SET TERM ^ ;

CREATE OR ALTER PROCEDURE ACCEPT_GIA_DTL (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$MAX_STAGE INTEGER;
DECLARE VARIABLE V$CUR_STAGE INTEGER;
DECLARE VARIABLE V$MAX_DATE DATE;
DECLARE VARIABLE S VARCHAR(1000);
begin

  -- Не числится ли ученик уже в классе для сдачи ГИА ?
  SELECT FIRST 1 LP125.PARENT_ID
  FROM LINKS LP125
  WHERE LP125.OBJ_ID = :I$OBJ_ID AND LP125.PARENT_TYPE_ID = 125 AND LP125.DATE_DEL IS NULL
  INTO :V$OBJ_ID;

  IF(V$OBJ_ID IS NOT NULL) THEN EXCEPTION DATA_ERROR 'Обучающийся уже включен в класс для сдачи ГИА: ' ||
    (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$OBJ_ID));

  -- В каком максимальном классе числился ученик ?
  SELECT MAX(LV.COST), MAX(COALESCE(M.DATE_OUT, M.DATE_IN))
  FROM PERSON_MOVEMENTS M
  JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID IN (9, 187)
  JOIN LISTVALS LV ON LV.LISTVAL_ID = M.STAGE_ID
  WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :I$OBJ_ID
  INTO :V$MAX_STAGE, :V$MAX_DATE;

  IF(V$MAX_STAGE IS NOT NULL) THEN
  BEGIN
    -- Если ученик выбыл более года назад, снимаем запрет - он мог уйти из школы, и вернуться только для сдачи
    IF(V$MAX_STAGE < 8 AND V$MAX_DATE > DATEADD(-9 MONTH TO CURRENT_DATE)) THEN
      EXCEPTION DATA_ERROR 'Обучающийся не закончил 8-й класс, его нельзя принять для сдачи ГИА';
  END

  -- Выдаем список групп, отмечаем особо группы куда включать нельзя
  TAG_NAME = 'grades::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
    SELECT L125.OBJ_ID, C.CAPTION, LV.COST
    FROM LINKS L2
    JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID IN (7, 502) AND L7.DATE_DEL IS NULL
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V49.LISTVAL_ID
    JOIN LINKS L125 ON L125.PARENT_ID = L8.OBJ_ID AND L125.OBJ_TYPE_ID = 125 AND L125.DATE_DEL IS NULL
    LEFT JOIN OBJECT_CAPTION_GET(L125.OBJ_ID) C ON 1 = 1
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    ORDER BY C.SORT_ORDER, C.CAPTION
    INTO :V$OBJ_ID, :S, :V$CUR_STAGE
  DO
  BEGIN
    TAG_NAME = 'grades:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'grades:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'grades:r:name';
    VAL = S;
    SUSPEND;
    -- Запрет для групп, куда входят обычные ученики со стороны
    TAG_NAME = 'grades:r:valid';
    VAL = '1';
    SELECT FIRST 1 '0'
    FROM LINKS L126
    WHERE L126.PARENT_ID = :V$OBJ_ID AND L126.OBJ_TYPE_ID = 126 AND L126.DATE_DEL IS NULL
    INTO :VAL;
    -- Блокируем прием 9-клашек в ГИА-11
    IF(V$MAX_STAGE < 10 AND V$CUR_STAGE = 11) THEN VAL = '0';
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE ACCEPT_GIA_PROCESS (
    I$OBJ_ID BIGINT,
    I$DEST_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    LINK_ID BIGINT)
AS
begin

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  -- Есть ли ученик
  IF(NOT EXISTS(
    SELECT FIRST 1 1
    FROM LINKS
    WHERE OBJ_ID = :I$OBJ_ID AND OBJ_TYPE_ID = 10 AND PARENT_TYPE_ID IN (81, 82, 83, 9, 187) AND DATE_DEL IS NULL
  ))
  THEN EXCEPTION DATA_ERROR 'Обучающийся не найден или был удален';

  -- Нет ли его уже в другом классе ГИА ?
  IF(EXISTS(
    SELECT FIRST 1 1
    FROM LINKS
    WHERE OBJ_ID = :I$OBJ_ID AND OBJ_TYPE_ID = 10 AND PARENT_TYPE_ID = 125 AND DATE_DEL IS NULL
  ))
  THEN EXCEPTION DATA_ERROR 'Обучающийся уже числится в другом классе для сдачи ГИА';

  -- Есть ли такой класс ?
  IF(NOT EXISTS(
    SELECT FIRST 1 1
    FROM LINKS
    WHERE OBJ_ID = :I$DEST_ID AND OBJ_TYPE_ID = 125 AND PARENT_TYPE_ID = 8 AND DATE_DEL IS NULL
  ))
  THEN EXCEPTION DATA_ERROR 'Выбранный класс для сдачи ГИА не найден или был удален';

  -- Нет ли в этом классе сторонних учеников ?
  IF(EXISTS(
    SELECT FIRST 1 1
    FROM LINKS
    WHERE PARENT_ID = :I$DEST_ID AND OBJ_TYPE_ID = 126 AND DATE_DEL IS NULL
  ))
  THEN EXCEPTION DATA_ERROR 'Штатных и выбывших обучающихся можно принимать только в класс ГИА, в котором нет сторонних учеников';

  SELECT LINK_ID
  FROM OBJECT_ADD_LINK(:I$DEST_ID, :I$OBJ_ID, 10, NULL, NULL, :I$USER_ID)
  INTO :LINK_ID;

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE ACCEPT_GRADE_LIST (
    I$FROM SMALLINT,
    I$GRADE BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    CAPTION VARCHAR(1000),
    OBJ_TYPE_ID BIGINT)
AS
DECLARE VARIABLE V$TYPE BIGINT;
DECLARE VARIABLE V$GRADE_ID BIGINT;
DECLARE VARIABLE V$GRADE_INDEX INTEGER;
DECLARE VARIABLE V$PREV_GRADE_ID BIGINT;
DECLARE VARIABLE V$ORDER INTEGER;
DECLARE VARIABLE V$GRADE_PARENT BIGINT;
DECLARE VARIABLE V$OU_LICENCE_TYPE CHAR(1);
DECLARE VARIABLE P INTEGER;
begin

  -- Актуальность будет утрачена после рефакторинга диалога зачисления

  SELECT TYPE_ID
  FROM OBJECTS
  WHERE OBJ_ID = :I$GRADE
  INTO :V$TYPE;

  V$OU_LICENCE_TYPE = (SELECT STATUS FROM OU_LICENCE_TYPE);

  IF(V$TYPE IN (9, 125, 187, 46)) THEN
  BEGIN
    OBJ_ID = I$GRADE;
    OBJ_TYPE_ID = V$TYPE;
    CAPTION = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$GRADE));
    SUSPEND;
  END
  ELSE IF(V$TYPE = 290) THEN
  BEGIN
    -- Все действующие и плановые классы этой параллели
    V$GRADE_ID = (SELECT LISTVAL_ID FROM VALL WHERE OBJ_ID = :I$GRADE AND PARAM_ID = 2346 AND IS_DEL = 0);

    SELECT FIRST 1 LV.COST, LV.PARENT_ID
    FROM LISTVALS LV
    WHERE LV.LISTVAL_ID = :V$GRADE_ID
    INTO :V$GRADE_INDEX, :V$GRADE_PARENT;

    SELECT FIRST 1 LV.LISTVAL_ID
    FROM LISTVALS LV
    WHERE LV.LIST_ID = 25 AND LV.IS_DEL = 0 AND (
      :V$GRADE_PARENT = LV.PARENT_ID OR
      (:V$GRADE_PARENT IN (2141, 12941) AND LV.PARENT_ID IN (2141, 12941))
    ) AND (
      LV.COST = :V$GRADE_INDEX - 1 OR
      (:V$GRADE_ID IN (30, 31, 32, 33, 3261) AND LV.LISTVAL_ID = 33) OR
      (:V$GRADE_ID IN (34, 35, 36, 3262) AND LV.LISTVAL_ID = 3262)
    )
    ORDER BY LV.SORT_ORDER
    INTO :V$PREV_GRADE_ID;

    FOR
      -- Действующие классы и экстернаты, специально уменьшаем номер чтобы были в начала списка
      SELECT L9.OBJ_ID, L9.OBJ_TYPE_ID, C.CAPTION, -1000 + LV.COST
      FROM LINKS L2
      JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
      JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
      JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0 AND V49.LISTVAL_ID = :V$GRADE_ID
      JOIN LISTVALS LV ON LV.LISTVAL_ID = V49.LISTVAL_ID
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 187) AND L9.DATE_DEL IS NULL
      LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C ON 1 = 1
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      -- Будущие новые классы
      UNION
      SELECT L403.OBJ_ID, L403.OBJ_TYPE_ID, C.CAPTION, LV.COST
      FROM LINKS L2
      JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
      JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
      JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0 AND V49.LISTVAL_ID = :V$GRADE_ID
      JOIN LISTVALS LV ON LV.LISTVAL_ID = V49.LISTVAL_ID
      JOIN LINKS L403 ON L403.PARENT_ID = L8.OBJ_ID AND L403.OBJ_TYPE_ID = 403 AND L403.DATE_DEL IS NULL
      LEFT JOIN OBJECT_CAPTION_GET(L403.OBJ_ID) C ON 1 = 1
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      -- Будущие классы после перевода года из числа действующих - специально корректируем id типа
      -- выпускные классы вычеркиваем
      UNION
      SELECT - L9.OBJ_ID, L9.OBJ_TYPE_ID, C.CAPTION, LV.COST + 1
      FROM LINKS L2
      JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
      JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
      JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0 AND V49.LISTVAL_ID = :V$PREV_GRADE_ID
      JOIN LISTVALS LV ON LV.LISTVAL_ID = V49.LISTVAL_ID
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
      LEFT JOIN VALL V1362 ON V1362.OBJ_ID = L9.OBJ_ID AND V1362.PARAM_ID = 1362 AND V1362.IS_DEL = 0
      LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C ON 1 = 1
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND (V1362.LISTVAL_ID IS NULL OR V1362.LISTVAL_ID = 3)
      ORDER BY 4, 3
      INTO :OBJ_ID, :OBJ_TYPE_ID, :CAPTION, :V$ORDER
    DO
    BEGIN
      -- Для школ исправляем название, заменяем код класса на следующий по порядку
      IF(V$OU_LICENCE_TYPE IN ('O', 'C') AND OBJ_TYPE_ID = 9 AND OBJ_ID < 0) THEN
      BEGIN
        P = POSITION(' ' IN CAPTION);
        IF(P <= 0) THEN CAPTION = V$ORDER;
        ELSE CAPTION = 'будущий ' || V$ORDER || ' ' || SUBSTRING(CAPTION FROM P + 1);
      END

      SUSPEND;
    END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE ACCESS_SELECTOR_GET RETURNS (
    MODULE_ID BIGINT,
    TASK_ID BIGINT)
AS
BEGIN
    SELECT FIRST 1 MODULE_ID
    FROM MODULES
    ORDER BY SORT_ORDER
    INTO :MODULE_ID;
    SELECT FIRST 1 TASK_ID
    FROM TASKS
    WHERE MODULE_ID = :MODULE_ID
    ORDER BY SORT_ORDER
    INTO :TASK_ID;
    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE ACCESS_SELECTOR_SET (
    MODULE_ID BIGINT,
    TASK_ID BIGINT)
AS
BEGIN
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE ACTIVEDIR_USERS_LIST RETURNS (
    USER_ID BIGINT,
    USER_NAME VARCHAR(100),
    FIRST_NAME VARCHAR(100),
    MIDDLE_NAME VARCHAR(100),
    LAST_NAME VARCHAR(100),
    IS_BLOCKED SMALLINT,
    MUST_CHANGE SMALLINT,
    EXP_DATE DATE)
AS
BEGIN
    FOR SELECT USER_ID, USER_NAME, FIRST_NAME, MIDDLE_NAME, LAST_NAME, IS_BLOCKED, MUST_CHANGE, EXP_DATE
        FROM USERS
        WHERE DATE_DEL IS NULL
        ORDER BY USER_ID
        INTO :USER_ID, :USER_NAME, :FIRST_NAME, :MIDDLE_NAME, :LAST_NAME, :IS_BLOCKED, :MUST_CHANGE, :EXP_DATE
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE ACTIVEDIR_USER_SET (
    USER_ID BIGINT,
    PWD VARCHAR(100),
    IS_BLOCKED SMALLINT = 0,
    MUST_CHANGE SMALLINT = 0,
    EXP_DATE DATE = null)
AS
BEGIN
    UPDATE USERS
    SET PWD = :PWD,
        IS_BLOCKED = :IS_BLOCKED,
        MUST_CHANGE = :MUST_CHANGE,
        EXP_DATE = :EXP_DATE
    WHERE USER_ID = :USER_ID;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE ADDITIONAL_EDU_GPD_LIST (
    I$OBJ_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    LISTVAL_ID BIGINT,
    PARENT_ID BIGINT,
    VAL VARCHAR(500),
    VAL_LONG VARCHAR(1000))
AS
declare variable V$LISTVAL_ID bigint;
declare variable RES_ID bigint;
declare variable LANG_CODE varchar(2);
declare variable V$PARENT_TYPE bigint;
BEGIN
  SELECT LANG_CODE
  FROM USERS
  WHERE USER_ID = :I$USER_ID
  INTO :LANG_CODE;

  -- PARENT_ID = NULL;

  SELECT FIRST 1 V1579.LISTVAL_ID
  FROM LINKS L86
  JOIN VALL V1579 ON V1579.OBJ_ID = L86.PARENT_ID AND V1579.PARAM_ID = 1579 AND V1579.IS_DEL = 0
  WHERE L86.OBJ_ID = :I$OBJ_ID AND L86.PARENT_TYPE_ID = 86
  INTO :V$LISTVAL_ID;

  -- Мультипараграф
  IF(V$LISTVAL_ID IS NULL) THEN
  BEGIN
    SELECT FIRST 1 LP.PARENT_TYPE_ID
    FROM LINKS LP
    WHERE LP.OBJ_ID = :I$OBJ_ID AND LP.DATE_DEL IS NULL
    INTO :V$PARENT_TYPE;

    IF(V$PARENT_TYPE = 500) THEN V$LISTVAL_ID = 3317; -- ГПД
    -- Надо разделять - если ДО внесено непосредственно или в подразделении
    -- в самой ОУ считаем как вне ДО, в подразделении как в ОДО, но пока оставляем так
    IF(V$PARENT_TYPE = 7) THEN V$LISTVAL_ID = 3315; -- Ступень образования = ДО
  END

  -- Пока оставляем гибридную схему - и для старого параграфа, и для мультипараграфа
  FOR
    SELECT LISTVAL_ID, RES_ID
    FROM LISTVALS
    WHERE LIST_ID = 132 AND IS_DEL = 0
      AND (((TAG LIKE '%GPD%') AND (:V$LISTVAL_ID = 3317)) OR (((TAG NOT LIKE '%GPD%') OR (TAG IS NULL)) AND (:V$LISTVAL_ID <> 3317)))
    INTO :LISTVAL_ID, :RES_ID
  DO
  BEGIN
    SELECT VAL, VAL_LONG
    FROM RES_GET(:RES_ID, :LANG_CODE)
    INTO :VAL, :VAL_LONG;
    SUSPEND;
  END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE ADD_EXTERNAT_GRADUATE (
    I$OBJ_ID BIGINT,
    I$GRADE_ID BIGINT)
AS
declare variable V$FOLDER_ID bigint;
declare variable V$OU_ID bigint;
declare variable V$OUT_FOLDER bigint;
declare variable Y integer;
begin

  -- Если ученик уже есть где-то в выпуске - сюда мы просто не попадем

  -- Год окончания - смотрим по выданному документу
  -- Если документа нет, удаляем безвозвратно
  SELECT FIRST 1 EXTRACT(YEAR FROM V566.VAL)
  FROM LINKS L11
  JOIN VALD V566 ON V566.OBJ_ID = L11.OBJ_ID AND V566.PARAM_ID = 566 AND V566.IS_DEL = 0
  JOIN VALS V569 ON V569.OBJ_ID = L11.OBJ_ID AND V569.PARAM_ID = 569 AND V569.IS_DEL = 0 -- если регистрация выданного документа в этой ОУ
  WHERE L11.PARENT_ID = :I$OBJ_ID AND L11.OBJ_TYPE_ID = 11 AND L11.DATE_DEL IS NULL
  ORDER BY V566.VAL DESC
  INTO :Y;
  IF(Y IS NULL) THEN EXIT;

  SELECT FIRST 1 L78.OBJ_ID
  FROM LINKS L2
  JOIN LINKS L78 ON L78.PARENT_ID = L2.OBJ_ID AND L78.OBJ_TYPE_ID = 78 AND L78.DATE_DEL IS NULL
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$FOLDER_ID;

  IF(V$FOLDER_ID IS NULL) THEN
  BEGIN
    SELECT FIRST 1 L2.OBJ_ID
    FROM LINKS L2
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :V$OU_ID;

    SELECT OBJ_ID FROM OBJECT_ADD(:V$OU_ID, 78) INTO :V$FOLDER_ID;
  END

  SELECT FIRST 1 L83.OBJ_ID
  FROM LINKS L83
  JOIN VALI V451 ON V451.OBJ_ID = L83.OBJ_ID AND V451.PARAM_ID = 451 AND V451.IS_DEL = 0 AND V451.VAL = :Y
  WHERE L83.PARENT_ID = :V$FOLDER_ID AND L83.OBJ_TYPE_ID = 83 AND L83.DATE_DEL IS NULL
  INTO :V$OUT_FOLDER;

  IF (V$OUT_FOLDER IS NULL) THEN
  BEGIN
    SELECT OBJ_ID FROM OBJECT_ADD(:V$FOLDER_ID, 83) INTO :V$OUT_FOLDER;
    SELECT 1 FROM VAL_ADD(451, :V$OUT_FOLDER, :Y, 1) INTO :Y;
  END

  INSERT INTO LINKS
  (PARENT_ID, OBJ_ID, DATE_INS)
  VALUES (:V$OUT_FOLDER, :I$OBJ_ID, CURRENT_TIMESTAMP);

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE ADR_ADD (
    I$PARAM_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$REGION VARCHAR(255),
    I$DISTRICT VARCHAR(255),
    I$TOWN VARCHAR(255),
    I$SETTLEMENT VARCHAR(255),
    I$STREET VARCHAR(255),
    I$HOUSE VARCHAR(10),
    I$LITER VARCHAR(10),
    I$CORP VARCHAR(10),
    I$FLAT VARCHAR(10),
    I$POST_INDEX VARCHAR(20),
    I$OCATD VARCHAR(11) = NULL,
    I$HOUSEGUID VARCHAR(36) = NULL,
    I$STREETGUID VARCHAR(36) = NULL,
    I$USER_ID BIGINT = NULL,
    I$IS_DEL SMALLINT = 0,
    I$RAW_TEXT VARCHAR(1000) = NULL)
RETURNS (
    BLOB_ID BIGINT,
    REFRESH_FLAG VARCHAR(100),
    VAL VARCHAR(4000))
AS
DECLARE VARIABLE VAL_TYPE VARCHAR(100);
DECLARE VARIABLE TAG VARCHAR(100);
DECLARE VARIABLE SCHOOL_ID BIGINT;
DECLARE VARIABLE OBJ_ID BIGINT;
DECLARE VARIABLE CNT INTEGER;
BEGIN
    BLOB_ID = NULL;
    REFRESH_FLAG = NULL;

    SELECT PT.VAL_TYPE, P.TAG
    FROM PARAMS P
    JOIN PARAMTYPES PT ON P.PARAM_TYPE = PT.PARAM_TYPE
    WHERE PARAM_ID = :I$PARAM_ID
    INTO :VAL_TYPE, :TAG;

    IF (VAL_TYPE = 'ADDRESS') THEN
    BEGIN
        UPDATE OR INSERT INTO VALA (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, REGION, DISTRICT, TOWN, SETTLEMENT, STREET, HOUSE, CORP, LITER, FLAT,
          POST_INDEX, OCATD, FIAS_UID, STREET_UID, RAW_TEXT)
        VALUES (:I$PARAM_ID, :I$OBJ_ID, :I$USER_ID, :I$IS_DEL, :I$REGION, :I$DISTRICT, :I$TOWN, :I$SETTLEMENT, :I$STREET, :I$HOUSE, :I$CORP, :I$LITER, :I$FLAT,
          :I$POST_INDEX, :I$OCATD, :I$HOUSEGUID, :I$STREETGUID, :I$RAW_TEXT);
        IF (I$PARAM_ID = 2357) THEN
        BEGIN
            REFRESH_FLAG = 'REFRESH_TAB';
        END
    END

    IF (TAG = 'BUILDING_ADDRESS') THEN
    BEGIN
        OBJ_ID = NULL;

        SELECT FIRST 1 L.OBJ_ID
        FROM LINKS L
        WHERE L.PARENT_ID IS NULL AND L.OBJ_TYPE_ID = 2 AND L.DATE_DEL IS NULL
        INTO :SCHOOL_ID;

        SELECT V.VAL
        FROM VALR V
        WHERE V.PARAM_ID = 1370 AND V.OBJ_ID = :SCHOOL_ID AND V.IS_DEL = 0
        INTO :OBJ_ID;

        IF (OBJ_ID = I$OBJ_ID) THEN
        BEGIN
            DELETE FROM VALA
            WHERE PARAM_ID = 1371 AND OBJ_ID = :SCHOOL_ID;

            INSERT INTO VALA (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, REGION, DISTRICT, TOWN, SETTLEMENT, STREET, HOUSE, LITER, CORP, FLAT, POST_INDEX, OCATD, FIAS_UID)
            SELECT 1371, :SCHOOL_ID, USER_ID, IS_DEL, REGION, DISTRICT, TOWN, SETTLEMENT, STREET, HOUSE, LITER, CORP, FLAT, POST_INDEX, OCATD, FIAS_UID
            FROM VALA V
            WHERE V.PARAM_ID = 420 AND V.OBJ_ID = :I$OBJ_ID AND V.IS_DEL = 0;
        END

    END

    -- При удалении адреса временной регистрации, удаляем документы о регистрации
    IF(I$PARAM_ID = 2357 AND I$IS_DEL = 1) THEN
    BEGIN
      EXECUTE PROCEDURE DELETE_STAY_DOCUMENTS(:I$OBJ_ID);
      REFRESH_FLAG = 'REFRESH_TAB';
    END

    IF(I$IS_DEL = 0) THEN
    BEGIN
      SELECT V.VAL
      FROM ADR_GET(:I$PARAM_ID, :I$OBJ_ID) V
      INTO :VAL;
    END

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE ADR_GET (
    I$PARAM_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$IS_DEL SMALLINT = 0,
    I$POST_INDEX_FL SMALLINT = 1)
RETURNS (
    REGION VARCHAR(255),
    DISTRICT VARCHAR(255),
    TOWN VARCHAR(255),
    SETTLEMENT VARCHAR(255),
    STREET VARCHAR(255),
    HOUSE VARCHAR(10),
    CORP VARCHAR(10),
    LITER VARCHAR(10),
    FLAT VARCHAR(10),
    POST_INDEX VARCHAR(20),
    VAL VARCHAR(2000),
    OCATD VARCHAR(11),
    HOUSEGUID VARCHAR(36),
    STREETGUID VARCHAR(36),
    RAW_TEXT VARCHAR(1000))
AS
BEGIN
    VAL = '';
    REGION = '';
    DISTRICT = '';
    TOWN = '';
    SETTLEMENT = '';
    STREET = '';
    HOUSE = '';
    CORP = '';
    LITER = '';
    FLAT = '';
    POST_INDEX = '';
    OCATD = '';
    FOR
        SELECT REGION, DISTRICT, TOWN, SETTLEMENT, STREET, HOUSE, CORP, LITER, FLAT, POST_INDEX, OCATD, FIAS_UID, STREET_UID, RAW_TEXT
        FROM VALA
        WHERE PARAM_ID = :I$PARAM_ID AND OBJ_ID = :I$OBJ_ID AND IS_DEL <= :I$IS_DEL
        INTO :REGION, :DISTRICT, :TOWN, :SETTLEMENT, :STREET, :HOUSE, :CORP, :LITER, :FLAT, :POST_INDEX, :OCATD, :HOUSEGUID, :STREETGUID, :RAW_TEXT
    DO
    BEGIN
        IF (POST_INDEX <> '' AND :I$POST_INDEX_FL = 1) THEN VAL = POST_INDEX;
        IF (REGION <> '') THEN
        BEGIN
            IF (VAL <> '') THEN VAL = VAL || ', ';
            VAL = VAL || REGION;
        END
        IF (DISTRICT <> '') THEN
        BEGIN
            IF (VAL <> '') THEN VAL = VAL || ', ';
            VAL = VAL || DISTRICT;
        END
        IF (TOWN <> '') THEN
        BEGIN
            IF (VAL <> '') THEN VAL = VAL || ', ';
            VAL = VAL || TOWN;
        END
        IF (SETTLEMENT <> '') THEN
        BEGIN
            IF (VAL <> '') THEN VAL = VAL || ', ';
            VAL = VAL || SETTLEMENT;
        END
        IF (STREET <> '') THEN
        BEGIN
            IF (VAL <> '') THEN VAL = VAL || ', ';
            VAL = VAL || STREET;
        END
        IF (HOUSE <> '') THEN
        BEGIN
            IF (VAL <> '') THEN VAL = VAL || ', д ';
            VAL = VAL || HOUSE;
        END
        IF (CORP <> '') THEN
        BEGIN
            IF (VAL <> '') THEN VAL = VAL || ', корп ';
            VAL = VAL || CORP;
        END
        IF (LITER <> '') THEN
        BEGIN
            IF (VAL <> '') THEN VAL = VAL || ', литер ';
            VAL = VAL || LITER;
        END
        IF (FLAT <> '') THEN
        BEGIN
            IF (VAL <> '') THEN VAL = VAL || ', кв ';
            VAL = VAL || FLAT;
        END
    END
    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE ANALISYS_REPORT_DISTRICT_1 (
    I$DISTRICT_ID BIGINT,
    I$STAGE_ID BIGINT,
    I$FINAL_TYPE_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    SCHOOL_ID BIGINT,
    SCHOOL_CAPTION VARCHAR(4000),
    SORT_ORDER DOUBLE PRECISION,
    SS INTEGER,
    SB DOUBLE PRECISION,
    SA DOUBLE PRECISION)
AS
declare variable Y smallint;
declare variable DT date;
declare variable YEAR_VAL varchar(100);
declare variable YEAR_ID bigint;
declare variable DISTRICT_ID bigint;
declare variable MARKVAL_ID bigint;
declare variable PUPIL_ID bigint;
declare variable STAGE_ID bigint;
declare variable SMM double precision;
declare variable CNT double precision;
declare variable SM double precision;
declare variable SC double precision;
declare variable TS integer;
declare variable TB double precision;
declare variable TA double precision;
BEGIN
    Y = EXTRACT(YEAR FROM CURRENT_DATE);
    DT = '1.09.' || Y;

    IF (CURRENT_DATE < DT) THEN
    BEGIN
        YEAR_VAL = (Y - 1) || '-' || Y;
    END
    ELSE
    BEGIN
        YEAR_VAL = Y || '-' ||(Y + 1);
    END

    SELECT FIRST 1
           LV.LISTVAL_ID
    FROM LISTVALS LV

    JOIN RES R
    ON R.RES_ID = LV.RES_ID
    AND R.LANG_CODE = 'RU'

    WHERE LV.LIST_ID = 29
    AND R.VAL LIKE :YEAR_VAL
    INTO :YEAR_ID;

    DISTRICT_ID = I$DISTRICT_ID;

    IF ((DISTRICT_ID = -1) OR (DISTRICT_ID IS NULL)) THEN
    BEGIN
        SELECT FIRST 1 L.OBJ_ID
        FROM LINKS L
        WHERE L.PARENT_ID IS NULL
        AND L.OBJ_TYPE_ID = 111
        AND L.DATE_DEL IS NULL
        INTO :DISTRICT_ID;
    END

    TS = 0;
    TB = 0;
    TA = 0;

    FOR SELECT L2.OBJ_ID
        FROM LINKS L2
        WHERE L2.PARENT_ID = :DISTRICT_ID
          AND L2.OBJ_TYPE_ID = 2
          AND L2.DATE_DEL IS NULL
        ORDER BY L2.OBJ_ID
        INTO :SCHOOL_ID
    DO
    BEGIN
        SS = 0;
        SB = 0;
        SM = 0;
        SC = 0;
        SA = 0;
        STAGE_ID = -1;

        IF (I$STAGE_ID > 0) THEN
        BEGIN
            SELECT FIRST 1 L7.OBJ_ID
            FROM LINKS L7
            INNER JOIN VALL VL ON VL.OBJ_ID = L7.OBJ_ID
            WHERE L7.PARENT_ID = :SCHOOL_ID
              AND L7.OBJ_TYPE_ID = 7
              AND L7.DATE_DEL IS NULL
              AND VL.PARAM_ID = 43
              AND VL.IS_DEL = 0
              AND VL.LISTVAL_ID = :I$STAGE_ID
            INTO :STAGE_ID;
        END

        FOR SELECT L10.OBJ_ID
            FROM LINKS L7
            INNER JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID
            INNER JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID
            INNER JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID
            WHERE L7.PARENT_ID = :SCHOOL_ID
              AND L7.OBJ_TYPE_ID = 7
              AND L7.DATE_DEL IS NULL
              AND ((:I$STAGE_ID = -1) OR (L7.OBJ_ID = :STAGE_ID))
              AND L8.OBJ_TYPE_ID = 8
              AND L8.DATE_DEL IS NULL
              AND L9.OBJ_TYPE_ID = 9
              AND L9.DATE_DEL IS NULL
              AND L10.OBJ_TYPE_ID = 10
              AND L10.DATE_DEL IS NULL
            INTO :PUPIL_ID
        DO
        BEGIN
            SMM = 0;
            CNT = 0;

            FOR SELECT MARKVAL_ID
                FROM VALM V
                WHERE V.PUPIL_ID = :PUPIL_ID
                  AND V.YEAR_ID = :YEAR_ID
                  AND V.MARKTYPE_ID = :I$FINAL_TYPE_ID
                  AND V.IS_DEL = 0
                INTO :MARKVAL_ID
            DO
            BEGIN
                IF (MARKVAL_ID = 3018) THEN
                BEGIN
                    SMM = SMM + 5;
                    CNT = CNT + 1;
                END
                IF (MARKVAL_ID = 3017) THEN
                BEGIN
                    SMM = SMM + 4;
                    CNT = CNT + 1;
                END
                IF (MARKVAL_ID = 3016) THEN
                BEGIN
                    SMM = SMM + 3;
                    CNT = CNT + 1;
                END
                IF (MARKVAL_ID = 3015) THEN
                BEGIN
                    SMM = SMM + 2;
                    CNT = CNT + 1;
                END
                IF (MARKVAL_ID = 3014) THEN
                BEGIN
                    SMM = SMM + 1;
                    CNT = CNT + 1;
                END
            END

            IF (CNT > 0) THEN
            BEGIN
                SS = SS + 1;
                SB = SB + SMM / CNT;
                SM = SM + SMM;
                SC = SC + CNT;
            END
        END

        IF (SS > 0) THEN
        BEGIN
            SELECT CAPTION, SORT_ORDER
            FROM OBJECT_CAPTION_GET(:SCHOOL_ID, NULL, NULL, :I$USER_ID)
            INTO :SCHOOL_CAPTION, :SORT_ORDER;

            SA = SM / SC;

            TS = TS + SS;
            TB = TB + SB;
            TA = TA + SA;

            SUSPEND;
        END
    END


    SELECT WORD
    FROM REPORT_WORDS
    WHERE ID = 18
    INTO :SCHOOL_CAPTION;

    SCHOOL_ID = -1;
    SORT_ORDER = 1E30;
    SS = TS;
    SB = TB;
    SA = TA;
    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE ANALISYS_REPORT_DISTRICT_2 (
    I$DISTRICT_ID BIGINT,
    I$STAGE_ID BIGINT,
    I$FINAL_TYPE_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    SCHOOL_ID BIGINT,
    SCHOOL_CAPTION VARCHAR(4000),
    SORT_ORDER DOUBLE PRECISION,
    SP INTEGER,
    SS INTEGER,
    S5 INTEGER,
    S4 INTEGER,
    S3 INTEGER,
    S2 INTEGER,
    SN INTEGER,
    S45 INTEGER,
    S345 INTEGER,
    S12345 INTEGER)
AS
declare variable Y smallint;
declare variable DT date;
declare variable YEAR_VAL varchar(100);
declare variable YEAR_ID bigint;
declare variable DISTRICT_ID bigint;
declare variable MARKVAL_ID bigint;
declare variable PUPIL_ID bigint;
declare variable STAGE_ID bigint;
declare variable M5 integer;
declare variable M4 integer;
declare variable M3 integer;
declare variable M2 integer;
declare variable M1 integer;
declare variable MN integer;
declare variable MS integer;
declare variable T5 integer;
declare variable T4 integer;
declare variable T3 integer;
declare variable T2 integer;
declare variable TN integer;
declare variable TS integer;
declare variable TP integer;
declare variable T45 integer;
declare variable T345 integer;
declare variable T12345 integer;
BEGIN
    Y = EXTRACT(YEAR FROM CURRENT_DATE);
    DT = '1.09.' || Y;

    IF (CURRENT_DATE < DT) THEN
    BEGIN
        YEAR_VAL = (Y - 1) || '-' || Y;
    END
    ELSE
    BEGIN
        YEAR_VAL = Y || '-' ||(Y + 1);
    END

    SELECT FIRST 1
           LV.LISTVAL_ID
    FROM LISTVALS LV

    JOIN RES R
    ON R.RES_ID = LV.RES_ID
    AND R.LANG_CODE = 'RU'

    WHERE LV.LIST_ID = 29
    AND R.VAL LIKE :YEAR_VAL
    INTO :YEAR_ID;

    DISTRICT_ID = I$DISTRICT_ID;

    IF ((DISTRICT_ID = -1) OR (DISTRICT_ID IS NULL)) THEN
    BEGIN
        SELECT FIRST 1 L.OBJ_ID
        FROM LINKS L
        WHERE L.PARENT_ID IS NULL
          AND L.OBJ_TYPE_ID = 111
          AND L.DATE_DEL IS NULL
        INTO :DISTRICT_ID;
    END

    T5 = 0;
    T4 = 0;
    T3 = 0;
    T2 = 0;
    TN = 0;
    TS = 0;
    TP = 0;
    T45 = 0;
    T345 = 0;
    T12345 = 0;

    FOR SELECT L2.OBJ_ID
        FROM LINKS L2
        WHERE L2.PARENT_ID = :DISTRICT_ID
          AND L2.OBJ_TYPE_ID = 2
          AND L2.DATE_DEL IS NULL
        ORDER BY L2.OBJ_ID
        INTO :SCHOOL_ID
    DO
    BEGIN
        S5 = 0;
        S4 = 0;
        S3 = 0;
        S2 = 0;
        SN = 0;
        SS = 0;
        SP = 0;
        S45 = 0;
        S345 = 0;
        S12345 = 0;
        STAGE_ID = -1;

        IF (I$STAGE_ID > 0) THEN
        BEGIN
            SELECT FIRST 1 L7.OBJ_ID
            FROM LINKS L7
            INNER JOIN VALL VL ON VL.OBJ_ID = L7.OBJ_ID
            WHERE L7.PARENT_ID = :SCHOOL_ID
              AND L7.OBJ_TYPE_ID = 7
              AND L7.DATE_DEL IS NULL
              AND VL.PARAM_ID = 43
              AND VL.IS_DEL = 0
              AND VL.LISTVAL_ID = :I$STAGE_ID
            INTO :STAGE_ID;
        END

        FOR SELECT L10.OBJ_ID
            FROM LINKS L7
            INNER JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID
            INNER JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID
            INNER JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID
            WHERE L7.PARENT_ID = :SCHOOL_ID
              AND L7.OBJ_TYPE_ID = 7
              AND L7.DATE_DEL IS NULL
              AND ((:I$STAGE_ID = -1) OR (L7.OBJ_ID = :STAGE_ID))
              AND L8.OBJ_TYPE_ID = 8
              AND L8.DATE_DEL IS NULL
              AND L9.OBJ_TYPE_ID = 9
              AND L9.DATE_DEL IS NULL
              AND L10.OBJ_TYPE_ID = 10
              AND L10.DATE_DEL IS NULL
            INTO :PUPIL_ID
        DO
        BEGIN
            M5 = 0;
            M4 = 0;
            M3 = 0;
            M2 = 0;
            M1 = 0;
            MN = 0;
            MS = 0;
            SP = SP + 1;

            FOR SELECT MARKVAL_ID
                FROM VALM V
                WHERE V.PUPIL_ID = :PUPIL_ID
                  AND V.YEAR_ID = :YEAR_ID
                  AND V.MARKTYPE_ID = :I$FINAL_TYPE_ID
                  AND V.IS_DEL = 0
                INTO :MARKVAL_ID
            DO
            BEGIN
                IF (MARKVAL_ID = 3018) THEN
                BEGIN
                    M5 = M5 + 1;
                    MS = MS + 1;
                    S45 = S45 + 1;
                    S345 = S345 + 1;
                    S12345 = S12345 + 1;
                END
                IF (MARKVAL_ID = 3017) THEN
                BEGIN
                    M4 = M4 + 1;
                    MS = MS + 1;
                    S45 = S45 + 1;
                    S345 = S345 + 1;
                    S12345 = S12345 + 1;
                END
                IF (MARKVAL_ID = 3016) THEN
                BEGIN
                    M3 = M3 + 1;
                    MS = MS + 1;
                    S345 = S345 + 1;
                    S12345 = S12345 + 1;
                END
                IF (MARKVAL_ID = 3015) THEN
                BEGIN
                    M2 = M2 + 1;
                    MS = MS + 1;
                    S12345 = S12345 + 1;
                END
                IF (MARKVAL_ID = 3014) THEN
                BEGIN
                    M1 = M1 + 1;
                    MS = MS + 1;
                    S12345 = S12345 + 1;
                END
                IF ((MARKVAL_ID = 3021) OR (MARKVAL_ID = 3022) OR (MARKVAL_ID = 3023)) THEN
                BEGIN
                    MN = 1;
                END
            END

            IF (MS > 0) THEN
            BEGIN
                IF ((M5 > 0) AND (M4 = 0) AND (M3 = 0) AND (M2 = 0) AND (M1 = 0)) THEN
                    S5 = S5 + 1;
                IF ((M4 > 0) AND (M3 = 0) AND (M2 = 0) AND (M1 = 0)) THEN
                    S4 = S4 + 1;
                IF ((M3 > 0) AND (M2 = 0) AND (M1 = 0)) THEN
                    S3 = S3 + 1;
                IF ((M2 > 0) OR (M1 > 0)) THEN
                    S2 = S2 + 1;
                SS = SS + 1;
            END
            IF (MN > 0) THEN
                SN = SN + 1;
        END

        IF (SS > 0) THEN
        BEGIN
            SELECT CAPTION, SORT_ORDER
            FROM OBJECT_CAPTION_GET(:SCHOOL_ID, NULL, NULL, :I$USER_ID)
            INTO :SCHOOL_CAPTION, :SORT_ORDER;

            TP = TP + SP;
            TS = TS + SS;
            T5 = T5 + S5;
            T4 = T4 + S4;
            T3 = T3 + S3;
            T2 = T2 + S2;
            TN = TN + SN;
            T45 = T45 + S45;
            T345 = T345 + S345;
            T12345 = T12345 + S12345;

            SUSPEND;
        END
    END


    SELECT WORD
    FROM REPORT_WORDS
    WHERE ID = 18
    INTO :SCHOOL_CAPTION;

    SCHOOL_ID = -1;
    SORT_ORDER = 20000000000000;
    SP = TP;
    SS = TS;
    S5 = T5;
    S4 = T4;
    S3 = T3;
    S2 = T2;
    SN = TN;
    S45 = T45;
    S345 = T345;
    S12345 = T12345;
    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE ANALISYS_REPORT_DISTRICT_3 (
    I$DISTRICT_ID BIGINT,
    I$STAGE_ID BIGINT,
    I$SUBJECT_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    SCHOOL_ID BIGINT,
    SCHOOL_CAPTION VARCHAR(4000),
    SORT_ORDER DOUBLE PRECISION,
    FINAL_TYPE_ID BIGINT,
    SB DOUBLE PRECISION)
AS
declare variable Y smallint;
declare variable DT date;
declare variable YEAR_VAL varchar(100);
declare variable YEAR_ID bigint;
declare variable DISTRICT_ID bigint;
declare variable MARKVAL_ID bigint;
declare variable STAGE_ID bigint;
declare variable SMM double precision;
declare variable CNT double precision;
BEGIN
    Y = EXTRACT(YEAR FROM CURRENT_DATE);
    DT = '1.09.' || Y;

    IF (CURRENT_DATE < DT) THEN
    BEGIN
        YEAR_VAL = (Y - 1) || '-' || Y;
    END
    ELSE
    BEGIN
        YEAR_VAL = Y || '-' ||(Y + 1);
    END

    SELECT FIRST 1
           LV.LISTVAL_ID
    FROM LISTVALS LV

    JOIN RES R
    ON R.RES_ID = LV.RES_ID
    AND R.LANG_CODE = 'RU'

    WHERE LV.LIST_ID = 29
    AND R.VAL LIKE :YEAR_VAL
    INTO :YEAR_ID;

    DISTRICT_ID = I$DISTRICT_ID;

    IF ((DISTRICT_ID = -1) OR (DISTRICT_ID IS NULL)) THEN
    BEGIN
        SELECT FIRST 1 L.OBJ_ID
        FROM LINKS L
        WHERE L.PARENT_ID IS NULL
          AND L.OBJ_TYPE_ID = 111
          AND L.DATE_DEL IS NULL
        INTO :DISTRICT_ID;
    END

    FOR SELECT L2.OBJ_ID
        FROM LINKS L2
        WHERE L2.PARENT_ID = :DISTRICT_ID
          AND L2.OBJ_TYPE_ID = 2
          AND L2.DATE_DEL IS NULL
        ORDER BY L2.OBJ_ID
        INTO :SCHOOL_ID
    DO
    BEGIN
        SELECT CAPTION, SORT_ORDER
        FROM OBJECT_CAPTION_GET(:SCHOOL_ID, NULL, NULL, :I$USER_ID)
        INTO :SCHOOL_CAPTION, :SORT_ORDER;

        STAGE_ID = -1;

        IF (I$STAGE_ID > 0) THEN
        BEGIN
            SELECT FIRST 1 L7.OBJ_ID
            FROM LINKS L7
            INNER JOIN VALL VL ON VL.OBJ_ID = L7.OBJ_ID
            WHERE L7.PARENT_ID = :SCHOOL_ID
              AND L7.OBJ_TYPE_ID = 7
              AND L7.DATE_DEL IS NULL
              AND VL.PARAM_ID = 43
              AND VL.IS_DEL = 0
              AND VL.LISTVAL_ID = :I$STAGE_ID
            INTO :STAGE_ID;
        END

        FOR SELECT LV.LISTVAL_ID
            FROM LISTVALS LV
            WHERE LV.LIST_ID = 220
              AND LV.LISTVAL_ID <> 3001
              AND LV.IS_DEL = 0
            ORDER BY LV.SORT_ORDER
            INTO :FINAL_TYPE_ID
        DO
        BEGIN
            SB = 0;
            SMM = 0;
            CNT = 0;

            FOR SELECT V.MARKVAL_ID
                FROM LINKS L7
                INNER JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID
                INNER JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID
                INNER JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID
                INNER JOIN VALM V ON V.PUPIL_ID = L10.OBJ_ID
                WHERE L7.PARENT_ID = :SCHOOL_ID
                  AND L7.OBJ_TYPE_ID = 7
                  AND L7.DATE_DEL IS NULL
                  AND ((:I$STAGE_ID = -1) OR (L7.OBJ_ID = :STAGE_ID))
                  AND L8.OBJ_TYPE_ID = 8
                  AND L8.DATE_DEL IS NULL
                  AND L9.OBJ_TYPE_ID = 9
                  AND L9.DATE_DEL IS NULL
                  AND L10.OBJ_TYPE_ID = 10
                  AND L10.DATE_DEL IS NULL
                  AND ((:I$SUBJECT_ID = -1) OR (V.SUBJECT_ID = :I$SUBJECT_ID))
                  AND V.YEAR_ID = :YEAR_ID
                  AND V.MARKTYPE_ID = :FINAL_TYPE_ID
                  AND V.IS_DEL = 0
                INTO :MARKVAL_ID
            DO
            BEGIN
                IF (MARKVAL_ID = 3018) THEN
                BEGIN
                    SMM = SMM + 5;
                    CNT = CNT + 1;
                END
                IF (MARKVAL_ID = 3017) THEN
                BEGIN
                    SMM = SMM + 4;
                    CNT = CNT + 1;
                END
                IF (MARKVAL_ID = 3016) THEN
                BEGIN
                    SMM = SMM + 3;
                    CNT = CNT + 1;
                END
                IF (MARKVAL_ID = 3015) THEN
                BEGIN
                    SMM = SMM + 2;
                    CNT = CNT + 1;
                END
                IF (MARKVAL_ID = 3014) THEN
                BEGIN
                    SMM = SMM + 1;
                    CNT = CNT + 1;
                END
            END

            IF (CNT > 0) THEN
            BEGIN
                SB = SMM / CNT;
                SUSPEND;
            END
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE ANALISYS_REPORT_DISTRICT_4 (
    I$DISTRICT_ID BIGINT,
    I$MARKTYPE_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    SCHOOL_CAPTION VARCHAR(4000),
    P1_1 SMALLINT,
    P1_2 SMALLINT,
    P1_3 SMALLINT,
    P2_1 SMALLINT,
    P2_2 SMALLINT,
    P2_3 SMALLINT,
    P3_1 SMALLINT,
    P3_2 SMALLINT,
    P3_3 SMALLINT,
    P4_1 SMALLINT,
    P4_2 SMALLINT,
    P4_3 SMALLINT,
    P5_1 SMALLINT,
    P5_2 SMALLINT,
    P5_3 SMALLINT,
    P6_1 SMALLINT,
    P6_2 SMALLINT,
    P6_3 SMALLINT,
    P7_1 SMALLINT,
    P7_2 SMALLINT,
    P7_3 SMALLINT,
    P8_1 SMALLINT,
    P8_2 SMALLINT,
    P8_3 SMALLINT,
    P9_1 SMALLINT,
    P9_2 SMALLINT,
    P9_3 SMALLINT,
    P10_1 SMALLINT,
    P10_2 SMALLINT,
    P10_3 SMALLINT,
    P11_1 SMALLINT,
    P11_2 SMALLINT,
    P11_3 SMALLINT,
    P12_1 SMALLINT,
    P12_2 SMALLINT,
    P12_3 SMALLINT,
    PT_1 SMALLINT,
    PT_2 SMALLINT,
    PT_3 SMALLINT,
    SORT_ORDER DOUBLE PRECISION)
AS
declare variable Y smallint;
declare variable DT date;
declare variable YEAR_VAL varchar(100);
declare variable V$YEAR_ID bigint;
declare variable V$PUPIL_ID bigint;
declare variable V$STAGE_ID bigint;
declare variable V$SCHOOL_ID bigint;
declare variable V$CURRICULUM_ID bigint;
declare variable V$CURRICULUM_STAGE_ID bigint;
declare variable V$MARK_TOTAL smallint;
declare variable V$MARK_COUNT smallint;
declare variable V$P1 smallint;
declare variable V$P2 smallint;
declare variable V$P3 smallint;
BEGIN
    Y = EXTRACT(YEAR FROM CURRENT_DATE);
    DT = '1.09.' || Y;

    IF (CURRENT_DATE < DT) THEN
    BEGIN
        YEAR_VAL = (Y - 1) || '-' || Y;
    END
    ELSE
    BEGIN
        YEAR_VAL = Y || '-' ||(Y + 1);
    END

    SELECT FIRST 1
           LV.LISTVAL_ID
    FROM LISTVALS LV

    JOIN RES R
    ON R.RES_ID = LV.RES_ID
    AND R.LANG_CODE = 'RU'

    WHERE LV.LIST_ID = 29
    AND R.VAL LIKE :YEAR_VAL
    INTO :V$YEAR_ID;

    IF ((I$DISTRICT_ID = -1) OR (I$DISTRICT_ID IS NULL)) THEN
    BEGIN
        SELECT FIRST 1
               L.OBJ_ID

        FROM LINKS L

        WHERE L.PARENT_ID IS NULL
        AND L.OBJ_TYPE_ID = 111
        AND L.DATE_DEL IS NULL

        INTO :I$DISTRICT_ID;
    END

    FOR
        SELECT L2.OBJ_ID
        FROM LINKS L2

--        WHERE L2.OBJ_ID = 708000000001 -- для отладки
        WHERE L2.PARENT_ID = :I$DISTRICT_ID
        AND L2.OBJ_TYPE_ID = 2
        AND L2.DATE_DEL IS NULL

        ORDER BY L2.OBJ_ID

        INTO :V$SCHOOL_ID
    DO
    BEGIN
        SELECT CAPTION, SORT_ORDER
        FROM OBJECT_CAPTION_GET(:V$SCHOOL_ID, NULL, NULL, :I$USER_ID)
        INTO :SCHOOL_CAPTION, :SORT_ORDER;

        P1_1 = 0;
        P1_2 = 0;
        P1_3 = 0;
        P2_1 = 0;
        P2_2 = 0;
        P2_3 = 0;
        P3_1 = 0;
        P3_2 = 0;
        P3_3 = 0;
        P4_1 = 0;
        P4_2 = 0;
        P4_3 = 0;
        P5_1 = 0;
        P5_2 = 0;
        P5_3 = 0;
        P6_1 = 0;
        P6_2 = 0;
        P6_3 = 0;
        P7_1 = 0;
        P7_2 = 0;
        P7_3 = 0;
        P8_1 = 0;
        P8_2 = 0;
        P8_3 = 0;
        P9_1 = 0;
        P9_2 = 0;
        P9_3 = 0;
        P10_1 = 0;
        P10_2 = 0;
        P10_3 = 0;
        P11_1 = 0;
        P11_2 = 0;
        P11_3 = 0;
        P12_1 = 0;
        P12_2 = 0;
        P12_3 = 0;
        FOR
            SELECT DISTINCT
                   V381.LISTVAL_ID, --этап УП
                   L50.OBJ_ID,
                   L54.OBJ_ID

            FROM LINKS L69 -- Образовательные программы

            JOIN VALL V2450
            ON V2450.OBJ_ID = L69.OBJ_ID
            AND V2450.PARAM_ID = 2450
            AND V2450.IS_DEL = 0
            AND V2450.LISTVAL_ID = 11385

            JOIN LINKS L57 -- Образовательная программа
            ON L57.PARENT_ID = L69.OBJ_ID
            AND L57.OBJ_TYPE_ID = 57
            AND L57.DATE_DEL IS NULL

            JOIN LINKS L50 --  Учебный план
            ON L50.PARENT_ID = L57.OBJ_ID
            AND L50.OBJ_TYPE_ID = 50
            AND L50.DATE_DEL IS NULL

            JOIN LINKS L54 -- Этап учебного плана
            ON L54.PARENT_ID = L50.OBJ_ID
            AND L54.OBJ_TYPE_ID = 54
            AND L54.DATE_DEL IS NULL

            JOIN VALL V381
            ON V381.OBJ_ID = L54.OBJ_ID
            AND V381.PARAM_ID = 381
            AND V381.IS_DEL = 0

            WHERE L69.PARENT_ID = :V$SCHOOL_ID
            AND L69.OBJ_TYPE_ID = 69
            AND L69.DATE_DEL IS NULL

            INTO :V$STAGE_ID,
                 :V$CURRICULUM_ID,
                 :V$CURRICULUM_STAGE_ID
        DO
        BEGIN
            V$MARK_TOTAL = 0;

            -- должно быть оценок у ученика (количество предметов)
            SELECT COUNT(DISTINCT L51.OBJ_ID)

            FROM LINKS L49 -- Учебный компонент

            JOIN LINKS L51 -- Предмет
            ON L51.PARENT_ID = L49.OBJ_ID
            AND L51.OBJ_TYPE_ID = 51
            AND L51.DATE_DEL IS NULL

            JOIN LINKS L56 -- Нагрузка учебного плана
            ON L56.PARENT_ID = L49.OBJ_ID
            AND L56.OBJ_TYPE_ID = 56
            AND L56.DATE_DEL IS NULL

            JOIN VALI V385
            ON V385.OBJ_ID = L56.OBJ_ID
            AND V385.PARAM_ID = 385
            AND V385.IS_DEL = 0
            AND V385.VAL > 0

            JOIN LINKS L51_56 -- Нагрузка учебного плана по предмету
            ON L51_56.PARENT_ID = L51.OBJ_ID
            AND L51_56.OBJ_ID = L56.OBJ_ID
            AND L51_56.DATE_DEL IS NULL

            JOIN LINKS L54_56 -- Нагрузка учебного плана на этапе обучения
            ON L54_56.PARENT_ID = :V$CURRICULUM_STAGE_ID
            AND L54_56.OBJ_ID = L56.OBJ_ID
            AND L54_56.DATE_DEL IS NULL

            WHERE L49.PARENT_ID = :V$CURRICULUM_ID
            AND L49.OBJ_TYPE_ID = 49
            AND L49.DATE_DEL IS NULL

            INTO :V$MARK_TOTAL;

            FOR
                SELECT DISTINCT
                       L10.OBJ_ID

                FROM LINKS L256 -- Группа учебного плана

                JOIN LINKS L10 -- Обучающийся, воспитанник
                ON L10.PARENT_ID = L256.OBJ_ID
                AND L10.OBJ_TYPE_ID = 10
                AND L10.DATE_DEL IS NULL
    
                WHERE L256.PARENT_ID = :V$CURRICULUM_STAGE_ID
                AND L256.OBJ_TYPE_ID = 256
                AND L256.DATE_DEL IS NULL

                INTO
                     :V$PUPIL_ID
            DO
            BEGIN
                V$MARK_COUNT = 0;
                V$P1 = 1;  -- Ученик
                V$P2 = 0;
                V$P3 = 0;

                -- есть оценок у ученика
                SELECT COUNT(*)
                FROM VALM V
                WHERE V.PUPIL_ID = :V$PUPIL_ID
                AND V.YEAR_ID = :V$YEAR_ID
                AND V.MARKTYPE_ID = :I$MARKTYPE_ID
                INTO :V$MARK_COUNT;

                IF (V$MARK_TOTAL > 0) THEN
                BEGIN
                    --Все оценки
                    IF (V$MARK_TOTAL = V$MARK_COUNT) THEN
                    BEGIN
                        V$P2 = 1;
                    END
                    --Нет оценок
                    ELSE IF (V$MARK_COUNT = 0) THEN
                    BEGIN
                        V$P3 = 1;
                    END
                END
    
                -- Раскидываем по параллелям
                IF(V$STAGE_ID = 37) THEN
                BEGIN
                    P1_1 = P1_1 + V$P1;
                    P1_2 = P1_2 + V$P2;
                    P1_3 = P1_3 + V$P3;
                END
                ELSE IF(V$STAGE_ID = 38) THEN
                BEGIN
                    P2_1 = P2_1 + V$P1;
                    P2_2 = P2_2 + V$P2;
                    P2_3 = P2_3 + V$P3;
                END
                ELSE IF(V$STAGE_ID = 39) THEN
                BEGIN
                    P3_1 = P3_1 + V$P1;
                    P3_2 = P3_2 + V$P2;
                    P3_3 = P3_3 + V$P3;
                END
                ELSE IF(V$STAGE_ID = 40) THEN
                BEGIN
                    P4_1 = P4_1 + V$P1;
                    P4_2 = P4_2 + V$P2;
                    P4_3 = P4_3 + V$P3;
                END
                ELSE IF(V$STAGE_ID = 41) THEN
                BEGIN
                    P5_1 = P5_1 + V$P1;
                    P5_2 = P5_2 + V$P2;
                    P5_3 = P5_3 + V$P3;
                END
                ELSE IF(V$STAGE_ID = 42) THEN
                BEGIN
                    P6_1 = P6_1 + V$P1;
                    P6_2 = P6_2 + V$P2;
                    P6_3 = P6_3 + V$P3;
                END
                ELSE IF(V$STAGE_ID = 43) THEN
                BEGIN
                    P7_1 = P7_1 + V$P1;
                    P7_2 = P7_2 + V$P2;
                    P7_3 = P7_3 + V$P3;
                END
                ELSE IF(V$STAGE_ID = 44) THEN
                BEGIN
                    P8_1 = P8_1 + V$P1;
                    P8_2 = P8_2 + V$P2;
                    P8_3 = P8_3 + V$P3;
                END
                ELSE IF(V$STAGE_ID = 45) THEN
                BEGIN
                    P9_1 = P9_1 + V$P1;
                    P9_2 = P9_2 + V$P2;
                    P9_3 = P9_3 + V$P3;
                END
                ELSE IF(V$STAGE_ID = 46) THEN
                BEGIN
                    P10_1 = P10_1 + V$P1;
                    P10_2 = P10_2 + V$P2;
                    P10_3 = P10_3 + V$P3;
                END
                ELSE IF(V$STAGE_ID = 47) THEN
                BEGIN
                    P11_1 = P11_1 + V$P1;
                    P11_2 = P11_2 + V$P2;
                    P11_3 = P11_3 + V$P3;
                END
                ELSE IF(V$STAGE_ID = 48) THEN
                BEGIN
                    P12_1 = P12_1 + V$P1;
                    P12_2 = P12_2 + V$P2;
                    P12_3 = P12_3 + V$P3;
                END
            END
        END
        PT_1 = P1_1 + P2_1 + P3_1 + P4_1 + P5_1 + P6_1 + P7_1 + P8_1 + P9_1 + P10_1 + P11_1 + P12_1;
        PT_2 = P1_2 + P2_2 + P3_2 + P4_2 + P5_2 + P6_2 + P7_2 + P8_2 + P9_2 + P10_2 + P11_2 + P12_2;
        PT_3 = P1_3 + P2_3 + P3_3 + P4_3 + P5_3 + P6_3 + P7_3 + P8_3 + P9_3 + P10_3 + P11_3 + P12_3;
        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE ANALISYS_REPORT_SCHOOL (
    I$SCHOOL_ID BIGINT,
    I$CLASS_ID BIGINT,
    I$FINAL_TYPE_ID BIGINT,
    I$SUBJECT_ID BIGINT = -1,
    I$TEACHER_ID BIGINT = -1,
    I$REPORT SMALLINT = -1,
    I$USER_ID BIGINT = 1,
    I$SHOW_LEFT INTEGER = 0)
RETURNS (
    FINALMARK_ID BIGINT,
    FINAL_TYPE_ID BIGINT,
    STAGE_ID BIGINT,
    GRADE_ID BIGINT,
    CLASS_ID BIGINT,
    PUPIL_ID BIGINT,
    SUBJECT_ID BIGINT,
    TEACHER_ID BIGINT,
    MARK_TYPE_ID BIGINT,
    MARK_SHORTNAME VARCHAR(10),
    CLASS_CAPTION VARCHAR(400),
    PUPIL_CAPTION VARCHAR(200),
    SUBJECT_CAPTION VARCHAR(400),
    TEACHER_CAPTION VARCHAR(200),
    SORT_ORDER DOUBLE PRECISION)
AS
declare variable Y integer;
declare variable YEAR_VAL varchar(100);
declare variable YEAR_ID bigint;
declare variable SCHOOL_ID bigint;
declare variable LANG_CODE varchar(2);
declare variable GRADUATE_FOLDER bigint;
declare variable LEAVED_FOLDER bigint;
declare variable PARENT_ID bigint;
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :LANG_CODE;

    IF(EXTRACT(MONTH FROM CURRENT_DATE) < 9) THEN Y = EXTRACT(YEAR FROM CURRENT_DATE) - 1; ELSE Y = EXTRACT(YEAR FROM CURRENT_DATE);
    YEAR_VAL = Y || '-' ||(Y + 1);

    SELECT FIRST 1 LV.LISTVAL_ID
    FROM LISTVALS LV
    JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
    WHERE LV.LIST_ID = 29 AND R.VAL LIKE :YEAR_VAL
    INTO :YEAR_ID;

    SCHOOL_ID = I$SCHOOL_ID;

    IF ((SCHOOL_ID = -1) OR (SCHOOL_ID IS NULL)) THEN
    BEGIN
        SELECT FIRST 1 L.OBJ_ID
        FROM LINKS L
        WHERE L.PARENT_ID IS NULL AND L.OBJ_TYPE_ID = 2 AND L.DATE_DEL IS NULL
        INTO :SCHOOL_ID;
    END

    -- Выбираем папки выбывших и выпуска текущего учебного года (выпуск идет следующим годом)
    SELECT FIRST 1 L82.OBJ_ID
    FROM LINKS L78
    JOIN LINKS L82 ON L82.PARENT_ID = L78.OBJ_ID AND L82.OBJ_TYPE_ID = 82 AND L82.DATE_DEL IS NULL
    JOIN VALI V448 ON V448.OBJ_ID = L82.OBJ_ID AND V448.PARAM_ID = 448 AND V448.IS_DEL = 0 AND V448.VAL = :Y
    WHERE L78.PARENT_ID = :SCHOOL_ID AND L78.OBJ_TYPE_ID = 78 AND L78.DATE_DEL IS NULL
    INTO :LEAVED_FOLDER;

    SELECT FIRST 1 L83.OBJ_ID
    FROM LINKS L78
    JOIN LINKS L83 ON L83.PARENT_ID = L78.OBJ_ID AND L83.OBJ_TYPE_ID = 83 AND L83.DATE_DEL IS NULL
    JOIN VALI V451 ON V451.OBJ_ID = L83.OBJ_ID AND V451.PARAM_ID = 451 AND V451.IS_DEL = 0 AND V451.VAL = (:Y + 1)
    WHERE L78.PARENT_ID = :SCHOOL_ID AND L78.OBJ_TYPE_ID = 78 AND L78.DATE_DEL IS NULL
    INTO :GRADUATE_FOLDER;

    -- Основной цикл по классам
    FOR
        SELECT L7.OBJ_ID, L8.OBJ_ID, L9.OBJ_ID
        FROM LINKS L7
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 187) AND L9.DATE_DEL IS NULL AND ((:I$CLASS_ID = -1) OR (L9.OBJ_ID = :I$CLASS_ID))
        WHERE L7.PARENT_ID = :SCHOOL_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
        INTO :GRADE_ID, :STAGE_ID, :CLASS_ID
    DO
    BEGIN

        IF (I$REPORT IN (5, 6, 7, 8)) THEN
        BEGIN
            SELECT CAPTION, SORT_ORDER FROM OBJECT_CAPTION_GET(:CLASS_ID, NULL, NULL, :I$USER_ID) INTO :CLASS_CAPTION, :SORT_ORDER;
        END

        -- Вложенный цикл по учащимся
        FOR
            -- Действующие учащиеся
            SELECT L10.PARENT_ID, L10.OBJ_ID, V.MARK_ID, V.SUBJECT_ID, V.TEACHER_ID, V.MARKTYPE_ID, V.MARKVAL_ID, R.VAL
            FROM LINKS L10
            JOIN VALM V ON V.PUPIL_ID = L10.OBJ_ID AND ((:I$SUBJECT_ID = -1) OR (V.SUBJECT_ID = :I$SUBJECT_ID)) AND ((:I$TEACHER_ID = -1) OR (V.TEACHER_ID = :I$TEACHER_ID))
                AND ((:I$FINAL_TYPE_ID = -1) OR (V.MARKTYPE_ID = :I$FINAL_TYPE_ID)) AND V.YEAR_ID = :YEAR_ID AND V.IS_DEL = 0
            JOIN LISTVALS LV ON LV.LISTVAL_ID = V.MARKVAL_ID
            LEFT JOIN RES_GET(LV.RES_ID, :LANG_CODE) R ON 1=1
            WHERE L10.PARENT_ID = :CLASS_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
            -- Выбывшие учащиеся, которые были в этом классе - только если указано их выбирать
            UNION
            SELECT L10.PARENT_ID, L10.OBJ_ID, V.MARK_ID, V.SUBJECT_ID, V.TEACHER_ID, V.MARKTYPE_ID, V.MARKVAL_ID, R.VAL
            FROM LINKS L10
            JOIN VALM V ON V.PUPIL_ID = L10.OBJ_ID AND ((:I$SUBJECT_ID = -1) OR (V.SUBJECT_ID = :I$SUBJECT_ID)) AND ((:I$TEACHER_ID = -1) OR (V.TEACHER_ID = :I$TEACHER_ID))
                AND ((:I$FINAL_TYPE_ID = -1) OR (V.MARKTYPE_ID = :I$FINAL_TYPE_ID)) AND V.YEAR_ID = :YEAR_ID AND V.IS_DEL = 0
            JOIN LISTVALS LV ON LV.LISTVAL_ID = V.MARKVAL_ID
            LEFT JOIN RES_GET(LV.RES_ID, :LANG_CODE) R ON 1 = 1
            WHERE (L10.PARENT_ID = :LEAVED_FOLDER OR L10.PARENT_ID = :GRADUATE_FOLDER) AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL AND :I$SHOW_LEFT = 1
            INTO :PARENT_ID, :PUPIL_ID, :FINALMARK_ID, :SUBJECT_ID, :TEACHER_ID, :FINAL_TYPE_ID, :MARK_TYPE_ID, :MARK_SHORTNAME
        DO
        BEGIN

            -- Для выбывших проверяем последний класс, где они были до выбытия
            IF(PARENT_ID <> CLASS_ID) THEN
            BEGIN

                PARENT_ID = NULL;

                -- Берем последнюю запись приема или перевода
                -- LISTVAL_ID IN (805, 806, 807, 808, 809, 810, 3276, 3277, 3278)
                SELECT FIRST 1 M.GROUP_ID
                FROM PERSON_MOVEMENTS M
                JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID IN (9, 187)
                WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :PUPIL_ID
                ORDER BY M.DATE_OUT DESC
                INTO :PARENT_ID;

            END

            IF (I$REPORT IN (5, 6, 7, 8)) THEN
            BEGIN
                SELECT CAPTION FROM OBJECT_CAPTION_GET(:PUPIL_ID, NULL, NULL, :I$USER_ID) INTO :PUPIL_CAPTION;
            END

            IF (I$REPORT IN (6, 7, 8)) THEN
            BEGIN
                SELECT CAPTION FROM OBJECT_CAPTION_GET(:SUBJECT_ID, NULL, NULL, :I$USER_ID) INTO :SUBJECT_CAPTION;
                SELECT CAPTION FROM THE_CAPTION_TEACHER(:TEACHER_ID) INTO :TEACHER_CAPTION;
            END

            IF(PARENT_ID = CLASS_ID) THEN SUSPEND;

        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE ANALISYS_SUBJECT_LIST RETURNS (
    SUBJECT_ID BIGINT,
    SUBJECT_CAPTION VARCHAR(1000))
AS
BEGIN
    FOR SELECT DISTINCT V.SUBJECT_ID
        FROM VALM V
        WHERE V.IS_DEL = 0
        INTO :SUBJECT_ID
    DO
    BEGIN
        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:SUBJECT_ID)
        INTO :SUBJECT_CAPTION;

        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE APPLY_AOOP_TYPE (
    I$OBJ_ID BIGINT,
    I$PARAM_ID BIGINT,
    I$VAL BIGINT)
AS
declare variable V$OP bigint;
begin

  IF(I$PARAM_ID = 1832) THEN
  BEGIN
    -- Адаптированность ?
    SELECT LISTVAL_ID
    FROM VALL
    WHERE OBJ_ID = :I$OBJ_ID AND PARAM_ID = 2379 AND IS_DEL = 0
    INTO :V$OP;

    IF(I$VAL = 13287 AND (V$OP IS NULL OR V$OP <> 11197)) THEN
    BEGIN
      UPDATE OR INSERT INTO VALL (OBJ_ID, PARAM_ID, LISTVAL_ID, IS_DEL) VALUES (:I$OBJ_ID, 2379, 11197, 0) MATCHING (OBJ_ID, PARAM_ID);
    END
    ELSE IF(I$VAL <> 13287 AND V$OP = 11197) THEN
    BEGIN
      -- Меняем на
      UPDATE OR INSERT INTO VALL (OBJ_ID, PARAM_ID, LISTVAL_ID, IS_DEL) VALUES (:I$OBJ_ID, 2379, 13269, 0) MATCHING (OBJ_ID, PARAM_ID);
    END
  END
  ELSE IF(I$PARAM_ID = 2379) THEN
  BEGIN

    -- Какой тип ОП ?
    SELECT LISTVAL_ID
    FROM VALL
    WHERE OBJ_ID = :I$OBJ_ID AND PARAM_ID = 1832 AND IS_DEL = 0
    INTO :V$OP;

    IF(I$VAL = 11197 AND (V$OP IS NULL OR V$OP <> 13287)) THEN
    BEGIN
      -- Меняем на АООП
      UPDATE OR INSERT INTO VALL (OBJ_ID, PARAM_ID, LISTVAL_ID, IS_DEL) VALUES (:I$OBJ_ID, 1832, 13287, 0) MATCHING (OBJ_ID, PARAM_ID);
      UPDATE OR INSERT INTO VALL (OBJ_ID, PARAM_ID, LISTVAL_ID, IS_DEL) VALUES (:I$OBJ_ID, 1594, 13272, 0) MATCHING (OBJ_ID, PARAM_ID);
      UPDATE OR INSERT INTO VALL (OBJ_ID, PARAM_ID, LISTVAL_ID, IS_DEL) VALUES (:I$OBJ_ID, 1593, 5336, 0) MATCHING (OBJ_ID, PARAM_ID);
    END
    ELSE IF(I$VAL <> 11197 AND V$OP = 13287) THEN
    BEGIN
      -- Меняем на начальное
      UPDATE OR INSERT INTO VALL (OBJ_ID, PARAM_ID, LISTVAL_ID, IS_DEL) VALUES (:I$OBJ_ID, 1832, 5340, 0) MATCHING (OBJ_ID, PARAM_ID);
      UPDATE OR INSERT INTO VALL (OBJ_ID, PARAM_ID, LISTVAL_ID, IS_DEL) VALUES (:I$OBJ_ID, 1594, 5339, 0) MATCHING (OBJ_ID, PARAM_ID);
      UPDATE OR INSERT INTO VALL (OBJ_ID, PARAM_ID, LISTVAL_ID, IS_DEL) VALUES (:I$OBJ_ID, 1593, 5336, 0) MATCHING (OBJ_ID, PARAM_ID);
    END

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE APPLY_OVZ_TYPE (
    I$OBJ_ID BIGINT,
    I$CLASS_CONTENT BIGINT)
AS
declare variable V$PERSON_ID bigint;
declare variable V$OVZ bigint;
declare variable V$CLASS_OVZ bigint;
begin

  -- Переносим данные по персонам
  FOR
    SELECT L10.OBJ_ID, V207.LISTVAL_ID, V592.LISTVAL_ID
    FROM LINKS L10
    LEFT JOIN VALL V207 ON V207.OBJ_ID = L10.OBJ_ID AND V207.PARAM_ID = 207 AND V207.IS_DEL = 0
    LEFT JOIN VALL V592 ON V592.OBJ_ID = L10.PARENT_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0
    WHERE L10.DATE_DEL IS NULL AND L10.PARENT_ID = :I$OBJ_ID AND L10.OBJ_TYPE_ID = 10
    INTO :V$PERSON_ID, :V$OVZ, :V$CLASS_OVZ
  DO
  BEGIN

    -- При изменении статуса класса в не-ОВЗ ничего вообще не делаем
    IF(V$CLASS_OVZ <> 13275) THEN EXIT;

    V$OVZ = (CASE I$CLASS_CONTENT
      WHEN 13276 THEN 13291
      WHEN 13277 THEN 13292
      WHEN 13278 THEN 13293
      WHEN 13279 THEN 13294
      WHEN 13280 THEN 13295
      WHEN 13281 THEN 13296
      WHEN 13282 THEN 13297
      WHEN 13283 THEN 13298
      WHEN 13284 THEN 13299
      WHEN 13285 THEN 13300
      WHEN 13286 THEN 13301
      ELSE NULL
    END);

    IF(V$OVZ IS NULL) THEN EXIT;

    SELECT BLOB_ID FROM VAL_ADD(207, :V$PERSON_ID, :V$OVZ) INTO :V$OVZ;

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE AREA_SL_ROOMS_CALC (
    I$OBJ_ID BIGINT)
AS
declare variable V$BUILDING bigint;
declare variable V$AREA double precision;
declare variable V$BLOB_ID bigint;
begin
  -- Выбираем ID здания, обязательно будет только один ID
  SELECT LP16.PARENT_ID
  FROM LINKS LP16
  WHERE LP16.OBJ_ID = :I$OBJ_ID AND LP16.PARENT_TYPE_ID = 16 AND LP16.DATE_DEL IS NULL
  INTO :V$BUILDING;

  -- Если наш объект удален (пересчет площадей при удалении помещения), необходимо смотреть также удаленные ID
  IF(V$BUILDING IS NULL) THEN BEGIN

    SELECT FIRST 1 LP16.PARENT_ID
    FROM LINKS LP16
    WHERE LP16.OBJ_ID = :I$OBJ_ID AND LP16.PARENT_TYPE_ID = 16
    INTO :V$BUILDING;

    IF(V$BUILDING IS NULL) THEN EXCEPTION DATA_ERROR 'Не удалось установить здание, к которому относится данное помещение';

  END

  SELECT SUM(V533.VAL)
  FROM LINKS L61
  -- учебно-лабораторные помещения
  JOIN VALL V525 ON V525.PARAM_ID = 525 AND V525.OBJ_ID = L61.OBJ_ID AND V525.IS_DEL = 0 AND V525.LISTVAL_ID = 23
  LEFT JOIN VALF V533 ON V533.PARAM_ID = 533 AND V533.OBJ_ID = L61.OBJ_ID AND V533.IS_DEL = 0
  WHERE L61.OBJ_TYPE_ID = 61 AND L61.DATE_DEL IS NULL AND L61.PARENT_ID = :V$BUILDING
  INTO :V$AREA;

  IF(V$AREA IS NULL) THEN V$AREA = 0;

  SELECT BLOB_ID FROM VAL_ADD(499, :V$BUILDING, :V$AREA) INTO :V$BLOB_ID;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE ATT_CHOOSE_LIST (
    I$OBJ_ID BIGINT,
    I$PARAM_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    PARENT_ID BIGINT,
    LISTVAL_ID BIGINT,
    VAL VARCHAR(1000))
AS
declare variable V$VAL bigint;
begin

  IF(I$PARAM_ID = 3289) THEN
  BEGIN
    -- Группа должностей - параметр исключен
  END
  ELSE IF(I$PARAM_ID = 3290) THEN
  BEGIN
    -- Форма аттестации - самый главный параметр, от которого крутим дальше
    -- Этого списка больше нет, параметр удален !
    /*FOR
      SELECT L.PARENT_ID, L.LISTVAL_ID, L.VAL
      FROM LISTVALS_LIST(345) L
      WHERE L.IS_DEL = 0
      ORDER BY L.SORT_ORDER
      INTO :PARENT_ID, :LISTVAL_ID, :VAL
    DO
    BEGIN
      SUSPEND;
    END*/
  END
  ELSE IF(I$PARAM_ID = 3298) THEN
  BEGIN
    -- Должность для аттестации - выбираем из числа текущих
    FOR
      SELECT L15.OBJ_ID, C.VAL
      FROM LINKS LP14
      JOIN LINKS L15 ON L15.PARENT_ID = LP14.PARENT_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
      LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
      JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
      JOIN VALL V58 ON V58.OBJ_ID = LP13.PARENT_ID AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0
      LEFT JOIN LISTVAL_TEXT(V58.LISTVAL_ID) C ON 1 = 1
      WHERE LP14.OBJ_ID = :I$OBJ_ID AND LP14.PARENT_TYPE_ID = 14 AND LP14.DATE_DEL IS NULL AND V74.VAL IS NULL
      ORDER BY 2
      INTO :LISTVAL_ID, :VAL
    DO
    BEGIN
      SUSPEND;
    END
  END
  ELSE IF(I$PARAM_ID = 3292) THEN
  BEGIN
    -- Критерий - фильтруем по форме
    /*SELECT FIRST 1 V.LISTVAL_ID
    FROM LINKS LP458
    JOIN VALL V ON V.OBJ_ID = LP458.PARENT_ID AND V.PARAM_ID = 3290 AND V.IS_DEL = 0
    WHERE LP458.OBJ_ID = :I$OBJ_ID AND LP458.PARENT_TYPE_ID = 458 AND LP458.DATE_DEL IS NULL
    INTO :V$VAL;

    FOR
      SELECT L.PARENT_ID, L.LISTVAL_ID, L.VAL
      FROM LISTVALS_LIST(346) L
      WHERE L.IS_DEL = 0 AND L.TAG LIKE '%' || :V$VAL || '%'
      ORDER BY L.SORT_ORDER
      INTO :PARENT_ID, :LISTVAL_ID, :VAL
    DO
    BEGIN
      SUSPEND;
    END*/
  END
  ELSE IF(I$PARAM_ID = 3293) THEN
  BEGIN
    -- Тип документа - выбираем по типу критерия
    /*SELECT FIRST 1 V.LISTVAL_ID
    FROM VALL V
    WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 3292 AND V.IS_DEL = 0
    INTO :V$VAL;

    FOR
      SELECT L.PARENT_ID, L.LISTVAL_ID, L.VAL
      FROM LISTVALS_LIST(348) L
      WHERE L.IS_DEL = 0 AND L.TAG LIKE '%' || :V$VAL || '%'
      ORDER BY L.SORT_ORDER
      INTO :PARENT_ID, :LISTVAL_ID, :VAL
    DO
    BEGIN
      SUSPEND;
    END*/
  END
  ELSE IF(I$PARAM_ID = 3295) THEN
  BEGIN
    -- Значение оценки - параметр исключен
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE ATT_CLASSES_GET RETURNS (
    CLASS_ID BIGINT,
    STAGE INTEGER,
    CLASS VARCHAR(250))
AS
DECLARE VARIABLE SCHOOL_ID BIGINT;
BEGIN
    SELECT FIRST 1 L.OBJ_ID
    FROM LINKS L
    WHERE L.PARENT_ID IS NULL
      AND L.OBJ_TYPE_ID = 2
      AND L.DATE_DEL IS NULL
    INTO :SCHOOL_ID;

    FOR SELECT L9.OBJ_ID, LV8.COST
        FROM LINKS L7
        INNER JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID
        INNER JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID
        INNER JOIN VALL V8 ON V8.OBJ_ID = L8.OBJ_ID
        INNER JOIN LISTVALS LV8 ON LV8.LISTVAL_ID = V8.LISTVAL_ID
        WHERE L7.PARENT_ID = :SCHOOL_ID
          AND L7.OBJ_TYPE_ID = 7
          AND L7.DATE_DEL IS NULL
          AND L8.OBJ_TYPE_ID = 8
          AND L8.DATE_DEL IS NULL
          AND L9.OBJ_TYPE_ID = 9
          AND L9.DATE_DEL IS NULL
          AND V8.PARAM_ID = 49
          AND V8.IS_DEL = 0
          AND LV8.COST > 8
        ORDER BY LV8.SORT_ORDER, L9.OBJ_ID
        INTO :CLASS_ID, :STAGE
    DO
    BEGIN
        SELECT CAPTION FROM OBJECT_CAPTION_GET(:CLASS_ID) INTO :CLASS;
        SUSPEND;
    END

    FOR SELECT L125.OBJ_ID, LV8.COST
        FROM LINKS L7
        INNER JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID
        INNER JOIN LINKS L125 ON L125.PARENT_ID = L8.OBJ_ID
        INNER JOIN VALL V8 ON V8.OBJ_ID = L8.OBJ_ID
        INNER JOIN LISTVALS LV8 ON LV8.LISTVAL_ID = V8.LISTVAL_ID
        WHERE L7.PARENT_ID = :SCHOOL_ID
          AND L7.OBJ_TYPE_ID = 7
          AND L7.DATE_DEL IS NULL
          AND L8.OBJ_TYPE_ID = 8
          AND L8.DATE_DEL IS NULL
          AND L125.OBJ_TYPE_ID = 125
          AND L125.DATE_DEL IS NULL
          AND V8.PARAM_ID = 49
          AND V8.IS_DEL = 0
          AND LV8.COST > 8
        ORDER BY LV8.SORT_ORDER, L125.OBJ_ID
        INTO :CLASS_ID, :STAGE
    DO
    BEGIN
        SELECT CAPTION FROM OBJECT_CAPTION_GET(:CLASS_ID) INTO :CLASS;
        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE ATT_CLASS_GET (
    I$CLASS_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    SCHOOLAR_ID BIGINT,
    F VARCHAR(250),
    I VARCHAR(250),
    O VARCHAR(250),
    SEX VARCHAR(250),
    CLASS VARCHAR(250),
    BIRTHDATE DATE,
    IS_GIA SMALLINT)
AS
declare variable LANG_CODE varchar(2);
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :LANG_CODE;

    FOR SELECT L10.OBJ_ID
        FROM LINKS L10
        WHERE L10.PARENT_ID = :I$CLASS_ID
          AND L10.OBJ_TYPE_ID = 10
          AND L10.DATE_DEL IS NULL
        INTO :SCHOOLAR_ID
    DO
    BEGIN
        IS_GIA = 0;
        F = NULL;
        I = NULL;
        O = NULL;
        SEX = NULL;
        CLASS = NULL;
        BIRTHDATE = NULL;

        SELECT FIRST 1 V.VAL
        FROM VALS V
        WHERE V.PARAM_ID = 55
          AND V.OBJ_ID = :SCHOOLAR_ID
          AND V.IS_DEL = 0
        INTO :F;

        SELECT FIRST 1 V.VAL
        FROM VALS V
        WHERE V.PARAM_ID = 56
          AND V.OBJ_ID = :SCHOOLAR_ID
          AND V.IS_DEL = 0
        INTO :I;

        SELECT FIRST 1 V.VAL
        FROM VALS V
        WHERE V.PARAM_ID = 57
          AND V.OBJ_ID = :SCHOOLAR_ID
          AND V.IS_DEL = 0
        INTO :O;

        SELECT FIRST 1 V.VAL
        FROM VALD V
        WHERE V.PARAM_ID = 89
          AND V.OBJ_ID = :SCHOOLAR_ID
          AND V.IS_DEL = 0
        INTO :BIRTHDATE;

        SELECT FIRST 1 R.VAL
        FROM VALL V
        INNER JOIN LISTVALS LV ON LV.LISTVAL_ID = V.LISTVAL_ID

        LEFT JOIN RES_GET(LV.RES_ID,  :LANG_CODE) R ON 1=1

        WHERE V.PARAM_ID = 88
          AND V.OBJ_ID = :SCHOOLAR_ID
          AND V.IS_DEL = 0
        INTO :SEX;


        SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$CLASS_ID, NULL, NULL, :I$USER_ID) INTO :CLASS;

        SUSPEND;
    END

    FOR SELECT L126.OBJ_ID
        FROM LINKS L126
        WHERE L126.PARENT_ID = :I$CLASS_ID
          AND L126.OBJ_TYPE_ID = 126
          AND L126.DATE_DEL IS NULL
        INTO :SCHOOLAR_ID
    DO
    BEGIN
        IS_GIA = 1;
        F = NULL;
        I = NULL;
        O = NULL;
        SEX = NULL;
        CLASS = NULL;
        BIRTHDATE = NULL;

        SELECT FIRST 1 V.VAL
        FROM VALS V
        WHERE V.PARAM_ID = 827
          AND V.OBJ_ID = :SCHOOLAR_ID
          AND V.IS_DEL = 0
        INTO :F;

        SELECT FIRST 1 V.VAL
        FROM VALS V
        WHERE V.PARAM_ID = 828
          AND V.OBJ_ID = :SCHOOLAR_ID
          AND V.IS_DEL = 0
        INTO :I;

        SELECT FIRST 1 V.VAL
        FROM VALS V
        WHERE V.PARAM_ID = 829
          AND V.OBJ_ID = :SCHOOLAR_ID
          AND V.IS_DEL = 0
        INTO :O;

        SELECT FIRST 1 V.VAL
        FROM VALD V
        WHERE V.PARAM_ID = 830
          AND V.OBJ_ID = :SCHOOLAR_ID
          AND V.IS_DEL = 0
        INTO :BIRTHDATE;

        SELECT FIRST 1 R.VAL
        FROM VALL V
        INNER JOIN LISTVALS LV ON LV.LISTVAL_ID = V.LISTVAL_ID

        LEFT JOIN RES_GET(LV.RES_ID,  :LANG_CODE) R ON 1=1

        WHERE V.PARAM_ID = 1022
          AND V.OBJ_ID = :SCHOOLAR_ID
          AND V.IS_DEL = 0
        INTO :SEX;


        SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$CLASS_ID, NULL, NULL, :I$USER_ID) INTO :CLASS;

        SUSPEND;
    END

END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE ATT_CONTENT_GET (
    I$OBJ_ID BIGINT,
    I$ZONE INTEGER,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
declare variable V$PERSON_ID bigint;
declare variable V$ROLE smallint;
declare variable V$PERSON_TYPE bigint;
declare variable V$OBJ_ID bigint;
declare variable V$DATE date;
declare variable S1 varchar(400);
declare variable S2 varchar(400);
declare variable S3 varchar(400);
declare variable H integer;
declare variable S4 varchar(400);
declare variable S5 varchar(400);
declare variable V$LV bigint;
declare variable V$LV2 bigint;
begin

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  SELECT FIRST 1 U.OBJ_ID, U.USER_TYPE, O.TYPE_ID
  FROM USERS U
  LEFT JOIN OBJECTS O ON O.OBJ_ID = U.OBJ_ID
  WHERE U.DATE_DEL IS NULL AND U.USER_ID = :I$USER_ID AND U.IS_BLOCKED = 0 AND (U.EXP_DATE IS NULL OR U.EXP_DATE >= CURRENT_DATE)
  INTO :V$PERSON_ID, :V$ROLE, :V$PERSON_TYPE;

  IF(V$ROLE IS NULL) THEN EXCEPTION DATA_ERROR 'Пользователь не идентифицирован как сотрудник';
  IF(V$PERSON_TYPE <> 14 AND V$PERSON_TYPE IS NOT NULL) THEN EXCEPTION DATA_ERROR 'Доступ к данным аттестации для этого пользователя не предусмотрен';

  -- Если передан id персоны, проверяем
  IF(I$OBJ_ID IS NOT NULL) THEN
  BEGIN
    -- Проверяем наличие прав доступа к app.odb в личные дела сотрудников
    IF(NOT EXISTS(
      SELECT FIRST 1 1
      FROM LUSERS LU
      WHERE LU.USER_ID = :I$USER_ID AND LU.LEVEL_ID IN (48)
    )) THEN EXCEPTION DATA_ERROR 'У вас нет доступа к личным делам сотрудников';

    IF(NOT EXISTS(
      SELECT FIRST 1 1
      FROM LINKS L14
      WHERE L14.OBJ_ID = :I$OBJ_ID AND L14.PARENT_TYPE_ID IN (2, 211) AND L14.DATE_DEL IS NULL
    ))
    THEN EXCEPTION DATA_ERROR 'Переданный id не является id сотрудника';

    V$PERSON_ID = I$OBJ_ID;
  END

  -- Свои данные, соответствие должности
  TAG_NAME = 'my_att_job::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
    SELECT L156.OBJ_ID, V1232.VAL, C1233.VAL, V1234.SVAL, C2348.VAL
    FROM LINKS L156
    LEFT JOIN VALD V1232 ON V1232.OBJ_ID = L156.OBJ_ID AND V1232.PARAM_ID = 1232 AND V1232.IS_DEL = 0
    LEFT JOIN VALL V1233 ON V1233.OBJ_ID = L156.OBJ_ID AND V1233.PARAM_ID = 1233 AND V1233.IS_DEL = 0
    LEFT JOIN LISTVAL_TEXT(V1233.LISTVAL_ID) C1233 ON 1 = 1
    LEFT JOIN VALS V1234 ON V1234.OBJ_ID = L156.OBJ_ID AND V1234.PARAM_ID = 1234 AND V1234.IS_DEL = 0
    LEFT JOIN VALL V2348 ON V2348.OBJ_ID = L156.OBJ_ID AND V2348.PARAM_ID = 2348 AND V2348.IS_DEL = 0
    LEFT JOIN LISTVAL_TEXT(V2348.LISTVAL_ID) C2348 ON 1 = 1
    WHERE L156.PARENT_ID = :V$PERSON_ID AND L156.OBJ_TYPE_ID = 156 AND L156.DATE_DEL IS NULL
    ORDER BY 2
    INTO :V$OBJ_ID, :V$DATE, :S1, :S2, :S3
  DO
  BEGIN
    TAG_NAME = 'my_att_job:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'my_att_job:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'my_att_job:r:date';
    VAL = (SELECT VAL FROM DATE2ISO(:V$DATE, 0));
    SUSPEND;
    TAG_NAME = 'my_att_job:r:result';
    VAL = S1;
    SUSPEND;
    TAG_NAME = 'my_att_job:r:reason';
    VAL = S2;
    SUSPEND;
    TAG_NAME = 'my_att_job:r:job';
    VAL = S3;
    SUSPEND;
  END

  -- Свои данные, соответствие категории
  TAG_NAME = 'my_att_cat::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
    SELECT L34.OBJ_ID, V544.VAL, C545.VAL, V294.SVAL, C2347.VAL
    FROM LINKS L34
    LEFT JOIN VALD V544 ON V544.OBJ_ID = L34.OBJ_ID AND V544.PARAM_ID = 544 AND V544.IS_DEL = 0
    LEFT JOIN VALL V545 ON V545.OBJ_ID = L34.OBJ_ID AND V545.PARAM_ID = 545 AND V545.IS_DEL = 0
    LEFT JOIN LISTVAL_TEXT(V545.LISTVAL_ID) C545 ON 1 = 1
    LEFT JOIN VALS V294 ON V294.OBJ_ID = L34.OBJ_ID AND V294.PARAM_ID = 294 AND V294.IS_DEL = 0
    LEFT JOIN VALL V2347 ON V2347.OBJ_ID = L34.OBJ_ID AND V2347.PARAM_ID = 2347 AND V2347.IS_DEL = 0
    LEFT JOIN LISTVAL_TEXT(V2347.LISTVAL_ID) C2347 ON 1 = 1
    WHERE L34.PARENT_ID = :V$PERSON_ID AND L34.OBJ_TYPE_ID = 34 AND L34.DATE_DEL IS NULL
    ORDER BY 2
    INTO :V$OBJ_ID, :V$DATE, :S1, :S2, :S3
  DO
  BEGIN
    TAG_NAME = 'my_att_cat:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'my_att_cat:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'my_att_cat:r:date';
    VAL = (SELECT VAL FROM DATE2ISO(:V$DATE, 0));
    SUSPEND;
    TAG_NAME = 'my_att_cat:r:result';
    VAL = S1;
    SUSPEND;
    TAG_NAME = 'my_att_cat:r:reason';
    VAL = S2;
    SUSPEND;
    TAG_NAME = 'my_att_cat:r:job';
    VAL = S3;
    SUSPEND;
  END

  -- Свои повышения квалификации
  TAG_NAME = 'my_qual::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
    SELECT L36.OBJ_ID, V310.VAL, V304.VAL, V305.SVAL, C1024.VAL, V306.VAL, COALESCE(C307.VAL || ' ', '') || COALESCE(V308.SVAL || ' ', '') || COALESCE('№' || V309.SVAL, '')
    FROM LINKS L36
    LEFT JOIN VALD V310 ON V310.OBJ_ID = L36.OBJ_ID AND V310.PARAM_ID = 310 AND V310.IS_DEL = 0
    LEFT JOIN VALS V304 ON V304.OBJ_ID = L36.OBJ_ID AND V304.PARAM_ID = 304 AND V304.IS_DEL = 0
    LEFT JOIN VALS V305 ON V305.OBJ_ID = L36.OBJ_ID AND V305.PARAM_ID = 305 AND V305.IS_DEL = 0
    LEFT JOIN VALL V1024 ON V1024.OBJ_ID = L36.OBJ_ID AND V1024.PARAM_ID = 1024 AND V1024.IS_DEL = 0
    LEFT JOIN LISTVAL_TEXT(V1024.LISTVAL_ID) C1024 ON 1 = 1
    LEFT JOIN VALI V306 ON V306.OBJ_ID = L36.OBJ_ID AND V306.PARAM_ID = 306 AND V306.IS_DEL = 0
    LEFT JOIN VALL V307 ON V307.OBJ_ID = L36.OBJ_ID AND V307.PARAM_ID = 307 AND V307.IS_DEL = 0
    LEFT JOIN LISTVAL_TEXT(V307.LISTVAL_ID) C307 ON 1 = 1
    LEFT JOIN VALS V308 ON V308.OBJ_ID = L36.OBJ_ID AND V308.PARAM_ID = 308 AND V308.IS_DEL = 0
    LEFT JOIN VALS V309 ON V309.OBJ_ID = L36.OBJ_ID AND V309.PARAM_ID = 309 AND V309.IS_DEL = 0
    WHERE L36.PARENT_ID = :V$PERSON_ID AND L36.OBJ_TYPE_ID = 36 AND L36.DATE_DEL IS NULL
    ORDER BY 2
    INTO :V$OBJ_ID, :V$DATE, :S1, :S2, :S3, :H, :S4
  DO
  BEGIN
    TAG_NAME = 'my_qual:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'my_qual:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'my_qual:r:date';
    VAL = (SELECT VAL FROM DATE2ISO(:V$DATE, 0));
    SUSPEND;
    TAG_NAME = 'my_qual:r:oo_name';
    VAL = S1;
    SUSPEND;
    TAG_NAME = 'my_qual:r:course_name';
    VAL = S2;
    SUSPEND;
    TAG_NAME = 'my_qual:r:type';
    VAL = S3;
    SUSPEND;
    TAG_NAME = 'my_qual:r:dur';
    VAL = H;
    SUSPEND;
    TAG_NAME = 'my_qual:r:doc';
    VAL = S4;
    SUSPEND;
  END

  -- Директор, Завуч, специалист по персоналу видят сводные данные по всем сотрудникам
  IF(V$ROLE IN (1, 5, 6, 10) AND I$OBJ_ID IS NULL) THEN
  BEGIN
    TAG_NAME = 'persons::json&colon;array';
    VAL = '1';
    SUSPEND;
    FOR
      SELECT L14.OBJ_ID, C.CAPTION
      FROM LINKS L2
      JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
      LEFT JOIN OBJECT_CAPTION_GET(L14.OBJ_ID) C ON 1 = 1
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      ORDER BY 2
      INTO :V$OBJ_ID, :S1
    DO
    BEGIN
      TAG_NAME = 'persons:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'persons:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'persons:r:name';
      VAL = S1;
      SUSPEND;
      TAG_NAME = 'persons:r:is_teacher';
      VAL = 0;
      SELECT FIRST 1 1
      FROM LINKS L15
      LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
      JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
      LEFT JOIN DO_FUNC(LP13.PARENT_ID, 400, 68) F ON 1 = 1
      WHERE L15.PARENT_ID = :V$OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL AND V74.VAL IS NULL AND F.SORT_ORDER = 2
      INTO :VAL;
      SUSPEND;
      TAG_NAME = 'persons:r:job_date';
      VAL = NULL;
      SELECT FIRST 1 D.VAL
      FROM LINKS L156
      JOIN VALD V1232 ON V1232.OBJ_ID = L156.OBJ_ID AND V1232.PARAM_ID = 1232 AND V1232.IS_DEL = 0
      LEFT JOIN DATE2ISO(V1232.VAL, 0) D ON 1 = 1
      JOIN VALL V1233 ON V1233.OBJ_ID = L156.OBJ_ID AND V1233.PARAM_ID = 1233 AND V1233.IS_DEL = 0 AND V1233.LISTVAL_ID = 3033
      -- JOIN VALL V2348 ON V2348.OBJ_ID = L156.OBJ_ID AND V2348.PARAM_ID = 2348 AND V2348.IS_DEL = 0
      WHERE L156.PARENT_ID = :V$OBJ_ID AND L156.OBJ_TYPE_ID = 156 AND L156.DATE_DEL IS NULL
      ORDER BY V1232.VAL DESC
      INTO :VAL;
      SUSPEND;
      TAG_NAME = 'persons:r:cat_date';
      VAL = NULL;
      SELECT FIRST 1 D.VAL
      FROM LINKS L34
      JOIN VALD V544 ON V544.OBJ_ID = L34.OBJ_ID AND V544.PARAM_ID = 544 AND V544.IS_DEL = 0
      LEFT JOIN DATE2ISO(V544.VAL, 0) D ON 1 = 1
      JOIN VALL V545 ON V545.OBJ_ID = L34.OBJ_ID AND V545.PARAM_ID = 545 AND V545.IS_DEL = 0 AND V545.LISTVAL_ID IN (1208, 1209, 1210)
      -- JOIN VALL V2347 ON V2347.OBJ_ID = L34.OBJ_ID AND V2347.PARAM_ID = 2347 AND V2347.IS_DEL = 0
      WHERE L34.PARENT_ID = :V$OBJ_ID AND L34.OBJ_TYPE_ID = 34 AND L34.DATE_DEL IS NULL
      ORDER BY V544.VAL DESC
      INTO :VAL;
      SUSPEND;
      TAG_NAME = 'persons:r:qual_date';
      VAL = NULL;
      SELECT FIRST 1 D.VAL
      FROM LINKS L36
      JOIN VALD V310 ON V310.OBJ_ID = L36.OBJ_ID AND V310.PARAM_ID = 310 AND V310.IS_DEL = 0
      LEFT JOIN DATE2ISO(V310.VAL, 0) D ON 1 = 1
      WHERE L36.PARENT_ID = :V$OBJ_ID AND L36.OBJ_TYPE_ID = 36 AND L36.DATE_DEL IS NULL
      ORDER BY V310.VAL DESC
      INTO :VAL;
      SUSPEND;
    END
  END

  -- Каталоги документов на аттестацию
  TAG_NAME = 'att_folders::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
    SELECT L458.OBJ_ID, D.VAL, C.VAL, V3298.VAL, V3463.LISTVAL_ID, D2.VAL, V3299.LISTVAL_ID, C2.VAL
    FROM LINKS L458
    JOIN VALD V3462 ON V3462.OBJ_ID = L458.OBJ_ID AND V3462.PARAM_ID = 3462 AND V3462.IS_DEL = 0
    LEFT JOIN DATE2ISO(V3462.VAL, 0) D ON 1 = 1
    JOIN VALL V3464 ON V3464.OBJ_ID = L458.OBJ_ID AND V3464.PARAM_ID = 3464 AND V3464.IS_DEL = 0
    LEFT JOIN LISTVAL_TEXT(V3464.LISTVAL_ID) C ON 1 = 1
    JOIN VALS V3298 ON V3298.OBJ_ID = L458.OBJ_ID AND V3298.PARAM_ID = 3298 AND V3298.IS_DEL = 0
    JOIN VALL V3299 ON V3299.OBJ_ID = L458.OBJ_ID AND V3299.PARAM_ID = 3299 AND V3299.IS_DEL = 0
    LEFT JOIN LISTVAL_TEXT(V3299.LISTVAL_ID) C2 ON 1 = 1
    LEFT JOIN VALL V3463 ON V3463.OBJ_ID = L458.OBJ_ID AND V3463.PARAM_ID = 3463 AND V3463.IS_DEL = 0
    LEFT JOIN VALD V3460 ON V3460.OBJ_ID = L458.OBJ_ID AND V3460.PARAM_ID = 3460 AND V3460.IS_DEL = 0
    LEFT JOIN DATE2ISO(V3460.VAL, 1) D2 ON 1 = 1
    WHERE L458.PARENT_ID = :V$PERSON_ID AND L458.OBJ_TYPE_ID = 458 AND L458.DATE_DEL IS NULL
    ORDER BY V3462.VAL
    INTO :V$OBJ_ID, :S1, :S2, :S3, :V$LV, :S4, :V$LV2, :S5
  DO
  BEGIN
    TAG_NAME = 'att_folders:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'att_folders:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'att_folders:r:date';
    VAL = S1;
    SUSPEND;
    TAG_NAME = 'att_folders:r:category';
    VAL = S2;
    SUSPEND;
    TAG_NAME = 'att_folders:r:job';
    VAL = S3;
    SUSPEND;
    TAG_NAME = 'att_folders:r:state';
    VAL = V$LV2;
    SUSPEND;
    TAG_NAME = 'att_folders:r:state_name';
    VAL = S5;
    SUSPEND;
    TAG_NAME = 'att_folders:r:sent_at';
    VAL = S4;
    SUSPEND;
    TAG_NAME = 'att_folders:r:result';
    VAL = V$LV;
    SUSPEND;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE ATT_DATE_VERIFY (
    I$OBJ_ID BIGINT)
AS
DECLARE VARIABLE D1 DATE;
DECLARE VARIABLE D2 DATE;
DECLARE VARIABLE DY1 DATE;
DECLARE VARIABLE DY2 DATE;
begin

  SELECT V.VAL
  FROM VALD V
  WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 3396 AND V.IS_DEL = 0
  INTO :D1;

  SELECT V.VAL
  FROM VALD V
  WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 3397 AND V.IS_DEL = 0
  INTO :D2;

  SELECT CAST(LV.TAG AS DATE)
  FROM LINKS LP151
  JOIN LINKS LP481 ON LP481.OBJ_ID = LP151.PARENT_TYPE_ID AND LP481.PARENT_TYPE_ID = 481 AND LP481.DATE_DEL IS NULL
  JOIN VALL V3389 ON V3389.OBJ_ID = LP481.PARENT_ID AND V3389.PARAM_ID = 3389 AND V3389.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V3389.LISTVAL_ID
  WHERE LP151.OBJ_ID = :I$OBJ_ID AND LP151.PARENT_TYPE_ID = 151 AND LP151.DATE_DEL IS NULL
  INTO :DY1;

  -- Даем текущий год и весь следующий на пересдачи
  DY2 = DATEADD(2 YEAR TO DY1);

  IF(D1 > D2) THEN EXCEPTION DATA_ERROR 'Дата начала периода не может быть позже даты начала';
  IF(D1 < DY1 OR D2 < DY1) THEN EXCEPTION DATA_ERROR 'Период не может начинаться раньше начала учебного года';
  IF(D1 > DY2 OR D2 > DY2) THEN EXCEPTION DATA_ERROR 'Предельная дата для окончания периода - конец следующего учебного года';

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE ATT_DOCS_GET (
    I$YEAR SMALLINT,
    I$SCHOOLAR_ID BIGINT,
    I$DOC_TYPE_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    DOC_ID BIGINT,
    DOB DATE,
    REG_NUMBER VARCHAR(100),
    GIVE_DATE DATE,
    GIVE_FL SMALLINT,
    FIO_D VARCHAR(255))
AS
declare variable V$DF date;
declare variable V$DT date;
declare variable V$PUPIL_TYPE_ID bigint;
declare variable V$STAGE_ID bigint;
BEGIN
    SELECT TYPE_ID
    FROM OBJECTS
    WHERE OBJ_ID = :I$SCHOOLAR_ID
    INTO :V$PUPIL_TYPE_ID;

    V$DF = (I$YEAR - 1) || '.09.01';
    V$DT = I$YEAR || '.08.31';

    SELECT FIRST 1
           L11.OBJ_ID,
           V565.VAL,
           V566.VAL
    FROM LINKS L11

    JOIN VALL V50
    ON V50.OBJ_ID = L11.OBJ_ID
    AND V50.PARAM_ID = 50
    AND V50.IS_DEL = 0
    AND V50.LISTVAL_ID = :I$DOC_TYPE_ID

    LEFT JOIN VALS V565
    ON V565.OBJ_ID = L11.OBJ_ID
    AND V565.PARAM_ID = 565
    AND V565.IS_DEL = 0

    JOIN VALD V566
    ON V566.OBJ_ID = L11.OBJ_ID
    AND V566.PARAM_ID = 566
    AND V566.IS_DEL = 0
    AND ((:I$DOC_TYPE_ID <> 11137) OR ((V566.VAL >= :V$DF) AND (V566.VAL <= :V$DT)))

    WHERE L11.PARENT_ID = :I$SCHOOLAR_ID
    AND L11.OBJ_TYPE_ID = 11
    AND L11.DATE_DEL IS NULL

    INTO :DOC_ID,
         :REG_NUMBER,
         :GIVE_DATE;

    SELECT D
    FROM VAL_GET(:I$SCHOOLAR_ID, IIF(:V$PUPIL_TYPE_ID = 10, 89, 830), 0, :I$USER_ID)
    INTO :DOB;

    SELECT V
    FROM VAL_GET(:DOC_ID, 565, 0, :I$USER_ID)
    INTO :REG_NUMBER;

/*    SELECT IIF(POSITION('ВЫДАН', UPPER(V)) > 0, 1, 0)
    FROM VAL_GET(:DOC_ID, 569, 0, :I$USER_ID)
    INTO :GIVE_FL;*/

/*    IF (:GIVE_FL = 1) THEN
    BEGIN*/
        GIVE_FL = 0;

        SELECT FIRST 1 OBJ_ID
        FROM OBJECT_PARENTS_GET(:I$SCHOOLAR_ID, 7)
        INTO :V$STAGE_ID;

        SELECT FIRST 1 1
        FROM LINKS L234

        JOIN VALR V1872
        ON V1872.OBJ_ID = L234.OBJ_ID
        AND V1872.PARAM_ID = 1872
        AND V1872.IS_DEL = 0
        AND V1872.VAL = :I$SCHOOLAR_ID

        LEFT JOIN VALR V1877
        ON V1877.OBJ_ID = L234.OBJ_ID
        AND V1877.PARAM_ID = 1877
        AND V1877.IS_DEL = 0

        WHERE L234.PARENT_ID = :V$STAGE_ID
        AND L234.OBJ_TYPE_ID = 234
        AND L234.DATE_DEL IS NULL
        AND V1877.VAL IS NULL

        INTO :GIVE_FL;
/*    END*/

    SELECT V
    FROM VAL_GET(:I$SCHOOLAR_ID, 2353, 0, :I$USER_ID)
    INTO :FIO_D;

    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE ATT_DOCS_SET (
    I$YEAR BIGINT,
    I$SCHOOLAR_ID BIGINT,
    I$BLANK_STATUS_ID BIGINT,
    I$DOC_TYPE_ID BIGINT,
    I$DOC_VID_ID BIGINT,
    I$DOC_CODE SMALLINT,
    I$DOC_SERIA VARCHAR(250),
    I$DOC_NUMBER VARCHAR(250),
    I$DOC_DATE DATE,
    I$DOC_ORG VARCHAR(1000),
    I$DOC_GIVE_FL SMALLINT = 0,
    I$FIO_D VARCHAR(255) = null)
RETURNS (
    DOC_ID BIGINT)
AS
declare variable V$BLOB_ID bigint;
declare variable V$RECORD_ID bigint;
declare variable V$OBJ_ID bigint;
declare variable V$VAL varchar(4000);
declare variable V$STAGE_ID bigint;
declare variable V$DF date;
declare variable V$DT date;
BEGIN
    IF (I$DOC_TYPE_ID IS NULL) THEN EXIT;

    V$DF = (I$YEAR - 1) || '.09.01';
    V$DT = I$YEAR || '.08.31';

    SELECT FIRST 1 L11.OBJ_ID
    FROM LINKS L11
    JOIN VALL V50 ON V50.OBJ_ID = L11.OBJ_ID AND V50.PARAM_ID = 50 AND V50.IS_DEL = 0 AND V50.LISTVAL_ID = :I$DOC_TYPE_ID
    LEFT JOIN VALS V564 ON V564.OBJ_ID = L11.OBJ_ID AND V564.PARAM_ID = 564 AND V564.IS_DEL = 0
    LEFT JOIN VALS V565 ON V565.OBJ_ID = L11.OBJ_ID AND V565.PARAM_ID = 565 AND V565.IS_DEL = 0
    JOIN VALD V566 ON V566.OBJ_ID = L11.OBJ_ID AND V566.PARAM_ID = 566 AND V566.IS_DEL = 0
        AND (((:I$DOC_TYPE_ID <> 11137) AND (V566.VAL = :I$DOC_DATE)) OR ((V566.VAL >= :V$DF) AND (V566.VAL <= :V$DT)))
    WHERE L11.PARENT_ID = :I$SCHOOLAR_ID AND L11.OBJ_TYPE_ID = 11 AND L11.DATE_DEL IS NULL
        AND ((:I$DOC_SERIA IS NULL) OR (V564.VAL LIKE :I$DOC_SERIA)) AND ((:I$DOC_NUMBER IS NULL) OR (V565.VAL LIKE :I$DOC_NUMBER))
    INTO :DOC_ID;

    IF (DOC_ID IS NULL) THEN
    BEGIN
        SELECT OBJ_ID
        FROM OBJECT_ADD(:I$SCHOOLAR_ID, 11)
        INTO :DOC_ID;
    END

    IF (DOC_ID IS NULL) THEN EXIT;

    IF (:I$FIO_D IS NOT NULL) THEN
    BEGIN
        SELECT BLOB_ID
        FROM VAL_ADD(2353, :I$SCHOOLAR_ID, :I$FIO_D)
        INTO :V$BLOB_ID;
    END

    SELECT BLOB_ID
    FROM VAL_ADD(50, :DOC_ID, :I$DOC_TYPE_ID)
    INTO :V$BLOB_ID;

    IF (I$BLANK_STATUS_ID IS NOT NULL) THEN
    BEGIN
        SELECT BLOB_ID
        FROM VAL_ADD(2458, :DOC_ID, :I$BLANK_STATUS_ID)
        INTO :V$BLOB_ID;
    END

    IF (I$DOC_VID_ID IS NOT NULL) THEN
    BEGIN
        SELECT BLOB_ID
        FROM VAL_ADD(705, :DOC_ID, :I$DOC_VID_ID)
        INTO :V$BLOB_ID;
    END

    IF (I$DOC_CODE IS NOT NULL) THEN
    BEGIN
        SELECT BLOB_ID
        FROM VAL_ADD(567, :DOC_ID, :I$DOC_CODE)
        INTO :V$BLOB_ID;
    END

    IF (I$DOC_SERIA IS NOT NULL) THEN
    BEGIN
        SELECT BLOB_ID
        FROM VAL_ADD(564, :DOC_ID, :I$DOC_SERIA)
        INTO :V$BLOB_ID;
    END

    IF (I$DOC_NUMBER IS NOT NULL) THEN
    BEGIN
        SELECT BLOB_ID
        FROM VAL_ADD(565, :DOC_ID, :I$DOC_NUMBER)
        INTO :V$BLOB_ID;
    END

    IF (I$DOC_DATE IS NOT NULL) THEN
    BEGIN
        SELECT BLOB_ID
        FROM VAL_ADD(566, :DOC_ID, :I$DOC_DATE)
        INTO :V$BLOB_ID;
    END

    IF (I$DOC_ORG IS NOT NULL) THEN
    BEGIN
        SELECT BLOB_ID
        FROM VAL_ADD(568, :DOC_ID, :I$DOC_ORG)
        INTO :V$BLOB_ID;
    END

    IF (I$DOC_GIVE_FL = 1) THEN
    BEGIN
        /*
        SELECT TRIM(V)
        FROM VAL_GET(:DOC_ID, 569)
        INTO :V$VAL;

        IF (POSITION('ВЫДАН', UPPER(:V$VAL)) = 0) THEN
        BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD(569, :DOC_ID, IIF(:V$VAL = '', 'ВЫДАНА', :V$VAL || '; ВЫДАНА'))
            INTO :V$BLOB_ID;
        END
        */

        SELECT FIRST 1 OBJ_ID
        FROM OBJECT_PARENTS_GET(:I$SCHOOLAR_ID, 7)
        INTO :V$STAGE_ID;

        IF(V$STAGE_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не удалось определить уровень образования для учащегося';

        V$BLOB_ID = 0;

        SELECT FIRST 1 L234.OBJ_ID
        FROM LINKS L234
        JOIN VALR V1872 ON V1872.OBJ_ID = L234.OBJ_ID AND V1872.PARAM_ID = 1872 AND V1872.IS_DEL = 0 AND V1872.VAL = :I$SCHOOLAR_ID
        LEFT JOIN VALR V1877 ON V1877.OBJ_ID = L234.OBJ_ID AND V1877.PARAM_ID = 1877 AND V1877.IS_DEL = 0
        WHERE L234.PARENT_ID = :V$STAGE_ID AND L234.OBJ_TYPE_ID = 234 AND L234.DATE_DEL IS NULL AND V1877.VAL IS NULL
        INTO :V$RECORD_ID;

        IF (:V$RECORD_ID IS NULL) THEN
        BEGIN
            SELECT OBJ_ID
            FROM OBJECT_ADD(:V$STAGE_ID,  234)
            INTO :V$RECORD_ID;

            SELECT BLOB_ID
            FROM VAL_ADD(1872, :V$RECORD_ID, :I$SCHOOLAR_ID)
            INTO :V$BLOB_ID;

            IF (I$DOC_DATE IS NOT NULL) THEN
            BEGIN
                SELECT BLOB_ID
                FROM VAL_ADD(1876, :V$RECORD_ID, :I$DOC_DATE)
                INTO :V$BLOB_ID;
            END

            V$OBJ_ID = NULL;
            SELECT FIRST 1 L292.OBJ_ID
            FROM LINKS L292
            JOIN VALI V2354 ON V2354.OBJ_ID = L292.OBJ_ID AND V2354.PARAM_ID = 2354 AND V2354.IS_DEL = 0 AND V2354.VAL = :I$YEAR
            WHERE L292.PARENT_ID = :I$SCHOOLAR_ID AND L292.OBJ_TYPE_ID = 292 AND L292.DATE_DEL IS NULL
            INTO :V$OBJ_ID;
    
            IF (V$OBJ_ID IS NULL) THEN
            BEGIN
                FOR
                    SELECT OBJ_ID
                    FROM OBJECT_ADD(:I$SCHOOLAR_ID, 292)
                    INTO :V$OBJ_ID
                DO
                BEGIN
                    SELECT BLOB_ID
                    FROM VAL_ADD(2354, :V$OBJ_ID, :I$YEAR)
                    INTO :V$BLOB_ID;
                END
            END
            SELECT BLOB_ID
            FROM VAL_ADD(2355, :V$RECORD_ID, :V$OBJ_ID)
            INTO :V$BLOB_ID;
        END

        SELECT BLOB_ID
        FROM VAL_ADD(2356, :V$RECORD_ID, :DOC_ID)
        INTO :V$BLOB_ID;
    END

    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE ATT_FILE_ADD (
    I$OBJ_ID BIGINT,
    I$TYPE_ID BIGINT NOT NULL,
    I$NAME VARCHAR(1000) NOT NULL,
    I$USER_ID VARCHAR(40))
RETURNS (
    ID BIGINT,
    BLOB_ID BIGINT,
    DOCTYPE BIGINT,
    STATE BIGINT,
    NAME VARCHAR(1000))
AS
declare variable V$STATE_ID bigint;
begin

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  SELECT V.LISTVAL_ID
  FROM VALL V
  WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 3299 AND V.IS_DEL = 0
  INTO :V$STATE_ID;

  IF(V$STATE_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не найден пакет документов';
  IF(V$STATE_ID IN (14342, 14343)) THEN EXCEPTION DATA_ERROR 'Нельзя загружать файлы после отправки';

  SELECT OBJ_ID FROM OBJECT_ADD(:I$OBJ_ID, 459, NULL, NULL, :I$USER_ID) INTO :ID;

  DOCTYPE = I$TYPE_ID;
  SELECT 1 FROM VAL_ADD(3293, :ID, :I$TYPE_ID) INTO :V$STATE_ID;

  STATE = 14338;
  NAME = I$NAME;

  -- Меняем сразу статус на заверенный для автоформируемых справок
  IF(I$TYPE_ID IN (14113, 14114, 14169)) THEN
  BEGIN
    SELECT 1 FROM VAL_ADD(3296, :ID, 14335) INTO :V$STATE_ID;
    STATE = 14335;
  END

  INSERT INTO VALB
  (OBJ_ID, PARAM_ID, VAL)
  VALUES (:ID, 3294, :I$NAME)
  RETURNING BLOB_ID INTO :BLOB_ID;

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE ATT_FILE_DELETE (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
AS
declare variable V$FILE_ID1 varchar(100);
declare variable V$FILE_ID2 varchar(100);
declare variable V$STATE_ID bigint;
declare variable V$FOLDER_ID bigint;
declare variable V$NAME varchar(1000);
begin

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  SELECT LP458.PARENT_ID, V.LISTVAL_ID, V1.VAL, V2.VAL, VN.VAL
  FROM LINKS LP458
  JOIN VALL V ON V.OBJ_ID = LP458.PARENT_ID AND V.PARAM_ID = 3299 AND V.IS_DEL = 0
  LEFT JOIN VALS V1 ON V1.OBJ_ID = LP458.OBJ_ID AND V1.PARAM_ID = 3291 AND V1.IS_DEL = 0
  LEFT JOIN VALS V2 ON V2.OBJ_ID = LP458.OBJ_ID AND V2.PARAM_ID = 3297 AND V2.IS_DEL = 0
  LEFT JOIN VALB VN ON VN.OBJ_ID = LP458.OBJ_ID AND VN.PARAM_ID = 3294 AND VN.IS_DEL = 0
  WHERE LP458.OBJ_ID = :I$OBJ_ID AND LP458.OBJ_TYPE_ID = 459 AND LP458.PARENT_TYPE_ID = 458 AND LP458.DATE_DEL IS NULL
  INTO :V$FOLDER_ID, :V$STATE_ID, :V$FILE_ID1, :V$FILE_ID2, :V$NAME;

  IF(V$STATE_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не найден файл или пакет документов';
  IF(V$STATE_ID IN (14342, 14343)) THEN EXCEPTION DATA_ERROR 'Нельзя загружать файлы после отправки пакета';
  IF(V$FILE_ID1 IS NOT NULL OR V$FILE_ID2 IS NOT NULL) THEN EXCEPTION DATA_ERROR 'Нельзя загружать уже отправленные файлы';

  UPDATE LINKS
  SET DATE_DEL = CURRENT_TIMESTAMP
  WHERE OBJ_ID = :I$OBJ_ID AND DATE_DEL IS NULL;

  INSERT INTO HISTVALS
  (TABLE_NAME, OBJ_ID, PARAM_ID, OPT_ID, VAL, USER_ID)
  VALUES ('LINKS', :V$FOLDER_ID, :I$OBJ_ID, 1, :V$NAME, :I$USER_ID);

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE ATT_FILE_GET (
    I$OBJ_ID BIGINT,
    I$ZONE SMALLINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    BLOB_ID BIGINT,
    FILE_NAME VARCHAR(1000))
AS
begin

  SELECT VN.VAL, VN.BLOB_ID
  FROM LINKS LP458
  JOIN VALB VN ON VN.OBJ_ID = LP458.OBJ_ID AND VN.PARAM_ID = 3294 AND VN.IS_DEL = 0
  WHERE LP458.OBJ_ID = :I$OBJ_ID AND LP458.OBJ_TYPE_ID = 459 AND LP458.PARENT_TYPE_ID = 458 AND LP458.DATE_DEL IS NULL
  INTO :FILE_NAME, :BLOB_ID;

  IF(FILE_NAME IS NULL) THEN EXCEPTION DATA_ERROR 'Файл или пакет документов не найдены';

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE ATT_FILE_STATE (
    I$OBJ_ID BIGINT,
    I$STATE BIGINT,
    I$USER_ID VARCHAR(40))
AS
declare variable V$FILE_ID1 varchar(100);
declare variable V$FILE_ID2 varchar(100);
declare variable V$STATE_ID bigint;
declare variable V$FOLDER_ID bigint;
declare variable V$NAME varchar(1000);
declare variable V$TYPE bigint;
begin

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  SELECT LP458.PARENT_ID, V.LISTVAL_ID, V1.VAL, V2.VAL, VN.VAL, V3296.LISTVAL_ID
  FROM LINKS LP458
  JOIN VALL V ON V.OBJ_ID = LP458.PARENT_ID AND V.PARAM_ID = 3299 AND V.IS_DEL = 0
  JOIN VALL V3296 ON V3296.OBJ_ID = LP458.OBJ_ID AND V3296.PARAM_ID = 3296 AND V3296.IS_DEL = 0
  LEFT JOIN VALS V1 ON V1.OBJ_ID = LP458.OBJ_ID AND V1.PARAM_ID = 3291 AND V1.IS_DEL = 0
  LEFT JOIN VALS V2 ON V2.OBJ_ID = LP458.OBJ_ID AND V2.PARAM_ID = 3297 AND V2.IS_DEL = 0
  LEFT JOIN VALB VN ON VN.OBJ_ID = LP458.OBJ_ID AND VN.PARAM_ID = 3294 AND VN.IS_DEL = 0
  WHERE LP458.OBJ_ID = :I$OBJ_ID AND LP458.OBJ_TYPE_ID = 459 AND LP458.PARENT_TYPE_ID = 458 AND LP458.DATE_DEL IS NULL
  INTO :V$FOLDER_ID, :V$STATE_ID, :V$FILE_ID1, :V$FILE_ID2, :V$NAME, :V$TYPE;

  IF(V$STATE_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не найден файл или пакет документов';
  IF(V$STATE_ID IN (14342, 14343)) THEN EXCEPTION DATA_ERROR 'Нельзя менять статус файлов после отправки пакета';
  IF(V$FILE_ID1 IS NOT NULL OR V$FILE_ID2 IS NOT NULL) THEN EXCEPTION DATA_ERROR 'Нельзя менять статус уже отправленных файлов';

  IF(V$TYPE IN (14113, 14114, 14169)) THEN EXCEPTION DATA_ERROR 'Для служебных документов нельзя менять статус';

  -- Статус можно менять только когда сам пакет в статусе заверения,
  -- либо пользователь имеет высокие права доступа

  SELECT 1 FROM VAL_ADD(3296, :I$OBJ_ID, :I$STATE) INTO :V$STATE_ID;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE ATT_FOLDER_ADD (
    I$PERSON_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$ZONE SMALLINT,
    I$USER_ID VARCHAR(40),
    I$JOB_ID VARCHAR(400),
    I$CAT_ID BIGINT,
    I$FORM_ID VARCHAR(40))
RETURNS (
    OBJ_ID BIGINT,
    "DATE" VARCHAR(20),
    CATEGORY VARCHAR(400),
    JOB VARCHAR(400),
    STATE BIGINT,
    STATE_NAME VARCHAR(400),
    FORM_ID VARCHAR(40))
AS
declare variable V$ROLE smallint;
declare variable V$PERSON_TYPE bigint;
declare variable V$JOB_ID bigint;
declare variable T integer;
begin

  IF(I$JOB_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не выбрана должность';
  IF(I$CAT_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не выбрана категория';

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  -- Если персона не указана, проверяем самого себя
  IF(I$PERSON_ID IS NULL) THEN
  BEGIN
    SELECT FIRST 1 U.OBJ_ID, U.USER_TYPE, O.TYPE_ID
    FROM USERS U
    LEFT JOIN OBJECTS O ON O.OBJ_ID = U.OBJ_ID
    WHERE U.DATE_DEL IS NULL AND U.USER_ID = :I$USER_ID AND U.IS_BLOCKED = 0 AND (U.EXP_DATE IS NULL OR U.EXP_DATE >= CURRENT_DATE)
    INTO :I$PERSON_ID, :V$ROLE, :V$PERSON_TYPE;

    IF(V$ROLE IS NULL) THEN EXCEPTION DATA_ERROR 'Пользователь не идентифицирован как сотрудник';
    IF(V$PERSON_TYPE <> 14 AND V$PERSON_TYPE IS NOT NULL) THEN EXCEPTION DATA_ERROR 'Доступ к данным аттестации для этого пользователя не предусмотрен';
  END

  -- Проверяем что должность актуальная
  SELECT FIRST 1 L15.OBJ_ID
  FROM LINKS L15
  JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
  LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
  LEFT JOIN DO_FUNC(LP13.PARENT_ID, 400) F ON 1 = 1
  JOIN VALS V589 ON V589.OBJ_ID = LP13.PARENT_ID AND V589.PARAM_ID = 589 AND V589.IS_DEL = 0 AND V589.VAL = :I$JOB_ID
  WHERE L15.PARENT_ID = :I$PERSON_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
    AND V74.VAL IS NULL AND F.VAL = 'Да'
  INTO :V$JOB_ID;

  IF(V$JOB_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Должность не найдена или была утрачена';
  IF(I$FORM_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не указана форма аттестации';

  SELECT OBJ_ID FROM OBJECT_ADD(:I$PERSON_ID, 458, NULL, NULL, :I$USER_ID) INTO :OBJ_ID;
  SELECT 1 FROM VAL_ADD(3298, :OBJ_ID, :I$JOB_ID) INTO :T;
  SELECT 1 FROM VAL_ADD(3464, :OBJ_ID, :I$CAT_ID) INTO :T;
  SELECT 1 FROM VAL_ADD(3290, :OBJ_ID, :I$FORM_ID) INTO :T;

  -- Достаем автосозданные поля
  SELECT VAL
  FROM LISTVAL_TEXT(:I$CAT_ID)
  INTO :CATEGORY;

  JOB = I$JOB_ID;
  FORM_ID = I$FORM_ID;

  SELECT V3299.LISTVAL_ID, C.VAL
  FROM VALL V3299
  LEFT JOIN LISTVAL_TEXT(V3299.LISTVAL_ID) C ON 1 = 1
  WHERE V3299.OBJ_ID = :OBJ_ID AND V3299.PARAM_ID = 3299 AND V3299.IS_DEL = 0
  INTO :STATE, :STATE_NAME;

  SELECT C.VAL
  FROM VALD V3462
  LEFT JOIN DATE2ISO(V3462.VAL, 0) C ON 1 = 1
  WHERE V3462.OBJ_ID = :OBJ_ID AND V3462.PARAM_ID = 3462 AND V3462.IS_DEL = 0
  INTO :"DATE";

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE ATT_FOLDER_DELETE (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
AS
declare variable V$FILE_ID1 varchar(100);
declare variable V$FILE_ID2 varchar(100);
declare variable V$STATE_ID bigint;
declare variable V$FOLDER_ID bigint;
declare variable V$NAME varchar(1000);
declare variable V$OWNER_ID bigint;
declare variable V$PERSON_ID bigint;
begin

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  SELECT V.LISTVAL_ID
  FROM VALL V
  WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 3299 AND V.IS_DEL = 0
  INTO :V$STATE_ID;

  IF(V$STATE_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не найден пакет документов';
  IF(V$STATE_ID IN (14342, 14343)) THEN EXCEPTION DATA_ERROR 'Нельзя удалять папку после начала отправки';

  -- Удалить пакет может только лично действующий сотрудник, либо руководитель или администратор после его увольнения
  SELECT LP14.PARENT_ID, LPG.PARENT_ID
  FROM LINKS LP14
  LEFT JOIN LINKS LPG ON LPG.OBJ_ID = LP14.PARENT_ID AND LPG.PARENT_TYPE_ID IN (2, 211) AND LPG.DATE_DEL IS NULL
  WHERE LP14.OBJ_ID = :I$OBJ_ID AND LP14.PARENT_TYPE_ID = 14 AND LP14.DATE_DEL IS NULL
  INTO :V$PERSON_ID, :V$OWNER_ID;

  IF(V$OWNER_ID IS NULL) THEN
  BEGIN
    IF(NOT EXISTS(
      SELECT FIRST 1 1
      FROM USERS U
      WHERE U.DATE_DEL IS NULL AND U.IS_BLOCKED = 0 AND (U.EXP_DATE IS NULL OR U.EXP_DATE > CURRENT_DATE) AND U.USER_TYPE IN (1, 5)
    ))
    THEN
      EXCEPTION DATA_ERROR 'Пакет документов уволенного сотрудника может удалить только пользователь с правами директора или администратора';
  END
  ELSE
  BEGIN
    IF(NOT EXISTS(
      SELECT FIRST 1 1
      FROM USERS U
      WHERE U.OBJ_ID = :V$PERSON_ID AND U.DATE_DEL IS NULL AND U.IS_BLOCKED = 0 AND (U.EXP_DATE IS NULL OR U.EXP_DATE > CURRENT_DATE)
    ))
    THEN
      EXCEPTION DATA_ERROR 'Удалить пакет документов может только сотрудник лично';
  END

  IF(EXISTS(
    SELECT FIRST 1 1
    FROM LINKS L459
    LEFT JOIN VALS V1 ON V1.OBJ_ID = L459.OBJ_ID AND V1.PARAM_ID = 3291 AND V1.IS_DEL = 0
    LEFT JOIN VALS V2 ON V2.OBJ_ID = L459.OBJ_ID AND V2.PARAM_ID = 3297 AND V2.IS_DEL = 0
    WHERE L459.PARENT_ID = :I$OBJ_ID AND L459.OBJ_TYPE_ID = 459 AND L459.DATE_DEL IS NULL
      AND (V1.VAL IS NOT NULL OR V2.VAL IS NOT NULL)
  ))
  THEN
    EXCEPTION DATA_ERROR 'Как минимум один из прикрепленных файлов уже был отправлен';

  UPDATE LINKS
  SET DATE_DEL = CURRENT_TIMESTAMP
  WHERE OBJ_ID = :I$OBJ_ID AND DATE_DEL IS NULL;

  INSERT INTO HISTVALS
  (TABLE_NAME, OBJ_ID, PARAM_ID, USER_ID)
  VALUES ('LINKS_DEL', :I$OBJ_ID, NULL, :I$USER_ID);

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE ATT_FOLDER_GET (
    I$PERSON_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$ZONE SMALLINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
declare variable V$ROLE bigint;
declare variable V$PERSON_TYPE bigint;
declare variable V$OBJ_ID bigint;
declare variable V$JOB_ID varchar(400);
declare variable V$CAT_ID bigint;
declare variable V$DT_ID bigint;
declare variable V$BLOB_ID bigint;
declare variable V$CAT_TAG varchar(10);
declare variable V$FORM_ID varchar(10);
declare variable S varchar(1000);
declare variable S2 varchar(1000);
declare variable T integer;
declare variable P integer;
declare variable V$TEMP varchar(40);
begin

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  IF(I$OBJ_ID IS NOT NULL) THEN
  BEGIN
    SELECT FIRST 1 LP14.PARENT_ID
    FROM LINKS LP14
    WHERE LP14.OBJ_ID = :I$OBJ_ID AND LP14.PARENT_TYPE_ID = 14 AND LP14.DATE_DEL IS NULL
    INTO :I$PERSON_ID;
  END

  -- Если персона не указана, проверяем самого себя
  IF(I$PERSON_ID IS NULL) THEN
  BEGIN
    SELECT FIRST 1 U.OBJ_ID, U.USER_TYPE, O.TYPE_ID
    FROM USERS U
    LEFT JOIN OBJECTS O ON O.OBJ_ID = U.OBJ_ID
    WHERE U.DATE_DEL IS NULL AND U.USER_ID = :I$USER_ID AND U.IS_BLOCKED = 0 AND (U.EXP_DATE IS NULL OR U.EXP_DATE >= CURRENT_DATE)
    INTO :I$PERSON_ID, :V$ROLE, :V$PERSON_TYPE;

    IF(V$ROLE IS NULL) THEN EXCEPTION DATA_ERROR 'Пользователь не идентифицирован как сотрудник';
    IF(V$PERSON_TYPE <> 14 AND V$PERSON_TYPE IS NOT NULL) THEN EXCEPTION DATA_ERROR 'Доступ к данным аттестации для этого пользователя не предусмотрен';
  END

  SELECT FIRST 1 V3298.VAL
  FROM VALS V3298
  WHERE V3298.OBJ_ID = :I$OBJ_ID AND V3298.PARAM_ID = 3298 AND V3298.IS_DEL = 0
  INTO :V$JOB_ID;

  SELECT FIRST 1 V3290.VAL
  FROM VALS V3290
  WHERE V3290.OBJ_ID = :I$OBJ_ID AND V3290.PARAM_ID = 3290 AND V3290.IS_DEL = 0
  INTO :V$FORM_ID;

  SELECT FIRST 1 V3464.LISTVAL_ID
  FROM VALL V3464
  WHERE V3464.OBJ_ID = :I$OBJ_ID AND V3464.PARAM_ID = 3464 AND V3464.IS_DEL = 0
  INTO :V$CAT_ID;

  TAG_NAME = 'id';
  VAL = I$OBJ_ID;
  SUSPEND;

  TAG_NAME = 'person_id';
  VAL = I$PERSON_ID;
  SUSPEND;

  TAG_NAME = 'person_name';
  VAL = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$PERSON_ID));
  SUSPEND;

  -- Номер заявления
  TAG_NAME = 'req_no';
  VAL = NULL;
  SELECT FIRST 1 V3465.VAL
  FROM VALS V3465
  WHERE V3465.OBJ_ID = :I$OBJ_ID AND V3465.PARAM_ID = 3465 AND V3465.IS_DEL = 0
  INTO :VAL;
  SUSPEND;

  -- Определяем форму по названию должности
  IF(V$FORM_ID IS NULL) THEN
  BEGIN
    S = LOWER(V$JOB_ID);
    IF(V$CAT_ID = 14331) THEN V$FORM_ID = '17';
    ELSE IF(V$CAT_ID = 14332) THEN V$FORM_ID = '18';
    ELSE IF(S = 'воспитатель' OR S = 'инструктор по труду' OR S = 'инструктор по физической культуре' OR S = 'логопед' OR S = 'мастер производственного обучения'
      OR S = 'педагог-организатор' OR S = 'преподаватель' OR S = 'преподаватель-организатор основ безопасности жизнедеятельности'
      OR S = 'руководитель физического воспитания' OR S = 'старший вожатый' OR S = 'тьютор' OR S = 'учитель' OR S = 'учитель-дефектолог'
      OR S = 'учитель-логопед') THEN V$FORM_ID = '1';
    ELSE IF(S = 'методист' OR S = 'старший методист') THEN V$FORM_ID = '2';
    ELSE IF(S = 'воспитатель' OR S = 'инструктор по физической культуре' OR S = 'музыкальный руководитель' OR S = 'старший воспитатель'
      OR S = 'учитель-дефектолог' OR S = 'учитель-логопед') THEN V$FORM_ID = '3';
    ELSE IF(S = 'воспитатель' OR S = 'инструктор по физической культуре' OR S = 'концертмейстер' OR S = 'педагог дополнительного образования'
      OR S = 'педагог-организатор') THEN V$FORM_ID = '4';
    ELSE IF(S = 'педагог-психолог' OR S = 'социальный педагог') THEN V$FORM_ID = '5';
    ELSE IF(S = 'старший тренер-преподаватель' OR S = 'тренер-преподаватель') THEN V$FORM_ID = '6';
    ELSE IF(S = 'инструктор-методист') THEN V$FORM_ID = '6';
    -- 8, 9, 10 пропускаем
    ELSE IF(S = 'педагог-библиотекарь') THEN V$FORM_ID = '11';
    -- 12, 13, 14, 15 пропускаем
    ELSE IF(S = 'советник руководителя по воспитанию и взаимодействию с детскими общественными объединениями'
      OR S = 'советник директора по воспитанию и взаимодействию с детскими общественными объединениями') THEN V$FORM_ID = '16';
  END

  -- Список доступных должностей, только педагогические
  -- только действующие, плюс выбираем ту которая уже была выбрана
  TAG_NAME = 'job_id:selection::json&colon;array';
  VAL = '1';
  SUSPEND;
  T = 0;
  FOR
    SELECT DISTINCT V589.VAL
    FROM LINKS L15
    JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
    LEFT JOIN DO_FUNC(LP13.PARENT_ID, 400) F ON 1 = 1
    JOIN VALS V589 ON V589.OBJ_ID = LP13.PARENT_ID AND V589.PARAM_ID = 589 AND V589.IS_DEL = 0
    WHERE L15.PARENT_ID = :I$PERSON_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL AND V74.VAL IS NULL AND F.VAL = 'Да'
    UNION
    SELECT :V$JOB_ID
    FROM RDB$DATABASE
    WHERE :V$JOB_ID IS NOT NULL
    ORDER BY 1
    INTO :S
  DO
  BEGIN
    TAG_NAME = 'job_id:selection:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'job_id:selection:r:id';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'job_id:selection:r:value';
    VAL = S;
    SUSPEND;
    V$TEMP = S;
    T = T + 1;
  END
  TAG_NAME = 'job_id:values:value';
  IF(T = 1 AND V$JOB_ID IS NULL) THEN V$JOB_ID = V$TEMP;
  VAL = V$JOB_ID;
  SUSPEND;
  TAG_NAME = 'job_name';
  SUSPEND;

  -- Категория для выбора
  -- Если есть активная категория по должности - подставляем ее
  TAG_NAME = 'cat_id:selection::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
    SELECT LISTVAL_ID, VAL
    FROM LISTVALS_LIST(361)
    WHERE IS_DEL = 0
    INTO :V$OBJ_ID, :S
  DO
  BEGIN
    TAG_NAME = 'cat_id:selection:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'cat_id:selection:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'cat_id:selection:r:value';
    VAL = S;
    SUSPEND;
  END
  TAG_NAME = 'cat_id:values:value';
  VAL = V$CAT_ID;
  SUSPEND;

  TAG_NAME = 'form_id:selection::json&colon;array';
  VAL = '1';
  SUSPEND;
  -- Всего 18 форм
  V$OBJ_ID = 1;
  WHILE(V$OBJ_ID <= 18) DO
  BEGIN
    IF(V$OBJ_ID NOT IN (8, 9, 10, 12, 13, 14, 15)) THEN
    BEGIN
      TAG_NAME = 'form_id:selection:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'form_id:selection:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'form_id:selection:r:value';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'form_id:selection:r:subset_id';
      VAL = NULL;
      IF(V$OBJ_ID = 1) THEN
        VAL = 'воспитатель;инструктор по труду;инструктор по физической культуре;логопед;мастер производственного обучения;педагог-организатор;преподаватель;' ||
          'преподаватель-организатор основ безопасности жизнедеятельности;руководитель физического воспитания;старший вожатый;тьютор;учитель;учитель-дефектолог;учитель-логопед';
      ELSE IF(V$OBJ_ID = 2) THEN
        VAL = 'методист;старший методист';
      ELSE IF(V$OBJ_ID = 3) THEN
        VAL = 'воспитатель;инструктор по физической культуре;музыкальный руководитель;старший воспитатель;учитель-дефектолог;учитель-логопед';
      ELSE IF(V$OBJ_ID = 4) THEN
        VAL = 'воспитатель;инструктор по физической культуре;концертмейстер;педагог дополнительного образования;педагог-организатор';
      ELSE IF(V$OBJ_ID = 5) THEN
        VAL = 'педагог-психолог;социальный педагог';
      ELSE IF(V$OBJ_ID = 6) THEN
        VAL = 'старший тренер-преподаватель;тренер-преподаватель';
      ELSE IF(V$OBJ_ID = 7) THEN
        VAL = 'инструктор-методист';
      ELSE IF(V$OBJ_ID = 11) THEN
        VAL = 'педагог-библиотекарь';
      ELSE IF(V$OBJ_ID = 16) THEN
        VAL = 'советник руководителя по воспитанию и взаимодействию с детскими общественными объединениями;советник директора по воспитанию и взаимодействию с детскими общественными объединениями';
      ELSE IF(V$OBJ_ID = 17) THEN
        VAL = '*14331';
      ELSE IF(V$OBJ_ID = 18) THEN
        VAL = '*14332';
      SUSPEND;
    END
    V$OBJ_ID = V$OBJ_ID + 1;
  END
  TAG_NAME = 'form_id:values:value';
  VAL = V$FORM_ID;
  SUSPEND;

  TAG_NAME = 'date';
  VAL = NULL;
  SELECT C.VAL
  FROM VALD V3462
  LEFT JOIN DATE2ISO(V3462.VAL, 0) C ON 1 = 1
  WHERE V3462.OBJ_ID = :I$OBJ_ID AND V3462.PARAM_ID = 3462 AND V3462.IS_DEL = 0
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'date_sent';
  VAL = NULL;
  SELECT C.VAL
  FROM VALDT V3460
  LEFT JOIN DATE2ISO(V3460.VAL, 1) C ON 1 = 1
  WHERE V3460.OBJ_ID = :I$OBJ_ID AND V3460.PARAM_ID = 3460 AND V3460.IS_DEL = 0
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'date_result';
  VAL = NULL;
  SELECT C.VAL
  FROM VALDT V3461
  LEFT JOIN DATE2ISO(V3461.VAL, 1) C ON 1 = 1
  WHERE V3461.OBJ_ID = :I$OBJ_ID AND V3461.PARAM_ID = 3461 AND V3461.IS_DEL = 0
  INTO :VAL;
  SUSPEND;

  -- Статус
  TAG_NAME = 'state_id:selection::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
    SELECT LISTVAL_ID, VAL
    FROM LISTVALS_LIST(364)
    WHERE IS_DEL = 0
    INTO :V$OBJ_ID, :S
  DO
  BEGIN
    TAG_NAME = 'state_id:selection:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'state_id:selection:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'state_id:selection:r:value';
    VAL = S;
    SUSPEND;
  END
  TAG_NAME = 'state_id:values:value';
  SELECT V3299.LISTVAL_ID
  FROM VALL V3299
  WHERE V3299.OBJ_ID = :I$OBJ_ID AND V3299.PARAM_ID = 3299 AND V3299.IS_DEL = 0
  INTO :VAL;
  SUSPEND;

  -- Результат
  TAG_NAME = 'result_id:selection::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
    SELECT LISTVAL_ID, VAL
    FROM LISTVALS_LIST(362)
    WHERE IS_DEL = 0
    INTO :V$OBJ_ID, :S
  DO
  BEGIN
    TAG_NAME = 'result_id:selection:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'result_id:selection:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'result_id:selection:r:value';
    VAL = S;
    SUSPEND;
  END
  TAG_NAME = 'result_id:values:value';
  VAL = NULL;
  SELECT V3463.LISTVAL_ID
  FROM VALL V3463
  WHERE V3463.OBJ_ID = :I$OBJ_ID AND V3463.PARAM_ID = 3463 AND V3463.IS_DEL = 0
  INTO :VAL;
  SUSPEND;

  -- Каталог положенных по должности типов документов, сразу же дофильтровываем его по выбранной должности
  -- фильтр берем по полю TAG - до первой точки
  TAG_NAME = 'doctypes::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
    SELECT LISTVAL_ID, VAL, TAG
    FROM LISTVALS_LIST(348)
    WHERE IS_DEL = 0
    INTO :V$OBJ_ID, :S, :S2
  DO
  BEGIN
    P = POSITION('.' IN S2);
    IF(V$FORM_ID = SUBSTRING(S2 FROM 1 FOR P - 1)) THEN
    BEGIN
      TAG_NAME = 'doctypes:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'doctypes:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'doctypes:r:section';
      VAL = SUBSTRING(S2 FROM P + 1);
      SUSPEND;
      TAG_NAME = 'doctypes:r:value';
      VAL = S;
      SUSPEND;
    END
  END

  -- Прикрепленные файлы
  TAG_NAME = 'items::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
    SELECT L459.OBJ_ID, V3293.LISTVAL_ID, V3294.BLOB_ID, V3294.VAL, V3296.LISTVAL_ID
    FROM LINKS L459
    JOIN VALL V3293 ON V3293.OBJ_ID = L459.OBJ_ID AND V3293.PARAM_ID = 3293 AND V3293.IS_DEL = 0
    LEFT JOIN VALB V3294 ON V3294.OBJ_ID = L459.OBJ_ID AND V3294.PARAM_ID = 3294 AND V3294.IS_DEL = 0
    JOIN VALL V3296 ON V3296.OBJ_ID = L459.OBJ_ID AND V3296.PARAM_ID = 3296 AND V3296.IS_DEL = 0
    WHERE L459.PARENT_ID = :I$OBJ_ID AND L459.OBJ_TYPE_ID = 459 AND L459.DATE_DEL IS NULL AND :I$OBJ_ID IS NOT NULL
    INTO :V$OBJ_ID, :V$DT_ID, :V$BLOB_ID, :S, :V$ROLE
  DO
  BEGIN
    TAG_NAME = 'items:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'items:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'items:r:doctype';
    VAL = V$DT_ID;
    SUSPEND;
    TAG_NAME = 'items:r:blob_id';
    VAL = V$BLOB_ID;
    SUSPEND;
    TAG_NAME = 'items:r:name';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'items:r:state';
    VAL = V$ROLE;
    SUSPEND;
  END

  -- Реквизиты для справки
  TAG_NAME = 'current_date';
  VAL = (SELECT VAL FROM DATE2SCRIPT(CURRENT_DATE));
  SUSPEND;

  TAG_NAME = 'director_name';
  VAL = NULL;
  S = NULL;
  S2 = NULL;
  SELECT FIRST 1 P.FIO, P.POST, V5.VAL
  FROM LINKS L2
  LEFT JOIN R_SPB_POST_DIRECTOR(L2.OBJ_ID, 1) P ON 1 = 1
  LEFT JOIN VALS V5 ON V5.OBJ_ID = L2.OBJ_ID AND V5.PARAM_ID = 5 AND V5.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :VAL, :S, :S2;
  SUSPEND;

  TAG_NAME = 'director_post';
  VAL = S;
  SUSPEND;

  TAG_NAME = 'ou_name';
  VAL = S2;
  SUSPEND;

  VAL = NULL;
  S = NULL;
  TAG_NAME = 'job_date';
  SELECT FIRST 1 D.VAL, COALESCE('№ ' || V1638.VAL, '___________________________')
  FROM LINKS L15
  JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0
  LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
  JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
  JOIN VALS V589 ON V589.OBJ_ID = LP13.PARENT_ID AND V589.PARAM_ID = 589 AND V589.IS_DEL = 0 AND V589.VAL = :V$JOB_ID
  LEFT JOIN DATE2SCRIPT(V73.VAL) D ON 1 = 1
  -- номер трудового договора
  LEFT JOIN VALS V1638 ON V1638.OBJ_ID = L15.OBJ_ID AND V1638.PARAM_ID = 1638 AND V1638.IS_DEL = 0
  WHERE L15.PARENT_ID = :I$PERSON_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL AND V74.VAL IS NULL
  ORDER BY V73.VAL
  INTO :VAL, :S;
  SUSPEND;

  TAG_NAME = 'contract_name';
  VAL = S;
  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE ATT_FOLDER_STATE (
    I$OBJ_ID BIGINT,
    I$STATE_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    EMAIL_ADDR VARCHAR(400),
    EMAIL_NAME VARCHAR(400),
    PERSON_NAME VARCHAR(400),
    N_FAIL INTEGER)
AS
declare variable T integer;
declare variable V$STATE_ID bigint;
declare variable V$FOLDER_ID bigint;
declare variable V$NAME varchar(1000);
declare variable V$PERSON_ID bigint;
begin

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  SELECT V.LISTVAL_ID
  FROM VALL V
  WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 3299 AND V.IS_DEL = 0
  INTO :V$STATE_ID;

  IF(V$STATE_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не найден пакет документов';
  IF(V$STATE_ID IN (14342, 14343)) THEN EXCEPTION DATA_ERROR 'Нельзя менять статус папки после начала отправки';

  IF(I$STATE_ID NOT IN (14342, 14343) AND EXISTS(
    SELECT FIRST 1 1
    FROM LINKS L459
    LEFT JOIN VALS V1 ON V1.OBJ_ID = L459.OBJ_ID AND V1.PARAM_ID = 3291 AND V1.IS_DEL = 0
    LEFT JOIN VALS V2 ON V2.OBJ_ID = L459.OBJ_ID AND V2.PARAM_ID = 3297 AND V2.IS_DEL = 0
    WHERE L459.PARENT_ID = :I$OBJ_ID AND L459.OBJ_TYPE_ID = 459 AND L459.DATE_DEL IS NULL
      AND (V1.VAL IS NOT NULL OR V2.VAL IS NOT NULL)
  ))
  THEN
    EXCEPTION DATA_ERROR 'Как минимум один из прикрепленных файлов уже был отправлен, нельзя менять статус';

  IF(NOT EXISTS(
    SELECT FIRST 1 1
    FROM LINKS L459
    WHERE L459.PARENT_ID = :I$OBJ_ID AND L459.OBJ_TYPE_ID = 459 AND L459.DATE_DEL IS NULL
  ))
  THEN
    EXCEPTION DATA_ERROR 'Нет ни одного файла';

  -- Не требуется повторно отправлять на заверение, если все уже и так готово ?
  IF(V$STATE_ID = 14341 AND I$STATE_ID = 14340) THEN
  BEGIN
  END

  -- По готовности заверения все документы должны иметь явный статус
  IF(I$STATE_ID = 14341) THEN
  BEGIN
    IF(EXISTS(
      SELECT FIRST 1 1
      FROM LINKS L459
      JOIN VALL V1 ON V1.OBJ_ID = L459.OBJ_ID AND V1.PARAM_ID = 3296 AND V1.IS_DEL = 0 AND V1.LISTVAL_ID = 14338
      WHERE L459.PARENT_ID = :I$OBJ_ID AND L459.OBJ_TYPE_ID = 459 AND L459.DATE_DEL IS NULL
    ))
    THEN
      EXCEPTION DATA_ERROR 'У всех документов должен быть выставлен статус заверения, отказ или указание об отсутствии необходимости в заверении';
  END

  SELECT 1 FROM VAL_ADD(3299, :I$OBJ_ID, :I$STATE_ID) INTO :T;

  -- Смотрим по статусу кому слать уведомление
  IF(I$STATE_ID = 14340) THEN
  BEGIN
    -- Кто будет проверять ?
    -- В порядке приоритета: пользователь с ролью специалист по кадрам, затем пользователь с ролью директор,
    -- затем сотрудник с должностью секретарь и т.п.,
    -- затем сотрудник с должностью руководитель 1 уровня
    SELECT FIRST 1 SQ, VAL, CAPTION
    FROM (
      SELECT 1 SQ, V.VAL, C.CAPTION
      FROM USERS U
      JOIN LINKS L14 ON L14.OBJ_ID = U.OBJ_ID AND L14.PARENT_TYPE_ID = 2 AND L14.DATE_DEL IS NULL
      LEFT JOIN VALS V ON V.OBJ_ID = L14.OBJ_ID AND V.PARAM_ID = 1180 AND V.IS_DEL = 0
      LEFT JOIN OBJECT_CAPTION_GET(L14.OBJ_ID) C ON 1 = 1
      WHERE U.DATE_DEL IS NULL AND U.IS_BLOCKED = 0 AND U.USER_TYPE = 10 AND (U.EXP_DATE IS NULL OR U.EXP_DATE > CURRENT_DATE)
      UNION
      SELECT 2 SQ, V.VAL, C.CAPTION
      FROM USERS U
      JOIN LINKS L14 ON L14.OBJ_ID = U.OBJ_ID AND L14.PARENT_TYPE_ID = 2 AND L14.DATE_DEL IS NULL
      LEFT JOIN VALS V ON V.OBJ_ID = L14.OBJ_ID AND V.PARAM_ID = 1180 AND V.IS_DEL = 0
      LEFT JOIN OBJECT_CAPTION_GET(L14.OBJ_ID) C ON 1 = 1
      WHERE U.DATE_DEL IS NULL AND U.IS_BLOCKED = 0 AND U.USER_TYPE = 5 AND (U.EXP_DATE IS NULL OR U.EXP_DATE > CURRENT_DATE)
      UNION
      SELECT IIF(V64.LISTVAL_ID = 56, 4, 3) SQ, V.VAL, C.CAPTION
      FROM USERS U
      JOIN LINKS L14 ON L14.OBJ_ID = U.OBJ_ID AND L14.PARENT_TYPE_ID = 2 AND L14.DATE_DEL IS NULL
      JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
      JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
      JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
      JOIN VALL V58 ON V58.OBJ_ID = L15.OBJ_ID AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0
      JOIN VALL V64 ON V64.OBJ_ID = L15.OBJ_ID AND V64.PARAM_ID = 64 AND V64.IS_DEL = 0
      LEFT JOIN VALS V ON V.OBJ_ID = L14.OBJ_ID AND V.PARAM_ID = 1180 AND V.IS_DEL = 0
      LEFT JOIN OBJECT_CAPTION_GET(L14.OBJ_ID) C ON 1 = 1
      WHERE U.DATE_DEL IS NULL AND U.IS_BLOCKED = 0 AND (U.EXP_DATE IS NULL OR U.EXP_DATE > CURRENT_DATE)
        AND V74.VAL IS NULL AND (V58.LISTVAL_ID IN (3302, 1317, 1314, 1321) OR V64.LISTVAL_ID = 56)
    )
    ORDER BY 1
    INTO :T, :EMAIL_ADDR, :EMAIL_NAME;

    SELECT FIRST 1 C.CAPTION
    FROM LINKS LP14
    LEFT JOIN OBJECT_CAPTION_GET(LP14.PARENT_ID) C ON 1 = 1
    WHERE LP14.OBJ_ID = :I$OBJ_ID AND LP14.PARENT_TYPE_ID = 14 AND LP14.DATE_DEL IS NULL
    INTO :PERSON_NAME;

    N_FAIL = -1;
  END
  ELSE IF(I$STATE_ID = 14341) THEN
  BEGIN
    -- Сам сотрудник
    SELECT FIRST 1 V.VAL, C.CAPTION
    FROM LINKS LP14
    LEFT JOIN VALS V ON V.OBJ_ID = LP14.PARENT_ID AND V.PARAM_ID = 1180 AND V.IS_DEL = 0
    LEFT JOIN OBJECT_CAPTION_GET(LP14.PARENT_ID) C ON 1 = 1
    WHERE LP14.OBJ_ID = :I$OBJ_ID AND LP14.PARENT_TYPE_ID = 14 AND LP14.DATE_DEL IS NULL
    INTO :EMAIL_ADDR, :EMAIL_NAME;

    SELECT COUNT(*)
    FROM LINKS L459
    JOIN VALL V1 ON V1.OBJ_ID = L459.OBJ_ID AND V1.PARAM_ID = 3296 AND V1.IS_DEL = 0 AND V1.LISTVAL_ID = 14336
    WHERE L459.PARENT_ID = :I$OBJ_ID AND L459.OBJ_TYPE_ID = 459 AND L459.DATE_DEL IS NULL
    INTO :N_FAIL;
  END
  ELSE IF(I$STATE_ID = 14342) THEN
  BEGIN
    SELECT 1 FROM VAL_ADD(3460, :I$OBJ_ID, CURRENT_TIMESTAMP) INTO :T;
  END

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE ATT_INFO_GET (
    I$OBJ_ID BIGINT,
    I$STATE SMALLINT)
RETURNS (
    STD_NUM INTEGER,
    STUFF_NAME VARCHAR(400),
    STATE_NAME VARCHAR(100),
    STUFF_IDS VARCHAR(400))
AS
DECLARE VARIABLE S VARCHAR(400);
DECLARE VARIABLE OBJ_ID BIGINT;
begin

  STUFF_NAME = '';
  STUFF_IDS = '';
  FOR
    SELECT C.CAPTION, S.PERSON_ID
    FROM ATT_REGISTER_STUFF S
    LEFT JOIN OBJECT_CAPTION_GET(S.PERSON_ID) C ON 1 = 1
    WHERE S.DATE_DEL IS NULL AND S.ATT_ID = :I$OBJ_ID
    ORDER BY 1
    INTO :S, :OBJ_ID
  DO
  BEGIN
    IF(CHAR_LENGTH(STUFF_NAME) + CHAR_LENGTH(S) < 398) THEN
    BEGIN
      IF(STUFF_NAME <> '') THEN STUFF_NAME = STUFF_NAME || ', ';
      IF(STUFF_IDS <> '') THEN STUFF_IDS = STUFF_IDS || ',';
      STUFF_NAME = STUFF_NAME || S;
      STUFF_IDS = STUFF_IDS || OBJ_ID;
    END
  END

  SELECT COUNT(*)
  FROM ATT_REGISTER_STDS S
  WHERE S.DATE_DEL IS NULL AND S.ATT_ID = :I$OBJ_ID
  INTO :STD_NUM;

  IF(I$STATE = 0) THEN STATE_NAME = 'Проект';
  ELSE IF(I$STATE = 1) THEN STATE_NAME = 'В процессе';
  ELSE IF(I$STATE = 2) THEN STATE_NAME = 'Завершено';
  ELSE IF(I$STATE = 3) THEN STATE_NAME = 'Отменено';

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE ATT_MARK_GET (
    I$SCHOOLAR_ID BIGINT,
    I$SUBJECT_ID BIGINT,
    I$USER_ID BIGINT,
    I$MARKTYPE_ID BIGINT = 3013,
    I$LAST_YEAR_FL SMALLINT = 0)
RETURNS (
    MARK VARCHAR(250),
    YEAR_RES_ID BIGINT,
    YEAR_COST INTEGER)
AS
DECLARE VARIABLE Y INTEGER;
DECLARE VARIABLE LANG_CODE VARCHAR(2);
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :LANG_CODE;

    Y = EXTRACT(YEAR FROM CURRENT_DATE) - 1;

/*    SELECT FIRST 1 LV3.VAL
    FROM LINKS L51
    INNER JOIN LINKS L10 ON L10.OBJ_ID = L51.OBJ_ID
    INNER JOIN VALL V1181 ON V1181.OBJ_ID = L51.OBJ_ID
    INNER JOIN VALL V1182 ON V1182.OBJ_ID = L51.OBJ_ID
    INNER JOIN VALL V1183 ON V1183.OBJ_ID = L51.OBJ_ID
    INNER JOIN LISTVALS LV1 ON LV1.LISTVAL_ID = V1181.LISTVAL_ID
    INNER JOIN LISTVALS LV2 ON LV2.LISTVAL_ID = V1182.LISTVAL_ID
    INNER JOIN LISTVALS LV3 ON LV3.LISTVAL_ID = V1183.LISTVAL_ID
    WHERE L51.PARENT_ID = :I$SUBJECT_ID
      AND L51.OBJ_TYPE_ID = 155
      AND L51.DATE_DEL IS NULL
      AND L10.PARENT_ID = :I$SCHOOLAR_ID
      AND L10.OBJ_TYPE_ID = 155
      AND L10.DATE_DEL IS NULL
      AND V1181.PARAM_ID = 1181
      AND V1181.IS_DEL = 0
      AND V1182.PARAM_ID = 1182
      AND V1182.IS_DEL = 0
      AND V1183.PARAM_ID = 1183
      AND V1183.IS_DEL = 0
      AND LV1.COST = :Y
      AND LV2.LISTVAL_ID = 3013
    INTO :MARK;     */

    SELECT FIRST 1
        R.VAL,
        LV1.RES_ID,
        LV1.COST
    FROM VALM VM
    INNER JOIN LISTVALS LV1 ON LV1.LISTVAL_ID = VM.YEAR_ID
    INNER JOIN LISTVALS LV3 ON LV3.LISTVAL_ID = VM.MARKVAL_ID
    LEFT JOIN RES_GET(LV3.RES_ID,  :LANG_CODE) R ON 1=1
    WHERE VM.PUPIL_ID = :I$SCHOOLAR_ID
      AND VM.SUBJECT_ID = :I$SUBJECT_ID
      AND VM.MARKTYPE_ID = :I$MARKTYPE_ID
      AND VM.IS_DEL = 0
      AND (:I$LAST_YEAR_FL = 1 OR LV1.COST = :Y)
    ORDER BY LV1.COST DESC
    INTO :MARK, :YEAR_RES_ID, :YEAR_COST;

    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE ATT_OU_GET (
    I$USER_ID BIGINT)
RETURNS (
    OU VARCHAR(4000),
    F VARCHAR(250),
    I VARCHAR(250),
    O VARCHAR(250),
    POST VARCHAR(250))
AS
declare variable SCHOOL_ID bigint;
BEGIN
    SELECT FIRST 1 L.OBJ_ID
    FROM LINKS L
    WHERE L.PARENT_ID IS NULL
      AND L.OBJ_TYPE_ID = 2
      AND L.DATE_DEL IS NULL
    INTO :SCHOOL_ID;

    SELECT FIRST 1 V.VAL
    FROM VALS V
    WHERE V.PARAM_ID = 5
      AND V.OBJ_ID = :SCHOOL_ID
      AND V.IS_DEL = 0
    INTO :OU;

    SELECT F, I, O, POST
    FROM R_SPB_POST_DIRECTOR(:SCHOOL_ID, :I$USER_ID)
    INTO :F, :I, :O, :POST;

    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE ATT_PKG_DATA (
    I$OBJ_ID BIGINT,
    I$REQ_NO VARCHAR(40),
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
declare variable V$OBJ_ID bigint;
declare variable V$CAT_ID bigint;
declare variable V$C1 varchar(100);
declare variable V$C2 varchar(100);
declare variable V$BLOB bigint;
declare variable V$CRIT varchar(400);
declare variable V$FT varchar(400);
declare variable V$FNAME varchar(400);
declare variable V$APPROVED bigint;
declare variable V$PERSON_ID bigint;
declare variable N integer;
begin

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  TAG_NAME = 'org_id';
  VAL = NULL;
  SELECT GEN
  FROM GEN
  INTO :VAL;
  SUSPEND;

  -- Номер заявления - обновляем при необходимости, но только если не было отправки
  IF(I$REQ_NO IS NOT NULL AND NOT EXISTS(
    SELECT FIRST 1 1
    FROM VALL V3299
    WHERE V3299.OBJ_ID = :I$OBJ_ID AND V3299.PARAM_ID = 3299 AND V3299.IS_DEL = 0 AND V3299.LISTVAL_ID IN (14342, 14343)
  )) THEN
    SELECT 1 FROM VAL_ADD(3465, :I$OBJ_ID, :I$REQ_NO) INTO :V$OBJ_ID;

  TAG_NAME = 'req_no';
  VAL = NULL;
  SELECT V.VAL
  FROM VALS V
  WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 3465 AND V.IS_DEL = 0
  INTO :VAL;
  IF(VAL IS NULL) THEN EXCEPTION DATA_ERROR 'Не указан номер заявления';
  SUSPEND;

  TAG_NAME = 'pkg_id';
  VAL = NULL;
  SELECT V.VAL
  FROM VALS V
  WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 3288 AND V.IS_DEL = 0
  INTO :VAL;
  SUSPEND;

  -- Идентификатор сотрудника
  -- сразу проверяем, что отправлять пакет может только сотрудник лично
  TAG_NAME = 'reg_id';
  VAL = NULL;
  SELECT V2915.VAL, LP14.PARENT_ID
  FROM LINKS LP14
  JOIN VALS V2915 ON V2915.OBJ_ID = LP14.PARENT_ID AND V2915.PARAM_ID = 2915 AND V2915.IS_DEL = 0
  WHERE LP14.OBJ_ID = :I$OBJ_ID AND LP14.PARENT_TYPE_ID = 14 AND LP14.DATE_DEL IS NULL
  INTO :VAL, :V$PERSON_ID;
  IF(VAL IS NULL) THEN EXCEPTION DATA_ERROR 'Нельзя отправить документы для сотрудника без DataID';
  IF(POSITION(':' IN VAL) > 0) THEN VAL = SUBSTRING(VAL FROM 1 FOR POSITION(':' IN VAL) - 1);
  SUSPEND;

  TAG_NAME = 'person_name';
  VAL = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$PERSON_ID));
  SUSPEND;

  IF(NOT EXISTS(
    SELECT FIRST 1 1
    FROM USERS U
    WHERE U.OBJ_ID = :V$PERSON_ID AND U.DATE_DEL IS NULL AND U.IS_BLOCKED = 0 AND (U.EXP_DATE IS NULL OR U.EXP_DATE > CURRENT_DATE)
  ))
  THEN
    EXCEPTION DATA_ERROR 'Отправку пакета документов может выполнять только сотрудник лично';

  TAG_NAME = 'form';
  VAL = NULL;
  SELECT V.VAL
  FROM VALS V
  WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 3290 AND V.IS_DEL = 0
  INTO :VAL;
  IF(VAL IS NULL) THEN EXCEPTION DATA_ERROR 'Не определена форма аттестации';
  SUSPEND;

  TAG_NAME = 'job';
  VAL = NULL;
  SELECT V.VAL
  FROM VALS V
  WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 3298 AND V.IS_DEL = 0
  INTO :VAL;
  IF(VAL IS NULL) THEN EXCEPTION DATA_ERROR 'Не заполнена должность, для которой выполняется аттестация';
  SUSPEND;

  TAG_NAME = 'category';
  VAL = NULL;
  SELECT V.LISTVAL_ID
  FROM VALL V
  WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 3464 AND V.IS_DEL = 0
  INTO :VAL;
  IF(VAL IS NULL) THEN EXCEPTION DATA_ERROR 'Не заполнена категория, для которой выполняется аттестация';
  SUSPEND;

  TAG_NAME = 'req_no';
  VAL = NULL;
  SELECT V.VAL
  FROM VALS V
  WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 3465 AND V.IS_DEL = 0
  INTO :VAL;
  IF(VAL IS NULL) THEN EXCEPTION DATA_ERROR 'Не указан номер заявления';
  SUSPEND;

  -- Проверяем, не было ли оно уже отправлено
  TAG_NAME = 'applied';
  VAL = NULL;
  SELECT V.LISTVAL_ID
  FROM VALL V
  WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 3299 AND V.IS_DEL = 0
  INTO :VAL;
  IF(VAL IN (14342, 14343)) THEN EXCEPTION DATA_ERROR 'Пакет документов уже был отправлен';
  SUSPEND;

  -- Файлы
  TAG_NAME = 'items::json&colon;array';
  VAL = 1;
  SUSPEND;
  N = 0;
  FOR
    SELECT L459.OBJ_ID, V3291.VAL, V3297.VAL, V3294.BLOB_ID, V3294.VAL, V3293.LISTVAL_ID, LV3293.TAG, V3296.LISTVAL_ID
    FROM LINKS L459
    LEFT JOIN VALS V3291 ON V3291.OBJ_ID = L459.OBJ_ID AND V3291.PARAM_ID = 3291 AND V3291.IS_DEL = 0
    LEFT JOIN VALS V3297 ON V3297.OBJ_ID = L459.OBJ_ID AND V3297.PARAM_ID = 3297 AND V3297.IS_DEL = 0
    LEFT JOIN VALB V3294 ON V3294.OBJ_ID = L459.OBJ_ID AND V3294.PARAM_ID = 3294 AND V3294.IS_DEL = 0
    LEFT JOIN VALL V3293 ON V3293.OBJ_ID = L459.OBJ_ID AND V3293.PARAM_ID = 3293 AND V3293.IS_DEL = 0
    LEFT JOIN VALL V3296 ON V3296.OBJ_ID = L459.OBJ_ID AND V3296.PARAM_ID = 3296 AND V3296.IS_DEL = 0
    LEFT JOIN LISTVALS LV3293 ON LV3293.LISTVAL_ID = V3293.LISTVAL_ID
    WHERE L459.PARENT_ID = :I$OBJ_ID AND L459.OBJ_TYPE_ID = 459 AND L459.DATE_DEL IS NULL
    INTO :V$OBJ_ID, :V$C1, :V$C2, :V$BLOB, :V$FNAME, :V$FT, :V$CRIT, :V$APPROVED
  DO
  BEGIN
    IF(V$APPROVED IN (14338, 14336)) THEN EXCEPTION DATA_ERROR 'По одному или более критериям не проставлено заверение от руководства организации';
    TAG_NAME = 'items:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'items:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'items:r:cr_id';
    VAL = V$C1;
    SUSPEND;
    TAG_NAME = 'items:r:file_id';
    VAL = V$C2;
    SUSPEND;
    TAG_NAME = 'items:r:blob_id';
    VAL = V$BLOB;
    SUSPEND;
    TAG_NAME = 'items:r:approve';
    VAL = V$APPROVED;
    SUSPEND;
    TAG_NAME = 'items:r:criteria';
    -- убираем символы до первой точки, где хранится форма аттестации
    VAL = SUBSTRING(V$CRIT FROM POSITION('.' IN V$CRIT) + 1);
    SUSPEND;
    TAG_NAME = 'items:r:filetype';
    VAL = V$FT;
    SUSPEND;
    TAG_NAME = 'items:r:filename';
    VAL = V$FNAME;
    SUSPEND;
    N = N + 1;
  END

  IF(N = 0) THEN EXCEPTION DATA_ERROR 'Нет ни одного файла в пакете';

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE ATT_REGISTER_ADD (
    I$OBJ_ID BIGINT,
    I$DATE DATE,
    I$STATE_ID SMALLINT,
    I$GROUP_ID BIGINT,
    I$SUBJECT_ID BIGINT,
    I$CONTROL_TYPE_ID BIGINT,
    I$STAGE_ID BIGINT,
    I$SUBSTAGE_ID SMALLINT,
    I$COMMENTS VARCHAR(1000),
    I$GROUP_NAME VARCHAR(1000),
    I$ROOM_ID BIGINT,
    I$TIME VARCHAR(100),
    I$USER_ID VARCHAR(40))
RETURNS (
    OBJ_ID BIGINT,
    ROLE_ID SMALLINT)
AS
DECLARE VARIABLE V$USER_PERSON_ID BIGINT;
DECLARE VARIABLE V$USER_ROLE SMALLINT;
DECLARE VARIABLE V$RO SMALLINT;
DECLARE VARIABLE V$YEAR_ID BIGINT;
DECLARE VARIABLE V$CY BIGINT;
DECLARE VARIABLE V$D1 DATE;
DECLARE VARIABLE V$GROUP_ID BIGINT;
DECLARE VARIABLE V$SUBJECT_ID BIGINT;
DECLARE VARIABLE V$STAGE_ID BIGINT;
DECLARE VARIABLE V$SUBSTAGE_ID SMALLINT;
DECLARE VARIABLE V$CJ_ID BIGINT;
DECLARE VARIABLE V$FT BIGINT;
DECLARE VARIABLE V$FINAL_ID BIGINT;
DECLARE VARIABLE V$MS BIGINT;
DECLARE VARIABLE V$ROOM_ID BIGINT;
DECLARE VARIABLE V$TIME VARCHAR(100);
begin

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;
  SELECT FIRST 1 U.OBJ_ID, U.USER_TYPE, LU.READ_ONLY
  FROM USERS U
  LEFT JOIN LUSERS LU ON LU.USER_ID = U.USER_ID AND LU.LEVEL_ID = 530 -- 258
  WHERE U.USER_ID = :I$USER_ID AND U.IS_BLOCKED = 0 AND U.DATE_DEL IS NULL AND (U.EXP_DATE IS NULL OR U.EXP_DATE > CURRENT_DATE)
  INTO :V$USER_PERSON_ID, :V$USER_ROLE, :V$RO;

  -- IF(V$RO IS NULL OR V$RO = 1 OR V$USER_ROLE IN (9, 12, 22)) THEN EXCEPTION DATA_ERROR 'У вас нет доступа для удаления ведомостей';

  SELECT FIRST 1 V1236.LISTVAL_ID, CAST(LV.TAG AS DATE)
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$CY, :V$D1;

  IF(I$DATE IS NULL) THEN EXCEPTION DATA_ERROR 'Должна быть заполнена дата аттестации';
  IF(I$DATE < V$D1 OR I$DATE >= DATEADD(1 YEAR TO V$D1)) THEN EXCEPTION DATA_ERROR 'Нельзя создавать или изменять ведомости за пределами текущего учебного года';
  IF(I$SUBJECT_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Должна быть указана дисциплина';
  IF(I$STAGE_ID IS NULL OR I$SUBSTAGE_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Должен быть указан этап обучения и семестр';
  IF(I$CONTROL_TYPE_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Должен быть указан вид аттестации';

  IF(I$OBJ_ID IS NULL) THEN
  BEGIN

    -- Нельзя добавлять сразу в статусе завершенного или отмененного
    IF(I$STATE_ID >= 2) THEN EXCEPTION DATA_ERROR 'Ведомость не может быть добавлена сразу в завершенном или отмененном статусе';

    INSERT INTO ATT_REGISTER
    (ATT_DATE, STATE_ID, YEAR_ID, GROUP_ID, SUBJECT_ID, CONTROL_TYPE_ID, STAGE_ID, SUBSTAGE_ID, USER_ID, COMMENTS, GROUP_NAME, ROOM_ID, TIME_VAL)
    VALUES (:I$DATE, :I$STATE_ID, :V$CY, :I$GROUP_ID, :I$SUBJECT_ID, :I$CONTROL_TYPE_ID, :I$STAGE_ID, :I$SUBSTAGE_ID, :I$USER_ID, :I$COMMENTS, :I$GROUP_NAME, :I$ROOM_ID, :I$TIME)
    RETURNING OBJ_ID INTO :OBJ_ID;

  END
  ELSE
  BEGIN
    SELECT FIRST 1 R.OBJ_ID, R.YEAR_ID, R.GROUP_ID, R.SUBJECT_ID, R.STAGE_ID, R.SUBSTAGE_ID, R.ROOM_ID, R.TIME_VAL
    FROM ATT_REGISTER R
    WHERE R.OBJ_ID = :I$OBJ_ID AND R.DATE_DEL IS NULL
    INTO :OBJ_ID, :V$YEAR_ID, :V$GROUP_ID, :V$SUBJECT_ID, :V$STAGE_ID, :V$SUBSTAGE_ID, :V$ROOM_ID, :V$TIME;

    IF(OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Ведомость не найдена или была удалена';
    IF(V$YEAR_ID <> V$CY) THEN EXCEPTION DATA_ERROR 'Нельзя изменять дату аттестации с изменением учебного периода';

    -- Нельзя менять данные, когда начали вводить оценки
    IF(I$SUBJECT_ID <> V$SUBJECT_ID OR I$STAGE_ID <> V$STAGE_ID OR I$SUBSTAGE_ID <> V$SUBSTAGE_ID OR COALESCE(I$GROUP_ID, 0) <> COALESCE(V$GROUP_ID, 0)
      OR COALESCE(I$ROOM_ID, 0) <> COALESCE(V$ROOM_ID, 0) OR COALESCE(I$TIME, '') <> COALESCE(V$TIME, '')) THEN
    BEGIN
      IF(EXISTS(
        SELECT FIRST 1 1
        FROM ATT_REGISTER_STDS S
        WHERE S.DATE_DEL IS NULL AND S.ATT_ID = :I$OBJ_ID AND S.MARK_ID IS NOT NULL
      ))
      THEN
        EXCEPTION DATA_ERROR 'Нельзя изменять этап, семестр или дисциплину, когда уже начато выставление отметок';
    END

    -- STATE тут не меняется !
    UPDATE ATT_REGISTER
    SET
      DATE_MODIFY = CURRENT_TIMESTAMP,
      ATT_DATE = :I$DATE,
      GROUP_ID = :I$GROUP_ID,
      SUBJECT_ID = :I$SUBJECT_ID,
      CONTROL_TYPE_ID = :I$CONTROL_TYPE_ID,
      STAGE_ID = :I$STAGE_ID,
      SUBSTAGE_ID = :I$SUBSTAGE_ID,
      COMMENTS = :I$COMMENTS,
      GROUP_NAME = :I$GROUP_NAME,
      ROOM_ID = :I$ROOM_ID,
      TIME_VAL = :I$TIME
    WHERE
      OBJ_ID = :OBJ_ID;
  END

  -- Если установлен статус 1 и аттестация стоит на конкретную группу, то создаем столбец для аттестации в журнале (если журнал есть)
  -- во всех подгруппах, куда входят ученики группы, только за указанный период обучения
  IF(I$STATE_ID = 1 AND I$GROUP_ID IS NOT NULL) THEN
  BEGIN

    IF(I$SUBSTAGE_ID = 1) THEN V$FT = 12973;
    IF(I$SUBSTAGE_ID = 2) THEN V$FT = 12974;

    FOR
      SELECT DISTINCT J.OBJ_ID, F.OBJ_ID
      FROM LINKS L10
      JOIN LINKS LPG ON LPG.OBJ_ID = L10.OBJ_ID AND LPG.PARENT_TYPE_ID IN (9, 256, 179) AND LPG.DATE_DEL IS NULL
      JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.GRADE_ID = LPG.PARENT_ID AND J.SUBJECT_ID = :I$SUBJECT_ID AND J.YEAR_ID = :V$CY AND J.STAGE_INDEX = :I$STAGE_ID
      LEFT JOIN CJ2_JOURNAL_FINALS F ON F.DATE_DEL IS NULL AND F.CJ_ID = J.OBJ_ID AND F.FINAL_TYPE = :V$FT
      WHERE L10.PARENT_ID = :I$GROUP_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL AND :V$FT IS NOT NULL
      INTO :V$CJ_ID, :V$FINAL_ID
    DO
    BEGIN
      IF(V$FINAL_ID IS NULL) THEN
      BEGIN
        IF(I$CONTROL_TYPE_ID = 5251) THEN V$MS = 100; -- зачет-незачет
        ELSE V$MS = 400; -- 5-балльная

        INSERT INTO CJ2_JOURNAL_FINALS
        (CJ_ID, FINAL_TYPE, FINAL_DATE, MARK_SYSTEM_ID)
        VALUES (:V$CJ_ID, :V$FT, :I$DATE, :V$MS);
      END
    END

  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE ATT_REGISTER_APPROVE (
    I$IDS VARCHAR(4000),
    I$USER_ID VARCHAR(40))
AS
DECLARE VARIABLE V$OBJ_ID BIGINT;
begin

  FOR
    SELECT L.ID
    FROM STR_TO_ID_LIST(:I$IDS) L
    JOIN ATT_REGISTER R ON R.DATE_DEL IS NULL AND R.OBJ_ID = L.ID AND R.STATE_ID = 0
    INTO :V$OBJ_ID
  DO
  BEGIN
    EXECUTE PROCEDURE ATT_REGISTER_STATE(:V$OBJ_ID, 1, :I$USER_ID);
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE ATT_REGISTER_DELETE (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
AS
DECLARE VARIABLE V$USER_PERSON_ID BIGINT;
DECLARE VARIABLE V$USER_ROLE SMALLINT;
DECLARE VARIABLE V$RO SMALLINT;
DECLARE VARIABLE V$YEAR_ID BIGINT;
DECLARE VARIABLE V$STATE_ID SMALLINT;
DECLARE VARIABLE V$CY BIGINT;
begin

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;
  SELECT FIRST 1 U.OBJ_ID, U.USER_TYPE, LU.READ_ONLY
  FROM USERS U
  LEFT JOIN LUSERS LU ON LU.USER_ID = U.USER_ID AND LU.LEVEL_ID = 530 -- 258
  WHERE U.USER_ID = :I$USER_ID AND U.IS_BLOCKED = 0 AND U.DATE_DEL IS NULL AND (U.EXP_DATE IS NULL OR U.EXP_DATE > CURRENT_DATE)
  INTO :V$USER_PERSON_ID, :V$USER_ROLE, :V$RO;

  IF(V$RO IS NULL OR V$RO = 1 OR V$USER_ROLE IN (9, 12, 22)) THEN EXCEPTION DATA_ERROR 'У вас нет доступа для удаления ведомостей';

  SELECT FIRST 1 R.YEAR_ID, R.STATE_ID
  FROM ATT_REGISTER R
  WHERE R.OBJ_ID = :I$OBJ_ID AND R.DATE_DEL IS NULL
  INTO :V$YEAR_ID, :V$STATE_ID;

  SELECT FIRST 1 V1236.LISTVAL_ID
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$CY;

  IF(V$YEAR_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Ведомость не найдена';
  IF(V$STATE_ID = 2) THEN EXCEPTION DATA_ERROR 'Нельзя удалить ведомость, работа с которой завершена';
  IF(V$YEAR_ID <> V$CY) THEN EXCEPTION DATA_ERROR 'Нельзя удалить ведомость закрытых учебных периодов';

  -- Нельзя удалять ведомость с отметками
  IF(EXISTS(
    SELECT FIRST 1 1
    FROM ATT_REGISTER_STDS S
    WHERE S.ATT_ID = :I$OBJ_ID AND S.DATE_DEL IS NULL AND S.MARK_ID IS NOT NULL
  ))
  THEN
    EXCEPTION DATA_ERROR 'Нельзя удалить ведомость при наличии выставленных оценок';

  UPDATE ATT_REGISTER
  SET DATE_DEL = CURRENT_TIMESTAMP
  WHERE OBJ_ID = :I$OBJ_ID;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE ATT_REGISTER_EXPLODE (
    I$OBJ_ID BIGINT,
    I$PREV_ID BIGINT,
    I$USER_ID VARCHAR(40))
AS
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$STATE_ID SMALLINT;
begin

  FOR
    SELECT S2.OBJ_ID, S2.STATE_ID
    FROM ATT_REGISTER_STDS S
    LEFT JOIN ATT_REGISTER_STDS S2 ON S2.DATE_DEL IS NULL AND S2.ATT_ID = :I$PREV_ID AND S2.PERSON_ID = S.PERSON_ID
    WHERE S.DATE_DEL IS NULL AND S.ATT_ID = :I$OBJ_ID
    ORDER BY 1
    INTO :V$OBJ_ID, :V$STATE_ID
  DO
  BEGIN
    IF(V$STATE_ID <> 0) THEN EXCEPTION DATA_ERROR 'Нельзя переносить обучающегося в новую ведомость, если он уже отмечен по старой';

    UPDATE ATT_REGISTER_STDS
    SET DATE_DEL = CURRENT_TIMESTAMP
    WHERE OBJ_ID = :V$OBJ_ID;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE ATT_REGISTER_GET (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$USER_PERSON_ID BIGINT;
DECLARE VARIABLE V$IS_TEACHER SMALLINT;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$ATT_DATE DATE;
DECLARE VARIABLE V$STATE_ID SMALLINT;
DECLARE VARIABLE V$YEAR_ID BIGINT;
DECLARE VARIABLE V$GROUP_ID BIGINT;
DECLARE VARIABLE V$SUBJECT_ID BIGINT;
DECLARE VARIABLE V$CONTROL_TYPE_ID BIGINT;
DECLARE VARIABLE V$STAGE_ID BIGINT;
DECLARE VARIABLE V$SUBSTAGE_ID SMALLINT;
DECLARE VARIABLE V$USER_ID BIGINT;
DECLARE VARIABLE V$COMMENTS VARCHAR(400);
DECLARE VARIABLE V$GROUP_NAME VARCHAR(400);
DECLARE VARIABLE V$LISTVAL_ID BIGINT;
DECLARE VARIABLE V$PERSON_ID BIGINT;
DECLARE VARIABLE V$MV_ID BIGINT;
DECLARE VARIABLE V$USER_ROLE SMALLINT;
DECLARE VARIABLE V$RO SMALLINT;
DECLARE VARIABLE V$OU_ID BIGINT;
DECLARE VARIABLE V$TYPE_ID BIGINT;
DECLARE VARIABLE V$GRADE_ID BIGINT;
DECLARE VARIABLE V$MARK_ID BIGINT;
DECLARE VARIABLE V$TEACHER_ID BIGINT;
DECLARE VARIABLE V$SN SMALLINT;
DECLARE VARIABLE S VARCHAR(400);
DECLARE VARIABLE V$ROOM_ID BIGINT;
DECLARE VARIABLE V$BUILDING_ID BIGINT;
DECLARE VARIABLE V$TIME VARCHAR(100);
begin

  SELECT R.OBJ_ID, R.ATT_DATE, R.STATE_ID, R.YEAR_ID, R.GROUP_ID, R.SUBJECT_ID, R.CONTROL_TYPE_ID, R.STAGE_ID, R.SUBSTAGE_ID, R.USER_ID, R.COMMENTS, R.GROUP_NAME,
    R.ROOM_ID, R.TIME_VAL
  FROM ATT_REGISTER R
  WHERE R.DATE_DEL IS NULL AND R.OBJ_ID = :I$OBJ_ID
  INTO :V$OBJ_ID, :V$ATT_DATE, :V$STATE_ID, :V$YEAR_ID, :V$GROUP_ID, :V$SUBJECT_ID, :V$CONTROL_TYPE_ID, :V$STAGE_ID, :V$SUBSTAGE_ID, :V$USER_ID, :V$COMMENTS, :V$GROUP_NAME,
    :V$ROOM_ID, :V$TIME;

  IF(V$OBJ_ID IS NULL AND I$OBJ_ID IS NOT NULL) THEN EXCEPTION DATA_ERROR 'Объект не найден или был удален';

  -- Данные по юзеру (у суперадмина записи в LUSERS тоже есть)
  -- если у юзера стоит уровень RO - он не может сам добавлять ведомости, но может ставить оценки будучи преподавателем
  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;
  SELECT FIRST 1 U.OBJ_ID, U.USER_TYPE, LU.READ_ONLY
  FROM USERS U
  LEFT JOIN LUSERS LU ON LU.USER_ID = U.USER_ID AND LU.LEVEL_ID = 530 -- 258
  WHERE U.USER_ID = :I$USER_ID AND U.IS_BLOCKED = 0 AND U.DATE_DEL IS NULL AND (U.EXP_DATE IS NULL OR U.EXP_DATE > CURRENT_DATE)
  INTO :V$USER_PERSON_ID, :V$USER_ROLE, :V$RO;

  IF(V$RO IS NULL) THEN EXCEPTION DATA_ERROR 'Пользователь не найден';

  TAG_NAME = 'id';
  VAL = V$OBJ_ID;
  SUSPEND;

  TAG_NAME = 'date';
  VAL = (SELECT VAL FROM DATE2ISO(:V$ATT_DATE, 0));
  SUSPEND;

  TAG_NAME = 'user_id';
  VAL = V$USER_ID;
  SUSPEND;

  TAG_NAME = 'user_name';
  VAL = NULL;
  SELECT FIRST 1 C.CAPTION
  FROM USERS U
  LEFT JOIN OBJECT_CAPTION_GET(U.OBJ_ID) C ON U.OBJ_ID IS NOT NULL
  WHERE U.USER_ID = :V$USER_ID
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'year_closed';
  VAL = 0;
  SELECT FIRST 1 1
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0 AND V1236.LISTVAL_ID <> :V$YEAR_ID
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'comments';
  VAL = V$COMMENTS;
  SUSPEND;

  TAG_NAME = 'group_id';
  VAL = V$GROUP_ID;
  SUSPEND;

  TAG_NAME = 'group_name';
  VAL = V$GROUP_NAME;
  SUSPEND;

  TAG_NAME = 'time';
  VAL = V$TIME;
  SUSPEND;

  TAG_NAME = 'state_id:values:value';
  VAL = V$STATE_ID;
  SUSPEND;
  TAG_NAME = 'state_id:selection::json&colon;array';
  VAL = 1;
  SUSPEND;
    TAG_NAME = 'state_id:selection:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'state_id:selection:r:id';
    VAL = 0;
    SUSPEND;
    TAG_NAME = 'state_id:selection:r:value';
    VAL = 'Проект';
    SUSPEND;
    TAG_NAME = 'state_id:selection:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'state_id:selection:r:id';
    VAL = 1;
    SUSPEND;
    TAG_NAME = 'state_id:selection:r:value';
    VAL = 'В процессе';
    SUSPEND;
    TAG_NAME = 'state_id:selection:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'state_id:selection:r:id';
    VAL = 2;
    SUSPEND;
    TAG_NAME = 'state_id:selection:r:value';
    VAL = 'Завершено';
    SUSPEND;
    TAG_NAME = 'state_id:selection:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'state_id:selection:r:id';
    VAL = 3;
    SUSPEND;
    TAG_NAME = 'state_id:selection:r:value';
    VAL = 'Отменено';
    SUSPEND;

  TAG_NAME = 'subject_id:values:value';
  VAL = V$SUBJECT_ID;
  SUSPEND;
  TAG_NAME = 'subject_id:selection::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L197.OBJ_ID, V1751.VAL, C.VAL
    FROM LINKS L197
    JOIN VALS V1751 ON V1751.OBJ_ID = L197.OBJ_ID AND V1751.PARAM_ID = 1751 AND V1751.IS_DEL = 0
    LEFT JOIN VALL V1750 ON V1750.OBJ_ID = L197.OBJ_ID AND V1750.PARAM_ID = 1750 AND V1750.IS_DEL = 0
    LEFT JOIN LISTVAL_TEXT(V1750.LISTVAL_ID) C ON V1750.LISTVAL_ID IS NOT NULL
    WHERE L197.PARENT_ID = 12313 AND L197.OBJ_TYPE_ID = 197 AND L197.DATE_DEL IS NULL
    ORDER BY 2, 3
    INTO :V$LISTVAL_ID, :V$COMMENTS, :S
  DO
  BEGIN
    TAG_NAME = 'subject_id:selection:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'subject_id:selection:r:id';
    VAL = V$LISTVAL_ID;
    SUSPEND;
    TAG_NAME = 'subject_id:selection:r:type';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'subject_id:selection:r:value';
    VAL = V$COMMENTS;
    SUSPEND;
  END

  TAG_NAME = 'control_type_id:values:value';
  VAL = V$CONTROL_TYPE_ID;
  SUSPEND;
  TAG_NAME = 'control_type_id:selection::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT LISTVAL_ID, VAL
    FROM LISTVALS_LIST(246)
    WHERE IS_DEL = 0
    INTO :V$LISTVAL_ID, :V$COMMENTS
  DO
  BEGIN
    TAG_NAME = 'control_type_id:selection:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'control_type_id:selection:r:id';
    VAL = V$LISTVAL_ID;
    SUSPEND;
    TAG_NAME = 'control_type_id:selection:r:value';
    VAL = V$COMMENTS;
    SUSPEND;
  END

  -- Учебный год чисто справочно
  TAG_NAME = 'year_id:values:value';
  VAL = V$YEAR_ID;
  SUSPEND;
  TAG_NAME = 'year_id:selection::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT LISTVAL_ID, VAL
    FROM LISTVALS_LIST(29)
    WHERE IS_DEL = 0
    INTO :V$LISTVAL_ID, :V$COMMENTS
  DO
  BEGIN
    TAG_NAME = 'year_id:selection:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'year_id:selection:r:id';
    VAL = V$LISTVAL_ID;
    SUSPEND;
    TAG_NAME = 'year_id:selection:r:value';
    VAL = V$COMMENTS;
    SUSPEND;
  END

  TAG_NAME = 'stage_id:values:value';
  VAL = V$STAGE_ID;
  SUSPEND;
  TAG_NAME = 'stage_id:selection::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT LISTVAL_ID, VAL
    FROM LISTVALS_LIST(25)
    WHERE IS_DEL = 0 AND PARENT_ID = 2142 AND LISTVAL_ID <> 13145
    INTO :V$LISTVAL_ID, :V$COMMENTS
  DO
  BEGIN
    TAG_NAME = 'stage_id:selection:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'stage_id:selection:r:id';
    VAL = V$LISTVAL_ID;
    SUSPEND;
    TAG_NAME = 'stage_id:selection:r:value';
    VAL = V$COMMENTS;
    SUSPEND;
  END

  TAG_NAME = 'substage_id:values:value';
  VAL = V$SUBSTAGE_ID;
  SUSPEND;
  TAG_NAME = 'substage_id:selection::json&colon;array';
  VAL = 1;
  SUSPEND;
    TAG_NAME = 'substage_id:selection:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'substage_id:selection:r:id';
    VAL = 1;
    SUSPEND;
    TAG_NAME = 'substage_id:selection:r:value';
    VAL = '1 семестр';
    SUSPEND;
    TAG_NAME = 'substage_id:selection:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'substage_id:selection:r:id';
    VAL = 2;
    SUSPEND;
    TAG_NAME = 'substage_id:selection:r:value';
    VAL = '2 семестр';
    SUSPEND;

  -- Проверяем права доступа одновременно с чтением списка преподавателей
  -- Доступ даем всем, у кого есть доступ RW к приложению итоговых отметок, либо кто прописан в качестве учителя в данной ведомости
  V$IS_TEACHER = 0;
  TAG_NAME = 'teachers::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT S.PERSON_ID, C.CAPTION
    FROM ATT_REGISTER_STUFF S
    LEFT JOIN OBJECT_CAPTION_GET(S.PERSON_ID) C ON 1 = 1
    WHERE S.DATE_DEL IS NULL AND S.ATT_ID = :I$OBJ_ID
    ORDER BY 1
    INTO :V$PERSON_ID, :V$COMMENTS
  DO
  BEGIN
    TAG_NAME = 'teachers:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'teachers:r:id';
    VAL = V$PERSON_ID;
    SUSPEND;
    TAG_NAME = 'teachers:r:name';
    VAL = V$COMMENTS;
    SUSPEND;
    IF(V$PERSON_ID = V$USER_PERSON_ID) THEN V$IS_TEACHER = 1;
  END

  -- Для добавления пользователь должен иметь права RW и иметь роль, отличную от Преподаватель
  -- Рядовой преподаватель даже с правами RW добавлять ведомости не может
  IF(I$OBJ_ID IS NULL AND (V$RO = 1 OR V$USER_ROLE IN (9, 12, 22))) THEN
    EXCEPTION DATA_ERROR 'У вас нет доступа для добавления ведомостей';

  -- Для открытия существующих ведомостей
  IF(I$OBJ_ID IS NOT NULL AND V$IS_TEACHER = 0 AND V$USER_ROLE IN (9, 12, 22)) THEN
    EXCEPTION DATA_ERROR 'У вас нет доступа к данной ведомости';

  TAG_NAME = 'user_role';
  VAL = V$USER_ROLE;
  SUSPEND;

  TAG_NAME = 'user_readonly';
  VAL = V$RO;
  SUSPEND;

  TAG_NAME = 'user_is_teacher';
  VAL = V$IS_TEACHER;
  SUSPEND;

  -- Участники
  TAG_NAME = 'students::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT S.PERSON_ID, S.STATE_ID, C.CAPTION, S.MARK_ID, M.MARKVAL_ID, M.MARK_TEACHER_ID, VM.VAL, MC.CAPTION, LPG.PARENT_ID, M.SEQ_INDEX
    FROM ATT_REGISTER_STDS S
    LEFT JOIN LINKS LPG ON LPG.OBJ_ID = S.PERSON_ID AND LPG.PARENT_TYPE_ID = 9 AND LPG.DATE_DEL IS NULL
    LEFT JOIN OBJECT_CAPTION_GET(S.PERSON_ID, 23) C ON 1 = 1
    LEFT JOIN VALM M ON M.MARK_ID = S.MARK_ID
    LEFT JOIN LISTVAL_TEXT(M.MARKVAL_ID) VM ON 1 = 1
    LEFT JOIN OBJECT_CAPTION_GET(M.MARK_TEACHER_ID) MC ON M.MARK_TEACHER_ID IS NOT NULL
    WHERE S.DATE_DEL IS NULL AND S.ATT_ID = :V$OBJ_ID
    ORDER BY 3
    INTO :V$PERSON_ID, :V$LISTVAL_ID, :V$COMMENTS, :V$MARK_ID, :V$MV_ID, :V$TEACHER_ID, :V$GROUP_NAME, :S, :V$GRADE_ID, :V$SN
  DO
  BEGIN
    TAG_NAME = 'students:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'students:r:id';
    VAL = V$PERSON_ID;
    SUSPEND;
    TAG_NAME = 'students:r:group_id';
    VAL = V$GRADE_ID;
    SUSPEND;
    TAG_NAME = 'students:r:name';
    VAL = V$COMMENTS;
    SUSPEND;
    TAG_NAME = 'students:r:seq';
    -- Если оценки еще нет - смотрим сколько было ведомостей до этого
    IF(V$SN IS NULL) THEN
    SELECT COUNT(*)
    FROM ATT_REGISTER_STDS S
    JOIN ATT_REGISTER R ON R.DATE_DEL IS NULL AND R.OBJ_ID = S.ATT_ID AND R.STATE_ID <> 3
      AND R.SUBJECT_ID = :V$SUBJECT_ID AND R.STATE_ID = :V$STAGE_ID AND R.SUBSTAGE_ID = :V$SUBSTAGE_ID
    WHERE S.DATE_DEL IS NULL AND (S.ATT_ID <> :V$OBJ_ID OR :V$OBJ_ID IS NULL) AND S.PERSON_ID = :V$PERSON_ID
    INTO :V$SN;
    VAL = V$SN;
    IF(VAL = '0') THEN VAL = ''; -- нет пересдач
    SUSPEND;
    TAG_NAME = 'students:r:state';
    VAL = V$LISTVAL_ID;
    SUSPEND;
    TAG_NAME = 'students:r:mark_id';
    VAL = V$MARK_ID;
    SUSPEND;
    TAG_NAME = 'students:r:markval_id';
    VAL = V$MV_ID;
    SUSPEND;
    TAG_NAME = 'students:r:markval';
    VAL = V$GROUP_NAME;
    SUSPEND;
    TAG_NAME = 'students:r:teacher_id';
    VAL = V$TEACHER_ID;
    SUSPEND;
    TAG_NAME = 'students:r:tname';
    VAL = S;
    SUSPEND;
  END

  -- Справочник отметок для контроля (в том числе пропуски)
  TAG_NAME = 'mark_types::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT MT.MARK_TYPE_ID, MT.PARENT_ID, MT.MARK_NAME
    FROM CJ2_MARK_TYPE MT
    WHERE MT.IS_DEL = 0
      -- кроме процентов, усвояемости, голосования
      AND MT.MARK_TYPE_ID NOT IN (-1, 0, 90, 99, 110, 200, 799)
      AND (MT.PARENT_ID IS NULL OR MT.PARENT_ID NOT IN (0, 110, 200, 799))
      -- и только те, которые могут быть итоговыми
      AND (MT.FINAL_ID IS NOT NULL OR MT.PARENT_ID IS NULL)
    ORDER BY 1
    INTO :V$LISTVAL_ID, :V$GROUP_ID, :S
  DO
  BEGIN
    TAG_NAME = 'mark_types:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'mark_types:r:id';
    VAL = V$LISTVAL_ID;
    SUSPEND;
    TAG_NAME = 'mark_types:r:parent_id';
    VAL = V$GROUP_ID;
    SUSPEND;
    TAG_NAME = 'mark_types:r:name';
    VAL = S;
    SUSPEND;
  END

  -- Список текущих групп для выбора при создании, а также для добавления учеников
  TAG_NAME = 'groups::json&colon;array';
  VAL = 1;
  SUSPEND;
  -- Корневой уровень - ОУ
  SELECT L2.OBJ_ID, C.CAPTION
  FROM LINKS L2
  LEFT JOIN OBJECT_CAPTION_GET(L2.OBJ_ID) C ON 1 = 1
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$OU_ID, :S;
  TAG_NAME = 'groups:r';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'groups:r:id';
  VAL = V$OU_ID;
  SUSPEND;
  TAG_NAME = 'groups:r:type';
  VAL = 2;
  SUSPEND;
  TAG_NAME = 'groups:r:name';
  VAL = S;
  SUSPEND;
  TAG_NAME = 'groups:r:items::json&colon;array';
  VAL = 1;
  SUSPEND;
  -- Второй уровень меню - уровни обучения
  FOR
    SELECT L7.OBJ_ID, L7.OBJ_TYPE_ID, C.CAPTION
    FROM LINKS L7
    LEFT JOIN OBJECT_CAPTION_GET(L7.OBJ_ID) C ON 1 = 1
    WHERE L7.PARENT_ID = :V$OU_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    AND EXISTS(
      SELECT FIRST 1 1
      FROM LINKS L8
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 187) AND L9.DATE_DEL IS NULL
      LEFT JOIN CJ2_GRADE_ACCESS(L9.OBJ_ID, :I$USER_ID) A ON 1 = 1
      WHERE L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL AND A.ACCESS_LEVEL > 0
    )
    ORDER BY C.SORT_ORDER, C.CAPTION
    INTO :V$OBJ_ID, :V$TYPE_ID, :S
  DO
  BEGIN
    TAG_NAME = 'groups:r:items:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'groups:r:items:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'groups:r:items:r:type';
    VAL = V$TYPE_ID;
    SUSPEND;
    TAG_NAME = 'groups:r:items:r:name';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'groups:r:items:r:items::json&colon;array';
    VAL = 1;
    SUSPEND;
    -- Третий уровень - параллели
    FOR
      SELECT L8.OBJ_ID, L8.OBJ_TYPE_ID, C.CAPTION
      FROM LINKS L8
      LEFT JOIN OBJECT_CAPTION_GET(L8.OBJ_ID) C ON 1 = 1
      WHERE L8.PARENT_ID = :V$OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
      AND EXISTS(
        SELECT FIRST 1 1
        FROM LINKS L9
        LEFT JOIN CJ2_GRADE_ACCESS(L9.OBJ_ID, :I$USER_ID) A ON 1 = 1
        WHERE L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 187) AND L8.DATE_DEL IS NULL AND A.ACCESS_LEVEL > 0
      )
      ORDER BY C.SORT_ORDER, C.CAPTION
      INTO :V$STAGE_ID, :V$TYPE_ID, :S
    DO
    BEGIN
      TAG_NAME = 'groups:r:items:r:items:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'groups:r:items:r:items:r:id';
      VAL = V$STAGE_ID;
      SUSPEND;
      TAG_NAME = 'groups:r:items:r:items:r:type';
      VAL = V$TYPE_ID;
      SUSPEND;
      TAG_NAME = 'groups:r:items:r:items:r:name';
      VAL = S;
      SUSPEND;
      TAG_NAME = 'groups:r:items:r:items:r:items::json&colon;array';
      VAL = 1;
      SUSPEND;
      FOR
        SELECT L9.OBJ_ID, L9.OBJ_TYPE_ID, C.CAPTION
        FROM LINKS L9
        LEFT JOIN CJ2_GRADE_ACCESS(L9.OBJ_ID, :I$USER_ID) A ON 1 = 1
        LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C ON 1 = 1
        WHERE L9.PARENT_ID = :V$STAGE_ID AND L9.OBJ_TYPE_ID IN (9, 187) AND L9.DATE_DEL IS NULL AND A.ACCESS_LEVEL > 0
        ORDER BY C.SORT_ORDER, C.CAPTION
        INTO :V$GRADE_ID, :V$TYPE_ID, :S
      DO
      BEGIN
        TAG_NAME = 'groups:r:items:r:items:r:items:r';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'groups:r:items:r:items:r:items:r:id';
        VAL = V$GRADE_ID;
        SUSPEND;
        TAG_NAME = 'groups:r:items:r:items:r:items:r:type';
        VAL = V$TYPE_ID;
        SUSPEND;
        TAG_NAME = 'groups:r:items:r:items:r:items:r:name';
        VAL = S;
        SUSPEND;
      END
    END
  END

  -- Место проведения
  TAG_NAME = 'room_id:values:value';
  VAL = V$ROOM_ID;
  SUSPEND;
  TAG_NAME = 'room_id:selection::json&colon;array';
  VAL = 1;
  SUSPEND;
    TAG_NAME = 'room_id:selection:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'room_id:selection:r:id';
    VAL = '*';
    SUSPEND;
    TAG_NAME = 'room_id:selection:r:value';
    VAL = 'Не указано';
    SUSPEND;
    TAG_NAME = 'room_id:selection:r:subset_id';
    VAL = '';
    SUSPEND;
  FOR
    SELECT L16.OBJ_ID, C.CAPTION
    FROM LINKS L73
    JOIN LINKS L16 ON L16.PARENT_ID = L73.OBJ_ID AND L16.OBJ_TYPE_ID = 16 AND L16.DATE_DEL IS NULL
    LEFT JOIN OBJECT_CAPTION_GET(L16.OBJ_ID) C ON 1 = 1
    WHERE L73.PARENT_ID = :V$OU_ID AND L73.OBJ_TYPE_ID = 73 AND L73.DATE_DEL IS NULL
    ORDER BY C.SORT_ORDER
    INTO :V$BUILDING_ID, :S
  DO
  BEGIN
    TAG_NAME = 'room_id:selection:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'room_id:selection:r:id';
    VAL = '*';
    SUSPEND;
    TAG_NAME = 'room_id:selection:r:value';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'room_id:selection:r:disabled';
    VAL = 'section';
    SUSPEND;

    FOR
      SELECT L61.OBJ_ID, C.CAPTION
      FROM LINKS L61
      JOIN VALL V525 ON V525.OBJ_ID = L61.OBJ_ID AND V525.PARAM_ID = 525 AND V525.IS_DEL = 0 AND V525.LISTVAL_ID IN (23, 12764)
      -- Номер и название помещения
      LEFT JOIN OBJECT_CAPTION_GET(L61.OBJ_ID) C ON 1 = 1
      WHERE L61.PARENT_ID = :V$BUILDING_ID AND L61.OBJ_TYPE_ID = 61 AND L61.DATE_DEL IS NULL
      ORDER BY 2
      INTO :V$ROOM_ID, :S
    DO
    BEGIN
      TAG_NAME = 'room_id:selection:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'room_id:selection:r:id';
      VAL = V$ROOM_ID;
      SUSPEND;
      TAG_NAME = 'room_id:selection:r:value';
      VAL = S;
      SUSPEND;
    END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE ATT_REGISTER_LATE (
    I$PERIOD_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$YEAR_ID BIGINT;
DECLARE VARIABLE V$DATE1 DATE;
DECLARE VARIABLE V$DATE2 DATE;
DECLARE VARIABLE V$GRADE_ID BIGINT;
DECLARE VARIABLE V$STAGE_ID BIGINT;
DECLARE VARIABLE V$SUBJECT_ID BIGINT;
DECLARE VARIABLE V$SUBSTAGE SMALLINT;
DECLARE VARIABLE V$STATE SMALLINT;
DECLARE VARIABLE V$CT BIGINT;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE S VARCHAR(1000);
DECLARE VARIABLE S2 VARCHAR(1000);
DECLARE VARIABLE S3 VARCHAR(400);
DECLARE VARIABLE N INTEGER;
begin

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  -- Период совпадает с текущим учебным годом ?
  -- По каждому году показываем данные за две сессии - зимнюю и летнюю
  SELECT FIRST 1 V1236.LISTVAL_ID
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  LEFT JOIN LISTVAL_TEXT(V1236.LISTVAL_ID) C ON 1 = 1
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$YEAR_ID;

  -- debug mode
  IF(I$PERIOD_ID IS NULL) THEN I$PERIOD_ID = V$YEAR_ID;

  TAG_NAME = 'year_name';
  SELECT FIRST 1 CAST(LV.TAG AS DATE), R.VAL
  FROM LISTVALS LV
  JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
  WHERE LV.LISTVAL_ID = :I$PERIOD_ID
  INTO :V$DATE1, :VAL;
  SUSPEND;

  V$DATE2 = '31.05.' || (EXTRACT(YEAR FROM V$DATE1) + 1);

  TAG_NAME = 'is_readonly';
  VAL = IIF(V$YEAR_ID = I$PERIOD_ID, 1, 0);

  -- Смотрим движение групп в период с начала учебного года и до мая
  TAG_NAME = 'groups::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT DISTINCT M.GROUP_ID, M.STAGE_ID, M.NAME_IN, C.VAL
    FROM PERSON_MOVEMENTS M
    LEFT JOIN LISTVAL_TEXT(M.STAGE_ID) C ON 1 = 1
    WHERE M.DATE_DEL IS NULL AND M.GROUP_TYPE_ID = 9 AND M.DATE_IN <= :V$DATE2 AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :V$DATE1) AND M.LEVEL_ID IN (29, 13131)
    ORDER BY 2, 3
    INTO :V$GRADE_ID, :V$STAGE_ID, :S, :S2
  DO
  BEGIN
    TAG_NAME = 'groups:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'groups:r:id';
    VAL = V$GRADE_ID;
    SUSPEND;
    TAG_NAME = 'groups:r:stage_id';
    VAL = V$STAGE_ID;
    SUSPEND;
    TAG_NAME = 'groups:r:stage_name';
    VAL = S2;
    SUSPEND;
    TAG_NAME = 'groups:r:name';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'groups:r:spc_name';
    VAL = NULL;
    SELECT FIRST 1 C.VAL
    FROM VALL V
    LEFT JOIN LISTVAL_TEXT(V.LISTVAL_ID) C ON 1 = 1
    WHERE V.OBJ_ID = :V$GRADE_ID AND V.PARAM_ID IN (2165, 2821, 3367) AND V.IS_DEL = 0
    INTO :VAL;
    IF(VAL IS NULL) THEN
    SELECT FIRST 1 C.VAL
    FROM VALR V
    JOIN VALL VV ON VV.OBJ_ID = V.VAL AND VV.PARAM_ID IN (3473, 3474, 3475) AND VV.IS_DEL = 0
    LEFT JOIN LISTVAL_TEXT(VV.LISTVAL_ID) C ON 1 = 1
    WHERE V.OBJ_ID = :V$GRADE_ID AND V.PARAM_ID = 3075 AND V.IS_DEL = 0
    INTO :VAL;
    SUSPEND;

    -- Список предметов аттестаций за этот курс, по семестрам
    TAG_NAME = 'groups:r:subjects::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT R.SUBJECT_ID, R.SUBSTAGE_ID, C.CAPTION, CI.STUFF_NAME, CI.STUFF_IDS, MAX(R.CONTROL_TYPE_ID), MAX(R.STATE_ID)
      FROM PERSON_MOVEMENTS M
      JOIN ATT_REGISTER_STDS S ON S.DATE_DEL IS NULL AND S.PERSON_ID = M.PERSON_ID
      JOIN ATT_REGISTER R ON R.DATE_DEL IS NULL AND R.OBJ_ID = S.ATT_ID AND R.YEAR_ID = :I$PERIOD_ID AND R.STAGE_ID = :V$STAGE_ID AND R.STATE_ID <> 3
      LEFT JOIN OBJECT_CAPTION_GET(R.SUBJECT_ID) C ON 1 = 1
      LEFT JOIN ATT_INFO_GET(R.OBJ_ID, R.STATE_ID) CI on 1 = 1
      WHERE M.DATE_DEL IS NULL AND M.GROUP_ID = :V$GRADE_ID AND M.DATE_IN <= :V$DATE2 AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :V$DATE1)
      GROUP BY 1, 2, 3, 4, 5
      ORDER BY 2, 3
      INTO :V$SUBJECT_ID, :V$SUBSTAGE, :S, :S2, :S3, :V$CT, :V$STATE
    DO
    BEGIN
      TAG_NAME = 'groups:r:subjects:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'groups:r:subjects:r:subject_id';
      VAL = V$SUBJECT_ID;
      SUSPEND;
      TAG_NAME = 'groups:r:subjects:r:substage';
      VAL = V$SUBSTAGE;
      SUSPEND;
      TAG_NAME = 'groups:r:subjects:r:subject_name';
      VAL = S;
      SUSPEND;
      TAG_NAME = 'groups:r:subjects:r:teachers_name';
      VAL = S2;
      SUSPEND;
      TAG_NAME = 'groups:r:subjects:r:teachers_ids';
      VAL = S3;
      SUSPEND;
      TAG_NAME = 'groups:r:subjects:r:control_type_id';
      VAL = V$CT;
      SUSPEND;
      TAG_NAME = 'groups:r:subjects:r:control_name';
      VAL = (SELECT VAL FROM LISTVAL_TEXT(:V$CT));
      SUSPEND;
      -- Поименный список неаттестованных
      -- Пока по упрощенной схеме, у кого вообще нет положительной оценки
      -- Надо учитывать только предметы, по которым первая волна уже прошла и ведомости закрыты
      TAG_NAME = 'groups:r:subjects:r:persons::json&colon;array';
      VAL = 1;
      SUSPEND;
      N = 0;
      FOR
        SELECT DISTINCT M.PERSON_ID, C.SCAPTION
        FROM PERSON_MOVEMENTS M
        LEFT JOIN OBJECT_CAPTION_GET(M.PERSON_ID, 23) C ON 1 = 1
        WHERE :V$STATE > 1 AND M.DATE_DEL IS NULL AND M.GROUP_ID = :V$GRADE_ID AND M.DATE_IN <= :V$DATE2 AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :V$DATE1) AND NOT EXISTS(
          SELECT FIRST 1 1
          FROM ATT_REGISTER_STDS S
          JOIN ATT_REGISTER R ON R.DATE_DEL IS NULL AND R.OBJ_ID = S.ATT_ID AND R.YEAR_ID = :I$PERIOD_ID AND R.STAGE_ID = :V$STAGE_ID
            AND R.STATE_ID <> 3 AND R.SUBJECT_ID = :V$SUBJECT_ID AND R.SUBSTAGE_ID = :V$SUBSTAGE
          JOIN VALM MM ON MM.IS_DEL = 0 AND MM.PUPIL_ID = M.PERSON_ID AND MM.MARKVAL_ID NOT IN (3014, 3015, 3020)
          WHERE S.DATE_DEL IS NULL AND S.PERSON_ID = M.PERSON_ID
        )
        ORDER BY 2
        INTO :V$OBJ_ID, :S
      DO
      BEGIN
        TAG_NAME = 'groups:r:subjects:r:persons:r';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'groups:r:subjects:r:persons:r:id';
        VAL = V$OBJ_ID;
        SUSPEND;
        TAG_NAME = 'groups:r:subjects:r:persons:r:name';
        VAL = S;
        SUSPEND;
        -- Проверяем, включен ли уже в открытую ведомость
        TAG_NAME = 'groups:r:subjects:r:persons:r:in_reg';
        VAL = 0;
        SELECT FIRST 1 1
        FROM ATT_REGISTER_STDS S
        JOIN ATT_REGISTER R ON R.DATE_DEL IS NULL AND R.OBJ_ID = S.ATT_ID AND R.YEAR_ID = :I$PERIOD_ID AND R.STAGE_ID = :V$STAGE_ID
          AND R.STATE_ID <> 3 AND R.SUBJECT_ID = :V$SUBJECT_ID AND R.SUBSTAGE_ID = :V$SUBSTAGE
        WHERE S.DATE_DEL IS NULL AND S.PERSON_ID = :V$OBJ_ID AND (S.STATE_ID <= 1 OR S.MARK_ID IS NULL)
        INTO :VAL;
        SUSPEND;
      END
      TAG_NAME = 'groups:r:subjects:r:n_lost';
      VAL = N;
      IF(V$STATE = 0) THEN VAL = NULL;
      SUSPEND;
    END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE ATT_REGISTER_MARK (
    I$OBJ_ID BIGINT,
    I$STUDENT_ID BIGINT,
    I$TEACHER_ID BIGINT,
    I$STATE SMALLINT,
    I$MARKVAL_ID BIGINT,
    I$USER_ID VARCHAR(40))
AS
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$YEAR_ID BIGINT;
DECLARE VARIABLE V$MARK_ID BIGINT;
DECLARE VARIABLE V$VAL_ID BIGINT;
DECLARE VARIABLE V$CJMARK_ID BIGINT;
DECLARE VARIABLE V$CJ_ID BIGINT;
DECLARE VARIABLE V$FINAL_ID BIGINT;
DECLARE VARIABLE V$SUBJECT_ID BIGINT;
DECLARE VARIABLE V$FINAL_TYPE BIGINT;
DECLARE VARIABLE V$STAGE_ID BIGINT;
DECLARE VARIABLE V$SUBSTAGE_ID SMALLINT;
DECLARE VARIABLE V$MARKVAL_ID BIGINT;
DECLARE VARIABLE V$PERIOD_FROM DATE;
DECLARE VARIABLE V$PERIOD_TO DATE;
DECLARE VARIABLE V$GRADE_ID BIGINT;
DECLARE VARIABLE V$IS_EXT SMALLINT;
DECLARE VARIABLE V$TEACHER_ID BIGINT;
DECLARE VARIABLE V$CT BIGINT;
DECLARE VARIABLE V$PREV_ID BIGINT;
DECLARE VARIABLE V$PP BIGINT;
DECLARE VARIABLE V$HOURS FLOAT;
DECLARE VARIABLE V$SEQ INTEGER;
begin

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  SELECT FIRST 1 R.YEAR_ID, R.SUBJECT_ID, R.STAGE_ID, R.SUBSTAGE_ID, S.OBJ_ID, S.MARK_ID, V.MARKVAL_ID, R.CONTROL_TYPE_ID
  FROM ATT_REGISTER_STDS S
  JOIN ATT_REGISTER R ON R.OBJ_ID = S.ATT_ID
  LEFT JOIN VALM V ON V.MARK_ID = S.MARK_ID
  WHERE S.DATE_DEL IS NULL AND S.ATT_ID = :I$OBJ_ID AND S.PERSON_ID = :I$STUDENT_ID
  INTO :V$YEAR_ID, :V$SUBJECT_ID, :V$STAGE_ID, :V$SUBSTAGE_ID, :V$OBJ_ID, :V$MARK_ID, :V$VAL_ID, :V$CT;

  IF(V$OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Обучающийся отсутствует в ведомости';

  IF(V$SUBSTAGE_ID = 1) THEN V$FINAL_TYPE = 12973; ELSE V$FINAL_TYPE = 12974;

  -- В каком журнале и контроле у нас ставится аттестация ?
  SELECT FIRST 1 J.OBJ_ID, F.OBJ_ID
  FROM PERSON_MOVEMENTS M
  JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.GRADE_ID = M.GROUP_ID AND J.SUBJECT_ID = :V$SUBJECT_ID
  LEFT JOIN CJ2_JOURNAL_FINALS F ON F.DATE_DEL IS NULL AND F.CJ_ID = J.OBJ_ID AND F.FINAL_TYPE = :V$FINAL_TYPE
  WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :I$STUDENT_ID AND M.DATE_OUT IS NULL
  INTO :V$CJ_ID, :V$FINAL_ID;

  IF(V$CJ_ID IS NOT NULL AND V$FINAL_ID IS NULL) THEN EXCEPTION DATA_ERROR 'В журнале занятий не внесена графа итоговой отметки';

  IF(V$FINAL_ID IS NOT NULL) THEN
  SELECT FIRST 1 M.MARK_ID
  FROM CJ2_MARK M
  WHERE M.DATE_DEL IS NULL AND M.FINAL_ID = :V$FINAL_TYPE AND M.STUDENT_ID = :I$STUDENT_ID
  INTO :V$CJMARK_ID;

  -- I$MARKVAL_ID = -1 если нужно отметку удалить, либо по справочнику CJ2_MARK_TYPES
  -- Если только удаляем, но оценки и так нет - просто ничего не делаем
  IF(V$MARK_ID IS NOT NULL) THEN
  BEGIN
    -- Нельзя удалять, если есть унаследованные оценки
    IF(EXISTS(SELECT FIRST 1 1 FROM VALM WHERE IS_DEL = 0 AND PREV_ID = :V$MARK_ID)) THEN
      EXCEPTION DATA_ERROR 'Нельзя удалять оценку, по которой была пересдача';

    IF(V$CJMARK_ID IS NOT NULL) THEN
    UPDATE CJ2_MARK
    SET DATE_DEL = CURRENT_TIMESTAMP
    WHERE MARK_ID = :V$CJMARK_ID;

    UPDATE VALM
    SET IS_DEL = 1
    WHERE MARK_ID = :V$MARK_ID;
  END

  -- Выставляем новую
  -- Удаление старой оценки происходит в случае указания STATE = NULL
  IF(I$STATE IS NOT NULL AND I$MARKVAL_ID > 0) THEN
  BEGIN
    -- Корректируем шкалу в LV221
    SELECT MT.FINAL_ID
    FROM CJ2_MARK_TYPE MT
    WHERE MT.MARK_TYPE_ID = :I$MARKVAL_ID AND MT.IS_DEL = 0
    INTO :V$MARKVAL_ID;

    IF(V$MARKVAL_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Данная отметка не может быть выставлена как итоговая';

    -- Восстанавливаем даты учебного периода, если получится
    -- !!!
    V$IS_EXT = 0;
    V$MARK_ID = NULL;

    SELECT FIRST 1 LP9.PARENT_ID
    FROM LINKS LP9
    WHERE LP9.OBJ_ID = :I$STUDENT_ID AND LP9.PARENT_TYPE_ID IN (9, 289) AND LP9.DATE_DEL IS NULL
    INTO :V$GRADE_ID;

    IF(V$GRADE_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Нельзя аттестовывать обучающихся, не числящимися в группах на момент аттестации';

    -- Если не явился или был удален - новую отметку не ставим
    IF(I$STATE <= 1) THEN
    BEGIN
      -- В журнале добавляем только если есть куда
      IF(V$FINAL_ID IS NOT NULL) THEN
      INSERT INTO CJ2_MARK
      (FINAL_ID, STUDENT_ID, MARK_TYPE_ID, IS_USED, USER_ID, MARK_DATE)
      VALUES (:V$FINAL_ID, :I$STUDENT_ID, :I$MARKVAL_ID, 1, :I$USER_ID, CURRENT_DATE);

      -- Сколько часов по УП ?
      SELECT FIRST 1 IIF(:V$SUBSTAGE_ID = 1, PL.LOAD_HOURS_S1, PL.LOAD_HOURS_S2)
      FROM LINKS LP256
      JOIN LINKS LP54 ON LP54.OBJ_ID = LP256.PARENT_ID AND LP54.PARENT_TYPE_ID = 54 AND LP54.DATE_DEL IS NULL
      JOIN LINKS LP400 ON LP400.OBJ_ID = LP54.PARENT_ID AND LP400.PARENT_TYPE_ID = 400 AND LP400.DATE_DEL IS NULL
      JOIN PLAN_SUBJECTS PS ON PS.DATE_DEL IS NULL AND PS.PLAN_ID = LP400.PARENT_ID AND PS.SUBJECT_ID = :V$SUBJECT_ID
      -- Выбираем тот этап обучения, за который выставляется оценка
      JOIN PLAN_LOADS PL ON PL.DATE_DEL IS NULL AND PL.SUBJECT_ID = PS.OBJ_ID
      JOIN LINKS L54 ON L54.OBJ_ID = PL.STAGE_ID AND L54.PARENT_ID = LP400.PARENT_ID AND L54.DATE_DEL IS NULL
      JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.LISTVAL_ID = :V$STAGE_ID
      WHERE LP256.OBJ_ID = :I$STUDENT_ID AND LP256.PARENT_TYPE_ID = 256 AND LP256.DATE_DEL IS NULL
      INTO :V$HOURS;

      -- Подсчитываем количество пересдач
      SELECT FIRST 1 M.MARK_ID, M.SEQ_INDEX
      FROM VALM M
      WHERE M.IS_DEL = 0 AND M.PUPIL_ID = :I$STUDENT_ID AND M.SUBJECT_ID = :V$SUBJECT_ID AND M.MARKTYPE_ID = :V$FINAL_TYPE
      INTO :V$PREV_ID, :V$SEQ;

      V$SEQ = COALESCE(V$SEQ, -1) + 1;

      INSERT INTO VALM (PUPIL_ID, SUBJECT_ID, TEACHER_ID, YEAR_ID, MARKTYPE_ID, MARKVAL_ID, STAGE_ID, IS_DEL,
        PERIOD_FROM, PERIOD_TO, GRADE_ID, MARK_DATE, IS_NATIVE, IS_EXT, MARK_TEACHER_ID, PLAN_HOURS, CONTROL_TYPE_ID, PREV_ID, SEQ_INDEX)
      VALUES (:I$STUDENT_ID, :V$SUBJECT_ID, :V$TEACHER_ID, :V$YEAR_ID, :V$FINAL_TYPE, :V$MARKVAL_ID, :V$STAGE_ID, 0,
        :V$PERIOD_FROM, :V$PERIOD_TO, :V$GRADE_ID, CURRENT_DATE, 1, :V$IS_EXT, :I$TEACHER_ID, :V$HOURS, :V$CT, :V$PREV_ID, :V$SEQ)
      RETURNING MARK_ID INTO :V$MARK_ID;
    END

    UPDATE ATT_REGISTER_STDS
    SET MARK_ID = :V$MARK_ID, STATE_ID = :I$STATE
    WHERE OBJ_ID = :V$OBJ_ID;
  END
  ELSE
  BEGIN
    -- Затираем ссылку на отметку в ведомости
    UPDATE ATT_REGISTER_STDS
    SET MARK_ID = NULL, STATE_ID = 0
    WHERE OBJ_ID = :V$OBJ_ID AND (MARK_ID IS NOT NULL OR STATE_ID <> 0);
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE ATT_REGISTER_MERGE (
    I$OBJ_ID BIGINT,
    I$SRC_ID BIGINT,
    I$USER_ID VARCHAR(40))
AS
DECLARE VARIABLE V$SRC_YEAR_ID BIGINT;
DECLARE VARIABLE V$SRC_STATE_ID SMALLINT;
DECLARE VARIABLE V$SRC_SUBJECT_ID BIGINT;
DECLARE VARIABLE V$SRC_STAGE_ID BIGINT;
DECLARE VARIABLE V$SRC_SUBSTAGE_ID BIGINT;
DECLARE VARIABLE V$SRC_CONTROL_TYPE_ID BIGINT;
DECLARE VARIABLE V$DST_YEAR_ID BIGINT;
DECLARE VARIABLE V$DST_STATE_ID SMALLINT;
DECLARE VARIABLE V$DST_SUBJECT_ID BIGINT;
DECLARE VARIABLE V$DST_STAGE_ID BIGINT;
DECLARE VARIABLE V$DST_SUBSTAGE_ID BIGINT;
DECLARE VARIABLE V$DST_CONTROL_TYPE_ID BIGINT;
DECLARE VARIABLE V$PERSON_ID BIGINT;
begin

  SELECT R.YEAR_ID, R.STATE_ID, R.SUBJECT_ID, R.STAGE_ID, R.SUBSTAGE_ID, R.CONTROL_TYPE_ID
  FROM ATT_REGISTER R
  WHERE R.OBJ_ID = :I$SRC_ID AND R.DATE_DEL IS NULL
  INTO :V$SRC_YEAR_ID, :V$SRC_STATE_ID, :V$SRC_SUBJECT_ID, :V$SRC_STAGE_ID, :V$SRC_SUBSTAGE_ID, :V$SRC_CONTROL_TYPE_ID;

  SELECT R.YEAR_ID, R.STATE_ID, R.SUBJECT_ID, R.STAGE_ID, R.SUBSTAGE_ID, R.CONTROL_TYPE_ID
  FROM ATT_REGISTER R
  WHERE R.OBJ_ID = :I$OBJ_ID AND R.DATE_DEL IS NULL
  INTO :V$DST_YEAR_ID, :V$DST_STATE_ID, :V$DST_SUBJECT_ID, :V$DST_STAGE_ID, :V$DST_SUBSTAGE_ID, :V$DST_CONTROL_TYPE_ID;

  IF(V$SRC_STATE_ID IS NULL OR V$DST_STATE_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Одна из ведомостей не найдена или была удалена';
  IF(V$SRC_STATE_ID NOT IN (0, 1) OR V$DST_STATE_ID NOT IN (0, 1)) THEN EXCEPTION DATA_ERROR 'Ведомости можно объединять только в статусе проекта или в процессе';
  IF(V$SRC_YEAR_ID <> V$DST_YEAR_ID OR V$SRC_STAGE_ID <> V$DST_STAGE_ID OR V$SRC_SUBJECT_ID <> V$DST_SUBJECT_ID
    OR V$SRC_CONTROL_TYPE_ID <> V$DST_CONTROL_TYPE_ID OR V$SRC_SUBSTAGE_ID <> V$DST_SUBSTAGE_ID)
  THEN
    EXCEPTION DATA_ERROR 'Должны совпадать предметы, этапы обучения и тип контроля';

  IF(EXISTS(
    SELECT FIRST 1 1
    FROM ATT_REGISTER_STDS S
    WHERE S.DATE_DEL IS NULL AND S.ATT_ID = :I$SRC_ID AND S.STATE_ID <> 0
  ))
  THEN
    EXCEPTION DATA_ERROR 'По ведомости уже начато выставление оценок';

  FOR
    SELECT S.PERSON_ID
    FROM ATT_REGISTER_STDS S
    LEFT JOIN ATT_REGISTER_STDS S2 ON S2.DATE_DEL IS NULL AND S2.ATT_ID = :I$OBJ_ID AND S2.PERSON_ID = S.PERSON_ID
    WHERE S.DATE_DEL IS NULL AND S.ATT_ID = :I$SRC_ID AND S2.OBJ_ID IS NULL
    ORDER BY 1
    INTO :V$PERSON_ID
  DO
  BEGIN
    INSERT INTO ATT_REGISTER_STDS
    (ATT_ID, PERSON_ID)
    VALUES (:I$OBJ_ID, :V$PERSON_ID);
  END

  -- Удаляем старую ведомость
  UPDATE ATT_REGISTER
  SET DATE_DEL = CURRENT_TIMESTAMP
  WHERE OBJ_ID = :I$SRC_ID;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE ATT_REGISTER_REJECT (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    COMMENTS VARCHAR(1000))
AS
DECLARE VARIABLE V$OBJ_ID BIGINT;
begin

  FOR
    SELECT S.OBJ_ID
    FROM ATT_REGISTER_STDS S
    JOIN ATT_REGISTER R ON R.DATE_DEL IS NULL AND R.OBJ_ID = S.ATT_ID AND R.STATE_ID IN (0, 1)
    WHERE S.DATE_DEL IS NULL AND S.PERSON_ID = :I$OBJ_ID AND S.STATE_ID = 0
    ORDER BY 1
    INTO :V$OBJ_ID
  DO
  BEGIN
    UPDATE ATT_REGISTER_STDS
    SET DATE_DEL = CURRENT_TIMESTAMP
    WHERE OBJ_ID = :V$OBJ_ID;

    -- COMMENTS
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE ATT_REGISTER_SCHEDULE (
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$D1 DATE;
DECLARE VARIABLE V$D2 DATE;
DECLARE VARIABLE V$STAGE BIGINT;
DECLARE VARIABLE V$TYPE_ID BIGINT;
begin

  TAG_NAME = 'schedule::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT V3426.LISTVAL_ID, V3396.VAL, V3397.VAL, V3603.LISTVAL_ID
    FROM LINKS L2
    JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
    JOIN LINKS L481 ON L481.PARENT_ID = L2.OBJ_ID AND L481.OBJ_TYPE_ID = 481 AND L481.DATE_DEL IS NULL
    JOIN VALL V3389 ON V3389.OBJ_ID = L481.OBJ_ID AND V3389.PARAM_ID = 3389 AND V3389.IS_DEL = 0 AND V3389.LISTVAL_ID = V1236.LISTVAL_ID
    JOIN VALL V3390 ON V3390.OBJ_ID = L481.OBJ_ID AND V3390.PARAM_ID = 3390 AND V3390.IS_DEL = 0 AND V3390.LISTVAL_ID = 11715
    JOIN LINKS L151 ON L151.PARENT_ID = L481.OBJ_ID AND L151.OBJ_TYPE_ID = 151 AND L151.DATE_DEL IS NULL
    JOIN LINKS L487 ON L487.PARENT_ID = L151.OBJ_ID AND L487.OBJ_TYPE_ID = 487 AND L487.DATE_DEL IS NULL
    JOIN VALD V3396 ON V3396.OBJ_ID = L487.OBJ_ID AND V3396.PARAM_ID = 3396 AND V3396.IS_DEL = 0
    JOIN VALD V3397 ON V3397.OBJ_ID = L487.OBJ_ID AND V3397.PARAM_ID = 3397 AND V3397.IS_DEL = 0
    JOIN VALL V3426 ON V3426.OBJ_ID = L487.OBJ_ID AND V3426.PARAM_ID = 3426 AND V3426.IS_DEL = 0
    LEFT JOIN VALL V3603 ON V3603.OBJ_ID = L487.OBJ_ID AND V3603.PARAM_ID = 3603 AND V3603.IS_DEL = 0
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    ORDER BY 1, 2
    INTO :V$STAGE, :V$D1, :V$D2, :V$TYPE_ID
  DO
  BEGIN
    TAG_NAME = 'schedule:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'schedule:r:substage_id';
    VAL = IIF(V$STAGE = 19, 0, 1);
    SUSPEND;
    TAG_NAME = 'schedule:r:date_from';
    VAL = (SELECT VAL FROM DATE2ISO(:V$D1, 0));
    SUSPEND;
    TAG_NAME = 'schedule:r:date_to';
    VAL = (SELECT VAL FROM DATE2ISO(:V$D2, 0));
    SUSPEND;
    TAG_NAME = 'schedule:r:type_id';
    VAL = V$TYPE_ID;
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE ATT_REGISTER_SILENT (
    I$GROUP_ID BIGINT,
    I$STAGE_ID BIGINT,
    I$SUBJECT_ID BIGINT,
    I$CONTROL_TYPE_ID BIGINT,
    I$SUBSTAGE_ID BIGINT,
    I$DATE DATE,
    I$PERIOD_TYPE BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    OBJ_ID BIGINT,
    SUBJECT_NAME VARCHAR(1000),
    SUBJECT_CODE VARCHAR(100),
    YEAR_ID BIGINT)
AS
DECLARE VARIABLE V$USER_PERSON_ID BIGINT;
DECLARE VARIABLE V$USER_ROLE INTEGER;
DECLARE VARIABLE V$RO SMALLINT;
DECLARE VARIABLE V$D1 DATE;
DECLARE VARIABLE V$GROUP_NAME VARCHAR(1000);
DECLARE VARIABLE V$TEACHER_ID BIGINT;
DECLARE VARIABLE V$STUDENT_ID BIGINT;
DECLARE VARIABLE V$MT INTEGER;
DECLARE VARIABLE NEW_VAR BIGINT;
begin

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;
  SELECT FIRST 1 U.OBJ_ID, U.USER_TYPE, LU.READ_ONLY
  FROM USERS U
  LEFT JOIN LUSERS LU ON LU.USER_ID = U.USER_ID AND LU.LEVEL_ID = 530 -- 258
  WHERE U.USER_ID = :I$USER_ID AND U.IS_BLOCKED = 0 AND U.DATE_DEL IS NULL AND (U.EXP_DATE IS NULL OR U.EXP_DATE > CURRENT_DATE)
  INTO :V$USER_PERSON_ID, :V$USER_ROLE, :V$RO;

  -- IF(V$RO IS NULL OR V$RO = 1 OR V$USER_ROLE IN (9, 12, 22)) THEN EXCEPTION DATA_ERROR 'У вас нет доступа для удаления ведомостей';

  SELECT FIRST 1 V1236.LISTVAL_ID, CAST(LV.TAG AS DATE)
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :YEAR_ID, :V$D1;

  IF(I$DATE IS NULL) THEN EXCEPTION DATA_ERROR 'Должна быть заполнена дата аттестации';
  IF(I$DATE < V$D1 OR I$DATE >= DATEADD(1 YEAR TO V$D1)) THEN EXCEPTION DATA_ERROR 'Нельзя создавать или изменять ведомости за пределами текущего учебного года';
  IF(I$SUBJECT_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Должна быть указана дисциплина';
  IF(I$STAGE_ID IS NULL OR I$SUBSTAGE_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Должен быть указан этап обучения и семестр';
  IF(I$CONTROL_TYPE_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Должен быть указан вид аттестации';
  IF(I$GROUP_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Должна быть указана группа';

  -- Не даем добавлять в тихом режиме пересечения по датам
  -- ??? уточнить, может ли быть зачет и экзамен сразу
  IF(EXISTS(
    SELECT FIRST 1 1
    FROM ATT_REGISTER A
    WHERE A.DATE_DEL IS NULL AND A.GROUP_ID = :I$GROUP_ID AND A.ATT_DATE = :I$DATE
  ))
  THEN
    EXCEPTION DATA_ERROR 'Нельзя назначать на одну дату аттестацию по той же группе в бесшумном режиме';

  -- В дополнительную сессию можно только если есть неаттестованные
  V$MT = IIF(I$SUBSTAGE_ID = 2, 12974, 12973);
  IF(I$PERIOD_TYPE = 23830) THEN
  BEGIN
    IF(NOT EXISTS(
      SELECT FIRST 1 1
      FROM PERSON_MOVEMENTS M
      LEFT JOIN VALM MM ON MM.IS_DEL = 0 AND MM.SUBJECT_ID = :I$SUBJECT_ID AND MM.STAGE_ID = :I$STAGE_ID AND MM.PUPIL_ID = M.PERSON_ID AND MM.MARKTYPE_ID = :V$MT
      WHERE M.DATE_DEL IS NULL AND M.GROUP_ID = :I$GROUP_ID AND M.DATE_OUT IS NULL
        AND (MM.MARK_ID IS NULL OR MM.MARKVAL_ID IN (3014, 3015, 3020, 3022, 3033))
    ))
    THEN
      EXCEPTION DATA_ERROR 'Нет неаттестованных обучающихся в группе. Для передачи на повышение оценки создайте ведомость вручную';
  END

  SELECT CAPTION
  FROM OBJECT_CAPTION_GET(:I$GROUP_ID)
  INTO :V$GROUP_NAME;

  INSERT INTO ATT_REGISTER
  (ATT_DATE, STATE_ID, YEAR_ID, GROUP_ID, SUBJECT_ID, CONTROL_TYPE_ID, STAGE_ID, SUBSTAGE_ID, USER_ID, COMMENTS, GROUP_NAME)
  VALUES (:I$DATE, 0, :YEAR_ID, :I$GROUP_ID, :I$SUBJECT_ID, :I$CONTROL_TYPE_ID, :I$STAGE_ID, :I$SUBSTAGE_ID, :I$USER_ID, NULL, :V$GROUP_NAME)
  RETURNING OBJ_ID INTO :OBJ_ID;

  -- Преподаватель. Несколько ?
  SELECT FIRST 1 J.TEACHER_ID
  FROM CJ2_JOURNAL J
  WHERE J.DATE_DEL IS NULL AND J.GRADE_ID = :I$GROUP_ID AND J.SUBJECT_ID = :I$SUBJECT_ID
  INTO :V$TEACHER_ID;

  IF(V$TEACHER_ID IS NULL) THEN
  BEGIN
    SELECT FIRST 1 J.TEACHER_ID
    FROM LINKS L10
    JOIN LINKS LP179 ON LP179.OBJ_ID = L10.OBJ_ID AND LP179.PARENT_TYPE_ID = 179 AND LP179.DATE_DEL IS NULL
    JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.GRADE_ID = LP179.PARENT_ID AND J.SUBJECT_ID = :I$SUBJECT_ID
    WHERE L10.PARENT_ID = :I$GROUP_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    INTO :V$TEACHER_ID;
  END

  IF(V$TEACHER_ID IS NOT NULL) THEN
  BEGIN
    INSERT INTO ATT_REGISTER_STUFF
    (ATT_ID, PERSON_ID)
    VALUES (:OBJ_ID, :V$TEACHER_ID);
  END

  -- Обучающиеся
  FOR
    SELECT M.PERSON_ID
    FROM PERSON_MOVEMENTS M
    WHERE M.DATE_DEL IS NULL AND M.GROUP_ID = :I$GROUP_ID AND M.DATE_OUT IS NULL
    INTO :V$STUDENT_ID
  DO
  BEGIN
    IF(I$PERIOD_TYPE <> 23830 OR NOT EXISTS(
      SELECT FIRST 1 1
      FROM VALM MM
      WHERE MM.IS_DEL = 0 AND MM.SUBJECT_ID = :I$SUBJECT_ID AND MM.STAGE_ID = :I$STAGE_ID AND MM.PUPIL_ID = :V$STUDENT_ID AND MM.MARKTYPE_ID = :V$MT
        AND MM.MARKVAL_ID NOT IN (3014, 3015, 3020, 3022, 3033)
    )) THEN
    BEGIN
      INSERT INTO ATT_REGISTER_STDS
      (ATT_ID, PERSON_ID)
      VALUES (:OBJ_ID, :V$STUDENT_ID);
    END
  END

  SELECT V.VAL
  FROM VALS V
  WHERE V.OBJ_ID = :I$SUBJECT_ID AND V.PARAM_ID = 1751
  INTO :SUBJECT_NAME;

  SELECT V.VAL
  FROM VALS V
  WHERE V.OBJ_ID = :I$SUBJECT_ID AND V.PARAM_ID = 1752
  INTO :SUBJECT_CODE;

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE ATT_REGISTER_STATE (
    I$OBJ_ID BIGINT,
    I$STATE_ID SMALLINT,
    I$USER_ID VARCHAR(40))
AS
declare variable V$STATE_ID smallint;
begin

  SELECT FIRST 1 R.STATE_ID
  FROM ATT_REGISTER R
  WHERE R.OBJ_ID = :I$OBJ_ID AND R.DATE_DEL IS NULL
  INTO :V$STATE_ID;

  -- Нельзя завершить, пока все оценки не выставлены
  IF(I$STATE_ID = 2 AND EXISTS(
    SELECT FIRST 1 1
    FROM ATT_REGISTER_STDS S
    WHERE S.DATE_DEL IS NULL AND S.ATT_ID = :I$OBJ_ID AND S.MARK_ID IS NULL
  ))
  THEN
    EXCEPTION DATA_ERROR 'Нельзя завершить ведомость, если не все оценки выставлены';

  -- Если нет студентов
  IF(I$STATE_ID IN (1, 2) AND NOT EXISTS(
    SELECT FIRST 1 1
    FROM ATT_REGISTER_STDS S
    WHERE S.DATE_DEL IS NULL AND S.ATT_ID = :I$OBJ_ID
  ))
  THEN
    EXCEPTION DATA_ERROR 'Нельзя завершить или начать аттестацию по ведомости, если в ней нет ни одного обучающегося';

  -- Нельзя аннулировать или вернуть в проект
  IF(I$STATE_ID IN (0, 3) AND EXISTS(
    SELECT FIRST 1 1
    FROM ATT_REGISTER_STDS S
    WHERE S.DATE_DEL IS NULL AND S.ATT_ID = :I$OBJ_ID AND S.MARK_ID IS NOT NULL
  ))
  THEN
    EXCEPTION DATA_ERROR 'Нельзя сделать проектом или аннулировать ведомость, если есть выставленные отметки';

  UPDATE ATT_REGISTER
  SET DATE_MODIFY = CURRENT_TIMESTAMP, STATE_ID = :I$STATE_ID
  WHERE OBJ_ID = :I$OBJ_ID AND STATE_ID <> :I$STATE_ID;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE ATT_REGISTER_STUDENTS (
    I$OBJ_ID BIGINT,
    I$STUDENTS VARCHAR(4000),
    I$USER_ID VARCHAR(40))
AS
DECLARE VARIABLE V$STUDENT_ID BIGINT;
DECLARE VARIABLE V$MARK_ID BIGINT;
begin

  -- Добавленные
  FOR
    SELECT DISTINCT L.ID
    FROM STR_TO_ID_LIST(:I$STUDENTS) L
    LEFT JOIN ATT_REGISTER_STDS S ON S.ATT_ID = :I$OBJ_ID AND S.PERSON_ID = L.ID AND S.DATE_DEL IS NULL
    WHERE S.OBJ_ID IS NULL
    INTO :V$STUDENT_ID
  DO
  BEGIN
    INSERT INTO ATT_REGISTER_STDS
    (ATT_ID, PERSON_ID)
    VALUES (:I$OBJ_ID, :V$STUDENT_ID);
  END

  -- Удаление, только если не стоит оценка
  FOR
    SELECT S.OBJ_ID, S.MARK_ID
    FROM ATT_REGISTER_STDS S
    WHERE S.DATE_DEL IS NULL AND S.ATT_ID = :I$OBJ_ID AND
      NOT EXISTS(SELECT FIRST 1 1 FROM STR_TO_ID_LIST(:I$STUDENTS) L WHERE L.ID = S.PERSON_ID)
    ORDER BY 1
    INTO :V$STUDENT_ID, :V$MARK_ID
  DO
  BEGIN
    IF(V$MARK_ID IS NOT NULL) THEN EXCEPTION DATA_ERROR 'Нельзя удалять из ведомости обучающегося с уже выставленной отметкой';

    UPDATE ATT_REGISTER_STDS
    SET DATE_DEL = CURRENT_TIMESTAMP
    WHERE OBJ_ID = :V$STUDENT_ID;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE ATT_REGISTER_TEACHERS (
    I$OBJ_ID BIGINT,
    I$TEACHERS VARCHAR(1000),
    I$USER_ID VARCHAR(40))
AS
DECLARE VARIABLE V$TEACHER_ID BIGINT;
begin

  -- Добавленные
  FOR
    SELECT DISTINCT L.ID
    FROM STR_TO_ID_LIST(:I$TEACHERS) L
    LEFT JOIN ATT_REGISTER_STUFF S ON S.ATT_ID = :I$OBJ_ID AND S.PERSON_ID = L.ID AND S.DATE_DEL IS NULL
    WHERE S.OBJ_ID IS NULL
    INTO :V$TEACHER_ID
  DO
  BEGIN
    INSERT INTO ATT_REGISTER_STUFF
    (ATT_ID, PERSON_ID)
    VALUES (:I$OBJ_ID, :V$TEACHER_ID);
  END

  -- Удаление
  FOR
    SELECT S.OBJ_ID
    FROM ATT_REGISTER_STUFF S
    WHERE S.DATE_DEL IS NULL AND S.ATT_ID = :I$OBJ_ID AND
      NOT EXISTS(SELECT FIRST 1 1 FROM STR_TO_ID_LIST(:I$TEACHERS) L WHERE L.ID = S.PERSON_ID)
    ORDER BY 1
    INTO :V$TEACHER_ID
  DO
  BEGIN
    -- Проверить, что данный учитель не выставлял отметки
    IF(EXISTS(
      SELECT FIRST 1 1
      FROM ATT_REGISTER_STDS D
      JOIN VALM M ON M.MARK_ID = D.MARK_ID AND M.IS_DEL = 0 AND M.MARK_TEACHER_ID = :V$TEACHER_ID
      WHERE D.DATE_DEL IS NULL AND D.ATT_ID = :I$OBJ_ID
    ))
    THEN
      EXCEPTION DATA_ERROR 'Нельзя удалить преподавателя (' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$TEACHER_ID)) || '), который выставил оценки';

    UPDATE ATT_REGISTER_STUFF
    SET DATE_DEL = CURRENT_TIMESTAMP
    WHERE OBJ_ID = :V$TEACHER_ID;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE ATT_REG_MARK_GET (
    I$REG_ID BIGINT,
    I$STUDENT_ID BIGINT,
    I$SUBJECT_ID BIGINT,
    I$STAGE_ID BIGINT,
    I$SUBSTAGE_ID SMALLINT,
    I$CONTROL_TYPE_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$STATE_ID SMALLINT;
DECLARE VARIABLE V$MARK_ID BIGINT;
DECLARE VARIABLE V$FINAL_ID BIGINT;
DECLARE VARIABLE V$YEAR_ID BIGINT;
DECLARE VARIABLE V$CY_ID BIGINT;
DECLARE VARIABLE V$MARK_TYPE_ID BIGINT;
DECLARE VARIABLE V$TEACHER_ID BIGINT;
DECLARE VARIABLE V$CJ_ID BIGINT;
DECLARE VARIABLE V$MARKVAL_ID BIGINT;
DECLARE VARIABLE V$CT BIGINT;
begin

  -- Если запись уже есть - возвращаем информацию по ней
  IF(I$REG_ID IS NOT NULL) THEN
  BEGIN
    SELECT FIRST 1 S.OBJ_ID, S.STATE_ID, S.MARK_ID
    FROM ATT_REGISTER_STDS S
    WHERE S.DATE_DEL IS NULL AND S.ATT_ID = :I$REG_ID AND S.PERSON_ID = :I$STUDENT_ID
    INTO :V$OBJ_ID, :V$STATE_ID, :V$MARK_ID;

    SELECT FIRST 1 R.YEAR_ID, R.CONTROL_TYPE_ID
    FROM ATT_REGISTER R
    WHERE R.DATE_DEL IS NULL AND R.OBJ_ID = :I$REG_ID
    INTO :V$YEAR_ID, :V$CT;

    IF(V$YEAR_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не найдена аттестационная ведомость';
  END

  SELECT FIRST 1 V1236.LISTVAL_ID
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$CY_ID;

  IF(V$YEAR_ID IS NULL) THEN V$YEAR_ID = V$CY_ID;

  IF(V$YEAR_ID = V$CY_ID) THEN
  BEGIN
    -- Ищем столбец итоговой отметки, пытаемся получить шкалу оценивания
    SELECT FIRST 1 J.OBJ_ID, F.OBJ_ID, F.MARK_SYSTEM_ID
    FROM LINKS LPG
    JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.YEAR_ID = :V$CY_ID AND J.GRADE_ID = LPG.PARENT_ID AND J.SUBJECT_ID = :I$SUBJECT_ID
    JOIN CJ2_JOURNAL_FINALS F ON F.DATE_DEL IS NULL AND F.CJ_ID = J.OBJ_ID AND F.FINAL_TYPE = IIF(:I$SUBSTAGE_ID = 1, 12973, 12974)
    WHERE LPG.OBJ_ID = :I$STUDENT_ID AND LPG.PARENT_TYPE_ID IN (9, 256, 179) AND LPG.DATE_DEL IS NULL
    INTO :V$CJ_ID, :V$FINAL_ID, :V$MARK_TYPE_ID;

    IF(V$CJ_ID IS NOT NULL AND V$FINAL_ID IS NULL) THEN EXCEPTION DATA_ERROR 'В журнале не внесен столбец для выставления итоговых отметок';
  END   
  ELSE
  BEGIN
    -- Прошлые учебные годы
    IF(V$OBJ_ID IS NULL OR V$MARK_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Для закрытых учебных периодов могут быть только существующие записи данных';

    /*SELECT FIRST 1
    FROM VALM V
    INTO :V$MARK_TYPE_ID;*/
  END

  -- Если столбец со шкалой еще не создан, корректируем если указан тип Зачет
  IF(V$MARK_TYPE_ID IS NULL) THEN
  BEGIN
    IF(V$CT = 5251) THEN V$MARK_TYPE_ID = 100;
  END

  IF(V$MARK_ID IS NOT NULL) THEN
  BEGIN
    SELECT FIRST 1 M.MARK_TEACHER_ID, M.MARKVAL_ID
    FROM VALM M
    WHERE M.MARK_ID = :V$MARK_ID
    INTO :V$TEACHER_ID, :V$MARKVAL_ID;
  END

  TAG_NAME = 'mark_id';
  VAL = V$MARK_ID;
  SUSPEND;

  TAG_NAME = 'mark_type_id';
  VAL = V$MARK_TYPE_ID;
  SUSPEND;

  TAG_NAME = 'markval_id';
  VAL = V$MARKVAL_ID;
  SUSPEND;

  TAG_NAME = 'state_id';
  VAL = COALESCE(V$STATE_ID, 0);
  SUSPEND;

  TAG_NAME = 'teacher_id';
  VAL = V$TEACHER_ID;
  SUSPEND;

  TAG_NAME = 'teacher_name';
  IF(V$TEACHER_ID IS NULL) THEN VAL = NULL;
  ELSE VAL = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$TEACHER_ID));
  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE ATT_REG_STUDENTS_LIST (
    I$OBJ_ID BIGINT,
    I$SUBJECT_ID BIGINT,
    I$STAGE_ID BIGINT,
    I$SUBSTAGE_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$SRC_TYPE BIGINT;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$TYPE_ID BIGINT;
DECLARE VARIABLE S1 VARCHAR(400);
begin

  IF((SELECT ACCESS_LEVEL FROM CJ2_GRADE_ACCESS(:I$OBJ_ID, :I$USER_ID)) = 0) THEN EXCEPTION DATA_ERROR 'Нет доступа к данному учебному коллективу';

  SELECT TYPE_ID
  FROM OBJECTS
  WHERE OBJ_ID = :I$OBJ_ID
  INTO :V$SRC_TYPE;

  TAG_NAME = 'items::json&colon;array';
  VAL = 1;
  SUSPEND;

  IF(V$SRC_TYPE IN (9, 187, 256, 347, 179, 289)) THEN
  BEGIN
    FOR
      SELECT DISTINCT L10.OBJ_ID, L10.OBJ_TYPE_ID, C.CAPTION
      FROM LINKS L10
      LEFT JOIN OBJECT_CAPTION_GET(L10.OBJ_ID, 23) C ON 1 = 1
      WHERE L10.PARENT_ID = :I$OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      ORDER BY 3
      INTO :V$OBJ_ID, :V$TYPE_ID, :S1
    DO
    BEGIN
      TAG_NAME = 'items:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'items:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'items:r:type';
      VAL = V$TYPE_ID;
      SUSPEND;
      TAG_NAME = 'items:r:name';
      VAL = S1;
      SUSPEND;
      -- 0 = не назначен, 1 = уже назначен
      TAG_NAME = 'items:r:state';
      VAL = 0;
      SUSPEND;
    END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE ATT_REG_TEACHERS_LIST (
    I$SUBJECT_ID BIGINT,
    I$STAGE_ID BIGINT,
    I$GROUP_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
declare variable V$OBJ_ID bigint;
declare variable V$USER_ID bigint;
declare variable S varchar(400);
begin

  TAG_NAME = 'items::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT DISTINCT L14.OBJ_ID, C.CAPTION, U.USER_ID
    FROM LINKS L2
    JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
    LEFT JOIN OBJECT_CAPTION_GET(L14.OBJ_ID) C ON 1 = 1
    JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
    JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
    JOIN VALL V63 ON V63.OBJ_ID = LP13.PARENT_ID AND V63.PARAM_ID = 63 AND V63.IS_DEL = 0 AND (V63.LISTVAL_ID NOT IN (1310, 1323) OR V63.LISTVAL_ID IN (1335, 3035))
    LEFT JOIN USERS U ON U.OBJ_ID = L14.OBJ_ID AND U.DATE_DEL IS NULL
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND (V74.VAL IS NULL OR V74.VAL > CURRENT_DATE)
    ORDER BY 2
    INTO :V$OBJ_ID, :S, :V$USER_ID
  DO
  BEGIN
    TAG_NAME = 'items:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'items:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'items:r:name';
    VAL = S;
    SUSPEND;
    -- Название основной должности
    TAG_NAME = 'items:r:jobname';
    VAL = NULL;
    SELECT FIRST 1 C.CAPTION
    FROM LINKS L15
    JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
    JOIN VALL V63 ON V63.OBJ_ID = LP13.PARENT_ID AND V63.PARAM_ID = 63 AND V63.IS_DEL = 0 AND (V63.LISTVAL_ID NOT IN (1310, 1323) OR V63.LISTVAL_ID IN (1335, 3035))
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V63.LISTVAL_ID
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
    LEFT JOIN OBJECT_CAPTION_GET(LP13.PARENT_ID) C ON 1 = 1
    WHERE L15.PARENT_ID = :V$OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL AND (V74.VAL IS NULL OR V74.VAL > CURRENT_DATE)
    ORDER BY LV.SORT_ORDER
    INTO :VAL;
    SUSPEND;
    -- Статус как преподавателя в данном сочетании параметров
    -- 1 = штатный, 11 = дополнительный с полным доступом, 21 = дополнительный RO
    -- 2 = по этому предмету в этом курсе, 3 = по этому предмету хоть где-нибудь
    TAG_NAME = 'items:r:status';
    VAL = NULL;
    -- Штатный преподаватель в этой группе
    IF(VAL IS NULL AND I$GROUP_ID IS NOT NULL) THEN
    SELECT FIRST 1 1
    FROM LINKS L10
    JOIN LINKS LPG ON LPG.OBJ_ID = L10.OBJ_ID AND LPG.PARENT_TYPE_ID IN (9, 179, 256, 46) AND LPG.DATE_DEL IS NULL
    JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.GRADE_ID = LPG.PARENT_ID AND J.SUBJECT_ID = :I$SUBJECT_ID AND J.TEACHER_ID = :V$OBJ_ID
    WHERE L10.PARENT_ID = :I$GROUP_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    INTO :VAL;
    -- Дополнительный преподаватель в этой группе
    IF(VAL IS NULL AND I$GROUP_ID IS NOT NULL) THEN
    SELECT FIRST 1 11 + U.ACCESS * 10
    FROM LINKS L10
    JOIN LINKS LPG ON LPG.OBJ_ID = L10.OBJ_ID AND LPG.PARENT_TYPE_ID IN (9, 179, 256, 46) AND LPG.DATE_DEL IS NULL
    JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.GRADE_ID = LPG.PARENT_ID AND J.SUBJECT_ID = :I$SUBJECT_ID
    JOIN CJ2_JOURNAL_USERS U ON U.DATE_DEL IS NULL AND U.CJ_ID = J.OBJ_ID AND U.USER_ID = :V$USER_ID
    WHERE L10.PARENT_ID = :I$GROUP_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    INTO :VAL;
    -- Преподаватель по этому предмету в том же курсе
    IF(VAL IS NULL) THEN
    SELECT FIRST 1 2
    FROM CJ2_JOURNAL J
    WHERE J.DATE_DEL IS NULL AND J.SUBJECT_ID = :I$SUBJECT_ID AND J.TEACHER_ID = :V$OBJ_ID AND J.STAGE_INDEX = :I$STAGE_ID
    INTO :VAL;
    -- Преподаватель по этому предмету хоть где-нибудь
    IF(VAL IS NULL) THEN
    SELECT FIRST 1 3
    FROM CJ2_JOURNAL J
    WHERE J.DATE_DEL IS NULL AND J.SUBJECT_ID = :I$SUBJECT_ID AND J.TEACHER_ID = :V$OBJ_ID
    INTO :VAL;
    SUSPEND;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE ATT_REG_WIZDATA (
    I$STAGE SMALLINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$TEACHER_ID BIGINT;
DECLARE VARIABLE V$PLAN_ID BIGINT;
DECLARE VARIABLE V$PLAN_NAME VARCHAR(1000);
DECLARE VARIABLE V$GROUP_ID BIGINT;
DECLARE VARIABLE V$GROUP_NAME VARCHAR(1000);
DECLARE VARIABLE V$STAGE_ID BIGINT;
DECLARE VARIABLE V$STAGE_NAME VARCHAR(100);
DECLARE VARIABLE V$SUBJECT_ID VARCHAR(1000);
DECLARE VARIABLE V$SUBJECT_NAME VARCHAR(1000);
DECLARE VARIABLE V$SUBJECT_CODE VARCHAR(400);
DECLARE VARIABLE V$CC BIGINT;
DECLARE VARIABLE V$YEAR_ID BIGINT;
DECLARE VARIABLE V$CJ_ID BIGINT;
DECLARE VARIABLE V$FINAL_ID BIGINT;
DECLARE VARIABLE V$DATE DATE;
DECLARE VARIABLE V$OP_ID BIGINT;
DECLARE VARIABLE N INTEGER;
begin

  -- I$STAGE: 1 - первый семестр, 2 - второй семестр, NULL = оба семестра
  IF(I$STAGE IS NULL) THEN
  BEGIN
    FOR
      SELECT TAG_NAME, VAL
      FROM ATT_REG_WIZDATA(-1, :I$USER_ID)
      INTO :TAG_NAME, :VAL
    DO
    BEGIN
      SUSPEND;
    END
    FOR
      SELECT TAG_NAME, VAL
      FROM ATT_REG_WIZDATA(-2, :I$USER_ID)
      INTO :TAG_NAME, :VAL
    DO
    BEGIN
      SUSPEND;
    END
  END
  ELSE
  BEGIN
    -- Заголовок выдаем только в первом семестре
    -- И также только в первом блоке выдаем список групп
    IF(I$STAGE > 0 OR I$STAGE = -1) THEN
    BEGIN
      TAG_NAME = 'groups::json&colon;array';
      VAL = 1;
      SUSPEND;
      FOR
        SELECT L9.OBJ_ID, C.CAPTION, V49.LISTVAL_ID, V2822.VAL
        FROM LINKS L2
        JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
        JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
        LEFT JOIN VALS V2822 ON V2822.OBJ_ID = L9.OBJ_ID AND V2822.PARAM_ID = 2822 AND V2822.IS_DEL = 0
        LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C ON 1 = 1
        WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
        ORDER BY C.SORT_ORDER, 2
        INTO :V$GROUP_ID, :V$GROUP_NAME, :V$STAGE_ID, :V$SUBJECT_CODE
      DO
      BEGIN
        TAG_NAME = 'groups:r';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'groups:r:id';
        VAL = V$GROUP_ID;
        SUSPEND;
        TAG_NAME = 'groups:r:name';
        VAL = V$GROUP_NAME;
        SUSPEND;
        TAG_NAME = 'groups:r:stage_id';
        VAL = V$STAGE_ID;
        SUSPEND;
        TAG_NAME = 'groups:r:spc_code';
        VAL = V$SUBJECT_CODE;
        SUSPEND;
        -- Список подгрупп где есть студенты это группы
        TAG_NAME = 'groups:r:subgroups';
        VAL = '';
        FOR
          SELECT DISTINCT LP179.OBJ_ID
          FROM LINKS L10
          JOIN LINKS LP179 ON LP179.OBJ_ID = L10.OBJ_ID AND LP179.PARENT_TYPE_ID = 179 AND LP179.DATE_DEL IS NULL
          WHERE L10.PARENT_ID = :V$GROUP_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
          INTO :V$SUBJECT_ID
        DO
        BEGIN
          IF(VAL <> '') THEN VAL = VAL || ',';
          VAL = VAL || V$SUBJECT_ID;
        END
        SUSPEND;
      END

      TAG_NAME = 'items::json&colon;array';
      VAL = 1;
      SUSPEND;
    END
    I$STAGE = ABS(I$STAGE);
    FOR
      SELECT V1236.LISTVAL_ID, L400.OBJ_ID, CP.CAPTION, L256.OBJ_ID, CG.CAPTION, V381.LISTVAL_ID, CS.CAPTION,
        PS.SUBJECT_ID, V1751.SVAL, V1752.SVAL, IIF(:I$STAGE = 1, PL.CONTROL_Q1, PL.CONTROL_Q2), L57.OBJ_ID
      FROM LINKS L2
      JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
      JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
      JOIN LINKS L69 ON L69.PARENT_ID = L2.OBJ_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL
      JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
      -- Год публикации в колледжах отсутствует
      -- JOIN VALI V3115 ON V3115.OBJ_ID = L57.OBJ_ID AND V3115.PARAM_ID = 3115 AND V3115.IS_DEL = 0 AND V3115.VAL = LV.COST
      JOIN LINKS L400 ON L400.PARENT_ID = L57.OBJ_ID AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL
      LEFT JOIN OBJECT_CAPTION_GET(L400.OBJ_ID) CP ON 1 = 1
      JOIN LINKS L54 ON L54.PARENT_ID = L400.OBJ_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
      JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
      LEFT JOIN OBJECT_CAPTION_GET(L54.OBJ_ID) CS ON 1 = 1
      JOIN LINKS L256 ON L256.PARENT_ID = L54.OBJ_ID AND L256.OBJ_TYPE_ID = 256 AND L256.DATE_DEL IS NULL
      LEFT JOIN OBJECT_CAPTION_GET(L256.OBJ_ID) CG ON 1 = 1
      -- Нагрузки УП и непустой тип контроля
      JOIN PLAN_SUBJECTS PS ON PS.DATE_DEL IS NULL AND PS.PLAN_ID = L400.OBJ_ID AND PS.ROW_TYPE = 10
      JOIN PLAN_LOADS PL ON PL.DATE_DEL IS NULL AND PL.SUBJECT_ID = PS.OBJ_ID AND PL.STAGE_ID = L54.OBJ_ID AND (PL.LOAD_HOURS_S1 > 0 OR PL.LOAD_HOURS_S2 > 0)
        AND ((:I$STAGE = 1 AND PL.CONTROL_Q1 IN (5250, 5251, 5252)) OR (:I$STAGE = 2 AND PL.CONTROL_Q2 IN (5250, 5251, 5252)))
      JOIN VALS V1751 ON V1751.OBJ_ID = PS.SUBJECT_ID AND V1751.PARAM_ID = 1751 AND V1751.IS_DEL = 0
      LEFT JOIN VALS V1752 ON V1752.OBJ_ID = PS.SUBJECT_ID AND V1752.PARAM_ID = 1752 AND V1752.IS_DEL = 0
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      ORDER BY CP.CAPTION, CS.SORT_ORDER
      INTO :V$YEAR_ID, :V$PLAN_ID, :V$PLAN_NAME, :V$GROUP_ID, :V$GROUP_NAME, :V$STAGE_ID, :V$STAGE_NAME,
        :V$SUBJECT_ID, :V$SUBJECT_NAME, :V$SUBJECT_CODE, :V$CC, :V$OP_ID
    DO
    BEGIN
      -- Есть ли журнал в этом сечении ?
      TAG_NAME = 'items:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'items:r:plan_id';
      VAL = V$PLAN_ID;
      SUSPEND;
      TAG_NAME = 'items:r:plan_name';
      VAL = V$PLAN_NAME;
      SUSPEND;
      TAG_NAME = 'items:r:gup_id';
      VAL = V$GROUP_ID;
      SUSPEND;
      TAG_NAME = 'items:r:gup_name';
      VAL = V$GROUP_NAME;
      SUSPEND;
      TAG_NAME = 'items:r:stage_id';
      VAL = V$STAGE_ID;
      SUSPEND;
      TAG_NAME = 'items:r:stage_name';
      VAL = V$STAGE_NAME;
      SUSPEND;
      TAG_NAME = 'items:r:subject_id';
      VAL = V$SUBJECT_ID;
      SUSPEND;
      TAG_NAME = 'items:r:subject_name';
      VAL = V$SUBJECT_NAME;
      SUSPEND;
      TAG_NAME = 'items:r:subject_code';
      VAL = V$SUBJECT_CODE;
      SUSPEND;
      -- Код специальности не в УП, а в ОП
      TAG_NAME = 'items:r:spc_code';
      VAL = NULL;
      SELECT V1754.VAL
      FROM VALS V1754
      WHERE V1754.OBJ_ID = :V$OP_ID AND V1754.PARAM_ID = 1754 AND V1754.IS_DEL = 0
      INTO :VAL;
      SUSPEND;
      TAG_NAME = 'items:r:control_type_id';
      VAL = V$CC;
      SUSPEND;
      TAG_NAME = 'items:r:control_type_name';
      VAL = (SELECT VAL FROM LISTVAL_TEXT(:V$CC));
      SUSPEND;
      -- Есть ли журнал прямо к этой ГУП
      V$CJ_ID = NULL;
      V$FINAL_ID = NULL;
      V$DATE = NULL;
      SELECT FIRST 1 J.OBJ_ID, F.OBJ_ID, F.FINAL_DATE, J.TEACHER_ID
      FROM CJ2_JOURNAL J
      JOIN LINKS L179 ON L179.OBJ_ID = J.GRADE_ID AND L179.PARENT_TYPE_ID = 2 AND L179.DATE_DEL IS NULL AND L179.EXT_OBJ_ID = :V$GROUP_ID
      LEFT JOIN CJ2_JOURNAL_FINALS F ON F.DATE_DEL IS NULL AND F.CJ_ID = J.OBJ_ID AND F.FINAL_TYPE = IIF(:I$STAGE = 1, 12973, 12974)
      WHERE J.DATE_DEL IS NULL AND J.YEAR_ID = :V$YEAR_ID AND J.SUBJECT_ID = :V$SUBJECT_ID
      INTO :V$CJ_ID, :V$FINAL_ID, :V$DATE, :V$TEACHER_ID;
      -- Если нет напрямую, ищем через обучающихся - где их больше
      IF(V$CJ_ID IS NULL) THEN
      SELECT FIRST 1 J.OBJ_ID, F.OBJ_ID, F.FINAL_DATE, J.TEACHER_ID, COUNT(*)
      FROM CJ2_JOURNAL J
      JOIN LINKS L10 ON L10.PARENT_ID = J.GRADE_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      JOIN LINKS LPG ON LPG.OBJ_ID = L10.OBJ_ID AND LPG.PARENT_ID = :V$GROUP_ID AND LPG.DATE_DEL IS NULL
      LEFT JOIN CJ2_JOURNAL_FINALS F ON F.DATE_DEL IS NULL AND F.CJ_ID = J.OBJ_ID AND F.FINAL_TYPE = IIF(:I$STAGE = 1, 12973, 12974)
      WHERE J.DATE_DEL IS NULL AND J.YEAR_ID = :V$YEAR_ID AND J.SUBJECT_ID = :V$SUBJECT_ID
      GROUP BY 1, 2, 3, 4
      ORDER BY 4 DESC
      INTO :V$CJ_ID, :V$FINAL_ID, :V$DATE, :V$TEACHER_ID, :N;
      -- Есть ли журнал
      TAG_NAME = 'items:r:cj_id';
      VAL = V$CJ_ID;
      SUSPEND;
      -- Есть ли контроль
      TAG_NAME = 'items:r:final_id';
      VAL = V$FINAL_ID;
      SUSPEND;
      TAG_NAME = 'items:r:final_date';
      VAL = (SELECT VAL FROM DATE2ISO(:V$DATE, 0));
      SUSPEND;
      -- Пытаемся определить группу
      TAG_NAME = 'items:r:grade_id';
      V$CJ_ID = NULL;
      SELECT FIRST 1 LP9.PARENT_ID, COUNT(*)
      FROM LINKS L10
      JOIN LINKS LP9 ON LP9.OBJ_ID = L10.OBJ_ID AND LP9.PARENT_TYPE_ID = 9 AND LP9.DATE_DEL IS NULL
      WHERE L10.PARENT_ID = :V$GROUP_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      GROUP BY 1
      ORDER BY 2 DESC
      INTO :V$CJ_ID, :N;
      VAL = V$CJ_ID;
      SUSPEND;
      TAG_NAME = 'items:r:grade_name';
      IF(V$CJ_ID IS NULL) THEN VAL = NULL; ELSE VAL = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$CJ_ID));
      SUSPEND;
      -- Сотрудники
      TAG_NAME = 'items:r:teachers';
      VAL = V$TEACHER_ID;
      IF(VAL IS NULL) THEN VAL = '';
      FOR
        SELECT U.OBJ_ID
        FROM CJ2_JOURNAL_USERS JU
        JOIN USERS U ON U.USER_ID = JU.USER_ID AND U.DATE_DEL IS NULL AND U.IS_BLOCKED = 0 AND U.OBJ_ID <> :V$TEACHER_ID
        JOIN LINKS L2 ON L2.OBJ_ID = U.OBJ_ID AND L2.PARENT_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
        WHERE JU.DATE_DEL IS NULL AND JU.CJ_ID = :V$CJ_ID
        INTO :V$CC
      DO
      BEGIN
        IF(VAL <> '') THEN VAL = VAL || ',';
        VAL = VAL || V$CC;
      END
      SUSPEND;
      -- Количество учеников - самих учеников выберем потом
      TAG_NAME = 'items:r:students';
      SELECT COUNT(*)
      FROM LINKS L10
      WHERE L10.PARENT_ID = :V$GROUP_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      INTO :VAL;
      SUSPEND;
      -- Есть ли ведомость
      TAG_NAME = 'items:r:register_id';
      VAL = NULL;
      V$DATE = NULL;
      N = NULL;
      SELECT FIRST 1 R.OBJ_ID, R.STATE_ID, R.ATT_DATE
      FROM ATT_REGISTER R
      WHERE R.DATE_DEL IS NULL AND R.YEAR_ID = :V$YEAR_ID AND R.SUBJECT_ID = :V$SUBJECT_ID AND R.STAGE_ID = :V$STAGE_ID AND R.SUBSTAGE_ID = :I$STAGE
      ORDER BY R.STATE_ID
      INTO :VAL, :N, :V$DATE;
      SUSPEND;
      TAG_NAME = 'items:r:register_state';
      VAL = N;
      SUSPEND;
      TAG_NAME = 'items:r:register_date';
      VAL = (SELECT VAL FROM DATE2ISO(:V$DATE, 0));
      SUSPEND;
    END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE ATT_SCHOOLAR_FIND (
    F VARCHAR(250),
    I VARCHAR(250),
    O VARCHAR(250),
    BIRTHDATE DATE)
RETURNS (
    SCHOOLAR_ID BIGINT)
AS
DECLARE VARIABLE SCHOOL_ID BIGINT;
DECLARE VARIABLE IS_OK SMALLINT;
BEGIN
    SELECT FIRST 1 L.OBJ_ID
    FROM LINKS L
    WHERE L.PARENT_ID IS NULL
      AND L.OBJ_TYPE_ID = 2
      AND L.DATE_DEL IS NULL
    INTO :SCHOOL_ID;

    FOR SELECT L10.OBJ_ID
        FROM LINKS L7
        INNER JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID
        INNER JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID
        INNER JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID
        INNER JOIN VALS V55 ON V55.OBJ_ID = L10.OBJ_ID
        INNER JOIN VALS V56 ON V56.OBJ_ID = L10.OBJ_ID
        WHERE L7.PARENT_ID = :SCHOOL_ID
          AND L7.OBJ_TYPE_ID = 7
          AND L7.DATE_DEL IS NULL
          AND L8.OBJ_TYPE_ID = 8
          AND L8.DATE_DEL IS NULL
          AND L9.OBJ_TYPE_ID = 9
          AND L9.DATE_DEL IS NULL
          AND L10.OBJ_TYPE_ID = 10
          AND L10.DATE_DEL IS NULL
          AND V55.PARAM_ID = 55
          AND V55.IS_DEL = 0
          AND V55.VAL = :F
          AND V56.PARAM_ID = 56
          AND V56.IS_DEL = 0
          AND V56.VAL = :I

        UNION

        SELECT L10.OBJ_ID
        FROM LINKS L78
        INNER JOIN LINKS L82 ON L82.PARENT_ID = L78.OBJ_ID
        INNER JOIN LINKS L10 ON L10.PARENT_ID = L82.OBJ_ID
        INNER JOIN VALS V55 ON V55.OBJ_ID = L10.OBJ_ID
        INNER JOIN VALS V56 ON V56.OBJ_ID = L10.OBJ_ID
        WHERE L78.PARENT_ID = :SCHOOL_ID
          AND L78.OBJ_TYPE_ID = 78
          AND L78.DATE_DEL IS NULL
          AND L82.OBJ_TYPE_ID = 82
          AND L82.DATE_DEL IS NULL
          AND L10.OBJ_TYPE_ID = 10
          AND L10.DATE_DEL IS NULL
          AND V55.PARAM_ID = 55
          AND V55.IS_DEL = 0
          AND V55.VAL = :F
          AND V56.PARAM_ID = 56
          AND V56.IS_DEL = 0
          AND V56.VAL = :I

        UNION

        SELECT L10.OBJ_ID
        FROM LINKS L78
        INNER JOIN LINKS L83 ON L83.PARENT_ID = L78.OBJ_ID
        INNER JOIN LINKS L10 ON L10.PARENT_ID = L83.OBJ_ID
        INNER JOIN VALS V55 ON V55.OBJ_ID = L10.OBJ_ID
        INNER JOIN VALS V56 ON V56.OBJ_ID = L10.OBJ_ID
        WHERE L78.PARENT_ID = :SCHOOL_ID
          AND L78.OBJ_TYPE_ID = 78
          AND L78.DATE_DEL IS NULL
          AND L83.OBJ_TYPE_ID = 83
          AND L83.DATE_DEL IS NULL
          AND L10.OBJ_TYPE_ID = 10
          AND L10.DATE_DEL IS NULL
          AND V55.PARAM_ID = 55
          AND V55.IS_DEL = 0
          AND V55.VAL = :F
          AND V56.PARAM_ID = 56
          AND V56.IS_DEL = 0
          AND V56.VAL = :I
        INTO :SCHOOLAR_ID

    DO
    BEGIN
        IS_OK = 1;

        IF (:O > '') THEN
        BEGIN
            IS_OK = 0;

            SELECT FIRST 1 1
            FROM VALS V
            WHERE V.PARAM_ID = 57
              AND V.OBJ_ID = :SCHOOLAR_ID
              AND V.IS_DEL = 0
              AND V.VAL = :O
            INTO :IS_OK;
        END

        IF ((IS_OK = 1) AND (:BIRTHDATE IS NOT NULL)) THEN
        BEGIN
            IS_OK = 0;

            SELECT FIRST 1 1
            FROM VALD V
            WHERE V.PARAM_ID = 89
              AND V.OBJ_ID = :SCHOOLAR_ID
              AND V.IS_DEL = 0
              AND V.VAL = :BIRTHDATE
            INTO :IS_OK;
        END

        IF (IS_OK = 1) THEN
            SUSPEND;
    END

    FOR SELECT L126.OBJ_ID
        FROM LINKS L7
        INNER JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID
        INNER JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID
        INNER JOIN LINKS L126 ON L126.PARENT_ID = L9.OBJ_ID
        INNER JOIN VALS V827 ON V827.OBJ_ID = L126.OBJ_ID
        INNER JOIN VALS V828 ON V828.OBJ_ID = L126.OBJ_ID
        WHERE L7.PARENT_ID = :SCHOOL_ID
          AND L7.OBJ_TYPE_ID = 7
          AND L7.DATE_DEL IS NULL
          AND L8.OBJ_TYPE_ID = 8
          AND L8.DATE_DEL IS NULL
          AND L9.OBJ_TYPE_ID = 9
          AND L9.DATE_DEL IS NULL
          AND L126.OBJ_TYPE_ID = 126
          AND L126.DATE_DEL IS NULL
          AND V827.PARAM_ID = 827
          AND V827.IS_DEL = 0
          AND V827.VAL = :F
          AND V828.PARAM_ID = 828
          AND V828.IS_DEL = 0
          AND V828.VAL = :I

        UNION

        SELECT L126.OBJ_ID
        FROM LINKS L7
        INNER JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID
        INNER JOIN LINKS L125 ON L125.PARENT_ID = L8.OBJ_ID
        INNER JOIN LINKS L126 ON L126.PARENT_ID = L125.OBJ_ID
        INNER JOIN VALS V827 ON V827.OBJ_ID = L126.OBJ_ID
        INNER JOIN VALS V828 ON V828.OBJ_ID = L126.OBJ_ID
        WHERE L7.PARENT_ID = :SCHOOL_ID
          AND L7.OBJ_TYPE_ID = 7
          AND L7.DATE_DEL IS NULL
          AND L8.OBJ_TYPE_ID = 8
          AND L8.DATE_DEL IS NULL
          AND L125.OBJ_TYPE_ID = 125
          AND L125.DATE_DEL IS NULL
          AND L126.OBJ_TYPE_ID = 126
          AND L126.DATE_DEL IS NULL
          AND V827.PARAM_ID = 827
          AND V827.IS_DEL = 0
          AND V827.VAL = :F
          AND V828.PARAM_ID = 828
          AND V828.IS_DEL = 0
          AND V828.VAL = :I
        INTO :SCHOOLAR_ID

    DO
    BEGIN
        IS_OK = 1;

        IF (:O > '') THEN
        BEGIN
            IS_OK = 0;

            SELECT FIRST 1 1
            FROM VALS V
            WHERE V.PARAM_ID = 829
              AND V.OBJ_ID = :SCHOOLAR_ID
              AND V.IS_DEL = 0
              AND V.VAL = :O
            INTO :IS_OK;
        END

        IF ((IS_OK = 1) AND (:BIRTHDATE IS NOT NULL)) THEN
        BEGIN
            IS_OK = 0;

            SELECT FIRST 1 1
            FROM VALD V
            WHERE V.PARAM_ID = 830
              AND V.OBJ_ID = :SCHOOLAR_ID
              AND V.IS_DEL = 0
              AND V.VAL = :BIRTHDATE
            INTO :IS_OK;
        END

        IF (IS_OK = 1) THEN
            SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE ATT_SUBJECT_GET (
    I$CLASS_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    SUBJECT_ID BIGINT,
    SUBJECT_CODE VARCHAR(250),
    SUBJECT VARCHAR(250),
    COMPONENT VARCHAR(250))
AS
declare variable SCHOOL_ID bigint;
declare variable CURRICULUM_ID bigint;
declare variable STAGE_ID bigint;
declare variable LANG_CODE varchar(2);
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :LANG_CODE;

    SELECT FIRST 1 L.OBJ_ID
    FROM LINKS L
    WHERE L.PARENT_ID IS NULL
    AND L.OBJ_TYPE_ID = 2
    AND L.DATE_DEL IS NULL
    INTO :SCHOOL_ID;

    SELECT FIRST 1
           L50.OBJ_ID,
           L54.OBJ_ID
    FROM LINKS L69

    JOIN LINKS L57
    ON L57.PARENT_ID = L69.OBJ_ID
    AND L57.OBJ_TYPE_ID = 57
    AND L57.DATE_DEL IS NULL

    JOIN LINKS L50
    ON L50.PARENT_ID = L57.OBJ_ID
    AND L50.OBJ_TYPE_ID = 50
    AND L50.DATE_DEL IS NULL

    JOIN LINKS L54
    ON L54.PARENT_ID = L50.OBJ_ID
    AND L54.OBJ_TYPE_ID = 54
    AND L54.DATE_DEL IS NULL

    JOIN LINKS L9
    ON L9.PARENT_ID = L54.OBJ_ID
    AND L9.OBJ_TYPE_ID = 9
    AND L9.DATE_DEL IS NULL
    AND L9.OBJ_ID = :I$CLASS_ID

    JOIN VALL V1832
    ON V1832.OBJ_ID = L57.OBJ_ID
    AND V1832.PARAM_ID = 1832
    AND V1832.IS_DEL = 0
    AND V1832.LISTVAL_ID = 5336

    WHERE L69.PARENT_ID = :SCHOOL_ID
    AND L69.OBJ_TYPE_ID = 69
    AND L69.DATE_DEL IS NULL

    INTO :CURRICULUM_ID, :STAGE_ID;

    FOR
        SELECT L51.OBJ_ID,
               VS.VAL,
               R.VAL
        FROM LINKS L49

        JOIN LINKS L51
        ON L51.PARENT_ID = L49.OBJ_ID
        AND L51.OBJ_TYPE_ID = 51
        AND L51.DATE_DEL IS NULL

        JOIN LINKS L56
        ON L56.PARENT_ID = :STAGE_ID
        AND L56.OBJ_TYPE_ID = 56
        AND L56.DATE_DEL IS NULL

        JOIN LINKS L51_56
        ON L51_56.OBJ_ID = L56.OBJ_ID
        AND L51_56.PARENT_ID = L51.OBJ_ID
        AND L51_56.DATE_DEL IS NULL

        JOIN LINKS L49_56
        ON L49_56.OBJ_ID = L56.OBJ_ID
        AND L49_56.PARENT_ID = L49.OBJ_ID
        AND L49_56.DATE_DEL IS NULL

        JOIN VALI VI
        ON VI.OBJ_ID = L56.OBJ_ID
        AND VI.PARAM_ID = 385
        AND VI.IS_DEL = 0
        AND VI.VAL > 0

        JOIN VALL VL
        ON VL.OBJ_ID = L49.OBJ_ID
        AND VL.PARAM_ID = 372
        AND VL.IS_DEL = 0

        JOIN LISTVALS LV
        ON LV.LISTVAL_ID = VL.LISTVAL_ID

        LEFT JOIN RES_GET(LV.RES_ID,  :LANG_CODE) R ON 1=1

        JOIN VALS VS
        ON VS.OBJ_ID = L51.OBJ_ID
        AND VS.PARAM_ID = 376
        AND VS.IS_DEL = 0

        WHERE L49.PARENT_ID = :CURRICULUM_ID
        AND L49.OBJ_TYPE_ID = 49
        AND L49.DATE_DEL IS NULL

        ORDER BY L51.OBJ_ID
        INTO :SUBJECT_ID,
             :SUBJECT,
             :COMPONENT
    DO
    BEGIN
        SUBJECT_CODE = NULL;

        SELECT FIRST 1 V.VAL
        FROM VALS V
        WHERE V.PARAM_ID = 377
        AND V.OBJ_ID = :SUBJECT_ID
        AND V.IS_DEL = 0
        INTO :SUBJECT_CODE;

        SUSPEND;
    END

END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE ATT_VAL_AFTER (
    I$OBJ_ID BIGINT,
    I$PARAM_ID BIGINT,
    I$VAL VARCHAR(4000),
    I$IS_DEL SMALLINT,
    I$USER_ID BIGINT)
AS
declare variable V$OBJ_ID bigint;
declare variable V$TYPE_ID bigint;
declare variable V$NF integer;
begin

  SELECT TYPE_ID
  FROM OBJECTS
  WHERE OBJ_ID = :I$OBJ_ID
  INTO :V$TYPE_ID;

  -- Ставить статус достоверности может только руководитель
  IF(I$PARAM_ID = 3296) THEN
  BEGIN
    SELECT U.USER_TYPE
    FROM USERS U
    WHERE U.USER_ID = :I$USER_ID
    INTO :V$OBJ_ID;

    IF(I$VAL = 2 AND (V$OBJ_ID IS NULL OR V$OBJ_ID NOT IN (1, 5, 6))) THEN
      EXCEPTION DATA_ERROR 'Только руководитель или завуч может менять статус подтверждения';

    IF(I$VAL = 2) THEN
    BEGIN
      -- Все ли поля заполнены ?
      V$NF = (SELECT COUNT(*) FROM VALL V WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID IN (3292, 3293) AND V.IS_DEL = 0) +
        (SELECT COUNT(*) FROM VALB V WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 3294 AND V.IS_DEL = 0);
      IF(V$NF <> 3) THEN EXCEPTION DATA_ERROR 'Не все обязательные поля заполнены, либо не загружен файл';
    END
  END

  -- После отправки менять ничего нельзя
  IF(V$TYPE_ID = 458) THEN
  BEGIN
    IF(EXISTS(
      SELECT FIRST 1 1
      FROM VALS V
      WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID IN (3288) AND V.IS_DEL = 0
    ))
    THEN EXCEPTION DATA_ERROR 'После отправки пакета, вносить изменения нельзя';

    -- Когд меняем форму аттестации - ругаемся, если выпали критерии
    IF(I$IS_DEL = 1) THEN I$VAL = NULL;
    IF(EXISTS(
      SELECT FIRST 1 1
      FROM LINKS L459
      JOIN VALL V3292 ON V3292.OBJ_ID = L459.OBJ_ID AND V3292.PARAM_ID = 3292 AND V3292.IS_DEL = 0
      LEFT JOIN LISTVALS LV ON LV.LISTVAL_ID = V3292.LISTVAL_ID AND LV.TAG LIKE '%' || :I$VAL || '%'
      WHERE L459.PARENT_ID = :I$OBJ_ID AND L459.OBJ_TYPE_ID = 459 AND L459.DATE_DEL IS NULL AND LV.LISTVAL_ID IS NULL
    ))
    THEN EXCEPTION DATA_ERROR 'Ранее внесенные критерии не подходят под выбранную форму аттестации';
  END
  ELSE IF(V$TYPE_ID = 459) THEN
  BEGIN
    -- Специальная заглушка, чтобы можно было сохранять статус, и не ругалось само на себя
    IF(I$PARAM_ID NOT IN (3291, 3297) AND EXISTS(
      SELECT FIRST 1 1
      FROM VALS V
      WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID IN (3291, 3297) AND V.IS_DEL = 0
    ))
    THEN EXCEPTION DATA_ERROR 'После отправки показателя, вносить изменения нельзя';

    IF(EXISTS(
      SELECT FIRST 1 1
      FROM LINKS LP458
      JOIN VALS V ON V.OBJ_ID = LP458.PARENT_ID AND V.PARAM_ID IN (3288) AND V.IS_DEL = 0
      WHERE LP458.OBJ_ID = :I$OBJ_ID AND LP458.PARENT_TYPE_ID = 458 AND LP458.DATE_DEL IS NULL
    ))
    THEN EXCEPTION DATA_ERROR 'После отправки пакета, вносить изменения нельзя';

    -- Когда меняем критерий - сбрасываем тип файла, если он несовместим
    IF(I$PARAM_ID = 3292) THEN
    BEGIN
      IF(I$IS_DEL = 1) THEN I$VAL = NULL;

      IF(NOT EXISTS(
        SELECT FIRST 1 1
        FROM VALL V3293
        JOIN LISTVALS LV ON LV.LISTVAL_ID = V3293.LISTVAL_ID AND LV.TAG LIKE '%' || :I$VAL || '%'
        WHERE V3293.OBJ_ID = :I$OBJ_ID AND V3293.PARAM_ID = 3293 AND V3293.IS_DEL = 0
      ))
      THEN
      BEGIN
        UPDATE VALL SET IS_DEL = 1 WHERE OBJ_ID = :I$OBJ_ID AND PARAM_ID = 3293 AND IS_DEL = 0;
      END
    END
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE BARBUTTONS_LIST (
    I$BAR_ID BIGINT,
    I$LANG_CODE CHAR(2) = 'RU')
RETURNS (
    BUTTON_ID BIGINT,
    BAR_ID BIGINT,
    SORT_ORDER SMALLINT,
    RES_ID BIGINT,
    BUTTON_CAPTION VARCHAR(4000),
    DO_FUNC VARCHAR(100),
    ICON_ID BIGINT,
    TAG VARCHAR(20),
    IS_DEL SMALLINT,
    LANG_CODE CHAR(2))
AS
BEGIN
    LANG_CODE = I$LANG_CODE;

    FOR
        SELECT BUTTON_ID, BAR_ID, SORT_ORDER, RES_ID, DO_FUNC, ICON_ID, IS_DEL, TAG
        FROM BARBUTTONS
        WHERE BAR_ID = :I$BAR_ID
        ORDER BY SORT_ORDER
        INTO  :BUTTON_ID, :BAR_ID, :SORT_ORDER, :RES_ID, :DO_FUNC, :ICON_ID, :IS_DEL, :TAG
    DO BEGIN
        SELECT VAL FROM RES_GET(:RES_ID, :I$LANG_CODE) INTO :BUTTON_CAPTION;
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE BARBUTTON_ADD (
    I$BUTTON_ID BIGINT,
    I$BAR_ID BIGINT,
    I$RES_ID BIGINT,
    I$DO_FUNC VARCHAR(100),
    I$LANG_CODE CHAR(2),
    I$BUTTON_CAPTION VARCHAR(4000),
    I$TAG VARCHAR(20),
    I$ICON_ID BIGINT,
    I$IS_DEL SMALLINT = 0)
RETURNS (
    BUTTON_ID BIGINT,
    RES_ID BIGINT)
AS
DECLARE VARIABLE SORT_ORDER SMALLINT;
BEGIN
   BUTTON_ID = I$BAR_ID;
   RES_ID = I$RES_ID;

   IF (:I$BUTTON_ID IS NULL) THEN BEGIN
      SELECT MAX(SORT_ORDER) + 1 FROM BARBUTTONS
      WHERE BAR_ID = :I$BAR_ID INTO :SORT_ORDER;

      IF (SORT_ORDER IS NULL) THEN SORT_ORDER = 1;

      INSERT INTO BARBUTTONS (BAR_ID, SORT_ORDER, DO_FUNC, TAG, ICON_ID, IS_DEL)
      VALUES (:I$BAR_ID, :SORT_ORDER, :I$DO_FUNC, :I$TAG, :I$ICON_ID, :I$IS_DEL)
      RETURNING BUTTON_ID, RES_ID INTO :BUTTON_ID, :RES_ID;

   END ELSE BEGIN
      UPDATE BARBUTTONS
      SET DO_FUNC = :I$DO_FUNC,
          ICON_ID = :I$ICON_ID,
          TAG = :I$TAG,
          IS_DEL = :I$IS_DEL
      WHERE BUTTON_ID = :I$BUTTON_ID;
   END

   IF (RES_ID IS NOT NULL) THEN
   BEGIN
       EXECUTE PROCEDURE RES_ADD (:RES_ID,:I$LANG_CODE,:I$BUTTON_CAPTION);
   END

   SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE BARBUTTON_MOVE (
    I$BUTTON_ID BIGINT,
    I$MOVE SMALLINT)
RETURNS (
    SORT_ORDER SMALLINT)
AS
DECLARE VARIABLE BUTTON_ID BIGINT = NULL;
DECLARE VARIABLE BAR_ID BIGINT = NULL;
BEGIN
   SELECT BAR_ID, SORT_ORDER FROM BARBUTTONS
   WHERE BUTTON_ID = :I$BUTTON_ID
   INTO :BAR_ID, :SORT_ORDER;

   SELECT BUTTON_ID FROM BARBUTTONS
   WHERE BAR_ID = :BAR_ID AND SORT_ORDER = (:SORT_ORDER + :I$MOVE)
   INTO :BUTTON_ID;

   IF (BUTTON_ID IS NOT NULL) THEN BEGIN
      UPDATE BARBUTTONS SET SORT_ORDER = :SORT_ORDER WHERE BUTTON_ID = :BUTTON_ID;
      UPDATE BARBUTTONS SET SORT_ORDER = (:SORT_ORDER + :I$MOVE) WHERE BUTTON_ID = :I$BUTTON_ID;
   END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE BARS_LIST RETURNS (
    BAR_ID BIGINT,
    TAG VARCHAR(100),
    IS_DEL SMALLINT)
AS
BEGIN
    FOR SELECT BAR_ID, TAG, IS_DEL
        FROM BARS
        ORDER BY BAR_ID
        INTO :BAR_ID, :TAG, :IS_DEL
    DO SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE BAR_ADD (
    I$BAR_ID BIGINT,
    I$TAG VARCHAR(100),
    I$IS_DEL SMALLINT = 0)
RETURNS (
    BAR_ID BIGINT)
AS
BEGIN
   BAR_ID = I$BAR_ID;

   IF (:I$BAR_ID IS NULL) THEN BEGIN
      INSERT INTO BARS (TAG, IS_DEL)
      VALUES (:I$TAG, :I$IS_DEL)
      RETURNING BAR_ID INTO :BAR_ID;
   END ELSE BEGIN
      UPDATE BARS
      SET TAG = :I$TAG,
          IS_DEL = :I$IS_DEL
      WHERE (BAR_ID = :I$BAR_ID);
   END

   SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE BLOBS_LIST RETURNS (
    BLOB_ID BIGINT,
    VAL VARCHAR(4000))
AS
begin

  FOR
      SELECT BLOB_ID, VAL
      FROM VALB
      WHERE IS_DEL = 0 OR (IS_DEL = 1 AND DATE_MODIFY < DATEADD(-5 YEAR TO CURRENT_DATE))
      INTO :BLOB_ID, :VAL
  DO
  BEGIN
      SUSPEND;
  END

  FOR
      SELECT OBJ_ID, FILE_NAME
      FROM CJ2_BLOB
      WHERE DATE_DEL IS NULL
      INTO :BLOB_ID, :VAL
  DO
  BEGIN
      SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE BOOK_SRC_SUBJECT_LIST RETURNS (
    OBJ_ID BIGINT,
    OBJ_CAPTION VARCHAR(1000))
AS
declare variable LC char(1);
begin

  -- Для школ берем тип 51 (предметы), для колледжей 197 (дисциплина)

  SELECT STATUS
  FROM OU_LICENCE_TYPE
  INTO :LC;

  IF(LC = 'C') THEN
  BEGIN

      FOR
          SELECT OBJ_ID, OBJ_CAPTION
          FROM PARAGRAF_TYPE_REFERENSE_LIST(197)
          INTO :OBJ_ID, :OBJ_CAPTION
      DO
      BEGIN
          SUSPEND;
      END

  END
  ELSE
  BEGIN

      FOR
          SELECT OBJ_ID, OBJ_CAPTION
          FROM PARAGRAF_TYPE_REFERENSE_LIST(51)
          INTO :OBJ_ID, :OBJ_CAPTION
      DO
      BEGIN
          SUSPEND;
      END

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE BOTAPI_IDENTIFY (
    I$ID VARCHAR(100),
    I$NAME VARCHAR(400),
    I$MESSAGE VARCHAR(1000),
    I$PHONENUM VARCHAR(100))
RETURNS (
    OBJ_ID BIGINT,
    TYPE_ID BIGINT)
AS
declare variable V$PERSON_ID bigint;
begin

  SELECT FIRST 1 VID.OBJ_ID, LP.OBJ_TYPE_ID
  FROM VALS VID
  JOIN LINKS LP ON LP.OBJ_ID = VID.OBJ_ID AND LP.PARENT_TYPE_ID IN (9, 10, 2, 211) AND LP.DATE_DEL IS NULL
  LEFT JOIN LINKS LPG ON LPG.OBJ_ID = LP.PARENT_ID AND LPG.PARENT_TYPE_ID IN (9) AND LPG.DATE_DEL IS NULL
  WHERE VID.PARAM_ID IN (3109, 3110, 3111) AND VID.IS_DEL = 0 AND VID.SVAL = :I$ID AND (LP.OBJ_TYPE_ID <> 20 OR LPG.PARENT_ID IS NOT NULL)
  INTO :OBJ_ID, :TYPE_ID;

  -- Если мессенджер не связан с персоной, после получения контактных данных вносим заявку авторизации
  IF(OBJ_ID IS NULL AND I$PHONENUM IS NOT NULL) THEN
  BEGIN
    -- Есть ли у нас контакт с таким номером телефона, чтобы точно совпадали последние 10 цифр ?
    -- причем если есть код страны, то обязательно +7
    IF(SUBSTRING(I$PHONENUM FROM 1 FOR 2) = '+7') THEN
    BEGIN
      I$PHONENUM = SUBSTRING(I$PHONENUM FROM 2);

      SELECT FIRST 1 V.OBJ_ID
      FROM VALS V
      JOIN LINKS LP ON LP.OBJ_ID = V.OBJ_ID AND LP.PARENT_TYPE_ID IN (9, 10, 2, 211) AND LP.DATE_DEL IS NULL
      LEFT JOIN LINKS LPG ON LPG.OBJ_ID = LP.PARENT_ID AND LPG.PARENT_TYPE_ID IN (9) AND LPG.DATE_DEL IS NULL
      WHERE V.PARAM_ID IN (102, 254, 146) AND V.IS_DEL = 0 AND REPLACE(REPLACE(REPLACE(REPLACE(V.SVAL, '(', ''), ')', ''), '-', ''), ' ', '') LIKE '%' || :I$PHONENUM
        AND (LP.OBJ_TYPE_ID <> 20 OR LPG.PARENT_ID IS NOT NULL)
      INTO :V$PERSON_ID;
    END

    INSERT INTO BOT_REQUESTS
    (ACC_ID, ACC_NAME, PHONE_NUM, PERSON_ID)
    VALUES (:I$ID, :I$NAME, :I$PHONENUM, :V$PERSON_ID);
  END

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE BOT_MESSAGES_GET RETURNS (
    CHAT_ID VARCHAR(40),
    MESSAGE_ID BIGINT,
    MESSAGE_TYPE VARCHAR(100),
    MESSAGE_TEXT VARCHAR(1000))
AS
declare variable S1 varchar(1000);
declare variable S2 varchar(1000);
begin

  -- Оповещения по аудиту журналов
  MESSAGE_TYPE = 'audit';
  FOR
    SELECT V3110.SVAL, A.OBJ_ID, A.MSG_TEXT, SC.CAPTION, SG.CAPTION
    FROM CJ2_AUDIT A
    JOIN VALS V3110 ON V3110.OBJ_ID = A.TEACHER_ID AND V3110.PARAM_ID = 3110 AND V3110.IS_DEL = 0
    JOIN CJ2_JOURNAL J ON J.OBJ_ID = A.CJ_ID AND J.DATE_DEL IS NULL
    LEFT JOIN OBJECT_CAPTION_GET(J.SUBJECT_ID) SC ON 1 = 1
    LEFT JOIN OBJECT_CAPTION_GET(J.GRADE_ID) SG ON 1 = 1
    WHERE A.DATE_DEL IS NULL AND A.BOT_STATUS = 0 AND A.STATE_ID = 0
    INTO :CHAT_ID, :MESSAGE_ID, :MESSAGE_TEXT, :S1, :S2
  DO
  BEGIN
    MESSAGE_TEXT = SUBSTRING('Замечание по ведению журнала' || ASCII_CHAR(10) || S1 || ' (' || S2 || ')' || ASCII_CHAR(10) || MESSAGE_TEXT FROM 1 FOR 1000);
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE BOT_MESSAGE_CONFIRM (
    I$MESSAGE_TYPE VARCHAR(100),
    I$ID BIGINT)
AS
begin

  IF(I$MESSAGE_TYPE = 'audit') THEN
  BEGIN
    UPDATE CJ2_AUDIT
    SET BOT_STATUS = BIN_OR(BOT_STATUS, 1)
    WHERE OBJ_ID = :I$ID;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE BUILDER_ACCESS (
    TYPE_ID BIGINT,
    PARAM_ID BIGINT,
    LEVEL_ID BIGINT,
    OBJ_ID BIGINT,
    USER_ID BIGINT)
RETURNS (
    ENA SMALLINT,
    FUNC_TYPE VARCHAR(100),
    EDITABLE SMALLINT)
AS
begin

  -- Кроме проверки доступа для полей типа FUNC возвращаем тег с типом

  ENA = 0;
  EDITABLE = 0;

  IF(PARAM_ID IS NULL) THEN
    SELECT FIRST 1 1, IIF(LT.EDIT_TYPE = 1 AND LU.READ_ONLY = 0, 1, 0)
    FROM TYPES T
    JOIN USERS U ON U.USER_ID = :USER_ID AND U.DATE_DEL IS NULL AND U.IS_BLOCKED = 0
    JOIN LUSERS LU ON LU.USER_ID = U.USER_ID
    JOIN LTYPES LT ON LT.TYPE_ID = T.TYPE_ID AND LT.EDIT_TYPE >= 0 AND LT.IS_DEL = 0 AND LT.LEVEL_ID = LU.LEVEL_ID
    WHERE T.TYPE_ID = :TYPE_ID
    INTO :ENA, :EDITABLE;
  ELSE
    SELECT FIRST 1 1, P.TAG, IIF(LT.EDIT_TYPE = 1 AND LU.READ_ONLY = 0 AND LP.EDIT_TYPE = 1, 1, 0)
    FROM TYPES T
    JOIN USERS U ON U.USER_ID = :USER_ID AND U.DATE_DEL IS NULL AND U.IS_BLOCKED = 0
    JOIN LUSERS LU ON LU.USER_ID = U.USER_ID
    JOIN LTYPES LT ON LT.TYPE_ID = T.TYPE_ID AND LT.EDIT_TYPE >= 0 AND LT.IS_DEL = 0 AND LT.LEVEL_ID = LU.LEVEL_ID
    JOIN PARAMS P ON P.TYPE_ID = T.TYPE_ID AND P.PARAM_ID = :PARAM_ID AND P.IS_DEL = 0
    JOIN LPARAMS LP ON LP.PARAM_ID = P.PARAM_ID AND LP.EDIT_TYPE >= 0 AND LP.IS_DEL = 0 AND LP.LEVEL_ID = LU.LEVEL_ID
    WHERE T.TYPE_ID = :TYPE_ID
    INTO :ENA, :FUNC_TYPE, :EDITABLE;

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE BUILD_CURPLAN_HOURS (
    PLAN_ID BIGINT,
    STDPLAN_ID BIGINT)
AS
declare variable COMPONENT_ID bigint;
declare variable COMPONENT_TYPE_ID bigint;
declare variable SUBJECT_ID bigint;
declare variable TEMPLATE_SUBJECT_ID bigint;
declare variable STAGE_ID bigint;
declare variable IS_ELECTIVE bigint;
declare variable HOURS integer;
declare variable STAGE_LV bigint;
begin
  -- Основной цикл по компонентам и предметам, пропускаем элективные предметы кроме основной строки
  -- Для УП нового формата
  FOR
    SELECT S.OBJ_ID, PS.FIELD_ID, S.SUBJECT_ID, COALESCE(V2816.LISTVAL_ID, 3), COALESCE(S.SRC_SUBJECT_ID, S.SUBJECT_ID)
    FROM PLAN_SUBJECTS S
    JOIN PLAN_SUBJECTS PS ON PS.OBJ_ID = S.PARENT_ID
    LEFT JOIN VALL V2816 ON V2816.OBJ_ID = PS.SUBJECT_ID AND V2816.PARAM_ID = 2816 AND V2816.IS_DEL = 0
    WHERE S.DATE_DEL IS NULL AND S.PLAN_ID = :PLAN_ID AND S.ROW_TYPE = 10
    INTO :COMPONENT_ID, :COMPONENT_TYPE_ID, :SUBJECT_ID, :IS_ELECTIVE, :TEMPLATE_SUBJECT_ID
  DO
  BEGIN

    -- Вложенный цикл по этапам
    FOR
      SELECT L54.OBJ_ID, V381.LISTVAL_ID
      FROM LINKS L54
      JOIN VALL V381 on V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
      WHERE L54.PARENT_ID = :PLAN_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
      INTO :STAGE_ID, :STAGE_LV
    DO
    BEGIN

      -- Подсчитываем количество часов нагрузки
      HOURS = 0;
      SELECT SUM(COALESCE(L.LOAD_HOURS_S1, 0) + COALESCE(L.LOAD_HOURS_S2, 0))
      FROM PLAN_LOADS L
      WHERE L.DATE_DEL IS NULL AND L.SUBJECT_ID = :COMPONENT_ID AND L.STAGE_ID = :STAGE_ID
      INTO :HOURS;

      IF(HOURS IS NULL) THEN HOURS = 0;

       -- Вставляем запись во временную таблицу
       -- Временный костыль: проверка УП по наличию обязательных предметов идет формально, а предмет если в нем нет часов в итоги не попадает
       --IF(HOURS > 0) THEN
       --BEGIN
         UPDATE OR INSERT INTO CURRICULUM_HOURS(CURRICULUM_ID, COMPONENT_TYPE_ID, SUBJECT_ID, TEMPLATE_SUBJECT_ID, STAGE_ID, IS_ELECTIVE, HOURS)
         VALUES (:PLAN_ID, :COMPONENT_TYPE_ID, :SUBJECT_ID, :TEMPLATE_SUBJECT_ID, :STAGE_LV, :IS_ELECTIVE, :HOURS)
         MATCHING (CURRICULUM_ID, COMPONENT_TYPE_ID, SUBJECT_ID, TEMPLATE_SUBJECT_ID, STAGE_ID, IS_ELECTIVE);
       --END

    END

  END

  -- Для УП старого формата (шаблоны)
  -- !!! убрать этот кусок, он больше не нужен
  FOR
    SELECT L49.OBJ_ID, V372.LISTVAL_ID, L51.OBJ_ID, COALESCE(V2816.LISTVAL_ID, 3)
    FROM LINKS L49
    JOIN LINKS L51 ON L51.PARENT_ID = L49.OBJ_ID AND L51.OBJ_TYPE_ID = 51 AND L51.DATE_DEL is null
    JOIN VALL V372 ON V372.OBJ_ID = L49.OBJ_ID AND V372.PARAM_ID = 372 AND V372.IS_DEL = 0
    LEFT JOIN VALL V2816 ON V2816.OBJ_ID = L51.OBJ_ID AND V2816.PARAM_ID = 2816 AND V2816.IS_DEL = 0
    WHERE L49.PARENT_ID = :PLAN_ID AND L49.OBJ_TYPE_ID = 49 AND L49.DATE_DEL is null
    INTO :COMPONENT_ID, :COMPONENT_TYPE_ID, :SUBJECT_ID, :IS_ELECTIVE
  DO
  BEGIN

    TEMPLATE_SUBJECT_ID = SUBJECT_ID;

    -- Для базового/федерального компонента ищем предмет шаблона, для которого прописана замена (если нет, берем сам предмет)
    IF(COMPONENT_TYPE_ID IN (780, 12752, 13303)) THEN
    BEGIN
        -- На всякий случай берем только одну запись, хотя их и должно быть ровно 1
        SELECT FIRST 1 V2718.VAL
        FROM LINKS L349
        JOIN VALR V2718 ON V2718.OBJ_ID = L349.OBJ_ID AND V2718.PARAM_ID = 2718 AND V2718.IS_DEL = 0
        JOIN VALR V2719 ON V2719.OBJ_ID = L349.OBJ_ID AND V2719.PARAM_ID = 2719 AND V2719.IS_DEL = 0 AND V2719.VAL = :SUBJECT_ID
        WHERE L349.PARENT_ID = :COMPONENT_ID AND L349.OBJ_TYPE_ID = 349 AND L349.DATE_DEL IS NULL
        INTO :TEMPLATE_SUBJECT_ID;
    END
    ELSE
    BEGIN
      -- Для переменной компоненты у нас всегда будет одна замена - виртуальный предмет #0
      TEMPLATE_SUBJECT_ID = 0;
    END

    -- Вложенный цикл по этапам
    FOR
      SELECT L54.OBJ_ID, V381.LISTVAL_ID
      FROM LINKS L54
      JOIN VALL V381 on V381.OBJ_ID = L54.OBJ_ID and V381.PARAM_ID = 381 and V381.IS_DEL = 0
      WHERE L54.PARENT_ID = :PLAN_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL is null
      INTO :STAGE_ID, :STAGE_LV
    DO
    BEGIN

      -- Подсчитываем количество часов нагрузки
      HOURS = 0;
      SELECT COALESCE(SUM(VI.VAL),0)
      -- Основной цикл по нагрузкам УП (связь 1 из 3)
      FROM LINKS L56
      -- По данному этапу (связь 2 из 3)
      JOIN LINKS L56_54 ON L56_54.OBJ_ID = L56.OBJ_ID AND L56_54.PARENT_ID = :STAGE_ID AND L56_54.DATE_DEL IS NULL
      -- По данному предмету (связь 3 из 3)
      JOIN LINKS L56_51 ON L56_51.OBJ_ID = L56.OBJ_ID AND L56_51.PARENT_ID = :SUBJECT_ID AND L56_51.DATE_DEL IS NULL
      -- Количество часов нагрузки не нулевое
      JOIN VALI VI ON VI.OBJ_ID = L56.OBJ_ID AND VI.PARAM_ID = 385 AND VI.IS_DEL = 0 AND VI.VAL > 0
      WHERE L56.PARENT_ID = :COMPONENT_ID AND L56.OBJ_TYPE_ID = 56 AND L56.DATE_DEL IS NULL
      INTO :HOURS;

       -- Вставляем запись во временную таблицу
       -- Временный костыль: проверка УП по наличию обязательных предметов идет формально, а предмет если в нем нет часов в итоги не попадает
       --IF(HOURS > 0) THEN
       --BEGIN
         UPDATE OR INSERT INTO CURRICULUM_HOURS(CURRICULUM_ID, COMPONENT_TYPE_ID, SUBJECT_ID, TEMPLATE_SUBJECT_ID, STAGE_ID, IS_ELECTIVE, HOURS)
         VALUES (:PLAN_ID, :COMPONENT_TYPE_ID, :SUBJECT_ID, :TEMPLATE_SUBJECT_ID, :STAGE_LV, :IS_ELECTIVE, :HOURS)
         MATCHING (CURRICULUM_ID, COMPONENT_TYPE_ID, SUBJECT_ID, TEMPLATE_SUBJECT_ID, STAGE_ID, IS_ELECTIVE);
       --END

    END

  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE BUILD_FIO (
    I$F VARCHAR(400),
    I$I VARCHAR(400),
    I$O VARCHAR(400))
RETURNS (
    FULL_NAME VARCHAR(400))
AS
begin

  FULL_NAME = I$F;
  IF(I$I IS NOT NULL AND I$I <> '') THEN FULL_NAME = FULL_NAME || ' ' || SUBSTRING(I$I FROM 1 FOR 1) || '.';
  IF(I$O IS NOT NULL AND I$O <> '') THEN FULL_NAME = FULL_NAME || SUBSTRING(I$O FROM 1 FOR 1) || '.';

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE BUILD_REP_FIO (
    I$OBJ_ID BIGINT,
    I$F BIGINT,
    I$I BIGINT,
    I$O BIGINT,
    I$FULL SMALLINT = 1)
RETURNS (
    C1 VARCHAR(4000),
    F VARCHAR(250),
    I VARCHAR(250),
    O VARCHAR(250))
AS
BEGIN
  SELECT V
  FROM VAL_GET(:I$OBJ_ID, :I$F)
  INTO :F;

  IF (I$FULL = 1) THEN
  BEGIN
    SELECT CASE WHEN CHAR_LENGTH(TRIM(V)) > 0 THEN TRIM(V) ELSE '' END
    FROM VAL_GET(:I$OBJ_ID, :I$I)
    INTO :I;
    SELECT CASE WHEN CHAR_LENGTH(TRIM(V)) > 0 THEN TRIM(V) ELSE '' END
    FROM VAL_GET(:I$OBJ_ID, :I$O)
    INTO :O;
    C1 = :F || ' ' || :I || ' ' || :O;
  END
  ELSE
  BEGIN
    SELECT :F || ' ' || CASE WHEN CHAR_LENGTH(TRIM(V)) > 0 THEN SUBSTRING(TRIM(V) FROM 1 FOR 1) || '.' ELSE '' END
    FROM VAL_GET(:I$OBJ_ID, :I$I)
    INTO :C1;
    SELECT :C1 || CASE WHEN CHAR_LENGTH(TRIM(V)) > 0 THEN SUBSTRING(TRIM(V) FROM 1 FOR 1) || '.' ELSE '' END
    FROM VAL_GET(:I$OBJ_ID, :I$O)
    INTO :C1;
  END

  SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE BUILD_REP_PARENT_VAL (
    I$TYPE_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$PARAM_ID BIGINT)
RETURNS (
    V VARCHAR(4000),
    I BIGINT)
AS
DECLARE VARIABLE OBJ_ID BIGINT;
BEGIN
    SELECT FIRST 1 OBJ_ID FROM OBJECT_PARENTS_GET(:I$OBJ_ID, :I$TYPE_ID)
    INTO :OBJ_ID;

    SELECT V,I FROM VAL_GET(:OBJ_ID, :I$PARAM_ID,0) INTO :V,:I;

    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE BVL_GIA_QUERY_REGION (
    I$DISTRICT_ID BIGINT = NULL,
    I$OU_GIA_CODE INTEGER = NULL,
    I$EXAM_CODE INTEGER = NULL,
    I$USER_ID BIGINT = NULL)
RETURNS (
    EXAM_CODE INTEGER,
    EXAM_STAGE VARCHAR(255),
    EXAM_TYPE VARCHAR(255),
    EXAM_SUBJECT VARCHAR(255),
    EXAM_DATE DATE,
    DISTRICT_ID BIGINT,
    DISTRICT_NAME VARCHAR(255),
    PUPIL_COUNT INTEGER)
AS
DECLARE VARIABLE REGION_ID BIGINT;
DECLARE VARIABLE EXAM_ID BIGINT;
DECLARE VARIABLE YEAR_ID BIGINT;
DECLARE VARIABLE DISTRICT_CODE INTEGER;
DECLARE VARIABLE LANG_CODE VARCHAR(2);
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :LANG_CODE;

    SELECT FIRST 1 L.OBJ_ID
    FROM LINKS L
    INNER JOIN VALL V742 ON V742.OBJ_ID = L.OBJ_ID
    INNER JOIN LISTVALS LV ON LV.LISTVAL_ID = V742.LISTVAL_ID

    LEFT JOIN RES_GET(LV.RES_ID,  :LANG_CODE) R ON 1=1

    WHERE L.PARENT_ID = 3866
      AND L.OBJ_TYPE_ID = 119
      AND L.DATE_DEL IS NULL
      AND V742.PARAM_ID = 742
      AND V742.IS_DEL = 0
      AND R.VAL = '2011-2012'
    INTO :YEAR_ID;

    SELECT FIRST 1 L.OBJ_ID
    FROM LINKS L
    WHERE L.PARENT_ID IS NULL
      AND L.OBJ_TYPE_ID = 112
      AND L.DATE_DEL IS NULL
    INTO :REGION_ID;

    FOR SELECT L111.OBJ_ID, R.VAL, LV.COST
        FROM LINKS L111
        INNER JOIN VALL V665 ON V665.OBJ_ID = L111.OBJ_ID
        INNER JOIN LISTVALS LV ON LV.LISTVAL_ID = V665.LISTVAL_ID

        LEFT JOIN RES_GET(LV.RES_ID,  :LANG_CODE) R ON 1=1

        WHERE L111.PARENT_ID = :REGION_ID
          AND L111.OBJ_TYPE_ID = 111
          AND L111.DATE_DEL IS NULL
          AND ((:I$DISTRICT_ID IS NULL) OR (L111.OBJ_ID = :I$DISTRICT_ID))
          AND V665.PARAM_ID = 665
          AND V665.IS_DEL = 0
        ORDER BY L111.OBJ_ID
        INTO :DISTRICT_ID, :DISTRICT_NAME, :DISTRICT_CODE
    DO
    BEGIN

        FOR SELECT L.OBJ_ID, V800.VAL, R1.VAL, R2.VAL, R3.VAL, V804.VAL
            FROM LINKS L
            INNER JOIN VALI V800 ON V800.OBJ_ID = L.OBJ_ID
            INNER JOIN VALL V801 ON V801.OBJ_ID = L.OBJ_ID
            INNER JOIN VALL V802 ON V802.OBJ_ID = L.OBJ_ID
            INNER JOIN VALL V803 ON V803.OBJ_ID = L.OBJ_ID
            INNER JOIN VALD V804 ON V804.OBJ_ID = L.OBJ_ID
            INNER JOIN LISTVALS LV1 ON LV1.LISTVAL_ID = V801.LISTVAL_ID
            INNER JOIN LISTVALS LV2 ON LV2.LISTVAL_ID = V802.LISTVAL_ID
            INNER JOIN LISTVALS LV3 ON LV3.LISTVAL_ID = V803.LISTVAL_ID
            LEFT JOIN RES_GET(LV1.RES_ID,  :LANG_CODE) R1 ON 1=1
            LEFT JOIN RES_GET(LV2.RES_ID,  :LANG_CODE) R2 ON 1=1
            LEFT JOIN RES_GET(LV3.RES_ID,  :LANG_CODE) R3 ON 1=1
            WHERE L.PARENT_ID = :YEAR_ID
              AND L.OBJ_TYPE_ID = 120
              AND L.DATE_DEL IS NULL
              AND V800.PARAM_ID = 800
              AND V800.IS_DEL = 0
              AND ((:I$EXAM_CODE IS NULL) OR (V800.VAL = :I$EXAM_CODE))
              AND V801.PARAM_ID = 801
              AND V801.IS_DEL = 0
              AND V802.PARAM_ID = 802
              AND V802.IS_DEL = 0
              AND V803.PARAM_ID = 803
              AND V803.IS_DEL = 0
              AND V804.PARAM_ID = 804
              AND V804.IS_DEL = 0
            ORDER BY V800.VAL
            INTO :EXAM_ID, :EXAM_CODE, :EXAM_STAGE, :EXAM_TYPE, :EXAM_SUBJECT, :EXAM_DATE
        DO
        BEGIN
            PUPIL_COUNT = 0;

            /* SCHOOLARS */

            SELECT COUNT(*)
            FROM LINKS L2
            INNER JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID
            INNER JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID
            INNER JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID
            INNER JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID
            INNER JOIN LINKS L120 ON L120.PARENT_ID = L10.OBJ_ID
            LEFT JOIN VALI VI ON VI.PARAM_ID = 1364 AND VI.OBJ_ID = L2.OBJ_ID AND VI.IS_DEL = 0
            WHERE L2.PARENT_ID = :DISTRICT_ID
              AND L2.OBJ_TYPE_ID = 2
              AND L2.DATE_DEL IS NULL
              AND L7.OBJ_TYPE_ID = 7
              AND L7.DATE_DEL IS NULL
              AND L8.OBJ_TYPE_ID = 8
              AND L8.DATE_DEL IS NULL
              AND L9.OBJ_TYPE_ID = 9
              AND L9.DATE_DEL IS NULL
              AND L10.OBJ_TYPE_ID = 10
              AND L10.DATE_DEL IS NULL
              AND L120.OBJ_TYPE_ID = 120
              AND L120.DATE_DEL IS NULL
              AND L120.OBJ_ID = :EXAM_ID
              AND ((:I$OU_GIA_CODE IS NULL) OR (VI.VAL = :I$OU_GIA_CODE))
            INTO :PUPIL_COUNT;

            /* VPL_PUPIL IN CLASS */

            SELECT :PUPIL_COUNT + COUNT(*)
            FROM LINKS L2
            INNER JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID
            INNER JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID
            INNER JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID
            INNER JOIN LINKS L126 ON L126.PARENT_ID = L9.OBJ_ID
            INNER JOIN LINKS L120 ON L120.PARENT_ID = L126.OBJ_ID
            LEFT JOIN VALI VI ON VI.PARAM_ID = 1364 AND VI.OBJ_ID = L2.OBJ_ID AND VI.IS_DEL = 0
            WHERE L2.PARENT_ID = :DISTRICT_ID
              AND L2.OBJ_TYPE_ID = 2
              AND L2.DATE_DEL IS NULL
              AND L7.OBJ_TYPE_ID = 7
              AND L7.DATE_DEL IS NULL
              AND L8.OBJ_TYPE_ID = 8
              AND L8.DATE_DEL IS NULL
              AND L9.OBJ_TYPE_ID = 9
              AND L9.DATE_DEL IS NULL
              AND L126.OBJ_TYPE_ID = 126
              AND L126.DATE_DEL IS NULL
              AND L120.OBJ_TYPE_ID = 120
              AND L120.DATE_DEL IS NULL
              AND L120.OBJ_ID = :EXAM_ID
              AND ((:I$OU_GIA_CODE IS NULL) OR (VI.VAL = :I$OU_GIA_CODE))
            INTO :PUPIL_COUNT;

            /* VPL_PUPIL IN VPL_CLASS */

            SELECT :PUPIL_COUNT + COUNT(*)
            FROM LINKS L2
            INNER JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID
            INNER JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID
            INNER JOIN LINKS L125 ON L125.PARENT_ID = L8.OBJ_ID
            INNER JOIN LINKS L126 ON L126.PARENT_ID = L125.OBJ_ID
            INNER JOIN LINKS L120 ON L120.PARENT_ID = L126.OBJ_ID
            LEFT JOIN VALI VI ON VI.PARAM_ID = 1364 AND VI.OBJ_ID = L2.OBJ_ID AND VI.IS_DEL = 0
            WHERE L2.PARENT_ID = :DISTRICT_ID
              AND L2.OBJ_TYPE_ID = 2
              AND L2.DATE_DEL IS NULL
              AND L7.OBJ_TYPE_ID IN (7, 502)
              AND L7.DATE_DEL IS NULL
              AND L8.OBJ_TYPE_ID = 8
              AND L8.DATE_DEL IS NULL
              AND L125.OBJ_TYPE_ID = 125
              AND L125.DATE_DEL IS NULL
              AND L126.OBJ_TYPE_ID = 126
              AND L126.DATE_DEL IS NULL
              AND L120.OBJ_TYPE_ID = 120
              AND L120.DATE_DEL IS NULL
              AND L120.OBJ_ID = :EXAM_ID
              AND ((:I$OU_GIA_CODE IS NULL) OR (VI.VAL = :I$OU_GIA_CODE))
            INTO :PUPIL_COUNT;

            /* VPL_PUPIL IN PUNKT_FOR_VPL */

            IF ((:I$OU_GIA_CODE IS NULL) OR (:DISTRICT_CODE * 1000 + 999 = :I$OU_GIA_CODE)) THEN
            BEGIN
                SELECT :PUPIL_COUNT + COUNT(*)
                FROM LINKS L124
                INNER JOIN LINKS L125 ON L125.PARENT_ID = L124.OBJ_ID
                INNER JOIN LINKS L126 ON L126.PARENT_ID = L125.OBJ_ID
                INNER JOIN LINKS L120 ON L120.PARENT_ID = L126.OBJ_ID
                WHERE L124.PARENT_ID = :DISTRICT_ID
                  AND L124.OBJ_TYPE_ID = 124
                  AND L124.DATE_DEL IS NULL
                  AND L125.OBJ_TYPE_ID = 125
                  AND L125.DATE_DEL IS NULL
                  AND L126.OBJ_TYPE_ID = 126
                  AND L126.DATE_DEL IS NULL
                  AND L120.OBJ_TYPE_ID = 120
                  AND L120.DATE_DEL IS NULL
                  AND L120.OBJ_ID = :EXAM_ID
                INTO :PUPIL_COUNT;
            END

            SUSPEND;
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CALC_AGE (
    DATE_FROM TIMESTAMP,
    DATE_TO TIMESTAMP)
RETURNS (
    AGE SMALLINT)
AS
begin
--select  (timestamp '2014-01-01 00:00' - timestamp '2008-12-31 00:00') / 365 from rdb$database
    AGE = NULL;

    SELECT
        EXTRACT(YEAR FROM :DATE_TO) -
        EXTRACT(YEAR FROM :DATE_FROM) +
        CASE
            WHEN EXTRACT (MONTH FROM :DATE_TO) >= EXTRACT (MONTH FROM :DATE_FROM)
                AND EXTRACT (DAY FROM :DATE_TO) >= EXTRACT (DAY FROM :DATE_FROM)
            THEN 0 ELSE -1
        END
    FROM RDB$DATABASE
    INTO :AGE;
    SUSPEND;
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CALC_JOB_OCCUPIED (
    I$JOB_ID BIGINT NOT NULL,
    I$SCH_ROW_ID BIGINT = null,
    I$SCH_RATE FLOAT = null)
AS
declare variable V$SCH_ID bigint;
declare variable V$SM double precision;
declare variable V$REASON_ID smallint;
declare variable V$REASON_CUR bigint;
declare variable V$POS_RATE double precision;
declare variable V$JOB_LV bigint;
declare variable V$JOB_NAME varchar(1000);
declare variable V$LINK_ID bigint;
begin
  /* https://jira.netrika.ru/browse/PARAGRAPH-299.
  Для мультипараграфа. ХП служит для вычисления индикатора занятости ставок для должности (13) с привязкой к элементу ШР
  I$SCH_ROW_ID - строка штатного расписания, опционально

  Результатом пересчета является флаг в поле REASON_ID записи должности:
  0 (серый) = нет активных ставок
  1 (оранжевый) = есть занятые ставки, но должности нет в действующем ШР, либо количество ставок не равно количеству ставок в действующем ШР
  2 (зеленый) = занятые ставки в пределах указанного количества ставок (меньше или равно)
  3 (красный) = количество занятых ставок превышает ставки в должности
  */

  SELECT FIRST 1 L13.LINK_ID, L13.REASON_ID, V58.LISTVAL_ID, V66.VAL, COALESCE(V62.VAL, 0)
  FROM LINKS L13
  LEFT JOIN VALL V58 ON V58.OBJ_ID = L13.OBJ_ID AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0 -- должность из списка (13)
  LEFT JOIN VALS V66 ON V66.OBJ_ID = L13.OBJ_ID AND V66.PARAM_ID = 66 AND V66.IS_DEL = 0 -- название должности  (13)
  LEFT JOIN VALF V62 ON V62.OBJ_ID = L13.OBJ_ID AND V62.PARAM_ID = 62 AND V62.IS_DEL = 0 -- кол-во ставок (13)
  WHERE L13.OBJ_ID = :I$JOB_ID AND L13.PARENT_TYPE_ID IN (2, 211)
  INTO :V$LINK_ID, :V$REASON_CUR, :V$JOB_LV, :V$JOB_NAME, :V$POS_RATE;

  IF(I$SCH_ROW_ID IS NULL) THEN
  BEGIN
    -- Если не указана строка ШР - надо ее отыскать среди действующих
    SELECT FIRST 1 L505.OBJ_ID, L506.OBJ_ID, V3493.VAL
    FROM LINKS L2
    JOIN LINKS L508 ON L508.PARENT_ID = L2.OBJ_ID AND L508.OBJ_TYPE_ID = 508 AND L508.DATE_DEL IS NULL
    JOIN LINKS L505 ON L505.PARENT_ID = L508.OBJ_ID AND L505.OBJ_TYPE_ID = 505 AND L505.DATE_DEL IS NULL
    JOIN VALL V3490 ON V3490.OBJ_ID = L505.OBJ_ID AND V3490.PARAM_ID = 3490 AND V3490.IS_DEL = 0 AND V3490.LISTVAL_ID = 11715  -- действующее ШР
    JOIN LINKS L506 ON L506.PARENT_ID = L505.OBJ_ID AND L506.OBJ_TYPE_ID = 506 AND L506.DATE_DEL IS NULL
    JOIN VALF V3493 ON V3493.OBJ_ID = L506.OBJ_ID AND V3493.PARAM_ID = 3493 AND V3493.IS_DEL = 0 -- кол-во ставок
    LEFT JOIN VALL V3492 ON V3492.OBJ_ID = L506.OBJ_ID AND V3492.PARAM_ID = 3492 AND V3492.IS_DEL = 0 -- должность из списка
    LEFT JOIN VALS V3494 ON V3494.OBJ_ID = L506.OBJ_ID AND V3494.PARAM_ID = 3494 AND V3494.IS_DEL =  0-- название должности
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      AND COALESCE(V3492.LISTVAL_ID, 0) = COALESCE(:V$JOB_LV, 0) AND UPPER(TRIM(V3494.VAL)) = UPPER(TRIM(:V$JOB_NAME))
    INTO :V$SCH_ID, :I$SCH_ROW_ID, :I$SCH_RATE;
  END

  -- Суммарное кол-во временно свободных ставок по должности
  SELECT VAL FROM VACANCY_NUM_TEMPFREE(:I$JOB_ID) INTO :V$SM;
  UPDATE OR INSERT INTO VALF (PARAM_ID, OBJ_ID, IS_DEL, VAL)
  VALUES (2851, :I$JOB_ID, 0, :V$SM);

  -- Ceммарное кол-во занятых ставок по должности
  SELECT VAL FROM VACANCY_NUM_OCCUPIED(:I$JOB_ID) INTO :V$SM;
  UPDATE OR INSERT INTO VALF (PARAM_ID, OBJ_ID, IS_DEL, VAL)
  VALUES (2850, :I$JOB_ID, 0, :V$SM);

  -- Найдем значение индикатора по количеству занятых ставок
  IF (I$SCH_ROW_ID IS NULL OR I$SCH_RATE <> V$POS_RATE) THEN
  BEGIN
    V$REASON_ID = 1;
  END
  ELSE IF (V$SM > 0) THEN
  BEGIN
    IF (V$SM > V$POS_RATE) THEN V$REASON_ID = 3;
    ELSE V$REASON_ID = 2;
  END
  ELSE
  BEGIN
    V$REASON_ID = 0;
  END

  IF (COALESCE(V$REASON_CUR, -1) <> COALESCE(V$REASON_ID, -1)) THEN
  BEGIN
    UPDATE LINKS L13
    SET REASON_ID = :V$REASON_ID
    WHERE L13.LINK_ID = :V$LINK_ID;
  END
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CALENDAR_PLAN_GET (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(4000))
AS
declare variable S varchar(4000);
declare variable S2 varchar(400);
declare variable S3 varchar(400);
declare variable V$PERIOD_ID bigint;
declare variable V$OBJ_ID bigint;
declare variable V$OU_ID bigint;
declare variable V$CY integer;
declare variable V$WD bigint;
declare variable V$YEAR_ID bigint;
declare variable N integer;
declare variable V$T1 time;
declare variable V$T2 time;
declare variable W1 integer;
declare variable W2 integer;
declare variable V$D1 date;
declare variable V$D2 date;
declare variable V$OU_TYPE varchar(10);
begin

  TAG_NAME = 'ou_type';
  V$OU_TYPE = (SELECT STATUS FROM OU_LICENCE_TYPE);
  VAL = V$OU_TYPE;
  SUSPEND;

  TAG_NAME = 'name';
  SELECT V.VAL
  FROM VALS V
  WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 3388 AND V.IS_DEL = 0
  INTO :VAL;
  SUSPEND;

  -- Учебный год
  TAG_NAME = 'year_id';
  VAL = NULL;
  SELECT V.LISTVAL_ID, C.VAL, LV.COST
  FROM VALL V
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V.LISTVAL_ID
  LEFT JOIN LISTVAL_TEXT(V.LISTVAL_ID) C ON 1 = 1
  WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 3389 AND V.IS_DEL = 0
  INTO :V$YEAR_ID, :S, :V$CY;
  VAL = V$YEAR_ID;
  SUSPEND;

  TAG_NAME = 'year_name';
  VAL = S;
  SUSPEND;

  TAG_NAME = 'order_num';
  VAL = NULL;
  SELECT V.VAL
  FROM VALS V
  WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 3391 AND V.IS_DEL = 0
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'order_date';
  VAL = NULL;
  SELECT C.RESULT
  FROM VALD V
  LEFT JOIN DATE2STR(V.VAL) C ON 1 = 1
  WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 3392 AND V.IS_DEL = 0
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'ou_name_full';
  VAL = NULL;
  SELECT V.VAL, LP2.PARENT_ID
  FROM LINKS LP2
  LEFT JOIN VALS V ON V.OBJ_ID = LP2.PARENT_ID AND V.PARAM_ID = 5 AND V.IS_DEL = 0
  WHERE LP2.OBJ_ID = :I$OBJ_ID AND LP2.PARENT_TYPE_ID = 2 AND LP2.DATE_DEL IS NULL
  INTO :VAL, :V$OU_ID;
  SUSPEND;

  TAG_NAME = 'signed_title';
  VAL = NULL;
  S = NULL;
  SELECT POST, F || ' ' || SUBSTRING(I FROM 1 FOR 1) || '.' || COALESCE(SUBSTRING(O FROM 1 FOR 1) || '.', '')
  FROM R_SPB_POST_DIRECTOR(:V$OU_ID, 1)
  INTO :VAL, :S;
  SUSPEND;
  TAG_NAME = 'signed_name';
  VAL = S;
  SUSPEND;

  -- Учебные периоды и каникулы
  TAG_NAME = 'plist::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L151.OBJ_ID, C.CAPTION
    FROM LINKS L151
    LEFT JOIN OBJECT_CAPTION_GET(L151.OBJ_ID) C ON 1 = 1
    WHERE L151.PARENT_ID = :I$OBJ_ID AND L151.OBJ_TYPE_ID = 151 AND L151.DATE_DEL IS NULL
    ORDER BY 2
    INTO :V$PERIOD_ID, :S
  DO
  BEGIN
    TAG_NAME = 'plist:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'plist:r:id';
    VAL = V$PERIOD_ID;
    SUSPEND;
    TAG_NAME = 'plist:r:name';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'plist:r:periods::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT L154.OBJ_ID, C.VAL, D1.RESULT, D2.RESULT, V3.LISTVAL_ID, V1.VAL, V2.VAL
      FROM LINKS L154
      LEFT JOIN VALD V1 ON V1.OBJ_ID = L154.OBJ_ID AND V1.PARAM_ID = 1169 AND V1.IS_DEL = 0
      LEFT JOIN VALD V2 ON V2.OBJ_ID = L154.OBJ_ID AND V2.PARAM_ID = 1174 AND V2.IS_DEL = 0
      LEFT JOIN VALL V3 ON V3.OBJ_ID = L154.OBJ_ID AND V3.PARAM_ID = 1170 AND V3.IS_DEL = 0
      LEFT JOIN DATE2STR(V1.VAL) D1 ON 1 = 1
      LEFT JOIN DATE2STR(V2.VAL) D2 ON 1 = 1
      LEFT JOIN LISTVAL_TEXT(V3.LISTVAL_ID) C ON 1 = 1
      WHERE L154.PARENT_ID = :V$PERIOD_ID AND L154.OBJ_TYPE_ID = 154 AND L154.DATE_DEL IS NULL
      ORDER BY V1.VAL
      INTO :V$OBJ_ID, :S, :S2, :S3, :V$WD, :V$D1, :V$D2
    DO
    BEGIN
      IF(S IS NULL OR S2 IS NULL OR S3 IS NULL) THEN EXCEPTION DATA_ERROR 'В одном из учебных периодов не заданы тип, дата начала или дата окончания';
      IF(V$D2 <= V$D1) THEN EXCEPTION DATA_ERROR 'Нарушена хронология в расписании учебных периодов';
      IF(V$D1 IS NULL OR V$D2 IS NULL) THEN EXCEPTION DATA_ERROR 'Не заполнены даты в расписании учебных периодов';
      TAG_NAME = 'plist:r:periods:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'plist:r:periods:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'plist:r:periods:r:type_id';
      VAL = V$WD;
      SUSPEND;
      TAG_NAME = 'plist:r:periods:r:name';
      VAL = S;
      SUSPEND;
      TAG_NAME = 'plist:r:periods:r:date_from';
      VAL = S2;
      SUSPEND;
      TAG_NAME = 'plist:r:periods:r:date_to';
      VAL = S3;
      SUSPEND;
    END
    TAG_NAME = 'plist:r:vacations::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT L450.OBJ_ID, V3.VAL, D1.RESULT, D2.RESULT
      FROM LINKS L450
      LEFT JOIN VALD V1 ON V1.OBJ_ID = L450.OBJ_ID AND V1.PARAM_ID = 3263 AND V1.IS_DEL = 0
      LEFT JOIN VALD V2 ON V2.OBJ_ID = L450.OBJ_ID AND V2.PARAM_ID = 3264 AND V2.IS_DEL = 0
      LEFT JOIN VALS V3 ON V3.OBJ_ID = L450.OBJ_ID AND V3.PARAM_ID = 3265 AND V3.IS_DEL = 0
      LEFT JOIN DATE2STR(V1.VAL) D1 ON 1 = 1
      LEFT JOIN DATE2STR(V2.VAL) D2 ON 1 = 1
      WHERE L450.PARENT_ID = :V$PERIOD_ID AND L450.OBJ_TYPE_ID = 450 AND L450.DATE_DEL IS NULL
      ORDER BY V1.VAL
      INTO :V$OBJ_ID, :S, :S2, :S3
    DO
    BEGIN
      IF(S2 IS NULL OR S3 IS NULL) THEN EXCEPTION DATA_ERROR 'В одном из описаний каникул не заданы дата начала или дата окончания';
      TAG_NAME = 'plist:r:vacations:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'plist:r:vacations:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'plist:r:vacations:r:name';
      VAL = S;
      SUSPEND;
      TAG_NAME = 'plist:r:vacations:r:date_from';
      VAL = S2;
      SUSPEND;
      TAG_NAME = 'plist:r:vacations:r:date_to';
      VAL = S3;
      SUSPEND;
    END
  END

  TAG_NAME = 'days::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT D1.RESULT, V3394.LISTVAL_ID, V3395.VAL
    FROM LINKS L486
    JOIN VALD V3393 ON V3393.OBJ_ID = L486.OBJ_ID AND V3393.PARAM_ID = 3393 AND V3393.IS_DEL = 0
    JOIN VALL V3394 ON V3394.OBJ_ID = L486.OBJ_ID AND V3394.PARAM_ID = 3394 AND V3394.IS_DEL = 0
    LEFT JOIN VALS V3395 ON V3395.OBJ_ID = L486.OBJ_ID AND V3395.PARAM_ID = 3395 AND V3395.IS_DEL = 0
    LEFT JOIN DATE2STR(V3393.VAL) D1 ON 1 = 1
    WHERE L486.PARENT_ID = :I$OBJ_ID AND L486.OBJ_TYPE_ID = 486 AND L486.DATE_DEL IS NULL
    INTO :S2, :V$PERIOD_ID, :S
  DO
  BEGIN
    TAG_NAME = 'days:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'days:r:date';
    VAL = S2;
    SUSPEND;
    TAG_NAME = 'days:r:type';
    VAL = V$PERIOD_ID;
    SUSPEND;
    TAG_NAME = 'days:r:name';
    VAL = S;
    SUSPEND;
  END

  -- Предполагается что ОП должна быть одна на весь уровень
  TAG_NAME = 'op::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L57.OBJ_ID, C.CAPTION, V1594.LISTVAL_ID
    FROM LINKS L69
    JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
    JOIN VALI V3115 ON V3115.OBJ_ID = L57.OBJ_ID AND V3115.PARAM_ID = 3115 AND V3115.IS_DEL = 0 AND V3115.VAL = :V$CY
    JOIN VALL V1594 ON V1594.OBJ_ID = L57.OBJ_ID AND V1594.PARAM_ID = 1594 AND V1594.IS_DEL = 0
    LEFT JOIN OBJECT_CAPTION_GET(L57.OBJ_ID) C ON 1 = 1
    WHERE L69.PARENT_ID = :V$OU_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL
    ORDER BY 2
    INTO :V$OBJ_ID, :S, :V$PERIOD_ID
  DO
  BEGIN
    TAG_NAME = 'op:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'op:r:id';
    VAL = V$PERIOD_ID;
    SUSPEND;
    TAG_NAME = 'op:r:level_id';
    VAL = V$PERIOD_ID;
    SUSPEND;
    TAG_NAME = 'op:r:name';
    VAL = S;
    SUSPEND;
    S = '';
    N = NULL;
    FOR
      SELECT L400.OBJ_ID, C.CAPTION
      FROM LINKS L400
      JOIN VALL V3013 ON V3013.OBJ_ID = L400.OBJ_ID AND V3013.PARAM_ID = 3013 AND V3013.IS_DEL = 0 AND V3013.LISTVAL_ID = 11715
      LEFT JOIN OBJECT_CAPTION_GET(L400.OBJ_ID) C ON 1 = 1
      WHERE L400.PARENT_ID = :V$OBJ_ID AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL
      ORDER BY 2
      INTO :V$PERIOD_ID, :S2
    DO
    BEGIN
      IF(S <> '') THEN S = S || ', ';
      S = S || S2;
    END
    FOR
      SELECT DISTINCT V2837.LISTVAL_ID
      FROM LINKS L400
      JOIN VALL V3013 ON V3013.OBJ_ID = L400.OBJ_ID AND V3013.PARAM_ID = 3013 AND V3013.IS_DEL = 0 AND V3013.LISTVAL_ID = 11715
      JOIN LINKS L54 ON L54.PARENT_ID = L400.OBJ_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
      JOIN VALL V2837 ON V2837.OBJ_ID = L54.OBJ_ID AND V2837.PARAM_ID = 2837 AND V2837.IS_DEL = 0
      WHERE L400.PARENT_ID = :V$OBJ_ID AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL
      INTO :V$WD
    DO
    BEGIN
      IF(V$WD = 11718) THEN V$WD = 5; ELSE V$WD = 6;
      IF(N IS NULL) THEN N = V$WD;
      ELSE IF(N <> V$WD) THEN N = -1;
    END
    TAG_NAME = 'op:r:weekdays';
    IF(N < 0) THEN N = NULL;
    VAL = N; -- варианты: NULL, 5, 6
    SUSPEND;
    -- Количество учебных недель
    W1 = NULL;
    W2 = NULL;
    SELECT MIN(V382.VAL), MAX(V382.VAL)
    FROM LINKS L400
    JOIN VALL V3013 ON V3013.OBJ_ID = L400.OBJ_ID AND V3013.PARAM_ID = 3013 AND V3013.IS_DEL = 0 AND V3013.LISTVAL_ID = 11715
    JOIN LINKS L54 ON L54.PARENT_ID = L400.OBJ_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
    JOIN VALI V382 ON V382.OBJ_ID = L54.OBJ_ID AND V382.PARAM_ID = 382 AND V382.IS_DEL = 0
    WHERE L400.PARENT_ID = :V$OBJ_ID AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL
    INTO :W1, :W2;
    TAG_NAME = 'op:r:weeks_min';
    VAL = W1;
    SUSPEND;
    TAG_NAME = 'op:r:weeks_max';
    VAL = W2;
    SUSPEND;
    TAG_NAME = 'op:r:plans';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'op:r:grade_names';
    VAL = '';
    FOR
      SELECT DISTINCT C.SORT_ORDER, C.CAPTION
      FROM LINKS L400
      JOIN VALL V3013 ON V3013.OBJ_ID = L400.OBJ_ID AND V3013.PARAM_ID = 3013 AND V3013.IS_DEL = 0 AND V3013.LISTVAL_ID = 11715
      JOIN LINKS L54 ON L54.PARENT_ID = L400.OBJ_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
      JOIN LINKS L256 ON L256.PARENT_ID = L54.OBJ_ID AND L256.OBJ_TYPE_ID = 256 AND L256.DATE_DEL IS NULL
      JOIN LINKS L10 ON L10.PARENT_ID = L256.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      JOIN LINKS LP9 ON LP9.OBJ_ID = L10.OBJ_ID AND LP9.PARENT_TYPE_ID = 9 AND LP9.DATE_DEL IS NULL
      LEFT JOIN OBJECT_CAPTION_GET(LP9.PARENT_ID) C ON 1 = 1
      WHERE L400.PARENT_ID = :V$OBJ_ID AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL
      ORDER BY 1, 2
      INTO :N, :S2
    DO
    BEGIN
      IF(VAL <> '') THEN VAL = VAL || ', ';
      VAL = VAL || S2;
    END
    SUSPEND;
    TAG_NAME = 'op:r:stage_names';
    VAL = '';
    FOR
      SELECT DISTINCT C.SORT_ORDER, C.CAPTION
      FROM LINKS L400
      JOIN VALL V3013 ON V3013.OBJ_ID = L400.OBJ_ID AND V3013.PARAM_ID = 3013 AND V3013.IS_DEL = 0 AND V3013.LISTVAL_ID = 11715
      JOIN LINKS L54 ON L54.PARENT_ID = L400.OBJ_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
      LEFT JOIN OBJECT_CAPTION_GET(L54.OBJ_ID) C ON 1 = 1
      WHERE L400.PARENT_ID = :V$OBJ_ID AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL
      ORDER BY 1, 2
      INTO :N, :S2
    DO
    BEGIN
      IF(VAL <> '') THEN VAL = VAL || ', ';
      VAL = VAL || S2;
    END
    SUSPEND;
    -- Время начала и окончания смотрим по расписанию, к которому прикреплена ОП, в том же учебном году
    V$T1 = NULL;
    V$T2 = NULL;
    SELECT MIN(V3080.VAL), MAX(V3081.VAL)
    FROM LINKS L68
    JOIN LINKS L3 ON L3.PARENT_ID = L68.OBJ_ID AND L3.OBJ_TYPE_ID = 3 AND L3.DATE_DEL IS NULL
    JOIN VALL V37 ON V37.OBJ_ID = L3.OBJ_ID AND V37.PARAM_ID = 37 AND V37.IS_DEL = 0 AND V37.LISTVAL_ID = :V$YEAR_ID
    JOIN LINKS L57 ON L57.PARENT_ID = L3.OBJ_ID AND L57.OBJ_ID = :V$OBJ_ID AND L57.DATE_DEL IS NULL -- эта ОП
    LEFT JOIN VALT V3080 ON V3080.OBJ_ID = L3.OBJ_ID AND V3080.PARAM_ID = 3080 AND V3080.IS_DEL = 0
    LEFT JOIN VALT V3081 ON V3081.OBJ_ID = L3.OBJ_ID AND V3081.PARAM_ID = 3081 AND V3081.IS_DEL = 0
    WHERE L68.PARENT_ID = :V$OU_ID AND L68.OBJ_TYPE_ID = 68 AND L68.DATE_DEL IS NULL
    INTO :V$T1, :V$T2;
    IF(V$T2 <= V$T1) THEN EXCEPTION DATA_ERROR 'Нарушена хронология в указании рабочего времени (времени начала и окончания занятий)';
    TAG_NAME = 'op:r:time_start';
    VAL = V$T1;
    SUSPEND;
    TAG_NAME = 'op:r:time_end';
    VAL = V$T2;
    SUSPEND;
    TAG_NAME = 'op:r:period_id';
    VAL = NULL;
    SELECT FIRST 1 J.PERIOD_ID, COUNT(DISTINCT L10.OBJ_ID)
    FROM LINKS L400
    JOIN VALL V3013 ON V3013.OBJ_ID = L400.OBJ_ID AND V3013.PARAM_ID = 3013 AND V3013.IS_DEL = 0 AND V3013.LISTVAL_ID = 11715
    JOIN LINKS L54 ON L54.PARENT_ID = L400.OBJ_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
    JOIN LINKS L256 ON L256.PARENT_ID = L54.OBJ_ID AND L256.OBJ_TYPE_ID = 256 AND L256.DATE_DEL IS NULL
    JOIN LINKS L10 ON L10.PARENT_ID = L256.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    JOIN LINKS LPG ON LPG.OBJ_ID = L10.OBJ_ID AND LPG.PARENT_TYPE_ID IN (9, 179, 256) AND LPG.DATE_DEL IS NULL
    JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.YEAR_ID = :V$YEAR_ID AND J.GRADE_ID = LPG.PARENT_ID AND J.JOURNAL_TYPE = 0
    WHERE L400.PARENT_ID = :V$OBJ_ID AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL
    GROUP BY 1
    ORDER BY 2 DESC
    INTO :VAL, :N;
    SUSPEND;
  END

  -- Количество классов в параллелях, по уровням образования
  TAG_NAME = 'classnums::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT C2.SORT_ORDER, C1.CAPTION, C2.CAPTION, COUNT(*)
    FROM LINKS L7
    LEFT JOIN OBJECT_CAPTION_GET(L7.OBJ_ID) C1 ON 1 = 1
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    LEFT JOIN OBJECT_CAPTION_GET(L8.OBJ_ID) C2 ON 1 = 1
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
    WHERE L7.PARENT_ID = :V$OU_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    GROUP BY 1, 2, 3
    ORDER BY 1
    INTO :V$WD, :S, :S2, :N
  DO
  BEGIN
    TAG_NAME = 'classnums:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'classnums:r:level';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'classnums:r:stage';
    VAL = S2;
    SUSPEND;
    TAG_NAME = 'classnums:r:n';
    VAL = N;
    SUSPEND;
  END

  -- Расписание экзаменов и зачетов для СПО
  TAG_NAME = 'attperiods::json&colon;array';
  VAL = 1;
  SUSPEND;
  N = 0;
  FOR
    SELECT V3396.VAL, MAX(V3397.VAL)
    FROM LINKS L481
    JOIN LINKS L151 ON L151.PARENT_ID = L481.OBJ_ID AND L151.OBJ_TYPE_ID = 151 AND L151.DATE_DEL IS NULL
    JOIN LINKS L487 ON L487.PARENT_ID = L151.OBJ_ID AND L487.OBJ_TYPE_ID = 487 AND L487.DATE_DEL IS NULL
    JOIN VALD V3396 ON V3396.OBJ_ID = L487.OBJ_ID AND V3396.PARAM_ID = 3396 AND V3396.IS_DEL = 0
    JOIN VALD V3397 ON V3397.OBJ_ID = L487.OBJ_ID AND V3397.PARAM_ID = 3397 AND V3397.IS_DEL = 0
    WHERE L481.PARENT_ID = :V$OU_ID AND L481.OBJ_TYPE_ID = 481 AND L481.OBJ_ID = :I$OBJ_ID AND L481.DATE_DEL IS NULL
    GROUP BY 1
    ORDER BY 1
    INTO :V$D1, :V$D2
  DO
  BEGIN
    IF(V$D2 <= V$D1) THEN EXCEPTION DATA_ERROR 'Нарушена хронология в расписании аттестационных периодов';
    TAG_NAME = 'attperiods:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'attperiods:r:date_from';
    VAL = (SELECT RESULT FROM DATE2STR(:V$D1));
    SUSPEND;
    TAG_NAME = 'attperiods:r:date_to';
    VAL = (SELECT RESULT FROM DATE2STR(:V$D2));
    SUSPEND;
    N = N + 1;
  END
  IF(V$OU_TYPE = 'C' AND N = 0) THEN EXCEPTION DATA_ERROR 'Внесите расписание аттестационных периодов';

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CAPTION_VIRTUAL_EXTERNAL_CLASS (
    I$OBJ_ID BIGINT,
    I$CAPTION VARCHAR(4000))
RETURNS (
    CAPTION VARCHAR(4000),
    SORT_ORDER SMALLINT)
AS
DECLARE VARIABLE V$TAG VARCHAR(100);
DECLARE VARIABLE V$OBJ_ID BIGINT;
BEGIN
    CAPTION = I$CAPTION;
    V$TAG = NULL;
    SORT_ORDER = 0;
    V$OBJ_ID = NULL;

    FOR SELECT FIRST 1 PARENT_ID
        FROM LINKS
        WHERE OBJ_ID = :I$OBJ_ID
          AND DATE_DEL IS NULL
          AND PARENT_TYPE_ID = 8
        INTO :V$OBJ_ID
    DO
    BEGIN
        FOR SELECT LV.TAG, LV.SORT_ORDER
            FROM VALL V
            INNER JOIN LISTVALS LV ON V.LISTVAL_ID = LV.LISTVAL_ID
            WHERE V.PARAM_ID = 49
              AND V.OBJ_ID = :V$OBJ_ID
            INTO :V$TAG, :SORT_ORDER
        DO
        BEGIN
            IF ((V$TAG IS NULL) OR (V$TAG = '')) THEN
            BEGIN
                CAPTION = I$CAPTION;
            END
            ELSE
            BEGIN
                IF (:I$CAPTION = '<  ...  >') THEN
                BEGIN
                    CAPTION = V$TAG;
                END
                ELSE
                BEGIN
                    CAPTION = V$TAG || ' ' || I$CAPTION;
                END
            END
        END
    END

    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CARDS_LIST_PERSONS (
    PARENT_ID BIGINT,
    PARENT_TYPE_ID BIGINT)
RETURNS (
    CAPTION VARCHAR(1000),
    OBJ_ID BIGINT,
    REG_ID VARCHAR(100))
AS
begin
  -- Для сотрудников PARENT_ID будет -1, подменяем ID ОУ
  IF(PARENT_ID < 0) THEN
  BEGIN
      SELECT FIRST 1 OBJ_ID
      FROM LINKS
      WHERE PARENT_ID IS NULL AND OBJ_TYPE_ID = 2 AND DATE_DEL IS NULL
      INTO :PARENT_ID;
  END

  -- Сначала возвращаем основной состав (сотрудники)
  FOR
      SELECT L14.OBJ_ID, C.CAPTION, V2915.VAL
      FROM LINKS L14
      -- Согласие на выдачу карты
      JOIN VALL V2856 ON V2856.OBJ_ID = L14.OBJ_ID AND V2856.PARAM_ID = 2856 AND V2856.IS_DEL = 0 AND V2856.LISTVAL_ID = 2
      -- Есть RegID
      JOIN VALS V2915 ON V2915.OBJ_ID = L14.OBJ_ID AND V2915.PARAM_ID = 2915 AND V2915.IS_DEL = 0
      -- Основной карты нет
      LEFT JOIN VALS V2857 ON V2857.OBJ_ID = L14.OBJ_ID AND V2857.PARAM_ID = 2857 AND V2857.IS_DEL = 0
      -- ФИО
      LEFT JOIN OBJECT_CAPTION_GET(L14.OBJ_ID) C ON 1 = 1
      WHERE L14.PARENT_ID = :PARENT_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL AND V2857.VAL IS NULL
      -- Добавляем сюда подразделения - про запас
      UNION
      SELECT L14.OBJ_ID, C.CAPTION, V2915.VAL
      FROM LINKS L211
      JOIN LINKS L14 ON L14.PARENT_ID = L211.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
      -- Согласие на выдачу карты
      JOIN VALL V2856 ON V2856.OBJ_ID = L14.OBJ_ID AND V2856.PARAM_ID = 2856 AND V2856.IS_DEL = 0 AND V2856.LISTVAL_ID = 2
      -- Есть RegID
      JOIN VALS V2915 ON V2915.OBJ_ID = L14.OBJ_ID AND V2915.PARAM_ID = 2915 AND V2915.IS_DEL = 0
      -- Основной карты нет
      LEFT JOIN VALS V2857 ON V2857.OBJ_ID = L14.OBJ_ID AND V2857.PARAM_ID = 2857 AND V2857.IS_DEL = 0
      -- ФИО
      LEFT JOIN OBJECT_CAPTION_GET(L14.OBJ_ID) C ON 1 = 1
      WHERE L211.PARENT_ID = :PARENT_ID AND L211.OBJ_TYPE_ID = 211 AND L211.DATE_DEL IS NULL AND V2857.VAL IS NULL
      ORDER BY 2
      INTO :OBJ_ID, :CAPTION, :REG_ID
  DO
  BEGIN
      SUSPEND;
  END

  -- Учащиеся
  FOR
      SELECT L10.OBJ_ID, C.CAPTION, V2912.VAL
      FROM LINKS L10
      -- Согласие на выдачу карты
      JOIN VALL V2854 ON V2854.OBJ_ID = L10.OBJ_ID AND V2854.PARAM_ID = 2854 AND V2854.IS_DEL = 0 AND V2854.LISTVAL_ID = 2
      -- Есть RegID
      JOIN VALS V2912 ON V2912.OBJ_ID = L10.OBJ_ID AND V2912.PARAM_ID = 2912 AND V2912.IS_DEL = 0
      -- Основной карты нет
      LEFT JOIN VALS V2855 ON V2855.OBJ_ID = L10.OBJ_ID AND V2855.PARAM_ID = 2855 AND V2855.IS_DEL = 0
      -- ФИО
      LEFT JOIN OBJECT_CAPTION_GET(L10.OBJ_ID) C ON 1 = 1
      WHERE L10.PARENT_ID = :PARENT_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL AND V2855.VAL IS NULL
      ORDER BY 2
      INTO :OBJ_ID, :CAPTION, :REG_ID
  DO
  BEGIN
      SUSPEND;
  END

  -- В последнюю очередь постоянные сопровождающие
  FOR                                                                                        
      SELECT L10.OBJ_ID, C.CAPTION || ' (' || C10.CAPTION || ')', V2917.VAL
      FROM LINKS L10
      JOIN LINKS L20 ON L20.PARENT_ID = L10.OBJ_ID AND L20.OBJ_TYPE_ID = 20 AND L20.DATE_DEL IS NULL
      -- Постоянный сопровождающий
      JOIN VALL V2818 ON V2818.OBJ_ID = L20.OBJ_ID AND V2818.PARAM_ID = 2818 AND V2818.IS_DEL = 0 AND V2818.LISTVAL_ID = 2
      -- Есть RegID
      JOIN VALS V2917 ON V2917.OBJ_ID = L20.OBJ_ID AND V2917.PARAM_ID = 2917 AND V2917.IS_DEL = 0
      -- Основной карты нет
      LEFT JOIN VALS V2918 ON V2918.OBJ_ID = L20.OBJ_ID AND V2918.PARAM_ID = 2918 AND V2918.IS_DEL = 0
      -- ФИО
      LEFT JOIN OBJECT_CAPTION_GET(L10.OBJ_ID) C10 ON 1 = 1
      LEFT JOIN OBJECT_CAPTION_GET(L20.OBJ_ID) C ON 1 = 1
      WHERE L10.PARENT_ID = :PARENT_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL AND V2918.VAL IS NULL
      ORDER BY C.CAPTION
      INTO :OBJ_ID, :CAPTION, :REG_ID
  DO
  BEGIN
      SUSPEND;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CARDS_LIST_SUBS (
    PARENT_ID BIGINT,
    PARENT_TYPE_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    OBJ_TYPE SMALLINT,
    CAPTION VARCHAR(1000),
    GRADE_NAME VARCHAR(1000),
    SORT_ORDER DOUBLE PRECISION,
    CARD_ALLOWED SMALLINT,
    REG_ID VARCHAR(100),
    CARD_ID VARCHAR(100),
    CARD_DATE DATE,
    TEMP_CARD_ID VARCHAR(100),
    TEMP_CARD_DATE DATE)
AS
declare variable STUFF_PARENT_ID bigint;
begin

  -- Сейчас промежуточно-костыльный вариант, идем не по реестру карт, а по текущим номерам карт в персонах
  -- весной 2023 надо будет сформировать реестр и забыть о старой схеме

  IF(PARENT_TYPE_ID IN (10, 14, 20)) THEN
  BEGIN

      -- Если выбрана персона, выводим данные по ней
      GRADE_NAME = '';
      OBJ_TYPE = -1;

      FOR
          SELECT P.OBJ_ID, V1.VAL || ' ' || V2.VAL || COALESCE(' ' || V3.VAL, ''), 0, IIF(V2856.LISTVAL_ID = 2, 1, 0), V2915.VAL, V2857.VAL, V2857.DATE_MODIFY
          FROM OBJECTS P
          JOIN VALS V1 ON V1.OBJ_ID = P.OBJ_ID AND V1.PARAM_ID IN (55, 59, 128) AND V1.IS_DEL = 0
          JOIN VALS V2 ON V2.OBJ_ID = P.OBJ_ID AND V2.PARAM_ID IN (56, 60, 129) AND V2.IS_DEL = 0
          LEFT JOIN VALS V3 ON V3.OBJ_ID = P.OBJ_ID AND V3.PARAM_ID IN (57, 61, 130) AND V3.IS_DEL = 0
          -- Согласие на выдачу карты или флаг постоянного сопровождающего
          LEFT JOIN VALL V2856 ON V2856.OBJ_ID = P.OBJ_ID AND V2856.PARAM_ID IN (2854, 2856, 2818) AND V2856.IS_DEL = 0
          -- RegID
          LEFT JOIN VALS V2915 ON V2915.OBJ_ID = P.OBJ_ID AND V2915.PARAM_ID IN (2912, 2915, 2917) AND V2915.IS_DEL = 0
          -- ID основной карты
          LEFT JOIN VALS V2857 ON V2857.OBJ_ID = P.OBJ_ID AND V2857.PARAM_ID IN (2855, 2857, 2918) AND V2857.IS_DEL = 0
          WHERE P.OBJ_ID = :PARENT_ID
          INTO :OBJ_ID, :CAPTION, :SORT_ORDER, :CARD_ALLOWED, :REG_ID, :CARD_ID, :CARD_DATE
      DO
      BEGIN
          -- Подменяем дату на правильную, если есть в реестре
          SELECT FIRST 1 V3269.VAL
          FROM LINKS L455
          JOIN VALS V3273 ON V3273.OBJ_ID = L455.OBJ_ID AND V3273.PARAM_ID = 3273 AND V3273.IS_DEL = 0 AND V3273.SVAL = :CARD_ID
          JOIN VALDT V3269 ON V3269.OBJ_ID = L455.OBJ_ID AND V3269.PARAM_ID = 3269 AND V3269.IS_DEL = 0
          LEFT JOIN VALDT V3271 ON V3271.OBJ_ID = L455.OBJ_ID AND V3271.PARAM_ID = 3271 AND V3271.IS_DEL = 0
          WHERE L455.PARENT_ID = :OBJ_ID AND L455.OBJ_TYPE_ID = 455 AND L455.DATE_DEL IS NULL AND V3271.VAL IS NULL
          ORDER BY L455.OBJ_ID DESC
          INTO :CARD_DATE;

          SUSPEND;
      END

  END
  ELSE BEGIN

      -- Выбрана группа или ОУ целиком, выбираем всех
      -- Выбраны все сотрудники ОУ
      GRADE_NAME = 'Сотрудники';
      OBJ_TYPE = 0;

      IF(PARENT_ID > 0) THEN STUFF_PARENT_ID = PARENT_ID;
      ELSE
      BEGIN
          SELECT FIRST 1 OBJ_ID
          FROM LINKS
          WHERE PARENT_ID IS NULL AND OBJ_TYPE_ID = 2 AND DATE_DEL IS NULL
          INTO :STUFF_PARENT_ID;
      END

      FOR
          SELECT L14.OBJ_ID, C.CAPTION, 0, IIF(V2856.LISTVAL_ID = 2, 1, 0), CAST(V2915.VAL AS VARCHAR(100)), CAST(V2857.VAL AS VARCHAR(100)), V2857.DATE_MODIFY
          FROM LINKS L14
          -- Согласие на выдачу карты
          JOIN VALL V2856 ON V2856.OBJ_ID = L14.OBJ_ID AND V2856.PARAM_ID = 2856 AND V2856.IS_DEL = 0 -- AND V2856.LISTVAL_ID = 2
          -- Есть RegID
          LEFT JOIN VALS V2915 ON V2915.OBJ_ID = L14.OBJ_ID AND V2915.PARAM_ID = 2915 AND V2915.IS_DEL = 0
          -- Основная карта
          LEFT JOIN VALS V2857 ON V2857.OBJ_ID = L14.OBJ_ID AND V2857.PARAM_ID = 2857 AND V2857.IS_DEL = 0
          -- ФИО
          LEFT JOIN OBJECT_CAPTION_GET(L14.OBJ_ID) C ON 1 = 1
          WHERE L14.PARENT_ID = :STUFF_PARENT_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
          -- Добавляем сюда подразделения - про запас
          UNION
          SELECT L14.OBJ_ID, C.CAPTION, 0, IIF(V2856.LISTVAL_ID = 2, 1, 0), CAST(V2915.VAL AS VARCHAR(100)), CAST(V2857.VAL AS VARCHAR(100)), V2857.DATE_MODIFY
          FROM LINKS L211
          JOIN LINKS L14 ON L14.PARENT_ID = L211.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
          -- Согласие на выдачу карты
          JOIN VALL V2856 ON V2856.OBJ_ID = L14.OBJ_ID AND V2856.PARAM_ID = 2856 AND V2856.IS_DEL = 0 -- AND V2856.LISTVAL_ID = 2
          -- Есть RegID
          LEFT JOIN VALS V2915 ON V2915.OBJ_ID = L14.OBJ_ID AND V2915.PARAM_ID = 2915 AND V2915.IS_DEL = 0
          -- Основная карта
          LEFT JOIN VALS V2857 ON V2857.OBJ_ID = L14.OBJ_ID AND V2857.PARAM_ID = 2857 AND V2857.IS_DEL = 0
          -- ФИО
          LEFT JOIN OBJECT_CAPTION_GET(L14.OBJ_ID) C ON 1 = 1
          WHERE L211.PARENT_ID = :STUFF_PARENT_ID AND L211.OBJ_TYPE_ID = 211 AND L211.DATE_DEL IS NULL
          ORDER BY 2
          INTO :OBJ_ID, :CAPTION, :SORT_ORDER, :CARD_ALLOWED, :REG_ID, :CARD_ID, :CARD_DATE
      DO
      BEGIN
          -- Подменяем дату на правильную, если есть в реестре
          SELECT FIRST 1 V3269.VAL
          FROM LINKS L455
          JOIN VALS V3273 ON V3273.OBJ_ID = L455.OBJ_ID AND V3273.PARAM_ID = 3273 AND V3273.IS_DEL = 0 AND V3273.SVAL = :CARD_ID
          JOIN VALDT V3269 ON V3269.OBJ_ID = L455.OBJ_ID AND V3269.PARAM_ID = 3269 AND V3269.IS_DEL = 0
          LEFT JOIN VALDT V3271 ON V3271.OBJ_ID = L455.OBJ_ID AND V3271.PARAM_ID = 3271 AND V3271.IS_DEL = 0
          WHERE L455.PARENT_ID = :OBJ_ID AND L455.OBJ_TYPE_ID = 455 AND L455.DATE_DEL IS NULL AND V3271.VAL IS NULL
          ORDER BY L455.OBJ_ID DESC
          INTO :CARD_DATE;

          SUSPEND;
      END

      -- Учащиеся и постоянные сопровождающие
      IF(PARENT_TYPE_ID = 2) THEN
      BEGIN

          -- Все учащиеся и сопровождающие в школе
          OBJ_TYPE = 1;

          FOR
              SELECT L10.OBJ_ID, C.CAPTION, CG.SORT_ORDER, CG.CAPTION,
                  IIF(V2854.LISTVAL_ID = 2, 1, 0), CAST(V2912.VAL AS VARCHAR(100)), CAST(V2855.VAL AS VARCHAR(100)), V2855.DATE_MODIFY
              FROM LINKS L7
              JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
              JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 125, 187) AND L9.DATE_DEL IS NULL
              JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
              -- Согласие на выдачу карты
              JOIN VALL V2854 ON V2854.OBJ_ID = L10.OBJ_ID AND V2854.PARAM_ID = 2854 AND V2854.IS_DEL = 0 -- AND V2854.LISTVAL_ID = 2
              -- Есть RegID
              LEFT JOIN VALS V2912 ON V2912.OBJ_ID = L10.OBJ_ID AND V2912.PARAM_ID = 2912 AND V2912.IS_DEL = 0
              -- Основная карта
              LEFT JOIN VALS V2855 ON V2855.OBJ_ID = L10.OBJ_ID AND V2855.PARAM_ID = 2855 AND V2855.IS_DEL = 0
              -- ФИО
              LEFT JOIN OBJECT_CAPTION_GET(L10.OBJ_ID, 23) C ON 1 = 1
              LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) CG ON 1 = 1
              WHERE L7.PARENT_ID = :PARENT_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
              ORDER BY 2
              INTO :OBJ_ID, :CAPTION, :SORT_ORDER, :GRADE_NAME, :CARD_ALLOWED, :REG_ID, :CARD_ID, :CARD_DATE
          DO
          BEGIN
              -- Подменяем дату на правильную, если есть в реестре
              SELECT FIRST 1 V3269.VAL
              FROM LINKS L455
              JOIN VALS V3273 ON V3273.OBJ_ID = L455.OBJ_ID AND V3273.PARAM_ID = 3273 AND V3273.IS_DEL = 0 AND V3273.SVAL = :CARD_ID
              JOIN VALDT V3269 ON V3269.OBJ_ID = L455.OBJ_ID AND V3269.PARAM_ID = 3269 AND V3269.IS_DEL = 0
              LEFT JOIN VALDT V3271 ON V3271.OBJ_ID = L455.OBJ_ID AND V3271.PARAM_ID = 3271 AND V3271.IS_DEL = 0
              WHERE L455.PARENT_ID = :OBJ_ID AND L455.OBJ_TYPE_ID = 455 AND L455.DATE_DEL IS NULL AND V3271.VAL IS NULL
              ORDER BY L455.OBJ_ID DESC
              INTO :CARD_DATE;

              SUSPEND;
          END

          GRADE_NAME = 'Сопровождающие';
          OBJ_TYPE = 2;
          FOR
              SELECT L20.OBJ_ID, C.CAPTION, 2, IIF(V2818.LISTVAL_ID = 2, 1, 0), CAST(V2917.VAL AS VARCHAR(100)), CAST(V2918.VAL AS VARCHAR(100)), V2918.DATE_MODIFY
              FROM LINKS L7
              JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
              JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 125, 187) AND L9.DATE_DEL IS NULL
              JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
              JOIN LINKS L20 ON L20.PARENT_ID = L10.OBJ_ID AND L20.OBJ_TYPE_ID = 20 AND L20.DATE_DEL IS NULL
              -- Постоянный сопровождающий
              JOIN VALL V2818 ON V2818.OBJ_ID = L20.OBJ_ID AND V2818.PARAM_ID = 2818 AND V2818.IS_DEL = 0
              -- Есть RegID
              LEFT JOIN VALS V2917 ON V2917.OBJ_ID = L20.OBJ_ID AND V2917.PARAM_ID = 2917 AND V2917.IS_DEL = 0
              -- Основная карта
              LEFT JOIN VALS V2918 ON V2918.OBJ_ID = L20.OBJ_ID AND V2918.PARAM_ID = 2918 AND V2918.IS_DEL = 0
              -- ФИО
              LEFT JOIN OBJECT_CAPTION_GET(L20.OBJ_ID) C ON 1 = 1
              WHERE L7.PARENT_ID = :PARENT_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL AND (V2818.LISTVAL_ID = 2 OR V2918.VAL IS NOT NULL /*OR */)
              ORDER BY 2
              INTO :OBJ_ID, :CAPTION, :SORT_ORDER, :CARD_ALLOWED, :REG_ID, :CARD_ID, :CARD_DATE
          DO
          BEGIN
              -- Подменяем дату на правильную, если есть в реестре
              SELECT FIRST 1 V3269.VAL
              FROM LINKS L455
              JOIN VALS V3273 ON V3273.OBJ_ID = L455.OBJ_ID AND V3273.PARAM_ID = 3273 AND V3273.IS_DEL = 0 AND V3273.SVAL = :CARD_ID
              JOIN VALDT V3269 ON V3269.OBJ_ID = L455.OBJ_ID AND V3269.PARAM_ID = 3269 AND V3269.IS_DEL = 0
              LEFT JOIN VALDT V3271 ON V3271.OBJ_ID = L455.OBJ_ID AND V3271.PARAM_ID = 3271 AND V3271.IS_DEL = 0
              WHERE L455.PARENT_ID = :OBJ_ID AND L455.OBJ_TYPE_ID = 455 AND L455.DATE_DEL IS NULL AND V3271.VAL IS NULL
              ORDER BY L455.OBJ_ID DESC
              INTO :CARD_DATE;

              SUSPEND;
          END

      END
      ELSE
      BEGIN

          -- Только в пределах класса - учащиеся
          OBJ_TYPE = 1;

          GRADE_NAME = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:PARENT_ID));
          FOR
              SELECT L10.OBJ_ID, C.CAPTION, 1, IIF(V2854.LISTVAL_ID = 2, 1, 0), CAST(V2912.VAL AS VARCHAR(100)), CAST(V2855.VAL AS VARCHAR(100)), V2855.DATE_MODIFY
              FROM LINKS L10
              -- Согласие на выдачу карты
              JOIN VALL V2854 ON V2854.OBJ_ID = L10.OBJ_ID AND V2854.PARAM_ID = 2854 AND V2854.IS_DEL = 0 -- AND V2854.LISTVAL_ID = 2
              -- Есть RegID
              LEFT JOIN VALS V2912 ON V2912.OBJ_ID = L10.OBJ_ID AND V2912.PARAM_ID = 2912 AND V2912.IS_DEL = 0
              -- Основная карта
              LEFT JOIN VALS V2855 ON V2855.OBJ_ID = L10.OBJ_ID AND V2855.PARAM_ID = 2855 AND V2855.IS_DEL = 0
              -- ФИО
              LEFT JOIN OBJECT_CAPTION_GET(L10.OBJ_ID, 23) C ON 1 = 1
              WHERE L10.PARENT_ID = :PARENT_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
              ORDER BY 2
              INTO :OBJ_ID, :CAPTION, :SORT_ORDER, :CARD_ALLOWED, :REG_ID, :CARD_ID, :CARD_DATE
          DO
          BEGIN
              -- Подменяем дату на правильную, если есть в реестре
              SELECT FIRST 1 V3269.VAL
              FROM LINKS L455
              JOIN VALS V3273 ON V3273.OBJ_ID = L455.OBJ_ID AND V3273.PARAM_ID = 3273 AND V3273.IS_DEL = 0 AND V3273.SVAL = :CARD_ID
              JOIN VALDT V3269 ON V3269.OBJ_ID = L455.OBJ_ID AND V3269.PARAM_ID = 3269 AND V3269.IS_DEL = 0
              LEFT JOIN VALDT V3271 ON V3271.OBJ_ID = L455.OBJ_ID AND V3271.PARAM_ID = 3271 AND V3271.IS_DEL = 0
              WHERE L455.PARENT_ID = :OBJ_ID AND L455.OBJ_TYPE_ID = 455 AND L455.DATE_DEL IS NULL AND V3271.VAL IS NULL
              ORDER BY L455.OBJ_ID DESC
              INTO :CARD_DATE;

              SUSPEND;
          END

          -- Только в пределах класса - сопровождающие (либо постоянные, либо те у которых есть хотя бы одна карта)
          GRADE_NAME = 'Сопровождающие';
          OBJ_TYPE = 2;
          FOR
              SELECT L20.OBJ_ID, C.CAPTION, 2, IIF(V2818.LISTVAL_ID = 2, 1, 0), CAST(V2917.VAL AS VARCHAR(100)), CAST(V2918.VAL AS VARCHAR(100)), V2918.DATE_MODIFY
              FROM LINKS L10
              JOIN LINKS L20 ON L20.PARENT_ID = L10.OBJ_ID AND L20.OBJ_TYPE_ID = 20 AND L20.DATE_DEL IS NULL
              -- Постоянный сопровождающий
              JOIN VALL V2818 ON V2818.OBJ_ID = L20.OBJ_ID AND V2818.PARAM_ID = 2818 AND V2818.IS_DEL = 0
              -- Есть RegID
              LEFT JOIN VALS V2917 ON V2917.OBJ_ID = L20.OBJ_ID AND V2917.PARAM_ID = 2917 AND V2917.IS_DEL = 0
              -- Основная карта
              LEFT JOIN VALS V2918 ON V2918.OBJ_ID = L20.OBJ_ID AND V2918.PARAM_ID = 2918 AND V2918.IS_DEL = 0
              -- ФИО
              LEFT JOIN OBJECT_CAPTION_GET(L20.OBJ_ID) C ON 1 = 1
              WHERE L10.PARENT_ID = :PARENT_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL AND (V2818.LISTVAL_ID = 2 OR V2918.VAL IS NOT NULL /*OR */)
              ORDER BY 2
              INTO :OBJ_ID, :CAPTION, :SORT_ORDER, :CARD_ALLOWED, :REG_ID, :CARD_ID, :CARD_DATE
          DO
          BEGIN
              -- Подменяем дату на правильную, если есть в реестре
              SELECT FIRST 1 V3269.VAL
              FROM LINKS L455
              JOIN VALS V3273 ON V3273.OBJ_ID = L455.OBJ_ID AND V3273.PARAM_ID = 3273 AND V3273.IS_DEL = 0 AND V3273.SVAL = :CARD_ID
              JOIN VALDT V3269 ON V3269.OBJ_ID = L455.OBJ_ID AND V3269.PARAM_ID = 3269 AND V3269.IS_DEL = 0
              LEFT JOIN VALDT V3271 ON V3271.OBJ_ID = L455.OBJ_ID AND V3271.PARAM_ID = 3271 AND V3271.IS_DEL = 0
              WHERE L455.PARENT_ID = :OBJ_ID AND L455.OBJ_TYPE_ID = 455 AND L455.DATE_DEL IS NULL AND V3271.VAL IS NULL
              ORDER BY L455.OBJ_ID DESC
              INTO :CARD_DATE;

              SUSPEND;
          END

      END

  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CARDS_MAIN_REPORT (
    PARENT_ID BIGINT,
    PARENT_TYPE_ID BIGINT)
RETURNS (
    VAL VARCHAR(6000))
AS
declare variable OBJ_ID bigint;
declare variable OBJ_TYPE smallint;
declare variable PREV_TYPE smallint;
declare variable S varchar(1000);
declare variable GRADE_NAME varchar(400);
declare variable CARD_ID varchar(100);
declare variable CARD_DATE date;
begin

  IF(PARENT_ID = -1) THEN
  BEGIN
    SELECT FIRST 1 L.OBJ_ID
    FROM LINKS L
    WHERE L.PARENT_ID IS NULL AND L.OBJ_TYPE_ID = 2 AND L.DATE_DEL IS NULL
    INTO :PARENT_ID;

    PARENT_TYPE_ID = -1;
  END

  IF(PARENT_TYPE_ID IS NULL) THEN
  SELECT TYPE_ID
  FROM OBJECTS
  WHERE OBJ_ID = :PARENT_ID
  INTO :PARENT_TYPE_ID;

  VAL = '<!DOCTYPE html>';
  VAL = VAL || '<html lang="ru">';
  VAL = VAL || '<head>';
  VAL = VAL || '<meta charset="utf-8" />';
  VAL = VAL || '<style>';
  VAL = VAL || 'html { font-family: Tahoma, Verdana, Arial;';
  VAL = VAL || 'font-size: 10pt; ';
  VAL = VAL || '} ';
  VAL = VAL || 'h1 { font-size: 150%;';
  VAL = VAL || 'font-weight: bold; ';
  VAL = VAL || '} ';
  VAL = VAL || 'h2 { font-size: 120%;';
  VAL = VAL || 'font-weight: bold; color: #006064; ';
  VAL = VAL || '} ';
  VAL = VAL || 'table { width: 100%; } ';
  VAL = VAL || 'table tr td, table tr th { text-align: left; padding: 0.4em 1em; } ';
  VAL = VAL || 'table tr th { border-bottom: 2px solid black; } ';
  VAL = VAL || 'table tr td.delimiter { border-bottom: 2px solid gray; } ';
  VAL = VAL || 'table tr th.td1, table tr td.td1 { width: 40%; } ';
  VAL = VAL || 'table tr th.td2, table tr td.td2 { width: 20%; } ';
  VAL = VAL || 'table tr th.td3, table tr td.td3 { width: 20%; } ';
  VAL = VAL || 'table tr th.td4, table tr td.td4 { width: 20%; } ';
  VAL = VAL || '</style>';

  VAL = VAL || '</head>';
  VAL = VAL || '<body style="padding: 8px;">';

  VAL = VAL || '<h1>Отчет о выданных картах</h1>';

  VAL = VAL || '<h2>Основные карты</h2>';

  VAL = VAL || '<table cellspacing="0" cellpadding="0">';
  VAL = VAL || '<tr>';
  VAL = VAL || '<th class="td1">ФИО</th>';
  VAL = VAL || '<th class="td2">Категория</th>';
  VAL = VAL || '<th class="td3">Номер карты</th>';
  VAL = VAL || '<th class="td4">Дата выдачи</th>';
  VAL = VAL || '</tr>';
  SUSPEND;
  PREV_TYPE = NULL;

  FOR
      SELECT S.OBJ_ID, S.OBJ_TYPE, S.CAPTION, S.GRADE_NAME, CS.VAL, S.CARD_DATE
      FROM CARDS_LIST_SUBS(:PARENT_ID, :PARENT_TYPE_ID) S
      LEFT JOIN CARD_TO_STR(S.CARD_ID) CS ON 1 = 1
      ORDER BY S.OBJ_TYPE, S.SORT_ORDER, S.CAPTION
      INTO :OBJ_ID, :OBJ_TYPE, :S, :GRADE_NAME, :CARD_ID, :CARD_DATE
  DO
  BEGIN

      IF(OBJ_TYPE <> PREV_TYPE) THEN
      BEGIN
        VAL = '<tr><td class="delimiter" colspan="4"></td></tr>';
        SUSPEND;
      END
      PREV_TYPE = OBJ_TYPE;

      VAL = '<tr>';
      VAL = VAL || '<td class="td1">' || S || '</td>';
      VAL = VAL || '<td class="td2">' || GRADE_NAME || '</td>';
      VAL = VAL || '<td class="td3">' || COALESCE(CARD_ID, 'Отсутствует') || '</td>';
      IF(CARD_DATE IS NOT NULL) THEN S = (SELECT RESULT FROM DATE2STR(:CARD_DATE)); ELSE S = '';
      VAL = VAL || '<td class="td4">' || S || '</td>';

      VAL = VAL || '</tr>';

      SUSPEND;

  END

  VAL = '</table>';

  VAL = VAL || '<h2>Временные карты на руках</h2>';

  VAL = VAL || '<table cellspacing="0" cellpadding="0">';
  VAL = VAL || '<tr>';
  VAL = VAL || '<th class="td1">ФИО</th>';
  VAL = VAL || '<th class="td2">Категория</th>';
  VAL = VAL || '<th class="td3">Номер временной карты</th>';
  VAL = VAL || '<th class="td4">Дата выдачи</th>';
  VAL = VAL || '</tr>';
  SUSPEND;

  PREV_TYPE = NULL;

  FOR
      SELECT S.OBJ_ID, S.OBJ_TYPE, S.CAPTION, S.GRADE_NAME, CS.VAL, S.TEMP_CARD_DATE
      FROM CARDS_LIST_SUBS(:PARENT_ID, :PARENT_TYPE_ID) S
      LEFT JOIN CARD_TO_STR(S.TEMP_CARD_ID) CS ON 1 = 1
      WHERE S.TEMP_CARD_ID IS NOT NULL
      ORDER BY S.OBJ_TYPE, S.SORT_ORDER, S.GRADE_NAME, S.CAPTION
      INTO :OBJ_ID, :OBJ_TYPE, :S, :GRADE_NAME, :CARD_ID, :CARD_DATE
  DO
  BEGIN

      IF(OBJ_TYPE <> PREV_TYPE) THEN
      BEGIN
        VAL = '<tr><td class="delimiter" colspan="4"></td></tr>';
        SUSPEND;
      END
      PREV_TYPE = OBJ_TYPE;

      VAL = '<tr>';
      VAL = VAL || '<td class="td1">' || S || '</td>';
      VAL = VAL || '<td class="td2">' || GRADE_NAME || '</td>';
      VAL = VAL || '<td class="td3">' || CARD_ID || '</td>';
      S = (SELECT RESULT FROM DATE2STR(:CARD_DATE));
      VAL = VAL || '<td class="td4">' || S || '</td>';
      VAL = VAL || '</tr>';

      SUSPEND;

  END

  VAL = '</table>';
  VAL = VAL || '</body>';
  VAL = VAL || '</html>';
  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CARDS_RETURN (
    I$OBJ_ID BIGINT,
    I$CARD_ID VARCHAR(100))
RETURNS (
    TMP INTEGER)
AS
declare variable V$OBJ_ID bigint;
declare variable T integer;
begin

  IF(I$OBJ_ID IS NULL) THEN
  BEGIN

      -- Затираем все временные карты
      UPDATE VALS
      SET IS_DEL = 1
      WHERE PARAM_ID IN (2913, 2916, 2919) AND IS_DEL = 0;

      -- Реестр временных карт - отмечаем как возвращенные, но оставляем пустым время возврата
      FOR
        SELECT V3273.OBJ_ID
        FROM VALS V3273
        JOIN VALL V3270 ON V3270.OBJ_ID = V3273.OBJ_ID AND V3270.PARAM_ID = 3273 AND V3270.IS_DEL = 0 AND V3270.LISTVAL_ID = 14074
        JOIN VALL V3272 ON V3272.OBJ_ID = V3273.OBJ_ID AND V3272.PARAM_ID = 3273 AND V3272.IS_DEL = 0 AND V3272.LISTVAL_ID = 2
        WHERE V3273.PARAM_ID = 3273 AND V3273.SVAL = :I$CARD_ID AND V3273.IS_DEL = 0
        ORDER BY 1
        INTO :V$OBJ_ID
      DO
      BEGIN
        UPDATE VALL
        SET LISTVAL_ID = 3
        WHERE OBJ_ID = :V$OBJ_ID AND PARAM_ID = 3272;
      END

  END
  ELSE
  BEGIN

      -- Затираем конкретную карту при возврате
      UPDATE VALS
      SET IS_DEL = 1
      WHERE PARAM_ID IN (2855, 2857, 2918, 2913, 2916, 2919) AND SVAL = :I$CARD_ID AND IS_DEL = 0;

      -- Фиксируем в реестре и статус, и время возврата, только если карта уже не отмечена как возвращенная
      FOR
        SELECT V3273.OBJ_ID
        FROM VALS V3273
        JOIN VALL V3272 ON V3272.OBJ_ID = V3273.OBJ_ID AND V3272.PARAM_ID = 3273 AND V3272.IS_DEL = 0 AND V3272.LISTVAL_ID = 2
        WHERE V3273.PARAM_ID = 3273 AND V3273.SVAL = :I$CARD_ID AND V3273.IS_DEL = 0
        ORDER BY 1
        INTO :V$OBJ_ID
      DO
      BEGIN
        UPDATE VALL
        SET LISTVAL_ID = 3
        WHERE OBJ_ID = :V$OBJ_ID AND PARAM_ID = 3272;

        SELECT 1 FROM VAL_ADD(3271, :V$OBJ_ID, CURRENT_TIMESTAMP) INTO :T;
      END

  END

  SUSPEND;
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CARDS_TAGS_REPORT (
    PARENT_ID BIGINT,
    PARENT_TYPE_ID BIGINT)
RETURNS (
    VAL VARCHAR(6000))
AS
declare variable S varchar(4000);
declare variable P integer;
declare variable P_NAME varchar(100);
declare variable P_VALUE varchar(1000);
declare variable OBJ_ID bigint;
declare variable N integer;
declare variable CURRENT_INDEX integer;
begin

  IF(PARENT_ID = -1) THEN
  BEGIN
    SELECT FIRST 1 L.OBJ_ID
    FROM LINKS L
    WHERE L.PARENT_ID IS NULL AND L.OBJ_TYPE_ID = 2 AND L.DATE_DEL IS NULL
    INTO :PARENT_ID;

    PARENT_TYPE_ID = -1;
  END

  IF(PARENT_TYPE_ID IS NULL) THEN
  SELECT TYPE_ID
  FROM OBJECTS
  WHERE OBJ_ID = :PARENT_ID
  INTO :PARENT_TYPE_ID;

  VAL = '<!DOCTYPE html>';
  VAL = VAL || '<html lang="ru">';
  VAL = VAL || '<head>';
  VAL = VAL || '<meta charset="utf-8" />';
  VAL = VAL || '<style>';
  VAL = VAL || '* { box-sizing: border-box; } ';
  VAL = VAL || 'html { font-family: Tahoma, Verdana, Arial; font-size: 7pt; } ';
  VAL = VAL || 'body, html { width: 100%; margin: 0; } ';
  VAL = VAL || 'body { padding: 1em; } ';
  VAL = VAL || '.card { width: 100%; padding: 1em; border-collapse: collapse; } ';
  VAL = VAL || '.card tr td { padding: 0.2em; } ';
  VAL = VAL || '.breakpage { page-break-after: always; } ';
  VAL = VAL || '.thick { border: 3px solid black; width: 100%; padding: 0.5em; font-size: 9pt; } ';
  VAL = VAL || '.td1 { width: 39%; vertical-align: top; } ';
  VAL = VAL || '.td2 { width: 2%; } ';
  VAL = VAL || '.td3 { width: 39%; vertical-align: top; } ';
  VAL = VAL || '.tdr { text-align: right; } ';
  VAL = VAL || '.tl { text-align: left; } ';
  VAL = VAL || '.tc { text-align: center; } ';
  VAL = VAL || '.tw { text-align: center; border-bottom: 2px solid gray; font-weight: bold; } ';
  VAL = VAL || '.tbold { font-weight: bold; } ';
  VAL = VAL || '.th { font-size: 120%; } ';
  VAL = VAL || '.delimiter { margin: 10px; border-bottom: 2px dotted gray; } ';
  VAL = VAL || '</style>';

  VAL = VAL || '</head>';
  VAL = VAL || '<body>';

  SUSPEND;
  VAL = '';

  IF(PARENT_TYPE_ID = -1) THEN
  BEGIN

    SELECT FIRST 1 OBJ_ID
    FROM LINKS
    WHERE PARENT_ID IS NULL AND OBJ_TYPE_ID = 2 AND DATE_DEL IS NULL
    INTO :PARENT_ID;

  END

  IF(PARENT_TYPE_ID IN (10, 14, 20)) THEN
  BEGIN
      -- ID карты нас тут не интересует, берем данные из памятки
      S = NULL;
      SELECT V.VAL
      FROM VALS V
      WHERE V.OBJ_ID = :PARENT_ID AND V.PARAM_ID IN (2921, 2922, 2923) AND V.IS_DEL = 0
      INTO :S;
      IF(S IS NULL) THEN S = '';

      IF(S = '') THEN EXIT;

      -- ФИО добавляем как параметр с именем PERSON_FIO
      SELECT :S || ASCII_CHAR(13) || 'PERSON_FIO=' || V1.VAL || ' ' || V2.VAL || COALESCE(' ' || V3.VAL, '')
      FROM OBJECTS P
      JOIN VALS V1 ON V1.OBJ_ID = P.OBJ_ID AND V1.PARAM_ID IN (55, 59, 128) AND V1.IS_DEL = 0
      JOIN VALS V2 ON V2.OBJ_ID = P.OBJ_ID AND V2.PARAM_ID IN (56, 60, 129) AND V2.IS_DEL = 0
      LEFT JOIN VALS V3 ON V3.OBJ_ID = P.OBJ_ID AND V3.PARAM_ID IN (57, 61, 130) AND V3.IS_DEL = 0
      WHERE P.OBJ_ID = :PARENT_ID
      INTO :S;

      IF(PARENT_TYPE_ID = 14) THEN S = S || ASCII_CHAR(13) || 'PERSON_CAT=Сотрудник';
      ELSE IF(PARENT_TYPE_ID = 20) THEN S = S || ASCII_CHAR(13) || 'PERSON_CAT=Сопровождающий';
      ELSE BEGIN
          P_VALUE = NULL;
          SELECT FIRST 1 CAPTION
          FROM LINKS LPG
          LEFT JOIN OBJECT_CAPTION_GET(LPG.PARENT_ID) C ON 1 = 1
          WHERE LPG.OBJ_ID = :PARENT_ID AND LPG.PARENT_TYPE_ID IN (9, 125, 187) AND LPG.DATE_DEL IS NULL
          INTO P_VALUE;

          S = S || ASCII_CHAR(13) || 'PERSON_CAT=' || COALESCE(P_VALUE, '');
      END

      -- Парсим параметры и поменяем текст в шаблоне
      SELECT VAL
      FROM CARDS_TAG_TEMPLATE(1)
      INTO :VAL;

      WHILE(S IS NOT NULL AND CHAR_LENGTH(S) > 0)
      DO
      BEGIN

        P = POSITION(ASCII_CHAR(13) IN S);
        IF(P <= 0) THEN P = CHAR_LENGTH(S) + 1;

        P_VALUE = SUBSTRING(S FROM 1 FOR P - 1);
        S = SUBSTRING(S FROM P + 1);
        IF(SUBSTRING(S FROM 1 FOR 1) = ASCII_CHAR(10)) THEN S = SUBSTRING(S FROM 2);

        P = POSITION('=' IN P_VALUE);
        IF(P > 2) THEN
        BEGIN
            P_NAME = '$' || UPPER(SUBSTRING(P_VALUE FROM 1 FOR P - 1));
            P_VALUE = SUBSTRING(P_VALUE FROM P + 1);
            VAL = REPLACE(VAL, P_NAME, P_VALUE);
        END

      END

      SUSPEND;
  END
  ELSE
  BEGIN

      -- Выбрана группа или ОУ целиком - все то же самое, но последовательно для каждой персоны в коллективе

      -- Подсчитываем общее количество записей
      CURRENT_INDEX = 0;

      SELECT COUNT(*)
      FROM LINKS LP
      JOIN VALS V ON V.OBJ_ID = LP.OBJ_ID AND V.PARAM_ID IN (2921, 2922, 2923) AND V.IS_DEL = 0 AND V.VAL <> ''
      WHERE LP.PARENT_ID = :PARENT_ID AND LP.OBJ_TYPE_ID IN (10, 14, 20) AND LP.DATE_DEL IS NULL
      INTO :N;

      FOR
         SELECT LP.OBJ_ID, C.CAPTION
         FROM LINKS LP
         LEFT JOIN OBJECT_CAPTION_GET(LP.OBJ_ID) C ON 1 = 1
         WHERE LP.PARENT_ID = :PARENT_ID AND LP.OBJ_TYPE_ID IN (10, 14, 20) AND LP.DATE_DEL IS NULL
         ORDER BY 2
         INTO :OBJ_ID, :S
      DO
      BEGIN

          -- ID карты нас тут не интересует, берем данные из памятки (#13 в конце нет)
          S = NULL;
          SELECT V.VAL
          FROM VALS V
          WHERE V.OBJ_ID = :OBJ_ID AND V.PARAM_ID IN (2921, 2922, 2923) AND V.IS_DEL = 0
          INTO :S;
          IF(S IS NULL) THEN S = '';

          IF(S <> '') THEN
          BEGIN

              CURRENT_INDEX = CURRENT_INDEX + 1;

              -- ФИО добавляем как параметр с именем PERSON_FIO
              SELECT :S || ASCII_CHAR(13) || 'PERSON_FIO=' || V1.VAL || ' ' || V2.VAL || COALESCE(' ' || V3.VAL, '')
              FROM OBJECTS P
              JOIN VALS V1 ON V1.OBJ_ID = P.OBJ_ID AND V1.PARAM_ID IN (55, 59, 128) AND V1.IS_DEL = 0
              JOIN VALS V2 ON V2.OBJ_ID = P.OBJ_ID AND V2.PARAM_ID IN (56, 60, 129) AND V2.IS_DEL = 0
              LEFT JOIN VALS V3 ON V3.OBJ_ID = P.OBJ_ID AND V3.PARAM_ID IN (57, 61, 130) AND V3.IS_DEL = 0
              WHERE P.OBJ_ID = :OBJ_ID
              INTO :S;

              IF(PARENT_TYPE_ID <= 2) THEN S = S || ASCII_CHAR(13) || 'PERSON_CAT=Сотрудник';
              ELSE IF(PARENT_TYPE_ID = 10) THEN S = S || ASCII_CHAR(13) || 'PERSON_CAT=Сопровождающий';
              ELSE BEGIN
                  P_VALUE = NULL;
                  SELECT CAPTION
                  FROM OBJECT_CAPTION_GET(:PARENT_ID)
                  INTO P_VALUE;

                  S = S || ASCII_CHAR(13) || 'PERSON_CAT=' || COALESCE(P_VALUE, '');
              END

              -- Парсим параметры и подменяем текст в шаблоне
              SELECT VAL
              FROM CARDS_TAG_TEMPLATE(IIF(:CURRENT_INDEX = :N, 1, 0))
              INTO :VAL;

              WHILE(S IS NOT NULL AND CHAR_LENGTH(S) > 0)
              DO
              BEGIN

                P = POSITION(ASCII_CHAR(13) IN S);
                IF(P <= 0) THEN P = CHAR_LENGTH(S) + 1;

                P_VALUE = SUBSTRING(S FROM 1 FOR P - 1);
                S = SUBSTRING(S FROM P + 1);
                IF(SUBSTRING(S FROM 1 FOR 1) = ASCII_CHAR(10)) THEN S = SUBSTRING(S FROM 2);

                P = POSITION('=' IN P_VALUE);
                IF(P > 2) THEN
                BEGIN
                    P_NAME = '$' || UPPER(SUBSTRING(P_VALUE FROM 1 FOR P - 1));
                    P_VALUE = SUBSTRING(P_VALUE FROM P + 1);
                    VAL = REPLACE(VAL, P_NAME, P_VALUE);
                END

              END

              SUSPEND;

          END

      END

  END

  VAL = '</body>';
  VAL = VAL || '</html>';
  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CARDS_TAG_TEMPLATE (
    I$IS_LAST INTEGER = 1)
RETURNS (
    VAL VARCHAR(6000))
AS
begin

  VAL = '<table class="card' || IIF(I$IS_LAST <> 0, '', ' breakpage') || '" cellspacing="0" cellpadding="0">';

  -- скрыто 08.2024
  -- VAL = VAL || '<tr>';
  -- VAL = VAL || '<td class="tc tbold th" colspan="3">Официальный спонсор - Банк "Санкт-Петербург"<br/><br/></td>';
  -- VAL = VAL || '</tr>';

  VAL = VAL || '<tr>';
    VAL = VAL || '<td class="td1 tdr">НОМЕР КАРТЫ УЧАЩЕГОСЯ:<br/>* полный номер указан на оборотной стороне карты</td>';
    VAL = VAL || '<td class="td2"></td>';
    VAL = VAL || '<td class="td3"><div class="thick">$CARD_NUMBER</div></td>';
  VAL = VAL || '</tr>';

  VAL = VAL || '<tr>';
    VAL = VAL || '<td class="td1 tdr">НОМЕР ЛИЦЕВОГО СЧЕТА УЧАЩЕГОСЯ:</td>';
    VAL = VAL || '<td class="td2"></td>';
    VAL = VAL || '<td class="td3"><div class="thick">$ACCOUNT_NUMBER</div></td>';
  VAL = VAL || '</tr>';

  VAL = VAL || '<tr>';
    VAL = VAL || '<td class="td1 tdr">КОМБИНАТ ПИТАНИЯ:</td>';
    VAL = VAL || '<td class="td2"></td>';
    VAL = VAL || '<td class="td3"><div class="thick">$SERVICER_NAME</div></td>';
  VAL = VAL || '</tr>';

  VAL = VAL || '<tr>';

  -- Первый столбец текста
  VAL = VAL || '<td class="td1">';
  VAL = VAL || '<p>Эта памятка прилагается к «Единой карте школьника» (далее – «Карта»), с помощью которой удобно проходить в школу и оплачивать покупки в школьной столовой. ';
    VAL = VAL || 'Детализацию питания, меню, историю проходов, и прочую информацию, связанную с обучением Вы можете посмотреть в личном кабинете на портале «Петербургское образование»:</p>';
  VAL = VAL || '<div class="tc tbold">https://petersburgedu.ru</div>';
  VAL = VAL || '<br/>';
  VAL = VAL || '<br/>';

  VAL = VAL || '<div class="tc tbold">КАК ПОЛЬЗОВАТЬСЯ КАРТОЙ</div>';
  VAL = VAL || '<p>Для прохода в школу нужно приложить Карту к считывателю турникета и осуществить проход после разрешающего сигнала. ';
    VAL = VAL || 'Для оплаты покупок в школьный столовой необходимо приложить Карту к считывателю терминала, и сумма спишется автоматически.';
  VAL = VAL || '</p>';

  VAL = VAL || '<div class="tc tbold">При использовании Карты запрещается:</div>';
  VAL = VAL || '<ul class="tl">';
  VAL = VAL || '<li>Сгибать и ломать Карту</li>';
  VAL = VAL || '<li>Допускать намокание Карты и хранить карту во влажных местах</li>';
  VAL = VAL || '<li>Подвергать Карту механическим и электромагнитным воздействиям</li>';
  VAL = VAL || '<li>Прокалывать Карту, делать какие-либо прорези и отверстия</li>';
  VAL = VAL || '<li>Передавать Карту для использования другим учащимся и сторонним лицам</li>';
  VAL = VAL || '</ul>';

  VAL = VAL || '</td>';

  VAL = VAL || '<td class="td2"></td>';

  -- Второй столбец текста
  VAL = VAL || '<td class="td3">';

  VAL = VAL || '<div class="tc">';
  VAL = VAL || '<br/>';
  VAL = VAL || '<div class="tc tbold">ВАЖНАЯ ИНФОРМАЦИЯ</div>';
  VAL = VAL || '<br/>';
  VAL = VAL || '<div class="tc tbold">Первый выпуск Карты является бесплатным. В случаях утери Карты или утраты по иной причине (повреждения или передаче другим лицам) повторное изготовление новой Карты является платным.</div>';
  VAL = VAL || '<br/>';
  VAL = VAL || '</div>';

  VAL = VAL || '<br/>';
  VAL = VAL || '<div class="thick">$PERSON_FIO<br/>$PERSON_CAT<br/>Карта номер $CARD_NUMBER</div>';
  VAL = VAL || '<br/>';

  VAL = VAL || '<div class="tc tbold">ВОССТАНОВЛЕНИЕ КАРТЫ</div>';
  VAL = VAL || '<ul>';
  VAL = VAL || '<li>В случае утраты Карты необходимо срочно обратиться к ответственному сотруднику школы для блокировки.</li>';
  VAL = VAL || '<li>После того как утраченная Карта заблокирована, ответственный сотрудник школы выдает новую Карту, которую необходимо оплатить в течение 10 дней (в случае неоплаты в указанный период – Карта автоматически блокируется).</li>';
  VAL = VAL || '<li>Оплатить новую Карту можно через систему «Сбербанк Онлайн», платежные терминалы ПАО «Сбербанк», ';
    VAL = VAL || 'интернет банк «Банк Санкт-Петербург», мобильное приложение и платежные терминалы ПАО «Банк Санкт-Петербург» (картой любого банка без комиссии), ';
  VAL = VAL || 'или на сайте «Моя школа» https://myschool.spb.ru</li>';
  VAL = VAL || '</ul>';
  VAL = VAL || '<br/>';

  VAL = VAL || '</td>';

  VAL = VAL || '</tr>';

  /*
  VAL = VAL || '<tr>';
  VAL = VAL || '<td class="tw" colspan="3">Способы Пополнения лицевого счета</td>';
  VAL = VAL || '</tr>';
  VAL = VAL || '<tr>';

  VAL = VAL || '<td class="td1">';
  VAL = VAL || '<div class="tc tbold">ЧЕРЕЗ СБЕРБАНК</div>';
  VAL = VAL || '<div class="tbold">Сервис Сбербанк Онлайн</div>';
  VAL = VAL || '<ol>';
  VAL = VAL || '<li>Выберите раздел "Платежи и переводы"</li>';
  VAL = VAL || '<li>В строке поиска введите ИНН или наименование Комбината питания</li>';
  VAL = VAL || '<li>Выберите услугу Комбината питания, введите лицевой счет, сумму и подтвердите платеж</li>';
  VAL = VAL || '</ol>';
  VAL = VAL || '<div class="tbold">Мобильное приложение Сбербанк Онлайн</div>';
  VAL = VAL || '<ol>';
  VAL = VAL || '<li>Выберите раздел "Платежи и переводы"</li>';
  VAL = VAL || '<li>В поисковой строке введите ИНН или наименование Комбината питания</li>';
  VAL = VAL || '<li>Выберите услугу Комбината питания, введите лицевой счет, сумму и подтвердите платеж</li>';
  VAL = VAL || '</ol>';
  VAL = VAL || '<div class="tbold">Платежный терминал</div>';
  VAL = VAL || '<ol>';
  VAL = VAL || '<li>Выберите раздел "Оплатить услуги"</li>';
  VAL = VAL || '<li>Выберите раздел "Образование", далее "Школы" -> "Питание школьников"</li>';
  VAL = VAL || '<li>Выберите иконку Комбината питания выберите услугу, введите лицевой счет, внесите сумму и подтвердите платеж</li>';
  VAL = VAL || '</ol>';
  VAL = VAL || '<div class="tbold">В офисах банка</div>';
  VAL = VAL || '<ol>';
  VAL = VAL || '<li>Предоставьте реквизиты комбината сотруднику питания (ИНН, р/счет, БИК), номер лицевого счета</li>';
  VAL = VAL || '<li>Назовите услугу и сумму</li>';
  VAL = VAL || '<li>Проведите оплату</li>';
  VAL = VAL || '</ol>';
  VAL = VAL || '</td>';

  VAL = VAL || '<td class="td2"></td>';

  VAL = VAL || '<td class="td3">';
  VAL = VAL || '<div class="tc tbold">ЧЕРЕЗ БАНК САНКТ-ПЕТЕРБУРГ</div>';
  VAL = VAL || '<div class="tbold">Сервис "Интернет банк"</div>';
  VAL = VAL || '<ol>';
  VAL = VAL || '<li>Выберите раздел "Платежи и переводы"</li>';
  VAL = VAL || '<li>В строке поиска введите ИНН или наименование Комбината питания</li>';
  VAL = VAL || '<li>Выберите услугу Комбината питания, введите лицевой счет, сумму и подтвердите платеж</li>';
  VAL = VAL || '</ol>';
  VAL = VAL || '<div class="tbold">Мобильное приложение</div>';
  VAL = VAL || '<ol>';
  VAL = VAL || '<li>Выберите раздел "Оплатить услугу"</li>';
  VAL = VAL || '<li>В строке поиска введите ИНН или наименование Комбината питания</li>';
  VAL = VAL || '<li>Выберите услугу Комбината питания, введите лицевой счет, сумму и подтвердите платеж</li>';
  VAL = VAL || '</ol>';
  VAL = VAL || '<div class="tbold">Платежный терминал (картой любого банка без комиссии)</div>';
  VAL = VAL || '<ol>';
  VAL = VAL || '<li>Выберите раздел "Оплатить услуги"</li>';
  VAL = VAL || '<li>Выберите раздел "Образование", далее "Школы" -> "Питание школьников"</li>';
  VAL = VAL || '<li>Выберите иконку Комбината питания выберите услугу, введите лицевой счет, внесите сумму и подтвердите платеж</li>';
  VAL = VAL || '</ol>';
  VAL = VAL || '</td>';

  VAL = VAL || '</tr>';
  */

  VAL = VAL || '<tr>';
    VAL = VAL || '<td colspan="3" class="tc"><br/>Получить подробную информацию об использовании Карты можно по телефону 8-812-333-91-00<br/><br/></td>';
  VAL = VAL || '</tr>';

  VAL = VAL || '<tr><td colspan="3">';
    VAL = VAL || '<div class="delimiter"></div>';
  VAL = VAL || '</td></tr>';

  VAL = VAL || '</table>';

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CARD_TO_STR (
    I$CARD_ID VARCHAR(100))
RETURNS (
    VAL VARCHAR(100))
AS
declare variable C char(1);
declare variable BV bigint;
declare variable V bigint;
begin

  IF(CHAR_LENGTH(I$CARD_ID) = 32 AND SUBSTRING(I$CARD_ID FROM 17) = '0000000000000000') THEN
  BEGIN

      I$CARD_ID = SUBSTRING(I$CARD_ID FROM 1 FOR 16);
      BV = 0;

      WHILE(CHAR_LENGTH(I$CARD_ID) > 0) DO
      BEGIN

          C = SUBSTRING(I$CARD_ID FROM 1 FOR 1);
          I$CARD_ID = SUBSTRING(I$CARD_ID FROM 2);

          IF(C = 'A') THEN V = 10;
          ELSE IF(C = 'B') THEN V = 11;
          ELSE IF(C = 'C') THEN V = 12;
          ELSE IF(C = 'D') THEN V = 13;
          ELSE IF(C = 'E') THEN V = 14;
          ELSE IF(C = 'F') THEN V = 15;
          ELSE V = C;

          BV = BV * 16 + V;

      END

      VAL = BV;

      -- Форматируем в стиле 0000 0000 000 0
      WHILE(CHAR_LENGTH(VAL) < 12) DO VAL = '0' || VAL;

      VAL = SUBSTRING(VAL FROM 1 FOR CHAR_LENGTH(VAL) - 1) || ' ' || SUBSTRING(VAL FROM CHAR_LENGTH(VAL));
      VAL = SUBSTRING(VAL FROM 1 FOR CHAR_LENGTH(VAL) - 5) || ' ' || SUBSTRING(VAL FROM CHAR_LENGTH(VAL) - 4);
      VAL = SUBSTRING(VAL FROM 1 FOR CHAR_LENGTH(VAL) - 10) || ' ' || SUBSTRING(VAL FROM CHAR_LENGTH(VAL) - 9);


  END
  ELSE VAL = I$CARD_ID;

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CARTOGRAPHY_DATA_EXPORT RETURNS (
    TAG_NAME VARCHAR(255),
    VAL VARCHAR(4000))
AS
declare variable V$SCHOOL_ID bigint;
declare variable V$DISTRICT_ID bigint;
declare variable V$PUPIL_ID bigint;
declare variable V$REGION varchar(255);
declare variable V$DISTRICT varchar(255);
declare variable V$TOWN varchar(255);
declare variable V$SETTLEMENT varchar(255);
declare variable V$STREET varchar(255);
declare variable V$HOUSE varchar(255);
declare variable V$LITER varchar(255);
declare variable V$CORP varchar(255);
declare variable V$FLAT varchar(255);
declare variable V$INDEX varchar(255);
declare variable V$FULLADR varchar(500);
BEGIN
    FOR
        SELECT L2.OBJ_ID, L111.OBJ_ID

        FROM LINKS L112
        
        JOIN LINKS L111
        ON L111.PARENT_ID = L112.OBJ_ID
        AND L111.OBJ_TYPE_ID = 111
        AND L111.DATE_DEL IS NULL
        
        JOIN VALL V665
        ON  V665.OBJ_ID = L111.OBJ_ID
        AND V665.PARAM_ID = 665
        AND V665.LISTVAL_ID IN (1035, 1044)
        AND V665.IS_DEL = 0
        
        JOIN LINKS L2
        ON L2.PARENT_ID = L111.OBJ_ID
        AND L2.OBJ_TYPE_ID = 2
        AND L2.DATE_DEL IS NULL
        
        WHERE L112.PARENT_ID IS NULL
        AND L112.OBJ_TYPE_ID = 112
        AND L112.DATE_DEL IS NULL
        INTO V$SCHOOL_ID, V$DISTRICT_ID
    DO
    BEGIN
        TAG_NAME = 'School:OGRN';
        VAL = NULL;
        SELECT V.VAL FROM VALS V
        WHERE V.OBJ_ID = :V$SCHOOL_ID
        AND V.PARAM_ID = 9
        AND V.IS_DEL = 0
        INTO VAL;
        SUSPEND;

        TAG_NAME = 'School:District';
        VAL = NULL;
        SELECT
            CASE WHEN V.LISTVAL_ID = 1035 then 'Кронштадтский'
                 WHEN V.LISTVAL_ID = 1044 then 'Центральный'
            END
        FROM VALL V
        WHERE V.OBJ_ID = :V$DISTRICT_ID
        AND V.PARAM_ID = 665
        AND V.IS_DEL = 0
        INTO VAL;
        SUSPEND;

        TAG_NAME = 'School:ShortName';
        VAL = NULL;
        SELECT V.VAL FROM VALS V
        WHERE V.OBJ_ID = :V$SCHOOL_ID
        AND V.PARAM_ID = 2
        AND V.IS_DEL = 0
        INTO VAL;
        SUSPEND;

        TAG_NAME = 'School:FullName';
        VAL = NULL;
        SELECT V.VAL FROM VALS V
        WHERE V.OBJ_ID = :V$SCHOOL_ID
        AND V.PARAM_ID = 5
        AND V.IS_DEL = 0
        INTO VAL;
        SUSPEND;

        FOR
            SELECT L10.OBJ_ID FROM LINKS L2
            
            JOIN LINKS L7
            ON L7.PARENT_ID = L2.OBJ_ID
            AND L7.OBJ_TYPE_ID = 7
            AND L7.DATE_DEL IS NULL
            
            JOIN LINKS L8
            ON L8.PARENT_ID = L7.OBJ_ID
            AND L8.OBJ_TYPE_ID = 8
            AND L8.DATE_DEL IS NULL
            
            JOIN LINKS L9
            ON L9.PARENT_ID = L8.OBJ_ID
            AND L9.OBJ_TYPE_ID IN (9, 187)
            AND L9.DATE_DEL IS NULL
            
            JOIN LINKS L10
            ON L10.PARENT_ID = L9.OBJ_ID
            AND L10.OBJ_TYPE_ID = 10
            AND L10.DATE_DEL IS NULL
            
            WHERE L2.OBJ_ID = :V$SCHOOL_ID
            AND L2.OBJ_TYPE_ID = 2
            AND L2.DATE_DEL IS NULL
    
            INTO V$PUPIL_ID
        DO
        BEGIN
            SELECT ADR.REGION,ADR.DISTRICT, ADR.TOWN, ADR.SETTLEMENT, ADR.STREET, ADR.HOUSE, ADR.LITER, ADR.CORP, ADR.FLAT, ADR.POST_INDEX, ADR.VAL
            FROM ADR_GET(103, :V$PUPIL_ID) ADR
            INTO :V$REGION, :V$DISTRICT, :V$TOWN, :V$SETTLEMENT, :V$STREET, :V$HOUSE, :V$LITER, :V$CORP, :V$FLAT, :V$INDEX, :V$FULLADR;

            IF (V$FULLADR <> '') THEN
            BEGIN
                TAG_NAME = 'School:Pupils:Pupil:DateBirth';
                VAL = NULL;
                SELECT V89.VAL
                FROM VALD V89
                WHERE V89.PARAM_ID = 89
                AND V89.OBJ_ID = :V$PUPIL_ID
                AND V89.IS_DEL = 0
                INTO VAL;
                SUSPEND;
    
                TAG_NAME = 'School:Pupils:Pupil:Address:Region';
                VAL = V$REGION;
                SUSPEND;
            
                TAG_NAME = 'School:Pupils:Pupil:Address:District';
                VAL = V$DISTRICT;
                SUSPEND;
            
                TAG_NAME = 'School:Pupils:Pupil:Address:Town';
                VAL = V$TOWN;
                SUSPEND;
            
                TAG_NAME = 'School:Pupils:Pupil:Address:Settlement';
                VAL = V$SETTLEMENT;
                SUSPEND;
            
                TAG_NAME = 'School:Pupils:Pupil:Address:Street';
                VAL = V$STREET;
                SUSPEND;
            
                TAG_NAME = 'School:Pupils:Pupil:Address:Building';
                VAL = V$HOUSE;
                SUSPEND;
            
                TAG_NAME = 'School:Pupils:Pupil:Address:Liter';
                VAL = V$LITER;
                SUSPEND;
            
                TAG_NAME = 'School:Pupils:Pupil:Address:Block';
                VAL = V$CORP;
                SUSPEND;
            
                TAG_NAME = 'School:Pupils:Pupil:Address:Appartment';
                VAL = V$FLAT;
                SUSPEND;
            
                TAG_NAME = 'School:Pupils:Pupil:Address:PostIndex';
                VAL = V$INDEX;
                SUSPEND;
    
                TAG_NAME = 'School:Pupils:Pupil:FullAddress';
                VAL = V$FULLADR;
                SUSPEND;
            END
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CEC_BROWSE (
    I$SUBJECT_ID BIGINT,
    I$GRADE_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(1000))
AS
declare variable V$OBJ_ID bigint;
declare variable V$SUBJECT_ID bigint;
declare variable V$NAME varchar(400);
declare variable V$TYPE_ID smallint;
declare variable V$TYPE varchar(400);
declare variable V$SUBJECT varchar(1000);
begin

  -- алиасинг предметов
  SELECT V3159.VAL
  FROM VALR V3159
  WHERE V3159.OBJ_ID = :I$SUBJECT_ID AND V3159.PARAM_ID = 3159 AND V3159.IS_DEL = 0
  INTO :I$SUBJECT_ID;

  TAG_NAME = 'items::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
    SELECT D.OBJ_ID, D.SUBJECT_ID, D.CAPTION, D.TYPE_ID, T.CAPTION, C.CAPTION
    FROM CEC D
    JOIN CEC_TYPES T ON T.OBJ_ID = D.TYPE_ID
    LEFT JOIN OBJECT_CAPTION_GET(D.SUBJECT_ID) C ON 1 = 1
    WHERE D.DATE_DEL IS NULL AND D.SUBJECT_ID = :I$SUBJECT_ID
    ORDER BY IIF(D.TYPE_ID >= 10000, 0, 1), D.TYPE_ID, C.CAPTION
    INTO :V$OBJ_ID, :V$SUBJECT_ID, :V$NAME, :V$TYPE_ID, :V$TYPE, :V$SUBJECT
  DO
  BEGIN
    TAG_NAME = 'items:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'items:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'items:r:subject_id';
    VAL = V$SUBJECT_ID;
    SUSPEND;
    TAG_NAME = 'items:r:type';
    VAL = V$TYPE_ID;
    SUSPEND;
    TAG_NAME = 'items:r:type_name';
    VAL = V$TYPE;
    SUSPEND;
    TAG_NAME = 'items:r:subject_name';
    VAL = V$SUBJECT;
    SUSPEND;
    TAG_NAME = 'items:r:name';
    VAL = V$NAME;
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CEC_BROWSE_ITEMS (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(1000))
AS
declare variable V$ID bigint;
declare variable V$PARENT_ID bigint;
declare variable V$SORT_INDEX smallint;
declare variable V$CODE varchar(40);
declare variable V$CAPTION varchar(1000);
declare variable S varchar(1000);
declare variable V$MID bigint;
declare variable V$MCODE varchar(40);
declare variable V$MCAPTION varchar(1000);
declare variable V$STAGE integer;
begin

  SELECT D.CAPTION, D.SUBJECT_ID, C.CAPTION
  FROM CEC D
  LEFT JOIN OBJECT_CAPTION_GET(D.SUBJECT_ID) C ON 1 = 1
  WHERE D.DATE_DEL IS NULL AND D.OBJ_ID = :I$OBJ_ID
  INTO :VAL, :V$ID, :S;

  TAG_NAME = 'name';
  SUSPEND;

  TAG_NAME = 'subject_id';
  VAL = V$ID;
  SUSPEND;

  TAG_NAME = 'subject_name';
  VAL = S;
  SUSPEND;

  TAG_NAME = 'items::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT D.OBJ_ID, D.PARENT_ID, D.SORT_INDEX, D.CODE, D.CAPTION, D."DESC", D.MASTER_ID, MD.CODE, MD.CAPTION, LV.COST
    FROM CEC_ITEMS D
    LEFT JOIN CEC_ITEMS MD ON MD.OBJ_ID = D.MASTER_ID
    LEFT JOIN LISTVALS LV ON LV.LISTVAL_ID = D.STAGE_ID
    WHERE D.DATE_DEL IS NULL AND D.CEC_ID = :I$OBJ_ID
    ORDER BY D.SORT_INDEX
    INTO :V$ID, :V$PARENT_ID, :V$SORT_INDEX, :V$CODE, :V$CAPTION, :S, :V$MID, :V$MCODE, :V$MCAPTION, :V$STAGE
  DO
  BEGIN
    TAG_NAME = 'items:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'items:r:id';
    VAL = V$ID;
    SUSPEND;
    TAG_NAME = 'items:r:parent_id';
    VAL = V$PARENT_ID;
    SUSPEND;
    TAG_NAME = 'items:r:sort_index';
    VAL = V$SORT_INDEX;
    SUSPEND;
    TAG_NAME = 'items:r:code';
    VAL = V$CODE;
    SUSPEND;
    TAG_NAME = 'items:r:name';
    VAL = V$CAPTION;
    SUSPEND;
    TAG_NAME = 'items:r:desc';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'items:r:stage';
    VAL = V$STAGE;
    SUSPEND;
    TAG_NAME = 'items:r:master_id';
    VAL = V$MID;
    SUSPEND;
    TAG_NAME = 'items:r:master_code';
    VAL = V$MCODE;
    SUSPEND;
    TAG_NAME = 'items:r:master_name';
    VAL = V$MCAPTION;
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CEC_DELETE (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
AS
declare variable V$OBJ_ID bigint;
declare variable V$GEN bigint;
declare variable V$MULTIPLIER bigint;
begin

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  IF(NOT EXISTS(
    SELECT 1
    FROM USERS U
    WHERE U.USER_ID = :I$OBJ_ID AND U.DATE_DEL IS NULL AND U.IS_BLOCKED = 0 AND U.USER_TYPE IN (1, 5, 6)
  )) THEN EXCEPTION DATA_ERROR 'Недостаточно прав доступа для выполнения операции';

  SELECT GEN, MULTIPLIER
  FROM GEN
  INTO :V$GEN, :V$MULTIPLIER;

  V$MULTIPLIER = I$OBJ_ID / V$MULTIPLIER;
  IF(V$GEN <> V$MULTIPLIER) THEN EXCEPTION DATA_ERROR 'Нельзя удалить объект, созданный в другой базе';

  SELECT OBJ_ID
  FROM CEC
  WHERE OBJ_ID = :I$OBJ_ID AND DATE_DEL IS NULL
  INTO :V$OBJ_ID;

  IF(V$OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Запись не найдена';

  UPDATE CEC
  SET DATE_DEL = CURRENT_TIMESTAMP
  WHERE OBJ_ID = :I$OBJ_ID;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CEC_DESCRIBE (
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(1000))
AS
declare variable V$OBJ_ID smallint;
declare variable V$CAPTION varchar(1000);
declare variable V$GEN bigint;
declare variable V$LEVEL smallint;
begin

  TAG_NAME = 'items';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'items::json&colon;array';
  VAL = 1;
  SUSPEND;

  V$GEN = (SELECT GEN FROM GEN);
  V$LEVEL = (SELECT KEY_VAL FROM KEYS WHERE KEY_CODE = 'LEVEL');

  FOR
    SELECT T.OBJ_ID, T.CAPTION
    FROM CEC_TYPES T
    WHERE T.IS_DEL = 0
    ORDER BY IIF(T.OBJ_ID >= 10000, 0, 1), 1
    INTO :V$OBJ_ID, :V$CAPTION
  DO
  BEGIN
    TAG_NAME = 'items:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'items:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'items:r:name';
    VAL = V$CAPTION;
    SUSPEND;
    -- Для уровня региона можно править региональные кодификаторы
    TAG_NAME = 'items:r:access';
    IF(V$GEN = 0) THEN VAL = 1;
    ELSE IF(V$LEVEL = 3 AND V$OBJ_ID = 9999) THEN VAL = 1;
    ELSE VAL = 0;
    SUSPEND;
  END

  -- Отдельно фейковая вкладка для УУД, всегда RO
  TAG_NAME = 'items:r';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'items:r:id';
  VAL = 10101;
  SUSPEND;
  TAG_NAME = 'items:r:name';
  VAL = 'УУД';
  SUSPEND;
  TAG_NAME = 'items:r:access';
  VAL = 0;
  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CEC_DE_DELETE (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
AS
declare variable V$OBJ_ID bigint;
declare variable V$GEN bigint;
declare variable V$MULTIPLIER bigint;
begin

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  SELECT GEN, MULTIPLIER
  FROM GEN
  INTO :V$GEN, :V$MULTIPLIER;

  V$MULTIPLIER = I$OBJ_ID / V$MULTIPLIER;
  IF(V$GEN <> V$MULTIPLIER) THEN EXCEPTION DATA_ERROR 'Нельзя удалить объект, созданный в другой базе';

  SELECT OBJ_ID
  FROM CEC_ITEMS
  WHERE OBJ_ID = :I$OBJ_ID AND CEC_ID = 0 AND DATE_DEL IS NULL
  INTO :V$OBJ_ID;

  IF(V$OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Запись не найдена';

  UPDATE CEC_ITEMS
  SET DATE_DEL = CURRENT_TIMESTAMP
  WHERE OBJ_ID = :I$OBJ_ID;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CEC_DE_GET (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
declare variable C varchar(400);
declare variable S varchar(1000);
declare variable V$OBJ_ID bigint;
declare variable V$SUBJECT_ID bigint;
declare variable V$STAGE_ID bigint;
declare variable V$MID varchar(400);
declare variable V$UMK_NAME varchar(400);
declare variable V$AUTHOR_NAME varchar(200);
declare variable V$TYPE_ID bigint;
declare variable V$SOURCE_NAME varchar(200);
declare variable V$CODE varchar(100);
declare variable V$ID bigint;
declare variable P integer;
begin

  SELECT D.OBJ_ID, D.CAPTION, D.SUBJECT_ID, D.DE_TYPE_ID, D.STAGE_ID, D."DESC", D.CODE, D.MASTER_ID, D.UMK_NAME, D.AUTHOR_NAME, D.SOURCE_NAME
  FROM CEC_ITEMS D
  WHERE D.DATE_DEL IS NULL AND D.OBJ_ID = :I$OBJ_ID AND D.CEC_ID = 0
  INTO :V$OBJ_ID, :C, :V$SUBJECT_ID, :V$TYPE_ID, :V$STAGE_ID, :S, :V$CODE, :V$MID, :V$UMK_NAME, :V$AUTHOR_NAME, :V$SOURCE_NAME;

  IF(I$OBJ_ID IS NOT NULL AND V$OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Запись не найдена';

  TAG_NAME = 'id';
  VAL = V$OBJ_ID;
  SUSPEND;

  TAG_NAME = 'caption';
  VAL = C;
  SUSPEND;

  TAG_NAME = 'code';
  VAL = V$CODE;
  SUSPEND;

  TAG_NAME = 'desc';
  VAL = S;
  SUSPEND;

  TAG_NAME = 'umk_name';
  VAL = V$UMK_NAME;
  SUSPEND;

  TAG_NAME = 'author_name';
  VAL = V$AUTHOR_NAME;
  SUSPEND;

  TAG_NAME = 'source_name';
  VAL = V$SOURCE_NAME;
  SUSPEND;

  -- Справочник базовых предметов ФГОС
  TAG_NAME = 'subject_id';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'subject_id:selection';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'subject_id:selection::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
      SELECT L51.OBJ_ID, C.CAPTION
      FROM LINKS L51
      JOIN VALL V2465 ON V2465.OBJ_ID = L51.OBJ_ID AND V2465.PARAM_ID = 2465 AND V2465.IS_DEL = 0 AND V2465.LISTVAL_ID = 2
      LEFT JOIN OBJECT_CAPTION_GET(L51.OBJ_ID) C ON 1 = 1
      WHERE L51.PARENT_ID = 32771 AND L51.OBJ_TYPE_ID = 51 AND L51.DATE_DEL IS NULL
      ORDER BY 2
      INTO :V$ID, :S
  DO
  BEGIN
      TAG_NAME = 'subject_id:selection:option';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'subject_id:selection:option:id';
      VAL = V$ID;
      SUSPEND;
      TAG_NAME = 'subject_id:selection:option:value';
      VAL = S;
      SUSPEND;
  END
  TAG_NAME = 'subject_id:values:value';
  VAL = V$SUBJECT_ID;
  SUSPEND;

  TAG_NAME = 'stage_id';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'stage_id:selection';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'stage_id:selection::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
      SELECT L.LISTVAL_ID, L.VAL
      FROM OO_FILTRED_LIST(25) L
      WHERE L.PARENT_ID IN (2141)
      INTO :V$ID, :S
  DO
  BEGIN
      TAG_NAME = 'stage_id:selection:option';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'stage_id:selection:option:id';
      VAL = V$ID;
      SUSPEND;
      TAG_NAME = 'stage_id:selection:option:value';
      VAL = S;
      SUSPEND;
  END
  TAG_NAME = 'stage_id:values:value';
  VAL = V$STAGE_ID;
  SUSPEND;

  TAG_NAME = 'type_id';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'type_id:selection';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'type_id:selection::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
      SELECT L.LISTVAL_ID, L.VAL
      FROM LISTVALS_LIST(334) L
      WHERE L.IS_DEL = 0
      INTO :V$ID, :S
  DO
  BEGIN
      TAG_NAME = 'type_id:selection:option';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'type_id:selection:option:id';
      VAL = V$ID;
      SUSPEND;
      TAG_NAME = 'type_id:selection:option:value';
      VAL = S;
      SUSPEND;
  END
  TAG_NAME = 'type_id:values:value';
  VAL = V$TYPE_ID;
  SUSPEND;

  IF(V$MID IS NULL) THEN V$MID = '';
  TAG_NAME = 'master_id::json&colon;array';
  VAL = 1;
  SUSPEND;
  WHILE(V$MID <> '') DO
  BEGIN
    P = POSITION(',' IN V$MID);
    IF(P <= 0) THEN P = CHAR_LENGTH(V$MID) + 1;
    TAG_NAME = 'master_id:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'master_id:r:id';
    V$ID = SUBSTRING(V$MID FROM 1 FOR P - 1);
    VAL = V$ID;
    SUSPEND;
    TAG_NAME = 'master_id:r:value';
    VAL = NULL;
    S = NULL;
    V$CODE = NULL;
    SELECT FIRST 1 I.CODE, I.CAPTION, LV.TAG
    FROM CEC_ITEMS I
    LEFT JOIN LISTVALS LV ON LV.LISTVAL_ID = I.STAGE_ID
    WHERE I.OBJ_ID = :V$ID
    INTO :S, :VAL, :V$CODE;
    SUSPEND;
    TAG_NAME = 'master_id:r:code';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'master_id:r:stage';
    VAL = V$CODE;
    SUSPEND;
    V$MID = SUBSTRING(V$MID FROM P + 1);
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CEC_GET (
    I$OBJ_ID BIGINT,
    I$TYPE_ID SMALLINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE S VARCHAR(1000);
DECLARE VARIABLE V$SUBJECT_ID BIGINT;
DECLARE VARIABLE V$TYPE_ID SMALLINT;
DECLARE VARIABLE V$ID BIGINT;
DECLARE VARIABLE V$PARENT_ID BIGINT;
DECLARE VARIABLE V$SORT_INDEX SMALLINT;
DECLARE VARIABLE V$CODE VARCHAR(40);
DECLARE VARIABLE V$CAPTION VARCHAR(1000);
DECLARE VARIABLE V$MID VARCHAR(400);
DECLARE VARIABLE V$GEN BIGINT;
DECLARE VARIABLE V$MULTIPLIER BIGINT;
DECLARE VARIABLE V$STAGE_ID BIGINT;
DECLARE VARIABLE P INTEGER;
begin

  SELECT D.OBJ_ID, D.CAPTION, D.SUBJECT_ID, D.TYPE_ID
  FROM CEC D
  WHERE D.DATE_DEL IS NULL AND D.OBJ_ID = :I$OBJ_ID AND D.TYPE_ID = :I$TYPE_ID
  INTO :V$OBJ_ID, :S, :V$SUBJECT_ID, :V$TYPE_ID;

  IF(I$OBJ_ID IS NOT NULL AND V$OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Запись не найдена';

  SELECT GEN, MULTIPLIER
  FROM GEN
  INTO :V$GEN, :V$MULTIPLIER;
  IF(I$OBJ_ID IS NULL AND V$GEN <> 0 AND I$TYPE_ID <> 9999) THEN EXCEPTION DATA_ERROR 'Нельзя добавлять данные в разделы, кроме регионального';

  TAG_NAME = 'id';
  VAL = V$OBJ_ID;
  SUSPEND;

  TAG_NAME = 'name';
  VAL = S;
  SUSPEND;

  TAG_NAME = 'row_readonly';
  VAL = 0;
  IF(I$OBJ_ID IS NOT NULL AND (V$GEN <> 0 AND V$GEN <> (V$OBJ_ID / V$MULTIPLIER))) THEN VAL = 1;
  SUSPEND;

  -- Справочник базовых предметов ФГОС
  TAG_NAME = 'subject_id:selection::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
      SELECT L51.OBJ_ID, C.CAPTION
      FROM LINKS L51
      JOIN VALL V2465 ON V2465.OBJ_ID = L51.OBJ_ID AND V2465.PARAM_ID = 2465 AND V2465.IS_DEL = 0 AND V2465.LISTVAL_ID = 2
      LEFT JOIN OBJECT_CAPTION_GET(L51.OBJ_ID) C ON 1 = 1
      WHERE L51.PARENT_ID = 32771 AND L51.OBJ_TYPE_ID = 51 AND L51.DATE_DEL IS NULL
      ORDER BY 2
      INTO :V$ID, :S
  DO
  BEGIN
      TAG_NAME = 'subject_id:selection:option';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'subject_id:selection:option:id';
      VAL = V$ID;
      SUSPEND;
      TAG_NAME = 'subject_id:selection:option:value';
      VAL = S;
      SUSPEND;
  END
  TAG_NAME = 'subject_id:values:value';
  VAL = V$SUBJECT_ID;
  SUSPEND;

  TAG_NAME = 'stages::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
      SELECT L.LISTVAL_ID, L.VAL
      FROM LISTVALS_LIST(25) L
      WHERE L.IS_DEL = 0 AND L.PARENT_ID IN (2141)
      INTO :V$ID, :S
  DO
  BEGIN
      TAG_NAME = 'stages:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'stages:r:id';
      VAL = V$ID;
      SUSPEND;
      TAG_NAME = 'stages:r:value';
      VAL = S;
      SUSPEND;
  END

  TAG_NAME = 'type_id';
  VAL = I$TYPE_ID;
  SUSPEND;

  TAG_NAME = 'type_name';
  VAL = (SELECT CAPTION FROM CEC_TYPES WHERE OBJ_ID = :I$TYPE_ID);
  SUSPEND;

  TAG_NAME = 'items::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT D.OBJ_ID, D.PARENT_ID, D.SORT_INDEX, D.CODE, D.CAPTION, D."DESC", D.MASTER_ID, D.STAGE_ID
    FROM CEC_ITEMS D
    WHERE D.DATE_DEL IS NULL AND D.CEC_ID = :I$OBJ_ID
    ORDER BY D.SORT_INDEX
    INTO :V$ID, :V$PARENT_ID, :V$SORT_INDEX, :V$CODE, :V$CAPTION, :S, :V$MID, :V$STAGE_ID
  DO
  BEGIN
    TAG_NAME = 'items:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'items:r:id';
    VAL = V$ID;
    SUSPEND;
    TAG_NAME = 'items:r:parent_id';
    VAL = V$PARENT_ID;
    SUSPEND;
    TAG_NAME = 'items:r:sort_index';
    VAL = V$SORT_INDEX;
    SUSPEND;
    TAG_NAME = 'items:r:code';
    VAL = V$CODE;
    SUSPEND;
    TAG_NAME = 'items:r:name';
    VAL = V$CAPTION;
    SUSPEND;
    TAG_NAME = 'items:r:desc';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'items:r:stage_id';
    VAL = V$STAGE_ID;
    SUSPEND;

    IF(V$MID IS NULL) THEN V$MID = '';
    TAG_NAME = 'items:r:master_id::json&colon;array';
    VAL = 1;
    SUSPEND;
    WHILE(V$MID <> '') DO
    BEGIN
      P = POSITION(',' IN V$MID);
      IF(P <= 0) THEN P = CHAR_LENGTH(V$MID) + 1;
      TAG_NAME = 'items:r:master_id:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'items:r:master_id:r:id';
      V$ID = SUBSTRING(V$MID FROM 1 FOR P - 1);
      VAL = V$ID;
      SUSPEND;
      TAG_NAME = 'items:r:master_id:r:value';
      VAL = NULL;
      S = NULL;
      V$CODE = NULL;
      SELECT FIRST 1 I.CODE, I.CAPTION, LV.TAG
      FROM CEC_ITEMS I
      LEFT JOIN LISTVALS LV ON LV.LISTVAL_ID = I.STAGE_ID
      WHERE I.OBJ_ID = :V$ID
      INTO :S, :VAL, :V$CODE;
      SUSPEND;
      TAG_NAME = 'items:r:master_id:r:code';
      VAL = S;
      SUSPEND;
      TAG_NAME = 'items:r:master_id:r:stage';
      VAL = V$CODE;
      SUSPEND;
      V$MID = SUBSTRING(V$MID FROM P + 1);
    END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CEC_ITEM_DE_SET (
    I$OBJ_ID BIGINT,
    I$TYPE_ID BIGINT,
    I$CODE VARCHAR(40),
    I$NAME VARCHAR(400),
    I$DESC VARCHAR(1000),
    I$MASTER_ID VARCHAR(200),
    I$STAGE_ID BIGINT,
    I$SUBJECT_ID BIGINT,
    I$UMK_NAME VARCHAR(400),
    I$AUTHOR_NAME VARCHAR(200),
    I$SOURCE_NAME VARCHAR(200),
    I$USER_ID VARCHAR(40))
RETURNS (
    OBJ_ID BIGINT)
AS
DECLARE VARIABLE V$NAME VARCHAR(400);
DECLARE VARIABLE V$CODE VARCHAR(40);
DECLARE VARIABLE V$DESC VARCHAR(1000);
DECLARE VARIABLE V$TYPE_ID BIGINT;
DECLARE VARIABLE V$MASTER_ID VARCHAR(400);
DECLARE VARIABLE V$STAGE_ID BIGINT;
DECLARE VARIABLE V$SUBJECT_ID BIGINT;
DECLARE VARIABLE V$UMK_NAME VARCHAR(400);
DECLARE VARIABLE V$AUTHOR_NAME VARCHAR(200);
DECLARE VARIABLE V$SOURCE_NAME VARCHAR(200);
begin

  IF(I$OBJ_ID IS NOT NULL) THEN
  BEGIN
    SELECT OBJ_ID, CAPTION, CODE, "DESC", MASTER_ID, STAGE_ID, SUBJECT_ID, DE_TYPE_ID, UMK_NAME, AUTHOR_NAME, SOURCE_NAME
    FROM CEC_ITEMS
    WHERE OBJ_ID = :I$OBJ_ID AND CEC_ID = 0 AND DATE_DEL IS NULL
    INTO :OBJ_ID, :V$NAME, :V$CODE, :V$DESC, :V$MASTER_ID, :V$STAGE_ID, :V$SUBJECT_ID, :V$TYPE_ID, :V$UMK_NAME, :V$AUTHOR_NAME, :V$SOURCE_NAME;

    IF(OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Дидактическая единица не найдена или была удалена';
  END

  IF(I$OBJ_ID IS NULL) THEN
  BEGIN
    INSERT INTO CEC_ITEMS
    (CEC_ID, SORT_INDEX, CODE, CAPTION, "DESC", STAGE_ID, SUBJECT_ID, DE_TYPE_ID, UMK_NAME, AUTHOR_NAME, SOURCE_NAME)
    VALUES (0, 0, :I$CODE, :I$NAME, :I$DESC, :I$STAGE_ID, :I$SUBJECT_ID, :I$TYPE_ID, :I$UMK_NAME, :I$AUTHOR_NAME, :I$SOURCE_NAME)
    RETURNING OBJ_ID INTO :OBJ_ID;
  END
  ELSE IF(I$CODE <> V$CODE OR I$NAME <> V$NAME OR I$DESC <> V$DESC OR COALESCE(I$MASTER_ID, '') <> COALESCE(V$MASTER_ID, '') OR COALESCE(I$STAGE_ID, -1) <> COALESCE(V$STAGE_ID, -1)
    OR COALESCE(I$SUBJECT_ID, -1) <> COALESCE(V$SUBJECT_ID, -1) OR COALESCE(I$TYPE_ID, -1) <> COALESCE(V$TYPE_ID, -1) OR COALESCE(I$UMK_NAME, '') <> COALESCE(V$UMK_NAME, '')
    OR COALESCE(I$AUTHOR_NAME, '') <> COALESCE(V$AUTHOR_NAME, '') OR COALESCE(I$SOURCE_NAME, '') <> COALESCE(V$SOURCE_NAME, '')
  ) THEN
  BEGIN
    UPDATE CEC_ITEMS
    SET CAPTION = :I$NAME, CODE = :I$CODE, "DESC" = :I$DESC, SORT_INDEX = 0, MASTER_ID = :I$MASTER_ID,
      STAGE_ID = :I$STAGE_ID, SUBJECT_ID = :I$SUBJECT_ID, DE_TYPE_ID = :I$TYPE_ID, UMK_NAME = :I$UMK_NAME, AUTHOR_NAME = :I$AUTHOR_NAME, SOURCE_NAME = :I$SOURCE_NAME,
      DATE_MODIFY = CURRENT_TIMESTAMP
    WHERE OBJ_ID = :I$OBJ_ID;
  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CEC_ITEM_SET (
    I$CEC_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40),
    I$DELETED SMALLINT,
    I$SORT_INDEX SMALLINT,
    I$CODE VARCHAR(40),
    I$NAME VARCHAR(400),
    I$DESC VARCHAR(1000),
    I$PARENT_ID BIGINT,
    I$MASTER_ID VARCHAR(200),
    I$STAGE_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$NAME varchar(400);
declare variable V$CODE varchar(40);
declare variable V$DESC varchar(1000);
declare variable V$INDEX integer;
declare variable V$PARENT_ID bigint;
declare variable V$MASTER_ID varchar(400);
declare variable V$STAGE_ID bigint;
begin

  IF(I$OBJ_ID IS NOT NULL) THEN
  BEGIN
    SELECT OBJ_ID, CAPTION, CODE, "DESC", SORT_INDEX, PARENT_ID, MASTER_ID, STAGE_ID
    FROM CEC_ITEMS
    WHERE OBJ_ID = :I$OBJ_ID AND CEC_ID = :I$CEC_ID AND DATE_DEL IS NULL
    INTO :OBJ_ID, :V$NAME, :V$CODE, :V$DESC, :V$INDEX, :V$PARENT_ID, :V$MASTER_ID, :V$STAGE_ID;

    IF(OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Элемент содержания не найден или был удален';
  END

  IF(I$DELETED = 1) THEN
  BEGIN
    UPDATE CEC_ITEMS
    SET DATE_DEL = CURRENT_TIMESTAMP
    WHERE OBJ_ID = :I$OBJ_ID;
  END
  ELSE IF(I$OBJ_ID IS NULL) THEN
  BEGIN
    INSERT INTO CEC_ITEMS
    (CEC_ID, SORT_INDEX, CODE, CAPTION, "DESC", STAGE_ID)
    VALUES (:I$CEC_ID, :I$SORT_INDEX, :I$CODE, :I$NAME, :I$DESC, :I$STAGE_ID)
    RETURNING OBJ_ID INTO :OBJ_ID;
  END
  ELSE IF(I$CODE <> V$CODE OR I$NAME <> V$NAME OR I$DESC <> V$DESC OR I$SORT_INDEX <> V$INDEX OR COALESCE(I$PARENT_ID, -1) <> COALESCE(V$PARENT_ID, -1) OR
    COALESCE(I$MASTER_ID, '') <> COALESCE(V$MASTER_ID, '') OR COALESCE(I$STAGE_ID, -1) <> COALESCE(V$STAGE_ID, -1)) THEN
  BEGIN
    UPDATE CEC_ITEMS
    SET CAPTION = :I$NAME, CODE = :I$CODE, "DESC" = :I$DESC, SORT_INDEX = :I$SORT_INDEX, PARENT_ID = :I$PARENT_ID, MASTER_ID = :I$MASTER_ID,
      DATE_MODIFY = CURRENT_TIMESTAMP
    WHERE OBJ_ID = :I$OBJ_ID;
  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CEC_SET (
    I$TYPE SMALLINT,
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40),
    I$NAME VARCHAR(400),
    I$SUBJECT_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT)
AS
DECLARE VARIABLE V$GEN BIGINT;
DECLARE VARIABLE V$MULTIPLIER BIGINT;
begin

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  IF(NOT EXISTS(
    SELECT 1
    FROM USERS U
    WHERE U.USER_ID = :I$USER_ID AND U.DATE_DEL IS NULL AND U.IS_BLOCKED = 0 AND U.USER_TYPE IN (1, 5, 6)
  )) THEN EXCEPTION DATA_ERROR 'Недостаточно прав доступа для выполнения операции';

  SELECT GEN, MULTIPLIER
  FROM GEN
  INTO :V$GEN, :V$MULTIPLIER;

  V$MULTIPLIER = I$OBJ_ID / V$MULTIPLIER;
  IF(V$GEN <> V$MULTIPLIER) THEN EXCEPTION DATA_ERROR 'Нельзя изменять раздел, созданный в другой базе';
  IF(I$OBJ_ID IS NULL AND V$GEN <> 0 AND I$TYPE <> 9999) THEN EXCEPTION DATA_ERROR 'Нельзя добавлять данные в разделы, кроме регионального';

  SELECT OBJ_ID
  FROM CEC
  WHERE OBJ_ID = :I$OBJ_ID AND DATE_DEL IS NULL
  INTO :OBJ_ID;

  IF(I$OBJ_ID IS NOT NULL AND OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Запись не найдена';

  IF(I$OBJ_ID IS NULL) THEN
  BEGIN

    INSERT INTO CEC
    (TYPE_ID, CAPTION, SUBJECT_ID, USER_ID)
    VALUES (:I$TYPE, :I$NAME, :I$SUBJECT_ID, :I$USER_ID)
    RETURNING OBJ_ID INTO :OBJ_ID;

  END
  ELSE
  BEGIN

    UPDATE CEC
    SET CAPTION = :I$NAME, DATE_MODIFY = CURRENT_TIMESTAMP, USER_ID = :I$USER_ID
    WHERE OBJ_ID = :I$OBJ_ID;

    OBJ_ID = :I$OBJ_ID;

  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CEC_USA_GET (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
declare variable V$MASK smallint;
begin

  TAG_NAME = 'id';
  VAL = I$OBJ_ID;
  SUSPEND;

  TAG_NAME = 'caption';
  SELECT R.VAL, LV.COST
  FROM LISTVALS LV
  JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
  WHERE LV.LISTVAL_ID = :I$OBJ_ID AND LV.IS_DEL = 0 AND LV.LIST_ID = 330
  INTO :VAL, :V$MASK;
  SUSPEND;

  TAG_NAME = 'apply_to';
  VAL = COALESCE(V$MASK, 0);
  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CERTIFICATE2_ADD (
    I$OBJ_ID BIGINT,
    I$PUPIL_ID BIGINT,
    I$NAME_FIRST VARCHAR(400),
    I$NAME_MID VARCHAR(400),
    I$NAME_LAST VARCHAR(400),
    I$BIRTH_DATE DATE,
    I$YEAR_ACCEPT SMALLINT,
    I$YEAR_LEAVE SMALLINT,
    I$SEX BIGINT,
    I$BLANK_STATE BIGINT,
    I$CERT_TYPE BIGINT,
    I$CERT_KIND BIGINT,
    I$STAGE_ID BIGINT,
    I$ISSUE_DATE DATE,
    I$CERT_SERIE VARCHAR(40),
    I$CERT_NUMBER VARCHAR(40),
    I$IS_OWN SMALLINT,
    I$ISSUED_BY VARCHAR(1000),
    I$PARENT_ID BIGINT,
    I$USER_ID BIGINT,
    I$SNILS VARCHAR(40),
    I$CITIZENSHIP BIGINT,
    I$BIRTH_PLACE VARCHAR(200),
    I$ORIG_SERIE VARCHAR(40),
    I$ORIG_NUMBER VARCHAR(40),
    I$ORIG_DATE DATE)
RETURNS (
    OBJ_ID BIGINT,
    STAGE_ID BIGINT)
AS
declare variable V$YEAR_OUT integer;
declare variable V$OU_ID bigint;
declare variable V$FOLDER_ID bigint;
declare variable V$YEAR_ID bigint;
declare variable V$SEX bigint;
declare variable TMP bigint;
begin

  -- STAGE_ID всегда формируется автоматически по типу бланка
  IF(I$CERT_TYPE IN (1375, 3241)) THEN I$STAGE_ID = 26;
  ELSE IF(I$CERT_TYPE IN (1376, 3240, 3149, 1382)) THEN I$STAGE_ID = 27;
  ELSE IF(I$CERT_TYPE IN (1379)) THEN I$STAGE_ID = 28;
  ELSE IF(I$CERT_TYPE IN (1380, 12785)) THEN I$STAGE_ID = 29;
  ELSE EXCEPTION DATA_ERROR 'Недопустимый код типа документа';

  IF(I$YEAR_LEAVE >= EXTRACT(YEAR FROM CURRENT_DATE)) THEN EXCEPTION DATA_ERROR 'Нельзя добавлять вручную документы учеников текущего года выпуска';

  I$CERT_SERIE = UPPER(TRIM(I$CERT_SERIE));
  I$CERT_NUMBER = UPPER(TRIM(I$CERT_NUMBER));
  IF(I$CERT_SERIE = '') THEN I$CERT_SERIE = NULL;
  I$ORIG_SERIE = UPPER(TRIM(I$ORIG_SERIE));
  I$ORIG_NUMBER = UPPER(TRIM(I$ORIG_NUMBER));
  IF(I$ORIG_SERIE = '') THEN I$ORIG_SERIE = NULL;
  IF(I$ORIG_NUMBER = '') THEN I$ORIG_NUMBER = NULL;
  IF(I$ORIG_DATE IS NOT NULL AND I$ORIG_DATE > I$ISSUE_DATE) THEN EXCEPTION DATA_ERROR 'Оригинальный документ не может быть датирован позднее заменяющего';

  -- Если не указана ОУ, пишем себя (краткое наименование)
  IF(I$ISSUED_BY = '') THEN I$ISSUED_BY = NULL;
  IF(I$ISSUED_BY IS NULL) THEN
  BEGIN
      SELECT V2.VAL
      FROM LINKS L2
      JOIN VALS V2 ON V2.OBJ_ID = L2.OBJ_ID AND V2.PARAM_ID = 2 AND V2.IS_DEL = 0
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      INTO :I$ISSUED_BY;
  END

  -- Проверяем, что такая пара серия-номер еще не внесены
  IF(EXISTS(
      SELECT FIRST 1 1
      FROM CERT_DATA
      WHERE DATE_DEL IS NULL AND (:I$OBJ_ID IS NULL OR OBJ_ID <> :I$OBJ_ID)
          AND (:I$CERT_SERIE IS NULL OR CERT_SERIE = :I$CERT_SERIE)
          AND CERT_NUMBER = :I$CERT_NUMBER
  )) THEN EXCEPTION DATA_ERROR 'Документ с такими реквизитами бланка уже внесен в систему';

  -- Если ученик уже есть, обновляем данные из него
  IF(I$PUPIL_ID IS NOT NULL) THEN
  BEGIN
  END

  IF(I$OBJ_ID IS NOT NULL) THEN
  BEGIN

      -- Статус документа с рабочего на нерабочий меняться не может
      SELECT FIRST 1 D.OBJ_ID, D.BLANK_STATE
      FROM CERT_DATA D
      WHERE D.DATE_DEL IS NULL AND D.OBJ_ID = :I$OBJ_ID
      INTO :OBJ_ID, :TMP;

      IF(OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Документ не найден или был удален';
      IF(I$BLANK_STATE <> TMP) THEN EXCEPTION DATA_ERROR 'Статус документа не может изменяться';

      -- Владелец документа меняться не может, связь с родительским документом тоже
      UPDATE CERT_DATA
      SET NAME_FIRST = :I$NAME_FIRST, NAME_MID = :I$NAME_MID, NAME_LAST = :I$NAME_LAST, BIRTH_DATE = :I$BIRTH_DATE, YEAR_ACCEPT = :I$YEAR_ACCEPT,
          YEAR_LEAVE = :I$YEAR_LEAVE, SEX = :I$SEX, BLANK_STATE = :I$BLANK_STATE, CERT_TYPE = :I$CERT_TYPE, CERT_KIND = :I$CERT_KIND,
          STAGE_ID = :I$STAGE_ID, ISSUE_DATE = :I$ISSUE_DATE, CERT_SERIE = :I$CERT_SERIE, CERT_NUMBER = :I$CERT_NUMBER, ISSUED_BY = :I$ISSUED_BY,
          SNILS = :I$SNILS, CITIZENSHIP = :I$CITIZENSHIP, BIRTH_PLACE = :I$BIRTH_PLACE
      WHERE OBJ_ID = :I$OBJ_ID;

  END
  ELSE
  BEGIN

      IF(I$PUPIL_ID IS NULL) THEN
      BEGIN

          SELECT FIRST 1 L10.OBJ_ID, V451.VAL, V88.LISTVAL_ID
          FROM LINKS L2
          JOIN LINKS L78 ON L78.PARENT_ID = L2.OBJ_ID AND L78.OBJ_TYPE_ID = 78 AND L78.DATE_DEL IS NULL
          JOIN LINKS L83 ON L83.PARENT_ID = L78.OBJ_ID AND L83.OBJ_TYPE_ID = 83 AND L83.DATE_DEL IS NULL
          JOIN VALI V451 ON V451.OBJ_ID = L83.OBJ_ID AND V451.PARAM_ID = 451 AND V451.IS_DEL = 0 AND V451.VAL >= :I$YEAR_LEAVE - 2 AND V451.VAL <= :I$YEAR_LEAVE + 2
          JOIN LINKS L10 ON L10.PARENT_ID = L83.OBJ_ID AND L10.OBJ_TYPE_ID IN (10, 126) AND L10.DATE_DEL IS NULL
          JOIN VALD V89 ON V89.OBJ_ID = L10.OBJ_ID AND V89.PARAM_ID IN (89, 830) AND V89.IS_DEL = 0 AND V89.VAL = :I$BIRTH_DATE
          JOIN VALS V55 ON V55.OBJ_ID = L10.OBJ_ID AND V55.PARAM_ID IN (55, 827) AND V55.IS_DEL = 0 AND V55.VAL = :I$NAME_LAST
          JOIN VALS V56 ON V56.OBJ_ID = L10.OBJ_ID AND V56.PARAM_ID IN (56, 828) AND V56.IS_DEL = 0 AND V56.VAL = :I$NAME_FIRST
          LEFT JOIN VALS V57 ON V57.OBJ_ID = L10.OBJ_ID AND V57.PARAM_ID IN (57, 829) AND V57.IS_DEL = 0
          LEFT JOIN VALL V88 ON V88.OBJ_ID = L10.OBJ_ID AND V88.PARAM_ID IN (88, 1022) AND V88.IS_DEL = 0
          WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND (:I$NAME_MID IS NULL OR V57.VAL = :I$NAME_MID)
          INTO :I$PUPIL_ID, :V$YEAR_OUT, :V$SEX;

          -- Если не указан PUPIL_ID, ищем ученика по сочетанию параметров с зазором в 2 года в каждую сторону
          IF(I$PUPIL_ID IS NULL) THEN
          BEGIN

              -- Если таки не был найден, регистрируем
              SELECT FIRST 1 L83.OBJ_ID
              FROM LINKS L2
              JOIN LINKS L78 ON L78.PARENT_ID = L2.OBJ_ID AND L78.OBJ_TYPE_ID = 78 AND L78.DATE_DEL IS NULL
              JOIN LINKS L83 ON L83.PARENT_ID = L78.OBJ_ID AND L83.OBJ_TYPE_ID = 83 AND L83.DATE_DEL IS NULL
              JOIN VALI V451 ON V451.OBJ_ID = L83.OBJ_ID AND V451.PARAM_ID = 451 AND V451.IS_DEL = 0 AND V451.VAL = :I$YEAR_LEAVE
              WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
              INTO :V$YEAR_ID;

              IF(V$YEAR_ID IS NULL) THEN
              BEGIN

                  SELECT FIRST 1 L78.OBJ_ID
                  FROM LINKS L2
                  JOIN LINKS L78 ON L78.PARENT_ID = L2.OBJ_ID AND L78.OBJ_TYPE_ID = 78 AND L78.DATE_DEL IS NULL
                  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
                  INTO :V$FOLDER_ID;

                  IF(V$FOLDER_ID IS NULL) THEN
                  BEGIN
                      SELECT FIRST 1 L2.OBJ_ID
                      FROM LINKS L2
                      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
                      INTO :V$OU_ID;

                      SELECT OBJ_ID FROM OBJECT_ADD(:V$OU_ID, 78) INTO :V$FOLDER_ID;
                  END

                  SELECT OBJ_ID FROM OBJECT_ADD_WITH_PARAM(:V$FOLDER_ID, NULL, 83, 451, :I$YEAR_LEAVE) INTO :V$YEAR_ID;

              END

              SELECT OBJ_ID FROM OBJECT_ADD(:V$YEAR_ID, 10) INTO :I$PUPIL_ID;

              SELECT BLOB_ID FROM VAL_ADD(55, :I$PUPIL_ID, :I$NAME_LAST) INTO :TMP;
              SELECT BLOB_ID FROM VAL_ADD(56, :I$PUPIL_ID, :I$NAME_FIRST) INTO :TMP;
              IF(I$NAME_MID IS NOT NULL) THEN SELECT BLOB_ID FROM VAL_ADD(57, :I$PUPIL_ID, :I$NAME_MID) INTO :TMP;
              SELECT BLOB_ID FROM VAL_ADD(89, :I$PUPIL_ID, :I$BIRTH_DATE) INTO :TMP;
              SELECT BLOB_ID FROM VAL_ADD(88, :I$PUPIL_ID, :I$SEX) INTO :TMP;
              SELECT BLOB_ID FROM VAL_ADD(91, :I$PUPIL_ID, :I$CITIZENSHIP) INTO :TMP;
              SELECT BLOB_ID FROM VAL_ADD(1343, :I$PUPIL_ID, :I$BIRTH_PLACE) INTO :TMP;
              SELECT BLOB_ID FROM VAL_ADD(1409, :I$PUPIL_ID, :I$SNILS) INTO :TMP;

          END
          ELSE
          BEGIN
              IF(V$YEAR_OUT <> I$YEAR_LEAVE) THEN EXCEPTION DATA_ERROR 'Данный ученик окончил школу в ' || V$YEAR_OUT || ' году, а не в ' || I$YEAR_LEAVE;
              IF(V$SEX <> I$SEX) THEN EXCEPTION DATA_ERROR 'Сохраненный в архиве пол ученика не совпадает с указанным';
          END

      END

      -- Проверяем наличие первоначального документа
      IF(I$PARENT_ID IS NULL AND I$BLANK_STATE IN (5439, 5440)) THEN
      BEGIN
          IF(I$ORIG_NUMBER IS NULL OR I$ORIG_DATE IS NULL) THEN EXCEPTION DATA_ERROR 'Не заполнены данные по оригинальному документу';

          SELECT FIRST 1 D.OBJ_ID
          FROM CERT_DATA D
          WHERE D.DATE_DEL IS NULL AND ((:I$ORIG_SERIE IS NULL AND D.CERT_SERIE IS NULL) OR D.CERT_SERIE = :I$ORIG_SERIE) AND D.CERT_NUMBER = :I$ORIG_NUMBER
              AND D.PUPIL_ID = :I$PUPIL_ID AND D.ISSUE_DATE = :I$ORIG_DATE
          INTO :I$PARENT_ID;

          IF(I$PARENT_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не найдено данных по оригинальному документу, он должен быть внесен в реестр до внесения основанных на нем документов';
      END

      INSERT INTO CERT_DATA
      (PUPIL_ID, NAME_FIRST, NAME_MID, NAME_LAST, BIRTH_DATE, YEAR_ACCEPT, YEAR_LEAVE, SEX, BLANK_STATE, CERT_TYPE, CERT_KIND,
          STAGE_ID, ISSUE_DATE, CERT_SERIE, CERT_NUMBER, IS_OWN, ISSUED_BY, PARENT_ID, USER_ADD, SNILS, CITIZENSHIP, BIRTH_PLACE)
      VALUES (:I$PUPIL_ID, :I$NAME_FIRST, :I$NAME_MID, :I$NAME_LAST, :I$BIRTH_DATE, :I$YEAR_ACCEPT, :I$YEAR_LEAVE, :I$SEX, :I$BLANK_STATE, :I$CERT_TYPE, :I$CERT_KIND,
          :I$STAGE_ID, :I$ISSUE_DATE, :I$CERT_SERIE, :I$CERT_NUMBER, :I$IS_OWN, :I$ISSUED_BY, :I$PARENT_ID, :I$USER_ID, :I$SNILS, :I$CITIZENSHIP, :I$BIRTH_PLACE)
      RETURNING OBJ_ID INTO :OBJ_ID;

  END

  STAGE_ID = I$STAGE_ID;
  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CERTIFICATE2_DEL (
    I$OBJ_ID BIGINT,
    I$USER_ID BIGINT)
AS
begin

  UPDATE CERT_DATA
  SET DATE_DEL = CURRENT_TIMESTAMP, USER_DEL = :I$OBJ_ID
  WHERE OBJ_ID = :I$OBJ_ID AND DATE_DEL IS NULL;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CERTIFICATE2_LIST (
    I$STAGE_ID BIGINT,
    I$YEAR1 DATE,
    I$YEAR2 DATE,
    I$OBJ_ID BIGINT = null,
    I$NUMBER VARCHAR(100) = null)
RETURNS (
    OBJ_ID BIGINT,
    PUPIL_ID BIGINT,
    NAME_FIRST VARCHAR(400),
    NAME_MID VARCHAR(400),
    NAME_LAST VARCHAR(400),
    BIRTH_DATE DATE,
    YEAR_ACCEPT SMALLINT,
    YEAR_LEAVE SMALLINT,
    SEX BIGINT,
    SEX_NAME VARCHAR(20),
    BLANK_STATE BIGINT,
    BLANK_STATE_NAME VARCHAR(100),
    BLANK_STATE_NAME2 VARCHAR(100),
    CERT_TYPE BIGINT,
    CERT_TYPE_NAME VARCHAR(200),
    CERT_TYPE_NAME2 VARCHAR(200),
    CERT_KIND BIGINT,
    CERT_KIND_NAME VARCHAR(100),
    STAGE_ID BIGINT,
    STAGE_NAME VARCHAR(100),
    ISSUE_DATE DATE,
    CERT_SERIE VARCHAR(40),
    CERT_NUMBER VARCHAR(40),
    IS_OWN SMALLINT,
    ISSUED_BY VARCHAR(1000),
    SNILS VARCHAR(40),
    BIRTH_PLACE VARCHAR(200),
    CITIZENSHIP BIGINT,
    CITIZENSHIP_NAME VARCHAR(200),
    CITIZENSHIP_OUT VARCHAR(200),
    ORIGINAL_SERIE VARCHAR(40),
    ORIGINAL_NUMBER VARCHAR(40),
    ORIGINAL_DATE DATE,
    ORIG_TYPE_NAME VARCHAR(200),
    MISS_TEXT VARCHAR(10),
    REPL_TEXT VARCHAR(10))
AS
declare variable V$PARENT_ID bigint;
begin

  IF(I$NUMBER IS NOT NULL) THEN
  BEGIN
      I$STAGE_ID = NULL;
      I$YEAR1 = NULL;
      I$YEAR2 = NULL;
  END

  FOR
      SELECT OBJ_ID, PUPIL_ID, PARENT_ID, NAME_FIRST, NAME_MID, NAME_LAST, BIRTH_DATE, YEAR_ACCEPT, YEAR_LEAVE, SEX, BLANK_STATE,
          CERT_TYPE, CERT_KIND, STAGE_ID, ISSUE_DATE, CERT_SERIE, CERT_NUMBER, IS_OWN, ISSUED_BY, SNILS, CITIZENSHIP, BIRTH_PLACE
      FROM CERT_DATA D
      WHERE D.DATE_DEL IS NULL AND (:I$STAGE_ID IS NULL OR D.STAGE_ID = :I$STAGE_ID)
          AND (:I$YEAR1 IS NULL OR D.ISSUE_DATE >= :I$YEAR1)
          AND (:I$YEAR2 IS NULL OR D.ISSUE_DATE <= :I$YEAR2)
          AND (:I$OBJ_ID IS NULL OR D.OBJ_ID = :I$OBJ_ID)
          AND (:I$NUMBER IS NULL OR D.CERT_NUMBER = :I$NUMBER)
      INTO :OBJ_ID, :PUPIL_ID, :V$PARENT_ID, :NAME_FIRST, :NAME_MID, :NAME_LAST, :BIRTH_DATE, :YEAR_ACCEPT, :YEAR_LEAVE, :SEX, :BLANK_STATE,
          :CERT_TYPE, :CERT_KIND, :STAGE_ID, :ISSUE_DATE, :CERT_SERIE, :CERT_NUMBER, :IS_OWN, :ISSUED_BY, :SNILS, :CITIZENSHIP,
          :BIRTH_PLACE
  DO
  BEGIN
      SELECT R.VAL
      FROM LISTVALS LV
      JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
      WHERE LV.LISTVAL_ID = :SEX
      INTO :SEX_NAME;

      SELECT R.VAL
      FROM LISTVALS LV
      JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
      WHERE LV.LISTVAL_ID = :BLANK_STATE
      INTO :BLANK_STATE_NAME;

      BLANK_STATE_NAME2 = BLANK_STATE_NAME;
      IF(BLANK_STATE = 5438) THEN BLANK_STATE_NAME2 = 'Оригинал';

      SELECT R.VAL
      FROM LISTVALS LV
      JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
      WHERE LV.LISTVAL_ID = :CERT_TYPE
      INTO :CERT_TYPE_NAME;

      CERT_TYPE_NAME2 = CERT_TYPE_NAME; -- !!!!

      SELECT R.VAL
      FROM LISTVALS LV
      JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
      WHERE LV.LISTVAL_ID = :CERT_KIND
      INTO :CERT_KIND_NAME;

      SELECT R.VAL
      FROM LISTVALS LV
      JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
      WHERE LV.LISTVAL_ID = :STAGE_ID
      INTO :STAGE_NAME;

      SELECT R.VAL
      FROM LISTVALS LV
      JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
      WHERE LV.LISTVAL_ID = :CITIZENSHIP
      INTO :CITIZENSHIP_NAME;

      IF(CITIZENSHIP IS NULL) THEN CITIZENSHIP_OUT = '';
      ELSE IF(CITIZENSHIP = 1515) THEN CITIZENSHIP_OUT = 'РФ';
      ELSE IF(CITIZENSHIP IN (1516, 1519, 1526, 1532, 1564, 1585, 1592, 1602, 1607, 1623, 1675, 1684, 1687, 1688, 1707, 12900)) THEN CITIZENSHIP_OUT = 'ближнее (из стран СНГ, Балтии, Грузии, Абхазии и Южной Осетии)';
      ELSE CITIZENSHIP_OUT = 'дальнее (других иностранных - кроме стран СНГ, Балтии, Грузии, Абхазии и Южной Осетии)';

      -- Связь с первоначальным документом
      ORIG_TYPE_NAME = NULL;
      ORIGINAL_SERIE = NULL;
      ORIGINAL_NUMBER = NULL;
      ORIGINAL_DATE = NULL;

      IF(V$PARENT_ID IS NOT NULL) THEN
      BEGIN
          SELECT D.CERT_SERIE, D.CERT_NUMBER, D.ISSUE_DATE, R.VAL
          FROM CERT_DATA D
          JOIN LISTVALS LV ON LV.LISTVAL_ID = D.CERT_TYPE
          JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
          WHERE D.DATE_DEL IS NULL AND D.OBJ_ID = :V$PARENT_ID
          INTO :ORIGINAL_SERIE, :ORIGINAL_NUMBER, :ORIGINAL_DATE, :ORIG_TYPE_NAME;
      END

      MISS_TEXT = 'Нет';
      REPL_TEXT = 'Нет';
      IF(EXISTS(
          SELECT FIRST 1 1
          FROM CERT_DATA D
          WHERE D.DATE_DEL IS NULL AND D.PARENT_ID = :OBJ_ID
      ))
      THEN
      BEGIN
          MISS_TEXT = 'Да';
          REPL_TEXT = 'Да';
      END
      ELSE IF(BLANK_STATE = 5441) THEN MISS_TEXT = 'Да'; -- для испорченных

      SUSPEND;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CERTIFICATE2_YEARS RETURNS (
    Y INTEGER)
AS
begin
  FOR
      SELECT DISTINCT EXTRACT(YEAR FROM D.ISSUE_DATE)
      FROM CERT_DATA D
      WHERE D.DATE_DEL IS NULL
      INTO :Y
  DO
  BEGIN
      SUSPEND;
  END
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CERTIFICATE_BASE_TMP_GET (
    I$TEMPLATE_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    TEMPLATE_ID BIGINT,
    STAGE_TYPE_ID BIGINT,
    TEMPLATE_TYPE_ID BIGINT,
    PRINT_TEMPLATE_ID BIGINT,
    TEMPLATE_NAME VARCHAR(255),
    TEMPLATE_DATA VARCHAR(4000))
AS
BEGIN
    SELECT I
    FROM VAL_GET(:I$TEMPLATE_ID, 1841, 0, :I$USER_ID)
    INTO :STAGE_TYPE_ID;

    SELECT I, LV.COST
    FROM VAL_GET(:I$TEMPLATE_ID, 1840, 0, :I$USER_ID) V
    JOIN LISTVALS LV
    ON LV.LISTVAL_ID = V.I
    INTO :TEMPLATE_TYPE_ID, :PRINT_TEMPLATE_ID;
    
    SELECT V
    FROM VAL_GET(:I$TEMPLATE_ID, 1838, 0, :I$USER_ID)
    INTO :TEMPLATE_NAME;
    
    SELECT V
    FROM VAL_GET(:I$TEMPLATE_ID, 1839, 0, :I$USER_ID)
    INTO :TEMPLATE_DATA;
    
    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CERTIFICATE_CLASSES_LIST (
    I$STAGE_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    CLASS_ID BIGINT,
    CLASS_NAME VARCHAR(255))
AS
declare variable V$LICENCE_TYPE varchar(1);
declare variable V$SCHOOL_ID bigint;
declare variable V$PLAN_ID bigint;
declare variable V$PARALLEL_TYPE_ID bigint;
declare variable V$IS_FIRST smallint;
declare variable V$PARALLEL_COST integer;
BEGIN

    SELECT STATUS FROM OU_LICENCE_TYPE
    INTO :V$LICENCE_TYPE;

    -- в колледжах учебные планы не ведут (они другие), поэтому так.
    IF (V$LICENCE_TYPE = 'C') THEN
    BEGIN
        FOR
            SELECT L9.OBJ_ID
            FROM LINKS L8
            JOIN VALL V8 ON V8.PARAM_ID = 49 AND V8.OBJ_ID = L8.OBJ_ID AND V8.IS_DEL = 0 AND V8.LISTVAL_ID IN (51, 52, 53, 54)
            JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
            WHERE L8.PARENT_ID = :I$STAGE_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
            INTO :CLASS_ID
        DO
        BEGIN
            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:CLASS_ID)
            INTO :CLASS_NAME;
  
            SUSPEND;
        END
        EXIT;
    END

    FOR 
        SELECT L125.OBJ_ID
        FROM LINKS L8
        JOIN LINKS L125 ON L125.PARENT_ID = L8.OBJ_ID AND L125.OBJ_TYPE_ID = 125 AND L125.DATE_DEL IS NULL
        WHERE L8.PARENT_ID = :I$STAGE_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
        INTO :CLASS_ID
    DO
    BEGIN
        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:CLASS_ID)
        INTO :CLASS_NAME;

        SUSPEND;
    END

    -- Разрешена печать аттестатов в 9, 10, 11, 12 параллелях экстернатов
    FOR 
        SELECT L187.OBJ_ID
        FROM LINKS L8
        JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0 AND V49.LISTVAL_ID IN (45, 46, 47, 48)
        JOIN LINKS L187 ON L187.PARENT_ID = L8.OBJ_ID AND L187.OBJ_TYPE_ID = 187 AND L187.DATE_DEL IS NULL
        WHERE L8.PARENT_ID = :I$STAGE_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
        INTO :CLASS_ID
    DO
    BEGIN
        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:CLASS_ID)
        INTO :CLASS_NAME;

        SUSPEND;
    END

    FOR
        SELECT FIRST 1 LP2.PARENT_ID
        FROM LINKS LP2
        WHERE LP2.OBJ_ID = :I$STAGE_ID AND LP2.PARENT_TYPE_ID = 2 AND LP2.DATE_DEL IS NULL
        INTO :V$SCHOOL_ID
    DO
    BEGIN
        FOR
            SELECT L400.OBJ_ID
            FROM LINKS L69
            JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
            JOIN VALL V1594 ON V1594.OBJ_ID = L57.OBJ_ID AND V1594.PARAM_ID = 1594 AND V1594.IS_DEL = 0 AND V1594.LISTVAL_ID IN (5341, 5343, 5346, 13272)
            JOIN LINKS L400 ON L400.PARENT_ID = L57.OBJ_ID AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL
            WHERE L69.PARENT_ID = :V$SCHOOL_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL
            INTO :V$PLAN_ID
        DO
        BEGIN
            V$IS_FIRST = 1;
            FOR
                SELECT LV.LISTVAL_ID, LV.COST
                FROM LINKS L54
                JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
                JOIN LISTVALS LV ON LV.LISTVAL_ID = V381.LISTVAL_ID
                WHERE L54.PARENT_ID = :V$PLAN_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
                AND EXISTS (
                    SELECT FIRST 1 1
                    FROM LINKS L256
                    JOIN LINKS L10 ON L10.PARENT_ID = L256.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
                    WHERE L256.PARENT_ID = L54.OBJ_ID AND L256.OBJ_TYPE_ID = 256 AND L256.DATE_DEL IS NULL
                    UNION
                    SELECT FIRST 1 1
                    FROM LINKS L346
                    JOIN LINKS L347 ON L347.PARENT_ID = L346.OBJ_ID AND L347.OBJ_TYPE_ID = 347 AND L347.DATE_DEL IS NULL
                    JOIN LINKS L10 ON L10.PARENT_ID = L347.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
                    WHERE L346.PARENT_ID = L54.OBJ_ID AND L346.OBJ_TYPE_ID = 346 AND L346.DATE_DEL IS NULL
                )
                ORDER BY LV.SORT_ORDER DESC
                INTO :V$PARALLEL_TYPE_ID, :V$PARALLEL_COST
            DO
            BEGIN
                IF ((V$IS_FIRST = 1) OR (V$PARALLEL_TYPE_ID IN (45, 46, 47, 48, 51, 52, 53, 54))) THEN
                BEGIN
                    FOR
                        SELECT DISTINCT OBJ_ID
                        FROM (
                            SELECT L9.OBJ_ID
                            FROM LINKS L8
                            JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0 AND V49.LISTVAL_ID = :V$PARALLEL_TYPE_ID
                            JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 125, 187) AND L9.DATE_DEL IS NULL
                            WHERE L8.PARENT_ID = :I$STAGE_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
                            -- Ветка для АООП, где коды параллелей другие
                            UNION
                            SELECT L9.OBJ_ID
                            FROM LINKS L8
                            JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
                            JOIN LISTVALS LV ON LV.LISTVAL_ID = V49.LISTVAL_ID AND LV.COST = :V$PARALLEL_COST
                            JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 125, 187) AND L9.DATE_DEL IS NULL
                            WHERE L8.PARENT_ID = :I$STAGE_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
                        )
                        INTO :CLASS_ID
                    DO
                    BEGIN
                        SELECT CAPTION
                        FROM OBJECT_CAPTION_GET(:CLASS_ID, NULL, NULL, :I$USER_ID)
                        INTO :CLASS_NAME;
        
                        SUSPEND;                
                    END
                END
                V$IS_FIRST = 0;
            END
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CERTIFICATE_CLASS_ENABLED_GET (
    I$CLASS_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    ENABLED SMALLINT)
AS
BEGIN
    ENABLED = 0;

    SELECT FIRST 1 1
    FROM OBJECT_PARENTS_GET(:I$CLASS_ID, 7) S
    JOIN CERTIFICATE_CLASSES_LIST(S.OBJ_ID, :I$USER_ID) C ON C.CLASS_ID = :I$CLASS_ID
    INTO :ENABLED;

    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CERTIFICATE_CLASS_INFO_GET (
    I$YEAR SMALLINT,
    I$CLASS_ID BIGINT,
    I$STAGE_ID BIGINT,
    I$USER_ID BIGINT,
    I$BLANK_CHECK_FL INTEGER = 1)
RETURNS (
    CLASS_INFO_ID BIGINT,
    ORDER_ID BIGINT,
    CLASS_NAME VARCHAR(100),
    TMPL1 VARCHAR(255),
    TMPL2 VARCHAR(255),
    TMPL3 VARCHAR(255),
    TMPL4 VARCHAR(255),
    TMPL5 VARCHAR(255),
    PROF VARCHAR(200),
    DATEGEK DATE,
    PEK VARCHAR(100),
    KV VARCHAR(200),
    UO VARCHAR(100),
    SROK VARCHAR(100))
AS
BEGIN
    CLASS_INFO_ID = NULL;

    SELECT FIRST 1 OBJ_CAPTION
    FROM CERTIFICATE_REG_CLASSES_LIST(:I$YEAR, :I$STAGE_ID, :I$BLANK_CHECK_FL)
    WHERE OBJ_ID = :I$CLASS_ID
    INTO :CLASS_NAME;

    IF (CLASS_NAME IS NULL) THEN
    BEGIN
        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:I$CLASS_ID, NULL, NULL, :I$USER_ID)
        INTO :CLASS_NAME;
    END

    SELECT FIRST 1 OBJ_ID
    FROM LINKS
    WHERE PARENT_ID = :I$CLASS_ID AND OBJ_TYPE_ID = 232 AND DATE_DEL IS NULL
    ORDER BY OBJ_ID DESC
    INTO :CLASS_INFO_ID;

    IF (CLASS_INFO_ID IS NULL) THEN
    BEGIN
        TMPL1 = 'Стандартный';
        TMPL2 = TMPL1;
        TMPL3 = TMPL1;
        TMPL4 = TMPL1;
        TMPL5 = TMPL1;
    END
    ELSE
    BEGIN
        SELECT I
        FROM VAL_GET(:CLASS_INFO_ID, 1865, 0, :I$USER_ID)
        INTO :ORDER_ID;

        SELECT V
        FROM VAL_GET(:CLASS_INFO_ID, 1866, 0, :I$USER_ID)
        INTO :TMPL1;

        SELECT V
        FROM VAL_GET(:CLASS_INFO_ID, 1867, 0, :I$USER_ID)
        INTO :TMPL2;

        SELECT V
        FROM VAL_GET(:CLASS_INFO_ID, 1868, 0, :I$USER_ID)
        INTO :TMPL3;

        SELECT V
        FROM VAL_GET(:CLASS_INFO_ID, 1869, 0, :I$USER_ID)
        INTO :TMPL4;

        SELECT V
        FROM VAL_GET(:CLASS_INFO_ID, 1886, 0, :I$USER_ID)
        INTO :TMPL5;

        SELECT V
        FROM VAL_GET(:CLASS_INFO_ID, 2889, 0, :I$USER_ID)
        INTO :PROF;

        SELECT D
        FROM VAL_GET(:CLASS_INFO_ID, 2890, 0, :I$USER_ID)
        INTO :DATEGEK;

        SELECT V
        FROM VAL_GET(:CLASS_INFO_ID, 2891, 0, :I$USER_ID)
        INTO :PEK;

        SELECT V
        FROM VAL_GET(:CLASS_INFO_ID, 2892, 0, :I$USER_ID)
        INTO :KV;

        SELECT V
        FROM VAL_GET(:CLASS_INFO_ID, 2893, 0, :I$USER_ID)
        INTO :UO;

        SELECT V
        FROM VAL_GET(:CLASS_INFO_ID, 2894, 0, :I$USER_ID)
        INTO :SROK;
    END

    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CERTIFICATE_CLASS_INFO_SET (
    I$CLASS_ID BIGINT,
    I$USER_ID BIGINT,
    I$CLASS_INFO_ID BIGINT,
    I$ORDER_ID BIGINT,
    I$TMPL1 VARCHAR(255),
    I$TMPL2 VARCHAR(255),
    I$TMPL3 VARCHAR(255),
    I$TMPL4 VARCHAR(255),
    I$TMPL5 VARCHAR(255),
    I$PROF VARCHAR(200),
    I$DATEGEK DATE,
    I$PEK VARCHAR(100),
    I$KV VARCHAR(200),
    I$UO VARCHAR(100),
    I$SROK VARCHAR(100))
RETURNS (
    CLASS_INFO_ID BIGINT)
AS
declare variable V$BLOB_ID bigint;
BEGIN
    CLASS_INFO_ID = I$CLASS_INFO_ID;

    IF (CLASS_INFO_ID IS NULL) THEN
    BEGIN
        SELECT FIRST 1
               L232.OBJ_ID
        FROM LINKS L232

        WHERE L232.PARENT_ID = :I$CLASS_ID
        AND L232.OBJ_TYPE_ID = 232
        AND L232.DATE_DEL IS NULL

        INTO :CLASS_INFO_ID;
    END
    IF (CLASS_INFO_ID IS NULL) THEN
    BEGIN
        SELECT OBJ_ID
        FROM OBJECT_ADD(:I$CLASS_ID, 232, NULL, NULL, :I$USER_ID)
        INTO :CLASS_INFO_ID;
    END
    IF (CLASS_INFO_ID IS NOT NULL) THEN
    BEGIN
        SELECT BLOB_ID
        FROM VAL_ADD(1865, :CLASS_INFO_ID, :I$ORDER_ID, :I$USER_ID)
        INTO V$BLOB_ID;

        SELECT BLOB_ID
        FROM VAL_ADD(1866, :CLASS_INFO_ID, :I$TMPL1, :I$USER_ID)
        INTO V$BLOB_ID;

        SELECT BLOB_ID
        FROM VAL_ADD(1867, :CLASS_INFO_ID, :I$TMPL2, :I$USER_ID)
        INTO V$BLOB_ID;

        SELECT BLOB_ID
        FROM VAL_ADD(1868, :CLASS_INFO_ID, :I$TMPL3, :I$USER_ID)
        INTO V$BLOB_ID;

        SELECT BLOB_ID
        FROM VAL_ADD(1869, :CLASS_INFO_ID, :I$TMPL4, :I$USER_ID)
        INTO V$BLOB_ID;

        SELECT BLOB_ID
        FROM VAL_ADD(1886, :CLASS_INFO_ID, :I$TMPL5, :I$USER_ID)
        INTO V$BLOB_ID;

        SELECT BLOB_ID
        FROM VAL_ADD(2889, :CLASS_INFO_ID, :I$PROF, :I$USER_ID)
        INTO V$BLOB_ID;

        SELECT BLOB_ID
        FROM VAL_ADD(2890, :CLASS_INFO_ID, :I$DATEGEK, :I$USER_ID)
        INTO V$BLOB_ID;

        SELECT BLOB_ID
        FROM VAL_ADD(2891, :CLASS_INFO_ID, :I$PEK, :I$USER_ID)
        INTO V$BLOB_ID;

        SELECT BLOB_ID
        FROM VAL_ADD(2892, :CLASS_INFO_ID, :I$KV, :I$USER_ID)
        INTO V$BLOB_ID;

        SELECT BLOB_ID
        FROM VAL_ADD(2893, :CLASS_INFO_ID, :I$UO, :I$USER_ID)
        INTO V$BLOB_ID;

        SELECT BLOB_ID
        FROM VAL_ADD(2894, :CLASS_INFO_ID, :I$SROK, :I$USER_ID)
        INTO V$BLOB_ID;
    END

    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CERTIFICATE_CLASS_LOAD_SUBJECTS (
    I$STAGE_ID BIGINT,
    I$CLASS_ID BIGINT,
    I$USER_ID BIGINT,
    I$PUPIL_ID BIGINT = null)
RETURNS (
    C_SUBJECT_ID BIGINT,
    INCLUDING_TYPE_ID BIGINT,
    SUBJECT_ID BIGINT,
    SUBJECT_NAME VARCHAR(1000),
    MARK VARCHAR(255),
    IS_BASE SMALLINT,
    IS_PLAN SMALLINT,
    SORT_ORDER INTEGER,
    SUBJECT_LOAD VARCHAR(10),
    REC_MARK DOUBLE PRECISION)
AS
declare variable V$LANG_CODE varchar(2);
declare variable V$PLAN_ID bigint;
declare variable V$HOURS_TOTAL integer;
declare variable V$PS_ID bigint;
declare variable Y smallint;
declare variable YEAR_ID bigint;
declare variable V$N_MARKS integer;
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :V$LANG_CODE;

    Y = EXTRACT(YEAR FROM CURRENT_DATE);
    IF(EXTRACT(MONTH FROM CURRENT_DATE) < 9) THEN Y = Y - 1;

    SELECT FIRST 1 LV.LISTVAL_ID
    FROM LISTVALS LV
    WHERE LV.LIST_ID = 29 AND LV.COST = :Y
    INTO :YEAR_ID;

    FOR
        SELECT L51.SUBJECT_ID, CASE WHEN L51.C_SUBJECT_NAME <> '' THEN L51.C_SUBJECT_NAME ELSE L51.SUBJECT_NAME END
        FROM CERTIFICATE_CLASS_SUBJECT_LIST (:I$STAGE_ID, :I$CLASS_ID, :I$USER_ID) AS L51
        INTO :SUBJECT_ID, :SUBJECT_NAME
    DO
    BEGIN
        C_SUBJECT_ID = NULL;
        INCLUDING_TYPE_ID = NULL;
        MARK = NULL;
        IS_BASE = 0;
        IS_PLAN = 0;
        SORT_ORDER = NULL;
        FOR
            SELECT LP400.PARENT_ID, PS.OBJ_ID, IIF(PS2.FIELD_ID = 13303, 1, 0) IS_BASE
            FROM LINKS L10
            JOIN LINKS LP256 ON LP256.OBJ_ID = L10.OBJ_ID AND LP256.PARENT_TYPE_ID = 256 AND LP256.DATE_DEL IS NULL
            JOIN LINKS LP54 ON LP54.OBJ_ID = LP256.PARENT_ID AND LP54.PARENT_TYPE_ID = 54 AND LP54.DATE_DEL IS NULL
            JOIN LINKS LP400 ON LP400.OBJ_ID = LP54.PARENT_ID AND LP400.PARENT_TYPE_ID = 400 AND LP400.DATE_DEL IS NULL
            JOIN PLAN_SUBJECTS PS ON PS.DATE_DEL IS NULL AND PS.PLAN_ID = LP400.PARENT_ID AND PS.ROW_TYPE = 10 AND PS.SUBJECT_ID = :SUBJECT_ID
            JOIN PLAN_SUBJECTS PS2 ON PS2.OBJ_ID = PS.PARENT_ID
            WHERE L10.PARENT_ID = :I$CLASS_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
            INTO :V$PLAN_ID, :V$PS_ID, :IS_BASE
        DO
        BEGIN
            IS_PLAN = 1;

            V$HOURS_TOTAL = 0;
            SELECT SUM(COALESCE(PL.LOAD_HOURS_S1, 0) + COALESCE(PL.LOAD_HOURS_S2, 0))
            FROM LINKS L54
            JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
            JOIN LISTVALS LV ON LV.LISTVAL_ID = V381.LISTVAL_ID
            JOIN PLAN_LOADS PL ON PL.DATE_DEL IS NULL AND PL.SUBJECT_ID = :V$PS_ID AND PL.STAGE_ID = L54.OBJ_ID
            WHERE L54.PARENT_ID = :V$PLAN_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
            INTO :V$HOURS_TOTAL;

            -- Индивидуальный проект по-умолчанию выдаем в основных, но печатаем в дополнении
            IF (V$HOURS_TOTAL >= 64 OR SUBJECT_ID = 34651) THEN
            BEGIN
                IS_BASE = 1;
            END
            ELSE IF (V$HOURS_TOTAL = 0) THEN
            BEGIN
                IS_BASE = 0;
            END
        END

        SELECT L229.OBJ_ID, V1852.LISTVAL_ID, V1854.VAL, V2880.VAL
        FROM LINKS L229
        JOIN VALL V1852 ON V1852.OBJ_ID = L229.OBJ_ID AND V1852.PARAM_ID = 1852 AND V1852.IS_DEL = 0
        JOIN VALR V1853 ON V1853.OBJ_ID = L229.OBJ_ID AND V1853.PARAM_ID = 1853 AND V1853.IS_DEL = 0 AND V1853.VAL = :SUBJECT_ID
        LEFT JOIN VALI V1854 ON V1854.OBJ_ID = L229.OBJ_ID AND V1854.PARAM_ID = 1854 AND V1854.IS_DEL = 0
        LEFT JOIN VALS V2880 ON V2880.OBJ_ID = L229.OBJ_ID AND V2880.PARAM_ID = 2880 AND V2880.IS_DEL = 0
        WHERE L229.PARENT_ID = :I$CLASS_ID AND L229.OBJ_TYPE_ID = 229 AND L229.DATE_DEL IS NULL
        INTO :C_SUBJECT_ID, :INCLUDING_TYPE_ID, :SORT_ORDER, :SUBJECT_LOAD;

        IF (I$PUPIL_ID IS NOT NULL) THEN
        BEGIN
            SELECT FIRST 1 (SELECT VAL FROM RES_GET(LV3.RES_ID, :V$LANG_CODE))
            FROM VALM VM
            JOIN LISTVALS LV1 ON LV1.LISTVAL_ID = VM.YEAR_ID
            JOIN LISTVALS LV3 ON LV3.LISTVAL_ID = VM.MARKVAL_ID
            WHERE VM.PUPIL_ID = :I$PUPIL_ID AND VM.SUBJECT_ID = :SUBJECT_ID AND VM.YEAR_ID = :YEAR_ID AND VM.MARKTYPE_ID = 3013 AND VM.IS_DEL = 0
            ORDER BY LV1.COST DESC
            INTO :MARK;

            -- Если запросили уровень среднего образования, показываем рекомендуемую среднюю отметку за 10 и 11 классы
            REC_MARK = NULL;
            IF(EXISTS(
                SELECT FIRST 1 1
                FROM VALL V43
                WHERE V43.OBJ_ID = :I$STAGE_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0 AND V43.LISTVAL_ID IN (27, 29)
            )) THEN
            BEGIN

                SELECT SUM(LV3.COST) / 10, COUNT(*)
                FROM VALM VM
                JOIN LISTVALS LV1 ON LV1.LISTVAL_ID = VM.YEAR_ID AND (LV1.COST = :Y OR LV1.COST = :Y - 1)
                JOIN LISTVALS LV3 ON LV3.LISTVAL_ID = VM.MARKVAL_ID
                WHERE VM.IS_DEL = 0 AND VM.PUPIL_ID = :I$PUPIL_ID AND VM.SUBJECT_ID = :SUBJECT_ID AND VM.MARKTYPE_ID IN (3009, 3010, 3011)
                    AND VM.MARKVAL_ID IN (3014, 3015, 3016, 3017, 3018)
                INTO :REC_MARK, :V$N_MARKS;

                IF(V$N_MARKS > 0) THEN REC_MARK = REC_MARK / V$N_MARKS;

            END
        END

        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CERTIFICATE_CLASS_LOAD_SUBJ_SET (
    I$CLASS_ID BIGINT,
    I$USER_ID BIGINT,
    I$C_SUBJECT_ID BIGINT,
    I$INCLUDING_TYPE_ID BIGINT,
    I$SUBJECT_ID BIGINT,
    I$SORT_ORDER INTEGER,
    I$SUBJECT_LOAD VARCHAR(100))
RETURNS (
    C_SUBJECT_ID BIGINT)
AS
declare variable V$BLOB_ID bigint;
BEGIN
    C_SUBJECT_ID = I$C_SUBJECT_ID;
    IF (C_SUBJECT_ID IS NULL) THEN
    BEGIN
        SELECT FIRST 1
               L229.OBJ_ID
        FROM LINKS L229

        JOIN VALR V1853
        ON V1853.OBJ_ID = L229.OBJ_ID
        AND V1853.PARAM_ID = 1853
        AND V1853.IS_DEL = 0
        AND V1853.VAL = :I$SUBJECT_ID

        WHERE L229.PARENT_ID = :I$CLASS_ID
        AND L229.OBJ_TYPE_ID = 229
        AND L229.DATE_DEL IS NULL

        INTO :C_SUBJECT_ID;
    END
    IF (C_SUBJECT_ID IS NULL) THEN
    BEGIN
        SELECT OBJ_ID
        FROM OBJECT_ADD(:I$CLASS_ID, 229, NULL, NULL, :I$USER_ID)
        INTO :C_SUBJECT_ID;

        IF (C_SUBJECT_ID IS NOT NULL) THEN
        BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD(1853, :C_SUBJECT_ID, :I$SUBJECT_ID, :I$USER_ID)
            INTO :V$BLOB_ID;
        END
    END
    IF (C_SUBJECT_ID IS NOT NULL) THEN
    BEGIN
        SELECT BLOB_ID
        FROM VAL_ADD(1852, :C_SUBJECT_ID, :I$INCLUDING_TYPE_ID, :I$USER_ID)
        INTO :V$BLOB_ID;

        SELECT BLOB_ID
        FROM VAL_ADD(1854, :C_SUBJECT_ID, :I$SORT_ORDER, :I$USER_ID)
        INTO :V$BLOB_ID;

        SELECT BLOB_ID
        FROM VAL_ADD(2880, :C_SUBJECT_ID, :I$SUBJECT_LOAD, :I$USER_ID)
        INTO :V$BLOB_ID;
    END
    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CERTIFICATE_CLASS_SUBJECT_LIST (
    I$STAGE_ID BIGINT,
    I$CLASS_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    C_SUBJECT_ID BIGINT,
    C_SUBJECT_NAME VARCHAR(1000),
    SUBJECT_ID BIGINT,
    SUBJECT_NAME VARCHAR(1000),
    SUBJECT_TYPE BIGINT)
AS
BEGIN
    FOR
        SELECT L51.SUBJECT_ID, L51.SUBJECT_NAME, L51.S_SUBJECT_NAME, L51.SUBJECT_TYPE
        FROM CERTIFICATE_STAGE_SUBJECT_LIST(:I$STAGE_ID, :I$USER_ID) L51
        ORDER BY L51.SUBJECT_NAME
        INTO :SUBJECT_ID, :SUBJECT_NAME, :C_SUBJECT_NAME, :SUBJECT_TYPE
    DO
    BEGIN
        C_SUBJECT_ID = NULL;

        /*SELECT FIRST 1 L227.OBJ_ID, V1846.VAL
        FROM LINKS L227
        JOIN VALR V1845 ON V1845.OBJ_ID = L227.OBJ_ID AND V1845.PARAM_ID = 1845 AND V1845.VAL = :SUBJECT_ID
        JOIN VALS V1846 ON V1846.OBJ_ID = L227.OBJ_ID AND V1846.PARAM_ID = 1846 AND V1846.IS_DEL = 0
        WHERE L227.PARENT_ID = :I$CLASS_ID AND L227.OBJ_TYPE_ID = 227 AND L227.DATE_DEL IS NULL
        INTO :C_SUBJECT_ID, :C_SUBJECT_NAME;*/

        SELECT FIRST 1 L227.OBJ_ID, V1846.VAL
        FROM VALR V1845
        JOIN LINKS L227 ON L227.OBJ_ID = V1845.OBJ_ID AND L227.PARENT_ID = :I$CLASS_ID AND L227.DATE_DEL IS NULL
        JOIN VALS V1846 ON V1846.OBJ_ID = V1845.OBJ_ID AND V1846.PARAM_ID = 1846 AND V1846.IS_DEL = 0
        WHERE V1845.PARAM_ID = 1845 AND V1845.VAL = :SUBJECT_ID
        INTO :C_SUBJECT_ID, :C_SUBJECT_NAME;

        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CERTIFICATE_CLASS_SUBJECT_SET (
    I$CLASS_ID BIGINT,
    I$C_SUBJECT_ID BIGINT,
    I$SUBJECT_ID BIGINT,
    I$USER_ID BIGINT,
    I$C_SUBJECT_NAME VARCHAR(1000))
RETURNS (
    C_SUBJECT_ID BIGINT)
AS
BEGIN
    SELECT S_SUBJECT_ID
    FROM CERTIFICATE_STAGE_SUBJECT_SET(:I$CLASS_ID,:I$C_SUBJECT_ID,:I$SUBJECT_ID,:I$USER_ID,:I$C_SUBJECT_NAME)
    INTO :C_SUBJECT_ID;
    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CERTIFICATE_DIR_FORM_MASTER_GET (
    I$STAGE_ID BIGINT,
    I$CLASS_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    FORM_MASTER_FIO VARCHAR(1000),
    DIRECTOR_POST VARCHAR(1000),
    DIRECTOR_FIO VARCHAR(1000))
AS
declare variable V$SCHOOL_ID bigint;
declare variable V$F varchar(255);
declare variable V$I varchar(255);
declare variable V$O varchar(255);
BEGIN
    FOR
        SELECT FIRST 1 OBJ_ID
        FROM OBJECT_PARENTS_GET(:I$STAGE_ID, 2)
        INTO :V$SCHOOL_ID
    DO
    BEGIN
        FOR
            SELECT F,I,O,POST
            FROM R_SPB_POST_DIRECTOR(:V$SCHOOL_ID, :I$USER_ID)
            INTO :V$F, :V$I, :V$O, :DIRECTOR_POST
        DO
        BEGIN   
            DIRECTOR_FIO = SUBSTRING(V$I FROM 1 FOR 1) || '.' || SUBSTRING(V$O FROM 1 FOR 1) || '. ' || V$F;
        END
    END
    SELECT SUBSTRING(I.V FROM 1 FOR 1) || '.' || SUBSTRING(O.V FROM 1 FOR 1) || '. ' || F.V
    FROM VALR VR
    LEFT JOIN VAL_GET(VR.VAL, 59, 0, :I$USER_ID) F ON 1=1
    LEFT JOIN VAL_GET(VR.VAL, 60, 0, :I$USER_ID) I ON 1=1
    LEFT JOIN VAL_GET(VR.VAL, 61, 0, :I$USER_ID) O ON 1=1
    WHERE OBJ_ID = :I$CLASS_ID AND PARAM_ID = 53 AND IS_DEL = 0
    INTO :FORM_MASTER_FIO;

    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CERTIFICATE_DUPL_PUPIL_ADD (
    I$LASTNAME VARCHAR(255),
    I$FIRSTNAME VARCHAR(255),
    I$MIDDLENAME VARCHAR(255),
    I$DOB DATE,
    I$YEARTOGO INTEGER,
    I$STAGE_ID BIGINT,
    I$USER_ID BIGINT = 1)
RETURNS (
    PUPIL_ID BIGINT)
AS
declare variable V$STAGETYPE integer;
declare variable V$ID78 bigint;
declare variable V$BLOB_ID bigint;
declare variable V$ID76 bigint;
declare variable V$CLASS_ID bigint;
BEGIN
    SELECT OBJ_ID FROM LINKS
    WHERE OBJ_TYPE_ID = 78 AND DATE_DEL IS NULL
    INTO :V$ID78;

    SELECT V.LISTVAL_ID FROM VALL V
    WHERE V.PARAM_ID = 43 AND V.IS_DEL = 0 AND V.OBJ_ID = :I$STAGE_ID
    INTO :V$STAGETYPE;

    SELECT L.OBJ_ID
    FROM LINKS L
    LEFT JOIN VALI V449 ON V449.OBJ_ID = L.OBJ_ID AND V449.PARAM_ID = 449 AND V449.IS_DEL = 0
    LEFT JOIN VALI V451 ON V451.OBJ_ID = L.OBJ_ID AND V451.PARAM_ID = 451 AND V451.IS_DEL = 0
    WHERE L.OBJ_TYPE_ID IN (82, 83) AND L.DATE_DEL IS NULL
      AND (
        ((:V$STAGETYPE = 26) AND (L.OBJ_TYPE_ID = 82) AND (V449.VAL = :I$YEARTOGO)) OR
        ((:V$STAGETYPE = 27) AND (L.OBJ_TYPE_ID = 83) AND (V451.VAL = :I$YEARTOGO))
      )
    INTO :V$CLASS_ID;

    -- Добавление класса 82, 83
    IF (V$CLASS_ID IS NULL) THEN
    BEGIN
        IF (V$STAGETYPE = 26) THEN
        BEGIN
            SELECT OBJ_ID FROM OBJECT_ADD(:V$ID78, 82, NULL, NULL, :I$USER_ID) INTO :V$CLASS_ID;

            SELECT BLOB_ID FROM VAL_ADD(447, :V$CLASS_ID, 899, :I$USER_ID) INTO :V$BLOB_ID;
            SELECT BLOB_ID FROM VAL_ADD(448, :V$CLASS_ID, :I$YEARTOGO - 1, :I$USER_ID) INTO :V$BLOB_ID;
            SELECT BLOB_ID FROM VAL_ADD(449, :V$CLASS_ID, :I$YEARTOGO, :I$USER_ID) INTO :V$BLOB_ID;
        END
        ELSE
        IF (V$STAGETYPE = 27) THEN
        BEGIN
            SELECT OBJ_ID FROM OBJECT_ADD(:V$ID78, 83, NULL, NULL, :I$USER_ID) INTO V$CLASS_ID;

            SELECT BLOB_ID FROM VAL_ADD(450, :V$CLASS_ID, 900, :I$USER_ID) INTO :V$BLOB_ID;
            SELECT BLOB_ID FROM VAL_ADD(451, :V$CLASS_ID, :I$YEARTOGO, :I$USER_ID) INTO :V$BLOB_ID;
        END
    END

    -- Добавление ученика
    SELECT OBJ_ID FROM OBJECT_ADD(:V$CLASS_ID, 10, NULL, NULL, :I$USER_ID) INTO PUPIL_ID;
    SELECT BLOB_ID FROM VAL_ADD(55, :PUPIL_ID, TRIM(:I$LASTNAME), :I$USER_ID) INTO :V$BLOB_ID;
    SELECT BLOB_ID FROM VAL_ADD(56, :PUPIL_ID, TRIM(:I$FIRSTNAME), :I$USER_ID) INTO :V$BLOB_ID;
    SELECT BLOB_ID FROM VAL_ADD(57, :PUPIL_ID, TRIM(:I$MIDDLENAME), :I$USER_ID) INTO :V$BLOB_ID;
    SELECT BLOB_ID FROM VAL_ADD(89, :PUPIL_ID, :I$DOB, :I$USER_ID) INTO :V$BLOB_ID;

    -- Добавление липовой записи движения
    INSERT INTO PERSON_MOVEMENTS
    (PERSON_ID, GROUP_ID, DATE_IN, DATE_OUT, REASON_OUT, NAME_IN)
    VALUES (:PUPIL_ID, :V$CLASS_ID, '01.01.1970', '31.08.' || :I$YEARTOGO, 812, 'Отчисленные (для печати дубликата аттестата)');

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CERTIFICATE_DUPL_PUPIL_LIST (
    I$LASTNAME CHAR(255),
    I$FIRSTNAME VARCHAR(255),
    I$MIDDLENAME VARCHAR(255),
    I$DOB DATE,
    I$YEARTOGO INTEGER,
    I$STAGE_ID BIGINT,
    I$USER_ID BIGINT = 1)
RETURNS (
    CLASS_ID BIGINT,
    PUPIL_ID BIGINT,
    LASTNAME CHAR(255),
    FIRSTNAME VARCHAR(255),
    MIDDLENAME VARCHAR(255),
    PUPIL_FIO VARCHAR(1000),
    CLASS_NAME VARCHAR(255),
    DOB DATE,
    YEARTOGO INTEGER)
AS
declare variable V$STAGETYPE integer;
declare variable V$CLASS_TYPE_ID bigint;
BEGIN
    SELECT V.LISTVAL_ID FROM VALL V
    WHERE V.PARAM_ID = 43 AND V.IS_DEL = 0 AND V.OBJ_ID = :I$STAGE_ID
    INTO :V$STAGETYPE;

    IF ((V$STAGETYPE = 26) OR (V$STAGETYPE = 27) OR (V$STAGETYPE = 29))  THEN
    BEGIN
        FOR
            SELECT L.OBJ_ID, L.PARENT_ID, L.PARENT_TYPE_ID, TRIM(V57.VAL), TRIM(V56.VAL), TRIM(V55.VAL), V89.VAL
            FROM LINKS L
            JOIN VALS V55 ON V55.OBJ_ID = L.OBJ_ID AND V55.PARAM_ID = 55 AND V55.IS_DEL = 0 AND V55.SVAL = :I$LASTNAME
            JOIN VALS V56 ON V56.OBJ_ID = L.OBJ_ID AND V56.PARAM_ID = 56 AND V56.IS_DEL = 0 AND V56.SVAL = :I$FIRSTNAME
            LEFT JOIN VALS V57 ON V57.OBJ_ID = L.OBJ_ID AND V57.PARAM_ID = 57 AND V57.IS_DEL = 0
            LEFT JOIN VALD V89 ON V89.OBJ_ID = L.OBJ_ID AND V89.PARAM_ID = 89 AND V89.IS_DEL = 0
            WHERE L.OBJ_TYPE_ID = 10 AND L.PARENT_TYPE_ID IN (9, 81, 82, 83) AND L.DATE_DEL IS NULL
                AND (:I$MIDDLENAME IS NULL OR V57.SVAL = :I$MIDDLENAME)
                AND (:I$DOB IS NULL OR V89.VAL = :I$DOB)
            INTO :PUPIL_ID, :CLASS_ID, :V$CLASS_TYPE_ID, :MIDDLENAME, :FIRSTNAME, :LASTNAME, :DOB
        DO
        BEGIN
            -- Пытаемся отыскать год выпуска в документах об образовании соответствующего типа
            SELECT FIRST 1 EXTRACT(YEAR FROM V566.VAL)
            FROM LINKS L11
            JOIN VALL V50 ON V50.OBJ_ID = L11.OBJ_ID AND V50.PARAM_ID = 50 AND V50.IS_DEL = 0
            AND (
                ((:V$STAGETYPE = 26) AND (V50.LISTVAL_ID IN (1375, 3241))) OR
                ((:V$STAGETYPE = 27) AND (V50.LISTVAL_ID IN (1376, 3240))) OR
                ((:V$STAGETYPE = 29) AND (V50.LISTVAL_ID IN (1380, 12785)))
            )
            LEFT JOIN VALD V566 ON V566.OBJ_ID = L11.OBJ_ID AND V566.PARAM_ID = 566 AND V566.IS_DEL = 0
            WHERE L11.PARENT_ID = :PUPIL_ID AND L11.OBJ_TYPE_ID = 11 AND L11.DATE_DEL IS NULL
            INTO :YEARTOGO;

            -- Если документ об образовании не задан, пытаемся найти среди уже выданных дубликатов
            IF (YEARTOGO IS NULL) THEN
            BEGIN
                SELECT FIRST 1 V2354.VAL
                FROM LINKS L292
                JOIN LINKS L230 ON L230.PARENT_ID = L292.OBJ_ID AND L230.OBJ_TYPE_ID = 230 AND L230.DATE_DEL IS NULL
                JOIN VALI V2354 ON V2354.OBJ_ID = L292.OBJ_ID AND V2354.PARAM_ID = 2354 AND V2354.IS_DEL = 0
                WHERE L292.PARENT_ID = :PUPIL_ID AND L292.OBJ_TYPE_ID = 292
                ORDER BY L292.OBJ_ID DESC
                INTO :YEARTOGO;
            END

            -- Если все равно не удалось найти год выпуска, пытаемся идентифицировать по году указанного в папке выбывших/окончивших
            IF (YEARTOGO IS NULL) THEN
            BEGIN
                IF (V$CLASS_TYPE_ID = 81) THEN
                BEGIN
                    SELECT I FROM VAL_GET(:CLASS_ID, 445) INTO :YEARTOGO;
                END
                ELSE IF (V$CLASS_TYPE_ID = 82) THEN
                BEGIN
                    SELECT I FROM VAL_GET(:CLASS_ID, 449) INTO :YEARTOGO;
                END
                ELSE IF (V$CLASS_TYPE_ID = 83) THEN
                BEGIN
                    SELECT I FROM VAL_GET(:CLASS_ID, 451) INTO :YEARTOGO;
                END
                ELSE
                BEGIN
                    YEARTOGO = I$YEARTOGO;
                END
            END

            PUPIL_FIO = TRIM(LASTNAME) || ' ' || FIRSTNAME;
            IF (MIDDLENAME IS NOT NULL) THEN PUPIL_FIO = TRIM(PUPIL_FIO) || ' ' || MIDDLENAME;

            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:CLASS_ID, NULL, NULL, :I$USER_ID)
            INTO :CLASS_NAME;

            SUSPEND;

        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CERTIFICATE_FORM_SET (
    I$STAGE_ID BIGINT,
    I$USER_ID BIGINT,
    I$FORM_ID BIGINT,
    I$FORM_TYPE_ID BIGINT,
    I$FORM_SERIA VARCHAR(10),
    I$FORM_FIRST_NUMBER VARCHAR(255),
    I$FORM_LAST_NUMBER VARCHAR(255),
    I$FORM_RECEIVE_DATE DATE,
    I$FORM_SUPPLIER VARCHAR(255))
RETURNS (
    FORM_ID BIGINT)
AS
declare variable V$SCHOOL_ID bigint;
declare variable V$BLOB_ID bigint;
declare variable RS1 varchar(100);
declare variable RS2 varchar(100);
declare variable NV1 bigint;
declare variable NV2 bigint;
declare variable RV1 bigint;
declare variable RV2 bigint;
BEGIN
    FORM_ID = I$FORM_ID;

    SELECT FIRST 1 LP2.PARENT_ID
    FROM LINKS LP2
    WHERE LP2.OBJ_ID = :I$STAGE_ID AND LP2.PARENT_TYPE_ID = 2 AND LP2.DATE_DEL IS NULL
    INTO :V$SCHOOL_ID;

    IF(V$SCHOOL_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не найден объект ОУ';

    BEGIN
        NV1 = CAST(I$FORM_FIRST_NUMBER AS BIGINT);
        WHEN ANY DO NV1 = -1;
    END
    BEGIN
        NV2 = CAST(I$FORM_LAST_NUMBER AS BIGINT);
        WHEN ANY DO NV2 = -1;
    END

    IF(NV1 > 0 AND NV2 > 0 AND NV1 > NV2) THEN
        EXCEPTION DATA_ERROR 'Неправильный порядок номеров бланков (должен быть сначала меньший, затем больший)';

    -- Проверяем, что диапазоны номеров не входят в другие цепочки, с той же серией
    FOR
        SELECT V1848.VAL, V1849.VAL
        FROM LINKS L228
        JOIN VALL V1847 ON V1847.OBJ_ID = L228.OBJ_ID AND V1847.PARAM_ID = 1847 AND V1847.IS_DEL = 0 AND V1847.LISTVAL_ID = :I$FORM_TYPE_ID
        JOIN VALS V1881 ON V1881.OBJ_ID = L228.OBJ_ID AND V1881.PARAM_ID = 1881 AND V1881.IS_DEL = 0 AND V1881.VAL = :I$FORM_SERIA
        JOIN VALS V1848 ON V1848.OBJ_ID = L228.OBJ_ID AND V1848.PARAM_ID = 1848 AND V1848.IS_DEL = 0
        JOIN VALS V1849 ON V1849.OBJ_ID = L228.OBJ_ID AND V1849.PARAM_ID = 1849 AND V1849.IS_DEL = 0
        WHERE L228.PARENT_ID = :V$SCHOOL_ID AND L228.OBJ_TYPE_ID = 228 AND L228.DATE_DEL IS NULL AND (L228.OBJ_ID <> :I$FORM_ID OR :I$FORM_ID IS NULL)
        INTO :RS1, :RS2
    DO
    BEGIN

        BEGIN
            RV1 = CAST(RS1 AS BIGINT);
            WHEN ANY DO RV1 = -1;
        END
        BEGIN
            RV2 = CAST(RS2 AS BIGINT);
            WHEN ANY DO RV2 = -1;
        END

        IF(RV1 >= 0 AND RV2 >= 0 AND NV1 >= 0 AND NV2 >= 0 AND NV1 <= RV2 AND NV2 >= RV1) THEN
            EXCEPTION DATA_ERROR 'Бланки с номерами ' || I$FORM_FIRST_NUMBER || '...' || I$FORM_LAST_NUMBER || ' пересекаются с другим пакетом бланков';

    END

    IF (FORM_ID IS NULL) THEN
    BEGIN
        SELECT OBJ_ID FROM OBJECT_ADD(:V$SCHOOL_ID, 228, NULL, NULL, :I$USER_ID) INTO :FORM_ID;
    END
    ELSE
    BEGIN
        -- Если количество бланков урезали, проверяем что все уже выданные бланки попали в новый диапазон
        FOR
            SELECT V1878.VAL
            FROM LINKS L236
            JOIN VALS V1878 ON V1878.OBJ_ID = L236.OBJ_ID AND V1878.PARAM_ID = 1878 AND V1878.IS_DEL = 0
            WHERE L236.PARENT_ID = :I$FORM_ID AND L236.OBJ_TYPE_ID = 236 AND L236.DATE_DEL IS NULL
            INTO :RS1
        DO
        BEGIN
            BEGIN
                RV1 = CAST(RS1 AS BIGINT);
                WHEN ANY DO RV1 = -1;
            END
            IF(RV1 >= 0 AND NV1 >= 0 AND NV2 >= 0 AND RV1 < NV1 AND RV1 > RV2) THEN
                EXCEPTION DATA_ERROR 'Бланк с номером ' || RS1 || ' внесен в книгу выдачи, но новый диапазон номеров не включает его';
        END
    END

    IF (FORM_ID IS NOT NULL) THEN
    BEGIN
        SELECT BLOB_ID FROM VAL_ADD(1847, :FORM_ID, :I$FORM_TYPE_ID, :I$USER_ID) INTO :V$BLOB_ID;
        SELECT BLOB_ID FROM VAL_ADD(1848, :FORM_ID, :I$FORM_FIRST_NUMBER, :I$USER_ID) INTO :V$BLOB_ID;
        SELECT BLOB_ID FROM VAL_ADD(1849, :FORM_ID, :I$FORM_LAST_NUMBER, :I$USER_ID) INTO :V$BLOB_ID;
        SELECT BLOB_ID FROM VAL_ADD(1850, :FORM_ID, :I$FORM_RECEIVE_DATE, :I$USER_ID) INTO :V$BLOB_ID;
        SELECT BLOB_ID FROM VAL_ADD(1851, :FORM_ID, :I$FORM_SUPPLIER, :I$USER_ID) INTO :V$BLOB_ID;
        SELECT BLOB_ID FROM VAL_ADD(1881, :FORM_ID, :I$FORM_SERIA, :I$USER_ID) INTO :V$BLOB_ID;
    END

    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CERTIFICATE_OBJECT_GET (
    I$OBJ_ID BIGINT)
RETURNS (
    STAGE_ID BIGINT,
    STAGE_TYPE_ID BIGINT,
    CLASS_ID BIGINT,
    PUPIL_ID BIGINT)
AS
BEGIN
    SELECT FIRST 1
           O.OBJ_ID,
           V43.LISTVAL_ID
    FROM OBJECT_PARENTS_GET(:I$OBJ_ID, 7) O

    JOIN VALL V43
    ON V43.OBJ_ID = O.OBJ_ID
    AND V43.PARAM_ID = 43
    AND V43.IS_DEL = 0

    INTO :STAGE_ID,
         :STAGE_TYPE_ID;

    SELECT FIRST 1
           O.OBJ_ID
    FROM OBJECT_PARENTS_GET(:I$OBJ_ID, 9) O

    INTO :CLASS_ID;

    IF (CLASS_ID IS NULL) THEN
    BEGIN
        SELECT FIRST 1
               O.OBJ_ID
        FROM OBJECT_PARENTS_GET(:I$OBJ_ID, 125) O
    
        INTO :CLASS_ID;
    END

    IF (CLASS_ID IS NULL) THEN
    BEGIN
        SELECT FIRST 1
               O.OBJ_ID
        FROM OBJECT_PARENTS_GET(:I$OBJ_ID, 187) O
    
        INTO :CLASS_ID;
    END

    IF (CLASS_ID IS NULL) THEN
    BEGIN
        SELECT FIRST 1
               O.OBJ_ID
        FROM OBJECT_PARENTS_GET(:I$OBJ_ID, 81) O
    
        INTO :CLASS_ID;
    END

    IF (CLASS_ID IS NULL) THEN
    BEGIN
        SELECT FIRST 1
               O.OBJ_ID
        FROM OBJECT_PARENTS_GET(:I$OBJ_ID, 82) O
    
        INTO :CLASS_ID;
    END

    IF (CLASS_ID IS NULL) THEN
    BEGIN
        SELECT FIRST 1
               O.OBJ_ID
        FROM OBJECT_PARENTS_GET(:I$OBJ_ID, 83) O
    
        INTO :CLASS_ID;
    END



    SELECT FIRST 1
           O.OBJ_ID
    FROM OBJECT_PARENTS_GET(:I$OBJ_ID, 10) O

    INTO :PUPIL_ID;

    IF (PUPIL_ID IS NULL) THEN
    BEGIN
        SELECT FIRST 1
               O.OBJ_ID
        FROM OBJECT_PARENTS_GET(:I$OBJ_ID, 126) O
    
        INTO :PUPIL_ID;
    END

    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CERTIFICATE_OO_DEF_PARAM_GET (
    I$PARAM_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    DEFAULT_VALUE VARCHAR(1000))
AS
declare variable V$FULL_NAME varchar(1000);
declare variable V$OBJ_ID_OU bigint;
BEGIN
    SELECT FIRST 1 OBJ_ID
    FROM LINKS
    WHERE OBJ_TYPE_ID = 2
    AND PARENT_ID IS NULL
    INTO :V$OBJ_ID_OU;

    IF ( (I$PARAM_ID = 1833) OR (I$PARAM_ID = 1834) )  THEN
    BEGIN
        SELECT V
        FROM VAL_GET(:V$OBJ_ID_OU, 5, 0, :I$USER_ID)
        INTO :DEFAULT_VALUE;
    END
    ELSE
    IF (I$PARAM_ID = 1835) THEN
    BEGIN
        SELECT V
        FROM VAL_GET(:V$OBJ_ID_OU, 5, 0, :I$USER_ID)
        INTO :V$FULL_NAME;

        IF ( POSITION('САНКТ-ПЕТЕРБУРГ' IN UPPER(V$FULL_NAME)) > 0 ) THEN
        BEGIN
            DEFAULT_VALUE = '';
        END
        ELSE
        BEGIN
            DEFAULT_VALUE = 'г. Санкт-Петербург';
        END
    END
    ELSE
    IF (I$PARAM_ID = 1836) THEN
    BEGIN
        SELECT
        SUBSTRING(I FROM 1 FOR 1) || '.' ||
        SUBSTRING(O FROM 1 FOR 1) || '. ' || F
        FROM R_SPB_POST_DIRECTOR(:V$OBJ_ID_OU,:I$USER_ID)
        INTO :DEFAULT_VALUE;
    END
    ELSE
    BEGIN
        DEFAULT_VALUE = '';
    END
    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CERTIFICATE_OO_SETTINGS_GET (
    I$OBJ_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    FULL_NAME VARCHAR(1000),
    FULL_NAME_PRINT VARCHAR(1000),
    FULL_NAME_PRINT2 VARCHAR(1000),
    OO_PLACE VARCHAR(255),
    DIRECTOR_FIO VARCHAR(1000),
    DIRECTOR_JOB BIGINT)
AS
declare variable V$OBJ_ID_OU bigint;
declare variable V$TYPE_ID integer;
declare variable V$OBJ_ID bigint;
BEGIN
    SELECT TYPE_ID
    FROM OBJECTS
    WHERE OBJ_ID = :I$OBJ_ID
    INTO :V$TYPE_ID;

    IF (V$TYPE_ID <> 7) THEN
    BEGIN
        IF (V$TYPE_ID IN (9,125,187)) THEN
        BEGIN
            SELECT LP7.PARENT_ID
            FROM LINKS LP8
            JOIN LINKS LP7 ON LP7.OBJ_ID = LP8.PARENT_ID AND LP7.PARENT_TYPE_ID=7 AND LP7.DATE_DEL IS NULL
            WHERE LP8.OBJ_ID = :I$OBJ_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
            INTO :I$OBJ_ID;
        END
        ELSE
        IF (V$TYPE_ID IN (10, 126)) THEN
        BEGIN
            SELECT LP7.PARENT_ID
            FROM LINKS LP9
            JOIN LINKS LP8 ON LP8.OBJ_ID=LP9.PARENT_ID AND LP8.PARENT_TYPE_ID=8 AND LP8.DATE_DEL IS NULL
            JOIN LINKS LP7 ON LP7.OBJ_ID = LP8.PARENT_ID AND LP7.PARENT_TYPE_ID=7 AND LP7.DATE_DEL IS NULL
            WHERE LP9.OBJ_ID = :I$OBJ_ID AND LP9.PARENT_TYPE_ID IN (9, 187, 125) AND LP9.DATE_DEL IS NULL
            INTO :I$OBJ_ID;    
        END
    END

    SELECT FIRST 1 L222.OBJ_ID
    FROM LINKS L222
    WHERE L222.PARENT_ID = :I$OBJ_ID AND L222.DATE_DEL IS NULL AND L222.OBJ_TYPE_ID = 222
    INTO :V$OBJ_ID;

    IF (V$OBJ_ID IS NOT NULL) THEN
    BEGIN
        SELECT V FROM VAL_GET(:V$OBJ_ID, 1833, 0, :I$USER_ID) INTO :FULL_NAME;
        SELECT V FROM VAL_GET(:V$OBJ_ID, 1834, 0, :I$USER_ID) INTO :FULL_NAME_PRINT;
        SELECT V FROM VAL_GET(:V$OBJ_ID, 2352, 0, :I$USER_ID) INTO :FULL_NAME_PRINT2;
        SELECT V FROM VAL_GET(:V$OBJ_ID, 1835, 0, :I$USER_ID) INTO :OO_PLACE;
        SELECT V FROM VAL_GET(:V$OBJ_ID, 1836, 0, :I$USER_ID) INTO :DIRECTOR_FIO;
        SELECT I FROM VAL_GET(:V$OBJ_ID, 3113, 0, :I$USER_ID) INTO :DIRECTOR_JOB;

        IF(DIRECTOR_JOB = 13267) THEN DIRECTOR_JOB = 0;
        ELSE IF(DIRECTOR_JOB = 13268) THEN DIRECTOR_JOB = 1;
        ELSE DIRECTOR_JOB = 0;
    END
    ELSE
    BEGIN
        SELECT FIRST 1 OBJ_ID
        FROM LINKS
        WHERE OBJ_TYPE_ID = 2 AND PARENT_ID IS NULL
        INTO :V$OBJ_ID_OU;
        
        SELECT V FROM VAL_GET(:V$OBJ_ID_OU, 5, 0, :I$USER_ID) INTO :FULL_NAME;
        SELECT V FROM VAL_GET(:V$OBJ_ID_OU, 5, 0, :I$USER_ID) INTO :FULL_NAME_PRINT;
        FULL_NAME_PRINT2 = FULL_NAME_PRINT;

        IF (POSITION('САНКТ-ПЕТЕРБУРГ' IN UPPER(:FULL_NAME))>0) THEN
        BEGIN
            OO_PLACE = '';
        END
        ELSE
        BEGIN
            OO_PLACE = 'г. Санкт-Петербург';
        END

        SELECT SUBSTRING(I FROM 1 FOR 1) || '.' || SUBSTRING(O FROM 1 FOR 1) || '. ' || F
        FROM R_SPB_POST_DIRECTOR(:V$OBJ_ID_OU,:I$USER_ID)
        INTO :DIRECTOR_FIO;

        DIRECTOR_JOB = 0;
    END

    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CERTIFICATE_OO_SETTINGS_SET (
    I$OBJ_ID BIGINT,
    I$FULL_NAME VARCHAR(1000),
    I$FULL_NAME_PRINT VARCHAR(1000),
    I$FULL_NAME_PRINT2 VARCHAR(1000),
    I$OO_PLACE VARCHAR(255),
    I$DIRECTOR_FIO VARCHAR(1000),
    I$DIRECTOR_JOB BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$BLOB_ID bigint;
declare variable V$TYPE_ID integer;
BEGIN
    SELECT TYPE_ID
    FROM OBJECTS
    WHERE OBJ_ID = :I$OBJ_ID
    INTO :V$TYPE_ID;

    IF (V$TYPE_ID <> 7) THEN
    BEGIN
      IF (V$TYPE_ID = 9) THEN
      BEGIN
          SELECT LP7.PARENT_ID
          FROM LINKS LP8
          JOIN LINKS LP7 ON LP7.OBJ_ID = LP8.PARENT_ID AND LP7.PARENT_TYPE_ID=7 AND LP7.DATE_DEL IS NULL
          WHERE LP8.OBJ_ID = :I$OBJ_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
          INTO :I$OBJ_ID;
      END
      ELSE
      IF (V$TYPE_ID = 10) THEN
      BEGIN
          SELECT LP7.PARENT_ID
          FROM LINKS LP9
          JOIN LINKS LP8 ON LP8.OBJ_ID=LP9.PARENT_ID AND LP8.PARENT_TYPE_ID=8 AND LP8.DATE_DEL IS NULL
          JOIN LINKS LP7 ON LP7.OBJ_ID = LP8.PARENT_ID AND LP7.PARENT_TYPE_ID=7 AND LP7.DATE_DEL IS NULL
          WHERE LP9.OBJ_ID = :I$OBJ_ID AND LP9.PARENT_TYPE_ID = 9 AND LP9.DATE_DEL IS NULL
          INTO :I$OBJ_ID;
      END
    END

    IF(V$TYPE_ID = 2 OR V$TYPE_ID = 7 OR V$TYPE_ID = 9 OR V$TYPE_ID = 10) THEN
    BEGIN
        SELECT FIRST 1 OBJ_ID
        FROM LINKS
        WHERE PARENT_ID = :I$OBJ_ID AND DATE_DEL IS NULL AND OBJ_TYPE_ID = 222
        INTO OBJ_ID;

        IF (OBJ_ID IS NULL) THEN
        BEGIN
            SELECT OBJ_ID FROM OBJECT_ADD(:I$OBJ_ID, 222, NULL, NULL, :I$USER_ID) INTO OBJ_ID;
        END

        SELECT BLOB_ID FROM VAL_ADD(1833, :OBJ_ID, :I$FULL_NAME, :I$USER_ID) INTO :V$BLOB_ID;
        SELECT BLOB_ID FROM VAL_ADD(1834, :OBJ_ID, :I$FULL_NAME_PRINT, :I$USER_ID) INTO :V$BLOB_ID;
        SELECT BLOB_ID FROM VAL_ADD(2352, :OBJ_ID, :I$FULL_NAME_PRINT2, :I$USER_ID) INTO :V$BLOB_ID;
        SELECT BLOB_ID FROM VAL_ADD(1835, :OBJ_ID, :I$OO_PLACE, :I$USER_ID) INTO :V$BLOB_ID;
        SELECT BLOB_ID FROM VAL_ADD(1836, :OBJ_ID, :I$DIRECTOR_FIO, :I$USER_ID) INTO :V$BLOB_ID;
        SELECT BLOB_ID FROM VAL_ADD(3113, :OBJ_ID, IIF(:I$DIRECTOR_JOB = 1, 13268, 13267), :I$USER_ID) INTO :V$BLOB_ID;
    END
    ELSE EXCEPTION DATA_ERROR 'Недопустимый id родительского объекта';

    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CERTIFICATE_PUPIL_ENABLED_GET (
    I$PUPIL_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    ENABLED SMALLINT)
AS
BEGIN
    ENABLED = 0;

    SELECT FIRST 1 C.ENABLED
    FROM LINKS LP9
    LEFT JOIN CERTIFICATE_CLASS_ENABLED_GET(LP9.PARENT_ID, :I$USER_ID) C ON 1 = 1
    WHERE LP9.OBJ_ID = :I$PUPIL_ID AND LP9.PARENT_TYPE_ID IN (9, 125, 187) AND LP9.DATE_DEL IS NULL
    INTO :ENABLED;

    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CERTIFICATE_PUPIL_INFO_GET (
    I$YEAR BIGINT,
    I$STAGE_ID BIGINT,
    I$PUPIL_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    PUPIL_INFO_ID BIGINT,
    ORDER_ID BIGINT,
    CERTIFICATE_TYPE_ID BIGINT,
    ORDER_DATE DATE,
    GIVE_DATE DATE,
    GRADUATE_YEAR INTEGER,
    FORM_ID BIGINT,
    FORM_SERIA VARCHAR(10),
    FORM_NUMBER VARCHAR(10),
    FIO VARCHAR(1000),
    DOB DATE,
    ORDER_NUMBER VARCHAR(255),
    TMPL1 VARCHAR(255),
    TMPL2 VARCHAR(255),
    TMPL3 VARCHAR(255),
    TMPL4 VARCHAR(255),
    TMPL5 VARCHAR(255),
    HAS_GARBAGE_FORM SMALLINT,
    PROF VARCHAR(200),
    DATEGEK DATE,
    PEK VARCHAR(200),
    REGNO VARCHAR(10),
    KV VARCHAR(200),
    UO VARCHAR(100),
    OLDSERT VARCHAR(100),
    SROK VARCHAR(100),
    F VARCHAR(100),
    I VARCHAR(50),
    O VARCHAR(50))
AS
declare variable V$STAGE_TYPE_ID bigint;
declare variable V$OBJ_ID bigint;
declare variable V$PUPIL_TYPE_ID bigint;
declare variable V$FIO4CHECK10 varchar(1000);
declare variable V$FIO4CHECK230 varchar(1000);
declare variable V$DOB date;
declare variable V$BLOB_ID bigint;
BEGIN
    -- тип ученика
    SELECT TYPE_ID
    FROM OBJECTS
    WHERE OBJ_ID = :I$PUPIL_ID
    INTO :V$PUPIL_TYPE_ID;

    PUPIL_INFO_ID = NULL;

    -- уровень образования
    SELECT FIRST 1 V43.LISTVAL_ID
    FROM OBJECT_PARENTS_GET(:I$PUPIL_ID, 7) S
    JOIN VALL V43 ON V43.OBJ_ID = S.OBJ_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0
    INTO :V$STAGE_TYPE_ID;

    -- испорченные бланки
    SELECT FIRST 1 1
    FROM VALR V1872
    JOIN LINKS L234 ON L234.OBJ_ID = V1872.OBJ_ID AND L234.DATE_DEL IS NULL AND ((:I$STAGE_ID IS NULL) OR (L234.PARENT_ID = :I$STAGE_ID))
    JOIN VALR V1877 ON V1877.OBJ_ID = L234.OBJ_ID AND V1877.PARAM_ID = 1877 AND V1877.IS_DEL = 0
    JOIN LINKS L236 ON L236.OBJ_ID = V1877.VAL AND L236.DATE_DEL IS NULL
    JOIN VALS V1878 ON V1878.OBJ_ID = L236.OBJ_ID AND V1878.PARAM_ID = 1878 AND V1878.IS_DEL = 0
    JOIN VALL V1880 ON V1880.OBJ_ID = L236.OBJ_ID AND V1880.PARAM_ID = 1880 AND V1880.IS_DEL = 0 AND V1880.LISTVAL_ID = 5441
    WHERE V1872.VAL = :I$PUPIL_ID AND V1872.PARAM_ID = 1872 AND V1872.IS_DEL = 0
    INTO :HAS_GARBAGE_FORM;

    -- бланки
    SELECT FIRST 1 L236.OBJ_ID, V1878.VAL, V1881.VAL
    FROM VALR V1872
    JOIN LINKS L234 ON L234.OBJ_ID = V1872.OBJ_ID AND L234.DATE_DEL IS NULL AND ((:I$STAGE_ID IS NULL) OR (L234.PARENT_ID = :I$STAGE_ID))
    JOIN VALD V1876 ON V1876.OBJ_ID = L234.OBJ_ID AND V1876.PARAM_ID = 1876 AND V1876.IS_DEL = 0
    JOIN VALR V1877 ON V1877.OBJ_ID = L234.OBJ_ID AND V1877.PARAM_ID = 1877 AND V1877.IS_DEL = 0
    JOIN LINKS L236 ON L236.OBJ_ID = V1877.VAL AND L236.DATE_DEL IS NULL
    JOIN VALS V1878 ON V1878.OBJ_ID = L236.OBJ_ID AND V1878.PARAM_ID = 1878 AND V1878.IS_DEL = 0
    JOIN VALL V1880 ON V1880.OBJ_ID = L236.OBJ_ID AND V1880.PARAM_ID = 1880 AND V1880.IS_DEL = 0 AND V1880.LISTVAL_ID IN (5438, 5439)
    JOIN LINKS LP228 ON LP228.OBJ_ID = L236.OBJ_ID AND LP228.PARENT_TYPE_ID = 228 AND LP228.DATE_DEL IS NULL
    JOIN VALS V1881 ON V1881.OBJ_ID = LP228.PARENT_ID AND V1881.PARAM_ID = 1881 AND V1881.IS_DEL = 0
    WHERE V1872.VAL = :I$PUPIL_ID AND V1872.PARAM_ID = 1872 AND V1872.IS_DEL = 0
    ORDER BY V1876.VAL DESC
    INTO :FORM_ID, :FORM_NUMBER, :FORM_SERIA;

    -- данные для печати аттестата
    SELECT FIRST 1 L230.OBJ_ID
    FROM LINKS L292
    JOIN VALI V2354 ON V2354.OBJ_ID = L292.OBJ_ID AND V2354.PARAM_ID = 2354 AND V2354.VAL = :I$YEAR AND V2354.IS_DEL = 0
    JOIN LINKS L230 ON L230.PARENT_ID = L292.OBJ_ID AND L230.OBJ_TYPE_ID = 230 AND L230.DATE_DEL IS NULL
    WHERE L292.PARENT_ID = :I$PUPIL_ID AND L292.OBJ_TYPE_ID = 292 AND L292.DATE_DEL IS NULL
    ORDER BY V2354.VAL DESC, L230.OBJ_ID DESC
    INTO :PUPIL_INFO_ID;

    IF (PUPIL_INFO_ID IS NULL) THEN
    BEGIN
        IF (V$PUPIL_TYPE_ID = 10) THEN
        BEGIN
            SELECT V FROM VAL_GET(:I$PUPIL_ID, 55, 0, :I$USER_ID) INTO :F;
            SELECT V FROM VAL_GET(:I$PUPIL_ID, 56, 0, :I$USER_ID) INTO :I;
            SELECT V FROM VAL_GET(:I$PUPIL_ID, 57, 0, :I$USER_ID) INTO :O;
            SELECT D FROM VAL_GET(:I$PUPIL_ID, 89, 0, :I$USER_ID) INTO :DOB;
        END
        ELSE IF (V$PUPIL_TYPE_ID = 126) THEN
        BEGIN
            SELECT V FROM VAL_GET(:I$PUPIL_ID, 827, 0, :I$USER_ID) INTO :F;
            SELECT V FROM VAL_GET(:I$PUPIL_ID, 828, 0, :I$USER_ID) INTO :I;
            SELECT V FROM VAL_GET(:I$PUPIL_ID, 829, 0, :I$USER_ID) INTO :O;
            SELECT D FROM VAL_GET(:I$PUPIL_ID, 830, 0, :I$USER_ID) INTO :DOB;
        END

        FIO = F || ASCII_CHAR(13) || ASCII_CHAR(10) || I || ' ' || O;

        IF (EXISTS(
                SELECT FIRST 1 1
                FROM LINKS
                WHERE OBJ_ID = :I$PUPIL_ID AND PARENT_TYPE_ID IN (125,187) AND DATE_DEL IS NULL)
            OR NOT EXISTS(
                SELECT FIRST 1 1
                FROM LINKS
                WHERE OBJ_ID = :I$PUPIL_ID AND PARENT_TYPE_ID IN (81,82,83) AND DATE_DEL IS NULL
        )) THEN
        BEGIN
            --для печати 3 волны аттестатов в сентябре берется календарный год
            GRADUATE_YEAR = EXTRACT(YEAR FROM CURRENT_DATE);
        END

        IF (V$STAGE_TYPE_ID = 26) THEN
        BEGIN
            CERTIFICATE_TYPE_ID = 5377;
        END
        ELSE
        BEGIN
            CERTIFICATE_TYPE_ID = 5379;
        END

        SELECT FIRST 1 L232.OBJ_ID
        FROM LINKS LP9
        JOIN LINKS L232 ON L232.PARENT_ID = LP9.PARENT_ID AND L232.OBJ_TYPE_ID = 232 AND L232.DATE_DEL IS NULL
        WHERE LP9.PARENT_TYPE_ID IN (9, 125, 187) AND LP9.OBJ_ID = :I$PUPIL_ID AND LP9.DATE_DEL IS NULL
        INTO :V$OBJ_ID;

        IF (V$OBJ_ID IS NULL) THEN
        BEGIN
            TMPL1 = 'Стандартный';
            TMPL2 = TMPL1;
            TMPL3 = TMPL1;
            TMPL4 = TMPL1;
            TMPL5 = TMPL1;
        END
        ELSE
        BEGIN
            SELECT I FROM VAL_GET(:V$OBJ_ID, 1865, 0, :I$USER_ID) INTO :ORDER_ID;

            IF (ORDER_ID IS NOT NULL) THEN
            BEGIN
                SELECT D FROM VAL_GET(:ORDER_ID, 1843, 0, :I$USER_ID) INTO :ORDER_DATE;
                SELECT V FROM VAL_GET(:ORDER_ID, 1842, 0, :I$USER_ID) INTO :ORDER_NUMBER;
            END

            SELECT V FROM VAL_GET(:V$OBJ_ID, 1866, 0, :I$USER_ID) INTO :TMPL1;
            SELECT V FROM VAL_GET(:V$OBJ_ID, 1867, 0, :I$USER_ID) INTO :TMPL2;
            SELECT V FROM VAL_GET(:V$OBJ_ID, 1868, 0, :I$USER_ID) INTO :TMPL3;
            SELECT V FROM VAL_GET(:V$OBJ_ID, 1869, 0, :I$USER_ID) INTO :TMPL4;
            SELECT V FROM VAL_GET(:V$OBJ_ID, 1886, 0, :I$USER_ID) INTO :TMPL5;
            SELECT V FROM VAL_GET(:V$OBJ_ID, 2889, 0, :I$USER_ID) INTO :PROF;
            SELECT D FROM VAL_GET(:V$OBJ_ID, 2890, 0, :I$USER_ID) INTO :DATEGEK;
            SELECT V FROM VAL_GET(:V$OBJ_ID, 2891, 0, :I$USER_ID) INTO :PEK;
            SELECT V FROM VAL_GET(:V$OBJ_ID, 2892, 0, :I$USER_ID) INTO :KV;
            SELECT V FROM VAL_GET(:V$OBJ_ID, 2893, 0, :I$USER_ID) INTO :UO;
            SELECT V FROM VAL_GET(:V$OBJ_ID, 2894, 0, :I$USER_ID) INTO :SROK;
        END
    END
    ELSE
    BEGIN
        SELECT I FROM VAL_GET(:PUPIL_INFO_ID, 1855, 0, :I$USER_ID) INTO :ORDER_ID;
        SELECT D FROM VAL_GET(:PUPIL_INFO_ID, 1856, 0, :I$USER_ID) INTO :ORDER_DATE;
        SELECT D FROM VAL_GET(:PUPIL_INFO_ID, 1884, 0, :I$USER_ID) INTO :GIVE_DATE;
        SELECT I FROM VAL_GET(:PUPIL_INFO_ID, 1857, 0, :I$USER_ID) INTO :GRADUATE_YEAR;

        --
        IF (V$PUPIL_TYPE_ID = 10) THEN
        BEGIN
            SELECT V FROM VAL_GET(:I$PUPIL_ID, 55, 0, :I$USER_ID) INTO :F;
            SELECT V FROM VAL_GET(:I$PUPIL_ID, 56, 0, :I$USER_ID) INTO :I;
            SELECT V FROM VAL_GET(:I$PUPIL_ID, 57, 0, :I$USER_ID) INTO :O;
            SELECT D FROM VAL_GET(:I$PUPIL_ID, 89, 0, :I$USER_ID) INTO :V$DOB;
        END
        ELSE IF (V$PUPIL_TYPE_ID = 126) THEN
        BEGIN
            SELECT V FROM VAL_GET(:I$PUPIL_ID, 827, 0, :I$USER_ID) INTO :F;
            SELECT V FROM VAL_GET(:I$PUPIL_ID, 828, 0, :I$USER_ID) INTO :I;
            SELECT V FROM VAL_GET(:I$PUPIL_ID, 829, 0, :I$USER_ID) INTO :O;
            SELECT D FROM VAL_GET(:I$PUPIL_ID, 830, 0, :I$USER_ID) INTO :V$DOB;
        END

        SELECT D FROM VAL_GET(:PUPIL_INFO_ID, 1859, 0, :I$USER_ID) INTO :DOB;

        IF (DOB <> V$DOB) THEN
        BEGIN
            SELECT BLOB_ID FROM VAL_ADD(1859, :PUPIL_INFO_ID, :V$DOB) INTO :V$BLOB_ID;
            DOB = V$DOB;
        END

        SELECT V FROM VAL_GET(:PUPIL_INFO_ID, 1858, 0, :I$USER_ID) INTO :FIO;

        V$FIO4CHECK230 = TRIM(FIO);
        V$FIO4CHECK230 = REPLACE(V$FIO4CHECK230,ASCII_CHAR(13)||ASCII_CHAR(10),'');
        V$FIO4CHECK230 = REPLACE(V$FIO4CHECK230,ASCII_CHAR(13),'');
        V$FIO4CHECK230 = REPLACE(V$FIO4CHECK230,ASCII_CHAR(10),'');
        V$FIO4CHECK230 = REPLACE(V$FIO4CHECK230,' ','');

        V$FIO4CHECK10 = TRIM(F||I||O);

        IF (V$FIO4CHECK230 <> V$FIO4CHECK10) THEN
        BEGIN
            FIO = F || ASCII_CHAR(13) || ASCII_CHAR(10) || I || ' ' || O;
        END
        --

        SELECT I FROM VAL_GET(:PUPIL_INFO_ID, 1860, 0, :I$USER_ID) INTO :CERTIFICATE_TYPE_ID;
        SELECT V FROM VAL_GET(:PUPIL_INFO_ID, 1861, 0, :I$USER_ID) INTO :TMPL1;
        SELECT V FROM VAL_GET(:PUPIL_INFO_ID, 1862, 0, :I$USER_ID) INTO :TMPL2;
        SELECT V FROM VAL_GET(:PUPIL_INFO_ID, 1863, 0, :I$USER_ID) INTO :TMPL3;
        SELECT V FROM VAL_GET(:PUPIL_INFO_ID, 1864, 0, :I$USER_ID) INTO :TMPL4;
        SELECT V FROM VAL_GET(:PUPIL_INFO_ID, 1887, 0, :I$USER_ID) INTO :TMPL5;
        SELECT V FROM VAL_GET(:PUPIL_INFO_ID, 2881, 0, :I$USER_ID) INTO :PROF;
        SELECT D FROM VAL_GET(:PUPIL_INFO_ID, 2882, 0, :I$USER_ID) INTO :DATEGEK;
        SELECT V FROM VAL_GET(:PUPIL_INFO_ID, 2883, 0, :I$USER_ID) INTO :PEK;
        SELECT V FROM VAL_GET(:PUPIL_INFO_ID, 2884, 0, :I$USER_ID) INTO :REGNO;
        SELECT V FROM VAL_GET(:PUPIL_INFO_ID, 2885, 0, :I$USER_ID) INTO :KV;
        SELECT V FROM VAL_GET(:PUPIL_INFO_ID, 2886, 0, :I$USER_ID) INTO :UO;
        SELECT V FROM VAL_GET(:PUPIL_INFO_ID, 2887, 0, :I$USER_ID) INTO :OLDSERT;
        SELECT V FROM VAL_GET(:PUPIL_INFO_ID, 2888, 0, :I$USER_ID) INTO :SROK;
    END

    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CERTIFICATE_PUPIL_INFO_READ (
    I$BOOK_REC_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    PUPIL_INFO_ID BIGINT,
    ORDER_ID BIGINT,
    CERTIFICATE_TYPE_ID BIGINT,
    ORDER_DATE DATE,
    GIVE_DATE DATE,
    GRADUATE_YEAR INTEGER,
    FORM_ID BIGINT,
    FORM_SERIA VARCHAR(10),
    FORM_NUMBER VARCHAR(10),
    FIO VARCHAR(1000),
    DOB DATE,
    TMPL1 VARCHAR(255),
    TMPL2 VARCHAR(255),
    TMPL3 VARCHAR(255),
    TMPL4 VARCHAR(255),
    TMPL5 VARCHAR(255),
    PROF VARCHAR(200),
    DATEGEK DATE,
    PEK VARCHAR(100),
    REGNO VARCHAR(10),
    KV VARCHAR(200),
    UO VARCHAR(100),
    OLDSERT VARCHAR(100),
    SROK VARCHAR(100))
AS
declare variable V$PUPIL_LASTNAME varchar(255);
declare variable V$PUPIL_FIRSTNAME varchar(255);
declare variable V$PUPIL_MIDDLENAME varchar(255);
declare variable V$STAGE_TYPE_ID bigint;
declare variable V$PUPIL_ID bigint;
declare variable V$PUPIL_TYPE_ID bigint;
declare variable V$FIO4CHECK10 varchar(1000);
declare variable V$FIO4CHECK230 varchar(1000);
declare variable V$DOB date;
declare variable V$BLOB_ID bigint;
BEGIN
    FOR
        SELECT FIRST 1
               L230.OBJ_ID,
               O10.OBJ_ID,
               O10.TYPE_ID
    
        FROM VALR V2355
    
        JOIN LINKS L230
        ON L230.PARENT_ID = V2355.VAL
        AND L230.OBJ_TYPE_ID = 230
        AND L230.DATE_DEL IS NULL
    
        JOIN VALR V1872
        ON V1872.OBJ_ID = :I$BOOK_REC_ID
        AND V1872.PARAM_ID = 1872
        AND V1872.IS_DEL = 0

        JOIN OBJECTS O10
        ON O10.OBJ_ID = V1872.VAL

        WHERE V2355.OBJ_ID = :I$BOOK_REC_ID
        AND V2355.PARAM_ID = 2355
        AND V2355.IS_DEL = 0
    
        INTO :PUPIL_INFO_ID,
             :V$PUPIL_ID,
             :V$PUPIL_TYPE_ID
    DO
    BEGIN
        SELECT I
        FROM VAL_GET(:PUPIL_INFO_ID, 1855, 0, :I$USER_ID)
        INTO :ORDER_ID;

        SELECT D
        FROM VAL_GET(:PUPIL_INFO_ID, 1856, 0, :I$USER_ID)
        INTO :ORDER_DATE;

        SELECT D
        FROM VAL_GET(:PUPIL_INFO_ID, 1884, 0, :I$USER_ID)
        INTO :GIVE_DATE;

        SELECT I
        FROM VAL_GET(:PUPIL_INFO_ID, 1857, 0, :I$USER_ID)
        INTO :GRADUATE_YEAR;

        --
        IF (V$PUPIL_TYPE_ID = 10) THEN
        BEGIN
            SELECT V
            FROM VAL_GET(:V$PUPIL_ID, 55, 0, :I$USER_ID)
            INTO :V$PUPIL_LASTNAME;
    
            SELECT V
            FROM VAL_GET(:V$PUPIL_ID, 56, 0, :I$USER_ID)
            INTO :V$PUPIL_FIRSTNAME;
    
            SELECT V
            FROM VAL_GET(:V$PUPIL_ID, 57, 0, :I$USER_ID)
            INTO :V$PUPIL_MIDDLENAME;

            SELECT D
            FROM VAL_GET(:V$PUPIL_ID, 89, 0, :I$USER_ID)
            INTO :V$DOB;
        END
        ELSE IF (V$PUPIL_TYPE_ID = 126) THEN
        BEGIN
            SELECT V
            FROM VAL_GET(:V$PUPIL_ID, 827, 0, :I$USER_ID)
            INTO :V$PUPIL_LASTNAME;
    
            SELECT V
            FROM VAL_GET(:V$PUPIL_ID, 828, 0, :I$USER_ID)
            INTO :V$PUPIL_FIRSTNAME;
    
            SELECT V
            FROM VAL_GET(:V$PUPIL_ID, 829, 0, :I$USER_ID)
            INTO :V$PUPIL_MIDDLENAME;

            SELECT D
            FROM VAL_GET(:V$PUPIL_ID, 830, 0, :I$USER_ID)
            INTO :V$DOB;
        END

        SELECT D
        FROM VAL_GET(:PUPIL_INFO_ID, 1859, 0, :I$USER_ID)
        INTO :DOB;

        IF (DOB <> V$DOB) THEN
        BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD(1859, :PUPIL_INFO_ID, :V$DOB)
            INTO :V$BLOB_ID;

            DOB = V$DOB;
        END

        SELECT V
        FROM VAL_GET(:PUPIL_INFO_ID, 1858, 0, :I$USER_ID)
        INTO :FIO;

        V$FIO4CHECK230 = TRIM(FIO);
        V$FIO4CHECK230 = REPLACE(V$FIO4CHECK230,ASCII_CHAR(13)||ASCII_CHAR(10),'');
        V$FIO4CHECK230 = REPLACE(V$FIO4CHECK230,ASCII_CHAR(13),'');
        V$FIO4CHECK230 = REPLACE(V$FIO4CHECK230,ASCII_CHAR(10),'');
        V$FIO4CHECK230 = REPLACE(V$FIO4CHECK230,' ','');

        V$FIO4CHECK10 = TRIM(V$PUPIL_LASTNAME||V$PUPIL_FIRSTNAME||V$PUPIL_MIDDLENAME);

        IF (V$FIO4CHECK230 <> V$FIO4CHECK10) THEN
        BEGIN
            FIO = V$PUPIL_LASTNAME || ASCII_CHAR(13) || ASCII_CHAR(10) || V$PUPIL_FIRSTNAME || ' ' || V$PUPIL_MIDDLENAME;
        END
        --

        SELECT I
        FROM VAL_GET(:PUPIL_INFO_ID, 1860, 0, :I$USER_ID)
        INTO :CERTIFICATE_TYPE_ID;

        SELECT V
        FROM VAL_GET(:PUPIL_INFO_ID, 1861, 0, :I$USER_ID)
        INTO :TMPL1;

        SELECT V
        FROM VAL_GET(:PUPIL_INFO_ID, 1862, 0, :I$USER_ID)
        INTO :TMPL2;

        SELECT V
        FROM VAL_GET(:PUPIL_INFO_ID, 1863, 0, :I$USER_ID)
        INTO :TMPL3;

        SELECT V
        FROM VAL_GET(:PUPIL_INFO_ID, 1864, 0, :I$USER_ID)
        INTO :TMPL4;

        SELECT V
        FROM VAL_GET(:PUPIL_INFO_ID, 1887, 0, :I$USER_ID)
        INTO :TMPL5;

        SELECT V
        FROM VAL_GET(:PUPIL_INFO_ID, 2881, 0, :I$USER_ID)
        INTO :PROF;

        SELECT D
        FROM VAL_GET(:PUPIL_INFO_ID, 2882, 0, :I$USER_ID)
        INTO :DATEGEK;

        SELECT V
        FROM VAL_GET(:PUPIL_INFO_ID, 2883, 0, :I$USER_ID)
        INTO :PEK;

        SELECT V
        FROM VAL_GET(:PUPIL_INFO_ID, 2884, 0, :I$USER_ID)
        INTO :REGNO;

        SELECT V
        FROM VAL_GET(:PUPIL_INFO_ID, 2885, 0, :I$USER_ID)
        INTO :KV;

        SELECT V
        FROM VAL_GET(:PUPIL_INFO_ID, 2886, 0, :I$USER_ID)
        INTO :UO;

        SELECT V
        FROM VAL_GET(:PUPIL_INFO_ID, 2887, 0, :I$USER_ID)
        INTO :OLDSERT;

        SELECT V
        FROM VAL_GET(:PUPIL_INFO_ID, 2888, 0, :I$USER_ID)
        INTO :SROK;
    END

    SELECT FIRST 1
           L236.OBJ_ID,
           V1878.VAL,
           V1881.VAL
    FROM VALD V1876

    JOIN VALR V1877
    ON V1877.OBJ_ID = :I$BOOK_REC_ID
    AND V1877.PARAM_ID = 1877
    AND V1877.IS_DEL = 0

    JOIN LINKS L236
    ON L236.OBJ_ID = V1877.VAL
    AND L236.DATE_DEL IS NULL

    JOIN VALS V1878
    ON V1878.OBJ_ID = L236.OBJ_ID
    AND V1878.PARAM_ID = 1878
    AND V1878.IS_DEL = 0

    JOIN VALL V1880
    ON V1880.OBJ_ID = L236.OBJ_ID
    AND V1880.PARAM_ID = 1880
    AND V1880.IS_DEL = 0
    AND V1880.LISTVAL_ID IN (5438, 5439)
 
    JOIN LINKS LP228
    ON LP228.OBJ_ID = L236.OBJ_ID
    AND LP228.PARENT_TYPE_ID = 228
    AND LP228.DATE_DEL IS NULL

    JOIN VALS V1881
    ON V1881.OBJ_ID = LP228.PARENT_ID
    AND V1881.PARAM_ID = 1881
    AND V1881.IS_DEL = 0

    WHERE V1876.OBJ_ID = :I$BOOK_REC_ID
    AND V1876.PARAM_ID = 1876
    AND V1876.IS_DEL = 0

    ORDER BY V1876.VAL DESC

    INTO :FORM_ID,
         :FORM_NUMBER,
         :FORM_SERIA;

    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CERTIFICATE_PUPIL_INFO_SET (
    I$PUPIL_ID BIGINT,
    I$USER_ID BIGINT,
    I$PUPIL_INFO_ID BIGINT,
    I$ORDER_ID BIGINT,
    I$CERTIFICATE_TYPE_ID BIGINT,
    I$ORDER_DATE DATE,
    I$GIVE_DATE DATE,
    I$GRADUATE_YEAR SMALLINT,
    I$REPLACE_GRADUATE_YEAR SMALLINT,
    I$FIO VARCHAR(1000),
    I$DOB DATE,
    I$TMPL1 VARCHAR(255),
    I$TMPL2 VARCHAR(255),
    I$TMPL3 VARCHAR(255),
    I$TMPL4 VARCHAR(255),
    I$TMPL5 VARCHAR(255),
    I$PROF VARCHAR(200),
    I$GEKDATE DATE,
    I$PEK VARCHAR(200),
    I$REGNO VARCHAR(10),
    I$KV VARCHAR(200),
    I$UO VARCHAR(100),
    I$OLDSERT VARCHAR(100),
    I$SROK VARCHAR(100))
RETURNS (
    PUPIL_INFO_ID BIGINT)
AS
declare variable V$BLOB_ID bigint;
declare variable V$STORAGE_ID bigint;
BEGIN
    IF (I$REPLACE_GRADUATE_YEAR IS NOT NULL) THEN
    BEGIN
        -- Заменяем год выпуска на новый, при этом в I$REPLACE_GRADUATE_YEAR будет указан старый год выпуска
        -- Но если уже есть контейнер со старым годом, то удаляем к черту старый контейнер
        SELECT FIRST 1 L292.OBJ_ID, L230.OBJ_ID
        FROM LINKS L292
        JOIN VALI V2354 ON V2354.OBJ_ID = L292.OBJ_ID AND V2354.PARAM_ID = 2354 AND V2354.IS_DEL = 0 AND V2354.VAL = :I$GRADUATE_YEAR
        JOIN LINKS L230 ON L230.PARENT_ID = L292.OBJ_ID AND L230.OBJ_TYPE_ID = 230 AND L230.DATE_DEL IS NULL
        WHERE L292.PARENT_ID = :I$PUPIL_ID AND L292.OBJ_TYPE_ID = 292 AND L292.DATE_DEL IS NULL
        ORDER BY V2354.VAL DESC, L230.OBJ_ID DESC
        INTO :V$STORAGE_ID, :PUPIL_INFO_ID;

        IF(V$STORAGE_ID IS NOT NULL) THEN
        BEGIN
            UPDATE LINKS SET DATE_DEL = CURRENT_TIMESTAMP WHERE OBJ_ID = :V$STORAGE_ID;
            V$STORAGE_ID = NULL;
            PUPIL_INFO_ID = NULL;
        END

        SELECT FIRST 1 L292.OBJ_ID, L230.OBJ_ID
        FROM LINKS L292
        JOIN VALI V2354 ON V2354.OBJ_ID = L292.OBJ_ID AND V2354.PARAM_ID = 2354 AND V2354.IS_DEL = 0 AND V2354.VAL = :I$REPLACE_GRADUATE_YEAR
        JOIN LINKS L230 ON L230.PARENT_ID = L292.OBJ_ID AND L230.OBJ_TYPE_ID = 230 AND L230.DATE_DEL IS NULL
        WHERE L292.PARENT_ID = :I$PUPIL_ID AND L292.OBJ_TYPE_ID = 292 AND L292.DATE_DEL IS NULL
        INTO :V$STORAGE_ID, :PUPIL_INFO_ID;

        --IF(V$STORAGE_ID IS NULL) THEN EXCEPTION 'Контейнер выдачи аттестата не найден';
        SELECT BLOB_ID
        FROM VAL_ADD(2354, :V$STORAGE_ID, :I$GRADUATE_YEAR)
        INTO :V$BLOB_ID;
    END
    ELSE
    BEGIN
        SELECT FIRST 1 L230.OBJ_ID
        FROM LINKS L292
        JOIN VALI V2354 ON V2354.OBJ_ID = L292.OBJ_ID AND V2354.PARAM_ID = 2354 AND V2354.IS_DEL = 0 AND V2354.VAL = :I$GRADUATE_YEAR
        JOIN LINKS L230 ON L230.PARENT_ID = L292.OBJ_ID AND L230.OBJ_TYPE_ID = 230 AND L230.DATE_DEL IS NULL
        WHERE L292.PARENT_ID = :I$PUPIL_ID AND L292.OBJ_TYPE_ID = 292 AND L292.DATE_DEL IS NULL
        ORDER BY V2354.VAL DESC, L230.OBJ_ID DESC
        INTO :PUPIL_INFO_ID;
    END

    IF (PUPIL_INFO_ID IS NULL) THEN
    BEGIN
        SELECT FIRST 1 L292.OBJ_ID
        FROM LINKS L292
        JOIN VALI V2354 ON V2354.OBJ_ID = L292.OBJ_ID AND V2354.PARAM_ID = 2354 AND V2354.IS_DEL = 0 AND V2354.VAL = :I$GRADUATE_YEAR
        WHERE L292.PARENT_ID = :I$PUPIL_ID AND L292.OBJ_TYPE_ID = 292 AND L292.DATE_DEL IS NULL
        INTO :V$STORAGE_ID;
    
        IF (V$STORAGE_ID IS NULL) THEN
        BEGIN
            FOR
                SELECT OBJ_ID
                FROM OBJECT_ADD(:I$PUPIL_ID, 292)
                INTO :V$STORAGE_ID
            DO
            BEGIN
                SELECT BLOB_ID FROM VAL_ADD(2354, :V$STORAGE_ID, :I$GRADUATE_YEAR) INTO :V$BLOB_ID;
            END
        END

        SELECT OBJ_ID FROM OBJECT_ADD(:V$STORAGE_ID, 230, NULL, NULL, :I$USER_ID) INTO :PUPIL_INFO_ID;
    END

    -- По идее всегда должны сюда попадать с непустым PUPIL_INFO_ID
    IF (PUPIL_INFO_ID IS NOT NULL) THEN
    BEGIN
        SELECT BLOB_ID FROM VAL_ADD(1855, :PUPIL_INFO_ID, :I$ORDER_ID, :I$USER_ID) INTO :V$BLOB_ID;
        SELECT BLOB_ID FROM VAL_ADD(1856, :PUPIL_INFO_ID, :I$ORDER_DATE, :I$USER_ID) INTO :V$BLOB_ID;
        SELECT BLOB_ID FROM VAL_ADD(1884, :PUPIL_INFO_ID, :I$GIVE_DATE, :I$USER_ID) INTO :V$BLOB_ID;
        SELECT BLOB_ID FROM VAL_ADD(1857, :PUPIL_INFO_ID, :I$GRADUATE_YEAR, :I$USER_ID) INTO :V$BLOB_ID;
        SELECT BLOB_ID FROM VAL_ADD(1858, :PUPIL_INFO_ID, :I$FIO, :I$USER_ID) INTO :V$BLOB_ID;
        SELECT BLOB_ID FROM VAL_ADD(1859, :PUPIL_INFO_ID, :I$DOB, :I$USER_ID) INTO :V$BLOB_ID;
        SELECT BLOB_ID FROM VAL_ADD(1860, :PUPIL_INFO_ID, :I$CERTIFICATE_TYPE_ID, :I$USER_ID) INTO :V$BLOB_ID;
        SELECT BLOB_ID FROM VAL_ADD(1861, :PUPIL_INFO_ID, :I$TMPL1, :I$USER_ID) INTO :V$BLOB_ID;
        SELECT BLOB_ID FROM VAL_ADD(1862, :PUPIL_INFO_ID, :I$TMPL2, :I$USER_ID) INTO :V$BLOB_ID;
        SELECT BLOB_ID FROM VAL_ADD(1863, :PUPIL_INFO_ID, :I$TMPL3, :I$USER_ID) INTO :V$BLOB_ID;
        SELECT BLOB_ID FROM VAL_ADD(1864, :PUPIL_INFO_ID, :I$TMPL4, :I$USER_ID) INTO :V$BLOB_ID;
        SELECT BLOB_ID FROM VAL_ADD(1887, :PUPIL_INFO_ID, :I$TMPL5, :I$USER_ID) INTO :V$BLOB_ID;
        SELECT BLOB_ID FROM VAL_ADD(2881, :PUPIL_INFO_ID, :I$PROF, :I$USER_ID) INTO :V$BLOB_ID;
        SELECT BLOB_ID FROM VAL_ADD(2882, :PUPIL_INFO_ID, :I$GEKDATE, :I$USER_ID) INTO :V$BLOB_ID;
        SELECT BLOB_ID FROM VAL_ADD(2883, :PUPIL_INFO_ID, :I$PEK, :I$USER_ID) INTO :V$BLOB_ID;
        SELECT BLOB_ID FROM VAL_ADD(2884, :PUPIL_INFO_ID, :I$REGNO, :I$USER_ID) INTO :V$BLOB_ID;
        SELECT BLOB_ID FROM VAL_ADD(2885, :PUPIL_INFO_ID, :I$KV, :I$USER_ID) INTO :V$BLOB_ID;
        SELECT BLOB_ID FROM VAL_ADD(2886, :PUPIL_INFO_ID, :I$UO, :I$USER_ID) INTO :V$BLOB_ID;
        SELECT BLOB_ID FROM VAL_ADD(2887, :PUPIL_INFO_ID, :I$OLDSERT, :I$USER_ID) INTO :V$BLOB_ID;
        SELECT BLOB_ID FROM VAL_ADD(2888, :PUPIL_INFO_ID, :I$SROK, :I$USER_ID) INTO :V$BLOB_ID;
    END

    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CERTIFICATE_PUPIL_LIST (
    I$CLASS_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    PUPIL_ID BIGINT,
    PUPIL_FIO VARCHAR(1000),
    PUPIL_FIRSTNAME VARCHAR(255),
    PUPIL_MIDDLENAME VARCHAR(255),
    PUPIL_LASTNAME VARCHAR(255))
AS
declare variable V$TYPE_ID bigint;
declare variable V$SCHOOL_ID bigint;
declare variable V$PLAN_ID bigint;
declare variable V$PARALLEL_TYPE_ID bigint;
BEGIN
    FOR
        SELECT L10.OBJ_ID,
               L10.OBJ_TYPE_ID
        FROM LINKS L10

        WHERE L10.PARENT_ID = :I$CLASS_ID
        AND L10.OBJ_TYPE_ID IN (10,126)
        AND L10.DATE_DEL IS NULL

        INTO :PUPIL_ID,
             :V$TYPE_ID
    DO
    BEGIN
        IF (V$TYPE_ID = 10) THEN
        BEGIN
            SELECT V
            FROM VAL_GET(:PUPIL_ID, 55, 0, :I$USER_ID)
            INTO :PUPIL_LASTNAME;
    
            SELECT V
            FROM VAL_GET(:PUPIL_ID, 56, 0, :I$USER_ID)
            INTO :PUPIL_FIRSTNAME;
    
            SELECT V
            FROM VAL_GET(:PUPIL_ID, 57, 0, :I$USER_ID)
            INTO :PUPIL_MIDDLENAME;
        END
        ELSE IF (V$TYPE_ID = 126) THEN
        BEGIN
            SELECT V
            FROM VAL_GET(:PUPIL_ID, 827, 0, :I$USER_ID)
            INTO :PUPIL_LASTNAME;
    
            SELECT V
            FROM VAL_GET(:PUPIL_ID, 828, 0, :I$USER_ID)
            INTO :PUPIL_FIRSTNAME;
    
            SELECT V
            FROM VAL_GET(:PUPIL_ID, 829, 0, :I$USER_ID)
            INTO :PUPIL_MIDDLENAME;
        END

        PUPIL_FIO = PUPIL_LASTNAME;
        IF (PUPIL_FIRSTNAME <> '') THEN
        BEGIN
            IF (PUPIL_FIO <> '') THEN
            BEGIN
                PUPIL_FIO = PUPIL_FIO || ' ';
            END
            PUPIL_FIO = PUPIL_FIO || PUPIL_FIRSTNAME;
        END
        IF (PUPIL_MIDDLENAME <> '') THEN
        BEGIN
            IF (PUPIL_FIO <> '') THEN
            BEGIN
                PUPIL_FIO = PUPIL_FIO || ' ';
            END
            PUPIL_FIO = PUPIL_FIO || PUPIL_MIDDLENAME;
        END
        IF (PUPIL_FIO <> '') THEN
        BEGIN
            SUSPEND;
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CERTIFICATE_PUPIL_LOAD_SUBJECTS (
    I$YEAR SMALLINT,
    I$STAGE_ID BIGINT,
    I$CLASS_ID BIGINT,
    I$PUPIL_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    P_SUBJECT_ID BIGINT,
    INCLUDING_TYPE_ID BIGINT,
    SUBJECT_ID BIGINT,
    SUBJECT_NAME VARCHAR(1000),
    MARK VARCHAR(255),
    MARK_YEAR VARCHAR(255),
    MARK_FIN VARCHAR(255),
    MARK_GIA VARCHAR(255),
    IS_BASE SMALLINT,
    IS_PLAN SMALLINT,
    SORT_ORDER INTEGER,
    SUBJECT_LOAD VARCHAR(10),
    REC_MARK DOUBLE PRECISION,
    PROJECT_THEME VARCHAR(4000))
AS
declare variable V$LANG_CODE varchar(2);
declare variable Y smallint;
declare variable YEAR_ID bigint;
declare variable V$PLAN_ID bigint;
declare variable V$HOURS_TOTAL float;
declare variable V$N_MARKS integer;
declare variable V$STAGE_CODE bigint;
BEGIN
    IF (I$CLASS_ID IS NULL) THEN
    BEGIN
        SELECT FIRST 1 PARENT_ID
        FROM LINKS
        WHERE OBJ_ID = :I$PUPIL_ID AND PARENT_TYPE_ID IN (9,125,187,81,82,83) AND DATE_DEL IS NULL
        INTO :I$CLASS_ID;
    END

    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :V$LANG_CODE;

    FOR
        SELECT L51.SUBJECT_ID, CASE WHEN L51.P_SUBJECT_NAME <> '' THEN L51.P_SUBJECT_NAME ELSE L51.SUBJECT_NAME END
        FROM CERTIFICATE_PUPIL_SUBJECT_LIST(:I$YEAR, :I$STAGE_ID, :I$CLASS_ID, :I$PUPIL_ID, :I$USER_ID) AS L51
        INTO :SUBJECT_ID, :SUBJECT_NAME
    DO
    BEGIN
        P_SUBJECT_ID = NULL;
        INCLUDING_TYPE_ID = NULL;
        IS_BASE = 0;
        IS_PLAN = 0;
        SORT_ORDER = NULL;
        MARK = NULL;
        MARK_YEAR = NULL;
        MARK_FIN = NULL;
        MARK_GIA = NULL;
        FOR
            SELECT DISTINCT LP400.PARENT_ID, IIF(PS2.FIELD_ID = 13303, 1, 0) IS_BASE
            FROM LINKS LP256
            JOIN LINKS LP54 ON LP54.OBJ_ID = LP256.PARENT_ID AND LP54.PARENT_TYPE_ID = 54 AND LP54.DATE_DEL IS NULL
            JOIN LINKS LP400 ON LP400.OBJ_ID = LP54.PARENT_ID AND LP400.PARENT_TYPE_ID = 400 AND LP400.DATE_DEL IS NULL
            JOIN PLAN_SUBJECTS PS ON PS.DATE_DEL IS NULL AND PS.PLAN_ID = LP400.PARENT_ID AND PS.ROW_TYPE = 10 AND PS.SUBJECT_ID = :SUBJECT_ID
            JOIN PLAN_SUBJECTS PS2 ON PS2.OBJ_ID = PS.PARENT_ID
            WHERE LP256.OBJ_ID = :I$PUPIL_ID AND LP256.PARENT_TYPE_ID = 256 AND LP256.DATE_DEL IS NULL
            INTO :V$PLAN_ID, :IS_BASE
        DO
        BEGIN
            IS_PLAN = 1;

            V$HOURS_TOTAL = 0;
            SELECT SUM(COALESCE(PL.LOAD_HOURS_S1, 0) + COALESCE(PL.LOAD_HOURS_S2, 0))
            FROM PLAN_SUBJECTS PS
            JOIN PLAN_LOADS PL ON PL.DATE_DEL IS NULL AND PL.SUBJECT_ID = PS.OBJ_ID
            WHERE PS.DATE_DEL IS NULL AND PS.PLAN_ID = :V$PLAN_ID AND PS.SUBJECT_ID = :SUBJECT_ID
            INTO :V$HOURS_TOTAL;

            IF (V$HOURS_TOTAL >= 64) THEN
            BEGIN
                IS_BASE = 1;
            END
            ELSE IF (V$HOURS_TOTAL = 0) THEN
            BEGIN
                IS_BASE = 0;
            END
        END

        SELECT FIRST 1 L229.OBJ_ID, V1852.LISTVAL_ID, V1870.VAL, V2349.VAL, V2350.VAL, V2351.VAL, V1854.VAL, V2880.VAL
        FROM LINKS L292
        JOIN VALI V2354 ON V2354.OBJ_ID = L292.OBJ_ID AND V2354.PARAM_ID = 2354 AND V2354.IS_DEL = 0 AND V2354.VAL = :I$YEAR
        JOIN LINKS L229 ON L229.PARENT_ID = L292.OBJ_ID AND L229.OBJ_TYPE_ID = 229 AND L229.DATE_DEL IS NULL
        JOIN VALL V1852 ON V1852.OBJ_ID = L229.OBJ_ID AND V1852.PARAM_ID = 1852 AND V1852.IS_DEL = 0
        JOIN VALR V1853 ON V1853.OBJ_ID = L229.OBJ_ID AND V1853.PARAM_ID = 1853 AND V1853.IS_DEL = 0 AND V1853.VAL = :SUBJECT_ID
        LEFT JOIN VALI V1854 ON V1854.OBJ_ID = L229.OBJ_ID AND V1854.PARAM_ID = 1854 AND V1854.IS_DEL = 0
        LEFT JOIN VALS V1870 ON V1870.OBJ_ID = L229.OBJ_ID AND V1870.PARAM_ID = 1870 AND V1870.IS_DEL = 0
        LEFT JOIN VALS V2349 ON V2349.OBJ_ID = L229.OBJ_ID AND V2349.PARAM_ID = 2349 AND V2349.IS_DEL = 0
        LEFT JOIN VALS V2350 ON V2350.OBJ_ID = L229.OBJ_ID AND V2350.PARAM_ID = 2350 AND V2350.IS_DEL = 0
        LEFT JOIN VALS V2351 ON V2351.OBJ_ID = L229.OBJ_ID AND V2351.PARAM_ID = 2351 AND V2351.IS_DEL = 0
        LEFT JOIN VALS V2880 ON V2880.OBJ_ID = L229.OBJ_ID AND V2880.PARAM_ID = 2880 AND V2880.IS_DEL = 0
        WHERE L292.PARENT_ID = :I$PUPIL_ID AND L292.OBJ_TYPE_ID = 292 AND L292.DATE_DEL IS NULL
        ORDER BY L229.OBJ_ID DESC
        INTO :P_SUBJECT_ID, :INCLUDING_TYPE_ID, :MARK, :MARK_YEAR, :MARK_FIN, :MARK_GIA, :SORT_ORDER, :SUBJECT_LOAD;

        -- временно для конвертации данных
        IF (P_SUBJECT_ID IS NULL) THEN
        BEGIN
            SELECT FIRST 1 L229.OBJ_ID, V1852.LISTVAL_ID, V1870.VAL, V2349.VAL, V2350.VAL, V2351.VAL, V1854.VAL, V2880.VAL
            FROM LINKS L229
            JOIN VALL V1852 ON V1852.OBJ_ID = L229.OBJ_ID AND V1852.PARAM_ID = 1852 AND V1852.IS_DEL = 0
            JOIN VALR V1853 ON V1853.OBJ_ID = L229.OBJ_ID AND V1853.PARAM_ID = 1853 AND V1853.IS_DEL = 0 AND V1853.VAL = :SUBJECT_ID
            LEFT JOIN VALI V1854 ON V1854.OBJ_ID = L229.OBJ_ID AND V1854.PARAM_ID = 1854 AND V1854.IS_DEL = 0
            LEFT JOIN VALS V1870 ON V1870.OBJ_ID = L229.OBJ_ID AND V1870.PARAM_ID = 1870 AND V1870.IS_DEL = 0
            LEFT JOIN VALS V2349 ON V2349.OBJ_ID = L229.OBJ_ID AND V2349.PARAM_ID = 2349 AND V2349.IS_DEL = 0
            LEFT JOIN VALS V2350 ON V2350.OBJ_ID = L229.OBJ_ID AND V2350.PARAM_ID = 2350 AND V2350.IS_DEL = 0
            LEFT JOIN VALS V2351 ON V2351.OBJ_ID = L229.OBJ_ID AND V2351.PARAM_ID = 2351 AND V2351.IS_DEL = 0
            LEFT JOIN VALS V2880 ON V2880.OBJ_ID = L229.OBJ_ID AND V2880.PARAM_ID = 2880 AND V2880.IS_DEL = 0
            WHERE L229.PARENT_ID = :I$PUPIL_ID AND L229.OBJ_TYPE_ID = 229 AND L229.DATE_DEL IS NULL
            ORDER BY L229.OBJ_ID DESC
            INTO :P_SUBJECT_ID, :INCLUDING_TYPE_ID, :MARK, :MARK_YEAR, :MARK_FIN, :MARK_GIA, :SORT_ORDER, :SUBJECT_LOAD;
        END

        -- Получаем последнюю итоговую отметку
        IF (MARK IS NULL) THEN
        BEGIN
            Y = EXTRACT(YEAR FROM CURRENT_DATE);
            IF (EXTRACT(MONTH FROM CURRENT_DATE) < 9) THEN Y = Y - 1;

            SELECT FIRST 1 LV.LISTVAL_ID
            FROM LISTVALS LV
            WHERE LV.LIST_ID = 29 AND LV.COST = :Y
            INTO :YEAR_ID;

            SELECT FIRST 1 (SELECT VAL FROM RES_GET(LV3.RES_ID, :V$LANG_CODE))
            FROM VALM VM
            JOIN LISTVALS LV1 ON LV1.LISTVAL_ID = VM.YEAR_ID
            JOIN LISTVALS LV3 ON LV3.LISTVAL_ID = VM.MARKVAL_ID
            WHERE VM.PUPIL_ID = :I$PUPIL_ID AND VM.SUBJECT_ID = :SUBJECT_ID AND VM.YEAR_ID = :YEAR_ID AND VM.MARKTYPE_ID = 3013 AND VM.IS_DEL = 0
            ORDER BY LV1.COST DESC
            INTO :MARK;
        END

        -- Если запросили уровень среднего образования, показываем рекомендуемую среднюю отметку за 10 и 11 классы
        SELECT FIRST 1 V43.LISTVAL_ID
        FROM VALL V43
        WHERE V43.OBJ_ID = :I$STAGE_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0
        INTO :V$STAGE_CODE;

        REC_MARK = NULL;
        IF(V$STAGE_CODE IN (27, 29)) THEN
        BEGIN

            SELECT SUM(LV3.COST) / 10, COUNT(*)
            FROM VALM VM
            JOIN LISTVALS LV1 ON LV1.LISTVAL_ID = VM.YEAR_ID AND (LV1.COST = :I$YEAR - 1 OR LV1.COST = :I$YEAR - 2)
            JOIN LISTVALS LV3 ON LV3.LISTVAL_ID = VM.MARKVAL_ID
            WHERE VM.IS_DEL = 0 AND VM.PUPIL_ID = :I$PUPIL_ID AND VM.SUBJECT_ID = :SUBJECT_ID AND VM.MARKTYPE_ID IN (3009, 3010, 3011)
                AND VM.MARKVAL_ID IN (3014, 3015, 3016, 3017, 3018)
            INTO :REC_MARK, :V$N_MARKS;

            IF(V$N_MARKS > 0) THEN REC_MARK = REC_MARK / V$N_MARKS;

        END

        -- Для 9 и 11 классов тема из разных полей
        PROJECT_THEME = NULL;
        SELECT V FROM VAL_GET(:I$PUPIL_ID, IIF(:V$STAGE_CODE = 27, 229, 3116)) WHERE IS_EXISTS = 1 AND :SUBJECT_ID = 34651 INTO :PROJECT_THEME;
        IF(PROJECT_THEME IS NULL) THEN SELECT V FROM VAL_GET(:I$PUPIL_ID, 3162) WHERE IS_EXISTS = 1 AND :SUBJECT_ID = 34651 INTO :PROJECT_THEME;

        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CERTIFICATE_PUPIL_LOAD_SUBJ_SET (
    I$YEAR BIGINT,
    I$PUPIL_ID BIGINT,
    I$USER_ID BIGINT,
    I$P_SUBJECT_ID BIGINT,
    I$INCLUDING_TYPE_ID BIGINT,
    I$SUBJECT_ID BIGINT,
    I$MARK VARCHAR(255),
    I$SORT_ORDER INTEGER,
    I$MARK_PARAM_ID BIGINT = 1870,
    I$SUBJECT_LOAD VARCHAR(100) = '')
RETURNS (
    P_SUBJECT_ID BIGINT)
AS
declare variable V$BLOB_ID bigint;
declare variable V$STORAGE_ID bigint;
BEGIN
    SELECT FIRST 1
           L292.OBJ_ID
    FROM LINKS L292

    JOIN VALI V2354
    ON V2354.OBJ_ID = L292.OBJ_ID
    AND V2354.PARAM_ID = 2354
    AND V2354.IS_DEL = 0
    AND V2354.VAL = :I$YEAR

    WHERE L292.PARENT_ID = :I$PUPIL_ID
    AND L292.OBJ_TYPE_ID = 292
    AND L292.DATE_DEL IS NULL

    INTO :V$STORAGE_ID;

    IF (V$STORAGE_ID IS NULL) THEN
    BEGIN
        FOR
            SELECT OBJ_ID
            FROM OBJECT_ADD(:I$PUPIL_ID, 292)
            INTO :V$STORAGE_ID
        DO
        BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD(2354, :V$STORAGE_ID, :I$YEAR)
            INTO :V$BLOB_ID;
        END
    END

    P_SUBJECT_ID = I$P_SUBJECT_ID;
    IF (P_SUBJECT_ID IS NULL) THEN
    BEGIN
        SELECT FIRST 1
               L229.OBJ_ID
        FROM LINKS L229

        JOIN VALR V1853
        ON V1853.OBJ_ID = L229.OBJ_ID
        AND V1853.PARAM_ID = 1853
        AND V1853.IS_DEL = 0
        AND V1853.VAL = :I$SUBJECT_ID

        WHERE L229.PARENT_ID = :V$STORAGE_ID
        AND L229.OBJ_TYPE_ID = 229
        AND L229.DATE_DEL IS NULL

        INTO :P_SUBJECT_ID;
    END
    IF (P_SUBJECT_ID IS NULL) THEN
    BEGIN
        SELECT OBJ_ID
        FROM OBJECT_ADD(:V$STORAGE_ID, 229, NULL, NULL, :I$USER_ID)
        INTO :P_SUBJECT_ID;

        IF (P_SUBJECT_ID IS NOT NULL) THEN
        BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD(1853, :P_SUBJECT_ID, :I$SUBJECT_ID, :I$USER_ID)
            INTO :V$BLOB_ID;
        END
    END
    IF (P_SUBJECT_ID IS NOT NULL) THEN
    BEGIN
        SELECT BLOB_ID
        FROM VAL_ADD(1852, :P_SUBJECT_ID, :I$INCLUDING_TYPE_ID, :I$USER_ID)
        INTO :V$BLOB_ID;

        SELECT BLOB_ID
        FROM VAL_ADD(1854, :P_SUBJECT_ID, :I$SORT_ORDER, :I$USER_ID)
        INTO :V$BLOB_ID;

        SELECT BLOB_ID
        FROM VAL_ADD(2880, :P_SUBJECT_ID, :I$SUBJECT_LOAD, :I$USER_ID)
        INTO :V$BLOB_ID;

        SELECT BLOB_ID
        FROM VAL_ADD(:I$MARK_PARAM_ID, :P_SUBJECT_ID, :I$MARK, :I$USER_ID)
        INTO :V$BLOB_ID;

        IF (:I$MARK IS NULL) THEN
        BEGIN
            UPDATE VALS
            SET IS_DEL = 1
            WHERE PARAM_ID = :I$MARK_PARAM_ID
              AND OBJ_ID = :P_SUBJECT_ID;
        END
        ELSE
        BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD(:I$MARK_PARAM_ID, :P_SUBJECT_ID, :I$MARK, :I$USER_ID)
            INTO :V$BLOB_ID;
        END
    END
    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CERTIFICATE_PUPIL_SUBJECT_LIST (
    I$YEAR SMALLINT,
    I$STAGE_ID BIGINT,
    I$CLASS_ID BIGINT,
    I$PUPIL_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    P_SUBJECT_ID BIGINT,
    P_SUBJECT_NAME VARCHAR(1000),
    SUBJECT_ID BIGINT,
    SUBJECT_NAME VARCHAR(1000))
AS
BEGIN
    FOR
        SELECT DISTINCT L51.SUBJECT_ID, L51.SUBJECT_NAME, L51.C_SUBJECT_NAME
        FROM CERTIFICATE_CLASS_SUBJECT_LIST(:I$STAGE_ID, :I$CLASS_ID, :I$USER_ID) L51
        ORDER BY L51.SUBJECT_NAME
        INTO :SUBJECT_ID, :SUBJECT_NAME, :P_SUBJECT_NAME
    DO
    BEGIN
        P_SUBJECT_ID = NULL;
        FOR
            --для конвертации, в следующем году удалить при случае
            SELECT FIRST 1 L227.OBJ_ID
            FROM VALR V1845
            JOIN LINKS L227 ON L227.OBJ_ID = V1845.OBJ_ID AND L227.PARENT_ID = :I$PUPIL_ID
            WHERE V1845.PARAM_ID = 1845 AND V1845.VAL = :SUBJECT_ID

            UNION ALL
            --

            SELECT FIRST 1 V1845.OBJ_ID
            FROM VALR V1845
            JOIN LINKS LP292 ON LP292.OBJ_ID = V1845.OBJ_ID AND LP292.PARENT_TYPE_ID = 292 AND LP292.DATE_DEL IS NULL
            JOIN VALI V2354 ON V2354.OBJ_ID = LP292.PARENT_ID AND V2354.PARAM_ID = 2354 AND V2354.IS_DEL = 0 AND V2354.VAL = :I$YEAR
            JOIN LINKS L292 ON L292.OBJ_ID = LP292.PARENT_ID AND L292.PARENT_ID = :I$PUPIL_ID AND L292.DATE_DEL IS NULL
            WHERE V1845.PARAM_ID = 1845 AND V1845.VAL = :SUBJECT_ID
            INTO :P_SUBJECT_ID
        DO
        BEGIN
            SELECT V
            FROM VAL_GET(:P_SUBJECT_ID, 1846, 0, :I$USER_ID)
            INTO :P_SUBJECT_NAME;
        END

        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CERTIFICATE_PUPIL_SUBJECT_SET (
    I$YEAR SMALLINT,
    I$PUPIL_ID BIGINT,
    I$P_SUBJECT_ID BIGINT,
    I$SUBJECT_ID BIGINT,
    I$USER_ID BIGINT,
    I$P_SUBJECT_NAME VARCHAR(1000))
RETURNS (
    P_SUBJECT_ID BIGINT)
AS
declare variable V$BLOB_ID bigint;
declare variable V$STORAGE_ID bigint;
BEGIN
    SELECT FIRST 1
           L292.OBJ_ID
    FROM LINKS L292

    JOIN VALI V2354
    ON V2354.OBJ_ID = L292.OBJ_ID
    AND V2354.PARAM_ID = 2354
    AND V2354.IS_DEL = 0
    AND V2354.VAL = :I$YEAR

    WHERE L292.PARENT_ID = :I$PUPIL_ID
    AND L292.OBJ_TYPE_ID = 292
    AND L292.DATE_DEL IS NULL

    INTO :V$STORAGE_ID;

    IF (V$STORAGE_ID IS NULL) THEN
    BEGIN
        FOR
            SELECT OBJ_ID
            FROM OBJECT_ADD(:I$PUPIL_ID, 292)
            INTO :V$STORAGE_ID
        DO
        BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD(2354, :V$STORAGE_ID, :I$YEAR)
            INTO :V$BLOB_ID;
        END
    END

    P_SUBJECT_ID = I$P_SUBJECT_ID;
    IF (P_SUBJECT_ID IS NULL) THEN
    BEGIN
        SELECT OBJ_ID
        FROM OBJECT_ADD(:V$STORAGE_ID, 227, NULL, NULL, :I$USER_ID)
        INTO :P_SUBJECT_ID;

        IF (P_SUBJECT_ID IS NOT NULL) THEN
        BEGIN   
            SELECT BLOB_ID
            FROM VAL_ADD(1845, :P_SUBJECT_ID, :I$SUBJECT_ID, :I$USER_ID)
            INTO :V$BLOB_ID;
        END
    END

    IF (P_SUBJECT_ID IS NOT NULL) THEN
    BEGIN
        SELECT BLOB_ID
        FROM VAL_ADD(1846, :P_SUBJECT_ID, TRIM(:I$P_SUBJECT_NAME), :I$USER_ID, IIF(TRIM(:I$P_SUBJECT_NAME) IS NULL, 1, 0))
        INTO :V$BLOB_ID;
    END
    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CERTIFICATE_PUPIL_TEMPLATES_GET (
    I$YEAR BIGINT,
    I$STAGE_ID BIGINT,
    I$PUPIL_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    NUM BIGINT,
    PRINT_TEMPLATE_ID BIGINT,
    TEMPLATE_DATA VARCHAR(4000),
    TEMPLATE_NAME VARCHAR(1000),
    TEMPLATE_TYPE_ID BIGINT,
    TEMPLATE_ID BIGINT)
AS
declare variable V$CERTIFICATE_TYPE_ID bigint;
declare variable V$TMPL1 varchar(255);
declare variable V$TMPL2 varchar(255);
declare variable V$TMPL3 varchar(255);
declare variable V$TMPL4 varchar(255);
declare variable V$TMPL5 varchar(255);
BEGIN
    FOR
        SELECT TMPL1,
               TMPL2,
               TMPL3,
               TMPL4,
               TMPL5,
               CERTIFICATE_TYPE_ID
        FROM CERTIFICATE_PUPIL_INFO_GET(:I$YEAR, :I$STAGE_ID, :I$PUPIL_ID, :I$USER_ID)
        INTO :V$TMPL1,
             :V$TMPL2,
             :V$TMPL3,
             :V$TMPL4,
             :V$TMPL5,
             :V$CERTIFICATE_TYPE_ID
    DO
    BEGIN
        FOR
            SELECT 1,
                   PRINT_TEMPLATE_ID,
                   TEMPLATE_DATA,
                   TEMPLATE_NAME,
                   TEMPLATE_TYPE_ID,
                   TEMPLATE_ID
            FROM CERTIFICATE_TEMPLATES_LIST(:I$STAGE_ID, :I$USER_ID)
            WHERE (
                ((:V$CERTIFICATE_TYPE_ID = 5377) AND (TEMPLATE_TYPE_ID = 5369)) OR
                ((:V$CERTIFICATE_TYPE_ID = 5377) AND (TEMPLATE_TYPE_ID = 13262)) OR
                ((:V$CERTIFICATE_TYPE_ID = 5379) AND (TEMPLATE_TYPE_ID = 5373)) OR
                ((:V$CERTIFICATE_TYPE_ID = 5379) AND (TEMPLATE_TYPE_ID = 13264)) OR
                ((:V$CERTIFICATE_TYPE_ID = 12766) AND (TEMPLATE_TYPE_ID = 12768))
            )
            AND TEMPLATE_NAME = :V$TMPL1

            UNION ALL

            SELECT 1,
                   PRINT_TEMPLATE_ID,
                   TEMPLATE_DATA,
                   TEMPLATE_NAME,
                   TEMPLATE_TYPE_ID,
                   TEMPLATE_ID
            FROM CERTIFICATE_TEMPLATES_LIST(:I$STAGE_ID, :I$USER_ID)
            WHERE (
                ((:V$CERTIFICATE_TYPE_ID = 5378) AND (TEMPLATE_TYPE_ID = 5370)) OR
                ((:V$CERTIFICATE_TYPE_ID = 5378) AND (TEMPLATE_TYPE_ID = 13263)) OR
                ((:V$CERTIFICATE_TYPE_ID = 5380) AND (TEMPLATE_TYPE_ID = 5374)) OR
                ((:V$CERTIFICATE_TYPE_ID = 5380) AND (TEMPLATE_TYPE_ID = 13265)) OR
                ((:V$CERTIFICATE_TYPE_ID = 12767) AND (TEMPLATE_TYPE_ID = 12769))
            )
            AND TEMPLATE_NAME = :V$TMPL2

            UNION ALL

            SELECT 2,
                   PRINT_TEMPLATE_ID,
                   TEMPLATE_DATA,
                   TEMPLATE_NAME,
                   TEMPLATE_TYPE_ID,
                   TEMPLATE_ID
            FROM CERTIFICATE_TEMPLATES_LIST(:I$STAGE_ID, :I$USER_ID)
            WHERE (
                ((:V$CERTIFICATE_TYPE_ID IN (5377, 5378)) AND (TEMPLATE_TYPE_ID IN (5371, 13305))) OR
                ((:V$CERTIFICATE_TYPE_ID IN (5379, 5380)) AND (TEMPLATE_TYPE_ID IN (5375, 13307))) OR
                ((:V$CERTIFICATE_TYPE_ID IN (12766, 12767)) AND (TEMPLATE_TYPE_ID = 12770))
            )
            AND TEMPLATE_NAME = :V$TMPL3

            UNION ALL

            SELECT 3,
                   PRINT_TEMPLATE_ID,
                   TEMPLATE_DATA,
                   TEMPLATE_NAME,
                   TEMPLATE_TYPE_ID,
                   TEMPLATE_ID
            FROM CERTIFICATE_TEMPLATES_LIST(:I$STAGE_ID, :I$USER_ID)
            WHERE (
                ((:V$CERTIFICATE_TYPE_ID IN (5377, 5378)) AND (TEMPLATE_TYPE_ID IN (5372, 13306))) OR
                ((:V$CERTIFICATE_TYPE_ID IN (5379, 5380)) AND (TEMPLATE_TYPE_ID IN (5376, 13308))) OR
                ((:V$CERTIFICATE_TYPE_ID IN (12766, 12767)) AND (TEMPLATE_TYPE_ID = 12771))
            )
            AND TEMPLATE_NAME = :V$TMPL4

            UNION ALL

            SELECT 4,
                   PRINT_TEMPLATE_ID,
                   TEMPLATE_DATA,
                   TEMPLATE_NAME,
                   TEMPLATE_TYPE_ID,
                   TEMPLATE_ID
            FROM CERTIFICATE_TEMPLATES_LIST(:I$STAGE_ID, :I$USER_ID)
            WHERE (:V$CERTIFICATE_TYPE_ID = 5385) AND (TEMPLATE_TYPE_ID = 5384)
            AND TEMPLATE_NAME = :V$TMPL5

            INTO :NUM,
                 :PRINT_TEMPLATE_ID,
                 :TEMPLATE_DATA,
                 :TEMPLATE_NAME,
                 :TEMPLATE_TYPE_ID,
                 :TEMPLATE_ID
        DO
        BEGIN
            SUSPEND;
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CERTIFICATE_REG_CLASSES_LIST (
    I$YEAR SMALLINT,
    I$STAGE_ID BIGINT,
    I$BLANK_CHECK_FL SMALLINT = 1)
RETURNS (
    OBJ_ID BIGINT,
    OBJ_CAPTION VARCHAR(4000),
    SORT_ORDER DOUBLE PRECISION)
AS
declare variable V$START_DATE date;
declare variable V$END_DATE date;
BEGIN
    V$START_DATE = '01.01.' || I$YEAR;
    V$END_DATE = '31.12.' || I$YEAR;

    FOR
        SELECT DISTINCT CLS.OBJ_ID, CLS.OBJ_CAPTION, CLS.SORT_ORDER
        FROM LINKS L234
        JOIN VALR V1872 ON V1872.OBJ_ID = L234.OBJ_ID AND V1872.PARAM_ID = 1872 AND V1872.IS_DEL = 0
        LEFT JOIN VALR V1877 ON V1877.OBJ_ID = L234.OBJ_ID AND V1877.PARAM_ID = 1877 AND V1877.IS_DEL = 0
        JOIN VALD V1876 ON V1876.OBJ_ID = L234.OBJ_ID AND V1876.PARAM_ID = 1876 AND V1876.IS_DEL = 0 AND V1876.VAL >= :V$START_DATE AND V1876.VAL <= :V$END_DATE
        LEFT JOIN CERTIFICATE_REG_PUPIL_CLASS_GET(V1872.VAL, V1876.VAL) CLS ON 1 = 1
        WHERE L234.PARENT_ID = :I$STAGE_ID AND L234.OBJ_TYPE_ID = 234 AND L234.DATE_DEL IS NULL
          AND ((:I$BLANK_CHECK_FL = 1 AND V1877.VAL IS NOT NULL) OR (:I$BLANK_CHECK_FL <> 1 AND V1877.VAL IS NULL))
        INTO :OBJ_ID, :OBJ_CAPTION, :SORT_ORDER
    DO
    BEGIN
        IF (OBJ_ID IS NOT NULL) THEN
        BEGIN
            SUSPEND;
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CERTIFICATE_REG_CLASS_GET (
    I$YEAR SMALLINT,
    I$CLASS_ID BIGINT,
    I$STAGE_ID BIGINT,
    I$USER_ID BIGINT,
    I$STATUS_FILTER BIGINT = 0)
RETURNS (
    NUMBER VARCHAR(50),
    VID VARCHAR(50),
    SN VARCHAR(50),
    FIO VARCHAR(50),
    DATEBIRTH VARCHAR(20),
    DATEORDER VARCHAR(20),
    NUMBERORDER VARCHAR(20),
    POLUCH VARCHAR(50),
    DATEVID VARCHAR(20),
    STATUS VARCHAR(20),
    DATERECORD VARCHAR(20),
    CLASS_ID BIGINT)
AS
BEGIN
    FOR
        SELECT VAL1,
               VAL2,
               VAL3,
               VAL4,
               VAL5,
               VAL6,
               VAL7,
               VAL8,
               VAL9,
               VAL11,
               VAL12,
               CLASS_ID
        FROM CERTIFICATE_REG_LIST(:I$YEAR, :I$CLASS_ID, :I$STAGE_ID, :I$USER_ID, 1, :I$STATUS_FILTER)
        ORDER BY VAL1
        INTO :NUMBER,
             :VID,
             :SN,
             :FIO,
             :DATEBIRTH,
             :DATEORDER,
             :NUMBERORDER,
             :POLUCH,
             :DATEVID,
             :STATUS,
             :DATERECORD,
             :CLASS_ID
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CERTIFICATE_REG_CLASS_PRIL_GET (
    I$YEAR SMALLINT,
    I$STAGE_ID BIGINT,
    I$CLASS_ID BIGINT,
    I$USER_ID BIGINT,
    I$ATTESTAT_PRINTED SMALLINT = 0)
RETURNS (
    SN VARCHAR(20),
    FIO VARCHAR(255),
    CLASS_NAME VARCHAR(1000),
    SUBJECTSLEFT VARCHAR(1000),
    SUBJECTSRIGHT VARCHAR(1000),
    MARKSLEFT VARCHAR(1000),
    MARKSRIGHT VARCHAR(1000),
    DOPOLSVED VARCHAR(4000),
    FIOSHORT VARCHAR(255),
    DOB VARCHAR(50),
    CTFIO VARCHAR(255))
AS
declare variable V$CURR_S varchar(1200);
declare variable V$CURR_M varchar(40);
declare variable V$OBJ_ID bigint;
declare variable V$PUPIL_ID bigint;
declare variable V$PUPIL_TYPE_ID bigint;
declare variable V$COUNT integer;
declare variable V$CLASS_TYPE_ID bigint;
declare variable V$STAGE_TYPE_ID bigint;
declare variable V$CLASS_ID bigint;
declare variable V$GRADUATE_YEAR smallint;
declare variable V$THEME varchar(1000);
declare variable V$TYPE bigint;
BEGIN
    FOR
        SELECT L.PUPIL_ID, O.TYPE_ID, L.CLASS_ID, L.GRADUATE_YEAR
        FROM CERTIFICATE_REG_LIST(:I$YEAR, :I$CLASS_ID, :I$STAGE_ID, :I$USER_ID) L
        JOIN OBJECTS O ON O.OBJ_ID = L.PUPIL_ID AND O.TYPE_ID IN (10, 126)
        WHERE ((:I$ATTESTAT_PRINTED = 0) OR EXISTS(
            SELECT FIRST 1 1
            FROM VALR VLR
            WHERE VLR.VAL = O.OBJ_ID AND VLR.PARAM_ID = 1872 AND VLR.IS_DEL = 0
        ))

        UNION
        -- ещё не распечатанные текущего года
        SELECT L10.OBJ_ID, L10.OBJ_TYPE_ID, :I$CLASS_ID, :I$YEAR
        FROM LINKS L10
        WHERE L10.PARENT_ID = :I$CLASS_ID AND L10.OBJ_TYPE_ID IN (10, 126) AND L10.DATE_DEL IS NULL AND :I$ATTESTAT_PRINTED = 0 AND :I$YEAR = (SELECT Y2 FROM CURRENT_SCHOOL_YEAR_GET)
        INTO :V$PUPIL_ID, :V$PUPIL_TYPE_ID, :V$CLASS_ID, :V$GRADUATE_YEAR
    DO
    BEGIN
        IF (:I$CLASS_ID IS NULL OR :V$CLASS_TYPE_ID IS NULL) THEN
        BEGIN
            SELECT TYPE_ID
            FROM OBJECTS
            WHERE OBJ_ID = :V$CLASS_ID
            INTO :V$CLASS_TYPE_ID;

            CTFIO = '/____________________/';
            SELECT FORM_MASTER_FIO
            FROM CERTIFICATE_DIR_FORM_MASTER_GET(:I$STAGE_ID, :V$CLASS_ID, :I$USER_ID)
            INTO :CTFIO;
        END

        -- Берем первый бланк аттестата, в порядке валидности
        SELECT FIRST 1 V1872.OBJ_ID
        FROM VALR V1872
        -- Контейнер выдачи аттестата -> год окончания
        JOIN VALR V2355 ON V2355.OBJ_ID = V1872.OBJ_ID AND V2355.PARAM_ID = 2355 AND V2355.IS_DEL = 0
        JOIN VALI V2354 ON V2354.OBJ_ID = V2355.VAL AND V2354.PARAM_ID = 2354 AND V2354.IS_DEL = 0 AND V2354.VAL = :I$YEAR
        -- Бланк из данной записи
        JOIN VALR V1877 ON V1877.OBJ_ID = V1872.OBJ_ID AND V1877.PARAM_ID = 1877 AND V1877.IS_DEL = 0
        LEFT JOIN VALL V1880 ON V1880.OBJ_ID = V1877.VAL AND V1880.PARAM_ID = 1880 AND V1880.IS_DEL = 0
        WHERE V1872.VAL = :V$PUPIL_ID AND V1872.PARAM_ID = 1872 AND V1872.IS_DEL = 0
        ORDER BY V1880.LISTVAL_ID, V1872.OBJ_ID
        INTO :V$OBJ_ID;

        SN = '0000000000000';
        SELECT S || N
        FROM CERTIFICATE_SN_GET(:V$OBJ_ID, :I$USER_ID)
        INTO :SN;

        IF (V$PUPIL_TYPE_ID = 10) THEN
        BEGIN
            SELECT F.V ||' '|| I.V ||' '|| O.V
            FROM VAL_GET(:V$PUPIL_ID, 55, 0, :I$USER_ID) F
            LEFT JOIN VAL_GET(:V$PUPIL_ID, 56, 0, :I$USER_ID) I ON 1=1
            LEFT JOIN VAL_GET(:V$PUPIL_ID, 57, 0, :I$USER_ID) O ON 1=1
            INTO :FIO;

            SELECT SUBSTRING(I.V FROM 1 FOR 1)||'. '||F.V
            FROM VAL_GET(:V$PUPIL_ID, 55, 0, :I$USER_ID) F
            LEFT JOIN VAL_GET(:V$PUPIL_ID, 56, 0, :I$USER_ID) I ON 1=1
            LEFT JOIN VAL_GET(:V$PUPIL_ID, 57, 0, :I$USER_ID) O ON 1=1
            INTO :FIOSHORT;

            SELECT V FROM VAL_GET(:V$PUPIL_ID, 89, 0, :I$USER_ID)
            INTO :DOB;
        END
        ELSE IF (V$PUPIL_TYPE_ID = 126) THEN
        BEGIN
            SELECT F.V ||' '|| I.V ||' '|| O.V
            FROM VAL_GET(:V$PUPIL_ID, 827, 0, :I$USER_ID) F
            LEFT JOIN VAL_GET(:V$PUPIL_ID, 828, 0, :I$USER_ID) I ON 1=1
            LEFT JOIN VAL_GET(:V$PUPIL_ID, 829, 0, :I$USER_ID) O ON 1=1
            INTO :FIO;

            SELECT SUBSTRING(I.V FROM 1 FOR 1)||'. '||F.V
            FROM VAL_GET(:V$PUPIL_ID, 827, 0, :I$USER_ID) F
            LEFT JOIN VAL_GET(:V$PUPIL_ID, 828, 0, :I$USER_ID) I ON 1=1
            LEFT JOIN VAL_GET(:V$PUPIL_ID, 829, 0, :I$USER_ID) O ON 1=1
            INTO :FIOSHORT;

            SELECT V FROM VAL_GET(:V$PUPIL_ID, 830, 0, :I$USER_ID)
            INTO :DOB;
        END

        IF (V$CLASS_TYPE_ID IN (81, 82, 83)) THEN
        BEGIN   
            -- Ищем последнюю запись зачисления в класс
            CLASS_NAME = NULL;
            SELECT FIRST 1 M.NAME_IN
            FROM PERSON_MOVEMENTS M
            JOIN OBJECTS O ON O.OBJ_ID = M.GROUP_ID AND O.TYPE_ID IN (9, 125, 187)
            WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :V$PUPIL_ID
            ORDER BY M.OBJ_ID DESC
            INTO :CLASS_NAME;

            IF (CLASS_NAME IS NULL) THEN
            BEGIN
                SELECT I
                FROM VAL_GET(:I$STAGE_ID, 43)
                INTO :V$STAGE_TYPE_ID;

                IF (V$STAGE_TYPE_ID = 26) THEN
                BEGIN
                    CLASS_NAME = '9';
                END
                ELSE IF (V$STAGE_TYPE_ID = 27) THEN
                BEGIN
                    CLASS_NAME = '11';
                END
            END
        END
        ELSE
        BEGIN
            SELECT CLASS_NAME FROM CERTIFICATE_CLASS_INFO_GET(:V$GRADUATE_YEAR, :V$CLASS_ID, :I$STAGE_ID, :I$USER_ID)
            INTO :CLASS_NAME;
        END
        
        SUBJECTSLEFT = '';
        MARKSLEFT = '';

        SUBJECTSRIGHT = '';
        MARKSRIGHT = '';

        V$COUNT = 0;
        FOR
            SELECT SUBJECT_NAME,
            CASE MARK
              WHEN '5' THEN '5 (отлично)'
              WHEN '4' THEN '4 (хорошо)'
              WHEN '3' THEN '3 (удовл.)'
              WHEN '2' THEN '2 (неудовл.)'
              ELSE IIF(MARK IS NULL,'',MARK)
            END
            FROM CERT_PUPIL_LOAD_SUBJECTS(:V$GRADUATE_YEAR, :I$STAGE_ID, :V$CLASS_ID, :V$PUPIL_ID, :I$USER_ID)
            WHERE INCLUDING_TYPE_ID = 5381 AND SUBJECT_ID <> 34651
            ORDER BY INCLUDING_TYPE_ID, SORT_ORDER, SUBJECT_NAME
            INTO :V$CURR_S, :V$CURR_M
        DO
        BEGIN
            IF ( V$COUNT < 21 ) THEN
            BEGIN
                SUBJECTSLEFT = SUBJECTSLEFT || V$CURR_S || ASCII_CHAR(13)||ASCII_CHAR(10);
                MARKSLEFT = MARKSLEFT || V$CURR_M || ASCII_CHAR(13)||ASCII_CHAR(10);
                V$COUNT = V$COUNT + 1;
            END
            ELSE
            BEGIN
                SUBJECTSRIGHT = SUBJECTSRIGHT || V$CURR_S || ASCII_CHAR(13)||ASCII_CHAR(10);
                MARKSRIGHT = MARKSRIGHT || V$CURR_M || ASCII_CHAR(13)||ASCII_CHAR(10);
                V$COUNT = V$COUNT + 1;
            END

            IF (V$COUNT = 42) THEN BREAK;
        END
    
        IF (CHAR_LENGTH(SUBJECTSLEFT) > 0) THEN
        BEGIN
            SUBJECTSLEFT = SUBSTRING (SUBJECTSLEFT FROM 1 FOR (CHAR_LENGTH(SUBJECTSLEFT) - 2) );
        END
        ELSE
        BEGIN
            SUBJECTSLEFT = NULL;
        END

        IF (CHAR_LENGTH(MARKSLEFT) > 0) THEN
        BEGIN
           MARKSLEFT = SUBSTRING (MARKSLEFT FROM 1 FOR (CHAR_LENGTH(MARKSLEFT) - 2) );
        END
        ELSE
        BEGIN
            MARKSLEFT = NULL;
        END

        IF (CHAR_LENGTH(SUBJECTSRIGHT) > 0) THEN
        BEGIN
            SUBJECTSRIGHT = SUBSTRING (SUBJECTSRIGHT FROM 1 FOR (CHAR_LENGTH(SUBJECTSRIGHT) - 2) );
        END
        ELSE
        BEGIN
            SUBJECTSRIGHT = NULL;
        END

        IF (CHAR_LENGTH(MARKSRIGHT) > 0) THEN
        BEGIN
            MARKSRIGHT = SUBSTRING (MARKSRIGHT FROM 1 FOR (CHAR_LENGTH(MARKSRIGHT) - 2) );
        END
        ELSE
        BEGIN
            MARKSRIGHT = NULL;
        END

        DOPOLSVED = '';
        FOR
            SELECT SUBJECT_NAME, INCLUDING_TYPE_ID, COALESCE(PROJECT_THEME, ''),
            CASE MARK
              WHEN '5' THEN '5 (отлично)'
              WHEN '4' THEN '4 (хорошо)'
              WHEN '3' THEN '3 (удовл.)'
              WHEN '2' THEN '2 (неудовл.)'
              ELSE IIF(MARK IS NULL,'',MARK)
            END
            FROM CERT_PUPIL_LOAD_SUBJECTS(:V$GRADUATE_YEAR, :I$STAGE_ID, :V$CLASS_ID, :V$PUPIL_ID, :I$USER_ID)
            WHERE INCLUDING_TYPE_ID = 5382 OR (INCLUDING_TYPE_ID = 5381 AND SUBJECT_ID = 34651)
            ORDER BY INCLUDING_TYPE_ID, SORT_ORDER, SUBJECT_NAME
            INTO :V$CURR_S, :V$TYPE, :V$THEME, :V$CURR_M
        DO
        BEGIN
            IF(V$TYPE = 5381) THEN V$CURR_S = V$CURR_S || ', отметка ' || V$CURR_M;
            IF(V$THEME <> '') THEN V$CURR_S = V$CURR_S || ', тема "' || V$THEME || '"';

            DOPOLSVED = DOPOLSVED || V$CURR_S || ', ';
        END
    
        IF (CHAR_LENGTH(DOPOLSVED) > 0) THEN
        BEGIN
            DOPOLSVED = SUBSTRING (DOPOLSVED FROM 1 FOR (CHAR_LENGTH(DOPOLSVED) - 2) );
        END
        ELSE
        BEGIN
            DOPOLSVED = NULL;
        END

        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CERTIFICATE_REG_DUPL_INFO_GET (
    I$OBJ_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    ORI_UNUMBER VARCHAR(10),
    ORI_DATEVID VARCHAR(20),
    ORI_KSNB VARCHAR(20),
    DUP_NUMORDER VARCHAR(20),
    DUP_DATEORDER VARCHAR(20),
    DUP_DATEVID VARCHAR(20),
    DUP_KSNB VARCHAR(50),
    DUP_OWNER VARCHAR(50),
    DUP_RECEIVER VARCHAR(50))
AS
declare variable V$ORI_ID bigint;
declare variable V$PUPIL_ID bigint;
declare variable V$PUPIL_INFO_ID bigint;
declare variable V$ID226 bigint;
declare variable V$ID11 bigint;
declare variable V$DOCTYPE bigint;
BEGIN
  --ученик, тип документа #234
  SELECT V1872.VAL, V50.LISTVAL_ID
  FROM VALR V1872
    LEFT JOIN VALR V2356 ON V2356.OBJ_ID = V1872.OBJ_ID AND V2356.PARAM_ID = 2356 AND V2356.IS_DEL = 0
    JOIN VALL V50 ON V50.OBJ_ID = V2356.VAL AND V50.PARAM_ID = 50 AND V50.IS_DEL = 0
  WHERE V1872.OBJ_ID = :I$OBJ_ID AND V1872.PARAM_ID = 1872 AND V1872.IS_DEL = 0
  INTO :V$PUPIL_ID, :V$DOCTYPE;

  FOR
    SELECT FIRST(1) L230.OBJ_ID FROM LINKS L292
      JOIN LINKS L230 ON L230.PARENT_ID = L292.OBJ_ID AND L230.OBJ_TYPE_ID = 230 AND L230.DATE_DEL IS NULL
    WHERE L292.PARENT_ID = :V$PUPIL_ID AND L292.OBJ_TYPE_ID = 292 AND L292.DATE_DEL IS NULL
    ORDER BY L292.OBJ_ID DESC
    INTO :V$PUPIL_INFO_ID
  DO
  BEGIN
    FOR
      SELECT VAL FROM VALR
      WHERE OBJ_ID = :V$PUPIL_INFO_ID AND PARAM_ID = 1855 AND IS_DEL = 0  --Приказ #226
      INTO :V$ID226
    DO
    BEGIN
      --номер приказа
      SELECT V FROM VAL_GET(:V$ID226, 1842, 0, :I$USER_ID)
      INTO :DUP_NUMORDER;

      --дата приказа
      SELECT V FROM VAL_GET(:V$ID226, 1843, 0, :I$USER_ID)
      INTO :DUP_DATEORDER;
    END
  END

  --дата выдачи дупликата
  SELECT V FROM VAL_GET(:I$OBJ_ID, 1876, 0, :I$USER_ID)
  INTO :DUP_DATEVID;

  FOR
    SELECT FIRST(1) V1872.OBJ_ID FROM VALR V1872 --ученик
      JOIN VALR V2356 ON V2356.OBJ_ID = V1872.OBJ_ID AND V2356.PARAM_ID = 2356 AND V2356.IS_DEL = 0  --документ
      JOIN VALL V50 ON V50.OBJ_ID = V2356.VAL AND V50.PARAM_ID = 50 AND V50.IS_DEL = 0 AND V50.LISTVAL_ID = :V$DOCTYPE --тип документа
      JOIN VALR V1877 ON V1877.OBJ_ID = V1872.OBJ_ID AND V1877.PARAM_ID = 1877 AND V1877.IS_DEL = 0  --бланк
      JOIN LINKS L236 ON L236.OBJ_ID = V1877.VAL AND L236.DATE_DEL IS NULL
      JOIN VALL V1880 ON V1880.OBJ_ID = L236.OBJ_ID AND V1880.PARAM_ID = 1880 AND V1880.IS_DEL = 0 AND V1880.LISTVAL_ID IN (5438, 5439) --первичный, взамен испорченого
    WHERE V1872.VAL = :V$PUPIL_ID AND V1872.PARAM_ID = 1872 AND V1872.IS_DEL = 0
    ORDER BY V1872.OBJ_ID
    INTO :V$ORI_ID
  DO
  BEGIN
    SELECT V FROM VAL_GET(:V$ORI_ID, 1871, 0, :I$USER_ID) --Номер учетной записи
    INTO :ORI_UNUMBER;

    SELECT S || N FROM CERTIFICATE_SN_GET(:V$ORI_ID, :I$USER_ID)
    INTO :ORI_KSNB;

    SELECT V FROM VAL_GET(:V$ORI_ID, 1876, 0, :I$USER_ID) --Дата выдачи
    INTO :ORI_DATEVID;
  END

  IF (V$ORI_ID IS NULL) THEN
  BEGIN
    SELECT FIRST(1) L11.OBJ_ID, (SELECT V FROM VAL_GET(L11.OBJ_ID, 566, 0, :I$USER_ID))
    FROM LINKS L234
      LEFT JOIN VALR V1877 ON V1877.OBJ_ID = L234.OBJ_ID AND V1877.PARAM_ID = 1877 AND V1877.IS_DEL = 0
      LEFT JOIN LINKS L228 ON L228.OBJ_ID = V1877.VAL AND L228.OBJ_TYPE_ID = 236 AND L228.PARENT_TYPE_ID = 228 AND L228.DATE_DEL IS NULL
      LEFT JOIN VALL V1847 ON V1847.PARAM_ID = 1847 AND V1847.IS_DEL = 0 AND V1847.OBJ_ID = L228.PARENT_ID
      LEFT JOIN VALR V1872 ON V1872.PARAM_ID = 1872 AND V1872.OBJ_ID = L234.OBJ_ID AND V1872.IS_DEL = 0
      LEFT JOIN LINKS L11 ON L11.OBJ_TYPE_ID = 11 AND L11.PARENT_ID = V1872.VAL AND L11.DATE_DEL IS NULL
      LEFT JOIN VALL  V50 ON V50.PARAM_ID = 50 AND V50.IS_DEL = 0 AND V50.OBJ_ID = L11.OBJ_ID
    WHERE L234.OBJ_TYPE_ID = 234 AND L234.DATE_DEL IS NULL
      AND
      (
      ((V1847.LISTVAL_ID = 5377) AND (V50.LISTVAL_ID = 1375)) OR
      ((V1847.LISTVAL_ID = 5378) AND (V50.LISTVAL_ID = 3241)) OR
      ((V1847.LISTVAL_ID = 5379) AND (V50.LISTVAL_ID = 1376)) OR
      ((V1847.LISTVAL_ID = 5380) AND (V50.LISTVAL_ID = 3240)) OR
      ((V1847.LISTVAL_ID = 5385) AND (V50.LISTVAL_ID = 3149))
      )
      AND L234.OBJ_ID = :I$OBJ_ID

    ORDER BY 2 DESC
    INTO :V$ID11, :ORI_DATEVID;

    IF (V$ID11 IS NOT NULL) THEN
    BEGIN
      SELECT S.V||N.V FROM VAL_GET(:V$ID11, 564, 0, :I$USER_ID) S
      LEFT JOIN VAL_GET(:V$ID11, 565, 0, :I$USER_ID) N ON 1=1
      INTO :ORI_KSNB;
    END
  END

  SELECT S || N
  FROM CERTIFICATE_SN_GET(:I$OBJ_ID, :I$USER_ID)
  INTO :DUP_KSNB;

  IF (:DUP_KSNB = :ORI_KSNB) THEN
  BEGIN
    ORI_KSNB = NULL;
    ORI_DATEVID = NULL;
  END

  SELECT F.V ||' '|| I.V ||' '|| O.V
  FROM VAL_GET(:V$PUPIL_ID, 55, 0, :I$USER_ID) F
  LEFT JOIN VAL_GET(:V$PUPIL_ID, 56, 0, :I$USER_ID) I ON 1=1
  LEFT JOIN VAL_GET(:V$PUPIL_ID, 57, 0, :I$USER_ID) O ON 1=1
  INTO :DUP_OWNER;

  SELECT TRIM(F.V ||' '|| I.V ||' '|| O.V)
  FROM VAL_GET(:I$OBJ_ID, 1874, 0, :I$USER_ID) F
  LEFT JOIN VAL_GET(:I$OBJ_ID, 1873, 0, :I$USER_ID) I ON 1=1
  LEFT JOIN VAL_GET(:I$OBJ_ID, 1875, 0, :I$USER_ID) O ON 1=1
  INTO :DUP_RECEIVER;

  IF (DUP_RECEIVER = '') THEN
  BEGIN
    DUP_RECEIVER = DUP_OWNER;
  END

  SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CERTIFICATE_REG_LIST (
    I$YEAR BIGINT,
    I$CLASS_ID BIGINT,
    I$STAGE_ID BIGINT,
    I$USER_ID BIGINT = 1,
    I$DATA_FL SMALLINT = 1,
    I$STATUS_FILTER SMALLINT = 0)
RETURNS (
    OBJ_ID BIGINT,
    PUPIL_ID BIGINT,
    VAL1 INTEGER,
    VAL2 VARCHAR(30),
    VAL3 VARCHAR(30),
    VAL4 VARCHAR(1000),
    VAL5 DATE,
    VAL6 DATE,
    VAL7 VARCHAR(255),
    VAL8 VARCHAR(255),
    VAL9 DATE,
    VAL11 VARCHAR(255),
    VAL12 DATE,
    GRADUATE_YEAR INTEGER,
    BLANK_ID BIGINT,
    FORM_USE_TYPE_ID BIGINT,
    CLASS_ID BIGINT)
AS
declare variable V$FIO varchar(255);
declare variable V$I integer;
declare variable V$LANG_CODE char(2);
declare variable V$START_DATE date;
declare variable V$STOP_DATE date;
declare variable V$CERTIFICATE_REG_DATE date;
BEGIN
    V$START_DATE = '01.01.' || I$YEAR;
    V$STOP_DATE = '31.12.' || I$YEAR;
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :V$LANG_CODE;

    FOR
        SELECT L234.OBJ_ID, V1872.VAL, V1877.VAL, L234.DATE_INS, V1876.VAL
        FROM LINKS L234
        JOIN VALR V1872 ON V1872.OBJ_ID = L234.OBJ_ID AND V1872.PARAM_ID = 1872 AND V1872.IS_DEL = 0
        JOIN VALR V1877 ON V1877.OBJ_ID = L234.OBJ_ID AND V1877.PARAM_ID = 1877 AND V1877.IS_DEL = 0
        JOIN VALD V1876 ON V1876.OBJ_ID = L234.OBJ_ID AND V1876.PARAM_ID = 1876 AND V1876.IS_DEL = 0 AND V1876.VAL >= :V$START_DATE AND V1876.VAL <= :V$STOP_DATE
        WHERE L234.PARENT_ID = :I$STAGE_ID AND L234.OBJ_TYPE_ID = 234 AND L234.DATE_DEL IS NULL
        AND EXISTS(
            SELECT FIRST 1 1
            FROM LINKS LP
            WHERE LP.OBJ_ID = V1872.VAL AND LP.PARENT_TYPE_ID IN (81,82,83,9,125,187)
                AND ((LP.DATE_DEL IS NULL) OR ((LP.DATE_DEL >= :V$START_DATE) AND (LP.DATE_DEL <= :V$STOP_DATE)))
                AND ((:I$CLASS_ID IS NULL) OR (LP.PARENT_ID = :I$CLASS_ID))
        )
        AND EXISTS(
            SELECT FIRST 1 1
            FROM LINKS LP
            WHERE LP.OBJ_ID = V1872.VAL AND LP.PARENT_TYPE_ID IN (81,82,83,9,125,187) AND LP.DATE_DEL IS NULL
        )
        INTO :OBJ_ID, :PUPIL_ID, :BLANK_ID, :VAL12, :V$CERTIFICATE_REG_DATE
    DO
    BEGIN
        CLASS_ID = NULL;

        SELECT FIRST 1 OBJ_ID
        FROM CERTIFICATE_REG_PUPIL_CLASS_GET(:PUPIL_ID, :V$CERTIFICATE_REG_DATE)
        WHERE OBJ_ID = :I$CLASS_ID OR :I$CLASS_ID IS NULL
        INTO :CLASS_ID;

        IF (:I$DATA_FL = 1) THEN
        BEGIN
            -- 1
            SELECT I
            FROM VAL_GET(:OBJ_ID, 1871, 0, :I$USER_ID)
            INTO :VAL1;

            -- 2, 4, 5, 6, 7, 9
            SELECT
            CASE CERTIFICATE_TYPE_ID
                WHEN 5377 THEN 'ОО'
                WHEN 5378 THEN 'ОО с отл.'
                WHEN 5379 THEN 'СО'
                WHEN 5380 THEN 'СО с отл.'
                ELSE (
                    SELECT TAG
                    FROM LISTVALS
                    WHERE LISTVAL_ID = CERTIFICATE_TYPE_ID
                )
            END VAL2,
            FIO VAL4,
            DOB VAL5,
            ORDER_DATE VAL6,
            (SELECT V FROM VAL_GET(ORDER_ID, 1842, 0, :I$USER_ID)) VAL7,
            GIVE_DATE VAL9,
            GRADUATE_YEAR
            FROM CERTIFICATE_PUPIL_INFO_READ(:OBJ_ID, :I$USER_ID)
            INTO :VAL2, :VAL4, :VAL5, :VAL6, :VAL7, :VAL9, :GRADUATE_YEAR;

            -- 3, 11
            SELECT V1881.VAL || V1878.VAL VAL3, R.VAL, V1880.LISTVAL_ID
            FROM LINKS L236
            JOIN VALS V1878 ON V1878.OBJ_ID = L236.OBJ_ID AND V1878.PARAM_ID = 1878 AND V1878.IS_DEL = 0
            JOIN LINKS LP228 ON LP228.OBJ_ID = L236.OBJ_ID AND LP228.PARENT_TYPE_ID = 228 AND LP228.DATE_DEL IS NULL
            JOIN VALS V1881 ON V1881.OBJ_ID = LP228.PARENT_ID AND V1881.PARAM_ID = 1881 AND V1881.IS_DEL = 0
            JOIN VALL V1880 ON V1880.OBJ_ID = L236.OBJ_ID AND V1880.PARAM_ID = 1880 AND V1880.IS_DEL = 0
            JOIN LISTVALS LV ON LV.LISTVAL_ID = V1880.LISTVAL_ID
            LEFT JOIN RES_GET(LV.RES_ID, :V$LANG_CODE) R ON 1=1
            LEFT JOIN VALL V1882 ON V1882.OBJ_ID = L236.OBJ_ID AND V1882.PARAM_ID = 1882 AND V1882.IS_DEL = 0
            LEFT JOIN VALR V1877 ON V1877.VAL = L236.OBJ_ID AND V1877.IS_DEL = 0
            WHERE L236.OBJ_ID = :BLANK_ID AND L236.OBJ_TYPE_ID = 236 AND L236.DATE_DEL IS NULL
            INTO :VAL3, :VAL11, :FORM_USE_TYPE_ID;

            -- 8
            SELECT V
            FROM VAL_GET(:OBJ_ID, 1874, 0, :I$USER_ID)
            INTO :VAL8;

            SELECT :VAL8||IIF(CHAR_LENGTH(V) = 0, '', ' '||SUBSTRING(V FROM 1 FOR 1)||'.')
            FROM VAL_GET(:OBJ_ID, 1873, 0, :I$USER_ID)
            INTO :VAL8;

            SELECT :VAL8||IIF(CHAR_LENGTH(V) = 0, '', SUBSTRING(V FROM 1 FOR 1)||'.')
            FROM VAL_GET(:OBJ_ID, 1875, 0, :I$USER_ID)
            INTO :VAL8;
        
            IF (:VAL8 = '') THEN
            BEGIN
                V$FIO = :VAL4;
                V$FIO = REPLACE(:V$FIO, ASCII_CHAR(13), ' ');
                V$FIO = REPLACE(:V$FIO, ASCII_CHAR(10), ' ');
                V$I = 1;
                WHILE (:V$I <= CHAR_LENGTH(:V$FIO) AND SUBSTRING(:V$FIO FROM :V$I FOR 1) <> ' ') DO
                BEGIN
                    V$I = :V$I + 1;
                END
                VAL8 = TRIM(SUBSTRING(:V$FIO FROM 1 FOR :V$I));
                V$FIO = TRIM(SUBSTRING(:V$FIO FROM :V$I FOR 255));
                IF (:V$FIO > '') THEN
                BEGIN
                    VAL8 = :VAL8||' '||SUBSTRING(:V$FIO FROM 1 FOR 1)||'.';
                    V$I = 1;
                    WHILE (:V$I <= CHAR_LENGTH(:V$FIO) AND SUBSTRING(:V$FIO FROM :V$I FOR 1) <> ' ') DO
                    BEGIN
                        V$I = :V$I + 1;
                    END
                    V$FIO = TRIM(SUBSTRING(:V$FIO FROM :V$I FOR 255));
                    IF (:V$FIO > '') THEN
                    BEGIN
                        VAL8 = :VAL8||SUBSTRING(:V$FIO FROM 1 FOR 1)||'.';
                    END
                END
            END
        END
        
        IF((:I$STATUS_FILTER = 0) OR
           ((I$STATUS_FILTER = 1) AND (FORM_USE_TYPE_ID = 5440)) OR
           ((I$STATUS_FILTER = 2) AND (FORM_USE_TYPE_ID <> 5440))) THEN
        BEGIN
            SUSPEND;
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CERTIFICATE_REG_PUPIL_CLASS_GET (
    I$PUPIL_ID BIGINT,
    I$CERTIFICATE_REG_DATE DATE)
RETURNS (
    OBJ_ID BIGINT,
    OBJ_CAPTION VARCHAR(4000),
    SORT_ORDER DOUBLE PRECISION)
AS
declare variable I integer;
declare variable LEN integer;
declare variable STR varchar(255);
declare variable S varchar(2);
declare variable V$OBJ_ID bigint;
declare variable V$TYPE_ID bigint;
BEGIN
    V$TYPE_ID = NULL;
    SELECT FIRST 1 M.GROUP_ID, M.NAME_IN, O.TYPE_ID
    FROM PERSON_MOVEMENTS M
    JOIN OBJECTS O ON O.OBJ_ID = M.GROUP_ID AND O.TYPE_ID IN (9, 125, 187)
    WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :I$PUPIL_ID AND M.DATE_IN > DATEADD(-1 YEAR TO :I$CERTIFICATE_REG_DATE) AND M.DATE_IN < :I$CERTIFICATE_REG_DATE AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :I$CERTIFICATE_REG_DATE)
    ORDER BY M.DATE_OUT NULLS FIRST
    INTO :OBJ_ID, :OBJ_CAPTION, :V$TYPE_ID;

    -- Индекс для сортировки берем из цифровой части номера класса
    LEN = CHARACTER_LENGTH(OBJ_CAPTION);
    I = 1;
    STR = '';
    WHILE(I <= LEN) DO
    BEGIN
        S = SUBSTRING(OBJ_CAPTION FROM I FOR 1);
        IF (S SIMILAR TO '[[:DIGIT:]]+') THEN
        BEGIN
            STR = STR || S;
        END
        ELSE
        BEGIN
            BREAK;
        END
        I = I + 1;
    END
    IF (STR <> '') THEN SORT_ORDER = STR;

    -- Совсем запасной вариант: если не нашли класс в нормальном реестре движения, пытаемся найти через линки
    IF (OBJ_ID IS NULL) THEN
    BEGIN
        SELECT FIRST 1 L.PARENT_TYPE_ID, L.PARENT_ID, C.CAPTION, C.SORT_ORDER
        FROM LINKS L
        LEFT JOIN OBJECT_CAPTION_GET(L.PARENT_ID) C ON 1 = 1
        WHERE L.OBJ_ID = :I$PUPIL_ID AND L.PARENT_TYPE_ID IN (9, 125, 187, 81, 82, 83) AND (L.DATE_DEL IS NULL OR L.DATE_DEL > :I$CERTIFICATE_REG_DATE)
        ORDER BY IIF(L.PARENT_TYPE_ID IN (9, 125, 187), 0, 1), L.DATE_DEL NULLS FIRST
        INTO :V$TYPE_ID, :OBJ_ID, :OBJ_CAPTION, :SORT_ORDER;
    END

    IF (OBJ_ID IS NULL) THEN EXIT;

    -- Если класс больше не существует, добавляем название куда ученик из класса выбыл
    IF ((V$TYPE_ID NOT IN (81, 82, 83)) AND NOT EXISTS(SELECT FIRST 1 1 FROM LINKS WHERE OBJ_ID = :OBJ_ID AND PARENT_TYPE_ID = 8 AND DATE_DEL IS NULL)) THEN
    BEGIN
        SELECT FIRST 1 PARENT_ID, C.CAPTION
        FROM LINKS
        LEFT JOIN OBJECT_CAPTION_GET(PARENT_ID) C ON 1 = 1
        WHERE OBJ_ID = :I$PUPIL_ID AND PARENT_TYPE_ID IN (81, 82, 83) AND DATE_DEL IS NULL
        INTO :V$OBJ_ID, :STR;

        OBJ_CAPTION = OBJ_CAPTION || ' (' || STR || ')';
    END
    -- А вот если класс существует, дописываем текущее название класса
    ELSE
    BEGIN
        SELECT CAPTION FROM OBJECT_CAPTION_GET(:OBJ_ID) INTO :STR;

        IF (OBJ_CAPTION <> STR) THEN
        BEGIN
            OBJ_CAPTION = OBJ_CAPTION || ' (' || STR || ')';
        END
    END

    SUSPEND;

END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CERTIFICATE_REG_TITUL_INFO_GET (
    I$STAGE_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    NAMEOU VARCHAR(2000),
    TYPEOBR VARCHAR(200),
    "YEAR" VARCHAR(200),
    RUKFIO VARCHAR(200))
AS
DECLARE VARIABLE V$LANG_CODE CHAR(2);
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :V$LANG_CODE;

    SELECT R.VAL_LONG FROM VAL_GET(:I$STAGE_ID, 43, 0, :I$USER_ID) V
    LEFT JOIN LISTVALS LV ON  V.I = LV.LISTVAL_ID
    LEFT JOIN RES_GET(LV.RES_ID, :V$LANG_CODE) R ON 1=1
    INTO :TYPEOBR;
  
    SELECT V.V FROM OBJECT_PARENTS_GET(:I$STAGE_ID,2)  P
    LEFT JOIN VAL_GET(P.OBJ_ID, 5, 0, 1) V ON 1=1
    INTO NAMEOU;

    SELECT 'Год учета '||EXTRACT(YEAR FROM CURRENT_DATE) FROM RDB$DATABASE
    INTO "YEAR";

    SELECT
    '/' ||SUBSTRING(D.I FROM 1 FOR 1) || '.' ||
    SUBSTRING(D.O FROM 1 FOR 1) || '. ' || D.F || '/'
    FROM OBJECT_PARENTS_GET(:I$STAGE_ID, 2)  P
    LEFT JOIN R_SPB_POST_DIRECTOR(P.OBJ_ID, :I$USER_ID) D ON 1=1
    INTO RUKFIO;

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CERTIFICATE_REG_YEARS_LIST (
    I$STAGE_ID BIGINT,
    I$BLANK_CHECK_FL SMALLINT = 1)
RETURNS (
    "YEAR" SMALLINT)
AS
BEGIN
    FOR
        -- Выдаем календарными годами
        SELECT EXTRACT(YEAR FROM CURRENT_DATE)
        FROM RDB$DATABASE

        UNION

        SELECT EXTRACT(YEAR FROM V1876.VAL)
        FROM LINKS L234
        JOIN VALR V1872 ON V1872.OBJ_ID = L234.OBJ_ID AND V1872.PARAM_ID = 1872 AND V1872.IS_DEL = 0
        JOIN LINKS LP ON LP.OBJ_ID = V1872.VAL AND LP.PARENT_TYPE_ID IN (9,125,187,81,82,83) AND LP.DATE_DEL IS NULL
        LEFT JOIN VALR V1877 ON V1877.OBJ_ID = L234.OBJ_ID AND V1877.PARAM_ID = 1877 AND V1877.IS_DEL = 0
        JOIN VALD V1876 ON V1876.OBJ_ID = L234.OBJ_ID AND V1876.PARAM_ID = 1876 AND V1876.IS_DEL = 0
        WHERE L234.PARENT_ID = :I$STAGE_ID AND L234.OBJ_TYPE_ID = 234 AND L234.DATE_DEL IS NULL
            AND ((:I$BLANK_CHECK_FL = 1 AND V1877.VAL IS NOT NULL) OR (:I$BLANK_CHECK_FL <> 1 AND V1877.VAL IS NULL))
        INTO :"YEAR"
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CERTIFICATE_SN_GET (
    I$OBJ_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    S VARCHAR(10),
    N VARCHAR(20))
AS
declare variable V$ID236 bigint;
declare variable V$ID228 bigint;
BEGIN
    SELECT
    VAL
    FROM VALR
    WHERE OBJ_ID = :I$OBJ_ID
    AND PARAM_ID = 1877
    AND IS_DEL = 0
    INTO V$ID236;
    
    SELECT V FROM VAL_GET (:V$ID236, 1878, 0, :I$USER_ID)
    INTO :N;
    
    SELECT
    PARENT_ID
    FROM LINKS
    WHERE OBJ_ID = :V$ID236
    --AND DATE_DEL IS NULL
    INTO :V$ID228;
    
    SELECT V FROM VAL_GET (:V$ID228, 1881, 0, :I$USER_ID)
    INTO :S;

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CERTIFICATE_STAGES_LIST (
    I$OBJ_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    STAGE_ID BIGINT,
    STAGE_TYPE_ID BIGINT,
    STAGE_NAME VARCHAR(255))
AS
declare variable V$SCHOOL_ID bigint;
BEGIN
    FOR
        SELECT FIRST 1
               OBJ_ID
        FROM OBJECT_PARENTS_GET(:I$OBJ_ID, 2)
        INTO :V$SCHOOL_ID
    DO
    BEGIN
        FOR
            SELECT L7.OBJ_ID,
                   V43.LISTVAL_ID
            FROM LINKS L7

            JOIN VALL V43
            ON V43.OBJ_ID = L7.OBJ_ID
            AND V43.PARAM_ID = 43
            AND V43.IS_DEL = 0
            AND V43.LISTVAL_ID IN (26, 27, 29)

            JOIN LISTVALS LV
            ON LV.LISTVAL_ID = V43.LISTVAL_ID

            WHERE L7.PARENT_ID = :V$SCHOOL_ID
            AND L7.OBJ_TYPE_ID = 7
            AND L7.DATE_DEL IS NULL

            ORDER BY LV.SORT_ORDER

            INTO :STAGE_ID,
                 :STAGE_TYPE_ID
        DO
        BEGIN
            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:STAGE_ID, NULL, NULL,  :I$USER_ID)
            INTO :STAGE_NAME;

            SUSPEND;
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CERTIFICATE_STAGE_SUBJECT_LIST (
    I$STAGE_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    S_SUBJECT_ID BIGINT,
    S_SUBJECT_NAME VARCHAR(1000),
    SUBJECT_ID BIGINT,
    SUBJECT_NAME VARCHAR(1000),
    SUBJECT_TYPE BIGINT)
AS
DECLARE VARIABLE V$STAGE_ID BIGINT;
DECLARE VARIABLE T BIGINT;
BEGIN

    IF(I$STAGE_ID IS NOT NULL) THEN
    SELECT FIRST 1 V.LISTVAL_ID
    FROM VALL V
    WHERE V.OBJ_ID = :I$STAGE_ID AND V.PARAM_ID = 43 AND V.IS_DEL = 0
    INTO :V$STAGE_ID;

    FOR
        SELECT L51.SUBJECT_ID, L51.SUBJECT_NAME, L51.SUBJECT_TYPE, L51.TYPE_ID
        FROM CERTIFICATE_SUBJECT_LIST(NULL, :I$USER_ID) L51
        ORDER BY L51.SUBJECT_NAME
        INTO :SUBJECT_ID, :SUBJECT_NAME, :SUBJECT_TYPE, :T
    DO
    BEGIN
        S_SUBJECT_ID = NULL;
        S_SUBJECT_NAME = NULL;

        /*SELECT FIRST 1 L227.OBJ_ID, V1846.VAL
        FROM LINKS L227
        JOIN VALR V1845 ON V1845.OBJ_ID = L227.OBJ_ID AND V1845.PARAM_ID = 1845 AND V1845.VAL = :SUBJECT_ID
        JOIN VALS V1846 ON V1846.OBJ_ID = L227.OBJ_ID AND V1846.PARAM_ID = 1846 AND V1846.IS_DEL = 0
        WHERE L227.PARENT_ID = :I$STAGE_ID AND L227.OBJ_TYPE_ID = 227 AND L227.DATE_DEL IS NULL
        INTO :S_SUBJECT_ID, :S_SUBJECT_NAME;*/

        IF(I$STAGE_ID IS NOT NULL) THEN
        SELECT FIRST 1 L227.OBJ_ID, V1846.VAL
        FROM VALR V1845
        JOIN LINKS L227 ON L227.OBJ_ID = V1845.OBJ_ID AND L227.PARENT_ID = :I$STAGE_ID AND L227.DATE_DEL IS NULL
        JOIN VALS V1846 ON V1846.OBJ_ID = V1845.OBJ_ID AND V1846.PARAM_ID = 1846 AND V1846.IS_DEL = 0
        WHERE V1845.PARAM_ID = 1845 AND V1845.VAL = :SUBJECT_ID
        INTO :S_SUBJECT_ID, :S_SUBJECT_NAME;

        -- Убираем предметы, не соответствующие уровню образования
        IF(V$STAGE_ID IN (22, 26, 27) AND T <> 51) THEN SUBJECT_ID = NULL;
        ELSE IF(V$STAGE_ID IN (28, 29) AND T <> 197) THEN SUBJECT_ID = NULL;

        IF(SUBJECT_ID IS NOT NULL) THEN SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CERTIFICATE_STAGE_SUBJECT_SET (
    I$STAGE_ID BIGINT,
    I$S_SUBJECT_ID BIGINT,
    I$SUBJECT_ID BIGINT,
    I$USER_ID BIGINT,
    I$S_SUBJECT_NAME VARCHAR(1000))
RETURNS (
    S_SUBJECT_ID BIGINT)
AS
declare variable V$BLOB_ID bigint;
BEGIN

    -- только для толстого клиента, в тонком CERTIFICATE_SUBJECT_SET

    S_SUBJECT_ID = I$S_SUBJECT_ID;
    IF (S_SUBJECT_ID IS NULL) THEN
    BEGIN
        SELECT OBJ_ID
        FROM OBJECT_ADD(:I$STAGE_ID, 227, NULL, NULL, :I$USER_ID)
        INTO :S_SUBJECT_ID;

        IF (S_SUBJECT_ID IS NOT NULL) THEN
        BEGIN   
            SELECT BLOB_ID
            FROM VAL_ADD(1845, :S_SUBJECT_ID, :I$SUBJECT_ID, :I$USER_ID)
            INTO :V$BLOB_ID;
        END
    END

    IF (S_SUBJECT_ID IS NOT NULL) THEN
    BEGIN
        SELECT BLOB_ID
        FROM VAL_ADD(1846, :S_SUBJECT_ID, TRIM(:I$S_SUBJECT_NAME), :I$USER_ID, IIF(TRIM(:I$S_SUBJECT_NAME) IS NULL, 1, 0))
        INTO :V$BLOB_ID;
    END
    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CERTIFICATE_SUBJECT_LIST (
    I$PARENT_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    SUBJECT_ID BIGINT,
    SUBJECT_NAME VARCHAR(1000),
    SUBJECT_TYPE BIGINT,
    TYPE_ID BIGINT)
AS
DECLARE VARIABLE V$PARENT_ID1 BIGINT;
DECLARE VARIABLE V$PARENT_ID2 BIGINT;
DECLARE VARIABLE V$HAS_OO SMALLINT;
DECLARE VARIABLE V$HAS_SPO SMALLINT;
BEGIN
    -- Вызов идет с PARENT_ID = NULL, внутри формируется второй уровень вызова

    IF (I$PARENT_ID IS NULL) THEN
    BEGIN
      SELECT FIRST 1 OBJ_ID
      FROM LINKS
      WHERE PARENT_ID IS NULL AND OBJ_TYPE_ID = 53 AND DATE_DEL IS NULL
      INTO :V$PARENT_ID1;

      SELECT FIRST 1 OBJ_ID
      FROM LINKS
      WHERE PARENT_ID IS NULL AND OBJ_TYPE_ID = 193 AND DATE_DEL IS NULL
      INTO :V$PARENT_ID2;
    END

    V$HAS_OO = 0;
    V$HAS_SPO = 0;

    SELECT FIRST 1 1
    FROM LINKS L472
    JOIN VALL V3327 ON V3327.OBJ_ID = L472.OBJ_ID AND V3327.PARAM_ID = 3327 AND V3327.IS_DEL = 0 AND V3327.LISTVAL_ID IN (22, 26, 27)
    WHERE L472.PARENT_TYPE_ID = 2 AND L472.OBJ_TYPE_ID = 472 AND L472.DATE_DEL IS NULL
    INTO :V$HAS_OO;

    SELECT FIRST 1 1
    FROM LINKS L472
    JOIN VALL V3327 ON V3327.OBJ_ID = L472.OBJ_ID AND V3327.PARAM_ID = 3327 AND V3327.IS_DEL = 0 AND V3327.LISTVAL_ID IN (28, 29, 13129, 13131)
    WHERE L472.PARENT_TYPE_ID = 2 AND L472.OBJ_TYPE_ID = 472 AND L472.DATE_DEL IS NULL
    INTO :V$HAS_SPO;

    IF(V$HAS_OO = 1) THEN
    FOR
        SELECT L51.OBJ_ID, V2461.LISTVAL_ID, L51.OBJ_TYPE_ID
        FROM LINKS L301
        -- Для предметов школ выдаем раздел предмета
        LEFT JOIN VALL V2461 ON V2461.OBJ_ID = L301.OBJ_ID AND V2461.PARAM_ID = 2461 AND V2461.IS_DEL = 0
        JOIN LINKS L51 ON L51.PARENT_ID = L301.OBJ_ID AND L51.OBJ_TYPE_ID = 51 AND L51.DATE_DEL IS NULL
        WHERE L301.PARENT_ID = :V$PARENT_ID1 AND L301.OBJ_TYPE_ID = 301 AND L301.DATE_DEL IS NULL
        INTO :SUBJECT_ID, :SUBJECT_TYPE, :TYPE_ID
    DO
    BEGIN
        SELECT V
        FROM VAL_GET(:SUBJECT_ID, 376, 0, :I$USER_ID)
        INTO :SUBJECT_NAME;

        IF (SUBJECT_NAME <> '') THEN SUSPEND;

        FOR
            SELECT SUBJECT_ID, SUBJECT_NAME, SUBJECT_TYPE, TYPE_ID
            FROM CERTIFICATE_SUBJECT_LIST(:SUBJECT_ID, :I$USER_ID)
            INTO :SUBJECT_ID, :SUBJECT_NAME, :SUBJECT_TYPE, :TYPE_ID
        DO
        BEGIN
            SUSPEND;
        END
    END

    IF(V$HAS_SPO = 1) THEN
    FOR
        SELECT L197.OBJ_ID, V1750.LISTVAL_ID, L197.OBJ_TYPE_ID
        FROM LINKS L197
        -- Для дисциплин колледжей выдаем вид учебной деятельности
        LEFT JOIN VALL V1750 ON V1750.OBJ_ID = L197.OBJ_ID AND V1750.PARAM_ID = 1750 AND V1750.IS_DEL = 0
        WHERE L197.PARENT_ID = :V$PARENT_ID2 AND L197.OBJ_TYPE_ID = 197 AND L197.DATE_DEL IS NULL
        -- Сюда отдельно добавляем Индивидуальный проект, чтобы код был одинаковый для школ и колледжей
        -- если он еще не был выдан как для школы
        UNION
        SELECT L51.OBJ_ID, V2461.LISTVAL_ID, L51.OBJ_TYPE_ID
        FROM LINKS L301
        LEFT JOIN VALL V2461 ON V2461.OBJ_ID = L301.OBJ_ID AND V2461.PARAM_ID = 2461 AND V2461.IS_DEL = 0
        JOIN LINKS L51 ON L51.PARENT_ID = L301.OBJ_ID AND L51.OBJ_TYPE_ID = 51 AND L51.DATE_DEL IS NULL AND L51.OBJ_ID = 34651
        WHERE :V$HAS_OO = 0 AND L301.PARENT_ID = :V$PARENT_ID1 AND L301.OBJ_TYPE_ID = 301 AND L301.DATE_DEL IS NULL
        INTO :SUBJECT_ID, :SUBJECT_TYPE, :TYPE_ID
    DO
    BEGIN
        SELECT V FROM VAL_GET(:SUBJECT_ID, 1751, 0, :I$USER_ID) INTO :SUBJECT_NAME;
        IF(SUBJECT_ID = 34651) THEN SELECT V FROM VAL_GET(:SUBJECT_ID, 376, 0, :I$USER_ID) INTO :SUBJECT_NAME;

        IF (SUBJECT_NAME <> '') THEN SUSPEND;

        FOR
            SELECT SUBJECT_ID, SUBJECT_NAME, SUBJECT_TYPE, TYPE_ID
            FROM CERTIFICATE_SUBJECT_LIST(:SUBJECT_ID, :I$USER_ID)
            INTO :SUBJECT_ID, :SUBJECT_NAME, :SUBJECT_TYPE, :TYPE_ID
        DO
        BEGIN
            SUSPEND;
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CERTIFICATE_SUBJECT_MAP_SET (
    I$OBJ_ID BIGINT,
    I$MAP VARCHAR(4000),
    I$USER_ID BIGINT)
AS
declare variable V$TYPE_ID bigint;
declare variable V$PARAM_ID bigint;
begin

  SELECT TYPE_ID
  FROM OBJECTS
  WHERE OBJ_ID = :I$OBJ_ID
  INTO :V$TYPE_ID;

  IF(V$TYPE_ID = 9) THEN V$PARAM_ID = 3150;
  ELSE IF(V$TYPE_ID = 187) THEN V$PARAM_ID = 3151;
  ELSE IF(V$TYPE_ID = 125) THEN V$PARAM_ID = 3152;
  ELSE EXCEPTION DATA_ERROR 'Недопустимый класс';

  SELECT BLOB_ID FROM VAL_ADD(:V$PARAM_ID, :I$OBJ_ID, :I$MAP) INTO :V$TYPE_ID;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CERTIFICATE_SUBJECT_SET (
    I$PARENT_ID BIGINT NOT NULL,
    I$SUBJECT_ID BIGINT NOT NULL,
    I$ALT_NAME VARCHAR(1000))
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$TYPE_ID bigint;
declare variable S varchar(1000);
begin

  SELECT TYPE_ID
  FROM OBJECTS
  WHERE OBJ_ID = :I$PARENT_ID
  INTO :V$TYPE_ID;

  IF(V$TYPE_ID IS NULL OR V$TYPE_ID NOT IN (7, 9, 125, 187)) THEN EXCEPTION DATA_ERROR 'Недопустимый id родительского объекта';

  SELECT FIRST 1 L227.OBJ_ID, V1846.VAL
  FROM LINKS L227
  JOIN VALR V1845 ON V1845.OBJ_ID = L227.OBJ_ID AND V1845.PARAM_ID = 1845 AND V1845.IS_DEL = 0 AND V1845.VAL = :I$SUBJECT_ID
  LEFT JOIN VALS V1846 ON V1846.OBJ_ID = L227.OBJ_ID AND V1846.PARAM_ID = 1846 AND V1846.IS_DEL = 0
  WHERE L227.PARENT_ID = :I$PARENT_ID AND L227.OBJ_TYPE_ID = 227 AND L227.DATE_DEL IS NULL
  INTO :OBJ_ID, :S;

  IF(I$ALT_NAME IS NULL) THEN
  BEGIN
    IF(OBJ_ID IS NOT NULL) THEN
    BEGIN
      UPDATE LINKS SET DATE_DEL = CURRENT_TIMESTAMP WHERE OBJ_ID = :OBJ_ID;
      OBJ_ID = NULL;
    END
  END
  ELSE
  BEGIN
    IF(COALESCE(S, '') <> I$ALT_NAME) THEN
    BEGIN
      IF(OBJ_ID IS NULL) THEN
      BEGIN
        -- Если нет такого предмета - проверяем удаленные. Если есть - восстанавливаем, иначе создаем новый
        SELECT FIRST 1 L227.OBJ_ID
        FROM LINKS L227
        JOIN VALR V1845 ON V1845.OBJ_ID = L227.OBJ_ID AND V1845.PARAM_ID = 1845 AND V1845.IS_DEL = 0 AND V1845.VAL = :I$SUBJECT_ID
        WHERE L227.PARENT_ID = :I$PARENT_ID AND L227.OBJ_TYPE_ID = 227
        INTO :OBJ_ID;

        IF(OBJ_ID IS NULL) THEN
        BEGIN
          SELECT OBJ_ID FROM OBJECT_ADD_WITH_PARAM(:I$PARENT_ID, NULL, 227, 1845, :I$SUBJECT_ID) INTO :OBJ_ID;
        END
        ELSE
        BEGIN
          UPDATE LINKS
          SET DATE_DEL = NULL
          WHERE OBJ_ID = :OBJ_ID;
        END
      END

      SELECT BLOB_ID FROM VAL_ADD(1846, :OBJ_ID, :I$ALT_NAME) INTO :V$TYPE_ID;
    END
  END

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CERTIFICATE_TEMPLATES_LIST (
    I$STAGE_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    STAGE_ID BIGINT,
    STAGE_TEMPLATE_ID BIGINT,
    TEMPLATE_ID BIGINT,
    STAGE_TYPE_ID BIGINT,
    TEMPLATE_TYPE_ID BIGINT,
    PRINT_TEMPLATE_ID BIGINT,
    TEMPLATE_NAME VARCHAR(255),
    TEMPLATE_DATA VARCHAR(4000))
AS
declare variable V$STAGE_TYPE_ID bigint;
BEGIN
    STAGE_ID = I$STAGE_ID;
    SELECT I
    FROM VAL_GET(:I$STAGE_ID, 43, 0, :I$USER_ID)
    INTO :V$STAGE_TYPE_ID;

    FOR
        SELECT L225.OBJ_ID
        FROM LINKS L224
        JOIN LINKS L225 ON L225.PARENT_ID = L224.OBJ_ID AND L225.OBJ_TYPE_ID = 225 AND L225.DATE_DEL IS NULL
        WHERE L224.PARENT_ID IS NULL AND L224.OBJ_TYPE_ID = 224 AND L224.DATE_DEL IS NULL
        INTO :TEMPLATE_ID
    DO
    BEGIN
        SELECT I
        FROM VAL_GET(:TEMPLATE_ID, 1841, 0, :I$USER_ID)
        INTO :STAGE_TYPE_ID;

        IF (V$STAGE_TYPE_ID = STAGE_TYPE_ID) THEN
        BEGIN
            SELECT I, LV.COST
            FROM VAL_GET(:TEMPLATE_ID, 1840, 0, :I$USER_ID) V
            JOIN LISTVALS LV ON LV.LISTVAL_ID = V.I
            INTO :TEMPLATE_TYPE_ID, :PRINT_TEMPLATE_ID;
    
            SELECT V
            FROM VAL_GET(:TEMPLATE_ID, 1838, 0, :I$USER_ID)
            INTO :TEMPLATE_NAME;
    
            STAGE_TEMPLATE_ID = NULL;
            SELECT FIRST 1 L225.OBJ_ID
            FROM LINKS L225
            JOIN VALL V1841 ON V1841.OBJ_ID = L225.OBJ_ID AND V1841.PARAM_ID = 1841 AND V1841.IS_DEL = 0 AND V1841.LISTVAL_ID = :STAGE_TYPE_ID
            JOIN VALL V1840 ON V1840.OBJ_ID = L225.OBJ_ID AND V1840.PARAM_ID = 1840 AND V1840.IS_DEL = 0 AND V1840.LISTVAL_ID = :TEMPLATE_TYPE_ID
            JOIN VALS V1838 ON V1838.OBJ_ID = L225.OBJ_ID AND V1838.PARAM_ID = 1838 AND V1838.IS_DEL = 0 AND V1838.VAL = :TEMPLATE_NAME
            WHERE L225.PARENT_ID = :I$STAGE_ID AND L225.OBJ_TYPE_ID = 225 AND L225.DATE_DEL IS NULL
            INTO :STAGE_TEMPLATE_ID;
    
            IF (STAGE_TEMPLATE_ID IS NULL) THEN
            BEGIN
                SELECT V
                FROM VAL_GET(:TEMPLATE_ID, 1839, 0, :I$USER_ID)
                INTO :TEMPLATE_DATA;
            END
            ELSE
            BEGIN
                SELECT V
                FROM VAL_GET(:STAGE_TEMPLATE_ID, 1839, 0, :I$USER_ID)
                INTO :TEMPLATE_DATA;
            END

            SUSPEND;
        END
    END
    FOR
        SELECT L225.OBJ_ID
        FROM LINKS L225
        WHERE L225.PARENT_ID = :I$STAGE_ID AND L225.OBJ_TYPE_ID = 225 AND L225.DATE_DEL IS NULL
        INTO :STAGE_TEMPLATE_ID
    DO
    BEGIN
        SELECT I
        FROM VAL_GET(:STAGE_TEMPLATE_ID, 1841, 0, :I$USER_ID)
        INTO :STAGE_TYPE_ID;

        IF (V$STAGE_TYPE_ID = STAGE_TYPE_ID) THEN
        BEGIN
            SELECT I, LV.COST
            FROM VAL_GET(:STAGE_TEMPLATE_ID, 1840, 0, :I$USER_ID) V
            JOIN LISTVALS LV ON LV.LISTVAL_ID = V.I
            INTO :TEMPLATE_TYPE_ID, :PRINT_TEMPLATE_ID;
    
            SELECT V
            FROM VAL_GET(:STAGE_TEMPLATE_ID, 1838, 0, :I$USER_ID)
            INTO :TEMPLATE_NAME;
    
            SELECT V
            FROM VAL_GET(:STAGE_TEMPLATE_ID, 1839, 0, :I$USER_ID)
            INTO :TEMPLATE_DATA;
    
            IF (NOT EXISTS(
                SELECT FIRST 1 1
                FROM LINKS L224
                JOIN LINKS L225 ON L225.PARENT_ID = L224.OBJ_ID AND L225.OBJ_TYPE_ID = 225 AND L225.DATE_DEL IS NULL
                JOIN VALL V1841 ON V1841.OBJ_ID = L225.OBJ_ID AND V1841.PARAM_ID = 1841 AND V1841.IS_DEL = 0 AND V1841.LISTVAL_ID = :STAGE_TYPE_ID
                JOIN VALL V1840 ON V1840.OBJ_ID = L225.OBJ_ID AND V1840.PARAM_ID = 1840 AND V1840.IS_DEL = 0 AND V1840.LISTVAL_ID = :TEMPLATE_TYPE_ID
                JOIN VALS V1838 ON V1838.OBJ_ID = L225.OBJ_ID AND V1838.PARAM_ID = 1838 AND V1838.IS_DEL = 0 AND V1838.VAL = :TEMPLATE_NAME
                WHERE L224.PARENT_ID IS NULL AND L224.OBJ_TYPE_ID = 224 AND L224.DATE_DEL IS NULL
            )) THEN
            BEGIN
                SUSPEND;
            END
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CERTIFICATE_TEMPLATES_SET (
    I$STAGE_ID BIGINT,
    I$USER_ID BIGINT,
    I$STAGE_TEMPLATE_ID BIGINT,
    I$TEMPLATE_ID BIGINT,
    I$STAGE_TYPE_ID BIGINT,
    I$TEMPLATE_TYPE_ID BIGINT,
    I$TEMPLATE_NAME VARCHAR(255),
    I$TEMPLATE_DATA VARCHAR(4000))
RETURNS (
    STAGE_TEMPLATE_ID BIGINT,
    TEMPLATE_ID BIGINT)
AS
DECLARE VARIABLE V$BLOB_ID BIGINT;
BEGIN
    STAGE_TEMPLATE_ID = I$STAGE_TEMPLATE_ID;
    TEMPLATE_ID = I$TEMPLATE_ID;

    IF (STAGE_TEMPLATE_ID IS NULL) THEN
    BEGIN
        SELECT FIRST 1
               L225.OBJ_ID
        FROM LINKS L225
    
        JOIN VALL V1841
        ON V1841.OBJ_ID = L225.OBJ_ID
        AND V1841.PARAM_ID = 1841
        AND V1841.IS_DEL = 0
        AND V1841.LISTVAL_ID = :I$STAGE_TYPE_ID
    
        JOIN VALL V1840
        ON V1840.OBJ_ID = L225.OBJ_ID
        AND V1840.PARAM_ID = 1840
        AND V1840.IS_DEL = 0
        AND V1840.LISTVAL_ID = :I$TEMPLATE_TYPE_ID

        JOIN VALS V1838
        ON V1838.OBJ_ID = L225.OBJ_ID
        AND V1838.PARAM_ID = 1838
        AND V1838.IS_DEL = 0
        AND V1838.VAL = :I$TEMPLATE_NAME
    
        WHERE L225.PARENT_ID = :I$STAGE_ID
        AND L225.OBJ_TYPE_ID = 225
        AND L225.DATE_DEL IS NULL
    
        INTO :STAGE_TEMPLATE_ID;
    END
    IF (STAGE_TEMPLATE_ID IS NULL) THEN
    BEGIN
        SELECT OBJ_ID
        FROM OBJECT_ADD(:I$STAGE_ID, 225, NULL, NULL,  :I$USER_ID)
        INTO :STAGE_TEMPLATE_ID;

        IF (STAGE_TEMPLATE_ID IS NOT NULL) THEN
        BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD(1838, :STAGE_TEMPLATE_ID, :I$TEMPLATE_NAME, :I$USER_ID)
            INTO :V$BLOB_ID;
        END
        TEMPLATE_ID = NULL;
    END
    IF (STAGE_TEMPLATE_ID IS NOT NULL) THEN
    BEGIN
        SELECT BLOB_ID
        FROM VAL_ADD(1841, :STAGE_TEMPLATE_ID, :I$STAGE_TYPE_ID, :I$USER_ID)
        INTO :V$BLOB_ID;

        SELECT BLOB_ID
        FROM VAL_ADD(1840, :STAGE_TEMPLATE_ID, :I$TEMPLATE_TYPE_ID, :I$USER_ID)
        INTO :V$BLOB_ID;

        SELECT BLOB_ID
        FROM VAL_ADD(1839, :STAGE_TEMPLATE_ID, :I$TEMPLATE_DATA, :I$USER_ID)
        INTO :V$BLOB_ID;

        IF (TEMPLATE_ID IS NULL) THEN
        BEGIN
            SELECT FIRST 1
                   L225.OBJ_ID
            FROM LINKS L224
        
            JOIN LINKS L225
            ON L225.PARENT_ID = L224.OBJ_ID
            AND L225.OBJ_TYPE_ID = 225
            AND L225.DATE_DEL IS NULL
        
            JOIN VALL V1841
            ON V1841.OBJ_ID = L225.OBJ_ID
            AND V1841.PARAM_ID = 1841
            AND V1841.IS_DEL = 0
            AND V1841.LISTVAL_ID = :I$STAGE_TYPE_ID
        
            JOIN VALL V1840
            ON V1840.OBJ_ID = L225.OBJ_ID
            AND V1840.PARAM_ID = 1840
            AND V1840.IS_DEL = 0
            AND V1840.LISTVAL_ID = :I$TEMPLATE_TYPE_ID

            JOIN VALS V1838
            ON V1838.OBJ_ID = L225.OBJ_ID
            AND V1838.PARAM_ID = 1838
            AND V1838.IS_DEL = 0
            AND V1838.VAL = :I$TEMPLATE_NAME
    
            WHERE L224.PARENT_ID IS NULL
            AND L224.OBJ_TYPE_ID = 224
            AND L224.DATE_DEL IS NULL

            INTO :TEMPLATE_ID;
        END
    END

    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CERTIFICATE_TYPES_LIST (
    I$STAGE_TYPE_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    CERTIFICATE_TYPE_ID BIGINT,
    CERTIFICATE_TYPE_NAME VARCHAR(1000))
AS
declare variable V$TAG varchar(100);
declare variable V$RES_ID bigint;
declare variable V$LANG_CODE char(2);
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :V$LANG_CODE;

    FOR
        SELECT LV.LISTVAL_ID, LV.TAG, LV.RES_ID
        FROM LISTVALS LV
        WHERE LV.LIST_ID = 256 AND LV.IS_DEL = 0
        AND (((:I$STAGE_TYPE_ID = 26) AND (LV.LISTVAL_ID IN (5377, 5378, 5385))) OR
             ((:I$STAGE_TYPE_ID = 27) AND (LV.LISTVAL_ID IN (5379, 5380, 5385))) OR
             ((:I$STAGE_TYPE_ID = 29) AND (LV.LISTVAL_ID IN (12766, 12767))))

        ORDER BY LV.SORT_ORDER
        INTO :CERTIFICATE_TYPE_ID, :V$TAG, :V$RES_ID
    DO
    BEGIN
        SELECT VAL
        FROM RES_GET(:V$RES_ID, :V$LANG_CODE)
        INTO CERTIFICATE_TYPE_NAME;

        IF (V$TAG <> '') THEN
        BEGIN
            CERTIFICATE_TYPE_NAME = CERTIFICATE_TYPE_NAME || ' (' || V$TAG || ')';
        END
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CERT_PUPIL_FINAL_MARKS (
    I$PUPIL_ID BIGINT,
    I$YEAR SMALLINT)
RETURNS (
    YEAR_VAL SMALLINT,
    SUBJECT_ID BIGINT,
    SUBJECT_NAME VARCHAR(1000),
    MARKTYPE_ID BIGINT,
    MARKTYPE_NAME VARCHAR(100),
    MARKVAL_ID BIGINT,
    MARK_VAL VARCHAR(100))
AS
begin

  FOR
      SELECT VM.SUBJECT_ID, S.CAPTION, VM.MARKTYPE_ID, RM.VAL, VM.MARKVAL_ID, LVY.COST, RV.VAL
      FROM VALM VM
      JOIN LISTVALS LVY ON LVY.LISTVAL_ID = VM.YEAR_ID AND (LVY.COST = :I$YEAR - 1 OR LVY.COST = :I$YEAR - 2)
      JOIN LISTVALS LVM ON LVM.LISTVAL_ID = VM.MARKTYPE_ID
      JOIN RES RM ON RM.RES_ID = LVM.RES_ID AND RM.LANG_CODE = 'RU'
      JOIN LISTVALS LVV ON LVV.LISTVAL_ID = VM.MARKVAL_ID
      JOIN RES RV ON RV.RES_ID = LVV.RES_ID AND RV.LANG_CODE = 'RU'
      LEFT JOIN OBJECT_CAPTION_GET(VM.SUBJECT_ID) S ON 1 = 1
      WHERE VM.IS_DEL = 0 AND VM.PUPIL_ID = :I$PUPIL_ID AND VM.MARKTYPE_ID IN (3009, 3010, 3011) AND VM.MARKVAL_ID IN (3014, 3015, 3016, 3017, 3018)
      INTO :SUBJECT_ID, :SUBJECT_NAME, :MARKTYPE_ID, :MARKTYPE_NAME, :MARKVAL_ID, :YEAR_VAL, :MARK_VAL
  DO
  BEGIN
      IF(MARKTYPE_ID = 3009) THEN MARKTYPE_NAME = 'H1';
      ELSE IF(MARKTYPE_ID = 3010) THEN MARKTYPE_NAME = 'H2';
      SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CERT_PUPIL_LOAD_SUBJECTS (
    I$YEAR SMALLINT,
    I$STAGE_ID BIGINT,
    I$CLASS_ID BIGINT,
    I$PUPIL_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    P_SUBJECT_ID BIGINT,
    INCLUDING_TYPE_ID BIGINT,
    SUBJECT_ID BIGINT,
    SUBJECT_NAME VARCHAR(1000),
    MARK VARCHAR(255),
    MARK_YEAR VARCHAR(255),
    MARK_FIN VARCHAR(255),
    MARK_GIA VARCHAR(255),
    IS_BASE SMALLINT,
    IS_PLAN SMALLINT,
    SORT_ORDER INTEGER,
    SUBJECT_LOAD VARCHAR(100),
    REC_MARK DOUBLE PRECISION,
    PROJECT_THEME VARCHAR(4000))
AS
declare variable V$STAGE_CODE bigint;
BEGIN
    IF(
        NOT EXISTS(
            SELECT FIRST 1 1
            FROM LINKS L292
            JOIN VALI V2354 ON V2354.OBJ_ID = L292.OBJ_ID AND V2354.PARAM_ID = 2354 AND V2354.IS_DEL = 0 AND V2354.VAL = :I$YEAR
            WHERE L292.PARENT_ID = :I$PUPIL_ID AND L292.OBJ_TYPE_ID = 292 AND L292.DATE_DEL IS NULL
        )
        AND NOT EXISTS(
            SELECT FIRST 1 1
            FROM CERTIFICATE_PUPIL_LOAD_SUBJECTS(:I$YEAR, :I$STAGE_ID, :I$CLASS_ID, :I$PUPIL_ID, :I$USER_ID)
            WHERE P_SUBJECT_ID IS NOT NULL
        )
    ) THEN
    BEGIN
        FOR
            SELECT INCLUDING_TYPE_ID, SUBJECT_ID, SUBJECT_NAME, MARK, IS_BASE, IS_PLAN, SORT_ORDER, SUBJECT_LOAD, REC_MARK
            FROM CERTIFICATE_CLASS_LOAD_SUBJECTS(:I$STAGE_ID, :I$CLASS_ID, :I$USER_ID, :I$PUPIL_ID)
            INTO :INCLUDING_TYPE_ID, :SUBJECT_ID, :SUBJECT_NAME, :MARK, :IS_BASE, :IS_PLAN, :SORT_ORDER, :SUBJECT_LOAD, :REC_MARK
        DO
        BEGIN
            PROJECT_THEME = NULL;
            IF(SUBJECT_ID = 34651) THEN
            BEGIN
                -- Для 9 и 11 классов тема из разных полей
                SELECT FIRST 1 V43.LISTVAL_ID
                FROM VALL V43
                WHERE V43.OBJ_ID = :I$STAGE_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0
                INTO :V$STAGE_CODE;

                SELECT V FROM VAL_GET(:I$PUPIL_ID, IIF(:V$STAGE_CODE = 27, 229, 3116)) WHERE IS_EXISTS = 1 AND :SUBJECT_ID = 34651 INTO :PROJECT_THEME;
                IF(PROJECT_THEME IS NULL) THEN SELECT V FROM VAL_GET(:I$PUPIL_ID, 3162) WHERE IS_EXISTS = 1 AND :SUBJECT_ID = 34651 INTO :PROJECT_THEME;
            END
            SUSPEND;
        END
    END
    ELSE
    BEGIN
        FOR
            SELECT P_SUBJECT_ID, INCLUDING_TYPE_ID, SUBJECT_ID, SUBJECT_NAME, MARK, MARK_YEAR, MARK_FIN, MARK_GIA, IS_BASE, IS_PLAN, SORT_ORDER, SUBJECT_LOAD, REC_MARK, PROJECT_THEME
            FROM CERTIFICATE_PUPIL_LOAD_SUBJECTS(:I$YEAR, :I$STAGE_ID, :I$CLASS_ID, :I$PUPIL_ID, :I$USER_ID)
            INTO :P_SUBJECT_ID, :INCLUDING_TYPE_ID, :SUBJECT_ID, :SUBJECT_NAME, :MARK, :MARK_YEAR, :MARK_FIN, :MARK_GIA, :IS_BASE, :IS_PLAN, :SORT_ORDER, :SUBJECT_LOAD, :REC_MARK, :PROJECT_THEME
        DO
        BEGIN
            IF (P_SUBJECT_ID IS NULL) THEN INCLUDING_TYPE_ID = 5383;
            SUSPEND;
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CERT_STUDY_PUPIL_LOAD_SUBJECTS (
    I$YEAR SMALLINT,
    I$PUPIL_ID BIGINT,
    I$CLASS_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    P_SUBJECT_ID BIGINT,
    INCLUDING_TYPE_ID BIGINT,
    SUBJECT_ID BIGINT,
    SUBJECT_NAME VARCHAR(1000),
    MARK_YEAR VARCHAR(255),
    MARK_FIN VARCHAR(255),
    MARK_GIA VARCHAR(255),
    IS_BASE SMALLINT,
    IS_PLAN SMALLINT,
    SORT_ORDER INTEGER,
    YEAR_VAL VARCHAR(100),
    YEAR_COST INTEGER)
AS
declare variable V$STAGE_ID bigint;
declare variable LANG_CODE varchar(2);
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :LANG_CODE;

    SELECT FIRST 1 OBJ_ID
    FROM OBJECT_PARENTS_GET(:I$PUPIL_ID, 7)
    INTO :V$STAGE_ID;

    FOR SELECT
            S.P_SUBJECT_ID,
            S.INCLUDING_TYPE_ID,
            S.SUBJECT_ID,
            S.SUBJECT_NAME,
            COALESCE(S.MARK_YEAR, M_Y.MARK) MARK_YEAR,
            COALESCE(S.MARK_FIN, M_F.MARK) MARK_FIN,
            S.MARK_GIA,
            S.IS_BASE,
            S.IS_PLAN,
            S.SORT_ORDER,
            IIF(COALESCE(R_Y.VAL, R_F.VAL) > COALESCE(R_F.VAL, R_Y.VAL),
                COALESCE(R_Y.VAL, R_F.VAL), COALESCE(R_F.VAL, R_Y.VAL)),
            IIF(COALESCE(M_Y.YEAR_COST, M_F.YEAR_COST) > COALESCE(M_F.YEAR_COST, M_Y.YEAR_COST),
                COALESCE(M_Y.YEAR_COST, M_F.YEAR_COST), COALESCE(M_F.YEAR_COST, M_Y.YEAR_COST))
        FROM CERTIFICATE_PUPIL_LOAD_SUBJECTS(:I$YEAR, :V$STAGE_ID, :I$CLASS_ID, :I$PUPIL_ID, :I$USER_ID) S

        LEFT JOIN ATT_MARK_GET(:I$PUPIL_ID, S.SUBJECT_ID, :I$USER_ID, 3011, 1) M_Y ON 1=1
        LEFT JOIN RES_GET(M_Y.YEAR_RES_ID, :LANG_CODE) R_Y ON 1=1

        LEFT JOIN ATT_MARK_GET(:I$PUPIL_ID, S.SUBJECT_ID, :I$USER_ID, 3013, 1) M_F ON 1=1
        LEFT JOIN RES_GET(M_F.YEAR_RES_ID, :LANG_CODE) R_F ON 1=1

        ORDER BY S.INCLUDING_TYPE_ID, S.SORT_ORDER, S.SUBJECT_NAME
        INTO
            :P_SUBJECT_ID,
            :INCLUDING_TYPE_ID,
            :SUBJECT_ID,
            :SUBJECT_NAME,
            :MARK_YEAR,
            :MARK_FIN,
            :MARK_GIA,
            :IS_BASE,
            :IS_PLAN,
            :SORT_ORDER,
            :YEAR_VAL,
            :YEAR_COST
    DO
    BEGIN
        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CERT_STUDY_REG_CLASS_GET (
    I$YEAR SMALLINT,
    I$CLASS_ID BIGINT,
    I$STAGE_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    NUMBER VARCHAR(50),
    FIO VARCHAR(50),
    DATEBIRTH VARCHAR(20),
    POLUCH VARCHAR(50),
    DATEVID VARCHAR(20),
    DATERECORD VARCHAR(20),
    CLASS_ID BIGINT)
AS
BEGIN
    FOR
        SELECT VAL1,
               VAL4,
               VAL5,
               VAL8,
               VAL9,
               VAL12,
               CLASS_ID
        FROM CERT_STUDY_REG_LIST(:I$YEAR, :I$CLASS_ID, :I$STAGE_ID, :I$USER_ID)
        ORDER BY VAL1
        INTO :NUMBER,
             :FIO,
             :DATEBIRTH,
             :POLUCH,
             :DATEVID,
             :DATERECORD,
             :CLASS_ID
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CERT_STUDY_REG_CLASS_PRIL_GET (
    I$YEAR SMALLINT,
    I$STAGE_ID BIGINT,
    I$CLASS_ID BIGINT,
    I$USER_ID BIGINT,
    I$ATTESTAT_PRINTED SMALLINT = 0)
RETURNS (
    SN VARCHAR(20),
    FIO VARCHAR(255),
    CLASS_NAME VARCHAR(1000),
    SUBJECTSLEFT VARCHAR(1000),
    SUBJECTSRIGHT VARCHAR(1000),
    MARKSLEFT VARCHAR(1000),
    MARKSRIGHT VARCHAR(1000),
    DOPOLSVED VARCHAR(4000),
    FIOSHORT VARCHAR(255),
    DOB VARCHAR(50),
    CTFIO VARCHAR(255))
AS
declare variable V$CURR_S varchar(200);
declare variable V$CURR_M varchar(40);
declare variable V$OBJ_ID bigint;
declare variable V$PUPIL_ID bigint;
declare variable V$PUPIL_TYPE_ID bigint;
declare variable V$COUNT integer;
declare variable V$CLASS_TYPE_ID bigint;
declare variable V$STAGE_TYPE_ID bigint;
BEGIN
    SELECT TYPE_ID
    FROM OBJECTS
    WHERE OBJ_ID = :I$CLASS_ID
    INTO :V$CLASS_TYPE_ID;

    CTFIO = '/____________________/';
    SELECT FORM_MASTER_FIO
    FROM CERTIFICATE_DIR_FORM_MASTER_GET(:I$STAGE_ID, :I$CLASS_ID, :I$USER_ID)
    INTO :CTFIO;

    FOR
        SELECT L.PUPIL_ID, O.TYPE_ID
        FROM CERT_STUDY_REG_LIST(:I$YEAR, :I$CLASS_ID, :I$STAGE_ID, :I$USER_ID) L
        JOIN OBJECTS O ON O.OBJ_ID = L.PUPIL_ID
        WHERE O.TYPE_ID IN (10, 126) AND ((:I$ATTESTAT_PRINTED = 0) OR EXISTS(SELECT FIRST 1 1 FROM VALR VLR WHERE VLR.VAL = O.OBJ_ID AND VLR.PARAM_ID = 1872 AND VLR.IS_DEL = 0))
        INTO :V$PUPIL_ID, :V$PUPIL_TYPE_ID
    DO
    BEGIN
        SELECT FIRST 1
               OBJ_ID
        FROM VALR
        WHERE VAL = :V$PUPIL_ID
        AND PARAM_ID = 1872 AND IS_DEL = 0
        ORDER BY OBJ_ID
        INTO :V$OBJ_ID;

        SN = '0000000000000';
        SELECT S || N
        FROM CERTIFICATE_SN_GET(:V$OBJ_ID, :I$USER_ID)
        INTO :SN;

        IF (V$PUPIL_TYPE_ID = 10) THEN
        BEGIN
            SELECT F.V ||' '|| I.V ||' '|| O.V
            FROM VAL_GET(:V$PUPIL_ID, 55, 0, :I$USER_ID) F
            LEFT JOIN VAL_GET(:V$PUPIL_ID, 56, 0, :I$USER_ID) I ON 1=1
            LEFT JOIN VAL_GET(:V$PUPIL_ID, 57, 0, :I$USER_ID) O ON 1=1
            INTO :FIO;

            SELECT SUBSTRING(I.V FROM 1 FOR 1)||'. '||F.V
            FROM VAL_GET(:V$PUPIL_ID, 55, 0, :I$USER_ID) F
            LEFT JOIN VAL_GET(:V$PUPIL_ID, 56, 0, :I$USER_ID) I ON 1=1
            LEFT JOIN VAL_GET(:V$PUPIL_ID, 57, 0, :I$USER_ID) O ON 1=1
            INTO :FIOSHORT;

            SELECT V FROM VAL_GET(:V$PUPIL_ID, 89, 0, :I$USER_ID)
            INTO :DOB;
        END
        ELSE IF (V$PUPIL_TYPE_ID = 126) THEN
        BEGIN
            SELECT F.V ||' '|| I.V ||' '|| O.V
            FROM VAL_GET(:V$PUPIL_ID, 827, 0, :I$USER_ID) F
            LEFT JOIN VAL_GET(:V$PUPIL_ID, 828, 0, :I$USER_ID) I ON 1=1
            LEFT JOIN VAL_GET(:V$PUPIL_ID, 829, 0, :I$USER_ID) O ON 1=1
            INTO :FIO;

            SELECT SUBSTRING(I.V FROM 1 FOR 1)||'. '||F.V
            FROM VAL_GET(:V$PUPIL_ID, 827, 0, :I$USER_ID) F
            LEFT JOIN VAL_GET(:V$PUPIL_ID, 828, 0, :I$USER_ID) I ON 1=1
            LEFT JOIN VAL_GET(:V$PUPIL_ID, 829, 0, :I$USER_ID) O ON 1=1
            INTO :FIOSHORT;

            SELECT V FROM VAL_GET(:V$PUPIL_ID, 830, 0, :I$USER_ID)
            INTO :DOB;
        END

        IF (V$CLASS_TYPE_ID IN (81, 82, 83)) THEN
        BEGIN   
            CLASS_NAME = NULL;
            SELECT FIRST 1 M.NAME_IN
            FROM PERSON_MOVEMENTS M
            JOIN OBJECTS O ON O.OBJ_ID = M.GROUP_ID AND O.TYPE_ID IN (9, 187)
            WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :V$PUPIL_ID
            ORDER BY M.DATE_OUT DESC
            INTO :CLASS_NAME;

            IF (CLASS_NAME IS NULL) THEN
            BEGIN
                SELECT I
                FROM VAL_GET(:I$STAGE_ID, 43)
                INTO :V$STAGE_TYPE_ID;

                IF (V$STAGE_TYPE_ID = 26) THEN
                BEGIN
                    CLASS_NAME = '9';
                END
                ELSE IF (V$STAGE_TYPE_ID = 27) THEN
                BEGIN
                    CLASS_NAME = '11';
                END
            END
        END
        ELSE
        BEGIN
            SELECT CLASS_NAME FROM CERTIFICATE_CLASS_INFO_GET(:I$YEAR, :I$CLASS_ID, :I$STAGE_ID, :I$USER_ID, 0)
            INTO :CLASS_NAME;
        END
        
        SUBJECTSLEFT = '';
        MARKSLEFT = '';

        SUBJECTSRIGHT = '';
        MARKSRIGHT = '';

        V$COUNT = 0;
        FOR
            SELECT SUBJECT_NAME,
            CASE MARK
            WHEN '5' THEN '5 (отлично)'
            WHEN '4' THEN '4 (хорошо)'
            WHEN '3' THEN '3 (удовл.)'
            WHEN '2' THEN '2 (неудовл.)'
            ELSE MARK
            END MARK
            FROM CERTIFICATE_PUPIL_LOAD_SUBJECTS(:I$YEAR, :I$STAGE_ID, :I$CLASS_ID, :V$PUPIL_ID, :I$USER_ID)
            WHERE INCLUDING_TYPE_ID = 5381
            ORDER BY INCLUDING_TYPE_ID, SORT_ORDER, SUBJECT_NAME
            INTO :V$CURR_S, :V$CURR_M
        DO
        BEGIN
            IF ( V$COUNT < 21 ) THEN
            BEGIN
                SUBJECTSLEFT = SUBJECTSLEFT || V$CURR_S || ASCII_CHAR(13)||ASCII_CHAR(10);
                MARKSLEFT = MARKSLEFT || V$CURR_M || ASCII_CHAR(13)||ASCII_CHAR(10);
                V$COUNT = V$COUNT + 1;
            END
            ELSE
            BEGIN
                SUBJECTSRIGHT = SUBJECTSRIGHT || V$CURR_S || ASCII_CHAR(13)||ASCII_CHAR(10);
                MARKSRIGHT = MARKSRIGHT || V$CURR_M || ASCII_CHAR(13)||ASCII_CHAR(10);
                V$COUNT = V$COUNT + 1;
            END

            IF (V$COUNT = 42) THEN BREAK;
        END
    
        IF (CHAR_LENGTH(SUBJECTSLEFT) > 0) THEN
        BEGIN
            SUBJECTSLEFT = SUBSTRING (SUBJECTSLEFT FROM 1 FOR (CHAR_LENGTH(SUBJECTSLEFT) - 2) );
        END
        ELSE
        BEGIN
            SUBJECTSLEFT = NULL;
        END

        IF (CHAR_LENGTH(MARKSLEFT) > 0) THEN
        BEGIN
           MARKSLEFT = SUBSTRING (MARKSLEFT FROM 1 FOR (CHAR_LENGTH(MARKSLEFT) - 2) );
        END
        ELSE
        BEGIN
            MARKSLEFT = NULL;
        END

        IF (CHAR_LENGTH(SUBJECTSRIGHT) > 0) THEN
        BEGIN
            SUBJECTSRIGHT = SUBSTRING (SUBJECTSRIGHT FROM 1 FOR (CHAR_LENGTH(SUBJECTSRIGHT) - 2) );
        END
        ELSE
        BEGIN
            SUBJECTSRIGHT = NULL;
        END

        IF (CHAR_LENGTH(MARKSRIGHT) > 0) THEN
        BEGIN
            MARKSRIGHT = SUBSTRING (MARKSRIGHT FROM 1 FOR (CHAR_LENGTH(MARKSRIGHT) - 2) );
        END
        ELSE
        BEGIN
            MARKSRIGHT = NULL;
        END

        DOPOLSVED = '';
        FOR
            SELECT SUBJECT_NAME FROM CERTIFICATE_PUPIL_LOAD_SUBJECTS(:I$YEAR, :I$STAGE_ID, :I$CLASS_ID, :V$PUPIL_ID, :I$USER_ID)
            WHERE INCLUDING_TYPE_ID = 5382
            ORDER BY INCLUDING_TYPE_ID, SORT_ORDER, SUBJECT_NAME
            INTO :V$CURR_S
        DO
        BEGIN
            DOPOLSVED = DOPOLSVED || V$CURR_S || ', ';
        END
    
        IF (CHAR_LENGTH(DOPOLSVED) > 0) THEN
        BEGIN
            DOPOLSVED = SUBSTRING (DOPOLSVED FROM 1 FOR (CHAR_LENGTH(DOPOLSVED) - 2) );
        END
        ELSE
        BEGIN
            DOPOLSVED = NULL;
        END

        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CERT_STUDY_REG_LIST (
    I$YEAR BIGINT,
    I$CLASS_ID BIGINT,
    I$STAGE_ID BIGINT,
    I$USER_ID BIGINT = 1)
RETURNS (
    OBJ_ID BIGINT,
    PUPIL_ID BIGINT,
    DOC_ID BIGINT,
    VAL1 VARCHAR(100),
    VAL4 VARCHAR(1000),
    VAL5 DATE,
    VAL8 VARCHAR(255),
    VAL9 DATE,
    VAL12 DATE,
    GRADUATE_YEAR INTEGER,
    CLASS_ID BIGINT)
AS
declare variable V$FIO varchar(255);
declare variable V$I integer;
declare variable V$START_DATE date;
declare variable V$STOP_DATE date;
declare variable V$CERTIFICATE_REG_DATE date;
BEGIN
    V$START_DATE = '1.09.' || (I$YEAR - 1);
    V$STOP_DATE = '31.08.' || I$YEAR;

    FOR
        SELECT L234.OBJ_ID, V1872.VAL PUPIL_ID, L11.OBJ_ID DOC_ID, V566.VAL VAL9,
               -- 12
               L234.DATE_INS VAL12, EXTRACT(YEAR FROM V566.VAL) GRADUATE_YEAR, V1876.VAL
        FROM LINKS L234
        JOIN VALR V1872 ON V1872.OBJ_ID = L234.OBJ_ID AND V1872.PARAM_ID = 1872 AND V1872.IS_DEL = 0
        JOIN VALD V1876 ON V1876.OBJ_ID = L234.OBJ_ID AND V1876.PARAM_ID = 1876 AND V1876.IS_DEL = 0 AND V1876.VAL >= :V$START_DATE AND V1876.VAL <= :V$STOP_DATE
        JOIN LINKS L11 ON L11.PARENT_ID = V1872.VAL AND L11.OBJ_TYPE_ID = 11 AND L11.DATE_DEL IS NULL
        JOIN VALL V50 ON V50.OBJ_ID = L11.OBJ_ID AND V50.PARAM_ID = 50 AND V50.IS_DEL = 0 AND V50.LISTVAL_ID = 11137
        JOIN VALD V566 ON V566.OBJ_ID = L11.OBJ_ID AND V566.PARAM_ID = 566 AND V566.IS_DEL = 0 AND EXTRACT(YEAR FROM V566.VAL) = :I$YEAR
        WHERE /*L234.PARENT_ID = :I$STAGE_ID AND */ L234.OBJ_TYPE_ID = 234 AND L234.DATE_DEL IS NULL
        AND NOT EXISTS (
            SELECT FIRST 1 1
            FROM VALR V1877
            WHERE V1877.OBJ_ID = L234.OBJ_ID AND V1877.PARAM_ID = 1877 AND V1877.IS_DEL = 0)
        INTO :OBJ_ID,
             :PUPIL_ID,
             :DOC_ID,
             :VAL9, 
             :VAL12,
             :GRADUATE_YEAR,
             :V$CERTIFICATE_REG_DATE
    DO
    BEGIN
        CLASS_ID = NULL;

        SELECT FIRST 1 OBJ_ID
        FROM CERTIFICATE_REG_PUPIL_CLASS_GET(:PUPIL_ID, :V$CERTIFICATE_REG_DATE)
        WHERE OBJ_ID = :I$CLASS_ID OR :I$CLASS_ID IS NULL
        INTO :CLASS_ID;

        IF ((I$CLASS_ID IS NULL) OR :CLASS_ID IS NOT NULL) THEN
        BEGIN
            -- 1
            SELECT V
            FROM VAL_GET(:DOC_ID, 565, 0, :I$USER_ID)
            INTO :VAL1;
            -- 4, 5
            /*SELECT
                FIO VAL4,
                DOB VAL5
            FROM CERTIFICATE_PUPIL_INFO_READ(:OBJ_ID, :I$USER_ID)
            INTO :VAL4, :VAL5;*/
            SELECT V
            FROM VAL_GET(:PUPIL_ID, 2353)
            INTO :VAL4;

            SELECT V
            FROM VAL_GET(:PUPIL_ID, 89)
            INTO :VAL5;

            -- 8
            V$FIO = :VAL4;
            V$FIO = REPLACE(:V$FIO, ASCII_CHAR(13), ' ');
            V$FIO = REPLACE(:V$FIO, ASCII_CHAR(10), ' ');
            V$I = 1;
            WHILE (:V$I <= CHAR_LENGTH(:V$FIO) AND SUBSTRING(:V$FIO FROM :V$I FOR 1) <> ' ') DO
            BEGIN
                V$I = :V$I + 1;
            END
            VAL8 = TRIM(SUBSTRING(:V$FIO FROM 1 FOR :V$I));
            V$FIO = TRIM(SUBSTRING(:V$FIO FROM :V$I FOR 255));
            IF (:V$FIO > '') THEN
            BEGIN
                VAL8 = :VAL8||' '||SUBSTRING(:V$FIO FROM 1 FOR 1)||'.';
                V$I = 1;
                WHILE (:V$I <= CHAR_LENGTH(:V$FIO) AND SUBSTRING(:V$FIO FROM :V$I FOR 1) <> ' ') DO
                BEGIN
                    V$I = :V$I + 1;
                END
                V$FIO = TRIM(SUBSTRING(:V$FIO FROM :V$I FOR 255));
                IF (:V$FIO > '') THEN
                BEGIN
                    VAL8 = :VAL8||SUBSTRING(:V$FIO FROM 1 FOR 1)||'.';
                END
            END
            SUSPEND;
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CHANGER_CLASSES_LIST (
    I$USER_ID BIGINT)
RETURNS (
    STAGE_ID BIGINT,
    STAGE_TYPE_ID BIGINT,
    STAGE_KIND BIGINT,
    GRADE_ID BIGINT,
    GRADE_TYPE BIGINT,
    GRADE_TYPE_NAME VARCHAR(100),
    CLASS_ID BIGINT,
    CLASS_TYPE_ID BIGINT,
    CLASS_CAPTION VARCHAR(100),
    CLASS_NAME VARCHAR(100),
    CLASS_TYPE BIGINT,
    CLASS_TYPE_NAME VARCHAR(100),
    CLASS_OUT BIGINT,
    GLOBAL_TYPE VARCHAR(10),
    CLASS_SORT_ORDER DOUBLE PRECISION,
    STAGE_SORT_ORDER DOUBLE PRECISION,
    GRADE_SORT_ORDER DOUBLE PRECISION)
AS
declare variable V$SCHOOL_ID bigint;
declare variable V$GRADE_PARENT_ID bigint;
BEGIN
    SELECT FIRST 1 L.OBJ_ID
    FROM LINKS L
    WHERE L.PARENT_ID IS NULL AND L.OBJ_TYPE_ID = 2 AND L.DATE_DEL IS NULL
    INTO :V$SCHOOL_ID;

    IF (V$SCHOOL_ID IS NULL) THEN EXIT;

    FOR
        -- Предварительный прием ДОУ
        SELECT L173.OBJ_ID, NULL, NULL, 9, L173.OBJ_TYPE_ID, 2140
        FROM LINKS L173
        WHERE L173.PARENT_ID = :V$SCHOOL_ID AND L173.OBJ_TYPE_ID = 173 AND L173.DATE_DEL IS NULL

        UNION ALL

        -- Обычный предварительный прием
        SELECT L77.OBJ_ID, NULL, L9.OBJ_ID, L9.OBJ_TYPE_ID, L77.OBJ_TYPE_ID, 2141
        FROM LINKS L77
        JOIN LINKS L9 ON L9.PARENT_ID = L77.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
        WHERE L77.PARENT_ID = :V$SCHOOL_ID AND L77.OBJ_TYPE_ID = 77 AND L77.DATE_DEL IS NULL

        UNION ALL

        -- Все остальные существующие коллективы, кроме ОВЗ
        SELECT L7.OBJ_ID, L8.OBJ_ID, L9.OBJ_ID, L9.OBJ_TYPE_ID, L7.OBJ_TYPE_ID, LV.PARENT_ID
        FROM LINKS L7
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
        JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
        JOIN LISTVALS LV ON LV.LISTVAL_ID = V49.LISTVAL_ID
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL -- IN (9, 187)
        LEFT JOIN VALL V592 ON V592.OBJ_ID = L9.OBJ_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0
        WHERE L7.PARENT_ID = :V$SCHOOL_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL -- ((L9.OBJ_TYPE_ID <> 187) OR (V49.LISTVAL_ID IN (47, 48)))
            AND (V592.LISTVAL_ID IS NULL OR V592.LISTVAL_ID = 197)

        INTO :STAGE_ID, :GRADE_ID, :CLASS_ID, :CLASS_TYPE_ID, :STAGE_TYPE_ID, :V$GRADE_PARENT_ID
    DO
    BEGIN
        SELECT I FROM VAL_GET(:STAGE_ID, 43) INTO :STAGE_KIND;

        IF (V$GRADE_PARENT_ID = 2140) THEN GLOBAL_TYPE = 'DOU';
        ELSE IF (V$GRADE_PARENT_ID = 2141) THEN GLOBAL_TYPE = 'SCHOOL';
        ELSE IF (V$GRADE_PARENT_ID = 2142) THEN GLOBAL_TYPE = 'COLLEGE';
        ELSE GLOBAL_TYPE = 'UNKNOWN';

        SELECT V FROM VAL_GET(:CLASS_ID, IIF(:CLASS_TYPE_ID = 9, 54, 1652)) INTO :CLASS_NAME;

        CLASS_OUT = 3;
        IF ((GLOBAL_TYPE = 'SCHOOL') AND (GRADE_ID IS NOT NULL)) THEN
        BEGIN
            -- Исправлена ошибка 2015 года - нужно выбирать не экзаменационный признак, а обычный бинарный
            SELECT FIRST 1 V.LISTVAL_ID
            FROM VALL V
            --WHERE V.PARAM_ID IN (2388, 2418) AND V.OBJ_ID = :CLASS_ID AND V.IS_DEL = 0 AND V.LISTVAL_ID <> 11217
            WHERE V.PARAM_ID IN (1362, 1747) AND V.OBJ_ID = :CLASS_ID AND V.IS_DEL = 0
            INTO :CLASS_OUT;
        END

        IF (GRADE_ID IS NOT NULL) THEN
        BEGIN
            SELECT I, V
            FROM VAL_GET(:GRADE_ID, 49)
            INTO :GRADE_TYPE, :GRADE_TYPE_NAME;
        END
        ELSE
        BEGIN
            GRADE_TYPE = NULL;
            GRADE_TYPE_NAME = NULL;
        END

        IF ((CLASS_ID IS NOT NULL) AND (CLASS_TYPE_ID = 9))THEN
        BEGIN
            SELECT I, V
            FROM VAL_GET(:CLASS_ID, 592)
            INTO :CLASS_TYPE, :CLASS_TYPE_NAME;
        END
        ELSE
        BEGIN
            CLASS_TYPE = NULL;
            CLASS_TYPE_NAME = NULL;
        END

        IF (CLASS_ID IS NOT NULL) THEN
        BEGIN
            SELECT CAPTION, SORT_ORDER
            FROM OBJECT_CAPTION_GET(:CLASS_ID, NULL, NULL, :I$USER_ID)
            INTO :CLASS_CAPTION, :CLASS_SORT_ORDER;
        END
        ELSE
        BEGIN
            CLASS_CAPTION = 'Новая группа';
            CLASS_SORT_ORDER = 0;
        END

        IF ((CLASS_ID IS NOT NULL) OR EXISTS(SELECT FIRST 1 1 FROM LINKS WHERE PARENT_ID = :STAGE_ID AND DATE_DEL IS NULL)) THEN
        BEGIN
            SELECT SORT_ORDER FROM OBJECT_CAPTION_GET(:STAGE_ID, NULL, NULL, :I$USER_ID) INTO :STAGE_SORT_ORDER;
            SELECT SORT_ORDER FROM OBJECT_CAPTION_GET(:GRADE_ID, NULL, NULL, :I$USER_ID) INTO :GRADE_SORT_ORDER;

            SUSPEND;
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CHANGER_CLASS_ADD (
    I$GRADE_ID BIGINT,
    I$CLASS_NAME VARCHAR(4000),
    I$CLASS_TYPE BIGINT,
    I$USER_ID BIGINT = null)
RETURNS (
    CLASS_ID BIGINT)
AS
declare variable BLOB_ID bigint;
BEGIN
    SELECT OBJ_ID FROM OBJECT_ADD(:I$GRADE_ID, 9) INTO :CLASS_ID;
    SELECT BLOB_ID FROM VAL_ADD(54, :CLASS_ID, :I$CLASS_NAME, :I$USER_ID) INTO :BLOB_ID;

    IF (NOT I$CLASS_TYPE IS NULL) THEN
    BEGIN
        SELECT BLOB_ID FROM VAL_ADD(592, :CLASS_ID, :I$CLASS_TYPE, :I$USER_ID) INTO :BLOB_ID;
    END

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CHANGER_CLASS_NEXT (
    I$CLASS_ID BIGINT,
    I$GRADE_ID BIGINT,
    I$NEXT_GRADE_ID BIGINT,
    I$CLASS_NAME VARCHAR(4000),
    I$CLASS_TYPE BIGINT,
    I$ACTION_DATE DATE,
    I$ORDER_NUMBER VARCHAR(4000),
    I$ORDER_DATE DATE,
    I$USER_ID BIGINT = null)
AS
declare variable TYPE_ID bigint;
declare variable PUPIL_ID bigint;
declare variable BLOB_ID bigint;
declare variable MOVEMENT_ID bigint;
declare variable CAPTION varchar(4000);
declare variable GRADE_TYPE_ID bigint;
declare variable LINK_ID bigint;
declare variable PLAN_ID bigint;
declare variable PLAN_STAGE_ID bigint;
declare variable DT date;
declare variable X bigint;
declare variable V$OU_LICENCE_TYPE varchar(1);
BEGIN

    -- Удалено в связи переходом на новые реестры движения

    /*

    SELECT STATUS FROM OU_LICENCE_TYPE INTO :V$OU_LICENCE_TYPE;
    SELECT TYPE_ID FROM OBJECTS WHERE OBJ_ID = :I$CLASS_ID INTO :TYPE_ID;

    IF (TYPE_ID <> 9) THEN EXIT;

    DT = CAST(EXTRACT(YEAR FROM :I$ACTION_DATE) AS CHAR(4)) || '-05-31';

    -- Удаляем связь коллектива со старым уровнем обучения
    UPDATE LINKS
    SET DATE_DEL = CURRENT_TIMESTAMP
    WHERE OBJ_ID = :I$CLASS_ID AND PARENT_ID = :I$GRADE_ID AND DATE_DEL IS NULL;

    -- Связываем коллектив с новым уровнем обучения
    INSERT INTO LINKS (PARENT_ID, OBJ_ID, DATE_INS)
    VALUES (:I$NEXT_GRADE_ID, :I$CLASS_ID, CURRENT_TIMESTAMP);

    -- Обновляем название коллектива и тип
    SELECT BLOB_ID FROM VAL_ADD(54, :I$CLASS_ID, :I$CLASS_NAME, :I$USER_ID) INTO :BLOB_ID;
    SELECT BLOB_ID FROM VAL_ADD(592, :I$CLASS_ID, :I$CLASS_TYPE, :I$USER_ID) INTO :BLOB_ID;

    SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$CLASS_ID) INTO :CAPTION;

    SELECT I FROM VAL_GET(:I$NEXT_GRADE_ID, 49) INTO :GRADE_TYPE_ID;

    -- Прописываем записи движение всем ученикам
    FOR
        SELECT DISTINCT L10.OBJ_ID
        FROM LINKS L10
        WHERE L10.PARENT_ID = :I$CLASS_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        INTO :PUPIL_ID
    DO
    BEGIN
        MOVEMENT_ID = NULL;
        SELECT OBJ_ID FROM OBJECT_ADD(:PUPIL_ID, 76) INTO :MOVEMENT_ID;

        IF (V$OU_LICENCE_TYPE = 'D') THEN
        BEGIN
            SELECT BLOB_ID FROM VAL_ADD(432, :MOVEMENT_ID, '3278', :I$USER_ID) INTO :BLOB_ID;
        END
        ELSE
        BEGIN
            SELECT BLOB_ID FROM VAL_ADD(432, :MOVEMENT_ID, '808', :I$USER_ID) INTO :BLOB_ID;
        END

        -- Тип движения - перевод года
        SELECT BLOB_ID FROM VAL_ADD(452, :MOVEMENT_ID, '901', :I$USER_ID) INTO :BLOB_ID;

        UPDATE OR INSERT INTO VALD (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
        VALUES (433, :MOVEMENT_ID, :I$USER_ID, 0, :I$ACTION_DATE);

        UPDATE OR INSERT INTO VALD (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
        VALUES (435, :MOVEMENT_ID, :I$USER_ID, 0, :I$ORDER_DATE);

        SELECT BLOB_ID FROM VAL_ADD(434, :MOVEMENT_ID, CAST(:I$ORDER_NUMBER AS VARCHAR(4000)), :I$USER_ID) INTO :BLOB_ID;
        SELECT BLOB_ID FROM VAL_ADD(436, :MOVEMENT_ID, CAST(:GRADE_TYPE_ID AS VARCHAR(4000)), :I$USER_ID) INTO :BLOB_ID;
        SELECT BLOB_ID FROM VAL_ADD(437, :MOVEMENT_ID, :CAPTION, :I$USER_ID) INTO :BLOB_ID;
        SELECT BLOB_ID FROM VAL_ADD(438, :MOVEMENT_ID, CAST(:I$CLASS_ID AS VARCHAR(4000)), :I$USER_ID) INTO :BLOB_ID;

        IF (:V$OU_LICENCE_TYPE = 'U') THEN
        BEGIN
            SELECT BLOB_ID FROM VAL_ADD(2448, :MOVEMENT_ID, (SELECT I FROM DO_FUNC2(:MOVEMENT_ID, 2448, 70)), :I$USER_ID) INTO :BLOB_ID;
        END

        SELECT BLOB_ID FROM VAL_ADD(1350, :MOVEMENT_ID, CAST(:I$CLASS_TYPE AS VARCHAR(4000)), :I$USER_ID) INTO :BLOB_ID;
    END

    */
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CHANGER_CLEAR_ALL
AS
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$OBJ_ID2 BIGINT;
DECLARE VARIABLE V$TYPE_ID BIGINT;
DECLARE VARIABLE V$DEL_COUNT BIGINT;
DECLARE VARIABLE V$STAGE_ID BIGINT;
DECLARE VARIABLE V$IS_VD BIGINT;
DECLARE VARIABLE V$IS_GROUP BIGINT;
DECLARE VARIABLE V$IS_ADAPTIVE BIGINT;
DECLARE VARIABLE V$PTP_ID BIGINT;
DECLARE VARIABLE V$STATUS BIGINT;
DECLARE VARIABLE V$YEAR_ID BIGINT;
DECLARE VARIABLE V$Y INTEGER;
DECLARE VARIABLE V$YD DATE;
DECLARE VARIABLE V$CHAT_ID VARCHAR(400);
DECLARE VARIABLE V$S VARCHAR(400);
DECLARE VARIABLE V$T VARCHAR(100);
DECLARE VARIABLE V$T2 VARCHAR(100);
DECLARE VARIABLE V$OP_YEAR INTEGER;
BEGIN
    /* Очистка классных журналов */

    DELETE FROM CJ_ACCESS WHERE 1 = 1;

    /* Чистим замены и новый КЖ - все что не относится к текущему году */
    SELECT FIRST 1 L.LISTVAL_ID, L.COST
    FROM LISTVALS L
    WHERE L.IS_DEL = 0 AND L.LIST_ID = 29 AND L.COST = EXTRACT(YEAR FROM CURRENT_DATE)
    INTO :V$YEAR_ID, :V$Y;

    /* Фиксируем факт выполнения ПТП в итоговых отметках */
    FOR
      SELECT DISTINCT VM.MARK_ID, J.OBJ_ID, P.PTP_ID
      FROM CJ2_JOURNAL J
      JOIN PERSON_MOVEMENTS M ON M.DATE_DEL IS NULL AND M.GROUP_ID = J.GRADE_ID AND M.DATE_OUT IS NULL
      JOIN VALM VM ON VM.IS_DEL = 0 AND VM.PUPIL_ID = M.PERSON_ID AND VM.SUBJECT_ID = J.SUBJECT_ID AND VM.IS_NATIVE = 1
      JOIN CJ2_JOURNAL_PTP P ON P.DATE_DEL IS NULL AND P.CJ_ID = J.OBJ_ID AND P.APPROVAL_STATE = 2
      WHERE J.DATE_DEL IS NULL AND J.JOURNAL_TYPE = 0 AND J.YEAR_ID = :V$YEAR_ID
      ORDER BY 1
      INTO :V$OBJ_ID, :V$OBJ_ID2, :V$PTP_ID
    DO
    BEGIN
      UPDATE VALM
      SET
        PTP_HOURS = (SELECT P.PTP_HOURS FROM PTP P WHERE P.OBJ_ID = :V$OBJ_ID2),
        FACT_HOURS = (SELECT SUM(COALESCE(L.LESSON_HOURS, 1)) FROM CJ2_JOURNAL_LESSONS L WHERE L.DATE_DEL IS NULL AND L.CJ_ID = :V$OBJ_ID AND L.IS_COMPLETED = 1)
      WHERE
        MARK_ID = :V$OBJ_ID;
    END

    -- Фиксируем удаленные id предметных чатов Сферум в истории
    -- Про запас: не удаляем чаты, которые перенесены в новый учебный год
    -- смотрим даже удаленные журналы
    FOR
      SELECT J.OBJ_ID, J.CHAT_ID, J.STAGE_INDEX, J.SUBJECT_ID, J.JOURNAL_NAME
      FROM CJ2_JOURNAL J
      LEFT JOIN CJ2_JOURNAL J2 ON J2.DATE_DEL IS NULL AND J2.YEAR_ID <> J.YEAR_ID AND J2.CHAT_ID = J.CHAT_ID
      WHERE J.JOURNAL_TYPE = 0 AND J.YEAR_ID = :V$YEAR_ID AND J.CHAT_ID IS NOT NULL AND J2.OBJ_ID IS NULL
      INTO :V$OBJ_ID,  :V$CHAT_ID, :V$STAGE_ID, :V$PTP_ID, :V$S
    DO
    BEGIN
      -- 25 это номер поля в списке полей таблицы
      INSERT INTO HISTVALS
      (TABLE_NAME, OBJ_ID, PARAM_ID, OPT_ID, PARENT_ID, VAL, OLD_VAL)
      VALUES ('CJ2_JOURNAL', :V$OBJ_ID, -25, :V$STAGE_ID, :V$PTP_ID, :V$CHAT_ID, :V$S);
    END

    DELETE FROM CJ2_REPL_PROCESS WHERE 1 = 1;
    DELETE FROM CJ2_REPL_PLAN WHERE 1 = 1;

    DELETE FROM CJ2_MARK WHERE 1 = 1;
    DELETE FROM CJ2_CONTROL WHERE 1 = 1;
    DELETE FROM CJ2_JOURNAL_FINALS WHERE 1 = 1;
    DELETE FROM CJ2_JOURNAL_LESSONS WHERE 1 = 1;
    DELETE FROM CJ2_AUDIT WHERE 1 = 1;
    DELETE FROM CJ2_JOURNAL WHERE DATE_DEL IS NOT NULL OR (YEAR_ID <> :V$YEAR_ID OR YEAR_ID IS NULL);
    DELETE FROM CJ2_JOURNAL_PTP WHERE APPROVAL_STATE <> 2;

    /* Очистка протокола работы */

    DELETE FROM "LOG" WHERE 1 = 1;

    DELETE FROM USER_SETTINGS WHERE USER_ID IN (SELECT USER_ID FROM USERS WHERE DATE_DEL IS NOT NULL);
    DELETE FROM LUSERS WHERE USER_ID IN (SELECT USER_ID FROM USERS WHERE DATE_DEL IS NOT NULL);

    /* Очистка пользовательских профилей */

    DELETE FROM FILTERVALS
    WHERE FILTER_ID IN (
      SELECT FILTER_ID FROM FILTERS
      WHERE USER_ID IN (SELECT USER_ID FROM USERS WHERE DATE_DEL IS NOT NULL)
    );

    DELETE FROM FILTERFIELDS
    WHERE FILTERFIELDSSET_ID IN (
      SELECT FILTERFIELDSSET_ID FROM FILTERFIELDSSETS
      WHERE USER_ID IN (SELECT USER_ID FROM USERS WHERE DATE_DEL IS NOT NULL)
    );

    DELETE FROM FILTERFIELDSSETS
    WHERE USER_ID IN (SELECT USER_ID FROM USERS WHERE DATE_DEL IS NOT NULL);

    DELETE FROM FILTERS
    WHERE USER_ID IN (SELECT USER_ID FROM USERS WHERE DATE_DEL IS NOT NULL);

    DELETE FROM SEARCHFIELDS
    WHERE SEARCH_ID IN (
      SELECT SEARCH_ID FROM SEARCH
      WHERE USER_ID IN (SELECT USER_ID FROM USERS WHERE DATE_DEL IS NOT NULL)
    );

    DELETE FROM SEARCHTYPES
    WHERE SEARCH_ID IN (
      SELECT SEARCH_ID FROM SEARCH
      WHERE USER_ID IN (SELECT USER_ID FROM USERS WHERE DATE_DEL IS NOT NULL)
    );

    DELETE FROM SEARCH
    WHERE USER_ID IN (SELECT USER_ID FROM USERS WHERE DATE_DEL IS NOT NULL);

    -- Удаляем только юзеров, удаленных старше 1 года назад, чтобы выполнить требования СЗИ
    DELETE FROM USERS WHERE DATE_DEL IS NOT NULL AND DATE_DEL < DATEADD(-1 YEAR TO CURRENT_DATE);

    /* Нагрузки учебных коллективов и привязки к преподавателям - удаляем физически - но этого уже никогда не будет */
    DELETE FROM LINKS WHERE OBJ_TYPE_ID = 58;
    DELETE FROM LINKS WHERE PARENT_TYPE_ID = 58;
    DELETE FROM OBJECTS WHERE TYPE_ID = 58;

    /* Расписание - старые сущности, в 2022-23 их уже нет */
    UPDATE LINKS L SET DATE_DEL = CURRENT_TIMESTAMP WHERE L.OBJ_TYPE_ID = 70 AND L.DATE_DEL IS NULL;
    UPDATE LINKS L SET DATE_DEL = CURRENT_TIMESTAMP WHERE L.OBJ_TYPE_ID = 63 AND L.DATE_DEL IS NULL;
    UPDATE LINKS L SET DATE_DEL = CURRENT_TIMESTAMP WHERE L.OBJ_TYPE_ID = 4 AND L.DATE_DEL IS NULL;

    /* Уже неактуальные хвосты в расписании */
    DELETE FROM SCHEDULE_ITEMS WHERE DATE_DEL IS NOT NULL;
    EXECUTE PROCEDURE FIX_SCHEDULE_ITEMS;

    /* Учебные периоды - удаляем не все, а только с датой начала ранее 31.08 */
    /* Это уже неактуально, учебные периоды у нас остаются в истории КУГ, но переносим в архив сами КУГ */
    FOR
      SELECT L151.OBJ_ID
      FROM LINKS L151
      WHERE L151.PARENT_TYPE_ID = 150 AND L151.OBJ_TYPE_ID = 151 AND L151.DATE_DEL IS NULL
        AND NOT EXISTS (
          SELECT FIRST 1 1
          FROM LINKS L154
          JOIN VALD V1169 ON V1169.OBJ_ID = L154.OBJ_ID AND V1169.PARAM_ID = 1169 AND V1169.IS_DEL = 0 AND V1169.VAL >= '31.08.' || EXTRACT(YEAR FROM CURRENT_DATE)
          WHERE L154.PARENT_ID = L151.OBJ_ID AND L154.OBJ_TYPE_ID = 154 AND L154.DATE_DEL IS NULL
        )
      ORDER BY 1
      INTO :V$OBJ_ID
    DO
    BEGIN
      UPDATE LINKS L SET DATE_DEL = CURRENT_TIMESTAMP WHERE L.PARENT_ID = :V$OBJ_ID AND L.DATE_DEL IS NULL;
      UPDATE LINKS L SET DATE_DEL = CURRENT_TIMESTAMP WHERE L.OBJ_ID = :V$OBJ_ID AND L.DATE_DEL IS NULL;
    END

    FOR
      SELECT L481.OBJ_ID
      FROM LINKS L481
      JOIN VALI V3389 ON V3389.OBJ_ID = L481.OBJ_ID AND V3389.PARAM_ID = 3389 AND V3389.IS_DEL = 0 AND V3389.VAL <= :V$Y
      JOIN VALL V3390 ON V3390.OBJ_ID = L481.OBJ_ID AND V3390.PARAM_ID = 3390 AND V3390.IS_DEL = 0 AND V3390.LISTVAL_ID NOT IN (11717, 14261)
      WHERE L481.PARENT_TYPE_ID = 2 AND L481.OBJ_TYPE_ID = 481 AND L481.DATE_DEL IS NULL
      ORDER BY 1
      INTO :V$OBJ_ID
    DO
    BEGIN
      SELECT 1 FROM VAL_ADD(3390, :V$OBJ_ID, 14261) INTO :V$OBJ_ID2;
    END

    /* Связи коллектив - ПТП - удаляем физически (ранее было только для классов, теперь для всех видов коллективов) */
    DELETE FROM LINKS L WHERE L.PARENT_TYPE_ID IN (9, 256, 347) AND L.OBJ_TYPE_ID = 87;
    /* На всякий случай подчищаем повисшие хвосты ПТП */
    DELETE FROM LINKS L WHERE L.PARENT_TYPE_ID IS NULL AND L.OBJ_TYPE_ID = 87;

    /* Удаляем все некорневые ПТП, старый формат - удалено, их больше нет */

    /* Удаляем все некорневые ПТП, новый формат */
    FOR
      SELECT P.OBJ_ID
      FROM PTP P
      LEFT JOIN CJ2_JOURNAL_PTP J ON J.DATE_DEL IS NULL AND J.PTP_ID = P.OBJ_ID
      WHERE P.DATE_DEL IS NULL AND P.LEVEL_NUM > 0 AND J.OBJ_ID IS NULL
      ORDER BY 1
      INTO :V$OBJ_ID
    DO
    BEGIN
      DELETE FROM PTP_LESSONS WHERE PTP_ID = :V$OBJ_ID;
      DELETE FROM PTP WHERE OBJ_ID = :V$OBJ_ID;
    END

    /* Связи класс-период, их реально уже давно нет */
    UPDATE LINKS L SET DATE_DEL = CURRENT_TIMESTAMP WHERE L.PARENT_TYPE_ID = 154 AND L.OBJ_TYPE_ID = 9 AND L.DATE_DEL IS NULL;

    /* Расписание */
    DELETE FROM LINKS L WHERE L.PARENT_TYPE_ID = 63 AND L.OBJ_TYPE_ID = 6;
    DELETE FROM LINKS L WHERE L.PARENT_TYPE_ID = 63 AND L.OBJ_TYPE_ID = 60;

    /* Связи класс-учебный план - устаревшее с 2015 года; с 2016 связь идет только через ГУП */
    DELETE FROM LINKS L WHERE L.PARENT_TYPE_ID = 54 AND L.OBJ_TYPE_ID IN (9, 243);

    /**********************************************************/
    /* Экзамены */
    /**********************************************************/

    /* Алиасы классов */
    UPDATE VALS V SET V.IS_DEL = 1 WHERE V.PARAM_ID = 1363;

    /* Помещения ППЭ */
    UPDATE VALR V SET V.IS_DEL = 1 WHERE V.PARAM_ID = 748;
    UPDATE VALS V SET V.IS_DEL = 1 WHERE V.PARAM_ID = 749;
    UPDATE VALI V SET V.IS_DEL = 1 WHERE V.PARAM_ID = 750;
    UPDATE VALI V SET V.IS_DEL = 1 WHERE V.PARAM_ID = 1372;
    UPDATE LINKS L SET DATE_DEL = CURRENT_TIMESTAMP WHERE L.OBJ_TYPE_ID = 122 AND L.DATE_DEL IS NULL;
    UPDATE LINKS L SET DATE_DEL = CURRENT_TIMESTAMP WHERE L.OBJ_TYPE_ID = 121 AND L.DATE_DEL IS NULL;

    /* Преподаватели ППЭ */
    UPDATE VALL V SET V.LISTVAL_ID = 2989 WHERE V.PARAM_ID = 1376;
    UPDATE VALL V SET V.LISTVAL_ID = 3 WHERE V.PARAM_ID = 1395;
    UPDATE VALL V SET V.LISTVAL_ID = 3 WHERE V.PARAM_ID = 1396;

    /* Все учебные планы оставляем, убираем только учебные коллективы; внеурочные, индивидуальные планы и все планы ОП несоответствующего года переводим в проект */
    FOR
      SELECT L50.OBJ_ID, L50.OBJ_TYPE_ID, V2545.LISTVAL_ID, V2101.LISTVAL_ID, V2379.LISTVAL_ID, V2470.LISTVAL_ID, V3115.VAL, V374.SVAL
      FROM LINKS L2
      JOIN LINKS L69 ON L69.PARENT_ID = L2.OBJ_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL
      JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
      -- Год публикации ОП
      LEFT JOIN VALI V3115 ON V3115.OBJ_ID = L57.OBJ_ID AND V3115.PARAM_ID = 3115 AND V3115.IS_DEL = 0
      -- Адаптированность ОП
      LEFT JOIN VALL V2379 ON V2379.OBJ_ID = L57.OBJ_ID AND V2379.PARAM_ID = 2379 AND V2379.IS_DEL = 0
      -- УП
      JOIN LINKS L50 ON L50.PARENT_ID = L57.OBJ_ID AND L50.OBJ_TYPE_ID IN (50, 400) AND L50.DATE_DEL IS NULL
      -- Внеурочка - запоминаем признак
      LEFT JOIN VALL V2545 ON V2545.OBJ_ID = L50.OBJ_ID AND V2545.PARAM_ID IN (2545, 3022) AND V2545.IS_DEL = 0
      -- Групповой или индивидуальный план
      LEFT JOIN VALL V2101 ON V2101.OBJ_ID = L50.OBJ_ID AND V2101.PARAM_ID IN (2101, 3016) AND V2101.IS_DEL = 0
      -- Текущий статус
      LEFT JOIN VALL V2470 ON V2470.OBJ_ID = L50.OBJ_ID AND V2470.PARAM_ID IN (2470, 3013) AND V2470.IS_DEL = 0
      -- Название
      LEFT JOIN VALS V374 ON V374.OBJ_ID = L50.OBJ_ID AND V374.PARAM_ID IN (374, 3012) AND V374.IS_DEL = 0
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      ORDER BY 1
      INTO :V$OBJ_ID, :V$TYPE_ID, :V$IS_VD, :V$IS_GROUP, :V$IS_ADAPTIVE, :V$STATUS, :V$OP_YEAR, :V$S
    DO
    BEGIN
      -- Удаляем учебные коллективы
      -- Раньше оставляли ГУП, в которых нет ни одного ученика - это проекты на следующий учебный год
      -- это было неправильно, поскольку после смены статуса УП их больше не удалить и надо восстанавливать статус
      FOR
        SELECT L54.OBJ_ID
        FROM LINKS L54
        WHERE L54.PARENT_ID = :V$OBJ_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
        ORDER BY 1
        INTO :V$STAGE_ID
      DO
      BEGIN
        -- По идее ни 51, ни 56 тут быть уже не должно, остаются только 256 ?
        FOR
          SELECT OBJ_ID, OBJ_TYPE_ID
          FROM LINKS
          WHERE PARENT_ID = :V$STAGE_ID AND OBJ_TYPE_ID NOT IN (51, 56)
          ORDER BY 1
          INTO :V$OBJ_ID2, :V$TYPE_ID
        DO
        BEGIN
          -- Удаляем:
          -- 1. Все что не ГУП (хотя это уже неактуально)
          -- 2. Все ГУП, где есть ученики
          -- 3. Все ГУП по критерию, где УП будет переводиться в статус проекта, но без проверки статуса (в проекте их и так быть не должно)
          IF(V$TYPE_ID <> 256 OR EXISTS(SELECT 1 FROM LINKS L10 WHERE L10.PARENT_ID = :V$OBJ_ID2 AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL)
            OR (V$IS_VD = 2 OR V$IS_GROUP IN (5466, 12904) OR V$OP_YEAR IS NULL OR V$OP_YEAR <> V$Y)
          ) THEN
          BEGIN
            UPDATE LINKS SET EXT_OBJ_ID = NULL WHERE EXT_OBJ_ID = :V$OBJ_ID2 AND :V$TYPE_ID = 256;
            DELETE FROM LINKS WHERE PARENT_ID = :V$STAGE_ID AND OBJ_ID = :V$OBJ_ID2;
            DELETE FROM OBJECTS WHERE OBJ_ID = :V$OBJ_ID2;
          END
        END
      END

      -- Переводим в проект все планы ВД и индивидуальные, а также групповые с несоответствующим годом публикации
      V$T = '%' || V$Y || '-' || (V$Y + 1) || '%';
      V$T2 = '%' || MOD(V$Y, 100) || '-' || MOD(V$Y + 1, 100) || '%';
      IF((V$IS_VD = 2 OR V$IS_GROUP IN (5466, 12904) OR V$OP_YEAR IS NULL OR (V$OP_YEAR <> V$Y AND V$S NOT LIKE :V$T AND V$S NOT LIKE :V$T2))
        AND (V$STATUS IS NULL OR V$STATUS = 11715)) THEN
      BEGIN
        SELECT BLOB_ID FROM VAL_ADD(IIF(:V$TYPE_ID = 50, 2470, 3013), :V$OBJ_ID, 11716) INTO :V$DEL_COUNT;
        SELECT BLOB_ID FROM VAL_ADD(IIF(:V$TYPE_ID = 50, 2472, 3018), :V$OBJ_ID, '') INTO :V$DEL_COUNT;
        SELECT BLOB_ID FROM VAL_ADD(IIF(:V$TYPE_ID = 50, 2473, 3019), :V$OBJ_ID, '') INTO :V$DEL_COUNT;
      END

    END

    /*
    Физическое удаление вообще всех временных коллективов и их реестров движений - потоков, подгрупп, групп переменного состава
    Удаление ГУП делаем только тех, которые висят в удаленных этапах, или удаленных планах, или где есть учащиеся
    */
    FOR
      SELECT L.OBJ_ID
      FROM LINKS L
      WHERE L.OBJ_TYPE_ID = 256 AND (
        L.DATE_DEL IS NOT NULL
        OR NOT EXISTS(
          SELECT 1
          FROM LINKS LP54
          JOIN LINKS LP400 ON LP400.OBJ_ID = LP54.PARENT_ID AND LP400.PARENT_TYPE_ID = 400 AND LP400.DATE_DEL IS NULL
          JOIN LINKS LP57 ON LP57.OBJ_ID = LP400.PARENT_ID AND LP57.PARENT_TYPE_ID = 57 AND LP57.DATE_DEL IS NULL
          JOIN LINKS LP69 ON LP69.OBJ_ID = LP57.PARENT_ID AND LP69.PARENT_TYPE_ID = 69 AND LP69.DATE_DEL IS NULL
          JOIN LINKS LP2 ON LP2.OBJ_ID = LP69.PARENT_ID AND LP2.PARENT_TYPE_ID = 2 AND LP2.DATE_DEL IS NULL
          WHERE LP54.OBJ_ID = L.OBJ_ID AND LP54.PARENT_TYPE_ID = 54 AND LP54.DATE_DEL IS NULL
        )
        OR EXISTS(SELECT 1 FROM LINKS L10 WHERE L10.PARENT_ID = :V$OBJ_ID2 AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL)
      )
      INTO :V$OBJ_ID2
    DO
    BEGIN
      UPDATE LINKS SET EXT_OBJ_ID = NULL WHERE EXT_OBJ_ID = :V$OBJ_ID2;
      DELETE FROM OBJECTS WHERE OBJ_ID = :V$OBJ_ID2;
    END

    -- записи движения сами почистятся, кроме случая с ГПД - их надо чистить
    DELETE FROM OBJECTS WHERE TYPE_ID IN (258, 346, 347, 348, 178, 47, 48);
    DELETE FROM OBJECTS O WHERE O.TYPE_ID = 179 AND NOT EXISTS (SELECT FIRST 1 1 FROM CJ2_JOURNAL J WHERE J.GRADE_ID = O.OBJ_ID AND J.YEAR_ID = :V$YEAR_ID);

    /* По ГПД и ДО (#46) удаляем только связи с коллективами, но сами коллективы оставляем */
    DELETE FROM LINKS WHERE PARENT_TYPE_ID = 46 AND OBJ_TYPE_ID IN (9, 10);
    DELETE FROM PERSON_MOVEMENTS M WHERE EXISTS(SELECT FIRST 1 1 FROM OBJECTS O WHERE O.OBJ_ID = M.GROUP_ID AND O.TYPE_ID = 46);

    -- Полностью физически удаляем связи УМК - вне зависимости от актуальности УП
    DELETE FROM LINKS WHERE PARENT_TYPE_ID = 56 AND OBJ_TYPE_ID = 107;
    DELETE FROM PLAN_RESOURCES WHERE 1 = 1;

    /* Удаляем привязки ОП к помещениям */
    DELETE FROM LINKS WHERE PARENT_TYPE_ID = 61 AND OBJ_TYPE_ID = 57;

    /* Удаляем привязки ОП к расписанию занятий - пока вообще все какие есть */
    DELETE FROM LINKS LP3 WHERE LP3.PARENT_TYPE_ID = 3 AND LP3.OBJ_TYPE_ID = 57;

   /* Чистка базы от удаленных предметов, помещений, ПТП, УП, ОП - там где не осталось живых ссылок сверху */
   FOR
       SELECT LXX.OBJ_ID, LXX.OBJ_TYPE_ID
       FROM LINKS LXX
       WHERE LXX.OBJ_TYPE_ID IN (51, 61, 87, 88, 89, 90, 50, 57, 49, 54, 56)
       ORDER BY IIF(LXX.OBJ_TYPE_ID = 51, 9999, LXX.OBJ_TYPE_ID) DESC -- сначала предметы, затем все остальное, чтобы корректно удалились ПТП
       INTO :V$OBJ_ID, :V$TYPE_ID
   DO
   BEGIN

       V$DEL_COUNT = 0;
       SELECT FIRST 1 1
       FROM LINKS LP
       WHERE LP.OBJ_ID = :V$OBJ_ID AND LP.DATE_DEL IS NULL
       INTO :V$DEL_COUNT;

       -- Проверяем также ссылки через VALR - чтобы и сам параметр был живой, и имелась хотя бы одна живая ссылка
       IF(V$DEL_COUNT = 0) THEN
       BEGIN
         SELECT FIRST 1 1
         FROM VALR VP
         JOIN LINKS LP ON LP.OBJ_ID = VP.OBJ_ID AND LP.DATE_DEL IS NULL
         WHERE VP.VAL = :V$OBJ_ID AND VP.IS_DEL = 0
         INTO :V$DEL_COUNT;
       END

       -- Удаляем объект
       IF(V$DEL_COUNT = 0) THEN
       BEGIN
         DELETE FROM OBJECTS WHERE OBJ_ID = :V$OBJ_ID;
       END

   END

   /* Для всех учеников удаляем выбор предметов по выбору и ВД */
   DELETE FROM VALS WHERE PARAM_ID IN (2838, 3466);

   /* Удаляем записи СКУД и Питания */
   DELETE FROM SCUD_RAW WHERE 1 = 1;
   DELETE FROM SOP_RAW WHERE 1 = 1;

   -- Удаляем назначение классных руководителей для всех действующих классов (в выпустившихся оставляем), а также в пользователях
   -- Внимание: это неправильно сработало бы в УДОД, но там год не переводится таким способом
   -- Нельзя просто так сбрасывать ROOT_OBJ_ID, это откроет полный доступ у тех, у кого раньше был ограниченный, ставим его в кривое значение
   UPDATE LUSERS SET ROOT_OBJ_ID = 0 WHERE ROOT_OBJ_ID IS NOT NULL;

   DELETE FROM VALR V53
   WHERE V53.PARAM_ID = 53 AND V53.IS_DEL = 0 AND EXISTS (
     SELECT FIRST 1 1
     FROM LINKS LPG
     WHERE LPG.OBJ_ID = V53.OBJ_ID AND LPG.PARENT_TYPE_ID = 8 AND LPG.DATE_DEL IS NULL
   );

   -- Удаляем физически хвосты ПТП, удаленные более года назад
   V$YD = '15.08.' || (V$Y - 1);
   DELETE FROM PTP WHERE DATE_DEL < :V$YD;

   -- Удаляем записи с проблемами dataid для сотрудников, уволенных более года назад
   -- чтобы не висели в отчете
   FOR
     SELECT LL.OBJ_ID
     FROM LINKS L2
     JOIN LINKS L84 ON L84.PARENT_ID = L2.OBJ_ID AND L84.OBJ_TYPE_ID = 84 AND L84.DATE_DEL IS NULL
     JOIN LINKS L14 ON L14.PARENT_ID = L84.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL AND L14.DATE_INS < :V$YD
     JOIN SYNC_LOG LL ON LL.PERSON_ID = L14.OBJ_ID AND (LL.MSG IS NOT NULL OR LL.VER_MSG IS NOT NULL)
     WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
     ORDER BY 1
     INTO :V$OBJ_ID
   DO
   BEGIN
     UPDATE SYNC_LOG
     SET MSG = NULL, VER_MSG = NULL
     WHERE OBJ_ID = :V$OBJ_ID;
   END

   -- Удаляем с концами папку старых периодов
   DELETE FROM LINKS WHERE PARENT_TYPE_ID = 150;
   DELETE FROM OBJECTS WHERE TYPE_ID = 150;

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CHANGER_CLEAR_ENTRANCE_GRADES
AS
declare variable V$OBJ_ID bigint;
declare variable V$PARENT_ID bigint;
declare variable V$DEL_COUNT bigint;
declare variable SCHOOL_ID bigint;
declare variable YEAR_LV bigint;
declare variable YEAR_STR varchar(100);
declare variable TMP bigint;
BEGIN

    -- Чистим папки зачисляемых
    FOR
        SELECT OBJ_ID, PARENT_ID
        FROM LINKS
        WHERE OBJ_TYPE_ID = 290 AND DATE_DEL IS NULL
        INTO :V$OBJ_ID, :V$PARENT_ID
    DO
    BEGIN
        SELECT DEL_COUNT
        FROM OBJECT_DEL(:V$PARENT_ID, :V$OBJ_ID)
        INTO :V$DEL_COUNT;
    END

    -- Переводим учебный год
    SELECT FIRST 1 OBJ_ID
    FROM LINKS
    WHERE PARENT_ID IS NULL AND OBJ_TYPE_ID = 2 AND DATE_DEL IS NULL
    INTO :SCHOOL_ID;

    IF(SCHOOL_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не найден объект образовательной организации';

    YEAR_STR = EXTRACT(YEAR FROM CURRENT_DATE) || '-' || (EXTRACT(YEAR FROM CURRENT_DATE) + 1);

    SELECT LV.LISTVAL_ID
    FROM LISTVALS LV
    JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU' AND R.VAL = :YEAR_STR
    WHERE LV.IS_DEL = 0 AND LV.LIST_ID = 29
    INTO :YEAR_LV;

    IF(YEAR_LV IS NULL) THEN EXCEPTION DATA_ERROR 'Не удалось найти подходящий объект справочника для идентификации учебного года ' || YEAR_STR;

    SELECT BLOB_ID FROM VAL_ADD(1236, :SCHOOL_ID, :YEAR_LV) INTO :TMP;

END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CHANGER_CREATE_GUP (
    PLAN_ID BIGINT,
    GRADE_ID BIGINT,
    GUP_NAME VARCHAR(1000))
RETURNS (
    GUP_ID BIGINT)
AS
declare variable V$STAGE_ID bigint;
declare variable TMP bigint;
begin
  -- Ищем этап УП
  SELECT FIRST 1 L54.OBJ_ID
  FROM LINKS L54
  JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0 AND V381.LISTVAL_ID = :GRADE_ID
  WHERE L54.PARENT_ID = :PLAN_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
  INTO :V$STAGE_ID;

  IF(V$STAGE_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не удалось найти требуемый этап в учебном плане ' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:PLAN_ID));

  SELECT OBJ_ID FROM OBJECT_ADD(:V$STAGE_ID, 256) INTO :GUP_ID;
  SELECT BLOB_ID FROM VAL_ADD(2162, :GUP_ID, :GUP_NAME) INTO :TMP;

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CHANGER_DELETING_PLANS_LIST RETURNS (
    PLAN_ID BIGINT,
    CAPTION VARCHAR(1000))
AS
declare variable HAS_PUPILS integer;
begin
  -- Функция была актуальна в 2017-м году для актуализации УП, более не применяется

  FOR
    SELECT L50.OBJ_ID, C.CAPTION
    FROM LINKS L2
    -- Образовательные программы
    JOIN LINKS L69 ON L69.PARENT_ID = L2.OBJ_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL
    -- Фильтр - только программы общего образования
    JOIN VALL V2450 ON V2450.OBJ_ID = L69.OBJ_ID AND V2450.PARAM_ID = 2450 AND V2450.IS_DEL = 0 AND V2450.LISTVAL_ID = 11385
    -- Образовательная программа + признак адаптированности (только неадаптированные)
    JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
    LEFT JOIN VALL V2379 ON V2379.OBJ_ID = L57.OBJ_ID AND V2379.PARAM_ID = 2379 AND V2379.IS_DEL = 0
    -- УП
    JOIN LINKS L50 ON L50.PARENT_ID = L57.OBJ_ID AND L50.OBJ_TYPE_ID = 50 AND L50.DATE_DEL IS NULL
    -- Название УП
    LEFT JOIN OBJECT_CAPTION_GET(L50.OBJ_ID) C ON 1 = 1
    -- Уровень (подвид) образования
    JOIN VALL V1594 ON V1594.OBJ_ID = L57.OBJ_ID AND V1594.PARAM_ID = 1594 AND V1594.IS_DEL = 0
    -- Внеурочка - запоминаем признак
    LEFT JOIN VALL V2545 ON V2545.OBJ_ID = L50.OBJ_ID AND V2545.PARAM_ID = 2545 AND V2545.IS_DEL = 0
    -- Групповой или индивидуальный план
    LEFT JOIN VALL V2101 ON V2101.OBJ_ID = L50.OBJ_ID AND V2101.PARAM_ID = 2101 AND V2101.IS_DEL = 0
    -- Удалению подлежат только общеобразовательные групповые УП неадаптированных ОП
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND (V2545.LISTVAL_ID = 3) AND (V2101.LISTVAL_ID IS NULL OR V2101.LISTVAL_ID = 5465)
        AND (V2379.LISTVAL_ID IS NULL OR V2379.LISTVAL_ID = 11187)
    INTO :PLAN_ID, :CAPTION
  DO
  BEGIN
    HAS_PUPILS = 0;
    SELECT FIRST 1 1
    FROM LINKS L54
    JOIN LINKS L256 ON L256.PARENT_ID = L54.OBJ_ID AND L256.OBJ_TYPE_ID = 256 AND L256.DATE_DEL IS NULL
    JOIN LINKS L10 ON L10.PARENT_ID = L256.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    WHERE L54.PARENT_ID = :PLAN_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
    INTO :HAS_PUPILS;

    IF(HAS_PUPILS <> 0) THEN SUSPEND;
  END
end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CHANGER_GRADES_LIST (
    I$USER_ID BIGINT)
RETURNS (
    STAGE_ID BIGINT,
    STAGE_TYPE_ID BIGINT,
    STAGE_KIND BIGINT,
    GRADE_ID BIGINT,
    GRADE_TYPE_ID BIGINT,
    GRADE_CAPTION VARCHAR(4000),
    GRADE_NAME VARCHAR(255),
    GLOBAL_TYPE VARCHAR(10),
    SORT_ORDER DOUBLE PRECISION,
    STAGE_SORT_ORDER DOUBLE PRECISION,
    TAG VARCHAR(100),
    HIDDEN SMALLINT)
AS
declare variable V$SCHOOL_ID bigint;
declare variable V$GRADE_PARENT_ID bigint;
declare variable V$OU_LICENCE_TYPE varchar(1);
declare variable LANG_CODE varchar(2);
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :LANG_CODE;

    SELECT STATUS FROM OU_LICENCE_TYPE INTO :V$OU_LICENCE_TYPE;
    FOR
        SELECT FIRST 1
               L.OBJ_ID
        FROM LINKS L
        WHERE L.PARENT_ID IS NULL
        AND L.DATE_DEL IS NULL
        AND L.OBJ_TYPE_ID = 2
        INTO :V$SCHOOL_ID
    DO
    BEGIN
        FOR
            SELECT L77.OBJ_ID,
                   L77.OBJ_TYPE_ID,
                   L290.OBJ_ID,
                   LV2346.PARENT_ID,
                   COALESCE((
                    SELECT FIRST 1 1
                    FROM LINKS L7
                    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.DATE_DEL IS NULL AND L8.OBJ_TYPE_ID = 8
                    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
                    JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
                    JOIN LISTVALS LV49 ON LV49.LISTVAL_ID = V49.LISTVAL_ID AND CAST(LV49.TAG AS SMALLINT) = CAST(LV2346.TAG AS SMALLINT) - 1
                    WHERE L7.PARENT_ID = :V$SCHOOL_ID AND L7.DATE_DEL IS NULL AND L7.OBJ_TYPE_ID = 7
                ), 0)
            FROM LINKS L77

            JOIN LINKS L290
            ON L290.PARENT_ID = L77.OBJ_ID
            AND L290.DATE_DEL IS NULL
            AND L290.OBJ_TYPE_ID = 290

            JOIN VALL V2346
            ON V2346.OBJ_ID = L290.OBJ_ID
            AND V2346.PARAM_ID = 2346
            AND V2346.IS_DEL = 0

            JOIN LISTVALS LV2346
            ON LV2346.LISTVAL_ID = V2346.LISTVAL_ID

            WHERE L77.PARENT_ID = :V$SCHOOL_ID
            AND L77.DATE_DEL IS NULL
            AND L77.OBJ_TYPE_ID = 77

            AND EXISTS (
                SELECT FIRST 1 1
                FROM LINKS L10
                WHERE L10.PARENT_ID = L290.OBJ_ID
                AND L10.OBJ_TYPE_ID = 10
                AND L10.DATE_DEL IS NULL
            )

/*            AND NOT EXISTS (
                SELECT FIRST 1 1
                FROM LINKS L7

                JOIN LINKS L8
                ON L8.PARENT_ID = L7.OBJ_ID
                AND L8.DATE_DEL IS NULL
                AND L8.OBJ_TYPE_ID = 8

                JOIN LINKS L9
                ON L9.PARENT_ID = L8.OBJ_ID
                AND L9.OBJ_TYPE_ID = 9
                AND L9.DATE_DEL IS NULL

                JOIN VALL V49
                ON V49.OBJ_ID = L8.OBJ_ID
                AND V49.PARAM_ID = 49
                AND V49.IS_DEL = 0

                JOIN LISTVALS LV49
                ON LV49.LISTVAL_ID = V49.LISTVAL_ID
                AND CAST(LV49.TAG AS SMALLINT) = CAST(LV2346.TAG AS SMALLINT) - 1

                WHERE L7.PARENT_ID = :V$SCHOOL_ID
                AND L7.DATE_DEL IS NULL
                AND L7.OBJ_TYPE_ID = 7
            )*/

            UNION ALL

            SELECT L7.OBJ_ID,
                   L7.OBJ_TYPE_ID,
                   L8.OBJ_ID,
                   LV.PARENT_ID,
                   0
            FROM LINKS L7

            JOIN LINKS L8
            ON L8.PARENT_ID = L7.OBJ_ID
            AND L8.DATE_DEL IS NULL
            AND L8.OBJ_TYPE_ID = 8

            JOIN VALL V49
            ON V49.OBJ_ID = L8.OBJ_ID
            AND V49.PARAM_ID = 49
            AND V49.IS_DEL = 0

            JOIN LISTVALS LV
            ON LV.LISTVAL_ID = V49.LISTVAL_ID

            WHERE L7.PARENT_ID = :V$SCHOOL_ID
            AND L7.DATE_DEL IS NULL
            AND L7.OBJ_TYPE_ID = 7

            INTO :STAGE_ID,
                 :STAGE_TYPE_ID,
                 :GRADE_ID,
                 :V$GRADE_PARENT_ID,
                 :HIDDEN
        DO
        BEGIN
            SELECT I
            FROM VAL_GET(:STAGE_ID, 43)
            INTO :STAGE_KIND;

            IF (V$OU_LICENCE_TYPE = 'D') THEN
            BEGIN
                GLOBAL_TYPE = 'DOU';
            END
            ELSE IF (V$OU_LICENCE_TYPE = 'C') THEN
            BEGIN
                GLOBAL_TYPE = 'COLLEGE';
            END
            ELSE IF (V$OU_LICENCE_TYPE = 'U') THEN
            BEGIN
                GLOBAL_TYPE = 'UDOD';
            END
            ELSE IF (V$OU_LICENCE_TYPE = 'O') THEN
            BEGIN
                GLOBAL_TYPE = 'SCHOOL';
            END
            /*IF (V$GRADE_PARENT_ID = 2140) THEN
            BEGIN
                GLOBAL_TYPE = 'DOU';
            END
            ELSE IF (V$GRADE_PARENT_ID = 2141) THEN
            BEGIN
                GLOBAL_TYPE = 'SCHOOL';
            END*/
            ELSE
            BEGIN
                GLOBAL_TYPE = 'UNKNOWN';
            END

            SELECT FIRST 1
                   CASE WHEN :V$OU_LICENCE_TYPE IN ('O','C') THEN LV.TAG ELSE R.VAL END,
                   LV.LISTVAL_ID,
                   LV.TAG
            FROM VALL V
            INNER JOIN LISTVALS LV
            ON V.LISTVAL_ID = LV.LISTVAL_ID

            LEFT JOIN RES_GET(LV.RES_ID,  :LANG_CODE) R ON 1=1

            WHERE V.PARAM_ID IN (49, 2346)
            AND   V.OBJ_ID = :GRADE_ID
            INTO :GRADE_NAME,
                 :GRADE_TYPE_ID,
                 :TAG;

            IF ((STAGE_TYPE_ID = 77) AND (GRADE_TYPE_ID IN (33, 3262))) THEN
            BEGIN
                HIDDEN = 1;
            END

            SELECT CAPTION,SORT_ORDER
            FROM OBJECT_CAPTION_GET(:GRADE_ID, NULL, NULL, :I$USER_ID)
            INTO :GRADE_CAPTION,:SORT_ORDER;

            SELECT SORT_ORDER
            FROM OBJECT_CAPTION_GET(:STAGE_ID, NULL, NULL, :I$USER_ID)
            INTO :STAGE_SORT_ORDER;
            SUSPEND;
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CHANGER_GRADE_ADD (
    I$STAGE_ID BIGINT,
    I$GRADE_TYPE_ID BIGINT,
    I$USER_ID BIGINT = null)
RETURNS (
    GRADE_ID BIGINT)
AS
declare variable BLOB_ID bigint;
BEGIN
    SELECT OBJ_ID
    FROM OBJECT_ADD(:I$STAGE_ID, 8)
    INTO :GRADE_ID;

    SELECT BLOB_ID
    FROM VAL_ADD(49, :GRADE_ID, :I$GRADE_TYPE_ID, :I$USER_ID)
    INTO :BLOB_ID;

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CHANGER_MONITORING_CLEANUP
AS
DECLARE VARIABLE V$OBJ162_ID BIGINT;
DECLARE VARIABLE V$BLOB_ID BIGINT;
begin

    -- Удаляем все поля из всех старых объектов мониторинга (сами объекты остаются - надеемся что их ровно 1)
    FOR
        SELECT OBJ_ID FROM OBJECTS WHERE TYPE_ID = 162
        INTO :V$OBJ162_ID
    DO
    BEGIN
        DELETE FROM VALI WHERE OBJ_ID = :V$OBJ162_ID;
        DELETE FROM VALF WHERE OBJ_ID = :V$OBJ162_ID;
        DELETE FROM VALD WHERE OBJ_ID = :V$OBJ162_ID;
        DELETE FROM VALT WHERE OBJ_ID = :V$OBJ162_ID;
        DELETE FROM VALDT WHERE OBJ_ID = :V$OBJ162_ID;
        DELETE FROM VALS WHERE OBJ_ID = :V$OBJ162_ID AND PARAM_ID <> 1494; -- оставляем строку названия
        DELETE FROM VALL WHERE OBJ_ID = :V$OBJ162_ID;
        SELECT BLOB_ID FROM VAL_ADD(1494, :V$OBJ162_ID, 'Мониторинг') INTO :V$BLOB_ID;
    END

    -- Удаляем все подчиненные объекты всех мониторингов, вместе с ними удалятся и поля
    -- кроме УП, этапов УП, счетчиков ДО по направленностям !!!
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.PARENT_TYPE_ID = 162 AND L.OBJ_TYPE_ID NOT IN (54, 400, 265, 368)
        ORDER BY 1
        INTO :V$OBJ162_ID
    DO
    BEGIN
        DELETE FROM OBJECTS WHERE OBJ_ID = :V$OBJ162_ID;
    END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CHANGER_MONITORING_PROCCESS (
    I$ACTION_DATE DATE,
    I$USER_ID BIGINT)
RETURNS (
    TAG VARCHAR(400),
    VAL VARCHAR(6000),
    DEST_ID BIGINT)
AS
declare variable SCHOOL_ID bigint;
declare variable V$YEAR_VAL varchar(100);
declare variable V$YEAR_ID bigint;
declare variable V$OBJ238_ID bigint;
declare variable V$BLOB_ID bigint;
declare variable V$OBJ162_ID bigint;
declare variable V$OBJ265_ID bigint;
declare variable V$OBJ268_ID bigint;
declare variable LANG_CODE varchar(2);
declare variable N integer;
BEGIN
    -- ID ОУ
    SELECT FIRST 1 L.OBJ_ID, V1236.LISTVAL_ID, R.VAL
    FROM LINKS L
    JOIN VALL V1236 ON V1236.OBJ_ID = L.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
    JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
    WHERE L.OBJ_TYPE_ID = 2 AND L.DATE_DEL IS NULL
    INTO :SCHOOL_ID, :V$YEAR_ID, :V$YEAR_VAL;

    IF(SCHOOL_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Отсутствует объект образовательной организации, либо не задан текущий учебный год. Перевод года невозможен';

    -- Проверяем, что архив за прошлый год если имеется - то в единственном числе
    N = 0;

    SELECT COUNT(*)
    FROM LINKS L
    JOIN VALL V1895 ON V1895.OBJ_ID = L.OBJ_ID AND V1895.PARAM_ID = 1895 AND V1895.IS_DEL = 0 AND V1895.LISTVAL_ID = :V$YEAR_ID
    WHERE L.DATE_DEL IS NULL AND L.OBJ_TYPE_ID = 238
    INTO :N;

    IF(N > 1) THEN EXCEPTION DATA_ERROR 'В базе более одной записи архивов перевода года за текущий период. Это ошибочная ситуация, необходимо связаться с районным координатором для исправления';
    IF(N > 0) THEN EXCEPTION DATA_ERROR 'Вы пытаетесь выполнить перевод года повторно, либо в прошлом учебном периоде перевод был выполнен некорректно. Перевод года невозможен. Свяжитесь с районным координатором, или восстановите базу из резервной копии.';

    -- Ищем текущий объект мониторинга (он должен быть единственным)
    SELECT FIRST 1 L.OBJ_ID FROM LINKS L WHERE L.OBJ_TYPE_ID = 162 AND L.DATE_DEL IS NULL INTO :V$OBJ162_ID;

    -- Ищем архивный объект за текущий период, если он вдруг есть
    SELECT L.OBJ_ID
    FROM LINKS L
    JOIN VALL V1895 ON V1895.OBJ_ID = L.OBJ_ID AND V1895.PARAM_ID = 1895 AND V1895.IS_DEL = 0 AND V1895.LISTVAL_ID = :V$YEAR_ID
    WHERE L.DATE_DEL IS NULL AND L.OBJ_TYPE_ID = 238
    INTO :V$OBJ238_ID;

    IF (V$OBJ238_ID IS NULL) THEN
    BEGIN
        SELECT OBJ_ID FROM OBJECT_ADD(:SCHOOL_ID, 238, NULL, NULL, :I$USER_ID) INTO :V$OBJ238_ID;
        SELECT BLOB_ID FROM VAL_ADD(1895, :V$OBJ238_ID, :V$YEAR_ID, :I$USER_ID) INTO :V$BLOB_ID;
    END

    -- Перенос значений параметров из 162 в 238
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1506, :V$OBJ238_ID, 2081, :I$USER_ID);

    --1942  1459
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1459, :V$OBJ238_ID, 1942, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1450, :V$OBJ238_ID, 1933, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1728, :V$OBJ238_ID, 1938, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1487, :V$OBJ238_ID, 1971, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1485, :V$OBJ238_ID, 1969, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1730, :V$OBJ238_ID, 1939, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1731, :V$OBJ238_ID, 1940, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1491, :V$OBJ238_ID, 1975, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1490, :V$OBJ238_ID, 1974, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1476, :V$OBJ238_ID, 1957, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1489, :V$OBJ238_ID, 1973, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1440, :V$OBJ238_ID, 1930, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1447, :V$OBJ238_ID, 1931, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1678, :V$OBJ238_ID, 1996, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1700, :V$OBJ238_ID, 2029, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1689, :V$OBJ238_ID, 2019, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1710, :V$OBJ238_ID, 2049, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1720, :V$OBJ238_ID, 2009, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1666, :V$OBJ238_ID, 2039, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1696, :V$OBJ238_ID, 2026, :I$USER_ID);


    --2006  1662
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1662, :V$OBJ238_ID, 2006, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1675, :V$OBJ238_ID, 2046, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1707, :V$OBJ238_ID, 2036, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1717, :V$OBJ238_ID, 1993, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1686, :V$OBJ238_ID, 2016, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1496, :V$OBJ238_ID, 1955, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1502, :V$OBJ238_ID, 1927, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1499, :V$OBJ238_ID, 1922, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1708, :V$OBJ238_ID, 2047, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1718, :V$OBJ238_ID, 2017, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1676, :V$OBJ238_ID, 1994, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1698, :V$OBJ238_ID, 2027, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1664, :V$OBJ238_ID, 2007, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1687, :V$OBJ238_ID, 2037, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1706, :V$OBJ238_ID, 2035, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1695, :V$OBJ238_ID, 2005, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1716, :V$OBJ238_ID, 1992, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1685, :V$OBJ238_ID, 2015, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1674, :V$OBJ238_ID, 2045, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1660, :V$OBJ238_ID, 2025, :I$USER_ID);


    --2022 1682
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1682, :V$OBJ238_ID, 2022, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1713, :V$OBJ238_ID, 2042, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1723, :V$OBJ238_ID, 2012, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1692, :V$OBJ238_ID, 2052, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1670, :V$OBJ238_ID, 2032, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1703, :V$OBJ238_ID, 1999, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1709, :V$OBJ238_ID, 2028, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1699, :V$OBJ238_ID, 2008, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1677, :V$OBJ238_ID, 2048, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1719, :V$OBJ238_ID, 2018, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1665, :V$OBJ238_ID, 2038, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1688, :V$OBJ238_ID, 1995, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1724, :V$OBJ238_ID, 2000, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1693, :V$OBJ238_ID, 2023, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1683, :V$OBJ238_ID, 2053, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1704, :V$OBJ238_ID, 2013, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1714, :V$OBJ238_ID, 2043, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1671, :V$OBJ238_ID, 2033, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1677, :V$OBJ238_ID, 2020, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1680, :V$OBJ238_ID, 2040, :I$USER_ID);


     --2010 1721
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1721, :V$OBJ238_ID, 2010, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1701, :V$OBJ238_ID, 1997, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1690, :V$OBJ238_ID, 2050, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1711, :V$OBJ238_ID, 2030, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1712, :V$OBJ238_ID, 2031, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1669, :V$OBJ238_ID, 2021, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1681, :V$OBJ238_ID, 2051, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1722, :V$OBJ238_ID, 2011, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1702, :V$OBJ238_ID, 2041, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1691, :V$OBJ238_ID, 1998, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1528, :V$OBJ238_ID, 2055, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1513, :V$OBJ238_ID, 2068, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1537, :V$OBJ238_ID, 2064, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1522, :V$OBJ238_ID, 2077, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1524, :V$OBJ238_ID, 2078, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1538, :V$OBJ238_ID, 2065, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1525, :V$OBJ238_ID, 2079, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1539, :V$OBJ238_ID, 2066, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1529, :V$OBJ238_ID, 2056, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1514, :V$OBJ238_ID, 2069, :I$USER_ID);


    -- 2057 1530
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1530, :V$OBJ238_ID, 2057, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1515, :V$OBJ238_ID, 2070, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1516, :V$OBJ238_ID, 2071, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1531, :V$OBJ238_ID, 2058, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1517, :V$OBJ238_ID, 2072, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1532, :V$OBJ238_ID, 2059, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1518, :V$OBJ238_ID, 2073, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1533, :V$OBJ238_ID, 2060, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1519, :V$OBJ238_ID, 2074, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1534, :V$OBJ238_ID, 2061, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1535, :V$OBJ238_ID, 2062, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1520, :V$OBJ238_ID, 2075, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1521, :V$OBJ238_ID, 2076, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1536, :V$OBJ238_ID, 2063, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1431, :V$OBJ238_ID, 1917, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1495, :V$OBJ238_ID, 1909, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1439, :V$OBJ238_ID, 1929, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1507, :V$OBJ238_ID, 1900, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1503, :V$OBJ238_ID, 1897, :I$USER_ID);


    --1898 1504
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1504, :V$OBJ238_ID, 1898, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1505, :V$OBJ238_ID, 1899, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1422, :V$OBJ238_ID, 1906, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1727, :V$OBJ238_ID, 1937, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1455, :V$OBJ238_ID, 1941, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1453, :V$OBJ238_ID, 1936, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1672, :V$OBJ238_ID, 1907, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1483, :V$OBJ238_ID, 1967, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1597, :V$OBJ238_ID, 1985, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1725, :V$OBJ238_ID, 2003, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1658, :V$OBJ238_ID, 1923, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1484, :V$OBJ238_ID, 1968, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1732, :V$OBJ238_ID, 1989, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1733, :V$OBJ238_ID, 1990, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1435, :V$OBJ238_ID, 1919, :I$USER_ID);


    --1935  1452
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1452, :V$OBJ238_ID, 1935, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1596, :V$OBJ238_ID, 1984, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1480, :V$OBJ238_ID, 1965, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1488, :V$OBJ238_ID, 1972, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1486, :V$OBJ238_ID, 1970, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1473, :V$OBJ238_ID, 1953, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1526, :V$OBJ238_ID, 2002, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1432, :V$OBJ238_ID, 1987, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1460, :V$OBJ238_ID, 1944, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1493, :V$OBJ238_ID, 1961, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1419, :V$OBJ238_ID, 1903, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1479, :V$OBJ238_ID, 1964, :I$USER_ID);


    --1960  1492
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1492, :V$OBJ238_ID, 1960, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1468, :V$OBJ238_ID, 1947, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1482, :V$OBJ238_ID, 1966, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1657, :V$OBJ238_ID, 1963, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1470, :V$OBJ238_ID, 1949, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1469, :V$OBJ238_ID, 1948, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1656, :V$OBJ238_ID, 1962, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1477, :V$OBJ238_ID, 1926, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1474, :V$OBJ238_ID, 1954, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1475, :V$OBJ238_ID, 1956, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1471, :V$OBJ238_ID, 1950, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1420, :V$OBJ238_ID, 1904, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1448, :V$OBJ238_ID, 1932, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1436, :V$OBJ238_ID, 1920, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1434, :V$OBJ238_ID, 1925, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1726, :V$OBJ238_ID, 1981, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1542, :V$OBJ238_ID, 1978, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1544, :V$OBJ238_ID, 1979, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1547, :V$OBJ238_ID, 1982, :I$USER_ID);
    
    
    --1977 1541
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1541, :V$OBJ238_ID, 1977, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1546, :V$OBJ238_ID, 1980, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1423, :V$OBJ238_ID, 1908, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1498, :V$OBJ238_ID, 1952, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1437, :V$OBJ238_ID, 1921, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1464, :V$OBJ238_ID, 1945, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1418, :V$OBJ238_ID, 1902, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1510, :V$OBJ238_ID, 1896, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1425, :V$OBJ238_ID, 1911, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1426, :V$OBJ238_ID, 1912, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1500, :V$OBJ238_ID, 1958, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1501, :V$OBJ238_ID, 1959, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1428, :V$OBJ238_ID, 1914, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1427, :V$OBJ238_ID, 1913, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1421, :V$OBJ238_ID, 1905, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1429, :V$OBJ238_ID, 1915, :I$USER_ID);
    
    
    --1988 1433
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1433, :V$OBJ238_ID, 1988, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1497, :V$OBJ238_ID, 1946, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1472, :V$OBJ238_ID, 1951, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1430, :V$OBJ238_ID, 1916, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 1424, :V$OBJ238_ID, 1910, :I$USER_ID);

    --new
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 2193, :V$OBJ238_ID, 2212, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 2194, :V$OBJ238_ID, 2213, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 2195, :V$OBJ238_ID, 2214, :I$USER_ID);

    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 2399, :V$OBJ238_ID, 2421, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 2400, :V$OBJ238_ID, 2422, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 2401, :V$OBJ238_ID, 2423, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 2402, :V$OBJ238_ID, 2424, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 2412, :V$OBJ238_ID, 2425, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 2414, :V$OBJ238_ID, 2426, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 2403, :V$OBJ238_ID, 2427, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 2404, :V$OBJ238_ID, 2428, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 2405, :V$OBJ238_ID, 2429, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 2406, :V$OBJ238_ID, 2430, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 2413, :V$OBJ238_ID, 2431, :I$USER_ID);
    EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ162_ID, 2415, :V$OBJ238_ID, 2432, :I$USER_ID);

    -- Вовлеченность в ДО
    FOR
        SELECT L.OBJ_ID FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 298 AND L.PARENT_TYPE_ID = 162 AND L.DATE_DEL IS NULL AND L.PARENT_ID = :V$OBJ162_ID
        INTO :V$OBJ265_ID
    DO
    BEGIN
        SELECT OBJ_ID FROM OBJECT_ADD(:V$OBJ238_ID, 299) INTO :V$OBJ268_ID;
        EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ265_ID, 2407, :V$OBJ268_ID, 2433, :I$USER_ID);
        EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ265_ID, 2408, :V$OBJ268_ID, 2434, :I$USER_ID);
        EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ265_ID, 2409, :V$OBJ268_ID, 2435, :I$USER_ID);
        EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ265_ID, 2410, :V$OBJ268_ID, 2436, :I$USER_ID);
        EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ265_ID, 2416, :V$OBJ268_ID, 2437, :I$USER_ID);
        EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ265_ID, 2417, :V$OBJ268_ID, 2438, :I$USER_ID);
        EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ265_ID, 2411, :V$OBJ268_ID, 2439, :I$USER_ID);
    END

    -- Контингент отделения ДО
    FOR
        SELECT L.OBJ_ID FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 265 AND L.PARENT_TYPE_ID = 162 AND L.DATE_DEL IS NULL AND L.PARENT_ID = :V$OBJ162_ID
        INTO :V$OBJ265_ID
    DO
    BEGIN
        SELECT OBJ_ID FROM OBJECT_ADD(:V$OBJ238_ID, 268) INTO :V$OBJ268_ID;
        EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ265_ID, 2196, :V$OBJ268_ID, 2199, :I$USER_ID);
        EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ265_ID, 2197, :V$OBJ268_ID, 2200, :I$USER_ID);
        EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ265_ID, 2198, :V$OBJ268_ID, 2201, :I$USER_ID);
    END

    -- Загруженность
    FOR
        SELECT L.OBJ_ID FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 270 AND L.PARENT_TYPE_ID = 162 AND L.DATE_DEL IS NULL AND L.PARENT_ID = :V$OBJ162_ID
        INTO :V$OBJ265_ID
    DO
    BEGIN
        SELECT OBJ_ID FROM OBJECT_ADD(:V$OBJ238_ID, 271) INTO :V$OBJ268_ID;
        EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ265_ID, 2206, :V$OBJ268_ID, 2207, :I$USER_ID);
        EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ265_ID, 2202, :V$OBJ268_ID, 2208, :I$USER_ID);
        EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ265_ID, 2203, :V$OBJ268_ID, 2209, :I$USER_ID);
        EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ265_ID, 2204, :V$OBJ268_ID, 2210, :I$USER_ID);
        EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ265_ID, 2205, :V$OBJ268_ID, 2211, :I$USER_ID);
    END

    -- Сериализуем XML в на выход - сами данные в BLOB положит само приложение
    -- UPDATE OR INSERT INTO VALN (OBJ_ID, OBJ_DATA) VALUES (:V$OBJ238_ID, :V$DATA) MATCHING (OBJ_ID);
    IF(V$OBJ162_ID IS NOT NULL) THEN
    BEGIN
        -- Выполняем сериализацию данных мониторинга (при этом они будут автоматически пересчитаны)
        DEST_ID = V$OBJ238_ID;
        FOR
            SELECT TAG, VAL
            FROM SERIALIZE_OBJECT(:SCHOOL_ID, :V$OBJ162_ID, 0, 1, 2, 1)
            INTO :TAG, :VAL
        DO
        BEGIN
            SUSPEND;
        END
    END

END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CHANGER_PARALLEL_FIXER
AS
declare variable V$SCHOOL_ID bigint;
declare variable V$GRADE_ID bigint;
declare variable V$STAGE_ID bigint;
declare variable V$CLASS_ID bigint;
declare variable V$BLOB_ID bigint;
declare variable V$KIND_SCHOOL_ID bigint;
declare variable V$TYPE_SCHOOL_ID bigint;
declare variable V$OU_LICENCE_TYPE varchar(1);
declare variable V$MIN_STAGE float;
declare variable V$MIN_STAGE_IN float;
declare variable V$MAX_STAGE float;
declare variable V$MAX_STAGE_IN float;
declare variable V$WANTS_13 smallint = 0;
declare variable V$WANTS_36 smallint = 0;
declare variable V$COST float;
declare variable V$LISTVAL_ID bigint;
declare variable V$YASLI_ID bigint;
declare variable V$SAD_ID bigint;
declare variable V$TAG smallint;
BEGIN
    -- Восстанавливаем ID ОУ
    SELECT STATUS FROM OU_LICENCE_TYPE INTO :V$OU_LICENCE_TYPE;
    SELECT FIRST 1 L.OBJ_ID
    FROM LINKS L
    WHERE L.PARENT_ID IS NULL AND L.OBJ_TYPE_ID = 2 AND L.DATE_DEL IS NULL
    INTO :V$SCHOOL_ID;

    IF (V$SCHOOL_ID IS NULL) THEN EXIT;

    -- ДОУ
    IF (V$OU_LICENCE_TYPE = 'D') THEN
    BEGIN
        -- Находим минимальный и максимальный уровень образования из числа существующих
        SELECT FIRST 1 LV.COST
        FROM LINKS L7
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.DATE_DEL IS NULL AND L8.OBJ_TYPE_ID = 8
        JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
        JOIN LISTVALS LV ON LV.LISTVAL_ID = V49.LISTVAL_ID AND LV.PARENT_ID = 2140
        WHERE L7.PARENT_ID = :V$SCHOOL_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
        ORDER BY LV.COST
        INTO :V$MIN_STAGE;

        SELECT FIRST 1 LV.COST
        FROM LINKS L7
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.DATE_DEL IS NULL AND L8.OBJ_TYPE_ID = 8
        JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
        JOIN LISTVALS LV ON LV.LISTVAL_ID = V49.LISTVAL_ID AND LV.PARENT_ID = 2140
        WHERE L7.PARENT_ID = :V$SCHOOL_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
        ORDER BY LV.COST DESC
        INTO :V$MAX_STAGE;

        -- Находим минимальный и максимальный уровень из зачисления
        SELECT FIRST 1 LV.COST
        FROM LINKS L77
        JOIN LINKS L290 ON L290.PARENT_ID = L77.OBJ_ID AND L290.DATE_DEL IS NULL AND L290.OBJ_TYPE_ID = 290
        JOIN VALL V2346 ON V2346.OBJ_ID = L290.OBJ_ID AND V2346.PARAM_ID = 2346 AND V2346.IS_DEL = 0
        JOIN LISTVALS LV ON LV.LISTVAL_ID = V2346.LISTVAL_ID AND LV.PARENT_ID = 2140
        WHERE L77.PARENT_ID = :V$SCHOOL_ID AND L77.OBJ_TYPE_ID = 77 AND L77.DATE_DEL IS NULL
        ORDER BY LV.COST
        INTO :V$MIN_STAGE_IN;

        SELECT FIRST 1 LV.COST
        FROM LINKS L77
        JOIN LINKS L290 ON L290.PARENT_ID = L77.OBJ_ID AND L290.DATE_DEL IS NULL AND L290.OBJ_TYPE_ID = 290
        JOIN VALL V2346 ON V2346.OBJ_ID = L290.OBJ_ID AND V2346.PARAM_ID = 2346 AND V2346.IS_DEL = 0
        JOIN LISTVALS LV ON LV.LISTVAL_ID = V2346.LISTVAL_ID AND LV.PARENT_ID = 2140
        WHERE L77.PARENT_ID = :V$SCHOOL_ID AND L77.OBJ_TYPE_ID = 77 AND L77.DATE_DEL IS NULL
        ORDER BY LV.COST DESC
        INTO :V$MAX_STAGE_IN;

        SELECT FIRST 1 1
        FROM LINKS L77
        JOIN LINKS L290 ON L290.PARENT_ID = L77.OBJ_ID AND L290.DATE_DEL IS NULL AND L290.OBJ_TYPE_ID = 290
        JOIN VALL V2346 ON V2346.OBJ_ID = L290.OBJ_ID AND V2346.PARAM_ID = 2346 AND V2346.IS_DEL = 0 AND V2346.LISTVAL_ID = 33
        WHERE L77.PARENT_ID = :V$SCHOOL_ID AND L77.OBJ_TYPE_ID = 77 AND L77.DATE_DEL IS NULL
        INTO :V$WANTS_13;

        SELECT FIRST 1 1
        FROM LINKS L77
        JOIN LINKS L290 ON L290.PARENT_ID = L77.OBJ_ID AND L290.DATE_DEL IS NULL AND L290.OBJ_TYPE_ID = 290
        JOIN VALL V2346 ON V2346.OBJ_ID = L290.OBJ_ID AND V2346.PARAM_ID = 2346 AND V2346.IS_DEL = 0 AND V2346.LISTVAL_ID = 3262
        WHERE L77.PARENT_ID = :V$SCHOOL_ID AND L77.OBJ_TYPE_ID = 77 AND L77.DATE_DEL IS NULL
        INTO :V$WANTS_36;

        IF(V$MIN_STAGE_IN IS NULL AND V$MIN_STAGE IS NULL) THEN EXIT;
        V$MIN_STAGE = MINVALUE(COALESCE(V$MIN_STAGE, 9999), COALESCE(V$MIN_STAGE_IN, 9999));

        -- Ясли
        SELECT FIRST 1 L7.OBJ_ID
        FROM LINKS L7
        JOIN VALL V43 ON V43.OBJ_ID = L7.OBJ_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0 AND V43.LISTVAL_ID = 3263
        WHERE L7.PARENT_ID = :V$SCHOOL_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
        INTO :V$YASLI_ID;

        -- Детский сад
        SELECT FIRST 1 L7.OBJ_ID
        FROM LINKS L7
        JOIN VALL V43 ON V43.OBJ_ID = L7.OBJ_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0 AND V43.LISTVAL_ID = 3264
        WHERE L7.PARENT_ID = :V$SCHOOL_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
        INTO :V$SAD_ID;

        IF(V$YASLI_ID IS NOT NULL AND V$SAD_ID IS NULL) THEN
        BEGIN
            -- Только Ясли, список обязательных этапов от 2 (вторая ранняя) до 3 (первая младшая)
            V$MIN_STAGE = MINVALUE(V$MIN_STAGE, 2);
            V$MAX_STAGE = MAXVALUE(V$MAX_STAGE, 3);
        END
        ELSE IF(V$YASLI_ID IS NULL AND V$SAD_ID IS NOT NULL) THEN
        BEGIN
            -- Только Сад, список обязательных этапов от 5 (вторая младшая) до 8 (первая младшая)
            V$MIN_STAGE = MINVALUE(V$MIN_STAGE, 5);
            V$MAX_STAGE = MAXVALUE(V$MAX_STAGE, 8);
            IF(V$WANTS_36 = 1) THEN V$MAX_STAGE = MAXVALUE(V$MAX_STAGE, 9);
        END
        ELSE IF(V$YASLI_ID IS NOT NULL AND V$SAD_ID IS NOT NULL) THEN
        BEGIN
            -- Есть и ясли, и сад, список обязательных этапов от 2 (вторая ранняя) до 8 (подготовительная), первая ранняя опционально
            V$MIN_STAGE = MINVALUE(V$MIN_STAGE, 2);
            V$MAX_STAGE = MAXVALUE(V$MAX_STAGE, 8);
            IF(V$WANTS_36 = 1) THEN V$MAX_STAGE = MAXVALUE(V$MAX_STAGE, 9);
        END

        -- Восстанавливаем непрерывность уровней начиная с минимального из имеющихся или идущих к зачислению
        FOR
            SELECT LV.LISTVAL_ID, LV.COST, CAST(LV.TAG AS SMALLINT)
            FROM LISTVALS LV
            WHERE LV.PARENT_ID = 2140 AND LV.IS_DEL = 0
            ORDER BY LV.COST
            INTO :V$LISTVAL_ID, :V$COST, :V$TAG
        DO
        BEGIN
            -- Разновозрастные группы создаем только если есть поступающие на эти уровни
            IF ((V$TAG < 10) OR (V$WANTS_13 = 1 AND V$TAG = 13) OR (V$WANTS_36 = 1 AND V$TAG = 36)) THEN
            BEGIN
                IF (V$COST <= 4) THEN V$GRADE_ID = V$YASLI_ID; ELSE V$GRADE_ID = V$SAD_ID;
                IF ((V$GRADE_ID IS NOT NULL) AND (V$COST >= :V$MIN_STAGE) AND (V$COST <= :V$MAX_STAGE)) THEN
                BEGIN
                    IF (NOT EXISTS(
                            SELECT FIRST 1 1
                            FROM LINKS L8
                            JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0 AND V49.LISTVAL_ID = :V$LISTVAL_ID
                            WHERE L8.PARENT_ID = :V$GRADE_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
                        )) THEN
                    BEGIN
                        SELECT OBJ_ID FROM OBJECT_ADD(:V$GRADE_ID, 8) INTO :V$STAGE_ID;
                        SELECT BLOB_ID FROM VAL_ADD(49, :V$STAGE_ID, :V$LISTVAL_ID) INTO :V$BLOB_ID;
                    END
                END
            END
        END
    END

    -- Тип и вид ОУ
    SELECT I FROM VAL_GET(:V$SCHOOL_ID,  10) INTO :V$KIND_SCHOOL_ID;
    SELECT I FROM VAL_GET(:V$SCHOOL_ID,  11) INTO :V$TYPE_SCHOOL_ID;

    -- Общеобразовательные школы кроме вечерних и специальных, начальные школы, основные школы
    IF (((V$TYPE_SCHOOL_ID = 958) AND (V$KIND_SCHOOL_ID NOT IN (965, 967, 2219, 2220))) OR
        (V$TYPE_SCHOOL_ID = 954) OR (V$KIND_SCHOOL_ID IN (961, 2213)) OR
        (V$KIND_SCHOOL_ID IN (962, 2214))
    ) THEN
    BEGIN

        -- Создаем все этапы начального образования
        V$GRADE_ID = NULL;

        SELECT FIRST 1 L7.OBJ_ID
        FROM LINKS L7
        JOIN VALL V43 ON V43.OBJ_ID = L7.OBJ_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0 AND V43.LISTVAL_ID = 22
        WHERE L7.PARENT_ID = :V$SCHOOL_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
        INTO :V$GRADE_ID;
    
        IF (V$GRADE_ID IS NOT NULL) THEN
        BEGIN
            V$STAGE_ID = NULL;
            SELECT FIRST 1 L8.OBJ_ID
            FROM LINKS L8
            JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0 AND V49.LISTVAL_ID = 37
            WHERE L8.PARENT_ID = :V$GRADE_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
            INTO :V$STAGE_ID;
    
            IF (V$STAGE_ID IS NULL) THEN
            BEGIN
                SELECT OBJ_ID FROM OBJECT_ADD(:V$GRADE_ID, 8) INTO :V$STAGE_ID;
                SELECT BLOB_ID FROM VAL_ADD(49, :V$STAGE_ID, '37') INTO :V$BLOB_ID;
            END
    
            V$STAGE_ID = NULL;
            SELECT FIRST 1 L8.OBJ_ID
            FROM LINKS L8
            JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0 AND V49.LISTVAL_ID = 38
            WHERE L8.PARENT_ID = :V$GRADE_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
            INTO :V$STAGE_ID;
    
            IF (V$STAGE_ID IS NULL) THEN
            BEGIN
                SELECT OBJ_ID FROM OBJECT_ADD(:V$GRADE_ID, 8) INTO :V$STAGE_ID;
                SELECT BLOB_ID FROM VAL_ADD(49, :V$STAGE_ID, '38') INTO :V$BLOB_ID;
            END
    
            V$STAGE_ID = NULL;
            SELECT FIRST 1 L8.OBJ_ID
            FROM LINKS L8
            JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0 AND V49.LISTVAL_ID = 39
            WHERE L8.PARENT_ID = :V$GRADE_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
            INTO :V$STAGE_ID;
    
            IF (V$STAGE_ID IS NULL) THEN
            BEGIN
                SELECT OBJ_ID FROM OBJECT_ADD(:V$GRADE_ID, 8) INTO :V$STAGE_ID;
                SELECT BLOB_ID FROM VAL_ADD(49, :V$STAGE_ID, '39') INTO :V$BLOB_ID;
            END
    
            V$STAGE_ID = NULL;
            SELECT FIRST 1 L8.OBJ_ID
            FROM LINKS L8
            JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0 AND V49.LISTVAL_ID = 40
            WHERE L8.PARENT_ID = :V$GRADE_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
            INTO :V$STAGE_ID;
    
            IF (V$STAGE_ID IS NULL) THEN
            BEGIN
                SELECT OBJ_ID FROM OBJECT_ADD(:V$GRADE_ID, 8) INTO :V$STAGE_ID;
                SELECT BLOB_ID FROM VAL_ADD(49, :V$STAGE_ID, '40') INTO :V$BLOB_ID;
            END
        END
    
        -- Основное образование - кроме начальных школ
        IF ((V$TYPE_SCHOOL_ID = 954) OR (V$KIND_SCHOOL_ID IN (961, 2213))) THEN
        BEGIN
            -- Для начальных школ - удаляем этапы среднего и общего образование, если они опустели
            FOR
                SELECT L7.OBJ_ID
                FROM LINKS L7
                JOIN VALL V43 ON V43.OBJ_ID = L7.OBJ_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0 AND V43.LISTVAL_ID IN (26, 27)
                INTO :V$GRADE_ID
            DO
            BEGIN
                FOR
                    SELECT L8.OBJ_ID
                    FROM LINKS L8
                    WHERE L8.PARENT_ID = :V$GRADE_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
                    INTO :V$STAGE_ID
                DO
                BEGIN
                    FOR
                        SELECT L9.OBJ_ID
                        FROM LINKS L9
                        WHERE L9.PARENT_ID = :V$STAGE_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
                        INTO :V$CLASS_ID
                    DO
                    BEGIN
                        IF (NOT EXISTS(SELECT FIRST 1 1 FROM LINKS WHERE PARENT_ID = :V$CLASS_ID AND DATE_DEL IS NULL)) THEN
                        BEGIN
                            UPDATE LINKS L
                            SET L.DATE_DEL = CURRENT_TIMESTAMP WHERE L.OBJ_ID = :V$CLASS_ID AND L.DATE_DEL IS NULL;
                        END
                    END
                    IF (NOT EXISTS(SELECT FIRST 1 1 FROM LINKS WHERE PARENT_ID = :V$STAGE_ID AND DATE_DEL IS NULL)) THEN
                    BEGIN
                        UPDATE LINKS L SET L.DATE_DEL = CURRENT_TIMESTAMP WHERE L.OBJ_ID = :V$STAGE_ID AND L.DATE_DEL IS NULL;
                    END
                END
                IF (NOT EXISTS(SELECT FIRST 1 1 FROM LINKS WHERE PARENT_ID = :V$GRADE_ID AND DATE_DEL IS NULL)) THEN
                BEGIN
                    UPDATE LINKS L SET L.DATE_DEL = CURRENT_TIMESTAMP WHERE L.OBJ_ID = :V$GRADE_ID AND L.DATE_DEL IS NULL;
                END
            END
        END
        ELSE
        BEGIN

            -- Автосоздание этапов общего образования

            V$GRADE_ID = NULL;
            SELECT FIRST 1 L7.OBJ_ID
            FROM LINKS L7
            JOIN VALL V43 ON V43.OBJ_ID = L7.OBJ_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0 AND V43.LISTVAL_ID = 26
            WHERE L7.PARENT_ID = :V$SCHOOL_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
            INTO :V$GRADE_ID;
        
            IF (V$GRADE_ID IS NOT NULL) THEN
            BEGIN
                V$STAGE_ID = NULL;
                SELECT FIRST 1 L8.OBJ_ID
                FROM LINKS L8
                JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0 AND V49.LISTVAL_ID = 41
                WHERE L8.PARENT_ID = :V$GRADE_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
                INTO :V$STAGE_ID;
        
                IF (V$STAGE_ID IS NULL) THEN
                BEGIN
                    SELECT OBJ_ID FROM OBJECT_ADD(:V$GRADE_ID, 8) INTO :V$STAGE_ID;
                    SELECT BLOB_ID FROM VAL_ADD(49, :V$STAGE_ID, '41') INTO :V$BLOB_ID;
                END
        
                V$STAGE_ID = NULL;
                SELECT FIRST 1 L8.OBJ_ID
                FROM LINKS L8
                JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0 AND V49.LISTVAL_ID = 42
                WHERE L8.PARENT_ID = :V$GRADE_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
                INTO :V$STAGE_ID;
        
                IF (V$STAGE_ID IS NULL) THEN
                BEGIN
                    SELECT OBJ_ID FROM OBJECT_ADD(:V$GRADE_ID, 8) INTO :V$STAGE_ID;
                    SELECT BLOB_ID FROM VAL_ADD(49, :V$STAGE_ID, '42') INTO :V$BLOB_ID;
                END
        
                V$STAGE_ID = NULL;
                SELECT FIRST 1 L8.OBJ_ID
                FROM LINKS L8
                JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0 AND V49.LISTVAL_ID = 43
                WHERE L8.PARENT_ID = :V$GRADE_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
                INTO :V$STAGE_ID;
        
                IF (V$STAGE_ID IS NULL) THEN
                BEGIN
                    SELECT OBJ_ID FROM OBJECT_ADD(:V$GRADE_ID, 8) INTO :V$STAGE_ID;
                    SELECT BLOB_ID FROM VAL_ADD(49, :V$STAGE_ID, '43') INTO :V$BLOB_ID;
                END
        
                V$STAGE_ID = NULL;
        
                SELECT FIRST 1 L8.OBJ_ID
                FROM LINKS L8
                JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0 AND V49.LISTVAL_ID = 44
                WHERE L8.PARENT_ID = :V$GRADE_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
                INTO :V$STAGE_ID;
        
                IF (V$STAGE_ID IS NULL) THEN
                BEGIN
                    SELECT OBJ_ID FROM OBJECT_ADD(:V$GRADE_ID, 8) INTO :V$STAGE_ID;
                    SELECT BLOB_ID FROM VAL_ADD(49, :V$STAGE_ID, '44') INTO :V$BLOB_ID;
                END
        
                V$STAGE_ID = NULL;
                SELECT FIRST 1 L8.OBJ_ID
                FROM LINKS L8
                JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0 AND V49.LISTVAL_ID = 45
                WHERE L8.PARENT_ID = :V$GRADE_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
                INTO :V$STAGE_ID;
        
                IF (V$STAGE_ID IS NULL) THEN
                BEGIN
                    SELECT OBJ_ID FROM OBJECT_ADD(:V$GRADE_ID, 8) INTO :V$STAGE_ID;
                    SELECT BLOB_ID FROM VAL_ADD(49, :V$STAGE_ID, '45') INTO :V$BLOB_ID;
                END
            END
        
            IF (V$KIND_SCHOOL_ID IN (962, 2214)) THEN
            BEGIN
                -- Для школ основного образования - удаляем опустевшие уровни среднего
    
                FOR
                    SELECT L7.OBJ_ID
                    FROM LINKS L7
                    JOIN VALL V43 ON V43.OBJ_ID = L7.OBJ_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0 AND V43.LISTVAL_ID = 27
                    INTO :V$GRADE_ID
                DO
                BEGIN
                    FOR
                        SELECT L8.OBJ_ID
                        FROM LINKS L8
                        WHERE L8.PARENT_ID = :V$GRADE_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
                        INTO :V$STAGE_ID
                    DO
                    BEGIN
                        FOR
                            SELECT L9.OBJ_ID
                            FROM LINKS L9
                            WHERE L9.PARENT_ID = :V$STAGE_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
                            INTO :V$CLASS_ID
                        DO
                        BEGIN
                            IF (NOT EXISTS(SELECT FIRST 1 1 FROM LINKS WHERE PARENT_ID = :V$CLASS_ID AND DATE_DEL IS NULL)) THEN
                            BEGIN
                                UPDATE LINKS L SET L.DATE_DEL = CURRENT_TIMESTAMP WHERE L.OBJ_ID = :V$CLASS_ID AND L.DATE_DEL IS NULL;
                            END
                        END
                        IF (NOT EXISTS(SELECT FIRST 1 1 FROM LINKS WHERE PARENT_ID = :V$STAGE_ID AND DATE_DEL IS NULL)) THEN
                        BEGIN
                            UPDATE LINKS L SET L.DATE_DEL = CURRENT_TIMESTAMP WHERE L.OBJ_ID = :V$STAGE_ID AND L.DATE_DEL IS NULL;
                        END
                    END
                    IF (NOT EXISTS(SELECT FIRST 1 1 FROM LINKS WHERE PARENT_ID = :V$GRADE_ID AND DATE_DEL IS NULL)) THEN
                    BEGIN
                        UPDATE LINKS L SET L.DATE_DEL = CURRENT_TIMESTAMP WHERE L.OBJ_ID = :V$GRADE_ID AND L.DATE_DEL IS NULL;
                    END
                END
            END
            ELSE
            BEGIN

                -- Автосоздание уровней среднего образования

                V$GRADE_ID = NULL;
            
                SELECT FIRST 1 L7.OBJ_ID
                FROM LINKS L7
                JOIN VALL V43 ON V43.OBJ_ID = L7.OBJ_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0 AND V43.LISTVAL_ID = 27
                WHERE L7.PARENT_ID = :V$SCHOOL_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
                INTO :V$GRADE_ID;
            
                IF (V$GRADE_ID IS NOT NULL) THEN
                BEGIN
                    V$STAGE_ID = NULL;
                    SELECT FIRST 1 L8.OBJ_ID
                    FROM LINKS L8
                    JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0 AND V49.LISTVAL_ID = 46
                    WHERE L8.PARENT_ID = :V$GRADE_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
                    INTO :V$STAGE_ID;
            
                    IF (V$STAGE_ID IS NULL) THEN
                    BEGIN
                        SELECT OBJ_ID FROM OBJECT_ADD(:V$GRADE_ID, 8) INTO :V$STAGE_ID;
                        SELECT BLOB_ID FROM VAL_ADD(49, :V$STAGE_ID, '46') INTO :V$BLOB_ID;
                    END
            
                    V$STAGE_ID = NULL;
                    SELECT FIRST 1 L8.OBJ_ID
                    FROM LINKS L8
                    JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0 AND V49.LISTVAL_ID = 47
                    WHERE L8.PARENT_ID = :V$GRADE_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
                    INTO :V$STAGE_ID;
            
                    IF (V$STAGE_ID IS NULL) THEN
                    BEGIN
                        SELECT OBJ_ID FROM OBJECT_ADD(:V$GRADE_ID, 8) INTO :V$STAGE_ID;
                        SELECT BLOB_ID FROM VAL_ADD(49, :V$STAGE_ID, '47') INTO :V$BLOB_ID;
                    END
                END
            END
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CHANGER_PCLASSES_LIST (
    I$USER_ID BIGINT)
RETURNS (
    CLASS_ID BIGINT,
    ENTRANCE_ID BIGINT,
    CLASS_CAPTION VARCHAR(4000),
    CLASS_NAME VARCHAR(4000),
    SORT_ORDER DOUBLE PRECISION)
AS
declare variable V$SCHOOL_ID bigint;
BEGIN
    SELECT FIRST 1 L.OBJ_ID
    FROM LINKS L
    WHERE L.PARENT_ID IS NULL
      AND L.OBJ_TYPE_ID = 2
      AND L.DATE_DEL IS NULL
    INTO :V$SCHOOL_ID;

    IF (V$SCHOOL_ID IS NULL) THEN
        EXIT;

    FOR SELECT L3.OBJ_ID, L.OBJ_ID
        FROM LINKS L
        INNER JOIN LINKS L3 ON L3.PARENT_ID = L.OBJ_ID
        WHERE L.PARENT_ID = :V$SCHOOL_ID
          AND L.OBJ_TYPE_ID = 77
          AND L.DATE_DEL IS NULL
          AND L3.OBJ_TYPE_ID = 9
          AND L3.DATE_DEL IS NULL
        INTO :CLASS_ID, :ENTRANCE_ID
    DO
    BEGIN
        SELECT V
        FROM VAL_GET(:CLASS_ID, 54, 0, :I$USER_ID)
        INTO :CLASS_NAME;

        SELECT CAPTION, SORT_ORDER
        FROM OBJECT_CAPTION_GET(:CLASS_ID, NULL, NULL, :I$USER_ID)
        INTO :CLASS_CAPTION, :SORT_ORDER;

        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CHANGER_PUPIL_GIA_OUT
AS
DECLARE VARIABLE V$SCHOOL_ID BIGINT;
DECLARE VARIABLE V$CONTAINER_PUPIL_OUT_ID BIGINT;
DECLARE VARIABLE V$GRADUATES_YEAR INTEGER;
DECLARE VARIABLE V$PUPIL_OUT_FOUND BIGINT;
DECLARE VARIABLE V$BLOB_ID BIGINT;
DECLARE VARIABLE V$PUPIL_ID BIGINT;
DECLARE VARIABLE V$KIND_SCHOOL_ID BIGINT;
DECLARE VARIABLE V$TYPE_SCHOOL_ID BIGINT;
BEGIN
    V$SCHOOL_ID = NULL;
    V$CONTAINER_PUPIL_OUT_ID = NULL;
    V$PUPIL_OUT_FOUND = NULL;
    V$GRADUATES_YEAR = EXTRACT(YEAR FROM CURRENT_DATE);

    SELECT FIRST 1 L.OBJ_ID
    FROM LINKS L
    WHERE L.PARENT_ID IS NULL AND L.OBJ_TYPE_ID = 2 AND L.DATE_DEL IS NULL
    INTO :V$SCHOOL_ID;

    IF (V$SCHOOL_ID IS NULL) THEN EXIT;

    SELECT I FROM VAL_GET(:V$SCHOOL_ID,  10) INTO :V$KIND_SCHOOL_ID;
    SELECT I FROM VAL_GET(:V$SCHOOL_ID,  11) INTO :V$TYPE_SCHOOL_ID;

    -- Только начальная и основная школа
    IF((SELECT STATUS FROM OU_LICENCE_TYPE) <> 'O') THEN EXIT;
    IF ((V$TYPE_SCHOOL_ID = 954) OR (V$KIND_SCHOOL_ID IN (961, 2213)) OR (V$KIND_SCHOOL_ID IN (962, 2214))) THEN EXIT;

    SELECT FIRST 1 L.OBJ_ID
    FROM LINKS L
    WHERE L.PARENT_ID = :V$SCHOOL_ID AND L.OBJ_TYPE_ID = 78 AND L.DATE_DEL IS NULL
    INTO :V$CONTAINER_PUPIL_OUT_ID;

    IF (V$CONTAINER_PUPIL_OUT_ID IS NULL) THEN EXIT;

    SELECT FIRST 1 L.OBJ_ID
    FROM LINKS L
    JOIN VALI V451 ON V451.OBJ_ID = L.OBJ_ID AND V451.PARAM_ID = 451 AND V451.IS_DEL = 0 AND V451.VAL = :V$GRADUATES_YEAR
    WHERE L.PARENT_ID = :V$CONTAINER_PUPIL_OUT_ID AND L.OBJ_TYPE_ID = 83 AND L.DATE_DEL IS NULL
    INTO :V$PUPIL_OUT_FOUND;

    IF (V$PUPIL_OUT_FOUND IS NULL) THEN
    BEGIN
        SELECT OBJ_ID FROM OBJECT_ADD(:V$CONTAINER_PUPIL_OUT_ID, 83) INTO :V$PUPIL_OUT_FOUND;

        IF (V$PUPIL_OUT_FOUND IS NOT NULL) THEN
        BEGIN
            SELECT BLOB_ID FROM VAL_ADD(451, :V$PUPIL_OUT_FOUND, CAST(:V$GRADUATES_YEAR AS VARCHAR(4000)), 1) INTO :V$BLOB_ID;
        END
    END

    IF (V$PUPIL_OUT_FOUND IS NULL) THEN EXIT;

    /* Принятые для сдачи ГИА */
    FOR
        SELECT L126.OBJ_ID
        FROM LINKS L7
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
        JOIN LINKS L126 ON L126.PARENT_ID = L9.OBJ_ID AND L126.OBJ_TYPE_ID = 126 AND L126.DATE_DEL IS NULL
        WHERE L7.PARENT_ID = :V$SCHOOL_ID AND L7.OBJ_TYPE_ID IN (7, 502) AND L7.DATE_DEL IS NULL
        INTO :V$PUPIL_ID
    DO
    BEGIN
        UPDATE LINKS L SET L.DATE_DEL = CURRENT_TIMESTAMP WHERE L.OBJ_ID = :V$PUPIL_ID AND L.DATE_DEL IS NULL;

        INSERT INTO LINKS (PARENT_ID, OBJ_ID, DATE_INS)
        VALUES (:V$PUPIL_OUT_FOUND, :V$PUPIL_ID, CURRENT_TIMESTAMP);
    END

    /* Сдающие ГИА в виртуальном классе */
    FOR
        SELECT L126.OBJ_ID
        FROM LINKS L7
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
        JOIN LINKS L125 ON L125.PARENT_ID = L8.OBJ_ID AND L125.OBJ_TYPE_ID = 125 AND L125.DATE_DEL IS NULL
        JOIN LINKS L126 ON L126.PARENT_ID = L125.OBJ_ID AND L126.OBJ_TYPE_ID = 126 AND L126.DATE_DEL IS NULL
        WHERE L7.PARENT_ID = :V$SCHOOL_ID AND L7.OBJ_TYPE_ID IN (7, 502) AND L7.DATE_DEL IS NULL
        INTO :V$PUPIL_ID
    DO
    BEGIN
        UPDATE LINKS L SET L.DATE_DEL = CURRENT_TIMESTAMP WHERE L.OBJ_ID = :V$PUPIL_ID AND L.DATE_DEL IS NULL;

        INSERT INTO LINKS (PARENT_ID, OBJ_ID, DATE_INS)
        VALUES (:V$PUPIL_OUT_FOUND, :V$PUPIL_ID, CURRENT_TIMESTAMP);
    END

    /* Удаляем сами виртуальные классы, в которых нет собственных учеников */
    FOR
        SELECT L125.OBJ_ID
        FROM LINKS L7
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
        JOIN LINKS L125 ON L125.PARENT_ID = L8.OBJ_ID AND L125.OBJ_TYPE_ID = 125 AND L125.DATE_DEL IS NULL
        JOIN LINKS L10 ON L10.PARENT_ID = L125.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        WHERE L7.PARENT_ID = :V$SCHOOL_ID AND L7.OBJ_TYPE_ID IN (7, 502) AND L7.DATE_DEL IS NULL AND L10.LINK_ID IS NULL
        INTO :V$BLOB_ID
    DO
    BEGIN
        UPDATE LINKS L SET L.DATE_DEL = CURRENT_TIMESTAMP WHERE L.OBJ_ID = :V$BLOB_ID AND L.DATE_DEL IS NULL;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CHANGER_PUPIL_OUT (
    I$PUPIL_ID BIGINT,
    I$ACTION_DATE DATE,
    I$ORDER_NUMBER VARCHAR(4000),
    I$ORDER_DATE DATE,
    I$USER_ID BIGINT = null)
AS
declare variable V$SCHOOL_ID bigint;
declare variable V$CONTAINER_PUPIL_OUT_ID bigint;
declare variable V$GRADUATES_YEAR integer;
declare variable V$PUPIL_OUT_FOUND bigint;
declare variable V$BLOB_ID bigint;
declare variable V$MOVEMENT_ID bigint;
declare variable CAPTION varchar(4000);
declare variable V$OU_LICENCE_TYPE varchar(1);
declare variable V$CLASS_ID bigint;
BEGIN

    /*

    SELECT STATUS FROM OU_LICENCE_TYPE INTO :V$OU_LICENCE_TYPE;

    V$SCHOOL_ID = NULL;
    V$CONTAINER_PUPIL_OUT_ID = NULL;
    V$PUPIL_OUT_FOUND = NULL;
    V$GRADUATES_YEAR = EXTRACT(YEAR FROM I$ACTION_DATE);

    SELECT FIRST 1 OBJ_ID
    FROM OBJECT_PARENTS_GET(:I$PUPIL_ID, 2)
    INTO :V$SCHOOL_ID;

    IF (V$SCHOOL_ID IS NULL) THEN
    BEGIN
        EXIT;
    END

    SELECT FIRST 1
           L.OBJ_ID

    FROM LINKS L

    WHERE L.PARENT_ID = :V$SCHOOL_ID
    AND L.OBJ_TYPE_ID = 78
    AND L.DATE_DEL IS NULL

    INTO :V$CONTAINER_PUPIL_OUT_ID;

    IF (V$CONTAINER_PUPIL_OUT_ID IS NULL) THEN
    BEGIN
        EXIT;
    END

    SELECT FIRST 1
           L.OBJ_ID

    FROM LINKS L

    JOIN VALI V451
    ON V451.OBJ_ID = L.OBJ_ID
    AND V451.PARAM_ID = 451
    AND V451.IS_DEL = 0
    AND V451.VAL = :V$GRADUATES_YEAR

    WHERE L.PARENT_ID = :V$CONTAINER_PUPIL_OUT_ID
    AND L.OBJ_TYPE_ID = 83
    AND L.DATE_DEL IS NULL

    INTO :V$PUPIL_OUT_FOUND;

    IF (V$PUPIL_OUT_FOUND IS NULL) THEN
    BEGIN
        SELECT OBJ_ID
        FROM OBJECT_ADD(:V$CONTAINER_PUPIL_OUT_ID, 83)
        INTO :V$PUPIL_OUT_FOUND;

        IF (V$PUPIL_OUT_FOUND IS NOT NULL) THEN
        BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD(451, :V$PUPIL_OUT_FOUND, CAST(:V$GRADUATES_YEAR AS VARCHAR(4000)), :I$USER_ID)
            INTO :V$BLOB_ID;

            SELECT BLOB_ID
            FROM VAL_ADD(450, :V$PUPIL_OUT_FOUND, '900', :I$USER_ID)
            INTO :V$BLOB_ID;
        END
    END

    IF (V$PUPIL_OUT_FOUND IS NULL) THEN
    BEGIN
        EXIT;
    END

    SELECT CAPTION
    FROM OBJECT_CAPTION_GET(:V$PUPIL_OUT_FOUND)
    INTO :CAPTION;

    UPDATE LINKS L
    SET L.DATE_DEL = CURRENT_TIMESTAMP
    WHERE L.OBJ_ID = :I$PUPIL_ID
    AND L.PARENT_TYPE_ID IN (9, 46, 48)
    AND L.DATE_DEL IS NULL;

    INSERT INTO LINKS (PARENT_ID, OBJ_ID, DATE_INS)
    VALUES (:V$PUPIL_OUT_FOUND, :I$PUPIL_ID, CURRENT_TIMESTAMP);

    SELECT OBJ_ID
    FROM OBJECT_ADD(:I$PUPIL_ID, 76)
    INTO :V$MOVEMENT_ID;

    SELECT BLOB_ID
    FROM VAL_ADD(432, :V$MOVEMENT_ID, '812', :I$USER_ID)
    INTO :V$BLOB_ID;

    SELECT BLOB_ID
    FROM VAL_ADD(452, :V$MOVEMENT_ID, '901', :I$USER_ID)
    INTO :V$BLOB_ID;

    UPDATE OR INSERT INTO VALD (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
    VALUES (433, :V$MOVEMENT_ID, :I$USER_ID, 0, :I$ACTION_DATE);

    UPDATE OR INSERT INTO VALD (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
    VALUES (435, :V$MOVEMENT_ID, :I$USER_ID, 0, :I$ORDER_DATE);

    SELECT BLOB_ID
    FROM VAL_ADD(434, :V$MOVEMENT_ID, CAST(:I$ORDER_NUMBER AS VARCHAR(4000)), :I$USER_ID)
    INTO :V$BLOB_ID;

    SELECT BLOB_ID
    FROM VAL_ADD(437, :V$MOVEMENT_ID, :CAPTION, :I$USER_ID)
    INTO :V$BLOB_ID;

    SELECT BLOB_ID
    FROM VAL_ADD(438, :V$MOVEMENT_ID, CAST(:V$PUPIL_OUT_FOUND AS VARCHAR(4000)), :I$USER_ID)
    INTO :V$BLOB_ID;
    IF (:V$OU_LICENCE_TYPE = 'U') THEN
    BEGIN
        SELECT BLOB_ID
        FROM VAL_ADD(2448, :V$MOVEMENT_ID, (SELECT I FROM DO_FUNC2(:V$MOVEMENT_ID, 2448, 70)), :I$USER_ID)
        INTO :V$BLOB_ID;
    END

    */

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CHANGER_STAGES_LIST RETURNS (
    STAGE_ID BIGINT,
    STAGE_KIND BIGINT,
    STAGE_TYPE_ID BIGINT,
    STAGE_CAPTION VARCHAR(4000),
    SORT_ORDER DOUBLE PRECISION)
AS
declare variable V$SCHOOL_ID bigint;
BEGIN
    FOR
        SELECT FIRST 1 L.OBJ_ID
        FROM LINKS L
        WHERE L.PARENT_ID IS NULL AND L.OBJ_TYPE_ID = 2 AND L.DATE_DEL IS NULL
        INTO :V$SCHOOL_ID
    DO
    BEGIN
        FOR
            SELECT L77.OBJ_ID, L77.OBJ_TYPE_ID
            FROM LINKS L77
            WHERE L77.PARENT_ID = :V$SCHOOL_ID AND L77.OBJ_TYPE_ID = 77 AND L77.DATE_DEL IS NULL 
            UNION
            SELECT DISTINCT L7.OBJ_ID, L7.OBJ_TYPE_ID
            FROM LINKS L7
            JOIN LINKS L8 ON L8.DATE_DEL IS NULL AND L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8
            WHERE L7.PARENT_TYPE_ID = 2 AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
            INTO :STAGE_ID, :STAGE_TYPE_ID
        DO
        BEGIN
            SELECT I FROM VAL_GET(:STAGE_ID, 43) INTO :STAGE_KIND;
            SELECT CAPTION, SORT_ORDER FROM OBJECT_CAPTION_GET(:STAGE_ID) INTO :STAGE_CAPTION, :SORT_ORDER;

            SUSPEND;
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CHANGE_PROCESS_ORDERS
AS
declare variable V$PARENT_ID bigint;
declare variable V$OBJ_ID bigint;
declare variable V$TMP bigint;
declare variable S varchar(1000);
begin

  -- Функция более неактуальна, все перенесено в YCHANGE_PROCESS

  -- Проверяем, что ничего лишнего в приказах не осталось
  IF(EXISTS(
    SELECT FIRST 1 1
    FROM ORDERS D
    WHERE D.DATE_DEL IS NULL AND D.STATE_ID = 11716 AND D.TYPE_ID NOT IN (12932, 12937)
  )) THEN EXCEPTION DATA_ERROR 'Остались приказы в статусе проекта. Необходимо выполнить их утверждение или удалить';

  -- Приказы о создании учебных коллективов - формируем на основе прототипов классов #403, сами прототипы преобразуем в классы
  -- Если есть хотя бы один такой учебный коллектив

  FOR
    SELECT L8.OBJ_ID, L403.OBJ_ID, V3026.VAL
    FROM LINKS L2
    JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN LINKS L403 ON L7.PARENT_ID = L2.OBJ_ID AND L403.OBJ_TYPE_ID = 403 AND L403.DATE_DEL IS NULL
    LEFT JOIN VALS V3026 ON V3026.OBJ_ID = L403.OBJ_ID AND V3026.PARAM_ID = 3026 AND V3026.IS_DEL = 0
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :V$PARENT_ID, :V$OBJ_ID, :S
  DO
  BEGIN
    SELECT OBJ_ID FROM OBJECT_ADD(:V$PARENT_ID, 9) INTO :V$OBJ_ID;
    SELECT BLOB_ID FROM VAL_ADD(54, :V$OBJ_ID, :S) INTO :V$TMP;
    S = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$OBJ_ID));

    -- Создаем в статусе проекта
    INSERT INTO ORDERS
    (ORDER_DATE, ACTION_DATE, TYPE_ID, STATE_ID, DETAILS_TEXT)
    VALUES (CURRENT_DATE, '01.09.' || EXTRACT(YEAR FROM CURRENT_DATE), 12964, 11716, :S);
  END

  UPDATE LINKS
  SET DATE_DEL = CURRENT_TIMESTAMP
  WHERE DATE_DEL IS NULL AND OBJ_TYPE_ID = 403 AND PARENT_TYPE_ID = 8;

  -- Проведение приказов о переводе учащихся

  -- Проведение приказов об оставлении на повторное обучение

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CHECK_ACTIVE_DOCUMENTS (
    I$OBJ_ID BIGINT)
AS
DECLARE VARIABLE V$ACTIVE BIGINT;
DECLARE VARIABLE V$TYPE BIGINT;
DECLARE VARIABLE V$PERSON_ID BIGINT;
begin

  SELECT V441.LISTVAL_ID
  FROM VALL V441
  WHERE V441.OBJ_ID = :I$OBJ_ID AND V441.PARAM_ID = 441 AND V441.IS_DEL = 0
  INTO :V$TYPE;

  SELECT V614.LISTVAL_ID
  FROM VALL V614
  WHERE V614.OBJ_ID = :I$OBJ_ID AND V614.PARAM_ID = 614 AND V614.IS_DEL = 0
  INTO :V$ACTIVE;

  IF(V$ACTIVE IS NULL) THEN V$ACTIVE = 1982; -- действующий

  IF(V$ACTIVE = 1982) THEN
  BEGIN
    SELECT FIRST 1 LP.PARENT_ID
    FROM LINKS LP
    JOIN LINKS L79 ON L79.PARENT_ID = LP.PARENT_ID AND L79.OBJ_TYPE_ID = 79 AND L79.DATE_DEL IS NULL AND L79.OBJ_ID <> :I$OBJ_ID
    JOIN VALL V441 ON V441.OBJ_ID = L79.OBJ_ID AND V441.PARAM_ID = 441 AND V441.IS_DEL = 0 AND V441.LISTVAL_ID = :V$TYPE
    JOIN VALL V614 ON V614.OBJ_ID = L79.OBJ_ID AND V614.PARAM_ID = 614 AND V614.IS_DEL = 0 AND V614.LISTVAL_ID = 1982
    WHERE LP.OBJ_ID = :I$OBJ_ID AND LP.PARENT_TYPE_ID IN (10, 14, 20) AND LP.DATE_DEL IS NULL
    INTO :V$PERSON_ID;

    IF(V$PERSON_ID IS NOT NULL) THEN
      EXCEPTION DATA_ERROR 'Обнаружены два действующих документа одного типа у ' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$PERSON_ID)) || ', ' ||
        COALESCE((SELECT VAL FROM LISTVAL_TEXT(:V$TYPE)), '???');
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CHECK_CURRICULUM_LIST (
    I$CURRICULUM_ID BIGINT,
    I$IS_PROFILE SMALLINT)
RETURNS (
    OBJ_ID BIGINT,
    PARENT_ID BIGINT,
    OBJ_CAPTION VARCHAR(1000))
AS
declare variable V$LEVEL_ID bigint;
declare variable V$PROFILE_ID bigint;
declare variable V$STANDARD bigint;
BEGIN
    PARENT_ID = NULL;

    -- Это заглушка для вызова из СМИР (устарело)
    SELECT V1594.LISTVAL_ID, V2166.LISTVAL_ID, V2478.LISTVAL_ID
    FROM VALR V2504
    JOIN LINKS LP57 ON LP57.OBJ_ID = V2504.VAL AND LP57.PARENT_TYPE_ID = 57 AND LP57.DATE_DEL IS NULL
    JOIN VALL V1594 ON V1594.OBJ_ID = LP57.PARENT_ID AND V1594.PARAM_ID = 1594 AND V1594.IS_DEL = 0
    LEFT JOIN VALL V2166 ON V2166.OBJ_ID = LP57.OBJ_ID AND V2166.PARAM_ID = 2166 AND V2166.IS_DEL = 0
    LEFT JOIN VALL V2478 ON V2478.OBJ_ID = LP57.OBJ_ID AND V2478.PARAM_ID = 2478 AND V2478.IS_DEL = 0
    WHERE V2504.OBJ_ID = :I$CURRICULUM_ID AND V2504.PARAM_ID = 2504 AND V2504.IS_DEL = 0
    INTO :V$LEVEL_ID, :V$PROFILE_ID, :V$STANDARD;

    -- Случай вызова из контроля УП
    IF(V$LEVEL_ID IS NULL) THEN
    BEGIN
      SELECT V1594.LISTVAL_ID, V2166.LISTVAL_ID, V2478.LISTVAL_ID
      FROM LINKS LP57
      JOIN VALL V1594 ON V1594.OBJ_ID = LP57.PARENT_ID AND V1594.PARAM_ID = 1594 AND V1594.IS_DEL = 0
      LEFT JOIN VALL V2166 ON V2166.OBJ_ID = LP57.OBJ_ID AND V2166.PARAM_ID = 2166 AND V2166.IS_DEL = 0
      LEFT JOIN VALL V2478 ON V2478.OBJ_ID = LP57.OBJ_ID AND V2478.PARAM_ID = 2478 AND V2478.IS_DEL = 0
      WHERE LP57.OBJ_ID = :I$CURRICULUM_ID AND LP57.PARENT_TYPE_ID = 57 AND LP57.DATE_DEL IS NULL
      INTO :V$LEVEL_ID, :V$PROFILE_ID, :V$STANDARD;
    END

    -- Профили УП у нас будут действовать только для средней школы
    IF(V$LEVEL_ID <> 5343 AND I$IS_PROFILE = 1) THEN EXIT;

    IF(V$LEVEL_ID = 5339 AND :V$STANDARD = 11720) THEN
      EXCEPTION DATA_ERROR 'Для ОП начального образования выбран 1 образовательный стандарт.';

    FOR
        -- Выборка из шаблонов УП (только ОУ !)
        SELECT L50.OBJ_ID
        FROM LINKS L50
        JOIN VALL V2466 ON V2466.OBJ_ID = L50.OBJ_ID AND V2466.PARAM_ID = 2466 AND V2466.IS_DEL = 0 AND V2466.LISTVAL_ID = 2
        -- Фильтр по уровню образования
        JOIN VALL V2503 ON V2503.OBJ_ID = L50.OBJ_ID AND V2503.PARAM_ID = 2503 AND V2503.IS_DEL = 0 AND V2503.LISTVAL_ID = :V$LEVEL_ID
        -- Выбираем данные по профилю
        LEFT JOIN VALL V2166 ON V2166.OBJ_ID = L50.OBJ_ID AND V2166.PARAM_ID = 2166 AND V2166.IS_DEL = 0
        -- Тот же образовательный стандарт
        LEFT JOIN VALL V2478 ON V2478.OBJ_ID = L50.OBJ_ID AND V2478.PARAM_ID = 2478 AND V2478.IS_DEL = 0
        WHERE L50.PARENT_ID = 258 AND L50.OBJ_TYPE_ID = 50 AND L50.DATE_DEL IS NULL
          AND (
            -- Если профильность не указана - возвращаем все подряд
            :I$IS_PROFILE IS NULL OR
            -- Если базовый УП - возвращаем универсальный профиль
            ((:I$IS_PROFILE = 0) AND (V2166.LISTVAL_ID = 10955)) OR
            -- Если запросили профиль - сюда попадаем только для средней школы
            ((:I$IS_PROFILE = 1) AND (
                -- Пока всегда берем шаблон, где поле профиля пусто
                --(:V$PROFILE_ID = 10955 AND V2166.LISTVAL_ID is null) OR (:V$PROFILE_ID <> 10955 AND V2166.LISTVAL_ID = :V$PROFILE_ID)
                V2166.LISTVAL_ID is null
              )
            )
          )
          AND ((V2478.LISTVAL_ID = :V$STANDARD) OR (:V$STANDARD IS NULL))
        INTO :OBJ_ID
    DO
    BEGIN
        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:OBJ_ID)
        INTO :OBJ_CAPTION;

        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CHECK_DIRECTOR_EXISTS (
    SCHOOL_ID BIGINT)
RETURNS (
    IS_EXISTS SMALLINT)
AS
BEGIN
    SELECT ISVPL
    FROM GIA_IS_VPL
    INTO IS_EXISTS;

    IF (IS_EXISTS = 0) THEN
    BEGIN
        IF (SCHOOL_ID IS NULL) THEN
        BEGIN
            SELECT FIRST 1
                   OBJ_ID
            FROM LINKS
            WHERE PARENT_ID IS NULL
            AND OBJ_TYPE_ID = 2
            AND DATE_DEL IS NULL
    
            INTO :SCHOOL_ID;
        END
        IF (EXISTS(
            SELECT FIRST 1 1
            FROM R_SPB_POST_DIRECTOR(:SCHOOL_ID, NULL)
            WHERE OBJ_ID IS NOT NULL
        )) THEN
        BEGIN
            IS_EXISTS = 1;
        END
        ELSE
        BEGIN
            IS_EXISTS = 0;
        END 
    END
    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CHECK_EMPLOYEE_TEACHING_IS_LEFT (
    I$MOVEMENT_ID BIGINT NOT NULL,
    I$EMPLOYEE_ID BIGINT NOT NULL,
    I$SECTION_ID BIGINT,
    I$NEW_JOB_ID BIGINT)
RETURNS (
    TEACHING_IS_LEFT SMALLINT,
    POST_IS_LEFT SMALLINT,
    DIVISION_POST_IS_LEFT SMALLINT)
AS
begin
  IF (I$NEW_JOB_ID = 0) THEN I$NEW_JOB_ID = NULL;
  TEACHING_IS_LEFT = 0; -- осталась педагогическая должность
  DIVISION_POST_IS_LEFT = 0; -- осталась должность в том же подразделении
  POST_IS_LEFT = 0; -- осталась должность вообще

  -- остались ли другие педагогические должности ?
  -- сначала проверяем без учета новой должности
  SELECT FIRST 1 1
  FROM LINKS LP14
  JOIN LINKS L15 ON L15.PARENT_ID = LP14.PARENT_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL AND L15.OBJ_ID <> LP14.OBJ_ID
  JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
  LEFT JOIN DO_FUNC(LP13.PARENT_ID, 400) T ON 1 = 1
  LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
  WHERE LP14.OBJ_ID = :I$MOVEMENT_ID AND LP14.PARENT_TYPE_ID = 14 AND LP14.DATE_DEL IS NULL AND V74.VAL IS NULL AND T.SORT_ORDER = 2
  INTO :TEACHING_IS_LEFT;

  -- Если не осталось, проверяем новую должность, вдруг она педагогическая
  IF(TEACHING_IS_LEFT = 0 AND I$NEW_JOB_ID IS NOT NULL) THEN
  SELECT FIRST 1 1
  FROM DO_FUNC(:I$NEW_JOB_ID, 400) T
  WHERE T.SORT_ORDER = 2
  INTO :TEACHING_IS_LEFT;

  -- Остались ли другие должности в подразделении
  -- сначала проверяем без учета новой должности
  SELECT FIRST 1 1
  FROM LINKS LP14
  JOIN LINKS L15 ON L15.PARENT_ID = LP14.PARENT_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL AND L15.OBJ_ID <> LP14.OBJ_ID
  LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
  JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
  JOIN LINKS LPS ON LPS.OBJ_ID = LP13.PARENT_ID AND LPS.PARENT_ID = :I$SECTION_ID AND LPS.DATE_DEL IS NULL
  WHERE LP14.OBJ_ID = :I$MOVEMENT_ID AND LP14.PARENT_TYPE_ID = 14 AND LP14.DATE_DEL IS NULL AND V74.VAL IS NULL
  INTO :DIVISION_POST_IS_LEFT;

  -- Если не осталось, проверяем новую должность
  IF(DIVISION_POST_IS_LEFT = 0 AND I$NEW_JOB_ID IS NOT NULL) THEN
  SELECT FIRST 1 1
  FROM LINKS LPS
  WHERE LPS.OBJ_ID = :I$NEW_JOB_ID AND LPS.PARENT_ID = :I$SECTION_ID AND LPS.DATE_DEL IS NULL
  INTO :DIVISION_POST_IS_LEFT;

  -- Вообще все должности. Если перевод, то однозначно остаются
  IF(I$NEW_JOB_ID IS NOT NULL) THEN POST_IS_LEFT = 1;
  ELSE
    SELECT FIRST 1 1
    FROM LINKS L15
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
    WHERE L15.PARENT_ID = :I$EMPLOYEE_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL AND V74.VAL IS NULL AND L15.OBJ_ID <> :I$MOVEMENT_ID
    INTO :POST_IS_LEFT;
  SUSPEND;
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CHECK_EMPL_MENTOR (
    I$OBJ_ID BIGINT,
    I$PARAM_ID BIGINT,
    I$PARAM_VAL VARCHAR(4000),
    I$IS_DEL SMALLINT)
AS
DECLARE VARIABLE V$S VARCHAR(1000);
DECLARE VARIABLE V$SRC DATE;
DECLARE VARIABLE V$DATE DATE;
begin

  IF(I$PARAM_ID IN (2985, 2987, 2988) AND I$IS_DEL <> 0) THEN EXCEPTION DATA_ERROR 'Поле нельзя удалять или очищать';

  -- Сотрудник не может наставничать над самим собой
  IF(I$PARAM_ID = 2985) THEN
  BEGIN
    IF(EXISTS(
      SELECT FIRST 1 1
      FROM LINKS LP14
      WHERE LP14.OBJ_ID = :I$OBJ_ID AND LP14.PARENT_TYPE_ID = 14 AND LP14.DATE_DEL IS NULL AND LP14.PARENT_ID = :I$PARAM_VAL
    ))
    THEN
      EXCEPTION DATA_ERROR 'Нельзя наставничать над самим собой';
  END

  -- Дату начала можно задать не ранее даты окончания срока
  IF(I$PARAM_ID = 2987) THEN
  BEGIN
    V$SRC = I$PARAM_VAL;

    SELECT V2989.VAL
    FROM VALD V2989
    WHERE V2989.OBJ_ID = :I$OBJ_ID AND V2989.PARAM_ID = 2989 AND V2989.IS_DEL = 0
    INTO :V$DATE;

    IF(V$DATE IS NOT NULL AND V$DATE < V$SRC) THEN EXCEPTION DATA_ERROR 'Дата начала наставничества должна быть не позднее даты окончания';
    IF(V$SRC < DATEADD(-3 YEAR TO CURRENT_DATE)) THEN EXCEPTION DATA_ERROR 'Дата начала наставничества должна быть не старше 3 лет';
  END

  -- Дату окончания можно заполнить только когда заполнены все три основных поля
  IF(I$PARAM_ID = 2989 AND I$IS_DEL = 0) THEN
  BEGIN
    V$SRC = I$PARAM_VAL;

    SELECT V2987.VAL
    FROM VALD V2987
    WHERE V2987.OBJ_ID = :I$OBJ_ID AND V2987.PARAM_ID = 2987 AND V2987.IS_DEL = 0
    INTO :V$DATE;
    IF(V$DATE IS NULL) THEN EXCEPTION DATA_ERROR 'Дата начала наставничества должна быть заполнена';
    IF(V$DATE > V$SRC) THEN EXCEPTION DATA_ERROR 'Дата окончания наставничества должна быть не ранее даты начала';

    SELECT V2985.VAL
    FROM VALR V2985
    WHERE V2985.OBJ_ID = :I$OBJ_ID AND V2985.PARAM_ID = 2985 AND V2985.IS_DEL = 0
    INTO :V$S;
    IF(V$S IS NULL) THEN EXCEPTION DATA_ERROR 'Не заполнен сотрудник, над которым осуществляется наставничество';

    V$S = NULL;
    SELECT V2988.VAL
    FROM VALS V2988
    WHERE V2988.OBJ_ID = :I$OBJ_ID AND V2988.PARAM_ID = 2988 AND V2988.IS_DEL = 0
    INTO :V$S;
    IF(V$S IS NULL) THEN EXCEPTION DATA_ERROR 'Не заполнен номер приказа';
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CHECK_INN (
    S VARCHAR(1000))
RETURNS (
    IS_REAL SMALLINT)
AS
declare variable I integer;
declare variable I1 integer;
declare variable I2 integer;
begin

    IS_REAL = 0;
    I = 0;
    I1 = 0;
    I2 = 0;

    IF(S = '000000000000') THEN
    BEGIN
      -- Разрешаем ИНН из 12 нулей для долбанутых
      IS_REAL = 1;
    END
    ELSE IF(CHAR_LENGTH(S) = 10 AND S SIMILAR TO '[0-9]{10}') THEN
    BEGIN
      I = I + CAST(SUBSTRING(S FROM 1 FOR 1) AS SMALLINT) * 2;
      I = I + CAST(SUBSTRING(S FROM 2 FOR 1) AS SMALLINT) * 4;
      I = I + CAST(SUBSTRING(S FROM 3 FOR 1) AS SMALLINT) * 10;
      I = I + CAST(SUBSTRING(S FROM 4 FOR 1) AS SMALLINT) * 3;
      I = I + CAST(SUBSTRING(S FROM 5 FOR 1) AS SMALLINT) * 5;
      I = I + CAST(SUBSTRING(S FROM 6 FOR 1) AS SMALLINT) * 9;
      I = I + CAST(SUBSTRING(S FROM 7 FOR 1) AS SMALLINT) * 4;
      I = I + CAST(SUBSTRING(S FROM 8 FOR 1) AS SMALLINT) * 6;
      I = I + CAST(SUBSTRING(S FROM 9 FOR 1) AS SMALLINT) * 8;
      I = MOD(I, 11);
      IF (I = 10) THEN I = 0;
      IF (CAST(SUBSTRING(S FROM 10 FOR 1) AS INTEGER) = I) THEN IS_REAL = 1;
    END
    ELSE IF(CHAR_LENGTH(S) = 12 AND S SIMILAR TO '[0-9]{12}') THEN
    BEGIN
      I1 = I1 + CAST(SUBSTRING(S FROM 1 FOR 1) AS SMALLINT) * 7;
      I1 = I1 + CAST(SUBSTRING(S FROM 2 FOR 1) AS SMALLINT) * 2;
      I1 = I1 + CAST(SUBSTRING(S FROM 3 FOR 1) AS SMALLINT) * 4;
      I1 = I1 + CAST(SUBSTRING(S FROM 4 FOR 1) AS SMALLINT) * 10;
      I1 = I1 + CAST(SUBSTRING(S FROM 5 FOR 1) AS SMALLINT) * 3;
      I1 = I1 + CAST(SUBSTRING(S FROM 6 FOR 1) AS SMALLINT) * 5;
      I1 = I1 + CAST(SUBSTRING(S FROM 7 FOR 1) AS SMALLINT) * 9;
      I1 = I1 + CAST(SUBSTRING(S FROM 8 FOR 1) AS SMALLINT) * 4;
      I1 = I1 + CAST(SUBSTRING(S FROM 9 FOR 1) AS SMALLINT) * 6;
      I1 = I1 + CAST(SUBSTRING(S FROM 10 FOR 1) AS SMALLINT) * 8;
      I1 = MOD(I1, 11);
      IF (I1 = 10) THEN I1 = 0;
      I2 = I2 + CAST(SUBSTRING(S FROM 1 FOR 1) AS SMALLINT) * 3;
      I2 = I2 + CAST(SUBSTRING(S FROM 2 FOR 1) AS SMALLINT) * 7;
      I2 = I2 + CAST(SUBSTRING(S FROM 3 FOR 1) AS SMALLINT) * 2;
      I2 = I2 + CAST(SUBSTRING(S FROM 4 FOR 1) AS SMALLINT) * 4;
      I2 = I2 + CAST(SUBSTRING(S FROM 5 FOR 1) AS SMALLINT) * 10;
      I2 = I2 + CAST(SUBSTRING(S FROM 6 FOR 1) AS SMALLINT) * 3;
      I2 = I2 + CAST(SUBSTRING(S FROM 7 FOR 1) AS SMALLINT) * 5;
      I2 = I2 + CAST(SUBSTRING(S FROM 8 FOR 1) AS SMALLINT) * 9;
      I2 = I2 + CAST(SUBSTRING(S FROM 9 FOR 1) AS SMALLINT) * 4;
      I2 = I2 + CAST(SUBSTRING(S FROM 10 FOR 1) AS SMALLINT) * 6;
      I2 = I2 + CAST(SUBSTRING(S FROM 11 FOR 1) AS SMALLINT) * 8;
      I2 = MOD(I2, 11);
      IF (I2 = 10) THEN I2 = 0;

      IF (CAST(SUBSTRING(S FROM 11 FOR 1) AS INTEGER) = I1 AND CAST(SUBSTRING(S FROM 12 FOR 1) AS INTEGER) = I2) THEN IS_REAL = 1;
    END

    SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CHECK_MEDAL_ALLOW (
    I$OBJ_ID BIGINT)
AS
begin

  IF(NOT EXISTS(
    SELECT FIRST 1 1
    FROM LINKS LP9
    JOIN VALL V ON V.OBJ_ID = LP9.PARENT_ID AND V.PARAM_ID IN (2388, 2418) AND V.IS_DEL = 0 AND V.LISTVAL_ID = 11203
    WHERE LP9.OBJ_ID = :I$OBJ_ID AND LP9.PARENT_TYPE_ID IN (9, 187) AND LP9.DATE_DEL IS NULL
  ))
  THEN
    EXCEPTION DATA_ERROR 'Ввод данных о медали возможен только для действующих обучающихся выпускных классов';

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CHECK_OGRN (
    S VARCHAR(1000))
RETURNS (
    IS_REAL SMALLINT)
AS
declare variable I bigint;
BEGIN
    IS_REAL = 0;

    IF (S SIMILAR TO '[0-9]{13}') THEN
    BEGIN
        I = CAST(SUBSTRING(S FROM 1 FOR 12) AS BIGINT);
        I = MOD(I, 11);
        IF (I = 10) THEN I = 0;
        IF (CAST(SUBSTRING(S FROM 13 FOR 1) AS INTEGER) = I) THEN IS_REAL = 1;
    END

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CHECK_OP_PLAN_EXISTS (
    OP_ID BIGINT)
AS
declare variable I integer;
begin
    I = 0;
    SELECT FIRST 1 1
    FROM LINKS
    WHERE PARENT_ID = :OP_ID AND OBJ_TYPE_ID = 50 AND DATE_DEL IS NULL
    INTO :I;

    IF(I <> 0) THEN EXCEPTION DATA_ERROR 'Поле "Вид ОП" является обязательным. Для удаления поля сначала удалите подчиненные учебные планы.';
end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CHECK_ORDERS (
    I$PERSON_ID BIGINT,
    I$ORDER_TYPE BIGINT = NULL,
    I$EXCLUDE_TYPE BIGINT = NULL)
RETURNS (
    ORDER_ID BIGINT,
    ORDER_TYPE BIGINT,
    MEDAL BIGINT)
AS
begin

  -- Если указан ORDER_TYPE - проверяем данный конкретный тип
  -- Если указан EXCLUDE_TYOE - исключаем из проверки этот тип

  SELECT FIRST 1 D.OBJ_ID, D.TYPE_ID
  FROM ORDER_DATA OD
  JOIN ORDERS D ON D.OBJ_ID = OD.ORDER_ID AND D.STATE_ID = 11716 AND D.DATE_DEL IS NULL AND (D.TYPE_ID = :I$ORDER_TYPE OR :I$ORDER_TYPE IS NULL)
    AND (D.TYPE_ID <> :I$EXCLUDE_TYPE OR :I$EXCLUDE_TYPE IS NULL)
  WHERE OD.DATE_DEL IS NULL AND OD.REF_ID = :I$PERSON_ID
  INTO :ORDER_ID, :ORDER_TYPE;

  SELECT FIRST 1 V3479.LISTVAL_ID
  FROM VALL V3479
  WHERE V3479.OBJ_ID = :I$PERSON_ID AND V3479.PARAM_ID = 3479 AND V3479.IS_DEL = 0
  INTO :MEDAL;

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CHECK_PLAN_STAGE (
    I$OBJ_ID BIGINT)
AS
DECLARE VARIABLE N INTEGER;
begin

  N = 0;

  -- Разрешаем менять этапы, даже если УП утвержден
  /* SELECT FIRST 1 1
  FROM LINKS LP50
  JOIN VALL V2470 ON V2470.OBJ_ID = LP50.PARENT_ID AND V2470.PARAM_ID = 2470 AND V2470.IS_DEL = 0 AND V2470.LISTVAL_ID = 11715
  WHERE LP50.OBJ_ID = :I$OBJ_ID AND LP50.PARENT_TYPE_ID = 50 AND LP50.DATE_DEL IS NULL
  INTO :N; */

  -- Для этапов где есть ГУПы или потоки нельзя менять этапы
  SELECT FIRST 1 1
  FROM LINKS LG
  WHERE LG.PARENT_ID = :I$OBJ_ID AND LG.OBJ_TYPE_ID IN (256, 346) AND LG.DATE_DEL IS NULL
  INTO :N;

  IF(N > 0) THEN EXCEPTION DATA_ERROR 'Нельзя менять этапы УП, когда уже созданы ГУПы или потоки';

  -- Требуем уникальности этапа
  SELECT FIRST 1 1
  FROM VALL V381
  JOIN LINKS LP400 ON LP400.OBJ_ID = V381.OBJ_ID AND LP400.PARENT_TYPE_ID = 400 AND LP400.DATE_DEL IS NULL
  JOIN LINKS L54 ON L54.PARENT_ID = LP400.PARENT_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL AND L54.OBJ_ID <> V381.OBJ_ID
  JOIN VALL V381X ON V381X.OBJ_ID = L54.OBJ_ID AND V381X.PARAM_ID = 381 AND V381X.IS_DEL = 0 AND V381X.LISTVAL_ID = V381.LISTVAL_ID
  WHERE V381.OBJ_ID = :I$OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
  INTO :N;

  IF(N > 0) THEN EXCEPTION DATA_ERROR 'Этап УП должен быть уникальным';

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CHECK_PLAN_STATUS_CANCHANGE (
    PLAN_ID BIGINT,
    I$STATE_ID BIGINT = NULL,
    I$PARAM_ID BIGINT = NULL)
AS
DECLARE VARIABLE HAS_PUPILS INTEGER;
DECLARE VARIABLE V$PT BIGINT;
DECLARE VARIABLE V$STD_ID BIGINT;
DECLARE VARIABLE V$SRC_ID BIGINT;
DECLARE VARIABLE V$STAGE_ID BIGINT;
DECLARE VARIABLE V$WEEK BIGINT;
DECLARE VARIABLE V$LEVEL_ID BIGINT;
DECLARE VARIABLE V$ADAPT BIGINT;
begin

    -- STATE_ID = NULL - удаление параметра
    IF(I$STATE_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Нельзя удалять статус учебного плана';

    HAS_PUPILS = 0;

    SELECT FIRST 1 1, L54.PARENT_TYPE_ID
    FROM LINKS L54
    JOIN LINKS L256 ON L256.PARENT_ID = L54.OBJ_ID AND L256.OBJ_TYPE_ID = 256 AND L256.DATE_DEL IS NULL
    JOIN LINKS L10 ON L10.PARENT_ID = L256.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    WHERE L54.PARENT_ID = :PLAN_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
    INTO :HAS_PUPILS, :V$PT;

    -- Делаем поблажку - можно менять стандарт
    IF(HAS_PUPILS <> 0 AND I$PARAM_ID <> 3014) THEN EXCEPTION DATA_ERROR 'Нельзя изменять статус или режим ВД для учебных планов, где уже прикреплены ученики';

    /* Потоков у нас уже нет
    HAS_PUPILS = 0;

    SELECT FIRST 1 1
    FROM LINKS L54
    JOIN LINKS L346 ON L346.PARENT_ID = L54.OBJ_ID AND L346.OBJ_TYPE_ID = 346 AND L346.DATE_DEL IS NULL
    WHERE L54.PARENT_ID = :PLAN_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
    INTO :HAS_PUPILS;

    IF(HAS_PUPILS <> 0) THEN EXCEPTION DATA_ERROR 'Нельзя изменять статус или режим ВД для учебных планов, где уже создано деление на потоки';*/

    IF(I$PARAM_ID IN (2545, 3022)) THEN
    BEGIN
      IF(EXISTS(
        SELECT FIRST 1 1
        FROM PLAN_SUBJECTS
        WHERE DATE_DEL IS NULL AND PLAN_ID = :PLAN_ID
      ))
      THEN
        EXCEPTION DATA_ERROR 'Нельзя изменять параметры ВД, если уже внесены разделы плана';
    END

    IF(I$STATE_ID = 11715 AND I$PARAM_ID NOT IN (2470, 3013, 3373)) THEN EXCEPTION DATA_ERROR 'Нельзя менять настройки действующего учебного плана';

    -- Должен быть хотя бы один этап
    IF(I$STATE_ID = 11715 AND I$PARAM_ID <> 3373 AND NOT EXISTS(
      SELECT FIRST 1 1
      FROM LINKS L54
      JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
      WHERE L54.PARENT_ID = :PLAN_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
    ))
    THEN
      EXCEPTION DATA_ERROR 'Не указаны этапы обучения в учебном плане';

    -- Вид ОП должен быть задан
    IF(I$STATE_ID = 11715 AND I$PARAM_ID <> 3373 AND NOT EXISTS(
      SELECT FIRST 1 1
      FROM LINKS LP57
      JOIN VALL V1832 ON V1832.OBJ_ID = LP57.PARENT_ID AND V1832.PARAM_ID = 1832 AND V1832.IS_DEL = 0
      WHERE LP57.OBJ_ID = :PLAN_ID AND LP57.PARENT_TYPE_ID = 57 AND LP57.DATE_DEL IS NULL
    ))
    THEN
      EXCEPTION DATA_ERROR 'Не задан вид образовательной программы';

    -- Внеурочность должна быть для школ
    IF(I$STATE_ID = 11715 AND I$PARAM_ID <> 3373 AND (SELECT STATUS FROM OU_LICENCE_TYPE) = 'O' AND NOT EXISTS(
      SELECT FIRST 1 1
      FROM VALL V3022
      WHERE V3022.OBJ_ID = :PLAN_ID AND V3022.PARAM_ID = 3022 AND V3022.IS_DEL = 0
    )) THEN
    BEGIN
      IF(V$PT = 50) THEN EXCEPTION DATA_ERROR 'Учебный планы старого типа больше не действуют. Пересоздайте или скопируйте учебный план нового типа';
      EXCEPTION DATA_ERROR 'Не указано, является ли план планом внеурочной деятельности';
    END

    -- При утверждении УП требуем чтобы были все этапы как в шаблоне
    IF(I$STATE_ID = 11715) THEN
    BEGIN
      SELECT FIRST 1 V2379.LISTVAL_ID
      FROM LINKS LP57
      JOIN VALL V2379 ON V2379.OBJ_ID = LP57.PARENT_ID AND V2379.PARAM_ID = 2379 AND V2379.IS_DEL = 0
      WHERE LP57.OBJ_ID = :PLAN_ID AND LP57.PARENT_TYPE_ID = 57 AND LP57.DATE_DEL IS NULL
      INTO :V$ADAPT;

      -- План воспитательной работы
      IF(I$PARAM_ID = 3373) THEN
      BEGIN
        -- Для всех элементов должны быть заданы участники, ответственные и место проведения
        -- !!!
      END
      -- Групповой, не-ВД
      ELSE IF(EXISTS(
        SELECT FIRST 1 1
        FROM VALL V3022
        JOIN VALL V3016 ON V3016.OBJ_ID = V3022.OBJ_ID AND V3016.PARAM_ID = 3016 AND V3016.IS_DEL = 0 AND V3016.LISTVAL_ID = 5465
        WHERE V3022.OBJ_ID = :PLAN_ID AND V3022.PARAM_ID = 3022 AND V3022.IS_DEL = 0 AND V3022.LISTVAL_ID = 3
      )) THEN
      BEGIN
        SELECT V3014.LISTVAL_ID
        FROM VALL V3014
        WHERE V3014.OBJ_ID = :PLAN_ID AND V3014.PARAM_ID = 3014 AND V3014.IS_DEL = 0
        INTO :V$STD_ID;

        SELECT FIRST 1 V1594.LISTVAL_ID
        FROM LINKS LP57
        JOIN VALL V1594 ON V1594.OBJ_ID = LP57.PARENT_ID AND V1594.PARAM_ID = 1594 AND V1594.IS_DEL = 0
        WHERE LP57.OBJ_ID = :PLAN_ID AND LP57.PARENT_TYPE_ID = 57 AND LP57.DATE_DEL IS NULL
        INTO :V$LEVEL_ID;

        SELECT FIRST 1 L400.OBJ_ID
        FROM LINKS L400
        -- нужный нам уровень
        JOIN VALL V3345 ON V3345.OBJ_ID = L400.OBJ_ID AND V3345.PARAM_ID = 3345 AND V3345.IS_DEL = 0 AND V3345.LISTVAL_ID = :V$LEVEL_ID
        -- нужный нам стандарт
        JOIN VALL V3014 ON V3014.OBJ_ID = L400.OBJ_ID AND V3014.PARAM_ID = 3014 AND V3014.IS_DEL = 0 AND V3014.LISTVAL_ID = :V$STD_ID
        -- контроль
        JOIN VALL V3347 ON V3347.OBJ_ID = L400.OBJ_ID AND V3347.PARAM_ID = 3347 AND V3347.IS_DEL = 0 AND V3347.LISTVAL_ID = 2
        -- профиль = универсальный
        JOIN VALL V3112 ON V3112.OBJ_ID = L400.OBJ_ID AND V3112.PARAM_ID = 3112 AND V3112.IS_DEL = 0 AND V3112.LISTVAL_ID = 10955
        WHERE L400.PARENT_ID = 258 AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL
        INTO :V$SRC_ID;

        -- Проверяем точную этапность для не-адаптированных ОП
        FOR
          SELECT DISTINCT V381.LISTVAL_ID
          FROM LINKS L54
          JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
          WHERE L54.PARENT_ID = :V$SRC_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL AND (:V$ADAPT = 11187 OR :V$ADAPT IS NULL)
          ORDER BY 1
          INTO :V$STAGE_ID
        DO
        BEGIN
          V$WEEK = NULL;
          SELECT FIRST 1 V2837.LISTVAL_ID
          FROM LINKS L54
          JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0 AND V381.LISTVAL_ID = :V$STAGE_ID
          LEFT JOIN VALL V2837 ON V2837.OBJ_ID = L54.OBJ_ID AND V2837.PARAM_ID = 2837 AND V2837.IS_DEL = 0
          WHERE L54.PARENT_ID = :PLAN_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
          INTO :V$WEEK;

          IF(V$WEEK IS NULL) THEN EXCEPTION DATA_ERROR 'В групповых УП должны присутствовать все этапы по образовательному стандарту, ' ||
             'а также должна быть заполнена длительность учебной недели';
        END

        -- Должны быть прописаны все замены предметов
        IF(V$SRC_ID IS NOT NULL AND EXISTS(
          SELECT FIRST 1 1
          FROM PLAN_SUBJECTS PS
          JOIN PLAN_SUBJECTS PS2 ON PS2.OBJ_ID = PS.PARENT_ID AND PS2.FIELD_ID = 13303
          LEFT JOIN PLAN_SUBJECTS PSS ON PSS.DATE_DEL IS NULL AND PSS.ROW_TYPE = 10 AND PSS.PLAN_ID = :V$SRC_ID AND PSS.SUBJECT_ID = PS.SUBJECT_ID
          WHERE PS.DATE_DEL IS NULL AND PS.ROW_TYPE = 10 AND PS.PLAN_ID = :PLAN_ID AND PS.SRC_SUBJECT_ID IS NULL AND PSS.OBJ_ID IS NULL
            AND (PS.SUBJECT_ID <> 32810 OR :V$LEVEL_ID <> 5341)
        ))
        THEN EXCEPTION DATA_ERROR 'Для всех пользовательских предметов должны быть указано соответствие предметам из образовательного стандарта';
      END
    END

    -- !!! проверка для групп ДПО ??? нельзя снимать статус, если есть активные группы

    -- Пересчет мониторинга при смене утверждения и типа
    -- 3016 сейчас сюда попадать не будет
    IF(I$PARAM_ID IN (3013, 3016)) THEN SELECT COUNT(*) FROM MONITORING_PLAN_UPD(:PLAN_ID) INTO :V$PT;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CHECK_SNILS (
    S VARCHAR(1000))
RETURNS (
    IS_REAL SMALLINT,
    SNILS_CHECKSUM VARCHAR(2))
AS
DECLARE VARIABLE I SMALLINT;
BEGIN
    IS_REAL = 0;
    I = 0;

    /* 112-233-445 95 */

    IF ((S <> '000-000-000 00') AND
        (S SIMILAR TO '[0-9]{3}\-[0-9]{3}\-[0-9]{3}[[:SPACE:]][0-9]{2}' ESCAPE '\')) THEN
    BEGIN
        I = I + CAST(SUBSTRING(S FROM 1 FOR 1) AS SMALLINT) * 9;
        I = I + CAST(SUBSTRING(S FROM 2 FOR 1) AS SMALLINT) * 8;
        I = I + CAST(SUBSTRING(S FROM 3 FOR 1) AS SMALLINT) * 7;
        I = I + CAST(SUBSTRING(S FROM 5 FOR 1) AS SMALLINT) * 6;
        I = I + CAST(SUBSTRING(S FROM 6 FOR 1) AS SMALLINT) * 5;
        I = I + CAST(SUBSTRING(S FROM 7 FOR 1) AS SMALLINT) * 4;
        I = I + CAST(SUBSTRING(S FROM 9 FOR 1) AS SMALLINT) * 3;
        I = I + CAST(SUBSTRING(S FROM 10 FOR 1) AS SMALLINT) * 2;
        I = I + CAST(SUBSTRING(S FROM 11 FOR 1) AS SMALLINT) * 1;
        I = MOD(I, 101);
        IF (I = 100) THEN I = 0;
        IF (CAST(SUBSTRING(S FROM 13 FOR 2) AS INTEGER) = I) THEN IS_REAL = 1;
        SNILS_CHECKSUM = I;
        IF(CHAR_LENGTH(SNILS_CHECKSUM) = 1) THEN SNILS_CHECKSUM = '0' || SNILS_CHECKSUM;
    END

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CHECK_UNIQUE_DIVS (
    DIV_ID BIGINT,
    SUBJECT_ID BIGINT)
AS
declare variable N smallint;
declare variable V$MASTER_ID bigint;
begin

  N = 0;

  -- В старом варианте сюда попадают деления на потоки и деления на подгруппы
  -- В новом варианте - только деления на потоки, но возможно прикрепленные к родительской ГУП

  -- Тут будет либо NULL, либо ссылка на родительский ГУП
  SELECT V2914.VAL
  FROM VALR V2914
  WHERE V2914.OBJ_ID = :DIV_ID AND V2914.PARAM_ID = 2914 AND V2914.IS_DEL = 0
  INTO :V$MASTER_ID;

  -- Выбираем ветку дерева вниз от вышестоящего объекта (для подгрупп это временно и в 2018-2019 будет уже неактуально)
  SELECT FIRST 1 1
  -- Для подгрупп родителем будет ГУП, для потоков - этап УП
  FROM LINKS LPG
  -- Все деления, кроме самого себя
  JOIN LINKS LDIV ON LDIV.PARENT_ID = LPG.PARENT_ID AND LDIV.OBJ_TYPE_ID IN (346, 47) AND LDIV.DATE_DEL IS NULL AND LDIV.OBJ_ID <> LPG.OBJ_ID
  -- Предмет, по которому идет деление
  JOIN VALR V ON V.OBJ_ID = LDIV.OBJ_ID AND V.PARAM_ID IN (428, 2705) AND V.IS_DEL = 0 AND V.VAL = :SUBJECT_ID
  -- Только для новой схемы, когда структура подгрупп виртуализуется на потоках
  -- Проверяем для прикрепления к той же родительской ГУП
  LEFT JOIN VALR V2914 ON V2914.OBJ_ID = LDIV.OBJ_ID AND V2914.PARAM_ID = 2914 AND V2914.IS_DEL = 0
  WHERE LPG.OBJ_ID = :DIV_ID AND LPG.PARENT_TYPE_ID IN (256, 54) AND LPG.DATE_DEL IS NULL
      AND ((V2914.VAL IS NULL AND :V$MASTER_ID IS NULL) OR (V2914.VAL = :V$MASTER_ID))
  INTO :N;

  IF(N <> 0) THEN EXCEPTION DATA_ERROR 'По данному предмету уже есть потоки/подгруппы';

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CHECK_USER_PWD (
    I$USER_ID BIGINT,
    I$PWD VARCHAR(100),
    I$PWD2 VARCHAR(200) = NULL)
RETURNS (
    IS_REAL SMALLINT)
AS
BEGIN
  IS_REAL = 0;

  SELECT 1
  FROM USERS
  WHERE USER_ID = :I$USER_ID AND (PWD = :I$PWD OR PWD = :I$PWD2) AND DATE_DEL IS NULL
  INTO :IS_REAL;

  SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2022_DO2_LINKS
AS
declare variable V$CJ_ID bigint;
declare variable V$SUBJECT_ID bigint;
declare variable V$STAGE bigint;
declare variable V$LESSON_ID bigint;
declare variable V$DATE date;
declare variable V$NUM integer;
declare variable S varchar(2000);
declare variable MS varchar(2000);
declare variable PS varchar(2000);
declare variable V$SID bigint;
declare variable V$PID bigint;
declare variable V$D1 date;
declare variable V$D2 date;
begin

  -- Должна отработать однократно, но не ранее 27 ноября
  -- После конца каникул также теряет смысл
  IF(CURRENT_DATE < '30.12.2023' OR CURRENT_DATE > '09.01.2024') THEN EXIT;

  IF(EXISTS(
    SELECT 1
    FROM INFO I
    WHERE I.INFO_CODE = 'CJ_DO2_LINKS 2023 Q2X'
  ))
  THEN EXIT;

  INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
  VALUES ('CJ_DO2_LINKS 2023 Q2X', 'CJ_DO2_LINKS 2023 Q2X', CURRENT_TIMESTAMP);

  V$D1 = '01.12.2023';
  V$D2 = '30.12.2023';

  -- Добавляем темы для уроков
  -- В последний опубликованный на эту дату урок, а также во все не-опубликованные с датой от опубликованного и до 01.01
  FOR
    SELECT J.OBJ_ID, J.SUBJECT_ID, J.STAGE_INDEX, L.LESSON_DATE, L.LESSON_NUM
    FROM CJ2_JOURNAL J
    JOIN CJ2_JOURNAL_LESSONS L ON L.DATE_DEL IS NULL AND L.CJ_ID = J.OBJ_ID AND L.LESSON_DATE >= :V$D1 AND L.LESSON_DATE <= :V$D2
      AND (L.IS_PUBLISHED <> 0 OR L.IS_COMPLETED <> 0)
    LEFT JOIN CJ2_JOURNAL_LESSONS L2 ON L2.DATE_DEL IS NULL AND L2.CJ_ID = J.OBJ_ID AND L2.LESSON_DATE >= :V$D1 AND L2.LESSON_DATE <= :V$D2
      AND (L2.IS_PUBLISHED <> 0 OR L2.IS_COMPLETED <> 0) AND (L2.LESSON_DATE > L.LESSON_DATE OR (L2.LESSON_DATE = L.LESSON_DATE AND L2.LESSON_NUM > L.LESSON_NUM))
    WHERE J.DATE_DEL IS NULL AND J.JOURNAL_TYPE = 0 AND L2.OBJ_ID IS NULL
    ORDER BY 1, 4, 5
    INTO :V$CJ_ID, :V$SUBJECT_ID, :V$STAGE, :V$DATE, :V$NUM
  DO
  BEGIN

    FOR
      SELECT L.OBJ_ID, COALESCE(L.LESSON_EXTRA, '')
      FROM CJ2_JOURNAL_LESSONS L
      WHERE L.DATE_DEL IS NULL AND L.CJ_ID = :V$CJ_ID AND (L.LESSON_DATE > :V$DATE OR (L.LESSON_DATE = :V$DATE AND L.LESSON_NUM >= :V$NUM))
        AND L.LESSON_DATE <= :V$D2
      ORDER BY 1
      INTO :V$LESSON_ID, :PS
    DO
    BEGIN

      S = NULL;
      V$SID = NULL;
      V$PID = NULL;

      IF(V$STAGE = 37) THEN
      BEGIN
        -- 1 класс
        -- технология
        IF(V$SUBJECT_ID = 200) THEN V$SID = 51;
      END
      ELSE IF(V$STAGE IN (38, 39, 40)) THEN
      BEGIN
        -- 2-4 классы
        -- математика
        IF(V$SUBJECT_ID = 190) THEN V$SID = 4;
        -- русский язык
        IF(V$SUBJECT_ID = 185) THEN V$SID = 10;
        -- литература
        IF(V$SUBJECT_ID IN (186, 187)) THEN V$SID = 13;
        -- технология
        IF(V$SUBJECT_ID = 200) THEN V$SID = 51;
        -- окрмир
        IF(V$SUBJECT_ID = 196) THEN V$SID = 42;
        -- фр яз
        IF(V$SUBJECT_ID = 189) THEN V$SID = 90;
        -- нем яз
        IF(V$SUBJECT_ID = 2129) THEN V$SID = 96;
      END
      ELSE
      BEGIN
        -- 5-11 классы
        -- математика
        IF(V$SUBJECT_ID = 190) THEN V$SID = 4;
        -- история
        IF(V$SUBJECT_ID IN (174, 3151, 38154)) THEN V$SID = 7;
        -- русский язык
        IF(V$SUBJECT_ID = 185) THEN V$SID = 10;
        -- география
        IF(V$SUBJECT_ID = 3139) THEN V$SID = 16;
        -- биология
        IF(V$SUBJECT_ID = 197) THEN V$SID = 25;
        -- литература
        IF(V$SUBJECT_ID IN (186, 187)) THEN V$SID = 13;
        -- обществознание
        IF(V$SUBJECT_ID = 194) THEN V$SID = 63;
        -- музыка
        IF(V$SUBJECT_ID = 203) THEN V$SID = 45;
        -- история спб
        IF(V$SUBJECT_ID = 3156) THEN V$SID = 66;
        -- изо
        IF(V$SUBJECT_ID = 202) THEN V$SID = 48;
        -- фр яз
        IF(V$SUBJECT_ID = 189) THEN V$SID = 90;
        -- информатика и икт
        IF(V$SUBJECT_ID IN (191, 5518, 32905)) THEN V$SID = 75;
        -- нем яз
        IF(V$SUBJECT_ID = 2129) THEN V$SID = 96;
        -- обж
        IF(V$SUBJECT_ID = 206) THEN V$SID = 102;
        -- естествознание
        IF(V$SUBJECT_ID = 177) THEN V$SID = 78;
        -- физика
        IF(V$SUBJECT_ID = 198) THEN V$SID = 19;
        -- химия
        IF(V$SUBJECT_ID = 199) THEN V$SID = 22;
        -- алгебра
        IF(V$SUBJECT_ID IN (172, 3149, 38150, 32819)) THEN V$SID = 69;
        -- геометрия
        IF(V$SUBJECT_ID IN (173, 38151)) THEN V$SID = 72;
        -- мхк
        IF(V$SUBJECT_ID = 204) THEN V$SID = 105;
        -- астрономия
        IF(V$SUBJECT_ID = 5516) THEN V$SID = 81;
      END

      IF(V$STAGE = 37) THEN
      BEGIN
        -- 1 класс
        V$PID = 4;
      END
      ELSE IF(V$STAGE = 38) THEN
      BEGIN
        -- 2 класс
        V$PID = 7;
      END
      ELSE IF(V$STAGE = 39) THEN
      BEGIN
        -- 3 класс
        V$PID = 10;
      END
      ELSE IF(V$STAGE = 40) THEN
      BEGIN
        -- 4 класс
        V$PID = 13;
      END
      ELSE IF(V$STAGE = 41) THEN
      BEGIN
        -- 5 класс
        V$PID = 16;
        IF(V$SID NOT IN (4, 7, 10, 16, 25, 13, 63, 45, 66, 48, 90, 75, 96, 102, 78)) THEN V$SID = NULL;
      END
      ELSE IF(V$STAGE = 42) THEN
      BEGIN
        -- 6 класс
        V$PID = 19;
        IF(V$SID NOT IN (4, 7, 10, 16, 25, 13, 37, 63, 48, 90, 75, 96, 102, 78)) THEN V$SID = NULL;
      END
      ELSE IF(V$STAGE = 43) THEN
      BEGIN
        -- 7 класс
        V$PID = 22;
        -- математику меняем на алгебру
        IF(V$SID = 4) THEN V$SID = 69;
        IF(V$SID NOT IN (7, 10, 16, 25, 13, 37, 63, 66, 69, 72, 90, 75, 96)) THEN V$SID = NULL;
      END
      ELSE IF(V$STAGE = 44) THEN
      BEGIN
        -- 8 класс
        V$PID = 25;
        -- математику меняем на алгебру
        IF(V$SID = 4) THEN V$SID = 69;
        IF(V$SID NOT IN (7, 10, 19, 22, 16, 25, 13, 37, 63, 69, 72, 75, 96)) THEN V$SID = NULL;
      END
      ELSE IF(V$STAGE = 45) THEN
      BEGIN
        -- 9 класс
        V$PID = 28;
        -- математику меняем на алгебру
        IF(V$SID = 4) THEN V$SID = 69;
        IF(V$SID NOT IN (7, 10, 19, 22, 25, 13, 37, 63, 69, 75, 72, 96)) THEN V$SID = NULL;
      END
      ELSE IF(V$STAGE = 46) THEN
      BEGIN
        -- 10 класс
        V$PID = 31;
        IF(V$SID NOT IN (4, 7, 10, 16, 19, 22, 25, 13, 37, 63, 75, 105)) THEN V$SID = NULL;
      END
      ELSE IF(V$STAGE = 47) THEN
      BEGIN
        -- 11 класс
        V$PID = 34;
        -- вместо биологии ссылка на химию
        IF(V$SID = 25) THEN V$SID = 22;
        IF(V$SID NOT IN (4, 7, 10, 22, 19, 13, 37, 63, 69, 72, 75, 105, 81)) THEN V$SID = NULL;
      END

      -- Старый текст ссылки на ДО2
      S = NULL;
      IF(V$SID IS NOT NULL AND V$PID IS NOT NULL) THEN
      BEGIN
        S = 'https://do2.rcokoit.ru/local/parallels/showcourses.php?subject=' || V$SID || '&parallel=' || V$PID;
      END

      -- Новый текст ссылки на MS
      V$SID = NULL; -- предмет
      V$PID = NULL; -- параллель
      IF(V$STAGE >= 37 AND V$STAGE <= 47) THEN V$PID = V$STAGE - 37 + 1;

      -- Алгебра, геометрия -> математика 3+
      IF(V$SUBJECT_ID IN (172, 173, 3149, 38150, 32819, 38151)) THEN V$SID = 94;
      -- Русский язык
      IF(V$SUBJECT_ID = 185) THEN V$SID = 95;
      -- История 5+
      IF(V$SUBJECT_ID IN (174, 3151, 38154) AND V$PID >= 5) THEN V$SID = 282;
      -- Литературное чтение 1-4
      IF(V$SUBJECT_ID = 186 AND V$PID <= 4) THEN V$SID = 284;
      -- Литература 5+
      IF(V$SUBJECT_ID IN (186, 187) AND V$PID >= 5) THEN V$SID = 283;
      -- Англ яз 2+
      IF(V$SUBJECT_ID = 188 AND V$PID >= 2) THEN V$SID = 276;
      -- Информатика и икт 7+
      IF(V$SUBJECT_ID IN (191, 5518, 32905) AND V$PID >= 7) THEN V$SID = 280;

      MS = NULL;
      IF(V$SID IS NOT NULL AND V$PID IS NOT NULL) THEN MS = 'https://lib.myschool.edu.ru/market?filters=%22subjectIds%22%3A%5B%22' || V$SID || '%22%5D%2C%22contentTypeIds%22%3A%5B%222%22%5D%2C%22schoolClassIds%22%3A%22' || V$PID || '%22';

      IF(S IS NOT NULL OR MS IS NOT NULL) THEN
      BEGIN
        IF(POSITION(MS IN PS) <= 0) THEN
        BEGIN
          -- Заменяем старую ссылку новой
          PS = REPLACE(PS, S, MS);
          IF(POSITION(MS IN PS) <= 0) THEN
          BEGIN
            IF(PS <> '') THEN PS = PS || ', ';
            PS = PS || MS;
          END

          UPDATE CJ2_JOURNAL_LESSONS
          SET LESSON_EXTRA = :PS
          WHERE OBJ_ID = :V$LESSON_ID;
        END
      END
    END

  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_ALIASES_GET (
    I$CJ_ID BIGINT,
    I$USER_ID VARCHAR(40),
    I$ZONE SMALLINT = 0)
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE ACCESS_LEVEL INTEGER;
DECLARE VARIABLE V$GRADE_ID BIGINT;
DECLARE VARIABLE V$GRADE_TYPE_ID BIGINT;
DECLARE VARIABLE V$MEMBER_TYPE_ID BIGINT;
DECLARE VARIABLE V$MEMBER_ID BIGINT;
DECLARE VARIABLE S1 VARCHAR(1000);
DECLARE VARIABLE S2 VARCHAR(1000);
DECLARE VARIABLE V$MULT BIGINT;
DECLARE VARIABLE V$GEN BIGINT;
DECLARE VARIABLE V$IS_CLASSMATE SMALLINT;
begin

  -- Проверяем права доступа к журналу
  SELECT ACCESS_LEVEL, IS_CLASSMATE
  FROM CJ2_JOURNAL_ACCESS(:I$USER_ID, :I$CJ_ID)
  INTO :ACCESS_LEVEL, :V$IS_CLASSMATE;
  IF(ACCESS_LEVEL NOT IN (1, 3) AND V$IS_CLASSMATE = 0) THEN EXCEPTION DATA_ERROR 'У вас нет прав для управления алиасами учащихся';

  SELECT CJM.GRADE_ID
  FROM CJ2_JOURNAL CJM
  WHERE CJM.OBJ_ID = :I$CJ_ID
  INTO :V$GRADE_ID;

  SELECT TYPE_ID
  FROM OBJECTS
  WHERE OBJ_ID = :V$GRADE_ID
  INTO :V$GRADE_TYPE_ID;

  SELECT MULTIPLIER, GEN
  FROM GEN
  INTO :V$MULT, :V$GEN;

  TAG_NAME = 'members::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
      SELECT DISTINCT MM.STUDENT_ID, MM.TYPE_ID, V1.VAL, V2.VAL
      FROM CJ2_MEMBER_MOVEMENTS(:V$GRADE_ID, :V$GRADE_TYPE_ID, NULL) MM
      JOIN VALS V1 ON V1.OBJ_ID = MM.STUDENT_ID AND V1.PARAM_ID IN (55, 59, 128, 827) AND V1.IS_DEL = 0
      JOIN VALS V2 ON V2.OBJ_ID = MM.STUDENT_ID AND V2.PARAM_ID IN (56, 60, 129, 828) AND V2.IS_DEL = 0
      WHERE MM.DATE_TO IS NULL
      ORDER BY 3, 4, 1
      INTO :V$MEMBER_ID, :V$MEMBER_TYPE_ID, :S1, :S2
  DO
  BEGIN
      TAG_NAME = 'members:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'members:r:id';
      VAL = V$MEMBER_ID;
      SUSPEND;
      TAG_NAME = 'members:r:type_id';
      VAL = V$MEMBER_TYPE_ID;
      SUSPEND;
      TAG_NAME = 'members:r:name';
      VAL = NULL;
      SELECT FIRST 1 V2991.VAL
      FROM VALS V2991
      WHERE V2991.OBJ_ID = :V$MEMBER_ID AND V2991.PARAM_ID = 2991 AND V2991.IS_DEL = 0
      INTO :VAL;
      IF(VAL IS NULL) THEN BEGIN
          SELECT FIRST 1 V2153.VAL
          FROM VALS V2153
          WHERE V2153.OBJ_ID = :V$MEMBER_ID AND V2153.PARAM_ID IN (2153, 2152) AND V2153.IS_DEL = 0
          INTO :VAL;
          IF(VAL IS NULL) THEN
          BEGIN
              VAL = V$GEN;
              IF(V$MEMBER_TYPE_ID = 14) THEN VAL = VAL || 't'; ELSE VAL = VAL || 'p';
              VAL = VAL || (V$MEMBER_ID - TRUNC(V$MEMBER_ID / V$MULT) * V$MULT);
          END
      END
      SUSPEND;

      IF(I$ZONE IN (0, 2)) THEN
      BEGIN
          TAG_NAME = 'members:r:name_full';
          VAL = COALESCE(S1, '') || ' ' || COALESCE(S2, '') || ' ' ||
              COALESCE((SELECT VAL FROM VALS WHERE OBJ_ID = :V$MEMBER_ID AND PARAM_ID IN (57, 61, 130, 829) AND IS_DEL = 0), '');
          SUSPEND;
      END

      TAG_NAME = 'members:r:code';
      VAL = NULL;
      SELECT FIRST 1 V2153.VAL
      FROM VALS V2153
      WHERE V2153.OBJ_ID = :V$MEMBER_ID AND V2153.PARAM_ID IN (2153, 2152) AND V2153.IS_DEL = 0
      INTO :VAL;
      IF(VAL IS NULL) THEN
      BEGIN
          VAL = V$GEN;
          IF(V$MEMBER_TYPE_ID = 14) THEN VAL = VAL || 't'; ELSE VAL = VAL || 'p';
          VAL = VAL || (V$MEMBER_ID - TRUNC(V$MEMBER_ID / V$MULT) * V$MULT);
      END
      SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_ALIAS_SET (
    I$CJ_ID BIGINT,
    I$STUDENT_ID BIGINT,
    I$TEXT VARCHAR(1000),
    I$USER_ID VARCHAR(40))
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable ACCESS_LEVEL integer;
declare variable V$GRADE_ID bigint;
declare variable V$TYPE_ID bigint;
declare variable TMP bigint;
declare variable V$IS_CLASSMATE smallint;
begin

  I$TEXT = TRIM(I$TEXT);

  -- Проверяем права доступа к журналу
  SELECT ACCESS_LEVEL, IS_CLASSMATE
  FROM CJ2_JOURNAL_ACCESS(:I$USER_ID, :I$CJ_ID)
  INTO :ACCESS_LEVEL, :V$IS_CLASSMATE;
  IF(ACCESS_LEVEL NOT IN (1, 3) AND V$IS_CLASSMATE <> 1) THEN EXCEPTION DATA_ERROR 'У вас нет прав для управления псевдонимами учащихся';

  SELECT CJM.GRADE_ID
  FROM CJ2_JOURNAL CJM
  WHERE CJM.OBJ_ID = :I$CJ_ID
  INTO :V$GRADE_ID;

  SELECT FIRST 1 L.OBJ_ID, L.OBJ_TYPE_ID
  FROM LINKS L
  WHERE L.PARENT_ID = :V$GRADE_ID AND L.OBJ_TYPE_ID IN (10, 14) AND L.OBJ_ID = :I$STUDENT_ID
  INTO :OBJ_ID, :V$TYPE_ID;

  IF(OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Учащийся не найден';

  SELECT BLOB_ID FROM VAL_ADD(2991, :OBJ_ID, :I$TEXT) INTO :TMP;

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_ASST_LIST (
    I$YEAR_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$STAGE_ID BIGINT;
DECLARE VARIABLE V$GRADE_ID BIGINT;
DECLARE VARIABLE V$SUBJECT_ID BIGINT;
DECLARE VARIABLE V$ASST_ID BIGINT;
DECLARE VARIABLE S VARCHAR(1000);
DECLARE VARIABLE V VARCHAR(400);
DECLARE VARIABLE F FLOAT;
begin

  -- Все данные - только для ОО, только основные журналы
  -- в разрезе ступеней обучения

  -- Предметы
  TAG_NAME = 'subjects::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
    SELECT SUBJECT_ID, CAPTION, LIST(STAGE_INDEX, ',')
    FROM (
      SELECT DISTINCT J.SUBJECT_ID, C.CAPTION, J.STAGE_INDEX
      FROM CJ2_JOURNAL J
      LEFT JOIN OBJECT_CAPTION_GET(J.SUBJECT_ID) C ON 1 = 1
      JOIN LISTVALS LV ON LV.LISTVAL_ID = J.STAGE_INDEX AND LV.PARENT_ID IN (2141, 12941)
      WHERE J.DATE_DEL IS NULL AND J.YEAR_ID = :I$YEAR_ID AND J.JOURNAL_TYPE = 0
    )
    GROUP BY 1, 2
    ORDER BY 2
    INTO :V$OBJ_ID, :S, :V
  DO
  BEGIN
    TAG_NAME = 'subjects:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'subjects:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'subjects:r:name';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'subjects:r:stages';
    VAL = V;
    SUSPEND;
  END

  -- Параллели
  TAG_NAME = 'stages::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
    SELECT DISTINCT J.STAGE_INDEX, LV.COST, R.VAL
    FROM CJ2_JOURNAL J
    JOIN LISTVALS LV ON LV.LISTVAL_ID = J.STAGE_INDEX AND LV.PARENT_ID IN (2141, 12941)
    JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
    WHERE J.DATE_DEL IS NULL AND J.YEAR_ID = :I$YEAR_ID AND J.JOURNAL_TYPE = 0
    ORDER BY 2, 3
    INTO :V$OBJ_ID, :F, :S
  DO
  BEGIN
    TAG_NAME = 'stages:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'stages:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'stages:r:name';
    VAL = S;
    SUSPEND;
  END

  -- Учебные коллективы
  TAG_NAME = 'grades::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
    SELECT L9.OBJ_ID, LV.LISTVAL_ID, C.CAPTION
    FROM LINKS L2
    JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V49.LISTVAL_ID
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 187) AND L9.DATE_DEL IS NULL
    LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C ON 1 = 1
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    ORDER BY 2, 3
    INTO :V$OBJ_ID, :V, :S
  DO
  BEGIN
    TAG_NAME = 'grades:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'grades:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'grades:r:stage_id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'grades:r:name';
    VAL = S;
    SUSPEND;
  END

  -- Шкалы оценивания, пока все что есть
  TAG_NAME = 'assts::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
    SELECT T.MARK_TYPE_ID, T.MARK_NAME
    FROM CJ2_MARK_TYPE T
    WHERE T.IS_DEL = 0 AND T.PARENT_ID IS NULL AND T.MARK_TYPE_ID > 0 AND T.MARK_TYPE_ID <> 200 -- кроме
    ORDER BY 1
    INTO :V$OBJ_ID, :S
  DO
  BEGIN
    TAG_NAME = 'assts:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'assts:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'assts:r:name';
    IF(V$OBJ_ID = 799) THEN S = 'Критериальная'; -- вместо процента выполнения
    IF(V$OBJ_ID = 999) THEN S = 'Б/О'; -- безотметочная
    VAL = S;
    SUSPEND;
  END

  -- Все настройки скопом
  -- Комбинация (NULL, NULL, NULL) задает глобальную настройку для всей школы

  TAG_NAME = 'values::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
    SELECT A.OBJ_ID, A.STAGE_ID, A.GRADE_ID, A.SUBJECT_ID, A.ASST_ID
    FROM CJ2_ASSESSMENT A
    WHERE A.DATE_DEL IS NULL AND A.YEAR_ID = :I$YEAR_ID
    ORDER BY 1
    INTO :V$OBJ_ID, :V$STAGE_ID, :V$GRADE_ID, :V$SUBJECT_ID, :V$ASST_ID
  DO
  BEGIN
    TAG_NAME = 'values:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'values:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'values:r:stage_id';
    VAL = V$STAGE_ID;
    SUSPEND;
    TAG_NAME = 'values:r:grade_id';
    VAL = V$GRADE_ID;
    SUSPEND;
    TAG_NAME = 'values:r:subject_id';
    VAL = V$SUBJECT_ID;
    SUSPEND;
    TAG_NAME = 'values:r:asst_id';
    VAL = V$ASST_ID;
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_ASST_SET (
    I$YEAR_ID BIGINT NOT NULL,
    I$STAGE_ID BIGINT,
    I$SUBJECT_ID BIGINT,
    I$GRADE_ID BIGINT,
    I$ASST_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    OBJ_ID BIGINT)
AS
DECLARE VARIABLE CH SMALLINT;
DECLARE VARIABLE V$ASST_ID BIGINT;
begin

  -- На входе ASST_ID точно будет непустой

  SELECT FIRST 1 C.OBJ_ID, C.ASST_ID
  FROM CJ2_ASSESSMENT C
  WHERE C.DATE_DEL IS NULL AND C.YEAR_ID = :I$YEAR_ID AND COALESCE(C.STAGE_ID, 0) = COALESCE(:I$STAGE_ID, 0)
    AND COALESCE(C.SUBJECT_ID, 0) = COALESCE(:I$SUBJECT_ID, 0) AND COALESCE(C.GRADE_ID, 0) = COALESCE(:I$GRADE_ID, 0)
  INTO :OBJ_ID, :V$ASST_ID;

  -- Флаг изменений
  CH = 0;
  IF(OBJ_ID IS NULL OR V$ASST_ID <> I$ASST_ID) THEN CH = 1;

  -- Проверять прямо тут нельзя, поскольку настройки каскадируются
  /*IF(CH = 1 AND EXISTS(
    SELECT FIRST 1 1
    JOIN CJ2_JOURNAL J
    JOIN CJ2_JOURNAL_LESSONS L ON L.DATE_DEL IS NULL AND L.CJ_ID = J.OBJ_ID
      AND (J.SUBJECT_ID = :I$SUBJECT_ID OR :I$SUBJECT_ID IS NULL) AND (J.STAGE_INDEX = :I$STAGE_ID OR :I$STAGE_ID IS NULL)
    WHERE J.DATE_DEL IS NULL AND J.JOURNAL_TYPE = 0 AND J.YEAR_ID = :I$YEAR_ID
  ))
  THEN
    EXCEPTION DATA_ERROR 'Нельзя менять настройку, когда уже есть выставленные оценки или добавлены столбцы итоговых';*/

  IF(OBJ_ID IS NULL) THEN
  BEGIN
    INSERT INTO CJ2_ASSESSMENT
    (YEAR_ID, STAGE_ID, SUBJECT_ID, GRADE_ID, ASST_ID)
    VALUES (:I$YEAR_ID, :I$STAGE_ID, :I$SUBJECT_ID, :I$GRADE_ID, :I$ASST_ID)
    RETURNING OBJ_ID INTO :OBJ_ID;
  END
  ELSE IF(CH = 1) THEN
  BEGIN
    UPDATE CJ2_ASSESSMENT
    SET ASST_ID = :I$ASST_ID
    WHERE OBJ_ID = :OBJ_ID;
  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_ASST_VERIFY (
    I$YEAR_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    OBJ_ID BIGINT)
AS
DECLARE VARIABLE V$Y INTEGER;
DECLARE VARIABLE V$CY INTEGER;
begin

  SELECT LV.COST
  FROM LISTVALS LV
  WHERE LV.LISTVAL_ID = :I$YEAR_ID
  INTO :V$Y;

  SELECT FIRST 1 LV.COST
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$CY;

  IF(V$CY IS NULL OR V$Y IS NULL OR V$Y < V$CY) THEN EXCEPTION DATA_ERROR 'Нет данных учебного года или недопустимый учебный год';

  FOR
    SELECT C.OBJ_ID
    FROM CJ2_ASSESSMENT C
    WHERE C.DATE_DEL IS NULL AND C.YEAR_ID = :I$YEAR_ID
    INTO :OBJ_ID
  DO
  BEGIN
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_AUDIT_ACCESS (
    I$USER_ID VARCHAR(40))
RETURNS (
    FILTER_OWNER BIGINT,
    FILTER_TEACHER BIGINT)
AS
declare variable V$USER_ID bigint;
declare variable V$TYPE smallint;
declare variable V$PERSON_ID bigint;
begin

  IF(I$USER_ID = 'Веб-администратор') THEN V$USER_ID = 1; ELSE V$USER_ID = I$USER_ID;

  SELECT U.USER_TYPE, U.OBJ_ID
  FROM USERS U
  WHERE U.DATE_DEL IS NULL AND U.USER_ID = :V$USER_ID AND U.IS_BLOCKED = 0 AND (U.EXP_DATE IS NULL OR U.EXP_DATE > CURRENT_DATE)
  INTO :V$TYPE, :V$PERSON_ID;

  IF(V$TYPE IS NULL) THEN EXCEPTION DATA_ERROR 'Пользователь не найден';

  -- Руководители имеют полный доступ, остальные только по себе
  IF(V$TYPE NOT IN (1, 5, 6)) THEN
  BEGIN
    FILTER_TEACHER = V$PERSON_ID;
  END

  -- Фильтр по авторству пока оставляем без действия

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_AUDIT_DELETE (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$TYPE smallint;
declare variable V$PERSON_ID bigint;
declare variable V$OWNER_ID bigint;
declare variable V$TEACHER_ID bigint;
declare variable V$STATE_ID smallint;
begin

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  SELECT U.USER_TYPE, U.OBJ_ID
  FROM USERS U
  WHERE U.DATE_DEL IS NULL AND U.USER_ID = :I$USER_ID
  INTO :V$TYPE, :V$PERSON_ID;

  SELECT A.OBJ_ID, A.STATE_ID, A.OWNER_ID, A.TEACHER_ID
  FROM CJ2_AUDIT A
  WHERE A.OBJ_ID = :I$OBJ_ID AND A.DATE_DEL IS NULL
  INTO :OBJ_ID, :V$STATE_ID, :V$OWNER_ID, :V$TEACHER_ID;

  IF(OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Запись не найдена';
  IF(V$STATE_ID > 1) THEN EXCEPTION DATA_ERROR 'Запись находится в статусе, не допускающем удаление';
  IF(V$TYPE IS NULL OR V$TYPE NOT IN (1, 5, 6)) THEN EXCEPTION DATA_ERROR 'Пользователь не найден или недостаточный уровень доступа';

  UPDATE CJ2_AUDIT
  SET DATE_DEL = CURRENT_TIMESTAMP, USER_DEL = :I$USER_ID
  WHERE OBJ_ID = :OBJ_ID;

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_AUDIT_GET (
    I$OBJ_ID BIGINT,
    I$CJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
declare variable V$OBJ_ID bigint;
declare variable V$OWNER_ID bigint;
declare variable V$TEACHER_ID bigint;
declare variable V$CJ_ID bigint;
declare variable V$CJ_ID2 bigint;
declare variable V$MSG_TEXT varchar(1000);
declare variable V$STATE_ID smallint;
declare variable V$DATE_ADD timestamp;
declare variable V$RESOLVED_AT timestamp;
declare variable V$CONFIRMED_AT timestamp;
declare variable V$TYPE smallint;
declare variable V$PERSON_ID bigint;
declare variable V$GRADE_ID bigint;
declare variable V$SUBJECT_ID bigint;
begin

  SELECT A.OBJ_ID, A.OWNER_ID, A.TEACHER_ID, A.CJ_ID, A.MSG_TEXT, A.STATE_ID, A.DATE_ADD, A.RESOLVED_AT, A.CONFIRMED_AT
  FROM CJ2_AUDIT A
  WHERE A.DATE_DEL IS NULL AND A.OBJ_ID = :I$OBJ_ID
  INTO :V$OBJ_ID, :V$OWNER_ID, :V$TEACHER_ID, :V$CJ_ID, :V$MSG_TEXT, :V$STATE_ID, :V$DATE_ADD, :V$RESOLVED_AT, :V$CONFIRMED_AT;

  IF(I$OBJ_ID IS NOT NULL AND V$OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Запись не найдена';

  SELECT J.GRADE_ID, J.SUBJECT_ID
  FROM CJ2_JOURNAL J
  WHERE J.OBJ_ID = COALESCE(:V$CJ_ID, :I$CJ_ID)
  INTO :V$GRADE_ID, :V$SUBJECT_ID;

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  SELECT U.USER_TYPE, U.OBJ_ID
  FROM USERS U
  WHERE U.DATE_DEL IS NULL AND U.USER_ID = :I$USER_ID
  INTO :V$TYPE, :V$PERSON_ID;

  IF(V$TYPE IS NULL) THEN EXCEPTION DATA_ERROR 'Отказано в доступе';

  IF(V$TEACHER_ID IS NULL) THEN
  BEGIN
    SELECT FIRST 1 V1609.VAL
    FROM LINKS L186
    JOIN VALR V1609 ON V1609.OBJ_ID = L186.OBJ_ID AND V1609.PARAM_ID = 1609 AND V1609.IS_DEL = 0
    WHERE L186.PARENT_ID = :V$GRADE_ID AND L186.OBJ_TYPE_ID = 186 AND L186.DATE_DEL IS NULL
    ORDER BY L186.COST
    INTO :V$TEACHER_ID;
  END

  -- Открывать может только автор, кому назначено или администратор
  IF(V$TYPE NOT IN (1, 5, 6)) THEN
  BEGIN
    IF(I$OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Вы не можете создавать задачи аудита';
    IF(V$PERSON_ID <> V$TEACHER_ID AND I$USER_ID <> V$OWNER_ID) THEN EXCEPTION DATA_ERROR 'Отказано в доступе';
  END

  TAG_NAME = 'id';
  VAL = I$OBJ_ID;
  SUSPEND;

  TAG_NAME = 'state_id';
  VAL = V$STATE_ID;
  SUSPEND;

  TAG_NAME = 'state_name';
  VAL = (SELECT VAL FROM CJ2_AUDIT_STATUS(:V$STATE_ID));
  SUSPEND;

  TAG_NAME = 'owner_id';
  VAL = COALESCE(V$OWNER_ID, I$USER_ID);
  SUSPEND;

  TAG_NAME = 'role';
  IF(V$TYPE IN (1, 5, 6)) THEN VAL = 'admin';
  ELSE IF(I$USER_ID = V$OWNER_ID) THEN VAL = 'owner';
  ELSE IF(V$PERSON_ID = V$TEACHER_ID) THEN VAL = 'teacher';
  ELSE VAL = 'unknown';
  SUSPEND;

  TAG_NAME = 'iam';
  VAL = IIF(V$PERSON_ID = V$TEACHER_ID, 1, 0);
  SUSPEND;

  TAG_NAME = 'cj_id';
  VAL = COALESCE(V$CJ_ID, I$CJ_ID);
  SUSPEND;

  TAG_NAME = 'owner_name';
  VAL = (SELECT USER_NAME FROM USERS WHERE USER_ID = :V$OWNER_ID);
  SUSPEND;

  TAG_NAME = 'teacher_id';
  VAL = V$TEACHER_ID;
  SUSPEND;

  TAG_NAME = 'teacher_name';
  IF(V$TEACHER_ID IS NULL) THEN VAL = NULL; ELSE VAL = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$TEACHER_ID));
  SUSPEND;

  TAG_NAME = 'grade_id';
  VAL = V$GRADE_ID;
  SUSPEND;

  TAG_NAME = 'grade_name';
  IF(V$GRADE_ID IS NULL) THEN VAL = NULL; ELSE VAL = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$GRADE_ID));
  SUSPEND;

  TAG_NAME = 'subject_id';
  VAL = V$SUBJECT_ID;
  SUSPEND;

  TAG_NAME = 'subject_name';
  IF(V$SUBJECT_ID IS NULL) THEN VAL = NULL; ELSE VAL = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$SUBJECT_ID));
  SUSPEND;

  TAG_NAME = 'msg_text';
  VAL = V$MSG_TEXT;
  SUSPEND;

  TAG_NAME = 'date_add';
  VAL = (SELECT VAL FROM DATE2ISO(:V$DATE_ADD));
  SUSPEND;

  TAG_NAME = 'resolved_at';
  VAL = (SELECT VAL FROM DATE2ISO(:V$RESOLVED_AT));
  SUSPEND;

  TAG_NAME = 'confirmed_at';
  VAL = (SELECT VAL FROM DATE2ISO(:V$CONFIRMED_AT));
  SUSPEND;

  -- Если не указан журнал, выдаем список журналов
  TAG_NAME = 'journals::json&colon;array';
  VAL = 1;
  SUSPEND;
  V$CJ_ID = COALESCE(V$CJ_ID, I$CJ_ID);
  FOR
    SELECT J.OBJ_ID, J.JOURNAL_TYPE, J.JOURNAL_NAME || IIF(J.SUBJECT_ID IS NULL, '', ' - ' || C.CAPTION), J.TEACHER_ID, J.GRADE_ID
    FROM CJ2_JOURNAL J
    LEFT JOIN OBJECT_CAPTION_GET(J.SUBJECT_ID) C ON 1 = 1
    WHERE (J.DATE_DEL IS NULL OR J.OBJ_ID = :V$CJ_ID) AND (:V$CJ_ID IS NULL OR J.OBJ_ID = :V$CJ_ID)
    ORDER BY 2, 3
    INTO :V$OBJ_ID, :V$CJ_ID2, :V$MSG_TEXT, :V$TEACHER_ID, :V$GRADE_ID
  DO
  BEGIN
    TAG_NAME = 'journals:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'journals:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'journals:r:type';
    VAL = V$CJ_ID2;
    SUSPEND;
    TAG_NAME = 'journals:r:name';
    VAL = V$MSG_TEXT;
    SUSPEND;
    TAG_NAME = 'journals:r:teacher_id';
    VAL = V$TEACHER_ID;
    IF(V$TEACHER_ID IS NULL) THEN
    SELECT FIRST 1 V1609.VAL
    FROM LINKS L186
    JOIN VALR V1609 ON V1609.OBJ_ID = L186.OBJ_ID AND V1609.PARAM_ID = 1609 AND V1609.IS_DEL = 0
    WHERE L186.PARENT_ID = :V$GRADE_ID AND L186.OBJ_TYPE_ID = 186 AND L186.DATE_DEL IS NULL
    ORDER BY L186.COST
    INTO :VAL;
    SUSPEND;
  END

  -- Пока выбираем учителей старой функцией
  TAG_NAME = 'teachers::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT OBJ_ID, OBJ_CAPTION
    FROM CJ_TEACHER_LIST(NULL)
    INTO :V$TEACHER_ID, :V$MSG_TEXT
  DO
  BEGIN
    TAG_NAME = 'teachers:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'teachers:r:id';
    VAL = V$TEACHER_ID;
    SUSPEND;
    TAG_NAME = 'teachers:r:name';
    VAL = V$MSG_TEXT;
    SUSPEND;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_AUDIT_SET (
    I$OBJ_ID BIGINT,
    I$CJ_ID BIGINT,
    I$TEACHER_ID BIGINT,
    I$MSG_TEXT VARCHAR(1000),
    I$FLAGS SMALLINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$STATE_ID smallint;
declare variable V$TYPE bigint;
declare variable V$PERSON_ID bigint;
declare variable V$MSG_TEXT varchar(1000);
declare variable V$OWNER_ID bigint;
declare variable V$TEACHER_ID bigint;
begin

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  I$MSG_TEXT = TRIM(I$MSG_TEXT);
  IF(I$MSG_TEXT IS NULL OR CHAR_LENGTH(I$MSG_TEXT) < 3) THEN EXCEPTION DATA_ERROR 'Требуется ввести текст замечаний';

  IF(I$TEACHER_ID IS NULL OR (SELECT COALESCE(TYPE_ID, 0) FROM OBJECTS WHERE OBJ_ID = :I$TEACHER_ID) <> 14) THEN EXCEPTION DATA_ERROR 'Не выбран сотрудник, к которому относится замечание';

  SELECT U.USER_TYPE, U.OBJ_ID
  FROM USERS U
  WHERE U.DATE_DEL IS NULL AND U.USER_ID = :I$USER_ID
  INTO :V$TYPE, :V$PERSON_ID;

  IF(I$OBJ_ID IS NULL) THEN
  BEGIN

    IF(V$TYPE NOT IN (1, 5, 6)) THEN EXCEPTION DATA_ERROR 'Вы не можете создавать записи аудита';

    -- Создание новой записи
    INSERT INTO CJ2_AUDIT
    (CJ_ID, OWNER_ID, TEACHER_ID, MSG_TEXT, STATE_ID)
    VALUES (:I$CJ_ID, :I$USER_ID, :I$TEACHER_ID, :I$MSG_TEXT, IIF(:I$FLAGS = 5, 5, 0))
    RETURNING OBJ_ID INTO :OBJ_ID;

  END
  ELSE
  BEGIN

    -- Менять текст можно только если замечание в начальном статусе, а менять его может только автор
    SELECT A.OBJ_ID, A.STATE_ID, A.MSG_TEXT, A.OWNER_ID, A.TEACHER_ID
    FROM CJ2_AUDIT A
    WHERE A.OBJ_ID = :I$OBJ_ID AND A.DATE_DEL IS NULL
    INTO :OBJ_ID, :V$STATE_ID, :V$MSG_TEXT, :V$OWNER_ID, :V$TEACHER_ID;

    IF(OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Запись не найдена';
    IF(V$STATE_ID >= 2) THEN EXCEPTION DATA_ERROR 'Нельзя менять данные завершенного аудита';

    -- Изменился текст или исполнитель
    IF(I$MSG_TEXT <> V$MSG_TEXT OR I$TEACHER_ID <> V$TEACHER_ID) THEN
    BEGIN
      IF(V$TYPE NOT IN (1, 5, 6) AND I$USER_ID <> V$OWNER_ID) THEN EXCEPTION DATA_ERROR 'Текст может менять только автор или руководитель';
      IF(V$STATE_ID > 0) THEN EXCEPTION DATA_ERROR 'Текст нельзя менять, когда требования уже выполнены исполнителем';

      -- Старую запись удаляем для истории, новую добавляем со ссылкой на старуюю
      UPDATE CJ2_AUDIT
      SET DATE_DEL = CURRENT_TIMESTAMP
      WHERE OBJ_ID = :I$OBJ_ID;

      INSERT INTO CJ2_AUDIT
      (CJ_ID, OWNER_ID, TEACHER_ID, MSG_TEXT, STATE_ID, PARENT_ID)
      VALUES (:I$CJ_ID, :I$USER_ID, :I$TEACHER_ID, :I$MSG_TEXT, 0, :I$OBJ_ID)
      RETURNING OBJ_ID INTO :OBJ_ID;
    END

    IF(I$FLAGS = 1) THEN
    BEGIN
      -- Выполнено
      IF(V$STATE_ID <> 0) THEN EXCEPTION DATA_ERROR 'Уже выполнено';
      IF(V$TEACHER_ID <> V$PERSON_ID) THEN EXCEPTION DATA_ERROR 'Может выполнить только назначенный сотрудник';
      UPDATE CJ2_AUDIT SET STATE_ID = 1, RESOLVED_AT = CURRENT_TIMESTAMP WHERE OBJ_ID = :OBJ_ID;
    END
    ELSE IF(I$FLAGS = 2) THEN
    BEGIN
      -- Принять
      IF(V$STATE_ID <> 1) THEN EXCEPTION DATA_ERROR 'Замечания не устранены';
      IF(V$TYPE NOT IN (1, 5, 6) AND I$USER_ID <> V$OWNER_ID) THEN EXCEPTION DATA_ERROR 'Может принять только автор или руководитель';
      UPDATE CJ2_AUDIT SET STATE_ID = 2, RESOLVED_AT = CURRENT_TIMESTAMP WHERE OBJ_ID = :OBJ_ID;
    END
    ELSE IF(I$FLAGS = 10) THEN
    BEGIN
      -- На доработку
      IF(V$STATE_ID <> 1) THEN EXCEPTION DATA_ERROR 'Замечания не устранены';
      IF(V$TYPE NOT IN (1, 5, 6) AND I$USER_ID <> V$OWNER_ID) THEN EXCEPTION DATA_ERROR 'Может отправить на доработку только автор или руководитель';
      UPDATE CJ2_AUDIT SET STATE_ID = 0, RESOLVED_AT = CURRENT_TIMESTAMP WHERE OBJ_ID = :OBJ_ID;
    END
    ELSE IF(I$FLAGS = 3) THEN
    BEGIN
      -- Отменить
      IF(V$STATE_ID > 1) THEN EXCEPTION DATA_ERROR 'Аудит закрыт, исправления невозможны';
      IF(V$TYPE NOT IN (1, 5, 6) AND I$USER_ID <> V$OWNER_ID) THEN EXCEPTION DATA_ERROR 'Может отменить только автор или руководитель';
      UPDATE CJ2_AUDIT SET STATE_ID = 3, RESOLVED_AT = CURRENT_TIMESTAMP WHERE OBJ_ID = :OBJ_ID;
    END
    ELSE IF(I$FLAGS = 4) THEN
    BEGIN
      -- Принять без исправления
      IF(V$STATE_ID > 1) THEN EXCEPTION DATA_ERROR 'Аудит закрыт, исправления невозможны';
      IF(V$TYPE NOT IN (1, 5, 6) AND I$USER_ID <> V$OWNER_ID) THEN EXCEPTION DATA_ERROR 'Может принять без исполнения только автор или руководитель';
      UPDATE CJ2_AUDIT SET STATE_ID = 4, RESOLVED_AT = CURRENT_TIMESTAMP WHERE OBJ_ID = :OBJ_ID;
    END
    ELSE IF(I$FLAGS = 5) THEN
    BEGIN
      -- Извещение об отсутствии замечаний
      IF(V$STATE_ID > 1) THEN EXCEPTION DATA_ERROR 'Аудит закрыт, исправления невозможны';
      IF(V$TYPE NOT IN (1, 5, 6) AND I$USER_ID <> V$OWNER_ID) THEN EXCEPTION DATA_ERROR 'Может принять как отсутствие замечаний только автор или руководитель';
      UPDATE CJ2_AUDIT SET STATE_ID = 5, RESOLVED_AT = CURRENT_TIMESTAMP WHERE OBJ_ID = :OBJ_ID;
    END

  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_AUDIT_STATUS (
    I$STATUS SMALLINT)
RETURNS (
    VAL VARCHAR(100))
AS
begin

  IF(I$STATUS = 0) THEN VAL = 'Новое';
  ELSE IF(I$STATUS = 1) THEN VAL = 'Устранено';
  ELSE IF(I$STATUS = 2) THEN VAL = 'Завершено';
  ELSE IF(I$STATUS = 3) THEN VAL = 'Отменено';
  ELSE IF(I$STATUS = 4) THEN VAL = 'Аннулировано';
  ELSE IF(I$STATUS = 5) THEN VAL = 'Без замечаний';

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_AUDIT_TEST (
    I$USER_ID VARCHAR(40))
RETURNS (
    TO_ME SMALLINT,
    FROM_ME SMALLINT)
AS
begin

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  TO_ME = 0;
  FROM_ME = 0;

  -- Устраненные, которые выставлял я, для контроля
  SELECT COUNT(*)
  FROM CJ2_AUDIT A
  WHERE A.DATE_DEL IS NULL AND A.OWNER_ID = :I$USER_ID AND A.STATE_ID = 1
  INTO :FROM_ME;

  -- Новые замечения мне
  SELECT COUNT(*)
  FROM USERS U
  JOIN CJ2_AUDIT A ON A.DATE_DEL IS NULL AND A.TEACHER_ID = U.OBJ_ID AND A.STATE_ID = 0
  WHERE U.USER_ID = :I$USER_ID AND U.DATE_DEL IS NULL
  INTO :TO_ME;

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_AVMEMBERS_LIST (
    I$JT_ID BIGINT,
    I$USER_ID BIGINT,
    I$GROUP_ID BIGINT = null,
    I$SUBJECT_ID BIGINT = null,
    I$GPP_ID BIGINT = null)
RETURNS (
    OBJ_ID BIGINT,
    OBJ_NAME VARCHAR(1000),
    OBJ_TYPE_ID BIGINT,
    GROUP_ID BIGINT,
    STAGE_INDEX BIGINT,
    SEX BIGINT,
    LISTED SMALLINT,
    GUP_ID BIGINT)
AS
declare variable V$LICENCE_TYPE char(1);
begin

  SELECT STATUS FROM OU_LICENCE_TYPE INTO :V$LICENCE_TYPE;

  -- Сначала сотрудники, идут однократно
  IF(I$JT_ID IN (10, 11)) THEN
  BEGIN
      GROUP_ID = 0;
      STAGE_INDEX = NULL;
      LISTED = 0;
      FOR
          SELECT L14.OBJ_ID, L14.OBJ_TYPE_ID, CAST(V1.VAL || ' ' || V2.VAL || COALESCE(' ' || V3.VAL, '') AS VARCHAR(400)), V239.LISTVAL_ID
          FROM LINKS L2
          JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
          JOIN VALS V1 ON V1.OBJ_ID = L14.OBJ_ID AND V1.PARAM_ID IN (55, 59, 128) AND V1.IS_DEL = 0
          JOIN VALS V2 ON V2.OBJ_ID = L14.OBJ_ID AND V2.PARAM_ID IN (56, 60, 129) AND V2.IS_DEL = 0
          LEFT JOIN VALS V3 ON V3.OBJ_ID = L14.OBJ_ID AND V3.PARAM_ID IN (57, 61, 130) AND V3.IS_DEL = 0
          LEFT JOIN VALL V239 ON V239.OBJ_ID = L14.OBJ_ID AND V239.PARAM_ID IN (239, 88, 2544) AND V239.IS_DEL = 0
          WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND (:I$GROUP_ID IS NULL OR :I$GROUP_ID = 0)
          ORDER BY 3
          INTO :OBJ_ID, :OBJ_TYPE_ID, :OBJ_NAME, :SEX
      DO
      BEGIN
          SUSPEND;
      END
  END

  -- Учащиеся классов
  FOR
      SELECT L10.OBJ_ID, L10.OBJ_TYPE_ID, CAST(V1.VAL || ' ' || V2.VAL || COALESCE(' ' || V3.VAL, '') AS VARCHAR(400)), L9.OBJ_ID, V49.LISTVAL_ID, V239.LISTVAL_ID
      FROM LINKS L2
      JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
      JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
      JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 187) AND L9.DATE_DEL IS NULL AND (:I$GROUP_ID IS NULL OR L9.OBJ_ID = :I$GROUP_ID)
      JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      JOIN VALS V1 ON V1.OBJ_ID = L10.OBJ_ID AND V1.PARAM_ID IN (55, 59, 128) AND V1.IS_DEL = 0
      JOIN VALS V2 ON V2.OBJ_ID = L10.OBJ_ID AND V2.PARAM_ID IN (56, 60, 129) AND V2.IS_DEL = 0
      LEFT JOIN VALS V3 ON V3.OBJ_ID = L10.OBJ_ID AND V3.PARAM_ID IN (57, 61, 130) AND V3.IS_DEL = 0
      LEFT JOIN VALL V239 ON V239.OBJ_ID = L10.OBJ_ID AND V239.PARAM_ID IN (239, 88, 2544) AND V239.IS_DEL = 0
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      ORDER BY 3
      INTO :OBJ_ID, :OBJ_TYPE_ID, :OBJ_NAME, :GROUP_ID, :STAGE_INDEX, :SEX
  DO
  BEGIN
      -- Сначала в составе класса
      -- Есть ли в других группах по этому предмету ? Проверка только в общеобре !
      LISTED = 0;
      SELECT FIRST 1 1
      FROM LINKS LP179
      JOIN CJ2_JOURNAL J ON J.GRADE_ID = LP179.PARENT_ID AND J.DATE_DEL IS NULL AND J.SUBJECT_ID = :I$SUBJECT_ID
      JOIN LINKS LP2 ON LP2.OBJ_ID = LP179.PARENT_ID AND LP2.DATE_DEL IS NULL AND LP2.EXT_OBJ_ID IS NULL
      WHERE LP179.OBJ_ID = :OBJ_ID AND LP179.PARENT_TYPE_ID = 179 AND LP179.DATE_DEL IS NULL AND LP179.PARENT_ID <> :I$GPP_ID
        AND :I$JT_ID = 0 AND (:I$SUBJECT_ID IS NULL OR :I$SUBJECT_ID NOT IN (179, 34607))
      INTO :LISTED;
      -- Есть ли в других ГУП (только общеобр) ? передаем через I$JT_ID = -1
      GUP_ID = NULL;
      SELECT FIRST 1 LP256.PARENT_ID
      FROM LINKS LP256
      JOIN LINKS LP54 ON LP54.OBJ_ID = LP256.PARENT_ID AND LP54.PARENT_TYPE_ID = 54 AND LP54.DATE_DEL IS NULL
      JOIN LINKS LP400 ON LP400.OBJ_ID = LP54.PARENT_ID AND LP400.PARENT_TYPE_ID = 400 AND LP400.DATE_DEL IS NULL
      JOIN VALL V3022 ON V3022.OBJ_ID = LP400.PARENT_ID AND V3022.PARAM_ID = 3022 AND V3022.IS_DEL = 0 AND V3022.LISTVAL_ID = 3
      WHERE LP256.OBJ_ID = :OBJ_ID AND LP256.PARENT_TYPE_ID = 256 AND LP256.DATE_DEL IS NULL AND :I$JT_ID = -1
      INTO :GUP_ID;
      SUSPEND;
      -- Затем по группам, куда они входят (только для толстого клиента)
      FOR
          SELECT LPG.PARENT_ID
          FROM LINKS LPG
          WHERE LPG.OBJ_ID = :OBJ_ID AND LPG.PARENT_TYPE_ID IN (256, 347) AND LPG.DATE_DEL IS NULL AND :I$GROUP_ID IS NULL
          INTO :GROUP_ID
      DO
      BEGIN
          SUSPEND;
      END
  END

  -- Учащиеся ДПО
  LISTED = 0;
  FOR
      SELECT L10.OBJ_ID, L10.OBJ_TYPE_ID, CAST(V1.VAL || ' ' || V2.VAL || COALESCE(' ' || V3.VAL, '') AS VARCHAR(400)), L46.OBJ_ID, V239.LISTVAL_ID
      FROM LINKS L2
      JOIN LINKS L86 ON L86.PARENT_ID = L2.OBJ_ID AND L86.OBJ_TYPE_ID = 86 AND L86.DATE_DEL IS NULL
      JOIN LINKS L46 ON L46.PARENT_ID = L86.OBJ_ID AND L46.OBJ_TYPE_ID = 46 AND L46.DATE_DEL IS NULL AND (:I$GROUP_ID IS NULL OR L46.OBJ_ID = :I$GROUP_ID)
      JOIN LINKS L10 ON L10.PARENT_ID = L46.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      JOIN VALS V1 ON V1.OBJ_ID = L10.OBJ_ID AND V1.PARAM_ID IN (55, 59, 128) AND V1.IS_DEL = 0
      JOIN VALS V2 ON V2.OBJ_ID = L10.OBJ_ID AND V2.PARAM_ID IN (56, 60, 129) AND V2.IS_DEL = 0
      LEFT JOIN VALS V3 ON V3.OBJ_ID = L10.OBJ_ID AND V3.PARAM_ID IN (57, 61, 130) AND V3.IS_DEL = 0
      LEFT JOIN VALL V239 ON V239.OBJ_ID = L10.OBJ_ID AND V239.PARAM_ID IN (239, 88, 2544) AND V239.IS_DEL = 0
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND :V$LICENCE_TYPE = 'P'
      ORDER BY 3
      INTO :OBJ_ID, :OBJ_TYPE_ID, :OBJ_NAME, :GROUP_ID, :SEX
  DO
  BEGIN
      SUSPEND;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_CC_LIST (
    I$YEAR_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$PREV_ID BIGINT;
DECLARE VARIABLE V$ID BIGINT;
DECLARE VARIABLE V$LEVEL_ID BIGINT;
DECLARE VARIABLE V$COST FLOAT;
DECLARE VARIABLE S VARCHAR(1000);
DECLARE VARIABLE F VARCHAR(400);
DECLARE VARIABLE V$HAS_OO SMALLINT;
DECLARE VARIABLE V$HAS_SPO SMALLINT;
begin

  V$HAS_OO = 0;
  V$HAS_SPO = 0;

  TAG_NAME = 'levels::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
    SELECT DISTINCT V3327.LISTVAL_ID, C.VAL
    FROM LINKS L472
    JOIN VALL V3327 ON V3327.OBJ_ID = L472.OBJ_ID AND V3327.PARAM_ID = 3327 AND V3327.IS_DEL = 0 AND V3327.LISTVAL_ID IN (22, 26, 27, 28, 29, 13131)
    LEFT JOIN LISTVAL_TEXT(V3327.LISTVAL_ID) C ON 1 = 1
    WHERE L472.PARENT_TYPE_ID = 2 AND L472.OBJ_TYPE_ID = 472 AND L472.DATE_DEL IS NULL
    ORDER BY 1
    INTO :V$ID, :S
  DO
  BEGIN
    IF(V$ID IN (22, 26, 27)) THEN V$HAS_OO = 1;
    IF(V$ID IN (28, 29, 13131)) THEN V$HAS_SPO = 1;
    TAG_NAME = 'levels:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'levels:r:id';
    VAL = V$ID;
    SUSPEND;
    TAG_NAME = 'levels:r:name';
    VAL = S;
    SUSPEND;
  END

  TAG_NAME = 'defaults::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
    SELECT C.CONTROL_TYPE_ID, C.CONTROL_DESC, C.DEFAULT_COST, C."FILTER"
    FROM CJ2_CONTROL_TYPE C
    WHERE C.IS_DEL = 0 AND C.CONTROL_TYPE_ID NOT IN (0, 9000, 30000) -- контроль УУД и служебный
      AND (
        (:V$HAS_OO = 1 AND C."FILTER" LIKE '%GOU%') OR
        (:V$HAS_SPO = 1 AND C."FILTER" LIKE '%COLLEGE%')
      )
    ORDER BY 1
    INTO :V$ID, :S, :V$COST, :F
  DO
  BEGIN
    TAG_NAME = 'defaults:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'defaults:r:id';
    VAL = V$ID;
    SUSPEND;
    TAG_NAME = 'defaults:r:name';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'defaults:r:value';
    VAL = CAST(V$COST AS NUMERIC(18, 5));
    SUSPEND;
    TAG_NAME = 'defaults:r:mask';
    VAL = '';
    IF(F LIKE '%GOU%') THEN VAL = VAL || 'O';
    IF(F LIKE '%COLLEGE%') THEN VAL = VAL || 'C';
    IF(F LIKE '%DPO%') THEN VAL = VAL || 'P';
    SUSPEND;
  END

  SELECT FIRST 1 LV2.LISTVAL_ID
  FROM LISTVALS LV1
  JOIN LISTVALS LV2 ON LV2.LIST_ID = LV1.LISTVAL_ID AND LV2.IS_DEL = 0 AND LV2.COST < LV1.COST
  JOIN CJ2_CONTROL_COST CC ON CC.DATE_DEL IS NULL AND CC.YEAR_ID = LV2.LISTVAL_ID
  WHERE LV1.LISTVAL_ID = :I$YEAR_ID
  ORDER BY LV2.COST DESC
  INTO :V$PREV_ID;

  TAG_NAME = 'prev::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
    SELECT CC.LEVEL_ID, CC.CONTROL_TYPE_ID, CC.COST
    FROM CJ2_CONTROL_COST CC
    WHERE CC.DATE_DEL IS NULL AND CC.YEAR_ID = :V$PREV_ID
    INTO :V$LEVEL_ID, :V$ID, :V$COST
  DO
  BEGIN
    TAG_NAME = 'prev:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'prev:r:id';
    VAL = V$ID;
    SUSPEND;
    TAG_NAME = 'prev:r:level_id';
    VAL = V$LEVEL_ID;
    SUSPEND;
    TAG_NAME = 'prev:r:value';
    VAL = CAST(V$COST AS NUMERIC(18, 5));
    SUSPEND;
  END

  TAG_NAME = 'current::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
    SELECT CC.LEVEL_ID, CC.CONTROL_TYPE_ID, CC.COST
    FROM CJ2_CONTROL_COST CC
    WHERE CC.DATE_DEL IS NULL AND CC.YEAR_ID = :I$YEAR_ID
    INTO :V$LEVEL_ID, :V$ID, :V$COST
  DO
  BEGIN
    TAG_NAME = 'current:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'current:r:id';
    VAL = V$ID;
    SUSPEND;
    TAG_NAME = 'current:r:level_id';
    VAL = V$LEVEL_ID;
    SUSPEND;
    TAG_NAME = 'current:r:value';
    VAL = CAST(V$COST AS NUMERIC(18, 5));
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_CC_SET (
    I$YEAR_ID BIGINT NOT NULL,
    I$LEVEL_ID BIGINT,
    I$CONTROL_TYPE_ID BIGINT NOT NULL,
    I$COST FLOAT,
    I$USER_ID VARCHAR(40))
RETURNS (
    OBJ_ID BIGINT)
AS
DECLARE VARIABLE DT TIMESTAMP;
DECLARE VARIABLE V FLOAT;
DECLARE VARIABLE CV FLOAT;
DECLARE VARIABLE CCV FLOAT;
DECLARE VARIABLE CH SMALLINT;
begin

  IF(I$COST <> -1 AND (I$COST < 0.5 OR I$COST > 3)) THEN EXCEPTION DATA_ERROR 'Вес за пределами диапазона 0.5...3';

  SELECT FIRST 1 C.OBJ_ID, C.DATE_DEL, C.COST
  FROM CJ2_CONTROL_COST C
  WHERE C.YEAR_ID = :I$YEAR_ID AND COALESCE(C.LEVEL_ID, 0) = COALESCE(:I$LEVEL_ID, 0) AND C.CONTROL_TYPE_ID = :I$CONTROL_TYPE_ID
  INTO :OBJ_ID, :DT, :V;

  -- Заодно смотрим что в уровне по-умолчанию
  IF(I$LEVEL_ID IS NOT NULL) THEN
  SELECT FIRST 1 C.COST
  FROM CJ2_CONTROL_COST C
  WHERE C.YEAR_ID = :I$YEAR_ID AND C.LEVEL_ID IS NULL AND C.CONTROL_TYPE_ID = :I$CONTROL_TYPE_ID
  INTO :CV;

  SELECT C.DEFAULT_COST
  FROM CJ2_CONTROL_TYPE C
  WHERE C.CONTROL_TYPE_ID = :I$CONTROL_TYPE_ID
  INTO :CCV;

  -- Флаг изменений
  CH = 0;

  -- -1 на входе = запрет использования
  -- NULL на входе = по-умолчанию, запись удалить
  IF(I$COST IS NULL) THEN
  BEGIN
    IF(OBJ_ID IS NOT NULL AND (DT IS NULL OR V IS NOT NULL)) THEN
    BEGIN
      -- Если был запрет использования, контролей и так быть не должно
      -- Проверяем только случай что было какое-то значение, и оно сменилось на другое вышестоящее
      IF(V IS NOT NULL AND V <> -1) THEN
      BEGIN
        IF(ABS(COALESCE(CV, CCV) - V) > 0.001) THEN CH = 1;
      END

      IF(CH = 1 AND EXISTS(
        SELECT FIRST 1 1
        FROM CJ2_CONTROL C
        JOIN CJ2_JOURNAL_LESSONS L ON L.OBJ_ID = C.LESSON_ID AND L.DATE_DEL IS NULL
        JOIN CJ2_JOURNAL J ON J.OBJ_ID = L.CJ_ID AND J.DATE_DEL IS NULL AND J.YEAR_ID = :I$YEAR_ID
        WHERE C.DATE_DEL IS NULL AND C.CONTROL_TYPE_ID = :I$CONTROL_TYPE_ID
      ))
      THEN
        EXCEPTION DATA_ERROR 'Нельзя менять настройку, когда уже есть выставленные оценки по контролю';

      UPDATE CJ2_CONTROL_COST
      SET DATE_DEL = CURRENT_TIMESTAMP
      WHERE OBJ_ID = OBJ_ID;
    END
    OBJ_ID = NULL;
  END
  ELSE
  BEGIN
    -- Добавление или изменение
    -- Запрет - проверяем просто наличие контролей
    IF(I$COST = -1) THEN CH = 1;
    -- Если поменялось значение
    IF(ABS(COALESCE(V, CV, CCV) - I$COST) > 0.001) THEN CH = 1;

    IF(CH = 1 AND EXISTS(
      SELECT FIRST 1 1
      FROM CJ2_CONTROL C
      JOIN CJ2_JOURNAL_LESSONS L ON L.OBJ_ID = C.LESSON_ID AND L.DATE_DEL IS NULL
      JOIN CJ2_JOURNAL J ON J.OBJ_ID = L.CJ_ID AND J.DATE_DEL IS NULL AND J.YEAR_ID = :I$YEAR_ID
      WHERE C.DATE_DEL IS NULL AND C.CONTROL_TYPE_ID = :I$CONTROL_TYPE_ID AND (:I$COST = -1 OR C.CONTROL_COST <> :I$COST)
    ))
    THEN
      EXCEPTION DATA_ERROR 'Нельзя менять настройку, когда уже есть выставленные оценки по контролю';

    IF(OBJ_ID IS NULL) THEN
    BEGIN
      INSERT INTO CJ2_CONTROL_COST
      (YEAR_ID, LEVEL_ID, CONTROL_TYPE_ID, COST)
      VALUES (:I$YEAR_ID, :I$LEVEL_ID, :I$CONTROL_TYPE_ID, :I$COST)
      RETURNING OBJ_ID INTO :OBJ_ID;
    END
    ELSE IF(DT IS NOT NULL OR ABS(V - I$COST) > 0.001) THEN
    BEGIN
      UPDATE CJ2_CONTROL_COST
      SET DATE_DEL = NULL, COST = :I$COST
      WHERE OBJ_ID = :OBJ_ID;
    END
  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_CC_VERIFY (
    I$YEAR_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    OBJ_ID BIGINT)
AS
DECLARE VARIABLE V$Y INTEGER;
DECLARE VARIABLE V$CY INTEGER;
begin

  SELECT LV.COST
  FROM LISTVALS LV
  WHERE LV.LISTVAL_ID = :I$YEAR_ID
  INTO :V$Y;

  SELECT FIRST 1 LV.COST
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$CY;

  IF(V$CY IS NULL OR V$Y IS NULL OR V$Y < V$CY) THEN EXCEPTION DATA_ERROR 'Нет данных учебного года или недопустимый учебный год';

  FOR
    SELECT C.OBJ_ID
    FROM CJ2_CONTROL_COST C
    WHERE C.DATE_DEL IS NULL AND C.YEAR_ID = :I$YEAR_ID
    INTO :OBJ_ID
  DO
  BEGIN
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_CJ_LIST_PTP (
    I$CJ_ID BIGINT,
    I$TYPE INTEGER,
    I$SUBJECT_ID BIGINT,
    I$STAGE_INDEX BIGINT,
    I$STAGE_MASK BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
declare variable V$USER_ID bigint;
declare variable V$USER_TYPE smallint;
declare variable V$TEACHER_ID bigint;
declare variable V$OBJ_ID bigint;
declare variable V$OBJ_NAME varchar(1000);
begin

  -- Уровень доступа пользователя
  IF(I$USER_ID = 'Веб-администратор') THEN V$USER_ID = 1; ELSE V$USER_ID = CAST(I$USER_ID AS BIGINT);

  SELECT U.USER_TYPE, U.OBJ_ID
  FROM USERS U
  WHERE U.USER_ID = :V$USER_ID AND U.DATE_DEL IS NULL AND U.IS_BLOCKED = 0
  INTO :V$USER_TYPE, :V$TEACHER_ID;

  IF(I$TYPE = 0) THEN
  BEGIN
      -- Общеобразовательные - в stage_index будет параллель
  END
  ELSE IF(I$TYPE = 1) THEN
  BEGIN
      -- ВД
      I$STAGE_INDEX = 2155;
  END
  ELSE IF(I$TYPE = 2) THEN
  BEGIN
      -- ГПД и ДОУ
      I$STAGE_INDEX = 2141;
  END
  ELSE IF(I$TYPE = 3) THEN
  BEGIN
      -- ДО и УДОД
      I$STAGE_INDEX = 2143;
  END

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

  TAG_NAME = 'items';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'items::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
      SELECT P.OBJ_ID, P.OBJ_NAME
      FROM PTP P
      WHERE P.DATE_DEL IS NULL
          AND (P.LEVEL_ID = :I$STAGE_INDEX OR :I$STAGE_INDEX IS NULL OR EXISTS(
              SELECT FIRST 1 1
              FROM LISTVALS LV
              LEFT JOIN MASK_MATCH(:I$STAGE_MASK, LV.COST) MM ON 1 = 1
              WHERE LV.LISTVAL_ID = P.LEVEL_ID AND MM.RESULT = 1
          ))
          AND ((P.SUBJECT_ID IS NULL AND :I$SUBJECT_ID IS NULL) OR P.SUBJECT_ID = :I$SUBJECT_ID OR EXISTS(
              SELECT FIRST 1 1
              FROM LINKS L302
              JOIN VALL V2462 ON V2462.OBJ_ID = L302.OBJ_ID AND V2462.PARAM_ID = 2462 AND V2462.IS_DEL = 0
              JOIN VALL VX2462 ON VX2462.IS_DEL = 0 AND VX2462.PARAM_ID = 2462 AND VX2462.LISTVAL_ID = V2462.LISTVAL_ID
              JOIN LINKS LP51 ON LP51.OBJ_ID = VX2462.OBJ_ID AND LP51.PARENT_ID = P.SUBJECT_ID AND LP51.DATE_DEL IS NULL
              WHERE L302.PARENT_ID = :I$SUBJECT_ID AND L302.OBJ_TYPE_ID = 302 AND L302.DATE_DEL IS NULL
          ))
          AND (P.OWNER_ID = :V$TEACHER_ID OR :V$USER_TYPE IN (1, 5, 6))
      ORDER BY 2
      INTO :V$OBJ_ID, :V$OBJ_NAME
  DO
  BEGIN
      TAG_NAME = 'items:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'items:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'items:r:ptp_name';
      VAL = V$OBJ_NAME;
      SUSPEND;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_CLASS_JOURNALS (
    I$CLASS_ID BIGINT,
    I$DATE_FROM DATE,
    I$DATE_TO DATE,
    I$USER_ID VARCHAR(40))
RETURNS (
    GRADE_ID BIGINT,
    CJ_ID BIGINT,
    SUBJECT_ID BIGINT)
AS
begin

  FOR
    SELECT J.OBJ_ID, J.GRADE_ID, J.SUBJECT_ID
    FROM PERSON_MOVEMENTS M
    JOIN PERSON_MOVEMENTS M2 ON M2.DATE_DEL IS NULL AND M2.PERSON_ID = M.PERSON_ID
      AND (M2.DATE_IN <= :I$DATE_TO OR :I$DATE_TO IS NULL) AND (M2.DATE_OUT IS NULL OR M2.DATE_OUT >= :I$DATE_FROM OR :I$DATE_FROM IS NULL)
    JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.GRADE_ID = M2.GROUP_ID
    LEFT JOIN CJ2_JOURNAL_ACCESS(:I$USER_ID, J.OBJ_ID) A ON 1 = 1
    WHERE M.DATE_DEL IS NULL AND M.GROUP_ID = :I$CLASS_ID AND (M.DATE_IN <= :I$DATE_TO OR :I$DATE_TO IS NULL)
      AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :I$DATE_FROM OR :I$DATE_FROM IS NULL)
      AND A.ACCESS_LEVEL > 0
    INTO :CJ_ID, :GRADE_ID, :SUBJECT_ID
  DO
  BEGIN
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_DESCRIBE (
    I$USER_ID VARCHAR(40),
    I$APP VARCHAR(100) = NULL)
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$OU_TYPE CHAR(1);
DECLARE VARIABLE V$YEAR INTEGER;
DECLARE VARIABLE V$YEAR_ID BIGINT;
DECLARE VARIABLE V$DGAPP VARCHAR(100);
DECLARE VARIABLE P INTEGER;
begin

  P = POSITION('/' IN I$APP);
  IF(P > 0) THEN
  BEGIN
    V$DGAPP = SUBSTRING(I$APP FROM P + 1);
    I$APP = SUBSTRING(I$APP FROM 1 FOR P - 1);
  END

  TAG_NAME = 'ou_type';
  V$OU_TYPE = (SELECT STATUS FROM OU_LICENCE_TYPE);
  VAL = V$OU_TYPE;
  SUSPEND;

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;
  TAG_NAME = 'role';
  VAL = (SELECT USER_TYPE FROM USERS WHERE USER_ID = :I$USER_ID);
  SUSPEND;

  TAG_NAME = 'items';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'items::json&colon;array';
  VAL = 1;
  SUSPEND;

  IF(V$OU_TYPE IN ('O', 'C', 'S')) THEN
  BEGIN
    TAG_NAME = 'items:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'items:r:id';
    VAL = '0';
    SUSPEND;
    TAG_NAME = 'items:r:name';
    VAL = 'Общеобразовательные журналы';
    SUSPEND;
    TAG_NAME = 'items:r:access';
    VAL = '1';
    SUSPEND;
  END

  IF(V$OU_TYPE IN ('D', 'S')) THEN
  BEGIN
    TAG_NAME = 'items:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'items:r:id';
    VAL = '4';
    SUSPEND;
    TAG_NAME = 'items:r:name';
    VAL = 'Журналы посещения';
    SUSPEND;
    TAG_NAME = 'items:r:access';
    VAL = '1';
    SUSPEND;
  END

  IF(V$OU_TYPE IN ('O', 'S')) THEN
  BEGIN
    TAG_NAME = 'items:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'items:r:id';
    VAL = '1';
    SUSPEND;
    TAG_NAME = 'items:r:name';
    VAL = 'Внеурочная деятельность';
    SUSPEND;
    TAG_NAME = 'items:r:access';
    VAL = '1';
    SUSPEND;
  END

  IF(V$OU_TYPE IN ('O', 'S')) THEN
  BEGIN
    TAG_NAME = 'items:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'items:r:id';
    VAL = '2';
    SUSPEND;
    TAG_NAME = 'items:r:name';
    VAL = 'Группы продленного дня';
    SUSPEND;
    TAG_NAME = 'items:r:access';
    VAL = '1';
    SUSPEND;
  END

  IF(V$OU_TYPE IN ('O', 'S')) THEN
  BEGIN
    TAG_NAME = 'items:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'items:r:id';
    VAL = '3';
    SUSPEND;
    TAG_NAME = 'items:r:name';
    VAL = 'Дополнительное образование';
    SUSPEND;
    TAG_NAME = 'items:r:access';
    VAL = '1';
    SUSPEND;
  END

  IF(V$OU_TYPE IN ('U', 'P')) THEN
  BEGIN
    TAG_NAME = 'items:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'items:r:id';
    VAL = '3';
    SUSPEND;
    TAG_NAME = 'items:r:name';
    VAL = 'Журналы занятий';
    SUSPEND;
    TAG_NAME = 'items:r:access';
    VAL = '1';
    SUSPEND;
  END

  IF(V$DGAPP IS NULL OR V$DGAPP <> 'app.ptp') THEN
  BEGIN
    TAG_NAME = 'items:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'items:r:id';
    VAL = '10';
    SUSPEND;
    TAG_NAME = 'items:r:name';
    VAL = 'Журналы мероприятий';
    SUSPEND;
    TAG_NAME = 'items:r:access';
    VAL = '1';
    SUSPEND;
  END

  IF(V$DGAPP = 'app.ptp') THEN
  BEGIN
    TAG_NAME = 'items:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'items:r:id';
    VAL = '100';
    SUSPEND;
    TAG_NAME = 'items:r:name';
    VAL = 'Рабочие программы';
    SUSPEND;
    TAG_NAME = 'items:r:access';
    VAL = '1';
    SUSPEND;
  END

  -- Кнопки визарда
  -- Показываем текущий и следующий учебный год - начиная с мая месяца
  SELECT FIRST 1 LV.COST, LV.LISTVAL_ID
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$YEAR, :V$YEAR_ID;

  TAG_NAME = 'autobuttons';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'autobuttons::json&colon;array';
  VAL = 1;
  SUSPEND;
  TAG_NAME = 'autobuttons:r';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'autobuttons:r:id';
  VAL = V$YEAR_ID;
  SUSPEND;
  TAG_NAME = 'autobuttons:r:text';
  VAL = V$YEAR || '-' || (V$YEAR + 1);
  SUSPEND;

  V$YEAR_ID = NULL;
  SELECT FIRST 1 LISTVAL_ID
  FROM LISTVALS_LIST(29)
  WHERE IS_DEL = 0 AND COST = :V$YEAR + 1
  INTO :V$YEAR_ID;

  -- В режиме отладки показываем кнопку следующего года раньше, чем положено
  IF(I$APP = 'test' OR (EXTRACT(MONTH FROM CURRENT_DATE) >= 5 AND V$YEAR_ID IS NOT NULL AND V$YEAR <> EXTRACT(YEAR FROM CURRENT_DATE))) THEN
  BEGIN
    TAG_NAME = 'autobuttons:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'autobuttons:r:id';
    VAL = V$YEAR_ID;
    SUSPEND;
    TAG_NAME = 'autobuttons:r:text';
    VAL = (V$YEAR + 1) || '-' || (V$YEAR + 2);
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_EXT_CONTROLS (
    I$LESSON_ID BIGINT,
    I$STAGE_ID BIGINT,
    I$DATE TIMESTAMP)
RETURNS (
    CONTROL_ID BIGINT,
    MARK_SYSTEM_ID BIGINT,
    EXT_ID VARCHAR(100),
    TEACHER_ID BIGINT,
    GRADE_ID BIGINT,
    GRADE_TYPE_ID BIGINT,
    MEMBERS VARCHAR(4000))
AS
declare variable V$DATE date;
declare variable V$STUDENT_ID bigint;
begin

  FOR
      SELECT C.CONTROL_ID, C.MARK_SYSTEM_ID, C.EXT_ID, CJL.TEACHER_ID, J.GRADE_ID, J.GRADE_TYPE_ID, CJL.LESSON_DATE
      FROM CJ2_CONTROL C
      JOIN CJ2_JOURNAL_LESSONS CJL ON CJL.OBJ_ID = C.LESSON_ID AND CJL.DATE_DEL IS NULL
      JOIN CJ2_JOURNAL J ON J.OBJ_ID = CJL.CJ_ID AND J.DATE_DEL IS NULL
      WHERE C.DATE_DEL IS NULL AND C.CONTROL_TYPE_ID = 8000 AND C.EXT_ID IS NOT NULL
          AND (:I$STAGE_ID IS NULL OR C.CONTROL_ID = :I$STAGE_ID)
          AND (:I$LESSON_ID IS NULL OR C.LESSON_ID = :I$LESSON_ID)
      INTO :CONTROL_ID, :MARK_SYSTEM_ID, :EXT_ID, :TEACHER_ID, :GRADE_ID, :GRADE_TYPE_ID, :V$DATE
  DO
  BEGIN
      -- Список участников
      MEMBERS = '';

      FOR
          SELECT DISTINCT M.STUDENT_ID
          FROM CJ2_MEMBER_MOVEMENTS(:GRADE_ID, :GRADE_TYPE_ID) M
          WHERE :V$DATE IS NULL OR (M.DATE_FROM <= :V$DATE AND (M.DATE_TO IS NULL OR M.DATE_TO >= :V$DATE))
          INTO :V$STUDENT_ID
      DO
      BEGIN
          IF(MEMBERS <> '') THEN MEMBERS = MEMBERS || ',';
          MEMBERS = MEMBERS || V$STUDENT_ID;
      END

      SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_EXT_UPDATE_MARK (
    I$GRADE_ID BIGINT,
    I$EXT_ID VARCHAR(100),
    I$STUDENT_ID VARCHAR(100),
    I$MARK INTEGER,
    I$MAX_MARK INTEGER,
    I$USER_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$CONTROL_ID bigint;
declare variable V$STUDENT_ID bigint;
declare variable V$MARK_SYSTEM bigint;
declare variable V$MARK_ID bigint;
declare variable V$TYPE_ID bigint;
declare variable V$OLD_MARK bigint;
begin

  SELECT FIRST 1 C.CONTROL_TYPE_ID, C.CONTROL_ID, C.MARK_SYSTEM_ID
  FROM CJ2_JOURNAL J
  JOIN CJ2_JOURNAL_LESSONS L ON L.DATE_DEL IS NULL AND L.CJ_ID = J.OBJ_ID
  JOIN CJ2_CONTROL C ON C.DATE_DEL IS NULL AND C.LESSON_ID = L.OBJ_ID AND C.EXT_ID = :I$EXT_ID
  WHERE J.DATE_DEL IS NULL AND J.GRADE_ID = :I$GRADE_ID
  INTO :V$TYPE_ID, :V$CONTROL_ID, :V$MARK_SYSTEM;

  IF(V$TYPE_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Контроль не найден или был удален';
  IF(V$TYPE_ID <> 8000) THEN EXCEPTION DATA_ERROR 'Контроль не является контролем электронных курсов';

  SELECT FIRST 1 V3060.OBJ_ID
  FROM VALS V3060
  JOIN LINKS LPG ON LPG.OBJ_ID = V3060.OBJ_ID AND LPG.PARENT_ID = :I$GRADE_ID AND LPG.DATE_DEL IS NULL
  WHERE V3060.PARAM_ID = 3060 AND V3060.IS_DEL = 0 AND V3060.SVAL = :I$STUDENT_ID
  INTO :V$STUDENT_ID;

  IF(V$STUDENT_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Обучающийся не найден в группе';

  SELECT FIRST 1 M.MARK_ID, M.MARK_TYPE_ID
  FROM CJ2_MARK M
  WHERE M.DATE_DEL IS NULL AND M.CONTROL_ID = :V$CONTROL_ID AND M.STUDENT_ID = :V$STUDENT_ID
  INTO :OBJ_ID, :V$OLD_MARK;

  IF(I$MARK = 0) THEN
  BEGIN
      -- Отметки нет или курс не пройден
      I$MARK = NULL;
  END
  ELSE IF(V$MARK_SYSTEM = 100) THEN
  BEGIN
      -- зачет-незачет
      IF(I$MARK >= I$MAX_MARK / 2) THEN I$MARK = 1; ELSE I$MARK = 0;
  END
  ELSE IF(V$MARK_SYSTEM = 400) THEN
  BEGIN
      -- 5-балльная шкала
      I$MARK = ROUND((5.0 * I$MARK) / I$MAX_MARK);
  END
  ELSE IF(V$MARK_SYSTEM = 499) THEN
  BEGIN
      -- 20-балльная шкала
      I$MARK = ROUND((20.0 * I$MARK) / I$MAX_MARK);
  END
  ELSE IF(V$MARK_SYSTEM = 599) THEN
  BEGIN
      -- 100-балльная шкала
      I$MARK = ROUND((100.0 * I$MARK) / I$MAX_MARK);
  END
  ELSE I$MARK = NULL;

  SELECT FIRST 1 MT.MARK_TYPE_ID
  FROM CJ2_MARK_TYPE MT
  WHERE MT.IS_DEL = 0 AND MT.PARENT_ID = :V$MARK_SYSTEM AND MT.MARK_COST = :I$MARK
  INTO :V$MARK_ID;

  IF(V$MARK_ID IS NULL) THEN
  BEGIN

      UPDATE CJ2_MARK
      SET DATE_DEL = CURRENT_TIMESTAMP
      WHERE MARK_ID = :OBJ_ID;

  END
  ELSE IF(OBJ_ID IS NULL) THEN
  BEGIN

      INSERT INTO CJ2_MARK
      (CONTROL_ID, STUDENT_ID, MARK_TYPE_ID, MARK_DATE, IS_USED, USER_ID)
      VALUES (:V$CONTROL_ID, :V$STUDENT_ID, :V$MARK_ID, CURRENT_DATE, 1, :I$USER_ID)
      RETURNING MARK_ID INTO :OBJ_ID;

  END
  ELSE IF(V$OLD_MARK <> V$MARK_ID) THEN
  BEGIN

      UPDATE CJ2_MARK
      SET MARK_TYPE_ID = :V$MARK_ID
      WHERE MARK_ID = :OBJ_ID;

  END

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_FILE_VERIFY (
    I$LESSON_ID BIGINT,
    I$FILE_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    FILE_NAME VARCHAR(4000),
    FILE_ID BIGINT)
AS
declare variable V$CJ_ID bigint;
declare variable ACCESS_LEVEL smallint;
begin

  SELECT CJL.CJ_ID, B.OBJ_ID, B.FILE_NAME
  FROM CJ2_JOURNAL_LESSONS CJL
  JOIN CJ2_BLOB B ON B.LESSON_ID = CJL.OBJ_ID AND B.OBJ_ID = :I$FILE_ID AND B.DATE_DEL IS NULL
  WHERE CJL.OBJ_ID = :I$LESSON_ID AND CJL.DATE_DEL IS NULL
  INTO :V$CJ_ID, :FILE_ID, :FILE_NAME;

  IF(I$FILE_ID IS NOT NULL AND FILE_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Файл не найден';

  -- Проверяем права доступа к журналу
  ACCESS_LEVEL = (SELECT ACCESS_LEVEL FROM CJ2_JOURNAL_ACCESS(:I$USER_ID, :V$CJ_ID));
  IF(ACCESS_LEVEL = 0) THEN EXCEPTION DATA_ERROR 'Нет прав доступа к указанному журналу';

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_FULL_NAME (
    I$CJ_ID BIGINT)
RETURNS (
    VAL VARCHAR(1000))
AS
begin

  SELECT J.JOURNAL_NAME || COALESCE(' (' || VC.VAL || ')', '')
  FROM CJ2_JOURNAL J
  LEFT JOIN VALS VC on VC.OBJ_ID = J.SUBJECT_ID and VC.PARAM_ID IN (376, 1751) and VC.IS_DEL = 0
  WHERE J.OBJ_ID = :I$CJ_ID
  INTO :VAL;

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_GPP_COPY_LIST (
    I$OBJ_ID BIGINT,
    I$TYPE_ID INTEGER,
    I$SUBJECT_ID BIGINT,
    I$STAGE_INDEX BIGINT,
    I$STAGE_MASK INTEGER,
    I$NAME VARCHAR(400),
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
declare variable V$GRADE_ID bigint;
declare variable V$OBJ_ID bigint;
declare variable V$SEX bigint;
declare variable V$CLASS_ID bigint;
declare variable V$STAGE_ID bigint;
declare variable V$CLASS_CAPTION varchar(1000);
declare variable V$DATE date;
declare variable V$ORDER_DATE date;
declare variable S varchar(1000);
declare variable P integer;
begin

  -- Уровень доступа пользователя
  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  -- При сортировке в первую очередь выдаем начинающиеся с того же префикса, затем той же параллели
  -- В названии выбираем текст до второго пробела
  I$NAME = UPPER(I$NAME);
  P = POSITION(' ' IN I$NAME);
  IF(P > 0) THEN
  BEGIN
    P = P + 1;
    WHILE(P <= CHAR_LENGTH(I$NAME) AND SUBSTRING(I$NAME FROM P FOR 1) <> ' ') DO P = P + 1;
    IF(SUBSTRING(I$NAME FROM P FOR 1) <> ' ') THEN P = P + 1;
    I$NAME = SUBSTRING(I$NAME FROM 1 FOR P - 1);
  END

  TAG_NAME = 'items';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'items::json&colon;array';
  VAL = 1;
  SUSPEND;
  -- Только потоковые группы !
  FOR
    SELECT J.GRADE_ID, J.JOURNAL_NAME || IIF(J.SUBJECT_ID IS NULL, '', ' ' || C.CAPTION)
    FROM CJ2_JOURNAL J
    LEFT JOIN LINKS LP2 ON LP2.OBJ_ID = J.GRADE_ID AND LP2.PARENT_TYPE_ID = 2 AND LP2.DATE_DEL IS NULL
    LEFT JOIN OBJECT_CAPTION_GET(J.SUBJECT_ID) C ON 1 = 1
    WHERE J.DATE_DEL IS NULL AND J.JOURNAL_TYPE = :I$TYPE_ID AND (J.STAGE_INDEX = :I$STAGE_INDEX OR BIN_AND(J.STAGE_MASK, :I$STAGE_MASK) > 0)
      AND (J.OBJ_ID <> :I$OBJ_ID OR :I$OBJ_ID IS NULL) AND LP2.EXT_OBJ_ID IS NULL
    ORDER BY IIF(POSITION(:I$NAME IN UPPER(J.JOURNAL_NAME)) > 0, 0, IIF(J.STAGE_INDEX = :I$STAGE_INDEX, 1, 2)), 2
    INTO :V$GRADE_ID, :S
  DO
  BEGIN
    TAG_NAME = 'items:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'items:r:id';
    VAL = V$GRADE_ID;
    SUSPEND;
    TAG_NAME = 'items:r:name';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'items:r:members::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT L10.OBJ_ID, V55.VAL || ' ' || V56.VAL || COALESCE(' ' || V57.VAL, ''), V88.LISTVAL_ID, LPG.PARENT_ID, C.CAPTION, V49.LISTVAL_ID
      FROM LINKS L10
      JOIN VALS V55 ON V55.OBJ_ID = L10.OBJ_ID AND V55.PARAM_ID IN (55, 59, 128) AND V55.IS_DEL = 0
      JOIN VALS V56 ON V56.OBJ_ID = L10.OBJ_ID AND V56.PARAM_ID IN (56, 60, 129) AND V56.IS_DEL = 0
      LEFT JOIN VALS V57 ON V57.OBJ_ID = L10.OBJ_ID AND V57.PARAM_ID IN (57, 61, 130) AND V57.IS_DEL = 0
      LEFT JOIN VALL V88 ON V88.OBJ_ID = L10.OBJ_ID AND V88.PARAM_ID IN (88, 239, 2544) AND V88.IS_DEL = 0
      JOIN LINKS LPG ON LPG.OBJ_ID = L10.OBJ_ID AND LPG.PARENT_TYPE_ID IN (9, 125, 187, 243, 10) AND LPG.DATE_DEL IS NULL
      LEFT JOIN OBJECT_CAPTION_GET(LPG.PARENT_ID) C ON 1 = 1
      LEFT JOIN LINKS LP8 ON LP8.OBJ_ID = LPG.PARENT_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
      LEFT JOIN VALL V49 ON V49.OBJ_ID = LP8.PARENT_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
      WHERE L10.PARENT_ID = :V$GRADE_ID AND L10.OBJ_TYPE_ID IN (10, 14, 20) AND L10.DATE_DEL IS NULL
      INTO :V$OBJ_ID, :S, :V$SEX, :V$CLASS_ID, :V$CLASS_CAPTION, :V$STAGE_ID
    DO
    BEGIN
      TAG_NAME = 'items:r:members:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'items:r:members:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'items:r:members:r:name';
      VAL = S;
      SUSPEND;
      TAG_NAME = 'items:r:members:r:sex';
      VAL = V$SEX;
      SUSPEND;
      TAG_NAME = 'items:r:members:r:group_id';
      VAL = V$CLASS_ID;
      SUSPEND;
      TAG_NAME = 'items:r:members:r:group_name';
      VAL = V$CLASS_CAPTION;
      SUSPEND;
      TAG_NAME = 'items:r:members:r:stage_index';
      VAL = V$STAGE_ID;
      SUSPEND;

      V$DATE = NULL;
      V$ORDER_DATE = NULL;
      S = NULL;
      SELECT FIRST 1 M.DATE_IN, M.ORDER_DATE_IN, M.ORDER_NUM_IN
      FROM PERSON_MOVEMENTS M
      WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :V$OBJ_ID AND M.GROUP_ID = :V$GRADE_ID AND M.DATE_OUT IS NULL
      ORDER BY M.DATE_IN DESC
      INTO :V$DATE, :V$ORDER_DATE, :S;

      TAG_NAME = 'items:r:members:r:date';
      VAL = (SELECT VAL FROM DATE2ISO(:V$DATE, 0));
      SUSPEND;
      TAG_NAME = 'items:r:members:r:order_date';
      VAL = (SELECT VAL FROM DATE2ISO(:V$ORDER_DATE, 0));
      SUSPEND;
      TAG_NAME = 'items:r:members:r:order_num';
      VAL = S;
      SUSPEND;
    END
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_GRADE_ACCESS (
    I$GRADE_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    ACCESS_LEVEL INTEGER,
    IS_ADMIN SMALLINT,
    USER_ID BIGINT,
    TEACHER_ID BIGINT,
    USER_TYPE SMALLINT,
    IS_CLASSMATE SMALLINT)
AS
DECLARE VARIABLE V$TYPE_ID BIGINT;
begin

  -- Преобразуем ID
  IF(I$USER_ID = '00000000-0000-0000-0000-000000000000' OR I$USER_ID = 'Веб-администратор') THEN USER_ID = 1;
  ELSE USER_ID = I$USER_ID;

  -- Получаем данные объекта сотрудника
  SELECT U.USER_TYPE, U.OBJ_ID
  FROM USERS U
  WHERE U.USER_ID = :USER_ID AND U.DATE_DEL IS NULL AND U.IS_BLOCKED = 0
  INTO :USER_TYPE, :TEACHER_ID;

  IS_ADMIN = 0;
  -- Добавлено: социальный педагог, специалист по работе с обучающимися
  IF(USER_TYPE IN (1, 5, 6, 16, 20)) THEN IS_ADMIN = 1;

  SELECT TYPE_ID FROM OBJECTS WHERE OBJ_ID = :I$GRADE_ID INTO :V$TYPE_ID;

  IS_CLASSMATE = 0;

  IF(V$TYPE_ID = 9) THEN
  BEGIN
      SELECT FIRST 1 1
      FROM VALR V53
      WHERE V53.OBJ_ID = :I$GRADE_ID AND V53.PARAM_ID = 53 AND V53.IS_DEL = 0 AND V53.VAL = :TEACHER_ID
      INTO :IS_CLASSMATE;

      SELECT FIRST 1 1
      FROM LUSERS U
      WHERE U.USER_ID = :USER_ID AND U.ROOT_OBJ_ID = :I$GRADE_ID
      INTO :IS_CLASSMATE;
  END
  ELSE IF(V$TYPE_ID = 179) THEN
  BEGIN
  END

  -- 0 = нет доступа, такой журнал не показываем вовсе
  -- 1 = административный полный доступ (директор / завуч)
  -- 2 = доступ назначенного руководителя / предметника / исполнителя
  -- 3 = классный руководитель (только назначенный в классе, не через права доступа)
  -- 4 = временный доступ через механизм замещения
  ACCESS_LEVEL = 0;
  IF(IS_ADMIN = 1) THEN ACCESS_LEVEL = 1;
  ELSE BEGIN
      -- Есть ли кто-либо из учеников класса, где данный пользователь является классным руководителем ?
      IF(IS_CLASSMATE = 1) THEN ACCESS_LEVEL = 3;

      -- Предподает ли что-то кому-то из учеников группы ?
      IF(ACCESS_LEVEL = 0) THEN
      BEGIN
          SELECT FIRST 1 2
          FROM LINKS L10
          JOIN LINKS LPG ON LPG.OBJ_ID = L10.OBJ_ID AND LPG.PARENT_TYPE_ID IN (9, 179) AND LPG.DATE_DEL IS NULL
          JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.GRADE_ID = LPG.PARENT_ID AND J.TEACHER_ID = :TEACHER_ID
          WHERE L10.PARENT_ID = :I$GRADE_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
          INTO :ACCESS_LEVEL;
      END
  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_GROUPS_LIST (
    I$JT_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    GROUP_ID BIGINT,
    GROUP_NAME VARCHAR(1000),
    GROUP_TYPE_ID BIGINT,
    SORT_INDEX DOUBLE PRECISION,
    STAGE_INDEX BIGINT)
AS
declare variable V$LICENCE_TYPE char(1);
begin

  -- Только для толстого Параграфа !

  SELECT STATUS FROM OU_LICENCE_TYPE INTO :V$LICENCE_TYPE;

  -- Виртуальный каталог "сотрудники" - только для мероприятий
  IF(I$JT_ID IN (10, 11)) THEN
  BEGIN
      SORT_INDEX = -1;
      GROUP_ID = NULL;
      GROUP_TYPE_ID = 0;
      STAGE_INDEX = NULL;
      GROUP_NAME = 'Сотрудники';
      SUSPEND;
  END

  -- Список классов
  FOR
      SELECT L9.OBJ_ID, L9.OBJ_TYPE_ID, C.CAPTION, C.SORT_ORDER, V49.LISTVAL_ID
      FROM LINKS L2
      JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
      JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
      JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
      LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C ON 1 = 1
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      INTO :GROUP_ID, :GROUP_TYPE_ID, :GROUP_NAME, :SORT_INDEX, :STAGE_INDEX
  DO
  BEGIN
      SUSPEND;
  END

  -- Список ГУПов

  -- Список групп продленного дня

  -- Список групп внеурочки

  -- Список групп ДПО - только для ДПО
  FOR
      SELECT L46.OBJ_ID, L46.OBJ_TYPE_ID, C.CAPTION, 0, NULL
      FROM LINKS L2
      JOIN LINKS L86 ON L86.PARENT_ID = L2.OBJ_ID AND L86.OBJ_TYPE_ID = 86 AND L86.DATE_DEL IS NULL
      JOIN LINKS L46 ON L46.PARENT_ID = L86.OBJ_ID AND L46.OBJ_TYPE_ID = 46 AND L46.DATE_DEL IS NULL
      LEFT JOIN OBJECT_CAPTION_GET(L46.OBJ_ID) C ON 1 = 1
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND :V$LICENCE_TYPE = 'P'
      INTO :GROUP_ID, :GROUP_TYPE_ID, :GROUP_NAME, :SORT_INDEX, :STAGE_INDEX
  DO
  BEGIN
      SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_HOMEWORK_ADD (
    I$LESSON_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$LESSON_DATE DATE,
    I$TEXT VARCHAR(1000),
    I$STUDENT_IDS VARCHAR(2000),
    I$DST_DATE DATE,
    I$DST_LESSON_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    OBJ_ID BIGINT)
AS
DECLARE VARIABLE V$HW_TEXT VARCHAR(1000);
DECLARE VARIABLE V$STUDENT_IDS VARCHAR(2000);
DECLARE VARIABLE V$DST_LESSON_ID BIGINT;
DECLARE VARIABLE V$DST_DATE DATE;
DECLARE VARIABLE Y INTEGER;
DECLARE VARIABLE P INTEGER;
DECLARE VARIABLE D DATE;
begin

  -- LESSON_DATE передается чтобы не вычитывать обратно дату урока

  -- LESSON_ID не проверяем, предполагается что он уже проверен
  SELECT FIRST 1 H.OBJ_ID, H.HW_TEXT, H.STUDENT_IDS, H.DST_LESSON_ID, H.DST_DATE
  FROM CJ2_HOMEWORKS H
  WHERE H.DATE_DEL IS NULL AND H.LESSON_ID = :I$LESSON_ID AND H.OBJ_ID = :I$OBJ_ID
  INTO :OBJ_ID, :V$HW_TEXT, :V$STUDENT_IDS, :V$DST_LESSON_ID, :V$DST_DATE;

  IF(I$OBJ_ID IS NOT NULL AND OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Запись домашнего задания не найдена или была удалена';

  -- Проверяем, что урок на который задано задание - есть, и опубликован
  -- Дата не должна выходить за пределы учебного года
  Y = EXTRACT(YEAR FROM CURRENT_DATE);
  IF(EXTRACT(MONTH FROM CURRENT_DATE) < 9) THEN Y = Y - 1;
  IF(I$DST_DATE < '01.09.' || Y OR I$DST_DATE > '30.06.' || (Y + 1)) THEN
    EXCEPTION DATA_ERROR 'Дата домашнего задания не должна выходить за пределы учебного года. Для задания на лето укажите эту информацию в тексте';

  IF(I$DST_LESSON_ID IS NOT NULL) THEN
  BEGIN
    SELECT FIRST 1 L.IS_PUBLISHED + L.IS_COMPLETED, L.LESSON_DATE
    FROM CJ2_JOURNAL_LESSONS L
    WHERE L.DATE_DEL IS NULL AND L.OBJ_ID = :I$DST_LESSON_ID
    INTO :P, :D;

    IF(P IS NULL) THEN EXCEPTION DATA_ERROR 'Выбранный урок не найден в журнале';
    IF(P = 0) THEN EXCEPTION DATA_ERROR 'Урок, на который задается домашнее задание, должен быть опубликован или отмечен как проведенный';
    IF(I$LESSON_DATE > D) THEN EXCEPTION DATA_ERROR 'Нельзя указывать домашнее задание со сдачей на урок, стоящем раньше урока, на котором задание выдано';
  END
  ELSE IF(I$DST_DATE IS NOT NULL) THEN
  BEGIN
    IF(I$LESSON_DATE > I$DST_DATE) THEN EXCEPTION DATA_ERROR 'Нельзя указывать домашнее задание со сдачей раньше даты выдачи';
  END

  -- Формальная валидация ID студентов, что там числа
  SELECT COUNT(*)
  FROM STR_TO_ID_LIST(:I$STUDENT_IDS)
  INTO :P;

  IF(I$OBJ_ID IS NULL) THEN
  BEGIN
    INSERT INTO CJ2_HOMEWORKS
    (LESSON_ID, HW_TEXT, STUDENT_IDS, DST_LESSON_ID, DST_DATE)
    VALUES (:I$LESSON_ID, :I$TEXT, :I$STUDENT_IDS, :I$DST_LESSON_ID, :I$DST_DATE)
    RETURNING OBJ_ID INTO :OBJ_ID;
  END
  ELSE IF (I$TEXT <> V$HW_TEXT OR COALESCE(I$STUDENT_IDS, '') <> COALESCE(V$STUDENT_IDS, '') OR COALESCE(I$DST_LESSON_ID, 0) <> COALESCE(V$DST_LESSON_ID, 0)
    OR COALESCE(I$DST_DATE, '01.01.2000') <> COALESCE(V$DST_DATE, '01.01.2000')) THEN
  BEGIN
    UPDATE CJ2_HOMEWORKS
    SET HW_TEXT = :I$TEXT, STUDENT_IDS = :I$STUDENT_IDS, DST_LESSON_ID = :I$DST_LESSON_ID, DST_DATE = :I$DST_DATE
    WHERE LESSON_ID = :I$LESSON_ID AND OBJ_ID = :I$OBJ_ID;
  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_JOURNAL_ACCESS (
    I$USER_ID VARCHAR(40),
    I$CJ_ID BIGINT)
RETURNS (
    ACCESS_LEVEL INTEGER,
    TEACHER_ID BIGINT,
    USER_TYPE INTEGER,
    USER_ID BIGINT,
    IS_CLASSMATE SMALLINT,
    IS_ADMIN SMALLINT,
    IS_SUBST SMALLINT)
AS
DECLARE VARIABLE V$TEACHER_ID BIGINT;
DECLARE VARIABLE V$GRADE_ID BIGINT;
DECLARE VARIABLE V$ACCESS_LEVEL SMALLINT;
DECLARE VARIABLE V$JU SMALLINT;
begin

  -- Преобразуем ID
  IF(I$USER_ID = '00000000-0000-0000-0000-000000000000' OR I$USER_ID = 'Веб-администратор') THEN USER_ID = 1;
  ELSE USER_ID = I$USER_ID;

  -- Получаем данные объекта сотрудника
  SELECT U.USER_TYPE, U.OBJ_ID
  FROM USERS U
  WHERE U.USER_ID = :USER_ID AND U.DATE_DEL IS NULL AND U.IS_BLOCKED = 0
  INTO :USER_TYPE, :TEACHER_ID;

  SELECT J.TEACHER_ID, J.GRADE_ID
  FROM CJ2_JOURNAL J
  WHERE J.DATE_DEL IS NULL AND J.OBJ_ID = :I$CJ_ID
  INTO :V$TEACHER_ID, :V$GRADE_ID;

  IS_ADMIN = 0;
  IF(USER_TYPE IN (1, 5, 6)) THEN IS_ADMIN = 1;

  IS_SUBST = 0;
  IS_CLASSMATE = 0;
  SELECT FIRST 1 1
  FROM LINKS L10
  JOIN LINKS LP9 ON LP9.OBJ_ID = L10.OBJ_ID AND LP9.PARENT_TYPE_ID = 9 AND LP9.DATE_DEL IS NULL
  JOIN VALR V53 ON V53.OBJ_ID = LP9.PARENT_ID AND V53.PARAM_ID = 53 AND V53.IS_DEL = 0 AND V53.VAL = :TEACHER_ID
  WHERE L10.PARENT_ID = :V$GRADE_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
  INTO :IS_CLASSMATE;

  -- 0 = нет доступа, такой журнал не показываем вовсе
  -- 1 = административный полный доступ (директор / завуч)
  -- 2 = доступ назначенного руководителя / предметника / исполнителя
  -- 3 = классный руководитель (только назначенный в классе, не через права доступа)
  -- 4 = временный доступ через механизм замещения
  -- 5 = доступ социальному педагогу и специалисту по работе с обучающимися
  -- 6 = только чтение
  ACCESS_LEVEL = 0;
  IF(IS_ADMIN = 1) THEN ACCESS_LEVEL = 1;
  IF(TEACHER_ID = V$TEACHER_ID) THEN ACCESS_LEVEL = 2;
  ELSE BEGIN

    -- Есть ли кто-либо из учеников класса, где данный пользователь является классным руководителем ?
    IF(IS_CLASSMATE = 1) THEN ACCESS_LEVEL = 3;

    SELECT FIRST 1 1
    FROM CJ2_JOURNAL_LESSONS CJL
    WHERE CJL.DATE_DEL IS NULL AND CJL.CJ_ID = :I$CJ_ID AND CJL.TEACHER_ID = :TEACHER_ID
      AND CJL.LESSON_DATE >= DATEADD(-3 DAY TO CURRENT_DATE) AND CJL.LESSON_DATE <= DATEADD(14 DAY TO CURRENT_DATE)
    INTO :IS_SUBST;

    IF(IS_SUBST = 0) THEN
    SELECT FIRST 1 1
    FROM CJ2_REPL_PROCESS P
    WHERE P.DATE_DEL IS NULL AND P.REPL_DATE >= DATEADD(-3 DAY TO CURRENT_DATE) AND P.REPL_DATE <= DATEADD(14 DAY TO CURRENT_DATE)
      AND P.REPL_PERSON_ID = :TEACHER_ID AND ((P.REPL_CJ_ID IS NULL AND P.CJ_ID = :I$CJ_ID) OR P.REPL_CJ_ID = :I$CJ_ID)
    INTO :IS_SUBST;

    -- Категорию 4 выставляем только если учитель не получил более высоких прав
    IF(IS_SUBST = 1 AND ACCESS_LEVEL = 0) THEN ACCESS_LEVEL = 4;

  END

  -- Проверяем доступ для ГПД, ДО, ДОУ (воспитатель, помощник воспитателя)
  IF(ACCESS_LEVEL IN (0, 4)) THEN
  BEGIN
    SELECT FIRST 1 2
    FROM LINKS L186
    JOIN VALR V1609 ON V1609.OBJ_ID = L186.OBJ_ID AND V1609.PARAM_ID = 1609 AND V1609.IS_DEL = 0 AND V1609.VAL = :TEACHER_ID
    WHERE L186.PARENT_ID = :V$GRADE_ID AND L186.OBJ_TYPE_ID = 186 AND L186.DATE_DEL IS NULL
    UNION
    SELECT FIRST 1 2
    FROM LINKS L165
    JOIN VALR V1556 ON V1556.OBJ_ID = L165.OBJ_ID AND V1556.PARAM_ID IN (1556, 1575) AND V1556.IS_DEL = 0 AND V1556.VAL = :TEACHER_ID
    WHERE L165.PARENT_ID = :V$GRADE_ID AND L165.OBJ_TYPE_ID IN (165, 170) AND L165.DATE_DEL IS NULL
    INTO :ACCESS_LEVEL;
  END

  IF(ACCESS_LEVEL = 0) THEN
  BEGIN
    IF(USER_TYPE IN (16, 20)) THEN ACCESS_LEVEL = 5;

    SELECT FIRST 1 JU.ACCESS
    FROM CJ2_JOURNAL_USERS JU
    WHERE JU.DATE_DEL IS NULL AND JU.USER_ID = :USER_ID AND JU.CJ_ID = :I$CJ_ID
    INTO :V$JU;

    IF(V$JU = 0) THEN ACCESS_LEVEL = 4; -- назначенный вручную
    ELSE IF(V$JU = 1) THEN ACCESS_LEVEL = 6; -- назначенный вручную только чтение
  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_JOURNAL_ACCESS_ADD (
    I$CJ_ID BIGINT,
    I$USER BIGINT,
    I$ACCESS SMALLINT,
    I$USER_ID VARCHAR(40))
AS
declare variable V$OBJ_ID bigint;
declare variable V$ACCESS integer;
begin

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;
  IF(I$USER = 1) THEN EXIT;

  IF(I$ACCESS IS NULL) THEN
  BEGIN
    UPDATE CJ2_JOURNAL_USERS
    SET DATE_DEL = CURRENT_TIMESTAMP, DELETED_BY = :I$USER_ID
    WHERE DATE_DEL IS NULL AND CJ_ID = :I$CJ_ID AND USER_ID = :I$USER;
  END
  ELSE
  BEGIN
    SELECT FIRST 1 JU.OBJ_ID, JU.ACCESS
    FROM CJ2_JOURNAL_USERS JU
    WHERE JU.DATE_DEL IS NULL AND JU.CJ_ID = :I$CJ_ID AND JU.USER_ID = :I$USER
    INTO :V$OBJ_ID, :V$ACCESS;

    IF(V$OBJ_ID IS NULL) THEN
    BEGIN
      INSERT INTO CJ2_JOURNAL_USERS
      (CJ_ID, USER_ID, ACCESS, ADDED_BY)
      VALUES (:I$CJ_ID, :I$USER, :I$ACCESS, :I$USER_ID);
    END
    ELSE IF(V$ACCESS <> I$ACCESS) THEN
    BEGIN
      UPDATE CJ2_JOURNAL_USERS
      SET ACCESS = :I$ACCESS
      WHERE OBJ_ID = :V$OBJ_ID;
    END
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_JOURNAL_ACCESS_UPD (
    I$CJ_ID BIGINT,
    I$USER_ID BIGINT)
AS
declare variable V$USER_ID bigint;
declare variable V$USER_TYPE smallint;
declare variable V$DD timestamp;
declare variable V$CLASS_ID bigint;
declare variable V$ROLE smallint;
declare variable V$CURRENT_ROLE smallint;
declare variable V$TEACHER_ID bigint;
declare variable V$GROUP_ID bigint;
declare variable V$PERSON_ID bigint;
declare variable V$CJ_ID bigint;
begin

  -- Роли
  -- 0 = нет доступа, такой журнал не показываем вовсе
  -- 1 = административный полный доступ (директор / завуч)
  -- 2 = доступ назначенного руководителя / предметника / исполнителя
  -- 3 = классный руководитель (только назначенный в классе, не через права доступа)
  -- 4 = временный доступ через механизм замещения, здесь не назначается
  -- 5 = доступ социальному педагогу и специалисту по работе с обучающимися
  -- 6 = только чтение

  -- Передается или CJ_ID, или USER_ID
  -- Также может быть вариант, когда указаны оба
  IF(I$CJ_ID IS NOT NULL) THEN
  BEGIN

    -- Пересчет прав для журнала

    SELECT J.TEACHER_ID, J.GRADE_ID
    FROM CJ2_JOURNAL J
    WHERE J.OBJ_ID = :I$CJ_ID
    INTO :V$TEACHER_ID, :V$GROUP_ID;

    FOR
      SELECT U.USER_ID, U.USER_TYPE, U.DATE_DEL, LU.ROOT_OBJ_ID, U.OBJ_ID, JU.ACCESS
      FROM USERS U
      LEFT JOIN CJ2_JOURNAL_AUTOUSERS JU ON JU.CJ_ID = :I$CJ_ID AND JU.USER_ID = U.USER_ID AND JU.DATE_DEL IS NULL
      -- Проверяем классное руководство, заданное через права пользователя (учебные коллективы)
      LEFT JOIN LUSERS LU ON LU.USER_ID = U.USER_ID AND LU.LEVEL_ID = 50
      WHERE U.DATE_DEL IS NULL AND (:I$USER_ID IS NULL OR U.USER_ID = :I$USER_ID) AND U.USER_TYPE NOT IN (12, 22)
      INTO :V$USER_ID, :V$USER_TYPE, :V$DD, :V$CLASS_ID, :V$PERSON_ID, :V$CURRENT_ROLE
    DO
    BEGIN

      V$ROLE = NULL;

      IF(V$DD IS NULL) THEN
      BEGIN
        -- Всегда есть полный административный доступ у админов, завучей и специалистов
        IF(V$USER_TYPE IN (1, 5, 6)) THEN V$ROLE = 1;
        -- Специальный доступ соцпедагогу и специалисту по работе с обучающимися
        ELSE IF(V$USER_TYPE IN (16, 20)) THEN V$ROLE = 5;
        -- Классный руководитель
        ELSE IF(V$USER_TYPE = 8) THEN
        BEGIN
          IF(EXISTS(
            SELECT FIRST 1 1
            FROM LINKS L10
            JOIN LINKS LPG ON LPG.OBJ_ID = L10.OBJ_ID AND LPG.PARENT_ID = :V$CLASS_ID AND LPG.DATE_DEL IS NULL
            WHERE L10.PARENT_ID = :V$GROUP_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
          ))
          THEN V$ROLE = 3;

          IF(V$ROLE IS NULL AND EXISTS (
            SELECT FIRST 1 1
            FROM LINKS L10
            JOIN LINKS LPG ON LPG.OBJ_ID = L10.OBJ_ID AND LPG.PARENT_TYPE_ID IN (9, 187) AND LPG.DATE_DEL IS NULL
            JOIN VALR V53 ON V53.OBJ_ID = LPG.PARENT_ID AND V53.PARAM_ID = 53 AND V53.IS_DEL = 0 AND V53.VAL = :V$PERSON_ID
            WHERE L10.PARENT_ID = :V$GROUP_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
          ))
          THEN V$ROLE = 3;
        END

        -- Все прочие - смотрим по конкретному журналу
        IF(V$ROLE IS NULL) THEN
        BEGIN
          IF(V$TEACHER_ID = V$PERSON_ID) THEN V$ROLE = 2;

          IF(V$ROLE IS NULL) THEN
          BEGIN
            IF(EXISTS(
              SELECT FIRST 1 1
              FROM LINKS L186
              JOIN VALR V1609 ON V1609.OBJ_ID = L186.OBJ_ID AND V1609.PARAM_ID = 1609 AND V1609.IS_DEL = 0 AND V1609.VAL = :V$PERSON_ID
              WHERE L186.PARENT_ID = :V$GROUP_ID AND L186.OBJ_TYPE_ID = 186 AND L186.DATE_DEL IS NULL
            ))
            THEN V$ROLE = 2;
          END
        END

      END

      IF(V$ROLE IS NULL) THEN
      BEGIN
        -- Удалить все доступы, если пользователь удален или доступ не положен
        UPDATE CJ2_JOURNAL_AUTOUSERS
        SET DATE_DEL = CURRENT_TIMESTAMP
        WHERE CJ_ID = :I$CJ_ID AND USER_ID = :V$USER_ID AND DATE_DEL IS NULL;
      END
      ELSE IF(V$ROLE <> V$CURRENT_ROLE OR V$CURRENT_ROLE IS NULL) THEN
      BEGIN
        UPDATE OR INSERT INTO CJ2_JOURNAL_AUTOUSERS
        (CJ_ID, USER_ID, ACCESS, DATE_DEL)
        VALUES (:I$CJ_ID, :V$USER_ID, :V$ROLE, NULL)
        MATCHING (CJ_ID, USER_ID);
      END

    END

  END
  ELSE
  BEGIN

    -- Пересчет прав для пользователя
    SELECT U.USER_ID, U.USER_TYPE, U.DATE_DEL, LU.ROOT_OBJ_ID, U.OBJ_ID
    FROM USERS U
    -- Проверяем классное руководство, заданное через права пользователя (учебные коллективы)
    LEFT JOIN LUSERS LU ON LU.USER_ID = U.USER_ID AND LU.LEVEL_ID = 50
    WHERE U.USER_ID = :I$USER_ID
    INTO :V$USER_ID, :V$USER_TYPE, :V$DD, :V$CLASS_ID, :V$PERSON_ID;

    FOR
      SELECT J.OBJ_ID, J.GRADE_ID, JU.ACCESS, J.TEACHER_ID
      FROM CJ2_JOURNAL J
      LEFT JOIN CJ2_JOURNAL_AUTOUSERS JU ON JU.CJ_ID = J.OBJ_ID AND JU.USER_ID = :I$USER_ID AND JU.DATE_DEL IS NULL
      WHERE J.DATE_DEL IS NULL
      INTO :V$CJ_ID, :V$GROUP_ID, :V$CURRENT_ROLE, :V$TEACHER_ID
    DO
    BEGIN

      V$ROLE = NULL;

      IF(V$DD IS NULL) THEN
      BEGIN
        -- Всегда есть полный административный доступ у админов, завучей и специалистов
        IF(V$USER_TYPE IN (1, 5, 6)) THEN V$ROLE = 1;
        -- Специальный доступ соцпедагогу и специалисту по работе с обучающимися
        ELSE IF(V$USER_TYPE IN (16, 20)) THEN V$ROLE = 5;
        -- Классный руководитель
        ELSE IF(V$USER_TYPE = 8) THEN
        BEGIN
          IF(EXISTS(
            SELECT FIRST 1 3
            FROM LINKS L10
            JOIN LINKS LPG ON LPG.OBJ_ID = L10.OBJ_ID AND LPG.PARENT_ID = :V$CLASS_ID AND LPG.DATE_DEL IS NULL
            WHERE L10.PARENT_ID = :V$GROUP_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
          ))
          THEN V$ROLE = 3;

          IF(V$ROLE IS NULL AND EXISTS (
            SELECT FIRST 1 3
            FROM LINKS L10
            JOIN LINKS LPG ON LPG.OBJ_ID = L10.OBJ_ID AND LPG.PARENT_TYPE_ID IN (9, 187) AND LPG.DATE_DEL IS NULL
            JOIN VALR V53 ON V53.OBJ_ID = LPG.PARENT_ID AND V53.PARAM_ID = 53 AND V53.IS_DEL = 0 AND V53.VAL = :V$PERSON_ID
            WHERE L10.PARENT_ID = :V$GROUP_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
          ))
          THEN V$ROLE = 3;
        END

        -- Все прочие - смотрим по конкретному журналу
        IF(V$ROLE IS NULL) THEN
        BEGIN
          IF(V$TEACHER_ID = V$PERSON_ID) THEN V$ROLE = 2;

          IF(V$ROLE IS NULL) THEN
          BEGIN
            IF(EXISTS(
              SELECT FIRST 1 1
              FROM LINKS L186
              JOIN VALR V1609 ON V1609.OBJ_ID = L186.OBJ_ID AND V1609.PARAM_ID = 1609 AND V1609.IS_DEL = 0 AND V1609.VAL = :V$PERSON_ID
              WHERE L186.PARENT_ID = :V$GROUP_ID AND L186.OBJ_TYPE_ID = 186 AND L186.DATE_DEL IS NULL
            ))
            THEN V$ROLE = 2;
          END
        END

      END

      IF(V$ROLE IS NULL) THEN
      BEGIN
        -- Удалить все доступы, если пользователь удален или доступ не положен
        UPDATE CJ2_JOURNAL_AUTOUSERS
        SET DATE_DEL = CURRENT_TIMESTAMP
        WHERE CJ_ID = :V$CJ_ID AND USER_ID = :V$USER_ID AND DATE_DEL IS NULL;
      END
      ELSE IF(V$ROLE <> V$CURRENT_ROLE OR V$CURRENT_ROLE IS NULL) THEN
      BEGIN
        UPDATE OR INSERT INTO CJ2_JOURNAL_AUTOUSERS
        (CJ_ID, USER_ID, ACCESS, DATE_DEL)
        VALUES (:V$CJ_ID, :I$USER_ID, :V$ROLE, NULL)
        MATCHING (CJ_ID, USER_ID);
      END

    END

  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_JOURNAL_ADD (
    I$OBJ_ID BIGINT,
    I$JOURNAL_TYPE SMALLINT NOT NULL,
    I$GRADE_ID BIGINT,
    I$GRADE_TYPE_ID BIGINT,
    I$SUBJECT_ID BIGINT,
    I$TEACHER_ID BIGINT,
    I$JOURNAL_NAME VARCHAR(1000),
    I$STAGE_INDEX INTEGER,
    I$USER_ID VARCHAR(40) = NULL,
    I$STAGE_MASK BIGINT = 0,
    I$REF_ID BIGINT = NULL,
    I$YEAR_ID BIGINT = NULL,
    I$PERIOD_ID BIGINT = NULL,
    I$WEEKS INTEGER = NULL,
    I$HOURS FLOAT = NULL,
    I$IS_ENABLED SMALLINT = 1,
    I$RCM_MODE SMALLINT = 0,
    I$DURATION SMALLINT = NULL,
    I$DAYMASK SMALLINT = 0,
    I$EXT_INFO VARCHAR(1000) = NULL,
    I$VK_ENABLED SMALLINT = NULL,
    I$ROOM_ID BIGINT = NULL,
    I$ASST_ID BIGINT = NULL)
RETURNS (
    CJ_ID BIGINT,
    GRADE_ID BIGINT,
    GRADE_TYPE_ID BIGINT,
    JOURNAL_NAME VARCHAR(1000))
AS
DECLARE VARIABLE V$SCHOOL_ID BIGINT;
DECLARE VARIABLE V$USER_ID BIGINT;
DECLARE VARIABLE V$ACCESS SMALLINT;
DECLARE VARIABLE V$TEACHER_ID BIGINT;
DECLARE VARIABLE V$OWNER_ID BIGINT;
DECLARE VARIABLE V$OU_TYPE CHAR(1);
DECLARE VARIABLE V$LINK_ID BIGINT;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$MOVE_DATE DATE;
DECLARE VARIABLE V$ORDER_DATE DATE;
DECLARE VARIABLE V$GRADE_TYPE_ID BIGINT;
DECLARE VARIABLE V$OLD_GRADE BIGINT;
DECLARE VARIABLE V$OLD_GRADE_TYPE BIGINT;
DECLARE VARIABLE V$COPP BIGINT;
DECLARE VARIABLE V$PERIOD_ID BIGINT;
DECLARE VARIABLE V$WEEKS INTEGER;
DECLARE VARIABLE V$HOURS FLOAT;
DECLARE VARIABLE V$RCM_MODE SMALLINT;
DECLARE VARIABLE V$DURATION INTEGER;
DECLARE VARIABLE V$Y INTEGER;
DECLARE VARIABLE V$SUBJECT_MS BIGINT;
DECLARE VARIABLE V$STAGE_INDEX_OVZ BIGINT;
DECLARE VARIABLE V$REF_ID BIGINT;
DECLARE VARIABLE V$CHAT_ID VARCHAR(400);
DECLARE VARIABLE V$ROOM_ID BIGINT;
DECLARE VARIABLE V$GS_ID BIGINT;
DECLARE VARIABLE V$ASST_ID BIGINT;
DECLARE VARIABLE S VARCHAR(1000);
DECLARE VARIABLE VI VARCHAR(100);
DECLARE VARIABLE VT1 VARCHAR(100);
DECLARE VARIABLE VT2 VARCHAR(100);
DECLARE VARIABLE T INTEGER;
begin

  -- !!! Проверка прав доступа
  IF(I$USER_ID = 'Веб-администратор') THEN V$USER_ID = 1; ELSE V$USER_ID = CAST(I$USER_ID AS BIGINT);

  SELECT U.OBJ_ID
  FROM USERS U
  WHERE U.USER_ID = :V$USER_ID AND U.DATE_DEL IS NULL AND U.IS_BLOCKED = 0
  INTO :V$TEACHER_ID;

  V$OU_TYPE = (SELECT STATUS FROM OU_LICENCE_TYPE);
  I$RCM_MODE = COALESCE(I$RCM_MODE, 0);
  I$DAYMASK = COALESCE(I$DAYMASK, 0);

  SELECT ACCESS_LEVEL FROM CJ2_JOURNAL_ACCESS(:I$USER_ID, :I$OBJ_ID) INTO :V$ACCESS;
  IF(I$OBJ_ID IS NOT NULL AND V$ACCESS = 0) THEN EXCEPTION DATA_ERROR 'Нет доступа к журналу';
  IF(I$OBJ_ID IS NOT NULL AND V$ACCESS = 6) THEN EXCEPTION DATA_ERROR 'Вы не можете вносить изменения в журнал';

  SELECT J.OBJ_ID, J.TEACHER_ID, J.GRADE_ID, J.GRADE_TYPE_ID, J.PERIOD_ID, J.WEEKS, J.HOURS, J.RCM_MODE, J.DURATION, J.REF_ID, J.CHAT_ID, J.ASST_ID
  FROM CJ2_JOURNAL J
  WHERE J.OBJ_ID = :I$OBJ_ID AND J.DATE_DEL IS NULL
  INTO :CJ_ID, :V$OWNER_ID, :V$OLD_GRADE, :V$OLD_GRADE_TYPE, :V$PERIOD_ID, :V$WEEKS, :V$HOURS, :V$RCM_MODE, :V$DURATION, :V$REF_ID, :V$CHAT_ID, :V$ASST_ID;

  IF(I$PERIOD_ID IS NULL AND V$PERIOD_ID IS NOT NULL) THEN I$PERIOD_ID = V$PERIOD_ID;
  IF(I$WEEKS IS NULL AND V$WEEKS IS NOT NULL) THEN I$WEEKS = V$WEEKS;
  IF(I$HOURS IS NULL AND V$HOURS IS NOT NULL) THEN I$HOURS = V$HOURS;
  IF(I$DURATION IS NULL AND V$DURATION IS NOT NULL) THEN I$DURATION = V$DURATION;
  IF(I$REF_ID IS NULL AND V$REF_ID IS NOT NULL) THEN I$REF_ID = V$REF_ID;

  IF(I$OBJ_ID IS NULL) THEN
  BEGIN
    IF(I$JOURNAL_TYPE IN (2, 3) AND I$GRADE_TYPE_ID = 179) THEN
    BEGIN
      -- В журналах ГПД и ДО в subject_id передается id группы
      I$GRADE_TYPE_ID = 46;
      I$GRADE_ID = I$SUBJECT_ID;
      I$SUBJECT_ID = NULL;
    END
    ELSE IF(I$JOURNAL_TYPE IN (4) AND I$GRADE_TYPE_ID = 179) THEN
    BEGIN
      -- В журнале ДОУ в subject_id передается id группы
      I$GRADE_TYPE_ID = 9;
      I$GRADE_ID = I$SUBJECT_ID;
      I$SUBJECT_ID = NULL;
    END
  END
  ELSE
  BEGIN
    IF(CJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Журнал не найден';
    IF(V$ACCESS <> 1 AND (V$TEACHER_ID <> I$TEACHER_ID OR V$TEACHER_ID <> V$OWNER_ID OR V$OWNER_ID IS NULL OR I$TEACHER_ID IS NULL)) THEN
      EXCEPTION DATA_ERROR 'Не-административные пользователи не могут редактировать чужие журналы';

    -- Привязки к группам не могут меняться
    I$GRADE_TYPE_ID = V$OLD_GRADE_TYPE;
    I$GRADE_ID = V$OLD_GRADE;
  END

  -- Для ГПД и ДО получаем тип сами
  IF(I$GRADE_ID IS NOT NULL) THEN
  BEGIN
    SELECT TYPE_ID FROM OBJECTS WHERE OBJ_ID = :I$GRADE_ID INTO :V$GRADE_TYPE_ID;
    IF(V$GRADE_TYPE_ID NOT IN (9, 179, 46, 256)) THEN EXCEPTION DATA_ERROR 'Недопустимый тип коллектива для этого типа журнала';
    IF(V$OLD_GRADE_TYPE <> V$GRADE_TYPE_ID) THEN EXCEPTION DATA_ERROR 'Системная ошибка - не совпадает тип коллектива в журнале. Переоткройте диалог редактирования';
  END

  -- При начальном создании визардом журналов ГПД и ДО выставляем маску на 4 дней недели
  IF(I$JOURNAL_TYPE IN (2, 3) AND I$DAYMASK = 0 AND I$TEACHER_ID IN (0, 1)) THEN I$DAYMASK = 31;

  I$JOURNAL_NAME = TRIM(I$JOURNAL_NAME);
  IF(I$JOURNAL_NAME IS NULL OR CHAR_LENGTH(I$JOURNAL_NAME) < 1) THEN EXCEPTION DATA_ERROR 'Слишком короткое название журнала';
  IF(I$JOURNAL_TYPE IN (0, 1) AND I$SUBJECT_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Для журнала этого вида должен быть указан предмет';
  IF(I$GRADE_TYPE_ID IS NULL) THEN EXCEPTION DATA_ERROR 'При сохранении журнала должен быть назначен учебный коллектив. Добавьте хотя бы одного ученика';
  IF(I$JOURNAL_TYPE IN (2, 3) AND I$DAYMASK = 0) THEN EXCEPTION DATA_ERROR 'Вы не указали дни недели, когда проводятся занятия';
  GRADE_TYPE_ID = I$GRADE_TYPE_ID;

  IF(I$DURATION < 15) THEN EXCEPTION DATA_ERROR 'Минимальная длительность занятия - 15 минут';
  IF(I$DURATION > 720) THEN EXCEPTION DATA_ERROR 'Максимальная длительность занятия - 12 часов (720 минут)';

  SELECT FIRST 1 OBJ_ID
  FROM LINKS
  WHERE PARENT_ID IS NULL AND OBJ_TYPE_ID = 2 AND DATE_DEL IS NULL
  INTO :V$SCHOOL_ID;

  IF(V$SCHOOL_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не найдена ОУ';

  -- Вакантная ставка предметника или журнал ГПД, ДО ?
  IF(I$TEACHER_ID = 0 OR I$TEACHER_ID = 1) THEN I$TEACHER_ID = NULL;

  -- Если учебный год не указан - берем текущий
  IF(I$YEAR_ID IS NULL) THEN
  BEGIN
    SELECT V1236.LISTVAL_ID
    FROM VALL V1236
    WHERE V1236.OBJ_ID = :V$SCHOOL_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
    INTO :I$YEAR_ID;
  END

  SELECT LV.COST
  FROM LISTVALS LV
  WHERE LV.LISTVAL_ID = :I$YEAR_ID
  INTO :V$Y;

  -- Проверяем, что выбранный период попадает в нужный учебный год
  IF(I$PERIOD_ID IS NOT NULL) THEN
  BEGIN
    IF(NOT EXISTS(
      SELECT FIRST 1 1
      FROM LINKS L154
      JOIN VALD V1169 ON V1169.OBJ_ID = L154.OBJ_ID AND V1169.PARAM_ID = 1169 AND V1169.IS_DEL = 0
        AND V1169.VAL >= '01.09.' || :V$Y AND V1169.VAL <= '31.05.' || (:V$Y + 1)
      WHERE L154.PARENT_ID = :I$PERIOD_ID AND L154.OBJ_TYPE_ID = 154 AND L154.DATE_DEL IS NULL
    ))
    THEN EXCEPTION DATA_ERROR 'Выбранные учебные периоды не попадают в выбранный учебный год';
  END

  -- Корректируем номер параллели для классов ОВЗ
  IF(V$OU_TYPE IN ('O', 'S') AND EXISTS(SELECT FIRST 1 1 FROM LISTVALS WHERE LISTVAL_ID = :I$STAGE_INDEX AND PARENT_ID = 12941)) THEN
  BEGIN
    SELECT FIRST 1 LV2.LISTVAL_ID
    FROM LISTVALS LV1
    JOIN LISTVALS LV2 ON LV2.PARENT_ID = 2141 AND LV2.COST = LV1.COST
    WHERE LV1.LISTVAL_ID = :I$STAGE_INDEX
    INTO :I$STAGE_INDEX;
  END

  -- Если PERIOD_ID не задан (генерация визардом), то подставляем первый подходящий по параллели и датам в нужном году
  -- Для классов 1-9 задаем четверти, для 10-12 полугодия
  IF(I$PERIOD_ID IS NULL) THEN
  BEGIN

    -- Стараемся подобрать расписание исходя из номера параллели и этапа
    SELECT FIRST 1 CAST(LV.COST AS INTEGER)
    FROM LISTVALS LV
    WHERE LV.LISTVAL_ID = :I$STAGE_INDEX
    INTO :VI;

    IF(I$STAGE_INDEX IN (37, 38, 39, 40)) THEN
    BEGIN
      VT1 = 'НАЧАЛЬН';
      VT2 = 'НОО';
    END
    ELSE IF(I$STAGE_INDEX IN (41, 42, 43, 44, 45)) THEN
    BEGIN
      VT1 = 'ОСНОВ';
      VT2 = 'ООО';
    END
    ELSE IF(I$STAGE_INDEX IN (46, 47, 48)) THEN
    BEGIN
      VT1 = 'СРЕДН';
      VT2 = 'СОО';
    END

    -- Расписание учебных периодов. Приоритетно ищем через КУГ
    SELECT FIRST 1 L481.OBJ_ID
    FROM LINKS L481
    JOIN VALL V3390 ON V3390.OBJ_ID = L481.OBJ_ID AND V3390.PARAM_ID = 3390 AND V3390.IS_DEL = 0 AND V3390.LISTVAL_ID NOT IN (11717, 14261) -- не архивный !
    JOIN VALL V3389 ON V3389.OBJ_ID = L481.OBJ_ID AND V3389.PARAM_ID = 3389 AND V3389.IS_DEL = 0 AND V3389.LISTVAL_ID = :I$YEAR_ID
    WHERE L481.PARENT_ID = :V$SCHOOL_ID AND L481.OBJ_TYPE_ID = 481 AND L481.DATE_DEL IS NULL
    INTO :V$GS_ID;
    -- В 2023-2024 году разрешаем выбирать периоды по старой схеме, если нет КУГ
    IF(V$GS_ID IS NULL AND V$Y <= 2023) THEN
    BEGIN
      SELECT FIRST 1 L150.OBJ_ID
      FROM LINKS L150
      WHERE L150.PARENT_ID = :V$SCHOOL_ID AND L150.OBJ_TYPE_ID = 150 AND L150.DATE_DEL IS NULL
      INTO :V$GS_ID;
    END

    SELECT FIRST 1 L151.OBJ_ID
    -- Просто выбор между четвертями, полугодиями и семестрами
    FROM LINKS L151
    JOIN VALS V1147 ON V1147.OBJ_ID = L151.OBJ_ID AND V1147.PARAM_ID = 1147 AND V1147.IS_DEL = 0
    WHERE L151.PARENT_ID = :V$GS_ID AND L151.OBJ_TYPE_ID = 151 AND L151.DATE_DEL IS NULL AND EXISTS(
      SELECT FIRST 1 1
      FROM LINKS L154
      JOIN VALD V1169 ON V1169.OBJ_ID = L154.OBJ_ID AND V1169.PARAM_ID = 1169 AND V1169.IS_DEL = 0 AND V1169.VAL >= '01.09.' || :V$Y AND V1169.VAL < '01.09.' || (:V$Y + 1)
      JOIN VALL V1170 ON V1170.OBJ_ID = L154.OBJ_ID AND V1170.PARAM_ID = 1170 AND V1170.IS_DEL = 0 AND (
        (:I$STAGE_INDEX <= 45 AND V1170.LISTVAL_ID IN (12, 13, 14, 15)) OR
        (:I$STAGE_INDEX IN (46, 47, 48) AND V1170.LISTVAL_ID IN (10, 11)) OR
        (:I$STAGE_INDEX IN (49, 50, 51, 52, 53, 54, 13145) AND V1170.LISTVAL_ID IN (19, 20))
      )
      WHERE L154.PARENT_ID = L151.OBJ_ID AND L154.OBJ_TYPE_ID = 154 AND L154.DATE_DEL IS NULL
    )
    -- Высший приоритет если период с номером параллели - записано как 1 класс или 1,2,3 классы
    -- Далее по этапу обучения - НОО/ООО/СОО или название этапа
    ORDER BY IIF(POSITION(:VI || ' ' IN V1147.VAL) > 0 OR POSITION(:VI || ',' IN V1147.VAL) > 0 AND POSITION('КЛАСС' IN UPPER(V1147.VAL)) > 0, 0,
      IIF(POSITION(:VT1 IN UPPER(V1147.VAL)) > 0 OR POSITION(:VT2 IN UPPER(V1147.VAL)) > 0, 1, 3))
    INTO :I$PERIOD_ID;

    -- Если для учителя есть ровно один закрепленный кабинет - фиксируем его
    IF(I$ROOM_ID IS NULL AND I$TEACHER_ID IS NOT NULL AND I$TEACHER_ID NOT IN (0, 1)) THEN
    BEGIN
      FOR
        SELECT L61.OBJ_ID
        FROM LINKS L73
        JOIN LINKS L16 ON L16.PARENT_ID = L73.OBJ_ID AND L16.OBJ_TYPE_ID = 16 AND L16.DATE_DEL IS NULL
        JOIN LINKS L61 ON L61.PARENT_ID = L16.OBJ_ID AND L61.OBJ_TYPE_ID = 61 AND L61.DATE_DEL IS NULL
        JOIN VALL V525 ON V525.OBJ_ID = L61.OBJ_ID AND V525.PARAM_ID = 525 AND V525.IS_DEL = 0 AND V525.LISTVAL_ID IN (23, 12764)
        JOIN VALR V1344 ON V1344.OBJ_ID = L61.OBJ_ID AND V1344.PARAM_ID = 1344 AND V1344.IS_DEL = 0 AND V1344.VAL = :I$TEACHER_ID
        WHERE L73.PARENT_ID = :V$SCHOOL_ID AND L73.OBJ_TYPE_ID = 73 AND L73.DATE_DEL IS NULL
        INTO :V$ROOM_ID
      DO
      BEGIN
        IF(I$ROOM_ID IS NULL) THEN I$ROOM_ID = V$ROOM_ID;
        ELSE I$ROOM_ID = -1; -- если более одного кабинета на учителя, скидываем
      END
      IF(I$ROOM_ID < 0) THEN I$ROOM_ID = NULL;
    END
  END

  -- Получаем ID базового предмета для модульных
  SELECT FIRST 1 LP301.OBJ_ID
  FROM VALR V3159
  JOIN VALL V3158 ON V3158.OBJ_ID = V3159.VAL AND V3158.PARAM_ID = 3158 AND V3158.IS_DEL = 0 AND V3158.LISTVAL_ID = 13462
  JOIN LINKS LP301 ON LP301.OBJ_ID = V3159.VAL AND LP301.PARENT_TYPE_ID = 301 AND LP301.DATE_DEL IS NULL
  WHERE V3159.OBJ_ID = :I$SUBJECT_ID AND V3159.PARAM_ID = 3159 AND V3159.IS_DEL = 0
  INTO :V$SUBJECT_MS;

  -- При наличии мастер-группы (ГУП) этап ОВЗ надо взять оттуда
  IF(I$GRADE_TYPE_ID = 179) THEN
  SELECT FIRST 1 V381.LISTVAL_ID
  FROM LINKS LP2
  JOIN LINKS LP54 ON LP54.OBJ_ID = LP2.EXT_OBJ_ID AND LP54.PARENT_TYPE_ID = 54 AND LP54.DATE_DEL IS NULL
  JOIN VALL V381 ON V381.OBJ_ID = LP54.PARENT_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
  WHERE LP2.OBJ_ID = :I$GRADE_ID AND LP2.PARENT_TYPE_ID = 2 AND LP2.DATE_DEL IS NULL
  INTO :V$STAGE_INDEX_OVZ;

  IF(I$REF_ID IS NOT NULL AND (I$WEEKS IS NULL OR I$WEEKS = 0)) THEN
  BEGIN
    SELECT MAX(L.WEEKS)
    FROM PLAN_SUBJECTS S
    JOIN PLAN_LOADS L ON L.SUBJECT_ID = S.OBJ_ID AND L.DATE_DEL IS NULL
    JOIN LINKS L54 ON L54.OBJ_ID = L.STAGE_ID AND L54.PARENT_ID = S.PLAN_ID AND L54.DATE_DEL IS NULL
    JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0 AND V381.LISTVAL_ID = COALESCE(:V$STAGE_INDEX_OVZ, :I$STAGE_INDEX)
    WHERE S.PLAN_ID = :I$REF_ID AND S.DATE_DEL IS NULL AND (S.SUBJECT_ID = :I$SUBJECT_ID OR S.SUBJECT_ID = :V$SUBJECT_MS)
    INTO :I$WEEKS;
  END

  IF(I$REF_ID IS NOT NULL AND (I$HOURS IS NULL OR I$HOURS = 0)) THEN
  BEGIN
    SELECT SUM(COALESCE(L.LOAD_HOURS_S1, 0) + COALESCE(L.LOAD_HOURS_S2, 0)) -- LOAD_HOURS пустой !
    FROM PLAN_SUBJECTS S
    JOIN PLAN_LOADS L ON L.SUBJECT_ID = S.OBJ_ID AND L.DATE_DEL IS NULL
    JOIN LINKS L54 ON L54.OBJ_ID = L.STAGE_ID AND L54.PARENT_ID = S.PLAN_ID AND L54.DATE_DEL IS NULL
    JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0 AND V381.LISTVAL_ID = COALESCE(:V$STAGE_INDEX_OVZ, :I$STAGE_INDEX)
    WHERE S.PLAN_ID = :I$REF_ID AND S.DATE_DEL IS NULL AND (S.SUBJECT_ID = :I$SUBJECT_ID OR S.SUBJECT_ID = :V$SUBJECT_MS)
    INTO :I$HOURS;
  END

  IF(I$STAGE_MASK IS NULL) THEN
  BEGIN
    SELECT BIN_SHL(1, CAST(LV.COST AS INTEGER))
    FROM LISTVALS LV
    WHERE LV.LISTVAL_ID = :I$STAGE_INDEX
    INTO :I$STAGE_MASK;
  END

  IF(I$GRADE_TYPE_ID = 0) THEN
  BEGIN
    -- Специальный случай - создание группы новой переменного состава для ГУП
    IF(I$GRADE_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Должна быть указана ссылка на базовую группу';
    I$GRADE_TYPE_ID = 179;
    GRADE_TYPE_ID = I$GRADE_TYPE_ID;

    SELECT OBJ_ID, LINK_ID FROM OBJECT_ADD(:V$SCHOOL_ID, 179) INTO :GRADE_ID, :V$LINK_ID;
    -- Запоминаем наименование
    SELECT 1 FROM VAL_ADD(2927, :GRADE_ID, :I$JOURNAL_NAME) INTO :T;
    -- Раз группа на основе ГУП, то все ученики точно оттуда - сразу фиксируем ссылку
    SELECT 1 FROM VAL_ADD(3370, :GRADE_ID, :I$GRADE_ID) INTO :T;
    -- Ссылка также фиксируется в EXT_OBJ_ID
    UPDATE LINKS SET EXT_OBJ_ID = :I$GRADE_ID WHERE LINK_ID = :V$LINK_ID;

    -- Добавляем всех учеников в текущем состоянии
    V$COPP = 3;
    FOR
      SELECT L10.OBJ_ID
      FROM LINKS L10
      WHERE L10.PARENT_ID = :I$GRADE_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      INTO :V$OBJ_ID
    DO
    BEGIN
      V$MOVE_DATE = NULL;
      SELECT FIRST 1 M.DATE_IN, M.ORDER_NUM_IN, M.ORDER_DATE_IN
      FROM PERSON_MOVEMENTS M
      WHERE M.DATE_DEL IS NULL AND M.DATE_OUT IS NULL AND M.PERSON_ID = :V$OBJ_ID AND M.GROUP_ID = :I$GRADE_ID
      ORDER BY M.OBJ_ID DESC
      INTO :V$MOVE_DATE, :S, :V$ORDER_DATE;

      IF(V$MOVE_DATE IS NOT NULL) THEN
      BEGIN
        SELECT OBJ_ID FROM VARGRP_MOVE_PUPIL(:V$OBJ_ID, :GRADE_ID, :S, :V$ORDER_DATE, :V$MOVE_DATE, 0, :V$USER_ID) INTO :V$OWNER_ID;
      END

      IF(V$COPP = 3 AND EXISTS(
        SELECT FIRST 1 1
        FROM LINKS LPG
        JOIN VALL V3063 ON V3063.OBJ_ID = LPG.PARENT_ID AND V3063.PARAM_ID = 3063 AND V3063.IS_DEL = 0 AND V3063.LISTVAL_ID = 2
        WHERE LPG.OBJ_ID = :V$OBJ_ID AND LPG.PARENT_TYPE_ID = 9 AND LPG.DATE_DEL IS NULL
      ))
      THEN V$COPP = 2;
    END

    SELECT 1 FROM VAL_ADD(3064, :GRADE_ID, :V$COPP) INTO :T;
  END
  ELSE IF(I$GRADE_ID IS NULL) THEN
  BEGIN
    -- Создаем новую группу переменного состава
    IF(I$GRADE_TYPE_ID <> 179) THEN EXCEPTION DATA_ERROR 'Автоматически создаются только группы персонального состава';
    SELECT OBJ_ID FROM OBJECT_ADD(:V$SCHOOL_ID, 179) INTO :GRADE_ID;
  END
  ELSE
  BEGIN
    -- Во всех прочих случаях оставляем группу, которая указана
    GRADE_ID = I$GRADE_ID;
    GRADE_TYPE_ID = I$GRADE_TYPE_ID;
  END

  -- Корректируем название группы по названию журнала
  IF(GRADE_TYPE_ID = 179) THEN
  BEGIN
    S = NULL;
    SELECT V FROM VAL_GET(:GRADE_ID, 2927) WHERE IS_EXISTS = 1 INTO :S;
    IF(COALESCE(S, '') <> COALESCE(I$JOURNAL_NAME, '')) THEN
    BEGIN
      SELECT BLOB_ID FROM VAL_ADD(2927, :GRADE_ID, :I$JOURNAL_NAME) INTO :S;
    END
  END

  IF(I$OBJ_ID IS NULL) THEN
  BEGIN
    IF(V$ACCESS <> 1 AND (I$TEACHER_ID <> V$TEACHER_ID OR I$TEACHER_ID IS NULL)) THEN EXCEPTION DATA_ERROR 'Вы можете создавать журнал только для себя';

    IF(I$VK_ENABLED IS NULL) THEN I$VK_ENABLED = 0;

    INSERT INTO CJ2_JOURNAL
    (GRADE_ID, SUBJECT_ID, TEACHER_ID, JOURNAL_TYPE, GRADE_TYPE_ID, STAGE_INDEX, JOURNAL_NAME, STAGE_MASK, REF_ID, YEAR_ID,
      WEEKS, HOURS, IS_ENABLED, RCM_MODE, DURATION, DAYMASK, PERIOD_ID, EXT_INFO, VK_ENABLED, ROOM_ID, ASST_ID)
    VALUES (:GRADE_ID, :I$SUBJECT_ID, :I$TEACHER_ID, :I$JOURNAL_TYPE, :I$GRADE_TYPE_ID, :I$STAGE_INDEX, :I$JOURNAL_NAME, :I$STAGE_MASK, :I$REF_ID, :I$YEAR_ID,
      :I$WEEKS, :I$HOURS, :I$IS_ENABLED, :I$RCM_MODE, :I$DURATION, :I$DAYMASK, :I$PERIOD_ID, :I$EXT_INFO, :I$VK_ENABLED, :I$ROOM_ID, :I$ASST_ID)
    RETURNING OBJ_ID
    INTO :CJ_ID;
  END
  ELSE
  BEGIN
    -- REF_ID и YEAR_ID не должны меняться
    IF(I$VK_ENABLED = 0 AND V$CHAT_ID IS NOT NULL) THEN EXCEPTION DATA_ERROR 'Чат к данному журналу уже создан, отменить нельзя';

    IF(COALESCE(I$ASST_ID, 0) <> COALESCE(V$ASST_ID, 0)) THEN
    BEGIN
      IF(EXISTS(
        SELECT FIRST 1 1
        FROM CJ2_JOURNAL_LESSONS L
        JOIN CJ2_CONTROL C ON C.DATE_DEL IS NULL AND C.LESSON_ID = L.OBJ_ID AND C.MARK_SYSTEM_ID <> :I$ASST_ID
        WHERE L.CJ_ID = :I$OBJ_ID AND L.DATE_DEL IS NULL
        UNION
        SELECT FIRST 1 1
        FROM CJ2_JOURNAL_FINALS F
        WHERE F.CJ_ID = :I$OBJ_ID AND F.DATE_DEL IS NULL AND F.MARK_SYSTEM_ID <> :I$ASST_ID
      ))
      THEN
        EXCEPTION DATA_ERROR 'Нельзя установить систему оценивания, если в систему внесены контроли или итоговые оценки по другой системе';
    END

    UPDATE CJ2_JOURNAL J
    SET J.TEACHER_ID = :I$TEACHER_ID, J.STAGE_INDEX = :I$STAGE_INDEX, J.JOURNAL_NAME = :I$JOURNAL_NAME, J.STAGE_MASK = :I$STAGE_MASK,
      WEEKS = :I$WEEKS, HOURS = :I$HOURS, IS_ENABLED = :I$IS_ENABLED, RCM_MODE = :I$RCM_MODE, DURATION = :I$DURATION, DAYMASK = :I$DAYMASK,
      PERIOD_ID = :I$PERIOD_ID, EXT_INFO = :I$EXT_INFO, J.VK_ENABLED = COALESCE(:I$VK_ENABLED, J.VK_ENABLED), J.ROOM_ID = :I$ROOM_ID,
      ASST_ID = :I$ASST_ID
    WHERE J.OBJ_ID = :I$OBJ_ID;
  END

  JOURNAL_NAME = I$JOURNAL_NAME;

  -- Обновляем права доступа
  EXECUTE PROCEDURE CJ2_JOURNAL_ACCESS_UPD(:CJ_ID, NULL);

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_JOURNAL_DELETE (
    I$CJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
AS
declare variable N integer;
declare variable V$GRADE_ID bigint;
declare variable V$GRADE_TYPE_ID bigint;
declare variable V$REAL_TYPE_ID bigint;
declare variable V$USER_ID bigint;
declare variable V$ACCESS smallint;
declare variable V$PERSON_ID bigint;
declare variable V$DATE date;
begin

  -- !!! Проверка прав доступа
  IF(I$USER_ID = 'Веб-администратор') THEN V$USER_ID = 1; ELSE V$USER_ID = CAST(I$USER_ID AS BIGINT);

  SELECT GRADE_ID, GRADE_TYPE_ID
  FROM CJ2_JOURNAL
  WHERE OBJ_ID = :I$CJ_ID AND DATE_DEL IS NULL
  INTO :V$GRADE_ID, :V$GRADE_TYPE_ID;

  IF(V$GRADE_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Регистрационная запись журнала не найдена';

  SELECT FIRST 1 TYPE_ID
  FROM OBJECTS
  WHERE OBJ_ID = :V$GRADE_ID
  INTO :V$REAL_TYPE_ID;

  IF(V$REAL_TYPE_ID <> V$GRADE_TYPE_ID) THEN EXCEPTION DATA_ERROR 'Системная ошибка, тип учебного коллектива не совпадает с указанным';

  SELECT ACCESS_LEVEL FROM CJ2_JOURNAL_ACCESS(:I$USER_ID, :I$CJ_ID) INTO :V$ACCESS;
  IF(V$ACCESS <> 1) THEN EXCEPTION DATA_ERROR 'Только руководящие сотрудники могут удалять журналы';

  -- Проверяем, что в журнале нет проведенных уроков и оценок
  SELECT COUNT(*)
  FROM CJ2_JOURNAL_LESSONS CJL
  WHERE CJL.CJ_ID = :I$CJ_ID AND CJL.DATE_DEL IS NULL AND CJL.IS_COMPLETED = 0
  INTO :N;

  IF(N > 0) THEN EXCEPTION DATA_ERROR 'Нельзя удалить журнал, в котором есть проведенные уроки (мероприятия)';

  SELECT COUNT(*)
  FROM (
    SELECT FIRST 1 1 CNT
    FROM CJ2_JOURNAL_LESSONS CJL
    JOIN CJ2_CONTROL CJC ON CJC.LESSON_ID = CJL.OBJ_ID AND CJC.DATE_DEL IS NULL
    JOIN CJ2_MARK CJM ON CJM.CONTROL_ID = CJC.CONTROL_ID AND CJM.DATE_DEL IS NULL AND CJM.MARK_TYPE_ID >= 100
    WHERE CJL.CJ_ID = :I$CJ_ID AND CJL.DATE_DEL IS NULL
    UNION
    SELECT FIRST 1 1
    FROM CJ2_JOURNAL_FINALS F
    JOIN CJ2_MARK M ON M.FINAL_ID = F.OBJ_ID AND M.DATE_DEL IS NULL
    WHERE F.CJ_ID = :I$CJ_ID AND F.DATE_DEL IS NULL
  )
  INTO :N;

  IF(N > 0) THEN EXCEPTION DATA_ERROR 'Нельзя удалить журнал, в котором есть выставленные оценки или события';

  SELECT COUNT(*)
  FROM CJ2_AUDIT A
  WHERE A.DATE_DEL IS NULL AND A.CJ_ID = :I$CJ_ID AND A.STATE_ID < 2
  INTO :N;

  IF(N > 0) THEN EXCEPTION DATA_ERROR 'Нельзя удалить журнал, по которому есть незакрытые записи аудита';

  -- Отмечаем выбытие всех учащихся, если тип группы 179
  IF(V$GRADE_TYPE_ID = 179) THEN
  BEGIN
    FOR
      SELECT M.PERSON_ID, M.DATE_IN
      FROM PERSON_MOVEMENTS M
      WHERE M.DATE_DEL IS NULL AND M.GROUP_ID = :V$GRADE_ID AND M.DATE_OUT IS NULL
      INTO :V$PERSON_ID, :V$DATE
    DO
    BEGIN
      IF(V$DATE > CURRENT_DATE) THEN EXCEPTION DATA_ERROR 'Нельзя выбыть ' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$PERSON_ID)) || ' раньше, чем он был зачислен';

      SELECT COUNT(*) FROM VARGRP_MOVE_PUPIL(:V$PERSON_ID, :V$GRADE_ID, NULL, NULL, CURRENT_DATE, 1, :I$USER_ID) INTO :N;
    END
  END

  -- Удаляем сам журнал
  UPDATE CJ2_JOURNAL
  SET DATE_DEL = CURRENT_TIMESTAMP
  WHERE OBJ_ID = :I$CJ_ID;

  -- Снимаем ссылки из расписания
  UPDATE SCHEDULE_ITEMS
  SET DATE_DEL = CURRENT_TIMESTAMP
  WHERE CJ_ID = :I$CJ_ID AND DATE_DEL IS NULL;

  -- Если была персональная группа, удаляем ее
  IF(V$GRADE_TYPE_ID = 179) THEN
  BEGIN

      UPDATE LINKS
      SET DATE_DEL = CURRENT_TIMESTAMP
      WHERE PARENT_TYPE_ID = 2 AND OBJ_ID = :V$GRADE_ID AND DATE_DEL IS NULL;

  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_JOURNAL_GET (
    IN_USER_ID VARCHAR(40),
    JOURNAL_ID BIGINT,
    GRADE_ID BIGINT,
    SUBJECT_ID BIGINT,
    ZONE_ID SMALLINT = 0)
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE ACCESS_LEVEL INTEGER;
DECLARE VARIABLE V$OU_LICENCE_TYPE CHAR(1);
DECLARE VARIABLE V$COPP BIGINT;
DECLARE VARIABLE V$IS_CLASSMATE SMALLINT;
DECLARE VARIABLE V$JOURNAL_ID BIGINT;
DECLARE VARIABLE V$TYPENAME VARCHAR(100);
DECLARE VARIABLE V$END_DATE DATE;
DECLARE VARIABLE S VARCHAR(1000);
DECLARE VARIABLE S1 VARCHAR(1000);
DECLARE VARIABLE S2 VARCHAR(1000);
DECLARE VARIABLE S3 VARCHAR(1000);
DECLARE VARIABLE SK VARCHAR(100);
DECLARE VARIABLE V$JOURNAL_TYPE BIGINT;
DECLARE VARIABLE V$GRADE_ID BIGINT;
DECLARE VARIABLE V$GRADE_TYPE_ID BIGINT;
DECLARE VARIABLE V$STAGE_INDEX BIGINT;
DECLARE VARIABLE V$SUBJECT_ID BIGINT;
DECLARE VARIABLE V$TEACHER_ID BIGINT;
DECLARE VARIABLE V$MEMBER_ID BIGINT;
DECLARE VARIABLE V$MEMBER_TYPE_ID BIGINT;
DECLARE VARIABLE V$PERIOD_LV BIGINT;
DECLARE VARIABLE V$D1 DATE;
DECLARE VARIABLE V$D2 DATE;
DECLARE VARIABLE V$CONTROL_TYPE_ID BIGINT;
DECLARE VARIABLE V$MARK_ID BIGINT;
DECLARE VARIABLE V$MARK_TYPE_ID BIGINT;
DECLARE VARIABLE V$COST NUMERIC(18,3);
DECLARE VARIABLE V$MASTER_ID BIGINT;
DECLARE VARIABLE V$YEAR DATE;
DECLARE VARIABLE V$MULT BIGINT;
DECLARE VARIABLE V$GEN BIGINT;
DECLARE VARIABLE V$Y INTEGER;
DECLARE VARIABLE V$PREV_YEAR_ID BIGINT;
DECLARE VARIABLE V$HAS_TOTAL SMALLINT;
DECLARE VARIABLE V$SUM1 DOUBLE PRECISION;
DECLARE VARIABLE V$SUM2 INTEGER;
DECLARE VARIABLE V$RCM_MODE SMALLINT;
DECLARE VARIABLE V$DUR SMALLINT;
DECLARE VARIABLE V$DAYMASK SMALLINT;
DECLARE VARIABLE V$T SMALLINT;
DECLARE VARIABLE V$PERIOD_ID BIGINT;
DECLARE VARIABLE V$REF_ID BIGINT;
DECLARE VARIABLE V$VK_ENABLED SMALLINT;
DECLARE VARIABLE V$CHAT_ID VARCHAR(400);
DECLARE VARIABLE V$LV BIGINT;
DECLARE VARIABLE V$YEAR_ID BIGINT;
DECLARE VARIABLE V$C2 FLOAT;
DECLARE VARIABLE V$C3 FLOAT;
DECLARE VARIABLE V$ASST_ID BIGINT;
begin

  -- Передается либо JOURNAL_ID, либо пара GRADE_ID+SUBJECT_ID

  SELECT J.OBJ_ID, J.JOURNAL_TYPE, J.GRADE_ID, J.GRADE_TYPE_ID, J.STAGE_INDEX, J.SUBJECT_ID, J.TEACHER_ID, J.JOURNAL_NAME, V3064.LISTVAL_ID,
    J.RCM_MODE, J.DURATION, J.DAYMASK, J.YEAR_ID, LV.TAG, J.PERIOD_ID, J.REF_ID, J.VK_ENABLED, J.CHAT_ID, J.ASST_ID
  FROM CJ2_JOURNAL J
  LEFT JOIN VALL V3064 ON V3064.OBJ_ID = J.GRADE_ID AND V3064.PARAM_ID = 3064 AND V3064.IS_DEL = 0
  LEFT JOIN LISTVALS LV ON LV.LISTVAL_ID = J.YEAR_ID
  WHERE J.DATE_DEL IS NULL AND (
    (J.OBJ_ID = :JOURNAL_ID AND :JOURNAL_ID IS NOT NULL) OR
    (J.GRADE_ID = :GRADE_ID AND J.SUBJECT_ID = :SUBJECT_ID AND :JOURNAL_ID IS NULL)
  )
  INTO :V$JOURNAL_ID, :V$JOURNAL_TYPE, :V$GRADE_ID, :V$GRADE_TYPE_ID, :V$STAGE_INDEX, :V$SUBJECT_ID, :V$TEACHER_ID, :S, :V$COPP,
    :V$RCM_MODE, :V$DUR, :V$DAYMASK, :V$YEAR_ID, :V$YEAR, :V$PERIOD_ID, :V$REF_ID, :V$VK_ENABLED, :V$CHAT_ID, :V$ASST_ID;

  IF(V$JOURNAL_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Журнал не найден';

  -- Проверяем права доступа к журналу
  SELECT ACCESS_LEVEL, IS_CLASSMATE
  FROM CJ2_JOURNAL_ACCESS(:IN_USER_ID, :V$JOURNAL_ID)
  INTO :ACCESS_LEVEL, :V$IS_CLASSMATE;

  IF(ACCESS_LEVEL = 0) THEN EXCEPTION DATA_ERROR 'Нет доступа к указанному журналу';

  SELECT MULTIPLIER, GEN
  FROM GEN
  INTO :V$MULT, :V$GEN;

  -- Титульная часть по журналу
  TAG_NAME = 'journal';
  VAL = NULL;
  SUSPEND;

  TAG_NAME = 'journal:id';
  VAL = V$JOURNAL_ID;
  SUSPEND;

  TAG_NAME = 'journal:type_id';
  VAL = V$JOURNAL_TYPE;
  SUSPEND;

  TAG_NAME = 'journal:name';
  VAL = S;
  SUSPEND;

  TAG_NAME = 'journal:grade_id';
  VAL = V$GRADE_ID;
  SUSPEND;

  TAG_NAME = 'journal:grade_name';
  VAL = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$GRADE_ID));
  SUSPEND;

  TAG_NAME = 'journal:grade_type';
  VAL = V$GRADE_TYPE_ID;
  SUSPEND;

  TAG_NAME = 'journal:stage';
  VAL = COALESCE(V$STAGE_INDEX, 0);
  SUSPEND;

  TAG_NAME = 'journal:subject_id';
  VAL = COALESCE(V$SUBJECT_ID, 0);
  SUSPEND;

  TAG_NAME = 'journal:subject_name';
  IF(V$SUBJECT_ID IS NULL) THEN VAL = ''; ELSE VAL = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$SUBJECT_ID));
  SUSPEND;

  TAG_NAME = 'journal:teacher_id';
  VAL = COALESCE(V$TEACHER_ID, 0);
  SUSPEND;

  TAG_NAME = 'journal:teacher_name';
  IF(V$TEACHER_ID IS NULL) THEN VAL = ''; ELSE VAL = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$TEACHER_ID));
  SUSPEND;

  TAG_NAME = 'journal:role_id';
  VAL = ACCESS_LEVEL;
  SUSPEND;

  TAG_NAME = 'journal:is_cm';
  VAL = V$IS_CLASSMATE;
  SUSPEND;

  TAG_NAME = 'journal:rcm_mode';
  VAL = V$RCM_MODE;
  SUSPEND;

  TAG_NAME = 'journal:duration';
  VAL = V$DUR;
  SUSPEND;

  TAG_NAME = 'journal:daymask';
  VAL = V$DAYMASK;
  SUSPEND;

  TAG_NAME = 'journal:vk_enabled';
  VAL = V$VK_ENABLED;
  SUSPEND;

  TAG_NAME = 'journal:chat_id';
  VAL = V$CHAT_ID;
  SUSPEND;

  TAG_NAME = 'journal:ou_type';
  V$OU_LICENCE_TYPE = (SELECT STATUS FROM OU_LICENCE_TYPE);
  VAL = V$OU_LICENCE_TYPE;
  SUSPEND;

  TAG_NAME = 'journal:copp';
  IF(V$COPP = 2) THEN VAL = '1'; ELSE VAL = '0';
  SUSPEND;

  -- Проверяем, относится ли журнал к индивидуальному плану
  TAG_NAME = 'journal:is_ind';
  VAL = 0;
  SELECT FIRST 1 1
  FROM VALL V3016
  WHERE V3016.OBJ_ID = :V$REF_ID AND V3016.PARAM_ID = 3016 AND V3016.LISTVAL_ID <> 5465
  INTO :VAL;
  SELECT FIRST 1 1
  FROM LINKS L10
  JOIN LINKS LP187 ON LP187.OBJ_ID = L10.OBJ_ID AND LP187.PARENT_TYPE_ID = 187 AND LP187.DATE_DEL IS NULL
  WHERE L10.PARENT_ID = :V$GRADE_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'journal:is_corr';
  VAL = 0;
  SELECT FIRST 1 1
  FROM LINKS L10
  JOIN VALL V207 ON V207.OBJ_ID = L10.OBJ_ID AND V207.PARAM_ID = 207 AND V207.IS_DEL = 0 AND V207.LISTVAL_ID <> 13289
  WHERE L10.PARENT_ID = :V$GRADE_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
  INTO :VAL;
  SUSPEND;

  -- Есть утвержденный ПТП ? или хотя бы какой есть
  TAG_NAME = 'journal:ptp_id';
  VAL = NULL;
  SELECT FIRST 1 P.PTP_ID
  FROM CJ2_JOURNAL_PTP P
  WHERE P.DATE_DEL IS NULL AND P.CJ_ID = :V$JOURNAL_ID AND P.APPROVAL_STATE < 3
  ORDER BY P.APPROVAL_STATE DESC
  INTO :VAL;
  SUSPEND;

  -- Есть ли другой ПТП в статусе к утверждению ?
  TAG_NAME = 'journal:ptp_pending';
  VAL = 0;
  SELECT FIRST 1 1
  FROM CJ2_JOURNAL_PTP P
  WHERE P.DATE_DEL IS NULL AND P.CJ_ID = :V$JOURNAL_ID AND P.APPROVAL_STATE = 1
  INTO :VAL;
  SUSPEND;

  -- Учебный год - если старая версия и не указан в самом журнале
  IF(V$YEAR IS NULL) THEN
  BEGIN
    SELECT FIRST 1 LV.TAG
    FROM LINKS L2
    JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :V$YEAR;
  END

  TAG_NAME = 'journal:date_start';
  VAL = (SELECT VAL FROM DATE2ISO(:V$YEAR));
  -- Для ДПО берем дату начала и окончания занятий в группе
  IF(V$GRADE_TYPE_ID = 46 AND V$OU_LICENCE_TYPE = 'P') THEN
  BEGIN
    V$D1 = NULL;
    SELECT FIRST 1 V.VAL
    FROM VALD V
    WHERE V.OBJ_ID = :V$GRADE_ID AND V.PARAM_ID = 2959 AND V.IS_DEL = 0
    INTO :V$D1;
    SELECT FIRST 1 V.VAL
    FROM VALD V
    WHERE V.OBJ_ID = :V$GRADE_ID AND V.PARAM_ID = 2960 AND V.IS_DEL = 0
    INTO :V$END_DATE;
    IF(V$D1 IS NOT NULL) THEN VAL = (SELECT VAL FROM DATE2ISO(:V$D1));
  END
  SUSPEND;

  TAG_NAME = 'journal:date_end';
  VAL = (SELECT VAL FROM DATE2ISO(:V$END_DATE));
  SUSPEND;

  -- !!! TODO заменить на выборку из КУГ
  TAG_NAME = 'holidays::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
    SELECT D.DATEVAL, D.DATETYPE
    FROM SPECIAL_DATES D
    WHERE D.DATEVAL >= :V$YEAR AND D.DATEVAL <= '31.08.' || (EXTRACT(YEAR FROM :V$YEAR) + 1) AND D.DATETYPE >= 0
    ORDER BY 1
    INTO :V$D1, :V$T
  DO
  BEGIN
    TAG_NAME = 'holidays:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'holidays:r:date';
    VAL = (SELECT VAL FROM DATE2ISO(:V$D1, 0));
    SUSPEND;
    TAG_NAME = 'holidays:r:type';
    VAL = V$T;
    SUSPEND;
  END

  -- Все виды контролей на уроке, справочник
  IF(V$OU_LICENCE_TYPE = 'O') THEN V$TYPENAME = 'GOU';
  ELSE IF(V$OU_LICENCE_TYPE = 'C') THEN V$TYPENAME = 'COLLEGE';
  ELSE IF(V$OU_LICENCE_TYPE = 'D') THEN V$TYPENAME = 'DOU';
  ELSE IF(V$OU_LICENCE_TYPE = 'U') THEN V$TYPENAME = 'UDOD';
  ELSE IF(V$OU_LICENCE_TYPE = 'P') THEN V$TYPENAME = 'DPO';
  ELSE IF(V$OU_LICENCE_TYPE = 'S') THEN
  BEGIN
    -- Градация исходя из типа журнала
    SELECT FIRST 1 LV.PARENT_ID
    FROM LISTVALS LV
    WHERE LV.LISTVAL_ID = :V$STAGE_INDEX
    INTO :V$LV;

    IF(V$LV = 2140) THEN V$TYPENAME = 'DOU';
    ELSE IF(V$LV = 2142) THEN V$TYPENAME = 'COLLEGE';
    ELSE IF(V$LV = 2143) THEN V$TYPENAME = 'UDOD';
    ELSE V$TYPENAME = 'GOU';
  END

  IF(V$STAGE_INDEX IN (37, 38, 39, 40, 12942, 12950)) THEN V$LV = 22;
  ELSE IF(V$STAGE_INDEX IN (41, 42, 43, 44, 45, 12951, 12960)) THEN V$LV = 26;
  ELSE IF(V$STAGE_INDEX IN (46, 47, 48, 12961)) THEN V$LV = 27;
  ELSE IF(V$STAGE_INDEX IN (49, 50, 51, 52, 53, 54)) THEN V$LV = 29;
  ELSE V$LV = NULL;

  TAG_NAME = 'control_types::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT T.CONTROL_TYPE_ID, T.CONTROL_NAME, T.CONTROL_SHORTNAME, T.CONTROL_DESC, T.MASTER_ID, T.TYPE_MASK, T.DEFAULT_COST, CC.COST, CL.COST
    FROM CJ2_CONTROL_TYPE T
    LEFT JOIN CJ2_CONTROL_COST CC ON CC.DATE_DEL IS NULL AND CC.YEAR_ID = :V$YEAR_ID AND CC.CONTROL_TYPE_ID = T.CONTROL_TYPE_ID AND CC.LEVEL_ID IS NULL
    LEFT JOIN CJ2_CONTROL_COST CL ON CL.DATE_DEL IS NULL AND CL.YEAR_ID = :V$YEAR_ID AND CL.CONTROL_TYPE_ID = T.CONTROL_TYPE_ID AND CL.LEVEL_ID = :V$LV
    WHERE T.IS_DEL = 0 AND (T."FILTER" IS NULL OR POSITION(:V$TYPENAME IN T."FILTER") > 0)
    INTO :V$CONTROL_TYPE_ID, :S, :S1, :S2, :V$MASTER_ID, :S3, :V$COST, :V$C2, :V$C3
  DO
  BEGIN
    TAG_NAME = 'control_types:control';
    VAL = NULL;
    SUSPEND;

    -- Для ЦОПП и не-общеобра меняем название
    IF(V$CONTROL_TYPE_ID = 1058 AND (V$JOURNAL_TYPE <> 0 OR V$COPP = 2)) THEN
    BEGIN
      S = 'Отм.';
      S1 = 'отм';
      S2 = 'Отметка';
    END

    TAG_NAME = 'control_types:control:id';
    VAL = V$CONTROL_TYPE_ID;
    SUSPEND;

    TAG_NAME = 'control_types:control:name';
    VAL = S;
    SUSPEND;

    TAG_NAME = 'control_types:control:shortname';
    VAL = S1;
    SUSPEND;

    TAG_NAME = 'control_types:control:desc';
    VAL = S2;
    SUSPEND;

    TAG_NAME = 'control_types:control:cost';
    IF(V$C3 > 0) THEN VAL = V$C3;
    ELSE IF(V$C2 > 0) THEN VAL = V$C2;
    ELSE VAL = V$COST;
    SUSPEND;

    TAG_NAME = 'control_types:control:master';
    VAL = V$MASTER_ID;
    SUSPEND;

    TAG_NAME = 'control_types:control:mask';
    VAL = S3;
    SUSPEND;

    TAG_NAME = 'control_types:control:enabled';
    VAL = 1;
    IF(V$C2 = -1 OR V$C3 = -1) THEN VAL = 0;
    SUSPEND;
  END

  -- Системы оценивания - выдаем линейным списком, второй уровень обязательно идет по id после родителя
  TAG_NAME = 'mark_types';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'mark_types::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
      SELECT T.MARK_TYPE_ID, T.MARK_NAME, T.MARK_SHORTNAME, T.MARK_COST, T.TYPE_MASK
      FROM CJ2_MARK_TYPE T
      WHERE T.PARENT_ID IS NULL
      ORDER BY T.MARK_TYPE_ID
      INTO :V$MARK_TYPE_ID, :S1, :S2, :V$COST, :S
  DO
  BEGIN
      TAG_NAME = 'mark_types:m';
      VAL = NULL;
      SUSPEND;

      TAG_NAME = 'mark_types:m:id';
      VAL = V$MARK_TYPE_ID;
      SUSPEND;

      TAG_NAME = 'mark_types:m:name';
      VAL = S1;
      SUSPEND;

      TAG_NAME = 'mark_types:m:mask';
      VAL = S;
      SUSPEND;

      TAG_NAME = 'mark_types:m:scale';
      VAL = V$COST;
      SUSPEND;

      -- Список оценок в системе оценивания
      TAG_NAME = 'mark_types:m:marks';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'mark_types:m:marks::json&colon;array';
      VAL = '1';
      SUSPEND;

      FOR
          SELECT T.MARK_TYPE_ID, T.MARK_NAME, T.MARK_SHORTNAME, T.MARK_COST, T.TYPE_MASK, T.MARK_SHORTCUT
          FROM CJ2_MARK_TYPE T
          WHERE T.PARENT_ID = :V$MARK_TYPE_ID
          ORDER BY T.MARK_TYPE_ID
          INTO :V$MARK_ID, :S1, :S2, :V$COST, :S, :SK
      DO
      BEGIN
          TAG_NAME = 'mark_types:m:marks:m';
          VAL = NULL;
          SUSPEND;

          TAG_NAME = 'mark_types:m:marks:m:id';
          VAL = V$MARK_ID;
          SUSPEND;

          TAG_NAME = 'mark_types:m:marks:m:name';
          VAL = S1;
          SUSPEND;

          TAG_NAME = 'mark_types:m:marks:m:shortname';
          VAL = S2;
          SUSPEND;

          TAG_NAME = 'mark_types:m:marks:m:cost';
          VAL = V$COST;
          SUSPEND;

          TAG_NAME = 'mark_types:m:marks:m:mask';
          VAL = S;
          SUSPEND;

          TAG_NAME = 'mark_types:m:marks:m:key';
          VAL = SK;
          SUSPEND;
      END
  END

  -- Виды занятий (ГПД и уроки)
  TAG_NAME = 'lesson_types';
  VAL = S1;
  SUSPEND;
  TAG_NAME = 'lesson_types::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
      SELECT L1.LISTVAL_ID, L1.VAL, 'E'
      FROM LISTVALS_LIST(276) L1
      WHERE L1.IS_DEL = 0
      UNION
      SELECT L2.LISTVAL_ID, L2.VAL, 'X'
      FROM LISTVALS_LIST(233) L2
      WHERE L2.IS_DEL = 0
      UNION
      SELECT L3.LISTVAL_ID, L3.VAL, 'G'
      FROM LISTVALS_LIST(389) L3
      WHERE L3.IS_DEL = 0
      ORDER BY 2
      INTO :V$CONTROL_TYPE_ID, :S, :S1
  DO
  BEGIN
      TAG_NAME = 'lesson_types:r';
      VAL = NULL;
      SUSPEND;

      TAG_NAME = 'lesson_types:r:id';
      VAL = V$CONTROL_TYPE_ID;
      SUSPEND;

      TAG_NAME = 'lesson_types:r:name';
      VAL = S;
      SUSPEND;

      TAG_NAME = 'lesson_types:r:mask';
      VAL = S1;
      SUSPEND;
  END

  -- Причины исправления отметок
  TAG_NAME = 'change_reasons::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
    SELECT L.LISTVAL_ID, L.VAL
    FROM LISTVALS_LIST(282) L
    WHERE L.IS_DEL = 0
    ORDER BY 2
    INTO :V$CONTROL_TYPE_ID, :S
  DO
  BEGIN
    TAG_NAME = 'change_reasons:r';
    VAL = NULL;
    SUSPEND;

    TAG_NAME = 'change_reasons:r:id';
    VAL = V$CONTROL_TYPE_ID;
    SUSPEND;

    TAG_NAME = 'change_reasons:r:name';
    VAL = S;
    SUSPEND;
  END

  -- Выбранная система оценивания
  -- Если не указана для данного конкретного журнала, смотрим в порядке приоритетов
  -- Сначала класс, потом пара предмет-параллель, потом предмет, потом параллель, и в конце глобальная настройка
  IF(V$JOURNAL_TYPE = 0) THEN
  BEGIN
    /*IF(V$ASST_ID IS NULL) THEN
    SELECT FIRST 1 A.ASST_ID
    FROM CJ2_ASSESSMENT A
    WHERE A.DATE_DEL IS NULL AND A.YEAR_ID = :V$YEAR_ID AND A.GRADE_ID = :...
    INTO :V$ASST_ID;*/

    IF(V$ASST_ID IS NULL) THEN
    SELECT FIRST 1 A.ASST_ID
    FROM CJ2_ASSESSMENT A
    WHERE A.DATE_DEL IS NULL AND A.YEAR_ID = :V$YEAR_ID AND A.SUBJECT_ID = :V$SUBJECT_ID AND A.STAGE_ID = :V$STAGE_INDEX
    INTO :V$ASST_ID;

    IF(V$ASST_ID IS NULL) THEN
    SELECT FIRST 1 A.ASST_ID
    FROM CJ2_ASSESSMENT A
    WHERE A.DATE_DEL IS NULL AND A.YEAR_ID = :V$YEAR_ID AND A.SUBJECT_ID = :V$SUBJECT_ID AND A.STAGE_ID IS NULL
    INTO :V$ASST_ID;

    IF(V$ASST_ID IS NULL) THEN
    SELECT FIRST 1 A.ASST_ID
    FROM CJ2_ASSESSMENT A
    WHERE A.DATE_DEL IS NULL AND A.YEAR_ID = :V$YEAR_ID AND A.SUBJECT_ID IS NULL AND A.STAGE_ID = :V$STAGE_INDEX
    INTO :V$ASST_ID;

    IF(V$ASST_ID IS NULL) THEN
    SELECT FIRST 1 A.ASST_ID
    FROM CJ2_ASSESSMENT A
    WHERE A.DATE_DEL IS NULL AND A.YEAR_ID = :V$YEAR_ID AND A.GRADE_ID IS NULL AND A.STAGE_ID IS NULL AND A.SUBJECT_ID IS NULL
    INTO :V$ASST_ID;
  END

  TAG_NAME = 'asst_id';
  VAL = V$ASST_ID;
  SUSPEND;

  V$HAS_TOTAL = 0;
  SELECT FIRST 1 1
  FROM CJ2_JOURNAL_FINALS F
  WHERE F.DATE_DEL IS NULL AND F.CJ_ID = :V$JOURNAL_ID AND F.FINAL_TYPE = 3013
  INTO :V$HAS_TOTAL;

  V$Y = EXTRACT(YEAR FROM CURRENT_DATE);
  IF(EXTRACT(MONTH FROM CURRENT_DATE) < 9) THEN V$Y = V$Y - 1;

  SELECT FIRST 1 LV.LISTVAL_ID
  FROM LISTVALS LV
  WHERE LV.LIST_ID = 29 AND LV.IS_DEL = 0 AND LV.COST = :V$Y - 1
  INTO :V$PREV_YEAR_ID;

  -- Список участников группы - массив, из всех кто когда либо был в группе
  -- Для zone 0 выдаем реальные ФИО, для зоны 1 - алиасы
  TAG_NAME = 'members::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
      SELECT DISTINCT MM.STUDENT_ID, MM.TYPE_ID, V1.VAL, V2.VAL
      FROM CJ2_MEMBER_MOVEMENTS(:V$GRADE_ID, :V$GRADE_TYPE_ID, NULL) MM
      JOIN VALS V1 ON V1.OBJ_ID = MM.STUDENT_ID AND V1.PARAM_ID IN (55, 59, 128, 827) AND V1.IS_DEL = 0
      JOIN VALS V2 ON V2.OBJ_ID = MM.STUDENT_ID AND V2.PARAM_ID IN (56, 60, 129, 828) AND V2.IS_DEL = 0
      WHERE MM.DATE_TO IS NULL OR MM.DATE_TO >= :V$YEAR
      ORDER BY 3, 4, 1
      INTO :V$MEMBER_ID, :V$MEMBER_TYPE_ID, :S, :S1
  DO
  BEGIN
      TAG_NAME = 'members:member';
      VAL = NULL;
      SUSPEND;

      TAG_NAME = 'members:member:id';
      VAL = V$MEMBER_ID;
      SUSPEND;

      TAG_NAME = 'members:member:type_id';
      VAL = V$MEMBER_TYPE_ID;
      SUSPEND;

      IF(ZONE_ID IN (0, 2)) THEN
      BEGIN
          TAG_NAME = 'members:member:name_last';
          VAL = S;
          SUSPEND;
          TAG_NAME = 'members:member:name_first';
          VAL = S1;
          SUSPEND;
          TAG_NAME = 'members:member:name_mid';
          VAL = (SELECT VAL FROM VALS WHERE OBJ_ID = :V$MEMBER_ID AND PARAM_ID IN (57, 61, 130, 829) AND IS_DEL = 0);
          SUSPEND;
      END

      TAG_NAME = 'members:member:alias';
      VAL = NULL;
      SELECT FIRST 1 V2991.VAL
      FROM VALS V2991
      WHERE V2991.OBJ_ID = :V$MEMBER_ID AND V2991.PARAM_ID = 2991 AND V2991.IS_DEL = 0
      INTO :VAL;
      IF(VAL IS NULL) THEN BEGIN
          SELECT FIRST 1 V2153.VAL
          FROM VALS V2153
          WHERE V2153.OBJ_ID = :V$MEMBER_ID AND V2153.PARAM_ID IN (2153, 2152) AND V2153.IS_DEL = 0
          INTO :VAL;
          IF(VAL IS NULL) THEN
          BEGIN
              VAL = V$GEN;
              IF(V$MEMBER_TYPE_ID = 14) THEN VAL = VAL || 't'; ELSE VAL = VAL || 'p';
              VAL = VAL || (V$MEMBER_ID - TRUNC(V$MEMBER_ID / V$MULT) * V$MULT);
          END
      END
      SUSPEND;

      -- Реестр движения
      TAG_NAME = 'members:member:movements';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'members:member:movements::json&colon;array';
      VAL = '1';
      SUSPEND;
      FOR
          SELECT MM.DATE_FROM, MM.DATE_TO
          FROM CJ2_MEMBER_MOVEMENTS(:V$GRADE_ID, :V$GRADE_TYPE_ID, :V$MEMBER_ID) MM
          INTO :V$D1, :V$D2
      DO
      BEGIN
          TAG_NAME = 'members:member:movements:mv';
          VAL = NULL;
          SUSPEND;
          TAG_NAME = 'members:member:movements:mv:date_in';
          VAL = (SELECT VAL FROM DATE2ISO(:V$D1, 0));
          SUSPEND;
          TAG_NAME = 'members:member:movements:mv:date_out';
          VAL = (SELECT VAL FROM DATE2ISO(:V$D2, 0));
          SUSPEND;
      END

      TAG_NAME = 'members:member:dm';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'members:member:dm::json&colon;array';
      VAL = '1';
      SUSPEND;
      FOR
          SELECT M.DATE_IN, M.DATE_OUT
          FROM PERSON_MOVEMENTS M
          JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 338
          WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :V$MEMBER_ID AND M.DATE_IN >= DATEADD(-1 YEAR TO CURRENT_DATE)
          INTO :V$D1, :V$D2
      DO
      BEGIN
          TAG_NAME = 'members:member:dm:mv';
          VAL = NULL;
          SUSPEND;
          TAG_NAME = 'members:member:dm:mv:date_in';
          VAL = (SELECT VAL FROM DATE2ISO(:V$D1, 0));
          SUSPEND;
          TAG_NAME = 'members:member:dm:mv:date_out';
          VAL = (SELECT VAL FROM DATE2ISO(:V$D2, 0));
          SUSPEND;
      END

      -- Отдаем прошлогодные итоговые отметки только для 11 и 12 классов
      IF(V$HAS_TOTAL = 1 AND V$STAGE_INDEX IN (47, 48)) THEN
      BEGIN
          V$SUM1 = NULL;
          V$SUM2 = NULL;

          SELECT SUM(MV.COST) / 10, COUNT(*)
          FROM VALM M
          JOIN LISTVALS MV ON MV.LISTVAL_ID = M.MARKVAL_ID
          WHERE M.PUPIL_ID = :V$MEMBER_ID AND M.SUBJECT_ID = :V$SUBJECT_ID AND M.IS_DEL = 0
              AND M.MARKTYPE_ID IN (3009, 3010, 3011) AND M.YEAR_ID = :V$PREV_YEAR_ID AND M.MARKVAL_ID IN (3014, 3015, 3016, 3017, 3018)
          INTO :V$SUM1, :V$SUM2;

          TAG_NAME = 'members:member:oysum1';
          VAL = V$SUM1;
          SUSPEND;
          TAG_NAME = 'members:member:oysum2';
          VAL = V$SUM2;
          SUSPEND;
      END

  END

  -- Список учебных периодов группы + текущий учебный год
  TAG_NAME = 'periods::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
    SELECT V1170.LISTVAL_ID, R.VAL, V1169.VAL, V1174.VAL
    FROM LINKS L151
    JOIN LINKS L154 ON L154.PARENT_ID = L151.OBJ_ID AND L154.OBJ_TYPE_ID = 154 AND L154.DATE_DEL IS NULL
    JOIN VALL V1170 ON V1170.OBJ_ID = L154.OBJ_ID AND V1170.PARAM_ID = 1170 AND V1170.IS_DEL = 0
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V1170.LISTVAL_ID
    JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
    JOIN VALD V1169 ON V1169.OBJ_ID = L154.OBJ_ID AND V1169.PARAM_ID = 1169 AND V1169.IS_DEL = 0
    JOIN VALD V1174 ON V1174.OBJ_ID = L154.OBJ_ID AND V1174.PARAM_ID = 1174 AND V1174.IS_DEL = 0
    WHERE L151.PARENT_TYPE_ID IN (150, 481) AND L151.OBJ_ID = :V$PERIOD_ID AND L151.DATE_DEL IS NULL
    ORDER BY 3
    INTO :V$PERIOD_LV, :S, :V$D1, :V$D2
  DO
  BEGIN
    TAG_NAME = 'periods:period';
    VAL = NULL;
    SUSPEND;

    TAG_NAME = 'periods:period:type_id';
    VAL = V$PERIOD_LV;
    SUSPEND;

    TAG_NAME = 'periods:period:date_from';
    VAL = (SELECT VAL FROM DATE2ISO(:V$D1, 0));
    SUSPEND;

    TAG_NAME = 'periods:period:date_to';
    VAL = (SELECT VAL FROM DATE2ISO(:V$D2, 0));
    SUSPEND;
  END

  -- Для журналов общего вида выдаем периодом текущий ученый год
  IF(V$JOURNAL_TYPE IN (10, 11)) THEN
  BEGIN
    TAG_NAME = 'periods:period';
    VAL = NULL;
    SUSPEND;

    TAG_NAME = 'periods:period:type_id';
    VAL = '0';
    SUSPEND;

    TAG_NAME = 'periods:period:date_from';
    VAL = (SELECT VAL FROM DATE2ISO(:V$YEAR, 0));
    SUSPEND;

    TAG_NAME = 'periods:period:date_to';
    VAL = (SELECT VAL FROM DATE2ISO('31.08.' || (EXTRACT(YEAR FROM :V$YEAR) + 1), 0));
    SUSPEND;
  END

  FOR
    SELECT TAG_NAME, VAL
    FROM CJ2_SERIALIZE(:V$JOURNAL_ID, NULL)
    INTO :TAG_NAME, :VAL
  DO
  BEGIN
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_JOURNAL_ITEM_GET (
    I$OBJ_ID BIGINT,
    I$TYPE_ID INTEGER,
    I$YEAR_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$USER_ID BIGINT;
DECLARE VARIABLE V$TYPE SMALLINT;
DECLARE VARIABLE V$ID BIGINT;
DECLARE VARIABLE V$SUBJECT_ID BIGINT;
DECLARE VARIABLE V$GRADE_ID BIGINT;
DECLARE VARIABLE V$GRADE_TYPE_ID BIGINT;
DECLARE VARIABLE V$TEACHER_ID BIGINT;
DECLARE VARIABLE V$CAPTION VARCHAR(1000);
DECLARE VARIABLE V$CLASS_CAPTION VARCHAR(1000);
DECLARE VARIABLE V$EXT_INFO VARCHAR(1000);
DECLARE VARIABLE V$MEMBERS_NUM INTEGER;
DECLARE VARIABLE V$STAGE_INDEX BIGINT;
DECLARE VARIABLE V$ACCESS_LEVEL INTEGER;
DECLARE VARIABLE V$MASK INTEGER;
DECLARE VARIABLE V$COST INTEGER;
DECLARE VARIABLE V$GROUP_ID BIGINT;
DECLARE VARIABLE V$STAGE_ID BIGINT;
DECLARE VARIABLE V$STAGE_MASK BIGINT;
DECLARE VARIABLE V$PTP_ID BIGINT;
DECLARE VARIABLE V$TYPE_ID BIGINT;
DECLARE VARIABLE V$OU_TYPE CHAR(1);
DECLARE VARIABLE V$YEAR_ID BIGINT;
DECLARE VARIABLE V$WEEKS INTEGER;
DECLARE VARIABLE V$HOURS FLOAT;
DECLARE VARIABLE V$IS_ENABLED SMALLINT;
DECLARE VARIABLE V$RCM_MODE SMALLINT;
DECLARE VARIABLE V$DUR SMALLINT;
DECLARE VARIABLE V$DAYMASK SMALLINT;
DECLARE VARIABLE V$YEAR INTEGER;
DECLARE VARIABLE V$T BIGINT;
DECLARE VARIABLE V$GRADE_MASTER_ID BIGINT;
DECLARE VARIABLE V$PERIOD_ID BIGINT;
DECLARE VARIABLE V$DATE DATE;
DECLARE VARIABLE V$VK_ENABLED SMALLINT;
DECLARE VARIABLE V$CHAT_ID VARCHAR(400);
DECLARE VARIABLE V$OU_ID BIGINT;
DECLARE VARIABLE V$ROOM_ID BIGINT;
DECLARE VARIABLE V$BUILDING_ID BIGINT;
DECLARE VARIABLE S VARCHAR(400);
DECLARE VARIABLE V$HAS_DO SMALLINT;
DECLARE VARIABLE V$HAS_OO SMALLINT;
DECLARE VARIABLE V$HAS_SPO SMALLINT;
DECLARE VARIABLE V$HAS_PO SMALLINT;
DECLARE VARIABLE V$ASST_ID BIGINT;
begin

  IF(I$USER_ID = 'Веб-администратор') THEN V$USER_ID = 1; ELSE V$USER_ID = CAST(I$USER_ID AS BIGINT);

  V$OU_TYPE = (SELECT STATUS FROM OU_LICENCE_TYPE);

  SELECT FIRST 1 L2.OBJ_ID, LV.COST
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$OU_ID, :V$YEAR;

  IF(V$YEAR IS NULL) THEN V$YEAR = EXTRACT(YEAR FROM CURRENT_DATE);

  V$HAS_DO = 0;
  V$HAS_OO = 0;
  V$HAS_SPO = 0;
  V$HAS_PO = 0;
  SELECT FIRST 1 1
  FROM LINKS L472
  JOIN VALL V3327 ON V3327.OBJ_ID = L472.OBJ_ID AND V3327.PARAM_ID = 3327 AND V3327.IS_DEL = 0 AND V3327.LISTVAL_ID IN (21, 3263, 3264)
  WHERE L472.PARENT_ID = :V$OU_ID AND L472.OBJ_TYPE_ID = 472 AND L472.DATE_DEL IS NULL
  INTO :V$HAS_DO;

  SELECT FIRST 1 1
  FROM LINKS L472
  JOIN VALL V3327 ON V3327.OBJ_ID = L472.OBJ_ID AND V3327.PARAM_ID = 3327 AND V3327.IS_DEL = 0 AND V3327.LISTVAL_ID IN (22, 26, 27)
  WHERE L472.PARENT_ID = :V$OU_ID AND L472.OBJ_TYPE_ID = 472 AND L472.DATE_DEL IS NULL
  INTO :V$HAS_OO;

  SELECT FIRST 1 1
  FROM LINKS L472
  JOIN VALL V3327 ON V3327.OBJ_ID = L472.OBJ_ID AND V3327.PARAM_ID = 3327 AND V3327.IS_DEL = 0 AND V3327.LISTVAL_ID IN (28, 29, 13129)
  WHERE L472.PARENT_ID = :V$OU_ID AND L472.OBJ_TYPE_ID = 472 AND L472.DATE_DEL IS NULL
  INTO :V$HAS_SPO;

  SELECT FIRST 1 1
  FROM LINKS L472
  JOIN VALL V3327 ON V3327.OBJ_ID = L472.OBJ_ID AND V3327.PARAM_ID = 3327 AND V3327.IS_DEL = 0 AND V3327.LISTVAL_ID IN (13129, 13131)
  WHERE L472.PARENT_ID = :V$OU_ID AND L472.OBJ_TYPE_ID = 472 AND L472.DATE_DEL IS NULL
  INTO :V$HAS_PO;

  -- Данные самого журнала
  SELECT CJ_ID, JOURNAL_TYPE, SUBJECT_ID, GRADE_ID, GRADE_TYPE_ID, TEACHER_ID, CAPTION, MEMBERS_NUM, STAGE_INDEX,
    STAGE_MASK, ACCESS_LEVEL, YEAR_ID, WEEKS, HOURS, IS_ENABLED, RCM_MODE, DURATION, DAYMASK,
    MASTER_ID, PERIOD_ID, VK_ENABLED, CHAT_ID, ROOM_ID, ASST_ID
  FROM CJ2_JOURNAL_LIST(:I$TYPE_ID, :V$USER_ID, :I$OBJ_ID)
  WHERE :I$OBJ_ID IS NOT NULL
  INTO :V$ID, :V$TYPE, :V$SUBJECT_ID, :V$GRADE_ID, :V$GRADE_TYPE_ID, :V$TEACHER_ID, :V$CAPTION, :V$MEMBERS_NUM, :V$STAGE_INDEX,
    :V$STAGE_MASK, :V$ACCESS_LEVEL, :V$YEAR_ID, :V$WEEKS, :V$HOURS, :V$IS_ENABLED, :V$RCM_MODE, :V$DUR, :V$DAYMASK,
    :V$GRADE_MASTER_ID, :V$PERIOD_ID, :V$VK_ENABLED, :V$CHAT_ID, :V$ROOM_ID, :V$ASST_ID;

  IF(I$OBJ_ID IS NOT NULL AND V$ID IS NULL) THEN EXCEPTION DATA_ERROR 'Журнал не найден или был удален';

  -- Для нового журнала учебный год берем из переданного параметра
  IF(V$YEAR_ID IS NULL) THEN V$YEAR_ID = I$YEAR_ID;

  SELECT J.EXT_INFO
  FROM CJ2_JOURNAL J
  WHERE J.OBJ_ID = :I$OBJ_ID AND J.DATE_DEL IS NULL
  INTO :V$EXT_INFO;

  TAG_NAME = 'id';
  VAL = I$OBJ_ID;
  SUSPEND;

  TAG_NAME = 'caption';
  VAL = V$CAPTION;
  SUSPEND;

  TAG_NAME = 'ext_info';
  VAL = V$EXT_INFO;
  SUSPEND;

  TAG_NAME = 'type_id';
  VAL = COALESCE(V$TYPE, I$TYPE_ID);
  SUSPEND;

  TAG_NAME = 'duration';
  VAL = IIF(I$OBJ_ID IS NULL, 45, V$DUR);
  SUSPEND;

  TAG_NAME = 'vk_enabled';
  VAL = V$VK_ENABLED;
  SUSPEND;

  TAG_NAME = 'chat_id';
  VAL = V$CHAT_ID;
  SUSPEND;

  -- ПТП
  SELECT FIRST 1 J.PTP_ID, P.OBJ_NAME, J.APPROVAL_STATE
  FROM CJ2_JOURNAL_PTP J
  JOIN PTP P ON P.OBJ_ID = J.PTP_ID AND P.DATE_DEL IS NULL
  WHERE J.DATE_DEL IS NULL AND J.CJ_ID = :I$OBJ_ID AND J.APPROVAL_STATE < 3
  ORDER BY J.APPROVAL_STATE DESC
  INTO :V$PTP_ID, :V$CLASS_CAPTION, :V$MASK;

  TAG_NAME = 'ptp_id';
  VAL = V$PTP_ID;
  SUSPEND;

  TAG_NAME = 'ptp_name';
  VAL = V$CLASS_CAPTION;
  SUSPEND;

  TAG_NAME = 'ptp_state';
  VAL = V$MASK;
  SUSPEND;

  -- Селектор предмета, пока только ВД
  -- В ОУ - предметы, в колледжах - дисциплины
  TAG_NAME = 'subject_id';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'subject_id:selection';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'subject_id:selection::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L51.OBJ_ID, C.CAPTION
    FROM LINKS L51
    LEFT JOIN OBJECT_CAPTION_GET(L51.OBJ_ID) C ON 1 = 1
    WHERE L51.DATE_DEL IS NULL  AND
      ((L51.OBJ_TYPE_ID = 51 AND :V$OU_TYPE IN ('O', 'S') AND :V$HAS_OO = 1) OR (L51.OBJ_TYPE_ID = 197 AND :V$OU_TYPE IN ('C', 'S') AND :V$HAS_SPO = 1)) AND (
        (:I$TYPE_ID = 0 AND (L51.PARENT_ID = 32771 OR L51.PARENT_ID = 12313)) OR
        (:I$TYPE_ID = 1 AND L51.PARENT_ID = 32772)
    )
    ORDER BY 2
    INTO :V$ID, :V$CAPTION
  DO
  BEGIN
    TAG_NAME = 'subject_id:selection:option';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'subject_id:selection:option:id';
    VAL = V$ID;
    SUSPEND;
    TAG_NAME = 'subject_id:selection:option:value';
    VAL = V$CAPTION;
    SUSPEND;
  END
  TAG_NAME = 'subject_id:values:value';
  VAL = V$SUBJECT_ID;
  SUSPEND;

  -- Селектор группы - выдаем в зависимости от типа + добавляем сюда саму выбранную
  -- Для школ это список ГПД и ДО, для ДОУ и УДОД (считаются как группы ГПД) это учебные коллективы
  -- Для ДПО берем со скрытым типом "группа"
  TAG_NAME = 'grade_id:selection::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT :V$GRADE_ID, C.CAPTION
    FROM RDB$DATABASE
    LEFT JOIN OBJECT_CAPTION_GET(:V$GRADE_ID) C ON 1 = 1
    WHERE :V$GRADE_ID IS NOT NULL
    -- Кружки и ГПД старая схема
    UNION
    SELECT L46.OBJ_ID, C.CAPTION
    FROM LINKS L86
    JOIN LINKS L46 ON L46.PARENT_ID = L86.OBJ_ID AND L46.OBJ_TYPE_ID = 46 AND L46.DATE_DEL IS NULL
    JOIN VALL V369 ON V369.OBJ_ID = L46.OBJ_ID AND V369.PARAM_ID = 369 AND V369.IS_DEL = 0
      AND (V369.LISTVAL_ID = IIF(:I$TYPE_ID = 2, 1246, IIF(:I$TYPE_ID = 3, 3318, NULL)) OR (:V$OU_TYPE = 'P' AND V369.LISTVAL_ID = 1719))
    LEFT JOIN OBJECT_CAPTION_GET(L46.OBJ_ID) C ON 1 = 1
    WHERE L86.PARENT_TYPE_ID = 2 AND L86.OBJ_TYPE_ID = 86 AND L86.DATE_DEL IS NULL
    -- ГПД новая схема мультипараграф
    UNION
    SELECT L46.OBJ_ID, C.CAPTION
    FROM LINKS L500
    JOIN LINKS L46 ON L46.PARENT_ID = L500.OBJ_ID AND L46.OBJ_TYPE_ID = 46 AND L46.DATE_DEL IS NULL
    LEFT JOIN OBJECT_CAPTION_GET(L46.OBJ_ID) C ON 1 = 1
    WHERE L500.PARENT_TYPE_ID = 2 AND L500.OBJ_TYPE_ID = 500 AND L500.DATE_DEL IS NULL AND :I$TYPE_ID = 2 AND :V$OU_TYPE = 'S'
    -- Кружки новая схема мультипараграф - в подразделении ???
    UNION
    SELECT L46.OBJ_ID, C.CAPTION
    FROM LINKS L211
    JOIN VALL V2102 ON V2102.OBJ_ID = L211.OBJ_ID AND V2102.PARAM_ID = 2102 AND V2102.IS_DEL = 0 AND V2102.LISTVAL_ID = 14246
    JOIN LINKS L46 ON L46.PARENT_ID = L211.OBJ_ID AND L46.OBJ_TYPE_ID = 46 AND L46.DATE_DEL IS NULL
    LEFT JOIN OBJECT_CAPTION_GET(L46.OBJ_ID) C ON 1 = 1
    WHERE L211.PARENT_TYPE_ID = 2 AND L211.OBJ_TYPE_ID = 211 AND L211.DATE_DEL IS NULL AND :I$TYPE_ID = 3 AND :V$OU_TYPE = 'S'
    -- Кружки новая схема мультипараграф - в разделе дополнительного образования
    UNION
    SELECT L46.OBJ_ID, C.CAPTION
    FROM LINKS L7
    JOIN VALL V43 ON V43.OBJ_ID = L7.OBJ_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0 AND V43.LISTVAL_ID = 13128
    JOIN LINKS L46 ON L46.PARENT_ID = L7.OBJ_ID AND L46.OBJ_TYPE_ID = 46 AND L46.DATE_DEL IS NULL
    LEFT JOIN OBJECT_CAPTION_GET(L46.OBJ_ID) C ON 1 = 1
    WHERE L7.PARENT_TYPE_ID = 2 AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL AND :I$TYPE_ID = 3 AND :V$OU_TYPE = 'S'
    -- ДОУ старая схема
    UNION
    SELECT L9.OBJ_ID, C.CAPTION
    FROM LINKS L7
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V49.LISTVAL_ID
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
    LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C ON 1 = 1
    WHERE L7.PARENT_TYPE_ID = 2 AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL AND :I$TYPE_ID IN (4) AND :V$OU_TYPE = 'D'
    -- ДОУ новая схема мультипараграф
    UNION
    SELECT L9.OBJ_ID, C.CAPTION
    FROM LINKS L7
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V49.LISTVAL_ID AND LV.PARENT_ID = 2140
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
    LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C ON 1 = 1
    WHERE L7.PARENT_TYPE_ID = 2 AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL AND :I$TYPE_ID IN (4) AND :V$OU_TYPE = 'S'
    -- УДОД
    UNION
    SELECT L243.OBJ_ID, C.CAPTION || ' - ' || C1.CAPTION
    FROM LINKS L242
    JOIN LINKS L243 ON L243.PARENT_ID = L242.OBJ_ID AND L243.OBJ_TYPE_ID = 243 AND L243.DATE_DEL IS NULL
    JOIN VALL V2114 ON V2114.OBJ_ID = L243.OBJ_ID AND V2114.PARAM_ID = 2114 AND V2114.IS_DEL = 0
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V2114.LISTVAL_ID
    LEFT JOIN OBJECT_CAPTION_GET(L242.OBJ_ID) C ON 1 = 1
    LEFT JOIN OBJECT_CAPTION_GET(L243.OBJ_ID) C1 ON 1 = 1
    WHERE L242.PARENT_TYPE_ID = 2 AND L242.OBJ_TYPE_ID = 242 AND L242.DATE_DEL IS NULL AND :I$TYPE_ID IN (3) AND :V$OU_TYPE = 'U'
    UNION
    SELECT L243.OBJ_ID, C.CAPTION || ' - ' || C1.CAPTION
    FROM LINKS L211
    JOIN LINKS L242 ON L242.PARENT_ID = L211.OBJ_ID AND L242.OBJ_TYPE_ID = 242 AND L242.DATE_DEL IS NULL
    JOIN LINKS L243 ON L243.PARENT_ID = L242.OBJ_ID AND L243.OBJ_TYPE_ID = 243 AND L243.DATE_DEL IS NULL
    JOIN VALL V2114 ON V2114.OBJ_ID = L243.OBJ_ID AND V2114.PARAM_ID = 2114 AND V2114.IS_DEL = 0
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V2114.LISTVAL_ID
    LEFT JOIN OBJECT_CAPTION_GET(L242.OBJ_ID) C ON 1 = 1
    LEFT JOIN OBJECT_CAPTION_GET(L243.OBJ_ID) C1 ON 1 = 1
    WHERE L211.PARENT_TYPE_ID = 2 AND L211.OBJ_TYPE_ID = 211 AND L211.DATE_DEL IS NULL AND :I$TYPE_ID IN (3) AND :V$OU_TYPE = 'U'
    ORDER BY 2
    INTO :V$ID, :V$CAPTION
  DO
  BEGIN
    TAG_NAME = 'grade_id:selection:option';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'grade_id:selection:option:id';
    VAL = V$ID;
    SUSPEND;
    TAG_NAME = 'grade_id:selection:option:value';
    VAL = V$CAPTION;
    SUSPEND;

    -- ГПД и ДО
    IF(I$TYPE_ID IN (2, 3)) THEN
    BEGIN
        TAG_NAME = 'grade_id:selection:option:owners';
        VAL = '';
        FOR
          SELECT DISTINCT C.CAPTION
          FROM LINKS L186
          JOIN VALR V1609 ON V1609.OBJ_ID = L186.OBJ_ID AND V1609.PARAM_ID = 1609 AND V1609.IS_DEL = 0
          LEFT JOIN OBJECT_CAPTION_GET(V1609.VAL) C ON 1 = 1
          WHERE L186.PARENT_ID = :V$ID AND L186.OBJ_TYPE_ID = 186 AND L186.DATE_DEL IS NULL
          ORDER BY 1
          INTO :V$CAPTION
        DO
        BEGIN
          IF(VAL <> '') THEN VAL = VAL || ', ';
          VAL = VAL || V$CAPTION;
        END
        SUSPEND;
    END
  END
  TAG_NAME = 'grade_id:values:value';
  VAL = V$GRADE_ID;
  SUSPEND;

  TAG_NAME = 'grade_type_id';
  VAL = V$GRADE_TYPE_ID;
  SUSPEND;

  SELECT FIRST 1 LP2.EXT_OBJ_ID
  FROM LINKS LP2
  WHERE LP2.OBJ_ID = :V$GRADE_ID AND LP2.PARENT_TYPE_ID = 2 AND LP2.DATE_DEL IS NULL
  INTO :V$GRADE_MASTER_ID;

  TAG_NAME = 'grade_master_id';
  VAL = V$GRADE_MASTER_ID;
  SUSPEND;
  TAG_NAME = 'grade_master_name';
  IF(V$GRADE_MASTER_ID IS NULL) THEN VAL = NULL;
  ELSE VAL = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$GRADE_MASTER_ID));
  SUSPEND;

  -- Помещения
  TAG_NAME = 'room_id:values:value';
  VAL = V$ROOM_ID;
  SUSPEND;
  TAG_NAME = 'room_id:selection::json&colon;array';
  VAL = 1;
  SUSPEND;
    TAG_NAME = 'room_id:selection:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'room_id:selection:r:id';
    VAL = '*';
    SUSPEND;
    TAG_NAME = 'room_id:selection:r:value';
    VAL = 'Не указано';
    SUSPEND;
    TAG_NAME = 'room_id:selection:r:subset_id';
    VAL = '';
    SUSPEND;
  FOR
    SELECT L16.OBJ_ID, C.CAPTION
    FROM LINKS L73
    JOIN LINKS L16 ON L16.PARENT_ID = L73.OBJ_ID AND L16.OBJ_TYPE_ID = 16 AND L16.DATE_DEL IS NULL
    LEFT JOIN OBJECT_CAPTION_GET(L16.OBJ_ID) C ON 1 = 1
    WHERE L73.PARENT_ID = :V$OU_ID AND L73.OBJ_TYPE_ID = 73 AND L73.DATE_DEL IS NULL
    ORDER BY C.SORT_ORDER
    INTO :V$BUILDING_ID, :S
  DO
  BEGIN
    TAG_NAME = 'room_id:selection:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'room_id:selection:r:id';
    VAL = '*';
    SUSPEND;
    TAG_NAME = 'room_id:selection:r:value';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'room_id:selection:r:disabled';
    VAL = 'section';
    SUSPEND;

    FOR
      SELECT L61.OBJ_ID, C.CAPTION, V1344.VAL
      FROM LINKS L61
      JOIN VALL V525 ON V525.OBJ_ID = L61.OBJ_ID AND V525.PARAM_ID = 525 AND V525.IS_DEL = 0 AND V525.LISTVAL_ID IN (23, 12764)
      LEFT JOIN VALR V1344 ON V1344.OBJ_ID = L61.OBJ_ID AND V1344.PARAM_ID = 1344 AND V1344.IS_DEL = 0
      -- Номер и название помещения
      LEFT JOIN OBJECT_CAPTION_GET(L61.OBJ_ID) C ON 1 = 1
      WHERE L61.PARENT_ID = :V$BUILDING_ID AND L61.OBJ_TYPE_ID = 61 AND L61.DATE_DEL IS NULL
      ORDER BY 2
      INTO :V$ROOM_ID, :S, :V$T
    DO
    BEGIN
      TAG_NAME = 'room_id:selection:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'room_id:selection:r:id';
      VAL = V$ROOM_ID;
      SUSPEND;
      TAG_NAME = 'room_id:selection:r:value';
      VAL = S;
      SUSPEND;
      TAG_NAME = 'room_id:selection:r:subset_id';
      VAL = V$T;
      SUSPEND;
    END
  END
    -- Добавляем виртуальный id для помещений на стороне, id помещения будет равно id ОУ чтобы сохранялась связность
    TAG_NAME = 'room_id:selection:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'room_id:selection:r:id';
    VAL = '*';
    SUSPEND;
    TAG_NAME = 'room_id:selection:r:value';
    VAL = 'Вне ОООД';
    SUSPEND;
    TAG_NAME = 'room_id:selection:r:disabled';
    VAL = 'section';
    SUSPEND;
    TAG_NAME = 'room_id:selection:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'room_id:selection:r:id';
    VAL = V$OU_ID;
    SUSPEND;
    TAG_NAME = 'room_id:selection:r:value';
    VAL = 'Вне ОООД';
    SUSPEND;
    TAG_NAME = 'room_id:selection:r:subset_id';
    VAL = '';
    SUSPEND;

  -- Списки учителей для выбора
  TAG_NAME = 'teacher_id:selection::json&colon;array';
  VAL = 1;
  SUSPEND;
    TAG_NAME = 'teacher_id:selection:option';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'teacher_id:selection:option:id';
    VAL = '*';
    SUSPEND;
    TAG_NAME = 'teacher_id:selection:option:value';
    VAL = 'Вакантная ставка';
    SUSPEND;
  FOR
    SELECT TEACHER_ID, TEACHER_NAME
    FROM CJ2_LESSON_TEACHERS_LIST(NULL, NULL, :I$USER_ID)
    ORDER BY 2
    INTO :V$ID, :V$CAPTION
  DO
  BEGIN
    TAG_NAME = 'teacher_id:selection:option';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'teacher_id:selection:option:id';
    VAL = V$ID;
    SUSPEND;
    TAG_NAME = 'teacher_id:selection:option:value';
    VAL = V$CAPTION;
    SUSPEND;
  END
  TAG_NAME = 'teacher_id:values:value';
  VAL = V$TEACHER_ID;
  SUSPEND;

  -- Учебный год
  -- Возвращаем будущее не более чем на 1 год вперед
  TAG_NAME = 'year_id:selection::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT LISTVAL_ID, VAL
    FROM LISTVALS_LIST(29)
    WHERE IS_DEL = 0 AND COST <= :V$YEAR + 1
    ORDER BY COST DESC
    INTO :V$ID, :V$CAPTION
  DO
  BEGIN
    TAG_NAME = 'year_id:selection:option';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'year_id:selection:option:id';
    VAL = V$ID;
    SUSPEND;
    TAG_NAME = 'year_id:selection:option:value';
    VAL = V$CAPTION;
    SUSPEND;
  END
  TAG_NAME = 'year_id:values:value';
  VAL = V$YEAR_ID;
  SUSPEND;

  TAG_NAME = 'members_num';
  VAL = V$MEMBERS_NUM;
  SUSPEND;

  TAG_NAME = 'weeks';
  VAL = V$WEEKS;
  SUSPEND;

  TAG_NAME = 'hours';
  VAL = V$HOURS;
  SUSPEND;

  TAG_NAME = 'is_enabled';
  VAL = COALESCE(V$IS_ENABLED, 1);
  SUSPEND;

  -- Список параллелей для выбора, и заодно битовая маска выбора
  V$MASK = 0;
  TAG_NAME = 'stage_index:selection::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT DISTINCT LV.LISTVAL_ID, R.VAL, LV.COST
    FROM LINKS L7
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V49.LISTVAL_ID
    JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
    WHERE L7.PARENT_TYPE_ID = 2 AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    ORDER BY LV.COST
    INTO :V$ID, :V$CAPTION, :V$COST
  DO
  BEGIN
    TAG_NAME = 'stage_index:selection:option';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'stage_index:selection:option:id';
    VAL = V$ID;
    SUSPEND;
    TAG_NAME = 'stage_index:selection:option:value';
    VAL = V$CAPTION;
    SUSPEND;
    TAG_NAME = 'stage_index:selection:option:stage_index';
    VAL = V$COST;
    SUSPEND;
    V$MASK = BIN_OR(V$MASK, BIN_SHL(1, V$COST));
  END
  TAG_NAME = 'stage_index:values:value';
  VAL = V$STAGE_INDEX;
  SUSPEND;

  -- Варианты периодов для выбора - по необходимости ограничиваем текущим учебным годом
  TAG_NAME = 'period_id:selection::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    -- Старая схема, запрещаем выбирать на 2024-2025 учебный год и далее
    SELECT L151.OBJ_ID, C.CAPTION
    FROM LINKS L150
    JOIN LINKS L151 ON L151.PARENT_ID = L150.OBJ_ID AND L151.OBJ_TYPE_ID = 151 AND L151.DATE_DEL IS NULL
    LEFT JOIN OBJECT_CAPTION_GET(L151.OBJ_ID) C ON 1 = 1
    WHERE L150.PARENT_TYPE_ID = 2 AND L150.OBJ_TYPE_ID = 150 AND L150.DATE_DEL IS NULL AND :V$YEAR <= 2023
    -- Новые периоды через календарный график
    UNION
    SELECT L151.OBJ_ID, C.CAPTION
    FROM LINKS L2
    JOIN LINKS L481 ON L481.PARENT_ID = L2.OBJ_ID AND L481.OBJ_TYPE_ID = 481 AND L481.DATE_DEL IS NULL
    JOIN VALL V3390 ON V3390.OBJ_ID = L481.OBJ_ID AND V3390.PARAM_ID = 3390 AND V3390.IS_DEL = 0 AND V3390.LISTVAL_ID NOT IN (11717, 14261) -- не архивный
    JOIN VALL V3389 ON V3389.OBJ_ID = L481.OBJ_ID AND V3389.PARAM_ID = 3389 AND V3389.IS_DEL = 0 AND (V3389.LISTVAL_ID = :V$YEAR_ID OR :V$YEAR_ID IS NULL)
    JOIN LINKS L151 ON L151.PARENT_ID = L481.OBJ_ID AND L151.OBJ_TYPE_ID = 151 AND L151.DATE_DEL IS NULL
    LEFT JOIN OBJECT_CAPTION_GET(L151.OBJ_ID) C ON 1 = 1
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    ORDER BY 2
    INTO :V$ID, :V$CAPTION
  DO
  BEGIN
    TAG_NAME = 'period_id:selection:option';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'period_id:selection:option:id';
    VAL = V$ID;
    SUSPEND;
    TAG_NAME = 'period_id:selection:option:value';
    VAL = V$CAPTION;
    SUSPEND;
  END
  TAG_NAME = 'period_id:values:value';
  VAL = V$PERIOD_ID;
  SUSPEND;

  -- Маска выбранных параллелей
  TAG_NAME = 'stage_mask';
  VAL = V$STAGE_MASK;
  SUSPEND;

  -- Маска доступных для выбора параллелей
  TAG_NAME = 'avail_stages';
  VAL = V$MASK;
  SUSPEND;

  TAG_NAME = 'access_level';
  VAL = V$ACCESS_LEVEL;
  SUSPEND;

  TAG_NAME = 'daymask';
  VAL = V$DAYMASK;
  SUSPEND;

  -- Действующие участники группы, с разбивкой по классам
  TAG_NAME = 'members::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    -- Учащиеся
    SELECT L10.OBJ_ID, L10.OBJ_TYPE_ID, C.NAME_FULL, CG.CAPTION, LV.COST, LPG.PARENT_ID, V49.LISTVAL_ID, M.DATE_IN
    FROM LINKS L10
    JOIN LINKS LPG ON LPG.OBJ_ID = L10.OBJ_ID AND LPG.PARENT_TYPE_ID IN (9, 187) AND LPG.DATE_DEL IS NULL
    JOIN LINKS LPS ON LPS.OBJ_ID = LPG.PARENT_ID AND LPS.PARENT_TYPE_ID = 8 AND LPS.DATE_DEL IS NULL
    JOIN VALL V49 ON V49.OBJ_ID = LPS.PARENT_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V49.LISTVAL_ID
    LEFT JOIN CJ2_PERSON_NAME(L10.OBJ_ID) C ON 1 = 1
    LEFT JOIN OBJECT_CAPTION_GET(LPG.PARENT_ID) CG ON 1 = 1
    LEFT JOIN PERSON_MOVEMENTS M ON M.DATE_DEL IS NULL AND M.PERSON_ID = L10.OBJ_ID AND M.GROUP_ID = L10.PARENT_ID AND M.DATE_OUT IS NULL
    WHERE L10.PARENT_ID = :V$GRADE_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    -- Внешние учащиеся ДО
    -- !!!
    -- Сотрудники
    UNION
    SELECT L14.OBJ_ID, L14.OBJ_TYPE_ID, C.CAPTION, 'Сотрудники', -1, 0, NULL, M.DATE_IN
    FROM LINKS L14
    LEFT JOIN OBJECT_CAPTION_GET(L14.OBJ_ID) C ON 1 = 1
    LEFT JOIN PERSON_MOVEMENTS M ON M.DATE_DEL IS NULL AND M.PERSON_ID = L14.OBJ_ID AND M.GROUP_ID = L14.PARENT_ID AND M.DATE_OUT IS NULL
    WHERE L14.PARENT_ID = :V$GRADE_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
    ORDER BY 4, 3, 2
    INTO :V$ID, :V$TYPE_ID, :V$CAPTION, :V$CLASS_CAPTION, :V$COST, :V$GROUP_ID, :V$STAGE_ID, :V$DATE
  DO
  BEGIN
    TAG_NAME = 'members:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'members:r:id';
    VAL = V$ID;
    SUSPEND;
    TAG_NAME = 'members:r:type_id';
    VAL = V$TYPE_ID;
    SUSPEND;
    TAG_NAME = 'members:r:name';
    VAL = V$CAPTION;
    SUSPEND;
    TAG_NAME = 'members:r:group_id';
    VAL = V$GROUP_ID;
    SUSPEND;
    TAG_NAME = 'members:r:group_name';
    VAL = V$CLASS_CAPTION;
    SUSPEND;
    TAG_NAME = 'members:r:stage_index';
    VAL = V$STAGE_ID;
    SUSPEND;
    TAG_NAME = 'members:r:date_from';
    VAL = (SELECT VAL FROM DATE2ISO(:V$DATE));
    SUSPEND;
  END

  TAG_NAME = 'source_groups::json&colon;array';
  VAL = 1;
  SUSPEND;
  -- Сотрудники могут входить только в журналы мероприятий
  IF(I$TYPE_ID IN (10, 11)) THEN
  BEGIN
    TAG_NAME = 'source_groups:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'source_groups:r:id';
    VAL = 0;
    SUSPEND;
    TAG_NAME = 'source_groups:r:type_id';
    VAL = 0;
    SUSPEND;
    TAG_NAME = 'source_groups:r:name';
    VAL = 'Сотрудники';
    SUSPEND;
  END
  -- ГПД и ДО вообще ничего не отдаем
  -- Для ВД, общеобр и мероприятий - список классов, но не ДО
  FOR
    SELECT L9.OBJ_ID, L9.OBJ_TYPE_ID, C.CAPTION
    FROM LINKS L7
    JOIN VALL V43 ON V43.OBJ_ID = L7.OBJ_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0 AND V43.LISTVAL_ID NOT IN (3263, 3264)
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V49.LISTVAL_ID
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 187) AND L9.DATE_DEL IS NULL
    LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C ON 1 = 1
    WHERE L7.PARENT_TYPE_ID = 2 AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL AND :I$TYPE_ID IN (0, 1, 10, 11)
    ORDER BY LV.COST, C.CAPTION
    INTO :V$ID, :V$GRADE_TYPE_ID, :V$CAPTION
  DO
  BEGIN
    TAG_NAME = 'source_groups:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'source_groups:r:id';
    VAL = V$ID;
    SUSPEND;
    TAG_NAME = 'source_groups:r:type_id';
    VAL = V$GRADE_TYPE_ID;
    SUSPEND;
    TAG_NAME = 'source_groups:r:name';
    VAL = V$CAPTION;
    SUSPEND;
  END

  -- Метод расчета рекомендуемой отметки
  TAG_NAME = 'rcm_mode:selection::json&colon;array';
  VAL = 1;
  SUSPEND;
    TAG_NAME = 'rcm_mode:selection:option';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'rcm_mode:selection:option:id';
    VAL = '0';
    SUSPEND;
    TAG_NAME = 'rcm_mode:selection:option:value';
    VAL = 'Средняя взвешенная отметка';
    SUSPEND;
    TAG_NAME = 'rcm_mode:selection:option';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'rcm_mode:selection:option:id';
    VAL = '1';
    SUSPEND;
    TAG_NAME = 'rcm_mode:selection:option:value';
    VAL = 'Медианная отметка';
    SUSPEND;
    TAG_NAME = 'rcm_mode:selection:option';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'rcm_mode:selection:option:id';
    VAL = '2';
    SUSPEND;
    TAG_NAME = 'rcm_mode:selection:option:value';
    VAL = 'Сумма баллов';
    SUSPEND;
  TAG_NAME = 'rcm_mode:values:value';
  VAL = V$RCM_MODE;
  SUSPEND;

  -- Список пользователей, имеющих доступ - включая владельца
  TAG_NAME = 'users::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT JU.USER_ID, IIF(U.OBJ_ID IS NULL, U.USER_NAME, C.CAPTION), JU.ACCESS
    FROM CJ2_JOURNAL_USERS JU
    JOIN USERS U ON U.USER_ID = JU.USER_ID AND U.DATE_DEL IS NULL
    LEFT JOIN OBJECT_CAPTION_GET(U.OBJ_ID) C ON 1 = 1
    WHERE JU.CJ_ID = :I$OBJ_ID AND JU.DATE_DEL IS NULL
    ORDER BY 2
    INTO :V$ID, :V$CAPTION, :V$COST
  DO
  BEGIN
    TAG_NAME = 'users:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'users:r:id';
    VAL = V$ID;
    SUSPEND;
    TAG_NAME = 'users:r:type';
    VAL = V$TYPE;
    SUSPEND;
    TAG_NAME = 'users:r:name';
    VAL = V$CAPTION;
    SUSPEND;
    TAG_NAME = 'users:r:access';
    VAL = V$COST;
    SUSPEND;
  END

  -- Система оценивания - выдаем и предполагаемую, и фиксированную для данного журнала
  -- оставляем опцию выбора по-умолчанию
  TAG_NAME = 'asst_id:selection::json&colon;array';
  VAL = 1;
  SUSPEND;
    TAG_NAME = 'asst_id:selection:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'asst_id:selection:r:id';
    VAL = '*';
    SUSPEND;
    TAG_NAME = 'asst_id:selection:r:value';
    VAL = 'По-умолчанию';
    SUSPEND;
  FOR
    SELECT T.MARK_TYPE_ID, T.MARK_NAME
    FROM CJ2_MARK_TYPE T
    WHERE T.IS_DEL = 0 AND T.PARENT_ID IS NULL AND T.MARK_TYPE_ID > 0 AND T.MARK_TYPE_ID <> 200 -- кроме
    ORDER BY 1
    INTO :V$ID, :V$CAPTION
  DO
  BEGIN
    TAG_NAME = 'asst_id:selection:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'asst_id:selection:r:id';
    VAL = V$ID;
    SUSPEND;
    TAG_NAME = 'asst_id:selection:r:value';
    IF(V$ID = 799) THEN V$CAPTION = 'Критериальная'; -- вместо процента выполнения
    IF(V$ID = 999) THEN V$CAPTION = 'Б/О'; -- безотметочная
    VAL = V$CAPTION;
    SUSPEND;
  END
  TAG_NAME = 'asst_id:values:value';
  VAL = V$ASST_ID;
  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_JOURNAL_LIST (
    I$TYPE_ID INTEGER,
    I$USER_ID VARCHAR(40),
    I$CJ_ID BIGINT = NULL)
RETURNS (
    JOURNAL_TYPE SMALLINT,
    CJ_ID BIGINT,
    SUBJECT_ID BIGINT,
    GRADE_ID BIGINT,
    GRADE_TYPE_ID BIGINT,
    TEACHER_ID BIGINT,
    CAPTION VARCHAR(1000),
    MEMBERS_NUM INTEGER,
    TEACHER_NAME VARCHAR(400),
    SUBJECT_NAME VARCHAR(1000),
    STAGE_INDEX BIGINT,
    STAGE_NAME VARCHAR(100),
    ACCESS_LEVEL SMALLINT,
    STAGE_MASK BIGINT,
    YEAR_ID BIGINT,
    YEAR_NAME VARCHAR(10),
    WEEKS INTEGER,
    HOURS FLOAT,
    IS_ENABLED SMALLINT,
    RCM_MODE SMALLINT,
    DURATION SMALLINT,
    DAYMASK SMALLINT,
    MASTER_ID BIGINT,
    MASTER_NAME VARCHAR(400),
    PERIOD_ID BIGINT,
    PERIOD_NAME VARCHAR(100),
    VK_ENABLED SMALLINT,
    CHAT_ID VARCHAR(400),
    ROOM_ID BIGINT,
    ASST_ID BIGINT)
AS
DECLARE VARIABLE V$USER_ID BIGINT;
DECLARE VARIABLE V$TEACHER_ID BIGINT;
DECLARE VARIABLE V$USER_TYPE SMALLINT;
DECLARE VARIABLE V$ALT_TYPE INTEGER;
begin

  IF(I$TYPE_ID = 10) THEN V$ALT_TYPE = 11;

  IF(I$USER_ID = 'Веб-администратор') THEN V$USER_ID = 1; ELSE V$USER_ID = I$USER_ID;

  -- Получаем ID сотрудника
  SELECT U.USER_TYPE, U.OBJ_ID
  FROM USERS U
  WHERE U.USER_ID = :V$USER_ID AND U.DATE_DEL IS NULL AND U.IS_BLOCKED = 0
  INTO :V$USER_TYPE, :V$TEACHER_ID;

  FOR
    SELECT CJM.OBJ_ID, CJM.JOURNAL_TYPE, CJM.SUBJECT_ID, CJM.GRADE_ID, CJM.GRADE_TYPE_ID, CJM.TEACHER_ID, CJM.JOURNAL_NAME,
      CJM.STAGE_INDEX, R.VAL, CJM.STAGE_MASK, CJM.YEAR_ID, CJM.WEEKS, CJM.HOURS, CJM.IS_ENABLED, CJM.RCM_MODE, CJM.DURATION, CJM.DAYMASK,
      L179.EXT_OBJ_ID, CJM.PERIOD_ID, CJM.VK_ENABLED, CJM.CHAT_ID, CJM.ROOM_ID, CJM.ASST_ID
    FROM CJ2_JOURNAL CJM
    LEFT JOIN LINKS L179 ON L179.OBJ_ID = CJM.GRADE_ID AND L179.PARENT_TYPE_ID = 2 AND L179.DATE_DEL IS NULL
    LEFT JOIN LISTVALS LV ON LV.LISTVAL_ID = CJM.STAGE_INDEX
    LEFT JOIN RES R ON R.RES_ID = LV.RES_ID
    WHERE CJM.DATE_DEL IS NULL AND (:I$TYPE_ID IS NULL OR CJM.JOURNAL_TYPE = :I$TYPE_ID OR CJM.JOURNAL_TYPE = :V$ALT_TYPE)
      AND (:I$CJ_ID IS NULL OR CJM.OBJ_ID = :I$CJ_ID)
    INTO :CJ_ID, :JOURNAL_TYPE, :SUBJECT_ID, :GRADE_ID, :GRADE_TYPE_ID, :TEACHER_ID, :CAPTION,
      :STAGE_INDEX, :STAGE_NAME, :STAGE_MASK, :YEAR_ID, :WEEKS, :HOURS, :IS_ENABLED, :RCM_MODE, :DURATION, :DAYMASK,
      :MASTER_ID, :PERIOD_ID, :VK_ENABLED, :CHAT_ID, :ROOM_ID, :ASST_ID
  DO
  BEGIN
    -- Проверяем наличие прав доступа к журналу
    ACCESS_LEVEL = (SELECT ACCESS_LEVEL FROM CJ2_JOURNAL_ACCESS(:V$USER_ID, :CJ_ID));

    IF(ACCESS_LEVEL > 0) THEN
    BEGIN

      -- Название предмета
      IF(SUBJECT_ID IS NOT NULL) THEN
      BEGIN
        SUBJECT_NAME = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:SUBJECT_ID));
      END
      ELSE
      BEGIN
        SUBJECT_NAME = NULL;
      END

      -- Формируем название по-умолчанию
      IF(CAPTION IS NULL) THEN
      BEGIN
        CAPTION = '';
        IF(SUBJECT_ID IS NOT NULL) THEN CAPTION = SUBJECT_NAME;
        IF(GRADE_ID IS NOT NULL) THEN
        BEGIN
          IF(CHAR_LENGTH(CAPTION) > 0) THEN CAPTION = CAPTION || ' - ';
          CAPTION = CAPTION || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:GRADE_ID));
        END
      END

      SELECT COALESCE(R.VAL, 'Текущий год')
      FROM LISTVALS LV
      JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
      WHERE LV.LISTVAL_ID = :YEAR_ID
      INTO :YEAR_NAME;

      -- ФИО предметника или ответственного
      IF(TEACHER_ID IS NULL) THEN TEACHER_NAME = NULL;
      ELSE TEACHER_NAME = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:TEACHER_ID));

      -- Смотрим состав участников, раздельно учащиеся и сотрудники
      SELECT COUNT(*)
      FROM LINKS
      WHERE PARENT_ID = :GRADE_ID AND OBJ_TYPE_ID IN (10, 14, 20) AND DATE_DEL IS NULL
      INTO :MEMBERS_NUM;

      -- Мастер-ГУП
      IF(MASTER_ID IS NULL) THEN MASTER_NAME = NULL;
      ELSE MASTER_NAME = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:MASTER_ID));

      IF(PERIOD_ID IS NULL) THEN PERIOD_NAMe = NULL;
      ELSE SELECT CAPTION FROM OBJECT_CAPTION_GET(:PERIOD_ID) INTO :PERIOD_NAME;

      SUSPEND;

    END

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_LESSONS_LIST (
    I$CJ_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    LESSON_ID BIGINT,
    LESSON_DATE DATE,
    LESSON_NUM INTEGER,
    LESSON_THEME VARCHAR(1000),
    TEACHER_ID BIGINT,
    TEACHER_NAME VARCHAR(1000),
    IS_COMPLETED SMALLINT)
AS
begin

  FOR
      SELECT L.OBJ_ID, L.LESSON_DATE, L.LESSON_NUM, L.LESSON_THEME, L.TEACHER_ID, C.CAPTION, L.IS_COMPLETED
      FROM CJ2_JOURNAL_LESSONS L
      LEFT JOIN OBJECT_CAPTION_GET(L.TEACHER_ID) C ON 1 = 1
      WHERE L.CJ_ID = :I$CJ_ID AND L.DATE_DEL IS NULL
      INTO :LESSON_ID, :LESSON_DATE, :LESSON_NUM, :LESSON_THEME, :TEACHER_ID, :TEACHER_NAME, :IS_COMPLETED
  DO
  BEGIN
      SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_LESSON_ADD (
    I$CJ_ID BIGINT NOT NULL,
    I$LESSON_ID BIGINT,
    I$LESSON_DATE DATE,
    I$LESSON_NUM INTEGER,
    I$TEACHER_ID BIGINT,
    I$IS_COMPLETED INTEGER NOT NULL,
    I$LESSON_THEME VARCHAR(1000) NOT NULL,
    I$LESSON_HOMETASK VARCHAR(1000),
    I$LESSON_EXTRA VARCHAR(2000),
    I$USER_ID VARCHAR(40),
    I$LESSON_TYPE BIGINT = NULL,
    I$HOURS FLOAT = 1,
    I$LESSON_PTP_ID BIGINT = NULL,
    I$REASON_ID BIGINT = NULL,
    I$DE_ID VARCHAR(400) = NULL,
    I$IS_ONLINE SMALLINT = NULL)
RETURNS (
    LESSON_ID BIGINT,
    DEFAULT_CONTROL_ID BIGINT)
AS
DECLARE VARIABLE ACCESS_LEVEL INTEGER;
DECLARE VARIABLE IS_SUBST SMALLINT;
DECLARE VARIABLE V$CONTROL_ID BIGINT;
DECLARE VARIABLE V$YEAR INTEGER;
DECLARE VARIABLE V$STATE SMALLINT;
DECLARE VARIABLE V$IM SMALLINT;
DECLARE VARIABLE V$DATE DATE;
DECLARE VARIABLE V$TIME TIME;
DECLARE VARIABLE V$N INTEGER;
DECLARE VARIABLE V$STATUS VARCHAR(1);
DECLARE VARIABLE V$DE_ID VARCHAR(400);
DECLARE VARIABLE V$GLOBAL_DISABLE BIGINT;
DECLARE VARIABLE P INTEGER;
DECLARE VARIABLE V$LESSON_THEME VARCHAR(1000);
DECLARE VARIABLE V$LESSON_HOMEWORK VARCHAR(1000);
DECLARE VARIABLE V$LESSON_EXTRA VARCHAR(2000);
DECLARE VARIABLE V$INST_ID VARCHAR(40);
DECLARE VARIABLE V$CHAT_ID VARCHAR(400);
DECLARE VARIABLE V$THEME_LIMIT INTEGER;
DECLARE VARIABLE V$TH DOUBLE PRECISION;
DECLARE VARIABLE V$LH DOUBLE PRECISION;
DECLARE VARIABLE V$H DOUBLE PRECISION;
DECLARE VARIABLE V$PARENT BIGINT;
DECLARE VARIABLE V$THIS BIGINT;
DECLARE VARIABLE V$JT INTEGER;
DECLARE VARIABLE V$RSRV BIGINT;
DECLARE VARIABLE V$REF_ID BIGINT;
DECLARE VARIABLE V$YEAR_ID BIGINT;
DECLARE VARIABLE V$SCH_ID BIGINT;
DECLARE VARIABLE V$MS_ID BIGINT;
DECLARE VARIABLE TH VARCHAR(2);
DECLARE VARIABLE TM VARCHAR(2);
DECLARE VARIABLE S VARCHAR(40);
DECLARE VARIABLE DD DATE;
DECLARE VARIABLE V$DDLAST DATE;
DECLARE VARIABLE V$HAS_HW SMALLINT;
begin

  -- Проверяем права доступа к журналу
  SELECT ACCESS_LEVEL, IS_SUBST
  FROM CJ2_JOURNAL_ACCESS(:I$USER_ID, :I$CJ_ID)
  INTO :ACCESS_LEVEL, :IS_SUBST;

  IF(ACCESS_LEVEL = 0) THEN EXCEPTION DATA_ERROR 'Нет прав доступа к указанному журналу';
  IF(ACCESS_LEVEL IN (5, 6)) THEN EXCEPTION DATA_ERROR 'Вы не можете изменять уроки';

  -- Проверить дополнительно права для уровня 3 (классрук) и 4 (замещение)

  I$LESSON_THEME = TRIM(I$LESSON_THEME);
  IF(CHAR_LENGTH(I$LESSON_THEME) < 2) THEN EXCEPTION DATA_ERROR 'Не заполнена тема';
  I$LESSON_HOMETASK = TRIM(I$LESSON_HOMETASK);
  IF(I$LESSON_HOMETASK = '') THEN I$LESSON_HOMETASK = NULL;
  I$LESSON_EXTRA = TRIM(I$LESSON_EXTRA);
  IF(I$LESSON_EXTRA = '') THEN I$LESSON_EXTRA = NULL;

  V$STATUS = (SELECT STATUS FROM OU_LICENCE_TYPE);

  V$HAS_HW = 0;
  IF(I$LESSON_HOMETASK IS NOT NULL AND CHAR_LENGTH(I$LESSON_HOMETASK) > 0) THEN V$HAS_HW = 1;

  -- Проверяем что дата урока попадает в диапазон дат текущего учебного периода
  SELECT FIRST 1 V1236.LISTVAL_ID, LV.COST, COALESCE(V3324.LISTVAL_ID, 3), COALESCE(V3368.VAL, 0), COALESCE(V3369.LISTVAL_ID, 3)
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  LEFT JOIN VALL V3324 ON V3324.OBJ_ID = L2.OBJ_ID AND V3324.PARAM_ID = 3324 AND V3324.IS_DEL = 0
  LEFT JOIN VALI V3368 ON V3368.OBJ_ID = L2.OBJ_ID AND V3368.PARAM_ID = 3368 AND V3368.IS_DEL = 0
  LEFT JOIN VALL V3369 ON V3369.OBJ_ID = L2.OBJ_ID AND V3369.PARAM_ID = 3369 AND V3369.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$YEAR_ID, :V$YEAR, :V$GLOBAL_DISABLE, :V$THEME_LIMIT, :V$RSRV;

  IF(V$GLOBAL_DISABLE = 2) THEN EXCEPTION DATA_ERROR 'Внесение изменений в классный журнал запрещено руководителем организации';

  IF(V$YEAR IS NULL) THEN
  BEGIN
    V$YEAR = EXTRACT(YEAR FROM CURRENT_DATE);
    IF(EXTRACT(MONTH FROM CURRENT_DATE) < 9) THEN V$YEAR = V$YEAR - 1;
  END

  SELECT FIRST 1 J.JOURNAL_TYPE, J.REF_ID, J.VK_ENABLED
  FROM CJ2_JOURNAL J
  WHERE J.OBJ_ID = :I$CJ_ID
  INTO :V$JT, :V$REF_ID, :P;

  -- Для отрицательных номеров (заголовки разделов в ПВР) уроков дату не проверяем
  IF((V$JT <> 20 OR I$LESSON_NUM >= 0) AND (I$LESSON_DATE < '01.09.' || V$YEAR OR I$LESSON_DATE > '31.07.' || (V$YEAR + 1))) THEN EXCEPTION DATA_ERROR 'Недопустимая дата в пределах текущего учебного года';

  IF(V$JT <> 20) THEN
  BEGIN
    IF(I$HOURS IS NULL) THEN I$HOURS = 1;
    IF(I$HOURS <= 0) THEN EXCEPTION DATA_ERROR 'Длительность занятия не может быть нулевой или отрицательной';
  END
  ELSE
  BEGIN
    IF(I$HOURS IS NULL) THEN I$HOURS = 0;
    IF(I$HOURS < 0) THEN EXCEPTION DATA_ERROR 'Длительность занятия не может быть отрицательной';
  END

  -- Запрет удалять строки для действующего плана
  IF(V$JT = 20 AND I$LESSON_ID IS NULL AND EXISTS(
    SELECT FIRST 1 1
    FROM VALL V
    WHERE V.OBJ_ID = :V$REF_ID AND V.PARAM_ID = 3373 AND V.IS_DEL = 0 AND V.LISTVAL_ID = 11715
  ))
  THEN
    EXCEPTION DATA_ERROR 'Нельзя добавлять разделы или мероприятия в действующем плане';

  -- Дата на которое задается ДЗ, если она указана
  P = POSITION('@@' IN I$LESSON_HOMETASK);
  IF(P > 0) THEN
  BEGIN
    S = SUBSTRING(I$LESSON_HOMETASK FROM P + 2 FOR 10);
    BEGIN
      DD = S;
      WHEN ANY DO DD = NULL;
    END
    -- Дата задания не может выходить за 31.05 или быть раньше даты урока
    IF(DD IS NOT NULL) THEN
    BEGIN
      IF(DD < I$LESSON_DATE) THEN EXCEPTION DATA_ERROR 'Дата домашнего задания не может быть раньше даты урока';
      IF(EXTRACT(MONTH FROM I$LESSON_DATE) < 9) THEN V$DDLAST = '31.05.' || EXTRACT(YEAR FROM I$LESSON_DATE);
        ELSE V$DDLAST = '31.05.' || (EXTRACT(YEAR FROM I$LESSON_DATE) + 1);
      IF(DD > V$DDLAST) THEN EXCEPTION DATA_ERROR 'Дата домашнего задания не может выходить за пределы учебного года';
    END
  END

  -- Вычисляем время урока
  IF(I$LESSON_NUM > 60) THEN
  BEGIN
    TH = TRUNC(I$LESSON_NUM / 60);
    IF(CHAR_LENGTH(TH) < 2) THEN TH = '0' || TH;
    TM = I$LESSON_NUM - TRUNC(I$LESSON_NUM / 60) * 60;
    IF(CHAR_LENGTH(TM) < 2) THEN TM = '0' || TM;
    V$TIME = TH || ':' || TM;
  END
  ELSE IF(I$LESSON_NUM > 0) THEN
  BEGIN
    -- Ищем подходящий шаблон расписания
    SELECT FIRST 1 SI.SCHEDULE_ID
    FROM SCHEDULE_ITEMS SI
    JOIN LINKS LP3 ON LP3.OBJ_ID = SI.SCHEDULE_ID AND LP3.PARENT_TYPE_ID = 3 AND LP3.DATE_DEL IS NULL
    JOIN VALD V3120 ON V3120.OBJ_ID = SI.SCHEDULE_ID AND V3120.PARAM_ID = 3120 AND V3120.IS_DEL = 0 AND V3120.VAL <= :I$LESSON_DATE
    JOIN VALD V3121 ON V3121.OBJ_ID = SI.SCHEDULE_ID AND V3121.PARAM_ID = 3121 AND V3121.IS_DEL = 0 AND V3121.VAL >= :I$LESSON_DATE
    WHERE SI.DATE_DEL IS NULL AND SI.CJ_ID = :I$CJ_ID
    INTO :V$SCH_ID;

    -- Если нет расписания где упомянут данный журнал, ищем первый попавшийся
    IF(V$SCH_ID IS NULL) THEN
    SELECT FIRST 1 L59.OBJ_ID
    FROM LINKS L68
    JOIN LINKS L3 ON L3.PARENT_ID = L68.OBJ_ID AND L3.OBJ_TYPE_ID = 3 AND L3.DATE_DEL IS NULL
    JOIN VALL V37 ON V37.OBJ_ID = L3.OBJ_ID AND V37.PARAM_ID = 37 AND V37.IS_DEL = 0 AND V37.LISTVAL_ID = :V$YEAR_ID
    JOIN LINKS L59 ON L59.PARENT_ID = L3.OBJ_ID AND L59.OBJ_TYPE_ID = 59 AND L59.DATE_DEL IS NULL
    JOIN VALL V1341 ON V1341.OBJ_ID = L59.OBJ_ID AND V1341.PARAM_ID = 1341 AND V1341.IS_DEL = 0 AND V1341.LISTVAL_ID = 2
    JOIN VALD V3120 ON V3120.OBJ_ID = L59.OBJ_ID AND V3120.PARAM_ID = 3120 AND V3120.IS_DEL = 0 AND V3120.VAL <= :I$LESSON_DATE
    JOIN VALD V3121 ON V3121.OBJ_ID = L59.OBJ_ID AND V3121.PARAM_ID = 3121 AND V3121.IS_DEL = 0 AND V3121.VAL >= :I$LESSON_DATE
    WHERE L68.PARENT_TYPE_ID = 2 AND L68.OBJ_TYPE_ID = 68 AND L68.DATE_DEL IS NULL
    INTO :V$SCH_ID;

    IF(V$SCH_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не создан шаблон расписания (в крайнем случае создайте шаблон без уроков, но с датами действия в которые попадет данный урок)';

    SELECT FIRST 1 V405.VAL
    FROM LINKS L60
    JOIN VALI V404 ON V404.OBJ_ID = L60.OBJ_ID AND V404.PARAM_ID = 404 AND V404.IS_DEL = 0 AND V404.VAL = :I$LESSON_NUM
    JOIN VALT V405 ON V405.OBJ_ID = L60.OBJ_ID AND V405.PARAM_ID = 405 AND V405.IS_DEL = 0
    WHERE L60.PARENT_ID = :V$SCH_ID AND L60.OBJ_TYPE_ID = 60 AND L60.DATE_DEL IS NULL
    INTO :V$TIME;

    IF(V$TIME IS NULL) THEN EXCEPTION DATA_ERROR 'В шаблоне расписания не указано время начала для указанного номера урока ' || I$LESSON_NUM;
  END

  -- Проверяем, что урока с такой датой и номером еще нет
  IF(EXISTS(
    SELECT FIRST 1 1
    FROM CJ2_JOURNAL_LESSONS L
    WHERE L.DATE_DEL IS NULL AND L.CJ_ID = :I$CJ_ID AND L.LESSON_DATE = :I$LESSON_DATE AND L.LESSON_NUM = :I$LESSON_NUM
      AND (:I$LESSON_ID IS NULL OR :I$LESSON_ID < 0 OR L.OBJ_ID <> :I$LESSON_ID)
  )) THEN
    EXCEPTION DATA_ERROR 'Урок с такой датой и номером уже есть';

  -- Нельзя ставить проведенными уроки в будущем
  IF(I$IS_COMPLETED = 2 AND I$LESSON_DATE > CURRENT_DATE) THEN EXCEPTION DATA_ERROR 'Нельзя отмечать проведенными уроки с датой в будущем';

  -- Внимание: в этих проверках может быть коллизия, если имеется микс из уроков по времени и по номеру
  -- Нельзя активировать уроки в конце списка, если до них есть неактивированные
  IF(V$JT < 20 AND I$LESSON_NUM >= 0 AND I$IS_COMPLETED <> 0 AND V$YEAR_ID > 10984) THEN
  BEGIN
    IF(EXISTS(
      SELECT FIRST 1 1
      FROM CJ2_JOURNAL_LESSONS L
      WHERE L.DATE_DEL IS NULL AND L.CJ_ID = :I$CJ_ID AND (L.LESSON_DATE < :I$LESSON_DATE OR (L.LESSON_DATE = :I$LESSON_DATE AND L.LESSON_TIME < :V$TIME))
        AND (L.OBJ_ID <> :I$LESSON_ID OR :I$LESSON_ID IS NULL) AND L.IS_COMPLETED = 0 AND L.IS_PUBLISHED = 0
    ))
    THEN
      EXCEPTION DATA_ERROR 'Нельзя отмечать урок как проведенный или опубликованный, если перед ним есть не-опубликованные и не-проведенные уроки';
  END
  -- Нельзя снимать активацию уроков в прошлом с образованием дырки
  IF(V$JT < 20 AND I$LESSON_NUM >= 0 AND I$IS_COMPLETED = 0 AND V$YEAR_ID > 10984) THEN
  BEGIN
    IF(EXISTS(
      SELECT FIRST 1 1
      FROM CJ2_JOURNAL_LESSONS L
      WHERE L.DATE_DEL IS NULL AND L.CJ_ID = :I$CJ_ID AND (L.LESSON_DATE > :I$LESSON_DATE OR (L.LESSON_DATE = :I$LESSON_DATE AND L.LESSON_TIME > :V$TIME))
        AND (L.OBJ_ID <> :I$LESSON_ID OR :I$LESSON_ID IS NULL) AND (L.IS_COMPLETED <> 0 OR L.IS_PUBLISHED <> 0)
    ))
    THEN
      EXCEPTION DATA_ERROR 'Нельзя снимать статус проведения или публикации урока, если после него есть уже опубликованные или проведенные уроки';
  END

  -- Для планов воспитательной работы IS_ONLINE означает признак добавления в расписание
  IF(I$IS_ONLINE = 1 AND V$JT <> 20) THEN
  BEGIN
    IF(P = 0) THEN EXCEPTION DATA_ERROR 'Онлайн-урок можно запустить только для журналов, отмеченных для интеграции';

    SELECT FIRST 1 V3355.VAL
    FROM VALS V3355
    WHERE V3355.OBJ_ID = :I$TEACHER_ID AND V3355.PARAM_ID = 3355 AND V3355.IS_DEL = 0
    INTO :V$CHAT_ID;

    IF(V$CHAT_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Онлайн-урок может провести только преподаватель, по которому есть профиль VK и в систему получены данные VKID';
  END

  -- При добавлении нового урока в общеобразовательном журнале контролируем лимит часов по ПТП
  -- подсчитываем количество часов вверх по дереву
  IF(I$LESSON_ID IS NULL AND I$LESSON_PTP_ID IS NOT NULL AND V$THEME_LIMIT >= 0) THEN
  BEGIN
    -- Какой тип журнала ? Смотрим только общеобр
    IF(V$JT = 0) THEN
    BEGIN

      -- Для школ запрещаем добавление уроков без ПТП
      IF(I$LESSON_ID IS NULL AND I$LESSON_PTP_ID IS NULL AND V$STATUS = 'O') THEN EXCEPTION DATA_ERROR 'В общеобразовательных журналах уроки должны добавляться только из ПТП';

      -- Сколько часов выставлено в текущей версии урока в плане ?
      SELECT COALESCE(L.DURATION, 1), L.PARENT_LESSON_ID
      FROM PTP_LESSONS L
      WHERE L.OBJ_ID = :I$LESSON_PTP_ID
      INTO :V$LH, :V$PARENT;

      SELECT SUM(COALESCE(L.LESSON_HOURS, 1))
      FROM CJ2_JOURNAL_LESSONS L
      WHERE L.DATE_DEL IS NULL AND L.CJ_ID = :I$CJ_ID AND L.LESSON_PTP_ID = :I$LESSON_PTP_ID
      INTO :V$TH;
      V$TH = COALESCE(V$TH, 0) + COALESCE(I$HOURS, 1);

      WHILE(V$PARENT IS NOT NULL) DO
      BEGIN
        V$H = 0;
        SELECT SUM(COALESCE(L.LESSON_HOURS, 1))
        FROM CJ2_JOURNAL_LESSONS L
        WHERE L.DATE_DEL IS NULL AND L.CJ_ID = :I$CJ_ID AND L.LESSON_PTP_ID = :V$PARENT
        INTO :V$H;
        V$TH = V$TH + V$H;

        V$THIS = NULL;
        SELECT L.PARENT_LESSON_ID
        FROM PTP_LESSONS L
        WHERE L.OBJ_ID = :V$PARENT
        INTO :V$THIS;

        V$PARENT = V$THIS;
      END

      IF(V$TH > V$LH + V$THEME_LIMIT) THEN
        EXCEPTION DATA_ERROR 'Вы превысили указанное в ПТП количество часов для данной темы. Текущие настройки позволяют превысить часы не более чем на ' ||
        V$THEME_LIMIT || ' часов. Завуч может изменить лимит в приложении СМИР';

    END

  END

  -- Проверка резервного урока
  IF(I$LESSON_ID IS NULL AND I$LESSON_PTP_ID = 0 AND V$RSRV = 3) THEN
  BEGIN
    EXCEPTION DATA_ERROR 'Настройками запрещено использование резервных уроков. Завуч может изменить настройку в приложении СМИР';
  END

  IF(I$LESSON_ID IS NULL OR I$LESSON_ID < 0) THEN
  BEGIN
    -- В случае ДПО делаем разбивку занятия на отдельные записи по часу. В остальных случаях добавляем один урок
    IF(V$STATUS = 'P' AND I$LESSON_ID IS NULL) THEN
    BEGIN

      WHILE(I$HOURS > 0) DO
      BEGIN
        SELECT LESSON_ID, DEFAULT_CONTROL_ID
        FROM CJ2_LESSON_ADD(:I$CJ_ID, -1, :I$LESSON_DATE, :I$LESSON_NUM, :I$TEACHER_ID, :I$IS_COMPLETED,
          :I$LESSON_THEME, :I$LESSON_HOMETASK, :I$LESSON_EXTRA, :I$USER_ID, :I$LESSON_TYPE, IIF(:I$HOURS >= 1, 1, :I$HOURS),
          :I$LESSON_PTP_ID, :I$REASON_ID, :I$DE_ID)
        INTO :LESSON_ID, :DEFAULT_CONTROL_ID;

        I$HOURS = I$HOURS - 1;
        IF(I$LESSON_NUM < 60) THEN BEGIN
          I$LESSON_NUM = I$LESSON_NUM + 1;
          IF(I$LESSON_NUM >= 60) THEN EXCEPTION DATA_ERROR 'Время занятия выходит за допустимую сетку номеров уроков';
        END
        ELSE BEGIN
          I$LESSON_NUM = I$LESSON_NUM + 60;
          IF(I$LESSON_NUM >= 1440) THEN EXCEPTION DATA_ERROR 'Время занятия выходит за 00:00';
        END
      END

    END
    ELSE
    BEGIN

      IF(I$IS_ONLINE IS NULL) THEN I$IS_ONLINE = 0;

      -- Привязываем урок к виртуальным урокам для витрины, либо обновляем привязку при изменении порядка уроков
      IF(I$IS_COMPLETED <> 0 AND V$JT IN (0, 1) AND V$YEAR_ID > 10984) THEN
      SELECT OBJ_ID FROM CJ2_LESSON_MS_ASSIGN(:I$CJ_ID, :I$LESSON_DATE, :I$LESSON_NUM, :V$TIME, NULL, NULL, NULL, NULL, :V$HAS_HW) INTO :V$MS_ID;

      INSERT INTO CJ2_JOURNAL_LESSONS
      (CJ_ID, LESSON_DATE, LESSON_NUM, LESSON_TIME, TEACHER_ID, LESSON_THEME, LESSON_HOMEWORK, LESSON_EXTRA,
        IS_COMPLETED, IS_PUBLISHED, LESSON_PTP_ID, LESSON_TYPE_ID, LESSON_HOURS, DE_ID, IS_ONLINE/*, MS_ID*/)
      VALUES (:I$CJ_ID, :I$LESSON_DATE, :I$LESSON_NUM, :V$TIME, :I$TEACHER_ID, :I$LESSON_THEME, :I$LESSON_HOMETASK, :I$LESSON_EXTRA,
        IIF(:I$IS_COMPLETED = 2, 1, 0), IIF(:I$IS_COMPLETED = 1, 1, 0), :I$LESSON_PTP_ID, :I$LESSON_TYPE, :I$HOURS, :I$DE_ID, :I$IS_ONLINE/*, :V$MS_ID*/)
      RETURNING OBJ_ID INTO :LESSON_ID;

      -- Создаем контроль по-умолчанию с тем же статусом
      INSERT INTO CJ2_CONTROL
      (LESSON_ID, CONTROL_TYPE_ID, MARK_SYSTEM_ID, CONTROL_COST, IS_COMPLETED)
      VALUES (:LESSON_ID, 0, 0, 0, IIF(:I$IS_COMPLETED = 2, 1, 0))
      RETURNING CONTROL_ID INTO :DEFAULT_CONTROL_ID;

      IF(I$IS_COMPLETED <> 0) THEN
      BEGIN
        INSERT INTO CJ2_LESSON_HISTORY
        (LESSON_ID, STATE_ID, USER_ID)
        VALUES (:LESSON_ID, :I$IS_COMPLETED, IIF(:I$USER_ID = 'Веб-администратор', 1, :I$USER_ID));
      END

      INSERT INTO CJ2_LESSON_LOG
      (LESSON_ID, FIELD_ID, VAL, USER_ID)
      VALUES (:LESSON_ID, 'NEW', 'Статус ' || :I$IS_COMPLETED || ', ' || (SELECT VAL FROM DATE2ISO(:I$LESSON_DATE, 0)) || ' #' || :I$LESSON_NUM, IIF(:I$USER_ID = 'Веб-администратор', 1, :I$USER_ID));

      INSERT INTO CJ2_LESSON_LOG
      (LESSON_ID, FIELD_ID, VAL, USER_ID)
      VALUES (:LESSON_ID, 'NEW LESSON_THEME', :I$LESSON_THEME, IIF(:I$USER_ID = 'Веб-администратор', 1, :I$USER_ID));

      INSERT INTO CJ2_LESSON_LOG
      (LESSON_ID, FIELD_ID, VAL, USER_ID)
      VALUES (:LESSON_ID, 'NEW LESSON_HOMEWORK', :I$LESSON_HOMETASK, IIF(:I$USER_ID = 'Веб-администратор', 1, :I$USER_ID));
    END
  END
  ELSE
  BEGIN

    LESSON_ID = I$LESSON_ID;

    SELECT FIRST 1 L.IS_PUBLISHED + L.IS_COMPLETED * 2, L.LESSON_DATE, L.LESSON_NUM, L.DE_ID, L.LESSON_THEME, L.LESSON_HOMEWORK, L.LESSON_EXTRA, L.INST_ID, L.MS_ID
    FROM CJ2_JOURNAL_LESSONS L
    WHERE L.OBJ_ID = :I$LESSON_ID AND L.DATE_DEL IS NULL
    INTO :V$STATE, :V$DATE, :V$N, :V$DE_ID, :V$LESSON_THEME, :V$LESSON_HOMEWORK, :V$LESSON_EXTRA, :V$INST_ID, :V$MS_ID;

    IF(V$STATE IS NULL) THEN EXCEPTION DATA_ERROR 'Урок не найден или был удален';
    -- IF(I$IS_ONLINE = 0 AND V$INST_ID IS NOT NULL) THEN EXCEPTION DATA_ERROR 'Видеозвонок уже создан, снять статус Онлайн нельзя';

    -- При изменении даты или номера урока перезапускаем внешние связи
    -- Проверяем, чтобы при изменении даты не сломалась хронология опубликованных уроков
    IF(I$LESSON_DATE <> V$DATE OR I$LESSON_NUM <> V$N) THEN
    BEGIN
      V$IM = 1;
    END

    -- Нельзя менять привязку ПЭС, если выставлены отметки
    IF(COALESCE(I$DE_ID, '') <> COALESCE(V$DE_ID, '') AND EXISTS(
      SELECT FIRST 1 1
      FROM CJ2_CONTROL C
      JOIN CJ2_MARK M ON M.DATE_DEL IS NULL AND M.CONTROL_ID = C.CONTROL_ID
      WHERE C.DATE_DEL IS NULL AND C.LESSON_ID = :I$LESSON_ID AND C.CONTROL_TYPE_ID <> 0
    ))
    THEN EXCEPTION DATA_ERROR 'Нельзя менять связи с элементами содержания при наличии выставленных отметок';

    -- Привязываем урок к виртуальным урокам для витрины, либо обновляем привязку при изменении порядка уроков
    -- только начиная с 2025 учебного года
    IF((V$MS_ID IS NULL OR V$IM = 1 OR COALESCE(I$LESSON_HOMETASK, '') <> COALESCE(V$LESSON_HOMEWORK, '')) AND I$IS_COMPLETED <> 0 AND V$JT IN (0, 1) AND V$YEAR_ID > 10984) THEN
    SELECT OBJ_ID FROM CJ2_LESSON_MS_ASSIGN(:I$CJ_ID, :I$LESSON_DATE, :I$LESSON_NUM, :V$TIME, :I$LESSON_ID, :V$MS_ID, :V$DATE, :V$N, :V$HAS_HW) INTO :V$MS_ID;

    UPDATE CJ2_JOURNAL_LESSONS
    SET LESSON_DATE = :I$LESSON_DATE, LESSON_NUM = :I$LESSON_NUM, LESSON_THEME = :I$LESSON_THEME, LESSON_HOMEWORK = :I$LESSON_HOMETASK, LESSON_EXTRA = :I$LESSON_EXTRA,
      TEACHER_ID = :I$TEACHER_ID, IS_COMPLETED = IIF(:I$IS_COMPLETED = 2, 1, 0), IS_PUBLISHED = IIF(:I$IS_COMPLETED = 1, 1, 0), LESSON_TYPE_ID = :I$LESSON_TYPE,
      LESSON_HOURS = :I$HOURS, INST_MODIFIED = COALESCE(:V$IM, INST_MODIFIED, 0), DE_ID = :I$DE_ID, IS_ONLINE = COALESCE(:I$IS_ONLINE, IS_ONLINE),
      LESSON_TIME = :V$TIME, MS_ID = :V$MS_ID
    WHERE OBJ_ID = :I$LESSON_ID AND DATE_DEL IS NULL;

    SELECT C.CONTROL_ID
    FROM CJ2_CONTROL C
    WHERE C.LESSON_ID = :LESSON_ID AND C.CONTROL_TYPE_ID = 0 AND C.DATE_DEL IS NULL
    INTO :DEFAULT_CONTROL_ID;

    IF(V$STATE <> I$IS_COMPLETED) THEN
    BEGIN
      INSERT INTO CJ2_LESSON_HISTORY
      (LESSON_ID, STATE_ID, USER_ID)
      VALUES (:LESSON_ID, :I$IS_COMPLETED, IIF(:I$USER_ID = 'Веб-администратор', 1, :I$USER_ID));
    END

    IF(I$LESSON_DATE <> V$DATE) THEN
    BEGIN
      INSERT INTO CJ2_LESSON_LOG
      (LESSON_ID, FIELD_ID, VAL, USER_ID)
      VALUES (:LESSON_ID, 'LESSON_DATE', :I$LESSON_DATE, IIF(:I$USER_ID = 'Веб-администратор', 1, :I$USER_ID));
    END
    IF(I$LESSON_NUM <> V$N) THEN
    BEGIN
      INSERT INTO CJ2_LESSON_LOG
      (LESSON_ID, FIELD_ID, VAL, USER_ID)
      VALUES (:LESSON_ID, 'LESSON_NUM', :I$LESSON_NUM, IIF(:I$USER_ID = 'Веб-администратор', 1, :I$USER_ID));
    END
    IF(COALESCE(I$LESSON_THEME, '') <> COALESCE(V$LESSON_THEME, '')) THEN
    BEGIN
      INSERT INTO CJ2_LESSON_LOG
      (LESSON_ID, FIELD_ID, VAL, USER_ID)
      VALUES (:LESSON_ID, 'LESSON_THEME', :I$LESSON_THEME, IIF(:I$USER_ID = 'Веб-администратор', 1, :I$USER_ID));
    END
    IF(COALESCE(I$LESSON_HOMETASK, '') <> COALESCE(V$LESSON_HOMEWORK, '')) THEN
    BEGIN
      INSERT INTO CJ2_LESSON_LOG
      (LESSON_ID, FIELD_ID, VAL, USER_ID)
      VALUES (:LESSON_ID, 'LESSON_HOMEWORK', :I$LESSON_HOMETASK, IIF(:I$USER_ID = 'Веб-администратор', 1, :I$USER_ID));
    END
    IF(COALESCE(I$LESSON_EXTRA, '') <> COALESCE(V$LESSON_EXTRA, '')) THEN
    BEGIN
      INSERT INTO CJ2_LESSON_LOG
      (LESSON_ID, FIELD_ID, VAL, USER_ID)
      VALUES (:LESSON_ID, 'LESSON_EXTRA', SUBSTRING(:I$LESSON_EXTRA FROM 1 FOR 1000), IIF(:I$USER_ID = 'Веб-администратор', 1, :I$USER_ID));
    END

  END

  -- Пересчитываем ссылки на ПЭС
  -- Сначала на пополнение
  V$DE_ID = I$DE_ID;
  WHILE(CHAR_LENGTH(V$DE_ID) > 0) DO
  BEGIN
    P = POSITION(',' IN V$DE_ID);
    IF(P <= 0) THEN P = CHAR_LENGTH(V$DE_ID) + 1;
    V$CONTROL_ID = SUBSTRING(V$DE_ID FROM 1 FOR P - 1);
    V$DE_ID = SUBSTRING(V$DE_ID FROM P + 1);

    V$N = NULL;
    SELECT FIRST 1 C.IS_DEL
    FROM CJ2_LESSON_CEC C
    WHERE C.LESSON_ID = :LESSON_ID AND C.CEC_ID = :V$CONTROL_ID
    INTO :V$N;

    IF(V$N = 1) THEN
      UPDATE CJ2_LESSON_CEC SET IS_DEL = 0, DATE_MODIFY = CURRENT_TIMESTAMP WHERE LESSON_ID = :LESSON_ID AND CEC_ID = :V$CONTROL_ID;
    ELSE IF(V$N IS NULL) THEN
      INSERT INTO CJ2_LESSON_CEC (LESSON_ID, CEC_ID) VALUES (:LESSON_ID, :V$CONTROL_ID);
  END
  -- И на удаление ранее имевшихся, но удаленных
  FOR
    SELECT C.CEC_ID
    FROM CJ2_LESSON_CEC C
    WHERE C.LESSON_ID = :LESSON_ID AND C.IS_DEL = 0
    ORDER BY 1
    INTO :V$CONTROL_ID
  DO
  BEGIN
    V$DE_ID = V$CONTROL_ID;
    IF(I$DE_ID = V$DE_ID) THEN BEGIN END
    ELSE IF(LEFT(I$DE_ID, CHAR_LENGTH(V$DE_ID) + 1) = V$DE_ID || ',') THEN BEGIN END
    ELSE IF(RIGHT(I$DE_ID, CHAR_LENGTH(V$DE_ID) + 1) = ',' || V$DE_ID) THEN BEGIN END
    ELSE IF(POSITION((',' || V$DE_ID || ',') IN I$DE_ID) > 0) THEN BEGIN END
    ELSE UPDATE CJ2_LESSON_CEC SET IS_DEL = 1, DATE_MODIFY = CURRENT_TIMESTAMP WHERE LESSON_ID = :LESSON_ID AND CEC_ID = :V$CONTROL_ID;
  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_LESSON_ATTR_ADD (
    I$LESSON_ID BIGINT NOT NULL,
    I$ATTR_NAME VARCHAR(100) NOT NULL,
    I$ATTR_VALUE VARCHAR(1000),
    I$USER_ID VARCHAR(40))
RETURNS (
    ERROR_TEXT VARCHAR(10))
AS
declare variable V$CJ_ID bigint;
declare variable ACCESS_LEVEL integer;
declare variable N integer;
declare variable V$DATE date;
declare variable V$OBJ_ID bigint;
declare variable V$YEAR integer;
declare variable V$TYPE_ID bigint;
declare variable V$HOURS float;
begin

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_LESSON_ATTR_SET (
    I$LESSON_ID BIGINT NOT NULL,
    I$ATTR_NAME VARCHAR(100) NOT NULL,
    I$ATTR_VALUE VARCHAR(1000),
    I$REF_ID VARCHAR(1000),
    I$LISTVAL_ID VARCHAR(1000))
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$ATTR_ID bigint;
declare variable V$VAL_ID bigint;
declare variable V$DT timestamp;
begin

  -- Удаление всего
  IF(I$ATTR_VALUE IS NULL AND I$REF_ID IS NULL AND I$LISTVAL_ID IS NULL) THEN
  BEGIN
    UPDATE CJ2_LESSON_ATTRS
    SET DATE_DEL = CURRENT_TIMESTAMP
    WHERE LESSON_ID = :I$LESSON_ID AND ATTR_NAME = :I$ATTR_NAME AND DATE_DEL IS NULL;
  END
  -- Сохраняем по названию
  ELSE IF(I$ATTR_VALUE IS NOT NULL) THEN
  BEGIN
    SELECT FIRST 1 A.OBJ_ID, A.DATE_DEL
    FROM CJ2_LESSON_ATTRS A
    WHERE A.LESSON_ID = :I$LESSON_ID AND A.ATTR_NAME = :I$ATTR_NAME
    ORDER BY A.DATE_DEL NULLS FIRST, A.OBJ_ID
    INTO :V$ATTR_ID, :V$DT;

    IF(V$ATTR_ID IS NULL) THEN
    BEGIN
      INSERT INTO CJ2_LESSON_ATTRS
      (LESSON_ID, ATTR_NAME, ATTR_VALUE)
      VALUES (:I$LESSON_ID, :I$ATTR_NAME, :I$ATTR_VALUE)
      RETURNING OBJ_ID INTO :OBJ_ID;
    END
    ELSE
    BEGIN
      UPDATE CJ2_LESSON_ATTRS
      SET ATTR_VALUE = :I$ATTR_VALUE, DATE_DEL = NULL
      WHERE OBJ_ID = :V$ATTR_ID;
    END
  END
  -- Сохраняем по REF_ID
  ELSE IF(I$REF_ID IS NOT NULL) THEN
  BEGIN
    -- Добавляем новые
    FOR
      SELECT V.ID, A.OBJ_ID, A.DATE_DEL
      FROM STR_TO_ID_LIST(:I$REF_ID) V
      LEFT JOIN CJ2_LESSON_ATTRS A ON A.LESSON_ID = :I$LESSON_ID AND A.ATTR_NAME = :I$ATTR_NAME AND A.REF_ID = V.ID
      WHERE A.OBJ_ID IS NULL OR A.DATE_DEL IS NOT NULL
      INTO :V$VAL_ID, :V$ATTR_ID, :V$DT
    DO
    BEGIN
      IF(V$DT IS NOT NULL) THEN
      BEGIN
        UPDATE CJ2_LESSON_ATTRS
        SET DATE_DEL = NULL
        WHERE OBJ_ID = :V$ATTR_ID;
      END
      ELSE BEGIN
        INSERT INTO CJ2_LESSON_ATTRS
        (LESSON_ID, ATTR_NAME, REF_ID)
        VALUES (:I$LESSON_ID, :I$ATTR_NAME, :V$VAL_ID)
        RETURNING OBJ_ID INTO :OBJ_ID;
      END
    END
    -- Удаляем лишние
    FOR
      SELECT A.OBJ_ID
      FROM CJ2_LESSON_ATTRS A
      WHERE A.LESSON_ID = :I$LESSON_ID AND A.ATTR_NAME = :I$ATTR_NAME AND A.DATE_DEL IS NULL AND NOT EXISTS(
        SELECT FIRST 1 1
        FROM STR_TO_ID_LIST(:I$REF_ID) V
        WHERE V.ID = A.REF_ID
      )
      ORDER BY 1
      INTO :V$ATTR_ID
    DO
    BEGIN
      UPDATE CJ2_LESSON_ATTRS
      SET DATE_DEL = CURRENT_TIMESTAMP
      WHERE OBJ_ID = :V$ATTR_ID;
    END
  END
  -- Сохраняем по LISTVAL_ID
  ELSE IF(I$LISTVAL_ID IS NOT NULL) THEN
  BEGIN
    -- Добавляем новые
    FOR
      SELECT V.ID, A.OBJ_ID, A.DATE_DEL
      FROM STR_TO_ID_LIST(:I$LISTVAL_ID) V
      LEFT JOIN CJ2_LESSON_ATTRS A ON A.LESSON_ID = :I$LESSON_ID AND A.ATTR_NAME = :I$ATTR_NAME AND A.LISTVAL_ID = V.ID
      WHERE A.OBJ_ID IS NULL OR A.DATE_DEL IS NOT NULL
      INTO :V$VAL_ID, :V$ATTR_ID, :V$DT
    DO
    BEGIN
      IF(V$DT IS NOT NULL) THEN
      BEGIN
        UPDATE CJ2_LESSON_ATTRS
        SET DATE_DEL = NULL
        WHERE OBJ_ID = :V$ATTR_ID;
      END
      ELSE BEGIN
        INSERT INTO CJ2_LESSON_ATTRS
        (LESSON_ID, ATTR_NAME, LISTVAL_ID)
        VALUES (:I$LESSON_ID, :I$ATTR_NAME, :V$VAL_ID)
        RETURNING OBJ_ID INTO :OBJ_ID;
      END
    END
    -- Удаляем лишние
    FOR
      SELECT A.OBJ_ID
      FROM CJ2_LESSON_ATTRS A
      WHERE A.LESSON_ID = :I$LESSON_ID AND A.ATTR_NAME = :I$ATTR_NAME AND A.DATE_DEL IS NULL AND NOT EXISTS(
        SELECT FIRST 1 1
        FROM STR_TO_ID_LIST(:I$LISTVAL_ID) V
        WHERE V.ID = A.LISTVAL_ID
      )
      ORDER BY 1
      INTO :V$ATTR_ID
    DO
    BEGIN
      UPDATE CJ2_LESSON_ATTRS
      SET DATE_DEL = CURRENT_TIMESTAMP
      WHERE OBJ_ID = :V$ATTR_ID;
    END
  END

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_LESSON_AUTO (
    I$CJ_ID BIGINT,
    I$LESSON_DATE DATE,
    I$USER_ID VARCHAR(40))
RETURNS (
    LESSON_ID BIGINT,
    CONTROL_ID BIGINT,
    ACCESS_LEVEL INTEGER)
AS
declare variable V$YEAR integer;
declare variable V$TEACHER_ID bigint;
declare variable V$DURATION float;
begin

  -- Проверяем права доступа к журналу
  ACCESS_LEVEL = (SELECT ACCESS_LEVEL FROM CJ2_JOURNAL_ACCESS(:I$USER_ID, :I$CJ_ID));
  IF(ACCESS_LEVEL = 0) THEN EXCEPTION DATA_ERROR 'Нет прав доступа к указанному журналу';

  -- Проверяем что дата урока попадает в диапазон дат текущего учебного периода
  SELECT FIRST 1 LV.COST
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$YEAR;

  IF(V$YEAR IS NULL) THEN
  BEGIN
      V$YEAR = EXTRACT(YEAR FROM CURRENT_DATE);
      IF(EXTRACT(MONTH FROM CURRENT_DATE) < 9) THEN V$YEAR = V$YEAR - 1;
  END

  IF(I$LESSON_DATE < '01.09.' || V$YEAR OR I$LESSON_DATE > '31.07.' || (V$YEAR + 1)) THEN EXCEPTION DATA_ERROR 'Недопустимая дата в пределах текущего учебного года';

  SELECT L.DURATION, L.TEACHER_ID
  FROM CJ2_JOURNAL L
  WHERE L.OBJ_ID = :I$CJ_ID
  INTO :V$DURATION, :V$TEACHER_ID;

  -- Если текущий юзер = учитель, ставим учителем в уроке именно его
  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  SELECT FIRST 1 U.OBJ_ID
  FROM USERS U
  WHERE U.USER_ID = :I$USER_ID AND U.OBJ_ID IS NOT NULL
  INTO :V$TEACHER_ID;

  IF(V$DURATION IS NULL OR V$DURATION < 60) THEN V$DURATION = 1; ELSE V$DURATION = V$DURATION / 60;

  INSERT INTO CJ2_JOURNAL_LESSONS
  (CJ_ID, LESSON_DATE, LESSON_NUM, TEACHER_ID, LESSON_THEME, LESSON_HOMEWORK, LESSON_EXTRA,
      IS_COMPLETED, IS_PUBLISHED, LESSON_PTP_ID, LESSON_TYPE_ID, LESSON_HOURS)
  VALUES (:I$CJ_ID, :I$LESSON_DATE, 1, :V$TEACHER_ID, 'Занятие', NULL, NULL,
      1, 0, NULL, NULL, :V$DURATION)
  RETURNING OBJ_ID INTO :LESSON_ID;

  -- Создаем контроль по-умолчанию с тем же статусом
  INSERT INTO CJ2_CONTROL
  (LESSON_ID, CONTROL_TYPE_ID, MARK_SYSTEM_ID, CONTROL_COST, IS_COMPLETED)
  VALUES (:LESSON_ID, 0, 0, 0, 1)
  RETURNING CONTROL_ID INTO :CONTROL_ID;

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_LESSON_CONTROL_ADD (
    I$LESSON_ID BIGINT NOT NULL,
    I$CONTROL_ID BIGINT,
    I$CONTROL_TYPE_ID BIGINT NOT NULL,
    I$MARK_SYSTEM_ID BIGINT NOT NULL,
    I$CONTROL_COST FLOAT NOT NULL,
    I$IS_COMPLETED INTEGER NOT NULL,
    I$TEXT VARCHAR(1000),
    I$EXT_ID VARCHAR(100),
    I$USER_ID VARCHAR(40),
    I$REASON_ID INTEGER,
    I$TEST_ID BIGINT)
RETURNS (
    CONTROL_ID BIGINT,
    CONTROL_TYPE_ID BIGINT,
    MARK_SYSTEM_ID BIGINT,
    CONTROL_COST FLOAT,
    IS_COMPLETED INTEGER)
AS
DECLARE VARIABLE ACCESS_LEVEL INTEGER;
DECLARE VARIABLE IS_SUBST SMALLINT;
DECLARE VARIABLE V$CJ_ID BIGINT;
DECLARE VARIABLE V$COST FLOAT;
DECLARE VARIABLE V$MARK_SYSTEM_ID BIGINT;
DECLARE VARIABLE V$IS_COMPLETED SMALLINT;
DECLARE VARIABLE V$HINT_TEXT VARCHAR(1000);
DECLARE VARIABLE V$EXT_ID VARCHAR(100);
DECLARE VARIABLE V$TEST_ID BIGINT;
DECLARE VARIABLE V$LT BIGINT;
DECLARE VARIABLE V$YEAR_ID BIGINT;
DECLARE VARIABLE V$LV BIGINT;
DECLARE VARIABLE V$JT INTEGER;
begin

  SELECT L.CJ_ID, L.LESSON_TYPE_ID, J.YEAR_ID, J.JOURNAL_TYPE, J.STAGE_INDEX
  FROM CJ2_JOURNAL_LESSONS L
  JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.OBJ_ID = L.CJ_ID
  WHERE L.OBJ_ID = :I$LESSON_ID AND L.DATE_DEL IS NULL
  INTO :V$CJ_ID, :V$LT, :V$YEAR_ID, :V$JT, :V$LV;
  IF(V$CJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Урок или журнал не найдены, возможно другой пользователь удалил данный урок';

  -- Проверяем права доступа к журналу
  SELECT ACCESS_LEVEL, IS_SUBST
  FROM CJ2_JOURNAL_ACCESS(:I$USER_ID, :V$CJ_ID)
  INTO :ACCESS_LEVEL, :IS_SUBST;

  IF(ACCESS_LEVEL = 0) THEN EXCEPTION DATA_ERROR 'Нет прав доступа к указанному журналу';

  IF(I$CONTROL_TYPE_ID = 0) THEN EXCEPTION DATA_ERROR 'Системный контроль создается только автоматически';
  IF(I$CONTROL_COST < 0 OR I$CONTROL_COST > 10) THEN EXCEPTION DATA_ERROR 'Вес контроля допустим в пределах 0...10';

  IF(V$YEAR_ID > 10984 AND I$CONTROL_TYPE_ID IN (28959, 28960) AND I$CONTROL_TYPE_ID IN (1084, 1085, 1087)) THEN
    EXCEPTION DATA_ERROR 'Контрольная работа может задаваться только для соответствующего типа занятия';

  CONTROL_TYPE_ID = I$CONTROL_TYPE_ID;
  MARK_SYSTEM_ID = I$MARK_SYSTEM_ID;
  CONTROL_COST = I$CONTROL_COST;
  IS_COMPLETED = I$IS_COMPLETED;

  -- Удаление теста
  IF(I$TEST_ID < 0) THEN
  BEGIN
    IF(I$CONTROL_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Недопустимая комбинация аргументов';

    -- Пока тест оставим, но возможно стоит удалить если он был создан персонально под контроль

    I$TEST_ID = NULL;
  END

  IF(I$CONTROL_ID IS NULL) THEN
  BEGIN

    -- Запрет типа контроля делаем только при добавлении нового
    -- если проскочил и сохранился, пусть живет
    IF(V$LV IN (37, 38, 39, 40, 12942, 12950)) THEN V$LV = 22;
    ELSE IF(V$LV IN (41, 42, 43, 44, 45, 12951, 12960)) THEN V$LV = 26;
    ELSE IF(V$LV IN (46, 47, 48, 12961)) THEN V$LV = 27;
    ELSE IF(V$LV IN (49, 50, 51, 52, 53, 54)) THEN V$LV = 29;

    IF(V$JT = 0 AND EXISTS(
      SELECT FIRST 1 1
      FROM CJ2_CONTROL_COST C
      WHERE C.DATE_DEL IS NULL AND C.YEAR_ID = :V$YEAR_ID AND (C.LEVEL_ID IS NULL OR C.LEVEL_ID = :V$LV) AND C.COST < 0 AND C.CONTROL_TYPE_ID = :I$CONTROL_TYPE_ID
    ))
    THEN
      EXCEPTION DATA_ERROR 'Использование контроля "' || (SELECT CONTROL_DESC FROM CJ2_CONTROL_TYPE WHERE CONTROL_TYPE_ID = :I$CONTROL_TYPE_ID) ||
        '" запрещено политикой ОУ, обратитесь к завучу';

    INSERT INTO CJ2_CONTROL
    (LESSON_ID, CONTROL_TYPE_ID, CONTROL_COST, MARK_SYSTEM_ID, IS_COMPLETED, HINT_TEXT, EXT_ID, TEST_ID)
    VALUES (:I$LESSON_ID, :I$CONTROL_TYPE_ID, :I$CONTROL_COST, :I$MARK_SYSTEM_ID, :I$IS_COMPLETED, :I$TEXT, :I$EXT_ID, :I$TEST_ID)
    RETURNING CONTROL_ID INTO :CONTROL_ID;

    INSERT INTO CJ2_LESSON_LOG
    (LESSON_ID, FIELD_ID, VAL, USER_ID)
    VALUES (:I$LESSON_ID, 'CONTROL_ADD', :I$CONTROL_TYPE_ID, IIF(:I$USER_ID = 'Веб-администратор', 1, :I$USER_ID));

  END
  ELSE
  BEGIN

    -- Тип контроля не может меняться на лету
    CONTROL_ID = I$CONTROL_ID;

    SELECT C.CONTROL_ID, C.CONTROL_COST, C.MARK_SYSTEM_ID, C.IS_COMPLETED, C.HINT_TEXT, C.EXT_ID, C.TEST_ID
    FROM CJ2_CONTROL C
    WHERE C.DATE_DEL IS NULL AND C.LESSON_ID = :I$LESSON_ID AND C.CONTROL_ID = :I$CONTROL_ID
    INTO :CONTROL_ID, :V$COST, :V$MARK_SYSTEM_ID, :V$IS_COMPLETED, :V$HINT_TEXT, :V$EXT_ID, :V$TEST_ID;

    IF(CONTROL_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Контроль не найден или был удален';

    -- Нельзя менять шкалу, если есть выставленные отметки
    IF(I$MARK_SYSTEM_ID <> V$MARK_SYSTEM_ID) THEN
    BEGIN
      IF(EXISTS(
        SELECT FIRST 1 1
        FROM CJ2_MARK M
        WHERE M.DATE_DEL IS NULL AND M.CONTROL_ID = :I$CONTROL_ID
      ))
      THEN
        EXCEPTION DATA_ERROR 'Нельзя менять шкалу оценивания при наличии выставленных отметок';
    END

      -- Логгируем изменения
      IF(I$CONTROL_COST <> V$COST) THEN
      BEGIN
        INSERT INTO CJ2_LESSON_LOG
        (LESSON_ID, FIELD_ID, ATTR_ID, VAL, USER_ID)
        VALUES (:I$LESSON_ID, 'CONTROL_COST', :I$CONTROL_ID, :I$CONTROL_COST, IIF(:I$USER_ID = 'Веб-администратор', 1, :I$USER_ID));
      END

      IF(I$MARK_SYSTEM_ID <> V$MARK_SYSTEM_ID) THEN
      BEGIN
        INSERT INTO CJ2_LESSON_LOG
        (LESSON_ID, FIELD_ID, ATTR_ID, VAL, USER_ID)
        VALUES (:I$LESSON_ID, 'CONTROL_MARK_SYSTEM', :I$CONTROL_ID, :I$MARK_SYSTEM_ID, IIF(:I$USER_ID = 'Веб-администратор', 1, :I$USER_ID));
      END

      IF(I$IS_COMPLETED <> V$IS_COMPLETED) THEN
      BEGIN
        INSERT INTO CJ2_LESSON_LOG
        (LESSON_ID, FIELD_ID, ATTR_ID, VAL, USER_ID)
        VALUES (:I$LESSON_ID, 'CONTROL_IS_COMPLETED', :I$CONTROL_ID, :I$IS_COMPLETED, IIF(:I$USER_ID = 'Веб-администратор', 1, :I$USER_ID));
      END

      IF(COALESCE(I$TEXT, '') <> COALESCE(V$HINT_TEXT, '')) THEN
      BEGIN
        INSERT INTO CJ2_LESSON_LOG
        (LESSON_ID, FIELD_ID, ATTR_ID, VAL, USER_ID)
        VALUES (:I$LESSON_ID, 'CONTROL_HINT_TEXT', :I$CONTROL_ID, :I$TEXT, IIF(:I$USER_ID = 'Веб-администратор', 1, :I$USER_ID));
      END

      IF(COALESCE(I$EXT_ID, '') <> COALESCE(V$EXT_ID, '')) THEN
      BEGIN
        INSERT INTO CJ2_LESSON_LOG
        (LESSON_ID, FIELD_ID, ATTR_ID, VAL, USER_ID)
        VALUES (:I$LESSON_ID, 'CONTROL_EXT_ID', :I$CONTROL_ID, :I$EXT_ID, IIF(:I$USER_ID = 'Веб-администратор', 1, :I$USER_ID));
      END

      IF(COALESCE(I$TEST_ID, 0) <> COALESCE(V$TEST_ID, 0)) THEN
      BEGIN
        INSERT INTO CJ2_LESSON_LOG
        (LESSON_ID, FIELD_ID, ATTR_ID, VAL, USER_ID)
        VALUES (:I$LESSON_ID, 'TEST_ID', :I$CONTROL_ID, :I$TEST_ID, IIF(:I$USER_ID = 'Веб-администратор', 1, :I$USER_ID));
      END

      IF(I$CONTROL_COST <> V$COST OR I$MARK_SYSTEM_ID <> V$MARK_SYSTEM_ID OR I$IS_COMPLETED <> V$IS_COMPLETED OR COALESCE(I$TEXT, '') <> COALESCE(V$HINT_TEXT, '') OR
          COALESCE(I$EXT_ID, '') <> COALESCE(V$EXT_ID, '') OR COALESCE(I$TEST_ID, 0) <> COALESCE(V$TEST_ID, 0)) THEN
      BEGIN
        UPDATE CJ2_CONTROL
        SET CONTROL_COST = :I$CONTROL_COST, MARK_SYSTEM_ID = :I$MARK_SYSTEM_ID, IS_COMPLETED = :I$IS_COMPLETED, HINT_TEXT = :I$TEXT, EXT_ID = :I$EXT_ID, TEST_ID = :I$TEST_ID
        WHERE CONTROL_ID = :CONTROL_ID AND DATE_DEL IS NULL;
      END

  END

  EXECUTE PROCEDURE CJ2_USA_UPDATE(:CONTROL_ID);

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_LESSON_CONTROL_DELETE (
    I$CONTROL_ID BIGINT,
    I$REASON_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    STUB BIGINT)
AS
DECLARE VARIABLE V$CJ_ID BIGINT;
DECLARE VARIABLE V$FINISHED SMALLINT;
DECLARE VARIABLE V$CONTROL_TYPE_ID BIGINT;
DECLARE VARIABLE V$LESSON_ID BIGINT;
DECLARE VARIABLE ACCESS_LEVEL INTEGER;
DECLARE VARIABLE V$TEST_ID BIGINT;
DECLARE VARIABLE V$TEST_STATE SMALLINT;
begin

  -- Нельзя удалять контроль, если по нему внесены отметки

  SELECT CJL.CJ_ID, CJL.IS_COMPLETED, CJC.CONTROL_TYPE_ID, CJC.LESSON_ID, CJC.TEST_ID, D.EXAM_STATE
  FROM CJ2_CONTROL CJC
  JOIN CJ2_JOURNAL_LESSONS CJL ON CJL.OBJ_ID = CJC.LESSON_ID AND CJL.DATE_DEL IS NULL
  LEFT JOIN UT_EXAM_DATES D ON D.OBJ_ID = CJC.TEST_ID AND D.DATE_DEL IS NULL
  WHERE CJC.CONTROL_ID = :I$CONTROL_ID AND CJC.DATE_DEL IS NULL
  INTO :V$CJ_ID, :V$FINISHED, :V$CONTROL_TYPE_ID, :V$LESSON_ID, :V$TEST_ID, :V$TEST_STATE;

  IF(V$CJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Контроль не найден';
  IF(V$CONTROL_TYPE_ID = 0) THEN EXCEPTION DATA_ERROR 'Нельзя удалять системный контроль';
  IF(V$TEST_STATE >= 600) THEN EXCEPTION DATA_ERROR 'Нельзя удалять контроль, в котором уже запущено тестирование. Сначала необходимо отменить само тестирование';

  -- Проверяем права доступа к журналу
  ACCESS_LEVEL = (SELECT ACCESS_LEVEL FROM CJ2_JOURNAL_ACCESS(:I$USER_ID, :V$CJ_ID));
  IF(ACCESS_LEVEL = 0) THEN EXCEPTION DATA_ERROR 'Нет прав доступа к указанному журналу';

  IF(V$FINISHED <> 0) THEN
  BEGIN
    IF(EXISTS(
      SELECT FIRST 1 1
      FROM CJ2_MARK
      WHERE CONTROL_ID = :I$CONTROL_ID AND DATE_DEL IS NULL
    ))
    THEN
      EXCEPTION DATA_ERROR 'По данному контролю уже выставлены оценки, нельзя удалять';
  END

  -- Удаляем все отметки
  UPDATE CJ2_MARK
  SET DATE_DEL = CURRENT_TIMESTAMP --, REASON_ID = :I$REASON_ID
  WHERE CONTROL_ID = :I$CONTROL_ID AND DATE_DEL IS NULL;

  UPDATE CJ2_CONTROL
  SET DATE_DEL = CURRENT_TIMESTAMP --, REASON_ID = :I$REASON_ID
  WHERE CONTROL_ID = :I$CONTROL_ID AND DATE_DEL IS NULL;

  INSERT INTO CJ2_LESSON_LOG
  (LESSON_ID, FIELD_ID, VAL, USER_ID)
  VALUES (:V$LESSON_ID, 'CONTROL_DEL', :V$CONTROL_TYPE_ID, IIF(:I$USER_ID = 'Веб-администратор', 1, :I$USER_ID));

  EXECUTE PROCEDURE CJ2_USA_UPDATE(:I$CONTROL_ID);

  IF(0 = 1) THEN SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_LESSON_DELETE (
    I$LESSON_ID BIGINT,
    I$REASON_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    CJ_ID BIGINT)
AS
DECLARE VARIABLE V$DATE DATE;
DECLARE VARIABLE V$ACCESS_LEVEL INTEGER;
DECLARE VARIABLE V$NUM INTEGER;
DECLARE VARIABLE V$ID BIGINT;
DECLARE VARIABLE V$REF_ID BIGINT;
DECLARE VARIABLE V$JT INTEGER;
DECLARE VARIABLE V$MS_ID BIGINT;
DECLARE VARIABLE V$SEQ INTEGER;
DECLARE VARIABLE S VARCHAR(1000);
begin

  SELECT FIRST 1 L.CJ_ID, L.LESSON_DATE, L.LESSON_NUM, J.REF_ID, J.JOURNAL_TYPE, L.MS_ID
  FROM CJ2_JOURNAL_LESSONS L
  JOIN CJ2_JOURNAL J ON J.OBJ_ID = L.CJ_ID
  WHERE L.OBJ_ID = :I$LESSON_ID AND L.DATE_DEL IS NULL
  INTO :CJ_ID, :V$DATE, :V$NUM, :V$REF_ID, :V$JT, :V$MS_ID;

  IF(CJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Урок не найден';
  V$ACCESS_LEVEL = (SELECT ACCESS_LEVEL FROM CJ2_JOURNAL_ACCESS(:I$USER_ID, :CJ_ID));
  IF(V$ACCESS_LEVEL IN (0, 5, 6)) THEN EXCEPTION DATA_ERROR 'У вас нет прав доступа к журналу для удаления уроков';

  -- Лимит на удаление отметок временно отключен
  -- IF(V$ACCESS_LEVEL <> 1 AND V$DATE < DATEADD(-7 DAY TO CURRENT_DATE)) THEN EXCEPTION DATA_ERROR 'Только завуч может удалять уроки старше 7 дней';

  -- Есть ли выставленные отметки ? Присутствие не в счет
  IF(EXISTS(
    SELECT FIRST 1 1
    FROM CJ2_CONTROL C
    JOIN CJ2_MARK M ON M.DATE_DEL IS NULL AND M.CONTROL_ID = C.CONTROL_ID AND (M.MARK_TYPE_ID = -1 OR M.MARK_TYPE_ID > 99 )
    WHERE C.DATE_DEL IS NULL AND C.LESSON_ID = :I$LESSON_ID
  )) THEN
    EXCEPTION DATA_ERROR 'По данному уроку уже выставлены отметки или замечания, сначала необходимо все удалить';

  -- Запрет удалять строки для действующего плана
  IF(V$JT = 20 AND EXISTS(
    SELECT FIRST 1 1
    FROM VALL V
    WHERE V.OBJ_ID = :V$REF_ID AND V.PARAM_ID = 3373 AND V.IS_DEL = 0 AND V.LISTVAL_ID = 11715
  ))
  THEN
    EXCEPTION DATA_ERROR 'Нельзя удалять разделы или мероприятия в действующем плане';

  -- Удаляем мероприятия при удалении раздела
  IF(V$NUM < 0) THEN
  BEGIN
    V$NUM = - V$NUM;
    -- Проверяем
    FOR
      SELECT L.OBJ_ID, L.LESSON_THEME
      FROM CJ2_JOURNAL_LESSONS L
      WHERE L.DATE_DEL IS NULL AND L.CJ_ID = :CJ_ID AND L.LESSON_NUM >= 10000 * :V$NUM AND L.LESSON_NUM < 10000 * (:V$NUM + 1)
      ORDER BY 1
      INTO :V$ID, :S
    DO
    BEGIN
      IF(EXISTS(
        SELECT FIRST 1 1
        FROM CJ2_CONTROL C
        JOIN CJ2_MARK M ON M.DATE_DEL IS NULL AND M.CONTROL_ID = C.CONTROL_ID
        WHERE C.DATE_DEL IS NULL AND C.LESSON_ID = :V$ID
      )) THEN
        EXCEPTION DATA_ERROR 'По мероприятию "' || S || '" уже выставлены контроли, сначала необходимо все удалить';
    END
    -- Само удаление
    FOR
      SELECT L.OBJ_ID
      FROM CJ2_JOURNAL_LESSONS L
      WHERE L.DATE_DEL IS NULL AND L.CJ_ID = :CJ_ID AND L.LESSON_NUM >= 10000 * :V$NUM AND L.LESSON_NUM < 10000 * (:V$NUM + 1)
      ORDER BY 1
      INTO :V$ID
    DO
    BEGIN
      UPDATE CJ2_JOURNAL_LESSONS
      SET DATE_DEL = CURRENT_TIMESTAMP
      WHERE OBJ_ID = :V$ID;
    END
    -- Сдвигаем нумерацию на 1 элемент
    FOR
      SELECT L.OBJ_ID
      FROM CJ2_JOURNAL_LESSONS L
      WHERE L.DATE_DEL IS NULL AND L.CJ_ID = :CJ_ID AND L.LESSON_NUM < - :V$NUM
      INTO :V$ID
    DO
    BEGIN
      UPDATE CJ2_JOURNAL_LESSONS
      SET LESSON_NUM = LESSON_NUM + 1
      WHERE OBJ_ID = :V$ID;
    END
    FOR
      SELECT L.OBJ_ID
      FROM CJ2_JOURNAL_LESSONS L
      WHERE L.DATE_DEL IS NULL AND L.CJ_ID = :CJ_ID AND L.LESSON_NUM >= 10000 * (:V$NUM + 1)
      INTO :V$ID
    DO
    BEGIN
      UPDATE CJ2_JOURNAL_LESSONS
      SET LESSON_NUM = LESSON_NUM - 10000
      WHERE OBJ_ID = :V$ID;
    END
  END

  UPDATE CJ2_JOURNAL_LESSONS
  SET DATE_DEL = CURRENT_TIMESTAMP
  WHERE OBJ_ID = :I$LESSON_ID;

  -- Если была связь с виртуальным уроком - нужно сдвинуть нумерацию
  -- освободившийся урок передвинуть в хвост, удаленных дырок в середине быть не должно
  IF(V$MS_ID IS NOT NULL) THEN
  BEGIN
    SELECT L.SEQ_INDEX
    FROM CJ2_MS_LESSONS L
    WHERE L.OBJ_ID = :V$MS_ID
    INTO :V$SEQ;

    UPDATE CJ2_MS_LESSONS
    SET SEQ_INDEX = SEQ_INDEX - 1
    WHERE CJ_ID = :CJ_ID AND SEQ_INDEX > :V$SEQ;

    V$SEQ = NULL;
    SELECT FIRST 1 L.SEQ_INDEX
    FROM CJ2_MS_LESSONS L
    WHERE L.CJ_ID = :CJ_ID AND L.OBJ_ID <> :V$MS_ID
    ORDER BY 1 DESC
    INTO :V$SEQ;

    -- Наш урок - единственный ?
    IF(V$SEQ IS NULL) THEN V$SEQ = 0;

    -- Дата и время в последнем уроке остаются старые
    UPDATE CJ2_MS_LESSONS
    SET DATE_DEL = CURRENT_TIMESTAMP, SEQ_INDEX = :V$SEQ + 1
    WHERE OBJ_ID = :V$MS_ID;
  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_LESSON_FILE_ADD (
    I$LESSON_ID BIGINT,
    I$FILE_ID BIGINT,
    I$NAME VARCHAR(4000),
    I$TYPE SMALLINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    FILE_ID BIGINT)
AS
declare variable V$TYPE smallint;
declare variable ACCESS_LEVEL smallint;
declare variable V$CJ_ID bigint;
begin

  SELECT CJL.CJ_ID, B.OBJ_ID, B.FILE_TYPE
  FROM CJ2_JOURNAL_LESSONS CJL
  LEFT JOIN CJ2_BLOB B ON B.LESSON_ID = CJL.OBJ_ID AND B.OBJ_ID = :I$FILE_ID
  WHERE CJL.OBJ_ID = :I$LESSON_ID
  INTO :V$CJ_ID, :FILE_ID, :V$TYPE;

  IF(I$FILE_ID IS NOT NULL AND FILE_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Файл не найден';

  -- Проверяем права доступа к журналу
  ACCESS_LEVEL = (SELECT ACCESS_LEVEL FROM CJ2_JOURNAL_ACCESS(:I$USER_ID, :V$CJ_ID));
  IF(ACCESS_LEVEL = 0) THEN EXCEPTION DATA_ERROR 'Нет прав доступа к указанному журналу';

  IF(FILE_ID IS NULL) THEN
  BEGIN
      INSERT INTO CJ2_BLOB
      (LESSON_ID, FILE_NAME, FILE_TYPE)
      VALUES (:I$LESSON_ID, :I$NAME, :I$TYPE)
      RETURNING OBJ_ID INTO :FILE_ID;

      INSERT INTO CJ2_LESSON_LOG
      (LESSON_ID, FIELD_ID, VAL, USER_ID)
      VALUES (:I$LESSON_ID, 'FILE_ADD', SUBSTRING(:I$NAME FROM 1 FOR 1000), IIF(:I$USER_ID = 'Веб-администратор', 1, :I$USER_ID));
  END
  ELSE IF(V$TYPE <> I$TYPE) THEN
  BEGIN
      UPDATE CJ2_BLOB
      SET FILE_TYPE = :I$TYPE
      WHERE OBJ_ID = :FILE_ID;
  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_LESSON_FILE_DELETE (
    I$LESSON_ID BIGINT,
    I$FILE_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    FILE_ID BIGINT)
AS
declare variable V$CJ_ID bigint;
declare variable V$NAME varchar(1000);
declare variable ACCESS_LEVEL smallint;
begin

  SELECT CJL.CJ_ID, B.OBJ_ID, B.FILE_NAME
  FROM CJ2_BLOB B
  JOIN CJ2_JOURNAL_LESSONS CJL ON CJL.OBJ_ID = B.LESSON_ID
  WHERE B.LESSON_ID = :I$LESSON_ID AND B.OBJ_ID = :I$FILE_ID AND B.DATE_DEL IS NULL
  INTO :V$CJ_ID, :FILE_ID, :V$NAME;

  IF(FILE_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Файл не найден или был удален другим пользователем';

  -- Проверяем права доступа к журналу
  ACCESS_LEVEL = (SELECT ACCESS_LEVEL FROM CJ2_JOURNAL_ACCESS(:I$USER_ID, :V$CJ_ID));
  IF(ACCESS_LEVEL = 0) THEN EXCEPTION DATA_ERROR 'Нет прав доступа к указанному журналу';

  UPDATE CJ2_BLOB SET DATE_DEL = CURRENT_TIMESTAMP WHERE OBJ_ID = :FILE_ID;

  INSERT INTO CJ2_LESSON_LOG
  (LESSON_ID, FIELD_ID, VAL, USER_ID)
  VALUES (:I$LESSON_ID, 'FILE_DEL', SUBSTRING(:V$NAME FROM 1 FOR 1000), IIF(:I$USER_ID = 'Веб-администратор', 1, :I$USER_ID));

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_LESSON_FINAL_ADD (
    I$CJ_ID BIGINT,
    I$LESSON_ID BIGINT,
    I$LESSON_DATE DATE,
    I$TYPE_ID BIGINT,
    I$MARKSYSTEM_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    LESSON_ID BIGINT)
AS
declare variable ACCESS_LEVEL integer;
declare variable V$YEAR integer;
declare variable V$DATE date;
declare variable V$SUBJECT_ID bigint;
declare variable V$PREV_YEAR_ID bigint;
declare variable V$PREV_MARKTYPE_ID bigint;
declare variable Y integer;
declare variable DT date;
declare variable YEAR_VAL varchar(40);
declare variable V$GLOBAL_DISABLE bigint;
begin

  IF(I$TYPE_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Тип итоговой отметки не указан';
  IF(I$TYPE_ID = 3001) THEN EXCEPTION DATA_ERROR 'Нельзя выбирать в качестве отметки раздел "за период" - должен быть указан конкретный период в разделе';
  IF(I$MARKSYSTEM_ID IS NULL) THEN I$MARKSYSTEM_ID = 400;

  -- Проверяем права доступа к журналу
  ACCESS_LEVEL = (SELECT ACCESS_LEVEL FROM CJ2_JOURNAL_ACCESS(:I$USER_ID, :I$CJ_ID));
  IF(ACCESS_LEVEL = 0) THEN EXCEPTION DATA_ERROR 'Нет прав доступа к указанному журналу';
  IF(ACCESS_LEVEL IN (5, 6)) THEN EXCEPTION DATA_ERROR 'Вы не можете изменять столбцы итоговых отметок';

  -- Проверяем что дата урока попадает в диапазон дат текущего учебного периода
  SELECT FIRST 1 LV.COST, COALESCE(V3324.LISTVAL_ID, 3)
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  LEFT JOIN VALL V3324 ON V3324.OBJ_ID = L2.OBJ_ID AND V3324.PARAM_ID = 3324 AND V3324.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$YEAR, :V$GLOBAL_DISABLE;

  IF(V$GLOBAL_DISABLE = 2) THEN EXCEPTION DATA_ERROR 'Внесение изменений в классный журнал запрещено руководителем организации';

  IF(V$YEAR IS NULL) THEN
  BEGIN
      V$YEAR = EXTRACT(YEAR FROM CURRENT_DATE);
      IF(EXTRACT(MONTH FROM CURRENT_DATE) < 9) THEN V$YEAR = V$YEAR - 1;
  END

  IF(I$LESSON_DATE < '01.09.' || V$YEAR OR I$LESSON_DATE > '20.07.' || (V$YEAR + 1)) THEN EXCEPTION DATA_ERROR 'Недопустимая дата в пределах текущего учебного года';

  -- Проверяем, что итога с таким типом еще нет
  IF(EXISTS(
      SELECT FIRST 1 1
      FROM CJ2_JOURNAL_FINALS F
      WHERE F.CJ_ID = :I$CJ_ID AND F.DATE_DEL IS NULL AND F.FINAL_TYPE = :I$TYPE_ID AND (:I$LESSON_ID IS NULL OR F.OBJ_ID <> :I$LESSON_ID)
  )) THEN EXCEPTION DATA_ERROR 'Графа итоговой отметки с таким типом уже есть';

  IF(I$LESSON_ID IS NULL) THEN
  BEGIN
      INSERT INTO CJ2_JOURNAL_FINALS
      (CJ_ID, FINAL_TYPE, FINAL_DATE, TEACHER_ID, MARK_SYSTEM_ID)
      VALUES (:I$CJ_ID, :I$TYPE_ID, :I$LESSON_DATE, NULL, :I$MARKSYSTEM_ID)
      RETURNING OBJ_ID INTO :LESSON_ID;
  END
  ELSE
  BEGIN

      SELECT F.OBJ_ID, F.FINAL_DATE, CJM.SUBJECT_ID, LV.LISTVAL_ID
      FROM CJ2_JOURNAL_FINALS F
      JOIN CJ2_JOURNAL CJM ON CJM.OBJ_ID = F.CJ_ID
      JOIN LISTVALS LV ON LV.LISTVAL_ID = F.FINAL_TYPE AND LV.LIST_ID = 220
      WHERE F.CJ_ID = :I$CJ_ID AND F.OBJ_ID = :I$LESSON_ID AND F.DATE_DEL IS NULL
      INTO :LESSON_ID, :V$DATE, :V$SUBJECT_ID, :V$PREV_MARKTYPE_ID;

      IF(LESSON_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Графа для итоговой отметки не найдена';

      IF(V$DATE <> I$LESSON_DATE) THEN
      BEGIN
          UPDATE CJ2_JOURNAL_FINALS
          SET FINAL_DATE = :I$LESSON_DATE
          WHERE OBJ_ID = :I$LESSON_ID;

          Y = EXTRACT(YEAR FROM V$DATE);
          DT = '31.08.' || Y;
    
          IF (V$DATE < DT) THEN YEAR_VAL = (Y - 1) || '-' || Y; ELSE YEAR_VAL = Y || '-' ||(Y + 1);

          SELECT FIRST 1 LV.LISTVAL_ID
          FROM LISTVALS LV
          JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
          WHERE LV.LIST_ID = 29 AND R.VAL LIKE :YEAR_VAL INTO :V$PREV_YEAR_ID;

          UPDATE VALM
          SET IS_DEL = 1
          WHERE SUBJECT_ID = :V$SUBJECT_ID AND YEAR_ID = :V$PREV_YEAR_ID AND MARKTYPE_ID = :V$PREV_MARKTYPE_ID
              AND PUPIL_ID IN (
                  SELECT L10.OBJ_ID
                  FROM CJ2_JOURNAL CJ
                  JOIN LINKS L10 ON L10.PARENT_ID = CJ.GRADE_ID AND L10.OBJ_TYPE_ID = 10 AND (L10.DATE_DEL IS NULL OR L10.DATE_DEL >= :I$LESSON_DATE)
                  WHERE CJ.OBJ_ID = :I$CJ_ID
              );

          EXECUTE PROCEDURE FINALMARK_SYNCHRONIZE(:LESSON_ID);
      END

  END

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_LESSON_FINAL_DELETE (
    I$LESSON_ID BIGINT,
    I$REASON_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    CJ_ID BIGINT)
AS
DECLARE VARIABLE V$DATE DATE;
DECLARE VARIABLE V$ACCESS_LEVEL INTEGER;
begin

  SELECT FIRST 1 L.CJ_ID, L.FINAL_DATE
  FROM CJ2_JOURNAL_FINALS L
  WHERE L.OBJ_ID = :I$LESSON_ID AND L.DATE_DEL IS NULL
  INTO :CJ_ID, :V$DATE;

  IF(CJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Запись итоговой отметки не найдена';
  V$ACCESS_LEVEL = (SELECT ACCESS_LEVEL FROM CJ2_JOURNAL_ACCESS(:I$USER_ID, :CJ_ID));
  IF(V$ACCESS_LEVEL IN (0, 5, 6)) THEN EXCEPTION DATA_ERROR 'У вас нет прав доступа к журналу для удаления итоговых отметок';

  -- Лимит на удаление отметок временно отключен
  -- IF(V$ACCESS_LEVEL <> 1 AND V$DATE < DATEADD(-7 DAY TO CURRENT_DATE)) THEN EXCEPTION DATA_ERROR 'Только завуч может удалять уроки старше 7 дней';

  -- Есть ли выставленные отметки ? Присутствие не в счет
  IF(EXISTS(
      SELECT FIRST 1 1
      FROM CJ2_MARK M
      WHERE M.DATE_DEL IS NULL AND M.FINAL_ID = :I$LESSON_ID
  )) THEN EXCEPTION DATA_ERROR 'По данной итоговой графе уже выставлены отметки, сначала необходимо все удалить';

  UPDATE CJ2_JOURNAL_FINALS
  SET DATE_DEL = CURRENT_TIMESTAMP
  WHERE OBJ_ID = :I$LESSON_ID;

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_LESSON_FINAL_GET (
    I$CJ_ID BIGINT,
    I$LESSON_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(4000))
AS
declare variable ACCESS_LEVEL integer;
declare variable V$LESSON_ID bigint;
declare variable V$LESSON_DATE date;
declare variable V$FINAL_TYPE_ID bigint;
declare variable V$ID bigint;
declare variable V$AID bigint;
declare variable V$PARENT_ID bigint;
declare variable V$COPP bigint;
declare variable V$SUBJECT_ID bigint;
declare variable V$PLAN_ID bigint;
declare variable V$MARK_SYSTEM_ID bigint;
declare variable V$JOURNAL_TYPE integer;
declare variable V$PERIOD_ID bigint;
declare variable V$MAX_FINAL bigint;
declare variable V$Y integer;
declare variable V$FT bigint;
declare variable S varchar(1000);
begin

  -- Проверяем права доступа к журналу
  ACCESS_LEVEL = (SELECT ACCESS_LEVEL FROM CJ2_JOURNAL_ACCESS(:I$USER_ID, :I$CJ_ID));
  IF(ACCESS_LEVEL = 0) THEN EXCEPTION DATA_ERROR 'Нет доступа к указанному журналу';

  SELECT F.OBJ_ID, F.FINAL_DATE, F.FINAL_TYPE, F.MARK_SYSTEM_ID
  FROM CJ2_JOURNAL_FINALS F
  WHERE F.CJ_ID = :I$CJ_ID AND F.OBJ_ID = :I$LESSON_ID AND F.DATE_DEL IS NULL
  INTO :V$LESSON_ID, :V$LESSON_DATE, :V$FINAL_TYPE_ID, :V$MARK_SYSTEM_ID;

  IF(V$LESSON_ID IS NULL AND I$LESSON_ID IS NOT NULL) THEN EXCEPTION DATA_ERROR 'Урок не найден, возможно он был удален. Обновите страницу';

  -- Детектируем дату новой итоговой отметки
  IF(V$LESSON_DATE IS NULL) THEN
  BEGIN

    SELECT J.PERIOD_ID, LV.COST
    FROM CJ2_JOURNAL J
    JOIN LISTVALS LV ON LV.LISTVAL_ID = J.YEAR_ID
    WHERE J.OBJ_ID = :I$CJ_ID
    INTO :V$PERIOD_ID, :V$Y;

    SELECT MAX(F.FINAL_TYPE)
    FROM CJ2_JOURNAL_FINALS F
    WHERE F.CJ_ID = :I$CJ_ID
    INTO :V$MAX_FINAL;

    IF(V$MAX_FINAL IS NULL) THEN V$FT = NULL;
    ELSE IF(V$MAX_FINAL = 3002) THEN V$FT = 12;
    ELSE IF(V$MAX_FINAL = 3003) THEN V$FT = 13;
    ELSE IF(V$MAX_FINAL = 3004) THEN V$FT = 14;
    ELSE IF(V$MAX_FINAL = 3005) THEN V$FT = 15;
    ELSE IF(V$MAX_FINAL = 3006) THEN V$FT = 16;
    ELSE IF(V$MAX_FINAL = 3007) THEN V$FT = 17;
    ELSE IF(V$MAX_FINAL = 3008) THEN V$FT = 18;
    ELSE IF(V$MAX_FINAL = 3009) THEN V$FT = 10;
    ELSE IF(V$MAX_FINAL = 3010) THEN V$FT = 11;
    ELSE IF(V$MAX_FINAL = 12973) THEN V$FT = 19;
    ELSE IF(V$MAX_FINAL = 12974) THEN V$FT = 20;
    ELSE V$FT = 999999;

    SELECT FIRST 1 V1174.VAL
    FROM LINKS L154
    JOIN VALL V1170 ON V1170.OBJ_ID = L154.OBJ_ID AND V1170.PARAM_ID = 1170 AND V1170.IS_DEL = 0 AND (V1170.LISTVAL_ID > :V$FT OR :V$FT IS NULL)
    JOIN VALD V1174 ON V1174.OBJ_ID = L154.OBJ_ID AND V1174.PARAM_ID = 1174 AND V1174.IS_DEL = 0
    WHERE L154.PARENT_ID = :V$PERIOD_ID AND L154.OBJ_TYPE_ID = 154 AND L154.DATE_DEL IS NULL
    ORDER BY 1
    INTO :V$LESSON_DATE;

    -- Все оценки кончились, ставим годовую или итоговую последним днем года
    -- для класса со сдачей ГИА ставим итоговую 1 июля, а дальше пусть школа сама разбирается
    IF(V$LESSON_DATE IS NULL) THEN
    BEGIN
      IF(V$MAX_FINAL < 13018) THEN
      BEGIN
        SELECT FIRST 1 V1174.VAL
        FROM LINKS L154
        JOIN VALL V1170 ON V1170.OBJ_ID = L154.OBJ_ID AND V1170.PARAM_ID = 1170 AND V1170.IS_DEL = 0 AND (V1170.LISTVAL_ID > :V$FT OR :V$FT IS NULL)
        JOIN VALD V1174 ON V1174.OBJ_ID = L154.OBJ_ID AND V1174.PARAM_ID = 1174 AND V1174.IS_DEL = 0
        WHERE L154.PARENT_ID = :V$PERIOD_ID AND L154.OBJ_TYPE_ID = 154 AND L154.DATE_DEL IS NULL
        ORDER BY 1 DESC
        INTO :V$LESSON_DATE;
      END
      ELSE
      BEGIN
        V$LESSON_DATE = '01.07.' || (V$Y + 1);
      END
    END

  END

  -- Проверяем, ЦОПП или обычный
  SELECT FIRST 1 COALESCE(V3064.LISTVAL_ID, 3), J.SUBJECT_ID, J.REF_ID, J.JOURNAL_TYPE
  FROM CJ2_JOURNAL J
  LEFT JOIN VALL V3064 ON V3064.OBJ_ID = J.GRADE_ID AND V3064.PARAM_ID = 3064 AND V3064.IS_DEL = 0
  WHERE J.OBJ_ID = :I$CJ_ID
  INTO :V$COPP, :V$SUBJECT_ID, :V$PLAN_ID, :V$JOURNAL_TYPE;

  TAG_NAME = 'id';
  VAL = V$LESSON_ID;
  SUSPEND;
  TAG_NAME = 'date';
  VAL = (SELECT VAL FROM DATE2ISO(:V$LESSON_DATE, 0));
  SUSPEND;
  TAG_NAME = 'type_id';
  VAL = V$FINAL_TYPE_ID;
  SUSPEND;
  TAG_NAME = 'system_id';
  -- в ДПО у нас зачет
  IF(V$MARK_SYSTEM_ID IS NULL AND V$JOURNAL_TYPE = 3) THEN V$MARK_SYSTEM_ID = 100;
  IF(V$MARK_SYSTEM_ID IS NULL) THEN V$MARK_SYSTEM_ID = 400;
  VAL = V$MARK_SYSTEM_ID;
  SUSPEND;

  -- Список выбора
  -- Промежуточные периоды фильтруем исходя из реально настроенных, и обязательно добавляем тот что уже выбран
  TAG_NAME = 'types::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
      SELECT FT.LISTVAL_ID, FT.PARENT_ID, FT.VAL
      FROM LISTVALS_LIST(220) FT
      LEFT JOIN CJ2_JOURNAL_FINALS F ON F.CJ_ID = :I$CJ_ID AND F.FINAL_TYPE = FT.LISTVAL_ID AND F.DATE_DEL IS NULL
      WHERE FT.IS_DEL = 0 AND (F.OBJ_ID IS NULL OR FT.LISTVAL_ID = :V$FINAL_TYPE_ID)
      ORDER BY 2 NULLS FIRST, 1
      INTO :V$ID, :V$PARENT_ID, :S
  DO
  BEGIN
      -- Перекодируем справочники итоговых журналов в используемые в периодах
      IF(V$ID = 3002) THEN V$AID = 12;
      ELSE IF(V$ID = 3003) THEN V$AID = 13;
      ELSE IF(V$ID = 3004) THEN V$AID = 14;
      ELSE IF(V$ID = 3005) THEN V$AID = 15;
      ELSE IF(V$ID = 3006) THEN V$AID = 16;
      ELSE IF(V$ID = 3007) THEN V$AID = 17;
      ELSE IF(V$ID = 3008) THEN V$AID = 18;
      ELSE IF(V$ID = 3009) THEN V$AID = 10;
      ELSE IF(V$ID = 3010) THEN V$AID = 11;
      ELSE IF(V$ID = 12973) THEN V$AID = 19;
      ELSE IF(V$ID = 12974) THEN V$AID = 20;
      ELSE IF(V$ID >= 12998 AND V$ID <= 13017) THEN V$AID = - (V$ID - 12998); -- ЦОПП модули
      ELSE V$AID = NULL;

      -- Выдаем итоговые отметки, либо отметки тех периодов, которые вообще настроены в ОУ
      IF((V$ID = 3001 AND V$JOURNAL_TYPE <> 3) OR V$ID = V$FINAL_TYPE_ID OR
          ((V$ID IN (3011, 3012, 5544, 3013) OR V$ID > 1000000000) AND V$COPP = 3 AND V$JOURNAL_TYPE <> 3) OR -- годовая, экзамены и итоговая всегда есть только в общеобре
          (V$ID = 3013 AND V$COPP = 3 AND V$JOURNAL_TYPE = 3) OR -- в ДПО есть только итоговая
          (V$COPP = 3 AND EXISTS( -- за период - из числа настроенных периодов
              SELECT FIRST 1 1
              FROM LINKS L2
              JOIN LINKS L150 ON L150.PARENT_ID = L2.OBJ_ID AND L150.OBJ_TYPE_ID IN (150, 481) AND L150.DATE_DEL IS NULL
              JOIN LINKS L151 ON L151.PARENT_ID = L150.OBJ_ID AND L151.OBJ_TYPE_ID = 151 AND L151.DATE_DEL IS NULL
              JOIN LINKS L154 ON L154.PARENT_ID = L151.OBJ_ID AND L154.OBJ_TYPE_ID = 154 AND L154.DATE_DEL IS NULL
              JOIN VALL V1170 ON V1170.OBJ_ID = L154.OBJ_ID AND V1170.PARAM_ID = 1170 AND V1170.IS_DEL = 0 AND V1170.LISTVAL_ID = :V$AID
              WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL)) OR
          (V$COPP = 2 AND V$ID = 3013 AND EXISTS( -- в ЦОПП итоговые можно ставить только в корневом разделе
              SELECT FIRST 1 1
              FROM PLAN_SUBJECTS S
              JOIN PLAN_SUBJECTS SP ON SP.OBJ_ID = S.PARENT_ID AND SP.FIELD_ID = 12975
              WHERE S.DATE_DEL IS NULL AND S.PLAN_ID = :V$PLAN_ID AND S.SUBJECT_ID = :V$SUBJECT_ID
          )) OR
          /*(V$COPP = 2 AND EXISTS( -- за модуль - в конкретном модуле, пока убрали
              SELECT FIRST 1 1
              FROM PLAN_SUBJECTS S
              JOIN PLAN_SUBJECTS SP ON SP.OBJ_ID = S.PARENT_ID AND SP.FIELD_ID = - :V$AID + 12978
              WHERE S.DATE_DEL IS NULL AND S.PLAN_ID = :V$PLAN_ID AND S.SUBJECT_ID = :V$SUBJECT_ID
          )) OR */
          (V$COPP = 2 AND V$ID IN (3012, 5544, 13018, 13019) AND EXISTS( -- тест, рефлексия, экзамены - в конкретном модуле
              SELECT FIRST 1 1
              FROM PLAN_SUBJECTS S
              JOIN PLAN_SUBJECTS SP ON SP.OBJ_ID = S.PARENT_ID AND SP.FIELD_ID >= 12978 AND SP.FIELD_ID <= 12997
              WHERE S.DATE_DEL IS NULL AND S.PLAN_ID = :V$PLAN_ID AND S.SUBJECT_ID = :V$SUBJECT_ID
          ))
      ) THEN
      BEGIN
          TAG_NAME = 'types:r';
          VAL = NULL;
          SUSPEND;
          TAG_NAME = 'types:r:id';
          VAL = V$ID;
          SUSPEND;
          TAG_NAME = 'types:r:parent_id';
          VAL = V$PARENT_ID;
          SUSPEND;
          TAG_NAME = 'types:r:name';
          VAL = S;
          SUSPEND;
      END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_LESSON_GET (
    I$CJ_ID BIGINT,
    I$LESSON_ID BIGINT,
    I$USER_ID VARCHAR(40),
    I$PTP_LESSON_ID BIGINT = NULL)
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(4000))
AS
DECLARE VARIABLE ACCESS_LEVEL SMALLINT;
DECLARE VARIABLE V$LESSON_ID BIGINT;
DECLARE VARIABLE V$TEACHER_ID BIGINT;
DECLARE VARIABLE V$LESSON_DATE DATE;
DECLARE VARIABLE V$LESSON_NUMBER SMALLINT;
DECLARE VARIABLE V$LESSON_HOURS FLOAT;
DECLARE VARIABLE V$LESSON_THEME VARCHAR(1000);
DECLARE VARIABLE V$LESSON_HOMEWORK VARCHAR(1000);
DECLARE VARIABLE V$LESSON_EXTRA VARCHAR(2000);
DECLARE VARIABLE V$COMPLETED SMALLINT;
DECLARE VARIABLE V$PTP_ID BIGINT;
DECLARE VARIABLE V$CONTROL_ID BIGINT;
DECLARE VARIABLE V$CONTROL_TYPE_ID BIGINT;
DECLARE VARIABLE V$TYPE SMALLINT;
DECLARE VARIABLE V$COST FLOAT;
DECLARE VARIABLE V$MARK_SYSTEM_ID BIGINT;
DECLARE VARIABLE V$JOURNAL_TYPE INTEGER;
DECLARE VARIABLE V$TYPE_ID BIGINT;
DECLARE VARIABLE V$LIST_ID BIGINT;
DECLARE VARIABLE V$EXT_ID VARCHAR(100);
DECLARE VARIABLE V$CURRENT_DATE DATE;
DECLARE VARIABLE V$CURRENT_NUM INTEGER;
DECLARE VARIABLE V$ROOM_ID BIGINT;
DECLARE VARIABLE V$INST VARCHAR(400);
DECLARE VARIABLE V$STATUS VARCHAR(1);
DECLARE VARIABLE V$STMASK BIGINT;
DECLARE VARIABLE V$DE_ID VARCHAR(400);
DECLARE VARIABLE V$ONLINE SMALLINT;
DECLARE VARIABLE V$LINK VARCHAR(400);
DECLARE VARIABLE V$INST_STATUS SMALLINT;
DECLARE VARIABLE V$JT INTEGER;
DECLARE VARIABLE P INTEGER;
DECLARE VARIABLE V$TEST_ID BIGINT;
DECLARE VARIABLE V$OU_ID BIGINT;
DECLARE VARIABLE V$HAS_DO SMALLINT;
DECLARE VARIABLE V$HAS_OO SMALLINT;
DECLARE VARIABLE V$HAS_SPO SMALLINT;
DECLARE VARIABLE V$HAS_PO SMALLINT;
DECLARE VARIABLE V$YEAR_ID BIGINT;
DECLARE VARIABLE V$LV BIGINT;
DECLARE VARIABLE D DATE;
DECLARE VARIABLE D2 DATE;
begin

  -- Проверяем права доступа к журналу
  ACCESS_LEVEL = (SELECT ACCESS_LEVEL FROM CJ2_JOURNAL_ACCESS(:I$USER_ID, :I$CJ_ID));
  IF(ACCESS_LEVEL = 0) THEN EXCEPTION DATA_ERROR 'Нет доступа к указанному журналу';

  V$STATUS = (SELECT STATUS FROM OU_LICENCE_TYPE);

  SELECT J.STAGE_INDEX, C.OBJ_ID, C.TEACHER_ID, C.LESSON_DATE, C.LESSON_NUM, C.LESSON_HOURS, C.LESSON_THEME, C.LESSON_HOMEWORK, C.LESSON_EXTRA, C.IS_COMPLETED * 2 + C.IS_PUBLISHED * 1,
    C.LESSON_PTP_ID, C.LESSON_TYPE_ID, C.INST_ID, C.DE_ID, C.IS_ONLINE, C.INST_LINK, C.INST_STATUS, J.JOURNAL_TYPE, J.YEAR_ID
  FROM CJ2_JOURNAL_LESSONS C
  JOIN CJ2_JOURNAL J ON J.OBJ_ID = C.CJ_ID AND J.DATE_DEL IS NULL
  WHERE C.CJ_ID = :I$CJ_ID AND C.OBJ_ID = :I$LESSON_ID AND C.DATE_DEL IS NULL
  INTO :V$STMASK, :V$LESSON_ID, :V$TEACHER_ID, :V$LESSON_DATE, :V$LESSON_NUMBER, :V$LESSON_HOURS, :V$LESSON_THEME, :V$LESSON_HOMEWORK, :V$LESSON_EXTRA, :V$COMPLETED,
    :V$PTP_ID, :V$TYPE_ID, :V$INST, :V$DE_ID, :V$ONLINE, :V$LINK, :V$INST_STATUS, :V$JT, :V$YEAR_ID;

  IF(V$LESSON_ID IS NULL AND I$LESSON_ID IS NOT NULL) THEN EXCEPTION DATA_ERROR 'Урок не найден, возможно он был удален. Обновите страницу';

  -- Подменяем id на полученный на входе, чтобы достать сведения об уроке
  IF(I$LESSON_ID IS NULL) THEN V$PTP_ID = I$PTP_LESSON_ID;

  SELECT FIRST 1 L2.OBJ_ID
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$OU_ID;

  V$HAS_DO = 0;
  V$HAS_OO = 0;
  V$HAS_SPO = 0;
  V$HAS_PO = 0;
  SELECT FIRST 1 1
  FROM LINKS L472
  JOIN VALL V3327 ON V3327.OBJ_ID = L472.OBJ_ID AND V3327.PARAM_ID = 3327 AND V3327.IS_DEL = 0 AND V3327.LISTVAL_ID IN (21, 3263, 3264)
  WHERE L472.PARENT_ID = :V$OU_ID AND L472.OBJ_TYPE_ID = 472 AND L472.DATE_DEL IS NULL
  INTO :V$HAS_DO;

  SELECT FIRST 1 1
  FROM LINKS L472
  JOIN VALL V3327 ON V3327.OBJ_ID = L472.OBJ_ID AND V3327.PARAM_ID = 3327 AND V3327.IS_DEL = 0 AND V3327.LISTVAL_ID IN (22, 26, 27)
  WHERE L472.PARENT_ID = :V$OU_ID AND L472.OBJ_TYPE_ID = 472 AND L472.DATE_DEL IS NULL
  INTO :V$HAS_OO;

  SELECT FIRST 1 1
  FROM LINKS L472
  JOIN VALL V3327 ON V3327.OBJ_ID = L472.OBJ_ID AND V3327.PARAM_ID = 3327 AND V3327.IS_DEL = 0 AND V3327.LISTVAL_ID IN (28, 29, 13129)
  WHERE L472.PARENT_ID = :V$OU_ID AND L472.OBJ_TYPE_ID = 472 AND L472.DATE_DEL IS NULL
  INTO :V$HAS_SPO;

  SELECT FIRST 1 1
  FROM LINKS L472
  JOIN VALL V3327 ON V3327.OBJ_ID = L472.OBJ_ID AND V3327.PARAM_ID = 3327 AND V3327.IS_DEL = 0 AND V3327.LISTVAL_ID IN (13129, 13131)
  WHERE L472.PARENT_ID = :V$OU_ID AND L472.OBJ_TYPE_ID = 472 AND L472.DATE_DEL IS NULL
  INTO :V$HAS_PO;

  IF(I$LESSON_ID IS NULL AND V$TEACHER_ID IS NULL) THEN
  BEGIN
    SELECT FIRST 1 TEACHER_ID FROM (
      SELECT J.TEACHER_ID
      FROM CJ2_JOURNAL J
      WHERE J.OBJ_ID = :I$CJ_ID AND J.TEACHER_ID IS NOT NULL
      UNION
      SELECT FIRST 1 V1609.VAL
      FROM CJ2_JOURNAL J
      JOIN LINKS L186 ON L186.PARENT_ID = J.GRADE_ID AND L186.OBJ_TYPE_ID = 186 AND L186.DATE_DEL IS NULL
      JOIN VALR V1609 ON V1609.OBJ_ID = L186.OBJ_ID AND V1609.PARAM_ID = 1609 AND V1609.IS_DEL = 0
      WHERE J.OBJ_ID = :I$CJ_ID
    )
    INTO :V$TEACHER_ID;
  END

  IF(I$LESSON_ID IS NULL) THEN
  BEGIN
    SELECT FIRST 1 J.STAGE_INDEX, J.JOURNAL_TYPE
    FROM CJ2_JOURNAL J
    WHERE J.OBJ_ID = :I$CJ_ID AND J.DATE_DEL IS NULL
    INTO :V$STMASK, :V$JT;
  END

  -- Битовая маска для отбора УУД
  IF(V$STMASK IN (37, 38, 39, 40)) THEN V$STMASK = 1;
  ELSE IF(V$STMASK IN (41, 42, 43, 44, 45)) THEN V$STMASK = 2;
  ELSE IF(V$STMASK IN (46, 47, 48)) THEN V$STMASK = 4;
  ELSE V$STMASK = 0;

  -- Заполняем дату и номер урока по расписанию
  IF(I$LESSON_ID IS NULL) THEN
  BEGIN

    -- Идем начиная с последнего урока до текущей даты
    SELECT FIRST 1 L.LESSON_DATE, L.LESSON_NUM
    FROM CJ2_JOURNAL_LESSONS L
    WHERE L.DATE_DEL IS NULL AND L.CJ_ID = :I$CJ_ID AND L.LESSON_DATE <= CURRENT_DATE
    ORDER BY L.LESSON_DATE DESC, L.LESSON_NUM DESC
    INTO :V$CURRENT_DATE, :V$CURRENT_NUM;

    IF(V$CURRENT_DATE IS NULL) THEN
    BEGIN
      V$CURRENT_DATE = '01.09.' || EXTRACT(YEAR FROM CURRENT_DATE);
      IF(EXTRACT(MONTH FROM CURRENT_DATE) < 9) THEN V$CURRENT_DATE = DATEADD(-1 YEAR TO V$CURRENT_DATE);
      V$CURRENT_NUM = 0;
    END

    SELECT FIRST 1 S.LESSON_DATE, S.LESSON_NUM
    FROM CJ2_SCHEDULE_STREAM(:I$CJ_ID, :V$CURRENT_DATE) S
    LEFT JOIN CJ2_JOURNAL_LESSONS L ON L.CJ_ID = :I$CJ_ID AND L.DATE_DEL IS NULL AND L.LESSON_DATE = S.LESSON_DATE AND L.LESSON_NUM = S.LESSON_NUM
    WHERE (S.LESSON_DATE > :V$CURRENT_DATE OR (S.LESSON_DATE = :V$CURRENT_DATE AND S.LESSON_NUM > :V$CURRENT_NUM)) AND L.OBJ_ID IS NULL
    ORDER BY 1, 2
    INTO :V$LESSON_DATE, :V$LESSON_NUMBER;

  END

  TAG_NAME = 'id';
  VAL = V$LESSON_ID;
  SUSPEND;
  TAG_NAME = 'teacher_id';
  VAL = V$TEACHER_ID;
  SUSPEND;
  TAG_NAME = 'teacher_name';
  VAL = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$TEACHER_ID));
  SUSPEND;
  TAG_NAME = 'date';
  VAL = (SELECT VAL FROM DATE2ISO(:V$LESSON_DATE, 0));
  SUSPEND;
  TAG_NAME = 'num';
  VAL = V$LESSON_NUMBER;
  SUSPEND;
  TAG_NAME = 'duration';
  VAL = CAST(V$LESSON_HOURS AS NUMERIC(18, 2));
  SUSPEND;
  TAG_NAME = 'theme';
  VAL = V$LESSON_THEME;
  SUSPEND;
  TAG_NAME = 'extra';
  VAL = V$LESSON_EXTRA;
  SUSPEND;
  TAG_NAME = 'homework';
  VAL = V$LESSON_HOMEWORK;
  SUSPEND;
  TAG_NAME = 'lesson_type';
  VAL = V$TYPE_ID;
  SUSPEND;
  TAG_NAME = 'lesson_ptp_id';
  VAL = V$PTP_ID;
  SUSPEND;
  TAG_NAME = 'inst_id';
  VAL = V$INST;
  SUSPEND;
  TAG_NAME = 'completed';
  VAL = V$COMPLETED;
  SUSPEND;
  TAG_NAME = 'is_online';
  VAL = V$ONLINE;
  SUSPEND;
  TAG_NAME = 'inst_link';
  VAL = V$LINK;
  SUSPEND;
  TAG_NAME = 'inst_status';
  VAL = V$INST_STATUS;
  SUSPEND;
  TAG_NAME = 'has_marks';
  VAL = 0;
  SELECT FIRST 1 1
  FROM CJ2_CONTROL C
  JOIN CJ2_MARK M ON M.DATE_DEL IS NULL AND M.CONTROL_ID = C.CONTROL_ID
  WHERE C.DATE_DEL IS NULL AND C.LESSON_ID = :I$LESSON_ID AND C.CONTROL_TYPE_ID <> 0
  INTO :VAL;
  SUSPEND;

  -- Разбираем DE_ID
  IF(V$DE_ID IS NULL) THEN V$DE_ID = '';
  TAG_NAME = 'de::json&colon;array';
  VAL = 1;
  SUSPEND;
  WHILE(V$DE_ID <> '') DO
  BEGIN
    P = POSITION(',' IN V$DE_ID);
    IF(P <= 0) THEN P = CHAR_LENGTH(V$DE_ID) + 1;
    TAG_NAME = 'de:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'de:r:id';
    V$LIST_ID = SUBSTRING(V$DE_ID FROM 1 FOR P - 1);
    VAL = V$LIST_ID;
    SUSPEND;
    TAG_NAME = 'de:r:value';
    VAL = NULL;
    V$EXT_ID = NULL;
    V$INST = NULL;
    SELECT FIRST 1 I.CODE, I.CAPTION, LV.TAG
    FROM CEC_ITEMS I
    LEFT JOIN LISTVALS LV ON LV.LISTVAL_ID = I.STAGE_ID
    WHERE I.OBJ_ID = :V$LIST_ID
    INTO :V$EXT_ID, :VAL, :V$INST;
    SUSPEND;
    TAG_NAME = 'de:r:code';
    VAL = V$EXT_ID;
    SUSPEND;
    TAG_NAME = 'de:r:stage';
    VAL = V$INST;
    SUSPEND;
    V$DE_ID = SUBSTRING(V$DE_ID FROM P + 1);
  END

  TAG_NAME = 'controls::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT CJC.CONTROL_ID, CJC.CONTROL_TYPE_ID, CJC.CONTROL_COST, CJC.MARK_SYSTEM_ID, CJC.IS_COMPLETED, CJC.HINT_TEXT, CJC.EXT_ID, CJC.TEST_ID
    FROM CJ2_CONTROL CJC
    WHERE CJC.LESSON_ID = :V$LESSON_ID AND CJC.DATE_DEL IS NULL AND CJC.CONTROL_TYPE_ID > 0
    ORDER BY 1
    INTO :V$CONTROL_ID, :V$CONTROL_TYPE_ID, :V$COST, :V$MARK_SYSTEM_ID, :V$COMPLETED, :V$LESSON_THEME, :V$EXT_ID, :V$TEST_ID
  DO
  BEGIN
    TAG_NAME = 'controls:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'controls:r:id';
    VAL = V$CONTROL_ID;
    SUSPEND;
    TAG_NAME = 'controls:r:type_id';
    VAL = V$CONTROL_TYPE_ID;
    SUSPEND;
    TAG_NAME = 'controls:r:system_id';
    VAL = V$MARK_SYSTEM_ID;
    SUSPEND;
    TAG_NAME = 'controls:r:cost';
    VAL = V$COST;
    SUSPEND;
    TAG_NAME = 'controls:r:completed';
    VAL = V$COMPLETED;
    SUSPEND;
    -- Текст ДЗ для контроля типа ДЗ, тема для голосования
    TAG_NAME = 'controls:r:text';
    VAL = V$LESSON_THEME;
    SUSPEND;
    TAG_NAME = 'controls:r:ext_id';
    VAL = V$EXT_ID;
    SUSPEND;
    TAG_NAME = 'controls:r:test_id';
    VAL = V$TEST_ID;
    SUSPEND;
    TAG_NAME = 'controls:r:test_name';
    VAL = NULL;
    P = NULL;
    IF(V$TEST_ID IS NOT NULL) THEN
    SELECT D.OBJ_NAME, D.EXAM_STATE
    FROM UT_EXAM_DATES D
    WHERE D.OBJ_ID = :V$TEST_ID
    INTO :VAL, :P;
    SUSPEND;
    TAG_NAME = 'controls:r:test_state';
    VAL = P;
    SUSPEND;
  END

  TAG_NAME = 'files::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT B.OBJ_ID, B.FILE_NAME, B.FILE_TYPE
    FROM CJ2_BLOB B
    WHERE B.LESSON_ID = :I$LESSON_ID AND B.DATE_DEL IS NULL
    ORDER BY 1
    INTO :V$CONTROL_ID, :V$LESSON_EXTRA, :V$TYPE
  DO
  BEGIN
    TAG_NAME = 'files:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'files:r:id';
    VAL = V$CONTROL_ID;
    SUSPEND;
    TAG_NAME = 'files:r:name';
    VAL = V$LESSON_EXTRA;
    SUSPEND;
    TAG_NAME = 'files:r:type_id';
    VAL = V$TYPE;
    SUSPEND;
  END

  TAG_NAME = 'teachers::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT TEACHER_ID, TEACHER_NAME, TEACHER_TYPE
    FROM CJ2_LESSON_TEACHERS_LIST(:I$CJ_ID, :I$LESSON_ID, :I$USER_ID)
    ORDER BY 3, 2
    INTO :V$TEACHER_ID, :V$LESSON_THEME, :V$TYPE
  DO
  BEGIN
    TAG_NAME = 'teachers:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'teachers:r:id';
    VAL = V$TEACHER_ID;
    SUSPEND;
    TAG_NAME = 'teachers:r:name';
    VAL = V$LESSON_THEME;
    SUSPEND;
    TAG_NAME = 'teachers:r:type';
    VAL = V$TYPE;
    SUSPEND;
  END

  -- Справочник типов занятий для этого журнала
  V$JOURNAL_TYPE = (SELECT JOURNAL_TYPE FROM CJ2_JOURNAL WHERE OBJ_ID = :I$CJ_ID);
  IF(V$JOURNAL_TYPE = 0) THEN V$LIST_ID = 389;  -- Общеобр
  ELSE IF(V$JOURNAL_TYPE = 1) THEN V$LIST_ID = 276;  -- ВД
  ELSE IF(V$JOURNAL_TYPE = 2) THEN V$LIST_ID = 233; -- ГПД
  ELSE IF(V$JOURNAL_TYPE = 3 AND V$STATUS = 'P') THEN V$LIST_ID = 329; -- ДО/ДПО
  --ELSE IF(V$JOURNAL_TYPE >= 10) THEN V$LIST_ID = ;
  -- для УДОД 318

  IF(V$LIST_ID IS NOT NULL) THEN
  BEGIN
    TAG_NAME = 'lesson_types::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT LISTVAL_ID, VAL
      FROM LISTVALS_LIST(:V$LIST_ID)
      WHERE IS_DEL = 0
      ORDER BY SORT_ORDER
      INTO :V$TYPE_ID, :V$LESSON_EXTRA
    DO
    BEGIN
      TAG_NAME = 'lesson_types:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'lesson_types:r:id';
      VAL = V$TYPE_ID;
      SUSPEND;
      TAG_NAME = 'lesson_types:r:value';
      VAL = V$LESSON_EXTRA;
      SUSPEND;
    END
  END

  --- УУД
  IF(V$JOURNAL_TYPE IN (0, 1)) THEN
  BEGIN
    TAG_NAME = 'usa::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT PARENT_ID, LISTVAL_ID, COST, "FILTER", VAL
      FROM LISTVALS_LIST(330)
      WHERE IS_DEL = 0
      ORDER BY SORT_ORDER
      INTO :V$CONTROL_ID, :V$TYPE_ID, :V$ROOM_ID, :V$EXT_ID, :V$LESSON_EXTRA
    DO
    BEGIN
      -- Фильтруем по маске этапа обучения
      IF(V$ROOM_ID = 0 OR BIN_AND(V$ROOM_ID, V$STMASK) > 0) THEN
      BEGIN
        TAG_NAME = 'usa:r';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'usa:r:parent_id';
        VAL = V$CONTROL_ID;
        SUSPEND;
        TAG_NAME = 'usa:r:id';
        VAL = V$TYPE_ID;
        SUSPEND;
        TAG_NAME = 'usa:r:filter';
        VAL = V$EXT_ID;
        SUSPEND;
        TAG_NAME = 'usa:r:value';
        VAL = V$LESSON_EXTRA;
        SUSPEND;
      END
    END
  END

  -- Ресурсы для урока
  TAG_NAME = 'resources::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT R.OBJ_ID, R.RES_ID, V604.LISTVAL_ID, V674.VAL || COALESCE(' ' || V3148.VAL, '', ' ' || V673.VAL, '')
    FROM CJ2_LESSON_RES R
    JOIN VALS V674 ON V674.OBJ_ID = R.RES_ID AND V674.PARAM_ID = 674 AND V674.IS_DEL = 0
    LEFT JOIN VALS V3148 ON V3148.OBJ_ID = R.RES_ID AND V3148.PARAM_ID = 3148 AND V3148.IS_DEL = 0
    LEFT JOIN VALS V673 ON V673.OBJ_ID = R.RES_ID AND V673.PARAM_ID = 673 AND V673.IS_DEL = 0
    LEFT JOIN LINKS LP95 ON LP95.OBJ_ID = R.RES_ID AND LP95.PARENT_TYPE_ID = 95 AND LP95.DATE_DEL IS NULL
    LEFT JOIN VALL V604 ON V604.OBJ_ID = LP95.PARENT_ID AND V604.PARAM_ID = 604 AND V604.IS_DEL = 0 AND V604.LISTVAL_ID IN (1816, 1931, 1933)
    WHERE R.LESSON_ID = :I$LESSON_ID AND R.DATE_DEL IS NULL
    ORDER BY 1
    INTO :V$CONTROL_ID, :V$CONTROL_TYPE_ID, :V$LIST_ID, :V$LESSON_EXTRA
  DO
  BEGIN
    TAG_NAME = 'resources:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'resources:r:id';
    VAL = V$CONTROL_ID;
    SUSPEND;
    TAG_NAME = 'resources:r:res_id';
    VAL = V$CONTROL_TYPE_ID;
    SUSPEND;
    TAG_NAME = 'resources:r:type_id';
    VAL = V$LIST_ID;
    SUSPEND;
    TAG_NAME = 'resources:r:name';
    VAL = V$LESSON_EXTRA;
    SUSPEND;
  END

  -- Получаем данные по кабинету и далее выбираем камеры по-умолчанию для этого кабинета, только общеобр и внеурочка
  -- Поскольку даты у нас нет, берем первый кабинет какой найдется по расписанию
  IF(I$LESSON_ID IS NULL AND V$JOURNAL_TYPE IN (0, 1)) THEN
  BEGIN

    SELECT J.YEAR_ID
    FROM CJ2_JOURNAL J
    WHERE J.OBJ_ID = :I$CJ_ID
    INTO :V$YEAR_ID;

    -- Назначение помещения на эту дату через разовый механизм
    -- !! TODO замещения !!!
    V$CURRENT_NUM = EXTRACT(MONTH FROM V$LESSON_DATE) * 100 + EXTRACT(DAY FROM V$LESSON_DATE);

    SELECT FIRST 1 M.ROOM_ID
    FROM SCHEDULE_ITEMS M
    JOIN LINKS LP68 ON LP68.OBJ_ID = M.SCHEDULE_ID AND LP68.PARENT_TYPE_ID = 68 AND LP68.DATE_DEL IS NULL
    JOIN VALL V37 ON V37.OBJ_ID = LP68.OBJ_ID AND V37.PARAM_ID = 37 AND V37.IS_DEL = 0 AND V37.LISTVAL_ID = :V$YEAR_ID
    WHERE M.DATE_DEL IS NULL AND M.CJ_ID = :I$CJ_ID AND M.ROOM_ID IS NOT NULL AND M.WEEKDAY_NUM = :V$CURRENT_NUM
    ORDER BY IIF(M.LESSON_NUM = :V$LESSON_NUMBER, 0, 1)
    INTO :V$ROOM_ID;

    -- Ищем по шаблону помещение, где больше всего занятий
    IF(V$ROOM_ID IS NULL) THEN
    SELECT FIRST 1 M.ROOM_ID, COUNT(*)
    FROM SCHEDULE_ITEMS M
    JOIN LINKS LP3 ON LP3.OBJ_ID = M.SCHEDULE_ID AND LP3.PARENT_TYPE_ID = 3 AND LP3.DATE_DEL IS NULL
    JOIN VALL V1341 ON V1341.OBJ_ID = LP3.OBJ_ID AND V1341.PARAM_ID = 1341 AND V1341.IS_DEL = 0 AND V1341.LISTVAL_ID = 2
    LEFT JOIN VALD V3120 ON V3120.OBJ_ID = LP3.OBJ_ID AND V3120.PARAM_ID = 3120 AND V3120.IS_DEL = 0
    LEFT JOIN VALD V3121 ON V3121.OBJ_ID = LP3.OBJ_ID AND V3121.PARAM_ID = 3121 AND V3121.IS_DEL = 0
    WHERE M.DATE_DEL IS NULL AND M.CJ_ID = :I$CJ_ID AND M.ROOM_ID IS NOT NULL
    AND (V3120.VAL <= :V$LESSON_DATE OR V3120.VAL IS NULL)
    AND (V3121.VAL >= :V$LESSON_DATE OR V3121.VAL IS NULL)
    GROUP BY 1
    ORDER BY 2 DESC
    INTO :V$ROOM_ID, :V$LIST_ID;

    FOR
      SELECT V679.OBJ_ID, V604.LISTVAL_ID, V674.VAL || COALESCE(' ' || V3148.VAL, ' ' || V673.VAL, '')
      FROM VALR V679
      JOIN LINKS LP95 ON LP95.OBJ_ID = V679.OBJ_ID AND LP95.PARENT_TYPE_ID = 95 AND LP95.DATE_DEL IS NULL
      JOIN VALL V604 ON V604.OBJ_ID = LP95.PARENT_ID AND V604.PARAM_ID = 604 AND V604.IS_DEL = 0 AND V604.LISTVAL_ID IN (1816, 1931, 1933)
      JOIN VALS V674 ON V674.OBJ_ID = LP95.OBJ_ID AND V674.PARAM_ID = 674 AND V674.IS_DEL = 0
      LEFT JOIN VALS V3148 ON V3148.OBJ_ID = LP95.OBJ_ID AND V3148.PARAM_ID = 3148 AND V3148.IS_DEL = 0
      LEFT JOIN VALS V673 ON V673.OBJ_ID = LP95.OBJ_ID AND V673.PARAM_ID = 673 AND V673.IS_DEL = 0
      WHERE V679.VAL = :V$ROOM_ID AND V679.PARAM_ID = 679 AND V679.IS_DEL = 0
      INTO :V$CONTROL_TYPE_ID, :V$LIST_ID, :V$LESSON_EXTRA
    DO
    BEGIN
      TAG_NAME = 'resources:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'resources:r:id';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'resources:r:res_id';
      VAL = V$CONTROL_TYPE_ID;
      SUSPEND;
      TAG_NAME = 'resources:r:type_id';
      VAL = V$LIST_ID;
      SUSPEND;
      TAG_NAME = 'resources:r:name';
      VAL = V$LESSON_EXTRA;
      SUSPEND;
    END

  END

  -- Атрибуты урока
  TAG_NAME = 'attrs::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT A.OBJ_ID, A.ATTR_NAME, A.ATTR_VALUE, A.REF_ID, A.LISTVAL_ID, IIF(OBJ.TYPE_ID = 2, 'Все классы', COALESCE(LC.VAL, C.CAPTION))
    FROM CJ2_LESSON_ATTRS A
    LEFT JOIN OBJECTS OBJ ON OBJ.OBJ_ID = A.REF_ID AND A.REF_ID IS NOT NULL
    LEFT JOIN OBJECT_CAPTION_GET(A.REF_ID) C ON A.REF_ID IS NOT NULL
    LEFT JOIN LISTVAL_TEXT(A.LISTVAL_ID) LC ON A.LISTVAL_ID IS NOT NULL
    WHERE A.DATE_DEL IS NULL AND A.LESSON_ID = :I$LESSON_ID
    INTO :V$CONTROL_ID, :V$LESSON_THEME, :V$LESSON_HOMEWORK, :V$CONTROL_ID, :V$CONTROL_TYPE_ID, :V$LESSON_EXTRA
  DO
  BEGIN
    TAG_NAME = 'attrs:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'attrs:r:id';
    VAL = V$CONTROL_ID;
    SUSPEND;
    TAG_NAME = 'attrs:r:name';
    VAL = V$LESSON_THEME;
    SUSPEND;
    TAG_NAME = 'attrs:r:value';
    VAL = COALESCE(V$LESSON_HOMEWORK, V$LESSON_EXTRA);
    SUSPEND;
    TAG_NAME = 'attrs:r:ref_id';
    VAL = V$CONTROL_ID;
    SUSPEND;
    TAG_NAME = 'attrs:r:listval_id';
    VAL = V$CONTROL_TYPE_ID;
    SUSPEND;
  END

  -- Только для журналов воспитательной работы - выдаем потенциальный список участников
  IF(V$JT = 20) THEN
  BEGIN
    TAG_NAME = 'mchoose::json&colon;array';
    VAL = 1;
    SUSPEND;
    -- Вся организация
    TAG_NAME = 'mchoose:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'mchoose:r:id';
    VAL = V$OU_ID;
    SUSPEND;
    TAG_NAME = 'mchoose:r:name';
    IF(V$STATUS = 'C') THEN VAL = 'Все учебные коллективы';
    ELSE VAL = 'Все классы'; -- !!! TODO
    SUSPEND;
    -- Диапазон классов по уровню образования
    FOR
      SELECT L7.OBJ_ID
      FROM LINKS L7
      JOIN VALL V43 ON V43.OBJ_ID = L7.OBJ_ID AND V43.PARAM_ID = 43
      JOIN LISTVALS LV ON LV.LISTVAL_ID = V43.LISTVAL_ID
      WHERE L7.PARENT_ID = :V$OU_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
      ORDER BY LV.COST
      INTO :V$DE_ID
    DO
    BEGIN
      TAG_NAME = 'mchoose:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'mchoose:r:id';
      VAL = V$DE_ID;
      SUSPEND;
      TAG_NAME = 'mchoose:r:name';
      VAL = NULL;
      SELECT CAST(MIN(LV.COST) AS INTEGER)
      FROM LINKS L8
      JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49
      JOIN LISTVALS LV ON LV.LISTVAL_ID = V49.LISTVAL_ID
      WHERE L8.PARENT_ID = :V$DE_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
      INTO :VAL;
      SELECT :VAL || '-' || CAST(MAX(LV.COST) AS INTEGER) || ' классы'
      FROM LINKS L8
      JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49
      JOIN LISTVALS LV ON LV.LISTVAL_ID = V49.LISTVAL_ID
      WHERE L8.PARENT_ID = :V$DE_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
      INTO :VAL;
      IF(VAL IS NULL) THEN VAL = '???-??? классы';
      IF(V$STATUS = 'C') THEN VAL = REPLACE(VAL, 'классы', 'курсы');
      SUSPEND;
    END
    -- Конкретные параллели
    FOR
      SELECT L8.OBJ_ID, REPLACE(C.CAPTION, 'параллель', 'классы')
      FROM LINKS L7
      JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
      LEFT JOIN OBJECT_CAPTION_GET(L8.OBJ_ID) C ON 1 = 1
      WHERE L7.PARENT_ID = :V$OU_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
      ORDER BY C.SORT_ORDER
      INTO :V$DE_ID, :V$LESSON_THEME
    DO
    BEGIN
      TAG_NAME = 'mchoose:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'mchoose:r:id';
      VAL = V$DE_ID;
      SUSPEND;
      TAG_NAME = 'mchoose:r:name';
      VAL = V$LESSON_THEME;
      SUSPEND;
    END
    -- Конкретные классы
    FOR
      SELECT L9.OBJ_ID, REPLACE(C.CAPTION, 'параллель', 'классы')
      FROM LINKS L7
      JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
      LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C ON 1 = 1
      WHERE L7.PARENT_ID = :V$OU_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
      ORDER BY C.SORT_ORDER
      INTO :V$DE_ID, :V$LESSON_THEME
    DO
    BEGIN
      TAG_NAME = 'mchoose:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'mchoose:r:id';
      VAL = V$DE_ID;
      SUSPEND;
      TAG_NAME = 'mchoose:r:name';
      VAL = V$LESSON_THEME;
      SUSPEND;
    END

    -- Направления воспитания
    TAG_NAME = 'directions::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT LISTVAL_ID, VAL
      FROM LISTVALS_LIST(353)
      ORDER BY SORT_ORDER
      INTO :V$TYPE_ID, :V$LESSON_EXTRA
    DO
    BEGIN
      TAG_NAME = 'directions:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'directions:r:id';
      VAL = V$TYPE_ID;
      SUSPEND;
      TAG_NAME = 'directions:r:value';
      VAL = V$LESSON_EXTRA;
      SUSPEND;
    END

    -- Направления воспитания
    TAG_NAME = 'modules::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT LISTVAL_ID, VAL
      FROM LISTVALS_LIST(354) L -- OO_FILTRED_LIST(354)
      WHERE L.IS_DEL = 0 AND (
        (:V$HAS_DO = 1 AND L."FILTER" LIKE '%DOU%') OR
        (:V$HAS_OO = 1 AND L."FILTER" LIKE '%GOU%') OR
        (:V$HAS_SPO = 1 AND L."FILTER" LIKE '%COLLEGE%') OR
        (:V$HAS_PO = 1 AND L."FILTER" LIKE '%COLLEGE%')
      )
      ORDER BY SORT_ORDER
      INTO :V$TYPE_ID, :V$LESSON_EXTRA
    DO
    BEGIN
      TAG_NAME = 'modules:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'modules:r:id';
      VAL = V$TYPE_ID;
      SUSPEND;
      TAG_NAME = 'modules:r:value';
      VAL = V$LESSON_EXTRA;
      SUSPEND;
    END
  END

  -- Тесты, которым положено быть в соответствии с ПТП
  TAG_NAME = 'tests::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT D.OBJ_ID, T.CONTROL_TYPE_ID, D.OBJ_NAME
    FROM PTP_LESSON_TESTS T
    JOIN UT_EXAM_DATES D ON D.DATE_DEL IS NULL AND D.OBJ_ID = T.TEST_ID
    WHERE T.DATE_DEL IS NULL AND T.LESSON_ID = :V$PTP_ID
    INTO :V$TEST_ID, :V$CONTROL_TYPE_ID, :V$LESSON_THEME
  DO
  BEGIN
    TAG_NAME = 'tests:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'tests:r:test_id';
    VAL = V$TEACHER_ID;
    SUSPEND;
    TAG_NAME = 'tests:r:control';
    VAL = V$CONTROL_TYPE_ID;
    SUSPEND;
    TAG_NAME = 'tests:r:name';
    VAL = V$LESSON_THEME;
    SUSPEND;
  END

  -- Дополнительные домашние задания
  TAG_NAME = 'homeworks::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT H.OBJ_ID, H.DST_LESSON_ID, H.DST_DATE, L.LESSON_DATE, H.HW_TEXT, H.STUDENT_IDS, IIF(L.DATE_DEL IS NULL, 0, 1)
    FROM CJ2_HOMEWORKS H
    LEFT JOIN CJ2_JOURNAL_LESSONS L ON L.OBJ_ID = H.DST_LESSON_ID
    WHERE H.DATE_DEL IS NULL AND H.LESSON_ID = :I$LESSON_ID
    INTO :V$EXT_ID, :V$LIST_ID, :D, :D2, :V$LESSON_HOMEWORK, :V$LESSON_EXTRA, :V$COMPLETED
  DO
  BEGIN
    TAG_NAME = 'homeworks:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'homeworks:r:id';
    VAL = V$EXT_ID;
    SUSPEND;
    TAG_NAME = 'homeworks:r:dst_lesson_id';
    VAL = V$LIST_ID;
    SUSPEND;
    TAG_NAME = 'homeworks:r:dst_date';
    VAL = (SELECT VAL FROM DATE2ISO(:D, 0));
    SUSPEND;
    TAG_NAME = 'homeworks:r:dst_lesson_date';
    VAL = (SELECT VAL FROM DATE2ISO(:D2, 0));
    SUSPEND;
    TAG_NAME = 'homeworks:r:text';
    VAL = V$LESSON_HOMEWORK;
    SUSPEND;
    TAG_NAME = 'homeworks:r:students';
    VAL = V$LESSON_EXTRA;
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_LESSON_MS_ASSIGN (
    I$CJ_ID BIGINT,
    I$DATE DATE,
    I$NUM INTEGER,
    I$TIME TIME,
    I$LESSON_ID BIGINT = NULL,
    I$OBJ_ID BIGINT = NULL,
    I$PREV_DATE DATE = NULL,
    I$PREV_NUM INTEGER = NULL,
    I$HAS_HW SMALLINT = 0)
RETURNS (
    OBJ_ID BIGINT)
AS
DECLARE VARIABLE V$LESSON_ID BIGINT;
DECLARE VARIABLE N INTEGER;
DECLARE VARIABLE V$DATE DATE;
DECLARE VARIABLE V$NUM INTEGER;
DECLARE VARIABLE V$TIME TIME;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$SEQ INTEGER;
DECLARE VARIABLE V$DT TIMESTAMP;
begin

  -- Может вызываться только для журналов 0 и 1 типов

  -- Если ничего не менялось, то и мы ничего не меняем
  IF(I$OBJ_ID IS NOT NULL AND I$PREV_DATE IS NOT NULL AND I$PREV_DATE = I$DATE AND I$PREV_NUM = I$NUM) THEN
  BEGIN
    OBJ_ID = I$OBJ_ID;
  END
  -- Привязки еще не было - создаем привязку
  ELSE IF(I$OBJ_ID IS NULL) THEN
  BEGIN
    -- Если виртуальных уроков вообще нет - создаем их по всем проведенным урокам этого журнала
    IF(NOT EXISTS(SELECT FIRST 1 1 FROM CJ2_MS_LESSONS WHERE CJ_ID = :I$CJ_ID AND DATE_DEL IS NULL)) THEN
    BEGIN
      N = 1;
      FOR
        SELECT L.OBJ_ID, L.LESSON_DATE, L.LESSON_NUM, L.LESSON_TIME
        FROM CJ2_JOURNAL_LESSONS L
        WHERE L.DATE_DEL IS NULL AND L.CJ_ID = :I$CJ_ID AND (L.IS_PUBLISHED <> 0 OR L.IS_COMPLETED <> 0 OR L.OBJ_ID = :I$LESSON_ID)
        ORDER BY 2, 4
        INTO :V$LESSON_ID, :V$DATE, :V$NUM, :V$TIME
      DO
      BEGIN
        V$OBJ_ID = NULL;
        SELECT FIRST 1 L.OBJ_ID
        FROM CJ2_MS_LESSONS L
        WHERE L.CJ_ID = :I$CJ_ID AND L.SEQ_INDEX = :N
        INTO :V$OBJ_ID;

        IF(V$OBJ_ID IS NULL) THEN
          INSERT INTO CJ2_MS_LESSONS
          (CJ_ID, SEQ_INDEX, LESSON_DATE, LESSON_NUM, LESSON_TIME)
          VALUES (:I$CJ_ID, :N, :V$DATE, :V$NUM, :V$TIME)
          RETURNING OBJ_ID INTO :V$OBJ_ID;
        ELSE
          UPDATE CJ2_MS_LESSONS
          SET DATE_DEL = NULL, LESSON_DATE = :V$DATE, LESSON_NUM = :V$NUM, LESSON_TIME = :V$TIME
          WHERE OBJ_ID = :V$OBJ_ID;

        -- Запоминаем созданный id виртуального урока - именно его и вернем
        IF(V$LESSON_ID = I$LESSON_ID) THEN
        BEGIN
          OBJ_ID = V$OBJ_ID;
          V$SEQ = N;
        END
        ELSE
        BEGIN
          -- Обновлять можно только для уроков, отличного от обрабатываемого
          UPDATE CJ2_JOURNAL_LESSONS
          SET MS_ID = :V$OBJ_ID
          WHERE OBJ_ID = :V$LESSON_ID;
        END

        N = N + 1;
      END
    END
    -- Уроки уже есть, выбираем нужный из уже накиданных или добавляем один новый
    ELSE
    BEGIN
      -- Есть ли уже связанные уроки после нашего ?
      -- Изменено: надо смотреть дату не от текущего урока, а от предыдущего ???
      SELECT FIRST 1 ML.SEQ_INDEX, L.LESSON_DATE, L.LESSON_NUM, L.LESSON_TIME
      FROM CJ2_JOURNAL_LESSONS L
      JOIN CJ2_MS_LESSONS ML ON ML.OBJ_ID = L.MS_ID
      WHERE L.DATE_DEL IS NULL AND L.CJ_ID = :I$CJ_ID AND L.OBJ_ID <> :I$LESSON_ID AND L.MS_ID IS NOT NULL
        AND (L.LESSON_DATE > :I$DATE OR (L.LESSON_DATE = :I$DATE AND L.LESSON_TIME > :I$TIME))
      ORDER BY 1
      INTO :V$SEQ, :V$DATE, :V$NUM, :V$TIME;

      -- Связанных уроков после нашего нет, берем очередной из пула или создаем новый
      IF(V$SEQ IS NULL) THEN
      BEGIN
        SELECT FIRST 1 ML.OBJ_ID, ML.DATE_DEL
        FROM CJ2_MS_LESSONS ML
        LEFT JOIN CJ2_JOURNAL_LESSONS L ON L.DATE_DEL IS NULL AND L.CJ_ID = ML.CJ_ID AND L.MS_ID = ML.OBJ_ID
        WHERE ML.CJ_ID = :I$CJ_ID AND L.OBJ_ID IS NULL
        ORDER BY ML.SEQ_INDEX
        INTO :OBJ_ID, :V$DT;

        V$DATE = I$DATE;
        V$TIME = I$TIME;
        V$NUM = I$NUM;

        IF(OBJ_ID IS NULL) THEN
        BEGIN
          SELECT FIRST 1 ML.SEQ_INDEX
          FROM CJ2_MS_LESSONS ML
          WHERE ML.CJ_ID = :I$CJ_ID
          ORDER BY ML.SEQ_INDEX DESC
          INTO :V$SEQ;

          IF(V$SEQ IS NULL) THEN V$SEQ = 1; ELSE V$SEQ = V$SEQ + 1;

          INSERT INTO CJ2_MS_LESSONS
          (CJ_ID, SEQ_INDEX, LESSON_DATE, LESSON_NUM, LESSON_TIME)
          VALUES (:I$CJ_ID, :V$SEQ, :V$DATE, :V$NUM, :V$TIME)
          RETURNING OBJ_ID INTO :OBJ_ID;
        END
        ELSE
        BEGIN
          UPDATE CJ2_MS_LESSONS
          SET DATE_DEL = NULL, LESSON_DATE = :V$DATE, LESSON_NUM = :V$NUM, LESSON_TIME = :V$TIME
          WHERE OBJ_ID = :OBJ_ID AND (LESSON_DATE <> :V$DATE OR LESSON_NUM <> :V$NUM OR LESSON_TIME <> :V$TIME);
        END
      END
      -- Связанные уроки есть, нужно раздвинуть нумерацию, но старые связи сохраняем
      -- дата и время ставим из того урока что там был раньше, остальные обновятся при пересчете расписания
      ELSE
      BEGIN
        UPDATE CJ2_MS_LESSONS
        SET SEQ_INDEX = SEQ_INDEX + 1
        WHERE CJ_ID = :I$CJ_ID AND SEQ_INDEX >= :V$SEQ;

        INSERT INTO CJ2_MS_LESSONS
        (CJ_ID, SEQ_INDEX, LESSON_DATE, LESSON_NUM, LESSON_TIME)
        VALUES (:I$CJ_ID, :V$SEQ, :V$DATE, :V$NUM, :V$TIME)
        RETURNING OBJ_ID INTO :OBJ_ID;
      END
    END
  END
  -- Привязка уже есть, и поменялась дата или номер урока
  ELSE
  BEGIN
    OBJ_ID = I$OBJ_ID;

    UPDATE CJ2_MS_LESSONS
    SET LESSON_DATE = :I$DATE, LESSON_NUM = :I$NUM, LESSON_TIME = :I$TIME
    WHERE OBJ_ID = :OBJ_ID;

    -- Перенумеровываем виртуальные уроки
    N = 1;
    FOR
      SELECT L.OBJ_ID
      FROM CJ2_MS_LESSONS L
      WHERE L.CJ_ID = :I$CJ_ID
      ORDER BY L.LESSON_DATE, L.LESSON_TIME
      INTO :V$LESSON_ID
    DO
    BEGIN
      UPDATE CJ2_MS_LESSONS
      SET SEQ_INDEX = :N
      WHERE OBJ_ID = :V$LESSON_ID AND SEQ_INDEX <> :N;

      IF(V$LESSON_ID = OBJ_ID) THEN V$SEQ = N;
      N = N + 1;
    END
  END

  -- Если у нас есть ДЗ, то создаем следующий виртуальный урок - если его еще нет
  -- следующий урок не создаем, если его дата выходит на июнь
  V$DATE = DATEADD(1 WEEK TO I$DATE);
  V$NUM = I$NUM;
  V$TIME = I$TIME;

  IF(I$HAS_HW = 1 AND EXTRACT(MONTH FROM V$DATE) <> 6) THEN
  BEGIN
    V$OBJ_ID = NULL;
    V$DT = NULL;
    SELECT FIRST 1 L.OBJ_ID, L.DATE_DEL
    FROM CJ2_MS_LESSONS L
    WHERE L.CJ_ID = :I$CJ_ID AND L.SEQ_INDEX > :V$SEQ
    INTO :V$OBJ_ID, :V$DT;

    IF(V$OBJ_ID IS NULL) THEN
    BEGIN
      -- Как минимум текущий у нас точно есть
      SELECT FIRST 1 SEQ_INDEX + 1
      FROM CJ2_MS_LESSONS
      WHERE CJ_ID = :I$CJ_ID
      ORDER BY 1 DESC
      INTO :N;

      INSERT INTO CJ2_MS_LESSONS
      (CJ_ID, SEQ_INDEX, LESSON_DATE, LESSON_NUM, LESSON_TIME)
      VALUES (:I$CJ_ID, :N, :V$DATE, :V$NUM, :V$TIME)
      RETURNING OBJ_ID INTO :V$OBJ_ID;
    END
    ELSE IF(V$DT IS NOT NULL) THEN
    BEGIN
      UPDATE CJ2_MS_LESSONS
      SET DATE_DEL = NULL, LESSON_DATE = :V$DATE, LESSON_NUM = :V$NUM, LESSON_TIME = :V$TIME
      WHERE OBJ_ID = :V$OBJ_ID;
    END
  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_LESSON_RES_ADD (
    I$LESSON_ID BIGINT,
    I$RES_ID BIGINT,
    I$USER_ID VARCHAR(40),
    I$WAS_COMPLETED SMALLINT = 0)
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$LESSON_ID bigint;
declare variable V$CJ_ID bigint;
declare variable V$DATE date;
declare variable V$TYPE bigint;
begin

  SELECT FIRST 1 L.OBJ_ID, L.CJ_ID, L.LESSON_DATE
  FROM CJ2_JOURNAL_LESSONS L
  WHERE L.DATE_DEL IS NULL AND L.OBJ_ID = :I$LESSON_ID
  INTO :V$LESSON_ID, :V$CJ_ID, :V$DATE;

  IF(V$LESSON_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Урок не найден';

  SELECT FIRST 1 R.OBJ_ID
  FROM CJ2_LESSON_RES R
  WHERE R.DATE_DEL IS NULL AND R.LESSON_ID = :I$LESSON_ID AND R.RES_ID = :I$RES_ID
  INTO :OBJ_ID;

  IF(OBJ_ID IS NULL) THEN
  BEGIN

    -- Есть ли такой МТР ? С запасом на будущее
    SELECT FIRST 1 V604.LISTVAL_ID
    FROM LINKS LP
    JOIN VALL V604 ON V604.OBJ_ID = LP.PARENT_ID AND V604.PARAM_ID = 604 AND V604.IS_DEL = 0
    JOIN LINKS LF ON LF.OBJ_ID = LP.PARENT_ID AND LF.PARENT_TYPE_ID = 23 AND LF.DATE_DEL IS NULL
    WHERE LP.OBJ_ID = :I$RES_ID AND LP.OBJ_TYPE_ID = 114 AND LP.PARENT_TYPE_ID = 95 AND LP.DATE_DEL IS NULL
    INTO :V$TYPE;

    IF(V$TYPE IS NULL) THEN EXCEPTION DATA_ERROR 'МТР не найден, либо для МТР не указан тип оборудования';

    -- Для уроков с датой в прошлом добавлять ресурсы нельзя
    -- Эта блокировка специально была для ВКС Пеликан, и неактуальна для всех прочих видов оборудования
     IF(V$DATE < CURRENT_DATE AND V$TYPE IN (1816, 1931, 1933)) THEN EXCEPTION DATA_ERROR 'Нельзя добавлять МТР с функциями ВКС в уроках с датой в прошлом, эта функция зарезервирована для функций видеотрансляции уроков';

    INSERT INTO CJ2_LESSON_RES
    (LESSON_ID, RES_ID, RES_TYPE)
    VALUES (:I$LESSON_ID, :I$RES_ID, :V$TYPE)
    RETURNING OBJ_ID INTO :OBJ_ID;

    -- Перерегистрируем связь
    UPDATE CJ2_JOURNAL_LESSONS SET INST_MODIFIED = 1 WHERE OBJ_ID = :I$LESSON_ID AND INST_MODIFIED = 0;

  END

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_LESSON_RES_DELETE (
    I$RES_ID BIGINT,
    I$USER_ID VARCHAR(40),
    I$WAS_COMPLETED SMALLINT = 0)
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$LESSON_ID bigint;
begin

  SELECT FIRST 1 R.OBJ_ID, L.OBJ_ID
  FROM CJ2_LESSON_RES R
  JOIN CJ2_JOURNAL_LESSONS L ON L.OBJ_ID = R.LESSON_ID AND L.DATE_DEL IS NULL
  WHERE R.DATE_DEL IS NULL AND R.OBJ_ID = :I$RES_ID
  INTO :OBJ_ID, :V$LESSON_ID;

  -- В случае ошибок не ругаемся, а просто ничего не делаем
  IF(OBJ_ID IS NOT NULL) THEN
  BEGIN
    -- Если урок проведен, удалять ресурсы может только руководитель
    -- !!!

    UPDATE CJ2_LESSON_RES
    SET DATE_DEL = CURRENT_TIMESTAMP
    WHERE OBJ_ID = :OBJ_ID;

    -- Перерегистрируем связь
    UPDATE CJ2_JOURNAL_LESSONS SET INST_MODIFIED = 1 WHERE OBJ_ID = :V$LESSON_ID AND INST_MODIFIED = 0;
  END

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_LESSON_SETINST (
    I$LESSON_ID BIGINT,
    I$INST_ID VARCHAR(1000))
AS
begin

  UPDATE CJ2_JOURNAL_LESSONS
  SET INST_ID = :I$INST_ID, INST_MODIFIED = 0
  WHERE OBJ_ID = :I$LESSON_ID;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_LESSON_TEACHERS_LIST (
    I$CJ_ID BIGINT,
    I$LESSON_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TEACHER_ID BIGINT,
    TEACHER_NAME VARCHAR(1000),
    TEACHER_TYPE INTEGER)
AS
declare variable V$NATIVE_TEACHER_ID bigint;
declare variable V$JOB_MATCH smallint;
begin

    -- TEACHER_TYPE: 0 = нативный учитель, 1 = заменяющий учитель, 2 = прочие учителя, предполагается что сортируем по этому полю
    -- Передается либо CJ_ID, либо LESSON_ID, либо вообще ничего
    IF(I$CJ_ID IS NULL) THEN
    BEGIN
        SELECT CJ_ID
        FROM CJ2_JOURNAL_LESSONS
        WHERE OBJ_ID = :I$LESSON_ID AND DATE_DEL IS NULL
        INTO :I$CJ_ID;
    END

    SELECT TEACHER_ID
    FROM CJ2_JOURNAL
    WHERE OBJ_ID = :I$CJ_ID AND DATE_DEL IS NULL
    INTO :V$NATIVE_TEACHER_ID;

    FOR
        SELECT L14.OBJ_ID
        FROM LINKS L2
        JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
        WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
        UNION
        SELECT L14.OBJ_ID
        FROM LINKS L2
        JOIN LINKS L211 ON L211.PARENT_ID = L2.OBJ_ID AND L211.OBJ_TYPE_ID = 211 AND L211.DATE_DEL IS NULL
        JOIN LINKS L14 ON L14.PARENT_ID = L211.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
        WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
        INTO :TEACHER_ID
    DO
    BEGIN

        -- Наличие действующей должности кроме персонала и служащих
        V$JOB_MATCH = 0;
        SELECT FIRST 1 1
        FROM LINKS L15
        JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
        JOIN VALL V63 ON V63.OBJ_ID = LP13.PARENT_ID AND V63.PARAM_ID = 63 AND V63.IS_DEL = 0 AND (V63.LISTVAL_ID NOT IN (1310, 1323) OR V63.LISTVAL_ID IN (1335, 3035))
        LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
        WHERE L15.PARENT_ID = :TEACHER_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL AND (V74.OBJ_ID IS NULL OR V74.VAL > CURRENT_DATE)
        INTO :V$JOB_MATCH;

        IF(V$JOB_MATCH = 1) THEN
        BEGIN
            IF(TEACHER_ID = V$NATIVE_TEACHER_ID) THEN TEACHER_TYPE = 0; ELSE TEACHER_TYPE = 2;
            TEACHER_NAME = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:TEACHER_ID));
            SUSPEND;
        END

    END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_LOAD_REPORT (
    I$YEAR_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    VAL VARCHAR(4000))
AS
declare variable V$NAME varchar(400);
declare variable V$SUBJECT varchar(1000);
declare variable V$WEEKS integer;
declare variable V$TEACHER_ID bigint;
declare variable V$HOURS float;
declare variable V$T integer;
declare variable V$OT integer;
declare variable V$THOURS float;
declare variable V$TTHOURS float;
declare variable V$TPW float;
declare variable V$TTPW float;
begin

  FOR
    SELECT DISTINCT J.TEACHER_ID, IIF(J.TEACHER_ID IS NULL, 'Вакантная ставка',  C.CAPTION)
    FROM CJ2_JOURNAL J
    LEFT JOIN OBJECT_CAPTION_GET(J.TEACHER_ID) C ON 1 = 1
    WHERE J.DATE_DEL IS NULL AND J.YEAR_ID = :I$YEAR_ID AND J.JOURNAL_TYPE < 10
    ORDER BY IIF(J.TEACHER_ID IS NULL, NULL, C.CAPTION) NULLS FIRST, 2
    INTO :V$TEACHER_ID, :VAL
  DO
  BEGIN

    VAL = '<div class="ui mini blue header">' || VAL || '</div>';

    VAL = VAL || '<table class="ui compact small fixed celled striped table">';
    VAL = VAL || '<thead><tr>';
    VAL = VAL || '<th style="width: 30%">Учебный коллектив, журнал</th>';
    VAL = VAL || '<th style="width: 30%">Предмет</th>';
    VAL = VAL || '<th>Часов нагрузки</th>';
    VAL = VAL || '<th>Недель</th>';
    VAL = VAL || '<th>Часов в неделю</th>';
    VAL = VAL || '</tr></thead>';
    SUSPEND;

    V$OT = -1;
    V$THOURS = 0;
    V$TTHOURS = 0;
    V$TPW = 0;
    V$TTPW = 0;

    FOR
      SELECT J.JOURNAL_TYPE, J.JOURNAL_NAME, CS.CAPTION, COALESCE(J.WEEKS, 0), COALESCE(J.HOURS, 0)
      FROM CJ2_JOURNAL J
      LEFT JOIN OBJECT_CAPTION_GET(J.SUBJECT_ID) CS ON 1 = 1
      WHERE J.DATE_DEL IS NULL AND J.YEAR_ID = :I$YEAR_ID AND J.JOURNAL_TYPE < 10 AND
        (J.TEACHER_ID = :V$TEACHER_ID OR (J.TEACHER_ID IS NULL AND :V$TEACHER_ID IS NULL))
      ORDER BY J.JOURNAL_TYPE, J.STAGE_INDEX, 1, 2
      INTO :V$T, :V$NAME, :V$SUBJECT, :V$WEEKS, :V$HOURS
    DO
    BEGIN

      VAL = '';

      IF(V$T <> V$OT) THEN
      BEGIN
        IF(V$OT >= 0) THEN
        BEGIN
          VAL = VAL || '<tr style="background: #f0f0f0; font-weight: bold">';
          VAL = VAL || '<td colspan="2">Всего</td>';
          VAL = VAL || '<td>' || CAST(V$THOURS AS NUMERIC(10, 1)) ||'</td>';
          VAL = VAL || '<td></td>';
          VAL = VAL || '<td>' || CAST(V$TPW AS NUMERIC(10, 1)) ||'</td>';
          VAL = VAL || '</tr></tbody>';
        END
        VAL = VAL || '<thead>';
        VAL = VAL || '<tr><th colspan="5">';
        IF(V$T = 0) THEN VAL = VAL || 'Общеобразовательные предметы';
        ELSE IF(V$T = 1) THEN VAL = VAL || 'Внеурочная деятельность';
        ELSE IF(V$T = 2) THEN VAL = VAL || 'ГПД';
        ELSE IF(V$T = 3) THEN VAL = VAL || 'Дополнительное образование';
        ELSE VAL = VAL || 'Неизвестный тип нагрузки';
        VAL = VAL || '</th></tr></thead><tbody>';
        V$THOURS = 0;
        V$TPW = 0;
        V$OT = V$T;
      END

      IF(V$SUBJECT = '<  ...  >') THEN V$SUBJECT = '';

      VAL = VAL || '<tr>';
      VAL = VAL || '<td>' || V$NAME || '</td>';
      VAL = VAL || '<td>' || V$SUBJECT || '</td>';
      VAL = VAL || '<td>' || CAST(V$HOURS AS NUMERIC(10, 1)) || '</td>';
      VAL = VAL || '<td>' || V$WEEKS || '</td>';
      IF(V$WEEKS = 0) THEN BEGIN V$WEEKS = 1; V$HOURS = 0; END
      VAL = VAL || '<td>' || CAST(V$HOURS / V$WEEKS AS NUMERIC(10, 1)) || '</td>';
      VAL = VAL || '</tr>';
      SUSPEND;

      V$THOURS = V$THOURS + V$HOURS;
      V$TTHOURS = V$TTHOURS + V$HOURS;
      V$TPW = V$TPW + V$HOURS / V$WEEKS;
      V$TTPW = V$TTPW + V$HOURS / V$WEEKS;

    END

    VAL = '';
    IF(V$OT >= 0) THEN
    BEGIN
      VAL = VAL || '<tr style="background: #f0f0f0; font-weight: bold">';
      VAL = VAL || '<td colspan="2">Всего</td>';
      VAL = VAL || '<td>' || CAST(V$THOURS AS NUMERIC(10, 1)) ||'</td>';
      VAL = VAL || '<td></td>';
      VAL = VAL || '<td></td>';
      VAL = VAL || '</tr>';
      VAL = VAL || '<tr style="border-top: 2px solid #404040; font-weight: bold; background: #90CAF9">';
      VAL = VAL || '<td colspan="2">Итого</td>';
      VAL = VAL || '<td>' || CAST(V$TTHOURS AS NUMERIC(10, 1)) ||'</td>';
      VAL = VAL || '<td></td>';
      VAL = VAL || '<td>' || CAST(V$TTPW AS NUMERIC(10, 1)) ||'</td>';
      VAL = VAL || '</tr>';
      VAL = VAL || '</tbody>';
    END
    VAL = VAL || '</table>';
    SUSPEND;

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_LOAD_TEACHERS (
    I$TYPE_ID SMALLINT,
    I$GRADE_ID BIGINT,
    I$STAGE_ID BIGINT,
    I$SUBJECT_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    OBJ_ID BIGINT,
    NAME VARCHAR(1000),
    CAT_ID SMALLINT)
AS
declare variable V$USER_ID bigint;
begin

  IF(I$USER_ID = 'Веб-администратор') THEN V$USER_ID = 1; ELSE V$USER_ID = CAST(I$USER_ID AS BIGINT);

  FOR
    SELECT TEACHER_ID, TEACHER_NAME
    FROM CJ2_LESSON_TEACHERS_LIST(NULL, NULL, :I$USER_ID)
    ORDER BY 2
    INTO :OBJ_ID, :NAME
  DO
  BEGIN
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_MARKS_AGG (
    I$CJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
declare variable V$SUBJECT_ID bigint;
declare variable V$GRADE_ID bigint;
declare variable V$ACCESS smallint;
declare variable V$YEAR_ID bigint;
declare variable V$YEAR_DATE date;
declare variable V$PERSON_ID bigint;
declare variable V$FINAL_ID bigint;
declare variable V$FT bigint;
declare variable V$DATE date;
declare variable V$PREV_DATE date;
declare variable V$CJ_ID bigint;
declare variable V$C1 float;
declare variable V$C2 float;
declare variable V$PERIOD_ID bigint;
begin

  SELECT J.SUBJECT_ID, J.GRADE_ID, J.YEAR_ID, CAST(LV.TAG AS DATE), J.PERIOD_ID
  FROM CJ2_JOURNAL J
  JOIN LISTVALS LV ON LV.LISTVAL_ID = J.YEAR_ID
  WHERE J.DATE_DEL IS NULL AND J.OBJ_ID = :I$CJ_ID
  INTO :V$SUBJECT_ID, :V$GRADE_ID, :V$YEAR_ID, :V$YEAR_DATE, :V$PERIOD_ID;

  SELECT ACCESS_LEVEL
  FROM CJ2_JOURNAL_ACCESS(:I$USER_ID, :I$CJ_ID)
  INTO :V$ACCESS;

  IF(V$ACCESS = 0) THEN EXCEPTION DATA_ERROR 'Нет доступа к журналу';

  TAG_NAME = 'agg::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
    SELECT DISTINCT M.PERSON_ID, J.OBJ_ID
    FROM PERSON_MOVEMENTS M
    JOIN PERSON_MOVEMENTS M2 ON M2.DATE_DEL IS NULL AND M2.PERSON_ID = M.PERSON_ID AND (M2.DATE_OUT IS NULL OR M2.DATE_OUT >= :V$YEAR_DATE)
    JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.YEAR_ID = :V$YEAR_ID AND J.GRADE_ID = M2.GROUP_ID AND J.SUBJECT_ID = :V$SUBJECT_ID AND J.OBJ_ID <> :I$CJ_ID
    WHERE M.DATE_DEL IS NULL AND M.GROUP_ID = :V$GRADE_ID AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :V$YEAR_DATE)
    INTO :V$PERSON_ID, :V$CJ_ID
  DO
  BEGIN

    -- Кроме итоговых по году
    -- Изначально шли по итоговым отметкам, но в измененной схеме идем по сетке периодов нашего журнала
    FOR
      SELECT F.OBJ_ID, F.FINAL_TYPE, V1169.VAL, V1174.VAL
      FROM LINKS L154
      JOIN VALD V1169 ON V1169.OBJ_ID = L154.OBJ_ID AND V1169.PARAM_ID = 1169 AND V1169.IS_DEL = 0 -- дата начала
      JOIN VALD V1174 ON V1174.OBJ_ID = L154.OBJ_ID AND V1174.PARAM_ID = 1174 AND V1174.IS_DEL = 0 -- дата окончания
      JOIN VALL V1170 ON V1170.OBJ_ID = L154.OBJ_ID AND V1170.PARAM_ID = 1170 AND V1170.IS_DEL = 0 -- тип периода
      JOIN CJ2_JOURNAL_FINALS F ON F.DATE_DEL IS NULL AND F.CJ_ID = :I$CJ_ID AND F.FINAL_DATE >= V1169.VAL AND F.FINAL_DATE <= DATEADD(1 DAY TO V1174.VAL)
        AND F.FINAL_TYPE = CASE V1170.LISTVAL_ID
          WHEN 12 THEN 3002
          WHEN 13 THEN 3003
          WHEN 14 THEN 3004
          WHEN 15 THEN 3005
          WHEN 10 THEN 3009
          WHEN 11 THEN 3010
          WHEN 16 THEN 3006
          WHEN 17 THEN 3007
          WHEN 18 THEN 3008
          WHEN 19 THEN 12973
          WHEN 20 THEN 12974
          ELSE NULL
        END
      WHERE L154.PARENT_ID = :V$PERIOD_ID AND L154.OBJ_TYPE_ID = 154 AND L154.DATE_DEL IS NULL
      ORDER BY 3
      INTO :V$FINAL_ID, :V$FT, :V$PREV_DATE, :V$DATE
    DO
    BEGIN
      TAG_NAME = 'agg:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'agg:r:person_id';
      VAL = V$PERSON_ID;
      SUSPEND;
      TAG_NAME = 'agg:r:final_id';
      VAL = V$FINAL_ID;
      SUSPEND;

      V$C1 = NULL;
      V$C2 = NULL;
      SELECT SUM(C.CONTROL_COST * MT.MARK_SCALE * MT.MARK_COST), SUM(C.CONTROL_COST)
      FROM CJ2_JOURNAL_LESSONS L
      JOIN CJ2_CONTROL C ON C.DATE_DEL IS NULL AND C.LESSON_ID = L.OBJ_ID AND C.CONTROL_TYPE_ID <> 0
      JOIN CJ2_MARK M ON M.DATE_DEL IS NULL AND M.CONTROL_ID = C.CONTROL_ID AND M.STUDENT_ID = :V$PERSON_ID
      JOIN CJ2_MARK_TYPE MT ON MT.MARK_TYPE_ID = M.MARK_TYPE_ID
      WHERE L.DATE_DEL IS NULL AND L.CJ_ID = :V$CJ_ID AND L.LESSON_DATE >= :V$PREV_DATE AND L.LESSON_DATE <= :V$DATE
      INTO :V$C1, :V$C2;

      TAG_NAME = 'agg:r:mv';
      VAL = CAST(V$C1 AS NUMERIC(18, 2));
      SUSPEND;
      TAG_NAME = 'agg:r:cv';
      VAL = CAST(V$C2 AS NUMERIC(18, 2));
      SUSPEND;
    END

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_MARK_ADD (
    I$CONTROL_ID BIGINT,
    I$STUDENT_ID BIGINT,
    I$MARK_ID BIGINT,
    I$COMMENTS_TEXT VARCHAR(1000),
    I$REASON_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    MARK_ID BIGINT,
    CJ_ID BIGINT)
AS
declare variable V$USER_ID bigint;
declare variable V$TEACHER_ID bigint;
declare variable ACCESS_LEVEL integer;
declare variable IS_SUBST smallint;
declare variable V$JOURNAL_TYPE smallint;
declare variable V$CONTROL_TYPE_ID bigint;
declare variable V$MARK_SYSTEM_ID bigint;
declare variable V$LESSON_DATE date;
declare variable V$CONTROL_COMPLETED integer;
declare variable V$CHECK_TYPE_SYSTEM bigint;
declare variable V$PREV_MARK_ID bigint;
declare variable V$PREV_MARK_TYPE bigint;
declare variable V$CJ_TEACHER bigint;
declare variable V$LESSON_TEACHER bigint;
declare variable V$USER_TYPE bigint;
declare variable V$PREV_TEXT varchar(1000);
declare variable V$LT bigint;
declare variable V$DE_ID varchar(400);
declare variable V$EXT_ID varchar(100);
declare variable V$YEAR_ID bigint;
declare variable V$GLOBAL_DISABLE bigint;
declare variable V$ZAV_MARKS bigint;
declare variable V$ZAV_FINALS bigint;
declare variable V$GLOBAL_DAYS integer;
declare variable IS_CLASSMATE smallint;
declare variable V$GRADE_ID bigint;
begin

  I$COMMENTS_TEXT = TRIM(I$COMMENTS_TEXT);
  IF(I$COMMENTS_TEXT = '') THEN I$COMMENTS_TEXT = NULL;

  -- Получаем кодификатор отметок для данного контроля
  SELECT J.JOURNAL_TYPE, CJC.CONTROL_TYPE_ID, CJC.MARK_SYSTEM_ID, CJL.LESSON_DATE, CJC.IS_COMPLETED, J.OBJ_ID,
    J.TEACHER_ID, CJL.TEACHER_ID, CJL.LESSON_TYPE_ID, COALESCE(CJL.DE_ID, ''), COALESCE(CJC.EXT_ID, ''), J.YEAR_ID,
    J.GRADE_ID
  FROM CJ2_CONTROL CJC
  JOIN CJ2_JOURNAL_LESSONS CJL ON CJL.OBJ_ID = CJC.LESSON_ID AND CJL.DATE_DEL IS NULL
  JOIN CJ2_JOURNAL J ON J.OBJ_ID = CJL.CJ_ID AND J.DATE_DEL IS NULL
  WHERE CJC.CONTROL_ID = :I$CONTROL_ID AND CJC.DATE_DEL IS NULL
  INTO :V$JOURNAL_TYPE, :V$CONTROL_TYPE_ID, :V$MARK_SYSTEM_ID, :V$LESSON_DATE, :V$CONTROL_COMPLETED, :CJ_ID,
    :V$CJ_TEACHER, :V$LESSON_TEACHER, :V$LT, :V$DE_ID, :V$EXT_ID, :V$YEAR_ID,
    :V$GRADE_ID;

  IF(V$CONTROL_TYPE_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Контроль не найден, возможно контроль или урок были удалены';

  -- Проверяем наличие прав доступа у пользователя
  IF(I$USER_ID = 'Веб-администратор') THEN V$USER_ID = 1; ELSE V$USER_ID = I$USER_ID;

  SELECT U.USER_TYPE, U.OBJ_ID
  FROM USERS U
  WHERE U.USER_ID = :V$USER_ID AND U.DATE_DEL IS NULL AND U.IS_BLOCKED = 0
  INTO :V$USER_TYPE, :V$TEACHER_ID;

  SELECT ACCESS_LEVEL, IS_SUBST, IS_CLASSMATE
  FROM CJ2_JOURNAL_ACCESS(:I$USER_ID, :CJ_ID)
  INTO :ACCESS_LEVEL, :IS_SUBST, :IS_CLASSMATE;

  IF(ACCESS_LEVEL = 0) THEN EXCEPTION DATA_ERROR 'Нет прав доступа к указанному журналу';
  IF(ACCESS_LEVEL = 5 AND V$CONTROL_TYPE_ID <> 0) THEN EXCEPTION DATA_ERROR 'Вы можете менять только пропуски, опоздания и замечания';
  IF(ACCESS_LEVEL = 6) THEN EXCEPTION DATA_ERROR 'Вы не можете изменять отметки';

  IF(V$USER_TYPE NOT IN (1, 5, 6) AND ACCESS_LEVEL NOT IN (2, 3, 4) AND (V$TEACHER_ID <> V$CJ_TEACHER OR V$CJ_TEACHER IS NULL)
      AND V$TEACHER_ID <> V$LESSON_TEACHER) THEN
  BEGIN
      EXCEPTION DATA_ERROR 'Вы не можете выставлять отметки в этом уроке, недостаточно прав доступа';
  END

  -- Проверяем глобальные настройки
  -- По-умолчанию завучу запрещено исправлять чужие отметки
  -- По-умолчанию лимит на отметки в 21 дней после даты урока
  -- По-умолчанию работа с журналами открыта
  SELECT COALESCE(V3324.LISTVAL_ID, 3), COALESCE(V3323.VAL, 21), COALESCE(V3321.LISTVAL_ID, 3), COALESCE(V3322.LISTVAL_ID, 3)
  FROM LINKS L2
  LEFT JOIN VALL V3324 ON V3324.OBJ_ID = L2.OBJ_ID AND V3324.PARAM_ID = 3324 AND V3324.IS_DEL = 0
  LEFT JOIN VALI V3323 ON V3323.OBJ_ID = L2.OBJ_ID AND V3323.PARAM_ID = 3323 AND V3323.IS_DEL = 0
  LEFT JOIN VALL V3321 ON V3321.OBJ_ID = L2.OBJ_ID AND V3321.PARAM_ID = 3321 AND V3321.IS_DEL = 0
  LEFT JOIN VALL V3322 ON V3322.OBJ_ID = L2.OBJ_ID AND V3322.PARAM_ID = 3322 AND V3322.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$GLOBAL_DISABLE, :V$GLOBAL_DAYS, :V$ZAV_MARKS, :V$ZAV_FINALS;

  IF(V$GLOBAL_DISABLE = 2) THEN EXCEPTION DATA_ERROR 'Внесение изменений в классный журнал запрещено руководителем организации';

  -- За пределами лимита в днях менять отметки может только админ или директор
  IF(V$USER_TYPE NOT IN (1, 5) AND V$LESSON_DATE < DATEADD(- V$GLOBAL_DAYS DAY TO CURRENT_DATE)) THEN
    EXCEPTION DATA_ERROR 'Лимит времени на изменение отметок истек. Только администратор или руководитель может изменить отметку';

  IF(V$USER_TYPE = 6) THEN
  BEGIN
    IF(V$ZAV_MARKS = 3 AND ACCESS_LEVEL NOT IN (2, 3, 4) AND (V$TEACHER_ID <> V$CJ_TEACHER OR V$CJ_TEACHER IS NULL) AND V$TEACHER_ID <> V$LESSON_TEACHER
      AND V$CONTROL_TYPE_ID <> 0)
    THEN
      EXCEPTION DATA_ERROR 'Настройки не позволяют Завучу изменять чужие текущие отметки';
  END

  -- Если не назначен штатный предметник, то классный руководитель может и отметки
  -- Роль классрука перекрывает роль замещения, надо дополнительные проверки
  IF(V$USER_TYPE NOT IN (1, 5, 6) AND ACCESS_LEVEL = 3 AND V$CONTROL_TYPE_ID <> 0 AND V$TEACHER_ID <> V$CJ_TEACHER) THEN
  BEGIN
      -- При замещениях проверяем, что есть права на эту конкретную дату. Скидываем IS_SUBST, если прав нет
      IF(IS_SUBST = 1) THEN
      BEGIN
      END

      IF(IS_SUBST = 0) THEN EXCEPTION DATA_ERROR 'Вы можете выставлять выставлять только опоздания, пропуски и замечания в данном журнале';
  END

  -- Если контроль уже проведен, требуется обязательно указать причину (только для самих отметок)
  IF(V$CONTROL_TYPE_ID <> 0 AND V$CONTROL_COMPLETED > 0 AND I$REASON_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не указана причина изменения/удаления отметки';

  -- Удаление отметки - все отметки кроме присутствия
  IF(I$MARK_ID IS NULL) THEN
  BEGIN

      UPDATE CJ2_MARK
      SET DATE_DEL = CURRENT_TIMESTAMP, USER_DEL = :V$USER_ID, REASON_ID = :I$REASON_ID
      WHERE CONTROL_ID = :I$CONTROL_ID AND STUDENT_ID = :I$STUDENT_ID AND DATE_DEL IS NULL AND MARK_TYPE_ID >= 100;

      IF(V$DE_ID <> '' OR (V$CONTROL_TYPE_ID = 30000 AND V$EXT_ID <> '')) THEN EXECUTE PROCEDURE RECALC_STUDENT_AGG(:I$STUDENT_ID, :V$YEAR_ID);

      MARK_ID = NULL;
      SUSPEND;
      EXIT;

  END
  -- Код 0 = обнулить все отметки присутствия
  ELSE IF(I$MARK_ID = 0) THEN
  BEGIN

      IF(V$CONTROL_TYPE_ID <> 0) THEN EXCEPTION DATA_ERROR 'Неверный код контроля для отметки присутствия';

      UPDATE CJ2_MARK
      SET DATE_DEL = CURRENT_TIMESTAMP, USER_DEL = :V$USER_ID, REASON_ID = :I$REASON_ID
      WHERE CONTROL_ID = :I$CONTROL_ID AND STUDENT_ID = :I$STUDENT_ID AND DATE_DEL IS NULL AND MARK_TYPE_ID BETWEEN 1 AND 98;

      MARK_ID = NULL;
      SUSPEND;
      EXIT;

  END
  -- Отметка из категории присутствия - отменяем все прочие отметки из этой области
  ELSE IF(I$MARK_ID >= 90 AND I$MARK_ID <= 99) THEN
  BEGIN

      IF(V$CONTROL_TYPE_ID <> 0) THEN EXCEPTION DATA_ERROR 'Неверный код контроля для отметки присутствия';

      UPDATE CJ2_MARK
      SET DATE_DEL = CURRENT_TIMESTAMP, USER_DEL = :V$USER_ID, REASON_ID = :I$REASON_ID
      WHERE CONTROL_ID = :I$CONTROL_ID AND STUDENT_ID = :I$STUDENT_ID AND DATE_DEL IS NULL AND MARK_TYPE_ID BETWEEN 90 AND 99;

      -- Для общеобра присутствие = отсутствие отсутствия, у остальных ставится явно
      IF(V$JOURNAL_TYPE = 0 AND I$MARK_ID = 99) THEN
      BEGIN
          MARK_ID = NULL;
          SUSPEND;
          EXIT;
      END

  END
  -- Обычная отметка или замечание
  ELSE
  BEGIN

      SELECT T.PARENT_ID
      FROM CJ2_MARK_TYPE T
      WHERE T.MARK_TYPE_ID = :I$MARK_ID
      INTO :V$CHECK_TYPE_SYSTEM;

      IF((I$MARK_ID = -1 AND V$MARK_SYSTEM_ID <> 0) OR (I$MARK_ID <> -1 AND (V$CHECK_TYPE_SYSTEM IS NULL OR V$CHECK_TYPE_SYSTEM <> V$MARK_SYSTEM_ID))) THEN
      BEGIN
          EXCEPTION DATA_ERROR 'Для данного контроля недопустима указанная отметка. Возможно с другого компьютера была изменена шкала оценивания';
      END

      -- Есть ли другие отметки (замечания затирают замечания, отметки - только сами отметки) ?
      SELECT FIRST 1 M.MARK_ID, M.MARK_TYPE_ID, M.COMMENTS_TEXT
      FROM CJ2_MARK M
      WHERE M.CONTROL_ID = :I$CONTROL_ID AND M.STUDENT_ID = :I$STUDENT_ID AND M.DATE_DEL IS NULL AND
          ((:I$MARK_ID = -1 AND M.MARK_TYPE_ID = -1) OR (:I$MARK_ID <> -1 AND M.MARK_TYPE_ID >= 100))
      INTO :V$PREV_MARK_ID, :V$PREV_MARK_TYPE, :V$PREV_TEXT;

      -- Если отметка была, то причину изменения вносим именно в старую отметку
      IF(V$PREV_MARK_ID IS NOT NULL) THEN
      BEGIN

          -- Если была та же отметка, ничего не меняем; кроме случая замечания - тут сверяем текст
          IF(V$PREV_MARK_TYPE = I$MARK_ID AND (V$PREV_MARK_TYPE <> -1 OR I$COMMENTS_TEXT = V$PREV_TEXT)) THEN
          BEGIN
              MARK_ID = V$PREV_MARK_ID;
              SUSPEND;
              EXIT;
          END

          UPDATE CJ2_MARK
          SET DATE_DEL = CURRENT_TIMESTAMP, USER_DEL = :V$USER_ID, REASON_ID = :I$REASON_ID
          WHERE MARK_ID = :V$PREV_MARK_ID AND DATE_DEL IS NULL;
      END

  END

  -- Вставляем новую отметку
  IF(I$MARK_ID <> -1 OR I$COMMENTS_TEXT IS NOT NULL) THEN
  BEGIN
      -- Отметки в раздел методической работы ДПО выставлять нельзя
      IF(V$LT = 13336) THEN EXCEPTION DATA_ERROR 'При учете учебно-методической работы отметки и присутствие не выставляются';

      -- Проверяем дату по движению
      IF(NOT EXISTS(
        SELECT FIRST 1 1
        FROM PERSON_MOVEMENTS M
        WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :I$STUDENT_ID AND M.GROUP_ID = :V$GRADE_ID
          AND M.DATE_IN <= :V$LESSON_DATE AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :V$LESSON_DATE)
      )) THEN
        EXCEPTION DATA_ERROR 'Обучающийся не числится в группе на указанную дату';

      INSERT INTO CJ2_MARK
      (CONTROL_ID, STUDENT_ID, MARK_TYPE_ID, COMMENTS_TEXT, MARK_DATE, USER_ID)
      VALUES (:I$CONTROL_ID, :I$STUDENT_ID, :I$MARK_ID, :I$COMMENTS_TEXT, CURRENT_DATE, :V$USER_ID)
      RETURNING MARK_ID
      INTO :MARK_ID;

      IF(V$DE_ID <> '' OR (V$CONTROL_TYPE_ID = 30000 AND V$EXT_ID <> '')) THEN EXECUTE PROCEDURE RECALC_STUDENT_AGG(:I$STUDENT_ID, :V$YEAR_ID);
  END

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_MARK_DETAILS (
    I$MARK_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$DATE_ADD TIMESTAMP;
DECLARE VARIABLE V$DATE_ADD2 TIMESTAMP;
DECLARE VARIABLE V$DATE_MODIFY TIMESTAMP;
DECLARE VARIABLE V$USER_ID BIGINT;
DECLARE VARIABLE V$CONTROL_ID BIGINT;
DECLARE VARIABLE V$FINAL_ID BIGINT;
DECLARE VARIABLE V$STUDENT_ID BIGINT;
DECLARE VARIABLE V$OLD_ID BIGINT;
DECLARE VARIABLE V$ACCESS INTEGER;
DECLARE VARIABLE S VARCHAR(400);
begin

  SELECT M.DATE_ADD, M.DATE_MODIFY, M.USER_ID, M.CONTROL_ID, M.FINAL_ID, M.STUDENT_ID, MT.MARK_SHORTNAME
  FROM CJ2_MARK M
  JOIN CJ2_MARK_TYPE MT ON MT.MARK_TYPE_ID = M.MARK_TYPE_ID
  WHERE M.DATE_DEL IS NULL AND M.MARK_ID = :I$MARK_ID
  INTO :V$DATE_ADD, :V$DATE_MODIFY, :V$USER_ID, :V$CONTROL_ID, :V$FINAL_ID, :V$STUDENT_ID, :S;

  IF(V$DATE_ADD IS NULL) THEN EXCEPTION DATA_ERROR 'Отметка не найдена';

  SELECT FIRST 1 A.ACCESS_LEVEL
  FROM CJ2_CONTROL C
  JOIN CJ2_JOURNAL_LESSONS L ON L.OBJ_ID = C.LESSON_ID AND L.DATE_DEL IS NULL
  JOIN CJ2_JOURNAL J ON J.OBJ_ID = L.CJ_ID AND J.DATE_DEL IS NULL
  LEFT JOIN CJ2_JOURNAL_ACCESS(:I$USER_ID, J.OBJ_ID) A ON 1 = 1
  WHERE C.CONTROL_ID = :V$CONTROL_ID AND C.DATE_DEL IS NULL
  UNION
  SELECT FIRST 1 A.ACCESS_LEVEL
  FROM CJ2_JOURNAL_FINALS F
  JOIN CJ2_JOURNAL J ON J.OBJ_ID = F.CJ_ID AND J.DATE_DEL IS NULL
  LEFT JOIN CJ2_JOURNAL_ACCESS(:I$USER_ID, J.OBJ_ID) A ON 1 = 1
  WHERE F.OBJ_ID = :V$FINAL_ID AND F.DATE_DEL IS NULL
  INTO :V$ACCESS;

  IF(V$ACCESS <= 0) THEN EXCEPTION DATA_ERROR 'У вас нет доступа к данному журналу';

  TAG_NAME = 'id';
  VAL = I$MARK_ID;
  SUSPEND;

  TAG_NAME = 'val';
  VAL = S;
  SUSPEND;

  TAG_NAME = 'date_add';
  VAL = (SELECT VAL FROM DATE2ISO(:V$DATE_ADD));
  SUSPEND;

  TAG_NAME = 'date_modify';
  VAL = (SELECT VAL FROM DATE2ISO(:V$DATE_MODIFY));
  SUSPEND;

  TAG_NAME = 'user_id';
  VAL = V$USER_ID;
  SUSPEND;

  TAG_NAME = 'teacher_name';
  VAL = NULL;
  SELECT FIRST 1 IIF(U.OBJ_ID IS NULL, U.USER_NAME, C.CAPTION)
  FROM USERS U
  LEFT JOIN OBJECT_CAPTION_GET(U.OBJ_ID) C ON U.OBJ_ID IS NOT NULL
  WHERE U.USER_ID = :V$USER_ID
  INTO :VAL;
  IF(V$USER_ID IS NULL) THEN VAL = 'АВТО';
  SUSPEND;

  TAG_NAME = 'modified';
  VAL = '0';
  SELECT FIRST 1 '1', M.MARK_ID, M.DATE_ADD, MT.MARK_SHORTNAME
  FROM CJ2_MARK M
  JOIN CJ2_MARK_TYPE MT ON MT.MARK_TYPE_ID = M.MARK_TYPE_ID
  WHERE M.MARK_ID < :I$MARK_ID AND M.DATE_DEL >= DATEADD(-1 MINUTE TO :V$DATE_ADD) AND M.STUDENT_ID = :V$STUDENT_ID
    AND (M.CONTROL_ID = :V$CONTROL_ID OR M.FINAL_ID = :V$FINAL_ID)
  INTO :VAL, :V$OLD_ID, :V$DATE_ADD2, :S;
  SUSPEND;

  TAG_NAME = 'old_id';
  VAL = V$OLD_ID;
  SUSPEND;

  TAG_NAME = 'old_val';
  VAL = S;
  SUSPEND;

  TAG_NAME = 'old_add';
  VAL = (SELECT VAL FROM DATE2ISO(:V$DATE_ADD2));
  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_MARK_FINAL_ADD (
    I$CONTROL_ID BIGINT,
    I$STUDENT_ID BIGINT,
    I$MARK_ID BIGINT,
    I$TEXT VARCHAR(2000),
    I$REASON_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    MARK_ID BIGINT,
    CJ_ID BIGINT)
AS
DECLARE VARIABLE V$GROUP_ID BIGINT;
DECLARE VARIABLE V$GROUP_TYPE_ID BIGINT;
DECLARE VARIABLE V$USER_ID BIGINT;
DECLARE VARIABLE V$TEACHER_ID BIGINT;
DECLARE VARIABLE ACCESS_LEVEL INTEGER;
DECLARE VARIABLE V$FINAL_TYPE_ID BIGINT;
DECLARE VARIABLE V$MARK_SYSTEM_ID BIGINT;
DECLARE VARIABLE V$LESSON_DATE DATE;
DECLARE VARIABLE V$CJ_TEACHER BIGINT;
DECLARE VARIABLE V$USER_TYPE BIGINT;
DECLARE VARIABLE V$MARK_TYPE BIGINT;
DECLARE VARIABLE V$MARKVAL_ID BIGINT;
DECLARE VARIABLE YEAR_ID BIGINT;
DECLARE VARIABLE V$SUBJECT_ID BIGINT;
DECLARE VARIABLE V$STAGE_ID BIGINT;
DECLARE VARIABLE V$PERIOD_ID BIGINT;
DECLARE VARIABLE V$PERIOD_FROM DATE;
DECLARE VARIABLE V$PERIOD_TO DATE;
DECLARE VARIABLE V$COPP BIGINT;
DECLARE VARIABLE V$PLAN_ID BIGINT;
DECLARE VARIABLE V$GRADE_ID BIGINT;
DECLARE VARIABLE V$BASE_TEACHER_ID BIGINT;
DECLARE VARIABLE V$LT BIGINT;
DECLARE VARIABLE V$LTM BIGINT;
DECLARE VARIABLE V$MASTER_SUBJ BIGINT;
DECLARE VARIABLE V$IS_EXT SMALLINT;
DECLARE VARIABLE IS_SUBST SMALLINT;
DECLARE VARIABLE IS_CLASSMATE SMALLINT;
DECLARE VARIABLE V$GLOBAL_DISABLE BIGINT;
DECLARE VARIABLE V$GLOBAL_DAYS INTEGER;
DECLARE VARIABLE V$ZAV_MARKS BIGINT;
DECLARE VARIABLE V$ZAV_FINALS BIGINT;
DECLARE VARIABLE V$STATUS VARCHAR(10);
DECLARE VARIABLE V$ATT_REG_ID BIGINT;
DECLARE VARIABLE V$SS_ID SMALLINT;
DECLARE VARIABLE V$ATT_DATE DATE;
DECLARE VARIABLE V$ATTR_STATE SMALLINT;
DECLARE VARIABLE V$MARK_ID BIGINT;
DECLARE VARIABLE V$PREV_MARK_ID BIGINT;
DECLARE VARIABLE V$SEQ INTEGER;
DECLARE VARIABLE V$HOURS FLOAT;
DECLARE VARIABLE V$CT BIGINT;
DECLARE VARIABLE V$IS_IND SMALLINT;
begin

  I$TEXT = TRIM(I$TEXT);
  IF(I$TEXT = '') THEN I$TEXT = NULL;

  V$STATUS = (SELECT STATUS FROM OU_LICENCE_TYPE);

  SELECT CJF.CJ_ID, CJM.TEACHER_ID, CJF.FINAL_DATE, CJF.FINAL_TYPE, CJM.GRADE_ID, CJM.GRADE_TYPE_ID,
    CJM.SUBJECT_ID, CJM.YEAR_ID, COALESCE(V3064.LISTVAL_ID, 3), CJM.REF_ID, CJM.PERIOD_ID, CJM.TEACHER_ID
  FROM CJ2_JOURNAL_FINALS CJF
  JOIN CJ2_JOURNAL CJM ON CJM.OBJ_ID = CJF.CJ_ID
  LEFT JOIN VALL V3064 ON V3064.OBJ_ID = CJM.GRADE_ID AND V3064.PARAM_ID IN (3063, 3064) AND V3064.IS_DEL = 0
  WHERE CJF.OBJ_ID = :I$CONTROL_ID AND CJF.DATE_DEL IS NULL
  INTO :CJ_ID, :V$CJ_TEACHER, :V$LESSON_DATE, :V$FINAL_TYPE_ID, :V$GROUP_ID, :V$GROUP_TYPE_ID,
    :V$SUBJECT_ID, :YEAR_ID, :V$COPP, :V$PLAN_ID, :V$PERIOD_ID, :V$BASE_TEACHER_ID;

  V$MARK_SYSTEM_ID = 400; -- ???

  IF(CJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Контроль не найден, возможно контроль или урок были удалены';

  -- Проверяем наличие прав доступа у пользователя
  IF(I$USER_ID = '00000000-0000-0000-0000-000000000000' OR I$USER_ID = 'Веб-администратор') THEN V$USER_ID = 1; ELSE V$USER_ID = I$USER_ID;

  SELECT U.USER_TYPE, U.OBJ_ID
  FROM USERS U
  WHERE U.USER_ID = :V$USER_ID AND U.DATE_DEL IS NULL AND U.IS_BLOCKED = 0
  INTO :V$USER_TYPE, :V$TEACHER_ID;

  SELECT ACCESS_LEVEL, IS_SUBST, IS_CLASSMATE
  FROM CJ2_JOURNAL_ACCESS(:I$USER_ID, :CJ_ID)
  INTO :ACCESS_LEVEL, :IS_SUBST, :IS_CLASSMATE;

  IF(ACCESS_LEVEL = 0) THEN EXCEPTION DATA_ERROR 'Нет прав доступа к указанному журналу';

  IF(V$USER_TYPE NOT IN (1, 5, 6) AND ACCESS_LEVEL NOT IN (2, 3, 4) AND V$TEACHER_ID <> V$CJ_TEACHER) THEN
  BEGIN
    EXCEPTION DATA_ERROR 'Вы не можете проставлять отметки в этом столбце, недостаточно прав доступа';
  END

  -- Если не назначен штатный предметник, то классный руководитель может и отметки
  IF(V$USER_TYPE NOT IN (1, 5, 6) AND ACCESS_LEVEL = 3 AND V$TEACHER_ID <> V$CJ_TEACHER AND I$MARK_ID NOT IN (100, 101, 102, 103, 104)) THEN
  BEGIN
    EXCEPTION DATA_ERROR 'Вы не можете выставлять итоговые отметки, отличные от аттестован/неаттестован';
  END

  -- Проверяем глобальные настройки
  -- По-умолчанию завучу запрещено исправлять чужие отметки
  -- По-умолчанию лимит на отметки в 21 дней после даты урока
  -- По-умолчанию работа с журналами открыта
  SELECT COALESCE(V3324.LISTVAL_ID, 3), COALESCE(V3323.VAL, 21), COALESCE(V3321.LISTVAL_ID, 3), COALESCE(V3322.LISTVAL_ID, 3)
  FROM LINKS L2
  LEFT JOIN VALL V3324 ON V3324.OBJ_ID = L2.OBJ_ID AND V3324.PARAM_ID = 3324 AND V3324.IS_DEL = 0
  LEFT JOIN VALI V3323 ON V3323.OBJ_ID = L2.OBJ_ID AND V3323.PARAM_ID = 3323 AND V3323.IS_DEL = 0
  LEFT JOIN VALL V3321 ON V3321.OBJ_ID = L2.OBJ_ID AND V3321.PARAM_ID = 3321 AND V3321.IS_DEL = 0
  LEFT JOIN VALL V3322 ON V3322.OBJ_ID = L2.OBJ_ID AND V3322.PARAM_ID = 3322 AND V3322.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$GLOBAL_DISABLE, :V$GLOBAL_DAYS, :V$ZAV_MARKS, :V$ZAV_FINALS;

  IF(V$GLOBAL_DISABLE = 2) THEN EXCEPTION DATA_ERROR 'Внесение изменений в классный журнал запрещено руководителем организации';

  -- За пределами лимита в днях менять отметки может только админ или директор
  IF(V$USER_TYPE NOT IN (1, 5) AND V$LESSON_DATE < DATEADD(- V$GLOBAL_DAYS DAY TO CURRENT_DATE)) THEN
    EXCEPTION DATA_ERROR 'Лимит времени на изменение отметок истек. Только администратор или руководитель может изменить отметку';

  IF(V$USER_TYPE = 6) THEN
  BEGIN
    IF(V$ZAV_FINALS = 3 AND ACCESS_LEVEL NOT IN (2, 3, 4) AND V$TEACHER_ID <> V$CJ_TEACHER) THEN
      EXCEPTION DATA_ERROR 'Настройки не позволяют Завучу изменять чужие итоговые отметки';
  END

  -- А был ли ученик в этом классе вообще ?
  IF(NOT EXISTS(
    SELECT FIRST 1 1
    FROM LINKS L10
    WHERE L10.PARENT_ID = :V$GROUP_ID AND L10.OBJ_ID = :I$STUDENT_ID AND L10.OBJ_TYPE_ID IN (10, 14)
  )) THEN EXCEPTION DATA_ERROR 'Учащийся не числится в группе (потоке)';

  -- Удалять можно всегда. Добавлять только если учащийся числится на дату
  IF(I$MARK_ID IS NOT NULL AND I$MARK_ID <> 0 AND I$MARK_ID <> 99) THEN
  BEGIN
    IF(NOT EXISTS(
      SELECT FIRST 1 1
      FROM CJ2_MEMBER_MOVEMENTS(:V$GROUP_ID, NULL, :I$STUDENT_ID) M
      WHERE M.DATE_FROM <= :V$LESSON_DATE AND (M.DATE_TO IS NULL OR M.DATE_TO >= :V$LESSON_DATE)
    )) THEN EXCEPTION DATA_ERROR 'Учащийся не числится в группе (потоке) на указанную дату';
  END

  -- Если исправление, требуется указать причину
  SELECT FIRST 1 MARK_TYPE_ID
  FROM CJ2_MARK
  WHERE FINAL_ID = :I$CONTROL_ID AND STUDENT_ID = :I$STUDENT_ID AND DATE_DEL IS NULL
  INTO :V$MARK_TYPE;

  IF(I$REASON_ID IS NULL AND V$MARK_TYPE IS NOT NULL) THEN EXCEPTION DATA_ERROR 'Не указана причина изменения/удаления отметки';

  -- Получаем текущий этап обучения по группе, в которой обучающийся числится или числился на указанную дату
  SELECT FIRST 1 V49.LISTVAL_ID, LP9.PARENT_ID
  FROM LINKS LP9
  JOIN LINKS LP8 ON LP8.OBJ_ID = LP9.PARENT_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
  JOIN VALL V49 ON V49.OBJ_ID = LP8.PARENT_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
  WHERE LP9.OBJ_ID = :I$STUDENT_ID AND LP9.PARENT_TYPE_ID IN (9, 187) AND LP9.DATE_DEL IS NULL
  INTO :V$STAGE_ID, :V$GRADE_ID;

  -- Меняем предмет, если у нас модуль в составе предмета
  SELECT FIRST 1 V3158.LISTVAL_ID, V3159.VAL, V3158_2.LISTVAL_ID
  FROM VALL V3158
  LEFT JOIN VALR V3159 ON V3159.OBJ_ID = V3158.OBJ_ID AND V3159.PARAM_ID = 3159 AND V3159.IS_DEL = 0
  LEFT JOIN VALL V3158_2 ON V3158_2.OBJ_ID = V3159.VAL AND V3158_2.PARAM_ID = 3158 AND V3158_2.IS_DEL = 0
  WHERE V3158.OBJ_ID = :V$SUBJECT_ID AND V3158.PARAM_ID = 3158 AND V3158.IS_DEL = 0
  INTO :V$LT, :V$MASTER_SUBJ, :V$LTM;

  IF(V$LT IN (13456, 13457) AND V$MASTER_SUBJ IS NOT NULL AND V$LTM = 13462) THEN V$SUBJECT_ID = V$MASTER_SUBJ;

  -- Для СПО - синхронизируем с ведомостью
  -- Курс и семестр обязательно должны совпадать с искомыми. Просроченные долги закрываются только напрямую через ведомость
  IF(V$STATUS = 'C') THEN
  BEGIN
    IF(V$FINAL_TYPE_ID = 12973) THEN V$SS_ID = 1;
    IF(V$FINAL_TYPE_ID = 12974) THEN V$SS_ID = 2;

    SELECT FIRST 1 S.OBJ_ID, R.ATT_DATE, R.STATE_ID
    FROM ATT_REGISTER_STDS S
    JOIN ATT_REGISTER R ON R.DATE_DEL IS NULL AND R.OBJ_ID = S.ATT_ID AND R.SUBJECT_ID = :V$SUBJECT_ID AND R.STAGE_ID = :V$STAGE_ID AND R.SUBSTAGE_ID = :V$SS_ID
    WHERE S.DATE_DEL IS NULL AND S.PERSON_ID = :I$STUDENT_ID
    ORDER BY R.STATE_ID
    INTO :V$ATT_REG_ID, :V$ATT_DATE, :V$ATTR_STATE;

    -- Нельзя аттестовывать раньше указанной
    IF(V$ATTR_STATE IS NULL) THEN EXCEPTION DATA_ERROR 'Нельзя выставлять оценки, если не открыта аттестационная ведомость, либо студент не включен в нее';
    IF(V$ATTR_STATE > 1) THEN EXCEPTION DATA_ERROR 'Все аттестационные ведомости по данному предмету/студенту закрыты';
    IF(V$ATT_DATE > CURRENT_DATE) THEN EXCEPTION DATA_ERROR 'Нельзя выставлять оценки ранее назначенной даты аттестации (' ||
      (SELECT RESULT FROM DATE2STR(:V$ATT_DATE)) || ')';
    IF(CURRENT_DATE > DATEADD(1 MONTH TO V$ATT_DATE)) THEN EXCEPTION DATA_ERROR 'На выставление оценок дается 1 месяц с назначенной даты аттестации';
  END

  -- Удаление отметки - удаляем все реальные отметки
  IF(I$MARK_ID IS NULL) THEN
  BEGIN
    UPDATE CJ2_MARK
    SET DATE_DEL = CURRENT_TIMESTAMP, REASON_ID = :I$REASON_ID, USER_DEL = :V$USER_ID
    WHERE FINAL_ID = :I$CONTROL_ID AND STUDENT_ID = :I$STUDENT_ID AND DATE_DEL IS NULL;

    UPDATE VALM
    SET IS_DEL = 1
    WHERE PUPIL_ID = :I$STUDENT_ID AND SUBJECT_ID = :V$SUBJECT_ID AND YEAR_ID = :YEAR_ID
      AND MARKTYPE_ID = :V$FINAL_TYPE_ID AND (STAGE_ID = :V$STAGE_ID OR STAGE_ID IS NULL) AND IS_DEL = 0;

    MARK_ID = NULL;

    IF(V$ATT_REG_ID IS NOT NULL) THEN
    BEGIN
      UPDATE ATT_REGISTER_STDS
      SET MARK_ID = NULL, STATE_ID = 0, DATE_MODIFY = CURRENT_TIMESTAMP
      WHERE OBJ_ID = :V$ATT_REG_ID AND (MARK_ID IS NULL OR STATE_ID <> 0);
    END
  END
  -- Код 0 = обнулить все отметки присутствия (замечания остаются)
  ELSE IF(I$MARK_ID = 0) THEN
  BEGIN
    -- Тут вообще нечего делать, но не ругаемся
    MARK_ID = NULL;
  END
  -- 99 = отметка присутствия, удаляет старые опоздания или отсутствия
  ELSE IF(I$MARK_ID = 99) THEN
  BEGIN
    -- Тут вообще нечего делать, но не ругаемся
    MARK_ID = NULL;
  END
  -- Замечание
  ELSE IF(I$MARK_ID = -1) THEN
  BEGIN
    EXCEPTION DATA_ERROR 'В данной графе замечания не предусмотрены';
  END
  -- Отметка из категории присутствия - отменяем все прочие отметки из этой области
  ELSE IF(I$MARK_ID = 90 OR I$MARK_ID > 2000) THEN
  BEGIN
      EXCEPTION DATA_ERROR 'В данной графе отметки присутствия не предусмотрены';
  END
  -- Обычная отметка
  ELSE
  BEGIN
    -- Проверка допустимости выбранной шкалы
    -- !!!

    SELECT FIRST 1 M.MARK_ID, M.MARK_TYPE_ID
    FROM CJ2_MARK M
    WHERE M.FINAL_ID = :I$CONTROL_ID AND M.STUDENT_ID = :I$STUDENT_ID AND M.DATE_DEL IS NULL
    INTO :MARK_ID, :V$MARK_TYPE;

    -- Корректируем шкалу в LV221
    SELECT MT.FINAL_ID
    FROM CJ2_MARK_TYPE MT
    WHERE MT.MARK_TYPE_ID = :I$MARK_ID AND MT.IS_DEL = 0
    INTO :V$MARKVAL_ID;

    IF(V$MARKVAL_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Данная отметка не может быть выставлена как итоговая';

    -- Получаем информацию о периоде
    IF(V$COPP = 2) THEN
    BEGIN
      IF(V$GROUP_TYPE_ID = 9) THEN
      BEGIN
        SELECT V3071.VAL FROM VALD V3071 WHERE V3071.OBJ_ID = :V$GROUP_ID AND V3071.PARAM_ID = 3071 AND V3071.IS_DEL = 0 INTO :V$PERIOD_FROM;
        SELECT V3072.VAL FROM VALD V3072 WHERE V3072.OBJ_ID = :V$GROUP_ID AND V3072.PARAM_ID = 3072 AND V3072.IS_DEL = 0 INTO :V$PERIOD_TO;
      END
      ELSE IF(V$GROUP_TYPE_ID = 179) THEN
      BEGIN
        SELECT FIRST 1 V3071.VAL, V3072.VAL
        FROM LINKS L10
        LEFT JOIN VALD V3071 ON V3071.OBJ_ID = L10.PARENT_ID AND V3071.PARAM_ID = 3071 AND V3071.IS_DEL = 0
        LEFT JOIN VALD V3072 ON V3072.OBJ_ID = L10.PARENT_ID AND V3072.PARAM_ID = 3072 AND V3072.IS_DEL = 0
        WHERE L10.OBJ_ID = :I$STUDENT_ID AND L10.PARENT_TYPE_ID = 9
        ORDER BY L10.DATE_INS DESC
        INTO :V$PERIOD_FROM, :V$PERIOD_TO;
      END
      IF(V$PERIOD_FROM IS NULL OR V$PERIOD_TO IS NULL) THEN EXCEPTION DATA_ERROR 'Не указаны дата начала или окончания занятий группы';
    END
    ELSE
    BEGIN
      SELECT MIN(V1169.VAL), MAX(V1174.VAL)
      FROM LINKS L154
      JOIN VALL V1171 ON V1171.OBJ_ID = L154.OBJ_ID AND V1171.PARAM_ID = 1171 AND V1171.IS_DEL = 0
        AND (V1171.LISTVAL_ID = :V$FINAL_TYPE_ID OR :V$FINAL_TYPE_ID IS NULL)
      JOIN VALD V1169 ON V1169.OBJ_ID = L154.OBJ_ID AND V1169.PARAM_ID = 1169 AND V1169.IS_DEL = 0
      JOIN VALD V1174 ON V1174.OBJ_ID = L154.OBJ_ID AND V1174.PARAM_ID = 1174 AND V1174.IS_DEL = 0
      WHERE L154.PARENT_ID = :V$PERIOD_ID AND L154.OBJ_TYPE_ID = 154 AND L154.DATE_DEL IS NULL
      INTO :V$PERIOD_FROM, :V$PERIOD_TO;
    END

    IF(MARK_ID IS NOT NULL) THEN
    BEGIN
      -- Коррекция для исправления наслоений - удаляем не одну оценку, а вообще все лишние копии
      UPDATE CJ2_MARK
      SET DATE_DEL = CURRENT_TIMESTAMP, REASON_ID = :I$REASON_ID, USER_DEL = :V$USER_ID
      WHERE FINAL_ID = :I$CONTROL_ID AND STUDENT_ID = :I$STUDENT_ID AND DATE_DEL IS NULL;
    END

    INSERT INTO CJ2_MARK
    (FINAL_ID, STUDENT_ID, MARK_TYPE_ID, IS_USED, USER_ID, MARK_DATE)
    VALUES (:I$CONTROL_ID, :I$STUDENT_ID, :I$MARK_ID, 1, :V$USER_ID, CURRENT_DATE)
    RETURNING MARK_ID INTO :MARK_ID;

    -- Предмет углубленного изучения ?
    V$IS_EXT = 0;
    SELECT FIRST 1 1
    FROM PLAN_SUBJECTS PS
    WHERE PS.DATE_DEL IS NULL AND PS.PLAN_ID = :V$PLAN_ID AND PS.SUBJECT_ID = :V$SUBJECT_ID AND PS.IS_ADV = 1
    INTO :V$IS_EXT;

    -- Индивидуальный УП ? Либо ученик в классе-экстернате
    V$IS_IND = 0;
    SELECT FIRST 1 IIF(V.LISTVAL_ID = 5465, 0, 1)
    FROM VALL V
    WHERE V.OBJ_ID = :V$PLAN_ID AND V.PARAM_ID = 3016 AND V.IS_DEL = 0
    INTO :V$IS_IND;
    IF(V$IS_IND = 0) THEN
    SELECT FIRST 1 1
    FROM LINKS LP187
    WHERE LP187.OBJ_ID = :I$STUDENT_ID AND LP187.PARENT_TYPE_ID = 187 AND LP187.DATE_DEL IS NULL
    INTO :V$IS_IND;

    -- Всегда вносится датой контроля
    -- Не сохраняем кастомные отметки школы
    -- В итоговой отметке VALM фиксируем не того, кто поставил отметку, а штатного предметника
    IF(V$FINAL_TYPE_ID < 1000000000) THEN
    BEGIN
      SELECT FIRST 1 M.MARK_ID, M.SEQ_INDEX
      FROM VALM M
      WHERE M.IS_DEL = 0 AND M.PUPIL_ID = :I$STUDENT_ID AND M.SUBJECT_ID = :V$SUBJECT_ID AND M.MARKTYPE_ID = :V$FINAL_TYPE_ID AND M.STAGE_ID = :V$STAGE_ID
      INTO :V$PREV_MARK_ID, :V$SEQ;

      -- Удаляем старые оценки в разрезе учебного года
      UPDATE VALM
      SET IS_DEL = 1
      WHERE IS_DEL = 0 AND PUPIL_ID = :I$STUDENT_ID AND SUBJECT_ID = :V$SUBJECT_ID AND YEAR_ID = :YEAR_ID AND MARKTYPE_ID = :V$FINAL_TYPE_ID;

      -- Достаем из УП данные по часам и типу контроля для СПО - в данном семестре
      SELECT FIRST 1 IIF(:V$FINAL_TYPE_ID = 12973, PL.LOAD_HOURS_S1, IIF(:V$FINAL_TYPE_ID = 12974, PL.LOAD_HOURS_S2, PL.LOAD_HOURS)), IIF(:V$FINAL_TYPE_ID = 12973, PL.CONTROL_Q1, IIF(:V$FINAL_TYPE_ID = 12974, PL.CONTROL_Q2, NULL))
      FROM LINKS LP256
      JOIN LINKS LP54 ON LP54.OBJ_ID = LP256.PARENT_ID AND LP54.PARENT_TYPE_ID = 54 AND LP54.DATE_DEL IS NULL
      JOIN LINKS LP400 ON LP400.OBJ_ID = LP54.PARENT_ID AND LP400.PARENT_TYPE_ID = 400 AND LP400.DATE_DEL IS NULL
      JOIN PLAN_SUBJECTS PS ON PS.DATE_DEL IS NULL AND PS.PLAN_ID = LP400.PARENT_ID AND PS.SUBJECT_ID = :V$SUBJECT_ID
      JOIN PLAN_LOADS PL ON PL.DATE_DEL IS NULL AND PL.SUBJECT_ID = PS.OBJ_ID
      JOIN VALL V381 ON V381.OBJ_ID = PL.STAGE_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0 AND V381.LISTVAL_ID = :V$STAGE_ID
      WHERE LP256.OBJ_ID = :I$STUDENT_ID AND LP256.PARENT_TYPE_ID = 256 AND LP256.DATE_DEL IS NULL
      INTO :V$HOURS, :V$CT;

      -- обновить ссылку на отметку в ведомости !!!
      INSERT INTO VALM (PUPIL_ID, SUBJECT_ID, TEACHER_ID, YEAR_ID, MARKTYPE_ID, MARKVAL_ID, STAGE_ID, IS_DEL,
        PERIOD_FROM, PERIOD_TO, GRADE_ID, MARK_DATE, IS_NATIVE, IS_EXT, IS_IND, PREV_ID, SEQ_INDEX, MARK_TEACHER_ID, PLAN_HOURS, CONTROL_TYPE_ID)
      VALUES (:I$STUDENT_ID, :V$SUBJECT_ID, COALESCE(:V$BASE_TEACHER_ID, :V$TEACHER_ID), :YEAR_ID, :V$FINAL_TYPE_ID, :V$MARKVAL_ID, :V$STAGE_ID, 0,
        :V$PERIOD_FROM, :V$PERIOD_TO, :V$GRADE_ID, CURRENT_DATE, 1, :V$IS_EXT, :V$IS_IND, :V$PREV_MARK_ID, COALESCE(:V$SEQ, 0) + 1, :V$CJ_TEACHER, :V$HOURS, :V$CT);

      IF(V$ATT_REG_ID IS NOT NULL) THEN
      BEGIN
        UPDATE ATT_REGISTER_STDS
        SET MARK_ID = :V$MARK_ID, STATE_ID = 0, DATE_MODIFY = CURRENT_TIMESTAMP
        WHERE OBJ_ID = :V$ATT_REG_ID;
      END
    END

  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_MARK_HISTORY (
    I$FINAL_ID BIGINT,
    I$PERSON_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
declare variable V$CJ_ID bigint;
declare variable V$SUBJECT_ID bigint;
declare variable V$GRADE_ID bigint;
declare variable V$YEAR_ID bigint;
declare variable V$YEAR_DATE date;
declare variable V$DATE date;
declare variable V$PREV_DATE date;
declare variable V$ACCESS smallint;
declare variable V$LESSON_DATE date;
declare variable V$MARK_ID bigint;
declare variable S varchar(100);
declare variable CT varchar(400);
begin

  SELECT J.OBJ_ID, J.SUBJECT_ID, J.GRADE_ID, J.YEAR_ID, CAST(LV.TAG AS DATE), F.FINAL_DATE
  FROM CJ2_JOURNAL_FINALS F
  JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.OBJ_ID = F.CJ_ID
  JOIN LISTVALS LV ON LV.LISTVAL_ID = J.YEAR_ID
  WHERE F.DATE_DEL IS NULL AND F.OBJ_ID = :I$FINAL_ID
  INTO :V$CJ_ID, :V$SUBJECT_ID, :V$GRADE_ID, :V$YEAR_ID, :V$YEAR_DATE, :V$DATE;

  SELECT ACCESS_LEVEL
  FROM CJ2_JOURNAL_ACCESS(:I$USER_ID, :V$CJ_ID)
  INTO :V$ACCESS;

  IF(V$ACCESS = 0) THEN EXCEPTION DATA_ERROR 'Нет доступа к журналу';

  SELECT FIRST 1 F.FINAL_DATE
  FROM CJ2_JOURNAL_FINALS F
  WHERE F.DATE_DEL IS NULL AND F.CJ_ID = :V$CJ_ID AND F.FINAL_DATE < :V$DATE
  INTO :V$PREV_DATE;

  IF(V$PREV_DATE IS NULL) THEN V$PREV_DATE = V$YEAR_DATE;

  TAG_NAME = 'journals::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
    SELECT DISTINCT J.OBJ_ID
    FROM PERSON_MOVEMENTS M2
    JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.YEAR_ID = :V$YEAR_ID AND J.GRADE_ID = M2.GROUP_ID AND J.SUBJECT_ID = :V$SUBJECT_ID AND J.OBJ_ID <> :V$CJ_ID
    WHERE M2.DATE_DEL IS NULL AND M2.PERSON_ID = :I$PERSON_ID AND (M2.DATE_OUT IS NULL OR M2.DATE_OUT >= :V$YEAR_DATE)
    ORDER BY M2.DATE_IN
    INTO :V$CJ_ID
  DO
  BEGIN
    TAG_NAME = 'journals:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'journals:r:name';
    SELECT FIRST 1 J.JOURNAL_NAME || ' - ' || C.CAPTION
    FROM CJ2_JOURNAL J
    LEFT JOIN OBJECT_CAPTION_GET(J.SUBJECT_ID) C ON 1 = 1
    WHERE J.OBJ_ID = :V$CJ_ID
    INTO :VAL;
    SUSPEND;

    TAG_NAME = 'journals:r:marks::json&colon;array';
    VAL = '1';
    SUSPEND;
    FOR
      SELECT M.MARK_ID, L.LESSON_DATE, MT.MARK_SHORTNAME, CT.CONTROL_NAME
      FROM CJ2_JOURNAL_LESSONS L
      JOIN CJ2_CONTROL C ON C.DATE_DEL IS NULL AND C.LESSON_ID = L.OBJ_ID
      JOIN CJ2_CONTROL_TYPE CT ON CT.CONTROL_TYPE_ID = C.CONTROL_TYPE_ID AND CT.CONTROL_TYPE_ID <> 0
      JOIN CJ2_MARK M ON M.DATE_DEL IS NULL AND M.CONTROL_ID = C.CONTROL_ID AND M.STUDENT_ID = :I$PERSON_ID
      JOIN CJ2_MARK_TYPE MT ON MT.MARK_TYPE_ID = M.MARK_TYPE_ID
      WHERE L.DATE_DEL IS NULL AND L.CJ_ID = :V$CJ_ID AND L.LESSON_DATE <= :V$DATE AND L.LESSON_DATE >= :V$PREV_DATE
      ORDER BY 1, C.CONTROL_ID
      INTO :V$MARK_ID, :V$LESSON_DATE, :S, :CT
    DO
    BEGIN
      TAG_NAME = 'journals:r:marks:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'journals:r:marks:r:id';
      VAL = V$MARK_ID;
      SUSPEND;
      TAG_NAME = 'journals:r:marks:r:date';
      VAL = (SELECT VAL FROM DATE2ISO(:V$LESSON_DATE));
      SUSPEND;
      TAG_NAME = 'journals:r:marks:r:ct';
      VAL = CT;
      SUSPEND;
      TAG_NAME = 'journals:r:marks:r:value';
      VAL = S;
      SUSPEND;
    END

  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_MASTER_ASSIGN (
    I$GROUP_ID BIGINT,
    I$MASTER_GROUP_ID BIGINT)
AS
begin

  IF(NOT EXISTS(
    SELECT FIRST 1 1
    FROM LINKS LPG
    WHERE LPG.OBJ_ID = :I$GROUP_ID AND LPG.PARENT_TYPE_ID = 2 AND LPG.DATE_DEL IS NULL
  ))
  THEN EXCEPTION DATA_ERROR 'Группа по предмету не найдена';

  IF(I$MASTER_GROUP_ID IS NOT NULL AND NOT EXISTS(
    SELECT FIRST 1 1
    FROM LINKS LPG
    WHERE LPG.OBJ_ID = :I$MASTER_GROUP_ID AND LPG.PARENT_TYPE_ID = 54 AND LPG.DATE_DEL IS NULL
  ))
  THEN EXCEPTION DATA_ERROR 'Мастер-группа не найдена';

  UPDATE LINKS
  SET EXT_OBJ_ID = :I$MASTER_GROUP_ID
  WHERE OBJ_ID = :I$GROUP_ID AND PARENT_TYPE_ID = 2 AND DATE_DEL IS NULL;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_MEMBERS_LIST (
    I$CJ_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    OBJ_NAME VARCHAR(1000),
    OBJ_TYPE_ID BIGINT)
AS
declare variable V$GROUP_ID bigint;
declare variable V$GROUP_TYPE_ID bigint;
declare variable V$YEAR_START date;
declare variable V$LAST_OUT date;
begin

  -- Используется в старом диалоге управления КЖ в толстом Параграфе, работает некорретно

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_MEMBER_MOVEMENTS (
    I$GROUP_ID BIGINT,
    I$GROUP_TYPE_ID BIGINT,
    I$MEMBER_ID BIGINT = null)
RETURNS (
    STUDENT_ID BIGINT,
    TYPE_ID BIGINT,
    DATE_FROM DATE,
    DATE_TO DATE)
AS
declare variable V$D1 date;
declare variable V$D2 date;
declare variable V$YEAR integer;
declare variable V$DATE date;
begin

  -- Какой текущий учебный год ?
  SELECT FIRST 1 LV.COST
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$YEAR;

  IF(V$YEAR IS NULL) THEN EXCEPTION DATA_ERROR 'Не задан текущий учебный год';
  V$DATE = '01.09.' || V$YEAR;

  IF(I$GROUP_TYPE_ID IS NULL) THEN
  BEGIN
      -- SELECT TYPE_ID FROM OBJECTS WHERE OBJ_ID = :I$GROUP_ID INTO :I$GROUP_TYPE_ID;
  END

  FOR
      SELECT DISTINCT LS.OBJ_ID, LS.OBJ_TYPE_ID
      FROM LINKS LS
      WHERE LS.PARENT_ID = :I$GROUP_ID AND LS.OBJ_TYPE_ID IN (10, 14, 20, 126) AND (:I$MEMBER_ID IS NULL OR LS.OBJ_ID = :I$MEMBER_ID)
      INTO :STUDENT_ID, :TYPE_ID
  DO
  BEGIN
      -- Новый реестр движения
      FOR
          SELECT M.DATE_IN, M.DATE_OUT
          FROM PERSON_MOVEMENTS M
          WHERE M.DATE_DEL IS NULL AND M.GROUP_ID = :I$GROUP_ID AND M.PERSON_ID = :STUDENT_ID
          ORDER BY M.DATE_IN, M.DATE_OUT NULLS LAST
          INTO :V$D1, :V$D2
      DO
      BEGIN
          DATE_FROM = V$D1;
          DATE_TO = V$D2;
          SUSPEND;
      END
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_MENU_LIST (
    I$USER_ID VARCHAR(40) NOT NULL)
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE USER_ID BIGINT;
DECLARE VARIABLE USER_TYPE INTEGER;
DECLARE VARIABLE TEACHER_ID BIGINT;
DECLARE VARIABLE STAGE_LV BIGINT;
DECLARE VARIABLE SUBJECT_ID BIGINT;
DECLARE VARIABLE SUBJECT_NAME VARCHAR(1000);
DECLARE VARIABLE GRADE_ID BIGINT;
DECLARE VARIABLE GRADE_NAME VARCHAR(1000);
DECLARE VARIABLE IS_STREAM SMALLINT;
DECLARE VARIABLE CJ_ID BIGINT;
DECLARE VARIABLE CJ_TYPE_ID SMALLINT;
DECLARE VARIABLE V$TEACHER_ID BIGINT;
DECLARE VARIABLE V$OU_TYPE CHAR(1);
DECLARE VARIABLE V$OU_ID BIGINT;
DECLARE VARIABLE V$YEAR_ID BIGINT;
begin
  -- Структура меню журналов разная для разных типов лицензий
  V$OU_TYPE = (SELECT STATUS FROM OU_LICENCE_TYPE);
  /*TAG_NAME = 'ou_type';
  VAL = V$OU_TYPE;
  SUSPEND;*/

  -- Преобразуем ID
  IF(I$USER_ID = '00000000-0000-0000-0000-000000000000' OR I$USER_ID = 'Веб-администратор') THEN USER_ID = 1;
  ELSE USER_ID = I$USER_ID;

  -- Получаем данные объекта сотрудника
  SELECT U.USER_TYPE, U.OBJ_ID
  FROM USERS U
  WHERE U.USER_ID = :USER_ID AND U.DATE_DEL IS NULL AND U.IS_BLOCKED = 0
  INTO :USER_TYPE, :TEACHER_ID;

  SELECT FIRST 1 L2.OBJ_ID, V1236.LISTVAL_ID
  FROM LINKS L2
  LEFT JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$OU_ID, :V$YEAR_ID;

  IF(V$OU_ID IS NOT NULL AND V$YEAR_ID IS NULL) THEN
  BEGIN
    SELECT FIRST 1 LV.LISTVAL_ID
    FROM LISTVALS LV
    WHERE LV.LIST_ID = 29 AND LV.IS_DEL = 0 AND LV.COST = IIF(EXTRACT(MONTH FROM CURRENT_DATE) < 9,
        EXTRACT(YEAR FROM CURRENT_DATE) - 1, EXTRACT(YEAR FROM CURRENT_DATE))
    INTO :V$YEAR_ID;

    IF(V$YEAR_ID IS NOT NULL) THEN SELECT BLOB_ID FROM VAL_ADD(1236, :V$OU_ID, :V$YEAR_ID) INTO :V$YEAR_ID;
  END

  -- Первая ветка по общеобразовательным журналам и журналам ВД
  FOR
      SELECT DISTINCT CJ.STAGE_INDEX
      FROM CJ2_JOURNAL CJ
      LEFT JOIN CJ2_JOURNAL_AUTOUSERS JU1 ON JU1.DATE_DEL IS NULL AND JU1.CJ_ID = CJ.OBJ_ID AND JU1.USER_ID = :USER_ID AND JU1.ACCESS > 0
      LEFT JOIN CJ2_JOURNAL_USERS JU2 ON JU2.DATE_DEL IS NULL AND JU2.CJ_ID = CJ.OBJ_ID AND JU2.USER_ID = :USER_ID
      LEFT JOIN CJ2_JOURNAL_LESSONS JL ON JL.DATE_DEL IS NULL AND JL.CJ_ID = CJ.OBJ_ID AND JL.TEACHER_ID = :TEACHER_ID AND JL.LESSON_DATE >= DATEADD(-3 DAY TO CURRENT_DATE) AND JL.LESSON_DATE <= DATEADD(14 DAY TO CURRENT_DATE)
      LEFT JOIN CJ2_REPL_PROCESS P ON P.DATE_DEL IS NULL AND ((P.CJ_ID = CJ.OBJ_ID AND P.REPL_CJ_ID IS NULL) OR P.REPL_CJ_ID = CJ.OBJ_ID) AND P.REPL_PERSON_ID = :TEACHER_ID AND P.REPL_DATE >= DATEADD(-3 DAY TO CURRENT_DATE) AND P.REPL_DATE <= DATEADD(14 DAY TO CURRENT_DATE)
      WHERE CJ.JOURNAL_TYPE IN (0, 1) AND CJ.DATE_DEL IS NULL AND (JU1.OBJ_ID IS NOT NULL OR JU2.OBJ_ID IS NOT NULL OR JL.OBJ_ID IS NOT NULL OR P.OBJ_ID IS NOT NULL)
        AND CJ.IS_ENABLED = 1 AND CJ.YEAR_ID = :V$YEAR_ID
      ORDER BY 1
      INTO :STAGE_LV
  DO
  BEGIN

      TAG_NAME = 'mi';
      VAL = NULL;
      SUSPEND;

      TAG_NAME = 'mi:name';
      IF(STAGE_LV IS NULL) THEN VAL = '';
      ELSE
      BEGIN
          SELECT R.VAL
          FROM LISTVALS LV
          JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
          WHERE LV.LISTVAL_ID = :STAGE_LV
          INTO VAL;
      END
      SUSPEND;

      TAG_NAME = 'mi:id';
      VAL = COALESCE(STAGE_LV, '0');
      SUSPEND;

      TAG_NAME = 'mi:type_id';
      VAL = '0';
      SUSPEND;

      TAG_NAME = 'mi:items';
      VAL = NULL;
      SUSPEND;

      TAG_NAME = 'mi:items::json&colon;array';
      VAL = '1';
      SUSPEND;

      -- Список предметов (сначала общеобразовательные, затем ВД)
      FOR
          SELECT DISTINCT CJ.SUBJECT_ID, C.CAPTION, CJ.JOURNAL_TYPE
          FROM CJ2_JOURNAL CJ
          LEFT JOIN CJ2_JOURNAL_AUTOUSERS JU1 ON JU1.DATE_DEL IS NULL AND JU1.CJ_ID = CJ.OBJ_ID AND JU1.USER_ID = :USER_ID AND JU1.ACCESS > 0
          LEFT JOIN CJ2_JOURNAL_USERS JU2 ON JU2.DATE_DEL IS NULL AND JU2.CJ_ID = CJ.OBJ_ID AND JU2.USER_ID = :USER_ID
          LEFT JOIN CJ2_JOURNAL_LESSONS JL ON JL.DATE_DEL IS NULL AND JL.CJ_ID = CJ.OBJ_ID AND JL.TEACHER_ID = :TEACHER_ID AND JL.LESSON_DATE >= DATEADD(-3 DAY TO CURRENT_DATE) AND JL.LESSON_DATE <= DATEADD(14 DAY TO CURRENT_DATE)
          LEFT JOIN CJ2_REPL_PROCESS P ON P.DATE_DEL IS NULL AND ((P.CJ_ID = CJ.OBJ_ID AND P.REPL_CJ_ID IS NULL) OR P.REPL_CJ_ID = CJ.OBJ_ID) AND P.REPL_PERSON_ID = :TEACHER_ID AND P.REPL_DATE >= DATEADD(-3 DAY TO CURRENT_DATE) AND P.REPL_DATE <= DATEADD(14 DAY TO CURRENT_DATE)
          LEFT JOIN OBJECT_CAPTION_GET(CJ.SUBJECT_ID) C ON CJ.SUBJECT_ID IS NOT NULL
          WHERE CJ.JOURNAL_TYPE IN (0, 1) AND CJ.DATE_DEL IS NULL AND ((CJ.STAGE_INDEX IS NULL AND :STAGE_LV IS NULL) OR CJ.STAGE_INDEX = :STAGE_LV)
            AND (JU1.OBJ_ID IS NOT NULL OR JU2.OBJ_ID IS NOT NULL OR JL.OBJ_ID IS NOT NULL OR P.OBJ_ID IS NOT NULL)
            AND CJ.IS_ENABLED = 1 AND CJ.YEAR_ID = :V$YEAR_ID
          ORDER BY 3, 2
          INTO :SUBJECT_ID, :SUBJECT_NAME, :CJ_TYPE_ID
      DO
      BEGIN

          TAG_NAME = 'mi:items:mi';
          VAL = NULL;
          SUSPEND;

          TAG_NAME = 'mi:items:mi:id';
          VAL = SUBJECT_ID;
          SUSPEND;

          TAG_NAME = 'mi:items:mi:name';
          VAL = SUBJECT_NAME;
          SUSPEND;

          TAG_NAME = 'mi:items:mi:type_id';
          VAL = CJ_TYPE_ID;
          SUSPEND;

          TAG_NAME = 'mi:items:mi:items';
          VAL = NULL;
          SUSPEND;

          TAG_NAME = 'mi:items:mi:items::json&colon;array';
          VAL = '1';
          SUSPEND;

          FOR
              SELECT DISTINCT CJ.OBJ_ID, CJ.JOURNAL_TYPE, CJ.GRADE_ID, COALESCE(VC.VAL, CJ.JOURNAL_NAME), IIF(VC.PARAM_ID IS NULL OR VC.PARAM_ID = 2162, 0, 1), CJ.TEACHER_ID
              FROM CJ2_JOURNAL CJ
              LEFT JOIN VALS VC ON VC.OBJ_ID = CJ.GRADE_ID AND VC.PARAM_ID IN (2162, 2706) AND VC.IS_DEL = 0
              LEFT JOIN CJ2_JOURNAL_AUTOUSERS JU1 ON JU1.DATE_DEL IS NULL AND JU1.CJ_ID = CJ.OBJ_ID AND JU1.USER_ID = :USER_ID AND JU1.ACCESS > 0
              LEFT JOIN CJ2_JOURNAL_USERS JU2 ON JU2.DATE_DEL IS NULL AND JU2.CJ_ID = CJ.OBJ_ID AND JU2.USER_ID = :USER_ID
              LEFT JOIN CJ2_JOURNAL_LESSONS JL ON JL.DATE_DEL IS NULL AND JL.CJ_ID = CJ.OBJ_ID AND JL.TEACHER_ID = :TEACHER_ID AND JL.LESSON_DATE >= DATEADD(-3 DAY TO CURRENT_DATE) AND JL.LESSON_DATE <= DATEADD(14 DAY TO CURRENT_DATE)
              LEFT JOIN CJ2_REPL_PROCESS P ON P.DATE_DEL IS NULL AND ((P.CJ_ID = CJ.OBJ_ID AND P.REPL_CJ_ID IS NULL) OR P.REPL_CJ_ID = CJ.OBJ_ID) AND P.REPL_PERSON_ID = :TEACHER_ID AND P.REPL_DATE >= DATEADD(-3 DAY TO CURRENT_DATE) AND P.REPL_DATE <= DATEADD(14 DAY TO CURRENT_DATE)
              WHERE CJ.JOURNAL_TYPE IN (0, 1) AND CJ.DATE_DEL IS NULL AND CJ.SUBJECT_ID = :SUBJECT_ID AND
                  ((CJ.STAGE_INDEX IS NULL AND :STAGE_LV IS NULL) OR CJ.STAGE_INDEX = :STAGE_LV) AND
                  (JU1.OBJ_ID IS NOT NULL OR JU2.OBJ_ID IS NOT NULL OR JL.OBJ_ID IS NOT NULL OR P.OBJ_ID IS NOT NULL)
                  AND CJ.IS_ENABLED = 1 AND CJ.YEAR_ID = :V$YEAR_ID
              ORDER BY 2 DESC, 5, 4
              INTO :CJ_ID, :CJ_TYPE_ID, :GRADE_ID, :GRADE_NAME, :IS_STREAM, :V$TEACHER_ID
          DO
          BEGIN

              TAG_NAME = 'mi:items:mi:items:mi';
              VAL = NULL;
              SUSPEND;

              TAG_NAME = 'mi:items:mi:items:mi:id';
              VAL = CJ_ID;
              SUSPEND;

              TAG_NAME = 'mi:items:mi:items:mi:type_id';
              VAL = CJ_TYPE_ID;
              SUSPEND;

              TAG_NAME = 'mi:items:mi:items:mi:grade_id';
              VAL = GRADE_ID;
              SUSPEND;

              TAG_NAME = 'mi:items:mi:items:mi:name';
              VAL = GRADE_NAME;
              SUSPEND;

              TAG_NAME = 'mi:items:mi:items:mi:stream';
              VAL = IS_STREAM;
              SUSPEND;

              -- Битовая маска с ролями, бит 0 = предметность, бит 1 = классность
              TAG_NAME = 'mi:items:mi:items:mi:rmask';
              VAL = IIF(TEACHER_ID = V$TEACHER_ID, 1, 0);
              SUSPEND;

          END

      END

  END

  -- ГПД - линейный список в 1 уровень
  FOR
      SELECT FIRST 1 1
      FROM CJ2_JOURNAL CJ
      LEFT JOIN CJ2_JOURNAL_AUTOUSERS JU1 ON JU1.DATE_DEL IS NULL AND JU1.CJ_ID = CJ.OBJ_ID AND JU1.USER_ID = :USER_ID AND JU1.ACCESS > 0
      LEFT JOIN CJ2_JOURNAL_USERS JU2 ON JU2.DATE_DEL IS NULL AND JU2.CJ_ID = CJ.OBJ_ID AND JU2.USER_ID = :USER_ID
      LEFT JOIN CJ2_JOURNAL_LESSONS JL ON JL.DATE_DEL IS NULL AND JL.CJ_ID = CJ.OBJ_ID AND JL.TEACHER_ID = :TEACHER_ID AND JL.LESSON_DATE >= DATEADD(-3 DAY TO CURRENT_DATE) AND JL.LESSON_DATE <= DATEADD(14 DAY TO CURRENT_DATE)
      LEFT JOIN CJ2_REPL_PROCESS P ON P.DATE_DEL IS NULL AND ((P.CJ_ID = CJ.OBJ_ID AND P.REPL_CJ_ID IS NULL) OR P.REPL_CJ_ID = CJ.OBJ_ID) AND P.REPL_PERSON_ID = :TEACHER_ID AND P.REPL_DATE >= DATEADD(-3 DAY TO CURRENT_DATE) AND P.REPL_DATE <= DATEADD(14 DAY TO CURRENT_DATE)
      WHERE CJ.JOURNAL_TYPE = 2 AND CJ.DATE_DEL IS NULL AND (JU1.OBJ_ID IS NOT NULL OR JU2.OBJ_ID IS NOT NULL OR JL.OBJ_ID IS NOT NULL OR P.OBJ_ID IS NOT NULL)
        AND CJ.IS_ENABLED = 1 AND CJ.YEAR_ID = :V$YEAR_ID
      INTO :STAGE_LV
  DO
  BEGIN

      TAG_NAME = 'mi';
      VAL = NULL;
      SUSPEND;

      TAG_NAME = 'mi:name';
      VAL = 'Группы продленного дня';
      SUSPEND;

      TAG_NAME = 'mi:id';
      VAL = '-2';
      SUSPEND;

      TAG_NAME = 'mi:type_id';
      VAL = '2';
      SUSPEND;

      TAG_NAME = 'mi:items';
      VAL = NULL;
      SUSPEND;

      TAG_NAME = 'mi:items::json&colon;array';
      VAL = '1';
      SUSPEND;

      FOR
          SELECT DISTINCT CJ.OBJ_ID, CJ.JOURNAL_TYPE, CJ.GRADE_ID, /* VC.VAL */ CJ.JOURNAL_NAME, CJ.TEACHER_ID
          FROM CJ2_JOURNAL CJ
          JOIN VALS VC ON VC.OBJ_ID = CJ.GRADE_ID AND VC.PARAM_ID IN (549, 54) AND VC.IS_DEL = 0
          LEFT JOIN CJ2_JOURNAL_AUTOUSERS JU1 ON JU1.DATE_DEL IS NULL AND JU1.CJ_ID = CJ.OBJ_ID AND JU1.USER_ID = :USER_ID AND JU1.ACCESS > 0
          LEFT JOIN CJ2_JOURNAL_USERS JU2 ON JU2.DATE_DEL IS NULL AND JU2.CJ_ID = CJ.OBJ_ID AND JU2.USER_ID = :USER_ID
          LEFT JOIN CJ2_JOURNAL_LESSONS JL ON JL.DATE_DEL IS NULL AND JL.CJ_ID = CJ.OBJ_ID AND JL.TEACHER_ID = :TEACHER_ID AND JL.LESSON_DATE >= DATEADD(-3 DAY TO CURRENT_DATE) AND JL.LESSON_DATE <= DATEADD(14 DAY TO CURRENT_DATE)
          LEFT JOIN CJ2_REPL_PROCESS P ON P.DATE_DEL IS NULL AND ((P.CJ_ID = CJ.OBJ_ID AND P.REPL_CJ_ID IS NULL) OR P.REPL_CJ_ID = CJ.OBJ_ID) AND P.REPL_PERSON_ID = :TEACHER_ID AND P.REPL_DATE >= DATEADD(-3 DAY TO CURRENT_DATE) AND P.REPL_DATE <= DATEADD(14 DAY TO CURRENT_DATE)
          WHERE CJ.JOURNAL_TYPE = 2 AND CJ.DATE_DEL IS NULL AND (JU1.OBJ_ID IS NOT NULL OR JU2.OBJ_ID IS NOT NULL OR JL.OBJ_ID IS NOT NULL OR P.OBJ_ID IS NOT NULL)
            AND CJ.IS_ENABLED = 1 AND CJ.YEAR_ID = :V$YEAR_ID
          ORDER BY 4
          INTO :CJ_ID, :CJ_TYPE_ID, :GRADE_ID, :GRADE_NAME, :V$TEACHER_ID
      DO
      BEGIN

          TAG_NAME = 'mi:items:mi';
          VAL = NULL;
          SUSPEND;

          TAG_NAME = 'mi:items:mi:id';
          VAL = CJ_ID;
          SUSPEND;

          TAG_NAME = 'mi:items:mi:type_id';
          VAL = CJ_TYPE_ID;
          SUSPEND;

          TAG_NAME = 'mi:items:mi:grade_id';
          VAL = GRADE_ID;
          SUSPEND;

          TAG_NAME = 'mi:items:mi:name';
          VAL = GRADE_NAME;
          SUSPEND;

          TAG_NAME = 'mi:items:mi:stream';
          VAL = 0;
          SUSPEND;

          -- Битовая маска с ролями, бит 0 = предметность, бит 1 = классность
          TAG_NAME = 'mi:items:mi:rmask';
          VAL = IIF(TEACHER_ID = V$TEACHER_ID, 1, 0);
          SUSPEND;

      END

  END

  -- ДО - линейный список в 1 уровень
  FOR
      SELECT FIRST 1 1
      FROM CJ2_JOURNAL CJ
      LEFT JOIN CJ2_JOURNAL_AUTOUSERS JU1 ON JU1.DATE_DEL IS NULL AND JU1.CJ_ID = CJ.OBJ_ID AND JU1.USER_ID = :USER_ID AND JU1.ACCESS > 0
      LEFT JOIN CJ2_JOURNAL_USERS JU2 ON JU2.DATE_DEL IS NULL AND JU2.CJ_ID = CJ.OBJ_ID AND JU2.USER_ID = :USER_ID
      LEFT JOIN CJ2_JOURNAL_LESSONS JL ON JL.DATE_DEL IS NULL AND JL.CJ_ID = CJ.OBJ_ID AND JL.TEACHER_ID = :TEACHER_ID AND JL.LESSON_DATE >= DATEADD(-3 DAY TO CURRENT_DATE) AND JL.LESSON_DATE <= DATEADD(14 DAY TO CURRENT_DATE)
      LEFT JOIN CJ2_REPL_PROCESS P ON P.DATE_DEL IS NULL AND ((P.CJ_ID = CJ.OBJ_ID AND P.REPL_CJ_ID IS NULL) OR P.REPL_CJ_ID = CJ.OBJ_ID) AND P.REPL_PERSON_ID = :TEACHER_ID AND P.REPL_DATE >= DATEADD(-3 DAY TO CURRENT_DATE) AND P.REPL_DATE <= DATEADD(14 DAY TO CURRENT_DATE)
      WHERE CJ.JOURNAL_TYPE = 3 AND CJ.DATE_DEL IS NULL AND (JU1.OBJ_ID IS NOT NULL OR JU2.OBJ_ID IS NOT NULL OR JL.OBJ_ID IS NOT NULL OR P.OBJ_ID IS NOT NULL)
        AND CJ.IS_ENABLED = 1 AND CJ.YEAR_ID = :V$YEAR_ID
      INTO :STAGE_LV
  DO
  BEGIN

      TAG_NAME = 'mi';
      VAL = NULL;
      SUSPEND;

      TAG_NAME = 'mi:name';
      IF(V$OU_TYPE = 'P') THEN VAL = 'Журналы обучения'; ELSE VAL = 'Дополнительное образование';
      SUSPEND;

      TAG_NAME = 'mi:id';
      VAL = '-3';
      SUSPEND;

      TAG_NAME = 'mi:type_id';
      VAL = '3';
      SUSPEND;

      TAG_NAME = 'mi:items';
      VAL = NULL;
      SUSPEND;

      TAG_NAME = 'mi:items::json&colon;array';
      VAL = '1';
      SUSPEND;

      FOR
          SELECT DISTINCT CJ.OBJ_ID, CJ.JOURNAL_TYPE, CJ.GRADE_ID, /* VC.VAL */ CJ.JOURNAL_NAME, CJ.TEACHER_ID
          FROM CJ2_JOURNAL CJ
          -- JOIN VALS VC ON VC.OBJ_ID = CJ.GRADE_ID AND VC.PARAM_ID IN (549, 54) AND VC.IS_DEL = 0
          LEFT JOIN CJ2_JOURNAL_AUTOUSERS JU1 ON JU1.DATE_DEL IS NULL AND JU1.CJ_ID = CJ.OBJ_ID AND JU1.USER_ID = :USER_ID AND JU1.ACCESS > 0
          LEFT JOIN CJ2_JOURNAL_USERS JU2 ON JU2.DATE_DEL IS NULL AND JU2.CJ_ID = CJ.OBJ_ID AND JU2.USER_ID = :USER_ID
          LEFT JOIN CJ2_JOURNAL_LESSONS JL ON JL.DATE_DEL IS NULL AND JL.CJ_ID = CJ.OBJ_ID AND JL.TEACHER_ID = :TEACHER_ID AND JL.LESSON_DATE >= DATEADD(-3 DAY TO CURRENT_DATE) AND JL.LESSON_DATE <= DATEADD(14 DAY TO CURRENT_DATE)
          LEFT JOIN CJ2_REPL_PROCESS P ON P.DATE_DEL IS NULL AND ((P.CJ_ID = CJ.OBJ_ID AND P.REPL_CJ_ID IS NULL) OR P.REPL_CJ_ID = CJ.OBJ_ID) AND P.REPL_PERSON_ID = :TEACHER_ID AND P.REPL_DATE >= DATEADD(-3 DAY TO CURRENT_DATE) AND P.REPL_DATE <= DATEADD(14 DAY TO CURRENT_DATE)
          WHERE CJ.JOURNAL_TYPE = 3 AND CJ.DATE_DEL IS NULL AND (JU1.OBJ_ID IS NOT NULL OR JU2.OBJ_ID IS NOT NULL OR JL.OBJ_ID IS NOT NULL OR P.OBJ_ID IS NOT NULL)
            AND CJ.IS_ENABLED = 1 AND CJ.YEAR_ID = :V$YEAR_ID
          ORDER BY 4
          INTO :CJ_ID, :CJ_TYPE_ID, :GRADE_ID, :GRADE_NAME, :V$TEACHER_ID
      DO
      BEGIN

          TAG_NAME = 'mi:items:mi';
          VAL = NULL;
          SUSPEND;

          TAG_NAME = 'mi:items:mi:id';
          VAL = CJ_ID;
          SUSPEND;

          TAG_NAME = 'mi:items:mi:type_id';
          VAL = CJ_TYPE_ID;
          SUSPEND;

          TAG_NAME = 'mi:items:mi:grade_id';
          VAL = GRADE_ID;
          SUSPEND;

          TAG_NAME = 'mi:items:mi:name';
          VAL = GRADE_NAME;
          SUSPEND;

          TAG_NAME = 'mi:items:mi:stream';
          VAL = 0;
          SUSPEND;

          -- Битовая маска с ролями, бит 0 = предметность, бит 1 = классность
          TAG_NAME = 'mi:items:mi:rmask';
          VAL = IIF(TEACHER_ID = V$TEACHER_ID, 1, 0);
          SUSPEND;

      END

  END

  -- Посещение садов - линейный список в 1 уровень
  FOR
      SELECT FIRST 1 1
      FROM CJ2_JOURNAL CJ
      LEFT JOIN CJ2_JOURNAL_AUTOUSERS JU1 ON JU1.DATE_DEL IS NULL AND JU1.CJ_ID = CJ.OBJ_ID AND JU1.USER_ID = :USER_ID AND JU1.ACCESS > 0
      LEFT JOIN CJ2_JOURNAL_USERS JU2 ON JU2.DATE_DEL IS NULL AND JU2.CJ_ID = CJ.OBJ_ID AND JU2.USER_ID = :USER_ID
      LEFT JOIN CJ2_JOURNAL_LESSONS JL ON JL.DATE_DEL IS NULL AND JL.CJ_ID = CJ.OBJ_ID AND JL.TEACHER_ID = :TEACHER_ID AND JL.LESSON_DATE >= DATEADD(-3 DAY TO CURRENT_DATE) AND JL.LESSON_DATE <= DATEADD(14 DAY TO CURRENT_DATE)
      LEFT JOIN CJ2_REPL_PROCESS P ON P.DATE_DEL IS NULL AND ((P.CJ_ID = CJ.OBJ_ID AND P.REPL_CJ_ID IS NULL) OR P.REPL_CJ_ID = CJ.OBJ_ID) AND P.REPL_PERSON_ID = :TEACHER_ID AND P.REPL_DATE >= DATEADD(-3 DAY TO CURRENT_DATE) AND P.REPL_DATE <= DATEADD(14 DAY TO CURRENT_DATE)
      WHERE CJ.JOURNAL_TYPE = 4 AND CJ.DATE_DEL IS NULL AND (JU1.OBJ_ID IS NOT NULL OR JU2.OBJ_ID IS NOT NULL OR JL.OBJ_ID IS NOT NULL OR P.OBJ_ID IS NOT NULL)
        AND CJ.IS_ENABLED = 1 AND CJ.YEAR_ID = :V$YEAR_ID
      INTO :STAGE_LV
  DO
  BEGIN

      TAG_NAME = 'mi';
      VAL = NULL;
      SUSPEND;

      TAG_NAME = 'mi:name';
      VAL = 'Группы ДОУ';
      SUSPEND;

      TAG_NAME = 'mi:id';
      VAL = '-4';
      SUSPEND;

      TAG_NAME = 'mi:type_id';
      VAL = '4';
      SUSPEND;

      TAG_NAME = 'mi:items';
      VAL = NULL;
      SUSPEND;

      TAG_NAME = 'mi:items::json&colon;array';
      VAL = '1';
      SUSPEND;

      FOR
          SELECT DISTINCT CJ.OBJ_ID, CJ.JOURNAL_TYPE, CJ.GRADE_ID, /* VC.VAL */ CJ.JOURNAL_NAME, CJ.TEACHER_ID
          FROM CJ2_JOURNAL CJ
          JOIN VALS VC ON VC.OBJ_ID = CJ.GRADE_ID AND VC.PARAM_ID IN (549, 54) AND VC.IS_DEL = 0
          LEFT JOIN CJ2_JOURNAL_AUTOUSERS JU1 ON JU1.DATE_DEL IS NULL AND JU1.CJ_ID = CJ.OBJ_ID AND JU1.USER_ID = :USER_ID AND JU1.ACCESS > 0
          LEFT JOIN CJ2_JOURNAL_USERS JU2 ON JU2.DATE_DEL IS NULL AND JU2.CJ_ID = CJ.OBJ_ID AND JU2.USER_ID = :USER_ID
          LEFT JOIN CJ2_JOURNAL_LESSONS JL ON JL.DATE_DEL IS NULL AND JL.CJ_ID = CJ.OBJ_ID AND JL.TEACHER_ID = :TEACHER_ID AND JL.LESSON_DATE >= DATEADD(-3 DAY TO CURRENT_DATE) AND JL.LESSON_DATE <= DATEADD(14 DAY TO CURRENT_DATE)
          LEFT JOIN CJ2_REPL_PROCESS P ON P.DATE_DEL IS NULL AND ((P.CJ_ID = CJ.OBJ_ID AND P.REPL_CJ_ID IS NULL) OR P.REPL_CJ_ID = CJ.OBJ_ID) AND P.REPL_PERSON_ID = :TEACHER_ID AND P.REPL_DATE >= DATEADD(-3 DAY TO CURRENT_DATE) AND P.REPL_DATE <= DATEADD(14 DAY TO CURRENT_DATE)
          WHERE CJ.JOURNAL_TYPE = 4 AND CJ.DATE_DEL IS NULL AND (JU1.OBJ_ID IS NOT NULL OR JU2.OBJ_ID IS NOT NULL OR JL.OBJ_ID IS NOT NULL OR P.OBJ_ID IS NOT NULL)
            AND CJ.IS_ENABLED = 1 AND CJ.YEAR_ID = :V$YEAR_ID
          ORDER BY 4
          INTO :CJ_ID, :CJ_TYPE_ID, :GRADE_ID, :GRADE_NAME, :V$TEACHER_ID
      DO
      BEGIN

          TAG_NAME = 'mi:items:mi';
          VAL = NULL;
          SUSPEND;

          TAG_NAME = 'mi:items:mi:id';
          VAL = CJ_ID;
          SUSPEND;

          TAG_NAME = 'mi:items:mi:type_id';
          VAL = CJ_TYPE_ID;
          SUSPEND;

          TAG_NAME = 'mi:items:mi:grade_id';
          VAL = GRADE_ID;
          SUSPEND;

          TAG_NAME = 'mi:items:mi:name';
          VAL = GRADE_NAME;
          SUSPEND;

          TAG_NAME = 'mi:items:mi:stream';
          VAL = 0;
          SUSPEND;

          -- Битовая маска с ролями, бит 0 = предметность, бит 1 = классность
          TAG_NAME = 'mi:items:mi:rmask';
          VAL = IIF(TEACHER_ID = V$TEACHER_ID, 1, 0);
          SUSPEND;

      END

  END

  -- Мероприятия - линейный список в 1 уровень. Эти без фильтра по году
  TAG_NAME = 'mi';
  VAL = NULL;
  SUSPEND;

  TAG_NAME = 'mi:name';
  VAL = 'Мероприятия';
  SUSPEND;

  TAG_NAME = 'mi:id';
  VAL = '10';
  SUSPEND;

  TAG_NAME = 'mi:type_id';
  VAL = '10';
  SUSPEND;

  TAG_NAME = 'mi:items';
  VAL = NULL;
  SUSPEND;

  TAG_NAME = 'mi:items::json&colon;array';
  VAL = '1';
  SUSPEND;

  -- Права доступа: админ/директор/завуч всегда, остальные когда явно назначено (сам журнал или конкретное мероприятие)

  FOR
      SELECT DISTINCT CJ.OBJ_ID, CJ.JOURNAL_TYPE, CJ.GRADE_ID, CJ.JOURNAL_NAME, CJ.TEACHER_ID
      FROM CJ2_JOURNAL CJ
      LEFT JOIN CJ2_JOURNAL_AUTOUSERS JU1 ON JU1.DATE_DEL IS NULL AND JU1.CJ_ID = CJ.OBJ_ID AND JU1.USER_ID = :USER_ID AND JU1.ACCESS > 0
      LEFT JOIN CJ2_JOURNAL_USERS JU2 ON JU2.DATE_DEL IS NULL AND JU2.CJ_ID = CJ.OBJ_ID AND JU2.USER_ID = :USER_ID
      LEFT JOIN CJ2_JOURNAL_LESSONS JL ON JL.DATE_DEL IS NULL AND JL.CJ_ID = CJ.OBJ_ID AND JL.TEACHER_ID = :TEACHER_ID AND JL.LESSON_DATE >= DATEADD(-3 DAY TO CURRENT_DATE) AND JL.LESSON_DATE <= DATEADD(14 DAY TO CURRENT_DATE)
      LEFT JOIN CJ2_REPL_PROCESS P ON P.DATE_DEL IS NULL AND ((P.CJ_ID = CJ.OBJ_ID AND P.REPL_CJ_ID IS NULL) OR P.REPL_CJ_ID = CJ.OBJ_ID) AND P.REPL_PERSON_ID = :TEACHER_ID AND P.REPL_DATE >= DATEADD(-3 DAY TO CURRENT_DATE) AND P.REPL_DATE <= DATEADD(14 DAY TO CURRENT_DATE)
      WHERE CJ.JOURNAL_TYPE IN (10, 11) AND CJ.DATE_DEL IS NULL AND (JU1.OBJ_ID IS NOT NULL OR JU2.OBJ_ID IS NOT NULL OR JL.OBJ_ID IS NOT NULL OR P.OBJ_ID IS NOT NULL)
        AND CJ.IS_ENABLED = 1
      ORDER BY 4
      INTO :CJ_ID, :CJ_TYPE_ID, :GRADE_ID, :GRADE_NAME, :V$TEACHER_ID
  DO
  BEGIN

      TAG_NAME = 'mi:items:mi';
      VAL = NULL;
      SUSPEND;

      TAG_NAME = 'mi:items:mi:id';
      VAL = CJ_ID;
      SUSPEND;

      TAG_NAME = 'mi:items:mi:type_id';
      VAL = CJ_TYPE_ID;
      SUSPEND;

      TAG_NAME = 'mi:items:mi:grade_id';
      VAL = GRADE_ID;
      SUSPEND;

      TAG_NAME = 'mi:items:mi:name';
      VAL = GRADE_NAME;
      SUSPEND;

      TAG_NAME = 'mi:items:mi:stream';
      VAL = 0;
      SUSPEND;

      -- Битовая маска с ролями, бит 0 = предметность, бит 1 = классность
      TAG_NAME = 'mi:items:mi:rmask';
      VAL = IIF(TEACHER_ID = V$TEACHER_ID, 1, 0);
      SUSPEND;

   END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_MISS_SET (
    I$PERSON_ID BIGINT,
    I$CJ_ID BIGINT,
    I$DATE_FROM DATE,
    I$N_FROM INTEGER,
    I$DATE_TO DATE,
    I$N_TO INTEGER,
    I$STATE SMALLINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    STUB INTEGER)
AS
declare variable V$CONTROL_ID bigint;
declare variable V$OLD_CONTROL bigint;
declare variable V$OLD_STATE bigint;
begin

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  -- Ставить можно пачкой, удалять только поштучно, но пока фильтр не стоит
  IF(I$STATE IS NULL AND I$DATE_TO > DATEADD(1 DAY TO I$DATE_FROM)) THEN EXCEPTION DATA_ERROR 'Снимать пропуски можно максимально за один день';

  -- Только из раздела пропуски
  IF(I$STATE IS NOT NULL AND NOT EXISTS(
    SELECT FIRST 1 1
    FROM CJ2_MARK_TYPE M
    WHERE M.MARK_TYPE_ID = :I$STATE AND M.IS_DEL = 0 AND M.PARENT_ID = 0
  )) THEN EXCEPTION DATA_ERROR 'Недопустимый код пропуска';

  -- Права доступа есть у руководителей ОУ и классного руководителя
  --IF(ACCESS_LEVEL = 0) THEN EXCEPTION DATA_ERROR 'Нет прав доступа к указанному журналу';

  -- Сначала поудалять все лишнее, где стоит неправильный контроль
  FOR
    SELECT DISTINCT C.CONTROL_ID, M.MARK_ID, M.MARK_TYPE_ID
    FROM CJ2_JOURNAL_LESSONS L
    JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.OBJ_ID = L.CJ_ID
    JOIN CJ2_CONTROL C ON C.DATE_DEL IS NULL AND C.CONTROL_TYPE_ID = 0 AND C.LESSON_ID = L.OBJ_ID
    LEFT JOIN CJ2_MARK M ON M.DATE_DEL IS NULL AND M.CONTROL_ID = C.CONTROL_ID AND M.STUDENT_ID = :I$PERSON_ID
    -- Записи где учащийся вообще был когда-либо в указанной группе
    JOIN LINKS LPG ON LPG.OBJ_ID = :I$PERSON_ID AND LPG.PARENT_ID = J.GRADE_ID
    -- ? не будет ли тут тормозов ?
    LEFT JOIN CJ2_MEMBER_MOVEMENTS(J.GRADE_ID, J.GRADE_TYPE_ID, :I$PERSON_ID) MV ON 1 = 1
    WHERE L.DATE_DEL IS NULL AND (L.CJ_ID = :I$CJ_ID OR :I$CJ_ID IS NULL) AND L.LESSON_DATE >= :I$DATE_FROM AND L.LESSON_DATE <= :I$DATE_TO
      AND ((L.LESSON_NUM >= :I$N_FROM AND L.LESSON_NUM <= :I$N_TO) OR :I$N_FROM IS NULL)
      -- Удалять пропуски можно за любую дату, ставить только там где учащийся присутствовал
      AND (:I$STATE IS NULL OR (MV.DATE_FROM <= :I$DATE_TO AND (MV.DATE_TO IS NULL OR MV.DATE_TO >= :I$DATE_FROM)))
    INTO :V$CONTROL_ID, :V$OLD_CONTROL, :V$OLD_STATE
  DO
  BEGIN
    IF(V$OLD_STATE IS NOT NULL AND COALESCE(V$OLD_STATE, -9999) <> COALESCE(I$STATE, -9999)) THEN
    begin
      UPDATE CJ2_MARK
      SET DATE_DEL = CURRENT_TIMESTAMP, USER_DEL = :I$USER_ID
      WHERE MARK_ID = :V$OLD_CONTROL;
    END
  END

  FOR
    SELECT DISTINCT C.CONTROL_ID, M.MARK_ID, M.MARK_TYPE_ID
    FROM CJ2_JOURNAL_LESSONS L
    JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.OBJ_ID = L.CJ_ID
    JOIN CJ2_CONTROL C ON C.DATE_DEL IS NULL AND C.CONTROL_TYPE_ID = 0 AND C.LESSON_ID = L.OBJ_ID
    LEFT JOIN CJ2_MARK M ON M.DATE_DEL IS NULL AND M.CONTROL_ID = C.CONTROL_ID AND M.STUDENT_ID = :I$PERSON_ID
    -- Записи где учащийся вообще был когда-либо в указанной группе
    JOIN LINKS LPG ON LPG.OBJ_ID = :I$PERSON_ID AND LPG.PARENT_ID = J.GRADE_ID
    -- ? не будет ли тут тормозов ?
    LEFT JOIN CJ2_MEMBER_MOVEMENTS(J.GRADE_ID, J.GRADE_TYPE_ID, :I$PERSON_ID) MV ON 1 = 1
    WHERE L.DATE_DEL IS NULL AND (L.CJ_ID = :I$CJ_ID OR :I$CJ_ID IS NULL) AND L.LESSON_DATE >= :I$DATE_FROM AND L.LESSON_DATE <= :I$DATE_TO
      AND ((L.LESSON_NUM >= :I$N_FROM AND L.LESSON_NUM <= :I$N_TO) OR :I$N_FROM IS NULL)
      -- Удалять пропуски можно за любую дату, ставить только там где учащийся присутствовал
      AND (:I$STATE IS NULL OR (MV.DATE_FROM <= :I$DATE_TO AND (MV.DATE_TO IS NULL OR MV.DATE_TO >= :I$DATE_FROM)))
    INTO :V$CONTROL_ID, :V$OLD_CONTROL, :V$OLD_STATE
  DO
  BEGIN
    IF(I$STATE IS NOT NULL AND COALESCE(V$OLD_STATE, -9999) <> COALESCE(I$STATE, -9999)) THEN
    BEGIN
      INSERT INTO CJ2_MARK
      (CONTROL_ID, STUDENT_ID, MARK_TYPE_ID, IS_USED, USER_ID, MARK_DATE)
      VALUES (:V$CONTROL_ID, :I$PERSON_ID, :I$STATE, 1, :I$USER_ID, CURRENT_DATE);
    END
  END

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_MOODLE_SUBSCRIBE RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(1000))
AS
declare variable V$CONTROL_ID bigint;
declare variable V$TEACHER_ID bigint;
declare variable V$GRADE_ID bigint;
declare variable V$EXT_ID varchar(100);
declare variable V$GRADE_NAME varchar(1000);
declare variable V$NAME1 varchar(200);
declare variable V$NAME2 varchar(200);
declare variable V$EMAIL varchar(400);
declare variable V$ESIA_ID varchar(100);
declare variable V$STUDENT_ID bigint;
declare variable V$DATE1 date;
declare variable V$DATE2 date;
begin

  TAG_NAME = 'tasks::json&colon;array';
  VAL = 1;
  SUSPEND;

  FOR
      SELECT C.CONTROL_ID, J.GRADE_ID, L.TEACHER_ID, C.EXT_ID, GC.CAPTION, V59.SVAL, V60.SVAL, V1180.SVAL, V3061.SVAL
      FROM CJ2_CONTROL C
      JOIN CJ2_JOURNAL_LESSONS L ON L.OBJ_ID = C.LESSON_ID AND L.DATE_DEL IS NULL
      JOIN CJ2_JOURNAL J ON J.OBJ_ID = L.CJ_ID AND J.DATE_DEL IS NULL AND J.IS_ENABLED = 1 AND J.JOURNAL_TYPE = 0
      LEFT JOIN OBJECT_CAPTION_GET(J.GRADE_ID) GC ON 1 = 1
      JOIN VALS V3061 ON V3061.OBJ_ID = L.TEACHER_ID AND V3061.PARAM_ID = 3061 AND V3061.IS_DEL = 0
      JOIN VALS V59 ON V59.OBJ_ID = L.TEACHER_ID AND V59.PARAM_ID = 59 AND V59.IS_DEL = 0
      JOIN VALS V60 ON V60.OBJ_ID = L.TEACHER_ID AND V60.PARAM_ID = 60 AND V60.IS_DEL = 0
      JOIN VALS V1180 ON V1180.OBJ_ID = L.TEACHER_ID AND V1180.PARAM_ID = 1180 AND V1180.IS_DEL = 0
      WHERE C.DATE_DEL IS NULL AND C.EXT_ASSIGNED IS NULL AND C.EXT_ID IS NOT NULL AND C.CONTROL_TYPE_ID = 8000
      INTO :V$CONTROL_ID, :V$GRADE_ID, :V$TEACHER_ID, :V$EXT_ID, :V$GRADE_NAME, :V$NAME1, :V$NAME2, :V$EMAIL, :V$ESIA_ID
  DO
  BEGIN
      TAG_NAME = 'tasks:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'tasks:r:cid';
      VAL = V$CONTROL_ID;
      SUSPEND;
      TAG_NAME = 'tasks:r:groupid';
      VAL = V$GRADE_ID;
      SUSPEND;
      TAG_NAME = 'tasks:r:name';
      VAL = V$GRADE_NAME;
      SUSPEND;

      TAG_NAME = 'tasks:r:teachers::json&colon;array';
      VAL = 1;
      SUSPEND;
      TAG_NAME = 'tasks:r:teachers:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'tasks:r:teachers:r:id';
      VAL = V$TEACHER_ID;
      SUSPEND;
      TAG_NAME = 'tasks:r:teachers:r:lastname';
      VAL = V$NAME1;
      SUSPEND;
      TAG_NAME = 'tasks:r:teachers:r:firstname';
      VAL = V$NAME2;
      SUSPEND;
      TAG_NAME = 'tasks:r:teachers:r:email';
      VAL = V$EMAIL;
      SUSPEND;
      TAG_NAME = 'tasks:r:teachers:r:esia_id';
      VAL = V$ESIA_ID;
      SUSPEND;

      TAG_NAME = 'tasks:r:students::json&colon;array';
      VAL = 1;
      SUSPEND;
      FOR
          SELECT L10.OBJ_ID, V55.SVAL, V56.SVAL, V3076.SVAL, V3060.SVAL
          FROM LINKS L10
          JOIN VALS V55 ON V55.OBJ_ID = L10.OBJ_ID AND V55.PARAM_ID = 55 AND V55.IS_DEL = 0
          JOIN VALS V56 ON V56.OBJ_ID = L10.OBJ_ID AND V56.PARAM_ID = 56 AND V56.IS_DEL = 0
          JOIN VALS V3076 ON V3076.OBJ_ID = L10.OBJ_ID AND V3076.PARAM_ID = 3076 AND V3076.IS_DEL = 0
          JOIN VALS V3060 ON V3060.OBJ_ID = L10.OBJ_ID AND V3060.PARAM_ID = 3060 AND V3060.IS_DEL = 0
          WHERE L10.PARENT_ID = :V$GRADE_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
          INTO :V$STUDENT_ID, :V$NAME1, :V$NAME2, :V$EMAIL, :V$ESIA_ID
      DO
      BEGIN
          TAG_NAME = 'tasks:r:students:r';
          VAL = NULL;
          SUSPEND;
          TAG_NAME = 'tasks:r:students:r:id';
          VAL = V$STUDENT_ID;
          SUSPEND;
          TAG_NAME = 'tasks:r:students:r:lastname';
          VAL = V$NAME1;
          SUSPEND;
          TAG_NAME = 'tasks:r:students:r:firstname';
          VAL = V$NAME2;
          SUSPEND;
          TAG_NAME = 'tasks:r:students:r:email';
          VAL = V$EMAIL;
          SUSPEND;
          TAG_NAME = 'tasks:r:students:r:esia_id';
          VAL = V$ESIA_ID;
          SUSPEND;
      END

      V$DATE1 = NULL;
      V$DATE2 = NULL;
      SELECT FIRST 1 V3071.VAL, V3072.VAL
      FROM LINKS L10
      JOIN LINKS LP9 ON LP9.OBJ_ID = L10.OBJ_ID AND LP9.PARENT_TYPE_ID IN (9, 187) AND LP9.DATE_DEL IS NULL
      JOIN VALD V3071 ON V3071.OBJ_ID = LP9.PARENT_ID AND V3071.PARAM_ID = 3071 AND V3071.IS_DEL = 0
      JOIN VALD V3072 ON V3072.OBJ_ID = LP9.PARENT_ID AND V3072.PARAM_ID = 3072 AND V3072.IS_DEL = 0
      WHERE L10.PARENT_ID = :V$GRADE_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      INTO :V$DATE1, :V$DATE2;

      TAG_NAME = 'tasks:r:courses::json&colon;array';
      VAL = 1;
      SUSPEND;
      TAG_NAME = 'tasks:r:courses:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'tasks:r:courses:r:id';
      VAL = V$EXT_ID;
      SUSPEND;
      TAG_NAME = 'tasks:r:courses:r:startdate';
      VAL = (SELECT VAL FROM DATE2ISO(:V$DATE1, 0));
      SUSPEND;
      TAG_NAME = 'tasks:r:courses:r:enddate';
      VAL = (SELECT VAL FROM DATE2ISO(:V$DATE2, 0));
      SUSPEND;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_MOODLE_SUBSCRIPTIONS RETURNS (
    CONTROL_ID BIGINT,
    GRADE_ID BIGINT,
    ASSN_ID VARCHAR(100),
    EXT_ID VARCHAR(100))
AS
declare variable V$DATE date;
begin

  -- Выборку делаем по датам валидности группы, с запасом в 7 дней после окончания курса

  FOR
      SELECT C.CONTROL_ID, J.GRADE_ID, C.EXT_ID, C.EXT_ASSIGNED
      FROM CJ2_CONTROL C
      JOIN CJ2_JOURNAL_LESSONS L ON L.OBJ_ID = C.LESSON_ID AND L.DATE_DEL IS NULL
      JOIN CJ2_JOURNAL J ON J.OBJ_ID = L.CJ_ID AND J.DATE_DEL IS NULL AND J.IS_ENABLED = 1 AND J.JOURNAL_TYPE = 0
      WHERE C.DATE_DEL IS NULL AND C.EXT_ASSIGNED IS NOT NULL AND C.EXT_ID IS NOT NULL AND C.CONTROL_TYPE_ID = 8000
      INTO :CONTROL_ID, :GRADE_ID, :EXT_ID, :ASSN_ID
  DO
  BEGIN

      V$DATE = NULL;
      SELECT FIRST 1 V3072.VAL
      FROM LINKS L10
      JOIN LINKS LP9 ON LP9.OBJ_ID = L10.OBJ_ID AND LP9.PARENT_TYPE_ID = 9 AND LP9.DATE_DEL IS NULL
      JOIN VALD V3072 ON V3072.OBJ_ID = LP9.PARENT_ID AND V3072.PARAM_ID = 3072 AND V3072.IS_DEL = 0
      WHERE L10.PARENT_ID = :GRADE_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      INTO :V$DATE;

      IF(V$DATE >= DATEADD(-7 DAY TO CURRENT_DATE)) THEN SUSPEND;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_PELIKAN_JOIN (
    I$LESSON_ID BIGINT,
    I$PERSON_ID BIGINT,
    I$MODE SMALLINT)
AS
begin


end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_PELIKAN_RSV RETURNS (
    LESSON_ID BIGINT,
    PREV_ROOM_ID BIGINT,
    LESSON_NAME VARCHAR(400),
    TYPE_ID INTEGER,
    TIME_START VARCHAR(40),
    TIME_STOP VARCHAR(40),
    CAMERAS VARCHAR(8000),
    PARTICIPANTS INTEGER)
AS
declare variable V$CJ_ID bigint;
declare variable V$LESSON_NUM integer;
declare variable V$LESSON_DATE date;
declare variable H integer;
declare variable M integer;
declare variable HS varchar(10);
declare variable MS varchar(10);
declare variable V$PERIOD_ID bigint;
declare variable V$DURATION smallint;
declare variable V$NAME varchar(400);
declare variable V$PATH varchar(1000);
declare variable V$T1 time;
declare variable V$T2 time;
declare variable V$GRADE_ID bigint;
begin

  TYPE_ID = 1;

  -- Новые уроки для регистрации - не позднее сегодняшнего дня и не старше чем +3 дня вперед
  FOR
    SELECT L.OBJ_ID, L.LESSON_DATE, L.LESSON_NUM, J.OBJ_ID, J.JOURNAL_NAME || ' ' || C.CAPTION, J.PERIOD_ID, J.DURATION, J.GRADE_ID
    FROM CJ2_JOURNAL_LESSONS L
    JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.OBJ_ID = L.CJ_ID
    LEFT JOIN OBJECT_CAPTION_GET(J.SUBJECT_ID) C ON 1 = 1
    WHERE L.DATE_DEL IS NULL AND (L.IS_PUBLISHED = 1 OR L.IS_COMPLETED = 1) AND L.LESSON_DATE >= CURRENT_DATE
      AND L.LESSON_DATE < DATEADD(3 DAY TO CURRENT_DATE) AND L.INST_ID IS NULL
    ORDER BY 2, 3
    INTO :LESSON_ID, :V$LESSON_DATE, :V$LESSON_NUM, :V$CJ_ID, :LESSON_NAME, :V$PERIOD_ID, :V$DURATION, :V$GRADE_ID
  DO
  BEGIN
    -- Выборка камер
    CAMERAS = '';
    FOR
      SELECT V3148.VAL, V3149.VAL
      FROM CJ2_LESSON_RES R
      JOIN LINKS LP95 ON LP95.OBJ_ID = R.RES_ID AND LP95.PARENT_TYPE_ID = 95 AND LP95.DATE_DEL IS NULL
      JOIN VALL V604 ON V604.OBJ_ID = LP95.PARENT_ID AND V604.PARAM_ID = 604 AND V604.IS_DEL = 0 AND V604.LISTVAL_ID IN (1816, 1931, 1933)
      JOIN VALS V3148 ON V3148.OBJ_ID = R.RES_ID AND V3148.PARAM_ID = 3148 AND V3148.IS_DEL = 0
      JOIN VALS V3149 ON V3149.OBJ_ID = R.RES_ID AND V3149.PARAM_ID = 3149 AND V3149.IS_DEL = 0
      WHERE R.DATE_DEL IS NULL AND R.LESSON_ID = :LESSON_ID
      INTO :V$NAME, :V$PATH
    DO
    BEGIN
      IF(CAMERAS <> '') THEN CAMERAS = CAMERAS || ASCII_CHAR(13);
      CAMERAS = CAMERAS || V$NAME || '|' || V$PATH;
    END

    IF(CAMERAS <> '') THEN
    BEGIN
      IF(V$DURATION IS NULL OR V$DURATION = 0) THEN V$DURATION = 45;

      LESSON_NAME = LESSON_NAME || ' ' || (SELECT RESULT FROM DATE2STR(:V$LESSON_DATE));

      -- Подсчет количества участников + 1 учитель + 1 запас
      SELECT COUNT(*) + 2
      FROM PERSON_MOVEMENTS M
      WHERE M.DATE_DEL IS NULL AND M.GROUP_ID = :V$GRADE_ID AND M.DATE_IN <= :V$LESSON_DATE AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :V$LESSON_DATE)
      INTO :PARTICIPANTS;

      TIME_START = (SELECT VAL FROM DATE2ISO(:V$LESSON_DATE, 0)) || ' ';
      TIME_STOP = TIME_START;

      IF(V$LESSON_NUM > 60) THEN
      BEGIN
        H = V$LESSON_NUM / 60;
        M = V$LESSON_NUM - H * 60;
        HS = H;
        MS = M;
        IF(H < 10) THEN HS = '0' || HS;
        IF(M < 10) THEN MS = '0' || MS;
        LESSON_NAME = LESSON_NAME || ' ' || HS || ':' || MS;

        TIME_START = TIME_START || HS || ':' || MS || ':00';

        V$LESSON_NUM = V$LESSON_NUM + V$DURATION;
        IF(V$LESSON_NUM > 1439) THEN V$LESSON_NUM = 1439; -- не позднее полуночи, чтобы не было перехода суток
        H = V$LESSON_NUM / 60;
        M = V$LESSON_NUM - H * 60;
        HS = H;
        MS = M;
        IF(H < 10) THEN HS = '0' || HS;
        IF(M < 10) THEN MS = '0' || MS;
        TIME_STOP = TIME_STOP || HS || ':' || MS || ':00';

      END
      ELSE
      BEGIN
        LESSON_NAME = LESSON_NAME || ' #' || V$LESSON_NUM;

        -- Смотрим время урока по расписанию, но сам день недели нас не волнует - сетка уроков от него не зависит
        H = EXTRACT(WEEKDAY FROM V$LESSON_DATE);
        IF(H = 0) THEN H = 6; ELSE H = H - 1;

        V$T1 = NULL;
        V$T2 = NULL;
        SELECT FIRST 1 V405.VAL, V406.VAL
        FROM SCHEDULE_ITEMS SI
        JOIN VALL V1341 ON V1341.OBJ_ID = SI.SCHEDULE_ID AND V1341.PARAM_ID = 1341 AND V1341.IS_DEL = 0 AND V1341.LISTVAL_ID = 2
        LEFT JOIN VALD V3120 ON V3120.OBJ_ID = SI.SCHEDULE_ID AND V3120.PARAM_ID = 3120 AND V3120.IS_DEL = 0
        LEFT JOIN VALD V3121 ON V3121.OBJ_ID = SI.SCHEDULE_ID AND V3121.PARAM_ID = 3121 AND V3121.IS_DEL = 0
        JOIN LINKS L60 ON L60.PARENT_ID = SI.SCHEDULE_ID AND L60.OBJ_TYPE_ID = 60 AND L60.DATE_DEL IS NULL
        JOIN VALI V404 ON V404.OBJ_ID = L60.OBJ_ID AND V404.PARAM_ID = 404 AND V404.IS_DEL = 0 AND V404.VAL = :V$LESSON_NUM
        JOIN VALT V405 ON V405.OBJ_ID = L60.OBJ_ID AND V405.PARAM_ID = 405 AND V405.IS_DEL = 0
        JOIN VALT V406 ON V406.OBJ_ID = L60.OBJ_ID AND V406.PARAM_ID = 406 AND V406.IS_DEL = 0
        WHERE SI.DATE_DEL IS NULL AND SI.CJ_ID = :V$CJ_ID -- AND SI.LESSON_NUM = :V$LESSON_NUM AND SI.WEEKDAY_NUM = :H
          AND (V3120.VAL IS NULL OR V3120.VAL <= :V$LESSON_DATE)
          AND (V3121.VAL IS NULL OR V3121.VAL >= :V$LESSON_DATE)
        INTO :V$T1, :V$T2;

        IF(V$T1 IS NULL OR V$T2 IS NULL) THEN LESSON_ID = NULL;
        ELSE
        BEGIN
          TIME_START = TIME_START || V$T1;
          TIME_STOP = TIME_STOP || V$T2;
        END
      END

      IF(LESSON_ID IS NOT NULL) THEN SUSPEND;
    END
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_PELIKAN_UNDO RETURNS (
    LESSON_ID BIGINT,
    ROOM_ID VARCHAR(400))
AS
begin

  FOR
    -- Удаленные мероприятия с датой не позднее текущей - старые уже неактуальны
    SELECT L.OBJ_ID, L.INST_ID
    FROM CJ2_JOURNAL_LESSONS L
    WHERE L.INST_ID IS NOT NULL AND L.LESSON_DATE >= CURRENT_DATE AND L.DATE_DEL IS NOT NULL
    -- Мероприятия из удаленных журналов
    UNION
    SELECT L.OBJ_ID, L.INST_ID
    FROM CJ2_JOURNAL_LESSONS L
    JOIN CJ2_JOURNAL J ON J.OBJ_ID = L.CJ_ID AND J.DATE_DEL IS NOT NULL
    WHERE L.INST_ID IS NOT NULL AND L.LESSON_DATE >= CURRENT_DATE
    -- Мероприятия с изменившимся временем
    UNION
    SELECT L.OBJ_ID, L.INST_ID
    FROM CJ2_JOURNAL_LESSONS L
    WHERE L.INST_ID IS NOT NULL AND L.LESSON_DATE >= CURRENT_DATE AND L.DATE_DEL IS NULL AND L.INST_MODIFIED <> 0
    INTO :LESSON_ID, :ROOM_ID
  DO
  BEGIN
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_PERSON_MISS_LIST (
    I$PERSON_ID BIGINT,
    I$DATE DATE,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(1000))
AS
declare variable V$DATE date;
declare variable V$CONTROL_ID bigint;
declare variable V$LESSON_NUM integer;
declare variable V$MARK bigint;
declare variable V$SUBJECT_ID bigint;
declare variable V$CJ_ID bigint;
declare variable V$OU_LICENCE_TYPE char(1);
begin

  IF(I$DATE IS NULL) THEN I$DATE = CURRENT_DATE;
  I$DATE = '01.' || EXTRACT(MONTH FROM I$DATE) || '.' || EXTRACT(YEAR FROM I$DATE);
  V$DATE = I$DATE;

  SELECT STATUS FROM OU_LICENCE_TYPE INTO :V$OU_LICENCE_TYPE;
  TAG_NAME = 'ou_type';
  VAL = V$OU_LICENCE_TYPE;
  SUSPEND;

  -- Идем по датам
  TAG_NAME = 'dates::json&colon;array';
  VAL = 1;
  SUSPEND;
  WHILE(EXTRACT(MONTH FROM V$DATE) = EXTRACT(MONTH FROM I$DATE) AND V$DATE <= CURRENT_DATE)
  DO
  BEGIN

    TAG_NAME = 'dates:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dates:r:date';
    VAL = (SELECT VAL FROM DATE2ISO(:V$DATE, 0));
    SUSPEND;

    -- Уроки по факту, где учащийся числился на указанную дату
    TAG_NAME = 'dates:r:lessons';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dates:r:lessons::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT CJL.OBJ_ID, C.CONTROL_ID, CJL.LESSON_NUM, J.SUBJECT_ID, M.MARK_TYPE_ID
      FROM CJ2_JOURNAL_LESSONS CJL
      JOIN CJ2_CONTROL C ON C.LESSON_ID = CJL.OBJ_ID AND C.DATE_DEL IS NULL AND C.CONTROL_TYPE_ID = 0
      JOIN CJ2_JOURNAL J ON J.OBJ_ID = CJL.CJ_ID
      LEFT JOIN CJ2_MARK M ON M.CONTROL_ID = C.CONTROL_ID AND M.STUDENT_ID = :I$PERSON_ID AND M.DATE_DEL IS NULL AND M.MARK_TYPE_ID >= 90 AND M.MARK_TYPE_ID <= 99
      WHERE CJL.DATE_DEL IS NULL AND CJL.LESSON_DATE = :V$DATE
      AND EXISTS(
        -- Учащийся есть сейчас или был в группе на указанную дату
        SELECT FIRST 1 1
        FROM LINKS LPG
        LEFT JOIN CJ2_MEMBER_MOVEMENTS(J.GRADE_ID, J.GRADE_TYPE_ID, :I$PERSON_ID) MV ON 1 = 1
        WHERE LPG.PARENT_ID = J.GRADE_ID AND LPG.OBJ_ID = :I$PERSON_ID AND (MV.DATE_FROM <= :V$DATE AND (MV.DATE_TO IS NULL OR MV.DATE_TO >= :V$DATE))
      )
      ORDER BY CJL.LESSON_NUM
      INTO :V$CJ_ID, :V$CONTROL_ID, :V$LESSON_NUM, :V$SUBJECT_ID, :V$MARK
    DO
    BEGIN
      TAG_NAME = 'dates:r:lessons:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'dates:r:lessons:r:id';
      VAL = V$CONTROL_ID;
      SUSPEND;
      TAG_NAME = 'dates:r:lessons:r:cj_id';
      VAL = V$CJ_ID;
      SUSPEND;
      TAG_NAME = 'dates:r:lessons:r:num';
      VAL = V$LESSON_NUM;
      SUSPEND;

      TAG_NAME = 'dates:r:lessons:r:subject';
      IF(V$OU_LICENCE_TYPE = 'D') THEN VAL = 'Гр';
      ELSE VAL = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$SUBJECT_ID));
      SUSPEND;

      -- Флаг присутствия
      TAG_NAME = 'dates:r:lessons:r:state';
      VAL = V$MARK;
      SUSPEND;
    END

    V$DATE = DATEADD(1 DAY TO V$DATE);

  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_PERSON_NAME (
    I$OBJ_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    TYPE_ID BIGINT,
    NAME_LAST VARCHAR(200),
    NAME_FIRST VARCHAR(200),
    NAME_MID VARCHAR(200),
    NAME_FULL VARCHAR(400))
AS
begin

  OBJ_ID = I$OBJ_ID;

  -- ФИО
  SELECT FIRST 1 O.TYPE_ID, V55.VAL, V56.VAL, V57.VAL
  FROM OBJECTS O
  JOIN VALS V55 ON V55.OBJ_ID = O.OBJ_ID AND V55.PARAM_ID IN (55, 59, 128, 827) AND V55.IS_DEL = 0
  JOIN VALS V56 ON V56.OBJ_ID = O.OBJ_ID AND V56.PARAM_ID IN (56, 60, 129, 828) AND V56.IS_DEL = 0
  LEFT JOIN VALS V57 ON V57.OBJ_ID = O.OBJ_ID AND V57.PARAM_ID IN (57, 61, 130, 829) AND V57.IS_DEL = 0
  WHERE O.OBJ_ID = :I$OBJ_ID
  INTO :TYPE_ID, :NAME_LAST, :NAME_FIRST, :NAME_MID;

  NAME_FULL = NAME_LAST || ' ' || NAME_FIRST || COALESCE(' ' || NAME_MID, '');

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_PRESENCE_SET (
    I$LESSON_ID BIGINT,
    I$STUDENT_ID BIGINT,
    I$STATE SMALLINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    MARK_ID BIGINT)
AS
declare variable V$CJ_ID bigint;
declare variable V$CONTROL_ID bigint;
declare variable V$ACCESS integer;
declare variable V$USER_ID bigint;
declare variable V$GRADE_ID bigint;
declare variable V$MARK bigint;
declare variable V$MARK_TYPE_ID bigint;
declare variable V$JOURNAL_TYPE smallint;
begin

  SELECT C.CONTROL_ID, L.CJ_ID, A.ACCESS_LEVEL, A.USER_ID, J.GRADE_ID, J.JOURNAL_TYPE
  FROM CJ2_CONTROL C
  JOIN CJ2_JOURNAL_LESSONS L ON L.OBJ_ID = C.LESSON_ID AND L.DATE_DEL IS NULL AND L.LESSON_DATE = CURRENT_DATE
  JOIN CJ2_JOURNAL J ON J.OBJ_ID = L.CJ_ID
  LEFT JOIN CJ2_JOURNAL_ACCESS(:I$USER_ID, L.CJ_ID) A ON 1 = 1
  WHERE C.LESSON_ID = :I$LESSON_ID AND C.DATE_DEL IS NULL AND C.CONTROL_TYPE_ID = 0
  INTO :V$CONTROL_ID, :V$CJ_ID, :V$ACCESS, :V$USER_ID, :V$GRADE_ID, :V$JOURNAL_TYPE;

  IF(V$CONTROL_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Урок не найден или не датирован текущим днем';
  IF(V$ACCESS = 0) THEN EXCEPTION DATA_ERROR 'У вас нет прав доступа для выставления пропусков';

  IF(I$STATE = 1 AND NOT EXISTS(
    SELECT 1
    FROM CJ2_MEMBER_MOVEMENTS(:V$GRADE_ID, NULL, :I$STUDENT_ID) M
    WHERE M.DATE_FROM <= CURRENT_DATE AND (M.DATE_TO IS NULL OR M.DATE_TO >= CURRENT_DATE)
  ))
  THEN
    EXCEPTION DATA_ERROR 'Ученик ' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$STUDENT_ID)) || ' не числится в классе на текущую дату';

  SELECT FIRST 1 M.MARK_ID, M.MARK_TYPE_ID
  FROM CJ2_MARK M
  WHERE M.DATE_DEL IS NULL AND M.STUDENT_ID = :I$STUDENT_ID AND M.CONTROL_ID = :V$CONTROL_ID AND M.MARK_TYPE_ID BETWEEN 1 AND 99
  INTO :V$MARK, V$MARK_TYPE_ID;

  -- Если ставится пропуск - не трогаем уже выставленный
  IF(I$STATE = 0 AND (V$MARK_TYPE_ID IS NULL OR V$MARK_TYPE_ID = 99)) THEN
  BEGIN
    -- Удаляем старую метку присутствия
    IF(V$MARK_TYPE_ID IS NOT NULL) THEN
    BEGIN
      UPDATE CJ2_MARK SET DATE_DEL = CURRENT_TIMESTAMP, USER_DEL = :V$USER_ID WHERE MARK_ID = :V$MARK;
    END
    -- Ставим новую метку отсутствия
    INSERT INTO CJ2_MARK
    (CONTROL_ID, STUDENT_ID, USER_ID, MARK_DATE, MARK_TYPE_ID)
    VALUES (:V$CONTROL_ID, :I$STUDENT_ID, :V$USER_ID, CURRENT_DATE, 91)
    RETURNING MARK_ID INTO :MARK_ID;
  END
  ELSE IF(I$STATE = 1 AND (V$MARK_TYPE_ID IS NULL OR V$MARK_TYPE_ID <> 99)) THEN
  BEGIN
    -- Удаляем старую метку отсутствия
    IF(V$MARK_TYPE_ID IS NOT NULL) THEN
    BEGIN
      UPDATE CJ2_MARK SET DATE_DEL = CURRENT_TIMESTAMP, USER_DEL = :V$USER_ID WHERE MARK_ID = :V$MARK;
    END
    -- Ставим присутствие - кроме общеобра
    IF(V$JOURNAL_TYPE <> 0) THEN
    BEGIN
      INSERT INTO CJ2_MARK
      (CONTROL_ID, STUDENT_ID, USER_ID, MARK_DATE, MARK_TYPE_ID)
      VALUES (:V$CONTROL_ID, :I$STUDENT_ID, :V$USER_ID, CURRENT_DATE, 99)
      RETURNING MARK_ID INTO :MARK_ID;
    END
  END
  ELSE MARK_ID = V$MARK;

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_PRINT_DATA (
    I$CJ_ID BIGINT,
    I$DATE_FROM DATE,
    I$DATE_TO DATE,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(1000))
AS
declare variable V$ACCESS integer;
declare variable V$TYPE integer;
declare variable V$GRADE_ID bigint;
declare variable V$GRADE_TYPE_ID bigint;
declare variable V$SUBJECT_ID bigint;
declare variable V$TEACHER_ID bigint;
declare variable S varchar(1000);
declare variable V$ID bigint;
declare variable V$LESSON_ID bigint;
declare variable V$LESSON_DATE date;
declare variable V$LESSON_NUM integer;
declare variable V$CONTROL_ID bigint;
declare variable V$CONTROL_TYPE_ID bigint;
declare variable V$MARK varchar(100);
declare variable V$DATE date;
declare variable V$THEME varchar(1000);
declare variable V$HOURS float;
declare variable V$LTD bigint;
declare variable V$LESSON_TYPE varchar(400);
declare variable V$STATUS varchar(10);
begin

  -- Есть ли у нас права доступа
  SELECT ACCESS_LEVEL FROM CJ2_JOURNAL_ACCESS(:I$USER_ID, :I$CJ_ID) INTO :V$ACCESS;

  IF(V$ACCESS NOT IN (1, 2)) THEN EXCEPTION DATA_ERROR 'Нет доступа или недостаточный уровень доступа к журналу';

  -- Общие данные по журналу
  SELECT J.JOURNAL_TYPE, J.GRADE_ID, J.GRADE_TYPE_ID, J.SUBJECT_ID, J.TEACHER_ID, J.JOURNAL_NAME
  FROM CJ2_JOURNAL J
  WHERE J.OBJ_ID = :I$CJ_ID
  INTO :V$TYPE, :V$GRADE_ID, :V$GRADE_TYPE_ID, :V$SUBJECT_ID, :V$TEACHER_ID, :S;

  TAG_NAME = 'journal:id';
  VAL = I$CJ_ID;
  SUSPEND;

  TAG_NAME = 'journal:ou_type';
  V$STATUS = (SELECT STATUS FROM OU_LICENCE_TYPE);
  VAL = V$STATUS;
  SUSPEND;

  TAG_NAME = 'journal:type';
  VAL = V$TYPE;
  SUSPEND;

  TAG_NAME = 'journal:type_name';
  IF(V$TYPE = 0) THEN VAL = 'Классный журнал';
  ELSE IF(V$TYPE = 1) THEN VAL = 'Журнал внеурочной деятельности';
  ELSE IF(V$TYPE = 2) THEN VAL = 'Журнал группы продленного дня';
  ELSE IF(V$TYPE = 3) THEN BEGIN
    IF(V$STATUS = 'P') THEN VAL = 'Журнал учебных занятий';
    ELSE VAL = 'Журнал дополнительного образования';
  END
  ELSE IF(V$TYPE IN (10, 11)) THEN VAL = 'Журнал мероприятий';
  ELSE EXCEPTION DATA_ERROR 'Неизвестный тип журнала';
  SUSPEND;

  TAG_NAME = 'journal:name';
  VAL = S;
  SUSPEND;

  TAG_NAME = 'journal:grade_id';
  VAL = V$GRADE_ID;
  SUSPEND;

  TAG_NAME = 'journal:grade_name';
  VAL = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$GRADE_ID));
  SUSPEND;

  TAG_NAME = 'journal:grade_type_id';
  VAL = V$GRADE_TYPE_ID;
  SUSPEND;

  TAG_NAME = 'journal:subject_id';
  VAL = V$SUBJECT_ID;
  SUSPEND;

  TAG_NAME = 'journal:subject_name';
  IF(V$SUBJECT_ID IS NULL) THEN VAL = ''; ELSE VAL = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$SUBJECT_ID));
  SUSPEND;

  TAG_NAME = 'journal:program_name';
  VAL = NULL;
  SELECT FIRST 1 C.CAPTION
  FROM VALR V
  LEFT JOIN OBJECT_CAPTION_GET(V.VAL) C ON 1 = 1
  WHERE V.OBJ_ID = :V$GRADE_ID AND V.PARAM_ID = 2823 AND V.IS_DEL = 0
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'journal:program_hours';
  VAL = '';
  SUSPEND;

  TAG_NAME = 'journal:teacher_id';
  VAL = V$TEACHER_ID;
  SUSPEND;

  -- Основной ответственный/предметник
  TAG_NAME = 'journal:teacher_name';
  VAL = NULL;
  SELECT V59.VAL || ' ' || V60.VAL || COALESCE(' ' || V61.VAL, '')
  FROM VALS V59
  JOIN VALS V60 ON V60.OBJ_ID = V59.OBJ_ID AND V60.PARAM_ID = 60 AND V60.IS_DEL = 0
  LEFT JOIN VALS V61 ON V61.OBJ_ID = V59.OBJ_ID AND V61.PARAM_ID = 61 AND V61.IS_DEL = 0
  WHERE V59.OBJ_ID = :V$TEACHER_ID AND V59.PARAM_ID = 59 AND V59.IS_DEL = 0
  INTO :VAL;
  IF(VAL IS NULL) THEN VAL = '';
  -- Для ГПД, ДО, ДПО берем список всех воспитателей/предподавателей
  FOR
    SELECT CAST(V59.VAL || ' ' || V60.VAL || COALESCE(' ' || V61.VAL, '') AS VARCHAR(400))
    FROM LINKS L186
    JOIN VALR V1609 ON V1609.OBJ_ID = L186.OBJ_ID AND V1609.PARAM_ID = 1609 AND V1609.IS_DEL = 0
    JOIN VALS V59 ON V59.OBJ_ID = V1609.VAL AND V59.PARAM_ID = 59 AND V59.IS_DEL = 0
    JOIN VALS V60 ON V60.OBJ_ID = V1609.VAL AND V60.PARAM_ID = 60 AND V60.IS_DEL = 0
    LEFT JOIN VALS V61 ON V61.OBJ_ID = V1609.VAL AND V61.PARAM_ID = 61 AND V61.IS_DEL = 0
    WHERE L186.PARENT_ID = :V$GRADE_ID AND L186.OBJ_TYPE_ID = 186 AND L186.DATE_DEL IS NULL
    ORDER BY 1
    INTO :S
  DO
  BEGIN
    IF(VAL <> '') THEN VAL = VAL || ', ';
    VAL = VAL || S;
  END
  SUSPEND;

  -- Текущий учебный год
  V$ID = NULL;
  S = NULL;

  SELECT V1236.LISTVAL_ID, R.VAL
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$ID, :S;

  IF(V$ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не задан текущий учебный период';

  TAG_NAME = 'journal:period_id';
  VAL = V$ID;
  SUSPEND;

  TAG_NAME = 'journal:period_name';
  VAL = S;
  SUSPEND;

  -- Даты начала и окончания занятий для ДПО
  TAG_NAME = 'journal:date_from';
  VAL = NULL;
  SELECT C.RESULT
  FROM VALD V
  LEFT JOIN DATE2STR(V.VAL) C ON 1 = 1
  WHERE V.OBJ_ID = :V$GRADE_ID AND V.PARAM_ID = 2959
  INTO VAL;
  SUSPEND;

  TAG_NAME = 'journal:date_to';
  VAL = NULL;
  SELECT C.RESULT
  FROM VALD V
  LEFT JOIN DATE2STR(V.VAL) C ON 1 = 1
  WHERE V.OBJ_ID = :V$GRADE_ID AND V.PARAM_ID = 2960
  INTO VAL;
  SUSPEND;

  -- Уроки и контроли
  TAG_NAME = 'lessons';
  VAL = NULL;
  SUSPEND;
  FOR
      SELECT CJL.OBJ_ID, CJL.LESSON_DATE, CJL.LESSON_NUM, C.CONTROL_ID, C.CONTROL_TYPE_ID, T.CONTROL_SHORTNAME,
        CJL.LESSON_THEME, CJL.TEACHER_ID, CJL.LESSON_HOURS, R.VAL, CJL.LESSON_TYPE_ID
      FROM CJ2_JOURNAL_LESSONS CJL
      JOIN CJ2_CONTROL C ON C.DATE_DEL IS NULL AND C.LESSON_ID = CJL.OBJ_ID -- AND (C.CONTROL_TYPE_ID = 0 OR C.IS_COMPLETED <> 0)
      JOIN CJ2_CONTROL_TYPE T ON T.CONTROL_TYPE_ID = C.CONTROL_TYPE_ID
      LEFT JOIN LISTVALS LV ON LV.LISTVAL_ID = CJL.LESSON_TYPE_ID
      LEFT JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
      WHERE CJL.DATE_DEL IS NULL AND CJL.CJ_ID = :I$CJ_ID AND (CJL.LESSON_DATE >= :I$DATE_FROM OR :I$DATE_FROM IS NULL)
          AND (CJL.LESSON_DATE <= :I$DATE_TO OR :I$DATE_TO IS NULL) AND CJL.IS_COMPLETED <> 0
      UNION
      -- вместо CONTROL_ID выдаем FINAL_TYPE_ID
      SELECT CJF.OBJ_ID, CJF.FINAL_DATE, 0, CJF.FINAL_TYPE, CJF.FINAL_TYPE, SUBSTRING(REPLACE(R.VAL, ' ', '') FROM 1 FOR 4),
        'Итоговая отметка ' || R.VAL, CJF.TEACHER_ID, 1, R.VAL, -1
      FROM CJ2_JOURNAL_FINALS CJF
      LEFT JOIN LISTVALS LV ON LV.LISTVAL_ID = CJF.FINAL_TYPE
      LEFT JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
      WHERE CJF.DATE_DEL IS NULL AND CJF.CJ_ID = :I$CJ_ID AND (CJF.FINAL_DATE >= :I$DATE_FROM OR :I$DATE_FROM IS NULL)
          AND (CJF.FINAL_DATE <= :I$DATE_TO OR :I$DATE_TO IS NULL)
      ORDER BY 2, 3, 5
      INTO :V$LESSON_ID, :V$LESSON_DATE, :V$LESSON_NUM, :V$CONTROL_ID, :V$CONTROL_TYPE_ID, :S, :V$THEME, :V$TEACHER_ID, :V$HOURS, :V$LESSON_TYPE, :V$LTD
  DO
  BEGIN
      TAG_NAME = 'lessons:control';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'lessons:control:lesson_id';
      VAL = V$LESSON_ID;
      SUSPEND;
      TAG_NAME = 'lessons:control:date';
      VAL = (SELECT VAL FROM DATE2ISO(:V$LESSON_DATE, 0));
      SUSPEND;
      TAG_NAME = 'lessons:control:num';
      VAL = V$LESSON_NUM;
      SUSPEND;
      TAG_NAME = 'lessons:control:id';
      VAL = V$CONTROL_ID;
      SUSPEND;
      TAG_NAME = 'lessons:control:lesson_type';
      VAL = V$LTD;
      SUSPEND;
      TAG_NAME = 'lessons:control:type_id';
      VAL = V$CONTROL_TYPE_ID;
      SUSPEND;
      IF(V$CONTROL_TYPE_ID = 0) THEN S = 'Ур.';
      ELSE IF(V$CONTROL_TYPE_ID = 9000) THEN S = 'Глс.';
      TAG_NAME = 'lessons:control:name';
      VAL = S;
      SUSPEND;
      TAG_NAME = 'lessons:control:teacher_name';
      VAL = (SELECT NAME_FULL FROM UT_PERSON_DESC(:V$TEACHER_ID));
      SUSPEND;
      TAG_NAME = 'lessons:control:theme';
      VAL = V$THEME;
      SUSPEND;
      TAG_NAME = 'lessons:control:hometask';
      VAL = (SELECT L.LESSON_HOMEWORK FROM CJ2_JOURNAL_LESSONS L WHERE L.OBJ_ID = :V$LESSON_ID AND :V$LESSON_NUM > 0);
      SUSPEND;
      TAG_NAME = 'lessons:control:hours';
      VAL = V$HOURS;
      SUSPEND;
      TAG_NAME = 'lessons:control:lt_name';
      VAL = V$LESSON_TYPE;
      SUSPEND;
  END

  -- Учащиеся
  TAG_NAME = 'students';
  VAL = NULL;
  SUSPEND;
  FOR
      SELECT DISTINCT MM.STUDENT_ID, V1.VAL || ' ' || V2.VAL
      FROM CJ2_MEMBER_MOVEMENTS(:V$GRADE_ID, :V$GRADE_TYPE_ID, NULL) MM
      JOIN VALS V1 ON V1.OBJ_ID = MM.STUDENT_ID AND V1.PARAM_ID IN (55, 59, 128, 827) AND V1.IS_DEL = 0
      JOIN VALS V2 ON V2.OBJ_ID = MM.STUDENT_ID AND V2.PARAM_ID IN (56, 60, 129, 828) AND V2.IS_DEL = 0
      ORDER BY 2
      INTO :V$ID, :S
  DO
  BEGIN
      TAG_NAME = 'students:student';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'students:student:id';
      VAL = V$ID;
      SUSPEND;
      TAG_NAME = 'students:student:name';
      VAL = S;
      SUSPEND;
      -- Список учебных периодов движения
      TAG_NAME = 'students:student:movements';
      VAL = NULL;
      SUSPEND;
  END

  -- Оценки, кроме замечаний
  TAG_NAME = 'marks';
  VAL = NULL;
  SUSPEND;
  FOR
      SELECT M.STUDENT_ID, M.CONTROL_ID, M.MARK_DATE, M.COMMENTS_TEXT, MT.MARK_SHORTNAME
      FROM CJ2_JOURNAL_LESSONS CJL
      JOIN CJ2_CONTROL C ON C.DATE_DEL IS NULL AND C.LESSON_ID = CJL.OBJ_ID -- AND (C.CONTROL_TYPE_ID = 0 OR C.IS_COMPLETED <> 0)
      JOIN CJ2_MARK M ON M.DATE_DEL IS NULL AND M.CONTROL_ID = C.CONTROL_ID
      JOIN CJ2_MARK_TYPE MT ON MT.MARK_TYPE_ID = M.MARK_TYPE_ID AND MT.MARK_TYPE_ID >= 0
      WHERE CJL.DATE_DEL IS NULL AND CJL.CJ_ID = :I$CJ_ID AND (CJL.LESSON_DATE >= :I$DATE_FROM OR :I$DATE_FROM IS NULL)
          AND (CJL.LESSON_DATE <= :I$DATE_TO OR :I$DATE_TO IS NULL) AND CJL.IS_COMPLETED <> 0
      UNION
      SELECT M.STUDENT_ID, CJF.FINAL_TYPE, M.MARK_DATE, M.COMMENTS_TEXT, MT.MARK_SHORTNAME
      FROM CJ2_JOURNAL_FINALS CJF
      JOIN CJ2_MARK M ON M.DATE_DEL IS NULL AND M.FINAL_ID = CJF.OBJ_ID
      JOIN CJ2_MARK_TYPE MT ON MT.MARK_TYPE_ID = M.MARK_TYPE_ID AND MT.MARK_TYPE_ID >= 0
      WHERE CJF.DATE_DEL IS NULL AND CJF.CJ_ID = :I$CJ_ID AND (CJF.FINAL_DATE >= :I$DATE_FROM OR :I$DATE_FROM IS NULL)
          AND (CJF.FINAL_DATE <= :I$DATE_TO OR :I$DATE_TO IS NULL)
      ORDER BY 3, 1, 2
      INTO :V$ID, :V$CONTROL_ID, :V$DATE, :S, :V$MARK
  DO
  BEGIN
      TAG_NAME = 'marks:mark';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'marks:mark:student_id';
      VAL = V$ID;
      SUSPEND;
      TAG_NAME = 'marks:mark:control_id';
      VAL = V$CONTROL_ID;
      SUSPEND;
      TAG_NAME = 'marks:mark:date';
      VAL = (SELECT VAL FROM DATE2ISO(:V$DATE, 0));
      SUSPEND;
      TAG_NAME = 'marks:mark:value';
      VAL = V$MARK;
      SUSPEND;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_PTP_APPROVE (
    I$OBJ_ID BIGINT,
    I$DATE DATE,
    I$NUM VARCHAR(200),
    I$USER_ID VARCHAR(40))
AS
declare variable V$STATE smallint;
declare variable V$CJ_ID bigint;
begin

  -- ОП доступны только администратору, руководителям и завучам
  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;
  IF(NOT EXISTS(
    SELECT FIRST 1 1
    FROM USERS U
    WHERE U.USER_ID = :I$USER_ID AND U.DATE_DEL IS NULL AND U.IS_BLOCKED = 0 AND U.USER_TYPE IN (1, 5, 6)
  )) THEN EXCEPTION DATA_ERROR 'Недостаточно прав доступа для утверждения ПТП, требуется уровень администратор, директор или завуч';

  -- Дата должна попадать в текущий учебный год
  -- !!!

  SELECT FIRST 1 P.APPROVAL_STATE, P.CJ_ID
  FROM CJ2_JOURNAL_PTP P
  WHERE P.DATE_DEL IS NULL AND P.OBJ_ID = :I$OBJ_ID
  INTO :V$STATE, :V$CJ_ID;

  IF(V$STATE IS NULL) THEN EXCEPTION DATA_ERROR 'Назначение ПТП не найдено';

  IF(V$STATE = 2) THEN EXIT; -- уже утвердили
  IF(V$STATE = 0) THEN EXCEPTION DATA_ERROR 'ПТП был переведен в статус проекта, утверждение невозможно';
  IF(V$STATE > 2) THEN EXCEPTION DATA_ERROR 'ПТП был переведен в статус недействительного, утверждение невозможно';

  -- Снимаем утверждение того что было раньше
  UPDATE CJ2_JOURNAL_PTP
  SET APPROVAL_STATE = 3
  WHERE DATE_DEL IS NULL AND CJ_ID = :V$CJ_ID AND APPROVAL_STATE = 2;

  -- Утверждаем указанный ПТП
  UPDATE CJ2_JOURNAL_PTP
  SET APPROVAL_STATE = 2, APP_ORDER_DATE = :I$DATE, APP_ORDER_NUM = :I$NUM
  WHERE OBJ_ID = :I$OBJ_ID;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_PTP_APPROVE_HAS (
    I$USER_ID VARCHAR(40))
RETURNS (
    CAN_APPROVE SMALLINT,
    HAS_PTP SMALLINT)
AS
declare variable V$STATUS varchar(10);
begin

  V$STATUS = (SELECT STATUS FROM OU_LICENCE_TYPE);

  CAN_APPROVE = 0;
  HAS_PTP = 0;

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;
  SELECT FIRST 1 1
  FROM USERS U
  WHERE U.USER_ID = :I$USER_ID AND U.DATE_DEL IS NULL AND U.IS_BLOCKED = 0 AND U.USER_TYPE IN (1, 5, 6)
  INTO :CAN_APPROVE;

  -- Ограничиваем только общеобразовательные и ВД, плюс журналы ДПО
  SELECT COUNT(*)
  FROM CJ2_JOURNAL_PTP P
  JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.OBJ_ID = P.CJ_ID AND (J.JOURNAL_TYPE IN (0, 1) OR (:V$STATUS = 'P' AND J.JOURNAL_TYPE = 3))
  WHERE P.DATE_DEL IS NULL AND P.APPROVAL_STATE = 1
  INTO :HAS_PTP;

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_PTP_APPROVE_LIST (
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(1000))
AS
declare variable V$STATUS varchar(10);
declare variable V$OP_ID bigint;
declare variable V$STAGE_ID bigint;
declare variable V$OBJ_ID bigint;
declare variable V$PTP_ID bigint;
declare variable V$CJ_ID bigint;
declare variable V$PLAN_ID bigint;
declare variable V$SUBJECT_ID bigint;
declare variable V$GRADE_ID bigint;
declare variable V$STAGE_INDEX bigint;
declare variable V$PLAN_HOURS integer;
declare variable V$LEVEL integer;
declare variable S varchar(1000);
declare variable S2 varchar(1000);
declare variable S3 varchar(1000);
begin

  -- ОП доступны только администратору, руководителям и завучам
  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;
  IF(NOT EXISTS(
    SELECT FIRST 1 1
    FROM USERS U
    WHERE U.USER_ID = :I$USER_ID AND U.DATE_DEL IS NULL AND U.IS_BLOCKED = 0 AND U.USER_TYPE IN (1, 5, 6)
  )) THEN EXCEPTION DATA_ERROR 'Недостаточно прав доступа для утверждения ПТП, требуется уровень администратор, директор или завуч';

  V$STATUS = (SELECT STATUS FROM OU_LICENCE_TYPE);

  TAG_NAME = 'op::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
    SELECT L57.OBJ_ID, C.CAPTION
    FROM LINKS L2
    JOIN LINKS L69 ON L69.PARENT_ID = L2.OBJ_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL
    JOIN VALL V2450 ON V2450.OBJ_ID = L69.OBJ_ID AND V2450.PARAM_ID = 2450 AND V2450.IS_DEL = 0 AND V2450.LISTVAL_ID IN (11385, 11387) -- только основное общее и СПО
    JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
    JOIN VALL V1832 ON V1832.OBJ_ID = L57.OBJ_ID AND V1832.PARAM_ID = 1832 AND V1832.IS_DEL = 0
    JOIN LISTVALS LV1832 ON LV1832.LISTVAL_ID = V1832.LISTVAL_ID
    LEFT JOIN OBJECT_CAPTION_GET(L57.OBJ_ID) C ON 1 = 1
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND EXISTS(
      SELECT FIRST 1 1
      FROM LINKS L400
      -- не-ВД
      JOIN VALL V3022 ON V3022.OBJ_ID = L400.OBJ_ID AND V3022.PARAM_ID = 3022 AND V3022.IS_DEL = 0 AND V3022.LISTVAL_ID = 3
      -- действующий
      JOIN VALL V3013 ON V3013.OBJ_ID = L400.OBJ_ID AND V3013.PARAM_ID = 3013 AND V3013.IS_DEL = 0 AND V3013.LISTVAL_ID = 11715
      WHERE L400.PARENT_ID = L57.OBJ_ID AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL
    )
    ORDER BY LV1832.SORT_ORDER, C.CAPTION
    INTO :V$OP_ID, :S
  DO
  BEGIN
    TAG_NAME = 'op:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'op:r:id';
    VAL = V$OP_ID;
    SUSPEND;
    TAG_NAME = 'op:r:name';
    VAL = S;
    SUSPEND;

    TAG_NAME = 'op:r:stages::json&colon;array';
    VAL = '1';
    SUSPEND;
    FOR
      SELECT DISTINCT LV.LISTVAL_ID, R.VAL
      FROM LINKS L400
      -- не-ВД
      JOIN VALL V3022 ON V3022.OBJ_ID = L400.OBJ_ID AND V3022.PARAM_ID = 3022 AND V3022.IS_DEL = 0 AND V3022.LISTVAL_ID = 3
      JOIN LINKS L54 ON L54.PARENT_ID = L400.OBJ_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
      JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
      -- замена кодов для адаптированных УП ? надо или нет ?
      JOIN LISTVALS LV ON LV.LISTVAL_ID = V381.LISTVAL_ID
      JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
      WHERE L400.PARENT_ID = :V$OP_ID AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL
      ORDER BY LV.COST
      INTO :V$STAGE_ID, :S
    DO
    BEGIN
      TAG_NAME = 'op:r:stages:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'op:r:stages:r:id';
      VAL = V$STAGE_ID;
      SUSPEND;
      TAG_NAME = 'op:r:stages:r:name';
      VAL = S;
      SUSPEND;

      -- Коррекция индексов ПТП длля ОВЗ
      V$STAGE_INDEX = V$STAGE_ID;
      IF(V$STAGE_ID >= 12942) THEN
      BEGIN
        SELECT FIRST 1 LV2.LISTVAL_ID
        FROM LISTVALS LV
        JOIN LISTVALS LV2 ON LV2.PARENT_ID = 2141 AND LV2.COST = LV.COST
        WHERE LV.LISTVAL_ID = :V$STAGE_ID
        INTO :V$STAGE_INDEX;
      END

      -- Возвращаем список ПТП в разрезе групп
      -- Если журнал прикреплен со ссылкой на ГУП - выдаем в соответствующем УП. Если нет, то выдаем во всех УП где вообще заведены ГУП или проекты ГУП
      TAG_NAME = 'op:r:stages:r:ptp::json&colon;array';
      VAL = '1';
      SUSPEND;
      FOR
        SELECT P.OBJ_ID, PX.OBJ_ID, PX.OBJ_NAME, GC.CAPTION, GS.CAPTION, J.OBJ_ID, J.REF_ID, J.SUBJECT_ID, J.GRADE_ID, J.HOURS, PX.LEVEL_NUM
        FROM CJ2_JOURNAL J
        JOIN CJ2_JOURNAL_PTP P ON P.DATE_DEL IS NULL AND P.CJ_ID = J.OBJ_ID AND P.APPROVAL_STATE = 1
        JOIN PTP PX ON PX.OBJ_ID = P.PTP_ID
        -- Первая цепочка сверки для обычных журналов
        LEFT JOIN LINKS L179 ON L179.OBJ_ID = J.GRADE_ID AND L179.PARENT_TYPE_ID = 2 AND L179.DATE_DEL IS NULL
        LEFT JOIN LINKS LP54 ON LP54.OBJ_ID = L179.EXT_OBJ_ID AND LP54.PARENT_TYPE_ID = 54 AND LP54.DATE_DEL IS NULL
        LEFT JOIN VALL V381 ON V381.OBJ_ID = LP54.PARENT_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
        LEFT JOIN LINKS LP400 ON LP400.OBJ_ID = LP54.PARENT_ID AND LP400.PARENT_TYPE_ID = 400 AND LP400.DATE_DEL IS NULL
        LEFT JOIN LINKS LP57 ON LP57.OBJ_ID = LP400.PARENT_ID AND LP57.PARENT_TYPE_ID = 57 AND LP57.DATE_DEL IS NULL
        -- Вторая цепочка для потоковых
        LEFT JOIN LINKS LP57X ON LP57X.OBJ_ID = J.REF_ID AND LP57X.PARENT_TYPE_ID = 57 AND LP57X.DATE_DEL IS NULL
        LEFT JOIN OBJECT_CAPTION_GET(J.GRADE_ID) GC ON 1 = 1
        LEFT JOIN OBJECT_CAPTION_GET(J.SUBJECT_ID) GS ON 1 = 1
        WHERE J.DATE_DEL IS NULL AND J.JOURNAL_TYPE = 0 AND (J.STAGE_INDEX = :V$STAGE_ID OR J.STAGE_INDEX = :V$STAGE_INDEX)
          AND ((LP57.PARENT_ID IS NULL AND J.REF_ID IS NULL) OR LP57.PARENT_ID = :V$OP_ID OR LP57X.PARENT_ID = :V$OP_ID)
        ORDER BY 2, 4, 5
        INTO :V$OBJ_ID, :V$PTP_ID, :S, :S2, :S3, :V$CJ_ID, :V$PLAN_ID, :V$SUBJECT_ID, :V$GRADE_ID, :V$PLAN_HOURS, :V$LEVEL
      DO
      BEGIN
        TAG_NAME = 'op:r:stages:r:ptp:r';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'op:r:stages:r:ptp:r:id';
        VAL = V$OBJ_ID;
        SUSPEND;
        TAG_NAME = 'op:r:stages:r:ptp:r:name';
        VAL = S;
        SUSPEND;
        TAG_NAME = 'op:r:stages:r:ptp:r:group_id';
        VAL = V$GRADE_ID;
        SUSPEND;
        TAG_NAME = 'op:r:stages:r:ptp:r:group_name';
        VAL = S2;
        SUSPEND;
        TAG_NAME = 'op:r:stages:r:ptp:r:subject_name';
        VAL = S3;
        SUSPEND;
        TAG_NAME = 'op:r:stages:r:ptp:r:teacher_name';
        VAL = (SELECT CAPTION FROM CJ2_JOURNAL J LEFT JOIN OBJECT_CAPTION_GET(J.TEACHER_ID) C ON 1 = 1 WHERE J.OBJ_ID = :V$CJ_ID);
        SUSPEND;
        TAG_NAME = 'op:r:stages:r:ptp:r:hours_ptp';
        VAL = (SELECT PTP_HOURS FROM PTP WHERE OBJ_ID = :V$PTP_ID);
        SUSPEND;
        TAG_NAME = 'op:r:stages:r:ptp:r:hours_op';
        VAL = V$PLAN_HOURS;
        SUSPEND;
        TAG_NAME = 'op:r:stages:r:ptp:r:version';
        VAL = V$LEVEL;
        SUSPEND;
      END
    END
  END

  -- Журналы вне УП
  IF(EXISTS(
    SELECT FIRST 1 1
    FROM CJ2_JOURNAL J
    JOIN CJ2_JOURNAL_PTP P ON P.DATE_DEL IS NULL AND P.CJ_ID = J.OBJ_ID AND P.APPROVAL_STATE = 1
    LEFT JOIN LINKS LP57 ON LP57.OBJ_ID = J.REF_ID AND LP57.PARENT_TYPE_ID = 57 AND LP57.DATE_DEL IS NULL
    WHERE J.DATE_DEL IS NULL AND LP57.PARENT_ID IS NULL AND (J.JOURNAL_TYPE IN (0, 1) OR (:V$STATUS = 'P' AND J.JOURNAL_TYPE = 3))
  )) THEN
  BEGIN
    TAG_NAME = 'op:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'op:r:id';
    VAL = 0;
    SUSPEND;
    TAG_NAME = 'op:r:name';
    VAL = 'Журналы без привязки к конкретному УП';
    SUSPEND;

    TAG_NAME = 'op:r:stages::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT DISTINCT COALESCE(J.STAGE_INDEX, 0), C.VAL
      FROM CJ2_JOURNAL J
      JOIN CJ2_JOURNAL_PTP P ON P.DATE_DEL IS NULL AND P.CJ_ID = J.OBJ_ID AND P.APPROVAL_STATE = 1
      LEFT JOIN LINKS LP57 ON LP57.OBJ_ID = J.REF_ID AND LP57.PARENT_TYPE_ID = 57 AND LP57.DATE_DEL IS NULL
      LEFT JOIN LISTVAL_TEXT(J.STAGE_INDEX) C ON 1 = 1
      WHERE J.DATE_DEL IS NULL AND LP57.PARENT_ID IS NULL AND (J.JOURNAL_TYPE IN (0, 1) OR (:V$STATUS = 'P' AND J.JOURNAL_TYPE = 3))
      ORDER BY J.STAGE_INDEX
      INTO :V$STAGE_ID, :S
    DO
    BEGIN
      TAG_NAME = 'op:r:stages:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'op:r:stages:r:id';
      VAL = V$STAGE_ID;
      SUSPEND;
      TAG_NAME = 'op:r:stages:r:name';
      IF(V$STAGE_ID = 0) THEN VAL = 'Все обучение'; ELSE VAL = S;
      SUSPEND;

      -- Возвращаем список ПТП в разрезе групп
      TAG_NAME = 'op:r:stages:r:ptp::json&colon;array';
      VAL = '1';
      SUSPEND;
      FOR
        SELECT P.OBJ_ID, PX.OBJ_ID, PX.OBJ_NAME, GC.CAPTION, GS.CAPTION, J.OBJ_ID, J.REF_ID, J.SUBJECT_ID, J.GRADE_ID, J.HOURS
        FROM CJ2_JOURNAL J
        JOIN CJ2_JOURNAL_PTP P ON P.DATE_DEL IS NULL AND P.CJ_ID = J.OBJ_ID AND P.APPROVAL_STATE = 1
        JOIN PTP PX ON PX.OBJ_ID = P.PTP_ID
        LEFT JOIN LINKS LP57 ON LP57.OBJ_ID = J.REF_ID AND LP57.PARENT_TYPE_ID = 57 AND LP57.DATE_DEL IS NULL
        LEFT JOIN OBJECT_CAPTION_GET(J.GRADE_ID) GC ON 1 = 1
        LEFT JOIN OBJECT_CAPTION_GET(J.SUBJECT_ID) GS ON 1 = 1
        WHERE J.DATE_DEL IS NULL AND (J.STAGE_INDEX = :V$STAGE_ID OR (J.STAGE_INDEX IS NULL AND :V$STAGE_ID = 0)) AND LP57.PARENT_ID IS NULL
          AND (J.JOURNAL_TYPE IN (0, 1) OR (:V$STATUS = 'P' AND J.JOURNAL_TYPE = 3))
        ORDER BY 2, 4, 5
        INTO :V$OBJ_ID, :V$PTP_ID, :S, :S2, :S3, :V$CJ_ID, :V$PLAN_ID, :V$SUBJECT_ID, :V$GRADE_ID, :V$PLAN_HOURS
      DO
      BEGIN
        TAG_NAME = 'op:r:stages:r:ptp:r';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'op:r:stages:r:ptp:r:id';
        VAL = V$OBJ_ID;
        SUSPEND;
        TAG_NAME = 'op:r:stages:r:ptp:r:name';
        VAL = S;
        SUSPEND;
        TAG_NAME = 'op:r:stages:r:ptp:r:group_id';
        VAL = V$GRADE_ID;
        SUSPEND;
        TAG_NAME = 'op:r:stages:r:ptp:r:group_name';
        VAL = S2;
        SUSPEND;
        TAG_NAME = 'op:r:stages:r:ptp:r:subject_name';
        IF(V$SUBJECT_ID IS NULL) THEN VAL = ''; ELSE VAL = S3;
        SUSPEND;
        TAG_NAME = 'op:r:stages:r:ptp:r:teacher_name';
        -- Корректируем ФИО преподавателей
        VAL = (SELECT CAPTION FROM CJ2_JOURNAL J LEFT JOIN OBJECT_CAPTION_GET(J.TEACHER_ID) C ON 1 = 1 WHERE J.OBJ_ID = :V$CJ_ID AND J.TEACHER_ID IS NOT NULL);
        SUSPEND;
        TAG_NAME = 'op:r:stages:r:ptp:r:hours_ptp';
        VAL = (SELECT PTP_HOURS FROM PTP WHERE OBJ_ID = :V$PTP_ID);
        SUSPEND;
        TAG_NAME = 'op:r:stages:r:ptp:r:hours_op';
        VAL = V$PLAN_HOURS;
        SUSPEND;
      END
    END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_PTP_ASSIGN (
    I$CJ_ID BIGINT,
    I$PTP_ID BIGINT)
AS
declare variable V$IS_APPROVED smallint;
declare variable V$PTP_ID bigint;
begin

  -- Если ПТП уже утвержден, то менять можно только если нет проведенных уроков
  V$IS_APPROVED = 0;
  SELECT FIRST 1 1, L.PTP_ID
  FROM CJ2_JOURNAL_PTP L
  WHERE L.CJ_ID = :I$CJ_ID AND L.DATE_DEL IS NULL AND L.APPROVAL_STATE = 2
  INTO :V$IS_APPROVED, :V$PTP_ID;

  -- Уже связан и утвержден
  IF(I$PTP_ID = V$PTP_ID) THEN EXIT;

  IF(V$IS_APPROVED = 1) THEN
  BEGIN
    IF(EXISTS(
      SELECT FIRST 1 1
      FROM CJ2_JOURNAL_LESSONS L
      WHERE L.DATE_DEL IS NULL AND L.CJ_ID = :I$CJ_ID AND L.LESSON_PTP_ID IS NOT NULL
    ))
    THEN EXCEPTION DATA_ERROR 'Нельзя менять ПТП, если уже внесены уроки по другому ПТП';
  END

  IF(EXISTS(
    SELECT FIRST 1 1
    FROM CJ2_JOURNAL_PTP L
    WHERE L.CJ_ID = :I$CJ_ID AND L.DATE_DEL IS NULL AND L.APPROVAL_STATE <> 3 AND L.PTP_ID = :I$PTP_ID
  ))
  THEN EXIT;

  -- Не удаляем, а ставим статус не действующий
  UPDATE CJ2_JOURNAL_PTP
  SET APPROVAL_STATE = 3
  WHERE CJ_ID = :I$CJ_ID AND DATE_DEL IS NULL AND APPROVAL_STATE <> 3;

  -- Вести сразу в статусе к утверждению
  IF(I$PTP_ID IS NOT NULL) THEN
  BEGIN
    INSERT INTO CJ2_JOURNAL_PTP
    (CJ_ID, PTP_ID, APPROVAL_STATE)
    VALUES (:I$CJ_ID, :I$PTP_ID, 1);
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_PTP_ASSIGN_CJ (
    I$PTP_ID BIGINT,
    I$CJ_ID BIGINT,
    I$USER_ID VARCHAR(40),
    I$DELETED SMALLINT,
    I$STATE SMALLINT)
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$USER_ID bigint;
declare variable V$USER_TYPE integer;
declare variable V$TEACHER_ID bigint;
declare variable V$LEVEL_ID bigint;
declare variable V$SUBJECT_ID bigint;
declare variable V$OWNER_ID bigint;
declare variable V$CJ_ID bigint;
declare variable V$JOURNAL_OWNER bigint;
declare variable V$STATE bigint;
declare variable V$LESSON_ID bigint;
declare variable V$PLESSON_ID bigint;
declare variable V$JT integer;
declare variable V$STATUS varchar(10);
begin

  -- Уровень доступа пользователя
  IF(I$USER_ID = 'Веб-администратор') THEN V$USER_ID = 1; ELSE V$USER_ID = CAST(I$USER_ID AS BIGINT);

  SELECT U.USER_TYPE, U.OBJ_ID
  FROM USERS U
  WHERE U.USER_ID = :V$USER_ID AND U.DATE_DEL IS NULL AND U.IS_BLOCKED = 0
  INTO :V$USER_TYPE, :V$TEACHER_ID;

  V$STATUS = (SELECT STATUS FROM OU_LICENCE_TYPE);
                                  
  SELECT FIRST 1 P.LEVEL_ID, P.SUBJECT_ID, P.OWNER_ID
  FROM PTP P
  WHERE P.DATE_DEL IS NULL AND P.OBJ_ID = :I$PTP_ID
  INTO :V$LEVEL_ID, :V$SUBJECT_ID, :V$OWNER_ID;

  SELECT FIRST 1 J.OBJ_ID, J.TEACHER_ID, J.JOURNAL_TYPE
  FROM CJ2_JOURNAL J
  WHERE J.DATE_DEL IS NULL AND J.OBJ_ID = :I$CJ_ID
  INTO :V$CJ_ID, :V$JOURNAL_OWNER, :V$JT;

  IF(V$CJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не найден журнал';

  IF(V$JOURNAL_OWNER <> V$TEACHER_ID AND V$USER_TYPE NOT IN (1, 5, 6)) THEN EXCEPTION DATA_ERROR 'Только административный сотрудник может управлять чужими журналами';

  IF(I$DELETED = 1) THEN
  BEGIN

      -- Удалять можно только если нет проведенных уроков, обрабатываем рекурсивно
      FOR
        SELECT PL.OBJ_ID, PL.PARENT_LESSON_ID, IIF(L.OBJ_ID IS NULL, 0, 1)
        FROM PTP_LESSONS PL
        LEFT JOIN CJ2_JOURNAL_LESSONS L ON L.DATE_DEL IS NULL AND L.CJ_ID = :I$CJ_ID AND L.LESSON_PTP_ID = PL.OBJ_ID
        WHERE PL.DATE_DEL IS NULL AND PL.PTP_ID = :I$PTP_ID
        INTO :V$LESSON_ID, :V$PLESSON_ID, :V$STATE
      DO
      BEGIN
        -- Урок, напрямую связанный с данным уроком в ПТП
        IF(V$STATE = 1) THEN EXCEPTION DATA_ERROR 'Нельзя удалять прикрепление ПТП, если были проведены уроки с участием этого плана';

        -- И вверх по дереву наследования
        WHILE(V$PLESSON_ID IS NOT NULL) DO
        BEGIN
          V$LESSON_ID = V$PLESSON_ID;
          V$PLESSON_ID = NULL;
          V$STATE = 0;

          SELECT PL.PARENT_LESSON_ID, IIF(L.OBJ_ID IS NULL, 0, 1)
          FROM PTP_LESSONS PL
          LEFT JOIN CJ2_JOURNAL_LESSONS L ON L.DATE_DEL IS NULL AND L.CJ_ID = :I$CJ_ID AND L.LESSON_PTP_ID = PL.OBJ_ID
          WHERE PL.DATE_DEL IS NULL AND PL.OBJ_ID = :V$LESSON_ID
          INTO :V$PLESSON_ID, :V$STATE;

          IF(V$STATE = 1) THEN EXCEPTION DATA_ERROR 'Нельзя удалять прикрепление ПТП, если были проведены уроки с участием этого плана';
        END
      END

      UPDATE CJ2_JOURNAL_PTP P
      SET P.DATE_DEL = CURRENT_TIMESTAMP
      WHERE P.DATE_DEL IS NULL AND P.PTP_ID = :I$PTP_ID AND P.CJ_ID = :I$CJ_ID;

  END
  ELSE
  BEGIN

      -- Если есть другой ПТП, прикрепленный к журналу - пока просто ругаемся
      -- по идее надо додумать, что делать с неправильно скорректированными планами
      -- !!!

      IF(I$STATE >= 2) THEN EXCEPTION DATA_ERROR 'Нельзя задавать статус утвержден и выше в данном диалоге';

      -- Для УП кроме общеобра и ВД при направлении на согласование сразу ставим утверждение
      -- для ДПО утверждаем все типы журналов
      IF(I$STATE = 1) THEN
      BEGIN
          IF((V$STATUS = 'P' AND V$JT IN (10, 11)) OR (V$STATUS <> 'P' AND V$JT IN (2, 3, 10, 11))) THEN I$STATE = 2;
      END

      IF(EXISTS(
          SELECT FIRST 1 1
          FROM CJ2_JOURNAL_PTP P
          WHERE P.DATE_DEL IS NULL AND P.CJ_ID = :I$CJ_ID AND P.APPROVAL_STATE <> 3 AND P.PTP_ID <> :I$PTP_ID
      )) THEN EXCEPTION DATA_ERROR 'Нельзя прикреплять ПТП к журналу, когда есть другой прикрепленный ПТП';

      SELECT FIRST 1 P.OBJ_ID, P.APPROVAL_STATE
      FROM CJ2_JOURNAL_PTP P
      WHERE P.DATE_DEL IS NULL AND P.CJ_ID = :I$CJ_ID AND P.PTP_ID = :I$PTP_ID
      INTO :OBJ_ID, :V$STATE;

      IF(OBJ_ID IS NULL) THEN
      BEGIN
          INSERT INTO CJ2_JOURNAL_PTP
          (PTP_ID, CJ_ID, APPROVAL_STATE)
          VALUES (:I$PTP_ID, :I$CJ_ID, :I$STATE)
          RETURNING OBJ_ID INTO :OBJ_ID;
      END
      ELSE IF(V$STATE <> I$STATE) THEN
      BEGIN
          UPDATE CJ2_JOURNAL_PTP
          SET APPROVAL_STATE = :I$STATE
          WHERE OBJ_ID = :OBJ_ID;
      END

  END

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_PTP_CLONE (
    I$PTP_ID BIGINT,
    I$OBJ_NAME VARCHAR(1000),
    I$USER_ID VARCHAR(40))
RETURNS (
    PTP_ID BIGINT)
AS
declare variable V$OWNER_ID bigint;
declare variable V$LEVEL_ID bigint;
declare variable V$SUBJECT_ID bigint;
begin

  SELECT P.OWNER_ID, P.LEVEL_ID, P.SUBJECT_ID
  FROM PTP P
  WHERE P.OBJ_ID = :I$PTP_ID AND P.DATE_DEL IS NULL
  INTO :V$OWNER_ID, :V$LEVEL_ID, :V$SUBJECT_ID;

  IF(V$LEVEL_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Корректируемый ПТП не найден или был удален';

  INSERT INTO PTP
  (OWNER_ID, LEVEL_ID, SUBJECT_ID, PARENT_ID, OBJ_NAME, PTP_HOURS)
  VALUES (:V$OWNER_ID, :V$LEVEL_ID, :V$SUBJECT_ID, :I$PTP_ID, :I$OBJ_NAME, 0)
  RETURNING OBJ_ID INTO :PTP_ID;

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_PTP_DELETE (
    I$PTP_ID BIGINT,
    I$USER_ID VARCHAR(40))
AS
declare variable V$USER_ID bigint;
declare variable V$USER_TYPE smallint;
declare variable V$OBJ_ID bigint;
declare variable V$OWNER_ID bigint;
declare variable V$PERSON_ID bigint;
declare variable V$PARENT_ID bigint;
declare variable V$CJ_ID bigint;
declare variable V$PREV_ID bigint;
declare variable V$GOODREFS integer;
declare variable V$LESSONREFS integer;
declare variable S varchar(400);
declare variable V$LC bigint;
declare variable V$MUL bigint;
begin

  IF(I$USER_ID = 'Веб-администратор') THEN V$USER_ID = 1; ELSE V$USER_ID = CAST(I$USER_ID AS BIGINT);

  SELECT FIRST 1 U.USER_TYPE, U.OBJ_ID
  FROM USERS U
  JOIN LUSERS L ON L.USER_ID = U.USER_ID AND L.READ_ONLY = 0 AND L.LEVEL_ID IN (46)
  WHERE U.USER_ID = :V$USER_ID AND U.DATE_DEL IS NULL AND U.IS_BLOCKED = 0 AND (U.EXP_DATE IS NULL OR U.EXP_DATE > CURRENT_DATE)
  INTO :V$USER_TYPE, :V$PERSON_ID;

  IF(V$USER_TYPE IS NULL) THEN EXCEPTION DATA_ERROR 'У вас нет доступа';

  SELECT GEN, MULTIPLIER FROM GEN INTO :V$LC, :V$MUL;
  IF(I$PTP_ID / V$MUL <> V$LC) THEN EXCEPTION DATA_ERROR 'Рабочая программа или типовой ПТП созданы в другой базе, нельзя удалить';

  -- Можно удалить либо свой ПТП, либо быть администратором для удаления чужого
  SELECT FIRST 1 P.OBJ_ID, P.OWNER_ID, P.PARENT_ID
  FROM PTP P
  WHERE P.DATE_DEL IS NULL AND P.OBJ_ID = :I$PTP_ID
  INTO :V$OBJ_ID, :V$OWNER_ID, :V$PARENT_ID;

  IF(V$OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'ПТП не найден';
  IF((V$OWNER_ID IS NULL OR V$PERSON_ID <> :V$PERSON_ID) AND V$USER_TYPE NOT IN (1, 5, 6)) THEN
    EXCEPTION DATA_ERROR 'Для удаления ПТП нужно быть его владельцем, или административным пользователем';

  -- Есть дочерние ПТП
  IF(EXISTS(
    SELECT FIRST 1 1
    FROM PTP
    WHERE DATE_DEL IS NULL AND PARENT_ID = :I$PTP_ID
  )) THEN
    EXCEPTION DATA_ERROR 'Есть дочерние ПТП, удаление невозможно';

  -- Есть ли у нас хотя бы одна связь в утвержденном или аннулированном статусе ?
  SELECT COUNT(*)
  FROM CJ2_JOURNAL_PTP J
  JOIN CJ2_JOURNAL C ON C.OBJ_ID = J.CJ_ID AND C.DATE_DEL IS NULL
  WHERE J.DATE_DEL IS NULL AND J.PTP_ID = :I$PTP_ID AND J.APPROVAL_STATE IN (2, 3)
  INTO :V$GOODREFS;

  -- Есть ли у нас уроки, которые были связаны непосредственно с уроками этого ПТП (а не их предыдущие версии)
  SELECT COUNT(*)
  FROM CJ2_JOURNAL_PTP J
  JOIN CJ2_JOURNAL C ON C.OBJ_ID = J.CJ_ID AND C.DATE_DEL IS NULL
  JOIN CJ2_JOURNAL_LESSONS L ON L.DATE_DEL IS NULL AND L.CJ_ID = C.OBJ_ID
  JOIN PTP_LESSONS PL ON PL.DATE_DEL IS NULL AND PL.OBJ_ID = L.LESSON_PTP_ID AND PL.PTP_ID = J.PTP_ID
  WHERE J.DATE_DEL IS NULL AND J.PTP_ID = :I$PTP_ID
  INTO :V$LESSONREFS;

  -- Есть связи в журналах
  -- + только живые журналы
  IF(EXISTS(
    SELECT FIRST 1 1
    FROM CJ2_JOURNAL_PTP J
    JOIN CJ2_JOURNAL C ON C.OBJ_ID = J.CJ_ID AND C.DATE_DEL IS NULL
    WHERE J.DATE_DEL IS NULL AND J.PTP_ID = :I$PTP_ID
  )) THEN
  BEGIN
    IF(V$GOODREFS = 0 AND V$LESSONREFS = 0 AND V$PARENT_ID IS NOT NULL) THEN
    BEGIN
      -- Связи с журналами есть, но они все в проекте или на утверждении, и нет ни одного использованного урока
      -- И это точно не оригинальный ПТП, а коррекция
      -- Можно удалять, но надо проверить предыдущую версию. какой-нибудь журнал могу быть с ноля прикреплен к уже скорректированному ПТП
      FOR
        SELECT J.OBJ_ID, J.CJ_ID, C.JOURNAL_NAME
        FROM CJ2_JOURNAL_PTP J
        JOIN CJ2_JOURNAL C ON C.OBJ_ID = J.CJ_ID AND C.DATE_DEL IS NULL
        WHERE J.DATE_DEL IS NULL AND J.PTP_ID = :I$PTP_ID -- других будут статусы только 0 и 1
        ORDER BY 1
        INTO :V$OBJ_ID, :V$CJ_ID, :S
      DO
      BEGIN
        V$PREV_ID = NULL;
        SELECT FIRST 1 J.OBJ_ID
        FROM CJ2_JOURNAL_PTP J
        WHERE J.DATE_DEL IS NULL AND J.PTP_ID = :V$PARENT_ID AND J.CJ_ID = :V$CJ_ID AND J.APPROVAL_STATE = 2
        INTO :V$PREV_ID;

        IF(V$PREV_ID IS NULL) THEN EXCEPTION DATA_ERROR 'В журнале ' || S || ' нет предыдущего ПТП, удаление невозможно';
      END

      -- Удаляем связи
      UPDATE CJ2_JOURNAL_PTP
      SET DATE_DEL = CURRENT_TIMESTAMP
      WHERE DATE_DEL IS NULL AND PTP_ID = :I$PTP_ID;
    END
    ELSE
    BEGIN
      EXCEPTION DATA_ERROR 'Есть связанные с данным ПТП журналы, удаление невозможно';
    END
  END

  UPDATE PTP
  SET DATE_DEL = CURRENT_TIMESTAMP
  WHERE OBJ_ID = :I$PTP_ID AND DATE_DEL IS NULL;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_PTP_FIX_HOURS (
    I$PTP_ID BIGINT,
    I$CORR SMALLINT = 0)
AS
DECLARE VARIABLE V$HOURS FLOAT;
DECLARE VARIABLE V$LEVEL_ID BIGINT;
DECLARE VARIABLE S1 VARCHAR(400);
DECLARE VARIABLE S2 DATE;
begin

  SELECT P.LEVEL_ID
  FROM PTP P
  WHERE P.OBJ_ID = :I$PTP_ID
  INTO :V$LEVEL_ID;

  -- Проверяем, все ли прикрепленные уроки размещены в ПТП
  IF(I$CORR <> 0) THEN
  BEGIN
    SELECT FIRST 1 J.JOURNAL_NAME, L.LESSON_DATE
    FROM CJ2_JOURNAL_PTP P
    JOIN CJ2_JOURNAL J ON J.OBJ_ID = P.CJ_ID AND J.DATE_DEL IS NULL
    JOIN CJ2_JOURNAL_LESSONS L ON L.CJ_ID = J.OBJ_ID AND L.DATE_DEL IS NULL AND L.LESSON_PTP_ID = 0
    WHERE P.DATE_DEL IS NULL AND P.PTP_ID = :I$PTP_ID AND P.APPROVAL_STATE = 2
    INTO :S1, :S2;

    IF(S1 IS NOT NULL) THEN EXCEPTION DATA_ERROR 'В журнале "' || S1 || '" остался нескорректированный резервный урок от ' || (SELECT RESULT FROM DATE2STR(:S2));
  END

  SELECT SUM(L.DURATION)
  FROM PTP_LESSONS L
  WHERE L.DATE_DEL IS NULL AND L.PTP_ID = :I$PTP_ID AND (:V$LEVEL_ID NOT IN (2167, 2200) OR (L.LESSON_NUM > 0 AND (L.H_TEXT IS NOT NULL OR L.H_TEXT2 IS NOT NULL)))
  INTO :V$HOURS;

  UPDATE PTP
  SET PTP_HOURS = COALESCE(:V$HOURS, 0)
  WHERE OBJ_ID = :I$PTP_ID;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_PTP_LESSON_CLONE (
    I$PTP_ID BIGINT,
    I$PARENT_ID BIGINT,
    I$LESSON_NUM INTEGER,
    I$THEME_TEXT VARCHAR(1000),
    I$HOMETASK_TEXT VARCHAR(1000),
    I$DURATION FLOAT,
    I$CONTROLS VARCHAR(400),
    I$MERGE_IDS VARCHAR(400),
    I$TYPE_ID BIGINT = NULL,
    I$EXTRA VARCHAR(1000) = NULL,
    I$CEC_REFS VARCHAR(400) = NULL,
    I$TEST_REFS VARCHAR(1000) = NULL)
RETURNS (
    OBJ_ID BIGINT)
AS
DECLARE VARIABLE V$ID BIGINT;
DECLARE VARIABLE V$DATE TIMESTAMP;
DECLARE VARIABLE V$TYPE_ID BIGINT;
DECLARE VARIABLE S VARCHAR(4000);
begin

  -- Проверяем, что у нас темы в уроках совпадают с тем, что указано в ПТП
  FOR
    SELECT L.OBJ_ID, L.DATE_DEL, L.LESSON_THEME
    FROM STR_TO_ID_LIST(:I$MERGE_IDS) M
    LEFT JOIN CJ2_JOURNAL_LESSONS L ON L.OBJ_ID = M.ID AND L.LESSON_PTP_ID = 0
    INTO :V$ID, :V$DATE, :S
  DO
  BEGIN
    IF(V$ID IS NULL OR V$DATE IS NOT NULL) THEN EXCEPTION DATA_ERROR 'Резервный урок не найден или был удален';
    IF(S <> I$THEME_TEXT) THEN EXCEPTION DATA_ERROR 'Тема резервного урока не совпадает с темой, указанной в ПТП. Проверьте возможные лишние пробелы в теме в журналах';
  END

  -- КЭС переносим из первоначального урока
  /*V$CEC_REFS = '';
  FOR
    SELECT C.CEC_ITEM_ID
    FROM PTP_LESSON_CEC C
    WHERE C.DATE_DEL IS NULL AND C.LESSON_ID = :I$PARENT_ID
    INTO :V$ID
  DO
  BEGIN
    IF(CHAR_LENGTH(V$CEC_REFS) > 0) THEN V$CEC_REFS = V$CEC_REFS || ',';
    V$CEC_REFS = V$CEC_REFS || V$ID;
  END*/

  -- Переносим назначение тестов из предыдущей версии ПТП
  -- формат test_id:control_type_id
  IF(I$TEST_REFS IS NULL AND I$PARENT_ID IS NOT NULL) THEN
  BEGIN
    SELECT LIST(T.TEST_ID || ':' || T.CONTROL_TYPE_ID, ',')
    FROM PTP_LESSON_TESTS T
    WHERE T.DATE_DEL IS NULL AND T.LESSON_ID = :I$PARENT_ID
    INTO :I$TEST_REFS;
  END

  -- !!!
  SELECT OBJ_ID
  FROM CJ2_PTP_LESSON_SET(:I$PTP_ID, NULL, NULL, 0, :I$LESSON_NUM, :I$THEME_TEXT, :I$HOMETASK_TEXT, :I$DURATION, :I$PARENT_ID, :I$CONTROLS,
    :I$CEC_REFS, :I$TEST_REFS, :I$TYPE_ID, :I$EXTRA)
  INTO :OBJ_ID;

  FOR
    SELECT M.ID
    FROM STR_TO_ID_LIST(:I$MERGE_IDS) M
    INTO :V$ID
  DO
  BEGIN
    UPDATE CJ2_JOURNAL_LESSONS L
    SET L.LESSON_PTP_ID = :OBJ_ID
    WHERE L.OBJ_ID = :V$ID AND L.LESSON_PTP_ID = 0;
  END

  SUSPEND;


end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_PTP_LESSON_SET (
    I$PTP_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40),
    I$DELETED SMALLINT,
    I$LESSON_NUM INTEGER,
    I$THEME_TEXT VARCHAR(1000),
    I$HOMETASK_TEXT VARCHAR(1000),
    I$DURATION FLOAT,
    I$PARENT_LESSON_ID BIGINT,
    I$CONTROLS VARCHAR(400),
    I$CEC_REFS VARCHAR(1000) = NULL,
    I$TEST_REFS VARCHAR(1000) = NULL,
    I$TYPE_ID BIGINT = NULL,
    I$EXTRA VARCHAR(1000) = NULL,
    I$VNUM VARCHAR(40) = NULL,
    I$STAGE_ID BIGINT = NULL)
RETURNS (
    OBJ_ID BIGINT)
AS
DECLARE VARIABLE P INTEGER;
DECLARE VARIABLE S VARCHAR(400);
DECLARE VARIABLE SS VARCHAR(100);
DECLARE VARIABLE V$ID BIGINT;
DECLARE VARIABLE V$REF_ID BIGINT;
DECLARE VARIABLE V$CT BIGINT;
DECLARE VARIABLE T TIMESTAMP;
begin

  IF(I$OBJ_ID IS NULL AND I$DELETED = 1) THEN EXCEPTION DATA_ERROR 'Недопустимая комбинация параметров';

  I$THEME_TEXT = TRIM(I$THEME_TEXT);
  I$HOMETASK_TEXT = TRIM(I$HOMETASK_TEXT);

  -- !!! проверка PARENT_LESSON_ID

  IF(I$DELETED = 1) THEN
  BEGIN
    UPDATE PTP_LESSONS
    SET DATE_DEL = CURRENT_TIMESTAMP
    WHERE OBJ_ID = :I$OBJ_ID AND DATE_DEL IS NULL AND PTP_ID = :I$PTP_ID;
    EXIT;
  END

  IF(I$OBJ_ID IS NULL) THEN
  BEGIN

    INSERT INTO PTP_LESSONS
    (PTP_ID, LESSON_NUM, THEME_TEXT, HOMETASK_TEXT, DURATION, PARENT_LESSON_ID, TYPE_ID, EXTRA_TEXT, VIRT_NUM, STAGE_ID)
    VALUES (:I$PTP_ID, :I$LESSON_NUM, :I$THEME_TEXT, :I$HOMETASK_TEXT, :I$DURATION, :I$PARENT_LESSON_ID, :I$TYPE_ID, :I$EXTRA, :I$VNUM, :I$STAGE_ID)
    RETURNING OBJ_ID INTO :OBJ_ID;

  END
  ELSE
  BEGIN

    OBJ_ID = :I$OBJ_ID;

    IF(NOT EXISTS(
      SELECT FIRST 1 1
      FROM PTP_LESSONS
      WHERE DATE_DEL IS NULL AND OBJ_ID = :I$OBJ_ID
    )) THEN EXCEPTION DATA_ERROR 'Урок ' || I$LESSON_NUM || ' не найден';

    UPDATE PTP_LESSONS
    SET LESSON_NUM = :I$LESSON_NUM, THEME_TEXT = :I$THEME_TEXT, HOMETASK_TEXT = :I$HOMETASK_TEXT, DURATION = :I$DURATION, TYPE_ID = :I$TYPE_ID,
      EXTRA_TEXT = :I$EXTRA, VIRT_NUM = :I$VNUM, STAGE_ID = :I$STAGE_ID
    WHERE OBJ_ID = :I$OBJ_ID;

  END

  -- Если у нас контроли в текстовом виде - корректируем
  IF(SUBSTRING(I$CONTROLS FROM 1 FOR 3) = 'STR') THEN
  BEGIN
    S = SUBSTRING(I$CONTROLS FROM 5);
    I$CONTROLS = '';
    WHILE(CHAR_LENGTH(S) > 0) DO
    BEGIN
      P = POSITION(',' IN S);
      IF(P <= 0) THEN P = CHAR_LENGTH(S) + 1;
      SS = SUBSTRING(S FROM 1 FOR P - 1);
      S = SUBSTRING(S FROM P + 1);

      V$ID = NULL;
      SELECT FIRST 1 CONTROL_TYPE_ID
      FROM CJ2_CONTROL_TYPE
      WHERE IS_DEL = 0 AND CONTROL_NAME = :SS
      INTO :V$ID;

      IF(V$ID IS NOT NULL) THEN I$CONTROLS = I$CONTROLS || V$ID || ',';
    END
  END

  -- Пополнение контролей
  S = I$CONTROLS;
  WHILE(CHAR_LENGTH(S) > 0) DO
  BEGIN
    P = POSITION(',' IN S);
    IF(P <= 0) THEN P = CHAR_LENGTH(S) + 1;
    V$ID = SUBSTRING(S FROM 1 FOR P - 1);
    S = SUBSTRING(S FROM P + 1);

    V$REF_ID = NULL;
    SELECT FIRST 1 OBJ_ID, DATE_DEL
    FROM PTP_LESSON_CONTROLS
    WHERE LESSON_ID = :OBJ_ID AND CONTROL_TYPE_ID = :V$ID
    INTO :V$REF_ID, :T;

    IF(V$REF_ID IS NULL) THEN
    BEGIN
      INSERT INTO PTP_LESSON_CONTROLS (LESSON_ID, CONTROL_TYPE_ID) VALUES (:OBJ_ID, :V$ID);
    END
    ELSE IF(T IS NOT NULL) THEN
    BEGIN
      UPDATE PTP_LESSON_CONTROLS SET DATE_DEL = NULL WHERE OBJ_ID = :V$REF_ID;
    END
  END

  -- Удаляем утраченные
  I$CONTROLS = I$CONTROLS || ',';
  FOR
    SELECT OBJ_ID, CONTROL_TYPE_ID
    FROM PTP_LESSON_CONTROLS
    WHERE DATE_DEL IS NULL AND LESSON_ID = :OBJ_ID
    INTO :V$REF_ID, :V$ID
  DO
  BEGIN
    IF(POSITION((V$ID || ',') IN I$CONTROLS) <= 0) THEN
    BEGIN
      UPDATE PTP_LESSON_CONTROLS SET DATE_DEL = CURRENT_TIMESTAMP WHERE OBJ_ID = :V$REF_ID;
    END
  END

  -- Пополнение КЭС
  S = I$CEC_REFS;
  WHILE(CHAR_LENGTH(S) > 0) DO
  BEGIN
    P = POSITION(',' IN S);
    IF(P <= 0) THEN P = CHAR_LENGTH(S) + 1;
    V$ID = SUBSTRING(S FROM 1 FOR P - 1);
    S = SUBSTRING(S FROM P + 1);

    V$REF_ID = NULL;
    SELECT FIRST 1 OBJ_ID, DATE_DEL
    FROM PTP_LESSON_CEC
    WHERE LESSON_ID = :OBJ_ID AND CEC_ITEM_ID = :V$ID
    INTO :V$REF_ID, :T;

    IF(V$REF_ID IS NULL) THEN
    BEGIN
      INSERT INTO PTP_LESSON_CEC (LESSON_ID, CEC_ITEM_ID) VALUES (:OBJ_ID, :V$ID);
    END
    ELSE IF(T IS NOT NULL) THEN
    BEGIN
      UPDATE PTP_LESSON_CEC SET DATE_DEL = NULL WHERE OBJ_ID = :V$REF_ID;
    END
  END

  -- Удаляем утраченные
  I$CEC_REFS = I$CEC_REFS || ',';
  FOR
    SELECT OBJ_ID, CEC_ITEM_ID
    FROM PTP_LESSON_CEC
    WHERE DATE_DEL IS NULL AND LESSON_ID = :OBJ_ID
    INTO :V$REF_ID, :V$ID
  DO
  BEGIN
    SS = V$ID;
    IF(LEFT(I$CEC_REFS, CHAR_LENGTH(SS) + 1) = SS || ',') THEN BEGIN END
    ELSE IF(POSITION((',' || SS || ',') IN I$CEC_REFS) <= 0) THEN
    BEGIN
      UPDATE PTP_LESSON_CEC SET DATE_DEL = CURRENT_TIMESTAMP WHERE OBJ_ID = :V$REF_ID;
    END
  END

  -- Пополнение ссылок на тесты, формат test_id:control_type_id
  S = I$TEST_REFS;
  WHILE(CHAR_LENGTH(S) > 0) DO
  BEGIN
    P = POSITION(',' IN S);
    IF(P <= 0) THEN P = CHAR_LENGTH(S) + 1;
    SS = SUBSTRING(S FROM 1 FOR P - 1);
    S = SUBSTRING(S FROM P + 1);

    P = POSITION(':' IN SS);
    V$ID = SUBSTRING(SS FROM 1 FOR P - 1);
    V$CT = SUBSTRING(SS FROM P + 1);

    V$REF_ID = NULL;
    SELECT FIRST 1 OBJ_ID, DATE_DEL
    FROM PTP_LESSON_TESTS
    WHERE LESSON_ID = :OBJ_ID AND TEST_ID = :V$ID AND CONTROL_TYPE_ID = :V$CT
    INTO :V$REF_ID, :T;

    IF(V$REF_ID IS NULL) THEN
    BEGIN
      INSERT INTO PTP_LESSON_TESTS (LESSON_ID, CONTROL_TYPE_ID, TEST_ID) VALUES (:OBJ_ID, :V$CT, :V$ID);
    END
    ELSE IF(T IS NOT NULL) THEN
    BEGIN
      UPDATE PTP_LESSON_TESTS SET DATE_DEL = NULL WHERE OBJ_ID = :V$REF_ID;
    END
  END

  -- Удаляем утраченные
  I$TEST_REFS = I$TEST_REFS || ',';
  FOR
    SELECT OBJ_ID, TEST_ID || ':' || CONTROL_TYPE_ID
    FROM PTP_LESSON_TESTS
    WHERE DATE_DEL IS NULL AND LESSON_ID = :OBJ_ID
    INTO :V$REF_ID, :SS
  DO
  BEGIN
    IF(LEFT(I$TEST_REFS, CHAR_LENGTH(SS) + 1) = SS || ',') THEN BEGIN END
    ELSE IF(POSITION((',' || SS || ',') IN I$TEST_REFS) <= 0) THEN
    BEGIN
      UPDATE PTP_LESSON_TESTS SET DATE_DEL = CURRENT_TIMESTAMP WHERE OBJ_ID = :V$REF_ID;
    END
  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_PTP_LIST_BY_OWNER (
    IN_USER_ID VARCHAR(40))
RETURNS (
    STAGE_NUM INTEGER,
    STAGE_NAME VARCHAR(100),
    GRADE_ID BIGINT,
    GRADE_NAME VARCHAR(1000),
    SUBJECT_ID BIGINT,
    SUBJECT_NAME VARCHAR(1000),
    PTP_ID BIGINT,
    PTP_NAME VARCHAR(1000),
    PTP_HOURS INTEGER,
    STATE_NUM SMALLINT,
    STATE_TEXT VARCHAR(100),
    PARENT_ID BIGINT,
    PARENT_NAME VARCHAR(1000))
AS
declare variable USER_ID bigint;
declare variable USER_TYPE smallint;
declare variable TEACHER_ID bigint;
begin

  -- Преобразуем ID
  IF(IN_USER_ID = '00000000-0000-0000-0000-000000000000' OR IN_USER_ID = 'Веб-администратор') THEN USER_ID = 1;
  ELSE USER_ID = IN_USER_ID;

  -- Получаем данные объекта сотрудника
  SELECT U.USER_TYPE, U.OBJ_ID
  FROM USERS U
  WHERE U.USER_ID = :USER_ID AND U.DATE_DEL IS NULL AND U.IS_BLOCKED = 0
  INTO :USER_TYPE, :TEACHER_ID;

  IF(0 = 1) THEN SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_PTP_LIST_CJ (
    I$PTP_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
declare variable V$LEVEL_ID bigint;
declare variable V$SUBJECT_ID bigint;
declare variable V$OWNER_ID bigint;
declare variable V$USER_ID bigint;
declare variable V$OBJ_ID bigint;
declare variable V$OBJ_NAME varchar(1000);
declare variable V$USER_TYPE integer;
declare variable V$TEACHER_ID bigint;
declare variable V$TYPE bigint;
declare variable V$STAGE_INDEX bigint;
declare variable V$SUBJECT_ID2 bigint;
begin

  -- Уровень доступа пользователя
  IF(I$USER_ID = 'Веб-администратор') THEN V$USER_ID = 1; ELSE V$USER_ID = CAST(I$USER_ID AS BIGINT);

  SELECT U.USER_TYPE, U.OBJ_ID
  FROM USERS U
  WHERE U.USER_ID = :V$USER_ID AND U.DATE_DEL IS NULL AND U.IS_BLOCKED = 0
  INTO :V$USER_TYPE, :V$TEACHER_ID;
                                  
  SELECT FIRST 1 P.LEVEL_ID, P.SUBJECT_ID, P.OWNER_ID
  FROM PTP P
  WHERE P.DATE_DEL IS NULL AND P.OBJ_ID = :I$PTP_ID
  INTO :V$LEVEL_ID, :V$SUBJECT_ID, :V$OWNER_ID;

  IF(V$LEVEL_ID IS NULL) THEN EXCEPTION DATA_ERROR 'ПТП не найден';

  V$STAGE_INDEX = NULL;
  IF(V$LEVEL_ID = 2141) THEN V$TYPE = 2; -- ГПД
  ELSE IF(V$LEVEL_ID = 2143) THEN V$TYPE = 3; -- ДО
  ELSE IF(V$LEVEL_ID = 2155) THEN V$TYPE = 1; -- ВД
  ELSE
  BEGIN
      -- общеобр - конкретная параллель
      V$TYPE = 0;
      V$STAGE_INDEX = V$LEVEL_ID;
  END

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

  TAG_NAME = 'items';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'items::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
      SELECT J.OBJ_ID, J.JOURNAL_NAME, J.SUBJECT_ID
      FROM CJ2_JOURNAL J
      WHERE J.DATE_DEL IS NULL AND J.JOURNAL_TYPE = :V$TYPE
          AND (J.STAGE_INDEX = :V$STAGE_INDEX OR :V$STAGE_INDEX IS NULL)
          AND ((J.SUBJECT_ID IS NULL AND :V$SUBJECT_ID IS NULL) OR J.SUBJECT_ID = :V$SUBJECT_ID OR EXISTS(
              SELECT FIRST 1 1
              FROM LINKS L302
              JOIN VALL V2462 ON V2462.OBJ_ID = L302.OBJ_ID AND V2462.PARAM_ID = 2462 AND V2462.IS_DEL = 0
              JOIN VALL VX2462 ON VX2462.IS_DEL = 0 AND VX2462.PARAM_ID = 2462 AND VX2462.LISTVAL_ID = V2462.LISTVAL_ID
              JOIN LINKS LP51 ON LP51.OBJ_ID = VX2462.OBJ_ID AND LP51.PARENT_ID = J.SUBJECT_ID AND LP51.DATE_DEL IS NULL
              WHERE L302.PARENT_ID = :V$SUBJECT_ID AND L302.OBJ_TYPE_ID = 302 AND L302.DATE_DEL IS NULL
          ))
          AND (:V$USER_TYPE IN (1, 5, 6) OR J.TEACHER_ID = :V$TEACHER_ID OR
            EXISTS (
              SELECT FIRST 1 1
              FROM LINKS L186
              JOIN VALR V1609 ON V1609.OBJ_ID = L186.OBJ_ID AND V1609.PARAM_ID = 1609 AND V1609.IS_DEL = 0 AND V1609.VAL = :V$TEACHER_ID
              WHERE L186.PARENT_ID = J.GRADE_ID AND L186.OBJ_TYPE_ID = 186 AND L186.DATE_DEL IS NULL
            )
          ) -- OR :V$OWNER_ID = :V$TEACHER_ID
          AND NOT EXISTS (
              SELECT FIRST 1 1
              FROM CJ2_JOURNAL_PTP P
              WHERE P.DATE_DEL IS NULL AND P.CJ_ID = J.OBJ_ID AND P.DATE_DEL IS NULL
          )
      ORDER BY 2
      INTO :V$OBJ_ID, :V$OBJ_NAME, :V$SUBJECT_ID2
  DO
  BEGIN
      TAG_NAME = 'items:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'items:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'items:r:journal_name';
      IF(V$SUBJECT_ID2 IS NOT NULL) THEN V$OBJ_NAME = V$OBJ_NAME || ' (' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$SUBJECT_ID2)) || ')';
      VAL = V$OBJ_NAME;
      SUSPEND;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_PTP_LIST_GEN (
    IN_USER_ID VARCHAR(40),
    IN_TYPE_ID INTEGER,
    IN_LEVEL_ID BIGINT,
    IN_SUBJECT_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    PARENT_ID BIGINT,
    OBJ_NAME VARCHAR(1000),
    OWNER_ID BIGINT,
    PTP_HOURS INTEGER,
    LEVEL_ID BIGINT,
    SUBJECT_ID BIGINT,
    LEVEL_NUM INTEGER,
    GRADES_LIST VARCHAR(4000),
    STATE_LIST VARCHAR(4000))
AS
DECLARE VARIABLE USER_ID BIGINT;
DECLARE VARIABLE USER_TYPE SMALLINT;
DECLARE VARIABLE TEACHER_ID BIGINT;
DECLARE VARIABLE S VARCHAR(1000);
DECLARE VARIABLE V$STATE INTEGER;
begin

  -- type, level, subject берутся аналогично CJ2_PTP_MENU_LIST
  -- для занятий кроме общеобразовательных level и subject = null

  IF(IN_TYPE_ID = 1) THEN IN_LEVEL_ID = 2155; -- Внеурочка
  ELSE IF(IN_TYPE_ID = 2) THEN IN_LEVEL_ID = 2141; -- ГПД
  ELSE IF(IN_TYPE_ID = 3) THEN IN_LEVEL_ID = 2143; -- ДО

  -- Преобразуем ID
  IF(IN_USER_ID = '00000000-0000-0000-0000-000000000000' OR IN_USER_ID = 'Веб-администратор') THEN USER_ID = 1;
  ELSE USER_ID = IN_USER_ID;

  -- Получаем данные объекта сотрудника
  SELECT U.USER_TYPE, U.OBJ_ID
  FROM USERS U
  WHERE U.USER_ID = :USER_ID AND U.DATE_DEL IS NULL AND U.IS_BLOCKED = 0
  INTO :USER_TYPE, :TEACHER_ID;

  -- Список ПТП возвращаем деревом, нижестоящие уровни обязательно идут после вышестоящих
  FOR
    SELECT OBJ_ID, PARENT_ID, OBJ_NAME, OWNER_ID, PTP_HOURS, LEVEL_ID, SUBJECT_ID, LEVEL_NUM
    FROM CJ2_PTP_LIST_GEN_INT(NULL, :IN_LEVEL_ID, :IN_SUBJECT_ID)
    INTO :OBJ_ID, :PARENT_ID, :OBJ_NAME, :OWNER_ID, :PTP_HOURS, :LEVEL_ID, :SUBJECT_ID, :LEVEL_NUM
  DO
  BEGIN
    GRADES_LIST = '';
    STATE_LIST = '';

    FOR
      SELECT C.CAPTION, JP.APPROVAL_STATE
      FROM CJ2_JOURNAL_PTP JP
      JOIN CJ2_JOURNAL J ON J.OBJ_ID = JP.CJ_ID AND J.DATE_DEL IS NULL
      LEFT JOIN OBJECT_CAPTION_GET(J.GRADE_ID) C ON 1 = 1
      WHERE JP.DATE_DEL IS NULL AND JP.PTP_ID = :OBJ_ID
      ORDER BY 1
      INTO :S, :V$STATE
    DO
    BEGIN
      IF(GRADES_LIST = '') THEN GRADES_LIST = GRADES_LIST || ', ';
      IF(STATE_LIST = '') THEN STATE_LIST = STATE_LIST || ', ';

      GRADES_LIST = GRADES_LIST || S;

      STATE_LIST = STATE_LIST || S || ' (';
      IF(V$STATE = 0) THEN STATE_LIST = STATE_LIST || 'проект';
      ELSE IF(V$STATE = 1) THEN STATE_LIST = STATE_LIST || 'к/утв';
      ELSE IF(V$STATE = 2) THEN STATE_LIST = STATE_LIST || 'действ';
      STATE_LIST = STATE_LIST || ')';
    END

    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_PTP_LIST_GEN_INT (
    I$PARENT_ID BIGINT,
    I$LEVEL_ID BIGINT,
    I$SUBJECT_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    PARENT_ID BIGINT,
    OBJ_NAME VARCHAR(1000),
    OWNER_ID BIGINT,
    PTP_HOURS INTEGER,
    LEVEL_ID BIGINT,
    SUBJECT_ID BIGINT,
    LEVEL_NUM INTEGER)
AS
declare variable V$PARENT_ID bigint;
begin

  FOR
      SELECT P.OBJ_ID, P.PARENT_ID, P.OBJ_NAME, P.OWNER_ID, P.PTP_HOURS, P.LEVEL_ID, P.SUBJECT_ID, P.LEVEL_NUM
      FROM PTP P
      WHERE P.DATE_DEL IS NULL AND ((:I$PARENT_ID IS NULL AND P.PARENT_ID IS NULL) OR (P.PARENT_ID = :I$PARENT_ID))
          AND ((:I$SUBJECT_ID IS NULL AND P.SUBJECT_ID IS NULL) OR (P.SUBJECT_ID = :I$SUBJECT_ID))
          AND P.LEVEL_ID = :I$LEVEL_ID
      ORDER BY P.OBJ_NAME
      INTO :OBJ_ID, :PARENT_ID, :OBJ_NAME, :OWNER_ID, :PTP_HOURS, :LEVEL_ID, :SUBJECT_ID, :LEVEL_NUM
  DO
  BEGIN

      -- Основной план
      V$PARENT_ID = PARENT_ID;
      SUSPEND;

      -- Дочерние планы следом за основным
      FOR
          SELECT OBJ_ID, PARENT_ID, OBJ_NAME, OWNER_ID, PTP_HOURS, LEVEL_ID, SUBJECT_ID, LEVEL_NUM
          FROM CJ2_PTP_LIST_GEN_INT(:OBJ_ID, :I$LEVEL_ID, :I$SUBJECT_ID)
          INTO :OBJ_ID, :PARENT_ID, :OBJ_NAME, :OWNER_ID, :PTP_HOURS, :LEVEL_ID, :SUBJECT_ID, :LEVEL_NUM
      DO
      BEGIN
          SUSPEND;
      END

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_PTP_LIST_OLD (
    I$TYPE_ID BIGINT,
    I$SUBJECT_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    OBJ_ID BIGINT,
    NAME VARCHAR(1000),
    SUBJECT_NAME VARCHAR(1000))
AS
declare variable V$TEACHER_ID bigint;
declare variable V$USER_TYPE integer;
begin

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  SELECT FIRST 1 U.USER_TYPE, U.OBJ_ID
  FROM USERS U
  WHERE U.USER_ID = :I$USER_ID
  INTO :V$USER_TYPE, :V$TEACHER_ID;

  IF(V$USER_TYPE IN (1, 5, 6)) THEN V$TEACHER_ID = NULL;
  IF(I$TYPE_ID IN (2, 2141)) THEN I$TYPE_ID = 189; -- ГПД
  IF(I$TYPE_ID IN (3, 2143)) THEN I$TYPE_ID = 275; -- ДО
  IF(I$TYPE_ID IN (1, 2155)) THEN I$TYPE_ID = 274; -- ВД

  FOR
    SELECT L87.OBJ_ID, V472.SVAL, V376.SVAL || COALESCE(' - ' || R.VAL, '')
    FROM LINKS L87
    JOIN VALS V472 ON V472.OBJ_ID = L87.OBJ_ID AND V472.PARAM_ID IN (472, 1601) AND V472.IS_DEL = 0
    LEFT JOIN VALR V2834 ON V2834.OBJ_ID = L87.OBJ_ID AND V2834.PARAM_ID = 2834 AND V2834.IS_DEL = 0
    LEFT JOIN LINKS LP51 ON LP51.OBJ_ID = L87.OBJ_ID AND LP51.PARENT_TYPE_ID IN (51, 197) AND LP51.DATE_DEL IS NULL
    LEFT JOIN VALR V473 ON V473.OBJ_ID = L87.OBJ_ID AND V473.PARAM_ID IN (473, 1602) AND V473.IS_DEL = 0
    LEFT JOIN VALL V49 ON V49.OBJ_ID = L87.PARENT_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
    LEFT JOIN VALI V2216 ON V2216.OBJ_ID = L87.OBJ_ID AND V2216.PARAM_ID = 2216 AND V2216.IS_DEL = 0
    LEFT JOIN VALS V376 ON V376.OBJ_ID = LP51.PARENT_ID AND V376.PARAM_ID = 376 AND V376.IS_DEL = 0
    LEFT JOIN LISTVALS LV ON LV.LISTVAL_ID = V49.LISTVAL_ID
    LEFT JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
    WHERE L87.OBJ_TYPE_ID IN (87, 182) AND L87.PARENT_TYPE_ID IN (2, 8) AND L87.DATE_DEL IS NULL
      AND (:I$SUBJECT_ID IS NULL OR LP51.PARENT_ID = :I$SUBJECT_ID)
      AND (V49.LISTVAL_ID = :I$TYPE_ID OR V2216.VAL = :I$TYPE_ID OR (:I$TYPE_ID = 0 AND V49.LISTVAL_ID IS NOT NULL))
      -- Убрали проверку по наличию связей с CJ_MAIN, чтобы грохнуть саму таблицу
      AND (:V$TEACHER_ID IS NULL OR V473.VAL = :V$TEACHER_ID)
      AND V2834.VAL IS NULL -- только корневые
    ORDER BY 3, LV.COST, 2
    INTO :OBJ_ID, :NAME, :SUBJECT_NAME
  DO
  BEGIN
    SUSPEND;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_PTP_MENU_LIST (
    IN_USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
declare variable V$OU_LICENSE_TYPE char(1);
declare variable USER_ID bigint;
declare variable USER_TYPE smallint;
declare variable TEACHER_ID bigint;
declare variable V$LEVEL_ID bigint;
declare variable S varchar(1000);
declare variable V$SUBJECT_ID bigint;
declare variable V$COLOR integer;
begin
  -- Устарело !!!

  -- Преобразуем ID
  IF(IN_USER_ID = '00000000-0000-0000-0000-000000000000' OR IN_USER_ID = 'Веб-администратор') THEN USER_ID = 1;
  ELSE USER_ID = IN_USER_ID;

  SELECT STATUS FROM OU_LICENCE_TYPE INTO :V$OU_LICENSE_TYPE;

  -- Получаем данные объекта сотрудника
  SELECT U.USER_TYPE, U.OBJ_ID
  FROM USERS U
  WHERE U.USER_ID = :USER_ID AND U.DATE_DEL IS NULL AND U.IS_BLOCKED = 0
  INTO :USER_TYPE, :TEACHER_ID;

  TAG_NAME = 'data';
  VAL = NULL;
  SUSPEND;

  TAG_NAME = 'data::json&colon;array';
  VAL = '1';
  SUSPEND;

  -- Все меню выдаем общим списком

  IF(V$OU_LICENSE_TYPE = 'O') THEN
  BEGIN

      -- Школа, общеобразовательные журналы - Параллели -> Предметы
      -- Оба уровня берем из настроенных в ОУ, дополняем тем что потерялось в существующих ПТП
      FOR
          SELECT DISTINCT LV.LISTVAL_ID, R.VAL
          FROM LINKS L2
          JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
          JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
          JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
          JOIN LISTVALS LV ON LV.LISTVAL_ID = V49.LISTVAL_ID
          JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
          WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
          -- Добавляем сечения по ПТП, которые фактически присутствуют
          UNION
          SELECT DISTINCT LV.LISTVAL_ID, R.VAL
          FROM PTP P
          JOIN LISTVALS LV ON LV.LISTVAL_ID = P.LEVEL_ID
          JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
          -- Коды этапов обучения жестко перечисляем, чтобы выбрать именно общеобразовательные предметы
          WHERE P.LEVEL_ID IN (36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 12765) AND P.DATE_DEL IS NULL
          ORDER BY 1, 2
          INTO :V$LEVEL_ID, :S
      DO
      BEGIN
          TAG_NAME = 'data:lv';
          VAL = NULL;
          SUSPEND;

          -- Тип журнала = общеобразовательный
          TAG_NAME = 'data:lv:type';
          VAL = '0';
          SUSPEND;

          -- Подтип 0 = школы
          TAG_NAME = 'data:lv:subtype';
          VAL = '0';
          SUSPEND;

          TAG_NAME = 'data:lv:id';
          VAL = V$LEVEL_ID;
          SUSPEND;

          TAG_NAME = 'data:lv:name';
          VAL = S;
          SUSPEND;

          TAG_NAME = 'data:lv:level';
          VAL = NULL;
          SUSPEND;

          TAG_NAME = 'data:lv:level::json&colon;array';
          VAL = '1';
          SUSPEND;

          -- Выводим предметы в рамках УП, к которым добавляем предметы из реальных ПТП
          FOR
              -- Предметы из нагрузок (общеобразовательные)
              SELECT DISTINCT LP51.PARENT_ID, C.CAPTION, C.COLOR
              FROM LINKS L2
              JOIN LINKS L69 ON L69.PARENT_ID = L2.OBJ_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL
              JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
              JOIN LINKS L50 ON L50.PARENT_ID = L57.OBJ_ID AND L50.OBJ_TYPE_ID = 50 AND L50.DATE_DEL IS NULL
              JOIN VALL V2545 ON V2545.OBJ_ID = L50.OBJ_ID AND V2545.PARAM_ID = 2545 AND V2545.IS_DEL = 0 AND V2545.LISTVAL_ID = 3
              JOIN LINKS L54 ON L54.PARENT_ID = L50.OBJ_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
              JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0 AND V381.LISTVAL_ID = :V$LEVEL_ID
              JOIN LINKS L56 ON L56.PARENT_ID = L54.OBJ_ID AND L56.OBJ_TYPE_ID = 56 AND L56.DATE_DEL IS NULL
              JOIN LINKS LP51 ON LP51.OBJ_ID = L56.OBJ_ID AND LP51.PARENT_TYPE_ID = 51 AND LP51.DATE_DEL IS NULL
              LEFT JOIN OBJECT_CAPTION_GET(LP51.PARENT_ID) C ON 1 = 1
              WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
              -- Предметы из реальных ПТП
              UNION
              SELECT DISTINCT P.SUBJECT_ID, C.CAPTION, C.COLOR
              FROM PTP P
              LEFT JOIN OBJECT_CAPTION_GET(P.SUBJECT_ID) C ON 1 = 1
              WHERE P.DATE_DEL IS NULL AND P.SUBJECT_ID IS NOT NULL AND P.LEVEL_ID = :V$LEVEL_ID
              ORDER BY 2
              INTO :V$SUBJECT_ID, :S, :V$COLOR
          DO
          BEGIN
              TAG_NAME = 'data:lv:level:lv';
              VAL = NULL;
              SUSPEND;

              TAG_NAME = 'data:lv:level:lv:id';
              VAL = V$SUBJECT_ID;
              SUSPEND;

              TAG_NAME = 'data:lv:level:lv:name';
              VAL = S;
              SUSPEND;

              TAG_NAME = 'data:lv:level:lv:color';
              VAL = V$COLOR;
              SUSPEND;
          END
      END

      -- Внеурочка
      TAG_NAME = 'data:lv';
      VAL = NULL;
      SUSPEND;

      TAG_NAME = 'data:lv:type';
      VAL = '1'; -- ВД
      SUSPEND;

      TAG_NAME = 'data:lv:subtype';
      VAL = '0'; -- школы
      SUSPEND;

      TAG_NAME = 'data:lv:id';
      VAL = '2167';
      SUSPEND;

      TAG_NAME = 'data:lv:name';
      VAL = 'Внеурочная деятельность';
      SUSPEND;

      -- ГПД
      TAG_NAME = 'data:lv';
      VAL = NULL;
      SUSPEND;

      TAG_NAME = 'data:lv:type';
      VAL = '2'; -- ГПД
      SUSPEND;

      TAG_NAME = 'data:lv:subtype';
      VAL = '0'; -- школы
      SUSPEND;

      TAG_NAME = 'data:lv:id';
      VAL = '2141';
      SUSPEND;

      TAG_NAME = 'data:lv:name';
      VAL = 'Группы продленного дня';
      SUSPEND;

      -- ДО
      TAG_NAME = 'data:lv';
      VAL = NULL;
      SUSPEND;

      TAG_NAME = 'data:lv:type';
      VAL = '3'; -- ДО
      SUSPEND;

      TAG_NAME = 'data:lv:subtype';
      VAL = '0'; -- школы
      SUSPEND;

      TAG_NAME = 'data:lv:id';
      VAL = '2143';
      SUSPEND;

      TAG_NAME = 'data:lv:name';
      VAL = 'Дополнительное образование';
      SUSPEND;

  END
  ELSE IF(V$OU_LICENSE_TYPE = 'C') THEN
  BEGIN

      -- Колледжи

  END
  ELSE IF(V$OU_LICENSE_TYPE = 'D') THEN
  BEGIN

       -- ДОУ

  END
  ELSE IF(V$OU_LICENSE_TYPE = 'U') THEN
  BEGIN

      -- УДОД

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_PTP_MIGRATE (
    I$OBJ_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$TEACHER_ID bigint;
declare variable V$STAGE_ID bigint;
declare variable V$SUBJECT_ID bigint;
declare variable V$TYPE_ID bigint;
declare variable N integer;
declare variable V$T varchar(2000);
declare variable V$H varchar(2000);
declare variable V$DUR integer;
declare variable V$SRC_ID bigint;
declare variable V$LESSON_ID bigint;
declare variable V$CT bigint;
declare variable S varchar(1000);
begin

  SELECT FIRST 1 L.OBJ_TYPE_ID, V49.LISTVAL_ID, VT.VAL, VN.VAL
  FROM LINKS L
  LEFT JOIN VALL V49 ON V49.OBJ_ID = L.PARENT_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
  JOIN VALS VN ON VN.OBJ_ID = L.OBJ_ID AND VN.PARAM_ID IN (472, 1601) AND VN.IS_DEL = 0
  LEFT JOIN VALR VT ON VT.OBJ_ID = L.OBJ_ID AND VT.PARAM_ID IN (473, 1602) AND VT.IS_DEL = 0
  WHERE L.OBJ_ID = :I$OBJ_ID AND L.PARENT_TYPE_ID IN (2, 8) AND L.DATE_DEL IS NULL
  INTO :V$TYPE_ID, :V$STAGE_ID, :V$TEACHER_ID, :S;

  SELECT FIRST 1 LP51.PARENT_ID
  FROM LINKS LP51
  WHERE LP51.OBJ_ID = :I$OBJ_ID AND LP51.PARENT_TYPE_ID = 51 AND LP51.DATE_DEL IS NULL
  INTO :V$SUBJECT_ID;

  IF(V$TYPE_ID = 87) THEN
  BEGIN
    -- Общеобразовательные, оставляем как есть
  END
  ELSE IF(V$TYPE_ID = 182) THEN
  BEGIN
    -- ГПД, ДО - идентифицируем
    SELECT FIRST 1 V2216.VAL
    FROM VALI V2216
    WHERE V2216.OBJ_ID = :I$OBJ_ID AND V2216.PARAM_ID = 2216 AND V2216.IS_DEL = 0
    INTO :V$TYPE_ID;

    IF(V$TYPE_ID = 274) THEN V$STAGE_ID = 2155; -- ВД
    ELSE IF(V$TYPE_ID = 189) THEN V$STAGE_ID = 2141; -- ГПД
    ELSE IF(V$TYPE_ID = 275) THEN V$STAGE_ID = 2143; -- ДО
    ELSE EXCEPTION DATA_ERROR 'Не удалось определить разновидность ПТП';
  END

  INSERT INTO PTP
  (OWNER_ID, LEVEL_ID, SUBJECT_ID, PTP_HOURS, OBJ_NAME)
  VALUES (:V$TEACHER_ID, :V$STAGE_ID, :V$SUBJECT_ID, 0, :S)
  RETURNING OBJ_ID INTO :OBJ_ID;

  N = 0;

  FOR
    SELECT L.OBJ_ID, VT.VAL, VH.VAL, COALESCE(VD.VAL, 1)
    FROM LINKS L
    JOIN VALI VN ON VN.OBJ_ID = L.OBJ_ID AND VN.PARAM_ID IN (475, 1605) AND VN.IS_DEL = 0
    JOIN VALS VT ON VT.OBJ_ID = L.OBJ_ID AND VT.PARAM_ID IN (476, 1606) AND VT.IS_DEL = 0
    LEFT JOIN VALS VH ON VH.OBJ_ID = L.OBJ_ID AND VH.PARAM_ID IN (477) AND VH.IS_DEL = 0
    LEFT JOIN VALI VD ON VD.OBJ_ID = L.OBJ_ID AND VD.PARAM_ID IN (477, 1607) AND VD.IS_DEL = 0
    WHERE L.PARENT_ID = :I$OBJ_ID AND L.OBJ_TYPE_ID IN (88, 183) AND L.DATE_DEL IS NULL
    ORDER BY VN.VAL
    INTO :V$SRC_ID, :V$T, :V$H, :V$DUR
  DO
  BEGIN
    N = N + 1;

    INSERT INTO PTP_LESSONS
    (PTP_ID, LESSON_NUM, THEME_TEXT, HOMETASK_TEXT, DURATION)
    VALUES (:OBJ_ID, :N, :V$T, :V$H, :V$DUR)
    RETURNING OBJ_ID INTO :V$LESSON_ID;

    -- Контроли есть только в общеобре
    FOR
      SELECT V546.LISTVAL_ID
      FROM LINKS LC
      JOIN VALL V546 ON V546.OBJ_ID = LC.OBJ_ID AND V546.PARAM_ID = 546 AND V546.IS_DEL = 0
      WHERE LC.PARENT_ID = :V$SRC_ID AND LC.OBJ_TYPE_ID = 89 AND LC.DATE_DEL IS NULL
      ORDER BY LC.OBJ_ID
      INTO :V$CT
    DO        
    BEGIN
      INSERT INTO PTP_LESSON_CONTROLS
      (LESSON_ID, CONTROL_TYPE_ID)
      VALUES (:V$LESSON_ID, :V$CT);
    END

  END

  UPDATE PTP
  SET PTP_HOURS = :N
  WHERE OBJ_ID = :OBJ_ID;

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_PTP_OLD_GET (
    I$PTP_ID BIGINT)
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(4000))
AS
declare variable V$LESSON_ID bigint;
declare variable V$THEME varchar(4000);
declare variable V$HW varchar(4000);
declare variable V$H integer;
begin

  FOR
    SELECT L88.OBJ_ID, V476.VAL, V477.VAL, V2082.VAL
    FROM LINKS L88
    JOIN VALI V475 ON V475.OBJ_ID = L88.OBJ_ID AND V475.PARAM_ID IN (475, 1605) AND V475.IS_DEL = 0
    JOIN VALS V476 ON V476.OBJ_ID = L88.OBJ_ID AND V476.PARAM_ID IN (476, 1606) AND V476.IS_DEL = 0
    LEFT JOIN VALS V477 ON V477.OBJ_ID = L88.OBJ_ID AND V477.PARAM_ID = 477 AND V477.IS_DEL = 0
    LEFT JOIN VALS V2082 ON V2082.OBJ_ID = L88.OBJ_ID AND V2082.PARAM_ID IN (2082, 1607) AND V2082.IS_DEL = 0
    WHERE L88.PARENT_ID = :I$PTP_ID AND L88.OBJ_TYPE_ID IN (88, 183) AND L88.DATE_DEL IS NULL
    ORDER BY V475.VAL
    INTO :V$LESSON_ID, :V$THEME, :V$HW, :V$H
  DO
  BEGIN

    TAG_NAME = 'r';
    VAL = NULL;
    SUSPEND;

    TAG_NAME = 'r:theme';
    VAL = REPLACE(TRIM(V$THEME), '  ', ' ');
    SUSPEND;

    TAG_NAME = 'r:task';
    VAL = REPLACE(TRIM(V$HW), '  ', ' ');
    SUSPEND;

    TAG_NAME = 'r:hours';
    VAL = COALESCE(:V$H, 1);
    SUSPEND;

    TAG_NAME = 'r:controls';
    VAL = 'STR';
    FOR
      SELECT LV.TAG
      FROM LINKS L89
      JOIN VALL V546 ON V546.OBJ_ID = L89.OBJ_ID AND V546.PARAM_ID = 546 AND V546.IS_DEL = 0
      JOIN LISTVALS LV ON LV.LISTVAL_ID = V546.LISTVAL_ID
      WHERE L89.PARENT_ID = :V$LESSON_ID AND L89.OBJ_TYPE_ID = 89 AND L89.DATE_DEL IS NULL
      ORDER BY L89.OBJ_ID
      INTO :V$HW
    DO
    BEGIN
      VAL = VAL || ',' || V$HW;
    END
    SUSPEND;

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_PTP_REASSIGN (
    I$PTP_ID BIGINT,
    I$FOR VARCHAR(1000))
AS
declare variable P integer;
declare variable V$CJ_ID bigint;
declare variable X$CJ_ID bigint;
declare variable V$STATE bigint;
declare variable V$CJ_TYPE bigint;
begin

  -- По-умолчанию статус к утверждению, но для УП не-общеобр и не-ВД ставим сразу утвержденный
  -- а ранее прикрепленный план отмечаем как не-действующий

  WHILE(CHAR_LENGTH(I$FOR) > 0) DO
  BEGIN

    P = POSITION(',' IN I$FOR);
    IF(P <= 0) THEN P = CHAR_LENGTH(I$FOR) + 1;

    -- Проверяем, что данный журнал у нас был ранее прикрепленный к прародителю нашего откорректированного ПТП
    X$CJ_ID = NULL;
    V$CJ_ID = SUBSTRING(I$FOR FROM 1 FOR P - 1);
    SELECT FIRST 1 J.OBJ_ID, CJ.JOURNAL_TYPE
    FROM PTP P
    JOIN CJ2_JOURNAL_PTP J ON J.DATE_DEL IS NULL AND J.PTP_ID = P.PARENT_ID AND J.CJ_ID = :V$CJ_ID AND J.APPROVAL_STATE > 0
    JOIN CJ2_JOURNAL CJ ON CJ.OBJ_ID = J.CJ_ID
    WHERE P.OBJ_ID = :I$PTP_ID
    INTO :X$CJ_ID, :V$CJ_TYPE;

    IF(X$CJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Нельзя связать откорректированный ПТП с журналом, которого не было в текущем варианте ПТП';

    IF(V$CJ_TYPE IN (0, 1)) THEN
    BEGIN
      -- Старый план остается, новый добавляем к утверждению
      V$STATE = 1;
    END
    ELSE
    BEGIN
      -- Новый сразу ставим утвержденным, старый отмечаем как не-действующий
      V$STATE = 2;

      UPDATE CJ2_JOURNAL_PTP
      SET APPROVAL_STATE = 3
      WHERE OBJ_ID = :X$CJ_ID AND APPROVAL_STATE = 2;
    END

    INSERT INTO CJ2_JOURNAL_PTP
    (CJ_ID, PTP_ID, APPROVAL_STATE)
    VALUES (:V$CJ_ID, :I$PTP_ID, :V$STATE);

    I$FOR = SUBSTRING(I$FOR FROM P + 1);

  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_PTP_SET (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40),
    I$PARENT_ID BIGINT,
    I$OBJ_NAME VARCHAR(400),
    I$OWNER_ID BIGINT,
    I$LEVEL_ID BIGINT,
    I$SUBJECT_ID BIGINT,
    I$EDU_LEVEL_ID BIGINT = NULL,
    I$STAGE_MASK BIGINT = NULL)
RETURNS (
    OBJ_ID BIGINT)
AS
DECLARE VARIABLE V$USER_ID BIGINT;
DECLARE VARIABLE V$USER_TYPE SMALLINT;
DECLARE VARIABLE V$OWNER_ID BIGINT;
DECLARE VARIABLE V$TEACHER_ID BIGINT;
DECLARE VARIABLE V$LC BIGINT;
DECLARE VARIABLE V$MUL BIGINT;
begin

  -- LEVEL_NUM посчитается триггером, PTP_HOURS посчитаем после сохранения всех уроков

  -- Права доступа к приложению КЖ или ВД
  -- !!! Надо проверять конкретный тип, который пользователь хочет создать
  IF(I$USER_ID = 'Веб-администратор') THEN V$USER_ID = 1; ELSE V$USER_ID = CAST(I$USER_ID AS BIGINT);
  SELECT FIRST 1 U.USER_TYPE, U.OBJ_ID
  FROM USERS U
  JOIN LUSERS L ON L.USER_ID = U.USER_ID AND L.READ_ONLY = 0 AND L.LEVEL_ID IN (/* O */ 46, 189, 274, 275, /* C */ 230, 249, 254, 255, /* D */ 180, /* U */ 256)
  WHERE U.USER_ID = :V$USER_ID AND U.DATE_DEL IS NULL AND U.IS_BLOCKED = 0 AND (U.EXP_DATE IS NULL OR U.EXP_DATE > CURRENT_DATE)
  INTO :V$USER_TYPE, :V$TEACHER_ID;

  IF(V$USER_TYPE IS NULL) THEN EXCEPTION DATA_ERROR 'У вас нет доступа';

  SELECT GEN, MULTIPLIER FROM GEN INTO :V$LC, :V$MUL;
  IF(I$OBJ_ID IS NOT NULL) THEN
  BEGIN
    IF(I$OBJ_ID / V$MUL <> V$LC) THEN EXCEPTION DATA_ERROR 'Рабочая программа или типовой ПП созданы в другой базе, нельзя редактировать';
  END

  -- Владельца можно не назначать для РП, а также в эталонной базе
  IF(I$OWNER_ID IS NULL AND I$LEVEL_ID <> 2167 AND V$LC <> 0) THEN EXCEPTION DATA_ERROR 'Не назначен владелец ПП';

  I$OBJ_NAME = TRIM(I$OBJ_NAME);

  -- LEVEL_ID соответствует допустимому ? пока упрощенная проверка
  IF(I$LEVEL_ID IS NULL OR NOT EXISTS(
    SELECT FIRST 1 1
    FROM LISTVALS
    WHERE LIST_ID = 25 AND IS_DEL = 0 AND LISTVAL_ID = :I$LEVEL_ID
  ))
  THEN
    EXCEPTION DATA_ERROR 'Недопустимый тип ПТП или параллель';

  -- Предмет не указывается для ГПД и ДО
  IF(I$LEVEL_ID IN (2141, 2143)) THEN I$SUBJECT_ID = NULL;
  ELSE IF(I$SUBJECT_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не назначен предмет';

  IF(I$PARENT_ID IS NOT NULL AND NOT EXISTS(
      SELECT FIRST 1 1
      FROM PTP
      WHERE OBJ_ID = :I$PARENT_ID AND DATE_DEL IS NULL
  ))
  THEN
    EXCEPTION DATA_ERROR 'Родительский ПТП не найден';

  IF(I$OBJ_ID IS NULL) THEN
  BEGIN

      -- Сохранять может или админ, или свой ПТП, или ПТП прикрепленный к своему классу
      IF(V$TEACHER_ID <> I$OWNER_ID AND V$USER_TYPE NOT IN (1, 5, 6)) THEN
          EXCEPTION DATA_ERROR 'Только завуч может сохранять ПТП, назначая автором другого сотрудника';

      -- Часы заполняются сразу при добавлении
      INSERT INTO PTP
      (PARENT_ID, OBJ_NAME, LEVEL_ID, SUBJECT_ID, OWNER_ID, PTP_HOURS, EDU_LEVEL_ID, STAGE_MASK)
      VALUES (:I$PARENT_ID, :I$OBJ_NAME, :I$LEVEL_ID, :I$SUBJECT_ID, :I$OWNER_ID, 0, :I$EDU_LEVEL_ID, :I$STAGE_MASK)
      RETURNING OBJ_ID INTO :OBJ_ID;

  END
  ELSE
  BEGIN

      -- Есть ли у нас права доступа к этому ПТП ?
      SELECT FIRST 1 P.OBJ_ID, P.OWNER_ID
      FROM PTP P
      WHERE P.OBJ_ID = :I$OBJ_ID AND P.DATE_DEL IS NULL
      INTO :OBJ_ID, :V$OWNER_ID;

      IF(OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'ПТП не найден';
      IF(V$OWNER_ID IS NOT NULL AND I$OWNER_ID <> V$OWNER_ID AND V$USER_TYPE NOT IN (1, 5, 6)) THEN
          EXCEPTION DATA_ERROR 'Менять владельца ПТП может только автор или пользователь с административными правами доступа';

      -- Или владелец, или есть журнал связанный с этим ПТП, где данный учитель является предметником
      IF(V$USER_TYPE NOT IN (1, 5, 6) AND NOT (
          V$TEACHER_ID = V$OWNER_ID OR
          EXISTS (
              SELECT FIRST 1 1
              FROM CJ2_JOURNAL_PTP P
              JOIN CJ2_JOURNAL J ON J.OBJ_ID = P.CJ_ID AND J.TEACHER_ID = :V$OWNER_ID
              WHERE P.DATE_DEL IS NULL AND P.PTP_ID = :I$OBJ_ID
          )
      )) THEN
      BEGIN
          -- Просто выходим без возврата чего-либо, сообщение будет отдельно
          EXIT;
          -- EXCEPTION DATA_ERROR 'Менять чужой ПТП может только автор или пользователь с административными правами доступа';
      END

      -- Нельзя менять ПТП, к которому прикреплены другие ПТП
      -- !!!

      -- Часы тут не трогаем, они обновятся при сохранении уроков
      UPDATE PTP
      SET OBJ_NAME = :I$OBJ_NAME, OWNER_ID = :I$OWNER_ID, EDU_LEVEL_ID = :I$EDU_LEVEL_ID, STAGE_MASK = :I$STAGE_MASK
      WHERE OBJ_ID = :I$OBJ_ID;

  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_PTP_TRANSFER
AS
declare variable V$SRC_ID bigint;
declare variable V$OWNER_ID bigint;
declare variable V$SUBJECT_ID bigint;
declare variable V$STAGE_LV bigint;
declare variable V$PLAN_NAME varchar(1000);
declare variable V$PTP_ID bigint;
declare variable V$SRC_LESSON_ID bigint;
declare variable N integer;
declare variable V$THEME varchar(1000);
declare variable V$HOMETASK varchar(1000);
declare variable V$LESSON_ID bigint;
declare variable V$CONTROL_LV bigint;
begin

  FOR
      SELECT L87.OBJ_ID, V49.LISTVAL_ID, LP51.PARENT_ID, V473.VAL, V472.VAL
      FROM LINKS L2
      JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
      JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
      JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
      -- Сами ПТП
      JOIN LINKS L87 ON L87.PARENT_ID = L8.OBJ_ID AND L87.OBJ_TYPE_ID = 87 AND L87.DATE_DEL IS NULL
      JOIN LINKS LP51 ON LP51.OBJ_ID = L87.OBJ_ID AND LP51.PARENT_TYPE_ID = 51 AND LP51.DATE_DEL IS NULL
      -- Родительский ПТП
      LEFT JOIN VALR V2834 ON V2834.OBJ_ID = L87.OBJ_ID AND V2834.PARAM_ID = 2834 AND V2834.IS_DEL = 0
      -- Автор
      LEFT JOIN VALR V473 ON V473.OBJ_ID = L87.OBJ_ID AND V473.PARAM_ID = 473 AND V473.IS_DEL = 0
      -- Название
      JOIN VALS V472 ON V472.OBJ_ID = L87.OBJ_ID AND V472.PARAM_ID = 472 AND V472.IS_DEL = 0
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND V2834.VAL IS NULL
      INTO :V$SRC_ID, :V$STAGE_LV, :V$SUBJECT_ID, :V$OWNER_ID, :V$PLAN_NAME
  DO
  BEGIN

      -- Повторно не импортируем
      V$PTP_ID = NULL;
      SELECT FIRST 1 P.OBJ_ID
      FROM PTP P
      WHERE P.LEVEL_ID = :V$STAGE_LV AND P.SUBJECT_ID = :V$SUBJECT_ID AND P.OBJ_NAME = :V$PLAN_NAME
      INTO :V$PTP_ID;

      IF(V$PTP_ID IS NULL) THEN
      BEGIN

          -- Добавляем ПТП
          INSERT INTO PTP
          (OBJ_NAME, PARENT_ID, OWNER_ID, LEVEL_ID, SUBJECT_ID, PTP_HOURS)
          VALUES (:V$PLAN_NAME, NULL, :V$OWNER_ID, :V$STAGE_LV, :V$SUBJECT_ID, 0)
          RETURNING OBJ_ID INTO :V$PTP_ID;

          -- Уроки в ПТП
          N = 1;

          FOR
              SELECT L88.OBJ_ID, V476.VAL, V477.VAL
              FROM LINKS L88
              JOIN VALI V475 ON V475.OBJ_ID = L88.OBJ_ID AND V475.PARAM_ID = 475 AND V475.IS_DEL = 0
              JOIN VALS V476 ON V476.OBJ_ID = L88.OBJ_ID AND V476.PARAM_ID = 476 AND V476.IS_DEL = 0
              LEFT JOIN VALS V477 ON V477.OBJ_ID = L88.OBJ_ID AND V477.PARAM_ID = 477 AND V477.IS_DEL = 0
              WHERE L88.PARENT_ID = :V$SRC_ID AND L88.OBJ_TYPE_ID = 88 AND L88.DATE_DEL IS NULL
              ORDER BY V475.VAL
              INTO :V$SRC_LESSON_ID, :V$THEME, :V$HOMETASK
          DO
          BEGIN

              INSERT INTO PTP_LESSONS
              (PTP_ID, LESSON_NUM, THEME_TEXT, HOMETASK_TEXT, DURATION)
              VALUES (:V$PTP_ID, :N, :V$THEME, :V$HOMETASK, 1)
              RETURNING OBJ_ID INTO :V$LESSON_ID;

              -- Контроли к уроку
              FOR
                  SELECT V546.LISTVAL_ID
                  FROM LINKS L89
                  JOIN VALL V546 ON V546.OBJ_ID = L89.OBJ_ID AND V546.PARAM_ID = 546 AND V546.IS_DEL = 0
                  WHERE L89.PARENT_ID = :V$SRC_LESSON_ID AND L89.OBJ_TYPE_ID = 89 AND L89.DATE_DEL IS NULL
                  INTO :V$CONTROL_LV
              DO
              BEGIN

                  INSERT INTO PTP_LESSON_CONTROLS
                  (LESSON_ID, CONTROL_TYPE_ID)
                  VALUES(:V$LESSON_ID, :V$CONTROL_LV);

              END

              N = N + 1;

          END

      END

  END

  UPDATE PTP P
  SET PTP_HOURS = (SELECT COUNT(*) FROM PTP_LESSONS L WHERE L.PTP_ID = P.OBJ_ID);

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_RANDOMDATA (
    I$CJ_ID BIGINT)
AS
declare variable V$DATE date;
declare variable N integer;
declare variable V$LESSON_ID bigint;
declare variable V$TEACHER_ID bigint;
declare variable V$GRADE_ID bigint;
declare variable V$CONTROL_ID bigint;
declare variable V$PERSON_ID bigint;
begin

  -- Удаляем все что было
  DELETE FROM CJ2_JOURNAL_LESSONS
  WHERE CJ_ID = :I$CJ_ID;

  SELECT TEACHER_ID, GRADE_ID
  FROM CJ2_JOURNAL
  WHERE OBJ_ID = :I$CJ_ID
  INTO :V$TEACHER_ID, :V$GRADE_ID;

  -- Добавить много уроков
  V$DATE = '01.09.' || EXTRACT(YEAR FROM CURRENT_DATE);
  N = 0;

  WHILE (N < 70) DO
  BEGIN
      N = N + 1;
      V$DATE = DATEADD(DAY, 1, V$DATE);

      -- Сам урок
      INSERT INTO CJ2_JOURNAL_LESSONS
      (CJ_ID, LESSON_DATE, LESSON_NUM, TEACHER_ID, LESSON_THEME, IS_COMPLETED)
      VALUES (:I$CJ_ID, :V$DATE, 1, :V$TEACHER_ID, 'Урок ' || :N, IIF(:N < 60, 1, 0))
      RETURNING OBJ_ID
      INTO :V$LESSON_ID;

      -- Системный контроль
      INSERT INTO CJ2_CONTROL
      (LESSON_ID, CONTROL_TYPE_ID, MARK_SYSTEM_ID)
      VALUES (:V$LESSON_ID, 0, 0)
      RETURNING CONTROL_ID
      INTO :V$CONTROL_ID;

      -- Отсутствие выставляем 1 и 2 ученику
      FOR
          SELECT FIRST 2 L10.OBJ_ID
          FROM LINKS L10
          WHERE L10.PARENT_ID = :V$GRADE_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
          INTO :V$PERSON_ID
      DO
      BEGIN
          INSERT INTO CJ2_MARK
          (CONTROL_ID, STUDENT_ID, MARK_TYPE_ID, MARK_DATE, IS_USED)
          VALUES (:V$CONTROL_ID, :V$PERSON_ID, 91, :V$DATE, 1);
      END

      -- Работа на уроке
      INSERT INTO CJ2_CONTROL
      (LESSON_ID, CONTROL_TYPE_ID, MARK_SYSTEM_ID)
      VALUES (:V$LESSON_ID, 1058, 400)
      RETURNING CONTROL_ID
      INTO :V$CONTROL_ID;

      -- Отметки выставляем детям с 2 по 12
      FOR
          SELECT FIRST 10 SKIP 2 L10.OBJ_ID
          FROM LINKS L10
          WHERE L10.PARENT_ID = :V$GRADE_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
          INTO :V$PERSON_ID
      DO
      BEGIN
          INSERT INTO CJ2_MARK
          (CONTROL_ID, STUDENT_ID, MARK_TYPE_ID, MARK_DATE, IS_USED)
          VALUES (:V$CONTROL_ID, :V$PERSON_ID, 401 + TRUNC(RAND() * 4), :V$DATE, 1);
      END

  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_REPLACEMENT_ADD (
    I$USER_ID VARCHAR(40) NOT NULL,
    I$OBJ_ID BIGINT,
    I$TEACHER_ID BIGINT NOT NULL,
    I$DATE_FROM DATE NOT NULL,
    I$DATE_TO DATE,
    I$REASON_ID BIGINT NOT NULL)
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable N integer;
begin

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  -- Запись замещения можно добавлять не старше 1 года назад
  IF(I$DATE_FROM < DATEADD(-1 YEAR TO CURRENT_DATE)) THEN EXCEPTION DATA_ERROR 'Слишком старая дата начала действия замещения';
  IF(I$DATE_FROM > I$DATE_TO) THEN EXCEPTION DATA_ERROR 'Дата окончания замещения должна быть не ранее даты начала';

  -- Проверяем наличие других замещений в тот же период у того же сотрудника
  SELECT FIRST 1 1
  FROM CJ2_REPL_PLAN
  WHERE (:I$OBJ_ID IS NULL OR OBJ_ID <> :I$OBJ_ID) AND (PERSON_ID = :I$TEACHER_ID) AND
    (
      (DATE_FROM <= :I$DATE_FROM AND (DATE_TO IS NULL OR DATE_TO > :I$DATE_FROM)) OR
      (DATE_FROM >= :I$DATE_FROM AND (:I$DATE_TO IS NULL OR :I$DATE_TO > DATE_FROM))
    )
    AND DATE_DEL IS NULL
  INTO :N;

  IF(N > 0) THEN EXCEPTION DATA_ERROR 'В указанный период у данного сотрудника уже есть действующее замещение';

  IF(I$OBJ_ID IS NULL) THEN
  BEGIN

      INSERT INTO CJ2_REPL_PLAN
      (PERSON_ID, DATE_FROM, DATE_TO, REASON_ID)
      VALUES (:I$TEACHER_ID, :I$DATE_FROM, :I$DATE_TO, :I$REASON_ID)
      RETURNING OBJ_ID INTO :OBJ_ID;

  END
  ELSE
  BEGIN

      OBJ_ID = I$OBJ_ID;

      UPDATE CJ2_REPL_PLAN
      SET PERSON_ID = :I$TEACHER_ID, DATE_FROM = :I$DATE_FROM, DATE_TO = :I$DATE_TO, REASON_ID = :I$REASON_ID
      WHERE OBJ_ID = :I$OBJ_ID AND DATE_DEL IS NULL;

  END

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_REPLACEMENT_DELETE (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    ERROR_TEXT VARCHAR(10))
AS
declare variable N integer;
begin

  N = 0;

  SELECT FIRST 1 1
  FROM CJ2_REPL_PLAN
  WHERE OBJ_ID = :I$OBJ_ID AND DATE_DEL IS NULL
  INTO :N;

  IF(N = 0) THEN EXCEPTION DATA_ERROR 'Запись замещения не найдена';

  UPDATE CJ2_REPL_PLAN
  SET DATE_DEL = CURRENT_TIMESTAMP
  WHERE OBJ_ID = :I$OBJ_ID AND DATE_DEL IS NULL;

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_REPLACEMENT_GET (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(1000))
AS
declare variable V$OBJ_ID bigint;
declare variable V$PERSON_ID bigint;
declare variable V$REASON_ID bigint;
declare variable V$DATE_FROM date;
declare variable V$DATE_TO date;
declare variable S varchar(1000);
begin

  SELECT P.OBJ_ID, P.PERSON_ID, P.REASON_ID, P.DATE_FROM, P.DATE_TO
  FROM CJ2_REPL_PLAN P
  WHERE P.DATE_DEL IS NULL AND P.OBJ_ID = :I$OBJ_ID
  INTO :V$OBJ_ID, :V$PERSON_ID, :V$REASON_ID, :V$DATE_FROM, :V$DATE_TO;

  IF(I$OBJ_ID IS NOT NULL AND V$OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Запись не найдена';

  TAG_NAME = 'id';
  VAL = V$OBJ_ID;
  SUSPEND;

  TAG_NAME = 'person_id:values:value';
  VAL = V$PERSON_ID;
  SUSPEND;
  FOR
    SELECT TEACHER_ID, TEACHER_CAPTION
    FROM PARAGRAF_GRADE_TEACHERS_LIST(NULL, 1)
    ORDER BY 2
    INTO :V$OBJ_ID, :S
  DO
  BEGIN
    TAG_NAME = 'person_id:selection:option';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'person_id:selection:option:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'person_id:selection:option:value';
    VAL = S;
    SUSPEND;
  END

  TAG_NAME = 'reason_id:values:value';
  VAL = V$REASON_ID;
  SUSPEND;
  FOR
    SELECT LISTVAL_ID, VAL
    FROM LISTVALS_LIST(317)
    WHERE IS_DEL = 0
    ORDER BY 2
    INTO :V$OBJ_ID, :S
  DO
  BEGIN
    TAG_NAME = 'reason_id:selection:option';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'reason_id:selection:option:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'reason_id:selection:option:value';
    VAL = S;
    SUSPEND;
  END

  TAG_NAME = 'date_from';
  VAL = (SELECT VAL FROM DATE2ISO(:V$DATE_FROM));
  SUSPEND;

  TAG_NAME = 'date_to';
  VAL = (SELECT VAL FROM DATE2ISO(:V$DATE_TO));
  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_REPLACEMENT_LIST (
    I$MODE INTEGER,
    I$USER_ID VARCHAR(40),
    I$OBJ_ID BIGINT = null)
RETURNS (
    OBJ_ID BIGINT,
    PERSON_ID BIGINT,
    PERSON_NAME VARCHAR(1000),
    DATE_FROM DATE,
    DATE_TO DATE,
    REASON_ID BIGINT,
    REASON_TEXT VARCHAR(200))
AS
begin
  -- I$MODE задает полный (1) или только актуальный (0) список

  FOR
      SELECT P.OBJ_ID, P.PERSON_ID, P.DATE_FROM, P.DATE_TO, P.REASON_ID, C.CAPTION, R.VAL
      FROM CJ2_REPL_PLAN P
      LEFT JOIN OBJECT_CAPTION_GET(P.PERSON_ID) C ON 1 = 1
      JOIN LISTVALS LV ON LV.LISTVAL_ID = P.REASON_ID
      JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
      WHERE P.DATE_DEL IS NULL AND (:I$MODE = 1 OR P.DATE_TO IS NULL OR P.DATE_TO >= CURRENT_DATE)
          AND (:I$OBJ_ID IS NULL OR P.OBJ_ID = :I$OBJ_ID)
      ORDER BY P.DATE_FROM
      INTO :OBJ_ID, :PERSON_ID, :DATE_FROM, :DATE_TO, :REASON_ID, :PERSON_NAME, :REASON_TEXT
  DO
  BEGIN
      SUSPEND;
  END
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_REPL_APPROVE_DATES (
    I$USER_ID VARCHAR(40))
RETURNS (
    VAL VARCHAR(20))
AS
declare variable D date;
begin

  FOR
    SELECT DISTINCT P.REPL_DATE
    FROM CJ2_REPL_PROCESS P
    WHERE P.DATE_DEL IS NULL AND P.IS_APPROVED = 0
    ORDER BY 1
    INTO :D
  DO
  BEGIN
    VAL = (SELECT VAL FROM DATE2ISO(:D, 0));
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_REPL_BYDATE (
    I$DATE DATE,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$YEAR_ID BIGINT;
DECLARE VARIABLE OBJ_ID BIGINT;
DECLARE VARIABLE PERSON_ID BIGINT;
DECLARE VARIABLE DATE_FROM DATE;
DECLARE VARIABLE DATE_TO DATE;
DECLARE VARIABLE REASON_ID BIGINT;
DECLARE VARIABLE PERSON_NAME VARCHAR(400);
DECLARE VARIABLE V$GRADE_ID BIGINT;
DECLARE VARIABLE V$GUP_ID BIGINT;
DECLARE VARIABLE V$STAGE BIGINT;
DECLARE VARIABLE S VARCHAR(1000);
begin

  SELECT FIRST 1 V1236.LISTVAL_ID
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$YEAR_ID;

  TAG_NAME = 'items::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT P.OBJ_ID, P.PERSON_ID, P.DATE_FROM, P.DATE_TO, P.REASON_ID, C.CAPTION, R.VAL
    FROM CJ2_REPL_PLAN P
    LEFT JOIN OBJECT_CAPTION_GET(P.PERSON_ID) C ON 1 = 1
    JOIN LISTVALS LV ON LV.LISTVAL_ID = P.REASON_ID
    JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
    WHERE P.DATE_DEL IS NULL AND P.DATE_FROM <= :I$DATE AND (P.DATE_TO IS NULL OR P.DATE_TO >= :I$DATE)
    ORDER BY P.DATE_FROM
    INTO :OBJ_ID, :PERSON_ID, :DATE_FROM, :DATE_TO, :REASON_ID, :PERSON_NAME, :S
  DO
  BEGIN
    TAG_NAME = 'items:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'items:r:id';
    VAL = OBJ_ID;
    SUSPEND;
    TAG_NAME = 'items:r:person_id';
    VAL = PERSON_ID;
    SUSPEND;
    TAG_NAME = 'items:r:reason_id';
    VAL = REASON_ID;
    SUSPEND;
    TAG_NAME = 'items:r:name';
    VAL = PERSON_NAME;
    SUSPEND;
    TAG_NAME = 'items:r:reason_text';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'items:r:date_from';
    VAL = (SELECT VAL FROM DATE2ISO(:DATE_FROM, 0));
    SUSPEND;
    TAG_NAME = 'items:r:date_to';
    VAL = (SELECT VAL FROM DATE2ISO(:DATE_TO, 0));
    SUSPEND;

    -- Журналы только реальные
    TAG_NAME = 'items:r:cj::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT J.OBJ_ID, J.JOURNAL_NAME || IIF(J.SUBJECT_ID IS NULL, '', ' (' || C.CAPTION || ')'), J.GRADE_ID, LP2.EXT_OBJ_ID, J.STAGE_INDEX
      FROM CJ2_JOURNAL J
      LEFT JOIN LINKS LP2 ON LP2.OBJ_ID = J.GRADE_ID AND LP2.PARENT_TYPE_ID = 2 AND LP2.DATE_DEL IS NULL
      LEFT JOIN OBJECT_CAPTION_GET(J.SUBJECT_ID) C ON 1 = 1
      WHERE J.DATE_DEL IS NULL AND J.YEAR_ID = :V$YEAR_ID AND J.TEACHER_ID = :PERSON_ID AND J.JOURNAL_TYPE < 10
      ORDER BY J.STAGE_INDEX, 2
      INTO :OBJ_ID, :S, :V$GRADE_ID, :V$GUP_ID, :V$STAGE
    DO
    BEGIN
      TAG_NAME = 'items:r:cj:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'items:r:cj:r:id';
      VAL = OBJ_ID;
      SUSPEND;
      TAG_NAME = 'items:r:cj:r:grade_id';
      VAL = V$GRADE_ID;
      SUSPEND;
      TAG_NAME = 'items:r:cj:r:master_id';
      VAL = V$GUP_ID;
      SUSPEND;
      TAG_NAME = 'items:r:cj:r:stage';
      VAL = V$STAGE;
      SUSPEND;
      TAG_NAME = 'items:r:cj:r:name';
      VAL = S;
      SUSPEND;
    END
  END

  -- Добавляем все журналы с вакантными ставками
  IF(EXISTS(
    SELECT FIRST 1 1
    FROM CJ2_JOURNAL J
    WHERE J.DATE_DEL IS NULL AND J.YEAR_ID = :V$YEAR_ID AND J.TEACHER_ID IS NULL
  )) THEN
  BEGIN
    TAG_NAME = 'items:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'items:r:id';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'items:r:person_id';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'items:r:reason_id';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'items:r:name';
    VAL = 'Вакантные журналы';
    SUSPEND;
    TAG_NAME = 'items:r:reason_text';
    VAL = 'Вакантные журналы';
    SUSPEND;
    TAG_NAME = 'items:r:date_from';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'items:r:date_to';
    VAL = NULL;
    SUSPEND;

    TAG_NAME = 'items:r:cj::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT J.OBJ_ID, J.JOURNAL_NAME || IIF(J.SUBJECT_ID IS NULL, '', ' (' || C.CAPTION || ')'), J.GRADE_ID, LP2.EXT_OBJ_ID, J.STAGE_INDEX
      FROM CJ2_JOURNAL J
      LEFT JOIN LINKS LP2 ON LP2.OBJ_ID = J.GRADE_ID AND LP2.PARENT_TYPE_ID = 2 AND LP2.DATE_DEL IS NULL
      LEFT JOIN OBJECT_CAPTION_GET(J.SUBJECT_ID) C ON 1 = 1
      WHERE J.DATE_DEL IS NULL AND J.YEAR_ID = :V$YEAR_ID AND J.TEACHER_ID IS NULL
      ORDER BY J.STAGE_INDEX, 2
      INTO :OBJ_ID, :S, :V$GRADE_ID, :V$GUP_ID, :V$STAGE
    DO
    BEGIN
      TAG_NAME = 'items:r:cj:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'items:r:cj:r:id';
      VAL = OBJ_ID;
      SUSPEND;
      TAG_NAME = 'items:r:cj:r:grade_id';
      VAL = V$GRADE_ID;
      SUSPEND;
      TAG_NAME = 'items:r:cj:r:master_id';
      VAL = V$GUP_ID;
      SUSPEND;
      TAG_NAME = 'items:r:cj:r:stage';
      VAL = V$STAGE;
      SUSPEND;
      TAG_NAME = 'items:r:cj:r:name';
      VAL = S;
      SUSPEND;
    END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_REPL_CAL RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(200))
AS
declare variable V$YEAR integer;
declare variable V$DATE1 date;
declare variable V$DATE date;
declare variable V$ENDATE date;
declare variable V$DAY integer;
declare variable V$DAYMASK integer;
begin

  SELECT FIRST 1 LV.COST
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$YEAR;

  -- Первый день учебного года
  V$DATE1 = '01.09.' || V$YEAR;

  -- Первый день недели = понедельник
  IF(EXTRACT(WEEKDAY FROM V$DATE1) = 0) THEN V$DATE = DATEADD(1 DAY TO V$DATE1);
  ELSE V$DATE = DATEADD((- EXTRACT(WEEKDAY FROM V$DATE1) + 1) DAY TO V$DATE1);

  -- Окончание = следующая неделя
  V$ENDATE = DATEADD(7 DAY TO CURRENT_DATE);

  -- Формируем маску обычных учебных дней по пересечению всех выгружаемых шаблонов расписания
  V$DAYMASK = 0;
  FOR
    SELECT V402.LISTVAL_ID - 798
    FROM LINKS L2
    JOIN LINKS L68 ON L68.PARENT_ID = L2.OBJ_ID AND L68.OBJ_TYPE_ID = 68 AND L68.DATE_DEL IS NULL
    JOIN LINKS L3 ON L3.PARENT_ID = L68.OBJ_ID AND L3.OBJ_TYPE_ID = 3 AND L3.DATE_DEL IS NULL
    JOIN LINKS L59 ON L59.PARENT_ID = L3.OBJ_ID AND L59.OBJ_TYPE_ID = 59 AND L59.DATE_DEL IS NULL
    JOIN VALL V1341 ON V1341.OBJ_ID = L59.OBJ_ID AND V1341.PARAM_ID = 1341 AND V1341.IS_DEL = 0 AND V1341.LISTVAL_ID = 2
    JOIN LINKS L6 ON L6.PARENT_ID = L59.OBJ_ID AND L6.OBJ_TYPE_ID = 6 AND L6.DATE_DEL IS NULL
    JOIN VALL V402 ON V402.OBJ_ID = L6.OBJ_ID AND V402.PARAM_ID = 402 AND V402.IS_DEL = 0
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :V$DAY
  DO
  BEGIN
    V$DAYMASK = BIN_OR(V$DAYMASK, BIN_SHL(1, V$DAY));
  END
  TAG_NAME = 'workdays';
  VAL = V$DAYMASK;
  SUSPEND;

  TAG_NAME = 'dates::json&colon;array';
  VAL = 1;
  SUSPEND;

  WHILE(V$DATE <= V$ENDATE) DO
  BEGIN
    TAG_NAME = 'dates:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dates:r:date';
    VAL = (SELECT RESULT FROM DATE2STR(:V$DATE));
    SUSPEND;
    V$DAY = EXTRACT(WEEKDAY FROM V$DATE);
    IF(V$DAY = 0) THEN V$DAY = 6; ELSE V$DAY = V$DAY - 1;
    TAG_NAME = 'dates:r:wd';
    VAL = V$DAY;
    SUSPEND;
    TAG_NAME = 'dates:r:disabled';
    VAL = IIF(V$DATE >= V$DATE1 AND BIN_AND(V$DAYMASK, BIN_SHL(1, V$DAY)) > 0, 0, 1);
    SUSPEND;
    TAG_NAME = 'dates:r:holiday';
    VAL = 0;
    SUSPEND;
    TAG_NAME = 'dates:r:status';
    VAL = 0;
    SUSPEND;

    V$DATE = DATEADD(1 DAY TO V$DATE);
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_REPL_DAPPROVE_DATES (
    I$USER_ID VARCHAR(40))
RETURNS (
    APPR_DATE VARCHAR(20),
    ORDER_DATE VARCHAR(20),
    ORDER_NUM VARCHAR(200))
AS
declare variable V$YEAR date;
declare variable D date;
declare variable D2 date;
begin

  SELECT LV.TAG
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$YEAR;

  FOR
    SELECT DISTINCT P.REPL_DATE, P.ORDER_DATE, P.ORDER_NUM
    FROM CJ2_REPL_PROCESS P
    WHERE P.DATE_DEL IS NULL AND P.IS_APPROVED = 1 AND P.REPL_DATE >= :V$YEAR
    ORDER BY 2 DESC, 1
    INTO :D, :D2, :ORDER_NUM
  DO
  BEGIN
    APPR_DATE = (SELECT VAL FROM DATE2ISO(:D, 0));
    ORDER_DATE = (SELECT VAL FROM DATE2ISO(:D2, 0));
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_REPL_DAYDATA (
    I$DATE DATE,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
declare variable V$OBJ_ID bigint;
declare variable V$PERSON_ID bigint;
declare variable S varchar(1000);
declare variable V$DATE_FROM date;
declare variable V$DATE_TO date;
declare variable V$REASON_ID bigint;
declare variable V$N integer;
declare variable V$CJ_ID bigint;
declare variable V$REPL_CJ_ID bigint;
declare variable V$REPL_PERSON_ID bigint;
declare variable V$DAY integer;
declare variable V$ROOM_ID bigint;
declare variable V$SUBJECT_ID bigint;
declare variable V$GRADE_ID bigint;
declare variable V$PS_ID bigint;
begin

  -- Более неактуально

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_REPL_PROCESS_ADD (
    I$OBJ_ID BIGINT,
    I$REPL_DATE DATE NOT NULL,
    I$PLAN_ID BIGINT,
    I$TEACHER_ID BIGINT,
    I$REPL_TEACHER_ID BIGINT,
    I$CJ_ID BIGINT,
    I$LESSON_NUM INTEGER,
    I$REPL_CJ_ID BIGINT,
    I$USER_ID VARCHAR(40) = NULL)
RETURNS (
    OBJ_ID BIGINT)
AS
DECLARE VARIABLE V$REPL_DATE DATE;
DECLARE VARIABLE V$PLAN_ID BIGINT;
DECLARE VARIABLE V$PERSON_ID BIGINT;
DECLARE VARIABLE V$APPROVED SMALLINT;
DECLARE VARIABLE V$DT TIME;
DECLARE VARIABLE V$SCH_ID BIGINT;
DECLARE VARIABLE V$YEAR_ID BIGINT;
DECLARE VARIABLE N INTEGER;
DECLARE VARIABLE TH VARCHAR(2);
DECLARE VARIABLE TM VARCHAR(2);
begin

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  -- Запрещать обнулять PLAN_ID для уже связанной записи
  -- Также нельзя менять дату
  V$APPROVED = 0;

  IF(I$OBJ_ID IS NOT NULL) THEN
  BEGIN
    SELECT REPL_DATE, PLAN_ID, PERSON_ID, IS_APPROVED
    FROM CJ2_REPL_PROCESS
    WHERE OBJ_ID = :I$OBJ_ID AND DATE_DEL IS NULL
    INTO :V$REPL_DATE, :V$PLAN_ID, :V$PERSON_ID, :V$APPROVED;

    IF(V$REPL_DATE IS NULL) THEN EXCEPTION DATA_ERROR 'Запись замещения утрачена';
    IF(V$PLAN_ID <> I$PLAN_ID OR (V$PLAN_ID IS NULL AND I$PLAN_ID IS NOT NULL) OR (V$PLAN_ID IS NOT NULL AND I$PLAN_ID IS NULL)) THEN
      EXCEPTION DATA_ERROR 'Нельзя изменять привязку к плану замещения';
    IF(V$PERSON_ID <> I$TEACHER_ID) THEN EXCEPTION DATA_ERROR 'Нельзя изменять учителя, который замещается';
  END

  -- Нельзя делать перекрывающие записи замещения для одного и того же учителя
  N = 0;
  SELECT FIRST 1 1
  FROM CJ2_REPL_PROCESS
  WHERE (:I$OBJ_ID IS NULL OR OBJ_ID <> :I$OBJ_ID) AND REPL_DATE = :I$REPL_DATE AND PERSON_ID = :I$TEACHER_ID AND DATE_DEL IS NULL
    AND (:I$CJ_ID IS NULL OR CJ_ID = :I$CJ_ID) AND LESSON_NUM = :I$LESSON_NUM
  INTO :N;

  IF(N > 0) THEN EXCEPTION DATA_ERROR 'Для этого учителя уже есть замещающие записи на указанную дату';

  -- Сетку времени уроков всегда смотрим по исходному журналу, даже если у замещающего журнала другая сетка
  SELECT FIRST 1 V1236.LISTVAL_ID
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$YEAR_ID;

  IF(I$LESSON_NUM > 60) THEN
  BEGIN
    TH = TRUNC(I$LESSON_NUM / 60);
    IF(CHAR_LENGTH(TH) < 2) THEN TH = '0' || TH;
    TM = I$LESSON_NUM - TRUNC(I$LESSON_NUM / 60) * 60;
    IF(CHAR_LENGTH(TM) < 2) THEN TM = '0' || TM;
    V$DT = TH || ':' || TM;
  END
  ELSE
  BEGIN
    -- Ищем подходящий шаблон расписания
    SELECT FIRST 1 SI.SCHEDULE_ID
    FROM SCHEDULE_ITEMS SI
    JOIN LINKS LP3 ON LP3.OBJ_ID = SI.SCHEDULE_ID AND LP3.PARENT_TYPE_ID = 3 AND LP3.DATE_DEL IS NULL
    JOIN VALD V3120 ON V3120.OBJ_ID = SI.SCHEDULE_ID AND V3120.PARAM_ID = 3120 AND V3120.IS_DEL = 0 AND V3120.VAL <= :I$REPL_DATE
    JOIN VALD V3121 ON V3121.OBJ_ID = SI.SCHEDULE_ID AND V3121.PARAM_ID = 3121 AND V3121.IS_DEL = 0 AND V3121.VAL >= :I$REPL_DATE
    WHERE SI.DATE_DEL IS NULL AND SI.CJ_ID = :I$CJ_ID
    INTO :V$SCH_ID;

    -- Если нет расписания где упомянут данный журнал, ищем первый попавшийся
    IF(V$SCH_ID IS NULL) THEN
    SELECT FIRST 1 L59.OBJ_ID
    FROM LINKS L68
    JOIN LINKS L3 ON L3.PARENT_ID = L68.OBJ_ID AND L3.OBJ_TYPE_ID = 3 AND L3.DATE_DEL IS NULL
    JOIN VALL V37 ON V37.OBJ_ID = L3.OBJ_ID AND V37.PARAM_ID = 37 AND V37.IS_DEL = 0 AND V37.LISTVAL_ID = :V$YEAR_ID
    JOIN LINKS L59 ON L59.PARENT_ID = L3.OBJ_ID AND L59.OBJ_TYPE_ID = 59 AND L59.DATE_DEL IS NULL
    JOIN VALL V1341 ON V1341.OBJ_ID = L59.OBJ_ID AND V1341.PARAM_ID = 1341 AND V1341.IS_DEL = 0 AND V1341.LISTVAL_ID = 2
    JOIN VALD V3120 ON V3120.OBJ_ID = L59.OBJ_ID AND V3120.PARAM_ID = 3120 AND V3120.IS_DEL = 0 AND V3120.VAL <= :I$REPL_DATE
    JOIN VALD V3121 ON V3121.OBJ_ID = L59.OBJ_ID AND V3121.PARAM_ID = 3121 AND V3121.IS_DEL = 0 AND V3121.VAL >= :I$REPL_DATE
    WHERE L68.PARENT_TYPE_ID = 2 AND L68.OBJ_TYPE_ID = 68 AND L68.DATE_DEL IS NULL
    INTO :V$SCH_ID;

    IF(V$SCH_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не создан шаблон расписания';

    SELECT FIRST 1 V405.VAL
    FROM LINKS L60
    JOIN VALI V404 ON V404.OBJ_ID = L60.OBJ_ID AND V404.PARAM_ID = 404 AND V404.IS_DEL = 0 AND V404.VAL = :I$LESSON_NUM
    JOIN VALT V405 ON V405.OBJ_ID = L60.OBJ_ID AND V405.PARAM_ID = 405 AND V405.IS_DEL = 0
    WHERE L60.PARENT_ID = :V$SCH_ID AND L60.OBJ_TYPE_ID = 60 AND L60.DATE_DEL IS NULL
    INTO :V$DT;

    IF(V$DT IS NULL) THEN EXCEPTION DATA_ERROR 'В шаблоне расписания не указано время начала для указанного номера урока ' || I$LESSON_NUM;
  END

  IF(I$OBJ_ID IS NULL) THEN
  BEGIN
    INSERT INTO CJ2_REPL_PROCESS
    (REPL_DATE, PLAN_ID, PERSON_ID, REPL_PERSON_ID, CJ_ID, REPL_CJ_ID, LESSON_NUM, LESSON_TIME)
    VALUES (:I$REPL_DATE, :I$PLAN_ID, :I$TEACHER_ID, :I$REPL_TEACHER_ID, :I$CJ_ID, :I$REPL_CJ_ID, :I$LESSON_NUM, :V$DT)
    RETURNING OBJ_ID
    INTO :OBJ_ID;
  END
  ELSE
  BEGIN
    IF(V$APPROVED = 0) THEN
    BEGIN
      UPDATE CJ2_REPL_PROCESS
      SET REPL_PERSON_ID = :I$REPL_TEACHER_ID, CJ_ID = :I$CJ_ID, REPL_CJ_ID = :I$REPL_CJ_ID, LESSON_NUM = :I$LESSON_NUM, LESSON_TIME = :V$DT
      WHERE OBJ_ID = :I$OBJ_ID;
    END

    OBJ_ID = I$OBJ_ID;
  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_REPL_PROCESS_APPR (
    I$REPL_DATE DATE,
    I$ORDER_DATE DATE,
    I$ORDER_NUM VARCHAR(100),
    I$USER_ID VARCHAR(40) = null)
RETURNS (
    ERROR_TEXT VARCHAR(1000))
AS
declare variable REPL_ID bigint;
declare variable CJ_ID bigint;
declare variable LESSON_NUM integer;
declare variable TEACHER_ID bigint;
begin

  IF(I$ORDER_DATE > I$REPL_DATE) THEN EXCEPTION DATA_ERROR 'Дата утверждения не может быть позднее даты замещений';
  IF(I$REPL_DATE < DATEADD(-365 DAY TO CURRENT_DATE)) THEN EXCEPTION DATA_ERROR 'Нельзя утвердить замещения задним числом';
  -- Временное разрешаем утверждать любой датой

  FOR
      SELECT P.OBJ_ID, COALESCE(P.REPL_CJ_ID, P.CJ_ID), P.LESSON_NUM, P.REPL_PERSON_ID
      FROM CJ2_REPL_PROCESS P
      WHERE P.REPL_DATE = :I$REPL_DATE AND P.DATE_DEL IS NULL AND P.IS_APPROVED = 0
      INTO :REPL_ID, :CJ_ID, :LESSON_NUM, :TEACHER_ID
  DO
  BEGIN

      -- Если урок уже есть в базе на указанное число, и еще не проведен - меняем преподавателя
      UPDATE CJ2_JOURNAL_LESSONS CJL
      SET CJL.TEACHER_ID = :TEACHER_ID
      WHERE CJL.CJ_ID = :CJ_ID AND CJL.IS_COMPLETED = 0 AND CJL.LESSON_DATE = :I$REPL_DATE AND CJL.LESSON_NUM = :LESSON_NUM;

      UPDATE CJ2_REPL_PROCESS
      SET IS_APPROVED = 1, ORDER_DATE = :I$ORDER_DATE, ORDER_NUM = :I$ORDER_NUM
      WHERE OBJ_ID = :REPL_ID;

  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_REPL_PROCESS_DELETE (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    ERROR_TEXT VARCHAR(1000))
AS
declare variable V$DATE date;
declare variable V$APPROVED smallint;
begin

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  -- Проверяем статус утверждения и дату
  SELECT REPL_DATE, IS_APPROVED
  FROM CJ2_REPL_PROCESS
  WHERE OBJ_ID = :I$OBJ_ID AND DATE_DEL IS NULL
  INTO :V$DATE, :V$APPROVED;

  IF(V$APPROVED <> 0) THEN EXCEPTION DATA_ERROR 'Нельзя удалять утвержденные замещения';
  -- IF(V$DATE < DATEADD(-7 DAY TO CURRENT_DATE)) THEN EXCEPTION DATA_ERROR 'Нельзя удалять замещения старше 7 дней';

  UPDATE CJ2_REPL_PROCESS
  SET DATE_DEL = CURRENT_TIMESTAMP
  WHERE OBJ_ID = :I$OBJ_ID AND DATE_DEL IS NULL;

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_REPL_PROCESS_GET (
    I$OBJ_ID BIGINT,
    I$PLAN_ID BIGINT,
    I$CJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
declare variable V$OBJ_ID bigint;
declare variable V$PLAN_ID bigint;
declare variable V$PERSON_ID bigint;
declare variable V$REPL_DATE date;
declare variable V$LESSON_NUM smallint;
declare variable V$CJ_ID bigint;
declare variable V$REPL_CJ_ID bigint;
declare variable V$REPL_PERSON_ID bigint;
declare variable V$IS_APPROVED smallint;
declare variable V$ORDER_DATE date;
declare variable V$ORDER_NUM varchar(100);
declare variable V$GRADE_ID bigint;
declare variable V$SUBJECT_ID bigint;
declare variable V$YEAR_ID bigint;
declare variable V$REASON_ID bigint;
declare variable V$GUP_ID bigint;
declare variable V$STAGE bigint;
declare variable S varchar(1000);
begin

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  SELECT P.OBJ_ID, P.PLAN_ID, P.PERSON_ID, P.REPL_DATE, P.LESSON_NUM, P.CJ_ID, P.REPL_CJ_ID, P.REPL_PERSON_ID,
    P.IS_APPROVED, P.ORDER_DATE, P.ORDER_NUM, J.GRADE_ID, J.SUBJECT_ID, LP2.EXT_OBJ_ID, J.STAGE_INDEX
  FROM CJ2_REPL_PROCESS P
  JOIN CJ2_JOURNAL J ON J.OBJ_ID = P.CJ_ID
  LEFT JOIN LINKS LP2 ON LP2.OBJ_ID = J.GRADE_ID AND LP2.PARENT_TYPE_ID = 2 AND LP2.DATE_DEL IS NULL
  WHERE P.DATE_DEL IS NULL AND P.OBJ_ID = :I$OBJ_ID AND P.DATE_DEL IS NULL
  INTO :V$OBJ_ID, :V$PLAN_ID, :V$PERSON_ID, :V$REPL_DATE, :V$LESSON_NUM, :V$CJ_ID, :V$REPL_CJ_ID, :V$REPL_PERSON_ID,
    :V$IS_APPROVED, :V$ORDER_DATE, :V$ORDER_NUM, :V$GRADE_ID, :V$SUBJECT_ID, :V$GUP_ID, :V$STAGE;

  IF(I$OBJ_ID IS NOT NULL AND V$OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Запись не найдена';
  IF(I$CJ_ID IS NOT NULL) THEN
  BEGIN
    V$PLAN_ID = I$PLAN_ID;
    SELECT J.OBJ_ID, J.TEACHER_ID, J.SUBJECT_ID
    FROM CJ2_JOURNAL J
    WHERE J.DATE_DEL IS NULL AND J.OBJ_ID = :I$CJ_ID
    INTO :V$CJ_ID, :V$PERSON_ID, :V$SUBJECT_ID;

    IF(V$CJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Журнал для замещения не найден';
  END

  TAG_NAME = 'id';
  VAL = V$OBJ_ID;
  SUSPEND;

  TAG_NAME = 'plan_id';
  VAL = V$PLAN_ID;
  SUSPEND;

  SELECT P.REASON_ID
  FROM CJ2_REPL_PLAN P
  WHERE P.OBJ_ID = :V$PLAN_ID
  INTO :V$REASON_ID;

  TAG_NAME = 'reason_id';
  VAL = V$REASON_ID;
  SUSPEND;

  TAG_NAME = 'reason_text';
  VAL = (SELECT VAL FROM LISTVAL_TEXT(:V$REASON_ID));
  SUSPEND;

  TAG_NAME = 'person_id';
  VAL = V$PERSON_ID;
  SUSPEND;

  TAG_NAME = 'person_name';
  IF(V$PERSON_ID IS NULL) THEN VAL = NULL; ELSE VAL = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$PERSON_ID));
  SUSPEND;

  TAG_NAME = 'repl_date';
  VAL = (SELECT VAL FROM DATE2ISO(:V$REPL_DATE));
  SUSPEND;

  TAG_NAME = 'lesson_num';
  VAL = V$LESSON_NUM;
  SUSPEND;

  TAG_NAME = 'cj_id';
  VAL = V$CJ_ID;
  SUSPEND;

  TAG_NAME = 'cj_name';
  IF(V$CJ_ID IS NULL) THEN VAL = NULL;
  ELSE
  BEGIN
    VAL = NULL;
    SELECT J.JOURNAL_NAME || IIF(J.SUBJECT_ID IS NULL, '', ' (' || C.CAPTION || ')')
    FROM CJ2_JOURNAL J
    LEFT JOIN OBJECT_CAPTION_GET(J.SUBJECT_ID) C ON 1 = 1
    WHERE J.OBJ_ID = :V$CJ_ID
    INTO :VAL;
  END
  SUSPEND;

  TAG_NAME = 'repl_cj_id';
  VAL = V$REPL_CJ_ID;
  IF(VAL IS NULL) THEN VAL = '*';
  SUSPEND;

  TAG_NAME = 'repl_cj_name';
  IF(V$REPL_CJ_ID IS NULL) THEN VAL = NULL;
  ELSE
  BEGIN
    VAL = NULL;
    SELECT J.JOURNAL_NAME || IIF(J.SUBJECT_ID IS NULL, '', ' (' || C.CAPTION || ')')
    FROM CJ2_JOURNAL J
    LEFT JOIN OBJECT_CAPTION_GET(J.SUBJECT_ID) C ON 1 = 1
    WHERE J.OBJ_ID = :V$REPL_CJ_ID
    INTO :VAL;
  END
  SUSPEND;

  TAG_NAME = 'repl_person_id';
  VAL = V$REPL_PERSON_ID;
  SUSPEND;

  TAG_NAME = 'repl_person_name';
  IF(V$REPL_PERSON_ID IS NULL) THEN VAL = NULL; ELSE VAL = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$REPL_PERSON_ID));
  SUSPEND;

  TAG_NAME = 'is_approved';
  VAL = V$IS_APPROVED;
  SUSPEND;

  TAG_NAME = 'order_date';
  VAL = (SELECT VAL FROM DATE2ISO(:V$ORDER_DATE));
  SUSPEND;

  TAG_NAME = 'order_num';
  VAL = V$ORDER_NUM;
  SUSPEND;

  -- Список выбора журналов, которые можно заменять - только текущий учебный год
  -- И только для учебных коллективов в одной ГУП
  SELECT FIRST 1 V1236.LISTVAL_ID
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$YEAR_ID;

  TAG_NAME = 'cj::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT J.OBJ_ID, J.JOURNAL_NAME || IIF(J.SUBJECT_ID IS NULL, '', ' (' || C.CAPTION || ')'), J.TEACHER_ID, LP2.EXT_OBJ_ID, J.SUBJECT_ID, J.STAGE_INDEX
    FROM CJ2_JOURNAL J
    LEFT JOIN LINKS LP2 ON LP2.OBJ_ID = J.GRADE_ID AND LP2.PARENT_TYPE_ID = 2 AND LP2.DATE_DEL IS NULL
    LEFT JOIN OBJECT_CAPTION_GET(J.SUBJECT_ID) C ON 1 = 1
    WHERE J.DATE_DEL IS NULL AND J.YEAR_ID = :V$YEAR_ID AND (J.GRADE_ID = :V$GRADE_ID OR LP2.EXT_OBJ_ID = :V$GUP_ID OR :I$OBJ_ID IS NULL)
      AND (J.STAGE_INDEX = :V$STAGE OR (:V$STAGE IS NULL AND J.STAGE_INDEX IS NULL) OR :I$OBJ_ID IS NULL)
    ORDER BY J.STAGE_INDEX, 2
    INTO :V$OBJ_ID, :S, :V$PERSON_ID, :V$GRADE_ID, :V$SUBJECT_ID, :V$STAGE
  DO
  BEGIN
    TAG_NAME = 'cj:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'cj:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'cj:r:name';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'cj:r:teacher_id';
    VAL = V$PERSON_ID;
    SUSPEND;
    TAG_NAME = 'cj:r:subject_id';
    VAL = V$SUBJECT_ID;
    SUSPEND;
    TAG_NAME = 'cj:r:master_id';
    VAL = V$GRADE_ID;
    SUSPEND;
    TAG_NAME = 'cj:r:stage';
    VAL = V$STAGE;
    SUSPEND;
  END

  -- Список выбора для преподавателей замен
  -- Сначала идут штатные преподаватели, затем все остальные
  TAG_NAME = 'repl_persons::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT TEACHER_ID, TEACHER_CAPTION
    FROM PARAGRAF_GRADE_TEACHERS_LIST(NULL, 2)
    ORDER BY 2
    INTO :V$OBJ_ID, :S
  DO
  BEGIN
    TAG_NAME = 'repl_persons:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'repl_persons:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'repl_persons:r:name';
    VAL = S;
    SUSPEND;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_REPL_PROCESS_SRL (
    I$DATE DATE)
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(2000))
AS
declare variable V$TEACHER1 varchar(400);
declare variable V$TEACHER2 varchar(400);
declare variable V$LESSON integer;
declare variable V$SUBJ1 varchar(1000);
declare variable V$SUBJ2 varchar(1000);
declare variable V$GROUP_ID bigint;
declare variable N integer;
begin

  TAG_NAME = 'replacement_date';
  VAL = (SELECT RESULT FROM DATE2STR(:I$DATE));
  SUSPEND;

  TAG_NAME = 'period_name';
  IF(EXTRACT(MONTH FROM CURRENT_DATE) < 9) THEN VAL = (EXTRACT(YEAR FROM CURRENT_DATE) - 1) || '-' || EXTRACT(YEAR FROM CURRENT_DATE);
  ELSE VAL = EXTRACT(YEAR FROM CURRENT_DATE) || '-' || (EXTRACT(YEAR FROM CURRENT_DATE) + 1);
  SUSPEND;

  TAG_NAME = 'director_post';
  VAL = '';
  SELECT FIRST 1 D.POST, SUBSTRING(D.I FROM 1 FOR 1) || '.' || SUBSTRING(D.O FROM 1 FOR 1) || '. ' || D.F, V5.VAL
  FROM LINKS L2
  JOIN VALS V5 ON V5.OBJ_ID = L2.OBJ_ID AND V5.PARAM_ID = 5 AND V5.IS_DEL = 0
  LEFT JOIN R_SPB_POST_DIRECTOR(L2.OBJ_ID, NULL) D ON 1 = 1
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :VAL, :V$TEACHER1, :V$SUBJ1;
  SUSPEND;

  TAG_NAME = 'director_fio';
  VAL = V$TEACHER1;
  SUSPEND;

  TAG_NAME = 'ou_name';
  VAL = V$SUBJ1;
  SUSPEND;

  -- Список по сотрудникам для самого приказа
  TAG_NAME = 'teachers';
  VAL = NULL;
  SUSPEND;
  FOR
      SELECT C1.CAPTION, C2.CAPTION, RP.LESSON_NUM, CJM.GRADE_ID, VS1.VAL, VS2.VAL
      FROM CJ2_REPL_PROCESS RP
      JOIN CJ2_JOURNAL CJM ON CJM.OBJ_ID = RP.CJ_ID
      JOIN VALS VS1 ON VS1.OBJ_ID = CJM.SUBJECT_ID AND VS1.PARAM_ID = 376 AND VS1.IS_DEL = 0
      LEFT JOIN CJ2_JOURNAL CJM2 ON CJM2.OBJ_ID = RP.REPL_CJ_ID
      LEFT JOIN VALS VS2 ON VS2.OBJ_ID = CJM2.SUBJECT_ID AND VS2.PARAM_ID = 376 AND VS2.IS_DEL = 0
      LEFT JOIN OBJECT_CAPTION_GET(RP.PERSON_ID) C1 ON 1 = 1
      LEFT JOIN OBJECT_CAPTION_GET(COALESCE(RP.REPL_PERSON_ID, CJM2.TEACHER_ID)) C2 ON 1 = 1
      LEFT JOIN OBJECT_CAPTION_GET(CJM.GRADE_ID) G ON 1 = 1
      WHERE RP.DATE_DEL IS NULL AND RP.REPL_DATE = :I$DATE AND RP.IS_APPROVED = 1
      ORDER BY 1, 3
      INTO :V$TEACHER1, :V$TEACHER2, :V$LESSON, :V$GROUP_ID, :V$SUBJ1, :V$SUBJ2
  DO
  BEGIN

      TAG_NAME = 'teachers:teacher';
      VAL = NULL;
      SUSPEND;

      TAG_NAME = 'teachers:teacher:fio';
      VAL = V$TEACHER1;
      SUSPEND;

      TAG_NAME = 'teachers:teacher:repl_fio';
      VAL = V$TEACHER2;
      SUSPEND;

      TAG_NAME = 'teachers:teacher:group';
      VAL = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$GROUP_ID));
      SUSPEND;

      TAG_NAME = 'teachers:teacher:lesson';
      VAL = V$LESSON;
      SUSPEND;

      TAG_NAME = 'teachers:teacher:subject';
      VAL = V$SUBJ1;
      SUSPEND;

      TAG_NAME = 'teachers:teacher:repl_subject';
      VAL = COALESCE(V$SUBJ2, 'Тот же предмет');
      SUSPEND;

  END

  -- Список всех фигурантов для ознакомления
  TAG_NAME = 'signatures';
  VAL = NULL;
  SUSPEND;
  N = 1;
  FOR
      SELECT DISTINCT C.CAPTION
      FROM CJ2_REPL_PROCESS RP
      LEFT JOIN OBJECT_CAPTION_GET(RP.PERSON_ID) C ON 1 = 1
      WHERE RP.DATE_DEL IS NULL AND RP.REPL_DATE = :I$DATE AND RP.IS_APPROVED = 1
      UNION
      SELECT DISTINCT C.CAPTION
      FROM CJ2_REPL_PROCESS RP
      LEFT JOIN CJ2_JOURNAL CJM2 ON CJM2.OBJ_ID = RP.REPL_CJ_ID
      LEFT JOIN OBJECT_CAPTION_GET(COALESCE(RP.REPL_PERSON_ID, CJM2.TEACHER_ID)) C ON 1 = 1
      WHERE RP.DATE_DEL IS NULL AND RP.REPL_DATE = :I$DATE AND RP.REPL_PERSON_ID IS NOT NULL AND RP.IS_APPROVED = 1
      ORDER BY 1
      INTO :V$TEACHER1
  DO
  BEGIN
      TAG_NAME = 'signatures:teacher';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'signatures:teacher:n';
      VAL = N;
      SUSPEND;
      TAG_NAME = 'signatures:teacher:fio';
      VAL = V$TEACHER1;
      SUSPEND;
      N = N + 1;
  END

  -- Список по группам и предметам для объявления
  TAG_NAME = 'groups';
  VAL = NULL;
  SUSPEND;
  FOR
      SELECT DISTINCT CJM.GRADE_ID, C.CAPTION
      FROM CJ2_REPL_PROCESS RP
      JOIN CJ2_JOURNAL CJM ON CJM.OBJ_ID = RP.CJ_ID
      LEFT JOIN OBJECT_CAPTION_GET(CJM.GRADE_ID) C ON 1 = 1
      WHERE RP.DATE_DEL IS NULL AND RP.REPL_DATE = :I$DATE AND RP.IS_APPROVED = 1
      ORDER BY 1
      INTO :V$GROUP_ID, :V$SUBJ1
  DO
  BEGIN
      TAG_NAME = 'groups:group';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'groups:group:name';
      VAL = V$SUBJ1;
      SUSPEND;
      TAG_NAME = 'groups:group:lessons';
      VAL = NULL;
      SUSPEND;

      FOR                                                                  
          SELECT C1.CAPTION, C2.CAPTION, RP.LESSON_NUM, VS1.VAL, VS2.VAL
          FROM CJ2_REPL_PROCESS RP
          JOIN CJ2_JOURNAL CJM ON CJM.OBJ_ID = RP.CJ_ID
          JOIN VALS VS1 ON VS1.OBJ_ID = CJM.SUBJECT_ID AND VS1.PARAM_ID = 376 AND VS1.IS_DEL = 0
          LEFT JOIN CJ2_JOURNAL CJM2 ON CJM2.OBJ_ID = RP.REPL_CJ_ID
          LEFT JOIN VALS VS2 ON VS2.OBJ_ID = CJM2.SUBJECT_ID AND VS2.PARAM_ID = 376 AND VS2.IS_DEL = 0
          LEFT JOIN OBJECT_CAPTION_GET(RP.PERSON_ID) C1 ON 1 = 1
          LEFT JOIN OBJECT_CAPTION_GET(COALESCE(RP.REPL_PERSON_ID, CJM2.TEACHER_ID)) C2 ON 1 = 1
          LEFT JOIN OBJECT_CAPTION_GET(CJM.GRADE_ID) G ON 1 = 1
          WHERE RP.DATE_DEL IS NULL AND RP.REPL_DATE = :I$DATE AND CJM.GRADE_ID = :V$GROUP_ID AND RP.IS_APPROVED = 1
          ORDER BY 3
          INTO :V$TEACHER1, :V$TEACHER2, :V$LESSON, :V$SUBJ1, :V$SUBJ2
      DO
      BEGIN

          TAG_NAME = 'groups:group:lessons:row';
          VAL = NULL;
          SUSPEND;

          TAG_NAME = 'groups:group:lessons:row:fio';
          VAL = V$TEACHER1;
          SUSPEND;

          TAG_NAME = 'groups:group:lessons:row:repl_fio';
          VAL = V$TEACHER2;
          SUSPEND;

          TAG_NAME = 'groups:group:lessons:row:lesson';
          VAL = V$LESSON;
          SUSPEND;

          TAG_NAME = 'groups:group:lessons:row:subject';
          VAL = V$SUBJ1;
          SUSPEND;

          TAG_NAME = 'groups:group:lessons:row:repl_subject';
          VAL = COALESCE(V$SUBJ2, 'Тот же предмет');
          SUSPEND;

      END
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_REPL_PROCESS_UA (
    I$REPL_DATE DATE,
    I$USER_ID VARCHAR(40) = null)
RETURNS (
    ERROR_TEXT VARCHAR(1000))
AS
declare variable REPL_ID bigint;
declare variable CJ_ID bigint;
declare variable LESSON_NUM integer;
declare variable TEACHER_ID bigint;
begin

  -- -3 !!!
  IF(I$REPL_DATE < DATEADD(-365 DAY TO CURRENT_DATE)) THEN EXCEPTION DATA_ERROR 'Нельзя снять утверждение замещений задним числом';

  -- Можно снимать утверждения только для замещений, которые еще не проводились
  FOR
      SELECT P.OBJ_ID, COALESCE(P.REPL_CJ_ID, P.CJ_ID), P.LESSON_NUM, P.REPL_PERSON_ID
      FROM CJ2_REPL_PROCESS P
      WHERE P.REPL_DATE = :I$REPL_DATE AND P.DATE_DEL IS NULL AND P.IS_APPROVED = 1
      INTO :REPL_ID, :CJ_ID, :LESSON_NUM, :TEACHER_ID
  DO
  BEGIN

      -- При наличии проведенного урока отменять нельзя

      UPDATE CJ2_REPL_PROCESS
      SET IS_APPROVED = 0, ORDER_DATE = NULL, ORDER_NUM = NULL
      WHERE OBJ_ID = :REPL_ID;

  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_REPL_REPORT (
    I$DATE_FROM DATE NOT NULL,
    I$DATE_TO DATE NOT NULL,
    I$MODE SMALLINT = 0)
RETURNS (
    VAL VARCHAR(6000))
AS
declare variable V$DATE date;
declare variable N integer;
declare variable TEACHER_NAME varchar(1000);
declare variable TEACHER_ID bigint;
declare variable VN integer;
declare variable SUBJECT_NAME varchar(1000);
declare variable SUBJECT_ID bigint;
begin

  -- MODE - 0 для старого журнала, 1 для нового журнала

  VAL = '<!DOCTYPE html>';
  VAL = VAL || '<html lang="ru">';
  VAL = VAL || '<head>';
  VAL = VAL || '<meta charset="utf-8" />';

  VAL = VAL || '<style>';
  VAL = VAL || 'html { font-family: Tahoma, Verdana, Arial;';
  VAL = VAL || 'font-size: 10pt; ';
  VAL = VAL || '} ';
  VAL = VAL || '.title1 { font-size: 150%;';
  VAL = VAL || 'padding: 8px;';
  VAL = VAL || 'margin-bottom: 4px;';
  VAL = VAL || 'font-weight: bold;';
  VAL = VAL || 'background-color: #D4E157;';
  VAL = VAL || '} ';
  VAL = VAL || '.title2 { ';
  VAL = VAL || 'padding: 4px;';
  VAL = VAL || 'font-weight: bold;';
  VAL = VAL || '} ';
  VAL = VAL || '.details {';
  VAL = VAL || 'width: 100%;';
  VAL = VAL || 'border: 1px solid #e0e0e0;';
  VAL = VAL || '} ';
  VAL = VAL || '.details tr td {';
  VAL = VAL || 'padding: 2px 4px;';
  VAL = VAL || 'border-right: 1px solid #e0e0e0;';
  VAL = VAL || 'text-align: left;';
  VAL = VAL || '} ';
  VAL = VAL || '.odd td {';
  VAL = VAL || 'background-color: #f7f7f7;';
  VAL = VAL || '} ';
  VAL = VAL || '.thd {';
  VAL = VAL || 'background-color: #F0F4C3;';
  VAL = VAL || '} ';
  VAL = VAL || '.tdd {';
  VAL = VAL || 'font-weight: bold;';
  VAL = VAL || 'background-color: #B3E5FC;';
  VAL = VAL || '} ';
  VAL = VAL || '.total {';
  VAL = VAL || 'font-weight: bold;';
  VAL = VAL || '} ';
  VAL = VAL || '</style>';

  VAL = VAL || '</head>';
  VAL = VAL || '<body style="padding: 8px;">';

  -- Заголовок отчета
  VAL = VAL || '<div class="title1">Отчет по пропускам и замещениям учителей</div>';
  VAL = VAL || '<div class="title2">За период с ' || (SELECT RESULT FROM DATE2STR(:I$DATE_FROM)) || ' по ' || (SELECT RESULT FROM DATE2STR(:I$DATE_TO)) || '</div>';

  -- Заголовок таблиц
  VAL = VAL || '<table class="details" cellspacing="0" cellpadding="0">';

  VAL = VAL || '<tr class="thd">';
  VAL = VAL || '<td class="c1">ФИО учителя</td>';
  VAL = VAL || '<td class="c2">Предмет</td>';
  VAL = VAL || '<td class="c3">Пропущено часов</td>';
  VAL = VAL || '<td class="c4">Замещено часов</td>';
  VAL = VAL || '</tr>';
  SUSPEND;

  -- Первый цикл по учителям
  FOR
      SELECT DISTINCT P.PERSON_ID, IIF(P.PERSON_ID IS NULL, 'Вакантная ставка', C.CAPTION)
      FROM CJ2_REPL_PROCESS P
      LEFT JOIN OBJECT_CAPTION_GET(P.PERSON_ID) C ON 1 = 1
      WHERE P.REPL_DATE >= :I$DATE_FROM AND P.REPL_DATE <= :I$DATE_TO AND P.DATE_DEL IS NULL
          -- AND P.IS_APPROVED = 1
      UNION
      SELECT DISTINCT P.REPL_PERSON_ID, C.CAPTION
      FROM CJ2_REPL_PROCESS P
      LEFT JOIN OBJECT_CAPTION_GET(P.REPL_PERSON_ID) C ON 1 = 1
      WHERE P.REPL_DATE >= :I$DATE_FROM AND P.REPL_DATE <= :I$DATE_TO AND P.DATE_DEL IS NULL AND P.REPL_PERSON_ID IS NOT NULL
          -- AND P.IS_APPROVED = 1
      ORDER BY 2
      INTO :TEACHER_ID, :TEACHER_NAME
  DO
  BEGIN

      N = 0;
      VAL = '<tr class="tdd">';

      VAL = VAL || '<td class="c1">' || (SELECT VAL FROM ESCAPE_STR(:TEACHER_NAME)) || '</td>';
      VAL = VAL || '<td class="c2">&nbsp;</td>';

      -- Суммарное количество пропусков
      SELECT COUNT(*)
      FROM CJ2_REPL_PROCESS P
      WHERE P.REPL_DATE >= :I$DATE_FROM AND P.REPL_DATE <= :I$DATE_TO AND P.DATE_DEL IS NULL AND (P.PERSON_ID = :TEACHER_ID OR (P.PERSON_ID IS NULL AND :TEACHER_ID IS NULL))
          -- AND P.IS_APPROVED = 1
      INTO :VN;
      VAL = VAL || '<td class="c3">' || VN || '</td>';

      -- Суммарное количество замен
      SELECT COUNT(*)
      FROM CJ2_REPL_PROCESS P
      WHERE P.REPL_DATE >= :I$DATE_FROM AND P.REPL_DATE <= :I$DATE_TO AND P.DATE_DEL IS NULL AND P.REPL_PERSON_ID = :TEACHER_ID
          -- AND P.IS_APPROVED = 1
      INTO :VN;
      VAL = VAL || '<td class="c4">' || VN || '</td>';

      VAL = VAL || '</tr>';
      SUSPEND;

      -- Далее цикл по предметам
      FOR
          SELECT DISTINCT CJM.SUBJECT_ID, C.CAPTION
          FROM CJ2_REPL_PROCESS P
          JOIN CJ2_JOURNAL CJM ON CJM.OBJ_ID = P.CJ_ID
          LEFT JOIN OBJECT_CAPTION_GET(CJM.SUBJECT_ID) C ON 1 = 1
          WHERE P.REPL_DATE >= :I$DATE_FROM AND P.REPL_DATE <= :I$DATE_TO AND P.DATE_DEL IS NULL AND (P.PERSON_ID = :TEACHER_ID OR (P.PERSON_ID IS NULL AND :TEACHER_ID IS NULL))
              -- AND P.IS_APPROVED = 1
          UNION
          SELECT DISTINCT CJMR.SUBJECT_ID, C.CAPTION
          FROM CJ2_REPL_PROCESS P
          JOIN CJ2_JOURNAL CJM ON CJM.OBJ_ID = P.CJ_ID
          JOIN CJ2_JOURNAL CJMR ON CJMR.OBJ_ID = IIF(P.REPL_CJ_ID IS NULL, P.CJ_ID, P.REPL_CJ_ID)
          LEFT JOIN OBJECT_CAPTION_GET(CJMR.SUBJECT_ID) C ON 1 = 1
          WHERE P.REPL_DATE >= :I$DATE_FROM AND P.REPL_DATE <= :I$DATE_TO AND P.DATE_DEL IS NULL AND P.REPL_PERSON_ID = :TEACHER_ID
              -- AND P.IS_APPROVED = 1
          ORDER BY 2
          INTO :SUBJECT_ID, :SUBJECT_NAME
      DO
      BEGIN

          VAL = '<tr';
          IF(N = 1) THEN VAL = VAL || ' class="odd"';
          VAL = VAL || '>';

          VAL = VAL || '<td class="c1">&nbsp;</td>';
          VAL = VAL || '<td class="c2">' || (SELECT VAL FROM ESCAPE_STR(:SUBJECT_NAME)) || '</td>';

          -- Суммарное количество пропусков
          SELECT COUNT(*)
          FROM CJ2_REPL_PROCESS P
          JOIN CJ2_JOURNAL CJM ON CJM.OBJ_ID = P.CJ_ID AND CJM.SUBJECT_ID = :SUBJECT_ID
          WHERE P.REPL_DATE >= :I$DATE_FROM AND P.REPL_DATE <= :I$DATE_TO AND P.DATE_DEL IS NULL AND (P.PERSON_ID = :TEACHER_ID OR (P.PERSON_ID IS NULL AND :TEACHER_ID IS NULL))
              -- AND P.IS_APPROVED = 1
          INTO :VN;
          VAL = VAL || '<td class="c3">' || VN || '</td>';

          -- Суммарное количество замен
          SELECT COUNT(*)
          FROM CJ2_REPL_PROCESS P
          JOIN CJ2_JOURNAL CJM ON CJM.OBJ_ID = P.CJ_ID
          JOIN CJ2_JOURNAL CJMR ON CJMR.OBJ_ID = IIF(P.REPL_CJ_ID IS NULL, P.CJ_ID, P.REPL_CJ_ID) AND CJMR.SUBJECT_ID = :SUBJECT_ID
          WHERE P.REPL_DATE >= :I$DATE_FROM AND P.REPL_DATE <= :I$DATE_TO AND P.DATE_DEL IS NULL AND P.REPL_PERSON_ID = :TEACHER_ID
              -- AND P.IS_APPROVED = 1
          INTO :VN;
          VAL = VAL || '<td class="c4">' || VN || '</td>';

          VAL = VAL || '</tr>';
          SUSPEND;
          IF(N = 0) THEN N = 1; ELSE N = 0;

      END

  END

  -- Итоги
  VAL = '<tr><td colspan="4" style="border-bottom: 2px solid gray;"></td></tr>';
  VAL = VAL || '<tr class="total">';

  VAL = VAL || '<td class="c1">ИТОГО</td>';
  VAL = VAL || '<td class="c2">&nbsp;</td>';

  -- Суммарное количество пропусков
  SELECT COUNT(*)
  FROM CJ2_REPL_PROCESS P
  WHERE P.REPL_DATE >= :I$DATE_FROM AND P.REPL_DATE <= :I$DATE_TO AND P.DATE_DEL IS NULL
      -- AND P.IS_APPROVED = 1
  INTO :VN;
  VAL = VAL || '<td class="c3">' || VN || '</td>';

  -- Суммарное количество замен
  SELECT COUNT(*)
  FROM CJ2_REPL_PROCESS P
  WHERE P.REPL_DATE >= :I$DATE_FROM AND P.REPL_DATE <= :I$DATE_TO AND P.DATE_DEL IS NULL AND P.REPL_PERSON_ID IS NOT NULL
      -- AND P.IS_APPROVED = 1
  INTO :VN;
  VAL = VAL || '<td class="c4">' || VN || '</td>';

  VAL = VAL || '</tr>';
  SUSPEND;

  VAL = '</table>';
  VAL = VAL || '</body>';
  VAL = VAL || '</html>';

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_REPL_REPORT_1 (
    I$DATE_FROM DATE NOT NULL,
    I$DATE_TO DATE NOT NULL,
    I$MODE SMALLINT = 0)
RETURNS (
    VAL VARCHAR(6000))
AS
declare variable V$DATE date;
declare variable N integer;
declare variable VN integer;
declare variable STAGE_NAME varchar(1000);
declare variable STAGE_ID bigint;
declare variable SORT_INDEX double precision;
begin

  -- MODE - 0 для старого журнала, 1 для нового журнала

  VAL = '<!DOCTYPE html>';
  VAL = VAL || '<html lang="ru">';
  VAL = VAL || '<head>';
  VAL = VAL || '<meta charset="utf-8" />';

  VAL = VAL || '<style>';
  VAL = VAL || 'html { font-family: Tahoma, Verdana, Arial;';
  VAL = VAL || 'font-size: 10pt; ';
  VAL = VAL || '} ';
  VAL = VAL || '.title1 { font-size: 150%;';
  VAL = VAL || 'padding: 8px;';
  VAL = VAL || 'margin-bottom: 4px;';
  VAL = VAL || 'font-weight: bold;';
  VAL = VAL || 'background-color: #D4E157;';
  VAL = VAL || '} ';
  VAL = VAL || '.title2 { ';
  VAL = VAL || 'padding: 4px;';
  VAL = VAL || 'font-weight: bold;';
  VAL = VAL || '} ';
  VAL = VAL || '.details {';
  VAL = VAL || 'width: 100%;';
  VAL = VAL || 'border: 1px solid #e0e0e0;';
  VAL = VAL || '} ';
  VAL = VAL || '.details tr td {';
  VAL = VAL || 'padding: 2px 4px;';
  VAL = VAL || 'border-right: 1px solid #e0e0e0;';
  VAL = VAL || 'text-align: left;';
  VAL = VAL || '} ';
  VAL = VAL || '.odd td {';
  VAL = VAL || 'background-color: #f7f7f7;';
  VAL = VAL || '} ';
  VAL = VAL || '.thd {';
  VAL = VAL || 'background-color: #F0F4C3;';
  VAL = VAL || '} ';
  VAL = VAL || '.tdd {';
  VAL = VAL || 'font-weight: bold;';
  VAL = VAL || 'background-color: #B3E5FC;';
  VAL = VAL || '} ';
  VAL = VAL || '.total {';
  VAL = VAL || 'font-weight: bold;';
  VAL = VAL || '} ';
  VAL = VAL || '</style>';

  VAL = VAL || '</head>';
  VAL = VAL || '<body style="padding: 8px;">';

  -- Заголовок отчета
  VAL = VAL || '<div class="title1">Отчет по пропускам и замещениям по параллелям</div>';
  VAL = VAL || '<div class="title2">За период с ' || (SELECT RESULT FROM DATE2STR(:I$DATE_FROM)) || ' по ' || (SELECT RESULT FROM DATE2STR(:I$DATE_TO)) || '</div>';

  -- Заголовок таблиц
  VAL = VAL || '<table class="details" cellspacing="0" cellpadding="0">';

  VAL = VAL || '<tr class="thd">';
  VAL = VAL || '<td class="c1">Параллель</td>';
  VAL = VAL || '<td class="c2">Пропущено часов</td>';
  VAL = VAL || '<td class="c3">Замещено часов</td>';
  VAL = VAL || '</tr>';
  SUSPEND;

  N = 0;

  -- Единственный цикл сразу по параллелям
  FOR
      SELECT DISTINCT CJM.STAGE_INDEX, R.VAL, LV.COST
      FROM CJ2_REPL_PROCESS P
      JOIN CJ2_JOURNAL CJM ON CJM.OBJ_ID = P.CJ_ID
      JOIN LISTVALS LV ON LV.LISTVAL_ID = CJM.STAGE_INDEX
      JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
      WHERE P.REPL_DATE >= :I$DATE_FROM AND P.REPL_DATE <= :I$DATE_TO AND P.DATE_DEL IS NULL AND P.IS_APPROVED = 1
      ORDER BY 3
      INTO :STAGE_ID, :STAGE_NAME, :SORT_INDEX
  DO
  BEGIN

      VAL = '<tr';
      IF(N = 1) THEN VAL = VAL || ' class="odd"';
      VAL = VAL || '>';

      VAL = VAL || '<td class="c1">' || (SELECT VAL FROM ESCAPE_STR(:STAGE_NAME)) || '</td>';

      -- Суммарное количество пропусков
      SELECT COUNT(*)
      FROM (
          SELECT P.OBJ_ID
          FROM CJ2_REPL_PROCESS P
          JOIN CJ2_JOURNAL CJM ON CJM.OBJ_ID = P.CJ_ID AND CJM.STAGE_INDEX = :STAGE_ID
          WHERE P.REPL_DATE >= :I$DATE_FROM AND P.REPL_DATE <= :I$DATE_TO AND P.DATE_DEL IS NULL AND P.IS_APPROVED = 1
      )
      INTO :VN;
      VAL = VAL || '<td class="c2">' || VN || '</td>';

      -- Суммарное количество замен
      SELECT COUNT(*)
      FROM (
          SELECT P.OBJ_ID
          FROM CJ2_REPL_PROCESS P
          JOIN CJ2_JOURNAL CJM ON CJM.OBJ_ID = P.CJ_ID AND CJM.STAGE_INDEX = :STAGE_ID
          WHERE P.REPL_DATE >= :I$DATE_FROM AND P.REPL_DATE <= :I$DATE_TO AND P.DATE_DEL IS NULL AND P.REPL_PERSON_ID IS NOT NULL AND P.IS_APPROVED = 1
      )
      INTO :VN;
      VAL = VAL || '<td class="c3">' || VN || '</td>';

      VAL = VAL || '</tr>';
      SUSPEND;
      IF(N = 0) THEN N = 1; ELSE N = 0;

  END

  -- Итоги
  VAL = '<tr><td colspan="4" style="border-bottom: 2px solid gray;"></td></tr>';
  VAL = VAL || '<tr class="total">';

  VAL = VAL || '<td class="c1">ИТОГО</td>';

  -- Суммарное количество пропусков
  SELECT COUNT(*)
  FROM CJ2_REPL_PROCESS P
  WHERE P.REPL_DATE >= :I$DATE_FROM AND P.REPL_DATE <= :I$DATE_TO AND P.DATE_DEL IS NULL AND P.IS_APPROVED = 1
  INTO :VN;
  VAL = VAL || '<td class="c2">' || VN || '</td>';

  -- Суммарное количество замен
  SELECT COUNT(*)
  FROM CJ2_REPL_PROCESS P
  WHERE P.REPL_DATE >= :I$DATE_FROM AND P.REPL_DATE <= :I$DATE_TO AND P.DATE_DEL IS NULL AND P.REPL_PERSON_ID IS NOT NULL AND P.IS_APPROVED = 1
  INTO :VN;
  VAL = VAL || '<td class="c3">' || VN || '</td>';

  VAL = VAL || '</tr>';
  SUSPEND;

  VAL = '</table>';
  VAL = VAL || '</body>';
  VAL = VAL || '</html>';

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_REPL_REPORT_2 (
    I$DATE_FROM DATE NOT NULL,
    I$DATE_TO DATE NOT NULL,
    I$MODE SMALLINT = 0)
RETURNS (
    VAL VARCHAR(6000))
AS
declare variable V$DATE date;
declare variable N integer;
declare variable GRADE_NAME varchar(1000);
declare variable GRADE_ID bigint;
declare variable VN integer;
declare variable SUBJECT_NAME varchar(1000);
declare variable SUBJECT_ID bigint;
begin

  VAL = '<!DOCTYPE html>';
  VAL = VAL || '<html lang="ru">';
  VAL = VAL || '<head>';
  VAL = VAL || '<meta charset="utf-8" />';

  VAL = VAL || '<style>';
  VAL = VAL || 'html { font-family: Tahoma, Verdana, Arial;';
  VAL = VAL || 'font-size: 10pt; ';
  VAL = VAL || '} ';
  VAL = VAL || '.title1 { font-size: 150%;';
  VAL = VAL || 'padding: 8px;';
  VAL = VAL || 'margin-bottom: 4px;';
  VAL = VAL || 'font-weight: bold;';
  VAL = VAL || 'background-color: #D4E157;';
  VAL = VAL || '} ';
  VAL = VAL || '.title2 { ';
  VAL = VAL || 'padding: 4px;';
  VAL = VAL || 'font-weight: bold;';
  VAL = VAL || '} ';
  VAL = VAL || '.details {';
  VAL = VAL || 'width: 100%;';
  VAL = VAL || 'border: 1px solid #e0e0e0;';
  VAL = VAL || '} ';
  VAL = VAL || '.details tr td {';
  VAL = VAL || 'padding: 2px 4px;';
  VAL = VAL || 'border-right: 1px solid #e0e0e0;';
  VAL = VAL || 'text-align: left;';
  VAL = VAL || '} ';
  VAL = VAL || '.odd td {';
  VAL = VAL || 'background-color: #f7f7f7;';
  VAL = VAL || '} ';
  VAL = VAL || '.thd {';
  VAL = VAL || 'background-color: #F0F4C3;';
  VAL = VAL || '} ';
  VAL = VAL || '.tdd {';
  VAL = VAL || 'font-weight: bold;';
  VAL = VAL || 'background-color: #B3E5FC;';
  VAL = VAL || '} ';
  VAL = VAL || '.total {';
  VAL = VAL || 'font-weight: bold;';
  VAL = VAL || '} ';
  VAL = VAL || '</style>';

  VAL = VAL || '</head>';
  VAL = VAL || '<body style="padding: 8px;">';

  -- Заголовок отчета
  VAL = VAL || '<div class="title1">Отчет по пропускам и замещениям по группам</div>';
  VAL = VAL || '<div class="title2">За период с ' || (SELECT RESULT FROM DATE2STR(:I$DATE_FROM)) || ' по ' || (SELECT RESULT FROM DATE2STR(:I$DATE_TO)) || '</div>';

  -- Заголовок таблиц
  VAL = VAL || '<table class="details" cellspacing="0" cellpadding="0">';

  VAL = VAL || '<tr class="thd">';
  VAL = VAL || '<td class="c1">ГУП, поток</td>';
  VAL = VAL || '<td class="c2">Предмет</td>';
  VAL = VAL || '<td class="c3">Пропущено часов</td>';
  VAL = VAL || '<td class="c4">Замещено часов</td>';
  VAL = VAL || '</tr>';
  SUSPEND;

  -- Первый цикл по учителям
  FOR
      SELECT DISTINCT CJM.GRADE_ID, C.CAPTION
      FROM CJ2_REPL_PROCESS P
      JOIN CJ2_JOURNAL CJM ON CJM.OBJ_ID = P.CJ_ID
      LEFT JOIN OBJECT_CAPTION_GET(CJM.GRADE_ID) C ON 1 = 1
      WHERE P.REPL_DATE >= :I$DATE_FROM AND P.REPL_DATE <= :I$DATE_TO AND P.DATE_DEL IS NULL
          -- AND P.IS_APPROVED = 1
      ORDER BY 2
      INTO :GRADE_ID, :GRADE_NAME
  DO
  BEGIN

      N = 0;
      VAL = '<tr class="tdd">';

      VAL = VAL || '<td class="c1">' || (SELECT VAL FROM ESCAPE_STR(:GRADE_NAME)) || '</td>';
      VAL = VAL || '<td class="c2">&nbsp;</td>';

      -- Суммарное количество пропусков
      SELECT COUNT(*)
      FROM CJ2_REPL_PROCESS P
      JOIN CJ2_JOURNAL CJM ON CJM.OBJ_ID = P.CJ_ID AND CJM.GRADE_ID = :GRADE_ID
      WHERE P.REPL_DATE >= :I$DATE_FROM AND P.REPL_DATE <= :I$DATE_TO AND P.DATE_DEL IS NULL AND P.IS_APPROVED = 1
      INTO :VN;
      VAL = VAL || '<td class="c3">' || VN || '</td>';

      -- Суммарное количество замен
      SELECT COUNT(*)
      FROM CJ2_REPL_PROCESS P
      JOIN CJ2_JOURNAL CJM ON CJM.OBJ_ID = P.CJ_ID AND CJM.GRADE_ID = :GRADE_ID
      WHERE P.REPL_DATE >= :I$DATE_FROM AND P.REPL_DATE <= :I$DATE_TO AND P.DATE_DEL IS NULL AND P.REPL_PERSON_ID IS NOT NULL AND P.IS_APPROVED = 1
      INTO :VN;
      VAL = VAL || '<td class="c4">' || VN || '</td>';

      VAL = VAL || '</tr>';
      SUSPEND;

      -- Далее цикл по предметам
      FOR
          SELECT DISTINCT CJM.SUBJECT_ID, C.CAPTION
          FROM CJ2_REPL_PROCESS P
          JOIN CJ2_JOURNAL CJM ON CJM.OBJ_ID = P.CJ_ID AND CJM.GRADE_ID = :GRADE_ID
          LEFT JOIN OBJECT_CAPTION_GET(CJM.SUBJECT_ID) C ON 1 = 1
          WHERE P.REPL_DATE >= :I$DATE_FROM AND P.REPL_DATE <= :I$DATE_TO AND P.DATE_DEL IS NULL AND P.IS_APPROVED = 1
          UNION
          SELECT DISTINCT CJMR.SUBJECT_ID, C.CAPTION
          FROM CJ2_REPL_PROCESS P
          JOIN CJ2_JOURNAL CJM ON CJM.OBJ_ID = P.CJ_ID AND CJM.GRADE_ID = :GRADE_ID
          JOIN CJ2_JOURNAL CJMR ON CJMR.OBJ_ID = IIF(P.REPL_CJ_ID IS NULL, P.CJ_ID, P.REPL_CJ_ID)
          LEFT JOIN OBJECT_CAPTION_GET(CJMR.SUBJECT_ID) C ON 1 = 1
          WHERE P.REPL_DATE >= :I$DATE_FROM AND P.REPL_DATE <= :I$DATE_TO AND P.DATE_DEL IS NULL AND P.REPL_PERSON_ID IS NOT NULL AND P.IS_APPROVED = 1
          ORDER BY 2
          INTO :SUBJECT_ID, :SUBJECT_NAME
      DO
      BEGIN

          VAL = '<tr';
          IF(N = 1) THEN VAL = VAL || ' class="odd"';
          VAL = VAL || '>';

          VAL = VAL || '<td class="c1">&nbsp;</td>';
          VAL = VAL || '<td class="c2">' || (SELECT VAL FROM ESCAPE_STR(:SUBJECT_NAME)) || '</td>';

          -- Суммарное количество пропусков
          SELECT COUNT(*)
          FROM CJ2_REPL_PROCESS P
          JOIN CJ2_JOURNAL CJM ON CJM.OBJ_ID = P.CJ_ID AND CJM.GRADE_ID = :GRADE_ID AND CJM.SUBJECT_ID = :SUBJECT_ID
          WHERE P.REPL_DATE >= :I$DATE_FROM AND P.REPL_DATE <= :I$DATE_TO AND P.DATE_DEL IS NULL AND P.IS_APPROVED = 1
          INTO :VN;
          VAL = VAL || '<td class="c3">' || VN || '</td>';

          -- Суммарное количество замен
          SELECT COUNT(*)
          FROM CJ2_REPL_PROCESS P
          JOIN CJ2_JOURNAL CJM ON CJM.OBJ_ID = P.CJ_ID AND CJM.GRADE_ID = :GRADE_ID
          JOIN CJ2_JOURNAL CJMR ON CJMR.OBJ_ID = IIF(P.REPL_CJ_ID IS NULL, P.CJ_ID, P.REPL_CJ_ID) AND CJMR.SUBJECT_ID = :SUBJECT_ID
          WHERE P.REPL_DATE >= :I$DATE_FROM AND P.REPL_DATE <= :I$DATE_TO AND P.DATE_DEL IS NULL AND P.REPL_PERSON_ID IS NOT NULL AND P.IS_APPROVED = 1
          INTO :VN;
          VAL = VAL || '<td class="c4">' || VN || '</td>';

          VAL = VAL || '</tr>';
          SUSPEND;
          IF(N = 0) THEN N = 1; ELSE N = 0;

      END

  END

  -- Итоги
  VAL = '<tr><td colspan="4" style="border-bottom: 2px solid gray;"></td></tr>';
  VAL = VAL || '<tr class="total">';

  VAL = VAL || '<td class="c1">ИТОГО</td>';
  VAL = VAL || '<td class="c2">&nbsp;</td>';

  -- Суммарное количество пропусков
  SELECT COUNT(*)
  FROM CJ2_REPL_PROCESS P
  WHERE P.REPL_DATE >= :I$DATE_FROM AND P.REPL_DATE <= :I$DATE_TO AND P.DATE_DEL IS NULL AND P.IS_APPROVED = 1
  INTO :VN;
  VAL = VAL || '<td class="c3">' || VN || '</td>';

  -- Суммарное количество замен
  SELECT COUNT(*)
  FROM CJ2_REPL_PROCESS P
  WHERE P.REPL_DATE >= :I$DATE_FROM AND P.REPL_DATE <= :I$DATE_TO AND P.DATE_DEL IS NULL AND P.REPL_PERSON_ID IS NOT NULL AND P.IS_APPROVED = 1
  INTO :VN;
  VAL = VAL || '<td class="c4">' || VN || '</td>';

  VAL = VAL || '</tr>';
  SUSPEND;

  VAL = '</table>';
  VAL = VAL || '</body>';
  VAL = VAL || '</html>';

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_REPL_REPORT_3 (
    I$DATE_FROM DATE NOT NULL,
    I$DATE_TO DATE NOT NULL,
    I$MODE SMALLINT = 0)
RETURNS (
    VAL VARCHAR(6000))
AS
declare variable L integer;
declare variable N integer;
declare variable V$DATE date;
declare variable V$S varchar(10);
declare variable V$DW integer;
declare variable V$LESSON_NUM integer;
declare variable V$VN varchar(10);
declare variable V$GROUP_NAME1 varchar(400);
declare variable V$SUBJECT_NAME1 varchar(400);
declare variable V$SUBJECT_NAME2 varchar(400);
declare variable V$TEACHER_NAME1 varchar(400);
declare variable V$TEACHER_NAME2 varchar(400);
begin

  -- MODE - 0 для старого журнала, 1 для нового журнала

  VAL = '<!DOCTYPE html>';
  VAL = VAL || '<html lang="ru">';
  VAL = VAL || '<head>';
  VAL = VAL || '<meta charset="utf-8" />';

  VAL = VAL || '<style>';
  VAL = VAL || 'html { font-family: Tahoma, Verdana, Arial;';
  VAL = VAL || 'font-size: 10pt; ';
  VAL = VAL || '} ';
  VAL = VAL || '.title1 { font-size: 150%;';
  VAL = VAL || 'padding: 8px;';
  VAL = VAL || 'margin-bottom: 4px;';
  VAL = VAL || 'font-weight: bold;';
  VAL = VAL || 'background-color: #D4E157;';
  VAL = VAL || '} ';
  VAL = VAL || '.title2 { ';
  VAL = VAL || 'padding: 4px;';
  VAL = VAL || 'font-weight: bold;';
  VAL = VAL || '} ';
  VAL = VAL || '.details {';
  VAL = VAL || 'width: 100%;';
  VAL = VAL || 'border: 1px solid #e0e0e0;';
  VAL = VAL || '} ';
  VAL = VAL || '.details tr td {';
  VAL = VAL || 'padding: 4px 6px;';
  VAL = VAL || 'min-height: 1rem;';
  VAL = VAL || 'border-right: 1px solid #e0e0e0;';
  VAL = VAL || 'text-align: left;';
  VAL = VAL || '} ';
  VAL = VAL || '.odd td {';
  VAL = VAL || 'background-color: #f7f7f7;';
  VAL = VAL || '} ';
  VAL = VAL || '.thd {';
  VAL = VAL || 'background-color: #F0F4C3;';
  VAL = VAL || '} ';
  VAL = VAL || '.c1 { width: 4rem; } ';
  VAL = VAL || '.c2 { width: 8rem; } ';
  VAL = VAL || '.c3 { width: 4rem; } ';
  VAL = VAL || '.c4 { width: 3rem; } ';
  VAL = VAL || '.c5 { width: 5rem; } ';
  VAL = VAL || '.c6 { width: 15%; } ';
  VAL = VAL || '.c7 { width: 15%; } ';
  VAL = VAL || '.c8 { width: 15%; } ';
  VAL = VAL || '.c9 { width: 15%; } ';
  VAL = VAL || '.c10 { width: 8rem; } ';
  VAL = VAL || '</style>';

  VAL = VAL || '</head>';
  VAL = VAL || '<body style="padding: 8px;">';

  -- Заголовок отчета
  VAL = VAL || '<div class="title1">Ведомость пропусков и замещений</div>';
  VAL = VAL || '<div class="title2">За период с ' || (SELECT RESULT FROM DATE2STR(:I$DATE_FROM)) || ' по ' || (SELECT RESULT FROM DATE2STR(:I$DATE_TO)) || '</div>';

  -- Заголовок таблиц
  VAL = VAL || '<table class="details" cellspacing="0" cellpadding="0">';

  VAL = VAL || '<tr class="thd">';
  VAL = VAL || '<td class="c1">№</td>';
  VAL = VAL || '<td class="c2">Дата</td>';
  VAL = VAL || '<td class="c3">День</td>';
  VAL = VAL || '<td class="c4">Урок</td>';
  VAL = VAL || '<td class="c5">Класс</td>';
  VAL = VAL || '<td class="c6">Было(учитель)</td>';
  VAL = VAL || '<td class="c7">Было(предмет)</td>';
  VAL = VAL || '<td class="c8">Стало(учитель)</td>';
  VAL = VAL || '<td class="c9">Стало(предмет)</td>';
  VAL = VAL || '<td class="c10">Подпись</td>';
  VAL = VAL || '</tr>';
  SUSPEND;

  N = 0;
  L = 1;

  -- Идем только по утвержденным замещениям
  FOR
      SELECT
          P.REPL_DATE, P.LESSON_NUM, EXTRACT(WEEKDAY FROM P.REPL_DATE),
          G1.CAPTION, S1.CAPTION, S2.CAPTION,
          IIF(P.PERSON_ID IS NULL, 'Вакантная ставка', T1.NAME_LAST || ' ' || SUBSTRING(T1.NAME_FIRST FROM 1 FOR 1) || '.' || COALESCE(SUBSTRING(T1.NAME_MID FROM 1 FOR 1) || '.', '')),
          T2.NAME_LAST || ' ' || SUBSTRING(T2.NAME_FIRST FROM 1 FOR 1) || '.' || COALESCE(SUBSTRING(T2.NAME_MID FROM 1 FOR 1) || '.', '')
      FROM CJ2_REPL_PROCESS P
      JOIN CJ2_JOURNAL J1 ON J1.OBJ_ID = P.CJ_ID
      JOIN CJ2_JOURNAL J2 ON J2.OBJ_ID = COALESCE(P.REPL_CJ_ID, P.CJ_ID)
      LEFT JOIN UT_PERSON_DESC(P.PERSON_ID) T1 ON 1 = 1
      LEFT JOIN UT_PERSON_DESC(P.REPL_PERSON_ID) T2 ON 1 = 1
      LEFT JOIN OBJECT_CAPTION_GET(J1.GRADE_ID) G1 ON 1 = 1
      LEFT JOIN OBJECT_CAPTION_GET(J1.SUBJECT_ID) S1 ON 1 = 1
      LEFT JOIN OBJECT_CAPTION_GET(J2.SUBJECT_ID) S2 ON 1 = 1
      WHERE P.REPL_DATE >= :I$DATE_FROM AND P.REPL_DATE <= :I$DATE_TO AND P.DATE_DEL IS NULL
          -- AND P.IS_APPROVED = 1
      ORDER BY 1, 2, 3
      INTO :V$DATE, :V$LESSON_NUM, :V$DW, :V$GROUP_NAME1, :V$SUBJECT_NAME1, :V$SUBJECT_NAME2, :V$TEACHER_NAME1, :V$TEACHER_NAME2
  DO
  BEGIN

      VAL = '<tr';
      IF(N = 1) THEN VAL = VAL || ' class="odd"';
      VAL = VAL || '>';

      IF(V$DW = 0) THEN V$S = 'Вс';
      ELSE IF(V$DW = 1) THEN V$S = 'Пн';
      ELSE IF(V$DW = 2) THEN V$S = 'Вт';
      ELSE IF(V$DW = 3) THEN V$S = 'Ср';
      ELSE IF(V$DW = 4) THEN V$S = 'Чт';
      ELSE IF(V$DW = 5) THEN V$S = 'Пт';
      ELSE IF(V$DW = 6) THEN V$S = 'Сб';

      IF(V$LESSON_NUM < 60) THEN V$VN = V$LESSON_NUM;
      ELSE
      BEGIN
        V$VN = CAST(V$LESSON_NUM / 100 AS INTEGER);
        V$LESSON_NUM = V$LESSON_NUM - CAST(V$VN AS INTEGER) * 100;
        IF(CHAR_LENGTH(V$VN) = 1) THEN V$VN = '0' || V$VN;
        V$VN = V$VN || ':';
        IF(V$LESSON_NUM < 10) THEN V$VN = V$VN || '0' || V$LESSON_NUM; ELSE V$VN = V$VN || V$LESSON_NUM;
      END

      VAL = VAL || '<td class="c1">' || L || '</td>';
      VAL = VAL || '<td class="c2">' || (SELECT RESULT FROM DATE2STR(:V$DATE)) || '</td>';
      VAL = VAL || '<td class="c3">' || V$S || '</td>';
      VAL = VAL || '<td class="c4">' || V$VN || '</td>';
      VAL = VAL || '<td class="c5">' || V$GROUP_NAME1 || '</td>';
      VAL = VAL || '<td class="c6">' || V$TEACHER_NAME1 || '</td>';
      VAL = VAL || '<td class="c7">' || V$SUBJECT_NAME1 || '</td>';
      VAL = VAL || '<td class="c8">' || V$TEACHER_NAME2 || '</td>';
      VAL = VAL || '<td class="c9">' || V$SUBJECT_NAME2 || '</td>';
      VAL = VAL || '<td class="c10">&nbsp;</td>';

      VAL = VAL || '</tr>';
      SUSPEND;

      IF(N = 0) THEN N = 1; ELSE N = 0;
      L = L + 1;

  END

  VAL = '</table>';
  VAL = VAL || '</body>';
  VAL = VAL || '</html>';

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_REPL_TEACHERS_LIST (
    I$USER_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    OBJ_CAPTION VARCHAR(1000),
    PARENT_ID BIGINT,
    COMMENTS VARCHAR(200))
AS
declare variable N integer;
begin

  FOR
      SELECT L14.OBJ_ID, C.CAPTION
      FROM LINKS L2
      JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
      LEFT JOIN OBJECT_CAPTION_GET(L14.OBJ_ID) C ON 1 = 1
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      INTO :OBJ_ID, :OBJ_CAPTION
  DO
  BEGIN

      -- Проверяем наличие учебной нагрузки
      N = 0;

      SELECT FIRST 1 1
      FROM LINKS L58
      WHERE L58.PARENT_ID = :OBJ_ID AND L58.OBJ_TYPE_ID = 58 AND L58.DATE_DEL IS NULL
      INTO :N;

      IF(N > 0) THEN SUSPEND;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_REPORTS_DTL (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40),
    I$ZONE SMALLINT)
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$SRC_TYPE BIGINT;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$TYPE_ID BIGINT;
DECLARE VARIABLE S1 VARCHAR(400);
DECLARE VARIABLE S2 VARCHAR(400);
DECLARE VARIABLE S3 VARCHAR(400);
DECLARE VARIABLE V$MULT BIGINT;
DECLARE VARIABLE V$IS_BIBL SMALLINT;
DECLARE VARIABLE V$GEN BIGINT;
DECLARE VARIABLE V$YEAR INTEGER;
begin

  -- Пользователь с ролью библиотекарь или должностью библиотекарь видит все
  V$IS_BIBL = 0;
  IF(I$USER_ID <> 'Веб-администратор') THEN
  IF(EXISTS(
    -- Роль = библиотекарь
    SELECT FIRST 1 1
    FROM USERS U
    WHERE U.USER_ID = :I$USER_ID AND U.DATE_DEL IS NULL AND U.USER_TYPE = 11
  )
  OR EXISTS(
    -- Должность = библиотекарь
    SELECT FIRST 1 1
    FROM USERS U
    JOIN LINKS L15 ON L15.PARENT_ID = U.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
    JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
    LEFT JOIN VALS V3543 ON V3543.OBJ_ID = L15.OBJ_ID AND V3543.PARAM_ID = 3543 AND V3543.IS_DEL = 0
    LEFT JOIN VALS V589 ON V589.OBJ_ID = L15.OBJ_ID AND V589.PARAM_ID = 589 AND V589.IS_DEL = 0
    WHERE U.USER_ID = :I$USER_ID AND U.DATE_DEL IS NULL AND V74.VAL IS NULL
      AND (UPPER(V3543.SVAL) LIKE '%БИБЛИОТ%' OR UPPER(V589.SVAL) LIKE '%БИБЛИОТ%')
  ))
  THEN
    V$IS_BIBL = 1;

  IF(V$IS_BIBL = 0 AND (SELECT ACCESS_LEVEL FROM CJ2_GRADE_ACCESS(:I$OBJ_ID, :I$USER_ID)) = 0) THEN
    EXCEPTION DATA_ERROR 'Нет доступа к данному учебному коллективу';

  SELECT TYPE_ID
  FROM OBJECTS
  WHERE OBJ_ID = :I$OBJ_ID
  INTO :V$SRC_TYPE;

  -- Сотрудники
  IF(I$OBJ_ID = 0) THEN V$SRC_TYPE = 0;

  SELECT MULTIPLIER, GEN
  FROM GEN
  INTO :V$MULT, :V$GEN;

  SELECT LV.COST
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$YEAR;

  TAG_NAME = 'items::json&colon;array';
  VAL = 1;
  SUSPEND;

  IF(V$SRC_TYPE IN (9, 187, 256, 347, 179)) THEN
  BEGIN
    FOR
      SELECT DISTINCT MM.STUDENT_ID, MM.TYPE_ID, V1.VAL, V2.VAL
      FROM CJ2_MEMBER_MOVEMENTS(:I$OBJ_ID, :V$SRC_TYPE, NULL) MM
      JOIN VALS V1 ON V1.OBJ_ID = MM.STUDENT_ID AND V1.PARAM_ID IN (55, 59, 128, 827) AND V1.IS_DEL = 0
      JOIN VALS V2 ON V2.OBJ_ID = MM.STUDENT_ID AND V2.PARAM_ID IN (56, 60, 129, 828) AND V2.IS_DEL = 0
      WHERE MM.DATE_FROM >= '25.08.' || :V$YEAR AND (MM.DATE_TO IS NULL OR MM.DATE_TO > '01.09.' || :V$YEAR)
      ORDER BY 3, 4, 1
      INTO :V$OBJ_ID, :V$TYPE_ID, :S1, :S2
    DO
    BEGIN
      TAG_NAME = 'items:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'items:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'items:r:type';
      VAL = V$TYPE_ID;
      SUSPEND;

      TAG_NAME = 'items:r:name';
      VAL = NULL;
      IF(I$ZONE IN (0, 2)) THEN
      BEGIN
        S3 = (SELECT VAL FROM VALS WHERE OBJ_ID = :V$OBJ_ID AND PARAM_ID IN (57, 61, 130, 829) AND IS_DEL = 0);
        VAL = S1 || ' ' || S2 || COALESCE(' ' || S3, '');
      END
      ELSE
      BEGIN
        SELECT FIRST 1 V2991.VAL
        FROM VALS V2991
        WHERE V2991.OBJ_ID = :V$OBJ_ID AND V2991.PARAM_ID = 2991 AND V2991.IS_DEL = 0
        INTO :VAL;
        IF(VAL IS NULL) THEN BEGIN
            SELECT FIRST 1 V2153.VAL
            FROM VALS V2153
            WHERE V2153.OBJ_ID = :V$OBJ_ID AND V2153.PARAM_ID IN (2153, 2152) AND V2153.IS_DEL = 0
            INTO :VAL;
        END
        IF(VAL IS NULL) THEN
        BEGIN
          VAL = V$GEN;
          IF(V$TYPE_ID = 14) THEN VAL = VAL || 't'; ELSE VAL = VAL || 'p';
          VAL = VAL || (V$OBJ_ID - TRUNC(V$OBJ_ID / V$MULT) * V$MULT);
        END
      END
      SUSPEND;
    END
  END

  IF(V$SRC_TYPE = 0) THEN
  BEGIN
    -- Все сотрудники в текущем учебном году
    FOR
      SELECT L14.OBJ_ID, L14.OBJ_ID, V1.SVAL, V2.SVAL
      FROM LINKS L2
      JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
      JOIN VALS V1 ON V1.OBJ_ID = L14.OBJ_ID AND V1.PARAM_ID IN (55, 59, 128, 827) AND V1.IS_DEL = 0
      JOIN VALS V2 ON V2.OBJ_ID = L14.OBJ_ID AND V2.PARAM_ID IN (56, 60, 129, 828) AND V2.IS_DEL = 0
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      ORDER BY 3, 4
      INTO :V$OBJ_ID, :V$TYPE_ID, :S1, :S2
    DO
    BEGIN
      TAG_NAME = 'items:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'items:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'items:r:type';
      VAL = V$TYPE_ID;
      SUSPEND;

      TAG_NAME = 'items:r:name';
      VAL = NULL;
      IF(I$ZONE IN (0, 2)) THEN
      BEGIN
          S3 = (SELECT VAL FROM VALS WHERE OBJ_ID = :V$OBJ_ID AND PARAM_ID IN (61) AND IS_DEL = 0);
          VAL = S1 || ' ' || S2 || COALESCE(' ' || S3, '');
      END
      ELSE
      BEGIN
        /*SELECT FIRST 1 V2152.VAL
        FROM VALS V2152
        WHERE V2152.OBJ_ID = :V$OBJ_ID AND V2152.PARAM_ID = 2152 AND V2152.IS_DEL = 0
        INTO :VAL;*/
        VAL = V$GEN;
        VAL = VAL || 't';
        VAL = VAL || (V$OBJ_ID - TRUNC(V$OBJ_ID / V$MULT) * V$MULT);
      END
      SUSPEND;
    END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_REPORTS_MENU (
    I$CJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$YEAR_ID BIGINT;
DECLARE VARIABLE V$OU_ID BIGINT;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$DATE1 DATE;
DECLARE VARIABLE V$DATE2 DATE;
DECLARE VARIABLE V$PERIOD BIGINT;
DECLARE VARIABLE V$TYPE_ID BIGINT;
DECLARE VARIABLE V$STAGE_ID BIGINT;
DECLARE VARIABLE V$GRADE_ID BIGINT;
DECLARE VARIABLE V$YEAR INTEGER;
DECLARE VARIABLE V$IS_BIBL SMALLINT;
DECLARE VARIABLE S VARCHAR(1000);
DECLARE VARIABLE V$OU_TYPE CHAR(1);
begin

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  V$OU_TYPE = (SELECT STATUS FROM OU_LICENCE_TYPE);
  TAG_NAME = 'ou_type';
  VAL = V$OU_TYPE;
  SUSPEND;

  -- Пользователь с ролью библиотекарь или должностью библиотекарь видит все
  V$IS_BIBL = 0;
  IF(EXISTS(
    -- Роль = библиотекарь
    SELECT FIRST 1 1
    FROM USERS U
    WHERE U.USER_ID = :I$USER_ID AND U.DATE_DEL IS NULL AND U.USER_TYPE = 11
  )
  OR EXISTS(
    -- Должность = библиотекарь
    SELECT FIRST 1 1
    FROM USERS U
    JOIN LINKS L15 ON L15.PARENT_ID = U.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
    JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
    LEFT JOIN VALS V3543 ON V3543.OBJ_ID = L15.OBJ_ID AND V3543.PARAM_ID = 3543 AND V3543.IS_DEL = 0
    LEFT JOIN VALS V589 ON V589.OBJ_ID = L15.OBJ_ID AND V589.PARAM_ID = 589 AND V589.IS_DEL = 0
    WHERE U.USER_ID = :I$USER_ID AND U.DATE_DEL IS NULL AND V74.VAL IS NULL
      AND (UPPER(V3543.SVAL) LIKE '%БИБЛИОТ%' OR UPPER(V589.SVAL) LIKE '%БИБЛИОТ%')
  ))
  THEN
    V$IS_BIBL = 1;

  -- Текущий учебный год
  SELECT FIRST 1 L2.OBJ_ID, V1236.LISTVAL_ID, LV.COST, C.CAPTION
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  LEFT JOIN OBJECT_CAPTION_GET(L2.OBJ_ID) C ON 1 = 1
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$OU_ID, :V$YEAR_ID, :V$YEAR, :S;

  TAG_NAME = 'year';
  VAL = V$YEAR;
  SUSPEND;

  -- Список всех настроенных периодов
  TAG_NAME = 'periods::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L154.OBJ_ID, V1169.VAL, V1174.VAL, V1170.LISTVAL_ID
    FROM LINKS L150
    LEFT JOIN VALL V3389 ON V3389.OBJ_ID = L150.OBJ_ID AND V3389.PARAM_ID = 3389 AND V3389.IS_DEL = 0
    JOIN LINKS L151 ON L151.PARENT_ID = L150.OBJ_ID AND L151.OBJ_TYPE_ID = 151 AND L151.DATE_DEL IS NULL
    JOIN LINKS L154 ON L154.PARENT_ID = L151.OBJ_ID AND L154.OBJ_TYPE_ID = 154 AND L154.DATE_DEL IS NULL
    JOIN VALL V1170 ON V1170.OBJ_ID = L154.OBJ_ID AND V1170.PARAM_ID = 1170 AND V1170.IS_DEL = 0
    JOIN VALD V1169 ON V1169.OBJ_ID = L154.OBJ_ID AND V1169.PARAM_ID = 1169 AND V1169.IS_DEL = 0
    JOIN VALD V1174 ON V1174.OBJ_ID = L154.OBJ_ID AND V1174.PARAM_ID = 1174 AND V1174.IS_DEL = 0
    WHERE L150.PARENT_TYPE_ID = 2 AND L150.OBJ_TYPE_ID IN (150, 481) AND L150.DATE_DEL IS NULL
      AND (V3389.LISTVAL_ID IS NULL OR V3389.LISTVAL_ID = :V$YEAR_ID)
    ORDER BY 2, 3
    INTO :V$OBJ_ID, :V$DATE1, :V$DATE2, :V$PERIOD
  DO
  BEGIN
    TAG_NAME = 'periods:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'periods:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'periods:r:period';
    VAL = V$PERIOD;
    SUSPEND;
    TAG_NAME = 'periods:r:date_from';
    VAL = (SELECT VAL FROM DATE2ISO(:V$DATE1));
    SUSPEND;
    TAG_NAME = 'periods:r:date_to';
    VAL = (SELECT VAL FROM DATE2ISO(:V$DATE2));
    SUSPEND;
  END

  -- Список всех коллективов, доступных данному пользователю
  -- Пока только общеобразовательные и внеурочка
  TAG_NAME = 'items::json&colon;array';
  VAL = 1;
  SUSPEND;
  -- Корневой уровень - ОУ
  TAG_NAME = 'items:r';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'items:r:id';
  VAL = V$OU_ID;
  SUSPEND;
  TAG_NAME = 'items:r:type';
  VAL = 2;
  SUSPEND;
  TAG_NAME = 'items:r:name';
  VAL = S;
  SUSPEND;
  TAG_NAME = 'items:r:items::json&colon;array';
  VAL = 1;
  SUSPEND;
  -- Второй уровень меню - уровни обучения
  -- Для Библиографа пункт Сотрудники
  IF(I$CJ_ID = -1) THEN
  BEGIN
    TAG_NAME = 'items:r:items:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'items:r:items:r:id';
    VAL = 0;
    SUSPEND;
    TAG_NAME = 'items:r:items:r:type';
    VAL = 0;
    SUSPEND;
    TAG_NAME = 'items:r:items:r:name';
    VAL = 'Сотрудники';
    SUSPEND;
  END
  -- !!! ОДОД
  /*
    SELECT L243.OBJ_ID, L243.OBJ_TYPE_ID, C1.CAPTION || ' - ' || C2.CAPTION, 0
    FROM LINKS L242
    JOIN LINKS L243 ON L243.PARENT_ID = L242.OBJ_ID AND L243.OBJ_TYPE_ID = 243 AND L243.DATE_DEL = 0
    LEFT JOIN CJ2_GRADE_ACCESS(L243.OBJ_ID, :I$USER_ID) A ON 1 = 1
    LEFT JOIN OBJECT_CAPTION_GET(L242.OBJ_ID) C1 ON 1 = 1
    LEFT JOIN OBJECT_CAPTION_GET(L243.OBJ_ID) C2 ON 1 = 1
    WHERE L242.PARENT_ID = :V$OU_ID AND L242.OBJ_TYPE_ID = 242 AND L242.DATE_DEL IS NULL AND A.ACCESS_LEVEL > 0
  */
  FOR
    SELECT L7.OBJ_ID, L7.OBJ_TYPE_ID, C.CAPTION
    FROM LINKS L7
    LEFT JOIN OBJECT_CAPTION_GET(L7.OBJ_ID) C ON 1 = 1
    WHERE L7.PARENT_ID = :V$OU_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    AND (:V$IS_BIBL = 1 OR EXISTS(
      SELECT FIRST 1 1
      FROM LINKS L8
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 187) AND L9.DATE_DEL IS NULL
      LEFT JOIN CJ2_GRADE_ACCESS(L9.OBJ_ID, :I$USER_ID) A ON 1 = 1
      WHERE L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL AND A.ACCESS_LEVEL > 0
    ))
    ORDER BY C.SORT_ORDER, C.CAPTION
    INTO :V$OBJ_ID, :V$TYPE_ID, :S
  DO
  BEGIN
    TAG_NAME = 'items:r:items:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'items:r:items:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'items:r:items:r:type';
    VAL = V$TYPE_ID;
    SUSPEND;
    TAG_NAME = 'items:r:items:r:name';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'items:r:items:r:items::json&colon;array';
    VAL = 1;
    SUSPEND;
    -- Третий уровень - параллели
    FOR
      SELECT L8.OBJ_ID, L8.OBJ_TYPE_ID, C.CAPTION
      FROM LINKS L8
      LEFT JOIN OBJECT_CAPTION_GET(L8.OBJ_ID) C ON 1 = 1
      WHERE L8.PARENT_ID = :V$OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
      AND (:V$IS_BIBL = 1 OR EXISTS(
        SELECT FIRST 1 1
        FROM LINKS L9
        LEFT JOIN CJ2_GRADE_ACCESS(L9.OBJ_ID, :I$USER_ID) A ON 1 = 1
        WHERE L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 187) AND L8.DATE_DEL IS NULL AND A.ACCESS_LEVEL > 0
      ))
      ORDER BY C.SORT_ORDER, C.CAPTION
      INTO :V$STAGE_ID, :V$TYPE_ID, :S
    DO
    BEGIN
      TAG_NAME = 'items:r:items:r:items:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'items:r:items:r:items:r:id';
      VAL = V$STAGE_ID;
      SUSPEND;
      TAG_NAME = 'items:r:items:r:items:r:type';
      VAL = V$TYPE_ID;
      SUSPEND;
      TAG_NAME = 'items:r:items:r:items:r:name';
      VAL = S;
      SUSPEND;
      TAG_NAME = 'items:r:items:r:items:r:items::json&colon;array';
      VAL = 1;
      SUSPEND;
      FOR
        SELECT L9.OBJ_ID, L9.OBJ_TYPE_ID, C.CAPTION
        FROM LINKS L9
        LEFT JOIN CJ2_GRADE_ACCESS(L9.OBJ_ID, :I$USER_ID) A ON 1 = 1
        LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C ON 1 = 1
        WHERE L9.PARENT_ID = :V$STAGE_ID AND L9.OBJ_TYPE_ID IN (9, 187) AND L9.DATE_DEL IS NULL AND (:V$IS_BIBL = 1 OR A.ACCESS_LEVEL > 0)
        ORDER BY C.SORT_ORDER, C.CAPTION
        INTO :V$GRADE_ID, :V$TYPE_ID, :S
      DO
      BEGIN
        TAG_NAME = 'items:r:items:r:items:r:items:r';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'items:r:items:r:items:r:items:r:id';
        VAL = V$GRADE_ID;
        SUSPEND;
        TAG_NAME = 'items:r:items:r:items:r:items:r:type';
        VAL = V$TYPE_ID;
        SUSPEND;
        TAG_NAME = 'items:r:items:r:items:r:items:r:name';
        VAL = S;
        SUSPEND;
      END
    END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_REPORT_NX100 (
    I$USER_ID BIGINT,
    I$DATE_FROM TIMESTAMP,
    I$DATE_TO TIMESTAMP,
    I$PARENT_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$OPTION_ID BIGINT,
    I$OPTIONS VARCHAR(1000),
    I$ZONE SMALLINT = 0)
RETURNS (
    VAL VARCHAR(6000))
AS
DECLARE VARIABLE S VARCHAR(6000);
DECLARE VARIABLE SS VARCHAR(6000);
DECLARE VARIABLE MS VARCHAR(100);
DECLARE VARIABLE N INTEGER;
DECLARE VARIABLE NN SMALLINT;
DECLARE VARIABLE V$SHOW_PERSONAL SMALLINT = 0;
DECLARE VARIABLE V$CALLER_TYPE BIGINT;
DECLARE VARIABLE V$GRADE_ID BIGINT;
DECLARE VARIABLE V$LESSON_ID BIGINT;
DECLARE VARIABLE V$LESSON_DATE DATE;
DECLARE VARIABLE V$SUBJECT_ID BIGINT;
DECLARE VARIABLE V$SUBJECT_NAME VARCHAR(1000);
DECLARE VARIABLE V$CONTROL_ID BIGINT;
DECLARE VARIABLE V$CONTROL_NAME VARCHAR(100);
DECLARE VARIABLE V$PREV BIGINT;
DECLARE VARIABLE V$PREV_NAME VARCHAR(1000);
DECLARE VARIABLE V$PUPIL_ID BIGINT;
DECLARE VARIABLE V$MARK_USED SMALLINT;
DECLARE VARIABLE V$YEAR_DATE DATE;
DECLARE VARIABLE V$EXISTS SMALLINT;
begin

  FOR
    SELECT TAKEN
    FROM PARSING_STRING_GET(:I$OPTIONS, ';')
    INTO :S
  DO
  BEGIN
    IF(S = 'SHOW_PERSONAL=1') THEN V$SHOW_PERSONAL = 1; -- 'SHOW_PERSONAL' -> 'Показывать персональщиков'
  END

  -- Школа, коллектив, персона
  SELECT TYPE_ID FROM OBJECTS WHERE OBJ_ID = :I$OBJ_ID INTO :V$CALLER_TYPE;

  IF(V$CALLER_TYPE = 10) THEN
  BEGIN
      I$OBJ_ID = I$PARENT_ID;
      SELECT TYPE_ID FROM OBJECTS WHERE OBJ_ID = :I$OBJ_ID INTO :V$CALLER_TYPE;
  END

  IF(EXTRACT(MONTH FROM CURRENT_DATE) >= 9) THEN V$YEAR_DATE = '01.09.' || EXTRACT(YEAR FROM CURRENT_DATE);
  ELSE V$YEAR_DATE = '01.09.' || (EXTRACT(YEAR FROM CURRENT_DATE) - 1);

  -- Таблица стилей
  VAL = '<!DOCTYPE html>';
  VAL = VAL || '<html lang="ru">';
  VAL = VAL || '<head>';
  VAL = VAL || '<meta charset="utf-8" />';

  VAL = VAL || '<style>';
  VAL = VAL || 'html { font-family: Tahoma, Verdana, Arial;';
  VAL = VAL || 'font-size: 10pt; ';
  VAL = VAL || '} ';
  VAL = VAL || '.title1 { font-size: 150%;';
  VAL = VAL || 'padding: 8px;';
  VAL = VAL || 'margin-bottom: 4px;';
  VAL = VAL || 'font-weight: bold;';
  VAL = VAL || 'background-color: #D4E157;';
  VAL = VAL || '} ';
  VAL = VAL || '.title2 { ';
  VAL = VAL || 'padding: 4px;';
  VAL = VAL || 'font-weight: bold;';
  VAL = VAL || '} ';
  VAL = VAL || '.title3 { ';
  VAL = VAL || 'padding: 4px;';
  VAL = VAL || 'font-weight: bold;';
  VAL = VAL || 'margin-bottom: 4px;';
  VAL = VAL || '} ';
  VAL = VAL || '.details {';
  VAL = VAL || 'margin-top: 10px;';
  VAL = VAL || 'border: 1px solid #c0c0c0;';
  VAL = VAL || '} ';
  VAL = VAL || '.details tr td {';
  VAL = VAL || 'padding: 2px 4px;';
  VAL = VAL || 'border-right: 1px solid #e0e0e0;';
  VAL = VAL || 'text-align: left;';
  VAL = VAL || '} ';
  VAL = VAL || '.odd td {';
  VAL = VAL || 'background-color: #f7f7f7;';
  VAL = VAL || '} ';
  VAL = VAL || '.thd {';
  VAL = VAL || 'background-color: #F0F4C3;';
  VAL = VAL || '} ';
  VAL = VAL || '.ths td {';
  VAL = VAL || 'border-bottom: 1px solid #c0c0c0;';
  VAL = VAL || '} ';
  VAL = VAL || '.thv {';
  VAL = VAL || 'width: 5em;';
  VAL = VAL || 'text-align: center;';
  VAL = VAL || '} ';
  VAL = VAL || '.tms {';
  VAL = VAL || 'width: 5em;';
  --VAL = VAL || 'background-color: #a0a0a0;';
  VAL = VAL || 'background-color: #808080;';
  VAL = VAL || '} ';
  VAL = VAL || '.odd td.tms {';
  VAL = VAL || 'width: 5em;';
  VAL = VAL || 'background-color: #808080;';
  VAL = VAL || '} ';
  VAL = VAL || '.tn {';
  VAL = VAL || 'width: 3em;';
  VAL = VAL || '} ';
  VAL = VAL || '.tp {';
  VAL = VAL || 'min-width: 15em;';
  VAL = VAL || '} ';
  VAL = VAL || '.thf {';
  VAL = VAL || 'background-color: #F0F4C3;';
  VAL = VAL || '} ';
  VAL = VAL || '.alert {';
  VAL = VAL || 'margin: 4px;';
  VAL = VAL || 'padding: 10px;';
  VAL = VAL || 'color: darkred;';
  VAL = VAL || 'background-color: #ffe0e0;';
  VAL = VAL || '} ';
  VAL = VAL || '</style>';

  VAL = VAL || '</head>';
  VAL = VAL || '<body>';

  -- Заголовок отчета
  VAL = VAL || '<div class="title1">Выписка отметок из классного журнала за период</div>';
  VAL = VAL || '<div class="title2">Период: ' || (SELECT RESULT FROM DATE2STR(:I$DATE_FROM)) || ' - ' || (SELECT RESULT FROM DATE2STR(:I$DATE_TO)) || '</div>';
  VAL = VAL || '<div class="title2">' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$OBJ_ID)) || '</div>';
  SUSPEND;

  -- Префикс и заголовок таблицы - формируем две строки заголовка
  -- Первая строка - группируем названия предметов
  VAL = '<table class="details" cellspacing="0" cellpadding="0">';
  VAL = VAL || '<tr class="ths thf"><td class="tn" /><td class="tp" />';
  S = '<tr class="ths thf"><td class="tn">№</td><td class="tp">Ученики</td>';
  SS = '<tr class="thf"><td /><td />';

  V$PREV = NULL;
  N = 0;
  FOR
    SELECT GRADE_ID, SUBJECT_ID, SUBJECT_NAME, LESSON_ID, LESSON_DATE, CONTROL_ID, CONTROL_NAME
    FROM CJ2_REPORT_NX100_LESSONS(:I$OBJ_ID, :I$DATE_FROM, :I$DATE_TO, :V$SHOW_PERSONAL)
    ORDER BY 3, 5, 6
    INTO :V$GRADE_ID, :V$SUBJECT_ID, :V$SUBJECT_NAME, :V$LESSON_ID, :V$LESSON_DATE, :V$CONTROL_ID, :V$CONTROL_NAME
  DO
  BEGIN
    IF(V$PREV IS NOT NULL AND V$PREV <> V$SUBJECT_ID) THEN
    BEGIN
      VAL = VAL || '<td';
      IF(N > 1) THEN VAL = VAL || ' colspan="' || N || '"';
      VAL = VAL || '>' || V$PREV_NAME || '</td>';
      N = 0;
    END
    V$PREV = V$SUBJECT_ID;
    V$PREV_NAME = V$SUBJECT_NAME;
    N = N + 1;
    S = S || '<td class="thv">' || EXTRACT(DAY FROM V$LESSON_DATE) || '.' || EXTRACT(MONTH FROM V$LESSON_DATE) || '</td>';
    SS = SS || '<td class="thv">' || V$CONTROL_NAME || '</td>';

    IF(CHAR_LENGTH(VAL) > 5900 OR CHAR_LENGTH(S) > 5900 OR CHAR_LENGTH(SS) > 5900) THEN
    BEGIN
      VAL = '<div class="alert">Переполнение при формировании отчета. Вероятно, вы выбрали слишком большой интервал времени...</div>';
      SUSPEND;
      EXIT;
    END
  END

  -- Закрываем последний заголовок предмета
  IF(N > 0) THEN
  BEGIN
    VAL = VAL || '<td';
    IF(N > 1) THEN VAL = VAL || ' colspan="' || N || '"';
    VAL = VAL || '>' || V$PREV_NAME || '</td>';
  END

  VAL = VAL || '</tr>';
  SUSPEND;
  VAL = S || '</tr>';
  SUSPEND;

  -- Цикл по ученикам
  N = 1;
  NN = 0;
  FOR
    SELECT DISTINCT L10.OBJ_ID, P.NAME_FULL -- IIF(:I$ZONE IN (0, 2), V55.SVAL || ' ' || V56.SVAL || COALESCE(' ' || V57.SVAL, ''), COALESCE(V1380.SVAL, L10.OBJ_ID))
    FROM LINKS L10
    LEFT JOIN UT_PERSON_DESC(L10.OBJ_ID, :I$ZONE, 1) P ON 1 = 1     -- имя пользователя тоже покажем через псевдоним в зависимости от зоны, redmine #1060
    JOIN PERSON_MOVEMENTS M1 ON M1.DATE_DEL IS NULL AND M1.PERSON_ID = L10.OBJ_ID AND M1.GROUP_ID = L10.PARENT_ID
      AND M1.DATE_IN <= :I$DATE_TO AND (M1.DATE_OUT IS NULL OR M1.DATE_OUT >= :I$DATE_FROM)
    -- ФИО
    --JOIN VALS V55 ON V55.OBJ_ID = L10.OBJ_ID AND V55.PARAM_ID = 55 AND V55.IS_DEL = 0
    --JOIN VALS V56 ON V56.OBJ_ID = L10.OBJ_ID AND V56.PARAM_ID = 56 AND V56.IS_DEL = 0
    --LEFT JOIN VALS V57 ON V57.OBJ_ID = L10.OBJ_ID AND V57.PARAM_ID = 57 AND V57.IS_DEL = 0
    -- Код
    --LEFT JOIN VALS V1380 ON V1380.OBJ_ID = L10.OBJ_ID AND V1380.PARAM_ID = 1380 AND V1380.IS_DEL = 0
    -- Надомник ?
    LEFT JOIN VALL V2169 ON V2169.OBJ_ID = L10.OBJ_ID AND V2169.PARAM_ID = 2169 AND V2169.IS_DEL = 0
    WHERE L10.PARENT_ID = :I$OBJ_ID AND L10.OBJ_TYPE_ID = 10
      AND (V2169.LISTVAL_ID IS NULL OR V2169.LISTVAL_ID = 3 OR :V$SHOW_PERSONAL = 1)
    ORDER BY 2
    INTO :V$PUPIL_ID, :V$SUBJECT_NAME
  DO
  BEGIN
    -- Префикс
    VAL = '<tr';
    IF(NN = 1) THEN VAL = VAL || ' class="odd"';
    VAL = VAL || '>';
    VAL = VAL || '<td class="tn">' || N || '</td>';
    VAL = VAL || '<td class="tp">' || V$SUBJECT_NAME || '</td>';

    -- Отметки
    FOR
      SELECT GRADE_ID, LESSON_ID, CONTROL_ID, IIF(M1.OBJ_ID IS NULL, 0, 1)
      FROM CJ2_REPORT_NX100_LESSONS(:I$OBJ_ID, :I$DATE_FROM, :I$DATE_TO, :V$SHOW_PERSONAL) LS
      LEFT JOIN PERSON_MOVEMENTS M1 ON M1.DATE_DEL IS NULL AND M1.PERSON_ID = :V$PUPIL_ID AND M1.GROUP_ID = LS.GRADE_ID
        AND M1.DATE_IN <= LS.LESSON_DATE AND (M1.DATE_OUT IS NULL OR M1.DATE_OUT >= LS.LESSON_DATE)
      ORDER BY SUBJECT_NAME, LESSON_DATE, CONTROL_ID
      INTO :V$GRADE_ID, :V$LESSON_ID, :V$CONTROL_ID, :V$EXISTS
    DO
    BEGIN
      IF(V$EXISTS = 0) THEN VAL = VAL || '<td class="tms">&nbsp;</td>';
      ELSE
      BEGIN

        S = '';

        -- Проверяем отсутствие на уроке
        SELECT FIRST 1 MT.MARK_SHORTNAME
        FROM CJ2_CONTROL C
        JOIN CJ2_MARK M ON M.DATE_DEL IS NULL AND M.CONTROL_ID = C.CONTROL_ID AND M.STUDENT_ID = :V$PUPIL_ID
        JOIN CJ2_MARK_TYPE MT ON MT.MARK_TYPE_ID = M.MARK_TYPE_ID AND MT.PARENT_ID = 0
        WHERE C.LESSON_ID = :V$LESSON_ID AND C.DATE_DEL IS NULL AND C.CONTROL_TYPE_ID = 0
        INTO :S;

        -- Отметки берем только если ученик присутствовал на уроке
        IF(CHAR_LENGTH(S) = 0) THEN
        BEGIN
          FOR
            SELECT M.IS_USED, MT.MARK_SHORTNAME
            FROM CJ2_MARK M
            JOIN CJ2_MARK_TYPE MT ON MT.MARK_TYPE_ID = M.MARK_TYPE_ID
            WHERE M.CONTROL_ID = :V$CONTROL_ID AND M.STUDENT_ID = :V$PUPIL_ID AND M.DATE_DEL IS NULL
            INTO :V$MARK_USED, :MS
          DO
          BEGIN
            IF(CHAR_LENGTH(S) > 0) THEN S = S || ', ';
            S = S || MS;
          END
        END
        VAL = VAL || '<td class="thv">' || S || '</td>';
      END
    END

    VAL = VAL || '</tr>';
    SUSPEND;
    N = N + 1;
    IF(NN = 0) THEN NN = 1; ELSE NN = 0;
  END

  -- Список названий контролей
  VAL = SS || '</tr>';
  SUSPEND;

  -- Закрываем таблицу
  VAL = '</table></body></html>';
  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_REPORT_NX100_LESSONS (
    I$GRADE_ID BIGINT,
    I$DATE_FROM DATE,
    I$DATE_TO DATE,
    I$SHOW_PERSONAL SMALLINT = 0)
RETURNS (
    CJ_ID BIGINT,
    LESSON_ID BIGINT,
    LESSON_DATE DATE,
    SUBJECT_ID BIGINT,
    GRADE_ID BIGINT,
    GRADE_TYPE_ID BIGINT,
    CONTROL_ID BIGINT,
    SUBJECT_NAME VARCHAR(4000),
    CONTROL_NAME VARCHAR(1000))
AS
declare variable N integer;
declare variable V$YEAR_DATE date;
declare variable V$SKIP smallint;
begin

  IF(EXTRACT(MONTH FROM CURRENT_DATE) >= 9) THEN V$YEAR_DATE = '01.09.' || EXTRACT(YEAR FROM CURRENT_DATE);
  ELSE V$YEAR_DATE = '01.09.' || (EXTRACT(YEAR FROM CURRENT_DATE) - 1);

  -- Выбираем список всех коллективов, где есть (были) дети этого класса в течение указанного промежутка времени
  FOR
    SELECT DISTINCT J.GRADE_ID, G.TYPE_ID, J.SUBJECT_ID, J.OBJ_ID
    FROM LINKS L10
    JOIN PERSON_MOVEMENTS M1 ON M1.DATE_DEL IS NULL AND M1.PERSON_ID = L10.OBJ_ID
    JOIN OBJECTS G ON G.OBJ_ID = M1.GROUP_ID AND G.TYPE_ID = 179
    JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.GRADE_ID = M1.GROUP_ID AND J.JOURNAL_TYPE = 0
    -- Был в классе
    JOIN PERSON_MOVEMENTS M2 ON M2.DATE_DEL IS NULL AND M2.PERSON_ID = L10.OBJ_ID AND M2.GROUP_ID = L10.PARENT_ID
      AND M2.DATE_IN <= :I$DATE_TO AND (M2.DATE_OUT IS NULL OR M2.DATE_OUT >= :I$DATE_FROM)
    -- Надомник ?
    LEFT JOIN VALL V2169 ON V2169.OBJ_ID = L10.OBJ_ID AND V2169.PARAM_ID = 2169 AND V2169.IS_DEL = 0
    WHERE L10.PARENT_ID = :I$GRADE_ID AND L10.OBJ_TYPE_ID = 10
      AND (V2169.LISTVAL_ID IS NULL OR V2169.LISTVAL_ID = 3 OR :I$SHOW_PERSONAL = 1)
    INTO :GRADE_ID, :GRADE_TYPE_ID, :SUBJECT_ID, :CJ_ID
  DO
  BEGIN

    -- Сокращенное наименование предмета
    SUBJECT_NAME = NULL;
    SELECT V377.VAL
    FROM VALS V377
    WHERE V377.OBJ_ID = :SUBJECT_ID AND V377.PARAM_ID = 377 AND V377.IS_DEL = 0
    INTO :SUBJECT_NAME;

    IF(SUBJECT_NAME IS NULL) THEN
    BEGIN
      SELECT SUBSTRING(V376.VAL FROM 1 FOR 10) || '&hellip;'
      FROM VALS V376
      WHERE V376.OBJ_ID = :SUBJECT_ID AND V376.PARAM_ID = 376 AND V376.IS_DEL = 0
      INTO :SUBJECT_NAME;
    END

    FOR
      SELECT CJL.OBJ_ID, CJL.LESSON_DATE
      FROM CJ2_JOURNAL_LESSONS CJL
      WHERE CJL.CJ_ID = :CJ_ID AND CJL.DATE_DEL IS NULL AND CJL.IS_COMPLETED <> 0 AND CJL.LESSON_DATE >= :I$DATE_FROM AND CJL.LESSON_DATE <= :I$DATE_TO
      INTO :LESSON_ID, :LESSON_DATE
    DO
    BEGIN

      -- Если на уроке нет контролей, возвращаем строку без контролей
      N = 0;

      FOR
        SELECT CJC.CONTROL_ID, T.CONTROL_SHORTNAME
        FROM CJ2_CONTROL CJC
        JOIN CJ2_CONTROL_TYPE T ON T.CONTROL_TYPE_ID = CJC.CONTROL_TYPE_ID
        WHERE CJC.LESSON_ID = :LESSON_ID AND CJC.DATE_DEL IS NULL AND CJC.CONTROL_TYPE_ID <> 0 AND CJC.CONTROL_TYPE_ID <> 30000
        INTO :CONTROL_ID, :CONTROL_NAME
      DO
      BEGIN
        N = N + 1;
        SUSPEND;
      END

      IF(N = 0) THEN
      BEGIN
        CONTROL_ID = NULL;
        CONTROL_NAME = '';
        SUSPEND;
      END
    END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_REPORT_NX107 (
    I$USER_ID VARCHAR(40),
    I$DATE_FROM DATE,
    I$DATE_TO DATE,
    I$PARENT_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$OPTION_ID BIGINT,
    I$OPTIONS VARCHAR(1000),
    I$ZONE SMALLINT = 0)
RETURNS (
    VAL VARCHAR(4000))
AS
declare variable V$CALLER_TYPE bigint;
declare variable V$OU_LICENCE_TYPE char(1);
declare variable V$S1 varchar(4000);
declare variable V$S2 varchar(400);
declare variable V$OBJ_ID bigint;
declare variable V$DATE date;
declare variable V$FINAL_TYPE bigint;
declare variable V$SUBJECT_ID bigint;
declare variable V$COST integer;
declare variable V$CNT integer;
declare variable V$DATE2 date;
declare variable V$MARK_ID bigint;
declare variable V$C varchar(100);
declare variable V$T integer;
declare variable V$MAXSCALE integer;
declare variable V$SYSTEM_ID bigint;
declare variable N integer;
begin

  -- Школа, коллектив, персона
  SELECT TYPE_ID FROM OBJECTS WHERE OBJ_ID = :I$OBJ_ID INTO :V$CALLER_TYPE;
  SELECT STATUS FROM OU_LICENCE_TYPE INTO :V$OU_LICENCE_TYPE;

  VAL = '<!DOCTYPE html>';
  VAL = VAL || '<html lang="ru">';
  VAL = VAL || '<head>';
  VAL = VAL || '<meta charset="utf-8" />';
  VAL = VAL || '<style>';
  VAL = VAL || 'html { font-family: Tahoma, Verdana, Arial;';
  VAL = VAL || 'font-size: 10pt; ';
  VAL = VAL || '} ';
  VAL = VAL || '</style>';

  VAL = VAL || '</head>';
  VAL = VAL || '<body>';
  SUSPEND;

  -- Заголовок отчета
  VAL = '<div class="title1">Рейтинги обучающихся</div>';

  VAL = VAL || '<div class="title2">' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$OBJ_ID)) || '</div>';
  V$S1 = (SELECT RESULT FROM DATE2STR(:I$DATE_FROM));
  V$S2 = (SELECT RESULT FROM DATE2STR(:I$DATE_TO));
  VAL = VAL || '<div class="title2">Период: ' || V$S1 || ' - ' || V$S2 || '</div>';

  -- Чистим временную таблицу и заполняем реальными датами
  DELETE FROM CJ_REPORT4_TEMP WHERE 1 = 1;

  -- Заголовок таблицы
  VAL = VAL || '<table class="table" cellspacing="0" cellpadding="0">';
  VAL = VAL || '<tr class="thd">';

  IF(V$CALLER_TYPE = 10) THEN
  BEGIN
    -- По конкретному ученику
    VAL = VAL || '<td class="sortable text">Предмет/тема</td>';
    VAL = VAL || '<td class="sortable text">Контроль</td>';
    VAL = VAL || '<td class="sortable date">Дата</td>';
    VAL = VAL || '<td class="sortable value">Результат</td>';
    VAL = VAL || '<td class="sortable date">Дата отметки</td>';
    VAL = VAL || '</tr>';
    SUSPEND;

    N = 0;
    V$T = 0;
    V$CNT = 0;
    V$MAXSCALE = 0;
    FOR
      SELECT DISTINCT F.OBJ_ID, J.SUBJECT_ID, F.FINAL_DATE, F.FINAL_TYPE, FT.VAL, MT.MARK_COST, MT.MARK_NAME, M.MARK_DATE, M.MARK_TYPE_ID, F.MARK_SYSTEM_ID
      FROM PERSON_MOVEMENTS MV
      JOIN OBJECTS G ON G.OBJ_ID = MV.GROUP_ID AND G.TYPE_ID = 179
      JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.GRADE_ID = G.OBJ_ID AND J.JOURNAL_TYPE = 0
      JOIN CJ2_JOURNAL_FINALS F ON F.DATE_DEL IS NULL AND F.CJ_ID = J.OBJ_ID
      LEFT JOIN LISTVAL_TEXT(F.FINAL_TYPE) FT ON 1 = 1
      LEFT JOIN CJ2_MARK M ON M.DATE_DEL IS NULL AND M.STUDENT_ID = MV.PERSON_ID AND M.FINAL_ID = F.OBJ_ID
      LEFT JOIN CJ2_MARK_TYPE MT ON MT.MARK_TYPE_ID = M.MARK_TYPE_ID
      WHERE MV.DATE_DEL IS NULL AND MV.PERSON_ID = :I$OBJ_ID
      ORDER BY 2, 3
      INTO :V$OBJ_ID, :V$SUBJECT_ID, :V$DATE, :V$FINAL_TYPE, :V$S1, :V$COST, :V$S2, :V$DATE2, :V$MARK_ID, :V$SYSTEM_ID
    DO
    BEGIN
      IF(V$SYSTEM_ID = 100) THEN V$MAXSCALE = V$MAXSCALE + 1;
      ELSE IF(V$SYSTEM_ID = 400) THEN V$MAXSCALE = V$MAXSCALE + 5;
      ELSE IF(V$SYSTEM_ID = 499) THEN V$MAXSCALE = V$MAXSCALE + 20;
      ELSE IF(V$SYSTEM_ID = 599) THEN V$MAXSCALE = V$MAXSCALE + 100;

      IF(V$MARK_ID = 401) THEN V$C = ' pink'; -- 1
      ELSE IF(V$MARK_ID IN (102, 402)) THEN V$C = ' red'; -- незачет или 2
      ELSE IF(V$MARK_ID = 403) THEN V$C = ' orange'; -- 3
      ELSE IF(V$MARK_ID = 404) THEN V$C = ' blue'; -- 4
      ELSE IF(V$MARK_ID IN (101, 405)) THEN V$C = ' blue'; -- зачет или 5
      ELSE V$C = '';

      VAL = '<tr>';
      VAL = VAL || '<td>' || (SELECT E.VAL FROM OBJECT_CAPTION_GET(:V$SUBJECT_ID) C LEFT JOIN ESCAPE_STR(C.CAPTION) E ON 1 = 1) || '</td>';
      VAL = VAL || '<td>' || (SELECT VAL FROM ESCAPE_STR(:V$S1)) || '</td>';
      VAL = VAL || '<td>' || (SELECT RESULT FROM DATE2STR(:V$DATE)) || '</td>';
      VAL = VAL || '<td>' || COALESCE('<div class="ui circular label' || V$C || '">' || V$S2 || '</div>', '') || '</td>';
      VAL = VAL || '<td>' || COALESCE((SELECT RESULT FROM DATE2STR(:V$DATE2)), '') || '</td>';
      VAL = VAL || '</tr>';
      N = N + COALESCE(V$COST, 0);
      IF(V$COST IS NOT NULL) THEN V$CNT = V$CNT + 1;
      V$T = V$T + 1;
      SUSPEND;
    END

    VAL = '<tr class="total">';
    VAL = VAL || '<td colspan=3>Сумма баллов</td>';
    IF(V$MAXSCALE = 0) THEN V$C = '0'; ELSE V$C = TRUNC(10 * ROUND(10.0 * N / V$MAXSCALE));
    VAL = VAL || '<td class="vpr p' || V$C || '">' || N || ' из ' || V$MAXSCALE || '</td>';
    VAL = VAL || '<td>&nbsp;</td>';
    VAL = VAL || '</tr>';
    VAL = VAL || '<tr class="total">';
    VAL = VAL || '<td colspan=3>Всего зачетов</td>';
    IF(V$T = 0) THEN V$C = '0'; ELSE V$C = TRUNC(10 * ROUND(10.0 * V$CNT / V$T));
    VAL = VAL || '<td class="vpr p' || V$C || '">' || V$CNT || ' из ' || V$T || ' </td>';
    VAL = VAL || '<td>&nbsp;</td>';
    VAL = VAL || '</tr>';
    SUSPEND;

  END
  ELSE IF(V$CALLER_TYPE = 9) THEN
  BEGIN
    -- По группе
    VAL = VAL || '<td class="sortable text">Обучающийся</td>';
    SUSPEND;

    -- Строим список контролей, и сразу его выводим
    V$MAXSCALE = 0;
    FOR
      SELECT DISTINCT F.OBJ_ID, J.SUBJECT_ID, F.FINAL_DATE, F.FINAL_TYPE, FT.VAL, F.MARK_SYSTEM_ID
      FROM LINKS L10
      JOIN PERSON_MOVEMENTS MV ON MV.DATE_DEL IS NULL AND MV.PERSON_ID = L10.OBJ_ID
      JOIN OBJECTS G ON G.OBJ_ID = MV.GROUP_ID AND G.TYPE_ID = 179
      JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.GRADE_ID = G.OBJ_ID AND J.JOURNAL_TYPE = 0
      JOIN CJ2_JOURNAL_FINALS F ON F.DATE_DEL IS NULL AND F.CJ_ID = J.OBJ_ID
      LEFT JOIN LISTVAL_TEXT(F.FINAL_TYPE) FT ON 1 = 1
      WHERE L10.PARENT_ID = :I$OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      ORDER BY 3, 4
      INTO :V$OBJ_ID, :V$SUBJECT_ID, :V$DATE, :V$FINAL_TYPE, :V$S1, :V$SYSTEM_ID
    DO
    BEGIN
      INSERT INTO CJ_REPORT4_TEMP (DATE_ID, CLASS_ID) VALUES (:V$DATE, :V$OBJ_ID);
      VAL = '<td class="dl" data-subject="' || (SELECT E.VAL FROM OBJECT_CAPTION_GET(:V$SUBJECT_ID) C LEFT JOIN ESCAPE_STR(C.CAPTION) E ON 1 = 1) || '" ';
      VAL = VAL || ' data-control="' || (SELECT VAL FROM ESCAPE_STR(:V$S1)) || '"';
      VAL = VAL || '>' || (SELECT RESULT FROM DATE2STR(:V$DATE)) || '</td>';
      SUSPEND;
      IF(V$SYSTEM_ID = 100) THEN V$MAXSCALE = V$MAXSCALE + 1;
      ELSE IF(V$SYSTEM_ID = 400) THEN V$MAXSCALE = V$MAXSCALE + 5;
      ELSE IF(V$SYSTEM_ID = 499) THEN V$MAXSCALE = V$MAXSCALE + 20;
      ELSE IF(V$SYSTEM_ID = 599) THEN V$MAXSCALE = V$MAXSCALE + 100;
    END

    VAL = '<td class="sortable value">Сумма баллов</td>';
    VAL = VAL || '<td class="sortable value">Средневзвешенная отметка</td>';
    VAL = VAL || '<td class="sortable value">Кол-во зачетов</td>';
    VAL = VAL || '</tr>';
    SUSPEND;

    -- Участники
    FOR
      SELECT DISTINCT MV.PERSON_ID, C.CAPTION
      FROM LINKS L10
      JOIN PERSON_MOVEMENTS MV ON MV.DATE_DEL IS NULL AND MV.PERSON_ID = L10.OBJ_ID
      JOIN OBJECTS G ON G.OBJ_ID = MV.GROUP_ID AND G.TYPE_ID = 179
      JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.GRADE_ID = G.OBJ_ID AND J.JOURNAL_TYPE = 0
      LEFT JOIN OBJECT_CAPTION_GET(MV.PERSON_ID, 23) C ON 1 = 1
      WHERE L10.PARENT_ID = :I$OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      ORDER BY 2
      INTO :V$OBJ_ID, :V$S1
    DO
    BEGIN
      VAL = '<tr>';
      VAL = VAL || '<td class="target student" data-target="' || V$OBJ_ID || '">' || V$S1 || '</td>';
      SUSPEND;

      N = 0;
      V$T = 0;
      V$CNT = 0;
      FOR
        SELECT M.MARK_TYPE_ID, M.MARK_DATE, MT.MARK_COST, MT.MARK_NAME
        FROM CJ_REPORT4_TEMP T
        LEFT JOIN CJ2_MARK M ON M.STUDENT_ID = :V$OBJ_ID AND M.FINAL_ID = T.CLASS_ID
        LEFT JOIN CJ2_MARK_TYPE MT ON MT.MARK_TYPE_ID = M.MARK_TYPE_ID
        INTO :V$MARK_ID, :V$DATE, :V$COST, :V$S2
      DO
      BEGIN
        IF(V$MARK_ID = 401) THEN V$C = ' pink'; -- 1
        ELSE IF(V$MARK_ID IN (102, 402)) THEN V$C = ' red'; -- незачет или 2
        ELSE IF(V$MARK_ID = 403) THEN V$C = ' orange'; -- 3
        ELSE IF(V$MARK_ID = 404) THEN V$C = ' blue'; -- 4
        ELSE IF(V$MARK_ID IN (101, 405)) THEN V$C = ' blue'; -- зачет или 5
        ELSE V$C = '';

        VAL = '<td class="dl">' || COALESCE('<div class="ui circular label dl' || V$C || '" data-date="' || COALESCE((SELECT RESULT FROM DATE2STR(:V$DATE)), '') || '">' || V$S2 || '</div>', '') || '</td>';
        SUSPEND;
        N = N + COALESCE(V$COST, 0);
        IF(V$COST IS NOT NULL) THEN V$CNT = V$CNT + 1;
        V$T = V$T + 1;
      END

      IF(V$MAXSCALE = 0) THEN V$C = '0'; ELSE V$C = TRUNC(10 * ROUND(10.0 * N / V$MAXSCALE));
      VAL = '<td class="vpr p' || V$C || '">' || N || '</td>';
      IF(V$CNT = 0) THEN VAL = VAL || '<td>&nbsp;</td>'; ELSE VAL = VAL || '<td>' || CAST(1.0 * N / V$CNT AS NUMERIC(18, 2)) || '</td>';

      -- Конверация в проценты с шагом 10
      IF(V$T = 0) THEN V$C = '0'; ELSE V$C = TRUNC(10 * ROUND(10.0 * V$CNT / V$T));
      VAL = VAL || '<td class="vpr p' || V$C|| '">' || V$CNT || '</td>';
      VAL = VAL || '</tr>';
      SUSPEND;

    END

  END

  VAL = '</table></body></html>';
  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_REPORT_NX11 (
    I$USER_ID VARCHAR(40),
    I$DATE_FROM DATE,
    I$DATE_TO DATE,
    I$PARENT_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$OPTION_ID BIGINT,
    I$OPTIONS VARCHAR(1000),
    I$ZONE SMALLINT = 0)
RETURNS (
    VAL VARCHAR(4000))
AS
DECLARE VARIABLE V$CALLER_TYPE BIGINT;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$S1 VARCHAR(1000);
DECLARE VARIABLE V$S2 VARCHAR(1000);
DECLARE VARIABLE V$S3 VARCHAR(1000);
DECLARE VARIABLE V$TEACHER_ID BIGINT;
DECLARE VARIABLE V$GRADE_TYPE BIGINT;
DECLARE VARIABLE V$GRADE_ID BIGINT;
DECLARE VARIABLE N INTEGER;
DECLARE VARIABLE N2 INTEGER;
DECLARE VARIABLE N3 INTEGER;
DECLARE VARIABLE V$PTP_ID BIGINT;
DECLARE VARIABLE V$AVG FLOAT;
DECLARE VARIABLE V$SUBJECT_ID BIGINT;
DECLARE VARIABLE V$WEEKS INTEGER;
DECLARE VARIABLE V$HOURS FLOAT;
DECLARE VARIABLE V$STAGE_ID1 BIGINT;
DECLARE VARIABLE V$STAGE_ID2 BIGINT;
DECLARE VARIABLE V$STAGE_ID3 BIGINT;
DECLARE VARIABLE V$STAGE_ID4 BIGINT;
DECLARE VARIABLE V$STAGE_ID5 BIGINT;
begin

  -- Отчет актуален только для уровня ОУ или группы учащихся
  -- если вызывается для учащегося, делаем все равно для группы

  -- Школа, коллектив, персона
  SELECT TYPE_ID FROM OBJECTS WHERE OBJ_ID = :I$OBJ_ID INTO :V$CALLER_TYPE;

  IF(V$CALLER_TYPE = 7) THEN
  BEGIN
    FOR
      SELECT DISTINCT V49.LISTVAL_ID
      FROM LINKS L8
      JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
      WHERE L8.PARENT_ID = :I$OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
      INTO :V$OBJ_ID
    DO
    BEGIN
      IF(V$STAGE_ID1 IS NULL) THEN V$STAGE_ID1 = V$OBJ_ID;
      ELSE IF(V$STAGE_ID2 IS NULL) THEN V$STAGE_ID2 = V$OBJ_ID;
      ELSE IF(V$STAGE_ID3 IS NULL) THEN V$STAGE_ID3 = V$OBJ_ID;
      ELSE IF(V$STAGE_ID4 IS NULL) THEN V$STAGE_ID4 = V$OBJ_ID;
      ELSE IF(V$STAGE_ID5 IS NULL) THEN V$STAGE_ID5 = V$OBJ_ID;
    END
  END
  ELSE IF(V$CALLER_TYPE = 8) THEN
  BEGIN
    SELECT V49.LISTVAL_ID
    FROM VALL V49
    WHERE V49.OBJ_ID = :I$OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
    INTO :V$STAGE_ID1;
  END
  ELSE IF(V$CALLER_TYPE = 10) THEN
  BEGIN
    I$OBJ_ID = I$PARENT_ID;
    SELECT TYPE_ID FROM OBJECTS WHERE OBJ_ID = :I$OBJ_ID INTO :V$CALLER_TYPE;
  END

  VAL = '<!DOCTYPE html>';
  VAL = VAL || '<html lang="ru">';
  VAL = VAL || '<head>';
  VAL = VAL || '<meta charset="utf-8" />';
  VAL = VAL || '<style>';
  VAL = VAL || 'html { font-family: Tahoma, Verdana, Arial;';
  VAL = VAL || 'font-size: 10pt; ';
  VAL = VAL || '} ';
  VAL = VAL || '</style>';

  VAL = VAL || '</head>';
  VAL = VAL || '<body>';
  SUSPEND;

  -- Заголовок отчета
  VAL = '<div class="title1">Заполнение журналов</div>';
  VAL = VAL || '<div class="title2">' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$OBJ_ID));
  IF(I$OPTION_ID IS NOT NULL) THEN VAL = VAL || ' · ' || (SELECT COALESCE(C.CAPTION || ' ', '') || J.JOURNAL_NAME
    FROM CJ2_JOURNAL J
    LEFT JOIN OBJECT_CAPTION_GET(J.SUBJECT_ID) C ON J.SUBJECT_ID IS NOT NULL
    WHERE J.OBJ_ID = :I$OPTION_ID
  );
  VAL = VAL || '</div>';
  V$S1 = (SELECT RESULT FROM DATE2STR(:I$DATE_FROM));
  V$S2 = (SELECT RESULT FROM DATE2STR(:I$DATE_TO));
  VAL = VAL || '<div class="title2">Период: ' || V$S1 || ' - ' || V$S2 || '</div>';

  -- Выдаем каталог журналов по классу
  IF(V$CALLER_TYPE = 9 AND I$OPTION_ID IS NULL) THEN
  BEGIN
    SUSPEND;
    FOR
      SELECT DISTINCT J.OBJ_ID, J.GRADE_ID, J.SUBJECT_ID
      FROM LINKS L10
      JOIN LINKS LP179 ON LP179.OBJ_ID = L10.OBJ_ID AND LP179.PARENT_TYPE_ID = 179
      JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.GRADE_ID = LP179.PARENT_ID
      WHERE L10.PARENT_ID = :I$OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      INTO :V$OBJ_ID, :V$GRADE_ID, :V$SUBJECT_ID
    DO
    BEGIN
      V$S1 = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$GRADE_ID)) || ' - ' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$SUBJECT_ID));
      VAL = '<div class="target journal" data-target="' || V$OBJ_ID || '" style="margin-bottom: 0.5rem">' || V$S1 || '</div>';
      SUSPEND;
    END

    VAL = '</body></html>';
    SUSPEND;
    EXIT;
  END

  -- Заголовок таблицы
  VAL = VAL || '<table class="wrapping table" cellspacing="0" cellpadding="0">';
  VAL = VAL || '<tr class="thd">';
  VAL = VAL || '<td>Группа</td>';
  VAL = VAL || '<td>Предмет</td>';
  VAL = VAL || '<td>Преподаватель</td>';
  VAL = VAL || '<td style="width: 6rem">Кол-во обучающихся</td>';
  VAL = VAL || '<td style="width: 6rem">Уроков по плану</td>';
  VAL = VAL || '<td style="width: 6rem">Уроков в журнале</td>';
  VAL = VAL || '<td style="width: 6rem">Выставлено отметок</td>';
  VAL = VAL || '<td style="width: 6rem">Средн. отметок на обучающегося</td>';
  VAL = VAL || '</tr>';
  SUSPEND;

  FOR
    SELECT J.OBJ_ID, CG.CAPTION, CS.CAPTION, J.TEACHER_ID, P.NAME_FULL, -- CC.CAPTION
      J.GRADE_ID, J.GRADE_TYPE_ID, J.WEEKS, J.HOURS
    FROM CJ2_JOURNAL J
    LEFT JOIN OBJECT_CAPTION_GET(J.GRADE_ID) CG ON 1 = 1
    LEFT JOIN OBJECT_CAPTION_GET(J.SUBJECT_ID) CS ON 1 = 1
    LEFT JOIN UT_PERSON_DESC(J.TEACHER_ID, :I$ZONE, 1) P ON 1 = 1   --redmine #1060 --LEFT JOIN OBJECT_CAPTION_GET(J.TEACHER_ID) CC ON 1 = 1
    LEFT JOIN CJ2_JOURNAL_ACCESS(:I$USER_ID, J.OBJ_ID) A ON 1 = 1
    WHERE J.DATE_DEL IS NULL AND J.JOURNAL_TYPE IN (0, 1) AND(
      (J.GRADE_ID = :I$OBJ_ID AND :I$OPTION_ID IS NULL) OR
      ((J.STAGE_INDEX = :V$STAGE_ID1 OR J.STAGE_INDEX = :V$STAGE_ID2 OR J.STAGE_INDEX = :V$STAGE_ID3 OR J.STAGE_INDEX = :V$STAGE_ID4 OR J.STAGE_INDEX = :V$STAGE_ID5) AND :I$OPTION_ID IS NULL) OR
      J.OBJ_ID = :I$OPTION_ID OR
      :V$CALLER_TYPE = 2
    ) AND A.ACCESS_LEVEL > 0
    ORDER BY 2, 3
    INTO :V$OBJ_ID, :V$S1, :V$S2, :V$TEACHER_ID, :V$S3, :V$GRADE_ID, :V$GRADE_TYPE, :V$WEEKS, :V$HOURS
  DO
  BEGIN
    /*SELECT COUNT(DISTINCT M.STUDENT_ID)
    FROM CJ2_MEMBER_MOVEMENTS(:V$GRADE_ID, :V$GRADE_TYPE) M
    WHERE M.DATE_FROM <= :I$DATE_TO AND (M.DATE_TO IS NULL OR M.DATE_TO >= :I$DATE_FROM)
    INTO :N;*/
    SELECT COUNT(*)
    FROM LINKS L10
    WHERE L10.PARENT_ID = :V$GRADE_ID AND L10.OBJ_TYPE_ID IN (10, 14) AND L10.DATE_DEL IS NULL
    INTO :N;

    V$PTP_ID = NULL;
    SELECT FIRST 1 P.PTP_ID
    FROM CJ2_JOURNAL_PTP P
    WHERE P.CJ_ID = :V$OBJ_ID AND P.DATE_DEL IS NULL AND P.APPROVAL_STATE <> 3
    ORDER BY P.APPROVAL_STATE DESC
    INTO :V$PTP_ID;

    SELECT COUNT(*)
    FROM CJ2_JOURNAL_LESSONS L
    WHERE L.CJ_ID = :V$OBJ_ID AND L.DATE_DEL IS NULL AND L.LESSON_DATE >= :I$DATE_FROM AND L.LESSON_DATE <= :I$DATE_TO AND L.IS_COMPLETED > 0
    INTO :N2;

    SELECT COUNT(*)
    FROM CJ2_JOURNAL_LESSONS L
    JOIN CJ2_CONTROL C ON C.LESSON_ID = L.OBJ_ID AND C.DATE_DEL IS NULL AND C.CONTROL_TYPE_ID > 0 AND C.CONTROL_TYPE_ID <> 30000
    JOIN CJ2_MARK M ON M.CONTROL_ID = C.CONTROL_ID AND M.DATE_DEL IS NULL
    JOIN CJ2_MARK_TYPE MT ON MT.MARK_TYPE_ID = M.MARK_TYPE_ID
    JOIN CJ2_MARK_TYPE MTP ON MTP.MARK_TYPE_ID = MT.PARENT_ID
    WHERE L.CJ_ID = :V$OBJ_ID AND L.DATE_DEL IS NULL AND L.LESSON_DATE >= :I$DATE_FROM AND L.LESSON_DATE <= :I$DATE_TO AND L.IS_COMPLETED > 0
    INTO :N3;

    IF(N > 0) THEN V$AVG = N3 / N; ELSE V$AVG = NULL;

    VAL = '<tr class="v" data-id="' || V$OBJ_ID || '">';
    VAL = VAL || '<td>' || V$S1 || '</td>';
    VAL = VAL || '<td>' || V$S2 || '</td>';
    VAL = VAL || '<td>' || V$S3 || '</td>';
    VAL = VAL || '<td>' || N || '</td>';

    N = NULL;
    IF ((I$DATE_TO - I$DATE_FROM) >= 6) THEN
    BEGIN
      IF (V$WEEKS IS NOT NULL AND V$WEEKS > 0) THEN N = V$HOURS * (I$DATE_TO - I$DATE_FROM + 1) / (7 * V$WEEKS);
    END

    VAL = VAL || '<td>' || COALESCE(N, '-') || '</td>';
    VAL = VAL || '<td>' || N2 || '</td>';
    VAL = VAL || '<td>' || N3 || '</td>';
    VAL = VAL || '<td>' || IIF(V$AVG IS NULL, '-', CAST(V$AVG AS NUMERIC(18, 2))) || '</td>';
    VAL = VAL || '</tr>';
    SUSPEND;
  END

  VAL = '</table></body></html>';
  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_REPORT_NX19 (
    I$USER_ID VARCHAR(40),
    I$DATE_FROM DATE,
    I$DATE_TO DATE,
    I$PARENT_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$OPTION_ID BIGINT,
    I$OPTIONS VARCHAR(1000),
    I$ZONE SMALLINT = 0)
RETURNS (
    VAL VARCHAR(4000))
AS
DECLARE VARIABLE V$CALLER_TYPE BIGINT;
DECLARE VARIABLE V$OU_LICENCE_TYPE CHAR(1);
DECLARE VARIABLE V$USER_ADD BIGINT;
DECLARE VARIABLE V$USER_DEL BIGINT;
DECLARE VARIABLE V$S1 VARCHAR(100);
DECLARE VARIABLE V$S2 VARCHAR(400);
DECLARE VARIABLE V$S3 VARCHAR(400);
DECLARE VARIABLE V$DATE DATE;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$LESSON_ID BIGINT;
DECLARE VARIABLE V$CONTROL_ID BIGINT;
DECLARE VARIABLE V$DATE2 TIMESTAMP;
DECLARE VARIABLE V$GRADE_ID BIGINT;
DECLARE VARIABLE V$SUBJECT_ID BIGINT;
DECLARE VARIABLE V$STUDENT_ID BIGINT;
DECLARE VARIABLE V$MARK_TYPE_ID BIGINT;
DECLARE VARIABLE V$T VARCHAR(40);
DECLARE VARIABLE V$STAGE_ID1 BIGINT;
DECLARE VARIABLE V$STAGE_ID2 BIGINT;
DECLARE VARIABLE V$STAGE_ID3 BIGINT;
DECLARE VARIABLE V$STAGE_ID4 BIGINT;
DECLARE VARIABLE V$STAGE_ID5 BIGINT;
begin

  -- Школа, коллектив, персона
  SELECT TYPE_ID FROM OBJECTS WHERE OBJ_ID = :I$OBJ_ID INTO :V$CALLER_TYPE;
  SELECT STATUS FROM OU_LICENCE_TYPE INTO :V$OU_LICENCE_TYPE;

  IF(V$CALLER_TYPE = 7) THEN
  BEGIN
    FOR
      SELECT DISTINCT V49.LISTVAL_ID
      FROM LINKS L8
      JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
      WHERE L8.PARENT_ID = :I$OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
      INTO :V$OBJ_ID
    DO
    BEGIN
      IF(V$STAGE_ID1 IS NULL) THEN V$STAGE_ID1 = V$OBJ_ID;
      ELSE IF(V$STAGE_ID2 IS NULL) THEN V$STAGE_ID2 = V$OBJ_ID;
      ELSE IF(V$STAGE_ID3 IS NULL) THEN V$STAGE_ID3 = V$OBJ_ID;
      ELSE IF(V$STAGE_ID4 IS NULL) THEN V$STAGE_ID4 = V$OBJ_ID;
      ELSE IF(V$STAGE_ID5 IS NULL) THEN V$STAGE_ID5 = V$OBJ_ID;
    END
  END
  ELSE IF(V$CALLER_TYPE = 8) THEN
  BEGIN
    SELECT V49.LISTVAL_ID
    FROM VALL V49
    WHERE V49.OBJ_ID = :I$OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
    INTO :V$STAGE_ID1;
  END

  VAL = '<!DOCTYPE html>';
  VAL = VAL || '<html lang="ru">';
  VAL = VAL || '<head>';
  VAL = VAL || '<meta charset="utf-8" />';
  VAL = VAL || '<style>';
  VAL = VAL || 'html { font-family: Tahoma, Verdana, Arial;';
  VAL = VAL || 'font-size: 10pt; ';
  VAL = VAL || '} ';
  VAL = VAL || '</style>';

  VAL = VAL || '</head>';
  VAL = VAL || '<body>';
  SUSPEND;

  -- Заголовок отчета
  VAL = '<div class="title1">Журнал учета исправлений</div>';

  VAL = VAL || '<div class="title2">';
  IF (:V$CALLER_TYPE = 10) THEN VAL = VAL || (SELECT NAME_FULL FROM UT_PERSON_DESC(:I$OBJ_ID, :I$ZONE, 1));      -- обущающийся
                           ELSE VAL = VAL || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$OBJ_ID));
  VAL = VAL || '</div>';

  V$S1 = (SELECT RESULT FROM DATE2STR(:I$DATE_FROM));
  V$S2 = (SELECT RESULT FROM DATE2STR(:I$DATE_TO));
  VAL = VAL || '<div class="title2">Период: ' || V$S1 || ' - ' || V$S2 || '</div>';

  -- Для организации целиком ставим NULL
  IF(V$CALLER_TYPE = 2) THEN I$OBJ_ID = NULL;

  -- Выдаем каталог журналов по классу
  /*IF(V$CALLER_TYPE = 9 AND I$OPTION_ID IS NULL) THEN
  BEGIN
    SUSPEND;
    FOR
      SELECT DISTINCT J.OBJ_ID, J.GRADE_ID, J.SUBJECT_ID
      FROM LINKS L10
      JOIN LINKS LP179 ON LP179.OBJ_ID = L10.OBJ_ID AND LP179.PARENT_TYPE_ID = 179
      JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.GRADE_ID = LP179.PARENT_ID
      WHERE L10.PARENT_ID = :I$OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      INTO :V$OBJ_ID, :V$GRADE_ID, :V$SUBJECT_ID
    DO
    BEGIN
      V$S1 = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$GRADE_ID)) || ' - ' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$SUBJECT_ID));
      VAL = '<div class="target journal" data-target="' || V$OBJ_ID || '" style="margin-bottom: 0.5rem">' || V$S1 || '</div>';
      SUSPEND;
    END

    VAL = '</body></html>';
    SUSPEND;
    EXIT;
  END*/

  -- Заголовок таблицы
  VAL = VAL || '<table class="table" cellspacing="0" cellpadding="0" style="width: 100%">';

  VAL = VAL || '<tr class="thd">';
  VAL = VAL || '<td>Дата исправления</td>';
  VAL = VAL || '<td>Дата урока</td>';
  VAL = VAL || '<td>Учебный коллектив</td>';
  IF(V$OU_LICENCE_TYPE IN ('O', 'C', 'S')) THEN VAL = VAL || '<td>Предмет</td>';
  VAL = VAL || '<td>ФИО</td>';
  VAL = VAL || '<td>Данные до исправления</td>';
  VAL = VAL || '<td>Кто поставил</td>';
  VAL = VAL || '<td>Данные после исправления</td>';
  VAL = VAL || '<td>Кто исправил</td>';
  VAL = VAL || '<td>Причина исправления</td>';
  VAL = VAL || '</tr>';

  SUSPEND;

  -- По школе смотрим без фильтров вообще
  -- Если стоит OPTION_ID - +фильтр по конкретному коллективу
  -- По классу смотрим все коллективы где есть дети класса
  -- По коллективам 179 и 46 смотрим журналы по данному коллективу

  FOR
    -- Выборка по конкретному учебному коллективу или коллективам
    SELECT L.OBJ_ID, C.CONTROL_ID, L.LESSON_DATE, M.MARK_ID, M.DATE_DEL, M.USER_ID, M.USER_DEL,
      MT.MARK_NAME, COALESCE(R.VAL, '-'), J.GRADE_ID, J.SUBJECT_ID, M.STUDENT_ID, M.MARK_TYPE_ID
    FROM CJ2_JOURNAL J
    JOIN CJ2_JOURNAL_LESSONS L ON L.CJ_ID = J.OBJ_ID AND L.DATE_DEL IS NULL
    JOIN CJ2_CONTROL C ON C.LESSON_ID = L.OBJ_ID AND C.DATE_DEL IS NULL
    JOIN CJ2_MARK M ON M.CONTROL_ID = C.CONTROL_ID AND M.DATE_DEL IS NOT NULL AND M.DATE_DEL BETWEEN :I$DATE_FROM AND DATEADD(1 DAY TO :I$DATE_TO)
    JOIN CJ2_MARK_TYPE MT ON MT.MARK_TYPE_ID = M.MARK_TYPE_ID
    LEFT JOIN LISTVALS LV ON LV.LISTVAL_ID = M.REASON_ID
    LEFT JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
    LEFT JOIN CJ2_JOURNAL_ACCESS(:I$USER_ID, J.OBJ_ID) A ON 1 = 1
    WHERE J.DATE_DEL IS NULL AND :V$CALLER_TYPE IN (2, 46, 7, 8, 179) AND (
      (J.GRADE_ID = :I$OBJ_ID AND :I$OPTION_ID IS NULL) OR
      ((J.STAGE_INDEX = :V$STAGE_ID1 OR J.STAGE_INDEX = :V$STAGE_ID2 OR J.STAGE_INDEX = :V$STAGE_ID3 OR J.STAGE_INDEX = :V$STAGE_ID4 OR J.STAGE_INDEX = :V$STAGE_ID5) AND :I$OPTION_ID IS NULL) OR
      J.OBJ_ID = :I$OPTION_ID OR
      :I$OBJ_ID IS NULL)
    AND A.ACCESS_LEVEL > 0
    UNION
    SELECT F.OBJ_ID, F.OBJ_ID, F.FINAL_DATE, M.MARK_ID, M.DATE_DEL, M.USER_ID, M.USER_DEL,
      MT.MARK_NAME, COALESCE(R.VAL, '-'), J.GRADE_ID, J.SUBJECT_ID, M.STUDENT_ID, M.MARK_TYPE_ID
    FROM CJ2_JOURNAL J
    JOIN CJ2_JOURNAL_FINALS F ON F.CJ_ID = J.OBJ_ID AND F.DATE_DEL IS NULL
    JOIN CJ2_MARK M ON M.FINAL_ID = F.OBJ_ID AND M.DATE_DEL IS NOT NULL AND M.DATE_DEL BETWEEN :I$DATE_FROM AND DATEADD(1 DAY TO :I$DATE_TO)
    JOIN CJ2_MARK_TYPE MT ON MT.MARK_TYPE_ID = M.MARK_TYPE_ID
    LEFT JOIN LISTVALS LV ON LV.LISTVAL_ID = M.REASON_ID
    LEFT JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
    LEFT JOIN CJ2_JOURNAL_ACCESS(:I$USER_ID, J.OBJ_ID) A ON 1 = 1
    WHERE J.DATE_DEL IS NULL AND :V$CALLER_TYPE IN (2, 46, 7, 8, 179) AND (
      (J.GRADE_ID = :I$OBJ_ID AND :I$OPTION_ID IS NULL) OR
      ((J.STAGE_INDEX = :V$STAGE_ID1 OR J.STAGE_INDEX = :V$STAGE_ID2 OR J.STAGE_INDEX = :V$STAGE_ID3 OR J.STAGE_INDEX = :V$STAGE_ID4 OR J.STAGE_INDEX = :V$STAGE_ID5) AND :I$OPTION_ID IS NULL) OR
      J.OBJ_ID = :I$OPTION_ID OR
      :I$OBJ_ID IS NULL
    ) AND A.ACCESS_LEVEL > 0
    ORDER BY 5
    INTO :V$LESSON_ID, :V$CONTROL_ID, :V$DATE, :V$OBJ_ID, :V$DATE2, :V$USER_ADD, :V$USER_DEL, :V$S2, :V$S3, :V$GRADE_ID, :V$SUBJECT_ID, :V$STUDENT_ID,
      :V$MARK_TYPE_ID
  DO
  BEGIN

    VAL = '<tr class="v">';
    V$T = (SELECT SUBSTRING(VAL FROM 12) FROM DATE2ISO(:V$DATE2));
    VAL = VAL || '<td>' || (SELECT RESULT FROM DATE2STR(:V$DATE2)) || ' ' || V$T || '</td>';
    VAL = VAL || '<td>' || (SELECT RESULT FROM DATE2STR(:V$DATE)) || '</td>';

    VAL = VAL || '<td>';
      IF(V$OU_LICENCE_TYPE = 'U') THEN
      BEGIN
        SELECT :VAL || C1.CAPTION || ' - '  || P.NAME_FULL
        FROM LINKS LPG
        LEFT JOIN OBJECT_CAPTION_GET(LPG.OBJ_ID) C1 ON 1 = 1
        LEFT JOIN UT_PERSON_DESC(LPG.PARENT_ID, :I$ZONE, 1) P ON 1 = 1
        WHERE LPG.OBJ_ID = :V$GRADE_ID AND LPG.PARENT_TYPE_ID = 242 AND LPG.DATE_DEL IS NULL
        INTO :VAL;
      END
      ELSE
      BEGIN
        VAL = VAL || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$GRADE_ID));
      END
    VAL = VAL || '</td>';

    IF(V$OU_LICENCE_TYPE IN ('O', 'C', 'S')) THEN
    BEGIN
      IF(V$SUBJECT_ID IS NULL) THEN VAL = VAL || '<td></td>';
      ELSE VAL = VAL || '<td>' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$SUBJECT_ID)) || '</td>';
    END
    VAL = VAL || '<td>' || (SELECT NAME_FULL FROM UT_PERSON_DESC(:V$STUDENT_ID, :I$ZONE, 1)) || ' </td>';
    VAL = VAL || '<td>' || V$S2 || '</td>';

    V$S1 = NULL;
    SELECT IIF(U.OBJ_ID IS NULL, U.USER_NAME, P.NAME_FULL)
    FROM USERS U
    LEFT JOIN UT_PERSON_DESC(U.OBJ_ID, :I$ZONE, 1) P ON 1 = 1
    WHERE U.USER_ID = :V$USER_ADD
    INTO :V$S1;
    VAL = VAL || '<td>' || COALESCE(V$S1, '-') || '</td>';

    VAL = VAL || '<td>';
      V$S2 = NULL;
      SELECT FIRST 1 MT.MARK_NAME
      FROM CJ2_MARK M
      JOIN CJ2_MARK_TYPE MT ON MT.MARK_TYPE_ID = M.MARK_TYPE_ID
      WHERE M.CONTROL_ID = :V$CONTROL_ID AND M.STUDENT_ID = :V$STUDENT_ID AND M.MARK_ID > :V$OBJ_ID AND (
        (:V$MARK_TYPE_ID = -1 AND M.MARK_TYPE_ID = -1) OR
        (:V$MARK_TYPE_ID BETWEEN 1 AND 99 AND M.MARK_TYPE_ID BETWEEN 1 AND 99) OR
        (:V$MARK_TYPE_ID >= 100 AND M.MARK_TYPE_ID >= 100)
      )
      INTO :V$S2;
      VAL = VAL || COALESCE(:V$S2, '-');
    VAL = VAL || '</td>';

    V$S1 = NULL;
    SELECT IIF(U.OBJ_ID IS NULL, U.USER_NAME, P.NAME_FULL)
    FROM USERS U
    LEFT JOIN UT_PERSON_DESC(U.OBJ_ID, :I$ZONE, 1) P ON 1 = 1
    WHERE U.USER_ID = :V$USER_DEL
    INTO :V$S1;
    VAL = VAL || '<td>' || COALESCE(V$S1, '-') || '</td>';

    VAL = VAL || '<td>' || V$S3 || '</td>';
    VAL = VAL || '</tr>';

    SUSPEND;

  END

  -- Для классов выбираем весь список вложенных учебных коллективов и далее отчет по каждому
  FOR
    SELECT L.OBJ_ID, C.CONTROL_ID, L.LESSON_DATE, M.MARK_ID, M.DATE_DEL, M.USER_ID, M.USER_DEL,
      MT.MARK_NAME, COALESCE(R.VAL, '-'), J.GRADE_ID, J.SUBJECT_ID, M.STUDENT_ID, M.MARK_TYPE_ID
    FROM CJ2_CLASS_JOURNALS(:I$OBJ_ID, :I$DATE_FROM, :I$DATE_TO, :I$USER_ID) J
    JOIN CJ2_JOURNAL_LESSONS L ON L.CJ_ID = J.CJ_ID AND L.DATE_DEL IS NULL
    JOIN CJ2_CONTROL C ON C.LESSON_ID = L.OBJ_ID AND C.DATE_DEL IS NULL
    JOIN CJ2_MARK M ON M.CONTROL_ID = C.CONTROL_ID AND M.DATE_DEL IS NOT NULL AND M.DATE_DEL BETWEEN :I$DATE_FROM AND DATEADD(1 DAY TO :I$DATE_TO)
    JOIN CJ2_MARK_TYPE MT ON MT.MARK_TYPE_ID = M.MARK_TYPE_ID
    LEFT JOIN LISTVALS LV ON LV.LISTVAL_ID = M.REASON_ID
    LEFT JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
    WHERE :V$CALLER_TYPE = 9
    UNION
    SELECT F.OBJ_ID, F.OBJ_ID, F.FINAL_DATE, M.MARK_ID, M.DATE_DEL, M.USER_ID, M.USER_DEL,
      MT.MARK_NAME, COALESCE(R.VAL, '-'), J.GRADE_ID, J.SUBJECT_ID, M.STUDENT_ID, M.MARK_TYPE_ID
    FROM CJ2_CLASS_JOURNALS(:I$OBJ_ID, :I$DATE_FROM, :I$DATE_TO, :I$USER_ID) J
    JOIN CJ2_JOURNAL_FINALS F ON F.CJ_ID = J.CJ_ID AND F.DATE_DEL IS NULL
    JOIN CJ2_MARK M ON M.FINAL_ID = F.OBJ_ID AND M.DATE_DEL IS NOT NULL AND M.DATE_DEL BETWEEN :I$DATE_FROM AND DATEADD(1 DAY TO :I$DATE_TO)
    JOIN CJ2_MARK_TYPE MT ON MT.MARK_TYPE_ID = M.MARK_TYPE_ID
    LEFT JOIN LISTVALS LV ON LV.LISTVAL_ID = M.REASON_ID
    LEFT JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
    WHERE :V$CALLER_TYPE = 9
    ORDER BY 5
    INTO :V$LESSON_ID, :V$CONTROL_ID, :V$DATE, :V$OBJ_ID, :V$DATE2, :V$USER_ADD, :V$USER_DEL, :V$S2, :V$S3, :V$GRADE_ID, :V$SUBJECT_ID, :V$STUDENT_ID,
      :V$MARK_TYPE_ID
  DO
  BEGIN

    VAL = '<tr class="v">';
    V$T = (SELECT SUBSTRING(VAL FROM 12) FROM DATE2ISO(:V$DATE2));
    VAL = VAL || '<td>' || (SELECT RESULT FROM DATE2STR(:V$DATE2)) || ' ' || V$T || '</td>';
    VAL = VAL || '<td>' || (SELECT RESULT FROM DATE2STR(:V$DATE)) || '</td>';

    VAL = VAL || '<td>';
      IF(V$OU_LICENCE_TYPE = 'U') THEN
      BEGIN
        SELECT :VAL || C1.CAPTION || ' - '  || P.NAME_FULL
        FROM LINKS LPG
        LEFT JOIN OBJECT_CAPTION_GET(LPG.OBJ_ID) C1 ON 1 = 1
        LEFT JOIN UT_PERSON_DESC(LPG.PARENT_ID, :I$ZONE, 1) P ON 1 = 1
        WHERE LPG.OBJ_ID = :V$GRADE_ID AND LPG.PARENT_TYPE_ID = 242 AND LPG.DATE_DEL IS NULL
        INTO :VAL;
      END
      ELSE
      BEGIN
        VAL = VAL || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$GRADE_ID));
      END
    VAL = VAL || '</td>';

    IF(V$OU_LICENCE_TYPE IN ('O', 'C', 'S')) THEN
    BEGIN
      IF(V$SUBJECT_ID IS NULL) THEN VAL = VAL || '<td></td>';
      ELSE VAL = VAL || '<td>' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$SUBJECT_ID)) || '</td>';
    END
    VAL = VAL || '<td>' || (SELECT NAME_FULL FROM UT_PERSON_DESC(:V$STUDENT_ID, :I$ZONE, 1)) || ' </td>';
    VAL = VAL || '<td>' || V$S2 || '</td>';

    V$S1 = NULL;
    SELECT IIF(U.OBJ_ID IS NULL, U.USER_NAME, P.NAME_FULL)
    FROM USERS U
    LEFT JOIN UT_PERSON_DESC(U.OBJ_ID, :I$ZONE, 1) P ON 1 = 1
    WHERE U.USER_ID = :V$USER_ADD
    INTO :V$S1;
    VAL = VAL || '<td>' || COALESCE(V$S1, '-') || '</td>';

    VAL = VAL || '<td>';
      V$S2 = NULL;
      SELECT FIRST 1 MT.MARK_NAME
      FROM CJ2_MARK M
      JOIN CJ2_MARK_TYPE MT ON MT.MARK_TYPE_ID = M.MARK_TYPE_ID
      WHERE M.CONTROL_ID = :V$CONTROL_ID AND M.STUDENT_ID = :V$STUDENT_ID AND M.MARK_ID > :V$OBJ_ID AND (
        (:V$MARK_TYPE_ID = -1 AND M.MARK_TYPE_ID = -1) OR
        (:V$MARK_TYPE_ID BETWEEN 1 AND 99 AND M.MARK_TYPE_ID BETWEEN 1 AND 99) OR
        (:V$MARK_TYPE_ID >= 100 AND M.MARK_TYPE_ID >= 100)
      )
      INTO :V$S2;
      VAL = VAL || COALESCE(:V$S2, '-');
    VAL = VAL || '</td>';

    V$S1 = NULL;
    SELECT IIF(U.OBJ_ID IS NULL, U.USER_NAME, P.NAME_FULL)
    FROM USERS U
    LEFT JOIN  UT_PERSON_DESC(U.OBJ_ID, :I$ZONE, 1) P ON 1 = 1
    WHERE U.USER_ID = :V$USER_DEL
    INTO :V$S1;
    VAL = VAL || '<td>' || COALESCE(V$S1, '-') || '</td>';

    VAL = VAL || '<td>' || V$S3 || '</td>';
    VAL = VAL || '</tr>';

    SUSPEND;

  END

  -- Для учеников смотрим все отметки
  FOR
    SELECT L.OBJ_ID, C.CONTROL_ID, L.LESSON_DATE, M.MARK_ID, M.DATE_DEL, M.USER_ID, M.USER_DEL,
      MT.MARK_NAME, COALESCE(R.VAL, '-'), J.GRADE_ID, J.SUBJECT_ID, M.STUDENT_ID, M.MARK_TYPE_ID
    FROM CJ2_MARK M 
    JOIN CJ2_CONTROL C ON C.CONTROL_ID = M.CONTROL_ID AND C.DATE_DEL IS NULL
    JOIN CJ2_JOURNAL_LESSONS L ON L.OBJ_ID = C.LESSON_ID AND L.DATE_DEL IS NULL
    JOIN CJ2_JOURNAL J ON J.OBJ_ID = L.CJ_ID AND J.DATE_DEL IS NULL
    JOIN CJ2_MARK_TYPE MT ON MT.MARK_TYPE_ID = M.MARK_TYPE_ID
    LEFT JOIN LISTVALS LV ON LV.LISTVAL_ID = M.REASON_ID
    LEFT JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
    LEFT JOIN CJ2_JOURNAL_ACCESS(:I$USER_ID, J.OBJ_ID) A ON 1 = 1
    WHERE M.DATE_DEL IS NOT NULL AND M.DATE_DEL BETWEEN :I$DATE_FROM AND DATEADD(1 DAY TO :I$DATE_TO) AND M.STUDENT_ID = :I$OBJ_ID AND :V$CALLER_TYPE = 10
      AND A.ACCESS_LEVEL > 0
    UNION
    SELECT F.OBJ_ID, F.OBJ_ID, F.FINAL_DATE, M.MARK_ID, M.DATE_DEL, M.USER_ID, M.USER_DEL,
      MT.MARK_NAME, COALESCE(R.VAL, '-'), J.GRADE_ID, J.SUBJECT_ID, M.STUDENT_ID, M.MARK_TYPE_ID
    FROM CJ2_MARK M 
    JOIN CJ2_JOURNAL_FINALS F ON F.OBJ_ID = M.FINAL_ID AND F.DATE_DEL IS NULL
    JOIN CJ2_JOURNAL J ON J.OBJ_ID = F.CJ_ID AND J.DATE_DEL IS NULL
    JOIN CJ2_MARK_TYPE MT ON MT.MARK_TYPE_ID = M.MARK_TYPE_ID
    LEFT JOIN LISTVALS LV ON LV.LISTVAL_ID = M.REASON_ID
    LEFT JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
    LEFT JOIN CJ2_JOURNAL_ACCESS(:I$USER_ID, J.OBJ_ID) A ON 1 = 1
    WHERE M.DATE_DEL IS NOT NULL AND M.DATE_DEL BETWEEN :I$DATE_FROM AND DATEADD(1 DAY TO :I$DATE_TO) AND M.STUDENT_ID = :I$OBJ_ID AND :V$CALLER_TYPE = 10
      AND A.ACCESS_LEVEL > 0
    ORDER BY 5
    INTO :V$LESSON_ID, :V$CONTROL_ID, :V$DATE, :V$OBJ_ID, :V$DATE2, :V$USER_ADD, :V$USER_DEL, :V$S2, :V$S3, :V$GRADE_ID, :V$SUBJECT_ID, :V$STUDENT_ID,
      :V$MARK_TYPE_ID
  DO
  BEGIN

    VAL = '<tr class="v">';
    V$T = (SELECT SUBSTRING(VAL FROM 12) FROM DATE2ISO(:V$DATE2));
    VAL = VAL || '<td>' || (SELECT RESULT FROM DATE2STR(:V$DATE2)) || ' ' || V$T || '</td>';
    VAL = VAL || '<td>' || (SELECT RESULT FROM DATE2STR(:V$DATE)) || '</td>';

    VAL = VAL || '<td>';
      IF(V$OU_LICENCE_TYPE = 'U') THEN
      BEGIN
        SELECT :VAL || C1.CAPTION || ' - '  || P.NAME_FULL
        FROM LINKS LPG
        LEFT JOIN OBJECT_CAPTION_GET(LPG.OBJ_ID) C1 ON 1 = 1
        LEFT JOIN UT_PERSON_DESC(LPG.PARENT_ID, :I$ZONE, 1) P ON 1 = 1
        WHERE LPG.OBJ_ID = :V$GRADE_ID AND LPG.PARENT_TYPE_ID = 242 AND LPG.DATE_DEL IS NULL
        INTO :VAL;
      END
      ELSE
      BEGIN
        VAL = VAL || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$GRADE_ID));
      END
    VAL = VAL || '</td>';

    IF(V$OU_LICENCE_TYPE IN ('O', 'C', 'S')) THEN
    BEGIN
      IF(V$SUBJECT_ID IS NULL) THEN VAL = VAL || '<td></td>';
      ELSE VAL = VAL || '<td>' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$SUBJECT_ID)) || '</td>';
    END
    VAL = VAL || '<td>' || (SELECT NAME_FULL FROM UT_PERSON_DESC(:V$STUDENT_ID, :I$ZONE, 1)) || ' </td>';
    VAL = VAL || '<td>' || V$S2 || '</td>';

    V$S1 = NULL;
    SELECT IIF(U.OBJ_ID IS NULL, U.USER_NAME, P.NAME_FULL)
    FROM USERS U
    LEFT JOIN UT_PERSON_DESC(U.OBJ_ID, :I$ZONE, 1) P ON 1 = 1
    WHERE U.USER_ID = :V$USER_ADD
    INTO :V$S1;
    VAL = VAL || '<td>' || COALESCE(V$S1, '-') || '</td>';

    VAL = VAL || '<td>';
      V$S2 = NULL;
      SELECT FIRST 1 MT.MARK_NAME
      FROM CJ2_MARK M
      JOIN CJ2_MARK_TYPE MT ON MT.MARK_TYPE_ID = M.MARK_TYPE_ID
      WHERE M.CONTROL_ID = :V$CONTROL_ID AND M.STUDENT_ID = :V$STUDENT_ID AND M.MARK_ID > :V$OBJ_ID AND (
        (:V$MARK_TYPE_ID = -1 AND M.MARK_TYPE_ID = -1) OR
        (:V$MARK_TYPE_ID BETWEEN 1 AND 99 AND M.MARK_TYPE_ID BETWEEN 1 AND 99) OR
        (:V$MARK_TYPE_ID >= 100 AND M.MARK_TYPE_ID >= 100)
      )
      INTO :V$S2;
      VAL = VAL || COALESCE(:V$S2, '-');
    VAL = VAL || '</td>';

    V$S1 = NULL;
    SELECT IIF(U.OBJ_ID IS NULL, U.USER_NAME, P.NAME_FULL)
    FROM USERS U
    LEFT JOIN UT_PERSON_DESC(U.OBJ_ID, :I$ZONE, 1) P ON 1 = 1
    WHERE U.USER_ID = :V$USER_DEL
    INTO :V$S1;
    VAL = VAL || '<td>' || COALESCE(V$S1, '-') || '</td>';

    VAL = VAL || '<td>' || V$S3 || '</td>';
    VAL = VAL || '</tr>';

    SUSPEND;

  END

  VAL = '</table></body></html>';
  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_REPORT_NX2 (
    I$USER_ID VARCHAR(40),
    I$DATE_FROM DATE,
    I$DATE_TO DATE,
    I$PARENT_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$OPTION_ID BIGINT,
    I$OPTIONS VARCHAR(1000),
    I$ZONE SMALLINT = 0)
RETURNS (
    VAL VARCHAR(4000))
AS
declare variable V$CALLER_TYPE bigint;
declare variable V$USER_TYPE smallint;
declare variable V$CJ_ID bigint;
declare variable V$COST double precision;
declare variable V$S1 varchar(400);
declare variable V$S2 varchar(400);
declare variable V$DATE date;
declare variable V$OBJ_ID bigint;
declare variable N90 integer;
declare variable N91 integer;
declare variable N92 integer;
declare variable N93 integer;
declare variable N94 integer;
declare variable TN90 integer;
declare variable TN91 integer;
declare variable TN92 integer;
declare variable TN93 integer;
declare variable TN94 integer;
declare variable V$OU_LICENCE_TYPE char(1);
declare variable V$ACCESS smallint;
begin

  -- Школа, коллектив, персона
  SELECT TYPE_ID FROM OBJECTS WHERE OBJ_ID = :I$OBJ_ID INTO :V$CALLER_TYPE;
  SELECT STATUS FROM OU_LICENCE_TYPE INTO :V$OU_LICENCE_TYPE;

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;
  SELECT USER_TYPE FROM USERS WHERE USER_ID = :I$USER_ID INTO :V$USER_TYPE;

  VAL = '<!DOCTYPE html>';
  VAL = VAL || '<html lang="ru">';
  VAL = VAL || '<head>';
  VAL = VAL || '<meta charset="utf-8" />';
  VAL = VAL || '<style>';
  VAL = VAL || 'html { font-family: Tahoma, Verdana, Arial;';
  VAL = VAL || 'font-size: 10pt; ';
  VAL = VAL || '} ';
  VAL = VAL || '</style>';

  VAL = VAL || '</head>';
  VAL = VAL || '<body>';
  SUSPEND;

  -- Заголовок отчета
  IF(V$OU_LICENCE_TYPE = 'O') THEN VAL = '<div class="title1">Пропуски и опоздания</div>';
  ELSE VAL = '<div class="title1">Посещение занятий</div>';

  VAL = VAL || '<div class="title2">';
  IF (:V$CALLER_TYPE = 10) THEN VAL = VAL || (SELECT NAME_FULL FROM UT_PERSON_DESC(:I$OBJ_ID, :I$ZONE, 1));        -- обущающийся
                           ELSE VAL = VAL || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$OBJ_ID));
  VAL = VAL || '</div>';
  IF(I$OPTION_ID IS NOT NULL) THEN
  BEGIN
    V$S1 = '';
    SELECT C.CAPTION
    FROM CJ2_JOURNAL J
    LEFT JOIN OBJECT_CAPTION_GET(J.SUBJECT_ID) C ON 1 = 1
    WHERE J.OBJ_ID = :I$OPTION_ID
    INTO :V$S1;
    VAL = VAL || '<div class="title2">В разрезе: ' || COALESCE(V$S1, '???') || '</div>';
  END

  V$S1 = (SELECT RESULT FROM DATE2STR(:I$DATE_FROM));
  V$S2 = (SELECT RESULT FROM DATE2STR(:I$DATE_TO));
  VAL = VAL || '<div class="title2">Период: ' || V$S1 || ' - ' || V$S2 || '</div>';

  -- Заголовок таблицы
  VAL = VAL || '<table class="table" cellspacing="0" cellpadding="0">';
  SUSPEND;

  -- Чистим временную таблицу и заполняем реальными датами
  DELETE FROM CJ_REPORT4_TEMP WHERE 1 = 1;

  -- Все берем без учета внеурочки
  -- Если уровень ОУ, то сумма по классам
  -- Если уровень класса, то список по ученикам
  -- Если уровень ученика, то список по предметам

  IF(V$CALLER_TYPE = 2 AND V$USER_TYPE NOT IN (1, 5, 6)) THEN
  BEGIN
      VAL = '<div style="padding: 10px; color: #fff; background: darkred; border-radius: 4px; margin-top: 20px; margin-bottom: 20px">';
      VAL = VAL || 'В разрезе организации отчет может строить только руководитель. Выберите конкретный учебный коллектив</div>';
      SUSPEND;
  END
  ELSE IF(V$CALLER_TYPE = 2 AND V$USER_TYPE IN (1, 5, 6)) THEN
  BEGIN
      FOR
          SELECT VAL
          FROM CJ2_REPORT_NX2_OU(:I$USER_ID, :I$DATE_FROM, :I$DATE_TO, :I$PARENT_ID, :I$OBJ_ID, :I$OPTION_ID, :I$OPTIONS, :I$ZONE)
          INTO :VAL
      DO
      BEGIN
          SUSPEND;
      END
  END
  ELSE IF(V$CALLER_TYPE = 10) THEN
  BEGIN
      -- Ученик, сечение по предметам

      FOR
          SELECT DISTINCT L.LESSON_DATE
          FROM CJ2_JOURNAL_LESSONS L
          JOIN CJ2_CONTROL C ON C.DATE_DEL IS NULL AND C.LESSON_ID = L.OBJ_ID AND C.CONTROL_TYPE_ID = 0
          JOIN CJ2_MARK M ON M.DATE_DEL IS NULL AND M.CONTROL_ID = C.CONTROL_ID AND M.MARK_TYPE_ID BETWEEN 90 AND 94 AND M.STUDENT_ID = :I$OBJ_ID
          JOIN CJ2_JOURNAL J ON J.OBJ_ID = L.CJ_ID AND J.JOURNAL_TYPE = 0
          --LEFT JOIN CJ2_JOURNAL_ACCESS(:I$USER_ID, L.CJ_ID) A ON 1 = 1
          JOIN CJ2_JOURNAL_AUTOUSERS A ON A.CJ_ID = J.OBJ_ID AND A.USER_ID = :I$USER_ID AND A.DATE_DEL IS NULL AND A.ACCESS > 0
          WHERE L.DATE_DEL IS NULL AND L.IS_COMPLETED > 0 AND L.LESSON_DATE BETWEEN :I$DATE_FROM AND :I$DATE_TO
          INTO :V$DATE
      DO
      BEGIN
          INSERT INTO CJ_REPORT4_TEMP (DATE_ID, CLASS_ID) VALUES (:V$DATE, 0);
      END

      -- Таблица: класс, даты, итоги по видам пропусков
      VAL = '<tr class="thd">';
      VAL = VAL || '<td class="sortable text">Предмет</td>';
      SUSPEND;
      FOR SELECT DATE_ID FROM CJ_REPORT4_TEMP ORDER BY 1 INTO :V$DATE DO
      BEGIN
          VAL = '<td>' || (SELECT RESULT FROM DATE2STR(:V$DATE, 2)) || '</td>';
          SUSPEND;
      END
      VAL = '<td class="t t1 sortable value">УВ</td>';
      VAL = VAL || '<td class="t sortable value">НУВ</td>';
      VAL = VAL || '<td class="t sortable value">БОЛ</td>';
      VAL = VAL || '<td class="t sortable value">НЕИЗВ</td>';
      VAL = VAL || '<td class="t sortable value">&sum;&nbsp;Пропуск</td>';
      VAL = VAL || '<td class="t sortable value">Опозд</td>';
      VAL = VAL || '</tr>';
      SUSPEND;

      FOR
          SELECT DISTINCT J.OBJ_ID, IIF(J.SUBJECT_ID IS NULL, J.JOURNAL_NAME, CC.CAPTION), J.OBJ_ID
          FROM CJ2_JOURNAL_LESSONS L
          JOIN CJ2_CONTROL C ON C.DATE_DEL IS NULL AND C.LESSON_ID = L.OBJ_ID AND C.CONTROL_TYPE_ID = 0
          JOIN CJ2_MARK M ON M.DATE_DEL IS NULL AND M.CONTROL_ID = C.CONTROL_ID AND M.MARK_TYPE_ID BETWEEN 90 AND 94 AND M.STUDENT_ID = :I$OBJ_ID
          JOIN CJ2_JOURNAL J ON J.OBJ_ID = L.CJ_ID AND J.DATE_DEL IS NULL AND J.JOURNAL_TYPE = 0
          JOIN CJ2_JOURNAL_AUTOUSERS A ON A.CJ_ID = J.OBJ_ID AND A.USER_ID = :I$USER_ID AND A.DATE_DEL IS NULL AND A.ACCESS > 0
          --LEFT JOIN CJ2_JOURNAL_ACCESS(:I$USER_ID, J.OBJ_ID) A ON 1 = 1
          LEFT JOIN OBJECT_CAPTION_GET(J.SUBJECT_ID) CC ON 1 = 1
          WHERE L.DATE_DEL IS NULL AND L.IS_COMPLETED > 0 AND L.LESSON_DATE BETWEEN :I$DATE_FROM AND :I$DATE_TO
          ORDER BY 2
          INTO :V$OBJ_ID, :V$S1, :V$CJ_ID
      DO
      BEGIN
          VAL = '<tr class="v">';
          VAL = VAL || '<td><div class="target journal" data-target="' || V$CJ_ID || '">' || V$S1 || '</div></td>';
          SUSPEND;
          TN90 = 0; TN91 = 0; TN92 = 0; TN93 = 0; TN94 = 0;
          FOR SELECT DATE_ID FROM CJ_REPORT4_TEMP ORDER BY 1 INTO :V$DATE DO
          BEGIN
              SELECT COUNT(*)
              FROM CJ2_JOURNAL_LESSONS L
              JOIN CJ2_CONTROL C ON C.DATE_DEL IS NULL AND C.LESSON_ID = L.OBJ_ID AND C.CONTROL_TYPE_ID = 0
              JOIN CJ2_MARK M ON M.DATE_DEL IS NULL AND M.CONTROL_ID = C.CONTROL_ID AND M.MARK_TYPE_ID = 90 AND M.STUDENT_ID = :I$OBJ_ID
              JOIN CJ2_JOURNAL J ON J.OBJ_ID = L.CJ_ID AND J.DATE_DEL IS NULL AND J.OBJ_ID = :V$OBJ_ID
              JOIN CJ2_JOURNAL_AUTOUSERS A ON A.CJ_ID = J.OBJ_ID AND A.USER_ID = :I$USER_ID AND A.DATE_DEL IS NULL AND A.ACCESS > 0
              --LEFT JOIN CJ2_JOURNAL_ACCESS(:I$USER_ID, J.OBJ_ID) A ON 1 = 1
              WHERE L.DATE_DEL IS NULL AND L.IS_COMPLETED > 0 AND L.LESSON_DATE = :V$DATE
              INTO :N90;

              SELECT COUNT(*)
              FROM CJ2_JOURNAL_LESSONS L
              JOIN CJ2_CONTROL C ON C.DATE_DEL IS NULL AND C.LESSON_ID = L.OBJ_ID AND C.CONTROL_TYPE_ID = 0
              JOIN CJ2_MARK M ON M.DATE_DEL IS NULL AND M.CONTROL_ID = C.CONTROL_ID AND M.MARK_TYPE_ID = 91 AND M.STUDENT_ID = :I$OBJ_ID
              JOIN CJ2_JOURNAL J ON J.OBJ_ID = L.CJ_ID AND J.DATE_DEL IS NULL AND J.OBJ_ID = :V$OBJ_ID
              --LEFT JOIN CJ2_JOURNAL_ACCESS(:I$USER_ID, J.OBJ_ID) A ON 1 = 1
              JOIN CJ2_JOURNAL_AUTOUSERS A ON A.CJ_ID = J.OBJ_ID AND A.USER_ID = :I$USER_ID AND A.DATE_DEL IS NULL AND A.ACCESS > 0
              WHERE L.DATE_DEL IS NULL AND L.IS_COMPLETED > 0 AND L.LESSON_DATE = :V$DATE
              INTO :N91;

              SELECT COUNT(*)
              FROM CJ2_JOURNAL_LESSONS L
              JOIN CJ2_CONTROL C ON C.DATE_DEL IS NULL AND C.LESSON_ID = L.OBJ_ID AND C.CONTROL_TYPE_ID = 0
              JOIN CJ2_MARK M ON M.DATE_DEL IS NULL AND M.CONTROL_ID = C.CONTROL_ID AND M.MARK_TYPE_ID = 92 AND M.STUDENT_ID = :I$OBJ_ID
              JOIN CJ2_JOURNAL J ON J.OBJ_ID = L.CJ_ID AND J.DATE_DEL IS NULL AND J.OBJ_ID = :V$OBJ_ID
              --LEFT JOIN CJ2_JOURNAL_ACCESS(:I$USER_ID, J.OBJ_ID) A ON 1 = 1
              JOIN CJ2_JOURNAL_AUTOUSERS A ON A.CJ_ID = J.OBJ_ID AND A.USER_ID = :I$USER_ID AND A.DATE_DEL IS NULL AND A.ACCESS > 0
              WHERE L.DATE_DEL IS NULL AND L.IS_COMPLETED > 0 AND L.LESSON_DATE = :V$DATE
              INTO :N92;

              SELECT COUNT(*)
              FROM CJ2_JOURNAL_LESSONS L
              JOIN CJ2_CONTROL C ON C.DATE_DEL IS NULL AND C.LESSON_ID = L.OBJ_ID AND C.CONTROL_TYPE_ID = 0
              JOIN CJ2_MARK M ON M.DATE_DEL IS NULL AND M.CONTROL_ID = C.CONTROL_ID AND M.MARK_TYPE_ID = 93 AND M.STUDENT_ID = :I$OBJ_ID
              JOIN CJ2_JOURNAL J ON J.OBJ_ID = L.CJ_ID AND J.DATE_DEL IS NULL AND J.OBJ_ID = :V$OBJ_ID
              --LEFT JOIN CJ2_JOURNAL_ACCESS(:I$USER_ID, J.OBJ_ID) A ON 1 = 1
              JOIN CJ2_JOURNAL_AUTOUSERS A ON A.CJ_ID = J.OBJ_ID AND A.USER_ID = :I$USER_ID AND A.DATE_DEL IS NULL AND A.ACCESS > 0
              WHERE L.DATE_DEL IS NULL AND L.IS_COMPLETED > 0 AND L.LESSON_DATE = :V$DATE
              INTO :N93;

              SELECT COUNT(*)
              FROM CJ2_JOURNAL_LESSONS L
              JOIN CJ2_CONTROL C ON C.DATE_DEL IS NULL AND C.LESSON_ID = L.OBJ_ID AND C.CONTROL_TYPE_ID = 0
              JOIN CJ2_MARK M ON M.DATE_DEL IS NULL AND M.CONTROL_ID = C.CONTROL_ID AND M.MARK_TYPE_ID = 94 AND M.STUDENT_ID = :I$OBJ_ID
              JOIN CJ2_JOURNAL J ON J.OBJ_ID = L.CJ_ID AND J.DATE_DEL IS NULL AND J.OBJ_ID = :V$OBJ_ID
              --LEFT JOIN CJ2_JOURNAL_ACCESS(:I$USER_ID, J.OBJ_ID) A ON 1 = 1
              JOIN CJ2_JOURNAL_AUTOUSERS A ON A.CJ_ID = J.OBJ_ID AND A.USER_ID = :I$USER_ID AND A.DATE_DEL IS NULL AND A.ACCESS > 0
              WHERE L.DATE_DEL IS NULL AND L.IS_COMPLETED > 0 AND L.LESSON_DATE = :V$DATE
              INTO :N94;

              VAL = '<td>' || (N90 + N91 + N92 + N93 + N94) || '</td>';
              SUSPEND;
              TN90 = TN90 + N90;
              TN91 = TN91 + N91;
              TN92 = TN92 + N92;
              TN93 = TN93 + N93;
              TN94 = TN94 + N94;
          END
          VAL = '<td class="t t1">' || TN93 || '</td>';
          VAL = VAL || '<td class="t">' || TN94 || '</td>';
          VAL = VAL || '<td class="t">' || TN92 || '</td>';
          VAL = VAL || '<td class="t">' || TN91 || '</td>';
          VAL = VAL || '<td class="t">' || (TN91 + TN92 + TN93 + TN94) || '</td>';
          VAL = VAL || '<td class="t">' || TN90 || '</td>';
          VAL = VAL || '</tr>';
          SUSPEND;
      END

      -- Итоги
      -- !!! тут надо дофильтровывать, что ученик был в группе на нужные даты
      VAL = '<tr class="v total">';
      VAL = VAL || '<td>Всего</td>';
      SUSPEND;
      TN90 = 0; TN91 = 0; TN92 = 0; TN93 = 0; TN94 = 0;
      FOR SELECT DATE_ID FROM CJ_REPORT4_TEMP ORDER BY 1 INTO :V$DATE DO
      BEGIN
          SELECT COUNT(*)
          FROM CJ2_JOURNAL_LESSONS L
          JOIN CJ2_CONTROL C ON C.DATE_DEL IS NULL AND C.LESSON_ID = L.OBJ_ID AND C.CONTROL_TYPE_ID = 0
          JOIN CJ2_MARK M ON M.DATE_DEL IS NULL AND M.CONTROL_ID = C.CONTROL_ID AND M.MARK_TYPE_ID = 90 AND M.STUDENT_ID = :I$OBJ_ID
          --LEFT JOIN CJ2_JOURNAL_ACCESS(:I$USER_ID, L.CJ_ID) A ON 1 = 1
          JOIN CJ2_JOURNAL J ON J.OBJ_ID = L.CJ_ID AND J.JOURNAL_TYPE = 0
          JOIN CJ2_JOURNAL_AUTOUSERS A ON A.CJ_ID = J.OBJ_ID AND A.USER_ID = :I$USER_ID AND A.DATE_DEL IS NULL AND A.ACCESS > 0
          WHERE L.DATE_DEL IS NULL AND L.IS_COMPLETED > 0 AND L.LESSON_DATE = :V$DATE
          INTO :N90;

          SELECT COUNT(*)
          FROM CJ2_JOURNAL_LESSONS L
          JOIN CJ2_CONTROL C ON C.DATE_DEL IS NULL AND C.LESSON_ID = L.OBJ_ID AND C.CONTROL_TYPE_ID = 0
          JOIN CJ2_MARK M ON M.DATE_DEL IS NULL AND M.CONTROL_ID = C.CONTROL_ID AND M.MARK_TYPE_ID = 91 AND M.STUDENT_ID = :I$OBJ_ID
          --LEFT JOIN CJ2_JOURNAL_ACCESS(:I$USER_ID, L.CJ_ID) A ON 1 = 1
          JOIN CJ2_JOURNAL J ON J.OBJ_ID = L.CJ_ID AND J.JOURNAL_TYPE = 0
          JOIN CJ2_JOURNAL_AUTOUSERS A ON A.CJ_ID = J.OBJ_ID AND A.USER_ID = :I$USER_ID AND A.DATE_DEL IS NULL AND A.ACCESS > 0
          WHERE L.DATE_DEL IS NULL AND L.IS_COMPLETED > 0 AND L.LESSON_DATE = :V$DATE
          INTO :N91;

          SELECT COUNT(*)
          FROM CJ2_JOURNAL_LESSONS L
          JOIN CJ2_CONTROL C ON C.DATE_DEL IS NULL AND C.LESSON_ID = L.OBJ_ID AND C.CONTROL_TYPE_ID = 0
          JOIN CJ2_MARK M ON M.DATE_DEL IS NULL AND M.CONTROL_ID = C.CONTROL_ID AND M.MARK_TYPE_ID = 92 AND M.STUDENT_ID = :I$OBJ_ID
          --LEFT JOIN CJ2_JOURNAL_ACCESS(:I$USER_ID, L.CJ_ID) A ON 1 = 1
          JOIN CJ2_JOURNAL J ON J.OBJ_ID = L.CJ_ID AND J.JOURNAL_TYPE = 0
          JOIN CJ2_JOURNAL_AUTOUSERS A ON A.CJ_ID = J.OBJ_ID AND A.USER_ID = :I$USER_ID AND A.DATE_DEL IS NULL AND A.ACCESS > 0
          WHERE L.DATE_DEL IS NULL AND L.IS_COMPLETED > 0 AND L.LESSON_DATE = :V$DATE
          INTO :N92;

          SELECT COUNT(*)
          FROM CJ2_JOURNAL_LESSONS L
          JOIN CJ2_CONTROL C ON C.DATE_DEL IS NULL AND C.LESSON_ID = L.OBJ_ID AND C.CONTROL_TYPE_ID = 0
          JOIN CJ2_MARK M ON M.DATE_DEL IS NULL AND M.CONTROL_ID = C.CONTROL_ID AND M.MARK_TYPE_ID = 93 AND M.STUDENT_ID = :I$OBJ_ID
          --LEFT JOIN CJ2_JOURNAL_ACCESS(:I$USER_ID, L.CJ_ID) A ON 1 = 1
          JOIN CJ2_JOURNAL J ON J.OBJ_ID = L.CJ_ID AND J.JOURNAL_TYPE = 0
          JOIN CJ2_JOURNAL_AUTOUSERS A ON A.CJ_ID = J.OBJ_ID AND A.USER_ID = :I$USER_ID AND A.DATE_DEL IS NULL AND A.ACCESS > 0
          WHERE L.DATE_DEL IS NULL AND L.IS_COMPLETED > 0 AND L.LESSON_DATE = :V$DATE
          INTO :N93;

          SELECT COUNT(*)
          FROM CJ2_JOURNAL_LESSONS L
          JOIN CJ2_CONTROL C ON C.DATE_DEL IS NULL AND C.LESSON_ID = L.OBJ_ID AND C.CONTROL_TYPE_ID = 0
          JOIN CJ2_MARK M ON M.DATE_DEL IS NULL AND M.CONTROL_ID = C.CONTROL_ID AND M.MARK_TYPE_ID = 94 AND M.STUDENT_ID = :I$OBJ_ID
          --LEFT JOIN CJ2_JOURNAL_ACCESS(:I$USER_ID, L.CJ_ID) A ON 1 = 1
          JOIN CJ2_JOURNAL J ON J.OBJ_ID = L.CJ_ID AND J.JOURNAL_TYPE = 0
          JOIN CJ2_JOURNAL_AUTOUSERS A ON A.CJ_ID = J.OBJ_ID AND A.USER_ID = :I$USER_ID AND A.DATE_DEL IS NULL AND A.ACCESS > 0
          WHERE L.DATE_DEL IS NULL AND L.IS_COMPLETED > 0 AND L.LESSON_DATE = :V$DATE
          INTO :N94;

          VAL = '<td>' || (N90 + N91 + N92 + N93 + N94) || '</td>';
          SUSPEND;
          TN90 = TN90 + N90;
          TN91 = TN91 + N91;
          TN92 = TN92 + N92;
          TN93 = TN93 + N93;
          TN94 = TN94 + N94;
      END
      VAL = '<td class="t t1">' || TN93 || '</td>';
      VAL = VAL || '<td class="t">' || TN94 || '</td>';
      VAL = VAL || '<td class="t">' || TN92 || '</td>';
      VAL = VAL || '<td class="t">' || TN91 || '</td>';
      VAL = VAL || '<td class="t">' || (TN91 + TN92 + TN93 + TN94) || '</td>';
      VAL = VAL || '<td class="t">' || TN90 || '</td>';
      VAL = VAL || '</tr>';
      SUSPEND;

  END
  ELSE
  BEGIN
      -- Группа, общий отчет аналогичен отчету по ОУ

      FOR
          SELECT DISTINCT L.LESSON_DATE
          FROM PERSON_MOVEMENTS M
          JOIN PERSON_MOVEMENTS M2 ON M2.DATE_DEL IS NULL AND M2.PERSON_ID = M.PERSON_ID AND M2.DATE_IN <= :I$DATE_TO AND (M2.DATE_OUT IS NULL OR M2.DATE_OUT >= :I$DATE_FROM)
          JOIN OBJECTS G ON G.OBJ_ID = M2.GROUP_ID AND G.TYPE_ID = 179
          JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.GRADE_ID = M2.GROUP_ID AND (:I$OPTION_ID IS NULL OR J.OBJ_ID = :I$OPTION_ID)
          JOIN CJ2_JOURNAL_LESSONS L ON L.DATE_DEL IS NULL AND L.CJ_ID = J.OBJ_ID AND L.IS_COMPLETED > 0 AND L.LESSON_DATE BETWEEN :I$DATE_FROM AND :I$DATE_TO
          JOIN CJ2_CONTROL C ON C.DATE_DEL IS NULL AND C.LESSON_ID = L.OBJ_ID AND C.CONTROL_TYPE_ID = 0
          JOIN CJ2_MARK CJM ON CJM.DATE_DEL IS NULL AND CJM.CONTROL_ID = C.CONTROL_ID AND CJM.MARK_TYPE_ID BETWEEN 90 AND 94
          --LEFT JOIN CJ2_JOURNAL_ACCESS(:I$USER_ID, J.OBJ_ID) A ON 1 = 1
          JOIN CJ2_JOURNAL_AUTOUSERS A ON A.CJ_ID = J.OBJ_ID AND A.USER_ID = :I$USER_ID AND A.DATE_DEL IS NULL AND A.ACCESS > 0
          WHERE M.DATE_DEL IS NULL AND M.GROUP_ID = :I$OBJ_ID AND M.DATE_IN <= :I$DATE_TO AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :I$DATE_FROM)
          INTO :V$DATE
      DO
      BEGIN
          INSERT INTO CJ_REPORT4_TEMP (DATE_ID, CLASS_ID) VALUES (:V$DATE, 0);
      END

      -- Таблица: класс, даты, итоги по видам пропусков
      VAL = '<tr class="thd">';
      VAL = VAL || '<td class="sortable text">Обучающийся</td>';
      SUSPEND;
      FOR SELECT DATE_ID FROM CJ_REPORT4_TEMP ORDER BY 1 INTO :V$DATE DO
      BEGIN
          VAL = '<td>' || (SELECT RESULT FROM DATE2STR(:V$DATE, 2)) || '</td>';
          SUSPEND;
      END
      VAL = '<td class="t t1 sortable value">УВ</td>';
      VAL = VAL || '<td class="t sortable value">НУВ</td>';
      VAL = VAL || '<td class="t sortable value">БОЛ</td>';
      VAL = VAL || '<td class="t sortable value">НЕИЗВ</td>';
      VAL = VAL || '<td class="t sortable value">&sum;&nbsp;Пропуск</td>';
      VAL = VAL || '<td class="t sortable value">Опозд</td>';
      VAL = VAL || '</tr>';
      SUSPEND;

      -- По действующим учащимся коллектива
      V$ACCESS = (SELECT ACCESS_LEVEL FROM CJ2_GRADE_ACCESS(:I$OBJ_ID, :I$USER_ID));

      FOR
          SELECT DISTINCT M.STUDENT_ID, P.NAME_FULL  --C.CAPTION , Redmine #1060
          FROM CJ2_MEMBER_MOVEMENTS(:I$OBJ_ID, :V$CALLER_TYPE, NULL) M
          JOIN UT_PERSON_DESC(M.STUDENT_ID, :I$ZONE, 1) P ON 1 = 1 --LEFT JOIN OBJECT_CAPTION_GET(M.STUDENT_ID, 23) C ON 1 = 1
          WHERE M.DATE_FROM <= :I$DATE_TO AND (M.DATE_TO IS NULL OR M.DATE_TO >= :I$DATE_FROM) AND :V$ACCESS > 0
          ORDER BY 2
          INTO :V$OBJ_ID, :V$S1
      DO
      BEGIN
          VAL = '<tr class="v">';
          VAL = VAL || '<td><div class="target student" data-target="' || V$OBJ_ID || '">' || V$S1 || '</div></td>';
          SUSPEND;
          TN90 = 0; TN91 = 0; TN92 = 0; TN93 = 0; TN94 = 0;
          FOR SELECT DATE_ID FROM CJ_REPORT4_TEMP ORDER BY 1 INTO :V$DATE DO
          BEGIN
              SELECT COUNT(*)
              FROM CJ2_JOURNAL_LESSONS L
              JOIN CJ2_JOURNAL J ON J.OBJ_ID = L.CJ_ID AND J.JOURNAL_TYPE = 0
              JOIN CJ2_CONTROL C ON C.DATE_DEL IS NULL AND C.LESSON_ID = L.OBJ_ID AND C.CONTROL_TYPE_ID = 0
              JOIN CJ2_MARK M ON M.DATE_DEL IS NULL AND M.CONTROL_ID = C.CONTROL_ID AND M.MARK_TYPE_ID = 90 AND M.STUDENT_ID = :V$OBJ_ID
              --LEFT JOIN CJ2_JOURNAL_ACCESS(:I$USER_ID, L.CJ_ID) A ON 1 = 1
              JOIN CJ2_JOURNAL_AUTOUSERS A ON A.CJ_ID = J.OBJ_ID AND A.USER_ID = :I$USER_ID AND A.DATE_DEL IS NULL AND A.ACCESS > 0
              WHERE L.DATE_DEL IS NULL AND L.IS_COMPLETED > 0 AND L.LESSON_DATE = :V$DATE AND (:I$OPTION_ID IS NULL OR L.CJ_ID = :I$OPTION_ID)
              INTO :N90;

              SELECT COUNT(*)
              FROM CJ2_JOURNAL_LESSONS L
              JOIN CJ2_JOURNAL J ON J.OBJ_ID = L.CJ_ID AND J.JOURNAL_TYPE = 0
              JOIN CJ2_CONTROL C ON C.DATE_DEL IS NULL AND C.LESSON_ID = L.OBJ_ID AND C.CONTROL_TYPE_ID = 0
              JOIN CJ2_MARK M ON M.DATE_DEL IS NULL AND M.CONTROL_ID = C.CONTROL_ID AND M.MARK_TYPE_ID = 91 AND M.STUDENT_ID = :V$OBJ_ID
              --LEFT JOIN CJ2_JOURNAL_ACCESS(:I$USER_ID, L.CJ_ID) A ON 1 = 1
              JOIN CJ2_JOURNAL_AUTOUSERS A ON A.CJ_ID = J.OBJ_ID AND A.USER_ID = :I$USER_ID AND A.DATE_DEL IS NULL AND A.ACCESS > 0
              WHERE L.DATE_DEL IS NULL AND L.IS_COMPLETED > 0 AND L.LESSON_DATE = :V$DATE AND (:I$OPTION_ID IS NULL OR L.CJ_ID = :I$OPTION_ID)
              INTO :N91;

              SELECT COUNT(*)
              FROM CJ2_JOURNAL_LESSONS L
              JOIN CJ2_JOURNAL J ON J.OBJ_ID = L.CJ_ID AND J.JOURNAL_TYPE = 0
              JOIN CJ2_CONTROL C ON C.DATE_DEL IS NULL AND C.LESSON_ID = L.OBJ_ID AND C.CONTROL_TYPE_ID = 0
              JOIN CJ2_MARK M ON M.DATE_DEL IS NULL AND M.CONTROL_ID = C.CONTROL_ID AND M.MARK_TYPE_ID = 92 AND M.STUDENT_ID = :V$OBJ_ID
              --LEFT JOIN CJ2_JOURNAL_ACCESS(:I$USER_ID, L.CJ_ID) A ON 1 = 1
              JOIN CJ2_JOURNAL_AUTOUSERS A ON A.CJ_ID = J.OBJ_ID AND A.USER_ID = :I$USER_ID AND A.DATE_DEL IS NULL AND A.ACCESS > 0
              WHERE L.DATE_DEL IS NULL AND L.IS_COMPLETED > 0 AND L.LESSON_DATE = :V$DATE AND (:I$OPTION_ID IS NULL OR L.CJ_ID = :I$OPTION_ID)
              INTO :N92;

              SELECT COUNT(*)
              FROM CJ2_JOURNAL_LESSONS L
              JOIN CJ2_JOURNAL J ON J.OBJ_ID = L.CJ_ID AND J.JOURNAL_TYPE = 0
              JOIN CJ2_CONTROL C ON C.DATE_DEL IS NULL AND C.LESSON_ID = L.OBJ_ID AND C.CONTROL_TYPE_ID = 0
              JOIN CJ2_MARK M ON M.DATE_DEL IS NULL AND M.CONTROL_ID = C.CONTROL_ID AND M.MARK_TYPE_ID = 93 AND M.STUDENT_ID = :V$OBJ_ID
              --LEFT JOIN CJ2_JOURNAL_ACCESS(:I$USER_ID, L.CJ_ID) A ON 1 = 1
              JOIN CJ2_JOURNAL_AUTOUSERS A ON A.CJ_ID = J.OBJ_ID AND A.USER_ID = :I$USER_ID AND A.DATE_DEL IS NULL AND A.ACCESS > 0
              WHERE L.DATE_DEL IS NULL AND L.IS_COMPLETED > 0 AND L.LESSON_DATE = :V$DATE AND (:I$OPTION_ID IS NULL OR L.CJ_ID = :I$OPTION_ID)
              INTO :N93;

              SELECT COUNT(*)
              FROM CJ2_JOURNAL_LESSONS L
              JOIN CJ2_JOURNAL J ON J.OBJ_ID = L.CJ_ID AND J.JOURNAL_TYPE = 0
              JOIN CJ2_CONTROL C ON C.DATE_DEL IS NULL AND C.LESSON_ID = L.OBJ_ID AND C.CONTROL_TYPE_ID = 0
              JOIN CJ2_MARK M ON M.DATE_DEL IS NULL AND M.CONTROL_ID = C.CONTROL_ID AND M.MARK_TYPE_ID = 94 AND M.STUDENT_ID = :V$OBJ_ID
              --LEFT JOIN CJ2_JOURNAL_ACCESS(:I$USER_ID, L.CJ_ID) A ON 1 = 1
              JOIN CJ2_JOURNAL_AUTOUSERS A ON A.CJ_ID = J.OBJ_ID AND A.USER_ID = :I$USER_ID AND A.DATE_DEL IS NULL AND A.ACCESS > 0
              WHERE L.DATE_DEL IS NULL AND L.IS_COMPLETED > 0 AND L.LESSON_DATE = :V$DATE AND (:I$OPTION_ID IS NULL OR L.CJ_ID = :I$OPTION_ID)
              INTO :N94;

              VAL = '<td>' || (N90 + N91 + N92 + N93 + N94) || '</td>';
              SUSPEND;
              TN90 = TN90 + N90;
              TN91 = TN91 + N91;
              TN92 = TN92 + N92;
              TN93 = TN93 + N93;
              TN94 = TN94 + N94;
          END
          VAL = '<td class="t t1">' || TN93 || '</td>';
          VAL = VAL || '<td class="t">' || TN94 || '</td>';
          VAL = VAL || '<td class="t">' || TN92 || '</td>';
          VAL = VAL || '<td class="t">' || TN91 || '</td>';
          VAL = VAL || '<td class="t">' || (TN91 + TN92 + TN93 + TN94) || '</td>';
          VAL = VAL || '<td class="t">' || TN90 || '</td>';
          VAL = VAL || '</tr>';
          SUSPEND;
      END

      -- Итоги
      -- !!! тут надо дофильтровывать, что ученик был в группе на нужные даты
      VAL = '<tr class="v total">';
      VAL = VAL || '<td>Всего</td>';
      SUSPEND;
      TN90 = 0; TN91 = 0; TN92 = 0; TN93 = 0; TN94 = 0;
      FOR SELECT DATE_ID FROM CJ_REPORT4_TEMP ORDER BY 1 INTO :V$DATE DO
      BEGIN
          SELECT COUNT(*)
          FROM PERSON_MOVEMENTS M
          JOIN PERSON_MOVEMENTS M2 ON M2.DATE_DEL IS NULL AND M2.PERSON_ID = M.PERSON_ID AND M2.DATE_IN <= :I$DATE_TO AND (M2.DATE_OUT IS NULL OR M2.DATE_OUT >= :I$DATE_FROM)
          JOIN OBJECTS G ON G.OBJ_ID = M2.GROUP_ID AND G.TYPE_ID = 179
          JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.GRADE_ID = M2.GROUP_ID AND J.JOURNAL_TYPE = 0 AND (:I$OPTION_ID IS NULL OR J.OBJ_ID = :I$OPTION_ID)
          JOIN CJ2_JOURNAL_LESSONS L ON L.DATE_DEL IS NULL AND L.CJ_ID = J.OBJ_ID AND L.IS_COMPLETED > 0 AND L.LESSON_DATE = :V$DATE
          JOIN CJ2_CONTROL C ON C.DATE_DEL IS NULL AND C.LESSON_ID = L.OBJ_ID AND C.CONTROL_TYPE_ID = 0
          JOIN CJ2_MARK CJM ON CJM.DATE_DEL IS NULL AND CJM.CONTROL_ID = C.CONTROL_ID AND CJM.STUDENT_ID = M2.PERSON_ID AND CJM.MARK_TYPE_ID = 90
          --LEFT JOIN CJ2_JOURNAL_ACCESS(:I$USER_ID, J.OBJ_ID) A ON 1 = 1
          JOIN CJ2_JOURNAL_AUTOUSERS A ON A.CJ_ID = J.OBJ_ID AND A.USER_ID = :I$USER_ID AND A.DATE_DEL IS NULL AND A.ACCESS > 0
          WHERE M.DATE_DEL IS NULL AND M.GROUP_ID = :I$OBJ_ID AND M.DATE_IN <= :I$DATE_TO AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :I$DATE_FROM)
          INTO :N90;

          SELECT COUNT(DISTINCT CJM.MARK_ID)
          FROM PERSON_MOVEMENTS M
          JOIN PERSON_MOVEMENTS M2 ON M2.DATE_DEL IS NULL AND M2.PERSON_ID = M.PERSON_ID AND M2.DATE_IN <= :I$DATE_TO AND (M2.DATE_OUT IS NULL OR M2.DATE_OUT >= :I$DATE_FROM)
          JOIN OBJECTS G ON G.OBJ_ID = M2.GROUP_ID AND G.TYPE_ID = 179
          JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.GRADE_ID = M2.GROUP_ID AND J.JOURNAL_TYPE = 0 AND (:I$OPTION_ID IS NULL OR J.OBJ_ID = :I$OPTION_ID)
          JOIN CJ2_JOURNAL_LESSONS L ON L.DATE_DEL IS NULL AND L.CJ_ID = J.OBJ_ID AND L.IS_COMPLETED > 0 AND L.LESSON_DATE = :V$DATE
          JOIN CJ2_CONTROL C ON C.DATE_DEL IS NULL AND C.LESSON_ID = L.OBJ_ID AND C.CONTROL_TYPE_ID = 0
          JOIN CJ2_MARK CJM ON CJM.DATE_DEL IS NULL AND CJM.CONTROL_ID = C.CONTROL_ID AND CJM.STUDENT_ID = M2.PERSON_ID AND CJM.MARK_TYPE_ID = 91
          --LEFT JOIN CJ2_JOURNAL_ACCESS(:I$USER_ID, J.OBJ_ID) A ON 1 = 1
          JOIN CJ2_JOURNAL_AUTOUSERS A ON A.CJ_ID = J.OBJ_ID AND A.USER_ID = :I$USER_ID AND A.DATE_DEL IS NULL AND A.ACCESS > 0
          WHERE M.DATE_DEL IS NULL AND M.GROUP_ID = :I$OBJ_ID AND M.DATE_IN <= :I$DATE_TO AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :I$DATE_FROM)
          INTO :N91;

          SELECT COUNT(DISTINCT CJM.MARK_ID)
          FROM PERSON_MOVEMENTS M
          JOIN PERSON_MOVEMENTS M2 ON M2.DATE_DEL IS NULL AND M2.PERSON_ID = M.PERSON_ID AND M2.DATE_IN <= :I$DATE_TO AND (M2.DATE_OUT IS NULL OR M2.DATE_OUT >= :I$DATE_FROM)
          JOIN OBJECTS G ON G.OBJ_ID = M2.GROUP_ID AND G.TYPE_ID = 179
          JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.GRADE_ID = M2.GROUP_ID AND J.JOURNAL_TYPE = 0 AND (:I$OPTION_ID IS NULL OR J.OBJ_ID = :I$OPTION_ID)
          JOIN CJ2_JOURNAL_LESSONS L ON L.DATE_DEL IS NULL AND L.CJ_ID = J.OBJ_ID AND L.IS_COMPLETED > 0 AND L.LESSON_DATE = :V$DATE
          JOIN CJ2_CONTROL C ON C.DATE_DEL IS NULL AND C.LESSON_ID = L.OBJ_ID AND C.CONTROL_TYPE_ID = 0
          JOIN CJ2_MARK CJM ON CJM.DATE_DEL IS NULL AND CJM.CONTROL_ID = C.CONTROL_ID AND CJM.STUDENT_ID = M2.PERSON_ID AND CJM.MARK_TYPE_ID = 92
          --LEFT JOIN CJ2_JOURNAL_ACCESS(:I$USER_ID, J.OBJ_ID) A ON 1 = 1
          JOIN CJ2_JOURNAL_AUTOUSERS A ON A.CJ_ID = J.OBJ_ID AND A.USER_ID = :I$USER_ID AND A.DATE_DEL IS NULL AND A.ACCESS > 0
          WHERE M.DATE_DEL IS NULL AND M.GROUP_ID = :I$OBJ_ID AND M.DATE_IN <= :I$DATE_TO AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :I$DATE_FROM)
          INTO :N92;

          SELECT COUNT(DISTINCT CJM.MARK_ID)
          FROM PERSON_MOVEMENTS M
          JOIN PERSON_MOVEMENTS M2 ON M2.DATE_DEL IS NULL AND M2.PERSON_ID = M.PERSON_ID AND M2.DATE_IN <= :I$DATE_TO AND (M2.DATE_OUT IS NULL OR M2.DATE_OUT >= :I$DATE_FROM)
          JOIN OBJECTS G ON G.OBJ_ID = M2.GROUP_ID AND G.TYPE_ID = 179
          JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.GRADE_ID = M2.GROUP_ID AND J.JOURNAL_TYPE = 0 AND (:I$OPTION_ID IS NULL OR J.OBJ_ID = :I$OPTION_ID)
          JOIN CJ2_JOURNAL_LESSONS L ON L.DATE_DEL IS NULL AND L.CJ_ID = J.OBJ_ID AND L.IS_COMPLETED > 0 AND L.LESSON_DATE = :V$DATE
          JOIN CJ2_CONTROL C ON C.DATE_DEL IS NULL AND C.LESSON_ID = L.OBJ_ID AND C.CONTROL_TYPE_ID = 0
          JOIN CJ2_MARK CJM ON CJM.DATE_DEL IS NULL AND CJM.CONTROL_ID = C.CONTROL_ID AND CJM.STUDENT_ID = M2.PERSON_ID AND CJM.MARK_TYPE_ID = 93
          --LEFT JOIN CJ2_JOURNAL_ACCESS(:I$USER_ID, J.OBJ_ID) A ON 1 = 1
          JOIN CJ2_JOURNAL_AUTOUSERS A ON A.CJ_ID = J.OBJ_ID AND A.USER_ID = :I$USER_ID AND A.DATE_DEL IS NULL AND A.ACCESS > 0
          WHERE M.DATE_DEL IS NULL AND M.GROUP_ID = :I$OBJ_ID AND M.DATE_IN <= :I$DATE_TO AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :I$DATE_FROM)
          INTO :N93;

          SELECT COUNT(DISTINCT CJM.MARK_ID)
          FROM PERSON_MOVEMENTS M
          JOIN PERSON_MOVEMENTS M2 ON M2.DATE_DEL IS NULL AND M2.PERSON_ID = M.PERSON_ID AND M2.DATE_IN <= :I$DATE_TO AND (M2.DATE_OUT IS NULL OR M2.DATE_OUT >= :I$DATE_FROM)
          JOIN OBJECTS G ON G.OBJ_ID = M2.GROUP_ID AND G.TYPE_ID = 179
          JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.GRADE_ID = M2.GROUP_ID AND J.JOURNAL_TYPE = 0 AND (:I$OPTION_ID IS NULL OR J.OBJ_ID = :I$OPTION_ID)
          JOIN CJ2_JOURNAL_LESSONS L ON L.DATE_DEL IS NULL AND L.CJ_ID = J.OBJ_ID AND L.IS_COMPLETED > 0 AND L.LESSON_DATE = :V$DATE
          JOIN CJ2_CONTROL C ON C.DATE_DEL IS NULL AND C.LESSON_ID = L.OBJ_ID AND C.CONTROL_TYPE_ID = 0
          JOIN CJ2_MARK CJM ON CJM.DATE_DEL IS NULL AND CJM.CONTROL_ID = C.CONTROL_ID AND CJM.STUDENT_ID = M2.PERSON_ID AND CJM.MARK_TYPE_ID = 94
          --LEFT JOIN CJ2_JOURNAL_ACCESS(:I$USER_ID, J.OBJ_ID) A ON 1 = 1
          JOIN CJ2_JOURNAL_AUTOUSERS A ON A.CJ_ID = J.OBJ_ID AND A.USER_ID = :I$USER_ID AND A.DATE_DEL IS NULL AND A.ACCESS > 0
          WHERE M.DATE_DEL IS NULL AND M.GROUP_ID = :I$OBJ_ID AND M.DATE_IN <= :I$DATE_TO AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :I$DATE_FROM)
          INTO :N94;

          VAL = '<td>' || (N90 + N91 + N92 + N93 + N94) || '</td>';
          SUSPEND;
          TN90 = TN90 + N90;
          TN91 = TN91 + N91;
          TN92 = TN92 + N92;
          TN93 = TN93 + N93;
          TN94 = TN94 + N94;
      END
      VAL = '<td class="t t1">' || TN93 || '</td>';
      VAL = VAL || '<td class="t">' || TN94 || '</td>';
      VAL = VAL || '<td class="t">' || TN92 || '</td>';
      VAL = VAL || '<td class="t">' || TN91 || '</td>';
      VAL = VAL || '<td class="t">' || (TN91 + TN92 + TN93 + TN94) || '</td>';
      VAL = VAL || '<td class="t">' || TN90 || '</td>';
      VAL = VAL || '</tr>';
      SUSPEND;

  END

  VAL = '</table></body></html>';
  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_REPORT_NX200 (
    I$USER_ID BIGINT,
    I$DATE_FROM TIMESTAMP,
    I$DATE_TO TIMESTAMP,
    I$PARENT_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$OPTION_ID BIGINT,
    I$OPTIONS VARCHAR(1000),
    I$ZONE SMALLINT = 0)
RETURNS (
    VAL VARCHAR(6000))
AS
declare variable S varchar(6000);
declare variable SS varchar(6000);
declare variable MS varchar(100);
declare variable N integer;
declare variable NN smallint;
declare variable V$CALLER_TYPE bigint;
declare variable V$YEAR_ID bigint;
declare variable V$ROLE smallint;
declare variable V$PERSON_ID bigint;
declare variable V$CJ_ID bigint;
declare variable V$OBJ_ID bigint;
declare variable V$GRADE_ID bigint;
declare variable V$STAGE_ID bigint;
declare variable V$CNT integer;
declare variable V$TCNT integer;
declare variable V$AVG float;
declare variable V$V float;
declare variable V$PREV float;
declare variable V$PRC integer;
declare variable V$PARENT_ID bigint;
declare variable V$TOP_PARENT bigint;
declare variable V$STUDENT_ID bigint;
begin

  -- Таблица стилей
  VAL = '<!DOCTYPE html>';
  VAL = VAL || '<html lang="ru">';
  VAL = VAL || '<head>';
  VAL = VAL || '<meta charset="utf-8" />';

  VAL = VAL || '<style>';
  VAL = VAL || 'html { font-family: Tahoma, Verdana, Arial;';
  VAL = VAL || 'font-size: 10pt; ';
  VAL = VAL || '} ';
  VAL = VAL || '.title1 { font-size: 150%;';
  VAL = VAL || 'padding: 8px;';
  VAL = VAL || 'margin-bottom: 4px;';
  VAL = VAL || 'font-weight: bold;';
  VAL = VAL || 'background-color: #D4E157;';
  VAL = VAL || '} ';
  VAL = VAL || '.title2 { ';
  VAL = VAL || 'padding: 4px;';
  VAL = VAL || 'font-weight: bold;';
  VAL = VAL || '} ';
  VAL = VAL || '.details {';
  VAL = VAL || 'margin-top: 10px;';
  VAL = VAL || 'border: 1px solid #c0c0c0;';
  VAL = VAL || '} ';
  VAL = VAL || '.details tr td {';
  VAL = VAL || 'padding: 2px 4px;';
  VAL = VAL || 'border-right: 1px solid #e0e0e0;';
  VAL = VAL || 'text-align: left;';
  VAL = VAL || '} ';
  VAL = VAL || '.odd td {';
  VAL = VAL || 'background-color: #f7f7f7;';
  VAL = VAL || '} ';
  VAL = VAL || '.thd {';
  VAL = VAL || 'background-color: #F0F4C3;';
  VAL = VAL || '} ';
  VAL = VAL || '.ths td {';
  VAL = VAL || 'border-bottom: 1px solid #c0c0c0;';
  VAL = VAL || '} ';
  VAL = VAL || '</style>';

  VAL = VAL || '</head>';
  VAL = VAL || '<body>';

  -- Школа, коллектив, персона
  SELECT TYPE_ID FROM OBJECTS WHERE OBJ_ID = :I$OBJ_ID INTO :V$CALLER_TYPE;

  -- Заголовок отчета
  VAL = VAL || '<div class="title1">Контроль УУД</div>';
  VAL = VAL || '<div class="title2">Период: ' || (SELECT RESULT FROM DATE2STR(:I$DATE_FROM)) || ' - ' || (SELECT RESULT FROM DATE2STR(:I$DATE_TO)) || '</div>';
  VAL = VAL || '<div class="title2">';
  IF (:V$CALLER_TYPE = 10) THEN VAL = VAL || (SELECT NAME_FULL FROM UT_PERSON_DESC(:I$OBJ_ID, :I$ZONE, 1));      -- обущающийся
                           ELSE VAL = VAL || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$OBJ_ID));
  VAL = VAL || '</div>';

  VAL = VAL || '<table class="details" cellspacing="0" cellpadding="0"';
  IF(V$CALLER_TYPE = 10) THEN VAL = VAL || ' style="width: 100%; table-layout: fixed;"';
  VAL = VAL || '>';

  SUSPEND;

  SELECT FIRST 1 V1236.LISTVAL_ID
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$YEAR_ID;

  SELECT U.OBJ_ID, U.USER_TYPE
  FROM USERS U
  WHERE U.USER_ID = :I$USER_ID AND U.DATE_DEL IS NULL AND U.IS_BLOCKED = 0
  INTO :V$PERSON_ID, :V$ROLE;

  IF(V$ROLE IS NULL) THEN EXCEPTION DATA_ERROR 'У вас нет доступа к этому отчету';

  N = 0;
  NN = 0;

  IF(V$CALLER_TYPE = 2) THEN
  BEGIN

    -- По ОУ в целом - журналы текущего года

    S = '<tr class="thd">';

    VAL = '<tr class="thd">';
    VAL = VAL || '<td rowspan="2">Этап обучения</td>';
    -- Разделы
    FOR
      SELECT LV.LISTVAL_ID, R.VAL
      FROM LISTVALS LV
      JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
      WHERE LV.LIST_ID = 330 AND LV.PARENT_ID IS NULL AND LV.IS_DEL = 0
      ORDER BY LV.SORT_ORDER
      INTO :V$OBJ_ID, :SS
    DO
    BEGIN
      SS = TRIM(REPLACE(SS, 'действия', ''));

      VAL = VAL || '<td data-value="' || V$OBJ_ID || '" colspan="3">' || SS || '</td>';
      S = S || '<td title="Кол-во мероприятий">мер</td>';
      S = S || '<td title="Охват обучающихся, %">охв</td>';
      S = S || '<td title="Результаты">рез</td>';
    END
    VAL = VAL || '</tr>';
    SUSPEND;
    VAL = S || '</tr>';
    SUSPEND;

    FOR
      SELECT DISTINCT J.STAGE_INDEX
      FROM CJ2_JOURNAL J
      JOIN LISTVALS LV ON LV.LISTVAL_ID = J.STAGE_INDEX
      WHERE J.DATE_DEL IS NULL AND J.JOURNAL_TYPE = 0 AND J.YEAR_ID = :V$YEAR_ID
      ORDER BY LV.SORT_ORDER
      INTO :V$STAGE_ID
    DO
    BEGIN
      VAL = '<tr data-value="' || V$STAGE_ID || '"';
      IF(NN = 1) THEN VAL = VAL || ' class="odd"';
      VAL = VAL || '>';
      VAL = VAL || '<td>' || (SELECT VAL FROM LISTVAL_TEXT(:V$STAGE_ID)) || '</td>';

      FOR
        SELECT LV.LISTVAL_ID
        FROM LISTVALS LV
        WHERE LV.LIST_ID = 330 AND LV.PARENT_ID IS NULL AND LV.IS_DEL = 0
        ORDER BY LV.SORT_ORDER
        INTO :V$OBJ_ID
      DO
      BEGIN
        -- Количество контролей за указанный период
        SELECT COUNT(DISTINCT C.CONTROL_ID)
        FROM CJ2_JOURNAL J
        JOIN CJ2_JOURNAL_LESSONS L ON L.DATE_DEL IS NULL AND L.CJ_ID = J.OBJ_ID AND (L.LESSON_DATE >= :I$DATE_FROM OR :I$DATE_FROM IS NULL)
          AND (L.LESSON_DATE <= :I$DATE_TO OR :I$DATE_TO IS NULL)
        JOIN CJ2_CONTROL C ON C.DATE_DEL IS NULL AND C.LESSON_ID = L.OBJ_ID AND C.CONTROL_TYPE_ID = 30000
        JOIN CJ2_LESSON_UUD U ON U.CONTROL_ID = C.CONTROL_ID AND U.GROUP_ID = :V$OBJ_ID AND U.IS_DEL = 0
        WHERE J.DATE_DEL IS NULL AND J.JOURNAL_TYPE = 0 AND J.YEAR_ID = :V$YEAR_ID AND J.STAGE_INDEX = :V$STAGE_ID
        INTO :V$CNT;
        VAL = VAL || '<td>' || V$CNT || '</td>';

        -- Охват участников, шкала 1-3-5 - сколько учеников получили отметки
        V$CNT = NULL;
        V$AVG = NULL;
        SELECT COUNT(DISTINCT M.STUDENT_ID), AVG(MT.MARK_COST - 3) * 5.0 / 2
        FROM CJ2_JOURNAL J
        JOIN CJ2_JOURNAL_LESSONS L ON L.DATE_DEL IS NULL AND L.CJ_ID = J.OBJ_ID AND (L.LESSON_DATE >= :I$DATE_FROM OR :I$DATE_FROM IS NULL)
          AND (L.LESSON_DATE <= :I$DATE_TO OR :I$DATE_TO IS NULL)
        JOIN CJ2_CONTROL C ON C.DATE_DEL IS NULL AND C.LESSON_ID = L.OBJ_ID AND C.CONTROL_TYPE_ID = 30000
        JOIN CJ2_LESSON_UUD U ON U.CONTROL_ID = C.CONTROL_ID AND U.GROUP_ID = :V$OBJ_ID AND U.IS_DEL = 0
        JOIN CJ2_MARK M ON M.DATE_DEL IS NULL AND M.CONTROL_ID = C.CONTROL_ID
        JOIN CJ2_MARK_TYPE MT ON MT.MARK_TYPE_ID = M.MARK_TYPE_ID
        WHERE J.DATE_DEL IS NULL AND J.JOURNAL_TYPE = 0 AND J.YEAR_ID = :V$YEAR_ID AND J.STAGE_INDEX = :V$STAGE_ID
        INTO :V$CNT, :V$AVG;

        -- Всего учеников классов
        SELECT COUNT(DISTINCT MV.PERSON_ID)
        FROM CJ2_JOURNAL J
        JOIN PERSON_MOVEMENTS MV ON MV.DATE_DEL IS NULL AND MV.GROUP_ID = J.GRADE_ID AND MV.DATE_IN <= :I$DATE_TO
          AND (MV.DATE_OUT >= :I$DATE_FROM OR MV.DATE_OUT IS NULL)
        WHERE J.DATE_DEL IS NULL AND J.JOURNAL_TYPE = 0 AND J.YEAR_ID = :V$YEAR_ID AND J.STAGE_INDEX = :V$STAGE_ID
        INTO :V$TCNT;

        IF(V$CNT IS NULL OR V$TCNT IS NULL OR V$CNT = 0 OR V$TCNT = 0) THEN V$V = NULL;
        ELSE V$V = MINVALUE(100 * V$CNT / V$TCNT, 100);

        V$PRC = TRUNC(V$V / 20) * 20;
        IF(V$CNT IS NULL OR V$CNT = 0) THEN MS = '';
        ELSE IF(V$PRC IS NULL) THEN MS = 'prcn';
        ELSE MS = 'prc' || V$PRC;
        VAL = VAL || '<td class="' || MS || '">' || IIF(V$V IS NULL, '', CAST(V$V AS NUMERIC(18, 1))) || '</td>';

        -- Средний результат
        VAL = VAL || '<td>' || IIF(V$AVG IS NULL, '', CAST(V$AVG AS NUMERIC(18, 2))) || '</td>';
      END

      VAL = VAL || '</tr>';
      SUSPEND;
      N = N + 1;
      IF(NN = 0) THEN NN = 1; ELSE NN = 0;
    END

    VAL = '<tr class="total">';
    VAL = VAL || '<td>Всего по ОУ</td>';
    FOR
      SELECT LV.LISTVAL_ID
      FROM LISTVALS LV
      WHERE LV.LIST_ID = 330 AND LV.PARENT_ID IS NULL AND LV.IS_DEL = 0
      ORDER BY LV.SORT_ORDER
      INTO :V$OBJ_ID
    DO
    BEGIN
      VAL = VAL || '<td class="sum">$SUM$</td>';
      VAL = VAL || '<td class="sum">$AVG$</td>';
      VAL = VAL || '<td></td>';
    END
    VAL = VAL || '</tr>';
    SUSPEND;

  END
  ELSE IF(V$CALLER_TYPE = 9) THEN
  BEGIN

    -- По классу - разделы и подразделы по предметам
    -- Тут показываем две таблицы - сначала по ученикам, потом по предметам
    S = '<tr class="thd">';

    VAL = '<tr class="thd">';
    VAL = VAL || '<td rowspan="2">Обучающийся</td>';
    -- Разделы
    FOR
      SELECT LV.LISTVAL_ID, R.VAL
      FROM LISTVALS LV
      JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
      WHERE LV.LIST_ID = 330 AND LV.PARENT_ID IS NULL AND LV.IS_DEL = 0
      ORDER BY LV.SORT_ORDER
      INTO :V$OBJ_ID, :SS
    DO
    BEGIN
      SS = TRIM(REPLACE(SS, 'действия', ''));

      VAL = VAL || '<td data-value="' || V$OBJ_ID || '" colspan="3">' || SS || '</td>';
      S = S || '<td title="Кол-во мероприятий">мер</td>';
      S = S || '<td title="Кол-во мероприятий в зачет">зчт</td>';
      S = S || '<td title="Результаты">рез</td>';
    END
    VAL = VAL || '</tr>';
    SUSPEND;
    VAL = S || '</tr>';
    SUSPEND;

    -- Только текущие журналы, где есть ученики класса
    FOR
      SELECT DISTINCT MV.PERSON_ID, P.NAME_FULL --C.CAPTION
      FROM PERSON_MOVEMENTS MV
      LEFT JOIN UT_PERSON_DESC(MV.PERSON_ID, :I$ZONE, 1) P ON 1 = 1 --Redmine #1060 --LEFT JOIN OBJECT_CAPTION_GET(MV.PERSON_ID, 23) C ON 1 = 1
      WHERE MV.DATE_DEL IS NULL AND MV.GROUP_ID = :I$OBJ_ID AND MV.DATE_IN <= :I$DATE_TO AND (MV.DATE_OUT >= :I$DATE_FROM OR MV.DATE_OUT IS NULL)
      ORDER BY 2
      INTO :V$STUDENT_ID, :S
    DO
    BEGIN
      VAL = '<tr data-value="' || V$STUDENT_ID || '"';
      IF(NN = 1) THEN VAL = VAL || ' class="odd"';
      VAL = VAL || '>';
      VAL = VAL || '<td>' || S || '</td>';

      FOR
        SELECT LV.LISTVAL_ID
        FROM LISTVALS LV
        WHERE LV.LIST_ID = 330 AND LV.PARENT_ID IS NULL AND LV.IS_DEL = 0
        ORDER BY LV.SORT_ORDER
        INTO :V$OBJ_ID
      DO
      BEGIN
        -- Количество контролей за указанный период
        V$CNT = NULL;
        SELECT COUNT(DISTINCT C.CONTROL_ID)
        FROM (
          SELECT DISTINCT J.OBJ_ID
          FROM PERSON_MOVEMENTS MV
          JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.GRADE_ID = MV.GROUP_ID AND J.JOURNAL_TYPE = 0
          WHERE MV.DATE_DEL IS NULL AND MV.PERSON_ID = :V$STUDENT_ID AND MV.DATE_IN <= :I$DATE_TO AND (MV.DATE_OUT >= :I$DATE_FROM OR MV.DATE_OUT IS NULL)
        ) CJ
        JOIN CJ2_JOURNAL_LESSONS L ON L.DATE_DEL IS NULL AND L.CJ_ID = CJ.OBJ_ID AND (L.LESSON_DATE >= :I$DATE_FROM OR :I$DATE_FROM IS NULL)
          AND (L.LESSON_DATE <= :I$DATE_TO OR :I$DATE_TO IS NULL)
        JOIN CJ2_CONTROL C ON C.DATE_DEL IS NULL AND C.LESSON_ID = L.OBJ_ID AND C.CONTROL_TYPE_ID = 30000
        JOIN CJ2_LESSON_UUD U ON U.CONTROL_ID = C.CONTROL_ID AND U.GROUP_ID = :V$OBJ_ID AND U.IS_DEL = 0
        INTO :V$CNT;
        VAL = VAL || '<td>' || V$CNT || '</td>';

        -- Охват участников не нужен, нужен средний балл, шкала 1-3-5
        V$CNT = NULL;
        V$AVG = NULL;
        SELECT COUNT(DISTINCT C.CONTROL_ID), AVG(MT.MARK_COST - 3) * 5.0 / 2
        FROM (
          SELECT DISTINCT J.OBJ_ID
          FROM PERSON_MOVEMENTS MV
          JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.GRADE_ID = MV.GROUP_ID AND J.JOURNAL_TYPE = 0
          WHERE MV.DATE_DEL IS NULL AND MV.PERSON_ID = :V$STUDENT_ID AND MV.DATE_IN <= :I$DATE_TO AND (MV.DATE_OUT >= :I$DATE_FROM OR MV.DATE_OUT IS NULL)
        ) CJ
        JOIN CJ2_JOURNAL_LESSONS L ON L.DATE_DEL IS NULL AND L.CJ_ID = CJ.OBJ_ID AND (L.LESSON_DATE >= :I$DATE_FROM OR :I$DATE_FROM IS NULL)
          AND (L.LESSON_DATE <= :I$DATE_TO OR :I$DATE_TO IS NULL)
        JOIN CJ2_CONTROL C ON C.DATE_DEL IS NULL AND C.LESSON_ID = L.OBJ_ID AND C.CONTROL_TYPE_ID = 30000
        JOIN CJ2_LESSON_UUD U ON U.CONTROL_ID = C.CONTROL_ID AND U.GROUP_ID = :V$OBJ_ID AND U.IS_DEL = 0
        JOIN CJ2_MARK M ON M.DATE_DEL IS NULL AND M.CONTROL_ID = C.CONTROL_ID AND M.STUDENT_ID = :V$STUDENT_ID
        JOIN CJ2_MARK_TYPE MT ON MT.MARK_TYPE_ID = M.MARK_TYPE_ID
        INTO :V$CNT, :V$AVG;

        VAL = VAL || '<td>' || IIF(V$CNT IS NULL, '0', V$CNT) || '</td>';

        -- Средний результат
        VAL = VAL || '<td>' || IIF(V$AVG IS NULL, '', CAST(V$AVG AS NUMERIC(18, 2))) || '</td>';
      END

      VAL = VAL || '</tr>';
      SUSPEND;
      N = N + 1;
      IF(NN = 0) THEN NN = 1; ELSE NN = 0;
    END

    VAL = '<tr class="total">';
    VAL = VAL || '<td>Всего/в среднем по классу</td>';
    FOR
      SELECT LV.LISTVAL_ID
      FROM LISTVALS LV
      WHERE LV.LIST_ID = 330 AND LV.PARENT_ID IS NULL AND LV.IS_DEL = 0
      ORDER BY LV.SORT_ORDER
      INTO :V$OBJ_ID
    DO
    BEGIN
      V$CNT = NULL;
      V$AVG = NULL;
      SELECT COUNT(DISTINCT C.CONTROL_ID)
      FROM (
        SELECT DISTINCT J.OBJ_ID
        FROM PERSON_MOVEMENTS MV
        JOIN PERSON_MOVEMENTS MV2 ON MV2.DATE_DEL IS NULL AND MV2.PERSON_ID = MV.PERSON_ID AND MV2.DATE_IN <= :I$DATE_TO
          AND (MV2.DATE_OUT >= :I$DATE_FROM OR MV2.DATE_OUT IS NULL)
        JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.GRADE_ID = MV2.GROUP_ID AND J.JOURNAL_TYPE = 0
        WHERE MV.DATE_DEL IS NULL AND MV.GROUP_ID = :I$OBJ_ID AND MV.DATE_IN <= :I$DATE_TO AND (MV.DATE_OUT >= :I$DATE_FROM OR MV.DATE_OUT IS NULL)
      ) CJ
      JOIN CJ2_JOURNAL_LESSONS L ON L.DATE_DEL IS NULL AND L.CJ_ID = CJ.OBJ_ID AND (L.LESSON_DATE >= :I$DATE_FROM OR :I$DATE_FROM IS NULL)
        AND (L.LESSON_DATE <= :I$DATE_TO OR :I$DATE_TO IS NULL)
      JOIN CJ2_CONTROL C ON C.DATE_DEL IS NULL AND C.LESSON_ID = L.OBJ_ID AND C.CONTROL_TYPE_ID = 30000
      JOIN CJ2_LESSON_UUD U ON U.CONTROL_ID = C.CONTROL_ID AND U.GROUP_ID = :V$OBJ_ID AND U.IS_DEL = 0
      INTO :V$CNT;

      /*SELECT AVG(MT.MARK_COST - 3) * 5.0 / 2
      FROM (
        SELECT DISTINCT J.OBJ_ID, MV.PERSON_ID
        FROM PERSON_MOVEMENTS MV
        JOIN PERSON_MOVEMENTS MV2 ON MV2.DATE_DEL IS NULL AND MV2.PERSON_ID = MV.PERSON_ID AND MV2.DATE_IN <= :I$DATE_TO
          AND (MV2.DATE_OUT >= :I$DATE_FROM OR MV2.DATE_OUT IS NULL)
        JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.GRADE_ID = MV2.GROUP_ID AND J.JOURNAL_TYPE = 0
        WHERE MV.DATE_DEL IS NULL AND MV.GROUP_ID = :I$OBJ_ID AND MV.DATE_IN <= :I$DATE_TO AND (MV.DATE_OUT >= :I$DATE_FROM OR MV.DATE_OUT IS NULL)
      ) CJ
      JOIN CJ2_JOURNAL_LESSONS L ON L.DATE_DEL IS NULL AND L.CJ_ID = CJ.OBJ_ID AND (L.LESSON_DATE >= :I$DATE_FROM OR :I$DATE_FROM IS NULL)
        AND (L.LESSON_DATE <= :I$DATE_TO OR :I$DATE_TO IS NULL)
      JOIN CJ2_CONTROL C ON C.DATE_DEL IS NULL AND C.LESSON_ID = L.OBJ_ID AND C.CONTROL_TYPE_ID = 30000
      JOIN CJ2_LESSON_UUD U ON U.CONTROL_ID = C.CONTROL_ID AND U.GROUP_ID = :V$OBJ_ID AND U.IS_DEL = 0
      JOIN CJ2_MARK M ON M.DATE_DEL IS NULL AND M.CONTROL_ID = C.CONTROL_ID AND M.STUDENT_ID = CJ.PERSON_ID
      JOIN CJ2_MARK_TYPE MT ON MT.MARK_TYPE_ID = M.MARK_TYPE_ID
      INTO :V$AVG;*/

      VAL = VAL || '<td>' || IIF(V$CNT IS NULL, '0', V$CNT) || '</td>';
      VAL = VAL || '<td></td>'; -- тут пусто
      VAL = VAL || '<td>' || IIF(V$AVG IS NULL, '', CAST(V$AVG AS NUMERIC(18, 2))) || '</td>';
    END
    VAL = VAL || '</tr>';
    SUSPEND;

    VAL = '</table>';
    VAL = VAL || '<table class="details" cellspacing="0" cellpadding="0">';
    SUSPEND;

    -- По предметам
    S = '<tr class="thd">';

    VAL = '<tr class="thd">';
    VAL = VAL || '<td rowspan="2">Журнал, группа, предмет</td>';
    VAL = VAL || '<td rowspan="2">Преподаватель</td>';
    -- Разделы
    FOR
      SELECT LV.LISTVAL_ID, R.VAL
      FROM LISTVALS LV
      JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
      WHERE LV.LIST_ID = 330 AND LV.PARENT_ID IS NULL AND LV.IS_DEL = 0
      ORDER BY LV.SORT_ORDER
      INTO :V$OBJ_ID, :SS
    DO
    BEGIN
      SS = TRIM(REPLACE(SS, 'действия', ''));

      VAL = VAL || '<td data-value="' || V$OBJ_ID || '" colspan="3">' || SS || '</td>';
      S = S || '<td title="Кол-во мероприятий">мер</td>';
      S = S || '<td title="Охват обучающихся, %">охв</td>';
      S = S || '<td title="Результаты">рез</td>';
    END
    VAL = VAL || '</tr>';
    SUSPEND;
    VAL = S || '</tr>';
    SUSPEND;

    -- Только текущие журналы, где есть ученики класса
    FOR
      SELECT CJ.OBJ_ID, CJ.GRADE_ID, CJ.JOURNAL_NAME || ' - ' || C.CAPTION, COALESCE(P.NAME_FULL, '')--COALESCE(CT.CAPTION, '')
      FROM (
        SELECT DISTINCT J.OBJ_ID, J.GRADE_ID, J.JOURNAL_NAME, J.STAGE_INDEX, J.TEACHER_ID, J.SUBJECT_ID
        FROM LINKS L10
        JOIN LINKS LPG ON LPG.OBJ_ID = L10.OBJ_ID AND LPG.PARENT_TYPE_ID IN (9, 179) AND LPG.DATE_DEL IS NULL
        JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.JOURNAL_TYPE = 0 AND J.YEAR_ID = :V$YEAR_ID AND J.GRADE_ID = LPG.PARENT_ID
        WHERE L10.PARENT_ID = :I$OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      ) CJ
      LEFT JOIN OBJECT_CAPTION_GET(CJ.SUBJECT_ID) C ON 1 = 1
      LEFT JOIN UT_PERSON_DESC(CJ.TEACHER_ID, :I$ZONE, 1) P ON 1 = 1 --Redmeni #1060 --LEFT JOIN OBJECT_CAPTION_GET(CJ.TEACHER_ID) CT ON CJ.TEACHER_ID IS NOT NULL
      ORDER BY CJ.STAGE_INDEX, 3
      INTO :V$CJ_ID, :V$GRADE_ID, :S, :SS
    DO
    BEGIN
      VAL = '<tr data-value="' || V$CJ_ID || '"';
      IF(NN = 1) THEN VAL = VAL || ' class="odd"';
      VAL = VAL || '>';
      VAL = VAL || '<td>' || S || '</td>';
      VAL = VAL || '<td>' || SS || '</td>';

      FOR
        SELECT LV.LISTVAL_ID
        FROM LISTVALS LV
        WHERE LV.LIST_ID = 330 AND LV.PARENT_ID IS NULL AND LV.IS_DEL = 0
        ORDER BY LV.SORT_ORDER
        INTO :V$OBJ_ID
      DO
      BEGIN
        -- Количество контролей за указанный период
        SELECT COUNT(DISTINCT C.CONTROL_ID)
        FROM CJ2_JOURNAL_LESSONS L
        JOIN CJ2_CONTROL C ON C.DATE_DEL IS NULL AND C.LESSON_ID = L.OBJ_ID AND C.CONTROL_TYPE_ID = 30000
        JOIN CJ2_LESSON_UUD U ON U.CONTROL_ID = C.CONTROL_ID AND U.GROUP_ID = :V$OBJ_ID AND U.IS_DEL = 0
        WHERE L.DATE_DEL IS NULL AND L.CJ_ID = :V$CJ_ID AND (L.LESSON_DATE >= :I$DATE_FROM OR :I$DATE_FROM IS NULL)
          AND (L.LESSON_DATE <= :I$DATE_TO OR :I$DATE_TO IS NULL)
        INTO :V$CNT;
        VAL = VAL || '<td>' || V$CNT || '</td>';

        -- Охват участников, шкала 1-3-5
        V$CNT = NULL;
        V$AVG = NULL;
        SELECT COUNT(DISTINCT M.STUDENT_ID), AVG(MT.MARK_COST - 3) * 5.0 / 2
        FROM CJ2_JOURNAL_LESSONS L
        JOIN CJ2_CONTROL C ON C.DATE_DEL IS NULL AND C.LESSON_ID = L.OBJ_ID AND C.CONTROL_TYPE_ID = 30000
        JOIN CJ2_LESSON_UUD U ON U.CONTROL_ID = C.CONTROL_ID AND U.GROUP_ID = :V$OBJ_ID AND U.IS_DEL = 0
        JOIN CJ2_MARK M ON M.DATE_DEL IS NULL AND M.CONTROL_ID = C.CONTROL_ID
        JOIN CJ2_MARK_TYPE MT ON MT.MARK_TYPE_ID = M.MARK_TYPE_ID
        WHERE L.DATE_DEL IS NULL AND L.CJ_ID = :V$CJ_ID AND (L.LESSON_DATE >= :I$DATE_FROM OR :I$DATE_FROM IS NULL)
          AND (L.LESSON_DATE <= :I$DATE_TO OR :I$DATE_TO IS NULL)
        INTO :V$CNT, :V$AVG;

        SELECT COUNT(DISTINCT MV.PERSON_ID)
        FROM PERSON_MOVEMENTS MV
        WHERE MV.DATE_DEL IS NULL AND MV.GROUP_ID = :V$GRADE_ID AND MV.DATE_IN <= :I$DATE_TO AND (MV.DATE_OUT >= :I$DATE_FROM OR MV.DATE_OUT IS NULL)
        INTO :V$TCNT;

        IF(V$CNT IS NULL OR V$TCNT IS NULL OR V$CNT = 0 OR V$TCNT = 0) THEN V$V = NULL;
        ELSE V$V = MINVALUE(100 * V$CNT / V$TCNT, 100);

        V$PRC = TRUNC(V$V / 20) * 20;
        IF(V$CNT IS NULL OR V$CNT = 0) THEN MS = '';
        ELSE IF(V$PRC IS NULL) THEN MS = 'prcn';
        ELSE MS = 'prc' || V$PRC;
        VAL = VAL || '<td class="' || MS || '">' || IIF(V$V IS NULL, '', CAST(V$V AS NUMERIC(18, 0))) || '</td>';

        -- Средний результат
        VAL = VAL || '<td>' || IIF(V$AVG IS NULL, '', CAST(V$AVG AS NUMERIC(18, 2))) || '</td>';
      END

      VAL = VAL || '</tr>';
      SUSPEND;
      N = N + 1;
      IF(NN = 0) THEN NN = 1; ELSE NN = 0;
    END

    VAL = '<tr class="total">';
    VAL = VAL || '<td colspan="2">Всего по классу</td>';
    FOR
      SELECT LV.LISTVAL_ID
      FROM LISTVALS LV
      WHERE LV.LIST_ID = 330 AND LV.PARENT_ID IS NULL AND LV.IS_DEL = 0
      ORDER BY LV.SORT_ORDER
      INTO :V$OBJ_ID
    DO
    BEGIN
      VAL = VAL || '<td class="sum">$SUM$</td>';
      VAL = VAL || '<td></td>';
      VAL = VAL || '<td></td>';
    END
    VAL = VAL || '</tr>';
    SUSPEND;

  END
  ELSE IF(V$CALLER_TYPE = 10) THEN
  BEGIN

    -- По ученику

    VAL = '<tr class="thd">';
    VAL = VAL || '<td style="width: 60%">Раздел, УУД</td>';
    VAL = VAL || '<td>За текущий год</td>';
    VAL = VAL || '<td>Контролей</td>';
    VAL = VAL || '<td>Результат на прошлый год(-ы)</td>';
    VAL = VAL || '<td>Суммарно за все время</td>';
    VAL = VAL || '</tr>';
    SUSPEND;

    FOR
      SELECT DISTINCT LV.PARENT_ID, LV.LISTVAL_ID, R.VAL
      FROM LISTVALS LV
      JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
      JOIN VALX V ON V.PUPIL_ID = :I$OBJ_ID AND (V.USA_GROUP = LV.LISTVAL_ID OR V.USA_SUBGROUP = LV.LISTVAL_ID OR V.USA_ITEM = LV.LISTVAL_ID)
      WHERE LV.LIST_ID = 330 AND LV.IS_DEL = 0
      ORDER BY LV.SORT_ORDER
      INTO :V$PARENT_ID, :V$OBJ_ID, :S
    DO
    BEGIN
      IF(V$PARENT_ID IS NULL) THEN V$TOP_PARENT = V$OBJ_ID;

      VAL = '<tr';
      IF(NN = 1) THEN VAL = VAL || ' class="odd"';
      VAL = VAL || '>';
      IF(V$PARENT_ID IS NULL OR V$PARENT_ID = V$TOP_PARENT) THEN S = '<b>' || S || '</b>';
      VAL = VAL || '<td>' || S || '</td>';

      -- Тут данные за текущий год и нарастающим итогом
      V$V = NULL;
      V$CNT = NULL;
      V$AVG = NULL;
      V$PREV = NULL;
      SELECT V.LVAL, V.YTOTAL, V.VAL
      FROM VALX V
      WHERE V.PUPIL_ID = :I$OBJ_ID AND V.USA_ID = :V$OBJ_ID AND V.YEAR_ID = :V$YEAR_ID
      INTO :V$V, :V$CNT, :V$AVG;

      SELECT V.VAL
      FROM VALX V
      WHERE V.PUPIL_ID = :I$OBJ_ID AND V.USA_ID = :V$OBJ_ID AND V.YEAR_ID < :V$YEAR_ID
      INTO :V$PREV;

      VAL = VAL || '<td>' || IIF(V$V IS NULL, '', CAST(V$V AS NUMERIC(18, 1))) || '</td>';
      VAL = VAL || '<td>' || IIF(V$CNT IS NULL, '', V$CNT) || '</td>';
      VAL = VAL || '<td>' || IIF(V$PREV IS NULL, '', CAST(V$PREV AS NUMERIC(18, 1))) || '</td>';
      VAL = VAL || '<td>' || IIF(V$AVG IS NULL, '', CAST(V$AVG AS NUMERIC(18, 1))) || '</td>';

      VAL = VAL || '</tr>';
      SUSPEND;
      N = N + 1;
      IF(NN = 0) THEN NN = 1; ELSE NN = 0;
    END

    IF(N = 0) THEN
    BEGIN
      VAL = '<tr><td colspan="5">Нет накопленных данных по УУД</td></tr>';
      SUSPEND;
    END

  END

  -- Закрываем таблицу
  VAL = '</table></body></html>';
  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_REPORT_NX210 (
    I$USER_ID BIGINT,
    I$DATE_FROM TIMESTAMP,
    I$DATE_TO TIMESTAMP,
    I$PARENT_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$OPTION_ID BIGINT,
    I$OPTIONS VARCHAR(1000),
    I$ZONE SMALLINT = 0)
RETURNS (
    VAL VARCHAR(6000))
AS
declare variable S varchar(6000);
declare variable SS varchar(6000);
declare variable MS varchar(100);
declare variable N integer;
declare variable NN smallint;
declare variable V$CALLER_TYPE bigint;
declare variable V$YEAR_ID bigint;
declare variable V$PERSON_ID bigint;
declare variable V$ROLE smallint;
declare variable V$CJ_ID bigint;
declare variable V$GRADE_ID bigint;
declare variable V$CNT integer;
begin

  -- Таблица стилей
  VAL = '<!DOCTYPE html>';
  VAL = VAL || '<html lang="ru">';
  VAL = VAL || '<head>';
  VAL = VAL || '<meta charset="utf-8" />';

  VAL = VAL || '<style>';
  VAL = VAL || 'html { font-family: Tahoma, Verdana, Arial;';
  VAL = VAL || 'font-size: 10pt; ';
  VAL = VAL || '} ';
  VAL = VAL || '.title1 { font-size: 150%;';
  VAL = VAL || 'padding: 8px;';
  VAL = VAL || 'margin-bottom: 4px;';
  VAL = VAL || 'font-weight: bold;';
  VAL = VAL || 'background-color: #D4E157;';
  VAL = VAL || '} ';
  VAL = VAL || '.title2 { ';
  VAL = VAL || 'padding: 4px;';
  VAL = VAL || 'font-weight: bold;';
  VAL = VAL || '} ';
  VAL = VAL || '.details {';
  VAL = VAL || 'margin-top: 10px;';
  VAL = VAL || 'border: 1px solid #c0c0c0;';
  VAL = VAL || '} ';
  VAL = VAL || '.details tr td {';
  VAL = VAL || 'padding: 2px 4px;';
  VAL = VAL || 'border-right: 1px solid #e0e0e0;';
  VAL = VAL || 'text-align: left;';
  VAL = VAL || '} ';
  VAL = VAL || '.odd td {';
  VAL = VAL || 'background-color: #f7f7f7;';
  VAL = VAL || '} ';
  VAL = VAL || '</style>';

  VAL = VAL || '</head>';
  VAL = VAL || '<body>';

  -- Школа, коллектив, персона
  SELECT TYPE_ID FROM OBJECTS WHERE OBJ_ID = :I$OBJ_ID INTO :V$CALLER_TYPE;

  -- Заголовок отчета
  VAL = VAL || '<div class="title1">Контроль ПЭС</div>';
  VAL = VAL || '<div class="title2">Период: ' || (SELECT RESULT FROM DATE2STR(:I$DATE_FROM)) || ' - ' || (SELECT RESULT FROM DATE2STR(:I$DATE_TO)) || '</div>';
  VAL = VAL || '<div class="title2">';
  IF (:V$CALLER_TYPE = 10) THEN VAL = VAL || (SELECT NAME_FULL FROM UT_PERSON_DESC(:I$OBJ_ID, :I$ZONE, 1));      -- обущающийся
                           ELSE VAL = VAL || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$OBJ_ID));
  VAL = VAL || '</div>';

  VAL = VAL || '<table class="details" cellspacing="0" cellpadding="0">';

  SUSPEND;

  SELECT FIRST 1 V1236.LISTVAL_ID
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$YEAR_ID;

  SELECT U.OBJ_ID, U.USER_TYPE
  FROM USERS U
  WHERE U.USER_ID = :I$USER_ID AND U.DATE_DEL IS NULL AND U.IS_BLOCKED = 0
  INTO :V$PERSON_ID, :V$ROLE;

  IF(V$ROLE IS NULL) THEN EXCEPTION DATA_ERROR 'У вас нет доступа к этому отчету';

  N = 0;
  NN = 0;

  IF(V$CALLER_TYPE = 2) THEN
  BEGIN

    -- По ОУ в целом
    VAL = '<tr class="thd">';
    VAL = VAL || '<td>Журнал, группа, предмет</td>';
    VAL = VAL || '<td>Преподаватель</td>';
    VAL = VAL || '<td>Кол-во уроков</td>';
    VAL = VAL || '<td>Связано с ПЭС</td>';
    VAL = VAL || '</tr>';
    SUSPEND;

    -- По ОУ в целом - журналы текущего года
    FOR
      SELECT J.OBJ_ID, J.GRADE_ID, J.JOURNAL_NAME || ' - ' || C.CAPTION,COALESCE(P.NAME_FULL, '')-- COALESCE(CT.CAPTION, '')
      FROM CJ2_JOURNAL J
      LEFT JOIN OBJECT_CAPTION_GET(J.SUBJECT_ID) C ON 1 = 1
      LEFT JOIN UT_PERSON_DESC(J.TEACHER_ID, :I$ZONE, 1) P ON 1 = 1 --Redmine #1060 --LEFT JOIN OBJECT_CAPTION_GET(J.TEACHER_ID) CT ON J.TEACHER_ID IS NOT NULL
      WHERE J.DATE_DEL IS NULL AND J.JOURNAL_TYPE = 0 AND J.YEAR_ID = :V$YEAR_ID
      ORDER BY J.STAGE_INDEX, 3
      INTO :V$CJ_ID, :V$GRADE_ID, :S, :SS
    DO
    BEGIN
      VAL = '<tr';
      IF(NN = 1) THEN VAL = VAL || ' class="odd"';
      VAL = VAL || '>';
      VAL = VAL || '<td>' || S || '</td>';
      VAL = VAL || '<td>' || SS || '</td>';

      SELECT COUNT(*)
      FROM CJ2_JOURNAL_LESSONS L
      WHERE L.DATE_DEL IS NULL AND L.CJ_ID = :V$CJ_ID AND (L.LESSON_DATE >= :I$DATE_FROM OR :I$DATE_FROM IS NULL)
        AND (L.LESSON_DATE <= :I$DATE_TO OR :I$DATE_TO IS NULL)
      INTO :V$CNT;
      VAL = VAL || '<td>' || V$CNT || '</td>';

      SELECT COUNT(*)
      FROM CJ2_JOURNAL_LESSONS L
      JOIN CJ2_LESSON_CEC C ON C.LESSON_ID = L.OBJ_ID AND C.IS_DEL = 0
      WHERE L.DATE_DEL IS NULL AND L.CJ_ID = :V$CJ_ID AND (L.LESSON_DATE >= :I$DATE_FROM OR :I$DATE_FROM IS NULL)
        AND (L.LESSON_DATE <= :I$DATE_TO OR :I$DATE_TO IS NULL)
      INTO :V$CNT;
      VAL = VAL || '<td>' || V$CNT || '</td>';

      VAL = VAL || '</tr>';
      SUSPEND;
      N = N + 1;
      IF(NN = 0) THEN NN = 1; ELSE NN = 0;
    END

    VAL = '<tr class="tf">';
    VAL = VAL || '<td colspan="2">Всего по ОУ</td>';
    VAL = VAL || '<td class="sum">$SUM$</td>';
    VAL = VAL || '<td class="sum">$SUM$</td>';
    VAL = VAL || '</tr>';
    SUSPEND;

  END
  ELSE IF(V$CALLER_TYPE = 9) THEN
  BEGIN

    -- По классу

  END
  ELSE IF(V$CALLER_TYPE = 10) THEN
  BEGIN

    -- По ученику

  END

  -- Закрываем таблицу
  VAL = '</table></body></html>';
  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_REPORT_NX22 (
    I$USER_ID VARCHAR(40),
    I$DATE_FROM DATE,
    I$DATE_TO DATE,
    I$PARENT_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$OPTION_ID BIGINT,
    I$OPTIONS VARCHAR(1000),
    I$ZONE SMALLINT = 0)
RETURNS (
    VAL VARCHAR(4000))
AS
DECLARE VARIABLE V$CALLER_TYPE BIGINT;
DECLARE VARIABLE V$OU_LICENCE_TYPE CHAR(1);
DECLARE VARIABLE V$S1 VARCHAR(400);
DECLARE VARIABLE V$S2 VARCHAR(400);
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$OWNER_UNAME VARCHAR(100);
DECLARE VARIABLE V$OWNER_PID BIGINT;
DECLARE VARIABLE V$TEACHER_ID BIGINT;
DECLARE VARIABLE V$JOURNAL_TYPE SMALLINT;
DECLARE VARIABLE V$GRADE_ID BIGINT;
DECLARE VARIABLE V$SUBJECT_ID BIGINT;
DECLARE VARIABLE V$JOURNAL_NAME VARCHAR(400);
DECLARE VARIABLE V$STATE_ID INTEGER;
DECLARE VARIABLE V$DATE_ADD TIMESTAMP;
DECLARE VARIABLE V$RESOLVED_AT TIMESTAMP;
DECLARE VARIABLE V$MSG_TEXT VARCHAR(1000);
DECLARE VARIABLE V$ACCESS INTEGER;
DECLARE VARIABLE V$STAGE_ID1 BIGINT;
DECLARE VARIABLE V$STAGE_ID2 BIGINT;
DECLARE VARIABLE V$STAGE_ID3 BIGINT;
DECLARE VARIABLE V$STAGE_ID4 BIGINT;
DECLARE VARIABLE V$STAGE_ID5 BIGINT;
begin

  -- Школа, коллектив, персона
  SELECT TYPE_ID FROM OBJECTS WHERE OBJ_ID = :I$OBJ_ID INTO :V$CALLER_TYPE;
  SELECT STATUS FROM OU_LICENCE_TYPE INTO :V$OU_LICENCE_TYPE;

  IF(V$CALLER_TYPE = 7) THEN
  BEGIN
    FOR
      SELECT DISTINCT V49.LISTVAL_ID
      FROM LINKS L8
      JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
      WHERE L8.PARENT_ID = :I$OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
      INTO :V$OBJ_ID
    DO
    BEGIN
      IF(V$STAGE_ID1 IS NULL) THEN V$STAGE_ID1 = V$OBJ_ID;
      ELSE IF(V$STAGE_ID2 IS NULL) THEN V$STAGE_ID2 = V$OBJ_ID;
      ELSE IF(V$STAGE_ID3 IS NULL) THEN V$STAGE_ID3 = V$OBJ_ID;
      ELSE IF(V$STAGE_ID4 IS NULL) THEN V$STAGE_ID4 = V$OBJ_ID;
      ELSE IF(V$STAGE_ID5 IS NULL) THEN V$STAGE_ID5 = V$OBJ_ID;
    END
  END
  ELSE IF(V$CALLER_TYPE = 8) THEN
  BEGIN
    SELECT V49.LISTVAL_ID
    FROM VALL V49
    WHERE V49.OBJ_ID = :I$OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
    INTO :V$STAGE_ID1;
  END
  ELSE IF(V$CALLER_TYPE = 10) THEN BEGIN
    I$OBJ_ID = I$PARENT_ID;
    SELECT TYPE_ID FROM OBJECTS WHERE OBJ_ID = :I$OBJ_ID INTO :V$CALLER_TYPE;
  END

  VAL = '<!DOCTYPE html>';
  VAL = VAL || '<html lang="ru">';
  VAL = VAL || '<head>';
  VAL = VAL || '<meta charset="utf-8" />';
  VAL = VAL || '<style>';
  VAL = VAL || 'html { font-family: Tahoma, Verdana, Arial;';
  VAL = VAL || 'font-size: 10pt; ';
  VAL = VAL || '} ';
  VAL = VAL || 'table { table-layout: fixed; } ';
  VAL = VAL || '</style>';

  VAL = VAL || '</head>';
  VAL = VAL || '<body>';
  SUSPEND;

  -- Заголовок отчета
  VAL = '<div class="title1">Журнал замечаний</div>';

  VAL = VAL || '<div class="title2">' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$OBJ_ID)) || '</div>';
  V$S1 = (SELECT RESULT FROM DATE2STR(:I$DATE_FROM));
  V$S2 = (SELECT RESULT FROM DATE2STR(:I$DATE_TO));
  VAL = VAL || '<div class="title2">Период: ' || V$S1 || ' - ' || V$S2 || '</div>';

  -- Выдаем каталог журналов по классу
  /*IF(V$CALLER_TYPE = 9 AND I$OPTION_ID IS NULL) THEN
  BEGIN
    SUSPEND;
    FOR
      SELECT DISTINCT J.OBJ_ID, J.GRADE_ID, J.SUBJECT_ID
      FROM LINKS L10
      JOIN LINKS LP179 ON LP179.OBJ_ID = L10.OBJ_ID AND LP179.PARENT_TYPE_ID = 179
      JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.GRADE_ID = LP179.PARENT_ID
      WHERE L10.PARENT_ID = :I$OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      INTO :V$OBJ_ID, :V$GRADE_ID, :V$SUBJECT_ID
    DO
    BEGIN
      V$S1 = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$GRADE_ID)) || ' - ' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$SUBJECT_ID));
      VAL = '<div class="target journal" data-target="' || V$OBJ_ID || '" style="margin-bottom: 0.5rem">' || V$S1 || '</div>';
      SUSPEND;
    END

    VAL = '</body></html>';
    SUSPEND;
    EXIT;
  END*/

  -- Заголовок таблицы
  VAL = VAL || '<table class="table" cellspacing="0" cellpadding="0" style="width: 100%; table-layout: fixed">';

  VAL = VAL || '<tr class="thd">';
  VAL = VAL || '<td style="width:5%; text-wrap: wrap;">Дата записи о проверке журнала</td>';
  VAL = VAL || '<td style="width:6%; text-wrap: wrap;">ФИО проверяющего</td>';
  VAL = VAL || '<td style="width:8%; text-wrap: wrap;">Должность проверяющего</td>';
  VAL = VAL || '<td style="width:6%; text-wrap: wrap;">Учебный коллектив</td>';
  VAL = VAL || '<td style="width:6%; text-wrap: wrap;">Предмет</td>';
  VAL = VAL || '<td style="width:30%; text-wrap: wrap;">Содержание замечания</td>';
  VAL = VAL || '<td style="width:8%; text-wrap: wrap;">ФИО сотрудника, которому адресовано замечание</td>';
  VAL = VAL || '<td style="width:5%; text-wrap: wrap;">Отметка об устранении</td>';
  VAL = VAL || '</tr>';

  SUSPEND;

  -- Либо админ-директор-завуч, либо только свои замечания
  FOR
    -- По всей ОУ или конкретному журналу
    SELECT U.USER_NAME, U.OBJ_ID, A.TEACHER_ID, J.JOURNAL_TYPE, J.GRADE_ID, J.SUBJECT_ID, J.JOURNAL_NAME, A.STATE_ID, A.DATE_ADD, A.RESOLVED_AT,
      A.MSG_TEXT, JA.ACCESS_LEVEL
    FROM CJ2_AUDIT A
    JOIN CJ2_JOURNAL J ON J.OBJ_ID = A.CJ_ID AND J.DATE_DEL IS NULL AND (
      :V$CALLER_TYPE = 2 OR
      (J.GRADE_ID = :I$OBJ_ID AND :I$OPTION_ID IS NULL) OR
      ((J.STAGE_INDEX = :V$STAGE_ID1 OR J.STAGE_INDEX = :V$STAGE_ID2 OR J.STAGE_INDEX = :V$STAGE_ID3 OR J.STAGE_INDEX = :V$STAGE_ID4 OR J.STAGE_INDEX = :V$STAGE_ID5) AND :I$OPTION_ID IS NULL) OR
      J.OBJ_ID = :I$OPTION_ID
    )
    JOIN USERS U ON U.USER_ID = A.OWNER_ID
    LEFT JOIN CJ2_JOURNAL_ACCESS(:I$USER_ID, J.OBJ_ID) JA ON 1 = 1
    WHERE A.DATE_DEL IS NULL AND (JA.ACCESS_LEVEL = 1 OR (JA.ACCESS_LEVEL > 1 AND A.TEACHER_ID = JA.TEACHER_ID))
    ORDER BY A.DATE_ADD
    INTO :V$OWNER_UNAME, :V$OWNER_PID, :V$TEACHER_ID, :V$JOURNAL_TYPE, :V$GRADE_ID, :V$SUBJECT_ID, :V$JOURNAL_NAME, :V$STATE_ID, :V$DATE_ADD, :V$RESOLVED_AT,
      :V$MSG_TEXT, :V$ACCESS
  DO
  BEGIN

    VAL = '<tr class="v">';
    VAL = VAL || '<td>' || (SELECT RESULT FROM DATE2STR(:V$DATE_ADD)) || '</td>';

    IF(V$OWNER_PID IS NOT NULL) THEN
    BEGIN
      -- ФИО
      VAL = VAL || '<td style="text-wrap: wrap;">' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$OWNER_PID)) || '</td>';

      -- Должность - приоритетно основная
      V$S1 = NULL;
      SELECT FIRST 1 C.CAPTION
      FROM LINKS L15
      JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0 AND V73.VAL <= :V$DATE_ADD
      LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
      JOIN VALL V72 ON V72.OBJ_ID = L15.OBJ_ID AND V72.PARAM_ID = 72 AND V72.IS_DEL = 0
      JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
      LEFT JOIN OBJECT_CAPTION_GET(LP13.PARENT_ID) C ON 1 = 1
      WHERE L15.PARENT_ID = :V$OWNER_PID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
        AND (V74.VAL IS NULL OR V74.VAL >= :V$DATE_ADD)
      ORDER BY V72.LISTVAL_ID, V73.VAL
      INTO :V$S1;

      VAL = VAL || '<td style="text-wrap: wrap;">' || COALESCE(V$S1, '-') || '</td>';
    END
    ELSE
    BEGIN
      VAL = VAL || '<td colspan=2>' || COALESCE(V$OWNER_UNAME, '???') || '</td>';
    END

    IF(V$JOURNAL_TYPE = 0) THEN
    BEGIN
      VAL = VAL || '<td>' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$GRADE_ID)) || '</td>';
      IF(V$SUBJECT_ID IS NULL) THEN VAL = VAL || '<td></td>';
      ELSE VAL = VAL || '<td style="text-wrap: wrap;">' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$SUBJECT_ID)) || '</td>';
    END
    ELSE
    BEGIN
      VAL = VAL || '<td colspan=2 style="text-wrap: wrap;">' || V$JOURNAL_NAME || '</td>';
    END

    VAL = VAL || '<td style="text-wrap: wrap;">' || (SELECT VAL FROM ESCAPE_STR(:V$MSG_TEXT)) || '</td>';
    VAL = VAL || '<td style="text-wrap: wrap;">' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$TEACHER_ID)) || '</td>';

    IF(V$STATE_ID = 0) THEN V$S1 = '';
    ELSE IF(V$STATE_ID = 1) THEN V$S1 = 'Устр. ' || (SELECT RESULT FROM DATE2STR(:V$RESOLVED_AT));
    ELSE IF(V$STATE_ID = 2) THEN V$S1 = 'Пров. ' || (SELECT RESULT FROM DATE2STR(:V$RESOLVED_AT));
    ELSE IF(V$STATE_ID = 3) THEN V$S1 = 'Отменено';
    ELSE IF(V$STATE_ID = 4) THEN V$S1 = 'Закрыто';
    ELSE V$S1 = '';

    VAL = VAL || '<td style="text-wrap: wrap;">' || COALESCE(V$S1, '?') || '</td>';

    VAL = VAL || '</tr>';

    SUSPEND;

  END

  VAL = '</table></body></html>';
  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_REPORT_NX2_OU (
    I$USER_ID VARCHAR(40),
    I$DATE_FROM DATE,
    I$DATE_TO DATE,
    I$PARENT_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$OPTION_ID BIGINT,
    I$OPTIONS VARCHAR(1000),
    I$ZONE SMALLINT = 0)
RETURNS (
    VAL VARCHAR(4000))
AS
declare variable V$USER_TYPE smallint;
declare variable V$CJ_ID bigint;
declare variable V$COST double precision;
declare variable V$S1 varchar(400);
declare variable V$S2 varchar(400);
declare variable V$DATE date;
declare variable V$OBJ_ID bigint;
declare variable N90 integer;
declare variable N91 integer;
declare variable N92 integer;
declare variable N93 integer;
declare variable N94 integer;
declare variable TN90 integer;
declare variable TN91 integer;
declare variable TN92 integer;
declare variable TN93 integer;
declare variable TN94 integer;
declare variable V$OU_LICENCE_TYPE char(1);
begin

  SELECT STATUS FROM OU_LICENCE_TYPE INTO :V$OU_LICENCE_TYPE;

  -- ОУ - доступно только для админа
  FOR
      SELECT DISTINCT L.LESSON_DATE
      FROM CJ2_JOURNAL_LESSONS L
      JOIN CJ2_CONTROL C ON C.DATE_DEL IS NULL AND C.LESSON_ID = L.OBJ_ID AND C.CONTROL_TYPE_ID = 0
      JOIN CJ2_MARK M ON M.DATE_DEL IS NULL AND M.CONTROL_ID = C.CONTROL_ID AND M.MARK_TYPE_ID BETWEEN 90 AND 94
      JOIN CJ2_JOURNAL J ON J.OBJ_ID = L.CJ_ID AND J.DATE_DEL IS NULL AND J.JOURNAL_TYPE = 0
      -- LEFT JOIN CJ2_JOURNAL_ACCESS(:I$USER_ID, J.OBJ_ID) A ON 1 = 1
      WHERE L.DATE_DEL IS NULL AND L.IS_COMPLETED > 0 AND L.LESSON_DATE BETWEEN :I$DATE_FROM AND :I$DATE_TO
      INTO :V$DATE
  DO
  BEGIN
      INSERT INTO CJ_REPORT4_TEMP (DATE_ID, CLASS_ID) VALUES (:V$DATE, 0);
  END

      -- Таблица: класс, даты, итоги по видам пропусков
      VAL = '<tr class="thd">';
      IF(V$OU_LICENCE_TYPE = 'O') THEN VAL = VAL || '<td class="sortable text">Класс</td>'; ELSE VAL = VAL || '<td class="sortable text">Группа</td>';
      SUSPEND;
      FOR SELECT DATE_ID FROM CJ_REPORT4_TEMP ORDER BY 1 INTO :V$DATE DO
      BEGIN
          VAL = '<td>' || (SELECT RESULT FROM DATE2STR(:V$DATE, 2)) || '</td>';
          SUSPEND;
      END
      VAL = '<td class="t t1 sortable value">УВ</td>';
      VAL = VAL || '<td class="t sortable value">НУВ</td>';
      VAL = VAL || '<td class="t sortable value">БОЛ</td>';
      VAL = VAL || '<td class="t sortable value">НЕИЗВ</td>';
      VAL = VAL || '<td class="t sortable value">&sum;&nbsp;Пропуск</td>';
      VAL = VAL || '<td class="t sortable value">Опозд</td>';
      VAL = VAL || '</tr>';
      SUSPEND;

      FOR
          SELECT L9.OBJ_ID, LV.COST, C.CAPTION, L7.OBJ_ID || ',' || L8.OBJ_ID || ',' || L9.OBJ_ID
          FROM LINKS L7
          JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
          JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
          JOIN LISTVALS LV ON LV.LISTVAL_ID = V49.LISTVAL_ID
          JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
          LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C ON 1 = 1
          WHERE L7.PARENT_ID = :I$OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
          -- УДОД
          UNION
          SELECT L243.OBJ_ID, 0, CL.CAPTION || ' - ' || C.CAPTION, L242.OBJ_ID || ',' || L243.OBJ_ID
          FROM LINKS L242
          JOIN LINKS L243 ON L243.PARENT_ID = L242.OBJ_ID AND L243.OBJ_TYPE_ID = 243 AND L243.DATE_DEL IS NULL
          LEFT JOIN OBJECT_CAPTION_GET(L242.OBJ_ID) CL ON 1 = 1
          LEFT JOIN OBJECT_CAPTION_GET(L243.OBJ_ID) C ON 1 = 1
          WHERE L242.PARENT_ID = :I$OBJ_ID AND L242.OBJ_TYPE_ID = 242 AND L242.DATE_DEL IS NULL
          UNION
          SELECT L243.OBJ_ID, 0, CL.CAPTION || ' - ' || C.CAPTION, L211.OBJ_ID || ',' || L242.OBJ_ID || ',' || L243.OBJ_ID
          FROM LINKS L211
          JOIN LINKS L242 ON L242.PARENT_ID = L211.OBJ_ID AND L242.OBJ_TYPE_ID = 242 AND L242.DATE_DEL IS NULL
          JOIN LINKS L243 ON L243.PARENT_ID = L242.OBJ_ID AND L243.OBJ_TYPE_ID = 243 AND L243.DATE_DEL IS NULL
          LEFT JOIN OBJECT_CAPTION_GET(L242.OBJ_ID) CL ON 1 = 1
          LEFT JOIN OBJECT_CAPTION_GET(L243.OBJ_ID) C ON 1 = 1
          WHERE L211.PARENT_ID = :I$OBJ_ID AND L211.OBJ_TYPE_ID = 211 AND L211.DATE_DEL IS NULL
          ORDER BY 2, 3
          INTO :V$OBJ_ID, :V$COST, :V$S1, :V$S2
      DO
      BEGIN
          VAL = '<tr class="v">';
          VAL = VAL || '<td><div class="target grade" data-target="' || V$S2 || '">' || V$S1 || '</div></td>';
          SUSPEND;
          TN90 = 0; TN91 = 0; TN92 = 0; TN93 = 0; TN94 = 0;
          FOR SELECT DATE_ID FROM CJ_REPORT4_TEMP ORDER BY 1 INTO :V$DATE DO
          BEGIN
              SELECT COUNT(*)
              FROM CJ2_JOURNAL_LESSONS L
              JOIN CJ2_CONTROL C ON C.DATE_DEL IS NULL AND C.LESSON_ID = L.OBJ_ID AND C.CONTROL_TYPE_ID = 0
              JOIN CJ2_MARK M ON M.DATE_DEL IS NULL AND M.CONTROL_ID = C.CONTROL_ID AND M.MARK_TYPE_ID = 90
              JOIN LINKS L10 ON L10.OBJ_ID = M.STUDENT_ID AND L10.PARENT_ID = :V$OBJ_ID AND L10.DATE_DEL IS NULL
              JOIN CJ2_JOURNAL J ON J.OBJ_ID = L.CJ_ID AND J.DATE_DEL IS NULL AND J.JOURNAL_TYPE = 0
              WHERE L.DATE_DEL IS NULL AND L.IS_COMPLETED > 0 AND L.LESSON_DATE = :V$DATE 
              INTO :N90;

              SELECT COUNT(*)
              FROM CJ2_JOURNAL_LESSONS L
              JOIN CJ2_CONTROL C ON C.DATE_DEL IS NULL AND C.LESSON_ID = L.OBJ_ID AND C.CONTROL_TYPE_ID = 0
              JOIN CJ2_MARK M ON M.DATE_DEL IS NULL AND M.CONTROL_ID = C.CONTROL_ID AND M.MARK_TYPE_ID = 91
              JOIN LINKS L10 ON L10.OBJ_ID = M.STUDENT_ID AND L10.PARENT_ID = :V$OBJ_ID AND L10.DATE_DEL IS NULL
              JOIN CJ2_JOURNAL J ON J.OBJ_ID = L.CJ_ID AND J.DATE_DEL IS NULL AND J.JOURNAL_TYPE = 0
              WHERE L.DATE_DEL IS NULL AND L.IS_COMPLETED > 0 AND L.LESSON_DATE = :V$DATE 
              INTO :N91;

              SELECT COUNT(*)
              FROM CJ2_JOURNAL_LESSONS L
              JOIN CJ2_CONTROL C ON C.DATE_DEL IS NULL AND C.LESSON_ID = L.OBJ_ID AND C.CONTROL_TYPE_ID = 0
              JOIN CJ2_MARK M ON M.DATE_DEL IS NULL AND M.CONTROL_ID = C.CONTROL_ID AND M.MARK_TYPE_ID = 92
              JOIN LINKS L10 ON L10.OBJ_ID = M.STUDENT_ID AND L10.PARENT_ID = :V$OBJ_ID AND L10.DATE_DEL IS NULL
              JOIN CJ2_JOURNAL J ON J.OBJ_ID = L.CJ_ID AND J.DATE_DEL IS NULL AND J.JOURNAL_TYPE = 0
              WHERE L.DATE_DEL IS NULL AND L.IS_COMPLETED > 0 AND L.LESSON_DATE = :V$DATE 
              INTO :N92;

              SELECT COUNT(*)
              FROM CJ2_JOURNAL_LESSONS L
              JOIN CJ2_CONTROL C ON C.DATE_DEL IS NULL AND C.LESSON_ID = L.OBJ_ID AND C.CONTROL_TYPE_ID = 0
              JOIN CJ2_MARK M ON M.DATE_DEL IS NULL AND M.CONTROL_ID = C.CONTROL_ID AND M.MARK_TYPE_ID = 93
              JOIN LINKS L10 ON L10.OBJ_ID = M.STUDENT_ID AND L10.PARENT_ID = :V$OBJ_ID AND L10.DATE_DEL IS NULL
              JOIN CJ2_JOURNAL J ON J.OBJ_ID = L.CJ_ID AND J.DATE_DEL IS NULL AND J.JOURNAL_TYPE = 0
              WHERE L.DATE_DEL IS NULL AND L.IS_COMPLETED > 0 AND L.LESSON_DATE = :V$DATE 
              INTO :N93;

              SELECT COUNT(*)
              FROM CJ2_JOURNAL_LESSONS L
              JOIN CJ2_CONTROL C ON C.DATE_DEL IS NULL AND C.LESSON_ID = L.OBJ_ID AND C.CONTROL_TYPE_ID = 0
              JOIN CJ2_MARK M ON M.DATE_DEL IS NULL AND M.CONTROL_ID = C.CONTROL_ID AND M.MARK_TYPE_ID = 94
              JOIN LINKS L10 ON L10.OBJ_ID = M.STUDENT_ID AND L10.PARENT_ID = :V$OBJ_ID AND L10.DATE_DEL IS NULL
              JOIN CJ2_JOURNAL J ON J.OBJ_ID = L.CJ_ID AND J.DATE_DEL IS NULL AND J.JOURNAL_TYPE = 0
              WHERE L.DATE_DEL IS NULL AND L.IS_COMPLETED > 0 AND L.LESSON_DATE = :V$DATE 
              INTO :N94;

              VAL = '<td>' || (N90 + N91 + N92 + N93 + N94) || '</td>';
              SUSPEND;
              TN90 = TN90 + N90;
              TN91 = TN91 + N91;
              TN92 = TN92 + N92;
              TN93 = TN93 + N93;
              TN94 = TN94 + N94;
          END
          VAL = '<td class="t t1">' || TN93 || '</td>';
          VAL = VAL || '<td class="t">' || TN94 || '</td>';
          VAL = VAL || '<td class="t">' || TN92 || '</td>';
          VAL = VAL || '<td class="t">' || TN91 || '</td>';
          VAL = VAL || '<td class="t">' || (TN91 + TN92 + TN93 + TN94) || '</td>';
          VAL = VAL || '<td class="t">' || TN90 || '</td>';
          VAL = VAL || '</tr>';
          SUSPEND;
      END

      -- Итоги
      VAL = '<tr class="v total">';
      VAL = VAL || '<td>Всего</td>';
      SUSPEND;
      TN90 = 0; TN91 = 0; TN92 = 0; TN93 = 0; TN94 = 0;
      FOR SELECT DATE_ID FROM CJ_REPORT4_TEMP ORDER BY 1 INTO :V$DATE DO
      BEGIN
          SELECT COUNT(*)
          FROM CJ2_JOURNAL_LESSONS L
          JOIN CJ2_CONTROL C ON C.DATE_DEL IS NULL AND C.LESSON_ID = L.OBJ_ID AND C.CONTROL_TYPE_ID = 0
          JOIN CJ2_MARK M ON M.DATE_DEL IS NULL AND M.CONTROL_ID = C.CONTROL_ID AND M.MARK_TYPE_ID = 90
          JOIN LINKS L10 ON L10.OBJ_ID = M.STUDENT_ID AND L10.PARENT_TYPE_ID = 9 AND L10.DATE_DEL IS NULL
          JOIN CJ2_JOURNAL J ON J.OBJ_ID = L.CJ_ID AND J.DATE_DEL IS NULL
          WHERE L.DATE_DEL IS NULL AND L.IS_COMPLETED > 0 AND L.LESSON_DATE = :V$DATE
          INTO :N90;

          SELECT COUNT(*)
          FROM CJ2_JOURNAL_LESSONS L
          JOIN CJ2_CONTROL C ON C.DATE_DEL IS NULL AND C.LESSON_ID = L.OBJ_ID AND C.CONTROL_TYPE_ID = 0
          JOIN CJ2_MARK M ON M.DATE_DEL IS NULL AND M.CONTROL_ID = C.CONTROL_ID AND M.MARK_TYPE_ID = 91
          JOIN LINKS L10 ON L10.OBJ_ID = M.STUDENT_ID AND L10.PARENT_TYPE_ID = 9 AND L10.DATE_DEL IS NULL
          JOIN CJ2_JOURNAL J ON J.OBJ_ID = L.CJ_ID AND J.DATE_DEL IS NULL
          WHERE L.DATE_DEL IS NULL AND L.IS_COMPLETED > 0 AND L.LESSON_DATE = :V$DATE
          INTO :N91;

          SELECT COUNT(*)
          FROM CJ2_JOURNAL_LESSONS L
          JOIN CJ2_CONTROL C ON C.DATE_DEL IS NULL AND C.LESSON_ID = L.OBJ_ID AND C.CONTROL_TYPE_ID = 0
          JOIN CJ2_MARK M ON M.DATE_DEL IS NULL AND M.CONTROL_ID = C.CONTROL_ID AND M.MARK_TYPE_ID = 92
          JOIN LINKS L10 ON L10.OBJ_ID = M.STUDENT_ID AND L10.PARENT_TYPE_ID = 9 AND L10.DATE_DEL IS NULL
          JOIN CJ2_JOURNAL J ON J.OBJ_ID = L.CJ_ID AND J.DATE_DEL IS NULL
          WHERE L.DATE_DEL IS NULL AND L.IS_COMPLETED > 0 AND L.LESSON_DATE = :V$DATE
          INTO :N92;

          SELECT COUNT(*)
          FROM CJ2_JOURNAL_LESSONS L
          JOIN CJ2_CONTROL C ON C.DATE_DEL IS NULL AND C.LESSON_ID = L.OBJ_ID AND C.CONTROL_TYPE_ID = 0
          JOIN CJ2_MARK M ON M.DATE_DEL IS NULL AND M.CONTROL_ID = C.CONTROL_ID AND M.MARK_TYPE_ID = 93
          JOIN LINKS L10 ON L10.OBJ_ID = M.STUDENT_ID AND L10.PARENT_TYPE_ID = 9 AND L10.DATE_DEL IS NULL
          JOIN CJ2_JOURNAL J ON J.OBJ_ID = L.CJ_ID AND J.DATE_DEL IS NULL
          WHERE L.DATE_DEL IS NULL AND L.IS_COMPLETED > 0 AND L.LESSON_DATE = :V$DATE
          INTO :N93;

          SELECT COUNT(*)
          FROM CJ2_JOURNAL_LESSONS L
          JOIN CJ2_CONTROL C ON C.DATE_DEL IS NULL AND C.LESSON_ID = L.OBJ_ID AND C.CONTROL_TYPE_ID = 0
          JOIN CJ2_MARK M ON M.DATE_DEL IS NULL AND M.CONTROL_ID = C.CONTROL_ID AND M.MARK_TYPE_ID = 94
          JOIN LINKS L10 ON L10.OBJ_ID = M.STUDENT_ID AND L10.PARENT_TYPE_ID = 9 AND L10.DATE_DEL IS NULL
          JOIN CJ2_JOURNAL J ON J.OBJ_ID = L.CJ_ID AND J.DATE_DEL IS NULL
          WHERE L.DATE_DEL IS NULL AND L.IS_COMPLETED > 0 AND L.LESSON_DATE = :V$DATE
          INTO :N94;

          VAL = '<td>' || (N90 + N91 + N92 + N93 + N94) || '</td>';
          SUSPEND;
          TN90 = TN90 + N90;
          TN91 = TN91 + N91;
          TN92 = TN92 + N92;
          TN93 = TN93 + N93;
          TN94 = TN94 + N94;
      END
      VAL = '<td class="t t1">' || TN93 || '</td>';
      VAL = VAL || '<td class="t">' || TN94 || '</td>';
      VAL = VAL || '<td class="t">' || TN92 || '</td>';
      VAL = VAL || '<td class="t">' || TN91 || '</td>';
      VAL = VAL || '<td class="t">' || (TN91 + TN92 + TN93 + TN94) || '</td>';
      VAL = VAL || '<td class="t">' || TN90 || '</td>';
      VAL = VAL || '</tr>';
      SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_REPORT_NX300 (
    I$USER_ID VARCHAR(40),
    I$DATE_FROM DATE,
    I$DATE_TO DATE,
    I$PARENT_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$OPTION_ID BIGINT,
    I$OPTIONS VARCHAR(1000),
    I$ZONE SMALLINT = 0)
RETURNS (
    VAL VARCHAR(4000))
AS
declare variable V$CALLER_TYPE bigint;
declare variable V$USER_TYPE smallint;
declare variable V$OU_LICENCE_TYPE varchar(2);
declare variable V$SP varchar(400);
declare variable V$S1 varchar(400);
declare variable V$S2 varchar(400);
declare variable V$S3 varchar(400);
declare variable V$FT varchar(100);
declare variable V$M varchar(100);
declare variable V$D varchar(20);
declare variable V$G5 smallint;
declare variable V$G4 smallint;
declare variable V$G3 smallint;
declare variable V$G2 smallint;
declare variable V$G1 smallint;
declare variable V$GN5 smallint;
declare variable V$PERSON_ID bigint;
declare variable V$SUBJECT_ID bigint;
declare variable V$DATE_TO date;
declare variable V$THRESHOLD varchar(100);
declare variable V$TH2 float;
begin

  -- Школа, коллектив, персона
  SELECT TYPE_ID FROM OBJECTS WHERE OBJ_ID = :I$OBJ_ID INTO :V$CALLER_TYPE;
  SELECT STATUS FROM OU_LICENCE_TYPE INTO :V$OU_LICENCE_TYPE;

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;
  SELECT USER_TYPE FROM USERS WHERE USER_ID = :I$USER_ID INTO :V$USER_TYPE;

  V$DATE_TO = DATEADD(7 DAY TO I$DATE_TO);

  -- Вытаскиваем порог оценки
  FOR
    SELECT TAKEN
    FROM PARSING_STRING_GET(:I$OPTIONS, ';')
    INTO :V$S1
  DO
  BEGIN
    IF(SUBSTRING(V$S1 FROM 1 FOR 10) = 'THRESHOLD=') THEN V$THRESHOLD = SUBSTRING(V$S1 FROM 11);
  END
  IF(V$THRESHOLD = '' OR V$THRESHOLD = '-') THEN V$THRESHOLD = NULL;

  VAL = '<!DOCTYPE html>';
  VAL = VAL || '<html lang="ru">';
  VAL = VAL || '<head>';
  VAL = VAL || '<meta charset="utf-8" />';
  VAL = VAL || '<style>';
  VAL = VAL || 'html { font-family: Tahoma, Verdana, Arial;';
  VAL = VAL || 'font-size: 10pt; ';
  VAL = VAL || '} ';
  VAL = VAL || '.title1 { font-size: 150%;';
  VAL = VAL || 'padding: 8px;';
  VAL = VAL || 'margin-bottom: 4px;';
  VAL = VAL || 'font-weight: bold;';
  VAL = VAL || 'background-color: #D4E157;';
  VAL = VAL || '} ';
  VAL = VAL || '.title2 { ';
  VAL = VAL || 'padding: 4px;';
  VAL = VAL || 'font-weight: bold;';
  VAL = VAL || '} ';
  VAL = VAL || '</style>';

  VAL = VAL || '</head>';
  VAL = VAL || '<body>';
  SUSPEND;

  -- Заголовок отчета
  VAL = '<div class="title1">Списки обучающихся по группам успеваемости</div>';

  VAL = VAL || '<div class="title2">';
  IF (:V$CALLER_TYPE = 10) THEN VAL = VAL || (SELECT NAME_FULL FROM UT_PERSON_DESC(:I$OBJ_ID, :I$ZONE, 1));      -- обущающийся
                           ELSE VAL = VAL || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$OBJ_ID));
  VAL = VAL || '</div>';

  IF(I$OPTION_ID IS NOT NULL) THEN
  BEGIN
    V$S1 = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$OPTION_ID));
    VAL = VAL || '<div class="title2">В разрезе: ' || COALESCE(V$S1, '???') || '</div>';
  END

  V$S1 = (SELECT RESULT FROM DATE2STR(:I$DATE_FROM));
  V$S2 = (SELECT RESULT FROM DATE2STR(:I$DATE_TO));
  VAL = VAL || '<div class="title2">Период: ' || V$S1 || ' - ' || V$S2 || '</div>';
  SUSPEND;

  -- Заголовок таблицы
  -- sort = сортировать внутри секций
  -- arrange = перераспределить по секциям
  VAL = '<div class="title3">Отличники</div>';
  VAL = VAL || '<table class="table" cellspacing="0" cellpadding="0" data-flags="sort arrange" style="min-width: 50%">';
  VAL = VAL || '<thead>';
  VAL = VAL || '<tr class="thd">';
    VAL = VAL || '<td>Учебный коллектив</td>';
    VAL = VAL || '<td>ФИО</td>';
    VAL = VAL || '<td>Кол-во оценок</td>';
  VAL = VAL || '</tr>';
  VAL = VAL || '</thead>';
  VAL = VAL || '<tbody data-group="5" id="g-5"></tbody>';
  VAL = VAL || '</table>';
  SUSPEND;

  VAL = '<div class="title3">Неуспевающие</div>';
  VAL = VAL || '<table class="table" cellspacing="0" cellpadding="0" data-flags="sort arrange" style="min-width: 50%">';
  VAL = VAL || '<thead>';
  VAL = VAL || '<tr class="thd">';
    VAL = VAL || '<td>Учебный коллектив</td>';
    VAL = VAL || '<td>ФИО</td>';
    VAL = VAL || '<td>Оценка</td>';
    VAL = VAL || '<td>Этап</td>';
    VAL = VAL || '<td>Предмет</td>';
    VAL = VAL || '<td>Преподаватель</td>';
  VAL = VAL || '</tr>';
  VAL = VAL || '</thead>';
  VAL = VAL || '<tbody data-group="2" id="g-2"></tbody>';
  VAL = VAL || '</table>';
  SUSPEND;

  VAL = '<div class="title3">Неаттестованные</div>';
  VAL = VAL || '<table class="table" cellspacing="0" cellpadding="0" data-flags="sort arrange" style="min-width: 50%">';
  VAL = VAL || '<thead>';
  VAL = VAL || '<tr class="thd">';
    VAL = VAL || '<td>Учебный коллектив</td>';
    VAL = VAL || '<td>ФИО</td>';
    VAL = VAL || '<td>Оценка</td>';
    VAL = VAL || '<td>Этап</td>';
    VAL = VAL || '<td>Предмет</td>';
    VAL = VAL || '<td>Преподаватель</td>';
  VAL = VAL || '</tr>';
  VAL = VAL || '</thead>';
  VAL = VAL || '<tbody data-group="na" id="g-na"></tbody>';
  VAL = VAL || '</table>';
  SUSPEND;

  VAL = '<div class="title3">Недоработавшие</div>';
  VAL = VAL || '<table class="table" cellspacing="0" cellpadding="0" data-flags="sort arrange" style="min-width: 50%">';
  VAL = VAL || '<thead>';
  VAL = VAL || '<tr class="thd">';
    VAL = VAL || '<td>Учебный коллектив</td>';
    VAL = VAL || '<td>ФИО</td>';
    VAL = VAL || '<td>Оценка</td>';
    VAL = VAL || '<td>Этап</td>';
    VAL = VAL || '<td>Предмет</td>';
    VAL = VAL || '<td>Преподаватель</td>';
  VAL = VAL || '</tr>';
  VAL = VAL || '</thead>';
  VAL = VAL || '<tbody data-group="nx" id="g-nx"></tbody>';
  VAL = VAL || '</table>';
  SUSPEND;

  VAL = '<table id="data" style="display: none">';
  SUSPEND;

  -- Выбираем всех обучающихся, которые числились в течение выбранного периода времени
  -- если стоит фильтр по классу - накладываем его сразу
  -- сортировка по фамилии выполняется уже после получения отчета на фронте
  FOR
    SELECT DISTINCT M.PERSON_ID
    FROM PERSON_MOVEMENTS M
    JOIN LINKS LP8 ON LP8.OBJ_ID = M.GROUP_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
    JOIN LINKS LP7 ON LP7.OBJ_ID = LP8.PARENT_ID AND LP7.PARENT_TYPE_ID = 7 AND LP7.DATE_DEL IS NULL
    WHERE M.DATE_DEL IS NULL AND M.GROUP_TYPE_ID IN (9, 187)
      AND (:V$CALLER_TYPE <> 10 OR M.PERSON_ID = :I$OBJ_ID) -- фильтр по конкретному ученику 
      AND (:V$CALLER_TYPE NOT IN (9, 187) OR M.GROUP_ID = :I$OBJ_ID) -- фильтр по классу
      AND (:V$CALLER_TYPE <> 8 OR LP8.PARENT_ID = :I$OBJ_ID) -- фильтр по параллели
      AND (:V$CALLER_TYPE <> 7 OR LP7.PARENT_ID = :I$OBJ_ID) -- фильтр по уровню
      AND M.DATE_IN <= :I$DATE_TO AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :I$DATE_FROM)
    INTO :V$PERSON_ID
  DO
  BEGIN

    V$SP = NULL;

    -- В каком классе был на конец периода
    SELECT FIRST 1 M.NAME_IN
    FROM PERSON_MOVEMENTS M
    WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :V$PERSON_ID AND M.GROUP_TYPE_ID IN (9, 187)
      AND M.DATE_IN <= :I$DATE_TO AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :I$DATE_FROM)
    ORDER BY M.DATE_OUT DESC NULLS FIRST
    INTO :V$S1;

    -- Не аттестованные - если ли отметки НАУ/НАН ?
    FOR
      SELECT C.CAPTION, Pt.NAME_FULL, --CT.CAPTION,
             MT.MARK_SHORTNAME, D.RESULT, FT.VAL, J.SUBJECT_ID
      FROM CJ2_MARK M
      JOIN CJ2_MARK_TYPE MT ON MT.MARK_TYPE_ID = M.MARK_TYPE_ID
      JOIN CJ2_JOURNAL_FINALS F ON F.OBJ_ID = M.FINAL_ID
      JOIN CJ2_JOURNAL J ON J.OBJ_ID = F.CJ_ID
      LEFT JOIN OBJECT_CAPTION_GET(J.SUBJECT_ID) C ON 1 = 1
      LEFT JOIN UT_PERSON_DESC(COALESCE(F.TEACHER_ID, J.TEACHER_ID), :I$ZONE, 1) Pt ON 1 = 1 --Redmine #1060 --OBJECT_CAPTION_GET(COALESCE(F.TEACHER_ID, J.TEACHER_ID)) CT ON 1 = 1
      LEFT JOIN LISTVAL_TEXT(F.FINAL_TYPE) FT ON 1 = 1
      LEFT JOIN DATE2STR(F.FINAL_DATE) D ON 1 = 1
      WHERE M.DATE_DEL IS NULL AND M.STUDENT_ID = :V$PERSON_ID AND M.MARK_TYPE_ID IN (103, 104)
        AND F.FINAL_DATE >= :I$DATE_FROM AND F.FINAL_DATE <= :V$DATE_TO
      ORDER BY C.CAPTION, F.FINAL_DATE
      INTO :V$S2, :V$S3, :V$M, :V$D, :V$FT, :V$SUBJECT_ID
    DO
    BEGIN
      IF(V$SP IS NULL) THEN V$SP = (SELECT NAME_FULL FROM UT_PERSON_DESC(:V$PERSON_ID, :I$ZONE, 1)); --Redmine #1060 --(SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$PERSON_ID, 23));

      VAL = '<tr data-group="na">';
        VAL = VAL || '<td>' || (SELECT VAL FROM ESCAPE_STR(:V$S1)) || '</td>';
        VAL = VAL || '<td data-sort="1">' || (SELECT VAL FROM ESCAPE_STR(:V$SP)) || '</td>';
        VAL = VAL || '<td>' || V$M || '</td>';
        VAL = VAL || '<td>' || V$FT || ' (' || V$D || ')</td>';
        VAL = VAL || '<td class="target subject" data-target="' || V$SUBJECT_ID || '">' || (SELECT VAL FROM ESCAPE_STR(:V$S2)) || '</td>';
        VAL = VAL || '<td>' || (SELECT VAL FROM ESCAPE_STR(:V$S3)) || '</td>';
      VAL = VAL || '</tr>';
      SUSPEND;
    END

    -- Не успевающие - с итоговыми оценками < 2.5, а также со средним баллом ниже 2.5
    FOR
      SELECT C.CAPTION, P.NAME_FULL --CT.CAPTION
            , MT.MARK_SHORTNAME, D.RESULT, FT.VAL, J.SUBJECT_ID
      FROM CJ2_MARK M
      JOIN CJ2_MARK_TYPE MT ON MT.MARK_TYPE_ID = M.MARK_TYPE_ID
      JOIN CJ2_JOURNAL_FINALS F ON F.OBJ_ID = M.FINAL_ID
      JOIN CJ2_JOURNAL J ON J.OBJ_ID = F.CJ_ID
      LEFT JOIN OBJECT_CAPTION_GET(J.SUBJECT_ID) C ON 1 = 1
      LEFT JOIN UT_PERSON_DESC(COALESCE(F.TEACHER_ID, J.TEACHER_ID), :I$ZONE, 1) P ON 1 = 1 --Redmine #1060 --OBJECT_CAPTION_GET(COALESCE(F.TEACHER_ID, J.TEACHER_ID)) CT ON 1 = 1
      LEFT JOIN LISTVAL_TEXT(F.FINAL_TYPE) FT ON 1 = 1
      LEFT JOIN DATE2STR(F.FINAL_DATE) D ON 1 = 1
      WHERE M.DATE_DEL IS NULL AND M.STUDENT_ID = :V$PERSON_ID AND MT.MARK_COST < 2.5 AND MT.PARENT_ID NOT IN (100)
        AND F.FINAL_DATE >= :I$DATE_FROM AND F.FINAL_DATE <= :V$DATE_TO
      ORDER BY C.CAPTION, F.FINAL_DATE
      INTO :V$S2, :V$S3, :V$M, :V$D, :V$FT, :V$SUBJECT_ID
    DO
    BEGIN
      IF(V$SP IS NULL) THEN V$SP = (SELECT NAME_FULL FROM UT_PERSON_DESC(:V$PERSON_ID, :I$ZONE, 1)); --Redmine #1060 --(SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$PERSON_ID, 23));

      VAL = '<tr data-group="2">';
        VAL = VAL || '<td>' || (SELECT VAL FROM ESCAPE_STR(:V$S1)) || '</td>';
        VAL = VAL || '<td data-sort="1">' || (SELECT VAL FROM ESCAPE_STR(:V$SP)) || '</td>';
        VAL = VAL || '<td>' || V$M || '</td>';
        VAL = VAL || '<td>' || V$FT || ' (' || V$D || ')</td>';
        VAL = VAL || '<td class="target subject" data-target="' || V$SUBJECT_ID || '">' || (SELECT VAL FROM ESCAPE_STR(:V$S2)) || '</td>';
        VAL = VAL || '<td>' || (SELECT VAL FROM ESCAPE_STR(:V$S3)) || '</td>';
      VAL = VAL || '</tr>';
      SUSPEND;
    END

    -- Отличники - итоговые отметки >= 4.5, и нет оценок < 4.5
    SELECT COUNT(*)
    FROM CJ2_MARK M
    JOIN CJ2_MARK_TYPE MT ON MT.MARK_TYPE_ID = M.MARK_TYPE_ID
    JOIN CJ2_JOURNAL_FINALS F ON F.OBJ_ID = M.FINAL_ID
    WHERE M.DATE_DEL IS NULL AND M.STUDENT_ID = :V$PERSON_ID AND MT.MARK_COST >= 4.5 AND MT.PARENT_ID NOT IN (100)
      AND F.FINAL_DATE >= :I$DATE_FROM AND F.FINAL_DATE <= :V$DATE_TO
    INTO :V$G5;

    SELECT COUNT(*)
    FROM CJ2_MARK M
    JOIN CJ2_MARK_TYPE MT ON MT.MARK_TYPE_ID = M.MARK_TYPE_ID
    JOIN CJ2_JOURNAL_FINALS F ON F.OBJ_ID = M.FINAL_ID
    WHERE M.DATE_DEL IS NULL AND M.STUDENT_ID = :V$PERSON_ID AND MT.MARK_COST >= 3.5 AND MT.MARK_COST < 4.5 AND MT.PARENT_ID NOT IN (100)
      AND F.FINAL_DATE >= :I$DATE_FROM AND F.FINAL_DATE <= :V$DATE_TO
    INTO :V$G4;

    SELECT COUNT(*)
    FROM CJ2_MARK M
    JOIN CJ2_MARK_TYPE MT ON MT.MARK_TYPE_ID = M.MARK_TYPE_ID
    JOIN CJ2_JOURNAL_FINALS F ON F.OBJ_ID = M.FINAL_ID
    WHERE M.DATE_DEL IS NULL AND M.STUDENT_ID = :V$PERSON_ID AND MT.MARK_COST >= 2.5 AND MT.MARK_COST < 3.5 AND MT.PARENT_ID NOT IN (100)
      AND F.FINAL_DATE >= :I$DATE_FROM AND F.FINAL_DATE <= :V$DATE_TO
    INTO :V$G3;

    SELECT COUNT(*)
    FROM CJ2_MARK M
    JOIN CJ2_MARK_TYPE MT ON MT.MARK_TYPE_ID = M.MARK_TYPE_ID
    JOIN CJ2_JOURNAL_FINALS F ON F.OBJ_ID = M.FINAL_ID
    WHERE M.DATE_DEL IS NULL AND M.STUDENT_ID = :V$PERSON_ID AND MT.MARK_COST >= 1.5 AND MT.MARK_COST < 2.5 AND MT.PARENT_ID NOT IN (100)
      AND F.FINAL_DATE >= :I$DATE_FROM AND F.FINAL_DATE <= :V$DATE_TO
    INTO :V$G2;

    SELECT COUNT(*)
    FROM CJ2_MARK M
    JOIN CJ2_MARK_TYPE MT ON MT.MARK_TYPE_ID = M.MARK_TYPE_ID
    JOIN CJ2_JOURNAL_FINALS F ON F.OBJ_ID = M.FINAL_ID
    WHERE M.DATE_DEL IS NULL AND M.STUDENT_ID = :V$PERSON_ID AND MT.MARK_COST < 1.5 AND MT.PARENT_ID NOT IN (100)
      AND F.FINAL_DATE >= :I$DATE_FROM AND F.FINAL_DATE <= :V$DATE_TO
    INTO :V$G1;

    V$GN5 = V$G4 + V$G3 + V$G2 + V$G1;

    IF(V$G5 >= 3 AND V$GN5 = 0) THEN
    BEGIN
      IF(V$SP IS NULL) THEN V$SP = (SELECT NAME_FULL FROM UT_PERSON_DESC(:V$PERSON_ID, :I$ZONE, 1)); --Redmine #1060 --(SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$PERSON_ID, 23));

      VAL = '<tr data-group="5">';
        VAL = VAL || '<td>' || (SELECT VAL FROM ESCAPE_STR(:V$S1)) || '</td>';
        VAL = VAL || '<td data-sort="1">' || (SELECT VAL FROM ESCAPE_STR(:V$SP)) || '</td>';
        VAL = VAL || '<td>' || V$G5 || '</td>';
      VAL = VAL || '</tr>';
      SUSPEND;
    END

    -- Недоработавшие
    -- те, у кого все оценки на некотором уровне, и одна оценка ниже на ступень
    IF(
      (V$THRESHOLD = '2' AND (
        V$G1 = 1 AND (V$G2 + V$G3 + V$G4 + V$G5) > 0
      )) OR
      (V$THRESHOLD = '3' AND (
        (V$G1 + V$G2) = 1 AND (V$G3 + V$G4 + V$G5) > 0
      )) OR
      (V$THRESHOLD = '4' AND (
        (V$G1 + V$G2 + V$G3) = 1 AND (V$G4 + V$G5) > 0
      )) OR
      (V$THRESHOLD = '5' AND (
        (V$G1 + V$G2 + V$G3 + V$G4) = 1 AND V$G5 > 0
      )) OR
      (V$THRESHOLD IS NULL AND (
        (V$G5 > 0 AND (V$G1 + V$G2 + V$G3 + V$G4) >= 1) OR
        (V$G5 = 0 AND V$G4 > 0 AND (V$G1 + V$G2 + V$G3) >= 1) OR
        (V$G5 = 0 AND V$G4 = 0 AND V$G3 > 0 AND (V$G1 + V$G2) >= 1) OR
        (V$G5 = 0 AND V$G4 = 0 AND V$G3 = 0 AND V$G2 > 0 AND V$G1 >= 1)
      ))
    )
    THEN
    BEGIN
      IF(V$SP IS NULL) THEN V$SP = (SELECT NAME_FULL FROM UT_PERSON_DESC(:V$PERSON_ID, :I$ZONE, 1)); --Redmine #1060 --(SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$PERSON_ID, 23));

      V$TH2 = NULL;
      IF(V$THRESHOLD = '2') THEN V$TH2 = 1.5;
      ELSE IF(V$THRESHOLD = '3') THEN V$TH2 = 2.5;
      ELSE IF(V$THRESHOLD = '4') THEN V$TH2 = 3.5;
      ELSE IF(V$THRESHOLD = '5') THEN V$TH2 = 4.5;
      ELSE
      BEGIN
        IF(V$G5 > 0) THEN V$TH2 = 4.5;
        ELSE IF(V$G4 > 0) THEN V$TH2 = 3.5;
        ELSE IF(V$G3 > 0) THEN V$TH2 = 2.5;
        ELSE IF(V$G2 > 0) THEN V$TH2 = 1.5;
      END

      -- Смотрим ту самую единственную оценку, которая выпадает
      FOR
        SELECT C.CAPTION,  P.NAME_FULL --, CT.CAPTION
                , MT.MARK_SHORTNAME, D.RESULT, FT.VAL, J.SUBJECT_ID
        FROM CJ2_MARK M
        JOIN CJ2_MARK_TYPE MT ON MT.MARK_TYPE_ID = M.MARK_TYPE_ID
        JOIN CJ2_JOURNAL_FINALS F ON F.OBJ_ID = M.FINAL_ID
        JOIN CJ2_JOURNAL J ON J.OBJ_ID = F.CJ_ID
        LEFT JOIN OBJECT_CAPTION_GET(J.SUBJECT_ID) C ON 1 = 1
        LEFT JOIN UT_PERSON_DESC(COALESCE(F.TEACHER_ID, J.TEACHER_ID), :I$ZONE, 1) P ON 1 = 1 --Redmine #1060 --OBJECT_CAPTION_GET(COALESCE(F.TEACHER_ID, J.TEACHER_ID)) CT ON 1 = 1
        LEFT JOIN LISTVAL_TEXT(F.FINAL_TYPE) FT ON 1 = 1
        LEFT JOIN DATE2STR(F.FINAL_DATE) D ON 1 = 1
        WHERE M.DATE_DEL IS NULL AND M.STUDENT_ID = :V$PERSON_ID AND MT.PARENT_ID NOT IN (100)
          AND F.FINAL_DATE >= :I$DATE_FROM AND F.FINAL_DATE <= :V$DATE_TO
          AND MT.MARK_COST < :V$TH2
        ORDER BY C.CAPTION, F.FINAL_DATE
        INTO :V$S2, :V$S3, :V$M, :V$D, :V$FT, :V$SUBJECT_ID
      DO
      BEGIN
        VAL = '<tr data-group="nx">';
          VAL = VAL || '<td>' || (SELECT VAL FROM ESCAPE_STR(:V$S1)) || '</td>';
          VAL = VAL || '<td data-sort="1">' || (SELECT VAL FROM ESCAPE_STR(:V$SP)) || '</td>';
          VAL = VAL || '<td>' || V$M || '</td>';
          VAL = VAL || '<td>' || V$FT || ' (' || V$D || ')</td>';
          VAL = VAL || '<td class="target subject" data-target="' || V$SUBJECT_ID || '">' || (SELECT VAL FROM ESCAPE_STR(:V$S2)) || '</td>';
          VAL = VAL || '<td>' || (SELECT VAL FROM ESCAPE_STR(:V$S3)) || '</td>';
        VAL = VAL || '</tr>';
        SUSPEND;
      END
    END

  END

  VAL = '</table></body></html>';
  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_REPORT_NX310 (
    I$USER_ID VARCHAR(40),
    I$DATE_FROM DATE,
    I$DATE_TO DATE,
    I$PARENT_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$OPTION_ID BIGINT,
    I$OPTIONS VARCHAR(1000),
    I$ZONE SMALLINT = 0)
RETURNS (
    VAL VARCHAR(4000))
AS
declare variable V$CALLER_TYPE bigint;
declare variable V$USER_TYPE smallint;
declare variable V$OU_LICENCE_TYPE varchar(2);
declare variable V$S1 varchar(400);
declare variable V$S2 varchar(400);
declare variable V$PERSON_ID bigint;
declare variable V$MT smallint;
declare variable V$EXPAND smallint;
declare variable V$OBJ_ID bigint;
declare variable N bigint;
begin

  -- Школа, коллектив, персона
  SELECT TYPE_ID FROM OBJECTS WHERE OBJ_ID = :I$OBJ_ID INTO :V$CALLER_TYPE;
  SELECT STATUS FROM OU_LICENCE_TYPE INTO :V$OU_LICENCE_TYPE;

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;
  SELECT USER_TYPE FROM USERS WHERE USER_ID = :I$USER_ID INTO :V$USER_TYPE;

  V$MT = 0;
  V$EXPAND = 0;
  FOR
    SELECT TAKEN
    FROM PARSING_STRING_GET(:I$OPTIONS, ';')
    INTO :V$S1
  DO
  BEGIN
    IF(SUBSTRING(V$S1 FROM 1 FOR 3) = 'MT=') THEN
    BEGIN
      IF(SUBSTRING(V$S1 FROM 4) = 'п/аттестация') THEN V$MT = 0;
      ELSE IF(SUBSTRING(V$S1 FROM 4) = 'текущие') THEN V$MT = 1;
      ELSE IF(SUBSTRING(V$S1 FROM 4) = 'итоговые') THEN V$MT = 2;
    END
    ELSE IF(SUBSTRING(V$S1 FROM 1 FOR 7) = 'EXPAND=') THEN
    BEGIN
      IF(SUBSTRING(V$S1 FROM 8) = '1') THEN V$EXPAND = 1;
    END
  END

  VAL = '<!DOCTYPE html>';
  VAL = VAL || '<html lang="ru">';
  VAL = VAL || '<head>';
  VAL = VAL || '<meta charset="utf-8" />';
  VAL = VAL || '<style>';
  VAL = VAL || 'html { font-family: Tahoma, Verdana, Arial;';
  VAL = VAL || 'font-size: 10pt; ';
  VAL = VAL || '} ';
  VAL = VAL || '.title1 { font-size: 150%;';
  VAL = VAL || 'padding: 8px;';
  VAL = VAL || 'margin-bottom: 4px;';
  VAL = VAL || 'font-weight: bold;';
  VAL = VAL || 'background-color: #D4E157;';
  VAL = VAL || '} ';
  VAL = VAL || '.title2 { ';
  VAL = VAL || 'padding: 4px;';
  VAL = VAL || 'font-weight: bold;';
  VAL = VAL || '} ';
  VAL = VAL || '</style>';

  VAL = VAL || '</head>';
  VAL = VAL || '<body>';
  SUSPEND;

  -- Заголовок отчета
  VAL = '<div class="title1">Обученность';
  IF(V$MT = 0) THEN VAL = VAL || ' (по промежуточной аттестации)';
  IF(V$MT = 1) THEN VAL = VAL || ' (по текущим отметкам)';
  IF(V$MT = 2) THEN VAL = VAL || ' (по итоговым отметкам)';
  VAL = VAL || '</div>';

  VAL = VAL || '<div class="title2">'
            || CASE WHEN :V$CALLER_TYPE = 10 THEN (SELECT NAME_FULL FROM UT_PERSON_DESC(:I$OBJ_ID, :I$ZONE, 1))      -- обущающийся
                                             ELSE (SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$OBJ_ID))
               END
            || '</div>';
  IF(I$OPTION_ID IS NOT NULL) THEN
  BEGIN
    V$S1 = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$OPTION_ID));
    VAL = VAL || '<div class="title2">В разрезе: ' || COALESCE(V$S1, '???') || '</div>';
  END

  V$S1 = (SELECT RESULT FROM DATE2STR(:I$DATE_FROM));
  V$S2 = (SELECT RESULT FROM DATE2STR(:I$DATE_TO));
  VAL = VAL || '<div class="title2">Период: ' || V$S1 || ' - ' || V$S2 || '</div>';
  SUSPEND;

  -- Если у нас выбран НЕ учебный коллектив, то показываем меню для перехода
  IF(V$CALLER_TYPE NOT IN (9, 187, 10) AND V$EXPAND = 0) THEN
  BEGIN
    -- Показываем кнопку для раскрытия детализации
    IF(V$CALLER_TYPE IN (7, 8)) THEN
    BEGIN
      VAL = '<div class="target option" data-target="EXPAND=1">Раскрыть детализацию для ' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$OBJ_ID)) || '</div>';
      SUSPEND;
    END

    VAL = '<div class="target-nav">';
    SUSPEND;

    FOR
      SELECT L7.OBJ_ID || ',' || L8.OBJ_ID || ',' || L9.OBJ_ID, C.CAPTION, C.SORT_ORDER
      FROM LINKS L7
      JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 187) AND L9.DATE_DEL IS NULL
      LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C ON 1 = 1
      WHERE L7.PARENT_ID = :I$OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL AND :V$CALLER_TYPE = 2
      UNION
      SELECT L8.OBJ_ID || ',' || L9.OBJ_ID, C.CAPTION, C.SORT_ORDER
      FROM LINKS L8
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 187) AND L9.DATE_DEL IS NULL
      LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C ON 1 = 1
      WHERE L8.PARENT_ID = :I$OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL AND :V$CALLER_TYPE = 7
      UNION
      SELECT L9.OBJ_ID, C.CAPTION, C.SORT_ORDER
      FROM LINKS L9
      LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C ON 1 = 1
      WHERE L9.PARENT_ID = :I$OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 187) AND L9.DATE_DEL IS NULL AND :V$CALLER_TYPE = 8
      ORDER BY 3, 2
      INTO :V$S1, :V$S2, :V$PERSON_ID
    DO
    BEGIN
      VAL = '<div class="target class" data-target="' || V$S1 || '">' || (SELECT VAL FROM ESCAPE_STR(:V$S2)) || '</div>';
      SUSPEND;
    END

    VAL = '</div>';
    SUSPEND;

    --VAL = '</body></html>';
    --SUSPEND;
    --EXIT;
  END

  IF(V$MT = 0) THEN
  BEGIN
    FOR
      SELECT D.OBJ_ID, C.CAPTION, C.SORT_ORDER
      FROM (
        SELECT :I$OBJ_ID OBJ_ID
        FROM RDB$DATABASE
        WHERE :V$CALLER_TYPE IN (9, 187, 10) OR :V$EXPAND = 0
        UNION
        SELECT L9.OBJ_ID -- без экстернатов
        FROM LINKS L9
        WHERE L9.PARENT_ID = :I$OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL AND :V$CALLER_TYPE = 8 AND :V$EXPAND = 1
        UNION
        SELECT L9.OBJ_ID -- без экстернатов
        FROM LINKS L8
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
        WHERE L8.PARENT_ID = :I$OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL AND :V$CALLER_TYPE = 7 AND :V$EXPAND = 1
      ) D
      LEFT JOIN OBJECT_CAPTION_GET(D.OBJ_ID) C ON 1 = 1
      ORDER BY 3, 2
      INTO :V$OBJ_ID, :V$S1, :N
    DO
    BEGIN
      -- Выводим заголовок класса
      IF(V$EXPAND = 1) THEN
      BEGIN
        VAL = '<div class="target class" data-target="' || V$OBJ_ID || '"><b>' || (SELECT VAL FROM ESCAPE_STR(:V$S1)) || '</b></div>';
        SUSPEND;
      END

      FOR
        SELECT VAL
        FROM CJ2_REPORT_NX310_PA(:I$USER_ID, :I$DATE_FROM, :I$DATE_TO, :I$PARENT_ID, :V$OBJ_ID, :I$OBJ_ID, :I$OPTION_ID, :I$OPTIONS, :I$ZONE)
        INTO :VAL
      DO
      BEGIN
        SUSPEND;
      END
    END
  END
  ELSE IF(V$MT = 1) THEN
  BEGIN
    FOR
      SELECT D.OBJ_ID, C.CAPTION, C.SORT_ORDER
      FROM (
        SELECT :I$OBJ_ID OBJ_ID
        FROM RDB$DATABASE
        WHERE :V$CALLER_TYPE IN (9, 187, 10) OR :V$EXPAND = 0
        UNION
        SELECT L9.OBJ_ID -- без экстернатов
        FROM LINKS L9
        WHERE L9.PARENT_ID = :I$OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL AND :V$CALLER_TYPE = 8 AND :V$EXPAND = 1
        UNION
        SELECT L9.OBJ_ID -- без экстернатов
        FROM LINKS L8
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
        WHERE L8.PARENT_ID = :I$OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL AND :V$CALLER_TYPE = 7 AND :V$EXPAND = 1
      ) D
      LEFT JOIN OBJECT_CAPTION_GET(D.OBJ_ID) C ON 1 = 1
      ORDER BY 3, 2
      INTO :V$OBJ_ID, :V$S1, :N
    DO
    BEGIN
      -- Выводим заголовок класса
      IF(V$EXPAND = 1) THEN
      BEGIN
        VAL = '<div class="target class" data-target="' || V$OBJ_ID || '"><b>' || (SELECT VAL FROM ESCAPE_STR(:V$S1)) || '</b></div>';
        SUSPEND;
      END

      FOR
        SELECT VAL
        FROM CJ2_REPORT_NX310_CC(:I$USER_ID, :I$DATE_FROM, :I$DATE_TO, :I$PARENT_ID, :V$OBJ_ID, :I$OBJ_ID, :I$OPTION_ID, :I$OPTIONS, :I$ZONE)
        INTO :VAL
      DO
      BEGIN
        SUSPEND;
      END
    END
  END
  ELSE IF(V$MT = 2) THEN
  BEGIN
    FOR
      SELECT D.OBJ_ID, C.CAPTION, C.SORT_ORDER
      FROM (
        SELECT :I$OBJ_ID OBJ_ID
        FROM RDB$DATABASE
        WHERE :V$CALLER_TYPE IN (9, 187, 10) OR :V$EXPAND = 0
        UNION
        SELECT L9.OBJ_ID -- без экстернатов
        FROM LINKS L9
        WHERE L9.PARENT_ID = :I$OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL AND :V$CALLER_TYPE = 8 AND :V$EXPAND = 1
        UNION
        SELECT L9.OBJ_ID -- без экстернатов
        FROM LINKS L8
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
        WHERE L8.PARENT_ID = :I$OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL AND :V$CALLER_TYPE = 7 AND :V$EXPAND = 1
      ) D
      LEFT JOIN OBJECT_CAPTION_GET(D.OBJ_ID) C ON 1 = 1
      ORDER BY 3, 2
      INTO :V$OBJ_ID, :V$S1, :N
    DO
    BEGIN
      -- Выводим заголовок класса
      IF(V$EXPAND = 1) THEN
      BEGIN
        VAL = '<div class="target class" data-target="' || V$OBJ_ID || '"><b>' || (SELECT VAL FROM ESCAPE_STR(:V$S1)) || '</b></div>';
        SUSPEND;
      END

      FOR
        SELECT VAL
        FROM CJ2_REPORT_NX310_FN(:I$USER_ID, :I$DATE_FROM, :I$DATE_TO, :I$PARENT_ID, :V$OBJ_ID, :I$OBJ_ID, :I$OPTION_ID, :I$OPTIONS, :I$ZONE)
        INTO :VAL
      DO
      BEGIN
        SUSPEND;
      END
    END
  END

  VAL = '</body></html>';
  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_REPORT_NX310_CC (
    I$USER_ID BIGINT,
    I$DATE_FROM DATE,
    I$DATE_TO DATE,
    I$PARENT_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$ROOT_ID BIGINT,
    I$OPTION_ID BIGINT,
    I$OPTIONS VARCHAR(1000),
    I$ZONE SMALLINT = 0)
RETURNS (
    VAL VARCHAR(4000))
AS
declare variable V$CALLER_TYPE bigint;
declare variable V$ROOT_TYPE bigint;
declare variable V$USER_TYPE smallint;
declare variable V$OU_LICENCE_TYPE varchar(2);
declare variable V$S1 varchar(400);
declare variable V$S2 varchar(400);
declare variable V$PERSON_ID bigint;
declare variable V$SUBJECT_ID bigint;
declare variable V$N5 integer;
declare variable V$N4 integer;
declare variable V$N3 integer;
declare variable V$N2 integer;
declare variable V$N0 integer;
declare variable V$TN5 integer;
declare variable V$TN4 integer;
declare variable V$TN3 integer;
declare variable V$TN2 integer;
declare variable V$TN0 integer;
declare variable V$V double precision;
declare variable V$VT double precision;
declare variable V$VS double precision;
declare variable V$VB double precision;
declare variable V$TT double precision;
declare variable V$ST double precision;
declare variable V$B double precision;
declare variable V$N integer;
declare variable V$SS varchar(4000);
declare variable V$OPTION_TYPE bigint;
declare variable V$SO double precision;
declare variable V$D date;
declare variable V$GRADE_ID bigint;
declare variable V$TEACHER_ID bigint;
declare variable V$PREV_ID bigint;
begin

  if(I$OBJ_ID is null) then I$OBJ_ID = 4404001250949;
  if(I$ROOT_ID is null) then I$ROOT_ID = 4404001250949;
  if(I$DATE_FROM is null) then I$DATE_FROM = '01.09.2023';
  if(I$DATE_to is null) then I$DATE_to = '01.01.2024';

  -- Школа, коллектив, персона
  SELECT TYPE_ID FROM OBJECTS WHERE OBJ_ID = :I$OBJ_ID INTO :V$CALLER_TYPE;
  SELECT TYPE_ID FROM OBJECTS WHERE OBJ_ID = :I$ROOT_ID INTO :V$ROOT_TYPE;
  SELECT STATUS FROM OU_LICENCE_TYPE INTO :V$OU_LICENCE_TYPE;

  -- Тип объекта опции - учитель или предмет
  V$OPTION_TYPE = 0;

  SELECT FIRST 1 TYPE_ID
  FROM OBJECTS
  WHERE OBJ_ID = :I$OPTION_ID
  INTO :V$OPTION_TYPE;

  -- В разбивке по ученику или по классу показываем сразу с разбивкой по предметам и в целом
  -- В разбивке по уровню или параллели показываем две таблицы - по классам и по предметам

  IF(V$CALLER_TYPE IN (10, 9, 187)) THEN
  BEGIN

  VAL = '<table id="t' || I$OBJ_ID || '" class="table centered" cellspacing="0" cellpadding="0" data-flags="sort arrange" style="min-width: 50%">';
  VAL = VAL || '<thead>';
  VAL = VAL || '<tr class="thd">';
    VAL = VAL || '<td class="tl sortable">ФИО</td>';
  SUSPEND;
  -- Список предметов для учеников класса, только действующих
  V$N = 0;
  FOR
    SELECT S.SUBJECT_ID, S.SUBJECT_CODE, S.SUBJECT_NAME
    FROM CJ2_REPORT_NX310_SUBJ(:I$ROOT_ID, :V$ROOT_TYPE, :I$OBJ_ID, 1, :I$DATE_FROM, :I$DATE_TO) S
    WHERE (:V$OPTION_TYPE = 51 AND S.SUBJECT_ID = :I$OPTION_ID) OR :V$OPTION_TYPE <> 51
    INTO :V$SUBJECT_ID, :V$S1, :V$S2
  DO
  BEGIN
    VAL = '<td class="sortable value" title="' || (SELECT VAL FROM ESCAPE_STR(:V$S2)) || '"><div class="target subject" data-target="' || V$SUBJECT_ID || '">' || (SELECT VAL FROM ESCAPE_STR(:V$S1)) || '</div></td>';
    V$N = V$N + 1;
    SUSPEND;
  END
  --
  VAL = '<td class="sortable value" style="width: 4rem">5</td>';
  VAL = VAL || '<td class="sortable value" style="width: 4rem">4</td>';
  VAL = VAL || '<td class="sortable value" style="width: 4rem">3</td>';
  VAL = VAL || '<td class="sortable value" style="width: 4rem">2</td>';
  VAL = VAL || '<td class="sortable value" style="width: 4rem">Н/А</td>';
  VAL = VAL || '<td class="sortable value" style="width: 4rem">СБ</td>';
  VAL = VAL || '<td class="sortable value" style="width: 4rem">СОУ</td>';
  VAL = VAL || '</tr>';
  VAL = VAL || '</thead>';
  VAL = VAL || '<tbody>';
  SUSPEND;

  FOR
    SELECT DISTINCT M.PERSON_ID, P.NAME_FULL --C.CAPTION
    FROM PERSON_MOVEMENTS M
    LEFT JOIN UT_PERSON_DESC(M.PERSON_ID, :I$ZONE, 1) P ON 1 = 1 --Redmine #1060 --LEFT JOIN OBJECT_CAPTION_GET(M.PERSON_ID, 23) C ON 1 = 1
    WHERE M.DATE_DEL IS NULL AND M.GROUP_TYPE_ID IN (9, 187)
      AND (:V$CALLER_TYPE <> 10 OR M.PERSON_ID = :I$OBJ_ID) -- фильтр по конкретному ученику
      AND (:V$CALLER_TYPE NOT IN (9, 187) OR M.GROUP_ID = :I$OBJ_ID) -- фильтр по классу
      AND M.DATE_IN <= :I$DATE_TO AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :I$DATE_FROM)
    ORDER BY 2
    INTO :V$PERSON_ID, :V$S1
  DO
  BEGIN
    V$TN5 = 0;
    V$TN4 = 0;
    V$TN3 = 0;
    V$TN2 = 0;
    V$TN0 = 0;
    V$TT = 0;
    V$ST = 0;
    V$B = 0;

    VAL = '<tr>';
    IF(V$CALLER_TYPE = 10) THEN
      VAL = VAL || '<td class="tl">' || (SELECT VAL FROM ESCAPE_STR(:V$S1)) || '</td>';
    ELSE
      VAL = VAL || '<td class="target student tl" data-target="' || V$PERSON_ID || '">' || (SELECT VAL FROM ESCAPE_STR(:V$S1)) || '</td>';
    SUSPEND;

    V$SS = '<tr><td class="tl">&nbsp;</td>';

    -- Оценки по предметам
    FOR
      SELECT S.SUBJECT_ID
      FROM CJ2_REPORT_NX310_SUBJ(:I$ROOT_ID, :V$ROOT_TYPE, :I$OBJ_ID, 1, :I$DATE_FROM, :I$DATE_TO, NULL, NULL) S
      WHERE (
        ((:V$OPTION_TYPE = 51 AND S.SUBJECT_ID = :I$OPTION_ID) OR :V$OPTION_TYPE <> 51) AND
        ((:V$OPTION_TYPE = 14 AND S.TEACHER_ID = :I$OPTION_ID) OR :V$OPTION_TYPE <> 14)
      )
      INTO :V$SUBJECT_ID
    DO
    BEGIN
      SELECT SUM(MT.MARK_COST), SUM(IIF(MT.MARK_COST = 0, 7, IIF(MT.MARK_COST < 2.5, 16, IIF(MT.MARK_COST < 3.5, 36, IIF(MT.MARK_COST < 4.5, 64, 100))))), COUNT(*),
        SUM(IIF(MT.MARK_COST >= 4.5, 1, 0)), SUM(IIF(MT.MARK_COST >= 3.5 AND MT.MARK_COST < 4.5, 1, 0)), SUM(IIF(MT.MARK_COST >= 2.5 AND MT.MARK_COST < 3.5, 1, 0)), SUM(IIF(MT.MARK_COST < 2.5 AND MT.MARK_COST > 0, 1, 0)),
          SUM(IIF(MT.MARK_COST = 0, 1, 0))
      FROM CJ2_MARK M
      JOIN CJ2_CONTROL C ON C.DATE_DEL IS NULL AND C.CONTROL_ID = M.CONTROL_ID AND C.CONTROL_TYPE_ID > 0
      JOIN CJ2_JOURNAL_LESSONS L ON L.DATE_DEL IS NULL AND L.OBJ_ID = C.LESSON_ID
      JOIN CJ2_JOURNAL J ON J.OBJ_ID = L.CJ_ID AND J.JOURNAL_TYPE = 0 AND J.SUBJECT_ID = :V$SUBJECT_ID
      JOIN CJ2_MARK_TYPE MT ON MT.MARK_TYPE_ID = M.MARK_TYPE_ID
      JOIN CJ2_CONTROL_TYPE CT ON CT.CONTROL_TYPE_ID = C.CONTROL_TYPE_ID
      WHERE M.DATE_DEL IS NULL AND M.STUDENT_ID = :V$PERSON_ID AND MT.PARENT_ID NOT IN (100)
        AND L.LESSON_DATE >= :I$DATE_FROM AND L.LESSON_DATE <= :I$DATE_TO
      INTO :V$VT, :V$VS, :V$VB, :V$N5, :V$N4, :V$N3, :V$N2, :V$N0;

      IF(V$VT IS NULL) THEN V$VT = 0;
      IF(V$VS IS NULL) THEN V$VS = 0;
      IF(V$VB IS NULL) THEN V$VB = 0;
      V$TT = V$TT + V$VT;
      V$ST = V$ST + V$VS;
      V$B = V$B + V$VB;
      V$V = IIF(V$VB > 0, V$VT / V$VB, NULL);

      -- Счетчик по диапазонам отметок
      -- неаттестацию как таковую тут вообще не меряем
      V$N5 = COALESCE(V$N5, 0);
      V$N4 = COALESCE(V$N4, 0);
      V$N3 = COALESCE(V$N3, 0);
      V$N2 = COALESCE(V$N2, 0);
      V$N0 = COALESCE(V$N0, 0);
      V$TN5 = V$TN5 + V$N5;
      V$TN4 = V$TN4 + V$N4;
      V$TN3 = V$TN3 + V$N3;
      V$TN2 = V$TN2 + V$N2;
      V$TN0 = V$TN0 + V$N0;

      VAL = '<td data-t="' || CAST(V$VT AS NUMERIC(18, 4)) || '" data-s="' || CAST(V$VS AS NUMERIC(18, 4)) || '" data-b="' || CAST(V$VB AS NUMERIC(18, 4)) || '"';
      VAL = VAL || ' data-n5="' || V$N5 || '" data-n4="' || V$N4 || '" data-n3="' || V$N3 || '" data-n2="' || V$N2 || '" data-n0="' || V$N0 || '"';
      VAL = VAL || '>' || IIF(V$V IS NULL, '&nbsp;', CAST(V$V AS NUMERIC(18, 1))) || '</td>';
      SUSPEND;

      V$SS = V$SS || '<td>&nbsp;</td>';
    END

    VAL = '<td class="line-left h">' || IIF(V$TN5 > 0, V$TN5, '&nbsp;') || '</td>';
    VAL = VAL || '<td class="h">' || IIF(V$TN4 > 0, V$TN4, '&nbsp;') || '</td>';
    VAL = VAL || '<td class="h">' || IIF(V$TN3 > 0, V$TN3, '&nbsp;') || '</td>';
    VAL = VAL || '<td class="h">' || IIF(V$TN2 > 0, V$TN2, '&nbsp;') || '</td>';
    VAL = VAL || '<td class="h">' || IIF(V$TN0 > 0, V$TN0, '&nbsp;') || '</td>';

    -- Средний балл
    VAL = VAL || '<td>' || IIF(V$B > 0, CAST((V$TT / V$B) AS NUMERIC(18, 1)), '&nbsp;') || '</td>';
    -- Обученность
    VAL = VAL || '<td>' || IIF(V$B > 0, CAST((V$ST / V$B) AS NUMERIC(18, 0)), '&nbsp;') || '</td>';

    VAL = VAL || '</tr>';
    SUSPEND;

    V$B = V$TN5 + V$TN4 + V$TN3 + V$TN2 + V$TN0;
    IF(V$B = 0) THEN V$B = 1;
    V$SS = V$SS || '<td>' || CAST(100 * V$TN5 / V$B AS NUMERIC(18, 1)) || '%</td>';
    V$SS = V$SS || '<td>' || CAST(100 * V$TN4 / V$B AS NUMERIC(18, 1)) || '%</td>';
    V$SS = V$SS || '<td>' || CAST(100 * V$TN3 / V$B AS NUMERIC(18, 1)) || '%</td>';
    V$SS = V$SS || '<td>' || CAST(100 * V$TN2 / V$B AS NUMERIC(18, 1)) || '%</td>';
    V$SS = V$SS || '<td>' || CAST(100 * V$TN0 / V$B AS NUMERIC(18, 1)) || '%</td>';
    V$SS = V$SS || '<td>&nbsp;</td><td>&nbsp;</td></tr>';
  END

  -- Строка процентов
  IF(V$CALLER_TYPE = 10) THEN
  BEGIN
    VAL = V$SS;
    SUSPEND;
  END

  -- Сводные данные по учебному коллективу, вычисляются скриптом уже на фронте
  IF(V$CALLER_TYPE IN (9, 187)) THEN
  BEGIN
    -- 5
    VAL = '<tr id="f5" class="line-top f">';
    VAL = VAL || '</tr>';
    SUSPEND;

    -- 4
    VAL = '<tr id="f4" class="f">';
    VAL = VAL || '</tr>';
    SUSPEND;

    -- 3
    VAL = '<tr id="f3" class="f">';
    VAL = VAL || '</tr>';
    SUSPEND;

    -- 2
    VAL = '<tr id="f2" class="f">';
    VAL = VAL || '</tr>';
    SUSPEND;

    -- Н/А
    VAL = '<tr id="f0" class="f">';
    VAL = VAL || '</tr>';
    SUSPEND;

    -- СБ
    VAL = '<tr id="fb" class="line-top f">';
    VAL = VAL || '</tr>';
    SUSPEND;

    -- СОУ
    VAL = '<tr id="fe" class="f">';
    VAL = VAL || '</tr>';
    SUSPEND;
  END

  VAL = '</tbody></table>';
  SUSPEND;

  VAL = '<script>';
  VAL = VAL || '(function () { ';
  VAL = VAL || 'let tid = "#t' || I$OBJ_ID || '";';
  VAL = VAL || 'let nr = ' || V$N || ';';
  VAL = VAL || 'let sb = "<td class=''tl''>Средний балл</td>", se = "<td class=''tl''>Обученность</td>";';
  VAL = VAL || 'let s5 = "<td class=''tl''>5</td>", s4 = "<td class=''tl''>4</td>", s3 = "<td class=''tl''>3</td>", s2 = "<td class=''tl''>2</td>", s0 = "<td class=''tl''>Н/А</td>";';
  VAL = VAL || 'let ttt = 0, tts = 0, ttb = 0, nx = [0, 0, 0, 0, 0], nxx = 0;';
  -- Столбцы по предметам
  VAL = VAL || '$(tid + " .thd td").each((n, el) => {';
  VAL = VAL || 'if(n === 0) return;';
  VAL = VAL || 'let tt = 0, ts = 0, tb = 0, ns = [0, 0, 0, 0, 0];';

  VAL = VAL || '$(tid + " tbody tr:not(.f)").each((m, tr) => {';
  VAL = VAL || '$(tr).find("td:eq(" + n + ")").each((k, el2) => {';
  VAL = VAL || 'if(n <= nr) {';
    -- Средний балл по предметам
    VAL = VAL || 'tt += parseFloat($(el2).attr("data-t"));';
    VAL = VAL || 'ts += parseFloat($(el2).attr("data-s"));';
    VAL = VAL || 'tb += parseFloat($(el2).attr("data-b"));';
    VAL = VAL || 'ttt += parseFloat($(el2).attr("data-t"));';
    VAL = VAL || 'tts += parseFloat($(el2).attr("data-s"));';
    VAL = VAL || 'ttb += parseFloat($(el2).attr("data-b"));';
    VAL = VAL || 'ns[0] += parseInt($(el2).attr("data-n5"));';
    VAL = VAL || 'ns[1] += parseInt($(el2).attr("data-n4"));';
    VAL = VAL || 'ns[2] += parseInt($(el2).attr("data-n3"));';
    VAL = VAL || 'ns[3] += parseInt($(el2).attr("data-n2"));';
    VAL = VAL || 'ns[4] += parseInt($(el2).attr("data-n0"));';
  VAL = VAL || '} else if(n <= nr + 5) {';
    -- Количество отметок суммарно
    VAL = VAL || 'let v = parseInt($(el2).text());';
    VAL = VAL || 'if(!isNaN(v)) { nx[n - nr - 1] += v; nxx += v; }';
  VAL = VAL || '}';
  VAL = VAL || '});'; -- tr
  VAL = VAL || '});';

  VAL = VAL || 'if(nxx == 0) nxx = 1;';

  VAL = VAL || 'if(n <= nr) {';
    -- Средний балл по предметам
    VAL = VAL || 's5 += "<td>" + (ns[0] > 0 ? ns[0] : "&nbsp;") + "</td>";';
    VAL = VAL || 's4 += "<td>" + (ns[1] > 0 ? ns[1] : "&nbsp;") + "</td>";';
    VAL = VAL || 's3 += "<td>" + (ns[2] > 0 ? ns[2] : "&nbsp;") + "</td>";';
    VAL = VAL || 's2 += "<td>" + (ns[3] > 0 ? ns[3] : "&nbsp;") + "</td>";';
    VAL = VAL || 's0 += "<td>" + (ns[4] > 0 ? ns[4] : "&nbsp;") + "</td>";';
    VAL = VAL || 'sb += "<td>" + (tb > 0 ? (tt / tb).toFixed(1) : "&nbsp;") + "</td>";';
    VAL = VAL || 'se += "<td>" + (tb > 0 ? (ts / tb).toFixed(0) : "&nbsp;") + "</td>";';
  VAL = VAL || '} else if(n <= nr + 5) {';
    -- Количество отметок
    VAL = VAL || 'let p = n === nr + 1 ? " line-left" : "";';
    VAL = VAL || 's5 += "<td class=''h" + p + "''>" + (nx[0] > 0 && n === nr + 1 ? nx[0] : "&nbsp;") + "</td>";';
    VAL = VAL || 's4 += "<td class=''h" + p + "''>" + (nx[1] > 0 && n === nr + 2 ? nx[1] : "&nbsp;") + "</td>";';
    VAL = VAL || 's3 += "<td class=''h" + p + "''>" + (nx[2] > 0 && n === nr + 3 ? nx[2] : "&nbsp;") + "</td>";';
    VAL = VAL || 's2 += "<td class=''h" + p + "''>" + (nx[3] > 0 && n === nr + 4 ? nx[3] : "&nbsp;") + "</td>";';
    VAL = VAL || 's0 += "<td class=''h" + p + "''>" + (nx[4] > 0 && n === nr + 5 ? nx[4] : "&nbsp;") + "</td>";';
    VAL = VAL || 'sb += "<td class=''h" + p + "''>&nbsp;</td>";';
    VAL = VAL || 'se += "<td class=''h" + p + "''>&nbsp;</td>";';
  VAL = VAL || '} else if(n == nr + 6) {';
    VAL = VAL || 's5 += "<td>" + (100.0 * nx[0] / nxx).toFixed(1) + "%</td>";';
    VAL = VAL || 's4 += "<td>" + (100.0 * nx[1] / nxx).toFixed(1) + "%</td>";';
    VAL = VAL || 's3 += "<td>" + (100.0 * nx[2] / nxx).toFixed(1) + "%</td>";';
    VAL = VAL || 's2 += "<td>" + (100.0 * nx[3] / nxx).toFixed(1) + "%</td>";';
    VAL = VAL || 's0 += "<td>" + (100.0 * nx[4] / nxx).toFixed(1) + "%</td>";';
    VAL = VAL || 'sb += "<td>" + (ttb > 0 ? (ttt / ttb).toFixed(1) : "&nbsp;") + "</td>";';
    VAL = VAL || 'se += "<td>&nbsp;</td>";';
  VAL = VAL || '} else if(n == nr + 7) {';
    VAL = VAL || 's5 += "<td>&nbsp;</td>";';
    VAL = VAL || 's4 += "<td>&nbsp;</td>";';
    VAL = VAL || 's3 += "<td>&nbsp;</td>";';
    VAL = VAL || 's2 += "<td>&nbsp;</td>";';
    VAL = VAL || 's0 += "<td>&nbsp;</td>";';
    VAL = VAL || 'sb += "<td>&nbsp;</td>";';
    VAL = VAL || 'se += "<td>" + (ttb > 0 ? (tts / ttb).toFixed(0) : "&nbsp;") + "</td>";';
  VAL = VAL || '}';
  VAL = VAL || '});';

  VAL = VAL || '$(tid + " #f5").html(s5);';
  VAL = VAL || '$(tid + " #f4").html(s4);';
  VAL = VAL || '$(tid + " #f3").html(s3);';
  VAL = VAL || '$(tid + " #f2").html(s2);';
  VAL = VAL || '$(tid + " #f0").html(s0);';
  VAL = VAL || '$(tid + " #fb").html(sb);';
  VAL = VAL || '$(tid + " #fe").html(se);';
  VAL = VAL || '})();';
  VAL = VAL || '</script>';
  SUSPEND;

  END
  ELSE
  BEGIN

    VAL = '<table id="t' || I$OBJ_ID || '" class="table centered" cellspacing="0" cellpadding="0" data-flags="sort arrange" style="min-width: 50%">';
    VAL = VAL || '<thead>';
    VAL = VAL || '<tr class="thd">';
      VAL = VAL || '<td class="tl sortable">Учебный коллектив</td>';
      VAL = VAL || '<td class="sortable value" style="width: 4rem">5</td>';
      VAL = VAL || '<td class="sortable value" style="width: 4rem">4</td>';
      VAL = VAL || '<td class="sortable value" style="width: 4rem">3</td>';
      VAL = VAL || '<td class="sortable value" style="width: 4rem">2</td>';
      VAL = VAL || '<td class="sortable value" style="width: 4rem">Н/А</td>';
      VAL = VAL || '<td class="sortable value" style="width: 4rem">СБ</td>';
      VAL = VAL || '<td class="sortable value" style="width: 4rem">СОУ</td>';
      VAL = VAL || '</tr>';
    VAL = VAL || '</tr></thead><tbody>';
    SUSPEND;

    FOR
      SELECT L9.OBJ_ID, C.CAPTION, C.SORT_ORDER
      FROM LINKS L2
      JOIN LINKS L8 ON L8.PARENT_ID = L2.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
      LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C ON 1 = 1
      WHERE L2.PARENT_ID = :I$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND :V$CALLER_TYPE = 2
      UNION
      SELECT L9.OBJ_ID, C.CAPTION, C.SORT_ORDER
      FROM LINKS L8
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
      LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C ON 1 = 1
      WHERE L8.PARENT_ID = :I$OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL AND :V$CALLER_TYPE = 7
      UNION
      SELECT L9.OBJ_ID, C.CAPTION, C.SORT_ORDER
      FROM LINKS L9
      LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C ON 1 = 1
      WHERE L9.PARENT_ID = :I$OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL AND :V$CALLER_TYPE = 8
      ORDER BY 3, 2
      INTO :V$PERSON_ID, :V$S1, :V$SO
    DO
    BEGIN
      VAL = '<tr>';
        VAL = VAL || '<td class="target class tl" data-target="' || V$PERSON_ID || '">' || V$S1 || '</td>';
        VAL = VAL || '<td>&nbsp;</td>';
        VAL = VAL || '<td>&nbsp;</td>';
        VAL = VAL || '<td>&nbsp;</td>';
        VAL = VAL || '<td>&nbsp;</td>';
        VAL = VAL || '<td>&nbsp;</td>';
        VAL = VAL || '<td>&nbsp;</td>';
        VAL = VAL || '<td>&nbsp;</td>';
      VAL = VAL || '</tr>';
      SUSPEND;
    END

    VAL = '</tbody></table>';
    SUSPEND;

    VAL = '<table id="s' || I$OBJ_ID || '" class="table centered" cellspacing="0" cellpadding="0" data-flags="sort arrange" style="min-width: 50%">';
    VAL = VAL || '<thead>';
    VAL = VAL || '<tr class="thd">';
      VAL = VAL || '<td class="tl sortable">Предмет</td>';
      VAL = VAL || '<td class="sortable value" style="width: 4rem">5</td>';
      VAL = VAL || '<td class="sortable value" style="width: 4rem">4</td>';
      VAL = VAL || '<td class="sortable value" style="width: 4rem">3</td>';
      VAL = VAL || '<td class="sortable value" style="width: 4rem">2</td>';
      VAL = VAL || '<td class="sortable value" style="width: 4rem">Н/А</td>';
      VAL = VAL || '<td class="sortable value" style="width: 4rem">СБ</td>';
      VAL = VAL || '<td class="sortable value" style="width: 4rem">СОУ</td>';
      VAL = VAL || '</tr>';
    VAL = VAL || '</tr></thead><tbody>';
    SUSPEND;

    FOR
      SELECT S.SUBJECT_ID, C.CAPTION
      FROM CJ2_REPORT_NX310_SUBJ(:I$OBJ_ID, :V$CALLER_TYPE, :I$OBJ_ID, 1, :I$DATE_FROM, :I$DATE_TO, IIF(:V$OPTION_TYPE = 14, :I$OPTION_ID, NULL)) S
      LEFT JOIN OBJECT_CAPTION_GET(S.SUBJECT_ID) C ON 1 = 1
      WHERE (:V$OPTION_TYPE = 51 AND S.SUBJECT_ID = :I$OPTION_ID) OR :V$OPTION_TYPE <> 51
      INTO :V$SUBJECT_ID, :V$S1
    DO
    BEGIN
      VAL = '<tr>';
        VAL = VAL || '<td  class="target subject tl" data-target="' || V$SUBJECT_ID || '">' || V$S1 || '</td>';
        VAL = VAL || '<td>&nbsp;</td>';
        VAL = VAL || '<td>&nbsp;</td>';
        VAL = VAL || '<td>&nbsp;</td>';
        VAL = VAL || '<td>&nbsp;</td>';
        VAL = VAL || '<td>&nbsp;</td>';
        VAL = VAL || '<td>&nbsp;</td>';
        VAL = VAL || '<td>&nbsp;</td>';
      VAL = VAL || '</tr>';
      SUSPEND;
    END

    VAL = '</tbody></table>';
    SUSPEND;

    VAL = '<table id="h' || I$OBJ_ID || '" class="table centered" cellspacing="0" cellpadding="0" data-flags="sort arrange" style="min-width: 50%">';
    VAL = VAL || '<thead>';
    VAL = VAL || '<tr class="thd">';
      VAL = VAL || '<td class="tl sortable">Преподаватель</td>';
      VAL = VAL || '<td class="sortable value" style="width: 4rem">5</td>';
      VAL = VAL || '<td class="sortable value" style="width: 4rem">4</td>';
      VAL = VAL || '<td class="sortable value" style="width: 4rem">3</td>';
      VAL = VAL || '<td class="sortable value" style="width: 4rem">2</td>';
      VAL = VAL || '<td class="sortable value" style="width: 4rem">Н/А</td>';
      VAL = VAL || '<td class="sortable value" style="width: 4rem">СБ</td>';
      VAL = VAL || '<td class="sortable value" style="width: 4rem">СОУ</td>';
      VAL = VAL || '</tr>';
    VAL = VAL || '</tr></thead><tbody>';
    SUSPEND;

    -- Собираем список преподавателей
    V$PREV_ID = 0;
    VAL = '';
    FOR
      SELECT DISTINCT S.TEACHER_ID, P.NAME_FULL --C.CAPTION
                    , S.SUBJECT_NAME
      FROM CJ2_REPORT_NX310_SUBJ(:I$OBJ_ID, :V$CALLER_TYPE, :I$OBJ_ID, 1, :I$DATE_FROM, :I$DATE_TO, NULL, IIF(:V$OPTION_TYPE = 14, :I$OPTION_ID, -1)) S
      LEFT JOIN UT_PERSON_DESC(S.TEACHER_ID, :I$ZONE, 1) P ON 1 = 1 --Redmine #1060 --LEFT JOIN OBJECT_CAPTION_GET(S.TEACHER_ID) C ON 1 = 1
      WHERE (
        ((:V$OPTION_TYPE = 51 AND S.SUBJECT_ID = :I$OPTION_ID) OR :V$OPTION_TYPE <> 51)
      )
      ORDER BY 2, 3
      INTO :V$SUBJECT_ID, :V$S1, :V$S2
    DO
    BEGIN
      IF(V$SUBJECT_ID <> V$PREV_ID) THEN
      BEGIN
        IF(V$PREV_ID > 0) THEN
        BEGIN
          VAL = VAL || ')</td>';
          VAL = VAL || '<td>&nbsp;</td>';
          VAL = VAL || '<td>&nbsp;</td>';
          VAL = VAL || '<td>&nbsp;</td>';
          VAL = VAL || '<td>&nbsp;</td>';
          VAL = VAL || '<td>&nbsp;</td>';
          VAL = VAL || '<td>&nbsp;</td>';
          VAL = VAL || '<td>&nbsp;</td>';
          VAL = VAL || '</tr>';
          SUSPEND;
        END

        VAL = '<tr>';
        VAL = VAL || '<td  class="target teacher tl" data-target="' || V$SUBJECT_ID || '">' || V$S1 || ' (' || V$S2;
      END
      ELSE
      BEGIN
        VAL = VAL || ', ' || V$S2;
      END
      V$PREV_ID = V$SUBJECT_ID;
    END
    IF(V$PREV_ID > 0) THEN
    BEGIN
      VAL = VAL || ')</td>';
      VAL = VAL || '<td>&nbsp;</td>';
      VAL = VAL || '<td>&nbsp;</td>';
      VAL = VAL || '<td>&nbsp;</td>';
      VAL = VAL || '<td>&nbsp;</td>';
      VAL = VAL || '<td>&nbsp;</td>';
      VAL = VAL || '<td>&nbsp;</td>';
      VAL = VAL || '<td>&nbsp;</td>';
      VAL = VAL || '</tr>';
      SUSPEND;
    END

    VAL = '</tbody></table>';
    SUSPEND;

    VAL = '<script>';
    VAL = VAL || '(function () { ';
    VAL = VAL || 'let tid = "#t' || I$OBJ_ID || '";';
    VAL = VAL || 'let sid = "#s' || I$OBJ_ID || '";';
    VAL = VAL || 'let hid = "#h' || I$OBJ_ID || '";';
    VAL = VAL || 'let m = [';
    SUSPEND;

    FOR
      SELECT P.OBJ_ID, J.SUBJECT_ID, MT.MARK_COST, L.LESSON_DATE, P.PARENT_ID, J.TEACHER_ID
      FROM (
        -- для уровня образования
        SELECT DISTINCT L10.OBJ_ID, L10.PARENT_ID
        FROM LINKS L8
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
        JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        WHERE L8.PARENT_ID = :I$OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL AND :V$CALLER_TYPE = 7
        -- для параллели
        UNION
        SELECT DISTINCT L10.OBJ_ID, L10.PARENT_ID
        FROM LINKS L9
        JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        WHERE L9.PARENT_ID = :I$OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL AND :V$CALLER_TYPE = 8
        -- для класса
        UNION
        SELECT DISTINCT L10.OBJ_ID, L10.PARENT_ID
        FROM LINKS L10
        WHERE L10.PARENT_ID = :I$OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL AND :V$CALLER_TYPE IN (9, 187)
        -- для конкретного ученика
        UNION
        SELECT :I$OBJ_ID, 0
        FROM RDB$DATABASE
        WHERE :V$CALLER_TYPE = 10
      ) P
      JOIN CJ2_MARK M ON M.DATE_DEL IS NULL AND M.STUDENT_ID = P.OBJ_ID AND M.CONTROL_ID IS NOT NULL
      JOIN CJ2_CONTROL C ON C.DATE_DEL IS NULL AND C.CONTROL_ID = M.CONTROL_ID AND C.CONTROL_TYPE_ID <> 0
      JOIN CJ2_JOURNAL_LESSONS L ON L.DATE_DEL IS NULL AND L.OBJ_ID = C.LESSON_ID AND L.IS_COMPLETED = 1 AND L.LESSON_DATE >= :I$DATE_FROM AND L.LESSON_DATE <= :I$DATE_TO
      JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.JOURNAL_TYPE = 0 AND J.OBJ_ID = L.CJ_ID
      JOIN CJ2_MARK_TYPE MT ON MT.MARK_TYPE_ID = M.MARK_TYPE_ID
      WHERE (
        ((:V$OPTION_TYPE = 51 AND J.SUBJECT_ID = :I$OPTION_ID) OR :V$OPTION_TYPE <> 51) AND
        ((:V$OPTION_TYPE = 14 AND J.TEACHER_ID = :I$OPTION_ID) OR :V$OPTION_TYPE <> 14)
      )
      INTO :V$PERSON_ID, :V$SUBJECT_ID, :V$SO, :V$D, :V$GRADE_ID, :V$TEACHER_ID
    DO
    BEGIN
      -- p - id ученика, c - id класса (только если идет групповая выборка), s - id предмета, m - значение оценки в 5-балльной шкале, d - номер дня от начальной даты
      VAL = '{p:' || V$PERSON_ID || ',s:' || V$SUBJECT_ID || ',h:' || V$TEACHER_ID || ',m:' || CAST(V$SO AS NUMERIC(18, 1)) || ',d:' || DATEDIFF(DAY FROM I$DATE_FROM TO V$D);
      -- Ищем какой класс был последний
      IF(V$CALLER_TYPE IN (2, 7, 8)) THEN VAL = VAL || ',c:' || V$GRADE_ID;
      VAL = VAL || '},';
      SUSPEND;
    END

    VAL = '];';
    VAL = VAL || 'cjrCalcEQ(tid, ' || V$CALLER_TYPE || ', m);';
    VAL = VAL || 'cjrCalcEQ(sid, ' || V$CALLER_TYPE || ', m);';
    VAL = VAL || 'cjrCalcEQ(hid, ' || V$CALLER_TYPE || ', m);';
    VAL = VAL || '})();';
    VAL = VAL || '</script>';
    SUSPEND;

  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_REPORT_NX310_FN (
    I$USER_ID BIGINT,
    I$DATE_FROM DATE,
    I$DATE_TO DATE,
    I$PARENT_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$ROOT_ID BIGINT,
    I$OPTION_ID BIGINT,
    I$OPTIONS VARCHAR(1000),
    I$ZONE SMALLINT = 0)
RETURNS (
    VAL VARCHAR(4000))
AS
declare variable V$CALLER_TYPE bigint;
declare variable V$ROOT_TYPE bigint;
declare variable V$USER_TYPE smallint;
declare variable V$OU_LICENCE_TYPE varchar(2);
declare variable V$DATE_TO date;
declare variable V$S1 varchar(400);
declare variable V$S2 varchar(400);
declare variable V$PERSON_ID bigint;
declare variable V$SUBJECT_ID bigint;
declare variable V$N5 integer;
declare variable V$N4 integer;
declare variable V$N3 integer;
declare variable V$N2 integer;
declare variable V$N1 integer;
declare variable V$N0 integer;
declare variable V$C integer;
declare variable V$V float;
declare variable V$N integer;
declare variable V$MC varchar(20);
declare variable V$YEAR_ID bigint;
declare variable V$MT bigint;
declare variable P integer;
declare variable V$OPTION_TYPE bigint;
declare variable V$SO double precision;
declare variable V$PREV_ID bigint;
begin

  if(I$OBJ_ID is null) then I$OBJ_ID = 4404001250949;
  if(I$ROOT_ID is null) then I$ROOT_ID = 4404001250949;
  if(I$DATE_FROM is null) then I$DATE_FROM = '01.09.2023';
  if(I$DATE_to is null) then I$DATE_to = '01.01.2024';

  -- Школа, коллектив, персона
  SELECT TYPE_ID FROM OBJECTS WHERE OBJ_ID = :I$OBJ_ID INTO :V$CALLER_TYPE;
  SELECT TYPE_ID FROM OBJECTS WHERE OBJ_ID = :I$ROOT_ID INTO :V$ROOT_TYPE;
  SELECT STATUS FROM OU_LICENCE_TYPE INTO :V$OU_LICENCE_TYPE;

  V$DATE_TO = DATEADD(7 DAY TO I$DATE_TO);

  SELECT FIRST 1 LV.LISTVAL_ID
  FROM LISTVALS LV
  WHERE LV.LIST_ID = 29 AND LV.COST = EXTRACT(YEAR FROM :I$DATE_FROM) AND LV.IS_DEL = 0
  INTO :V$YEAR_ID;

  -- Тип объекта опции - учитель или предмет
  V$OPTION_TYPE = 0;

  SELECT FIRST 1 TYPE_ID
  FROM OBJECTS
  WHERE OBJ_ID = :I$OPTION_ID
  INTO :V$OPTION_TYPE;

  -- В разбивке по ученику или по классу показываем сразу с разбивкой по предметам и в целом
  -- В разбивке по уровню или параллели показываем две таблицы - по классам и по предметам

  IF(V$CALLER_TYPE IN (10, 9, 187)) THEN
  BEGIN

  VAL = '<table id="t' || I$OBJ_ID || '" class="table centered" cellspacing="0" cellpadding="0" data-flags="sort arrange" style="min-width: 50%">';
  VAL = VAL || '<thead>';
  VAL = VAL || '<tr class="thd">';
    VAL = VAL || '<td class="tl sortable">ФИО</td>';
  SUSPEND;
  -- Список предметов для учеников класса, только действующих
  FOR
    SELECT S.SUBJECT_ID, S.SUBJECT_CODE, S.SUBJECT_NAME
    FROM CJ2_REPORT_NX310_SUBJ(:I$ROOT_ID, :V$ROOT_TYPE, :I$OBJ_ID, 2, :I$DATE_FROM, :V$DATE_TO, :V$YEAR_ID) S
    WHERE (:V$OPTION_TYPE = 51 AND S.SUBJECT_ID = :I$OPTION_ID) OR :V$OPTION_TYPE <> 51
    INTO :V$SUBJECT_ID, :V$S1, :V$S2
  DO
  BEGIN
    VAL = '<td class="sortable value" title="' || (SELECT VAL FROM ESCAPE_STR(:V$S2)) || '"><div class="target subject" data-target="' || V$SUBJECT_ID || '">' || (SELECT VAL FROM ESCAPE_STR(:V$S1)) || '</div></td>';
    SUSPEND;
  END
  --
  VAL = '<td style="width: 4rem">5</td>';
  VAL = VAL || '<td style="width: 4rem">4</td>';
  VAL = VAL || '<td style="width: 4rem">3</td>';
  VAL = VAL || '<td style="width: 4rem">2</td>';
  VAL = VAL || '<td style="width: 4rem">Н/А</td>';
  VAL = VAL || '<td style="width: 4rem">СБ</td>';
  VAL = VAL || '<td style="width: 4rem">СОУ</td>';
  VAL = VAL || '</tr>';
  VAL = VAL || '</thead>';
  VAL = VAL || '<tbody>';
  SUSPEND;

  FOR
    SELECT DISTINCT M.PERSON_ID, P.NAME_FULL --C.CAPTION
    FROM PERSON_MOVEMENTS M
    LEFT JOIN UT_PERSON_DESC(M.PERSON_ID, :I$ZONE, 1) P ON 1 = 1 --Redmine #1060 --LEFT JOIN OBJECT_CAPTION_GET(M.PERSON_ID, 23) C ON 1 = 1
    WHERE M.DATE_DEL IS NULL AND M.GROUP_TYPE_ID IN (9, 187)
      AND (:V$CALLER_TYPE <> 10 OR M.PERSON_ID = :I$OBJ_ID) -- фильтр по конкретному ученику
      AND (:V$CALLER_TYPE NOT IN (9, 187) OR M.GROUP_ID = :I$OBJ_ID) -- фильтр по классу
      AND M.DATE_IN <= :I$DATE_TO AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :I$DATE_FROM)
    ORDER BY 2
    INTO :V$PERSON_ID, :V$S1
  DO
  BEGIN
    V$N5 = 0;
    V$N4 = 0;
    V$N3 = 0;
    V$N2 = 0;
    V$N1 = 0;
    V$N0 = 0;
    V$C = 0;

    VAL = '<tr>';
    IF(V$CALLER_TYPE = 10) THEN
      VAL = VAL || '<td class="tl">' || (SELECT VAL FROM ESCAPE_STR(:V$S1)) || '</td>';
    ELSE
      VAL = VAL || '<td class="target student tl" data-target="' || V$PERSON_ID || '">' || (SELECT VAL FROM ESCAPE_STR(:V$S1)) || '</td>';
    SUSPEND;

    -- Оценки по предметам
    FOR
      SELECT S.SUBJECT_ID
      FROM CJ2_REPORT_NX310_SUBJ(:I$ROOT_ID, :V$ROOT_TYPE, :I$OBJ_ID, 2, :I$DATE_FROM, :V$DATE_TO, :V$YEAR_ID) S
      WHERE (:V$OPTION_TYPE = 51 AND S.SUBJECT_ID = :I$OPTION_ID) OR :V$OPTION_TYPE <> 51
      INTO :V$SUBJECT_ID
    DO
    BEGIN
      VAL = '<td>';
      FOR
        SELECT M.MARKTYPE_ID, R.VAL, R.VAL, LV.COST
        FROM VALM M
        JOIN LISTVALS LV ON LV.LISTVAL_ID = M.MARKVAL_ID
        JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
        JOIN LISTVALS LVT ON LVT.LISTVAL_ID = M.MARKTYPE_ID
        JOIN RES RT ON RT.RES_ID = LVT.RES_ID AND RT.LANG_CODE = 'RU'
        WHERE M.IS_DEL = 0 AND (M.IS_NATIVE IS NULL OR M.IS_NATIVE = 1) AND M.YEAR_ID = :V$YEAR_ID AND M.SUBJECT_ID = :V$SUBJECT_ID AND M.PUPIL_ID = :V$PERSON_ID
          -- AND F.FINAL_DATE >= :I$DATE_FROM AND F.FINAL_DATE <= :V$DATE_TO
          AND M.MARKTYPE_ID <> 3021 -- без ОСВ
          AND M.MARKTYPE_ID NOT IN (3011, 3012, 3013, 5544) -- без годовых
        ORDER BY M.MARKTYPE_ID
        INTO :V$MT, :V$S1, :V$S2, :V$V
      DO
      BEGIN
        -- Название переделываем в вес для отметок
        IF(V$S2 = 'НАУ' OR V$S2 = 'НАН' OR V$S2 = 'НЗТ' OR V$S2 = 'НУСВ') THEN V$V = 0;
        ELSE IF(V$S2 = 'ЗТ' OR V$S2 = 'НАН' OR V$S2 = 'УСВ' OR V$S2 = 'ЗТ') THEN V$V = 5;
        ELSE IF(V$S2 = 'ЧУСВ') THEN V$V = 3;
        ELSE IF(V$V >= 10 AND V$V <= 50) THEN V$V = V$V / 10;
        ELSE IF(V$V = 0 OR V$V IS NULL) THEN
        BEGIN
          P = POSITION('/' IN V$S2);
          IF(P > 0) THEN V$V = 5 * CAST(SUBSTRING(V$S2 FROM 1 FOR P - 1) AS FLOAT) / CAST(SUBSTRING(V$S2 FROM P + 1) AS FLOAT);
        END

        -- По идее 1 в качестве оценки аттестации быть не должно
        IF(V$S2 = 'НАУ' OR V$S2 = 'НАН') THEN BEGIN V$N0 = V$N0 + 1; V$MC = ' pink'; END
        ELSE IF(V$V < 1.5) THEN BEGIN V$N1 = V$N1 + 1; V$MC = ' pink'; END
        ELSE IF(V$V < 2.5) THEN BEGIN V$N2 = V$N2 + 1; V$MC = ' red'; END
        ELSE IF(V$V < 3.5) THEN BEGIN V$N3 = V$N3 + 1; V$MC = ' orange'; END
        ELSE IF(V$V < 4.5) THEN BEGIN V$N4 = V$N4 + 1; V$MC = ' violet'; END
        ELSE BEGIN V$N5 = V$N5 + 1; V$MC = ' blue'; END

        -- VAL = VAL || '<i class="ui circular' || V$MC || ' label">' || V$S2 || '</i>';
        IF(V$MT = 3011) THEN
          VAL = VAL || '<i class="ui circular gray label" title="' || V$S1 || '">' || V$S2 || '</i>';
        ELSE IF(V$MT = 3013) THEN
          VAL = VAL || '<i class="ui circular black label" title="' || V$S1 || '">' || V$S2 || '</i>';
        ELSE
          VAL = VAL || '<i style="margin-right: 4px" title="' || V$S1 || '">' || V$S2 || '</i>';
        V$C = V$C + 1;
      END
      VAL = VAL || '</td>';
      SUSPEND;
    END

    VAL = '<td class="line-left h">' || IIF(V$N5 > 0, V$N5, '&nbsp;') || '</td>';
    VAL = VAL || '<td class="h">' || IIF(V$N4 > 0, V$N4, '&nbsp;') || '</td>';
    VAL = VAL || '<td class="h">' || IIF(V$N3 > 0, V$N3, '&nbsp;') || '</td>';
    VAL = VAL || '<td class="h">' || IIF(V$N2 > 0, V$N2, '&nbsp;') || '</td>';
    VAL = VAL || '<td class="h">' || IIF(V$N0 > 0, V$N0, '&nbsp;') || '</td>';

    -- Средний балл
    VAL = VAL || '<td>' || IIF(V$C > 0, CAST(((V$N5 * 5.0 + V$N4 * 4.0 + V$N3 * 3.0 + V$N2 * 2.0 + V$N1 * 1.0) / V$C) AS NUMERIC(18, 1)), '&nbsp;') || '</td>';
    -- Обученность
    VAL = VAL || '<td>' || IIF(V$C > 0, CAST(((V$N5 * 100.0 + V$N4 * 64.0 + V$N3 * 36.0 + V$N2 * 16 + V$N0 * 7) / V$C) AS NUMERIC(18, 0)), '&nbsp;') || '</td>';

    VAL = VAL || '</tr>';
    SUSPEND;
  END

  -- Строка процентов
  IF(V$CALLER_TYPE = 10) THEN
  BEGIN
    -- VAL = V$SS;
    -- SUSPEND;
  END

  -- Сводные данные по учебному коллективу
  IF(V$CALLER_TYPE IN (9, 187)) THEN
  BEGIN
    V$N5 = 0;
    V$N4 = 0;
    V$N3 = 0;
    V$N2 = 0;
    V$N1 = 0;
    V$N0 = 0;
    V$C = 0;

    -- 5
    VAL = '<tr id="f5" class="line-top f">';
    VAL = VAL || '<td class="tl">5</td>';
    SUSPEND;
    FOR
      SELECT S.SUBJECT_ID
      FROM CJ2_REPORT_NX310_SUBJ(:I$ROOT_ID, :V$ROOT_TYPE, :I$OBJ_ID, 2, :I$DATE_FROM, :V$DATE_TO, :V$YEAR_ID) S
      WHERE (:V$OPTION_TYPE = 51 AND S.SUBJECT_ID = :I$OPTION_ID) OR :V$OPTION_TYPE <> 51
      INTO :V$SUBJECT_ID
    DO
    BEGIN
      SELECT COUNT(DISTINCT M.MARK_ID)
      FROM PERSON_MOVEMENTS MV
      JOIN VALM M ON M.IS_DEL = 0 AND (M.IS_NATIVE IS NULL OR M.IS_NATIVE = 1) AND M.YEAR_ID = :V$YEAR_ID AND M.SUBJECT_ID = :V$SUBJECT_ID
        AND M.PUPIL_ID = MV.PERSON_ID
        -- AND F.FINAL_DATE >= :I$DATE_FROM AND F.FINAL_DATE <= :V$DATE_TO
      WHERE MV.DATE_DEL IS NULL
        AND (:V$CALLER_TYPE <> 10 OR MV.PERSON_ID = :I$OBJ_ID) -- фильтр по конкретному ученику
        AND (:V$CALLER_TYPE NOT IN (9, 187) OR MV.GROUP_ID = :I$OBJ_ID) -- фильтр по классу
        AND MV.DATE_IN <= :I$DATE_TO AND (MV.DATE_OUT IS NULL OR MV.DATE_OUT >= :I$DATE_FROM)
        -- AND MT.MARK_COST >= 4.5
        AND M.MARKVAL_ID = 3018 -- !!!
      INTO :V$N;
      V$N5 = V$N5 + V$N;
      V$C = V$C + V$N;
      VAL = '<td class="s">' || IIF(V$N > 0, V$N, '&nbsp;') || '</td>';
      SUSPEND;
    END

    VAL = '<td class="line-left">' || IIF(V$N5 > 0, V$N5, '&nbsp;') || '</td>';
    VAL = VAL || '<td>&nbsp;</td>';
    VAL = VAL || '<td>&nbsp;</td>';
    VAL = VAL || '<td>&nbsp;</td>';
    VAL = VAL || '<td>&nbsp;</td>';
    VAL = VAL || '<td>&nbsp;</td>'; -- СБ
    VAL = VAL || '<td>&nbsp;</td>';
    VAL = VAL || '</tr>';
    SUSPEND;

    -- 4
    VAL = '<tr id="f4" class="f">';
    VAL = VAL || '<td class="tl">4</td>';
    SUSPEND;
    FOR
      SELECT S.SUBJECT_ID
      FROM CJ2_REPORT_NX310_SUBJ(:I$ROOT_ID, :V$ROOT_TYPE, :I$OBJ_ID, 2, :I$DATE_FROM, :V$DATE_TO, :V$YEAR_ID) S
      WHERE (:V$OPTION_TYPE = 51 AND S.SUBJECT_ID = :I$OPTION_ID) OR :V$OPTION_TYPE <> 51
      INTO :V$SUBJECT_ID
    DO
    BEGIN
      SELECT COUNT(DISTINCT M.MARK_ID)
      FROM PERSON_MOVEMENTS MV
      JOIN VALM M ON M.IS_DEL = 0 AND (M.IS_NATIVE IS NULL OR M.IS_NATIVE = 1) AND M.YEAR_ID = :V$YEAR_ID AND M.SUBJECT_ID = :V$SUBJECT_ID
        AND M.PUPIL_ID = MV.PERSON_ID
        -- AND F.FINAL_DATE >= :I$DATE_FROM AND F.FINAL_DATE <= :V$DATE_TO
      WHERE MV.DATE_DEL IS NULL
        AND (:V$CALLER_TYPE <> 10 OR MV.PERSON_ID = :I$OBJ_ID) -- фильтр по конкретному ученику
        AND (:V$CALLER_TYPE NOT IN (9, 187) OR MV.GROUP_ID = :I$OBJ_ID) -- фильтр по классу
        AND MV.DATE_IN <= :I$DATE_TO AND (MV.DATE_OUT IS NULL OR MV.DATE_OUT >= :I$DATE_FROM)
        -- AND MT.MARK_COST >= 4.5
        AND M.MARKVAL_ID = 3017 -- !!!
      INTO :V$N;
      V$N4 = V$N4 + V$N;
      V$C = V$C + V$N;
      VAL = '<td class="s">' || IIF(V$N > 0, V$N, '&nbsp;') || '</td>';
      SUSPEND;
    END

    VAL = '<td class="line-left">&nbsp;</td>';
    VAL = VAL || '<td>' || IIF(V$N4 > 0, V$N4, '&nbsp;') || '</td>';
    VAL = VAL || '<td>&nbsp;</td>';
    VAL = VAL || '<td>&nbsp;</td>';
    VAL = VAL || '<td>&nbsp;</td>';
    VAL = VAL || '<td>&nbsp;</td>'; -- СБ
    VAL = VAL || '<td>&nbsp;</td>';
    VAL = VAL || '</tr>';
    SUSPEND;

    -- 3
    VAL = '<tr id="f3" class="f">';
    VAL = VAL || '<td class="tl">3</td>';
    SUSPEND;
    FOR
      SELECT S.SUBJECT_ID
      FROM CJ2_REPORT_NX310_SUBJ(:I$ROOT_ID, :V$ROOT_TYPE, :I$OBJ_ID, 2, :I$DATE_FROM, :V$DATE_TO, :V$YEAR_ID) S
      WHERE (:V$OPTION_TYPE = 51 AND S.SUBJECT_ID = :I$OPTION_ID) OR :V$OPTION_TYPE <> 51
      INTO :V$SUBJECT_ID
    DO
    BEGIN
      SELECT COUNT(DISTINCT M.MARK_ID)
      FROM PERSON_MOVEMENTS MV
      JOIN VALM M ON M.IS_DEL = 0 AND (M.IS_NATIVE IS NULL OR M.IS_NATIVE = 1) AND M.YEAR_ID = :V$YEAR_ID AND M.SUBJECT_ID = :V$SUBJECT_ID
        AND M.PUPIL_ID = MV.PERSON_ID
        -- AND F.FINAL_DATE >= :I$DATE_FROM AND F.FINAL_DATE <= :V$DATE_TO
      WHERE MV.DATE_DEL IS NULL
        AND (:V$CALLER_TYPE <> 10 OR MV.PERSON_ID = :I$OBJ_ID) -- фильтр по конкретному ученику
        AND (:V$CALLER_TYPE NOT IN (9, 187) OR MV.GROUP_ID = :I$OBJ_ID) -- фильтр по классу
        AND MV.DATE_IN <= :I$DATE_TO AND (MV.DATE_OUT IS NULL OR MV.DATE_OUT >= :I$DATE_FROM)
        -- AND MT.MARK_COST >= 4.5
        AND M.MARKVAL_ID = 3016 -- !!!
      INTO :V$N;
      V$N3 = V$N3 + V$N;
      V$C = V$C + V$N;
      VAL = '<td class="s">' || IIF(V$N > 0, V$N, '&nbsp;') || '</td>';
      SUSPEND;
    END

    VAL = '<td class="line-left">&nbsp;</td>';
    VAL = VAL || '<td>&nbsp;</td>';
    VAL = VAL || '<td>' || IIF(V$N3 > 0, V$N3, '&nbsp;') || '</td>';
    VAL = VAL || '<td>&nbsp;</td>';
    VAL = VAL || '<td>&nbsp;</td>';
    VAL = VAL || '<td>&nbsp;</td>'; -- СБ
    VAL = VAL || '<td>&nbsp;</td>';
    VAL = VAL || '</tr>';
    SUSPEND;

    -- 2
    VAL = '<tr id="f2" class="f">';
    VAL = VAL || '<td class="tl">2</td>';
    SUSPEND;
    FOR
      SELECT S.SUBJECT_ID
      FROM CJ2_REPORT_NX310_SUBJ(:I$ROOT_ID, :V$ROOT_TYPE, :I$OBJ_ID, 2, :I$DATE_FROM, :V$DATE_TO, :V$YEAR_ID) S
      WHERE (:V$OPTION_TYPE = 51 AND S.SUBJECT_ID = :I$OPTION_ID) OR :V$OPTION_TYPE <> 51
      INTO :V$SUBJECT_ID
    DO
    BEGIN
      SELECT COUNT(DISTINCT M.MARK_ID)
      FROM PERSON_MOVEMENTS MV
      JOIN VALM M ON M.IS_DEL = 0 AND (M.IS_NATIVE IS NULL OR M.IS_NATIVE = 1) AND M.YEAR_ID = :V$YEAR_ID AND M.SUBJECT_ID = :V$SUBJECT_ID
        AND M.PUPIL_ID = MV.PERSON_ID
        -- AND F.FINAL_DATE >= :I$DATE_FROM AND F.FINAL_DATE <= :V$DATE_TO
      WHERE MV.DATE_DEL IS NULL
        AND (:V$CALLER_TYPE <> 10 OR MV.PERSON_ID = :I$OBJ_ID) -- фильтр по конкретному ученику
        AND (:V$CALLER_TYPE NOT IN (9, 187) OR MV.GROUP_ID = :I$OBJ_ID) -- фильтр по классу
        AND MV.DATE_IN <= :I$DATE_TO AND (MV.DATE_OUT IS NULL OR MV.DATE_OUT >= :I$DATE_FROM)
        AND M.MARKVAL_ID IN (3014, 3015) -- !!!
      INTO :V$N;
      V$N2 = V$N2 + V$N;
      V$C = V$C + V$N;
      VAL = '<td class="s">' || IIF(V$N > 0, V$N, '&nbsp;') || '</td>';
      SUSPEND;
    END

    VAL = '<td class="line-left">&nbsp;</td>';
    VAL = VAL || '<td>&nbsp;</td>';
    VAL = VAL || '<td>&nbsp;</td>';
    VAL = VAL || '<td>' || IIF(V$N2 > 0, V$N2, '&nbsp;') || '</td>';
    VAL = VAL || '<td>&nbsp;</td>';
    VAL = VAL || '<td>&nbsp;</td>'; -- СБ
    VAL = VAL || '<td>&nbsp;</td>';
    VAL = VAL || '</tr>';
    SUSPEND;

    -- Не аттестован
    VAL = '<tr id="f0" class="f">';
    VAL = VAL || '<td class="tl">Н/А</td>';
    SUSPEND;
    FOR
      SELECT S.SUBJECT_ID
      FROM CJ2_REPORT_NX310_SUBJ(:I$ROOT_ID, :V$ROOT_TYPE, :I$OBJ_ID, 2, :I$DATE_FROM, :V$DATE_TO, :V$YEAR_ID) S
      WHERE (:V$OPTION_TYPE = 51 AND S.SUBJECT_ID = :I$OPTION_ID) OR :V$OPTION_TYPE <> 51
      INTO :V$SUBJECT_ID
    DO
    BEGIN
      SELECT COUNT(DISTINCT M.MARK_ID)
      FROM PERSON_MOVEMENTS MV
      JOIN VALM M ON M.IS_DEL = 0 AND (M.IS_NATIVE IS NULL OR M.IS_NATIVE = 1) AND M.YEAR_ID = :V$YEAR_ID AND M.SUBJECT_ID = :V$SUBJECT_ID
        AND M.PUPIL_ID = MV.PERSON_ID
        -- AND F.FINAL_DATE >= :I$DATE_FROM AND F.FINAL_DATE <= :V$DATE_TO
      WHERE MV.DATE_DEL IS NULL
        AND (:V$CALLER_TYPE <> 10 OR MV.PERSON_ID = :I$OBJ_ID) -- фильтр по конкретному ученику
        AND (:V$CALLER_TYPE NOT IN (9, 187) OR MV.GROUP_ID = :I$OBJ_ID) -- фильтр по классу
        AND MV.DATE_IN <= :I$DATE_TO AND (MV.DATE_OUT IS NULL OR MV.DATE_OUT >= :I$DATE_FROM)
        AND M.MARKVAL_ID IN (3022, 3023) -- !!!
      INTO :V$N;
      V$N0 = V$N0 + V$N;
      V$C = V$C + V$N;
      VAL = '<td class="s">' || IIF(V$N > 0, V$N, '&nbsp;') || '</td>';
      SUSPEND;
    END

    VAL = '<td class="line-left">&nbsp;</td>';
    VAL = VAL || '<td>&nbsp;</td>';
    VAL = VAL || '<td>&nbsp;</td>';
    VAL = VAL || '<td>&nbsp;</td>';
    VAL = VAL || '<td>' || IIF(V$N0 > 0, V$N0, '&nbsp;') || '</td>';
    VAL = VAL || '<td>&nbsp;</td>'; -- СБ
    VAL = VAL || '<td>&nbsp;</td>';
    VAL = VAL || '</tr>';
    SUSPEND;

    -- СБ
    VAL = '<tr id="fb" class="line-top f">';
    VAL = VAL || '</tr>';
    SUSPEND;

    -- СОУ
    VAL = '<tr id="fe" class="f">';
    VAL = VAL || '</tr>';
    SUSPEND;
  END

  VAL = '</tbody></table>';
  SUSPEND;

  VAL = '<script>';
  VAL = VAL || '(function () { ';
  VAL = VAL || 'let tid = "#t' || I$OBJ_ID || '";';
  VAL = VAL || 'let s1 = "<td class=''tl''>Средний балл</td>", s2 = "<td class=''tl''>Обученность</td>", sc = 0, sn5 = 0, sn4 = 0, sn3 = 0, sn2 = 0, sn0 = 0;';
  VAL = VAL || '$(tid + " #f5 .s").each((n, el) => {';
  VAL = VAL || 'let n5 = parseInt($(tid + " #f5 .s:eq(" + n + ")").text()); if(isNaN(n5)) n5 = 0;';
  VAL = VAL || 'let n4 = parseInt($(tid + " #f4 .s:eq(" + n + ")").text()); if(isNaN(n4)) n4 = 0;';
  VAL = VAL || 'let n3 = parseInt($(tid + " #f3 .s:eq(" + n + ")").text()); if(isNaN(n3)) n3 = 0;';
  VAL = VAL || 'let n2 = parseInt($(tid + " #f2 .s:eq(" + n + ")").text()); if(isNaN(n2)) n2 = 0;';
  VAL = VAL || 'let n0 = parseInt($(tid + " #f0 .s:eq(" + n + ")").text()); if(isNaN(n0)) n0 = 0;';
  VAL = VAL || 'let c = n5 + n4 + n3 + n2 + n0;';
  VAL = VAL || 'let v1 = n5 * 5 + n4 * 4 + n3 * 3 + n2 * 2;';
  VAL = VAL || 'let v2 = n5 * 100 + n4 * 64 + n3 * 36 + n2 * 16 + n0 * 7;';
  VAL = VAL || 'sc += c; sn5 += n5; sn4 += n4; sn3 += n3; sn2 += n2;';
  VAL = VAL || 's1 += "<td>" + (c > 0 ? (v1 / c).toFixed(2) : "&nbsp;") + "</td>";';
  VAL = VAL || 's2 += "<td>" + (c > 0 ? (v2 / c).toFixed(0) : "&nbsp;") + "</td>";';
  VAL = VAL || '});';
  VAL = VAL || 'let v1 = sn5 * 5 + sn4 * 4 + sn3 * 3 + sn2 * 2;';
  VAL = VAL || 'let v2 = sn5 * 100 + sn4 * 64 + sn3 * 36 + sn2 * 16 + sn0 * 7;';
  VAL = VAL || 's1 += "<td class=''line-left h''>&nbsp;</td>";';
  VAL = VAL || 's1 += "<td class=''h''>&nbsp;</td>";';
  VAL = VAL || 's1 += "<td class=''h''>&nbsp;</td>";';
  VAL = VAL || 's1 += "<td class=''h''>&nbsp;</td>";';
  VAL = VAL || 's1 += "<td class=''h''>&nbsp;</td>";';
  VAL = VAL || 's1 += "<td>" + (sc > 0 ? (v1 / sc).toFixed(2) : "&nbsp;") + "</td>";';
  VAL = VAL || 's1 += "<td>&nbsp;</td>";';
  VAL = VAL || 's2 += "<td class=''line-left h''>&nbsp;</td>";';
  VAL = VAL || 's2 += "<td class=''h''>&nbsp;</td>";';
  VAL = VAL || 's2 += "<td class=''h''>&nbsp;</td>";';
  VAL = VAL || 's2 += "<td class=''h''>&nbsp;</td>";';
  VAL = VAL || 's2 += "<td class=''h''>&nbsp;</td>";';
  VAL = VAL || 's2 += "<td>&nbsp;</td>";';
  VAL = VAL || 's2 += "<td>" + (sc > 0 ? (v2 / sc).toFixed(0) : "&nbsp;") + "</td>";';
  VAL = VAL || '$(tid + " #fb").html(s1);';
  VAL = VAL || '$(tid + " #fe").html(s2);';
  VAL = VAL || '})();';
  VAL = VAL || '</script>';
  SUSPEND;

  END
  ELSE
  BEGIN

    VAL = '<table id="t' || I$OBJ_ID || '" class="table centered" cellspacing="0" cellpadding="0" data-flags="sort arrange" style="min-width: 50%">';
    VAL = VAL || '<thead>';
    VAL = VAL || '<tr class="thd">';
      VAL = VAL || '<td class="tl sortable">Учебный коллектив</td>';
      VAL = VAL || '<td class="sortable value" style="width: 4rem">5</td>';
      VAL = VAL || '<td class="sortable value" style="width: 4rem">4</td>';
      VAL = VAL || '<td class="sortable value" style="width: 4rem">3</td>';
      VAL = VAL || '<td class="sortable value" style="width: 4rem">2</td>';
      VAL = VAL || '<td class="sortable value" style="width: 4rem">Н/А</td>';
      VAL = VAL || '<td class="sortable value" style="width: 4rem">СБ</td>';
      VAL = VAL || '<td class="sortable value" style="width: 4rem">СОУ</td>';
      VAL = VAL || '</tr>';
    VAL = VAL || '</tr></thead><tbody>';
    SUSPEND;

    FOR
      SELECT L9.OBJ_ID, C.CAPTION, C.SORT_ORDER
      FROM LINKS L2
      JOIN LINKS L8 ON L8.PARENT_ID = L2.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
      LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C ON 1 = 1
      WHERE L2.PARENT_ID = :I$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND :V$CALLER_TYPE = 2
      UNION
      SELECT L9.OBJ_ID, C.CAPTION, C.SORT_ORDER
      FROM LINKS L8
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
      LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C ON 1 = 1
      WHERE L8.PARENT_ID = :I$OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL AND :V$CALLER_TYPE = 7
      UNION
      SELECT L9.OBJ_ID, C.CAPTION, C.SORT_ORDER
      FROM LINKS L9
      LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C ON 1 = 1
      WHERE L9.PARENT_ID = :I$OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL AND :V$CALLER_TYPE = 8
      ORDER BY 3, 2
      INTO :V$PERSON_ID, :V$S1, :V$SO
    DO
    BEGIN
      VAL = '<tr>';
        VAL = VAL || '<td class="target class tl" data-target="' || V$PERSON_ID || '">' || V$S1 || '</td>';
        VAL = VAL || '<td>&nbsp;</td>';
        VAL = VAL || '<td>&nbsp;</td>';
        VAL = VAL || '<td>&nbsp;</td>';
        VAL = VAL || '<td>&nbsp;</td>';
        VAL = VAL || '<td>&nbsp;</td>';
        VAL = VAL || '<td>&nbsp;</td>';
        VAL = VAL || '<td>&nbsp;</td>';
      VAL = VAL || '</tr>';
      SUSPEND;
    END

    VAL = '</tbody></table>';
    SUSPEND;

    VAL = '<table id="s' || I$OBJ_ID || '" class="table centered" cellspacing="0" cellpadding="0" data-flags="sort arrange" style="min-width: 50%">';
    VAL = VAL || '<thead>';
    VAL = VAL || '<tr class="thd">';
      VAL = VAL || '<td class="tl sortable">Предмет</td>';
      VAL = VAL || '<td class="sortable value" style="width: 4rem">5</td>';
      VAL = VAL || '<td class="sortable value" style="width: 4rem">4</td>';
      VAL = VAL || '<td class="sortable value" style="width: 4rem">3</td>';
      VAL = VAL || '<td class="sortable value" style="width: 4rem">2</td>';
      VAL = VAL || '<td class="sortable value" style="width: 4rem">Н/А</td>';
      VAL = VAL || '<td class="sortable value" style="width: 4rem">СБ</td>';
      VAL = VAL || '<td class="sortable value" style="width: 4rem">СОУ</td>';
      VAL = VAL || '</tr>';
    VAL = VAL || '</tr></thead><tbody>';
    SUSPEND;

    FOR
      SELECT S.SUBJECT_ID, C.CAPTION
      FROM CJ2_REPORT_NX310_SUBJ(:I$OBJ_ID, :V$CALLER_TYPE, :I$OBJ_ID, 2, :I$DATE_FROM, :V$DATE_TO, IIF(:V$OPTION_TYPE = 14, :I$OPTION_ID, NULL)) S
      LEFT JOIN OBJECT_CAPTION_GET(S.SUBJECT_ID) C ON 1 = 1
      WHERE (:V$OPTION_TYPE = 51 AND S.SUBJECT_ID = :I$OPTION_ID) OR :V$OPTION_TYPE <> 51
      INTO :V$SUBJECT_ID, :V$S1
    DO
    BEGIN
      VAL = '<tr>';
        VAL = VAL || '<td  class="target subject tl" data-target="' || V$SUBJECT_ID || '">' || V$S1 || '</td>';
        VAL = VAL || '<td>&nbsp;</td>';
        VAL = VAL || '<td>&nbsp;</td>';
        VAL = VAL || '<td>&nbsp;</td>';
        VAL = VAL || '<td>&nbsp;</td>';
        VAL = VAL || '<td>&nbsp;</td>';
        VAL = VAL || '<td>&nbsp;</td>';
        VAL = VAL || '<td>&nbsp;</td>';
      VAL = VAL || '</tr>';
      SUSPEND;
    END

    VAL = '</tbody></table>';
    SUSPEND;

    VAL = '<table id="h' || I$OBJ_ID || '" class="table centered" cellspacing="0" cellpadding="0" data-flags="sort arrange" style="min-width: 50%">';
    VAL = VAL || '<thead>';
    VAL = VAL || '<tr class="thd">';
      VAL = VAL || '<td class="tl sortable">Преподаватель</td>';
      VAL = VAL || '<td class="sortable value" style="width: 4rem">5</td>';
      VAL = VAL || '<td class="sortable value" style="width: 4rem">4</td>';
      VAL = VAL || '<td class="sortable value" style="width: 4rem">3</td>';
      VAL = VAL || '<td class="sortable value" style="width: 4rem">2</td>';
      VAL = VAL || '<td class="sortable value" style="width: 4rem">Н/А</td>';
      VAL = VAL || '<td class="sortable value" style="width: 4rem">СБ</td>';
      VAL = VAL || '<td class="sortable value" style="width: 4rem">СОУ</td>';
      VAL = VAL || '</tr>';
    VAL = VAL || '</tr></thead><tbody>';
    SUSPEND;

    -- Собираем список преподавателей
    V$PREV_ID = 0;
    VAL = '';
    FOR
      SELECT DISTINCT S.TEACHER_ID, P.NAME_FULL --C.CAPTION
                    , S.SUBJECT_NAME
      FROM CJ2_REPORT_NX310_SUBJ(:I$OBJ_ID, :V$CALLER_TYPE, :I$OBJ_ID, 2, :I$DATE_FROM, :V$DATE_TO, NULL, IIF(:V$OPTION_TYPE = 14, :I$OPTION_ID, -1)) S
      LEFT JOIN UT_PERSON_DESC(S.TEACHER_ID, :I$ZONE, 1) P ON 1 = 1 --Redmine #1060 --LEFT JOIN OBJECT_CAPTION_GET(S.TEACHER_ID) C ON 1 = 1
      WHERE (
        ((:V$OPTION_TYPE = 51 AND S.SUBJECT_ID = :I$OPTION_ID) OR :V$OPTION_TYPE <> 51)
      )
      ORDER BY 2, 3
      INTO :V$SUBJECT_ID, :V$S1, :V$S2
    DO
    BEGIN
      IF(V$SUBJECT_ID <> V$PREV_ID) THEN
      BEGIN
        IF(V$PREV_ID > 0) THEN
        BEGIN
          VAL = VAL || ')</td>';
          VAL = VAL || '<td>&nbsp;</td>';
          VAL = VAL || '<td>&nbsp;</td>';
          VAL = VAL || '<td>&nbsp;</td>';
          VAL = VAL || '<td>&nbsp;</td>';
          VAL = VAL || '<td>&nbsp;</td>';
          VAL = VAL || '<td>&nbsp;</td>';
          VAL = VAL || '<td>&nbsp;</td>';
          VAL = VAL || '</tr>';
          SUSPEND;
        END

        VAL = '<tr>';
        VAL = VAL || '<td  class="target teacher tl" data-target="' || V$SUBJECT_ID || '">' || V$S1 || ' (' || V$S2;
      END
      ELSE
      BEGIN
        VAL = VAL || ', ' || V$S2;
      END
      V$PREV_ID = V$SUBJECT_ID;
    END
    IF(V$PREV_ID > 0) THEN
    BEGIN
      VAL = VAL || ')</td>';
      VAL = VAL || '<td>&nbsp;</td>';
      VAL = VAL || '<td>&nbsp;</td>';
      VAL = VAL || '<td>&nbsp;</td>';
      VAL = VAL || '<td>&nbsp;</td>';
      VAL = VAL || '<td>&nbsp;</td>';
      VAL = VAL || '<td>&nbsp;</td>';
      VAL = VAL || '<td>&nbsp;</td>';
      VAL = VAL || '</tr>';
      SUSPEND;
    END

    VAL = '</tbody></table>';
    SUSPEND;

  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_REPORT_NX310_PA (
    I$USER_ID BIGINT,
    I$DATE_FROM DATE,
    I$DATE_TO DATE,
    I$PARENT_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$ROOT_ID BIGINT,
    I$OPTION_ID BIGINT,
    I$OPTIONS VARCHAR(1000),
    I$ZONE SMALLINT = 0)
RETURNS (
    VAL VARCHAR(4000))
AS
declare variable V$CALLER_TYPE bigint;
declare variable V$ROOT_TYPE bigint;
declare variable V$USER_TYPE smallint;
declare variable V$OU_LICENCE_TYPE varchar(2);
declare variable V$DATE_TO date;
declare variable V$S1 varchar(400);
declare variable V$S2 varchar(400);
declare variable V$PERSON_ID bigint;
declare variable V$SUBJECT_ID bigint;
declare variable V$N5 integer;
declare variable V$N4 integer;
declare variable V$N3 integer;
declare variable V$N2 integer;
declare variable V$N0 integer;
declare variable V$C integer;
declare variable V$V float;
declare variable V$N integer;
declare variable V$MC varchar(20);
declare variable V$SS varchar(4000);
declare variable V$B integer;
declare variable V$OPTION_TYPE bigint;
declare variable V$SO double precision;
declare variable V$D date;
declare variable V$GRADE_ID bigint;
declare variable V$TEACHER_ID bigint;
declare variable V$PREV_ID bigint;
begin

  -- I$OBJ_ID указывает реальный уровень, для которого выполняется выборка
  -- I$ROOT_ID указывает объект, для которого выполняется весь отчет
  -- при выборе раскрытия детализации ROOT_ID будет параллель или уровень, OBJ_ID будет класс

  if(I$OBJ_ID is null) then I$OBJ_ID = 4404001250949;
  if(I$ROOT_ID is null) then I$ROOT_ID = 4404001250949;
  if(I$DATE_FROM is null) then I$DATE_FROM = '01.09.2023';
  if(I$DATE_to is null) then I$DATE_to = '01.01.2024';

  -- Школа, коллектив, персона
  SELECT TYPE_ID FROM OBJECTS WHERE OBJ_ID = :I$OBJ_ID INTO :V$CALLER_TYPE;
  SELECT TYPE_ID FROM OBJECTS WHERE OBJ_ID = :I$ROOT_ID INTO :V$ROOT_TYPE;
  SELECT STATUS FROM OU_LICENCE_TYPE INTO :V$OU_LICENCE_TYPE;

  V$DATE_TO = DATEADD(7 DAY TO I$DATE_TO);

  -- Тип объекта опции - учитель или предмет
  V$OPTION_TYPE = 0;

  SELECT FIRST 1 TYPE_ID
  FROM OBJECTS
  WHERE OBJ_ID = :I$OPTION_ID
  INTO :V$OPTION_TYPE;

  -- В разбивке по ученику или по классу показываем сразу с разбивкой по предметам и в целом
  -- В разбивке по уровню или параллели показываем две таблицы - по классам и по предметам

  IF(V$CALLER_TYPE IN (10, 9, 187)) THEN
  BEGIN

    -- arrange не особо имеет смысл, поскольку разбивка идет по #data
    VAL = '<table id="t' || I$OBJ_ID || '" class="table centered" cellspacing="0" cellpadding="0" data-flags="sort arrange" style="min-width: 50%">';
    VAL = VAL || '<thead>';
    VAL = VAL || '<tr class="thd">';
      VAL = VAL || '<td class="tl sortable">ФИО</td>';
    SUSPEND;
    -- Список предметов для учеников класса, только действующих
    FOR
      SELECT S.SUBJECT_ID, S.SUBJECT_CODE, S.SUBJECT_NAME
      FROM CJ2_REPORT_NX310_SUBJ(:I$ROOT_ID, :V$ROOT_TYPE, :I$OBJ_ID, 0, :I$DATE_FROM, :V$DATE_TO) S
      WHERE (:V$OPTION_TYPE = 51 AND S.SUBJECT_ID = :I$OPTION_ID) OR :V$OPTION_TYPE <> 51
      INTO :V$SUBJECT_ID, :V$S1, :V$S2
    DO
    BEGIN
      VAL = '<td class="sortable value" title="' || (SELECT VAL FROM ESCAPE_STR(:V$S2)) || '"><div class="target subject" data-target="' || V$SUBJECT_ID || '">' || (SELECT VAL FROM ESCAPE_STR(:V$S1)) || '</div></td>';
      SUSPEND;
    END
    --
    VAL = '<td class="sortable value" style="width: 4rem">5</td>';
    VAL = VAL || '<td class="sortable value" style="width: 4rem">4</td>';
    VAL = VAL || '<td class="sortable value" style="width: 4rem">3</td>';
    VAL = VAL || '<td class="sortable value" style="width: 4rem">2</td>';
    VAL = VAL || '<td class="sortable value" style="width: 4rem">Н/А</td>';
    VAL = VAL || '<td class="sortable value" style="width: 4rem">СБ</td>';
    VAL = VAL || '<td class="sortable value" style="width: 4rem">СОУ</td>';
    VAL = VAL || '</tr>';
    VAL = VAL || '</thead>';
    VAL = VAL || '<tbody>';
    SUSPEND;

  FOR
    SELECT DISTINCT M.PERSON_ID, P.NAME_FULL --C.CAPTION
    FROM PERSON_MOVEMENTS M
    LEFT JOIN UT_PERSON_DESC(M.PERSON_ID, :I$ZONE, 1) P ON 1 = 1 --Redmine #1060 --LEFT JOIN OBJECT_CAPTION_GET(M.PERSON_ID, 23) C ON 1 = 1
    WHERE M.DATE_DEL IS NULL AND M.GROUP_TYPE_ID IN (9, 187)
      AND (:V$CALLER_TYPE <> 10 OR M.PERSON_ID = :I$OBJ_ID) -- фильтр по конкретному ученику
      AND (:V$CALLER_TYPE NOT IN (9, 187) OR M.GROUP_ID = :I$OBJ_ID) -- фильтр по классу
      AND M.DATE_IN <= :I$DATE_TO AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :I$DATE_FROM)
    ORDER BY 2
    INTO :V$PERSON_ID, :V$S1
  DO
  BEGIN
    V$N5 = 0;
    V$N4 = 0;
    V$N3 = 0;
    V$N2 = 0;
    V$N0 = 0;
    V$C = 0;

    VAL = '<tr>';
    IF(V$CALLER_TYPE = 10) THEN
      VAL = VAL || '<td class="tl">' || (SELECT VAL FROM ESCAPE_STR(:V$S1)) || '</td>';
    ELSE
      VAL = VAL || '<td class="target student tl" data-target="' || V$PERSON_ID || '">' || (SELECT VAL FROM ESCAPE_STR(:V$S1)) || '</td>';
    SUSPEND;

    V$SS = '<tr><td class="tl">&nbsp;</td>';

    -- Оценки по предметам
    FOR
      SELECT S.SUBJECT_ID
      FROM CJ2_REPORT_NX310_SUBJ(:I$ROOT_ID, :V$ROOT_TYPE, :I$OBJ_ID, 0, :I$DATE_FROM, :V$DATE_TO) S
      WHERE (:V$OPTION_TYPE = 51 AND S.SUBJECT_ID = :I$OPTION_ID) OR :V$OPTION_TYPE <> 51
      INTO :V$SUBJECT_ID
    DO
    BEGIN
      VAL = '<td>';
      FOR
        SELECT MT.MARK_SHORTNAME, MT.MARK_COST
        FROM CJ2_MARK M
        JOIN CJ2_JOURNAL_FINALS F ON F.OBJ_ID = M.FINAL_ID
        JOIN CJ2_JOURNAL J ON J.OBJ_ID = F.CJ_ID AND J.JOURNAL_TYPE = 0 AND J.SUBJECT_ID = :V$SUBJECT_ID
        JOIN CJ2_MARK_TYPE MT ON MT.MARK_TYPE_ID = M.MARK_TYPE_ID
        WHERE M.DATE_DEL IS NULL AND M.STUDENT_ID = :V$PERSON_ID
          AND F.FINAL_DATE >= :I$DATE_FROM AND F.FINAL_DATE <= :V$DATE_TO
        ORDER BY F.FINAL_DATE
        INTO :V$S2, :V$V
      DO
      BEGIN
        -- По идее 1 в качестве оценки аттестации быть не должно
        IF(V$S2 = 'НАУ' OR V$S2 = 'НАН') THEN BEGIN V$N0 = V$N0 + 1; V$MC = ' pink'; END
        ELSE IF(V$V < 1.5) THEN BEGIN V$N2 = V$N2 + 1; V$MC = ' pink'; END
        ELSE IF(V$V < 2.5) THEN BEGIN V$N2 = V$N2 + 1; V$MC = ' red'; END
        ELSE IF(V$V < 3.5) THEN BEGIN V$N3 = V$N3 + 1; V$MC = ' orange'; END
        ELSE IF(V$V < 4.5) THEN BEGIN V$N4 = V$N4 + 1; V$MC = ' violet'; END
        ELSE BEGIN V$N5 = V$N5 + 1; V$MC = ' blue'; END

        VAL = VAL || '<i class="ui circular' || V$MC || ' label">' || V$S2 || '</i>';
        V$C = V$C + 1;
      END
      VAL = VAL || '</td>';
      SUSPEND;

      V$SS = V$SS || '<td>&nbsp;</td>';
    END

    VAL = '<td class="line-left h">' || IIF(V$N5 > 0, V$N5, '&nbsp;') || '</td>';
    VAL = VAL || '<td class="h">' || IIF(V$N4 > 0, V$N4, '&nbsp;') || '</td>';
    VAL = VAL || '<td class="h">' || IIF(V$N3 > 0, V$N3, '&nbsp;') || '</td>';
    VAL = VAL || '<td class="h">' || IIF(V$N2 > 0, V$N2, '&nbsp;') || '</td>';
    VAL = VAL || '<td class="h">' || IIF(V$N0 > 0, V$N0, '&nbsp;') || '</td>';

    -- Средний балл
    -- единиц тут по идее быть не должно
    VAL = VAL || '<td>' || IIF(V$C > 0, CAST(((V$N5 * 5.0 + V$N4 * 4.0 + V$N3 * 3.0 + V$N2 * 2.0) / V$C) AS NUMERIC(18, 1)), '&nbsp;') || '</td>';
    -- Обученность
    VAL = VAL || '<td>' || IIF(V$C > 0, CAST(((V$N5 * 100.0 + V$N4 * 64.0 + V$N3 * 36.0 + V$N2 * 16 + V$N0 * 7) / V$C) AS NUMERIC(18, 0)), '&nbsp;') || '</td>';

    VAL = VAL || '</tr>';
    SUSPEND;

    V$B = V$N5 + V$N4 + V$N3 + V$N2 + V$N0;
    IF(V$B = 0) THEN V$B = 1;
    V$SS = V$SS || '<td>' || CAST(100 * V$N5 / V$B AS NUMERIC(18, 1)) || '%</td>';
    V$SS = V$SS || '<td>' || CAST(100 * V$N4 / V$B AS NUMERIC(18, 1)) || '%</td>';
    V$SS = V$SS || '<td>' || CAST(100 * V$N3 / V$B AS NUMERIC(18, 1)) || '%</td>';
    V$SS = V$SS || '<td>' || CAST(100 * V$N2 / V$B AS NUMERIC(18, 1)) || '%</td>';
    V$SS = V$SS || '<td>' || CAST(100 * V$N0 / V$B AS NUMERIC(18, 1)) || '%</td>';
    V$SS = V$SS || '<td>&nbsp;</td><td>&nbsp;</td></tr>';
  END

  -- Строка процентов
  IF(V$CALLER_TYPE = 10) THEN
  BEGIN
    VAL = V$SS;
    SUSPEND;
  END

  -- Сводные данные по учебному коллективу
  IF(V$CALLER_TYPE IN (9, 187)) THEN
  BEGIN
    V$N5 = 0;
    V$N4 = 0;
    V$N3 = 0;
    V$N2 = 0;
    V$N0 = 0;
    V$C = 0;

    -- 5
    VAL = '<tr id="f5" class="line-top f">';
    VAL = VAL || '<td class="tl">5</td>';
    SUSPEND;
    FOR
      SELECT S.SUBJECT_ID
      FROM CJ2_REPORT_NX310_SUBJ(:I$ROOT_ID, :V$ROOT_TYPE, :I$OBJ_ID, 0, :I$DATE_FROM, :V$DATE_TO) S
      WHERE (:V$OPTION_TYPE = 51 AND S.SUBJECT_ID = :I$OPTION_ID) OR :V$OPTION_TYPE <> 51
      INTO :V$SUBJECT_ID
    DO
    BEGIN
      SELECT COUNT(DISTINCT M.MARK_ID)
      FROM PERSON_MOVEMENTS MV
      JOIN CJ2_MARK M ON M.DATE_DEL IS NULL AND M.STUDENT_ID = MV.PERSON_ID
      JOIN CJ2_JOURNAL_FINALS F ON F.OBJ_ID = M.FINAL_ID
      JOIN CJ2_JOURNAL J ON J.OBJ_ID = F.CJ_ID AND J.JOURNAL_TYPE = 0 AND J.SUBJECT_ID = :V$SUBJECT_ID
      JOIN CJ2_MARK_TYPE MT ON MT.MARK_TYPE_ID = M.MARK_TYPE_ID
      WHERE MV.DATE_DEL IS NULL
        AND (:V$CALLER_TYPE <> 10 OR MV.PERSON_ID = :I$OBJ_ID) -- фильтр по конкретному ученику
        AND (:V$CALLER_TYPE NOT IN (9, 187) OR MV.GROUP_ID = :I$OBJ_ID) -- фильтр по классу
        AND MV.DATE_IN <= :I$DATE_TO AND (MV.DATE_OUT IS NULL OR MV.DATE_OUT >= :I$DATE_FROM)
        AND MT.PARENT_ID NOT IN (100)
        AND MT.MARK_COST >= 4.5
        AND F.FINAL_DATE >= :I$DATE_FROM AND F.FINAL_DATE <= :V$DATE_TO
      INTO :V$N;
      V$N5 = V$N5 + V$N;
      V$C = V$C + V$N;
      VAL = '<td class="s">' || IIF(V$N > 0, V$N, '&nbsp;') || '</td>';
      SUSPEND;
    END

    VAL = '<td class="line-left h">' || IIF(V$N5 > 0, V$N5, '&nbsp;') || '</td>';
    VAL = VAL || '<td class="h">&nbsp;</td>';
    VAL = VAL || '<td class="h">&nbsp;</td>';
    VAL = VAL || '<td class="h">&nbsp;</td>';
    VAL = VAL || '<td class="h">&nbsp;</td>';
    VAL = VAL || '<td>&nbsp;</td>'; -- СБ
    VAL = VAL || '<td>&nbsp;</td>';
    VAL = VAL || '</tr>';
    SUSPEND;

    -- 4
    VAL = '<tr id="f4" class="f">';
    VAL = VAL || '<td class="tl">4</td>';
    SUSPEND;
    FOR
      SELECT S.SUBJECT_ID
      FROM CJ2_REPORT_NX310_SUBJ(:I$ROOT_ID, :V$ROOT_TYPE, :I$OBJ_ID, 0, :I$DATE_FROM, :V$DATE_TO) S
      WHERE (:V$OPTION_TYPE = 51 AND S.SUBJECT_ID = :I$OPTION_ID) OR :V$OPTION_TYPE <> 51
      INTO :V$SUBJECT_ID
    DO
    BEGIN
      SELECT COUNT(DISTINCT M.MARK_ID)
      FROM PERSON_MOVEMENTS MV
      JOIN CJ2_MARK M ON M.DATE_DEL IS NULL AND M.STUDENT_ID = MV.PERSON_ID
      JOIN CJ2_JOURNAL_FINALS F ON F.OBJ_ID = M.FINAL_ID
      JOIN CJ2_JOURNAL J ON J.OBJ_ID = F.CJ_ID AND J.JOURNAL_TYPE = 0 AND J.SUBJECT_ID = :V$SUBJECT_ID
      JOIN CJ2_MARK_TYPE MT ON MT.MARK_TYPE_ID = M.MARK_TYPE_ID
      WHERE MV.DATE_DEL IS NULL
        AND (:V$CALLER_TYPE <> 10 OR MV.PERSON_ID = :I$OBJ_ID) -- фильтр по конкретному ученику
        AND (:V$CALLER_TYPE NOT IN (9, 187) OR MV.GROUP_ID = :I$OBJ_ID) -- фильтр по классу
        AND MV.DATE_IN <= :I$DATE_TO AND (MV.DATE_OUT IS NULL OR MV.DATE_OUT >= :I$DATE_FROM)
        AND MT.PARENT_ID NOT IN (100)
        AND MT.MARK_COST >= 3.5 AND MT.MARK_COST < 4.5
        AND F.FINAL_DATE >= :I$DATE_FROM AND F.FINAL_DATE <= :V$DATE_TO
      INTO :V$N;
      V$N4 = V$N4 + V$N;
      V$C = V$C + V$N;
      VAL = '<td class="s">' || IIF(V$N > 0, V$N, '&nbsp;') || '</td>';
      SUSPEND;
    END

    VAL = '<td class="line-left h">&nbsp;</td>';
    VAL = VAL || '<td class="h">' || IIF(V$N4 > 0, V$N4, '&nbsp;') || '</td>';
    VAL = VAL || '<td class="h">&nbsp;</td>';
    VAL = VAL || '<td class="h">&nbsp;</td>';
    VAL = VAL || '<td class="h">&nbsp;</td>';
    VAL = VAL || '<td>&nbsp;</td>'; -- СБ
    VAL = VAL || '<td>&nbsp;</td>';
    VAL = VAL || '</tr>';
    SUSPEND;

    -- 3
    VAL = '<tr id="f3" class="f">';
    VAL = VAL || '<td class="tl">3</td>';
    SUSPEND;
    FOR
      SELECT S.SUBJECT_ID
      FROM CJ2_REPORT_NX310_SUBJ(:I$ROOT_ID, :V$ROOT_TYPE, :I$OBJ_ID, 0, :I$DATE_FROM, :V$DATE_TO) S
      WHERE (:V$OPTION_TYPE = 51 AND S.SUBJECT_ID = :I$OPTION_ID) OR :V$OPTION_TYPE <> 51
      INTO :V$SUBJECT_ID
    DO
    BEGIN
      SELECT COUNT(DISTINCT M.MARK_ID)
      FROM PERSON_MOVEMENTS MV
      JOIN CJ2_MARK M ON M.DATE_DEL IS NULL AND M.STUDENT_ID = MV.PERSON_ID
      JOIN CJ2_JOURNAL_FINALS F ON F.OBJ_ID = M.FINAL_ID
      JOIN CJ2_JOURNAL J ON J.OBJ_ID = F.CJ_ID AND J.JOURNAL_TYPE = 0 AND J.SUBJECT_ID = :V$SUBJECT_ID
      JOIN CJ2_MARK_TYPE MT ON MT.MARK_TYPE_ID = M.MARK_TYPE_ID
      WHERE MV.DATE_DEL IS NULL
        AND (:V$CALLER_TYPE <> 10 OR MV.PERSON_ID = :I$OBJ_ID) -- фильтр по конкретному ученику
        AND (:V$CALLER_TYPE NOT IN (9, 187) OR MV.GROUP_ID = :I$OBJ_ID) -- фильтр по классу
        AND MV.DATE_IN <= :I$DATE_TO AND (MV.DATE_OUT IS NULL OR MV.DATE_OUT >= :I$DATE_FROM)
        AND MT.PARENT_ID NOT IN (100)
        AND MT.MARK_COST >= 2.5 AND MT.MARK_COST < 3.5
        AND F.FINAL_DATE >= :I$DATE_FROM AND F.FINAL_DATE <= :V$DATE_TO
      INTO :V$N;
      V$N3 = V$N3 + V$N;
      V$C = V$C + V$N;
      VAL = '<td class="s">' || IIF(V$N > 0, V$N, '&nbsp;') || '</td>';
      SUSPEND;
    END

    VAL = '<td class="line-left h">&nbsp;</td>';
    VAL = VAL || '<td class="h">&nbsp;</td>';
    VAL = VAL || '<td class="h">' || IIF(V$N3 > 0, V$N3, '&nbsp;') || '</td>';
    VAL = VAL || '<td class="h">&nbsp;</td>';
    VAL = VAL || '<td class="h">&nbsp;</td>';
    VAL = VAL || '<td>&nbsp;</td>'; -- СБ
    VAL = VAL || '<td>&nbsp;</td>';
    VAL = VAL || '</tr>';
    SUSPEND;

    -- 2
    VAL = '<tr id="f2" class="f">';
    VAL = VAL || '<td class="tl">2</td>';
    SUSPEND;
    FOR
      SELECT S.SUBJECT_ID
      FROM CJ2_REPORT_NX310_SUBJ(:I$ROOT_ID, :V$ROOT_TYPE, :I$OBJ_ID, 0, :I$DATE_FROM, :V$DATE_TO) S
      WHERE (:V$OPTION_TYPE = 51 AND S.SUBJECT_ID = :I$OPTION_ID) OR :V$OPTION_TYPE <> 51
      INTO :V$SUBJECT_ID
    DO
    BEGIN
      SELECT COUNT(DISTINCT M.MARK_ID)
      FROM PERSON_MOVEMENTS MV
      JOIN CJ2_MARK M ON M.DATE_DEL IS NULL AND M.STUDENT_ID = MV.PERSON_ID
      JOIN CJ2_JOURNAL_FINALS F ON F.OBJ_ID = M.FINAL_ID
      JOIN CJ2_JOURNAL J ON J.OBJ_ID = F.CJ_ID AND J.JOURNAL_TYPE = 0 AND J.SUBJECT_ID = :V$SUBJECT_ID
      JOIN CJ2_MARK_TYPE MT ON MT.MARK_TYPE_ID = M.MARK_TYPE_ID
      WHERE MV.DATE_DEL IS NULL
        AND (:V$CALLER_TYPE <> 10 OR MV.PERSON_ID = :I$OBJ_ID) -- фильтр по конкретному ученику
        AND (:V$CALLER_TYPE NOT IN (9, 187) OR MV.GROUP_ID = :I$OBJ_ID) -- фильтр по классу
        AND MV.DATE_IN <= :I$DATE_TO AND (MV.DATE_OUT IS NULL OR MV.DATE_OUT >= :I$DATE_FROM)
        AND MT.PARENT_ID NOT IN (100)
        AND MT.MARK_COST < 2.5
        AND F.FINAL_DATE >= :I$DATE_FROM AND F.FINAL_DATE <= :V$DATE_TO
      INTO :V$N;
      V$N2 = V$N2 + V$N;
      V$C = V$C + V$N;
      VAL = '<td class="s">' || IIF(V$N > 0, V$N, '&nbsp;') || '</td>';
      SUSPEND;
    END

    VAL = '<td class="line-left h">&nbsp;</td>';
    VAL = VAL || '<td class="h">&nbsp;</td>';
    VAL = VAL || '<td class="h">&nbsp;</td>';
    VAL = VAL || '<td class="h">' || IIF(V$N2 > 0, V$N2, '&nbsp;') || '</td>';
    VAL = VAL || '<td class="h">&nbsp;</td>';
    VAL = VAL || '<td>&nbsp;</td>'; -- СБ
    VAL = VAL || '<td>&nbsp;</td>';
    VAL = VAL || '</tr>';
    SUSPEND;

    -- Не аттестован
    VAL = '<tr id="f0" class="f">';
    VAL = VAL || '<td class="tl">Н/А</td>';
    SUSPEND;
    FOR
      SELECT S.SUBJECT_ID
      FROM CJ2_REPORT_NX310_SUBJ(:I$ROOT_ID, :V$ROOT_TYPE, :I$OBJ_ID, 0, :I$DATE_FROM, :V$DATE_TO) S
      WHERE (:V$OPTION_TYPE = 51 AND S.SUBJECT_ID = :I$OPTION_ID) OR :V$OPTION_TYPE <> 51
      INTO :V$SUBJECT_ID
    DO
    BEGIN
      SELECT COUNT(DISTINCT M.MARK_ID)
      FROM PERSON_MOVEMENTS MV
      JOIN CJ2_MARK M ON M.DATE_DEL IS NULL AND M.STUDENT_ID = MV.PERSON_ID
      JOIN CJ2_JOURNAL_FINALS F ON F.OBJ_ID = M.FINAL_ID
      JOIN CJ2_JOURNAL J ON J.OBJ_ID = F.CJ_ID AND J.JOURNAL_TYPE = 0 AND J.SUBJECT_ID = :V$SUBJECT_ID
      JOIN CJ2_MARK_TYPE MT ON MT.MARK_TYPE_ID = M.MARK_TYPE_ID
      WHERE MV.DATE_DEL IS NULL
        AND (:V$CALLER_TYPE <> 10 OR MV.PERSON_ID = :I$OBJ_ID) -- фильтр по конкретному ученику
        AND (:V$CALLER_TYPE NOT IN (9, 187) OR MV.GROUP_ID = :I$OBJ_ID) -- фильтр по классу
        AND MV.DATE_IN <= :I$DATE_TO AND (MV.DATE_OUT IS NULL OR MV.DATE_OUT >= :I$DATE_FROM)
        AND MT.MARK_TYPE_ID IN (103, 104)
        AND F.FINAL_DATE >= :I$DATE_FROM AND F.FINAL_DATE <= :V$DATE_TO
      INTO :V$N;
      V$N0 = V$N0 + V$N;
      V$C = V$C + V$N;
      VAL = '<td class="s">' || IIF(V$N > 0, V$N, '&nbsp;') || '</td>';
      SUSPEND;
    END

    VAL = '<td class="line-left h">&nbsp;</td>';
    VAL = VAL || '<td class="h">&nbsp;</td>';
    VAL = VAL || '<td class="h">&nbsp;</td>';
    VAL = VAL || '<td class="h">&nbsp;</td>';
    VAL = VAL || '<td class="h">' || IIF(V$N0 > 0, V$N0, '&nbsp;') || '</td>';
    VAL = VAL || '<td>&nbsp;</td>'; -- СБ
    VAL = VAL || '<td>&nbsp;</td>';
    VAL = VAL || '</tr>';
    SUSPEND;

    -- СБ
    VAL = '<tr id="fb" class="line-top f">';
    VAL = VAL || '</tr>';
    SUSPEND;

    -- СОУ
    VAL = '<tr id="fe" class="f">';
    VAL = VAL || '</tr>';
    SUSPEND;
  END

  VAL = '</tbody></table>';
  SUSPEND;

  VAL = '<script>';
  VAL = VAL || '(function () { ';
  VAL = VAL || 'let tid = "#t' || I$OBJ_ID || '";';
  VAL = VAL || 'let s1 = "<td class=''tl''>Средний балл</td>", s2 = "<td class=''tl''>Обученность</td>", sc = 0, sn5 = 0, sn4 = 0, sn3 = 0, sn2 = 0, sn0 = 0;';
  VAL = VAL || '$(tid + " #f5 .s").each((n, el) => {';
  VAL = VAL || 'let n5 = parseInt($(tid + " #f5 .s:eq(" + n + ")").text()); if(isNaN(n5)) n5 = 0;';
  VAL = VAL || 'let n4 = parseInt($(tid + " #f4 .s:eq(" + n + ")").text()); if(isNaN(n4)) n4 = 0;';
  VAL = VAL || 'let n3 = parseInt($(tid + " #f3 .s:eq(" + n + ")").text()); if(isNaN(n3)) n3 = 0;';
  VAL = VAL || 'let n2 = parseInt($(tid + " #f2 .s:eq(" + n + ")").text()); if(isNaN(n2)) n2 = 0;';
  VAL = VAL || 'let n0 = parseInt($(tid + " #f0 .s:eq(" + n + ")").text()); if(isNaN(n0)) n0 = 0;';
  VAL = VAL || 'let c = n5 + n4 + n3 + n2 + n0;';
  VAL = VAL || 'let v1 = n5 * 5 + n4 * 4 + n3 * 3 + n2 * 2;';
  VAL = VAL || 'let v2 = n5 * 100 + n4 * 64 + n3 * 36 + n2 * 16 + n0 * 7;';
  VAL = VAL || 'sc += c; sn5 += n5; sn4 += n4; sn3 += n3; sn2 += n2;';
  VAL = VAL || 's1 += "<td>" + (c > 0 ? (v1 / c).toFixed(2) : "&nbsp;") + "</td>";';
  VAL = VAL || 's2 += "<td>" + (c > 0 ? (v2 / c).toFixed(0) : "&nbsp;") + "</td>";';
  VAL = VAL || '});';
  VAL = VAL || 'let v1 = sn5 * 5 + sn4 * 4 + sn3 * 3 + sn2 * 2;';
  VAL = VAL || 'let v2 = sn5 * 100 + sn4 * 64 + sn3 * 36 + sn2 * 16 + sn0 * 7;';
  VAL = VAL || 's1 += "<td class=''line-left h''>&nbsp;</td>";';
  VAL = VAL || 's1 += "<td class=''h''>&nbsp;</td>";';
  VAL = VAL || 's1 += "<td class=''h''>&nbsp;</td>";';
  VAL = VAL || 's1 += "<td class=''h''>&nbsp;</td>";';
  VAL = VAL || 's1 += "<td class=''h''>&nbsp;</td>";';
  VAL = VAL || 's1 += "<td>" + (sc > 0 ? (v1 / sc).toFixed(2) : "&nbsp;") + "</td>";';
  VAL = VAL || 's1 += "<td>&nbsp;</td>";';
  VAL = VAL || 's2 += "<td class=''line-left h''>&nbsp;</td>";';
  VAL = VAL || 's2 += "<td class=''h''>&nbsp;</td>";';
  VAL = VAL || 's2 += "<td class=''h''>&nbsp;</td>";';
  VAL = VAL || 's2 += "<td class=''h''>&nbsp;</td>";';
  VAL = VAL || 's2 += "<td class=''h''>&nbsp;</td>";';
  VAL = VAL || 's2 += "<td>&nbsp;</td>";';
  VAL = VAL || 's2 += "<td>" + (sc > 0 ? (v2 / sc).toFixed(0) : "&nbsp;") + "</td>";';
  VAL = VAL || '$(tid + " #fb").html(s1);';
  VAL = VAL || '$(tid + " #fe").html(s2);';
  VAL = VAL || '})();';
  VAL = VAL || '</script>';
  SUSPEND;

  END
  ELSE
  BEGIN

    VAL = '<table id="t' || I$OBJ_ID || '" class="table centered" cellspacing="0" cellpadding="0" data-flags="sort arrange" style="min-width: 50%">';
    VAL = VAL || '<thead>';
    VAL = VAL || '<tr class="thd">';
      VAL = VAL || '<td class="tl sortable">Учебный коллектив</td>';
      VAL = VAL || '<td class="sortable value" style="width: 4rem">5</td>';
      VAL = VAL || '<td class="sortable value" style="width: 4rem">4</td>';
      VAL = VAL || '<td class="sortable value" style="width: 4rem">3</td>';
      VAL = VAL || '<td class="sortable value" style="width: 4rem">2</td>';
      VAL = VAL || '<td class="sortable value" style="width: 4rem">Н/А</td>';
      VAL = VAL || '<td class="sortable value" style="width: 4rem">СБ</td>';
      VAL = VAL || '<td class="sortable value" style="width: 4rem">СОУ</td>';
      VAL = VAL || '</tr>';
    VAL = VAL || '</tr></thead><tbody>';
    SUSPEND;

    FOR
      SELECT L9.OBJ_ID, C.CAPTION, C.SORT_ORDER
      FROM LINKS L2
      JOIN LINKS L8 ON L8.PARENT_ID = L2.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
      LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C ON 1 = 1
      WHERE L2.PARENT_ID = :I$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND :V$CALLER_TYPE = 2
      UNION
      SELECT L9.OBJ_ID, C.CAPTION, C.SORT_ORDER
      FROM LINKS L8
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
      LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C ON 1 = 1
      WHERE L8.PARENT_ID = :I$OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL AND :V$CALLER_TYPE = 7
      UNION
      SELECT L9.OBJ_ID, C.CAPTION, C.SORT_ORDER
      FROM LINKS L9
      LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C ON 1 = 1
      WHERE L9.PARENT_ID = :I$OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL AND :V$CALLER_TYPE = 8
      ORDER BY 3, 2
      INTO :V$PERSON_ID, :V$S1, :V$SO
    DO
    BEGIN
      VAL = '<tr>';
        VAL = VAL || '<td class="target class tl" data-target="' || V$PERSON_ID || '">' || V$S1 || '</td>';
        VAL = VAL || '<td>&nbsp;</td>';
        VAL = VAL || '<td>&nbsp;</td>';
        VAL = VAL || '<td>&nbsp;</td>';
        VAL = VAL || '<td>&nbsp;</td>';
        VAL = VAL || '<td>&nbsp;</td>';
        VAL = VAL || '<td>&nbsp;</td>';
        VAL = VAL || '<td>&nbsp;</td>';
      VAL = VAL || '</tr>';
      SUSPEND;
    END

    VAL = '</tbody></table>';
    SUSPEND;

    VAL = '<table id="s' || I$OBJ_ID || '" class="table centered" cellspacing="0" cellpadding="0" data-flags="sort arrange" style="min-width: 50%">';
    VAL = VAL || '<thead>';
    VAL = VAL || '<tr class="thd">';
      VAL = VAL || '<td class="tl sortable">Предмет</td>';
      VAL = VAL || '<td class="sortable value" style="width: 4rem">5</td>';
      VAL = VAL || '<td class="sortable value" style="width: 4rem">4</td>';
      VAL = VAL || '<td class="sortable value" style="width: 4rem">3</td>';
      VAL = VAL || '<td class="sortable value" style="width: 4rem">2</td>';
      VAL = VAL || '<td class="sortable value" style="width: 4rem">Н/А</td>';
      VAL = VAL || '<td class="sortable value" style="width: 4rem">СБ</td>';
      VAL = VAL || '<td class="sortable value" style="width: 4rem">СОУ</td>';
      VAL = VAL || '</tr>';
    VAL = VAL || '</tr></thead><tbody>';
    SUSPEND;

    FOR
      SELECT S.SUBJECT_ID, C.CAPTION
      FROM CJ2_REPORT_NX310_SUBJ(:I$OBJ_ID, :V$CALLER_TYPE, :I$OBJ_ID, 0, :I$DATE_FROM, :V$DATE_TO, IIF(:V$OPTION_TYPE = 14, :I$OPTION_ID, NULL)) S
      LEFT JOIN OBJECT_CAPTION_GET(S.SUBJECT_ID) C ON 1 = 1
      WHERE (:V$OPTION_TYPE = 51 AND S.SUBJECT_ID = :I$OPTION_ID) OR :V$OPTION_TYPE <> 51
      INTO :V$SUBJECT_ID, :V$S1
    DO
    BEGIN
      VAL = '<tr>';
        VAL = VAL || '<td  class="target subject tl" data-target="' || V$SUBJECT_ID || '">' || V$S1 || '</td>';
        VAL = VAL || '<td>&nbsp;</td>';
        VAL = VAL || '<td>&nbsp;</td>';
        VAL = VAL || '<td>&nbsp;</td>';
        VAL = VAL || '<td>&nbsp;</td>';
        VAL = VAL || '<td>&nbsp;</td>';
        VAL = VAL || '<td>&nbsp;</td>';
        VAL = VAL || '<td>&nbsp;</td>';
      VAL = VAL || '</tr>';
      SUSPEND;
    END

    VAL = '</tbody></table>';
    SUSPEND;

    VAL = '<table id="h' || I$OBJ_ID || '" class="table centered" cellspacing="0" cellpadding="0" data-flags="sort arrange" style="min-width: 50%">';
    VAL = VAL || '<thead>';
    VAL = VAL || '<tr class="thd">';
      VAL = VAL || '<td class="tl sortable">Преподаватель</td>';
      VAL = VAL || '<td class="sortable value" style="width: 4rem">5</td>';
      VAL = VAL || '<td class="sortable value" style="width: 4rem">4</td>';
      VAL = VAL || '<td class="sortable value" style="width: 4rem">3</td>';
      VAL = VAL || '<td class="sortable value" style="width: 4rem">2</td>';
      VAL = VAL || '<td class="sortable value" style="width: 4rem">Н/А</td>';
      VAL = VAL || '<td class="sortable value" style="width: 4rem">СБ</td>';
      VAL = VAL || '<td class="sortable value" style="width: 4rem">СОУ</td>';
      VAL = VAL || '</tr>';
    VAL = VAL || '</tr></thead><tbody>';
    SUSPEND;

    -- Собираем список преподавателей
    V$PREV_ID = 0;
    VAL = '';
    FOR
      SELECT DISTINCT S.TEACHER_ID, P.NAME_FULL --C.CAPTION
                    , S.SUBJECT_NAME
      FROM CJ2_REPORT_NX310_SUBJ(:I$OBJ_ID, :V$CALLER_TYPE, :I$OBJ_ID, 0, :I$DATE_FROM, :I$DATE_TO, NULL, IIF(:V$OPTION_TYPE = 14, :I$OPTION_ID, -1)) S
      LEFT JOIN UT_PERSON_DESC(S.TEACHER_ID, :I$ZONE, 1) P ON 1 = 1 --Redmine #1060 --LEFT JOIN OBJECT_CAPTION_GET(S.TEACHER_ID) C ON 1 = 1
      WHERE (
        ((:V$OPTION_TYPE = 51 AND S.SUBJECT_ID = :I$OPTION_ID) OR :V$OPTION_TYPE <> 51)
      )
      ORDER BY 2, 3
      INTO :V$SUBJECT_ID, :V$S1, :V$S2
    DO
    BEGIN
      IF(V$SUBJECT_ID <> V$PREV_ID) THEN
      BEGIN
        IF(V$PREV_ID > 0) THEN
        BEGIN
          VAL = VAL || ')</td>';
          VAL = VAL || '<td>&nbsp;</td>';
          VAL = VAL || '<td>&nbsp;</td>';
          VAL = VAL || '<td>&nbsp;</td>';
          VAL = VAL || '<td>&nbsp;</td>';
          VAL = VAL || '<td>&nbsp;</td>';
          VAL = VAL || '<td>&nbsp;</td>';
          VAL = VAL || '<td>&nbsp;</td>';
          VAL = VAL || '</tr>';
          SUSPEND;
        END

        VAL = '<tr>';
        VAL = VAL || '<td  class="target teacher tl" data-target="' || V$SUBJECT_ID || '">' || V$S1 || ' (' || V$S2;
      END
      ELSE
      BEGIN
        VAL = VAL || ', ' || V$S2;
      END
      V$PREV_ID = V$SUBJECT_ID;
    END
    IF(V$PREV_ID > 0) THEN
    BEGIN
      VAL = VAL || ')</td>';
      VAL = VAL || '<td>&nbsp;</td>';
      VAL = VAL || '<td>&nbsp;</td>';
      VAL = VAL || '<td>&nbsp;</td>';
      VAL = VAL || '<td>&nbsp;</td>';
      VAL = VAL || '<td>&nbsp;</td>';
      VAL = VAL || '<td>&nbsp;</td>';
      VAL = VAL || '<td>&nbsp;</td>';
      VAL = VAL || '</tr>';
      SUSPEND;
    END

    VAL = '</tbody></table>';
    SUSPEND;

    VAL = '<script>';
    VAL = VAL || '(function () { ';
    VAL = VAL || 'let tid = "#t' || I$OBJ_ID || '";';
    VAL = VAL || 'let sid = "#s' || I$OBJ_ID || '";';
    VAL = VAL || 'let hid = "#h' || I$OBJ_ID || '";';
    VAL = VAL || 'let m = [';
    SUSPEND;

    FOR
      SELECT P.OBJ_ID, J.SUBJECT_ID, MT.MARK_COST, C.FINAL_DATE, P.PARENT_ID, J.TEACHER_ID
      FROM (
        -- для уровня образования
        SELECT DISTINCT L10.OBJ_ID, L10.PARENT_ID
        FROM LINKS L8
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
        JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        WHERE L8.PARENT_ID = :I$OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL AND :V$CALLER_TYPE = 7
        -- для параллели
        UNION
        SELECT DISTINCT L10.OBJ_ID, L10.PARENT_ID
        FROM LINKS L9
        JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        WHERE L9.PARENT_ID = :I$OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL AND :V$CALLER_TYPE = 8
        -- для класса
        UNION
        SELECT DISTINCT L10.OBJ_ID, L10.PARENT_ID
        FROM LINKS L10
        WHERE L10.PARENT_ID = :I$OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL AND :V$CALLER_TYPE IN (9, 187)
        -- для конкретного ученика
        UNION
        SELECT :I$OBJ_ID, 0
        FROM RDB$DATABASE
        WHERE :V$CALLER_TYPE = 10
      ) P
      JOIN CJ2_MARK M ON M.DATE_DEL IS NULL AND M.STUDENT_ID = P.OBJ_ID AND M.FINAL_ID IS NOT NULL
      JOIN CJ2_JOURNAL_FINALS C ON C.DATE_DEL IS NULL AND C.OBJ_ID = M.FINAL_ID AND C.FINAL_DATE >= :I$DATE_FROM AND C.FINAL_DATE <= :V$DATE_TO
      JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.JOURNAL_TYPE = 0 AND J.OBJ_ID = C.CJ_ID
      JOIN CJ2_MARK_TYPE MT ON MT.MARK_TYPE_ID = M.MARK_TYPE_ID
      WHERE (
        ((:V$OPTION_TYPE = 51 AND J.SUBJECT_ID = :I$OPTION_ID) OR :V$OPTION_TYPE <> 51) AND
        ((:V$OPTION_TYPE = 14 AND J.TEACHER_ID = :I$OPTION_ID) OR :V$OPTION_TYPE <> 14)
      )
      INTO :V$PERSON_ID, :V$SUBJECT_ID, :V$SO, :V$D, :V$GRADE_ID, :V$TEACHER_ID
    DO
    BEGIN
      -- p - id ученика, c - id класса (только если идет групповая выборка), s - id предмета, m - значение оценки в 5-балльной шкале, d - номер дня от начальной даты
      VAL = '{p:' || V$PERSON_ID || ',s:' || V$SUBJECT_ID || ',h:' || V$TEACHER_ID || ',m:' || CAST(V$SO AS NUMERIC(18, 1)) || ',d:' || DATEDIFF(DAY FROM I$DATE_FROM TO V$D);
      -- Ищем какой класс был последний
      IF(V$CALLER_TYPE IN (2, 7, 8)) THEN VAL = VAL || ',c:' || V$GRADE_ID;
      VAL = VAL || '},';
      SUSPEND;
    END

    VAL = '];';
    VAL = VAL || 'cjrCalcEQ(tid, ' || V$CALLER_TYPE || ', m);';
    VAL = VAL || 'cjrCalcEQ(sid, ' || V$CALLER_TYPE || ', m);';
    VAL = VAL || 'cjrCalcEQ(hid, ' || V$CALLER_TYPE || ', m);';
    VAL = VAL || '})();';
    VAL = VAL || '</script>';
    SUSPEND;

  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_REPORT_NX310_SUBJ (
    I$OBJ_ID BIGINT,
    I$OBJ_TYPE BIGINT,
    I$GROUP_ID BIGINT,
    I$MODE SMALLINT,
    I$DATE_FROM DATE,
    I$DATE_TO DATE,
    I$YEAR_ID BIGINT = null,
    I$TEACHER_ID BIGINT = null)
RETURNS (
    SUBJECT_ID BIGINT,
    SUBJECT_NAME VARCHAR(400),
    SUBJECT_CODE VARCHAR(100),
    TEACHER_ID BIGINT)
AS
begin

  -- GROUP_ID - конкретная сущность для детализации
  -- MODE: 0 = по промежуточным, 1 = по текущим, 2 = по итоговым историческим
  -- DATE должны передаваться уже в финальном виде
  -- YEAR_ID - используется для выборки по историческим оценкам, конкретный учебный год
  -- TEACHER_ID - выборка по конкретному учителю, -1 чтобы сделать разбивку по учителям, NULL без разбивки

  IF(I$MODE = 0) THEN
  BEGIN
    FOR
      SELECT DISTINCT J.SUBJECT_ID, COALESCE(V.SVAL, '???'), VC.SVAL, IIF(:I$TEACHER_ID IS NULL, NULL, IIF(:I$TEACHER_ID IS NULL, NULL, J.TEACHER_ID))
      FROM (
        -- для уровня образования
        SELECT DISTINCT L10.OBJ_ID                                                                           
        FROM LINKS L8
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
        JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        WHERE L8.PARENT_ID = :I$OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL AND :I$OBJ_TYPE = 7
        -- для параллели
        UNION
        SELECT DISTINCT L10.OBJ_ID                                                                           
        FROM LINKS L9
        JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        WHERE L9.PARENT_ID = :I$OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL AND :I$OBJ_TYPE = 8
        -- для класса
        UNION
        SELECT DISTINCT L10.OBJ_ID
        FROM LINKS L10
        WHERE L10.PARENT_ID = :I$OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL AND :I$OBJ_TYPE IN (9, 187)
        -- для конкретного ученика
        UNION
        SELECT :I$OBJ_ID
        FROM RDB$DATABASE
        WHERE :I$OBJ_TYPE = 10
      ) P
      JOIN CJ2_MARK M ON M.DATE_DEL IS NULL AND M.STUDENT_ID = P.OBJ_ID
      JOIN CJ2_JOURNAL_FINALS F ON F.OBJ_ID = M.FINAL_ID
      JOIN CJ2_JOURNAL J ON J.OBJ_ID = F.CJ_ID AND J.JOURNAL_TYPE = 0 AND (:I$TEACHER_ID IS NULL OR :I$TEACHER_ID = -1 OR J.TEACHER_ID = :I$TEACHER_ID)
      LEFT JOIN VALS V ON V.OBJ_ID = J.SUBJECT_ID AND V.PARAM_ID IN (377, 1752) AND V.IS_DEL = 0
      LEFT JOIN VALS VC ON VC.OBJ_ID = J.SUBJECT_ID AND VC.PARAM_ID IN (376, 1751) AND VC.IS_DEL = 0
      WHERE F.FINAL_DATE >= :I$DATE_FROM AND F.FINAL_DATE <= :I$DATE_TO
      ORDER BY 2
      INTO :SUBJECT_ID, :SUBJECT_CODE, :SUBJECT_NAME, :TEACHER_ID
    DO
    BEGIN
      SUSPEND;
    END
  END
  ELSE IF(I$MODE = 1) THEN
  BEGIN
    FOR
      SELECT DISTINCT J.SUBJECT_ID, COALESCE(V.SVAL, '???'), VC.SVAL, IIF(:I$TEACHER_ID IS NULL, NULL, IIF(:I$TEACHER_ID IS NULL, NULL, J.TEACHER_ID))
      FROM (
        -- для уровня образования
        SELECT DISTINCT L10.OBJ_ID                                                                           
        FROM LINKS L8
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
        JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        WHERE L8.PARENT_ID = :I$OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL AND :I$OBJ_TYPE = 7
        -- для параллели
        UNION
        SELECT DISTINCT L10.OBJ_ID                                                                           
        FROM LINKS L9
        JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        WHERE L9.PARENT_ID = :I$OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL AND :I$OBJ_TYPE = 8
        -- для класса
        UNION
        SELECT DISTINCT L10.OBJ_ID
        FROM LINKS L10
        WHERE L10.PARENT_ID = :I$OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL AND :I$OBJ_TYPE IN (9, 187)
        -- для конкретного ученика
        UNION
        SELECT :I$OBJ_ID
        FROM RDB$DATABASE
        WHERE :I$OBJ_TYPE = 10
      ) P
      JOIN LINKS LPG ON LPG.OBJ_ID = P.OBJ_ID AND LPG.PARENT_TYPE_ID IN (9, 187, 256, 179) AND LPG.DATE_DEL IS NULL
      JOIN CJ2_JOURNAL J ON J.GRADE_ID = LPG.PARENT_ID AND J.JOURNAL_TYPE = 0 AND (:I$TEACHER_ID IS NULL OR :I$TEACHER_ID = -1 OR J.TEACHER_ID = :I$TEACHER_ID)
      LEFT JOIN VALS V ON V.OBJ_ID = J.SUBJECT_ID AND V.PARAM_ID IN (377, 1752) AND V.IS_DEL = 0
      LEFT JOIN VALS VC ON VC.OBJ_ID = J.SUBJECT_ID AND VC.PARAM_ID IN (376, 1751) AND VC.IS_DEL = 0
      ORDER BY 2
      INTO :SUBJECT_ID, :SUBJECT_CODE, :SUBJECT_NAME, :TEACHER_ID
    DO
    BEGIN
      SUSPEND;
    END
  END
  ELSE IF(I$MODE = 2) THEN
  BEGIN
    FOR
      SELECT DISTINCT M.SUBJECT_ID, COALESCE(V.SVAL, '???'), VC.SVAL, IIF(:I$TEACHER_ID IS NULL, NULL, IIF(:I$TEACHER_ID IS NULL, NULL, M.TEACHER_ID))
      FROM (
        -- для уровня образования
        SELECT DISTINCT L10.OBJ_ID                                                                           
        FROM LINKS L8
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
        JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        WHERE L8.PARENT_ID = :I$OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL AND :I$OBJ_TYPE = 7
        -- для параллели
        UNION
        SELECT DISTINCT L10.OBJ_ID                                                                           
        FROM LINKS L9
        JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        WHERE L9.PARENT_ID = :I$OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL AND :I$OBJ_TYPE = 8
        -- для класса
        UNION
        SELECT DISTINCT L10.OBJ_ID
        FROM LINKS L10
        WHERE L10.PARENT_ID = :I$OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL AND :I$OBJ_TYPE IN (9, 187)
        -- для конкретного ученика
        UNION
        SELECT :I$OBJ_ID
        FROM RDB$DATABASE
        WHERE :I$OBJ_TYPE = 10
      ) P
      JOIN VALM M ON M.IS_DEL = 0 AND (M.IS_NATIVE IS NULL OR M.IS_NATIVE = 1) AND M.YEAR_ID = :I$YEAR_ID AND M.PUPIL_ID = P.OBJ_ID AND (:I$TEACHER_ID IS NULL OR :I$TEACHER_ID = -1 OR M.TEACHER_ID = :I$TEACHER_ID)
      LEFT JOIN VALS V ON V.OBJ_ID = M.SUBJECT_ID AND V.PARAM_ID IN (377, 1752) AND V.IS_DEL = 0
      LEFT JOIN VALS VC ON VC.OBJ_ID = M.SUBJECT_ID AND VC.PARAM_ID IN (376, 1751) AND VC.IS_DEL = 0
      ORDER BY 2
      INTO :SUBJECT_ID, :SUBJECT_CODE, :SUBJECT_NAME, :TEACHER_ID
    DO
    BEGIN
      SUSPEND;
    END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_REPORT_NX320 (
    I$USER_ID VARCHAR(40),
    I$DATE_FROM DATE,
    I$DATE_TO DATE,
    I$PARENT_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$OPTION_ID BIGINT,
    I$OPTIONS VARCHAR(1000),
    I$ZONE SMALLINT = 0)
RETURNS (
    VAL VARCHAR(4000))
AS
declare variable V$CALLER_TYPE bigint;
declare variable V$USER_TYPE smallint;
declare variable V$OU_LICENCE_TYPE varchar(2);
declare variable V$S1 varchar(400);
declare variable V$S2 varchar(400);
declare variable V$PERSON_ID bigint;
declare variable V$MT smallint;
declare variable V$EXPAND smallint;
declare variable V$OBJ_ID bigint;
declare variable N bigint;
begin

  -- Школа, коллектив, персона
  SELECT TYPE_ID FROM OBJECTS WHERE OBJ_ID = :I$OBJ_ID INTO :V$CALLER_TYPE;
  SELECT STATUS FROM OU_LICENCE_TYPE INTO :V$OU_LICENCE_TYPE;

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;
  SELECT USER_TYPE FROM USERS WHERE USER_ID = :I$USER_ID INTO :V$USER_TYPE;

  V$MT = 0;
  V$EXPAND = 0;
  FOR
    SELECT TAKEN
    FROM PARSING_STRING_GET(:I$OPTIONS, ';')
    INTO :V$S1
  DO
  BEGIN
    IF(SUBSTRING(V$S1 FROM 1 FOR 3) = 'MT=') THEN
    BEGIN
      IF(SUBSTRING(V$S1 FROM 4) = 'п/аттестация') THEN V$MT = 0;
      ELSE IF(SUBSTRING(V$S1 FROM 4) = 'текущие') THEN V$MT = 1;
    END
    ELSE IF(SUBSTRING(V$S1 FROM 1 FOR 7) = 'EXPAND=') THEN
    BEGIN
      IF(SUBSTRING(V$S1 FROM 8) = '1') THEN V$EXPAND = 1;
    END
  END

  VAL = '<!DOCTYPE html>';
  VAL = VAL || '<html lang="ru">';
  VAL = VAL || '<head>';
  VAL = VAL || '<meta charset="utf-8" />';
  VAL = VAL || '<style>';
  VAL = VAL || 'html { font-family: Tahoma, Verdana, Arial;';
  VAL = VAL || 'font-size: 10pt; ';
  VAL = VAL || '} ';
  VAL = VAL || '.title1 { font-size: 150%;';
  VAL = VAL || 'padding: 8px;';
  VAL = VAL || 'margin-bottom: 4px;';
  VAL = VAL || 'font-weight: bold;';
  VAL = VAL || 'background-color: #D4E157;';
  VAL = VAL || '} ';
  VAL = VAL || '.title2 { ';
  VAL = VAL || 'padding: 4px;';
  VAL = VAL || 'font-weight: bold;';
  VAL = VAL || '} ';
  VAL = VAL || '</style>';

  VAL = VAL || '</head>';
  VAL = VAL || '<body>';
  SUSPEND;

  -- Заголовок отчета
  VAL = '<div class="title1">Динамика успеваемости';
  IF(V$MT = 0) THEN VAL = VAL || ' (по промежуточной аттестации)';
  IF(V$MT = 1) THEN VAL = VAL || ' (по текущим отметкам)';
  VAL = VAL || '</div>';

  VAL = VAL || '<div class="title2">';
  IF (:V$CALLER_TYPE = 10) THEN VAL = VAL || (SELECT NAME_FULL FROM UT_PERSON_DESC(:I$OBJ_ID, :I$ZONE, 1));      -- обущающийся
                           ELSE VAL = VAL || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$OBJ_ID));
  VAL = VAL || '</div>';
  IF(I$OPTION_ID IS NOT NULL) THEN
  BEGIN
    V$S1 = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$OPTION_ID));
    VAL = VAL || '<div class="title2">В разрезе: ' || COALESCE(V$S1, '???') || '</div>';
  END

  V$S1 = (SELECT RESULT FROM DATE2STR(:I$DATE_FROM));
  V$S2 = (SELECT RESULT FROM DATE2STR(:I$DATE_TO));
  VAL = VAL || '<div class="title2">Период: ' || V$S1 || ' - ' || V$S2 || '</div>';
  SUSPEND;

  -- Если у нас выбран НЕ учебный коллектив, то показываем меню для перехода
  -- но не выходим, а продолжаем дальше чтобы показать сводный отчет
  IF(V$CALLER_TYPE NOT IN (9, 187, 10) AND V$EXPAND = 0) THEN
  BEGIN
    -- Показываем кнопку для раскрытия детализации
    IF(V$CALLER_TYPE IN (7, 8)) THEN
    BEGIN
      VAL = '<div class="target option" data-target="EXPAND=1">Раскрыть детализацию для ' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$OBJ_ID)) || '</div>';
      SUSPEND;
    END

    VAL = '<div class="target-nav">';
    SUSPEND;

    FOR
      SELECT L7.OBJ_ID || ',' || L8.OBJ_ID || ',' || L9.OBJ_ID, C.CAPTION, C.SORT_ORDER
      FROM LINKS L7
      JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 187) AND L9.DATE_DEL IS NULL
      LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C ON 1 = 1
      WHERE L7.PARENT_ID = :I$OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL AND :V$CALLER_TYPE = 2
      UNION
      SELECT L8.OBJ_ID || ',' || L9.OBJ_ID, C.CAPTION, C.SORT_ORDER
      FROM LINKS L8
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 187) AND L9.DATE_DEL IS NULL
      LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C ON 1 = 1
      WHERE L8.PARENT_ID = :I$OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL AND :V$CALLER_TYPE = 7
      UNION
      SELECT L9.OBJ_ID, C.CAPTION, C.SORT_ORDER
      FROM LINKS L9
      LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C ON 1 = 1
      WHERE L9.PARENT_ID = :I$OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 187) AND L9.DATE_DEL IS NULL AND :V$CALLER_TYPE = 8
      ORDER BY 3, 2
      INTO :V$S1, :V$S2, :V$PERSON_ID
    DO
    BEGIN
      VAL = '<div class="target class" data-target="' || V$S1 || '">' || (SELECT VAL FROM ESCAPE_STR(:V$S2)) || '</div>';
      SUSPEND;
    END

    VAL = '</div>';
    SUSPEND;

    --VAL = '</body></html>';
    --SUSPEND;
    --EXIT;
  END

  VAL = '<div class="target-nav">';
  VAL = VAL || '<div class="d3" style="padding: 0.5em" title="Высокая положительная динамика">&gt;0.06</div>';
  VAL = VAL || '<div class="d2" style="padding: 0.5em"title="Средняя положительная динамика">&gt;0.04</div>';
  VAL = VAL || '<div class="d1" style="padding: 0.5em"title="Небольшая положительная динамика">&gt;0.02</div>';
  VAL = VAL || '<div class="d0" style="padding: 0.5em"title="Околонулевая динамика">-0.02...0.02</div>';
  VAL = VAL || '<div class="dm1" style="padding: 0.5em"title="Небольшая отрицательная динамика">&lt;-0.02</div>';
  VAL = VAL || '<div class="dm2" style="padding: 0.5em"title="Средняя отрицательная динамика">&lt;-0.04</div>';
  VAL = VAL || '<div class="dm3" style="padding: 0.5em"title="Высокая отрицательная динамика">&lt;-0.06</div>';
  VAL = VAL || '</div>';
  SUSPEND;

  IF(V$MT = 0) THEN
  BEGIN
    FOR
      SELECT D.OBJ_ID, C.CAPTION, C.SORT_ORDER
      FROM (
        SELECT :I$OBJ_ID OBJ_ID
        FROM RDB$DATABASE
        WHERE :V$CALLER_TYPE IN (9, 187, 10) OR :V$EXPAND = 0
        UNION
        SELECT L9.OBJ_ID -- без экстернатов
        FROM LINKS L9
        WHERE L9.PARENT_ID = :I$OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL AND :V$CALLER_TYPE = 8 AND :V$EXPAND = 1
        UNION
        SELECT L9.OBJ_ID -- без экстернатов
        FROM LINKS L8
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
        WHERE L8.PARENT_ID = :I$OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL AND :V$CALLER_TYPE = 7 AND :V$EXPAND = 1
      ) D
      LEFT JOIN OBJECT_CAPTION_GET(D.OBJ_ID) C ON 1 = 1
      ORDER BY 3, 2
      INTO :V$OBJ_ID, :V$S1, :N
    DO
    BEGIN
      -- Выводим заголовок класса
      IF(V$EXPAND = 1) THEN
      BEGIN
        VAL = '<div class="target class" data-target="' || V$OBJ_ID || '"><b>' || (SELECT VAL FROM ESCAPE_STR(:V$S1)) || '</b></div>';
        SUSPEND;
      END

      FOR
        SELECT VAL
        FROM CJ2_REPORT_NX320_PA(:I$USER_ID, :I$DATE_FROM, :I$DATE_TO, :I$PARENT_ID, :V$OBJ_ID, :I$OBJ_ID, :I$OPTION_ID, :I$OPTIONS, :I$ZONE)
        INTO :VAL
      DO
      BEGIN
        SUSPEND;
      END
    END
  END
  ELSE IF(V$MT = 1) THEN
  BEGIN
    FOR
      SELECT D.OBJ_ID, C.CAPTION, C.SORT_ORDER
      FROM (
        SELECT :I$OBJ_ID OBJ_ID
        FROM RDB$DATABASE
        WHERE :V$CALLER_TYPE IN (9, 187, 10) OR :V$EXPAND = 0
        UNION
        SELECT L9.OBJ_ID -- без экстернатов
        FROM LINKS L9
        WHERE L9.PARENT_ID = :I$OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL AND :V$CALLER_TYPE = 8 AND :V$EXPAND = 1
        UNION
        SELECT L9.OBJ_ID -- без экстернатов
        FROM LINKS L8
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
        WHERE L8.PARENT_ID = :I$OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL AND :V$CALLER_TYPE = 7 AND :V$EXPAND = 1
      ) D
      LEFT JOIN OBJECT_CAPTION_GET(D.OBJ_ID) C ON 1 = 1
      ORDER BY 3, 2
      INTO :V$OBJ_ID, :V$S1, :N
    DO
    BEGIN
      IF(V$EXPAND = 1) THEN
      BEGIN
        VAL = '<div class="target class" data-target="' || V$OBJ_ID || '"><b>' || (SELECT VAL FROM ESCAPE_STR(:V$S1)) || '</b></div>';
        SUSPEND;
      END

      FOR
        SELECT VAL
        FROM CJ2_REPORT_NX320_CC(:I$USER_ID, :I$DATE_FROM, :I$DATE_TO, :I$PARENT_ID, :V$OBJ_ID, :I$OBJ_ID, :I$OPTION_ID, :I$OPTIONS, :I$ZONE)
        INTO :VAL
      DO
      BEGIN
        SUSPEND;
      END
    END
  END

  VAL = '</body></html>';
  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_REPORT_NX320_CC (
    I$USER_ID BIGINT,
    I$DATE_FROM DATE,
    I$DATE_TO DATE,
    I$PARENT_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$ROOT_ID BIGINT,
    I$OPTION_ID BIGINT,
    I$OPTIONS VARCHAR(1000),
    I$ZONE SMALLINT = 0)
RETURNS (
    VAL VARCHAR(4000))
AS
declare variable V$CALLER_TYPE bigint;
declare variable V$ROOT_TYPE bigint;
declare variable V$USER_TYPE smallint;
declare variable V$OU_LICENCE_TYPE varchar(2);
declare variable V$SUBJECT_ID bigint;
declare variable V$S1 varchar(400);
declare variable V$S2 varchar(400);
declare variable V$PERSON_ID bigint;
declare variable V$SO double precision;
declare variable V$D date;
declare variable V$GRADE_ID bigint;
declare variable V$OPTION_TYPE bigint;
declare variable V$TEACHER_ID bigint;
declare variable V$PREV_ID bigint;
begin

  if(I$OBJ_ID is null) then I$OBJ_ID = 825000002729;
  if(I$ROOT_ID is null) then I$ROOT_ID = 825000002729;
  if(I$DATE_FROM is null) then I$DATE_FROM = '01.09.2023';
  if(I$DATE_to is null) then I$DATE_to = '01.01.2024';

  -- Школа, коллектив, персона
  SELECT TYPE_ID FROM OBJECTS WHERE OBJ_ID = :I$OBJ_ID INTO :V$CALLER_TYPE;
  SELECT TYPE_ID FROM OBJECTS WHERE OBJ_ID = :I$ROOT_ID INTO :V$ROOT_TYPE;
  SELECT STATUS FROM OU_LICENCE_TYPE INTO :V$OU_LICENCE_TYPE;

  -- Тип объекта опции - учитель или предмет
  V$OPTION_TYPE = 0;

  SELECT FIRST 1 TYPE_ID
  FROM OBJECTS
  WHERE OBJ_ID = :I$OPTION_ID
  INTO :V$OPTION_TYPE;

  -- В разбивке по ученику или по классу показываем сразу с разбивкой по предметам и в целом
  -- В разбивке по уровню или параллели показываем две таблицы - по классам и по предметам

  IF(V$CALLER_TYPE IN (10, 9, 187)) THEN
  BEGIN

    VAL = '<table id="t' || I$OBJ_ID || '" class="table centered" cellspacing="0" cellpadding="0" data-flags="sort arrange" style="min-width: 50%">';
    VAL = VAL || '<thead>';
    VAL = VAL || '<tr class="thd">';
      VAL = VAL || '<td class="tl sortable">ФИО</td>';
    SUSPEND;
    -- Список предметов для учеников класса, только действующих
    -- По ученикам пока нет разреза по преподавателям в списке предметов, но он есть непосредственно при выборке оценок
    FOR
      SELECT S.SUBJECT_ID, S.SUBJECT_CODE, S.SUBJECT_NAME
      FROM CJ2_REPORT_NX310_SUBJ(:I$ROOT_ID, :V$ROOT_TYPE, :I$OBJ_ID, 1, :I$DATE_FROM, :I$DATE_TO, NULL, IIF(:V$OPTION_TYPE = 14, :I$OPTION_ID, NULL)) S
      WHERE (
        ((:V$OPTION_TYPE = 51 AND S.SUBJECT_ID = :I$OPTION_ID) OR :V$OPTION_TYPE <> 51)
        -- по учителю фильтр уже наложен
      )
      INTO :V$SUBJECT_ID, :V$S1, :V$S2
    DO
    BEGIN
      VAL = '<td class="sortable value" title="' || (SELECT VAL FROM ESCAPE_STR(:V$S2)) || '"><div class="target subject" data-target="' || V$SUBJECT_ID || '">' || (SELECT VAL FROM ESCAPE_STR(:V$S1)) || '</div></td>';
      SUSPEND;
    END
    VAL = '<td class="sortable value" data-target="all">Общий</td></tr></thead><tbody>';
    SUSPEND;

    FOR
      SELECT DISTINCT M.PERSON_ID, P.NAME_FULL --C.CAPTION
      FROM PERSON_MOVEMENTS M
      LEFT JOIN UT_PERSON_DESC(M.PERSON_ID, :I$ZONE, 1) P ON 1 = 1 --Redmine #1060 --LEFT JOIN OBJECT_CAPTION_GET(M.PERSON_ID, 23) C ON 1 = 1
      WHERE M.DATE_DEL IS NULL AND M.GROUP_TYPE_ID IN (9, 187)
        AND (:V$CALLER_TYPE <> 10 OR M.PERSON_ID = :I$OBJ_ID) -- фильтр по конкретному ученику
        AND (:V$CALLER_TYPE NOT IN (9, 187) OR M.GROUP_ID = :I$OBJ_ID) -- фильтр по классу
        AND M.DATE_IN <= :I$DATE_TO AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :I$DATE_FROM)
      ORDER BY 2
      INTO :V$PERSON_ID, :V$S1
    DO
    BEGIN
      VAL = '<tr>';
      IF(V$CALLER_TYPE = 10) THEN
        VAL = VAL || '<td class="tl" data-target="' || V$PERSON_ID || '">' || (SELECT VAL FROM ESCAPE_STR(:V$S1)) || '</td>';
      ELSE
        VAL = VAL || '<td class="target student tl" data-target="' || V$PERSON_ID || '">' || (SELECT VAL FROM ESCAPE_STR(:V$S1)) || '</td>';
      SUSPEND;
      -- Заглушки по предметам
      FOR
        SELECT DISTINCT S.SUBJECT_ID
        FROM CJ2_REPORT_NX310_SUBJ(:I$ROOT_ID, :V$ROOT_TYPE, :I$OBJ_ID, 1, :I$DATE_FROM, :I$DATE_TO, NULL, IIF(:V$OPTION_TYPE = 14, :I$OPTION_ID, NULL)) S
        WHERE (
          ((:V$OPTION_TYPE = 51 AND S.SUBJECT_ID = :I$OPTION_ID) OR :V$OPTION_TYPE <> 51)
          -- по учителю фильтр уже наложен
        )
        INTO :V$SUBJECT_ID
      DO
      BEGIN
        VAL = '<td>&nbsp;</td>';
        SUSPEND;
      END
      -- По всем
      VAL = '<td>&nbsp;</td></tr>';
      SUSPEND;
    END

    -- Итоговая строка по всем ученикам

    VAL = '</tbody></table>';
    SUSPEND;

  END
  -------------------
  ELSE
  BEGIN

    -- Если выбранный преподаватель в этом классе не преподает - просто будет строка без данных
    VAL = '<table id="t' || I$OBJ_ID || '" class="table centered" cellspacing="0" cellpadding="0" data-flags="sort arrange" style="min-width: 50%">';
    VAL = VAL || '<thead>';
    VAL = VAL || '<tr class="thd">';
      VAL = VAL || '<td class="tl sortable">Учебный коллектив</td>';
      VAL = VAL || '<td class="sortable value">Средний балл</td>';
      VAL = VAL || '<td class="sortable value">Динамика</td>';
    VAL = VAL || '</tr></thead><tbody>';
    SUSPEND;

    FOR
      SELECT L9.OBJ_ID, C.CAPTION, C.SORT_ORDER
      FROM LINKS L2
      JOIN LINKS L8 ON L8.PARENT_ID = L2.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
      LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C ON 1 = 1
      WHERE L2.PARENT_ID = :I$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND :V$CALLER_TYPE = 2
      UNION
      SELECT L9.OBJ_ID, C.CAPTION, C.SORT_ORDER
      FROM LINKS L8
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
      LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C ON 1 = 1
      WHERE L8.PARENT_ID = :I$OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL AND :V$CALLER_TYPE = 7
      UNION
      SELECT L9.OBJ_ID, C.CAPTION, C.SORT_ORDER
      FROM LINKS L9
      LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C ON 1 = 1
      WHERE L9.PARENT_ID = :I$OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL AND :V$CALLER_TYPE = 8
      ORDER BY 3, 2
      INTO :V$PERSON_ID, :V$S1, :V$SO
    DO
    BEGIN
      VAL = '<tr>';
        VAL = VAL || '<td class="target class tl" data-target="' || V$PERSON_ID || '">' || V$S1 || '</td>';
        VAL = VAL || '<td>&nbsp;</td>';
        VAL = VAL || '<td>&nbsp;</td>';
      VAL = VAL || '</tr>';
      SUSPEND;
    END

    VAL = '</tbody></table>';
    SUSPEND;

    VAL = '<table id="s' || I$OBJ_ID || '" class="table centered" cellspacing="0" cellpadding="0" data-flags="sort arrange" style="min-width: 50%">';
    VAL = VAL || '<thead>';
    VAL = VAL || '<tr class="thd">';
      VAL = VAL || '<td class="tl sortable">Предмет</td>';
      VAL = VAL || '<td class="sortable value">Средний балл</td>';
      VAL = VAL || '<td class="sortable value">Динамика</td>';
    VAL = VAL || '</tr></thead><tbody>';
    SUSPEND;

    FOR
      SELECT S.SUBJECT_ID, C.CAPTION
      FROM CJ2_REPORT_NX310_SUBJ(:I$OBJ_ID, :V$CALLER_TYPE, :I$OBJ_ID, 1, :I$DATE_FROM, :I$DATE_TO, NULL, IIF(:V$OPTION_TYPE = 14, :I$OPTION_ID, NULL)) S
      LEFT JOIN OBJECT_CAPTION_GET(S.SUBJECT_ID) C ON 1 = 1
      WHERE (
        ((:V$OPTION_TYPE = 51 AND S.SUBJECT_ID = :I$OPTION_ID) OR :V$OPTION_TYPE <> 51)
      )
      INTO :V$SUBJECT_ID, :V$S1
    DO
    BEGIN
      VAL = '<tr>';
        VAL = VAL || '<td  class="target subject tl" data-target="' || V$SUBJECT_ID || '">' || V$S1 || '</td>';
        VAL = VAL || '<td>&nbsp;</td>';
        VAL = VAL || '<td>&nbsp;</td>';
      VAL = VAL || '</tr>';
      SUSPEND;
    END

    VAL = '</tbody></table>';
    SUSPEND;

    VAL = '<table id="h' || I$OBJ_ID || '" class="table centered" cellspacing="0" cellpadding="0" data-flags="sort arrange" style="min-width: 50%">';
    VAL = VAL || '<thead>';
    VAL = VAL || '<tr class="thd">';
      VAL = VAL || '<td class="tl sortable">Предподаватель</td>';
      VAL = VAL || '<td class="sortable value">Средний балл</td>';
      VAL = VAL || '<td class="sortable value">Динамика</td>';
    VAL = VAL || '</tr></thead><tbody>';
    SUSPEND;

    -- Собираем список преподавателей
    V$PREV_ID = 0;
    VAL = '';
    FOR
      SELECT DISTINCT S.TEACHER_ID, P.NAME_FULL --C.CAPTION
                    , S.SUBJECT_NAME
      FROM CJ2_REPORT_NX310_SUBJ(:I$OBJ_ID, :V$CALLER_TYPE, :I$OBJ_ID, 1, :I$DATE_FROM, :I$DATE_TO, NULL, IIF(:V$OPTION_TYPE = 14, :I$OPTION_ID, -1)) S
      LEFT JOIN UT_PERSON_DESC(S.TEACHER_ID, :I$ZONE, 1) P ON 1 = 1 --Redmine #1060 --LEFT JOIN OBJECT_CAPTION_GET(S.TEACHER_ID) C ON 1 = 1
      WHERE (
        ((:V$OPTION_TYPE = 51 AND S.SUBJECT_ID = :I$OPTION_ID) OR :V$OPTION_TYPE <> 51)
      )
      ORDER BY 2, 3
      INTO :V$SUBJECT_ID, :V$S1, :V$S2
    DO
    BEGIN
      IF(V$SUBJECT_ID <> V$PREV_ID) THEN
      BEGIN
        IF(V$PREV_ID > 0) THEN
        BEGIN
          VAL = VAL || ')</td>';
          VAL = VAL || '<td>&nbsp;</td>';
          VAL = VAL || '<td>&nbsp;</td>';
          VAL = VAL || '</tr>';
          SUSPEND;
        END

        VAL = '<tr>';
        VAL = VAL || '<td  class="target teacher tl" data-target="' || V$SUBJECT_ID || '">' || V$S1 || ' (' || V$S2;
      END
      ELSE
      BEGIN
        VAL = VAL || ', ' || V$S2;
      END
      V$PREV_ID = V$SUBJECT_ID;
    END
    IF(V$PREV_ID > 0) THEN
    BEGIN
      VAL = VAL || ')</td>';
      VAL = VAL || '<td>&nbsp;</td>';
      VAL = VAL || '<td>&nbsp;</td>';
      VAL = VAL || '</tr>';
      SUSPEND;
    END

    VAL = '</tbody></table>';
    SUSPEND;

  END

  VAL = '<script>';
  VAL = VAL || '(function () { ';
  VAL = VAL || 'let tid = "#t' || I$OBJ_ID || '";';
  VAL = VAL || 'let sid = "#s' || I$OBJ_ID || '";';
  VAL = VAL || 'let hid = "#h' || I$OBJ_ID || '";';
  VAL = VAL || 'let m = [';
  SUSPEND;

  FOR
    SELECT P.OBJ_ID, J.SUBJECT_ID, MT.MARK_COST, L.LESSON_DATE, P.PARENT_ID, J.TEACHER_ID
    FROM (
      -- для уровня образования
      SELECT DISTINCT L10.OBJ_ID, L10.PARENT_ID
      FROM LINKS L8
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
      JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      WHERE L8.PARENT_ID = :I$OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL AND :V$CALLER_TYPE = 7
      -- для параллели
      UNION
      SELECT DISTINCT L10.OBJ_ID, L10.PARENT_ID
      FROM LINKS L9
      JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      WHERE L9.PARENT_ID = :I$OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL AND :V$CALLER_TYPE = 8
      -- для класса
      UNION
      SELECT DISTINCT L10.OBJ_ID, L10.PARENT_ID
      FROM LINKS L10
      WHERE L10.PARENT_ID = :I$OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL AND :V$CALLER_TYPE IN (9, 187)
      -- для конкретного ученика
      UNION
      SELECT :I$OBJ_ID, 0
      FROM RDB$DATABASE
      WHERE :V$CALLER_TYPE = 10
    ) P
    JOIN CJ2_MARK M ON M.DATE_DEL IS NULL AND M.STUDENT_ID = P.OBJ_ID AND M.CONTROL_ID IS NOT NULL
    JOIN CJ2_CONTROL C ON C.DATE_DEL IS NULL AND C.CONTROL_ID = M.CONTROL_ID AND C.CONTROL_TYPE_ID <> 0
    JOIN CJ2_JOURNAL_LESSONS L ON L.DATE_DEL IS NULL AND L.OBJ_ID = C.LESSON_ID AND L.IS_COMPLETED = 1 AND L.LESSON_DATE >= :I$DATE_FROM AND L.LESSON_DATE <= :I$DATE_TO
    JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.JOURNAL_TYPE = 0 AND J.OBJ_ID = L.CJ_ID
    JOIN CJ2_MARK_TYPE MT ON MT.MARK_TYPE_ID = M.MARK_TYPE_ID
    WHERE (
      ((:V$OPTION_TYPE = 51 AND J.SUBJECT_ID = :I$OPTION_ID) OR :V$OPTION_TYPE <> 51) AND
      ((:V$OPTION_TYPE = 14 AND J.TEACHER_ID = :I$OPTION_ID) OR :V$OPTION_TYPE <> 14)
    )
    INTO :V$PERSON_ID, :V$SUBJECT_ID, :V$SO, :V$D, :V$GRADE_ID, :V$TEACHER_ID
  DO
  BEGIN
    -- p - id ученика, c - id класса (только если идет групповая выборка), s - id предмета, m - значение оценки в 5-балльной шкале, d - номер дня от начальной даты
    VAL = '{p:' || V$PERSON_ID || ',s:' || V$SUBJECT_ID || ',h:' || V$TEACHER_ID || ',m:' || CAST(V$SO AS NUMERIC(18, 1)) || ',d:' || DATEDIFF(DAY FROM I$DATE_FROM TO V$D);
    -- Ищем какой класс был последний
    IF(V$CALLER_TYPE IN (2, 7, 8)) THEN VAL = VAL || ',c:' || V$GRADE_ID;
    VAL = VAL || '},';
    SUSPEND;
  END

  VAL = '];';
  VAL = VAL || 'cjrCalcDynamics(tid, ' || V$CALLER_TYPE || ', m);';
  VAL = VAL || 'cjrCalcDynamics(sid, ' || V$CALLER_TYPE || ', m);';
  VAL = VAL || 'cjrCalcDynamics(hid, ' || V$CALLER_TYPE || ', m);';
  VAL = VAL || '})();';
  VAL = VAL || '</script>';
  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_REPORT_NX320_PA (
    I$USER_ID BIGINT,
    I$DATE_FROM DATE,
    I$DATE_TO DATE,
    I$PARENT_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$ROOT_ID BIGINT,
    I$OPTION_ID BIGINT,
    I$OPTIONS VARCHAR(1000),
    I$ZONE SMALLINT = 0)
RETURNS (
    VAL VARCHAR(4000))
AS
declare variable V$CALLER_TYPE bigint;
declare variable V$ROOT_TYPE bigint;
declare variable V$USER_TYPE smallint;
declare variable V$OU_LICENCE_TYPE varchar(2);
declare variable V$DATE_TO date;
declare variable V$SUBJECT_ID bigint;
declare variable V$S1 varchar(400);
declare variable V$S2 varchar(400);
declare variable V$PERSON_ID bigint;
declare variable V$SO double precision;
declare variable V$D date;
declare variable V$GRADE_ID bigint;
declare variable V$OPTION_TYPE bigint;
declare variable V$TEACHER_ID bigint;
declare variable V$PREV_ID bigint;
begin

  if(I$OBJ_ID is null) then I$OBJ_ID = 4404001250949;
  if(I$ROOT_ID is null) then I$ROOT_ID = 4404001250949;
  if(I$DATE_FROM is null) then I$DATE_FROM = '01.09.2023';
  if(I$DATE_to is null) then I$DATE_to = '01.01.2024';

  -- Школа, коллектив, персона
  SELECT TYPE_ID FROM OBJECTS WHERE OBJ_ID = :I$OBJ_ID INTO :V$CALLER_TYPE;
  SELECT TYPE_ID FROM OBJECTS WHERE OBJ_ID = :I$ROOT_ID INTO :V$ROOT_TYPE;
  SELECT STATUS FROM OU_LICENCE_TYPE INTO :V$OU_LICENCE_TYPE;

  V$DATE_TO = DATEADD(7 DAY TO I$DATE_TO);

  -- Тип объекта опции - учитель или предмет
  V$OPTION_TYPE = 0;

  SELECT FIRST 1 TYPE_ID
  FROM OBJECTS
  WHERE OBJ_ID = :I$OPTION_ID
  INTO :V$OPTION_TYPE;

  -- В разбивке по ученику или по классу показываем сразу с разбивкой по предметам и в целом
  -- В разбивке по уровню или параллели показываем две таблицы - по классам и по предметам

  IF(V$CALLER_TYPE IN (10, 9, 187)) THEN
  BEGIN

    VAL = '<table id="t' || I$OBJ_ID || '" class="table centered" cellspacing="0" cellpadding="0" data-flags="sort arrange" style="min-width: 50%">';
    VAL = VAL || '<thead>';
    VAL = VAL || '<tr class="thd">';
      VAL = VAL || '<td class="tl sortable">ФИО</td>';
    SUSPEND;
    -- Список предметов для учеников класса, только действующих
    FOR
      SELECT S.SUBJECT_ID, S.SUBJECT_CODE, S.SUBJECT_NAME
      FROM CJ2_REPORT_NX310_SUBJ(:I$ROOT_ID, :V$ROOT_TYPE, :I$OBJ_ID, 0, :I$DATE_FROM, :V$DATE_TO, NULL, IIF(:V$OPTION_TYPE = 14, :I$OPTION_ID, NULL)) S
      WHERE (
        ((:V$OPTION_TYPE = 51 AND S.SUBJECT_ID = :I$OPTION_ID) OR :V$OPTION_TYPE <> 51)
        -- по учителю фильтр уже наложен
      )
      INTO :V$SUBJECT_ID, :V$S1, :V$S2
    DO
    BEGIN
      VAL = '<td class="sortable value" title="' || (SELECT VAL FROM ESCAPE_STR(:V$S2)) || '"><div class="target subject" data-target="' || V$SUBJECT_ID || '">' || (SELECT VAL FROM ESCAPE_STR(:V$S1)) || '</div></td>';
      SUSPEND;
    END
    VAL = '<td class="sortable value" data-target="all">Общий</td></tr></thead><tbody>';
    SUSPEND;

    FOR
      SELECT DISTINCT M.PERSON_ID, P.NAME_FULL --C.CAPTION
      FROM PERSON_MOVEMENTS M
      LEFT JOIN UT_PERSON_DESC(M.PERSON_ID, :I$ZONE, 1) P ON 1 = 1 --Redmine #1060 --LEFT JOIN OBJECT_CAPTION_GET(M.PERSON_ID, 23) C ON 1 = 1
      WHERE M.DATE_DEL IS NULL AND M.GROUP_TYPE_ID IN (9, 187)
        AND (:V$CALLER_TYPE <> 10 OR M.PERSON_ID = :I$OBJ_ID) -- фильтр по конкретному ученику
        AND (:V$CALLER_TYPE NOT IN (9, 187) OR M.GROUP_ID = :I$OBJ_ID) -- фильтр по классу
        AND M.DATE_IN <= :I$DATE_TO AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :I$DATE_FROM)
      ORDER BY 2
      INTO :V$PERSON_ID, :V$S1
    DO
    BEGIN
      VAL = '<tr>';
      IF(V$CALLER_TYPE = 10) THEN
        VAL = VAL || '<td class="tl" data-target="' || V$PERSON_ID || '">' || (SELECT VAL FROM ESCAPE_STR(:V$S1)) || '</td>';
      ELSE
        VAL = VAL || '<td class="target student tl" data-target="' || V$PERSON_ID || '">' || (SELECT VAL FROM ESCAPE_STR(:V$S1)) || '</td>';
      SUSPEND;
      -- Заглушки по предметам
      FOR
        SELECT S.SUBJECT_ID
        FROM CJ2_REPORT_NX310_SUBJ(:I$ROOT_ID, :V$ROOT_TYPE, :I$OBJ_ID, 0, :I$DATE_FROM, :V$DATE_TO, NULL, IIF(:V$OPTION_TYPE = 14, :I$OPTION_ID, NULL)) S
        WHERE (
          ((:V$OPTION_TYPE = 51 AND S.SUBJECT_ID = :I$OPTION_ID) OR :V$OPTION_TYPE <> 51)
          -- по учителю фильтр уже наложен
        )
        INTO :V$SUBJECT_ID
      DO
      BEGIN
        VAL = '<td>&nbsp;</td>';
        SUSPEND;
      END
      -- По всем
      VAL = '<td>&nbsp;</td></tr>';
      SUSPEND;
    END

    VAL = '</tbody></table>';
    SUSPEND;

  END
  -------------------
  ELSE
  BEGIN

    VAL = '<table id="t' || I$OBJ_ID || '" class="table centered" cellspacing="0" cellpadding="0" data-flags="sort arrange" style="min-width: 50%">';
    VAL = VAL || '<thead>';
    VAL = VAL || '<tr class="thd">';
      VAL = VAL || '<td class="tl sortable">Учебный коллектив</td>';
      VAL = VAL || '<td class="sortable value">Средний балл</td>';
      VAL = VAL || '<td class="sortable value">Динамика</td>';
    VAL = VAL || '</tr></thead><tbody>';
    SUSPEND;

    FOR
      SELECT L9.OBJ_ID, C.CAPTION, C.SORT_ORDER
      FROM LINKS L2
      JOIN LINKS L8 ON L8.PARENT_ID = L2.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
      LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C ON 1 = 1
      WHERE L2.PARENT_ID = :I$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND :V$CALLER_TYPE = 2
      UNION
      SELECT L9.OBJ_ID, C.CAPTION, C.SORT_ORDER
      FROM LINKS L8
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
      LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C ON 1 = 1
      WHERE L8.PARENT_ID = :I$OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL AND :V$CALLER_TYPE = 7
      UNION
      SELECT L9.OBJ_ID, C.CAPTION, C.SORT_ORDER
      FROM LINKS L9
      LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C ON 1 = 1
      WHERE L9.PARENT_ID = :I$OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL AND :V$CALLER_TYPE = 8
      ORDER BY 3, 2
      INTO :V$PERSON_ID, :V$S1, :V$SO
    DO
    BEGIN
      VAL = '<tr>';
        VAL = VAL || '<td class="target class tl" data-target="' || V$PERSON_ID || '">' || V$S1 || '</td>';
        VAL = VAL || '<td>&nbsp;</td>';
        VAL = VAL || '<td>&nbsp;</td>';
      VAL = VAL || '</tr>';
      SUSPEND;
    END

    VAL = '</tbody></table>';
    SUSPEND;

    VAL = '<table id="s' || I$OBJ_ID || '" class="table centered" cellspacing="0" cellpadding="0" data-flags="sort arrange" style="min-width: 50%">';
    VAL = VAL || '<thead>';
    VAL = VAL || '<tr class="thd">';
      VAL = VAL || '<td class="tl sortable">Предмет</td>';
      VAL = VAL || '<td class="sortable value">Средний балл</td>';
      VAL = VAL || '<td class="sortable value">Динамика</td>';
    VAL = VAL || '</tr></thead><tbody>';
    SUSPEND;

    FOR
      SELECT S.SUBJECT_ID, C.CAPTION
      FROM CJ2_REPORT_NX310_SUBJ(:I$OBJ_ID, :V$CALLER_TYPE, :I$OBJ_ID, 0, :I$DATE_FROM, :V$DATE_TO, IIF(:V$OPTION_TYPE = 14, :I$OPTION_ID, NULL)) S
      LEFT JOIN OBJECT_CAPTION_GET(S.SUBJECT_ID) C ON 1 = 1
      WHERE (:V$OPTION_TYPE = 51 AND S.SUBJECT_ID = :I$OPTION_ID) OR :V$OPTION_TYPE <> 51
      INTO :V$SUBJECT_ID, :V$S1
    DO
    BEGIN
      VAL = '<tr>';
        VAL = VAL || '<td  class="target subject tl" data-target="' || V$SUBJECT_ID || '">' || V$S1 || '</td>';
        VAL = VAL || '<td>&nbsp;</td>';
        VAL = VAL || '<td>&nbsp;</td>';
      VAL = VAL || '</tr>';
      SUSPEND;
    END

    VAL = '</tbody></table>';
    SUSPEND;

    VAL = '<table id="h' || I$OBJ_ID || '" class="table centered" cellspacing="0" cellpadding="0" data-flags="sort arrange" style="min-width: 50%">';
    VAL = VAL || '<thead>';
    VAL = VAL || '<tr class="thd">';
      VAL = VAL || '<td class="tl sortable">Предподаватель</td>';
      VAL = VAL || '<td class="sortable value">Средний балл</td>';
      VAL = VAL || '<td class="sortable value">Динамика</td>';
    VAL = VAL || '</tr></thead><tbody>';
    SUSPEND;

    -- Собираем список преподавателей
    V$PREV_ID = 0;
    VAL = '';
    FOR
      SELECT DISTINCT S.TEACHER_ID, P.NAME_FULL --C.CAPTION
                    , S.SUBJECT_NAME
      FROM CJ2_REPORT_NX310_SUBJ(:I$OBJ_ID, :V$CALLER_TYPE, :I$OBJ_ID, 0, :I$DATE_FROM, :I$DATE_TO, NULL, IIF(:V$OPTION_TYPE = 14, :I$OPTION_ID, -1)) S
      LEFT JOIN UT_PERSON_DESC(S.TEACHER_ID, :I$ZONE, 1) P ON 1 = 1 --Redmine #1060 --LEFT JOIN OBJECT_CAPTION_GET(S.TEACHER_ID) C ON 1 = 1
      WHERE (
        ((:V$OPTION_TYPE = 51 AND S.SUBJECT_ID = :I$OPTION_ID) OR :V$OPTION_TYPE <> 51)
      )
      ORDER BY 2, 3
      INTO :V$SUBJECT_ID, :V$S1, :V$S2
    DO
    BEGIN
      IF(V$SUBJECT_ID <> V$PREV_ID) THEN
      BEGIN
        IF(V$PREV_ID > 0) THEN
        BEGIN
          VAL = VAL || ')</td>';
          VAL = VAL || '<td>&nbsp;</td>';
          VAL = VAL || '<td>&nbsp;</td>';
          VAL = VAL || '</tr>';
          SUSPEND;
        END

        VAL = '<tr>';
        VAL = VAL || '<td  class="target teacher tl" data-target="' || V$SUBJECT_ID || '">' || V$S1 || ' (' || V$S2;
      END
      ELSE
      BEGIN
        VAL = VAL || ', ' || V$S2;
      END
      V$PREV_ID = V$SUBJECT_ID;
    END
    IF(V$PREV_ID > 0) THEN
    BEGIN
      VAL = VAL || ')</td>';
      VAL = VAL || '<td>&nbsp;</td>';
      VAL = VAL || '<td>&nbsp;</td>';
      VAL = VAL || '</tr>';
      SUSPEND;
    END

    VAL = '</tbody></table>';
    SUSPEND;

  END

  VAL = '<script>';
  VAL = VAL || '(function () { ';
  VAL = VAL || 'let tid = "#t' || I$OBJ_ID || '";';
  VAL = VAL || 'let sid = "#s' || I$OBJ_ID || '";';
  VAL = VAL || 'let hid = "#h' || I$OBJ_ID || '";';
  VAL = VAL || 'let m = [';
  SUSPEND;

  FOR
    SELECT P.OBJ_ID, J.SUBJECT_ID, MT.MARK_COST, C.FINAL_DATE, P.PARENT_ID, J.TEACHER_ID
    FROM (
      -- для уровня образования
      SELECT DISTINCT L10.OBJ_ID, L10.PARENT_ID
      FROM LINKS L8
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
      JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      WHERE L8.PARENT_ID = :I$OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL AND :V$CALLER_TYPE = 7
      -- для параллели
      UNION
      SELECT DISTINCT L10.OBJ_ID, L10.PARENT_ID
      FROM LINKS L9
      JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      WHERE L9.PARENT_ID = :I$OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL AND :V$CALLER_TYPE = 8
      -- для класса
      UNION
      SELECT DISTINCT L10.OBJ_ID, L10.PARENT_ID
      FROM LINKS L10
      WHERE L10.PARENT_ID = :I$OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL AND :V$CALLER_TYPE IN (9, 187)
      -- для конкретного ученика
      UNION
      SELECT :I$OBJ_ID, 0
      FROM RDB$DATABASE
      WHERE :V$CALLER_TYPE = 10
    ) P
    JOIN CJ2_MARK M ON M.DATE_DEL IS NULL AND M.STUDENT_ID = P.OBJ_ID AND M.FINAL_ID IS NOT NULL
    JOIN CJ2_JOURNAL_FINALS C ON C.DATE_DEL IS NULL AND C.OBJ_ID = M.FINAL_ID AND C.FINAL_DATE >= :I$DATE_FROM AND C.FINAL_DATE <= :V$DATE_TO
    JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.JOURNAL_TYPE = 0 AND J.OBJ_ID = C.CJ_ID
    JOIN CJ2_MARK_TYPE MT ON MT.MARK_TYPE_ID = M.MARK_TYPE_ID
    WHERE (
      ((:V$OPTION_TYPE = 51 AND J.SUBJECT_ID = :I$OPTION_ID) OR :V$OPTION_TYPE <> 51) AND
      ((:V$OPTION_TYPE = 14 AND J.TEACHER_ID = :I$OPTION_ID) OR :V$OPTION_TYPE <> 14)
    )
    INTO :V$PERSON_ID, :V$SUBJECT_ID, :V$SO, :V$D, :V$GRADE_ID, :V$TEACHER_ID
  DO
  BEGIN
    -- p - id ученика, c - id класса (только если идет групповая выборка), s - id предмета, m - значение оценки в 5-балльной шкале, d - номер дня от начальной даты
    VAL = '{p:' || V$PERSON_ID || ',s:' || V$SUBJECT_ID || ',h:' || V$TEACHER_ID || ',m:' || CAST(V$SO AS NUMERIC(18, 1)) || ',d:' || DATEDIFF(DAY FROM I$DATE_FROM TO V$D);
    -- Ищем какой класс был последний
    IF(V$CALLER_TYPE IN (2, 7, 8)) THEN VAL = VAL || ',c:' || V$GRADE_ID;
    VAL = VAL || '},';
    SUSPEND;
  END

  VAL = '];';
  VAL = VAL || 'cjrCalcDynamics(tid, ' || V$CALLER_TYPE || ', m);';
  VAL = VAL || 'cjrCalcDynamics(sid, ' || V$CALLER_TYPE || ', m);';
  VAL = VAL || 'cjrCalcDynamics(hid, ' || V$CALLER_TYPE || ', m);';
  VAL = VAL || '})();';
  VAL = VAL || '</script>';
  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_REPORT_NX321 (
    I$USER_ID VARCHAR(40),
    I$DATE_FROM DATE,
    I$DATE_TO DATE,
    I$PARENT_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$OPTION_ID BIGINT,
    I$OPTIONS VARCHAR(1000),
    I$ZONE SMALLINT = 0)
RETURNS (
    VAL VARCHAR(4000))
AS
declare variable V$CALLER_TYPE bigint;
declare variable V$USER_TYPE smallint;
declare variable V$OU_LICENCE_TYPE varchar(2);
declare variable V$THRESHOLD varchar(20);
declare variable V$FLT varchar(20);
declare variable V$S1 varchar(400);
declare variable V$S2 varchar(400);
declare variable V$PERSON_ID bigint;
declare variable V$OPTION_TYPE bigint;
declare variable V$SUBJECT_ID bigint;
declare variable V$SO float;
declare variable V$D date;
declare variable V$GRADE_ID bigint;
begin

  -- Школа, коллектив, персона
  SELECT TYPE_ID FROM OBJECTS WHERE OBJ_ID = :I$OBJ_ID INTO :V$CALLER_TYPE;
  SELECT STATUS FROM OU_LICENCE_TYPE INTO :V$OU_LICENCE_TYPE;

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;
  SELECT USER_TYPE FROM USERS WHERE USER_ID = :I$USER_ID INTO :V$USER_TYPE;

  -- Вытаскиваем порог динамики
  FOR
    SELECT TAKEN
    FROM PARSING_STRING_GET(:I$OPTIONS, ';')
    INTO :V$S1
  DO
  BEGIN
    IF(SUBSTRING(V$S1 FROM 1 FOR 10) = 'THRESHOLD=') THEN V$THRESHOLD = SUBSTRING(V$S1 FROM 11);
    IF(SUBSTRING(V$S1 FROM 1 FOR 5) = 'SUBJ=') THEN V$FLT = SUBSTRING(V$S1 FROM 6);
  END

  IF(V$THRESHOLD IS NULL) THEN V$THRESHOLD = 'ННН';
  IF(V$FLT IS NULL) THEN V$FLT = 'Все предметы';

  -- Тип объекта опции - учитель или предмет
  V$OPTION_TYPE = 0;

  SELECT FIRST 1 TYPE_ID
  FROM OBJECTS
  WHERE OBJ_ID = :I$OPTION_ID
  INTO :V$OPTION_TYPE;

  VAL = '<!DOCTYPE html>';
  VAL = VAL || '<html lang="ru">';
  VAL = VAL || '<head>';
  VAL = VAL || '<meta charset="utf-8" />';
  VAL = VAL || '<style>';
  VAL = VAL || 'html { font-family: Tahoma, Verdana, Arial;';
  VAL = VAL || 'font-size: 10pt; ';
  VAL = VAL || '} ';
  VAL = VAL || '.title1 { font-size: 150%;';
  VAL = VAL || 'padding: 8px;';
  VAL = VAL || 'margin-bottom: 4px;';
  VAL = VAL || 'font-weight: bold;';
  VAL = VAL || 'background-color: #D4E157;';
  VAL = VAL || '} ';
  VAL = VAL || '.title2 { ';
  VAL = VAL || 'padding: 4px;';
  VAL = VAL || 'font-weight: bold;';
  VAL = VAL || '} ';
  VAL = VAL || '</style>';

  VAL = VAL || '</head>';
  VAL = VAL || '<body>';
  SUSPEND;

  -- Заголовок отчета
  VAL = '<div class="title1">Списки обучающихся по уровню динамики</div>';

  VAL = VAL || '<div class="title2">';
  IF (:V$CALLER_TYPE = 10) THEN VAL = VAL || (SELECT NAME_FULL FROM UT_PERSON_DESC(:I$OBJ_ID, :I$ZONE, 1));      -- обущающийся
                           ELSE VAL = VAL || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$OBJ_ID));
  VAL = VAL || '</div>';

  IF(I$OPTION_ID IS NOT NULL) THEN
  BEGIN
    V$S1 = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$OPTION_ID));
    VAL = VAL || '<div class="title2">В разрезе: ' || COALESCE(V$S1, '???') || '</div>';
  END

  V$S1 = (SELECT RESULT FROM DATE2STR(:I$DATE_FROM));
  V$S2 = (SELECT RESULT FROM DATE2STR(:I$DATE_TO));
  VAL = VAL || '<div class="title2">Период: ' || V$S1 || ' - ' || V$S2 || '</div>';
  SUSPEND;

  -- Заголовок таблицы
  -- sort = сортировать внутри секций
  -- arrange = перераспределить по секциям
  VAL = '<div class="title3">Уровень динамики: ';
  IF(V$THRESHOLD = 'ВВВ') THEN VAL = VAL || 'Высокая положительная динамика';
  IF(V$THRESHOLD = 'ВВ') THEN VAL = VAL || 'Средняя положительная динамика';
  IF(V$THRESHOLD = 'В') THEN VAL = VAL || 'Низкая положительная динамика';
  IF(V$THRESHOLD = '0') THEN VAL = VAL || 'Околонулевая динамика';
  IF(V$THRESHOLD = 'Н') THEN VAL = VAL || 'Низкая отрицательная динамика';
  IF(V$THRESHOLD = 'НН') THEN VAL = VAL || 'Средняя отрицательная динамика';
  IF(V$THRESHOLD = 'ННН') THEN VAL = VAL || 'Высокая отрицательная динамика';
  VAL = VAL || '</div>';

  VAL = VAL || '<table id="t0" class="table" cellspacing="0" cellpadding="0" data-flags="sort arrange" style="width: 100%">';
  VAL = VAL || '<thead>';
  VAL = VAL || '<tr class="thd">';
    VAL = VAL || '<td class="sortable">Учебный коллектив</td>';
    VAL = VAL || '<td class="sortable">ФИО</td>';
    VAL = VAL || '<td class="sortable" style="width: 40%">Предмет</td>';
    VAL = VAL || '<td class="sortable value">Средняя оценка</td>';
    VAL = VAL || '<td class="sortable value">Динамика оценок</td>';
  VAL = VAL || '</tr>';
  VAL = VAL || '</thead>';
  VAL = VAL || '<tbody>';
  SUSPEND;

  -- Список всех обучающихся выбранного уровня
  FOR
    SELECT MM.PERSON_ID, P.NAME_FULL --C.CAPTION,
           , CG.CAPTION
    FROM (
      SELECT M.PERSON_ID, MAX(M.GROUP_ID) GROUP_ID
      FROM PERSON_MOVEMENTS M
      JOIN LINKS LP8 ON LP8.OBJ_ID = M.GROUP_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
      JOIN LINKS LP7 ON LP7.OBJ_ID = LP8.PARENT_ID AND LP7.PARENT_TYPE_ID = 7 AND LP7.DATE_DEL IS NULL
      WHERE M.DATE_DEL IS NULL AND M.GROUP_TYPE_ID IN (9, 187)
        AND (:V$CALLER_TYPE <> 10 OR M.PERSON_ID = :I$OBJ_ID) -- фильтр по конкретному ученику
        AND (:V$CALLER_TYPE NOT IN (9, 187) OR M.GROUP_ID = :I$OBJ_ID) -- фильтр по классу
        AND (:V$CALLER_TYPE <> 8 OR LP8.PARENT_ID = :I$OBJ_ID) -- фильтр по параллели
        AND (:V$CALLER_TYPE <> 7 OR LP7.PARENT_ID = :I$OBJ_ID) -- фильтр по уровню
        AND M.DATE_IN <= :I$DATE_TO AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :I$DATE_FROM)
       GROUP BY 1
    ) MM
    LEFT JOIN UT_PERSON_DESC(MM.PERSON_ID, :I$ZONE, 1) P ON 1 = 1 --Redmine #1060 --LEFT JOIN OBJECT_CAPTION_GET(MM.PERSON_ID, 23) C ON 1 = 1
    LEFT JOIN OBJECT_CAPTION_GET(MM.GROUP_ID) CG ON 1 = 1
    ORDER BY CG.SORT_ORDER, 2
    INTO :V$PERSON_ID, :V$S1, :V$S2
  DO
  BEGIN
    VAL = '<tr class="hidden" data-value="' || V$PERSON_ID || '">';
    VAL = VAL || '<td>' || V$S2 || '</td>';
    VAL = VAL || '<td>' || V$S1 || '</td>';
    VAL = VAL || '<td class="v">&nbsp;</td>';
    VAL = VAL || '<td class="v">&nbsp;</td>';
    VAL = VAL || '<td class="v">&nbsp;</td>';
    VAL = VAL || '</tr>';
    SUSPEND;
  END

  VAL = '</tbody></table>';
  SUSPEND;

  -- Скрипт с данными оценок
  VAL = '<script>';
  VAL = VAL || '(function () { ';
  VAL = VAL || 'let m = [';
  SUSPEND;

  FOR
    SELECT P.OBJ_ID, J.SUBJECT_ID, MT.MARK_COST, L.LESSON_DATE, P.PARENT_ID
    FROM (
      -- для ОУ
      SELECT DISTINCT L10.OBJ_ID, L10.PARENT_ID
      FROM LINKS L7
      JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
      JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      WHERE L7.PARENT_ID = :I$OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL AND :V$CALLER_TYPE = 2
      -- для уровня образования
      UNION
      SELECT DISTINCT L10.OBJ_ID, L10.PARENT_ID
      FROM LINKS L8
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
      JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      WHERE L8.PARENT_ID = :I$OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL AND :V$CALLER_TYPE = 7
      -- для параллели
      UNION
      SELECT DISTINCT L10.OBJ_ID, L10.PARENT_ID
      FROM LINKS L9
      JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      WHERE L9.PARENT_ID = :I$OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL AND :V$CALLER_TYPE = 8
      -- для класса
      UNION
      SELECT DISTINCT L10.OBJ_ID, L10.PARENT_ID
      FROM LINKS L10
      WHERE L10.PARENT_ID = :I$OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL AND :V$CALLER_TYPE IN (9, 187)
      -- для конкретного ученика
      UNION
      SELECT :I$OBJ_ID, 0
      FROM RDB$DATABASE
      WHERE :V$CALLER_TYPE = 10
    ) P
    JOIN CJ2_MARK M ON M.DATE_DEL IS NULL AND M.STUDENT_ID = P.OBJ_ID AND M.CONTROL_ID IS NOT NULL
    JOIN CJ2_CONTROL C ON C.DATE_DEL IS NULL AND C.CONTROL_ID = M.CONTROL_ID AND C.CONTROL_TYPE_ID <> 0
    JOIN CJ2_JOURNAL_LESSONS L ON L.DATE_DEL IS NULL AND L.OBJ_ID = C.LESSON_ID AND L.IS_COMPLETED = 1 AND L.LESSON_DATE >= :I$DATE_FROM AND L.LESSON_DATE <= :I$DATE_TO
    JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.JOURNAL_TYPE = 0 AND J.OBJ_ID = L.CJ_ID
    JOIN CJ2_MARK_TYPE MT ON MT.MARK_TYPE_ID = M.MARK_TYPE_ID
    WHERE (:V$OPTION_TYPE = 51 AND J.SUBJECT_ID = :I$OPTION_ID) OR :V$OPTION_TYPE <> 51
    INTO :V$PERSON_ID, :V$SUBJECT_ID, :V$SO, :V$D, :V$GRADE_ID
  DO
  BEGIN
    -- p - id ученика, c - id класса (только если идет групповая выборка), s - id предмета, m - значение оценки в 5-балльной шкале (-1 для пропусков), d - номер дня от начальной даты
    VAL = '{p:' || V$PERSON_ID || ',s:' || V$SUBJECT_ID || ',m:' || CAST(V$SO AS NUMERIC(18, 1)) || ',d:' || DATEDIFF(DAY FROM I$DATE_FROM TO V$D);
    VAL = VAL || '},';
    SUSPEND;
  END

  VAL = '];';
  VAL = VAL || 'let s = [';
  SUSPEND;

  -- Список предметов
  FOR
    SELECT DISTINCT J.SUBJECT_ID
    FROM CJ2_JOURNAL J
    WHERE J.DATE_DEL IS NULL AND J.JOURNAL_TYPE = 0
    INTO :V$SUBJECT_ID
  DO
  BEGIN
    VAL = '{i:' || V$SUBJECT_ID || ',v:"' || REPLACE((SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$SUBJECT_ID)), '"', '');
    VAL = VAL || '"},';
    SUSPEND;
  END

  VAL = '];';

  VAL = VAL || 'cjrCalcDynList("#t0", "' || V$THRESHOLD || '","' || V$FLT || '", m, s);';
  VAL = VAL || '})();';
  VAL = VAL || '</script>';
  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_REPORT_NX330 (
    I$USER_ID VARCHAR(40),
    I$DATE_FROM DATE,
    I$DATE_TO DATE,
    I$PARENT_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$OPTION_ID BIGINT,
    I$OPTIONS VARCHAR(1000),
    I$ZONE SMALLINT = 0)
RETURNS (
    VAL VARCHAR(4000))
AS
declare variable V$CALLER_TYPE bigint;
declare variable V$USER_TYPE smallint;
declare variable V$OU_LICENCE_TYPE varchar(2);
declare variable V$S1 varchar(400);
declare variable V$S2 varchar(400);
declare variable V$PERSON_ID bigint;
declare variable V$EXPAND smallint;
declare variable V$OBJ_ID bigint;
declare variable N bigint;
begin

  -- Школа, коллектив, персона
  SELECT TYPE_ID FROM OBJECTS WHERE OBJ_ID = :I$OBJ_ID INTO :V$CALLER_TYPE;
  SELECT STATUS FROM OU_LICENCE_TYPE INTO :V$OU_LICENCE_TYPE;

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;
  SELECT USER_TYPE FROM USERS WHERE USER_ID = :I$USER_ID INTO :V$USER_TYPE;

  V$EXPAND = 0;
  FOR
    SELECT TAKEN
    FROM PARSING_STRING_GET(:I$OPTIONS, ';')
    INTO :V$S1
  DO
  BEGIN
    IF(SUBSTRING(V$S1 FROM 1 FOR 7) = 'EXPAND=') THEN
    BEGIN
      IF(SUBSTRING(V$S1 FROM 8) = '1') THEN V$EXPAND = 1;
    END
  END

  VAL = '<!DOCTYPE html>';
  VAL = VAL || '<html lang="ru">';
  VAL = VAL || '<head>';
  VAL = VAL || '<meta charset="utf-8" />';
  VAL = VAL || '<style>';
  VAL = VAL || 'html { font-family: Tahoma, Verdana, Arial;';
  VAL = VAL || 'font-size: 10pt; ';
  VAL = VAL || '} ';
  VAL = VAL || '.title1 { font-size: 150%;';
  VAL = VAL || 'padding: 8px;';
  VAL = VAL || 'margin-bottom: 4px;';
  VAL = VAL || 'font-weight: bold;';
  VAL = VAL || 'background-color: #D4E157;';
  VAL = VAL || '} ';
  VAL = VAL || '.title2 { ';
  VAL = VAL || 'padding: 4px;';
  VAL = VAL || 'font-weight: bold;';
  VAL = VAL || '} ';
  VAL = VAL || '</style>';

  VAL = VAL || '</head>';
  VAL = VAL || '<body>';
  SUSPEND;

  -- Заголовок отчета
  VAL = '<div class="title1">Корреляция успеваемости и посещаемости</div>';

  VAL = VAL || '<div class="title2">';
  IF (:V$CALLER_TYPE = 10) THEN VAL = VAL ||(SELECT NAME_FULL FROM UT_PERSON_DESC(:I$OBJ_ID, :I$ZONE, 1));      -- обущающийся
                           ELSE VAL = VAL || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$OBJ_ID));
  VAL = VAL || '</div>';

  IF(I$OPTION_ID IS NOT NULL) THEN
  BEGIN
    V$S1 = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$OPTION_ID));
    VAL = VAL || '<div class="title2">В разрезе: ' || COALESCE(V$S1, '???') || '</div>';
  END

  V$S1 = (SELECT RESULT FROM DATE2STR(:I$DATE_FROM));
  V$S2 = (SELECT RESULT FROM DATE2STR(:I$DATE_TO));
  VAL = VAL || '<div class="title2">Период: ' || V$S1 || ' - ' || V$S2 || '</div>';
  SUSPEND;

  -- Если у нас выбран НЕ учебный коллектив, то показываем меню для перехода
  -- но не выходим, а продолжаем дальше чтобы показать сводный отчет
  IF(V$CALLER_TYPE NOT IN (9, 187, 10) AND V$EXPAND = 0) THEN
  BEGIN
    -- Показываем кнопку для раскрытия детализации
    IF(V$CALLER_TYPE IN (7, 8)) THEN
    BEGIN
      VAL = '<div class="target option" data-target="EXPAND=1">Раскрыть детализацию для ' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$OBJ_ID)) || '</div>';
      SUSPEND;
    END

    VAL = '<div class="target-nav">';
    SUSPEND;

    FOR
      SELECT L7.OBJ_ID || ',' || L8.OBJ_ID || ',' || L9.OBJ_ID, C.CAPTION, C.SORT_ORDER
      FROM LINKS L7
      JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 187) AND L9.DATE_DEL IS NULL
      LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C ON 1 = 1
      WHERE L7.PARENT_ID = :I$OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL AND :V$CALLER_TYPE = 2
      UNION
      SELECT L8.OBJ_ID || ',' || L9.OBJ_ID, C.CAPTION, C.SORT_ORDER
      FROM LINKS L8
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 187) AND L9.DATE_DEL IS NULL
      LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C ON 1 = 1
      WHERE L8.PARENT_ID = :I$OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL AND :V$CALLER_TYPE = 7
      UNION
      SELECT L9.OBJ_ID, C.CAPTION, C.SORT_ORDER
      FROM LINKS L9
      LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C ON 1 = 1
      WHERE L9.PARENT_ID = :I$OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 187) AND L9.DATE_DEL IS NULL AND :V$CALLER_TYPE = 8
      ORDER BY 3, 2
      INTO :V$S1, :V$S2, :V$PERSON_ID
    DO
    BEGIN
      VAL = '<div class="target class" data-target="' || V$S1 || '">' || (SELECT VAL FROM ESCAPE_STR(:V$S2)) || '</div>';
      SUSPEND;
    END

    VAL = '</div>';
    SUSPEND;

    --VAL = '</body></html>';
    --SUSPEND;
    --EXIT;
  END

  FOR
    SELECT D.OBJ_ID, C.CAPTION, C.SORT_ORDER
    FROM (
      SELECT :I$OBJ_ID OBJ_ID
      FROM RDB$DATABASE
      WHERE :V$CALLER_TYPE IN (9, 187, 10) OR :V$EXPAND = 0
      UNION
      SELECT L9.OBJ_ID -- без экстернатов
      FROM LINKS L9
      WHERE L9.PARENT_ID = :I$OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL AND :V$CALLER_TYPE = 8 AND :V$EXPAND = 1
      UNION
      SELECT L9.OBJ_ID -- без экстернатов
      FROM LINKS L8
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
      WHERE L8.PARENT_ID = :I$OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL AND :V$CALLER_TYPE = 7 AND :V$EXPAND = 1
    ) D
    LEFT JOIN OBJECT_CAPTION_GET(D.OBJ_ID) C ON 1 = 1
    ORDER BY 3, 2
    INTO :V$OBJ_ID, :V$S1, :N
  DO
  BEGIN
    -- Выводим заголовок класса
    IF(V$EXPAND = 1) THEN
    BEGIN
      VAL = '<div class="target class" data-target="' || V$OBJ_ID || '"><b>' || (SELECT VAL FROM ESCAPE_STR(:V$S1)) || '</b></div>';
      SUSPEND;
    END

    FOR
      SELECT VAL
      FROM CJ2_REPORT_NX330_CC(:I$USER_ID, :I$DATE_FROM, :I$DATE_TO, :I$PARENT_ID, :V$OBJ_ID, :I$OBJ_ID, :I$OPTION_ID, :I$OPTIONS, :I$ZONE)
      INTO :VAL
    DO
    BEGIN
      SUSPEND;
    END
  END

  VAL = '</body></html>';
  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_REPORT_NX330_CC (
    I$USER_ID BIGINT,
    I$DATE_FROM DATE,
    I$DATE_TO DATE,
    I$PARENT_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$ROOT_ID BIGINT,
    I$OPTION_ID BIGINT,
    I$OPTIONS VARCHAR(1000),
    I$ZONE SMALLINT = 0)
RETURNS (
    VAL VARCHAR(4000))
AS
declare variable V$CALLER_TYPE bigint;
declare variable V$ROOT_TYPE bigint;
declare variable V$USER_TYPE smallint;
declare variable V$OU_LICENCE_TYPE varchar(2);
declare variable V$SUBJECT_ID bigint;
declare variable V$S1 varchar(400);
declare variable V$S2 varchar(400);
declare variable V$PERSON_ID bigint;
declare variable V$SO double precision;
declare variable V$D date;
declare variable V$GRADE_ID bigint;
declare variable V$OPTION_TYPE bigint;
declare variable V$DAYS integer;
begin

  if(I$OBJ_ID is null) then I$OBJ_ID = 825000002729;
  if(I$ROOT_ID is null) then I$ROOT_ID = 825000002729;
  if(I$DATE_FROM is null) then I$DATE_FROM = '01.09.2023';
  if(I$DATE_to is null) then I$DATE_to = '01.01.2024';

  -- Школа, коллектив, персона
  SELECT TYPE_ID FROM OBJECTS WHERE OBJ_ID = :I$OBJ_ID INTO :V$CALLER_TYPE;
  SELECT TYPE_ID FROM OBJECTS WHERE OBJ_ID = :I$ROOT_ID INTO :V$ROOT_TYPE;
  SELECT STATUS FROM OU_LICENCE_TYPE INTO :V$OU_LICENCE_TYPE;

  -- Тип объекта опции - учитель или предмет
  V$OPTION_TYPE = 0;

  SELECT FIRST 1 TYPE_ID
  FROM OBJECTS
  WHERE OBJ_ID = :I$OPTION_ID
  INTO :V$OPTION_TYPE;

  -- В разбивке по ученику или по классу показываем сразу с разбивкой по предметам и в целом
  -- В разбивке по уровню или параллели показываем две таблицы - по классам и по предметам

  IF(V$CALLER_TYPE IN (10, 9, 187)) THEN
  BEGIN

    VAL = '<table id="t' || I$OBJ_ID || '" class="table centered" cellspacing="0" cellpadding="0" data-flags="sort arrange" style="min-width: 50%">';
    VAL = VAL || '<thead>';
    VAL = VAL || '<tr class="thd">';
      VAL = VAL || '<td class="tl sortable">ФИО</td>';
      VAL = VAL || '<td class="sortable value">Средний балл</td>';
      VAL = VAL || '<td class="sortable value">Всего пропусков</td>';
      VAL = VAL || '<td class="sortable value">Среднее количество пропусков</td>';
      VAL = VAL || '<td class="sortable value">Корелляция</td>';
    VAL = VAL || '</tr></thead><tbody>';
    SUSPEND;

    FOR
      SELECT DISTINCT M.PERSON_ID, P.NAME_FULL --C.CAPTION
      FROM PERSON_MOVEMENTS M
      LEFT JOIN UT_PERSON_DESC(M.PERSON_ID, :I$ZONE, 1) P ON 1 = 1 --Redmine #1060 --LEFT JOIN OBJECT_CAPTION_GET(M.PERSON_ID, 23) C ON 1 = 1
      WHERE M.DATE_DEL IS NULL AND M.GROUP_TYPE_ID IN (9, 187)
        AND (:V$CALLER_TYPE <> 10 OR M.PERSON_ID = :I$OBJ_ID) -- фильтр по конкретному ученику
        AND (:V$CALLER_TYPE NOT IN (9, 187) OR M.GROUP_ID = :I$OBJ_ID) -- фильтр по классу
        AND M.DATE_IN <= :I$DATE_TO AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :I$DATE_FROM)
      ORDER BY 2
      INTO :V$PERSON_ID, :V$S1
    DO
    BEGIN
      VAL = '<tr>';
      IF(V$CALLER_TYPE = 10) THEN
        VAL = VAL || '<td class="tl" data-target="' || V$PERSON_ID || '">' || (SELECT VAL FROM ESCAPE_STR(:V$S1)) || '</td>';
      ELSE
        VAL = VAL || '<td class="target student tl" data-target="' || V$PERSON_ID || '">' || (SELECT VAL FROM ESCAPE_STR(:V$S1)) || '</td>';
      VAL = VAL || '<td>&nbsp;</td>';
      VAL = VAL || '<td>&nbsp;</td>';
      VAL = VAL || '<td>&nbsp;</td>';
      VAL = VAL || '<td>&nbsp;</td>';
      VAL = VAL || '</tr>';
      SUSPEND;
    END

    -- Итоговая строка по всем ученикам

    VAL = '</tbody></table>';
    SUSPEND;

  END
  -------------------
  ELSE
  BEGIN

    VAL = '<table id="t' || I$OBJ_ID || '" class="table centered" cellspacing="0" cellpadding="0" data-flags="sort arrange" style="min-width: 50%">';
    VAL = VAL || '<thead>';
    VAL = VAL || '<tr class="thd">';
      VAL = VAL || '<td class="tl sortable">Учебный коллектив</td>';
      VAL = VAL || '<td class="sortable value">Средний балл</td>';
      VAL = VAL || '<td class="sortable value">Всего пропусков</td>';
      VAL = VAL || '<td class="sortable value">Среднее количество пропусков</td>';
      VAL = VAL || '<td class="sortable value">Корелляция</td>';
    VAL = VAL || '</tr></thead><tbody>';
    SUSPEND;

    FOR
      SELECT L9.OBJ_ID, C.CAPTION, C.SORT_ORDER
      FROM LINKS L2
      JOIN LINKS L8 ON L8.PARENT_ID = L2.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
      LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C ON 1 = 1
      WHERE L2.PARENT_ID = :I$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND :V$CALLER_TYPE = 2
      UNION
      SELECT L9.OBJ_ID, C.CAPTION, C.SORT_ORDER
      FROM LINKS L8
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
      LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C ON 1 = 1
      WHERE L8.PARENT_ID = :I$OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL AND :V$CALLER_TYPE = 7
      UNION
      SELECT L9.OBJ_ID, C.CAPTION, C.SORT_ORDER
      FROM LINKS L9
      LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C ON 1 = 1
      WHERE L9.PARENT_ID = :I$OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL AND :V$CALLER_TYPE = 8
      ORDER BY 3, 2
      INTO :V$PERSON_ID, :V$S1, :V$SO
    DO
    BEGIN
      VAL = '<tr>';
        VAL = VAL || '<td class="target class tl" data-target="' || V$PERSON_ID || '">' || V$S1 || '</td>';
        VAL = VAL || '<td>&nbsp;</td>';
        VAL = VAL || '<td>&nbsp;</td>';
        VAL = VAL || '<td>&nbsp;</td>';
        VAL = VAL || '<td>&nbsp;</td>';
      VAL = VAL || '</tr>';
      SUSPEND;
    END

    VAL = '</tbody></table>';
    SUSPEND;

    VAL = '<table id="s' || I$OBJ_ID || '" class="table centered" cellspacing="0" cellpadding="0" data-flags="sort arrange" style="min-width: 50%">';
    VAL = VAL || '<thead>';
    VAL = VAL || '<tr class="thd">';
      VAL = VAL || '<td class="tl sortable">Предмет</td>';
      VAL = VAL || '<td class="sortable value">Средний балл</td>';
      VAL = VAL || '<td class="sortable value">Всего пропусков</td>';
      VAL = VAL || '<td class="sortable value">Среднее количество пропусков</td>';
      VAL = VAL || '<td class="sortable value">Корелляция</td>';
    VAL = VAL || '</tr></thead><tbody>';
    SUSPEND;

    FOR
      SELECT S.SUBJECT_ID, C.CAPTION
      FROM CJ2_REPORT_NX310_SUBJ(:I$OBJ_ID, :V$CALLER_TYPE, :I$OBJ_ID, 1, :I$DATE_FROM, :I$DATE_TO) S
      LEFT JOIN OBJECT_CAPTION_GET(S.SUBJECT_ID) C ON 1 = 1
      WHERE (:V$OPTION_TYPE = 51 AND S.SUBJECT_ID = :I$OPTION_ID) OR :V$OPTION_TYPE <> 51
      INTO :V$SUBJECT_ID, :V$S1
    DO
    BEGIN
      VAL = '<tr>';
        VAL = VAL || '<td  class="target subject tl" data-target="' || V$SUBJECT_ID || '">' || V$S1 || '</td>';
        VAL = VAL || '<td>&nbsp;</td>';
        VAL = VAL || '<td>&nbsp;</td>';
        VAL = VAL || '<td>&nbsp;</td>';
        VAL = VAL || '<td>&nbsp;</td>';
      VAL = VAL || '</tr>';
      SUSPEND;
    END

    VAL = '</tbody></table>';
    SUSPEND;

  END

  VAL = '<script>';
  VAL = VAL || '(function () { ';
  VAL = VAL || 'let tid = "#t' || I$OBJ_ID || '";';
  VAL = VAL || 'let sid = "#s' || I$OBJ_ID || '";';
  VAL = VAL || 'let m = [';
  SUSPEND;

  FOR
    SELECT P.OBJ_ID, J.SUBJECT_ID, IIF(MT.MARK_TYPE_ID < 100, -1, MT.MARK_COST), L.LESSON_DATE, P.PARENT_ID
    FROM (
      -- для уровня образования
      SELECT DISTINCT L10.OBJ_ID, L10.PARENT_ID
      FROM LINKS L8
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
      JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      WHERE L8.PARENT_ID = :I$OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL AND :V$CALLER_TYPE = 7
      -- для параллели
      UNION
      SELECT DISTINCT L10.OBJ_ID, L10.PARENT_ID
      FROM LINKS L9
      JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      WHERE L9.PARENT_ID = :I$OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL AND :V$CALLER_TYPE = 8
      -- для класса
      UNION
      SELECT DISTINCT L10.OBJ_ID, L10.PARENT_ID
      FROM LINKS L10
      WHERE L10.PARENT_ID = :I$OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL AND :V$CALLER_TYPE IN (9, 187)
      -- для конкретного ученика
      UNION
      SELECT :I$OBJ_ID, 0
      FROM RDB$DATABASE
      WHERE :V$CALLER_TYPE = 10
    ) P
    JOIN CJ2_MARK M ON M.DATE_DEL IS NULL AND M.STUDENT_ID = P.OBJ_ID AND M.CONTROL_ID IS NOT NULL AND M.MARK_TYPE_ID NOT IN (-1, 90) -- опоздания и замечания
    JOIN CJ2_CONTROL C ON C.DATE_DEL IS NULL AND C.CONTROL_ID = M.CONTROL_ID
    JOIN CJ2_JOURNAL_LESSONS L ON L.DATE_DEL IS NULL AND L.OBJ_ID = C.LESSON_ID AND L.IS_COMPLETED = 1 AND L.LESSON_DATE >= :I$DATE_FROM AND L.LESSON_DATE <= :I$DATE_TO
    JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.JOURNAL_TYPE = 0 AND J.OBJ_ID = L.CJ_ID
    JOIN CJ2_MARK_TYPE MT ON MT.MARK_TYPE_ID = M.MARK_TYPE_ID
    WHERE (:V$OPTION_TYPE = 51 AND J.SUBJECT_ID = :I$OPTION_ID) OR :V$OPTION_TYPE <> 51
    INTO :V$PERSON_ID, :V$SUBJECT_ID, :V$SO, :V$D, :V$GRADE_ID
  DO
  BEGIN
    -- p - id ученика, c - id класса (только если идет групповая выборка), s - id предмета, m - значение оценки в 5-балльной шкале (-1 для пропусков), d - номер дня от начальной даты
    VAL = '{p:' || V$PERSON_ID || ',s:' || V$SUBJECT_ID || ',m:' || CAST(V$SO AS NUMERIC(18, 1)) || ',d:' || DATEDIFF(DAY FROM I$DATE_FROM TO V$D);
    -- Ищем какой класс был последний
    IF(V$CALLER_TYPE IN (2, 7, 8)) THEN VAL = VAL || ',c:' || V$GRADE_ID;
    VAL = VAL || '},';
    SUSPEND;
  END

  VAL = '];';
  V$DAYS = DATEDIFF(DAY FROM I$DATE_FROM TO I$DATE_TO);
  VAL = VAL || 'cjrCalcCorellation(tid, ' || V$CALLER_TYPE || ',' || V$DAYS || ', m);';
  VAL = VAL || 'cjrCalcCorellation(sid, ' || V$CALLER_TYPE || ',' || V$DAYS || ', m);';
  VAL = VAL || '})();';
  VAL = VAL || '</script>';
  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_REPORT_NX400 (
    I$USER_ID VARCHAR(40),
    I$DATE_FROM DATE,
    I$DATE_TO DATE,
    I$PARENT_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$OPTION_ID BIGINT,
    I$OPTIONS VARCHAR(1000),
    I$ZONE SMALLINT = 0)
RETURNS (
    VAL VARCHAR(4000))
AS
declare variable V$CALLER_TYPE bigint;
declare variable V$USER_TYPE smallint;
declare variable V$OU_LICENCE_TYPE varchar(2);
declare variable V$S1 varchar(400);
declare variable V$S2 varchar(400);
declare variable V$PERSON_ID bigint;
declare variable V$EXPAND smallint;
declare variable V$OBJ_ID bigint;
declare variable N bigint;
declare variable N1 integer;
declare variable N2 integer;
declare variable V$STAGE_ID bigint;
declare variable V$SUBJECT_ID bigint;
begin

  -- Школа, коллектив, персона
  SELECT TYPE_ID FROM OBJECTS WHERE OBJ_ID = :I$OBJ_ID INTO :V$CALLER_TYPE;
  SELECT STATUS FROM OU_LICENCE_TYPE INTO :V$OU_LICENCE_TYPE;

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;
  SELECT USER_TYPE FROM USERS WHERE USER_ID = :I$USER_ID INTO :V$USER_TYPE;

  V$EXPAND = 0;
  FOR
    SELECT TAKEN
    FROM PARSING_STRING_GET(:I$OPTIONS, ';')
    INTO :V$S1
  DO
  BEGIN
    IF(SUBSTRING(V$S1 FROM 1 FOR 7) = 'EXPAND=') THEN
    BEGIN
      IF(SUBSTRING(V$S1 FROM 8) = '1') THEN V$EXPAND = 1;
    END
  END

  VAL = '<!DOCTYPE html>';
  VAL = VAL || '<html lang="ru">';
  VAL = VAL || '<head>';
  VAL = VAL || '<meta charset="utf-8" />';
  VAL = VAL || '<style>';
  VAL = VAL || 'html { font-family: Tahoma, Verdana, Arial;';
  VAL = VAL || 'font-size: 10pt; ';
  VAL = VAL || '} ';
  VAL = VAL || '.title1 { font-size: 150%;';
  VAL = VAL || 'padding: 8px;';
  VAL = VAL || 'margin-bottom: 4px;';
  VAL = VAL || 'font-weight: bold;';
  VAL = VAL || 'background-color: #D4E157;';
  VAL = VAL || '} ';
  VAL = VAL || '.title2 { ';
  VAL = VAL || 'padding: 4px;';
  VAL = VAL || 'font-weight: bold;';
  VAL = VAL || '} ';
  VAL = VAL || '</style>';

  VAL = VAL || '</head>';
  VAL = VAL || '<body>';
  SUSPEND;

  -- Заголовок отчета
  VAL = '<div class="title1">Посещаемость и тематика ВУД по обязательным предметам</div>';

  VAL = VAL || '<div class="title2">';
  IF (:V$CALLER_TYPE = 10) THEN VAL = VAL || (SELECT NAME_FULL FROM UT_PERSON_DESC(:I$OBJ_ID, :I$ZONE, 1));      -- обущающийся
                           ELSE VAL = VAL || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$OBJ_ID));
  VAL = VAL ||  '</div>';

  IF(I$OPTION_ID IS NOT NULL) THEN
  BEGIN
    V$S1 = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$OPTION_ID));
    VAL = VAL || '<div class="title2">В разрезе: ' || COALESCE(V$S1, '???') || '</div>';
  END

  V$S1 = (SELECT RESULT FROM DATE2STR(:I$DATE_FROM));
  V$S2 = (SELECT RESULT FROM DATE2STR(:I$DATE_TO));
  VAL = VAL || '<div class="title2">Период: ' || V$S1 || ' - ' || V$S2 || '</div>';
  SUSPEND;

  VAL = '<table id="t' || I$OBJ_ID || '" class="table centered" cellspacing="0" cellpadding="0" data-flags="sort arrange" style="min-width: 50%">';
  VAL = VAL || '<thead>';
  VAL = VAL || '<tr class="thd">';

  -- В разрезе классов выводим таблицу с общими сведениями
  IF(V$CALLER_TYPE IN (2, 7, 8, 9, 187)) THEN
  BEGIN
    VAL = VAL || '<td class="tl sortable">Учебный коллектив, предмет</td>';
    VAL = VAL || '<td class="sortable">Количество занятий</td>';
    VAL = VAL || '<td class="sortable">Средняя посещаемость</td>';
  END

  VAL = VAL || '</tr></thead><tbody>';
  SUSPEND;

  FOR
    SELECT D.OBJ_ID, C.CAPTION, C.SORT_ORDER
    FROM (
      SELECT :I$OBJ_ID OBJ_ID
      FROM RDB$DATABASE
      WHERE :V$CALLER_TYPE IN (9, 187)
      UNION
      SELECT L9.OBJ_ID -- без экстернатов
      FROM LINKS L9
      WHERE L9.PARENT_ID = :I$OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL AND :V$CALLER_TYPE = 8
      UNION
      SELECT L9.OBJ_ID -- без экстернатов
      FROM LINKS L8
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
      WHERE L8.PARENT_ID = :I$OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL AND :V$CALLER_TYPE = 7
      UNION
      SELECT L9.OBJ_ID -- без экстернатов
      FROM LINKS L2
      JOIN LINKS L8 ON L8.PARENT_ID = L2.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
      WHERE L2.PARENT_ID = :I$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND :V$CALLER_TYPE = 2
    ) D
    LEFT JOIN OBJECT_CAPTION_GET(D.OBJ_ID) C ON 1 = 1
    ORDER BY 3, 2
    INTO :V$OBJ_ID, :V$S1, :N
  DO
  BEGIN
    VAL = '<tr><td colspan="3" class="tl">' || V$S1 || '</td></tr>';
    SUSPEND;

    V$STAGE_ID = NULL;
    SELECT FIRST 1 V49.LISTVAL_ID
    FROM LINKS LP8
    JOIN VALL V49 ON V49.OBJ_ID = LP8.PARENT_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
    WHERE LP8.OBJ_ID = :V$OBJ_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
    INTO :V$STAGE_ID;

    -- Идем по всем предметам, по которым есть журналы в этой параллели
    FOR
      SELECT DISTINCT J.SUBJECT_ID, C.CAPTION
      FROM CJ2_JOURNAL J
      JOIN VALL V3377 ON V3377.OBJ_ID = J.SUBJECT_ID AND V3377.PARAM_ID = 3377 AND V3377.IS_DEL = 0 AND V3377.LISTVAL_ID = 2
      LEFT JOIN OBJECT_CAPTION_GET(J.SUBJECT_ID) C ON 1 = 1
      WHERE J.DATE_DEL IS NULL AND J.STAGE_INDEX = :V$STAGE_ID AND J.JOURNAL_TYPE = 1
      ORDER BY 2
      INTO :V$SUBJECT_ID, :V$S1
    DO
    BEGIN
      VAL = '<tr><td class="tl">' || V$S1 || '</td>';

      -- Количество занятий
      SELECT COUNT(DISTINCT L.OBJ_ID)
      FROM LINKS L10
      JOIN LINKS LPG ON LPG.OBJ_ID = L10.OBJ_ID AND LPG.PARENT_TYPE_ID IN (9, 187, 179, 256) AND LPG.DATE_DEL IS NULL
      JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.SUBJECT_ID = :V$SUBJECT_ID AND J.GRADE_ID = LPG.PARENT_ID AND J.JOURNAL_TYPE = 1
      JOIN CJ2_JOURNAL_LESSONS L ON L.DATE_DEL IS NULL AND (L.IS_COMPLETED = 1 OR L.IS_PUBLISHED = 1) AND L.CJ_ID = J.OBJ_ID
      WHERE L10.PARENT_ID = :V$OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      INTO :N;

      VAL = VAL || '<td>' || COALESCE(N, 0) || '</td>';

      -- Сколько у нас учеников
      SELECT COUNT(DISTINCT L10.OBJ_ID)
      FROM LINKS L10
      JOIN LINKS LPG ON LPG.OBJ_ID = L10.OBJ_ID AND LPG.PARENT_TYPE_ID IN (9, 187, 179, 256) AND LPG.DATE_DEL IS NULL
      JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.SUBJECT_ID = :V$SUBJECT_ID AND J.GRADE_ID = LPG.PARENT_ID AND J.JOURNAL_TYPE = 1
      WHERE L10.PARENT_ID = :V$OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      INTO :N1;

      -- Сколько суммарно пропусков
      SELECT COUNT(DISTINCT L.OBJ_ID)
      FROM LINKS L10
      JOIN LINKS LPG ON LPG.OBJ_ID = L10.OBJ_ID AND LPG.PARENT_TYPE_ID IN (9, 187, 179, 256) AND LPG.DATE_DEL IS NULL
      JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.SUBJECT_ID = :V$SUBJECT_ID AND J.GRADE_ID = LPG.PARENT_ID AND J.JOURNAL_TYPE = 1
      JOIN CJ2_JOURNAL_LESSONS L ON L.DATE_DEL IS NULL AND (L.IS_COMPLETED = 1 OR L.IS_PUBLISHED = 1) AND L.CJ_ID = J.OBJ_ID
      JOIN CJ2_CONTROL C ON C.DATE_DEL IS NULL AND C.LESSON_ID = L.OBJ_ID AND C.CONTROL_TYPE_ID = 0
      JOIN CJ2_MARK M ON M.DATE_DEL IS NULL AND M.CONTROL_ID = C.CONTROL_ID AND M.STUDENT_ID = L10.OBJ_ID AND M.MARK_TYPE_ID IN (91, 92, 93, 94)
      WHERE L10.PARENT_ID = :V$OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      INTO :N2;

      -- Посещаемость занятий, в процентах
      IF(N * N1 > 0) THEN V$S2 = CAST(100 - 100.0 * N2 / (N * N1) AS INTEGER); ELSE V$S2 = '&nbsp;';
      VAL = VAL || '<td>' || V$S2 || '</td>';

      VAL = VAL || '</tr>';
      SUSPEND;
    END
  END

  -- Закрываем прошлую таблицу
  IF(V$CALLER_TYPE <> 10) THEN
  BEGIN
    VAL = '</tbody></table>';
    SUSPEND;
  END

  -- Темы занятий
  IF(V$CALLER_TYPE IN (9, 187, 10)) THEN
  BEGIN
    V$STAGE_ID = NULL;
    SELECT FIRST 1 V49.LISTVAL_ID
    FROM LINKS LP8
    JOIN VALL V49 ON V49.OBJ_ID = LP8.PARENT_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
    WHERE LP8.OBJ_ID = :V$OBJ_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
    INTO :V$STAGE_ID;

    FOR
      SELECT DISTINCT J.SUBJECT_ID, C.CAPTION
      FROM CJ2_JOURNAL J
      JOIN VALL V3377 ON V3377.OBJ_ID = J.SUBJECT_ID AND V3377.PARAM_ID = 3377 AND V3377.IS_DEL = 0 AND V3377.LISTVAL_ID = 2
      LEFT JOIN OBJECT_CAPTION_GET(J.SUBJECT_ID) C ON 1 = 1
      WHERE J.DATE_DEL IS NULL AND J.STAGE_INDEX = :V$STAGE_ID AND J.JOURNAL_TYPE = 1
      ORDER BY 2
      INTO :V$SUBJECT_ID, :V$S1
    DO
    BEGIN
      VAL = '<div class="target subject" data-target="' || V$SUBJECT_ID || '"><b>' || (SELECT VAL FROM ESCAPE_STR(:V$S1)) || '</b></div>';
      VAL = VAL || '<table id="t' || I$OBJ_ID || '" class="table centered" cellspacing="0" cellpadding="0" data-flags="sort arrange" style="min-width: 50%">';
      VAL = VAL || '<thead>';
      VAL = VAL || '<tr class="thd">';
        VAL = VAL || '<td class="tl sortable">Тема занятия</td>';
        VAL = VAL || '<td class="sortable">Посещаемость, %</td>';
      VAL = VAL || '</tr></thead><tbody>';
      SUSPEND;

      -- Сколько у нас учеников
      SELECT COUNT(DISTINCT L10.OBJ_ID)
      FROM LINKS L10
      JOIN LINKS LPG ON LPG.OBJ_ID = L10.OBJ_ID AND LPG.PARENT_TYPE_ID IN (9, 187, 179, 256) AND LPG.DATE_DEL IS NULL
      JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.SUBJECT_ID = :V$SUBJECT_ID AND J.GRADE_ID = LPG.PARENT_ID AND J.JOURNAL_TYPE = 1
      WHERE L10.PARENT_ID = :V$OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      INTO :N1;

      FOR
        SELECT DISTINCT L.OBJ_ID, L.LESSON_THEME
        FROM LINKS L10
        JOIN LINKS LPG ON LPG.OBJ_ID = L10.OBJ_ID AND LPG.PARENT_TYPE_ID IN (9, 187, 179, 256) AND LPG.DATE_DEL IS NULL
        JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.SUBJECT_ID = :V$SUBJECT_ID AND J.GRADE_ID = LPG.PARENT_ID AND J.JOURNAL_TYPE = 1
        JOIN CJ2_JOURNAL_LESSONS L ON L.DATE_DEL IS NULL AND (L.IS_COMPLETED = 1 OR L.IS_PUBLISHED = 1) AND L.CJ_ID = J.OBJ_ID
        WHERE L10.PARENT_ID = :V$OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        INTO :V$OBJ_ID, :V$S1
      DO
      BEGIN
        VAL = '<tr><td class="tl">' || V$S1 || '</td>';

        SELECT COUNT(*)
        FROM CJ2_CONTROL C
        JOIN CJ2_MARK M ON M.DATE_DEL IS NULL AND M.CONTROL_ID = C.CONTROL_ID AND M.MARK_TYPE_ID IN (91, 92, 93, 94)
        WHERE C.DATE_DEL IS NULL AND C.LESSON_ID = :V$OBJ_ID AND C.CONTROL_TYPE_ID = 0
        INTO :N2;

        IF(N1 > 0) THEN V$S2 = CAST(100 - 100.0 * N2 / N1 AS INTEGER); ELSE V$S2 = '&nbsp;';
        VAL = VAL || '<td>' || V$S2 || '</td>';

        VAL = VAL || '</tr>';
        SUSPEND;
      END

      VAL = '</tbody></table>';
      SUSPEND;
    END

  END

  VAL = '</body></html>';
  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_REPORT_NX7 (
    I$USER_ID VARCHAR(40),
    I$DATE_FROM DATE,
    I$DATE_TO DATE,
    I$PARENT_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$OPTION_ID BIGINT,
    I$OPTIONS VARCHAR(1000),
    I$ZONE SMALLINT = 0)
RETURNS (
    VAL VARCHAR(4000))
AS
DECLARE VARIABLE V$CALLER_TYPE BIGINT;
DECLARE VARIABLE V$OU_LICENCE_TYPE CHAR(1);
DECLARE VARIABLE V$YEAR_ID BIGINT;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$CJ_ID BIGINT;
DECLARE VARIABLE V$LESSON_DATE DATE;
DECLARE VARIABLE N_DATES INTEGER;
DECLARE VARIABLE V$S1 VARCHAR(100);
DECLARE VARIABLE V$S2 VARCHAR(100);
DECLARE VARIABLE V$C VARCHAR(100);
DECLARE VARIABLE V$S3 VARCHAR(100);
DECLARE VARIABLE V$PREV_CJ BIGINT;
DECLARE VARIABLE S VARCHAR(4000);
DECLARE VARIABLE V$MARK_ID BIGINT;
DECLARE VARIABLE V$MARK FLOAT;
DECLARE VARIABLE V$CC FLOAT;
DECLARE VARIABLE V$SUM FLOAT;
DECLARE VARIABLE V$N FLOAT;
DECLARE VARIABLE V$MC FLOAT;
DECLARE VARIABLE N INTEGER;
DECLARE VARIABLE L INTEGER;
DECLARE VARIABLE V$DATE_TO2 DATE;
DECLARE VARIABLE V$FT BIGINT;
DECLARE VARIABLE V$TFT BIGINT;
DECLARE VARIABLE V$FTSCALE FLOAT;
DECLARE VARIABLE V$DATE DATE;
DECLARE VARIABLE V$CC_ID BIGINT;
begin

  -- Школа, коллектив, персона
  SELECT TYPE_ID FROM OBJECTS WHERE OBJ_ID = :I$OBJ_ID INTO :V$CALLER_TYPE;
  SELECT STATUS FROM OU_LICENCE_TYPE INTO :V$OU_LICENCE_TYPE;

  SELECT V1236.LISTVAL_ID
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$YEAR_ID;

  V$DATE_TO2 = DATEADD(1 MONTH TO I$DATE_TO);

  VAL = '<!DOCTYPE html>';
  VAL = VAL || '<html lang="ru">';
  VAL = VAL || '<head>';
  VAL = VAL || '<meta charset="utf-8" />';
  VAL = VAL || '<style>';
  VAL = VAL || 'html { font-family: Tahoma, Verdana, Arial;';
  VAL = VAL || 'font-size: 10pt; ';
  VAL = VAL || '} ';
  VAL = VAL || '</style>';

  VAL = VAL || '</head>';
  VAL = VAL || '<body>';
  SUSPEND;

  -- Заголовок отчета
  VAL = '<div class="title1">Отчет об успеваемости</div>';

  VAL = VAL || '<div class="title2">';
  IF (V$CALLER_TYPE = 10) THEN VAL = VAL || (SELECT NAME_FULL FROM UT_PERSON_DESC(:I$OBJ_ID, :I$ZONE, 1));      -- обущающийся
  ELSE VAL = VAL || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$OBJ_ID));
  VAL = VAL || '</div>';

  V$S1 = (SELECT RESULT FROM DATE2STR(:I$DATE_FROM));
  V$S2 = (SELECT RESULT FROM DATE2STR(:I$DATE_TO));
  VAL = VAL || '<div class="title2">Период: ' || V$S1 || ' - ' || V$S2 || '</div>';

  IF(V$CALLER_TYPE = 2) THEN
  BEGIN
    VAL = VAL || '<div style="padding: 10px; color: #fff; background: darkred; border-radius: 4px; margin-top: 20px; margin-bottom: 20px">';
      VAL = VAL || 'Отчет об успеваемости строится только в масштабе учебного коллектива или конкретного обучающегося';
    VAL = VAL || '</div>';
    VAL = VAL ||'</body></html>';
    SUSPEND;
    EXIT;
  END

  -- Чистим буфер и заполняем даты
  DELETE FROM CJ_REPORT4_TEMP WHERE 1 = 1;

  S = '';
  N_DATES = 0;
  FOR
    -- Выборка по группе
    SELECT DISTINCT L.LESSON_DATE
    FROM LINKS L10
    JOIN PERSON_MOVEMENTS MV ON MV.DATE_DEL IS NULL AND MV.PERSON_ID = L10.OBJ_ID AND MV.DATE_IN <= :I$DATE_TO AND (MV.DATE_OUT IS NULL OR MV.DATE_OUT >= :I$DATE_FROM)
    JOIN CJ2_JOURNAL J ON J.GRADE_ID = MV.GROUP_ID AND J.DATE_DEL IS NULL AND J.JOURNAL_TYPE = 0 AND J.YEAR_ID = :V$YEAR_ID
    JOIN CJ2_JOURNAL_LESSONS L ON L.CJ_ID = J.OBJ_ID AND (L.LESSON_DATE BETWEEN :I$DATE_FROM AND :I$DATE_TO)
      AND L.IS_COMPLETED = 1 AND L.DATE_DEL IS NULL
    WHERE L10.PARENT_ID = :I$OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL AND :V$CALLER_TYPE <> 10
    UNION
    SELECT DISTINCT L.LESSON_DATE
    FROM PERSON_MOVEMENTS MV
    JOIN CJ2_JOURNAL J ON J.GRADE_ID = MV.GROUP_ID AND J.DATE_DEL IS NULL AND J.JOURNAL_TYPE = 0 AND J.YEAR_ID = :V$YEAR_ID
    JOIN CJ2_JOURNAL_LESSONS L ON L.CJ_ID = J.OBJ_ID AND (L.LESSON_DATE BETWEEN :I$DATE_FROM AND :I$DATE_TO)
      AND L.IS_COMPLETED = 1 AND L.DATE_DEL IS NULL
    WHERE MV.DATE_DEL IS NULL AND MV.PERSON_ID = :I$OBJ_ID AND :V$CALLER_TYPE = 10 AND MV.DATE_IN <= :I$DATE_TO AND (MV.DATE_OUT IS NULL OR MV.DATE_OUT >= :I$DATE_FROM)
    ORDER BY 1
    INTO :V$DATE
  DO
  BEGIN
    INSERT INTO CJ_REPORT4_TEMP (DATE_ID, CLASS_ID) VALUES (:V$DATE, 0);
    S = S || '<td>' || (SELECT RESULT FROM DATE2STR(:V$DATE)) || '</td>';
    N_DATES = N_DATES + 1;
  END

  -- Для учебного коллектива выдаем список ссылок на группы
  IF(V$CALLER_TYPE <> 10) THEN
  BEGIN
    /*FOR
      FROM LINKS L10
    DO
    BEGIN
    END*/
  END

  -- Заголовок таблицы
  VAL = VAL || '<table class="table" cellspacing="0" cellpadding="0" style="width: 100%">';

  VAL = VAL || '<tr class="thd">';
  VAL = VAL || '<td style="width: 20%" class="sortable text grouped">';
    IF(V$CALLER_TYPE = 10) THEN VAL = VAL || 'Предмет'; ELSE VAL = VAL || 'Обучающийся';
  VAL = VAL || '</td>';
  -- Дополнительный столбец
  IF(V$CALLER_TYPE <> 10) THEN VAL = VAL || '<td>Предмет</td>';
  VAL = VAL || '<td>Отметки</td>';
  VAL = VAL || '<td style="width: 5rem" class="sortable value">Рек. отметка</td>';
  VAL = VAL || '<td style="width: 5rem" class="sortable value">Итоговая отметка</td>';
  VAL = VAL || '<td style="width: 5rem" class="sortable value">Пропуски</td>';
  VAL = VAL || '</tr>';

  SUSPEND;

  IF(V$CALLER_TYPE = 10) THEN
  BEGIN
    -- По конкретному ученику
    FOR
      SELECT DISTINCT J.OBJ_ID, J.SUBJECT_ID, C.CAPTION
      FROM PERSON_MOVEMENTS MV
      JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.GRADE_ID = MV.GROUP_ID AND J.JOURNAL_TYPE = 0 AND J.YEAR_ID = :V$YEAR_ID
      LEFT JOIN OBJECT_CAPTION_GET(J.SUBJECT_ID) C ON 1 = 1
      WHERE MV.PERSON_ID = :I$OBJ_ID AND MV.DATE_DEL IS NULL AND MV.DATE_IN <= :I$DATE_TO AND (MV.DATE_OUT IS NULL OR MV.DATE_OUT >= :I$DATE_FROM)
      ORDER BY 3
      INTO :V$CJ_ID, :V$OBJ_ID, :S
    DO
    BEGIN
      VAL = '<tr class="v">';
      VAL = VAL || '<td><div class="target journal" data-target="' || V$CJ_ID || '">' || S || '</div></td>';
      VAL = VAL || '<td>';
      SUSPEND;

      V$SUM = 0;
      V$N = 0;

      FOR
        SELECT C.CONTROL_COST, MT.MARK_COST, MT.MARK_SHORTNAME, MT.MARK_TYPE_ID
        FROM PERSON_MOVEMENTS MV
        JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.GRADE_ID = MV.GROUP_ID AND J.OBJ_ID = :V$CJ_ID AND J.JOURNAL_TYPE = 0 AND J.YEAR_ID = :V$YEAR_ID
        JOIN CJ2_JOURNAL_LESSONS L ON L.DATE_DEL IS NULL AND L.CJ_ID = J.OBJ_ID AND (L.LESSON_DATE BETWEEN :I$DATE_FROM AND :I$DATE_TO)
          AND L.IS_COMPLETED = 1
        JOIN CJ2_CONTROL C ON C.DATE_DEL IS NULL AND C.LESSON_ID = L.OBJ_ID AND C.CONTROL_TYPE_ID <> 0 AND C.CONTROL_TYPE_ID <> 30000
        JOIN CJ2_MARK M ON M.DATE_DEL IS NULL AND M.CONTROL_ID = C.CONTROL_ID AND M.STUDENT_ID = MV.PERSON_ID
        JOIN CJ2_MARK_TYPE MT ON MT.MARK_TYPE_ID = M.MARK_TYPE_ID AND MT.PARENT_ID <> 200 -- скрываем да/нет
        WHERE MV.PERSON_ID = :I$OBJ_ID AND MV.DATE_DEL IS NULL AND MV.DATE_IN <= :I$DATE_TO AND (MV.DATE_OUT IS NULL OR MV.DATE_OUT >= :I$DATE_FROM)
        ORDER BY L.LESSON_DATE, C.CONTROL_ID
        INTO :V$CC, :V$MARK, :V$S1, :V$MARK_ID
      DO
      BEGIN
        IF(V$MARK = 1) THEN V$C = ' pink'; -- 1
        ELSE IF(V$MARK = 2) THEN V$C = ' red'; -- незачет или 2
        ELSE IF(V$MARK = 3) THEN V$C = ' orange'; -- 3
        ELSE IF(V$MARK = 4) THEN V$C = ' violet'; -- 4
        ELSE IF(V$MARK = 5) THEN V$C = ' blue'; -- зачет или 5
        ELSE V$C = '';

        VAL = '<div class="ui circular label dl' || V$C || '" data-subject="' || REPLACE(S, '"', '&quot;') || '">' || V$S1 || '</div>';
        SUSPEND;
        V$SUM = V$SUM + V$MARK * V$CC;
        V$N = V$N + V$CC;
      END

      VAL = '</td>';

      -- Итоговая
      S = '';
      V$FT = 400; -- 5-балльная по-умолчанию
      FOR
        SELECT T.VAL, MT.MARK_SHORTNAME, MT.MARK_COST, F.MARK_SYSTEM_ID
        FROM CJ2_JOURNAL J
        JOIN CJ2_JOURNAL_FINALS F ON F.DATE_DEL IS NULL AND F.CJ_ID = J.OBJ_ID AND (F.FINAL_DATE BETWEEN :I$DATE_FROM AND :V$DATE_TO2)
          -- AND L.IS_COMPLETED = 1
        JOIN CJ2_MARK M ON M.DATE_DEL IS NULL AND M.FINAL_ID = F.OBJ_ID AND M.STUDENT_ID = :I$OBJ_ID
        JOIN CJ2_MARK_TYPE MT ON MT.MARK_TYPE_ID = M.MARK_TYPE_ID AND MT.PARENT_ID <> 200 -- скрываем да/нет
        LEFT JOIN LISTVAL_TEXT(F.FINAL_TYPE) T ON 1 = 1
        WHERE J.DATE_DEL IS NULL AND J.OBJ_ID = :V$CJ_ID
        ORDER BY F.FINAL_TYPE
        INTO :V$S2, :V$S3, :V$MC, :V$TFT
      DO
      BEGIN
        IF(V$MC > 0 AND V$MC < 1.5) THEN V$C = ' pink'; -- 1
        ELSE IF(V$MC < 2.5) THEN V$C = ' red'; -- незачет или 2
        ELSE IF(V$MC < 3.5) THEN V$C = ' orange'; -- 3
        ELSE IF(V$MC < 4.5) THEN V$C = ' violet'; -- 4
        ELSE IF(V$MC >= 4.5 AND V$MC <= 5) THEN V$C = ' blue'; -- зачет или 5
        ELSE V$C = '';
        S = S || '<div class="ui circular label dl' || V$C || ' data-period="' || V$S2 || '" title="' || V$S2 || '">' || V$S3 || '</div>';
        V$FT = V$TFT;
      END

      -- Рекомендуемая
      IF(V$FT = 450) THEN V$FTSCALE = 2;
      ELSE IF(V$FT = 499) THEN V$FTSCALE = 4;
      ELSE IF(V$FT = 599) THEN V$FTSCALE = 20;
      ELSE V$FTSCALE = 1;

      IF(V$N >= 3) THEN VAL = VAL || '<td>' || CAST(V$FTSCALE * V$SUM / V$N AS NUMERIC(18, 2)) || '</td>';
      ELSE VAL = VAL || '<td>-</td>';

      VAL = VAL || '<td>' || S || '</td>';

      SELECT COUNT(DISTINCT M.MARK_ID)
      FROM CJ2_MARK M
      JOIN CJ2_CONTROL C ON C.DATE_DEL IS NULL AND C.CONTROL_ID = M.CONTROL_ID AND C.CONTROL_TYPE_ID = 0
      JOIN CJ2_JOURNAL_LESSONS L ON L.DATE_DEL IS NULL AND L.OBJ_ID = C.LESSON_ID AND (L.LESSON_DATE BETWEEN :I$DATE_FROM AND :I$DATE_TO)
        AND L.IS_COMPLETED = 1
      JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.OBJ_ID = L.CJ_ID AND J.SUBJECT_ID = :V$OBJ_ID AND J.JOURNAL_TYPE = 0
      WHERE M.DATE_DEL IS NULL AND M.MARK_TYPE_ID BETWEEN 91 AND 98 AND M.STUDENT_ID = :I$OBJ_ID
      INTO :N;
      VAL = VAL || '<td>' || N || '</td>';

      VAL = VAL || '</tr>';
      SUSPEND;
    END
  END
  ELSE
  BEGIN
    -- По группе
    FOR
      SELECT DISTINCT MV.PERSON_ID, P.NAME_FULL-- C.CAPTION
      FROM PERSON_MOVEMENTS MV
      JOIN UT_PERSON_DESC(MV.PERSON_ID, :I$ZONE, 1) P ON 1 = 1   --redmine #1060
      LEFT JOIN OBJECT_CAPTION_GET(MV.PERSON_ID, 23) C ON 1 = 1
      WHERE MV.GROUP_ID = :I$OBJ_ID AND MV.DATE_DEL IS NULL AND MV.DATE_IN <= :I$DATE_TO AND (MV.DATE_OUT IS NULL OR MV.DATE_OUT >= :I$DATE_FROM)
      ORDER BY C.SORT_ORDER, P.NAME_FULL --C.CAPTION
      INTO :V$OBJ_ID, :S
    DO
    BEGIN
      VAL = '<tr class="v" data-id="' || V$OBJ_ID || '">';
      VAL = VAL || '<td><div class="target student" data-target="' || V$OBJ_ID || '">' || S || '</div></td>';
      SUSPEND;

      V$SUM = 0;
      V$N = 0;
      V$PREV_CJ = -1;
      L = 0;

      FOR
        SELECT C.CONTROL_COST, MT.MARK_COST, MT.MARK_SHORTNAME, MT.MARK_TYPE_ID, CS.CAPTION, J.OBJ_ID, L.LESSON_DATE, C.CONTROL_ID
        FROM PERSON_MOVEMENTS MV
        JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.GRADE_ID = MV.GROUP_ID AND J.JOURNAL_TYPE = 0
        JOIN CJ2_JOURNAL_LESSONS L ON L.DATE_DEL IS NULL AND L.CJ_ID = J.OBJ_ID AND (L.LESSON_DATE BETWEEN :I$DATE_FROM AND :I$DATE_TO)
          AND L.IS_COMPLETED = 1
        JOIN CJ2_CONTROL C ON C.DATE_DEL IS NULL AND C.LESSON_ID = L.OBJ_ID AND C.CONTROL_TYPE_ID <> 0 AND C.CONTROL_TYPE_ID <> 30000
        JOIN CJ2_MARK M ON M.DATE_DEL IS NULL AND M.CONTROL_ID = C.CONTROL_ID AND M.STUDENT_ID = MV.PERSON_ID
        JOIN CJ2_MARK_TYPE MT ON MT.MARK_TYPE_ID = M.MARK_TYPE_ID AND MT.PARENT_ID <> 200 -- скрываем да/нет
        LEFT JOIN OBJECT_CAPTION_GET(J.SUBJECT_ID) CS ON 1 = 1
        WHERE MV.PERSON_ID = :V$OBJ_ID AND MV.DATE_DEL IS NULL AND MV.DATE_IN <= :I$DATE_TO AND (MV.DATE_OUT IS NULL OR MV.DATE_OUT >= :I$DATE_FROM)
        UNION
        SELECT NULL, NULL, NULL, NULL, CS.CAPTION, J.OBJ_ID, F.FINAL_DATE, NULL
        FROM PERSON_MOVEMENTS MV
        JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.GRADE_ID = MV.GROUP_ID AND J.JOURNAL_TYPE = 0
        JOIN CJ2_JOURNAL_FINALS F ON F.DATE_DEL IS NULL AND F.CJ_ID = J.OBJ_ID AND (F.FINAL_DATE BETWEEN :I$DATE_FROM AND :I$DATE_TO)
          --AND F.IS_COMPLETED = 1
        LEFT JOIN OBJECT_CAPTION_GET(J.SUBJECT_ID) CS ON 1 = 1
        WHERE MV.PERSON_ID = :V$OBJ_ID AND MV.DATE_DEL IS NULL AND MV.DATE_IN <= :I$DATE_TO AND (MV.DATE_OUT IS NULL OR MV.DATE_OUT >= :I$DATE_FROM)
        ORDER BY 5, 7, 8
        INTO :V$CC, :V$MARK, :V$S1, :V$MARK_ID, :S, :V$CJ_ID, :V$LESSON_DATE, :V$CC_ID
      DO
      BEGIN
        IF(V$PREV_CJ <> V$CJ_ID) THEN
        BEGIN
          -- Счетчик сколько у нас было выдано журналов
          L = L + 1;
          -- Закрываем предыдущий журнал и открываем строку нового
          IF(L > 1) THEN
          BEGIN
            -- Ячейка отметок
            VAL = '</td>';
            -- Средняя
            IF(V$N >= 3) THEN VAL = VAL || '<td>' || CAST(V$SUM / V$N AS NUMERIC(18, 2)) || '</td>';
            ELSE VAL = VAL || '<td>-</td>';
            -- Итоговая
            VAL = VAL || '<td>';
            FOR
              SELECT T.VAL, MT.MARK_SHORTNAME, MT.MARK_COST, F.MARK_SYSTEM_ID
              FROM CJ2_JOURNAL J
              JOIN CJ2_JOURNAL_FINALS F ON F.DATE_DEL IS NULL AND F.CJ_ID = J.OBJ_ID AND (F.FINAL_DATE BETWEEN :I$DATE_FROM AND :V$DATE_TO2)
                -- AND L.IS_COMPLETED = 1
              JOIN CJ2_MARK M ON M.DATE_DEL IS NULL AND M.FINAL_ID = F.OBJ_ID AND M.STUDENT_ID = :V$OBJ_ID
              JOIN CJ2_MARK_TYPE MT ON MT.MARK_TYPE_ID = M.MARK_TYPE_ID AND MT.PARENT_ID <> 200 -- скрываем да/нет
              LEFT JOIN LISTVAL_TEXT(F.FINAL_TYPE) T ON 1 = 1
              WHERE J.DATE_DEL IS NULL AND J.OBJ_ID = :V$PREV_CJ
              ORDER BY F.FINAL_TYPE
              INTO :V$S2, :V$S3, :V$MC, :V$TFT
            DO
            BEGIN
              IF(V$MC > 0 AND V$MC < 1.5) THEN V$C = ' pink'; -- 1
              ELSE IF(V$MC < 2.5) THEN V$C = ' red'; -- незачет или 2
              ELSE IF(V$MC < 3.5) THEN V$C = ' orange'; -- 3
              ELSE IF(V$MC < 4.5) THEN V$C = ' violet'; -- 4
              ELSE IF(V$MC >= 4.5 AND V$MC <= 5) THEN V$C = ' blue'; -- зачет или 5
              ELSE V$C = '';
              VAL = VAL || '<div class="ui circular label dl' || V$C || ' data-period="' || V$S2 || '" title="' || V$S2 || '">' || V$S3 || '</div>';
              V$FT = V$TFT;
            END
            VAL = VAL || '</td>';
            -- Пропуски
            N = 0;
            SELECT COUNT(*)
            FROM CJ2_JOURNAL J
            JOIN CJ2_JOURNAL_LESSONS L ON L.DATE_DEL IS NULL AND L.CJ_ID = J.OBJ_ID AND (L.LESSON_DATE BETWEEN :I$DATE_FROM AND :I$DATE_TO)
              AND L.IS_COMPLETED = 1
            JOIN CJ2_CONTROL C ON C.DATE_DEL IS NULL AND C.LESSON_ID = L.OBJ_ID AND C.CONTROL_TYPE_ID = 0
            JOIN CJ2_MARK M ON M.DATE_DEL IS NULL AND M.CONTROL_ID = C.CONTROL_ID AND M.MARK_TYPE_ID BETWEEN 91 AND 98 AND M.STUDENT_ID = :V$OBJ_ID
            WHERE J.DATE_DEL IS NULL AND J.OBJ_ID = :V$PREV_CJ
            INTO :N;
            VAL = VAL || '<td>' || N || '</td>';
            VAL = VAL || '</tr>';
            VAL = VAL || '<tr class="v" data-id="' || V$OBJ_ID || '"><td></td>';
            SUSPEND;

            V$SUM = 0;
            V$N = 0;
          END

          -- Название предмета, и открываем блок для отметок
          VAL = '<td>' || REPLACE(S, '"', '&quot;') || '</td><td>';
          SUSPEND;
        END

        -- Оценки может не быть, если в журнале есть только итоговые - этот блок будет пропущен
        IF(V$MARK IS NOT NULL) THEN
        BEGIN
          IF(V$MARK = 1) THEN V$C = ' pink'; -- 1
          ELSE IF(V$MARK = 2) THEN V$C = ' red'; -- незачет или 2
          ELSE IF(V$MARK = 3) THEN V$C = ' orange'; -- 3
          ELSE IF(V$MARK = 4) THEN V$C = ' violet'; -- 4
          ELSE IF(V$MARK = 5) THEN V$C = ' blue'; -- зачет или 5
          ELSE V$C = '';

          VAL = '<div class="ui circular label target journal dl' || V$C || '" data-target="' || V$CJ_ID || '" data-subject="' || REPLACE(S, '"', '&quot;') || '">' || V$S1 || '</div>';
          SUSPEND;
          V$SUM = V$SUM + V$MARK * V$CC;
          V$N = V$N + V$CC;
        END
        V$PREV_CJ = V$CJ_ID;
      END

      -- Закрываем строку предмета, если она вообще была
      VAL = '</td>';

      IF(V$PREV_CJ IS NULL OR V$PREV_CJ < 0) THEN
      BEGIN
        VAL = VAL || '<td></td>';
        VAL = VAL || '<td></td>';
        VAL = VAL || '<td></td>';
        VAL = VAL || '<td></td>';
        VAL = VAL || '<td></td>';
      END
      ELSE
      BEGIN
        IF(V$N >= 3) THEN VAL = VAL || '<td>' || CAST(V$SUM / V$N AS NUMERIC(18, 2)) || '</td>';
        ELSE VAL = VAL || '<td>-</td>';

        -- Итоговая
        VAL = VAL || '<td>';
        FOR
          SELECT T.VAL, MT.MARK_SHORTNAME, MT.MARK_COST
          FROM CJ2_JOURNAL J
          JOIN CJ2_JOURNAL_FINALS F ON F.DATE_DEL IS NULL AND F.CJ_ID = J.OBJ_ID AND (F.FINAL_DATE BETWEEN :I$DATE_FROM AND :V$DATE_TO2)
            -- AND L.IS_COMPLETED = 1
          JOIN CJ2_MARK M ON M.DATE_DEL IS NULL AND M.FINAL_ID = F.OBJ_ID AND M.STUDENT_ID = :V$OBJ_ID
          JOIN CJ2_MARK_TYPE MT ON MT.MARK_TYPE_ID = M.MARK_TYPE_ID AND MT.PARENT_ID <> 200 -- скрываем да/нет
          LEFT JOIN LISTVAL_TEXT(F.FINAL_TYPE) T ON 1 = 1
          WHERE J.DATE_DEL IS NULL AND J.OBJ_ID = :V$PREV_CJ
          ORDER BY F.FINAL_TYPE
          INTO :V$S2, :V$S3, :V$MC
        DO
        BEGIN
          IF(V$MC > 0 AND V$MC < 1.5) THEN V$C = ' pink'; -- 1
          ELSE IF(V$MC < 2.5) THEN V$C = ' red'; -- незачет или 2
          ELSE IF(V$MC < 3.5) THEN V$C = ' orange'; -- 3
          ELSE IF(V$MC < 4.5) THEN V$C = ' violet'; -- 4
          ELSE IF(V$MC >= 4.5 AND V$MC <= 5) THEN V$C = ' blue'; -- зачет или 5
          ELSE V$C = '';
          VAL = VAL || '<div class="ui circular label dl' || V$C || ' data-period="' || V$S2 || '" title="' || V$S2 || '">' || V$S3 || '</div>';
        END
        VAL = VAL || '</td>';

        N = 0;
        SELECT COUNT(DISTINCT M.MARK_ID)
        FROM CJ2_MARK M
        JOIN CJ2_CONTROL C ON C.DATE_DEL IS NULL AND C.CONTROL_ID = M.CONTROL_ID AND C.CONTROL_TYPE_ID = 0
        JOIN CJ2_JOURNAL_LESSONS L ON L.DATE_DEL IS NULL AND L.OBJ_ID = C.LESSON_ID AND (L.LESSON_DATE BETWEEN :I$DATE_FROM AND :I$DATE_TO)
          AND L.IS_COMPLETED = 1
        JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.OBJ_ID = L.CJ_ID AND J.JOURNAL_TYPE = 0 AND J.OBJ_ID = :V$PREV_CJ
        WHERE M.DATE_DEL IS NULL AND M.MARK_TYPE_ID BETWEEN 91 AND 98 AND M.STUDENT_ID = :V$OBJ_ID
        INTO :N;
        VAL = VAL || '<td>' || N || '</td>';
      END

      VAL = VAL || '</tr>';
      SUSPEND;
    END
  END

  VAL = '</table></body></html>';
  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_RESOURCES_LIST (
    I$CJ_ID BIGINT,
    I$LESSON_ID BIGINT,
    I$LESSON_DATE DATE,
    I$LESSON_NUM INTEGER,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
declare variable V$TYPE_ID bigint;
declare variable V$OBJ_ID bigint;
declare variable V$YEAR_ID bigint;
declare variable V$ROOM_ID bigint;
declare variable V$DATE_NUM integer;
declare variable S varchar(1000);
declare variable N integer;
begin

  -- Сортировка:
  -- сначала относящиеся к данному конкретному помещению, затем все остальное
  -- !!! проверка пока стоит по номеру урока, а не по времени

  -- Получаем id помещения для данного журнала
  SELECT J.YEAR_ID
  FROM CJ2_JOURNAL J
  WHERE J.OBJ_ID = :I$CJ_ID
  INTO :V$YEAR_ID;

  V$DATE_NUM = EXTRACT(MONTH FROM I$LESSON_DATE) * 100 + EXTRACT(DAY FROM I$LESSON_DATE);

  SELECT FIRST 1 M.ROOM_ID
  FROM SCHEDULE_ITEMS M
  JOIN LINKS LP68 ON LP68.OBJ_ID = M.SCHEDULE_ID AND LP68.PARENT_TYPE_ID = 68 AND LP68.DATE_DEL IS NULL
  JOIN VALL V37 ON V37.OBJ_ID = LP68.OBJ_ID AND V37.PARAM_ID = 37 AND V37.IS_DEL = 0 AND V37.LISTVAL_ID = :V$YEAR_ID
  WHERE M.DATE_DEL IS NULL AND M.CJ_ID = :I$CJ_ID AND M.ROOM_ID IS NOT NULL AND M.WEEKDAY_NUM = :V$DATE_NUM
  ORDER BY IIF(M.LESSON_NUM = :I$LESSON_NUM, 0, 1)
  INTO :V$ROOM_ID;

    -- Ищем по шаблону помещение, где больше всего занятий
  IF(V$ROOM_ID IS NULL) THEN
  SELECT FIRST 1 M.ROOM_ID, COUNT(*)
  FROM SCHEDULE_ITEMS M
  JOIN LINKS LP3 ON LP3.OBJ_ID = M.SCHEDULE_ID AND LP3.PARENT_TYPE_ID = 3 AND LP3.DATE_DEL IS NULL
  JOIN VALL V1341 ON V1341.OBJ_ID = LP3.OBJ_ID AND V1341.PARAM_ID = 1341 AND V1341.IS_DEL = 0 AND V1341.LISTVAL_ID = 2
  LEFT JOIN VALD V3120 ON V3120.OBJ_ID = LP3.OBJ_ID AND V3120.PARAM_ID = 3120 AND V3120.IS_DEL = 0
  LEFT JOIN VALD V3121 ON V3121.OBJ_ID = LP3.OBJ_ID AND V3121.PARAM_ID = 3121 AND V3121.IS_DEL = 0
  WHERE M.DATE_DEL IS NULL AND M.CJ_ID = :I$CJ_ID AND M.ROOM_ID IS NOT NULL
    AND (V3120.VAL <= :I$LESSON_DATE OR V3120.VAL IS NULL)
    AND (V3121.VAL >= :I$LESSON_DATE OR V3121.VAL IS NULL)
  GROUP BY 1
  ORDER BY 2 DESC
  INTO :V$ROOM_ID, :N;

  TAG_NAME = 'items::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L114.OBJ_ID, V674.SVAL || COALESCE(' ' || V3148.SVAL, ' ' || V673.SVAL, ''), V626.LISTVAL_ID
    FROM LINKS L2
    JOIN LINKS L23 ON L23.PARENT_ID = L2.OBJ_ID AND L23.OBJ_TYPE_ID = 23 AND L23.DATE_DEL IS NULL
    JOIN LINKS L95 ON L95.PARENT_ID = L23.OBJ_ID AND L95.OBJ_TYPE_ID = 95 AND L95.DATE_DEL IS NULL
    JOIN VALL V626 ON V626.OBJ_ID = L95.OBJ_ID AND V626.PARAM_ID = 626 AND V626.IS_DEL = 0
    JOIN LINKS L114 ON L114.PARENT_ID = L95.OBJ_ID AND L114.OBJ_TYPE_ID = 114 AND L114.DATE_DEL IS NULL
    JOIN VALS V674 ON V674.OBJ_ID = L114.OBJ_ID AND V674.PARAM_ID = 674 AND V674.IS_DEL = 0
    LEFT JOIN VALS V3148 ON V3148.OBJ_ID = L114.OBJ_ID AND V3148.PARAM_ID = 3148 AND V3148.IS_DEL = 0
    LEFT JOIN VALS V673 ON V673.OBJ_ID = L114.OBJ_ID AND V673.PARAM_ID = 673 AND V673.IS_DEL = 0
    LEFT JOIN VALR V679 ON V679.OBJ_ID = L114.OBJ_ID AND V679.PARAM_ID = 679 AND V679.IS_DEL = 0
    -- Проверку использования в своем журнале делаем на фронте
    LEFT JOIN CJ2_LESSON_RES LR ON LR.DATE_DEL IS NULL AND LR.RES_ID = L114.OBJ_ID
    LEFT JOIN CJ2_JOURNAL_LESSONS L ON L.DATE_DEL IS NULL AND L.OBJ_ID = LR.LESSON_ID AND (L.OBJ_ID <> :I$LESSON_ID OR :I$LESSON_ID IS NULL)
      AND (L.LESSON_DATE <> :I$LESSON_DATE OR (L.LESSON_DATE = :I$LESSON_DATE AND L.LESSON_NUM <> :I$LESSON_NUM))
    LEFT JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.OBJ_ID = L.CJ_ID AND J.OBJ_ID <> :I$CJ_ID
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND J.OBJ_ID IS NULL
    -- Выбор только оборудования в этом кабинете, или МТР не привязанного к помещениям
      AND (V679.VAL IS NULL OR :V$ROOM_ID IS NULL OR V679.VAL = :V$ROOM_ID)
    ORDER BY 2
    INTO :V$OBJ_ID, :S, :V$TYPE_ID
  DO
  BEGIN
    TAG_NAME = 'items:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'items:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'items:r:type_id';
    VAL = V$TYPE_ID;
    SUSPEND;
    TAG_NAME = 'items:r:name';
    VAL = S;
    SUSPEND;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_SCHEDULE_GEN
AS
DECLARE VARIABLE V$YEAR_ID BIGINT;
DECLARE VARIABLE Y INTEGER;
DECLARE VARIABLE V$PREV_PERIOD BIGINT;
DECLARE VARIABLE V$CJ_ID BIGINT;
DECLARE VARIABLE V$PERIOD_ID BIGINT;
DECLARE VARIABLE V$OU_ID BIGINT;
DECLARE VARIABLE V$KUG_ID BIGINT;
DECLARE VARIABLE V$DSTART DATE;
DECLARE VARIABLE V$DEND DATE;
DECLARE VARIABLE V$D1S DATE;
DECLARE VARIABLE V$D1E DATE;
DECLARE VARIABLE V$D2S DATE;
DECLARE VARIABLE V$D2E DATE;
DECLARE VARIABLE V$D3S DATE;
DECLARE VARIABLE V$D3E DATE;
DECLARE VARIABLE V$D4S DATE;
DECLARE VARIABLE V$D4E DATE;
DECLARE VARIABLE V$D5S DATE;
DECLARE VARIABLE V$D5E DATE;
DECLARE VARIABLE D1 DATE;
DECLARE VARIABLE D2 DATE;
DECLARE VARIABLE V$DFROM DATE;
DECLARE VARIABLE V$NFROM INTEGER;
DECLARE VARIABLE V$DTO DATE;
DECLARE VARIABLE T$DATE DATE;
DECLARE VARIABLE T$NUM INTEGER;
DECLARE VARIABLE V$IDX INTEGER;
DECLARE VARIABLE N INTEGER;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$DT TIMESTAMP;
DECLARE VARIABLE V$SEQ INTEGER;
DECLARE VARIABLE T$TIME TIME;
DECLARE VARIABLE T TIME;
begin

  -- Генерация выполняется на 2 недели вперед от текущей даты
  SELECT L2.OBJ_ID, V1236.LISTVAL_ID, LV.COST
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$OU_ID, :V$YEAR_ID, :Y;

  IF(Y IS NULL OR (Y <> EXTRACT(YEAR FROM CURRENT_DATE) AND Y <> EXTRACT(YEAR FROM CURRENT_DATE) - 1)) THEN
    EXCEPTION DATA_ERROR 'Учебный год не задан или не соответствует текущему календарному году';

  -- Обязательно нужен КУГ
  SELECT FIRST 1 L481.OBJ_ID
  FROM LINKS L481
  JOIN VALL V3389 ON V3389.OBJ_ID = L481.OBJ_ID AND V3389.PARAM_ID = 3389 AND V3389.IS_DEL = 0 AND V3389.LISTVAL_ID = :V$YEAR_ID
  JOIN VALL V3390 ON V3390.OBJ_ID = L481.OBJ_ID AND V3390.PARAM_ID = 3390 AND V3390.IS_DEL = 0 AND V3390.LISTVAL_ID = 11715
  WHERE L481.PARENT_ID = :V$OU_ID AND L481.OBJ_TYPE_ID = 481 AND L481.DATE_DEL IS NULL
  INTO :V$KUG_ID;

  IF(V$KUG_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не создан или не утвержден КУГ на текущий учебный год';

  -- Сразу проверяем, что все периоды в КУГ корректно сконфигурированы, иначе будет бесполезная трата id
  T$NUM = 0;
  FOR
    SELECT L151.OBJ_ID
    FROM LINKS L151
    WHERE L151.PARENT_ID = :V$KUG_ID AND L151.OBJ_TYPE_ID = 151 AND L151.DATE_DEL IS NULL
    INTO :V$PERIOD_ID
  DO
  BEGIN
    D1 = NULL;
    N = 0;
    FOR
      SELECT V1169.VAL, V1174.VAL
      FROM LINKS L154
      LEFT JOIN VALD V1169 ON V1169.OBJ_ID = L154.OBJ_ID AND V1169.PARAM_ID = 1169 AND V1169.IS_DEL = 0
      LEFT JOIN VALD V1174 ON V1174.OBJ_ID = L154.OBJ_ID AND V1174.PARAM_ID = 1174 AND V1174.IS_DEL = 0
      WHERE L154.PARENT_ID = :V$PERIOD_ID AND L154.OBJ_TYPE_ID = 154 AND L154.DATE_DEL IS NULL
      ORDER BY 1
      INTO :V$DSTART, :V$DEND
    DO
    BEGIN
      IF(V$DSTART IS NULL) THEN EXCEPTION DATA_ERROR 'В одном из ученых периодов не указан дата начала';
      IF(V$DEND IS NULL) THEN EXCEPTION DATA_ERROR 'В одном из ученых периодов не указан дата окончания';
      IF(V$DSTART >= V$DEND OR V$DSTART <= D1) THEN EXCEPTION DATA_ERROR 'В одном из ученых периодов нарушена хронология дат';
      D1 = V$DEND;
      N = N + 1;
    END
    IF(N = 0) THEN EXCEPTION DATA_ERROR 'В одном из учебных периодов не внесены сами периоды';
    D1 = NULL;
    N = 0;
    FOR
      SELECT V3263.VAL, V3264.VAL
      FROM LINKS L450
      LEFT JOIN VALD V3263 ON V3263.OBJ_ID = L450.OBJ_ID AND V3263.PARAM_ID = 3263 AND V3263.IS_DEL = 0
      LEFT JOIN VALD V3264 ON V3264.OBJ_ID = L450.OBJ_ID AND V3264.PARAM_ID = 3264 AND V3264.IS_DEL = 0
      WHERE L450.PARENT_ID = :V$PERIOD_ID AND L450.OBJ_TYPE_ID = 450 AND L450.DATE_DEL IS NULL
      ORDER BY 1
      INTO :V$DSTART, :V$DEND
    DO
    BEGIN
      IF(V$DSTART IS NULL) THEN EXCEPTION DATA_ERROR 'В одном из периодов каникул не указан дата начала';
      IF(V$DEND IS NULL) THEN EXCEPTION DATA_ERROR 'В одном из периодов каникул не указан дата окончания';
      IF(V$DSTART >= V$DEND OR V$DSTART <= D1) THEN EXCEPTION DATA_ERROR 'В одном из периодов каникул нарушена хронология дат';
      D1 = V$DEND;
      N = N + 1;
    END
    T$NUM = T$NUM + 1;
  END
  IF(T$NUM = 0) THEN EXCEPTION DATA_ERROR 'В КУГ не задано ни одной сетки учебных периодов';

  -- Идем по учебным периодам, чтобы кэшировать данные
  V$PREV_PERIOD = 0;
  FOR
    SELECT J.OBJ_ID, J.PERIOD_ID
    FROM CJ2_JOURNAL J
    WHERE J.DATE_DEL IS NULL AND J.JOURNAL_TYPE IN (0, 1) AND J.YEAR_ID = :V$YEAR_ID AND J.PERIOD_ID IS NOT NULL
    ORDER BY J.PERIOD_ID
    INTO :V$CJ_ID, :V$PERIOD_ID
  DO
  BEGIN
    IF(V$PERIOD_ID <> V$PREV_PERIOD) THEN
    BEGIN
      -- Из учебных периодов достаем даты начала и конца занятий, остальное из каникул
      V$PREV_PERIOD = V$PERIOD_ID;
      V$DSTART = NULL;
      V$DEND = NULL;
      V$D1S = NULL;
      V$D1E = NULL;
      V$D2S = NULL;
      V$D2E = NULL;
      V$D3S = NULL;
      V$D3E = NULL;
      V$D4S = NULL;
      V$D4E = NULL;
      V$D5S = NULL;
      V$D5E = NULL;
      SELECT MIN(V1169.VAL), MAX(V1174.VAL)
      FROM LINKS L154
      JOIN VALD V1169 ON V1169.OBJ_ID = L154.OBJ_ID AND V1169.PARAM_ID = 1169 AND V1169.IS_DEL = 0
      JOIN VALD V1174 ON V1174.OBJ_ID = L154.OBJ_ID AND V1174.PARAM_ID = 1174 AND V1174.IS_DEL = 0
      WHERE L154.PARENT_ID = :V$PERIOD_ID AND L154.OBJ_TYPE_ID = 154 AND L154.DATE_DEL IS NULL
      INTO :V$DSTART, :V$DEND;
      IF(V$DSTART IS NULL) THEN EXCEPTION DATA_ERROR 'Учебные периоды в КУГ не полностью настроены';

      -- Каникулы смотрим только попадающие в диапазон учебных периодов
      -- максимально 5 каникул
      FOR
        SELECT V3263.VAL, V3264.VAL
        FROM LINKS L450
        JOIN VALD V3263 ON V3263.OBJ_ID = L450.OBJ_ID AND V3263.PARAM_ID = 3263 AND V3263.IS_DEL = 0 AND V3263.VAL >= :V$DSTART AND V3263.VAL <= :V$DEND
        JOIN VALD V3264 ON V3264.OBJ_ID = L450.OBJ_ID AND V3264.PARAM_ID = 3264 AND V3264.IS_DEL = 0
        WHERE L450.PARENT_ID = :V$PERIOD_ID AND L450.OBJ_TYPE_ID = 450 AND L450.DATE_DEL IS NULL
        ORDER BY 1
        INTO :D1, :D2
      DO
      BEGIN
        IF(V$D1S IS NULL) THEN BEGIN
          V$D1S = D1;
          V$D1E = D2;
        END
        ELSE IF(V$D2S IS NULL) THEN BEGIN
          V$D2S = D1;
          V$D2E = D2;
        END
        ELSE IF(V$D3S IS NULL) THEN BEGIN
          V$D3S = D1;
          V$D3E = D2;
        END
        ELSE IF(V$D4S IS NULL) THEN BEGIN
          V$D4S = D1;
          V$D4E = D2;
        END
        ELSE IF(V$D5S IS NULL) THEN BEGIN
          V$D5S = D1;
          V$D5E = D2;
        END
      END
    END

    -- Смотрим начиная с какой даты надо сформировать или переформировать уроки
    -- начальная дата = дата последнего реального урока, уже связанного с КЖ
    V$DFROM = NULL;
    V$NFROM = NULL;
    SELECT FIRST 1 M.LESSON_DATE, M.LESSON_NUM, M.SEQ_INDEX
    FROM CJ2_MS_LESSONS M
    JOIN CJ2_JOURNAL_LESSONS L ON L.DATE_DEL IS NULL AND L.CJ_ID = M.CJ_ID AND L.MS_ID = M.OBJ_ID
    WHERE M.CJ_ID = :V$CJ_ID AND M.DATE_DEL IS NULL
    ORDER BY 3
    INTO :V$DFROM, :V$NFROM, :V$IDX;
    -- Если уроков вообще нет, то ставим начало года
    IF(V$DFROM IS NULL) THEN
    BEGIN
      V$DFROM = V$DSTART;
      V$NFROM = 0;
      V$IDX = 0;
    END

    -- Дата конца обязательно +1 день, чтобы зачесть все номера уроков в последний день
    V$DTO = MINVALUE(DATEADD(15 DAY TO CURRENT_DATE), DATEADD(1 DAY TO V$DEND));
    WHILE(V$DFROM IS NOT NULL AND V$DFROM < V$DTO) DO
    BEGIN
      T$DATE = NULL;
      T$NUM = NULL;
      -- Все переносы рабочих дней, а также внеочередные выходные будут уже учтены внутри
      -- !!! надо сортировать не по lesson_num, а добавить поле в единицах времени
      SELECT FIRST 1 S.LESSON_DATE, S.LESSON_NUM, S.LESSON_TIME
      FROM CJ2_SCHEDULE_STREAM(:V$CJ_ID, :V$DFROM, :V$DTO) S
      WHERE S.LESSON_DATE > :V$DFROM OR (S.LESSON_DATE = :V$DFROM AND S.LESSON_NUM > :V$NFROM)
      ORDER BY 1, 3
      INTO :T$DATE, :T$NUM, :T$TIME;

      IF(T$TIME IS NULL) THEN EXCEPTION DATA_ERROR 'Критическая ошибка, повреждение в структуре расписания из-за некорректных действий';

      IF(T$DATE IS NULL) THEN
      BEGIN
        -- Следующего урока нет вовсе, надо подчистить хвосты
        -- видимо учебный год кончился
        -- сверяться с JOURNAL_LESSONS не нужно, т.к. мы уже после последнего связанного урока
        UPDATE CJ2_MS_LESSONS
        SET DATE_DEL = CURRENT_TIMESTAMP
        WHERE DATE_DEL IS NULL AND CJ_ID = :V$CJ_ID AND SEQ_INDEX > :V$IDX;
      END
      -- Периоды не смотрим, они должны быть уже учтены в CJ2_SCHEDULE_STREAM
      /*ELSE IF((T$DATE >= V$D1S AND T$DATE <= V$D1E) OR (T$DATE >= V$D2S AND T$DATE <= V$D2E) OR (T$DATE >= V$D3S AND T$DATE <= V$D3E) OR
        (T$DATE >= V$D4S AND T$DATE <= V$D4E) OR (T$DATE >= V$D5S AND T$DATE <= V$D5E)) THEN
      BEGIN
        -- Следующий урок есть, но попадает на каникулы - подчищаем хвосты
        IF(T$DATE >= V$D5S) THEN D1 = V$D5E;
        ELSE IF(T$DATE >= V$D4S) THEN D1 = V$D4E;
        ELSE IF(T$DATE >= V$D3S) THEN D1 = V$D3E;
        ELSE IF(T$DATE >= V$D2S) THEN D1 = V$D2E;
        ELSE D1 = V$D1E;

        -- Дату сразу переставляем на конец каникул
        V$DFROM = D1;
        T$NUM = 9999;
      END
      */
      ELSE
      BEGIN
        -- Обычный следующий урок
        -- По идее дырок в нумерации быть не должно, и seq_index должен быть равен IDX + 1
        V$OBJ_ID = NULL;
        SELECT FIRST 1 L.OBJ_ID, L.DATE_DEL, L.LESSON_DATE, L.LESSON_NUM, L.SEQ_INDEX, L.LESSON_TIME
        FROM CJ2_MS_LESSONS L
        WHERE L.CJ_ID = :V$CJ_ID AND L.SEQ_INDEX > :V$IDX
        ORDER BY L.SEQ_INDEX
        INTO :V$OBJ_ID, :V$DT, :D1, :N, :V$SEQ, :T;

        V$IDX = V$IDX + 1;
        IF(V$OBJ_ID IS NULL) THEN
        BEGIN
          -- Добавляем
          INSERT INTO CJ2_MS_LESSONS
          (CJ_ID, LESSON_DATE, LESSON_NUM, LESSON_TIME, SEQ_INDEX)
          VALUES (:V$CJ_ID, :T$DATE, :T$NUM, :T$TIME, :V$IDX);
        END
        ELSE IF(V$SEQ <> V$IDX OR V$DT IS NOT NULL OR D1 <> T$DATE OR N <> T$NUM OR COALESCE(T, '00:00') <> T$TIME) THEN
        BEGIN
          -- Обновляем (восстанавливаем из удаленных, либо сдвигаем нумерацию, либо переставляем дату и номер)
          UPDATE CJ2_MS_LESSONS
          SET SEQ_INDEX = :V$IDX, LESSON_DATE = :T$DATE, LESSON_NUM = :T$NUM, LESSON_TIME = :T$TIME, DATE_DEL = NULL
          WHERE OBJ_ID = :V$OBJ_ID;
        END
      END

      V$DFROM = T$DATE;
      V$NFROM = T$NUM;
    END

    -- Все что вдруг вылезло за пределы интервала, подчищаем
    UPDATE CJ2_MS_LESSONS
    SET DATE_DEL = CURRENT_TIMESTAMP
    WHERE DATE_DEL IS NULL AND CJ_ID = :V$CJ_ID AND SEQ_INDEX > :V$IDX;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_SCHEDULE_STREAM (
    I$CJ_ID BIGINT,
    I$DATE DATE,
    I$TO_DATE DATE = NULL)
RETURNS (
    LESSON_DATE DATE,
    LESSON_NUM INTEGER,
    LESSON_TIME TIME)
AS
DECLARE VARIABLE V$YEAR_ID BIGINT;
DECLARE VARIABLE V$DAY1 INTEGER;
DECLARE VARIABLE V$DAY2 INTEGER;
DECLARE VARIABLE V$YEAR INTEGER;
DECLARE VARIABLE N INTEGER;
DECLARE VARIABLE M INTEGER;
DECLARE VARIABLE D INTEGER;
DECLARE VARIABLE V$BASEDATE DATE;
DECLARE VARIABLE V$DATE DATE;
DECLARE VARIABLE W SMALLINT;
DECLARE VARIABLE V$SKIP SMALLINT;
DECLARE VARIABLE V$PERIOD_ID BIGINT;
DECLARE VARIABLE V$SI BIGINT;
begin

  -- TODO: выдавать не конечное количество записей, а до указанной даты TO_DATE

  SELECT FIRST 1 V1236.LISTVAL_ID, LV.COST
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$YEAR_ID, :V$YEAR;

  SELECT J.PERIOD_ID, J.STAGE_INDEX
  FROM CJ2_JOURNAL J
  WHERE J.OBJ_ID = :I$CJ_ID
  INTO :V$PERIOD_ID, :V$SI;

  -- Замещения на месяц вперед
  FOR
    SELECT RP.REPL_DATE, RP.LESSON_NUM, RP.LESSON_TIME
    FROM CJ2_REPL_PROCESS RP
    WHERE RP.DATE_DEL IS NULL AND (RP.REPL_CJ_ID = :I$CJ_ID OR (RP.REPL_CJ_ID IS NULL AND RP.CJ_ID = :I$CJ_ID)) AND RP.REPL_DATE >= :I$DATE AND RP.REPL_DATE <= DATEADD(1 MONTH TO :I$DATE)
    INTO :LESSON_DATE, :LESSON_NUM, :LESSON_TIME
  DO
  BEGIN
    SUSPEND;
  END

  -- Внесеточные или переставленные уроки из ленты также на месяц вперед
  -- Если у нас декабрь, то окончание ставим в следующем году
  V$DAY1 = EXTRACT(MONTH FROM I$DATE) * 100 + EXTRACT(DAY FROM I$DATE);
  IF(V$DAY1 >= 1200) THEN
  BEGIN
    V$DAY2 = 200;
  END
  ELSE
  BEGIN
    V$DAY2 = V$DAY1 + 200;
  END

  FOR
    SELECT SI.WEEKDAY_NUM, SI.LESSON_NUM, SI.LESSON_TIME
    FROM SCHEDULE_ITEMS SI
    JOIN LINKS L3 ON L3.OBJ_ID = SI.SCHEDULE_ID AND L3.PARENT_TYPE_ID = 68 AND L3.DATE_DEL IS NULL
    JOIN VALL V37 ON V37.OBJ_ID = L3.OBJ_ID AND V37.PARAM_ID = 37 AND V37.IS_DEL = 0 AND V37.LISTVAL_ID = :V$YEAR_ID
    WHERE SI.DATE_DEL IS NULL AND SI.CJ_ID = :I$CJ_ID AND (
      -- Обычный порядок
      (:V$DAY1 <= :V$DAY2 AND SI.WEEKDAY_NUM >= :V$DAY1 AND SI.WEEKDAY_NUM <= :V$DAY2) OR
      -- Конец года, с заходом в следующий
      (:V$DAY1 > :V$DAY2 AND (SI.WEEKDAY_NUM >= :V$DAY1 OR SI.WEEKDAY_NUM <= :V$DAY2))
    )
    ORDER BY 1, 3, 2
    INTO :N, :LESSON_NUM, :LESSON_TIME
  DO
  BEGIN
    M = N / 100;
    D = N - M * 100;
    -- В начале учебного года у нас год = году начала УГ; при переходе границы  календарного года увеличиваем номер на 1
    IF(N > 900) THEN LESSON_DATE = D || '.' || M || '.' || V$YEAR; ELSE LESSON_DATE = D || '.' || M || '.' || (V$YEAR + 1);
    SUSPEND;
  END

  -- Записи шаблонов расписания, не перекрытые замещениями или перестановками
  -- выдаем данные на 4 недели вперед с указанной даты
  V$BASEDATE = I$DATE;
  N = EXTRACT(WEEKDAY FROM V$BASEDATE);
  IF(N = 0) THEN N = 6; ELSE N = N - 1;
  V$BASEDATE = DATEADD(-N DAY TO V$BASEDATE);
  W = 0;

  WHILE(W < 4) DO
  BEGIN
    V$DATE = DATEADD(W * 7 DAY TO V$BASEDATE);

    FOR
      SELECT SI.WEEKDAY_NUM, SI.LESSON_NUM, SI.LESSON_TIME
      FROM SCHEDULE_ITEMS SI
      JOIN LINKS L59 ON L59.OBJ_ID = SI.SCHEDULE_ID AND L59.PARENT_TYPE_ID = 3 AND L59.DATE_DEL IS NULL
      JOIN VALL V1341 ON V1341.OBJ_ID = L59.OBJ_ID AND V1341.PARAM_ID = 1341 AND V1341.IS_DEL = 0 AND V1341.LISTVAL_ID = 2
      LEFT JOIN VALD V3120 ON V3120.OBJ_ID = L59.OBJ_ID AND V3120.PARAM_ID = 3120 AND V3120.IS_DEL = 0
      LEFT JOIN VALD V3121 ON V3121.OBJ_ID = L59.OBJ_ID AND V3121.PARAM_ID = 3121 AND V3121.IS_DEL = 0
      WHERE SI.DATE_DEL IS NULL AND SI.CJ_ID = :I$CJ_ID
        AND (V3120.VAL IS NULL OR V3120.VAL < DATEADD(7 DAY TO :V$DATE)) AND (V3121.VAL IS NULL OR V3121.VAL >= :V$DATE)
      INTO :N, :LESSON_NUM, :LESSON_TIME
    DO
    BEGIN
      LESSON_DATE = DATEADD(N DAY TO V$DATE);
      V$SKIP = 0;
      IF(LESSON_DATE < I$DATE) THEN V$SKIP = 1;

      -- Попадает в число праздничных дней ?
      IF(EXISTS(SELECT 1 FROM SPECIAL_DATES WHERE DATEVAL = :LESSON_DATE AND DATETYPE = 0)) THEN V$SKIP = 1;

      -- Попадает в выходные ? Проверяем вообще все КУГ, независимо от статуса и года
      IF(V$SKIP = 0 AND EXISTS(
        SELECT FIRST 1 1
        FROM LINKS L481
        JOIN LINKS L486 ON L486.PARENT_ID = L481.OBJ_ID AND L486.OBJ_TYPE_ID = 486 AND L486.DATE_DEL IS NULL
        JOIN VALD V3393 ON V3393.OBJ_ID = L486.OBJ_ID AND V3393.PARAM_ID = 3393 AND V3393.IS_DEL = 0 AND V3393.VAL = :LESSON_DATE
        JOIN VALL V3394 ON V3394.OBJ_ID = L486.OBJ_ID AND V3394.PARAM_ID = 3394 AND V3394.IS_DEL = 0 AND V3394.LISTVAL_ID IN (14233, 14234)
        WHERE L481.PARENT_ID = :V$PERIOD_ID AND L481.OBJ_TYPE_ID = 481 AND L481.DATE_DEL IS NULL
      ))
      THEN
        V$SKIP = 1;

      -- Попадает в перенос выходного ? Отменяем выходной
      IF(V$SKIP = 1 AND EXISTS(
        SELECT FIRST 1 1
        FROM LINKS L481
        JOIN LINKS L486 ON L486.PARENT_ID = L481.OBJ_ID AND L486.OBJ_TYPE_ID = 486 AND L486.DATE_DEL IS NULL
        JOIN VALD V3393 ON V3393.OBJ_ID = L486.OBJ_ID AND V3393.PARAM_ID = 3393 AND V3393.IS_DEL = 0 AND V3393.VAL = :LESSON_DATE
        JOIN VALL V3394 ON V3394.OBJ_ID = L486.OBJ_ID AND V3394.PARAM_ID = 3394 AND V3394.IS_DEL = 0 AND V3394.LISTVAL_ID = 14235
        WHERE L481.PARENT_ID = :V$PERIOD_ID AND L481.OBJ_TYPE_ID = 481 AND L481.DATE_DEL IS NULL
      ))
      THEN
        V$SKIP = 1;

      -- Попадает в сетку периодов ?
      IF(V$SKIP = 0 AND NOT EXISTS(
        SELECT FIRST 1 1
        FROM LINKS L154
        JOIN VALD V1169 ON V1169.OBJ_ID = L154.OBJ_ID AND V1169.PARAM_ID = 1169 AND V1169.IS_DEL = 0 AND V1169.VAL <= :LESSON_DATE
        JOIN VALD V1174 ON V1174.OBJ_ID = L154.OBJ_ID AND V1174.PARAM_ID = 1174 AND V1174.IS_DEL = 0 AND V1174.VAL >= :LESSON_DATE
        WHERE L154.PARENT_ID = :V$PERIOD_ID AND L154.OBJ_TYPE_ID = 154 AND L154.DATE_DEL IS NULL
      ))
      THEN
        V$SKIP = 1;

      -- Попадает в каникулы ? отдельно исключаем каникулы 1 классов
      IF(V$SKIP = 0 AND EXISTS(
        SELECT FIRST 1 1
        FROM LINKS L450
        JOIN VALD V3263 ON V3263.OBJ_ID = L450.OBJ_ID AND V3263.PARAM_ID = 3263 AND V3263.IS_DEL = 0 AND V3263.VAL <= :LESSON_DATE
        JOIN VALD V3264 ON V3264.OBJ_ID = L450.OBJ_ID AND V3264.PARAM_ID = 3264 AND V3264.IS_DEL = 0 AND V3264.VAL >= :LESSON_DATE
        LEFT JOIN VALS V3265 ON V3265.OBJ_ID = L450.OBJ_ID AND V3265.PARAM_ID = 3265 AND V3265.IS_DEL = 0
        WHERE L450.PARENT_ID = :V$PERIOD_ID AND L450.OBJ_TYPE_ID = 450 AND L450.DATE_DEL IS NULL
          AND (:V$SI <> 37 OR V3265.VAL IS NULL OR (POSITION('перв' IN LOWER(V3265.VAL)) > 0 OR POSITION('доп' IN LOWER(V3265.VAL)) > 0))
      ))
      THEN
        V$SKIP = 1;

      IF(V$SKIP = 0) THEN SUSPEND;
    END

    W = W + 1;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_SCUD_PUPIL_LIST (
    I$GRADE_ID BIGINT)
RETURNS (
    PERSON_ID BIGINT,
    STATE SMALLINT)
AS
begin

  FOR
    SELECT DISTINCT MM.STUDENT_ID, IIF(S.PUPIL_ID IS NULL, 0, 1)
    FROM CJ2_MEMBER_MOVEMENTS(:I$GRADE_ID, NULL, NULL) MM
    LEFT JOIN SCUD_PUPILS S ON S.PUPIL_ID = MM.STUDENT_ID AND S.UPDATED >= CURRENT_DATE
    WHERE MM.DATE_FROM <= CURRENT_DATE AND (MM.DATE_TO IS NULL OR MM.DATE_TO >= CURRENT_DATE)
    INTO :PERSON_ID, :STATE
  DO
  BEGIN
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_SERIALIZE (
    I$JOURNAL_ID BIGINT,
    I$FROM TIMESTAMP)
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(4000))
AS
declare variable V$LESSON_ID varchar(40);
declare variable V$D1 date;
declare variable V$LESSON_NUM smallint;
declare variable V$TEACHER_ID bigint;
declare variable S varchar(4000);
declare variable S1 varchar(1000);
declare variable S2 varchar(1000);
declare variable V$COMPLETED smallint;
declare variable V$PUBLISHED smallint;
declare variable V$PTP_ID bigint;
declare variable V$HOURS float;
declare variable V$EXT_ID varchar(100);
declare variable V$TYPE_ID bigint;
declare variable V$CONTROL_TYPE_ID bigint;
declare variable V$MASTER_ID bigint;
declare variable V$CONTROL_ID varchar(40);
declare variable V$COST float;
declare variable V$STUDENT_ID bigint;
declare variable V$MARK_ID varchar(40);
declare variable V$MARK_TYPE_ID bigint;
declare variable V$IS_USED smallint;
declare variable V$CONTROL_STR varchar(40);
declare variable V$LT varchar(40);
declare variable V$YEAR_ID bigint;
declare variable V$STAGE_ID bigint;
declare variable V$SUBJECT_ID bigint;
declare variable V$GRADE_ID bigint;
declare variable V$JT integer;
declare variable V$INST smallint;
declare variable N integer;
declare variable V$PARENT_ID bigint;
begin

  -- Текущая метка времени
  TAG_NAME = 'timestamp';
  VAL = (SELECT VAL FROM DATE2ISO(CURRENT_TIMESTAMP));
  SUSPEND;

  SELECT J.STAGE_INDEX, J.SUBJECT_ID, J.YEAR_ID, J.GRADE_ID, J.JOURNAL_TYPE
  FROM CJ2_JOURNAL J
  WHERE J.OBJ_ID = :I$JOURNAL_ID
  INTO :V$STAGE_ID, :V$SUBJECT_ID, :V$YEAR_ID, :V$GRADE_ID, :V$JT;

  -- Уроки (флаг публикации выдаем во 2 бите на всякий случай)
  TAG_NAME = 'lessons';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'lessons::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
      SELECT CJL.OBJ_ID, CJL.LESSON_DATE, CJL.LESSON_NUM, CJL.TEACHER_ID, IIF(CJL.TEACHER_ID IS NULL, NULL, C.CAPTION), CJL.LESSON_THEME, CJL.LESSON_HOMEWORK,
          CJL.IS_COMPLETED, CJL.IS_PUBLISHED, CJL.LESSON_PTP_ID, CJL.LESSON_HOURS, CJL.LESSON_TYPE_ID, NULL, IIF(CJL.INST_ID IS NULL, 0, 1)
      FROM CJ2_JOURNAL_LESSONS CJL
      LEFT JOIN OBJECT_CAPTION_GET(CJL.TEACHER_ID) C ON 1 = 1
      WHERE CJL.CJ_ID = :I$JOURNAL_ID AND CJL.DATE_DEL IS NULL AND (CJL.DATE_MODIFY >= :I$FROM OR :I$FROM IS NULL)
      -- Рекомендуемые отметки, кроме экзаменов
      UNION
      SELECT 'v' || CJF.OBJ_ID, CJF.FINAL_DATE, 900, NULL, NULL, 'рек', NULL,
          0, 8, NULL, NULL, CJF.FINAL_TYPE, 'v', NULL
      FROM CJ2_JOURNAL_FINALS CJF
      WHERE CJF.CJ_ID = :I$JOURNAL_ID AND CJF.DATE_DEL IS NULL AND (CJF.DATE_MODIFY >= :I$FROM OR :I$FROM IS NULL)
          AND CJF.FINAL_TYPE NOT IN (3012, 5544)
      -- Итоговые отметки
      UNION
      SELECT 'f' || CJF.OBJ_ID, CJF.FINAL_DATE, 1000, CJF.TEACHER_ID, IIF(CJF.TEACHER_ID IS NULL, NULL, C.CAPTION), R.VAL, NULL,
          0, CJF.IS_PUBLISHED, NULL, NULL, CJF.FINAL_TYPE, 'f', NULL
      FROM CJ2_JOURNAL_FINALS CJF
      JOIN LISTVALS LV ON LV.LISTVAL_ID = CJF.FINAL_TYPE
      JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
      LEFT JOIN OBJECT_CAPTION_GET(CJF.TEACHER_ID) C ON 1 = 1
      WHERE CJF.CJ_ID = :I$JOURNAL_ID AND CJF.DATE_DEL IS NULL AND (CJF.DATE_MODIFY >= :I$FROM OR :I$FROM IS NULL)
      ORDER BY 2, 3
      INTO :V$LESSON_ID, :V$D1, :V$LESSON_NUM, :V$TEACHER_ID, :S, :S1, :S2,
          :V$COMPLETED, :V$PUBLISHED, :V$PTP_ID, :V$HOURS, :V$TYPE_ID, :V$LT, :V$INST
  DO
  BEGIN
      TAG_NAME = 'lessons:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'lessons:r:id';
      VAL = V$LESSON_ID;
      SUSPEND;
      TAG_NAME = 'lessons:r:lt';
      VAL = V$LT;
      SUSPEND;
      TAG_NAME = 'lessons:r:num';
      VAL = V$LESSON_NUM;
      SUSPEND;
      TAG_NAME = 'lessons:r:date';
      VAL = (SELECT VAL FROM DATE2ISO(:V$D1, 0));
      SUSPEND;
      TAG_NAME = 'lessons:r:teacher_id';
      VAL = V$TEACHER_ID;
      SUSPEND;
      TAG_NAME = 'lessons:r:teacher_name';
      VAL = S;
      SUSPEND;
      TAG_NAME = 'lessons:r:completed';
      VAL = V$COMPLETED * 2 + V$PUBLISHED * 1;
      SUSPEND;
      TAG_NAME = 'lessons:r:theme';
      VAL = S1;
      SUSPEND;
      TAG_NAME = 'lessons:r:homework';
      VAL = S2;
      SUSPEND;
      TAG_NAME = 'lessons:r:duration';
      VAL = V$HOURS;
      SUSPEND;
      TAG_NAME = 'lessons:r:lesson_type';
      VAL = V$TYPE_ID;
      SUSPEND;
      TAG_NAME = 'lessons:r:lesson_ptp_id';
      VAL = V$PTP_ID;
      SUSPEND;

      -- Скидываем признак, если в уроке нет ресурсов, а также когда дата уже неактуальна
      IF(V$D1 < DATEADD(- 3 DAY TO CURRENT_DATE) OR V$D1 > DATEADD(3 DAY TO CURRENT_DATE)) THEN V$INST = NULL;
      ELSE IF(V$INST = 0) THEN
      BEGIN
        IF(NOT EXISTS(
          SELECT FIRST 1 1 FROM CJ2_LESSON_RES R WHERE R.DATE_DEL IS NULL AND R.LESSON_ID = :V$LESSON_ID AND R.RES_TYPE IN (1816, 1931, 1933)
        ))
        THEN V$INST = NULL;
      END
      TAG_NAME = 'lessons:r:inst';
      VAL = V$INST;
      SUSPEND;
  END

  TAG_NAME = 'deleted_lessons';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'deleted_lessons::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
      SELECT CJL.OBJ_ID
      FROM CJ2_JOURNAL_LESSONS CJL
      WHERE CJL.CJ_ID = :I$JOURNAL_ID AND (CJL.DATE_DEL >= :I$FROM)
      UNION
      SELECT 'v' || CJF.OBJ_ID
      FROM CJ2_JOURNAL_FINALS CJF
      WHERE CJF.CJ_ID = :I$JOURNAL_ID AND (CJF.DATE_DEL >= :I$FROM) AND CJF.FINAL_TYPE NOT IN (3012, 5544)
      UNION
      SELECT 'f' || CJF.OBJ_ID
      FROM CJ2_JOURNAL_FINALS CJF
      WHERE CJF.CJ_ID = :I$JOURNAL_ID AND (CJF.DATE_DEL >= :I$FROM)
      INTO :V$LESSON_ID
  DO
  BEGIN
      TAG_NAME = 'deleted_lessons:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'deleted_lessons:r:id';
      VAL = V$LESSON_ID;
      SUSPEND;
  END

  -- Контроль по-умолчанию у нас есть настоящий
  TAG_NAME = 'controls';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'controls::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
      SELECT CJC.LESSON_ID,  CJC.CONTROL_ID, CJC.CONTROL_TYPE_ID, CJC.MARK_SYSTEM_ID, CJC.CONTROL_COST, CJC.IS_COMPLETED, CJC.HINT_TEXT, CJC.EXT_ID
      FROM CJ2_JOURNAL_LESSONS CJL
      JOIN CJ2_CONTROL CJC ON CJC.LESSON_ID = CJL.OBJ_ID AND CJC.DATE_DEL IS NULL AND (CJC.DATE_MODIFY >= :I$FROM OR :I$FROM IS NULL)
      WHERE CJL.CJ_ID = :I$JOURNAL_ID AND CJL.DATE_DEL IS NULL
      ORDER BY CJC.CONTROL_TYPE_ID
      INTO :V$LESSON_ID, :V$CONTROL_ID, :V$CONTROL_TYPE_ID, :V$MASTER_ID, :V$COST, :V$COMPLETED, :S, :V$EXT_ID
  DO
  BEGIN
      TAG_NAME = 'controls:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'controls:r:id';
      VAL = V$CONTROL_ID;
      SUSPEND;
      TAG_NAME = 'controls:r:lesson_id';
      VAL = V$LESSON_ID;
      SUSPEND;
      TAG_NAME = 'controls:r:type_id';
      VAL = V$CONTROL_TYPE_ID;
      SUSPEND;
      TAG_NAME = 'controls:r:system_id';
      VAL = V$MASTER_ID;
      SUSPEND;
      TAG_NAME = 'controls:r:cost';
      VAL = V$COST;
      SUSPEND;
      TAG_NAME = 'controls:r:completed';
      VAL = V$COMPLETED;
      SUSPEND;
      TAG_NAME = 'controls:r:text';
      VAL = S;
      SUSPEND;
      TAG_NAME = 'controls:r:ext_id';
      VAL = V$EXT_ID;
      SUSPEND;
  END

  -- Контроли для итоговых отметок
  FOR
      SELECT CJF.OBJ_ID, CJF.FINAL_TYPE, R.VAL, CJF.MARK_SYSTEM_ID
      FROM CJ2_JOURNAL_FINALS CJF
      JOIN LISTVALS LV ON LV.LISTVAL_ID = CJF.FINAL_TYPE
      JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
      WHERE CJF.CJ_ID = :I$JOURNAL_ID AND (CJF.DATE_MODIFY >= :I$FROM OR :I$FROM IS NULL)
      INTO :V$LESSON_ID, :V$CONTROL_TYPE_ID, :S, :V$MASTER_ID
  DO
  BEGIN
      -- Рекомендуемая отметка
      IF(V$CONTROL_TYPE_ID NOT IN (3012, 5544)) THEN
      BEGIN
          TAG_NAME = 'controls:r';
          VAL = NULL;
          SUSPEND;
          TAG_NAME = 'controls:r:lesson_id';
          VAL = 'v' || V$LESSON_ID;
          SUSPEND;
          TAG_NAME = 'controls:r:id';
          VAL = 'v' || V$LESSON_ID;
          SUSPEND;
          TAG_NAME = 'controls:r:type_id';
          VAL = V$CONTROL_TYPE_ID;
          SUSPEND;
          TAG_NAME = 'controls:r:system_id'; -- всегда 5-балльная шкала
          VAL = V$MASTER_ID;
          SUSPEND;
          TAG_NAME = 'controls:r:cost';
          VAL = 0;
          SUSPEND;
          TAG_NAME = 'controls:r:completed';
          VAL = 1;
          SUSPEND;
          TAG_NAME = 'controls:r:text';
          VAL = 'Рек';
          SUSPEND;
          TAG_NAME = 'controls:r:ext_id';
          VAL = NULL;
          SUSPEND;
      END
      -- Сама итоговая отметка
      TAG_NAME = 'controls:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'controls:r:lesson_id';
      VAL = 'f' || V$LESSON_ID;
      SUSPEND;
      TAG_NAME = 'controls:r:id';
      VAL = 'f' || V$LESSON_ID;
      SUSPEND;
      TAG_NAME = 'controls:r:type_id';
      VAL = V$CONTROL_TYPE_ID;
      SUSPEND;
      TAG_NAME = 'controls:r:system_id';
      VAL = V$MASTER_ID;
      SUSPEND;
      TAG_NAME = 'controls:r:cost';
      VAL = 0;
      SUSPEND;
      TAG_NAME = 'controls:r:completed';
      VAL = 1;
      SUSPEND;
      TAG_NAME = 'controls:r:text';
      VAL = S;
      SUSPEND;
      TAG_NAME = 'controls:r:short';
      IF(V$CONTROL_TYPE_ID = 3002) THEN VAL = '1Чт';
      ELSE IF(V$CONTROL_TYPE_ID = 3003) THEN VAL = '2Чт';
      ELSE IF(V$CONTROL_TYPE_ID = 3004) THEN VAL = '3Чт';
      ELSE IF(V$CONTROL_TYPE_ID = 3005) THEN VAL = '4Чт';
      ELSE IF(V$CONTROL_TYPE_ID = 3006) THEN VAL = '1Тр';
      ELSE IF(V$CONTROL_TYPE_ID = 3007) THEN VAL = '2Тр';
      ELSE IF(V$CONTROL_TYPE_ID = 3008) THEN VAL = '3Тр';
      ELSE IF(V$CONTROL_TYPE_ID = 3009) THEN VAL = '1По';
      ELSE IF(V$CONTROL_TYPE_ID = 3010) THEN VAL = '2По';
      ELSE IF(V$CONTROL_TYPE_ID = 3011) THEN VAL = 'Год';
      ELSE IF(V$CONTROL_TYPE_ID = 3012) THEN VAL = 'Экз';
      ELSE IF(V$CONTROL_TYPE_ID = 5544) THEN VAL = 'КЭ';
      ELSE IF(V$CONTROL_TYPE_ID = 3013) THEN VAL = 'Итг';
      ELSE BEGIN
        -- Кастомный контроль, берем первые буквы слов
        VAL = '';
        WHILE(CHAR_LENGTH(S) > 0) DO
        BEGIN
          N = POSITION(' ' IN S);
          VAL = VAL || UPPER(SUBSTRING(S FROM 1 FOR 1));
          IF(N > 0) THEN S = SUBSTRING(S FROM N + 1); ELSE S = '';
        END
      END
      SUSPEND;
      TAG_NAME = 'controls:r:ext_id';
      VAL = NULL;
      SUSPEND;
  END

  TAG_NAME = 'deleted_controls';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'deleted_controls::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
      SELECT CJC.CONTROL_ID
      FROM CJ2_JOURNAL_LESSONS CJL
      JOIN CJ2_CONTROL CJC ON CJC.LESSON_ID = CJL.OBJ_ID
      WHERE CJL.CJ_ID = :I$JOURNAL_ID AND (CJL.DATE_DEL >= :I$FROM OR CJC.DATE_DEL >= :I$FROM)
      UNION
      SELECT 'v' || CJF.OBJ_ID
      FROM CJ2_JOURNAL_FINALS CJF
      WHERE CJF.CJ_ID = :I$JOURNAL_ID AND (CJF.DATE_DEL >= :I$FROM) AND CJF.FINAL_TYPE NOT IN (3012, 5544)
      UNION
      SELECT 'f' || CJF.OBJ_ID
      FROM CJ2_JOURNAL_FINALS CJF
      WHERE CJF.CJ_ID = :I$JOURNAL_ID AND (CJF.DATE_DEL >= :I$FROM)
      INTO :V$CONTROL_ID
  DO
  BEGIN
      TAG_NAME = 'deleted_controls:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'deleted_controls:r:id';
      VAL = V$CONTROL_ID;
      SUSPEND;
  END

  -- Оценки
  TAG_NAME = 'marks';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'marks::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
      SELECT CJM.STUDENT_ID, CJM.CONTROL_ID, CJM.MARK_ID, CJM.MARK_TYPE_ID, CJM.IS_USED, CJM.COMMENTS_TEXT
      FROM CJ2_JOURNAL_LESSONS CJL
      JOIN CJ2_CONTROL CJC ON CJC.LESSON_ID = CJL.OBJ_ID AND CJC.DATE_DEL IS NULL
      JOIN CJ2_MARK CJM ON CJM.CONTROL_ID = CJC.CONTROL_ID AND CJM.DATE_DEL IS NULL AND (CJM.DATE_MODIFY >= :I$FROM OR :I$FROM IS NULL)
      WHERE CJL.CJ_ID = :I$JOURNAL_ID AND CJL.DATE_DEL IS NULL
      UNION
      SELECT CJM.STUDENT_ID, 'f' || CJM.FINAL_ID, CJM.MARK_ID, CJM.MARK_TYPE_ID, CJM.IS_USED, NULL
      FROM CJ2_JOURNAL_FINALS CJF
      JOIN CJ2_MARK CJM ON CJM.FINAL_ID = CJF.OBJ_ID AND CJM.DATE_DEL IS NULL AND (CJM.DATE_MODIFY >= :I$FROM OR :I$FROM IS NULL)
      WHERE CJF.CJ_ID = :I$JOURNAL_ID AND CJF.DATE_DEL IS NULL
      INTO :V$STUDENT_ID, :V$CONTROL_STR, :V$MARK_ID, :V$MARK_TYPE_ID, :V$IS_USED, :S
  DO
  BEGIN
      TAG_NAME = 'marks:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'marks:r:student_id';
      VAL = V$STUDENT_ID;
      SUSPEND;
      TAG_NAME = 'marks:r:control_id';
      VAL = V$CONTROL_STR;
      SUSPEND;
      TAG_NAME = 'marks:r:id';
      VAL = V$MARK_ID;
      SUSPEND;
      TAG_NAME = 'marks:r:type_id';
      VAL = V$MARK_TYPE_ID;
      SUSPEND;
      TAG_NAME = 'marks:r:is_used';
      VAL = V$IS_USED;
      SUSPEND;
      TAG_NAME = 'marks:r:text';
      VAL = S;
      SUSPEND;
  END

  -- Итоговые отметки, поставленные за текущий учебный год и тот же этап в другом классе или школе
  -- обязательно по тому же предмету
  FOR
      SELECT DISTINCT MO.STUDENT_ID, JFO.FINAL_TYPE, MO.MARK_ID, MO.MARK_TYPE_ID, MO.IS_USED
      FROM PERSON_MOVEMENTS M
      JOIN PERSON_MOVEMENTS M2 ON M2.DATE_DEL IS NULL AND M2.PERSON_ID = M.PERSON_ID
      JOIN CJ2_JOURNAL JO ON JO.DATE_DEL IS NULL AND JO.GRADE_ID = M2.GROUP_ID AND JO.YEAR_ID = :V$YEAR_ID AND JO.SUBJECT_ID = :V$SUBJECT_ID
        AND JO.STAGE_INDEX = :V$STAGE_ID AND JO.OBJ_ID <> :I$JOURNAL_ID
      JOIN CJ2_JOURNAL_FINALS JFO ON JFO.DATE_DEL IS NULL AND JFO.CJ_ID = JO.OBJ_ID
      JOIN CJ2_MARK MO ON MO.DATE_DEL IS NULL AND MO.FINAL_ID = JFO.OBJ_ID AND MO.STUDENT_ID = M.PERSON_ID
      WHERE M.DATE_DEL IS NULL AND M.GROUP_ID = :V$GRADE_ID AND :V$JT = 0
      INTO :V$STUDENT_ID, :V$MASTER_ID, :V$MARK_ID, :V$MARK_TYPE_ID, :V$IS_USED
  DO
  BEGIN
      -- Восстанавливаем final_id в новом журнале, если он есть
      V$CONTROL_STR = NULL;
      SELECT FIRST 1 'f' || F.OBJ_ID
      FROM CJ2_JOURNAL_FINALS F
      WHERE F.DATE_DEL IS NULL AND F.CJ_ID = :I$JOURNAL_ID AND F.FINAL_TYPE = :V$MASTER_ID
      INTO :V$CONTROL_STR;

      IF(V$CONTROL_STR IS NOT NULL) THEN
      BEGIN
          TAG_NAME = 'marks:r';
          VAL = NULL;
          SUSPEND;
          TAG_NAME = 'marks:r:student_id';
          VAL = V$STUDENT_ID;
          SUSPEND;
          TAG_NAME = 'marks:r:control_id';
          VAL = V$CONTROL_STR;
          SUSPEND;
          TAG_NAME = 'marks:r:id';
          VAL = V$MARK_ID;
          SUSPEND;
          TAG_NAME = 'marks:r:type_id';
          VAL = V$MARK_TYPE_ID;
          SUSPEND;
          TAG_NAME = 'marks:r:is_used';
          VAL = V$IS_USED;
          SUSPEND;
          TAG_NAME = 'marks:r:text';
          VAL = NULL;
          SUSPEND;
          TAG_NAME = 'marks:r:is_native';
          VAL = 2;
          SUSPEND;
      END
  END

  -- Итоговые отметки из другой школы, если они есть
  FOR
      SELECT DISTINCT M.PERSON_ID, V.MARKTYPE_ID, V.MARK_ID, V.MARKVAL_ID, R.VAL
      FROM PERSON_MOVEMENTS M
      JOIN VALM V ON V.PUPIL_ID = M.PERSON_ID AND V.YEAR_ID = :V$YEAR_ID AND V.STAGE_ID = :V$STAGE_ID AND V.SUBJECT_ID = :V$SUBJECT_ID AND V.IS_NATIVE = 0 AND V.IS_DEL = 0
      JOIN LISTVALS LV ON LV.LISTVAL_ID = V.MARKVAL_ID
      JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
      WHERE M.DATE_DEL IS NULL AND M.GROUP_ID = :V$GRADE_ID AND :V$JT = 0
      INTO :V$STUDENT_ID, :V$MASTER_ID, :V$MARK_ID, :V$CONTROL_TYPE_ID, :V$CONTROL_ID
  DO
  BEGIN
      -- Восстанавливаем final_id в новом журнале, если он есть
      V$CONTROL_STR = NULL;
      SELECT FIRST 1 'f' || F.OBJ_ID
      FROM CJ2_JOURNAL_FINALS F
      WHERE F.DATE_DEL IS NULL AND F.CJ_ID = :I$JOURNAL_ID AND F.FINAL_TYPE = :V$MASTER_ID
      INTO :V$CONTROL_STR;

      V$MARK_TYPE_ID = NULL;
      IF(V$CONTROL_TYPE_ID <= 3018) THEN V$PARENT_ID = 400; -- 5-балльная
      ELSE IF(V$CONTROL_TYPE_ID IN (3019, 3020, 3022, 3023)) THEN V$PARENT_ID = 100; -- зачет
      ELSE IF(V$CONTROL_TYPE_ID IN (11040, 11041, 11042)) THEN V$PARENT_ID = 110; -- усвоил
      ELSE IF(V$CONTROL_TYPE_ID >= 13020 AND V$CONTROL_TYPE_ID <= 13119) THEN V$PARENT_ID = 499; -- 100-балльная
      ELSE IF(V$CONTROL_TYPE_ID >= 13309 AND V$CONTROL_TYPE_ID <= 13320) THEN V$PARENT_ID = 450; -- 12-балльная
      ELSE V$PARENT_ID = NULL;

      IF(POSITION('/' IN V$CONTROL_ID) > 0) THEN V$CONTROL_ID = SUBSTRING(V$CONTROL_ID FROM 1 FOR POSITION('/' IN V$CONTROL_ID));

      SELECT FIRST 1 MT.MARK_TYPE_ID
      FROM CJ2_MARK_TYPE MT
      WHERE MT.IS_DEL = 0 AND MT.PARENT_ID = :V$PARENT_ID AND MT.MARK_SHORTNAME = :V$CONTROL_ID
      INTO :V$MARK_TYPE_ID;

      IF(V$CONTROL_STR IS NOT NULL AND V$MARK_TYPE_ID IS NOT NULL) THEN
      BEGIN
          TAG_NAME = 'marks:r';
          VAL = NULL;
          SUSPEND;
          TAG_NAME = 'marks:r:student_id';
          VAL = V$STUDENT_ID;
          SUSPEND;
          TAG_NAME = 'marks:r:control_id';
          VAL = V$CONTROL_STR;
          SUSPEND;
          TAG_NAME = 'marks:r:id';
          VAL = V$MARK_ID;
          SUSPEND;
          TAG_NAME = 'marks:r:type_id';
          VAL = V$MARK_TYPE_ID;
          SUSPEND;
          TAG_NAME = 'marks:r:is_used';
          VAL = 1;
          SUSPEND;
          TAG_NAME = 'marks:r:text';
          VAL = NULL;
          SUSPEND;
          TAG_NAME = 'marks:r:is_native';
          VAL = 2;
          SUSPEND;
      END
  END

  TAG_NAME = 'deleted_marks';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'deleted_marks::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
      SELECT CJM.MARK_ID
      FROM CJ2_JOURNAL_LESSONS CJL
      JOIN CJ2_CONTROL CJC ON CJC.LESSON_ID = CJL.OBJ_ID
      JOIN CJ2_MARK CJM ON CJM.CONTROL_ID = CJC.CONTROL_ID
      WHERE CJL.CJ_ID = :I$JOURNAL_ID AND (CJL.DATE_DEL >= :I$FROM OR CJC.DATE_DEL >= :I$FROM OR CJM.DATE_DEL >= :I$FROM)
      UNION
      SELECT CJM.MARK_ID
      FROM CJ2_JOURNAL_FINALS CJF
      JOIN CJ2_MARK CJM ON CJM.FINAL_ID = CJF.OBJ_ID
      WHERE CJF.CJ_ID = :I$JOURNAL_ID AND (CJF.DATE_DEL >= :I$FROM OR CJM.DATE_DEL >= :I$FROM)
      INTO :V$MARK_ID
  DO
  BEGIN
      TAG_NAME = 'deleted_marks:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'deleted_marks:r:id';
      VAL = V$MARK_ID;
      SUSPEND;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_STATE_PROCESS (
    I$CJ_ID BIGINT,
    I$LESSON_ID BIGINT)
AS
DECLARE VARIABLE V$PUBLISHED SMALLINT;
DECLARE VARIABLE V$COMPLETED SMALLINT;
DECLARE VARIABLE V$DATE DATE;
DECLARE VARIABLE V$DATE2 DATE;
DECLARE VARIABLE V$NUM INTEGER;
DECLARE VARIABLE V$TEST_ID BIGINT;
DECLARE VARIABLE V$CONTROL_ID BIGINT;
DECLARE VARIABLE V$GRADE_ID BIGINT;
DECLARE VARIABLE V$STATE INTEGER;
DECLARE VARIABLE V$CT BIGINT;
DECLARE VARIABLE V$TIME TIME;
DECLARE VARIABLE V$VAR INTEGER;
DECLARE VARIABLE N1 INTEGER;
DECLARE VARIABLE N2 INTEGER;
DECLARE VARIABLE S1 VARCHAR(10);
DECLARE VARIABLE S2 VARCHAR(10);
DECLARE VARIABLE SN1 INTEGER;
DECLARE VARIABLE SN2 INTEGER;
DECLARE VARIABLE V$PERSON_ID BIGINT;
DECLARE VARIABLE V$OU_ID BIGINT;
DECLARE VARIABLE V$AREA_ID BIGINT;
DECLARE VARIABLE S VARCHAR(1000);
DECLARE VARIABLE SS VARCHAR(100);
DECLARE VARIABLE P INTEGER;
DECLARE VARIABLE P2 INTEGER;
DECLARE VARIABLE V$JN VARCHAR(100);
begin

  SELECT L.LESSON_DATE, L.LESSON_NUM, L.IS_PUBLISHED, L.IS_COMPLETED, J.GRADE_ID, LOWER(L.LESSON_HOMEWORK), SUBSTRING(J.JOURNAL_NAME FROM 1 FOR 100)
  FROM CJ2_JOURNAL_LESSONS L
  JOIN CJ2_JOURNAL J ON J.OBJ_ID = L.CJ_ID
  WHERE L.OBJ_ID = :I$LESSON_ID
  INTO :V$DATE, :V$NUM, :V$PUBLISHED, :V$COMPLETED, :V$GRADE_ID, :S, :V$JN;

  -- Остановить тестирование, если оно не было завершено
  IF(V$PUBLISHED = 0 AND V$COMPLETED = 0) THEN
  BEGIN
    FOR
      SELECT C.TEST_ID
      FROM CJ2_CONTROL C
      JOIN UT_EXAM_DATES D ON D.OBJ_ID = C.TEST_ID AND D.DATE_DEL IS NULL AND D.EXAM_STATE = 600
      WHERE C.LESSON_ID = :I$LESSON_ID
      ORDER BY 1
      INTO :V$TEST_ID
    DO
    BEGIN
      UPDATE UT_EXAM_DATES
      SET EXAM_STATE = 550
      WHERE OBJ_ID = :V$TEST_ID;
    END
  END

  -- Про переводе в статус опубликован или проведен - запускаем тестирования, если они еще не запущены
  IF(V$PUBLISHED = 1 OR V$COMPLETED = 1) THEN
  BEGIN
    -- Время начала урока смотрим по расписанию
    IF(V$NUM < 60) THEN
    BEGIN
      -- !!!
    END
    ELSE
    BEGIN
      -- Минуты с начала суток
      N1 = V$NUM / 60;
      N2 = V$NUM - N1 * 60;
      S1 = IIF(N1 < 10, '0' || N1, N1);
      S2 = IIF(N2 < 10, '0' || N2, N2);
      V$TIME = S1 || ':' || S2;
    END

    FOR
      SELECT C.CONTROL_ID, C.TEST_ID, D.EXAM_STATE, C.CONTROL_TYPE_ID
      FROM CJ2_CONTROL C
      JOIN UT_EXAM_DATES D ON D.OBJ_ID = C.TEST_ID AND D.DATE_DEL IS NULL AND D.EXAM_STATE < 600
      WHERE C.LESSON_ID = :I$LESSON_ID
      ORDER BY 1
      INTO :V$CONTROL_ID, :V$TEST_ID, :V$STATE, :V$CT
    DO
    BEGIN
      -- Назначены ли задания однородно во всех вариантах ?
      -- По не сверяем сложности
      V$NUM = 0;
      FOR
        SELECT Q.VARIANT_INDEX, COUNT(*), SUM(QQ.MAX_SCORE)
        FROM UT_EXAM_QUESTIONS Q
        JOIN UT_QUESTIONS QQ ON QQ.OBJ_ID = Q.QUESTION_ID
        WHERE Q.DATE_DEL IS NULL AND Q.EXAM_ID = :V$TEST_ID
        GROUP BY 1
        ORDER BY 1
        INTO :V$VAR, :N1, :N2
      DO
      BEGIN
        -- Используем фичу что NULL ничему не равен
        IF(SN1 <> N1) THEN EXCEPTION DATA_ERROR 'Количество вопросов не совпадает по вариантам тестирования';
        IF(SN2 <> N2) THEN EXCEPTION DATA_ERROR 'Суммарный балл вопросов совпадает по вариантам тестирования';
        SN1 = N1;
        SN2 = N2;
        V$NUM = V$NUM + 1;
      END
      IF(V$NUM = 0) THEN EXCEPTION DATA_ERROR 'Не подготовлены вопросы в тестировании';

      -- Тестирование с типом Домашнее задание сразу ставим в статусе Выполняется
      -- все остальные подготавливаем, но не запускаем - учитель сам его запустит
      IF(V$CT = 1063) THEN
      BEGIN
        -- Дата окончания тестирования = указана в тексте ДЗ (пройти/выполнить до XX.XX), либо берется по расписанию следующий урок
        P = POSITION('выполнить до ', S);
        IF(P <= 0) THEN P = POSITION('пройти до ', S);
        IF(P > 0) THEN
        BEGIN
          -- Пропускаем два пробела
          WHILE(SUBSTRING(S FROM P FOR 1) <> ' ') DO P = P + 1; P = P + 1;
          WHILE(SUBSTRING(S FROM P FOR 1) <> ' ') DO P = P + 1; P = P + 1;
          -- Конец даты - следующий пробел или конец строки
          P2 = POSITION(' ', S, P);
          IF(P2 <= 0) THEN P2 = CHAR_LENGTH(S) + 1;
          SS = SUBSTRING(S FROM P FOR P2 - P);
          IF(CHAR_LENGTH(SS) IN (1, 2)) THEN
          BEGIN
            -- Указано только число - добавляем месяц и год
            N1 = SS;
            IF(N1 > EXTRACT(DAY FROM V$DATE2)) THEN V$DATE2 = SS || '.' || EXTRACT(MONTH FROM V$DATE) || '.' || EXTRACT(YEAR FROM V$DATE);
            ELSE IF(EXTRACT(MONTH FROM V$DATE) < 12) THEN V$DATE2 = SS || '.' || (EXTRACT(MONTH FROM V$DATE) + 1) || '.' || EXTRACT(YEAR FROM V$DATE);
            ELSE V$DATE2 = SS || '.01.' || (EXTRACT(YEAR FROM V$DATE) + 1);
          END
          ELSE IF(CHAR_LENGTH(SS) = 5) THEN BEGIN
            -- Указано число и месяц - добавляем год
            IF(RIGHT(SS, 2) IN ('09', '10', '11', '12') OR EXTRACT(MONTH FROM V$DATE) < 9) THEN V$DATE2 = SS || '.' || EXTRACT(YEAR FROM V$DATE);
            ELSE V$DATE2 = SS || '.' || (EXTRACT(YEAR FROM V$DATE) + 1);
          END
          ELSE V$DATE2 = SS;
        END
        ELSE
        BEGIN
          V$DATE2 = V$DATE;
          SELECT FIRST 1 S.LESSON_DATE
          FROM CJ2_SCHEDULE_STREAM(:I$CJ_ID, :V$DATE) S
          WHERE S.LESSON_DATE > :V$DATE
          INTO :V$DATE2;
        END

        V$STATE = 600;
        IF(V$DATE2 < V$DATE) THEN EXCEPTION DATA_ERROR 'Неверно указана дата окончания тестирования в тексте ДЗ';
      END
      ELSE
      BEGIN
        -- Дата окончания тестирования = текущая дата
        V$STATE = 550;
        V$DATE2 = V$DATE;
      END

      -- Если это плановое тестирование со связями в ПТП, либо есть несколько связей с уроками - надо сделать копию
      IF(EXISTS(
        SELECT FIRST 1 1
        FROM PTP_LESSON_TESTS T
        WHERE T.DATE_DEL IS NULL AND T.TEST_ID = :V$TEST_ID
        UNION
        SELECT FIRST 1 1
        FROM CJ2_CONTROL C
        WHERE C.DATE_DEL IS NULL AND C.TEST_ID = :V$TEST_ID AND C.CONTROL_ID <> :V$CONTROL_ID
      ))
      THEN
      BEGIN
        SELECT OBJ_ID
        FROM UT_TEST_CLONE(:V$TEST_ID, :V$STATE, :V$DATE, :V$DATE2, :V$TIME, :V$JN)
        INTO :V$TEST_ID;

        UPDATE CJ2_CONTROL
        SET TEST_ID = :V$TEST_ID
        WHERE CONTROL_ID = :V$CONTROL_ID;
      END
      -- Если же это единственная инкарнация тестирования - обновляем даты и запускаем
      ELSE
      BEGIN
        UPDATE UT_EXAM_DATES
        SET EXAM_STATE = :V$STATE, EXAM_DATE_START = :V$DATE, EXAM_DATE_END = :V$DATE2
        WHERE OBJ_ID = :V$TEST_ID;
      END

      -- Назначаем обучающихся
      FOR
        SELECT DISTINCT M.PERSON_ID
        FROM PERSON_MOVEMENTS M
        LEFT JOIN UT_EXAM_PERSON_ASSN PA ON PA.DATE_DEL IS NULL AND PA.EXAM_ID = :V$TEST_ID AND PA.PERSON_ID = M.PERSON_ID
        WHERE M.DATE_DEL IS NULL AND M.GROUP_ID = :V$GRADE_ID AND M.DATE_IN <= :V$DATE AND M.DATE_OUT IS NULL AND PA.OBJ_ID IS NULL
        ORDER BY 1
        INTO :V$PERSON_ID
      DO
      BEGIN
        IF(V$OU_ID IS NULL) THEN
        SELECT FIRST 1 L2.OBJ_ID, V2163.LISTVAL_ID
        FROM LINKS L2
        JOIN VALL V2163 ON V2163.OBJ_ID = L2.OBJ_ID AND V2163.PARAM_ID = 2163 AND V2163.IS_DEL = 0
        WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
        INTO :V$OU_ID, :V$AREA_ID;

        INSERT INTO UT_EXAM_PERSON_ASSN
        (EXAM_ID, PERSON_ID, OU_ID, AREA_ID)
        VALUES (:V$TEST_ID, :V$PERSON_ID, :V$OU_ID, :V$AREA_ID);
      END
    END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_TEACHER_NAME (
    I$GRADE_ID BIGINT,
    I$TEACHER_ID BIGINT)
RETURNS (
    CAPTION VARCHAR(1000))
AS
declare variable S varchar(400);
begin

  IF(I$TEACHER_ID IS NOT NULL) THEN
  BEGIN
    SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$TEACHER_ID) INTO :CAPTION;
  END
  ELSE IF(I$GRADE_ID IS NOT NULL) THEN
  BEGIN
    CAPTION = '';

    FOR
      SELECT C.CAPTION
      FROM LINKS L186
      JOIN VALR V1609 ON V1609.OBJ_ID = L186.OBJ_ID AND V1609.PARAM_ID = 1609 AND V1609.IS_DEL = 0
      LEFT JOIN OBJECT_CAPTION_GET(V1609.VAL) C ON 1 = 1
      WHERE L186.PARENT_ID = :I$GRADE_ID AND L186.OBJ_TYPE_ID = 186 AND L186.DATE_DEL IS NULL
      UNION
      SELECT C.CAPTION
      FROM LINKS L165
      JOIN VALR V1556 ON V1556.OBJ_ID = L165.OBJ_ID AND V1556.PARAM_ID IN (1556, 1575) AND V1556.IS_DEL = 0
      LEFT JOIN OBJECT_CAPTION_GET(V1556.VAL) C ON 1 = 1
      WHERE L165.PARENT_ID = :I$GRADE_ID AND L165.OBJ_TYPE_ID IN (165, 170) AND L165.DATE_DEL IS NULL
      ORDER BY 1
      INTO :S
    DO
    BEGIN
      IF(CHAR_LENGTH(CAPTION) + CHAR_LENGTH(S) + 2 < 1000) THEN
      BEGIN
        IF(CAPTION <> '') THEN CAPTION = CAPTION || ', ';
        CAPTION = CAPTION || S;
      END
    END

  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_UPDATE_RATING (
    I$DATE DATE = CURRENT_DATE)
AS
DECLARE VARIABLE V$STUDENT_ID BIGINT;
DECLARE VARIABLE V$START_DATE DATE;
DECLARE VARIABLE V$SUBJECT_ID BIGINT;
DECLARE VARIABLE V$CLASS_ID BIGINT;
DECLARE VARIABLE N INTEGER;
DECLARE VARIABLE N2 INTEGER;
DECLARE VARIABLE V$U DOUBLE PRECISION;
DECLARE VARIABLE V$D DOUBLE PRECISION;
DECLARE VARIABLE V$S DOUBLE PRECISION;
DECLARE VARIABLE V$DATE DATE;
DECLARE VARIABLE V$OU_ID BIGINT;
DECLARE VARIABLE V$TN INTEGER;
DECLARE VARIABLE V$TS DOUBLE PRECISION;
DECLARE VARIABLE V$TT INTEGER;
DECLARE VARIABLE V$TT4 INTEGER;
DECLARE VARIABLE V$R4 SMALLINT;
DECLARE VARIABLE V$TTG DOUBLE PRECISION;
DECLARE VARIABLE V$TTTG INTEGER;
DECLARE VARIABLE V$SX INTEGER;
DECLARE VARIABLE V$S2 INTEGER;
DECLARE VARIABLE V$S3 INTEGER;
DECLARE VARIABLE V$S4 INTEGER;
DECLARE VARIABLE V$S5 INTEGER;
DECLARE VARIABLE V$GRADE_ID BIGINT;
DECLARE VARIABLE V$TN5 INTEGER;
DECLARE VARIABLE V$N5 INTEGER;
DECLARE VARIABLE V$F5 SMALLINT;
DECLARE VARIABLE V$C5 SMALLINT;
DECLARE VARIABLE V$N678 INTEGER;
DECLARE VARIABLE V$NB678 INTEGER;
DECLARE VARIABLE V$M45 INTEGER;
DECLARE VARIABLE V$NOBJ INTEGER;
DECLARE VARIABLE V$PROFCNT INTEGER;
DECLARE VARIABLE V$PROFILE_ID BIGINT;
DECLARE VARIABLE V$N212 INTEGER;
DECLARE VARIABLE V$M212 INTEGER;
DECLARE VARIABLE V$F212 INTEGER;
DECLARE VARIABLE V$D212 INTEGER;
DECLARE VARIABLE V$HOURS FLOAT;
DECLARE VARIABLE V$WEEKS INTEGER;
DECLARE VARIABLE V$M INTEGER;
DECLARE VARIABLE V$MINM INTEGER;
DECLARE VARIABLE V$MAXM INTEGER;
DECLARE VARIABLE V$PREV_ID BIGINT;
DECLARE VARIABLE V$CN INTEGER;
DECLARE VARIABLE V$CU DOUBLE PRECISION;
DECLARE VARIABLE V$CS DOUBLE PRECISION;
DECLARE VARIABLE V$CD DOUBLE PRECISION;
DECLARE VARIABLE V$YEAR_ID BIGINT;
DECLARE VARIABLE V$PERIOD_TYPE BIGINT;
DECLARE VARIABLE V$PERIOD BIGINT;
DECLARE VARIABLE V$LN INTEGER;
DECLARE VARIABLE V$LNG INTEGER;
begin

  -- Пересчет рейтингов по обучающимся и школе в целом
  -- Все средние подсчитываем с начала текущего учебного периода для конкретного класса

  -- Хитрые значения в CJ2_STUDENT_RATING идут с SUBJECT_ID от 0, STUDENT_ID равным OU_ID

  -- Выгрузка всегда маркируется 00:00 понедельника
  N = EXTRACT(WEEKDAY FROM I$DATE);
  IF(N = 0) THEN N = 6; ELSE N = N - 1;
  I$DATE = DATEADD(- N DAY TO I$DATE);

  SELECT FIRST 1 L2.OBJ_ID, CAST(LV.TAG AS DATE), LV.LISTVAL_ID
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$OU_ID, :V$START_DATE, :V$YEAR_ID;

  V$TT = 0;  -- счетчик персон
  V$TT4 = 0; -- счетчик персон с баллом >= 4
  V$TN = 0;
  V$TS = 0;
  V$TTG = 0; -- счетчики для обученности
  V$TTTG = 0;
  V$TN5 = 0;
  V$N5 = 0;
  V$N678 = 0;
  V$NB678 = 0;
  V$M45 = 0;
  V$NOBJ = 0;
  V$N212 = 0;
  V$D212 = 0;
  V$M212 = 0;
  V$PREV_ID = 0;

  FOR
    SELECT DISTINCT L10.OBJ_ID, L10.PARENT_ID, V49.LISTVAL_ID
    FROM LINKS L10
    JOIN LINKS LP8 ON LP8.OBJ_ID = L10.PARENT_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
    JOIN VALL V49 ON V49.OBJ_ID = LP8.PARENT_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
    WHERE L10.PARENT_TYPE_ID = 9 AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    ORDER BY 3, 2
    INTO :V$STUDENT_ID, :V$CLASS_ID, :V$GRADE_ID
  DO
  BEGIN

    -- Дата начала текущего учебного периода - считаем по классам чтобы было быстрее
    IF(V$PREV_ID <> V$CLASS_ID) THEN
    BEGIN
      V$DATE = NULL;
      V$PERIOD = NULL;
      V$PERIOD_TYPE = NULL;
      SELECT FIRST 1 L154.OBJ_ID, V1169.VAL, V1170.LISTVAL_ID
      FROM PERSON_MOVEMENTS M
      JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.GRADE_ID = M.GROUP_ID AND J.JOURNAL_TYPE = 0
      JOIN LINKS L154 ON L154.PARENT_ID = J.PERIOD_ID AND L154.OBJ_TYPE_ID = 154 AND L154.DATE_DEL IS NULL
      JOIN VALD V1169 ON V1169.OBJ_ID = L154.OBJ_ID AND V1169.PARAM_ID = 1169 AND V1169.IS_DEL = 0 AND V1169.VAL <= :I$DATE
      JOIN VALL V1170 ON V1170.OBJ_ID = L154.OBJ_ID AND V1170.PARAM_ID = 1170 AND V1170.IS_DEL = 0
      WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :V$STUDENT_ID AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :V$START_DATE)
      ORDER BY V1169.VAL DESC
      INTO :V$PERIOD, :V$DATE, :V$PERIOD_TYPE;
      IF(V$DATE IS NULL) THEN V$DATE = V$START_DATE;
      V$PREV_ID = V$CLASS_ID;
    END

    V$R4 = 1;
    V$S2 = 0;
    V$PROFCNT = 0;
    V$PROFILE_ID = NULL;
    V$F212 = 1;
    V$MINM = 1000;
    V$MAXM = -1;
    V$F5 = 1;
    V$C5 = 0;

    -- Счетчики для суммарного балла по всем предметам
    V$CN = 0;
    V$CU = 0;
    V$CS = 0;
    V$CD = 0;

    -- 10-12 классы - исходно 5-12, но в общей школе нет профилей
    -- Достаем текущий профиль
    IF(V$GRADE_ID IN (46, 47, 48)) THEN
    BEGIN
      SELECT FIRST 1 V3112.LISTVAL_ID
      FROM PERSON_MOVEMENTS M
      JOIN LINKS L256 ON L256.OBJ_ID = M.GROUP_ID AND L256.OBJ_TYPE_ID = 256 AND L256.PARENT_TYPE_ID = 54 AND L256.DATE_DEL IS NULL
      JOIN LINKS LP400 ON LP400.OBJ_ID = L256.PARENT_ID AND LP400.PARENT_TYPE_ID = 400 AND LP400.DATE_DEL IS NULL
      JOIN VALL V3112 ON V3112.OBJ_ID = LP400.PARENT_ID AND V3112.PARAM_ID = 3112 AND V3112.IS_DEL = 0
      WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :V$STUDENT_ID AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :V$DATE)
      INTO :V$PROFILE_ID;
    END

    FOR
      SELECT J.SUBJECT_ID, SUM(J.HOURS), SUM(J.WEEKS)
      FROM PERSON_MOVEMENTS M
      JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.GRADE_ID = M.GROUP_ID AND J.JOURNAL_TYPE = 0
      WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :V$STUDENT_ID AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :V$DATE)
      GROUP BY 1
      INTO :V$SUBJECT_ID, :V$HOURS, :V$WEEKS
    DO
    BEGIN

      N = NULL;
      V$U = NULL;
      V$S = NULL;
      V$D = NULL;

      SELECT COUNT(*), SUM(MT.MARK_COST * MT.MARK_SCALE * CT.DEFAULT_COST), SUM(MT.MARK_COST), SUM(CT.DEFAULT_COST)
      FROM CJ2_JOURNAL J
      JOIN CJ2_JOURNAL_LESSONS L ON L.DATE_DEL IS NULL AND L.CJ_ID = J.OBJ_ID AND L.LESSON_DATE >= :V$DATE AND L.LESSON_DATE <= :I$DATE
      JOIN CJ2_CONTROL C ON C.DATE_DEL IS NULL AND C.LESSON_ID = L.OBJ_ID AND C.CONTROL_TYPE_ID <> 0
      JOIN CJ2_CONTROL_TYPE CT ON CT.CONTROL_TYPE_ID = C.CONTROL_TYPE_ID
      JOIN CJ2_MARK M ON M.DATE_DEL IS NULL AND M.CONTROL_ID = C.CONTROL_ID AND M.STUDENT_ID = :V$STUDENT_ID
      JOIN CJ2_MARK_TYPE MT ON MT.MARK_TYPE_ID = M.MARK_TYPE_ID
      WHERE J.DATE_DEL IS NULL AND J.JOURNAL_TYPE = 0 AND J.SUBJECT_ID = :V$SUBJECT_ID
      INTO :N, :V$U, :V$S, :V$D;

      IF(N IS NULL) THEN N = 0;
      IF(V$U IS NULL) THEN V$U = 0;
      IF(V$S IS NULL) THEN V$S = 0;
      IF(V$D IS NULL) THEN V$D = 0;

      V$CN = V$CN + N;
      V$CU = V$CU + V$U;
      V$CS = V$CS + V$S;
      V$CD = V$CD + V$D;

      V$TN = V$TN + N;
      V$TS = V$TS + V$S;
      IF(N > 0) THEN V$M = V$S / N; ELSE V$M = NULL;

      IF(N >= 3 AND V$D > 0) THEN
      BEGIN
        UPDATE OR INSERT INTO CJ2_STUDENT_RATING
        (STUDENT_ID, SUBJECT_ID, PERIOD_ID, PERIOD_TYPE_ID, RATE_DATE, RATE_VALUE, VAL_TOP, VAL_BOTTOM)
        VALUES (:V$STUDENT_ID, :V$SUBJECT_ID, :V$PERIOD, :V$PERIOD_TYPE, :I$DATE, :V$U / :V$D, :V$U, :V$D)
        MATCHING (STUDENT_ID, SUBJECT_ID, RATE_DATE);
      END

      IF(V$D > 0 AND V$S / V$D < 4) THEN V$R4 = 0;

      -- Подсчет предметов где есть оценки по профилю, а также расхождение средних отметок
      IF(V$GRADE_ID IN (46, 47, 48) AND N > 2) THEN
      BEGIN
        -- Гуманитарный
        IF((V$PROFILE_ID = 10952 AND V$SUBJECT_ID IN (185, 187, 194, 174, 3151, 38154, 3150)) OR
        -- Социально-экономический
        (V$PROFILE_ID = 10953 AND V$SUBJECT_ID IN (194, 32843, 3138, 174, 3151, 38154, 3150, 3139, 32840)) OR
        -- Физико-математический
        (V$PROFILE_ID = 12746 AND V$SUBJECT_ID IN (198, 190, 172, 3149, 38150, 173)) OR
        -- Информационной-технологический
        (V$PROFILE_ID = 12743 AND V$SUBJECT_ID IN (5518, 190, 172, 3149, 38150, 173)) OR
        -- Химико-биологический
        (V$PROFILE_ID = 12749 AND V$SUBJECT_ID IN (199, 197, 177, 3160)))
        THEN
        BEGIN
          V$PROFCNT = V$PROFCNT + 1;

          IF((V$S / N) - V$M >= 0.5) THEN V$M = V$M + 1; -- коррекция среднего балла в большую сторону
          IF(V$M < V$MINM) THEN V$MINM = V$M;
          IF(V$M > V$MAXM) THEN V$MAXM = V$M;
        END
      END

      -- Достаточность количества отметок
      IF(V$GRADE_ID <> 37 AND V$WEEKS > 0) THEN
      BEGIN
        V$HOURS = V$HOURS / V$WEEKS;
        IF((V$HOURS > 1 AND N < 5) OR N < 3) THEN V$F212 = 0;
      END

      -- Пятиклассники - адаптированность
      IF(V$GRADE_ID = 41 AND V$SUBJECT_ID IN (185, 190)) THEN
      BEGIN
        -- Средняя оценка прошлого года - только 5-балльная
        V$S = NULL;
        SELECT AVG(LV.COST / 10)
        FROM VALM M
        JOIN LISTVALS LV ON LV.LISTVAL_ID = M.MARKVAL_ID
        JOIN LISTVALS LVP ON LVP.LISTVAL_ID = M.YEAR_ID AND LVP.COST = EXTRACT(YEAR FROM :V$START_DATE) - 1
        WHERE M.PUPIL_ID = :V$STUDENT_ID AND M.SUBJECT_ID = :V$SUBJECT_ID AND M.MARKTYPE_ID IN (3002, 3003, 3004, 3005)
        INTO :V$S;

        -- Если нет четвертных - смотрим какие есть
        IF(V$S IS NULL) THEN 
        SELECT AVG(LV.COST / 10)
        FROM VALM M
        JOIN LISTVALS LV ON LV.LISTVAL_ID = M.MARKVAL_ID
        JOIN LISTVALS LVP ON LVP.LISTVAL_ID = M.YEAR_ID AND LVP.COST = EXTRACT(YEAR FROM :V$START_DATE) - 1
        WHERE M.PUPIL_ID = :V$STUDENT_ID AND M.SUBJECT_ID = :V$SUBJECT_ID
        INTO :V$S;

        IF(V$S IS NOT NULL) THEN
        BEGIN
          IF(V$M < V$S) THEN V$F5 = 0;
          V$C5 = V$C5 + 1;
        END
      END

      -- Подсчет двоек
      IF(V$GRADE_ID IN (42, 43, 44) AND V$SUBJECT_ID IN (185, 190, 172)) THEN
      BEGIN
        N = 0;
        FOR
          SELECT MT.MARK_COST
          FROM CJ2_JOURNAL J
          JOIN CJ2_JOURNAL_LESSONS L ON L.DATE_DEL IS NULL AND L.CJ_ID = J.OBJ_ID AND L.LESSON_DATE >= :V$DATE AND L.LESSON_DATE <= :I$DATE
          JOIN CJ2_CONTROL C ON C.DATE_DEL IS NULL AND C.LESSON_ID = L.OBJ_ID AND C.CONTROL_TYPE_ID <> 0
          JOIN CJ2_MARK M ON M.DATE_DEL IS NULL AND M.CONTROL_ID = C.CONTROL_ID AND M.STUDENT_ID = :V$STUDENT_ID
          JOIN CJ2_MARK_TYPE MT ON MT.MARK_TYPE_ID = M.MARK_TYPE_ID
          WHERE J.DATE_DEL IS NULL AND J.JOURNAL_TYPE = 0 AND J.SUBJECT_ID = :V$SUBJECT_ID
          ORDER BY L.LESSON_DATE, L.LESSON_NUM
          INTO :V$U
        DO
        BEGIN
          IF(V$U < 2.5) THEN
          BEGIN
            N = N + 1;
            IF(N = 3) THEN V$S2 = 1;
          END
          ELSE
            N = 0;
        END
      END

    END

    -- Системная неуспеваемость для 6-7-8 классов
    -- подсчитываем количество двоек
    IF(V$GRADE_ID IN (42, 43, 44)) THEN
    BEGIN
      V$N678 = V$N678 + 1;
      IF(V$S2 <> 0) THEN V$NB678 = V$NB678 + 1;
    END

    -- Пятиклассники - адаптированность
    IF(V$GRADE_ID = 41) THEN
    BEGIN
      V$TN5 = V$TN5 + 1;
      IF(V$C5 > 0 AND V$F5 = 1) THEN V$N5 = V$N5 + 1;
    END

    -- 10-12 классы - исходно 5-12, но в общей школе нет профилей
    IF(V$GRADE_ID IN (46, 47, 48) AND V$PROFCNT >= 2) THEN
    BEGIN
      V$NOBJ = V$NOBJ + 1;
    END

    IF(V$GRADE_ID <> 37) THEN V$N212 = V$N212 + 1;
    IF(V$GRADE_ID <> 37 AND V$F212 <> 0) THEN V$M212 = V$M212 + 1;
    IF(V$GRADE_ID <> 37 AND V$MAXM >= 0 AND ABS(V$MAXM - V$MINM) <= 1) THEN V$D212 = V$D212 + 1;

    -- Средний балл по всем предметам
    IF(V$CN >= 3 AND V$CD > 0) THEN
    BEGIN
      UPDATE OR INSERT INTO CJ2_STUDENT_RATING
      (STUDENT_ID, SUBJECT_ID, PERIOD_ID, PERIOD_TYPE_ID, RATE_DATE, RATE_VALUE)
      VALUES (:V$STUDENT_ID, NULL, :V$PERIOD, :V$PERIOD_TYPE, :I$DATE, :V$CU / :V$CD)
      MATCHING (STUDENT_ID, SUBJECT_ID, RATE_DATE);
    END

    IF(V$CN > 0) THEN
    BEGIN
      V$TT = V$TT + 1;
      IF(V$R4 = 1) THEN V$TT4 = V$TT4 + 1;

      -- Подсчитываем обученность
      SELECT SUM(IIF(MT.MARK_TYPE_ID IN (103, 104), 1, 0)), SUM(IIF(MT.MARK_COST <= 2, 1, 0)), SUM(IIF(MT.MARK_COST > 2 AND MT.MARK_COST * MT.MARK_SCALE <= 3, 1, 0)),
        SUM(IIF(MT.MARK_COST > 3 AND MT.MARK_COST * MT.MARK_SCALE <= 4, 1, 0)), SUM(IIF(MT.MARK_COST > 4, 1, 0))
      FROM CJ2_MARK M
      JOIN CJ2_CONTROL C ON C.DATE_DEL IS NULL AND C.CONTROL_ID = M.CONTROL_ID AND C.CONTROL_TYPE_ID <> 0
      JOIN CJ2_JOURNAL_LESSONS L ON L.DATE_DEL IS NULL AND L.OBJ_ID = C.LESSON_ID AND L.LESSON_DATE >= :V$DATE AND L.LESSON_DATE <= :I$DATE
      JOIN CJ2_CONTROL_TYPE CT ON CT.CONTROL_TYPE_ID = C.CONTROL_TYPE_ID
      JOIN CJ2_MARK_TYPE MT ON MT.MARK_TYPE_ID = M.MARK_TYPE_ID
      JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.JOURNAL_TYPE = 0 AND J.OBJ_ID = L.CJ_ID
      WHERE M.DATE_DEL IS NULL AND M.STUDENT_ID = :V$STUDENT_ID
      INTO :V$SX, :V$S2, :V$S3, :V$S4, :V$S5;
      V$S2 = V$S2 - V$SX;

      V$TTG = V$TTG + V$S2 * 0.16 + V$S3 * 0.36 + V$S4 * 0.64 + V$S5 + V$SX * 0.07;
      V$TTTG = V$TTTG + V$S2 + V$S3 + V$S4 + V$S5 + V$SX;
      V$M45 = V$M45 + V$S4 + V$S5;
    END

  END

  -- Расставляем места в рейтинге по классам
  FOR
    SELECT DISTINCT L9.OBJ_ID
    FROM LINKS L9
    WHERE L9.PARENT_TYPE_ID = 8 AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
    INTO :V$CLASS_ID
  DO
  BEGIN

    N = 0;

    FOR
      SELECT DISTINCT CAST(R.RATE_VALUE AS NUMERIC(18, 1))
      FROM LINKS L10
      JOIN CJ2_STUDENT_RATING R ON R.DATE_DEL IS NULL AND R.STUDENT_ID = L10.OBJ_ID AND R.SUBJECT_ID IS NULL AND R.RATE_DATE = :I$DATE
      WHERE L10.PARENT_ID = :V$CLASS_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      ORDER BY 1 DESC
      INTO :V$U
    DO
    BEGIN

      N = N + 1;

      FOR
        SELECT L10.OBJ_ID
        FROM LINKS L10
        JOIN CJ2_STUDENT_RATING R ON R.DATE_DEL IS NULL AND R.STUDENT_ID = L10.OBJ_ID AND R.SUBJECT_ID IS NULL
          AND R.RATE_DATE = :I$DATE AND CAST(R.RATE_VALUE AS NUMERIC(18, 1)) = CAST(:V$U AS NUMERIC(18, 1))
        WHERE L10.PARENT_ID = :V$CLASS_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        INTO :V$STUDENT_ID
      DO
      BEGIN
        UPDATE CJ2_STUDENT_RATING R
        SET R.RATE_INDEX = :N
        WHERE R.DATE_DEL IS NULL AND R.STUDENT_ID = :V$STUDENT_ID AND R.SUBJECT_ID IS NULL AND R.RATE_DATE = :I$DATE;
      END

    END

  END

  -- Подсчитываем своевременность выдачи ДЗ
  V$LN = 0;
  V$LNG = 0;
  V$PREV_ID = 0;
  FOR
    SELECT J.OBJ_ID --, J.PERIOD_ID
    FROM CJ2_JOURNAL J
    WHERE J.DATE_DEL IS NULL AND J.STAGE_INDEX <> 37 AND J.JOURNAL_TYPE = 0 AND J.YEAR_ID = :V$YEAR_ID
    INTO :V$CLASS_ID
  DO
  BEGIN
    N = 0;
    SELECT COUNT(DISTINCT L.OBJ_ID)
    FROM CJ2_JOURNAL J
    JOIN CJ2_JOURNAL_LESSONS L ON L.DATE_DEL IS NULL AND L.CJ_ID = J.OBJ_ID AND L.LESSON_DATE >= :V$DATE AND L.LESSON_DATE <= :I$DATE
    WHERE J.OBJ_ID = :V$CLASS_ID
    INTO :N;
    V$LN = V$LN + N;

    N2 = 0;
    SELECT COUNT(DISTINCT L.OBJ_ID)
    FROM CJ2_JOURNAL J
    JOIN CJ2_JOURNAL_LESSONS L ON L.DATE_DEL IS NULL AND L.CJ_ID = J.OBJ_ID AND L.LESSON_DATE >= :V$DATE AND L.LESSON_DATE <= :I$DATE
    JOIN CJ2_LESSON_HISTORY H ON H.DATE_DEL IS NULL AND H.LESSON_ID = L.OBJ_ID AND H.STATE_ID > 0 AND H.DATE_ADD >= DATEADD(-7 DAY TO L.LESSON_DATE)
      AND H.DATE_ADD <= L.LESSON_DATE || ' 13:00:00'
    WHERE J.OBJ_ID = :V$CLASS_ID
    INTO :N2;
    V$LNG = V$LNG + N2;
  END

  -- Статистика по школе сохраняется с ID школы и левыми SUBJECT_ID
  -- GroupCount
  SELECT COUNT(DISTINCT L9.PARENT_ID)
  FROM LINKS L9
  WHERE L9.PARENT_TYPE_ID = 9 AND L9.OBJ_TYPE_ID = 10 AND L9.DATE_DEL IS NULL
  INTO :N;

  UPDATE OR INSERT INTO CJ2_STUDENT_RATING
  (STUDENT_ID, SUBJECT_ID, RATE_DATE, RATE_VALUE)
  VALUES (:V$OU_ID, 0, :I$DATE, :N)
  MATCHING (STUDENT_ID, SUBJECT_ID, RATE_DATE);

  -- AverageMark
  IF(V$TN > 0) THEN
  UPDATE OR INSERT INTO CJ2_STUDENT_RATING
  (STUDENT_ID, SUBJECT_ID, RATE_DATE, RATE_VALUE)
  VALUES (:V$OU_ID, 1, :I$DATE, :V$TS / :V$TN)
  MATCHING (STUDENT_ID, SUBJECT_ID, RATE_DATE);

  -- KnowledgeQuality
  IF(V$TT > 0) THEN
  UPDATE OR INSERT INTO CJ2_STUDENT_RATING
  (STUDENT_ID, SUBJECT_ID, RATE_DATE, RATE_VALUE)
  VALUES (:V$OU_ID, 2, :I$DATE, (100.0 * :V$TT4) / :V$TT)
  MATCHING (STUDENT_ID, SUBJECT_ID, RATE_DATE);

  -- TrainingGrade
  IF(V$TTTG > 0) THEN
  UPDATE OR INSERT INTO CJ2_STUDENT_RATING
  (STUDENT_ID, SUBJECT_ID, RATE_DATE, RATE_VALUE)
  VALUES (:V$OU_ID, 3, :I$DATE, (100.0 * :V$TTG) / :V$TTTG)
  MATCHING (STUDENT_ID, SUBJECT_ID, RATE_DATE);

  -- PoorGrades
  IF(V$N678 > 0) THEN
  UPDATE OR INSERT INTO CJ2_STUDENT_RATING
  (STUDENT_ID, SUBJECT_ID, RATE_DATE, RATE_VALUE)
  VALUES (:V$OU_ID, 4, :I$DATE, (100.0 * :V$NB678) / :V$N678)
  MATCHING (STUDENT_ID, SUBJECT_ID, RATE_DATE);

  -- AcademicPerformance
  IF(V$TTTG > 0) THEN
  UPDATE OR INSERT INTO CJ2_STUDENT_RATING
  (STUDENT_ID, SUBJECT_ID, RATE_DATE, RATE_VALUE)
  VALUES (:V$OU_ID, 5, :I$DATE, (100.0 * :V$M45) / :V$TTTG)
  MATCHING (STUDENT_ID, SUBJECT_ID, RATE_DATE);

  -- StudentsFifthParallel
  UPDATE OR INSERT INTO CJ2_STUDENT_RATING
  (STUDENT_ID, SUBJECT_ID, RATE_DATE, RATE_VALUE)
  VALUES (:V$OU_ID, 6, :I$DATE, :V$TN5)
  MATCHING (STUDENT_ID, SUBJECT_ID, RATE_DATE);

  -- AdaptedStudents - единицы, а не проценты. Пока идет 0
  UPDATE OR INSERT INTO CJ2_STUDENT_RATING
  (STUDENT_ID, SUBJECT_ID, RATE_DATE, RATE_VALUE)
  VALUES (:V$OU_ID, 7, :I$DATE, :V$N5)
  MATCHING (STUDENT_ID, SUBJECT_ID, RATE_DATE);

  -- StudentsForObjectivity - единицы, а не проценты
  UPDATE OR INSERT INTO CJ2_STUDENT_RATING
  (STUDENT_ID, SUBJECT_ID, RATE_DATE, RATE_VALUE)
  VALUES (:V$OU_ID, 8, :I$DATE, :V$NOBJ)
  MATCHING (STUDENT_ID, SUBJECT_ID, RATE_DATE);

  -- StudentsWithObjectiveMarks 
  UPDATE OR INSERT INTO CJ2_STUDENT_RATING
  (STUDENT_ID, SUBJECT_ID, RATE_DATE, RATE_VALUE)
  VALUES (:V$OU_ID, 9, :I$DATE, :V$D212)
  MATCHING (STUDENT_ID, SUBJECT_ID, RATE_DATE);

  -- Students2to12parallel - единицы, а не проценты
  UPDATE OR INSERT INTO CJ2_STUDENT_RATING
  (STUDENT_ID, SUBJECT_ID, RATE_DATE, RATE_VALUE)
  VALUES (:V$OU_ID, 10, :I$DATE, :V$N212)
  MATCHING (STUDENT_ID, SUBJECT_ID, RATE_DATE);

  -- StudentsMarksAccumulation - единицы, а не проценты
  UPDATE OR INSERT INTO CJ2_STUDENT_RATING
  (STUDENT_ID, SUBJECT_ID, RATE_DATE, RATE_VALUE)
  VALUES (:V$OU_ID, 11, :I$DATE, :V$M212)
  MATCHING (STUDENT_ID, SUBJECT_ID, RATE_DATE);

  -- TimelyDz
  IF(V$LN > 0) THEN
  UPDATE OR INSERT INTO CJ2_STUDENT_RATING
  (STUDENT_ID, SUBJECT_ID, RATE_DATE, RATE_VALUE)
  VALUES (:V$OU_ID, 12, :I$DATE, (100.0 * :V$LNG) / :V$LN)
  MATCHING (STUDENT_ID, SUBJECT_ID, RATE_DATE);

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_USA_UPDATE (
    I$CONTROL_ID BIGINT)
AS
declare variable V$CONTROL_ID bigint;
declare variable P integer;
declare variable S varchar(400);
declare variable V$N integer;
declare variable V$ID bigint;
declare variable V$SID varchar(30);
declare variable V$G1 bigint;
declare variable V$G2 bigint;
declare variable V$G3 bigint;
declare variable V$PID bigint;
begin

  -- На пополнение
  FOR
    SELECT C2.CONTROL_ID, C2.EXT_ID
    FROM CJ2_CONTROL C
    JOIN CJ2_JOURNAL_LESSONS L ON L.OBJ_ID = C.LESSON_ID
    JOIN CJ2_CONTROL C2 ON C2.LESSON_ID = L.OBJ_ID AND C2.DATE_DEL IS NULL AND C2.CONTROL_TYPE_ID = 30000
    WHERE C.CONTROL_ID = :I$CONTROL_ID
    INTO :V$CONTROL_ID, :S
  DO
  BEGIN
    WHILE(CHAR_LENGTH(S) > 0) DO
    BEGIN
      P = POSITION(',' IN S);
      IF(P <= 0) THEN P = CHAR_LENGTH(S) + 1;
      V$ID = SUBSTRING(S FROM 1 FOR P - 1);
      S = SUBSTRING(S FROM P + 1);

      V$N = NULL;
      SELECT FIRST 1 C.IS_DEL
      FROM CJ2_LESSON_UUD C
      WHERE C.CONTROL_ID = :V$CONTROL_ID AND C.USA_ID = :V$ID
      INTO :V$N;

      IF(V$N = 1) THEN
      BEGIN
        UPDATE CJ2_LESSON_UUD SET IS_DEL = 0, DATE_MODIFY = CURRENT_TIMESTAMP WHERE CONTROL_ID = :V$CONTROL_ID AND USA_ID = :V$ID;
      END
      ELSE IF(V$N IS NULL) THEN
      BEGIN
        V$G1 = V$ID;
        V$PID = NULL;
        SELECT LV.PARENT_ID
        FROM LISTVALS LV
        WHERE LV.LISTVAL_ID = :V$G1 AND LV.LIST_ID = 330
        INTO :V$PID;

        -- Родитель есть, значит мы точно не корневой раздел
        IF(V$PID IS NOT NULL) THEN
        BEGIN
          V$G2 = V$G1;
          V$G1 = V$PID;
          V$PID = NULL;
          SELECT LV.PARENT_ID
          FROM LISTVALS LV
          WHERE LV.LISTVAL_ID = :V$G1 AND LV.LIST_ID = 330
          INTO :V$PID;

          -- Если и сейчас есть родитель, то мы точно корневой раздел
          IF(V$PID IS NOT NULL) THEN
          BEGIN
            V$G3 = V$G2;
            V$G2 = V$G1;
            V$G1 = V$PID;
          END
        END

        INSERT INTO CJ2_LESSON_UUD (CONTROL_ID, USA_ID, GROUP_ID, SUBGROUP_ID, ITEM_ID) VALUES (:V$CONTROL_ID, :V$ID, :V$G1, :V$G2, :V$G3);
      END
    END
  END

  -- На удаление
  FOR
    SELECT IIF(C.DATE_DEL IS NULL, C.EXT_ID, ''), U.USA_ID
    FROM CJ2_CONTROL C
    JOIN CJ2_LESSON_UUD U ON U.CONTROL_ID = C.CONTROL_ID AND U.IS_DEL = 0
    WHERE C.CONTROL_ID = :I$CONTROL_ID
    ORDER BY 2
    INTO :S, :V$ID
  DO
  BEGIN
    V$SID = V$ID;

    V$N = 0;
    IF(S = V$SID) THEN V$N = 1;
    ELSE IF(LEFT(S, CHAR_LENGTH(V$SID) + 1) = V$SID || ',') THEN V$N = 1;
    ELSE IF(RIGHT(S, CHAR_LENGTH(V$SID) + 1) = ',' || V$SID) THEN V$N = 1;
    ELSE IF(POSITION((',' || V$SID || ',') IN S) > 0) THEN V$N = 1;

    IF(V$N = 0) THEN UPDATE CJ2_LESSON_UUD SET IS_DEL = 1, DATE_MODIFY = CURRENT_TIMESTAMP WHERE CONTROL_ID = :I$CONTROL_ID AND USA_ID = :V$ID;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_WEEKDAYS (
    I$GRADE_ID BIGINT = null)
RETURNS (
    WEEK_DAYS INTEGER)
AS
begin

  -- Без параметров возвращает длительность максимальной учебной недели (5 или 6 дней)
  -- С указанным ID коллектива возвращает длительность недели в данном конкретном коллективе, пока не сделано

  SELECT MAX(IIF(V2837.LISTVAL_ID = 11718, 5, 6))
  FROM LINKS L2
  JOIN LINKS L69 ON L69.PARENT_ID = L2.OBJ_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL
  JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
  JOIN LINKS L50 ON L50.PARENT_ID = L57.OBJ_ID AND L50.OBJ_TYPE_ID = 50 AND L50.DATE_DEL IS NULL
  JOIN LINKS L54 ON L54.PARENT_ID = L50.OBJ_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
  JOIN VALL V2837 ON V2837.OBJ_ID = L54.OBJ_ID AND V2837.PARAM_ID = 2837 AND V2837.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :WEEK_DAYS;

  -- Если ничего не указано, то 6-дневка
  IF(WEEK_DAYS IS NULL) THEN WEEK_DAYS = 6;

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ2_WIZARD_DATA (
    I$TYPE SMALLINT,
    I$YEAR_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$OU_LICENCE_TYPE CHAR(1);
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$STAGE_ID BIGINT;
DECLARE VARIABLE V$ROW_ID BIGINT;
DECLARE VARIABLE V$STAGE_NAME VARCHAR(200);
DECLARE VARIABLE V$SUBJECT_ID BIGINT;
DECLARE VARIABLE V$JOURNAL_ID BIGINT;
DECLARE VARIABLE V$TEACHER_ID BIGINT;
DECLARE VARIABLE V$GRADE_ID BIGINT;
DECLARE VARIABLE V$GRADE_TYPE_ID BIGINT;
DECLARE VARIABLE V$STAGE_INDEX BIGINT;
DECLARE VARIABLE V$YEAR INTEGER;
DECLARE VARIABLE V$YEAR_ID BIGINT;
DECLARE VARIABLE V$STM SMALLINT;
DECLARE VARIABLE V$WEEKS INTEGER;
DECLARE VARIABLE V$TYPE BIGINT;
DECLARE VARIABLE V$REAL_SUBJ BIGINT;
DECLARE VARIABLE V$Y INTEGER;
DECLARE VARIABLE V$YC1 VARCHAR(20);
DECLARE VARIABLE V$YC2 VARCHAR(20);
DECLARE VARIABLE V$YC3 VARCHAR(20);
DECLARE VARIABLE V$YC4 VARCHAR(20);
DECLARE VARIABLE S VARCHAR(1000);
DECLARE VARIABLE N FLOAT;
DECLARE VARIABLE V$OU_ID BIGINT;
DECLARE VARIABLE V$HAS_DO SMALLINT;
DECLARE VARIABLE V$HAS_OO SMALLINT;
DECLARE VARIABLE V$HAS_SPO SMALLINT;
DECLARE VARIABLE V$HAS_PO SMALLINT;
DECLARE VARIABLE V$SORT_ORDER BIGINT;
DECLARE VARIABLE V$MASTER_STAGE BIGINT;
begin

  V$OU_LICENCE_TYPE = (SELECT STATUS FROM OU_LICENCE_TYPE);

  TAG_NAME = 'type_id';
  VAL = I$TYPE;
  SUSPEND;

  TAG_NAME = 'ou_type';
  VAL = V$OU_LICENCE_TYPE;
  SUSPEND;

  IF(V$OU_LICENCE_TYPE = 'O') THEN V$MASTER_STAGE = 2141;

  -- Учебный год
  TAG_NAME = 'year_id';
  VAL = I$YEAR_ID;
  SUSPEND;

  SELECT FIRST 1 L2.OBJ_ID, LV.COST, LV.LISTVAL_ID
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$OU_ID, :V$YEAR, :V$YEAR_ID;

  SELECT LV.COST
  FROM LISTVALS LV
  WHERE LV.LISTVAL_ID = :I$YEAR_ID
  INTO :V$Y;

  V$YC1 = V$Y || '/' || (V$Y + 1); --- XXXX/XXXX
  V$YC2 = V$Y || '/' || SUBSTRING(V$Y + 1 FROM 3); --- XXXX/XX
  V$YC3 = V$Y || '-' || (V$Y + 1); --- XXXX-XXXX
  V$YC4 = V$Y || '-' || SUBSTRING(V$Y + 1 FROM 3); --- XXXX-XX

  V$HAS_DO = 0;
  V$HAS_OO = 0;
  V$HAS_SPO = 0;
  V$HAS_PO = 0;
  SELECT FIRST 1 1
  FROM LINKS L472
  JOIN VALL V3327 ON V3327.OBJ_ID = L472.OBJ_ID AND V3327.PARAM_ID = 3327 AND V3327.IS_DEL = 0 AND V3327.LISTVAL_ID IN (21, 3263, 3264)
  WHERE L472.PARENT_ID = :V$OU_ID AND L472.OBJ_TYPE_ID = 472 AND L472.DATE_DEL IS NULL
  INTO :V$HAS_DO;

  SELECT FIRST 1 1
  FROM LINKS L472
  JOIN VALL V3327 ON V3327.OBJ_ID = L472.OBJ_ID AND V3327.PARAM_ID = 3327 AND V3327.IS_DEL = 0 AND V3327.LISTVAL_ID IN (22, 26, 27)
  WHERE L472.PARENT_ID = :V$OU_ID AND L472.OBJ_TYPE_ID = 472 AND L472.DATE_DEL IS NULL
  INTO :V$HAS_OO;

  SELECT FIRST 1 1
  FROM LINKS L472
  JOIN VALL V3327 ON V3327.OBJ_ID = L472.OBJ_ID AND V3327.PARAM_ID = 3327 AND V3327.IS_DEL = 0 AND V3327.LISTVAL_ID IN (28, 29, 13129)
  WHERE L472.PARENT_ID = :V$OU_ID AND L472.OBJ_TYPE_ID = 472 AND L472.DATE_DEL IS NULL
  INTO :V$HAS_SPO;

  SELECT FIRST 1 1
  FROM LINKS L472
  JOIN VALL V3327 ON V3327.OBJ_ID = L472.OBJ_ID AND V3327.PARAM_ID = 3327 AND V3327.IS_DEL = 0 AND V3327.LISTVAL_ID IN (13129, 13131)
  WHERE L472.PARENT_ID = :V$OU_ID AND L472.OBJ_TYPE_ID = 472 AND L472.DATE_DEL IS NULL
  INTO :V$HAS_PO;

  TAG_NAME = 'years::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT LISTVAL_ID, VAL
    FROM LISTVALS_LIST(29)
    WHERE IS_DEL = 0 AND COST <= :V$YEAR + 1
    ORDER BY COST DESC
    INTO :V$OBJ_ID, :S
  DO
  BEGIN
    TAG_NAME = 'years:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'years:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'years:r:value';
    VAL = S;
    SUSPEND;
  END

  -- Список классов (групп)
  TAG_NAME = 'classes::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT V49.LISTVAL_ID, L9.OBJ_ID, C.CAPTION
    FROM LINKS L7
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
    -- фильтровать по этапу исходя из типа журнала !!!
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
    LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C ON 1 = 1
    WHERE L7.PARENT_TYPE_ID = 2 AND L7.OBJ_TYPE_ID IN (7, 502) AND L7.DATE_DEL IS NULL
    INTO :V$STAGE_ID, :V$OBJ_ID, :S
  DO
  BEGIN
    TAG_NAME = 'classes:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'classes:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'classes:r:name';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'classes:r:stage_id';
    VAL = V$STAGE_ID;
    SUSPEND;
  END

  -- Дерево данных для журналов
  TAG_NAME = 'items::json&colon;array';
  VAL = 1;
  SUSPEND;

  IF(I$TYPE = 0) THEN
  BEGIN

    -- Общеобразовательные (ВД не ставится только в колледжах)
    -- УП -> предмет -> ...
    FOR
      SELECT L400.OBJ_ID, V1594.LISTVAL_ID, R.VAL, C.CAPTION
      FROM LINKS L2
      JOIN LINKS L69 ON L69.PARENT_ID = L2.OBJ_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL
      JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
      JOIN VALL V1594 ON V1594.OBJ_ID = L57.OBJ_ID AND V1594.PARAM_ID = 1594 AND V1594.IS_DEL = 0
      -- В СПО игнорируем год публикации
      LEFT JOIN VALI V3115 ON V3115.OBJ_ID = L57.OBJ_ID AND V3115.PARAM_ID = 3115 AND V3115.IS_DEL = 0 -- год публикации
      JOIN LISTVALS LV ON LV.LISTVAL_ID = V1594.LISTVAL_ID
      JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
      JOIN LINKS L400 ON L400.PARENT_ID = L57.OBJ_ID AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL
      LEFT JOIN VALL V3022 ON V3022.OBJ_ID = L400.OBJ_ID AND V3022.PARAM_ID = 3022 AND V3022.IS_DEL = 0 -- не ВД
      JOIN VALL V3013 ON V3013.OBJ_ID = L400.OBJ_ID AND V3013.PARAM_ID = 3013 AND V3013.IS_DEL = 0 AND V3013.LISTVAL_ID = 11715 -- утвержден
      LEFT JOIN OBJECT_CAPTION_GET(L400.OBJ_ID) C ON 1 = 1
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
        AND (V3022.LISTVAL_ID = 3 OR (:V$OU_LICENCE_TYPE = 'C' AND V3022.LISTVAL_ID IS NULL))
        AND (:V$OU_LICENCE_TYPE = 'C' OR V3115.VAL = :V$Y OR POSITION(:V$YC1 IN C.CAPTION) > 0 OR POSITION(:V$YC2 IN C.CAPTION) > 0 OR POSITION(:V$YC3 IN C.CAPTION) > 0 OR POSITION(:V$YC4 IN C.CAPTION) > 0)
      ORDER BY 2, 4
      INTO :V$OBJ_ID, :V$STAGE_ID, :V$STAGE_NAME, :S
    DO
    BEGIN

      TAG_NAME = 'items:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'items:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'items:r:stage_id';
      VAL = V$STAGE_ID;
      SUSPEND;
      TAG_NAME = 'items:r:stage_name';
      VAL = V$STAGE_NAME;
      SUSPEND;
      TAG_NAME = 'items:r:name';
      VAL = S;
      SUSPEND;

      -- Этапы
      TAG_NAME = 'items:r:stages::json&colon;array';
      VAL = 1;
      SUSPEND;
      FOR
         SELECT V381.LISTVAL_ID, R.VAL, V382.VAL
         FROM LINKS L54
         JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
         JOIN LISTVALS LV ON LV.LISTVAL_ID = V381.LISTVAL_ID
         JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
         JOIN VALI V382 ON V382.OBJ_ID = L54.OBJ_ID AND V382.PARAM_ID = 382 AND V382.IS_DEL = 0
         WHERE L54.PARENT_ID = :V$OBJ_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
         ORDER BY LV.COST
         INTO :V$STAGE_ID, :S, :V$WEEKS
      DO
      BEGIN
        TAG_NAME = 'items:r:stages:r';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'items:r:stages:r:id';
        VAL = V$STAGE_ID;
        SUSPEND;
        TAG_NAME = 'items:r:stages:r:name';
        VAL = S;
        SUSPEND;
        TAG_NAME = 'items:r:stages:r:weeks';
        VAL = V$WEEKS;
        SUSPEND;

        TAG_NAME = 'items:r:stages:r:groups::json&colon;array';
        VAL = 1;
        SUSPEND;
        FOR
          SELECT L256.OBJ_ID, C.CAPTION
          FROM LINKS L54
          JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0 AND V381.LISTVAL_ID = :V$STAGE_ID
          JOIN LINKS L256 ON L256.PARENT_ID = L54.OBJ_ID AND L256.OBJ_TYPE_ID = 256 AND L256.DATE_DEL IS NULL
          LEFT JOIN OBJECT_CAPTION_GET(L256.OBJ_ID) C ON 1 = 1
          WHERE L54.PARENT_ID = :V$OBJ_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
            AND ((:I$YEAR_ID = :V$YEAR_ID AND POSITION('будущий' IN C.CAPTION) <= 0) OR (:I$YEAR_ID <> :V$YEAR_ID AND POSITION('будущий' IN C.CAPTION) > 0))
          ORDER BY 2
          INTO :V$GRADE_ID, :S
        DO
        BEGIN
          TAG_NAME = 'items:r:stages:r:groups:r';
          VAL = NULL;
          SUSPEND;
          TAG_NAME = 'items:r:stages:r:groups:r:id';
          VAL = V$GRADE_ID;
          SUSPEND;
          TAG_NAME = 'items:r:stages:r:groups:r:name';
          VAL = S;
          SUSPEND;
        END
      END

      -- Список предметов в УП
      -- В СПО не показываем предметы итоговой аттестации
      TAG_NAME = 'items:r:subjects::json&colon;array';
      VAL = 1;
      SUSPEND;
      FOR
        SELECT DISTINCT S.SUBJECT_ID, C.CAPTION, S.IS_STM, V3158.LISTVAL_ID
        FROM PLAN_SUBJECTS S
        LEFT JOIN PLAN_SUBJECTS P ON P.OBJ_ID = S.PARENT_ID
        LEFT JOIN OBJECT_CAPTION_GET(S.SUBJECT_ID) C ON 1 = 1
        LEFT JOIN VALL V3158 ON V3158.OBJ_ID = S.SUBJECT_ID AND V3158.PARAM_ID = 3158 AND V3158.IS_DEL = 0
        WHERE S.PLAN_ID = :V$OBJ_ID AND S.ROW_TYPE = 10 AND S.DATE_DEL IS NULL AND S.SUBJECT_ID <> 34607
          AND (P.FIELD_ID IS NULL OR P.FIELD_ID <> 5249) -- СПО
        ORDER BY S.GLOBAL_INDEX
        INTO :V$SUBJECT_ID, :S, :V$STM, :V$TYPE
      DO
      BEGIN
        TAG_NAME = 'items:r:subjects:r';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'items:r:subjects:r:id';
        VAL = V$SUBJECT_ID;
        SUSPEND;
        TAG_NAME = 'items:r:subjects:r:name';
        VAL = S;
        SUSPEND;
        TAG_NAME = 'items:r:subjects:r:is_stm';
        VAL = V$STM;
        SUSPEND;
        TAG_NAME = 'items:r:subjects:r:type';
        VAL = V$TYPE;
        SUSPEND;

        -- Модули по предмету
        TAG_NAME = 'items:r:subjects:r:modules::json&colon;array';
        VAL = 1;
        SUSPEND;
        FOR
          SELECT L51.OBJ_ID, C.CAPTION
          FROM LINKS L51
          JOIN VALL V3158 ON V3158.OBJ_ID = L51.OBJ_ID AND V3158.PARAM_ID = 3158 AND V3158.IS_DEL = 0 AND V3158.LISTVAL_ID IN (13456, 13457)
          JOIN VALR V3159 ON V3159.OBJ_ID = L51.OBJ_ID AND V3159.PARAM_ID = 3159 AND V3159.IS_DEL = 0 AND V3159.VAL = :V$SUBJECT_ID
          LEFT JOIN OBJECT_CAPTION_GET(L51.OBJ_ID) C ON 1 = 1
          WHERE L51.PARENT_ID = 32771 AND L51.OBJ_TYPE_ID = 51 AND L51.DATE_DEL IS NULL AND :V$TYPE = 13462
          ORDER BY 2
          INTO :V$STAGE_ID, :S
        DO
        BEGIN
          TAG_NAME = 'items:r:subjects:r:modules:r';
          VAL = NULL;
          SUSPEND;
          TAG_NAME = 'items:r:subjects:r:modules:r:id';
          VAL = V$STAGE_ID;
          SUSPEND;
          TAG_NAME = 'items:r:subjects:r:modules:r:name';
          VAL = S;
          SUSPEND;
        END

        -- Этапы - берем как в УП
        -- Но на выходе дополнительно учитываем доп этапы, чтобы подменять этап журнала на общеобразовательный этап - V$ROW_ID <> V$STAGE_INDEX
        TAG_NAME = 'items:r:subjects:r:stages::json&colon;array';
        VAL = 1;
        SUSPEND;
        FOR
          SELECT L54.OBJ_ID, V381.LISTVAL_ID, LV2.LISTVAL_ID
          FROM LINKS L54
          JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
          JOIN LISTVALS LV ON LV.LISTVAL_ID = V381.LISTVAL_ID
          JOIN LISTVALS LV2 ON (LV2.PARENT_ID = :V$MASTER_STAGE OR (:V$MASTER_STAGE IS NULL AND LV2.LISTVAL_ID = LV.LISTVAL_ID)) AND LV2.COST = LV.COST
          WHERE L54.PARENT_ID = :V$OBJ_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
          ORDER BY LV.COST
          INTO :V$STAGE_ID, :V$ROW_ID, :V$STAGE_INDEX
        DO
        BEGIN
          TAG_NAME = 'items:r:subjects:r:stages:r';
          VAL = NULL;
          SUSPEND;
          TAG_NAME = 'items:r:subjects:r:stages:r:id';
          VAL = V$ROW_ID;
          SUSPEND;
          -- Есть ли нагрузка в нужной паре параллель-предмет ?
          TAG_NAME = 'items:r:subjects:r:stages:r:hours';
          VAL = 0;
          SELECT CAST(SUM(COALESCE(L.LOAD_HOURS_S1, 0) + COALESCE(L.LOAD_HOURS_S2, 0)) AS NUMERIC(18, 2))
          FROM PLAN_SUBJECTS S
          JOIN PLAN_LOADS L ON L.SUBJECT_ID = S.OBJ_ID AND L.STAGE_ID = :V$STAGE_ID AND L.DATE_DEL IS NULL
          WHERE S.PLAN_ID = :V$OBJ_ID AND S.ROW_TYPE = 10 AND S.DATE_DEL IS NULL AND S.SUBJECT_ID = :V$SUBJECT_ID
          INTO :VAL;
          IF(VAL IS NULL) THEN VAL = 0;
          SUSPEND;

          -- Список журналов в данном сечении
          -- Берем как по точно указанному предмету, так и по его подвидам
          -- Группы со словами доп, НОО, ООО, СОО показываются только в дополнительных этапах !
          TAG_NAME = 'items:r:subjects:r:stages:r:journals::json&colon;array';
          VAL = 1;
          SUSPEND;
          FOR
            -- Точно этот предмет
            SELECT J.OBJ_ID, J.JOURNAL_NAME, J.TEACHER_ID, J.GRADE_ID, J.GRADE_TYPE_ID, J.SUBJECT_ID
            FROM CJ2_JOURNAL J
            WHERE J.JOURNAL_TYPE = :I$TYPE AND J.SUBJECT_ID = :V$SUBJECT_ID AND J.STAGE_INDEX = :V$STAGE_INDEX AND J.DATE_DEL IS NULL AND J.REF_ID = :V$OBJ_ID AND (J.YEAR_ID IS NULL OR :I$YEAR_ID IS NULL OR J.YEAR_ID = :I$YEAR_ID)
              -- AND (:V$ROW_ID = :V$STAGE_INDEX AND POSITION('доп' IN J.JOURNAL_NAME) <= 0 AND POSITION('НОО' IN J.JOURNAL_NAME) <= 0 AND POSITION('ООО' IN J.JOURNAL_NAME) <= 0 AND POSITION('СОО' IN J.JOURNAL_NAME) <= 0)
            -- Модули по предмету
            UNION
            SELECT J.OBJ_ID, J.JOURNAL_NAME, J.TEACHER_ID, J.GRADE_ID, J.GRADE_TYPE_ID, J.SUBJECT_ID
            FROM LINKS L51
            JOIN VALL V3158 ON V3158.OBJ_ID = L51.OBJ_ID AND V3158.PARAM_ID = 3158 AND V3158.IS_DEL = 0 AND V3158.LISTVAL_ID IN (13456, 13457)
            JOIN VALR V3159 ON V3159.OBJ_ID = L51.OBJ_ID AND V3159.PARAM_ID = 3159 AND V3159.IS_DEL = 0 AND V3159.VAL = :V$SUBJECT_ID
            JOIN CJ2_JOURNAL J ON J.JOURNAL_TYPE = :I$TYPE AND J.SUBJECT_ID = L51.OBJ_ID AND J.STAGE_INDEX = :V$STAGE_INDEX AND J.DATE_DEL IS NULL AND J.REF_ID = :V$OBJ_ID AND (J.YEAR_ID IS NULL OR :I$YEAR_ID IS NULL OR J.YEAR_ID = :I$YEAR_ID)
              -- AND (:V$ROW_ID = :V$STAGE_INDEX AND POSITION('доп' IN J.JOURNAL_NAME) <= 0 AND POSITION('НОО' IN J.JOURNAL_NAME) <= 0 AND POSITION('ООО' IN J.JOURNAL_NAME) <= 0 AND POSITION('СОО' IN J.JOURNAL_NAME) <= 0)
            WHERE L51.PARENT_ID = 32771 AND L51.OBJ_TYPE_ID = 51 AND L51.DATE_DEL IS NULL AND :V$TYPE = 13462
            ORDER BY 2
            INTO :V$JOURNAL_ID, :S, :V$TEACHER_ID, :V$GRADE_ID, :V$GRADE_TYPE_ID, :V$REAL_SUBJ
          DO
          BEGIN
            TAG_NAME = 'items:r:subjects:r:stages:r:journals:r';
            VAL = NULL;
            SUSPEND;
            TAG_NAME = 'items:r:subjects:r:stages:r:journals:r:id';
            VAL = V$JOURNAL_ID;
            SUSPEND;
            TAG_NAME = 'items:r:subjects:r:stages:r:journals:r:subject_id';
            VAL = V$REAL_SUBJ;
            SUSPEND;
            TAG_NAME = 'items:r:subjects:r:stages:r:journals:r:name';
            VAL = S;
            SUSPEND;
            TAG_NAME = 'items:r:subjects:r:stages:r:journals:r:teacher_id';
            VAL = V$TEACHER_ID;
            SUSPEND;
            TAG_NAME = 'items:r:subjects:r:stages:r:journals:r:teacher_name';
            IF(V$TEACHER_ID IS NULL) THEN VAL = 'Вакантная ставка';
            ELSE VAL = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$TEACHER_ID));
            SUSPEND;
            TAG_NAME = 'items:r:subjects:r:stages:r:journals:r:grade_type_id';
            VAL = V$GRADE_TYPE_ID;
            SUSPEND;
            TAG_NAME = 'items:r:subjects:r:stages:r:journals:r:grade_id';
            VAL = V$GRADE_ID;
            SUSPEND;
            TAG_NAME = 'items:r:subjects:r:stages:r:journals:r:grade_name';
            IF(V$GRADE_TYPE_ID IS NULL) THEN VAL = 'Не назначена';
            VAL = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$GRADE_ID));
            SUSPEND;
            -- Ссылка на мастер-группу, если она есть
            TAG_NAME = 'items:r:subjects:r:stages:r:journals:r:master_grade_id';
            VAL = NULL;
            IF(V$GRADE_TYPE_ID = 179) THEN
            BEGIN
              SELECT FIRST 1 LP2.EXT_OBJ_ID
              FROM LINKS LP2
              WHERE LP2.OBJ_ID = :V$GRADE_ID AND LP2.PARENT_TYPE_ID = 2 AND LP2.DATE_DEL IS NULL
              INTO :VAL;
            END
            SUSPEND;
          END
        END
      END

    END

    -- Список названий этапов
    -- А оно нам еще для чего-то нужно ?
    TAG_NAME = 'stages::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      -- Старая схема выборки
      SELECT L.LISTVAL_ID, L.VAL, L.SORT_ORDER
      FROM OO_FILTRED_LIST(25) L
      WHERE L.PARENT_ID IS NOT NULL AND :V$OU_LICENCE_TYPE <> 'S'
      -- Новая схема выборки
      UNION
      SELECT LV.LISTVAL_ID, C.VAL, LV.SORT_ORDER
      FROM LISTVALS LV
      LEFT JOIN LISTVAL_TEXT(LV.LISTVAL_ID) C ON 1 = 1
      WHERE LV.LIST_ID = 25 AND LV.IS_DEL = 0 AND :V$OU_LICENCE_TYPE = 'S'
      AND (
        -- ДОО не в этом типе журналов
        (LV.PARENT_ID IN (2141, 12941) AND :V$HAS_OO = 1)
        OR (LV.PARENT_ID = 2142 AND (:V$HAS_SPO = 1 OR :V$HAS_PO = 1))
      )
      ORDER BY 3
      INTO :V$OBJ_ID, :S, :V$SORT_ORDER
    DO
    BEGIN
      TAG_NAME = 'stages:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'stages:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'stages:r:name';
      VAL = S;
      SUSPEND;
    END

  END
  ELSE IF(I$TYPE = 1) THEN
  BEGIN

    -- ВД
    -- УП -> предмет -> ...
    FOR
      SELECT L400.OBJ_ID, V1594.LISTVAL_ID, R.VAL, C.CAPTION
      FROM LINKS L69
      JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
      JOIN VALL V1594 ON V1594.OBJ_ID = L57.OBJ_ID AND V1594.PARAM_ID = 1594 AND V1594.IS_DEL = 0
      JOIN LISTVALS LV ON LV.LISTVAL_ID = V1594.LISTVAL_ID
      JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
      LEFT JOIN VALI V3115 ON V3115.OBJ_ID = L57.OBJ_ID AND V3115.PARAM_ID = 3115 AND V3115.IS_DEL = 0 -- год публикации
      JOIN LINKS L400 ON L400.PARENT_ID = L57.OBJ_ID AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL
      JOIN VALL V3022 ON V3022.OBJ_ID = L400.OBJ_ID AND V3022.PARAM_ID = 3022 AND V3022.IS_DEL = 0 AND V3022.LISTVAL_ID = 2
      JOIN VALL V3013 ON V3013.OBJ_ID = L400.OBJ_ID AND V3013.PARAM_ID = 3013 AND V3013.IS_DEL = 0 AND V3013.LISTVAL_ID = 11715
      LEFT JOIN OBJECT_CAPTION_GET(L400.OBJ_ID) C ON 1 = 1
      WHERE L69.PARENT_TYPE_ID = 2 AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL
        AND (V3115.VAL = :V$Y OR POSITION(:V$YC1 IN C.CAPTION) > 0 OR POSITION(:V$YC2 IN C.CAPTION) > 0 OR POSITION(:V$YC3 IN C.CAPTION) > 0 OR POSITION(:V$YC4 IN C.CAPTION) > 0)
      ORDER BY 2, 3
      INTO :V$OBJ_ID, :V$STAGE_ID, :V$STAGE_NAME, :S
    DO
    BEGIN
      TAG_NAME = 'items:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'items:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'items:r:stage_id';
      VAL = V$STAGE_ID;
      SUSPEND;
      TAG_NAME = 'items:r:stage_name';
      VAL = V$STAGE_NAME;
      SUSPEND;
      TAG_NAME = 'items:r:name';
      VAL = S;
      SUSPEND;

      -- Этапы
      TAG_NAME = 'items:r:stages::json&colon;array';
      VAL = 1;
      SUSPEND;
      FOR
         SELECT V381.LISTVAL_ID, R.VAL, V382.VAL
         FROM LINKS L54
         JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
         JOIN LISTVALS LV ON LV.LISTVAL_ID = V381.LISTVAL_ID
         JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
         JOIN VALI V382 ON V382.OBJ_ID = L54.OBJ_ID AND V382.PARAM_ID = 382 AND V382.IS_DEL = 0
         WHERE L54.PARENT_ID = :V$OBJ_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
         ORDER BY LV.COST
         INTO :V$STAGE_ID, :S, :V$WEEKS
      DO
      BEGIN
        TAG_NAME = 'items:r:stages:r';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'items:r:stages:r:id';
        VAL = V$STAGE_ID;
        SUSPEND;
        TAG_NAME = 'items:r:stages:r:name';
        VAL = S;
        SUSPEND;
        TAG_NAME = 'items:r:stages:r:weeks';
        VAL = V$WEEKS;
        SUSPEND;
        -- ГУП нам тут не нужны
        TAG_NAME = 'items:r:stages:r:groups::json&colon;array';
        VAL = 1;
        SUSPEND;
      END

      TAG_NAME = 'items:r:subjects::json&colon;array';
      VAL = 1;
      SUSPEND;
      FOR
        SELECT S.OBJ_ID, S.SUBJECT_ID, C.CAPTION
        FROM PLAN_SUBJECTS S
        LEFT JOIN OBJECT_CAPTION_GET(S.SUBJECT_ID) C ON 1 = 1
        WHERE S.PLAN_ID = :V$OBJ_ID AND S.DATE_DEL IS NULL AND S.ROW_TYPE = 10
        ORDER BY S.GLOBAL_INDEX
        INTO :V$ROW_ID, :V$SUBJECT_ID, :S
      DO
      BEGIN
        TAG_NAME = 'items:r:subjects:r';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'items:r:subjects:r:id';
        VAL = V$SUBJECT_ID;
        SUSPEND;
        TAG_NAME = 'items:r:subjects:r:name';
        VAL = S;
        SUSPEND;
        TAG_NAME = 'items:r:subjects:r:is_stm';
        VAL = 1;
        SUSPEND;

        TAG_NAME = 'items:r:subjects:r:stages::json&colon;array';
        VAL = 1;
        SUSPEND;
        FOR
          SELECT V381.LISTVAL_ID, COALESCE(L.LOAD_HOURS_S1, 0) + COALESCE(L.LOAD_HOURS_S2, 0)
          FROM PLAN_LOADS L
          JOIN LINKS ST ON ST.OBJ_ID = L.STAGE_ID AND ST.PARENT_ID = :V$OBJ_ID AND ST.DATE_DEL IS NULL
          JOIN VALL V381 ON V381.OBJ_ID = L.STAGE_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
          JOIN LISTVALS LV ON LV.LISTVAL_ID = V381.LISTVAL_ID
          WHERE L.SUBJECT_ID = :V$ROW_ID AND L.DATE_DEL IS NULL
          ORDER BY LV.COST
          INTO :V$STAGE_ID, :N
        DO
        BEGIN
          TAG_NAME = 'items:r:subjects:r:stages:r';
          VAL = NULL;
          SUSPEND;
          TAG_NAME = 'items:r:subjects:r:stages:r:id';
          VAL = V$STAGE_ID;
          SUSPEND;
          TAG_NAME = 'items:r:subjects:r:stages:r:hours';
          VAL = CAST(N AS NUMERIC(18, 2));
          SUSPEND;

          -- Список журналов в данном сечении - совместимость со старым режимом где не было фиксации связи с УП
          TAG_NAME = 'items:r:subjects:r:stages:r:journals::json&colon;array';
          VAL = 1;
          SUSPEND;
          FOR
            SELECT J.OBJ_ID, J.JOURNAL_NAME, J.TEACHER_ID, J.GRADE_ID, J.GRADE_TYPE_ID
            FROM CJ2_JOURNAL J
            WHERE J.JOURNAL_TYPE = :I$TYPE AND J.SUBJECT_ID = :V$SUBJECT_ID AND J.STAGE_INDEX = :V$STAGE_ID AND J.DATE_DEL IS NULL
              AND (J.REF_ID IS NULL OR J.REF_ID = :V$OBJ_ID) AND (J.YEAR_ID IS NULL OR :I$YEAR_ID IS NULL OR J.YEAR_ID = :I$YEAR_ID)
            ORDER BY 2
            INTO :V$JOURNAL_ID, :S, :V$TEACHER_ID, :V$GRADE_ID, :V$GRADE_TYPE_ID
          DO
          BEGIN
            TAG_NAME = 'items:r:subjects:r:stages:r:journals:r';
            VAL = NULL;
            SUSPEND;
            TAG_NAME = 'items:r:subjects:r:stages:r:journals:r:id';
            VAL = V$JOURNAL_ID;
            SUSPEND;
            TAG_NAME = 'items:r:subjects:r:stages:r:journals:r:name';
            VAL = S;
            SUSPEND;
            TAG_NAME = 'items:r:subjects:r:stages:r:journals:r:teacher_id';
            VAL = V$TEACHER_ID;
            SUSPEND;
            TAG_NAME = 'items:r:subjects:r:stages:r:journals:r:teacher_name';
            VAL = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$TEACHER_ID));
            SUSPEND;
            TAG_NAME = 'items:r:subjects:r:stages:r:journals:r:grade_type_id';
            VAL = V$GRADE_TYPE_ID;
            SUSPEND;
            TAG_NAME = 'items:r:subjects:r:stages:r:journals:r:grade_id';
            VAL = V$GRADE_ID;
            SUSPEND;
            TAG_NAME = 'items:r:subjects:r:stages:r:journals:r:grade_name';
            IF(V$GRADE_TYPE_ID IS NULL) THEN VAL = 'Не назначена';
            ELSE IF(V$GRADE_TYPE_ID = 179) THEN VAL = S; -- 'Группа по предмету';
            ELSE IF(V$GRADE_TYPE_ID = 9) THEN VAL = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$GRADE_ID)) || ' класс';
            SUSPEND;
          END
        END
      END

    END

    -- Список названий этапов
    TAG_NAME = 'stages::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      -- Старая схема выборки
      SELECT L.LISTVAL_ID, L.VAL, L.SORT_ORDER
      FROM OO_FILTRED_LIST(25) L
      WHERE L.PARENT_ID IS NOT NULL AND :V$OU_LICENCE_TYPE <> 'S'
      -- Новая схема выборки
      UNION
      SELECT LV.LISTVAL_ID, C.VAL, LV.SORT_ORDER
      FROM LISTVALS LV
      LEFT JOIN LISTVAL_TEXT(LV.LISTVAL_ID) C ON 1 = 1
      WHERE LV.LIST_ID = 25 AND LV.IS_DEL = 0 AND :V$OU_LICENCE_TYPE = 'S'
      AND (
        -- Тут только ВД - ни ДОО, ни СПО тут нет
        LV.PARENT_ID IN (2141, 12941) AND :V$HAS_OO = 1
      )
      ORDER BY 3
      INTO :V$OBJ_ID, :S, :V$SORT_ORDER
    DO
    BEGIN
      TAG_NAME = 'stages:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'stages:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'stages:r:name';
      VAL = S;
      SUSPEND;
    END

  END
  ELSE IF(I$TYPE = 2) THEN
  BEGIN

    -- ГПД
    TAG_NAME = 'items:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'items:r:id';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'items:r:stage_id';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'items:r:stage_name';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'items:r:name';
    VAL = 'Все группы';
    SUSPEND;

    TAG_NAME = 'items:r:stages::json&colon;array';
    VAL = 1;
    SUSPEND;
    TAG_NAME = 'items:r:stages:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'items:r:stages:r:id';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'items:r:stages:r:name';
    VAL = 'Все группы';
    SUSPEND;
    TAG_NAME = 'items:r:stages:r:weeks';
    VAL = 0;
    SUSPEND;
    -- ГУП нам тут не нужны
    TAG_NAME = 'items:r:stages:r:groups::json&colon;array';
    VAL = 1;
    SUSPEND;

    -- Под видом предметов перебираем сами группы
    TAG_NAME = 'items:r:subjects::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT L46.OBJ_ID, NULL, C.CAPTION
      FROM LINKS L2
      JOIN LINKS L86 ON L86.PARENT_ID = L2.OBJ_ID AND L86.OBJ_TYPE_ID = 86 AND L86.DATE_DEL IS NULL
      JOIN VALL V1579 ON V1579.OBJ_ID = L86.OBJ_ID AND V1579.PARAM_ID = 1579 AND V1579.IS_DEL = 0 AND V1579.LISTVAL_ID = 3317
      JOIN LINKS L46 ON L46.PARENT_ID = L86.OBJ_ID AND L46.OBJ_TYPE_ID = 46 AND L46.DATE_DEL IS NULL
      LEFT JOIN OBJECT_CAPTION_GET(L46.OBJ_ID) C ON 1 = 1
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      -- новая схема мультипараграф
      UNION
      SELECT L46.OBJ_ID, NULL, C.CAPTION
      FROM LINKS L2
      JOIN LINKS L500 ON L500.PARENT_ID = L2.OBJ_ID AND L500.OBJ_TYPE_ID = 500 AND L500.DATE_DEL IS NULL
      JOIN LINKS L46 ON L46.PARENT_ID = L500.OBJ_ID AND L46.OBJ_TYPE_ID = 46 AND L46.DATE_DEL IS NULL
      LEFT JOIN OBJECT_CAPTION_GET(L46.OBJ_ID) C ON 1 = 1
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      ORDER BY 2, 3
      INTO :V$ROW_ID, :V$SUBJECT_ID, :S
    DO
    BEGIN
      TAG_NAME = 'items:r:subjects:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'items:r:subjects:r:id';
      VAL = V$ROW_ID;
      SUSPEND;
      TAG_NAME = 'items:r:subjects:r:name';
      VAL = S;
      SUSPEND;
      TAG_NAME = 'items:r:subjects:r:is_stm';
      VAL = '1';
      SUSPEND;
      TAG_NAME = 'items:r:subjects:r:type';
      VAL = '';
      SUSPEND;

      -- Этап у нас тут всегда один
      TAG_NAME = 'items:r:subjects:r:stages::json&colon;array';
      VAL = 1;
      SUSPEND;
      TAG_NAME = 'items:r:subjects:r:stages:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'items:r:subjects:r:stages:r:id';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'items:r:subjects:r:stages:r:hours';
      VAL = 99999;
      SUSPEND;

      TAG_NAME = 'items:r:subjects:r:stages:r:journals::json&colon;array';
      VAL = 1;
      SUSPEND;
      FOR
        SELECT J.OBJ_ID, J.JOURNAL_NAME, J.TEACHER_ID, J.GRADE_ID, J.GRADE_TYPE_ID
        FROM CJ2_JOURNAL J
        WHERE J.JOURNAL_TYPE = :I$TYPE AND J.DATE_DEL IS NULL AND J.GRADE_ID = :V$ROW_ID AND (J.YEAR_ID IS NULL OR :I$YEAR_ID IS NULL OR J.YEAR_ID = :I$YEAR_ID)
        ORDER BY 2
        INTO :V$JOURNAL_ID, :S, :V$TEACHER_ID, :V$GRADE_ID, :V$GRADE_TYPE_ID
      DO
      BEGIN
        TAG_NAME = 'items:r:subjects:r:stages:r:journals:r';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'items:r:subjects:r:stages:r:journals:r:id';
        VAL = V$JOURNAL_ID;
        SUSPEND;
        TAG_NAME = 'items:r:subjects:r:stages:r:journals:r:name';
        VAL = S;
        SUSPEND;
        TAG_NAME = 'items:r:subjects:r:stages:r:journals:r:teacher_id';
        VAL = '1';
        SUSPEND;
        TAG_NAME = 'items:r:subjects:r:stages:r:journals:r:teacher_name';
        VAL = 'Штатный воспитатель';
        SUSPEND;
        TAG_NAME = 'items:r:subjects:r:stages:r:journals:r:grade_type_id';
        VAL = V$GRADE_TYPE_ID;
        SUSPEND;
        TAG_NAME = 'items:r:subjects:r:stages:r:journals:r:grade_id';
        VAL = V$GRADE_ID;
        SUSPEND;
        TAG_NAME = 'items:r:subjects:r:stages:r:journals:r:grade_name';
        VAL = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$GRADE_ID));
        IF(VAL <> S) THEN VAL = S;
        SUSPEND;
      END

    END -- цикл по группам

    TAG_NAME = 'stages::json&colon;array';
    VAL = 1;
    SUSPEND;
    TAG_NAME = 'stages:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'stages:r:id';
    VAL = '';
    SUSPEND;
    TAG_NAME = 'stages:r:name';
    VAL = 'Без указания этапа';
    SUSPEND;

  END
  ELSE IF(I$TYPE = 3) THEN
  BEGIN

    -- ДО и УДОД
    TAG_NAME = 'items:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'items:r:id';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'items:r:stage_id';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'items:r:stage_name';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'items:r:name';
    VAL = 'Все группы';
    SUSPEND;

    -- Под видом предметов перебираем сами группы
    TAG_NAME = 'items:r:subjects::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT L46.OBJ_ID, NULL, C.CAPTION
      FROM LINKS L2
      JOIN LINKS L86 ON L86.PARENT_ID = L2.OBJ_ID AND L86.OBJ_TYPE_ID = 86 AND L86.DATE_DEL IS NULL
      JOIN VALL V1579 ON V1579.OBJ_ID = L86.OBJ_ID AND V1579.PARAM_ID = 1579 AND V1579.IS_DEL = 0 AND V1579.LISTVAL_ID IN (3315, 3316)
      JOIN LINKS L46 ON L46.PARENT_ID = L86.OBJ_ID AND L46.OBJ_TYPE_ID = 46 AND L46.DATE_DEL IS NULL
      LEFT JOIN OBJECT_CAPTION_GET(L46.OBJ_ID) C ON 1 = 1
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      -- новая схема мультипараграф - в подразделении
      UNION
      SELECT L46.OBJ_ID, NULL, C.CAPTION
      FROM LINKS L2
      JOIN LINKS L211 ON L211.PARENT_ID = L2.OBJ_ID AND L211.OBJ_TYPE_ID = 211 AND L211.DATE_DEL IS NULL
      JOIN VALL V2102 ON V2102.OBJ_ID = L211.OBJ_ID AND V2102.PARAM_ID = 2102 AND V2102.IS_DEL = 0 AND V2102.LISTVAL_ID = 14246
      JOIN LINKS L46 ON L46.PARENT_ID = L211.OBJ_ID AND L46.OBJ_TYPE_ID = 46 AND L46.DATE_DEL IS NULL
      LEFT JOIN OBJECT_CAPTION_GET(L46.OBJ_ID) C ON 1 = 1
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      -- новая схема мультипараграф - в ступени ДО
      UNION
      SELECT L46.OBJ_ID, NULL, C.CAPTION
      FROM LINKS L2
      JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
      JOIN VALL V43 ON V43.OBJ_ID = L7.OBJ_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0 AND V43.LISTVAL_ID = 13128
      JOIN LINKS L46 ON L46.PARENT_ID = L7.OBJ_ID AND L46.OBJ_TYPE_ID = 46 AND L46.DATE_DEL IS NULL
      LEFT JOIN OBJECT_CAPTION_GET(L46.OBJ_ID) C ON 1 = 1
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      ORDER BY 2, 3
      INTO :V$ROW_ID, :V$SUBJECT_ID, :S
    DO
    BEGIN
      TAG_NAME = 'items:r:subjects:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'items:r:subjects:r:id';
      VAL = V$ROW_ID;
      SUSPEND;
      TAG_NAME = 'items:r:subjects:r:name';
      VAL = S;
      SUSPEND;
      TAG_NAME = 'items:r:subjects:r:is_stm';
      VAL = '1';
      SUSPEND;
      TAG_NAME = 'items:r:subjects:r:type';
      VAL = '';
      SUSPEND;

      -- Этап у нас тут всегда один
      TAG_NAME = 'items:r:subjects:r:stages::json&colon;array';
      VAL = 1;
      SUSPEND;
      TAG_NAME = 'items:r:subjects:r:stages:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'items:r:subjects:r:stages:r:id';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'items:r:subjects:r:stages:r:hours';
      VAL = 99999;
      SUSPEND;

      TAG_NAME = 'items:r:subjects:r:stages:r:journals::json&colon;array';
      VAL = 1;
      SUSPEND;
      FOR
        SELECT J.OBJ_ID, J.JOURNAL_NAME, J.TEACHER_ID, J.GRADE_ID, J.GRADE_TYPE_ID
        FROM CJ2_JOURNAL J
        WHERE J.JOURNAL_TYPE = :I$TYPE AND J.DATE_DEL IS NULL AND J.GRADE_ID = :V$ROW_ID AND (J.YEAR_ID IS NULL OR :V$YEAR_ID IS NULL OR J.YEAR_ID = :V$YEAR_ID)
        ORDER BY 2
        INTO :V$JOURNAL_ID, :S, :V$TEACHER_ID, :V$GRADE_ID, :V$GRADE_TYPE_ID
      DO
      BEGIN
        TAG_NAME = 'items:r:subjects:r:stages:r:journals:r';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'items:r:subjects:r:stages:r:journals:r:id';
        VAL = V$JOURNAL_ID;
        SUSPEND;
        TAG_NAME = 'items:r:subjects:r:stages:r:journals:r:name';
        VAL = S;
        SUSPEND;
        TAG_NAME = 'items:r:subjects:r:stages:r:journals:r:teacher_id';
        VAL = '1';
        SUSPEND;
        TAG_NAME = 'items:r:subjects:r:stages:r:journals:r:teacher_name';
        VAL = 'Штатный преподаватель';
        SUSPEND;
        TAG_NAME = 'items:r:subjects:r:stages:r:journals:r:grade_type_id';
        VAL = V$GRADE_TYPE_ID;
        SUSPEND;
        TAG_NAME = 'items:r:subjects:r:stages:r:journals:r:grade_id';
        VAL = V$GRADE_ID;
        SUSPEND;
        TAG_NAME = 'items:r:subjects:r:stages:r:journals:r:grade_name';
        VAL = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$GRADE_ID));
        IF(VAL <> S) THEN VAL = S;
        SUSPEND;
      END

    END -- цикл по группам

    TAG_NAME = 'stages::json&colon;array';
    VAL = 1;
    SUSPEND;
    TAG_NAME = 'stages:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'stages:r:id';
    VAL = '';
    SUSPEND;
    TAG_NAME = 'stages:r:name';
    VAL = 'Без указания этапа';
    SUSPEND;

  END
  ELSE IF(I$TYPE = 4) THEN
  BEGIN

    -- ДОУ
    TAG_NAME = 'items:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'items:r:id';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'items:r:stage_id';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'items:r:stage_name';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'items:r:name';
    VAL = 'Все группы';
    SUSPEND;

    -- Под видом предметов перебираем сами группы, выбираем все учебные коллективы уровня Ясли и Сад
    TAG_NAME = 'items:r:subjects::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT L9.OBJ_ID, NULL, C.CAPTION
      FROM LINKS L2
      JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
      JOIN VALL V43 ON V43.OBJ_ID = L7.OBJ_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0 AND V43.LISTVAL_ID IN (3263, 3264)
      JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
      LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C ON 1 = 1
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      ORDER BY C.SORT_ORDER, 3
      INTO :V$ROW_ID, :V$SUBJECT_ID, :S
    DO
    BEGIN
      TAG_NAME = 'items:r:subjects:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'items:r:subjects:r:id';
      VAL = V$ROW_ID;
      SUSPEND;
      TAG_NAME = 'items:r:subjects:r:name';
      VAL = S;
      SUSPEND;
      TAG_NAME = 'items:r:subjects:r:is_stm';
      VAL = '1';
      SUSPEND;
      TAG_NAME = 'items:r:subjects:r:type';
      VAL = '';
      SUSPEND;

      -- Этап у нас тут всегда один
      TAG_NAME = 'items:r:subjects:r:stages::json&colon;array';
      VAL = 1;
      SUSPEND;
      TAG_NAME = 'items:r:subjects:r:stages:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'items:r:subjects:r:stages:r:id';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'items:r:subjects:r:stages:r:hours';
      VAL = 99999;
      SUSPEND;

      TAG_NAME = 'items:r:subjects:r:stages:r:journals::json&colon;array';
      VAL = 1;
      SUSPEND;
      FOR
        SELECT J.OBJ_ID, J.JOURNAL_NAME, J.TEACHER_ID, J.GRADE_ID, J.GRADE_TYPE_ID
        FROM CJ2_JOURNAL J
        WHERE J.JOURNAL_TYPE = :I$TYPE AND J.DATE_DEL IS NULL AND J.GRADE_ID = :V$ROW_ID AND (J.YEAR_ID IS NULL OR :V$YEAR_ID IS NULL OR J.YEAR_ID = :V$YEAR_ID)
        ORDER BY 2
        INTO :V$JOURNAL_ID, :S, :V$TEACHER_ID, :V$GRADE_ID, :V$GRADE_TYPE_ID
      DO
      BEGIN
        TAG_NAME = 'items:r:subjects:r:stages:r:journals:r';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'items:r:subjects:r:stages:r:journals:r:id';
        VAL = V$JOURNAL_ID;
        SUSPEND;
        TAG_NAME = 'items:r:subjects:r:stages:r:journals:r:name';
        VAL = S;
        SUSPEND;
        TAG_NAME = 'items:r:subjects:r:stages:r:journals:r:teacher_id';
        VAL = '1';
        SUSPEND;
        TAG_NAME = 'items:r:subjects:r:stages:r:journals:r:teacher_name';
        VAL = 'Штатный воспитатель';
        SUSPEND;
        TAG_NAME = 'items:r:subjects:r:stages:r:journals:r:grade_type_id';
        VAL = V$GRADE_TYPE_ID;
        SUSPEND;
        TAG_NAME = 'items:r:subjects:r:stages:r:journals:r:grade_id';
        VAL = V$GRADE_ID;
        SUSPEND;
        TAG_NAME = 'items:r:subjects:r:stages:r:journals:r:grade_name';
        VAL = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$GRADE_ID));
        IF(VAL <> S) THEN VAL = S;
        SUSPEND;
      END
    END -- цикл по группам

    TAG_NAME = 'stages::json&colon;array';
    VAL = 1;
    SUSPEND;
    TAG_NAME = 'stages:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'stages:r:id';
    VAL = '';
    SUSPEND;
    TAG_NAME = 'stages:r:name';
    VAL = 'Без указания этапа';
    SUSPEND;

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ_COLLEGE_SUBJECTS_LIST (
    I$GRADE_ID BIGINT,
    I$USER_ID BIGINT,
    I$LEVEL_ID INTEGER = 0,
    IS_ACCESSIBLE SMALLINT = 1)
RETURNS (
    OBJ_ID BIGINT,
    OBJ_CAPTION VARCHAR(4000),
    SORT_ORDER DOUBLE PRECISION)
AS
declare variable USER_TYPE smallint;
declare variable CLASS_ID bigint;
declare variable TEACHER_ID bigint;
BEGIN
    SORT_ORDER = 0;

    SELECT U.USER_TYPE, U.OBJ_ID
    FROM USERS U
    WHERE U.USER_ID = :I$USER_ID AND U.DATE_DEL IS NULL AND U.IS_BLOCKED = 0
    INTO :USER_TYPE, :TEACHER_ID;

    SELECT FIRST 1 U.ROOT_OBJ_ID
    FROM LUSERS U
    WHERE U.LEVEL_ID IN (50, 174, 414, /* +Apostrof */ 305) AND U.USER_ID = :I$USER_ID
    INTO :CLASS_ID;

    FOR
        -- Нагрузки обычных предметов
        SELECT DISTINCT SUBJECT_ID, SUBJECT_CAPTION
        FROM COLLEGE_GRADE_CURRICULUM_LIST(:I$GRADE_ID, :I$USER_ID) GC
        JOIN PARAGRAF_COLLEGE_SUBJECTS_LIST2(GC.CURRICULUM_ID, :I$USER_ID, :I$LEVEL_ID) ON 1 = 1
        -- Для профобучения выдаем липовый предмет NULL
        UNION ALL
        SELECT S.OBJ_ID, C.CAPTION
        FROM OBJECTS S
        LEFT JOIN OBJECT_CAPTION_GET(S.OBJ_ID) C ON 1 = 1
        WHERE :I$LEVEL_ID = 254 AND S.OBJ_ID = 34726
        UNION ALL
        SELECT S.OBJ_ID, C.CAPTION
        FROM OBJECTS S
        LEFT JOIN OBJECT_CAPTION_GET(S.OBJ_ID) C ON 1 = 1
        WHERE :I$LEVEL_ID = 255 AND S.OBJ_ID = 34727
        ORDER BY 2
        INTO :OBJ_ID, :OBJ_CAPTION
    DO
    BEGIN
        IF (USER_TYPE IN (1, 5, 6)) THEN IS_ACCESSIBLE = 1;
        IF ((USER_TYPE IN (8, 9, 10, 20)) AND (I$GRADE_ID = CLASS_ID)) THEN IS_ACCESSIBLE = 1;

        IF (IS_ACCESSIBLE = 0) THEN
        BEGIN
            SELECT FIRST 1 1
            FROM CJ_ACCESS A
            WHERE A.USER_ID = :I$USER_ID AND A.CLASS_ID = :I$GRADE_ID AND A.SUBJECT_ID = :OBJ_ID
            INTO :IS_ACCESSIBLE;
        END

        IF (IS_ACCESSIBLE = 0) THEN
        BEGIN
            -- Учитель является куратором группы, где числится хотя бы один обучающийся
            SELECT FIRST 1 1
            FROM VALR V53
            WHERE V53.VAL = :TEACHER_ID AND V53.PARAM_ID = 53 AND V53.IS_DEL = 0 AND V53.OBJ_ID IN (
                SELECT L9_10.PARENT_ID
                FROM LINKS L256_10
                JOIN LINKS L9_10 ON L9_10.OBJ_ID = L256_10.OBJ_ID AND L9_10.PARENT_TYPE_ID IN (9, 187) AND L9_10.DATE_DEL IS NULL
                WHERE L256_10.PARENT_ID = :I$GRADE_ID AND L256_10.OBJ_TYPE_ID = 10 AND L256_10.DATE_DEL IS NULL
            )
            INTO :IS_ACCESSIBLE;
        END

        IF (IS_ACCESSIBLE = 0) THEN
        BEGIN
            -- Учитель назначен в нагрузке коллектива по этому предмету
            SELECT FIRST 1 1
            FROM LINKS L58
            JOIN LINKS LP14 ON LP14.OBJ_ID = L58.OBJ_ID AND LP14.PARENT_ID = :TEACHER_ID AND LP14.DATE_DEL IS NULL
            JOIN LINKS LP201 ON LP201.OBJ_ID = L58.OBJ_ID AND LP201.PARENT_TYPE_ID = 201 AND LP201.DATE_DEL IS NULL
            JOIN VALR V1766 ON V1766.OBJ_ID = LP201.PARENT_ID AND V1766.PARAM_ID = 1766 AND V1766.IS_DEL = 0 AND V1766.VAL = :OBJ_ID
            WHERE L58.PARENT_ID = :I$GRADE_ID AND L58.OBJ_TYPE_ID = 58 AND L58.DATE_DEL IS NULL
            INTO :IS_ACCESSIBLE;
        END

        IF (IS_ACCESSIBLE = 1) THEN
        BEGIN
            SORT_ORDER = :SORT_ORDER + 1;
            SUSPEND;
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ_GRADE_LIST (
    I$USER_ID BIGINT,
    I$REPORT_ID BIGINT = 0)
RETURNS (
    OBJ_ID BIGINT,
    TYPE_ID BIGINT,
    GROUP_TYPE BIGINT,
    OBJ_CAPTION VARCHAR(4000),
    SORT_ORDER DOUBLE PRECISION,
    STAGE_ID BIGINT,
    STAGE_NUM BIGINT,
    PARENT_ID BIGINT,
    COLOR INTEGER)
AS
DECLARE VARIABLE V$SCHOOL_ID BIGINT;
DECLARE VARIABLE V$OU_LICENCE_TYPE VARCHAR(1);
DECLARE VARIABLE V$USER_TYPE SMALLINT;
DECLARE VARIABLE TEACHER_ID BIGINT;
DECLARE VARIABLE V$OLD_ROOT_ACCESS_CLASS_ID BIGINT;
BEGIN

    -- В зависимости от ID отчета, может подкручиваться механизм выборки
    -- 0 будет для выборки списка уровня ДОУ
    -- для прочих отчетов может быть выдан как линейный список, так и дерево с использованием поля PARENT_ID, при этом родительские объекты выдаются
    -- все с SORT_INDEX в отрицательной области

    SELECT STATUS FROM OU_LICENCE_TYPE INTO :V$OU_LICENCE_TYPE;

    SELECT FIRST 1 L.OBJ_ID
    FROM LINKS L
    WHERE L.PARENT_ID IS NULL AND L.OBJ_TYPE_ID = 2 AND L.DATE_DEL IS NULL
    INTO :V$SCHOOL_ID;

    -- Получаем ID сотрудника
    SELECT U.USER_TYPE, U.OBJ_ID
    FROM USERS U
    WHERE U.USER_ID = :I$USER_ID AND U.DATE_DEL IS NULL AND U.IS_BLOCKED = 0
    INTO :V$USER_TYPE, :TEACHER_ID;

    /* Получаем ID класса, к которому назначен полный доступ как для руководителя по "старой схеме" */
    SELECT FIRST 1 ROOT_OBJ_ID
    FROM LUSERS
    WHERE LEVEL_ID IN (50, 174, /* AP */ 305, 440) AND USER_ID = :I$USER_ID
    INTO :V$OLD_ROOT_ACCESS_CLASS_ID;

    IF(I$REPORT_ID = 11) THEN
    BEGIN
       SORT_ORDER = -1E30;
       OBJ_ID = NULL;
       COLOR = 0x0000E0;
       OBJ_CAPTION = 'Все ступени обучения';
       GROUP_TYPE = NULL;
       PARENT_ID = NULL;
       STAGE_ID = 0;
       STAGE_NUM = 0;
       TYPE_ID = 7;

       SUSPEND;

      COLOR = 0;
      PARENT_ID = NULL;
      GROUP_TYPE = NULL;
      STAGE_ID = 0;
      STAGE_NUM = 0;
      SORT_ORDER = 4;
      TYPE_ID = 7;

      FOR
        SELECT OBJ_ID, OBJ_CAPTION FROM CJ_GRADE_LIST3(:I$USER_ID) ORDER BY SORT_ORDER,OBJ_CAPTION
        INTO :OBJ_ID, :OBJ_CAPTION
      DO
      BEGIN
        SUSPEND;
      END

    END

    ELSE

    IF(I$REPORT_ID in (19, 22)) THEN
    BEGIN
       SORT_ORDER = -1E30;
       OBJ_ID = NULL;
       COLOR = 0x0000E0;
       OBJ_CAPTION = 'Все коллективы';
       GROUP_TYPE = NULL;
       PARENT_ID = NULL;
       STAGE_ID = 0;
       STAGE_NUM = 0;
       TYPE_ID = 54;

       SUSPEND;

      PARENT_ID = NULL;
      GROUP_TYPE = NULL;
      STAGE_ID = 0;
      STAGE_NUM = 0;

      FOR
        SELECT L9.OBJ_ID, L9.OBJ_TYPE_ID, L.SORT_ORDER, 0 as COLOR, (SELECT CAPTION  FROM OBJECT_CAPTION_GET(L9.OBJ_ID, NULL, NULL, :I$USER_ID))
        FROM LINKS L2
        JOIN LINKS L69 ON L69.PARENT_ID = L2.OBJ_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL
        JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
        JOIN LINKS L50 ON L50.PARENT_ID = L57.OBJ_ID AND L50.OBJ_TYPE_ID = 50 AND L50.DATE_DEL IS NULL
        -- Исключаем УП внеурочной деятельности
        JOIN VALL V2545 ON V2545.OBJ_ID = L50.OBJ_ID AND V2545.PARAM_ID = 2545 AND V2545.IS_DEL = 0 AND V2545.LISTVAL_ID = 3
        JOIN LINKS L54 ON L54.PARENT_ID = L50.OBJ_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
        JOIN LINKS L9 ON L9.PARENT_ID = L54.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 256) AND L9.DATE_DEL IS NULL
        JOIN VALL V ON V.OBJ_ID = L54.OBJ_ID AND V.PARAM_ID = 381 AND V.IS_DEL = 0
        JOIN LISTVALS L ON L.LISTVAL_ID = V.LISTVAL_ID
        WHERE L2.OBJ_TYPE_ID = 2 AND L2.PARENT_ID IS NULL AND L2.DATE_DEL IS NULL

        union

        SELECT L347.OBJ_ID, 347, L.SORT_ORDER, 0xA00000 as COLOR, (SELECT CAPTION  FROM OBJECT_CAPTION_GET( L347.OBJ_ID, NULL, NULL, :I$USER_ID))
        FROM LINKS L2        -- ОООД
        JOIN LINKS L69 ON L69.PARENT_ID = L2.OBJ_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL   -- Образовательные программы
        JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL  -- Образовательная программа
        JOIN LINKS L50 ON L50.PARENT_ID = L57.OBJ_ID AND L50.OBJ_TYPE_ID = 50 AND L50.DATE_DEL IS NULL  -- Учебный план
        JOIN VALL V2545 ON V2545.OBJ_ID = L50.OBJ_ID AND V2545.PARAM_ID = 2545 AND V2545.IS_DEL = 0 AND V2545.LISTVAL_ID = 3
        JOIN LINKS L54 ON L54.PARENT_ID = L50.OBJ_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL  -- Этап учебного плана
        JOIN LINKS L346 ON L346.PARENT_ID = L54.OBJ_ID AND L346.OBJ_TYPE_ID = 346 AND L346.DATE_DEL IS NULL   -- Потоки
        JOIN LINKS L347 ON L347.PARENT_ID = L346.OBJ_ID AND L347.OBJ_TYPE_ID  = 347 AND L347.DATE_DEL IS NULL   --  347 - Поток
        JOIN VALL V ON V.OBJ_ID = L54.OBJ_ID AND V.PARAM_ID = 381 AND V.IS_DEL = 0
        JOIN LISTVALS L ON L.LISTVAL_ID = V.LISTVAL_ID


      INTO :OBJ_ID, :TYPE_ID, :SORT_ORDER, :COLOR, :OBJ_CAPTION
      DO
      BEGIN
        SUSPEND;
      END 

    END

    ELSE

    BEGIN

      FOR
        SELECT L9.OBJ_ID, L9.OBJ_TYPE_ID, L8.OBJ_ID, V49.LISTVAL_ID
        FROM LINKS L7
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
        JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
        WHERE L7.PARENT_ID = :V$SCHOOL_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
        INTO :OBJ_ID, :TYPE_ID, :STAGE_ID, :STAGE_NUM
      DO
      BEGIN
        PARENT_ID = NULL;

        SELECT CAPTION, SORT_ORDER
        FROM OBJECT_CAPTION_GET(:OBJ_ID, NULL, NULL, :I$USER_ID)
        INTO :OBJ_CAPTION, :SORT_ORDER;

        IF (TYPE_ID = 9) THEN
        BEGIN
            GROUP_TYPE = -1;
        END
        ELSE
        BEGIN
            -- Неактуальный ошметок от #46
            SELECT I
            FROM VAL_GET(:OBJ_ID, 369, 0, :I$USER_ID)
            INTO :GROUP_TYPE;
        END

        -- Есть ли у сотрудника доступ к данному коллективу ?

        -- Выдаем только те коллективы, к которым разрешен доступ

        -- Для отчетов сдвигаем сортировку в минус
        IF(I$REPORT_ID > 0) THEN SORT_ORDER = SORT_ORDER - 1E10;
        SUSPEND;

        -- Список учеников класса, которые присутствовали в нем в течение учебного года
        -- #2 - пропуски в разных сечениях
        -- #7 - сведения об успеваемости
        IF(I$REPORT_ID IN (2, 7)) THEN
        BEGIN
            PARENT_ID = OBJ_ID;
            GROUP_TYPE = NULL;
            STAGE_ID = 0;
            STAGE_NUM = 0;
            SORT_ORDER = 0;
            FOR
                SELECT L10.OBJ_ID, L10.OBJ_TYPE_ID, COALESCE(V55.VAL || ' ', '') || COALESCE(V56.VAL, '')
                FROM LINKS L10
                LEFT JOIN VALS V55 ON V55.OBJ_ID = L10.OBJ_ID AND V55.PARAM_ID = 55 AND V55.IS_DEL = 0
                LEFT JOIN VALS V56 ON V56.OBJ_ID = L10.OBJ_ID AND V56.PARAM_ID = 56 AND V56.IS_DEL = 0
                WHERE L10.PARENT_ID = :PARENT_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
                INTO :OBJ_ID, :TYPE_ID, :OBJ_CAPTION
            DO
            BEGIN
                SUSPEND;
            END
        END

      END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ_GRADE_LIST3 (
    I$USER_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    OBJ_CAPTION VARCHAR(4000),
    SORT_ORDER DOUBLE PRECISION)
AS
declare variable SCHOOL_ID bigint;
BEGIN
    SELECT FIRST 1 L.OBJ_ID
    FROM LINKS L
    WHERE L.PARENT_ID IS NULL AND L.OBJ_TYPE_ID = 2 AND L.DATE_DEL IS NULL
    INTO :SCHOOL_ID;

    FOR
        SELECT DISTINCT L7.OBJ_ID
        FROM LINKS L7
        WHERE L7.PARENT_ID = :SCHOOL_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
        INTO :OBJ_ID
    DO
    BEGIN
        SELECT CAPTION, SORT_ORDER
        FROM OBJECT_CAPTION_GET(:OBJ_ID, NULL, NULL, :I$USER_ID)
        INTO :OBJ_CAPTION, :SORT_ORDER;
        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ_GRADE_SUBJECTS_LIST (
    I$GRADE_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    OBJ_CAPTION VARCHAR(4000),
    SORT_ORDER DOUBLE PRECISION)
AS
BEGIN
    FOR SELECT DISTINCT L51.OBJ_ID
        FROM LINKS L54
        INNER JOIN LINKS L50 ON L50.OBJ_ID = L54.PARENT_ID
        INNER JOIN LINKS L49 ON L49.PARENT_ID = L50.PARENT_ID
        INNER JOIN LINKS L51 ON L51.PARENT_ID = L49.OBJ_ID
        WHERE L54.OBJ_ID = :I$GRADE_ID
          AND L54.PARENT_TYPE_ID = 54
          AND L54.DATE_DEL IS NULL
          AND L50.PARENT_TYPE_ID = 50
          AND L50.DATE_DEL IS NULL
          AND L49.OBJ_TYPE_ID = 49
          AND L49.DATE_DEL IS NULL
          AND L51.OBJ_TYPE_ID = 51
          AND L51.DATE_DEL IS NULL
        INTO :OBJ_ID
    DO
    BEGIN
        SELECT CAPTION, SORT_ORDER
        FROM OBJECT_CAPTION_GET(:OBJ_ID, NULL, NULL, :I$USER_ID)
        INTO :OBJ_CAPTION, :SORT_ORDER;
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ_IS_GROUP_CLASSMATE (
    I$TEACHER_ID BIGINT,
    I$GROUP_ID BIGINT,
    I$GROUP_TYPE BIGINT,
    I$ROOT_ACCESS_CLASS_ID BIGINT)
RETURNS (
    IS_CLASSMATE SMALLINT)
AS
declare variable V$CLASS_ID integer;
BEGIN

    /* Как правило, тип группы передается. Но в исключительных случаях восстанавливаем */
    IF(I$GROUP_TYPE IS NULL) THEN
    BEGIN
        SELECT TYPE_ID FROM OBJECTS WHERE OBJ_ID = :I$GROUP_ID
        INTO :I$GROUP_TYPE;
    END

    /* Обычный класс */
    IF(I$GROUP_TYPE = 9) THEN
    BEGIN
    
        /* Руководство по "старой" схеме */
        IF(I$GROUP_ID = I$ROOT_ACCESS_CLASS_ID) THEN IS_CLASSMATE = 1;

        /* Руководство по "новой" схеме */
        IF(IS_CLASSMATE = 0) THEN
        BEGIN
           SELECT FIRST 1 1
           FROM VALR CR
           WHERE CR.OBJ_ID = :I$GROUP_ID AND CR.PARAM_ID = 53 AND CR.IS_DEL = 0 AND CR.VAL = :I$TEACHER_ID
           INTO :IS_CLASSMATE;
        END

    END
    /* Группа продленного дня - только в части руководства ГПД */
    ELSE IF(I$GROUP_TYPE = 46) THEN
    BEGIN

        SELECT FIRST 1 1
        FROM LINKS L186
        JOIN VALR CR ON CR.OBJ_ID = L186.OBJ_ID AND CR.PARAM_ID = 53 AND CR.IS_DEL = 0 AND CR.VAL = :I$TEACHER_ID
        WHERE L186.PARENT_ID = :I$GROUP_ID AND L186.OBJ_TYPE_ID = 186 AND L186.DATE_DEL IS NULL
        INTO :IS_CLASSMATE;

    END
    /* Для деления на потоки (выборка в КЖ) нужно проверять по всем детям, входящим в подчиненные потоки */
    ELSE IF(I$GROUP_TYPE = 346) THEN
    BEGIN

        SELECT FIRST 1 1
        FROM LINKS L347
        JOIN LINKS L10 ON L10.PARENT_ID = L347.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        JOIN LINKS LP9 ON LP9.PARENT_TYPE_ID = 9 AND LP9.OBJ_ID = L10.OBJ_ID AND LP9.DATE_DEL IS NULL
        LEFT JOIN VALR CR ON CR.OBJ_ID = LP9.PARENT_ID AND CR.PARAM_ID = 53 AND CR.IS_DEL = 0 AND CR.VAL = :I$TEACHER_ID
        WHERE L347.PARENT_ID = :I$GROUP_ID AND L347.OBJ_TYPE_ID = 347 AND L347.DATE_DEL IS NULL
            AND (CR.VAL = :I$TEACHER_ID OR LP9.PARENT_ID = :I$ROOT_ACCESS_CLASS_ID)
        INTO :IS_CLASSMATE;

    END
    /* Коллективы УДОД - проверяем назначенного в кружке руководителя */
    ELSE IF(I$GROUP_TYPE = 243) THEN
    BEGIN

        SELECT FIRST 1 1
        FROM LINKS LP242
        LEFT JOIN VALR CR ON CR.OBJ_ID = LP242.PARENT_ID AND CR.PARAM_ID = 2113 AND CR.IS_DEL = 0 AND CR.VAL = :I$TEACHER_ID
        WHERE LP242.OBJ_ID = :I$GROUP_ID AND LP242.PARENT_TYPE_ID = 242 AND LP242.DATE_DEL IS NULL
            -- Пока непонятно, что именно переназначается в доступе - кружок или коллектив
            AND (CR.VAL = :I$TEACHER_ID OR LP242.OBJ_ID = :I$ROOT_ACCESS_CLASS_ID OR LP242.PARENT_ID = :I$ROOT_ACCESS_CLASS_ID)
        INTO :IS_CLASSMATE;

    END
    /* Все прочие виды групп и коллективов - связка только через учащихся */
    ELSE
    BEGIN

        SELECT FIRST 1 1
        FROM LINKS L10
        JOIN LINKS LP9 ON LP9.PARENT_TYPE_ID = 9 AND LP9.OBJ_ID = L10.OBJ_ID AND LP9.DATE_DEL IS NULL
        LEFT JOIN VALR CR ON CR.OBJ_ID = LP9.PARENT_ID AND CR.PARAM_ID = 53 AND CR.IS_DEL = 0 AND CR.VAL = :I$TEACHER_ID
        WHERE L10.PARENT_ID = :I$GROUP_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
            AND (CR.VAL = :I$TEACHER_ID OR LP9.PARENT_ID = :I$ROOT_ACCESS_CLASS_ID)
        INTO :IS_CLASSMATE;

    END

    IF(IS_CLASSMATE IS NULL) THEN IS_CLASSMATE = 0;

    SUSPEND;

END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ_PTP_GET (
    I$PTP_ID BIGINT,
    I$USER_ID VARCHAR(40),
    I$CJ_ID BIGINT = NULL,
    I$NEW_TYPE_ID BIGINT = NULL)
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$PTP_ID BIGINT;
DECLARE VARIABLE V$ID BIGINT;
DECLARE VARIABLE V$TYPE INTEGER;
DECLARE VARIABLE V$OBJ_NAME VARCHAR(1000);
DECLARE VARIABLE V$PARENT_ID BIGINT;
DECLARE VARIABLE V$OWNER_ID BIGINT;
DECLARE VARIABLE V$LEVEL_ID BIGINT;
DECLARE VARIABLE V$SUBJECT_ID BIGINT;
DECLARE VARIABLE V$LEVEL_NUM INTEGER;
DECLARE VARIABLE V$PTP_HOURS INTEGER;
DECLARE VARIABLE V$LESSON_ID BIGINT;
DECLARE VARIABLE V$HOMESTASK VARCHAR(1000);
DECLARE VARIABLE V$DURATION FLOAT;
DECLARE VARIABLE V$SHORT VARCHAR(100);
DECLARE VARIABLE V$MASK VARCHAR(100);
DECLARE VARIABLE V$TYPENAME VARCHAR(100);
DECLARE VARIABLE V$OU_LICENCE_TYPE CHAR(1);
DECLARE VARIABLE V$STAGE_ID BIGINT;
DECLARE VARIABLE V$PLAN_ID BIGINT;
DECLARE VARIABLE V$HOURS FLOAT;
DECLARE VARIABLE V$JOURNAL_TYPE INTEGER;
DECLARE VARIABLE V$APPROVAL_STATE INTEGER;
DECLARE VARIABLE V$TMP BIGINT;
DECLARE VARIABLE V$CJ_ID BIGINT;
DECLARE VARIABLE V$USED SMALLINT;
DECLARE VARIABLE V$MAP VARCHAR(1000);
DECLARE VARIABLE V$VNUM VARCHAR(40);
DECLARE VARIABLE V$TYPE_ID BIGINT;
DECLARE VARIABLE V$EDU_LEVEL_ID BIGINT;
DECLARE VARIABLE V$STAGE_MASK BIGINT;
DECLARE VARIABLE V$CJHOURS FLOAT;
DECLARE VARIABLE V$GEN BIGINT;
DECLARE VARIABLE V$MUL BIGINT;
DECLARE VARIABLE V$OU_ID BIGINT;
DECLARE VARIABLE V$HAS_DO SMALLINT;
DECLARE VARIABLE V$HAS_OO SMALLINT;
DECLARE VARIABLE V$HAS_SPO SMALLINT;
DECLARE VARIABLE V$HAS_PO SMALLINT;
DECLARE VARIABLE V$SORT_ORDER BIGINT;
DECLARE VARIABLE V$LEVEL_PARENT BIGINT;
BEGIN

  SELECT STATUS FROM OU_LICENCE_TYPE INTO :V$OU_LICENCE_TYPE;

  SELECT P.OBJ_ID, P.OBJ_NAME, P.PARENT_ID, P.OWNER_ID, P.LEVEL_ID, P.SUBJECT_ID, P.LEVEL_NUM, P.PTP_HOURS, P.EDU_LEVEL_ID, P.STAGE_MASK, LV.PARENT_ID
  FROM PTP P
  LEFT JOIN LISTVALS LV ON LV.LISTVAL_ID = P.LEVEL_ID
  WHERE P.OBJ_ID = :I$PTP_ID AND P.DATE_DEL IS NULL
  INTO :V$PTP_ID, :V$OBJ_NAME, :V$PARENT_ID, :V$OWNER_ID, :V$LEVEL_ID, :V$SUBJECT_ID, :V$LEVEL_NUM, :V$PTP_HOURS, :V$EDU_LEVEL_ID, :V$STAGE_MASK, :V$LEVEL_PARENT;

  IF(I$PTP_ID IS NOT NULL AND V$PTP_ID IS NULL) THEN EXCEPTION DATA_ERROR 'ПТП не найден или был удален';

  -- Узнаем тип журнала и статус утверждения
  SELECT FIRST 1 J.JOURNAL_TYPE, P.APPROVAL_STATE
  FROM CJ2_JOURNAL J
  LEFT JOIN CJ2_JOURNAL_PTP P ON P.CJ_ID = J.OBJ_ID AND P.DATE_DEL IS NULL AND (P.PTP_ID = :I$PTP_ID OR P.APPROVAL_STATE IN (1, 2))
  WHERE J.OBJ_ID = :I$CJ_ID
  ORDER BY 2
  INTO :V$JOURNAL_TYPE, :V$APPROVAL_STATE;

  SELECT GEN, MULTIPLIER
  FROM GEN
  INTO :V$GEN, :V$MUL;

  SELECT FIRST 1 L2.OBJ_ID
  FROM LINKS L2
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$OU_ID;

  V$HAS_DO = 0;
  V$HAS_OO = 0;
  V$HAS_SPO = 0;
  V$HAS_PO = 0;
  SELECT FIRST 1 1
  FROM LINKS L472
  JOIN VALL V3327 ON V3327.OBJ_ID = L472.OBJ_ID AND V3327.PARAM_ID = 3327 AND V3327.IS_DEL = 0 AND V3327.LISTVAL_ID IN (21, 3263, 3264)
  WHERE L472.PARENT_ID = :V$OU_ID AND L472.OBJ_TYPE_ID = 472 AND L472.DATE_DEL IS NULL
  INTO :V$HAS_DO;

  SELECT FIRST 1 1
  FROM LINKS L472
  JOIN VALL V3327 ON V3327.OBJ_ID = L472.OBJ_ID AND V3327.PARAM_ID = 3327 AND V3327.IS_DEL = 0 AND V3327.LISTVAL_ID IN (22, 26, 27)
  WHERE L472.PARENT_ID = :V$OU_ID AND L472.OBJ_TYPE_ID = 472 AND L472.DATE_DEL IS NULL
  INTO :V$HAS_OO;

  SELECT FIRST 1 1
  FROM LINKS L472
  JOIN VALL V3327 ON V3327.OBJ_ID = L472.OBJ_ID AND V3327.PARAM_ID = 3327 AND V3327.IS_DEL = 0 AND V3327.LISTVAL_ID IN (28, 29, 13129)
  WHERE L472.PARENT_ID = :V$OU_ID AND L472.OBJ_TYPE_ID = 472 AND L472.DATE_DEL IS NULL
  INTO :V$HAS_SPO;

  SELECT FIRST 1 1
  FROM LINKS L472
  JOIN VALL V3327 ON V3327.OBJ_ID = L472.OBJ_ID AND V3327.PARAM_ID = 3327 AND V3327.IS_DEL = 0 AND V3327.LISTVAL_ID IN (13129, 13131)
  WHERE L472.PARENT_ID = :V$OU_ID AND L472.OBJ_TYPE_ID = 472 AND L472.DATE_DEL IS NULL
  INTO :V$HAS_PO;

  TAG_NAME = 'id';
  VAL = I$PTP_ID;
  SUSPEND;

  TAG_NAME = 'obj_name';
  VAL = V$OBJ_NAME;
  SUSPEND;

  TAG_NAME = 'level_num';
  VAL = V$LEVEL_NUM;
  SUSPEND;

  TAG_NAME = 'ptp_hours';
  VAL = V$PTP_HOURS;
  SUSPEND;

  TAG_NAME = 'parent_id';
  VAL = V$PARENT_ID;
  SUSPEND;
  TAG_NAME = 'parent_name';
  VAL = (SELECT OBJ_NAME FROM PTP WHERE OBJ_ID = :V$PARENT_ID);
  SUSPEND;

  -- Блокировка для ПТП (рабочих программ, ФПП), созданных в другой базе
  IF(I$PTP_ID IS NOT NULL AND I$PTP_ID / V$MUL <> V$GEN) THEN
  BEGIN
    TAG_NAME = 'row_readonly';
    VAL = 1;
    SUSPEND;
  END

  -- Наличие дочерних ПТП
  TAG_NAME = 'has_children';
  VAL = 0;
  SELECT FIRST 1 1
  FROM PTP
  WHERE DATE_DEL IS NULL AND PARENT_ID = :I$PTP_ID
  INTO :VAL;
  SUSPEND;

  -- Отдаем полный список предметов, далее он фильтруется
  -- Временно !!! для СПО только дисциплины
  TAG_NAME = 'subject_id';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'subject_id:selection';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'subject_id:selection::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L51.OBJ_ID, C.CAPTION, IIF(L51.PARENT_ID IN (32771, 12313), 0, 1)
    FROM LINKS L51
    LEFT JOIN OBJECT_CAPTION_GET(L51.OBJ_ID) C ON 1 = 1
    WHERE L51.PARENT_ID IN (32771, 32772, 12313) AND L51.OBJ_TYPE_ID IN (51, 197) AND L51.DATE_DEL IS NULL AND
      ((L51.OBJ_TYPE_ID = 51 AND :V$OU_LICENCE_TYPE IN ('O', 'S') AND :V$HAS_OO = 1) OR (L51.OBJ_TYPE_ID = 197 AND :V$OU_LICENCE_TYPE IN ('C', 'S') AND :V$HAS_SPO = 1))
    ORDER BY L51.OBJ_TYPE_ID,  2
    INTO :V$ID, :V$OBJ_NAME, :V$TYPE
  DO
  BEGIN
    TAG_NAME = 'subject_id:selection:option';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'subject_id:selection:option:id';
    VAL = V$ID;
    SUSPEND;
    TAG_NAME = 'subject_id:selection:option:value';
    VAL = V$OBJ_NAME;
    SUSPEND;
    TAG_NAME = 'subject_id:selection:option:type';
    VAL = V$TYPE;
    SUSPEND;
  END
  TAG_NAME = 'subject_id:values:value';
  VAL = V$SUBJECT_ID;
  SUSPEND;

  -- Списки учителей для выбора, всегда в список добавляем самого себя
  TAG_NAME = 'owner_id:selection::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
      SELECT L14.OBJ_ID, C.CAPTION
      FROM LINKS L14
      LEFT JOIN OBJECT_CAPTION_GET(L14.OBJ_ID) C ON 1 = 1
      WHERE L14.PARENT_TYPE_ID = 2 AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
      UNION
      SELECT L14.OBJ_ID, C.CAPTION
      FROM LINKS L211
      JOIN LINKS L14 ON L14.PARENT_ID = L211.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
      LEFT JOIN OBJECT_CAPTION_GET(L14.OBJ_ID) C ON 1 = 1
      WHERE L211.PARENT_TYPE_ID = 2 AND L211.OBJ_TYPE_ID = 211 AND L211.DATE_DEL IS NULL
      UNION
      SELECT :V$OWNER_ID, C.CAPTION
      FROM RDB$DATABASE
      LEFT JOIN OBJECT_CAPTION_GET(:V$OWNER_ID) C ON 1 = 1
      WHERE :V$OWNER_ID IS NOT NULL
      ORDER BY 2
      INTO :V$ID, :V$OBJ_NAME
  DO
  BEGIN
    TAG_NAME = 'owner_id:selection:option';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'owner_id:selection:option:id';
    VAL = V$ID;
    SUSPEND;
    TAG_NAME = 'owner_id:selection:option:value';
    VAL = V$OBJ_NAME;
    SUSPEND;
  END
  TAG_NAME = 'owner_id:values:value';
  VAL = V$OWNER_ID;
  SUSPEND;

  -- Виды уроков
  TAG_NAME = 'lesson_types::json&colon;array';
  VAL = 1;
  SUSPEND;
  -- ФРП и общеобразовательные
  IF(I$NEW_TYPE_ID = 0 OR V$LEVEL_PARENT IN (2141, 12941)) THEN
  BEGIN
    FOR
      SELECT L.LISTVAL_ID, L.VAL, L.TAG
      FROM LISTVALS_LIST(389) L
      WHERE L.IS_DEL = 0
      INTO :V$LESSON_ID, :V$OBJ_NAME, :V$SHORT
    DO
    BEGIN
      TAG_NAME = 'lesson_types:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'lesson_types:r:id';
      VAL = V$LESSON_ID;
      SUSPEND;
      TAG_NAME = 'lesson_types:r:value';
      VAL = V$OBJ_NAME;
      SUSPEND;
      TAG_NAME = 'lesson_types:r:short';
      VAL = V$SHORT;
      SUSPEND;
    END
  END

  -- Выбор уровня: для общеобразовательных не показываем уровни ДОУ и Весь курс, для журналов посещения показываем только ДОУ и Весь курс
  TAG_NAME = 'level_id:selection::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
      SELECT V.LISTVAL_ID, V.PARENT_ID, VAL, IIF(V.LISTVAL_ID = 2141, -3, IIF(V.LISTVAL_ID = 2143, -2, IIF(V.LISTVAL_ID = 2155, -1, IIF(V.LISTVAL_ID = 2167, -4, V.SORT_ORDER))))
      FROM (
          -- Старая схема
          SELECT F.LISTVAL_ID, F.PARENT_ID, F.VAL, F.SORT_ORDER
          FROM OO_FILTRED_LIST(25) F
          WHERE :V$OU_LICENCE_TYPE <> 'S'
          -- Новая схема
          UNION
          SELECT LV.LISTVAL_ID, LV.PARENT_ID, C.VAL, LV.SORT_ORDER
          FROM LISTVALS LV
          LEFT JOIN LISTVAL_TEXT(LV.LISTVAL_ID) C ON 1 = 1
          WHERE LV.LIST_ID = 25 AND LV.IS_DEL = 0 AND :V$OU_LICENCE_TYPE = 'S'
          AND (
            (LV.PARENT_ID = 2140 AND :V$HAS_DO = 1) -- тут надо проверить, а в том ли разделе оно показывается ? надо чтобы было в журналах посещения
            OR (LV.PARENT_ID = 2141 AND :V$HAS_OO = 1)
            OR (LV.PARENT_ID = 2142 AND :V$HAS_SPO = 1)
          )
          UNION
          SELECT 2143, NULL, 'Дополнительное образование', NULL
          FROM RDB$DATABASE
          UNION
          SELECT 2155, NULL, 'Внеурочная деятельность', NULL
          FROM RDB$DATABASE
          UNION
          SELECT 2167, NULL, 'Рабочие программы', NULL
          FROM RDB$DATABASE
          UNION
          SELECT 2200, NULL, 'Федеральные ПП', NULL
          FROM RDB$DATABASE
      ) V
      WHERE V.PARENT_ID IN (2140, 2141, 2142, 2143, 2144) OR V.LISTVAL_ID IN (2141, 2143, 2155, 2167)
      ORDER BY 4
      INTO :V$ID, :V$PARENT_ID, :V$OBJ_NAME, :V$TYPE
  DO
  BEGIN
    -- Скрываем лишние этапы между 0 и 1 разделами
    IF(I$NEW_TYPE_ID = 0 AND (V$PARENT_ID NOT IN (2141, 2142, 12941) OR V$ID = 13145)) THEN V$ID = NULL;
    IF(I$NEW_TYPE_ID = 4 AND (V$PARENT_ID IN (2141, 12941) OR (V$PARENT_ID = 2142 AND V$ID <> 13145))) THEN V$ID = NULL;
    IF(V$ID IS NOT NULL) THEN
    BEGIN
      TAG_NAME = 'level_id:selection:option';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'level_id:selection:option:id';
      VAL = V$ID;
      SUSPEND;
      TAG_NAME = 'level_id:selection:option:value';
      IF(V$ID = 2141) THEN V$OBJ_NAME = 'ГПД';
      IF(V$OU_LICENCE_TYPE = 'P' AND V$ID = 2143) THEN V$OBJ_NAME = 'Журналы занятий';
      VAL = V$OBJ_NAME;
      SUSPEND;
    END
  END
  TAG_NAME = 'level_id:values:value';
  IF(I$NEW_TYPE_ID = 1) THEN I$NEW_TYPE_ID = 2155; -- ВД
  ELSE IF(I$NEW_TYPE_ID = 2) THEN I$NEW_TYPE_ID = 2141; -- ГПД
  ELSE IF(I$NEW_TYPE_ID = 3) THEN I$NEW_TYPE_ID = 2143; -- ДО
  ELSE IF(I$NEW_TYPE_ID = 100) THEN I$NEW_TYPE_ID = 2167; -- Рабочие программы
  ELSE I$NEW_TYPE_ID = NULL;
  VAL = COALESCE(V$LEVEL_ID, I$NEW_TYPE_ID);
  SUSPEND;

  -- Для ФП выдаем этапы обучения именно тут, для РП выдаем уровни образования, в остальных случаях ничего
  TAG_NAME = 'edu_level_id:selection::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
      SELECT V.LISTVAL_ID, VAL
      FROM LISTVALS_LIST(19) V
      WHERE V.PARENT_ID IS NULL AND V.IS_DEL = 0 AND (:I$NEW_TYPE_ID = 2167 OR :V$TYPE_ID = 2167)
        AND (
          ((:V$OU_LICENCE_TYPE = 'O' OR :V$HAS_OO = 1) AND V.LISTVAL_ID IN (21, 22, 26, 27)) OR
          ((:V$OU_LICENCE_TYPE = 'C' OR :V$HAS_SPO = 1) AND V.LISTVAL_ID IN (27, 28, 29, 13130)) OR
          ((:V$OU_LICENCE_TYPE = 'D' OR :V$HAS_DO = 1) AND V.LISTVAL_ID IN (21))
        )
      INTO :V$ID, :V$OBJ_NAME
  DO
  BEGIN
      TAG_NAME = 'edu_level_id:selection:option';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'edu_level_id:selection:option:id';
      VAL = V$ID;
      SUSPEND;
      TAG_NAME = 'edu_level_id:selection:option:value';
      VAL = V$OBJ_NAME;
      SUSPEND;
  END
  TAG_NAME = 'edu_level_id:values:value';
  VAL = V$EDU_LEVEL_ID;
  SUSPEND;

  -- Поле маски этапов и данные для выбора
  TAG_NAME = 'stage_mask:selection::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
      -- Старая схема выборки
      SELECT F.LISTVAL_ID, F.VAL, F.COST, F.SORT_ORDER
      FROM OO_FILTRED_LIST(25) F
      WHERE F.PARENT_ID IN (2140, 2141, 2142) AND :V$OU_LICENCE_TYPE <> 'S'
      -- Новая схема выборки, мультипараграф
      UNION
      SELECT LV.LISTVAL_ID, C.VAL, LV.COST, LV.SORT_ORDER
      FROM LISTVALS LV
      LEFT JOIN LISTVAL_TEXT(LV.LISTVAL_ID) C ON 1 = 1
      WHERE LV.LIST_ID = 25 AND LV.IS_DEL = 0 AND :V$OU_LICENCE_TYPE = 'S'
      AND (LV.LISTVAL_ID = :V$STAGE_ID
        OR (LV.PARENT_ID = 2141 AND :V$HAS_OO = 1)
        OR (LV.PARENT_ID = 2142 AND :V$HAS_SPO = 1 AND LV.LISTVAL_ID <> 13145)
        OR (LV.LISTVAL_ID = 13145 AND :V$HAS_PO = 1) -- весь курс обучения - только в ДПО или курсах
      )
      ORDER BY 4
      INTO :V$ID, :V$OBJ_NAME, :V$TMP, :V$SORT_ORDER
  DO
  BEGIN
      TAG_NAME = 'stage_mask:selection:option';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'stage_mask:selection:option:id';
      VAL = V$ID;
      SUSPEND;
      TAG_NAME = 'stage_mask:selection:option:value';
      VAL = V$OBJ_NAME;
      SUSPEND;
      TAG_NAME = 'stage_mask:selection:option:subset_id';
      VAL = V$TMP;
      SUSPEND;
  END
  -- Само значение надо разобрать побитно на фронте
  TAG_NAME = 'stage_mask:values:value';
  VAL = V$STAGE_MASK;
  SUSPEND;

  -- Список видов контроля
  IF(V$OU_LICENCE_TYPE = 'O') THEN V$TYPENAME = 'GOU';
  ELSE IF(V$OU_LICENCE_TYPE = 'C') THEN V$TYPENAME = 'COLLEGE';
  ELSE IF(V$OU_LICENCE_TYPE = 'D') THEN V$TYPENAME = 'DOU';
  ELSE IF(V$OU_LICENCE_TYPE = 'U') THEN V$TYPENAME = 'UDOD';
  ELSE IF(V$OU_LICENCE_TYPE = 'P') THEN V$TYPENAME = 'DPO';

  TAG_NAME = 'controls::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    -- Для мультипараграфа пока показываем все виды контроля, надо доработать
    SELECT T.CONTROL_TYPE_ID, T.CONTROL_NAME, T.CONTROL_SHORTNAME, T.CONTROL_DESC, T.TYPE_MASK
    FROM CJ2_CONTROL_TYPE T
    WHERE T.IS_DEL = 0 AND T.CONTROL_TYPE_ID > 0 AND (T."FILTER" IS NULL OR POSITION(:V$TYPENAME IN T."FILTER") > 0 OR :V$OU_LICENCE_TYPE = 'S')
    INTO :V$ID, :V$OBJ_NAME, :V$SHORT, :V$HOMESTASK, :V$MASK
  DO
  BEGIN
    TAG_NAME = 'controls:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'controls:r:id';
    VAL = V$ID;
    SUSPEND;
    TAG_NAME = 'controls:r:name';
    VAL = V$OBJ_NAME;
    SUSPEND;
    TAG_NAME = 'controls:r:description';
    VAL = V$HOMESTASK;
    SUSPEND;
    TAG_NAME = 'controls:r:code';
    VAL = V$SHORT;
    SUSPEND;
    TAG_NAME = 'controls:r:mask';
    VAL = V$MASK;
    SUSPEND;
  END

  TAG_NAME = 'assignments::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT J.OBJ_ID, J.JOURNAL_NAME, P.APPROVAL_STATE, J.SUBJECT_ID, J.STAGE_INDEX, J.REF_ID, J.HOURS
    FROM CJ2_JOURNAL_PTP P
    JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.OBJ_ID = P.CJ_ID
    WHERE P.DATE_DEL IS NULL AND P.PTP_ID = :I$PTP_ID
    INTO :V$ID, :V$OBJ_NAME, :V$TYPE, :V$SUBJECT_ID, :V$STAGE_ID, :V$PLAN_ID, :V$HOURS
  DO
  BEGIN
    TAG_NAME = 'assignments:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'assignments:r:id';
    VAL = V$ID;
    SUSPEND;
    TAG_NAME = 'assignments:r:name';
    VAL = V$OBJ_NAME;
    SUSPEND;
    TAG_NAME = 'assignments:r:state';
    VAL = V$TYPE;
    SUSPEND;
    -- Часы по учебному плану
    TAG_NAME = 'assignments:r:hours';
    VAL = V$HOURS;
    SUSPEND;
  END

  -- tests надо выдать обязательно ДО lessons, иначе ломается выдача списка для КЖ
  -- Не выдаем id самого теста, считаем что в одном уроке может быть только один тест одного вида
  TAG_NAME = 'tests::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L.OBJ_ID, LT.CONTROL_TYPE_ID, LT.TEST_ID, D.OBJ_NAME
    FROM PTP_LESSONS L
    JOIN PTP_LESSON_TESTS LT ON LT.DATE_DEL IS NULL AND LT.LESSON_ID = L.OBJ_ID
    JOIN UT_EXAM_DATES D ON D.DATE_DEL IS NULL AND D.OBJ_ID = LT.TEST_ID
    WHERE L.DATE_DEL IS NULL AND L.PTP_ID = :I$PTP_ID
    INTO :V$LESSON_ID, :V$STAGE_ID, :V$TMP, :V$OBJ_NAME
  DO
  BEGIN
    TAG_NAME = 'tests:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'tests:r:lesson_id';
    VAL = V$LESSON_ID;
    SUSPEND;
    TAG_NAME = 'tests:r:control';
    VAL = V$STAGE_ID;
    SUSPEND;
    TAG_NAME = 'tests:r:test_id';
    VAL = V$TMP;
    SUSPEND;
    TAG_NAME = 'tests:r:name';
    VAL = V$OBJ_NAME;
    SUSPEND;
  END

  -- Элементы ПТП - специально переставлены в конец
  TAG_NAME = 'lessons::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L.OBJ_ID, L.LESSON_NUM, L.THEME_TEXT, L.HOMETASK_TEXT, L.DURATION, L.TYPE_ID, L.EXTRA_TEXT, L.VIRT_NUM, L.STAGE_ID
    FROM PTP_LESSONS L
    WHERE L.DATE_DEL IS NULL AND L.PTP_ID = :I$PTP_ID
    ORDER BY L.LESSON_NUM
    INTO :V$LESSON_ID, :V$LEVEL_NUM, :V$OBJ_NAME, :V$HOMESTASK, :V$DURATION, :V$TYPE_ID, :V$MAP, :V$VNUM, :V$STAGE_ID
  DO
  BEGIN
    TAG_NAME = 'lessons:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'lessons:r:id';
    VAL = V$LESSON_ID;
    SUSPEND;
    TAG_NAME = 'lessons:r:lesson_num';
    VAL = V$LEVEL_NUM;
    SUSPEND;
    TAG_NAME = 'lessons:r:theme_text';
    VAL = V$OBJ_NAME;
    SUSPEND;
    TAG_NAME = 'lessons:r:hometask_text';
    VAL = V$HOMESTASK;
    SUSPEND;
    TAG_NAME = 'lessons:r:extra';
    VAL = V$MAP;
    SUSPEND;
    TAG_NAME = 'lessons:r:vnum';
    VAL = V$VNUM;
    SUSPEND;
    TAG_NAME = 'lessons:r:duration';
    VAL = V$DURATION;
    SUSPEND;
    TAG_NAME = 'lessons:r:type_id';
    VAL = V$TYPE_ID;
    SUSPEND;
    TAG_NAME = 'lessons:r:stage_id';
    VAL = V$STAGE_ID;
    SUSPEND;

      -- Был ли проведен урок ? 0 = не использован, 1 = использован, 2 = использован и проведен
      -- !!! надо проверять всю цепочку по дереву вниз
      TAG_NAME = 'lessons:r:lesson_used';
      VAL = '0';
      V$MAP = '';
      V$TMP = V$LESSON_ID;
      V$CJHOURS = 0;
      WHILE(V$TMP IS NOT NULL) DO
      BEGIN
          -- Был ли использован данный конкретный урок ?
          V$USED = NULL;
          FOR
            SELECT L.CJ_ID, MAX(L.IS_COMPLETED), SUM(L.LESSON_HOURS)
            FROM CJ2_JOURNAL_LESSONS L
            JOIN CJ2_JOURNAL_PTP JP ON JP.CJ_ID = L.CJ_ID AND JP.PTP_ID = :I$PTP_ID AND JP.DATE_DEL IS NULL AND JP.APPROVAL_STATE < 3
            WHERE (:I$CJ_ID IS NULL OR L.CJ_ID = :I$CJ_ID) AND L.LESSON_PTP_ID = :V$TMP AND L.DATE_DEL IS NULL
            GROUP BY 1
            INTO :V$CJ_ID, :V$USED, :V$HOURS
          DO
          BEGIN
            VAL = V$USED + 1;
            IF(CHAR_LENGTH(V$MAP) + CHAR_LENGTH(V$CJ_ID) + 1 < 1000) THEN V$MAP = V$MAP || V$CJ_ID || ';';
            IF(V$CJ_ID = I$CJ_ID) THEN V$CJHOURS = V$CJHOURS + V$HOURS;
          END

          -- Поднимаемся вверх
          V$TMP = (SELECT PARENT_LESSON_ID FROM PTP_LESSONS WHERE DATE_DEL IS NULL AND OBJ_ID = :V$TMP);
      END
      -- Не даем выбирать уроки в неутвержденном УП в общеобре, либо если есть другой план к утверждению
      IF(VAL = '0' AND V$JOURNAL_TYPE = 0 AND V$APPROVAL_STATE < 2) THEN VAL = '1';
      SUSPEND;

      -- Количество часов, использованных в данном журнале
      TAG_NAME = 'lessons:r:uhours';
      VAL = CAST(V$CJHOURS AS NUMERIC(18, 2));
      SUSPEND;

      TAG_NAME = 'lessons:r:usemap';
      VAL = V$MAP;
      SUSPEND;

      -- Список кодов контроля
      TAG_NAME = 'lessons:r:controls';
      VAL = '';
      FOR
          SELECT DISTINCT C.CONTROL_TYPE_ID
          FROM PTP_LESSON_CONTROLS C
          WHERE C.DATE_DEL IS NULL AND C.LESSON_ID = :V$LESSON_ID
          INTO :V$ID
      DO
      BEGIN
          IF(VAL <> '') THEN VAL = VAL || ',';
          VAL = VAL || V$ID;
      END
      SUSPEND;

      TAG_NAME = 'lessons:r:cec::json&colon;array';
      VAL = 1;
      SUSPEND;
      FOR
          SELECT CI.OBJ_ID, CI.CODE, CI.CAPTION, CI.CEC_ID, LV.TAG
          FROM PTP_LESSON_CEC R
          JOIN CEC_ITEMS CI ON CI.OBJ_ID = R.CEC_ITEM_ID
          LEFT JOIN LISTVALS LV ON LV.LISTVAL_ID = CI.STAGE_ID
          JOIN CEC C ON C.OBJ_ID = CI.CEC_ID
          WHERE R.DATE_DEL IS NULL AND R.LESSON_ID = :V$LESSON_ID
          ORDER BY C.TYPE_ID, CI.SORT_INDEX
          INTO :V$ID, :V$SHORT, :V$OBJ_NAME, :V$LEVEL_ID, :V$MASK
      DO
      BEGIN
          TAG_NAME = 'lessons:r:cec:r';
          VAL = NULL;
          SUSPEND;
          TAG_NAME = 'lessons:r:cec:r:id';
          VAL = V$ID;
          SUSPEND;
          TAG_NAME = 'lessons:r:cec:r:cec_id';
          VAL = V$LEVEL_ID;
          SUSPEND;
          TAG_NAME = 'lessons:r:cec:r:code';
          VAL = V$SHORT;
          SUSPEND;
          TAG_NAME = 'lessons:r:cec:r:name';
          VAL = V$OBJ_NAME;
          SUSPEND;
          TAG_NAME = 'lessons:r:cec:r:stage';
          VAL = V$MASK;
          SUSPEND;
      END
  END

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ_PTP_GET_FOR_CJ (
    I$CJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$PTP_ID BIGINT;
DECLARE VARIABLE V$TEACHER_ID BIGINT;
DECLARE VARIABLE V$NAME VARCHAR(1000);
DECLARE VARIABLE V$TYPE BIGINT;
DECLARE VARIABLE V$APPROVAL_STATE INTEGER;
DECLARE VARIABLE V$HAS_LESSONS SMALLINT;
DECLARE VARIABLE V$HAS_PENDING SMALLINT;
DECLARE VARIABLE V$RSRV BIGINT;
DECLARE VARIABLE V$JT INTEGER;
begin

  IF((SELECT ACCESS_LEVEL FROM CJ2_JOURNAL_ACCESS(:I$USER_ID, :I$CJ_ID)) = 0) THEN EXCEPTION DATA_ERROR 'Нет доступа к журналу';

  SELECT FIRST 1 P.PTP_ID, P.APPROVAL_STATE, J.JOURNAL_TYPE
  FROM CJ2_JOURNAL J
  JOIN CJ2_JOURNAL_PTP P ON P.DATE_DEL IS NULL AND P.CJ_ID = J.OBJ_ID AND P.APPROVAL_STATE <> 3
  WHERE J.DATE_DEL IS NULL AND J.OBJ_ID = :I$CJ_ID
  ORDER BY P.APPROVAL_STATE DESC
  INTO :V$PTP_ID, :V$APPROVAL_STATE, :V$JT;

  -- Для общеобразовательных журналов не даем работать с неутвержденными ПТП
  IF(V$JT = 0 AND V$APPROVAL_STATE <> 2) THEN EXCEPTION DATA_ERROR 'Нельзя выбирать уроки из неутвержденного ПТП';

  -- Нельзя добавлять уроки, если есть неутвержденная коррекция ПТП
  IF(V$JT = 0 AND EXISTS(
    SELECT FIRST 1 1
    FROM CJ2_JOURNAL_PTP P
    WHERE P.DATE_DEL IS NULL AND P.CJ_ID = :I$CJ_ID AND P.APPROVAL_STATE = 1
  ))
  THEN
    EXCEPTION DATA_ERROR 'Нельзя добавлять уроки, пока откорректированный ПТП не утвержден';

  V$HAS_PENDING = 0;
  SELECT FIRST 1 1
  FROM CJ2_JOURNAL J
  JOIN CJ2_JOURNAL_PTP P ON P.DATE_DEL IS NULL AND P.CJ_ID = J.OBJ_ID AND P.APPROVAL_STATE = 1
  WHERE J.DATE_DEL IS NULL AND J.OBJ_ID = :I$CJ_ID
  INTO :V$HAS_PENDING;

  TAG_NAME = 'teacher_id';
  VAL = NULL;
  SELECT FIRST 1 TEACHER_ID
  FROM (
    SELECT J.TEACHER_ID
    FROM CJ2_JOURNAL J
    WHERE J.OBJ_ID = :I$CJ_ID AND J.TEACHER_ID IS NOT NULL
    UNION
    SELECT FIRST 1 V1609.VAL
    FROM CJ2_JOURNAL J
    JOIN LINKS L186 ON L186.PARENT_ID = J.GRADE_ID AND L186.OBJ_TYPE_ID = 186 AND L186.DATE_DEL IS NULL
    JOIN VALR V1609 ON V1609.OBJ_ID = L186.OBJ_ID AND V1609.PARAM_ID = 1609 AND V1609.IS_DEL = 0
    WHERE J.OBJ_ID = :I$CJ_ID
  )
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'teachers::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT TEACHER_ID, TEACHER_NAME, TEACHER_TYPE
    FROM CJ2_LESSON_TEACHERS_LIST(:I$CJ_ID, NULL, :I$USER_ID)
    ORDER BY 3, 2
    INTO :V$TEACHER_ID, :V$NAME, :V$TYPE
  DO
  BEGIN
    TAG_NAME = 'teachers:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'teachers:r:id';
    VAL = V$TEACHER_ID;
    SUSPEND;
    TAG_NAME = 'teachers:r:name';
    VAL = V$NAME;
    SUSPEND;
    TAG_NAME = 'teachers:r:type';
    VAL = V$TYPE;
    SUSPEND;
  END

  -- На отсутствие ПТП не ругаемся, просто выдадим пустой ПТП
  V$HAS_LESSONS = 0;
  FOR
    SELECT TAG_NAME, VAL
    FROM CJ_PTP_GET(:V$PTP_ID, :I$USER_ID, :I$CJ_ID)
    INTO :TAG_NAME, :VAL
  DO
  BEGIN
    IF(TAG_NAME = 'lessons:r') THEN V$HAS_LESSONS = 1;
    IF(V$APPROVAL_STATE <> 2 OR V$HAS_PENDING = 0 OR POSITION('lessons:r' IN TAG_NAME) <= 0) THEN SUSPEND;
  END

  -- Добавляем резервный урок
  IF(V$HAS_LESSONS = 0) THEN
  BEGIN
    TAG_NAME = 'lessons';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'lessons::json&colon;array';
    VAL = 1;
    SUSPEND;
  END

  IF(V$APPROVAL_STATE = 2 AND V$HAS_PENDING = 1) THEN
  BEGIN
    TAG_NAME = 'lessons:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'lessons:r:id';
    VAL = 0;
    SUSPEND;
    TAG_NAME = 'lessons:r:lesson_num';
    VAL = 0;
    SUSPEND;
    TAG_NAME = 'lessons:r:theme_text';
    VAL = 'Нельзя добавлять уроки, пока новый ПТП не утвержден';
    SUSPEND;
    TAG_NAME = 'lessons:r:hometask_text';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'lessons:r:duration';
    VAL = 1;
    SUSPEND;
    TAG_NAME = 'lessons:r:lesson_used';
    VAL = '1';
    SUSPEND;
    TAG_NAME = 'lessons:r:controls';
    VAL = '';
    SUSPEND;
    TAG_NAME = 'lessons:r:cec::json&colon;array';
    VAL = 1;
    SUSPEND;
  END

  -- Разрешен ли резервный урок ?
  SELECT FIRST 1 COALESCE(V3369.LISTVAL_ID, 3)
  FROM LINKS L2
  LEFT JOIN VALL V3369 ON V3369.OBJ_ID = L2.OBJ_ID AND V3369.PARAM_ID = 3369 AND V3369.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$RSRV;

  IF(V$RSRV = 2) THEN
  BEGIN
    TAG_NAME = 'lessons:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'lessons:r:id';
    VAL = 0;
    SUSPEND;
    TAG_NAME = 'lessons:r:lesson_num';
    VAL = 0;
    SUSPEND;
    TAG_NAME = 'lessons:r:theme_text';
    VAL = 'Резервный урок';
    SUSPEND;
    TAG_NAME = 'lessons:r:hometask_text';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'lessons:r:duration';
    VAL = 1;
    SUSPEND;
    TAG_NAME = 'lessons:r:lesson_used';
    VAL = '0';
    SUSPEND;
    TAG_NAME = 'lessons:r:controls';
    VAL = '';
    SUSPEND;
    TAG_NAME = 'lessons:r:cec::json&colon;array';
    VAL = 1;
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ_PTP_LIST_TEMPLATES (
    STAGE_ID BIGINT,
    SUBJECT_ID BIGINT)
RETURNS (
    GRADE_ID BIGINT,
    GRADE_NAME VARCHAR(1000),
    TEACHER_ID BIGINT,
    TEACHER_NAME VARCHAR(1000),
    HOURS INTEGER,
    GRADE_TYPE_ID BIGINT)
AS
declare variable V$STAGE_LV bigint;
declare variable V$OBJ_ID bigint;
begin
  -- Получаем LISTVAL_ID для уровня образования
  SELECT V49.LISTVAL_ID
  FROM VALL V49
  WHERE V49.OBJ_ID = :STAGE_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
  INTO :V$STAGE_LV;

  IF(V$STAGE_LV IS NULL) THEN EXIT;

  FOR
    -- Выбираем ID этапов обучения в УП
    SELECT L54.OBJ_ID, SUM(V385.VAL)
    FROM LINKS L2
    -- Образовательные программы - только общего образования
    JOIN LINKS L69 ON L69.PARENT_ID = L2.OBJ_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL
    JOIN VALL V2450 ON V2450.OBJ_ID = L69.OBJ_ID AND V2450.PARAM_ID = 2450 AND V2450.IS_DEL = 0 AND V2450.LISTVAL_ID = 11385
    -- ОП
    JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
    -- Учебные планы - только групповые
    JOIN LINKS L50 ON L50.PARENT_ID = L57.OBJ_ID AND L50.OBJ_TYPE_ID = 50 AND L50.DATE_DEL IS NULL
    JOIN VALL V2101 ON V2101.OBJ_ID = L50.OBJ_ID AND V2101.PARAM_ID = 2101 AND V2101.IS_DEL = 0 AND V2101.LISTVAL_ID = 5465
    -- Этап, соответствующий требуемому
    JOIN LINKS L54 ON L54.PARENT_ID = L50.OBJ_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
    JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0 AND V381.LISTVAL_ID = :V$STAGE_LV
    -- Где есть ненулевая нагрузка в часах по требуемому предмету
    JOIN LINKS L56 ON L56.PARENT_ID = L54.OBJ_ID AND L56.OBJ_TYPE_ID = 56 AND L56.DATE_DEL IS NULL
    JOIN LINKS LP51 ON LP51.OBJ_ID = L56.OBJ_ID AND LP51.PARENT_ID = :SUBJECT_ID AND L56.DATE_DEL IS NULL
    JOIN VALI V385 ON V385.OBJ_ID = L56.OBJ_ID AND V385.PARAM_ID = 385 AND V385.IS_DEL = 0 AND V385.VAL > 0
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    GROUP BY 1
    HAVING SUM(V385.VAL) > 0
    INTO :V$OBJ_ID, :HOURS
  DO
  BEGIN
    -- Выбираем связку с нагрузкой коллектива
    FOR
      SELECT DISTINCT LPG.PARENT_ID, C.CAPTION, LP14.PARENT_ID, C14.CAPTION, LPG.PARENT_TYPE_ID
      FROM LINKS L56
      JOIN LINKS L58 ON L58.PARENT_ID = L56.OBJ_ID AND L58.OBJ_TYPE_ID = 58 AND L58.DATE_DEL IS NULL
      JOIN LINKS LPG ON LPG.OBJ_ID = L58.OBJ_ID AND LPG.PARENT_TYPE_ID IN (256, 347, 48) AND LPG.DATE_DEL IS NULL
      JOIN LINKS LP51 ON LP51.PARENT_ID = :SUBJECT_ID AND LP51.OBJ_ID = L58.OBJ_ID AND LP51.DATE_DEL IS NULL
      JOIN LINKS LP14 ON LP14.OBJ_ID = L58.OBJ_ID AND LP14.PARENT_TYPE_ID = 14 AND LP14.DATE_DEL IS NULL
      LEFT JOIN OBJECT_CAPTION_GET(LPG.PARENT_ID) C ON 1 = 1
      LEFT JOIN OBJECT_CAPTION_GET(LP14.PARENT_ID) C14 ON 1 = 1
      WHERE L56.PARENT_ID = :V$OBJ_ID AND L56.OBJ_TYPE_ID = 56 AND L56.DATE_DEL IS NULL
      INTO :GRADE_ID, :GRADE_NAME, :TEACHER_ID, :TEACHER_NAME, :GRADE_TYPE_ID
    DO
    BEGIN
      SUSPEND;
    END
  END
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ_PTP_PLAN_HOURS (
    I$GRADE_ID BIGINT,
    I$SUBJECT_ID BIGINT)
RETURNS (
    PLAN_HOURS INTEGER)
AS
begin
  -- Не адаптировано для колледжа !

  PLAN_HOURS = 0;

  SELECT SUM(V385.VAL)
  -- Основной цикл по нагрузкам коллектива
  FROM LINKS L58
  -- Связь с нагрузкой УП
  JOIN LINKS LP56 ON LP56.OBJ_ID = L58.OBJ_ID AND LP56.PARENT_TYPE_ID = 56 AND LP56.DATE_DEL IS NULL
  -- Связь с этапом обучения
  JOIN LINKS LP54 ON LP54.OBJ_ID = LP56.PARENT_ID AND LP54.PARENT_TYPE_ID = 54 AND LP54.DATE_DEL IS NULL
  -- Учебный компонент
  JOIN LINKS LP49 ON LP49.OBJ_ID = LP56.PARENT_ID AND LP49.PARENT_TYPE_ID = 49 AND LP49.DATE_DEL IS NULL
  -- УП
  JOIN LINKS LP50 ON LP50.OBJ_ID = LP49.PARENT_ID AND LP50.PARENT_TYPE_ID = 50 AND LP50.DATE_DEL IS NULL
  -- Предмет (тот, который реальный в УП)
  JOIN LINKS LP51 ON LP51.OBJ_ID = LP56.PARENT_ID AND LP51.PARENT_TYPE_ID = 51 AND LP51.DATE_DEL IS NULL AND LP51.PARENT_ID = :I$SUBJECT_ID
  -- А теперь ищем все остальные нагрузки #56, поскольку L58 связывается только с одной из всех возможных нагрузок
  JOIN LINKS ALL51_56 ON ALL51_56.PARENT_ID = LP51.PARENT_ID AND ALL51_56.OBJ_TYPE_ID = 56 AND ALL51_56.DATE_DEL IS NULL
  JOIN LINKS ALL54_56 ON ALL54_56.PARENT_ID = LP54.PARENT_ID AND ALL54_56.OBJ_ID = ALL51_56.OBJ_ID AND ALL54_56.DATE_DEL IS NULL
  JOIN LINKS ALL49 ON ALL49.PARENT_ID = LP50.PARENT_ID AND ALL49.OBJ_TYPE_ID = 49 AND ALL49.DATE_DEL IS NULL
  JOIN LINKS ALL49_56 ON ALL49_56.PARENT_ID = ALL49.OBJ_ID AND ALL49_56.OBJ_ID = ALL51_56.OBJ_ID AND ALL49_56.DATE_DEL IS NULL
  -- Нагрузка
  JOIN VALI V385 ON V385.OBJ_ID = ALL51_56.OBJ_ID AND V385.PARAM_ID = 385 AND V385.IS_DEL = 0
  WHERE L58.PARENT_ID = :I$GRADE_ID AND L58.OBJ_TYPE_ID = 58 AND L58.DATE_DEL IS NULL
  INTO :PLAN_HOURS;

  SUSPEND;
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ_PTP_PREVIEW (
    I$PTP_ID BIGINT,
    I$GRADE_ID BIGINT,
    I$USER_ID VARCHAR(40) = null)
RETURNS (
    V VARCHAR(6000))
AS
declare variable SS varchar(4000);
declare variable LESSON_ID bigint;
declare variable LESSON_NUM integer;
declare variable LESSON_THEME varchar(1000);
declare variable LESSON_HOMETASK varchar(1000);
declare variable C_S varchar(100);
declare variable N integer;
declare variable V$PTP_PARENT_ID bigint;
declare variable V$TMP bigint;
declare variable REVISION_NUM integer;
begin
  V = '<!DOCTYPE html>';
  V = V || '<html xmlns="http://www.w3.org/1999/xhtml">';
  V = V || '<head>';
  V = V || '<meta charset="UTF-8">';
  V = V || '<title>Поурочно-тематический план</title>';
  V = V || '<style>';
    V = V || 'html { font-family: Tahoma, Verdana, Arial;';
      V = V || 'font-size: 10pt; ';
    V = V || '} ';
    V = V || 'table {';
      V = V || 'width: 100%;';
      V = V || 'margin: 4px;';
    V = V || '} ';
    V = V || 'table tr td {';
      V = V || 'padding: 2px 4px;';
    V = V || '} ';
    V = V || '.title-topic {';
      V = V || 'width: 30%;';
    V = V || '} ';
    V = V || '.title-main td {';
      V = V || 'background: #D4E157;';
    V = V || '} ';
    V = V || '.odd td {';
      V = V || 'background-color: #f7f7f7;';
    V = V || '} ';
  V = V || '</style>';
  V = V || '</head>';

  V = V || '<body>';

  V = V || '<h1>Поурочно-тематический план</h1>';

  IF(I$GRADE_ID IS NULL) THEN
  BEGIN
    SELECT P.PTP_ID, J.GRADE_ID
    FROM CJ2_JOURNAL_PTP P
    JOIN CJ2_JOURNAL J ON J.OBJ_ID = P.CJ_ID
    WHERE P.OBJ_ID = :I$PTP_ID
    INTO :I$PTP_ID, :I$GRADE_ID;
  END

  REVISION_NUM = 0;
  V$PTP_PARENT_ID = I$PTP_ID;
  WHILE(V$PTP_PARENT_ID IS NOT NULL) DO
  BEGIN
    V$TMP = V$PTP_PARENT_ID;
    V$PTP_PARENT_ID = NULL;

    SELECT P.PARENT_ID
    FROM PTP P
    WHERE P.OBJ_ID = :V$TMP
    INTO :V$PTP_PARENT_ID;

    REVISION_NUM = REVISION_NUM + 1;
  END

  V = V || '<table cellspacing=0 cellpadding=0 class="title">';
  SUSPEND;

  V = '<tr><td class="title-topic">Наименование</td><td>' || (SELECT OBJ_NAME FROM PTP WHERE OBJ_ID = :I$PTP_ID) || '</td></tr>';
  V = V || '<tr><td class="title-topic">Ревизия</td><td>' || REVISION_NUM || '</td></tr>';

  SELECT FIRST 1 C.CAPTION
  FROM PTP P
  LEFT JOIN OBJECT_CAPTION_GET(P.SUBJECT_ID) C ON 1 = 1
  WHERE P.OBJ_ID = :I$PTP_ID AND P.DATE_DEL IS NULL
  INTO :SS;
  IF(SS IS NULL) THEN EXCEPTION DATA_ERROR 'ПТП не найден или был удален';
  V = V || '<tr><td class="title-topic">Предмет</td><td>' || COALESCE(SS, '') || '</td></tr>';

  SS = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$GRADE_ID));
  V = V || '<tr><td class="title-topic">Учебный коллектив</td><td>' || COALESCE(SS, '') || '</td></tr>';

  SS = NULL;
  SELECT FIRST 1 C.CAPTION
  FROM CJ2_JOURNAL_PTP P
  JOIN CJ2_JOURNAL J ON J.OBJ_ID = P.CJ_ID AND J.DATE_DEL IS NULL AND J.GRADE_ID = :I$GRADE_ID
  LEFT JOIN OBJECT_CAPTION_GET(J.TEACHER_ID) C ON 1 = 1
  WHERE P.PTP_ID = :I$PTP_ID AND P.DATE_DEL IS NULL
  INTO :SS;
  V = V || '<tr><td class="title-topic">Преподаватель</td><td>' || COALESCE(SS, '') || '</td></tr>';

  SS = (SELECT CAST(SUM(COALESCE(L.DURATION, 1)) AS NUMERIC(18, 1)) FROM PTP_LESSONS L WHERE L.DATE_DEL IS NULL AND L.PTP_ID = :I$PTP_ID);
  V = V || '<tr><td class="title-topic">Учебных часов</td><td>' || COALESCE(SS, '') || '</td></tr>';

  SS = NULL;
  SELECT FIRST 1 P2.OBJ_NAME
  FROM PTP P
  JOIN PTP P2 ON P2.OBJ_ID = P.PARENT_ID
  WHERE P.OBJ_ID = :I$PTP_ID
  INTO :SS;
  IF(SS IS NULL) THEN V = V || '<tr><td class="title-topic" colspan=2>Этот ПТП является корневым</td></tr>';
  ELSE V = V || '<tr><td class="title-topic">Основан на ПТП</td><td>' || SS || '</td></tr>';
  V = V || '</table>';

  V = V || '<table cellspacing=0 cellpadding=0 style="margin-top: 10px; border: 1px solid #f7f7f7;" class="ui compact fixed small striped celled table">';
  V = V || '<thead>';
  V = V || '<tr class="title-main">';
  V = V || '<td style="width: 4%;">№</td>';
  V = V || '<td>Тема урока</td>';
  V = V || '<td>Домашнее задание</td>';
  V = V || '<td>Контроль</td>';
  V = V || '</tr>';
  V = V || '</thead>';
  V = V || '<tbody>';
  SUSPEND;

  N = 0;

  FOR
    SELECT L.OBJ_ID, L.LESSON_NUM, COALESCE(E1.VAL, ''), COALESCE(E2.VAL, '')
    FROM PTP_LESSONS L
    LEFT JOIN ESCAPE_STR(L.THEME_TEXT) E1 ON 1 = 1
    LEFT JOIN ESCAPE_STR(L.HOMETASK_TEXT) E2 ON 1 = 1
    WHERE L.PTP_ID = :I$PTP_ID AND L.DATE_DEL IS NULL
    ORDER BY 2
    INTO :LESSON_ID, :LESSON_NUM, :LESSON_THEME, :LESSON_HOMETASK
  DO
  BEGIN
    V =  '<tr class="row';
      IF(N = 1) THEN V = V || ' odd';
    V = V || '">';
    V = V || '<td>' || LESSON_NUM || '</td>';
    V = V || '<td>' || LESSON_THEME || '</td>';
    V = V || '<td>' || LESSON_HOMETASK || '</td>';

    SS = '';
    FOR
      SELECT R.VAL
      FROM PTP_LESSON_CONTROLS C
      JOIN LISTVALS LV ON LV.LISTVAL_ID = C.CONTROL_TYPE_ID
      JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
      WHERE C.LESSON_ID = :LESSON_ID AND C.DATE_DEL IS NULL
      ORDER BY 1
      INTO :C_S
    DO
    BEGIN
      IF(SS <> '') THEN SS = SS || ', ';
      SS = SS || C_S;
    END

    V = V || '<td>' || SS || '</td>';
    V = V || '</tr>';
    SUSPEND;

    N = N + 1;
    IF(N = 2) THEN N = 0;
  END

  V = '</tbody></table>';
  V = V || '</body>';
  V = V || '</html>';
  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ_PTP_STAGE_LIST (
    I$PTP_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    PTP_ID BIGINT,
    LINK_ID BIGINT,
    STAGE_ID BIGINT,
    STAGE_NAME VARCHAR(4000),
    SORT_ORDER DOUBLE PRECISION)
AS
BEGIN
    PTP_ID = :I$PTP_ID;
    FOR
        SELECT LINK_ID, PARENT_ID
        FROM LINKS L
        WHERE L.OBJ_ID = :I$PTP_ID
          AND L.PARENT_TYPE_ID = 8
          AND L.DATE_DEL IS NULL
        INTO :LINK_ID, :STAGE_ID
    DO
    BEGIN
        SELECT CAPTION, SORT_ORDER
        FROM OBJECT_CAPTION_GET(:STAGE_ID, NULL, NULL, :I$USER_ID)
        INTO :STAGE_NAME, :SORT_ORDER;
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ_PTP_ULESSONS (
    I$PTP_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(4000))
AS
declare variable V$CJ_ID bigint;
declare variable V$LESSON_ID bigint;
declare variable V$DATE date;
declare variable S varchar(4000);
begin

  TAG_NAME = 'ulessons::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT J.OBJ_ID, L.OBJ_ID, L.LESSON_THEME, L.LESSON_DATE
    FROM CJ2_JOURNAL_PTP P
    JOIN CJ2_JOURNAL J ON J.OBJ_ID = P.CJ_ID AND J.DATE_DEL IS NULL
    JOIN CJ2_JOURNAL_LESSONS L ON L.CJ_ID = J.OBJ_ID AND L.DATE_DEL IS NULL AND L.LESSON_PTP_ID = 0
    WHERE P.DATE_DEL IS NULL AND P.PTP_ID = :I$PTP_ID AND P.APPROVAL_STATE = 2
    ORDER BY L.LESSON_DATE, L.LESSON_NUM, J.JOURNAL_NAME
    INTO :V$CJ_ID, :V$LESSON_ID, :S, :V$DATE
  DO
  BEGIN
    TAG_NAME = 'ulessons:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'ulessons:r:cj_id';
    VAL = V$CJ_ID;
    SUSPEND;
    TAG_NAME = 'ulessons:r:id';
    VAL = V$LESSON_ID;
    SUSPEND;
    TAG_NAME = 'ulessons:r:theme';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'ulessons:r:date';
    VAL = (SELECT VAL FROM DATE2ISO(:V$DATE, 0));
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ_PTP_USEREFS_GET (
    I$PTP_ID BIGINT,
    I$APPROVED_ONLY SMALLINT = 0)
RETURNS (
    CLASS_ID BIGINT,
    CLASS_CAPTION VARCHAR(1000),
    CLASS_TYPE_ID BIGINT,
    SUBJECT_ID BIGINT,
    CLASS_TEACHER_ID BIGINT)
AS
begin
  -- Процедура более неактуальна
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ_STAGE_LIST (
    I$USER_ID BIGINT,
    I$LEVEL_ID INTEGER = 0)
RETURNS (
    OBJ_ID BIGINT,
    OBJ_CAPTION VARCHAR(4000),
    SORT_ORDER DOUBLE PRECISION,
    LISTVAL_ID BIGINT)
AS
declare variable SCHOOL_ID bigint;
declare variable ROOT_LV_ID bigint;
declare variable V$LANG_CODE char(2);
BEGIN
    IF (:I$LEVEL_ID > 0 AND (SELECT STATUS FROM OU_LICENCE_TYPE) = 'C') THEN
    BEGIN
        -- Только колледжи в случае с меню (реально не используется)
        SELECT LANG_CODE
        FROM USERS
        WHERE USER_ID = :I$USER_ID
        INTO :V$LANG_CODE;

        IF(I$LEVEL_ID IN (230, 254, 457, 459)) THEN ROOT_LV_ID = 3400;
        ELSE IF(I$LEVEL_ID IN (249, 255, 458, 460)) THEN ROOT_LV_ID = 3405;

        -- Выбираем видов учебной деятельности, являющиеся конечными листьями дерева
        FOR
            SELECT L240.LISTVAL_ID, (SELECT VAL FROM RES_GET(L240.RES_ID, :V$LANG_CODE))
            FROM LISTVALS L240
            WHERE L240.LIST_ID = 240 AND L240.LISTVAL_ID <> 3403 AND L240.IS_DEL = 0
              -- выбираем все элементы из заданных каталогов
              AND L240.PARENT_ID IN (
                SELECT P.LISTVAL_ID
                FROM LISTVALS P
                WHERE P.LIST_ID = 240 AND P.IS_DEL = 0 AND (P.PARENT_ID = :ROOT_LV_ID OR P.LISTVAL_ID = :ROOT_LV_ID)
              )
              -- выбираем только конечные листья
              AND NOT EXISTS (
                SELECT FIRST 1 1
                FROM LISTVALS C
                WHERE C.LIST_ID = 240 AND C.IS_DEL = 0 AND C.PARENT_ID = L240.LISTVAL_ID)
            INTO :OBJ_ID, :OBJ_CAPTION
        DO
        BEGIN
            LISTVAL_ID = OBJ_ID;
            SUSPEND;
        END
    END
    ELSE
    BEGIN
        -- Для всех остальных случаев выбираем реально имеющиеся параллели
        SELECT FIRST 1 L.OBJ_ID
        FROM LINKS L
        WHERE L.PARENT_ID IS NULL AND L.OBJ_TYPE_ID = 2 AND L.DATE_DEL IS NULL
        INTO :SCHOOL_ID;

        FOR
            SELECT DISTINCT L8.OBJ_ID, V49.LISTVAL_ID
            FROM LINKS L7
            JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
            JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
            WHERE L7.PARENT_ID = :SCHOOL_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
            INTO :OBJ_ID, :LISTVAL_ID
        DO
        BEGIN
            SELECT CAPTION, SORT_ORDER
            FROM OBJECT_CAPTION_GET(:OBJ_ID, NULL, NULL, :I$USER_ID)
            INTO :OBJ_CAPTION, :SORT_ORDER;
            SUSPEND;
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ_STAGE_SUBJECTS_LIST (
    I$USER_ID BIGINT,
    I$LEVEL_ID INTEGER = 0,
    I$LISTVAL_ID BIGINT = 3)
RETURNS (
    STAGE_ID BIGINT,
    OBJ_ID BIGINT,
    OBJ_CAPTION VARCHAR(4000),
    SORT_ORDER DOUBLE PRECISION)
AS
declare variable V$SCHOOL_ID bigint;
declare variable V$STAGE_LISTVAL_ID bigint;
BEGIN
    IF ((SELECT STATUS FROM OU_LICENCE_TYPE) = 'C') THEN
    BEGIN
        FOR
            SELECT V1750.LISTVAL_ID, L197.OBJ_ID, (SELECT V FROM VAL_GET(L197.OBJ_ID, 1751, 0, :I$USER_ID)) OBJ_CAPTION
            FROM LINKS L197
            JOIN VALL V1750 ON V1750.OBJ_ID = L197.OBJ_ID AND V1750.PARAM_ID = 1750 AND V1750.IS_DEL = 0
                AND V1750.LISTVAL_ID IN (SELECT OBJ_ID FROM CJ_STAGE_LIST(:I$USER_ID, :I$LEVEL_ID))
            WHERE L197.OBJ_TYPE_ID = 197 AND L197.PARENT_TYPE_ID = 193 AND L197.DATE_DEL IS NULL
                AND L197.OBJ_ID IN (SELECT VAL FROM VALR V1766 WHERE V1766.PARAM_ID = 1766 AND V1766.IS_DEL = 0)
            ORDER BY OBJ_CAPTION
            INTO :STAGE_ID, :OBJ_ID, :OBJ_CAPTION
        DO
        BEGIN
            SUSPEND;
        END
    END
    ELSE
    BEGIN
        SELECT FIRST 1 L.OBJ_ID
        FROM LINKS L
        WHERE L.PARENT_ID IS NULL AND L.DATE_DEL IS NULL AND L.OBJ_TYPE_ID = 2
        INTO :V$SCHOOL_ID;

        IF (V$SCHOOL_ID IS NULL) THEN EXIT;

        FOR
            SELECT DISTINCT L51.OBJ_ID, V381.LISTVAL_ID
            FROM LINKS L69
            JOIN VALL V2450 ON V2450.OBJ_ID = L69.OBJ_ID AND V2450.PARAM_ID = 2450 AND V2450.IS_DEL = 0 AND V2450.LISTVAL_ID = 11385
            JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
            JOIN LINKS L50 ON L50.PARENT_ID = L57.OBJ_ID AND L50.OBJ_TYPE_ID = 50 AND L50.DATE_DEL IS NULL
            JOIN VALL V2545 ON V2545.OBJ_ID = L50.OBJ_ID AND V2545.PARAM_ID = 2545 AND V2545.IS_DEL = 0 AND V2545.LISTVAL_ID = :I$LISTVAL_ID
            JOIN LINKS L54 ON L54.PARENT_ID = L50.OBJ_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
            JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
            JOIN LINKS L49 ON L49.PARENT_ID = L50.OBJ_ID AND L49.OBJ_TYPE_ID = 49 AND L49.DATE_DEL IS NULL
            -- Исключаем Электив (предметы по выбору)
            JOIN LINKS L51 ON L51.PARENT_ID = L49.OBJ_ID AND L51.OBJ_TYPE_ID = 51 AND L51.DATE_DEL IS NULL AND L51.OBJ_ID <> 34607
            WHERE L69.PARENT_ID = :V$SCHOOL_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL
            INTO :OBJ_ID, :V$STAGE_LISTVAL_ID
        DO
        BEGIN
            FOR
                SELECT FIRST 1 L8.OBJ_ID
                FROM LINKS L7
                JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
                JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0 AND V49.LISTVAL_ID = :V$STAGE_LISTVAL_ID
                WHERE L7.PARENT_ID = :V$SCHOOL_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
                INTO :STAGE_ID
            DO
            BEGIN
                SELECT CAPTION, SORT_ORDER
                FROM OBJECT_CAPTION_GET(:OBJ_ID, NULL, NULL, :I$USER_ID)
                INTO :OBJ_CAPTION, :SORT_ORDER;
                SUSPEND;
            END
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CJ_TEACHER_LIST (
    I$GRADE_ID BIGINT = null)
RETURNS (
    OBJ_ID BIGINT,
    OBJ_CAPTION VARCHAR(4000))
AS
BEGIN
    IF (I$GRADE_ID IS NULL) THEN
    BEGIN
        SELECT FIRST 1 L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 2 AND L.PARENT_ID IS NULL AND L.DATE_DEL IS NULL
        INTO :I$GRADE_ID;
    END 

    FOR
        SELECT TEACHER_ID, TEACHER_CAPTION
        FROM PARAGRAF_GRADE_TEACHERS_LIST(:I$GRADE_ID)
        INTO :OBJ_ID, :OBJ_CAPTION
    DO
    BEGIN
        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CLASSES_COUNT_DISTRICT_GET (
    I$DT DATE,
    I$USER_ID BIGINT)
RETURNS (
    STR VARCHAR(200),
    CLASSES1 INTEGER,
    PUPILS1 INTEGER,
    CLASSES2 INTEGER,
    PUPILS2 INTEGER,
    CLASSES3 INTEGER,
    PUPILS3 INTEGER,
    CLASSES4 INTEGER,
    PUPILS4 INTEGER,
    CLASSESYASALL INTEGER,
    PUPILSYASALL INTEGER,
    CLASSES5 INTEGER,
    PUPILS5 INTEGER,
    CLASSES6 INTEGER,
    PUPILS6 INTEGER,
    CLASSES7 INTEGER,
    PUPILS7 INTEGER,
    CLASSES8 INTEGER,
    PUPILS8 INTEGER,
    CLASSES9 INTEGER,
    PUPILS9 INTEGER,
    CLASSESDSALL INTEGER,
    PUPILSDSALL INTEGER,
    CLASSESALL INTEGER,
    PUPILSALL INTEGER,
    ORDER_SCHOOL INTEGER,
    ORDER_KIND INTEGER)
AS
declare variable V$SORT_ORDER integer;
declare variable V$CLASS_ID bigint;
declare variable V$CLASS_KIND integer;
declare variable V$SCHOOLAR_ID bigint;
declare variable V$DT_IN date;
declare variable V$DT_OUT date;
declare variable V$OU_ID bigint;
declare variable V$STAGE_KIND integer;
declare variable V$OU_SHORTNAME varchar(200);
declare variable V$CLASSES1 integer;
declare variable V$PUPILS1 integer;
declare variable V$CLASSES2 integer;
declare variable V$PUPILS2 integer;
declare variable V$CLASSES3 integer;
declare variable V$PUPILS3 integer;
declare variable V$CLASSES4 integer;
declare variable V$PUPILS4 integer;
declare variable V$CLASSESYASALL integer;
declare variable V$PUPILSYASALL integer;
declare variable V$CLASSES5 integer;
declare variable V$PUPILS5 integer;
declare variable V$CLASSES6 integer;
declare variable V$PUPILS6 integer;
declare variable V$CLASSES7 integer;
declare variable V$PUPILS7 integer;
declare variable V$CLASSES8 integer;
declare variable V$PUPILS8 integer;
declare variable V$CLASSES9 integer;
declare variable V$PUPILS9 integer;
declare variable V$CLASSESDSALL integer;
declare variable V$PUPILSDSALL integer;
declare variable V$CLASSESALL integer;
declare variable V$PUPILSALL integer;
declare variable V$CLASSES1_ITOGALL integer;
declare variable V$PUPILS1_ITOGALL integer;
declare variable V$CLASSES2_ITOGALL integer;
declare variable V$PUPILS2_ITOGALL integer;
declare variable V$CLASSES3_ITOGALL integer;
declare variable V$PUPILS3_ITOGALL integer;
declare variable V$CLASSES4_ITOGALL integer;
declare variable V$PUPILS4_ITOGALL integer;
declare variable V$CLASSESYASALL_ITOGALL integer;
declare variable V$PUPILSYASALL_ITOGALL integer;
declare variable V$CLASSES5_ITOGALL integer;
declare variable V$PUPILS5_ITOGALL integer;
declare variable V$CLASSES6_ITOGALL integer;
declare variable V$PUPILS6_ITOGALL integer;
declare variable V$CLASSES7_ITOGALL integer;
declare variable V$PUPILS7_ITOGALL integer;
declare variable V$CLASSES8_ITOGALL integer;
declare variable V$PUPILS8_ITOGALL integer;
declare variable V$CLASSES9_ITOGALL integer;
declare variable V$PUPILS9_ITOGALL integer;
declare variable V$CLASSESDSALL_ITOGALL integer;
declare variable V$PUPILSDSALL_ITOGALL integer;
declare variable V$CLASSESALL_ITOGALL integer;
declare variable V$PUPILSALL_ITOGALL integer;
declare variable V$CLASSES1_ITOG1 integer;
declare variable V$PUPILS1_ITOG1 integer;
declare variable V$CLASSES2_ITOG1 integer;
declare variable V$PUPILS2_ITOG1 integer;
declare variable V$CLASSES3_ITOG1 integer;
declare variable V$PUPILS3_ITOG1 integer;
declare variable V$CLASSES4_ITOG1 integer;
declare variable V$PUPILS4_ITOG1 integer;
declare variable V$CLASSESYASALL_ITOG1 integer;
declare variable V$PUPILSYASALL_ITOG1 integer;
declare variable V$CLASSES5_ITOG1 integer;
declare variable V$PUPILS5_ITOG1 integer;
declare variable V$CLASSES6_ITOG1 integer;
declare variable V$PUPILS6_ITOG1 integer;
declare variable V$CLASSES7_ITOG1 integer;
declare variable V$PUPILS7_ITOG1 integer;
declare variable V$CLASSES8_ITOG1 integer;
declare variable V$PUPILS8_ITOG1 integer;
declare variable V$CLASSES9_ITOG1 integer;
declare variable V$PUPILS9_ITOG1 integer;
declare variable V$CLASSESDSALL_ITOG1 integer;
declare variable V$PUPILSDSALL_ITOG1 integer;
declare variable V$CLASSESALL_ITOG1 integer;
declare variable V$PUPILSALL_ITOG1 integer;
declare variable V$CLASSES1_ITOG2 integer;
declare variable V$PUPILS1_ITOG2 integer;
declare variable V$CLASSES2_ITOG2 integer;
declare variable V$PUPILS2_ITOG2 integer;
declare variable V$CLASSES3_ITOG2 integer;
declare variable V$PUPILS3_ITOG2 integer;
declare variable V$CLASSES4_ITOG2 integer;
declare variable V$PUPILS4_ITOG2 integer;
declare variable V$CLASSESYASALL_ITOG2 integer;
declare variable V$PUPILSYASALL_ITOG2 integer;
declare variable V$CLASSES5_ITOG2 integer;
declare variable V$PUPILS5_ITOG2 integer;
declare variable V$CLASSES6_ITOG2 integer;
declare variable V$PUPILS6_ITOG2 integer;
declare variable V$CLASSES7_ITOG2 integer;
declare variable V$PUPILS7_ITOG2 integer;
declare variable V$CLASSES8_ITOG2 integer;
declare variable V$PUPILS8_ITOG2 integer;
declare variable V$CLASSES9_ITOG2 integer;
declare variable V$PUPILS9_ITOG2 integer;
declare variable V$CLASSESDSALL_ITOG2 integer;
declare variable V$PUPILSDSALL_ITOG2 integer;
declare variable V$CLASSESALL_ITOG2 integer;
declare variable V$PUPILSALL_ITOG2 integer;
declare variable V$CLASSES1_ITOG3 integer;
declare variable V$PUPILS1_ITOG3 integer;
declare variable V$CLASSES2_ITOG3 integer;
declare variable V$PUPILS2_ITOG3 integer;
declare variable V$CLASSES3_ITOG3 integer;
declare variable V$PUPILS3_ITOG3 integer;
declare variable V$CLASSES4_ITOG3 integer;
declare variable V$PUPILS4_ITOG3 integer;
declare variable V$CLASSESYASALL_ITOG3 integer;
declare variable V$PUPILSYASALL_ITOG3 integer;
declare variable V$CLASSES5_ITOG3 integer;
declare variable V$PUPILS5_ITOG3 integer;
declare variable V$CLASSES6_ITOG3 integer;
declare variable V$PUPILS6_ITOG3 integer;
declare variable V$CLASSES7_ITOG3 integer;
declare variable V$PUPILS7_ITOG3 integer;
declare variable V$CLASSES8_ITOG3 integer;
declare variable V$PUPILS8_ITOG3 integer;
declare variable V$CLASSES9_ITOG3 integer;
declare variable V$PUPILS9_ITOG3 integer;
declare variable V$CLASSESDSALL_ITOG3 integer;
declare variable V$PUPILSDSALL_ITOG3 integer;
declare variable V$CLASSESALL_ITOG3 integer;
declare variable V$PUPILSALL_ITOG3 integer;
declare variable V$CLASSES1_ITOG4 integer;
declare variable V$PUPILS1_ITOG4 integer;
declare variable V$CLASSES2_ITOG4 integer;
declare variable V$PUPILS2_ITOG4 integer;
declare variable V$CLASSES3_ITOG4 integer;
declare variable V$PUPILS3_ITOG4 integer;
declare variable V$CLASSES4_ITOG4 integer;
declare variable V$PUPILS4_ITOG4 integer;
declare variable V$CLASSESYASALL_ITOG4 integer;
declare variable V$PUPILSYASALL_ITOG4 integer;
declare variable V$CLASSES5_ITOG4 integer;
declare variable V$PUPILS5_ITOG4 integer;
declare variable V$CLASSES6_ITOG4 integer;
declare variable V$PUPILS6_ITOG4 integer;
declare variable V$CLASSES7_ITOG4 integer;
declare variable V$PUPILS7_ITOG4 integer;
declare variable V$CLASSES8_ITOG4 integer;
declare variable V$PUPILS8_ITOG4 integer;
declare variable V$CLASSES9_ITOG4 integer;
declare variable V$PUPILS9_ITOG4 integer;
declare variable V$CLASSESDSALL_ITOG4 integer;
declare variable V$PUPILSDSALL_ITOG4 integer;
declare variable V$CLASSESALL_ITOG4 integer;
declare variable V$PUPILSALL_ITOG4 integer;
declare variable V$OUID_FROM bigint;
declare variable V$OUID_TO bigint;
declare variable V$PREV_CLASS_ID bigint;
BEGIN
    V$CLASSES1_ITOGALL = 0;
    V$PUPILS1_ITOGALL = 0;
    V$CLASSES2_ITOGALL = 0;
    V$PUPILS2_ITOGALL = 0;
    V$CLASSES3_ITOGALL = 0;
    V$PUPILS3_ITOGALL = 0;
    V$CLASSES4_ITOGALL = 0;
    V$PUPILS4_ITOGALL = 0;
    V$CLASSESYASALL_ITOGALL = 0;
    V$PUPILSYASALL_ITOGALL = 0;
    V$CLASSES5_ITOGALL = 0;
    V$PUPILS5_ITOGALL = 0;
    V$CLASSES6_ITOGALL = 0;
    V$PUPILS6_ITOGALL = 0;
    V$CLASSES7_ITOGALL = 0;
    V$PUPILS7_ITOGALL = 0;
    V$CLASSES8_ITOGALL = 0;
    V$PUPILS8_ITOGALL = 0;
    V$CLASSES9_ITOGALL = 0;
    V$PUPILS9_ITOGALL = 0;
    V$CLASSESDSALL_ITOGALL = 0;
    V$PUPILSDSALL_ITOGALL = 0;
    V$CLASSESALL_ITOGALL = 0;
    V$PUPILSALL_ITOGALL = 0;

    V$CLASSES1_ITOG1 = 0;
    V$PUPILS1_ITOG1 = 0;
    V$CLASSES2_ITOG1 = 0;
    V$PUPILS2_ITOG1 = 0;
    V$CLASSES3_ITOG1 = 0;
    V$PUPILS3_ITOG1 = 0;
    V$CLASSES4_ITOG1 = 0;
    V$PUPILS4_ITOG1 = 0;
    V$CLASSESYASALL_ITOG1 = 0;
    V$PUPILSYASALL_ITOG1 = 0;
    V$CLASSES5_ITOG1 = 0;
    V$PUPILS5_ITOG1 = 0;
    V$CLASSES6_ITOG1 = 0;
    V$PUPILS6_ITOG1 = 0;
    V$CLASSES7_ITOG1 = 0;
    V$PUPILS7_ITOG1 = 0;
    V$CLASSES8_ITOG1 = 0;
    V$PUPILS8_ITOG1 = 0;
    V$CLASSES9_ITOG1 = 0;
    V$PUPILS9_ITOG1 = 0;
    V$CLASSESDSALL_ITOG1 = 0;
    V$PUPILSDSALL_ITOG1 = 0;
    V$CLASSESALL_ITOG1 = 0;
    V$PUPILSALL_ITOG1 = 0;

    V$CLASSES1_ITOG2 = 0;
    V$PUPILS1_ITOG2 = 0;
    V$CLASSES2_ITOG2 = 0;
    V$PUPILS2_ITOG2 = 0;
    V$CLASSES3_ITOG2 = 0;
    V$PUPILS3_ITOG2 = 0;
    V$CLASSES4_ITOG2 = 0;
    V$PUPILS4_ITOG2 = 0;
    V$CLASSESYASALL_ITOG2 = 0;
    V$PUPILSYASALL_ITOG2 = 0;
    V$CLASSES5_ITOG2 = 0;
    V$PUPILS5_ITOG2 = 0;
    V$CLASSES6_ITOG2 = 0;
    V$PUPILS6_ITOG2 = 0;
    V$CLASSES7_ITOG2 = 0;
    V$PUPILS7_ITOG2 = 0;
    V$CLASSES8_ITOG2 = 0;
    V$PUPILS8_ITOG2 = 0;
    V$CLASSES9_ITOG2 = 0;
    V$PUPILS9_ITOG2 = 0;
    V$CLASSESDSALL_ITOG2 = 0;
    V$PUPILSDSALL_ITOG2 = 0;
    V$CLASSESALL_ITOG2 = 0;
    V$PUPILSALL_ITOG2 = 0;

    V$CLASSES1_ITOG3 = 0;
    V$PUPILS1_ITOG3 = 0;
    V$CLASSES2_ITOG3 = 0;
    V$PUPILS2_ITOG3 = 0;
    V$CLASSES3_ITOG3 = 0;
    V$PUPILS3_ITOG3 = 0;
    V$CLASSES4_ITOG3 = 0;
    V$PUPILS4_ITOG3 = 0;
    V$CLASSESYASALL_ITOG3 = 0;
    V$PUPILSYASALL_ITOG3 = 0;
    V$CLASSES5_ITOG3 = 0;
    V$PUPILS5_ITOG3 = 0;
    V$CLASSES6_ITOG3 = 0;
    V$PUPILS6_ITOG3 = 0;
    V$CLASSES7_ITOG3 = 0;
    V$PUPILS7_ITOG3 = 0;
    V$CLASSES8_ITOG3 = 0;
    V$PUPILS8_ITOG3 = 0;
    V$CLASSES9_ITOG3 = 0;
    V$PUPILS9_ITOG3 = 0;
    V$CLASSESDSALL_ITOG3 = 0;
    V$PUPILSDSALL_ITOG3 = 0;
    V$CLASSESALL_ITOG3 = 0;
    V$PUPILSALL_ITOG3 = 0;

    V$CLASSES1_ITOG4 = 0;
    V$PUPILS1_ITOG4 = 0;
    V$CLASSES2_ITOG4 = 0;
    V$PUPILS2_ITOG4 = 0;
    V$CLASSES3_ITOG4 = 0;
    V$PUPILS3_ITOG4 = 0;
    V$CLASSES4_ITOG4 = 0;
    V$PUPILS4_ITOG4 = 0;
    V$CLASSESYASALL_ITOG4 = 0;
    V$PUPILSYASALL_ITOG4 = 0;
    V$CLASSES5_ITOG4 = 0;
    V$PUPILS5_ITOG4 = 0;
    V$CLASSES6_ITOG4 = 0;
    V$PUPILS6_ITOG4 = 0;
    V$CLASSES7_ITOG4 = 0;
    V$PUPILS7_ITOG4 = 0;
    V$CLASSES8_ITOG4 = 0;
    V$PUPILS8_ITOG4 = 0;
    V$CLASSES9_ITOG4 = 0;
    V$PUPILS9_ITOG4 = 0;
    V$CLASSESDSALL_ITOG4 = 0;
    V$PUPILSDSALL_ITOG4 = 0;
    V$CLASSESALL_ITOG4 = 0;
    V$PUPILSALL_ITOG4 = 0;


    ORDER_SCHOOL = 1;

    FOR
        -- проход по школам
        SELECT L2.OBJ_ID, CAST(V2.VAL AS VARCHAR(200))
        FROM LINKS L111
        JOIN LINKS L2 ON L2.PARENT_ID = L111.OBJ_ID AND L2.DATE_DEL IS NULL AND L2.OBJ_TYPE_ID = 2
        JOIN VALS V2 ON V2.OBJ_ID = L2.OBJ_ID AND V2.IS_DEL = 0 AND V2.PARAM_ID = 2
        LEFT JOIN OBJECT_CAPTION_GET(L2.OBJ_ID, NULL, NULL,  :I$USER_ID) C ON 1=1
        WHERE L111.PARENT_ID IS NULL AND L111.DATE_DEL IS NULL AND L111.OBJ_TYPE_ID = 111
        ORDER BY C.SORT_ORDER
        INTO :V$OU_ID, :V$OU_SHORTNAME
    DO
    BEGIN
        V$CLASSES1 = 0;
        V$PUPILS1 = 0;
        V$CLASSES2 = 0;
        V$PUPILS2 = 0;
        V$CLASSES3 = 0;
        V$PUPILS3 = 0;
        V$CLASSES4 = 0;
        V$PUPILS4 = 0;
        V$CLASSES5 = 0;
        V$PUPILS5 = 0;
        V$CLASSES6 = 0;
        V$PUPILS6 = 0;
        V$CLASSES7 = 0;
        V$PUPILS7 = 0;
        V$CLASSES8 = 0;
        V$PUPILS8 = 0;
        V$CLASSES9 = 0;
        V$PUPILS9 = 0;
        V$CLASSESYASALL = 0;
        V$PUPILSYASALL = 0;
        V$CLASSESDSALL = 0;
        V$PUPILSDSALL = 0;
        V$CLASSESALL = 0;
        V$PUPILSALL = 0;

        V$OUID_FROM = V$OU_ID / 1000000000;
        V$OUID_FROM = V$OUID_FROM * 1000000000;
        V$OUID_TO = V$OUID_FROM + 1000000000 - 1;

        FOR
            SELECT LV.LISTVAL_ID,LV.SORT_ORDER
            FROM LISTVALS LV
            WHERE  LV.LISTVAL_ID IN (3265, 3266, 3267, 3268)

            UNION ALL

            SELECT NULL,0 FROM RDB$DATABASE

            ORDER BY 2
            INTO :V$CLASS_KIND, :V$SORT_ORDER
        DO
        BEGIN
            IF (V$CLASS_KIND = 3265) THEN
            BEGIN
                STR = 'общераз';
                ORDER_KIND = 1;
            END
            ELSE IF (V$CLASS_KIND = 3266) THEN
            BEGIN
                STR = 'компен';
                ORDER_KIND = 2;
            END
            ELSE IF (V$CLASS_KIND = 3267) THEN
            BEGIN
                STR = 'оздор';
                ORDER_KIND = 3;
            END
            ELSE IF (V$CLASS_KIND = 3268) THEN
            BEGIN
                STR = 'комбинир';
                ORDER_KIND = 4;
            END
            ELSE
            BEGIN
                STR = NULL;
                ORDER_KIND = NULL;
            END

            CLASSES1 = 0;
            PUPILS1 = 0;
            CLASSES2 = 0;
            PUPILS2 = 0;
            CLASSES3 = 0;
            PUPILS3 = 0;
            CLASSES4 = 0;
            PUPILS4 = 0;
            CLASSES5 = 0;
            PUPILS5 = 0;
            CLASSES6 = 0;
            PUPILS6 = 0;
            CLASSES7 = 0;
            PUPILS7 = 0;
            CLASSES8 = 0;
            PUPILS8 = 0;
            CLASSES9 = 0;
            PUPILS9 = 0;
            CLASSESYASALL = 0;
            PUPILSYASALL = 0;
            CLASSESDSALL = 0;
            PUPILSDSALL = 0;
            CLASSESALL = 0;
            PUPILSALL = 0;

            V$PREV_CLASS_ID = 0;

            FOR
                SELECT DISTINCT
                       V438.VAL,
                       L76.PARENT_ID,
                       MAX(V433.VAL),
                       V49.LISTVAL_ID
                FROM LINKS L76
    
                JOIN VALR V438
                ON V438.OBJ_ID = L76.OBJ_ID
                AND V438.PARAM_ID = 438
                AND V438.IS_DEL = 0
    
                JOIN OBJECTS O9
                ON O9.OBJ_ID = V438.VAL
                AND O9.TYPE_ID = 9

                LEFT JOIN VALL V1549
                ON V1549.OBJ_ID = O9.OBJ_ID
                AND V1549.PARAM_ID = 1549
                AND V1549.IS_DEL = 0

                JOIN LINKS LP8
                ON LP8.OBJ_ID = O9.OBJ_ID
                AND LP8.PARENT_TYPE_ID = 8
                AND LP8.DATE_DEL IS NULL
                
                JOIN VALL V49
                ON V49.OBJ_ID = LP8.PARENT_ID
                AND V49.PARAM_ID = 49
                AND V49.IS_DEL = 0

                JOIN VALL V432
                ON V432.OBJ_ID = L76.OBJ_ID
                AND V432.PARAM_ID = 432
                AND V432.IS_DEL = 0
                AND V432.LISTVAL_ID IN (3276,3277,3278,806)
    
                JOIN VALD V433
                ON V433.OBJ_ID = L76.OBJ_ID
                AND V433.PARAM_ID = 433
                AND V433.IS_DEL = 0
    
                AND V433.VAL <= :I$DT

                WHERE L76.OBJ_TYPE_ID = 76
                AND L76.DATE_DEL IS NULL
                AND L76.LINK_ID >= :V$OUID_FROM
                AND L76.LINK_ID <= :V$OUID_TO
                AND (((:V$CLASS_KIND IS NOT NULL) AND (V1549.LISTVAL_ID = :V$CLASS_KIND)) OR
                     ((:V$CLASS_KIND IS NULL) AND ((V1549.LISTVAL_ID IS NULL) OR (V1549.LISTVAL_ID NOT IN (3265, 3266, 3267, 3268)))))
    
                GROUP BY V438.VAL, L76.PARENT_ID, V49.LISTVAL_ID
                ORDER BY V438.VAL

                INTO :V$CLASS_ID,
                     :V$SCHOOLAR_ID,
                     :V$DT_IN,
                     :V$STAGE_KIND
            DO
            BEGIN
                SELECT MIN(V433.VAL)
    
                FROM LINKS L76
    
                JOIN VALR V438
                ON V438.OBJ_ID = L76.OBJ_ID
                AND V438.PARAM_ID = 438
                AND V438.IS_DEL = 0
                AND V438.VAL <> :V$CLASS_ID
    
                JOIN VALL V432
                ON V432.OBJ_ID = L76.OBJ_ID
                AND V432.PARAM_ID = 432
                AND V432.IS_DEL = 0
    
                JOIN VALD V433
                ON V433.OBJ_ID = L76.OBJ_ID
                AND V433.PARAM_ID = 433
                AND V433.IS_DEL = 0
                AND V433.VAL >= :V$DT_IN
    
                WHERE L76.PARENT_ID = :V$SCHOOLAR_ID
                AND L76.OBJ_TYPE_ID = 76
                AND L76.DATE_DEL IS NULL
    
                INTO :V$DT_OUT;
    
                IF ((V$DT_OUT > I$DT) OR (V$DT_OUT IS NULL)) THEN
                BEGIN
                    IF (V$STAGE_KIND = 30) THEN
                    BEGIN
                        PUPILS1 = PUPILS1 + 1;
                        IF (V$PREV_CLASS_ID <> V$CLASS_ID) THEN
                        BEGIN
                            CLASSES1 = CLASSES1 + 1;
                        END
                    END
                    ELSE IF (V$STAGE_KIND = 31) THEN
                    BEGIN
                        PUPILS2 = PUPILS2 + 1;
                        IF (V$PREV_CLASS_ID <> V$CLASS_ID) THEN
                        BEGIN
                            CLASSES2 = CLASSES2 + 1;
                        END
                    END
                    ELSE IF (V$STAGE_KIND = 32) THEN
                    BEGIN
                        PUPILS3 = PUPILS3 + 1;
                        IF (V$PREV_CLASS_ID <> V$CLASS_ID) THEN
                        BEGIN
                            CLASSES3 = CLASSES3 + 1;
                        END
                    END
                    ELSE IF (V$STAGE_KIND = 33) THEN
                    BEGIN
                        PUPILS4 = PUPILS4 + 1;
                        IF (V$PREV_CLASS_ID <> V$CLASS_ID) THEN
                        BEGIN
                            CLASSES4 = CLASSES4 + 1;
                        END
                    END
                    ELSE IF (V$STAGE_KIND = 3261) THEN
                    BEGIN
                        PUPILS5 = PUPILS5 + 1;
                        IF (V$PREV_CLASS_ID <> V$CLASS_ID) THEN
                        BEGIN
                            CLASSES5 = CLASSES5 + 1;
                        END
                    END
                    ELSE IF (V$STAGE_KIND = 34) THEN
                    BEGIN
                        PUPILS6 = PUPILS6 + 1;
                        IF (V$PREV_CLASS_ID <> V$CLASS_ID) THEN
                        BEGIN
                            CLASSES6 = CLASSES6 + 1;
                        END
                    END
                    ELSE IF (V$STAGE_KIND = 35) THEN
                    BEGIN
                        PUPILS7 = PUPILS7 + 1;
                        IF (V$PREV_CLASS_ID <> V$CLASS_ID) THEN
                        BEGIN
                            CLASSES7 = CLASSES7 + 1;
                        END
                    END
                    ELSE IF (V$STAGE_KIND = 36) THEN
                    BEGIN
                        PUPILS8 = PUPILS8 + 1;
                        IF (V$PREV_CLASS_ID <> V$CLASS_ID) THEN
                        BEGIN
                            CLASSES8 = CLASSES8 + 1;
                        END
                    END
                    ELSE IF (V$STAGE_KIND = 3262) THEN
                    BEGIN
                        PUPILS9 = PUPILS9 + 1;
                        IF (V$PREV_CLASS_ID <> V$CLASS_ID) THEN
                        BEGIN
                            CLASSES9 = CLASSES9 + 1;
                        END
                    END
                    V$PREV_CLASS_ID = V$CLASS_ID;
                END
            END

            CLASSESYASALL = CLASSESYASALL + CLASSES1 + CLASSES2 + CLASSES3 + CLASSES4;
            PUPILSYASALL =  PUPILSYASALL + PUPILS1 + PUPILS2 + PUPILS3 + PUPILS4;
            
            CLASSESDSALL = CLASSESDSALL + CLASSES5 + CLASSES6 + CLASSES7 + CLASSES8 + CLASSES9;
            PUPILSDSALL = PUPILSDSALL + PUPILS5 + PUPILS6 + PUPILS7 + PUPILS8 + PUPILS9;
            
            CLASSESALL = CLASSESYASALL + CLASSESDSALL;
            PUPILSALL = PUPILSYASALL + PUPILSDSALL;

            IF (STR IS NOT NULL) THEN
            BEGIN
                SUSPEND;
            END

            V$CLASSES1 = V$CLASSES1 + CLASSES1;
            V$PUPILS1 = V$PUPILS1 + PUPILS1;
            V$CLASSES2 = V$CLASSES2 + CLASSES2;
            V$PUPILS2 = V$PUPILS2 + PUPILS2;
            V$CLASSES3 = V$CLASSES3 + CLASSES3;
            V$PUPILS3 = V$PUPILS3 + PUPILS3;
            V$CLASSES4 = V$CLASSES4 + CLASSES4;
            V$PUPILS4 = V$PUPILS4 + PUPILS4;
            V$CLASSES5 = V$CLASSES5 + CLASSES5;
            V$PUPILS5 = V$PUPILS5 + PUPILS5;
            V$CLASSES6 = V$CLASSES6 + CLASSES6;
            V$PUPILS6 = V$PUPILS6 + PUPILS6;
            V$CLASSES7 = V$CLASSES7 + CLASSES7;
            V$PUPILS7 = V$PUPILS7 + PUPILS7;
            V$CLASSES8 = V$CLASSES8 + CLASSES8;
            V$PUPILS8 = V$PUPILS8 + PUPILS8;
            V$CLASSES9 = V$CLASSES9 + CLASSES9;
            V$PUPILS9 = V$PUPILS9 + PUPILS9;
            V$CLASSESYASALL = V$CLASSESYASALL + CLASSESYASALL;
            V$PUPILSYASALL = V$PUPILSYASALL + PUPILSYASALL;
            V$CLASSESDSALL = V$CLASSESDSALL + CLASSESDSALL;
            V$PUPILSDSALL = V$PUPILSDSALL + PUPILSDSALL;
            V$CLASSESALL = V$CLASSESALL + CLASSESALL;
            V$PUPILSALL = V$PUPILSALL + PUPILSALL;

            IF (V$CLASS_KIND = 3265) THEN
            BEGIN
                V$CLASSES1_ITOG1 = V$CLASSES1_ITOG1 + CLASSES1;
                V$PUPILS1_ITOG1 = V$PUPILS1_ITOG1 + PUPILS1;
                V$CLASSES2_ITOG1 = V$CLASSES2_ITOG1 + CLASSES2;
                V$PUPILS2_ITOG1 = V$PUPILS2_ITOG1 + PUPILS2;
                V$CLASSES3_ITOG1 = V$CLASSES3_ITOG1 + CLASSES3;
                V$PUPILS3_ITOG1 = V$PUPILS3_ITOG1 + PUPILS3;
                V$CLASSES4_ITOG1 = V$CLASSES4_ITOG1 + CLASSES4;
                V$PUPILS4_ITOG1 = V$PUPILS4_ITOG1 + PUPILS4;
                V$CLASSESYASALL_ITOG1 = V$CLASSESYASALL_ITOG1 + CLASSESYASALL;
                V$PUPILSYASALL_ITOG1 = V$PUPILSYASALL_ITOG1 + PUPILSYASALL;
                V$CLASSES5_ITOG1 = V$CLASSES5_ITOG1 + CLASSES5;
                V$PUPILS5_ITOG1 = V$PUPILS5_ITOG1 + PUPILS5;
                V$CLASSES6_ITOG1 = V$CLASSES6_ITOG1 + CLASSES6;
                V$PUPILS6_ITOG1 = V$PUPILS6_ITOG1 + PUPILS6;
                V$CLASSES7_ITOG1 = V$CLASSES7_ITOG1 + CLASSES7;
                V$PUPILS7_ITOG1 = V$PUPILS7_ITOG1 + PUPILS7;
                V$CLASSES8_ITOG1 = V$CLASSES8_ITOG1 + CLASSES8;
                V$PUPILS8_ITOG1 = V$PUPILS8_ITOG1 + PUPILS8;
                V$CLASSES9_ITOG1 = V$CLASSES9_ITOG1 + CLASSES9;
                V$PUPILS9_ITOG1 = V$PUPILS9_ITOG1 + PUPILS9;
                V$CLASSESDSALL_ITOG1 = V$CLASSESDSALL_ITOG1 + CLASSESDSALL;
                V$PUPILSDSALL_ITOG1 = V$PUPILSDSALL_ITOG1 + PUPILSDSALL;
                V$CLASSESALL_ITOG1 = V$CLASSESALL_ITOG1 + CLASSESALL;
                V$PUPILSALL_ITOG1 = V$PUPILSALL_ITOG1 + PUPILSALL;
            END
            ELSE IF (V$CLASS_KIND = 3266) THEN
            BEGIN
                V$CLASSES1_ITOG2 = V$CLASSES1_ITOG2 + CLASSES1;
                V$PUPILS1_ITOG2 = V$PUPILS1_ITOG2 + PUPILS1;
                V$CLASSES2_ITOG2 = V$CLASSES2_ITOG2 + CLASSES2;
                V$PUPILS2_ITOG2 = V$PUPILS2_ITOG2 + PUPILS2;
                V$CLASSES3_ITOG2 = V$CLASSES3_ITOG2 + CLASSES3;
                V$PUPILS3_ITOG2 = V$PUPILS3_ITOG2 + PUPILS3;
                V$CLASSES4_ITOG2 = V$CLASSES4_ITOG2 + CLASSES4;
                V$PUPILS4_ITOG2 = V$PUPILS4_ITOG2 + PUPILS4;
                V$CLASSESYASALL_ITOG2 = V$CLASSESYASALL_ITOG2 + CLASSESYASALL;
                V$PUPILSYASALL_ITOG2 = V$PUPILSYASALL_ITOG2 + PUPILSYASALL;
                V$CLASSES5_ITOG2 = V$CLASSES5_ITOG2 + CLASSES5;
                V$PUPILS5_ITOG2 = V$PUPILS5_ITOG2 + PUPILS5;
                V$CLASSES6_ITOG2 = V$CLASSES6_ITOG2 + CLASSES6;
                V$PUPILS6_ITOG2 = V$PUPILS6_ITOG2 + PUPILS6;
                V$CLASSES7_ITOG2 = V$CLASSES7_ITOG2 + CLASSES7;
                V$PUPILS7_ITOG2 = V$PUPILS7_ITOG2 + PUPILS7;
                V$CLASSES8_ITOG2 = V$CLASSES8_ITOG2 + CLASSES8;
                V$PUPILS8_ITOG2 = V$PUPILS8_ITOG2 + PUPILS8;
                V$CLASSES9_ITOG2 = V$CLASSES9_ITOG2 + CLASSES9;
                V$PUPILS9_ITOG2 = V$PUPILS9_ITOG2 + PUPILS9;
                V$CLASSESDSALL_ITOG2 = V$CLASSESDSALL_ITOG2 + CLASSESDSALL;
                V$PUPILSDSALL_ITOG2 = V$PUPILSDSALL_ITOG2 + PUPILSDSALL;
                V$CLASSESALL_ITOG2 = V$CLASSESALL_ITOG2 + CLASSESALL;
                V$PUPILSALL_ITOG2 = V$PUPILSALL_ITOG2 + PUPILSALL;
            END
            ELSE IF (V$CLASS_KIND = 3267) THEN
            BEGIN
                V$CLASSES1_ITOG3 = V$CLASSES1_ITOG3 + CLASSES1;
                V$PUPILS1_ITOG3 = V$PUPILS1_ITOG3 + PUPILS1;
                V$CLASSES2_ITOG3 = V$CLASSES2_ITOG3 + CLASSES2;
                V$PUPILS2_ITOG3 = V$PUPILS2_ITOG3 + PUPILS2;
                V$CLASSES3_ITOG3 = V$CLASSES3_ITOG3 + CLASSES3;
                V$PUPILS3_ITOG3 = V$PUPILS3_ITOG3 + PUPILS3;
                V$CLASSES4_ITOG3 = V$CLASSES4_ITOG3 + CLASSES4;
                V$PUPILS4_ITOG3 = V$PUPILS4_ITOG3 + PUPILS4;
                V$CLASSESYASALL_ITOG3 = V$CLASSESYASALL_ITOG3 + CLASSESYASALL;
                V$PUPILSYASALL_ITOG3 = V$PUPILSYASALL_ITOG3 + PUPILSYASALL;
                V$CLASSES5_ITOG3 = V$CLASSES5_ITOG3 + CLASSES5;
                V$PUPILS5_ITOG3 = V$PUPILS5_ITOG3 + PUPILS5;
                V$CLASSES6_ITOG3 = V$CLASSES6_ITOG3 + CLASSES6;
                V$PUPILS6_ITOG3 = V$PUPILS6_ITOG3 + PUPILS6;
                V$CLASSES7_ITOG3 = V$CLASSES7_ITOG3 + CLASSES7;
                V$PUPILS7_ITOG3 = V$PUPILS7_ITOG3 + PUPILS7;
                V$CLASSES8_ITOG3 = V$CLASSES8_ITOG3 + CLASSES8;
                V$PUPILS8_ITOG3 = V$PUPILS8_ITOG3 + PUPILS8;
                V$CLASSES9_ITOG3 = V$CLASSES9_ITOG3 + CLASSES9;
                V$PUPILS9_ITOG3 = V$PUPILS9_ITOG3 + PUPILS9;
                V$CLASSESDSALL_ITOG3 = V$CLASSESDSALL_ITOG3 + CLASSESDSALL;
                V$PUPILSDSALL_ITOG3 = V$PUPILSDSALL_ITOG3 + PUPILSDSALL;
                V$CLASSESALL_ITOG3 = V$CLASSESALL_ITOG3 + CLASSESALL;
                V$PUPILSALL_ITOG3 = V$PUPILSALL_ITOG3 + PUPILSALL;
            END
            ELSE IF (V$CLASS_KIND = 3268) THEN
            BEGIN
                V$CLASSES1_ITOG4 = V$CLASSES1_ITOG4 + CLASSES1;
                V$PUPILS1_ITOG4 = V$PUPILS1_ITOG4 + PUPILS1;
                V$CLASSES2_ITOG4 = V$CLASSES2_ITOG4 + CLASSES2;
                V$PUPILS2_ITOG4 = V$PUPILS2_ITOG4 + PUPILS2;
                V$CLASSES3_ITOG4 = V$CLASSES3_ITOG4 + CLASSES3;
                V$PUPILS3_ITOG4 = V$PUPILS3_ITOG4 + PUPILS3;
                V$CLASSES4_ITOG4 = V$CLASSES4_ITOG4 + CLASSES4;
                V$PUPILS4_ITOG4 = V$PUPILS4_ITOG4 + PUPILS4;
                V$CLASSESYASALL_ITOG4 = V$CLASSESYASALL_ITOG4 + CLASSESYASALL;
                V$PUPILSYASALL_ITOG4 = V$PUPILSYASALL_ITOG4 + PUPILSYASALL;
                V$CLASSES5_ITOG4 = V$CLASSES5_ITOG4 + CLASSES5;
                V$PUPILS5_ITOG4 = V$PUPILS5_ITOG4 + PUPILS5;
                V$CLASSES6_ITOG4 = V$CLASSES6_ITOG4 + CLASSES6;
                V$PUPILS6_ITOG4 = V$PUPILS6_ITOG4 + PUPILS6;
                V$CLASSES7_ITOG4 = V$CLASSES7_ITOG4 + CLASSES7;
                V$PUPILS7_ITOG4 = V$PUPILS7_ITOG4 + PUPILS7;
                V$CLASSES8_ITOG4 = V$CLASSES8_ITOG4 + CLASSES8;
                V$PUPILS8_ITOG4 = V$PUPILS8_ITOG4 + PUPILS8;
                V$CLASSES9_ITOG4 = V$CLASSES9_ITOG4 + CLASSES9;
                V$PUPILS9_ITOG4 = V$PUPILS9_ITOG4 + PUPILS9;
                V$CLASSESDSALL_ITOG4 = V$CLASSESDSALL_ITOG4 + CLASSESDSALL;
                V$PUPILSDSALL_ITOG4 = V$PUPILSDSALL_ITOG4 + PUPILSDSALL;
                V$CLASSESALL_ITOG4 = V$CLASSESALL_ITOG4 + CLASSESALL;
                V$PUPILSALL_ITOG4 = V$PUPILSALL_ITOG4 + PUPILSALL;
            END
        END

        ORDER_KIND = 0;

        STR = V$OU_SHORTNAME;
        CLASSES1 = V$CLASSES1;
        PUPILS1 = V$PUPILS1;
        CLASSES2 = V$CLASSES2;
        PUPILS2 = V$PUPILS2;
        CLASSES3 = V$CLASSES3;
        PUPILS3 = V$PUPILS3;
        CLASSES4 = V$CLASSES4;
        PUPILS4 = V$PUPILS4;
        CLASSES5 = V$CLASSES5;
        PUPILS5 = V$PUPILS5;
        CLASSES6 = V$CLASSES6;
        PUPILS6 = V$PUPILS6;
        CLASSES7 = V$CLASSES7;
        PUPILS7 = V$PUPILS7;
        CLASSES8 = V$CLASSES8;
        PUPILS8 = V$PUPILS8;
        CLASSES9 = V$CLASSES9;
        PUPILS9 = V$PUPILS9;
        CLASSESYASALL = V$CLASSESYASALL;
        PUPILSYASALL = V$PUPILSYASALL;
        CLASSESDSALL = V$CLASSESDSALL;
        PUPILSDSALL = V$PUPILSDSALL;
        CLASSESALL = V$CLASSESALL;
        PUPILSALL = V$PUPILSALL;

        SUSPEND;

        V$CLASSES1_ITOGALL = V$CLASSES1_ITOGALL + CLASSES1;
        V$PUPILS1_ITOGALL = V$PUPILS1_ITOGALL + PUPILS1;
        V$CLASSES2_ITOGALL = V$CLASSES2_ITOGALL + CLASSES2;
        V$PUPILS2_ITOGALL = V$PUPILS2_ITOGALL + PUPILS2;
        V$CLASSES3_ITOGALL = V$CLASSES3_ITOGALL + CLASSES3;
        V$PUPILS3_ITOGALL = V$PUPILS3_ITOGALL + PUPILS3;
        V$CLASSES4_ITOGALL = V$CLASSES4_ITOGALL + CLASSES4;
        V$PUPILS4_ITOGALL = V$PUPILS4_ITOGALL + PUPILS4;
        V$CLASSESYASALL_ITOGALL = V$CLASSESYASALL_ITOGALL + CLASSESYASALL;
        V$PUPILSYASALL_ITOGALL = V$PUPILSYASALL_ITOGALL + PUPILSYASALL;
        V$CLASSES5_ITOGALL = V$CLASSES5_ITOGALL + CLASSES5;
        V$PUPILS5_ITOGALL = V$PUPILS5_ITOGALL + PUPILS5;
        V$CLASSES6_ITOGALL = V$CLASSES6_ITOGALL + CLASSES6;
        V$PUPILS6_ITOGALL = V$PUPILS6_ITOGALL + PUPILS6;
        V$CLASSES7_ITOGALL = V$CLASSES7_ITOGALL + CLASSES7;
        V$PUPILS7_ITOGALL = V$PUPILS7_ITOGALL + PUPILS7;
        V$CLASSES8_ITOGALL = V$CLASSES8_ITOGALL + CLASSES8;
        V$PUPILS8_ITOGALL = V$PUPILS8_ITOGALL + PUPILS8;
        V$CLASSES9_ITOGALL = V$CLASSES9_ITOGALL + CLASSES9;
        V$PUPILS9_ITOGALL = V$PUPILS9_ITOGALL + PUPILS9;
        V$CLASSESDSALL_ITOGALL = V$CLASSESDSALL_ITOGALL + CLASSESDSALL;
        V$PUPILSDSALL_ITOGALL = V$PUPILSDSALL_ITOGALL + PUPILSDSALL;
        V$CLASSESALL_ITOGALL = V$CLASSESALL_ITOGALL + CLASSESALL;
        V$PUPILSALL_ITOGALL = V$PUPILSALL_ITOGALL + PUPILSALL;


        ORDER_KIND = -1;

        STR = null;
        CLASSES1 = null;
        PUPILS1 = null;
        CLASSES2 = null;
        PUPILS2 = null;
        CLASSES3 = null;
        PUPILS3 = null;
        CLASSES4 = null;
        PUPILS4 = null;
        CLASSES5 = null;
        PUPILS5 = null;
        CLASSES6 = null;
        PUPILS6 = null;
        CLASSES7 = null;
        PUPILS7 = null;
        CLASSES8 = null;
        PUPILS8 = null;
        CLASSES9 = null;
        PUPILS9 = null;
        CLASSESYASALL = null;
        PUPILSYASALL = null;
        CLASSESDSALL = null;
        PUPILSDSALL = null;
        CLASSESALL = null;
        PUPILSALL = null;
        SUSPEND;

        ORDER_SCHOOL = ORDER_SCHOOL + 1;
    END

    ORDER_SCHOOL = 0;

    ORDER_KIND = 1;

    STR = 'общераз';
    CLASSES1 = V$CLASSES1_ITOG1;
    PUPILS1 = V$PUPILS1_ITOG1;
    CLASSES2 = V$CLASSES2_ITOG1;
    PUPILS2 = V$PUPILS2_ITOG1;
    CLASSES3 = V$CLASSES3_ITOG1;
    PUPILS3 = V$PUPILS3_ITOG1;
    CLASSES4 = V$CLASSES4_ITOG1;
    PUPILS4 = V$PUPILS4_ITOG1;
    CLASSES5 = V$CLASSES5_ITOG1;
    PUPILS5 = V$PUPILS5_ITOG1;
    CLASSES6 = V$CLASSES6_ITOG1;
    PUPILS6 = V$PUPILS6_ITOG1;
    CLASSES7 = V$CLASSES7_ITOG1;
    PUPILS7 = V$PUPILS7_ITOG1;
    CLASSES8 = V$CLASSES8_ITOG1;
    PUPILS8 = V$PUPILS8_ITOG1;
    CLASSES9 = V$CLASSES9_ITOG1;
    PUPILS9 = V$PUPILS9_ITOG1;
    CLASSESYASALL = V$CLASSESYASALL_ITOG1;
    PUPILSYASALL = V$PUPILSYASALL_ITOG1;
    CLASSESDSALL = V$CLASSESDSALL_ITOG1;
    PUPILSDSALL = V$PUPILSDSALL_ITOG1;
    CLASSESALL = V$CLASSESALL_ITOG1;
    PUPILSALL = V$PUPILSALL_ITOG1;

    SUSPEND;

    ORDER_KIND = 2;

    STR = 'компен';
    CLASSES1 = V$CLASSES1_ITOG2;
    PUPILS1 = V$PUPILS1_ITOG2;
    CLASSES2 = V$CLASSES2_ITOG2;
    PUPILS2 = V$PUPILS2_ITOG2;
    CLASSES3 = V$CLASSES3_ITOG2;
    PUPILS3 = V$PUPILS3_ITOG2;
    CLASSES4 = V$CLASSES4_ITOG2;
    PUPILS4 = V$PUPILS4_ITOG2;
    CLASSES5 = V$CLASSES5_ITOG2;
    PUPILS5 = V$PUPILS5_ITOG2;
    CLASSES6 = V$CLASSES6_ITOG2;
    PUPILS6 = V$PUPILS6_ITOG2;
    CLASSES7 = V$CLASSES7_ITOG2;
    PUPILS7 = V$PUPILS7_ITOG2;
    CLASSES8 = V$CLASSES8_ITOG2;
    PUPILS8 = V$PUPILS8_ITOG2;
    CLASSES9 = V$CLASSES9_ITOG2;
    PUPILS9 = V$PUPILS9_ITOG2;
    CLASSESYASALL = V$CLASSESYASALL_ITOG2;
    PUPILSYASALL = V$PUPILSYASALL_ITOG2;
    CLASSESDSALL = V$CLASSESDSALL_ITOG2;
    PUPILSDSALL = V$PUPILSDSALL_ITOG2;
    CLASSESALL = V$CLASSESALL_ITOG2;
    PUPILSALL = V$PUPILSALL_ITOG2;

    SUSPEND;

    ORDER_KIND = 3;

    STR = 'оздор';
    CLASSES1 = V$CLASSES1_ITOG3;
    PUPILS1 = V$PUPILS1_ITOG3;
    CLASSES2 = V$CLASSES2_ITOG3;
    PUPILS2 = V$PUPILS2_ITOG3;
    CLASSES3 = V$CLASSES3_ITOG3;
    PUPILS3 = V$PUPILS3_ITOG3;
    CLASSES4 = V$CLASSES4_ITOG3;
    PUPILS4 = V$PUPILS4_ITOG3;
    CLASSES5 = V$CLASSES5_ITOG3;
    PUPILS5 = V$PUPILS5_ITOG3;
    CLASSES6 = V$CLASSES6_ITOG3;
    PUPILS6 = V$PUPILS6_ITOG3;
    CLASSES7 = V$CLASSES7_ITOG3;
    PUPILS7 = V$PUPILS7_ITOG3;
    CLASSES8 = V$CLASSES8_ITOG3;
    PUPILS8 = V$PUPILS8_ITOG3;
    CLASSES9 = V$CLASSES9_ITOG3;
    PUPILS9 = V$PUPILS9_ITOG3;
    CLASSESYASALL = V$CLASSESYASALL_ITOG3;
    PUPILSYASALL = V$PUPILSYASALL_ITOG3;
    CLASSESDSALL = V$CLASSESDSALL_ITOG3;
    PUPILSDSALL = V$PUPILSDSALL_ITOG3;
    CLASSESALL = V$CLASSESALL_ITOG3;
    PUPILSALL = V$PUPILSALL_ITOG3;

    SUSPEND;

    ORDER_KIND = 4;

    STR = 'комбинир';
    CLASSES1 = V$CLASSES1_ITOG4;
    PUPILS1 = V$PUPILS1_ITOG4;
    CLASSES2 = V$CLASSES2_ITOG4;
    PUPILS2 = V$PUPILS2_ITOG4;
    CLASSES3 = V$CLASSES3_ITOG4;
    PUPILS3 = V$PUPILS3_ITOG4;
    CLASSES4 = V$CLASSES4_ITOG4;
    PUPILS4 = V$PUPILS4_ITOG4;
    CLASSES5 = V$CLASSES5_ITOG4;
    PUPILS5 = V$PUPILS5_ITOG4;
    CLASSES6 = V$CLASSES6_ITOG4;
    PUPILS6 = V$PUPILS6_ITOG4;
    CLASSES7 = V$CLASSES7_ITOG4;
    PUPILS7 = V$PUPILS7_ITOG4;
    CLASSES8 = V$CLASSES8_ITOG4;
    PUPILS8 = V$PUPILS8_ITOG4;
    CLASSES9 = V$CLASSES9_ITOG4;
    PUPILS9 = V$PUPILS9_ITOG4;
    CLASSESYASALL = V$CLASSESYASALL_ITOG4;
    PUPILSYASALL = V$PUPILSYASALL_ITOG4;
    CLASSESDSALL = V$CLASSESDSALL_ITOG4;
    PUPILSDSALL = V$PUPILSDSALL_ITOG4;
    CLASSESALL = V$CLASSESALL_ITOG4;
    PUPILSALL = V$PUPILSALL_ITOG4;

    SUSPEND;
     
    ORDER_KIND = 0;

    STR = 'по району';
    CLASSES1 = V$CLASSES1_ITOGALL;
    PUPILS1 = V$PUPILS1_ITOGALL;
    CLASSES2 = V$CLASSES2_ITOGALL;
    PUPILS2 = V$PUPILS2_ITOGALL;
    CLASSES3 = V$CLASSES3_ITOGALL;
    PUPILS3 = V$PUPILS3_ITOGALL;
    CLASSES4 = V$CLASSES4_ITOGALL;
    PUPILS4 = V$PUPILS4_ITOGALL;
    CLASSES5 = V$CLASSES5_ITOGALL;
    PUPILS5 = V$PUPILS5_ITOGALL;
    CLASSES6 = V$CLASSES6_ITOGALL;
    PUPILS6 = V$PUPILS6_ITOGALL;
    CLASSES7 = V$CLASSES7_ITOGALL;
    PUPILS7 = V$PUPILS7_ITOGALL;
    CLASSES8 = V$CLASSES8_ITOGALL;
    PUPILS8 = V$PUPILS8_ITOGALL;
    CLASSES9 = V$CLASSES9_ITOGALL;
    PUPILS9 = V$PUPILS9_ITOGALL;
    CLASSESYASALL = V$CLASSESYASALL_ITOGALL;
    PUPILSYASALL = V$PUPILSYASALL_ITOGALL;
    CLASSESDSALL = V$CLASSESDSALL_ITOGALL;
    PUPILSDSALL = V$PUPILSDSALL_ITOGALL;
    CLASSESALL = V$CLASSESALL_ITOGALL;
    PUPILSALL = V$PUPILSALL_ITOGALL;
    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CLASSES_COUNT_ON_DATE_DTL (
    I$STAGE_NAME VARCHAR(100),
    I$CLASS_KIND_COL INTEGER,
    I$DT DATE,
    I$USER_ID BIGINT)
RETURNS (
    VAL1 VARCHAR(250),
    VAL2 VARCHAR(250))
AS
declare variable V$LANG_CODE varchar(2);
declare variable V$STAGE_ID bigint;
declare variable V$CLASS_ID bigint;
declare variable V$CLASS_KIND integer;
declare variable V$SCHOOLAR_ID bigint;
declare variable V$MOVE_ID integer;
declare variable V$COUNT_PUPIL integer;
declare variable V$DT_IN date;
declare variable V$DT_OUT date;
declare variable V$ALLYASL_CLASSES_ALL integer;
declare variable V$ALLYASL_PUPILS_ALL integer;
declare variable V$ALLYASL_CLASSES1 integer;
declare variable V$ALLYASL_PUPILS1 integer;
declare variable V$ALLYASL_CLASSES2 integer;
declare variable V$ALLYASL_PUPILS2 integer;
declare variable V$ALLYASL_CLASSES3 integer;
declare variable V$ALLYASL_PUPILS3 integer;
declare variable V$ALLYASL_CLASSES4 integer;
declare variable V$ALLYASL_PUPILS4 integer;
declare variable V$ALLDS_CLASSES_ALL integer;
declare variable V$ALLDS_PUPILS_ALL integer;
declare variable V$ALLDS_CLASSES1 integer;
declare variable V$ALLDS_PUPILS1 integer;
declare variable V$ALLDS_CLASSES2 integer;
declare variable V$ALLDS_PUPILS2 integer;
declare variable V$ALLDS_CLASSES3 integer;
declare variable V$ALLDS_PUPILS3 integer;
declare variable V$ALLDS_CLASSES4 integer;
declare variable V$ALLDS_PUPILS4 integer;
BEGIN
  SELECT LANG_CODE
  FROM USERS
  WHERE USER_ID = :I$USER_ID
  INTO :V$LANG_CODE;

  FOR
    SELECT L8.OBJ_ID
    FROM LISTVALS LV
    LEFT JOIN RES_GET(LV.RES_ID, :V$LANG_CODE) R ON 1 = 1
    JOIN VALL V49 ON V49.PARAM_ID = 49 AND V49.IS_DEL = 0 AND V49.LISTVAL_ID = LV.LISTVAL_ID
    JOIN LINKS L8 ON L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL AND L8.OBJ_ID = V49.OBJ_ID AND L8.PARENT_TYPE_ID = 7
    WHERE LV.LIST_ID = 25 AND LV.PARENT_ID = 2140
      AND (
        :I$STAGE_NAME = R.VAL
        OR (:I$STAGE_NAME = 'Итого Ясли' AND LV.LISTVAL_ID IN (30, 31, 32, 33))
        OR (:I$STAGE_NAME = 'Итого Детский сад'  AND LV.LISTVAL_ID IN (3261, 34, 35, 36, 3262))
        OR :I$STAGE_NAME = 'Всего по учреждению')
    INTO :V$STAGE_ID
  DO
  BEGIN
    FOR
      SELECT L9.OBJ_ID
      FROM LINKS L9
      JOIN VALL V1549 ON V1549.OBJ_ID = L9.OBJ_ID AND V1549.IS_DEL = 0 AND V1549.PARAM_ID = 1549
      WHERE L9.PARENT_ID = :V$STAGE_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
      AND (
        :I$CLASS_KIND_COL = 2
        OR (:I$CLASS_KIND_COL = 4 AND V1549.LISTVAL_ID = 3265)
        OR (:I$CLASS_KIND_COL = 6 AND V1549.LISTVAL_ID = 3266)
        OR (:I$CLASS_KIND_COL = 8 AND V1549.LISTVAL_ID = 3268)
        OR (:I$CLASS_KIND_COL = 10 AND V1549.LISTVAL_ID = 3267))
      INTO :V$CLASS_ID
    DO
    BEGIN
      FOR
        SELECT DISTINCT M.PERSON_ID
        FROM PERSON_MOVEMENTS M
        WHERE M.DATE_DEL IS NULL AND M.GROUP_ID = :V$CLASS_ID AND (M.DATE_IN <= :I$DT OR :I$DT IS NULL) AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :I$DT)
        INTO :V$SCHOOLAR_ID
      DO
      BEGIN
        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:V$SCHOOLAR_ID)
        INTO :VAL1;

        SELECT D
        FROM VAL_GET(:V$SCHOOLAR_ID, 89)
        INTO :VAL2;

        SUSPEND;
      END
    END
  END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CLASSES_COUNT_ON_DATE_GET (
    I$DT DATE,
    I$USER_ID BIGINT)
RETURNS (
    STAGE_NAME VARCHAR(400),
    CLASSES_COUNT_ALL INTEGER,
    PUPILS_COUNT_ALL INTEGER,
    CLASSES1_COUNT INTEGER,
    PUPILS1_COUNT INTEGER,
    CLASSES2_COUNT INTEGER,
    PUPILS2_COUNT INTEGER,
    CLASSES3_COUNT INTEGER,
    PUPILS3_COUNT INTEGER,
    CLASSES4_COUNT INTEGER,
    PUPILS4_COUNT INTEGER)
AS
declare variable V$LANG_CODE varchar(2);
declare variable V$STAGE_ID bigint;
declare variable V$CLASS_ID bigint;
declare variable V$CLASS_KIND integer;
declare variable V$SCHOOLAR_ID bigint;
declare variable V$MOVE_ID integer;
declare variable V$COUNT_PUPIL integer;
declare variable V$DT_IN date;
declare variable V$DT_OUT date;
declare variable V$ALLYASL_CLASSES_ALL integer;
declare variable V$ALLYASL_PUPILS_ALL integer;
declare variable V$ALLYASL_CLASSES1 integer;
declare variable V$ALLYASL_PUPILS1 integer;
declare variable V$ALLYASL_CLASSES2 integer;
declare variable V$ALLYASL_PUPILS2 integer;
declare variable V$ALLYASL_CLASSES3 integer;
declare variable V$ALLYASL_PUPILS3 integer;
declare variable V$ALLYASL_CLASSES4 integer;
declare variable V$ALLYASL_PUPILS4 integer;
declare variable V$ALLDS_CLASSES_ALL integer;
declare variable V$ALLDS_PUPILS_ALL integer;
declare variable V$ALLDS_CLASSES1 integer;
declare variable V$ALLDS_PUPILS1 integer;
declare variable V$ALLDS_CLASSES2 integer;
declare variable V$ALLDS_PUPILS2 integer;
declare variable V$ALLDS_CLASSES3 integer;
declare variable V$ALLDS_PUPILS3 integer;
declare variable V$ALLDS_CLASSES4 integer;
declare variable V$ALLDS_PUPILS4 integer;
declare variable V$SO integer;
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :V$LANG_CODE;

    ----------Ясли---------------
    V$ALLYASL_CLASSES_ALL = 0;
    V$ALLYASL_PUPILS_ALL = 0;
    V$ALLYASL_CLASSES1 = 0;
    V$ALLYASL_PUPILS1 = 0;
    V$ALLYASL_CLASSES2 = 0;
    V$ALLYASL_PUPILS2 = 0;
    V$ALLYASL_CLASSES3 = 0;
    V$ALLYASL_PUPILS3 = 0;
    V$ALLYASL_CLASSES4 = 0;
    V$ALLYASL_PUPILS4 = 0;
    FOR
        -- Пустая строка если вообще нет
        SELECT R.VAL, NULL, LV.SORT_ORDER
        FROM LISTVALS LV
        LEFT JOIN RES_GET(LV.RES_ID, :V$LANG_CODE) R ON 1 = 1
        WHERE LV.PARENT_ID = 2140 AND LV.LISTVAL_ID IN (30, 31, 32, 33) AND NOT EXISTS (
          SELECT FIRST 1 1
          FROM VALL V49
          JOIN LINKS L8 ON L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL AND L8.OBJ_ID = V49.OBJ_ID AND L8.PARENT_TYPE_ID = 7
          WHERE V49.PARAM_ID = 49 AND V49.IS_DEL = 0 AND V49.LISTVAL_ID = LV.LISTVAL_ID
        )
        -- По одной строке на каждый уровень, если есть
        UNION
        SELECT R.VAL, L8.OBJ_ID, LV.SORT_ORDER
        FROM LISTVALS LV
        LEFT JOIN RES_GET(LV.RES_ID, :V$LANG_CODE) R ON 1 = 1
        JOIN VALL V49 ON V49.PARAM_ID = 49 AND V49.IS_DEL = 0 AND V49.LISTVAL_ID = LV.LISTVAL_ID
        JOIN LINKS L8 ON L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL AND L8.OBJ_ID = V49.OBJ_ID AND L8.PARENT_TYPE_ID = 7
        WHERE LV.PARENT_ID = 2140 AND LV.LISTVAL_ID IN (30, 31, 32, 33)
        ORDER BY 3
        INTO :STAGE_NAME, :V$STAGE_ID, :V$SO
    DO
    BEGIN
        CLASSES_COUNT_ALL = 0;
        PUPILS_COUNT_ALL = 0;
        CLASSES1_COUNT = 0;
        PUPILS1_COUNT = 0;
        CLASSES2_COUNT = 0;
        PUPILS2_COUNT = 0;
        CLASSES3_COUNT = 0;
        PUPILS3_COUNT = 0;
        CLASSES4_COUNT = 0;
        PUPILS4_COUNT = 0;

        FOR
            SELECT L9.OBJ_ID, V1549.LISTVAL_ID
            FROM LINKS L9
            JOIN VALL V1549 ON V1549.OBJ_ID = L9.OBJ_ID AND V1549.IS_DEL = 0 AND V1549.PARAM_ID = 1549
            WHERE L9.PARENT_ID = :V$STAGE_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
            INTO :V$CLASS_ID, :V$CLASS_KIND
        DO
        BEGIN
            SELECT COUNT(DISTINCT M.PERSON_ID)
            FROM PERSON_MOVEMENTS M
            WHERE M.DATE_DEL IS NULL AND M.GROUP_ID = :V$CLASS_ID -- AND M.REASON_IN >= 3276 AND M.REASON_IN <= 3278
              AND M.DATE_IN <= :I$DT AND (M.DATE_OUT IS NULL OR M.DATE_OUT > :I$DT)
            INTO :V$COUNT_PUPIL;

            IF (V$COUNT_PUPIL >0) THEN
            BEGIN
                IF (V$CLASS_KIND = 3265) THEN
                BEGIN
                    PUPILS1_COUNT = PUPILS1_COUNT + V$COUNT_PUPIL;
                    CLASSES1_COUNT = CLASSES1_COUNT + 1;
                END
                ELSE IF (V$CLASS_KIND = 3266) THEN
                BEGIN
                    PUPILS2_COUNT = PUPILS2_COUNT + V$COUNT_PUPIL;
                    CLASSES2_COUNT = CLASSES2_COUNT + 1;
                END
                ELSE IF (V$CLASS_KIND = 3268) THEN
                BEGIN
                    PUPILS3_COUNT = PUPILS3_COUNT + V$COUNT_PUPIL;
                    CLASSES3_COUNT = CLASSES3_COUNT + 1;
                END
                ELSE IF (V$CLASS_KIND = 3267) THEN
                BEGIN
                    PUPILS4_COUNT = PUPILS4_COUNT + V$COUNT_PUPIL;
                    CLASSES4_COUNT = CLASSES4_COUNT + 1;
                END
            END
        END

        CLASSES_COUNT_ALL = CLASSES1_COUNT + CLASSES2_COUNT + CLASSES3_COUNT + CLASSES4_COUNT;
        PUPILS_COUNT_ALL = PUPILS1_COUNT + PUPILS2_COUNT + PUPILS3_COUNT + PUPILS4_COUNT;
        SUSPEND;

        V$ALLYASL_CLASSES_ALL = V$ALLYASL_CLASSES_ALL + CLASSES_COUNT_ALL;
        V$ALLYASL_PUPILS_ALL = V$ALLYASL_PUPILS_ALL + PUPILS_COUNT_ALL;
        V$ALLYASL_CLASSES1 = V$ALLYASL_CLASSES1 + CLASSES1_COUNT;
        V$ALLYASL_CLASSES2 = V$ALLYASL_CLASSES2 + CLASSES2_COUNT;
        V$ALLYASL_CLASSES3 = V$ALLYASL_CLASSES3 + CLASSES3_COUNT;
        V$ALLYASL_CLASSES4 = V$ALLYASL_CLASSES4 + CLASSES4_COUNT;
        V$ALLYASL_PUPILS1 = V$ALLYASL_PUPILS1 + PUPILS1_COUNT;
        V$ALLYASL_PUPILS2 = V$ALLYASL_PUPILS2 + PUPILS2_COUNT;
        V$ALLYASL_PUPILS3 = V$ALLYASL_PUPILS3 + PUPILS3_COUNT;
        V$ALLYASL_PUPILS4 = V$ALLYASL_PUPILS4 + PUPILS4_COUNT;
    END

    STAGE_NAME = 'Итого Ясли';
    CLASSES_COUNT_ALL = V$ALLYASL_CLASSES_ALL;
    PUPILS_COUNT_ALL  = V$ALLYASL_PUPILS_ALL;
    CLASSES1_COUNT = V$ALLYASL_CLASSES1;
    CLASSES2_COUNT = V$ALLYASL_CLASSES2;
    CLASSES3_COUNT = V$ALLYASL_CLASSES3;
    CLASSES4_COUNT = V$ALLYASL_CLASSES4;
    PUPILS1_COUNT = V$ALLYASL_PUPILS1;
    PUPILS2_COUNT = V$ALLYASL_PUPILS2;
    PUPILS3_COUNT = V$ALLYASL_PUPILS3;
    PUPILS4_COUNT = V$ALLYASL_PUPILS4;
    SUSPEND;


    ----------Детский сад---------------
    V$ALLDS_CLASSES_ALL = 0;
    V$ALLDS_PUPILS_ALL = 0;
    V$ALLDS_CLASSES1 = 0;
    V$ALLDS_PUPILS1 = 0;
    V$ALLDS_CLASSES2 = 0;
    V$ALLDS_PUPILS2 = 0;
    V$ALLDS_CLASSES3 = 0;
    V$ALLDS_PUPILS3 = 0;
    V$ALLDS_CLASSES4 = 0;
    V$ALLDS_PUPILS4 = 0;
    FOR
        -- Пустая строка если вообще нет
        SELECT R.VAL, NULL, LV.SORT_ORDER
        FROM LISTVALS LV
        LEFT JOIN RES_GET(LV.RES_ID, :V$LANG_CODE) R ON 1 = 1
        WHERE LV.PARENT_ID = 2140 AND LV.LISTVAL_ID IN (3261, 34, 35, 36, 3262) AND NOT EXISTS (
          SELECT FIRST 1 1
          FROM VALL V49
          JOIN LINKS L8 ON L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL AND L8.OBJ_ID = V49.OBJ_ID AND L8.PARENT_TYPE_ID = 7
          WHERE V49.PARAM_ID = 49 AND V49.IS_DEL = 0 AND V49.LISTVAL_ID = LV.LISTVAL_ID
        )
        -- По одной строке на каждый уровень, если есть
        UNION
        SELECT R.VAL, L8.OBJ_ID, LV.SORT_ORDER
        FROM LISTVALS LV
        LEFT JOIN RES_GET(LV.RES_ID, :V$LANG_CODE) R ON 1 = 1
        JOIN VALL V49 ON V49.PARAM_ID = 49 AND V49.IS_DEL = 0 AND V49.LISTVAL_ID = LV.LISTVAL_ID
        JOIN LINKS L8 ON L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL AND L8.OBJ_ID = V49.OBJ_ID AND L8.PARENT_TYPE_ID = 7
        WHERE LV.PARENT_ID = 2140 AND LV.LISTVAL_ID IN (3261, 34, 35, 36, 3262)
        ORDER BY 3
        INTO :STAGE_NAME, :V$STAGE_ID, :V$SO
    DO
    BEGIN
        CLASSES_COUNT_ALL = 0;
        PUPILS_COUNT_ALL = 0;
        CLASSES1_COUNT = 0;
        PUPILS1_COUNT = 0;
        CLASSES2_COUNT = 0;
        PUPILS2_COUNT = 0;
        CLASSES3_COUNT = 0;
        PUPILS3_COUNT = 0;
        CLASSES4_COUNT = 0;
        PUPILS4_COUNT = 0;

        FOR
            SELECT L9.OBJ_ID, V1549.LISTVAL_ID
            FROM LINKS L9
            JOIN VALL V1549 ON V1549.OBJ_ID = L9.OBJ_ID AND V1549.IS_DEL = 0 AND V1549.PARAM_ID = 1549
            WHERE L9.PARENT_ID = :V$STAGE_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
            INTO :V$CLASS_ID, :V$CLASS_KIND
        DO
        BEGIN
            SELECT COUNT(DISTINCT M.PERSON_ID)
            FROM PERSON_MOVEMENTS M
            WHERE M.DATE_DEL IS NULL AND M.GROUP_ID = :V$CLASS_ID -- AND M.REASON_IN >= 3276 AND M.REASON_IN <= 3278
              AND M.DATE_IN <= :I$DT AND (M.DATE_OUT IS NULL OR M.DATE_OUT > :I$DT)
            INTO :V$COUNT_PUPIL;

            IF (V$COUNT_PUPIL >0) THEN
            BEGIN
                IF (V$CLASS_KIND = 3265) THEN
                BEGIN
                    PUPILS1_COUNT = PUPILS1_COUNT + V$COUNT_PUPIL;
                    CLASSES1_COUNT = CLASSES1_COUNT + 1;
                END
                ELSE IF (V$CLASS_KIND = 3266) THEN
                BEGIN
                    PUPILS2_COUNT = PUPILS2_COUNT + V$COUNT_PUPIL;
                    CLASSES2_COUNT = CLASSES2_COUNT + 1;
                END
                ELSE IF (V$CLASS_KIND = 3268) THEN
                BEGIN
                    PUPILS3_COUNT = PUPILS3_COUNT + V$COUNT_PUPIL;
                    CLASSES3_COUNT = CLASSES3_COUNT + 1;
                END
                ELSE IF (V$CLASS_KIND = 3267) THEN
                BEGIN
                    PUPILS4_COUNT = PUPILS4_COUNT + V$COUNT_PUPIL;
                    CLASSES4_COUNT = CLASSES4_COUNT + 1;
                END
            END
        END

        CLASSES_COUNT_ALL = CLASSES1_COUNT + CLASSES2_COUNT + CLASSES3_COUNT + CLASSES4_COUNT;
        PUPILS_COUNT_ALL = PUPILS1_COUNT + PUPILS2_COUNT + PUPILS3_COUNT + PUPILS4_COUNT;

        SUSPEND;

        V$ALLDS_CLASSES_ALL = V$ALLDS_CLASSES_ALL + CLASSES_COUNT_ALL;
        V$ALLDS_PUPILS_ALL = V$ALLDS_PUPILS_ALL + PUPILS_COUNT_ALL;
        V$ALLDS_CLASSES1 = V$ALLDS_CLASSES1 + CLASSES1_COUNT;
        V$ALLDS_CLASSES2 = V$ALLDS_CLASSES2 + CLASSES2_COUNT;
        V$ALLDS_CLASSES3 = V$ALLDS_CLASSES3 + CLASSES3_COUNT;
        V$ALLDS_CLASSES4 = V$ALLDS_CLASSES4 + CLASSES4_COUNT;
        V$ALLDS_PUPILS1 = V$ALLDS_PUPILS1 + PUPILS1_COUNT;
        V$ALLDS_PUPILS2 = V$ALLDS_PUPILS2 + PUPILS2_COUNT;
        V$ALLDS_PUPILS3 = V$ALLDS_PUPILS3 + PUPILS3_COUNT;
        V$ALLDS_PUPILS4 = V$ALLDS_PUPILS4 + PUPILS4_COUNT;
    END

    STAGE_NAME = 'Итого Детский сад';
    CLASSES_COUNT_ALL = V$ALLDS_CLASSES_ALL;
    PUPILS_COUNT_ALL  = V$ALLDS_PUPILS_ALL;
    CLASSES1_COUNT = V$ALLDS_CLASSES1;
    CLASSES2_COUNT = V$ALLDS_CLASSES2;
    CLASSES3_COUNT = V$ALLDS_CLASSES3;
    CLASSES4_COUNT = V$ALLDS_CLASSES4;
    PUPILS1_COUNT = V$ALLDS_PUPILS1;
    PUPILS2_COUNT = V$ALLDS_PUPILS2;
    PUPILS3_COUNT = V$ALLDS_PUPILS3;
    PUPILS4_COUNT = V$ALLDS_PUPILS4;
    SUSPEND;

    STAGE_NAME = 'Всего по учреждению';
    CLASSES_COUNT_ALL = V$ALLDS_CLASSES_ALL + V$ALLYASL_CLASSES_ALL ;
    PUPILS_COUNT_ALL  = V$ALLDS_PUPILS_ALL + V$ALLYASL_PUPILS_ALL;
    CLASSES1_COUNT = V$ALLDS_CLASSES1 + V$ALLYASL_CLASSES1;
    CLASSES2_COUNT = V$ALLDS_CLASSES2 + V$ALLYASL_CLASSES2;
    CLASSES3_COUNT = V$ALLDS_CLASSES3 + V$ALLYASL_CLASSES3;
    CLASSES4_COUNT = V$ALLDS_CLASSES4 + V$ALLYASL_CLASSES4;
    PUPILS1_COUNT = V$ALLDS_PUPILS1 + V$ALLYASL_PUPILS1;
    PUPILS2_COUNT = V$ALLDS_PUPILS2 + V$ALLYASL_PUPILS2;
    PUPILS3_COUNT = V$ALLDS_PUPILS3 + V$ALLYASL_PUPILS3;
    PUPILS4_COUNT = V$ALLDS_PUPILS4 + V$ALLYASL_PUPILS4;
    SUSPEND;

END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CLASSEXTERNAT_LIST_NEXT_STAGE (
    I$CLASS_ID BIGINT)
RETURNS (
    CLASS_ID BIGINT,
    CLASS_NUMBER INTEGER,
    CLASS_NAME VARCHAR(255))
AS
declare variable V$CLASS_NUMNBER integer;
BEGIN

    SELECT LV.TAG
    FROM LINKS L187
    
    INNER JOIN LINKS L8
    ON L8.OBJ_ID = L187.PARENT_ID
    AND L8.OBJ_TYPE_ID = 8
    AND L8.DATE_DEL IS NULL
    
    INNER JOIN VALL V49
    ON V49.OBJ_ID = L8.OBJ_ID
    AND V49.PARAM_ID = 49
    AND V49.IS_DEL = 0
    
    INNER JOIN LISTVALS LV
    ON LV.LISTVAL_ID = V49.LISTVAL_ID
    
    WHERE L187.OBJ_ID = :I$CLASS_ID
    AND L187.OBJ_TYPE_ID = 187
    AND L187.DATE_DEL IS NULL
    INTO :V$CLASS_NUMNBER;

    V$CLASS_NUMNBER = V$CLASS_NUMNBER + 1;
    FOR
        SELECT L187.OBJ_ID,
               LV.TAG
        FROM LINKS L187
        
        JOIN LINKS L8
        ON L8.OBJ_ID = L187.PARENT_ID
        AND L8.OBJ_TYPE_ID = 8
        AND L8.DATE_DEL IS NULL
        
        JOIN VALL V49
        ON V49.OBJ_ID = L8.OBJ_ID
        AND V49.PARAM_ID = 49
        AND V49.IS_DEL = 0
        
        JOIN LISTVALS LV
        ON LV.LISTVAL_ID = V49.LISTVAL_ID
        AND LV.TAG = :V$CLASS_NUMNBER
        
        WHERE L187.OBJ_TYPE_ID = 187
        AND L187.DATE_DEL IS NULL
        INTO :CLASS_ID, :CLASS_NUMBER
    DO
    BEGIN
        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:CLASS_ID)
        INTO :CLASS_NAME;
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CLASSEXTERNAT_PUPILS_LIST (
    I$CLASS_ID BIGINT)
RETURNS (
    PUPIL_ID BIGINT,
    FIO VARCHAR(500))
AS
BEGIN

    FOR
        SELECT V55.VAL||' '||COALESCE(V56.VAL,'')||' '||COALESCE(V57.VAL,''), L10.OBJ_ID FROM LINKS L10
        
        LEFT JOIN VALS V55
        ON V55.OBJ_ID = L10.OBJ_ID
        AND V55.PARAM_ID = 55
        AND V55.IS_DEL = 0
        
        LEFT JOIN VALS V56
        ON V56.OBJ_ID = L10.OBJ_ID
        AND V56.PARAM_ID = 56
        AND V56.IS_DEL = 0
        
        LEFT JOIN VALS V57
        ON V57.OBJ_ID = L10.OBJ_ID
        AND V57.PARAM_ID = 57
        AND V57.IS_DEL = 0
        
        WHERE L10.OBJ_TYPE_ID = 10
        AND L10.DATE_DEL IS NULL
        AND L10.PARENT_TYPE_ID = 187
        AND L10.PARENT_ID = :I$CLASS_ID
        INTO :FIO, :PUPIL_ID
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CLASSEXTERNAT_PUPIL_TRANSFER (
    I$PUPIL_ID BIGINT,
    I$CLASS_ID BIGINT,
    I$USER_ID BIGINT)
AS
declare variable V$BLOB_ID bigint;
declare variable V$STAGE_ID bigint;
declare variable V$CAPTION varchar(1000);
declare variable V$OLD_STAGE bigint;
declare variable V$OLD_CLASS bigint;
declare variable V$OLD_TYPE bigint;
declare variable V$REF bigint;
BEGIN
    -- Перевод класса-экстерната на следующую ступень

    IF (I$CLASS_ID IS NULL) THEN EXIT;

    -- Какой сейчас уровень и класс ?
    SELECT L187.OBJ_ID
    FROM LINKS L10
    JOIN LINKS L187 ON L187.OBJ_ID = L10.PARENT_ID AND L187.DATE_DEL IS NULL AND L187.OBJ_TYPE_ID = 187
    JOIN LINKS L8 ON L8.OBJ_ID = L187.PARENT_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
    WHERE L10.OBJ_ID = :I$PUPIL_ID AND L10.PARENT_TYPE_ID = 187 AND L10.DATE_DEL IS NULL
    INTO :V$OLD_CLASS;

    SELECT OBJ_ID FROM VARGRP_MOVE_PUPIL(:I$PUPIL_ID, :V$OLD_CLASS, NULL, NULL, CURRENT_DATE, 1, :I$USER_ID, NULL, 12906) INTO :V$BLOB_ID;
    SELECT OBJ_ID FROM VARGRP_MOVE_PUPIL(:I$PUPIL_ID, :I$CLASS_ID, NULL, NULL, CURRENT_DATE, 0, :I$USER_ID, NULL, 12905) INTO :V$BLOB_ID;

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CLASSEXTERNAT_TRANSFER_ADD (
    I$PUPIL_ID BIGINT,
    I$USER_ID BIGINT,
    I$CLASS_NAME VARCHAR(255))
RETURNS (
    CLASS_ID BIGINT)
AS
declare variable V$CLASS_NUMBER integer;
declare variable V$STAGE_ID bigint;
declare variable V$BLOB_ID bigint;
BEGIN
    SELECT LV.TAG
    FROM LINKS L10
    JOIN LINKS L187 ON L187.OBJ_ID = L10.PARENT_ID AND L187.DATE_DEL IS NULL AND L187.OBJ_TYPE_ID = 187
    JOIN LINKS L8 ON L8.OBJ_ID = L187.PARENT_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V49.LISTVAL_ID
    WHERE L10.OBJ_ID = :I$PUPIL_ID AND L10.PARENT_TYPE_ID = 187 AND L10.DATE_DEL IS NULL
    INTO :V$CLASS_NUMBER;

    IF (V$CLASS_NUMBER < 12) THEN
    BEGIN
        V$CLASS_NUMBER = V$CLASS_NUMBER + 1;

        SELECT L187.OBJ_ID
        FROM LINKS L187
        JOIN LINKS L8 ON L8.OBJ_ID = L187.PARENT_ID AND L8.DATE_DEL IS NULL
        JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
        JOIN LISTVALS LV ON LV.LISTVAL_ID = V49.LISTVAL_ID AND LV.TAG = :V$CLASS_NUMBER
        JOIN VALS V1652 ON V1652.OBJ_ID = L187.OBJ_ID AND V1652.PARAM_ID = 1652 AND V1652.IS_DEL = 0 AND V1652.VAL = :I$CLASS_NAME
        WHERE L187.OBJ_TYPE_ID = 187 AND L187.DATE_DEL IS NULL AND L187.PARENT_TYPE_ID = 8
        INTO :CLASS_ID;

        IF (CLASS_ID IS NULL) THEN
        BEGIN
            SELECT L8.OBJ_ID
            FROM LINKS L8
            JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
            JOIN LISTVALS LV ON LV.LISTVAL_ID = V49.LISTVAL_ID AND LV.TAG = :V$CLASS_NUMBER
            WHERE L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
            INTO :V$STAGE_ID;

            SELECT OBJ_ID FROM OBJECT_ADD(:V$STAGE_ID, 187, NULL, NULL, :I$USER_ID) INTO :CLASS_ID;
            SELECT BLOB_ID FROM VAL_ADD(1652, :CLASS_ID, :I$CLASS_NAME, :I$USER_ID) INTO :V$BLOB_ID;
        END
    END

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CLASSIFY_COURSE_EXPORT (
    I$USER_ID BIGINT = 1)
RETURNS (
    TAG_NAME VARCHAR(255),
    VAL VARCHAR(4000))
AS
declare variable V$LIST_ID bigint;
declare variable V$LISTVAL_ID bigint;
declare variable V$PARENT_ID bigint;
declare variable V$RES_ID bigint;
declare variable LANG_CODE varchar(2);
begin
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :LANG_CODE;

    FOR
        SELECT L.LIST_ID,
               L.RES_ID
        FROM LISTS L

        WHERE L.LIST_ID IN (168,260,258,92,96,281,5424)

        INTO :V$LIST_ID,
             :V$RES_ID
    DO
    BEGIN
        TAG_NAME = 'lists:list::id';
        VAL = V$LIST_ID;
        SUSPEND;

        TAG_NAME = 'lists:list::name';
        SELECT VAL
        FROM RES_GET(:V$RES_ID, :LANG_CODE)
        INTO :VAL;
        SUSPEND;

        FOR
            SELECT L.LISTVAL_ID,
                   L.PARENT_ID,
                   L.RES_ID
            FROM LISTVALS L

            WHERE L.LIST_ID=:V$LIST_ID
            AND L.IS_DEL = 0
            ORDER BY L.SORT_ORDER

            INTO :V$LISTVAL_ID,
                 :V$PARENT_ID,
                 :V$RES_ID
        DO
        BEGIN
            TAG_NAME = 'lists:list:listval::id';
            VAL = V$LISTVAL_ID;
            SUSPEND;
            TAG_NAME = 'lists:list:listval::parent_id';
            VAL = V$PARENT_ID;
            SUSPEND;

            IF (V$LIST_ID = 281) THEN
            BEGIN
                TAG_NAME = 'lists:list:listval::short_name';
                SELECT REPLACE(VAL, '"', '&quot;')
                FROM RES_GET(:V$RES_ID, :LANG_CODE)
                INTO :VAL;
                SUSPEND;

                TAG_NAME = 'lists:list:listval::name';
                SELECT REPLACE(VAL_LONG, '"', '&quot;')
                FROM RES_GET(:V$RES_ID, :LANG_CODE)
                INTO :VAL;
                SUSPEND;
            END
            ELSE
            BEGIN
                TAG_NAME = 'lists:list:listval::name';
                SELECT REPLACE(VAL, '"', '&quot;')
                FROM RES_GET(:V$RES_ID, :LANG_CODE)
                INTO :VAL;
                SUSPEND;
            END
        END
    END
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CLASS_EDU_DO_ATTR (
    I$CLASS_ID BIGINT,
    I$ATTR VARCHAR(40),
    I$PERSONS VARCHAR(1000),
    I$VALUE VARCHAR(400),
    I$ALL SMALLINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    STUB INTEGER)
AS
declare variable P integer;
declare variable V$OBJ_ID bigint;
declare variable V$MOVE_ID bigint;
declare variable V$GROUP_ID bigint;
declare variable V$D date;
declare variable V$ATTR bigint;
begin

  --
  SELECT FIRST 1 L338.OBJ_ID
  FROM LINKS L2
  LEFT JOIN LINKS L338 ON L338.PARENT_ID = L2.OBJ_ID AND L338.OBJ_TYPE_ID = 338 AND L338.DATE_DEL IS NULL
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$GROUP_ID;

  WHILE(CHAR_LENGTH(I$PERSONS) > 0) DO
  BEGIN

    P = POSITION(',' IN I$PERSONS);
    IF(P <= 0) THEN P = CHAR_LENGTH(I$PERSONS) + 1;
    V$OBJ_ID = SUBSTRING(I$PERSONS FROM 1 FOR P - 1);
    I$PERSONS = SUBSTRING(I$PERSONS FROM P + 1);

    IF(NOT EXISTS(SELECT 1 FROM LINKS L10 WHERE L10.PARENT_ID = :I$CLASS_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL AND L10.OBJ_ID = :V$OBJ_ID)) THEN
    BEGIN
      EXCEPTION DATA_ERROR 'Персона не найдена в учебном коллективе';
    END

    V$MOVE_ID = NULL;
    V$D = NULL;

    IF(I$ATTR = 'apply') THEN
    BEGIN
      -- Принять на дистанционное обучение. Если уже на нем - дату не трогаем
      SELECT FIRST 1 M.OBJ_ID
      FROM PERSON_MOVEMENTS M
      JOIN OBJECTS OBJ ON OBJ.OBJ_ID = M.GROUP_ID AND OBJ.TYPE_ID = 338
      WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :V$OBJ_ID AND M.DATE_OUT IS NULL
      INTO :V$MOVE_ID;

      -- Если дата окончания ранее закрытого дистанционного меньше новой - ругаемся
      SELECT MAX(M.DATE_OUT)
      FROM PERSON_MOVEMENTS M
      JOIN OBJECTS OBJ ON OBJ.OBJ_ID = M.GROUP_ID AND OBJ.TYPE_ID = 338
      WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :V$OBJ_ID AND M.DATE_OUT IS NULL
      INTO :V$D;

      IF(V$D > I$VALUE) THEN EXCEPTION DATA_ERROR 'Дата окончания предыдущего периода дистанционного обучения позднее указанной даты';

      IF(V$MOVE_ID IS NULL) THEN
      BEGIN
        INSERT INTO PERSON_MOVEMENTS
        (PERSON_ID, GROUP_ID, DATE_IN)
        VALUES (:V$OBJ_ID, :V$GROUP_ID, :I$VALUE);
      END

      SELECT BLOB_ID FROM VAL_ADD(2992, :V$OBJ_ID, 2) INTO :V$MOVE_ID;
    END
    ELSE IF(I$ATTR = 'revert') THEN
    BEGIN
      -- Возврат с дистанционного обучения. Если мы не на нем - ничего не делаем
      SELECT FIRST 1 M.OBJ_ID, M.DATE_IN
      FROM PERSON_MOVEMENTS M
      JOIN OBJECTS OBJ ON OBJ.OBJ_ID = M.GROUP_ID AND OBJ.TYPE_ID = 338
      WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :V$OBJ_ID AND M.DATE_OUT IS NULL
      INTO :V$MOVE_ID, :V$D;

      IF(V$D > I$VALUE) THEN EXCEPTION DATA_ERROR 'Дата начала дистанционного обучения позднее указанной даты окончания';

      IF(V$MOVE_ID IS NOT NULL) THEN
      BEGIN
        UPDATE PERSON_MOVEMENTS SET DATE_OUT = :I$VALUE WHERE OBJ_ID = :V$MOVE_ID;
      END

      SELECT BLOB_ID FROM VAL_ADD(2992, :V$OBJ_ID, 3) INTO :V$MOVE_ID;
    END
    ELSE IF(I$ATTR = 'computer' OR I$ATTR = 'inet') THEN
    BEGIN
      -- Переключение флага
      IF(I$ATTR = 'computer') THEN V$ATTR = 2993;
      IF(I$ATTR = 'inet') THEN V$ATTR = 2994;

      -- Если ученик не на дистанционном - ставить флаг нельзя
      IF(I$ATTR = '1') THEN
      BEGIN
        IF(NOT EXISTS(
          SELECT 1
          FROM PERSON_MOVEMENTS M
          JOIN OBJECTS OBJ ON OBJ.OBJ_ID = M.GROUP_ID AND OBJ.TYPE_ID = 338
          WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :V$OBJ_ID AND M.DATE_OUT IS NULL
        ))
        THEN EXCEPTION DATA_ERROR 'Нельзя устанавливать потребность в компьютере или интернете вне режима дистанционного обучения';
      END

      SELECT BLOB_ID FROM VAL_ADD(:V$ATTR, :V$OBJ_ID, IIF(:I$VALUE = '1', 2, 3)) INTO :V$MOVE_ID;
    END
    ELSE IF(I$ATTR = 'date_computer' OR I$ATTR = 'date_inet' OR I$ATTR = 'serial') THEN
    BEGIN
      -- Переключение флага
      IF(I$ATTR = 'date_computer') THEN V$ATTR = 2995;
      IF(I$ATTR = 'date_inet') THEN V$ATTR = 2996;
      IF(I$ATTR = 'serial') THEN V$ATTR = 2997;

      SELECT BLOB_ID FROM VAL_ADD(:V$ATTR, :V$OBJ_ID, :I$VALUE) INTO :V$MOVE_ID;
    END
    ELSE IF(I$ATTR = 'rmperiod') THEN
    BEGIN
      -- Удаление периода ДО в конкретной персоне. id периода передаем в I$VALUE
      SELECT FIRST 1 M.OBJ_ID
      FROM PERSON_MOVEMENTS M
      JOIN OBJECTS OBJ ON OBJ.OBJ_ID = M.GROUP_ID AND OBJ.TYPE_ID = 338
      WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :V$OBJ_ID AND M.OBJ_ID = :I$VALUE
      INTO :V$MOVE_ID;

      IF(V$MOVE_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Период ДО не найден';

      IF(EXISTS(
        SELECT 1
        FROM PERSON_MOVEMENTS M
        JOIN OBJECTS OBJ ON OBJ.OBJ_ID = M.GROUP_ID AND OBJ.TYPE_ID = 338
        WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :V$OBJ_ID AND M.OBJ_ID > :I$VALUE
      ))
      THEN EXCEPTION DATA_ERROR 'Нельзя удалять период ДО в середине';

      UPDATE PERSON_MOVEMENTS SET DATE_DEL = CURRENT_TIMESTAMP WHERE OBJ_ID = :V$MOVE_ID;

      SELECT BLOB_ID FROM VAL_ADD(2992, :V$OBJ_ID, 3) INTO :V$MOVE_ID;
    END
    ELSE IF(I$ATTR = 'cancel') THEN
    BEGIN
      -- Отменить окончание последнего закрытого периода ДО
      -- Если последний период открыт - ничего не делаем
      SELECT FIRST 1 M.OBJ_ID, M.DATE_OUT
      FROM PERSON_MOVEMENTS M
      JOIN OBJECTS OBJ ON OBJ.OBJ_ID = M.GROUP_ID AND OBJ.TYPE_ID = 338
      WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :V$OBJ_ID
      ORDER BY M.DATE_IN DESC
      INTO :V$MOVE_ID, :V$D;

      IF(V$MOVE_ID IS NOT NULL AND V$D IS NOT NULL) THEN
      BEGIN
        UPDATE PERSON_MOVEMENTS
        SET DATE_OUT = NULL
        WHERE OBJ_ID = :V$MOVE_ID;

        SELECT BLOB_ID FROM VAL_ADD(2992, :V$OBJ_ID, 2) INTO :V$MOVE_ID;
      END
    END
    ELSE IF(I$ATTR = 'undo') THEN
    BEGIN
      -- Отменить последнюю открытую запись ДО
      SELECT FIRST 1 M.OBJ_ID
      FROM PERSON_MOVEMENTS M
      JOIN OBJECTS OBJ ON OBJ.OBJ_ID = M.GROUP_ID AND OBJ.TYPE_ID = 338
      WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :V$OBJ_ID AND M.DATE_OUT IS NULL
      ORDER BY M.DATE_IN DESC
      INTO :V$MOVE_ID;

      IF(V$MOVE_ID IS NOT NULL) THEN
      BEGIN
        UPDATE PERSON_MOVEMENTS
        SET DATE_DEL = CURRENT_TIMESTAMP
        WHERE OBJ_ID = :V$MOVE_ID;
      END

      SELECT BLOB_ID FROM VAL_ADD(2992, :V$OBJ_ID, 3) INTO :V$MOVE_ID;
    END
    ELSE IF(I$ATTR = 'setperiod') THEN
    BEGIN
      -- Изменение одного периода в конкретной персоне

    END
  END


  IF(0 = 1) THEN SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CLASS_EDU_DO_DATA (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(1000))
AS
declare variable V$OBJ_ID bigint;
declare variable V$CAPTION varchar(1000);
declare variable V$C1 smallint;
declare variable V$C2 smallint;
declare variable V$D1 date;
declare variable V$D2 date;
declare variable V$S varchar(1000);
declare variable V$MOVE_ID bigint;
begin

  -- Флаг ДО по классу в целом
  TAG_NAME = 'class_do';
  VAL = 0;
  SELECT IIF(V3053.LISTVAL_ID = 2, 1, 0)
  FROM VALL V3053
  WHERE V3053.OBJ_ID = :I$OBJ_ID AND V3053.PARAM_ID = 3053 AND V3053.IS_DEL = 0
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'persons::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L10.OBJ_ID, C.CAPTION, IIF(V2993.LISTVAL_ID = 2, 1, 0), IIF(V2994.LISTVAL_ID = 2, 1, 0), V2995.VAL, V2996.VAL, V2997.VAL
    FROM LINKS L10
    LEFT JOIN OBJECT_CAPTION_GET(L10.OBJ_ID, 23) C ON 1 = 1
    LEFT JOIN VALL V2993 ON V2993.OBJ_ID = L10.OBJ_ID AND V2993.PARAM_ID = 2993 AND V2993.IS_DEL = 0
    LEFT JOIN VALL V2994 ON V2994.OBJ_ID = L10.OBJ_ID AND V2994.PARAM_ID = 2994 AND V2994.IS_DEL = 0
    LEFT JOIN VALD V2995 ON V2995.OBJ_ID = L10.OBJ_ID AND V2995.PARAM_ID = 2995 AND V2995.IS_DEL = 0
    LEFT JOIN VALD V2996 ON V2996.OBJ_ID = L10.OBJ_ID AND V2996.PARAM_ID = 2996 AND V2996.IS_DEL = 0
    LEFT JOIN VALS V2997 ON V2997.OBJ_ID = L10.OBJ_ID AND V2997.PARAM_ID = 2997 AND V2997.IS_DEL = 0
    WHERE L10.PARENT_ID = :I$OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    ORDER BY 2
    INTO :V$OBJ_ID, :V$CAPTION, :V$C1, :V$C2, :V$D1, :V$D2, :V$S
  DO
  BEGIN
    TAG_NAME = 'persons:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'persons:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'persons:r:name';
    VAL = V$CAPTION;
    SUSPEND;
    TAG_NAME = 'persons:r:needs_computer';
    VAL = V$C1;
    SUSPEND;
    TAG_NAME = 'persons:r:needs_inet';
    VAL = V$C2;
    SUSPEND;
    TAG_NAME = 'persons:r:date_computer';
    VAL = (SELECT VAL FROM DATE2ISO(:V$D1));
    SUSPEND;
    TAG_NAME = 'persons:r:date_inet';
    VAL = (SELECT VAL FROM DATE2ISO(:V$D2));
    SUSPEND;
    TAG_NAME = 'persons:r:serial';
    VAL = V$S;
    SUSPEND;

    TAG_NAME = 'persons:r:do_items::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT M.OBJ_ID, M.DATE_IN, M.DATE_OUT
      FROM PERSON_MOVEMENTS M
      JOIN OBJECTS OBJ ON OBJ.OBJ_ID = M.GROUP_ID AND OBJ.TYPE_ID = 338
      WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :V$OBJ_ID
      ORDER BY M.DATE_IN
      INTO :V$MOVE_ID, :V$D1, :V$D2
    DO
    BEGIN
      TAG_NAME = 'persons:r:do_items:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'persons:r:do_items:r:id';
      VAL = V$MOVE_ID;
      SUSPEND;
      TAG_NAME = 'persons:r:do_items:r:date_from';
      VAL = (SELECT VAL FROM DATE2ISO(:V$D1));
      SUSPEND;
      TAG_NAME = 'persons:r:do_items:r:date_to';
      VAL = (SELECT VAL FROM DATE2ISO(:V$D2));
      SUSPEND;
    END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CLASS_EDU_DO_MOVEMENTS (
    I$CLASS_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    STUDENT_ID BIGINT,
    STUDENT_NAME VARCHAR(1000),
    MOVE_PERIODS VARCHAR(1000),
    MOVE_IDS VARCHAR(1000),
    NEED_COMPUTER SMALLINT,
    NEED_INET SMALLINT,
    DATE_COMPUTER DATE,
    DATE_INET DATE,
    COMPUTER_SERIAL VARCHAR(1000))
AS
declare variable V$MOVE_ID bigint;
declare variable V$DATE_FROM date;
declare variable V$DATE_TO date;
begin

  FOR
      SELECT L10.OBJ_ID, V55.VAL || ' ' || V56.VAL, IIF(V2993.LISTVAL_ID = 2, 1, 0), IIF(V2994.LISTVAL_ID = 2, 1, 0), V2995.VAL, V2996.VAL
      FROM LINKS L10
      JOIN VALS V55 ON V55.OBJ_ID = L10.OBJ_ID AND V55.PARAM_ID = 55 AND V55.IS_DEL = 0
      JOIN VALS V56 ON V56.OBJ_ID = L10.OBJ_ID AND V56.PARAM_ID = 56 AND V56.IS_DEL = 0
      LEFT JOIN VALL V2993 ON V2993.OBJ_ID = L10.OBJ_ID AND V2993.PARAM_ID = 2993 AND V2993.IS_DEL = 0
      LEFT JOIN VALL V2994 ON V2994.OBJ_ID = L10.OBJ_ID AND V2994.PARAM_ID = 2994 AND V2994.IS_DEL = 0
      LEFT JOIN VALD V2995 ON V2995.OBJ_ID = L10.OBJ_ID AND V2995.PARAM_ID = 2995 AND V2995.IS_DEL = 0
      LEFT JOIN VALD V2996 ON V2996.OBJ_ID = L10.OBJ_ID AND V2996.PARAM_ID = 2996 AND V2996.IS_DEL = 0
      WHERE L10.PARENT_ID = :I$CLASS_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      ORDER BY 2
      INTO :STUDENT_ID, :STUDENT_NAME, :NEED_COMPUTER, :NEED_INET, :DATE_COMPUTER, :DATE_INET
  DO
  BEGIN
      MOVE_IDS = '';
      MOVE_PERIODS = '';

      FOR
        SELECT M.OBJ_ID, M.DATE_IN, M.DATE_OUT
        FROM PERSON_MOVEMENTS M
        JOIN OBJECTS OBJ ON OBJ.OBJ_ID = M.GROUP_ID AND OBJ.TYPE_ID = 338
        WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :STUDENT_ID
        ORDER BY M.ORDER_DATE_IN DESC
        INTO :V$MOVE_ID, :V$DATE_FROM, :V$DATE_TO
      DO
      BEGIN
        MOVE_IDS = MOVE_IDS || ',' || V$MOVE_ID;
        MOVE_PERIODS = MOVE_PERIODS || ', с ';
        MOVE_PERIODS = MOVE_PERIODS || (SELECT RESULT FROM DATE2STR(:V$DATE_FROM));
        IF(V$DATE_TO IS NOT NULL) THEN MOVE_PERIODS = MOVE_PERIODS || ' по ' || (SELECT RESULT FROM DATE2STR(:V$DATE_TO));
      END

      COMPUTER_SERIAL = NULL;
      SELECT FIRST 1 V2997.VAL
      FROM VALS V2997
      WHERE V2997.OBJ_ID = :STUDENT_ID AND V2997.PARAM_ID = 2997 AND V2997.IS_DEL = 0
      INTO :COMPUTER_SERIAL;

      MOVE_IDS = SUBSTRING(MOVE_IDS FROM 2);
      MOVE_PERIODS = SUBSTRING(MOVE_PERIODS FROM 3);

      SUSPEND;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CLASS_EDU_DO_SETMOVE (
    I$CLASS_ID BIGINT,
    I$STUDENT_ID BIGINT,
    I$USER_ID BIGINT,
    I$NEEDS_COMPUTER SMALLINT,
    I$NEEDS_INET SMALLINT,
    I$DATE_COMPUTER DATE,
    I$DATE_INET DATE,
    I$COMPUTER_SERIAL VARCHAR(1000))
RETURNS (
    STUB BIGINT)
AS
declare variable T bigint;
declare variable V$OU_ID bigint;
declare variable V$GROUP_ID bigint;
begin

  IF(I$DATE_COMPUTER > CURRENT_DATE) THEN EXCEPTION DATA_ERROR 'Дата предоставления компьютера не может быть поставлена позднее текущей даты';
  IF(I$DATE_INET > CURRENT_DATE) THEN EXCEPTION DATA_ERROR 'Дата предоставления доступа к интернету не может быть поставлена позднее текущей даты';

  IF(TRIM(I$COMPUTER_SERIAL) = '') THEN I$COMPUTER_SERIAL = NULL;
  IF((I$DATE_COMPUTER IS NOT NULL OR I$COMPUTER_SERIAL IS NOT NULL) AND I$NEEDS_COMPUTER = 0) THEN
    EXCEPTION DATA_ERROR 'Нельзя вносить дату выдачи компьютера или серийный номер, если не указано наличие потребности в нем';
  IF(I$DATE_INET IS NOT NULL AND I$NEEDS_INET = 0) THEN
    EXCEPTION DATA_ERROR 'Нельзя вносить дату предоставления доступа к интернету, если не указано наличие потребности в нем';

  /*IF(I$MOVE_ID IS NOT NULL AND I$DATE_FROM IS NULL AND I$DATE_TO IS NULL) THEN
  BEGIN
      UPDATE PERSON_MOVEMENTS
      SET DATE_DEL = CURRENT_TIMESTAMP
      WHERE OBJ_ID = :I$MOVE_ID;

      SELECT BLOB_ID FROM VAL_ADD(2992, :I$STUDENT_ID, 3) INTO :T;
  END
  ELSE IF(I$MOVE_ID IS NOT NULL AND I$DATE_FROM IS NOT NULL) THEN
  BEGIN
      UPDATE PERSON_MOVEMENTS
      SET DATE_IN = :I$DATE_FROM, DATE_OUT = :I$DATE_TO
      WHERE OBJ_ID = :I$MOVE_ID;

      SELECT BLOB_ID FROM VAL_ADD(2992, :I$STUDENT_ID, IIF(:I$DATE_TO IS NULL, 2, 3)) INTO :T;

      MOVE_ID = I$MOVE_ID;
  END
  ELSE BEGIN
      SELECT FIRST 1 L2.OBJ_ID, L338.OBJ_ID
      FROM LINKS L2
      LEFT JOIN LINKS L338 ON L338.PARENT_ID = L2.OBJ_ID AND L338.OBJ_TYPE_ID = 338 AND L338.DATE_DEL IS NULL
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      INTO :V$OU_ID, :V$GROUP_ID;

      IF(V$OU_ID IS NULL) THEN EXCEPTION DATA_ERROR 'ОУ не идентифицирована';

      -- Создаем виртуальную группу по необходимоси
      IF(V$GROUP_ID IS NULL) THEN
      BEGIN
          SELECT OBJ_ID
          FROM OBJECT_ADD(:V$OU_ID, 338)
          INTO :V$GROUP_ID;
      END

      INSERT INTO PERSON_MOVEMENTS
      (PERSON_ID, GROUP_ID, DATE_IN, DATE_OUT)
      VALUES (:I$STUDENT_ID, :V$GROUP_ID, :I$DATE_FROM, :I$DATE_TO)
      RETURNING OBJ_ID INTO :MOVE_ID;

      SELECT BLOB_ID FROM VAL_ADD(2992, :I$STUDENT_ID, IIF(:I$DATE_TO IS NULL, 2, 3)) INTO :T;
  END */

  SELECT BLOB_ID FROM VAL_ADD(2993, :I$STUDENT_ID, IIF(:I$NEEDS_COMPUTER = 1, 2, 3)) INTO :T;
  SELECT BLOB_ID FROM VAL_ADD(2994, :I$STUDENT_ID, IIF(:I$NEEDS_INET = 1, 2, 3)) INTO :T;
  SELECT BLOB_ID FROM VAL_ADD(2995, :I$STUDENT_ID, :I$DATE_COMPUTER) INTO :T;
  SELECT BLOB_ID FROM VAL_ADD(2996, :I$STUDENT_ID, :I$DATE_INET) INTO :T;
  SELECT BLOB_ID FROM VAL_ADD(2997, :I$STUDENT_ID, :I$COMPUTER_SERIAL) INTO :T;

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CLASS_FILLDET (
    I$CLASS_ID BIGINT NOT NULL,
    I$DT DATE,
    I$IS_BOYS SMALLINT = null)
RETURNS (
    VAL1 VARCHAR(250),
    VAL2 VARCHAR(250))
AS
BEGIN
  FOR
    SELECT (SELECT CAPTION FROM OBJECT_CAPTION_GET(M.PERSON_ID)) VAL1, (SELECT D FROM VAL_GET(M.PERSON_ID, 89)) VAL2
    FROM PERSON_MOVEMENTS M
    LEFT JOIN VALL L88 ON L88.PARAM_ID = 88 AND L88.OBJ_ID = M.PERSON_ID AND L88.IS_DEL = 0
    WHERE M.DATE_DEL IS NULL AND M.GROUP_ID = :I$CLASS_ID AND M.DATE_IN <= :I$DT AND (M.DATE_OUT IS NULL OR M.DATE_OUT > :I$DT)
      AND (:I$IS_BOYS IS NULL OR L88.LISTVAL_ID = 182 + :I$IS_BOYS)
    ORDER BY 1
    INTO :VAL1, :VAL2
  DO
  BEGIN
    SUSPEND;
  END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CLASS_OVZ_RECALC (
    I$OBJ_ID BIGINT,
    I$CLASS_ID BIGINT = NULL)
AS
DECLARE VARIABLE V$HAS SMALLINT;
DECLARE VARIABLE V$CURRENT BIGINT;
DECLARE VARIABLE V$CLASS_ID BIGINT;
DECLARE VARIABLE T INTEGER;
begin

  -- Есть ли хотя бы один ученик с ОВЗ ?
  IF(I$CLASS_ID IS NULL) THEN
  BEGIN
    SELECT FIRST 1 LP9.PARENT_ID, V592.LISTVAL_ID
    FROM LINKS LP9
    LEFT JOIN VALL V592 ON V592.OBJ_ID = LP9.PARENT_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0
    WHERE LP9.OBJ_ID = :I$OBJ_ID AND LP9.PARENT_TYPE_ID = 9 AND LP9.DATE_DEL IS NULL
    INTO :V$CLASS_ID, :V$CURRENT;
  END
  ELSE
  BEGIN
    SELECT V592.LISTVAL_ID
    FROM VALL V592
    WHERE V592.OBJ_ID = :V$CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0
    INTO :V$CURRENT;
  END

  V$HAS = 0;
  SELECT FIRST 1 1
  FROM LINKS L10
  JOIN VALL V207 ON V207.OBJ_ID = L10.OBJ_ID AND V207.PARAM_ID = 207 AND V207.IS_DEL = 0 AND V207.LISTVAL_ID <> 13289
  WHERE L10.PARENT_ID = :V$CLASS_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
  INTO :V$HAS;

  IF(V$HAS = 0 AND V$CURRENT = 13274) THEN
  BEGIN
    SELECT 1 FROM VAL_ADD(592, :V$CLASS_ID, 197) INTO :T;
  END
  ELSE IF(V$HAS = 1 AND V$CURRENT = 197) THEN
  BEGIN
    SELECT 1 FROM VAL_ADD(592, :V$CLASS_ID, 13274) INTO :T;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CLASS_PERIOD_LIST (
    I$OBJ_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    PARENT_ID BIGINT,
    OBJ_CAPTION VARCHAR(1000))
AS
DECLARE VARIABLE V$OU_ID BIGINT;
DECLARE VARIABLE V$YEAR_ID BIGINT;
DECLARE VARIABLE V$YEAR INTEGER;
begin

  SELECT FIRST 1 L2.OBJ_ID, V1236.LISTVAL_ID, LV.COST
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$OU_ID, :V$YEAR_ID, :V$YEAR;

  FOR
    SELECT L151.OBJ_ID, C.CAPTION
    FROM LINKS L481
    JOIN VALL V3390 ON V3390.OBJ_ID = L481.OBJ_ID AND V3390.PARAM_ID = 3390 AND V3390.IS_DEL = 0 AND V3390.LISTVAL_ID NOT IN (11717, 14261) -- не архивный
    JOIN VALL V3389 ON V3389.OBJ_ID = L481.OBJ_ID AND V3389.PARAM_ID = 3389 AND V3389.IS_DEL = 0 AND (V3389.LISTVAL_ID = :V$YEAR_ID OR :V$YEAR_ID IS NULL)
    JOIN LINKS L151 ON L151.PARENT_ID = L481.OBJ_ID AND L151.OBJ_TYPE_ID = 151 AND L151.DATE_DEL IS NULL
    LEFT JOIN OBJECT_CAPTION_GET(L151.OBJ_ID) C ON 1 = 1
    WHERE L481.PARENT_ID = :V$OU_ID AND L481.OBJ_TYPE_ID = 481 AND L481.DATE_DEL IS NULL
    ORDER BY 2
    INTO :OBJ_ID, :OBJ_CAPTION
  DO
  BEGIN
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CLASS_PUPIL_LIST (
    I$CLASS_ID BIGINT,
    I$LEVEL_ID BIGINT)
RETURNS (
    PUPIL_ID BIGINT,
    FIO VARCHAR(1000),
    LASTNAME VARCHAR(1000),
    FIRSTNAME VARCHAR(1000),
    MIDDLENAME VARCHAR(1000))
AS
BEGIN
    FOR
        SELECT L10.OBJ_ID
        FROM LINKS L10

        WHERE L10.PARENT_ID = :I$CLASS_ID
        AND L10.OBJ_TYPE_ID = 10
        AND L10.DATE_DEL IS NULL

        INTO :PUPIL_ID
    DO
    BEGIN
        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:PUPIL_ID, :I$LEVEL_ID)
        INTO :FIO;

        SELECT V
        FROM VAL_GET(:PUPIL_ID, 55)
        INTO :LASTNAME;

        SELECT V
        FROM VAL_GET(:PUPIL_ID, 56)
        INTO :FIRSTNAME;

        SELECT V
        FROM VAL_GET(:PUPIL_ID, 57)
        INTO :MIDDLENAME;

        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CLASS_VIRT_ID (
    OBJ_ID BIGINT,
    OBJ_TYPE_ID BIGINT)
RETURNS (
    VIRT_ID BIGINT,
    DATE_MODIFY TIMESTAMP)
AS
declare variable TMP bigint;
begin

  SELECT VAL, DATE_MODIFY
  FROM VALI
  WHERE OBJ_ID = :OBJ_ID AND PARAM_ID IN (1748, 2866) AND IS_DEL = 0
  INTO :VIRT_ID, :DATE_MODIFY;

  IF(VIRT_ID IS NULL) THEN
  BEGIN

    SELECT MAX(V1748.VAL)
    FROM LINKS L9
    JOIN VALI V1748 ON V1748.OBJ_ID = L9.OBJ_ID AND V1748.PARAM_ID IN (1748, 2866) AND V1748.IS_DEL = 0
    WHERE L9.OBJ_TYPE_ID IN (9, 187) AND L9.PARENT_TYPE_ID = 8
    INTO :VIRT_ID;

    -- Если нет ни одного ID, нумерацию начинаем с единицы
    IF(VIRT_ID IS NULL) THEN VIRT_ID = 1; ELSE VIRT_ID = VIRT_ID + 1;

    SELECT BLOB_ID FROM VAL_ADD(IIF(:OBJ_TYPE_ID = 9, 1748, 2866), :OBJ_ID, :VIRT_ID) INTO :TMP;
    DATE_MODIFY = CURRENT_TIMESTAMP;

  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CLEAR_LEEVED_EMPLOYEE_STATUS
AS
declare variable V$OBJ_ID bigint;
declare variable V$BLOB_ID bigint;
BEGIN
    FOR
        SELECT L14.OBJ_ID
        FROM LINKS L14
        JOIN VALL V274 ON V274.OBJ_ID = L14.OBJ_ID AND V274.PARAM_ID = 274 AND V274.IS_DEL = 0
        WHERE L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL AND L14.PARENT_TYPE_ID = 84
        INTO :V$OBJ_ID
    DO
    BEGIN
        UPDATE VALL
        SET IS_DEL = 1, DATE_MODIFY = CURRENT_TIMESTAMP
        WHERE OBJ_ID = :V$OBJ_ID AND PARAM_ID = 274 AND IS_DEL = 0;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CLEAR_PPE_ROOMS (
    I$SCHOOL_ID BIGINT = null,
    I$FORCE_CLEAR SMALLINT = 0)
AS
declare variable V$SCHOOL_ID bigint;
declare variable V$ROOM_ID bigint;
declare variable V$DEL_COUNT bigint;
BEGIN

    IF ((I$SCHOOL_ID IS NULL) OR (I$SCHOOL_ID = 0)) THEN
    BEGIN
        SELECT FIRST 1 L.OBJ_ID
        FROM LINKS L
        WHERE L.PARENT_ID IS NULL AND L.OBJ_TYPE_ID = 2 AND L.DATE_DEL IS NULL INTO :V$SCHOOL_ID;
    END
    ELSE
    BEGIN
        V$SCHOOL_ID = I$SCHOOL_ID;
    END
    IF (V$SCHOOL_ID IS NULL) THEN EXIT;

    IF (I$FORCE_CLEAR = 1) THEN
    BEGIN
        UPDATE VALI SET IS_DEL = 1 WHERE PARAM_ID = 1365 AND OBJ_ID = :V$SCHOOL_ID;
    END
    IF (EXISTS(SELECT FIRST 1 1 FROM VALI WHERE PARAM_ID = 1365 AND OBJ_ID = :V$SCHOOL_ID AND IS_DEL = 0 AND VAL > 0)) THEN EXIT;

    FOR
        SELECT L61.OBJ_ID
        FROM LINKS L73
        JOIN LINKS L16 ON L16.PARENT_ID = L73.OBJ_ID AND L16.OBJ_TYPE_ID = 16 AND L16.DATE_DEL IS NULL
        JOIN LINKS L61 ON L61.PARENT_ID = L16.OBJ_ID AND L61.OBJ_TYPE_ID = 61 AND L61.DATE_DEL IS NULL
        JOIN VALS RN ON RN.OBJ_ID = L61.OBJ_ID AND RN.PARAM_ID = 1403 AND RN.IS_DEL = 0 AND RN.VAL IS NOT NULL
        WHERE L73.OBJ_TYPE_ID = 73 AND L73.PARENT_ID = :V$SCHOOL_ID AND L73.DATE_DEL IS NULL
        INTO :V$ROOM_ID
    DO
    BEGIN
        SELECT DEL_COUNT FROM GIA_ROOM_DEL(:V$ROOM_ID) INTO :V$DEL_COUNT;
    END

    SELECT OLD_ROOM_COUNT FROM GIA_CODES_SET(:V$SCHOOL_ID, 0, NULL) INTO :V$DEL_COUNT;

END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE COLLEGE_DISCIPLINES_LIST RETURNS (
    OBJ_ID BIGINT,
    OBJ_CAPTION VARCHAR(1000),
    SORT_ORDER DOUBLE PRECISION)
AS
declare variable V$DISCIPLINES_ID bigint;
BEGIN
    FOR
        SELECT L193.OBJ_ID
        FROM LINKS L193

        WHERE L193.OBJ_TYPE_ID = 193
        AND L193.DATE_DEL IS NULL

        INTO :V$DISCIPLINES_ID
    DO
    BEGIN
        FOR
            SELECT DISTINCT
                   O.OBJ_ID
            FROM OBJECT_CHILDREN_GET_DEEP(:V$DISCIPLINES_ID, 197, 2) O
            INTO :OBJ_ID
        DO
        BEGIN
            SELECT CAPTION, SORT_ORDER
            FROM OBJECT_CAPTION_GET(:OBJ_ID)
            INTO :OBJ_CAPTION, :SORT_ORDER;
    
            IF (OBJ_CAPTION <> '<  ...  >') THEN SUSPEND;
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE COLLEGE_GRADE_CURRICULUM_LIST (
    I$GRADE_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    CURRICULUM_ID BIGINT,
    CURRICULUM_CAPTION VARCHAR(4000))
AS
BEGIN
    FOR
        SELECT LP50.PARENT_ID
        FROM LINKS LP54
        JOIN LINKS LP50 ON LP50.OBJ_ID = LP54.PARENT_ID AND LP50.PARENT_TYPE_ID IN (50, 245) AND LP50.DATE_DEL IS NULL
        WHERE LP54.OBJ_ID = :I$GRADE_ID AND LP54.PARENT_TYPE_ID IN (54, 247) AND LP54.DATE_DEL IS NULL
        INTO :CURRICULUM_ID
    DO
    BEGIN
        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:CURRICULUM_ID, NULL, NULL, :I$USER_ID)
        INTO :CURRICULUM_CAPTION;

        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE COLLEGE_GRADE_DISCIPLINES_LIST (
    I$GRADE_ID BIGINT,
    I$CURRICULUM_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    STAGE_ID BIGINT,
    STAGE_LOADING_ID BIGINT,
    DISCIPLINE_LINK_ID BIGINT,
    DISCIPLINE_ID BIGINT,
    DISCIPLINE_CAPTION VARCHAR(4000),
    STAGE_LOADING_PERIOD INTEGER,
    STAGE_LOADING_LIMIT INTEGER,
    VAL INTEGER,
    SORT_ORDER DOUBLE PRECISION,
    CURRICULUM_ID BIGINT)
AS
declare variable STAGE_LOADING_TYPE_ID bigint;
declare variable V$STAGE_TYPE_ID bigint;
declare variable V$PRO_EDU_FL smallint;
BEGIN
    FOR
        SELECT LP54.PARENT_ID, V381.LISTVAL_ID, IIF(LP54.PARENT_TYPE_ID = 247, 1, 0), L50_54.PARENT_ID
        FROM LINKS LP54
        JOIN LINKS L50_54 ON L50_54.OBJ_ID = LP54.PARENT_ID AND L50_54.PARENT_ID = COALESCE(:I$CURRICULUM_ID, L50_54.PARENT_ID) AND L50_54.DATE_DEL IS NULL
        JOIN VALL V381 ON V381.OBJ_ID = LP54.PARENT_ID AND V381.PARAM_ID IN (381, 2130) AND V381.IS_DEL = 0
        WHERE LP54.OBJ_ID = :I$GRADE_ID AND LP54.PARENT_TYPE_ID IN (54, 247) AND LP54.DATE_DEL IS NULL
        INTO :STAGE_ID, :V$STAGE_TYPE_ID, :V$PRO_EDU_FL, :CURRICULUM_ID
    DO
    BEGIN
        FOR
            SELECT V1766.VAL, DT.OBJ_ID, L205.OBJ_ID, V1769.LISTVAL_ID, IIF(:V$PRO_EDU_FL = 0, COALESCE(V1777.VAL, 0) + COALESCE(V1779.VAL, 0), COALESCE(V1773.VAL, 0)), V1770.VAL, V1771.VAL
            FROM DISCIPLINE_TREE(:CURRICULUM_ID) DT
            JOIN VALR V1766 ON V1766.OBJ_ID = DT.OBJ_ID AND V1766.PARAM_ID = 1766 AND V1766.IS_DEL = 0
            JOIN LINKS L203 ON L203.PARENT_ID = DT.OBJ_ID AND L203.OBJ_TYPE_ID = 203 AND L203.DATE_DEL IS NULL
            JOIN VALI V1770 ON V1770.OBJ_ID = L203.OBJ_ID AND V1770.PARAM_ID = 1770 AND V1770.IS_DEL = 0
            JOIN VALI V1771 ON V1771.OBJ_ID = L203.OBJ_ID AND V1771.PARAM_ID = 1771 AND V1771.IS_DEL = 0
            JOIN VALL V1769 ON V1769.OBJ_ID = L203.OBJ_ID AND V1769.PARAM_ID = 1769 AND V1769.IS_DEL = 0
            LEFT JOIN VALI V1773 ON V1773.OBJ_ID = L203.OBJ_ID AND V1773.PARAM_ID = 1773 AND V1773.IS_DEL = 0
            JOIN LINKS L205 ON L205.PARENT_ID = L203.OBJ_ID AND L205.OBJ_TYPE_ID = 205 AND L205.DATE_DEL IS NULL
            JOIN VALL V1776 ON V1776.OBJ_ID = L205.OBJ_ID AND V1776.PARAM_ID = 1776 AND V1776.IS_DEL = 0 AND V1776.LISTVAL_ID = :V$STAGE_TYPE_ID
            LEFT JOIN VALI V1777 ON V1777.OBJ_ID = L205.OBJ_ID AND V1777.PARAM_ID = 1777 AND V1777.IS_DEL = 0
            LEFT JOIN VALI V1779 ON V1779.OBJ_ID = L205.OBJ_ID AND V1779.PARAM_ID = 1779 AND V1779.IS_DEL = 0
            WHERE DT.TYPE_ID = 201 AND ((:V$PRO_EDU_FL = 0 AND COALESCE(V1777.VAL, 0) + COALESCE(V1779.VAL, 0) > 0) OR (:V$PRO_EDU_FL = 1 AND COALESCE(V1773.VAL, 0) > 0))
            INTO :DISCIPLINE_ID, :DISCIPLINE_LINK_ID, :STAGE_LOADING_ID, :STAGE_LOADING_TYPE_ID, :VAL, :STAGE_LOADING_PERIOD, :STAGE_LOADING_LIMIT
        DO
        BEGIN
            SELECT CAPTION, SORT_ORDER
            FROM OBJECT_CAPTION_GET(:DISCIPLINE_LINK_ID, NULL, NULL, :I$USER_ID)
            INTO :DISCIPLINE_CAPTION, :SORT_ORDER;

            SUSPEND;
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE COLLEGE_GRADE_GROUPS_LIST (
    I$GRADE_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    GROUP_ID BIGINT,
    GROUP_DISCIPLINE_ID BIGINT,
    GROUP_CAPTION VARCHAR(4000),
    DISCIPLINE_ID BIGINT,
    DISCIPLINE_CAPTION VARCHAR(4000),
    SUBGROUP_ID BIGINT,
    SUBGROUP_CAPTION VARCHAR(4000))
AS
declare variable V$COUNT_ID integer;
BEGIN
    GROUP_ID = I$GRADE_ID;
    SUBGROUP_ID = I$GRADE_ID;

    SELECT CAPTION FROM OBJECT_CAPTION_GET(:GROUP_ID, NULL, NULL, :I$USER_ID) INTO :GROUP_CAPTION;

    SUBGROUP_CAPTION = GROUP_CAPTION;
    DISCIPLINE_ID = NULL;
    SUSPEND;

    FOR
        SELECT L47.OBJ_ID, L48.OBJ_ID
        FROM LINKS L47
        LEFT JOIN LINKS L48 ON L48.PARENT_ID = L47.OBJ_ID AND L48.OBJ_TYPE_ID = 48 AND L48.DATE_DEL IS NULL
        WHERE L47.PARENT_ID = :I$GRADE_ID AND L47.OBJ_TYPE_ID = 47 AND L47.DATE_DEL IS NULL
        INTO :GROUP_ID, :SUBGROUP_ID
    DO
    BEGIN
        SELECT I FROM VAL_GET(:GROUP_ID, 2105, 0, :I$USER_ID) INTO :GROUP_DISCIPLINE_ID;

        SELECT CAPTION FROM OBJECT_CAPTION_GET(:GROUP_ID, NULL, NULL, :I$USER_ID) INTO :GROUP_CAPTION;

        IF (SUBGROUP_ID IS NOT NULL) THEN
        BEGIN
            SELECT CAPTION FROM OBJECT_CAPTION_GET(:SUBGROUP_ID, NULL, NULL, :I$USER_ID) INTO :SUBGROUP_CAPTION;

            V$COUNT_ID = 0;
            FOR
                SELECT L197.OBJ_ID
                FROM LINKS L197
                WHERE L197.PARENT_ID = :SUBGROUP_ID AND L197.OBJ_TYPE_ID = 197 AND L197.DATE_DEL IS NULL
                INTO :DISCIPLINE_ID
            DO
            BEGIN
                V$COUNT_ID = V$COUNT_ID + 1;
                SELECT CAPTION FROM OBJECT_CAPTION_GET(:DISCIPLINE_ID, NULL, NULL, :I$USER_ID) INTO :DISCIPLINE_CAPTION;
                SUSPEND;
            END
            IF (V$COUNT_ID = 0) THEN
            BEGIN
                DISCIPLINE_ID = GROUP_DISCIPLINE_ID;
                SELECT CAPTION FROM OBJECT_CAPTION_GET(:DISCIPLINE_ID, NULL, NULL, :I$USER_ID) INTO :DISCIPLINE_CAPTION;
                SUSPEND;
            END
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE COLLEGE_GRADE_LOADING_ADD (
    I$LOADING_ID BIGINT,
    I$STAGE_LOADING_ID BIGINT,
    I$DISCIPLINE_LINK_ID BIGINT,
    I$SUBGROUP_ID BIGINT,
    I$TEACHER_ID BIGINT)
RETURNS (
    LOADING_ID BIGINT)
AS
declare variable V$OBJ_ID bigint;
declare variable V$SUBGROUP_ID bigint;
declare variable V$SUBGROUP_TYPE_ID bigint;
declare variable V$CLASS_ID bigint;
declare variable V$DIVISION_ID bigint;
declare variable V$CLASS_DISCIPLINE_ID bigint;
declare variable V$DEL_COUNT bigint;
declare variable V$GROUP_SUBJECT_ID bigint;
BEGIN
    IF (I$LOADING_ID IS NULL) THEN
    BEGIN
        SELECT OBJ_ID
        FROM OBJECT_ADD(:I$SUBGROUP_ID, 58)
        INTO :LOADING_ID;

        SELECT OBJ_ID
        FROM OBJECT_ADD_LINK(:I$DISCIPLINE_LINK_ID, :LOADING_ID, 58)
        INTO :LOADING_ID;

        SELECT OBJ_ID
        FROM OBJECT_ADD_LINK(:I$STAGE_LOADING_ID, :LOADING_ID, 58)
        INTO :LOADING_ID;
    END
    ELSE
    BEGIN
        LOADING_ID = I$LOADING_ID;

        UPDATE LINKS L
        SET L.DATE_DEL = CURRENT_TIMESTAMP
        WHERE ((:I$TEACHER_ID IS NULL) OR (L.PARENT_ID <> :I$TEACHER_ID))
        AND L.PARENT_TYPE_ID = 14
        AND L.OBJ_ID = :LOADING_ID
        AND L.DATE_DEL IS NULL;

        UPDATE LINKS L
        SET L.PARENT_ID = :I$STAGE_LOADING_ID
        WHERE L.PARENT_TYPE_ID = 205
        AND L.OBJ_ID = :LOADING_ID
        AND L.DATE_DEL IS NULL;
    END

    IF (I$TEACHER_ID IS NOT NULL) THEN
    BEGIN
        SELECT OBJ_ID
        FROM OBJECT_ADD_LINK(:I$TEACHER_ID, :LOADING_ID, 58)
        INTO :LOADING_ID;
    END

    /* EUGENE: OTHER LOADING DELETING */
    SELECT O.TYPE_ID
    FROM OBJECTS O
    WHERE O.OBJ_ID = :I$SUBGROUP_ID
    INTO :V$SUBGROUP_TYPE_ID;

    IF (V$SUBGROUP_TYPE_ID = 48) THEN
    BEGIN
        V$DIVISION_ID = NULL;
        V$CLASS_DISCIPLINE_ID = NULL;
        V$CLASS_ID = NULL;

        /* FIND DIVISION*/
        SELECT L.PARENT_ID
        FROM LINKS L
        WHERE L.PARENT_TYPE_ID = 47
        AND L.OBJ_ID = :I$SUBGROUP_ID
        AND L.DATE_DEL IS NULL
        INTO :V$DIVISION_ID;

        /* FIND DIVISION SUBJECT*/
        SELECT V.VAL

        FROM VALR V

        WHERE V.PARAM_ID = 2105
        AND V.OBJ_ID = :V$DIVISION_ID
        AND V.IS_DEL = 0

        INTO :V$CLASS_DISCIPLINE_ID;

        /* FIND CLASS*/
        SELECT L.PARENT_ID

        FROM LINKS L

        WHERE L.PARENT_TYPE_ID = 9
        AND L.OBJ_ID = :V$DIVISION_ID
        AND L.DATE_DEL IS NULL

        INTO :V$CLASS_ID;

        FOR
            SELECT L58.OBJ_ID

            FROM LINKS L58

            JOIN LINKS L51
            ON L51.OBJ_ID = L58.OBJ_ID
            AND L51.PARENT_ID = :V$CLASS_DISCIPLINE_ID
            AND L51.DATE_DEL IS NULL

            JOIN LINKS LP205
            ON LP205.OBJ_ID = L58.OBJ_ID
            AND LP205.PARENT_ID = :I$STAGE_LOADING_ID
            AND LP205.DATE_DEL IS NULL

            WHERE L58.OBJ_TYPE_ID = 58
            AND L58.PARENT_ID = :V$CLASS_ID
            AND L58.DATE_DEL IS NULL

            INTO :V$OBJ_ID
        DO
        BEGIN
            SELECT DEL_COUNT
            FROM OBJECT_DEL(:V$CLASS_ID, :V$OBJ_ID)
            INTO :V$DEL_COUNT;
        END
    END
    ELSE
    BEGIN
        V$CLASS_DISCIPLINE_ID = I$DISCIPLINE_LINK_ID;
    END

    FOR
        SELECT L58.OBJ_ID

        FROM LINKS L58

        JOIN LINKS L51
        ON L51.OBJ_ID = L58.OBJ_ID
        AND L51.PARENT_ID IN (:I$DISCIPLINE_LINK_ID, :V$CLASS_DISCIPLINE_ID)
        AND L51.DATE_DEL IS NULL

        JOIN LINKS LP205
        ON LP205.OBJ_ID = L58.OBJ_ID
        AND LP205.PARENT_ID = :I$STAGE_LOADING_ID
        AND LP205.DATE_DEL IS NULL

        WHERE L58.OBJ_TYPE_ID = 58
        AND L58.PARENT_ID = :I$SUBGROUP_ID
        AND L58.OBJ_ID <> :LOADING_ID
        AND L58.DATE_DEL IS NULL

        INTO :V$OBJ_ID
    DO
    BEGIN
        SELECT DEL_COUNT
        FROM OBJECT_DEL(:I$SUBGROUP_ID, :V$OBJ_ID)
        INTO :V$DEL_COUNT;
    END

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE COLLEGE_GRADE_LOADING_LIST (
    I$GRADE_ID BIGINT,
    I$CURRICULUM_ID BIGINT)
RETURNS (
    LOADING_ID BIGINT,
    STAGE_LOADING_ID BIGINT,
    DISCIPLINE_ID BIGINT,
    DISCIPLINE_LINK_ID BIGINT,
    CURRICULUM_DISCIPLINE_LINK_ID BIGINT,
    SUBGROUP_ID BIGINT,
    TEACHER_ID BIGINT,
    TEACHER_CAPTION VARCHAR(4000))
AS
declare variable V$STAGE_TYPE_ID bigint;
BEGIN

    -- Номер этапа обучения
    SELECT V381.LISTVAL_ID
    FROM LINKS LP54
    JOIN VALL V381 ON V381.OBJ_ID = LP54.PARENT_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
    WHERE LP54.OBJ_ID = :I$GRADE_ID AND LP54.PARENT_TYPE_ID = 54 AND LP54.DATE_DEL IS NULL
    INTO :V$STAGE_TYPE_ID;

    FOR
        SELECT V1766.VAL, DT.OBJ_ID, DT.OBJ_ID, L58.OBJ_ID, PGR.PARENT_ID, L205.OBJ_ID, LP14.PARENT_ID
        FROM DISCIPLINE_TREE(:I$CURRICULUM_ID) DT
        JOIN VALR V1766 ON V1766.OBJ_ID = DT.OBJ_ID AND V1766.PARAM_ID = 1766 AND V1766.IS_DEL = 0
        JOIN LINKS L203 ON L203.PARENT_ID = DT.OBJ_ID AND L203.OBJ_TYPE_ID = 203 AND L203.DATE_DEL IS NULL
        -- Распределение обязательной нагрузки по этому этапу
        JOIN LINKS L205 ON L205.PARENT_ID = L203.OBJ_ID AND L205.OBJ_TYPE_ID = 205 AND L205.DATE_DEL IS NULL
        JOIN VALL V1776 ON V1776.OBJ_ID = L205.OBJ_ID AND V1776.PARAM_ID = 1776 AND V1776.IS_DEL = 0 AND V1776.LISTVAL_ID = :V$STAGE_TYPE_ID
        -- Далее сама нагрузка для этого распределения
        -- > предмет
        JOIN LINKS L58 ON L58.PARENT_ID = DT.OBJ_ID AND L58.OBJ_TYPE_ID = 58 AND L58.DATE_DEL IS NULL
        -- > распределение
        JOIN LINKS LP205 ON LP205.OBJ_ID = L58.OBJ_ID AND LP205.PARENT_ID = L205.OBJ_ID AND LP205.DATE_DEL IS NULL
        -- > группа
        JOIN LINKS PGR ON PGR.PARENT_ID = :I$GRADE_ID AND PGR.OBJ_ID = L58.OBJ_ID AND PGR.DATE_DEL IS NULL
        -- Назначенный преподаватель
        LEFT JOIN LINKS LP14 ON LP14.OBJ_ID = L58.OBJ_ID AND LP14.PARENT_TYPE_ID = 14 AND LP14.DATE_DEL IS NULL
        WHERE DT.TYPE_ID = 201
        INTO :DISCIPLINE_ID, :CURRICULUM_DISCIPLINE_LINK_ID, :DISCIPLINE_LINK_ID, :LOADING_ID, :SUBGROUP_ID, :STAGE_LOADING_ID, :TEACHER_ID
    DO
    BEGIN
        TEACHER_CAPTION = NULL;
        IF (TEACHER_ID IS NOT NULL) THEN
        BEGIN
            SELECT CAPTION FROM OBJECT_CAPTION_GET(:TEACHER_ID, NULL) INTO :TEACHER_CAPTION;
        END

        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE COLLEGE_GRADE_TEACHERS_LIST (
    I$GRADE_ID BIGINT,
    I$NOT_ONLY_PEDAGOGS SMALLINT = 0)
RETURNS (
    TEACHER_ID BIGINT,
    TEACHER_CAPTION VARCHAR(4000))
AS
DECLARE VARIABLE V$SCHOOL_ID BIGINT;
BEGIN
    IF (I$GRADE_ID IS NULL) THEN
    BEGIN
        SELECT FIRST 1
               OBJ_ID

        FROM LINKS L

        WHERE L.PARENT_ID IS NULL
        AND L.OBJ_TYPE_ID = 2
        AND L.DATE_DEL IS NULL

        INTO :V$SCHOOL_ID;
    END
    ELSE
    BEGIN
        SELECT FIRST 1
               OBJ_ID

        FROM OBJECT_PARENTS_GET(:I$GRADE_ID, 2)

        INTO :V$SCHOOL_ID;
    END

    FOR
        SELECT DISTINCT
               L14.OBJ_ID
        FROM LINKS L14

        JOIN LINKS L15
        ON L15.PARENT_ID = L14.OBJ_ID
        AND L15.OBJ_TYPE_ID = 15
        AND L15.DATE_DEL IS NULL

        JOIN LINKS L13
        ON L13.OBJ_ID = L15.OBJ_ID
        AND L13.PARENT_TYPE_ID = 13
        AND L13.DATE_DEL IS NULL

        JOIN VALD V73
        ON V73.OBJ_ID = L15.OBJ_ID
        AND V73.PARAM_ID = 73
        AND V73.IS_DEL = 0
        AND V73.VAL <= CURRENT_DATE

        LEFT JOIN VALD V74
        ON V74.OBJ_ID = L15.OBJ_ID
        AND V74.PARAM_ID = 74
        AND V74.IS_DEL = 0
        AND ((V74.VAL IS NULL) OR (V74.VAL >= CURRENT_DATE))

        WHERE L14.PARENT_ID = :V$SCHOOL_ID
        AND L14.OBJ_TYPE_ID = 14
        AND L14.DATE_DEL IS NULL
        AND ((:I$NOT_ONLY_PEDAGOGS = 1) OR ((SELECT SORT_ORDER FROM DO_FUNC(L13.PARENT_ID, 400)) = 2))

        INTO :TEACHER_ID
    DO
    BEGIN
        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:TEACHER_ID, NULL)
        INTO :TEACHER_CAPTION;
        SUSPEND;
    END

END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE COLLEGE_GRADE_TEACHER_L_LIST (
    I$TEACHER_ID BIGINT)
RETURNS (
    SUBJECT_ID BIGINT,
    SUBJECT_CAPTION VARCHAR(4000),
    GROUP_CAPTION VARCHAR(4000),
    SUBJECT_LOADING DOUBLE PRECISION,
    GRADE_SORT_ORDER DOUBLE PRECISION,
    GROUP_SORT_ORDER DOUBLE PRECISION)
AS
declare variable V$GRADE_ID bigint;
declare variable V$CURRICULUM_ID bigint;
BEGIN
    FOR
        SELECT DISTINCT PGR.PARENT_ID
        FROM LINKS L58
        JOIN LINKS L201 ON L201.OBJ_ID = L58.OBJ_ID AND L201.PARENT_TYPE_ID = 201 AND L201.DATE_DEL IS NULL
        JOIN LINKS PGR ON PGR.OBJ_ID = L58.OBJ_ID AND PGR.PARENT_TYPE_ID IN (9, 46, 48, 347) AND PGR.DATE_DEL IS NULL
        WHERE L58.PARENT_ID = :I$TEACHER_ID AND L58.OBJ_TYPE_ID = 58 AND L58.DATE_DEL IS NULL
        INTO :V$GRADE_ID
    DO
    BEGIN
        FOR
            SELECT DISTINCT DISCIPLINE_ID, DISCIPLINE_CAPTION, CURRICULUM_ID, SUM(VAL)
            FROM COLLEGE_GRADE_DISCIPLINES_LIST(:V$GRADE_ID, NULL, 1)
            GROUP BY DISCIPLINE_ID, DISCIPLINE_CAPTION, CURRICULUM_ID
            INTO :SUBJECT_ID, :SUBJECT_CAPTION, :V$CURRICULUM_ID, :SUBJECT_LOADING
        DO
        BEGIN
            IF (EXISTS(SELECT FIRST 1 1
                       FROM COLLEGE_GRADE_LOADING_LIST(:V$GRADE_ID, :V$CURRICULUM_ID)
                       WHERE TEACHER_ID = :I$TEACHER_ID AND DISCIPLINE_ID = :SUBJECT_ID
            )) THEN
            BEGIN
                SELECT CAPTION, SORT_ORDER FROM OBJECT_CAPTION_GET(:V$GRADE_ID, NULL)
                INTO :GROUP_CAPTION, :GROUP_SORT_ORDER;
                SUSPEND;
            END
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE COLLEGE_LOADING_COMPONENTS (
    I$PLAN_ID BIGINT,
    I$PARENT_ID BIGINT = null)
RETURNS (
    OBJ_ID BIGINT,
    OBJ_CAPTION VARCHAR(4000),
    COMPONENT_ID BIGINT)
AS
declare variable V$PARENT_ID bigint;
begin

  FOR
      SELECT L185.OBJ_ID, C.CAPTION
      FROM LINKS L185
      LEFT JOIN OBJECT_CAPTION_GET(L185.OBJ_ID) C ON 1 = 1
      WHERE L185.PARENT_ID = COALESCE(:I$PARENT_ID, :I$PLAN_ID) AND L185.OBJ_TYPE_ID = 185 AND L185.DATE_DEL IS NULL
      INTO :OBJ_ID, :OBJ_CAPTION
  DO
  BEGIN
      -- Может быть динамическое количество уровней вложений, отдаем только те уровни где есть нагрузка
      IF(EXISTS(
          SELECT FIRST 1 1
          FROM LINKS L201
          WHERE L201.PARENT_ID = :OBJ_ID AND L201.OBJ_TYPE_ID = 201 AND L201.DATE_DEL IS NULL
      ))
      THEN SUSPEND;

      V$PARENT_ID = OBJ_ID;

      FOR
          SELECT OBJ_ID, OBJ_CAPTION
          FROM COLLEGE_LOADING_COMPONENTS(NULL, :V$PARENT_ID)
          INTO :OBJ_ID, :OBJ_CAPTION
      DO
      BEGIN
          SUSPEND;
      END
  END

  -- Итоговая строка в УМК не нужна

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE COLLEGE_LOADING_SUBJECTS (
    I$PARENT_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    OBJ_CAPTION VARCHAR(4000),
    SORT_ORDER DOUBLE PRECISION,
    LOAD_ID BIGINT)
AS
begin

  FOR
      SELECT V1766.VAL, C.CAPTION, L201.COST, L201.OBJ_ID
      FROM LINKS L201
      JOIN VALR V1766 ON V1766.OBJ_ID = L201.OBJ_ID AND V1766.PARAM_ID = 1766 AND V1766.IS_DEL = 0
      LEFT JOIN OBJECT_CAPTION_GET(V1766.VAL) C ON 1 = 1
      WHERE L201.PARENT_ID = :I$PARENT_ID AND L201.OBJ_TYPE_ID = 201 AND L201.DATE_DEL IS NULL
      ORDER BY L201.COST
      INTO :OBJ_ID, :OBJ_CAPTION, :SORT_ORDER, :LOAD_ID
  DO
  BEGIN
      SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE COLLEGE_LOADING_UNION_LIST (
    I$STAGE_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    OBJ_CAPTION VARCHAR(4000),
    SORT_ORDER DOUBLE PRECISION)
AS
DECLARE VARIABLE V$SCHOOL_ID BIGINT;
DECLARE VARIABLE V$OP_ID BIGINT;
DECLARE VARIABLE V$OP_PARAM_2124 BIGINT;
BEGIN
    SELECT FIRST 1 OBJ_ID FROM OBJECT_PARENTS_GET(:I$STAGE_ID, 244) INTO :V$OP_ID;
    SELECT I FROM VAL_GET(:V$OP_ID, 2124) INTO :V$OP_PARAM_2124;
    SELECT FIRST 1 OBJ_ID FROM OBJECT_PARENTS_GET(:V$OP_ID, 2) INTO :V$SCHOOL_ID;

    FOR
        SELECT DISTINCT
               L46.OBJ_ID
        FROM LINKS L86

        JOIN LINKS L46
        ON L46.PARENT_ID = L86.OBJ_ID
        AND L46.OBJ_TYPE_ID = 46
        AND L46.DATE_DEL IS NULL

        LEFT JOIN LINKS LP247
        ON LP247.PARENT_TYPE_ID = 247
        AND LP247.OBJ_ID = L46.OBJ_ID
        AND LP247.DATE_DEL IS NULL

        WHERE L86.PARENT_ID = :V$SCHOOL_ID
        AND L86.OBJ_TYPE_ID = 86
        AND L86.DATE_DEL IS NULL
        AND LP247.LINK_ID IS NULL
        AND (SELECT I FROM VAL_GET(L86.OBJ_ID, 1579)) =
            CASE :V$OP_PARAM_2124
                WHEN 5366 THEN 5538
                WHEN 5367 THEN 5539
                WHEN 5368 THEN 5540
            END

        INTO :OBJ_ID
    DO
    BEGIN
        SELECT CAPTION, SORT_ORDER
        FROM OBJECT_CAPTION_GET(:OBJ_ID, NULL, NULL, :I$USER_ID)
        INTO :OBJ_CAPTION, :SORT_ORDER;
        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE COLLEGE_LOADING_VALS_LIST (
    I$PLAN_ID BIGINT,
    I$COMPONENT_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    STAGE_ID BIGINT,
    SUBJECT_ID BIGINT,
    COMPONENT_ID BIGINT,
    OBJ_ID BIGINT,
    VAL INTEGER,
    UMK1 INTEGER,
    UMK2 INTEGER,
    UMK3 INTEGER,
    UMK4 INTEGER,
    UMK5 INTEGER)
AS
declare variable V$DISC_ID bigint;
declare variable V$STAGE_LV bigint;
declare variable V$OBJ_ID bigint;
declare variable V$COST float;
declare variable V$LISTVAL_ID bigint;
begin
    -- Тут на самом деле не компонент УП, а предметный модуль (185)
    COMPONENT_ID = I$COMPONENT_ID;

    FOR
        SELECT L54.OBJ_ID, V381.LISTVAL_ID
        FROM LINKS L54
        JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
        WHERE L54.PARENT_ID = :I$PLAN_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
        INTO :STAGE_ID, :V$STAGE_LV
    DO
    BEGIN

        FOR
            SELECT L201.OBJ_ID, V1766.VAL
            FROM LINKS L201
            JOIN VALR V1766 ON V1766.OBJ_ID = L201.OBJ_ID AND V1766.PARAM_ID = 1766 AND V1766.IS_DEL = 0
            WHERE L201.PARENT_ID = :I$COMPONENT_ID AND L201.OBJ_TYPE_ID = 201 AND L201.DATE_DEL IS NULL
            INTO :V$DISC_ID, :SUBJECT_ID
        DO
        BEGIN

            UMK1 = 0;
            UMK2 = 0;
            UMK3 = 0;
            UMK4 = 0;
            UMK5 = 0;

            -- Общая нагрузка по предмету
            FOR
                SELECT FIRST 1 L205.OBJ_ID
                FROM LINKS L203
                JOIN LINKS L205 ON L205.PARENT_ID = L203.OBJ_ID AND L205.OBJ_TYPE_ID = 205 AND L205.DATE_DEL IS NULL
                JOIN VALL V1776 ON V1776.OBJ_ID = L205.OBJ_ID AND V1776.PARAM_ID = 1776 AND V1776.IS_DEL = 0 AND V1776.LISTVAL_ID = :V$STAGE_LV
                WHERE L203.PARENT_ID = :V$DISC_ID AND L203.OBJ_TYPE_ID = 203 AND L203.DATE_DEL IS NULL
                INTO :OBJ_ID
            DO
            BEGIN

                -- Нагрузка в часах
                SELECT COALESCE(SUM(VVAL.VAL), 0)
                FROM VALI VVAL
                WHERE VVAL.OBJ_ID = :OBJ_ID AND VVAL.PARAM_ID IN (1777, 1779) AND VVAL.IS_DEL = 0
                INTO :VAL;

                -- UMK1 нерабочая
                SELECT COUNT(*)
                FROM LINKS
                WHERE PARENT_ID = :OBJ_ID AND OBJ_TYPE_ID = 52 AND DATE_DEL IS NULL
                INTO :UMK1;

                SELECT COUNT(*)
                FROM LINKS
                WHERE PARENT_ID = :OBJ_ID AND OBJ_TYPE_ID = 106 AND DATE_DEL IS NULL
                INTO :UMK5;

                FOR
                    SELECT L107.OBJ_ID, COALESCE(L107.COST, 0)
                    FROM LINKS L107
                    /* Отслеживаем чтобы не попали удаленные учебники */
                    JOIN LINKS L105 ON L105.PARENT_TYPE_ID = 105 AND L105.OBJ_ID = L107.OBJ_ID AND L105.DATE_DEL IS NULL
                    WHERE L107.PARENT_ID = :OBJ_ID AND L107.OBJ_TYPE_ID = 107 AND L107.DATE_DEL IS NULL
                    INTO :V$OBJ_ID, :V$COST
                DO
                BEGIN
                    SELECT I FROM VAL_GET(:V$OBJ_ID, 653, 0, :I$USER_ID) INTO :V$LISTVAL_ID;
                    IF (V$LISTVAL_ID = 2097) THEN UMK2 = UMK2 + 1;
                    ELSE IF (V$LISTVAL_ID = 2098) THEN UMK3 = UMK3 + 1;
                    ELSE IF (V$LISTVAL_ID = 2099) THEN UMK4 = UMK4 + V$COST;
                END

                SUSPEND;
            END

        END

    END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE COLLEGE_OUT_PUPIL_LIST (
    I$GROUP_ID BIGINT)
RETURNS (
    PUPIL_ID BIGINT,
    FIRSTNAME VARCHAR(255),
    MIDDLENAME VARCHAR(255),
    LASTNAME VARCHAR(255),
    CLASSNAME VARCHAR(255))
AS
DECLARE VARIABLE V$OBJ_ID BIGINT;
BEGIN
    FOR
        SELECT L10.PARENT_ID,
               L10.OBJ_ID
        FROM LINKS L10
        WHERE L10.PARENT_ID = :I$GROUP_ID
          AND L10.OBJ_TYPE_ID = 10
          AND L10.DATE_DEL IS NULL

        INTO :V$OBJ_ID,
             :PUPIL_ID
    DO
    BEGIN
        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:V$OBJ_ID, 49)
        INTO :CLASSNAME;

        SELECT V
        FROM VAL_GET(:PUPIL_ID, 55)
        INTO :LASTNAME;

        SELECT V
        FROM VAL_GET(:PUPIL_ID, 56)
        INTO :FIRSTNAME;

        SELECT V
        FROM VAL_GET(:PUPIL_ID, 57)
        INTO :MIDDLENAME;

        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE COLLEGE_PUPIL_OUT (
    I$PUPIL_ID BIGINT,
    I$ACTION_DATE DATE,
    I$ORDER_NUMBER VARCHAR(4000),
    I$ORDER_DATE DATE,
    I$USER_ID BIGINT = null)
AS
declare variable V$GROUP_ID bigint;
declare variable V$BLOB_ID bigint;
BEGIN

    SELECT FIRST 1 LPG.PARENT_ID
    FROM LINKS LPG
    WHERE LPG.OBJ_ID = :I$PUPIL_ID AND LPG.PARENT_TYPE_ID = 9 AND LPG.DATE_DEL IS NULL
    INTO :V$GROUP_ID;

    IF(V$GROUP_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Учебный коллектив не найден';

    SELECT OBJ_ID FROM VARGRP_MOVE_PUPIL(:I$PUPIL_ID, :V$GROUP_ID, :I$ORDER_NUMBER, :I$ORDER_DATE, :I$ACTION_DATE, 1, :I$USER_ID, NULL, 812) INTO :V$BLOB_ID;

END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE COLLEGE_PUPIL_OUT_ALL (
    I$GROUP_ID BIGINT,
    I$ACTION_DATE DATE,
    I$ORDER_NUMBER VARCHAR(4000),
    I$ORDER_DATE DATE,
    I$USER_ID BIGINT)
AS
declare variable V$PUPIL_ID bigint;
declare variable V$GROUP_ID bigint;
declare variable V$CJ_ID bigint;
begin

  FOR
    SELECT L10.OBJ_ID
    FROM LINKS L10
    WHERE L10.PARENT_ID = :I$GROUP_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    INTO :V$PUPIL_ID
  DO
  BEGIN
    EXECUTE PROCEDURE COLLEGE_PUPIL_OUT(:V$PUPIL_ID, :I$ACTION_DATE, :I$ORDER_NUMBER, :I$ORDER_DATE, :I$USER_ID);
  END

  -- Удалить все группы, где числились обучающиеся, если там никого не осталось
  -- а также связанные с ними журналы и элементы расписания
  FOR
    SELECT DISTINCT LPG.PARENT_ID
    FROM LINKS L10
    JOIN LINKS LPG ON LPG.OBJ_ID = L10.OBJ_ID AND LPG.PARENT_TYPE_ID IN (256, 179, 46, 48)
    LEFT JOIN LINKS L10N ON L10N.PARENT_ID = LPG.PARENT_ID AND L10N.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    WHERE L10.PARENT_ID = :I$GROUP_ID AND L10.OBJ_TYPE_ID = 10 AND L10N.OBJ_ID IS NULL
    INTO :V$GROUP_ID
  DO
  BEGIN
    UPDATE LINKS
    SET DATE_DEL = CURRENT_TIMESTAMP
    WHERE OBJ_ID = :V$GROUP_ID AND DATE_DEL IS NULL;

    FOR
      SELECT OBJ_ID
      FROM CJ2_JOURNAL
      WHERE GRADE_ID = :V$GROUP_ID AND DATE_DEL IS NULL
      INTO :V$CJ_ID
    DO
    BEGIN
      UPDATE SCHEDULE_ITEMS
      SET DATE_DEL = CURRENT_TIMESTAMP
      WHERE CJ_ID = :V$GROUP_ID AND DATE_DEL IS NULL;
    END

    UPDATE CJ2_JOURNAL
    SET DATE_DEL = CURRENT_TIMESTAMP
    WHERE GRADE_ID = :V$GROUP_ID AND DATE_DEL IS NULL;
  END

  -- Удалить саму группу
  UPDATE LINKS
  SET DATE_DEL = CURRENT_TIMESTAMP
  WHERE OBJ_ID = :I$GROUP_ID AND DATE_DEL IS NULL;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE COLLEGE_PUPIL_SPECIALITY_SET (
    I$PUPIL_ID BIGINT,
    I$GROUP_ID BIGINT,
    I$USER_ID BIGINT)
AS
DECLARE VARIABLE V$LISTVAL_ID BIGINT;
DECLARE VARIABLE V$BLOB_ID BIGINT;
BEGIN
    FOR
        SELECT V2165.LISTVAL_ID
        FROM VALL V2165
        WHERE V2165.OBJ_ID = :I$GROUP_ID
        AND V2165.PARAM_ID = 2165
        AND V2165.IS_DEL = 0
        INTO :V$LISTVAL_ID
    DO
    BEGIN
        SELECT BLOB_ID
        FROM VAL_ADD(2164, :I$PUPIL_ID, :V$LISTVAL_ID, :I$USER_ID)
        INTO :V$BLOB_ID;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE COLLEGE_SEMESTR_COUNT_CHANGED (
    I$STAGE_ID BIGINT)
AS
declare variable V$SEMESTR_COUNT integer;
declare variable V$EXISTS_SEMESTR_COUNT integer;
declare variable V$SEMESTR_LOAD_ID bigint;
declare variable V$LISTVAL_ID bigint;
BEGIN
    V$SEMESTR_COUNT = 0;

    SELECT FIRST 1
           VAL
    FROM VALI
    WHERE OBJ_ID = :I$STAGE_ID
    AND PARAM_ID IN (1762,2131)
    AND IS_DEL = 0
    AND VAL > 0
    INTO :V$SEMESTR_COUNT;

    IF (V$SEMESTR_COUNT = 0) THEN
    BEGIN
        FOR
            SELECT LINK_ID
            FROM LINKS
            WHERE PARENT_ID = :I$STAGE_ID
            AND OBJ_TYPE_ID = 209
            AND DATE_DEL IS NULL

            INTO :V$SEMESTR_LOAD_ID
        DO
        BEGIN
            UPDATE LINKS
            SET DATE_DEL = CURRENT_TIMESTAMP
            WHERE LINK_ID = :V$SEMESTR_LOAD_ID;
        END
    END
    ELSE
    BEGIN
        V$EXISTS_SEMESTR_COUNT = 0;
        FOR
            SELECT L209.LINK_ID
            FROM LINKS L209

            WHERE L209.PARENT_ID = :I$STAGE_ID
            AND L209.OBJ_TYPE_ID = 209

            INTO :V$SEMESTR_LOAD_ID
        DO
        BEGIN
            V$EXISTS_SEMESTR_COUNT = V$EXISTS_SEMESTR_COUNT + 1;
            IF (V$EXISTS_SEMESTR_COUNT <= V$SEMESTR_COUNT) THEN
            BEGIN
                UPDATE LINKS
                SET DATE_DEL = NULL
                WHERE LINK_ID = :V$SEMESTR_LOAD_ID;
            END
            ELSE
            BEGIN
                UPDATE LINKS
                SET DATE_DEL = CURRENT_TIMESTAMP
                WHERE LINK_ID = :V$SEMESTR_LOAD_ID;
            END
        END
        WHILE (V$EXISTS_SEMESTR_COUNT < V$SEMESTR_COUNT) DO
        BEGIN
            V$SEMESTR_LOAD_ID = NULL;

            INSERT INTO OBJECTS(TYPE_ID) VALUES(209)
            RETURNING OBJ_ID INTO :V$SEMESTR_LOAD_ID;

            IF (V$SEMESTR_LOAD_ID IS NOT NULL) THEN
            BEGIN
                INSERT INTO LINKS(PARENT_ID,OBJ_ID,DATE_INS)
                VALUES(:I$STAGE_ID, :V$SEMESTR_LOAD_ID,CURRENT_TIMESTAMP);

                SELECT BLOB_ID
                FROM VAL_ADD(
                    1787,
                    :V$SEMESTR_LOAD_ID,
                    CAST(:V$EXISTS_SEMESTR_COUNT + 1 AS VARCHAR(10)) || ' семестр'
                )
                INTO :V$LISTVAL_ID;

                V$EXISTS_SEMESTR_COUNT = V$EXISTS_SEMESTR_COUNT + 1;
            END
            ELSE
            BEGIN
                BREAK;
            END
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE COLLEGE_SP_STAGE_CHANGED (
    I$PLAN_ID BIGINT)
AS
declare variable V$STAGE_COUNT integer;
declare variable V$EXISTS_STAGE_COUNT integer;
declare variable V$STAGE_LOAD_ID bigint;
declare variable V$LISTVAL_ID bigint;
BEGIN
    V$STAGE_COUNT = 0;

    SELECT FIRST 1 VAL
    FROM VALI
    WHERE OBJ_ID = :I$PLAN_ID AND PARAM_ID IN (1760, 3371) AND IS_DEL = 0 AND VAL > 0
    INTO :V$STAGE_COUNT;

    -- Не более 5 курсов
    IF (V$STAGE_COUNT > 5) THEN V$STAGE_COUNT = 5;

    V$EXISTS_STAGE_COUNT = 0;
    FOR
        SELECT L208.LINK_ID
        FROM LINKS L208
        LEFT JOIN VALL V1785 ON V1785.OBJ_ID = L208.OBJ_ID AND V1785.PARAM_ID = 1785 AND V1785.IS_DEL = 0
        LEFT JOIN LISTVALS LV ON LV.LISTVAL_ID = V1785.LISTVAL_ID
        WHERE L208.PARENT_ID = :I$PLAN_ID AND L208.OBJ_TYPE_ID = 208
        ORDER BY 1
        INTO :V$STAGE_LOAD_ID
    DO
    BEGIN
        V$EXISTS_STAGE_COUNT = V$EXISTS_STAGE_COUNT + 1;
        IF (V$EXISTS_STAGE_COUNT <= V$STAGE_COUNT) THEN
        BEGIN
            UPDATE LINKS
            SET DATE_DEL = NULL
            WHERE LINK_ID = :V$STAGE_LOAD_ID AND DATE_DEL IS NOT NULL;
        END
        ELSE
        BEGIN
            UPDATE LINKS
            SET DATE_DEL = CURRENT_TIMESTAMP
            WHERE LINK_ID = :V$STAGE_LOAD_ID AND DATE_DEL IS NULL;
        END
    END

    WHILE (V$EXISTS_STAGE_COUNT < V$STAGE_COUNT) DO
    BEGIN
        V$STAGE_LOAD_ID = NULL;

        INSERT INTO OBJECTS
        (TYPE_ID)
        VALUES (208)
        RETURNING OBJ_ID
        INTO :V$STAGE_LOAD_ID;

        INSERT INTO LINKS
        (PARENT_ID, OBJ_ID, DATE_INS)
        VALUES (:I$PLAN_ID, :V$STAGE_LOAD_ID, CURRENT_TIMESTAMP);

        SELECT BLOB_ID
        FROM VAL_ADD(
            1785,
            :V$STAGE_LOAD_ID,
            (SELECT LISTVAL_ID FROM LISTVALS WHERE PARENT_ID = 2142 AND IS_DEL = 0 AND LISTVAL_ID <> 13145 AND COST = :V$EXISTS_STAGE_COUNT + 1)
        )
        INTO :V$LISTVAL_ID;

        V$EXISTS_STAGE_COUNT = V$EXISTS_STAGE_COUNT + 1;
    END

    V$EXISTS_STAGE_COUNT = 0;
    FOR
        SELECT L54.LINK_ID
        FROM LINKS L54
        LEFT JOIN VALL V49 ON V49.OBJ_ID = L54.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
        LEFT JOIN LISTVALS LV ON LV.LISTVAL_ID = V49.LISTVAL_ID
        WHERE L54.PARENT_ID = :I$PLAN_ID AND L54.OBJ_TYPE_ID = 54
        ORDER BY 1
        INTO :V$STAGE_LOAD_ID
    DO
    BEGIN
        V$EXISTS_STAGE_COUNT = V$EXISTS_STAGE_COUNT + 1;
        IF (V$EXISTS_STAGE_COUNT <= V$STAGE_COUNT) THEN
        BEGIN
            UPDATE LINKS
            SET DATE_DEL = NULL
            WHERE LINK_ID = :V$STAGE_LOAD_ID AND DATE_DEL IS NOT NULL;
        END
        ELSE
        BEGIN
            UPDATE LINKS
            SET DATE_DEL = CURRENT_TIMESTAMP
            WHERE LINK_ID = :V$STAGE_LOAD_ID AND DATE_DEL IS NULL;
        END
    END

    WHILE (V$EXISTS_STAGE_COUNT < V$STAGE_COUNT) DO
    BEGIN
        V$STAGE_LOAD_ID = NULL;

        INSERT INTO OBJECTS
        (TYPE_ID)
        VALUES (54)
        RETURNING OBJ_ID INTO :V$STAGE_LOAD_ID;

        INSERT INTO LINKS
        (PARENT_ID, OBJ_ID, DATE_INS)
        VALUES(:I$PLAN_ID, :V$STAGE_LOAD_ID, CURRENT_TIMESTAMP);

        SELECT BLOB_ID
        FROM VAL_ADD(
            381,
            :V$STAGE_LOAD_ID,
            (SELECT LISTVAL_ID FROM LISTVALS WHERE PARENT_ID = 2142 AND IS_DEL = 0 AND LISTVAL_ID <> 13145 AND COST = :V$EXISTS_STAGE_COUNT + 1)
        )
        INTO :V$LISTVAL_ID;

        V$EXISTS_STAGE_COUNT = V$EXISTS_STAGE_COUNT + 1;
    END

END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE COLLEGE_VERIFY_ALL (
    I$OBJ_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    LINK_ID BIGINT,
    OBJECT_ID BIGINT,
    NAME_TASK VARCHAR(1000),
    ERROR_NAME VARCHAR(1000),
    PARAMS_NAME VARCHAR(1000),
    ERROR_TEXT VARCHAR(1000),
    ERROR_TYPE SMALLINT)
AS
BEGIN
    FOR
        SELECT LINK_ID,
               OBJECT_ID,
               NAME_TASK,
               ERROR_NAME,
               PARAMS_NAME,
               ERROR_TEXT,
               ERROR_TYPE
        FROM COLLEGE_VERIFY_BUILDING(:I$OBJ_ID, :I$USER_ID)
        INTO :LINK_ID,
             :OBJECT_ID,
             :NAME_TASK,
             :ERROR_NAME,
             :PARAMS_NAME,
             :ERROR_TEXT,
             :ERROR_TYPE
    DO
    BEGIN
        SUSPEND;
    END

    FOR
        SELECT LINK_ID,
               OBJECT_ID,
               NAME_TASK,
               ERROR_NAME,
               PARAMS_NAME,
               ERROR_TEXT,
               ERROR_TYPE
        FROM VERIFY_CLASS(:I$OBJ_ID)
        INTO :LINK_ID,
             :OBJECT_ID,
             :NAME_TASK,
             :ERROR_NAME,
             :PARAMS_NAME,
             :ERROR_TEXT,
             :ERROR_TYPE
    DO
    BEGIN
        SUSPEND;
    END

    FOR
        SELECT LINK_ID,
               OBJECT_ID,
               NAME_TASK,
               ERROR_NAME,
               PARAMS_NAME,
               ERROR_TEXT,
               ERROR_TYPE
        FROM VERIFY_DOCS(:I$OBJ_ID)
        INTO :LINK_ID,
             :OBJECT_ID,
             :NAME_TASK,
             :ERROR_NAME,
             :PARAMS_NAME,
             :ERROR_TEXT,
             :ERROR_TYPE
    DO
    BEGIN
        SUSPEND;
    END

    FOR
        SELECT LINK_ID,
               OBJECT_ID,
               NAME_TASK,
               ERROR_NAME,
               PARAMS_NAME,
               ERROR_TEXT,
               ERROR_TYPE
        FROM VERIFY_POST(:I$OBJ_ID)
        INTO :LINK_ID,
             :OBJECT_ID,
             :NAME_TASK,
             :ERROR_NAME,
             :PARAMS_NAME,
             :ERROR_TEXT,
             :ERROR_TYPE
    DO
    BEGIN
        SUSPEND;
    END

    FOR
        SELECT LINK_ID,
               OBJECT_ID,
               NAME_TASK,
               ERROR_NAME,
               PARAMS_NAME,
               ERROR_TEXT,
               ERROR_TYPE
        FROM COLLEGE_VERIFY_PUPIL(:I$OBJ_ID)
        INTO :LINK_ID,
             :OBJECT_ID,
             :NAME_TASK,
             :ERROR_NAME,
             :PARAMS_NAME,
             :ERROR_TEXT,
             :ERROR_TYPE
    DO
    BEGIN
        SUSPEND;
    END

    FOR
        SELECT LINK_ID,
               OBJECT_ID,
               NAME_TASK,
               ERROR_NAME,
               PARAMS_NAME,
               ERROR_TEXT,
               ERROR_TYPE
        FROM VERIFY_SUBJECT(:I$OBJ_ID)
        INTO :LINK_ID,
             :OBJECT_ID,
             :NAME_TASK,
             :ERROR_NAME,
             :PARAMS_NAME,
             :ERROR_TEXT,
             :ERROR_TYPE
    DO
    BEGIN
        SUSPEND;
    END

    FOR
        SELECT LINK_ID,
               OBJECT_ID,
               NAME_TASK,
               ERROR_NAME,
               PARAMS_NAME,
               ERROR_TEXT,
               ERROR_TYPE
        FROM VERIFY_WORKERS(:I$OBJ_ID)
        INTO :LINK_ID,
             :OBJECT_ID,
             :NAME_TASK,
             ERROR_NAME,
             :PARAMS_NAME,
             :ERROR_TEXT,
             :ERROR_TYPE
    DO
    BEGIN
        SUSPEND;
    END

    FOR
        SELECT LINK_ID,
               OBJECT_ID,
               NAME_TASK,
               ERROR_NAME,
               PARAMS_NAME,
               ERROR_TEXT,
               ERROR_TYPE
        FROM VERIFY_TIMETABLE(:I$OBJ_ID)
        INTO :LINK_ID,
             :OBJECT_ID,
             :NAME_TASK,
             :ERROR_NAME,
             :PARAMS_NAME,
             :ERROR_TEXT,
             :ERROR_TYPE
    DO
    BEGIN
        SUSPEND;
    END

   FOR
        SELECT LINK_ID,
               SCHOOLAR_ID,
               NAME_TASK,
               ERROR_NAME,
               PARAMS_NAME,
               LOCATION || ', ' || PUPIL || ', ' || ERROR_TEXT,
               ERROR_TYPE
        FROM VERIFY_MOVEMENT(:I$OBJ_ID,:I$USER_ID)
        INTO :LINK_ID,
             :OBJECT_ID,
             :NAME_TASK,
             :ERROR_NAME,
             :PARAMS_NAME,
             :ERROR_TEXT,
             :ERROR_TYPE
    DO
    BEGIN
        SUSPEND;
    END

    FOR
        SELECT LINK_ID,
               OBJECT_ID,
               NAME_TASK,
               ERROR_NAME,
               PARAMS_NAME,
               ERROR_TEXT,
               ERROR_TYPE
        FROM VERIFY_MTR(:I$OBJ_ID)
        INTO :LINK_ID,
             :OBJECT_ID,
             :NAME_TASK,
             :ERROR_NAME,
             :PARAMS_NAME,
             :ERROR_TEXT,
             :ERROR_TYPE
    DO
    BEGIN
        SUSPEND;
    END

    FOR
        SELECT LINK_ID,
               OBJECT_ID,
               NAME_TASK,
               ERROR_NAME,
               PARAMS_NAME,
               ERROR_TEXT,
               ERROR_TYPE
        FROM VERIFY_MONITORING(:I$OBJ_ID)
        INTO :LINK_ID,
             :OBJECT_ID,
             :NAME_TASK,
             :ERROR_NAME,
             :PARAMS_NAME,
             :ERROR_TEXT,
             :ERROR_TYPE
    DO
    BEGIN
        SUSPEND;
    END

    FOR
        SELECT LINK_ID,
               OBJECT_ID,
               NAME_TASK,
               ERROR_NAME,
               PARAMS_NAME,
               ERROR_TEXT,
               ERROR_TYPE
        FROM VERIFY_GIA(:I$OBJ_ID)
        INTO :LINK_ID,
             :OBJECT_ID,
             :NAME_TASK,
             :ERROR_NAME,
             :PARAMS_NAME,
             :ERROR_TEXT,
             :ERROR_TYPE
    DO
    BEGIN
        SUSPEND;
    END

    FOR
        SELECT LINK_ID,
               OBJECT_ID,
               NAME_TASK,
               ERROR_NAME,
               PARAMS_NAME,
               ERROR_TEXT,
               ERROR_TYPE
        FROM VERIFY_OP(:I$OBJ_ID)
        INTO :LINK_ID,
             :OBJECT_ID,
             :NAME_TASK,
             :ERROR_NAME,
             :PARAMS_NAME,
             :ERROR_TEXT,
             :ERROR_TYPE
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE COLLEGE_VERIFY_BUILDING (
    I$OBJ_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    LINK_ID BIGINT,
    OBJECT_ID BIGINT,
    NAME_TASK VARCHAR(1000),
    ERROR_NAME VARCHAR(1000),
    PARAMS_NAME VARCHAR(1000),
    ERROR_TEXT VARCHAR(1000),
    ERROR_TYPE SMALLINT)
AS
DECLARE VARIABLE V$BLOB_ID BIGINT;
DECLARE VARIABLE V$TEMP INTEGER;
DECLARE VARIABLE V$VALS VARCHAR(1000);
DECLARE VARIABLE V$TVALS VARCHAR(1000);
DECLARE VARIABLE V$TVALS2 VARCHAR(1000);
BEGIN
    NAME_TASK = 'Образовательное учреждение, здания, помещения';
    ERROR_TYPE = 1;

    SELECT FIRST 1 L2.OBJ_ID, L2.LINK_ID
    FROM LINKS L2
    WHERE L2.OBJ_ID = :I$OBJ_ID
    AND L2.OBJ_TYPE_ID = 2
    AND L2.DATE_DEL IS NULL
    INTO :OBJECT_ID, :LINK_ID;


    V$VALS = NULL;
    SELECT V
    FROM VAL_GET(:OBJECT_ID, 8, 0, :I$USER_ID)
    INTO :V$VALS;

    IF (V$VALS = '') THEN
    BEGIN
        ERROR_TEXT = 'Поле «Организационно-правовая форма» должно быть заполнено!';
        ERROR_NAME = :ERROR_TEXT;
        PARAMS_NAME = 'Организационно-правовая форма';
        ERROR_TYPE = 3;
        SUSPEND;
    END

    V$VALS = NULL;
    SELECT V
    FROM VAL_GET(:OBJECT_ID, 14, 0, :I$USER_ID)
    INTO :V$VALS;

    IF (V$VALS = '') THEN
    BEGIN
        ERROR_TEXT = 'Поле «Общая площадь территории» должно быть заполнено!';
        ERROR_NAME = :ERROR_TEXT;
        PARAMS_NAME = 'Общая площадь территории';
        ERROR_TYPE = 3;
        SUSPEND;
    END

    V$VALS = NULL;
    SELECT V
    FROM VAL_GET(:OBJECT_ID, 29, 0, :I$USER_ID)
    INTO :V$VALS;

    IF (V$VALS = '') THEN
    BEGIN
        ERROR_TEXT = 'Поле «Телефон приёмной» должно быть заполнено!';
        ERROR_NAME = :ERROR_TEXT;
        PARAMS_NAME = 'Телефон приёмной';
        ERROR_TYPE = 3;
        SUSPEND;
    END

    V$VALS = NULL;
    SELECT V
    FROM VAL_GET(:OBJECT_ID, 35, 0, :I$USER_ID)
    INTO :V$VALS;

    IF (V$VALS = '') THEN
    BEGIN
        ERROR_TEXT = 'Поле «Электронная почта» должно быть заполнено!';
        ERROR_NAME = :ERROR_TEXT;
        PARAMS_NAME = 'Электронная почта';
        ERROR_TYPE = 3;
        SUSPEND;
    END

    V$VALS = NULL;
    SELECT V
    FROM VAL_GET(:OBJECT_ID, 36, 0, :I$USER_ID)
    INTO :V$VALS;

    IF (V$VALS = '') THEN
    BEGIN
        ERROR_TEXT = 'Поле «Адрес сайта» должно быть заполнено!';
        ERROR_NAME = :ERROR_TEXT;
        PARAMS_NAME = 'Адрес сайта';
        ERROR_TYPE = 3;
        SUSPEND;
    END

    IF (NOT EXISTS(
        SELECT FIRST 1 1
        FROM R_SPB_POST_DIRECTOR(:OBJECT_ID, :I$USER_ID)
        WHERE POST_ID IN (64, 74, 65, 3399, 18497, 18531, 18532)
    )) THEN
    BEGIN
        ERROR_TEXT = 'Ошибочная должность руководителя';
        ERROR_NAME = :ERROR_TEXT;
        PARAMS_NAME = 'Руководитель образовательного учреждения';
        ERROR_TYPE = 3;
        SUSPEND;
    END

    -- 1 --

    SELECT V
    FROM VAL_GET(:OBJECT_ID, 2, 0, :I$USER_ID)
    INTO :V$VALS;

    V$TVALS = REPLACE(TRIM(V$VALS), '  ', ' ');
    WHILE(V$TVALS <> V$VALS) DO
    BEGIN
        V$TVALS2 = V$TVALS;
        V$TVALS = REPLACE(TRIM(V$TVALS), '  ', ' ');
        IF (V$TVALS2 = V$TVALS) THEN
        BEGIN
            BREAK;
        END
    END

    IF (V$TVALS <> V$VALS) THEN
    BEGIN
        SELECT BLOB_ID
        FROM VAL_ADD(2, :OBJECT_ID, :V$TVALS)
        INTO :V$BLOB_ID;
    
        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:OBJECT_ID, NULL, NULL, :I$USER_ID)
        INTO :V$TVALS;

        ERROR_TEXT = 'Поле «Краткое наименование ОУ» объекта «' || V$TVALS || '» исправлено.';
        ERROR_NAME = 'Поле «Краткое наименование ОУ» объекта исправлено.';
        PARAMS_NAME = 'Краткое наименование ОУ';
        ERROR_TYPE = 1;
        SUSPEND;
    END

    IF (V$TVALS = '') THEN
    BEGIN
        ERROR_TEXT = 'Поле «Краткое наименование ОУ» должно быть заполнено!';
        ERROR_NAME = :ERROR_TEXT;
        PARAMS_NAME = 'Краткое наименование ОУ';
        ERROR_TYPE = 3;
        SUSPEND;
    END

    -- 2 --
    V$VALS = NULL;
    SELECT V
    FROM VAL_GET(:OBJECT_ID, 5, 0, :I$USER_ID)
    INTO :V$VALS;
    V$TVALS = REPLACE(TRIM(V$VALS), '  ', ' ');
    WHILE(V$TVALS <> V$VALS) DO
    BEGIN
        V$TVALS2 = V$TVALS;
        V$TVALS = REPLACE(TRIM(V$TVALS), '  ', ' ');
        IF (V$TVALS2 = V$TVALS) THEN
        BEGIN
            BREAK;
        END
    END

    IF (V$TVALS <> V$VALS) THEN
    BEGIN
        SELECT BLOB_ID
        FROM VAL_ADD(5, :OBJECT_ID, :V$TVALS)
        INTO :V$BLOB_ID;
    
        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:OBJECT_ID, NULL, NULL, :I$USER_ID)
        INTO :V$TVALS;

        ERROR_TEXT = 'Поле «Полное наименование ОУ» объекта «' || V$TVALS || '» исправлено.';
        ERROR_NAME = 'Поле «Полное наименование ОУ» объекта исправлено.';
        PARAMS_NAME = 'Полное наименование ОУ';
        ERROR_TYPE = 1;
        SUSPEND;
    END

    IF (V$TVALS = '') THEN
    BEGIN
        ERROR_TEXT = 'Поле «Полное наименование ОУ» должно быть заполнено!';
        ERROR_NAME = :ERROR_TEXT;
        PARAMS_NAME = 'Полное наименование ОУ';
        ERROR_TYPE = 3;
        SUSPEND;
    END

    -- 3 --
    V$VALS = NULL;
    SELECT V
    FROM VAL_GET(:OBJECT_ID, 999, 0, :I$USER_ID)
    INTO :V$VALS;
    V$TVALS = REPLACE(TRIM(V$VALS), '  ', ' ');
    WHILE(V$TVALS <> V$VALS) DO
    BEGIN
        V$TVALS2 = V$TVALS;
        V$TVALS = REPLACE(TRIM(V$TVALS), '  ', ' ');
        IF (V$TVALS2 = V$TVALS) THEN
        BEGIN
            BREAK;
        END
    END

    IF (V$VALS <> V$TVALS) THEN
    BEGIN
        SELECT BLOB_ID
        FROM VAL_ADD(999, :OBJECT_ID, :V$TVALS)
        INTO :V$BLOB_ID;

        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:OBJECT_ID, NULL, NULL, :I$USER_ID)
        INTO :V$TVALS;

        ERROR_TEXT = 'Поле «Сокращённое наименование ОУ по Уставу» объекта «' || V$TVALS || '» исправлено.';
        ERROR_NAME = 'Поле «Сокращённое наименование ОУ по Уставу» объекта исправлено.';
        PARAMS_NAME = 'Сокращённое наименование ОУ по Уставу';
        ERROR_TYPE = 1;
        SUSPEND;
    END

    IF (V$TVALS = '') THEN
    BEGIN
        ERROR_TEXT = 'Поле «Сокращённое наименование ОУ по Уставу» должно быть заполнено!';
        ERROR_NAME = :ERROR_TEXT;
        PARAMS_NAME = 'Сокращённое наименование ОУ по Уставу';
        ERROR_TYPE = 3;
        SUSPEND;
    END

    -- 4 --
    V$VALS = NULL;
    SELECT V
    FROM VAL_GET(:OBJECT_ID, 6, 0, :I$USER_ID)
    INTO :V$VALS;
    V$TVALS = REPLACE(TRIM(V$VALS), '  ', ' ');
    WHILE(V$TVALS <> V$VALS) DO
    BEGIN
        V$TVALS2 = V$TVALS;
        V$TVALS = REPLACE(TRIM(V$TVALS), '  ', ' ');
        IF (V$TVALS2 = V$TVALS) THEN
        BEGIN
            BREAK;
        END
    END

    IF (V$VALS <> V$TVALS) THEN
    BEGIN
        SELECT BLOB_ID
        FROM VAL_ADD(6, :OBJECT_ID, :V$TVALS)
        INTO :V$BLOB_ID;

        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:OBJECT_ID, NULL, NULL, :I$USER_ID)
        INTO :V$TVALS;

        ERROR_TEXT = 'Поле «Подчинение» объекта «' || V$TVALS || '» исправлено.';
        ERROR_NAME = 'Поле «Подчинение» объекта исправлено.';
        PARAMS_NAME = 'Подчинение';
        ERROR_TYPE = 1;
        SUSPEND;
    END
    IF (V$TVALS NOT LIKE 'Комитет по образованию Санкт-Петербурга')  THEN
    BEGIN
        IF (NOT EXISTS(
            SELECT FIRST 1 1
            FROM VALL VLL
            WHERE VLL.PARAM_ID = 8
            AND VLL.IS_DEL = 0
            AND VLL.LISTVAL_ID IN (1734, 1735)
            AND VLL.OBJ_ID = :OBJECT_ID
        )) THEN
        BEGIN
            IF (V$TVALS = '') THEN
            BEGIN
                ERROR_TEXT = 'Поле «Подчинение» должно быть заполнено!';
                ERROR_NAME = :ERROR_TEXT;
                PARAMS_NAME = 'Подчинение';
                ERROR_TYPE = 3;
                SUSPEND;
            END
            ELSE
            BEGIN
                ERROR_TEXT = 'Значение в поле «Подчинение» не соответствует стандартному "Комитет по образованию Санкт-Петербурга"';
                ERROR_NAME = :ERROR_TEXT;
                PARAMS_NAME = 'Подчинение';
                ERROR_TYPE = 2;
                SUSPEND;
            END
        END
    END

    -- 5 --
    V$VALS = NULL;
    SELECT V
    FROM VAL_GET(:OBJECT_ID, 7, 0, :I$USER_ID)
    INTO :V$VALS;
    V$TVALS = REPLACE(TRIM(V$VALS), '  ', ' ');
    WHILE(V$TVALS <> V$VALS) DO
    BEGIN
        V$TVALS2 = V$TVALS;
        V$TVALS = REPLACE(TRIM(V$TVALS), '  ', ' ');
        IF (V$TVALS2 = V$TVALS) THEN
        BEGIN
            BREAK;
        END
    END

    IF (V$VALS <> V$TVALS) THEN
    BEGIN
        SELECT BLOB_ID
        FROM VAL_ADD(7, :OBJECT_ID, :V$TVALS)
        INTO :V$BLOB_ID;

        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:OBJECT_ID, NULL, NULL, :I$USER_ID)
        INTO :V$TVALS;

        ERROR_TEXT = 'Поле «Вышестоящий орган» объекта «' || V$TVALS || '» исправлено.';
        ERROR_NAME = 'Поле «Вышестоящий орган» объекта исправлено.';
        PARAMS_NAME = 'Вышестоящий орган';
        ERROR_TYPE = 1;
        SUSPEND;
    END
    IF (NOT EXISTS(
        SELECT FIRST 1 1
        FROM VALL VLL
        WHERE VLL.PARAM_ID = 8
        AND VLL.IS_DEL = 0
        AND VLL.LISTVAL_ID IN (1734, 1735)
        AND VLL.OBJ_ID = :OBJECT_ID
    )) THEN
    BEGIN
        IF (V$TVALS = '') THEN
        BEGIN
            ERROR_TEXT = 'Поле «Вышестоящий орган» должно быть заполнено!';
            ERROR_NAME = :ERROR_TEXT;
            PARAMS_NAME = 'Вышестоящий орган';
            ERROR_TYPE = 3;
            SUSPEND;
        END
        ELSE
        BEGIN
            IF (NOT EXISTS(
                SELECT FIRST 1 1
                FROM VALS VS
                JOIN LISTVALS LV
                ON LV.LIST_ID = 168
                AND LV.IS_DEL = 0

                JOIN RES R
                ON R.RES_ID = LV.RES_ID
                AND R.LANG_CODE = 'RU'
                AND VS.VAL = R.VAL

                WHERE VS.IS_DEL = 0
                AND VS.PARAM_ID = 7
                AND VS.OBJ_ID = :OBJECT_ID
            )) THEN
            BEGIN
                ERROR_TEXT = 'Значение не соответствует рекомендуемому (не выбрано из списка значений)';
                ERROR_NAME = :ERROR_TEXT;
                PARAMS_NAME = 'Вышестоящий орган';
                ERROR_TYPE = 2;
                SUSPEND;
            END
        END
    END
    -- 6 --
    V$TEMP = NULL;

    SELECT VI.VAL
    FROM VALI VI
    WHERE VI.PARAM_ID = 17
    AND VI.IS_DEL = 0
    AND VI.OBJ_ID = :OBJECT_ID
    INTO :V$TEMP;

    IF (:V$TEMP = 0) THEN
    BEGIN
        UPDATE VALI VI
        SET VI.IS_DEL = 1
        WHERE VI.PARAM_ID = 17
        AND VI.OBJ_ID = :OBJECT_ID
        AND VI.IS_DEL = 0;
        ERROR_TEXT = 'Номер ОУ не может содержать значение "0". Поле было очищено';
        ERROR_NAME = :ERROR_TEXT;
        PARAMS_NAME = 'Номер ОУ';
        ERROR_TYPE = 1;
        SUSPEND;
    END

    -- 7 --
    IF (:V$TEMP > 0) THEN
    BEGIN
        SELECT COUNT(VS.VAL)
        FROM VALS VS
        WHERE VS.PARAM_ID = 5
        AND VS.IS_DEL = 0
        AND VS.OBJ_ID = :OBJECT_ID
        AND VS.VAL LIKE '%' || :V$TEMP || '%'
        INTO :V$TEMP;

        IF (:V$TEMP = 0) THEN
        BEGIN
            ERROR_TEXT = 'Номер ОУ не содержится в полном наименовании ОУ!';
            ERROR_NAME = :ERROR_TEXT;
            PARAMS_NAME = 'Полное наименование ОУ';
            ERROR_TYPE = 2;
            SUSPEND;
        END
    END

    -- 8 --
    V$TEMP = NULL;
    SELECT COUNT(VLL.LISTVAL_ID)
    FROM VALL VLL
    WHERE VLL.PARAM_ID IN (10, 11)
    AND VLL.IS_DEL = 0
    AND VLL.OBJ_ID = :OBJECT_ID
    INTO :V$TEMP;
    IF (:V$TEMP < 2) THEN
    BEGIN
        ERROR_TEXT = 'Поля «Тип ОУ» и «Вид ОУ» должны быть заполнены';
        ERROR_NAME = :ERROR_TEXT;
        PARAMS_NAME = 'Тип ОУ, Вид ОУ';
        ERROR_TYPE = 3;
        SUSPEND;
    END

    -- 11 --
    V$TEMP = NULL;
    SELECT COUNT(VS.VAL)
    FROM VALS VS
    WHERE VS.PARAM_ID = 28
    AND VS.IS_DEL = 0
    AND VS.OBJ_ID = :OBJECT_ID
    AND TRIM(VS.VAL) > ''
    INTO :V$TEMP;

    IF (:V$TEMP = 0) THEN
    BEGIN
        ERROR_TEXT = 'Поле «Телефон руководителя» должно быть заполнено!';
        ERROR_NAME = :ERROR_TEXT;
        PARAMS_NAME = 'Телефон руководителя';
        ERROR_TYPE = 3;
        SUSPEND;
    END
    ELSE
    BEGIN
        SELECT COUNT(VS.VAL)
        FROM VALS VS
        WHERE VS.IS_DEL = 0
        AND VS.PARAM_ID = 28
        AND VS.OBJ_ID = :OBJECT_ID
        AND VS.VAL SIMILAR TO '[0-9]{1}\-[0-9]{3}\-[0-9]{2,3}\-[0-9]{2}\-[0-9]{2}' ESCAPE '\'
        INTO :V$TEMP;

        IF (:V$TEMP = 0) THEN
        BEGIN
            ERROR_TEXT = 'Поле «Телефон руководителя» заполнено некорректно (не соответствует маске ввода)';
            ERROR_NAME = :ERROR_TEXT;
            PARAMS_NAME = 'Телефон руководителя';
            ERROR_TYPE = 2;
            SUSPEND;
        END
    END

    -- 9 --
/*    V$TEMP = NULL;
    SELECT VI.VAL
    FROM VALI VI
    WHERE VI.PARAM_ID = 12
    AND VI.OBJ_ID = :OBJECT_ID
    AND VI.IS_DEL = 0
    INTO :V$TEMP;

    IF ((V$TEMP IS NULL) OR (:V$TEMP < 0)) THEN
    BEGIN
        ERROR_TEXT = 'Поле «Проектная мощность (чел.)» должно быть заполнено';
        ERROR_NAME = :ERROR_TEXT;
        PARAMS_NAME = 'Проектная мощность (чел.)';
        ERROR_TYPE = 3;
        SUSPEND;
    END*/

    -- 10 --
    SELECT TRIM(V)
    FROM VAL_GET(:OBJECT_ID, 27, 0, :I$USER_ID)
    INTO :V$VALS;

    IF (V$VALS <> '') THEN
    BEGIN
        V$VALS = NULL;
        SELECT FIRST 1 TRIM(VA.REGION)
        FROM VALA VA
        WHERE VA.PARAM_ID = 27
        AND VA.OBJ_ID = :OBJECT_ID
        AND VA.IS_DEL = 0
        INTO :V$VALS;

        IF (V$VALS IS NULL) THEN
        BEGIN
            V$VALS = '';
        END

        IF (V$VALS = '') THEN
        BEGIN
            ERROR_TEXT = 'Значение поля «Регион» в юридическом адресе ОУ не может быть пустым!';
            ERROR_NAME = :ERROR_TEXT;
            PARAMS_NAME = 'Юридический адрес';
            ERROR_TYPE = 3;
        END
        ELSE IF (:V$VALS != 'Санкт-Петербург г') THEN
        BEGIN
            ERROR_TEXT = 'Поле «Регион» в юридическом адресе ОУ ="' || :V$VALS || '", Вы уверены?';
            ERROR_NAME = 'Поле «Регион» в юридическом адресе ОУ <> "Санкт-Петербург г", Вы уверены?';
            PARAMS_NAME = 'Юридический адрес';
            ERROR_TYPE = 2;
            SUSPEND;
        END
        ELSE
        BEGIN
            SELECT COUNT(VA.DISTRICT)
            FROM VALA VA
            WHERE VA.PARAM_ID = 27
            AND VA.OBJ_ID = :OBJECT_ID
            AND VA.IS_DEL = 0
            AND VA.DISTRICT > ''
            INTO :V$TEMP;
    
            IF (:V$TEMP > 0) THEN
            BEGIN
                UPDATE VALA VA
                SET VA.DISTRICT = NULL
                WHERE VA.PARAM_ID = 27
                AND VA.OBJ_ID = :OBJECT_ID;
                ERROR_TEXT = 'Поле «Район» в юридическом адресе должно быть пустым. Поле было очищено.';
                ERROR_NAME = :ERROR_TEXT;
                PARAMS_NAME = 'Юридический адрес';
                ERROR_TYPE = 1;
                SUSPEND;
            END
        END
        SELECT FIRST 1 VLL.LISTVAL_ID
        FROM VALL VLL
        WHERE VLL.PARAM_ID = 8
        AND VLL.IS_DEL = 0
        AND VLL.OBJ_ID = :OBJECT_ID
        INTO :V$TEMP;
    
        IF (:V$TEMP != 1734) THEN
        BEGIN
            UPDATE VALA VA
            SET VA.FLAT = ''
            WHERE VA.PARAM_ID = 27
            AND VA.OBJ_ID = :OBJECT_ID
            AND VA.IS_DEL = 0
            AND VA.FLAT > '';
    
            IF (ROW_COUNT > 0) THEN
            BEGIN
                ERROR_TEXT = 'Поле «Квартира» в юридическом адресе государственного ОУ должно быть пустым. Поле было очищено.';
                ERROR_NAME = :ERROR_TEXT;
                PARAMS_NAME = 'Юридический адрес';
                ERROR_TYPE = 1;
                SUSPEND;
            END
        END

        IF (EXISTS(
            SELECT FIRST 1 1
            FROM VALA VA
            WHERE VA.PARAM_ID = 27
            AND VA.OBJ_ID = :OBJECT_ID
            AND VA.IS_DEL = 0
            AND ((VA.STREET = '') OR (VA.STREET IS NULL))
        )) THEN
        BEGIN
            ERROR_TEXT = 'Значение поля «Улица» в юридическом адресе ОУ не может быть пустым!';
            ERROR_NAME = :ERROR_TEXT;
            PARAMS_NAME = 'Юридический адрес';
            ERROR_TYPE = 3;
            SUSPEND;
        END
    
        IF (EXISTS(
            SELECT FIRST 1 1
            FROM VALA VA
            WHERE VA.PARAM_ID = 27
            AND VA.OBJ_ID = :OBJECT_ID
            AND VA.IS_DEL = 0
            AND ((VA.POST_INDEX = '') OR (VA.POST_INDEX IS NULL))
        )) THEN
        BEGIN
            ERROR_TEXT = 'Значение поля «Индекс» в юридическом адресе ОУ не может быть пустым!';
            ERROR_NAME = :ERROR_TEXT;
            PARAMS_NAME = 'Юридический адрес';
            ERROR_TYPE = 3;
            SUSPEND;
        END
    END
    ELSE
    BEGIN
        ERROR_TEXT = 'Поле «Юридический адрес» должно быть заполнено!';
        ERROR_NAME = :ERROR_TEXT;
        PARAMS_NAME = 'Юридический адрес';
        ERROR_TYPE = 3;
        SUSPEND;
    END
    -- 12 --

    V$TEMP = NULL;
    SELECT COUNT(VS.VAL)
    FROM VALS VS
    WHERE VS.PARAM_ID = 29
    AND VS.IS_DEL = 0
    AND VS.OBJ_ID = :OBJECT_ID
    AND VS.VAL > ''
    INTO :V$TEMP;

    IF (:V$TEMP > 0) THEN
    BEGIN
        SELECT COUNT(VS.VAL)
        FROM VALS VS
        WHERE VS.IS_DEL = 0
        AND VS.PARAM_ID = 29
        AND VS.OBJ_ID = :OBJECT_ID
        AND VS.VAL SIMILAR TO '[0-9]{1}\-[0-9]{3}\-[0-9]{2,3}\-[0-9]{2}\-[0-9]{2}' ESCAPE '\'
        INTO :V$TEMP;

        IF (:V$TEMP = 0) THEN
        BEGIN
            ERROR_TEXT = 'Поле «Телефон приемной» заполнено некорректно (не соответствует маске ввода!';
            ERROR_NAME = :ERROR_TEXT;
            PARAMS_NAME = 'Телефон приемной';
            ERROR_TYPE = 2;
            SUSPEND;
        END
    END

    -- 13 --
    V$TEMP = NULL;
    SELECT COUNT(VS.VAL)
    FROM VALS VS
    WHERE VS.PARAM_ID = 30
    AND VS.IS_DEL = 0
    AND VS.OBJ_ID = :OBJECT_ID
    AND VS.VAL > ''
    INTO :V$TEMP;

    IF (:V$TEMP > 0) THEN
    BEGIN
        SELECT COUNT(VS.VAL)
        FROM VALS VS
        WHERE VS.IS_DEL = 0
        AND VS.PARAM_ID = 30
        AND VS.OBJ_ID = :OBJECT_ID
        AND VS.VAL SIMILAR TO '[0-9]{1}\-[0-9]{3}\-[0-9]{2,3}\-[0-9]{2}\-[0-9]{2}' ESCAPE '\'
        INTO :V$TEMP;

        IF (:V$TEMP = 0) THEN
        BEGIN
            ERROR_TEXT = 'Поле «Факс» заполнено некорректно (не соответствует маске ввода)';
            ERROR_NAME = :ERROR_TEXT;
            PARAMS_NAME = 'Факс';
            ERROR_TYPE = 2;
            SUSPEND;
        END
    END

    -- 14 --
    V$TEMP = NULL;
    SELECT COUNT(VS.VAL)
    FROM VALS VS
    WHERE VS.PARAM_ID = 31
    AND VS.IS_DEL = 0
    AND VS.OBJ_ID = :OBJECT_ID
    AND VS.VAL > ''
    INTO :V$TEMP;

    IF (:V$TEMP > 0) THEN
    BEGIN
        SELECT COUNT(VS.VAL)
        FROM VALS VS
        WHERE VS.IS_DEL = 0
        AND VS.PARAM_ID = 31
        AND VS.OBJ_ID = :OBJECT_ID
        AND VS.VAL SIMILAR TO '[0-9]{1}\-[0-9]{3}\-[0-9]{2,3}\-[0-9]{2}\-[0-9]{2}' ESCAPE '\'
        INTO :V$TEMP;

        IF (:V$TEMP = 0) THEN
        BEGIN
            ERROR_TEXT = 'Поле «Телефон главного бухгалтера» заполнено некорректно (не соответствует маске ввода)';
            ERROR_NAME = :ERROR_TEXT;
            PARAMS_NAME = 'Телефон главного бухгалтера';
            ERROR_TYPE = 2;
            SUSPEND;
        END
    END

    -- 15 --
    V$VALS = NULL;
    SELECT V
    FROM VAL_GET(:OBJECT_ID, 35, 0, :I$USER_ID)
    INTO :V$VALS;
    V$TVALS = REPLACE(TRIM(V$VALS), ' ', '');
    WHILE(V$TVALS <> V$VALS) DO
    BEGIN
        V$TVALS2 = V$TVALS;
        V$TVALS = REPLACE(TRIM(V$TVALS), ' ', '');
        IF (V$TVALS2 = V$TVALS) THEN
        BEGIN
            BREAK;
        END
    END

    IF (V$TVALS <> V$VALS) THEN
    BEGIN
        SELECT BLOB_ID
        FROM VAL_ADD(35, :OBJECT_ID, :V$TVALS)
        INTO :V$BLOB_ID;
    
        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:OBJECT_ID, NULL, NULL, :I$USER_ID)
        INTO :V$TVALS;

        ERROR_TEXT = 'Поле «Электронная почта» объекта «' || V$TVALS || '» исправлено.';
        ERROR_NAME = 'Поле «Электронная почта» объекта исправлено.';
        PARAMS_NAME = 'Электронная почта';
        ERROR_TYPE = 1;
        SUSPEND;
    END

    V$TEMP = NULL;
    SELECT COUNT(VS.VAL)
    FROM VALS VS
    WHERE VS.PARAM_ID = 35
    AND VS.IS_DEL = 0
    AND VS.OBJ_ID = :OBJECT_ID
    AND VS.VAL > ''
    INTO :V$TEMP;

    IF (:V$TEMP > 0) THEN
    BEGIN
        SELECT COUNT(VS.VAL)
        FROM VALS VS
        WHERE VS.IS_DEL = 0
        AND VS.PARAM_ID = 35
        AND VS.OBJ_ID = :OBJECT_ID
        AND VS.VAL SIMILAR TO '[0-9a-zа-я_.\-]{2,}@[0-9a-zа-я_.\-]{2,}' ESCAPE '\'
        INTO :V$TEMP;
        IF (:V$TEMP = 0) THEN
        BEGIN
            ERROR_TEXT = '«Электронная почта» заполнено некорректно (не соответствует маске ввода)';
            ERROR_NAME = :ERROR_TEXT;
            PARAMS_NAME = 'Электронная почта';
            ERROR_TYPE = 2;
            SUSPEND;
        END
    END

    -- 16 --
    IF (NOT EXISTS(
        SELECT FIRST 1 1
        FROM R_SPB_POST_DIRECTOR(:I$OBJ_ID, :I$USER_ID)
    )) THEN
    BEGIN
        ERROR_TEXT = 'Не указан действующий (исполняющий обязанности) руководитель ОУ';
        ERROR_NAME = :ERROR_TEXT;
        PARAMS_NAME = 'Руководитель образовательного учереждения';
        ERROR_TYPE = 3;
        SUSPEND;
    END

    -- 17 --
    V$TEMP = NULL;
    SELECT COUNT(L51.OBJ_ID)
    FROM LINKS L51
    WHERE L51.PARENT_ID = :OBJECT_ID
    AND L51.OBJ_TYPE_ID = 51
    AND L51.DATE_DEL IS NULL
    INTO :V$TEMP;

    IF (EXISTS(
        SELECT FIRST 1 1
        FROM VALL VLL
        WHERE VLL.PARAM_ID = 10
        AND VLL.IS_DEL = 0
        AND VLL.LISTVAL_ID IN (964, 2212, 970, 959, 960)
        AND VLL.OBJ_ID = :OBJECT_ID
    )) THEN
    BEGIN
        IF (V$TEMP = 0) THEN
        BEGIN
            ERROR_TEXT = 'Не указаны предметы, изучаемые углубленно';
            ERROR_NAME = :ERROR_TEXT;
            PARAMS_NAME = 'Предмет';
            ERROR_TYPE = 2;
            SUSPEND;
        END
    END
    ELSE IF (V$TEMP > 0) THEN
    BEGIN
        SELECT V
        FROM VAL_GET(:OBJECT_ID, 10, 0, :I$USER_ID)
        INTO :ERROR_NAME;

        ERROR_TEXT = 'Для ОУ вида «' || ERROR_NAME || '» список «Углубленное изучение предметов» должен быть пуст';
        ERROR_NAME = :ERROR_TEXT;
        PARAMS_NAME = 'Углубленное изучение предметов';
        ERROR_TYPE = 2;
        SUSPEND;
    END

    IF (:V$TEMP > 10) THEN
    BEGIN
        ERROR_TEXT = 'Список предметов, изучаемых углубленно, не может содержать более 10 предметов';
        ERROR_NAME = :ERROR_TEXT;
        PARAMS_NAME = 'Предмет';
        ERROR_TYPE = 2;
        SUSPEND;
    END
    -- 18 --
    IF (NOT EXISTS(
        SELECT FIRST 1 1
        FROM LINKS L73
        INNER JOIN LINKS L16 ON (L16.PARENT_ID = L73.OBJ_ID)
        WHERE L73.DATE_DEL IS NULL
        AND L73.PARENT_ID = :OBJECT_ID
        AND L73.OBJ_TYPE_ID = 73
        AND L16.OBJ_TYPE_ID = 16
        AND L16.DATE_DEL IS NULL
    )) THEN
    BEGIN
        ERROR_TEXT = 'Должно быть введено хотя бы одно здание образовательного учреждения';
        ERROR_NAME = :ERROR_TEXT;
        PARAMS_NAME = 'Здание';
        ERROR_TYPE = 3;
        SUSPEND;
    END
    -- 19 --
    FOR
        SELECT L16.OBJ_ID, L16.LINK_ID
        FROM LINKS L73
        INNER JOIN LINKS L16 ON L16.PARENT_ID = L73.OBJ_ID
        WHERE L73.DATE_DEL IS NULL
        AND L73.PARENT_ID = :OBJECT_ID
        AND L73.OBJ_TYPE_ID = 73
        AND L16.OBJ_TYPE_ID = 16
        AND L16.DATE_DEL IS NULL
        INTO :OBJECT_ID, :LINK_ID
    DO
    BEGIN
        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:OBJECT_ID, NULL, NULL, :I$USER_ID)
        INTO :V$VALS;

        -- проверки - отчет заполненности для НИП
        ERROR_NAME = V$VALS;
        ERROR_TYPE = 5;

        FOR
            SELECT R.VAL
            FROM PARAMS P
            
            JOIN LPARAMS LP
            ON LP.PARAM_ID = P.PARAM_ID
            AND LP.IS_DEL = 0
            AND LP.LEVEL_ID IN (15, /* Apostrof */ 297)
            
            JOIN RES R
            ON R.RES_ID = P.RES_ID
            AND R.LANG_CODE = 'RU'
            
            LEFT JOIN VAL_GET(:OBJECT_ID, P.PARAM_ID, 0, :I$USER_ID) VL
            ON 1=1

            WHERE P.TYPE_ID = 16
            AND P.IS_DEL = 0
            AND P.PARAM_ID IN (504, 505, 542, 508, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 509, 510, 511, 512, 520, 522, 521)
            AND VL.V = ''

            INTO :V$TVALS
        DO
        BEGIN
            ERROR_TEXT = 'Не заполнено поле «' || :V$TVALS || '» для здания «' || :V$VALS || '»';
            PARAMS_NAME = V$TVALS;
            SUSPEND;
        END
        --

        V$TVALS = NULL;
        SELECT V
        FROM VAL_GET(:OBJECT_ID, 485, 0, :I$USER_ID)
        INTO :V$TVALS;

        IF (V$TVALS = '') THEN
        BEGIN
            ERROR_TEXT = 'Поле «Назначение здания» для здания «' || :V$VALS || '» должно быть заполнено!';
            ERROR_NAME = 'Поле «Назначение здания» для здания должно быть заполнено!';
            PARAMS_NAME = 'Назначение здания';
            ERROR_TYPE = 3;
            SUSPEND;
        END

        -- Данные по спортплощадкам и стадионам вынесены в отдельную сущность
        /*V$TVALS = NULL;
        SELECT V
        FROM VAL_GET(:OBJECT_ID, 1441, 0, :I$USER_ID)
        INTO :V$TVALS;

        IF (V$TVALS = '') THEN
        BEGIN
            ERROR_TEXT = 'Поле «Наличие стадиона с естественным покрытием» для здания «' || :V$VALS || '» должно быть заполнено!';
            ERROR_NAME = 'Поле «Наличие стадиона с естественным покрытием» для здания должно быть заполнено!';
            PARAMS_NAME = 'Наличие стадиона с естественным покрытием';
            ERROR_TYPE = 3;
            SUSPEND;
        END

        V$TVALS = NULL;
        SELECT V
        FROM VAL_GET(:OBJECT_ID, 1443, 0, :I$USER_ID)
        INTO :V$TVALS;

        IF (V$TVALS = '') THEN
        BEGIN
            ERROR_TEXT = 'Поле «Наличие стадиона с искусственным покрытием» для здания «' || :V$VALS || '» должно быть заполнено!';
            ERROR_NAME = 'Поле «Наличие стадиона с искусственным покрытием» для здания должно быть заполнено!';
            PARAMS_NAME = 'Наличие стадиона с искусственным покрытием';
            ERROR_TYPE = 3;
            SUSPEND;
        END

        V$TVALS = NULL;
        SELECT V
        FROM VAL_GET(:OBJECT_ID, 1446, 0, :I$USER_ID)
        INTO :V$TVALS;

        IF (V$TVALS = '') THEN
        BEGIN
            ERROR_TEXT = 'Поле «Наличие спортплощадки» для здания «' || :V$VALS || '» должно быть заполнено!';
            ERROR_NAME = 'Поле «Наличие спортплощадки» для здания должно быть заполнено!';
            PARAMS_NAME = 'Наличие спортплощадки';
            ERROR_TYPE = 3;
            SUSPEND;
        END*/

        IF (:V$VALS = '<  ...  >') THEN
        BEGIN
            ERROR_TEXT = 'Не указано название здания, обозначенного как "<  ...  >"';
            ERROR_NAME = 'Поле «Название» для здания должно быть заполнено';
            PARAMS_NAME = '«Название»';
            ERROR_TYPE = 3;
            SUSPEND;
        END
        ELSE
        BEGIN
            IF (NOT EXISTS(
                SELECT FIRST 1 1
                FROM VALA V
                WHERE V.PARAM_ID = 420
                AND V.OBJ_ID = :OBJECT_ID
                AND V.IS_DEL = 0
            )) THEN
            BEGIN
                ERROR_TEXT = 'Не указан адрес для здания «' || :V$VALS || '»!';
                ERROR_NAME = 'Не указан адрес для здания!';
                PARAMS_NAME = 'Адрес';
                ERROR_TYPE = 3;
                SUSPEND;
            END
            ELSE
            BEGIN
                IF (NOT EXISTS(
                    SELECT FIRST 1 1
                    FROM VALA VA
                    WHERE VA.PARAM_ID = 420
                    AND VA.OBJ_ID = :OBJECT_ID
                    AND VA.IS_DEL = 0
                    AND TRIM(COALESCE(VA.STREET,'')) != ''
                )) THEN
                BEGIN
                    ERROR_TEXT = 'Значение поля «Улица» в адресе здания «' || :V$VALS || '» не заполнено!';
                    ERROR_NAME = 'Значение поля «Улица» в адресе здания не заполнено!';
                    PARAMS_NAME = 'Адрес';
                    ERROR_TYPE = 2;
                    SUSPEND;
                END

                IF (NOT EXISTS(
                    SELECT FIRST 1 1
                    FROM VALA VA
                    WHERE VA.PARAM_ID = 420
                    AND VA.OBJ_ID = :OBJECT_ID
                    AND VA.IS_DEL = 0
                    AND TRIM(COALESCE(VA.POST_INDEX,'')) != ''
                )) THEN
                BEGIN
                    ERROR_TEXT = 'Значение поля «Индекс» в адресе здания «' || :V$VALS || '» не может быть пустым!';
                    ERROR_NAME = 'Значение поля «Индекс» в адресе здания не может быть пустым!';
                    PARAMS_NAME = 'Адрес';
                    ERROR_TYPE = 3;
                    SUSPEND;
                END
            END
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE COLLEGE_VERIFY_PUPIL (
    I$OBJ_ID BIGINT)
RETURNS (
    LINK_ID BIGINT,
    OBJECT_ID BIGINT,
    NAME_TASK VARCHAR(1000),
    ERROR_NAME VARCHAR(1000),
    PARAMS_NAME VARCHAR(1000),
    ERROR_TEXT VARCHAR(1000),
    ERROR_TYPE SMALLINT)
AS
declare variable OBJ_ID bigint;
declare variable PARAM_ID bigint;
declare variable I integer;
declare variable CLASS varchar(1000);
declare variable FIO varchar(1000);
declare variable V varchar(4000);
declare variable Y integer;
declare variable M integer;
BEGIN
    NAME_TASK = 'Личные дела обучающихся, воспитанников ';
    ERROR_TYPE = 1;

    M = EXTRACT(MONTH FROM CURRENT_DATE);
    Y = EXTRACT(YEAR FROM CURRENT_DATE);
    IF (M < 9) THEN
    BEGIN
        Y = Y - 1;
    END

    FOR
        SELECT L82.OBJ_ID,
               L10.OBJ_ID,
               L10.LINK_ID

        FROM LINKS L78

        JOIN LINKS L82
        ON L82.PARENT_ID = L78.OBJ_ID
        AND L82.OBJ_TYPE_ID = 82
        AND L82.DATE_DEL IS NULL

        JOIN VALI V448
        ON V448.OBJ_ID = L82.OBJ_ID
        AND V448.PARAM_ID = 448
        AND V448.IS_DEL = 0
        AND V448.VAL = :Y

        JOIN LINKS L10
        ON L10.PARENT_ID = L82.OBJ_ID
        AND L10.OBJ_TYPE_ID = 10
        AND L10.DATE_DEL IS NULL

        WHERE L78.PARENT_ID = :I$OBJ_ID
        AND L78.OBJ_TYPE_ID = 78
        AND L78.DATE_DEL IS NULL

        INTO :OBJ_ID,
             :OBJECT_ID,
             :LINK_ID
    DO
    BEGIN
        IF (EXISTS(
            SELECT FIRST 1 1
            FROM VAL_GET(:OBJECT_ID, 105)
            WHERE V = ''
        )) THEN
        BEGIN
            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:OBJ_ID)
            INTO :CLASS;
    
            SELECT C1
            FROM BUILD_REP_FIO(:OBJECT_ID, 55, 56, 57, 0)
            INTO FIO;

            ERROR_NAME = 'Не заполнено поле «Выбыл(а) в»';
            ERROR_TEXT = 'Не заполнено поле «Выбыл(а) в» для учащегося «' || :FIO || '» выбывшего в «' || :CLASS || '»';
            PARAMS_NAME = 'Выбыл(а) в';
            ERROR_TYPE = 5;
            SUSPEND;
        END
    END

    FOR
        SELECT L83.OBJ_ID,
               L10.OBJ_ID,
               L10.LINK_ID

        FROM LINKS L78

        JOIN LINKS L83
        ON L83.PARENT_ID = L78.OBJ_ID
        AND L83.OBJ_TYPE_ID = 83
        AND L83.DATE_DEL IS NULL

        JOIN VALI V451
        ON V451.OBJ_ID = L83.OBJ_ID
        AND V451.PARAM_ID = 451
        AND V451.IS_DEL = 0
        AND V451.VAL = :Y

        JOIN LINKS L10
        ON L10.PARENT_ID = L83.OBJ_ID
        AND L10.OBJ_TYPE_ID = 10
        AND L10.DATE_DEL IS NULL

        WHERE L78.PARENT_ID = :I$OBJ_ID
        AND L78.OBJ_TYPE_ID = 78
        AND L78.DATE_DEL IS NULL

        INTO :OBJ_ID,
             :OBJECT_ID,
             :LINK_ID
    DO
    BEGIN
        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:OBJ_ID)
        INTO :CLASS;
    
        SELECT C1
        FROM BUILD_REP_FIO(:OBJECT_ID, 55, 56, 57, 0)
        INTO FIO;

        IF (NOT EXISTS(
            SELECT FIRST 1 1
            FROM LINKS L11

            WHERE L11.PARENT_ID = :OBJECT_ID
            AND L11.OBJ_TYPE_ID = 11
            AND L11.DATE_DEL IS NULL
        )) THEN
        BEGIN
            ERROR_NAME = 'Не введены данные документа об образовании';
            ERROR_TEXT = 'Не введены данные документа об образовании для учащегося «' || :FIO || '» в «' || :CLASS || '»';
            PARAMS_NAME = 'Документ об образовании';
            ERROR_TYPE = 5;
            SUSPEND;
        END
        ELSE
        BEGIN
            FOR
                SELECT L11.OBJ_ID
                FROM LINKS L11

                WHERE L11.PARENT_ID = :OBJECT_ID
                AND L11.OBJ_TYPE_ID = 11
                AND L11.DATE_DEL IS NULL

                INTO :PARAM_ID
            DO
            BEGIN
                FOR
                    SELECT R.VAL
                    FROM PARAMS P
                    
                    JOIN LPARAMS LP
                    ON LP.PARAM_ID = P.PARAM_ID
                    AND LP.IS_DEL = 0
                    AND LP.LEVEL_ID = 23
                    
                    JOIN RES R
                    ON R.RES_ID = P.RES_ID
                    AND R.LANG_CODE = 'RU'
                    
                    LEFT JOIN VAL_GET(:PARAM_ID, P.PARAM_ID) VL
                    ON 1=1
        
                    WHERE P.TYPE_ID = 11
                    AND P.IS_DEL = 0
                    AND P.PARAM_ID IN (50, 564, 565, 566)
                    AND VL.V = ''
        
                    INTO :V
                DO
                BEGIN
                    ERROR_TEXT = 'У документа об образовании не заполнено поле «' || :V || '» для учащегося «' || :FIO || '» в «' || :CLASS || '»';
                    ERROR_NAME = 'У документа об образовании не заполнено поле «' || :V || '»';
                    PARAMS_NAME = V;
                    ERROR_TYPE = 5;
                    SUSPEND;
                END
            END
        END
    END

    FOR
        SELECT L9.OBJ_ID, L10.OBJ_ID, L10.LINK_ID

        FROM LINKS L7

        JOIN LINKS L8
        ON L8.PARENT_ID = L7.OBJ_ID
        AND L8.OBJ_TYPE_ID = 8
        AND L8.DATE_DEL IS NULL

        JOIN LINKS L9
        ON L9.PARENT_ID = L8.OBJ_ID
        AND L9.OBJ_TYPE_ID IN (9, 187)
        AND L9.DATE_DEL IS NULL

        JOIN LINKS L10
        ON L10.PARENT_ID = L9.OBJ_ID
        AND L10.OBJ_TYPE_ID = 10
        AND L10.DATE_DEL IS NULL

        WHERE L7.PARENT_ID = :I$OBJ_ID
        AND L7.OBJ_TYPE_ID = 7
        AND L7.DATE_DEL IS NULL

        INTO :OBJ_ID, :OBJECT_ID, :LINK_ID
    DO
    BEGIN
        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:OBJ_ID)
        INTO :CLASS;

        SELECT C1
        FROM BUILD_REP_FIO(:OBJECT_ID, 55, 56, 57, 0)
        INTO FIO;

        -- проверки - отчет заполненности для НИП
        ERROR_TYPE = 5;

        FOR
            SELECT R.VAL, P.PARAM_ID
            FROM PARAMS P
            
            JOIN LPARAMS LP
            ON LP.PARAM_ID = P.PARAM_ID
            AND LP.IS_DEL = 0
            AND LP.LEVEL_ID = 50
            
            JOIN RES R
            ON R.RES_ID = P.RES_ID
            AND R.LANG_CODE = 'RU'
            
            LEFT JOIN VAL_GET(:OBJECT_ID, P.PARAM_ID) VL
            ON 1=1

            WHERE P.TYPE_ID = 10
            AND P.IS_DEL = 0
            AND P.PARAM_ID IN (108, 1343, 1409, 80, 176, 208, 78, 101, 103, 111)
            AND VL.V = ''

            INTO :V, :PARAM_ID
        DO
        BEGIN
            IF ((PARAM_ID <> 101) OR EXISTS(
                SELECT FIRST 1 1
                FROM ADR_GET(103, :OBJECT_ID)
                WHERE REGION LIKE 'Санкт-Петербург%'
            )) THEN
            BEGIN
                ERROR_NAME = 'Не заполнено поле «' || :V || '»';
                ERROR_TEXT = 'Не заполнено поле «' || :V || '» для учащегося «' || :CLASS || '» класса «' || :FIO || '»';
                PARAMS_NAME = V;
                SUSPEND;
            END
        END

        -- 2 --
        SELECT COUNT(VLL.LISTVAL_ID)
        FROM VALL VLL
        WHERE VLL.PARAM_ID = 88
        AND VLL.IS_DEL = 0
        AND VLL.OBJ_ID = :OBJECT_ID
        INTO :I;
        IF (:I = 0) THEN
        BEGIN
            ERROR_TEXT = 'Поле «ПОЛ» для учащегося «' || :CLASS || '» класса «' || :FIO || '» должно быть заполнено.';
            ERROR_NAME = 'Поле «ПОЛ» для учащегося должно быть заполнено.';
            PARAMS_NAME = 'Пол';
            ERROR_TYPE = 3;
            SUSPEND;
        END
        -- 3 --
        SELECT COUNT(VD.VAL)
        FROM VALD VD
        WHERE VD.PARAM_ID = 89
        AND VD.IS_DEL = 0
        AND VD.OBJ_ID = :OBJECT_ID
        INTO :I;
        IF (:I = 0) THEN
        BEGIN
            ERROR_TEXT = 'Поле «Дата рождения » для учащегося «' || :CLASS || '» класса «' || :FIO || '» должно быть заполнено.';
            ERROR_NAME = 'Поле «Дата рождения » для учащегося должно быть заполнено.';
            PARAMS_NAME = 'Дата рождения';
            ERROR_TYPE = 3;
            SUSPEND;
        END
        -- 4 --
        SELECT COUNT(VLL.LISTVAL_ID)
        FROM VALL VLL
        WHERE VLL.PARAM_ID = 91
        AND VLL.IS_DEL = 0
        AND VLL.OBJ_ID = :OBJECT_ID
        INTO :I;
        IF (:I = 0) THEN
        BEGIN
            ERROR_TEXT = 'Поле «Гражданство» для учащегося «' || :CLASS || '» класса «' || :FIO || '» должно быть заполнено.';
            ERROR_NAME = 'Поле «Гражданство» для учащегося должно быть заполнено.';
            PARAMS_NAME = 'Гражданство';
            ERROR_TYPE = 3;
            SUSPEND;
        END
        -- 5 --
      /*  SELECT COUNT(VS.VAL)
        FROM VALS VS
        WHERE VS.PARAM_ID = 1343
        AND VS.IS_DEL = 0
        AND VS.OBJ_ID = :OBJECT_ID
        INTO :I;
        IF (:I = 0) THEN
        BEGIN
            ERROR_TEXT = 'Поле «Место рождения» для учащегося «' || :CLASS || '» класса «' || :FIO || '» должно быть заполнено.';
            ERROR_NAME = 'Поле «Место рождения» для учащегося должно быть заполнено.';
            PARAMS_NAME = 'Место рождения';
            ERROR_TYPE = 2;
            SUSPEND;
        END  */
        -- 6 --
        SELECT COUNT(VLL.LISTVAL_ID)
        FROM VALL VLL
        WHERE VLL.PARAM_ID = 127
        AND VLL.IS_DEL = 0
        AND VLL.OBJ_ID = :OBJECT_ID
        INTO :I;
        IF (:I = 0) THEN
        BEGIN
            ERROR_TEXT = 'Поле «Родной язык» для учащегося «' || :CLASS || '» класса «' || :FIO || '» должно быть заполнено.';
            ERROR_NAME = 'Поле «Родной язык» для учащегося должно быть заполнено.';
            PARAMS_NAME = 'Родной язык';
            ERROR_TYPE = 3;
            SUSPEND;
        END

        -- 8 --
        SELECT COUNT(L79.OBJ_ID)
        FROM LINKS L79
        WHERE L79.OBJ_TYPE_ID = 79
        AND L79.PARENT_ID = :OBJECT_ID
        AND L79.DATE_DEL IS NULL
        INTO :I;

        IF (:I = 0) THEN
        BEGIN
            ERROR_TEXT = 'Для учащегося «' || :CLASS || '» класса «' || :FIO || '» не введены данные документа, удостоверяющего личность';
            ERROR_NAME = 'Для учащегося не введены данные документа, удостоверяющего личность';
            PARAMS_NAME = 'Документ удостоверяющий личность';
            ERROR_TYPE = 2;
            SUSPEND;
        END

        -- 12 --
/*        SELECT COUNT(*)
        FROM VALS VLL
        WHERE VLL.OBJ_ID = :OBJECT_ID
        AND VLL.PARAM_ID = 1409
        AND VLL.IS_DEL = 0
        INTO :I;
        IF (:I = 0) THEN
        BEGIN
            ERROR_TEXT = 'Для учащегося «' || :CLASS || '» класса «' || :FIO || '» не заполнено поле СНИЛС.';
            ERROR_NAME = 'Для учащегося не заполнено поле СНИЛС.';
            PARAMS_NAME = 'Документ';
            ERROR_TYPE = 2;
            SUSPEND;
        END*/

        FOR
            SELECT VLL.VAL
            FROM VALS VLL

            LEFT JOIN CHECK_SNILS(VLL.VAL) CS ON 1=1

            WHERE VLL.OBJ_ID = :OBJECT_ID
            AND VLL.PARAM_ID = 1409
            AND VLL.IS_DEL = 0
            AND CS.IS_REAL = 0
            INTO :V
        DO
        BEGIN
            IF (:I > 0) THEN
            BEGIN
                ERROR_TEXT = 'Для учащегося «' || :FIO || '» «' || :CLASS || '» введен неверный СНИЛС «' || V || '».';
                ERROR_NAME = 'Для учащегося введен неверный СНИЛС.';
                PARAMS_NAME = 'Документ';
                ERROR_TYPE = 3;
                SUSPEND;
            END
        END


        --7 --
        FOR
            SELECT L79.OBJ_ID,
                   (SELECT COUNT(VS.VAL)
                    FROM VALS VS
                    WHERE VS.PARAM_ID IN (442, 559, 562, 563)
                    AND VS.IS_DEL = 0
                    AND VS.OBJ_ID = L79.OBJ_ID
                   ) +
                   (SELECT COUNT(VLL.LISTVAL_ID)
                    FROM VALL VLL
                    WHERE VLL.PARAM_ID = 441
                    AND VLL.IS_DEL = 0
                    AND VLL.OBJ_ID = L79.OBJ_ID
                   ) +
                   (SELECT COUNT(VD.VAL)
                    FROM VALD VD
                    WHERE VD.PARAM_ID IN (560, 561)
                    AND VD.IS_DEL = 0
                    AND VD.OBJ_ID = L79.OBJ_ID
                   ) +
                   (SELECT COUNT(VB.VAL)
                    FROM VALB VB
                    WHERE VB.PARAM_ID = 576
                    AND VB.IS_DEL = 0
                    AND VB.OBJ_ID = L79.OBJ_ID
                   )
            FROM LINKS L79
            WHERE L79.OBJ_TYPE_ID = 79
            AND L79.PARENT_ID = :OBJECT_ID
            AND L79.DATE_DEL IS NULL
            INTO :OBJ_ID, :I
        DO
        BEGIN
            IF (:I = 0) THEN
            BEGIN
                UPDATE LINKS L
                SET L.DATE_DEL = CURRENT_TIMESTAMP
                WHERE L.OBJ_ID = :OBJ_ID
                AND L.OBJ_TYPE_ID = 79
                AND DATE_DEL IS NULL;
                ERROR_TEXT = 'Для учащегося «' || :CLASS || '» класса «' || :FIO || '» удалены пустые записи в поле Документ удостоверяющий личность.';
                ERROR_NAME = 'Для учащегося удалены пустые записи в поле Документ удостоверяющий личность.';
                PARAMS_NAME = 'Документ удостоверяющий личность';
                ERROR_TYPE = 1;
                SUSPEND;
            END
        END

        IF (EXISTS(
            SELECT FIRST 1 1
            FROM LINKS L79
            WHERE L79.PARENT_ID = :OBJECT_ID
            AND L79.OBJ_TYPE_ID = 79
            AND L79.DATE_DEL IS NULL
        )) THEN
        BEGIN
            -- 9 --
            FOR
                SELECT (SELECT COUNT(VS.VAL)
                        FROM VALS VS
                        WHERE VS.PARAM_ID = 442
                        AND VS.IS_DEL = 0
                        AND VS.OBJ_ID = L79.OBJ_ID)
                FROM LINKS L79
                WHERE L79.OBJ_TYPE_ID = 79
                AND L79.PARENT_ID = :OBJECT_ID
                AND L79.DATE_DEL IS NULL
                INTO :I
            DO
            BEGIN
                IF (:I = 0) THEN
                BEGIN
                    ERROR_TEXT = 'Для учащегося «' || :CLASS || '» класса «' || :FIO || '» не введена серия документа, удостоверяющего личность';
                    ERROR_NAME = 'Для учащегося не введена серия документа, удостоверяющего личность';
                    PARAMS_NAME = 'Документ удостоверяющий личность';
                    ERROR_TYPE = 5;
                    SUSPEND;
                END
            END
            -- 10 --
            FOR
                SELECT (SELECT COUNT(VS.VAL)
                        FROM VALS VS
                        WHERE VS.PARAM_ID = 559
                        AND VS.IS_DEL = 0
                        AND VS.OBJ_ID = L79.OBJ_ID)
                FROM LINKS L79
                WHERE L79.OBJ_TYPE_ID = 79
                AND L79.PARENT_ID = :OBJECT_ID
                AND L79.DATE_DEL IS NULL
                INTO :I
            DO
            BEGIN
                IF (:I = 0) THEN
                BEGIN
                    ERROR_TEXT = 'Для учащегося «' || :CLASS || '» класса «' || :FIO || '» не введен номер документа, удостоверяющего личность';
                    ERROR_NAME = 'Для учащегося не введен номер документа, удостоверяющего личность';
                    PARAMS_NAME = 'Документ удостоверяющий личность';
                    ERROR_TYPE = 5;
                    SUSPEND;
                END
            END
        END
        ELSE
        BEGIN
            ERROR_TEXT = 'Для учащегося «' || :CLASS || '» класса «' || :FIO || '» не введены данные документа, удостоверяющего личность';
            ERROR_NAME = 'Для учащегося не введены данные документа, удостоверяющего личность';
            PARAMS_NAME = 'Документ удостоверяющий личность';
            ERROR_TYPE = 5;
        END
        -- 11 --
        FOR
            SELECT L12.OBJ_ID,
                   (SELECT COUNT(VS.VAL)
                    FROM VALS VS
                    WHERE VS.PARAM_ID IN (570, 571, 574, 575)
                    AND VS.IS_DEL = 0
                    AND VS.OBJ_ID = L12.OBJ_ID
                   ) +
                   (SELECT COUNT(VLL.LISTVAL_ID)
                    FROM VALL VLL
                    WHERE VLL.PARAM_ID = 51
                    AND VLL.IS_DEL = 0
                    AND VLL.OBJ_ID = L12.OBJ_ID
                   ) +
                   (SELECT COUNT(VD.VAL)
                    FROM VALD VD
                    WHERE VD.PARAM_ID IN (572, 573)
                    AND VD.IS_DEL = 0
                    AND VD.OBJ_ID = L12.OBJ_ID
                   ) +
                   (SELECT COUNT(VB.VAL)
                    FROM VALB VB
                    WHERE VB.PARAM_ID = 578
                    AND VB.IS_DEL = 0
                    AND VB.OBJ_ID = L12.OBJ_ID
                   )
            FROM LINKS L12
            WHERE L12.OBJ_TYPE_ID = 12
            AND L12.PARENT_ID = :OBJECT_ID
            AND L12.DATE_DEL IS NULL
            INTO :OBJ_ID, :I
        DO
        BEGIN
            IF (:I = 0) THEN
            BEGIN
                UPDATE LINKS L
                SET L.DATE_DEL = CURRENT_TIMESTAMP
                WHERE L.OBJ_ID = :OBJ_ID
                AND L.OBJ_TYPE_ID = 12
                AND DATE_DEL IS NULL;
                ERROR_TEXT = 'Для учащегося «' || :CLASS || '» класса «' || :FIO || '» удалены пустые записи в поле Документ.';
                ERROR_NAME = 'Для учащегося удалены пустые записи в поле Документ.';
                PARAMS_NAME = 'Документ';
                ERROR_TYPE = 1;
                SUSPEND;
            END
        END

        Y = EXTRACT(YEAR FROM CURRENT_TIMESTAMP);
        M = EXTRACT(MONTH FROM CURRENT_TIMESTAMP);

        IF (M < 9) THEN
        BEGIN
            Y = Y - 1;
        END

        IF(EXISTS(
            SELECT FIRST 1 1

            FROM LINKS L120

            JOIN VALL V803
            ON V803.OBJ_ID = L120.OBJ_ID
            AND V803.PARAM_ID = 803
            AND V803.IS_DEL = 0
            AND V803.LISTVAL_ID = 2926

            JOIN LINKS LP119
            ON LP119.OBJ_ID = L120.OBJ_ID
            AND LP119.PARENT_TYPE_ID = 119
            AND LP119.DATE_DEL IS NULL

            JOIN VALL V742
            ON V742.OBJ_ID = LP119.PARENT_ID
            AND V742.PARAM_ID = 742
            AND V742.IS_DEL = 0

            JOIN LISTVALS LV
            ON LV.LISTVAL_ID = V742.LISTVAL_ID
            AND LV.COST = :Y

            WHERE L120.PARENT_ID = :OBJECT_ID
            AND L120.OBJ_TYPE_ID = 120
            AND L120.DATE_DEL IS NULL
        )) THEN
        BEGIN
            IF (NOT EXISTS(
                SELECT FIRST 1 1
                FROM VALL
                WHERE OBJ_ID = :OBJECT_ID
                AND PARAM_ID = 1620
                AND IS_DEL = 0
            )) THEN
            BEGIN
                ERROR_TEXT = 'Для ученика «' || :CLASS || '»: «' || :FIO || '», сдающего ГИА/ЕГЭ по информатике, не указано значение в поле «Язык программирования»';
                ERROR_NAME = 'Для ученика, сдающего ГИА/ЕГЭ по информатике, не указано значение в поле «Язык программирования»';
                PARAMS_NAME = 'Язык программирования';
                ERROR_TYPE = 3;
                SUSPEND;
            END
            IF (NOT EXISTS(
                SELECT FIRST 1 1
                FROM VALL
                WHERE OBJ_ID = :OBJECT_ID
                AND PARAM_ID = 1622
                AND IS_DEL = 0
            )) THEN
            BEGIN
                ERROR_TEXT = 'Для ученика «' || :CLASS || '»: «' || :FIO || '», сдающего ГИА/ЕГЭ по информатике, не указано значение в поле «Среда программирования»';
                ERROR_NAME = 'Для ученика, сдающего ГИА/ЕГЭ по информатике, не указано значение в поле «Среда программирования»';
                PARAMS_NAME = 'Среда программирования';
                ERROR_TYPE = 3;
                SUSPEND;
            END
            IF (NOT EXISTS(
                SELECT FIRST 1 1
                FROM VALL
                WHERE OBJ_ID = :OBJECT_ID
                AND PARAM_ID = 1624
                AND IS_DEL = 0
            )) THEN
            BEGIN
                ERROR_TEXT = 'Для ученика «' || :CLASS || '»: «' || :FIO || '», сдающего ГИА/ЕГЭ по информатике, не указано значение в поле «Текстовый редактор»';
                ERROR_NAME = 'Для ученика, сдающего ГИА/ЕГЭ по информатике, не указано значение в поле «Текстовый редактор»';
                PARAMS_NAME = 'Текстовый редактор';
                ERROR_TYPE = 3;
                SUSPEND;
            END
            IF (NOT EXISTS(
                SELECT FIRST 1 1
                FROM VALL
                WHERE OBJ_ID = :OBJECT_ID
                AND PARAM_ID = 1625
                AND IS_DEL = 0
            )) THEN
            BEGIN
                ERROR_TEXT = 'Для ученика «' || :CLASS || '»: «' || :FIO || '», сдающего ГИА/ЕГЭ по информатике, не указано значение в поле «Редактор электронных таблиц»';
                ERROR_NAME = 'Для ученика, сдающего ГИА/ЕГЭ по информатике, не указано значение в поле «Редактор электронных таблиц»';
                PARAMS_NAME = 'Редактор электронных таблиц';
                ERROR_TYPE = 3;
                SUSPEND;
            END
        END
    END
    FOR
        SELECT V1570.VAL
        FROM LINKS L20

        JOIN LINKS L10
        ON L10.OBJ_ID = L20.PARENT_ID
        AND L10.OBJ_TYPE_ID = 10
        AND L10.DATE_DEL IS NULL
        AND L10.PARENT_TYPE_ID = 9

        JOIN LINKS L9
        ON L9.OBJ_ID = L10.PARENT_ID
        AND L9.OBJ_TYPE_ID IN (9,187)
        AND L9.DATE_DEL IS NULL
        AND L9.PARENT_TYPE_ID = 8

        JOIN VALS V1570
        ON V1570.OBJ_ID = L20.EXT_OBJ_ID
        AND V1570.PARAM_ID = 1570
        AND V1570.IS_DEL = 0

        WHERE L20.PARENT_TYPE_ID = 10
        AND L20.DATE_DEL IS NULL
        AND L20.OBJ_TYPE_ID = 20

        GROUP BY V1570.VAL

        HAVING COUNT(*) > 1

        INTO :V
    DO
    BEGIN
        ERROR_TYPE = 3;
        PARAMS_NAME = 'Идентификатор для экспорта на портал «Петербургское образование» (ученика)';
        ERROR_TEXT = 'Идентификатор ' || :V || ' введен для нескольких учеников: ';
        ERROR_NAME = 'Идентификатор введен для нескольких учеников';
        I = 0;
        FOR
            SELECT L20.PARENT_ID,
                   L20.OBJ_ID,
                   L20.LINK_ID
            FROM LINKS L20

            JOIN VALS V1570
            ON V1570.OBJ_ID = L20.EXT_OBJ_ID
            AND V1570.PARAM_ID = 1570
            AND V1570.IS_DEL = 0

            WHERE L20.PARENT_TYPE_ID = 10
            AND L20.DATE_DEL IS NULL
            AND L20.OBJ_TYPE_ID = 20

            AND V1570.VAL LIKE :V

            INTO :OBJ_ID,
                 :OBJECT_ID,
                 :LINK_ID
        DO
        BEGIN
            IF (I = 1) THEN
            BEGIN
                ERROR_TEXT = ERROR_TEXT || ', ';
            END
            SELECT V
            FROM VAL_GET(:OBJ_ID, 55)
            INTO :FIO;
            ERROR_TEXT = ERROR_TEXT || FIO || ' ';
            SELECT VAL
            FROM DO_FUNC(:OBJ_ID, 1348, 21)
            INTO :FIO;
            IF (FIO IS NULL) THEN
            BEGIN
                FIO = '';
            END
            ERROR_TEXT = ERROR_TEXT || FIO || ' (родитель: ';
            SELECT V
            FROM VAL_GET(:OBJECT_ID, 128)
            INTO :FIO;
            ERROR_TEXT = ERROR_TEXT || FIO || ' ';
            SELECT VAL
            FROM DO_FUNC(:OBJECT_ID, 136, 21)
            INTO :FIO;
            IF (FIO IS NULL) THEN
            BEGIN
                FIO = '';
            END
            ERROR_TEXT = ERROR_TEXT || FIO || ')';
            I = 1;
        END
        ERROR_TEXT = ERROR_TEXT || '.';
        SUSPEND;
    END

    FOR
        SELECT LIST(CLASS, ', '),
               F || ' ' || COALESCE(I, '') || ' ' || COALESCE(O, '') ||
                ' (документ ' || COALESCE(SER, '') || ' ' || COALESCE(NUM, '') || ')'
        FROM R_TWINS(:I$OBJ_ID, 0, 1)
        WHERE F IS NOT NULL
        GROUP BY F, I, O, DOC, SER, NUM
        HAVING COUNT(1) > 1
    
        INTO :V, :FIO
    DO
    BEGIN
        ERROR_TYPE = 2;
        PARAMS_NAME = 'Дубли учащихся';
        ERROR_TEXT = 'Учащийся ' || :FIO || ' присутствует в нескольких группах: ' || :V;
        ERROR_NAME = 'Дубли учащихся';
        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CONTINGENT_CALC_FOR_DISTRICT RETURNS (
    SCHOOL_ID BIGINT)
AS
DECLARE VARIABLE DISTRICT_ID BIGINT;
DECLARE VARIABLE GRADE_ID BIGINT;
DECLARE VARIABLE STAGE_ID BIGINT;
DECLARE VARIABLE CLASS_ID BIGINT;
DECLARE VARIABLE LISTVAL_ID BIGINT;

DECLARE VARIABLE SCHOOL_C INTEGER;
DECLARE VARIABLE SCHOOL_M INTEGER;
DECLARE VARIABLE SCHOOL_W INTEGER;
DECLARE VARIABLE GRADE_C INTEGER;
DECLARE VARIABLE GRADE_M INTEGER;
DECLARE VARIABLE GRADE_W INTEGER;
DECLARE VARIABLE STAGE_C INTEGER;
DECLARE VARIABLE STAGE_M INTEGER;
DECLARE VARIABLE STAGE_W INTEGER;
DECLARE VARIABLE CLASS_C INTEGER;
DECLARE VARIABLE CLASS_M INTEGER;
DECLARE VARIABLE CLASS_W INTEGER;

DECLARE VARIABLE GRADE_NUM BIGINT;
DECLARE VARIABLE STAGE_NUM BIGINT;
DECLARE VARIABLE CLASS_NUM BIGINT;

DECLARE VARIABLE BLOB_ID BIGINT;
BEGIN
    SELECT FIRST 1 L.OBJ_ID
    FROM LINKS L
    WHERE L.PARENT_ID IS NULL
      AND L.OBJ_TYPE_ID = 111
      AND L.DATE_DEL IS NULL
    INTO :DISTRICT_ID;

    FOR SELECT L2.OBJ_ID
        FROM LINKS L2
        WHERE L2.PARENT_ID = :DISTRICT_ID
          AND L2.OBJ_TYPE_ID = 2
          AND L2.DATE_DEL IS NULL
        INTO :SCHOOL_ID
    DO
    BEGIN

        SCHOOL_C = 0;
        SCHOOL_M = 0;
        SCHOOL_W = 0;
        GRADE_C = 0;
        GRADE_M = 0;
        GRADE_W = 0;
        STAGE_C = 0;
        STAGE_M = 0;
        STAGE_W = 0;
        CLASS_C = 0;
        CLASS_M = 0;
        CLASS_W = 0;

        GRADE_NUM = 0;
        STAGE_NUM = 0;
        CLASS_NUM = 0;

        /* clear */

        FOR SELECT L7.OBJ_ID
            FROM LINKS L7
            WHERE L7.PARENT_ID = :SCHOOL_ID
              AND L7.OBJ_TYPE_ID = 7
              AND L7.DATE_DEL IS NULL
            INTO :GRADE_ID
        DO
        BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD(47, :GRADE_ID, 0)
            INTO :BLOB_ID;
            SELECT BLOB_ID
            FROM VAL_ADD(48, :GRADE_ID, 0)
            INTO :BLOB_ID;
            SELECT BLOB_ID
            FROM VAL_ADD(1384, :GRADE_ID, 0)
            INTO :BLOB_ID;

            FOR SELECT L8.OBJ_ID
                FROM LINKS L8
                WHERE L8.PARENT_ID = :GRADE_ID
                  AND L8.OBJ_TYPE_ID = 8
                  AND L8.DATE_DEL IS NULL
                INTO :STAGE_ID
            DO
            BEGIN
                SELECT BLOB_ID
                FROM VAL_ADD(1385, :STAGE_ID, 0)
                INTO :BLOB_ID;
                SELECT BLOB_ID
                FROM VAL_ADD(1386, :STAGE_ID, 0)
                INTO :BLOB_ID;
                SELECT BLOB_ID
                FROM VAL_ADD(1387, :STAGE_ID, 0)
                INTO :BLOB_ID;

                FOR SELECT L9.OBJ_ID
                    FROM LINKS L9
                    WHERE L9.PARENT_ID = :STAGE_ID
                      AND L9.OBJ_TYPE_ID = 9
                      AND L9.DATE_DEL IS NULL
                    INTO :CLASS_ID
                DO
                BEGIN
                    SELECT BLOB_ID
                    FROM VAL_ADD(1379, :CLASS_ID, 0)
                    INTO :BLOB_ID;
                    SELECT BLOB_ID
                    FROM VAL_ADD(1388, :CLASS_ID, 0)
                    INTO :BLOB_ID;
                    SELECT BLOB_ID
                    FROM VAL_ADD(1389, :CLASS_ID, 0)
                    INTO :BLOB_ID;
                END
            END
        END

        /* calc */

        FOR SELECT L7.OBJ_ID, L8.OBJ_ID, L9.OBJ_ID, V.LISTVAL_ID
            FROM LINKS L7
            INNER JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID
            INNER JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID
            INNER JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID
            LEFT JOIN VALL V ON V.PARAM_ID = 88 AND V.OBJ_ID = L10.OBJ_ID AND V.IS_DEL = 0
            WHERE L7.PARENT_ID = :SCHOOL_ID
              AND L7.OBJ_TYPE_ID = 7
              AND L7.DATE_DEL IS NULL
              AND L8.OBJ_TYPE_ID = 8
              AND L8.DATE_DEL IS NULL
              AND L9.OBJ_TYPE_ID = 9
              AND L9.DATE_DEL IS NULL
              AND L10.OBJ_TYPE_ID = 10
              AND L10.DATE_DEL IS NULL
            ORDER BY L7.OBJ_ID, L8.OBJ_ID, L9.OBJ_ID, L10.OBJ_ID
            INTO :GRADE_ID, :STAGE_ID, :CLASS_ID, :LISTVAL_ID
        DO
        BEGIN
            IF (GRADE_NUM = 0) THEN
                GRADE_NUM = GRADE_ID;
            IF (STAGE_NUM = 0) THEN
                STAGE_NUM = STAGE_ID;
            IF (CLASS_NUM = 0) THEN
                CLASS_NUM = CLASS_ID;

            IF (GRADE_NUM <> GRADE_ID) THEN
            BEGIN
                SELECT BLOB_ID
                FROM VAL_ADD(47, :GRADE_NUM, :GRADE_C)
                INTO :BLOB_ID;
                SELECT BLOB_ID
                FROM VAL_ADD(48, :GRADE_NUM, :GRADE_M)
                INTO :BLOB_ID;
                SELECT BLOB_ID
                FROM VAL_ADD(1384, :GRADE_NUM, :GRADE_W)
                INTO :BLOB_ID;
                GRADE_C = 0;
                GRADE_M = 0;
                GRADE_W = 0;
                GRADE_NUM = GRADE_ID;
            END

            IF (STAGE_NUM <> STAGE_ID) THEN
            BEGIN
                SELECT BLOB_ID
                FROM VAL_ADD(1385, :STAGE_NUM, :STAGE_C)
                INTO :BLOB_ID;
                SELECT BLOB_ID
                FROM VAL_ADD(1386, :STAGE_NUM, :STAGE_M)
                INTO :BLOB_ID;
                SELECT BLOB_ID
                FROM VAL_ADD(1387, :STAGE_NUM, :STAGE_W)
                INTO :BLOB_ID;
                STAGE_C = 0;
                STAGE_M = 0;
                STAGE_W = 0;
                STAGE_NUM = STAGE_ID;
            END

            IF (CLASS_NUM <> CLASS_ID) THEN
            BEGIN
                SELECT BLOB_ID
                FROM VAL_ADD(1379, :CLASS_NUM, :CLASS_C)
                INTO :BLOB_ID;
                SELECT BLOB_ID
                FROM VAL_ADD(1388, :CLASS_NUM, :CLASS_M)
                INTO :BLOB_ID;
                SELECT BLOB_ID
                FROM VAL_ADD(1389, :CLASS_NUM, :CLASS_W)
                INTO :BLOB_ID;
                CLASS_C = 0;
                CLASS_M = 0;
                CLASS_W = 0;
                CLASS_NUM = CLASS_ID;
            END

            SCHOOL_C = SCHOOL_C + 1;
            GRADE_C = GRADE_C + 1;
            STAGE_C = STAGE_C + 1;
            CLASS_C = CLASS_C + 1;

            IF (LISTVAL_ID = 183) THEN
            BEGIN
                SCHOOL_M = SCHOOL_M + 1;
                GRADE_M = GRADE_M + 1;
                STAGE_M = STAGE_M + 1;
                CLASS_M = CLASS_M + 1;
            END

            IF (LISTVAL_ID = 182) THEN
            BEGIN
                SCHOOL_W = SCHOOL_W + 1;
                GRADE_W = GRADE_W + 1;
                STAGE_W = STAGE_W + 1;
                CLASS_W = CLASS_W + 1;
            END

        END

        IF (SCHOOL_ID IS NOT NULL) THEN
        BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD(1381, :SCHOOL_ID, :SCHOOL_C)
            INTO :BLOB_ID;
            SELECT BLOB_ID
            FROM VAL_ADD(1382, :SCHOOL_ID, :SCHOOL_M)
            INTO :BLOB_ID;
            SELECT BLOB_ID
            FROM VAL_ADD(1383, :SCHOOL_ID, :SCHOOL_W)
            INTO :BLOB_ID;
        END

        IF (GRADE_ID IS NOT NULL) THEN
        BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD(47, :GRADE_ID, :GRADE_C)
            INTO :BLOB_ID;
            SELECT BLOB_ID
            FROM VAL_ADD(48, :GRADE_ID, :GRADE_M)
            INTO :BLOB_ID;
            SELECT BLOB_ID
            FROM VAL_ADD(1384, :GRADE_ID, :GRADE_W)
            INTO :BLOB_ID;
        END

        IF (STAGE_ID IS NOT NULL) THEN
        BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD(1385, :STAGE_ID, :STAGE_C)
            INTO :BLOB_ID;
            SELECT BLOB_ID
            FROM VAL_ADD(1386, :STAGE_ID, :STAGE_M)
            INTO :BLOB_ID;
            SELECT BLOB_ID
            FROM VAL_ADD(1387, :STAGE_ID, :STAGE_W)
            INTO :BLOB_ID;
        END

        IF (CLASS_ID IS NOT NULL) THEN
        BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD(1379, :CLASS_ID, :CLASS_C)
            INTO :BLOB_ID;
            SELECT BLOB_ID
            FROM VAL_ADD(1388, :CLASS_ID, :CLASS_M)
            INTO :BLOB_ID;
            SELECT BLOB_ID
            FROM VAL_ADD(1389, :CLASS_ID, :CLASS_W)
            INTO :BLOB_ID;
        END
        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE COPP_GROUP_SYNC (
    I$PROGRAM_ID BIGINT,
    I$ID BIGINT,
    I$NAME VARCHAR(1000),
    I$STATUS VARCHAR(100),
    I$DATE_FROM DATE,
    I$DUR_YEARS INTEGER,
    I$DUR_MONTHS INTEGER,
    I$DUR_DAYS INTEGER)
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$OU_ID bigint;
declare variable V$PLAN_ID bigint;
declare variable V$LEVEL_ID bigint;
declare variable V$FOLDER_ID bigint;
declare variable V$FOLDER2_ID bigint;
declare variable TMP bigint;
begin

  SELECT FIRST 1 L2.OBJ_ID
  FROM LINKS L2
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$OU_ID;

  IF(V$OU_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Запись организации не найдена';

  -- Какой уровень образования ?
  SELECT V2450.LISTVAL_ID, L400.OBJ_ID
  FROM LINKS L400
  JOIN LINKS LP69 ON LP69.OBJ_ID = L400.PARENT_ID AND LP69.PARENT_TYPE_ID = 69 AND LP69.DATE_DEL IS NULL
  JOIN VALL V2450 ON V2450.OBJ_ID = LP69.PARENT_ID AND V2450.PARAM_ID = 2450 AND V2450.IS_DEL = 0
  JOIN LINKS LP2 ON LP2.OBJ_ID = LP69.PARENT_ID AND LP2.PARENT_ID = :V$OU_ID AND LP2.DATE_DEL IS NULL
  WHERE L400.PARENT_TYPE_ID = 57 AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL AND L400.REASON_ID = :I$PROGRAM_ID
  INTO :V$LEVEL_ID, :V$PLAN_ID;

  IF(V$PLAN_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Образовательная программа (учебный план) не найдена';
  IF(V$LEVEL_ID = 11388) THEN V$LEVEL_ID = 13131; ELSE V$LEVEL_ID = 13129;

  SELECT FIRST 1 L9.OBJ_ID
  FROM LINKS L7
  JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
  JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL AND L9.REASON_ID = :I$ID
  WHERE L7.PARENT_ID = :V$OU_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
  INTO :OBJ_ID;

  -- Если группа уже есть - все равно в какой уровень ее занесло
  -- После удаления или выпуска группы и повторном ее появлении, снова создастся объект

  IF(OBJ_ID IS NULL) THEN
  BEGIN
    -- Уровень в учебных коллективах
    SELECT FIRST 1 L7.OBJ_ID
    FROM LINKS L7
    JOIN VALL V43 ON V43.OBJ_ID = L7.OBJ_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0 AND V43.LISTVAL_ID = :V$LEVEL_ID
    WHERE L7.PARENT_ID = :V$OU_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    INTO :V$FOLDER_ID;

    IF(V$FOLDER_ID IS NULL) THEN
    BEGIN
      SELECT OBJ_ID FROM OBJECT_ADD(:V$OU_ID, 7) INTO :V$FOLDER_ID;
      SELECT BLOB_ID FROM VAL_ADD(43, :V$FOLDER_ID, :V$LEVEL_ID) INTO :TMP;
    END

    -- Курс - всегда 1 курс
    SELECT FIRST 1 L8.OBJ_ID
    FROM LINKS L8
    JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0 AND V49.LISTVAL_ID = 13145
    WHERE L8.PARENT_ID = :V$FOLDER_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    INTO :V$FOLDER2_ID;

    IF(V$FOLDER2_ID IS NULL) THEN
    BEGIN
      SELECT OBJ_ID FROM OBJECT_ADD(:V$FOLDER_ID, 8) INTO :V$FOLDER2_ID;
      SELECT BLOB_ID FROM VAL_ADD(49, :V$FOLDER2_ID, 13145) INTO :TMP;
    END

    -- Группа
    SELECT OBJ_ID FROM OBJECT_ADD(:V$FOLDER2_ID, 9, :I$ID) INTO :OBJ_ID;
    SELECT BLOB_ID FROM VAL_ADD(3075, :OBJ_ID, :V$PLAN_ID) INTO :TMP;
    SELECT BLOB_ID FROM VAL_ADD(3063, :OBJ_ID, 2) INTO :TMP;
    SELECT BLOB_ID FROM VAL_ADD(54, :OBJ_ID, :I$NAME) INTO :TMP;
    SELECT BLOB_ID FROM VAL_ADD(3071, :OBJ_ID, :I$DATE_FROM) INTO :TMP;

  END

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE COPP_OP_SYNC (
    I$ORG_ID BIGINT,
    I$ID BIGINT,
    I$STATUS BIGINT,
    I$NAME VARCHAR(1000),
    I$CONTENT VARCHAR(4000),
    I$STUDY_FORM_ID BIGINT,
    I$EDUCATION_TYPE_ID BIGINT,
    I$PAYMENT BIGINT,
    I$VOLUME INTEGER,
    I$STUDY_TERM VARCHAR(200))
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$TYPE bigint;
declare variable V$YEAR_ID bigint;
declare variable V$OU_ID bigint;
declare variable N bigint;
declare variable V$FOLDER_ID bigint;
declare variable V$FOLDER2_ID bigint;
declare variable TMP bigint;
declare variable S varchar(4000);
begin

  -- ORG_ID уже не нужно смотреть, мы и так уже находимся в нужной базе

  /*
  IF(I$EDUCATION_TYPE_ID = 1) THEN V$TYPE = 12976; -- высшее профессиональное
  ELSE IF(I$EDUCATION_TYPE_ID = 2) THEN V$TYPE = 11385; -- подготовка к поступлению в ВУЗ -> общее
  ELSE IF(I$EDUCATION_TYPE_ID = 3) THEN V$TYPE = 11385; -- кружок, секция -> общее
  ELSE IF(I$EDUCATION_TYPE_ID = 4) THEN V$TYPE = 11388; -- профессиональное обучение
  ELSE IF(I$EDUCATION_TYPE_ID = 5) THEN V$TYPE = 12909; -- дополнительное профобразование
  */
  V$TYPE = 12909; -- всегда дополнительное профессиональное образование

  -- Без уровня невозможно понять, в какую папку класть
  IF(V$TYPE IS NULL) THEN EXCEPTION DATA_ERROR 'Не указан уровень ОП';

  SELECT FIRST 1 L2.OBJ_ID, V1236.LISTVAL_ID
  FROM LINKS L2
  LEFT JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$OU_ID, :V$YEAR_ID;

  IF(V$OU_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Запись организации не найдена';

  -- Если нет учебного года, задаем текущий, перевод в августе
  IF(V$YEAR_ID IS NULL) THEN
  BEGIN
    N = EXTRACT(YEAR FROM CURRENT_DATE);
    IF(EXTRACT(MONTH FROM CURRENT_DATE) < 8) THEN N = N - 1;
    V$YEAR_ID = (SELECT FIRST 1 LISTVAL_ID FROM LISTVALS WHERE LIST_ID = 29 AND IS_DEL = 0 AND COST = :N);
    IF(V$YEAR_ID IS NULL) THEN EXIT;
    SELECT BLOB_ID FROM VAL_ADD(1236, :V$OU_ID, :V$YEAR_ID) INTO :TMP;
  END

  -- Если у нас уже есть эта программа где-то (все равно, если в другом типе ОП), ее и берем
  -- оригинальный id храним в REASON_ID
  SELECT FIRST 1 L400.OBJ_ID
  FROM LINKS L69
  JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
  JOIN LINKS L400 ON L400.PARENT_ID = L57.OBJ_ID AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL AND L400.REASON_ID = :I$ID
  WHERE L69.PARENT_ID = :V$OU_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL
  INTO :OBJ_ID;

  -- Если нет - находим папку, соответствующую нужному типу
  IF(OBJ_ID IS NULL) THEN
  BEGIN
    SELECT FIRST 1 L69.OBJ_ID
    FROM LINKS L69
    JOIN VALL V2450 ON V2450.OBJ_ID = L69.OBJ_ID AND V2450.PARAM_ID = 2450 AND V2450.IS_DEL = 0 AND V2450.LISTVAL_ID = :V$TYPE
    WHERE L69.PARENT_ID = :V$OU_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL
    INTO :V$FOLDER_ID;

    IF(V$FOLDER_ID IS NULL) THEN
    BEGIN
      SELECT OBJ_ID FROM OBJECT_ADD(:V$OU_ID, 69) INTO :V$FOLDER_ID;
      SELECT BLOB_ID FROM VAL_ADD(2450, :V$FOLDER_ID, :V$TYPE) INTO :TMP;
    END

    -- Для работы с ЦОПП добавляем папку с фиксированным названием
    SELECT FIRST 1 L57.OBJ_ID
    FROM LINKS L57
    JOIN VALS V386 ON V386.OBJ_ID = L57.OBJ_ID AND V386.PARAM_ID = 386 AND V386.IS_DEL = 0 AND V386.VAL LIKE '%ЦОПП%'
    WHERE L57.PARENT_ID = :V$FOLDER_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
    INTO :V$FOLDER2_ID;

    IF(V$FOLDER2_ID IS NULL) THEN
    BEGIN
      SELECT OBJ_ID FROM OBJECT_ADD(:V$FOLDER_ID, 57) INTO :V$FOLDER2_ID;
      SELECT BLOB_ID FROM VAL_ADD(386, :V$FOLDER2_ID, 'ЦОПП') INTO :TMP;
    END

    -- Сам учебный план - фиксируем вместе с оригинальным id
    SELECT OBJ_ID FROM OBJECT_ADD(:V$FOLDER2_ID, 400, :I$ID) INTO :OBJ_ID;

  END

  -- Поменялось ли название ?
  S = (SELECT COALESCE(V, '') FROM VAL_GET(:OBJ_ID, 3012));
  IF(I$NAME <> S) THEN SELECT BLOB_ID FROM VAL_ADD(3012, :OBJ_ID, :I$NAME) INTO :TMP;

  -- Форма обучения ?
  IF(I$STUDY_FORM_ID IS NULL OR I$STUDY_FORM_ID = 1) THEN I$STUDY_FORM_ID = 153; -- очная
  ELSE IF(I$STUDY_FORM_ID = 2) THEN I$STUDY_FORM_ID = 155; -- заочная
  ELSE IF(I$STUDY_FORM_ID = 3) THEN I$STUDY_FORM_ID = 154; -- очно-заочная
  ELSE IF(I$STUDY_FORM_ID = 4) THEN I$STUDY_FORM_ID = 156; -- экстернат
  ELSE IF(I$STUDY_FORM_ID = 5) THEN I$STUDY_FORM_ID = 1221; -- дистанционная -> самообучение
  N = (SELECT COALESCE(I, 0) FROM VAL_GET(:OBJ_ID, 3015));
  IF(I$STUDY_FORM_ID <> N) THEN SELECT BLOB_ID FROM VAL_ADD(3015, :OBJ_ID, :I$STUDY_FORM_ID) INTO :TMP;

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE COPP_ORGANIZATION_FORCE (
    I$OBJ_ID BIGINT,
    I$ID BIGINT,
    I$OGRN VARCHAR(40),
    I$NAME_SHORT VARCHAR(1000),
    I$NAME_FULL VARCHAR(1000),
    I$PHONE VARCHAR(200),
    I$EMAIL VARCHAR(200),
    I$WEBSITE VARCHAR(200),
    I$ALIAS VARCHAR(40),
    I$VM_INDEX INTEGER,
    I$VM_PORT INTEGER)
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$GEN bigint;
declare variable V$MULT bigint;
declare variable TMP bigint;
declare variable LEVEL_ID bigint;
begin

  -- Записи организации тут быть вообще не должно
  SELECT FIRST 1 L2.OBJ_ID
  FROM LINKS L2
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :OBJ_ID;

  IF(OBJ_ID IS NOT NULL) THEN EXCEPTION DATA_ERROR 'Функция может вызываться только для начальной инициализации';

  -- Номер лицензии для генерации данных
  V$MULT = 1000000000;
  V$GEN = I$OBJ_ID / V$MULT;
  IF(EXISTS(SELECT 1 FROM GEN)) THEN
  BEGIN
    UPDATE GEN SET GEN = :V$GEN WHERE 1 = 1;
  END
  ELSE
  BEGIN
    INSERT INTO GEN VALUES(:V$GEN, :V$MULT);
  END

  SELECT OBJ_ID FROM OBJECT_ADD(NULL, 2) INTO :TMP;
  IF(TMP <> I$OBJ_ID) THEN
  BEGIN
    INSERT INTO OBJECTS (OBJ_ID, TYPE_ID, IS_REPL) VALUES (:I$OBJ_ID, 2, 1);
    UPDATE OBJECTS SET OBJ_ID = :I$OBJ_ID WHERE OBJ_ID = :TMP;
    UPDATE LINKS SET OBJ_ID = :I$OBJ_ID WHERE OBJ_ID = :TMP;
    UPDATE LINKS SET PARENT_ID = :I$OBJ_ID WHERE PARENT_ID = :TMP;
    DELETE FROM OBJECTS WHERE OBJ_ID = :TMP;
  END

  -- Обновляем базовые поля
  SELECT BLOB_ID FROM VAL_ADD(3068, :I$OBJ_ID, :I$ID) INTO :TMP;
  SELECT BLOB_ID FROM VAL_ADD(9, :I$OBJ_ID, :I$OGRN) INTO :TMP;
  SELECT BLOB_ID FROM VAL_ADD(2, :I$OBJ_ID, :I$NAME_SHORT) INTO :TMP;
  SELECT BLOB_ID FROM VAL_ADD(5, :I$OBJ_ID, :I$NAME_FULL) INTO :TMP;
  SELECT BLOB_ID FROM VAL_ADD(29, :I$OBJ_ID, :I$PHONE) INTO :TMP;
  SELECT BLOB_ID FROM VAL_ADD(35, :I$OBJ_ID, :I$EMAIL) INTO :TMP;
  SELECT BLOB_ID FROM VAL_ADD(36, :I$OBJ_ID, :I$WEBSITE) INTO :TMP;
  SELECT BLOB_ID FROM VAL_ADD(3074, :I$OBJ_ID, :I$ALIAS) INTO :TMP;
  SELECT BLOB_ID FROM VAL_ADD(3069, :I$OBJ_ID, :I$VM_INDEX) INTO :TMP;
  SELECT BLOB_ID FROM VAL_ADD(3070, :I$OBJ_ID, :I$VM_PORT) INTO :TMP;

  -- Ключи
  INSERT INTO KEYS (KEY_CODE, KEY_NAME, KEY_VAL) VALUES ('ABOUT', 'Активационный ключ для программного комплекса "Параграф 3"', '03.05.2013');
  INSERT INTO KEYS (KEY_CODE, KEY_NAME, KEY_VAL) VALUES ('COPYRIGHT', 'Авторское право', '© ООО "Петербургский ИВЦ"');
  INSERT INTO KEYS (KEY_CODE, KEY_NAME, KEY_VAL) VALUES ('PROJECT_NAME', 'Название проекта', 'Параграф Колледж');
  INSERT INTO KEYS (KEY_CODE, KEY_NAME, KEY_VAL) VALUES ('ORGANIZATION_SHORT_NAME', 'Сокращённое название организации', :I$NAME_SHORT);
  INSERT INTO KEYS (KEY_CODE, KEY_NAME, KEY_VAL) VALUES ('ORGANIZATION_FULL_NAME', 'Полное название организации', :I$NAME_FULL);
  INSERT INTO KEYS (KEY_CODE, KEY_NAME, KEY_VAL) VALUES ('LEVEL', 'ОУ', '1');
  INSERT INTO KEYS (KEY_CODE, KEY_NAME, KEY_VAL) VALUES ('TYPE', 'Колледж, ПТО', '2');
  INSERT INTO KEYS (KEY_CODE, KEY_NAME, KEY_VAL) VALUES ('REG_NUMBER', 'Регистрационный номер', :V$GEN);

  -- Цепочка приложений module-task-level
  UPDATE MODULES SET IS_ACTIVE = 0 WHERE 1 = 1;
  UPDATE MODULES SET IS_ACTIVE = 1 WHERE MODULE_ID IN (5, 16, 38, 39, 40, 44, 48, 51);

  -- Прописываем права админу по-умолчанию
  IF(NOT EXISTS(SELECT FIRST 1 1 FROM USERS WHERE USER_NAME = 'admin' AND DATE_DEL IS NULL)) THEN
  BEGIN
    INSERT INTO USERS (USER_ID, USER_TYPE, USER_NAME, PWD, FIRST_NAME, MIDDLE_NAME, LAST_NAME, LANG_CODE)
    VALUES (1, 1, 'admin', '', 'Администратор', 'базы', 'данных', 'BY');
  END

  FOR
    SELECT LEVEL_ID FROM LEVELS INTO :LEVEL_ID
  DO
  BEGIN
    UPDATE OR INSERT INTO LUSERS (LEVEL_ID, USER_ID, ROOT_OBJ_ID, ROOT_PARENT_ID) VALUES (:LEVEL_ID, 1, NULL, NULL);
  END

  OBJ_ID = I$OBJ_ID;
  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE COPP_ORGANIZATION_SYNC (
    I$ID BIGINT,
    I$OGRN VARCHAR(40),
    I$NAME_SHORT VARCHAR(1000),
    I$NAME_FULL VARCHAR(1000),
    I$PHONE VARCHAR(200),
    I$EMAIL VARCHAR(200),
    I$WEBSITE VARCHAR(200),
    I$ALIAS VARCHAR(40),
    I$VMNUM INTEGER = 1,
    I$ADMIN_EMAIL VARCHAR(200) = null)
RETURNS (
    OBJ_ID BIGINT,
    ALIAS VARCHAR(40),
    VM_INDEX INTEGER,
    VM_PORT INTEGER,
    EMAIL_CHANGED SMALLINT)
AS
declare variable V$ROOT bigint;
declare variable V$OGRN varchar(40);
declare variable V$NAME_SHORT varchar(1000);
declare variable V$NAME_FULL varchar(1000);
declare variable TMP bigint;
declare variable S varchar(1000);
declare variable V$GEN bigint;
declare variable V$MULT bigint;
begin

  SELECT FIRST 1 L.OBJ_ID
  FROM LINKS L
  WHERE L.PARENT_ID IS NULL AND L.OBJ_TYPE_ID = 112 AND L.DATE_DEL IS NULL
  INTO :V$ROOT;

  IF(V$ROOT IS NULL) THEN EXCEPTION DATA_ERROR 'Импорт возможен только в базу регионального уровня, либо не найден корневой объект';

  SELECT FIRST 1 L2.OBJ_ID, V9.VAL, V2.VAL, V5.VAL
  FROM LINKS L2
  JOIN VALS V3068 ON V3068.OBJ_ID = L2.OBJ_ID AND V3068.PARAM_ID = 3068 AND V3068.IS_DEL = 0 AND V3068.VAL = :I$ID
  LEFT JOIN VALS V9 ON V9.OBJ_ID = L2.OBJ_ID AND V9.PARAM_ID = 9 AND V9.IS_DEL = 0
  LEFT JOIN VALS V2 ON V2.OBJ_ID = L2.OBJ_ID AND V2.PARAM_ID = 2 AND V2.IS_DEL = 0
  LEFT JOIN VALS V5 ON V5.OBJ_ID = L2.OBJ_ID AND V5.PARAM_ID = 5 AND V5.IS_DEL = 0
  WHERE L2.PARENT_ID = :V$ROOT AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :OBJ_ID, :V$OGRN, :V$NAME_SHORT, :V$NAME_FULL;

  IF(OBJ_ID IS NULL) THEN
  BEGIN
    -- Тут надо не просто добавить, а добавить новое адресное пространство начиная с адреса 101 (кроме 4290 - занят для региона колледжей)
    -- SELECT OBJ_ID FROM OBJECT_ADD(:V$ROOT, 2) INTO :OBJ_ID;
    V$GEN = 101;
    SELECT MULTIPLIER FROM GEN INTO :V$MULT;

    WHILE(EXISTS(
      SELECT FIRST 1 1
      FROM OBJECTS OBJ
      WHERE OBJ.OBJ_ID >= :V$GEN * :V$MULT AND OBJ.OBJ_ID < (:V$GEN + 1) * :V$MULT
    ) OR V$GEN = 4290)
    DO V$GEN = V$GEN + 1;

    INSERT INTO OBJECTS (TYPE_ID, OBJ_ID) VALUES (2, :V$GEN * :V$MULT + 1) RETURNING OBJ_ID INTO :OBJ_ID;
    SELECT LINK_ID FROM OBJECT_ADD_LINK(:V$ROOT, :OBJ_ID, 2) INTO :TMP;

    UPDATE OR INSERT INTO VALS
    (OBJ_ID, PARAM_ID, IS_DEL, VAL)
    VALUES (:OBJ_ID, 3068, 0, :I$ID)
    MATCHING (OBJ_ID, PARAM_ID);
  END

  IF(I$OGRN <> V$OGRN OR (V$OGRN IS NULL AND I$OGRN IS NOT NULL)) THEN
  BEGIN
    UPDATE OR INSERT INTO VALS
    (OBJ_ID, PARAM_ID, IS_DEL, VAL)
    VALUES (:OBJ_ID, 9, 0, :I$OGRN)
    MATCHING (OBJ_ID, PARAM_ID);
  END
  IF(I$NAME_SHORT <> V$NAME_SHORT OR (V$NAME_SHORT IS NULL AND I$NAME_SHORT IS NOT NULL)) THEN
  BEGIN
    UPDATE OR INSERT INTO VALS
    (OBJ_ID, PARAM_ID, IS_DEL, VAL)
    VALUES (:OBJ_ID, 2, 0, :I$NAME_SHORT)
    MATCHING (OBJ_ID, PARAM_ID);
  END
  IF(I$NAME_FULL <> V$NAME_FULL OR (V$NAME_FULL IS NULL AND I$NAME_FULL IS NOT NULL)) THEN
  BEGIN
    UPDATE OR INSERT INTO VALS
    (OBJ_ID, PARAM_ID, IS_DEL, VAL)
    VALUES (:OBJ_ID, 5, 0, :I$NAME_FULL)
    MATCHING (OBJ_ID, PARAM_ID);
  END

  -- Остальные атрибуты
  S = (SELECT COALESCE(VAL, '') FROM VALS WHERE OBJ_ID = :OBJ_ID AND PARAM_ID = 29 AND IS_DEL = 0);
  IF(I$PHONE <> S) THEN
  BEGIN
    UPDATE OR INSERT INTO VALS
    (OBJ_ID, PARAM_ID, IS_DEL, VAL)
    VALUES (:OBJ_ID, 29, 0, :I$PHONE)
    MATCHING (OBJ_ID, PARAM_ID);
  END

  S = (SELECT COALESCE(VAL, '') FROM VALS WHERE OBJ_ID = :OBJ_ID AND PARAM_ID = 35 AND IS_DEL = 0);
  IF(I$EMAIL <> S) THEN
  BEGIN
    UPDATE OR INSERT INTO VALS
    (OBJ_ID, PARAM_ID, IS_DEL, VAL)
    VALUES (:OBJ_ID, 35, 0, :I$EMAIL)
    MATCHING (OBJ_ID, PARAM_ID);
  END

  S = (SELECT COALESCE(VAL, '') FROM VALS WHERE OBJ_ID = :OBJ_ID AND PARAM_ID = 36 AND IS_DEL = 0);
  IF(I$WEBSITE <> S) THEN
  BEGIN
    UPDATE OR INSERT INTO VALS
    (OBJ_ID, PARAM_ID, IS_DEL, VAL)
    VALUES (:OBJ_ID, 36, 0, :I$WEBSITE)
    MATCHING (OBJ_ID, PARAM_ID);
  END

  -- Сохраняем alias
  S = (SELECT COALESCE(VAL, '') FROM VALS WHERE OBJ_ID = :OBJ_ID AND PARAM_ID = 3074 AND IS_DEL = 0);
  IF(I$ALIAS <> S) THEN
  BEGIN
    UPDATE OR INSERT INTO VALS
    (OBJ_ID, PARAM_ID, IS_DEL, VAL)
    VALUES (:OBJ_ID, 3074, 0, :I$ALIAS)
    MATCHING (OBJ_ID, PARAM_ID);
  END

  -- Сохраняем email админа
  EMAIL_CHANGED = 0;
  S = (SELECT COALESCE(VAL, '') FROM VALS WHERE OBJ_ID = :OBJ_ID AND PARAM_ID = 3106 AND IS_DEL = 0);
  IF(I$ADMIN_EMAIL <> S) THEN
  BEGIN
    EMAIL_CHANGED = 1;
    UPDATE OR INSERT INTO VALS
    (OBJ_ID, PARAM_ID, IS_DEL, VAL)
    VALUES (:OBJ_ID, 3106, 0, :I$ADMIN_EMAIL)
    MATCHING (OBJ_ID, PARAM_ID);
  END

  -- Формируем размещение на серверах - при первом добавлении, ищем первый свободный порт
  ALIAS = I$ALIAS;
  VM_INDEX = (SELECT VAL FROM VALI WHERE OBJ_ID = :OBJ_ID AND PARAM_ID = 3069 AND IS_DEL = 0);
  VM_PORT = (SELECT VAL FROM VALI WHERE OBJ_ID = :OBJ_ID AND PARAM_ID = 3070 AND IS_DEL = 0);
  IF(VM_INDEX IS NULL OR VM_PORT IS NULL OR VM_PORT < 10000) THEN
  BEGIN
    VM_INDEX = 0;
    VM_PORT = 10000;
    WHILE(EXISTS(
      SELECT FIRST 1 1
      FROM LINKS L2
      JOIN VALI V3069 ON V3069.OBJ_ID = L2.OBJ_ID AND V3069.PARAM_ID = 3069 AND V3069.IS_DEL = 0 AND V3069.VAL = :VM_INDEX
      JOIN VALI V3070 ON V3070.OBJ_ID = L2.OBJ_ID AND V3070.PARAM_ID = 3070 AND V3070.IS_DEL = 0 AND V3070.VAL = :VM_PORT
      WHERE L2.PARENT_TYPE_ID = 112 AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    )) DO
    BEGIN
      VM_INDEX = VM_INDEX + 1;
      IF(VM_INDEX >= I$VMNUM) THEN
      BEGIN
        VM_INDEX = 0;
        VM_PORT = VM_PORT + 1;
      END
    END

    UPDATE OR INSERT INTO VALI
    (OBJ_ID, PARAM_ID, IS_DEL, VAL)
    VALUES (:OBJ_ID, 3069, 0, :VM_INDEX)
    MATCHING (OBJ_ID, PARAM_ID);

    UPDATE OR INSERT INTO VALI
    (OBJ_ID, PARAM_ID, IS_DEL, VAL)
    VALUES (:OBJ_ID, 3070, 0, :VM_PORT)
    MATCHING (OBJ_ID, PARAM_ID);

  END

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE COPP_PERSON_SYNC (
    I$PROGRAM_ID BIGINT,
    I$GROUP_ID INTEGER,
    I$ID BIGINT,
    I$NAME_FIRST VARCHAR(200),
    I$NAME_MID VARCHAR(200),
    I$NAME_LAST VARCHAR(200),
    I$BIRTH_DATE DATE,
    I$SEX VARCHAR(10),
    I$EMAIL VARCHAR(200),
    I$PHONE VARCHAR(200),
    I$ESIA_ID VARCHAR(100))
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$OU_ID bigint;
declare variable V$LEVEL_ID bigint;
declare variable V$FOLDER_ID bigint;
declare variable V$FOLDER2_ID bigint;
declare variable V$PLAN_ID bigint;
declare variable V$GROUP_ID bigint;
declare variable V$MOVE_ID bigint;
declare variable TMP bigint;
declare variable S varchar(1000);
begin

  SELECT FIRST 1 L2.OBJ_ID
  FROM LINKS L2
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$OU_ID;

  IF(V$OU_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Запись организации не найдена';

  SELECT FIRST 1 L9.OBJ_ID
  FROM LINKS L7
  JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
  JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL AND L9.REASON_ID = :I$GROUP_ID
  WHERE L7.PARENT_ID = :V$OU_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
  INTO :V$GROUP_ID;

  IF(V$GROUP_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Группа не найдена';

  -- Все атрибуты вносим только один раз и далее больше не трогаем
  SELECT FIRST 1 L10.OBJ_ID
  FROM LINKS L10
  WHERE L10.PARENT_ID = :V$GROUP_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL AND L10.REASON_ID = :I$ID
  INTO :OBJ_ID;

  IF(OBJ_ID IS NULL) THEN
  BEGIN
    -- Нет учащегося в этой инкарнации группы, но вероятно есть в старой комплектности (уже удаленной) ?
    SELECT FIRST 1 L10.OBJ_ID
    FROM LINKS L10
    JOIN LINKS LP8 ON LP8.OBJ_ID = L10.PARENT_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.REASON_ID = :I$GROUP_ID
    WHERE L10.PARENT_TYPE_ID = 9 AND L10.OBJ_TYPE_ID = 10 AND L10.REASON_ID = :I$ID AND L10.DATE_DEL IS NOT NULL
    INTO :OBJ_ID;

    IF(OBJ_ID IS NULL) THEN
    BEGIN
      SELECT OBJ_ID FROM OBJECT_ADD(:V$GROUP_ID, 10, :I$ID) INTO :OBJ_ID;
      SELECT BLOB_ID FROM VAL_ADD(55, :OBJ_ID, :I$NAME_LAST) INTO :TMP;
      SELECT BLOB_ID FROM VAL_ADD(56, :OBJ_ID, :I$NAME_FIRST) INTO :TMP;
      SELECT BLOB_ID FROM VAL_ADD(57, :OBJ_ID, :I$NAME_MID) INTO :TMP;
      SELECT BLOB_ID FROM VAL_ADD(89, :OBJ_ID, :I$BIRTH_DATE) INTO :TMP;
      SELECT BLOB_ID FROM VAL_ADD(88, :OBJ_ID, IIF(:I$SEX = 'man', 183, 182)) INTO :TMP;
      SELECT BLOB_ID FROM VAL_ADD(3076, :OBJ_ID, :I$EMAIL) INTO :TMP;
      SELECT BLOB_ID FROM VAL_ADD(102, :OBJ_ID, :I$PHONE) INTO :TMP;
      SELECT BLOB_ID FROM VAL_ADD(3060, :OBJ_ID, :I$ESIA_ID) INTO :TMP;

      S = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$GROUP_ID));

      -- Создаем запись в реестре движения - только нового формата
      INSERT INTO PERSON_MOVEMENTS
      (PERSON_ID, GROUP_ID, STAGE_ID, DATE_IN, NAME_IN, REASON_IN)
      VALUES (:OBJ_ID, :V$GROUP_ID, 49, CURRENT_DATE, :S, 5322);
    END
  END

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE COPY_EMPLOYEE_SNILS (
    I$OBJ_ID BIGINT,
    I$PARAM_ID BIGINT = NULL,
    I$USER BIGINT = NULL)
AS
DECLARE VARIABLE V$PERSON_ID BIGINT;
DECLARE VARIABLE V$DOC_TYPE BIGINT;
DECLARE VARIABLE V$VAL VARCHAR(100);
DECLARE VARIABLE V$PERSON_SNILS VARCHAR(100);
DECLARE VARIABLE V$DOC_ID BIGINT;
DECLARE VARIABLE V$ID BIGINT;
begin
  -- Проверка корреляции при вводе в самой персоне
  IF(I$PARAM_ID IN (1409, 2455)) THEN
  BEGIN
    SELECT FIRST 1 VN.VAL
    FROM VALS VN
    WHERE VN.OBJ_ID = :I$OBJ_ID AND VN.PARAM_ID = :I$PARAM_ID AND VN.IS_DEL = 0
    INTO :V$PERSON_SNILS;

    -- Что внесено в документах ?
    SELECT FIRST 1 L12.OBJ_ID, V571.VAL
    FROM LINKS L12
    JOIN VALL V51 ON V51.OBJ_ID = L12.OBJ_ID AND V51.PARAM_ID = 51 AND V51.IS_DEL = 0 AND V51.LISTVAL_ID = 1384
    LEFT JOIN VALS V571 ON V571.OBJ_ID = L12.OBJ_ID AND V571.PARAM_ID = 571 AND V571.IS_DEL = 0
    WHERE L12.PARENT_ID = :I$OBJ_ID AND L12.OBJ_TYPE_ID = 12 AND L12.DATE_DEL IS NULL
    INTO :V$DOC_ID, :V$VAL;

    IF (V$VAL IS NULL) THEN
    BEGIN
      --Redmine #1113 --п. 1. При внесении снилс в личное дело, если ранее он не был внесен, в личное дело - добавить его же как документ
      IF (V$DOC_ID IS NULL AND V$PERSON_SNILS IS NOT NULL) THEN
      BEGIN
        SELECT OBJ_ID FROM OBJECT_ADD(:I$OBJ_ID, 12, NULL, NULL, :I$USER) INTO :V$ID;
        UPDATE OR INSERT INTO VALL (PARAM_ID, OBJ_ID, USER_ID, LISTVAL_ID)
        VALUES (51, :V$ID, :I$USER, 1384);
        V$DOC_ID = V$ID;
      END
      --4. При изменении снилс в личном деле синхронно изменить его в записи документа
      UPDATE OR INSERT INTO VALS (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
      VALUES (571, :V$DOC_ID, :I$USER, 0, :V$PERSON_SNILS);
    END
    ELSE IF (V$PERSON_SNILS IS NULL) THEN
    BEGIN
      --Redmine 1113 п. 2. При очистке снилс в личном деле, если он был ранее внесен - удалить запись в документе
      UPDATE LINKS
      SET DATE_DEL = CURRENT_TIMESTAMP
      WHERE PARENT_ID = :I$OBJ_ID AND OBJ_ID = :V$DOC_ID AND DATE_DEL IS NULL;
    END
    ELSE IF (COALESCE(V$VAL, '') <> COALESCE(V$PERSON_SNILS, '')) THEN
    BEGIN
      --Redmine #1113 п. 4. При изменении снилс в личном деле синхронно изменить его в записи документа
      UPDATE OR INSERT INTO VALS (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
      VALUES (571, :V$DOC_ID, :I$USER, 0, :V$PERSON_SNILS);
    END
    EXIT;
  END

  -- Сюда попадаем при изменении номера, серии или типа документа
  -- Что это был за документ ?
  SELECT FIRST 1 LISTVAL_ID
  FROM VALL V51
  WHERE V51.OBJ_ID = :I$OBJ_ID AND V51.PARAM_ID = 51 AND V51.IS_DEL = 0
  INTO :V$DOC_TYPE;

  -- Номер
  SELECT FIRST 1 V571.VAL
  FROM VALS V571
  WHERE V571.OBJ_ID = :I$OBJ_ID AND V571.PARAM_ID = 571 AND V571.IS_DEL = 0
  INTO :V$VAL;

  IF(V$DOC_TYPE = 1384) THEN
  BEGIN
    -- Получаем данные персоны
    SELECT FIRST 1 LP.PARENT_ID, VN.VAL
    FROM LINKS LP
    LEFT JOIN VALS VN ON VN.OBJ_ID = LP.PARENT_ID AND VN.PARAM_ID IN (1409, 2455) AND VN.IS_DEL = 0
    WHERE LP.OBJ_ID = :I$OBJ_ID AND LP.PARENT_TYPE_ID IN (10, 14) AND LP.DATE_DEL IS NULL
    INTO :V$PERSON_ID, :V$PERSON_SNILS;

    -- Для СНИЛСа
    IF (I$PARAM_ID = 571) THEN
    BEGIN
      IF (V$VAL IS NULL) THEN
      BEGIN
        EXCEPTION DATA_ERROR 'Удалять номер СНИЛС следует непосредственно в данных сотрудника, а не в документе';
      END
      ELSE
      BEGIN
        -- Проверяем валидность
        IF(NOT EXISTS(SELECT 1 FROM CHECK_SNILS(:V$VAL) C WHERE C.IS_REAL = 1)) THEN
          EXCEPTION DATA_ERROR 'Введенное значение СНИЛС (' || COALESCE(V$VAL, '?') || ') невалидно у сотрудника ' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$PERSON_ID));
        IF(V$PERSON_ID IS NOT NULL AND V$PERSON_SNILS IS DISTINCT FROM V$VAL) THEN
          EXCEPTION DATA_ERROR 'Изменять номер СНИЛС следует непосредственно в данных сотрудника, а не в документе';
      END
    END
  END
end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE COPY_PARAM_VALUE (
    I$FROM_OBJ_ID BIGINT,
    I$FROM_PARAM_ID BIGINT,
    I$TO_OBJ_ID BIGINT,
    I$TO_PARAM_ID BIGINT,
    I$USER_ID BIGINT = 1)
AS
declare variable V$FROM_TYPE smallint;
declare variable V$TO_TYPE smallint;
declare variable V$TO_LIST integer;
declare variable V$S varchar(4000);
declare variable V$BLOB_ID bigint;
declare variable V$LANG_CODE varchar(2);
BEGIN
    V$LANG_CODE = 'RU';

    SELECT P.PARAM_TYPE
    FROM PARAMS P
    WHERE P.PARAM_ID = :I$FROM_PARAM_ID
    AND P.IS_DEL = 0
    INTO V$FROM_TYPE;
    
    SELECT P.PARAM_TYPE,
    P.LIST_ID
    FROM PARAMS P
    WHERE P.PARAM_ID = :I$TO_PARAM_ID
    AND P.IS_DEL = 0
    INTO V$TO_TYPE, V$TO_LIST;

    IF (V$FROM_TYPE = 1) THEN
    BEGIN /* INTEGER */
        SELECT BLOB_ID
        FROM VAL_ADD(
            :I$TO_PARAM_ID,
            :I$TO_OBJ_ID,
            (
                SELECT V.I
                FROM VAL_GET(
                    :I$FROM_OBJ_ID,
                    :I$FROM_PARAM_ID,
                    0,
                    :I$USER_ID
                ) V
            ),
            :I$USER_ID
        )
        INTO :V$BLOB_ID;
    END
    ELSE
    IF (V$FROM_TYPE = 2) THEN
    BEGIN /* FLOAT */
        SELECT BLOB_ID
        FROM VAL_ADD(
            :I$TO_PARAM_ID,
            :I$TO_OBJ_ID,
            (
                SELECT V.F
                FROM VAL_GET(
                    :I$FROM_OBJ_ID,
                    :I$FROM_PARAM_ID,
                    0,
                    :I$USER_ID
                ) V
            ),
            :I$USER_ID
        )
        INTO :V$BLOB_ID;
    END
    ELSE
    IF (V$FROM_TYPE = 3) THEN
    BEGIN /* TIMESTAMP */
        SELECT BLOB_ID
        FROM VAL_ADD(
            :I$TO_PARAM_ID,
            :I$TO_OBJ_ID,
            (
                SELECT V.DT
                FROM VAL_GET(
                    :I$FROM_OBJ_ID,
                    :I$FROM_PARAM_ID,
                    0,
                    :I$USER_ID
                ) V
            ),
            :I$USER_ID
        )
        INTO :V$BLOB_ID;
    END
    ELSE
    IF (V$FROM_TYPE = 4) THEN
    BEGIN /* DATE */
        SELECT BLOB_ID
        FROM VAL_ADD(
            :I$TO_PARAM_ID,
            :I$TO_OBJ_ID,
            (
                SELECT V.D
                FROM VAL_GET(
                    :I$FROM_OBJ_ID,
                    :I$FROM_PARAM_ID,
                    0,
                    :I$USER_ID
                ) V
            ),
            :I$USER_ID
        )
        INTO :V$BLOB_ID;
    END
    ELSE
    IF (V$FROM_TYPE = 5) THEN
    BEGIN /* TIME */
        SELECT BLOB_ID
        FROM VAL_ADD(
            :I$TO_PARAM_ID,
            :I$TO_OBJ_ID,
            (
                SELECT V.T
                FROM VAL_GET(
                    :I$FROM_OBJ_ID,
                    :I$FROM_PARAM_ID,
                    0,
                    :I$USER_ID
                ) V
            ),
            :I$USER_ID
        )
        INTO :V$BLOB_ID;
    END
    ELSE
    IF (V$FROM_TYPE = 6) THEN
    BEGIN /* LIST_VALUE */
        IF (V$TO_TYPE = 6) THEN
        BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD(
                :I$TO_PARAM_ID,
                :I$TO_OBJ_ID,
                (
                    SELECT LISTVAL_ID
                    FROM LISTVALS LV
                    LEFT JOIN RES_GET(LV.RES_ID, :V$LANG_CODE) R ON 1=1
                    WHERE R.VAL LIKE (
                        SELECT V.V
                        FROM VAL_GET(
                            :I$FROM_OBJ_ID,
                            :I$FROM_PARAM_ID,
                            0,
                            :I$USER_ID
                        ) V
                    )
                    AND LV.LIST_ID = :V$TO_LIST
                ),
                :I$USER_ID
            )
            INTO :V$BLOB_ID;
        END
        ELSE
        BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD(
                :I$TO_PARAM_ID,
                :I$TO_OBJ_ID,
                (
                    SELECT V.V
                    FROM VAL_GET(
                        :I$FROM_OBJ_ID,
                        :I$FROM_PARAM_ID,
                        0,
                        :I$USER_ID
                    ) V
                ),
                :I$USER_ID)
                INTO :V$BLOB_ID;
        END
    END
    ELSE
    IF ((V$FROM_TYPE = 7) OR (V$FROM_TYPE = 8) OR (V$FROM_TYPE = 9)) THEN
    BEGIN /* STRING */
        SELECT BLOB_ID
        FROM VAL_ADD(
            :I$TO_PARAM_ID,
            :I$TO_OBJ_ID,
            (
                SELECT V.V
                FROM VAL_GET(
                    :I$FROM_OBJ_ID,
                    :I$FROM_PARAM_ID,
                    0,
                    :I$USER_ID
                ) V
            ),
            :I$USER_ID
        )
        INTO :V$BLOB_ID;
    END
    IF ((V$FROM_TYPE = 11) OR (V$FROM_TYPE = 12) OR (V$FROM_TYPE = 13) ) THEN
    BEGIN /* STRING */
        SELECT BLOB_ID
        FROM VAL_ADD(
            :I$TO_PARAM_ID,
            :I$TO_OBJ_ID,
            (
                SELECT V.I
                FROM VAL_GET(
                    :I$FROM_OBJ_ID,
                    :I$FROM_PARAM_ID,
                    0,
                    :I$USER_ID
                ) V
            ),
            :I$USER_ID
        )
        INTO :V$BLOB_ID;
    END
    ELSE
    IF ((V$FROM_TYPE = 17) OR (V$FROM_TYPE = 19)) THEN
    BEGIN
        IF (V$TO_TYPE = 6) THEN
        BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD(
                :I$TO_PARAM_ID,
                :I$TO_OBJ_ID,
                (
                    SELECT LISTVAL_ID
                    FROM LISTVALS LV
                    LEFT JOIN RES_GET(LV.RES_ID, :V$LANG_CODE) R ON 1=1
                    WHERE R.VAL LIKE (
                        SELECT V.V
                        FROM VAL_GET(
                            :I$FROM_OBJ_ID,
                            :I$FROM_PARAM_ID,
                            0,
                            :I$USER_ID
                        ) V
                    )
                    AND LV.LIST_ID = :V$TO_LIST
                ),
                :I$USER_ID
            )
            INTO :V$BLOB_ID;
        END
        ELSE
        BEGIN
            SELECT V.V
            FROM VAL_GET(
                :I$FROM_OBJ_ID,
                :I$FROM_PARAM_ID,
                0,
                :I$USER_ID
            ) V
            INTO V$S;
            IF (V$S = '') THEN
            BEGIN
                V$S = NULL; 
            END
            SELECT BLOB_ID
            FROM VAL_ADD(
                :I$TO_PARAM_ID,
                :I$TO_OBJ_ID,
                :V$S,
                :I$USER_ID
            )
            INTO :V$BLOB_ID;
        END
    END

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE COPY_SPO_CODES (
    I$OBJ_ID BIGINT,
    I$PLAN_ID BIGINT)
AS
declare variable V$PARAM_ID bigint;
declare variable V$TYPE_ID bigint;
declare variable V$PT smallint;
declare variable V varchar(1000);
declare variable N smallint;
begin

  SELECT TYPE_ID
  FROM OBJECTS
  WHERE OBJ_ID = :I$OBJ_ID
  INTO :V$TYPE_ID;

  -- Зачищаем старые значения кодов
  UPDATE VALL
  SET IS_DEL = 1
  WHERE OBJ_ID = :I$OBJ_ID AND PARAM_ID IN (3381, 3382, 3383, 3384, 2165, 2821, 3367, 2822) AND IS_DEL = 0;

  -- Копируем коды на уровне сырых таблиц, чтобы не попасть на блокировку
  N = 0;
  FOR
    SELECT 0, V.PARAM_ID, V.LISTVAL_ID
    FROM LINKS LP57
    JOIN VALL V ON V.OBJ_ID = LP57.PARENT_ID AND V.PARAM_ID IN (1753, 2460, 3378) AND V.IS_DEL = 0
    WHERE LP57.OBJ_ID = :I$PLAN_ID AND LP57.PARENT_TYPE_ID = 57 AND LP57.DATE_DEL IS NULL
    UNION
    SELECT 1, V.PARAM_ID, V.VAL
    FROM LINKS LP57
    JOIN VALS V ON V.OBJ_ID = LP57.PARENT_ID AND V.PARAM_ID IN (1754) AND V.IS_DEL = 0
    WHERE LP57.OBJ_ID = :I$PLAN_ID AND LP57.PARENT_TYPE_ID = 57 AND LP57.DATE_DEL IS NULL
    INTO :V$PT, :V$PARAM_ID, :V
  DO
  BEGIN
    IF(V$TYPE_ID = 9) THEN
    BEGIN
      IF(V$PARAM_ID = 1753) THEN V$PARAM_ID = 2165;
      ELSE IF(V$PARAM_ID = 2460) THEN V$PARAM_ID = 2821;
      ELSE IF(V$PARAM_ID = 3378) THEN V$PARAM_ID = 3367;
      ELSE IF(V$PARAM_ID = 1754) THEN V$PARAM_ID = 2822;
    END
    ELSE IF(V$TYPE_ID = 403) THEN
    BEGIN
      IF(V$PARAM_ID = 1753) THEN V$PARAM_ID = 3381;
      ELSE IF(V$PARAM_ID = 2460) THEN V$PARAM_ID = 3382;
      ELSE IF(V$PARAM_ID = 3378) THEN V$PARAM_ID = 3383;
      ELSE IF(V$PARAM_ID = 1754) THEN V$PARAM_ID = 3384;
    END

    IF(V$PT = 0) THEN
    BEGIN
      UPDATE OR INSERT INTO VALL
      (OBJ_ID, PARAM_ID, IS_DEL, LISTVAL_ID)
      VALUES (:I$OBJ_ID, :V$PARAM_ID, 0, :V);
    END
    ELSE
    BEGIN
      UPDATE OR INSERT INTO VALS
      (OBJ_ID, PARAM_ID, IS_DEL, VAL)
      VALUES (:I$OBJ_ID, :V$PARAM_ID, 0, :V);
    END

    N = N + 1;
  END

  IF(N = 0) THEN EXCEPTION DATA_ERROR 'В учебном плане не указан код профессии/специальности';

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE COUNT_SL_ROOMS_CALC (
    I$OBJ_ID BIGINT)
AS
declare variable V$BUILDING bigint;
declare variable V$COUNT_ROOMS bigint;
declare variable V$BLOB_ID bigint;
begin
  -- Выбираем ID здания, обязательно будет только один ID
  SELECT LP16.PARENT_ID
  FROM LINKS LP16
  WHERE LP16.OBJ_ID = :I$OBJ_ID AND LP16.PARENT_TYPE_ID = 16 AND LP16.DATE_DEL IS NULL
  INTO :V$BUILDING;

  -- Если наш объект удален (пересчет площадей при удалении помещения), необходимо смотреть также удаленные ID
  IF(V$BUILDING IS NULL) THEN 
  BEGIN

    SELECT FIRST 1 LP16.PARENT_ID
    FROM LINKS LP16
    WHERE LP16.OBJ_ID = :I$OBJ_ID AND LP16.PARENT_TYPE_ID = 16
    INTO :V$BUILDING;

    IF(V$BUILDING IS NULL) THEN EXCEPTION DATA_ERROR 'Не удалось установить здание, к которому относится данное помещение';

  END

  SELECT count(V525.OBJ_ID)
  FROM LINKS L61
  -- учебно-лабораторные помещения
  JOIN VALL V525 ON V525.PARAM_ID = 525 AND V525.OBJ_ID = L61.OBJ_ID AND V525.IS_DEL = 0 AND V525.LISTVAL_ID = 23
  WHERE L61.OBJ_TYPE_ID = 61 AND L61.DATE_DEL IS NULL AND L61.PARENT_ID = :V$BUILDING
  INTO :V$COUNT_ROOMS;

  IF(V$COUNT_ROOMS IS NULL) THEN V$COUNT_ROOMS = 0;

  -- 501 -- здание - "Количество учебно-лабораторных помещений (фактическое)"
  SELECT BLOB_ID FROM VAL_ADD(501, :V$BUILDING, :V$COUNT_ROOMS) INTO :V$BLOB_ID;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CPLAN_COPY (
    I$PLAN_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    OBJ_ID BIGINT,
    OBJ_CAPTION VARCHAR(1000))
AS
DECLARE VARIABLE V$OU_ID BIGINT;
DECLARE VARIABLE V$YEAR_ID BIGINT;
DECLARE VARIABLE V$STATE_ID BIGINT;
DECLARE VARIABLE V$PYEAR_ID BIGINT;
DECLARE VARIABLE V$GRADE_ID BIGINT;
DECLARE VARIABLE V$SUBJECT_ID BIGINT;
DECLARE VARIABLE V$GRADE_NAME VARCHAR(200);
DECLARE VARIABLE V$CONTROL_TYPE_ID BIGINT;
DECLARE VARIABLE V$PTP_LESSON_ID BIGINT;
DECLARE VARIABLE V$STAGE_ID BIGINT;
DECLARE VARIABLE V$DATE DATE;
DECLARE VARIABLE V$LESSON_NUM INTEGER;
DECLARE VARIABLE S VARCHAR(20);
DECLARE VARIABLE Y INTEGER;
DECLARE VARIABLE V$YEAR_VAL INTEGER;
DECLARE VARIABLE V$PYEAR_VAL INTEGER;
DECLARE VARIABLE V$TEACHER_ID BIGINT;
DECLARE VARIABLE V$DUR FLOAT;
begin

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  SELECT FIRST 1 L2.OBJ_ID, V1236.LISTVAL_ID, LV.COST
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$OU_ID, :V$YEAR_ID, :V$YEAR_VAL;

  SELECT FIRST 1 V3591.LISTVAL_ID
  FROM VALL V3591
  WHERE V3591.OBJ_ID = :I$PLAN_ID AND V3591.PARAM_ID = 3591 AND V3591.IS_DEL = 0
  INTO :V$STATE_ID;

  IF(V$STATE_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Данные не найдены';
  IF(V$STATE_ID = 11716) THEN EXCEPTION DATA_ERROR 'Данный график является проектом, копировать можно только действующие графики';

  SELECT FIRST 1 V3590.LISTVAL_ID, LV.COST
  FROM VALL V3590
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V3590.LISTVAL_ID
  WHERE V3590.OBJ_ID = :I$PLAN_ID AND V3590.PARAM_ID = 3590 AND V3590.IS_DEL = 0
  INTO :V$PYEAR_ID, :V$PYEAR_VAL;

  IF(EXISTS(
    SELECT FIRST 1 1
    FROM LINKS L535
    JOIN VALL V3591 ON V3591.OBJ_ID = L535.OBJ_ID AND V3591.PARAM_ID = 3591 AND V3591.IS_DEL = 0 AND V3591.LISTVAL_ID = 11716
    WHERE L535.PARENT_ID = :V$OU_ID AND L535.OBJ_TYPE_ID = 535 AND L535.DATE_DEL IS NULL
  ))
  THEN
    EXCEPTION DATA_ERROR 'График в статусе проекта уже есть';

  SELECT OBJ_ID FROM OBJECT_ADD(:V$OU_ID, 535, NULL, NULL, :I$USER_ID) INTO :OBJ_ID;

  -- Переносим график, по необходимости исправляем даты и зачищаем ссылки на ПТП в случае смены года
  -- ID классов берем новые по названию и сверяем, остались ли в них такие же предметы
  FOR
    SELECT D.PERSON_ID, D.REF_ID, D.GROUP_NAME, D.PLAN_ID, D.REF_TYPE_ID, D.STAGE_ID, D.VAL_DATE, D.VERIFIED, D.GROUP_TYPE_ID, D.LOAD_VAL
    FROM EDULOAD_DATA D
    WHERE D.DATE_DEL IS NULL AND D.PARENT_ID = :I$PLAN_ID
    ORDER BY D.OBJ_ID
    INTO :V$GRADE_ID, :V$SUBJECT_ID, :V$GRADE_NAME, :V$CONTROL_TYPE_ID, :V$PTP_LESSON_ID, :V$STAGE_ID, :V$DATE, :V$LESSON_NUM, :V$TEACHER_ID, :V$DUR
  DO
  BEGIN
    IF(V$PYEAR_ID = V$YEAR_ID) THEN
    BEGIN
      -- Год не меняется - проверяем что класс и предмет не пропали
      IF(NOT EXISTS(
        SELECT FIRST 1 1
        FROM LINKS LP8
        WHERE LP8.OBJ_ID = :V$GRADE_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
      ))
      THEN
        V$GRADE_ID = NULL;
    END
    ELSE
    BEGIN
      -- Год меняется - переставляем дату, ссылку на ПТП зачищаем
      V$PTP_LESSON_ID = NULL;

      -- Подбираем новый класс по старому названию
      V$GRADE_ID = NULL;
      SELECT FIRST 1 L9.OBJ_ID
      FROM LINKS L2
      JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
      JOIN VALL V43 ON V43.OBJ_ID = L7.OBJ_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0 AND V43.LISTVAL_ID IN (22, 26, 27)
      JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
      JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0 AND V49.LISTVAL_ID = :V$STAGE_ID
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
      LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C ON 1 = 1
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND C.CAPTION = :V$GRADE_NAME
      INTO :V$GRADE_ID;

      -- Проверяем что предмет остался для этого класса
      IF(V$GRADE_ID IS NOT NULL AND NOT EXISTS(
        SELECT FIRST 1 1
        FROM LINKS L10
        JOIN LINKS LP179 ON LP179.OBJ_ID = L10.OBJ_ID AND LP179.PARENT_TYPE_ID = 179 AND LP179.DATE_DEL IS NULL
        JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.JOURNAL_TYPE = 0 AND J.GRADE_ID = LP179.PARENT_ID AND J.SUBJECT_ID = :V$SUBJECT_ID
        WHERE L10.PARENT_ID = :V$GRADE_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      ))
      THEN
        V$GRADE_ID = NULL;

      -- если вдруг 29.02 - точно такую дату заменяем на 28.02
      S = (SELECT RESULT FROM DATE2STR(:V$DATE));
      IF(SUBSTRING(S FROM 1 FOR 5) = '29.02') THEN S = '28.02.' || SUBSTRING(S FROM 7);
      Y = SUBSTRING(S FROM 7);
      IF(V$YEAR_ID = Y) THEN S = SUBSTRING(S FROM 1 FOR 6) || V$PYEAR_VAL; ELSE S = SUBSTRING(S FROM 1 FOR 6) || (V$PYEAR_VAL + 1);
    END

    IF(V$GRADE_ID IS NOT NULL) THEN
    BEGIN
      INSERT INTO EDULOAD_DATA
      (PARENT_ID, PERSON_ID, REF_ID, GROUP_NAME, PLAN_ID, REF_TYPE_ID, STAGE_ID, VAL_DATE, VERIFIED,
        GROUP_TYPE_ID, LOAD_VAL)
      VALUES(:OBJ_ID, :V$GRADE_ID, :V$SUBJECT_ID, :V$GRADE_NAME, :V$CONTROL_TYPE_ID, :V$PTP_LESSON_ID, :V$STAGE_ID, :V$DATE, :V$LESSON_NUM,
        :V$TEACHER_ID, :V$DUR);
    END
  END

  SELECT CAPTION
  FROM OBJECT_CAPTION_GET(:OBJ_ID)
  INTO :OBJ_CAPTION;

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CPLAN_PRINT_GET (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(4000))
AS
DECLARE VARIABLE M INTEGER;
DECLARE VARIABLE V$GRADE_ID BIGINT;
DECLARE VARIABLE V$D1 DATE;
DECLARE VARIABLE V$D2 DATE;
DECLARE VARIABLE S VARCHAR(200);
DECLARE VARIABLE V$YEAR INTEGER;
DECLARE VARIABLE V$L1 SMALLINT;
DECLARE VARIABLE V$L2 SMALLINT;
DECLARE VARIABLE V$L3 SMALLINT;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$SUBJECT_LIST VARCHAR(1000);
DECLARE VARIABLE V$SUBJECT_ID BIGINT;
begin

  TAG_NAME = 'year';
  SELECT C.VAL, LV.COST
  FROM VALL V3590
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V3590.LISTVAL_ID
  LEFT JOIN LISTVAL_TEXT(V3590.LISTVAL_ID) C ON 1 = 1
  WHERE V3590.OBJ_ID = :I$OBJ_ID AND V3590.PARAM_ID = 3590 AND V3590.IS_DEL = 0
  INTO :VAL, :V$YEAR;
  SUSPEND;

  -- Первый блок - сводная ведомость по классам по месяцам
  -- Сами названия месяцев не нужны - они заложены в шаблон статикой
  TAG_NAME = 'summary::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT DISTINCT D.PERSON_ID, D.GROUP_NAME
    FROM EDULOAD_DATA D
    JOIN LISTVALS LV ON LV.LISTVAL_ID = D.STAGE_ID
    WHERE D.DATE_DEL IS NULL AND D.PARENT_ID = :I$OBJ_ID
    ORDER BY LV.COST
    INTO :V$GRADE_ID, :S
  DO
  BEGIN
    TAG_NAME = 'summary:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'summary:r:grade_name';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'summary:r:months::json&colon;array';
    VAL = 1;
    SUSPEND;
    M = 9;
    WHILE(M <> 6) DO
    BEGIN
      IF(M > 9) THEN V$D1 = '1.' || M || '.' || V$YEAR; ELSE V$D1 = '1.' || M || '.' || (V$YEAR + 1);
      V$D2 = DATEADD(1 MONTH TO V$D1);

      TAG_NAME = 'summary:r:months:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'summary:r:months:r:count';
      SELECT COUNT(*)
      FROM EDULOAD_DATA D
      WHERE D.DATE_DEL IS NULL AND D.PARENT_ID = :I$OBJ_ID AND D.PERSON_ID = :V$GRADE_ID AND D.VAL_DATE >= :V$D1 AND D.VAL_DATE < :V$D2
      INTO :VAL;
      SUSPEND;

      -- То же с разбивкой по конкретным мероприятиям
      TAG_NAME = 'summary:r:months:r:details::json&colon;array';
      VAL = 1;
      SUSPEND;
      FOR
        SELECT SUBSTRING(DC.RESULT FROM 1 FOR 2) || ' ' || CT.CONTROL_NAME, COALESCE(V377.SVAL, '*')
        FROM EDULOAD_DATA D
        LEFT JOIN VALS V377 ON V377.OBJ_ID = D.REF_ID AND V377.PARAM_ID = 377
        JOIN CJ2_CONTROL_TYPE CT ON CT.CONTROL_TYPE_ID = D.PLAN_ID
        LEFT JOIN DATE2STR(D.VAL_DATE) DC ON 1 = 1
        WHERE D.DATE_DEL IS NULL AND D.PARENT_ID = :I$OBJ_ID AND D.PERSON_ID = :V$GRADE_ID AND D.VAL_DATE >= :V$D1 AND D.VAL_DATE < :V$D2
        ORDER BY D.VAL_DATE
        INTO :S, :V$SUBJECT_LIST
      DO
      BEGIN
        TAG_NAME = 'summary:r:months:r:details:r';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'summary:r:months:r:details:r:item';
        VAL = S;
        SUSPEND;
        TAG_NAME = 'summary:r:months:r:details:r:subject';
        VAL = V$SUBJECT_LIST;
        SUSPEND;
      END

      M = M + 1;
      IF(M = 13) THEN M = 1;
    END
  END

  -- Списки по уровням образования
  V$L1 = 0; -- НОО
  V$L2 = 0; -- ООО
  V$L3 = 0; -- СОО
  SELECT FIRST 1 1
  FROM EDULOAD_DATA D
  WHERE D.DATE_DEL IS NULL AND D.PARENT_ID = :I$OBJ_ID AND D.STAGE_ID IN (37, 38, 39, 40, 12942, 12950)
  INTO :V$L1;
  SELECT FIRST 1 1
  FROM EDULOAD_DATA D
  WHERE D.DATE_DEL IS NULL AND D.PARENT_ID = :I$OBJ_ID AND D.STAGE_ID IN (41, 42, 43, 44, 45, 12951, 12960)
  INTO :V$L2;
  SELECT FIRST 1 1
  FROM EDULOAD_DATA D
  WHERE D.DATE_DEL IS NULL AND D.PARENT_ID = :I$OBJ_ID AND D.STAGE_ID IN (46, 47, 48, 12961)
  INTO :V$L3;

  TAG_NAME = 'levels::json&colon;array';
  VAL = 1;
  SUSPEND;
  IF(V$L1 = 1) THEN
  BEGIN
    TAG_NAME = 'levels:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'levels:r:name';
    VAL = 'Начальное общее образование';
    SUSPEND;
    TAG_NAME = 'levels:r:subjects::json&colon;array';
    VAL = 1;
    SUSPEND;
    V$SUBJECT_LIST = '';
    FOR
      SELECT DISTINCT D.REF_ID, V376.SVAL
      FROM EDULOAD_DATA D
      JOIN VALS V376 ON V376.OBJ_ID = D.REF_ID AND V376.PARAM_ID = 376
      WHERE D.DATE_DEL IS NULL AND D.PARENT_ID = :I$OBJ_ID AND D.STAGE_ID IN (37, 38, 39, 40, 12942, 12950)
      ORDER BY 2
      INTO :V$OBJ_ID, :S
    DO
    BEGIN
      TAG_NAME = 'levels:r:subjects:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'levels:r:subjects:r:name';
      VAL = S;
      SUSPEND;
      IF(V$SUBJECT_LIST <> '') THEN V$SUBJECT_LIST = V$SUBJECT_LIST || ',';
      V$SUBJECT_LIST = V$SUBJECT_LIST || V$OBJ_ID;
    END
    TAG_NAME = 'levels:r:rows::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT DISTINCT D.PERSON_ID, D.GROUP_NAME
      FROM EDULOAD_DATA D
      JOIN LISTVALS LV ON LV.LISTVAL_ID = D.STAGE_ID
      WHERE D.DATE_DEL IS NULL AND D.PARENT_ID = :I$OBJ_ID AND D.STAGE_ID IN (37, 38, 39, 40, 12942, 12950)
      ORDER BY LV.COST
      INTO :V$OBJ_ID, :S
    DO
    BEGIN
      TAG_NAME = 'levels:r:rows:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'levels:r:rows:r:name';
      VAL = S;
      SUSPEND;
      TAG_NAME = 'levels:r:rows:r:subjects::json&colon;array';
      VAL = 1;
      SUSPEND;
      FOR
        SELECT L.ID
        FROM STR_TO_ID_LIST(:V$SUBJECT_LIST) L
        INTO :V$SUBJECT_ID
      DO
      BEGIN
        TAG_NAME = 'levels:r:rows:r:subjects:r';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'levels:r:rows:r:subjects:r:items::json&colon;array';
        VAL = 1;
        SUSPEND;
        FOR
          SELECT SUBSTRING(DC.RESULT FROM 1 FOR 5) || ' ' || CT.CONTROL_NAME
          FROM EDULOAD_DATA D
          LEFT JOIN CJ2_CONTROL_TYPE CT ON CT.CONTROL_TYPE_ID = D.PLAN_ID
          LEFT JOIN DATE2STR(D.VAL_DATE) DC ON 1 = 1
          WHERE D.DATE_DEL IS NULL AND D.PARENT_ID = :I$OBJ_ID AND D.PERSON_ID = :V$OBJ_ID AND D.REF_ID = :V$SUBJECT_ID
          ORDER BY D.VAL_DATE
          INTO :S
        DO
        BEGIN
          TAG_NAME = 'levels:r:rows:r:subjects:r:items:r';
          VAL = NULL;
          SUSPEND;
          TAG_NAME = 'levels:r:rows:r:subjects:r:items:r:text';
          VAL = S;
          SUSPEND;
        END
      END
    END
  END

  IF(V$L2 = 1) THEN
  BEGIN
    TAG_NAME = 'levels:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'levels:r:name';
    VAL = 'Основное общее образование';
    SUSPEND;
    TAG_NAME = 'levels:r:subjects::json&colon;array';
    VAL = 1;
    SUSPEND;
    V$SUBJECT_LIST = '';
    FOR
      SELECT DISTINCT D.REF_ID, V376.SVAL
      FROM EDULOAD_DATA D
      JOIN VALS V376 ON V376.OBJ_ID = D.REF_ID AND V376.PARAM_ID = 376
      WHERE D.DATE_DEL IS NULL AND D.PARENT_ID = :I$OBJ_ID AND D.STAGE_ID IN (41, 42, 43, 44, 45, 12951, 12960)
      ORDER BY 2
      INTO :V$OBJ_ID, :S
    DO
    BEGIN
      TAG_NAME = 'levels:r:subjects:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'levels:r:subjects:r:name';
      VAL = S;
      SUSPEND;
      IF(V$SUBJECT_LIST <> '') THEN V$SUBJECT_LIST = V$SUBJECT_LIST || ',';
      V$SUBJECT_LIST = V$SUBJECT_LIST || V$OBJ_ID;
    END
    TAG_NAME = 'levels:r:rows::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT DISTINCT D.PERSON_ID, D.GROUP_NAME
      FROM EDULOAD_DATA D
      JOIN LISTVALS LV ON LV.LISTVAL_ID = D.STAGE_ID
      WHERE D.DATE_DEL IS NULL AND D.PARENT_ID = :I$OBJ_ID AND D.STAGE_ID IN (41, 42, 43, 44, 45, 12951, 12960)
      ORDER BY LV.COST
      INTO :V$OBJ_ID, :S
    DO
    BEGIN
      TAG_NAME = 'levels:r:rows:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'levels:r:rows:r:name';
      VAL = S;
      SUSPEND;
      TAG_NAME = 'levels:r:rows:r:subjects::json&colon;array';
      VAL = 1;
      SUSPEND;
      FOR
        SELECT L.ID
        FROM STR_TO_ID_LIST(:V$SUBJECT_LIST) L
        INTO :V$SUBJECT_ID
      DO
      BEGIN
        TAG_NAME = 'levels:r:rows:r:subjects:r';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'levels:r:rows:r:subjects:r:items::json&colon;array';
        VAL = 1;
        SUSPEND;
        FOR
          SELECT SUBSTRING(DC.RESULT FROM 1 FOR 5) || ' ' || CT.CONTROL_NAME
          FROM EDULOAD_DATA D
          LEFT JOIN CJ2_CONTROL_TYPE CT ON CT.CONTROL_TYPE_ID = D.PLAN_ID
          LEFT JOIN DATE2STR(D.VAL_DATE) DC ON 1 = 1
          WHERE D.DATE_DEL IS NULL AND D.PARENT_ID = :I$OBJ_ID AND D.PERSON_ID = :V$OBJ_ID AND D.REF_ID = :V$SUBJECT_ID
          ORDER BY D.VAL_DATE
          INTO :S
        DO
        BEGIN
          TAG_NAME = 'levels:r:rows:r:subjects:r:items:r';
          VAL = NULL;
          SUSPEND;
          TAG_NAME = 'levels:r:rows:r:subjects:r:items:r:text';
          VAL = S;
          SUSPEND;
        END
      END
    END
  END

  IF(V$L3 = 1) THEN
  BEGIN
    TAG_NAME = 'levels:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'levels:r:name';
    VAL = 'Среднее общее образование';
    SUSPEND;
    TAG_NAME = 'levels:r:subjects::json&colon;array';
    VAL = 1;
    SUSPEND;
    V$SUBJECT_LIST = '';
    FOR
      SELECT DISTINCT D.REF_ID, V376.SVAL
      FROM EDULOAD_DATA D
      JOIN VALS V376 ON V376.OBJ_ID = D.REF_ID AND V376.PARAM_ID = 376
      WHERE D.DATE_DEL IS NULL AND D.PARENT_ID = :I$OBJ_ID AND D.STAGE_ID IN (46, 47, 48, 12961)
      ORDER BY 2
      INTO :V$OBJ_ID, :S
    DO
    BEGIN
      TAG_NAME = 'levels:r:subjects:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'levels:r:subjects:r:name';
      VAL = S;
      SUSPEND;
      IF(V$SUBJECT_LIST <> '') THEN V$SUBJECT_LIST = V$SUBJECT_LIST || ',';
      V$SUBJECT_LIST = V$SUBJECT_LIST || V$OBJ_ID;
    END
    TAG_NAME = 'levels:r:rows::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT DISTINCT D.PERSON_ID, D.GROUP_NAME
      FROM EDULOAD_DATA D
      JOIN LISTVALS LV ON LV.LISTVAL_ID = D.STAGE_ID
      WHERE D.DATE_DEL IS NULL AND D.PARENT_ID = :I$OBJ_ID AND D.STAGE_ID IN (46, 47, 48, 12961)
      ORDER BY LV.COST
      INTO :V$OBJ_ID, :S
    DO
    BEGIN
      TAG_NAME = 'levels:r:rows:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'levels:r:rows:r:name';
      VAL = S;
      SUSPEND;
      TAG_NAME = 'levels:r:rows:r:subjects::json&colon;array';
      VAL = 1;
      SUSPEND;
      FOR
        SELECT L.ID
        FROM STR_TO_ID_LIST(:V$SUBJECT_LIST) L
        INTO :V$SUBJECT_ID
      DO
      BEGIN
        TAG_NAME = 'levels:r:rows:r:subjects:r';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'levels:r:rows:r:subjects:r:items::json&colon;array';
        VAL = 1;
        SUSPEND;
        FOR
          SELECT SUBSTRING(DC.RESULT FROM 1 FOR 5) || ' ' || CT.CONTROL_NAME
          FROM EDULOAD_DATA D
          JOIN CJ2_CONTROL_TYPE CT ON CT.CONTROL_TYPE_ID = D.PLAN_ID
          LEFT JOIN DATE2STR(D.VAL_DATE) DC ON 1 = 1
          WHERE D.DATE_DEL IS NULL AND D.PARENT_ID = :I$OBJ_ID AND D.PERSON_ID = :V$OBJ_ID AND D.REF_ID = :V$SUBJECT_ID
          ORDER BY D.VAL_DATE
          INTO :S
        DO
        BEGIN
          TAG_NAME = 'levels:r:rows:r:subjects:r:items:r';
          VAL = NULL;
          SUSPEND;
          TAG_NAME = 'levels:r:rows:r:subjects:r:items:r:text';
          VAL = S;
          SUSPEND;
        END
      END
    END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CPLAN_ROW_DELETE (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
AS
DECLARE VARIABLE V$STATUS_ID BIGINT;
begin

  SELECT FIRST 1 V3591.LISTVAL_ID
  FROM EDULOAD_DATA D
  JOIN VALL V3591 ON V3591.OBJ_ID = D.PARENT_ID AND V3591.PARAM_ID = 3591 AND V3591.IS_DEL = 0
  WHERE D.DATE_DEL IS NULL AND D.OBJ_ID = :I$OBJ_ID
  INTO :V$STATUS_ID;

  IF(V$STATUS_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Запись не найдена или была удалена';
  IF(V$STATUS_ID <> 11716) THEN EXCEPTION DATA_ERROR 'Изменение графика возможно только в статусе Проект';

  UPDATE EDULOAD_DATA
  SET DATE_DEL = CURRENT_TIMESTAMP
  WHERE OBJ_ID = :I$OBJ_ID;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CPLAN_ROW_GET (
    I$PLAN_ID BIGINT NOT NULL,
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$STATE_ID BIGINT;
DECLARE VARIABLE V$GRADE_ID BIGINT;
DECLARE VARIABLE V$GRADE_NAME VARCHAR(200);
DECLARE VARIABLE V$SUBJECT_ID BIGINT;
DECLARE VARIABLE V$PTP_LESSON_ID BIGINT;
DECLARE VARIABLE V$CT BIGINT;
DECLARE VARIABLE V$STAGE_ID BIGINT;
DECLARE VARIABLE V$DATE DATE;
DECLARE VARIABLE V$N INTEGER;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$TEACHER_ID BIGINT;
DECLARE VARIABLE V$DUR FLOAT;
DECLARE VARIABLE S VARCHAR(1000);
begin

  SELECT FIRST 1 V3591.LISTVAL_ID
  FROM VALL V3591
  WHERE V3591.OBJ_ID = :I$PLAN_ID AND V3591.PARAM_ID = 3591 AND V3591.IS_DEL = 0
  INTO :V$STATE_ID;

  IF(V$STATE_ID <> 11716 AND I$OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Изменение графика возможно только в статусе Проект';

  -- Формат хранения в EDULOAD_DATA смотри UPDATE_CHECK_PLAN

  SELECT FIRST 1 D.PERSON_ID, D.GROUP_NAME, D.REF_ID, D.REF_TYPE_ID, D.PLAN_ID, D.STAGE_ID, D.VAL_DATE, D.VERIFIED,
    D.GROUP_TYPE_ID, D.LOAD_VAL
  FROM EDULOAD_DATA D
  WHERE D.DATE_DEL IS NULL AND D.PARENT_ID = :I$PLAN_ID AND D.OBJ_ID = :I$OBJ_ID
  INTO :V$GRADE_ID, :V$GRADE_NAME, :V$SUBJECT_ID, :V$PTP_LESSON_ID, :V$CT, :V$STAGE_ID, :V$DATE, :V$N,
    :V$TEACHER_ID, :V$DUR;

  IF(I$OBJ_ID IS NOT NULL AND V$GRADE_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Данные не найдены';

  TAG_NAME = 'parent_id';
  VAL = I$PLAN_ID;
  SUSPEND;

  TAG_NAME = 'id';
  VAL = I$OBJ_ID;
  SUSPEND;

  TAG_NAME = 'date';
  VAL = (SELECT VAL FROM DATE2ISO(:V$DATE, 0));
  SUSPEND;

  TAG_NAME = 'lesson_num';
  VAL = V$N;
  SUSPEND;

  IF(V$STATE_ID <> 11716) THEN
  BEGIN
    TAG_NAME = 'row_readonly';
    VAL = 1;
    SUSPEND;
  END

  -- В Проекте можно выбирать, в закрытых статусах только текущий выбор
  TAG_NAME = 'grade_id:values:value';
  VAL = V$GRADE_ID;
  SUSPEND;
  TAG_NAME = 'grade_id:selection::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L9.OBJ_ID, C.SORT_ORDER, C.SCAPTION
    FROM LINKS L2
    JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    JOIN VALL V43 ON V43.OBJ_ID = L7.OBJ_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0 AND V43.LISTVAL_ID IN (22, 26, 27)
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
    LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C ON 1 = 1
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND :V$STATE_ID = 11716
    UNION
    SELECT :V$GRADE_ID, 0, :V$GRADE_NAME
    FROM RDB$DATABASE D
    WHERE :V$STATE_ID <> 11716
    ORDER BY 2, 3
    INTO :V$OBJ_ID, :V$N, :S
  DO
  BEGIN
    TAG_NAME = 'grade_id:selection:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'grade_id:selection:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'grade_id:selection:r:value';
    VAL = S;
    SUSPEND;
  END

  TAG_NAME = 'subject_id:values:value';
  VAL = V$SUBJECT_ID;
  SUSPEND;
  TAG_NAME = 'subject_id:selection::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L51.OBJ_ID, V376.SVAL
    FROM LINKS L51
    JOIN VALS V376 ON V376.OBJ_ID = L51.OBJ_ID AND V376.PARAM_ID = 376 AND V376.IS_DEL = 0
    WHERE L51.PARENT_ID = 32771 AND L51.OBJ_TYPE_ID = 51 AND (L51.DATE_DEL IS NULL OR L51.OBJ_ID = :V$SUBJECT_ID)
    ORDER BY 2
    INTO :V$OBJ_ID, :S
  DO
  BEGIN
    TAG_NAME = 'subject_id:selection:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'subject_id:selection:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'subject_id:selection:r:value';
    VAL = S;
    SUSPEND;
  END

  TAG_NAME = 'control_type_id:values:value';
  VAL = V$CT;
  SUSPEND;
  TAG_NAME = 'control_type_id:selection::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT CT.CONTROL_TYPE_ID, CT.CONTROL_DESC
    FROM CJ2_CONTROL_TYPE CT
    WHERE CT.IS_DEL = 0 AND CT.CONTROL_TYPE_ID IN (1077, 1083, 1084, 1085, 1086, 1087, 1091, 1092)
    ORDER BY 2
    INTO :V$OBJ_ID, :S
  DO
  BEGIN
    TAG_NAME = 'control_type_id:selection:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'control_type_id:selection:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'control_type_id:selection:r:value';
    VAL = S;
    SUSPEND;
  END

  TAG_NAME = 'lesson_theme';
  VAL = NULL;
  SELECT FIRST 1 L.THEME_TEXT
  FROM PTP_LESSONS L
  WHERE L.OBJ_ID = :V$PTP_LESSON_ID
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'duration';
  VAL = CAST(V$DUR AS NUMERIC(18, 1));
  SUSPEND;

  TAG_NAME = 'teacher_id:values:value';
  VAL = V$teacher_id;
  SUSPEND;
  TAG_NAME = 'teacher_id:selection::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT C.TEACHER_ID, C.TEACHER_NAME
    FROM CJ2_LESSON_TEACHERS_LIST(NULL, NULL, 1) C
    WHERE :V$STATE_ID = 11716
    UNION
    SELECT :V$TEACHER_ID, C.CAPTION
    FROM OBJECT_CAPTION_GET(:V$TEACHER_ID) C
    WHERE :V$STATE_ID <> 11716 AND :V$TEACHER_ID IS NOT NULL
    INTO :V$OBJ_ID, :S
  DO
  BEGIN
    TAG_NAME = 'teacher_id:selection:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'teacher_id:selection:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'teacher_id:selection:r:value';
    VAL = S;
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CPLAN_ROW_IMPORT (
    I$PLAN_ID BIGINT,
    I$GRADE_NAME VARCHAR(200),
    I$SUBJECT_NAME VARCHAR(200),
    I$CONTROL_TYPE VARCHAR(200),
    I$DATE DATE,
    I$LESSON_NUM INTEGER,
    I$TEACHER_NAME VARCHAR(1000),
    I$DURATION FLOAT,
    I$USER_ID VARCHAR(40))
RETURNS (
    OBJ_ID BIGINT)
AS
DECLARE VARIABLE V$GRADE_ID BIGINT;
DECLARE VARIABLE V$GRADE_NAME VARCHAR(200);
DECLARE VARIABLE V$STAGE_ID BIGINT;
DECLARE VARIABLE V$SUBJECT_ID BIGINT;
DECLARE VARIABLE V$CONTROL_TYPE_ID BIGINT;
DECLARE VARIABLE V$TEACHER_ID BIGINT;
begin

  I$GRADE_NAME = LOWER(I$GRADE_NAME);
  I$SUBJECT_NAME = LOWER(I$SUBJECT_NAME);
  I$CONTROL_TYPE = LOWER(I$CONTROL_TYPE);
  I$TEACHER_NAME = LOWER(I$TEACHER_NAME);

  SELECT FIRST 1 L9.OBJ_ID, C.CAPTION, V49.LISTVAL_ID
  FROM LINKS L2
  JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
  JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
  JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
  JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
  LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C ON 1 = 1
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND LOWER(C.CAPTION) = :I$GRADE_NAME
  INTO :V$GRADE_ID, :V$GRADE_NAME, :V$STAGE_ID;

  IF(V$GRADE_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Нет учебного коллектива ' || I$GRADE_NAME;

  SELECT FIRST 1 L51.OBJ_ID
  FROM LINKS L51
  JOIN VALS V376 ON V376.OBJ_ID = L51.OBJ_ID AND V376.PARAM_ID = 376 AND V376.IS_DEL = 0
  LEFT JOIN VALS V377 ON V377.OBJ_ID = L51.OBJ_ID AND V377.PARAM_ID = 377 AND V377.IS_DEL = 0
  WHERE L51.PARENT_ID = 32771 AND L51.OBJ_TYPE_ID = 51 AND L51.DATE_DEL IS NULL
    AND (LOWER(V376.SVAL) = :I$SUBJECT_NAME OR LOWER(V377.SVAL) = :I$SUBJECT_NAME)
  INTO :V$SUBJECT_ID;

  IF(V$SUBJECT_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Нет предмета ' || I$SUBJECT_NAME;

  SELECT FIRST 1 CT.CONTROL_TYPE_ID
  FROM CJ2_CONTROL_TYPE CT
  WHERE CT.IS_DEL = 0 AND (LOWER(CT.CONTROL_NAME) = :I$CONTROL_TYPE OR LOWER(CT.CONTROL_SHORTNAME) = :I$CONTROL_TYPE OR LOWER(CT.CONTROL_DESC) = :I$CONTROL_TYPE)
  INTO :V$CONTROL_TYPE_ID;

  IF(V$CONTROL_TYPE_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Нет вида контроля ' || I$CONTROL_TYPE;

  SELECT FIRST 1 L.TEACHER_ID
  FROM CJ2_LESSON_TEACHERS_LIST(NULL, NULL, 1) L
  WHERE LOWER(L.TEACHER_NAME) = :I$TEACHER_NAME
  INTO :V$TEACHER_ID;

  SELECT FIRST 1 D.OBJ_ID
  FROM EDULOAD_DATA D
  WHERE D.DATE_DEL IS NULL AND D.PARENT_ID = :I$PLAN_ID AND D.PERSON_ID = :V$GRADE_ID AND D.REF_ID = :V$SUBJECT_ID AND D.VAL_DATE = :I$DATE
  INTO :OBJ_ID;

  IF(OBJ_ID IS NULL) THEN
  BEGIN
    INSERT INTO EDULOAD_DATA
    (PARENT_ID, PERSON_ID, REF_ID, GROUP_NAME, PLAN_ID, STAGE_ID, VAL_DATE, VERIFIED, GROUP_TYPE_ID, LOAD_VAL)
    VALUES(:I$PLAN_ID, :V$GRADE_ID, :V$SUBJECT_ID, :V$GRADE_NAME, :V$CONTROL_TYPE_ID, :V$STAGE_ID, :I$DATE, :I$LESSON_NUM, :V$TEACHER_ID, :I$DURATION)
    RETURNING OBJ_ID INTO :OBJ_ID;
  END
  ELSE
  BEGIN
    UPDATE EDULOAD_DATA
    SET VERIFIED = COALESCE(VERIFIED, :I$LESSON_NUM), LOAD_VAL = COALESCE(LOAD_VAL, :I$DURATION), GROUP_TYPE_ID = :V$TEACHER_ID
    WHERE OBJ_ID = :OBJ_ID;
  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CPLAN_ROW_SET (
    I$PLAN_ID BIGINT NOT NULL,
    I$OBJ_ID BIGINT,
    I$GRADE_ID BIGINT NOT NULL,
    I$SUBJECT_ID BIGINT NOT NULL,
    I$CONTROL_TYPE_ID BIGINT NOT NULL,
    I$DATE DATE NOT NULL,
    I$LESSON_NUM INTEGER,
    I$TEACHER_ID BIGINT,
    I$DUR FLOAT,
    I$USER_ID VARCHAR(40))
RETURNS (
    OBJ_ID BIGINT)
AS
DECLARE VARIABLE V$STATE_ID BIGINT;
DECLARE VARIABLE V$GRADE_NAME VARCHAR(200);
DECLARE VARIABLE V$STAGE_ID BIGINT;
DECLARE VARIABLE V$DATE DATE;
DECLARE VARIABLE V$LESSON_NUM SMALLINT;
begin

  SELECT FIRST 1 V3591.LISTVAL_ID
  FROM VALL V3591
  WHERE V3591.OBJ_ID = :I$PLAN_ID AND V3591.PARAM_ID = 3591 AND V3591.IS_DEL = 0
  INTO :V$STATE_ID;

  IF(V$STATE_ID <> 11716) THEN EXCEPTION DATA_ERROR 'Изменение графика возможно только в статусе Проект';

  SELECT FIRST 1 D.OBJ_ID, D.VAL_DATE, D.VERIFIED
  FROM EDULOAD_DATA D
  WHERE D.DATE_DEL IS NULL AND D.PARENT_ID = :I$PLAN_ID AND D.OBJ_ID = :I$OBJ_ID
  INTO :OBJ_ID, :V$DATE, :V$LESSON_NUM;

  IF(I$OBJ_ID IS NOT NULL AND OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Данные не найдены';
  IF(I$LESSON_NUM <= 0 OR I$LESSON_NUM > 20) THEN EXCEPTION DATA_ERROR 'Недопустимый номер урока';
  IF(I$DUR <= 0 OR I$DUR > 24) THEN EXCEPTION DATA_ERROR 'Недопустимая длительность. Длительность задается в часах, и не может превышать 24 часа';

  -- Дата только в текущем учебном году

  SELECT CAPTION
  FROM OBJECT_CAPTION_GET(:I$GRADE_ID)
  INTO :V$GRADE_NAME;

  SELECT V49.LISTVAL_ID
  FROM LINKS LP8
  JOIN VALL V49 ON V49.OBJ_ID = LP8.PARENT_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
  WHERE LP8.OBJ_ID = :I$GRADE_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
  INTO :V$STAGE_ID;

  IF(I$OBJ_ID IS NULL) THEN
  BEGIN
    INSERT INTO EDULOAD_DATA
    (PARENT_ID, PERSON_ID, REF_ID, GROUP_NAME, PLAN_ID, REF_TYPE_ID, STAGE_ID, VAL_DATE, VERIFIED, VAL_FLAG,
      LOAD_VAL, GROUP_TYPE_ID)
    VALUES(:I$PLAN_ID, :I$GRADE_ID, :I$SUBJECT_ID, :V$GRADE_NAME, :I$CONTROL_TYPE_ID, NULL, :V$STAGE_ID, :I$DATE, :I$LESSON_NUM, 1,
      :I$DUR, :I$TEACHER_ID)
    RETURNING OBJ_ID INTO :OBJ_ID;
  END
  ELSE
  BEGIN
    -- Ссылку на урок из ПТП не обновляем
    UPDATE EDULOAD_DATA
    SET PERSON_ID = :I$GRADE_ID, REF_ID = :I$SUBJECT_ID, GROUP_NAME = :V$GRADE_NAME, PLAN_ID = :I$CONTROL_TYPE_ID, STAGE_ID = :V$STAGE_ID,
      VAL_DATE = :I$DATE, VERIFIED = :I$LESSON_NUM, GROUP_TYPE_ID = :I$TEACHER_ID, LOAD_VAL = :I$DUR,
      VAL_FLAG = IIF(VAL_FLAG <> 0 OR :I$DATE <> :V$DATE OR :V$LESSON_NUM <> :I$LESSON_NUM, 1, 0)
    WHERE OBJ_ID = :OBJ_ID;
  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CREATE_CALENDAR_PLAN (
    I$OBJ_ID BIGINT)
AS
DECLARE VARIABLE V$OU_ID BIGINT;
DECLARE VARIABLE V$YEAR_ID BIGINT;
DECLARE VARIABLE N INTEGER;
DECLARE VARIABLE Y INTEGER;
begin

  SELECT FIRST 1 L2.OBJ_ID, V1236.LISTVAL_ID, LV.COST
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$OU_ID, :V$YEAR_ID, :Y;

  -- Если на текущий учебный год уже есть, добавляем на следующий

  -- Не даем добавлять КУГ повторно на тот же год
  IF(EXISTS(
    SELECT FIRST 1 1
    FROM LINKS L481
    JOIN VALL V3389 ON V3389.OBJ_ID = L481.OBJ_ID AND V3389.PARAM_ID = 3389 AND V3389.IS_DEL = 0 AND V3389.LISTVAL_ID = :V$YEAR_ID
    WHERE L481.PARENT_ID = :V$OU_ID AND L481.OBJ_TYPE_ID = 481 AND L481.DATE_DEL IS NULL AND L481.OBJ_ID <> :I$OBJ_ID
  ))
  THEN
  BEGIN
    -- Текущий год есть, пробуем следующий год
    IF(Y = EXTRACT(YEAR FROM CURRENT_DATE) - 1) THEN
    BEGIN
      Y = Y + 1;
      V$YEAR_ID = NULL;
      SELECT FIRST 1 LV.LISTVAL_ID
      FROM LISTVALS LV
      WHERE LV.LIST_ID = 29 AND LV.IS_DEL = 0 AND LV.COST = :Y
      INTO :V$YEAR_ID;
      IF(V$YEAR_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Нет данных в справочнике учебных годов для ' || Y;
      IF(EXISTS(
        SELECT FIRST 1 1
        FROM LINKS L481
        JOIN VALL V3389 ON V3389.OBJ_ID = L481.OBJ_ID AND V3389.PARAM_ID = 3389 AND V3389.IS_DEL = 0 AND V3389.LISTVAL_ID = :V$YEAR_ID
        WHERE L481.PARENT_ID = :V$OU_ID AND L481.OBJ_TYPE_ID = 481 AND L481.DATE_DEL IS NULL AND L481.OBJ_ID <> :I$OBJ_ID
      ))
      THEN
        EXCEPTION DATA_ERROR 'График за текущий и будущий учебный год уже есть, новый добавить нельзя';
    END
    ELSE
      EXCEPTION DATA_ERROR 'График за текущий учебный год уже есть, для будущего можно добавить начиная с 1 января';
  END

  SELECT 1 FROM VAL_ADD(3389, :I$OBJ_ID, :V$YEAR_ID) INTO :N;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CREATE_CHECK_PLAN (
    I$OBJ_ID BIGINT)
AS
DECLARE VARIABLE V$OU_ID BIGINT;
DECLARE VARIABLE V$YEAR_ID BIGINT;
DECLARE VARIABLE N INTEGER;
begin

  SELECT FIRST 1 L2.OBJ_ID, V1236.LISTVAL_ID
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$OU_ID, :V$YEAR_ID;

  -- Не даем добавлять КУГ повторно на тот же год, если уже есть документ в статусе проекта
  IF(EXISTS(
    SELECT FIRST 1 1
    FROM LINKS L535
    JOIN VALL V3591 ON V3591.OBJ_ID = L535.OBJ_ID AND V3591.PARAM_ID = 3591 AND V3591.IS_DEL = 0 AND V3591.LISTVAL_ID = 11716
    WHERE L535.PARENT_ID = :V$OU_ID AND L535.OBJ_TYPE_ID = 535 AND L535.DATE_DEL IS NULL AND L535.OBJ_ID <> :I$OBJ_ID
  ))
  THEN
    EXCEPTION DATA_ERROR 'График в статусе проекта уже есть';

  SELECT 1 FROM VAL_ADD(3590, :I$OBJ_ID, :V$YEAR_ID) INTO :N;

  -- Не делаем автоматическое заполнение !
  -- EXECUTE PROCEDURE UPDATE_CHECK_PLAN(:I$OBJ_ID, 1);

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CREATE_CJ_VOSP (
    I$OBJ_ID BIGINT)
AS
declare variable V$YEAR_ID bigint;
declare variable N integer;
declare variable V$CJ_ID bigint;
declare variable V$CJ_YEAR bigint;
declare variable V$OU_ID bigint;
begin

  -- Если год не задан - задаем текущий учебный год
  SELECT FIRST 1 V3372.LISTVAL_ID
  FROM VALL V3372
  WHERE V3372.OBJ_ID = :I$OBJ_ID AND V3372.PARAM_ID = 3372 AND V3372.IS_DEL = 0
  INTO :V$YEAR_ID;

  IF(V$YEAR_ID IS NULL) THEN
  BEGIN
    SELECT FIRST 1 V1236.LISTVAL_ID
    FROM LINKS L2
    JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :V$YEAR_ID;

    SELECT 1 FROM VAL_ADD(3372, :I$OBJ_ID, :V$YEAR_ID) INTO :N;
  END

  -- Создаем журнал или корректируем год журнала
  SELECT J.OBJ_ID, J.YEAR_ID
  FROM CJ2_JOURNAL J
  WHERE J.REF_ID = :I$OBJ_ID
  INTO :V$CJ_ID, :V$CJ_YEAR;

  IF(V$CJ_ID IS NULL) THEN
  BEGIN
    SELECT FIRST 1 L2.OBJ_ID
    FROM LINKS L2
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :V$OU_ID;

    INSERT INTO CJ2_JOURNAL
    (JOURNAL_TYPE, GRADE_TYPE_ID, GRADE_ID, YEAR_ID, REF_ID, JOURNAL_NAME)
    VALUES (20, 0, :V$OU_ID, :V$YEAR_ID, :I$OBJ_ID, 'Календарный план воспитательной работы')
    RETURNING OBJ_ID INTO :V$CJ_ID;
  END
  ELSE IF(V$CJ_YEAR <> V$YEAR_ID) THEN
  BEGIN
    -- !!! проверить, что расписание еще не размещено

    UPDATE CJ2_JOURNAL
    SET YEAR_ID = :I$OBJ_ID
    WHERE OBJ_ID = :V$CJ_ID;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CREATE_EDU_LOAD (
    I$OBJ_ID BIGINT)
AS
DECLARE VARIABLE V$OU_ID BIGINT;
DECLARE VARIABLE V$Y INTEGER;
DECLARE VARIABLE V$YEAR_ID BIGINT;
DECLARE VARIABLE V$PARENT_ID BIGINT;
DECLARE VARIABLE V$REF_ID BIGINT;
DECLARE VARIABLE V$STAGE_ID BIGINT;
DECLARE VARIABLE V$PERSON_ID BIGINT;
DECLARE VARIABLE V$GROUP_NAME VARCHAR(400);
DECLARE VARIABLE V$PLAN_ID BIGINT;
DECLARE VARIABLE V$JT SMALLINT;
DECLARE VARIABLE V$H FLOAT;
DECLARE VARIABLE V$W FLOAT;
DECLARE VARIABLE V FLOAT;
begin

  SELECT FIRST 1 LV.COST, LP527.PARENT_ID, LP2.PARENT_ID
  FROM LINKS LP527
  JOIN LINKS LP2 ON LP2.OBJ_ID = LP527.PARENT_ID AND LP2.PARENT_TYPE_ID = 2 AND LP2.DATE_DEL IS NULL
  JOIN LINKS L531 ON L531.PARENT_ID = LP527.PARENT_ID AND L531.OBJ_TYPE_ID = 531 AND L531.DATE_DEL IS NULL AND L531.OBJ_ID <> :I$OBJ_ID
  JOIN VALL V3567 ON V3567.OBJ_ID = L531.OBJ_ID AND V3567.PARAM_ID = 3567 AND V3567.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V3567.LISTVAL_ID
  WHERE LP527.OBJ_ID = :I$OBJ_ID AND LP527.PARENT_TYPE_ID = 527 AND LP527.DATE_DEL IS NULL
  ORDER BY 1 DESC
  INTO :V$Y, :V$PARENT_ID, :V$OU_ID;

  IF(V$Y > EXTRACT(YEAR FROM CURRENT_DATE)) THEN EXCEPTION DATA_ERROR 'Распределение на будущий год уже создано';

  -- Вообще нет ни одного - добавляем на будущий учебный год
  IF(V$Y IS NULL) THEN
  BEGIN
    V$Y = EXTRACT(YEAR FROM CURRENT_DATE);
    IF(EXTRACT(MONTH FROM CURRENT_DATE) >= 9) THEN V$Y = V$Y + 1;
  END

  -- Проверяем что нет других записей в статусе проекта
  IF(EXISTS(
    SELECT FIRST 1 1
    FROM LINKS L531
    JOIN VALL V3568 ON V3568.OBJ_ID = L531.OBJ_ID AND V3568.PARAM_ID = 3568 AND V3568.IS_DEL = 0 AND V3568.LISTVAL_ID = 11716
    WHERE L531.PARENT_ID = :V$PARENT_ID AND L531.OBJ_TYPE_ID = 531 AND L531.DATE_DEL IS NULL AND L531.OBJ_ID <> :I$OBJ_ID
  ))
  THEN
    EXCEPTION DATA_ERROR 'При создании нового распределения нагрузки не должно быть других распределений в статусе проекта';

  SELECT FIRST 1 LV.LISTVAL_ID
  FROM LISTVALS LV
  WHERE LV.LIST_ID = 29 AND LV.IS_DEL = 0 AND LV.COST >= :V$Y
  INTO :V$YEAR_ID;

  SELECT 1 FROM VAL_ADD(3567, :I$OBJ_ID, :V$YEAR_ID) INTO :V$Y;

  -- Выбираем текущее распределение и сохраняем его
  -- Классное руководство
  FOR
    SELECT G.GRADE_ID, G.STAGE_ID_NEW, V53.VAL, G.GRADE_NAME_NEW
    FROM YCHANGE_REVIEW_GRADES(NULL) G
    JOIN VALR V53 ON V53.OBJ_ID = G.GRADE_ID AND V53.PARAM_ID = 53 AND V53.IS_DEL = 0
    WHERE G.GRADE_NAME_NEW IS NOT NULL
    INTO :V$REF_ID, :V$STAGE_ID, :V$PERSON_ID, :V$GROUP_NAME
  DO
  BEGIN
    INSERT INTO EDULOAD_DATA
    (PARENT_ID, PERSON_ID, STAGE_ID, GROUP_TYPE_ID, GROUP_NAME)
    VALUES (:I$OBJ_ID, :V$PERSON_ID, :V$STAGE_ID, 9, :V$GROUP_NAME);
  END

  -- Ответственные за кабинеты
  FOR
    SELECT L16.OBJ_ID, V421.SVAL || ' - ' || COALESCE(V407.SVAL, V408.SVAL), V1344.VAL
    FROM LINKS L73
    JOIN LINKS L16 ON L16.PARENT_ID = L73.OBJ_ID AND L16.OBJ_TYPE_ID = 16 AND L16.DATE_DEL IS NULL
    JOIN VALS V421 ON V421.OBJ_ID = L16.OBJ_ID AND V421.PARAM_ID = 421 AND V421.IS_DEL = 0
    LEFT JOIN VALD V3164 ON V3164.OBJ_ID = L16.OBJ_ID AND V3164.PARAM_ID = 3164 AND V3164.IS_DEL = 0
    JOIN LINKS L61 ON L61.PARENT_ID = L16.OBJ_ID AND L61.OBJ_TYPE_ID = 61 AND L61.DATE_DEL IS NULL
    LEFT JOIN VALS V407 ON V407.OBJ_ID = L61.OBJ_ID AND V407.PARAM_ID = 407 AND V407.IS_DEL = 0
    JOIN VALS V408 ON V408.OBJ_ID = L61.OBJ_ID AND V408.PARAM_ID = 408 AND V408.IS_DEL = 0
    -- Учебные кабинеты, учебные лаборатории, учебные мастерские, спортивный зал, тренажерный зал
    JOIN VALL V526 ON V526.OBJ_ID = L61.OBJ_ID AND V526.PARAM_ID = 526 AND V526.IS_DEL = 0
    JOIN LISTVALS LV526 ON LV526.LISTVAL_ID = V526.LISTVAL_ID
    JOIN VALR V1344 ON V1344.OBJ_ID = L61.OBJ_ID AND V1344.PARAM_ID = 1344 AND V1344.IS_DEL = 0
    WHERE L73.PARENT_ID = :V$OU_ID AND L73.OBJ_TYPE_ID = 73 AND L73.DATE_DEL IS NULL AND V3164.VAL IS NULL
      AND (LV526.PARENT_ID = 24 OR V526.LISTVAL_ID IN (1130, 1131, 1146, 1147))
    INTO :V$REF_ID, :V$GROUP_NAME, :V$PERSON_ID
  DO
  BEGIN
    INSERT INTO EDULOAD_DATA
    (PARENT_ID, PERSON_ID, GROUP_TYPE_ID, GROUP_NAME)
    VALUES (:I$OBJ_ID, :V$PERSON_ID, 61, :V$GROUP_NAME);
  END

  -- Предметники
  -- Только журналы, созданные на основе групповых УП, где есть хотя бы один ученик
  FOR
    SELECT J.REF_ID, J.JOURNAL_TYPE, J.JOURNAL_NAME, J.SUBJECT_ID, J.STAGE_INDEX, J.HOURS, J.WEEKS
    FROM CJ2_JOURNAL J
    JOIN LINKS L400 ON L400.OBJ_ID = J.REF_ID AND L400.PARENT_TYPE_ID = 57 AND L400.DATE_DEL IS NULL
    JOIN VALL V3016 ON V3016.OBJ_ID = L400.OBJ_ID AND V3016.PARAM_ID = 3016 AND V3016.IS_DEL = 0 AND V3016.LISTVAL_ID = 5465
    WHERE J.DATE_DEL IS NULL AND J.JOURNAL_TYPE IN (0, 1) AND J.YEAR_ID = :V$YEAR_ID AND J.REF_ID IS NOT NULL
    INTO :V$PLAN_ID, :V$JT, :V$GROUP_NAME, :V$REF_ID, :V$STAGE_ID, :V$H, :V$W
  DO
  BEGIN
    IF(V$H IS NOT NULL AND V$W IS NOT NULL AND V$W > 0) THEN V = V$H / V$W; ELSE V = NULL;

    INSERT INTO EDULOAD_DATA
    (PARENT_ID, PERSON_ID, STAGE_ID, GROUP_TYPE_ID, GROUP_NAME, PLAN_ID, REF_ID, REF_TYPE_ID, LOAD_VAL)
    VALUES (:I$OBJ_ID, :V$PERSON_ID, :V$STAGE_ID, :V$JT, :V$GROUP_NAME, :V$PLAN_ID, :V$REF_ID, 51, :V);
  END

  -- Ветка там где журналы еще не созданы (по факту нам важны только потоковые журналы)
  -- чтобы не утруждать с их созданием

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CREATE_GZ_FOLDERS
AS
DECLARE VARIABLE V$OU_ID BIGINT;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE T INTEGER;
begin

  FOR
    SELECT L2.OBJ_ID
    FROM LINKS L2
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :V$OU_ID
  DO
  BEGIN

    V$OBJ_ID = NULL;
    SELECT FIRST 1 L432.OBJ_ID
    FROM LINKS L432
    JOIN VALI V3210 ON V3210.OBJ_ID = L432.OBJ_ID AND V3210.PARAM_ID = 3210 AND V3210.IS_DEL = 0 AND V3210.VAL = 0
    WHERE L432.PARENT_ID = :V$OU_ID AND L432.OBJ_TYPE_ID = 432 AND L432.DATE_DEL IS NULL
    INTO :V$OBJ_ID;

    IF(V$OBJ_ID IS NULL) THEN
    BEGIN
      SELECT OBJ_ID FROM OBJECT_ADD(:V$OU_ID, 432) INTO :V$OBJ_ID;
      SELECT 1 FROM VAL_ADD(3209, :V$OBJ_ID, 'Действующие Государственные Задания и проекты') INTO :T;
      SELECT 1 FROM VAL_ADD(3210, :V$OBJ_ID, 0) INTO :T;
    END

    V$OBJ_ID = NULL;
    SELECT FIRST 1 L432.OBJ_ID
    FROM LINKS L432
    JOIN VALI V3210 ON V3210.OBJ_ID = L432.OBJ_ID AND V3210.PARAM_ID = 3210 AND V3210.IS_DEL = 0 AND V3210.VAL = 1
    WHERE L432.PARENT_ID = :V$OU_ID AND L432.OBJ_TYPE_ID = 432 AND L432.DATE_DEL IS NULL
    INTO :V$OBJ_ID;

    IF(V$OBJ_ID IS NULL) THEN
    BEGIN
      SELECT OBJ_ID FROM OBJECT_ADD(:V$OU_ID, 432) INTO :V$OBJ_ID;
      SELECT 1 FROM VAL_ADD(3209, :V$OBJ_ID, 'Архив Государственных Заданий') INTO :T;
      SELECT 1 FROM VAL_ADD(3210, :V$OBJ_ID, 1) INTO :T;
    END

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CREATE_LOCAL_ACT_FOLDER
AS
DECLARE VARIABLE V$OU_ID BIGINT;
DECLARE VARIABLE V$PARENT_ID BIGINT;
DECLARE VARIABLE V$ID BIGINT;
DECLARE VARIABLE V$I BIGINT;
DECLARE VARIABLE V$LOCAL_ACT_ID BIGINT;
begin
  SELECT FIRST 1 L2.OBJ_ID
  FROM LINKS L2
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$OU_ID;

  -- Проверяем, если ли объект с типом 530 -- локальные акты
  IF (NOT EXISTS(SELECT FIRST 1 1
    FROM LINKS L
    WHERE L.OBJ_TYPE_ID = 530 AND L.PARENT_ID = :V$OU_ID AND L.DATE_DEL iS NULL
  )) THEN
  BEGIN
    SELECT OBJ_ID FROM OBJECT_ADD(:V$OU_ID, 530) INTO :V$LOCAL_ACT_ID;

    -- Переместим имеющиеся локальные акты в новую папку
    FOR
      SELECT L17.OBJ_ID, L17.PARENT_ID
      FROM LINKS L17
      JOIN VALL V471 ON V471.OBJ_ID = L17.OBJ_ID AND V471.PARAM_ID = 471 AND V471.IS_DEL = 0 AND V471.LISTVAL_ID = 18627 -- локальный норм акт ОО
      WHERE L17.OBJ_TYPE_ID = 17 AND L17.PARENT_ID = :V$OU_ID AND L17.DATE_DEL IS NULL
      INTO :V$ID, :V$PARENT_ID
    DO
    BEGIN
      SELECT OBJ_ID FROM OBJECT_MOVE(:V$PARENT_ID, :V$LOCAL_ACT_ID, :V$ID, 17) INTO :V$I;
    END
  END 

  -- Проверяем, если ли объект с типом 527 -- распределение учебной нагрузки
  IF (NOT EXISTS(SELECT FIRST 1 1
    FROM LINKS L
    WHERE L.OBJ_TYPE_ID = 527 AND L.PARENT_ID = :V$OU_ID AND L.DATE_DEL iS NULL
  )) THEN
  BEGIN
    SELECT OBJ_ID FROM OBJECT_ADD(:V$OU_ID, 527) INTO :V$LOCAL_ACT_ID;
  END
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CREATE_MTL_REPORT (
    I$OBJ_ID BIGINT,
    I$YEAR INTEGER,
    I$PERIOD_ID BIGINT,
    I$USER_ID VARCHAR(40))
AS
DECLARE VARIABLE V$YEAR INTEGER;
DECLARE VARIABLE V$PERIOD_ID BIGINT;
DECLARE VARIABLE V$BASE_LEVEL SMALLINT;
DECLARE VARIABLE V$TYPE_ID BIGINT;
DECLARE VARIABLE V$PT BIGINT;
DECLARE VARIABLE M INTEGER;
DECLARE VARIABLE T INTEGER;
begin

  M = EXTRACT(MONTH FROM CURRENT_DATE);

  -- На уровне района-региона запрещено создавать школьные отчеты
  SELECT COALESCE(CAST(K.KEY_VAL AS INTEGER), 1)
  FROM KEYS K
  WHERE K.KEY_CODE = 'LEVEL'
  INTO :V$BASE_LEVEL;

  SELECT TYPE_ID
  FROM OBJECTS
  WHERE OBJ_ID = :I$OBJ_ID
  INTO :V$TYPE_ID;

  IF(V$TYPE_ID = 512) THEN
  BEGIN
    -- Сам отчет
    SELECT FIRST 1 LP.PARENT_TYPE_ID
    FROM LINKS LP511
    JOIN LINKS LP511X ON LP511X.OBJ_ID = LP511.PARENT_ID AND LP511X.PARENT_TYPE_ID = 511 AND LP511X.DATE_DEL IS NULL
    JOIN LINKS LP ON LP.OBJ_ID = LP511X.PARENT_ID AND LP.PARENT_TYPE_ID IN (2, 111, 112) AND LP.DATE_DEL IS NULL
    WHERE LP511.OBJ_ID = :I$OBJ_ID AND LP511.PARENT_TYPE_ID = 511 AND LP511.DATE_DEL IS NULL
    INTO :V$PT;
  END
  ELSE
  BEGIN
    -- Папка отчетов
    SELECT FIRST 1 LP.PARENT_TYPE_ID
    FROM LINKS LP511
    JOIN LINKS LP ON LP.OBJ_ID = LP511.PARENT_ID AND LP.PARENT_TYPE_ID IN (2, 111, 112) AND LP.DATE_DEL IS NULL
    WHERE LP511.OBJ_ID = :I$OBJ_ID AND LP511.PARENT_TYPE_ID = 511 AND LP511.DATE_DEL IS NULL
    INTO :V$PT;
  END
  IF(V$BASE_LEVEL > 1 AND V$PT = 2) THEN EXCEPTION DATA_ERROR 'Нельзя создавать отчет уровня ОУ на районном или региональном уровне базы';

  -- Передается либо пара год+период (тогда в I$OBJ_ID передаем id папки отчетов), либо ID стандартно созданного отчета
  IF(I$YEAR IS NULL) THEN
  BEGIN
    -- Настраиваем стандартно созданный
    -- Проверяем чтобы не создавали так отчеты для нижестоящих уровней

    -- Какой у нас последний отчет был ?
    SELECT FIRST 1 V3512.VAL, V3511.LISTVAL_ID
    FROM LINKS LP511
    JOIN LINKS L512 ON L512.PARENT_ID = LP511.PARENT_ID AND L512.OBJ_TYPE_ID = 512 AND L512.DATE_DEL IS NULL
    JOIN VALI V3512 ON V3512.OBJ_ID = L512.OBJ_ID AND V3512.PARAM_ID = 3512 AND V3512.IS_DEL = 0
    JOIN VALL V3511 ON V3511.OBJ_ID = L512.OBJ_ID AND V3511.PARAM_ID = 3511 AND V3511.IS_DEL = 0
    WHERE LP511.OBJ_ID = :I$OBJ_ID AND LP511.PARENT_TYPE_ID = 511 AND LP511.DATE_DEL IS NULL
    ORDER BY 1 DESC, 2 DESC
    INTO :V$YEAR, :V$PERIOD_ID;

    -- Вообще не было отчетов - ставим последний актуальный период
    IF(V$YEAR IS NULL) THEN
    BEGIN
      V$YEAR = EXTRACT(YEAR FROM CURRENT_DATE);
      V$PERIOD_ID = 18579;
      IF(M <= 6) THEN
      BEGIN
        V$YEAR = V$YEAR - 1;
        V$PERIOD_ID = 18580;
      END
    END
    -- Уже есть отчеты, мы должны добавить следующий период
    ELSE
    BEGIN
      IF(V$PERIOD_ID = 18579) THEN V$PERIOD_ID = 18580;
      ELSE
      BEGIN
        V$YEAR = V$YEAR + 1;
        V$PERIOD_ID = 18579;
      END
      IF(
        -- Первое полугодие можно ?
        (V$PERIOD_ID = 18579 AND V$YEAR > EXTRACT(YEAR FROM CURRENT_DATE) + 1) OR
        -- Второе полугодие можно ?
        (V$PERIOD_ID = 18580 AND V$YEAR > EXTRACT(YEAR FROM CURRENT_DATE))
      )
      THEN
        EXCEPTION DATA_ERROR 'Срок для заполнения данных отчета за следующий период еще не наступил';
    END

  END
  ELSE
  BEGIN
    -- Создаем новый
    -- Формальная проверка
    IF(
      -- Первое полугодие можно ?
      (I$PERIOD_ID = 18579 AND I$YEAR > EXTRACT(YEAR FROM CURRENT_DATE) + 1) OR
      -- Второе полугодие можно ?
      (I$PERIOD_ID = 18580 AND I$YEAR > EXTRACT(YEAR FROM CURRENT_DATE))
    )
    THEN
      EXCEPTION DATA_ERROR 'Срок для заполнения данных отчета за выбранный период еще не наступил';

    IF(EXISTS(
      SELECT FIRST 1 1
      FROM LINKS L512
      JOIN VALI V3512 ON V3512.OBJ_ID = L512.OBJ_ID AND V3512.PARAM_ID = 3512 AND V3512.IS_DEL = 0 AND V3512.VAL = :I$YEAR
      JOIN VALL V3511 ON V3511.OBJ_ID = L512.OBJ_ID AND V3511.PARAM_ID = 3511 AND V3511.IS_DEL = 0 AND V3511.LISTVAL_ID = :I$PERIOD_ID
      WHERE L512.PARENT_ID = :I$OBJ_ID AND L512.OBJ_TYPE_ID = 512 AND L512.DATE_DEL IS NULL
    ))
    THEN
      EXCEPTION DATA_ERROR 'Отчет за указанный период уже есть';

    SELECT OBJ_ID FROM OBJECT_ADD(:I$OBJ_ID, 512) INTO :I$OBJ_ID;

    V$YEAR = I$YEAR;
    V$PERIOD_ID = I$PERIOD_ID;

  END

  SELECT 1 FROM VAL_ADD(3512, :I$OBJ_ID, :V$YEAR) INTO :T;
  SELECT 1 FROM VAL_ADD(3511, :I$OBJ_ID, :V$PERIOD_ID) INTO :T;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CREATE_REPORT_FOLDERS (
    I$OBJ_ID BIGINT)
AS
DECLARE VARIABLE T BIGINT;
DECLARE VARIABLE V$PARENT_ID BIGINT;
begin

  -- Если NULL, то вызов из fixer для создания корневой папки
  -- подкаталоги вызовут повторно из OBJECT_ADD
  IF(I$OBJ_ID IS NULL) THEN
  BEGIN
    SELECT FIRST 1 L.OBJ_ID
    FROM LINKS L
    WHERE L.PARENT_ID IS NULL AND L.OBJ_TYPE_ID IN (2, 111, 112) AND L.DATE_DEL IS NULL
    INTO :I$OBJ_ID;

    -- Тип назначится по-умолчанию
    IF(I$OBJ_ID IS NOT NULL) THEN
    BEGIN
      SELECT FIRST 1 L511.OBJ_ID
      FROM LINKS L511
      WHERE L511.PARENT_ID = :I$OBJ_ID AND L511.OBJ_TYPE_ID = 511 AND L511.DATE_DEL IS NULL
      INTO :V$PARENT_ID;
      IF(V$PARENT_ID IS NULL) THEN
      BEGIN
        SELECT OBJ_ID FROM OBJECT_ADD(:I$OBJ_ID, 511) INTO :T;
        EXECUTE PROCEDURE CREATE_REPORT_FOLDERS(:T);
      END
      -- Проверяем просто наличие папки - впоследствии при появлении новых каталогов надо проверять по типам
      ELSE IF(NOT EXISTS(
        SELECT FIRST 1 1
        FROM LINKS L511
        WHERE L511.PARENT_ID = :V$PARENT_ID AND L511.OBJ_TYPE_ID = 511 AND L511.DATE_DEL IS NULL
      ))
      THEN
      BEGIN
        EXECUTE PROCEDURE CREATE_REPORT_FOLDERS(:V$PARENT_ID);
      END
    END

    EXIT;
  END

  -- Если не-NULL, создаем подкаталоги внутри основного каталога отчетов - вызов из OBJECT_ADD
  -- Мониторинг талантов
  SELECT OBJ_ID FROM OBJECT_ADD(:I$OBJ_ID, 511) INTO :T;
  SELECT 1 FROM VAL_ADD(3510, :T, 18578) INTO :T;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CREATE_SCHEDULE_DEF (
    I$OBJ_ID BIGINT)
AS
declare variable V$SRC_ID bigint;
declare variable V$OBJ_ID bigint;
declare variable V$LV bigint;
declare variable T bigint;
declare variable S bigint;
declare variable T1 time;
declare variable T2 time;
begin

  -- Сначала смотрим в текущем году
  -- Сначала все старые, потом будущие. Внутри даты окончания сортируем по дате начала
  SELECT FIRST 1 L59.OBJ_ID
  FROM LINKS LP3
  JOIN LINKS L59 ON L59.PARENT_ID = LP3.PARENT_ID AND L59.OBJ_TYPE_ID = 59 AND L59.DATE_DEL IS NULL AND L59.OBJ_ID <> LP3.OBJ_ID
  LEFT JOIN VALD V3120 ON V3120.OBJ_ID = L59.OBJ_ID AND V3120.PARAM_ID = 3120 AND V3120.IS_DEL = 0
  LEFT JOIN VALD V3121 ON V3121.OBJ_ID = L59.OBJ_ID AND V3121.PARAM_ID = 3121 AND V3121.IS_DEL = 0
  WHERE LP3.OBJ_ID = :I$OBJ_ID AND LP3.PARENT_TYPE_ID = 3 AND LP3.DATE_DEL IS NULL
  ORDER BY IIF(V3121.VAL < CURRENT_DATE, 0, 1), V3120.VAL DESC
  INTO :V$SRC_ID;

  -- Если не нашли, смотрим вообще все годы, в порядке от более свежих к более старым датам
  IF(V$SRC_ID IS NULL) THEN
  SELECT FIRST 1 L59.OBJ_ID
  FROM LINKS LP3
  JOIN LINKS LP68 ON LP68.OBJ_ID = LP3.PARENT_ID AND LP68.PARENT_TYPE_ID = 68 AND LP68.DATE_DEL IS NULL
  JOIN LINKS L3 ON L3.PARENT_ID = LP68.PARENT_ID AND L3.OBJ_TYPE_ID = 3 AND L3.DATE_DEL IS NULL
  LEFT JOIN VALL V37 ON V37.OBJ_ID = L3.OBJ_ID AND V37.PARAM_ID = 37 AND V37.IS_DEL = 0
  LEFT JOIN LISTVALS LV ON LV.LISTVAL_ID = V37.LISTVAL_ID
  JOIN LINKS L59 ON L59.PARENT_ID = L3.OBJ_ID AND L59.OBJ_TYPE_ID = 59 AND L59.DATE_DEL IS NULL AND L59.OBJ_ID <> LP3.OBJ_ID
  LEFT JOIN VALD V3120 ON V3120.OBJ_ID = L59.OBJ_ID AND V3120.PARAM_ID = 3120 AND V3120.IS_DEL = 0
  LEFT JOIN VALD V3121 ON V3121.OBJ_ID = L59.OBJ_ID AND V3121.PARAM_ID = 3121 AND V3121.IS_DEL = 0
  WHERE LP3.OBJ_ID = :I$OBJ_ID AND LP3.PARENT_TYPE_ID = 3 AND LP3.DATE_DEL IS NULL
  ORDER BY LV.COST DESC, IIF(V3121.VAL < CURRENT_DATE, 0, 1), V3120.VAL DESC
  INTO :V$SRC_ID;

  IF(V$SRC_ID IS NULL) THEN
  BEGIN
    -- Ничего не нашлось
    -- Дни
    FOR
      SELECT LISTVAL_ID
      FROM LISTVALS LV
      WHERE LV.LIST_ID = 121 AND LV.IS_DEL = 0 AND LV.LISTVAL_ID < 803 -- без сб и вс
      ORDER BY LV.SORT_ORDER
      INTO :V$LV
    DO
    BEGIN
      SELECT OBJ_ID FROM OBJECT_ADD(:I$OBJ_ID, 6) INTO :V$OBJ_ID;
      SELECT 1 FROM VAL_ADD(402, :V$OBJ_ID, :V$LV) INTO :T;
    END
    -- Номера уроков с 1 по 6
    V$LV = 1;
    WHILE(V$LV <= 6) DO
    BEGIN
      SELECT OBJ_ID FROM OBJECT_ADD(:I$OBJ_ID, 60) INTO :V$OBJ_ID;
      SELECT 1 FROM VAL_ADD(404, :V$OBJ_ID, :V$LV) INTO :T;
      V$LV = V$LV + 1;
    END
  END
  ELSE
  BEGIN
    -- Копируем как есть
    -- Дни
    FOR
      SELECT DISTINCT LV.LISTVAL_ID, LV.SORT_ORDER
      FROM LINKS L6
      JOIN VALL V402 ON V402.OBJ_ID = L6.OBJ_ID AND V402.PARAM_ID = 402 AND V402.IS_DEL = 0
      JOIN LISTVALS LV ON LV.LISTVAL_ID = V402.LISTVAL_ID
      WHERE L6.PARENT_ID = :V$SRC_ID AND L6.OBJ_TYPE_ID = 6 AND L6.DATE_DEL IS NULL
      ORDER BY 2
      INTO :V$LV, :S
    DO
    BEGIN
      SELECT OBJ_ID FROM OBJECT_ADD(:I$OBJ_ID, 6) INTO :V$OBJ_ID;
      SELECT 1 FROM VAL_ADD(402, :V$OBJ_ID, :V$LV) INTO :T;
    END
    -- Номера и время уроков
    FOR
      SELECT V404.VAL, V405.VAL, V406.VAL
      FROM LINKS L60
      JOIN VALI V404 ON V404.OBJ_ID = L60.OBJ_ID AND V404.PARAM_ID = 404 AND V404.IS_DEL = 0
      LEFT JOIN VALT V405 ON V405.OBJ_ID = L60.OBJ_ID AND V405.PARAM_ID = 405 AND V405.IS_DEL = 0
      LEFT JOIN VALT V406 ON V406.OBJ_ID = L60.OBJ_ID AND V406.PARAM_ID = 406 AND V406.IS_DEL = 0
      WHERE L60.PARENT_ID = :V$SRC_ID AND L60.OBJ_TYPE_ID = 60 AND L60.DATE_DEL IS NULL
      ORDER BY 1
      INTO :V$LV, :T1, :T2
    DO
    BEGIN
      SELECT OBJ_ID FROM OBJECT_ADD(:I$OBJ_ID, 60) INTO :V$OBJ_ID;
      SELECT 1 FROM VAL_ADD(404, :V$OBJ_ID, :V$LV) INTO :T;
      SELECT 1 FROM VAL_ADD(405, :V$OBJ_ID, :T1) INTO :T;
      SELECT 1 FROM VAL_ADD(406, :V$OBJ_ID, :T2) INTO :T;
    END
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CREATE_SNILS_INDEX
AS
declare variable LEVEL_ID smallint;
declare variable SCHOOL_ID bigint;
declare variable DISTRICT_ID bigint;
declare variable PUPIL_ID bigint;
declare variable SNILS varchar(20);
declare variable FIRSTNAME varchar(50);
declare variable LASTNAME varchar(50);
declare variable DOB date;
declare variable SECONDNAME varchar(50);
declare variable DOCTYPE bigint;
declare variable DOCSERIA varchar(20);
declare variable DOCNUMBER varchar(20);
declare variable DROPOUT smallint;
declare variable DOC_ID bigint;
BEGIN
    SELECT KEY_VAL
    FROM KEYS
    WHERE KEY_CODE = 'LEVEL'
    INTO :LEVEL_ID;

    DELETE FROM DOC_INDEX WHERE 1=1;
    DELETE FROM SNILS_INDEX WHERE 1=1;

    FOR
        SELECT FIRST 1 L.OBJ_ID, NULL
        FROM LINKS L
        WHERE L.PARENT_ID IS NULL
        AND L.OBJ_TYPE_ID = 2
        AND L.DATE_DEL IS NULL
        AND ((:LEVEL_ID IS NULL) OR (:LEVEL_ID < 2))

        UNION

        SELECT L2.OBJ_ID, L111.OBJ_ID
        FROM LINKS L111
        JOIN LINKS L2
        ON L2.PARENT_ID = L111.OBJ_ID
        AND L2.OBJ_TYPE_ID = 2
        AND L2.DATE_DEL IS NULL
        WHERE L111.PARENT_ID IS NULL
        AND L111.OBJ_TYPE_ID = 111
        AND L111.DATE_DEL IS NULL
        AND :LEVEL_ID = 2

        UNION

        SELECT FIRST 500 L2.OBJ_ID, L111.OBJ_ID
        FROM LINKS L112
        JOIN LINKS L111
        ON L111.PARENT_ID = L112.OBJ_ID
        AND L111.OBJ_TYPE_ID = 111
        AND L111.DATE_DEL IS NULL
        JOIN LINKS L2
        ON L2.PARENT_ID = L111.OBJ_ID
        AND L2.OBJ_TYPE_ID = 2
        AND L2.DATE_DEL IS NULL
        WHERE L112.PARENT_ID IS NULL
        AND L112.OBJ_TYPE_ID = 112
        AND L112.DATE_DEL IS NULL
        AND :LEVEL_ID = 3

        INTO :SCHOOL_ID, :DISTRICT_ID
    DO
    BEGIN
        FOR
            SELECT L10.OBJ_ID, 0
            FROM LINKS L7
            JOIN LINKS L8
            ON L8.PARENT_ID = L7.OBJ_ID
            AND L8.OBJ_TYPE_ID = 8
            AND L8.DATE_DEL IS NULL
            JOIN LINKS L9
            ON L9.PARENT_ID = L8.OBJ_ID
            AND L9.OBJ_TYPE_ID = 9
            AND L9.DATE_DEL IS NULL
            JOIN LINKS L10
            ON L10.PARENT_ID = L9.OBJ_ID
            AND L10.OBJ_TYPE_ID = 10
            AND L10.DATE_DEL IS NULL
            WHERE L7.PARENT_ID = :SCHOOL_ID
            AND L7.OBJ_TYPE_ID = 7
            AND L7.DATE_DEL IS NULL

            UNION

            SELECT L10.OBJ_ID, 1
            FROM LINKS L78
            JOIN LINKS L82
            ON L82.PARENT_ID = L78.OBJ_ID
            AND L82.OBJ_TYPE_ID = 82
            AND L82.DATE_DEL IS NULL
            JOIN LINKS L10
            ON L10.PARENT_ID = L82.OBJ_ID
            AND L10.OBJ_TYPE_ID = 10
            AND L10.DATE_DEL IS NULL
            WHERE L78.PARENT_ID = :SCHOOL_ID
            AND L78.OBJ_TYPE_ID = 78
            AND L78.DATE_DEL IS NULL

            INTO :PUPIL_ID, :DROPOUT
        DO
        BEGIN
            SNILS = NULL;
            FIRSTNAME = NULL;
            LASTNAME = NULL;
            SECONDNAME = NULL;
            DOCTYPE = NULL;
            DOCSERIA = NULL;
            DOCNUMBER = NULL;
            DOB = NULL;
            
            SELECT V
            FROM VAL_GET(:PUPIL_ID,1409)
            INTO :SNILS;

            SELECT V
            FROM VAL_GET(:PUPIL_ID,55)
            INTO :LASTNAME;

            SELECT V
            FROM VAL_GET(:PUPIL_ID,56)
            INTO :FIRSTNAME;

            SELECT V
            FROM VAL_GET(:PUPIL_ID,57)
            INTO :SECONDNAME;

            SELECT D
            FROM VAL_GET(:PUPIL_ID,89)
            INTO :DOB;

            IF (SNILS = '') THEN
            BEGIN
                SNILS = NULL;
            END
            ELSE
            BEGIN
                SNILS = REPLACE(REPLACE(SNILS,  ' ', ''),  '-', '');
            END
                
            FIRSTNAME = REPLACE(REPLACE(REPLACE(REPLACE(LOWER(FIRSTNAME),  'ё', 'е'),  ' ', ''),  '-', ''), 'й', 'и');
            LASTNAME = REPLACE(REPLACE(REPLACE(REPLACE(LOWER(LASTNAME),  'ё', 'е'),  ' ', ''),  '-', ''), 'й', 'и');
            SECONDNAME = REPLACE(REPLACE(REPLACE(REPLACE(LOWER(SECONDNAME),  'ё', 'е'),  ' ', ''),  '-', ''), 'й', 'и');

            UPDATE OR INSERT INTO SNILS_INDEX(
                SNILS,
                FIRSTNAME,
                SECONDNAME,
                LASTNAME,
                DOB,
                PUPIL_ID,
                DROPOUT
            ) VALUES(
                :SNILS,
                :FIRSTNAME,
                :SECONDNAME,
                :LASTNAME,
                :DOB,
                :PUPIL_ID,
                :DROPOUT
            );
            
            FOR
                SELECT L79.OBJ_ID,LV.LISTVAL_ID, LS.VAL, LN.VAL
                FROM LINKS L79
                JOIN VALL LV
                ON LV.OBJ_ID = L79.OBJ_ID
                AND LV.PARAM_ID = 441
                AND LV.IS_DEL = 0
                LEFT JOIN VALS LS
                ON LS.OBJ_ID = L79.OBJ_ID
                AND LS.PARAM_ID = 442
                AND LS.IS_DEL = 0
                LEFT JOIN VALS LN
                ON LN.OBJ_ID = L79.OBJ_ID
                AND LN.PARAM_ID = 559
                AND LN.IS_DEL = 0
                WHERE L79.PARENT_ID = :PUPIL_ID
                AND L79.DATE_DEL IS NULL
                AND L79.OBJ_TYPE_ID = 79
                INTO :DOC_ID,:DOCTYPE,:DOCSERIA,:DOCNUMBER
            DO
            BEGIN
                DOCSERIA = REPLACE(DOCSERIA,'У','Y');
                DOCSERIA = REPLACE(DOCSERIA,'К','K');
                DOCSERIA = REPLACE(DOCSERIA,'Е','E');
                DOCSERIA = REPLACE(DOCSERIA,'Н','H');
                DOCSERIA = REPLACE(DOCSERIA,'Х','X');
                DOCSERIA = REPLACE(DOCSERIA,'В','B');
                DOCSERIA = REPLACE(DOCSERIA,'А','A');
                DOCSERIA = REPLACE(DOCSERIA,'Р','P');
                DOCSERIA = REPLACE(DOCSERIA,'О','O');
                DOCSERIA = REPLACE(DOCSERIA,'С','C');
                DOCSERIA = REPLACE(DOCSERIA,'М','M');
                DOCSERIA = REPLACE(DOCSERIA,'Т','T');
                DOCSERIA = REPLACE(REPLACE(LOWER(DOCSERIA),' ', ''),  '-', '');
                
                DOCNUMBER = REPLACE(REPLACE(DOCNUMBER,  ' ', ''),  '-', '');

                UPDATE OR INSERT INTO DOC_INDEX VALUES(:DOC_ID,:PUPIL_ID,:DOCTYPE,:DOCSERIA,:DOCNUMBER);
            END
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CUP_EXPORT_COMPONENTS (
    PLAN_ID BIGINT)
RETURNS (
    CMP_ID BIGINT,
    CMP_INDEX BIGINT,
    SUBJ_LINK_ID BIGINT,
    SUBJECT_ID BIGINT,
    SUBJECT_INDEX BIGINT,
    SUBJECT_NAME VARCHAR(1000),
    SUBJECT_CODE VARCHAR(100),
    MASTER_ID BIGINT,
    MASTER_NAME VARCHAR(1000),
    MASTER_CODE VARCHAR(100))
AS
begin

  FOR
    SELECT L49.OBJ_ID, V372.LISTVAL_ID, L51.LINK_ID, L51.OBJ_ID, L51.COST, C51.CAPTION, V377.VAL
    FROM LINKS L49
    JOIN VALL V372 ON V372.OBJ_ID = L49.OBJ_ID AND V372.PARAM_ID = 372 AND V372.IS_DEL = 0
    JOIN LINKS L51 ON L51.PARENT_ID = L49.OBJ_ID AND L51.OBJ_TYPE_ID = 51 AND L51.DATE_DEL IS NULL
    LEFT JOIN OBJECT_CAPTION_GET(L51.OBJ_ID) C51 ON 1 = 1
    LEFT JOIN VALS V377 ON V377.OBJ_ID = L51.OBJ_ID AND V377.PARAM_ID = 377 AND V377.IS_DEL = 0
    WHERE L49.PARENT_ID = :PLAN_ID AND L49.OBJ_TYPE_ID = 49 AND L49.DATE_DEL IS NULL
    ORDER BY V372.LISTVAL_ID, L51.COST, C51.CAPTION
    INTO :CMP_ID, :CMP_INDEX, :SUBJ_LINK_ID, :SUBJECT_ID, :SUBJECT_INDEX, :SUBJECT_NAME, :SUBJECT_CODE
  DO
  BEGIN
    MASTER_ID = NULL;
    MASTER_NAME = NULL;
    MASTER_CODE = NULL;

    -- Связка с эталонным предметом шаблона
    SELECT V2718.VAL, C51.CAPTION, V377.VAL
    FROM LINKS L349
    JOIN VALR V2719 ON V2719.OBJ_ID = L349.OBJ_ID AND V2719.PARAM_ID = 2719 AND V2719.IS_DEL = 0 AND V2719.VAL = :SUBJECT_ID
    JOIN VALR V2718 ON V2718.OBJ_ID = L349.OBJ_ID AND V2718.PARAM_ID = 2718 AND V2718.IS_DEL = 0
    LEFT JOIN OBJECT_CAPTION_GET(V2718.VAL) C51 ON 1 = 1
    LEFT JOIN VALS V377 ON V377.OBJ_ID = V2718.VAL AND V377.PARAM_ID = 377 AND V377.IS_DEL = 0
    WHERE L349.PARENT_ID = :CMP_ID AND L349.OBJ_TYPE_ID = 349 AND L349.DATE_DEL IS NULL
    INTO :MASTER_ID, :MASTER_NAME, :MASTER_CODE;

    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CUP_EXPORT_LOADS (
    PLAN_ID BIGINT)
RETURNS (
    SUBJECT_ID BIGINT,
    STAGE_ID BIGINT,
    LOAD_ID BIGINT,
    LOAD_WEEKS INTEGER,
    LOAD_HOURS INTEGER)
AS
begin

  FOR
    -- Вместо реального ID предмета возвращаем линк компонент -> предмет
    SELECT L56.OBJ_ID, L54.OBJ_ID, L51.LINK_ID, V2547.VAL, V385.VAL
    FROM LINKS L54
    JOIN LINKS L56 ON L56.PARENT_ID = L54.OBJ_ID AND L56.OBJ_TYPE_ID = 56 AND L56.DATE_DEL IS NULL
    JOIN LINKS L49 ON L49.PARENT_ID = L54.PARENT_ID AND L49.OBJ_TYPE_ID = 49 AND L56.DATE_DEL IS NULL
    JOIN LINKS L49_56 ON L49_56.PARENT_ID = L49.OBJ_ID AND L49_56.OBJ_ID = L56.OBJ_ID AND L49_56.DATE_DEL IS NULL
    JOIN LINKS L51 ON L51.PARENT_ID = L49.OBJ_ID AND L51.OBJ_TYPE_ID = 51 AND L51.DATE_DEL IS NULL
    JOIN LINKS L51_56 ON L51_56.PARENT_ID = L51.OBJ_ID AND L51_56.OBJ_ID = L56.OBJ_ID AND L51_56.DATE_DEL IS NULL
    -- Нагрузка
    JOIN VALI V2547 ON V2547.OBJ_ID = L56.OBJ_ID AND V2547.PARAM_ID = 2547 AND V2547.IS_DEL = 0
    JOIN VALI V385 ON V385.OBJ_ID = L56.OBJ_ID AND V385.PARAM_ID = 385 AND V385.IS_DEL = 0 AND V385.VAL > 0
    WHERE L54.PARENT_ID = :PLAN_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
    INTO :LOAD_ID, :STAGE_ID, :SUBJECT_ID, :LOAD_WEEKS, :LOAD_HOURS
  DO
  BEGIN
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CURGROUP_MOVE_PUPIL (
    I$PUPIL_ID BIGINT,
    I$CURGROUP_ID BIGINT,
    I$USER_ID BIGINT,
    I$MOVE_TYPE_ID INTEGER = null,
    I$MOVE_DATE DATE = null,
    I$ORDER_NUMBER VARCHAR(100) = null,
    I$ORDER_DATE DATE = null,
    I$MOVEMENT_SOURCE_ID BIGINT = 902,
    I$LINK_CURGROUP SMALLINT = 0)
AS
declare variable V$IS_OUTLESSON smallint;
declare variable V$BLOB_ID bigint;
declare variable V$MOVEMENT_ID bigint;
declare variable V$STAGE_ID bigint;
declare variable V$CAPTION varchar(1000);
declare variable V$FORM_OF_TRAINING smallint;
declare variable V$LINK_ID bigint;
declare variable V$LAST_DATE date;
BEGIN

  -- Все перенесено в VARGRP_MOVE_PUPIL

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CURRENT_DATE_GET (
    I$DT DATE = CURRENT_DATE,
    I$FORMAT VARCHAR(100) = 'DD.MM.YYYY')
RETURNS (
    DT VARCHAR(100))
AS
DECLARE VARIABLE Y SMALLINT;
DECLARE VARIABLE M SMALLINT;
DECLARE VARIABLE D SMALLINT;
BEGIN
    DT = '';
    I$FORMAT = UPPER(:I$FORMAT);
    Y = EXTRACT(YEAR  FROM I$DT);
    M = EXTRACT(MONTH FROM I$DT);
    D = EXTRACT(DAY   FROM I$DT);

    IF (:I$FORMAT IN ('DD MONTH YYYY', 'MONTH')) THEN
    BEGIN
        DT = TRIM(CASE M
                 WHEN  1 THEN 'января'
                 WHEN  2 THEN 'февраля'
                 WHEN  3 THEN 'марта'
                 WHEN  4 THEN 'апреля'
                 WHEN  5 THEN 'мая'
                 WHEN  6 THEN 'июня'
                 WHEN  7 THEN 'июля'
                 WHEN  8 THEN 'августа'
                 WHEN  9 THEN 'сентября'
                 WHEN 10 THEN 'октября'
                 WHEN 11 THEN 'ноября'
                 WHEN 12 THEN 'декабря'
             END);
        IF (:I$FORMAT = 'DD MONTH YYYY') THEN
        BEGIN
            DT = D || ' ' || DT || ' ' || Y;
            IF (D < 10) THEN DT = '0' || DT;
        END
    END

    IF (:I$FORMAT = 'DD') THEN
    BEGIN
        DT = D;
        IF (D < 10) THEN DT = '0' || DT;
    END

    IF (:I$FORMAT = 'YY') THEN
    BEGIN
        DT = SUBSTRING(Y FROM CHAR_LENGTH(Y) - 1 FOR 2);
    END

    IF (:I$FORMAT = 'DD.MM.YYYY' OR :I$FORMAT IS NULL OR :I$FORMAT = '' OR :DT = '') THEN
    BEGIN
        DT = M || '.' || Y;
        IF (M < 10) THEN DT = '0' || DT;
        DT = D || '.' || DT;
        IF (D < 10) THEN DT = '0' || DT;
    END

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CURRENT_SCHOOL_YEAR_GET (
    I$DT DATE = CURRENT_DATE)
RETURNS (
    Y1 SMALLINT,
    Y2 SMALLINT,
    V1 VARCHAR(12),
    V2 VARCHAR(12))
AS
DECLARE VARIABLE M SMALLINT;
BEGIN
    Y1 = EXTRACT(YEAR FROM I$DT);
    M = EXTRACT(MONTH FROM I$DT);
    IF (M < 9) THEN Y1 = Y1 - 1;
    Y2 = Y1 + 1;
    V1 = Y1 || '/' || Y2;
    V2 = Y1 || ' - ' || Y2;
    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CURRENT_TIME_GET (
    I$T TIME = CURRENT_TIME)
RETURNS (
    T CHAR(5))
AS
DECLARE VARIABLE H SMALLINT;
DECLARE VARIABLE M SMALLINT;
BEGIN
    H = EXTRACT(HOUR FROM I$T);
    M = EXTRACT(MINUTE FROM I$T);

    IF (M > 9) THEN T = ':' || M; ELSE  T = ':0' || M;
    IF (H > 9) THEN T = H || T; ELSE T = '0' || H || T;

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CURRENT_YEAR_GET (
    I$DT DATE = CURRENT_DATE)
RETURNS (
    Y SMALLINT)
AS
BEGIN
    Y = EXTRACT(YEAR  FROM I$DT);
    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CURRICULUM_CONTROL_REPORT1 (
    I$OBJ_ID BIGINT NOT NULL,
    I$STAGE SMALLINT = 0)
RETURNS (
    OOOD_SHORT_NAME VARCHAR(5000),
    OOOD_NUMBER VARCHAR(10),
    DISTRICT_NAME VARCHAR(255),
    EDUCATION_PROGRAM_LEVEL VARCHAR(255),
    PLAN_NAME VARCHAR(255),
    EDUCATION_STANDART VARCHAR(20),
    EXT_SUBJECTS VARCHAR(1000),
    MISSED_SUBJECTS VARCHAR(4000),
    ODD_SUBJECTS VARCHAR(4000),
    MATCH_HOURS_ALL VARCHAR(10),
    MATCH_HOURS_FIX VARCHAR(10),
    MATCH_HOURS_FIL VARCHAR(10))
AS
declare variable V$MATCH_ID bigint;
declare variable V$SMIR_ID bigint;
declare variable V$DISTRICT_ID bigint;
declare variable V$SCHOOL_ID bigint;
declare variable V$CURRICULUM_ID bigint;
declare variable V$EDUCATION_PROGRAM_ID bigint;
declare variable V$OBJ_ID bigint;
declare variable V$PLAN_ID bigint;
BEGIN

    -- STAGE: 0 = НОО, 1 = ООО

    FOR
        SELECT L111.OBJ_ID
        FROM LINKS L111
        WHERE L111.PARENT_ID = :I$OBJ_ID AND L111.OBJ_TYPE_ID = 111 AND L111.DATE_DEL IS NULL
        UNION ALL
        SELECT O111.OBJ_ID
        FROM OBJECTS O111
        WHERE O111.OBJ_ID = :I$OBJ_ID AND O111.TYPE_ID = 111
        INTO :V$DISTRICT_ID
    DO
    BEGIN
        FOR
            SELECT L2.OBJ_ID, L162.OBJ_ID, L305.OBJ_ID, V2482.VAL, LP57.PARENT_ID, LP57.OBJ_ID,
                IIF(V2486.LISTVAL_ID = 2, 'Да', 'Нет'), IIF(V2488.LISTVAL_ID = 2, 'Да', 'Нет'), IIF(V3157.LISTVAL_ID = 2, 'Да', 'Нет')
            FROM LINKS L2
            JOIN LINKS L162 ON L162.PARENT_ID = L2.OBJ_ID AND L162.OBJ_TYPE_ID = 162 AND L162.DATE_DEL IS NULL
            JOIN LINKS L305 ON L305.PARENT_ID = L162.OBJ_ID AND L305.OBJ_TYPE_ID = 305 AND L305.DATE_DEL IS NULL
            JOIN VALR V2482 ON V2482.OBJ_ID = L305.OBJ_ID AND V2482.PARAM_ID = 2482 AND V2482.IS_DEL = 0
            JOIN VALL V2486 ON V2486.OBJ_ID = L305.OBJ_ID AND V2486.PARAM_ID = 2486 AND V2486.IS_DEL = 0
            JOIN VALL V2488 ON V2488.OBJ_ID = L305.OBJ_ID AND V2488.PARAM_ID = 2488 AND V2488.IS_DEL = 0
            LEFT JOIN VALL V3157 ON V3157.OBJ_ID = L305.OBJ_ID AND V3157.PARAM_ID = 3157 AND V3157.IS_DEL = 0
            JOIN LINKS LP57 ON LP57.OBJ_ID = V2482.VAL AND LP57.PARENT_TYPE_ID = 57 AND LP57.DATE_DEL IS NULL
            JOIN VALL V1594 ON V1594.OBJ_ID = LP57.PARENT_ID AND V1594.PARAM_ID = 1594 AND V1594.IS_DEL = 0 AND V1594.LISTVAL_ID = IIF(:I$STAGE = 0, 5339, 5341)
            -- Фильтр по подчинению и не-частные школы
            JOIN VALS V6 ON V6.OBJ_ID = L2.OBJ_ID AND V6.PARAM_ID = 6 AND V6.IS_DEL = 0 AND V6.VAL = 'Комитет по образованию Санкт-Петербурга'
            LEFT JOIN VALL V8 ON V8.OBJ_ID = L2.OBJ_ID AND V8.PARAM_ID = 8 AND V8.IS_DEL = 0
            WHERE L2.PARENT_ID = :V$DISTRICT_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND (V8.LISTVAL_ID IS NULL OR V8.LISTVAL_ID <> 5404)
            ORDER BY 1, 3
            INTO :V$SCHOOL_ID, :V$SMIR_ID, :V$MATCH_ID, :V$CURRICULUM_ID, :V$EDUCATION_PROGRAM_ID, :V$PLAN_ID,
                :MATCH_HOURS_ALL, :MATCH_HOURS_FIX, :MATCH_HOURS_FIL
        DO
        BEGIN

            V$OBJ_ID = NULL;

            SELECT FIRST 1 L306.OBJ_ID
            FROM LINKS L306
            JOIN VALR V2490 ON V2490.OBJ_ID = L306.OBJ_ID AND V2490.PARAM_ID = 2490 AND V2490.IS_DEL = 0 AND V2490.VAL = :V$PLAN_ID
            WHERE L306.PARENT_ID = :V$SMIR_ID AND L306.OBJ_TYPE_ID = 306 AND L306.DATE_DEL IS NULL
            INTO :V$OBJ_ID;

            SELECT V FROM VAL_GET(:V$SCHOOL_ID, 2) INTO :OOOD_SHORT_NAME;
            SELECT V FROM VAL_GET(:V$SCHOOL_ID, 17) INTO :OOOD_NUMBER;
            SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$DISTRICT_ID) INTO :DISTRICT_NAME;
            SELECT V FROM VAL_GET(:V$CURRICULUM_ID, 3014) INTO :EDUCATION_STANDART;
            SELECT V FROM VAL_GET(:V$EDUCATION_PROGRAM_ID, 1594) INTO :EDUCATION_PROGRAM_LEVEL;

            IF(V$OBJ_ID IS NULL) THEN
            BEGIN
                MISSED_SUBJECTS = '';
                ODD_SUBJECTS = '';
            END
            ELSE
            BEGIN
                SELECT V FROM VAL_GET(:V$OBJ_ID, 2491) INTO :MISSED_SUBJECTS;
                SELECT V FROM VAL_GET(:V$OBJ_ID, 2492) INTO :ODD_SUBJECTS;
            END

            SELECT V FROM VAL_GET(:V$MATCH_ID, 3160) INTO :EXT_SUBJECTS;
            SELECT V FROM VAL_GET(:V$PLAN_ID, 3012) INTO :PLAN_NAME;

            SUSPEND;
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CURRICULUM_CONTROL_REPORT2 (
    I$OBJ_ID BIGINT NOT NULL)
RETURNS (
    OOOD_SHORT_NAME VARCHAR(5000),
    OOOD_NUMBER VARCHAR(10),
    DISTRICT_NAME VARCHAR(255),
    EDUCATION_PROGRAM_LEVEL VARCHAR(255),
    EDUCATION_STANDART VARCHAR(20),
    CURRICULUM_DONE FLOAT,
    PTP_DONE FLOAT)
AS
declare variable V$DISTRICT_ID bigint;
declare variable V$SCHOOL_ID bigint;
declare variable V$CURRICULUM_ID bigint;
declare variable V$EDUCATION_PROGRAM_ID bigint;
declare variable V$OBJ_ID bigint;
BEGIN
    FOR
        SELECT L111.OBJ_ID

        FROM LINKS L111

        WHERE L111.PARENT_ID = :I$OBJ_ID
        AND L111.OBJ_TYPE_ID = 111
        AND L111.DATE_DEL IS NULL

        UNION ALL

        SELECT O111.OBJ_ID
        FROM OBJECTS O111

        WHERE O111.OBJ_ID = :I$OBJ_ID
        AND O111.TYPE_ID = 111

        INTO :V$DISTRICT_ID
    DO
    BEGIN
        FOR
            SELECT L2.OBJ_ID,
                   LP50.PARENT_ID,
                   LP57.PARENT_ID,
                   L316.OBJ_ID

            FROM LINKS L2

            JOIN LINKS L162
            ON L162.PARENT_ID = L2.OBJ_ID
            AND L162.OBJ_TYPE_ID = 162
            AND L162.DATE_DEL IS NULL

            JOIN LINKS L316
            ON L316.PARENT_ID = L162.OBJ_ID
            AND L316.OBJ_TYPE_ID = 316
            AND L316.DATE_DEL IS NULL

            JOIN VALR V2523
            ON V2523.OBJ_ID = L316.OBJ_ID
            AND V2523.PARAM_ID = 2523
            AND V2523.IS_DEL = 0

            JOIN LINKS LP54
            ON LP54.OBJ_ID = V2523.VAL
            AND LP54.PARENT_TYPE_ID = 54
            AND LP54.DATE_DEL IS NULL

            JOIN LINKS LP50
            ON LP50.OBJ_ID = LP54.PARENT_ID
            AND LP50.PARENT_TYPE_ID = 50
            AND LP50.DATE_DEL IS NULL

            JOIN LINKS LP57
            ON LP57.OBJ_ID = LP50.PARENT_ID
            AND LP57.PARENT_TYPE_ID = 57
            AND LP57.DATE_DEL IS NULL

            WHERE L2.PARENT_ID = :V$DISTRICT_ID
            AND L2.OBJ_TYPE_ID = 2
            AND L2.DATE_DEL IS NULL

            INTO :V$SCHOOL_ID,
                 :V$CURRICULUM_ID,
                 :V$EDUCATION_PROGRAM_ID,
                 :V$OBJ_ID
        DO
        BEGIN
            SELECT V
            FROM VAL_GET(:V$SCHOOL_ID, 2)
            INTO :OOOD_SHORT_NAME;

            SELECT V
            FROM VAL_GET(:V$SCHOOL_ID, 17)
            INTO :OOOD_NUMBER;

            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:V$DISTRICT_ID)
            INTO :DISTRICT_NAME;

            SELECT V
            FROM VAL_GET(:V$CURRICULUM_ID, 2478)
            INTO :EDUCATION_STANDART;

            SELECT V
            FROM VAL_GET(:V$EDUCATION_PROGRAM_ID, 1594)
            INTO :EDUCATION_PROGRAM_LEVEL;

            SELECT V
            FROM VAL_GET(:V$OBJ_ID, 2530)
            INTO :CURRICULUM_DONE;

            SELECT V
            FROM VAL_GET(:V$OBJ_ID, 2529)
            INTO :PTP_DONE;

            SUSPEND;
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CURRICULUM_CONTROL_REPORT3 (
    I$OBJ_ID BIGINT NOT NULL)
RETURNS (
    OOOD_SHORT_NAME VARCHAR(5000),
    OOOD_NUMBER VARCHAR(10),
    DISTRICT_NAME VARCHAR(255),
    EDUCATION_PROGRAM_LEVEL VARCHAR(255),
    EDUCATION_STANDART VARCHAR(20),
    LESSON_DONE FLOAT,
    LAB_DONE FLOAT)
AS
declare variable V$DISTRICT_ID bigint;
declare variable V$SCHOOL_ID bigint;
declare variable V$CURRICULUM_ID bigint;
declare variable V$EDUCATION_PROGRAM_ID bigint;
declare variable V$OBJ_ID bigint;
BEGIN
    FOR
        SELECT L111.OBJ_ID

        FROM LINKS L111

        WHERE L111.PARENT_ID = :I$OBJ_ID
        AND L111.OBJ_TYPE_ID = 111
        AND L111.DATE_DEL IS NULL

        UNION ALL

        SELECT O111.OBJ_ID
        FROM OBJECTS O111

        WHERE O111.OBJ_ID = :I$OBJ_ID
        AND O111.TYPE_ID = 111

        INTO :V$DISTRICT_ID
    DO
    BEGIN
        FOR
            SELECT L2.OBJ_ID,
                   LP50.PARENT_ID,
                   LP57.PARENT_ID,
                   L317.OBJ_ID

            FROM LINKS L2

            JOIN LINKS L162
            ON L162.PARENT_ID = L2.OBJ_ID
            AND L162.OBJ_TYPE_ID = 162
            AND L162.DATE_DEL IS NULL

            JOIN LINKS L317
            ON L317.PARENT_ID = L162.OBJ_ID
            AND L317.OBJ_TYPE_ID = 317
            AND L317.DATE_DEL IS NULL

            JOIN VALR V2533
            ON V2533.OBJ_ID = L317.OBJ_ID
            AND V2533.PARAM_ID = 2533
            AND V2533.IS_DEL = 0

            JOIN LINKS LP54
            ON LP54.OBJ_ID = V2533.VAL
            AND LP54.PARENT_TYPE_ID = 54
            AND LP54.DATE_DEL IS NULL

            JOIN LINKS LP50
            ON LP50.OBJ_ID = LP54.PARENT_ID
            AND LP50.PARENT_TYPE_ID = 50
            AND LP50.DATE_DEL IS NULL

            JOIN LINKS LP57
            ON LP57.OBJ_ID = LP50.PARENT_ID
            AND LP57.PARENT_TYPE_ID = 57
            AND LP57.DATE_DEL IS NULL

            WHERE L2.PARENT_ID = :V$DISTRICT_ID
            AND L2.OBJ_TYPE_ID = 2
            AND L2.DATE_DEL IS NULL

            INTO :V$SCHOOL_ID,
                 :V$CURRICULUM_ID,
                 :V$EDUCATION_PROGRAM_ID,
                 :V$OBJ_ID
        DO
        BEGIN
            SELECT V
            FROM VAL_GET(:V$SCHOOL_ID, 2)
            INTO :OOOD_SHORT_NAME;

            SELECT V
            FROM VAL_GET(:V$SCHOOL_ID, 17)
            INTO :OOOD_NUMBER;

            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:V$DISTRICT_ID)
            INTO :DISTRICT_NAME;

            SELECT V
            FROM VAL_GET(:V$CURRICULUM_ID, 2478)
            INTO :EDUCATION_STANDART;

            SELECT V
            FROM VAL_GET(:V$EDUCATION_PROGRAM_ID, 1594)
            INTO :EDUCATION_PROGRAM_LEVEL;

            SELECT V
            FROM VAL_GET(:V$OBJ_ID, 2536)
            INTO :LESSON_DONE;

            LAB_DONE = NULL;
            SUSPEND;
        END

        FOR
            SELECT L2.OBJ_ID,
                   LP50.PARENT_ID,
                   LP57.PARENT_ID,
                   L319.OBJ_ID

            FROM LINKS L2

            JOIN LINKS L162
            ON L162.PARENT_ID = L2.OBJ_ID
            AND L162.OBJ_TYPE_ID = 162
            AND L162.DATE_DEL IS NULL

            JOIN LINKS L319
            ON L319.PARENT_ID = L162.OBJ_ID
            AND L319.OBJ_TYPE_ID = 319
            AND L319.DATE_DEL IS NULL

            JOIN VALR V2538
            ON V2538.OBJ_ID = L319.OBJ_ID
            AND V2538.PARAM_ID = 2538
            AND V2538.IS_DEL = 0

            JOIN LINKS LP54
            ON LP54.OBJ_ID = V2538.VAL
            AND LP54.PARENT_TYPE_ID = 54
            AND LP54.DATE_DEL IS NULL

            JOIN LINKS LP50
            ON LP50.OBJ_ID = LP54.PARENT_ID
            AND LP50.PARENT_TYPE_ID = 50
            AND LP50.DATE_DEL IS NULL

            JOIN LINKS LP57
            ON LP57.OBJ_ID = LP50.PARENT_ID
            AND LP57.PARENT_TYPE_ID = 57
            AND LP57.DATE_DEL IS NULL

            WHERE L2.PARENT_ID = :V$DISTRICT_ID
            AND L2.OBJ_TYPE_ID = 2
            AND L2.DATE_DEL IS NULL

            INTO :V$SCHOOL_ID,
                 :V$CURRICULUM_ID,
                 :V$EDUCATION_PROGRAM_ID,
                 :V$OBJ_ID
        DO
        BEGIN
            SELECT V
            FROM VAL_GET(:V$SCHOOL_ID, 2)
            INTO :OOOD_SHORT_NAME;

            SELECT V
            FROM VAL_GET(:V$SCHOOL_ID, 17)
            INTO :OOOD_NUMBER;

            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:V$DISTRICT_ID)
            INTO :DISTRICT_NAME;

            SELECT V
            FROM VAL_GET(:V$CURRICULUM_ID, 2478)
            INTO :EDUCATION_STANDART;

            SELECT V
            FROM VAL_GET(:V$EDUCATION_PROGRAM_ID, 1594)
            INTO :EDUCATION_PROGRAM_LEVEL;

            LESSON_DONE = NULL;

            SELECT V
            FROM VAL_GET(:V$OBJ_ID, 2542)
            INTO :LAB_DONE;

            SUSPEND;
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CURRICULUM_CONTROL_REPORT4 (
    I$OBJ_ID BIGINT)
RETURNS (
    DISTRICT_NAME VARCHAR(255),
    OOOD_SHORT_NAME VARCHAR(1000),
    OOOD_NUMBER VARCHAR(20),
    PLAN_NAME VARCHAR(1000),
    STD_NAME VARCHAR(200),
    WEEK_DAYS VARCHAR(100),
    PROFILE_NAME VARCHAR(255),
    PROF_SUBJECTS VARCHAR(4000),
    MATCH_1 VARCHAR(10),
    MATCH_2 VARCHAR(10),
    MATCH_3 VARCHAR(10),
    MATCH_4 VARCHAR(10),
    MATCH_6A VARCHAR(10),
    MATCH_7 VARCHAR(10))
AS
declare variable V$PLAN_ID bigint;
declare variable V$WEEK_LID bigint;
declare variable V$PROFILE_LID bigint;
declare variable V$DISTRICT_ID bigint;
declare variable V$SCHOOL_ID bigint;
declare variable V$STD_NUM bigint;
begin

    FOR
        SELECT L111.OBJ_ID
        FROM LINKS L111
        WHERE L111.PARENT_ID = :I$OBJ_ID AND L111.OBJ_TYPE_ID = 111 AND L111.DATE_DEL IS NULL
        UNION ALL
        SELECT O111.OBJ_ID
        FROM OBJECTS O111
        WHERE O111.OBJ_ID = :I$OBJ_ID AND O111.TYPE_ID = 111
        INTO :V$DISTRICT_ID
    DO
    BEGIN
        FOR
            SELECT L2.OBJ_ID, V2745.VAL, V3014.LISTVAL_ID, V2746.LISTVAL_ID, V2747.LISTVAL_ID, V2751.VAL,
                IIF(V2752.LISTVAL_ID IS NULL, '', IIF(V2752.LISTVAL_ID = 2, 'Да', 'Нет')), -- предметы инвариантной части +
                IIF(V2925.LISTVAL_ID IS NULL, '', IIF(V2925.LISTVAL_ID = 2, 'Да', 'Нет')), -- контроль количества преметов
                IIF(V2754.LISTVAL_ID IS NULL, '', IIF(V2754.LISTVAL_ID = 2, 'Да', 'Нет')), -- наличие/отсутствие профильных предметов +
                IIF(V2755.LISTVAL_ID IS NULL, '', IIF(V2755.LISTVAL_ID = 2, 'Да', 'Нет')), -- часы на базовые/профильные +
                IIF(V2926.LISTVAL_ID IS NULL, '', IIF(V2926.LISTVAL_ID = 2, 'Да', 'Нет')), -- общие часы
                IIF(V2758.LISTVAL_ID IS NULL, '', IIF(V2758.LISTVAL_ID = 2, 'Да', 'Нет'))  -- предельная наполняемость
            FROM LINKS L2
            JOIN LINKS L162 ON L162.PARENT_ID = L2.OBJ_ID AND L162.OBJ_TYPE_ID = 162 AND L162.DATE_DEL IS NULL
            JOIN LINKS L357 ON L357.PARENT_ID = L162.OBJ_ID AND L357.OBJ_TYPE_ID = 357 AND L357.DATE_DEL IS NULL
            JOIN VALR V2745 ON V2745.OBJ_ID = L357.OBJ_ID AND V2745.PARAM_ID = 2745 AND V2745.IS_DEL = 0
            LEFT JOIN VALL V2746 ON V2746.OBJ_ID = L357.OBJ_ID AND V2746.PARAM_ID = 2746 AND V2746.IS_DEL = 0
            LEFT JOIN VALL V2747 ON V2747.OBJ_ID = L357.OBJ_ID AND V2747.PARAM_ID = 2747 AND V2747.IS_DEL = 0
            LEFT JOIN VALL V3014 ON V3014.OBJ_ID = V2745.VAL AND V3014.PARAM_ID = 3014 AND V3014.IS_DEL = 0
            LEFT JOIN VALS V2751 ON V2751.OBJ_ID = L357.OBJ_ID AND V2751.PARAM_ID = 2751 AND V2751.IS_DEL = 0
            LEFT JOIN VALL V2752 ON V2752.OBJ_ID = L357.OBJ_ID AND V2752.PARAM_ID = 2752 AND V2752.IS_DEL = 0
            LEFT JOIN VALL V2754 ON V2754.OBJ_ID = L357.OBJ_ID AND V2754.PARAM_ID = 2754 AND V2754.IS_DEL = 0
            LEFT JOIN VALL V2755 ON V2755.OBJ_ID = L357.OBJ_ID AND V2755.PARAM_ID = 2755 AND V2755.IS_DEL = 0
            LEFT JOIN VALL V2758 ON V2758.OBJ_ID = L357.OBJ_ID AND V2758.PARAM_ID = 2758 AND V2758.IS_DEL = 0
            LEFT JOIN VALL V2925 ON V2925.OBJ_ID = L357.OBJ_ID AND V2925.PARAM_ID = 2925 AND V2925.IS_DEL = 0
            LEFT JOIN VALL V2926 ON V2926.OBJ_ID = L357.OBJ_ID AND V2926.PARAM_ID = 2926 AND V2926.IS_DEL = 0
            -- Фильтр по подчинению и не-частные школы
            JOIN VALS V6 ON V6.OBJ_ID = L2.OBJ_ID AND V6.PARAM_ID = 6 AND V6.IS_DEL = 0 AND V6.VAL = 'Комитет по образованию Санкт-Петербурга'
            LEFT JOIN VALL V8 ON V8.OBJ_ID = L2.OBJ_ID AND V8.PARAM_ID = 8 AND V8.IS_DEL = 0
            WHERE L2.PARENT_ID = :V$DISTRICT_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND (V8.LISTVAL_ID IS NULL OR V8.LISTVAL_ID <> 5404)
            INTO :V$SCHOOL_ID, :V$PLAN_ID, :V$STD_NUM, :V$WEEK_LID, :V$PROFILE_LID, :PROF_SUBJECTS,
              :MATCH_1, :MATCH_2, :MATCH_3, :MATCH_4, :MATCH_6A, :MATCH_7
        DO
        BEGIN
            SELECT V FROM VAL_GET(:V$SCHOOL_ID, 2) INTO :OOOD_SHORT_NAME;
            SELECT V FROM VAL_GET(:V$SCHOOL_ID, 17) INTO :OOOD_NUMBER;
            SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$DISTRICT_ID) INTO :DISTRICT_NAME;
            SELECT V FROM VAL_GET(:V$PLAN_ID, 3012) INTO :PLAN_NAME;

            STD_NAME = NULL;
            SELECT FIRST 1 R.VAL
            FROM LISTVALS L
            JOIN RES R on R.RES_ID = L.RES_ID and R.LANG_CODE = 'RU' and R.IS_DEL = 0
            WHERE L.LISTVAL_ID = :V$STD_NUM
            INTO :STD_NAME;

            WEEK_DAYS = NULL;
            SELECT FIRST 1 R.VAL
            FROM LISTVALS L
            JOIN RES R on R.RES_ID = L.RES_ID and R.LANG_CODE = 'RU' and R.IS_DEL = 0
            WHERE L.LISTVAL_ID = :V$WEEK_LID
            INTO :WEEK_DAYS;

            PROFILE_NAME = NULL;
            SELECT FIRST 1 R.VAL
            FROM LISTVALS L
            JOIN RES R on R.RES_ID = L.RES_ID and R.LANG_CODE = 'RU' and R.IS_DEL = 0
            WHERE L.LISTVAL_ID = :V$PROFILE_LID
            INTO :PROFILE_NAME;

            SUSPEND;
        END
    END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CURRICULUM_DELTA_INV_SUBJ_GET (
    I$CURRICULUM_ID BIGINT,
    I$COMPONENT_TYPE_ID BIGINT = null,
    I$STD_NUM INTEGER = 1)
RETURNS (
    DELTA INTEGER,
    SUBJECTS_MISS VARCHAR(5000))
AS
declare variable V$COUNT1 smallint;
declare variable V$COUNT2 smallint;
declare variable V$COUNT3 smallint;
BEGIN
    SUBJECTS_MISS = '';
    DELTA = 0;

    -- Русский язык
    IF (NOT EXISTS(
        SELECT FIRST 1 1
        FROM CURRICULUM_INV_SUBJ_EXISTS(:I$CURRICULUM_ID, 185, :I$COMPONENT_TYPE_ID)
        WHERE EXIST = 1
    )) THEN
    BEGIN
        DELTA = DELTA + 1;
        IF (SUBJECTS_MISS <> '') THEN
        BEGIN
            SUBJECTS_MISS = SUBJECTS_MISS || '; ';
        END
        SUBJECTS_MISS = SUBJECTS_MISS || (SELECT CAPTION FROM OBJECT_CAPTION_GET(185));
    END

    -- Литература
    IF (NOT EXISTS(
        SELECT FIRST 1 1
        FROM CURRICULUM_INV_SUBJ_EXISTS(:I$CURRICULUM_ID, 187, :I$COMPONENT_TYPE_ID)
        WHERE EXIST = 1
    )) THEN
    BEGIN
        DELTA = DELTA + 1;
        IF (SUBJECTS_MISS <> '') THEN
        BEGIN
            SUBJECTS_MISS = SUBJECTS_MISS || '; ';
        END
        SUBJECTS_MISS = SUBJECTS_MISS || (SELECT CAPTION FROM OBJECT_CAPTION_GET(187));
    END

    -- Иностранный язык
    IF (NOT EXISTS(
        SELECT FIRST 1 1
        FROM CURRICULUM_INV_SUBJ_EXISTS(:I$CURRICULUM_ID, 178, :I$COMPONENT_TYPE_ID)
        WHERE EXIST = 1
    )) THEN
    BEGIN
        DELTA = DELTA + 1;
        IF (SUBJECTS_MISS <> '') THEN
        BEGIN
            SUBJECTS_MISS = SUBJECTS_MISS || '; ';
        END
        SUBJECTS_MISS = SUBJECTS_MISS || (SELECT CAPTION FROM OBJECT_CAPTION_GET(178));
    END

    -- Математика
    IF (NOT EXISTS(
        SELECT FIRST 1 1
        FROM CURRICULUM_INV_SUBJ_EXISTS(:I$CURRICULUM_ID, 190, :I$COMPONENT_TYPE_ID)
        WHERE EXIST = 1
    )) THEN
    BEGIN
        DELTA = DELTA + 1;
        IF (SUBJECTS_MISS <> '') THEN
        BEGIN
            SUBJECTS_MISS = SUBJECTS_MISS || '; ';
        END
        SUBJECTS_MISS = SUBJECTS_MISS || (SELECT CAPTION FROM OBJECT_CAPTION_GET(190));
    END

    -- История (для ФГОС также Россия в мире, а также Россия в мире и всеобщая история)
    IF (NOT EXISTS(
        SELECT FIRST 1 1
        FROM CURRICULUM_INV_SUBJ_EXISTS(:I$CURRICULUM_ID, 174, :I$COMPONENT_TYPE_ID)
        WHERE EXIST = 1
    )) THEN
    BEGIN
        V$COUNT1 = 0;

        IF(I$STD_NUM = 2) THEN
        BEGIN
            SELECT FIRST 1 1
            FROM CURRICULUM_INV_SUBJ_EXISTS(:I$CURRICULUM_ID, 32840, :I$COMPONENT_TYPE_ID)
            WHERE EXIST = 1
            INTO :V$COUNT1;

            IF(V$COUNT1 = 0) THEN
            BEGIN
                SELECT FIRST 1 1
                FROM CURRICULUM_INV_SUBJ_EXISTS(:I$CURRICULUM_ID, 38154, :I$COMPONENT_TYPE_ID)
                WHERE EXIST = 1
                INTO :V$COUNT1;
            END
        END

        IF(V$COUNT1 = 0) THEN
        BEGIN
            DELTA = DELTA + 1;
            IF (SUBJECTS_MISS <> '') THEN
            BEGIN
                SUBJECTS_MISS = SUBJECTS_MISS || '; ';
            END
            SUBJECTS_MISS = SUBJECTS_MISS || (SELECT CAPTION FROM OBJECT_CAPTION_GET(174));
        END
    END

    -- ОБЖ
    IF (NOT EXISTS(
        SELECT FIRST 1 1
        FROM CURRICULUM_INV_SUBJ_EXISTS(:I$CURRICULUM_ID, 206, :I$COMPONENT_TYPE_ID)
        WHERE EXIST = 1
    )) THEN
    BEGIN
        DELTA = DELTA + 1;
        IF (SUBJECTS_MISS <> '') THEN
        BEGIN
            SUBJECTS_MISS = SUBJECTS_MISS || '; ';
        END
        SUBJECTS_MISS = SUBJECTS_MISS || (SELECT CAPTION FROM OBJECT_CAPTION_GET(206));
    END

    -- Физкультура
    IF (NOT EXISTS(
        SELECT FIRST 1 1
        FROM CURRICULUM_INV_SUBJ_EXISTS(:I$CURRICULUM_ID, 205, :I$COMPONENT_TYPE_ID)
        WHERE EXIST = 1
    )) THEN
    BEGIN
        DELTA = DELTA + 1;
        IF (SUBJECTS_MISS <> '') THEN
        BEGIN
            SUBJECTS_MISS = SUBJECTS_MISS || '; ';
        END
        SUBJECTS_MISS = SUBJECTS_MISS || (SELECT CAPTION FROM OBJECT_CAPTION_GET(205));
    END

    -- Обществознание, включая экономику и право
    IF (I$STD_NUM = 1 AND NOT EXISTS(
        SELECT FIRST 1 1
        FROM CURRICULUM_INV_SUBJ_EXISTS(:I$CURRICULUM_ID, 175, :I$COMPONENT_TYPE_ID, 1)
        WHERE EXIST = 1
    )) THEN
    BEGIN
        V$COUNT1 = 0;
        V$COUNT2 = 0;
        V$COUNT3 = 0;

        SELECT FIRST 1 1
        FROM CURRICULUM_INV_SUBJ_EXISTS(:I$CURRICULUM_ID, 194, :I$COMPONENT_TYPE_ID)
        WHERE EXIST = 1
        INTO :V$COUNT1;

        SELECT FIRST 1 1
        FROM CURRICULUM_INV_SUBJ_EXISTS(:I$CURRICULUM_ID, 32843, :I$COMPONENT_TYPE_ID)
        WHERE EXIST = 1
        INTO :V$COUNT2;

        SELECT FIRST 1 1
        FROM CURRICULUM_INV_SUBJ_EXISTS(:I$CURRICULUM_ID, 3138, :I$COMPONENT_TYPE_ID)
        WHERE EXIST = 1
        INTO :V$COUNT3;

        IF (V$COUNT1 + V$COUNT2 + V$COUNT3 <> 3) THEN
        BEGIN
            IF (V$COUNT1 = 0) THEN
            BEGIN
                DELTA = DELTA + 1;
                IF (SUBJECTS_MISS <> '') THEN
                BEGIN
                    SUBJECTS_MISS = SUBJECTS_MISS || '; ';
                END
                SUBJECTS_MISS = SUBJECTS_MISS || (SELECT CAPTION FROM OBJECT_CAPTION_GET(194));
            END
            IF (V$COUNT2 = 0) THEN
            BEGIN
                DELTA = DELTA + 1;
                IF (SUBJECTS_MISS <> '') THEN
                BEGIN
                    SUBJECTS_MISS = SUBJECTS_MISS || '; ';
                END
                SUBJECTS_MISS = SUBJECTS_MISS || (SELECT CAPTION FROM OBJECT_CAPTION_GET(32843));
            END
            IF (V$COUNT3 = 0) THEN
            BEGIN
                DELTA = DELTA + 1;
                IF (SUBJECTS_MISS <> '') THEN
                BEGIN
                    SUBJECTS_MISS = SUBJECTS_MISS || '; ';
                END
                SUBJECTS_MISS = SUBJECTS_MISS || (SELECT CAPTION FROM OBJECT_CAPTION_GET(3138));
            END
        END
    END

    -- Естествознание
    IF (I$STD_NUM = 1 AND NOT EXISTS(
        SELECT FIRST 1 1
        FROM CURRICULUM_INV_SUBJ_EXISTS(:I$CURRICULUM_ID, 177, :I$COMPONENT_TYPE_ID)
        WHERE EXIST = 1
    )) THEN
    BEGIN
        V$COUNT1 = 0;
        V$COUNT2 = 0;
        V$COUNT3 = 0;

        SELECT FIRST 1 1
        FROM CURRICULUM_INV_SUBJ_EXISTS(:I$CURRICULUM_ID, 198, :I$COMPONENT_TYPE_ID)
        WHERE EXIST = 1
        INTO :V$COUNT1;

        SELECT FIRST 1 1
        FROM CURRICULUM_INV_SUBJ_EXISTS(:I$CURRICULUM_ID, 199, :I$COMPONENT_TYPE_ID)
        WHERE EXIST = 1
        INTO :V$COUNT2;

        SELECT FIRST 1 1
        FROM CURRICULUM_INV_SUBJ_EXISTS(:I$CURRICULUM_ID, 197, :I$COMPONENT_TYPE_ID)
        WHERE EXIST = 1
        INTO :V$COUNT3;

        IF (V$COUNT1 + V$COUNT2 + V$COUNT3 <> 3) THEN
        BEGIN
            IF (V$COUNT1 = 0) THEN
            BEGIN
                DELTA = DELTA + 1;
                IF (SUBJECTS_MISS <> '') THEN
                BEGIN
                    SUBJECTS_MISS = SUBJECTS_MISS || '; ';
                END
                SUBJECTS_MISS = SUBJECTS_MISS || (SELECT CAPTION FROM OBJECT_CAPTION_GET(198));
            END
            IF (V$COUNT2 = 0) THEN
            BEGIN
                DELTA = DELTA + 1;
                IF (SUBJECTS_MISS <> '') THEN
                BEGIN
                    SUBJECTS_MISS = SUBJECTS_MISS || '; ';
                END
                SUBJECTS_MISS = SUBJECTS_MISS || (SELECT CAPTION FROM OBJECT_CAPTION_GET(199));
            END
            IF (V$COUNT3 = 0) THEN
            BEGIN
                DELTA = DELTA + 1;
                IF (SUBJECTS_MISS <> '') THEN
                BEGIN
                    SUBJECTS_MISS = SUBJECTS_MISS || '; ';
                END
                SUBJECTS_MISS = SUBJECTS_MISS || (SELECT CAPTION FROM OBJECT_CAPTION_GET(197));
            END
        END
    END

    -- Астрономия 18.04.2018
    IF (NOT EXISTS(
        SELECT FIRST 1 1
        FROM CURRICULUM_INV_SUBJ_EXISTS(:I$CURRICULUM_ID, 5516, :I$COMPONENT_TYPE_ID)
        WHERE EXIST = 1
    )) THEN
    BEGIN
        DELTA = DELTA + 1;
        IF (SUBJECTS_MISS <> '') THEN
        BEGIN
            SUBJECTS_MISS = SUBJECTS_MISS || '; ';
        END
        SUBJECTS_MISS = SUBJECTS_MISS || (SELECT CAPTION FROM OBJECT_CAPTION_GET(5516));
    END

    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CURRICULUM_DELTA_SUBJECT_GET (
    I$CURRICULUM_ID BIGINT,
    I$CHECK_CURRICULUM_ID BIGINT,
    I$COMPONENT_TYPE_ID BIGINT NOT NULL)
RETURNS (
    DELTA INTEGER,
    SUBJECTS_MISS VARCHAR(5000),
    SUBJECTS_MORE VARCHAR(5000),
    SUBJECTS_REPLACEMENT VARCHAR(5000))
AS
declare variable V$LEVEL_ID bigint;
declare variable V$SUBJECTS_REPLACEMENT varchar(5000);
declare variable V$MISS_SUBJECT_COUNT integer;
declare variable V$MORE_SUBJECT_COUNT integer;
declare variable V$SUBJECT_ID bigint;
declare variable V$COMPONENT_TYPE_ID bigint;
declare variable V$COMPONENT_TYPE_ID2 bigint;
BEGIN
    -- Функция утратила смысл, под удаление

    SUBJECTS_MISS = '';
    SUBJECTS_MORE = '';
    SUBJECTS_REPLACEMENT = '';

    -- Федеральный и обязательный компоненты идентичны, региональный и компонент ОО также
    IF(I$COMPONENT_TYPE_ID IS NOT NULL) THEN BEGIN
      IF(I$COMPONENT_TYPE_ID = 780) THEN
      BEGIN
        V$COMPONENT_TYPE_ID = 12752;
        V$COMPONENT_TYPE_ID2 = 13303;
      END
      ELSE IF(I$COMPONENT_TYPE_ID = 782) THEN
      BEGIN
        V$COMPONENT_TYPE_ID = 12753;
        V$COMPONENT_TYPE_ID2 = 13304;
      END
      ELSE IF(I$COMPONENT_TYPE_ID = 13303) THEN
      BEGIN
        V$COMPONENT_TYPE_ID = 12752;
        V$COMPONENT_TYPE_ID2 = 780;
      END
      ELSE IF(I$COMPONENT_TYPE_ID = 13304) THEN
      BEGIN
        V$COMPONENT_TYPE_ID = 12753;
        V$COMPONENT_TYPE_ID2 = 782;
      END
    END

    SELECT V1594.LISTVAL_ID
    FROM LINKS LP57
    JOIN VALL V1594 ON V1594.OBJ_ID = LP57.PARENT_ID AND V1594.PARAM_ID = 1594 AND V1594.IS_DEL = 0
    WHERE LP57.OBJ_ID = :I$CURRICULUM_ID AND LP57.PARENT_TYPE_ID = 57 AND LP57.DATE_DEL IS NULL
    INTO :V$LEVEL_ID;

    -- Здесь только федеральный компонент !
    FOR
      SELECT C1.CAPTION || ' = ' || C2.CAPTION || '; '
      FROM PLAN_SUBJECTS S
      JOIN PLAN_SUBJECTS PS ON PS.OBJ_ID = S.PARENT_ID AND
        ((:I$COMPONENT_TYPE_ID IS NULL) OR (PS.FIELD_ID = :I$COMPONENT_TYPE_ID) OR (PS.FIELD_ID = :V$COMPONENT_TYPE_ID) OR (PS.FIELD_ID = :V$COMPONENT_TYPE_ID2))
      LEFT JOIN OBJECT_CAPTION_GET(S.SUBJECT_ID) C1 ON 1=1
      LEFT JOIN OBJECT_CAPTION_GET(S.SRC_SUBJECT_ID) C2 ON 1=1
      WHERE S.DATE_DEL IS NULL AND S.PLAN_ID = :I$CURRICULUM_ID AND S.ROW_TYPE = 10 AND S.SRC_SUBJECT_ID IS NOT NULL
      INTO :V$SUBJECTS_REPLACEMENT
    DO
    BEGIN
      SUBJECTS_REPLACEMENT = SUBJECTS_REPLACEMENT || V$SUBJECTS_REPLACEMENT;
    END

    DELTA = 0;
    V$MISS_SUBJECT_COUNT = 0;
    V$MORE_SUBJECT_COUNT = 0;

    -- Выдаем список предметов, которых нет в шаблоне
    -- для началки - пропускаем второй иностранный
    FOR
        SELECT DISTINCT CS.SUBJECT_ID
        FROM CURRICULUM_VIRTUAL_SUBJECT_LIST(:I$CURRICULUM_ID, :I$COMPONENT_TYPE_ID) CS
        WHERE NOT EXISTS(
            SELECT FIRST 1 1
            FROM CURRICULUM_VIRTUAL_SUBJECT_LIST(:I$CHECK_CURRICULUM_ID, :I$COMPONENT_TYPE_ID) CS2
            WHERE CS2.SUBJECT_ID = CS.SUBJECT_ID
        ) AND ((:V$LEVEL_ID IN (5339, 5341) AND CS.SUBJECT_ID <> 32810) OR :V$LEVEL_ID NOT IN (5339, 5341))
        INTO :V$SUBJECT_ID
    DO
    BEGIN
        V$MORE_SUBJECT_COUNT = V$MORE_SUBJECT_COUNT + 1;
        IF (SUBJECTS_MORE <> '') THEN
        BEGIN
            SUBJECTS_MORE = SUBJECTS_MORE || '; ';
        END
        SUBJECTS_MORE = SUBJECTS_MORE || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$SUBJECT_ID));
    END

    -- Выдаем список предметов, которые есть в шаблоне и которых не хватает в УП
    FOR
        SELECT CS.SUBJECT_ID
        FROM CURRICULUM_VIRTUAL_SUBJECT_LIST(:I$CHECK_CURRICULUM_ID, :I$COMPONENT_TYPE_ID) CS
        WHERE NOT EXISTS(
            SELECT FIRST 1 1
            FROM CURRICULUM_VIRTUAL_SUBJECT_LIST(:I$CURRICULUM_ID, :I$COMPONENT_TYPE_ID) CS2
            WHERE CS2.SUBJECT_ID = CS.SUBJECT_ID
        )
        INTO :V$SUBJECT_ID
    DO
    BEGIN
        V$MISS_SUBJECT_COUNT = V$MISS_SUBJECT_COUNT + 1;
        IF (SUBJECTS_MISS <> '') THEN
        BEGIN
            SUBJECTS_MISS = SUBJECTS_MISS || '; ';
        END
        SUBJECTS_MISS = SUBJECTS_MISS || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$SUBJECT_ID));
    END

    IF (V$MISS_SUBJECT_COUNT > 0) THEN
    BEGIN
        DELTA = -V$MISS_SUBJECT_COUNT;
    END
    ELSE IF (V$MORE_SUBJECT_COUNT > 0) THEN
    BEGIN
        DELTA = V$MORE_SUBJECT_COUNT;
    END

    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CURRICULUM_DELTA_SUBJECT_GET2 (
    I$CURRICULUM_ID BIGINT,
    I$COMPONENT_TYPE_ID BIGINT = null)
RETURNS (
    DELTA INTEGER,
    SUBJECTS_MISS VARCHAR(5000))
AS
BEGIN
    SUBJECTS_MISS = '';
    DELTA = 0;

    -- География (3139) убрана
    -- Искусство МХК (34279) убрано
    -- Технология (200) убрана
    
    IF (NOT EXISTS(
        SELECT FIRST 1 1
        FROM CURRICULUM_VIRTUAL_SUBJECT_LIST(:I$CURRICULUM_ID, :I$COMPONENT_TYPE_ID) CS2
        WHERE CS2.SUBJECT_ID = 206
    )) THEN
    BEGIN
        DELTA = DELTA + 1;
        SUBJECTS_MISS = SUBJECTS_MISS || (SELECT CAPTION FROM OBJECT_CAPTION_GET(206));
    END

    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CURRICULUM_FILL_REPORT1 (
    I$OBJ_ID BIGINT NOT NULL,
    I$STAGE SMALLINT = null)
RETURNS (
    OOOD_SHORT_NAME VARCHAR(5000),
    OOOD_NUMBER VARCHAR(10),
    DISTRICT_NAME VARCHAR(255),
    EDUCATION_PROGRAM_LEVEL VARCHAR(255),
    PLAN_NAME VARCHAR(255),
    EDUCATION_STANDART VARCHAR(20),
    STAGE_NAME VARCHAR(100),
    WEEK_DAYS VARCHAR(10),
    HOURS_LIMIT INTEGER,
    HOURS_ACT INTEGER)
AS
declare variable V$SMIR_ID blob sub_type 0 segment size 80;
declare variable V$DISTRICT_ID bigint;
declare variable V$SCHOOL_ID bigint;
declare variable V$CURRICULUM_ID bigint;
declare variable V$EDUCATION_PROGRAM_ID bigint;
declare variable V$STAGE_ID bigint;
BEGIN

    -- STAGE: 0 = НОО, 1 = ООО, 2 = СОО, null = все

    FOR
        SELECT L111.OBJ_ID
        FROM LINKS L111
        WHERE L111.PARENT_ID = :I$OBJ_ID AND L111.OBJ_TYPE_ID = 111 AND L111.DATE_DEL IS NULL
        UNION ALL
        SELECT O111.OBJ_ID
        FROM OBJECTS O111
        WHERE O111.OBJ_ID = :I$OBJ_ID AND O111.TYPE_ID = 111
        INTO :V$DISTRICT_ID
    DO
    BEGIN
        FOR
            SELECT L2.OBJ_ID, L162.OBJ_ID, LP400.PARENT_ID, LP57.PARENT_ID, L54.OBJ_ID, V383.VAL, V1185.VAL
            FROM LINKS L2
            JOIN LINKS L162 ON L162.PARENT_ID = L2.OBJ_ID AND L162.OBJ_TYPE_ID = 162 AND L162.DATE_DEL IS NULL
            JOIN LINKS L54 ON L54.PARENT_ID = L162.OBJ_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
            JOIN LINKS LP400 ON LP400.OBJ_ID = L54.OBJ_ID AND LP400.PARENT_TYPE_ID = 400 AND LP400.DATE_DEL IS NULL
            JOIN LINKS LP57 ON LP57.OBJ_ID = LP400.PARENT_ID AND LP57.PARENT_TYPE_ID = 57 AND LP57.DATE_DEL IS NULL
            JOIN VALL V1594 ON V1594.OBJ_ID = LP57.PARENT_ID AND V1594.PARAM_ID = 1594 AND V1594.IS_DEL = 0 AND (:I$STAGE IS NULL OR V1594.LISTVAL_ID = IIF(:I$STAGE = 0, 5339, IIF(:I$STAGE = 1, 5341, 5343)))
            JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
            JOIN VALI V383 ON V383.OBJ_ID = L54.OBJ_ID AND V383.PARAM_ID = 383 AND V383.IS_DEL = 0
            LEFT JOIN VALI V1185 ON V1185.OBJ_ID = L54.OBJ_ID AND V1185.PARAM_ID = 1185 AND V1185.IS_DEL = 0
            -- Фильтр по подчинению и не-частные школы
            JOIN VALS V6 ON V6.OBJ_ID = L2.OBJ_ID AND V6.PARAM_ID = 6 AND V6.IS_DEL = 0 AND V6.VAL = 'Комитет по образованию Санкт-Петербурга'
            LEFT JOIN VALL V8 ON V8.OBJ_ID = L2.OBJ_ID AND V8.PARAM_ID = 8 AND V8.IS_DEL = 0
            WHERE L2.PARENT_ID = :V$DISTRICT_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND (V8.LISTVAL_ID IS NULL OR V8.LISTVAL_ID <> 5404)
            ORDER BY 1, 3, V381.LISTVAL_ID
            INTO :V$SCHOOL_ID, :V$SMIR_ID, :V$CURRICULUM_ID, :V$EDUCATION_PROGRAM_ID, :V$STAGE_ID, :HOURS_LIMIT, :HOURS_ACT
        DO
        BEGIN

            SELECT V FROM VAL_GET(:V$SCHOOL_ID, 2) INTO :OOOD_SHORT_NAME;
            SELECT V FROM VAL_GET(:V$SCHOOL_ID, 17) INTO :OOOD_NUMBER;
            SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$DISTRICT_ID) INTO :DISTRICT_NAME;
            SELECT V FROM VAL_GET(:V$CURRICULUM_ID, 3014) INTO :EDUCATION_STANDART;
            SELECT V FROM VAL_GET(:V$EDUCATION_PROGRAM_ID, 1594) INTO :EDUCATION_PROGRAM_LEVEL;

            SELECT V FROM VAL_GET(:V$CURRICULUM_ID, 3012) INTO :PLAN_NAME;
            SELECT V FROM VAL_GET(:V$STAGE_ID, 381) INTO :STAGE_NAME;
            SELECT V FROM VAL_GET(:V$STAGE_ID, 2837) INTO :WEEK_DAYS;

            SUSPEND;
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CURRICULUM_GUP_HAS_PTP (
    I$CURRICULUM_ID BIGINT,
    I$CHECK_CURRICULUM_ID BIGINT,
    I$COMPONENT_TYPE_ID BIGINT = null)
RETURNS (
    NO_PTP SMALLINT,
    NO_EQUAL_HOURS SMALLINT)
AS
declare variable V$SUBJECT_ID bigint;
declare variable V$STAGE_ID bigint;
declare variable V$CJ_ID bigint;
declare variable V$GUP_ID bigint;
declare variable V$GUP_HOURS integer;
declare variable V$CURRICULUM_HOURS integer;
declare variable V$COMPONENT_TYPE_ID bigint;
BEGIN

    -- Федеральный и обязательный компоненты идентичны, региональный и компонент ОО также
    IF(I$COMPONENT_TYPE_ID IS NOT NULL) THEN BEGIN
      IF(I$COMPONENT_TYPE_ID = 780) THEN V$COMPONENT_TYPE_ID = 13303;
      ELSE IF(I$COMPONENT_TYPE_ID = 782) THEN V$COMPONENT_TYPE_ID = 13304;
    END

    NO_PTP = 0;
    NO_EQUAL_HOURS = 0;
    FOR
        SELECT DISTINCT PS.SUBJECT_ID
        FROM PLAN_SUBJECTS S
        JOIN PLAN_SUBJECTS PS ON PS.OBJ_ID = S.PARENT_ID
        WHERE S.DATE_DEL IS NULL AND S.PLAN_ID = :I$CURRICULUM_ID AND S.ROW_TYPE = 10
            AND ((:I$COMPONENT_TYPE_ID IS NULL) OR (PS.FIELD_ID = :I$COMPONENT_TYPE_ID) OR (PS.FIELD_ID = :V$COMPONENT_TYPE_ID))
            AND S.SUBJECT_ID <> 34607
        INTO :V$SUBJECT_ID
    DO
    BEGIN
        FOR
            SELECT J.OBJ_ID, J.STAGE_INDEX, P.PTP_HOURS
            FROM CJ2_JOURNAL J
            LEFT JOIN CJ2_JOURNAL_PTP JP ON JP.DATE_DEL IS NULL AND JP.CJ_ID = J.OBJ_ID AND JP.APPROVAL_STATE = 2
            LEFT JOIN PTP P ON P.OBJ_ID = JP.PTP_ID
            WHERE J.DATE_DEL IS NULL AND J.REF_ID = :I$CURRICULUM_ID AND J.SUBJECT_ID = :V$SUBJECT_ID AND J.JOURNAL_TYPE = 0
            INTO :V$CJ_ID, :V$STAGE_ID, :V$GUP_HOURS
        DO
        BEGIN
            V$CURRICULUM_HOURS = (SELECT HOURS FROM CURRICULUM_HOURS_GET(:I$CURRICULUM_ID, :I$COMPONENT_TYPE_ID, :V$SUBJECT_ID, :V$STAGE_ID));
            IF (V$CURRICULUM_HOURS > 0) THEN
            BEGIN
                IF (V$GUP_HOURS <> V$CURRICULUM_HOURS) THEN
                BEGIN
                    NO_EQUAL_HOURS = NO_EQUAL_HOURS + 1;
                END

                IF(V$GUP_HOURS IS NULL) THEN
                BEGIN
                    NO_PTP = NO_PTP + 1;
                END
            END
        END
    END
    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CURRICULUM_GUP_SUBJ_HAS_PTP (
    I$CURRICULUM_ID BIGINT,
    I$CHECK_CURRICULUM_ID BIGINT,
    I$COMPONENT_TYPE_ID BIGINT = null)
RETURNS (
    SUBJECT_ID BIGINT,
    STAGE_ID BIGINT,
    JOURNAL_NAME VARCHAR(1000))
AS
declare variable V$COMPONENT_TYPE_ID bigint;
declare variable SORT_ORDER bigint;
BEGIN

    -- Федеральный и обязательный компоненты идентичны, региональный и компонент ОО также
    IF(I$COMPONENT_TYPE_ID IS NOT NULL) THEN BEGIN
      IF(I$COMPONENT_TYPE_ID = 780) THEN V$COMPONENT_TYPE_ID = 13303;
      ELSE IF(I$COMPONENT_TYPE_ID = 782) THEN V$COMPONENT_TYPE_ID = 13304;
    END

    FOR
        SELECT DISTINCT S.SUBJECT_ID, V381.LISTVAL_ID
        FROM PLAN_SUBJECTS S
        JOIN PLAN_SUBJECTS PS ON PS.OBJ_ID = S.PARENT_ID
        JOIN PLAN_LOADS L ON L.DATE_DEL IS NULL AND L.SUBJECT_ID = S.OBJ_ID AND (L.LOAD_HOURS_S1 > 0 OR L.LOAD_HOURS_S2 > 0)
        JOIN VALL V381 ON V381.OBJ_ID = L.STAGE_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
        JOIN LISTVALS LV381 ON LV381.LISTVAL_ID = V381.LISTVAL_ID
        LEFT JOIN VALI V375 ON V375.OBJ_ID = S.SUBJECT_ID AND V375.PARAM_ID = 375 AND V375.IS_DEL = 0
        WHERE S.DATE_DEL IS NULL AND S.PLAN_ID = :I$CURRICULUM_ID AND S.ROW_TYPE = 10
            AND ((:I$COMPONENT_TYPE_ID IS NULL) OR (PS.FIELD_ID = :I$COMPONENT_TYPE_ID) OR (PS.FIELD_ID = :V$COMPONENT_TYPE_ID))
            AND S.SUBJECT_ID <> 34607
        ORDER BY V375.VAL, LV381.SORT_ORDER
        INTO :SUBJECT_ID, :STAGE_ID
    DO
    BEGIN

        FOR
            SELECT J.JOURNAL_NAME
            FROM CJ2_JOURNAL J
            LEFT JOIN CJ2_JOURNAL_PTP JP ON JP.DATE_DEL IS NULL AND JP.CJ_ID = J.OBJ_ID AND JP.APPROVAL_STATE = 2
            WHERE J.DATE_DEL IS NULL AND J.REF_ID = :I$CURRICULUM_ID AND J.SUBJECT_ID = :SUBJECT_ID
                AND J.STAGE_INDEX = :STAGE_ID AND J.JOURNAL_TYPE = 0 AND JP.OBJ_ID IS NULL
            ORDER BY 1
            INTO :JOURNAL_NAME
        DO
        BEGIN
            SUSPEND;
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CURRICULUM_GUP_SUBJ_PTP_HOURS (
    I$CURRICULUM_ID BIGINT,
    I$CHECK_CURRICULUM_ID BIGINT,
    I$COMPONENT_TYPE_ID BIGINT = null)
RETURNS (
    SUBJECT_ID BIGINT,
    STAGE_ID BIGINT,
    JOURNAL_NAME VARCHAR(1000),
    CURRICULUM_HOURS INTEGER,
    PTP_HOURS INTEGER)
AS
declare variable V$COMPONENT_TYPE_ID bigint;
declare variable SORT_ORDER bigint;
BEGIN

    -- Федеральный и обязательный компоненты идентичны, региональный и компонент ОО также
    IF(I$COMPONENT_TYPE_ID IS NOT NULL) THEN BEGIN
      IF(I$COMPONENT_TYPE_ID = 780) THEN V$COMPONENT_TYPE_ID = 13303;
      ELSE IF(I$COMPONENT_TYPE_ID = 782) THEN V$COMPONENT_TYPE_ID = 13304;
    END

    FOR
        SELECT DISTINCT S.SUBJECT_ID, V381.LISTVAL_ID, COALESCE(L.LOAD_HOURS_S1, 0) + COALESCE(L.LOAD_HOURS_S2, 0)
        FROM PLAN_SUBJECTS S
        JOIN PLAN_SUBJECTS PS ON PS.OBJ_ID = S.PARENT_ID
        JOIN PLAN_LOADS L ON L.DATE_DEL IS NULL AND L.SUBJECT_ID = S.OBJ_ID AND (L.LOAD_HOURS_S1 > 0 OR L.LOAD_HOURS_S2 > 0)
        JOIN VALL V381 ON V381.OBJ_ID = L.STAGE_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
        JOIN LISTVALS LV381 ON LV381.LISTVAL_ID = V381.LISTVAL_ID
        LEFT JOIN VALI V375 ON V375.OBJ_ID = S.SUBJECT_ID AND V375.PARAM_ID = 375 AND V375.IS_DEL = 0
        WHERE S.DATE_DEL IS NULL AND S.PLAN_ID = :I$CURRICULUM_ID AND S.ROW_TYPE = 10
            AND ((:I$COMPONENT_TYPE_ID IS NULL) OR (PS.FIELD_ID = :I$COMPONENT_TYPE_ID) OR (PS.FIELD_ID = :V$COMPONENT_TYPE_ID))
            AND S.SUBJECT_ID <> 34607
        ORDER BY V375.VAL, LV381.SORT_ORDER
        INTO :SUBJECT_ID, :STAGE_ID, :CURRICULUM_HOURS
    DO
    BEGIN
        FOR
            SELECT J.JOURNAL_NAME, P.PTP_HOURS
            FROM CJ2_JOURNAL J
            LEFT JOIN CJ2_JOURNAL_PTP JP ON JP.DATE_DEL IS NULL AND JP.CJ_ID = J.OBJ_ID AND JP.APPROVAL_STATE = 2
            LEFT JOIN PTP P ON P.OBJ_ID = JP.PTP_ID
            WHERE J.DATE_DEL IS NULL AND J.REF_ID = :I$CURRICULUM_ID AND J.SUBJECT_ID = :SUBJECT_ID
                AND J.STAGE_INDEX = :STAGE_ID AND J.JOURNAL_TYPE = 0
            ORDER BY 1
            INTO :JOURNAL_NAME, :PTP_HOURS
        DO
        BEGIN
            IF (PTP_HOURS <> CURRICULUM_HOURS OR PTP_HOURS IS NULL) THEN SUSPEND;
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CURRICULUM_HOURS_GET (
    I$CURRICULUM_ID BIGINT,
    I$COMPONENT_TYPE_ID BIGINT = null,
    I$SUBJECT_ID BIGINT = null,
    I$STAGE_ID BIGINT = null,
    I$IS_ELECTIVE SMALLINT = null)
RETURNS (
    HOURS INTEGER)
AS
declare variable V$COMPONENT_TYPE_ID bigint;
declare variable V$COMPONENT_TYPE_ID2 bigint;
declare variable V$EXACT_SUBJECT_ID bigint;
BEGIN

    -- Федеральный и обязательный компоненты идентичны, региональный и компонент ОО также
    IF(I$COMPONENT_TYPE_ID IS NOT NULL) THEN BEGIN
      IF(I$COMPONENT_TYPE_ID = 780) THEN
      BEGIN
        V$COMPONENT_TYPE_ID = 12752;
        V$COMPONENT_TYPE_ID2 = 13303;
      END
      ELSE IF(I$COMPONENT_TYPE_ID = 782) THEN
      BEGIN
        V$COMPONENT_TYPE_ID = 12753;
        V$COMPONENT_TYPE_ID2 = 13304;
        V$EXACT_SUBJECT_ID = 34607;
      END
      ELSE IF(I$COMPONENT_TYPE_ID = 13303) THEN
      BEGIN
        V$COMPONENT_TYPE_ID = 12752;
        V$COMPONENT_TYPE_ID2 = 780;
      END
      ELSE IF(I$COMPONENT_TYPE_ID = 13304) THEN
      BEGIN
        V$COMPONENT_TYPE_ID = 12753;
        V$COMPONENT_TYPE_ID2 = 782;
        V$EXACT_SUBJECT_ID = 34607;
      END
    END

    -- На всякий случай разрешаем IS_ELECTIVE задавать как LISTVAL_ID (3 / 2), так и BOOL (0 / 1)
    IF(I$IS_ELECTIVE = 0) THEN I$IS_ELECTIVE = 3;
    ELSE IF(I$IS_ELECTIVE = 1) THEN I$IS_ELECTIVE = 2;

    -- Собираем сумму по уже разложенными во временную таблицу предметам
    SELECT SUM(HOURS)
    FROM CURRICULUM_HOURS
    -- Суммирование всегда по конкретному УП
    WHERE CURRICULUM_ID = :I$CURRICULUM_ID
      -- Фильтр по типу компонента
      AND ((:I$COMPONENT_TYPE_ID IS NULL) OR ((:I$COMPONENT_TYPE_ID IS NOT NULL) AND
        (SUBJECT_ID = :V$EXACT_SUBJECT_ID OR COMPONENT_TYPE_ID IN (:I$COMPONENT_TYPE_ID, :V$COMPONENT_TYPE_ID, :V$COMPONENT_TYPE_ID2))))
      -- Фильтр по предмету
      AND ((:I$SUBJECT_ID IS NULL) OR (:I$SUBJECT_ID = SUBJECT_ID))
      -- Фильтр по этапу
      AND ((:I$STAGE_ID IS NULL) OR (:I$STAGE_ID = STAGE_ID))
      -- Фильтр по элективности
      AND ((:I$IS_ELECTIVE IS NULL) OR (:I$IS_ELECTIVE = IS_ELECTIVE))
    INTO :HOURS;

    IF(HOURS IS NULL) THEN HOURS = 0;

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CURRICULUM_HOURS_GET_CONST (
    LEVEL_ID BIGINT NOT NULL,
    STANDARD_ID BIGINT NOT NULL,
    STAGE_ID BIGINT NOT NULL,
    WEEK_ID BIGINT NOT NULL,
    YEAR_VAL INTEGER = 2023,
    HAS_LANG2 SMALLINT = 0)
RETURNS (
    HOURS INTEGER,
    WEEKS INTEGER)
AS
begin

  HOURS = 0;
  WEEKS = 0;

  IF(STANDARD_ID = 11720) THEN
  BEGIN
    -- Стандарт 1 - ФБУП
    IF(WEEK_ID = 11718) THEN
    BEGIN
      IF(STAGE_ID = 37) THEN HOURS = 0;
      ELSE IF(STAGE_ID = 38) THEN HOURS = 0;
      ELSE IF(STAGE_ID = 39) THEN HOURS = 0;
      ELSE IF(STAGE_ID = 40) THEN HOURS = 0;
      ELSE IF(STAGE_ID = 41) THEN HOURS = 68;
      ELSE IF(STAGE_ID = 42) THEN HOURS = 68;
      ELSE IF(STAGE_ID = 43) THEN HOURS = 68;
      ELSE IF(STAGE_ID = 44) THEN HOURS = 68;
      ELSE IF(STAGE_ID = 45) THEN HOURS = 102;
      ELSE IF(STAGE_ID = 46) THEN HOURS = 0;
      ELSE IF(STAGE_ID = 47) THEN HOURS = 0;
    END
    ELSE IF(WEEK_ID = 11719) THEN
    BEGIN
      IF(STAGE_ID = 37) THEN HOURS = 0;
      ELSE IF(STAGE_ID = 38) THEN HOURS = 0;
      ELSE IF(STAGE_ID = 39) THEN HOURS = 0;
      ELSE IF(STAGE_ID = 40) THEN HOURS = 0;
      ELSE IF(STAGE_ID = 41) THEN HOURS = 170;
      ELSE IF(STAGE_ID = 42) THEN HOURS = 170;
      ELSE IF(STAGE_ID = 43) THEN HOURS = 170;
      ELSE IF(STAGE_ID = 44) THEN HOURS = 170;
      ELSE IF(STAGE_ID = 45) THEN HOURS = 204;
      ELSE IF(STAGE_ID = 46) THEN HOURS = 0;
      ELSE IF(STAGE_ID = 47) THEN HOURS = 0;
    END
  END
  ELSE IF(STANDARD_ID = 11721) THEN
  BEGIN
    -- Стандарт 2 - ФГОС
    IF(WEEK_ID = 11718) THEN
    BEGIN
      IF(STAGE_ID = 37) THEN HOURS = 33;
      ELSE IF(STAGE_ID = 38) THEN HOURS = 34;
      ELSE IF(STAGE_ID = 39) THEN HOURS = 34;
      ELSE IF(STAGE_ID = 40) THEN HOURS = 34;
      ELSE IF(STAGE_ID = 41) THEN HOURS = 68;
      ELSE IF(STAGE_ID = 42) THEN HOURS = 34;
      ELSE IF(STAGE_ID = 43) THEN HOURS = 68;
      ELSE IF(STAGE_ID = 44) THEN HOURS = 34;
      ELSE IF(STAGE_ID = 45) THEN HOURS = 34;
      ELSE IF(STAGE_ID = 46) THEN HOURS = 0;
      ELSE IF(STAGE_ID = 47) THEN HOURS = 0;
    END
    ELSE IF(WEEK_ID = 11719) THEN
    BEGIN
      IF(STAGE_ID = 37) THEN HOURS = 0;
      ELSE IF(STAGE_ID = 38) THEN HOURS = 0;
      ELSE IF(STAGE_ID = 39) THEN HOURS = 0;
      ELSE IF(STAGE_ID = 40) THEN HOURS = 0;
      ELSE IF(STAGE_ID = 41) THEN HOURS = 170;
      ELSE IF(STAGE_ID = 42) THEN HOURS = 136;
      ELSE IF(STAGE_ID = 43) THEN HOURS = 170;
      ELSE IF(STAGE_ID = 44) THEN HOURS = 136;
      ELSE IF(STAGE_ID = 45) THEN HOURS = 136;
      ELSE IF(STAGE_ID = 46) THEN HOURS = 0;
      ELSE IF(STAGE_ID = 47) THEN HOURS = 0;
    END
  END
  ELSE
  BEGIN
    -- ФГОС-2021, ФОП и далее
    IF(WEEK_ID = 11718) THEN
    BEGIN
      IF(STAGE_ID = 37) THEN
      BEGIN
        IF(STANDARD_ID = 14184 AND YEAR_VAL >= 2025) THEN HOURS = 0;
        ELSE HOURS = 33;
      END
      ELSE IF(STAGE_ID = 38) THEN HOURS = 34;
      ELSE IF(STAGE_ID = 39) THEN HOURS = 34;
      ELSE IF(STAGE_ID = 40) THEN HOURS = 0;
      ELSE IF(STAGE_ID = 41) THEN
      BEGIN
        IF(STANDARD_ID = 14184 AND YEAR_VAL >= 2025) THEN HOURS = 68;
        ELSE HOURS = 102;
      END
      ELSE IF(STAGE_ID = 42) THEN HOURS = 68;
      ELSE IF(STAGE_ID = 43) THEN HOURS = 68;
      ELSE IF(STAGE_ID = 44) THEN HOURS = 68;
      ELSE IF(STAGE_ID = 45) THEN HOURS = 34;
      ELSE IF(STAGE_ID = 46) THEN HOURS = 0;
      ELSE IF(STAGE_ID = 47) THEN HOURS = 0;
    END
    -- 6-дневка без второго иностранного
    ELSE IF(WEEK_ID = 11719 AND HAS_LANG2 = 0) THEN
    BEGIN
      IF(STAGE_ID = 37) THEN HOURS = 0;
      ELSE IF(STAGE_ID = 38) THEN HOURS = 0;
      ELSE IF(STAGE_ID = 39) THEN HOURS = 0;
      ELSE IF(STAGE_ID = 40) THEN HOURS = 0;
      ELSE IF(STAGE_ID = 41) THEN
      BEGIN
        IF(STANDARD_ID = 14184 AND YEAR_VAL >= 2025) THEN HOURS = 170;
        ELSE HOURS = 102;
      END
      ELSE IF(STAGE_ID = 42) THEN
      BEGIN
        IF(STANDARD_ID = 14184 AND YEAR_VAL >= 2025) THEN HOURS = 170;
        ELSE HOURS = 68;
      END
      ELSE IF(STAGE_ID = 43) THEN
      BEGIN
        IF(STANDARD_ID = 14184 AND YEAR_VAL >= 2025) THEN HOURS = 170;
        ELSE HOURS = 102;
      END
      ELSE IF(STAGE_ID = 44) THEN
      BEGIN
        IF(STANDARD_ID = 14184 AND YEAR_VAL >= 2025) THEN HOURS = 170;
        ELSE HOURS = 136;
      END
      ELSE IF(STAGE_ID = 45) THEN HOURS = 136;
      ELSE IF(STAGE_ID = 46) THEN HOURS = 0;
      ELSE IF(STAGE_ID = 47) THEN HOURS = 0;
    END
    -- 6-дневка со вторым иностранным
    ELSE IF(WEEK_ID = 11719 AND HAS_LANG2 = 1) THEN
    BEGIN
      IF(STAGE_ID = 37) THEN HOURS = 0;
      ELSE IF(STAGE_ID = 38) THEN HOURS = 0;
      ELSE IF(STAGE_ID = 39) THEN HOURS = 0;
      ELSE IF(STAGE_ID = 40) THEN HOURS = 0;
      ELSE IF(STAGE_ID = 41) THEN
      BEGIN
        IF(STANDARD_ID = 14184 AND YEAR_VAL >= 2025) THEN HOURS = 102;
        ELSE HOURS = 34;
      END
      ELSE IF(STAGE_ID = 42) THEN
      BEGIN
        IF(STANDARD_ID = 14184 AND YEAR_VAL >= 2025) THEN HOURS = 102;
        ELSE HOURS = 34;
      END
      ELSE IF(STAGE_ID = 43) THEN
      BEGIN
        IF(STANDARD_ID = 14184 AND YEAR_VAL >= 2025) THEN HOURS = 102;
        ELSE HOURS = 34;
      END
      ELSE IF(STAGE_ID = 44) THEN
      BEGIN
        IF(STANDARD_ID = 14184 AND YEAR_VAL >= 2025) THEN HOURS = 102;
        ELSE HOURS = 34;
      END
      ELSE IF(STAGE_ID = 45) THEN 
      BEGIN
        IF(STANDARD_ID = 14184 AND YEAR_VAL >= 2025) THEN HOURS = 102;
        ELSE HOURS = 68;
      END
      ELSE IF(STAGE_ID = 46) THEN HOURS = 0;
      ELSE IF(STAGE_ID = 47) THEN HOURS = 0;
    END
  END

  SUSPEND;
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CURRICULUM_INV_SUBJ_EXISTS (
    I$CURRICULUM_ID BIGINT,
    I$CHECK_SUBJECT_ID BIGINT,
    I$COMPONENT_TYPE_ID BIGINT,
    I$CHECK_SOURCE SMALLINT = 0)
RETURNS (
    EXIST SMALLINT)
AS
declare variable V$COMPONENT_TYPE_ID bigint; /* Альтернативный тип компонента */
declare variable V$COMPONENT_TYPE_ID2 bigint;
BEGIN
    -- Проверяем наличие либо непосредственно такого предмета, либо предмета, указанного как соответствующего данному
    -- Федеральный и обязательный компоненты идентичны, региональный и компонент ОО также
    IF(I$COMPONENT_TYPE_ID IS NOT NULL) THEN BEGIN
      IF(I$COMPONENT_TYPE_ID = 780) THEN
      BEGIN
        V$COMPONENT_TYPE_ID = 12752;
        V$COMPONENT_TYPE_ID2 = 13303;
      END
      ELSE IF(I$COMPONENT_TYPE_ID = 782) THEN
      BEGIN
        V$COMPONENT_TYPE_ID = 12753;
        V$COMPONENT_TYPE_ID2 = 13304;
      END
      ELSE IF(I$COMPONENT_TYPE_ID = 13303) THEN
      BEGIN
        V$COMPONENT_TYPE_ID = 12752;
        V$COMPONENT_TYPE_ID2 = 780;
      END
      ELSE IF(I$COMPONENT_TYPE_ID = 13304) THEN
      BEGIN
        V$COMPONENT_TYPE_ID = 12753;
        V$COMPONENT_TYPE_ID2 = 782;
      END
    END

    EXIST = 0;

    -- Специальный флаг I$CHECK_SOURCE сделан для проверки обществознания в среднем образовании, где в шаблоне сидит просто обществознание
    -- и проверять нужно именно исходный предмет

    -- Там где замена не прописана, предмет вписан заменой самого себя
    -- Внимание: вызовы везде идут с COMPONENT_TYPE_ID = null, но для вариативной компоненты код предмета замены всегда 0,
    -- поэтому все ключевые предметы обязательно должны присутствовать в обязательной компоненте !
    SELECT FIRST 1 1
    FROM CURRICULUM_HOURS H
    WHERE H.CURRICULUM_ID = :I$CURRICULUM_ID AND
      (((H.TEMPLATE_SUBJECT_ID = :I$CHECK_SUBJECT_ID) AND (:I$CHECK_SOURCE = 0)) OR (H.SUBJECT_ID = :I$CHECK_SUBJECT_ID)) AND
      ((:I$COMPONENT_TYPE_ID IS NULL) OR (H.COMPONENT_TYPE_ID IN (:I$COMPONENT_TYPE_ID, :V$COMPONENT_TYPE_ID, :V$COMPONENT_TYPE_ID2)))
    INTO :EXIST;

    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CURRICULUM_REPLACE_SUBJECT_LIST (
    I$CURRICULUM_ID BIGINT,
    I$COMPONENT_TYPE_ID BIGINT,
    I$SUBJECT_ID BIGINT)
RETURNS (
    SUBJECT_ID BIGINT)
AS
declare variable V$COMPONENT_TYPE_ID bigint;
BEGIN

    -- Федеральный и обязательный компоненты идентичны, региональный и компонент ОО также
    IF(I$COMPONENT_TYPE_ID IS NOT NULL) THEN BEGIN
      IF(I$COMPONENT_TYPE_ID = 780) THEN V$COMPONENT_TYPE_ID = 12752;
      ELSE IF(I$COMPONENT_TYPE_ID = 782) THEN V$COMPONENT_TYPE_ID = 12753;
    END

    FOR
        SELECT :I$SUBJECT_ID
        FROM RDB$DATABASE

        UNION

        SELECT V2719.VAL
        FROM LINKS L49
        JOIN VALL V372 ON V372.OBJ_ID = L49.OBJ_ID AND V372.PARAM_ID = 372 AND V372.IS_DEL = 0 AND
          (V372.LISTVAL_ID = :I$COMPONENT_TYPE_ID OR V372.LISTVAL_ID = :V$COMPONENT_TYPE_ID)
        JOIN LINKS L349 ON L349.PARENT_ID = L49.OBJ_ID AND L349.OBJ_TYPE_ID = 349 AND L349.DATE_DEL IS NULL
        JOIN VALR V2718 ON V2718.OBJ_ID = L349.OBJ_ID AND V2718.PARAM_ID = 2718 AND V2718.IS_DEL = 0 AND V2718.VAL = :I$SUBJECT_ID
        JOIN VALR V2719 ON V2719.OBJ_ID = L349.OBJ_ID AND V2719.PARAM_ID = 2719 AND V2719.IS_DEL = 0
        WHERE L49.PARENT_ID = :I$CURRICULUM_ID AND L49.OBJ_TYPE_ID = 49 AND L49.DATE_DEL IS NULL

        INTO :SUBJECT_ID
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CURRICULUM_STAGE_LIST (
    I$STAGE_ID BIGINT,
    I$CURRENT_STAGE_TYPE_FL SMALLINT = 0)
RETURNS (
    STAGE_ID BIGINT,
    STAGE_TYPE_ID BIGINT)
AS
BEGIN
    FOR SELECT
            LL54.OBJ_ID,
            V381.LISTVAL_ID
        FROM LINKS L54
        JOIN LINKS LL54 ON LL54.PARENT_ID = L54.PARENT_ID
          AND LL54.OBJ_TYPE_ID = 54
          AND LL54.DATE_DEL IS NULL
        JOIN VALL V381 ON V381.OBJ_ID = LL54.OBJ_ID
          AND V381.PARAM_ID = 381
          AND V381.IS_DEL = 0
          AND (:I$CURRENT_STAGE_TYPE_FL = 1 OR V381.LISTVAL_ID <> (SELECT I FROM VAL_GET(:I$STAGE_ID, 381)))
        WHERE L54.OBJ_ID = :I$STAGE_ID
          AND L54.DATE_DEL IS NULL
          AND L54.PARENT_TYPE_ID = 50
        INTO :STAGE_ID, :STAGE_TYPE_ID
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CURRICULUM_SUBJECT_HOURS_NEQ (
    I$CURRICULUM_ID BIGINT,
    I$CHECK_CURRICULUM_ID BIGINT,
    I$COMPONENT_TYPE_ID BIGINT NOT NULL,
    I$YEAR INTEGER,
    I$LANG2 SMALLINT)
RETURNS (
    SUBJECT_ID BIGINT,
    STAGE_ID BIGINT,
    HOURS INTEGER,
    CHECK_HOURS INTEGER)
AS
DECLARE VARIABLE V$COMPONENT_TYPE_ID BIGINT;
DECLARE VARIABLE V$COMPONENT_TYPE_ID2 BIGINT;
DECLARE VARIABLE V$ADV SMALLINT;
DECLARE VARIABLE V$STADY_STANDARD_ID BIGINT;
BEGIN
    -- Функция устарела, заменена на PLAN_SUBJECT_HOURS_NEQ

    -- Федеральный и обязательный компоненты идентичны, региональный и компонент ОО также
    IF(I$COMPONENT_TYPE_ID IS NOT NULL) THEN BEGIN
      IF(I$COMPONENT_TYPE_ID = 780) THEN
      BEGIN
        V$COMPONENT_TYPE_ID = 12752;
        V$COMPONENT_TYPE_ID2 = 13303;
      END
      ELSE IF(I$COMPONENT_TYPE_ID = 782) THEN
      BEGIN
        V$COMPONENT_TYPE_ID = 12753;
        V$COMPONENT_TYPE_ID2 = 13304;
      END
      ELSE IF(I$COMPONENT_TYPE_ID = 13303) THEN
      BEGIN
        V$COMPONENT_TYPE_ID = 12752;
        V$COMPONENT_TYPE_ID2 = 780;
      END
      ELSE IF(I$COMPONENT_TYPE_ID = 13304) THEN
      BEGIN
        V$COMPONENT_TYPE_ID = 12753;
        V$COMPONENT_TYPE_ID2 = 782;
      END
    END

    SELECT V.LISTVAL_ID
    FROM VALL V
    WHERE V.OBJ_ID = :I$CURRICULUM_ID AND V.PARAM_ID = 3014 AND V.IS_DEL = 0
    INTO :V$STADY_STANDARD_ID;

    IF(I$COMPONENT_TYPE_ID IN (780, 13303)) THEN
    BEGIN
      -- По обязательной компоненте выбираем все предметы (суммирование с учетом переназначения предметов)
      -- из шаблона берем исходные коды предметов, при этом выборку из шаблона делаем только по тем предметам, которые есть в рабочем плане, и где есть хоть один коллектив
      FOR
        SELECT H.SUBJECT_ID, H.STAGE_ID, H.HOURS
        FROM CURRICULUM_HOURS H
        WHERE H.CURRICULUM_ID = :I$CHECK_CURRICULUM_ID AND H.COMPONENT_TYPE_ID IN (:I$COMPONENT_TYPE_ID, :V$COMPONENT_TYPE_ID, :V$COMPONENT_TYPE_ID2)
          AND H.STAGE_ID IN (
            SELECT DISTINCT V381.LISTVAL_ID
            FROM LINKS L54
            JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0 AND V381.LISTVAL_ID = H.STAGE_ID
            WHERE L54.PARENT_ID = :I$CURRICULUM_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
           )
        ORDER BY 2
        INTO :SUBJECT_ID, :STAGE_ID, :CHECK_HOURS
      DO
      BEGIN
        -- Суммирование делаем сами, т.к. CURRICULUM_HOURS_GET работает с реальными кодами предметов, а не с заменами
        HOURS = 0;
        SELECT SUM(H.HOURS)
        FROM CURRICULUM_HOURS H
        WHERE H.CURRICULUM_ID = :I$CURRICULUM_ID AND H.COMPONENT_TYPE_ID IN (:I$COMPONENT_TYPE_ID, :V$COMPONENT_TYPE_ID, :V$COMPONENT_TYPE_ID2)
          AND H.TEMPLATE_SUBJECT_ID = :SUBJECT_ID AND H.STAGE_ID = :STAGE_ID
        INTO :HOURS;

        V$ADV = 0;
        SELECT FIRST 1 S.IS_ADV
        FROM PLAN_SUBJECTS S
        WHERE S.DATE_DEL IS NULL AND S.PLAN_ID = :I$CURRICULUM_ID AND S.ROW_TYPE = 10 AND (S.SRC_SUBJECT_ID = :SUBJECT_ID OR S.SUBJECT_ID = :SUBJECT_ID)
        INTO :V$ADV;

        -- Для ФГОС-2021 и углубленных предметов делаем проверку не на точное равенство, а на не меньше
        -- Второй иностранный тут пройдет поскольку CHECK_HOURS будет нулевой
        IF(V$STADY_STANDARD_ID = 13452 AND V$ADV = 1 AND CHECK_HOURS > 0) THEN HOURS = CHECK_HOURS;

        IF((CHECK_HOURS > 0) AND (CHECK_HOURS <> HOURS)) THEN
        BEGIN
          SUSPEND;
        END
      END
    END
    ELSE
    BEGIN
      -- По переменной компоненте цифры заданы константами !
      FOR
        SELECT V381.LISTVAL_ID, HC.HOURS
        FROM LINKS L54
        JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0 -- этап обучения
        JOIN VALL V3014 ON V3014.OBJ_ID = L54.PARENT_ID AND V3014.PARAM_ID = 3014 AND V3014.IS_DEL = 0 -- образовательный стандарт
        JOIN VALL V2837 ON V2837.OBJ_ID = L54.OBJ_ID AND V2837.PARAM_ID = 2837 AND V2837.IS_DEL = 0 -- учебная неделя
        LEFT JOIN CURRICULUM_HOURS_GET_CONST(0, V3014.LISTVAL_ID, V381.LISTVAL_ID, V2837.LISTVAL_ID, :I$YEAR, :I$LANG2) HC ON 1=1
        WHERE L54.PARENT_ID = :I$CURRICULUM_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
        INTO :STAGE_ID, :CHECK_HOURS
      DO
      BEGIN
        -- Суммирование делаем сами, т.к. CURRICULUM_HOURS_GET работает с реальными кодами предметов, а не с заменами
        HOURS = 0;
        SELECT SUM(H.HOURS)
        FROM CURRICULUM_HOURS H
        LEFT JOIN VALL V2816 ON V2816.OBJ_ID = H.SUBJECT_ID AND V2816.PARAM_ID = 2816 AND V2816.IS_DEL = 0
        WHERE H.CURRICULUM_ID = :I$CURRICULUM_ID AND H.COMPONENT_TYPE_ID IN (:I$COMPONENT_TYPE_ID, :V$COMPONENT_TYPE_ID) AND H.STAGE_ID = :STAGE_ID
          AND ((H.SUBJECT_ID = 34607) OR (COALESCE(V2816.LISTVAL_ID, 3) = 3))
        INTO :HOURS;

        IF((CHECK_HOURS > 0) AND (CHECK_HOURS <> HOURS)) THEN
        BEGIN
          SUSPEND;
        END
      END
    END

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CURRICULUM_SUBJECT_LIST (
    I$STAGE_ID BIGINT,
    I$F1 SMALLINT = 0,
    SUBJECT_ID BIGINT = null)
RETURNS (
    OBJ_ID BIGINT,
    OBJ_CAPTION VARCHAR(1000),
    SORT_ORDER DOUBLE PRECISION)
AS
declare variable STAGE_OBJ_TYPE bigint;
declare variable ROOT_STAGE_ID bigint;
declare variable GUP_ID bigint;
BEGIN

    -- SUBJECT_ID указываем предмет, который можно нужно игнорировать при фильтрации

    -- В качестве STAGE_ID может быть передан как объект #54 (этап учебного плана), так и конкретный ГУП
    -- в последнем случае деление по подгруппам может быть в каждой подгруппе свое
    SELECT TYPE_ID FROM OBJECTS WHERE OBJ_ID = :I$STAGE_ID INTO :STAGE_OBJ_TYPE;

    IF(STAGE_OBJ_TYPE = 256) THEN
    BEGIN
        -- Выбираем реальный этап плана
        SELECT PARENT_ID
        FROM LINKS LP54
        WHERE LP54.OBJ_ID = :I$STAGE_ID AND LP54.PARENT_TYPE_ID = 54 AND LP54.DATE_DEL IS NULL
        INTO :ROOT_STAGE_ID;
        GUP_ID = I$STAGE_ID;
    END
    ELSE ROOT_STAGE_ID = I$STAGE_ID;

    FOR
        SELECT DISTINCT LP51.PARENT_ID
        FROM LINKS L56
        JOIN LINKS LP51 ON LP51.OBJ_ID = L56.OBJ_ID AND LP51.PARENT_TYPE_ID = 51 AND LP51.DATE_DEL IS NULL
        JOIN VALI VI ON VI.OBJ_ID = L56.OBJ_ID AND VI.PARAM_ID = 385 AND VI.IS_DEL = 0 AND VI.VAL > 0
        WHERE L56.PARENT_ID = :ROOT_STAGE_ID AND L56.OBJ_TYPE_ID = 56 AND L56.DATE_DEL IS NULL
        --I$F1 параметр добавлен для того, чтобы при создании потоков убирать из списка предметы,
        --потоки по которым уже есть на данном этапе обучения
        AND NOT EXISTS (SELECT FIRST 1 1
          FROM LINKS L346
          JOIN VALR V2705 ON V2705.OBJ_ID = L346.OBJ_ID AND V2705.PARAM_ID = 2705 AND V2705.IS_DEL = 0 AND V2705.VAL = LP51.PARENT_ID AND
            (:SUBJECT_ID IS NULL OR :SUBJECT_ID <> V2705.VAL)
          WHERE :I$F1 > 0 AND L346.PARENT_ID = :I$STAGE_ID AND L346.OBJ_TYPE_ID = 346 AND L346.DATE_DEL IS NULL
        )
        -- А также фильтруем по конкретной подгруппе, если передана именно она
        AND NOT EXISTS (SELECT FIRST 1 1
          FROM LINKS L47
          JOIN VALR V428 ON V428.OBJ_ID = L47.OBJ_ID AND V428.PARAM_ID = 428 AND V428.IS_DEL = 0 AND V428.VAL = LP51.PARENT_ID AND
            (:SUBJECT_ID IS NULL OR :SUBJECT_ID <> V428.VAL)
          WHERE :I$F1 > 0 AND :GUP_ID IS NOT NULL AND L47.PARENT_ID = :GUP_ID AND L47.OBJ_TYPE_ID = 47 AND L47.DATE_DEL IS NULL
        )
        INTO :OBJ_ID
    DO
    BEGIN
        SELECT CAPTION,SORT_ORDER FROM OBJECT_CAPTION_GET(:OBJ_ID) INTO :OBJ_CAPTION, :SORT_ORDER;
        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CURRICULUM_SUBJECT_LIST_HS (
    I$CURRICULUM_ID BIGINT)
RETURNS (
    SUBJECT_ID BIGINT,
    HOURS INTEGER)
AS
begin

  FOR
      SELECT IIF(TEMPLATE_SUBJECT_ID = 0, SUBJECT_ID, TEMPLATE_SUBJECT_ID), SUM(HOURS)
      FROM CURRICULUM_HOURS
      WHERE CURRICULUM_ID = :I$CURRICULUM_ID AND IS_ELECTIVE = 3 AND TEMPLATE_SUBJECT_ID <> 34651 AND SUBJECT_ID <> 34651 AND HOURS > 0
      GROUP BY 1
      INTO :SUBJECT_ID, :HOURS
  DO
  BEGIN
      SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CURRICULUM_SUBJECT_TO_FGOS (
    I$OBJ_ID BIGINT)
RETURNS (
    VAL VARCHAR(4000),
    I BIGINT)
AS
declare variable V$CHECK_CURRICULUM_ID bigint;
declare variable V$CURRICULUM_ID bigint;
declare variable V$STADY_WEEK_ID bigint;
declare variable V$STADY_STANDARD_ID bigint;
declare variable V$LEVEL_ID bigint;
declare variable V$COMPONENT_TYPE_ID bigint;
declare variable V$SUBJECT_ID bigint;
declare variable V$OBJ_ID bigint;
declare variable V$BLOB_ID bigint;
declare variable V$LINK_ID bigint;
declare variable V$COMP_TYPE bigint;
BEGIN
    I = 2;
    VAL = 'Да';

    -- Отмечаем все замены предметов как удаленные (затем нужные вернем обратно)
    UPDATE LINKS
    SET DATE_DEL = CURRENT_TIMESTAMP
    WHERE PARENT_ID = :I$OBJ_ID AND OBJ_TYPE_ID = 349 AND DATE_DEL IS NULL;

    -- Для вариативных компонентов замены не предусмотрены
    SELECT V372.LISTVAL_ID
    FROM VALL V372
    WHERE V372.OBJ_ID = :I$OBJ_ID AND V372.PARAM_ID = 372 AND V372.IS_DEL = 0
    INTO :V$COMP_TYPE;

    IF(V$COMP_TYPE IS NULL) THEN
    BEGIN
      VAL = 'Необходимо указать название компонента';
      I = 3;
      SUSPEND;
      EXIT;
    END

    IF(V$COMP_TYPE NOT IN (780, 12752)) THEN
    BEGIN
      VAL = 'Не требуется';
      SUSPEND;
      EXIT;
    END

    FOR
        -- Выбираем учебный план и его атрибуты - он и так должен быть один
        SELECT FIRST 1 L49.PARENT_ID, V1594.LISTVAL_ID, V2837.LISTVAL_ID, V2478.LISTVAL_ID, V372.LISTVAL_ID
        -- Учебные компоненты
        FROM LINKS L49
        -- Тип компонента (федеральный/региональный/рег+ОО)
        JOIN VALL V372 ON V372.OBJ_ID = L49.OBJ_ID AND V372.PARAM_ID = 372 AND V372.IS_DEL = 0
        -- Учебная неделя
        LEFT JOIN LINKS L54 ON L54.OBJ_TYPE_ID = 54 AND L54.PARENT_ID = L49.PARENT_ID AND L54.DATE_DEL IS NULL
        LEFT JOIN VALL V2837 ON V2837.OBJ_ID = L54.OBJ_ID AND V2837.PARAM_ID = 2837 AND V2837.IS_DEL = 0
        -- Образовательный стандарт (1 или 2)
        LEFT JOIN VALL V2478 ON V2478.OBJ_ID = L49.PARENT_ID AND V2478.PARAM_ID = 2478 AND V2478.IS_DEL = 0
        -- Из образовательной программы достаем уровень образования
        JOIN LINKS LP57 ON LP57.OBJ_ID = L49.PARENT_ID AND LP57.PARENT_TYPE_ID = 57 AND LP57.DATE_DEL IS NULL
        JOIN VALL V1594 ON V1594.OBJ_ID = LP57.PARENT_ID AND V1594.PARAM_ID = 1594 AND V1594.IS_DEL = 0 AND V1594.LISTVAL_ID IN (5339,5341,5343)
        WHERE L49.OBJ_ID = :I$OBJ_ID AND L49.PARENT_TYPE_ID = 50 AND L49.DATE_DEL IS NULL
        INTO :V$CURRICULUM_ID, :V$LEVEL_ID, :V$STADY_WEEK_ID, :V$STADY_STANDARD_ID, :V$COMPONENT_TYPE_ID
    DO
    BEGIN
        FOR
            -- Ищем подходящий шаблон для проверки
            SELECT FIRST 1 L50.OBJ_ID
            -- Шаблон УП (#256 - папка Шаблоны)
            FROM LINKS L50
            -- Соответствующий нашему уровню образования (остались только шаблоны, обеспечивающие однозначный выбор)
            JOIN VALL V2503 ON V2503.OBJ_ID = L50.OBJ_ID AND V2503.PARAM_ID = 2503 AND V2503.IS_DEL = 0 AND V2503.LISTVAL_ID = :V$LEVEL_ID
            -- Учебной недели у нас тут больше нет
            -- Тот же образовательный стандарт
            LEFT JOIN VALL V2478 ON V2478.OBJ_ID = L50.OBJ_ID AND V2478.PARAM_ID = 2478 AND V2478.IS_DEL = 0
            -- Подлежащий контролю
            JOIN VALL V2466 ON V2466.OBJ_ID = L50.OBJ_ID AND V2466.PARAM_ID = 2466 AND V2466.IS_DEL = 0 AND V2466.LISTVAL_ID = 2
            -- Берем всегда универсальный профиль
            JOIN VALL V2166 ON V2166.OBJ_ID = L50.OBJ_ID AND V2166.PARAM_ID = 2166 AND V2166.IS_DEL = 0 AND V2166.LISTVAL_ID = 10955
            WHERE L50.PARENT_ID = 258 AND L50.OBJ_TYPE_ID = 50 AND L50.DATE_DEL IS NULL AND ((:V$STADY_STANDARD_ID IS NULL) OR (V2478.LISTVAL_ID = :V$STADY_STANDARD_ID))
            INTO :V$CHECK_CURRICULUM_ID
        DO
        BEGIN
            -- Необходимо пересчитать временные таблицы по УП
            EXECUTE PROCEDURE BUILD_CURPLAN_HOURS(:V$CURRICULUM_ID, :V$CHECK_CURRICULUM_ID);
            EXECUTE PROCEDURE BUILD_CURPLAN_HOURS(:V$CHECK_CURRICULUM_ID, :V$CHECK_CURRICULUM_ID);
            -- Цикл по предметам, для которых не прописаны замены
            FOR
                SELECT DISTINCT CS.SUBJECT_ID
                FROM CURRICULUM_VIRTUAL_SUBJECT_LIST(:V$CURRICULUM_ID, :V$COMPONENT_TYPE_ID, 1) CS
                WHERE NOT EXISTS(
                    SELECT FIRST 1 1
                    FROM CURRICULUM_VIRTUAL_SUBJECT_LIST(:V$CHECK_CURRICULUM_ID, :V$COMPONENT_TYPE_ID, 1) CS2
                    WHERE CS2.SUBJECT_ID = CS.SUBJECT_ID
                ) AND (CS.SUBJECT_ID <> 175 OR :V$LEVEL_ID <> 5343)
                INTO :V$SUBJECT_ID
            DO
            BEGIN
                -- Ищем, есть ли такая связь в списке замен
                V$OBJ_ID = NULL;
                SELECT FIRST 1 L349.OBJ_ID, L349.LINK_ID
                FROM LINKS L349
                JOIN VALR V2719 ON V2719.OBJ_ID = L349.OBJ_ID AND V2719.PARAM_ID = 2719 AND V2719.VAL = :V$SUBJECT_ID
                WHERE L349.PARENT_ID = :I$OBJ_ID AND L349.OBJ_TYPE_ID = 349
                INTO :V$OBJ_ID, :V$LINK_ID;
        
                IF (V$OBJ_ID IS NULL) THEN
                BEGIN
                    -- Если предмета в списке нет - создаем связь
                    SELECT OBJ_ID FROM OBJECT_ADD(:I$OBJ_ID, 349) INTO :V$OBJ_ID;
                    SELECT BLOB_ID FROM VAL_ADD(2719, :V$OBJ_ID, :V$SUBJECT_ID) INTO :V$BLOB_ID;
                END
                ELSE
                BEGIN
                    -- Если предмет в списке есть, восстанавливаем ранее установленный флаг удаления
                    UPDATE LINKS SET DATE_DEL = NULL WHERE LINK_ID = :V$LINK_ID;
                END

                -- Отбор макрошаблонных предметов более неактуален

                -- Если есть хотя бы один предмет, где нет связи предмета "УП-Шаблон", возвращаем что связи не прописаны
                IF (NOT EXISTS(
                    SELECT FIRST 1 1
                    FROM VALR V2718
                    WHERE V2718.OBJ_ID = :V$OBJ_ID AND V2718.PARAM_ID = 2718 AND V2718.IS_DEL = 0
                )) THEN
                BEGIN
                    I = 3;
                    VAL = 'Нет';
                END
            END
        END
    END

    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE CURRICULUM_VIRTUAL_SUBJECT_LIST (
    I$CURRICULUM_ID BIGINT,
    I$COMPONENT_TYPE_ID BIGINT,
    I$SOURCE SMALLINT = 0)
RETURNS (
    SUBJECT_ID BIGINT)
AS
declare variable V$COMPONENT_TYPE_ID bigint;
declare variable V$COMPONENT_TYPE_ID2 bigint;
BEGIN

    -- Федеральный и обязательный компоненты идентичны, региональный и компонент ОО также
    IF(I$COMPONENT_TYPE_ID IS NOT NULL) THEN BEGIN
      IF(I$COMPONENT_TYPE_ID = 780) THEN
      BEGIN
        V$COMPONENT_TYPE_ID = 12752;
        V$COMPONENT_TYPE_ID2 = 13303;
      END
      ELSE IF(I$COMPONENT_TYPE_ID = 782) THEN
      BEGIN
        V$COMPONENT_TYPE_ID = 12753;
        V$COMPONENT_TYPE_ID2 = 13304;
      END
      ELSE IF(I$COMPONENT_TYPE_ID = 13303) THEN
      BEGIN
        V$COMPONENT_TYPE_ID = 12752;
        V$COMPONENT_TYPE_ID2 = 780;
      END
      ELSE IF(I$COMPONENT_TYPE_ID = 13304) THEN
      BEGIN
        V$COMPONENT_TYPE_ID = 12753;
        V$COMPONENT_TYPE_ID2 = 782;
      END
    END

    -- Если установлен I$SOURCE = 1, то берем реальное название предмета (из CURRICULUM_SUBJECT_TO_FGOS)
    -- если 0, то берем альтернативное название

    IF(I$SOURCE = 1) THEN
    BEGIN
      FOR
        SELECT DISTINCT H.SUBJECT_ID
        FROM CURRICULUM_HOURS H
        WHERE H.CURRICULUM_ID = :I$CURRICULUM_ID AND ((:I$COMPONENT_TYPE_ID IS NULL) OR
          (H.COMPONENT_TYPE_ID IN (:I$COMPONENT_TYPE_ID, :V$COMPONENT_TYPE_ID, :V$COMPONENT_TYPE_ID2)))
        INTO :SUBJECT_ID
      DO
      BEGIN
        SUSPEND;
      END
    END
    ELSE
    BEGIN
      FOR
        SELECT DISTINCT H.TEMPLATE_SUBJECT_ID
        FROM CURRICULUM_HOURS H
        WHERE H.CURRICULUM_ID = :I$CURRICULUM_ID AND ((:I$COMPONENT_TYPE_ID IS NULL) OR
          (H.COMPONENT_TYPE_ID IN (:I$COMPONENT_TYPE_ID, :V$COMPONENT_TYPE_ID, :V$COMPONENT_TYPE_ID2)))
        INTO :SUBJECT_ID
      DO
      BEGIN
        SUSPEND;
      END
    END

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DATABUILDER_SETUP (
    I$OBJ_ID BIGINT,
    I$LEVEL_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$OBJ_ID2 BIGINT;
DECLARE VARIABLE V$LEVEL SMALLINT;
DECLARE VARIABLE V$LIST_ID INTEGER;
DECLARE VARIABLE V$T INTEGER;
DECLARE VARIABLE V$USER_ID BIGINT;
DECLARE VARIABLE V$EDIT_TYPE SMALLINT;
DECLARE VARIABLE V$RO SMALLINT;
DECLARE VARIABLE V$TYPE_ID BIGINT;
DECLARE VARIABLE S VARCHAR(1000);
begin

  SELECT KEY_VAL FROM KEYS WHERE KEY_CODE = 'LEVEL' INTO :V$LEVEL;

  IF(I$USER_ID = 'Веб-администратор') THEN V$USER_ID = 1; ELSE V$USER_ID = I$USER_ID;

  TAG_NAME = 'types::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT T.TYPE_ID, R.VAL
    FROM LTYPES P
    JOIN TYPES T ON T.TYPE_ID = P.TYPE_ID AND T.IS_DEL = 0
    JOIN RES R ON R.RES_ID = T.RES_ID AND R.LANG_CODE = 'RU'
    JOIN LUSERS LU ON LU.USER_ID = :V$USER_ID AND LU.LEVEL_ID = P.LEVEL_ID
    WHERE P.LEVEL_ID = :I$LEVEL_ID AND P.IS_DEL = 0 AND P.EDIT_TYPE >= 0
    ORDER BY 1
    INTO :V$OBJ_ID, :S
  DO
  BEGIN
    TAG_NAME = 'types:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'types:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'types:r:name';
    VAL = S;
    SUSPEND;

    TAG_NAME = 'types:r:params::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT P.PARAM_ID, R.VAL, P.PARAM_TYPE, P.LIST_ID, LP.EDIT_TYPE, LU.READ_ONLY
      FROM PARAMS P
      JOIN RES R ON R.RES_ID = P.RES_ID AND R.LANG_CODE = 'RU'
      JOIN LPARAMS LP ON LP.PARAM_ID = P.PARAM_ID AND LP.LEVEL_ID = :I$LEVEL_ID AND LP.IS_DEL = 0 AND LP.EDIT_TYPE >= 0
      JOIN LUSERS LU ON LU.USER_ID = :V$USER_ID AND LU.LEVEL_ID = LP.LEVEL_ID
      WHERE P.TYPE_ID = :V$OBJ_ID AND P.IS_DEL = 0 AND P.PARAM_TYPE NOT IN (14, 15)
      ORDER BY P.GRID_ORDER
      INTO :V$OBJ_ID2, :S, :V$T, :V$LIST_ID, :V$EDIT_TYPE, :V$RO
    DO
    BEGIN
      TAG_NAME = 'types:r:params:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'types:r:params:r:id';
      VAL = V$OBJ_ID2;
      SUSPEND;
      TAG_NAME = 'types:r:params:r:type';
      VAL = V$T;
      SUSPEND;
      TAG_NAME = 'types:r:params:r:name';
      VAL = S;
      SUSPEND;
      TAG_NAME = 'types:r:params:r:list_id';
      VAL = V$LIST_ID;
      SUSPEND;
      TAG_NAME = 'types:r:params:r:editable';
      VAL = IIF(V$RO = 0 AND V$EDIT_TYPE = 1, 1, 0);
      SUSPEND;
    END
  END

  TAG_NAME = 'links::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT PP.TYPE_ID, PP.CHILD_ID
    FROM LTYPES P
    JOIN TYPES T ON T.TYPE_ID = P.TYPE_ID AND T.IS_DEL = 0 -- сам тип может быть виден на этом уровне
    JOIN PARENTS PP ON PP.CHILD_ID = T.TYPE_ID AND PP.IS_DEL = 0 AND (PP.IS_ADD = 1 OR PP.IS_INTERNAL_ADD = 1 OR PP.IS_SELECT = 1 OR PP.IS_FROM_LIST = 1)
    LEFT JOIN TYPES T2 ON T2.TYPE_ID = PP.TYPE_ID AND T2.IS_DEL = 0 -- родительский тип
    LEFT JOIN LTYPES P2 ON P2.LEVEL_ID = P.LEVEL_ID AND P2.TYPE_ID = T2.TYPE_ID AND P2.IS_DEL = 0 AND P2.EDIT_TYPE >= 0 -- тоже виден на этом уровне
    WHERE P.LEVEL_ID = :I$LEVEL_ID AND P.IS_DEL = 0 AND P.EDIT_TYPE >= 0
      AND (PP.TYPE_ID IS NULL OR P2.EDIT_TYPE IS NOT NULL) AND PP.TYPE_ID <> PP.CHILD_ID
    ORDER BY 1 NULLS FIRST
    INTO :V$OBJ_ID, :V$OBJ_ID2
  DO
  BEGIN
    TAG_NAME = 'links:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'links:r:parent_id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'links:r:child_id';
    VAL = V$OBJ_ID2;
    SUSPEND;
  END

  TAG_NAME = 'is_stuff';
  VAL = 0;
  -- Личные дела, движение и просто сотрудники школ, СПО
  IF(I$LEVEL_ID IN (38, 48, 27, 29, 201, 534)) THEN VAL = 1;
  SUSPEND;

  -- Список сохраненных фильтров для данного пользователя
  SELECT TYPE_ID
  FROM OBJECTS
  WHERE OBJ_ID = :I$OBJ_ID
  INTO :V$TYPE_ID;

  TAG_NAME = 'saved::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT F.OBJ_ID, F.OBJ_NAME
    FROM DC_FILTERS F
    WHERE F.DATE_DEL IS NULL AND F.USER_ID = :V$USER_ID AND F.LEVEL_ID = :I$LEVEL_ID AND F.TYPE_ID = :V$TYPE_ID
    ORDER BY 2 NULLS FIRST
    INTO :V$OBJ_ID, :S
  DO
  BEGIN
    TAG_NAME = 'saved:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'saved:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'saved:r:name';
    VAL = S;
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DATAPACKET_VALIDATE (
    REG_NUMBER BIGINT,
    PACKET_TYPE VARCHAR(25),
    PACKET_DATE TIMESTAMP)
RETURNS (
    N SMALLINT)
AS
DECLARE VARIABLE KEY_LEVEL VARCHAR(4000);
DECLARE VARIABLE OBJ_ID BIGINT;
DECLARE VARIABLE IS_EXISTS SMALLINT;
BEGIN
    N = 1;

    SELECT FIRST 1 0
    FROM DATAPACKET
    WHERE REG_NUMBER = :REG_NUMBER
      AND PACKET_TYPE LIKE :PACKET_TYPE
      AND PACKET_DATE > :PACKET_DATE
    INTO :N;

    IF (N = 0) THEN
    BEGIN
        SELECT K.KEY_VAL
        FROM KEYS K
        WHERE K.KEY_CODE = 'LEVEL'
        INTO :KEY_LEVEL;

        OBJ_ID = NULL;

        SELECT FIRST 1 L.OBJ_ID
        FROM LINKS L
        WHERE L.PARENT_ID IS NULL
          AND (((:KEY_LEVEL = 2) AND (L.OBJ_TYPE_ID = 111)) OR ((:KEY_LEVEL = 3) AND (L.OBJ_TYPE_ID = 112)))
          AND L.DATE_DEL IS NULL
        INTO :OBJ_ID;

        IF (((KEY_LEVEL = 2) OR (KEY_LEVEL = 3)) AND (OBJ_ID IS NOT NULL)) THEN
        BEGIN
            IS_EXISTS = 0;

            SELECT FIRST 1 1
            FROM LINKS L
            WHERE L.PARENT_ID = :OBJ_ID
              AND L.OBJ_ID >= :REG_NUMBER * 1000000000
              AND L.OBJ_ID <  :REG_NUMBER * 1000000000 + 1000000000
              AND L.DATE_DEL IS NULL
            INTO :IS_EXISTS;

            IF (IS_EXISTS = 0) THEN N = 1;
        END
    END

    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DATE2ISO (
    D TIMESTAMP,
    FULL_TIME SMALLINT = 1)
RETURNS (
    VAL VARCHAR(64))
AS
declare variable S varchar(10);
begin

  VAL = EXTRACT(YEAR FROM D) || '-';

  S = EXTRACT(MONTH FROM D);
  IF(CHAR_LENGTH(S) = 1) THEN S = '0' || S;
  VAL = VAL || S || '-';

  S = EXTRACT(DAY FROM D);
  IF(CHAR_LENGTH(S) = 1) THEN S = '0' || S;
  VAL = VAL || S;

  IF(FULL_TIME <> 0) THEN
  BEGIN

      VAL = VAL || 'T';

      S = EXTRACT(HOUR FROM D);
      IF(CHAR_LENGTH(S) = 1) THEN S = '0' || S;
      VAL = VAL || S || ':';

      S = EXTRACT(MINUTE FROM D);
      IF(CHAR_LENGTH(S) = 1) THEN S = '0' || S;
      VAL = VAL || S || ':';

      S = TRUNC(EXTRACT(SECOND FROM D));
      IF(CHAR_LENGTH(S) = 1) THEN S = '0' || S;
      VAL = VAL || S;

      IF(FULL_TIME = 2) THEN
      BEGIN
          VAL = VAL || '.';

          S = EXTRACT(MILLISECOND FROM D);
          IF(POSITION('.' IN S) > 0) THEN S = SUBSTRING(S FROM 1 FOR POSITION('.' IN S) - 1);
          IF(POSITION(',' IN S) > 0) THEN S = SUBSTRING(S FROM 1 FOR POSITION(',' IN S) - 1);

          IF(CHAR_LENGTH(S) = 1) THEN S = '00' || S;
          ELSE IF(CHAR_LENGTH(S) = 2) THEN S = '0' || S;
          VAL = VAL || S;  -- || 'Z'
      END

  END

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DATE2SCRIPT (
    I$DATE DATE,
    I$PLAIN_NUM SMALLINT = 0)
RETURNS (
    VAL VARCHAR(100))
AS
DECLARE VARIABLE V$DAY VARCHAR(10);
DECLARE VARIABLE V$MONTH VARCHAR(20);
DECLARE VARIABLE N INTEGER;
begin

  IF(I$DATE IS NULL) THEN VAL = '«___» ___________ ____ г.';
  ELSE
  BEGIN
    V$DAY = EXTRACT(DAY FROM I$DATE);
    IF(CHAR_LENGTH(V$DAY) = 1) THEN V$DAY = '0' || V$DAY;

    N = EXTRACT(MONTH FROM I$DATE);
    IF(N = 1) THEN V$MONTH = 'января';
    ELSE IF(N = 2) THEN V$MONTH = 'февраля';
    ELSE IF(N = 3) THEN V$MONTH = 'марта';
    ELSE IF(N = 4) THEN V$MONTH = 'апреля';
    ELSE IF(N = 5) THEN V$MONTH = 'мая';
    ELSE IF(N = 6) THEN V$MONTH = 'июня';
    ELSE IF(N = 7) THEN V$MONTH = 'июля';
    ELSE IF(N = 8) THEN V$MONTH = 'августа';
    ELSE IF(N = 9) THEN V$MONTH = 'сентября';
    ELSE IF(N = 10) THEN V$MONTH = 'октября';
    ELSE IF(N = 11) THEN V$MONTH = 'ноября';
    ELSE IF(N = 12) THEN V$MONTH = 'декабря';

    IF (COALESCE(I$PLAIN_NUM, 0) = 0) THEN
      V$DAY = '«' || V$DAY || '»';
    VAL = V$DAY || ' ' || V$MONTH || ' ' || EXTRACT(YEAR FROM I$DATE) || ' г.';
  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DATE2STR (
    A_DATE DATE,
    LEADING_ZERO SMALLINT = 1)
RETURNS (
    RESULT VARCHAR(10))
AS
declare variable D_YEAR smallint;
declare variable D_MONTH smallint;
declare variable D_DAY smallint;
begin
  if (A_DATE is null) then
    RESULT = null;
  else
  begin
    D_YEAR = extract(year from A_DATE);
    D_MONTH = extract(month from A_DATE);
    D_DAY = extract(day from A_DATE);
    if (coalesce(LEADING_ZERO, 0) <> 0) then
      RESULT = lpad(cast(D_DAY as varchar(2)), 2, '0');
    else
    RESULT = cast(D_DAY as varchar(2));
    RESULT = RESULT || '.' || lpad(cast(D_MONTH as varchar(2)), 2, '0');
    IF(COALESCE(LEADING_ZERO, 0) <> 2) THEN RESULT = RESULT || '.' ||cast(D_YEAR as varchar(4));
  end
  suspend;
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DATIVECASE (
    I$F VARCHAR(250),
    I$I VARCHAR(250),
    I$O VARCHAR(250),
    I$SEX SMALLINT = null)
RETURNS (
    F VARCHAR(250),
    I VARCHAR(250),
    O VARCHAR(250))
AS
declare variable V$F varchar(250); /* declare variable V$I varchar(250); */
declare variable V$SRES varchar(200);
declare variable V$TMP varchar(200);
declare variable V$SEX smallint; /* declare variable V$L integer; */
declare variable V$COUNT_F_FULL integer;
declare variable V$COUNT_F integer;
declare variable V$COUNT_I integer;
declare variable V$COUNT_O integer;
declare variable V$STR_VAR1 varchar(250);
declare variable V$STR_VAR2 varchar(250);
BEGIN
    --lower
    -- V$L = 0;
    I$F = TRIM(:I$F);
    I$I = TRIM(:I$I);
    I$O = TRIM(:I$O);
    IF ((:I$F IS NULL)
        OR (:I$I IS NULL)
        OR (:I$O IS NULL)
        OR (CHAR_LENGTH(:I$O) < 4)
        OR (CHAR_LENGTH(:I$F) < 3)
        OR (CHAR_LENGTH(:I$I) < 2)) THEN
    BEGIN
        F = CASE
              WHEN CHAR_LENGTH(:I$F) > 0 THEN (:I$F)
              ELSE ''
            END;
        I = CASE
              WHEN CHAR_LENGTH(:I$I) > 0 THEN (:I$I)
              ELSE ''
            END;
        O = CASE
              WHEN CHAR_LENGTH(:I$O) > 0 THEN (:I$O)
              ELSE ''
            END;
        SUSPEND;
        EXIT;
    END
    I$F = REPLACE(TRIM(:I$F), ' - ', '-');
    I$F = REPLACE(REPLACE(:I$F, ' -', '-'), '- ', '-');

    IF (I$SEX IS NULL) THEN
    BEGIN
        V$COUNT_O = CHAR_LENGTH(:I$O);
        V$STR_VAR1 = SUBSTRING(:I$O FROM :V$COUNT_O FOR 1);
        V$STR_VAR2 = SUBSTRING(:I$O FROM :V$COUNT_O - 3 FOR 4);

        IF ((:V$STR_VAR1 = 'ч') OR (:V$STR_VAR2 = 'оглы')) THEN
        BEGIN
            V$SEX = 1;
        END
        ELSE
        BEGIN
            V$STR_VAR1 = SUBSTRING(:I$O FROM :V$COUNT_O - 1 FOR 2);
            V$STR_VAR2 = SUBSTRING(:I$O FROM V$COUNT_O - 3 FOR 4);
            IF ((:V$STR_VAR1 = 'на') OR (V$STR_VAR2 = 'кызы')) THEN
            BEGIN
                V$SEX = 0;
            END
        END

        V$COUNT_F_FULL = CHAR_LENGTH(:I$F);
        IF (:V$COUNT_F_FULL > 0) THEN -- Фамилия
        BEGIN
            FOR SELECT TAKEN
                FROM PARSING_STRING_GET(:I$F, '-')
                INTO :V$F
            DO
            BEGIN
                V$SRES = '';
                V$COUNT_F = CHAR_LENGTH(:V$F);
                IF (:V$SEX = 1) THEN -- мужские фамилии
                BEGIN
                    V$TMP = SUBSTRING(:V$F FROM :V$COUNT_F FOR 1);
                    IF (:V$TMP IN ('о', 'и', 'ы', 'у', 'э', 'е', 'ю')) THEN
                    BEGIN
                        V$SRES = :V$F;
                    END
                    ELSE
                    IF (:V$TMP IN ('ь', 'й')) THEN
                    BEGIN
                        V$SRES = SUBSTRING(:V$F FROM 1 FOR :V$COUNT_F - 1) || 'ю';
                    END
                    ELSE
                    IF (:V$TMP IN ('я', 'а')) THEN
                    BEGIN
                        V$SRES = SUBSTRING(:V$F FROM 1 FOR :V$COUNT_F - 1) || 'е';
                    END
                    ELSE
                        V$SRES = :V$F || 'у';
                    /* if (:V$L = 0) then
            V$SRES = :V$F;
          V$L = V$L + 1;   */

                    V$TMP = SUBSTRING(:V$F FROM :V$COUNT_F - 1 FOR 2);
                    IF (:V$TMP = 'ец') THEN
                        V$SRES = SUBSTRING(:V$F FROM 1 FOR :V$COUNT_F - 2) || 'цу';

                    IF (:V$TMP SIMILAR TO '%[уеыаоэяиюё]ец') THEN
                        V$SRES = SUBSTRING(:V$F FROM 1 FOR :V$COUNT_F - 1) || 'цу';
                    IF (:V$TMP SIMILAR TO '%[^уеыаоэяиюё][^уеыаоэяиюё]ец') THEN
                        V$SRES = :V$F || 'у';/**/
                    IF (:V$TMP IN ('зе', 'их', 'ых')) THEN
                        V$SRES = :V$F;
                    IF (:V$TMP = 'ый') THEN
                        V$SRES = SUBSTRING(:V$F FROM 1 FOR :V$COUNT_F - 2) || 'ому';
                    IF (:V$TMP IN ('ой', 'ий')) THEN
                        V$SRES = SUBSTRING(:V$F FROM 1 FOR :V$COUNT_F - 2) || 'ому';
                    IF (V$COUNT_F <= 4) THEN
                        V$SRES = SUBSTRING(:V$F FROM 1 FOR :V$COUNT_F - 1) || 'ю';
                    IF (SUBSTRING(:V$F FROM :V$COUNT_F - 2 FOR 3) = 'чий') THEN
                        V$SRES = SUBSTRING(:V$F FROM 1 FOR :V$COUNT_F - 2) || 'ему';
                    IF (:V$TMP = 'уй') THEN
                        V$SRES = SUBSTRING(:V$F FROM 1 FOR :V$COUNT_F - 2) || 'ую';
                END
                ELSE -- Женские фамилии
                BEGIN
                    V$TMP = SUBSTRING(:V$F FROM :V$COUNT_F FOR 1);
                    IF (:V$TMP IN ('о', 'е', 'э', 'и', 'ы', 'у', 'ю', 'б',
                                    'в', 'г', 'д', 'ж', 'з', 'к', 'л', 'м', 'н',
                                    'п', 'р', 'с', 'т', 'ф', 'х', 'ц', 'ч', 'ш',
                                    'щ', 'ь', 'й')) THEN
                        V$SRES = :V$F;
                    ELSE
                    IF (:V$TMP = 'я') THEN
                        V$SRES = SUBSTRING(:V$F FROM 1 FOR :V$COUNT_F - 2) || 'ой';
                    ELSE
                        V$SRES = SUBSTRING(:V$F FROM 1 FOR :V$COUNT_F - 1) || 'ой';

                    V$TMP = SUBSTRING(:V$F FROM :V$COUNT_F - 1 FOR 2);
                    IF (:V$TMP IN ('ха', 'да', 'ее')) THEN
                        V$SRES = SUBSTRING(:V$F FROM 1 FOR :V$COUNT_F - 1) || 'е';

                    IF (:V$TMP SIMILAR TO '%[уеыаоэяиюё]а') THEN
                        V$SRES = :V$F;/**/
                END
                IF ((:F IS NULL) OR (:F = '')) THEN
                    F = :V$SRES;
                ELSE
                    F = :F || '-' || :V$SRES;
            END
        END

        IF (CHAR_LENGTH(I$I) > 0) THEN -- Имя
        BEGIN
            V$COUNT_I = CHAR_LENGTH(:I$I);

            IF (:I$I = 'Павел') THEN
                V$SRES = 'Павлу';
            ELSE
            IF (:I$I = 'Лев') THEN
                V$SRES = 'Льву';
            ELSE
            IF (:I$I IN ('Петр', 'Пётр')) THEN
                V$SRES = 'Петру';
            ELSE
            IF (:I$I IN ('Али', 'Бали', 'Рене', 'Роже', 'Оноре', 'Хосе',
                         'Дитте', 'Озе', 'Панталоне', 'Анри', 'Луи', 'Лизи',
                         'Бетси', 'Джованни', 'Мери', 'Этери', 'Гиви', 'Пьеро',
                         'Лео', 'Амадео', 'Ромео', 'Карло', 'Ласло', 'Бруно',
                         'Гуго', 'Данко', 'Франсуа', 'Нана', 'Атала', 'Коломба')) THEN
                V$SRES = :I$I;
            ELSE
            IF (:V$SEX = 1) THEN
            BEGIN
                V$TMP = SUBSTRING(:I$I FROM :V$COUNT_I FOR 1);
                IF (:V$TMP IN ('й', 'ь')) THEN
                    V$SRES = SUBSTRING(:I$I FROM 1 FOR :V$COUNT_I - 1) || 'ю';
                ELSE
                IF (:V$TMP IN ('а', 'я')) THEN
                    V$SRES = SUBSTRING(:I$I FROM 1 FOR :V$COUNT_I - 1) || 'е';
                ELSE
                IF (:V$TMP = 'о') THEN
                    V$SRES = :I$I;
                ELSE
                    V$SRES = :I$I || 'у';
            END
            ELSE
            BEGIN
                V$TMP = SUBSTRING(:I$I FROM :V$COUNT_I FOR 1);
                IF (:V$TMP IN ('а', 'я')) THEN
                BEGIN
                    IF (SUBSTRING(:I$I FROM :V$COUNT_I - 1 FOR 1) = 'и') THEN -- ???
                        V$SRES = SUBSTRING(:I$I FROM 1 FOR :V$COUNT_I - 1) || 'и';
                    ELSE
                        V$SRES = SUBSTRING(:I$I FROM 1 FOR :V$COUNT_I - 1) || 'е';
                END
                ELSE
                IF (:V$TMP = 'ь') THEN
                    V$SRES = SUBSTRING(:I$I FROM 1 FOR :V$COUNT_I - 1) || 'и';
                ELSE
                    V$SRES = :I$I;
            END
            I = :V$SRES;
        END

        IF (CHAR_LENGTH(I$O) > 0) THEN -- отчество
        BEGIN
            IF ((:V$STR_VAR2 = 'оглы') OR (:V$STR_VAR2 = 'кызы')) THEN
                V$SRES = :I$O;
            ELSE
            IF (:V$SEX = 1) THEN
                V$SRES = :I$O || 'у';
            ELSE
                V$SRES = SUBSTRING(:I$O FROM 1 FOR :V$COUNT_O - 1) || 'е';
        END
        O = :V$SRES;
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DAYS_COUNT_TO_WORK_TIME (
    C INTEGER)
RETURNS (
    WORK_TIME VARCHAR(100))
AS
declare variable Y integer;
declare variable M integer;
declare variable D integer;
declare variable V varchar(5);
BEGIN
    WORK_TIME = '';
    Y = C / 360;
    C = C - Y * 360; -- MOD 360
    M = C / 30;
    C = C - M * 30; -- MOD 30
    D = C;

    IF (Y > 0) THEN
    BEGIN
        SELECT WORD FROM REPORT_WORDS WHERE ID = 22 INTO :V;
        IF (Y < 5) THEN SELECT WORD FROM REPORT_WORDS WHERE ID = 23 INTO :V;
        WORK_TIME = Y || V || ' ';
    END

    IF (M > 0) THEN
    BEGIN
        SELECT WORD FROM REPORT_WORDS WHERE ID = 24 INTO :V;
        WORK_TIME = WORK_TIME || M || V || ' ';
    END

    IF (D > 0) THEN
    BEGIN
        SELECT WORD FROM REPORT_WORDS WHERE ID = 25 INTO :V;
        WORK_TIME = WORK_TIME || D || V;
    END

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_DELETE_LEAVE (
    I$VACANCY_ID BIGINT,
    I$USER_ID VARCHAR(40))
AS
DECLARE VARIABLE V$ID BIGINT;
DECLARE VARIABLE V$PERSON_ID BIGINT;
DECLARE VARIABLE V$JOB_ID BIGINT;
DECLARE VARIABLE S VARCHAR(1000);
begin

  -- Есть ли права у пользователя ?
  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  -- !!! надо вероятно проверять, что нельзя удалять последнюю запись

  -- Найдем уволенного сотрудника
  SELECT FIRST 1 LP14.PARENT_ID
  FROM LINKS LP14
  WHERE LP14.OBJ_ID = :I$VACANCY_ID AND LP14.OBJ_TYPE_ID = 15 AND LP14.PARENT_TYPE_ID = 14 AND LP14.DATE_DEL IS NULL
  INTO :V$PERSON_ID;

  IF(V$PERSON_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Недопустимый объект, или назначение на должность было уже удалено';

  -- Найдем приказы, согласно которому прошли прием на должность и увольнение
  FOR
    SELECT OBJ_ID
    FROM (
      SELECT O.OBJ_ID
      FROM ORDERS O
      JOIN ORDER_DATA OD ON OD.ORDER_ID = O.OBJ_ID AND OD.DATE_DEL IS NULL AND OD.REF_ID = :V$PERSON_ID
        AND OD.JOB_ID = (SELECT FIRST 1 L15.PARENT_ID FROM LINKS L15 WHERE L15.OBJ_ID = :I$VACANCY_ID AND L15.PARENT_TYPE_ID = 13 AND L15.DATE_DEL IS NULL)
      WHERE O.DATE_DEL IS NULL AND O.TYPE_ID = 14256 AND O.STATE_ID = 11715  -- действующий приказ на прием
      UNION
      SELECT O.OBJ_ID
      FROM ORDERS O
      JOIN ORDER_DATA OD ON OD.ORDER_ID = O.OBJ_ID AND OD.DATE_DEL IS NULL AND OD.REF_ID = :V$PERSON_ID AND OD.JOB_ID = :I$VACANCY_ID
      WHERE O.DATE_DEL IS NULL AND O.TYPE_ID = 14257 AND O.STATE_ID = 11715)  -- действующий приказ на увольнение
    ORDER BY OBJ_ID DESC
    INTO :V$ID
  DO
  BEGIN
    -- Отменим приказ
    --FOR
    --  SELECT VAL FROM ORDER_SET_STATE(:V$ID, 11717, :I$USER_ID) INTO :S -- недействующий
    --DO
    --BEGIN
      -- Если приказ был на увольнение со всех должностей, то и при отмене увольнения будет отменен приказ, а сотрудник будет восстановлен по всем должностям
    --END
    UPDATE ORDERS O
    SET
      O.USER_ID = :I$USER_ID,
      O.STATE_ID = 11717 -- недействительный
    WHERE O.OBJ_ID = :V$ID AND O.STATE_ID <> 11717;

    -- Раз запись была ошибочной, то и сам приказ надо удалить.
    EXECUTE PROCEDURE ORDER_DELETE(:V$ID, :I$USER_ID);
  END

  -- Удаляем назначение на должность. ID удалившего юзера фиксируем в REASON_ID
  -- если прием был через приказы, то на этой фазе строка в LINKS уже будет удаленной
  UPDATE LINKS
  SET DATE_DEL = CURRENT_TIMESTAMP, REASON_ID = :I$USER_ID
  WHERE OBJ_ID = :I$VACANCY_ID AND DATE_DEL IS NULL;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_LINK_SET (
    I$PARENT_ID BIGINT,
    I$CHILD_ID BIGINT,
    I$LEVEL_ID BIGINT,
    I$SORT_ORDER BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    LINK_ID BIGINT)
AS
DECLARE VARIABLE V$TYPE_ID BIGINT;
DECLARE VARIABLE V$CHILD_TYPE_ID BIGINT;
DECLARE VARIABLE V$ORDER BIGINT;
begin

  IF(I$LEVEL_ID > 100000) THEN I$LEVEL_ID = I$LEVEL_ID - 100000;

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  SELECT TYPE_ID
  FROM OBJECTS
  WHERE OBJ_ID = :I$PARENT_ID
  INTO :V$TYPE_ID;

  IF(V$TYPE_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Родительский объект не найден или бы удален';

  SELECT TYPE_ID
  FROM OBJECTS
  WHERE OBJ_ID = :I$CHILD_ID
  INTO :V$CHILD_TYPE_ID;

  IF(V$CHILD_TYPE_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Подчиненный объект не найден или бы удален';

  -- А можно ли редактировать объекты этого типа в данном уровне ?
  IF(NOT EXISTS(
    SELECT FIRST 1 1
    FROM PARENTS P
    JOIN LTYPES LT ON LT.TYPE_ID = P.CHILD_ID AND LT.LEVEL_ID = :I$LEVEL_ID AND LT.IS_DEL = 0 AND LT.EDIT_TYPE >= 0
    JOIN LUSERS LU ON LU.USER_ID = :I$USER_ID AND LU.LEVEL_ID = LT.LEVEL_ID AND LU.READ_ONLY = 0
    JOIN USERS U ON U.USER_ID = LU.USER_ID AND U.DATE_DEL IS NULL AND U.IS_BLOCKED = 0
    WHERE P.TYPE_ID = :V$TYPE_ID AND P.CHILD_ID = :V$CHILD_TYPE_ID AND (P.IS_LINK <> 0 OR P.IS_SELECT <> 0)
  )) THEN EXCEPTION DATA_ERROR 'Редактирование связей в данном приложении невозможно или у вас нет прав доступа';

  IF(I$SORT_ORDER < 0) THEN
  BEGIN
    SELECT DEL_COUNT
    FROM OBJECT_DEL(:I$PARENT_ID, :I$CHILD_ID)
    INTO :V$TYPE_ID;
  END
  ELSE
  BEGIN
    SELECT FIRST 1 L.LINK_ID, L.COST
    FROM LINKS L
    WHERE L.PARENT_ID = :I$PARENT_ID AND L.OBJ_ID = :I$CHILD_ID AND L.DATE_DEL IS NULL
    INTO :LINK_ID, :V$ORDER;

    IF(LINK_ID IS NULL) THEN
    BEGIN
      SELECT LINK_ID FROM OBJECT_ADD_LINK(:I$PARENT_ID, :I$CHILD_ID, :V$CHILD_TYPE_ID, NULL, NULL, :I$USER_ID, :I$SORT_ORDER, :I$LEVEL_ID) INTO :LINK_ID;
    END
    ELSE IF(V$ORDER <> I$SORT_ORDER) THEN
    BEGIN
      UPDATE LINKS
      SET COST = :I$SORT_ORDER
      WHERE LINK_ID = :LINK_ID;
    END
  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_LIST_CONTENT (
    I$OBJ_ID BIGINT,
    I$PARAM_ID BIGINT,
    I$USER_ID VARCHAR(40),
    I$FILTERED SMALLINT = 0)
RETURNS (
    LIST_ID BIGINT,
    LISTVAL_ID BIGINT,
    PARENT_ID BIGINT,
    VAL VARCHAR(4000),
    TAG VARCHAR(100),
    "FILTER" VARCHAR(255),
    SORT_ORDER SMALLINT,
    COST FLOAT,
    IS_DEL SMALLINT)
AS
declare variable V$USER_ID bigint;
declare variable V$PARAM_TYPE smallint;
declare variable V$LIST_ID bigint;
declare variable V$SQL varchar(1000);
begin

  IF(I$USER_ID = 'Веб-администратор') THEN V$USER_ID = 1; ELSE V$USER_ID = CAST(I$USER_ID AS BIGINT);

  IF(NOT EXISTS(
      SELECT FIRST 1 1
      FROM USERS U
      WHERE U.USER_ID = :V$USER_ID AND U.DATE_DEL IS NULL AND U.IS_BLOCKED = 0 AND (U.EXP_DATE IS NULL OR U.EXP_DATE > CURRENT_DATE)
  )) THEN EXCEPTION DATA_ERROR 'У вас нет доступа';

  -- Проверяем, что за параметр
  SELECT P.PARAM_TYPE, P.LIST_ID, P.RUN_SQL
  FROM PARAMS P
  WHERE P.PARAM_ID = :I$PARAM_ID AND P.IS_DEL = 0
  INTO :V$PARAM_TYPE, :V$LIST_ID, :V$SQL;

  -- Тип 13 reference также обрабатываем как список
  IF(V$PARAM_TYPE IS NULL OR V$PARAM_TYPE NOT IN (6, 7, 13, 20)) THEN EXCEPTION DATA_ERROR 'Параметр не найден или имеет не-списковый тип';

  IF(V$SQL IS NULL OR CHAR_LENGTH(V$SQL) = 0) THEN
  BEGIN
      IF(V$LIST_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не задан ID списка';

      FOR
          SELECT LIST_ID, LISTVAL_ID, PARENT_ID, VAL, TAG, "FILTER", SORT_ORDER, COST, IS_DEL
          FROM LISTVALS_LIST(:V$LIST_ID, 'RU')
          WHERE IS_DEL = 0
          INTO :LIST_ID, :LISTVAL_ID, :PARENT_ID, :VAL, :TAG, :"FILTER", :SORT_ORDER, :COST, :IS_DEL
      DO
      BEGIN
          SUSPEND;
      END
  END
  ELSE
  BEGIN
      -- Выборку сделает вторым вызовом серверная сторона, признак такого варианта - значение IS_DEL = 2
      IS_DEL = 2;
      LIST_ID = V$LIST_ID;
      VAL = V$SQL;
      SUSPEND;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_LPJ_SERIALIZE (
    I$DATE_FROM TIMESTAMP,
    I$DATE_TO TIMESTAMP = current_timestamp)
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
declare variable V$OBJ_ID bigint;
declare variable V$TYPE_ID bigint;
declare variable V$CJ_TYPE integer;
declare variable V$PERSON_ID bigint;
declare variable V$REPL_ID bigint;
declare variable V$GRADE_ID bigint;
declare variable V$TEMPLATE_ID bigint;
declare variable V$PERIOD_ID bigint;
declare variable V$YEAR_ID bigint;
declare variable V$YEAR integer;
declare variable S1 varchar(1000);
declare variable S2 varchar(1000);
declare variable S3 varchar(1000);
declare variable V$DATE1 date;
declare variable V$DATE2 date;
declare variable V$DT timestamp;
declare variable V$ROLE smallint;
declare variable N integer;
begin

  TAG_NAME = 'ou_name';
  SELECT FIRST 1 C.CAPTION, V1236.LISTVAL_ID, CY.VAL, LV.COST
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  LEFT JOIN OBJECT_CAPTION_GET(L2.OBJ_ID) C ON 1 = 1
  LEFT JOIN LISTVAL_TEXT(V1236.LISTVAL_ID) CY ON 1 = 1
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :VAL, :V$YEAR_ID, :S1, :V$YEAR;
  SUSPEND;

  TAG_NAME = 'year';
  VAL = S1;
  SUSPEND;

  -- Пользователи - сотрудники, родители, ученики
  TAG_NAME = 'users::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT U.USER_ID, U.DATE_DEL, U.IS_BLOCKED, U.USER_NAME, U.PWD, U.OBJ_ID, U.USER_TYPE
    FROM USERS U
    WHERE (U.DATE_MODIFY >= :I$DATE_FROM OR :I$DATE_FROM IS NULL) AND (U.DATE_MODIFY < :I$DATE_TO
      OR EXISTS(SELECT FIRST 1 1 FROM LINKS LP10 WHERE LP10.OBJ_ID = U.OBJ_ID AND LP10.PARENT_TYPE_ID = 10
        AND (LP10.DATE_MODIFY >= :I$DATE_FROM OR :I$DATE_FROM IS NULL)
      ))
    INTO :V$OBJ_ID, :V$DT, :N, :S1, :S2, :V$PERSON_ID, :V$ROLE
  DO
  BEGIN
    TAG_NAME = 'users:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'users:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    IF(V$DT IS NOT NULL OR N > 0) THEN
    BEGIN
      TAG_NAME = 'users:r:delete';
      VAL = 1;
      SUSPEND;
    END
    ELSE
    BEGIN
      TAG_NAME = 'users:r:ref_id';
      VAL = V$PERSON_ID;
      SUSPEND;
      TAG_NAME = 'users:r:role';
      VAL = V$ROLE;
      SUSPEND;
      TAG_NAME = 'users:r:username';
      VAL = S1;
      SUSPEND;
      TAG_NAME = 'users:r:password';
      VAL = S2;
      SUSPEND;

      V$TYPE_ID = NULL;
      S3 = NULL;
      SELECT FIRST 1 L.OBJ_TYPE_ID, C.CAPTION
      FROM LINKS L
      LEFT JOIN OBJECT_CAPTION_GET(L.PARENT_ID) C ON 1 = 1
      WHERE L.OBJ_ID = :V$PERSON_ID AND L.PARENT_TYPE_ID IN (2, 211, 9, 10, 125, 187, 81, 82, 83, 84, 86) AND L.DATE_DEL IS NULL
      ORDER BY IIF(L.PARENT_TYPE_ID IN (81, 82, 83, 84, 86), 1, 0)
      INTO :V$TYPE_ID, :S3;

      IF(V$TYPE_ID = 14) THEN S3 = NULL;

      TAG_NAME = 'users:r:type';
      VAL = V$TYPE_ID;
      SUSPEND;
      TAG_NAME = 'users:r:grade';
      VAL = S3;
      SUSPEND;
      -- Дети
      TAG_NAME = 'users:r:children::json&colon;array';
      VAL = 1;
      SUSPEND;
      IF(V$TYPE_ID = 20) THEN
      BEGIN
        FOR
          SELECT DISTINCT LP10.PARENT_ID
          FROM LINKS LP10
          WHERE LP10.OBJ_ID = :V$PERSON_ID AND LP10.PARENT_TYPE_ID = 10
          INTO :V$OBJ_ID
        DO
        BEGIN
          TAG_NAME = 'users:r:children:r';
          VAL = NULL;
          SUSPEND;
          TAG_NAME = 'users:r:children:r:id';
          VAL = V$OBJ_ID;
          SUSPEND;
          TAG_NAME = 'users:r:children:r:deleted';
          VAL = 1;
          SELECT FIRST 1 0
          FROM LINKS LP10
          JOIN LINKS LP9 ON LP9.OBJ_ID = LP10.PARENT_ID AND LP9.PARENT_TYPE_ID IN (9, 187, 46) AND LP9.DATE_DEL IS NULL
          WHERE LP10.OBJ_ID = :V$PERSON_ID AND LP10.PARENT_ID = :V$OBJ_ID AND LP10.DATE_DEL IS NULL
          INTO :VAL;
          SUSPEND;
        END
      END
      ELSE IF(V$TYPE_ID = 14) THEN
      BEGIN
        -- Ищем копию самого себя среди родителей - по СНИЛС или по ФИО и дате рождения !
        FOR
          SELECT DISTINCT LP10.PARENT_ID, LP10.OBJ_ID
          FROM VALS V2455
          JOIN VALS V2365 ON V2365.PARAM_ID = 2365 AND V2365.IS_DEL = 0 AND V2365.SVAL = V2455.SVAL
          JOIN LINKS LP10 ON LP10.OBJ_ID = V2365.OBJ_ID AND LP10.PARENT_TYPE_ID = 10 AND LP10.DATE_DEL IS NULL
          WHERE V2455.OBJ_ID = :V$PERSON_ID AND V2455.PARAM_ID = 2455 AND V2455.IS_DEL = 0
          INTO :V$OBJ_ID, :V$REPL_ID
        DO
        BEGIN
          TAG_NAME = 'users:r:children:r';
          VAL = NULL;
          SUSPEND;
          TAG_NAME = 'users:r:children:r:id';
          VAL = V$OBJ_ID;
          SUSPEND;
          TAG_NAME = 'users:r:children:r:deleted';
          VAL = 1;
          SELECT FIRST 1 0
          FROM LINKS LP10
          JOIN LINKS LP9 ON LP9.OBJ_ID = LP10.PARENT_ID AND LP9.PARENT_TYPE_ID IN (9, 187, 46) AND LP9.DATE_DEL IS NULL
          WHERE LP10.OBJ_ID = :V$REPL_ID AND LP10.PARENT_ID = :V$OBJ_ID AND LP10.DATE_DEL IS NULL
          INTO :VAL;
          SUSPEND;
        END
      END
    END
  END

  -- Персоны
  TAG_NAME = 'persons::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT DISTINCT L10.OBJ_ID, L10.OBJ_TYPE_ID, V55.SVAL || ' ' || V56.SVAL || COALESCE(' ' || V57.SVAL, '')
    FROM LINKS L10
    JOIN VALS V55 ON V55.OBJ_ID = L10.OBJ_ID AND V55.PARAM_ID = 55 AND V55.IS_DEL = 0
    JOIN VALS V56 ON V56.OBJ_ID = L10.OBJ_ID AND V56.PARAM_ID = 56 AND V56.IS_DEL = 0
    LEFT JOIN VALS V57 ON V57.OBJ_ID = L10.OBJ_ID AND V57.PARAM_ID = 57 AND V57.IS_DEL = 0
    WHERE L10.PARENT_TYPE_ID IN (9, 46, 187) AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      AND (
        ((L10.DATE_MODIFY >= :I$DATE_FROM OR :I$DATE_FROM IS NULL) AND L10.DATE_MODIFY < :I$DATE_TO) OR
        ((V55.DATE_MODIFY >= :I$DATE_FROM OR :I$DATE_FROM IS NULL) AND V55.DATE_MODIFY < :I$DATE_TO) OR
        ((V56.DATE_MODIFY >= :I$DATE_FROM OR :I$DATE_FROM IS NULL) AND V56.DATE_MODIFY < :I$DATE_TO)
      )
    UNION
    SELECT DISTINCT L20.OBJ_ID, L20.OBJ_TYPE_ID, V128.SVAL || ' ' || V129.SVAL || COALESCE(' ' || V130.SVAL, '')
    FROM LINKS L20
    JOIN VALS V128 ON V128.OBJ_ID = L20.OBJ_ID AND V128.PARAM_ID = 128 AND V128.IS_DEL = 0
    JOIN VALS V129 ON V129.OBJ_ID = L20.OBJ_ID AND V129.PARAM_ID = 129 AND V129.IS_DEL = 0
    LEFT JOIN VALS V130 ON V130.OBJ_ID = L20.OBJ_ID AND V130.PARAM_ID = 130 AND V130.IS_DEL = 0
    WHERE L20.PARENT_TYPE_ID = 10 AND L20.OBJ_TYPE_ID = 20 AND L20.DATE_DEL IS NULL
      AND (
        ((L20.DATE_MODIFY >= :I$DATE_FROM OR :I$DATE_FROM IS NULL) AND L20.DATE_MODIFY < :I$DATE_TO) OR
        ((V128.DATE_MODIFY >= :I$DATE_FROM OR :I$DATE_FROM IS NULL) AND V128.DATE_MODIFY < :I$DATE_TO) OR
        ((V129.DATE_MODIFY >= :I$DATE_FROM OR :I$DATE_FROM IS NULL) AND V129.DATE_MODIFY < :I$DATE_TO)
      )
    UNION
    SELECT DISTINCT L14.OBJ_ID, L14.OBJ_TYPE_ID, V59.SVAL || ' ' || V60.SVAL || COALESCE(' ' || V61.SVAL, '')
    FROM LINKS L14
    JOIN VALS V59 ON V59.OBJ_ID = L14.OBJ_ID AND V59.PARAM_ID = 59 AND V59.IS_DEL = 0
    JOIN VALS V60 ON V60.OBJ_ID = L14.OBJ_ID AND V60.PARAM_ID = 60 AND V60.IS_DEL = 0
    LEFT JOIN VALS V61 ON V61.OBJ_ID = L14.OBJ_ID AND V61.PARAM_ID = 61 AND V61.IS_DEL = 0
    WHERE L14.PARENT_TYPE_ID = 2 AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
      AND (
        ((L14.DATE_MODIFY >= :I$DATE_FROM OR :I$DATE_FROM IS NULL) AND L14.DATE_MODIFY < :I$DATE_TO) OR
        ((V59.DATE_MODIFY >= :I$DATE_FROM OR :I$DATE_FROM IS NULL) AND V59.DATE_MODIFY < :I$DATE_TO) OR
        ((V60.DATE_MODIFY >= :I$DATE_FROM OR :I$DATE_FROM IS NULL) AND V60.DATE_MODIFY < :I$DATE_TO)
      )
    ORDER BY 2, 3
    INTO :V$PERSON_ID, :V$TYPE_ID, :S1
  DO
  BEGIN
    TAG_NAME = 'persons:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'persons:r:id';
    VAL = V$PERSON_ID;
    SUSPEND;
    TAG_NAME = 'persons:r:type';
    VAL = V$TYPE_ID;
    SUSPEND;
    TAG_NAME = 'persons:r:name';
    VAL = S1;
    SUSPEND;
    TAG_NAME = 'persons:r:grade_name';
    VAL = '';
    IF(V$TYPE_ID = 10) THEN
    BEGIN
      SELECT FIRST 1 C.CAPTION
      FROM LINKS LPG
      LEFT JOIN OBJECT_CAPTION_GET(LPG.PARENT_ID) C ON 1 = 1
      WHERE LPG.OBJ_ID = :V$PERSON_ID AND LPG.PARENT_TYPE_ID IN (9, 125, 187) AND LPG.DATE_DEL IS NULL
      INTO :VAL;
    END
    SUSPEND;
  END

  -- Группы - тут сразу отдаем журнал
  TAG_NAME = 'groups::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT DISTINCT M.GROUP_ID, G.TYPE_ID, M.STAGE_ID
    FROM PERSON_MOVEMENTS M
    JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID IN (9, 125, 157, 256, 179, 46)
    WHERE (M.DATE_MODIFY >= :I$DATE_FROM OR :I$DATE_FROM IS NULL) AND M.DATE_MODIFY < :I$DATE_TO
      AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :I$DATE_FROM)
    INTO :V$GRADE_ID, :V$TYPE_ID, :V$REPL_ID
  DO
  BEGIN
    TAG_NAME = 'groups:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'groups:r:id';
    VAL = V$GRADE_ID;
    SUSPEND;
    TAG_NAME = 'groups:r:type';
    VAL = V$TYPE_ID;
    SUSPEND;
    TAG_NAME = 'groups:r:stage';
    VAL = V$REPL_ID;
    SUSPEND;
    TAG_NAME = 'groups:r:name';
    VAL = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$GRADE_ID));
    SUSPEND;
  END

  -- Журналы
  TAG_NAME = 'journals::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT J.OBJ_ID, J.DATE_DEL, J.JOURNAL_TYPE, J.GRADE_ID, J.PERIOD_ID, J.SUBJECT_ID, J.TEACHER_ID,
      J.JOURNAL_NAME, IIF(J.SUBJECT_ID IS NULL, NULL, C.CAPTION)
    FROM CJ2_JOURNAL J
    LEFT JOIN OBJECT_CAPTION_GET(J.SUBJECT_ID) C ON 1 = 1
    WHERE (J.DATE_MODIFY >= :I$DATE_FROM OR :I$DATE_FROM IS NULL) AND J.DATE_MODIFY < :I$DATE_TO
    INTO :V$OBJ_ID, :V$DT, :V$CJ_TYPE, :V$GRADE_ID, :V$PERIOD_ID, :V$TYPE_ID, :V$TEMPLATE_ID, :S1, :S2
  DO
  BEGIN
    TAG_NAME = 'journals:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'journals:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    IF(V$DT IS NOT NULL) THEN
    BEGIN
      TAG_NAME = 'journals:r:delete';
      VAL = 1;
      SUSPEND;
    END
    ELSE
    BEGIN
      TAG_NAME = 'journals:r:cj_type';
      VAL = V$CJ_TYPE;
      SUSPEND;
      TAG_NAME = 'journals:r:group_id';
      VAL = V$GRADE_ID;
      SUSPEND;
      TAG_NAME = 'journals:r:period_id';
      VAL = V$PERIOD_ID;
      SUSPEND;
      TAG_NAME = 'journals:r:subject_id';
      VAL = V$TYPE_ID;
      SUSPEND;
      TAG_NAME = 'journals:r:name';
      VAL = S1;
      SUSPEND;
      TAG_NAME = 'journals:r:subject';
      VAL = S2;
      SUSPEND;
      TAG_NAME = 'journals:r:teacher';
      VAL = '';
      IF(V$TEMPLATE_ID IS NULL) THEN
      BEGIN
        VAL = NULL;
        SELECT LIST(C.CAPTION, ', ')
        FROM LINKS L186
        JOIN VALR V1609 ON V1609.OBJ_ID = L186.OBJ_ID AND V1609.PARAM_ID = 1609 AND V1609.IS_DEL = 0
        LEFT JOIN OBJECT_CAPTION_GET(V1609.VAL) C ON 1 = 1
        WHERE L186.PARENT_ID = :V$GRADE_ID AND L186.OBJ_TYPE_ID = 186 AND L186.DATE_DEL IS NULL
        INTO :VAL;
      END
      ELSE
      BEGIN
        VAL = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$TEMPLATE_ID));
      END
      SUSPEND;

    END
  END

  -- Периоды
  TAG_NAME = 'periods::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L151.OBJ_ID, L154.OBJ_ID, COALESCE(L151.DATE_DEL, L154.DATE_DEL), V1170.LISTVAL_ID, C.VAL, V1169.VAL, V1174.VAL
    FROM LINKS L2
    JOIN LINKS L150 ON L150.PARENT_ID = L2.OBJ_ID AND L150.OBJ_TYPE_ID IN (150, 481) AND L150.DATE_DEL IS NULL
    JOIN LINKS L151 ON L151.PARENT_ID = L150.OBJ_ID AND L151.OBJ_TYPE_ID = 151 AND L151.DATE_DEL IS NULL
    JOIN LINKS L154 ON L154.PARENT_ID = L151.OBJ_ID AND L154.OBJ_TYPE_ID = 154 AND L154.DATE_DEL IS NULL
    LEFT JOIN VALL V1170 ON V1170.OBJ_ID = L154.OBJ_ID AND V1170.PARAM_ID = 1170 AND V1170.IS_DEL = 0
    LEFT JOIN VALD V1169 ON V1169.OBJ_ID = L154.OBJ_ID AND V1169.PARAM_ID = 1169 AND V1169.IS_DEL = 0
    LEFT JOIN VALD V1174 ON V1174.OBJ_ID = L154.OBJ_ID AND V1174.PARAM_ID = 1174 AND V1174.IS_DEL = 0
    LEFT JOIN LISTVAL_TEXT(V1170.LISTVAL_ID) C ON 1 = 1
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :V$PERIOD_ID, :V$OBJ_ID, :V$DT, :V$TEMPLATE_ID, :S1, :V$DATE1, :V$DATE2
  DO
  BEGIN
    TAG_NAME = 'periods:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'periods:r:period_id';
    VAL = V$PERIOD_ID;
    SUSPEND;
    TAG_NAME = 'periods:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    IF(V$DT IS NOT NULL) THEN
    BEGIN
      TAG_NAME = 'periods:r:delete';
      VAL = 1;
      SUSPEND;
    END
    ELSE
    BEGIN
      TAG_NAME = 'periods:r:type_id';
      VAL = V$TEMPLATE_ID;
      SUSPEND;
      TAG_NAME = 'periods:r:name';
      VAL = S1;
      SUSPEND;
      TAG_NAME = 'periods:r:date_from';
      VAL = (SELECT VAL FROM DATE2ISO(:V$DATE1, 0));
      SUSPEND;
      TAG_NAME = 'periods:r:date_to';
      VAL = (SELECT VAL FROM DATE2ISO(:V$DATE2, 0));
      SUSPEND;
    END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_LPJ_SERIALIZE_FILES (
    I$DATE_FROM TIMESTAMP,
    I$DATE_TO TIMESTAMP = current_timestamp)
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
declare variable V$LESSON_ID bigint;
declare variable V$CC_ID bigint;
declare variable S1 varchar(1000);
declare variable V$DT timestamp;
declare variable N integer;
declare variable NX integer;
begin

  NX = 0;

  TAG_NAME = 'files::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT B.OBJ_ID, B.LESSON_ID, B.DATE_DEL, B.FILE_TYPE, B.FILE_NAME
    FROM CJ2_BLOB B
    JOIN CJ2_JOURNAL_LESSONS L ON L.OBJ_ID = B.LESSON_ID AND L.DATE_DEL IS NULL
    JOIN CJ2_JOURNAL J ON J.OBJ_ID = L.CJ_ID AND J.DATE_DEL IS NULL
    WHERE (B.DATE_MODIFY >= :I$DATE_FROM OR :I$DATE_FROM IS NULL) AND B.DATE_MODIFY < :I$DATE_TO
    INTO :V$CC_ID, :V$LESSON_ID, :V$DT, :N, :S1
  DO
  BEGIN
    TAG_NAME = 'files:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'files:r:id';
    VAL = V$CC_ID;
    SUSPEND;
    TAG_NAME = 'files:r:lesson_id';
    VAL = V$LESSON_ID;
    SUSPEND;
    IF(V$DT IS NOT NULL) THEN
    BEGIN
      TAG_NAME = 'files:r:deleted';
      VAL = 1;
      SUSPEND;
    END
    ELSE
    BEGIN
      TAG_NAME = 'files:r:type';
      VAL = N;
      SUSPEND;
      TAG_NAME = 'files:r:name';
      VAL = S1;
      SUSPEND;
    END

    NX = NX + 1;
    IF(NX >= 10000) THEN
    BEGIN
      NX = 0;
      TAG_NAME = NULL;
      VAL = 'DIVIDE';
      SUSPEND;
      TAG_NAME = 'files::json&colon;array';
      VAL = 1;
      SUSPEND;
    END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_LPJ_SERIALIZE_LESSONS (
    I$DATE_FROM TIMESTAMP,
    I$DATE_TO TIMESTAMP = current_timestamp)
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(4000))
AS
declare variable V$GRADE_ID bigint;
declare variable SID varchar(40);
declare variable S1 varchar(1000);
declare variable S2 varchar(1000);
declare variable S3 varchar(2000);
declare variable V$DATE1 date;
declare variable V$DT timestamp;
declare variable N bigint;
declare variable F integer;
declare variable V$INST varchar(1000);
declare variable NX integer;
begin

  NX = 0;

  -- Уроки
  TAG_NAME = 'lessons::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L.OBJ_ID, L.DATE_DEL, L.CJ_ID, L.LESSON_DATE, L.LESSON_NUM, L.LESSON_THEME, L.LESSON_HOMEWORK, L.LESSON_EXTRA,
      L.INST_ID, L.IS_COMPLETED + L.IS_PUBLISHED * 2
    FROM CJ2_JOURNAL_LESSONS L
    JOIN CJ2_JOURNAL J ON J.OBJ_ID = L.CJ_ID AND J.DATE_DEL IS NULL
    WHERE (L.DATE_MODIFY >= :I$DATE_FROM OR :I$DATE_FROM IS NULL) AND L.DATE_MODIFY < :I$DATE_TO
    UNION
    SELECT 'F' || F.OBJ_ID, F.DATE_DEL, F.CJ_ID, F.FINAL_DATE, - F.FINAL_TYPE, FC.VAL, NULL, NULL,
      NULL, F.IS_PUBLISHED
    FROM CJ2_JOURNAL_FINALS F
    JOIN CJ2_JOURNAL J ON J.OBJ_ID = F.CJ_ID AND J.DATE_DEL IS NULL
    LEFT JOIN LISTVAL_TEXT(F.FINAL_TYPE) FC ON 1 = 1
    WHERE (F.DATE_MODIFY >= :I$DATE_FROM OR :I$DATE_FROM IS NULL) AND F.DATE_MODIFY < :I$DATE_TO
    ORDER BY 1
    INTO :SID, :V$DT, :V$GRADE_ID, :V$DATE1, :N, :S1, :S2, :S3, :V$INST, :F
  DO
  BEGIN
    TAG_NAME = 'lessons:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'lessons:r:id';
    VAL = SID;
    SUSPEND;
    TAG_NAME = 'lessons:r:cj_id';
    VAL = V$GRADE_ID;
    SUSPEND;
    IF(V$DT IS NOT NULL) THEN
    BEGIN
      TAG_NAME = 'lessons:r:delete';
      VAL = 1;
      SUSPEND;
    END
    ELSE
    BEGIN
      TAG_NAME = 'lessons:r:date';
      VAL = (SELECT VAL FROM DATE2ISO(:V$DATE1));
      SUSPEND;
      TAG_NAME = 'lessons:r:num';
      VAL = N;
      SUSPEND;
      TAG_NAME = 'lessons:r:flags';
      VAL = F;
      SUSPEND;
      TAG_NAME = 'lessons:r:theme';
      VAL = S1;
      SUSPEND;
      TAG_NAME = 'lessons:r:hometask';
      VAL = S2;
      SUSPEND;
      TAG_NAME = 'lessons:r:extra';
      -- В extra докладываем контроли с типом электронной урок со ссылками
      VAL = COALESCE(S3, '');
      IF(SUBSTRING(SID FROM 1 FOR 1) <> 'F') THEN
      FOR
        SELECT C.EXT_ID, C.HINT_TEXT
        FROM CJ2_CONTROL C
        WHERE C.DATE_DEL IS NULL AND C.LESSON_ID = CAST(:SID AS BIGINT) AND C.CONTROL_TYPE_ID = 8000
        ORDER BY C.CONTROL_ID
        INTO :S1, :S3
      DO
      BEGIN
        -- Находим где начинается адрес
        N = POSITION('https://' IN S3);
        IF(N <= 0) THEN N = POSITION('http://' IN S3);

        IF(N > 0) THEN
        BEGIN
          IF(VAL <> '') THEN VAL = VAL || ', ';
          VAL = VAL || '<a data-ref="' || S1 || '" href="' || SUBSTRING(S3 FROM N) || '">' || SUBSTRING(S3 FROM 1 FOR N - 2) || '</a>';
        END
      END
      SUSPEND;
      TAG_NAME = 'lessons:r:inst_id';
      VAL = V$INST;
      SUSPEND;
    END

    NX = NX + 1;
    IF(NX >= 10000) THEN
    BEGIN
      NX = 0;
      TAG_NAME = NULL;
      VAL = 'DIVIDE';
      SUSPEND;
      TAG_NAME = 'lessons::json&colon;array';
      VAL = 1;
      SUSPEND;
    END
  END

 --WHEN ANY DO EXCEPTION DATA_ERROR 'Ошибка сериализации уроков на id ' || SID;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_LPJ_SERIALIZE_MARKS (
    I$DATE_FROM TIMESTAMP,
    I$DATE_TO TIMESTAMP = current_timestamp)
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
declare variable V$OBJ_ID bigint;
declare variable V$PERSON_ID bigint;
declare variable V$LESSON_ID bigint;
declare variable V$CC_ID bigint;
declare variable V$MT_ID bigint;
declare variable S1 varchar(1000);
declare variable S2 varchar(1000);
declare variable V$DT timestamp;
declare variable V$VM numeric(15,3);
declare variable V$VS float;
declare variable V$CS float;
declare variable NX integer;
begin

  NX = 0;

  -- Отметки
  TAG_NAME = 'marks::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT M.MARK_ID, COALESCE(M.DATE_DEL, C.DATE_DEL), M.STUDENT_ID, C.LESSON_ID, C.CONTROL_TYPE_ID, M.MARK_TYPE_ID, MT.MARK_SHORTNAME,
      M.COMMENTS_TEXT, MT.MARK_COST, MT.MARK_SCALE, C.CONTROL_COST
    FROM CJ2_MARK M
    JOIN CJ2_MARK_TYPE MT ON MT.MARK_TYPE_ID = M.MARK_TYPE_ID
    JOIN CJ2_CONTROL C ON C.CONTROL_ID = M.CONTROL_ID
    WHERE (((M.DATE_MODIFY >= :I$DATE_FROM OR :I$DATE_FROM IS NULL) AND M.DATE_MODIFY < :I$DATE_TO) OR
      ((C.DATE_MODIFY >= :I$DATE_FROM OR :I$DATE_FROM IS NULL) AND C.DATE_MODIFY < :I$DATE_TO))
      AND EXISTS(SELECT FIRST 1 1 FROM LINKS LPG WHERE LPG.OBJ_ID = M.STUDENT_ID AND LPG.PARENT_TYPE_ID IN (9, 46, 187) AND LPG.DATE_DEL IS NULL)
    INTO :V$OBJ_ID, :V$DT, :V$PERSON_ID, :V$LESSON_ID, :V$CC_ID, :V$MT_ID, :S1, :S2, :V$VM, :V$VS, :V$CS
  DO
  BEGIN
    TAG_NAME = 'marks:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'marks:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'marks:r:person_id';
    VAL = V$PERSON_ID;
    SUSPEND;
    TAG_NAME = 'marks:r:lesson_id';
    VAL = V$LESSON_ID;
    SUSPEND;
    IF(V$DT IS NOT NULL) THEN
    BEGIN
      TAG_NAME = 'marks:r:delete';
      VAL = 1;
      SUSPEND;
    END
    ELSE
    BEGIN
      TAG_NAME = 'marks:r:ct_id';
      VAL = V$CC_ID;
      SUSPEND;
      TAG_NAME = 'marks:r:mt_id';
      VAL = V$MT_ID;
      SUSPEND;
      TAG_NAME = 'marks:r:val';
      VAL = S1;
      SUSPEND;
      TAG_NAME = 'marks:r:wval';
      VAL = V$VM;
      SUSPEND;
      TAG_NAME = 'marks:r:ms';
      VAL = V$VS;
      SUSPEND;
      TAG_NAME = 'marks:r:cs';
      VAL = V$CS;
      SUSPEND;
      TAG_NAME = 'marks:r:text';
      VAL = S2;
      SUSPEND;
    END
  END

  -- Итоговые
  FOR
    SELECT M.MARK_ID, COALESCE(M.DATE_DEL, F.DATE_DEL), M.STUDENT_ID, F.OBJ_ID, F.FINAL_TYPE, M.MARK_TYPE_ID, MT.MARK_SHORTNAME,
      M.COMMENTS_TEXT, MT.MARK_COST, MT.MARK_SCALE, 1
    FROM CJ2_MARK M
    JOIN CJ2_MARK_TYPE MT ON MT.MARK_TYPE_ID = M.MARK_TYPE_ID
    JOIN CJ2_JOURNAL_FINALS F ON F.OBJ_ID = M.FINAL_ID
    WHERE (((M.DATE_MODIFY >= :I$DATE_FROM OR :I$DATE_FROM IS NULL) AND M.DATE_MODIFY < :I$DATE_TO) OR
      ((F.DATE_MODIFY >= :I$DATE_FROM OR :I$DATE_FROM IS NULL) AND F.DATE_MODIFY < :I$DATE_TO))
      AND EXISTS(SELECT FIRST 1 1 FROM LINKS LPG WHERE LPG.OBJ_ID = M.STUDENT_ID AND LPG.PARENT_TYPE_ID IN (9, 46, 187) AND LPG.DATE_DEL IS NULL)
    INTO :V$OBJ_ID, :V$DT, :V$PERSON_ID, :V$LESSON_ID, :V$CC_ID, :V$MT_ID, :S1, :S2, :V$VM, :V$VS, :V$CS
  DO
  BEGIN
    TAG_NAME = 'marks:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'marks:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'marks:r:person_id';
    VAL = V$PERSON_ID;
    SUSPEND;
    TAG_NAME = 'marks:r:lesson_id';
    VAL = 'F' || V$LESSON_ID;
    SUSPEND;
    IF(V$DT IS NOT NULL) THEN
    BEGIN
      TAG_NAME = 'marks:r:delete';
      VAL = 1;
      SUSPEND;
    END
    ELSE
    BEGIN
      TAG_NAME = 'marks:r:ct_id';
      VAL = V$CC_ID;
      SUSPEND;
      TAG_NAME = 'marks:r:mt_id';
      VAL = V$MT_ID;
      SUSPEND;
      TAG_NAME = 'marks:r:val';
      VAL = S1;
      SUSPEND;
      TAG_NAME = 'marks:r:wval';
      VAL = V$VM;
      SUSPEND;
      TAG_NAME = 'marks:r:ms';
      VAL = V$VS;
      SUSPEND;
      TAG_NAME = 'marks:r:cs';
      VAL = V$CS;
      SUSPEND;
      TAG_NAME = 'marks:r:text';
      VAL = S2;
      SUSPEND;
    END

    NX = NX + 1;
    IF(NX >= 10000) THEN
    BEGIN
      NX = 0;
      TAG_NAME = NULL;
      VAL = 'DIVIDE';
      SUSPEND;
      TAG_NAME = 'marks::json&colon;array';
      VAL = 1;
      SUSPEND;
    END
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_LPJ_SERIALIZE_MOVES (
    I$DATE_FROM TIMESTAMP,
    I$DATE_TO TIMESTAMP = current_timestamp)
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
declare variable V$OBJ_ID bigint;
declare variable V$PERSON_ID bigint;
declare variable V$GRADE_ID bigint;
declare variable V$DY date;
declare variable V$DM date;
declare variable V$DATE1 date;
declare variable V$DATE2 date;
declare variable V$DT timestamp;
declare variable NX integer;
begin

  NX = 0;

  SELECT FIRST 1 LV.TAG
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$DY;

  V$DM = DATEADD(-1 YEAR TO V$DY);

  -- Реестр движения
  TAG_NAME = 'movements::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT M.OBJ_ID, M.PERSON_ID, M.GROUP_ID, M.DATE_IN, M.DATE_OUT, M.DATE_DEL
    FROM PERSON_MOVEMENTS M
    WHERE (M.DATE_MODIFY >= :I$DATE_FROM OR :I$DATE_FROM IS NULL) AND M.DATE_MODIFY < :I$DATE_TO AND M.DATE_IN >= :V$DM
      AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :V$DY)
      AND EXISTS(SELECT FIRST 1 1 FROM LINKS LPG WHERE LPG.OBJ_ID = M.PERSON_ID AND LPG.PARENT_TYPE_ID IN (9, 46, 187) AND LPG.DATE_DEL IS NULL)
    ORDER BY 1
    INTO :V$OBJ_ID, :V$PERSON_ID, :V$GRADE_ID, :V$DATE1, :V$DATE2, :V$DT
  DO
  BEGIN
    TAG_NAME = 'movements:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'movements:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'movements:r:person_id';
    VAL = V$PERSON_ID;
    SUSPEND;
    TAG_NAME = 'movements:r:group_id';
    VAL = V$GRADE_ID;
    SUSPEND;
    IF(V$DT IS NOT NULL) THEN
    BEGIN
      TAG_NAME = 'movements:r:delete';
      VAL = 1;
      SUSPEND;
    END
    ELSE
    BEGIN
      TAG_NAME = 'movements:r:date_from';
      VAL = (SELECT VAL FROM DATE2ISO(:V$DATE1, 0));
      SUSPEND;
      TAG_NAME = 'movements:r:date_to';
      VAL = (SELECT VAL FROM DATE2ISO(:V$DATE2, 0));
      SUSPEND;
    END

    NX = NX + 1;
    IF(NX >= 10000) THEN
    BEGIN
      NX = 0;
      TAG_NAME = NULL;
      VAL = 'DIVIDE';
      SUSPEND;
      TAG_NAME = 'movements::json&colon;array';
      VAL = 1;
      SUSPEND;
    END
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_LPJ_SERIALIZE_MSG (
    I$DATE_FROM TIMESTAMP,
    I$DATE_TO TIMESTAMP = current_timestamp)
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(4000))
AS
declare variable V$OBJ_ID bigint;
declare variable V$DT timestamp;
declare variable V$USER_ID bigint;
declare variable V$FROM_ADDR varchar(200);
declare variable V$TEXT varchar(4000);
declare variable V$DATE_ADD timestamp;
declare variable V$DATE_MODIFY timestamp;
declare variable V$GROUP_ID bigint;
declare variable V$FLAGS integer;
begin

  -- Смысл утрачен

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_LPJ_SERIALIZE_MSGRCPT (
    I$DATE_FROM TIMESTAMP,
    I$DATE_TO TIMESTAMP = current_timestamp)
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
declare variable V$OBJ_ID bigint;
declare variable V$DT timestamp;
declare variable V$MSG_ID timestamp;
declare variable V$DATE_ADD timestamp;
declare variable V$DATE_MODIFY timestamp;
declare variable V$RECIPIENT_ID bigint;
declare variable V$STATE_ID smallint;
declare variable V$SENT_AT timestamp;
declare variable V$SEEN_AT timestamp;
begin

  -- Смысл утрачен

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_LPJ_SERIALIZE_RATING (
    I$DATE_FROM TIMESTAMP,
    I$DATE_TO TIMESTAMP = current_timestamp)
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
declare variable V$OBJ_ID bigint;
declare variable V$PERSON_ID bigint;
declare variable V$SUBJECT_ID bigint;
declare variable V$DATE date;
declare variable V$VAL float;
declare variable V$INDEX integer;
declare variable V$DT timestamp;
declare variable NX integer;
declare variable V$LV bigint;
declare variable S varchar(1000);
begin

  NX = 0;

  -- Рейтинги
  TAG_NAME = 'rating::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT R.OBJ_ID, R.STUDENT_ID, R.SUBJECT_ID, R.RATE_DATE, R.RATE_VALUE, R.RATE_INDEX, R.DATE_DEL
    FROM CJ2_STUDENT_RATING R
    WHERE (R.DATE_MODIFY >= :I$DATE_FROM OR :I$DATE_FROM IS NULL) AND R.DATE_MODIFY < :I$DATE_TO
      AND EXISTS(SELECT FIRST 1 1 FROM LINKS LPG WHERE LPG.OBJ_ID = R.STUDENT_ID AND LPG.PARENT_TYPE_ID IN (9, 46, 187) AND LPG.DATE_DEL IS NULL)
    ORDER BY 1
    INTO :V$OBJ_ID, :V$PERSON_ID, :V$SUBJECT_ID, :V$DATE, :V$VAL, :V$INDEX, :V$DT
  DO
  BEGIN
    TAG_NAME = 'rating:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'rating:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'rating:r:person_id';
    VAL = V$PERSON_ID;
    SUSPEND;
    IF(V$DT IS NOT NULL) THEN
    BEGIN
      TAG_NAME = 'rating:r:delete';
      VAL = 1;
      SUSPEND;
    END
    ELSE
    BEGIN
      TAG_NAME = 'rating:r:subject_id';
      VAL = V$SUBJECT_ID;
      SUSPEND;
      TAG_NAME = 'rating:r:date';
      VAL = (SELECT VAL FROM DATE2ISO(:V$DATE, 0));
      SUSPEND;
      TAG_NAME = 'rating:r:index';
      VAL = V$INDEX;
      SUSPEND;
      TAG_NAME = 'rating:r:value';
      VAL = V$VAL;
      SUSPEND;
    END

    NX = NX + 1;
    IF(NX >= 10000) THEN
    BEGIN
      NX = 0;
      TAG_NAME = NULL;
      VAL = 'DIVIDE';
      SUSPEND;
      TAG_NAME = 'rating::json&colon;array';
      VAL = 1;
      SUSPEND;
    END
  END

  -- Портфолио
  TAG_NAME = 'pfdata::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT R.PARENT_ID, R.OBJ_ID, R.OBJ_TYPE_ID
    FROM LINKS R
    WHERE R.PARENT_TYPE_ID = 10 AND R.OBJ_TYPE_ID IN (22, 24, 26, 297) AND R.DATE_DEL IS NULL
      AND (R.DATE_MODIFY >= :I$DATE_FROM OR :I$DATE_FROM IS NULL) AND R.DATE_MODIFY < :I$DATE_TO
      AND EXISTS(SELECT FIRST 1 1 FROM LINKS LPG WHERE LPG.OBJ_ID = R.PARENT_ID AND LPG.PARENT_TYPE_ID IN (9, 46, 187) AND LPG.DATE_DEL IS NULL)
    INTO :V$PERSON_ID, :V$OBJ_ID, :V$SUBJECT_ID
  DO
  BEGIN
    TAG_NAME = 'pfdata:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'pfdata:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'pfdata:r:person_id';
    VAL = V$PERSON_ID;
    SUSPEND;
    TAG_NAME = 'pfdata:r:type';
    VAL = V$SUBJECT_ID;
    SUSPEND;
    FOR
      SELECT L.PARAM_ID, L.LISTVAL_ID, L.VAL
      FROM OBJECT_PARAMS_LIST(1, :V$OBJ_ID, 50) L
      INTO :V$SUBJECT_ID, :V$LV, :S
    DO
    BEGIN
      TAG_NAME = 'pfdata:r:p' || V$SUBJECT_ID;
      IF(V$LV IS NULL OR V$LV = 0) THEN VAL = S; ELSE VAL = V$LV;
      SUSPEND;
    END

    NX = NX + 1;
    IF(NX >= 10000) THEN
    BEGIN
      NX = 0;
      TAG_NAME = NULL;
      VAL = 'DIVIDE';
      SUSPEND;
      TAG_NAME = 'pfdata::json&colon;array';
      VAL = 1;
      SUSPEND;
    END
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_LPJ_SERIALIZE_SCHEDULE (
    I$DATE_FROM TIMESTAMP,
    I$DATE_TO TIMESTAMP = current_timestamp)
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
declare variable V$OBJ_ID bigint;
declare variable V$YEAR_ID bigint;
declare variable V$YEAR integer;
declare variable V$GRADE_ID bigint;
declare variable V$SCHEDULE_ID bigint;
declare variable V$TEMPLATE_ID bigint;
declare variable V$ROOM_ID bigint;
declare variable V$LESSON_ID bigint;
declare variable V$CC_ID bigint;
declare variable S1 varchar(1000);
declare variable S2 varchar(1000);
declare variable V$DATE1 date;
declare variable V$DATE2 date;
declare variable V$T1 time;
declare variable V$T2 time;
declare variable V$DT timestamp;
declare variable N integer;
declare variable F integer;
begin

  SELECT FIRST 1 V1236.LISTVAL_ID, LV.COST
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$YEAR_ID, :V$YEAR;

  -- Расписание - отдаем всегда все, но начинку фильтруем по изменениям
  TAG_NAME = 'schedule::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT DISTINCT L3.OBJ_ID
    FROM LINKS L2
    JOIN LINKS L68 ON L68.PARENT_ID = L2.OBJ_ID AND L68.OBJ_TYPE_ID = 68 AND L68.DATE_DEL IS NULL
    JOIN LINKS L3 ON L3.PARENT_ID = L68.OBJ_ID AND L3.OBJ_TYPE_ID = 3 AND L3.DATE_DEL IS NULL
    JOIN VALL V37 ON V37.OBJ_ID = L3.OBJ_ID AND V37.PARAM_ID = 37 AND V37.IS_DEL = 0 AND V37.LISTVAL_ID = :V$YEAR_ID
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :V$SCHEDULE_ID
  DO
  BEGIN
    -- Шаблоны расписания
    FOR
      SELECT L59.OBJ_ID, V3120.VAL, V3121.VAL
      FROM LINKS L59
      JOIN VALL V1341 ON V1341.OBJ_ID = L59.OBJ_ID AND V1341.PARAM_ID = 1341 AND V1341.IS_DEL = 0 AND V1341.LISTVAL_ID = 2
      LEFT JOIN VALD V3120 ON V3120.OBJ_ID = L59.OBJ_ID AND V3120.PARAM_ID = 3120 AND V3120.IS_DEL = 0
      LEFT JOIN VALD V3121 ON V3121.OBJ_ID = L59.OBJ_ID AND V3121.PARAM_ID = 3121 AND V3121.IS_DEL = 0
      WHERE L59.PARENT_ID = :V$SCHEDULE_ID AND L59.OBJ_TYPE_ID = 59 AND L59.DATE_DEL IS NULL
      INTO :V$TEMPLATE_ID, :V$DATE1, :V$DATE2
    DO
    BEGIN
      TAG_NAME = 'schedule:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'schedule:r:id';
      VAL = V$TEMPLATE_ID;
      SUSPEND;
      TAG_NAME = 'schedule:r:master_id';
      VAL = V$SCHEDULE_ID;
      SUSPEND;
      TAG_NAME = 'schedule:r:date_from';
      VAL = (SELECT VAL FROM DATE2ISO(:V$DATE1, 0));
      SUSPEND;
      TAG_NAME = 'schedule:r:date_to';
      VAL = (SELECT VAL FROM DATE2ISO(:V$DATE2, 0));
      SUSPEND;

      TAG_NAME = 'schedule:r:days::json&colon;array';
      VAL = 1;
      SUSPEND;
      FOR
        SELECT V402.LISTVAL_ID - 798
        FROM LINKS L6
        JOIN VALL V402 ON V402.OBJ_ID = L6.OBJ_ID AND V402.PARAM_ID = 402 AND V402.IS_DEL = 0
        WHERE L6.PARENT_ID = :V$TEMPLATE_ID AND L6.OBJ_TYPE_ID = 6 AND L6.DATE_DEL IS NULL
        INTO :N
      DO
      BEGIN
        TAG_NAME = 'schedule:r:days:r';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'schedule:r:days:r:id';
        VAL = N;
        SUSPEND;
      END

      TAG_NAME = 'schedule:r:lessons::json&colon;array';
      VAL = 1;
      SUSPEND;
      FOR
        SELECT V404.VAL, V405.VAL, V406.VAL
        FROM LINKS L60
        JOIN VALI V404 ON V404.OBJ_ID = L60.OBJ_ID AND V404.PARAM_ID = 404 AND V404.IS_DEL = 0
        JOIN VALT V405 ON V405.OBJ_ID = L60.OBJ_ID AND V405.PARAM_ID = 405 AND V405.IS_DEL = 0
        JOIN VALT V406 ON V406.OBJ_ID = L60.OBJ_ID AND V406.PARAM_ID = 406 AND V406.IS_DEL = 0
        WHERE L60.PARENT_ID = :V$TEMPLATE_ID AND L60.OBJ_TYPE_ID = 60 AND L60.DATE_DEL IS NULL
        ORDER BY 1
        INTO :N, :V$T1, :V$T2
      DO
      BEGIN
        TAG_NAME = 'schedule:r:lessons:r';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'schedule:r:lessons:r:id';
        VAL = N;
        SUSPEND;
        TAG_NAME = 'schedule:r:lessons:r:t_from';
        VAL = V$T1;
        SUSPEND;
        TAG_NAME = 'schedule:r:lessons:r:t_to';
        VAL = V$T2;
        SUSPEND;
      END

      TAG_NAME = 'schedule:r:items::json&colon;array';
      VAL = 1;
      SUSPEND;
      FOR
        SELECT SI.OBJ_ID, SI.DATE_DEL, SI.CJ_ID, SI.ROOM_ID, SI.WEEKDAY_NUM, SI.LESSON_NUM
        FROM SCHEDULE_ITEMS SI
        WHERE SI.SCHEDULE_ID = :V$TEMPLATE_ID AND (SI.DATE_MODIFY >= :I$DATE_FROM OR :I$DATE_FROM IS NULL) AND SI.DATE_MODIFY < :I$DATE_TO
        INTO :V$OBJ_ID, :V$DT, :V$GRADE_ID, :V$ROOM_ID, :F, :N
      DO
      BEGIN
        TAG_NAME = 'schedule:r:items:r';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'schedule:r:items:r:id';
        VAL = V$OBJ_ID;
        SUSPEND;
        IF(V$DT IS NOT NULL) THEN
        BEGIN
          TAG_NAME = 'schedule:r:items:r:delete';
          VAL = 1;
          SUSPEND;
        END
        ELSE
        BEGIN
          TAG_NAME = 'schedule:r:items:r:cj_id';
          VAL = V$GRADE_ID;
          SUSPEND;
          TAG_NAME = 'schedule:r:items:r:room_id';
          VAL = V$ROOM_ID;
          SUSPEND;
          TAG_NAME = 'schedule:r:items:r:day';
          VAL = F;
          SUSPEND;
          TAG_NAME = 'schedule:r:items:r:lesson';
          VAL = N;
          SUSPEND;
        END
      END
    END

    -- Лента расписания
    TAG_NAME = 'schedule:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'schedule:r:id';
    VAL = V$SCHEDULE_ID;
    SUSPEND;
    TAG_NAME = 'schedule:r:master_id';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'schedule:r:date_from';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'schedule:r:date_to';
    VAL = NULL;
    SUSPEND;

    TAG_NAME = 'schedule:r:items::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT SI.OBJ_ID, SI.DATE_DEL, SI.CJ_ID, SI.ROOM_ID, SI.WEEKDAY_NUM, SI.LESSON_NUM, SI.PARENT_ID
      FROM SCHEDULE_ITEMS SI
      WHERE SI.SCHEDULE_ID = :V$SCHEDULE_ID AND (SI.DATE_MODIFY >= :I$DATE_FROM OR :I$DATE_FROM IS NULL) AND SI.DATE_MODIFY < :I$DATE_TO
      INTO :V$OBJ_ID, :V$DT, :V$GRADE_ID, :V$ROOM_ID, :F, :N, :V$LESSON_ID
    DO
    BEGIN
      TAG_NAME = 'schedule:r:items:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'schedule:r:items:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      IF(V$DT IS NOT NULL) THEN
      BEGIN
        TAG_NAME = 'schedule:r:items:r:delete';
        VAL = 1;
        SUSPEND;
      END
      ELSE
      BEGIN
        TAG_NAME = 'schedule:r:items:r:cj_id';
        VAL = V$GRADE_ID;
        SUSPEND;
        TAG_NAME = 'schedule:r:items:r:room_id';
        VAL = V$ROOM_ID;
        SUSPEND;
        TAG_NAME = 'schedule:r:items:r:date'; -- MMDD
        S1 = F / 100;
        S2 = MOD(F, 100);
        IF(CHAR_LENGTH(S1) < 2) THEN S1 = '0' || S1;
        IF(CHAR_LENGTH(S2) < 2) THEN S2 = '0' || S2;
        VAL = V$YEAR || '-' || S1 || '-' || S2;
        SUSPEND;
        TAG_NAME = 'schedule:r:items:r:lesson';
        VAL = N;
        SUSPEND;
        TAG_NAME = 'schedule:r:items:r:parent';
        VAL = V$LESSON_ID;
        SUSPEND;
      END
    END

  END

  -- Замещения - выдаем как будто отдельная таблица расписания
  TAG_NAME = 'schedule:r';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'schedule:r:id';
  VAL = '0';
  SUSPEND;
  TAG_NAME = 'schedule:r:master_id';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'schedule:r:items::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT RP.OBJ_ID, RP.DATE_DEL, COALESCE(RP.REPL_CJ_ID, RP.CJ_ID), RP.CJ_ID, NULL, RP.REPL_DATE, RP.LESSON_NUM
    FROM CJ2_REPL_PROCESS RP
    LEFT JOIN CJ2_JOURNAL J ON J.OBJ_ID = COALESCE(RP.REPL_CJ_ID, RP.CJ_ID)
    WHERE (RP.DATE_MODIFY >= :I$DATE_FROM OR :I$DATE_FROM IS NULL) AND RP.DATE_MODIFY < :I$DATE_TO
    INTO :V$OBJ_ID, :V$DT, :V$GRADE_ID, :V$CC_ID, :V$ROOM_ID, :V$DATE1, :N
  DO
    BEGIN
    TAG_NAME = 'schedule:r:items:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'schedule:r:items:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    IF(V$DT IS NOT NULL) THEN
    BEGIN
      TAG_NAME = 'schedule:r:items:r:delete';
      VAL = 1;
      SUSPEND;
    END
    ELSE
    BEGIN
      TAG_NAME = 'schedule:r:items:r:cj_id';
      VAL = V$GRADE_ID;
      SUSPEND;
      TAG_NAME = 'schedule:r:items:r:src_cj_id';
      VAL = V$CC_ID;
      SUSPEND;
      TAG_NAME = 'schedule:r:items:r:room_id';
      VAL = V$ROOM_ID;
      SUSPEND;
      TAG_NAME = 'schedule:r:items:r:date';
      VAL = (SELECT VAL FROM DATE2ISO(:V$DATE1, 0));
      SUSPEND;
      TAG_NAME = 'schedule:r:items:r:lesson';
      VAL = N;
      SUSPEND;
    END
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_MAX_CHATS (
    I$OBJ_ID BIGINT,
    I$TIMEMARK TIMESTAMP)
RETURNS (
    OU_TITLE VARCHAR(1000),
    CLASS_ID BIGINT,
    CLASS_CAPTION VARCHAR(400),
    CLASS_INDEX INTEGER,
    CLASS_DIGIT VARCHAR(100),
    CHAT_ID VARCHAR(40),
    CHAT_TYPE VARCHAR(20),
    CHAT_TITLE VARCHAR(1000),
    SUBJECT_NAME VARCHAR(400),
    CLASS_CODE VARCHAR(80),
    MEMBER_ID VARCHAR(40),
    MEMBER_INT_ID BIGINT,
    IS_ADMIN SMALLINT)
AS
DECLARE VARIABLE V$Y INTEGER;
DECLARE VARIABLE V$YEAR_ID BIGINT;
DECLARE VARIABLE V$PARENTS_CHAT_ID VARCHAR(40);
DECLARE VARIABLE V$CHILD_CHAT_ID VARCHAR(40);
DECLARE VARIABLE V$TEACHER_ID VARCHAR(40);
DECLARE VARIABLE V$TEACHER_INT_ID BIGINT;
DECLARE VARIABLE V$GRADE_ID BIGINT;
DECLARE VARIABLE T INTEGER;
begin

  IF(I$OBJ_ID IS NULL) THEN
  SELECT FIRST 1 L2.OBJ_ID
  FROM LINKS L2
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :I$OBJ_ID;

  SELECT FIRST 1 LV.COST, V1236.LISTVAL_ID
  FROM VALL V1236
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE V1236.OBJ_ID = :I$OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  INTO :V$Y, :V$YEAR_ID;

  SELECT FIRST 1 V2.VAL
  FROM VALS V2
  WHERE V2.OBJ_ID = :I$OBJ_ID AND V2.PARAM_ID = 2 AND V2.IS_DEL = 0
  INTO :OU_TITLE;

  -- Для СПО берем наименование из другого параметра
  IF(SUBSTRING(OU_TITLE FROM 1 FOR 2) = '19') THEN
  SELECT FIRST 1 V999.VAL
  FROM VALS V999
  WHERE V999.OBJ_ID = :I$OBJ_ID AND V999.PARAM_ID = 999 AND V999.IS_DEL = 0
  INTO :OU_TITLE;

  IF(OU_TITLE IS NULL) THEN EXCEPTION DATA_ERROR 'Не внесено наименование ОУ';

  -- Все чаты хранятся в формате id;ссылка
  -- Сначала идет запись с MEMBER_ID = NULL - это сам чат, затем записи актуальных участников

  -- Сотрудники
  CHAT_TYPE = 'teacher';
  CLASS_CAPTION = 'Учительская';
  CHAT_TITLE = CLASS_CAPTION || ' · ' || OU_TITLE;
  SELECT FIRST 1 V3357.VAL
  FROM VALS V3357
  WHERE V3357.OBJ_ID = :I$OBJ_ID AND V3357.PARAM_ID = 3357 AND V3357.IS_DEL = 0
  INTO :CHAT_ID;
  SUSPEND;

  FOR
    SELECT L14.OBJ_ID, V3355.SVAL
    FROM LINKS L14
    JOIN VALS V3355 ON V3355.OBJ_ID = L14.OBJ_ID AND V3355.PARAM_ID = 3355 AND V3355.IS_DEL = 0
    WHERE L14.PARENT_ID = :I$OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
    -- Подразделения
    UNION
    SELECT L14.OBJ_ID, V3355.SVAL
    FROM LINKS L211
    JOIN LINKS L14 ON L14.PARENT_ID = L211.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
    JOIN VALS V3355 ON V3355.OBJ_ID = L14.OBJ_ID AND V3355.PARAM_ID = 3355 AND V3355.IS_DEL = 0
    WHERE L211.PARENT_ID = :I$OBJ_ID AND L211.OBJ_TYPE_ID = 211 AND L211.DATE_DEL IS NULL
    INTO :MEMBER_INT_ID, :MEMBER_ID
  DO
  BEGIN
    -- Админ
    IS_ADMIN = 0;
    -- ? ИО директора
    SELECT FIRST 1 1
    FROM VALL V3343
    WHERE V3343.OBJ_ID = :MEMBER_INT_ID AND V3343.PARAM_ID = 3343 AND V3343.IS_DEL = 0 AND V3343.LISTVAL_ID = 2
    INTO :IS_ADMIN;

    -- Должность = директор
    IF(IS_ADMIN = 0) THEN
    SELECT FIRST 1 1
    FROM LINKS L15
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
    -- подгруппа = руководители 1 уровня
    JOIN VALL V1399 ON V1399.OBJ_ID = L15.OBJ_ID AND V1399.PARAM_ID = 1399 AND V1399.IS_DEL = 0 AND V1399.LISTVAL_ID = 56
    WHERE L15.PARENT_ID = :MEMBER_INT_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL AND V74.VAL IS NULL
    INTO :IS_ADMIN;

    -- Роль = админ, директор, специалист по кадрам
    IF(IS_ADMIN = 0) THEN
    SELECT FIRST 1 1
    FROM USERS U
    WHERE U.DATE_DEL IS NULL AND U.OBJ_ID = :MEMBER_INT_ID AND U.USER_TYPE IN (1, 5, 10)
    INTO :IS_ADMIN;

    SUSPEND;
  END

  -- Классные чаты
  FOR
    SELECT L9.OBJ_ID, C.CAPTION, LV.COST, V54.SVAL, V3359.SVAL, V3336.SVAL, V3355.SVAL, V53.VAL
    FROM LINKS L7
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
    -- Только школьный уровень
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V49.LISTVAL_ID AND LV.PARENT_ID IN (2141, 12941)
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
    LEFT JOIN VALS V54 ON V54.OBJ_ID = L9.OBJ_ID AND V54.PARAM_ID = 54 AND V54.IS_DEL = 0
    LEFT JOIN VALS V3359 ON V3359.OBJ_ID = L9.OBJ_ID AND V3359.PARAM_ID = 3359 AND V3359.IS_DEL = 0
    LEFT JOIN VALS V3336 ON V3336.OBJ_ID = L9.OBJ_ID AND V3336.PARAM_ID = 3336 AND V3336.IS_DEL = 0
    LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C ON 1 = 1
    LEFT JOIN VALR V53 ON V53.OBJ_ID = L9.OBJ_ID AND V53.PARAM_ID = 53 AND V53.IS_DEL = 0
    LEFT JOIN VALS V3355 ON V3355.OBJ_ID = V53.VAL AND V3355.PARAM_ID = 3355 AND V3355.IS_DEL = 0
    WHERE L7.PARENT_ID = :I$OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    ORDER BY 1
    INTO :CLASS_ID, :CLASS_CAPTION, :CLASS_INDEX, :CLASS_DIGIT, :V$PARENTS_CHAT_ID, :V$CHILD_CHAT_ID, :V$TEACHER_ID, :V$TEACHER_INT_ID
  DO
  BEGIN
    CLASS_CODE = CLASS_ID || 'Y' || V$Y;

    -- Если чата еще нет - не создавать, пока нет id классного руководителя
    IF(V$PARENTS_CHAT_ID IS NOT NULL OR V$TEACHER_ID IS NOT NULL) THEN
    BEGIN
      MEMBER_ID = NULL;
      MEMBER_INT_ID = NULL;
      IS_ADMIN = NULL;
      CHAT_ID = V$PARENTS_CHAT_ID;
      CHAT_TYPE = 'parent';
      CHAT_TITLE = CLASS_CAPTION || ' · Родители ·' || OU_TITLE;
      SUSPEND;

      MEMBER_INT_ID = V$TEACHER_INT_ID;
      MEMBER_ID = V$TEACHER_ID;
      IS_ADMIN = 1;
      IF(MEMBER_ID IS NOT NULL) THEN SUSPEND;

      -- Все родители, кроме учителя-родителя
      IS_ADMIN = 0;
      FOR
        SELECT DISTINCT L20.OBJ_ID, V3356.SVAL
        FROM LINKS L10
        JOIN LINKS L20 ON L20.PARENT_ID = L10.OBJ_ID AND L20.OBJ_TYPE_ID = 20 AND L20.DATE_DEL IS NULL
        JOIN VALS V3356 ON V3356.OBJ_ID = L20.OBJ_ID AND V3356.PARAM_ID = 3356 AND V3356.IS_DEL = 0 AND V3356.SVAL <> :V$TEACHER_ID
        WHERE L10.PARENT_ID = :CLASS_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        ORDER BY 1
        INTO :MEMBER_INT_ID, :MEMBER_ID
      DO
      BEGIN
        SUSPEND;
      END
    END

    IF(V$CHILD_CHAT_ID IS NOT NULL OR V$TEACHER_ID IS NOT NULL) THEN
    BEGIN
      MEMBER_ID = NULL;
      MEMBER_INT_ID = NULL;
      IS_ADMIN = NULL;
      CHAT_ID = V$CHILD_CHAT_ID;
      CHAT_TYPE = 'grade';
      CHAT_TITLE = CLASS_CAPTION || ' · ' || OU_TITLE;
      SUSPEND;

      MEMBER_INT_ID = V$TEACHER_INT_ID;
      MEMBER_ID = V$TEACHER_ID;
      IS_ADMIN = 1;
      IF(MEMBER_ID IS NOT NULL) THEN SUSPEND;

      IS_ADMIN = 0;
      FOR
        SELECT L10.OBJ_ID, V3354.SVAL
        FROM LINKS L10
        JOIN VALS V3354 ON V3354.OBJ_ID = L10.OBJ_ID AND V3354.PARAM_ID = 3354 AND V3354.IS_DEL = 0
        WHERE L10.PARENT_ID = :CLASS_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        ORDER BY 1
        INTO :MEMBER_INT_ID, :MEMBER_ID
      DO
      BEGIN
        SUSPEND;
      END
    END
  END

  -- Предметные чаты текущего учебного года
  CHAT_TYPE = 'grade_subject';
  CLASS_DIGIT = NULL;
  FOR
    SELECT J.OBJ_ID, J.CHAT_ID, V3355.SVAL, J.TEACHER_ID, J.GRADE_ID, V376.SVAL, LV.COST, J.JOURNAL_NAME
    FROM CJ2_JOURNAL J
    JOIN LISTVALS LV ON LV.LISTVAL_ID = J.STAGE_INDEX
    LEFT JOIN VALS V3355 ON V3355.OBJ_ID = J.TEACHER_ID AND V3355.PARAM_ID = 3355 AND V3355.IS_DEL = 0
    JOIN VALS V376 ON V376.OBJ_ID = J.SUBJECT_ID AND V376.PARAM_ID = 376 AND V376.IS_DEL = 0
    WHERE J.DATE_DEL IS NULL AND J.JOURNAL_TYPE = 0 AND J.IS_ENABLED = 1 AND J.VK_ENABLED = 1 AND J.TEACHER_ID IS NOT NULL AND J.YEAR_ID = :V$YEAR_ID
    ORDER BY 1
    INTO :CLASS_ID, :CHAT_ID, :V$TEACHER_ID, :V$TEACHER_INT_ID, :V$GRADE_ID, :SUBJECT_NAME, :CLASS_INDEX, :CLASS_CAPTION
  DO
  BEGIN
    CHAT_TITLE = CLASS_CAPTION || ' · ' || SUBJECT_NAME || ' · ' || OU_TITLE;

    -- Код класса формируем по большинству участников. Если участников нет, то группу вовсе не выдаем
    CLASS_CODE = NULL;
    SELECT FIRST 1 LP9.PARENT_ID, COUNT(*)
    FROM LINKS L10
    JOIN LINKS LP9 ON LP9.OBJ_ID = L10.OBJ_ID AND LP9.PARENT_TYPE_ID = 9 AND LP9.DATE_DEL IS NULL
    WHERE L10.PARENT_ID = :V$GRADE_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    GROUP BY 1
    ORDER BY 2 DESC
    INTO :CLASS_CODE, :T;

    -- Если чата еще нет - не создавать, пока нет id классного руководителя
    IF(CLASS_CODE IS NOT NULL AND (CHAT_ID IS NOT NULL OR V$TEACHER_ID IS NOT NULL)) THEN
    BEGIN
      CLASS_CODE = CLASS_CODE || 'Y' || V$Y;
      MEMBER_ID = NULL;
      MEMBER_INT_ID = NULL;
      IS_ADMIN = NULL;
      SUSPEND;

      MEMBER_INT_ID = V$TEACHER_INT_ID;
      MEMBER_ID = V$TEACHER_ID;
      IS_ADMIN = 1;
      IF(MEMBER_ID IS NOT NULL) THEN SUSPEND;

      IS_ADMIN = 0;
      FOR
        SELECT L10.OBJ_ID, V3354.SVAL
        FROM LINKS L10
        JOIN VALS V3354 ON V3354.OBJ_ID = L10.OBJ_ID AND V3354.PARAM_ID = 3354 AND V3354.IS_DEL = 0
        WHERE L10.PARENT_ID = :V$GRADE_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        ORDER BY 1
        INTO :MEMBER_INT_ID, :MEMBER_ID
      DO
      BEGIN
        SUSPEND;
      END
    END
  END

  -- В конце выдаем пустую запись, чтобы обработать удаление участников последней группы
  CHAT_TYPE = 'end';
  CLASS_CAPTION = NULL;
  CLASS_INDEX = NULL;
  CLASS_DIGIT = NULL;
  CHAT_ID = NULL;
  CLASS_ID = NULL;
  MEMBER_ID = NULL;
  MEMBER_INT_ID = NULL;
  IS_ADMIN = NULL;
  IS_ADMIN = NULL;
  SUSPEND;

  -- Удаление неактуальных чатов

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_MOVEMENT_DELETE (
    I$OBJ_ID BIGINT,
    I$SIDE SMALLINT,
    I$USER_ID VARCHAR(40))
AS
declare variable V$YEAR integer;
declare variable V$PERSON_ID bigint;
declare variable V$DATE_IN date;
declare variable V$DATE_OUT date;
declare variable V$DATE date;
declare variable V$GROUP_ID bigint;
declare variable V$REASON_ID bigint;
declare variable V$TYPE varchar(400);
declare variable TMP bigint;
begin

  -- 0 = отмена зачисления, 1 = отмена выбытия, 2 = отмена движения в старом формате

  -- Менять движения можно только в пределах текущего учебного года
  SELECT FIRST 1 LV.COST, LV.TAG
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$YEAR, :V$DATE;

  IF(V$YEAR IS NULL) THEN EXCEPTION DATA_ERROR 'Не задан текущий учебный год';

  SELECT FIRST 1 M.PERSON_ID, M.DATE_IN, M.DATE_OUT, M.GROUP_ID
  FROM PERSON_MOVEMENTS M
  WHERE M.DATE_DEL IS NULL AND M.OBJ_ID = :I$OBJ_ID
  INTO :V$PERSON_ID, :V$DATE_IN, :V$DATE_OUT, :V$GROUP_ID;

  IF((V$DATE_OUT IS NOT NULL AND V$DATE_OUT < V$DATE) OR (V$DATE_OUT IS NULL AND V$DATE_IN < V$DATE)) THEN EXCEPTION DATA_ERROR 'Нельзя отменить архивную запись движения';

  IF(EXISTS(
    SELECT FIRST 1 1
    FROM PERSON_MOVEMENTS M
    JOIN OBJECTS O ON O.OBJ_ID = M.GROUP_ID AND O.TYPE_ID IN (9, 187, 243, 289)
    WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :V$PERSON_ID AND M.OBJ_ID > :I$OBJ_ID
  ))
  THEN EXCEPTION DATA_ERROR 'Запись движения не является последней, отмена невозможна';

  IF(V$PERSON_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Запись движения не найдена';

  SELECT X FROM PARAGRAF_PUPIL_REVERT(:V$PERSON_ID, :I$OBJ_ID) INTO :TMP;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_MOVEMENT_REACCEPT (
    I$STUDENT_ID BIGINT,
    I$GROUP_ID BIGINT,
    I$ACTION_DATE DATE,
    I$ACTION_TYPE BIGINT,
    I$ORDER_NUMBER VARCHAR(100),
    I$ORDER_DATE DATE,
    I$GUP_ID BIGINT,
    I$USER_ID BIGINT)
AS
DECLARE VARIABLE V$OUT_ID BIGINT;
DECLARE VARIABLE V$CLASS_TYPE BIGINT;
DECLARE VARIABLE TMP BIGINT;
DECLARE VARIABLE V$REGID VARCHAR(100);
DECLARE VARIABLE V$LDT TIMESTAMP;
DECLARE VARIABLE V$LASTDATE DATE;
begin

  -- Проверем, что ученик таки в выбывших или окончивших
  SELECT FIRST 1 LPX.PARENT_ID, LPX.DATE_INS
  FROM LINKS LPX
  WHERE LPX.OBJ_ID = :I$STUDENT_ID AND LPX.PARENT_TYPE_ID IN (81, 82, 83) AND LPX.DATE_DEL IS NULL
  INTO :V$OUT_ID, :V$LDT;

  IF(V$OUT_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Обучающийся не числится среди выбывших/окончивших';

  SELECT FIRST 1 LG.OBJ_TYPE_ID
  FROM LINKS LG
  WHERE LG.OBJ_ID = :I$GROUP_ID AND LG.PARENT_TYPE_ID IN (8, 77) AND LG.DATE_DEL IS NULL
  INTO :V$CLASS_TYPE;

  IF(V$CLASS_TYPE IS NULL) THEN EXCEPTION DATA_ERROR 'Указанный учебный коллектив не найден';

  -- Нельзя зачислять, пока числится в классе ГИА (второгодник)
  IF(EXISTS(
    SELECT FIRST 1 1
    FROM LINKS LP125
    WHERE LP125.OBJ_ID = :I$STUDENT_ID AND LP125.PARENT_TYPE_ID = 125 AND LP125.DATE_DEL IS NULL
  ))
  THEN EXCEPTION DATA_ERROR 'Нельзя зачислить обучающегося, пока он включен в класс для сдачи ГИА';

  -- Нельзя зачислять, если уже числится в экстернате
  -- разрешаем только в предварительный прием
  IF(V$CLASS_TYPE <> 290 AND EXISTS(
    SELECT FIRST 1 1
    FROM LINKS LP187
    WHERE LP187.OBJ_ID = :I$STUDENT_ID AND LP187.PARENT_TYPE_ID = 187 AND LP187.DATE_DEL IS NULL
  ))
  THEN EXCEPTION DATA_ERROR 'Обучающийся уже числится в классе-экстернате';

  -- Проверяем, что запись зачисления позднее, чем последняя запись выбытия (если она есть)
  SELECT FIRST 1 M.DATE_OUT
  FROM PERSON_MOVEMENTS M
  WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :I$STUDENT_ID AND M.DATE_OUT IS NOT NULL AND M.GROUP_TYPE_ID IN (9, 125, 187)
  ORDER BY 1 DESC
  INTO :V$LASTDATE;

  IF(V$LASTDATE > I$ACTION_DATE) THEN EXCEPTION DATA_ERROR 'Нельзя зачислить в новый учебный коллектив с датой раньше, чем дата последнего выбытия - ' || (SELECT RESULT FROM DATE2STR(:V$LASTDATE));

  -- В предварительный прием реестр движения не корректируется
  -- а дата движения и тип движения вообще не заполняются
  IF(V$CLASS_TYPE = 290) THEN
  BEGIN
    IF(I$GUP_ID IS NOT NULL) THEN EXCEPTION DATA_ERROR 'Нельзя указывать ГУП при возврате в предварительный прием';

    IF(EXISTS(
      SELECT FIRST 1 1
      FROM LINKS LP
      WHERE LP.OBJ_ID = :I$STUDENT_ID AND LP.PARENT_TYPE_ID IN (9, 125, 187, 290) AND LP.DATE_DEL IS NULL
    ))
    THEN
      EXCEPTION DATA_ERROR 'Нельзя принимать ученика в с предварительный прием, когда он уже числится в учебном коллективе или уже был принят в предварительный прием';

    SELECT 1 FROM OBJECT_ADD_LINK(:I$GROUP_ID, :I$STUDENT_ID, 10) INTO :TMP;
  END
  ELSE
  BEGIN
    IF(I$ACTION_TYPE IS NULL) THEN EXCEPTION DATA_ERROR 'Не указана причина перевода';
    IF(I$ACTION_DATE IS NULL) THEN EXCEPTION DATA_ERROR 'Не указана дата зачисления';
    IF(EXISTS(
      SELECT FIRST 1 1
      FROM LINKS LP
      WHERE LP.OBJ_ID = :I$STUDENT_ID AND LP.PARENT_TYPE_ID = 290 AND LP.DATE_DEL IS NULL
    ))
    THEN
      EXCEPTION DATA_ERROR 'Нельзя принимать ученика в учебный коллектив одновременно с предварительным приемом';

    SELECT OBJ_ID FROM VARGRP_MOVE_PUPIL(:I$STUDENT_ID, :I$GROUP_ID, :I$ORDER_NUMBER, :I$ORDER_DATE, :I$ACTION_DATE, 0,
      COALESCE(:I$USER_ID, 'Веб-администратор'), NULL, :I$ACTION_TYPE)
    INTO :TMP;
  END

  -- При возврате в настоящий класс затираем данные по выбытию (дата регистрации заявления)
  IF(V$CLASS_TYPE IN (9, 290)) THEN
  BEGIN
    SELECT BLOB_ID FROM VAL_ADD(3000, :I$STUDENT_ID, '') INTO :TMP;
  END

  -- Очищаем РегИД, предыдущее значение сохраняем в другом поле. Требуется обязательно перевыдать РегИД
  -- если дата выбытия была более чем 3 дня от текущей даты
  IF(V$LDT < DATEADD(-3 DAY TO CURRENT_DATE)) THEN
  BEGIN
    SELECT FIRST 1 V.VAL
    FROM VALS V
    WHERE V.OBJ_ID = :I$STUDENT_ID AND V.PARAM_ID = 2912 AND V.IS_DEL = 0
    INTO :V$REGID;

    IF(V$REGID IS NOT NULL) THEN
    SELECT 1 FROM VAL_ADD(3326, :I$STUDENT_ID, :V$REGID) INTO :TMP;

    SELECT 1 FROM VAL_ADD(2912, :I$STUDENT_ID, NULL, NULL, 1) INTO :TMP;
  END

  IF(I$GUP_ID IS NOT NULL) THEN
  SELECT OBJ_ID FROM VARGRP_MOVE_PUPIL(:I$STUDENT_ID, :I$GUP_ID, :I$ORDER_NUMBER, :I$ORDER_DATE, :I$ACTION_DATE, 0,
    COALESCE(:I$USER_ID, 'Веб-администратор'), NULL, :I$ACTION_TYPE)
  INTO :TMP;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_MOVEMENT_SET (
    I$MOVE_ID BIGINT,
    I$FIELD_NAME VARCHAR(100),
    I$VAL DATE,
    I$VAL2 VARCHAR(100),
    I$USER_ID VARCHAR(40))
AS
declare variable V$USERTYPE integer;
declare variable V$PERSON_ID bigint;
declare variable V$DATE_IN date;
declare variable V$DATE_OUT date;
declare variable V$GROUP_ID bigint;
declare variable V$GROUP_TYPE_ID bigint;
declare variable V$ORDER_ID_IN bigint;
declare variable V$ORDER_ID_OUT bigint;
declare variable V$SEC_GROUP_ID bigint;
declare variable V$SEC_DATE date;
declare variable V$YEAR integer;
declare variable V$CC integer;
begin

  -- Запись движения может редактировать только админ, директор или завуч
  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  SELECT U.USER_TYPE
  FROM USERS U
  WHERE U.USER_ID = :I$USER_ID
  INTO :V$USERTYPE;

  IF(V$USERTYPE NOT IN (1, 5, 6)) THEN EXCEPTION DATA_ERROR 'Только руководители и завучи могут менять данные движения';

  IF(NOT EXISTS(
    SELECT FIRST 1 1
    FROM KEYS
    WHERE KEY_CODE = 'LEVEL' AND KEY_VAL = '1'
  ))
  THEN EXCEPTION DATA_ERROR 'Редактирование движения возможно только на уровне организации';

  SELECT FIRST 1 LV.COST
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$YEAR;

  SELECT M.PERSON_ID, M.DATE_IN, M.DATE_OUT, M.GROUP_ID, G.TYPE_ID, M.ORDER_ID_IN, M.ORDER_ID_OUT
  FROM PERSON_MOVEMENTS M
  JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID
  WHERE M.OBJ_ID = :I$MOVE_ID AND M.DATE_DEL IS NULL
  INTO :V$PERSON_ID, :V$DATE_IN, :V$DATE_OUT, :V$GROUP_ID, :V$GROUP_TYPE_ID, :V$ORDER_ID_IN, :V$ORDER_ID_OUT;

  IF(V$DATE_IN IS NULL) THEN EXCEPTION DATA_ERROR 'Запись движения не найдена или была удалена';
  IF(I$VAL IS NULL AND I$FIELD_NAME IN ('date_in', 'date_out')) THEN EXCEPTION DATA_ERROR 'Нельзя обнулять дату зачисления или отчисления';

  IF(I$FIELD_NAME = 'date_in') THEN
  BEGIN
    IF(I$VAL IS NULL) THEN EXCEPTION DATA_ERROR 'Нельзя обнулять дату зачисления';
    V$CC = EXTRACT(YEAR FROM V$DATE_IN);
    IF(EXTRACT(MONTH FROM V$DATE_IN) < 9) THEN V$CC = V$CC - 1;
    IF(I$VAL < '01.09.' || V$CC) THEN EXCEPTION DATA_ERROR 'Дату зачисления можно менять только в пределах учебного года';
    IF(I$VAL > '31.08.' || (EXTRACT(YEAR FROM V$DATE_IN) + 1)) THEN EXCEPTION DATA_ERROR 'Дату зачисления можно менять только в пределах учебного года';
    IF(I$VAL < '01.09.' || V$YEAR) THEN EXCEPTION DATA_ERROR 'Дату зачисления можно менять только в пределах учебного года';
    IF(V$DATE_OUT IS NOT NULL AND I$VAL >= V$DATE_OUT) THEN EXCEPTION DATA_ERROR 'Дату зачисления должна быть не позднее даты отчисления';

    -- Проверяем, что у нас не произошло нарушение хронологии в подчиненных группах
    --
    V$SEC_GROUP_ID = NULL;
    SELECT FIRST 1 M.GROUP_ID, M.DATE_IN
    FROM PERSON_MOVEMENTS M
    JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID NOT IN (9, 125, 187)
    WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :V$PERSON_ID AND :V$GROUP_TYPE_ID IN (9, 125, 187) AND M.DATE_IN >= :V$DATE_IN AND (M.DATE_OUT IS NULL OR M.DATE_OUT > :V$DATE_IN)
      AND M.DATE_IN < :I$VAL
    INTO :V$SEC_GROUP_ID, :V$SEC_DATE;

    IF(V$SEC_GROUP_ID IS NOT NULL) THEN EXCEPTION DATA_ERROR 'Нарушение хронологии движений в группе ' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$SEC_GROUP_ID));

    IF(V$ORDER_ID_IN IS NOT NULL) THEN
    BEGIN
      -- Исправляем даты зачисления для всех учащихся в приказе
      UPDATE PERSON_MOVEMENTS
      SET DATE_IN = :I$VAL
      WHERE DATE_DEL IS NULL AND ORDER_ID_IN = :V$ORDER_ID_IN;

      UPDATE PERSON_MOVEMENTS
      SET DATE_OUT = :I$VAL
      WHERE DATE_DEL IS NULL AND ORDER_ID_OUT = :V$ORDER_ID_IN;

      UPDATE ORDERS
      SET ACTION_DATE = :I$VAL
      WHERE OBJ_ID = :V$ORDER_ID_IN;
    END
    ELSE
    BEGIN
      UPDATE PERSON_MOVEMENTS
      SET DATE_IN = :I$VAL
      WHERE OBJ_ID = :I$MOVE_ID;
    END
  END
  ELSE IF(I$FIELD_NAME = 'date_out') THEN
  BEGIN
    IF((I$VAL IS NULL AND V$DATE_OUT IS NOT NULL) OR (I$VAL IS NOT NULL AND V$DATE_OUT IS NULL)) THEN EXCEPTION DATA_ERROR 'Нельзя задавать дату отчисления для действующих учеников, или отменять ее для отчисленных';
    V$CC = EXTRACT(YEAR FROM V$DATE_IN);
    IF(EXTRACT(MONTH FROM V$DATE_IN) < 9) THEN V$CC = V$CC - 1;
    IF(I$VAL < '01.09.' || V$CC) THEN EXCEPTION DATA_ERROR 'Дату отчисления можно менять только в пределах учебного года';
    IF(I$VAL > '31.08.' || (EXTRACT(YEAR FROM V$DATE_OUT) + 1)) THEN EXCEPTION DATA_ERROR 'Дату отчисления можно менять только в пределах учебного года';
    IF(I$VAL < '01.09.' || V$YEAR) THEN EXCEPTION DATA_ERROR 'Дату отчисления можно менять только в пределах учебного года';
    IF(I$VAL <= V$DATE_IN) THEN EXCEPTION DATA_ERROR 'Дату отчисления должна быть не ранее даты зачисления';

    IF(V$ORDER_ID_OUT IS NOT NULL) THEN
    BEGIN
      -- Исправляем даты зачисления для всех учащихся в приказе
      UPDATE PERSON_MOVEMENTS
      SET DATE_IN = :I$VAL
      WHERE DATE_DEL IS NULL AND ORDER_ID_IN = :V$ORDER_ID_OUT;

      UPDATE PERSON_MOVEMENTS
      SET DATE_OUT = :I$VAL
      WHERE DATE_DEL IS NULL AND ORDER_ID_OUT = :V$ORDER_ID_OUT;

      UPDATE ORDERS
      SET ACTION_DATE = :I$VAL
      WHERE OBJ_ID = :V$ORDER_ID_OUT;
    END
    ELSE
    BEGIN
      UPDATE PERSON_MOVEMENTS
      SET DATE_OUT = :I$VAL
      WHERE OBJ_ID = :I$MOVE_ID;
    END
  END
  ELSE IF(I$FIELD_NAME = 'order_in') THEN
  BEGIN
    IF(I$VAL IS NULL AND V$ORDER_ID_IN IS NOT NULL) THEN EXCEPTION DATA_ERROR 'Нельзя обнулять приказ для зарегистрированных приказов';

    IF(V$ORDER_ID_IN IS NOT NULL) THEN
    BEGIN
      UPDATE PERSON_MOVEMENTS
      SET ORDER_DATE_IN = :I$VAL, ORDER_NUM_IN = :I$VAL2
      WHERE DATE_DEL IS NULL AND ORDER_ID_IN = :V$ORDER_ID_IN;

      UPDATE PERSON_MOVEMENTS
      SET ORDER_DATE_OUT = :I$VAL, ORDER_NUM_OUT = :I$VAL2
      WHERE DATE_DEL IS NULL AND ORDER_ID_OUT = :V$ORDER_ID_IN;

      UPDATE ORDERS
      SET ORDER_DATE = :I$VAL, ORDER_NUM = :I$VAL2
      WHERE OBJ_ID = :V$ORDER_ID_IN;
    END
    ELSE
    BEGIN
      UPDATE PERSON_MOVEMENTS
      SET ORDER_DATE_IN = :I$VAL, ORDER_NUM_IN = :I$VAL2
      WHERE OBJ_ID = :I$MOVE_ID;
    END
  END
  ELSE IF(I$FIELD_NAME = 'order_out') THEN
  BEGIN
    IF(V$DATE_OUT IS NULL) THEN EXCEPTION DATA_ERROR 'Нельзя заполнять реквизиты приказа об отчислении для действующих обучающихся';
    IF(I$VAL IS NULL AND V$ORDER_ID_OUT IS NOT NULL) THEN EXCEPTION DATA_ERROR 'Нельзя обнулять приказ для зарегистрированных приказов';

    IF(V$ORDER_ID_OUT IS NOT NULL) THEN
    BEGIN
      UPDATE PERSON_MOVEMENTS
      SET ORDER_DATE_OUT = :I$VAL, ORDER_NUM_OUT = :I$VAL2
      WHERE DATE_DEL IS NULL AND ORDER_ID_OUT = :V$ORDER_ID_OUT;

      UPDATE PERSON_MOVEMENTS
      SET ORDER_DATE_IN = :I$VAL, ORDER_NUM_IN = :I$VAL2
      WHERE DATE_DEL IS NULL AND ORDER_ID_IN = :V$ORDER_ID_OUT;

      UPDATE ORDERS
      SET ORDER_DATE = :I$VAL, ORDER_NUM = :I$VAL2
      WHERE OBJ_ID = :V$ORDER_ID_OUT;
    END
    ELSE
    BEGIN
      UPDATE PERSON_MOVEMENTS
      SET ORDER_DATE_OUT = :I$VAL, ORDER_NUM_OUT = :I$VAL2
      WHERE OBJ_ID = :I$MOVE_ID;
    END
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_MS_ADAPTATION (
    I$DT1 TIMESTAMP,
    I$DT2 TIMESTAMP NOT NULL = current_timestamp)
RETURNS (
    ID VARCHAR(60),
    SCHOOL_ID VARCHAR(60),
    CODE INTEGER,
    NAME VARCHAR(1000),
    CREATE_DATETIME TIMESTAMP,
    SEND_DATETIME TIMESTAMP)
AS
declare variable V$SCHOOL_ID bigint;
declare variable V$GP_ID bigint;
declare variable V$Y integer;
declare variable V$DT1 timestamp;
declare variable V$DT2 timestamp;
declare variable V$DT3 timestamp;
declare variable V$TYPE_ID bigint;
begin

  SEND_DATETIME = I$DT2;

  SELECT FIRST 1 L2.OBJ_ID, V1236.LISTVAL_ID, LV.COST, V9.VAL
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  JOIN VALS V9 ON V9.OBJ_ID = L2.OBJ_ID AND V9.PARAM_ID = 9 AND V9.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$SCHOOL_ID, :V$GP_ID, :V$Y, :SCHOOL_ID;

  FOR
    SELECT L57.OBJ_ID, V2379.LISTVAL_ID, C.CAPTION, MAXVALUE(L57.DATE_MODIFY, V2379.DATE_MODIFY)
    FROM LINKS L69
    JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
    JOIN VALL V2379 ON V2379.OBJ_ID = L57.OBJ_ID AND V2379.PARAM_ID = 2379 AND V2379.IS_DEL = 0 AND V2379.LISTVAL_ID <> 11187
    LEFT JOIN OBJECT_CAPTION_GET(L57.OBJ_ID) C ON 1 = 1
    WHERE L69.PARENT_ID = :V$SCHOOL_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL
    AND EXISTS (
      -- Действующий, не внеурочный
      SELECT FIRST 1 1
      FROM LINKS L400
      JOIN VALL V3013 ON V3013.OBJ_ID = L400.OBJ_ID AND V3013.PARAM_ID = 3013 AND V3013.IS_DEL = 0 AND V3013.LISTVAL_ID = 11715
      JOIN VALL V3022 ON V3022.OBJ_ID = L400.OBJ_ID AND V3022.PARAM_ID = 3022 AND V3022.IS_DEL = 0 AND V3022.LISTVAL_ID = 3
      WHERE L400.PARENT_ID = L57.OBJ_ID AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL
    )
    INTO :ID, :V$TYPE_ID, :NAME, :V$DT1
  DO
  BEGIN
    CREATE_DATETIME = V$DT1;

    CODE = NULL;
    IF(V$TYPE_ID = 11189) THEN
    BEGIN
      CODE = 24; -- слабовидящие
      NAME = 'Адаптированная основная общеобразовательная программа начального общего образования для слабовидящих обучающихся';
    END
    ELSE IF(V$TYPE_ID = 11190) THEN
    BEGIN
      CODE = 22; -- слепые
      NAME = 'Адаптированная основная общеобразовательная программа начального общего образования слепых обучающихся';
    END
    ELSE IF(V$TYPE_ID = 11191) THEN
    BEGIN
      CODE = 14; -- слабослышащие, позднооглохшие
      NAME = 'Адаптированная основная общеобразовательная программа начального общего образования слабослышащих и позднооглохших обучающихся';
    END
    ELSE IF(V$TYPE_ID = 11192) THEN
    BEGIN
      CODE = 12; -- глухие
      NAME = 'Адаптированная основная образовательная программа начального общего образования глухих обучающихся';
    END
    ELSE IF(V$TYPE_ID = 11194) THEN
    BEGIN
      CODE = 42; -- дефекты ОДА
      NAME = 'Адаптированная основная общеобразовательная программа начального общего образования обучающихся с нарушениями опорно-двигательного аппарата';
    END
    ELSE IF(V$TYPE_ID = 11195) THEN
    BEGIN
      CODE = 32; -- тяжелые нарушения речи
      NAME = 'Адаптированная основная общеобразовательная программа начального общего образования обучающихся с тяжелыми нарушениями речи';
    END
    ELSE IF(V$TYPE_ID = 11196) THEN
    BEGIN
      CODE = 52; -- задержка психразвития
      NAME = 'Адаптированная основная общеобразовательная программа начального общего образования обучающихся с задержкой психического развития';
    END
    ELSE IF(V$TYPE_ID = 11197) THEN
    BEGIN
      CODE = 72; -- уо
      NAME = 'Адаптированная основная общеобразовательная программа образования обучающихся с умственной отсталостью (интеллектуальными нарушениями)';
    END
    ELSE IF(V$TYPE_ID = 13269) THEN
    BEGIN
      CODE = 61; -- аутизм
      NAME = 'Адаптированная основная общеобразовательная программа начального общего образования обучающихся с расстройствами аутистического спектра';
    END

    IF(CODE IS NOT NULL AND (I$DT1 IS NULL OR V$DT1 >= I$DT1 OR V$DT2 >= I$DT1)) THEN
    SUSPEND;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_MS_ADDRESS (
    I$DT1 TIMESTAMP,
    I$DT2 TIMESTAMP NOT NULL = current_timestamp)
RETURNS (
    ID VARCHAR(60),
    USE_ADDRESS INTEGER,
    TYPE_ADDRESS INTEGER,
    TEXT VARCHAR(1000),
    CITY VARCHAR(400),
    DISTRICT VARCHAR(400),
    STATE VARCHAR(400),
    POSTAL_CODE VARCHAR(100),
    COUNTRY VARCHAR(10),
    START_DATETIME TIMESTAMP,
    END_DATETIME TIMESTAMP,
    FLAT VARCHAR(20),
    BUILDING VARCHAR(20),
    HOUSE VARCHAR(20),
    STREET VARCHAR(400),
    CREATE_DATETIME TIMESTAMP,
    SEND_DATETIME TIMESTAMP)
AS
declare variable V$SCHOOL_ID bigint;
declare variable V$GP_ID bigint;
declare variable V$Y integer;
declare variable V$DT1 timestamp;
declare variable V$DT2 timestamp;
declare variable V$ID varchar(60);
declare variable V$EOD bigint;
begin

  SEND_DATETIME = I$DT2;

  SELECT FIRST 1 L2.OBJ_ID, V1236.LISTVAL_ID, LV.COST, V9.VAL
  FROM LINKS L2
  JOIN VALS V2 ON V2.OBJ_ID = L2.OBJ_ID AND V2.PARAM_ID = 2 AND V2.IS_DEL = 0
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  JOIN VALS V9 ON V9.OBJ_ID = L2.OBJ_ID AND V9.PARAM_ID = 9 AND V9.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$SCHOOL_ID, :V$GP_ID, :V$Y, :V$ID;

  COUNTRY = 'RU';
  USE_ADDRESS = 2; -- work
  TYPE_ADDRESS = 1; -- почтовый. или нужен location ?

  FOR
    SELECT L16.OBJ_ID, L16.DATE_INS, C.VAL, V420.REGION, V420.DISTRICT, V420.TOWN, V420.STREET,
      V420.HOUSE, V420.CORP, V420.FLAT, V420.POST_INDEX,
      MAXVALUE(L16.DATE_MODIFY, V420.DATE_MODIFY)
    FROM LINKS L73
    JOIN LINKS L16 ON L16.PARENT_ID = L73.OBJ_ID AND L16.OBJ_TYPE_ID = 16 AND L16.DATE_DEL IS NULL
    JOIN VALL V485 ON V485.OBJ_ID = L16.OBJ_ID AND V485.PARAM_ID = 485 AND V485.IS_DEL = 0 AND V485.LISTVAL_ID = 1093
    -- Адрес должен быть заполнен с указанием кода ФИАС
    JOIN VALA V420 ON V420.OBJ_ID = L16.OBJ_ID AND V420.PARAM_ID = 420 AND V420.IS_DEL = 0 AND V420.FIAS_UID IS NOT NULL
    LEFT JOIN ADR_GET(420, L16.OBJ_ID) C ON 1 = 1
    WHERE L73.PARENT_ID = :V$SCHOOL_ID AND L73.OBJ_TYPE_ID = 73 AND L73.DATE_DEL IS NULL
    ORDER BY 1
    INTO :ID, :CREATE_DATETIME, :TEXT, :STATE, :DISTRICT, :CITY, :STREET,
      :HOUSE, :BUILDING, :FLAT, :POSTAL_CODE, :V$DT1
  DO
  BEGIN
    IF(I$DT1 IS NULL OR V$DT1 >= I$DT1 OR V$DT2 >= I$DT1) THEN SUSPEND;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_MS_CHANGES (
    I$DT1 TIMESTAMP,
    I$DT2 TIMESTAMP NOT NULL = current_timestamp)
RETURNS (
    ID BIGINT,
    LESSON_ID BIGINT,
    CHANGE_DATETIME TIMESTAMP,
    AUTHOR VARCHAR(400),
    REASON VARCHAR(100),
    CREATE_DATETIME TIMESTAMP,
    SEND_DATETIME TIMESTAMP)
AS
declare variable V$SCHOOL_ID bigint;
declare variable V$GP_ID bigint;
declare variable V$Y integer;
declare variable V$FIELD_ID varchar(100);
begin

  SEND_DATETIME = I$DT2;

  SELECT FIRST 1 L2.OBJ_ID, V1236.LISTVAL_ID, LV.COST
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$SCHOOL_ID, :V$GP_ID, :V$Y;

  FOR
    SELECT LL.OBJ_ID, LL.LESSON_ID, LL.DATE_ADD, LL.FIELD_ID, CU.CAPTION
    FROM CJ2_LESSON_LOG LL
    JOIN CJ2_JOURNAL_LESSONS L ON L.DATE_DEL IS NULL AND L.OBJ_ID = LL.LESSON_ID
    JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.OBJ_ID = L.CJ_ID AND J.JOURNAL_TYPE = 0 AND J.YEAR_ID = :V$GP_ID
    LEFT JOIN USERS U ON U.USER_ID = LL.USER_ID
    LEFT JOIN OBJECT_CAPTION_GET(U.OBJ_ID) CU ON U.OBJ_ID IS NOT NULL
    WHERE LL.DATE_DEL IS NULL AND (LL.FIELD_ID = 'LESSON_DATE' OR LL.FIELD_ID = 'LESSON_NUM' OR LL.FIELD_ID = 'LESSON_THEME' OR LL.FIELD_ID = 'TEACHER' OR LL.FIELD_ID = 'ROOM')
      AND (:I$DT1 IS NULL OR LL.DATE_ADD >= :I$DT1)
    ORDER BY 1
    INTO :ID,  :LESSON_ID, :CHANGE_DATETIME, :V$FIELD_ID, :AUTHOR
  DO
  BEGIN
    -- REASON_ID не заполняем
    CREATE_DATETIME = CHANGE_DATETIME;
    IF(AUTHOR IS NULL) THEN AUTHOR = 'Администратор';
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_MS_CHANGE_DETAILS (
    I$DT1 TIMESTAMP,
    I$DT2 TIMESTAMP NOT NULL = current_timestamp)
RETURNS (
    ID VARCHAR(60),
    CHANGE_ID BIGINT,
    TYPE_CHANGE INTEGER,
    VALUE_OLD VARCHAR(2000),
    VALUE_NEW VARCHAR(2000),
    DESCRIPTION VARCHAR(1000),
    CREATE_DATETIME TIMESTAMP,
    SEND_DATETIME TIMESTAMP)
AS
declare variable V$SCHOOL_ID bigint;
declare variable V$GP_ID bigint;
declare variable V$Y integer;
declare variable V$FIELD_ID varchar(100);
declare variable V$LESSON_ID bigint;
declare variable V$PREV_FIELD varchar(100);
begin

  SEND_DATETIME = I$DT2;

  SELECT FIRST 1 L2.OBJ_ID, V1236.LISTVAL_ID, LV.COST
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$SCHOOL_ID, :V$GP_ID, :V$Y;

  FOR
    SELECT LL.OBJ_ID, LL.LESSON_ID, LL.DATE_ADD, LL.FIELD_ID, LL.VAL
    FROM CJ2_LESSON_LOG LL
    JOIN CJ2_JOURNAL_LESSONS L ON L.DATE_DEL IS NULL AND L.OBJ_ID = LL.LESSON_ID
    JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.OBJ_ID = L.CJ_ID AND J.JOURNAL_TYPE = 0 AND J.YEAR_ID = :V$GP_ID
    WHERE LL.DATE_DEL IS NULL AND (LL.FIELD_ID = 'LESSON_DATE' OR LL.FIELD_ID = 'LESSON_NUM' OR LL.FIELD_ID = 'LESSON_THEME' OR LL.FIELD_ID = 'TEACHER' OR LL.FIELD_ID = 'ROOM')
      AND (:I$DT1 IS NULL OR LL.DATE_ADD >= :I$DT1)
    ORDER BY 1
    INTO :CHANGE_ID, :V$LESSON_ID, :CREATE_DATETIME, :V$FIELD_ID, :VALUE_NEW
  DO
  BEGIN
    ID = CHANGE_ID || ':' || V$FIELD_ID;
    VALUE_OLD = NULL;

    IF(V$FIELD_ID = 'LESSON_DATE' OR V$FIELD_ID = 'LESSON_NUM') THEN
    BEGIN
      TYPE_CHANGE = 2;
      SELECT FIRST 1 LL.VAL, LL.FIELD_ID
      FROM CJ2_LESSON_LOG LL
      WHERE LL.OBJ_ID < :CHANGE_ID AND LL.LESSON_ID = :V$LESSON_ID AND (LL.FIELD_ID = 'LESSON_DATE' OR LL.FIELD_ID = 'LESSON_NUM')
      ORDER BY LL.OBJ_ID DESC                                          
      INTO :VALUE_OLD, :V$PREV_FIELD;

      IF(VALUE_OLD IS NULL) THEN
      BEGIN
        SELECT FIRST 1 LL.VAL
        FROM CJ2_LESSON_LOG LL
        WHERE LL.OBJ_ID < :CHANGE_ID AND LL.LESSON_ID = :V$LESSON_ID AND LL.FIELD_ID = 'NEW'
        ORDER BY LL.OBJ_ID DESC
        INTO :VALUE_OLD;

        -- Если тут есть данные о дате и номере урока, то отрезаем статус по первой запятой
        IF(VALUE_OLD IS NOT NULL) THEN
        BEGIN
          IF(POSITION('#' IN VALUE_OLD) > 0) THEN
          BEGIN
            VALUE_OLD = SUBSTRING(VALUE_OLD FROM POSITION(',' IN VALUE_OLD) + 2);
          END
          ELSE
          BEGIN
            -- старый формат, нет данных о дате или времени
            VALUE_OLD = NULL;
          END
        END
      END
      ELSE
      BEGIN
        IF(V$PREV_FIELD = 'LESSON_NUM') THEN VALUE_OLD = 'Номер урока ' || VALUE_OLD;
        ELSE IF(V$PREV_FIELD = 'LESSON_DATE') THEN
        BEGIN
          -- Сменить формат даты
        END
      END
    END
    ELSE IF(V$FIELD_ID = 'LESSON_THEME') THEN
    BEGIN
      TYPE_CHANGE = 6;
      SELECT FIRST 1 LL.VAL
      FROM CJ2_LESSON_LOG LL
      WHERE LL.OBJ_ID < :CHANGE_ID AND LL.LESSON_ID = :V$LESSON_ID AND (LL.FIELD_ID = 'LESSON_THEME' OR LL.FIELD_ID = 'NEW LESSON_THEME')
      ORDER BY LL.OBJ_ID DESC
      INTO :VALUE_OLD;
    END
    ELSE IF(V$FIELD_ID = 'TEACHER') THEN
    BEGIN
      TYPE_CHANGE = 1;
      -- Этого вида изменений пока нет
    END
    ELSE IF(V$FIELD_ID = 'ROOM') THEN
    BEGIN
      TYPE_CHANGE = 4;
      -- Этого вида изменений пока нет
    END

    IF(VALUE_OLD IS NULL) THEN VALUE_OLD = 'Неизвестно';

    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_MS_CLASSES_PERIODS (
    I$DT1 TIMESTAMP,
    I$DT2 TIMESTAMP NOT NULL = CURRENT_TIMESTAMP)
RETURNS (
    PERIOD_ID VARCHAR(40),
    CLASS_ID VARCHAR(40),
    SCHOOL_ID VARCHAR(40),
    SCHOOL_NAME VARCHAR(400),
    STUDENT_ID VARCHAR(60),
    CLASS_NUM VARCHAR(20),
    CLASS_LETTER VARCHAR(20),
    CLASS_YEAR_FROM INTEGER,
    PERIOD_NUM INTEGER,
    PERIOD_START_DATE DATE,
    PERIOD_END_DATE DATE,
    PERIOD_TYPE_CODE VARCHAR(20),
    PERIOD_TYPE_VALUE INTEGER,
    PERIOD_TYPE_DESCRIOPTION VARCHAR(100),
    PERIOD_IS_STUDY VARCHAR(10),
    DIARY_ID VARCHAR(40),
    DIARY_URL VARCHAR(200),
    DIARY_LOGIN_PASS_AUTH SMALLINT,
    CLASS_START_DATE DATE,
    CLASS_END_DATE DATE,
    SUBJECTS_COUNT INTEGER,
    IS_LAST_CLASS VARCHAR(10),
    PART_OF_CLASS VARCHAR(40),
    CLASS_PLACES INTEGER,
    CLASS_LOCATION VARCHAR(100),
    ATTENDANCE VARCHAR(100),
    EDU_PROGRAM_NAME VARCHAR(200),
    TIMEZONE VARCHAR(20),
    SCHEDULE_URL VARCHAR(200),
    CREATE_DATETIME TIMESTAMP,
    SEND_DATETIME TIMESTAMP,
    PERIOD_ID_CTL BIGINT)
AS
DECLARE VARIABLE V$MAX_NUM INTEGER;
DECLARE VARIABLE V$RANGE_FROM DATE;
DECLARE VARIABLE V$YEAR_ID BIGINT;
DECLARE VARIABLE V$GY_ID BIGINT;
DECLARE VARIABLE V$IN_DATE DATE;
DECLARE VARIABLE V$PERIOD_ID BIGINT;
DECLARE VARIABLE V$STUDENT_ID BIGINT;
DECLARE VARIABLE V$CLASS_ID BIGINT;
DECLARE VARIABLE V$Y INTEGER;
DECLARE VARIABLE V$YSTART DATE;
DECLARE VARIABLE V$YSTART2 DATE;
DECLARE VARIABLE V$YEND DATE;
DECLARE VARIABLE V$YEND2X DATE;
DECLARE VARIABLE V$YEND2 DATE;
DECLARE VARIABLE V$SCHOOL_ID BIGINT;
DECLARE VARIABLE V$FY INTEGER;
DECLARE VARIABLE V$FY2 INTEGER;
DECLARE VARIABLE V$DT1 TIMESTAMP;
DECLARE VARIABLE V$DT2 TIMESTAMP;
DECLARE VARIABLE V$DT3 TIMESTAMP;
DECLARE VARIABLE V$DT4 TIMESTAMP;
DECLARE VARIABLE V$DT5 TIMESTAMP;
DECLARE VARIABLE V$PREV_DATE DATE;
DECLARE VARIABLE V$LAST_DATE DATE;
DECLARE VARIABLE V$START_DATE DATE;
DECLARE VARIABLE V$END_DATE DATE;
DECLARE VARIABLE V$LEVEL_ID BIGINT;
DECLARE VARIABLE V$STAGE_ID BIGINT;
DECLARE VARIABLE V$USE_PRG BIGINT;
DECLARE VARIABLE V$CLASS_PERIOD BIGINT;
DECLARE VARIABLE V$CLASS_STAGE BIGINT;
DECLARE VARIABLE D1 DATE;
DECLARE VARIABLE D2 DATE;
begin

  -- ID дневника всегда один и тот же
  DIARY_ID = '1';
  DIARY_URL = 'https://dnevnik2.petersburgedu.ru';
  SCHEDULE_URL = 'https://dnevnik2.petersburgedu.ru';
  TIMEZONE = '+03:00';
  SEND_DATETIME = I$DT2;

  -- Поле PERIOD_ID_CTL нужно для служебных целей для связывания класса с расписанием периодов на РК
  -- в ЕФТТ оно не выдается

  V$FY = EXTRACT(YEAR FROM CURRENT_DATE);
  V$FY2 = V$FY + 1;

  SELECT FIRST 1 L2.OBJ_ID, V2.VAL, V1236.LISTVAL_ID, LV.COST, V9.VAL, V3516.LISTVAL_ID
  FROM LINKS L2
  JOIN VALS V2 ON V2.OBJ_ID = L2.OBJ_ID AND V2.PARAM_ID = 2 AND V2.IS_DEL = 0
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  JOIN VALS V9 ON V9.OBJ_ID = L2.OBJ_ID AND V9.PARAM_ID = 9 AND V9.IS_DEL = 0
  LEFT JOIN VALL V3516 ON V3516.OBJ_ID = L2.OBJ_ID AND V3516.PARAM_ID = 3516 AND V3516.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$SCHOOL_ID, :SCHOOL_NAME, :V$GY_ID, :V$Y, :SCHOOL_ID, :V$USE_PRG;

  V$RANGE_FROM = '31.08.' || (V$Y - 3);

  IF(V$SCHOOL_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Объект школы не найден';

  -- Максимальный номер параллели ?
  -- только школьные уровни !!
  SELECT MAX(CAST(LV.COST AS INTEGER))
  FROM LINKS L7
  JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
  JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V49.LISTVAL_ID AND LV.PARENT_ID IN (2141, 12941)
  JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
  WHERE L7.PARENT_ID = :V$SCHOOL_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
  INTO :V$MAX_NUM;

  -- Если поменялся хотя бы один период в ОУ
  -- Схема выборки изменена - раньше было 150 > 151 > 154, теперь 481 > 151 > 154
  V$DT5 = NULL;
  SELECT MAX(MAXVALUE(L154.DATE_INS, V1170.DATE_MODIFY, V1169.DATE_MODIFY, V1174.DATE_MODIFY))
  FROM LINKS L481
  JOIN LINKS L151 ON L151.PARENT_ID = L481.OBJ_ID AND L151.OBJ_TYPE_ID = 151 AND L151.DATE_DEL IS NULL
  JOIN LINKS L154 ON L154.PARENT_ID = L151.OBJ_ID AND L154.OBJ_TYPE_ID = 154 AND L154.DATE_DEL IS NULL
  JOIN VALL V1170 ON V1170.OBJ_ID = L154.OBJ_ID AND V1170.PARAM_ID = 1170 AND V1170.IS_DEL = 0
  JOIN VALD V1169 ON V1169.OBJ_ID = L154.OBJ_ID AND V1169.PARAM_ID = 1169 AND V1169.IS_DEL = 0
  JOIN VALD V1174 ON V1174.OBJ_ID = L154.OBJ_ID AND V1174.PARAM_ID = 1174 AND V1174.IS_DEL = 0
  WHERE L481.PARENT_ID = :V$SCHOOL_ID AND L481.OBJ_TYPE_ID = 481 AND L481.DATE_DEL IS NULL
  INTO :V$DT5;

  -- Выбираем всех обучающихся, засветившихся в школе за последние 3 года, но только действующих
  FOR
    SELECT L10.OBJ_ID, V2912.SVAL, MIN(M.DATE_IN), MAX(M.DATE_MODIFY), MAX(V2912.DATE_MODIFY)
    FROM LINKS L10
    JOIN PERSON_MOVEMENTS M ON M.DATE_DEL IS NULL AND M.PERSON_ID = L10.OBJ_ID AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :V$RANGE_FROM) AND M.LEVEL_ID IN (22, 26, 27)
    JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
    -- Есть регид
    JOIN VALS V2912 ON V2912.OBJ_ID = M.PERSON_ID AND V2912.PARAM_ID = 2912 AND V2912.IS_DEL = 0
    WHERE L10.PARENT_TYPE_ID IN (9, 125, 187) AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL -- , 81, 82, 83
    GROUP BY 1, 2
    UNION
    SELECT L10.OBJ_ID, V2912.SVAL, MIN(M.DATE_IN), MAX(M.DATE_MODIFY), MAX(V2912.DATE_MODIFY)
    FROM LINKS L2
    JOIN LINKS L78 ON L78.PARENT_ID = L2.OBJ_ID AND L78.OBJ_TYPE_ID = 78 AND L78.DATE_DEL IS NULL
    JOIN LINKS L83 ON L83.PARENT_ID = L78.OBJ_ID AND L83.OBJ_TYPE_ID = 83 AND L83.DATE_DEL IS NULL
    JOIN VALI V451 ON V451.OBJ_ID = L83.OBJ_ID AND V451.PARAM_ID = 451 AND V451.IS_DEL = 0 AND (V451.VAL = :V$FY OR V451.VAL = :V$FY2)
    JOIN LINKS L10 ON L10.PARENT_ID = L83.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    JOIN VALS V2912 ON V2912.OBJ_ID = L10.OBJ_ID AND V2912.PARAM_ID = 2912 AND V2912.IS_DEL = 0
    JOIN PERSON_MOVEMENTS M ON M.DATE_DEL IS NULL AND M.PERSON_ID = L10.OBJ_ID AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :V$RANGE_FROM) AND M.LEVEL_ID IN (22, 26, 27)
    JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    GROUP BY 1, 2
    ORDER BY 1
    INTO :V$STUDENT_ID, :STUDENT_ID, :V$IN_DATE, :V$DT1, :V$DT2
  DO
  BEGIN

    IF(POSITION(':' IN STUDENT_ID) > 0) THEN STUDENT_ID = SUBSTRING(STUDENT_ID FROM 1 FOR POSITION(':' IN STUDENT_ID) - 1);
    STUDENT_ID = REPLACE(STUDENT_ID, '{', '');
    STUDENT_ID = REPLACE(STUDENT_ID, '}', '');
    STUDENT_ID = LOWER(STUDENT_ID);

    V$DT3 = NULL;
    ATTENDANCE = NULL;
    SELECT C.VAL, V80.DATE_MODIFY
    FROM VALL V80
    LEFT JOIN LISTVAL_TEXT(V80.LISTVAL_ID) C ON 1 = 1
    WHERE V80.OBJ_ID = :V$STUDENT_ID AND V80.PARAM_ID = 80 AND V80.IS_DEL = 0
    INTO :ATTENDANCE, :V$DT3;

    V$DT4 = NULL;
    SELECT MAX(MAXVALUE(L20.DATE_INS, V155.DATE_MODIFY, V1570.DATE_MODIFY))
    FROM LINKS L20
    JOIN VALS V155 ON V155.OBJ_ID = L20.OBJ_ID AND V155.PARAM_ID = 155 AND V155.IS_DEL = 0
    JOIN VALS V1570 ON V1570.OBJ_ID = L20.EXT_OBJ_ID AND V1570.PARAM_ID = 1570 AND V1570.IS_DEL = 0
    WHERE L20.PARENT_ID = :V$STUDENT_ID AND L20.OBJ_TYPE_ID = 20 AND L20.DATE_DEL IS NULL
    INTO :V$DT4;

    -- Перебираем учебные годы с года прихода вплоть до текущего года
    -- если дата зачисления была раньше августа - то ученик успел попасть в предыдущий учебный год
    -- изменение: теперь по ФЛК ставим именно тот календарный год, когда ученик пришел в класс
    CLASS_YEAR_FROM = EXTRACT(YEAR FROM V$IN_DATE);
    IF(EXTRACT(MONTH FROM V$IN_DATE) < 8) THEN CLASS_YEAR_FROM = CLASS_YEAR_FROM - 1;

    IF(I$DT1 IS NULL OR V$DT1 >= I$DT1 OR V$DT2 >= I$DT1 OR V$DT3 >= I$DT1 OR V$DT4 >= I$DT1 OR V$DT5 >= I$DT1) THEN
    WHILE(CLASS_YEAR_FROM <= V$Y) DO
    BEGIN
      V$YSTART = '01.09.' || CLASS_YEAR_FROM; -- дата начала обучения в году
      V$YSTART2 = '25.08.' || CLASS_YEAR_FROM; -- дата, начиная с которой можно зачислять
      V$YEND = '31.08.' || (CLASS_YEAR_FROM + 1);
      V$YEND2X = DATEADD(10 DAY TO V$YEND);
      V$YEND2 = DATEADD(-10 DAY TO V$YEND);
      CLASS_START_DATE = NULL;
      CLASS_END_DATE = NULL;

      FOR
        -- Если ученик шатался между классами - выбираем диапазоны по min-max
        -- исключаем случаи, когда зачисление и выбытие прошли одной датой
        -- дубли потом подчистим на прокси прямо перед отправкой
        SELECT M.GROUP_ID, SUBSTRING(M.NAME_IN FROM 1 FOR 20), CAST(LV.COST AS INTEGER), M.DATE_IN, M.DATE_OUT, M.DATE_ADD, V3517.VAL, M.STAGE_ID
        FROM PERSON_MOVEMENTS M
        JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
        JOIN LISTVALS LV ON LV.LISTVAL_ID = M.STAGE_ID
        LEFT JOIN VALR V3517 ON V3517.OBJ_ID = M.GROUP_ID AND V3517.PARAM_ID = 3517 AND V3517.IS_DEL = 0
        WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :V$STUDENT_ID AND M.DATE_IN >= :V$YSTART2 AND M.DATE_IN <= :V$YEND2
          AND (M.DATE_OUT IS NULL OR (M.DATE_OUT > :V$YSTART AND M.DATE_OUT <= :V$YEND2X AND M.DATE_OUT <> M.DATE_IN))
          AND M.LEVEL_ID IN (22, 26, 27)
        ORDER BY 4, 3, 2
        INTO :V$CLASS_ID, :CLASS_LETTER, :CLASS_NUM, :D1, :D2, :CREATE_DATETIME, :V$CLASS_PERIOD, :V$CLASS_STAGE
      DO
      BEGIN
        CLASS_ID = V$CLASS_ID || 'Y' || CLASS_YEAR_FROM;

        -- Год начинается строго с 01.09 и заканчивается 31.08, пустым конец быть не должен
        CLASS_START_DATE = D1;
        CLASS_END_DATE = D2;
        IF(CLASS_START_DATE < V$YSTART) THEN CLASS_START_DATE = V$YSTART;
        IF(CLASS_END_DATE IS NULL) THEN CLASS_END_DATE = V$YEND;

        -- Отрезаем параллель
        IF(POSITION(' ' IN CLASS_LETTER) > 0) THEN CLASS_LETTER = SUBSTRING(CLASS_LETTER FROM POSITION(' ' IN CLASS_LETTER) + 1);

        -- !!! досмотреть коррекционки
        IF(CLASS_NUM = V$MAX_NUM) THEN IS_LAST_CLASS = 'true'; ELSE IS_LAST_CLASS = 'false';

        -- Текущий учебный год
        IF(CLASS_YEAR_FROM = V$Y) THEN
        BEGIN
          SELECT COUNT(DISTINCT J.SUBJECT_ID)
          FROM PERSON_MOVEMENTS M
          JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.JOURNAL_TYPE = 0 AND J.GRADE_ID = M.GROUP_ID AND J.YEAR_ID = :V$GY_ID
          WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :V$STUDENT_ID AND M.DATE_IN >= :D1 AND (M.DATE_IN <= :D2 OR :D2 IS NULL)
            AND M.LEVEL_ID IN (22, 26, 27)
          INTO :SUBJECTS_COUNT;

          V$PREV_DATE = NULL;
          V$LAST_DATE = NULL;
          FOR
            SELECT V1170.LISTVAL_ID, V1169.VAL, V1174.VAL, MIN(M.LEVEL_ID), MIN(M.STAGE_ID), MAX(L154.PARENT_ID)
            FROM PERSON_MOVEMENTS M
            JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.JOURNAL_TYPE = 0 AND J.GRADE_ID = M.GROUP_ID AND J.YEAR_ID = :V$GY_ID
            JOIN LINKS L154 ON L154.PARENT_ID = J.PERIOD_ID AND L154.OBJ_TYPE_ID = 154 AND L154.DATE_DEL IS NULL
            JOIN VALL V1170 ON V1170.OBJ_ID = L154.OBJ_ID AND V1170.PARAM_ID = 1170 AND V1170.IS_DEL = 0
            JOIN VALD V1169 ON V1169.OBJ_ID = L154.OBJ_ID AND V1169.PARAM_ID = 1169 AND V1169.IS_DEL = 0
            JOIN VALD V1174 ON V1174.OBJ_ID = L154.OBJ_ID AND V1174.PARAM_ID = 1174 AND V1174.IS_DEL = 0
            WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :V$STUDENT_ID AND M.DATE_IN >= :D1 AND (M.DATE_IN <= :D2 OR :D2 IS NULL)
              AND M.LEVEL_ID IN (22, 26, 27)
            GROUP BY 1, 2, 3
            -- Вторая ветка - для школ без Параграфа, по периоду из класса
            UNION
            SELECT V1170.LISTVAL_ID, V1169.VAL, V1174.VAL, :V$CLASS_STAGE, NULL, :V$CLASS_PERIOD
            FROM LINKS L154
            JOIN VALL V1170 ON V1170.OBJ_ID = L154.OBJ_ID AND V1170.PARAM_ID = 1170 AND V1170.IS_DEL = 0
            JOIN VALD V1169 ON V1169.OBJ_ID = L154.OBJ_ID AND V1169.PARAM_ID = 1169 AND V1169.IS_DEL = 0
            JOIN VALD V1174 ON V1174.OBJ_ID = L154.OBJ_ID AND V1174.PARAM_ID = 1174 AND V1174.IS_DEL = 0
            WHERE :V$USE_PRG = 3 AND L154.PARENT_ID = :V$CLASS_PERIOD AND L154.OBJ_TYPE_ID = 154 AND L154.DATE_DEL IS NULL
            GROUP BY 1, 2, 3
            ORDER BY 1
            INTO :V$PERIOD_ID, :PERIOD_START_DATE, :PERIOD_END_DATE, :V$LEVEL_ID, :V$STAGE_ID, :PERIOD_ID_CTL
          DO
          BEGIN
            IF(V$PREV_DATE IS NULL) THEN V$PREV_DATE = PERIOD_START_DATE; -- дата начала отсчета
            V$LAST_DATE = PERIOD_END_DATE; -- дата конца года
            IF(V$PERIOD_ID IN (12, 13, 14, 15)) THEN BEGIN
              PERIOD_NUM = V$PERIOD_ID - 12 + 1;
              PERIOD_TYPE_VALUE = 1;
              PERIOD_TYPE_CODE = 'quarter';
              PERIOD_TYPE_DESCRIOPTION = 'четверть';
              PERIOD_ID = CLASS_YEAR_FROM || '-Q' || PERIOD_NUM;
            END
            ELSE IF(V$PERIOD_ID IN (10, 11)) THEN BEGIN
              PERIOD_NUM = V$PERIOD_ID - 10 + 1;
              PERIOD_TYPE_VALUE = 4;
              PERIOD_TYPE_CODE = 'halfyear';
              PERIOD_TYPE_DESCRIOPTION = 'полугодие';
              PERIOD_ID = CLASS_YEAR_FROM || '-H' || PERIOD_NUM;
            END
            ELSE IF(V$PERIOD_ID IN (16, 17, 18)) THEN BEGIN
              PERIOD_NUM = V$PERIOD_ID - 16 + 1;
              PERIOD_TYPE_VALUE = 3;
              PERIOD_TYPE_CODE = 'trimester';
              PERIOD_TYPE_DESCRIOPTION = 'триместр';
              PERIOD_ID = CLASS_YEAR_FROM || '-T' || PERIOD_NUM;
            END
            -- семестры ?!!!

            IF(V$LEVEL_ID IN (22, 5339)) THEN EDU_PROGRAM_NAME = 'elementary';
            ELSE IF(V$LEVEL_ID IN (26, 5341)) THEN EDU_PROGRAM_NAME = 'basic';
            ELSE IF(V$LEVEL_ID IN (27, 5343)) THEN EDU_PROGRAM_NAME = 'secondary';
            ELSE IF(V$LEVEL_ID IN (37, 38, 39, 40)) THEN EDU_PROGRAM_NAME = 'elementary';
            ELSE IF(V$LEVEL_ID IN (41, 42, 43, 44, 45)) THEN EDU_PROGRAM_NAME = 'basic';
            ELSE IF(V$LEVEL_ID IN (46, 47, 48)) THEN EDU_PROGRAM_NAME = 'secondary';
            ELSE EDU_PROGRAM_NAME = NULL;

            PERIOD_IS_STUDY = 'false';
            SUSPEND;
          END

          -- Расписание каникул - выдаем только для текущего учебного года, архивные дополняем из РК
          -- Начинаем с V$PREV_DATE
          -- не выдаем данные по летним каникулам
          PERIOD_ID_CTL = NULL;
          PERIOD_NUM = 1;
          PERIOD_TYPE_VALUE = 1;
          PERIOD_TYPE_CODE = 'quarter';
          PERIOD_TYPE_DESCRIOPTION = 'четверть';
          PERIOD_IS_STUDY = 'true';
          FOR
            SELECT V3263.VAL, V3264.VAL, MIN(M.LEVEL_ID), MIN(M.STAGE_ID)
            FROM PERSON_MOVEMENTS M
            JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.JOURNAL_TYPE = 0 AND J.GRADE_ID = M.GROUP_ID AND J.YEAR_ID = :V$GY_ID
            JOIN LINKS L450 ON L450.PARENT_ID = J.PERIOD_ID AND L450.OBJ_TYPE_ID = 450 AND L450.DATE_DEL IS NULL
            JOIN VALD V3263 ON V3263.OBJ_ID = L450.OBJ_ID AND V3263.PARAM_ID = 3263 AND V3263.IS_DEL = 0 AND V3263.VAL < :V$LAST_DATE
            JOIN VALD V3264 ON V3264.OBJ_ID = L450.OBJ_ID AND V3264.PARAM_ID = 3264 AND V3264.IS_DEL = 0
            LEFT JOIN VALS V3265 ON V3265.OBJ_ID = L450.OBJ_ID AND V3265.PARAM_ID = 3265 AND V3265.IS_DEL = 0
            WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :V$STUDENT_ID AND M.DATE_IN >= :D1 AND (M.DATE_IN <= :D2 OR :D2 IS NULL)
              -- не выдаем: каникулы для первоклассников по слову ПЕРВ или ДОП
              AND (V3265.VAL IS NULL OR (POSITION('перв' IN LOWER(V3265.VAL)) <= 0 AND POSITION('доп' IN LOWER(V3265.VAL)) <= 0))
              AND M.LEVEL_ID IN (22, 26, 27)
            GROUP BY 1, 2
            -- Вторая ветка - для школ без Параграфа, по периоду из класса
            UNION
            SELECT V3263.VAL, V3264.VAL, :V$CLASS_STAGE, NULL
            FROM LINKS L450
            JOIN VALD V3263 ON V3263.OBJ_ID = L450.OBJ_ID AND V3263.PARAM_ID = 3263 AND V3263.IS_DEL = 0 AND V3263.VAL < :V$LAST_DATE
            JOIN VALD V3264 ON V3264.OBJ_ID = L450.OBJ_ID AND V3264.PARAM_ID = 3264 AND V3264.IS_DEL = 0
            LEFT JOIN VALS V3265 ON V3265.OBJ_ID = L450.OBJ_ID AND V3265.PARAM_ID = 3265 AND V3265.IS_DEL = 0
            WHERE :V$USE_PRG = 3 AND L450.PARENT_ID = :V$CLASS_PERIOD AND L450.OBJ_TYPE_ID = 450 AND L450.DATE_DEL IS NULL
              -- не выдаем: каникулы для первоклассников по слову ПЕРВ или ДОП
              AND (V3265.VAL IS NULL OR (POSITION('перв' IN LOWER(V3265.VAL)) <= 0 AND POSITION('доп' IN LOWER(V3265.VAL)) <= 0))
            ORDER BY 1
            INTO :V$START_DATE, :V$END_DATE, :V$LEVEL_ID, :V$STAGE_ID
          DO
          BEGIN
            PERIOD_START_DATE = V$PREV_DATE;
            PERIOD_END_DATE = V$START_DATE;
            PERIOD_ID = CLASS_YEAR_FROM || '-C' || PERIOD_NUM;

            IF(V$LEVEL_ID IN (22, 5339)) THEN EDU_PROGRAM_NAME = 'elementary';
            ELSE IF(V$LEVEL_ID IN (26, 5341)) THEN EDU_PROGRAM_NAME = 'basic';
            ELSE IF(V$LEVEL_ID IN (27, 5343)) THEN EDU_PROGRAM_NAME = 'secondary';
            ELSE IF(V$LEVEL_ID IN (37, 38, 39, 40)) THEN EDU_PROGRAM_NAME = 'elementary';
            ELSE IF(V$LEVEL_ID IN (41, 42, 43, 44, 45)) THEN EDU_PROGRAM_NAME = 'basic';
            ELSE IF(V$LEVEL_ID IN (46, 47, 48)) THEN EDU_PROGRAM_NAME = 'secondary';
            ELSE EDU_PROGRAM_NAME = NULL;

            SUSPEND;
            PERIOD_NUM = PERIOD_NUM + 1;
            V$PREV_DATE = DATEADD(1 DAY TO V$END_DATE);
          END

          -- Закрываем последний период
          IF(V$LAST_DATE > V$PREV_DATE) THEN
          BEGIN
            PERIOD_START_DATE = V$PREV_DATE;
            PERIOD_END_DATE = V$LAST_DATE;
            PERIOD_ID = CLASS_YEAR_FROM || '-C' || PERIOD_NUM;
            SUSPEND;
          END

        END
        -- Архивный учебный год
        ELSE
        BEGIN
          -- id учебного года, он обязательно есть
          SELECT FIRST 1 LV.LISTVAL_ID
          FROM LISTVALS LV
          WHERE LV.IS_DEL = 0 AND LV.LIST_ID = 29 AND LV.COST = :CLASS_YEAR_FROM
          INTO :V$YEAR_ID;

          V$LEVEL_ID = NULL;
          SELECT FIRST 1 M.LEVEL_ID, M.STAGE_ID
          FROM PERSON_MOVEMENTS M
          WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :V$STUDENT_ID AND M.GROUP_ID = :V$CLASS_ID
            AND M.DATE_IN >= :D1 AND (M.DATE_IN <= :D2 OR :D2 IS NULL)
            AND M.LEVEL_ID IN (22, 26, 27)
          ORDER BY M.DATE_IN DESC
          INTO :V$LEVEL_ID, :V$STAGE_ID;

          IF(V$LEVEL_ID IN (22, 5339)) THEN EDU_PROGRAM_NAME = 'elementary';
          ELSE IF(V$LEVEL_ID IN (26, 5341)) THEN EDU_PROGRAM_NAME = 'basic';
          ELSE IF(V$LEVEL_ID IN (27, 5343)) THEN EDU_PROGRAM_NAME = 'secondary';
          ELSE IF(V$LEVEL_ID IN (37, 38, 39, 40)) THEN EDU_PROGRAM_NAME = 'elementary';
          ELSE IF(V$LEVEL_ID IN (41, 42, 43, 44, 45)) THEN EDU_PROGRAM_NAME = 'basic';
          ELSE IF(V$LEVEL_ID IN (46, 47, 48)) THEN EDU_PROGRAM_NAME = 'secondary';
          ELSE EDU_PROGRAM_NAME = NULL;

          FOR
            SELECT DISTINCT M.MARKTYPE_ID
            FROM VALM M
            WHERE M.IS_DEL = 0 AND (M.IS_NATIVE IS NULL OR M.IS_NATIVE = 1) AND M.PUPIL_ID = :V$STUDENT_ID AND M.YEAR_ID = :V$YEAR_ID
              AND (M.MARKTYPE_ID <= 3010 OR M.MARKTYPE_ID IN (12973, 12974))
            ORDER BY 1
            INTO :V$PERIOD_ID
          DO
          BEGIN
            -- !!! Что там с семестрами в СПО ?
            -- Даты для прошедших периодов берем таблично
            IF(V$PERIOD_ID IN (3002, 3003, 3004, 3005)) THEN BEGIN
              PERIOD_NUM = V$PERIOD_ID - 3002 + 1;
              PERIOD_TYPE_VALUE = 1;
              PERIOD_TYPE_CODE = 'quarter';
              PERIOD_TYPE_DESCRIOPTION = 'четверть';
              PERIOD_ID = CLASS_YEAR_FROM || '-Q' || PERIOD_NUM;
            END
            ELSE IF(V$PERIOD_ID IN (3009, 3010)) THEN BEGIN
              PERIOD_NUM = V$PERIOD_ID - 3009 + 1;
              PERIOD_TYPE_VALUE = 4;
              PERIOD_TYPE_CODE = 'halfyear';
              PERIOD_TYPE_DESCRIOPTION = 'полугодие';
              PERIOD_ID = CLASS_YEAR_FROM || '-H' || PERIOD_NUM;
            END
            ELSE IF(V$PERIOD_ID IN (3006, 3007, 3008)) THEN BEGIN
              PERIOD_NUM = V$PERIOD_ID - 3006 + 1;
              PERIOD_TYPE_VALUE = 3;
              PERIOD_TYPE_CODE = 'trimester';
              PERIOD_TYPE_DESCRIOPTION = 'триместр';
              PERIOD_ID = CLASS_YEAR_FROM || '-T' || PERIOD_NUM;
            END

            IF(V$PERIOD_ID = 3002) THEN
            BEGIN
              PERIOD_START_DATE = CLASS_YEAR_FROM || '-09-01';
              PERIOD_END_DATE = CLASS_YEAR_FROM || '-10-31';
            END
            ELSE IF(V$PERIOD_ID = 3003) THEN
            BEGIN
              PERIOD_START_DATE = CLASS_YEAR_FROM || '-11-01';
              PERIOD_END_DATE = CLASS_YEAR_FROM || '-12-31';
            END
            ELSE IF(V$PERIOD_ID = 3004) THEN
            BEGIN
              PERIOD_START_DATE = (CLASS_YEAR_FROM + 1) || '-01-01';
              PERIOD_END_DATE = (CLASS_YEAR_FROM + 1) || '-03-20';
            END
            ELSE IF(V$PERIOD_ID = 3005) THEN
            BEGIN
              PERIOD_START_DATE = (CLASS_YEAR_FROM + 1) || '-03-21';
              PERIOD_END_DATE = (CLASS_YEAR_FROM + 1) || '-05-31';
            END
            ELSE IF(V$PERIOD_ID = 3006) THEN
            BEGIN
              PERIOD_START_DATE = CLASS_YEAR_FROM || '-09-01';
              PERIOD_END_DATE = CLASS_YEAR_FROM || '-11-30';
            END
            ELSE IF(V$PERIOD_ID = 3007) THEN
            BEGIN
              PERIOD_START_DATE = CLASS_YEAR_FROM || '-12-01';
              PERIOD_END_DATE = (CLASS_YEAR_FROM + 1) || '-03-01';
            END
            ELSE IF(V$PERIOD_ID = 3008) THEN
            BEGIN
              PERIOD_START_DATE = (CLASS_YEAR_FROM + 1) || '-03-02';
              PERIOD_END_DATE = (CLASS_YEAR_FROM + 1) || '-05-31';
            END
            ELSE IF(V$PERIOD_ID = 3009) THEN
            BEGIN
              PERIOD_START_DATE = CLASS_YEAR_FROM || '-09-01';
              PERIOD_END_DATE = CLASS_YEAR_FROM || '-12-31';
            END
            ELSE IF(V$PERIOD_ID = 3010) THEN
            BEGIN
              PERIOD_START_DATE = (CLASS_YEAR_FROM + 1) || '-01-01';
              PERIOD_END_DATE = (CLASS_YEAR_FROM + 1) || '-05-31';
            END

            SELECT COUNT(DISTINCT M.SUBJECT_ID)
            FROM VALM M
            WHERE M.IS_DEL = 0 AND (M.IS_NATIVE IS NULL OR M.IS_NATIVE = 1) AND M.PUPIL_ID = :V$STUDENT_ID AND M.YEAR_ID = :V$YEAR_ID AND M.MARKTYPE_ID = :V$PERIOD_ID
            INTO :SUBJECTS_COUNT;

            PERIOD_IS_STUDY = 'false';
            SUSPEND;
          END
        END

      END

      CLASS_YEAR_FROM = CLASS_YEAR_FROM + 1;
    END

  END

  WHEN ANY DO EXCEPTION DATA_ERROR 'Ошибка на персоне ' || V$STUDENT_ID;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_MS_COMMONPLANMARKS (
    I$DT1 TIMESTAMP,
    I$DT2 TIMESTAMP NOT NULL = CURRENT_TIMESTAMP)
RETURNS (
    PERIOD_ID VARCHAR(40),
    STUDENT_ID VARCHAR(60),
    CLASS_ID VARCHAR(40),
    TOTAL VARCHAR(20),
    FIVEPOINT_TOTAL VARCHAR(20),
    SCHOOL_ID VARCHAR(40),
    CLASS_NUM INTEGER,
    CLASS_YEAR_FROM INTEGER,
    MARK_SCALE_CODE VARCHAR(20),
    MARK_SCALE_VALUE INTEGER,
    MARK_SCALE_DESCRIPTION VARCHAR(40),
    CREATE_DATETIME TIMESTAMP,
    SEND_DATETIME TIMESTAMP)
AS
DECLARE VARIABLE V$GP_ID BIGINT;
DECLARE VARIABLE V$Y INTEGER;
DECLARE VARIABLE V$YSTART DATE;
DECLARE VARIABLE V$YEND DATE;
DECLARE VARIABLE V$STUDENT_ID BIGINT;
DECLARE VARIABLE V$PERIOD_ID BIGINT;
DECLARE VARIABLE V$PERIOD_DATE DATE;
DECLARE VARIABLE V$SCHOOL_ID BIGINT;
DECLARE VARIABLE V$CLASS_ID BIGINT;
DECLARE VARIABLE V$T DOUBLE PRECISION;
DECLARE VARIABLE V$B DOUBLE PRECISION;
DECLARE VARIABLE PERIOD_NUM INTEGER;
DECLARE VARIABLE V$DT1 TIMESTAMP;
DECLARE VARIABLE V$DT2 TIMESTAMP;
DECLARE VARIABLE V$DT3 TIMESTAMP;
DECLARE VARIABLE V$DT4 TIMESTAMP;
begin

  CREATE_DATETIME = I$DT2;
  SEND_DATETIME = I$DT2;

  MARK_SCALE_VALUE = '1';
  MARK_SCALE_CODE = '5-points';
  MARK_SCALE_DESCRIPTION = 'Пятибалльная';

  SELECT FIRST 1 L2.OBJ_ID, V1236.LISTVAL_ID, LV.COST, V9.VAL
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  JOIN VALS V9 ON V9.OBJ_ID = L2.OBJ_ID AND V9.PARAM_ID = 9 AND V9.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$SCHOOL_ID, :V$GP_ID, :V$Y, :SCHOOL_ID;

  V$YSTART = '01.09.' || V$Y;
  V$YEND = '31.08.' || (V$Y + 1);
  CLASS_YEAR_FROM = V$Y;

  IF(V$SCHOOL_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Объект школы не найден';

  FOR
    SELECT L10.OBJ_ID, V2912.SVAL, MAX(M.DATE_MODIFY), MAX(V2912.DATE_MODIFY)
    FROM LINKS L10
    JOIN PERSON_MOVEMENTS M ON M.DATE_DEL IS NULL AND M.PERSON_ID = L10.OBJ_ID AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :V$YSTART) AND M.LEVEL_ID IN (22, 26, 27)
    -- Фильтруем только действующих учеников
    JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID IN (9, 125, 187)
    -- Есть регид
    JOIN VALS V2912 ON V2912.OBJ_ID = M.PERSON_ID AND V2912.PARAM_ID = 2912 AND V2912.IS_DEL = 0
    WHERE L10.PARENT_TYPE_ID IN (9, 125, 187) AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL -- , 81, 82, 83
    GROUP BY 1, 2
    ORDER BY 1
    INTO :V$STUDENT_ID, :STUDENT_ID, :V$DT1, :V$DT2
  DO
  BEGIN
    IF(POSITION(':' IN STUDENT_ID) > 0) THEN STUDENT_ID = SUBSTRING(STUDENT_ID FROM 1 FOR POSITION(':' IN STUDENT_ID) - 1);
    STUDENT_ID = REPLACE(STUDENT_ID, '{', '');
    STUDENT_ID = REPLACE(STUDENT_ID, '}', '');
    STUDENT_ID = LOWER(STUDENT_ID);

    V$DT3 = NULL;
    SELECT MAX(MAXVALUE(L20.DATE_INS, V155.DATE_MODIFY, V1570.DATE_MODIFY))
    FROM LINKS L20
    JOIN VALS V155 ON V155.OBJ_ID = L20.OBJ_ID AND V155.PARAM_ID = 155 AND V155.IS_DEL = 0
    JOIN VALS V1570 ON V1570.OBJ_ID = L20.EXT_OBJ_ID AND V1570.PARAM_ID = 1570 AND V1570.IS_DEL = 0
    WHERE L20.PARENT_ID = :V$STUDENT_ID AND L20.OBJ_TYPE_ID = 20 AND L20.DATE_DEL IS NULL
    INTO :V$DT3;

    -- Проходим по всем классам, где ученик побывал
    FOR
      SELECT DISTINCT M.GROUP_ID, LV.COST
      FROM PERSON_MOVEMENTS M
      JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID IN (9, 125, 187)
      JOIN LISTVALS LV ON LV.LISTVAL_ID = M.STAGE_ID
      WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :V$STUDENT_ID AND M.DATE_IN <= :V$YEND
        AND (M.DATE_OUT IS NULL OR (M.DATE_OUT >= :V$YSTART AND M.DATE_OUT <= :V$YEND AND M.DATE_OUT <> M.DATE_IN))
      ORDER BY 1, 2
      INTO :V$CLASS_ID, :CLASS_NUM
    DO
    BEGIN
      CLASS_ID = V$CLASS_ID || 'Y' || CLASS_YEAR_FROM;

      -- Идем по периодам
      FOR
        SELECT V1170.LISTVAL_ID, V1174.VAL, SUM(CT.DEFAULT_COST * MT.MARK_COST), SUM(CT.DEFAULT_COST),
          MAX(MAXVALUE(V1170.DATE_MODIFY, V1169.DATE_MODIFY, V1174.DATE_MODIFY, MV.DATE_MODIFY))
        FROM PERSON_MOVEMENTS M
        JOIN PERSON_MOVEMENTS M2 ON M2.DATE_DEL IS NULL AND M2.PERSON_ID = M.PERSON_ID
          AND (M2.DATE_IN <= M.DATE_OUT OR M.DATE_OUT IS NULL)
          AND ((M2.DATE_OUT >= M.DATE_IN AND M2.DATE_OUT > M2.DATE_IN) OR M2.DATE_OUT IS NULL)
        JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.JOURNAL_TYPE = 0 AND J.GRADE_ID = M2.GROUP_ID
        JOIN CJ2_JOURNAL_LESSONS L ON L.CJ_ID = J.OBJ_ID AND L.DATE_DEL IS NULL AND L.LESSON_DATE >= M.DATE_IN AND (L.LESSON_DATE <= M.DATE_OUT OR M.DATE_OUT IS NULL)
        JOIN CJ2_CONTROL C ON C.LESSON_ID = L.OBJ_ID AND C.DATE_DEL IS NULL AND C.CONTROL_TYPE_ID <> 0
        JOIN CJ2_CONTROL_TYPE CT ON CT.CONTROL_TYPE_ID = C.CONTROL_TYPE_ID
        JOIN CJ2_MARK MV ON MV.DATE_DEL IS NULL AND MV.CONTROL_ID = C.CONTROL_ID AND MV.STUDENT_ID = M.PERSON_ID
        JOIN CJ2_MARK_TYPE MT ON MT.MARK_TYPE_ID = MV.MARK_TYPE_ID
        -- Выбираем подходящий период
        JOIN LINKS L154 ON L154.PARENT_ID = J.PERIOD_ID AND L154.OBJ_TYPE_ID = 154 AND L154.DATE_DEL IS NULL
        JOIN VALD V1169 ON V1169.OBJ_ID = L154.OBJ_ID AND V1169.PARAM_ID = 1169 AND V1169.IS_DEL = 0 AND V1169.VAL <= L.LESSON_DATE
        JOIN VALD V1174 ON V1174.OBJ_ID = L154.OBJ_ID AND V1174.PARAM_ID = 1174 AND V1174.IS_DEL = 0 AND V1174.VAL >= L.LESSON_DATE
        JOIN VALL V1170 ON V1170.OBJ_ID = L154.OBJ_ID AND V1170.PARAM_ID = 1170 AND V1170.IS_DEL = 0
        WHERE M.DATE_DEL IS NULL AND M.GROUP_ID = :V$CLASS_ID AND M.PERSON_ID = :V$STUDENT_ID AND M.DATE_IN <= :V$YEND
          AND (M.DATE_OUT IS NULL OR (M.DATE_OUT >= :V$YSTART AND M.DATE_OUT <= :V$YEND AND M.DATE_OUT <> M.DATE_IN))
        GROUP BY 1, 2
        ORDER BY 1
        INTO :V$PERIOD_ID, :CREATE_DATETIME, :V$T, :V$B, :V$DT4
      DO
      BEGIN
        IF(CREATE_DATETIME > CURRENT_DATE) THEN CREATE_DATETIME = CURRENT_DATE;
        IF(V$B > 0) THEN 
        BEGIN
          TOTAL = CAST(V$T / V$B AS NUMERIC(18, 2));
          FIVEPOINT_TOTAL = CAST(V$T / V$B AS NUMERIC(18, 1));

          IF(V$PERIOD_ID IN (12, 13, 14, 15)) THEN BEGIN
            PERIOD_NUM = V$PERIOD_ID - 12 + 1;
            PERIOD_ID = CLASS_YEAR_FROM || '-Q' || PERIOD_NUM;
          END
          ELSE IF(V$PERIOD_ID IN (10, 11)) THEN BEGIN
            PERIOD_NUM = V$PERIOD_ID - 10 + 1;
            PERIOD_ID = CLASS_YEAR_FROM || '-H' || PERIOD_NUM;
          END
          ELSE IF(V$PERIOD_ID IN (16, 17, 18)) THEN BEGIN
            PERIOD_NUM = V$PERIOD_ID - 16 + 1;
            PERIOD_ID = CLASS_YEAR_FROM || '-T' || PERIOD_NUM;
          END
          -- семестры ?!!!

          IF(I$DT1 IS NULL OR V$DT1 >= I$DT1 OR V$DT2 >= I$DT1 OR V$DT3 >= I$DT1 OR V$DT4 >= I$DT1) THEN
          SUSPEND;
        END
      END

    END

  END

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_MS_CSTUDENTS_EDU_GROUP (
    I$DT1 TIMESTAMP,
    I$DT2 TIMESTAMP NOT NULL = CURRENT_TIMESTAMP)
RETURNS (
    STUDENT_ID VARCHAR(60),
    EDU_GROUP_URI VARCHAR(200),
    CREATE_DATETIME TIMESTAMP,
    SEND_DATETIME TIMESTAMP)
AS
DECLARE VARIABLE V$SCHOOL_ID BIGINT;
DECLARE VARIABLE V$GP_ID BIGINT;
DECLARE VARIABLE V$Y INTEGER;
DECLARE VARIABLE V$DT1 TIMESTAMP;
DECLARE VARIABLE V$DT2 TIMESTAMP;
DECLARE VARIABLE V$DT3 TIMESTAMP;
DECLARE VARIABLE SCHOOL_ID VARCHAR(40);
DECLARE VARIABLE V$PERSON_ID BIGINT;
DECLARE VARIABLE V$FY INTEGER;
DECLARE VARIABLE V$FY2 INTEGER;
begin

  -- Полное название пакета classes_students_edu_group
  -- Сам пакет - непонятная шняга, содержащая связь обучающихся и плана учебных мест

  SEND_DATETIME = I$DT2;

  V$FY = EXTRACT(YEAR FROM CURRENT_DATE);
  V$FY2 = V$FY + 1;

  SELECT FIRST 1 L2.OBJ_ID, V1236.LISTVAL_ID, LV.COST, V9.VAL
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  JOIN VALS V9 ON V9.OBJ_ID = L2.OBJ_ID AND V9.PARAM_ID = 9 AND V9.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$SCHOOL_ID, :V$GP_ID, :V$Y, :SCHOOL_ID;

  EDU_GROUP_URI = 'https://dnevnik2.petersburgedu.ru/groups/' || SCHOOL_ID || '/' || V$Y;

  -- Передаем только учебные группы ?
  FOR
    -- Текущие ученики
    SELECT SID, MAX(OBJ_ID), MAX(DATE_MODIFY)
    FROM (
      SELECT V2912.SVAL SID, L10.OBJ_ID, L10.DATE_MODIFY
      FROM LINKS L2
      JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
      JOIN VALL V43 ON V43.OBJ_ID = L7.OBJ_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0 AND V43.LISTVAL_ID IN (22, 26, 27)
      JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
      JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      JOIN VALS V2912 ON V2912.OBJ_ID = L10.OBJ_ID AND V2912.PARAM_ID = 2912 AND V2912.IS_DEL = 0
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      UNION
      -- Окончившие
      SELECT V2912.SVAL, L10.OBJ_ID, L10.DATE_MODIFY
      FROM LINKS L2
      JOIN LINKS L78 ON L78.PARENT_ID = L2.OBJ_ID AND L78.OBJ_TYPE_ID = 78 AND L78.DATE_DEL IS NULL
      JOIN LINKS L83 ON L83.PARENT_ID = L78.OBJ_ID AND L83.OBJ_TYPE_ID = 83 AND L83.DATE_DEL IS NULL
      JOIN VALI V451 ON V451.OBJ_ID = L83.OBJ_ID AND V451.PARAM_ID = 451 AND V451.IS_DEL = 0 AND (V451.VAL = :V$FY OR V451.VAL = :V$FY2)
      JOIN LINKS L10 ON L10.PARENT_ID = L83.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      JOIN VALS V2912 ON V2912.OBJ_ID = L10.OBJ_ID AND V2912.PARAM_ID = 2912 AND V2912.IS_DEL = 0
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    )
    GROUP BY 1
    ORDER BY 1
    INTO :STUDENT_ID, :V$PERSON_ID, :V$DT1
  DO
  BEGIN
    IF(POSITION(':' IN STUDENT_ID) > 0) THEN STUDENT_ID = SUBSTRING(STUDENT_ID FROM 1 FOR POSITION(':' IN STUDENT_ID) - 1);
    STUDENT_ID = REPLACE(STUDENT_ID, '{', '');
    STUDENT_ID = REPLACE(STUDENT_ID, '}', '');
    STUDENT_ID = LOWER(STUDENT_ID);

    CREATE_DATETIME = MAXVALUE(V$DT1, '01.09.' || V$Y);

    IF(I$DT1 IS NULL OR V$DT1 >= I$DT1 OR V$DT2 >= I$DT1) THEN
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_MS_DOCUMENTS (
    I$DT1 TIMESTAMP,
    I$DT2 TIMESTAMP NOT NULL = current_timestamp)
RETURNS (
    ID VARCHAR(60),
    DOC_TYPE INTEGER,
    NUM VARCHAR(100),
    SERIES VARCHAR(100),
    ISSUE_DATE DATE,
    WHO_ISSUE VARCHAR(1000),
    COMMENT VARCHAR(1000),
    CREATE_DATETIME TIMESTAMP,
    SEND_DATETIME TIMESTAMP)
AS
declare variable V$SCHOOL_ID bigint;
declare variable V$GP_ID bigint;
declare variable V$Y integer;
declare variable V$DT1 timestamp;
declare variable V$DT2 timestamp;
declare variable V$PERSON_ID bigint;
declare variable SID varchar(100);
declare variable V$YDATE date;
begin

  SEND_DATETIME = I$DT2;

  SELECT FIRST 1 L2.OBJ_ID, V1236.LISTVAL_ID, LV.COST
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  JOIN VALS V9 ON V9.OBJ_ID = L2.OBJ_ID AND V9.PARAM_ID = 9 AND V9.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$SCHOOL_ID, :V$GP_ID, :V$Y;

  V$YDATE = '30.08.' || V$Y;

  -- Выгружаем только действующие документы, и только учителей (образование, повышение квалификации)
  -- с родителями TODO
  FOR
    -- Действующие
    SELECT SID, MAX(OBJ_ID), MAX(DATE_MODIFY)
    FROM (
      SELECT V2915.SVAL SID, L14.OBJ_ID, L14.DATE_MODIFY
      FROM LINKS L2
      JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
      JOIN VALS V2915 ON V2915.OBJ_ID = L14.OBJ_ID AND V2915.PARAM_ID = 2915 AND V2915.IS_DEL = 0
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      UNION
      -- Уволенные не ранее даты начала текущего учебного года
      SELECT V2915.SVAL, L14.OBJ_ID, L14.DATE_MODIFY
      FROM LINKS L2
      JOIN LINKS L84 ON L84.PARENT_ID = L2.OBJ_ID AND L84.OBJ_TYPE_ID = 84 AND L84.DATE_DEL IS NULL
      JOIN LINKS L14 ON L14.PARENT_ID = L84.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
      JOIN VALS V2915 ON V2915.OBJ_ID = L14.OBJ_ID AND V2915.PARAM_ID = 2915 AND V2915.IS_DEL = 0
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND EXISTS(
        SELECT FIRST 1 1
        FROM LINKS L15
        LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
        WHERE L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL AND (V74.VAL IS NULL OR V74.VAL >= :V$YDATE)
      )
    )
    GROUP BY 1
    ORDER BY 1
    INTO :SID, :V$PERSON_ID, :V$DT1
  DO
  BEGIN
    FOR
      SELECT L33.OBJ_ID, L33.DATE_INS, V287.VAL, V288.VAL, V290.VAL, V285.VAL,
        MAXVALUE(L33.DATE_MODIFY, V287.DATE_MODIFY, V288.DATE_MODIFY, V290.DATE_MODIFY, V285.DATE_MODIFY)
      FROM LINKS L33
      LEFT JOIN VALD V290 ON V290.OBJ_ID = L33.OBJ_ID AND V290.PARAM_ID IN (290, 310) AND V290.IS_DEL = 0
      LEFT JOIN VALS V288 ON V288.OBJ_ID = L33.OBJ_ID AND V288.PARAM_ID IN (288, 309) AND V288.IS_DEL = 0
      LEFT JOIN VALS V287 ON V287.OBJ_ID = L33.OBJ_ID AND V287.PARAM_ID IN (287, 308) AND V287.IS_DEL = 0
      JOIN VALS V285 ON V285.OBJ_ID = L33.OBJ_ID AND V285.PARAM_ID IN (285, 304) AND V285.IS_DEL = 0
      WHERE L33.PARENT_ID = :V$PERSON_ID AND L33.OBJ_TYPE_ID IN (33, 36) AND L33.DATE_DEL IS NULL
        AND (V287.VAL IS NOT NULL OR V288.VAL IS NOT NULL OR V290.VAL IS NOT NULL)
      INTO :ID, :CREATE_DATETIME, :SERIES, :NUM, :ISSUE_DATE, :WHO_ISSUE, :V$DT2
    DO
    BEGIN
      -- Всегда документ об образовании, повышении квалификации
      DOC_TYPE = 2;

      IF(DOC_TYPE IS NOT NULL AND (I$DT1 IS NULL OR V$DT1 >= I$DT1 OR V$DT2 >= I$DT1)) THEN SUSPEND;
    END
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_MS_ECONOMY_ACTIVITY (
    I$DT1 TIMESTAMP,
    I$DT2 TIMESTAMP NOT NULL = current_timestamp)
RETURNS (
    ID VARCHAR(600),
    SCHOOL_ID VARCHAR(40),
    CODE VARCHAR(100),
    NAME VARCHAR(400),
    IS_MAIN VARCHAR(10),
    CREATE_DATETIME TIMESTAMP,
    SEND_DATETIME TIMESTAMP)
AS
declare variable V$SCHOOL_ID bigint;
declare variable V$GP_ID bigint;
declare variable V$Y integer;
declare variable V$DT1 timestamp;
declare variable V$DT2 timestamp;
declare variable V$DT3 timestamp;
declare variable S varchar(1000);
declare variable P integer;
declare variable N integer;
declare variable NC timestamp;
begin

  SEND_DATETIME = I$DT2;
  NC = '01.01.2023';

  SELECT FIRST 1 L2.OBJ_ID, V1236.LISTVAL_ID, LV.COST, TRIM(V20.VAL), V9.VAL,
    MAXVALUE(COALESCE(L2.DATE_INS, :NC), COALESCE(V9.DATE_MODIFY, :NC), COALESCE(V20.DATE_MODIFY, :NC))
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  JOIN VALS V20 ON V20.OBJ_ID = L2.OBJ_ID AND V20.PARAM_ID = 20 AND V20.IS_DEL = 0
  JOIN VALS V9 ON V9.OBJ_ID = L2.OBJ_ID AND V9.PARAM_ID = 9 AND V9.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$SCHOOL_ID, :V$GP_ID, :V$Y, :S, :SCHOOL_ID, :CREATE_DATETIME;

  IF(NC < I$DT2) THEN EXIT;

  N = 1;
  WHILE(S <> '') DO
  BEGIN

    P = POSITION(',' IN S);
    IF(P <= 0) THEN P = CHAR_LENGTH(S);

    CODE = TRIM(SUBSTRING(S FROM 1 FOR P - 1));
    S = SUBSTRING(S FROM P + 1);

    IF(CODE <> '') THEN
    BEGIN
      -- Тут могут быть только цифры и точки
      P = 1;
      WHILE(P <= CHAR_LENGTH(CODE)) DO
      BEGIN
        IF(SUBSTRING(CODE FROM P FOR 1) NOT IN ('.', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9')) THEN
          EXCEPTION DATA_ERROR 'Недопустимые символы в кодах ОКВЭД';
        P = P + 1;
      END

      -- Не должно кончаться на точку
      IF(RIGHT(CODE, 1) = '.') THEN EXCEPTION DATA_ERROR 'Код ОКВЭД не должен оканчиваться точкой';

      IF(N = 1) THEN IS_MAIN = 'true'; ELSE IS_MAIN = 'false';
      ID = SCHOOL_ID || 'C' || CODE;

      SUSPEND;
      N = N + 1;
    END
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_MS_EDU_GROUPS (
    I$DT1 TIMESTAMP,
    I$DT2 TIMESTAMP NOT NULL = current_timestamp)
RETURNS (
    URI VARCHAR(200),
    VERSION VARCHAR(60),
    ID VARCHAR(60),
    SCHOOL_ID VARCHAR(60),
    ACADEM_YEAR INTEGER,
    START_DATETIME TIMESTAMP,
    END_DATETIME TIMESTAMP,
    TOTAL_PLACES INTEGER,
    STATUS INTEGER,
    CREATE_DATETIME TIMESTAMP,
    SEND_DATETIME TIMESTAMP)
AS
declare variable V$SCHOOL_ID bigint;
declare variable V$GP_ID bigint;
declare variable V$Y integer;
declare variable V$DT1 timestamp;
declare variable V$DT2 timestamp;
declare variable V$DT3 timestamp;
begin

  SEND_DATETIME = I$DT2;

  SELECT FIRST 1 L2.OBJ_ID, V1236.LISTVAL_ID, LV.COST, V9.VAL
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  JOIN VALS V9 ON V9.OBJ_ID = L2.OBJ_ID AND V9.PARAM_ID = 9 AND V9.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$SCHOOL_ID, :V$GP_ID, :V$Y, :SCHOOL_ID;

  ID = SCHOOL_ID || ':' || V$Y;
  URI = 'https://dnevnik2.petersburgedu.ru/groups/' || SCHOOL_ID || '/' || V$Y;
  ACADEM_YEAR = V$Y;

  START_DATETIME = '01.09.' || V$Y;
  END_DATETIME = '31.08.' || (V$Y + 1) || ' 23:59:59';
  STATUS = 1;
  "VERSION" = '1';

  SELECT COUNT(*), MAX(L10.DATE_MODIFY)
  FROM LINKS L7
  JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
  JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
  JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
  WHERE L7.PARENT_ID = :V$SCHOOL_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
  INTO :TOTAL_PLACES, :CREATE_DATETIME;

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_MS_EDU_LOCATIONS (
    I$DT1 TIMESTAMP,
    I$DT2 TIMESTAMP NOT NULL = current_timestamp)
RETURNS (
    ID VARCHAR(60),
    STATUS INTEGER,
    NAME VARCHAR(1000),
    DESCRIPTION VARCHAR(1000),
    MODE INTEGER,
    ADDRESS_ID VARCHAR(60),
    PHYSICAL_TYPE_CODE VARCHAR(60),
    PHYSICAL_TYPE_VALUE INTEGER,
    PHYSICAL_TYPE_DESCRIPTION VARCHAR(100),
    LONGITUDE DOUBLE PRECISION,
    LATITUDE VARCHAR(60),
    ALTITUDE VARCHAR(60),
    MANAGING_ORG VARCHAR(60),
    EDUCATIONAL_ORG VARCHAR(60),
    PART_OF_LOCATION VARCHAR(60),
    CREATE_DATETIME TIMESTAMP,
    SEND_DATETIME TIMESTAMP)
AS
declare variable V$SCHOOL_ID bigint;
declare variable V$GP_ID bigint;
declare variable V$Y integer;
declare variable V$DT1 timestamp;
declare variable V$DT2 timestamp;
declare variable V$ID varchar(60);
declare variable V$EOD bigint;
declare variable NC timestamp;
begin

  SEND_DATETIME = I$DT2;

  SELECT FIRST 1 L2.OBJ_ID, V1236.LISTVAL_ID, LV.COST, V9.VAL
  FROM LINKS L2
  JOIN VALS V2 ON V2.OBJ_ID = L2.OBJ_ID AND V2.PARAM_ID = 2 AND V2.IS_DEL = 0
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  JOIN VALS V9 ON V9.OBJ_ID = L2.OBJ_ID AND V9.PARAM_ID = 9 AND V9.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$SCHOOL_ID, :V$GP_ID, :V$Y, :V$ID;

  MANAGING_ORG = V$ID;
  EDUCATIONAL_ORG = V$ID;
  NC = '01.01.2023';

  -- Выдаем все адреса зданий, только учебные
  -- заполнение координат не требуем, если что оставляем возможность подложить на сервере
  FOR
    SELECT L16.OBJ_ID, L16.DATE_INS, V421.VAL, CAST(V3457.VAL AS NUMERIC(18, 8)), CAST(V3458.VAL AS NUMERIC(18, 8)), V3164.VAL,
      MAXVALUE(COALESCE(L16.DATE_MODIFY, :NC), COALESCE(V421.DATE_MODIFY, :NC), COALESCE(V420.DATE_MODIFY, :NC),
      COALESCE(V3457.DATE_MODIFY, :NC), COALESCE(V3458.DATE_MODIFY, :NC), COALESCE(V3164.DATE_MODIFY, :NC))
    FROM LINKS L73
    JOIN LINKS L16 ON L16.PARENT_ID = L73.OBJ_ID AND L16.OBJ_TYPE_ID = 16 AND L16.DATE_DEL IS NULL
    JOIN VALL V485 ON V485.OBJ_ID = L16.OBJ_ID AND V485.PARAM_ID = 485 AND V485.IS_DEL = 0 AND V485.LISTVAL_ID = 1093
    -- Адрес должен быть заполнен с указанием кода ФИАС
    JOIN VALA V420 ON V420.OBJ_ID = L16.OBJ_ID AND V420.PARAM_ID = 420 AND V420.IS_DEL = 0 AND V420.FIAS_UID IS NOT NULL
    LEFT JOIN VALS V421 ON V421.OBJ_ID = L16.OBJ_ID AND V421.PARAM_ID = 421 AND V421.IS_DEL = 0
    LEFT JOIN VALF V3457 ON V3457.OBJ_ID = L16.OBJ_ID AND V3457.PARAM_ID = 3457 AND V3457.IS_DEL = 0
    LEFT JOIN VALF V3458 ON V3458.OBJ_ID = L16.OBJ_ID AND V3458.PARAM_ID = 3458 AND V3458.IS_DEL = 0
    -- Дата завершения эксплуатации
    LEFT JOIN VALD V3164 ON V3164.OBJ_ID = L16.OBJ_ID AND V3164.PARAM_ID = 3164 AND V3164.IS_DEL = 0
    WHERE L73.PARENT_ID = :V$SCHOOL_ID AND L73.OBJ_TYPE_ID = 73 AND L73.DATE_DEL IS NULL
    ORDER BY 1
    INTO :ID, :CREATE_DATETIME, :NAME, :LATITUDE, :LONGITUDE, :V$EOD, :V$DT1
  DO
  BEGIN
    IF(NAME IS NULL) THEN EXCEPTION DATA_ERROR 'Наименование всех зданий должно быть заполнено';
    ADDRESS_ID = ID;

    -- Действует, не действует
    IF(V$EOD IS NULL) THEN STATUS = 1; ELSE STATUS = 3;

    -- Всегда = место образовательной деятельности
    MODE = 1;

    -- Тип = всегда здание
    PHYSICAL_TYPE_CODE = 'building';
    PHYSICAL_TYPE_VALUE = 13;
    PHYSICAL_TYPE_DESCRIPTION = 'Здание';

    IF(I$DT1 IS NULL OR V$DT1 >= I$DT1 OR V$DT2 >= I$DT1) THEN SUSPEND;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_MS_EDU_LOCATIONS_CLASSES (
    I$DT1 TIMESTAMP,
    I$DT2 TIMESTAMP NOT NULL = CURRENT_TIMESTAMP)
RETURNS (
    EDU_LOCATION_ID VARCHAR(60),
    CLASS_ID VARCHAR(60),
    CREATE_DATETIME TIMESTAMP,
    SEND_DATETIME TIMESTAMP)
AS
DECLARE VARIABLE V$SCHOOL_ID BIGINT;
DECLARE VARIABLE V$GP_ID BIGINT;
DECLARE VARIABLE V$Y INTEGER;
DECLARE VARIABLE V$DT1 TIMESTAMP;
DECLARE VARIABLE V$DT2 TIMESTAMP;
DECLARE VARIABLE V$DT3 TIMESTAMP;
DECLARE VARIABLE V$CLASS_ID BIGINT;
begin

  SEND_DATETIME = I$DT2;

  SELECT FIRST 1 L2.OBJ_ID, V1236.LISTVAL_ID, LV.COST
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  JOIN VALS V9 ON V9.OBJ_ID = L2.OBJ_ID AND V9.PARAM_ID = 9 AND V9.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$SCHOOL_ID, :V$GP_ID, :V$Y;

  SELECT FIRST 1 L16.OBJ_ID
  FROM LINKS L73
  JOIN LINKS L16 ON L16.PARENT_ID = L73.OBJ_ID AND L16.OBJ_TYPE_ID = 16 AND L16.DATE_DEL IS NULL
  JOIN VALL V485 ON V485.OBJ_ID = L16.OBJ_ID AND V485.PARAM_ID = 485 AND V485.IS_DEL = 0 AND V485.LISTVAL_ID = 1093
  -- Адрес должен быть заполнен с указанием кода ФИАС
  JOIN VALA V420 ON V420.OBJ_ID = L16.OBJ_ID AND V420.PARAM_ID = 420 AND V420.IS_DEL = 0 AND V420.FIAS_UID IS NOT NULL
  -- Дата завершения эксплуатации
  LEFT JOIN VALD V3164 ON V3164.OBJ_ID = L16.OBJ_ID AND V3164.PARAM_ID = 3164 AND V3164.IS_DEL = 0
  WHERE L73.PARENT_ID = :V$SCHOOL_ID AND L73.OBJ_TYPE_ID = 73 AND L73.DATE_DEL IS NULL AND V3164.VAL IS NULL
  ORDER BY L16.OBJ_ID
  INTO :EDU_LOCATION_ID;

  IF(EDU_LOCATION_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Требуется внести главное здание ОУ и указать обязательные атрибуты, включая адрес';

  FOR
    SELECT L9.OBJ_ID, L9.DATE_MODIFY
    FROM LINKS L7
    JOIN VALL V43 ON V43.OBJ_ID = L7.OBJ_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0 AND V43.LISTVAL_ID IN (22, 26, 27)
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
    WHERE L7.PARENT_ID = :V$SCHOOL_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    ORDER BY 1
    INTO :V$CLASS_ID, :V$DT1
  DO
  BEGIN
    CLASS_ID = V$CLASS_ID || 'Y' || V$Y;
    CREATE_DATETIME = V$DT1;

    IF(I$DT1 IS NULL OR V$DT1 >= I$DT1 OR V$DT2 >= I$DT1) THEN
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_MS_EVENTS (
    I$DT1 TIMESTAMP,
    I$DT2 TIMESTAMP NOT NULL = CURRENT_TIMESTAMP)
RETURNS (
    EVENT_ID VARCHAR(60),
    STUDENT_ID VARCHAR(60),
    NAME VARCHAR(400),
    START_DATETIME TIMESTAMP,
    END_DATETIME TIMESTAMP,
    AUTHOR VARCHAR(200),
    TYPE_CODE VARCHAR(20),
    TYPE_VALUE INTEGER,
    TYPE_DESCRIPTION VARCHAR(100),
    DESCRIPTION VARCHAR(1000),
    PLACE VARCHAR(200),
    STATUS_CODE VARCHAR(20),
    STATUS_VALUE INTEGER,
    STATUS_DESCRIPTION VARCHAR(200),
    LINK VARCHAR(400),
    TIMEZONE VARCHAR(20),
    IS_MANDATORY SMALLINT,
    CREATE_DATETIME TIMESTAMP,
    SEND_DATETIME TIMESTAMP)
AS
DECLARE VARIABLE V$GP_ID BIGINT;
DECLARE VARIABLE V$Y INTEGER;
DECLARE VARIABLE V$YSTART DATE;
DECLARE VARIABLE V$YEND DATE;
DECLARE VARIABLE V$STUDENT_ID BIGINT;
DECLARE VARIABLE V$DT DATE;
DECLARE VARIABLE V$CJ_ID BIGINT;
DECLARE VARIABLE SCHOOL_ID VARCHAR(400);
DECLARE VARIABLE V$TEACHER BIGINT;
DECLARE VARIABLE V$SUBJECT_ID BIGINT;
DECLARE VARIABLE V$SCHOOL_ID BIGINT;
DECLARE VARIABLE N INTEGER;
DECLARE VARIABLE V$DT1 TIMESTAMP;
DECLARE VARIABLE V$DT2 TIMESTAMP;
DECLARE VARIABLE V$DT3 TIMESTAMP;
DECLARE VARIABLE V$DT4 TIMESTAMP;
begin

  TIMEZONE = '+03:00';
  SEND_DATETIME = I$DT2;

  SELECT FIRST 1 L2.OBJ_ID, V1236.LISTVAL_ID, LV.COST, V9.VAL
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  JOIN VALS V9 ON V9.OBJ_ID = L2.OBJ_ID AND V9.PARAM_ID = 9 AND V9.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$SCHOOL_ID, :V$GP_ID, :V$Y, :SCHOOL_ID;

  V$YSTART = '01.09.' || V$Y;
  V$YEND = '31.08.' || (V$Y + 1);

  IF(V$SCHOOL_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Объект школы не найден';

  -- Только контрольные работы - всем действующим ученикам групп
  FOR
    SELECT 'CR' || C.CONTROL_ID || '-' || M.PERSON_ID, C.DATE_ADD, V2912.SVAL, CT.CONTROL_DESC, J.OBJ_ID, L.LESSON_DATE, L.LESSON_NUM,
      COALESCE(L.TEACHER_ID, J.TEACHER_ID), J.SUBJECT_ID, V2912.DATE_MODIFY, M.DATE_MODIFY, C.DATE_MODIFY
    FROM CJ2_JOURNAL J
    JOIN CJ2_JOURNAL_LESSONS L ON L.DATE_DEL IS NULL AND L.CJ_ID = J.OBJ_ID AND (L.IS_COMPLETED <> 0 OR L.IS_PUBLISHED <> 0)
    JOIN CJ2_CONTROL C ON C.DATE_DEL IS NULL AND C.LESSON_ID = L.OBJ_ID AND C.CONTROL_TYPE_ID IN (1084, 1085, 1087, 1091)
    JOIN CJ2_CONTROL_TYPE CT ON CT.CONTROL_TYPE_ID = C.CONTROL_TYPE_ID
    JOIN PERSON_MOVEMENTS M ON M.DATE_DEL IS NULL AND M.GROUP_ID = J.GRADE_ID AND M.DATE_IN <= L.LESSON_DATE AND (M.DATE_OUT IS NULL OR M.DATE_OUT > L.LESSON_DATE)
      AND M.LEVEL_ID IN (22, 26, 27)
    JOIN VALS V2912 ON V2912.OBJ_ID = M.PERSON_ID AND V2912.PARAM_ID = 2912 AND V2912.IS_DEL = 0
    WHERE J.DATE_DEL IS NULL AND J.JOURNAL_TYPE = 0 AND J.YEAR_ID = :V$GP_ID
      AND L.LESSON_DATE >= M.DATE_IN AND (M.DATE_OUT IS NULL OR L.LESSON_DATE <= M.DATE_OUT)
      AND EXISTS(
        SELECT FIRST 1 1
        FROM LINKS LPG
        WHERE LPG.OBJ_ID = M.PERSON_ID AND LPG.PARENT_TYPE_ID IN (9, 125, 187) AND LPG.DATE_DEL IS NULL
      )
      /*
      AND EXISTS(
        SELECT FIRST 1 1
        FROM LINKS L20
        JOIN VALS V155 ON V155.OBJ_ID = L20.OBJ_ID AND V155.PARAM_ID = 155 AND V155.IS_DEL = 0
        JOIN VALS V1570 ON V1570.OBJ_ID = L20.EXT_OBJ_ID AND V1570.PARAM_ID = 1570 AND V1570.IS_DEL = 0
        WHERE L20.PARENT_ID = M.PERSON_ID AND L20.OBJ_TYPE_ID = 20 AND L20.DATE_DEL IS NULL
      )
      */
    INTO :EVENT_ID, :CREATE_DATETIME, :STUDENT_ID, :NAME, :V$CJ_ID, :V$DT, :N, :V$TEACHER, :V$SUBJECT_ID, :V$DT1, :V$DT2, :V$DT3
  DO
  BEGIN
    IF(POSITION(':' IN STUDENT_ID) > 0) THEN STUDENT_ID = SUBSTRING(STUDENT_ID FROM 1 FOR POSITION(':' IN STUDENT_ID) - 1);
    STUDENT_ID = REPLACE(STUDENT_ID, '{', '');
    STUDENT_ID = REPLACE(STUDENT_ID, '}', '');
    STUDENT_ID = LOWER(STUDENT_ID);

    V$DT4 = NULL;
    SELECT MAXVALUE(L20.DATE_INS, V155.DATE_MODIFY, V1570.DATE_MODIFY)
    FROM LINKS L20
    JOIN VALS V155 ON V155.OBJ_ID = L20.OBJ_ID AND V155.PARAM_ID = 155 AND V155.IS_DEL = 0
    JOIN VALS V1570 ON V1570.OBJ_ID = L20.EXT_OBJ_ID AND V1570.PARAM_ID = 1570 AND V1570.IS_DEL = 0
    WHERE L20.PARENT_ID = :V$STUDENT_ID AND L20.OBJ_TYPE_ID = 20 AND L20.DATE_DEL IS NULL
    INTO :V$DT4;

    IF(V$TEACHER IS NULL) THEN AUTHOR = NULL; ELSE AUTHOR = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$TEACHER));
    IF(V$SUBJECT_ID IS NULL) THEN DESCRIPTION = NULL; ELSE DESCRIPTION = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$SUBJECT_ID));

    -- Определяем время начала и окончания урока - сначала через конкретное расписание, потом через какое найдется
    -- только по шаблону, даты действия которого попадают на это число
    START_DATETIME = NULL;
    END_DATETIME = NULL;
    SELECT FIRST 1 :V$DT + V405.VAL, :V$DT + V406.VAL
    FROM SCHEDULE_ITEMS SI
    JOIN LINKS L60 ON L60.PARENT_ID = SI.SCHEDULE_ID AND L60.OBJ_TYPE_ID = 60 AND L60.DATE_DEL IS NULL
    LEFT JOIN VALD V3120 ON V3120.OBJ_ID = L60.OBJ_ID AND V3120.PARAM_ID = 3120 AND V3120.IS_DEL = 0
    LEFT JOIN VALD V3121 ON V3121.OBJ_ID = L60.OBJ_ID AND V3121.PARAM_ID = 3121 AND V3121.IS_DEL = 0
    JOIN VALI V404 ON V404.OBJ_ID = L60.OBJ_ID AND V404.PARAM_ID = 404 AND V404.IS_DEL = 0 AND V404.VAL = :N
    JOIN VALT V405 ON V405.OBJ_ID = L60.OBJ_ID AND V405.PARAM_ID = 405 AND V405.IS_DEL = 0
    JOIN VALT V406 ON V406.OBJ_ID = L60.OBJ_ID AND V406.PARAM_ID = 406 AND V406.IS_DEL = 0
    WHERE SI.DATE_DEL IS NULL AND SI.CJ_ID = :V$CJ_ID AND (V3120.VAL IS NULL OR V3120.VAL <= :V$DT) AND (V3121.VAL IS NULL OR V3121.VAL >= :V$DT)
    INTO :START_DATETIME, :END_DATETIME;

    IF(START_DATETIME IS NULL) THEN
    BEGIN
      SELECT FIRST 1 :V$DT + V405.VAL, :V$DT + V406.VAL
      FROM LINKS L68
      JOIN LINKS L3 ON L3.PARENT_ID = L68.OBJ_ID AND L3.OBJ_TYPE_ID = 3 AND L3.DATE_DEL IS NULL
      JOIN LINKS L59 ON L59.PARENT_ID = L3.OBJ_ID AND L59.OBJ_TYPE_ID = 59 AND L59.DATE_DEL IS NULL
      JOIN LINKS L60 ON L60.PARENT_ID = L59.OBJ_ID AND L60.OBJ_TYPE_ID = 60 AND L60.DATE_DEL IS NULL
      LEFT JOIN VALD V3120 ON V3120.OBJ_ID = L60.OBJ_ID AND V3120.PARAM_ID = 3120 AND V3120.IS_DEL = 0
      LEFT JOIN VALD V3121 ON V3121.OBJ_ID = L60.OBJ_ID AND V3121.PARAM_ID = 3121 AND V3121.IS_DEL = 0
      JOIN VALI V404 ON V404.OBJ_ID = L60.OBJ_ID AND V404.PARAM_ID = 404 AND V404.IS_DEL = 0 AND V404.VAL = :N
      JOIN VALT V405 ON V405.OBJ_ID = L60.OBJ_ID AND V405.PARAM_ID = 405 AND V405.IS_DEL = 0
      JOIN VALT V406 ON V406.OBJ_ID = L60.OBJ_ID AND V406.PARAM_ID = 406 AND V406.IS_DEL = 0
      WHERE L68.PARENT_ID = :V$SCHOOL_ID AND L68.OBJ_TYPE_ID = 68 AND L68.DATE_DEL IS NULL
        AND (V3120.VAL IS NULL OR V3120.VAL <= :V$DT) AND (V3121.VAL IS NULL OR V3121.VAL >= :V$DT)
      INTO :START_DATETIME, :END_DATETIME;
    END

    TYPE_CODE = 'cw';
    TYPE_VALUE = 4;
    TYPE_DESCRIPTION = 'Контрольная работа';

    STATUS_CODE = 'active';
    STATUS_VALUE = 1;
    STATUS_DESCRIPTION = 'Актуально';

    IF(START_DATETIME IS NOT NULL AND
      (I$DT1 IS NULL OR V$DT1 >= I$DT1 OR V$DT2 >= I$DT1 OR V$DT3 >= I$DT1 OR V$DT4 >= I$DT1)
    )
    THEN SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_MS_GROUPSS (
    I$DT1 TIMESTAMP,
    I$DT2 TIMESTAMP NOT NULL = CURRENT_TIMESTAMP)
RETURNS (
    ID VARCHAR(60),
    EDU_GROUP_URI VARCHAR(200),
    TYPE_GROUPSS VARCHAR(60),
    NAME VARCHAR(1000),
    EDU_LOCATIONS_ID VARCHAR(60),
    IS_LAST VARCHAR(10),
    PARTOF VARCHAR(60),
    PLACES INTEGER,
    STATUS VARCHAR(60),
    REASON VARCHAR(60),
    CREATE_DATETIME TIMESTAMP,
    SEND_DATETIME TIMESTAMP)
AS
DECLARE VARIABLE V$SCHOOL_ID BIGINT;
DECLARE VARIABLE V$GP_ID BIGINT;
DECLARE VARIABLE V$Y INTEGER;
DECLARE VARIABLE V$DT1 TIMESTAMP;
DECLARE VARIABLE V$DT2 TIMESTAMP;
DECLARE VARIABLE V$DT3 TIMESTAMP;
DECLARE VARIABLE V$YDATE DATE;
DECLARE VARIABLE V$ID BIGINT;
DECLARE VARIABLE SCHOOL_ID VARCHAR(100);
DECLARE VARIABLE V VARCHAR(1000);
begin

  SEND_DATETIME = I$DT2;

  SELECT FIRST 1 L2.OBJ_ID, V1236.LISTVAL_ID, LV.COST, V9.VAL
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  JOIN VALS V9 ON V9.OBJ_ID = L2.OBJ_ID AND V9.PARAM_ID = 9 AND V9.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$SCHOOL_ID, :V$GP_ID, :V$Y, :SCHOOL_ID;

  V$YDATE = '30.08.' || V$Y;

  SELECT FIRST 1 L16.OBJ_ID
  FROM LINKS L73
  JOIN LINKS L16 ON L16.PARENT_ID = L73.OBJ_ID AND L16.OBJ_TYPE_ID = 16 AND L16.DATE_DEL IS NULL
  JOIN VALL V485 ON V485.OBJ_ID = L16.OBJ_ID AND V485.PARAM_ID = 485 AND V485.IS_DEL = 0 AND V485.LISTVAL_ID = 1093
  -- Адрес должен быть заполнен с указанием кода ФИАС
  JOIN VALA V420 ON V420.OBJ_ID = L16.OBJ_ID AND V420.PARAM_ID = 420 AND V420.IS_DEL = 0 AND V420.FIAS_UID IS NOT NULL
  -- Дата завершения эксплуатации
  LEFT JOIN VALD V3164 ON V3164.OBJ_ID = L16.OBJ_ID AND V3164.PARAM_ID = 3164 AND V3164.IS_DEL = 0
  WHERE L73.PARENT_ID = :V$SCHOOL_ID AND L73.OBJ_TYPE_ID = 73 AND L73.DATE_DEL IS NULL AND V3164.VAL IS NULL
  ORDER BY L16.OBJ_ID
  INTO :EDU_LOCATIONS_ID;

  IF(EDU_LOCATIONS_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Требуется внести главное здание ОУ и указать обязательные атрибуты, включая адрес';

  STATUS = 'active';

  FOR
    -- Сама школа
    SELECT NULL, :SCHOOL_ID, '01.01.2000', NULL, 'school', 'Учебное заведение для получения общего образования'
    FROM RDB$DATABASE
    WHERE 1 = 1
    -- Параллели
    UNION
    SELECT :SCHOOL_ID, L8.OBJ_ID, L8.DATE_MODIFY, C.CAPTION, 'parallel', 'Число классов, групп обучающихся одного возраста'
    FROM LINKS L7
    JOIN VALL V43 ON V43.OBJ_ID = L7.OBJ_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0 AND V43.LISTVAL_ID IN (22, 26, 27)
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    LEFT JOIN OBJECT_CAPTION_GET(L8.OBJ_ID) C ON 1 = 1
    WHERE L7.PARENT_ID = :V$SCHOOL_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    -- Классы
    UNION
    SELECT L9.PARENT_ID, L9.OBJ_ID, L9.DATE_MODIFY, C.CAPTION, 'class', 'Постоянный в пределах учебного года коллектив обучающихся, работающий по единой учебной программе'
    FROM LINKS L7
    JOIN VALL V43 ON V43.OBJ_ID = L7.OBJ_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0 AND V43.LISTVAL_ID IN (22, 26, 27)
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
    LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C ON 1 = 1
    WHERE L7.PARENT_ID = :V$SCHOOL_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    -- Учебные группы - только текущий учебный год
    -- Дополнительная проверка по этапу обучения
    UNION
    SELECT :SCHOOL_ID, J.GRADE_ID, J.DATE_MODIFY, J.JOURNAL_NAME, 'group', 'Обособленная часть контингента образовательного учреждения, являющаяся для ее членов первичным коллективом'
    FROM CJ2_JOURNAL J
    JOIN LISTVALS LV ON LV.LISTVAL_ID = J.STAGE_INDEX AND LV.PARENT_ID IN (2141, 12941)
    WHERE J.DATE_DEL IS NULL AND J.JOURNAL_TYPE = 0 AND J.YEAR_ID = :V$GP_ID AND J.GRADE_TYPE_ID = 179
    INTO :PARTOF, :V$ID, :V$DT1, :V, :TYPE_GROUPSS, :NAME
  DO
  BEGIN
    CREATE_DATETIME = V$DT1;

    ID = V$ID || ':' || V$Y;
    EDU_GROUP_URI = 'https://dnevnik2.petersburgedu.ru/groups/' || V$ID || '/' || V$Y;
    NAME = TRIM(NAME);
    TYPE_GROUPSS = TRIM(TYPE_GROUPSS);

    IF(I$DT1 IS NULL OR V$DT1 >= I$DT1 OR V$DT2 >= I$DT1) THEN
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_MS_HOMEWORKS (
    I$DT1 TIMESTAMP,
    I$DT2 TIMESTAMP NOT NULL = CURRENT_TIMESTAMP)
RETURNS (
    ID VARCHAR(40),
    DESCRIPTION VARCHAR(4000),
    ISSUE_DATE DATE,
    PLAN_READY_DATE DATE,
    ISSUE_LESSON_ID VARCHAR(40),
    READY_LESSON_ID VARCHAR(40),
    CREATE_DATETIME TIMESTAMP,
    SEND_DATETIME TIMESTAMP)
AS
DECLARE VARIABLE V$SCHOOL_ID BIGINT;
DECLARE VARIABLE V$GP_ID BIGINT;
DECLARE VARIABLE V$Y INTEGER;
DECLARE VARIABLE V$LESSON_ID BIGINT;
DECLARE VARIABLE V$CJ_ID BIGINT;
DECLARE VARIABLE V$DT1 TIMESTAMP;
DECLARE VARIABLE V$DT2 TIMESTAMP;
DECLARE VARIABLE N INTEGER;
DECLARE VARIABLE P INTEGER;
DECLARE VARIABLE DD DATE;
DECLARE VARIABLE S VARCHAR(20);
begin

  SEND_DATETIME = I$DT2;

  SELECT FIRST 1 L2.OBJ_ID, V1236.LISTVAL_ID, LV.COST
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$SCHOOL_ID, :V$GP_ID, :V$Y;

  -- Старую схему выгрузки больше не используем, новая схема стартует в 2025 учебном году
  IF(V$Y < 2025) THEN EXIT;

  FOR
    SELECT MSL.OBJ_ID, MSL.DATE_ADD, L.LESSON_HOMEWORK, MAXVALUE(MSL.DATE_MODIFY, L.DATE_MODIFY), L.LESSON_DATE, L.CJ_ID, MSL.LESSON_NUM
    FROM CJ2_JOURNAL J
    JOIN LISTVALS LV ON LV.LISTVAL_ID = J.STAGE_INDEX AND LV.PARENT_ID IN (2141, 12941)
    JOIN CJ2_MS_LESSONS MSL ON MSL.DATE_DEL IS NULL AND MSL.CJ_ID = J.OBJ_ID
    JOIN CJ2_JOURNAL_LESSONS L ON L.DATE_DEL IS NULL AND L.CJ_ID = J.OBJ_ID AND L.MS_ID = MSL.OBJ_ID AND (L.IS_COMPLETED = 1 OR L.IS_PUBLISHED = 1)
      AND L.LESSON_HOMEWORK IS NOT NULL AND CHAR_LENGTH(TRIM(L.LESSON_HOMEWORK)) > 2
    WHERE J.DATE_DEL IS NULL AND J.JOURNAL_TYPE = 0 AND J.YEAR_ID = :V$GP_ID
    ORDER BY 3, 1
    INTO :V$LESSON_ID, :CREATE_DATETIME, :DESCRIPTION, :V$DT1, :ISSUE_DATE, :V$CJ_ID, :N
  DO
  BEGIN
    ID = V$Y || 'X' || V$LESSON_ID;
    ISSUE_LESSON_ID = V$Y || 'X' || V$LESSON_ID;
                                                                                                               
    DESCRIPTION = TRIM(REPLACE(REPLACE(REPLACE(DESCRIPTION, ASCII_CHAR(10), ' '), ASCII_CHAR(13), ' '), '  ', ' '));
    IF(CHAR_LENGTH(DESCRIPTION) < 3) THEN DESCRIPTION = DESCRIPTION || '--';

    -- В качестве урока назначения ставим ближайший урок следующий по датам (нельзя делать ДЗ на следующий урок того же дня)
    -- Если в тексте ДЗ указана дата, то ставим на эту или ближайшую дату, в формате @@DD.MM.YYYY
    DD = NULL;
    P = POSITION('@@' IN DESCRIPTION);
    IF(P > 0) THEN
    BEGIN
      S = SUBSTRING(DESCRIPTION FROM P + 2 FOR 10);
      BEGIN
        DD = S;
        WHEN ANY DO DD = NULL;
      END
      -- Дата задания не может выходить за 31.05 или быть раньше даты урока
      -- но это проверяем при сохранении урока, а тут как получится
    END
    IF(DD IS NULL) THEN DD = DATEADD(1 DAY TO ISSUE_DATE);

    READY_LESSON_ID = NULL;
    SELECT FIRST 1 L.OBJ_ID, L.LESSON_DATE, L.DATE_MODIFY
    FROM CJ2_MS_LESSONS L
    WHERE L.DATE_DEL IS NULL AND L.CJ_ID = :V$CJ_ID AND L.LESSON_DATE >= :DD
    ORDER BY L.SEQ_INDEX
    INTO :READY_LESSON_ID, :PLAN_READY_DATE, :V$DT2;

    IF(READY_LESSON_ID IS NOT NULL AND (I$DT1 IS NULL OR V$DT1 >= I$DT1 OR V$DT2 >= I$DT1)) THEN
    BEGIN
      READY_LESSON_ID = V$Y || 'X' || READY_LESSON_ID;
      SUSPEND;
    END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_MS_HOMEWORKS_MATERIALS (
    I$DT1 TIMESTAMP,
    I$DT2 TIMESTAMP NOT NULL = CURRENT_TIMESTAMP)
RETURNS (
    HOMEWORK_ID VARCHAR(60),
    MATERIAL_ID VARCHAR(60),
    CREATE_DATETIME TIMESTAMP,
    SEND_DATETIME TIMESTAMP)
AS
DECLARE VARIABLE V$SCHOOL_ID BIGINT;
DECLARE VARIABLE V$GP_ID BIGINT;
DECLARE VARIABLE V$Y INTEGER;
DECLARE VARIABLE V$DT1 TIMESTAMP;
DECLARE VARIABLE V$DT2 TIMESTAMP;
DECLARE VARIABLE V$DT3 TIMESTAMP;
DECLARE VARIABLE V$PERSON_ID BIGINT;
begin

  SEND_DATETIME = I$DT2;

  SELECT FIRST 1 L2.OBJ_ID, V1236.LISTVAL_ID, LV.COST
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$SCHOOL_ID, :V$GP_ID, :V$Y;

  -- Старую схему выгрузки больше не используем, новая схема стартует в 2025 учебном году
  IF(V$Y < 2025) THEN EXIT;

  FOR
    SELECT MSL.OBJ_ID, B.OBJ_ID, B.DATE_ADD, MAXVALUE(MSL.DATE_MODIFY, L.DATE_MODIFY, B.DATE_MODIFY)
    FROM CJ2_JOURNAL J
    JOIN LISTVALS LV ON LV.LISTVAL_ID = J.STAGE_INDEX AND LV.PARENT_ID IN (2141, 12941)
    JOIN CJ2_MS_LESSONS MSL ON MSL.DATE_DEL IS NULL AND MSL.CJ_ID = J.OBJ_ID
    JOIN CJ2_JOURNAL_LESSONS L ON L.DATE_DEL IS NULL AND L.CJ_ID = J.OBJ_ID AND L.MS_ID = MSL.OBJ_ID AND (L.IS_COMPLETED = 1 OR L.IS_PUBLISHED = 1)
      AND L.LESSON_HOMEWORK IS NOT NULL AND CHAR_LENGTH(TRIM(L.LESSON_HOMEWORK)) > 2
    JOIN CJ2_BLOB B ON B.DATE_DEL IS NULL AND B.LESSON_ID = L.OBJ_ID AND B.FILE_TYPE = 0
    WHERE J.DATE_DEL IS NULL AND J.JOURNAL_TYPE = 0 AND J.YEAR_ID = :V$GP_ID
    ORDER BY 1
    INTO :HOMEWORK_ID, :MATERIAL_ID, :CREATE_DATETIME, :V$DT1
  DO
  BEGIN
    HOMEWORK_ID = V$Y || 'X' || HOMEWORK_ID;

    -- Проверку на существование урока назначения не делаем, чтобы не жрать ресурсы

    IF(I$DT1 IS NULL OR V$DT1 >= I$DT1) THEN
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_MS_HOMEWORKS_STUDENTS (
    I$DT1 TIMESTAMP,
    I$DT2 TIMESTAMP NOT NULL = CURRENT_TIMESTAMP)
RETURNS (
    HOMEWORK_ID VARCHAR(40),
    STUDENT_ID VARCHAR(60),
    CREATE_DATETIME TIMESTAMP,
    SEND_DATETIME TIMESTAMP)
AS
DECLARE VARIABLE V$SCHOOL_ID BIGINT;
DECLARE VARIABLE V$GP_ID BIGINT;
DECLARE VARIABLE V$Y INTEGER;
DECLARE VARIABLE V$DT1 TIMESTAMP;
DECLARE VARIABLE V$DT2 TIMESTAMP;
DECLARE VARIABLE V$DT3 TIMESTAMP;
DECLARE VARIABLE V$DT1X TIMESTAMP;
DECLARE VARIABLE V$GROUP_ID BIGINT;
DECLARE VARIABLE V$LD DATE;
DECLARE VARIABLE V$PERSON_ID BIGINT;
DECLARE VARIABLE V$LESSON_ID BIGINT;
DECLARE VARIABLE V$CJ_ID BIGINT;
DECLARE VARIABLE READY_LESSON_ID BIGINT;
DECLARE VARIABLE P INTEGER;
DECLARE VARIABLE S VARCHAR(40);
DECLARE VARIABLE DD DATE;
DECLARE VARIABLE HW VARCHAR(1000);
begin

  SEND_DATETIME = I$DT2;

  SELECT FIRST 1 L2.OBJ_ID, V1236.LISTVAL_ID, LV.COST
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$SCHOOL_ID, :V$GP_ID, :V$Y;

  -- Старую схему выгрузки больше не используем, новая схема стартует в 2025 учебном году
  IF(V$Y < 2025) THEN EXIT;

  FOR
    SELECT MSL.OBJ_ID, MAXVALUE(MSL.DATE_MODIFY, L.DATE_MODIFY), J.GRADE_ID, L.LESSON_DATE, L.CJ_ID, L.LESSON_HOMEWORK
    FROM CJ2_JOURNAL J
    JOIN CJ2_MS_LESSONS MSL ON MSL.DATE_DEL IS NULL AND MSL.CJ_ID = J.OBJ_ID
    JOIN CJ2_JOURNAL_LESSONS L ON L.DATE_DEL IS NULL AND L.CJ_ID = J.OBJ_ID AND L.MS_ID = MSL.OBJ_ID AND (L.IS_COMPLETED = 1 OR L.IS_PUBLISHED = 1)
      AND L.LESSON_HOMEWORK IS NOT NULL AND CHAR_LENGTH(TRIM(L.LESSON_HOMEWORK)) > 2
    JOIN LISTVALS LV ON LV.LISTVAL_ID = J.STAGE_INDEX AND LV.PARENT_ID IN (2141, 12941)
    WHERE J.DATE_DEL IS NULL AND J.JOURNAL_TYPE = 0 AND J.YEAR_ID = :V$GP_ID
    ORDER BY 4, 1
    INTO :V$LESSON_ID, :V$DT1, :V$GROUP_ID, :V$LD, :V$CJ_ID, :HW
  DO
  BEGIN

    HOMEWORK_ID = V$Y || 'X' || V$LESSON_ID;

    DD = NULL;
    P = POSITION('@@' IN HW);
    IF(P > 0) THEN
    BEGIN
      S = SUBSTRING(HW FROM P + 2 FOR 10);
      BEGIN
        DD = S;
        WHEN ANY DO DD = NULL;
      END
      -- Дата задания не может выходить за 31.05 или быть раньше даты урока
      -- но это проверяем при сохранении урока, а тут как получится
    END
    IF(DD IS NULL) THEN DD = DATEADD(1 DAY TO V$LD);

    READY_LESSON_ID = NULL;
    SELECT FIRST 1 L.OBJ_ID, L.DATE_MODIFY
    FROM CJ2_MS_LESSONS L
    WHERE L.DATE_DEL IS NULL AND L.CJ_ID = :V$CJ_ID AND L.LESSON_DATE >= :DD
    ORDER BY L.SEQ_INDEX
    INTO :READY_LESSON_ID, :V$DT1X;

    CREATE_DATETIME = V$DT1;

    IF(READY_LESSON_ID IS NOT NULL) THEN
    FOR
      SELECT M.PERSON_ID, V2912.SVAL, MAX(V2912.DATE_MODIFY), MAX(M.DATE_MODIFY)
      FROM PERSON_MOVEMENTS M
      JOIN VALS V2912 ON V2912.OBJ_ID = M.PERSON_ID AND V2912.PARAM_ID = 2912 AND V2912.IS_DEL = 0
      WHERE M.DATE_DEL IS NULL AND M.GROUP_ID = :V$GROUP_ID AND M.DATE_IN <= :DD AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :DD) AND M.LEVEL_ID IN (22, 26, 27)
      GROUP BY 1, 2
      ORDER BY 1
      INTO :V$PERSON_ID, :STUDENT_ID, :V$DT2, :V$DT3
    DO
    BEGIN
      IF(I$DT1 IS NULL OR V$DT1 >= I$DT1 OR V$DT1X >= I$DT1 OR V$DT2 >= I$DT1 OR V$DT3 >= I$DT1) THEN
      BEGIN
        IF(POSITION(':' IN STUDENT_ID) > 0) THEN STUDENT_ID = SUBSTRING(STUDENT_ID FROM 1 FOR POSITION(':' IN STUDENT_ID) - 1);
        STUDENT_ID = REPLACE(STUDENT_ID, '{', '');
        STUDENT_ID = REPLACE(STUDENT_ID, '}', '');
        STUDENT_ID = LOWER(STUDENT_ID);

        SUSPEND;
      END
    END

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_MS_LESSONS (
    I$DT1 TIMESTAMP,
    I$DT2 TIMESTAMP NOT NULL = CURRENT_TIMESTAMP)
RETURNS (
    ID VARCHAR(40),
    PERIOD_ID VARCHAR(40),
    CLASS_ID VARCHAR(40),
    EDU_LOCATIONS_ID VARCHAR(40),
    SUBJECT_ID VARCHAR(40),
    START_DATETIME TIMESTAMP,
    END_DATETIME TIMESTAMP,
    ROOM VARCHAR(400),
    TEACHER_ID VARCHAR(60),
    ACTIVE VARCHAR(10),
    DESCRIPTION VARCHAR(1000),
    THEME VARCHAR(1000),
    IS_DISTANT SMALLINT,
    LINK VARCHAR(1000),
    SUBJECT_NAME VARCHAR(1000),
    LESSON_PLAN_ID VARCHAR(100),
    LESSON_TYPE SMALLINT,
    CREATE_DATETIME TIMESTAMP,
    SEND_DATETIME TIMESTAMP)
AS
DECLARE VARIABLE V$SCHOOL_ID BIGINT;
DECLARE VARIABLE V$GP_ID BIGINT;
DECLARE VARIABLE V$Y INTEGER;
DECLARE VARIABLE V$PERIOD_ID BIGINT;
DECLARE VARIABLE V$DATE DATE;
DECLARE VARIABLE V$T TIME;
DECLARE VARIABLE V$TEACHER_ID BIGINT;
DECLARE VARIABLE V$N INTEGER;
DECLARE VARIABLE V$PD BIGINT;
DECLARE VARIABLE V$CJ_ID BIGINT;
DECLARE VARIABLE V$DT1 TIMESTAMP;
DECLARE VARIABLE V$DT2 TIMESTAMP;
DECLARE VARIABLE V$DT3 TIMESTAMP;
DECLARE VARIABLE V$ID BIGINT;
DECLARE VARIABLE V$CT BIGINT;
DECLARE VARIABLE V$CLASS_ID BIGINT;
DECLARE VARIABLE V$GROUP_ID BIGINT;
DECLARE VARIABLE V$GTYPE BIGINT;
DECLARE VARIABLE V$YEARDATE DATE;
DECLARE VARIABLE H FLOAT;
DECLARE VARIABLE T INTEGER;
begin

  SEND_DATETIME = I$DT2;

  SELECT FIRST 1 L2.OBJ_ID, V1236.LISTVAL_ID, LV.COST
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$SCHOOL_ID, :V$GP_ID, :V$Y;

  SELECT FIRST 1 L16.OBJ_ID
  FROM LINKS L73
  JOIN LINKS L16 ON L16.PARENT_ID = L73.OBJ_ID AND L16.OBJ_TYPE_ID = 16 AND L16.DATE_DEL IS NULL
  JOIN VALL V485 ON V485.OBJ_ID = L16.OBJ_ID AND V485.PARAM_ID = 485 AND V485.IS_DEL = 0 AND V485.LISTVAL_ID = 1093
  -- Адрес должен быть заполнен с указанием кода ФИАС
  JOIN VALA V420 ON V420.OBJ_ID = L16.OBJ_ID AND V420.PARAM_ID = 420 AND V420.IS_DEL = 0 AND V420.FIAS_UID IS NOT NULL
  -- Дата завершения эксплуатации
  LEFT JOIN VALD V3164 ON V3164.OBJ_ID = L16.OBJ_ID AND V3164.PARAM_ID = 3164 AND V3164.IS_DEL = 0
  WHERE L73.PARENT_ID = :V$SCHOOL_ID AND L73.OBJ_TYPE_ID = 73 AND L73.DATE_DEL IS NULL AND V3164.VAL IS NULL
  ORDER BY L16.OBJ_ID
  INTO :EDU_LOCATIONS_ID;

  IF(EDU_LOCATIONS_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Требуется внести главное здание ОУ и указать обязательные атрибуты, включая адрес';

  -- Старую схему выгрузки больше не используем, новая схема стартует в 2025 учебном году
  IF(V$Y < 2025) THEN EXIT;

  -- Приход в класс смотрим не ранее 20 августа - если раньше, это будет конкретный косяк школы
  V$YEARDATE = '20.08.' || V$Y;

  "ACTIVE" = 'true';

  FOR
    SELECT MSL.OBJ_ID, L.LESSON_PTP_ID, J.OBJ_ID, MSL.DATE_ADD, J.SUBJECT_ID, SC.CAPTION, J.PERIOD_ID, MSL.LESSON_DATE, MSL.LESSON_NUM, MSL.LESSON_TIME,
      COALESCE(L.LESSON_THEME, '----'), L.TEACHER_ID, J.GRADE_ID, J.GRADE_TYPE_ID, L.LESSON_HOURS, MAXVALUE(MSL.DATE_MODIFY, L.DATE_MODIFY)
    FROM CJ2_JOURNAL J
    LEFT JOIN OBJECT_CAPTION_GET(J.SUBJECT_ID) SC ON 1 = 1
    JOIN CJ2_MS_LESSONS MSL ON MSL.DATE_DEL IS NULL AND MSL.CJ_ID = J.OBJ_ID
    -- статус проведения не смотрим, если связывание случилось - назад дороги нет
    -- дата, номер и время уроков в ленте расписания и в самом уроке должны совпадать
    LEFT JOIN CJ2_JOURNAL_LESSONS L ON L.DATE_DEL IS NULL AND L.CJ_ID = J.OBJ_ID AND L.MS_ID = MSL.OBJ_ID
    WHERE J.DATE_DEL IS NULL AND J.JOURNAL_TYPE = 0 AND J.YEAR_ID = :V$GP_ID
    ORDER BY 1
    INTO :V$ID, :LESSON_PLAN_ID, :V$CJ_ID, :CREATE_DATETIME, :SUBJECT_ID, :SUBJECT_NAME, :V$PERIOD_ID, :V$DATE, :V$N, :V$T,
      :THEME, :V$TEACHER_ID, :V$GROUP_ID, :V$GTYPE, :H, :V$DT1
  DO
  BEGIN
    -- Новый формат ID
    ID = V$Y || 'X' || V$ID;

    CLASS_ID = NULL;
    IF(V$GTYPE = 9) THEN V$CLASS_ID = V$GROUP_ID;
    ELSE
    BEGIN
      -- Тут будут только текущие коллективы, поэтому за дату прихода можно не беспокоиться
      -- берем класс, где больше всего учеников из данной группы, иначе при переходах не разобраться
      -- но скорость выборки будет адовая
      SELECT FIRST 1 M2.GROUP_ID, COUNT(*)
      FROM PERSON_MOVEMENTS M
      JOIN PERSON_MOVEMENTS M2 ON M2.DATE_DEL IS NULL AND M2.PERSON_ID = M.PERSON_ID AND M2.GROUP_TYPE_ID = 9 AND M2.DATE_IN >= :V$YEARDATE
      WHERE M.DATE_DEL IS NULL AND M.GROUP_ID = :V$GROUP_ID
      GROUP BY 1
      ORDER BY 2 DESC
      INTO :V$CLASS_ID, :T;
    END
    CLASS_ID = V$CLASS_ID || 'Y' || V$Y;

    V$PD = NULL;
    SELECT FIRST 1 V1170.LISTVAL_ID, MAXVALUE(V1169.DATE_MODIFY, V1174.DATE_MODIFY, V1170.DATE_MODIFY)
    FROM LINKS L154
    JOIN VALD V1169 ON V1169.OBJ_ID = L154.OBJ_ID AND V1169.PARAM_ID = 1169 AND V1169.IS_DEL = 0 AND V1169.VAL <= :V$DATE
    JOIN VALD V1174 ON V1174.OBJ_ID = L154.OBJ_ID AND V1174.PARAM_ID = 1174 AND V1174.IS_DEL = 0 AND V1174.VAL >= :V$DATE
    JOIN VALL V1170 ON V1170.OBJ_ID = L154.OBJ_ID AND V1170.PARAM_ID = 1170 AND V1170.IS_DEL = 0
    WHERE L154.PARENT_ID = :V$PERIOD_ID AND L154.OBJ_TYPE_ID = 154 AND L154.DATE_DEL IS NULL
    INTO :V$PD, :V$DT2;

    -- Если урок поставлен черти как
    IF(V$PD IS NULL) THEN 
    SELECT FIRST 1 V1170.LISTVAL_ID, MAXVALUE(V1169.DATE_MODIFY, V1174.DATE_MODIFY, V1170.DATE_MODIFY)
    FROM LINKS L154
    JOIN VALD V1169 ON V1169.OBJ_ID = L154.OBJ_ID AND V1169.PARAM_ID = 1169 AND V1169.IS_DEL = 0
    JOIN VALD V1174 ON V1174.OBJ_ID = L154.OBJ_ID AND V1174.PARAM_ID = 1174 AND V1174.IS_DEL = 0
    JOIN VALL V1170 ON V1170.OBJ_ID = L154.OBJ_ID AND V1170.PARAM_ID = 1170 AND V1170.IS_DEL = 0
    WHERE L154.PARENT_ID = :V$PERIOD_ID AND L154.OBJ_TYPE_ID = 154 AND L154.DATE_DEL IS NULL
    ORDER BY IIF(V1169.VAL <= :V$DATE, 0, 1), V1169.VAL DESC
    INTO :V$PD, :V$DT2;

    IF(V$PD IS NULL) THEN EXCEPTION DATA_ERROR 'В уроке ' || ID || ' не удалось привязаться к периоду обучения';

    IF(V$PD IN (12, 13, 14, 15)) THEN PERIOD_ID = V$Y || '-Q' || (V$PD - 12 + 1);
    ELSE IF(V$PD IN (10, 11)) THEN PERIOD_ID = V$Y || '-H' || (V$PD - 10 + 1);
    ELSE IF(V$PD IN (16, 17, 18)) THEN PERIOD_ID = V$Y || '-T' || (V$PD - 16 + 1);
    ELSE IF(V$PD IN (19, 20)) THEN PERIOD_ID = V$Y || '-S' || (V$PD - 10 + 1);

    TEACHER_ID = NULL;
    SELECT LOWER(REPLACE(REPLACE(V.VAL, '{', ''), '}', '')), V.DATE_MODIFY
    FROM VALS V
    WHERE V.OBJ_ID = :V$TEACHER_ID AND V.PARAM_ID = 2915 AND V.IS_DEL = 0
    INTO :TEACHER_ID, :V$DT3;
    IF(POSITION(':' IN TEACHER_ID) > 0) THEN TEACHER_ID = SUBSTRING(TEACHER_ID FROM 1 FOR POSITION(':' IN TEACHER_ID) - 1);

    -- тип урока
    SELECT FIRST 1 C.CONTROL_TYPE_ID
    FROM CJ2_CONTROL C
    WHERE C.DATE_DEL IS NULL AND C.LESSON_ID = :V$ID AND C.CONTROL_TYPE_ID > 0
    INTO :V$CT;

    LESSON_TYPE = 0; -- default
    IF(V$CT IN (1084, 1085, 1087, 1091)) THEN LESSON_TYPE = 1; -- контрольная
    ELSE IF(V$CT = 1065) THEN LESSON_TYPE = 2; -- самостоятельная
    ELSE IF(V$CT = 1083) THEN LESSON_TYPE = 3; -- диктант
    ELSE IF(V$CT IN (1088, 1089)) THEN LESSON_TYPE = 4; -- сочинение
    ELSE IF(V$CT = 3160) THEN LESSON_TYPE = 5; -- изложение
    ELSE IF(V$CT = 1069) THEN LESSON_TYPE = 6; -- лабораторная
    ELSE IF(V$CT = 11204) THEN LESSON_TYPE = 7; -- практическая
    -- 8 ВПР

    -- Время - больше не надо лазать в расписание
    -- но пока оставим что время всегда 45 минут, даже в 1 классе
    -- если в уроке стоит длительность, и она больше часа - выдаем ее как указано
    START_DATETIME = V$DATE + V$T;
    IF(H > 1) THEN END_DATETIME = DATEADD(H HOUR TO START_DATETIME);
    ELSE END_DATETIME = DATEADD(45 MINUTE TO START_DATETIME);

    IF(START_DATETIME IS NULL) THEN EXCEPTION DATA_ERROR 'В уроке ' || ID || ' не удалось найти сетку уроков';

    -- Изменение: план делаем индивидуальным в каждом журнале
    LESSON_PLAN_ID = V$CJ_ID || ':' || LESSON_PLAN_ID;

    -- Ограничиваем выдачу по CLASS_ID - в конце года могут быть чудеса при переходах и выбытиях
    IF(CLASS_ID IS NOT NULL) THEN
    IF(I$DT1 IS NULL OR V$DT1 >= I$DT1 OR V$DT2 >= I$DT1 OR V$DT3 >= I$DT1) THEN
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_MS_LESSONSCOUNT (
    I$DT1 TIMESTAMP,
    I$DT2 TIMESTAMP NOT NULL = current_timestamp)
RETURNS (
    SUBJECT_ID BIGINT,
    PERIOD_ID VARCHAR(20),
    STUDENT_ID VARCHAR(60),
    CLASS_ID VARCHAR(40),
    LESSONS_COUNT INTEGER,
    ALLOWED_SKIPPINGS_COUNT INTEGER,
    NOT_ALLOWED_SKIPPINGS_COUNT INTEGER,
    SICK_DAY_COUNT INTEGER,
    LATENESS_COUNT INTEGER,
    SUBJECT_NAME VARCHAR(400),
    CREATE_DATETIME TIMESTAMP,
    SEND_DATETIME TIMESTAMP)
AS
declare variable SCHOOL_ID varchar(40);
declare variable V$SCHOOL_ID bigint;
declare variable V$GY_ID bigint;
declare variable V$Y integer;
declare variable V$YSTART date;
declare variable V$YEND date;
declare variable V$STUDENT_ID bigint;
declare variable V$CLASS_ID bigint;
declare variable V$PERIOD_ID bigint;
declare variable PERIOD_NUM integer;
declare variable V$DT1 timestamp;
declare variable V$DT2 timestamp;
declare variable V$DT3 timestamp;
declare variable V$DT4 timestamp;
begin

  -- Данные только по текущему учебному году

  CREATE_DATETIME = I$DT2;
  SEND_DATETIME = I$DT2;

  SELECT FIRST 1 L2.OBJ_ID, V1236.LISTVAL_ID, LV.COST, V9.VAL
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  JOIN VALS V9 ON V9.OBJ_ID = L2.OBJ_ID AND V9.PARAM_ID = 9 AND V9.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$SCHOOL_ID, :V$GY_ID, :V$Y, :SCHOOL_ID;

  V$YSTART = '01.09.' || V$Y;
  V$YEND = '31.08.' || (V$Y + 1);

  IF(V$SCHOOL_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Объект школы не найден';

  FOR
    SELECT M.PERSON_ID, V2912.SVAL, M.GROUP_ID, MAX(M.DATE_MODIFY), MAX(V2912.DATE_MODIFY)
    FROM PERSON_MOVEMENTS M
    JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID IN (9, 125, 187)
    JOIN VALS V2912 ON V2912.OBJ_ID = M.PERSON_ID AND V2912.PARAM_ID = 2912 AND V2912.IS_DEL = 0
    WHERE M.DATE_DEL IS NULL AND M.DATE_IN <= :V$YEND AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :V$YSTART)
      AND EXISTS(
        SELECT FIRST 1 1
        FROM LINKS LPG
        WHERE LPG.OBJ_ID = M.PERSON_ID AND LPG.PARENT_TYPE_ID IN (9, 125, 187) AND LPG.DATE_DEL IS NULL
      )
      /*
      AND EXISTS(
        SELECT FIRST 1 1
        FROM LINKS L20
        JOIN VALS V155 ON V155.OBJ_ID = L20.OBJ_ID AND V155.PARAM_ID = 155 AND V155.IS_DEL = 0
        JOIN VALS V1570 ON V1570.OBJ_ID = L20.EXT_OBJ_ID AND V1570.PARAM_ID = 1570 AND V1570.IS_DEL = 0
        WHERE L20.PARENT_ID = M.PERSON_ID AND L20.OBJ_TYPE_ID = 20 AND L20.DATE_DEL IS NULL
      )
      */
    GROUP BY 1, 2, 3
    ORDER BY 1
    INTO :V$STUDENT_ID, :STUDENT_ID, :V$CLASS_ID, :V$DT1, :V$DT2
  DO
  BEGIN
    IF(POSITION(':' IN STUDENT_ID) > 0) THEN STUDENT_ID = SUBSTRING(STUDENT_ID FROM 1 FOR POSITION(':' IN STUDENT_ID) - 1);
    STUDENT_ID = REPLACE(STUDENT_ID, '{', '');
    STUDENT_ID = REPLACE(STUDENT_ID, '}', '');
    STUDENT_ID = LOWER(STUDENT_ID);

    CLASS_ID = V$CLASS_ID || 'Y' || V$Y;

    V$DT3 = NULL;
    SELECT MAX(MAXVALUE(L20.DATE_INS, V155.DATE_MODIFY, V1570.DATE_MODIFY))
    FROM LINKS L20
    JOIN VALS V155 ON V155.OBJ_ID = L20.OBJ_ID AND V155.PARAM_ID = 155 AND V155.IS_DEL = 0
    JOIN VALS V1570 ON V1570.OBJ_ID = L20.EXT_OBJ_ID AND V1570.PARAM_ID = 1570 AND V1570.IS_DEL = 0
    WHERE L20.PARENT_ID = :V$STUDENT_ID AND L20.OBJ_TYPE_ID = 20 AND L20.DATE_DEL IS NULL
    INTO :V$DT3;

    FOR
      SELECT V1170.LISTVAL_ID, J.SUBJECT_ID, MAX(MAXVALUE(V1170.DATE_MODIFY, V1169.DATE_MODIFY, V1174.DATE_MODIFY, J.DATE_MODIFY, M.DATE_MODIFY))
      FROM PERSON_MOVEMENTS M
      JOIN PERSON_MOVEMENTS MG ON MG.DATE_DEL IS NULL AND MG.PERSON_ID = M.PERSON_ID
        AND (MG.DATE_IN <= M.DATE_OUT OR M.DATE_OUT IS NULL)
        AND ((M.DATE_OUT IS NULL AND MG.DATE_OUT IS NULL) OR (M.DATE_OUT IS NOT NULL AND (MG.DATE_OUT IS NULL OR MG.DATE_OUT >= M.DATE_IN)))
      JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.JOURNAL_TYPE = 0 AND J.GRADE_ID = MG.GROUP_ID AND J.YEAR_ID = :V$GY_ID
      JOIN LINKS L154 ON L154.PARENT_ID = J.PERIOD_ID AND L154.OBJ_TYPE_ID = 154 AND L154.DATE_DEL IS NULL
      JOIN VALL V1170 ON V1170.OBJ_ID = L154.OBJ_ID AND V1170.PARAM_ID = 1170 AND V1170.IS_DEL = 0
      JOIN VALD V1169 ON V1169.OBJ_ID = L154.OBJ_ID AND V1169.PARAM_ID = 1169 AND V1169.IS_DEL = 0
      JOIN VALD V1174 ON V1174.OBJ_ID = L154.OBJ_ID AND V1174.PARAM_ID = 1174 AND V1174.IS_DEL = 0
      -- Надо ли фильтровать периоды, где ученик был в школе ?
      -- ...
      WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :V$STUDENT_ID AND M.GROUP_ID = :V$CLASS_ID
        AND M.DATE_IN <= :V$YEND AND (M.DATE_OUT IS NULL OR M.DATE_IN >= :V$YSTART)
      GROUP BY 1, 2
      ORDER BY 1, 2
      INTO :V$PERIOD_ID, :SUBJECT_ID, :V$DT4
    DO
    BEGIN
      SUBJECT_NAME = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:SUBJECT_ID));

      IF(V$PERIOD_ID IN (12, 13, 14, 15)) THEN BEGIN
        PERIOD_NUM = V$PERIOD_ID - 12 + 1;
        PERIOD_ID = V$Y || '-Q' || PERIOD_NUM;
      END
      ELSE IF(V$PERIOD_ID IN (10, 11)) THEN BEGIN
        PERIOD_NUM = V$PERIOD_ID - 10 + 1;
        PERIOD_ID = V$Y || '-H' || PERIOD_NUM;
      END
      ELSE IF(V$PERIOD_ID IN (16, 17, 18)) THEN BEGIN
        PERIOD_NUM = V$PERIOD_ID - 16 + 1;
        PERIOD_ID = V$Y || '-T' || PERIOD_NUM;
      END
      -- семестры ?!!!

      SELECT COUNT(DISTINCT L.OBJ_ID), SUM(IIF(M1.MARK_ID IS NULL, 0, 1)), SUM(IIF(M2.MARK_ID IS NULL, 0, 1)), SUM(IIF(M3.MARK_ID IS NULL, 0, 1)), SUM(IIF(M4.MARK_ID IS NULL, 0, 1))
      FROM PERSON_MOVEMENTS M
      JOIN PERSON_MOVEMENTS MG ON MG.DATE_DEL IS NULL AND MG.PERSON_ID = M.PERSON_ID
        AND (MG.DATE_IN <= M.DATE_OUT OR M.DATE_OUT IS NULL)
        AND ((M.DATE_OUT IS NULL AND MG.DATE_OUT IS NULL) OR (M.DATE_OUT IS NOT NULL AND (MG.DATE_OUT IS NULL OR MG.DATE_OUT >= M.DATE_IN)))
      JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.JOURNAL_TYPE = 0 AND J.GRADE_ID = MG.GROUP_ID AND J.YEAR_ID = :V$GY_ID AND J.SUBJECT_ID = :SUBJECT_ID
      JOIN LINKS L154 ON L154.PARENT_ID = J.PERIOD_ID AND L154.OBJ_TYPE_ID = 154 AND L154.DATE_DEL IS NULL
      JOIN VALL V1170 ON V1170.OBJ_ID = L154.OBJ_ID AND V1170.PARAM_ID = 1170 AND V1170.IS_DEL = 0 AND V1170.LISTVAL_ID = :V$PERIOD_ID
      JOIN VALD V1169 ON V1169.OBJ_ID = L154.OBJ_ID AND V1169.PARAM_ID = 1169 AND V1169.IS_DEL = 0
      JOIN VALD V1174 ON V1174.OBJ_ID = L154.OBJ_ID AND V1174.PARAM_ID = 1174 AND V1174.IS_DEL = 0
      -- Урок в диапазоне дат периода, и в диапазоне дат присутствия ученика
      JOIN CJ2_JOURNAL_LESSONS L ON L.DATE_DEL IS NULL AND L.CJ_ID = J.OBJ_ID AND L.IS_COMPLETED = 1 AND L.LESSON_DATE >= V1169.VAL AND L.LESSON_DATE <= V1174.VAL
        AND L.LESSON_DATE >= MG.DATE_IN AND (MG.DATE_OUT IS NULL OR L.LESSON_DATE <= MG.DATE_OUT)
      JOIN CJ2_CONTROL C ON C.DATE_DEL IS NULL AND C.LESSON_ID = L.OBJ_ID AND C.CONTROL_TYPE_ID = 0
      LEFT JOIN CJ2_MARK M1 ON M1.DATE_DEL IS NULL AND M1.CONTROL_ID = C.CONTROL_ID AND M1.STUDENT_ID = M.PERSON_ID AND M1.MARK_TYPE_ID = 90 -- опоздал
      LEFT JOIN CJ2_MARK M2 ON M2.DATE_DEL IS NULL AND M2.CONTROL_ID = C.CONTROL_ID AND M2.STUDENT_ID = M.PERSON_ID AND M2.MARK_TYPE_ID = 93 -- уважительная
      LEFT JOIN CJ2_MARK M3 ON M3.DATE_DEL IS NULL AND M3.CONTROL_ID = C.CONTROL_ID AND M3.STUDENT_ID = M.PERSON_ID AND M3.MARK_TYPE_ID+0 IN (91, 94) -- неуважительная
      LEFT JOIN CJ2_MARK M4 ON M4.DATE_DEL IS NULL AND M4.CONTROL_ID = C.CONTROL_ID AND M4.STUDENT_ID = M.PERSON_ID AND M4.MARK_TYPE_ID = 92 -- болезнь
      WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :V$STUDENT_ID AND M.GROUP_ID = :V$CLASS_ID
        AND M.DATE_IN <= :V$YEND AND (M.DATE_OUT IS NULL OR M.DATE_IN >= :V$YSTART)
      INTO :LESSONS_COUNT, :LATENESS_COUNT, :ALLOWED_SKIPPINGS_COUNT, :NOT_ALLOWED_SKIPPINGS_COUNT, :SICK_DAY_COUNT;

      LATENESS_COUNT = COALESCE(LATENESS_COUNT, 0);
      ALLOWED_SKIPPINGS_COUNT = COALESCE(ALLOWED_SKIPPINGS_COUNT, 0);
      NOT_ALLOWED_SKIPPINGS_COUNT = COALESCE(NOT_ALLOWED_SKIPPINGS_COUNT, 0);
      SICK_DAY_COUNT = COALESCE(SICK_DAY_COUNT, 0);

      IF(I$DT1 IS NULL OR V$DT1 >= I$DT1 OR V$DT2 >= I$DT1 OR V$DT3 >= I$DT1 OR V$DT4 >= I$DT1) THEN
      SUSPEND;

    END
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_MS_LESSONS_MARKS (
    I$DT1 TIMESTAMP,
    I$DT2 TIMESTAMP NOT NULL = CURRENT_TIMESTAMP)
RETURNS (
    LESSON_ID VARCHAR(40),
    MARK_ID VARCHAR(40),
    CREATE_DATETIME TIMESTAMP,
    SEND_DATETIME TIMESTAMP)
AS
DECLARE VARIABLE V$SCHOOL_ID BIGINT;
DECLARE VARIABLE V$GP_ID BIGINT;
DECLARE VARIABLE V$Y INTEGER;
DECLARE VARIABLE V$DT1 TIMESTAMP;
DECLARE VARIABLE V$DT2 TIMESTAMP;
DECLARE VARIABLE V$DT3 TIMESTAMP;
DECLARE VARIABLE V$PERSON_ID BIGINT;
begin

  SEND_DATETIME = I$DT2;

  SELECT FIRST 1 L2.OBJ_ID, V1236.LISTVAL_ID, LV.COST
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$SCHOOL_ID, :V$GP_ID, :V$Y;

  -- Старую схему выгрузки больше не используем, новая схема стартует в 2025 учебном году
  IF(V$Y < 2025) THEN EXIT;

  FOR
    SELECT MSL.OBJ_ID, M.MARK_ID, M.STUDENT_ID, MAXVALUE(MSL.DATE_MODIFY, L.DATE_MODIFY), M.DATE_MODIFY, V2912.DATE_MODIFY
    FROM CJ2_JOURNAL J
    JOIN LISTVALS LV ON LV.LISTVAL_ID = J.STAGE_INDEX AND LV.PARENT_ID IN (2141, 12941)
    JOIN CJ2_MS_LESSONS MSL ON MSL.DATE_DEL IS NULL AND MSL.CJ_ID = J.OBJ_ID
    JOIN CJ2_JOURNAL_LESSONS L ON L.DATE_DEL IS NULL AND L.CJ_ID = J.OBJ_ID AND L.MS_ID = MSL.OBJ_ID AND (L.IS_COMPLETED = 1 OR L.IS_PUBLISHED = 1)
    JOIN CJ2_CONTROL C ON C.DATE_DEL IS NULL AND C.LESSON_ID = L.OBJ_ID AND C.CONTROL_TYPE_ID <> 0
    JOIN CJ2_MARK M ON M.DATE_DEL IS NULL AND M.CONTROL_ID = C.CONTROL_ID
    -- Есть регид
    JOIN VALS V2912 ON V2912.OBJ_ID = M.STUDENT_ID AND V2912.PARAM_ID = 2912 AND V2912.IS_DEL = 0
    WHERE J.DATE_DEL IS NULL AND J.JOURNAL_TYPE = 0 AND J.YEAR_ID = :V$GP_ID
      AND EXISTS(
        SELECT FIRST 1 1
        FROM LINKS LPG
        WHERE LPG.OBJ_ID = M.STUDENT_ID AND LPG.PARENT_TYPE_ID IN (9, 125, 187) AND LPG.DATE_DEL IS NULL
      )
    ORDER BY 2
    INTO :LESSON_ID, :MARK_ID, :V$PERSON_ID, :V$DT1, :V$DT2, :V$DT3
  DO
  BEGIN
    LESSON_ID = V$Y || 'X' || LESSON_ID;
    CREATE_DATETIME = V$DT2;

    IF(I$DT1 IS NULL OR V$DT1 >= I$DT1 OR V$DT2 >= I$DT1 OR V$DT3 >= I$DT1) THEN
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_MS_LESSONS_MATERIALS (
    I$DT1 TIMESTAMP,
    I$DT2 TIMESTAMP NOT NULL = CURRENT_TIMESTAMP)
RETURNS (
    LESSON_ID VARCHAR(60),
    MATERIAL_ID VARCHAR(60),
    CREATE_DATETIME TIMESTAMP,
    SEND_DATETIME TIMESTAMP)
AS
DECLARE VARIABLE V$SCHOOL_ID BIGINT;
DECLARE VARIABLE V$GP_ID BIGINT;
DECLARE VARIABLE V$Y INTEGER;
DECLARE VARIABLE V$DT1 TIMESTAMP;
DECLARE VARIABLE V$DT2 TIMESTAMP;
DECLARE VARIABLE V$DT3 TIMESTAMP;
DECLARE VARIABLE V$PERSON_ID BIGINT;
begin

  SEND_DATETIME = I$DT2;

  SELECT FIRST 1 L2.OBJ_ID, V1236.LISTVAL_ID, LV.COST
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$SCHOOL_ID, :V$GP_ID, :V$Y;

  -- Старую схему выгрузки больше не используем, новая схема стартует в 2025 учебном году
  IF(V$Y < 2025) THEN EXIT;

  FOR
    SELECT MSL.OBJ_ID, B.OBJ_ID, B.DATE_ADD, MAXVALUE(MSL.DATE_MODIFY, L.DATE_MODIFY, B.DATE_MODIFY)
    FROM CJ2_JOURNAL J
    JOIN LISTVALS LV ON LV.LISTVAL_ID = J.STAGE_INDEX AND LV.PARENT_ID IN (2141, 12941)
    JOIN CJ2_MS_LESSONS MSL ON MSL.DATE_DEL IS NULL AND MSL.CJ_ID = J.OBJ_ID
    JOIN CJ2_JOURNAL_LESSONS L ON L.DATE_DEL IS NULL AND L.CJ_ID = J.OBJ_ID AND L.MS_ID = MSL.OBJ_ID AND (L.IS_COMPLETED = 1 OR L.IS_PUBLISHED = 1)
    JOIN CJ2_BLOB B ON B.DATE_DEL IS NULL AND B.LESSON_ID = L.OBJ_ID AND B.FILE_TYPE = 1
    WHERE J.DATE_DEL IS NULL AND J.JOURNAL_TYPE = 0 AND J.YEAR_ID = :V$GP_ID
    ORDER BY 1
    INTO :LESSON_ID, :MATERIAL_ID, :CREATE_DATETIME, :V$DT1
  DO
  BEGIN
    LESSON_ID = V$Y || 'X' || LESSON_ID;

    IF(I$DT1 IS NULL OR V$DT1 >= I$DT1) THEN
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_MS_LESSONS_STUDENTS (
    I$DT1 TIMESTAMP,
    I$DT2 TIMESTAMP NOT NULL = CURRENT_TIMESTAMP)
RETURNS (
    LESSON_ID VARCHAR(40),
    STUDENT_ID VARCHAR(60),
    CREATE_DATETIME TIMESTAMP,
    SEND_DATETIME TIMESTAMP)
AS
DECLARE VARIABLE V$SCHOOL_ID BIGINT;
DECLARE VARIABLE V$GP_ID BIGINT;
DECLARE VARIABLE V$Y INTEGER;
DECLARE VARIABLE V$DT1 TIMESTAMP;
DECLARE VARIABLE V$DT2 TIMESTAMP;
DECLARE VARIABLE V$DT3 TIMESTAMP;
DECLARE VARIABLE V$GROUP_ID BIGINT;
DECLARE VARIABLE V$LD DATE;
DECLARE VARIABLE V$PERSON_ID BIGINT;
begin

  SEND_DATETIME = I$DT2;

  SELECT FIRST 1 L2.OBJ_ID, V1236.LISTVAL_ID, LV.COST
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$SCHOOL_ID, :V$GP_ID, :V$Y;

  -- Старую схему выгрузки больше не используем, новая схема стартует в 2025 учебном году
  IF(V$Y < 2025) THEN EXIT;

  FOR
    SELECT MSL.OBJ_ID, MAXVALUE(MSL.DATE_MODIFY, L.DATE_MODIFY), J.GRADE_ID, MSL.LESSON_DATE
    FROM CJ2_JOURNAL J
    JOIN LISTVALS LV ON LV.LISTVAL_ID = J.STAGE_INDEX AND LV.PARENT_ID IN (2141, 12941)
    JOIN CJ2_MS_LESSONS MSL ON MSL.DATE_DEL IS NULL AND MSL.CJ_ID = J.OBJ_ID
    LEFT JOIN CJ2_JOURNAL_LESSONS L ON L.DATE_DEL IS NULL AND L.CJ_ID = J.OBJ_ID AND L.MS_ID = MSL.OBJ_ID -- AND (L.IS_COMPLETED = 1 OR L.IS_PUBLISHED = 1)
    WHERE J.DATE_DEL IS NULL AND J.JOURNAL_TYPE = 0 AND J.YEAR_ID = :V$GP_ID
    ORDER BY 4, 1
    INTO :LESSON_ID, :V$DT1, :V$GROUP_ID, :V$LD
  DO
  BEGIN

    LESSON_ID = V$Y || 'X' || LESSON_ID;
    CREATE_DATETIME = V$DT1;

    FOR
      SELECT M.PERSON_ID, V2912.SVAL, MAX(V2912.DATE_MODIFY), MAX(M.DATE_MODIFY)
      FROM PERSON_MOVEMENTS M
      JOIN VALS V2912 ON V2912.OBJ_ID = M.PERSON_ID AND V2912.PARAM_ID = 2912 AND V2912.IS_DEL = 0
      WHERE M.DATE_DEL IS NULL AND M.GROUP_ID = :V$GROUP_ID AND M.DATE_IN <= :V$LD AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :V$LD) AND M.LEVEL_ID IN (22, 26, 27)
      GROUP BY 1, 2
      ORDER BY 1
      INTO :V$PERSON_ID, :STUDENT_ID, :V$DT2, :V$DT3
    DO
    BEGIN
      IF(I$DT1 IS NULL OR V$DT1 >= I$DT1 OR V$DT2 >= I$DT1 OR V$DT3 >= I$DT1) THEN
      BEGIN
        IF(POSITION(':' IN STUDENT_ID) > 0) THEN STUDENT_ID = SUBSTRING(STUDENT_ID FROM 1 FOR POSITION(':' IN STUDENT_ID) - 1);
        STUDENT_ID = REPLACE(STUDENT_ID, '{', '');
        STUDENT_ID = REPLACE(STUDENT_ID, '}', '');
        STUDENT_ID = LOWER(STUDENT_ID);

        SUSPEND;
      END
    END

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_MS_LESSON_PLAN (
    I$DT1 TIMESTAMP,
    I$DT2 TIMESTAMP NOT NULL = current_timestamp)
RETURNS (
    ID VARCHAR(100),
    LESSON_THEME VARCHAR(1000),
    UNIT_ID VARCHAR(40),
    LESSON_NUMBER INTEGER,
    HOURS_COUNT VARCHAR(40),
    DESCRIPTION VARCHAR(1000),
    CREATE_DATETIME TIMESTAMP,
    SEND_DATETIME TIMESTAMP)
AS
declare variable V$SCHOOL_ID bigint;
declare variable V$GP_ID bigint;
declare variable V$Y integer;
declare variable V$DT1 timestamp;
declare variable V$DT2 timestamp;
declare variable V$DT3 timestamp;
declare variable V$CJ_ID bigint;
begin

  SEND_DATETIME = I$DT2;

  SELECT FIRST 1 L2.OBJ_ID, V1236.LISTVAL_ID, LV.COST
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$SCHOOL_ID, :V$GP_ID, :V$Y;

  FOR
    SELECT J.OBJ_ID, J.OBJ_ID, PL.OBJ_ID, PL.LESSON_NUM, PL.THEME_TEXT, CAST(COALESCE(PL.DURATION, 1) AS NUMERIC(18, 1)),
      J.DATE_MODIFY, L.DATE_MODIFY, PL.DATE_MODIFY
    FROM CJ2_JOURNAL J
    JOIN CJ2_JOURNAL_LESSONS L ON L.DATE_DEL IS NULL AND L.CJ_ID = J.OBJ_ID AND (L.IS_PUBLISHED = 1 OR L.IS_COMPLETED = 1)
    JOIN PTP_LESSONS PL ON PL.OBJ_ID = L.LESSON_PTP_ID
    WHERE J.DATE_DEL IS NULL AND J.JOURNAL_TYPE = 0 AND J.YEAR_ID = :V$GP_ID
    ORDER BY 1
    INTO :V$CJ_ID, :UNIT_ID, :ID, :LESSON_NUMBER, :LESSON_THEME, :HOURS_COUNT,
      :V$DT1, :V$DT2, :V$DT3
  DO
  BEGIN
    ID = V$CJ_ID || ':' || ID;
    HOURS_COUNT = REPLACE(HOURS_COUNT, '.0', '');
    CREATE_DATETIME = V$DT1;

    IF(I$DT1 IS NULL OR V$DT1 >= I$DT1 OR V$DT2 >= I$DT1 OR V$DT3 >= I$DT1) THEN
    SUSPEND;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_MS_LOCATION_PROPERTIES (
    I$DT1 TIMESTAMP,
    I$DT2 TIMESTAMP NOT NULL = current_timestamp)
RETURNS (
    ID VARCHAR(60),
    EDU_LOCATION_ID VARCHAR(60),
    SEQUENCE VARCHAR(100),
    CODE VARCHAR(60),
    TYPE_LOCATION VARCHAR(60),
    LABEL VARCHAR(1000),
    DESCRIPTION VARCHAR(1000),
    VALUECODING VARCHAR(100),
    VALUESTRING VARCHAR(1000),
    CREATE_DATETIME TIMESTAMP,
    SEND_DATETIME TIMESTAMP)
AS
declare variable V$SCHOOL_ID bigint;
declare variable V$GP_ID bigint;
declare variable V$Y integer;
declare variable V$DT1 timestamp;
declare variable V$DT2 timestamp;
declare variable V$ID bigint;
declare variable V$PARAM_ID bigint;
declare variable V varchar(1000);
begin

  SEND_DATETIME = I$DT2;

  SELECT FIRST 1 L2.OBJ_ID, V1236.LISTVAL_ID, LV.COST
  FROM LINKS L2
  JOIN VALS V2 ON V2.OBJ_ID = L2.OBJ_ID AND V2.PARAM_ID = 2 AND V2.IS_DEL = 0
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  JOIN VALS V9 ON V9.OBJ_ID = L2.OBJ_ID AND V9.PARAM_ID = 9 AND V9.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$SCHOOL_ID, :V$GP_ID, :V$Y;

  -- Выдаем все адреса зданий, только учебные
  -- заполнение координат не требуем, если что оставляем возможность подложить на сервере
  FOR
    SELECT L16.OBJ_ID, L16.DATE_MODIFY
    FROM LINKS L73
    JOIN LINKS L16 ON L16.PARENT_ID = L73.OBJ_ID AND L16.OBJ_TYPE_ID = 16 AND L16.DATE_DEL IS NULL
    JOIN VALL V485 ON V485.OBJ_ID = L16.OBJ_ID AND V485.PARAM_ID = 485 AND V485.IS_DEL = 0 AND V485.LISTVAL_ID = 1093
    -- Адрес должен быть заполнен с указанием кода ФИАС
    JOIN VALA V420 ON V420.OBJ_ID = L16.OBJ_ID AND V420.PARAM_ID = 420 AND V420.IS_DEL = 0 AND V420.FIAS_UID IS NOT NULL
    WHERE L73.PARENT_ID = :V$SCHOOL_ID AND L73.OBJ_TYPE_ID = 73 AND L73.DATE_DEL IS NULL
    ORDER BY 1
    INTO :V$ID, :V$DT1
  DO
  BEGIN
    EDU_LOCATION_ID = V$ID;

    FOR
      SELECT V.PARAM_ID, CAST(V.VAL AS VARCHAR(1000)), V.DATE_MODIFY, 4
      FROM VALI V
      WHERE V.OBJ_ID = :V$ID AND V.PARAM_ID IN (500, 502, 508) AND V.IS_DEL = 0
      UNION
      SELECT V.PARAM_ID, CAST(V.VAL AS NUMERIC(18, 1)), V.DATE_MODIFY, 7
      FROM VALF V
      WHERE V.OBJ_ID = :V$ID AND V.PARAM_ID IN (496, 499) AND V.IS_DEL = 0
      UNION
      SELECT V.PARAM_ID, EXTRACT(YEAR FROM V.VAL), V.DATE_MODIFY, 4
      FROM VALD V
      WHERE V.OBJ_ID = :V$ID AND V.PARAM_ID IN (493, 3163) AND V.IS_DEL = 0
      ORDER BY 1
      INTO :V$PARAM_ID, :V, :CREATE_DATETIME, :TYPE_LOCATION
    DO
    BEGIN
      ID = V$ID || ':' || V$PARAM_ID;
      V$DT2 = CREATE_DATETIME;

      IF(V$PARAM_ID = 502) THEN CODE = 1; -- Количество ученических мест (проектное)
      IF(V$PARAM_ID = 500) THEN CODE = 4; -- Количество учебных помещений (проектное)
      IF(V$PARAM_ID = 499) THEN CODE = 8; -- Площадь помещений
      IF(V$PARAM_ID = 496) THEN CODE = 11; -- Площадь здания
      IF(V$PARAM_ID = 508) THEN CODE = 12; -- Количество этажей
      IF(V$PARAM_ID = 493) THEN CODE = 13; -- Год постройки
      IF(V$PARAM_ID = 3163) THEN CODE = 14; -- Год ввода в эксплуатацию

      VALUESTRING = V;

      IF(I$DT1 IS NULL OR V$DT1 >= I$DT1 OR V$DT2 >= I$DT1) THEN SUSPEND;
    END
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_MS_MARKS (
    I$DT1 TIMESTAMP,
    I$DT2 TIMESTAMP NOT NULL = CURRENT_TIMESTAMP)
RETURNS (
    ID BIGINT,
    STUDENT_ID VARCHAR(60),
    SUBJECT_ID BIGINT,
    PERIOD_ID VARCHAR(40),
    CLASS_ID VARCHAR(40),
    MARK_VALUE1 VARCHAR(100),
    MARK_VALUE2 VARCHAR(100),
    WEIGHT VARCHAR(40),
    MARK_DATE DATE,
    SUBJECT_NAME VARCHAR(400),
    WORK_TYPE_CODE VARCHAR(20),
    WORK_TYPE_VALUE INTEGER,
    WORK_TYPE_DESCRIPTION VARCHAR(40),
    WORK_NAME VARCHAR(100),
    COMMENT VARCHAR(1000),
    SCALE_CODE VARCHAR(20),
    SCALE_VALUE INTEGER,
    SCALE_DESCRIPTION VARCHAR(40),
    SCHOOL_ID VARCHAR(40),
    CLASS_NUM INTEGER,
    CLASS_YEAR_FROM INTEGER,
    WORK_KIND VARCHAR(100),
    CREATE_DATETIME TIMESTAMP,
    SEND_DATETIME TIMESTAMP)
AS
DECLARE VARIABLE V$GP_ID BIGINT;
DECLARE VARIABLE V$Y INTEGER;
DECLARE VARIABLE V$YSTART DATE;
DECLARE VARIABLE V$YEND DATE;
DECLARE VARIABLE V$STUDENT_ID BIGINT;
DECLARE VARIABLE V$CLASS_ID BIGINT;
DECLARE VARIABLE V$MARKVAL BIGINT;
DECLARE VARIABLE V$YEARVAL INTEGER;
DECLARE VARIABLE V$DATEEND DATE;
DECLARE VARIABLE V$CT BIGINT;
DECLARE VARIABLE V$MTM BIGINT;
DECLARE VARIABLE V$MS BIGINT;
DECLARE VARIABLE V$MVAL BIGINT;
DECLARE VARIABLE V$PERIOD_ID BIGINT;
DECLARE VARIABLE V$SP_ID BIGINT;
DECLARE VARIABLE V$SCHOOL_ID BIGINT;
DECLARE VARIABLE PERIOD_NUM INTEGER;
DECLARE VARIABLE V$DT1 TIMESTAMP;
DECLARE VARIABLE V$DT2 TIMESTAMP;
begin

  SEND_DATETIME = I$DT2;

  SELECT FIRST 1 L2.OBJ_ID, V1236.LISTVAL_ID, LV.COST, V9.VAL
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  JOIN VALS V9 ON V9.OBJ_ID = L2.OBJ_ID AND V9.PARAM_ID = 9 AND V9.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$SCHOOL_ID, :V$GP_ID, :V$Y, :SCHOOL_ID;

  CLASS_YEAR_FROM = V$Y;

  V$YSTART = '01.09.' || V$Y;
  V$YEND = '31.08.' || (V$Y + 1);

  IF(V$SCHOOL_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Объект школы не найден';

  FOR
    SELECT M.MARK_ID, J.PERIOD_ID, L.LESSON_DATE, M.STUDENT_ID, V2912.SVAL, J.SUBJECT_ID, CAST(CT.DEFAULT_COST AS NUMERIC(18, 2)),
      CT.CONTROL_TYPE_ID, CT.CONTROL_DESC, C.MARK_SYSTEM_ID, M.MARK_TYPE_ID, MT.MARK_NAME, MT.PARENT_ID, M.DATE_ADD, V2912.DATE_MODIFY
    FROM CJ2_JOURNAL J
    JOIN CJ2_JOURNAL_LESSONS L ON L.DATE_DEL IS NULL AND L.CJ_ID = J.OBJ_ID AND L.IS_COMPLETED <> 0
    JOIN CJ2_CONTROL C ON C.DATE_DEL IS NULL AND C.LESSON_ID = L.OBJ_ID AND C.CONTROL_TYPE_ID <> 0
    JOIN CJ2_CONTROL_TYPE CT ON CT.CONTROL_TYPE_ID = C.CONTROL_TYPE_ID
    JOIN CJ2_MARK M ON M.DATE_DEL IS NULL AND M.CONTROL_ID = C.CONTROL_ID
    JOIN CJ2_MARK_TYPE MT ON MT.MARK_TYPE_ID = M.MARK_TYPE_ID
    JOIN VALS V2912 ON V2912.OBJ_ID = M.STUDENT_ID AND V2912.PARAM_ID = 2912 AND V2912.IS_DEL = 0
    JOIN LISTVALS LV ON LV.LISTVAL_ID = J.STAGE_INDEX AND LV.PARENT_ID IN (2141, 12941)
    WHERE J.DATE_DEL IS NULL AND J.JOURNAL_TYPE = 0 AND J.YEAR_ID = :V$GP_ID
      AND EXISTS(
        SELECT FIRST 1 1
        FROM LINKS LPG
        WHERE LPG.OBJ_ID = M.STUDENT_ID AND LPG.PARENT_TYPE_ID IN (9, 125, 187) AND LPG.DATE_DEL IS NULL
      )
    ORDER BY 5, 6, 3
    INTO :ID, :V$PERIOD_ID, :MARK_DATE, :V$STUDENT_ID, :STUDENT_ID, :SUBJECT_ID, :WEIGHT,
      :V$CT, :WORK_KIND, :V$MS, :V$MVAL, :MARK_VALUE1, :V$MTM, :CREATE_DATETIME, :V$DT1
  DO
  BEGIN

    IF(POSITION(':' IN STUDENT_ID) > 0) THEN STUDENT_ID = SUBSTRING(STUDENT_ID FROM 1 FOR POSITION(':' IN STUDENT_ID) - 1);
    STUDENT_ID = REPLACE(STUDENT_ID, '{', '');
    STUDENT_ID = REPLACE(STUDENT_ID, '}', '');
    STUDENT_ID = LOWER(STUDENT_ID);

    V$DT2 = NULL;
    SELECT MAX(MAXVALUE(L20.DATE_INS, V155.DATE_MODIFY, V1570.DATE_MODIFY))
    FROM LINKS L20
    JOIN VALS V155 ON V155.OBJ_ID = L20.OBJ_ID AND V155.PARAM_ID = 155 AND V155.IS_DEL = 0
    JOIN VALS V1570 ON V1570.OBJ_ID = L20.EXT_OBJ_ID AND V1570.PARAM_ID = 1570 AND V1570.IS_DEL = 0
    WHERE L20.PARENT_ID = :V$STUDENT_ID AND L20.OBJ_TYPE_ID = 20 AND L20.DATE_DEL IS NULL
    INTO :V$DT2;

    -- Восстанавливаем класс и параллель на момент выставления отметки
    V$CLASS_ID = NULL;
    SELECT FIRST 1 M.GROUP_ID, CAST(LV.COST AS INTEGER)
    FROM PERSON_MOVEMENTS M
    JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
    JOIN LISTVALS LV ON LV.LISTVAL_ID = M.STAGE_ID
    WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :V$STUDENT_ID AND M.DATE_IN <= :V$YEND
    ORDER BY M.DATE_OUT DESC NULLS FIRST
    INTO :V$CLASS_ID, :CLASS_NUM;

    CLASS_ID = V$CLASS_ID || 'Y' || CLASS_YEAR_FROM;

    SUBJECT_NAME = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:SUBJECT_ID));

    -- Подбираем период по дате, конвертируем его в нужный формат
    PERIOD_ID = NULL;
    SELECT FIRST 1 V1170.LISTVAL_ID
    FROM LINKS L154
    JOIN VALL V1170 ON V1170.OBJ_ID = L154.OBJ_ID AND V1170.PARAM_ID = 1170 AND V1170.IS_DEL = 0
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V1170.LISTVAL_ID
    JOIN VALD V1169 ON V1169.OBJ_ID = L154.OBJ_ID AND V1169.PARAM_ID = 1169 AND V1169.IS_DEL = 0 AND V1169.VAL <= :MARK_DATE
    JOIN VALD V1174 ON V1174.OBJ_ID = L154.OBJ_ID AND V1174.PARAM_ID = 1174 AND V1174.IS_DEL = 0
    WHERE L154.PARENT_ID = :V$PERIOD_ID AND L154.OBJ_TYPE_ID = 154 AND L154.DATE_DEL IS NULL
    ORDER BY V1169.VAL DESC
    INTO :V$SP_ID;

    IF(V$SP_ID IN (12, 13, 14, 15)) THEN BEGIN
      PERIOD_NUM = V$SP_ID - 12 + 1;
      PERIOD_ID = CLASS_YEAR_FROM || '-Q' || PERIOD_NUM;
    END
    ELSE IF(V$SP_ID IN (10, 11)) THEN BEGIN
      PERIOD_NUM = V$SP_ID - 10 + 1;
      PERIOD_ID = CLASS_YEAR_FROM || '-H' || PERIOD_NUM;
    END
    ELSE IF(V$SP_ID IN (16, 17, 18)) THEN BEGIN
      PERIOD_NUM = V$SP_ID - 16 + 1;
      PERIOD_ID = CLASS_YEAR_FROM || '-T' || PERIOD_NUM;
    END
    -- семестры ?!!!

    WORK_TYPE_CODE = NULL;
    SCALE_CODE = NULL;

    IF(V$MTM = 400) THEN
    BEGIN
      SCALE_VALUE = '1';
      SCALE_CODE = '5-points';
      SCALE_DESCRIPTION = 'Пятибалльная';
    END
    ELSE IF(V$MTM = 100) THEN
    BEGIN
      SCALE_VALUE = '5';
      SCALE_CODE = 'pass/fail';
      SCALE_DESCRIPTION = 'Зачет-Незачет';
    END
    ELSE IF(V$MTM = 599) THEN
    BEGIN
      SCALE_VALUE = '3';
      SCALE_CODE = '100-points';
      SCALE_DESCRIPTION = 'Стобалльная';
    END
    ELSE
    BEGIN
      SCALE_VALUE = '6';
      SCALE_CODE = 'nomarks';
      SCALE_DESCRIPTION = 'Безотметочная';
    END

    IF(V$CT IN (1084, 1085, 1087, 1091)) THEN
    BEGIN
      WORK_TYPE_VALUE = '1';
      WORK_TYPE_CODE = 'Test';
      WORK_TYPE_DESCRIPTION = 'Контрольная работа';
    END
    ELSE
    BEGIN
      WORK_TYPE_VALUE = '2';
      WORK_TYPE_CODE = 'Ordinary';
      WORK_TYPE_DESCRIPTION = 'Обычная отметка';
    END

    IF(WORK_TYPE_CODE IS NOT NULL AND SCALE_CODE IS NOT NULL AND PERIOD_ID IS NOT NULL AND
      (I$DT1 IS NULL OR V$DT1 >= I$DT1 OR V$DT2 >= I$DT1 OR CREATE_DATETIME >= I$DT1)
    )
    THEN SUSPEND;

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_MS_MATERIALS (
    I$DT1 TIMESTAMP,
    I$DT2 TIMESTAMP NOT NULL = current_timestamp)
RETURNS (
    ID VARCHAR(40),
    NAME VARCHAR(400),
    SIZE INTEGER,
    LINK VARCHAR(400),
    CREATE_DATETIME TIMESTAMP,
    SEND_DATETIME TIMESTAMP)
AS
declare variable V$SCHOOL_ID bigint;
declare variable V$GP_ID bigint;
declare variable V$Y integer;
declare variable V$DT1 timestamp;
declare variable V$DT2 timestamp;
declare variable V$DT3 timestamp;
declare variable DB varchar(400);
begin

  SEND_DATETIME = I$DT2;

  SELECT FIRST 1 L2.OBJ_ID, V1236.LISTVAL_ID, LV.COST
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$SCHOOL_ID, :V$GP_ID, :V$Y;

  SELECT MON$DATABASE_NAME FROM MON$DATABASE INTO :DB;
  DB = REPLACE(DB, 'BASE.FDB', 'BLOB.FDB');

  FOR
    SELECT B.OBJ_ID, B.DATE_ADD, B.FILE_NAME, MAXVALUE(L.DATE_MODIFY, B.DATE_MODIFY)
    FROM CJ2_JOURNAL J
    JOIN CJ2_JOURNAL_LESSONS L ON L.DATE_DEL IS NULL AND L.CJ_ID = J.OBJ_ID AND (L.IS_COMPLETED = 1 OR L.IS_PUBLISHED = 1)
    JOIN CJ2_BLOB B ON B.DATE_DEL IS NULL AND B.LESSON_ID = L.OBJ_ID
    INTO :ID, :CREATE_DATETIME, :NAME, :V$DT1
  DO
  BEGIN
    IF(I$DT1 IS NULL OR V$DT1 >= I$DT1) THEN
    BEGIN
      -- Надо достать размер из BLOB
      "SIZE" = NULL;

      EXECUTE STATEMENT 'SELECT OCTET_LENGTH(VAL) FROM BLOBS WHERE BLOB_ID = ' || ID
      ON EXTERNAL :DB
      WITH COMMON TRANSACTION
      INTO :"SIZE";

      -- Вместо линка возвращаем только переменную часть
      -- https://dnevnik2.petersburgedu.ru/api/filekit/file/download?p_uuid=...
      LINK = ID;

      IF("SIZE" IS NOT NULL) THEN SUSPEND;
    END
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_MS_ORGANISATION_UNIT (
    I$DT1 TIMESTAMP,
    I$DT2 TIMESTAMP NOT NULL = current_timestamp)
RETURNS (
    CODE VARCHAR(60),
    NAME VARCHAR(1000),
    PART_OF_UNIT VARCHAR(60),
    CREATE_DATETIME TIMESTAMP,
    SEND_DATETIME TIMESTAMP)
AS
declare variable V$SCHOOL_ID bigint;
declare variable V$GP_ID bigint;
declare variable V$Y integer;
declare variable V$DT1 timestamp;
declare variable V$DT2 timestamp;
declare variable V$DT3 timestamp;
declare variable NC timestamp;
begin

  SEND_DATETIME = I$DT2;
  NC = '01.01.2023';

  SELECT FIRST 1 L2.OBJ_ID, V1236.LISTVAL_ID, LV.COST, V9.VAL, V2.VAL,
    MAXVALUE(COALESCE(L2.DATE_MODIFY, :NC), COALESCE(V2.DATE_MODIFY, :NC), COALESCE(V9.DATE_MODIFY, :NC))
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  JOIN VALS V2 ON V2.OBJ_ID = L2.OBJ_ID AND V2.PARAM_ID = 2 AND V2.IS_DEL = 0
  JOIN VALS V9 ON V9.OBJ_ID = L2.OBJ_ID AND V9.PARAM_ID = 9 AND V9.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$SCHOOL_ID, :V$GP_ID, :V$Y, :CODE, :NAME, :V$DT1;

  CREATE_DATETIME = V$DT1;

  IF(I$DT1 IS NULL OR V$DT1 >= I$DT1 OR V$DT2 >= I$DT1) THEN
  SUSPEND;

  PART_OF_UNIT = CODE;

  FOR
    SELECT :PART_OF_UNIT || ':' || L211.OBJ_ID, V1792.VAL, MAXVALUE(COALESCE(L211.DATE_MODIFY, :NC), COALESCE(V1792.DATE_MODIFY, :NC))
    FROM LINKS L211
    JOIN VALS V1792 ON V1792.OBJ_ID = L211.OBJ_ID AND V1792.PARAM_ID = 1792 AND V1792.IS_DEL = 0
    WHERE L211.PARENT_ID = :V$SCHOOL_ID AND L211.OBJ_TYPE_ID = 211 AND L211.DATE_DEL IS NULL
    ORDER BY L211.OBJ_ID
    INTO :CODE, :NAME, :V$DT2
  DO
  BEGIN
    CREATE_DATETIME = V$DT2;

    IF(I$DT1 IS NULL OR V$DT1 >= I$DT1 OR V$DT2 >= I$DT1) THEN
    SUSPEND;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_MS_ORG_ALIAS (
    I$DT1 TIMESTAMP,
    I$DT2 TIMESTAMP NOT NULL = current_timestamp)
RETURNS (
    ID VARCHAR(60),
    ORGANISATION_ID VARCHAR(60),
    OTHER_VALUE VARCHAR(1000),
    CREATE_DATETIME TIMESTAMP,
    SEND_DATETIME TIMESTAMP)
AS
declare variable V$SCHOOL_ID bigint;
declare variable V$GP_ID bigint;
declare variable V$Y integer;
declare variable V$DT1 timestamp;
declare variable V$DT2 timestamp;
begin

  SEND_DATETIME = I$DT2;

  SELECT FIRST 1 L2.OBJ_ID, V1236.LISTVAL_ID, LV.COST, V9.VAL
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  JOIN VALS V9 ON V9.OBJ_ID = L2.OBJ_ID AND V9.PARAM_ID = 9 AND V9.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$SCHOOL_ID, :V$GP_ID, :V$Y, :ORGANISATION_ID;

  FOR
    SELECT L475.OBJ_ID, V3362.VAL, MAXVALUE(L475.DATE_MODIFY, V3362.DATE_MODIFY)
    FROM LINKS L475
    JOIN VALS V3362 ON V3362.OBJ_ID = L475.OBJ_ID AND V3362.PARAM_ID = 3362 AND V3362.IS_DEL = 0
    WHERE L475.PARENT_ID = :V$SCHOOL_ID AND L475.OBJ_TYPE_ID = 475 AND L475.DATE_DEL IS NULL
    INTO :ID, :OTHER_VALUE, :V$DT1
  DO
  BEGIN
    CREATE_DATETIME = V$DT1;

    IF(I$DT1 IS NULL OR V$DT1 >= I$DT1) THEN SUSPEND;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_MS_ORG_MEMBER (
    I$DT1 TIMESTAMP,
    I$DT2 TIMESTAMP NOT NULL = CURRENT_TIMESTAMP)
RETURNS (
    ID VARCHAR(60),
    ORGANISATION_ID VARCHAR(60),
    SCHOOL_ID VARCHAR(60),
    COLLEGES_ID VARCHAR(60),
    ORGANISATION_NAME VARCHAR(1000),
    CREATE_DATETIME TIMESTAMP,
    SEND_DATETIME TIMESTAMP)
AS
DECLARE VARIABLE V$SCHOOL_ID BIGINT;
DECLARE VARIABLE V$GP_ID BIGINT;
DECLARE VARIABLE V$Y INTEGER;
DECLARE VARIABLE V$DT1 TIMESTAMP;
DECLARE VARIABLE V$DT2 TIMESTAMP;
DECLARE VARIABLE V$ID VARCHAR(60);
DECLARE VARIABLE V$STATUS VARCHAR(10);
DECLARE VARIABLE P1 BIGINT;
DECLARE VARIABLE P2 BIGINT;
begin

  SEND_DATETIME = I$DT2;

  SELECT FIRST 1 L2.OBJ_ID, V1236.LISTVAL_ID, LV.COST, V9.VAL
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  JOIN VALS V9 ON V9.OBJ_ID = L2.OBJ_ID AND V9.PARAM_ID = 9 AND V9.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$SCHOOL_ID, :V$GP_ID, :V$Y, :V$ID;

  -- В зависимости от типа лицензии отдаем ID как школу, либо как СПО
  -- Выгружаем по ИЛИ название и ОРГН, на сервере разбираемся можно ли что вытащить
  V$STATUS = (SELECT STATUS FROM OU_LICENCE_TYPE);
  IF(V$STATUS = 'O') THEN SCHOOL_ID = V$ID;
  ELSE IF(V$STATUS = 'C') THEN COLLEGES_ID = V$ID;
  ELSE IF(V$STATUS = 'S') THEN
  -- Для мультипараграфа выдаем в зависимости от настроек
  BEGIN
    FOR
      SELECT DISTINCT LV.PARENT_ID, LV.LISTVAL_ID
      FROM LINKS L472
      JOIN VALL V3327 ON V3327.OBJ_ID = L472.OBJ_ID AND V3327.PARAM_ID = 3327 AND V3327.IS_DEL = 0
      JOIN LISTVALS LV ON LV.LISTVAL_ID = V3327.LISTVAL_ID AND LV.LIST_ID = 19 AND LV.IS_DEL = 0
      WHERE L472.PARENT_ID = :V$SCHOOL_ID AND L472.OBJ_TYPE_ID = 472 AND L472.DATE_DEL IS NULL
      INTO :P1, :P2
    DO
    BEGIN
      -- IF (P1 = 21) THEN V$IS_DOU = 1;
      IF (P2 IN (22, 26, 27)) THEN SCHOOL_ID = V$ID;
      IF (P2 = 29) THEN COLLEGES_ID = V$ID;
    END
  END

  IF(SCHOOL_ID IS NULL AND COLLEGES_ID IS NULL) THEN EXIT;

  FOR
    SELECT L5.OBJ_ID, V24.VAL, V3456.VAL, MAXVALUE(L5.DATE_MODIFY, V24.DATE_MODIFY, V3456.DATE_MODIFY)
    FROM LINKS L5
    LEFT JOIN VALS V24 ON V24.OBJ_ID = L5.OBJ_ID AND V24.PARAM_ID = 24 AND V24.IS_DEL = 0
    LEFT JOIN VALS V3456 ON V3456.OBJ_ID = L5.OBJ_ID AND V3456.PARAM_ID = 3456 AND V3456.IS_DEL = 0
    WHERE L5.PARENT_ID = :V$SCHOOL_ID AND L5.OBJ_TYPE_ID = 5 AND L5.DATE_DEL IS NULL
      AND (V24.VAL IS NOT NULL OR V3456.VAL IS NOT NULL)
    INTO :ID, :ORGANISATION_NAME, :ORGANISATION_ID, :V$DT1
  DO
  BEGIN
    CREATE_DATETIME = V$DT1;

    IF(I$DT1 IS NULL OR V$DT1 >= I$DT1) THEN SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_MS_PL_ORG_UNIT (
    I$DT1 TIMESTAMP,
    I$DT2 TIMESTAMP NOT NULL = current_timestamp)
RETURNS (
    POSITION_LIST_URI VARCHAR(200),
    ORGANISATION_UNIT_CODE VARCHAR(60),
    CREATE_DATETIME TIMESTAMP,
    SEND_DATETIME TIMESTAMP)
AS
declare variable V$SCHOOL_ID bigint;
declare variable V$GP_ID bigint;
declare variable V$Y integer;
declare variable V$DT1 timestamp;
declare variable V$DT2 timestamp;
declare variable V$DT3 timestamp;
declare variable NC timestamp;
begin

  SEND_DATETIME = I$DT2;
  NC = '01.01.2023';

  SELECT FIRST 1 L2.OBJ_ID, V1236.LISTVAL_ID, LV.COST, V9.VAL, MAXVALUE(COALESCE(L2.DATE_MODIFY, :NC), COALESCE(V9.DATE_MODIFY, :NC))
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  JOIN VALS V9 ON V9.OBJ_ID = L2.OBJ_ID AND V9.PARAM_ID = 9 AND V9.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$SCHOOL_ID, :V$GP_ID, :V$Y, :ORGANISATION_UNIT_CODE, :V$DT1;

  CREATE_DATETIME = V$DT1;
  POSITION_LIST_URI = 'https://dnevnik2.petersburgedu.ru/stuff/' || ORGANISATION_UNIT_CODE || '/' || V$Y;

  IF(I$DT1 IS NULL OR V$DT1 >= I$DT1 OR V$DT2 >= I$DT1) THEN
  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_MS_PMARKS (
    I$DT1 TIMESTAMP,
    I$DT2 TIMESTAMP NOT NULL = CURRENT_TIMESTAMP)
RETURNS (
    ID VARCHAR(100),
    PERIOD_ID VARCHAR(40),
    SUBJECT_ID BIGINT,
    STUDENT_ID VARCHAR(60),
    CLASS_ID VARCHAR(40),
    SUBJECT_NAME VARCHAR(400),
    FACT VARCHAR(20),
    FIVEPOINT_FACT VARCHAR(20),
    RECENT_PLAN VARCHAR(20),
    FIVEPOINT_RECENT_PLAN VARCHAR(20),
    SCHOOL_ID VARCHAR(40),
    CLASS_NUM INTEGER,
    CLASS_YEAR_FROM INTEGER,
    MARK_SCALE_CODE VARCHAR(20),
    MARK_SCALE_VALUE INTEGER,
    MARK_SCALE_DESCRIPTION VARCHAR(40),
    CREATE_DATETIME TIMESTAMP,
    SEND_DATETIME TIMESTAMP)
AS
DECLARE VARIABLE V$GP_ID BIGINT;
DECLARE VARIABLE V$Y INTEGER;
DECLARE VARIABLE V$RANGE_FROM DATE;
DECLARE VARIABLE V$RANGE_CY DATE;
DECLARE VARIABLE V$IN_DATE DATE;
DECLARE VARIABLE V$YEAR_ID BIGINT;
DECLARE VARIABLE V$YSTART DATE;
DECLARE VARIABLE V$YEND DATE;
DECLARE VARIABLE V$STUDENT_ID BIGINT;
DECLARE VARIABLE V$CLASS_ID BIGINT;
DECLARE VARIABLE V$MARKVAL BIGINT;
DECLARE VARIABLE V$SCHOOL_ID BIGINT;
DECLARE VARIABLE V$MT_ID BIGINT;
DECLARE VARIABLE PERIOD_NUM INTEGER;
DECLARE VARIABLE V$DT1 TIMESTAMP;
DECLARE VARIABLE V$DT2 TIMESTAMP;
DECLARE VARIABLE V$DT3 TIMESTAMP;
DECLARE VARIABLE V$DT4 TIMESTAMP;
DECLARE VARIABLE V$DT5 TIMESTAMP;
DECLARE VARIABLE V$MV DOUBLE PRECISION;
DECLARE VARIABLE V$D1 DATE;
DECLARE VARIABLE V$D2 DATE;
DECLARE VARIABLE V$TM TIMESTAMP;
begin

  SEND_DATETIME = I$DT2;

  SELECT FIRST 1 L2.OBJ_ID, V1236.LISTVAL_ID, LV.COST, V9.VAL
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  JOIN VALS V9 ON V9.OBJ_ID = L2.OBJ_ID AND V9.PARAM_ID = 9 AND V9.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$SCHOOL_ID, :V$GP_ID, :V$Y, :SCHOOL_ID;

  V$RANGE_FROM = '31.08.' || (V$Y - 3);
  V$RANGE_CY = '01.09.' || V$Y;

  IF(V$SCHOOL_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Объект школы не найден';

  SELECT FIRST 1 CAST(I.INFO_VAL AS TIMESTAMP)
  FROM INFO I
  WHERE I.INFO_CODE = 'MS_LAST_EXPORT_DATE'
  INTO :V$TM;

  -- Выбираем всех обучающихся, засветившихся в школе за последние 3 года
  FOR
    SELECT L10.OBJ_ID, V2912.SVAL, MIN(M.DATE_IN), MAX(M.DATE_MODIFY), MAX(V2912.DATE_MODIFY)
    FROM LINKS L10
    JOIN PERSON_MOVEMENTS M ON M.DATE_DEL IS NULL AND M.PERSON_ID = L10.OBJ_ID AND M.DATE_IN >= :V$RANGE_FROM AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :V$RANGE_FROM)
      AND M.LEVEL_ID IN (22, 26, 27) AND M.GROUP_TYPE_ID IN (9, 125, 187)
    -- Есть регид
    JOIN VALS V2912 ON V2912.OBJ_ID = M.PERSON_ID AND V2912.PARAM_ID = 2912 AND V2912.IS_DEL = 0
    WHERE L10.PARENT_TYPE_ID IN (9, 125, 187) AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL -- , 81, 82, 83
    GROUP BY 1, 2
    ORDER BY 1
    INTO :V$STUDENT_ID, :STUDENT_ID, :V$IN_DATE, :V$DT1, :V$DT2
  DO
  BEGIN

    IF(POSITION(':' IN STUDENT_ID) > 0) THEN STUDENT_ID = SUBSTRING(STUDENT_ID FROM 1 FOR POSITION(':' IN STUDENT_ID) - 1);
    STUDENT_ID = REPLACE(STUDENT_ID, '{', '');
    STUDENT_ID = REPLACE(STUDENT_ID, '}', '');
    STUDENT_ID = LOWER(STUDENT_ID);

    V$DT3 = NULL;
    SELECT MAX(MAXVALUE(L20.DATE_INS, V155.DATE_MODIFY, V1570.DATE_MODIFY))
    FROM LINKS L20
    JOIN VALS V155 ON V155.OBJ_ID = L20.OBJ_ID AND V155.PARAM_ID = 155 AND V155.IS_DEL = 0
    JOIN VALS V1570 ON V1570.OBJ_ID = L20.EXT_OBJ_ID AND V1570.PARAM_ID = 1570 AND V1570.IS_DEL = 0
    WHERE L20.PARENT_ID = :V$STUDENT_ID AND L20.OBJ_TYPE_ID = 20 AND L20.DATE_DEL IS NULL
    INTO :V$DT3;

    -- Перебираем учебные годы с года прихода вплоть до текущего года
    -- если дата зачисления была раньше августа - то ученик успел попасть в предыдущий учебный год
    CLASS_YEAR_FROM = EXTRACT(YEAR FROM V$IN_DATE);
    IF(EXTRACT(MONTH FROM V$IN_DATE) < 8) THEN CLASS_YEAR_FROM = CLASS_YEAR_FROM - 1;

    WHILE(CLASS_YEAR_FROM <= V$Y) DO
    BEGIN
      V$YSTART = '01.09.' || CLASS_YEAR_FROM; -- дата начала обучения в году
      V$YEND = '31.08.' || (CLASS_YEAR_FROM + 1);

      -- id учебного года, он обязательно есть
      SELECT FIRST 1 LV.LISTVAL_ID
      FROM LISTVALS LV
      WHERE LV.IS_DEL = 0 AND LV.LIST_ID = 29 AND LV.COST = :CLASS_YEAR_FROM
      INTO :V$YEAR_ID;

      -- Внимание: выборку PMARKS делаем только по текущему учебному году, потому как за прошлые годы невозможно посчитать рекомендованную оценку
      -- Предыдущие годы предполагается что все уже загружено. В случае чистки загружать по данным РК
      FOR
        SELECT DISTINCT J.SUBJECT_ID, V1171.LISTVAL_ID, V.MARK_TYPE_ID, V1174.VAL, COALESCE(V.DATE_MODIFY, F.DATE_MODIFY, M.DATE_MODIFY)
        FROM PERSON_MOVEMENTS M
        JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.GRADE_ID = M.GROUP_ID AND J.JOURNAL_TYPE = 0 AND J.YEAR_ID = :V$YEAR_ID
        JOIN LINKS L154 ON L154.PARENT_ID = J.PERIOD_ID AND L154.OBJ_TYPE_ID = 154 AND L154.DATE_DEL IS NULL
        JOIN VALL V1171 ON V1171.OBJ_ID = L154.OBJ_ID AND V1171.PARAM_ID = 1171 AND V1171.IS_DEL = 0
        JOIN VALD V1174 ON V1174.OBJ_ID = L154.OBJ_ID AND V1174.PARAM_ID = 1174 AND V1174.IS_DEL = 0
        LEFT JOIN CJ2_JOURNAL_FINALS F ON F.DATE_DEL IS NULL AND F.CJ_ID = J.OBJ_ID AND F.FINAL_TYPE = V1171.LISTVAL_ID
        LEFT JOIN CJ2_MARK V ON V.DATE_DEL IS NULL AND V.STUDENT_ID = M.PERSON_ID AND V.FINAL_ID = F.OBJ_ID
        WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :V$STUDENT_ID AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :V$RANGE_FROM) AND (:V$Y = :CLASS_YEAR_FROM)
          AND M.GROUP_TYPE_ID = 179 AND M.LEVEL_ID IN (22, 26, 27)
        ORDER BY 1, 2
        INTO :SUBJECT_ID, :V$MT_ID, :V$MARKVAL, :CREATE_DATETIME, :V$DT4
      DO
      BEGIN
        SUBJECT_NAME = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:SUBJECT_ID));

        ID = STUDENT_ID || 'S' || SUBJECT_ID || 'Y' || CLASS_YEAR_FROM || 'P' || V$MT_ID;

        -- Восстанавливаем id класса на дату отметки
        V$CLASS_ID = NULL;
        SELECT FIRST 1 M.GROUP_ID, CAST(LV.COST AS INTEGER)
        FROM PERSON_MOVEMENTS M
        JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID IN (9, 187)
        JOIN LISTVALS LV ON LV.LISTVAL_ID = M.STAGE_ID
        WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :V$STUDENT_ID AND M.DATE_IN <= :CREATE_DATETIME AND M.LEVEL_ID IN (22, 26, 27)
        ORDER BY M.DATE_OUT DESC NULLS FIRST
        INTO :V$CLASS_ID, :CLASS_NUM;

        -- Если вдруг с датой отметки полная шляпа, выбираем вообще что найдется
        IF(V$CLASS_ID IS NULL) THEN
        SELECT FIRST 1 M.GROUP_ID, CAST(LV.COST AS INTEGER)
        FROM PERSON_MOVEMENTS M
        JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID IN (9, 187)
        JOIN LISTVALS LV ON LV.LISTVAL_ID = M.STAGE_ID
        WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :V$STUDENT_ID AND M.LEVEL_ID IN (22, 26, 27)
        ORDER BY M.DATE_IN
        INTO :V$CLASS_ID, :CLASS_NUM;

        CLASS_ID = V$CLASS_ID || 'Y' || CLASS_YEAR_FROM;

        IF(V$MARKVAL IS NULL OR (V$MARKVAL >= 401 AND V$MARKVAL <= 405)) THEN
        BEGIN
          MARK_SCALE_VALUE = '1';
          MARK_SCALE_CODE = '5-points';
          MARK_SCALE_DESCRIPTION = 'Пятибалльная';
          FACT = V$MARKVAL - 401 + 1;
          FIVEPOINT_FACT = FACT;
        END
        ELSE IF(V$MARKVAL >= 101 AND V$MARKVAL <= 102) THEN
        BEGIN
          MARK_SCALE_VALUE = '5';
          MARK_SCALE_CODE = 'pass/fail';
          MARK_SCALE_DESCRIPTION = 'Зачет-Незачет';
          IF(V$MARKVAL = 101) THEN BEGIN
            FACT = 'Зачет';
            FIVEPOINT_FACT = 5;
          END
          ELSE BEGIN
            FACT = 'Незачет';
            FIVEPOINT_FACT = 1;
          END
        END
        ELSE IF(V$MARKVAL >= 601 AND V$MARKVAL <= 700) THEN
        BEGIN
          MARK_SCALE_VALUE = '3';
          MARK_SCALE_CODE = '100-points';
          MARK_SCALE_DESCRIPTION = 'Стобалльная';
          FACT = V$MARKVAL - 601 + 1;
          FIVEPOINT_FACT = 1 + CAST(ROUND((V$MARKVAL - 601 + 1) / 25) AS INTEGER);
        END
        ELSE
        BEGIN
          MARK_SCALE_VALUE = '6';
          MARK_SCALE_CODE = 'nomarks';
          MARK_SCALE_DESCRIPTION = 'Безотметочная';
          FACT = NULL;
          FIVEPOINT_FACT = NULL;
        END

        IF(V$MT_ID IN (3002, 3003, 3004, 3005)) THEN BEGIN
          PERIOD_NUM = V$MT_ID - 3002 + 1;
          PERIOD_ID = CLASS_YEAR_FROM || '-Q' || PERIOD_NUM;
        END
        ELSE IF(V$MT_ID IN (3009, 3010)) THEN BEGIN
          PERIOD_NUM = V$MT_ID - 3009 + 1;
          PERIOD_ID = CLASS_YEAR_FROM || '-H' || PERIOD_NUM;
        END
        ELSE IF(V$MT_ID IN (3006, 3007, 3008)) THEN BEGIN
          PERIOD_NUM = V$MT_ID - 3006 + 1;
          PERIOD_ID = CLASS_YEAR_FROM || '-T' || PERIOD_NUM;
        END
        -- семестры ?!!!

        -- Прогнозная отметка - только в текущем году, выбираем по данным статистики на последнюю дату
        RECENT_PLAN = NULL;
        FIVEPOINT_RECENT_PLAN = NULL;
        V$DT5 = NULL;
        IF(CLASS_YEAR_FROM = V$Y AND V$MT_ID IS NOT NULL) THEN
        BEGIN
          V$MV = NULL;
          SELECT FIRST 1 R.RATE_VALUE, R.DATE_MODIFY
          FROM CJ2_STUDENT_RATING R
          WHERE R.DATE_DEL IS NULL AND R.STUDENT_ID = :V$STUDENT_ID AND R.SUBJECT_ID = :SUBJECT_ID AND R.RATE_DATE <= :CREATE_DATETIME AND R.RATE_DATE > :V$RANGE_CY
          ORDER BY R.RATE_DATE DESC
          INTO :V$MV, :V$DT5;

          IF(V$MV IS NOT NULL) THEN
          BEGIN
            RECENT_PLAN = CAST(V$MV AS NUMERIC(18, 1));
            FIVEPOINT_RECENT_PLAN = CAST(V$MV AS NUMERIC(18, 1));
          END
        END

        -- Изменение: для обеспечения актуальности нужно слать итоговые оценки не реже 1 раза в 3 дня, даже если ничего не меняется

        IF(I$DT1 IS NULL OR V$DT1 >= I$DT1 OR V$DT2 >= I$DT1 OR V$DT3 >= I$DT1 OR V$DT4 >= I$DT1 OR V$DT5 >= I$DT1 OR V$TM <= DATEADD(-3 DAY TO :I$DT1)) THEN
        BEGIN
          IF(FACT IS NOT NULL OR RECENT_PLAN IS NOT NULL) THEN
          SUSPEND;
        END

      END

      CLASS_YEAR_FROM = CLASS_YEAR_FROM + 1;
    END

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_MS_POSITIONS (
    I$DT1 TIMESTAMP,
    I$DT2 TIMESTAMP NOT NULL = current_timestamp)
RETURNS (
    CODE VARCHAR(60),
    POSITION_LIST_URI VARCHAR(200),
    NAME VARCHAR(1000),
    FTE VARCHAR(40),
    RATE VARCHAR(40),
    SALARY VARCHAR(40),
    EXTRA_BUDGET VARCHAR(40),
    NOTE VARCHAR(1000),
    CREATE_DATETIME TIMESTAMP,
    SEND_DATETIME TIMESTAMP)
AS
declare variable V$SCHOOL_ID bigint;
declare variable V$GP_ID bigint;
declare variable V$Y integer;
declare variable V$DT1 timestamp;
declare variable V$DT2 timestamp;
declare variable V$DT3 timestamp;
declare variable SCHOOL_ID varchar(40);
declare variable V$TEACHER_RATE double precision;
declare variable NC timestamp;
begin

  SEND_DATETIME = I$DT2;
  NC = '01.01.2023';

  SELECT FIRST 1 L2.OBJ_ID, V1236.LISTVAL_ID, LV.COST, V9.VAL, COALESCE(V1342.VAL, 0)
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  JOIN VALS V9 ON V9.OBJ_ID = L2.OBJ_ID AND V9.PARAM_ID = 9 AND V9.IS_DEL = 0
  LEFT JOIN VALF V1342 ON V1342.OBJ_ID = L2.OBJ_ID AND V1342.PARAM_ID = 1342 AND V1342.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$SCHOOL_ID, :V$GP_ID, :V$Y, :SCHOOL_ID, :V$TEACHER_RATE;

  POSITION_LIST_URI = 'https://dnevnik2.petersburgedu.ru/stuff/' || SCHOOL_ID || '/' || V$Y;

  -- Общая должность "учитель" с суммарным количеством ставок
  -- Выгружаем вообще всегда
  IF(V$TEACHER_RATE > 0) THEN
  BEGIN
    CODE = 'teacher' || SCHOOL_ID;
    NAME = 'Учитель';
    FTE = CAST(V$TEACHER_RATE AS NUMERIC(18, 2));
    V$DT1 = '01.09.' || V$Y;
    CREATE_DATETIME = V$DT1;
    SUSPEND;
  END

  -- Выдаем все должности с ненулевым количеством ставок
  FOR
    SELECT L13.OBJ_ID, V66.VAL, CAST(V62.VAL AS NUMERIC(18, 2)),
      MAXVALUE(COALESCE(L13.DATE_MODIFY, :NC), COALESCE(V66.DATE_MODIFY, :NC), COALESCE(V62.DATE_MODIFY, :NC))
    FROM LINKS L13
    JOIN VALS V66 ON V66.OBJ_ID = L13.OBJ_ID AND V66.PARAM_ID = 66 AND V66.IS_DEL = 0
    JOIN VALF V62 ON V62.OBJ_ID = L13.OBJ_ID AND V62.PARAM_ID = 62 AND V62.IS_DEL = 0 AND V62.VAL > 0
    WHERE L13.PARENT_ID = :V$SCHOOL_ID AND L13.OBJ_TYPE_ID = 13 AND L13.DATE_DEL IS NULL
    INTO :CODE, :NAME, :FTE, :V$DT1
  DO
  BEGIN
    CREATE_DATETIME = V$DT1;

    IF(I$DT1 IS NULL OR V$DT1 >= I$DT1 OR V$DT2 >= I$DT1 OR V$DT3 >= I$DT1) THEN
    SUSPEND;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_MS_POSITION_LIST (
    I$DT1 TIMESTAMP,
    I$DT2 TIMESTAMP NOT NULL = current_timestamp)
RETURNS (
    URI VARCHAR(200),
    VERSION VARCHAR(60),
    ID VARCHAR(60),
    KIND VARCHAR(60),
    SCHOOL_ID VARCHAR(60),
    ACADEM_YEAR INTEGER,
    START_DATETIME TIMESTAMP,
    END_DATETIME TIMESTAMP,
    TOTAL_FTE VARCHAR(40),
    TOTAL_RATE VARCHAR(40),
    TOTAL_SALARY VARCHAR(40),
    TOTAL_EXTRA_BUDGET VARCHAR(40),
    NOTE VARCHAR(1000),
    STATUS INTEGER,
    REASON_CODE VARCHAR(20),
    REASON_VALUE INTEGER,
    REASON_DESCRIPTION VARCHAR(100),
    CREATE_DATETIME TIMESTAMP,
    SEND_DATETIME TIMESTAMP)
AS
declare variable V$SCHOOL_ID bigint;
declare variable V$GP_ID bigint;
declare variable V$Y integer;
declare variable V$DT1 timestamp;
declare variable V$DT2 timestamp;
declare variable V$DT3 timestamp;
begin

  SEND_DATETIME = I$DT2;

  SELECT FIRST 1 L2.OBJ_ID, V1236.LISTVAL_ID, LV.COST, V9.VAL
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  JOIN VALS V9 ON V9.OBJ_ID = L2.OBJ_ID AND V9.PARAM_ID = 9 AND V9.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$SCHOOL_ID, :V$GP_ID, :V$Y, :SCHOOL_ID;

  -- ID, KIND не заполняем
  -- ID = SCHOOL_ID || ':' || V$Y;
  URI = 'https://dnevnik2.petersburgedu.ru/stuff/' || SCHOOL_ID || '/' || V$Y;
  ACADEM_YEAR = V$Y;

  START_DATETIME = '01.09.' || V$Y;
  END_DATETIME = '31.08.' || (V$Y + 1) || ' 23:59:59';
  STATUS = 1;
  "VERSION" = '1';

  -- REASON не заполняем

  -- Ставки тоже не заполняем
  CREATE_DATETIME = '01.09.' || V$Y;

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_MS_PRECALC
AS
DECLARE VARIABLE V TIMESTAMP;
DECLARE VARIABLE C VARCHAR(2);
begin

  -- В СПО не пересчитываем расписание
  C = (SELECT STATUS FROM OU_LICENCE_TYPE);
  IF(C = 'C') THEN EXIT;

  -- Пересчет расписания - не чаще раза в сутки
  SELECT FIRST 1 CAST(INFO_VAL AS TIMESTAMP)
  FROM INFO
  WHERE INFO_CODE = 'MS_LAST_EXPORT_SCHED'
  INTO :V;

  IF(V IS NULL OR V > DATEADD(1 DAY TO CURRENT_TIMESTAMP) OR V < DATEADD(-1440 MINUTE TO CURRENT_TIMESTAMP)) THEN
  BEGIN
    IF(V IS NULL) THEN
      INSERT INTO INFO
      (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('MS_LAST_EXPORT_SCHED', 'MS_LAST_EXPORT_SCHED', CURRENT_TIMESTAMP);
    ELSE
      UPDATE INFO
      SET INFO_VAL = CURRENT_TIMESTAMP
      WHERE INFO_CODE = 'MS_LAST_EXPORT_SCHED';

    EXECUTE PROCEDURE CJ2_SCHEDULE_GEN;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_MS_P_ORG_UNIT (
    I$DT1 TIMESTAMP,
    I$DT2 TIMESTAMP NOT NULL = current_timestamp)
RETURNS (
    POSITION_CODE VARCHAR(60),
    ORGANISATION_UNIT_CODE VARCHAR(60),
    CREATE_DATETIME TIMESTAMP,
    SEND_DATETIME TIMESTAMP)
AS
declare variable V$SCHOOL_ID bigint;
declare variable V$GP_ID bigint;
declare variable V$Y integer;
declare variable V$DT1 timestamp;
declare variable V$DT2 timestamp;
declare variable V$DT3 timestamp;
declare variable NC timestamp;
declare variable V$TEACHER_RATE double precision;
begin

  SEND_DATETIME = I$DT2;
  NC = '01.01.2023';

  SELECT FIRST 1 L2.OBJ_ID, V1236.LISTVAL_ID, LV.COST, V9.VAL, COALESCE(V1342.VAL, 0),
    MAXVALUE(COALESCE(L2.DATE_MODIFY, :NC), COALESCE(V9.DATE_MODIFY, :NC))
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  JOIN VALS V9 ON V9.OBJ_ID = L2.OBJ_ID AND V9.PARAM_ID = 9 AND V9.IS_DEL = 0
  LEFT JOIN VALF V1342 ON V1342.OBJ_ID = L2.OBJ_ID AND V1342.PARAM_ID = 1342 AND V1342.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$SCHOOL_ID, :V$GP_ID, :V$Y, :ORGANISATION_UNIT_CODE, :V$TEACHER_RATE, :V$DT1;

  -- Общая должность "учитель" с суммарным количеством ставок
  -- Выгружаем вообще всегда
  IF(V$TEACHER_RATE > 0) THEN
  BEGIN
    POSITION_CODE = 'teacher' || ORGANISATION_UNIT_CODE;
    V$DT1 = '01.09.' || V$Y;
    CREATE_DATETIME = V$DT1;
    SUSPEND;
  END

  -- Выдаем все должности с ненулевым количеством ставок
  FOR
    SELECT L13.OBJ_ID,
      MAXVALUE(COALESCE(L13.DATE_MODIFY, :NC), COALESCE(V66.DATE_MODIFY, :NC), COALESCE(V62.DATE_MODIFY, :NC))
    FROM LINKS L13
    JOIN VALS V66 ON V66.OBJ_ID = L13.OBJ_ID AND V66.PARAM_ID = 66 AND V66.IS_DEL = 0
    JOIN VALF V62 ON V62.OBJ_ID = L13.OBJ_ID AND V62.PARAM_ID = 62 AND V62.IS_DEL = 0 AND V62.VAL > 0
    WHERE L13.PARENT_ID = :V$SCHOOL_ID AND L13.OBJ_TYPE_ID = 13 AND L13.DATE_DEL IS NULL
    INTO :POSITION_CODE, :V$DT1
  DO
  BEGIN
    CREATE_DATETIME = V$DT1;

    IF(I$DT1 IS NULL OR V$DT1 >= I$DT1 OR V$DT2 >= I$DT1 OR V$DT3 >= I$DT1) THEN
    SUSPEND;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_MS_QUALIFICATION (
    I$DT1 TIMESTAMP,
    I$DT2 TIMESTAMP NOT NULL = current_timestamp)
RETURNS (
    ID VARCHAR(60),
    TYPE_QUALIFICATION INTEGER,
    CODE INTEGER,
    NAME VARCHAR(1000),
    QUANTITY VARCHAR(40),
    TEACHER_ID VARCHAR(60),
    START_DATETIME TIMESTAMP,
    END_DATETIME TIMESTAMP,
    STATUS_CODE VARCHAR(40),
    STATUS_VALUE INTEGER,
    STATUS_DESCRIPTION VARCHAR(400),
    REASON_CODE VARCHAR(40),
    REASON_VALUE INTEGER,
    REASON_DESCRIPTION VARCHAR(400),
    CREATE_DATETIME TIMESTAMP,
    SEND_DATETIME TIMESTAMP)
AS
declare variable V$SCHOOL_ID bigint;
declare variable V$GP_ID bigint;
declare variable V$Y integer;
declare variable V$DT1 timestamp;
declare variable V$DT2 timestamp;
declare variable V$DT3 timestamp;
declare variable V$PERSON_ID bigint;
declare variable V$YDATE date;
declare variable V$IS_TEACHER smallint;
declare variable V$CT bigint;
declare variable V$TYPE_ID bigint;
begin

  SEND_DATETIME = I$DT2;

  SELECT FIRST 1 L2.OBJ_ID, V1236.LISTVAL_ID, LV.COST
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  JOIN VALS V9 ON V9.OBJ_ID = L2.OBJ_ID AND V9.PARAM_ID = 9 AND V9.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$SCHOOL_ID, :V$GP_ID, :V$Y;

  V$YDATE = '30.08.' || V$Y;

  FOR
    -- Действующие
    SELECT SID, MAX(OBJ_ID), MAX(DATE_MODIFY)
    FROM (
      SELECT V2915.SVAL SID, L14.OBJ_ID, L14.DATE_MODIFY
      FROM LINKS L2
      JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
      JOIN VALS V2915 ON V2915.OBJ_ID = L14.OBJ_ID AND V2915.PARAM_ID = 2915 AND V2915.IS_DEL = 0
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      UNION
      -- Уволенные не ранее даты начала текущего учебного года
      SELECT V2915.SVAL, L14.OBJ_ID, L14.DATE_MODIFY
      FROM LINKS L2
      JOIN LINKS L84 ON L84.PARENT_ID = L2.OBJ_ID AND L84.OBJ_TYPE_ID = 84 AND L84.DATE_DEL IS NULL
      JOIN LINKS L14 ON L14.PARENT_ID = L84.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
      JOIN VALS V2915 ON V2915.OBJ_ID = L14.OBJ_ID AND V2915.PARAM_ID = 2915 AND V2915.IS_DEL = 0
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND EXISTS(
        SELECT FIRST 1 1
        FROM LINKS L15
        LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
        WHERE L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL AND (V74.VAL IS NULL OR V74.VAL >= :V$YDATE)
      )
    )
    GROUP BY 1
    ORDER BY 1
    INTO :TEACHER_ID, :V$PERSON_ID, :V$DT1
  DO
  BEGIN
    IF(POSITION(':' IN TEACHER_ID) > 0) THEN TEACHER_ID = SUBSTRING(TEACHER_ID FROM 1 FOR POSITION(':' IN TEACHER_ID) - 1);
    TEACHER_ID = REPLACE(TEACHER_ID, '{', '');
    TEACHER_ID = REPLACE(TEACHER_ID, '}', '');
    TEACHER_ID = LOWER(TEACHER_ID);

    -- Выбираем только действующие учительские и руководящие должности
    V$IS_TEACHER = 0;
    SELECT FIRST 1 1
    FROM LINKS L15
    JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
    JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
    JOIN VALS V66 ON V66.OBJ_ID = LP13.PARENT_ID AND V66.PARAM_ID = 66 AND V66.IS_DEL = 0
    JOIN VALL V72 ON V72.OBJ_ID = L15.OBJ_ID AND V72.PARAM_ID = 72 AND V72.IS_DEL = 0
    JOIN VALL V63 ON V63.OBJ_ID = LP13.PARENT_ID AND V63.PARAM_ID = 63 AND V63.IS_DEL = 0 -- группа должностей
    JOIN VALL V64 ON V64.OBJ_ID = LP13.PARENT_ID AND V64.PARAM_ID = 64 AND V64.IS_DEL = 0 -- подгруппа должностей
    JOIN VALL V58 ON V58.OBJ_ID = LP13.PARENT_ID AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0 -- сама должность
    WHERE L15.PARENT_ID = :V$PERSON_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
      AND V74.VAL IS NULL
      -- исключаем финансовые и вспомогательные должности 2 уровня
      AND V58.LISTVAL_ID NOT IN (69, 86, 95, 141, 3300, 11095)
      -- исключаем подгруппы рабочих, служащих, персонал
      AND V64.LISTVAL_ID NOT IN (1313, 1323, 1257)
    INTO :V$IS_TEACHER;

    IF(V$IS_TEACHER = 1) THEN
    BEGIN
      FOR
        -- Аттестация на категорию
        SELECT L34.OBJ_ID, V544.VAL, L34.OBJ_TYPE_ID, V545.LISTVAL_ID, MAXVALUE(L34.DATE_INS, V544.DATE_MODIFY, V545.DATE_MODIFY)
        FROM LINKS L34
        JOIN VALD V544 ON V544.OBJ_ID = L34.OBJ_ID AND V544.PARAM_ID = 544 AND V544.IS_DEL = 0
        JOIN VALL V545 ON V545.OBJ_ID = L34.OBJ_ID AND V545.PARAM_ID = 545 AND V545.IS_DEL = 0 AND V545.LISTVAL_ID IN (1208, 1209)
        WHERE L34.PARENT_ID = :V$PERSON_ID AND L34.OBJ_TYPE_ID = 34 AND L34.DATE_DEL IS NULL
        -- Повышение квалификации
        UNION
        SELECT L36.OBJ_ID, V310.VAL, L36.OBJ_TYPE_ID, NULL, MAXVALUE(L36.DATE_INS, V310.DATE_MODIFY)
        FROM LINKS L36
        JOIN VALD V310 ON V310.OBJ_ID = L36.OBJ_ID AND V310.PARAM_ID = 310 AND V310.IS_DEL = 0
        WHERE L36.PARENT_ID = :V$PERSON_ID AND L36.OBJ_TYPE_ID = 36 AND L36.DATE_DEL IS NULL
        ORDER BY 2
        INTO :ID, :START_DATETIME, :V$TYPE_ID, :V$CT, :V$DT2
      DO
      BEGIN
        CREATE_DATETIME = V$DT2;

        STATUS_VALUE = 1;
        STATUS_CODE = 'active';
        STATUS_DESCRIPTION = 'Действует';

        NAME = NULL;
        CODE = NULL;
        IF(V$TYPE_ID = 34) THEN
        BEGIN
          REASON_VALUE = 7;
          REASON_CODE = 'attestation_comission';
          REASON_DESCRIPTION = 'Решение аттестационной комиссии о присвоении, подтверждении или снятии квалификационной категории';

          TYPE_QUALIFICATION = 7; -- Квалификационная категория педагогического работника
          IF(V$CT = 1208) THEN CODE = 2; -- высшая
          ELSE IF(V$CT = 1209) THEN CODE = 1; -- первая

          NAME = 'Прохождение аттестации с целью установления соответствия уровня квалификации';
        END
        ELSE IF(V$TYPE_ID = 36) THEN
        BEGIN
          REASON_VALUE = 3;
          REASON_CODE = 'qualification';
          REASON_DESCRIPTION = 'Документ, подтверждающий прохождение курсов повышения квалификации - диплом, свидетельство, удостоверение';

          TYPE_QUALIFICATION = 8; -- Повышение квалификации

          NAME = 'Повышение квалификации';
        END

        IF(I$DT1 IS NULL OR V$DT1 >= I$DT1 OR V$DT2 >= I$DT1) THEN
        SUSPEND;
      END
    END
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_MS_REGION_EXPORT (
    I$RAISE SMALLINT = 1,
    I$TYPE INTEGER = 403)
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(4000))
AS
DECLARE VARIABLE RQ VARCHAR(100);
DECLARE VARIABLE RQS VARCHAR(100);
DECLARE VARIABLE RQP VARCHAR(100);
DECLARE VARIABLE RQL VARCHAR(100);
DECLARE VARIABLE V$REGID VARCHAR(100);
DECLARE VARIABLE V$PERSON_ID BIGINT;
DECLARE VARIABLE S VARCHAR(1000);
DECLARE VARIABLE S1 VARCHAR(400);
DECLARE VARIABLE S2 VARCHAR(400);
DECLARE VARIABLE S3 VARCHAR(400);
DECLARE VARIABLE SD DATE;
DECLARE VARIABLE D2 DATE;
DECLARE VARIABLE SSEX BIGINT;
DECLARE VARIABLE V$DOC_TYPE BIGINT;
DECLARE VARIABLE V$WHERE_TYPE BIGINT;
DECLARE VARIABLE V$WHERE_ID BIGINT;
DECLARE VARIABLE V$OU_ID BIGINT;
DECLARE VARIABLE V$STAGE INTEGER;
DECLARE VARIABLE V$GROUP_ID BIGINT;
DECLARE VARIABLE V$PLAN_ID BIGINT;
DECLARE VARIABLE V$DURATION INTEGER;
DECLARE VARIABLE V$DURMONTH INTEGER;
DECLARE VARIABLE D3 DATE;
DECLARE VARIABLE D4 DATE;
DECLARE VARIABLE V$GRADUATE BIGINT;
DECLARE VARIABLE V$AGE16 DATE;
DECLARE VARIABLE V$MDT TIMESTAMP;
begin

  -- 403  = СПО, 404 = Школа
  IF(I$TYPE = 403) THEN
  BEGIN
    RQ = 'CollegeRequest';
    RQS = 'СведКолледж';
    RQP = 'college';
    RQL = 'tns&colon;' || RQ || ':tns&colon;Документ:tns&colon;' || RQS || ':tns&colon;СведОрг:tns&colon;СведЛиценз';
  END
  ELSE
  BEGIN
    RQ = 'schoolRequest';
    RQS = 'СведОбуч';
    RQP = 'school';
    RQL = 'tns&colon;' || RQ || ':tns&colon;Документ:tns&colon;' || RQS || ':tns&colon;СведЛиценз';
  END

  TAG_NAME = 'tns&colon;' || RQ || '';
  VAL = NULL;
  SUSPEND;

  TAG_NAME = 'tns&colon;' || RQ || '::xmlns&colon;xsi';
  VAL = 'http://www.w3.org/2001/XMLSchema-instance';
  SUSPEND;

  TAG_NAME = 'tns&colon;' || RQ || '::xmlns&colon;tns';
  VAL = 'urn://x-artefacts-fns-' || RQP || '/root/1.0.0';
  SUSPEND;

  TAG_NAME = 'tns&colon;' || RQ || '::xmlns&colon;fns';
  VAL = 'urn://x-artefacts-fns-' || RQP || '/types/1.0.0';
  SUSPEND;

  -- guid мы сгенерировать не можем, поэтому генерим что получается
  TAG_NAME = 'tns&colon;' || RQ || '::ИдСвед';
  VAL = (SELECT VAL FROM DATE2ISO(CURRENT_TIMESTAMP, 1));
  VAL = REPLACE(VAL, ':', '-');
  SUSPEND;

  TAG_NAME = 'tns&colon;' || RQ || '::ДатаСвед';
  VAL = (SELECT RESULT FROM DATE2STR(CURRENT_DATE));
  SUSPEND;

  -- Всегда полная выгрузка
  TAG_NAME = 'tns&colon;' || RQ || '::ТипВыгр';
  VAL = '1';
  SUSPEND;

  -- Дата рождения такова, что на конец текущего года исполнится 16 лет
  V$AGE16 = '31.12.' || (EXTRACT(YEAR FROM CURRENT_DATE) - 16);

  -- Корректируем таблицу VALS
  -- Убираем старые значения GUID, оставляем все в LOWERCASE
  -- Суффиксную часть убираем в XVAL
  FOR
    SELECT V.OBJ_ID, V.SVAL
    FROM VALS V
    WHERE V.PARAM_ID = 2912 AND V.XVAL IS NULL AND V.IS_DEL = 0
    ORDER BY 1, 2
    INTO :V$PERSON_ID, :S1
  DO
  BEGIN
    S1 = REPLACE(REPLACE(LOWER(S1), '{', ''), '}', '');
    S2 = SUBSTRING(S1 FROM 1 FOR 36);
    S3 = SUBSTRING(S1 FROM 38); -- после двоеточия, если там что-то есть
    IF(S3 = '') THEN S3 = NULL;

    UPDATE VALS
    SET VAL = :S2, XVAL = :S3
    WHERE OBJ_ID = :V$PERSON_ID AND PARAM_ID = 2912;
  END

  -- Так конечно нехорошо, но вытащить количество документов до основной выборки иначе никак
  TAG_NAME = 'tns&colon;' || RQ || '::КолДок';
  SELECT COUNT(*) FROM (
    SELECT DISTINCT V2912.SVAL REGID
    FROM VALS V2912
    JOIN LINKS LPG ON LPG.OBJ_ID = V2912.OBJ_ID AND LPG.PARENT_TYPE_ID IN (9, 289) AND LPG.DATE_DEL IS NULL
    JOIN VALD V89 ON V89.OBJ_ID = V2912.OBJ_ID AND V89.PARAM_ID = 89 AND (V89.VAL <= :V$AGE16 OR :I$TYPE = 403)
    WHERE V2912.PARAM_ID = 2912 AND V2912.IS_DEL = 0 AND (:I$TYPE = 404 OR LPG.PARENT_TYPE_ID = 289 OR EXISTS(
      SELECT FIRST 1 1
      FROM LINKS LP8
      JOIN LINKS LP7 ON LP7.OBJ_ID = LP8.PARENT_ID AND LP7.PARENT_TYPE_ID = 7 AND LP7.DATE_DEL IS NULL
      JOIN VALL V43 ON V43.OBJ_ID = LP7.PARENT_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0 AND V43.LISTVAL_ID = 29
      -- код профессии в группе
      JOIN VALL VP ON VP.OBJ_ID = LPG.PARENT_ID AND VP.PARAM_ID IN (2165, 2821) AND VP.IS_DEL = 0
      WHERE LP8.OBJ_ID = LPG.PARENT_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
    ))
    -- есть документ с типом паспорт
    AND EXISTS(
      SELECT FIRST 1 1
      FROM LINKS L79
      JOIN VALL V441 ON V441.OBJ_ID = L79.OBJ_ID AND V441.PARAM_ID = 441 AND V441.IS_DEL = 0 AND V441.LISTVAL_ID = 1368
      WHERE L79.PARENT_ID = LPG.OBJ_ID AND L79.OBJ_TYPE_ID = 79 AND L79.DATE_DEL IS NULL
    )
  )
  INTO :VAL;
  -- VAL = 1000;
  SUSPEND;

  -- Выбираем список уникальных обучаюющихся, числящихся в ОУ на текущий момент
  -- Выбираем только основную образовательную программу СПО, но не ДПО или профобучение
  -- и только те, где указан код профессии
  -- + только имеющие российский паспорт
  -- Обрезаем суффиксную часть id. По факту в СПО нет записей старого формата без суффикса
  FOR
    -- Меняем выборку, чтобы сразу доставать и РегИД, и OBJ_ID ученика
    -- FIRST 1000
    SELECT V2912.SVAL, MIN(LPG.OBJ_ID)
    FROM VALS V2912
    JOIN LINKS LPG ON LPG.OBJ_ID = V2912.OBJ_ID AND LPG.PARENT_TYPE_ID IN (9, 289) AND LPG.DATE_DEL IS NULL
    JOIN VALD V89 ON V89.OBJ_ID = V2912.OBJ_ID AND V89.PARAM_ID = 89 AND (V89.VAL <= :V$AGE16 OR :I$TYPE = 403)
    WHERE V2912.PARAM_ID = 2912 AND V2912.IS_DEL = 0 AND (:I$TYPE = 404 OR LPG.PARENT_TYPE_ID = 289 OR EXISTS(
      SELECT FIRST 1 1
      FROM LINKS LP8
      JOIN LINKS LP7 ON LP7.OBJ_ID = LP8.PARENT_ID AND LP7.PARENT_TYPE_ID = 7 AND LP7.DATE_DEL IS NULL
      JOIN VALL V43 ON V43.OBJ_ID = LP7.PARENT_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0 AND V43.LISTVAL_ID = 29
      -- код профессии в группе
      JOIN VALL VP ON VP.OBJ_ID = LPG.PARENT_ID AND VP.PARAM_ID IN (2165, 2821) AND VP.IS_DEL = 0
      WHERE LP8.OBJ_ID = LPG.PARENT_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
    ))
    -- есть документ с типом паспорт
    AND EXISTS(
      SELECT FIRST 1 1
      FROM LINKS L79
      JOIN VALL V441 ON V441.OBJ_ID = L79.OBJ_ID AND V441.PARAM_ID = 441 AND V441.IS_DEL = 0 AND V441.LISTVAL_ID = 1368
      WHERE L79.PARENT_ID = LPG.OBJ_ID AND L79.OBJ_TYPE_ID = 79 AND L79.DATE_DEL IS NULL
    )
    GROUP BY 1
    ORDER BY 1
    INTO :V$REGID, :V$PERSON_ID
  DO
  BEGIN

    TAG_NAME = 'tns&colon;' || RQ || ':tns&colon;Документ';
    VAL = NULL;
    SUSPEND;

    TAG_NAME = 'tns&colon;' || RQ || ':tns&colon;Документ::ИдДок';
    VAL = V$REGID;
    SUSPEND;

    -- Берем первый попавшийся совпавший вариант
    /*SELECT FIRST 1 LPG.OBJ_ID, LPG.PARENT_TYPE_ID
    FROM VALS V2912
    JOIN LINKS LPG ON LPG.OBJ_ID = V2912.OBJ_ID AND LPG.PARENT_TYPE_ID IN (9, 289) AND LPG.DATE_DEL IS NULL
    WHERE V2912.PARAM_ID = 2912 AND V2912.IS_DEL = 0 AND V2912.SVAL = :V$REGID
    INTO :V$PERSON_ID, :V$WHERE_TYPE;*/
    SELECT FIRST 1 LPG.PARENT_ID, LPG.PARENT_TYPE_ID
    FROM LINKS LPG
    WHERE LPG.OBJ_ID = :V$PERSON_ID AND LPG.PARENT_TYPE_ID IN (9, 289) AND LPG.DATE_DEL IS NULL
    INTO :V$WHERE_ID, :V$WHERE_TYPE;

    -- Есть ли СНИЛС ?
    S = NULL;
    SELECT FIRST 1 REPLACE(REPLACE(V1409.SVAL, '-', ''), ' ', '')
    FROM VALS V1409
    WHERE V1409.OBJ_ID = :V$PERSON_ID AND V1409.PARAM_ID = 1409 AND V1409.IS_DEL = 0
    INTO :S;
    IF(S IS NOT NULL) THEN
    BEGIN
      TAG_NAME = 'tns&colon;' || RQ || ':tns&colon;Документ:tns&colon;ИдФЛ';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'tns&colon;' || RQ || ':tns&colon;Документ:tns&colon;ИдФЛ::СНИЛС';
      VAL = SUBSTRING(S FROM 1 FOR 3) || '-' || SUBSTRING(S FROM 4 FOR 3) || '-' || SUBSTRING(S FROM 7 FOR 3) || ' ' || SUBSTRING(S FROM 10);
      SUSPEND;
    END

    -- ФИО и дата рождения
    SD = NULL;
    S1 = NULL;
    S2 = NULL;
    S3 = NULL;
    SSEX = NULL;
    SELECT FIRST 1 V55.SVAL, V56.SVAL, V57.SVAL, V89.VAL, V88.LISTVAL_ID
    FROM VALS V55
    JOIN VALS V56 ON V56.OBJ_ID = V55.OBJ_ID AND V56.PARAM_ID = 56 AND V56.IS_DEL = 0
    LEFT JOIN VALS V57 ON V57.OBJ_ID = V55.OBJ_ID AND V57.PARAM_ID = 57 AND V57.IS_DEL = 0
    JOIN VALD V89 ON V89.OBJ_ID = V55.OBJ_ID AND V89.PARAM_ID = 89 AND V89.IS_DEL = 0
    LEFT JOIN VALL V88 ON V88.OBJ_ID = V55.OBJ_ID AND V88.PARAM_ID = 88 AND V88.IS_DEL = 0
    WHERE V55.OBJ_ID = :V$PERSON_ID AND V55.PARAM_ID = 55 AND V55.IS_DEL = 0
    INTO :S1, :S2, :S3, :SD, :SSEX;

    TAG_NAME = 'tns&colon;' || RQ || ':tns&colon;Документ:tns&colon;СведФЛ';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'tns&colon;' || RQ || ':tns&colon;Документ:tns&colon;СведФЛ::Пол';
    VAL = IIF(SSEX = 182, '2', '1');
    SUSPEND;

    -- Считаем что фамилия и имя всегда есть
    TAG_NAME = 'tns&colon;' || RQ || ':tns&colon;Документ:tns&colon;СведФЛ:tns&colon;ФИО:fns&colon;Фамилия';
    VAL = S1;
    SUSPEND;
    TAG_NAME = 'tns&colon;' || RQ || ':tns&colon;Документ:tns&colon;СведФЛ:tns&colon;ФИО:fns&colon;Имя';
    VAL = S2;
    SUSPEND;
    IF(S3 IS NULL) THEN
    BEGIN
      TAG_NAME = 'tns&colon;' || RQ || ':tns&colon;Документ:tns&colon;СведФЛ:tns&colon;ФИО:fns&colon;ПрОтсОтч';
      VAL = 1;
    END
    ELSE
    BEGIN
      TAG_NAME = 'tns&colon;' || RQ || ':tns&colon;Документ:tns&colon;СведФЛ:tns&colon;ФИО:fns&colon;Отчество';
      VAL = S3;
    END
    SUSPEND;
    TAG_NAME = 'tns&colon;' || RQ || ':tns&colon;Документ:tns&colon;СведФЛ:tns&colon;ДатаРожд';
    VAL = (SELECT RESULT FROM DATE2STR(:SD));
    SUSPEND;

    -- <tns:УдЛичнФЛ КодВидДок="21" СерДок="8016" НомДок="123584" ДатаДок="14.12.2020" ВыдДок="Отделом УФМС в г.Тобольск" КодВыдДок="004-323"/>
    -- КодВыдДок мы не умеем
    TAG_NAME = 'tns&colon;' || RQ || ':tns&colon;Документ:tns&colon;УдЛичнФЛ';
    VAL = NULL;
    SUSPEND;
    V$DOC_TYPE = NULL;
    S = NULL;
    S1 = NULL;
    S2 = NULL;
    S3 = NULL;
    SD = NULL;
    SELECT FIRST 1 V441.LISTVAL_ID, V442.SVAL, V559.SVAL, V560.VAL, V562.VAL, NULL
    FROM LINKS L79
    JOIN VALL V441 ON V441.OBJ_ID = L79.OBJ_ID AND V441.PARAM_ID = 441 AND V441.IS_DEL = 0 AND V441.LISTVAL_ID = 1368
    LEFT JOIN VALS V442 ON V442.OBJ_ID = L79.OBJ_ID AND V442.PARAM_ID = 442 AND V442.IS_DEL = 0
    JOIN VALS V559 ON V559.OBJ_ID = L79.OBJ_ID AND V559.PARAM_ID = 559 AND V559.IS_DEL = 0
    JOIN VALD V560 ON V560.OBJ_ID = L79.OBJ_ID AND V560.PARAM_ID = 560 AND V560.IS_DEL = 0
    LEFT JOIN VALS V562 ON V562.OBJ_ID = L79.OBJ_ID AND V562.PARAM_ID = 562 AND V562.IS_DEL = 0
    WHERE L79.PARENT_ID = :V$PERSON_ID AND L79.OBJ_TYPE_ID = 79 AND L79.DATE_DEL IS NULL
    INTO :V$DOC_TYPE, :S1, :S2, :SD, :S, :S3;

    IF(V$DOC_TYPE IS NULL AND I$RAISE = 1) THEN EXCEPTION DATA_ERROR 'Для обучающегося ' || V$REGID || ' в одном из ОУ не внесены или не полностью внесены сведения идентифицирующего документа';

    TAG_NAME = 'tns&colon;' || RQ || ':tns&colon;Документ:tns&colon;УдЛичнФЛ::КодВидДок';
    VAL = 21; -- паспорт = всегда, загранпаспорт пока забиваем
    SUSPEND;
    TAG_NAME = 'tns&colon;' || RQ || ':tns&colon;Документ:tns&colon;УдЛичнФЛ::СерДок';
    VAL = S1; -- есть серии где ввели пробел в середине
    IF(CHAR_LENGTH(VAL) <> 4 AND I$RAISE = 1) THEN EXCEPTION DATA_ERROR 'Для обучающегося ' || V$REGID || ' внесенная серия идентифицирующего документа некорректна';
    ELSE VAL = REPLACE(VAL, ' ', '');
    IF(VAL = '') THEN VAL = '4000'; -- в одной из записей нет серии ?
    SUSPEND;
    TAG_NAME = 'tns&colon;' || RQ || ':tns&colon;Документ:tns&colon;УдЛичнФЛ::НомДок';
    VAL = S2;
    IF(CHAR_LENGTH(VAL) <> 6 AND I$RAISE = 1) THEN EXCEPTION DATA_ERROR 'Для обучающегося ' || V$REGID || ' внесенный номер идентифицирующего документа некорректен';
    ELSE VAL = SUBSTRING(VAL FROM 1 FOR 6);
    SUSPEND;
    TAG_NAME = 'tns&colon;' || RQ || ':tns&colon;Документ:tns&colon;УдЛичнФЛ::ДатаДок';
    VAL = (SELECT RESULT FROM DATE2STR(:SD));
    SUSPEND;
    TAG_NAME = 'tns&colon;' || RQ || ':tns&colon;Документ:tns&colon;УдЛичнФЛ::ВыдДок';
    -- В школах есть записи где в КемВыдано сидит nbsp, либо символ пробела с кодом A0
    VAL = REPLACE(S, '&nbsp;', ' ');
    VAL = REPLACE(S, ' ', ' '); -- тут не простой пробел, а специальный A0
    IF(VAL IS NULL OR CHAR_LENGTH(VAL) < 3) THEN VAL = 'ГУ МВД России';
    SUSPEND;

    -- Сведения об ОУ
    -- Если в группе
    IF(V$WHERE_TYPE = 9) THEN
    BEGIN
      SELECT FIRST 1 LP2.PARENT_ID
      FROM LINKS LP8
      JOIN LINKS LP7 ON LP7.OBJ_ID = LP8.PARENT_ID AND LP7.PARENT_TYPE_ID = 7 AND LP7.DATE_DEL IS NULL
      JOIN LINKS LP2 ON LP2.OBJ_ID = LP7.PARENT_ID AND LP2.PARENT_TYPE_ID = 2 AND LP2.DATE_DEL IS NULL
      WHERE LP8.OBJ_ID = :V$WHERE_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
      INTO :V$OU_ID;
    END
    -- Если в академическом отпуске
    ELSE
    BEGIN
      SELECT FIRST 1 LP2.PARENT_ID
      FROM LINKS LP7
      JOIN LINKS LP2 ON LP2.OBJ_ID = LP7.PARENT_ID AND LP2.PARENT_TYPE_ID = 2 AND LP2.DATE_DEL IS NULL
      WHERE LP7.OBJ_ID = :V$WHERE_ID AND LP7.PARENT_TYPE_ID = 7 AND LP7.DATE_DEL IS NULL
      INTO :V$OU_ID;
    END

    TAG_NAME = 'tns&colon;' || RQ || ':tns&colon;Документ:tns&colon;' || RQS || '';
    VAL = NULL;
    SUSPEND;

    -- Тут мы умеем только обучается (1) или в отпуске (4), статуса восстановлен у нас пока нет
    -- с отчисленными будем разбираться позже
    TAG_NAME = 'tns&colon;' || RQ || ':tns&colon;Документ:tns&colon;' || RQS || '::Статус';
    VAL = IIF(V$WHERE_TYPE = 9, 1, 4);
    SUSPEND;

    V$STAGE = NULL;
    V$GRADUATE = NULL;
    V$GROUP_ID = NULL;
    V$PLAN_ID = NULL;
    IF(I$TYPE = 403) THEN
    BEGIN
      TAG_NAME = 'tns&colon;' || RQ || ':tns&colon;Документ:tns&colon;' || RQS || '::КодУровОбр';
      VAL = 10; -- всегда СПО
      SUSPEND;
      --
      TAG_NAME = 'tns&colon;' || RQ || ':tns&colon;Документ:tns&colon;' || RQS || '::НомерКурса';
      SELECT FIRST 1 LV.COST, V1362.LISTVAL_ID, M.GROUP_ID, V3075.VAL, M.DATE_ADD
      FROM PERSON_MOVEMENTS M
      JOIN LISTVALS LV ON LV.LISTVAL_ID = M.STAGE_ID
      LEFT JOIN VALL V1362 ON V1362.OBJ_ID = M.GROUP_ID AND V1362.PARAM_ID = 1362 AND V1362.IS_DEL = 0
      LEFT JOIN VALR V3075 ON V3075.OBJ_ID = M.GROUP_ID AND V3075.PARAM_ID = 3075 AND V3075.IS_DEL = 0
      WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :V$PERSON_ID AND M.DATE_OUT IS NULL AND M.GROUP_TYPE_ID IN (9, 289)
      INTO :V$STAGE, :V$GRADUATE, :V$GROUP_ID, :V$PLAN_ID, :V$MDT;

      -- Если нет в записи движения, пытаемся найти среди соседних
      IF(V$STAGE IS NULL) THEN
      BEGIN
        SELECT FIRST 1 LV.COST
        FROM PERSON_MOVEMENTS M
        JOIN LISTVALS LV ON LV.LISTVAL_ID = M.STAGE_ID
        WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :V$PERSON_ID AND M.GROUP_TYPE_ID = 9 AND M.STAGE_ID IS NOT NULL AND M.DATE_ADD <= :V$MDT
        ORDER BY M.DATE_ADD DESC
        INTO :V$STAGE;

        IF(V$STAGE IS NULL) THEN
        SELECT FIRST 1 LV.COST
        FROM PERSON_MOVEMENTS M
        JOIN LISTVALS LV ON LV.LISTVAL_ID = M.STAGE_ID
        WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :V$PERSON_ID AND M.GROUP_TYPE_ID = 9 AND M.STAGE_ID IS NOT NULL AND M.DATE_ADD > :V$MDT
        ORDER BY M.DATE_ADD
        INTO :V$STAGE;
      END

      -- Для СПО в случае академического отпуска план не найдется - пробуем его найти из последнего класса
      IF(V$PLAN_ID IS NULL) THEN
      SELECT FIRST 1 M.GROUP_ID, V3075.VAL
      FROM PERSON_MOVEMENTS M
      LEFT JOIN VALR V3075 ON V3075.OBJ_ID = M.GROUP_ID AND V3075.PARAM_ID = 3075 AND V3075.IS_DEL = 0
      WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :V$PERSON_ID AND M.GROUP_TYPE_ID = 9
      ORDER BY M.DATE_IN DESC
      INTO :V$GROUP_ID, :V$PLAN_ID;

      VAL = V$STAGE;
      SUSPEND;
    END
    IF(I$TYPE = 404) THEN
    BEGIN
      --
      TAG_NAME = 'tns&colon;' || RQ || ':tns&colon;Документ:tns&colon;' || RQS || '::Класс';
      SELECT FIRST 1 LV.COST, V1362.LISTVAL_ID, M.GROUP_ID
      FROM PERSON_MOVEMENTS M
      JOIN LISTVALS LV ON LV.LISTVAL_ID = M.STAGE_ID
      LEFT JOIN VALL V1362 ON V1362.OBJ_ID = M.GROUP_ID AND V1362.PARAM_ID = 1362 AND V1362.IS_DEL = 0
      WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :V$PERSON_ID AND M.DATE_OUT IS NULL AND M.GROUP_TYPE_ID IN (9)
      INTO :V$STAGE, :V$GRADUATE, :V$GROUP_ID;
      VAL = V$STAGE;
      SUSPEND;
    END
    --
    TAG_NAME = 'tns&colon;' || RQ || ':tns&colon;Документ:tns&colon;' || RQS || '::';
    IF(I$TYPE = 403) THEN TAG_NAME = TAG_NAME || 'ДатаЗачисл'; ELSE TAG_NAME = TAG_NAME || 'ДатаПоступ';
    SD = NULL;
    D2 = NULL;
    S1 = NULL;
    SELECT FIRST 1 M.DATE_IN, M.ORDER_DATE_IN, M.ORDER_NUM_IN
    FROM PERSON_MOVEMENTS M
    WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :V$PERSON_ID AND M.GROUP_TYPE_ID = 9
    ORDER BY 1
    INTO :SD, :D2, :S1;
    VAL = (SELECT RESULT FROM DATE2STR(:SD));
    SUSPEND;

    IF(D2 IS NULL) THEN D2 = SD;
    IF(D2 < '01.01.2000') THEN D2 = SD;
    IF(S1 IS NULL) THEN S1 = 'Неизвестно';

    IF(I$TYPE = 404) THEN
    BEGIN
      -- Дата зачисления должна быть Август или Сентябрь. Если Январь-Май, то переносим на предыдущий год
      IF(EXTRACT(MONTH FROM SD) <= 5) THEN SD = '01.09.' || (EXTRACT(YEAR FROM SD) - 1); ELSE SD = '01.09.' || EXTRACT(YEAR FROM SD);
      -- Считаем дату окончания исходя из 11 лет обучения, корректируем если 12 класс
      IF(V$STAGE = 12) THEN V$STAGE = 11;
      -- Также если стоит 11 класс не-выпускной (кроме августа, сентября и октября - могут еще не выставить) - тоже добавляем 1 год обучения
      IF(V$GRADUATE = 3 AND V$STAGE = 11 AND EXTRACT(MONTH FROM CURRENT_DATE) NOT IN (8, 9, 10)) THEN V$STAGE = V$STAGE - 1;
      SD = '01.07.' || (EXTRACT(YEAR FROM SD) + (11 + 1 - V$STAGE));
      TAG_NAME = 'tns&colon;' || RQ || ':tns&colon;Документ:tns&colon;' || RQS || '::ДатаОжид';
      VAL = (SELECT RESULT FROM DATE2STR(:SD));
      SUSPEND;
    END

    TAG_NAME = 'tns&colon;' || RQ || ':tns&colon;Документ:tns&colon;' || RQS || '::ДатаПриказЗачисл';
    VAL = (SELECT RESULT FROM DATE2STR(:D2));
    SUSPEND;
    TAG_NAME = 'tns&colon;' || RQ || ':tns&colon;Документ:tns&colon;' || RQS || '::НомПриказЗачисл';
    VAL = S1;
    SUSPEND;

    -- Вариант для СПО
    IF(I$TYPE = 403) THEN
    BEGIN
      -- Сведения об образовательной программе - ищем по последней группе
      -- если код будет не по тому справочнику - вот будет веселье
      -- КодСпец="43.02.11" ФормаОбуч="1" ДатаНачОбуч="01.01.2022" СрокОбрПрогр="4" ПланДатаОконч="01.01.2026"

      TAG_NAME = 'tns&colon;' || RQ || ':tns&colon;Документ:tns&colon;' || RQS || ':tns&colon;СведОбрПрог';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'tns&colon;' || RQ || ':tns&colon;Документ:tns&colon;' || RQS || ':tns&colon;СведОбрПрог::КодСпец';
      VAL = NULL;
      SELECT FIRST 1 V2822.SVAL
      FROM VALS V2822
      WHERE V2822.OBJ_ID = :V$GROUP_ID AND V2822.PARAM_ID = 2822 AND V2822.IS_DEL = 0
      INTO :VAL;
      IF(VAL IS NULL AND I$RAISE = 1) THEN EXCEPTION DATA_ERROR 'Для обучающегося ' || V$REGID || ' в ' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$OU_ID)) || ' нет кода специальности';
      SUSPEND;
      TAG_NAME = 'tns&colon;' || RQ || ':tns&colon;Документ:tns&colon;' || RQS || ':tns&colon;СведОбрПрог::ФормаОбуч';
      VAL = 1; -- всегда очная
      SUSPEND;
      -- Даты начала обучения у нас отдельно нет, корректируем по дате зачисления
      -- Дату всегда делаем 01 сентября, далее корректируем по году
      TAG_NAME = 'tns&colon;' || RQ || ':tns&colon;Документ:tns&colon;' || RQS || ':tns&colon;СведОбрПрог::ДатаНачОбуч';
      IF(EXTRACT(MONTH FROM SD) > 5) THEN SD = EXTRACT(YEAR FROM SD) || '-09-01'; ELSE SD = (EXTRACT(YEAR FROM SD) - 1) || '-09-01';
      VAL = (SELECT RESULT FROM DATE2STR(:SD));
      SUSPEND;
      --
      V$DURATION = NULL;
      SELECT FIRST 1 V3371.VAL
      FROM VALI V3371
      WHERE V3371.OBJ_ID = :V$PLAN_ID AND V3371.PARAM_ID = 3371 AND V3371.IS_DEL = 0
      INTO :V$DURATION;
      IF(V$DURATION IS NULL) THEN V$DURATION = 3;
      V$DURMONTH = NULL;
      SELECT FIRST 1 V3352.VAL
      FROM VALI V3352
      WHERE V3352.OBJ_ID = :V$PLAN_ID AND V3352.PARAM_ID = 3352 AND V3352.IS_DEL = 0
      INTO :V$DURMONTH;
      IF(V$DURMONTH IS NULL) THEN V$DURMONTH = 12 * (V$DURATION - 1) + 10;
      TAG_NAME = 'tns&colon;' || RQ || ':tns&colon;Документ:tns&colon;' || RQS || ':tns&colon;СведОбрПрог::СрокОбрПрогр';
      VAL = V$DURATION;
      SUSPEND;
      -- Для даты окончания берем срок обучения в месяцах, но если его нет - пытаемся посчитать из курсов
      TAG_NAME = 'tns&colon;' || RQ || ':tns&colon;Документ:tns&colon;' || RQS || ':tns&colon;СведОбрПрог::ПланДатаОконч';
      VAL = (SELECT RESULT FROM DATE2STR(DATEADD(:V$DURMONTH MONTH TO :SD)));
      SUSPEND;

      -- Аккредитация, считаем что у нас всегда одна аккредитация
      -- если не внесено, выдаем признак отсутствия сведений
      -- <tns:СведАккред РегНомАккред="58584578448" ДатаГосАккред="01.01.2003" ТипАккред="2" НаимОргАккред="Министерство образования"/>
      S1 = NULL;
      S2 = NULL;
      SD = NULL;
      S = NULL;
      D2 = NULL;
      SELECT FIRST 1 COALESCE(V479.SVAL, '') || V480.SVAL, V482.VAL, COALESCE(V481.VAL, 'Нет сведений'), V483.VAL
      FROM LINKS L17
      JOIN VALL V471 ON V471.OBJ_ID = L17.OBJ_ID AND V471.PARAM_ID = 471 AND V471.IS_DEL = 0 AND V471.LISTVAL_ID IN (1053, 18625) -- аккредитация
      JOIN VALL V613 ON V613.OBJ_ID = L17.OBJ_ID AND V613.PARAM_ID = 613 AND V613.IS_DEL = 0 AND V613.LISTVAL_ID IN (1982, 1984) -- действующий
      LEFT JOIN VALD V483 ON V483.OBJ_ID = L17.OBJ_ID AND V483.PARAM_ID = 483 AND V483.IS_DEL = 0 -- дата окончания действия
      LEFT JOIN VALS V479 ON V479.OBJ_ID = L17.OBJ_ID AND V479.PARAM_ID = 479 AND V479.IS_DEL = 0 -- серия
      JOIN VALS V480 ON V480.OBJ_ID = L17.OBJ_ID AND V480.PARAM_ID = 480 AND V480.IS_DEL = 0 -- номер
      JOIN VALD V482 ON V482.OBJ_ID = L17.OBJ_ID AND V482.PARAM_ID = 482 AND V482.IS_DEL = 0 -- дата выдачи
      LEFT JOIN VALS V481 ON V481.OBJ_ID = L17.OBJ_ID AND V481.PARAM_ID = 481 AND V481.IS_DEL = 0 -- кем выдана - часто не заполняют
      WHERE L17.PARENT_ID = :V$OU_ID AND L17.OBJ_TYPE_ID = 17 AND L17.DATE_DEL IS NULL
        AND (V483.VAL IS NULL OR V483.VAL > CURRENT_DATE)
      ORDER BY L17.DATE_INS DESC
      INTO :S1, :SD, :S, :D2;

      IF(S1 IS NULL) THEN
      BEGIN
        TAG_NAME = 'tns&colon;' || RQ || ':tns&colon;Документ:tns&colon;' || RQS || ':tns&colon;СведОбрПрог:tns&colon;ПрОтсАккред';
        VAL = 1;
        SUSPEND;
      END
      ELSE
      BEGIN
        TAG_NAME = 'tns&colon;' || RQ || ':tns&colon;Документ:tns&colon;' || RQS || ':tns&colon;СведОбрПрог:tns&colon;СведАккред';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'tns&colon;' || RQ || ':tns&colon;Документ:tns&colon;' || RQS || ':tns&colon;СведОбрПрог:tns&colon;СведАккред::РегНомАккред';
        VAL = S1;
        SUSPEND;
        TAG_NAME = 'tns&colon;' || RQ || ':tns&colon;Документ:tns&colon;' || RQS || ':tns&colon;СведОбрПрог:tns&colon;СведАккред::ДатаГосАккред';
        VAL = (SELECT RESULT FROM DATE2STR(:SD));
        SUSPEND;
        TAG_NAME = 'tns&colon;' || RQ || ':tns&colon;Документ:tns&colon;' || RQS || ':tns&colon;СведОбрПрог:tns&colon;СведАккред::ТипАккред';
        VAL = IIF(D2 IS NULL, 2, 1); -- срочная или бессрочная
        SUSPEND;
        IF(D2 IS NOT NULL) THEN
        BEGIN
          TAG_NAME = 'tns&colon;' || RQ || ':tns&colon;Документ:tns&colon;' || RQS || ':tns&colon;СведОбрПрог:tns&colon;СведАккред::ДатаОкончАккред';
          VAL = (SELECT RESULT FROM DATE2STR(:D2));
          SUSPEND;
        END
        TAG_NAME = 'tns&colon;' || RQ || ':tns&colon;Документ:tns&colon;' || RQS || ':tns&colon;СведОбрПрог:tns&colon;СведАккред::НаимОргАккред';
        VAL = REPLACE(S, '&nbsp;', ' ');
        IF(VAL IS NULL OR CHAR_LENGTH(VAL) < 3) THEN VAL = 'Правительство Санкт-Петербурга Комитет по образованию';
        SUSPEND;
      END

    END -- конец блока по колледжу

    -- Сведения об организации
    TAG_NAME = 'tns&colon;' || RQ || ':tns&colon;Документ:tns&colon;' || RQS || ':tns&colon;СведОрг';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'tns&colon;' || RQ || ':tns&colon;Документ:tns&colon;' || RQS || ':tns&colon;СведОрг::НаимОрг';
    VAL = NULL;
    SELECT FIRST 1 V999.VAL
    FROM VALS V999
    WHERE V999.OBJ_ID = :V$OU_ID AND V999.PARAM_ID = 999 AND V999.IS_DEL = 0
    INTO :VAL;
    SUSPEND;
    TAG_NAME = 'tns&colon;' || RQ || ':tns&colon;Документ:tns&colon;' || RQS || ':tns&colon;СведОрг::ИНН';
    VAL = NULL;
    SELECT FIRST 1 V33.VAL
    FROM VALS V33
    WHERE V33.OBJ_ID = :V$OU_ID AND V33.PARAM_ID = 33 AND V33.IS_DEL = 0
    INTO :VAL;
    SUSPEND;
    TAG_NAME = 'tns&colon;' || RQ || ':tns&colon;Документ:tns&colon;' || RQS || ':tns&colon;СведОрг::КПП';
    VAL = NULL;
    SELECT FIRST 1 V34.VAL
    FROM VALS V34
    WHERE V34.OBJ_ID = :V$OU_ID AND V34.PARAM_ID = 34 AND V34.IS_DEL = 0
    INTO :VAL;
    VAL = REPLACE(VAL, ' ', '');
    SUSPEND;
    TAG_NAME = 'tns&colon;' || RQ || ':tns&colon;Документ:tns&colon;' || RQS || ':tns&colon;СведОрг::ОГРН';
    VAL = NULL;
    SELECT FIRST 1 V9.VAL
    FROM VALS V9
    WHERE V9.OBJ_ID = :V$OU_ID AND V9.PARAM_ID = 9 AND V9.IS_DEL = 0
    INTO :VAL;
    SUSPEND;
    TAG_NAME = 'tns&colon;' || RQ || ':tns&colon;Документ:tns&colon;' || RQS || ':tns&colon;СведОрг::АдресОрг';
    VAL = NULL;
    SELECT FIRST 1 A.VAL
    FROM ADR_GET(27, :V$OU_ID) A
    INTO :VAL;
    SUSPEND;

    -- Вариант для школ
    IF(I$TYPE = 404) THEN
    BEGIN
      -- Аккредитация, считаем что у нас всегда одна аккредитация
      -- если не внесено, выдаем признак отсутствия сведений
      -- <tns:СведАккред РегНомАккред="58584578448" ДатаГосАккред="01.01.2003" ТипАккред="2" НаимОргАккред="Министерство образования"/>
      S1 = NULL;
      S2 = NULL;
      SD = NULL;
      S = NULL;
      D2 = NULL;
      SELECT FIRST 1 COALESCE(V479.SVAL, '') || V480.SVAL, V482.VAL, V481.VAL, V483.VAL
      FROM LINKS L17
      JOIN VALL V471 ON V471.OBJ_ID = L17.OBJ_ID AND V471.PARAM_ID = 471 AND V471.IS_DEL = 0 AND V471.LISTVAL_ID IN (1053, 18625) -- аккредитация
      JOIN VALL V613 ON V613.OBJ_ID = L17.OBJ_ID AND V613.PARAM_ID = 613 AND V613.IS_DEL = 0 AND V613.LISTVAL_ID IN (1982, 1984) -- действующий
      LEFT JOIN VALD V483 ON V483.OBJ_ID = L17.OBJ_ID AND V483.PARAM_ID = 483 AND V483.IS_DEL = 0 -- дата окончания действия
      LEFT JOIN VALS V479 ON V479.OBJ_ID = L17.OBJ_ID AND V479.PARAM_ID = 479 AND V479.IS_DEL = 0 -- серия
      JOIN VALS V480 ON V480.OBJ_ID = L17.OBJ_ID AND V480.PARAM_ID = 480 AND V480.IS_DEL = 0 -- номер
      JOIN VALD V482 ON V482.OBJ_ID = L17.OBJ_ID AND V482.PARAM_ID = 482 AND V482.IS_DEL = 0 -- дата выдачи
      JOIN VALS V481 ON V481.OBJ_ID = L17.OBJ_ID AND V481.PARAM_ID = 481 AND V481.IS_DEL = 0 -- кем выдана
      WHERE L17.PARENT_ID = :V$OU_ID AND L17.OBJ_TYPE_ID = 17 AND L17.DATE_DEL IS NULL
        AND (V483.VAL IS NULL OR V483.VAL > CURRENT_DATE)
      ORDER BY L17.DATE_INS DESC
      INTO :S1, :SD, :S, :D2;

      IF(S1 IS NULL) THEN
      BEGIN
        S1 = 'Не указана';
        SD = '01.01.2020';
      END
      TAG_NAME = 'tns&colon;' || RQ || ':tns&colon;Документ:tns&colon;' || RQS || ':tns&colon;СведАккред';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'tns&colon;' || RQ || ':tns&colon;Документ:tns&colon;' || RQS || ':tns&colon;СведАккред::РегНомАккред';
      VAL = S1;
      SUSPEND;
      TAG_NAME = 'tns&colon;' || RQ || ':tns&colon;Документ:tns&colon;' || RQS || ':tns&colon;СведАккред::ДатаГосАккред';
      VAL = (SELECT RESULT FROM DATE2STR(:SD));
      SUSPEND;
      TAG_NAME = 'tns&colon;' || RQ || ':tns&colon;Документ:tns&colon;' || RQS || ':tns&colon;СведАккред::ТипАккред';
      VAL = IIF(D2 IS NULL, 2, 1); -- срочная или бессрочная
      SUSPEND;
      IF(D2 IS NOT NULL) THEN
      BEGIN
        TAG_NAME = 'tns&colon;' || RQ || ':tns&colon;Документ:tns&colon;' || RQS || ':tns&colon;СведАккред::ДатаОкончАккред';
        VAL = (SELECT RESULT FROM DATE2STR(:D2));
        SUSPEND;
      END
      TAG_NAME = 'tns&colon;' || RQ || ':tns&colon;Документ:tns&colon;' || RQS || ':tns&colon;СведАккред::НаимОргАккред';
      VAL = REPLACE(S, '&nbsp;', ' ');
      IF(VAL IS NULL OR CHAR_LENGTH(VAL) < 3) THEN VAL = 'Правительство Санкт-Петербурга Комитет по образованию';
      SUSPEND;
    END

    -- <tns:СведЛиценз РегНомЛиценз="3232665451" ДатаЛиценз="01.01.2003" ТипЛиценз="2" НаимОргЛиценз="Министерство образования"/>
    S1 = NULL;
    S2 = NULL;
    SD = NULL;
    S = NULL;
    D2 = NULL;
    SELECT FIRST 1 COALESCE(V479.SVAL, '') || V480.SVAL, V482.VAL, V481.VAL, V483.VAL
    FROM LINKS L17
    JOIN VALL V471 ON V471.OBJ_ID = L17.OBJ_ID AND V471.PARAM_ID = 471 AND V471.IS_DEL = 0 AND V471.LISTVAL_ID IN (1052, 18624) -- лицензия
    JOIN VALL V613 ON V613.OBJ_ID = L17.OBJ_ID AND V613.PARAM_ID = 613 AND V613.IS_DEL = 0 AND V613.LISTVAL_ID IN (1982, 1984) -- действующий
    LEFT JOIN VALD V483 ON V483.OBJ_ID = L17.OBJ_ID AND V483.PARAM_ID = 483 AND V483.IS_DEL = 0 -- дата окончания действия
    LEFT JOIN VALS V479 ON V479.OBJ_ID = L17.OBJ_ID AND V479.PARAM_ID = 479 AND V479.IS_DEL = 0 -- серия
    JOIN VALS V480 ON V480.OBJ_ID = L17.OBJ_ID AND V480.PARAM_ID = 480 AND V480.IS_DEL = 0 -- номер
    JOIN VALD V482 ON V482.OBJ_ID = L17.OBJ_ID AND V482.PARAM_ID = 482 AND V482.IS_DEL = 0 -- дата выдачи
    LEFT JOIN VALS V481 ON V481.OBJ_ID = L17.OBJ_ID AND V481.PARAM_ID = 481 AND V481.IS_DEL = 0 -- кем выдана
    WHERE L17.PARENT_ID = :V$OU_ID AND L17.OBJ_TYPE_ID = 17 AND L17.DATE_DEL IS NULL
      AND (V483.VAL IS NULL OR V483.VAL > CURRENT_DATE)
    ORDER BY L17.DATE_INS DESC
    INTO :S1, :SD, :S, :D2;
    IF(S1 IS NULL AND I$RAISE = 1) THEN EXCEPTION DATA_ERROR 'Не внесена лицензия в ОУ ' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$OU_ID));

    -- Кем выдана
    IF(S1 IS NULL OR S1 = '') THEN S1 = 'Не указана';
    IF(SD IS NULL) THEN SD = '01.01.2020'; -- если нет даты лицензии или самой лицензии
    IF(D2 > '01.01.2040') THEN D2 = NULL; -- зачистка кривых дат окончания

    TAG_NAME = RQL;
    VAL = NULL;
    SUSPEND;
    TAG_NAME = RQL || '::РегНомЛиценз';
    VAL = S1;
    SUSPEND;
    TAG_NAME = RQL || '::ДатаЛиценз';
    VAL = (SELECT RESULT FROM DATE2STR(:SD));
    SUSPEND;
    TAG_NAME = RQL || '::ТипЛиценз';
    VAL = IIF(D2 IS NULL, 2, 1); -- срочная или бессрочная
    SUSPEND;
    IF(D2 IS NOT NULL) THEN
    BEGIN
      TAG_NAME = RQL || '::ДатаОкончЛиценз';
      VAL = (SELECT RESULT FROM DATE2STR(:D2));
      SUSPEND;
    END
    TAG_NAME = RQL || '::НаимОргЛиценз';
    VAL = REPLACE(S, '&nbsp;', ' ');
    IF(VAL IS NULL OR CHAR_LENGTH(VAL) < 3) THEN VAL = 'Правительство Санкт-Петербурга Комитет по образованию';
    SUSPEND;

    IF(I$TYPE = 403) THEN
    BEGIN
      -- Сведения об академических отпусках
      -- у нас нет данных о причинах академического отпуска, всегда выдаем 4
      FOR
        SELECT M.DATE_IN, M.ORDER_DATE_IN, M.ORDER_NUM_IN, M.DATE_OUT, M.ORDER_DATE_OUT, M.ORDER_NUM_OUT
        FROM PERSON_MOVEMENTS M
        WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :V$PERSON_ID AND M.GROUP_TYPE_ID = 289
        ORDER BY 1
        INTO :SD, :D2, :S1, :D3, :D4, :S2
      DO
      BEGIN
        TAG_NAME = 'tns&colon;' || RQ || ':tns&colon;Документ:tns&colon;' || RQS || ':tns&colon;СведОтпуск';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'tns&colon;' || RQ || ':tns&colon;Документ:tns&colon;' || RQS || ':tns&colon;СведОтпуск::СтатусОтпуск';
        VAL = IIF(D3 IS NULL, 1, 2); -- 1 = в отпуске
        SUSPEND;
        TAG_NAME = 'tns&colon;' || RQ || ':tns&colon;Документ:tns&colon;' || RQS || ':tns&colon;СведОтпуск::НомПриказНач';
        VAL = COALESCE(S1, 'Неизвестно');
        SUSPEND;
        TAG_NAME = 'tns&colon;' || RQ || ':tns&colon;Документ:tns&colon;' || RQS || ':tns&colon;СведОтпуск::ДатаНач';
        VAL = (SELECT RESULT FROM DATE2STR(:SD));
        SUSPEND;
        TAG_NAME = 'tns&colon;' || RQ || ':tns&colon;Документ:tns&colon;' || RQS || ':tns&colon;СведОтпуск::ДатаПриказНач';
        VAL = (SELECT RESULT FROM DATE2STR(COALESCE(:D2, :SD)));
        SUSPEND;
        -- Плановой даты окончания у нас все равно нет - выдаем +1 год от начала или текущую дату
        TAG_NAME = 'tns&colon;' || RQ || ':tns&colon;Документ:tns&colon;' || RQS || ':tns&colon;СведОтпуск::ПланДатаОконч';
        SD = DATEADD(1 YEAR TO SD);
        IF(SD < CURRENT_DATE) THEN SD = CURRENT_DATE;
        VAL = (SELECT RESULT FROM DATE2STR(:SD));
        SUSPEND;
        IF(D3 IS NOT NULL) THEN
        BEGIN
          TAG_NAME = 'tns&colon;' || RQ || ':tns&colon;Документ:tns&colon;' || RQS || ':tns&colon;СведОтпуск::НомПриказОконч';
          VAL = COALESCE(S2, 'Неизвестно');
          SUSPEND;
          TAG_NAME = 'tns&colon;' || RQ || ':tns&colon;Документ:tns&colon;' || RQS || ':tns&colon;СведОтпуск::ДатаОконч';
          VAL = (SELECT RESULT FROM DATE2STR(:D3));
          SUSPEND;
          TAG_NAME = 'tns&colon;' || RQ || ':tns&colon;Документ:tns&colon;' || RQS || ':tns&colon;СведОтпуск::ДатаПриказОконч';
          VAL = (SELECT RESULT FROM DATE2STR(COALESCE(:D4, :D3)));
          SUSPEND;
        END
        TAG_NAME = 'tns&colon;' || RQ || ':tns&colon;Документ:tns&colon;' || RQS || ':tns&colon;СведОтпуск::ПричОтпуск';
        VAL = 4; -- иные обстоятельства
        SUSPEND;
      END
    END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_MS_REP_CITIZENSHIP (
    I$DT1 TIMESTAMP,
    I$DT2 TIMESTAMP NOT NULL = CURRENT_TIMESTAMP)
RETURNS (
    ID VARCHAR(60),
    REPRESENTATIVE_ID VARCHAR(60),
    CODE VARCHAR(40),
    NAME VARCHAR(100),
    CREATE_DATETIME TIMESTAMP,
    SEND_DATETIME TIMESTAMP,
    ID_HASH_GOST256 VARCHAR(200))
AS
DECLARE VARIABLE V$SCHOOL_ID BIGINT;
DECLARE VARIABLE V$GP_ID BIGINT;
DECLARE VARIABLE V$Y INTEGER;
DECLARE VARIABLE V$PERSON_ID BIGINT;
DECLARE VARIABLE V$DT1 TIMESTAMP;
DECLARE VARIABLE V$DT2 TIMESTAMP;
DECLARE VARIABLE V$RANGE_FROM DATE;
DECLARE VARIABLE V$ID BIGINT;
DECLARE VARIABLE FIRSTNAME VARCHAR(100);
DECLARE VARIABLE LASTNAME VARCHAR(100);
DECLARE VARIABLE PATRONYMIC VARCHAR(100);
DECLARE VARIABLE BIRTHDATE DATE;
DECLARE VARIABLE NUMB_PASSPORT VARCHAR(40);
begin

  SEND_DATETIME = I$DT2;

  SELECT FIRST 1 L2.OBJ_ID, V1236.LISTVAL_ID, LV.COST
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$SCHOOL_ID, :V$GP_ID, :V$Y;

  V$RANGE_FROM = '31.08.' || (V$Y - 3);

  FOR
    SELECT L20.OBJ_ID, MAX(L20.DATE_MODIFY), MAX(L20.DATE_INS)
    FROM LINKS L10
    JOIN PERSON_MOVEMENTS M ON M.DATE_DEL IS NULL AND M.PERSON_ID = L10.OBJ_ID AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :V$RANGE_FROM) AND M.LEVEL_ID IN (22, 26, 27)
    JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
    -- Есть регид у ученика
    JOIN VALS V2912 ON V2912.OBJ_ID = M.PERSON_ID AND V2912.PARAM_ID = 2912 AND V2912.IS_DEL = 0
    -- Родитель
    JOIN LINKS L20 ON L20.PARENT_ID = L10.OBJ_ID AND L20.OBJ_TYPE_ID = 20 AND L20.DATE_DEL IS NULL
    LEFT JOIN VALL V1564 ON V1564.OBJ_ID = L20.EXT_OBJ_ID AND V1564.PARAM_ID = 1564 AND V1564.IS_DEL = 0
    WHERE L10.PARENT_TYPE_ID IN (9, 125, 187) AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL -- , 81, 82, 83
      AND (V1564.LISTVAL_ID IS NULL OR V1564.LISTVAL_ID = 2) -- добавлена фича чтобы отключать выгрузку родителя
    GROUP BY 1
    ORDER BY 1
    INTO :V$PERSON_ID, :V$DT1, :CREATE_DATETIME
  DO
  BEGIN
    CREATE_DATETIME = V$DT1;

    -- ID, REPRESENTATIVE_ID оставляем пустыми - на сервере они заменятся хэшем ID_HASH_GOST256
    LASTNAME = NULL;
    FIRSTNAME = NULL;
    PATRONYMIC = NULL;
    BIRTHDATE = NULL;
    NUMB_PASSPORT = NULL;
    V$DT2 = NULL;

    SELECT V128.VAL, MAXVALUE(V128.DATE_MODIFY, :V$DT2)
    FROM VALS V128
    WHERE V128.OBJ_ID = :V$PERSON_ID AND V128.PARAM_ID = 128 AND V128.IS_DEL = 0
    INTO :LASTNAME, :V$DT2;

    SELECT V129.VAL, MAXVALUE(V129.DATE_MODIFY, :V$DT2)
    FROM VALS V129
    WHERE V129.OBJ_ID = :V$PERSON_ID AND V129.PARAM_ID = 129 AND V129.IS_DEL = 0
    INTO :FIRSTNAME, :V$DT2;

    SELECT V130.VAL, MAXVALUE(V130.DATE_MODIFY, :V$DT2)
    FROM VALS V130
    WHERE V130.OBJ_ID = :V$PERSON_ID AND V130.PARAM_ID = 130 AND V130.IS_DEL = 0
    INTO :PATRONYMIC, :V$DT2;

    SELECT D.VAL, MAXVALUE(V143.DATE_MODIFY, :V$DT2)
    FROM VALD V143
    LEFT JOIN DATE2ISO(V143.VAL, 0) D ON 1 = 1
    WHERE V143.OBJ_ID = :V$PERSON_ID AND V143.PARAM_ID = 143 AND V143.IS_DEL = 0
    INTO :BIRTHDATE, :V$DT2;

    -- Данные паспорта
    SELECT FIRST 1 V559.VAL, MAXVALUE(L79.DATE_MODIFY, V441.DATE_MODIFY, V614.DATE_MODIFY, V560.DATE_MODIFY, V442.DATE_MODIFY, V559.DATE_MODIFY, :V$DT2)
    FROM LINKS L79
    JOIN VALL V441 ON V441.OBJ_ID = L79.OBJ_ID AND V441.PARAM_ID = 441 AND V441.IS_DEL = 0 AND V441.LISTVAL_ID = 1368
    JOIN VALL V614 ON V614.OBJ_ID = L79.OBJ_ID AND V614.PARAM_ID = 614 AND V614.IS_DEL = 0 AND V614.LISTVAL_ID = 1982
    JOIN VALD V560 ON V560.OBJ_ID = L79.OBJ_ID AND V560.PARAM_ID = 560 AND V560.IS_DEL = 0
    JOIN VALS V442 ON V442.OBJ_ID = L79.OBJ_ID AND V442.PARAM_ID = 442 AND V442.IS_DEL = 0
    JOIN VALS V559 ON V559.OBJ_ID = L79.OBJ_ID AND V559.PARAM_ID = 559 AND V559.IS_DEL = 0
    WHERE L79.PARENT_ID = :V$PERSON_ID AND L79.OBJ_TYPE_ID = 79 AND L79.DATE_DEL IS NULL
    INTO :NUMB_PASSPORT, :V$DT2;

    CODE = NULL;
    NAME = NULL;
    SELECT V1559.LISTVAL_ID, R.VAL, R.VAL_LONG, V1559.DATE_MODIFY
    FROM VALL V1559
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V1559.LISTVAL_ID
    JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
    WHERE V1559.OBJ_ID = :V$PERSON_ID AND V1559.PARAM_ID = 1559 AND V1559.IS_DEL = 0
    INTO :V$ID, :NAME, :CODE, :CREATE_DATETIME;

    IF(CODE = '') THEN CODE = NULL;

    -- Тут обязательно должен быть именно паспорт
    ID_HASH_GOST256 = UPPER(LASTNAME || FIRSTNAME || COALESCE(PATRONYMIC, '')) || REPLACE((SELECT VAL FROM DATE2ISO(:BIRTHDATE, 0)), '-', '') || '+' || NUMB_PASSPORT;

    IF(ID_HASH_GOST256 IS NOT NULL AND NAME IS NOT NULL AND CODE IS NOT NULL AND (I$DT1 IS NULL OR V$DT1 >= I$DT1 OR V$DT2 >= I$DT1)) THEN SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_MS_REP_SCHOOL (
    I$DT1 TIMESTAMP,
    I$DT2 TIMESTAMP NOT NULL = CURRENT_TIMESTAMP)
RETURNS (
    ID VARCHAR(60),
    OID VARCHAR(40),
    AUTH_LINK VARCHAR(200),
    VK_ID VARCHAR(40),
    FIRSTNAME VARCHAR(100),
    LASTNAME VARCHAR(100),
    PATRONYMIC VARCHAR(100),
    HASH_GOST2012 VARCHAR(200),
    HASH_NUM INTEGER,
    HASH_GOST2012_2 VARCHAR(200),
    HASH_NUM_2 INTEGER,
    HASH_GOST2012_3 VARCHAR(200),
    HASH_NUM_3 INTEGER,
    BIRTHDATE DATE,
    E_MAIL VARCHAR(100),
    GENDER_CODE VARCHAR(20),
    GENDER_VALUE INTEGER,
    GENDER_DESCRIPTION VARCHAR(100),
    ACTIVE VARCHAR(20),
    CREATE_DATETIME TIMESTAMP,
    SEND_DATETIME TIMESTAMP,
    ID_HASH_GOST256 VARCHAR(200))
AS
DECLARE VARIABLE V$SCHOOL_ID BIGINT;
DECLARE VARIABLE V$GY_ID BIGINT;
DECLARE VARIABLE V$Y INTEGER;
DECLARE VARIABLE V$RANGE_FROM DATE;
DECLARE VARIABLE V$PERSON_ID BIGINT;
DECLARE VARIABLE V$HUSED SMALLINT;
DECLARE VARIABLE V$DT1 TIMESTAMP;
DECLARE VARIABLE V$DT2 TIMESTAMP;
DECLARE VARIABLE SNILS VARCHAR(20);
DECLARE VARIABLE DATA_PASSPORT VARCHAR(20);
DECLARE VARIABLE SER_PASSPORT VARCHAR(40);
DECLARE VARIABLE NUMB_PASSPORT VARCHAR(40);
DECLARE VARIABLE DATA_SOR VARCHAR(20);
DECLARE VARIABLE SER_SOR VARCHAR(40);
DECLARE VARIABLE NUMB_SOR VARCHAR(40);
begin

  -- Грузим не только тех, кого нет на портале, а вообще всех родителей

  SEND_DATETIME = I$DT2;
  AUTH_LINK = 'login';
  "ACTIVE" = 'true';

  SELECT FIRST 1 L2.OBJ_ID, V1236.LISTVAL_ID, LV.COST
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  JOIN VALS V9 ON V9.OBJ_ID = L2.OBJ_ID AND V9.PARAM_ID = 9 AND V9.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$SCHOOL_ID, :V$GY_ID, :V$Y;

  V$RANGE_FROM = '31.08.' || (V$Y - 3);

  FOR
    SELECT L20.OBJ_ID, MAX(L20.DATE_MODIFY), MAX(L20.DATE_INS)
    FROM LINKS L10
    JOIN PERSON_MOVEMENTS M ON M.DATE_DEL IS NULL AND M.PERSON_ID = L10.OBJ_ID AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :V$RANGE_FROM) AND M.LEVEL_ID IN (22, 26, 27)
    JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
    -- Есть регид у ученика
    JOIN VALS V2912 ON V2912.OBJ_ID = M.PERSON_ID AND V2912.PARAM_ID = 2912 AND V2912.IS_DEL = 0
    -- Родитель
    JOIN LINKS L20 ON L20.PARENT_ID = L10.OBJ_ID AND L20.OBJ_TYPE_ID = 20 AND L20.DATE_DEL IS NULL
    LEFT JOIN VALL V1564 ON V1564.OBJ_ID = L20.EXT_OBJ_ID AND V1564.PARAM_ID = 1564 AND V1564.IS_DEL = 0
    WHERE L10.PARENT_TYPE_ID IN (9, 125, 187) AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL -- , 81, 82, 83
      AND (V1564.LISTVAL_ID IS NULL OR V1564.LISTVAL_ID = 2) -- добавлена фича чтобы отключать выгрузку родителя, если он не участвует в воспитании
    GROUP BY 1
    ORDER BY 1
    INTO :V$PERSON_ID, :V$DT1, :CREATE_DATETIME
  DO
  BEGIN

    LASTNAME = NULL;
    FIRSTNAME = NULL;
    PATRONYMIC = NULL;
    BIRTHDATE = NULL;
    GENDER_VALUE = NULL;
    V$HUSED = 0;
    V$DT2 = NULL;

    SELECT V128.VAL, MAXVALUE(V128.DATE_MODIFY, :V$DT2)
    FROM VALS V128
    WHERE V128.OBJ_ID = :V$PERSON_ID AND V128.PARAM_ID = 128 AND V128.IS_DEL = 0
    INTO :LASTNAME, :V$DT2;

    SELECT V129.VAL, MAXVALUE(V129.DATE_MODIFY, :V$DT2)
    FROM VALS V129
    WHERE V129.OBJ_ID = :V$PERSON_ID AND V129.PARAM_ID = 129 AND V129.IS_DEL = 0
    INTO :FIRSTNAME, :V$DT2;

    SELECT V130.VAL, MAXVALUE(V130.DATE_MODIFY, :V$DT2)
    FROM VALS V130
    WHERE V130.OBJ_ID = :V$PERSON_ID AND V130.PARAM_ID = 130 AND V130.IS_DEL = 0
    INTO :PATRONYMIC, :V$DT2;

    SELECT D.VAL, MAXVALUE(V143.DATE_MODIFY, :V$DT2)
    FROM VALD V143
    LEFT JOIN DATE2ISO(V143.VAL, 0) D ON 1 = 1
    WHERE V143.OBJ_ID = :V$PERSON_ID AND V143.PARAM_ID = 143 AND V143.IS_DEL = 0
    INTO :BIRTHDATE, :V$DT2;

    SELECT IIF(V2544.LISTVAL_ID = 182, 2, 1), MAXVALUE(V2544.DATE_MODIFY, :V$DT2)
    FROM VALL V2544
    WHERE V2544.OBJ_ID = :V$PERSON_ID AND V2544.PARAM_ID = 2544 AND V2544.IS_DEL = 0
    INTO :GENDER_VALUE, :V$DT2;

    -- Если не указан пол, пробуем достать по степени родства
    -- исключаем нейтральные варианты
    IF(GENDER_VALUE IS NULL) THEN
    BEGIN
      SELECT FIRST 1 IIF(V1573.LISTVAL_ID IN (225, 1224, 1226, 1228, 1235, 1237, 1243), 2, 1)
      FROM LINKS LP10
      JOIN VALL V1573 ON V1573.OBJ_ID = LP10.EXT_OBJ_ID AND V1573.PARAM_ID = 1573 AND V1573.IS_DEL = 0 AND V1573.LISTVAL_ID NOT IN (3253, 1713, 1714, 3255)
      WHERE LP10.OBJ_ID = :V$PERSON_ID AND LP10.PARENT_TYPE_ID = 10 AND LP10.DATE_DEL IS NULL
      ORDER BY LP10.DATE_INS DESC
      INTO :GENDER_VALUE;
    END

    IF(GENDER_VALUE = 1) THEN
    BEGIN
      GENDER_CODE = 'male';
      GENDER_DESCRIPTION = 'мужской';
    END
    IF(GENDER_VALUE = 2) THEN
    BEGIN
      GENDER_CODE = 'female';
      GENDER_DESCRIPTION = 'женский';
    END

    IF(LASTNAME IS NOT NULL AND FIRSTNAME IS NOT NULL AND BIRTHDATE IS NOT NULL AND GENDER_VALUE IS NOT NULL) THEN
    BEGIN

      VK_ID = NULL;
      SELECT V3356.VAL, MAXVALUE(V3356.DATE_MODIFY, :V$DT2)
      FROM VALS V3356
      WHERE V3356.OBJ_ID = :V$PERSON_ID AND V3356.PARAM_ID = 3356 AND V3356.IS_DEL = 0
      INTO :VK_ID, :V$DT2;

      E_MAIL = NULL;
      SELECT V144.VAL, MAXVALUE(V144.DATE_MODIFY, :V$DT2)
      FROM VALS V144
      WHERE V144.OBJ_ID = :V$PERSON_ID AND V144.PARAM_ID = 144 AND V144.IS_DEL = 0
      INTO :E_MAIL, :V$DT2;

      -- Хэши документов
      SNILS = NULL;
      SELECT REPLACE(REPLACE(V1409.VAL, ' ', ''), '-', ''), MAXVALUE(V1409.DATE_MODIFY, :V$DT2)
      FROM VALS V1409
      WHERE V1409.OBJ_ID = :V$PERSON_ID AND V1409.PARAM_ID = 1409 AND V1409.IS_DEL = 0
      INTO :SNILS, :V$DT2;

      IF(SNILS IS NOT NULL) THEN
      BEGIN
        V$HUSED = V$HUSED + 1;
        IF(V$HUSED = 1) THEN BEGIN HASH_NUM = 1; HASH_GOST2012 = SNILS; END
        ELSE IF(V$HUSED = 2) THEN BEGIN HASH_NUM_2 = 1; HASH_GOST2012_2 = SNILS; END
        ELSE IF(V$HUSED = 3) THEN BEGIN HASH_NUM_3 = 1; HASH_GOST2012_3 = SNILS; END
      END

      -- Данные паспорта
      DATA_PASSPORT = NULL;
      NUMB_PASSPORT = NULL;
      SER_PASSPORT = NULL;
      SELECT FIRST 1 D.VAL, V442.VAL, V559.VAL, MAXVALUE(L79.DATE_MODIFY, V441.DATE_MODIFY, V614.DATE_MODIFY, V560.DATE_MODIFY, V442.DATE_MODIFY, V559.DATE_MODIFY, :V$DT2)
      FROM LINKS L79
      JOIN VALL V441 ON V441.OBJ_ID = L79.OBJ_ID AND V441.PARAM_ID = 441 AND V441.IS_DEL = 0 AND V441.LISTVAL_ID IN (1368, 1369)
      JOIN VALL V614 ON V614.OBJ_ID = L79.OBJ_ID AND V614.PARAM_ID = 614 AND V614.IS_DEL = 0 AND V614.LISTVAL_ID = 1982
      JOIN VALD V560 ON V560.OBJ_ID = L79.OBJ_ID AND V560.PARAM_ID = 560 AND V560.IS_DEL = 0
      LEFT JOIN DATE2ISO(V560.VAL, 0) D ON 1 = 1
      JOIN VALS V442 ON V442.OBJ_ID = L79.OBJ_ID AND V442.PARAM_ID = 442 AND V442.IS_DEL = 0
      JOIN VALS V559 ON V559.OBJ_ID = L79.OBJ_ID AND V559.PARAM_ID = 559 AND V559.IS_DEL = 0
      WHERE L79.PARENT_ID = :V$PERSON_ID AND L79.OBJ_TYPE_ID = 79 AND L79.DATE_DEL IS NULL
      ORDER BY V441.LISTVAL_ID
      INTO :DATA_PASSPORT, :SER_PASSPORT, :NUMB_PASSPORT, :V$DT2;

      IF(DATA_PASSPORT IS NOT NULL) THEN
      BEGIN
        V$HUSED = V$HUSED + 1;
        IF(V$HUSED = 1) THEN BEGIN HASH_NUM = 2; HASH_GOST2012 = SER_PASSPORT || ' ' || NUMB_PASSPORT; END
        ELSE IF(V$HUSED = 2) THEN BEGIN HASH_NUM_2 = 2; HASH_GOST2012_2 = SER_PASSPORT || ' ' || NUMB_PASSPORT; END
        ELSE IF(V$HUSED = 3) THEN BEGIN HASH_NUM_3 = 2; HASH_GOST2012_3 = SER_PASSPORT || ' ' || NUMB_PASSPORT; END
      END

      -- Свидетельство о рождении
      DATA_SOR = NULL;
      NUMB_SOR = NULL;
      SER_SOR = NULL;
      SELECT FIRST 1 D.VAL, REPLACE(REPLACE(UPPER(V442.VAL), ' ', ''), '-', ''), V559.VAL, MAXVALUE(L79.DATE_MODIFY, V441.DATE_MODIFY, V614.DATE_MODIFY, V560.DATE_MODIFY, V442.DATE_MODIFY, V559.DATE_MODIFY, :V$DT2)
      FROM LINKS L79
      JOIN VALL V441 ON V441.OBJ_ID = L79.OBJ_ID AND V441.PARAM_ID = 441 AND V441.IS_DEL = 0 AND V441.LISTVAL_ID IN (1370, 11343)
      JOIN VALL V614 ON V614.OBJ_ID = L79.OBJ_ID AND V614.PARAM_ID = 614 AND V614.IS_DEL = 0 AND V614.LISTVAL_ID = 1982
      JOIN VALD V560 ON V560.OBJ_ID = L79.OBJ_ID AND V560.PARAM_ID = 560 AND V560.IS_DEL = 0
      LEFT JOIN DATE2ISO(V560.VAL, 0) D ON 1 = 1
      JOIN VALS V442 ON V442.OBJ_ID = L79.OBJ_ID AND V442.PARAM_ID = 442 AND V442.IS_DEL = 0
      JOIN VALS V559 ON V559.OBJ_ID = L79.OBJ_ID AND V559.PARAM_ID = 559 AND V559.IS_DEL = 0
      WHERE L79.PARENT_ID = :V$PERSON_ID AND L79.OBJ_TYPE_ID = 79 AND L79.DATE_DEL IS NULL
      ORDER BY V441.LISTVAL_ID
      INTO :DATA_SOR, :SER_SOR, :NUMB_SOR, :V$DT2;

      --IF(SER_SOR IS NOT NULL AND CHAR_LENGTH(NUMB_SOR) <> 6) THEN
      --  EXCEPTION DATA_ERROR 'Некорректный формат серии/номера в свидетельстве о рождении ' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$PERSON_ID));

      IF(DATA_SOR IS NOT NULL) THEN
      BEGIN
        DATA_SOR = REPLACE(DATA_SOR, '-', '');
        V$HUSED = V$HUSED + 1;
        IF(V$HUSED = 1) THEN BEGIN HASH_NUM = 3; HASH_GOST2012 = SER_SOR || ' ' || NUMB_SOR || ' ' || DATA_SOR; END
        ELSE IF(V$HUSED = 2) THEN BEGIN HASH_NUM_2 = 3; HASH_GOST2012_2 = SER_SOR || ' ' || NUMB_SOR || ' ' || DATA_SOR; END
        ELSE IF(V$HUSED = 3) THEN BEGIN HASH_NUM_3 = 3; HASH_GOST2012_3 = SER_SOR || ' ' || NUMB_SOR || ' ' || DATA_SOR; END
      END

      -- Тут обязательно должен быть именно паспорт
      ID_HASH_GOST256 = UPPER(LASTNAME || FIRSTNAME || COALESCE(PATRONYMIC, '')) || REPLACE((SELECT VAL FROM DATE2ISO(:BIRTHDATE, 0)), '-', '') || '+' || NUMB_PASSPORT;

      IF(ID_HASH_GOST256 IS NOT NULL AND (I$DT1 IS NULL OR V$DT1 >= I$DT1 OR V$DT2 >= I$DT1)) THEN SUSPEND;
    END
  END

  WHEN ANY DO EXCEPTION DATA_ERROR 'Ошибка выгрузки сведений о представителе на ' || V$PERSON_ID || ' ' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$PERSON_ID));

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_MS_REP_STD_SCHOOL (
    I$DT1 TIMESTAMP,
    I$DT2 TIMESTAMP NOT NULL = CURRENT_TIMESTAMP)
RETURNS (
    STUDENT_ID VARCHAR(60),
    REPRESENTATIVE_ID VARCHAR(60),
    REP_ID_HASH_GOST256 VARCHAR(200),
    APPROVE_DOC_ID VARCHAR(60),
    RELATIONSHIP_CODE VARCHAR(40),
    RELATIONSHIP_VALUE INTEGER,
    RELATIONSHIP_DESCRIPTION VARCHAR(100),
    START_DATETIME TIMESTAMP,
    END_DATETIME TIMESTAMP,
    STATUS_CODE VARCHAR(40),
    STATUS_VALUE INTEGER,
    STATUS_DESCRIPTION VARCHAR(100),
    REASON_CODE VARCHAR(40),
    REASON_VALUE INTEGER,
    REASON_DESCRIPTION VARCHAR(100),
    CREATE_DATETIME TIMESTAMP,
    SEND_DATETIME TIMESTAMP)
AS
DECLARE VARIABLE V$SCHOOL_ID BIGINT;
DECLARE VARIABLE V$GY_ID BIGINT;
DECLARE VARIABLE V$Y INTEGER;
DECLARE VARIABLE V$RANGE_FROM DATE;
DECLARE VARIABLE V$PERSON_ID BIGINT;
DECLARE VARIABLE V$STUDENT_ID BIGINT;
DECLARE VARIABLE V$NUMB_PASS VARCHAR(40);
DECLARE VARIABLE V$REL_CODE BIGINT;
DECLARE VARIABLE V$GENDER BIGINT;
DECLARE VARIABLE V$DT1 TIMESTAMP;
DECLARE VARIABLE V$DT2 TIMESTAMP;
DECLARE VARIABLE V$DT3 TIMESTAMP;
begin

  SEND_DATETIME = I$DT2;

  SELECT FIRST 1 L2.OBJ_ID, V1236.LISTVAL_ID, LV.COST
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  JOIN VALS V9 ON V9.OBJ_ID = L2.OBJ_ID AND V9.PARAM_ID = 9 AND V9.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$SCHOOL_ID, :V$GY_ID, :V$Y;

  V$RANGE_FROM = '31.08.' || (V$Y - 3);

  FOR
    SELECT L20.OBJ_ID, L10.OBJ_ID, V2912.VAL, V1573.LISTVAL_ID, V88.LISTVAL_ID, L20.DATE_INS, MAXVALUE(V1573.DATE_MODIFY, V2912.DATE_MODIFY)
    FROM LINKS L10
    -- Есть регид у ученика
    JOIN VALS V2912 ON V2912.OBJ_ID = L10.OBJ_ID AND V2912.PARAM_ID = 2912 AND V2912.IS_DEL = 0
    -- Родитель
    JOIN LINKS L20 ON L20.PARENT_ID = L10.OBJ_ID AND L20.OBJ_TYPE_ID = 20 AND L20.DATE_DEL IS NULL
    JOIN VALL V1573 ON V1573.OBJ_ID = L20.EXT_OBJ_ID AND V1573.PARAM_ID = 1573 AND V1573.IS_DEL = 0
    JOIN VALL V88 ON V88.OBJ_ID = L10.OBJ_ID AND V88.PARAM_ID = 88 AND V88.IS_DEL = 0
    LEFT JOIN VALL V1564 ON V1564.OBJ_ID = L20.EXT_OBJ_ID AND V1564.PARAM_ID = 1564 AND V1564.IS_DEL = 0
    WHERE L10.PARENT_TYPE_ID IN (9, 125, 187) AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL -- , 81, 82, 83
      AND (V1564.LISTVAL_ID IS NULL OR V1564.LISTVAL_ID = 2) -- добавлена фича чтобы отключать выгрузку родителя, если он не участвует в воспитании
      AND EXISTS(
        SELECT FIRST 1 1
        FROM PERSON_MOVEMENTS M
        JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
        WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = L10.OBJ_ID AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :V$RANGE_FROM) AND M.LEVEL_ID IN (22, 26, 27)
      )
    ORDER BY 1
    INTO :V$PERSON_ID, :V$STUDENT_ID, :STUDENT_ID, :V$REL_CODE, :V$GENDER, :CREATE_DATETIME, :V$DT1
  DO
  BEGIN

    IF(POSITION(':' IN STUDENT_ID) > 0) THEN STUDENT_ID = SUBSTRING(STUDENT_ID FROM 1 FOR POSITION(':' IN STUDENT_ID) - 1);
    STUDENT_ID = REPLACE(STUDENT_ID, '{', '');
    STUDENT_ID = REPLACE(STUDENT_ID, '}', '');
    STUDENT_ID = LOWER(STUDENT_ID);

    START_DATETIME = CREATE_DATETIME;

    V$NUMB_PASS = NULL;
    SELECT FIRST 1 V559.VAL, MAXVALUE(L79.DATE_MODIFY, V441.DATE_MODIFY, V614.DATE_MODIFY, V560.DATE_MODIFY, V442.DATE_MODIFY, V559.DATE_MODIFY)
    FROM LINKS L79
    JOIN VALL V441 ON V441.OBJ_ID = L79.OBJ_ID AND V441.PARAM_ID = 441 AND V441.IS_DEL = 0 AND V441.LISTVAL_ID IN (1368, 1369)
    JOIN VALL V614 ON V614.OBJ_ID = L79.OBJ_ID AND V614.PARAM_ID = 614 AND V614.IS_DEL = 0 AND V614.LISTVAL_ID = 1982
    JOIN VALD V560 ON V560.OBJ_ID = L79.OBJ_ID AND V560.PARAM_ID = 560 AND V560.IS_DEL = 0
    LEFT JOIN DATE2ISO(V560.VAL, 0) D ON 1 = 1
    JOIN VALS V442 ON V442.OBJ_ID = L79.OBJ_ID AND V442.PARAM_ID = 442 AND V442.IS_DEL = 0
    JOIN VALS V559 ON V559.OBJ_ID = L79.OBJ_ID AND V559.PARAM_ID = 559 AND V559.IS_DEL = 0
    WHERE L79.PARENT_ID = :V$PERSON_ID AND L79.OBJ_TYPE_ID = 79 AND L79.DATE_DEL IS NULL
    ORDER BY V441.LISTVAL_ID
    INTO :V$NUMB_PASS, :V$DT1;

    REP_ID_HASH_GOST256 = NULL;
    SELECT FIRST 1 UPPER(V128.SVAL || V129.SVAL || COALESCE(V130.SVAL, '')) || REPLACE(D.VAL, '-', '') || '+' || :V$NUMB_PASS,
      MAXVALUE(V128.DATE_MODIFY, V129.DATE_MODIFY, V130.DATE_MODIFY)
    FROM VALS V128
    JOIN VALS V129 ON V129.OBJ_ID = V128.OBJ_ID AND V129.PARAM_ID = 129 AND V129.IS_DEL = 0
    LEFT JOIN VALS V130 ON V130.OBJ_ID = V128.OBJ_ID AND V130.PARAM_ID = 130 AND V130.IS_DEL = 0
    JOIN VALD V143 ON V143.OBJ_ID = V128.OBJ_ID AND V143.PARAM_ID = 143 AND V143.IS_DEL = 0
    LEFT JOIN DATE2ISO(V143.VAL, 0) D ON 1 = 1
    WHERE V128.OBJ_ID = :V$PERSON_ID AND V128.PARAM_ID = 128 AND V128.IS_DEL = 0
    INTO :REP_ID_HASH_GOST256, :V$DT3;

    -- APPROVE_DOC_ID

    -- Тут все через задницу, статус не родителя к ребенку, а ребенка к родителю
    RELATIONSHIP_CODE = NULL;
    IF(V$REL_CODE IN (224, 225)) THEN BEGIN
      -- мать, отец
      IF(V$GENDER = 182) THEN BEGIN
        RELATIONSHIP_CODE = 'daughter';
        RELATIONSHIP_VALUE = 2;
        RELATIONSHIP_DESCRIPTION = 'дочь';
      END
      ELSE BEGIN
        RELATIONSHIP_CODE = 'son';
        RELATIONSHIP_VALUE = 1;
        RELATIONSHIP_DESCRIPTION = 'сын';
      END
    END
    ELSE IF(V$REL_CODE IN (226, 1224)) THEN BEGIN
      -- брат, сестра
      IF(V$GENDER = 182) THEN BEGIN
        RELATIONSHIP_CODE = 'sister';
        RELATIONSHIP_VALUE = 6;
        RELATIONSHIP_DESCRIPTION = 'сестра';
      END
      ELSE BEGIN
        RELATIONSHIP_CODE = 'brother';
        RELATIONSHIP_VALUE = 5;
        RELATIONSHIP_DESCRIPTION = 'брат';
      END
    END
    ELSE IF (V$REL_CODE = 3254) THEN BEGIN
      -- официальный представитель
      RELATIONSHIP_CODE = 'ward';
      RELATIONSHIP_VALUE = 12;
      RELATIONSHIP_DESCRIPTION = 'опекаемый';
    END
    ELSE BEGIN
      -- неизвестно
      RELATIONSHIP_CODE = 'other';
      RELATIONSHIP_VALUE = 98;
      RELATIONSHIP_DESCRIPTION = 'другие отношения';
    END

    STATUS_CODE = 'active';
    STATUS_VALUE = 1;
    STATUS_DESCRIPTION = 'Действует';

    -- Тут только причина для недостоверности
    -- REASON_CODE
    -- REASON_VALUE
    -- REASON_DESCRIPTION

    IF(I$DT1 IS NULL OR CREATE_DATETIME >= I$DT1 OR V$DT1 >= I$DT1 OR V$DT2 >= I$DT1 OR V$DT3 >= I$DT1) THEN
    BEGIN
      IF(REP_ID_HASH_GOST256 IS NOT NULL AND RELATIONSHIP_CODE IS NOT NULL) THEN SUSPEND;
    END

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_MS_SCHOOL_CLASSES (
    I$DT1 TIMESTAMP,
    I$DT2 TIMESTAMP NOT NULL = CURRENT_TIMESTAMP)
RETURNS (
    ID VARCHAR(60),
    SCHOOL_ID VARCHAR(60),
    TEACHER_ID VARCHAR(60),
    CLASS_NUM INTEGER,
    CLASS_LETTER VARCHAR(400),
    ACADEM_YEAR INTEGER,
    CLASS_START_DATE DATE,
    CLASS_END_DATE DATE,
    ATTENDANCE VARCHAR(100),
    SHIFT INTEGER,
    CORRECTION_CLASS VARCHAR(20),
    MARK_SCALE_VALUE INTEGER,
    MARK_SCALE_CODE VARCHAR(100),
    CREATE_DATETIME TIMESTAMP,
    SEND_DATETIME TIMESTAMP)
AS
DECLARE VARIABLE V$SCHOOL_ID BIGINT;
DECLARE VARIABLE V$GP_ID BIGINT;
DECLARE VARIABLE V$Y INTEGER;
DECLARE VARIABLE V$HDATE DATE;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE D DATE;
DECLARE VARIABLE S VARCHAR(20);
begin

  SEND_DATETIME = I$DT2;

  SELECT FIRST 1 L2.OBJ_ID, V1236.LISTVAL_ID, LV.COST, V9.VAL
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  JOIN VALS V9 ON V9.OBJ_ID = L2.OBJ_ID AND V9.PARAM_ID = 9 AND V9.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$SCHOOL_ID, :V$GP_ID, :V$Y, :SCHOOL_ID;

  V$HDATE = '25.08.' || (V$Y - 3);

  -- Вся история по учебным коллективам за последние три года
  -- где в классе был хотя бы один ученик, букву и параллель класса смотрим по реестру движения
  FOR
    SELECT M.GROUP_ID, M.NAME_IN, LV.COST, MIN(M.DATE_IN)
    FROM PERSON_MOVEMENTS M
    JOIN LISTVALS LV ON LV.LISTVAL_ID = M.STAGE_ID
    WHERE M.DATE_DEL IS NULL AND M.GROUP_TYPE_ID = 9 AND M.LEVEL_ID IN (22, 26, 27) AND M.DATE_IN >= :V$HDATE AND (M.DATE_MODIFY >= :I$DT1 OR :I$DT1 IS NULL)
    GROUP BY 1, 2, 3
    ORDER BY 1, 3
    INTO :V$OBJ_ID, :CLASS_LETTER, :CLASS_NUM, :D
  DO
  BEGIN
    CREATE_DATETIME = D;

    -- Учебный год берем по дате приема
    ACADEM_YEAR = EXTRACT(YEAR FROM D);
    IF(EXTRACT(MONTH FROM D) < 6) THEN ACADEM_YEAR = ACADEM_YEAR - 1;

    ID = V$OBJ_ID || 'Y' || ACADEM_YEAR;
    CLASS_START_DATE = '01.09.' || ACADEM_YEAR;
    CLASS_END_DATE = '31.08.' || (ACADEM_YEAR + 1);

    -- Из названия отрезаем цифру класса
    S = CLASS_NUM;
    CLASS_LETTER = SUBSTRING(CLASS_LETTER FROM CHAR_LENGTH(S) + 1);

    SHIFT = 1;
    ATTENDANCE = 'resident'; -- пока так
    MARK_SCALE_VALUE = 1; -- 5-points, потом разберемся
    MARK_SCALE_CODE = '5-points';

    -- Классрука всегда берем текущего
    TEACHER_ID = NULL;
    SELECT FIRST 1 V2915.SVAL
    FROM VALR V53
    JOIN VALS V2915 ON V2915.OBJ_ID = V53.VAL AND V2915.PARAM_ID = 2915 AND V2915.IS_DEL = 0
    WHERE V53.OBJ_ID = :V$OBJ_ID AND V53.PARAM_ID = 53 AND V53.IS_DEL = 0
    INTO :TEACHER_ID;

    IF(POSITION(':' IN TEACHER_ID) > 0) THEN TEACHER_ID = SUBSTRING(TEACHER_ID FROM 1 FOR POSITION(':' IN TEACHER_ID) - 1);
    TEACHER_ID = REPLACE(TEACHER_ID, '{', '');
    TEACHER_ID = REPLACE(TEACHER_ID, '}', '');
    TEACHER_ID = LOWER(TEACHER_ID);

    -- Коррекционность по последнему статусу
    CORRECTION_CLASS = 'false';
    SELECT FIRST 1 'true'
    FROM VALL V592
    WHERE V592.OBJ_ID = :V$OBJ_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 13275
    INTO :CORRECTION_CLASS;

    SUSPEND;
  END

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_MS_SKIPPINGS (
    I$DT1 TIMESTAMP,
    I$DT2 TIMESTAMP NOT NULL = CURRENT_TIMESTAMP)
RETURNS (
    ID VARCHAR(60),
    STUDENT_ID VARCHAR(60),
    LESSON_ID VARCHAR(40),
    SKIP_DATE DATE,
    TYPE_CODE VARCHAR(100),
    TYPE_VALUE INTEGER,
    TYPE_DESCRIPTION VARCHAR(100),
    DESCRIPTION VARCHAR(1000),
    MINUTES INTEGER,
    CREATE_DATETIME TIMESTAMP,
    SEND_DATETIME TIMESTAMP)
AS
DECLARE VARIABLE V$SCHOOL_ID BIGINT;
DECLARE VARIABLE V$GP_ID BIGINT;
DECLARE VARIABLE V$Y INTEGER;
DECLARE VARIABLE V$DT1 TIMESTAMP;
DECLARE VARIABLE V$DT2 TIMESTAMP;
DECLARE VARIABLE V$DT3 TIMESTAMP;
DECLARE VARIABLE V$MT_ID BIGINT;
begin

  SEND_DATETIME = I$DT2;

  SELECT FIRST 1 L2.OBJ_ID, V1236.LISTVAL_ID, LV.COST
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$SCHOOL_ID, :V$GP_ID, :V$Y;

  FOR
    SELECT L.OBJ_ID, M.MARK_ID, L.LESSON_DATE, V2912.VAL, M.MARK_TYPE_ID, MAXVALUE(L.DATE_MODIFY, V2912.DATE_MODIFY, M.DATE_MODIFY)
    FROM CJ2_JOURNAL J
    JOIN CJ2_JOURNAL_LESSONS L ON L.DATE_DEL IS NULL AND L.CJ_ID = J.OBJ_ID AND (L.IS_COMPLETED = 1 OR L.IS_PUBLISHED = 1)
    JOIN CJ2_CONTROL C ON C.DATE_DEL IS NULL AND C.LESSON_ID = L.OBJ_ID AND C.CONTROL_TYPE_ID = 0
    JOIN CJ2_MARK M ON M.DATE_DEL IS NULL AND M.CONTROL_ID = C.CONTROL_ID AND M.MARK_TYPE_ID IN (90, 91, 92, 93, 94)
    JOIN VALS V2912 ON V2912.OBJ_ID = M.STUDENT_ID AND V2912.PARAM_ID = 2912 AND V2912.IS_DEL = 0
    JOIN LISTVALS LV ON LV.LISTVAL_ID = J.STAGE_INDEX AND LV.PARENT_ID IN (2141, 12941)
    WHERE J.DATE_DEL IS NULL AND J.JOURNAL_TYPE = 0 AND J.YEAR_ID = :V$GP_ID
    ORDER BY L.LESSON_DATE, L.LESSON_NUM
    INTO :LESSON_ID, :ID, :SKIP_DATE, :STUDENT_ID, :V$MT_ID, :V$DT1
  DO
  BEGIN

    CREATE_DATETIME = V$DT1;

    IF(I$DT1 IS NULL OR V$DT1 >= I$DT1 OR V$DT2 >= I$DT1 OR V$DT3 >= I$DT1) THEN
    BEGIN
      IF(POSITION(':' IN STUDENT_ID) > 0) THEN STUDENT_ID = SUBSTRING(STUDENT_ID FROM 1 FOR POSITION(':' IN STUDENT_ID) - 1);
      STUDENT_ID = REPLACE(STUDENT_ID, '{', '');
      STUDENT_ID = REPLACE(STUDENT_ID, '}', '');
      STUDENT_ID = LOWER(STUDENT_ID);

      IF(V$MT_ID = 90) THEN TYPE_CODE = 'lateness';
      ELSE IF(V$MT_ID = 91) THEN TYPE_CODE = 'notallowded'; -- считаем неизвестную причину неуважительной
      ELSE IF(V$MT_ID = 92) THEN TYPE_CODE = 'sickday';
      ELSE IF(V$MT_ID = 93) THEN TYPE_CODE = 'allowded';
      ELSE IF(V$MT_ID = 94) THEN TYPE_CODE = 'notallowded';

      -- По идее VALUE и DESCRIPTION тоже надо заполнять, но мы это сделаем на сервере

      SUSPEND;
    END

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_MS_SPECIALITY (
    I$DT1 TIMESTAMP,
    I$DT2 TIMESTAMP NOT NULL = current_timestamp)
RETURNS (
    ID VARCHAR(60),
    TEACHER_ROLE_ID VARCHAR(60),
    CODE VARCHAR(100),
    NAME VARCHAR(1000),
    CREATE_DATETIME TIMESTAMP,
    SEND_DATETIME TIMESTAMP)
AS
declare variable V$SCHOOL_ID bigint;
declare variable V$GP_ID bigint;
declare variable V$Y integer;
declare variable V$DT1 timestamp;
declare variable V$DT2 timestamp;
declare variable V$DT3 timestamp;
declare variable V$PERSON_ID bigint;
declare variable V$YDATE date;
declare variable V$JOB bigint;
declare variable TEACHER_ID varchar(60);
begin

  SEND_DATETIME = I$DT2;

  SELECT FIRST 1 L2.OBJ_ID, V1236.LISTVAL_ID, LV.COST
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  JOIN VALS V9 ON V9.OBJ_ID = L2.OBJ_ID AND V9.PARAM_ID = 9 AND V9.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$SCHOOL_ID, :V$GP_ID, :V$Y;

  V$YDATE = '30.08.' || V$Y;

  FOR
    -- Действующие
    SELECT SID, MAX(OBJ_ID), MAX(DATE_MODIFY)
    FROM (
      SELECT V2915.SVAL SID, L14.OBJ_ID, L14.DATE_MODIFY
      FROM LINKS L2
      JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
      JOIN VALS V2915 ON V2915.OBJ_ID = L14.OBJ_ID AND V2915.PARAM_ID = 2915 AND V2915.IS_DEL = 0
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      UNION
      -- Уволенные не ранее даты начала текущего учебного года
      SELECT V2915.SVAL, L14.OBJ_ID, L14.DATE_MODIFY
      FROM LINKS L2
      JOIN LINKS L84 ON L84.PARENT_ID = L2.OBJ_ID AND L84.OBJ_TYPE_ID = 84 AND L84.DATE_DEL IS NULL
      JOIN LINKS L14 ON L14.PARENT_ID = L84.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
      JOIN VALS V2915 ON V2915.OBJ_ID = L14.OBJ_ID AND V2915.PARAM_ID = 2915 AND V2915.IS_DEL = 0
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND EXISTS(
        SELECT FIRST 1 1
        FROM LINKS L15
        LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
        WHERE L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL AND (V74.VAL IS NULL OR V74.VAL >= :V$YDATE)
      )
    )
    GROUP BY 1
    ORDER BY 1
    INTO :TEACHER_ID, :V$PERSON_ID, :V$DT1
  DO
  BEGIN

    -- Специальности выгружаем только для учительских должностей

    FOR
      SELECT L15.OBJ_ID, L15.DATE_INS, V58.LISTVAL_ID, MAXVALUE(L15.DATE_MODIFY, V73.DATE_MODIFY, V74.DATE_MODIFY, V72.DATE_MODIFY, V63.DATE_MODIFY)
      FROM LINKS L15
      JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
      JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0
      LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
      JOIN VALS V66 ON V66.OBJ_ID = LP13.PARENT_ID AND V66.PARAM_ID = 66 AND V66.IS_DEL = 0
      JOIN VALL V72 ON V72.OBJ_ID = L15.OBJ_ID AND V72.PARAM_ID = 72 AND V72.IS_DEL = 0
      JOIN VALL V63 ON V63.OBJ_ID = LP13.PARENT_ID AND V63.PARAM_ID = 63 AND V63.IS_DEL = 0 -- группа должностей
      JOIN VALL V64 ON V64.OBJ_ID = LP13.PARENT_ID AND V64.PARAM_ID = 64 AND V64.IS_DEL = 0 -- подгруппа должностей
      JOIN VALL V58 ON V58.OBJ_ID = LP13.PARENT_ID AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0 -- сама должность
      WHERE L15.PARENT_ID = :V$PERSON_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
        -- Только раздел: учителя
        AND V64.LISTVAL_ID = 98
      INTO :TEACHER_ROLE_ID, :CREATE_DATETIME, :V$JOB, :V$DT2
    DO
    BEGIN
      -- Роль всегда = должность
      -- Но к роли всегда добавляем ID должности
      ID = TEACHER_ROLE_ID || ':' || V$JOB;

      -- Перекодируем должности
      CODE = NULL;
      IF(V$JOB = 99) THEN
      BEGIN
        -- Учитель английского языка
        CODE = '05';
        NAME = 'Иностранные языки';
      END
      ELSE IF(V$JOB = 100) THEN
      BEGIN
        -- Учитель биологии
        CODE = '01.1';
        NAME = 'Биология (осн)';
      END
      ELSE IF(V$JOB = 101) THEN
      BEGIN
        -- Учитель географии
        CODE = '10.2';
        NAME = 'География (осн)';
      END
      ELSE IF(V$JOB = 102) THEN
      BEGIN
        -- Учитель информатики и ИКТ
        CODE = '09';
        NAME = 'Математика и информатика';
      END
      ELSE IF(V$JOB = 104) THEN
      BEGIN
        -- Учитель истории
        CODE = '11.2';
        NAME = 'История';
      END
      ELSE IF(V$JOB = 105) THEN
      BEGIN
        -- Учитель математики
        CODE = '08';
        NAME = 'Математика';
      END
      ELSE IF(V$JOB = 106) THEN
      BEGIN
        -- Учитель музыки
        CODE = '07.3';
        NAME = 'Музыка';
      END
      ELSE IF(V$JOB = 107) THEN
      BEGIN
        -- Учитель МХК
      END
      ELSE IF(V$JOB = 108) THEN
      BEGIN
        -- Учитель начальных классов
      END
      ELSE IF(V$JOB = 109) THEN
      BEGIN
        -- Учитель немецкого языка
        CODE = '05';
        NAME = 'Иностранные языки';
      END
      ELSE IF(V$JOB = 110) THEN
      BEGIN
        -- Учитель ОБЖ
        CODE = '24.3';
        NAME = 'Основы безопасности жизнедеятельности (средн в том числе для ОВЗ)';
      END
      ELSE IF(V$JOB = 111) THEN
      BEGIN
        -- Учитель ИЗО
        CODE = '07.1';
        NAME = 'Изобразительное искусство';
      END
      ELSE IF(V$JOB = 112) THEN
      BEGIN
        -- Учитель русского языка
        CODE = '19.1';
        NAME = 'Русский язык (осн средн)';
      END
      ELSE IF(V$JOB = 114) THEN
      BEGIN
        -- Учитель труда
        CODE = '21';
        NAME = 'Технология';
      END
      ELSE IF(V$JOB = 115) THEN
      BEGIN
        -- Учитель физики
        CODE = '02.4';
        NAME = 'Физика (средн)';
      END
      ELSE IF(V$JOB = 116) THEN
      BEGIN
        -- Учитель физической культуры
        CODE = '22';
        NAME = 'Физическая культура';
      END
      ELSE IF(V$JOB = 117) THEN
      BEGIN
        -- Учитель французского языка
        CODE = '05';
        NAME = 'Иностранные языки';
      END
      ELSE IF(V$JOB = 118) THEN
      BEGIN
        -- Учитель химии
        CODE = '02.5';
        NAME = 'Химия (средн)';
      END
      ELSE IF(V$JOB = 119) THEN
      BEGIN
        -- Учитель логопед
      END
      ELSE IF(V$JOB = 120) THEN
      BEGIN
        -- Учитель дефектолог
      END
      ELSE IF(V$JOB = 122) THEN
      BEGIN
        -- Преподаватель
      END
      ELSE IF(V$JOB = 1260) THEN
      BEGIN
        -- Учитель русского и литературы
        CODE = '19';
        NAME = 'Русский язык и литература';
      END
      ELSE IF(V$JOB = 1264) THEN
      BEGIN
        -- Учитель иностранного языка
        CODE = '06';
        NAME = 'Иностранный язык';
      END
      ELSE IF(V$JOB = 1268) THEN
      BEGIN
        -- Учитель обществознания
        CODE = '11.3';
        NAME = 'Обществознание (средн)';
      END
      ELSE IF(V$JOB = 1273) THEN
      BEGIN
        -- Учитель экономики
        CODE = '11.6';
        NAME = 'Экономика';
      END
      ELSE IF(V$JOB = 1278) THEN
      BEGIN
        -- Учитель права
        CODE = '11.4';
        NAME = 'Право';
      END
      ELSE IF(V$JOB = 1282) THEN
      BEGIN
        -- Учитель истории СПб
      END
      ELSE IF(V$JOB = 1283) THEN
      BEGIN
        -- Учитель краеведения
      END
      ELSE IF(V$JOB = 1285) THEN
      BEGIN
        -- Естественно-научные предметы
        CODE = '01';
        NAME = 'Естественно-научные предметы';
      END
      ELSE IF(V$JOB = 1286) THEN
      BEGIN
        -- Учитель технологии
        CODE = '21';
        NAME = 'Технология';
      END
      ELSE IF(V$JOB = 1089) THEN
      BEGIN
        -- Учитель природоведения
      END
      ELSE IF(V$JOB = 3148) THEN
      BEGIN
        -- Учитель черчения
      END

      IF(CODE IS NOT NULL AND (I$DT1 IS NULL OR V$DT1 >= I$DT1 OR V$DT2 >= I$DT1)) THEN
      SUSPEND;
    END

  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_MS_STATCOMMON (
    I$DT1 TIMESTAMP,
    I$DT2 TIMESTAMP NOT NULL = CURRENT_TIMESTAMP)
RETURNS (
    PERIOD_ID VARCHAR(40),
    STUDENT_ID VARCHAR(60),
    START_OF_WEEK DATE,
    CLASS_ID VARCHAR(40),
    DATETIME TIMESTAMP,
    TOTAL VARCHAR(20),
    FIVEPOINT_TOTAL VARCHAR(20),
    TEST VARCHAR(20),
    FIVEPOINT_TEST VARCHAR(20),
    SCHOOL_ID VARCHAR(40),
    CLASS_NUM INTEGER,
    CLASS_YEAR_FROM INTEGER,
    MARK_SCALE_CODE VARCHAR(20),
    MARK_SCALE_VALUE INTEGER,
    MARK_SCALE_DESCRIPTION VARCHAR(40),
    CREATE_DATETIME TIMESTAMP,
    SEND_DATETIME TIMESTAMP)
AS
DECLARE VARIABLE V$GP_ID BIGINT;
DECLARE VARIABLE V$Y INTEGER;
DECLARE VARIABLE V$YSTART DATE;
DECLARE VARIABLE V$YEND DATE;
DECLARE VARIABLE V$WSTART DATE;
DECLARE VARIABLE V$STUDENT_ID BIGINT;
DECLARE VARIABLE V$CLASS_ID BIGINT;
DECLARE VARIABLE V$PERIOD_ID BIGINT;
DECLARE VARIABLE V$PERIOD_DATE DATE;
DECLARE VARIABLE V$SCHOOL_ID BIGINT;
DECLARE VARIABLE V$FROM_DATE DATE;
DECLARE VARIABLE PERIOD_NUM INTEGER;
DECLARE VARIABLE V$T DOUBLE PRECISION;
DECLARE VARIABLE V$B DOUBLE PRECISION;
DECLARE VARIABLE V$T2 DOUBLE PRECISION;
DECLARE VARIABLE V$B2 DOUBLE PRECISION;
DECLARE VARIABLE N INTEGER;
DECLARE VARIABLE V$DT1 TIMESTAMP;
DECLARE VARIABLE V$DT2 TIMESTAMP;
DECLARE VARIABLE V$DT3 TIMESTAMP;
DECLARE VARIABLE V$DT4 TIMESTAMP;
begin

  CREATE_DATETIME = I$DT2;
  SEND_DATETIME = I$DT2;
  DATETIME = I$DT2;

  MARK_SCALE_VALUE = '1';
  MARK_SCALE_CODE = '5-points';
  MARK_SCALE_DESCRIPTION = 'Пятибалльная';

  SELECT FIRST 1 L2.OBJ_ID, V1236.LISTVAL_ID, LV.COST, V9.VAL
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  JOIN VALS V9 ON V9.OBJ_ID = L2.OBJ_ID AND V9.PARAM_ID = 9 AND V9.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$SCHOOL_ID, :V$GP_ID, :V$Y, :SCHOOL_ID;

  V$YSTART = '01.09.' || V$Y;
  V$YEND = '31.08.' || (V$Y + 1);
  CLASS_YEAR_FROM = V$Y;

  -- Подбираем ближайший понедельник следующий за 1 сентября
  N = EXTRACT(WEEKDAY FROM V$YSTART); -- 0 = ВС
  IF(N = 0) THEN N = 6; ELSE N = N - 1;
  V$WSTART = DATEADD((7 - N) DAY TO V$YSTART);

  IF(V$SCHOOL_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Объект школы не найден';

  FOR
    SELECT M.PERSON_ID, V2912.SVAL, MAX(M.DATE_MODIFY), MAX(V2912.DATE_MODIFY)
    FROM PERSON_MOVEMENTS M
    JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID IN (9, 125, 187)
    JOIN VALS V2912 ON V2912.OBJ_ID = M.PERSON_ID AND V2912.PARAM_ID = 2912 AND V2912.IS_DEL = 0
    WHERE M.DATE_DEL IS NULL AND M.DATE_IN <= :V$YEND AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :V$YSTART)
      AND EXISTS(
        SELECT FIRST 1 1
        FROM LINKS LPG
        WHERE LPG.OBJ_ID = M.PERSON_ID AND LPG.PARENT_TYPE_ID IN (9, 125, 187) AND LPG.DATE_DEL IS NULL
      )
      AND M.LEVEL_ID IN (22, 26, 27)
    GROUP BY 1, 2
    ORDER BY 1
    INTO :V$STUDENT_ID, :STUDENT_ID, :V$DT1, :V$DT2
  DO
  BEGIN
    IF(POSITION(':' IN STUDENT_ID) > 0) THEN STUDENT_ID = SUBSTRING(STUDENT_ID FROM 1 FOR POSITION(':' IN STUDENT_ID) - 1);
    STUDENT_ID = REPLACE(STUDENT_ID, '{', '');
    STUDENT_ID = REPLACE(STUDENT_ID, '}', '');
    STUDENT_ID = LOWER(STUDENT_ID);

    V$DT3 = NULL;
    SELECT MAX(MAXVALUE(L20.DATE_INS, V155.DATE_MODIFY, V1570.DATE_MODIFY))
    FROM LINKS L20
    JOIN VALS V155 ON V155.OBJ_ID = L20.OBJ_ID AND V155.PARAM_ID = 155 AND V155.IS_DEL = 0
    JOIN VALS V1570 ON V1570.OBJ_ID = L20.EXT_OBJ_ID AND V1570.PARAM_ID = 1570 AND V1570.IS_DEL = 0
    WHERE L20.PARENT_ID = :V$STUDENT_ID AND L20.OBJ_TYPE_ID = 20 AND L20.DATE_DEL IS NULL
    INTO :V$DT3;

    -- Проходим по всем классам, где ученик побывал
    FOR
      SELECT M.GROUP_ID, LV.COST, MIN(M.DATE_IN)
      FROM PERSON_MOVEMENTS M
      JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
      JOIN LISTVALS LV ON LV.LISTVAL_ID = M.STAGE_ID
      WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :V$STUDENT_ID AND M.DATE_IN <= :V$YEND
        AND (M.DATE_OUT IS NULL OR (M.DATE_OUT >= :V$YSTART AND M.DATE_OUT <= :V$YEND AND M.DATE_OUT <> M.DATE_IN))
        AND M.LEVEL_ID IN (22, 26, 27)
      GROUP BY 1, 2
      ORDER BY 1, 2
      INTO :V$CLASS_ID, :CLASS_NUM, :V$FROM_DATE
    DO
    BEGIN

      CLASS_ID = V$CLASS_ID || 'Y' || CLASS_YEAR_FROM;

      N = EXTRACT(WEEKDAY FROM V$FROM_DATE); -- 0 = ВС
      IF(N = 0) THEN N = 6; ELSE N = N - 1;
      V$FROM_DATE = DATEADD((7 - N) DAY TO V$FROM_DATE);

      START_OF_WEEK = MAXVALUE(V$WSTART, V$FROM_DATE);
      WHILE(START_OF_WEEK <= CURRENT_DATE AND START_OF_WEEK <= V$YEND) DO
      BEGIN

        -- Если неделя попадает враскоряку, она будет относиться по началу недели
        V$PERIOD_ID = NULL;
        SELECT FIRST 1 V1170.LISTVAL_ID, V1174.VAL, SUM(CT.DEFAULT_COST * MT.MARK_COST), SUM(CT.DEFAULT_COST),  -- C.CONTROL_COST
          SUM(IIF(CT.CONTROL_TYPE_ID IN (1084, 1085, 1087, 1091), CT.DEFAULT_COST * MT.MARK_COST, 0)), SUM(IIF(CT.CONTROL_TYPE_ID IN (1084, 1085, 1087, 1091), CT.DEFAULT_COST, 0)),
          MAX(MAXVALUE(MV.DATE_MODIFY, V1169.DATE_MODIFY, V1174.DATE_MODIFY, V1170.DATE_MODIFY))
        FROM PERSON_MOVEMENTS M
        JOIN PERSON_MOVEMENTS M2 ON M2.DATE_DEL IS NULL AND M2.PERSON_ID = M.PERSON_ID
          AND (M2.DATE_IN <= M.DATE_OUT OR M.DATE_OUT IS NULL)
          AND ((M2.DATE_OUT >= M.DATE_IN AND M2.DATE_OUT > M2.DATE_IN) OR M2.DATE_OUT IS NULL)
          AND M2.LEVEL_ID IN (22, 26, 27)
        JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.JOURNAL_TYPE = 0 AND J.GRADE_ID = M2.GROUP_ID
        JOIN CJ2_JOURNAL_LESSONS L ON L.CJ_ID = J.OBJ_ID AND L.DATE_DEL IS NULL AND L.LESSON_DATE >= M.DATE_IN AND (L.LESSON_DATE <= M.DATE_OUT OR M.DATE_OUT IS NULL)
          AND L.LESSON_DATE < :START_OF_WEEK
        JOIN CJ2_CONTROL C ON C.LESSON_ID = L.OBJ_ID AND C.DATE_DEL IS NULL AND C.CONTROL_TYPE_ID <> 0
        JOIN CJ2_CONTROL_TYPE CT ON CT.CONTROL_TYPE_ID = C.CONTROL_TYPE_ID
        JOIN CJ2_MARK MV ON MV.DATE_DEL IS NULL AND MV.CONTROL_ID = C.CONTROL_ID AND MV.STUDENT_ID = M.PERSON_ID
        JOIN CJ2_MARK_TYPE MT ON MT.MARK_TYPE_ID = MV.MARK_TYPE_ID
        -- Выбираем подходящий период
        JOIN LINKS L154 ON L154.PARENT_ID = J.PERIOD_ID AND L154.OBJ_TYPE_ID = 154 AND L154.DATE_DEL IS NULL
        JOIN VALD V1169 ON V1169.OBJ_ID = L154.OBJ_ID AND V1169.PARAM_ID = 1169 AND V1169.IS_DEL = 0 AND V1169.VAL <= L.LESSON_DATE
          AND V1169.VAL <= :START_OF_WEEK
        JOIN VALD V1174 ON V1174.OBJ_ID = L154.OBJ_ID AND V1174.PARAM_ID = 1174 AND V1174.IS_DEL = 0 AND V1174.VAL > L.LESSON_DATE
          AND V1174.VAL > :START_OF_WEEK
        JOIN VALL V1170 ON V1170.OBJ_ID = L154.OBJ_ID AND V1170.PARAM_ID = 1170 AND V1170.IS_DEL = 0
        WHERE M.DATE_DEL IS NULL AND M.GROUP_ID = :V$CLASS_ID AND M.PERSON_ID = :V$STUDENT_ID AND M.DATE_IN <= :V$YEND
          AND (M.DATE_OUT IS NULL OR (M.DATE_OUT >= :V$YSTART AND M.DATE_OUT <= :V$YEND AND M.DATE_OUT <> M.DATE_IN))
          AND M.LEVEL_ID IN (22, 26, 27)
        GROUP BY 1, 2
        ORDER BY 1
        INTO :V$PERIOD_ID, :CREATE_DATETIME, :V$T, :V$B, :V$T2, :V$B2, :V$DT4;

        IF(V$PERIOD_ID IS NOT NULL AND V$B > 0) THEN
        BEGIN
          CREATE_DATETIME = START_OF_WEEK;

          TOTAL = CAST(V$T / V$B AS NUMERIC(18, 2));
          FIVEPOINT_TOTAL = CAST(V$T / V$B AS NUMERIC(18, 1));
          IF(V$B2 > 0) THEN
          BEGIN
            TEST = CAST(V$T2 / V$B2 AS NUMERIC(18, 2));
            FIVEPOINT_TEST = CAST(V$T2 / V$B2 AS NUMERIC(18, 1));
          END
          ELSE
          BEGIN
            TEST = NULL;
            FIVEPOINT_TEST = NULL;
          END

          IF(V$PERIOD_ID IN (12, 13, 14, 15)) THEN BEGIN
            PERIOD_NUM = V$PERIOD_ID - 12 + 1;
            PERIOD_ID = CLASS_YEAR_FROM || '-Q' || PERIOD_NUM;
          END
          ELSE IF(V$PERIOD_ID IN (10, 11)) THEN BEGIN
            PERIOD_NUM = V$PERIOD_ID - 10 + 1;
            PERIOD_ID = CLASS_YEAR_FROM || '-H' || PERIOD_NUM;
          END
          ELSE IF(V$PERIOD_ID IN (16, 17, 18)) THEN BEGIN
            PERIOD_NUM = V$PERIOD_ID - 16 + 1;
            PERIOD_ID = CLASS_YEAR_FROM || '-T' || PERIOD_NUM;
          END
          -- семестры ?!!!

          IF(I$DT1 IS NULL OR V$DT1 >= I$DT1 OR V$DT2 >= I$DT1 OR V$DT3 >= I$DT1 OR V$DT4 >= I$DT1) THEN
          SUSPEND;
        END

        START_OF_WEEK = DATEADD(7 DAY TO START_OF_WEEK);
      END

    END

  END

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_MS_STATSUBJECT (
    I$DT1 TIMESTAMP,
    I$DT2 TIMESTAMP NOT NULL = CURRENT_TIMESTAMP)
RETURNS (
    PERIOD_ID VARCHAR(40),
    STUDENT_ID VARCHAR(60),
    SUBJECT_ID BIGINT,
    START_OF_WEEK DATE,
    CLASS_ID VARCHAR(40),
    DATETIME TIMESTAMP,
    TOTAL VARCHAR(20),
    FIVEPOINT_TOTAL VARCHAR(20),
    TEST VARCHAR(20),
    FIVEPOINT_TEST VARCHAR(20),
    SCHOOL_ID VARCHAR(40),
    CLASS_NUM INTEGER,
    CLASS_YEAR_FROM INTEGER,
    MARK_SCALE_CODE VARCHAR(20),
    MARK_SCALE_VALUE INTEGER,
    MARK_SCALE_DESCRIPTION VARCHAR(40),
    CREATE_DATETIME TIMESTAMP,
    SEND_DATETIME TIMESTAMP)
AS
DECLARE VARIABLE V$GP_ID BIGINT;
DECLARE VARIABLE V$Y INTEGER;
DECLARE VARIABLE V$YSTART DATE;
DECLARE VARIABLE V$YEND DATE;
DECLARE VARIABLE V$STUDENT_ID BIGINT;
DECLARE VARIABLE V$CLASS_ID BIGINT;
DECLARE VARIABLE V$PERIOD_ID BIGINT;
DECLARE VARIABLE V$FROM_DATE DATE;
DECLARE VARIABLE V$WSTART DATE;
DECLARE VARIABLE V$T DOUBLE PRECISION;
DECLARE VARIABLE V$B DOUBLE PRECISION;
DECLARE VARIABLE V$T2 DOUBLE PRECISION;
DECLARE VARIABLE V$B2 DOUBLE PRECISION;
DECLARE VARIABLE V$SCHOOL_ID BIGINT;
DECLARE VARIABLE N INTEGER;
DECLARE VARIABLE PERIOD_NUM INTEGER;
DECLARE VARIABLE V$DT1 TIMESTAMP;
DECLARE VARIABLE V$DT2 TIMESTAMP;
DECLARE VARIABLE V$DT3 TIMESTAMP;
DECLARE VARIABLE V$DT4 TIMESTAMP;
begin

  CREATE_DATETIME = I$DT2;
  SEND_DATETIME = I$DT2;
  DATETIME = I$DT2;

  MARK_SCALE_VALUE = '1';
  MARK_SCALE_CODE = '5-points';
  MARK_SCALE_DESCRIPTION = 'Пятибалльная';

  SELECT FIRST 1 L2.OBJ_ID, V1236.LISTVAL_ID, LV.COST, V9.VAL
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  JOIN VALS V9 ON V9.OBJ_ID = L2.OBJ_ID AND V9.PARAM_ID = 9 AND V9.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$SCHOOL_ID, :V$GP_ID, :V$Y, :SCHOOL_ID;

  V$YSTART = '01.09.' || V$Y;
  V$YEND = '31.08.' || (V$Y + 1);
  CLASS_YEAR_FROM = V$Y;

  -- Подбираем ближайший понедельник следующий за 1 сентября
  N = EXTRACT(WEEKDAY FROM V$YSTART); -- 0 = ВС
  IF(N = 0) THEN N = 6; ELSE N = N - 1;
  V$WSTART = DATEADD((7 - N) DAY TO V$YSTART);

  IF(V$SCHOOL_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Объект школы не найден';

  FOR
    SELECT M.PERSON_ID, V2912.SVAL, MAX(M.DATE_MODIFY), MAX(V2912.DATE_MODIFY)
    FROM PERSON_MOVEMENTS M
    -- Фильтруем только действующих учеников
    JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID IN (9, 125, 187)
    JOIN VALS V2912 ON V2912.OBJ_ID = M.PERSON_ID AND V2912.PARAM_ID = 2912 AND V2912.IS_DEL = 0
    WHERE M.DATE_DEL IS NULL AND M.DATE_IN <= :V$YEND AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :V$YSTART)
      AND EXISTS(
        SELECT FIRST 1 1
        FROM LINKS LPG
        WHERE LPG.OBJ_ID = M.PERSON_ID AND LPG.PARENT_TYPE_ID IN (9, 125, 187) AND LPG.DATE_DEL IS NULL
      )
      AND M.LEVEL_ID IN (22, 26, 27)
    GROUP BY 1, 2
    ORDER BY 1
    INTO :V$STUDENT_ID, :STUDENT_ID, :V$DT1, :V$DT2
  DO
  BEGIN
    IF(POSITION(':' IN STUDENT_ID) > 0) THEN STUDENT_ID = SUBSTRING(STUDENT_ID FROM 1 FOR POSITION(':' IN STUDENT_ID) - 1);
    STUDENT_ID = REPLACE(STUDENT_ID, '{', '');
    STUDENT_ID = REPLACE(STUDENT_ID, '}', '');
    STUDENT_ID = LOWER(STUDENT_ID);

    V$DT3 = NULL;
    SELECT MAX(MAXVALUE(L20.DATE_INS, V155.DATE_MODIFY, V1570.DATE_MODIFY))
    FROM LINKS L20
    JOIN VALS V155 ON V155.OBJ_ID = L20.OBJ_ID AND V155.PARAM_ID = 155 AND V155.IS_DEL = 0
    JOIN VALS V1570 ON V1570.OBJ_ID = L20.EXT_OBJ_ID AND V1570.PARAM_ID = 1570 AND V1570.IS_DEL = 0
    WHERE L20.PARENT_ID = :V$STUDENT_ID AND L20.OBJ_TYPE_ID = 20 AND L20.DATE_DEL IS NULL
    INTO :V$DT3;

    -- Проходим по всем классам, где ученик побывал
    FOR
      SELECT M.GROUP_ID, LV.COST, MIN(M.DATE_IN)
      FROM PERSON_MOVEMENTS M
      JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID IN (9, 125, 187)
      JOIN LISTVALS LV ON LV.LISTVAL_ID = M.STAGE_ID
      WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :V$STUDENT_ID AND M.DATE_IN <= :V$YEND
        AND (M.DATE_OUT IS NULL OR (M.DATE_OUT >= :V$YSTART AND M.DATE_OUT <= :V$YEND AND M.DATE_OUT <> M.DATE_IN))
        AND M.LEVEL_ID IN (22, 26, 27)
      GROUP BY 1, 2
      ORDER BY 1, 2
      INTO :V$CLASS_ID, :CLASS_NUM, :V$FROM_DATE
    DO
    BEGIN

      CLASS_ID = V$CLASS_ID || 'Y' || CLASS_YEAR_FROM;

      N = EXTRACT(WEEKDAY FROM V$FROM_DATE); -- 0 = ВС
      IF(N = 0) THEN N = 6; ELSE N = N - 1;
      V$FROM_DATE = DATEADD((7 - N) DAY TO V$FROM_DATE);

      START_OF_WEEK = MAXVALUE(V$WSTART, V$FROM_DATE);
      WHILE(START_OF_WEEK <= CURRENT_DATE AND START_OF_WEEK <= V$YEND) DO
      BEGIN

        -- Если неделя попадает враскоряку, она будет относиться по началу недели
        FOR
          SELECT J.SUBJECT_ID, V1170.LISTVAL_ID, V1174.VAL, SUM(CT.DEFAULT_COST * MT.MARK_COST), SUM(CT.DEFAULT_COST),  -- C.CONTROL_COST
            SUM(IIF(CT.CONTROL_TYPE_ID IN (1084, 1085, 1087, 1091), CT.DEFAULT_COST * MT.MARK_COST, 0)), SUM(IIF(CT.CONTROL_TYPE_ID IN (1084, 1085, 1087, 1091), CT.DEFAULT_COST, 0)),
            MAX(MAXVALUE(MV.DATE_MODIFY, V1169.DATE_MODIFY, V1174.DATE_MODIFY, V1170.DATE_MODIFY))
          FROM PERSON_MOVEMENTS M
          JOIN PERSON_MOVEMENTS M2 ON M2.DATE_DEL IS NULL AND M2.PERSON_ID = M.PERSON_ID
            AND (M2.DATE_IN <= M.DATE_OUT OR M.DATE_OUT IS NULL)
            AND ((M2.DATE_OUT >= M.DATE_IN AND M2.DATE_OUT > M2.DATE_IN) OR M2.DATE_OUT IS NULL)
            AND M2.LEVEL_ID IN (22, 26, 27)
          JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.JOURNAL_TYPE = 0 AND J.GRADE_ID = M2.GROUP_ID
          JOIN CJ2_JOURNAL_LESSONS L ON L.CJ_ID = J.OBJ_ID AND L.DATE_DEL IS NULL AND L.LESSON_DATE >= M.DATE_IN AND (L.LESSON_DATE <= M.DATE_OUT OR M.DATE_OUT IS NULL)
            AND L.LESSON_DATE < :START_OF_WEEK
          JOIN CJ2_CONTROL C ON C.LESSON_ID = L.OBJ_ID AND C.DATE_DEL IS NULL AND C.CONTROL_TYPE_ID <> 0
          JOIN CJ2_CONTROL_TYPE CT ON CT.CONTROL_TYPE_ID = C.CONTROL_TYPE_ID
          JOIN CJ2_MARK MV ON MV.DATE_DEL IS NULL AND MV.CONTROL_ID = C.CONTROL_ID AND MV.STUDENT_ID = M.PERSON_ID
          JOIN CJ2_MARK_TYPE MT ON MT.MARK_TYPE_ID = MV.MARK_TYPE_ID
          -- Выбираем подходящий период
          JOIN LINKS L154 ON L154.PARENT_ID = J.PERIOD_ID AND L154.OBJ_TYPE_ID = 154 AND L154.DATE_DEL IS NULL
          JOIN VALD V1169 ON V1169.OBJ_ID = L154.OBJ_ID AND V1169.PARAM_ID = 1169 AND V1169.IS_DEL = 0 AND V1169.VAL <= L.LESSON_DATE
            AND V1169.VAL <= :START_OF_WEEK
          JOIN VALD V1174 ON V1174.OBJ_ID = L154.OBJ_ID AND V1174.PARAM_ID = 1174 AND V1174.IS_DEL = 0 AND V1174.VAL > L.LESSON_DATE
            AND V1174.VAL > :START_OF_WEEK
          JOIN VALL V1170 ON V1170.OBJ_ID = L154.OBJ_ID AND V1170.PARAM_ID = 1170 AND V1170.IS_DEL = 0
          WHERE M.DATE_DEL IS NULL AND M.GROUP_ID = :V$CLASS_ID AND M.PERSON_ID = :V$STUDENT_ID AND M.DATE_IN <= :V$YEND
            AND (M.DATE_OUT IS NULL OR (M.DATE_OUT >= :V$YSTART AND M.DATE_OUT <= :V$YEND AND M.DATE_OUT <> M.DATE_IN))
            AND M.LEVEL_ID IN (22, 26, 27)
          GROUP BY 1, 2, 3
          ORDER BY 1, 2
          INTO :SUBJECT_ID, :V$PERIOD_ID, :CREATE_DATETIME, :V$T, :V$B, :V$T2, :V$B2, :V$DT4
        DO
        BEGIN

          IF(V$B > 0) THEN
          BEGIN
            CREATE_DATETIME = START_OF_WEEK;

            TOTAL = CAST(V$T / V$B AS NUMERIC(18, 2));
            FIVEPOINT_TOTAL = CAST(V$T / V$B AS NUMERIC(18, 1));
            IF(V$B2 > 0) THEN
            BEGIN
              TEST = CAST(V$T2 / V$B2 AS NUMERIC(18, 2));
              FIVEPOINT_TEST = CAST(V$T2 / V$B2 AS NUMERIC(18, 1));
            END
            ELSE
            BEGIN
              TEST = 'NULL';
              FIVEPOINT_TEST = 'NULL';
            END

            IF(V$PERIOD_ID IN (12, 13, 14, 15)) THEN BEGIN
              PERIOD_NUM = V$PERIOD_ID - 12 + 1;
              PERIOD_ID = CLASS_YEAR_FROM || '-Q' || PERIOD_NUM;
            END
            ELSE IF(V$PERIOD_ID IN (10, 11)) THEN BEGIN
              PERIOD_NUM = V$PERIOD_ID - 10 + 1;
              PERIOD_ID = CLASS_YEAR_FROM || '-H' || PERIOD_NUM;
            END
            ELSE IF(V$PERIOD_ID IN (16, 17, 18)) THEN BEGIN
              PERIOD_NUM = V$PERIOD_ID - 16 + 1;
              PERIOD_ID = CLASS_YEAR_FROM || '-T' || PERIOD_NUM;
            END
            -- семестры ?!!!

            IF(I$DT1 IS NULL OR V$DT1 >= I$DT1 OR V$DT2 >= I$DT1 OR V$DT3 >= I$DT1 OR V$DT4 >= I$DT1) THEN
            SUSPEND;
          END

        END

        START_OF_WEEK = DATEADD(7 DAY TO START_OF_WEEK);
      END

    END

  END

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_MS_STUDENTS_COLLEGE (
    I$DT1 TIMESTAMP,
    I$DT2 TIMESTAMP NOT NULL = current_timestamp)
RETURNS (
    STUDENT_ID VARCHAR(60))
AS
declare variable V$SCHOOL_ID bigint;
declare variable V$GY_ID bigint;
declare variable V$Y integer;
declare variable V$RANGE_FROM date;
begin

  SELECT FIRST 1 L2.OBJ_ID, V1236.LISTVAL_ID, LV.COST
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  JOIN VALS V9 ON V9.OBJ_ID = L2.OBJ_ID AND V9.PARAM_ID = 9 AND V9.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$SCHOOL_ID, :V$GY_ID, :V$Y;

  V$RANGE_FROM = '31.08.' || (V$Y - 3);

  -- Выбираем всех обучающихся, засветившихся в колледже за последние 3 года, но только действующих
  -- только тех у кого есть паспорт
  -- исключаем из выборки профессиональное обучение
  -- + академический отпуск
  FOR
    SELECT DISTINCT V2912.SVAL
    FROM LINKS L10
    JOIN PERSON_MOVEMENTS M ON M.DATE_DEL IS NULL AND M.PERSON_ID = L10.OBJ_ID AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :V$RANGE_FROM)
    JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
    LEFT JOIN VALL V3367 ON V3367.OBJ_ID = M.GROUP_ID AND V3367.PARAM_ID = 3367 AND V3367.IS_DEL = 0
    -- Есть регид
    JOIN VALS V2912 ON V2912.OBJ_ID = M.PERSON_ID AND V2912.PARAM_ID = 2912 AND V2912.IS_DEL = 0
    WHERE L10.PARENT_TYPE_ID IN (9, 125, 187, 289, 81, 82, 83) AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL -- , 81, 82, 83
    -- не профобучение
    AND V3367.LISTVAL_ID IS NULL
    AND EXISTS (
      SELECT FIRST 1 1
      FROM LINKS L79
      JOIN VALL V441 ON V441.OBJ_ID = L79.OBJ_ID AND V441.PARAM_ID = 441 AND V441.IS_DEL = 0 AND V441.LISTVAL_ID IN (1368, 1373, 1371)
      WHERE L79.PARENT_ID = L10.OBJ_ID AND L79.OBJ_TYPE_ID = 79 AND L79.DATE_DEL IS NULL
    )
    ORDER BY 1
    INTO :STUDENT_ID
  DO
  BEGIN
    IF(POSITION(':' IN STUDENT_ID) > 0) THEN STUDENT_ID = SUBSTRING(STUDENT_ID FROM 1 FOR POSITION(':' IN STUDENT_ID) - 1);
    STUDENT_ID = REPLACE(STUDENT_ID, '{', '');
    STUDENT_ID = REPLACE(STUDENT_ID, '}', '');
    STUDENT_ID = LOWER(STUDENT_ID);

    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_MS_STUDENTS_SCHOOL (
    I$DT1 TIMESTAMP,
    I$DT2 TIMESTAMP NOT NULL = CURRENT_TIMESTAMP)
RETURNS (
    ID VARCHAR(60),
    OID VARCHAR(40),
    AUTH_LINK VARCHAR(200),
    VK_ID VARCHAR(40),
    FIRSTNAME VARCHAR(100),
    LASTNAME VARCHAR(100),
    PATRONYMIC VARCHAR(100),
    HASH_GOST2012 VARCHAR(200),
    HASH_NUM INTEGER,
    HASH_GOST2012_2 VARCHAR(200),
    HASH_NUM_2 INTEGER,
    HASH_GOST2012_3 VARCHAR(200),
    HASH_NUM_3 INTEGER,
    BIRTHDATE VARCHAR(10),
    BIRTHPLACE VARCHAR(400),
    SNILS VARCHAR(40),
    E_MAIL VARCHAR(100),
    NUMB_PASSPORT VARCHAR(20),
    SER_PASSPORT VARCHAR(20),
    DATA_PASSPORT VARCHAR(10),
    GENDER_CODE VARCHAR(10),
    GENDER_VALUE INTEGER,
    GENDER_DESCRIPTION VARCHAR(20),
    START_DATETIME TIMESTAMP,
    END_DATETIME TIMESTAMP,
    ACTIVE VARCHAR(10),
    STATUS_CODE VARCHAR(20),
    STATUS_VALUE INTEGER,
    STATUS_DESCRIPTION VARCHAR(100),
    REASON_CODE VARCHAR(20),
    REASON_VALUE INTEGER,
    REASON_DESCRIPTION VARCHAR(100),
    DATA_START_STUDY DATE,
    EXPECT_END_STUDY DATE,
    DATA_END_STUDY DATE,
    RDDM_FIRST VARCHAR(10),
    CREATE_DATETIME TIMESTAMP,
    SEND_DATETIME TIMESTAMP,
    ORGN SMALLINT)
AS
DECLARE VARIABLE V$SCHOOL_ID BIGINT;
DECLARE VARIABLE V$GP_ID BIGINT;
DECLARE VARIABLE V$Y INTEGER;
DECLARE VARIABLE V$PERSON_ID BIGINT;
DECLARE VARIABLE V$HUSED INTEGER;
DECLARE VARIABLE DATA_SOR VARCHAR(200);
DECLARE VARIABLE SER_SOR VARCHAR(200);
DECLARE VARIABLE NUMB_SOR VARCHAR(200);
DECLARE VARIABLE V$STAGE INTEGER;
DECLARE VARIABLE V$DT1 TIMESTAMP;
DECLARE VARIABLE V$DT2 TIMESTAMP;
DECLARE VARIABLE V$FY INTEGER;
DECLARE VARIABLE V$FY2 INTEGER;
begin

  SEND_DATETIME = I$DT2;
  AUTH_LINK = 'login';
  -- active все равно будем корректировать с РК
  "ACTIVE" = 'true';
  STATUS_CODE = 'active';
  STATUS_VALUE = 1;
  STATUS_DESCRIPTION = 'Действует';
  /*REASON_CODE = 'start_study';
  REASON_VALUE = 1;
  REASON_DESCRIPTION = 'Начало обучения';*/

  -- START_DATETIME, END_DATETIME и REASON пока вообще не грузим
  -- DATA_START_STUDY подставляются на РК, не заполняем тут
  -- Сюда же добавляем выпускников текущего и прошлого учебного года

  V$FY = EXTRACT(YEAR FROM CURRENT_DATE);
  V$FY2 = V$FY + 1;

  SELECT FIRST 1 L2.OBJ_ID, V1236.LISTVAL_ID, LV.COST
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$SCHOOL_ID, :V$GP_ID, :V$Y;

  FOR
    -- Текущие ученики
    SELECT SID, MAX(OBJ_ID), MAX(DATE_MODIFY)
    FROM (
      SELECT V2912.SVAL SID, L10.OBJ_ID, L10.DATE_MODIFY
      FROM LINKS L2
      JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
      JOIN VALL V43 ON V43.OBJ_ID = L7.OBJ_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0 AND V43.LISTVAL_ID IN (22, 26, 27)
      JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
      JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      JOIN VALS V2912 ON V2912.OBJ_ID = L10.OBJ_ID AND V2912.PARAM_ID = 2912 AND V2912.IS_DEL = 0
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      UNION
      -- Окончившие (окончившие ДОУ будут в именном разделе)
      SELECT V2912.SVAL, L10.OBJ_ID, L10.DATE_MODIFY
      FROM LINKS L2
      JOIN LINKS L78 ON L78.PARENT_ID = L2.OBJ_ID AND L78.OBJ_TYPE_ID = 78 AND L78.DATE_DEL IS NULL
      JOIN LINKS L83 ON L83.PARENT_ID = L78.OBJ_ID AND L83.OBJ_TYPE_ID = 83 AND L83.DATE_DEL IS NULL
      JOIN VALI V451 ON V451.OBJ_ID = L83.OBJ_ID AND V451.PARAM_ID = 451 AND V451.IS_DEL = 0 AND (V451.VAL = :V$FY OR V451.VAL = :V$FY2)
      JOIN LINKS L10 ON L10.PARENT_ID = L83.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      JOIN VALS V2912 ON V2912.OBJ_ID = L10.OBJ_ID AND V2912.PARAM_ID = 2912 AND V2912.IS_DEL = 0
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      -- Выбывшие грузятся централизованно
    )
    GROUP BY 1
    ORDER BY 1
    INTO :ID, :V$PERSON_ID, :V$DT1
  DO
  BEGIN
    IF(POSITION(':' IN ID) > 0) THEN ID = SUBSTRING(ID FROM 1 FOR POSITION(':' IN ID) - 1);
    ID = REPLACE(ID, '{', '');
    ID = REPLACE(ID, '}', '');
    ID = LOWER(ID);

    -- 0 = действующий, 1 = выпустившийся
    ORGN = 0;
    SELECT FIRST 1 1
    FROM LINKS LP82
    WHERE LP82.OBJ_ID = :V$PERSON_ID AND LP82.PARENT_TYPE_ID = 82 AND LP82.DATE_DEL IS NULL
    INTO :ORGN;

    LASTNAME = NULL;
    FIRSTNAME = NULL;
    PATRONYMIC = NULL;
    BIRTHDATE = NULL;
    BIRTHPLACE = NULL;
    GENDER_VALUE = NULL;
    V$HUSED = 0;
    V$DT2 = NULL;

    SELECT V55.VAL, MAXVALUE(V55.DATE_MODIFY, :V$DT2)
    FROM VALS V55
    WHERE V55.OBJ_ID = :V$PERSON_ID AND V55.PARAM_ID = 55 AND V55.IS_DEL = 0
    INTO :LASTNAME, :V$DT2;

    SELECT V56.VAL, MAXVALUE(V56.DATE_MODIFY, :V$DT2)
    FROM VALS V56
    WHERE V56.OBJ_ID = :V$PERSON_ID AND V56.PARAM_ID = 56 AND V56.IS_DEL = 0
    INTO :FIRSTNAME, :V$DT2;

    SELECT V57.VAL, MAXVALUE(V57.DATE_MODIFY, :V$DT2)
    FROM VALS V57
    WHERE V57.OBJ_ID = :V$PERSON_ID AND V57.PARAM_ID = 57 AND V57.IS_DEL = 0
    INTO :PATRONYMIC, :V$DT2;

    SELECT D.VAL, MAXVALUE(V89.DATE_MODIFY, :V$DT2)
    FROM VALD V89
    LEFT JOIN DATE2ISO(V89.VAL, 0) D ON 1 = 1
    WHERE V89.OBJ_ID = :V$PERSON_ID AND V89.PARAM_ID = 89 AND V89.IS_DEL = 0
    INTO :BIRTHDATE, :V$DT2;

    SELECT IIF(V88.LISTVAL_ID = 182, 2, 1), MAXVALUE(V88.DATE_MODIFY, :V$DT2)
    FROM VALL V88
    WHERE V88.OBJ_ID = :V$PERSON_ID AND V88.PARAM_ID = 88 AND V88.IS_DEL = 0
    INTO :GENDER_VALUE, :V$DT2;

    IF(GENDER_VALUE = 1) THEN
    BEGIN
      GENDER_CODE = 'male';
      GENDER_DESCRIPTION = 'мужской';
    END
    IF(GENDER_VALUE = 2) THEN
    BEGIN
      GENDER_CODE = 'female';
      GENDER_DESCRIPTION = 'женский';
    END

    IF(LASTNAME IS NULL OR FIRSTNAME IS NULL OR BIRTHDATE IS NULL OR GENDER_VALUE IS NULL) THEN
      EXCEPTION DATA_ERROR 'Неполные данные об обучающемcя (не указаны ФИО, дата рождения или пол) ' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$PERSON_ID));

    VK_ID = NULL;
    SELECT V3354.VAL, MAXVALUE(V3354.DATE_MODIFY, :V$DT2)
    FROM VALS V3354
    WHERE V3354.OBJ_ID = :V$PERSON_ID AND V3354.PARAM_ID = 3354 AND V3354.IS_DEL = 0
    INTO :VK_ID, :V$DT2;

    BIRTHPLACE = NULL;
    SELECT V1343.VAL, MAXVALUE(V1343.DATE_MODIFY, :V$DT2)
    FROM VALS V1343
    WHERE V1343.OBJ_ID = :V$PERSON_ID AND V1343.PARAM_ID = 1343 AND V1343.IS_DEL = 0
    INTO :BIRTHPLACE, :V$DT2;

    E_MAIL = NULL;
    SELECT V3076.VAL, MAXVALUE(V3076.DATE_MODIFY, :V$DT2)
    FROM VALS V3076
    WHERE V3076.OBJ_ID = :V$PERSON_ID AND V3076.PARAM_ID = 3076 AND V3076.IS_DEL = 0
    INTO :E_MAIL, :V$DT2;

    SNILS = NULL;
    SELECT REPLACE(REPLACE(V1409.VAL, ' ', ''), '-', ''), MAXVALUE(V1409.DATE_MODIFY, :V$DT2)
    FROM VALS V1409
    WHERE V1409.OBJ_ID = :V$PERSON_ID AND V1409.PARAM_ID = 1409 AND V1409.IS_DEL = 0
    INTO :SNILS, :V$DT2;

    IF(SNILS IS NOT NULL) THEN
    BEGIN
      V$HUSED = V$HUSED + 1;
      IF(V$HUSED = 1) THEN BEGIN HASH_NUM = 1; HASH_GOST2012 = SNILS; END
      ELSE IF(V$HUSED = 2) THEN BEGIN HASH_NUM_2 = 1; HASH_GOST2012_2 = SNILS; END
      ELSE IF(V$HUSED = 3) THEN BEGIN HASH_NUM_3 = 1; HASH_GOST2012_3 = SNILS; END
    END

    -- Данные паспорта
    DATA_PASSPORT = NULL;
    NUMB_PASSPORT = NULL;
    SER_PASSPORT = NULL;
    SELECT FIRST 1 D.VAL, V442.VAL, V559.VAL, MAXVALUE(L79.DATE_MODIFY, V441.DATE_MODIFY, V614.DATE_MODIFY, V560.DATE_MODIFY, V442.DATE_MODIFY, V559.DATE_MODIFY, :V$DT2)
    FROM LINKS L79
    JOIN VALL V441 ON V441.OBJ_ID = L79.OBJ_ID AND V441.PARAM_ID = 441 AND V441.IS_DEL = 0 AND V441.LISTVAL_ID IN (1368, 1369)
    JOIN VALL V614 ON V614.OBJ_ID = L79.OBJ_ID AND V614.PARAM_ID = 614 AND V614.IS_DEL = 0 AND V614.LISTVAL_ID = 1982
    JOIN VALD V560 ON V560.OBJ_ID = L79.OBJ_ID AND V560.PARAM_ID = 560 AND V560.IS_DEL = 0
    LEFT JOIN DATE2ISO(V560.VAL, 0) D ON 1 = 1
    JOIN VALS V442 ON V442.OBJ_ID = L79.OBJ_ID AND V442.PARAM_ID = 442 AND V442.IS_DEL = 0
    JOIN VALS V559 ON V559.OBJ_ID = L79.OBJ_ID AND V559.PARAM_ID = 559 AND V559.IS_DEL = 0
    WHERE L79.PARENT_ID = :V$PERSON_ID AND L79.OBJ_TYPE_ID = 79 AND L79.DATE_DEL IS NULL
    ORDER BY V441.LISTVAL_ID
    INTO :DATA_PASSPORT, :SER_PASSPORT, :NUMB_PASSPORT, :V$DT2;

    IF(DATA_PASSPORT IS NOT NULL) THEN
    BEGIN
      V$HUSED = V$HUSED + 1;
      IF(V$HUSED = 1) THEN BEGIN HASH_NUM = 2; HASH_GOST2012 = SER_PASSPORT || ' ' || NUMB_PASSPORT; END
      ELSE IF(V$HUSED = 2) THEN BEGIN HASH_NUM_2 = 2; HASH_GOST2012_2 = SER_PASSPORT || ' ' || NUMB_PASSPORT; END
      ELSE IF(V$HUSED = 3) THEN BEGIN HASH_NUM_3 = 2; HASH_GOST2012_3 = SER_PASSPORT || ' ' || NUMB_PASSPORT; END
    END

    -- Свидетельство о рождении или иностранное свидетельство о рождении
    DATA_SOR = NULL;
    NUMB_SOR = NULL;
    SER_SOR = NULL;
    SELECT FIRST 1 D.VAL, REPLACE(REPLACE(UPPER(V442.VAL), ' ', ''), '-', ''), V559.VAL, MAXVALUE(L79.DATE_MODIFY, V441.DATE_MODIFY, V614.DATE_MODIFY, V560.DATE_MODIFY, V442.DATE_MODIFY, V559.DATE_MODIFY, :V$DT2)
    FROM LINKS L79
    JOIN VALL V441 ON V441.OBJ_ID = L79.OBJ_ID AND V441.PARAM_ID = 441 AND V441.IS_DEL = 0 AND V441.LISTVAL_ID IN (1370, 11343)
    JOIN VALL V614 ON V614.OBJ_ID = L79.OBJ_ID AND V614.PARAM_ID = 614 AND V614.IS_DEL = 0 AND V614.LISTVAL_ID = 1982
    JOIN VALD V560 ON V560.OBJ_ID = L79.OBJ_ID AND V560.PARAM_ID = 560 AND V560.IS_DEL = 0
    LEFT JOIN DATE2ISO(V560.VAL, 0) D ON 1 = 1
    JOIN VALS V442 ON V442.OBJ_ID = L79.OBJ_ID AND V442.PARAM_ID = 442 AND V442.IS_DEL = 0
    JOIN VALS V559 ON V559.OBJ_ID = L79.OBJ_ID AND V559.PARAM_ID = 559 AND V559.IS_DEL = 0
    WHERE L79.PARENT_ID = :V$PERSON_ID AND L79.OBJ_TYPE_ID = 79 AND L79.DATE_DEL IS NULL
    ORDER BY V441.LISTVAL_ID -- сначала российское, потом иностранное
    INTO :DATA_SOR, :SER_SOR, :NUMB_SOR, :V$DT2;

    --IF(SER_SOR IS NOT NULL AND CHAR_LENGTH(NUMB_SOR) <> 6) THEN
    --  EXCEPTION DATA_ERROR 'Некорректный формат серии/номера в свидетельстве о рождении ' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$PERSON_ID));

    IF(DATA_SOR IS NOT NULL) THEN
    BEGIN
      DATA_SOR = REPLACE(DATA_SOR, '-', '');
      V$HUSED = V$HUSED + 1;
      IF(V$HUSED = 1) THEN BEGIN HASH_NUM = 3; HASH_GOST2012 = SER_SOR || ' ' || NUMB_SOR || ' ' || DATA_SOR; END
      ELSE IF(V$HUSED = 2) THEN BEGIN HASH_NUM_2 = 3; HASH_GOST2012_2 = SER_SOR || ' ' || NUMB_SOR || ' ' || DATA_SOR; END
      ELSE IF(V$HUSED = 3) THEN BEGIN HASH_NUM_3 = 3; HASH_GOST2012_3 = SER_SOR || ' ' || NUMB_SOR || ' ' || DATA_SOR; END
    END

    RDDM_FIRST = NULL;
    SELECT IIF(V3358.LISTVAL_ID = 2, 'true', 'false'), MAXVALUE(V3358.DATE_MODIFY, :V$DT2)
    FROM VALL V3358
    WHERE V3358.OBJ_ID = :V$PERSON_ID AND V3358.PARAM_ID = 3358 AND V3358.IS_DEL = 0
    INTO :RDDM_FIRST, :V$DT2;
    RDDM_FIRST = TRIM(RDDM_FIRST);

    -- Плановая дата окончания - считаем 15 июля достижения 11 класса
    -- если вдруг не нашлось, ставим текущий учебный год
    V$STAGE = NULL;
    SELECT FIRST 1 LV.COST
    FROM PERSON_MOVEMENTS M
    JOIN LISTVALS LV ON LV.LISTVAL_ID = M.STAGE_ID
    WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :V$PERSON_ID AND M.GROUP_TYPE_ID IN (9, 125, 187)
    ORDER BY M.DATE_OUT DESC NULLS FIRST
    INTO :V$STAGE;

    IF(V$STAGE = 12) THEN V$STAGE = 11; -- для адаптивки 12-й класс делаем 11-м

    IF(V$STAGE IS NULL) THEN EXPECT_END_STUDY = (V$Y + 1) || '-07-01';
    ELSE EXPECT_END_STUDY = (V$Y + 1 + 11 - V$STAGE) || '-07-01';

    IF(I$DT1 IS NULL OR V$DT1 >= I$DT1 OR V$DT2 >= I$DT1) THEN SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_MS_STUDENTS_TRAINING (
    I$DT1 TIMESTAMP,
    I$DT2 TIMESTAMP NOT NULL = CURRENT_TIMESTAMP)
RETURNS (
    ID VARCHAR(40),
    STUDENT_ID VARCHAR(60),
    COLLEGES_ID VARCHAR(40),
    SPECIALITY VARCHAR(400),
    CODE_SPECIALITY VARCHAR(400),
    NUM_COURSO INTEGER,
    ACADEM_YEAR INTEGER,
    COURSO_START_DATE DATE,
    COURSO_END_DATE DATE,
    ATTENDANCE VARCHAR(40),
    REASON_CODE VARCHAR(40),
    DATA_REASON DATE,
    DATA_START_STUDY DATE,
    DATA_END_STUDY DATE,
    DOC_NAME VARCHAR(40),
    DOC_NUMBER VARCHAR(400),
    DATA_DOC DATE,
    QUALIFICATION VARCHAR(400),
    PROGRAM_FOCUSE VARCHAR(400),
    CREATE_DATETIME TIMESTAMP,
    SEND_DATETIME TIMESTAMP)
AS
DECLARE VARIABLE V$SCHOOL_ID BIGINT;
DECLARE VARIABLE V$GY_ID BIGINT;
DECLARE VARIABLE V$Y INTEGER;
DECLARE VARIABLE V$RANGE_FROM DATE;
DECLARE VARIABLE V$STUDENT_ID BIGINT;
DECLARE VARIABLE V$STAGE_ID BIGINT;
DECLARE VARIABLE V$GRADE_ID BIGINT;
DECLARE VARIABLE V$DT1 TIMESTAMP;
DECLARE VARIABLE V$DT2 TIMESTAMP;
DECLARE VARIABLE V$DT3 TIMESTAMP;
DECLARE VARIABLE V$DT4 TIMESTAMP;
DECLARE VARIABLE V$DT5 TIMESTAMP;
DECLARE VARIABLE V$GRADE_TYPE_ID BIGINT;
DECLARE VARIABLE V$REASON BIGINT;
begin

  SEND_DATETIME = I$DT2;

  SELECT FIRST 1 L2.OBJ_ID, V1236.LISTVAL_ID, LV.COST, V9.VAL
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  JOIN VALS V9 ON V9.OBJ_ID = L2.OBJ_ID AND V9.PARAM_ID = 9 AND V9.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$SCHOOL_ID, :V$GY_ID, :V$Y, :COLLEGES_ID;

  V$RANGE_FROM = '31.08.' || (V$Y - 3);

  IF(V$SCHOOL_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Объект ОУ не найден, либо не указан текущий учебный год';

  -- Выбираем всех обучающихся, засветившихся в школе за последние 3 года, но только действующих
  -- только тех у кого есть паспорт
  -- исключаем из выборки профессиональное обучение
  FOR
    SELECT DISTINCT L10.OBJ_ID, V2912.SVAL
    FROM LINKS L10
    JOIN PERSON_MOVEMENTS M ON M.DATE_DEL IS NULL AND M.PERSON_ID = L10.OBJ_ID AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :V$RANGE_FROM)
    JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
    LEFT JOIN VALL V3367 ON V3367.OBJ_ID = M.GROUP_ID AND V3367.PARAM_ID = 3367 AND V3367.IS_DEL = 0
    -- Есть регид
    JOIN VALS V2912 ON V2912.OBJ_ID = L10.OBJ_ID AND V2912.PARAM_ID = 2912 AND V2912.IS_DEL = 0
    WHERE L10.PARENT_TYPE_ID IN (9, 125, 187, 289, 81, 82, 83) AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL -- , 81, 82, 83
    -- Исключаем профобучение
    AND V3367.LISTVAL_ID IS NULL
    AND EXISTS (
      SELECT FIRST 1 1
      FROM LINKS L79
      JOIN VALL V441 ON V441.OBJ_ID = L79.OBJ_ID AND V441.PARAM_ID = 441 AND V441.IS_DEL = 0 AND V441.LISTVAL_ID IN (1368, 1373, 1371)
      WHERE L79.PARENT_ID = L10.OBJ_ID AND L79.OBJ_TYPE_ID = 79 AND L79.DATE_DEL IS NULL
    )
    ORDER BY 1
    INTO :V$STUDENT_ID, :STUDENT_ID
  DO
  BEGIN

    IF(POSITION(':' IN STUDENT_ID) > 0) THEN STUDENT_ID = SUBSTRING(STUDENT_ID FROM 1 FOR POSITION(':' IN STUDENT_ID) - 1);
    STUDENT_ID = REPLACE(STUDENT_ID, '{', '');
    STUDENT_ID = REPLACE(STUDENT_ID, '}', '');
    STUDENT_ID = LOWER(STUDENT_ID);

    -- ID делаем равным id самого обучающегося - все равно это только текущий слепок
    ID = STUDENT_ID;

    -- Название ATTENDANCE выдаем всегда в первозданном виде, оно корректируется в код на стороне сервера
    V$DT3 = NULL;
    ATTENDANCE = NULL;
    SELECT C.VAL, V80.DATE_MODIFY
    FROM VALL V80
    LEFT JOIN LISTVAL_TEXT(V80.LISTVAL_ID) C ON 1 = 1
    WHERE V80.OBJ_ID = :V$STUDENT_ID AND V80.PARAM_ID = 80 AND V80.IS_DEL = 0
    INTO :ATTENDANCE, :V$DT3;

    -- Дата начала обучения - самая старая вообще из всех записей движения
    CREATE_DATETIME = NULL;
    DATA_START_STUDY = NULL;
    SELECT FIRST 1 M.DATE_IN, M.DATE_ADD
    FROM PERSON_MOVEMENTS M
    JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
    WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :V$STUDENT_ID
    ORDER BY 1
    INTO :DATA_START_STUDY, :CREATE_DATETIME;

    -- Где числится прямо сейчас ? Исключаем профобучение
    V$GRADE_ID = NULL;
    V$STAGE_ID = NULL;
    COURSO_START_DATE = NULL;
    DATA_END_STUDY = NULL;
    SELECT FIRST 1 M.DATE_IN, M.DATE_OUT, M.GROUP_ID, G.TYPE_ID, M.STAGE_ID, COALESCE(M.REASON_OUT, M.REASON_IN), M.DATE_IN,
      COALESCE(M.ORDER_NUM_OUT, M.ORDER_NUM_IN), COALESCE(M.ORDER_DATE_OUT, M.ORDER_DATE_IN),
      M.DATE_ADD, M.DATE_MODIFY
    FROM PERSON_MOVEMENTS M
    JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID IN (9, 125, 187, 289)
    LEFT JOIN VALL V3367 ON V3367.OBJ_ID = M.GROUP_ID AND V3367.PARAM_ID = 3367 AND V3367.IS_DEL = 0
    WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :V$STUDENT_ID AND V3367.LISTVAL_ID IS NULL
    ORDER BY 1 DESC
    INTO :COURSO_START_DATE, :COURSO_END_DATE, :V$GRADE_ID, :V$GRADE_TYPE_ID, :V$STAGE_ID, :V$REASON, :DATA_REASON,
      :DOC_NUMBER, :DATA_DOC, :CREATE_DATETIME, :V$DT1;

    IF(DOC_NUMBER IS NULL) THEN DOC_NAME = NULL; ELSE DOC_NAME = 'Приказ';

    -- Если это академический отпуск, надо поднять последнюю группу где был до этого
    -- значит мы все еще числимся, но дату начала и группу надо обновить
    IF(V$GRADE_TYPE_ID = 289) THEN
    BEGIN
      COURSO_END_DATE = NULL;
      SELECT FIRST 1 M.DATE_IN, M.GROUP_ID, M.DATE_ADD
      FROM PERSON_MOVEMENTS M
      JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID IN (9, 125, 187)
      LEFT JOIN VALL V3367 ON V3367.OBJ_ID = M.GROUP_ID AND V3367.PARAM_ID = 3367 AND V3367.IS_DEL = 0
      WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :V$STUDENT_ID AND V3367.LISTVAL_ID IS NULL
      ORDER BY 1 DESC
      INTO :COURSO_START_DATE, :V$GRADE_ID, :CREATE_DATETIME;
    END

    -- Окончание на текущем курсе всегда = глобальное окончание
    DATA_END_STUDY = COURSO_END_DATE;

    -- Учебный год формируем по году движения, при этом август относим к будущему году
    ACADEM_YEAR = EXTRACT(YEAR FROM COURSO_START_DATE);
    IF(EXTRACT(MONTH FROM COURSO_START_DATE) < 8) THEN ACADEM_YEAR = ACADEM_YEAR - 1;

    -- Номер курса берем синтетически
    NUM_COURSO = V$STAGE_ID - 49 + 1;

    V$DT4 = NULL;
    SPECIALITY = NULL;
    SELECT FIRST 1 C.VAL, V.DATE_MODIFY
    FROM VALL V
    JOIN LISTVAL_TEXT(V.LISTVAL_ID) C ON 1 = 1
    WHERE V.OBJ_ID = :V$GRADE_ID AND V.PARAM_ID IN (2821, 2165, 3367) AND V.IS_DEL = 0
    INTO :SPECIALITY, :V$DT4;

    V$DT5 = NULL;
    CODE_SPECIALITY = NULL;
    SELECT FIRST 1 V.VAL, V.DATE_MODIFY
    FROM VALS V
    WHERE V.OBJ_ID = :V$GRADE_ID AND V.PARAM_ID = 2822 AND V.IS_DEL = 0
    INTO :CODE_SPECIALITY, :V$DT5;

    -- Ругаемся только для актуальных групп, а для старых пропускаем выдачу записи
    -- если группы именно СПО нет, то не выдаем
    IF(V$GRADE_ID IS NOT NULL AND COURSO_END_DATE IS NULL) THEN
    BEGIN
      -- IF(V$GRADE_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Для обучаюещегося ' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$STUDENT_ID)) || ' ' || V$STUDENT_ID || ' не удалось идентифицировать текущий учебный коллектив';
      IF(SPECIALITY IS NULL) THEN EXCEPTION DATA_ERROR 'Для группы ' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$GRADE_ID)) || ' ' || V$GRADE_ID || ' не указано наименование специальности, ' ||
        'обучающийся ' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$STUDENT_ID));
      IF(CODE_SPECIALITY IS NULL) THEN EXCEPTION DATA_ERROR 'Для группы ' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$GRADE_ID)) || ' ' || V$GRADE_ID || ' не указан код специальности, ' ||
        'обучающийся ' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$STUDENT_ID));
    END

    -- Формируем поле REASON_CODE
    IF(V$REASON IN (805, 5322)) THEN REASON_CODE = 'start_study'; -- 12788, 5321 ?
    ELSE IF(V$REASON IN (5319)) THEN REASON_CODE = 'academ_vacation';
    ELSE IF(V$REASON IN (812)) THEN REASON_CODE = 'finish_study';
    ELSE IF(V$REASON IN (811, 5316, 5317, 5318)) THEN REASON_CODE = 'expulsion';
    ELSE IF(V$REASON IN (11093)) THEN REASON_CODE = 'death';
    ELSE REASON_CODE = 'transfer';

    IF((I$DT1 IS NULL OR V$DT1 >= I$DT1 OR V$DT2 >= I$DT1 OR V$DT3 >= I$DT1 OR V$DT4 >= I$DT1 OR V$DT5 >= I$DT1)
      AND V$GRADE_ID IS NOT NULL AND V$STAGE_ID IS NOT NULL AND CODE_SPECIALITY IS NOT NULL AND SPECIALITY IS NOT NULL
    )
    THEN
      SUSPEND;

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_MS_STUDENT_CITIZENSHIP (
    I$DT1 TIMESTAMP,
    I$DT2 TIMESTAMP NOT NULL = CURRENT_TIMESTAMP)
RETURNS (
    ID VARCHAR(60),
    STUDENT_ID VARCHAR(60),
    CODE VARCHAR(40),
    NAME VARCHAR(100),
    CREATE_DATETIME TIMESTAMP,
    SEND_DATETIME TIMESTAMP)
AS
DECLARE VARIABLE V$SCHOOL_ID BIGINT;
DECLARE VARIABLE V$GP_ID BIGINT;
DECLARE VARIABLE V$Y INTEGER;
DECLARE VARIABLE V$PERSON_ID BIGINT;
DECLARE VARIABLE V$DT1 TIMESTAMP;
DECLARE VARIABLE V$DT2 TIMESTAMP;
DECLARE VARIABLE V$FY INTEGER;
DECLARE VARIABLE V$FY2 INTEGER;
DECLARE VARIABLE V$ID BIGINT;
begin

  SEND_DATETIME = I$DT2;

  V$FY = EXTRACT(YEAR FROM CURRENT_DATE);
  V$FY2 = V$FY + 1;

  SELECT FIRST 1 L2.OBJ_ID, V1236.LISTVAL_ID, LV.COST
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$SCHOOL_ID, :V$GP_ID, :V$Y;

  FOR
    -- Текущие ученики
    SELECT SID, MAX(OBJ_ID), MAX(DATE_MODIFY)
    FROM (
      SELECT V2912.SVAL SID, L10.OBJ_ID, L10.DATE_MODIFY
      FROM LINKS L2
      JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
      JOIN VALL V43 ON V43.OBJ_ID = L7.OBJ_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0 AND V43.LISTVAL_ID IN (22, 26, 27)
      JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
      JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      JOIN VALS V2912 ON V2912.OBJ_ID = L10.OBJ_ID AND V2912.PARAM_ID = 2912 AND V2912.IS_DEL = 0
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      UNION
      -- Окончившие
      SELECT V2912.SVAL, L10.OBJ_ID, L10.DATE_MODIFY
      FROM LINKS L2
      JOIN LINKS L78 ON L78.PARENT_ID = L2.OBJ_ID AND L78.OBJ_TYPE_ID = 78 AND L78.DATE_DEL IS NULL
      JOIN LINKS L83 ON L83.PARENT_ID = L78.OBJ_ID AND L83.OBJ_TYPE_ID = 83 AND L83.DATE_DEL IS NULL
      JOIN VALI V451 ON V451.OBJ_ID = L83.OBJ_ID AND V451.PARAM_ID = 451 AND V451.IS_DEL = 0 AND (V451.VAL = :V$FY OR V451.VAL = :V$FY2)
      JOIN LINKS L10 ON L10.PARENT_ID = L83.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      JOIN VALS V2912 ON V2912.OBJ_ID = L10.OBJ_ID AND V2912.PARAM_ID = 2912 AND V2912.IS_DEL = 0
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    )
    GROUP BY 1
    ORDER BY 1
    INTO :STUDENT_ID, :V$PERSON_ID, :V$DT1
  DO
  BEGIN
    IF(POSITION(':' IN STUDENT_ID) > 0) THEN STUDENT_ID = SUBSTRING(STUDENT_ID FROM 1 FOR POSITION(':' IN STUDENT_ID) - 1);
    STUDENT_ID = REPLACE(STUDENT_ID, '{', '');
    STUDENT_ID = REPLACE(STUDENT_ID, '}', '');
    STUDENT_ID = LOWER(STUDENT_ID);

    ID = STUDENT_ID;

    CREATE_DATETIME = V$DT1;

    CODE = NULL;
    NAME = NULL;
    SELECT V91.LISTVAL_ID, R.VAL, R.VAL_LONG, V91.DATE_MODIFY
    FROM VALL V91
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V91.LISTVAL_ID
    JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
    WHERE V91.OBJ_ID = :V$PERSON_ID AND V91.PARAM_ID = 91 AND V91.IS_DEL = 0
    INTO :V$ID, :NAME, :CODE, :CREATE_DATETIME;

    IF(CODE = '') THEN CODE = NULL;

    IF(NAME IS NOT NULL AND CODE IS NOT NULL AND (I$DT1 IS NULL OR V$DT1 >= I$DT1 OR V$DT2 >= I$DT1)) THEN SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_MS_SUBJECTS (
    I$DT1 TIMESTAMP,
    I$DT2 TIMESTAMP NOT NULL = current_timestamp)
RETURNS (
    ID VARCHAR(40),
    NAME VARCHAR(400),
    BASE_SUBJ INTEGER,
    CREATE_DATETIME TIMESTAMP,
    SEND_DATETIME TIMESTAMP)
AS
declare variable S varchar(400);
declare variable G bigint;
declare variable M bigint;
BEGIN

  SEND_DATETIME = I$DT2;

  SELECT GEN, MULTIPLIER
  FROM GEN
  INTO :G, :M;

  FOR
    SELECT L51.OBJ_ID, V376.SVAL, L51.DATE_MODIFY
    FROM LINKS L51
    JOIN VALS V376 ON V376.OBJ_ID = L51.OBJ_ID AND V376.PARAM_ID = 376 AND V376.IS_DEL = 0
    WHERE L51.PARENT_ID IN (32771, 32772) AND L51.OBJ_TYPE_ID = 51 AND L51.DATE_DEL IS NULL AND (L51.DATE_MODIFY >= :I$DT1 OR :I$DT1 IS NULL)
      AND (L51.OBJ_ID < 38707 OR L51.OBJ_ID > 38720) -- олимпиады СПб
      AND (L51.OBJ_ID > :M OR :G = 0 OR :G = 100) -- только с региона
    ORDER BY 1
    INTO :ID, :NAME, :CREATE_DATETIME
  DO
  BEGIN
    S = UPPER(NAME);

    IF(ID = 197 OR POSITION('БИОЛОГ' IN S) > 0) THEN BASE_SUBJ = 1; -- биология
    ELSE IF(ID = 3139 OR POSITION('ГЕОГРАФ' IN S) > 0) THEN BASE_SUBJ = 7; -- география
    ELSE IF(ID = 202 OR POSITION('ИЗО' IN S) > 0) THEN BASE_SUBJ = 18; -- ИЗО
    ELSE IF(ID = 5518 OR ID = 191 OR ID = 32905 OR POSITION('ИНФОРМАТИКА' IN S) > 0) THEN BASE_SUBJ = 24; -- Информатика
    ELSE IF(ID = 174 OR POSITION('ИСТОРИЯ' IN S) > 0) THEN BASE_SUBJ = 25; -- История
    ELSE IF(ID = 187 OR POSITION('ЛИТЕРАТУР' IN S) > 0) THEN BASE_SUBJ = 26; -- Литература
    ELSE IF(ID = 190 OR POSITION('МАТЕМАТИКА' IN S) > 0) THEN BASE_SUBJ = 27; -- Математика базовый уровень
    ELSE IF(ID = 203 OR POSITION('МУЗЫК' IN S) > 0) THEN BASE_SUBJ = 28; -- Музыка
    ELSE IF(ID = 194 OR POSITION('ОБЩЕСТВОЗНА' IN S) > 0) THEN BASE_SUBJ = 29; -- Обществознание
    ELSE IF(ID = 206 OR ID = 38700 OR POSITION('ЗАЩИТЫ' IN S) > 0) THEN BASE_SUBJ = 30; -- ОБЗР
    ELSE IF(ID = 5532 OR POSITION('ОДНКНР' IN S) > 0 OR POSITION('НАРОДОВ' IN S) > 0) THEN BASE_SUBJ = 31; -- ОДНКНР
    ELSE IF(ID = 185 OR POSITION('РУССКИЙ' IN S) > 0) THEN BASE_SUBJ = 137; -- Русский
    ELSE IF(ID = 200 OR ID = 201 OR ID = 38703 OR POSITION('ТРУД' IN S) > 0 OR POSITION('ТЕХНОЛОГИЯ' IN S) > 0) THEN BASE_SUBJ = 138; -- Труд, технология
    ELSE IF(ID = 198 OR POSITION('ФИЗИКА' IN S) > 0) THEN BASE_SUBJ = 139; -- Физика
    ELSE IF(ID = 205 OR POSITION('ФИЗИЧЕСКАЯ' IN S) > 0) THEN BASE_SUBJ = 139; -- Физра
    ELSE IF(ID = 199 OR POSITION('ХИМИ' IN S) > 0) THEN BASE_SUBJ = 139; -- Химия
    ELSE IF(POSITION('АНГЛИЙ' IN S) > 0) THEN BASE_SUBJ = 19; -- Английский
    ELSE IF(POSITION('ИСПАНСК' IN S) > 0) THEN BASE_SUBJ = 20; -- Испанский
    ELSE IF(POSITION('КИТАЙСК' IN S) > 0) THEN BASE_SUBJ = 21; -- Китайский
    ELSE IF(POSITION('НЕМЕЦК' IN S) > 0) THEN BASE_SUBJ = 22; -- Немецкий
    ELSE IF(POSITION('ФРАНЦУЗСК' IN S) > 0) THEN BASE_SUBJ = 23; -- Французский
    ELSE BASE_SUBJ = 0;

    SUSPEND;
  END

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_MS_SUBJECT_PLAN (
    I$DT1 TIMESTAMP,
    I$DT2 TIMESTAMP NOT NULL = current_timestamp)
RETURNS (
    ID VARCHAR(40),
    GRADE INTEGER,
    SUBJECT_ID VARCHAR(40),
    SCHOOL_ID VARCHAR(40),
    CLASS_YEAR INTEGER,
    CREATE_DATETIME TIMESTAMP,
    SEND_DATETIME TIMESTAMP)
AS
declare variable V$SCHOOL_ID bigint;
declare variable V$GP_ID bigint;
declare variable V$Y integer;
declare variable V$DT1 timestamp;
begin

  SEND_DATETIME = I$DT2;

  SELECT FIRST 1 L2.OBJ_ID, V1236.LISTVAL_ID, LV.COST, V9.VAL
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  JOIN VALS V9 ON V9.OBJ_ID = L2.OBJ_ID AND V9.PARAM_ID = 9 AND V9.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$SCHOOL_ID, :V$GP_ID, :V$Y, :SCHOOL_ID;

  CLASS_YEAR = V$Y;

  FOR
    SELECT J.OBJ_ID, J.SUBJECT_ID, LV.COST, J.DATE_MODIFY
    FROM CJ2_JOURNAL J
    JOIN LISTVALS LV ON LV.LISTVAL_ID = J.STAGE_INDEX
    WHERE J.DATE_DEL IS NULL AND J.JOURNAL_TYPE = 0 AND J.YEAR_ID = :V$GP_ID
    ORDER BY 1
    INTO :ID, :SUBJECT_ID, :GRADE, :V$DT1
  DO
  BEGIN
    CREATE_DATETIME = V$DT1;

    IF(I$DT1 IS NULL OR V$DT1 >= I$DT1) THEN
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_MS_TEACHERS (
    I$DT1 TIMESTAMP,
    I$DT2 TIMESTAMP NOT NULL = CURRENT_TIMESTAMP)
RETURNS (
    ID VARCHAR(60),
    OID VARCHAR(40),
    AUTH_LINK VARCHAR(200),
    VK_ID VARCHAR(40),
    FIRSTNAME VARCHAR(100),
    LASTNAME VARCHAR(100),
    PATRONYMIC VARCHAR(100),
    HASH_GOST2012 VARCHAR(200),
    HASH_NUM INTEGER,
    BIRTHDATE VARCHAR(10),
    E_MAIL VARCHAR(100),
    GENDER_CODE VARCHAR(10),
    GENDER_VALUE INTEGER,
    GENDER_DESCRIPTION VARCHAR(20),
    ACTIVE VARCHAR(10),
    START_DATETIME TIMESTAMP,
    END_DATETIME TIMESTAMP,
    STATUS_CODE VARCHAR(20),
    STATUS_VALUE INTEGER,
    STATUS_DESCRIPTION VARCHAR(100),
    REASON_CODE VARCHAR(20),
    REASON_VALUE INTEGER,
    REASON_DESCRIPTION VARCHAR(100),
    ERN_ID VARCHAR(40),
    CREATE_DATETIME TIMESTAMP,
    SEND_DATETIME TIMESTAMP,
    ORGN SMALLINT)
AS
DECLARE VARIABLE V$SCHOOL_ID BIGINT;
DECLARE VARIABLE V$GP_ID BIGINT;
DECLARE VARIABLE V$Y INTEGER;
DECLARE VARIABLE V$PERSON_ID BIGINT;
DECLARE VARIABLE V$HUSED INTEGER;
DECLARE VARIABLE V$STAGE INTEGER;
DECLARE VARIABLE V$DT1 TIMESTAMP;
DECLARE VARIABLE V$DT2 TIMESTAMP;
DECLARE VARIABLE V$DT3 TIMESTAMP;
DECLARE VARIABLE V$FY INTEGER;
DECLARE VARIABLE V$FY2 INTEGER;
DECLARE VARIABLE SNILS VARCHAR(100);
DECLARE VARIABLE DATA_PASSPORT VARCHAR(100);
DECLARE VARIABLE NUMB_PASSPORT VARCHAR(400);
DECLARE VARIABLE SER_PASSPORT VARCHAR(400);
DECLARE VARIABLE V$YDATE DATE;
begin

  SEND_DATETIME = I$DT2;
  AUTH_LINK = 'login';
  -- Коды для reason формируются на сервере через полный реестр движения
  -- а пока вообще не формируются, поскольку не являются обязательными
  /*REASON_CODE = 'start_work';
  REASON_VALUE = 1;
  REASON_DESCRIPTION = 'Начало работы';*/

  -- START_DATETIME, END_DATETIME и REASON пока вообще не грузим

  V$FY = EXTRACT(YEAR FROM CURRENT_DATE);
  V$FY2 = V$FY + 1;

  SELECT FIRST 1 L2.OBJ_ID, V1236.LISTVAL_ID, LV.COST
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$SCHOOL_ID, :V$GP_ID, :V$Y;

  V$YDATE = '30.08.' || V$Y;

  FOR
    -- Действующие
    SELECT SID, MAX(OBJ_ID), MAX(DATE_MODIFY)
    FROM (
      SELECT V2915.SVAL SID, L14.OBJ_ID, L14.DATE_MODIFY
      FROM LINKS L2
      JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
      JOIN VALS V2915 ON V2915.OBJ_ID = L14.OBJ_ID AND V2915.PARAM_ID = 2915 AND V2915.IS_DEL = 0
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      UNION
      -- Уволенные не ранее даты начала текущего учебного года
      SELECT V2915.SVAL, L14.OBJ_ID, L14.DATE_MODIFY
      FROM LINKS L2
      JOIN LINKS L84 ON L84.PARENT_ID = L2.OBJ_ID AND L84.OBJ_TYPE_ID = 84 AND L84.DATE_DEL IS NULL
      JOIN LINKS L14 ON L14.PARENT_ID = L84.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
      JOIN VALS V2915 ON V2915.OBJ_ID = L14.OBJ_ID AND V2915.PARAM_ID = 2915 AND V2915.IS_DEL = 0
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND EXISTS(
        SELECT FIRST 1 1
        FROM LINKS L15
        LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
        WHERE L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL AND (V74.VAL IS NULL OR V74.VAL >= :V$YDATE)
      )
    )
    GROUP BY 1
    ORDER BY 1
    INTO :ID, :V$PERSON_ID, :V$DT1
  DO
  BEGIN
    IF(POSITION(':' IN ID) > 0) THEN ID = SUBSTRING(ID FROM 1 FOR POSITION(':' IN ID) - 1);
    ID = REPLACE(ID, '{', '');
    ID = REPLACE(ID, '}', '');
    ID = LOWER(ID);

    -- 0 = действующий, 1 = уволенный
    ORGN = 0;
    SELECT FIRST 1 1
    FROM LINKS LP84
    WHERE LP84.OBJ_ID = :V$PERSON_ID AND LP84.PARENT_TYPE_ID = 84 AND LP84.DATE_DEL IS NULL
    INTO :ORGN;

    IF(ORGN = 0) THEN
    BEGIN
      "ACTIVE" = 'true';
      STATUS_CODE = 'active';
      STATUS_VALUE = 1;
      STATUS_DESCRIPTION = 'Действует';
    END
    ELSE
    BEGIN
      "ACTIVE" = 'false';
      STATUS_CODE = 'active';
      STATUS_VALUE = 1;
      STATUS_DESCRIPTION = 'Действует';
    END

    -- Дата создания
    SELECT FIRST 1 LP.DATE_INS
    FROM LINKS LP
    WHERE LP.DATE_DEL IS NULL AND LP.OBJ_ID = :V$PERSON_ID AND LP.PARENT_TYPE_ID IN (2, 211, 84)
    ORDER BY 1
    INTO :CREATE_DATETIME;

    LASTNAME = NULL;
    FIRSTNAME = NULL;
    PATRONYMIC = NULL;
    BIRTHDATE = NULL;
    GENDER_VALUE = NULL;
    V$HUSED = 0;
    V$DT2 = NULL;

    SELECT V59.VAL, MAXVALUE(V59.DATE_MODIFY, :V$DT2)
    FROM VALS V59
    WHERE V59.OBJ_ID = :V$PERSON_ID AND V59.PARAM_ID = 59 AND V59.IS_DEL = 0
    INTO :LASTNAME, :V$DT2;

    SELECT V60.VAL, MAXVALUE(V60.DATE_MODIFY, :V$DT2)
    FROM VALS V60
    WHERE V60.OBJ_ID = :V$PERSON_ID AND V60.PARAM_ID = 60 AND V60.IS_DEL = 0
    INTO :FIRSTNAME, :V$DT2;

    SELECT V61.VAL, MAXVALUE(V61.DATE_MODIFY, :V$DT2)
    FROM VALS V61
    WHERE V61.OBJ_ID = :V$PERSON_ID AND V61.PARAM_ID = 61 AND V61.IS_DEL = 0
    INTO :PATRONYMIC, :V$DT2;

    SELECT D.VAL, MAXVALUE(V241.DATE_MODIFY, :V$DT2)
    FROM VALD V241
    LEFT JOIN DATE2ISO(V241.VAL, 0) D ON 1 = 1
    WHERE V241.OBJ_ID = :V$PERSON_ID AND V241.PARAM_ID = 241 AND V241.IS_DEL = 0
    INTO :BIRTHDATE, :V$DT2;

    SELECT IIF(V239.LISTVAL_ID = 182, 2, 1), MAXVALUE(V239.DATE_MODIFY, :V$DT2)
    FROM VALL V239
    WHERE V239.OBJ_ID = :V$PERSON_ID AND V239.PARAM_ID = 239 AND V239.IS_DEL = 0
    INTO :GENDER_VALUE, :V$DT2;

    IF(GENDER_VALUE = 1) THEN
    BEGIN
      GENDER_CODE = 'male';
      GENDER_DESCRIPTION = 'мужской';
    END
    IF(GENDER_VALUE = 2) THEN
    BEGIN
      GENDER_CODE = 'female';
      GENDER_DESCRIPTION = 'женский';
    END

    IF(LASTNAME IS NULL OR FIRSTNAME IS NULL OR BIRTHDATE IS NULL OR GENDER_VALUE IS NULL) THEN
      EXCEPTION DATA_ERROR 'Неполные данные о сотруднике (не указаны ФИО, дата рождения или пол) ' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$PERSON_ID));

    VK_ID = NULL;
    SELECT V3355.VAL, MAXVALUE(V3355.DATE_MODIFY, :V$DT2)
    FROM VALS V3355
    WHERE V3355.OBJ_ID = :V$PERSON_ID AND V3355.PARAM_ID = 3355 AND V3355.IS_DEL = 0
    INTO :VK_ID, :V$DT2;

    E_MAIL = NULL;
    SELECT V1180.VAL, MAXVALUE(V1180.DATE_MODIFY, :V$DT2)
    FROM VALS V1180
    WHERE V1180.OBJ_ID = :V$PERSON_ID AND V1180.PARAM_ID = 1180 AND V1180.IS_DEL = 0
    INTO :E_MAIL, :V$DT2;

    SNILS = NULL;
    SELECT REPLACE(REPLACE(V2455.VAL, ' ', ''), '-', ''), MAXVALUE(V2455.DATE_MODIFY, :V$DT2)
    FROM VALS V2455
    WHERE V2455.OBJ_ID = :V$PERSON_ID AND V2455.PARAM_ID = 2455 AND V2455.IS_DEL = 0
    INTO :SNILS, :V$DT2;

    IF(SNILS IS NOT NULL) THEN
    BEGIN
      V$HUSED = V$HUSED + 1;
      IF(V$HUSED = 1) THEN BEGIN HASH_NUM = 1; HASH_GOST2012 = SNILS; END
    END

    -- Данные паспорта
    DATA_PASSPORT = NULL;
    NUMB_PASSPORT = NULL;
    SER_PASSPORT = NULL;
    SELECT FIRST 1 D.VAL, V442.VAL, V559.VAL, MAXVALUE(L79.DATE_MODIFY, V441.DATE_MODIFY, V614.DATE_MODIFY, V560.DATE_MODIFY, V442.DATE_MODIFY, V559.DATE_MODIFY, :V$DT2)
    FROM LINKS L79
    JOIN VALL V441 ON V441.OBJ_ID = L79.OBJ_ID AND V441.PARAM_ID = 441 AND V441.IS_DEL = 0 AND V441.LISTVAL_ID IN (1368, 1369)
    JOIN VALL V614 ON V614.OBJ_ID = L79.OBJ_ID AND V614.PARAM_ID = 614 AND V614.IS_DEL = 0 AND V614.LISTVAL_ID = 1982
    JOIN VALD V560 ON V560.OBJ_ID = L79.OBJ_ID AND V560.PARAM_ID = 560 AND V560.IS_DEL = 0
    LEFT JOIN DATE2ISO(V560.VAL, 0) D ON 1 = 1
    JOIN VALS V442 ON V442.OBJ_ID = L79.OBJ_ID AND V442.PARAM_ID = 442 AND V442.IS_DEL = 0
    JOIN VALS V559 ON V559.OBJ_ID = L79.OBJ_ID AND V559.PARAM_ID = 559 AND V559.IS_DEL = 0
    WHERE L79.PARENT_ID = :V$PERSON_ID AND L79.OBJ_TYPE_ID = 79 AND L79.DATE_DEL IS NULL
    ORDER BY V441.LISTVAL_ID
    INTO :DATA_PASSPORT, :SER_PASSPORT, :NUMB_PASSPORT, :V$DT2;

    IF(CHAR_LENGTH(SER_PASSPORT) > 50 OR CHAR_LENGTH(NUMB_PASSPORT) > 50) THEN EXCEPTION DATA_ERROR 'Неверно внесены серия или номер документа, идентифицирующего личность сотрудника';

    IF(DATA_PASSPORT IS NOT NULL) THEN
    BEGIN
      V$HUSED = V$HUSED + 1;
      IF(V$HUSED = 1) THEN BEGIN HASH_NUM = 2; HASH_GOST2012 = SER_PASSPORT || ' ' || NUMB_PASSPORT; END
    END

    IF(I$DT1 IS NULL OR V$DT1 >= I$DT1 OR V$DT2 >= I$DT1 OR V$DT3 >= I$DT1) THEN SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_MS_TEACHERS_DOCUMENTS (
    I$DT1 TIMESTAMP,
    I$DT2 TIMESTAMP NOT NULL = current_timestamp)
RETURNS (
    TEACHER_ID VARCHAR(60),
    DOCUMENT_ID VARCHAR(60),
    CREATE_DATETIME TIMESTAMP,
    SEND_DATETIME TIMESTAMP)
AS
declare variable V$SCHOOL_ID bigint;
declare variable V$GP_ID bigint;
declare variable V$Y integer;
declare variable V$DT1 timestamp;
declare variable V$DT2 timestamp;
declare variable V$PERSON_ID bigint;
declare variable SID varchar(100);
declare variable V$YDATE date;
begin

  SEND_DATETIME = I$DT2;

  SELECT FIRST 1 L2.OBJ_ID, V1236.LISTVAL_ID, LV.COST
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  JOIN VALS V9 ON V9.OBJ_ID = L2.OBJ_ID AND V9.PARAM_ID = 9 AND V9.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$SCHOOL_ID, :V$GP_ID, :V$Y;

  V$YDATE = '30.08.' || V$Y;

  -- Выгружаем только действующие документы, и только учителей (образование, повышение квалификации)
  -- с родителями TODO
  FOR
    -- Действующие
    SELECT SID, MAX(OBJ_ID), MAX(DATE_MODIFY)
    FROM (
      SELECT V2915.SVAL SID, L14.OBJ_ID, L14.DATE_MODIFY
      FROM LINKS L2
      JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
      JOIN VALS V2915 ON V2915.OBJ_ID = L14.OBJ_ID AND V2915.PARAM_ID = 2915 AND V2915.IS_DEL = 0
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      UNION
      -- Уволенные не ранее даты начала текущего учебного года
      SELECT V2915.SVAL, L14.OBJ_ID, L14.DATE_MODIFY
      FROM LINKS L2
      JOIN LINKS L84 ON L84.PARENT_ID = L2.OBJ_ID AND L84.OBJ_TYPE_ID = 84 AND L84.DATE_DEL IS NULL
      JOIN LINKS L14 ON L14.PARENT_ID = L84.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
      JOIN VALS V2915 ON V2915.OBJ_ID = L14.OBJ_ID AND V2915.PARAM_ID = 2915 AND V2915.IS_DEL = 0
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND EXISTS(
        SELECT FIRST 1 1
        FROM LINKS L15
        LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
        WHERE L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL AND (V74.VAL IS NULL OR V74.VAL >= :V$YDATE)
      )
    )
    GROUP BY 1
    ORDER BY 1
    INTO :SID, :V$PERSON_ID, :V$DT1
  DO
  BEGIN
    IF(POSITION(':' IN SID) > 0) THEN SID = SUBSTRING(SID FROM 1 FOR POSITION(':' IN SID) - 1);
    SID = REPLACE(SID, '{', '');
    SID = REPLACE(SID, '}', '');
    TEACHER_ID = LOWER(SID);

    FOR
      SELECT L33.OBJ_ID, L33.DATE_INS,
        MAXVALUE(L33.DATE_MODIFY, V287.DATE_MODIFY, V288.DATE_MODIFY, V290.DATE_MODIFY, V285.DATE_MODIFY)
      FROM LINKS L33
      LEFT JOIN VALD V290 ON V290.OBJ_ID = L33.OBJ_ID AND V290.PARAM_ID IN (290, 310) AND V290.IS_DEL = 0
      LEFT JOIN VALS V288 ON V288.OBJ_ID = L33.OBJ_ID AND V288.PARAM_ID IN (288, 308) AND V288.IS_DEL = 0
      LEFT JOIN VALS V287 ON V287.OBJ_ID = L33.OBJ_ID AND V287.PARAM_ID IN (287, 309) AND V287.IS_DEL = 0
      JOIN VALS V285 ON V285.OBJ_ID = L33.OBJ_ID AND V285.PARAM_ID IN (285, 304) AND V285.IS_DEL = 0
      WHERE L33.PARENT_ID = :V$PERSON_ID AND L33.OBJ_TYPE_ID IN (33, 36) AND L33.DATE_DEL IS NULL
        AND (V287.VAL IS NOT NULL OR V288.VAL IS NOT NULL OR V290.VAL IS NOT NULL)
      INTO :DOCUMENT_ID, :CREATE_DATETIME, :V$DT2
    DO
    BEGIN
      IF(I$DT1 IS NULL OR V$DT1 >= I$DT1 OR V$DT2 >= I$DT1) THEN SUSPEND;
    END
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_MS_TEACHERS_GROUPS (
    I$DT1 TIMESTAMP,
    I$DT2 TIMESTAMP NOT NULL = CURRENT_TIMESTAMP)
RETURNS (
    TEACHER_ID VARCHAR(60),
    GROUP_ID VARCHAR(60),
    CREATE_DATETIME TIMESTAMP,
    SEND_DATETIME TIMESTAMP)
AS
DECLARE VARIABLE V$SCHOOL_ID BIGINT;
DECLARE VARIABLE V$GP_ID BIGINT;
DECLARE VARIABLE V$Y INTEGER;
DECLARE VARIABLE V$DT1 TIMESTAMP;
DECLARE VARIABLE V$DT2 TIMESTAMP;
DECLARE VARIABLE V$DT3 TIMESTAMP;
DECLARE VARIABLE V$GROUP_ID BIGINT;
begin

  SEND_DATETIME = I$DT2;

  SELECT FIRST 1 L2.OBJ_ID, V1236.LISTVAL_ID, LV.COST
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  JOIN VALS V9 ON V9.OBJ_ID = L2.OBJ_ID AND V9.PARAM_ID = 9 AND V9.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$SCHOOL_ID, :V$GP_ID, :V$Y;

  FOR
    SELECT J.GRADE_ID, V2915.VAL, MAXVALUE(J.DATE_MODIFY, V2915.DATE_MODIFY)
    FROM CJ2_JOURNAL J
    JOIN VALS V2915 ON V2915.OBJ_ID = J.TEACHER_ID AND V2915.PARAM_ID = 2915 AND V2915.IS_DEL = 0
    JOIN LISTVALS LV ON LV.LISTVAL_ID = J.STAGE_INDEX AND LV.PARENT_ID IN (2141, 12941)
    WHERE J.DATE_DEL IS NULL AND J.JOURNAL_TYPE = 0 AND J.YEAR_ID = :V$GP_ID AND J.GRADE_TYPE_ID = 179
    INTO :V$GROUP_ID, :TEACHER_ID, :V$DT1
  DO
  BEGIN
    CREATE_DATETIME = V$DT1;
    GROUP_ID = V$GROUP_ID || ':' || V$Y;

    IF(POSITION(':' IN TEACHER_ID) > 0) THEN TEACHER_ID = SUBSTRING(TEACHER_ID FROM 1 FOR POSITION(':' IN TEACHER_ID) - 1);
    TEACHER_ID = REPLACE(TEACHER_ID, '{', '');
    TEACHER_ID = REPLACE(TEACHER_ID, '}', '');
    TEACHER_ID = LOWER(TEACHER_ID);

    IF(I$DT1 IS NULL OR V$DT1 >= I$DT1 OR V$DT2 >= I$DT1) THEN
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_MS_TEACHER_CITIZENSHIP (
    I$DT1 TIMESTAMP,
    I$DT2 TIMESTAMP NOT NULL = current_timestamp)
RETURNS (
    ID VARCHAR(60),
    TEACHER_ID VARCHAR(60),
    CODE VARCHAR(40),
    NAME VARCHAR(100),
    CREATE_DATETIME TIMESTAMP,
    SEND_DATETIME TIMESTAMP)
AS
declare variable V$SCHOOL_ID bigint;
declare variable V$GP_ID bigint;
declare variable V$Y integer;
declare variable V$PERSON_ID bigint;
declare variable V$DT1 timestamp;
declare variable V$DT2 timestamp;
declare variable V$FY integer;
declare variable V$FY2 integer;
declare variable V$ID bigint;
declare variable V$YDATE date;
begin

  SEND_DATETIME = I$DT2;

  V$FY = EXTRACT(YEAR FROM CURRENT_DATE);
  V$FY2 = V$FY + 1;

  SELECT FIRST 1 L2.OBJ_ID, V1236.LISTVAL_ID, LV.COST
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$SCHOOL_ID, :V$GP_ID, :V$Y;

  V$YDATE = '30.08.' || V$Y;

  FOR
    -- Действующие
    SELECT SID, MAX(OBJ_ID), MAX(DATE_MODIFY)
    FROM (
      SELECT V2915.SVAL SID, L14.OBJ_ID, L14.DATE_MODIFY
      FROM LINKS L2
      JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
      JOIN VALS V2915 ON V2915.OBJ_ID = L14.OBJ_ID AND V2915.PARAM_ID = 2915 AND V2915.IS_DEL = 0
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      UNION
      -- Уволенные не ранее даты начала текущего учебного года
      SELECT V2915.SVAL, L14.OBJ_ID, L14.DATE_MODIFY
      FROM LINKS L2
      JOIN LINKS L84 ON L84.PARENT_ID = L2.OBJ_ID AND L84.OBJ_TYPE_ID = 84 AND L84.DATE_DEL IS NULL
      JOIN LINKS L14 ON L14.PARENT_ID = L84.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
      JOIN VALS V2915 ON V2915.OBJ_ID = L14.OBJ_ID AND V2915.PARAM_ID = 2915 AND V2915.IS_DEL = 0
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND EXISTS(
        SELECT FIRST 1 1
        FROM LINKS L15
        LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
        WHERE L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL AND (V74.VAL IS NULL OR V74.VAL >= :V$YDATE)
      )
    )
    GROUP BY 1
    ORDER BY 1
    INTO :TEACHER_ID, :V$PERSON_ID, :V$DT1
  DO
  BEGIN
    IF(POSITION(':' IN TEACHER_ID) > 0) THEN TEACHER_ID = SUBSTRING(TEACHER_ID FROM 1 FOR POSITION(':' IN TEACHER_ID) - 1);
    TEACHER_ID = REPLACE(TEACHER_ID, '{', '');
    TEACHER_ID = REPLACE(TEACHER_ID, '}', '');
    TEACHER_ID = LOWER(TEACHER_ID);

    ID = TEACHER_ID;

    -- Специально, если вдруг в VAL поле пустое
    CREATE_DATETIME = V$DT1;

    CODE = NULL;
    NAME = NULL;
    SELECT V243.LISTVAL_ID, R.VAL, R.VAL_LONG, V243.DATE_MODIFY
    FROM VALL V243
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V243.LISTVAL_ID
    JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
    WHERE V243.OBJ_ID = :V$PERSON_ID AND V243.PARAM_ID = 243 AND V243.IS_DEL = 0
    INTO :V$ID, :NAME, :CODE, :CREATE_DATETIME;

    IF(CODE = '') THEN CODE = NULL;

    IF(NAME IS NOT NULL AND CODE IS NOT NULL AND (I$DT1 IS NULL OR V$DT1 >= I$DT1 OR V$DT2 >= I$DT1)) THEN SUSPEND;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_MS_TEACHER_ROLE (
    I$DT1 TIMESTAMP,
    I$DT2 TIMESTAMP NOT NULL = current_timestamp)
RETURNS (
    ID VARCHAR(60),
    TEACHER_ID VARCHAR(60),
    SCHOOL_ID VARCHAR(60),
    CODE VARCHAR(100),
    NAME VARCHAR(1000),
    EDU_LOCATION_ID VARCHAR(60),
    START_DATETIME TIMESTAMP,
    END_DATETIME TIMESTAMP,
    FTE VARCHAR(20),
    EMPLOYMENT INTEGER,
    STATUS_CODE VARCHAR(20),
    STATUS_VALUE INTEGER,
    STATUS_DESCRIPTION VARCHAR(100),
    REASON_CODE VARCHAR(20),
    REASON_VALUE INTEGER,
    REASON_DESCRIPTION VARCHAR(100),
    CREATE_DATETIME TIMESTAMP,
    SEND_DATETIME TIMESTAMP)
AS
declare variable V$SCHOOL_ID bigint;
declare variable V$GP_ID bigint;
declare variable V$Y integer;
declare variable V$DT1 timestamp;
declare variable V$DT2 timestamp;
declare variable V$DT3 timestamp;
declare variable V$PERSON_ID bigint;
declare variable V$YDATE date;
declare variable V$JOB bigint;
declare variable V$JOB_GROUP bigint;
declare variable V$JOB_SUBGROUP bigint;
declare variable ND timestamp;
begin

  SEND_DATETIME = I$DT2;

  SELECT FIRST 1 L2.OBJ_ID, V1236.LISTVAL_ID, LV.COST, V9.VAL
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  JOIN VALS V9 ON V9.OBJ_ID = L2.OBJ_ID AND V9.PARAM_ID = 9 AND V9.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$SCHOOL_ID, :V$GP_ID, :V$Y, :SCHOOL_ID;

  V$YDATE = '30.08.' || V$Y;
  ND = '01.01.2023';

  SELECT FIRST 1 L16.OBJ_ID
  FROM LINKS L73
  JOIN LINKS L16 ON L16.PARENT_ID = L73.OBJ_ID AND L16.OBJ_TYPE_ID = 16 AND L16.DATE_DEL IS NULL
  JOIN VALL V485 ON V485.OBJ_ID = L16.OBJ_ID AND V485.PARAM_ID = 485 AND V485.IS_DEL = 0 AND V485.LISTVAL_ID = 1093
  -- Адрес должен быть заполнен с указанием кода ФИАС
  JOIN VALA V420 ON V420.OBJ_ID = L16.OBJ_ID AND V420.PARAM_ID = 420 AND V420.IS_DEL = 0 AND V420.FIAS_UID IS NOT NULL
  -- Дата завершения эксплуатации
  LEFT JOIN VALD V3164 ON V3164.OBJ_ID = L16.OBJ_ID AND V3164.PARAM_ID = 3164 AND V3164.IS_DEL = 0
  WHERE L73.PARENT_ID = :V$SCHOOL_ID AND L73.OBJ_TYPE_ID = 73 AND L73.DATE_DEL IS NULL AND V3164.VAL IS NULL
  ORDER BY L16.OBJ_ID
  INTO :EDU_LOCATION_ID;

  IF(EDU_LOCATION_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Требуется внести главное здание ОУ и указать обязательные атрибуты, включая адрес';

  FOR
    -- Действующие
    SELECT SID, MAX(OBJ_ID), MAX(DATE_MODIFY)
    FROM (
      SELECT V2915.SVAL SID, L14.OBJ_ID, L14.DATE_MODIFY
      FROM LINKS L2
      JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
      JOIN VALS V2915 ON V2915.OBJ_ID = L14.OBJ_ID AND V2915.PARAM_ID = 2915 AND V2915.IS_DEL = 0
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      UNION
      -- Уволенные не ранее даты начала текущего учебного года
      SELECT V2915.SVAL, L14.OBJ_ID, L14.DATE_MODIFY
      FROM LINKS L2
      JOIN LINKS L84 ON L84.PARENT_ID = L2.OBJ_ID AND L84.OBJ_TYPE_ID = 84 AND L84.DATE_DEL IS NULL
      JOIN LINKS L14 ON L14.PARENT_ID = L84.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
      JOIN VALS V2915 ON V2915.OBJ_ID = L14.OBJ_ID AND V2915.PARAM_ID = 2915 AND V2915.IS_DEL = 0
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND EXISTS(
        SELECT FIRST 1 1
        FROM LINKS L15
        LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
        WHERE L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL AND (V74.VAL IS NULL OR V74.VAL >= :V$YDATE)
      )
    )
    GROUP BY 1
    ORDER BY 1
    INTO :TEACHER_ID, :V$PERSON_ID, :V$DT1
  DO
  BEGIN
    IF(POSITION(':' IN TEACHER_ID) > 0) THEN TEACHER_ID = SUBSTRING(TEACHER_ID FROM 1 FOR POSITION(':' IN TEACHER_ID) - 1);
    TEACHER_ID = REPLACE(TEACHER_ID, '{', '');
    TEACHER_ID = REPLACE(TEACHER_ID, '}', '');
    TEACHER_ID = LOWER(TEACHER_ID);

    -- Роли выгружаем только для педагогических сотрудников

    FOR
      SELECT L15.OBJ_ID, L15.DATE_INS, V73.VAL, V74.VAL, IIF(V72.LISTVAL_ID = 934, 1, 2), V63.LISTVAL_ID, V64.LISTVAL_ID, V58.LISTVAL_ID,
        MAXVALUE(COALESCE(L15.DATE_MODIFY, :ND), COALESCE(V73.DATE_MODIFY, :ND), COALESCE(V74.DATE_MODIFY, :ND),
          COALESCE(V72.DATE_MODIFY, :ND), COALESCE(V63.DATE_MODIFY, :ND))
      FROM LINKS L15
      JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
      JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0
      LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
      JOIN VALS V66 ON V66.OBJ_ID = LP13.PARENT_ID AND V66.PARAM_ID = 66 AND V66.IS_DEL = 0
      JOIN VALL V72 ON V72.OBJ_ID = L15.OBJ_ID AND V72.PARAM_ID = 72 AND V72.IS_DEL = 0
      JOIN VALL V63 ON V63.OBJ_ID = LP13.PARENT_ID AND V63.PARAM_ID = 63 AND V63.IS_DEL = 0 -- группа должностей
      JOIN VALL V64 ON V64.OBJ_ID = LP13.PARENT_ID AND V64.PARAM_ID = 64 AND V64.IS_DEL = 0 -- подгруппа должностей
      JOIN VALL V58 ON V58.OBJ_ID = LP13.PARENT_ID AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0 -- сама должность
      WHERE L15.PARENT_ID = :V$PERSON_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
        -- исключаем финансовые и вспомогательные должности 2 уровня
        AND V58.LISTVAL_ID NOT IN (69, 86, 95, 141, 3300, 11095)
        -- исключаем подгруппы рабочих, служащих, персонал
        AND V64.LISTVAL_ID NOT IN (1313, 1323, 1257)
      INTO :ID, :CREATE_DATETIME, :START_DATETIME, :END_DATETIME, :EMPLOYMENT, :V$JOB_GROUP, :V$JOB_SUBGROUP, :V$JOB,
        :V$DT2
    DO
    BEGIN
      IF(END_DATETIME IS NULL) THEN
      BEGIN
        STATUS_VALUE = 1;
        STATUS_CODE = 'active';
        STATUS_DESCRIPTION = 'Действует';
      END
      ELSE
      BEGIN
        STATUS_VALUE = 2;
        STATUS_CODE = 'retired';
        STATUS_DESCRIPTION = 'Прекращена';
      END

      -- Руководители 1 и 2 уровней
      IF(V$JOB_SUBGROUP IN (56, 113)) THEN
      BEGIN
        CODE = '4';
        NAME = 'head_of_teaching_department';
      END
      ELSE IF(V$JOB_SUBGROUP IN (125)) THEN
      BEGIN
        CODE = '2';
        NAME = 'educator';
      END
      ELSE
      BEGIN
        CODE = '1';
        NAME = 'teacher';
      END
      -- Роли классных руководителей у нас вообще нет
      -- Возможно ее стоит выдавать как дополнительную роль к основной роли
      -- 3 class_chief

      IF(I$DT1 IS NULL OR V$DT1 >= I$DT1 OR V$DT2 >= I$DT1) THEN
      SUSPEND;
    END
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_MS_TEACHER_ROLE_EDU_GROUPS (
    I$DT1 TIMESTAMP,
    I$DT2 TIMESTAMP NOT NULL = current_timestamp)
RETURNS (
    TEACHER_ROLE_ID VARCHAR(60),
    EDU_GROUP_URI VARCHAR(200),
    CREATE_DATETIME TIMESTAMP,
    SEND_DATETIME TIMESTAMP)
AS
declare variable V$SCHOOL_ID bigint;
declare variable V$GP_ID bigint;
declare variable V$Y integer;
declare variable V$DT1 timestamp;
declare variable V$DT2 timestamp;
declare variable V$DT3 timestamp;
declare variable SCHOOL_ID varchar(40);
declare variable TEACHER_ID varchar(60);
declare variable V$PERSON_ID bigint;
declare variable V$YDATE date;
declare variable ND timestamp;
begin

  -- Полное название пакета classes_students_edu_group
  -- Сам пакет - непонятная шняга, содержащая связь обучающихся и плана учебных мест

  SEND_DATETIME = I$DT2;

  SELECT FIRST 1 L2.OBJ_ID, V1236.LISTVAL_ID, LV.COST, V9.VAL
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  JOIN VALS V9 ON V9.OBJ_ID = L2.OBJ_ID AND V9.PARAM_ID = 9 AND V9.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$SCHOOL_ID, :V$GP_ID, :V$Y, :SCHOOL_ID;

  EDU_GROUP_URI = 'https://dnevnik2.petersburgedu.ru/groups/' || SCHOOL_ID || '/' || V$Y;

  V$YDATE = '30.08.' || V$Y;
  ND = '01.01.2023';

  FOR
    -- Действующие
    SELECT SID, MAX(OBJ_ID), MAX(DATE_MODIFY)
    FROM (
      SELECT V2915.SVAL SID, L14.OBJ_ID, L14.DATE_MODIFY
      FROM LINKS L2
      JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
      JOIN VALS V2915 ON V2915.OBJ_ID = L14.OBJ_ID AND V2915.PARAM_ID = 2915 AND V2915.IS_DEL = 0
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      UNION
      -- Уволенные не ранее даты начала текущего учебного года
      SELECT V2915.SVAL, L14.OBJ_ID, L14.DATE_MODIFY
      FROM LINKS L2
      JOIN LINKS L84 ON L84.PARENT_ID = L2.OBJ_ID AND L84.OBJ_TYPE_ID = 84 AND L84.DATE_DEL IS NULL
      JOIN LINKS L14 ON L14.PARENT_ID = L84.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
      JOIN VALS V2915 ON V2915.OBJ_ID = L14.OBJ_ID AND V2915.PARAM_ID = 2915 AND V2915.IS_DEL = 0
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND EXISTS(
        SELECT FIRST 1 1
        FROM LINKS L15
        LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
        WHERE L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL AND (V74.VAL IS NULL OR V74.VAL >= :V$YDATE)
      )
    )
    GROUP BY 1
    ORDER BY 1
    INTO :TEACHER_ID, :V$PERSON_ID, :V$DT1
  DO
  BEGIN
    -- Роли выгружаем только для педагогических сотрудников
    FOR
      SELECT L15.OBJ_ID, MAXVALUE(COALESCE(L15.DATE_MODIFY, :ND), COALESCE(V73.DATE_MODIFY, :ND),
        COALESCE(V74.DATE_MODIFY, :ND), COALESCE(V72.DATE_MODIFY, :ND), COALESCE(V63.DATE_MODIFY, :ND))
      FROM LINKS L15
      JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
      JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0
      LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
      JOIN VALS V66 ON V66.OBJ_ID = LP13.PARENT_ID AND V66.PARAM_ID = 66 AND V66.IS_DEL = 0
      JOIN VALL V72 ON V72.OBJ_ID = L15.OBJ_ID AND V72.PARAM_ID = 72 AND V72.IS_DEL = 0
      JOIN VALL V63 ON V63.OBJ_ID = LP13.PARENT_ID AND V63.PARAM_ID = 63 AND V63.IS_DEL = 0 -- группа должностей
      JOIN VALL V64 ON V64.OBJ_ID = LP13.PARENT_ID AND V64.PARAM_ID = 64 AND V64.IS_DEL = 0 -- подгруппа должностей
      JOIN VALL V58 ON V58.OBJ_ID = LP13.PARENT_ID AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0 -- сама должность
      WHERE L15.PARENT_ID = :V$PERSON_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
        -- исключаем финансовые и вспомогательные должности 2 уровня
        AND V58.LISTVAL_ID NOT IN (69, 86, 95, 141, 3300, 11095)
        -- исключаем подгруппы рабочих, служащих, персонал
        AND V64.LISTVAL_ID NOT IN (1313, 1323, 1257)
      INTO :TEACHER_ROLE_ID, :V$DT2
    DO
    BEGIN
      CREATE_DATETIME = V$DT2;

      IF(I$DT1 IS NULL OR V$DT1 >= I$DT1 OR V$DT2 >= I$DT1) THEN
      SUSPEND;
    END
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_MS_TEACHER_ROLE_SERVICE (
    I$DT1 TIMESTAMP,
    I$DT2 TIMESTAMP NOT NULL = current_timestamp)
RETURNS (
    TEACHER_ROLE_ID VARCHAR(60),
    SERVICE_ID VARCHAR(60),
    CREATE_DATETIME TIMESTAMP,
    SEND_DATETIME TIMESTAMP)
AS
declare variable V$SCHOOL_ID bigint;
declare variable V$GP_ID bigint;
declare variable V$Y integer;
declare variable V$DT1 timestamp;
declare variable V$DT2 timestamp;
declare variable V$DT3 timestamp;
declare variable SCHOOL_ID varchar(40);
declare variable TEACHER_ID varchar(60);
declare variable V$PERSON_ID bigint;
declare variable V$YDATE date;
declare variable ND timestamp;
begin

  SEND_DATETIME = I$DT2;

  SELECT FIRST 1 L2.OBJ_ID, V1236.LISTVAL_ID, LV.COST, V9.VAL
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  JOIN VALS V9 ON V9.OBJ_ID = L2.OBJ_ID AND V9.PARAM_ID = 9 AND V9.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$SCHOOL_ID, :V$GP_ID, :V$Y, :SCHOOL_ID;

  SERVICE_ID = 'dnevnik';

  V$YDATE = '30.08.' || V$Y;
  ND = '01.01.2023';

  FOR
    -- Действующие
    SELECT SID, MAX(OBJ_ID), MAX(DATE_MODIFY)
    FROM (
      SELECT V2915.SVAL SID, L14.OBJ_ID, L14.DATE_MODIFY
      FROM LINKS L2
      JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
      JOIN VALS V2915 ON V2915.OBJ_ID = L14.OBJ_ID AND V2915.PARAM_ID = 2915 AND V2915.IS_DEL = 0
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      UNION
      -- Уволенные не ранее даты начала текущего учебного года
      SELECT V2915.SVAL, L14.OBJ_ID, L14.DATE_MODIFY
      FROM LINKS L2
      JOIN LINKS L84 ON L84.PARENT_ID = L2.OBJ_ID AND L84.OBJ_TYPE_ID = 84 AND L84.DATE_DEL IS NULL
      JOIN LINKS L14 ON L14.PARENT_ID = L84.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
      JOIN VALS V2915 ON V2915.OBJ_ID = L14.OBJ_ID AND V2915.PARAM_ID = 2915 AND V2915.IS_DEL = 0
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND EXISTS(
        SELECT FIRST 1 1
        FROM LINKS L15
        LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
        WHERE L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL AND (V74.VAL IS NULL OR V74.VAL >= :V$YDATE)
      )
    )
    GROUP BY 1
    ORDER BY 1
    INTO :TEACHER_ID, :V$PERSON_ID, :V$DT1
  DO
  BEGIN
    -- Роли выгружаем только для педагогических сотрудников
    FOR
      SELECT L15.OBJ_ID, MAXVALUE(COALESCE(L15.DATE_MODIFY, :ND), COALESCE(V73.DATE_MODIFY, :ND),
        COALESCE(V74.DATE_MODIFY, :ND), COALESCE(V72.DATE_MODIFY, :ND), COALESCE(V63.DATE_MODIFY, :ND))
      FROM LINKS L15
      JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
      JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0
      LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
      JOIN VALS V66 ON V66.OBJ_ID = LP13.PARENT_ID AND V66.PARAM_ID = 66 AND V66.IS_DEL = 0
      JOIN VALL V72 ON V72.OBJ_ID = L15.OBJ_ID AND V72.PARAM_ID = 72 AND V72.IS_DEL = 0
      JOIN VALL V63 ON V63.OBJ_ID = LP13.PARENT_ID AND V63.PARAM_ID = 63 AND V63.IS_DEL = 0 -- группа должностей
      JOIN VALL V64 ON V64.OBJ_ID = LP13.PARENT_ID AND V64.PARAM_ID = 64 AND V64.IS_DEL = 0 -- подгруппа должностей
      JOIN VALL V58 ON V58.OBJ_ID = LP13.PARENT_ID AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0 -- сама должность
      WHERE L15.PARENT_ID = :V$PERSON_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
        -- исключаем финансовые и вспомогательные должности 2 уровня
        AND V58.LISTVAL_ID NOT IN (69, 86, 95, 141, 3300, 11095)
        -- исключаем подгруппы рабочих, служащих, персонал
        AND V64.LISTVAL_ID NOT IN (1313, 1323, 1257)
      INTO :TEACHER_ROLE_ID, :V$DT2
    DO
    BEGIN
      CREATE_DATETIME = V$DT2;

      IF(I$DT1 IS NULL OR V$DT1 >= I$DT1 OR V$DT2 >= I$DT1) THEN
      SUSPEND;
    END
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_MS_TELECOM (
    I$DT1 TIMESTAMP,
    I$DT2 TIMESTAMP NOT NULL = current_timestamp)
RETURNS (
    ID VARCHAR(60),
    TYPE_CONTACT INTEGER,
    VALUE_TYPE VARCHAR(400),
    USE_COD INTEGER,
    RANK_CONTACT INTEGER,
    CREATE_DATETIME TIMESTAMP,
    SEND_DATETIME TIMESTAMP)
AS
declare variable V$SCHOOL_ID bigint;
declare variable V$OGRN varchar(100);
declare variable V$GP_ID bigint;
declare variable V$Y integer;
declare variable V$DT1 timestamp;
declare variable V$DT2 timestamp;
declare variable V$PARAM_ID bigint;
declare variable V$OBJ_ID bigint;
begin

  SEND_DATETIME = I$DT2;

  SELECT FIRST 1 L2.OBJ_ID, V1236.LISTVAL_ID, LV.COST, V9.VAL
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  JOIN VALS V9 ON V9.OBJ_ID = L2.OBJ_ID AND V9.PARAM_ID = 9 AND V9.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$SCHOOL_ID, :V$GP_ID, :V$Y, :V$OGRN;

  FOR
    -- Сама организация
    SELECT :V$SCHOOL_ID, :V$OGRN, V.PARAM_ID, V.VAL, NULL, NULL, NULL, V.DATE_MODIFY
    FROM VALS V
    WHERE V.OBJ_ID = :V$SCHOOL_ID AND V.PARAM_ID IN (28, 29, 30, 35) AND V.IS_DEL = 0
    -- Сотрудники - мобильный телефон
    UNION
    SELECT L14.OBJ_ID, V2915.VAL, V254.PARAM_ID, V254.VAL, 1, 5, MAXVALUE(L14.DATE_MODIFY, V2915.DATE_MODIFY), V254.DATE_MODIFY
    FROM LINKS L14
    JOIN VALS V2915 ON V2915.OBJ_ID = L14.OBJ_ID AND V2915.PARAM_ID = 2915 AND V2915.IS_DEL = 0
    JOIN VALS V254 ON V254.OBJ_ID = L14.OBJ_ID AND V254.PARAM_ID = 254 AND V254.IS_DEL = 0
    WHERE L14.PARENT_ID = :V$SCHOOL_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
    -- Сотрудники - email. Почту считаем домашней
    UNION
    SELECT L14.OBJ_ID, V2915.VAL, V1180.PARAM_ID, V1180.VAL, 3, 1, MAXVALUE(L14.DATE_MODIFY, V2915.DATE_MODIFY), V1180.DATE_MODIFY
    FROM LINKS L14
    JOIN VALS V2915 ON V2915.OBJ_ID = L14.OBJ_ID AND V2915.PARAM_ID = 2915 AND V2915.IS_DEL = 0
    JOIN VALS V1180 ON V1180.OBJ_ID = L14.OBJ_ID AND V1180.PARAM_ID = 1180 AND V1180.IS_DEL = 0
    WHERE L14.PARENT_ID = :V$SCHOOL_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
    -- Обучающиеся - мобильный телефон
    UNION
    SELECT L10.OBJ_ID, V2912.VAL, V102.PARAM_ID, V102.VAL, 1, 5, MAXVALUE(L10.DATE_MODIFY, V2912.DATE_MODIFY), V102.DATE_MODIFY
    FROM LINKS L7
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
    JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    JOIN VALS V2912 ON V2912.OBJ_ID = L10.OBJ_ID AND V2912.PARAM_ID = 2912 AND V2912.IS_DEL = 0
    JOIN VALS V102 ON V102.OBJ_ID = L10.OBJ_ID AND V102.PARAM_ID = 102 AND V102.IS_DEL = 0
    WHERE L7.PARENT_ID = :V$SCHOOL_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    -- Обучающиеся - email. Почту считаем домашней
    UNION
    SELECT L10.OBJ_ID, V2912.VAL, V3076.PARAM_ID, V3076.VAL, 3, 1, MAXVALUE(L10.DATE_MODIFY, V2912.DATE_MODIFY), V3076.DATE_MODIFY
    FROM LINKS L7
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
    JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    JOIN VALS V2912 ON V2912.OBJ_ID = L10.OBJ_ID AND V2912.PARAM_ID = 2912 AND V2912.IS_DEL = 0
    JOIN VALS V3076 ON V3076.OBJ_ID = L10.OBJ_ID AND V3076.PARAM_ID = 3076 AND V3076.IS_DEL = 0
    WHERE L7.PARENT_ID = :V$SCHOOL_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    ORDER BY 1, 3
    INTO :V$OBJ_ID, :ID, :V$PARAM_ID, :VALUE_TYPE, :TYPE_CONTACT, :USE_COD, :V$DT1, :V$DT2
  DO
  BEGIN
    CREATE_DATETIME = V$DT2;

    IF(POSITION(':' IN ID) > 0) THEN ID = SUBSTRING(ID FROM 1 FOR POSITION(':' IN ID) - 1);
    ID = REPLACE(ID, '{', '');
    ID = REPLACE(ID, '}', '');
    ID = LOWER(ID);

    ID = ID || ':' || V$PARAM_ID;

    IF(V$PARAM_ID IN (28, 29)) THEN
    BEGIN
      -- Телефон директора и приемной ОУ
      TYPE_CONTACT = 1;
      USE_COD = 2;
    END
    IF(V$PARAM_ID IN (30)) THEN
    BEGIN
      -- Факс ОУ
      TYPE_CONTACT = 2;
      USE_COD = 2;
    END
    IF(V$PARAM_ID IN (35)) THEN
    BEGIN
      -- Почта ОУ
      TYPE_CONTACT = 3;
      USE_COD = 2;
    END

    IF(I$DT1 IS NULL OR V$DT1 >= I$DT1 OR V$DT2 >= I$DT1) THEN SUSPEND;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_MS_TELECOM_LOCATIONS (
    I$DT1 TIMESTAMP,
    I$DT2 TIMESTAMP NOT NULL = current_timestamp)
RETURNS (
    TELECOM_ID VARCHAR(60),
    EDU_LOCATION_ID VARCHAR(60),
    CREATE_DATETIME TIMESTAMP,
    SEND_DATETIME TIMESTAMP)
AS
declare variable V$SCHOOL_ID bigint;
declare variable V$GP_ID bigint;
declare variable V$Y integer;
declare variable V$DT1 timestamp;
declare variable V$DT2 timestamp;
declare variable V$PARAM_ID bigint;
declare variable ORGANISATION_ID varchar(40);
declare variable NC timestamp;
begin

  SEND_DATETIME = I$DT2;

  SELECT FIRST 1 L2.OBJ_ID, V1236.LISTVAL_ID, LV.COST, V9.VAL
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  JOIN VALS V9 ON V9.OBJ_ID = L2.OBJ_ID AND V9.PARAM_ID = 9 AND V9.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$SCHOOL_ID, :V$GP_ID, :V$Y, :ORGANISATION_ID;

  NC = '01.01.2023';

  FOR
    SELECT V.PARAM_ID, V.DATE_MODIFY
    FROM VALS V
    WHERE V.OBJ_ID = :V$SCHOOL_ID AND V.PARAM_ID IN (28, 29, 30, 35) AND V.IS_DEL = 0
    ORDER BY 1
    INTO :V$PARAM_ID, :V$DT1
  DO
  BEGIN
    TELECOM_ID = ORGANISATION_ID || ':' || V$PARAM_ID;

    FOR
      SELECT L16.OBJ_ID, MAXVALUE(COALESCE(L16.DATE_MODIFY, :NC), COALESCE(V421.DATE_MODIFY, :NC), COALESCE(V420.DATE_MODIFY, :NC))
      FROM LINKS L73
      JOIN LINKS L16 ON L16.PARENT_ID = L73.OBJ_ID AND L16.OBJ_TYPE_ID = 16 AND L16.DATE_DEL IS NULL
      JOIN VALL V485 ON V485.OBJ_ID = L16.OBJ_ID AND V485.PARAM_ID = 485 AND V485.IS_DEL = 0 AND V485.LISTVAL_ID = 1093
      -- Адрес должен быть заполнен с указанием кода ФИАС
      JOIN VALA V420 ON V420.OBJ_ID = L16.OBJ_ID AND V420.PARAM_ID = 420 AND V420.IS_DEL = 0 AND V420.FIAS_UID IS NOT NULL
      JOIN VALS V421 ON V421.OBJ_ID = L16.OBJ_ID AND V421.PARAM_ID = 421 AND V421.IS_DEL = 0
      -- Дата завершения эксплуатации
      LEFT JOIN VALD V3164 ON V3164.OBJ_ID = L16.OBJ_ID AND V3164.PARAM_ID = 3164 AND V3164.IS_DEL = 0
      WHERE L73.PARENT_ID = :V$SCHOOL_ID AND L73.OBJ_TYPE_ID = 73 AND L73.DATE_DEL IS NULL
        AND V3164.VAL IS NULL
      ORDER BY 1
      INTO :EDU_LOCATION_ID, :V$DT2
    DO
    BEGIN
      CREATE_DATETIME = V$DT2;
      IF(I$DT1 IS NULL OR V$DT1 >= I$DT1 OR V$DT2 >= I$DT1) THEN SUSPEND;
    END
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_MS_TELECOM_ORGANISATIONS (
    I$DT1 TIMESTAMP,
    I$DT2 TIMESTAMP NOT NULL = current_timestamp)
RETURNS (
    TELECOM_ID VARCHAR(60),
    ORGANISATION_ID VARCHAR(60),
    CREATE_DATETIME TIMESTAMP,
    SEND_DATETIME TIMESTAMP)
AS
declare variable V$SCHOOL_ID bigint;
declare variable V$GP_ID bigint;
declare variable V$Y integer;
declare variable V$DT1 timestamp;
declare variable V$DT2 timestamp;
declare variable V$PARAM_ID bigint;
begin

  SEND_DATETIME = I$DT2;

  SELECT FIRST 1 L2.OBJ_ID, V1236.LISTVAL_ID, LV.COST, V9.VAL
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  JOIN VALS V9 ON V9.OBJ_ID = L2.OBJ_ID AND V9.PARAM_ID = 9 AND V9.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$SCHOOL_ID, :V$GP_ID, :V$Y, :ORGANISATION_ID;

  FOR
    SELECT V.PARAM_ID, V.DATE_MODIFY
    FROM VALS V
    WHERE V.OBJ_ID = :V$SCHOOL_ID AND V.PARAM_ID IN (28, 29, 30, 35) AND V.IS_DEL = 0
    ORDER BY 1
    INTO :V$PARAM_ID, :V$DT1
  DO
  BEGIN
    CREATE_DATETIME = V$DT1;

    TELECOM_ID = ORGANISATION_ID || ':' || V$PARAM_ID;

    IF(I$DT1 IS NULL OR V$DT1 >= I$DT1) THEN SUSPEND;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_MS_TELECOM_STUDENT (
    I$DT1 TIMESTAMP,
    I$DT2 TIMESTAMP NOT NULL = current_timestamp)
RETURNS (
    TELECOM_ID VARCHAR(60),
    STUDENT_ID VARCHAR(60),
    CREATE_DATETIME TIMESTAMP,
    SEND_DATETIME TIMESTAMP)
AS
declare variable V$SCHOOL_ID bigint;
declare variable V$GP_ID bigint;
declare variable V$Y integer;
declare variable V$DT1 timestamp;
declare variable V$DT2 timestamp;
declare variable V$PARAM_ID bigint;
begin

  SEND_DATETIME = I$DT2;

  SELECT FIRST 1 L2.OBJ_ID, V1236.LISTVAL_ID, LV.COST
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  JOIN VALS V9 ON V9.OBJ_ID = L2.OBJ_ID AND V9.PARAM_ID = 9 AND V9.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$SCHOOL_ID, :V$GP_ID, :V$Y;

  FOR
    SELECT V2912.VAL, VC.PARAM_ID, MAX(MAXVALUE(L10.DATE_MODIFY, V2912.DATE_MODIFY, VC.DATE_MODIFY))
    FROM LINKS L7
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
    JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    JOIN VALS V2912 ON V2912.OBJ_ID = L10.OBJ_ID AND V2912.PARAM_ID = 2912 AND V2912.IS_DEL = 0
    JOIN VALS VC ON VC.OBJ_ID = L10.OBJ_ID AND VC.PARAM_ID IN (102, 3076) AND VC.IS_DEL = 0
    WHERE L7.PARENT_ID = :V$SCHOOL_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    GROUP BY 1, 2
    INTO :STUDENT_ID, :V$PARAM_ID, :V$DT1
  DO
  BEGIN
    CREATE_DATETIME = V$DT1;

    IF(POSITION(':' IN STUDENT_ID) > 0) THEN STUDENT_ID = SUBSTRING(STUDENT_ID FROM 1 FOR POSITION(':' IN STUDENT_ID) - 1);
    STUDENT_ID = REPLACE(STUDENT_ID, '{', '');
    STUDENT_ID = REPLACE(STUDENT_ID, '}', '');
    STUDENT_ID = LOWER(STUDENT_ID);

    TELECOM_ID = STUDENT_ID || ':' || V$PARAM_ID;

    IF(I$DT1 IS NULL OR V$DT1 >= I$DT1) THEN SUSPEND;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_MS_TELECOM_TEACHER (
    I$DT1 TIMESTAMP,
    I$DT2 TIMESTAMP NOT NULL = current_timestamp)
RETURNS (
    TELECOM_ID VARCHAR(60),
    TEACHER_ID VARCHAR(60),
    CREATE_DATETIME TIMESTAMP,
    SEND_DATETIME TIMESTAMP)
AS
declare variable V$SCHOOL_ID bigint;
declare variable V$GP_ID bigint;
declare variable V$Y integer;
declare variable V$DT1 timestamp;
declare variable V$DT2 timestamp;
declare variable V$PARAM_ID bigint;
begin

  SEND_DATETIME = I$DT2;

  SELECT FIRST 1 L2.OBJ_ID, V1236.LISTVAL_ID, LV.COST
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  JOIN VALS V9 ON V9.OBJ_ID = L2.OBJ_ID AND V9.PARAM_ID = 9 AND V9.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$SCHOOL_ID, :V$GP_ID, :V$Y;

  FOR
    SELECT V2915.VAL, VC.PARAM_ID, MAX(MAXVALUE(L14.DATE_MODIFY, V2915.DATE_MODIFY, VC.DATE_MODIFY))
    FROM LINKS L14
    JOIN VALS V2915 ON V2915.OBJ_ID = L14.OBJ_ID AND V2915.PARAM_ID = 2915 AND V2915.IS_DEL = 0
    JOIN VALS VC ON VC.OBJ_ID = L14.OBJ_ID AND VC.PARAM_ID IN (1180, 254) AND VC.IS_DEL = 0
    WHERE L14.PARENT_ID = :V$SCHOOL_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
    GROUP BY 1, 2
    INTO :TEACHER_ID, :V$PARAM_ID, :V$DT1
  DO
  BEGIN
    CREATE_DATETIME = V$DT1;

    IF(POSITION(':' IN TEACHER_ID) > 0) THEN TEACHER_ID = SUBSTRING(TEACHER_ID FROM 1 FOR POSITION(':' IN TEACHER_ID) - 1);
    TEACHER_ID = REPLACE(TEACHER_ID, '{', '');
    TEACHER_ID = REPLACE(TEACHER_ID, '}', '');
    TEACHER_ID = LOWER(TEACHER_ID);

    TELECOM_ID = TEACHER_ID || ':' || V$PARAM_ID;

    IF(I$DT1 IS NULL OR V$DT1 >= I$DT1) THEN SUSPEND;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_MS_TELECOM_TEACHERS_ROLES (
    I$DT1 TIMESTAMP,
    I$DT2 TIMESTAMP NOT NULL = current_timestamp)
RETURNS (
    TELECOM_ID VARCHAR(60),
    TEACHER_ROLE_ID VARCHAR(60),
    CREATE_DATETIME TIMESTAMP,
    SEND_DATETIME TIMESTAMP)
AS
declare variable V$SCHOOL_ID bigint;
declare variable V$GP_ID bigint;
declare variable V$Y integer;
declare variable V$DT1 timestamp;
declare variable V$DT2 timestamp;
declare variable V$PARAM_ID bigint;
declare variable TEACHER_ID varchar(60);
begin

  SEND_DATETIME = I$DT2;

  SELECT FIRST 1 L2.OBJ_ID, V1236.LISTVAL_ID, LV.COST
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  JOIN VALS V9 ON V9.OBJ_ID = L2.OBJ_ID AND V9.PARAM_ID = 9 AND V9.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$SCHOOL_ID, :V$GP_ID, :V$Y;

  FOR
    SELECT V2915.VAL, L15.OBJ_ID, VC.PARAM_ID, MAX(MAXVALUE(L14.DATE_MODIFY, V2915.DATE_MODIFY, VC.DATE_MODIFY))
    FROM LINKS L14
    JOIN VALS V2915 ON V2915.OBJ_ID = L14.OBJ_ID AND V2915.PARAM_ID = 2915 AND V2915.IS_DEL = 0
    JOIN VALS VC ON VC.OBJ_ID = L14.OBJ_ID AND VC.PARAM_ID IN (1180, 254) AND VC.IS_DEL = 0
    -- Пересекаем со всеми актуальными должностями
    JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
    JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
    JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
    JOIN VALS V66 ON V66.OBJ_ID = LP13.PARENT_ID AND V66.PARAM_ID = 66 AND V66.IS_DEL = 0
    JOIN VALL V72 ON V72.OBJ_ID = L15.OBJ_ID AND V72.PARAM_ID = 72 AND V72.IS_DEL = 0
    JOIN VALL V63 ON V63.OBJ_ID = LP13.PARENT_ID AND V63.PARAM_ID = 63 AND V63.IS_DEL = 0 -- группа должностей
    JOIN VALL V64 ON V64.OBJ_ID = LP13.PARENT_ID AND V64.PARAM_ID = 64 AND V64.IS_DEL = 0 -- подгруппа должностей
    JOIN VALL V58 ON V58.OBJ_ID = LP13.PARENT_ID AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0 -- сама должность
    WHERE L14.PARENT_ID = :V$SCHOOL_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
      -- только действующие должности
      AND V74.VAL IS NULL
      -- исключаем финансовые и вспомогательные должности 2 уровня
      AND V58.LISTVAL_ID NOT IN (69, 86, 95, 141, 3300, 11095)
      -- исключаем подгруппы рабочих, служащих, персонал
      AND V64.LISTVAL_ID NOT IN (1313, 1323, 1257)
    GROUP BY 1, 2, 3
    INTO :TEACHER_ID, :TEACHER_ROLE_ID, :V$PARAM_ID, :V$DT1
  DO
  BEGIN
    CREATE_DATETIME = V$DT1;

    IF(POSITION(':' IN TEACHER_ID) > 0) THEN TEACHER_ID = SUBSTRING(TEACHER_ID FROM 1 FOR POSITION(':' IN TEACHER_ID) - 1);
    TEACHER_ID = REPLACE(TEACHER_ID, '{', '');
    TEACHER_ID = REPLACE(TEACHER_ID, '}', '');
    TEACHER_ID = LOWER(TEACHER_ID);

    TELECOM_ID = TEACHER_ID || ':' || V$PARAM_ID;

    IF(I$DT1 IS NULL OR V$DT1 >= I$DT1) THEN SUSPEND;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_MS_UNIT_PLAN (
    I$DT1 TIMESTAMP,
    I$DT2 TIMESTAMP NOT NULL = current_timestamp)
RETURNS (
    ID VARCHAR(40),
    UNIT_NAME VARCHAR(400),
    DESCRIPTION VARCHAR(1000),
    UNIT_NUMBER VARCHAR(40),
    SUBJECT_PLAN_ID VARCHAR(40),
    CREATE_DATETIME TIMESTAMP,
    SEND_DATETIME TIMESTAMP)
AS
declare variable V$SCHOOL_ID bigint;
declare variable V$GP_ID bigint;
declare variable V$Y integer;
declare variable V$DT1 timestamp;
declare variable V$DT2 timestamp;
declare variable V$CJ_ID bigint;
begin

  SEND_DATETIME = I$DT2;

  SELECT FIRST 1 L2.OBJ_ID, V1236.LISTVAL_ID, LV.COST
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$SCHOOL_ID, :V$GP_ID, :V$Y;

  UNIT_NUMBER = 'Основной раздел';

  FOR
    SELECT J.OBJ_ID, J.OBJ_ID, J.DATE_MODIFY
    FROM CJ2_JOURNAL J
    WHERE J.DATE_DEL IS NULL AND J.JOURNAL_TYPE = 0 AND J.YEAR_ID = :V$GP_ID
    ORDER BY 1
    INTO :V$CJ_ID, :ID, :V$DT1
  DO
  BEGIN
    SUBJECT_PLAN_ID = ID;
    CREATE_DATETIME = V$DT1;

    DESCRIPTION = 'Не назначен';
    V$DT2 = NULL;
    SELECT FIRST 1 P.OBJ_NAME, JP.DATE_MODIFY
    FROM CJ2_JOURNAL_PTP JP
    JOIN PTP P ON P.OBJ_ID = JP.PTP_ID
    WHERE JP.DATE_DEL IS NULL AND JP.CJ_ID = :V$CJ_ID AND JP.APPROVAL_STATE = 2
    INTO :DESCRIPTION, :V$DT2;

    UNIT_NAME = SUBSTRING(DESCRIPTION FROM 1 FOR 400);

    IF(I$DT1 IS NULL OR V$DT1 >= I$DT1 OR V$DT2 >= I$DT1) THEN
    SUSPEND;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_MS_UPDATE_TM (
    I$TM TIMESTAMP)
AS
declare variable ID bigint;
declare variable V$TM timestamp;
begin

  -- Фиксируем метку времени раз в 3 дня относительно предыдущей отправки
  SELECT FIRST 1 I.INFO_ID, CAST(I.INFO_VAL AS TIMESTAMP)
  FROM INFO I
  WHERE I.INFO_CODE = 'MS_LAST_EXPORT_DATE'
  INTO :ID, :V$TM;

  IF(ID IS NULL) THEN
  BEGIN
    -- С нуля добавляем запись всегда
    INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
    VALUES ('MS_LAST_EXPORT_DATE', 'MS_LAST_EXPORT_DATE', :I$TM);
  END
  ELSE IF(V$TM IS NULL OR V$TM < DATEADD(-3 DAY TO :I$TM)) THEN
  BEGIN
    -- Цифра 3 дня должна точно коррелировать с DC_MS_PMARKS и DC_MS_YMARKS
    UPDATE INFO
    SET INFO_VAL = :I$TM
    WHERE INFO_ID = :ID;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_MS_YMARKS (
    I$DT1 TIMESTAMP,
    I$DT2 TIMESTAMP NOT NULL = CURRENT_TIMESTAMP)
RETURNS (
    ID VARCHAR(100),
    SUBJECT_ID BIGINT,
    STUDENT_ID VARCHAR(60),
    CLASS_ID VARCHAR(40),
    SUBJECT_NAME VARCHAR(400),
    FACT VARCHAR(20),
    FIVEPOINT_FACT VARCHAR(20),
    FINAL_FACT VARCHAR(20),
    FIVEPOINT_FINAL_FACT VARCHAR(20),
    RECENT_PLAN VARCHAR(20),
    FIVEPOINT_RECENT_PLAN VARCHAR(20),
    SCHOOL_ID VARCHAR(40),
    CLASS_NUM INTEGER,
    CLASS_YEAR_FROM INTEGER,
    MARK_SCALE_CODE VARCHAR(20),
    MARK_SCALE_VALUE INTEGER,
    MARK_SCALE_DESCRIPTION VARCHAR(40),
    CREATE_DATETIME TIMESTAMP,
    SEND_DATETIME TIMESTAMP)
AS
DECLARE VARIABLE V$MARK_ID BIGINT;
DECLARE VARIABLE V$GY_ID BIGINT;
DECLARE VARIABLE V$Y INTEGER;
DECLARE VARIABLE V$RANGE_FROM DATE;
DECLARE VARIABLE V$YSTART DATE;
DECLARE VARIABLE V$YEND DATE;
DECLARE VARIABLE V$YEAR BIGINT;
DECLARE VARIABLE V$IN_DATE DATE;
DECLARE VARIABLE V$MARKVAL BIGINT;
DECLARE VARIABLE V$YEARVAL INTEGER;
DECLARE VARIABLE V$STUDENT_ID BIGINT;
DECLARE VARIABLE V$CLASS_ID BIGINT;
DECLARE VARIABLE V$SCHOOL_ID BIGINT;
DECLARE VARIABLE V$YEAR_ID BIGINT;
DECLARE VARIABLE V$DT1 TIMESTAMP;
DECLARE VARIABLE V$DT2 TIMESTAMP;
DECLARE VARIABLE V$DT3 TIMESTAMP;
DECLARE VARIABLE V$DT4 TIMESTAMP;
DECLARE VARIABLE V$DT5 TIMESTAMP;
DECLARE VARIABLE V$DT6 TIMESTAMP;
DECLARE VARIABLE V$TM TIMESTAMP;
begin

  SEND_DATETIME = I$DT2;

  SELECT FIRST 1 L2.OBJ_ID, V1236.LISTVAL_ID, LV.COST, V9.VAL
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  JOIN VALS V9 ON V9.OBJ_ID = L2.OBJ_ID AND V9.PARAM_ID = 9 AND V9.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$SCHOOL_ID, :V$GY_ID, :V$Y, :SCHOOL_ID;

  V$RANGE_FROM = '31.08.' || (V$Y - 3);

  IF(SCHOOL_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Объект школы не найден';

  SELECT FIRST 1 CAST(I.INFO_VAL AS TIMESTAMP)
  FROM INFO I
  WHERE I.INFO_CODE = 'MS_LAST_EXPORT_DATE'
  INTO :V$TM;

  -- Выбираем всех обучающихся, засветившихся в школе за последние 3 года
  FOR
    SELECT L10.OBJ_ID, V2912.SVAL, MIN(M.DATE_IN), MAX(M.DATE_MODIFY), MAX(V2912.DATE_MODIFY)
    FROM LINKS L10
    JOIN PERSON_MOVEMENTS M ON M.DATE_DEL IS NULL AND M.PERSON_ID = L10.OBJ_ID AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :V$RANGE_FROM) AND M.LEVEL_ID IN (22, 26, 27)
    JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
    -- Есть регид
    JOIN VALS V2912 ON V2912.OBJ_ID = M.PERSON_ID AND V2912.PARAM_ID = 2912 AND V2912.IS_DEL = 0
    WHERE L10.PARENT_TYPE_ID IN (9, 125, 187) AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL -- , 81, 82, 83
    GROUP BY 1, 2
    ORDER BY 1
    INTO :V$STUDENT_ID, :STUDENT_ID, :V$IN_DATE, :V$DT1, :V$DT2
  DO
  BEGIN

    IF(POSITION(':' IN STUDENT_ID) > 0) THEN STUDENT_ID = SUBSTRING(STUDENT_ID FROM 1 FOR POSITION(':' IN STUDENT_ID) - 1);
    STUDENT_ID = REPLACE(STUDENT_ID, '{', '');
    STUDENT_ID = REPLACE(STUDENT_ID, '}', '');
    STUDENT_ID = LOWER(STUDENT_ID);

    V$DT3 = NULL;
    SELECT MAX(MAXVALUE(L20.DATE_INS, V155.DATE_MODIFY, V1570.DATE_MODIFY))
    FROM LINKS L20
    JOIN VALS V155 ON V155.OBJ_ID = L20.OBJ_ID AND V155.PARAM_ID = 155 AND V155.IS_DEL = 0
    JOIN VALS V1570 ON V1570.OBJ_ID = L20.EXT_OBJ_ID AND V1570.PARAM_ID = 1570 AND V1570.IS_DEL = 0
    WHERE L20.PARENT_ID = :V$STUDENT_ID AND L20.OBJ_TYPE_ID = 20 AND L20.DATE_DEL IS NULL
    INTO :V$DT3;

    -- Перебираем учебные годы с года прихода вплоть до текущего года
    -- если дата зачисления была раньше августа - то ученик успел попасть в предыдущий учебный год
    CLASS_YEAR_FROM = EXTRACT(YEAR FROM V$IN_DATE);
    IF(EXTRACT(MONTH FROM V$IN_DATE) < 8) THEN CLASS_YEAR_FROM = CLASS_YEAR_FROM - 1;

    WHILE(CLASS_YEAR_FROM <= V$Y) DO
    BEGIN
      V$YSTART = '01.09.' || CLASS_YEAR_FROM; -- дата начала обучения в году
      V$YEND = '25.08.' || (CLASS_YEAR_FROM + 1); -- специальный запас, чтобы не зацепить следующий год

      -- Восстанавливаем id класса на конец года
      V$CLASS_ID = NULL;
      SELECT FIRST 1 M.GROUP_ID, CAST(LV.COST AS INTEGER)
      FROM PERSON_MOVEMENTS M
      JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
      JOIN LISTVALS LV ON LV.LISTVAL_ID = M.STAGE_ID
      WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :V$STUDENT_ID AND M.DATE_IN <= :V$YEND AND M.LEVEL_ID IN (22, 26, 27)
      ORDER BY M.DATE_OUT DESC NULLS FIRST
      INTO :V$CLASS_ID, :CLASS_NUM;

      CLASS_ID = V$CLASS_ID || 'Y' || CLASS_YEAR_FROM;

      -- id учебного года, он обязательно есть
      SELECT FIRST 1 LV.LISTVAL_ID
      FROM LISTVALS LV
      WHERE LV.IS_DEL = 0 AND LV.LIST_ID = 29 AND LV.COST = :CLASS_YEAR_FROM
      INTO :V$YEAR_ID;

      FOR
        -- уже выставленные отметки
        SELECT V.MARK_ID, V.SUBJECT_ID, V.MARKVAL_ID, V.MARK_DATE, V.DATE_MODIFY
        FROM VALM V
        WHERE V.IS_DEL = 0 AND V.YEAR_ID = :V$YEAR_ID AND V.PUPIL_ID = :V$STUDENT_ID
          AND V.MARKTYPE_ID = 3011 AND (V.IS_NATIVE IS NULL OR V.IS_NATIVE = 1)
        -- невыставленные отметки текущего года
        UNION
        SELECT DISTINCT NULL, J.SUBJECT_ID, NULL, CAST('31.05.' || (:CLASS_YEAR_FROM + 1) AS DATE), NULL
        FROM PERSON_MOVEMENTS M
        JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.GRADE_ID = M.GROUP_ID AND J.JOURNAL_TYPE = 0 AND J.YEAR_ID = :V$YEAR_ID
        LEFT JOIN VALM V ON V.IS_DEL = 0 AND V.YEAR_ID = J.YEAR_ID AND V.SUBJECT_ID = J.SUBJECT_ID AND V.MARKTYPE_ID = 3011 AND V.PUPIL_ID = :V$STUDENT_ID
          AND (V.IS_NATIVE IS NULL OR V.IS_NATIVE = 1)
        WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :V$STUDENT_ID AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :V$RANGE_FROM) AND (:V$Y = :CLASS_YEAR_FROM) AND V.MARK_ID IS NULL
          AND M.LEVEL_ID IN (22, 26, 27)
        ORDER BY 2, 3
        INTO :V$MARK_ID, :SUBJECT_ID, :V$MARKVAL, :CREATE_DATETIME, :V$DT4
      DO
      BEGIN
        ID = STUDENT_ID || 'S' || SUBJECT_ID || 'Y' || CLASS_YEAR_FROM;
        SUBJECT_NAME = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:SUBJECT_ID));

        IF(V$MARKVAL IS NULL OR (V$MARKVAL >= 3014 AND V$MARKVAL <= 3018)) THEN
        BEGIN
          MARK_SCALE_VALUE = '1';
          MARK_SCALE_CODE = '5-points';
          MARK_SCALE_DESCRIPTION = 'Пятибалльная';
          FACT = V$MARKVAL - 3014 + 1;
          FIVEPOINT_FACT = FACT;
        END
        ELSE IF(V$MARKVAL >= 3019 AND V$MARKVAL <= 3020) THEN
        BEGIN
          MARK_SCALE_VALUE = '5';
          MARK_SCALE_CODE = 'pass/fail';
          MARK_SCALE_DESCRIPTION = 'Зачет-Незачет';
          IF(V$MARKVAL = 3019) THEN BEGIN
            FACT = 'Зачет';
            FIVEPOINT_FACT = 5;
          END
          ELSE BEGIN
            FACT = 'Незачет';
            FIVEPOINT_FACT = 1;
          END
        END
        ELSE IF(V$MARKVAL >= 13020 AND V$MARKVAL <= 13119) THEN
        BEGIN
          MARK_SCALE_VALUE = '3';
          MARK_SCALE_CODE = '100-points';
          MARK_SCALE_DESCRIPTION = 'Стобалльная';
          FACT = V$MARKVAL - 13020 + 1;
          FIVEPOINT_FACT = 1 + CAST(ROUND((V$MARKVAL - 13020 + 1) / 25) AS INTEGER);
        END
        ELSE
        BEGIN
          MARK_SCALE_VALUE = '6';
          MARK_SCALE_CODE = 'nomarks';
          MARK_SCALE_DESCRIPTION = 'Безотметочная';
          FACT = NULL;
          FIVEPOINT_FACT = NULL;
        END

        IF(CREATE_DATETIME IS NULL) THEN CREATE_DATETIME = (V$Y + 1) || '-05-31';

        -- Выбираем парную итоговую
        V$MARKVAL = NULL;
        V$DT5 = NULL;
        SELECT FIRST 1 V.MARKVAL_ID, V.DATE_MODIFY
        FROM VALM V
        WHERE V.IS_DEL = 0 AND V.YEAR_ID = :V$YEAR_ID AND V.PUPIL_ID = :V$STUDENT_ID AND V.SUBJECT_ID = :SUBJECT_ID
          AND V.MARKTYPE_ID = 3013 AND (V.IS_NATIVE IS NULL OR V.IS_NATIVE = 1)
        INTO :V$MARKVAL, :V$DT5;

        FINAL_FACT = NULL;
        FIVEPOINT_FINAL_FACT = NULL;
        IF(V$MARKVAL >= 3014 AND V$MARKVAL <= 3018) THEN
        BEGIN
          FINAL_FACT = V$MARKVAL - 3014 + 1;
          FIVEPOINT_FINAL_FACT = FINAL_FACT;
        END
        ELSE IF(V$MARKVAL >= 3019 AND V$MARKVAL <= 3020) THEN
        BEGIN
          IF(V$MARKVAL = 3019) THEN BEGIN
            FINAL_FACT = 'Зачет';
            FIVEPOINT_FINAL_FACT = 5;
          END
          ELSE BEGIN
            FINAL_FACT = 'Незачет';
            FIVEPOINT_FINAL_FACT = 1;
          END
        END
        ELSE IF(V$MARKVAL >= 13020 AND V$MARKVAL <= 13119) THEN
        BEGIN
          FINAL_FACT = V$MARKVAL - 13020 + 1;
          FIVEPOINT_FINAL_FACT = 1 + CAST(ROUND((V$MARKVAL - 13020 + 1) / 25) AS INTEGER);
        END
        ELSE
        BEGIN
        END

        -- Расчетная годовая оценка - вычисляем как среднее по четвертным/триместровым/полугодовым
        -- !!! пока только в 5-балльной шкале !!!
        RECENT_PLAN = NULL;
        V$DT6 = NULL;
        SELECT CAST(AVG(CAST(LV.TAG AS FLOAT)) AS NUMERIC(18, 1)), MAX(V.DATE_MODIFY)
        FROM VALM V
        JOIN LISTVALS LV ON LV.LISTVAL_ID = V.MARKVAL_ID
        WHERE V.IS_DEL = 0 AND V.YEAR_ID = :V$YEAR_ID AND V.PUPIL_ID = :V$STUDENT_ID AND V.SUBJECT_ID = :SUBJECT_ID
          AND V.MARKTYPE_ID IN (3002, 3003, 3004, 3005, 3006, 3007, 3008, 3009, 3010) AND (V.IS_NATIVE IS NULL OR V.IS_NATIVE = 1)
          AND V.MARKVAL_ID IN (3014, 3015, 3016, 3017, 3018) -- 1...5
        INTO :RECENT_PLAN, :V$DT6;
        FIVEPOINT_RECENT_PLAN = RECENT_PLAN;

        -- Изменение: для обеспечения актуальности нужно слать итоговые оценки не реже 1 раза в 3 дня, даже если ничего не меняется

        IF(I$DT1 IS NULL OR V$DT1 >= I$DT1 OR V$DT2 >= I$DT1 OR V$DT3 >= I$DT1 OR V$DT4 >= I$DT1 OR V$DT5 >= I$DT1 OR V$DT6 >= :I$DT1 OR V$TM <= DATEADD(-3 DAY TO :I$DT1)) THEN
        SUSPEND;

      END

      CLASS_YEAR_FROM = CLASS_YEAR_FROM + 1;
    END

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_OBJECTS_LIST (
    I$ROOT_ID BIGINT,
    I$LEVEL_ID BIGINT,
    I$USER_ID VARCHAR(40),
    I$FROM_IP VARCHAR(200) = NULL)
RETURNS (
    OBJ_ID BIGINT,
    TYPE_ID BIGINT,
    PARENT_ID BIGINT,
    PARENT_TYPE_ID BIGINT,
    USER_ID BIGINT,
    SORT_ORDER DOUBLE PRECISION,
    CAPTION VARCHAR(4000),
    HAS_CHILD INTEGER,
    COLOR INTEGER,
    TAB_ID BIGINT,
    TYPE_ORDER SMALLINT,
    LINK_ID BIGINT,
    TAG VARCHAR(100),
    NATIVE SMALLINT)
AS
DECLARE VARIABLE V$MYDATA SMALLINT;
DECLARE VARIABLE V$USER_ID BIGINT;
DECLARE VARIABLE V$ROOT_OBJ BIGINT;
DECLARE VARIABLE V$GEN BIGINT;
DECLARE VARIABLE V$MULT BIGINT;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$TYPE_ID BIGINT;
DECLARE VARIABLE N INTEGER;
begin

  V$MYDATA = 0;
  IF(I$LEVEL_ID > 100000) THEN
  BEGIN
    I$LEVEL_ID = I$LEVEL_ID - 100000;
    V$MYDATA = 1;
  END

  -- Проверяем доступ пользователя к запрошенному уровню
  -- Для level_id 48 (мои данные) доступ есть у всех реальных пользователей
  -- !!! временно, в дальнейшем веб-администратор сюда попадать не должен !!!
  IF(I$USER_ID = 'Веб-администратор') THEN V$USER_ID = 1; ELSE V$USER_ID = CAST(I$USER_ID AS BIGINT);

  SELECT GEN, MULTIPLIER
  FROM GEN
  INTO :V$GEN, :V$MULT;

  IF(V$MYDATA = 1) THEN
  BEGIN
    -- Просто проверяем наличие пользователя - тут и сотрудники, и ученики, но пока без родителей
    SELECT FIRST 1 U.OBJ_ID, LPG.OBJ_TYPE_ID
    FROM USERS U
    JOIN LINKS LPG ON LPG.OBJ_ID = U.OBJ_ID AND LPG.PARENT_TYPE_ID IN (2, 211, 9, 187) AND LPG.DATE_DEL IS NULL
    WHERE U.USER_ID = :V$USER_ID AND U.DATE_DEL IS NULL AND U.IS_BLOCKED = 0 AND (U.EXP_DATE IS NULL OR U.EXP_DATE > CURRENT_DATE)
    INTO :V$OBJ_ID, :V$TYPE_ID;

    IF(V$OBJ_ID IS NULL OR (V$TYPE_ID = 14 AND I$LEVEL_ID <> 48) OR (V$TYPE_ID = 10 AND I$LEVEL_ID <> 50)) THEN EXCEPTION DATA_ERROR 'У вас нет доступа к данному приложению';

    V$ROOT_OBJ = V$OBJ_ID;
  END
  ELSE
  BEGIN
    IF(NOT EXISTS(
      SELECT FIRST 1 1
      FROM USERS U
      JOIN LUSERS LU ON LU.USER_ID = U.USER_ID AND LU.LEVEL_ID = :I$LEVEL_ID
      WHERE U.USER_ID = :V$USER_ID AND U.DATE_DEL IS NULL AND U.IS_BLOCKED = 0 AND (U.EXP_DATE IS NULL OR U.EXP_DATE > CURRENT_DATE)
    ))
    THEN
      EXCEPTION DATA_ERROR 'У вас нет доступа к данному приложению';
  END

  N = 0;
  FOR
    SELECT OBJ_ID, TYPE_ID, PARENT_ID, PARENT_TYPE_ID, USER_ID, SORT_ORDER, CAPTION, HAS_CHILD, COLOR, TAB_ID, TYPE_ORDER, LINK_ID, TAG
    FROM OBJECTS_LIST(:I$ROOT_ID, :I$LEVEL_ID, :V$USER_ID, 0, :V$ROOT_OBJ, :I$FROM_IP)
    INTO :OBJ_ID, :TYPE_ID, :PARENT_ID, :PARENT_TYPE_ID, :USER_ID, :SORT_ORDER, :CAPTION, :HAS_CHILD, :COLOR, :TAB_ID, :TYPE_ORDER, :LINK_ID, :TAG
  DO
  BEGIN
    NATIVE = IIF((OBJ_ID >= V$GEN * V$MULT) AND (OBJ_ID < (V$GEN + 1) * V$MULT), 1, 0);

    -- Для администрирования пользователей скрываем лишнее в вебе
    -- В толстом клиенте сотрудники нужны, а в тонком - нет
    -- В мультипараграфе это уже не требуется
    IF(I$LEVEL_ID IN (54, 157, 167, 233)) THEN HAS_CHILD = 0;

    N = N + 1;
    SUSPEND;
  END

  -- Если нет корня дерева, то создаем корневой объект
  -- ОУ, район или регион
  IF(I$ROOT_ID IS NULL AND N = 0 AND V$USER_ID = 1 AND I$LEVEL_ID IN (14, 182, 190, /**/ 15, 17, 18, /**/ 16, 217, /**/ 237, 259, 278, /**/ 64, /**/ 545)) THEN
  BEGIN
    IF(NOT EXISTS(
      SELECT FIRST 1 1
      FROM LINKS
      WHERE PARENT_ID IS NULL AND OBJ_TYPE_ID IN (2, 111, 112, 124) AND DATE_DEL IS NULL
    ))
    THEN
    BEGIN
      N = NULL;
      SELECT KEY_VAL FROM KEYS WHERE KEY_CODE = 'LEVEL' INTO :N;
      IF(N IS NULL) THEN EXCEPTION DATA_ERROR 'Не загружен регистрационный ключ';
      ELSE IF(I$LEVEL_ID = 64) THEN V$TYPE_ID = 124;
      ELSE IF(N = 1) THEN V$TYPE_ID = 2;
      ELSE IF(N = 2) THEN V$TYPE_ID = 111;
      ELSE IF(N = 3) THEN V$TYPE_ID = 112;

      SELECT 1 FROM OBJECT_ADD(NULL, :V$TYPE_ID) INTO :N;

      -- И сразу выдаем свежедобавленное
      NATIVE = 1;
      FOR
        SELECT OBJ_ID, TYPE_ID, PARENT_ID, PARENT_TYPE_ID, USER_ID, SORT_ORDER, CAPTION, HAS_CHILD, COLOR, TAB_ID, TYPE_ORDER, LINK_ID, TAG
        FROM OBJECTS_LIST(:I$ROOT_ID, :I$LEVEL_ID, :V$USER_ID, 0, :V$ROOT_OBJ, :I$FROM_IP)
        INTO :OBJ_ID, :TYPE_ID, :PARENT_ID, :PARENT_TYPE_ID, :USER_ID, :SORT_ORDER, :CAPTION, :HAS_CHILD, :COLOR, :TAB_ID, :TYPE_ORDER, :LINK_ID, :TAG
      DO
      BEGIN
        SUSPEND;
      END
    END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_OBJECT_ADD (
    I$PARENT_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$OBJ_TYPE_ID BIGINT,
    I$LEVEL_ID BIGINT,
    I$TAB_ID BIGINT,
    I$USER_ID VARCHAR(40),
    I$GRIDFORMAT SMALLINT)
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(4000))
AS
declare variable V$MYDATA smallint;
declare variable V$USER_ID bigint;
declare variable V$TYPE_ID bigint;
declare variable V$OBJ_ID bigint;
declare variable V$PARENT_TYPE_ID bigint;
declare variable V$LINK_ID bigint;
declare variable V$PARAM_ID bigint;
declare variable V$BLOB_ID bigint;
declare variable V$S varchar(4000);
declare variable V$COLOR integer;
declare variable V$IS_EXISTS smallint;
declare variable V$OBJ_ID_P bigint;
declare variable V$LISTVAL_ID bigint;
declare variable V$EXACT_ACCESS smallint;
declare variable V$ALT_ACCESS smallint;
declare variable T$OBJ_ID bigint;
declare variable V$LIST_ID bigint;
declare variable V$COST double precision;
declare variable V$SORT_ORDER double precision;
declare variable V$IS_SELECT smallint;
declare variable V$SHOW_ALL_FIELDS smallint;
begin

  V$MYDATA = 0;
  IF(I$LEVEL_ID > 100000) THEN
  BEGIN
    I$LEVEL_ID = I$LEVEL_ID - 100000;
    V$MYDATA = 1;
  END

  IF(I$USER_ID = 'Веб-администратор') THEN V$USER_ID = 1; ELSE V$USER_ID = CAST(I$USER_ID AS BIGINT);

  IF(V$MYDATA = 1) THEN
  BEGIN
    -- Просто проверяем наличие пользователя - тут и сотрудники, и ученики, но пока без родителей
    SELECT FIRST 1 U.OBJ_ID, LPG.OBJ_TYPE_ID, LU.READ_ONLY
    FROM USERS U
    JOIN LINKS LPG ON LPG.OBJ_ID = U.OBJ_ID AND LPG.PARENT_TYPE_ID IN (2, 211, 9, 187) AND LPG.DATE_DEL IS NULL
    -- Дополнительно проверяем, что пользователю разрешено что-то менять тут
    LEFT JOIN LUSERS LU ON LU.USER_ID = U.USER_ID AND LU.LEVEL_ID = :I$LEVEL_ID
    WHERE U.USER_ID = :V$USER_ID AND U.DATE_DEL IS NULL AND U.IS_BLOCKED = 0 AND (U.EXP_DATE IS NULL OR U.EXP_DATE > CURRENT_DATE)
    INTO :V$OBJ_ID, :V$TYPE_ID, :V$EXACT_ACCESS;

    IF(V$OBJ_ID IS NOT NULL AND (V$EXACT_ACCESS IS NULL OR V$EXACT_ACCESS = 1)) THEN
    BEGIN
      -- При добавлении критерия аттестации - надо подняться на уровень выше
      IF(I$OBJ_TYPE_ID = 459) THEN
      BEGIN
        -- Если папка уже отправлена - добавлять нельзя
        IF(EXISTS(
          SELECT FIRST 1 1
          FROM VALL V
          WHERE V.OBJ_ID = :I$PARENT_ID AND V.PARAM_ID = 3299 AND V.IS_DEL = 0 AND V.LISTVAL_ID = 2
        ))
        THEN
          EXCEPTION DATA_ERROR 'Папка уже отправлена, добавлять новые критерии нельзя';

        SELECT FIRST 1 LP14.PARENT_ID
        FROM LINKS LP14
        WHERE LP14.OBJ_ID = :I$PARENT_ID AND LP14.PARENT_TYPE_ID = 14 AND LP14.DATE_DEL IS NULL
        INTO :T$OBJ_ID;
      END
      ELSE
      BEGIN
        T$OBJ_ID = I$PARENT_ID;
      END

      -- Если у пользователя нет доступа, проверяем перекрывающий доступ для своих собственных данных
      IF(V$OBJ_ID = T$OBJ_ID AND (
        -- Для сотрудника - только аттестация
        (V$TYPE_ID = 14 AND I$LEVEL_ID = 48 AND I$OBJ_TYPE_ID IN (458, 459)) OR
        -- Для учеников - портфолио
        (V$TYPE_ID = 10 AND I$LEVEL_ID = 50 AND I$OBJ_TYPE_ID IN (22, 24, 25, 430))
      ))
      THEN
        V$ALT_ACCESS = 0;

      IF(V$EXACT_ACCESS IS NULL OR V$ALT_ACCESS < V$EXACT_ACCESS) THEN V$EXACT_ACCESS = V$ALT_ACCESS;
    END

    IF(V$OBJ_ID IS NULL OR V$EXACT_ACCESS IS NULL OR V$EXACT_ACCESS = 1) THEN
      EXCEPTION DATA_ERROR 'У вас нет доступа к данному приложению (полностью или для данного конкретного типа объектов)';
  END
  ELSE
  BEGIN
    SELECT FIRST 1 U.USER_ID
    FROM USERS U
    JOIN LUSERS LU ON LU.USER_ID = U.USER_ID AND LU.LEVEL_ID = :I$LEVEL_ID AND LU.READ_ONLY = 0
    WHERE U.USER_ID = :V$USER_ID AND U.DATE_DEL IS NULL AND U.IS_BLOCKED = 0 AND (U.EXP_DATE IS NULL OR U.EXP_DATE > CURRENT_DATE)
    INTO :V$OBJ_ID;
  END

  IF(V$OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'У вас нет доступа к данному приложению';
  V$OBJ_ID = NULL;

  IF(I$OBJ_ID IS NULL AND I$OBJ_TYPE_ID IS NOT NULL) THEN
  BEGIN

    SELECT OBJ_ID, TYPE_ID, PARENT_TYPE_ID, LINK_ID
    FROM OBJECT_ADD(:I$PARENT_ID, :I$OBJ_TYPE_ID, NULL, NULL, :V$USER_ID)
    INTO :V$OBJ_ID, :I$OBJ_TYPE_ID, :V$PARENT_TYPE_ID, :V$LINK_ID;

  END
  ELSE IF(I$OBJ_ID IS NOT NULL) THEN
  BEGIN

    I$OBJ_TYPE_ID = (SELECT TYPE_ID FROM OBJECTS WHERE OBJ_ID = :I$OBJ_ID);
    V$PARENT_TYPE_ID = (SELECT TYPE_ID FROM OBJECTS WHERE OBJ_ID = :I$PARENT_ID);

    SELECT OBJ_ID, LINK_ID
    FROM OBJECT_ADD_LINK(:I$PARENT_ID, :I$OBJ_ID, :I$OBJ_TYPE_ID, NULL, NULL, :V$USER_ID)
    INTO :V$OBJ_ID, :V$LINK_ID;

  END
  ELSE EXCEPTION DATA_ERROR 'Недопустимая комбинация параметров';

  -- Выдаем результат в зависимости от того, где именно добавляли - в дереве или в закладках
  TAG_NAME = 'obj_id';
  VAL = V$OBJ_ID;
  SUSPEND;

  TAG_NAME = 'type_id';
  VAL = I$OBJ_TYPE_ID;
  SUSPEND;

  TAG_NAME = 'link_id';
  VAL = V$LINK_ID;
  SUSPEND;

  TAG_NAME = 'caption';
  SELECT CAPTION, COLOR
  FROM OBJECT_CAPTION_GET(:V$OBJ_ID)
  INTO :VAL, :V$COLOR;
  SUSPEND;

  TAG_NAME = 'color';
  VAL = V$COLOR;
  SUSPEND;

  -- Если добавлено в дереве - на этом заканчиваем
  -- Но если добавлено в гриде - продолжаем
  IF(I$GRIDFORMAT = 0) THEN EXIT;

  -- Это бесполезный кусок - мы никогда не вытаскивали данные в таком формате
  -- полей адреса тут нет, поэтому ошибки не будет
  TAG_NAME = 'fields::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
    SELECT OBJ_ID, PARAM_ID, BLOB_ID, VAL, COLOR, IS_EXISTS, LISTVAL_ID
    FROM OBJECT_PARAMS_LIST(:V$USER_ID, :V$OBJ_ID, :I$LEVEL_ID, :I$TAB_ID)
    INTO :V$OBJ_ID_P, :V$PARAM_ID, :V$BLOB_ID, :V$S, :V$COLOR, :V$IS_EXISTS, :V$LISTVAL_ID
  DO
  BEGIN
    TAG_NAME = 'fields:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'fields:r:obj_id';
    VAL = V$OBJ_ID_P;
    SUSPEND;
    TAG_NAME = 'fields:r:link_id'; -- тут всегда орининальный линк
    VAL = V$LINK_ID;
    SUSPEND;
    TAG_NAME = 'fields:r:param_id';
    VAL = V$PARAM_ID;
    SUSPEND;
    TAG_NAME = 'fields:r:blob_id';
    VAL = V$BLOB_ID;
    SUSPEND;
    TAG_NAME = 'fields:r:value';
    VAL = V$S;
    SUSPEND;
    TAG_NAME = 'fields:r:listval_id';
    VAL = V$LISTVAL_ID;
    SUSPEND;
    TAG_NAME = 'fields:r:color';
    VAL = V$COLOR;
    SUSPEND;
    TAG_NAME = 'fields:r:is_exists';
    VAL = V$IS_EXISTS;
    SUSPEND;
  END

  -- Выдача всех полей в формате грида, изменения 05.2024
  -- предполагается что раз уж метод вызван в режиме грида, значит грид есть и видим
  SELECT FIRST 1 P.IS_SELECT, P.SHOW_ALL_FIELDS
  FROM OBJECTS O
  JOIN PARENTS P ON P.TYPE_ID = O.TYPE_ID AND P.CHILD_ID = :I$OBJ_TYPE_ID AND P.IS_DEL = 0
  WHERE O.OBJ_ID = :I$PARENT_ID
  INTO :V$IS_SELECT, :V$SHOW_ALL_FIELDS;

  TAG_NAME = 'items::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
    SELECT LINK_ID, OBJ_ID, PARAM_ID, LIST_ID, VAL, COST, BLOB_ID, LISTVAL_ID, IS_EXISTS, SORT_ORDER, COLOR
    FROM OBJECT_GRID_VALS(NULL, :I$PARENT_ID, :I$OBJ_TYPE_ID, :I$LEVEL_ID, :V$IS_SELECT - :V$SHOW_ALL_FIELDS, 0, :V$USER_ID, 0) V
    WHERE V.OBJ_ID = :V$OBJ_ID
    INTO :V$LINK_ID, :V$OBJ_ID_P, :V$PARAM_ID, :V$LIST_ID, :V$S, :V$COST, :V$BLOB_ID, :V$LISTVAL_ID, :V$IS_EXISTS, :V$SORT_ORDER, :V$COLOR
  DO
  BEGIN
    TAG_NAME = 'items:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'items:r:link_id';
    VAL = V$LINK_ID;
    SUSPEND;
    TAG_NAME = 'items:r:obj_id';
    VAL = V$OBJ_ID_P;
    SUSPEND;
    TAG_NAME = 'items:r:param_id';
    VAL = V$PARAM_ID;
    SUSPEND;
    TAG_NAME = 'items:r:value';
    VAL = V$S;
    SUSPEND;
    TAG_NAME = 'items:r:listval_id';
    VAL = COALESCE(V$LISTVAL_ID, V$BLOB_ID);
    SUSPEND;
    TAG_NAME = 'items:r:cost';
    VAL = V$COST;
    SUSPEND;
    TAG_NAME = 'items:r:is_exists';
    VAL = V$IS_EXISTS;
    SUSPEND;
    TAG_NAME = 'items:r:sort_order';
    VAL = V$SORT_ORDER;
    SUSPEND;
    TAG_NAME = 'items:r:color';
    VAL = V$COLOR;
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_OBJECT_CONTENT (
    I$PARENT_ID BIGINT,
    I$PARENT_TYPE_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$TYPE_ID BIGINT,
    I$LEVEL_ID BIGINT NOT NULL,
    I$TAB_ID BIGINT,
    I$USER_ID VARCHAR(40),
    I$FROM_IP VARCHAR(200) = NULL)
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(4000))
AS
DECLARE VARIABLE V$USER_ID BIGINT;
DECLARE VARIABLE V$CAPTION VARCHAR(4000);
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$NUM INTEGER;
DECLARE VARIABLE V$PARAM_ID BIGINT;
DECLARE VARIABLE V$LIST_ID BIGINT;
DECLARE VARIABLE V$LISTVAL_ID BIGINT;
DECLARE VARIABLE V$BLOB_ID BIGINT;
DECLARE VARIABLE V$IS_REQUIRED SMALLINT;
DECLARE VARIABLE V$IS_HISTORY SMALLINT;
DECLARE VARIABLE V$IS_TREEVIEW SMALLINT;
DECLARE VARIABLE V$PARAM_CAPTION VARCHAR(4000);
DECLARE VARIABLE V$HINT_CAPTION VARCHAR(4000);
DECLARE VARIABLE V$SQL VARCHAR(1000);
DECLARE VARIABLE V$EDIT_MASK VARCHAR(200);
DECLARE VARIABLE V$TAG VARCHAR(100);
DECLARE VARIABLE V$COST DOUBLE PRECISION;
DECLARE VARIABLE V$REGION VARCHAR(255);
DECLARE VARIABLE V$DISTRICT VARCHAR(255);
DECLARE VARIABLE V$TOWN VARCHAR(255);
DECLARE VARIABLE V$SETTLEMENT VARCHAR(255);
DECLARE VARIABLE V$STREET VARCHAR(255);
DECLARE VARIABLE V$HOUSE VARCHAR(10);
DECLARE VARIABLE V$LITER VARCHAR(10);
DECLARE VARIABLE V$CORP VARCHAR(10);
DECLARE VARIABLE V$FLAT VARCHAR(10);
DECLARE VARIABLE V$POST_INDEX VARCHAR(20);
DECLARE VARIABLE V$OCATD VARCHAR(11);
DECLARE VARIABLE V$HOUSEGUID VARCHAR(36);
DECLARE VARIABLE V$STREETGUID VARCHAR(36);
DECLARE VARIABLE V$BKG_COLOR INTEGER;
DECLARE VARIABLE V$COLOR INTEGER;
DECLARE VARIABLE V$IS_EXISTS SMALLINT;
DECLARE VARIABLE V$LIST_EDIT_TYPE SMALLINT;
DECLARE VARIABLE V$DO_CHECK SMALLINT;
DECLARE VARIABLE V$DO_CHECK_EVENT SMALLINT;
DECLARE VARIABLE V$BEGIN_GROUP SMALLINT;
DECLARE VARIABLE V$TAB_ID BIGINT;
DECLARE VARIABLE V$TYPE_ID BIGINT;
DECLARE VARIABLE V$IS_ADD SMALLINT;
DECLARE VARIABLE V$IS_COPY SMALLINT;
DECLARE VARIABLE V$IS_CUT SMALLINT;
DECLARE VARIABLE V$IS_LINK SMALLINT;
DECLARE VARIABLE V$IS_FROM_LIST SMALLINT;
DECLARE VARIABLE V$IS_AUTO_CREATE SMALLINT;
DECLARE VARIABLE V$EDIT_TYPE SMALLINT;
DECLARE VARIABLE V$IS_SELECT SMALLINT;
DECLARE VARIABLE V$SORT_ORDER DOUBLE PRECISION;
DECLARE VARIABLE V$IS_TAB_VERTICAL_ALIGNMENT SMALLINT;
DECLARE VARIABLE V$SHOW_ALL_FIELDS SMALLINT;
DECLARE VARIABLE V$RUN_FUNCTION SMALLINT;
DECLARE VARIABLE V$DO_FUNC BIGINT;
DECLARE VARIABLE V$IS_SORT SMALLINT;
DECLARE VARIABLE V$LINK_ID BIGINT;
DECLARE VARIABLE V$LANG_CODE CHAR(2);
DECLARE VARIABLE V$GEN BIGINT;
DECLARE VARIABLE V$MULT BIGINT;
DECLARE VARIABLE V$FC BIGINT;
DECLARE VARIABLE V$MYDATA SMALLINT;
DECLARE VARIABLE V$BUTTON_ID BIGINT;
begin

  V$MYDATA = 0;
  IF(I$LEVEL_ID > 100000) THEN
  BEGIN
    I$LEVEL_ID = I$LEVEL_ID - 100000;
    V$MYDATA = 1;
  END

  -- Проверяем доступ пользователя к запрошенному уровню
  -- !!! временно, в дальнейшем веб-администратор сюда попадать не должен !!!
  IF(I$USER_ID = 'Веб-администратор') THEN V$USER_ID = 1; ELSE V$USER_ID = CAST(I$USER_ID AS BIGINT);

  -- Логгируем доступ к ПД
  -- тут не надо - оно в OBJECT_PARAMS_LIST

  IF(V$MYDATA = 1) THEN
  BEGIN
    -- Просто проверяем наличие пользователя - тут и сотрудники, и ученики, но пока без родителей
    SELECT FIRST 1 U.OBJ_ID, LPG.OBJ_TYPE_ID, U.LANG_CODE
    FROM USERS U
    JOIN LINKS LPG ON LPG.OBJ_ID = U.OBJ_ID AND LPG.PARENT_TYPE_ID IN (2, 211, 9, 187) AND LPG.DATE_DEL IS NULL
    WHERE U.USER_ID = :V$USER_ID AND U.DATE_DEL IS NULL AND U.IS_BLOCKED = 0 AND (U.EXP_DATE IS NULL OR U.EXP_DATE > CURRENT_DATE)
    INTO :V$OBJ_ID, :V$TYPE_ID, :V$LANG_CODE;

    IF(V$OBJ_ID IS NULL OR (V$TYPE_ID = 14 AND I$LEVEL_ID <> 48) OR (V$TYPE_ID = 10 AND I$LEVEL_ID <> 50)) THEN EXCEPTION DATA_ERROR 'У вас нет доступа к данному приложению';
  END
  ELSE
  BEGIN
    SELECT FIRST 1 U.USER_ID, U.LANG_CODE
    FROM USERS U
    JOIN LUSERS LU ON LU.USER_ID = U.USER_ID AND LU.LEVEL_ID = :I$LEVEL_ID
    WHERE U.USER_ID = :V$USER_ID AND U.DATE_DEL IS NULL AND U.IS_BLOCKED = 0 AND (U.EXP_DATE IS NULL OR U.EXP_DATE > CURRENT_DATE)
    INTO :V$OBJ_ID, :V$LANG_CODE;
  END

  IF(V$OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'У вас нет доступа к данному приложению';

  SELECT GEN, MULTIPLIER
  FROM GEN
  INTO :V$GEN, :V$MULT;

  -- В некоторых случаях PARENT_TYPE_ID не приходит, восстанавливаем
  -- например для районного пользователя на уровне региона
  IF(I$PARENT_ID IS NOT NULL AND I$PARENT_TYPE_ID IS NULL) THEN
  BEGIN
    SELECT TYPE_ID
    FROM OBJECTS
    WHERE OBJ_ID = :I$PARENT_ID
    INTO :I$PARENT_TYPE_ID;
  END

  TAG_NAME = 'db_type';
  VAL = (SELECT STATUS FROM OU_LICENCE_TYPE);
  SUSPEND;

  TAG_NAME = 'db_level';
  VAL = (SELECT KEY_VAL FROM KEYS WHERE KEY_CODE = 'LEVEL');
  SUSPEND;

  TAG_NAME = 'obj_id';
  VAL = I$OBJ_ID;
  SUSPEND;

  TAG_NAME = 'is_native';
  IF(I$OBJ_ID IS NULL OR TRUNC(I$OBJ_ID / V$MULT) = V$GEN) THEN VAL = '1'; ELSE VAL = '0';
  SUSPEND;

  -- Для формы зачисления нужно получить уровень образования для выбранного объекта
  -- класс, группа, предварительный прием
  -- тут будет или id по справочнику уровней, или id раздела для этапов
  TAG_NAME = 'edu_level';
  VAL = NULL;
  IF(I$TYPE_ID IN (9, 187)) THEN
  BEGIN
    -- Учебный коллектив
    SELECT V43.LISTVAL_ID
    FROM LINKS LP8
    JOIN LINKS LP7 ON LP7.OBJ_ID = LP8.PARENT_ID AND LP7.PARENT_TYPE_ID = 7 AND LP7.DATE_DEL IS NULL
    JOIN VALL V43 ON V43.OBJ_ID = LP7.PARENT_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0
    WHERE LP8.OBJ_ID = :I$OBJ_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
    INTO :VAL;
  END
  ELSE IF(I$TYPE_ID = 290) THEN
  BEGIN
    -- Предварительный прием
    SELECT LV.PARENT_ID
    FROM VALL V
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V.LISTVAL_ID
    WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 43 AND V.IS_DEL = 0
    INTO :VAL;
  END
  ELSE IF(I$TYPE_ID = 46) THEN
  BEGIN
    -- Возможно это группа профобучения по новой схеме учета ? пока на перспективу
    SELECT V43.LISTVAL_ID
    FROM LINKS LP7
    JOIN VALL V43 ON V43.OBJ_ID = LP7.PARENT_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0
    WHERE LP7.OBJ_ID = :I$OBJ_ID AND LP7.PARENT_TYPE_ID = 7 AND LP7.DATE_DEL IS NULL
    INTO :VAL;
  END
  -- Для групп ОДОД с этапами обучения неактуально
  SUSPEND;

  -- Проверяем наличие доступа к данному объекту в приложении
  -- NULL значит оставить доступ как в токене
  -- Пока только для приложения 48 в режиме личного кабинета, для сотрудника = текущий пользователь
  TAG_NAME = 'role_override';
  VAL = NULL;
  IF(V$MYDATA = 1 AND I$LEVEL_ID IN (48)) THEN
  BEGIN
    SELECT OBJ.TYPE_ID
    FROM OBJECTS OBJ
    WHERE OBJ.OBJ_ID = :I$OBJ_ID
    INTO :V$TYPE_ID;

    IF(V$TYPE_ID = 458) THEN
    BEGIN
      IF(V$OBJ_ID = I$PARENT_ID) THEN VAL = 1;
    END
  END
  SUSPEND;

  -- Если TAB_ID указан, возвращаем данные для него. Если нет, возвращаем данные для основной страницы
  TAG_NAME = 'tabs';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'tabs::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
    SELECT TAB_ID, TAB_NUM, TAB_CAPTION
    FROM OBJECT_TABS_LIST(:I$TYPE_ID, :I$LEVEL_ID, :V$USER_ID, :I$PARENT_TYPE_ID)
    INTO :V$TAB_ID, :V$NUM, :V$CAPTION
  DO
  BEGIN
    TAG_NAME = 'tabs:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'tabs:r:tab_id';
    VAL = V$TAB_ID;
    SUSPEND;
    TAG_NAME = 'tabs:r:tab_num';
    VAL = V$NUM;
    SUSPEND;
    TAG_NAME = 'tabs:r:tab_caption';
    VAL = V$CAPTION;
    SUSPEND;
    -- Открываем первую закладку, если не знаем какую
    IF(I$TAB_ID IS NULL) THEN I$TAB_ID = V$TAB_ID;
  END

  TAG_NAME = 'tab_id';
  VAL = I$TAB_ID;
  SUSPEND;

  -- Параметры
  TAG_NAME = 'params';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'params::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
    -- DO_FUNC, RUN_SQL пропускаем
    SELECT OBJ_ID, PARAM_ID, PARAM_TYPE, LIST_ID, LISTVAL_ID, BLOB_ID, IS_REQUIRED, IS_HISTORY, IS_TREEVIEW,
      PARAM_CAPTION, HINT_CAPTION, EDIT_MASK, IS_AUTO_CREATE, TAG, EDIT_TYPE, VAL, COST,
      REGION, DISTRICT, TOWN, SETTLEMENT, STREET, HOUSE, LITER, CORP, FLAT, POST_INDEX, OCATD, HOUSEGUID, STREETGUID,
      BKG_COLOR, COLOR, IS_EXISTS, LIST_EDIT_TYPE, TAB_ID, "DO_CHECK", DO_CHECK_EVENT, BEGIN_GROUP, DO_FUNC
    FROM OBJECT_PARAMS_LIST(:V$USER_ID, :I$OBJ_ID, :I$LEVEL_ID, :I$TAB_ID, :I$TYPE_ID, 0, :I$PARENT_ID, :I$FROM_IP)
    INTO :V$OBJ_ID, :V$PARAM_ID, :V$NUM, :V$LIST_ID, :V$LISTVAL_ID, :V$BLOB_ID, :V$IS_REQUIRED, :V$IS_HISTORY, :V$IS_TREEVIEW,
      :V$PARAM_CAPTION, :V$HINT_CAPTION, :V$EDIT_MASK, :V$IS_AUTO_CREATE, :V$TAG, :V$EDIT_TYPE, :V$CAPTION, :V$COST,
      :V$REGION, :V$DISTRICT, :V$TOWN, :V$SETTLEMENT, :V$STREET, :V$HOUSE, :V$LITER, :V$CORP, :V$FLAT, :V$POST_INDEX, :V$OCATD, :V$HOUSEGUID, :V$STREETGUID,
      :V$BKG_COLOR, :V$COLOR, :V$IS_EXISTS, :V$LIST_EDIT_TYPE, :V$TAB_ID, :V$DO_CHECK, :V$DO_CHECK_EVENT, :V$BEGIN_GROUP, :V$FC
  DO
  BEGIN
      TAG_NAME = 'params:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'params:r:obj_id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'params:r:param_id';
      VAL = V$PARAM_ID;
      SUSPEND;
      TAG_NAME = 'params:r:param_type';
      VAL = V$NUM;
      SUSPEND;
      TAG_NAME = 'params:r:list_id';
      VAL = V$LIST_ID;
      SUSPEND;
      TAG_NAME = 'params:r:listval_id';
      VAL = V$LISTVAL_ID;
      SUSPEND;
      TAG_NAME = 'params:r:blob_id';
      VAL = V$BLOB_ID;
      SUSPEND;
      TAG_NAME = 'params:r:is_required';
      VAL = V$IS_REQUIRED;
      SUSPEND;
      TAG_NAME = 'params:r:is_history';
      VAL = V$IS_HISTORY;
      SUSPEND;
      TAG_NAME = 'params:r:is_treeview';
      VAL = V$IS_TREEVIEW;
      SUSPEND;
      TAG_NAME = 'params:r:param_caption';
      VAL = V$PARAM_CAPTION;
      SUSPEND;
      TAG_NAME = 'params:r:hint_caption';
      VAL = V$HINT_CAPTION;
      SUSPEND;
      TAG_NAME = 'params:r:edit_mask';
      VAL = V$EDIT_MASK;
      SUSPEND;
      TAG_NAME = 'params:r:tag';
      VAL = V$TAG;
      SUSPEND;
      -- Разрешение редактирования полей ОУ и документов на уровне региона, созданных в нем же
      -- только для суперадмина
      IF(I$LEVEL_ID = 117 AND V$EDIT_TYPE = 0 AND V$OBJ_ID < 101000000000 AND (V$TAB_ID IN (2, 3, 10) OR I$TYPE_ID = 17)
        AND V$NUM NOT IN (10, 17, 19) AND I$USER_ID = 'Веб-администратор') THEN V$EDIT_TYPE = 1;
      TAG_NAME = 'params:r:edit_type';
      VAL = V$EDIT_TYPE;
      SUSPEND;
      TAG_NAME = 'params:r:cost';
      VAL = V$COST;
      SUSPEND;
      TAG_NAME = 'params:r:func';
      VAL = V$FC;
      SUSPEND;

      TAG_NAME = 'params:r:val';
      -- Для полей DATE, TIME, DATETIME преобразуем в ISO
      IF(V$NUM = 3 AND V$CAPTION IS NOT NULL AND V$CAPTION <> '') THEN
      BEGIN
        -- DD.MM.YYYY HH:NN
        V$CAPTION = SUBSTRING(V$CAPTION FROM 7 FOR 4) || '-' || SUBSTRING(V$CAPTION FROM 4 FOR 2) || '-' || SUBSTRING(V$CAPTION FROM 1 FOR 2) || 'T' ||
          SUBSTRING(V$CAPTION FROM 12 FOR 2) || ':' || SUBSTRING(V$CAPTION FROM 15 FOR 2) || ':00';
      END
      ELSE IF(V$NUM = 4 AND V$CAPTION IS NOT NULL AND V$CAPTION <> '') THEN
      BEGIN
        V$CAPTION = SUBSTRING(V$CAPTION FROM 7 FOR 4) || '-' || SUBSTRING(V$CAPTION FROM 4 FOR 2) || '-' || SUBSTRING(V$CAPTION FROM 1 FOR 2);
      END
      ELSE IF(V$NUM = 5 AND V$CAPTION IS NOT NULL AND V$CAPTION <> '') THEN
      BEGIN
        V$CAPTION = V$CAPTION || ':00';
      END
      VAL = V$CAPTION;
      SUSPEND;

      TAG_NAME = 'params:r:bkg_color';
      VAL = V$BKG_COLOR;
      SUSPEND;
      TAG_NAME = 'params:r:color';
      VAL = V$COLOR;
      SUSPEND;
      TAG_NAME = 'params:r:is_exists';
      VAL = V$IS_EXISTS;
      SUSPEND;
      TAG_NAME = 'params:r:list_edit_type';
      VAL = V$LIST_EDIT_TYPE;
      SUSPEND;
      TAG_NAME = 'params:r:tab_id';
      VAL = V$TAB_ID;
      SUSPEND;
      TAG_NAME = 'params:r:do_check';
      VAL = V$DO_CHECK;
      SUSPEND;
      TAG_NAME = 'params:r:do_check_event';
      VAL = V$DO_CHECK_EVENT;
      SUSPEND;
      TAG_NAME = 'params:r:begin_group';
      VAL = V$BEGIN_GROUP;
      SUSPEND;

      -- Количество знаков для FLOAT
      -- Координаты здания
      IF(V$PARAM_ID IN (3457, 3458)) THEN
      BEGIN
        TAG_NAME = 'params:r:digits';
        VAL = 6;
        SUSPEND;
      END
  END

  -- Вложенные объекты - для закладки по-умолчанию если TAB_ID = NULL, или для указанной закладки
  TAG_NAME = 'grids';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'grids::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
    SELECT OBJ_ID, TYPE_ID, TYPE_CAPTION, IS_ADD, IS_COPY, IS_CUT, IS_LINK, IS_FROM_LIST, RUN_SQL, DO_FUNC, IS_AUTO_CREATE,
      EDIT_TYPE, IS_SELECT, SORT_ORDER, IS_TAB_VERTICAL_ALIGNMENT, SHOW_ALL_FIELDS, RUN_FUNCTION
    FROM OBJECT_GRIDS_LIST(:V$USER_ID, :I$TYPE_ID, :I$LEVEL_ID, :I$TAB_ID, :I$OBJ_ID, :I$PARENT_ID)
    INTO :V$OBJ_ID, :V$TYPE_ID, :V$CAPTION, :V$IS_ADD, :V$IS_COPY, :V$IS_CUT, :V$IS_LINK, :V$IS_FROM_LIST, :V$SQL, :V$DO_FUNC, :V$IS_AUTO_CREATE,
      :V$EDIT_TYPE, :V$IS_SELECT, :V$SORT_ORDER, :V$IS_TAB_VERTICAL_ALIGNMENT, :V$SHOW_ALL_FIELDS, :V$RUN_FUNCTION
  DO
  BEGIN
      TAG_NAME = 'grids:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'grids:r:obj_id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'grids:r:type_id';
      VAL = V$TYPE_ID;
      SUSPEND;
      TAG_NAME = 'grids:r:type_caption';
      VAL = V$CAPTION;
      SUSPEND;
      -- Строка из 11 символов
      TAG_NAME = 'grids:r:flags';
      VAL = V$IS_ADD || V$IS_COPY || V$IS_CUT || V$IS_LINK || V$IS_FROM_LIST || V$DO_FUNC || V$IS_AUTO_CREATE || V$IS_SELECT || V$IS_TAB_VERTICAL_ALIGNMENT || V$SHOW_ALL_FIELDS || V$RUN_FUNCTION;
      SUSPEND;
      TAG_NAME = 'grids:r:edit_type';
      VAL = V$EDIT_TYPE;
      SUSPEND;
      -- TAG_NAME = 'grids:r:run_sql';
      TAG_NAME = 'grids:r:sort_order';
      VAL = V$SORT_ORDER;
      SUSPEND;

      -- Список столбцов (строк в вертикальном режиме)
      TAG_NAME = 'grids:r:params';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'grids:r:params::json&colon;array';
      VAL = NULL;
      SUSPEND;
      FOR
          SELECT PARAM_ID, PARAM_TYPE, LIST_ID, IS_SORT, IS_REQUIRED, IS_HISTORY, PARAM_CAPTION, SIZE_CAPTION, HINT_CAPTION, DO_FUNC,
              EDIT_MASK, RUN_SQL, IS_AUTO_CREATE, TAG, EDIT_TYPE, BKG_COLOR, COLOR, LIST_EDIT_TYPE, DO_CHECK, DO_CHECK_EVENT, BEGIN_GROUP
          FROM OBJECT_GRID_PARAMS(:V$USER_ID, :V$TYPE_ID, :I$LEVEL_ID, :V$IS_SELECT - :V$SHOW_ALL_FIELDS, 0, :I$PARENT_ID, 0)
          INTO :V$PARAM_ID, :V$NUM, :V$LIST_ID, :V$IS_SORT, :V$IS_REQUIRED, :V$IS_HISTORY, :V$PARAM_CAPTION, :V$CAPTION, :V$HINT_CAPTION, :V$DO_FUNC,
              :V$EDIT_MASK, :V$SQL, :V$IS_AUTO_CREATE, :V$TAG, :V$EDIT_TYPE, :V$BKG_COLOR, :V$COLOR, :V$LIST_EDIT_TYPE, :V$DO_CHECK, :V$DO_CHECK_EVENT, :V$BEGIN_GROUP
      DO
      BEGIN
          TAG_NAME = 'grids:r:params:r';
          VAL = NULL;
          SUSPEND;
          TAG_NAME = 'grids:r:params:r:param_id';
          VAL = V$PARAM_ID;
          SUSPEND;
          TAG_NAME = 'grids:r:params:r:param_type';
          VAL = V$NUM;
          SUSPEND;
          TAG_NAME = 'grids:r:params:r:list_id';
          VAL = V$LIST_ID;
          SUSPEND;
          TAG_NAME = 'grids:r:params:r:caption';
          VAL = V$PARAM_CAPTION;
          SUSPEND;
          TAG_NAME = 'grids:r:params:r:size_caption';
          VAL = V$CAPTION;
          SUSPEND;
          TAG_NAME = 'grids:r:params:r:hint';
          VAL = V$HINT_CAPTION;
          SUSPEND;
          TAG_NAME = 'grids:r:params:r:edit_mask';
          VAL = V$EDIT_MASK;
          SUSPEND;
          -- SQL
          TAG_NAME = 'grids:r:params:r:tag';
          VAL = V$TAG;
          SUSPEND;
          -- Разрешаем редактирование на уровне региона
          IF(I$LEVEL_ID = 117 AND V$EDIT_TYPE = 0 AND V$OBJ_ID < 101000000000 AND V$TAB_ID IN (2, 3, 10) AND V$NUM NOT IN (10, 17, 19) AND I$USER_ID = 'Веб-администратор') THEN V$EDIT_TYPE = 1;
          TAG_NAME = 'grids:r:params:r:edit_type';
          VAL = V$EDIT_TYPE;
          SUSPEND;
          TAG_NAME = 'grids:r:params:r:list_edit_type';
          VAL = V$LIST_EDIT_TYPE;
          SUSPEND;
          TAG_NAME = 'grids:r:params:r:bkg_color';
          VAL = V$BKG_COLOR;
          SUSPEND;
          TAG_NAME = 'grids:r:params:r:color';
          VAL = V$COLOR;
          SUSPEND;
          -- Флаги, 8 символов
          TAG_NAME = 'grids:r:params:r:flags';
          VAL = V$IS_SORT || V$IS_REQUIRED || V$IS_HISTORY || V$DO_FUNC || V$IS_AUTO_CREATE || V$DO_CHECK || V$DO_CHECK_EVENT || V$BEGIN_GROUP;
          SUSPEND;
      END

      -- Объекты в гриде, VAL2 и детали адреса тут не нужны
      TAG_NAME = 'grids:r:items';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'grids:r:items::json&colon;array';
      VAL = NULL;
      SUSPEND;
      FOR
          SELECT LINK_ID, OBJ_ID, PARAM_ID, LIST_ID, VAL, COST, BLOB_ID, LISTVAL_ID, IS_EXISTS, SORT_ORDER, COLOR
          FROM OBJECT_GRID_VALS(:I$PARENT_ID, :I$OBJ_ID, :V$TYPE_ID, :I$LEVEL_ID, :V$IS_SELECT - :V$SHOW_ALL_FIELDS, 0, :V$USER_ID, 0)
          INTO :V$LINK_ID, :V$OBJ_ID, :V$PARAM_ID, :V$LIST_ID, :V$CAPTION, :V$COST, :V$BLOB_ID, :V$LISTVAL_ID, :V$IS_EXISTS, :V$SORT_ORDER, :V$COLOR
      DO
      BEGIN
          TAG_NAME = 'grids:r:items:r';
          VAL = NULL;
          SUSPEND;
          TAG_NAME = 'grids:r:items:r:link_id';
          VAL = V$LINK_ID;
          SUSPEND;
          TAG_NAME = 'grids:r:items:r:obj_id';
          VAL = V$OBJ_ID;
          SUSPEND;
          TAG_NAME = 'grids:r:items:r:param_id';
          VAL = V$PARAM_ID;
          SUSPEND;
          TAG_NAME = 'grids:r:items:r:value';
          VAL = V$CAPTION;
          SUSPEND;
          TAG_NAME = 'grids:r:items:r:listval_id';
          VAL = COALESCE(V$LISTVAL_ID, V$BLOB_ID);
          SUSPEND;
          TAG_NAME = 'grids:r:items:r:cost';
          VAL = V$COST;
          SUSPEND;
          TAG_NAME = 'grids:r:items:r:is_exists';
          VAL = V$IS_EXISTS;
          SUSPEND;
          TAG_NAME = 'grids:r:items:r:sort_order';
          VAL = V$SORT_ORDER;
          SUSPEND;
          TAG_NAME = 'grids:r:items:r:color';
          VAL = V$COLOR;
          SUSPEND;
      END
  END

  -- Фреймы
  TAG_NAME = 'frames';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'frames::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
    SELECT F.FRAME_CLASS, F.CAPTION
    FROM OBJECT_FRAMES F
    WHERE F.IS_DEL = 0 AND (F.TAB_ID = :I$TAB_ID OR F.TAB_ID IS NULL OR :I$TAB_ID IS NULL) AND F.TYPE_ID = :I$TYPE_ID
      AND ((F.PARENT_TYPE_ID IS NULL AND :I$PARENT_TYPE_ID IS NULL) OR F.PARENT_TYPE_ID = :I$PARENT_TYPE_ID)
      AND (F.LEVEL_ID IS NULL OR F.LEVEL_ID = :I$LEVEL_ID)
    INTO :V$PARAM_CAPTION, :V$CAPTION
  DO
  BEGIN
    TAG_NAME = 'frames:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'frames:r:class';
    VAL = V$PARAM_CAPTION;
    SUSPEND;
    TAG_NAME = 'frames:r:caption';
    VAL = V$CAPTION;
    SUSPEND;
  END

  -- Панели кнопок и кнопки
  V$LANG_CODE = 'RU';
  TAG_NAME = 'buttons';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'buttons::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
      SELECT B.DO_FUNC, B.ICON_ID, R.VAL, B.SORT_ORDER, B.BUTTON_ID
      FROM LTYPES LT
      JOIN BARS BB ON BB.BAR_ID = LT.BAR_ID AND BB.IS_DEL = 0
      JOIN BARBUTTONS B ON B.IS_DEL = 0 AND B.BAR_ID = BB.BAR_ID
      JOIN RES R ON R.RES_ID = B.RES_ID AND R.LANG_CODE = :V$LANG_CODE
      WHERE LT.IS_DEL = 0 AND LT.LEVEL_ID = :I$LEVEL_ID AND LT.TYPE_ID = :I$TYPE_ID AND LT.EDIT_TYPE >= 0
      UNION
      SELECT B.DO_FUNC, B.ICON_ID, R.VAL, B.SORT_ORDER, B.BUTTON_ID
      FROM LTYPES LT
      JOIN LBUTTONS LB ON LB.IS_DEL = 0 AND LB.LEVEL_ID = LT.LEVEL_ID AND LB.OBJ_TYPE_ID = LT.TYPE_ID
        AND (LB.PARENT_TYPE_ID = :I$PARENT_TYPE_ID OR (LB.PARENT_TYPE_ID = -1 AND :I$PARENT_TYPE_ID IS NULL))
      JOIN BARBUTTONS B ON B.IS_DEL = 0 AND B.BUTTON_ID = LB.BUTTON_ID
      JOIN RES R ON R.RES_ID = B.RES_ID AND R.LANG_CODE = :V$LANG_CODE
      WHERE LT.IS_DEL = 0 AND LT.LEVEL_ID = :I$LEVEL_ID AND LT.TYPE_ID = :I$TYPE_ID AND LT.EDIT_TYPE >= 0
      ORDER BY 4
      INTO :V$PARAM_CAPTION, :V$OBJ_ID, :V$CAPTION, :V$TAG, :V$BUTTON_ID
  DO
  BEGIN
      -- На уровне региона некоторые кнопки доступны только суперадмину
      IF(I$LEVEL_ID = 117 AND V$BUTTON_ID = 226 AND (I$OBJ_ID > 101000000000 OR I$USER_ID <> 'Веб-администратор')) THEN V$PARAM_CAPTION = NULL;
      -- Кнопку сброса пароля родителя делаем только в 369
      IF(V$GEN <> 903 AND V$BUTTON_ID = 204) THEN V$PARAM_CAPTION = NULL;

      IF(V$PARAM_CAPTION IS NOT NULL) THEN
      BEGIN
          TAG_NAME = 'buttons:r';
          VAL = NULL;
          SUSPEND;
          TAG_NAME = 'buttons:r:fname';
          VAL = V$PARAM_CAPTION;
          SUSPEND;
          TAG_NAME = 'buttons:r:icon';
          VAL = V$OBJ_ID;
          SUSPEND;
          TAG_NAME = 'buttons:r:caption';
          VAL = V$CAPTION;
          SUSPEND;
      END
  END
  -- Для классов ОВЗ выдаем кнопку ручного перевода в движении обучающихся
  IF(I$TYPE_ID = 9 AND I$LEVEL_ID = 23 AND (SELECT LISTVAL_ID FROM VALL WHERE OBJ_ID = :I$OBJ_ID AND PARAM_ID = 592 AND IS_DEL = 0) <> 197) THEN
  BEGIN
    TAG_NAME = 'buttons:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'buttons:r:fname';
    VAL = 'EXTERNAT_STAGE_CHANGER';
    SUSPEND;
    TAG_NAME = 'buttons:r:icon';
    VAL = 'USER_MOVE';
    SUSPEND;
    TAG_NAME = 'buttons:r:caption';
    VAL = 'Перевод на следующий этап обучения';
    SUSPEND;
  END

  -- Отчеты и их параметры
  TAG_NAME = 'reports';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'reports::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
    SELECT R.REPORT_ID, LR.GROUP_NAME, RR.VAL
    FROM LREPORTS LR
    JOIN REPORTS R ON R.IS_DEL = 0 AND R.REPORT_ID = LR.REPORT_ID AND R.TYPE_ID = :I$TYPE_ID
    JOIN RES RR ON RR.RES_ID = R.RES_ID AND RR.LANG_CODE = 'RU'
    WHERE LR.LEVEL_ID = :I$LEVEL_ID AND LR.IS_DEL = 0
    ORDER BY R.SORT_ORDER
    INTO :V$OBJ_ID, :V$HINT_CAPTION, :V$CAPTION
  DO
  BEGIN
    TAG_NAME = 'reports:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'reports:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'reports:r:group';
    VAL = V$HINT_CAPTION;
    SUSPEND;
    TAG_NAME = 'reports:r:name';
    VAL = V$CAPTION;
    SUSPEND;
    TAG_NAME = 'reports:r:params::json&colon;array';
    VAL = '1';
    SUSPEND;
    FOR
      SELECT P.RPARAM, P.PARAM_TYPE, P.LIST_ID, P.IS_REQUIRED, R.VAL
      FROM RPARAMS P
      JOIN RES R ON R.RES_ID = P.RES_ID AND R.LANG_CODE = 'RU'
      WHERE P.IS_DEL = 0 AND P.REPORT_ID = :V$OBJ_ID
      INTO :V$DISTRICT, :V$TYPE_ID, :V$LIST_ID, :V$BLOB_ID, :V$CAPTION
    DO
    BEGIN
      TAG_NAME = 'reports:r:params:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'reports:r:params:r:id';
      VAL = V$DISTRICT;
      SUSPEND;
      TAG_NAME = 'reports:r:params:r:type';
      VAL = V$TYPE_ID;
      SUSPEND;
      TAG_NAME = 'reports:r:params:r:list_id';
      VAL = V$LIST_ID;
      SUSPEND;
      TAG_NAME = 'reports:r:params:r:required';
      VAL = V$BLOB_ID;
      SUSPEND;
      TAG_NAME = 'reports:r:params:r:name';
      VAL = V$CAPTION;
      SUSPEND;
    END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_OBJECT_CONTEXT (
    I$PARENT_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$LEVEL_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$USER_ID BIGINT;
DECLARE VARIABLE V$PARENT_TYPE_ID BIGINT;
DECLARE VARIABLE V$OBJ_TYPE_ID BIGINT;
DECLARE VARIABLE V$TYPE_ID BIGINT;
DECLARE VARIABLE V$CAPTION VARCHAR(1000);
DECLARE VARIABLE V$GROUP_NAME VARCHAR(1000);
DECLARE VARIABLE V$EDIT_TYPE SMALLINT;
DECLARE VARIABLE V$LEVEL INTEGER;
DECLARE VARIABLE V$A1 INTEGER;
DECLARE VARIABLE V$A2 INTEGER;
DECLARE VARIABLE V$IS_CABINET SMALLINT;
DECLARE VARIABLE V$PERSON_ID BIGINT;
DECLARE VARIABLE V$STATUS VARCHAR(2);
DECLARE VARIABLE V$ID BIGINT;
begin

  V$IS_CABINET = 0;
  IF(I$LEVEL_ID > 100000) THEN
  BEGIN
    I$LEVEL_ID = I$LEVEL_ID - 100000;
    V$IS_CABINET = 1;
  END

  IF(I$USER_ID = 'Веб-администратор') THEN V$USER_ID = 1; ELSE V$USER_ID = CAST(I$USER_ID AS BIGINT);

  -- Внимание: если OBJ_ID пустой, считаем что хотим добавить в корень дерева
  SELECT TYPE_ID
  FROM OBJECTS
  WHERE OBJ_ID = :I$PARENT_ID
  INTO :V$PARENT_TYPE_ID;

  SELECT TYPE_ID
  FROM OBJECTS
  WHERE OBJ_ID = :I$OBJ_ID
  INTO :V$OBJ_TYPE_ID;

  V$STATUS = (SELECT STATUS FROM OU_LICENCE_TYPE);

  SELECT KEY_VAL FROM KEYS WHERE KEY_CODE = 'LEVEL' INTO :V$LEVEL;

  IF(I$OBJ_ID IS NOT NULL AND V$OBJ_TYPE_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Объект не найден или был удален другим пользователем';

  -- Можно ли удалять сам объект
  TAG_NAME = 'can_delete';
  IF(V$PARENT_TYPE_ID IS NULL) THEN
  BEGIN
    SELECT FIRST 1 1, 0
    FROM USERS U
    JOIN LUSERS LU ON LU.USER_ID = U.USER_ID AND LU.LEVEL_ID = :I$LEVEL_ID AND LU.READ_ONLY = 0
    JOIN LTYPES LT ON LT.TYPE_ID = :V$OBJ_TYPE_ID AND LT.LEVEL_ID = LU.LEVEL_ID AND LT.EDIT_TYPE = 1
    WHERE U.USER_ID = :V$USER_ID AND U.DATE_DEL IS NULL AND U.IS_BLOCKED = 0 AND (U.EXP_DATE IS NULL OR U.EXP_DATE >= CURRENT_DATE)
    INTO :V$A1, :V$A2;
  END
  ELSE
  BEGIN
    SELECT FIRST 1 P.IS_ADD, P.IS_INTERNAL_ADD
    FROM USERS U
    JOIN LUSERS LU ON LU.USER_ID = U.USER_ID AND LU.LEVEL_ID = :I$LEVEL_ID AND LU.READ_ONLY = 0
    JOIN PARENTS P ON P.TYPE_ID = :V$PARENT_TYPE_ID AND P.CHILD_ID = :V$OBJ_TYPE_ID AND P.IS_DEL = 0 AND P.TAB_ID IS NULL
    JOIN TYPES T ON T.TYPE_ID = P.CHILD_ID AND T.IS_DEL = 0
    JOIN LTYPES LT ON LT.TYPE_ID = T.TYPE_ID AND LT.LEVEL_ID = LU.LEVEL_ID AND LT.EDIT_TYPE = 1
    WHERE U.USER_ID = :V$USER_ID AND U.DATE_DEL IS NULL AND U.IS_BLOCKED = 0 AND (U.EXP_DATE IS NULL OR U.EXP_DATE >= CURRENT_DATE)
    INTO :V$A1, :V$A2;
  END

  -- При работе в личном кабинете юзер может добавлять или удалять папки аттестации лично для себя
  -- даже если у него нет доступа к самому приложению или стоит доступ RO
  IF(V$OBJ_TYPE_ID IN (14, 458, 459) AND I$LEVEL_ID IN (48)) THEN
  BEGIN
    IF(V$OBJ_TYPE_ID = 14) THEN V$PERSON_ID = I$OBJ_ID;
    ELSE IF(V$OBJ_TYPE_ID = 458) THEN V$PERSON_ID = I$PARENT_ID;
    -- Для критерия аттестации надо подняться на уровень выше
    IF(V$OBJ_TYPE_ID = 459) THEN
    SELECT FIRST 1 LP14.PARENT_ID
    FROM LINKS LP14
    WHERE LP14.OBJ_ID = :I$PARENT_ID AND LP14.PARENT_TYPE_ID = 14 AND LP14.DATE_DEL IS NULL
    INTO :V$PERSON_ID;

    IF(EXISTS(
      SELECT FIRST 1 1
      FROM USERS U
      WHERE U.USER_ID = :V$USER_ID AND U.DATE_DEL IS NULL AND U.IS_BLOCKED = 0 AND (U.EXP_DATE IS NULL OR U.EXP_DATE >= CURRENT_DATE) AND U.OBJ_ID = :V$PERSON_ID
    ))
    THEN V$A1 = 1;
  END
  -- Разрешить удаление района и ОУ в региональной базе, приложение Импорт
  IF(V$PARENT_TYPE_ID = 112 AND V$OBJ_TYPE_ID = 111 AND I$LEVEL_ID = 30 AND I$USER_ID = 'Веб-администратор') THEN V$A1 = 1;
  IF(V$PARENT_TYPE_ID = 111 AND V$OBJ_TYPE_ID IN (2, 124) AND I$LEVEL_ID = 30 AND I$USER_ID = 'Веб-администратор') THEN V$A1 = 1;

  VAL = 0;
  IF(V$A1 = 1) THEN VAL = 1;
  ELSE IF(V$A2 = 1) THEN
  BEGIN
    -- Обучающиеcя - только предварительный прием
    IF(V$PARENT_TYPE_ID = 290 AND V$OBJ_TYPE_ID = 10) THEN VAL = 1;
    -- Родители - всегда
    ELSE IF(V$PARENT_TYPE_ID = 10 AND V$OBJ_TYPE_ID = 20) THEN VAL = 1;
    -- Услуги ГЗ
    ELSE IF(V$PARENT_TYPE_ID = 441 AND V$OBJ_TYPE_ID = 442) THEN VAL = 1;
    -- Остальные - никогда
    ELSE VAL = 0;
  END
  -- Дополнение - если удалять нельзя по правилам, разрешаем удаление второгодников в классе ГИА
  IF(VAL = '0') THEN
  BEGIN
    IF(V$PARENT_TYPE_ID = 125 AND V$OBJ_TYPE_ID = 10) THEN VAL = 1;
  END
  SUSPEND;

  -- Какие типы можно добавлять в данном узле (только когда тыкаем по существующему объекту)
  TAG_NAME = 'types';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'types::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
      SELECT T.TYPE_ID, R.VAL, LT.EDIT_TYPE
      FROM USERS U
      JOIN LUSERS LU ON LU.USER_ID = U.USER_ID AND LU.LEVEL_ID = :I$LEVEL_ID AND LU.READ_ONLY = 0
      JOIN PARENTS P ON P.TYPE_ID = :V$OBJ_TYPE_ID AND P.IS_ADD = 1 AND P.IS_DEL = 0 AND P.TAB_ID IS NULL
      JOIN TYPES T ON T.TYPE_ID = P.CHILD_ID AND T.IS_DEL = 0
      JOIN RES R ON R.RES_ID = T.RES_ID AND R.LANG_CODE = 'RU'
      JOIN LTYPES LT ON LT.TYPE_ID = T.TYPE_ID AND LT.LEVEL_ID = LU.LEVEL_ID AND LT.EDIT_TYPE >= 0
      WHERE U.USER_ID = :V$USER_ID AND U.DATE_DEL IS NULL AND U.IS_BLOCKED = 0 AND (U.EXP_DATE IS NULL OR U.EXP_DATE >= CURRENT_DATE)
      -- Добавление в корень
      UNION
      SELECT T.TYPE_ID, R.VAL, LT.EDIT_TYPE
      FROM USERS U
      JOIN LUSERS LU ON LU.USER_ID = U.USER_ID AND LU.LEVEL_ID = :I$LEVEL_ID AND LU.READ_ONLY = 0
      JOIN TYPES T ON T.TYPE_ID = IIF(:V$LEVEL = 1, 2, IIF(:V$LEVEL = 2, 111, 112)) AND T.IS_DEL = 0
      JOIN RES R ON R.RES_ID = T.RES_ID AND R.LANG_CODE = 'RU'
      JOIN LTYPES LT ON LT.TYPE_ID = T.TYPE_ID AND LT.LEVEL_ID = LU.LEVEL_ID AND LT.EDIT_TYPE >= 0
      WHERE U.USER_ID = :V$USER_ID AND U.DATE_DEL IS NULL AND U.IS_BLOCKED = 0 AND (U.EXP_DATE IS NULL OR U.EXP_DATE >= CURRENT_DATE) AND :I$PARENT_ID IS NULL AND :I$OBJ_ID IS NULL
      -- Рядовой сотрудник без доступа, но в личном кабинете - только папка аттестации и критерии
      UNION
      SELECT T.TYPE_ID, R.VAL, 1
      FROM USERS U
      JOIN PARENTS P ON P.TYPE_ID = :V$OBJ_TYPE_ID AND P.IS_ADD = 1 AND P.IS_DEL = 0 AND P.TAB_ID IS NULL AND P.CHILD_ID IN (458, 459)
      JOIN TYPES T ON T.TYPE_ID = P.CHILD_ID AND T.IS_DEL = 0
      JOIN RES R ON R.RES_ID = T.RES_ID AND R.LANG_CODE = 'RU'
      WHERE U.USER_ID = :V$USER_ID AND U.DATE_DEL IS NULL AND U.IS_BLOCKED = 0 AND (U.EXP_DATE IS NULL OR U.EXP_DATE >= CURRENT_DATE)
        AND :V$IS_CABINET = 1 AND U.OBJ_ID = :V$PERSON_ID AND :I$LEVEL_ID IN (48)
      ORDER BY 2
      INTO :V$TYPE_ID, :V$CAPTION, :V$EDIT_TYPE
  DO
  BEGIN
    -- Ограничения для классов-экстернатов - только в разделе общего образования
    IF(V$TYPE_ID = 187 AND NOT EXISTS(
      SELECT FIRST 1 1
      FROM VALL V43
      WHERE V43.OBJ_ID = :I$PARENT_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0 AND V43.LISTVAL_ID IN (22, 26, 27)
    ))
    THEN
      V$TYPE_ID = NULL;
    -- Классы ГИА - только в разделе ГИА (изменения вступают в силу только в Мульти-Параграфе)
    IF(I$LEVEL_ID = 533 AND V$TYPE_ID = 125 AND V$PARENT_TYPE_ID <> 502) THEN V$TYPE_ID = NULL;
    -- Обычные и новые учебные коллективы - не даем в разделе ГИА
    IF(V$TYPE_ID IN (9, 403) AND V$PARENT_TYPE_ID = 502) THEN V$TYPE_ID = NULL;
    -- Уровень обучения можно добавлять только в самой ОУ и в подразделении ОДОД, в других подразделениях нельзя
    -- временно вообще запрещаем добавлять в подразделениях любых видов
    IF(V$TYPE_ID = 7 AND V$OBJ_TYPE_ID = 211 AND V$STATUS = 'S')
    THEN
      V$TYPE_ID = NULL;
    -- Этап обучения - не даем добавлять в дополнительном образовании и профобучении в мультипараграфе
    -- но оставляем в старом Параграф СПО
    IF(V$TYPE_ID = 8 AND V$STATUS = 'S' AND EXISTS(
      SELECT FIRST 1 1
      FROM VALL V43
      WHERE V43.OBJ_ID = :I$OBJ_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0 AND V43.LISTVAL_ID IN (13128, 13129, 13131)
    ))
    THEN
      V$TYPE_ID = NULL;
    -- Группы (кружки, ГПД) - в разделах ДО, ГПД и профобучения
    -- 86 = раздел, старая схема
    -- 500 = каталог ГПД
    IF(V$TYPE_ID = 46 AND NOT (V$OBJ_TYPE_ID IN (86, 500) OR EXISTS(
      SELECT FIRST 1 1
      FROM VALL V43
      WHERE V43.OBJ_ID = :I$OBJ_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0 AND V43.LISTVAL_ID IN (13128, 13129, 13131)
    )))
    THEN
      V$TYPE_ID = NULL;
    -- Группы ОДОД с этапностью - только в разделе ДО
    IF(V$TYPE_ID = 242 AND I$LEVEL_ID = 533 AND NOT EXISTS(
      SELECT FIRST 1 1
      FROM VALL V43
      WHERE V43.OBJ_ID = :I$OBJ_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0 AND V43.LISTVAL_ID = 13128
    ))
    THEN
      V$TYPE_ID = NULL;
    -- Разделы отчетов
    IF (V$TYPE_ID = 512) THEN
    BEGIN
      -- можем добавлять объект монторинг талантов (512) только к разделу отчетов (511), у которого тип = "Мониторинг талантов"
      IF (V$PARENT_TYPE_ID IN (2, 111, 112)) THEN
      BEGIN
        V$TYPE_ID = NULL;
      END
      ELSE IF (V$PARENT_TYPE_ID = 511) THEN
      BEGIN
        SELECT LISTVAL_ID FROM VALL WHERE OBJ_ID = :I$OBJ_ID AND PARAM_ID = 3510 AND IS_DEL = 0 INTO :V$ID;
        V$TYPE_ID = IIF(V$ID = 18578, V$TYPE_ID, NULL);
      END
    END

    IF(V$STATUS = 'S' AND V$TYPE_ID = 242) THEN V$CAPTION = 'Объединение, группа (c этапами обучения)';
    ------------------------------------------
    -- Учитываем дополнительные ограничения
    IF(V$TYPE_ID IS NOT NULL) THEN
    BEGIN
      TAG_NAME = 'types:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'types:r:id';
      VAL = V$TYPE_ID;
      SUSPEND;
      TAG_NAME = 'types:r:caption';
      VAL = V$CAPTION;
      SUSPEND;
      TAG_NAME = 'types:r:edit_type';
      -- Специальный кейс: возможность ручного добавления ОООД на уровне региона в приложении Документы ОООД региона
      IF(I$LEVEL_ID = 117 AND V$TYPE_ID = 2) THEN V$EDIT_TYPE = 1;
      VAL = V$EDIT_TYPE;
      SUSPEND;
    END
  END

  TAG_NAME = 'reports';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'reports::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
    SELECT R.REPORT_ID, RR.VAL, LR.GROUP_NAME
    FROM LREPORTS LR
    JOIN REPORTS R ON R.REPORT_ID = LR.REPORT_ID AND R.IS_DEL = 0 AND R.TYPE_ID = :V$OBJ_TYPE_ID
    JOIN RES RR ON RR.RES_ID = R.RES_ID AND RR.LANG_CODE = 'RU'
    WHERE LR.IS_DEL = 0 AND LR.LEVEL_ID = :I$LEVEL_ID
    ORDER BY 3, R.SORT_ORDER
    INTO :V$TYPE_ID, :V$CAPTION, :V$GROUP_NAME
  DO
  BEGIN
    TAG_NAME = 'reports:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'reports:r:id';
    VAL = V$TYPE_ID;
    SUSPEND;
    TAG_NAME = 'reports:r:caption';
    VAL = V$CAPTION;
    SUSPEND;
    TAG_NAME = 'reports:r:group_name';
    VAL = V$GROUP_NAME;
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_OBJECT_DELETE (
    I$PARENT_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$LEVEL_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    DEL_COUNT SMALLINT)
AS
DECLARE VARIABLE V$USER_ID BIGINT;
DECLARE VARIABLE V$PARENT_TYPE_ID BIGINT;
DECLARE VARIABLE V$OBJ_TYPE_ID BIGINT;
DECLARE VARIABLE V$ALLOW SMALLINT;
DECLARE VARIABLE V$MSG VARCHAR(2000);
DECLARE VARIABLE V$MYDATA SMALLINT;
DECLARE VARIABLE V$TYPE_ID BIGINT;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$EXACT_ACCESS SMALLINT;
DECLARE VARIABLE V$ALT_ACCESS SMALLINT;
DECLARE VARIABLE T$OBJ_ID BIGINT;
DECLARE VARIABLE V$E SMALLINT;
DECLARE VARIABLE V$OU_LEVEL SMALLINT;
DECLARE VARIABLE V$GEN BIGINT;
DECLARE VARIABLE V$MULT BIGINT;
DECLARE VARIABLE V$LINK_ID BIGINT;
begin

  -- Допроверять работу с grids в режиме выбора !!!

  V$MYDATA = 0;
  IF(I$LEVEL_ID > 100000) THEN
  BEGIN
    I$LEVEL_ID = I$LEVEL_ID - 100000;
    V$MYDATA = 1;
  END

  SELECT FIRST 1 KEY_VAL
  FROM KEYS
  WHERE KEY_CODE = 'LEVEL'
  INTO :V$OU_LEVEL;

  SELECT GEN, MULTIPLIER
  FROM GEN
  INTO :V$GEN, :V$MULT;

  IF(I$USER_ID = 'Веб-администратор') THEN V$USER_ID = 1; ELSE V$USER_ID = CAST(I$USER_ID AS BIGINT);

  SELECT FIRST 1 L.PARENT_TYPE_ID, L.OBJ_TYPE_ID, L.LINK_ID
  FROM LINKS L
  WHERE L.DATE_DEL IS NULL AND L.OBJ_ID = :I$OBJ_ID AND (L.PARENT_ID = :I$PARENT_ID OR (L.PARENT_ID IS NULL AND :I$PARENT_ID IS NULL))
  INTO :V$PARENT_TYPE_ID, :V$OBJ_TYPE_ID, :V$LINK_ID;

  IF(V$OBJ_TYPE_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Объект не найден, или его удалил другой пользователь';

  -- В корне можно удалять только конкретные типы объектов
  IF(V$PARENT_TYPE_ID IS NULL) THEN
  BEGIN
    IF(V$OBJ_TYPE_ID NOT IN (2, 124, 111, 112)) THEN EXCEPTION DATA_ERROR 'Нельзя удалить данный корневой объект';
  END
  -- Есть ли право write на данном уровне ?
  -- I$LEVEL_ID = NULL при передаче из пользовательских процедур
  ELSE IF(I$LEVEL_ID IS NOT NULL) THEN BEGIN
    V$E = 0;
    SELECT FIRST 1 1
    FROM PARENTS P
    JOIN LTYPES LT ON LT.TYPE_ID = P.CHILD_ID AND LT.LEVEL_ID = :I$LEVEL_ID AND LT.IS_DEL = 0 AND LT.EDIT_TYPE = 1
    WHERE P.CHILD_ID = :V$OBJ_TYPE_ID AND P.TYPE_ID = :V$PARENT_TYPE_ID AND P.IS_DEL = 0
    INTO :V$E;

    -- Удаление в классе ГИА второгодника ?
    IF(V$OU_LEVEL = 1 AND V$PARENT_TYPE_ID = 125 AND V$OBJ_TYPE_ID = 10) THEN V$E = 1;

    -- Удаление статуса жизненного цикла
    IF(V$OU_LEVEL = 1 AND V$PARENT_TYPE_ID = 2 AND V$OBJ_TYPE_ID = 497) THEN V$E = 1;

    -- Удаление настроек выгрузки на сайт
    IF(V$OU_LEVEL = 1 AND V$PARENT_TYPE_ID = 2 AND V$OBJ_TYPE_ID = 514) THEN V$E = 1;

    -- Удаление района или ОУ в регионе
    IF(V$OU_LEVEL = 3 AND V$PARENT_TYPE_ID = 112 AND V$OBJ_TYPE_ID = 111) THEN V$E = 1;
    IF(V$OU_LEVEL IN (2, 3) AND V$PARENT_TYPE_ID = 111 AND V$OBJ_TYPE_ID IN (2, 124)) THEN V$E = 1;

    -- Удаление отпуска
    IF(V$OU_LEVEL = 1 AND V$PARENT_TYPE_ID = 14 AND V$OBJ_TYPE_ID = 37) THEN V$E = 1;

    IF(V$E = 0) THEN EXCEPTION DATA_ERROR 'Невозможно удалить данный объект в текущем приложении';
  END

  -- Есть ли у пользователя право write в данном приложении ?
  IF(V$MYDATA = 1) THEN
  BEGIN
    -- Просто проверяем наличие пользователя - тут и сотрудники, и ученики, но пока без родителей
    SELECT FIRST 1 U.OBJ_ID, LPG.OBJ_TYPE_ID, LU.READ_ONLY
    FROM USERS U
    JOIN LINKS LPG ON LPG.OBJ_ID = U.OBJ_ID AND LPG.PARENT_TYPE_ID IN (2, 211, 9, 187) AND LPG.DATE_DEL IS NULL
    -- Дополнительно проверяем, что пользователю разрешено что-то менять тут
    LEFT JOIN LUSERS LU ON LU.USER_ID = U.USER_ID AND LU.LEVEL_ID = :I$LEVEL_ID
    WHERE U.USER_ID = :V$USER_ID AND U.DATE_DEL IS NULL AND U.IS_BLOCKED = 0 AND (U.EXP_DATE IS NULL OR U.EXP_DATE > CURRENT_DATE)
    INTO :V$OBJ_ID, :V$TYPE_ID, :V$EXACT_ACCESS;

    IF(V$OBJ_ID IS NOT NULL AND (V$EXACT_ACCESS IS NULL OR V$EXACT_ACCESS = 1)) THEN
    BEGIN
      SELECT FIRST 1 LP1.PARENT_ID
      FROM LINKS LP1
      WHERE LP1.OBJ_ID = :I$OBJ_ID AND LP1.PARENT_TYPE_ID IN (10, 14) AND LP1.DATE_DEL IS NULL
      UNION
      SELECT FIRST 1 LP2.PARENT_ID
      FROM LINKS LP1
      JOIN LINKS LP2 ON LP2.OBJ_ID = LP1.PARENT_ID AND LP2.PARENT_TYPE_ID = 14 AND LP2.DATE_DEL IS NULL
      WHERE LP1.OBJ_ID = :I$OBJ_ID AND LP1.PARENT_TYPE_ID IN (458) AND LP1.DATE_DEL IS NULL
      INTO :T$OBJ_ID;

      -- Если у пользователя нет доступа, проверяем перекрывающий доступ для своих собственных данных
      IF(V$OBJ_ID = T$OBJ_ID AND (
        -- Для сотрудника - только аттестация
        (V$TYPE_ID = 14 AND I$LEVEL_ID = 48 AND V$OBJ_TYPE_ID IN (458, 459)) OR
        -- Для учеников - портфолио
        (V$TYPE_ID = 10 AND I$LEVEL_ID = 50 AND V$OBJ_TYPE_ID IN (22, 24, 25, 430))
      ))
      THEN
        V$ALT_ACCESS = 0;

      IF(V$EXACT_ACCESS IS NULL OR V$ALT_ACCESS < V$EXACT_ACCESS) THEN V$EXACT_ACCESS = V$ALT_ACCESS;

      -- Ученик не может удалить подтвержденную запись портфолио
      IF(V$TYPE_ID = 10 AND EXISTS(
        SELECT FIRST 1 1
        FROM VALL V
        WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID IN (3182, 3192, 3193, 3203) AND V.IS_DEL = 0 AND V.LISTVAL_ID = 2
      ))
      THEN
        EXCEPTION DATA_ERROR 'Вы не можете удалить подтвержденную запись портфолио, обратитесь к классному руководителю';
    END

    IF(V$OBJ_ID IS NULL OR V$EXACT_ACCESS IS NULL OR V$EXACT_ACCESS = 1) THEN
      EXCEPTION DATA_ERROR 'У вас нет доступа к данному приложению (полностью или для данного конкретного типа объектов)';
  END
  ELSE
  BEGIN
    IF(I$LEVEL_ID IS NOT NULL AND NOT EXISTS(
      SELECT FIRST 1 1
      FROM USERS U
      JOIN LUSERS L ON L.USER_ID = U.USER_ID AND L.LEVEL_ID = :I$LEVEL_ID AND L.READ_ONLY = 0
      WHERE U.USER_ID = :V$USER_ID AND U.IS_BLOCKED = 0 AND U.DATE_DEL IS NULL AND (U.EXP_DATE IS NULL OR U.EXP_DATE >= CURRENT_DATE)
    ))
    THEN
      EXCEPTION DATA_ERROR 'У вас нет права удаления в данном приложении';
  END

  -- Нельзя удалять учащихся напрямую, кроме как из предварительного приема и из классов ГИА
  IF(V$OBJ_TYPE_ID = 10) THEN
  BEGIN
    IF(V$PARENT_TYPE_ID NOT IN (125, 290)) THEN EXCEPTION DATA_ERROR 'Нельзя удалять обучающегося, кроме как из этапа предварительного приема или класса ГИА';
  END

  -- Нельзя удалить сущности, созданные в другой базе
  IF(V$GEN <> V$LINK_ID / V$MULT AND V$OBJ_TYPE_ID NOT IN (2, 124, 111, 112)) THEN
  BEGIN
    EXCEPTION DATA_ERROR 'Нельзя удалить объект, созданный в другой базе';
  END

  -- Дополнительно проверяем ограничение прав для классных руководителей через ROOT_OBJ_ID
  -- !!!

  SELECT CD.CAN_DELETE, COALESCE(CD.ERR_MSG, '')
  FROM PARAGRAF_CAN_DELETE_OBJECT(:I$OBJ_ID) CD
  INTO :V$ALLOW, :V$MSG;

  IF(V$ALLOW = 0) THEN
  BEGIN
    IF(V$MSG = '') THEN V$MSG = 'Объект не может быть удален';
    EXCEPTION DATA_ERROR V$MSG;
  END

  -- Удаляем
  SELECT DEL_COUNT FROM OBJECT_DEL(:I$PARENT_ID, :I$OBJ_ID) INTO :DEL_COUNT;

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_OBJECT_HISTORY (
    I$PARENT_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$PARAM_ID BIGINT,
    I$LEVEL_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE S VARCHAR(1000);
DECLARE VARIABLE S2 VARCHAR(1000);
DECLARE VARIABLE DT TIMESTAMP;
DECLARE VARIABLE V$PARAM_TYPE BIGINT;
begin

  SELECT P.PARAM_TYPE
  FROM PARAMS P
  WHERE P.PARAM_ID = :I$PARAM_ID
  INTO :V$PARAM_TYPE;

  -- json:array уже выдан
  FOR
    SELECT V.DATE_ADD, V.OLD_VAL, V.VAL
    FROM HISTVALS V
    WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = :I$PARAM_ID AND V.TABLE_NAME = 'VAL'
    ORDER BY V.DATE_ADD DESC
    INTO :DT, :S, :S2
  DO
  BEGIN
    TAG_NAME = 'r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'r:dt';
    VAL = (SELECT VAL FROM DATE2ISO(:DT));
    SUSPEND;
    TAG_NAME = 'r:old_value';
    VAL = S;
    IF(V$PARAM_TYPE = 6 AND VAL IS NOT NULL) THEN
    BEGIN
      SELECT FIRST 1 V.VAL
      FROM LISTVAL_TEXT(CAST(:VAL AS BIGINT)) V
      INTO :VAL;
    END
    SUSPEND;
    TAG_NAME = 'r:value';
    VAL = S2;
    IF(V$PARAM_TYPE = 6 AND VAL IS NOT NULL) THEN
    BEGIN
      SELECT FIRST 1 V.VAL
      FROM LISTVAL_TEXT(CAST(:VAL AS BIGINT)) V
      INTO :VAL;
    END
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_OBJECT_PARAM_DELETE (
    I$PARENT_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$PARAM_ID BIGINT,
    I$LEVEL_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    BLOB_ID BIGINT,
    REFRESH_FLAG VARCHAR(100),
    OBJ_CAPTION VARCHAR(4000))
AS
DECLARE VARIABLE V$USER_ID BIGINT;
DECLARE VARIABLE V$PARENT_TYPE_ID BIGINT;
DECLARE VARIABLE V$OBJ_TYPE_ID BIGINT;
DECLARE VARIABLE V$PARAM_TYPE SMALLINT;
DECLARE VARIABLE REGION VARCHAR(255);
DECLARE VARIABLE DISTRICT VARCHAR(255);
DECLARE VARIABLE TOWN VARCHAR(255);
DECLARE VARIABLE SETTLEMENT VARCHAR(255);
DECLARE VARIABLE STREET VARCHAR(255);
DECLARE VARIABLE HOUSE VARCHAR(10);
DECLARE VARIABLE CORP VARCHAR(10);
DECLARE VARIABLE LITER VARCHAR(10);
DECLARE VARIABLE FLAT VARCHAR(10);
DECLARE VARIABLE POST_INDEX VARCHAR(20);
DECLARE VARIABLE OCATD VARCHAR(11);
DECLARE VARIABLE HOUSEGUID VARCHAR(36);
DECLARE VARIABLE STREETGUID VARCHAR(36);
begin

  IF(I$LEVEL_ID > 100000) THEN I$LEVEL_ID = I$LEVEL_ID - 100000;

  IF(I$USER_ID = 'Веб-администратор') THEN V$USER_ID = 1; ELSE V$USER_ID = CAST(I$USER_ID AS BIGINT);

  SELECT FIRST 1 L.PARENT_TYPE_ID, L.OBJ_TYPE_ID
  FROM LINKS L
  WHERE L.DATE_DEL IS NULL AND L.OBJ_ID = :I$OBJ_ID AND (L.PARENT_ID = :I$PARENT_ID OR (L.PARENT_ID IS NULL AND :I$PARENT_ID IS NULL))
  INTO :V$PARENT_TYPE_ID, :V$OBJ_TYPE_ID;

  IF(V$OBJ_TYPE_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Объект не найден, или его удалил другой пользователь';

  SELECT P.PARAM_TYPE
  FROM PARAMS P
  WHERE P.TYPE_ID = :V$OBJ_TYPE_ID AND P.PARAM_ID = :I$PARAM_ID AND P.IS_DEL = 0
  INTO :V$PARAM_TYPE;

  IF(V$PARAM_TYPE IS NULL) THEN EXCEPTION DATA_ERROR 'Параметр не найден у данного типа объекта';

  -- Есть ли доступ к типу объекта и типу параметра ?
  -- Исключения: запись выгрузки на сайт ОУ
  IF(NOT EXISTS(
    SELECT FIRST 1 1
    FROM PARENTS P
    JOIN LTYPES LT ON LT.TYPE_ID = P.CHILD_ID AND LT.LEVEL_ID = :I$LEVEL_ID AND ((LT.IS_DEL = 0 AND LT.EDIT_TYPE >= 0) OR P.CHILD_ID = 514)
    JOIN LPARAMS LP ON LP.LEVEL_ID = LT.LEVEL_ID AND LP.PARAM_ID = :I$PARAM_ID AND LP.IS_DEL = 0 AND LP.EDIT_TYPE = 1
    WHERE P.CHILD_ID = :V$OBJ_TYPE_ID AND (P.TYPE_ID = :V$PARENT_TYPE_ID OR (P.TYPE_ID IS NULL AND :V$PARENT_TYPE_ID IS NULL)) AND P.IS_DEL = 0
  ))
  THEN
    EXCEPTION DATA_ERROR 'Нет доступа на редактирование к объекту или параметру в данном приложении';

  -- Есть ли у пользователя право write в данном приложении ?
  IF(NOT EXISTS(
    SELECT FIRST 1 1
    FROM USERS U
    JOIN LUSERS L ON L.USER_ID = U.USER_ID AND L.LEVEL_ID = :I$LEVEL_ID AND L.READ_ONLY = 0
    WHERE U.USER_ID = :V$USER_ID AND U.IS_BLOCKED = 0 AND U.DATE_DEL IS NULL AND (U.EXP_DATE IS NULL OR U.EXP_DATE >= CURRENT_DATE)
  ))
  THEN
    EXCEPTION DATA_ERROR 'У вас нет права редактирования в данном приложении';

  -- Дополнительно проверяем ограничение прав для классных руководителей через ROOT_OBJ_ID
  -- !!!
                  
  IF(V$PARAM_TYPE = 18) THEN
  BEGIN
    -- Нужно вытащить текущие данные адреса
    SELECT REGION, DISTRICT, TOWN, SETTLEMENT, STREET, HOUSE, CORP, LITER, FLAT, POST_INDEX, OCATD, HOUSEGUID, STREETGUID
    FROM ADR_GET(:I$PARAM_ID, :I$OBJ_ID)
    INTO :REGION, :DISTRICT, :TOWN, :SETTLEMENT, :STREET, :HOUSE, :CORP, :LITER, :FLAT, :POST_INDEX, :OCATD, :HOUSEGUID, :STREETGUID;

    SELECT REFRESH_FLAG
    FROM ADR_ADD(:I$PARAM_ID, :I$OBJ_ID, :REGION, :DISTRICT, :TOWN, :SETTLEMENT, :STREET, :HOUSE, :CORP, :LITER, :FLAT, :POST_INDEX, :OCATD, :HOUSEGUID, :STREETGUID, :V$USER_ID, 1)
    INTO :REFRESH_FLAG;
  END
  ELSE
  BEGIN
    SELECT BLOB_ID, REFRESH_FLAG
    FROM VAL_ADD(:I$PARAM_ID, :I$OBJ_ID, NULL, :V$USER_ID)
    INTO :BLOB_ID, :REFRESH_FLAG;
  END

  SELECT CAPTION
  FROM OBJECT_CAPTION_GET(:I$OBJ_ID, :I$LEVEL_ID)
  INTO :OBJ_CAPTION;

  SUSPEND;
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_OD_EDUCATION (
    ID1 VARCHAR(40),
    ID2 VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(2000))
AS
declare variable PERSON_ID bigint;
declare variable STAGE_VAL bigint;
declare variable D date;
declare variable Y integer;
begin

  FOR
      SELECT L10.OBJ_ID, V49.LISTVAL_ID, LV.COST
      FROM LINKS L2
      JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
      JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
      -- Уровень образования
      JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
      JOIN VALL V43 ON V43.OBJ_ID = L7.OBJ_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0
      -- Этап обучения
      JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
      JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
      -- Класс
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 125, 187) AND L9.DATE_DEL IS NULL
      JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
        AND EXISTS (
          SELECT FIRST 1 1
          FROM UT_EXAM_PERSON_ASSN PA
          JOIN UT_EXAM_DATES D ON D.DATE_DEL IS NULL AND D.OBJ_ID = PA.EXAM_ID AND D.EXAM_DAY_TYPE = 100 AND D.PERIOD_ID = V1236.LISTVAL_ID
            AND D.EXAM_STATE > 0 AND D.EXAM_STATE < 1000 -- кроме черновика или неактивной записи
          WHERE PA.DATE_DEL IS NULL AND PA.PERSON_ID = L10.OBJ_ID
        )
      INTO :PERSON_ID, :STAGE_VAL, :Y
  DO
  BEGIN

      TAG_NAME = 'wsdl&colon;EducationInput';
      VAL = NULL;
      SUSPEND;

      TAG_NAME = 'wsdl&colon;EducationInput:identity:external_id';
      VAL = PERSON_ID;
      SUSPEND;

      TAG_NAME = 'wsdl&colon;EducationInput:person_id:external_id';
      VAL = PERSON_ID;
      SUSPEND;

      TAG_NAME = 'wsdl&colon;EducationInput:institution_id:id';
      VAL = ID1;
      SUSPEND;

      -- Дата начала обучения в данной параллели
      D = NULL;
      SELECT FIRST 1 M.DATE_IN
      FROM PERSON_MOVEMENTS M
      JOIN OBJECTS O ON O.OBJ_ID = M.GROUP_ID AND O.TYPE_ID IN (9, 187)
      WHERE M.DATE_DEL IS NULL AND M.OBJ_ID = :PERSON_ID AND M.DATE_OUT IS NULL
      ORDER BY M.OBJ_ID DESC
      INTO :D;

      IF(D IS NULL) THEN D = '01.09.' || Y;

      TAG_NAME = 'wsdl&colon;EducationInput:date_from';
      VAL = (SELECT VAL FROM DATE2ISO(:D, 0));
      SUSPEND;

      -- Параллель education_stage/code
      TAG_NAME = 'wsdl&colon;EducationInput:education_stage:code';
      IF(STAGE_VAL = 12765) THEN STAGE_VAL = 0;
      ELSE IF(STAGE_VAL >= 37 AND STAGE_VAL <= 47) THEN STAGE_VAL = STAGE_VAL - 37 + 1;
      ELSE IF(STAGE_VAL = 48) THEN STAGE_VAL = 13;
      ELSE EXCEPTION DATA_ERROR 'Недопустимый код уровня обучения для учащегося';
      VAL = STAGE_VAL;
      IF(CHAR_LENGTH(VAL) = 1) THEN VAL = '0' || VAL;
      SUSPEND;

  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_OD_MEETINGS (
    ID1 VARCHAR(40),
    ID2 VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(2000))
AS
DECLARE VARIABLE EXAM_ID BIGINT;
DECLARE VARIABLE SUBJECT_ID BIGINT;
DECLARE VARIABLE SIG VARCHAR(200);
DECLARE VARIABLE LEVEL_ID INTEGER;
DECLARE VARIABLE V$YEAR_ID BIGINT;
begin

    SELECT FIRST 1 V1236.LISTVAL_ID
    FROM LINKS L2
    JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :V$YEAR_ID;

    -- Выбираем все уникальные сочетания олимпиада-ученик-этап
    FOR
        SELECT DISTINCT D.OBJ_ID, D.LINK_HASH, PA.LEVEL_ID, D.SUBJECT_ID
        FROM UT_EXAM_DATES D
        JOIN UT_EXAM_PERSON_ASSN PA ON PA.DATE_DEL IS NULL AND PA.EXAM_ID = D.OBJ_ID AND PA.LEVEL_ID > 0 -- Временно, ограничиваем 0-й класс !
        JOIN LINKS LP9 ON LP9.OBJ_ID = PA.PERSON_ID AND LP9.PARENT_TYPE_ID IN (9, 125, 187) AND LP9.DATE_DEL IS NULL
        WHERE D.DATE_DEL IS NULL AND D.EXAM_DAY_TYPE = 100 AND D.EXAM_STATE > 0 AND D.EXAM_STATE < 1000 AND D.PERIOD_ID = :V$YEAR_ID
        INTO :EXAM_ID, :SIG, :LEVEL_ID, :SUBJECT_ID
    DO
    BEGIN

        TAG_NAME = 'wsdl&colon;Meeting';
        VAL = NULL;
        SUSPEND;

        TAG_NAME = 'wsdl&colon;Meeting:identity:external_id';
        VAL = EXAM_ID || ':' || LEVEL_ID;
        SUSPEND;

        TAG_NAME = 'wsdl&colon;Meeting:institution_id:id';
        VAL = ID1;
        SUSPEND;

        -- Код предмета заменяем
        TAG_NAME = 'wsdl&colon;Meeting:discipline:code';
        IF(SUBJECT_ID = 5516) THEN VAL = 1; -- Астрономия
        ELSE IF(SUBJECT_ID = 172) THEN VAL = 2; -- Алгебра
        ELSE IF(SUBJECT_ID = 188) THEN VAL = 3; -- Английский язык
        ELSE IF(SUBJECT_ID = 197) THEN VAL = 4; -- Биология
        ELSE IF(SUBJECT_ID = 3139) THEN VAL = 5; -- География
        ELSE IF(SUBJECT_ID = 34752) THEN VAL = 6; -- Геология
        ELSE IF(SUBJECT_ID = 173) THEN VAL = 7; -- Геометрия
        ELSE IF(SUBJECT_ID = 177) THEN VAL = 8; -- Естествознание
        ELSE IF(SUBJECT_ID = 202) THEN VAL = 9; -- Изобразительное искусство
        ELSE IF(SUBJECT_ID = 191) THEN VAL = 10; -- Информатика и ИКТ
        ELSE IF(SUBJECT_ID = 34279) THEN VAL = 11; -- Искусство (мировая художественная культура)
        ELSE IF(SUBJECT_ID = 3131) THEN VAL = 12; -- Испанский язык
        ELSE IF(SUBJECT_ID = 174) THEN VAL = 13; -- История
        ELSE IF(SUBJECT_ID = 3151) THEN VAL = 14; -- История России
        ELSE IF(SUBJECT_ID = 3155) THEN VAL = 15; -- Итальянский язык
        ELSE IF(SUBJECT_ID = 3132) THEN VAL = 16; -- Китайский язык
        ELSE IF(SUBJECT_ID = 34753) THEN VAL = 17; -- Корейский язык
        ELSE IF(SUBJECT_ID = 195) THEN VAL = 18; -- Краеведение
        ELSE IF(SUBJECT_ID = 187) THEN VAL = 19; -- Литература
        ELSE IF(SUBJECT_ID = 190) THEN VAL = 20; -- Математика
        ELSE IF(SUBJECT_ID = 34754) THEN VAL = 21; -- Медицина
        ELSE IF(SUBJECT_ID = 2129) THEN VAL = 22; -- Немецкий язык
        ELSE IF(SUBJECT_ID = 34755) THEN VAL = 23; -- Общественно-научные предметы
        ELSE IF(SUBJECT_ID = 194) THEN VAL = 24; -- Обществознание
        ELSE IF(SUBJECT_ID = 206) THEN VAL = 25; -- Основы безопасности жизнедеятельности (ОБЖ)
        ELSE IF(SUBJECT_ID = 5532) THEN VAL = 26; -- Основы духовно-нравственной культуры народов России
        ELSE IF(SUBJECT_ID = 900) THEN VAL = 27; -- Основы религиозных культур и светской этики
        ELSE IF(SUBJECT_ID = 3138) THEN VAL = 28; -- Право
        ELSE IF(SUBJECT_ID = 32787) THEN VAL = 29; -- Родная литература
        ELSE IF(SUBJECT_ID = 929) THEN VAL = 30; -- Родной язык
        ELSE IF(SUBJECT_ID = 34756) THEN VAL = 31; -- Родной язык и литературное чтение на родном языке
        ELSE IF(SUBJECT_ID = 32840) THEN VAL = 32; -- Россия в мире
        ELSE IF(SUBJECT_ID = 185) THEN VAL = 33; -- Русский язык
        ELSE IF(SUBJECT_ID = 34757) THEN VAL = 34; -- Русский язык и литературное чтение
        ELSE IF(SUBJECT_ID = 200) THEN VAL = 35; -- Технология
        ELSE IF(SUBJECT_ID = 198) THEN VAL = 36; -- Физика
        ELSE IF(SUBJECT_ID = 205) THEN VAL = 37; -- Физическая культура
        ELSE IF(SUBJECT_ID = 3130) THEN VAL = 38; -- Финский язык
        ELSE IF(SUBJECT_ID = 189) THEN VAL = 39; -- Французский язык
        ELSE IF(SUBJECT_ID = 199) THEN VAL = 40; -- Химия
        ELSE IF(SUBJECT_ID = 3135) THEN VAL = 41; -- Хинди
        ELSE IF(SUBJECT_ID = 3160) THEN VAL = 42; -- Экология
        ELSE IF(SUBJECT_ID = 32843) THEN VAL = 43; -- Экономика
        ELSE IF(SUBJECT_ID = 3134) THEN VAL = 44; -- Японский язык
        -- Новые местные олимпиады, добавлено 26.08.2024
        ELSE IF(SUBJECT_ID = 38707) then VAL = 45; -- С-Пб "Гиды - переводчики"
        ELSE IF(SUBJECT_ID = 38708) then VAL = 46;  -- С-Пб Лингострановедческая
        ELSE IF(SUBJECT_ID = 38709) then VAL = 47; -- С-Пб ОБЖ с ОВЗ
        ELSE IF(SUBJECT_ID = 38710) then VAL = 48; -- С-Пб Русский язык и литература с ОВЗ
        ELSE IF(SUBJECT_ID = 38711) then VAL = 49; -- С-Пб Технология с ОВЗ
        ELSE IF(SUBJECT_ID = 38712) then VAL = 50; -- С-Пб География
        ELSE IF(SUBJECT_ID = 38713) then VAL = 51; -- С-Пб ОБЖ
        ELSE IF(SUBJECT_ID = 38714) then VAL = 52; -- С-Пб Информатика
        ELSE IF(SUBJECT_ID = 38715) then VAL = 53; -- С-Пб Технология "Азбука мастерства"
        ELSE IF(SUBJECT_ID = 38716) then VAL = 54; -- С-Пб История и обществознание
        ELSE IF(SUBJECT_ID = 38717) then VAL = 55; -- С-Пб Русский язык и литература
        ELSE IF(SUBJECT_ID = 38718) then VAL = 56; -- С-Пб Физическая культура
        ELSE IF(SUBJECT_ID = 38719) then VAL = 57; -- С-Пб Экономика
        ELSE IF(SUBJECT_ID = 38720) then VAL = 58; -- С-Пб "Паруса науки"
        ELSE EXCEPTION DATA_ERROR 'Недопустимый предмет в олимпиаде';
        IF(CHAR_LENGTH(VAL) = 1) THEN VAL = '0' || VAL;
        SUSPEND;

        -- Сдвиг в нумерации для 12-х классов
        IF(LEVEL_ID = 12) THEN LEVEL_ID = 13;
        TAG_NAME = 'wsdl&colon;Meeting:education_stage:code';
        VAL = LEVEL_ID;
        IF(CHAR_LENGTH(VAL) = 1) THEN VAL = '0' || VAL;
        SUSPEND;

        -- id этапа олимпиады - последний (третий) в списке SIG
        WHILE(POSITION(';' IN SIG) > 0) DO SIG = SUBSTRING(SIG FROM POSITION(';' IN SIG) + 1);
        TAG_NAME = 'wsdl&colon;Meeting:period_id:id';
        VAL = SIG;
        SUSPEND;

    END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_OD_MEETING_MEMBERS (
    ID1 VARCHAR(40),
    ID2 VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(2000))
AS
declare variable PERSON_ID bigint;
declare variable EXAM_ID bigint;
declare variable LEVEL_ID integer;
declare variable V$YEAR_ID bigint;
begin

    SELECT FIRST 1 V1236.LISTVAL_ID
    FROM LINKS L2
    JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :V$YEAR_ID;

    FOR
        SELECT D.OBJ_ID, PA.PERSON_ID, PA.LEVEL_ID
        FROM UT_EXAM_DATES D
        JOIN UT_EXAM_PERSON_ASSN PA ON PA.DATE_DEL IS NULL AND PA.EXAM_ID = D.OBJ_ID AND PA.LEVEL_ID > 0 -- !!! ограничиваем 0-й класс
        JOIN LINKS LP9 ON LP9.OBJ_ID = PA.PERSON_ID AND LP9.PARENT_TYPE_ID IN (9, 125, 187) AND LP9.DATE_DEL IS NULL
        WHERE D.DATE_DEL IS NULL AND D.EXAM_DAY_TYPE = 100 AND D.EXAM_STATE > 0 AND D.EXAM_STATE < 1000 AND D.PERIOD_ID = :V$YEAR_ID
        INTO :EXAM_ID, :PERSON_ID, :LEVEL_ID
    DO
    BEGIN

        TAG_NAME = 'wsdl&colon;MeetingMemberInput';
        VAL = NULL;
        SUSPEND;

        TAG_NAME = 'wsdl&colon;MeetingMemberInput:identity:external_id';
        VAL = EXAM_ID || ':' || PERSON_ID;
        SUSPEND;

        TAG_NAME = 'wsdl&colon;MeetingMemberInput:meeting_id:external_id';
        VAL = EXAM_ID || ':' || LEVEL_ID;
        SUSPEND;

        TAG_NAME = 'wsdl&colon;MeetingMemberInput:student_id:external_id';
        VAL = PERSON_ID;
        SUSPEND;

    END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_OD_PERSONS (
    ID1 VARCHAR(40),
    ID2 VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(2000))
AS
DECLARE VARIABLE PERSON_ID BIGINT;
DECLARE VARIABLE V1 VARCHAR(1000);
DECLARE VARIABLE V2 VARCHAR(1000);
DECLARE VARIABLE V3 VARCHAR(1000);
DECLARE VARIABLE BD DATE;
DECLARE VARIABLE SEX INTEGER;
DECLARE VARIABLE SNILS VARCHAR(40);
DECLARE VARIABLE OVZ BIGINT;
DECLARE VARIABLE CITIZENSHIP VARCHAR(400);
begin

    -- Персоны только из числа имеющих назначения на олимпиады

    FOR
        SELECT L10.OBJ_ID, V55.VAL, V56.VAL, V57.VAL, V89.VAL, V88.LISTVAL_ID, /*REPLACE(REPLACE(V1409.SVAL, '-', ''), ' ', '')*/ V1409.SVAL, V207.LISTVAL_ID, CS.VAL
        FROM LINKS L2
        JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
        JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID IN (7, 502) AND L7.DATE_DEL IS NULL
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 125, 187) AND L9.DATE_DEL IS NULL
        JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        JOIN VALS V55 ON V55.OBJ_ID = L10.OBJ_ID AND V55.PARAM_ID = 55 AND V55.IS_DEL = 0
        JOIN VALS V56 ON V56.OBJ_ID = L10.OBJ_ID AND V56.PARAM_ID = 56 AND V56.IS_DEL = 0
        LEFT JOIN VALS V57 ON V57.OBJ_ID = L10.OBJ_ID AND V57.PARAM_ID = 57 AND V57.IS_DEL = 0
        JOIN VALD V89 ON V89.OBJ_ID = L10.OBJ_ID AND V89.PARAM_ID = 89 AND V89.IS_DEL = 0
        JOIN VALL V88 ON V88.OBJ_ID = L10.OBJ_ID AND V88.PARAM_ID = 88 AND V88.IS_DEL = 0
        LEFT JOIN VALS V1409 ON V1409.OBJ_ID = L10.OBJ_ID AND V1409.PARAM_ID = 1409 AND V1409.IS_DEL = 0
        LEFT JOIN VALL V207 ON V207.OBJ_ID = L10.OBJ_ID AND V207.PARAM_ID = 207 AND V207.IS_DEL = 0
        LEFT JOIN VALL V91 ON V91.OBJ_ID = L10.OBJ_ID AND V91.PARAM_ID = 91 AND V91.IS_DEL = 0
        LEFT JOIN LISTVAL_TEXT(V91.LISTVAL_ID) CS ON 1 = 1
        WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
          AND EXISTS (
            SELECT FIRST 1 1
            FROM UT_EXAM_PERSON_ASSN PA
            JOIN UT_EXAM_DATES D ON D.DATE_DEL IS NULL AND D.OBJ_ID = PA.EXAM_ID AND D.EXAM_DAY_TYPE = 100 AND D.PERIOD_ID = V1236.LISTVAL_ID
              AND D.EXAM_STATE > 0 AND D.EXAM_STATE < 1000 -- кроме черновика или неактивной записи
            WHERE PA.DATE_DEL IS NULL AND PA.PERSON_ID = L10.OBJ_ID
          )
        INTO :PERSON_ID, :V1, :V2, :V3, :BD, :SEX, :SNILS, :OVZ, :CITIZENSHIP
    DO
    BEGIN

        TAG_NAME = 'wsdl&colon;PersonInput';
        VAL = NULL;
        SUSPEND;

        TAG_NAME = 'wsdl&colon;PersonInput:identity:external_id';
        VAL = PERSON_ID;
        SUSPEND;

        TAG_NAME = 'wsdl&colon;PersonInput:identity:uid';
        SELECT COALESCE(V2912.VAL, '')
        FROM RDB$DATABASE
        LEFT JOIN VALS V2912 ON V2912.OBJ_ID = :PERSON_ID AND V2912.PARAM_ID = 2912 AND V2912.IS_DEL = 0
        INTO :VAL;
        IF(POSITION(':' IN VAL) > 0) THEN VAL = SUBSTRING(VAL FROM 1 FOR POSITION(':' IN VAL) - 1);
        SUSPEND;

        TAG_NAME = 'wsdl&colon;PersonInput:firstname';
        VAL = V2;
        SUSPEND;

        TAG_NAME = 'wsdl&colon;PersonInput:surname';
        VAL = V1;
        SUSPEND;

        TAG_NAME = 'wsdl&colon;PersonInput:middlename';
        VAL = V3;
        SUSPEND;

        TAG_NAME = 'wsdl&colon;PersonInput:birth_date';
        VAL = (SELECT VAL FROM DATE2ISO(:BD, 0));
        SUSPEND;

        TAG_NAME = 'wsdl&colon;PersonInput:sex:code';
        VAL = IIF(SEX = 182, 'F', 'M');
        SUSPEND;

        TAG_NAME = 'wsdl&colon;PersonInput:petrobr_id';
        VAL = NULL;
        SELECT FIRST 1 V1570.VAL
        FROM LINKS L20
        JOIN VALS V1570 ON V1570.OBJ_ID = L20.EXT_OBJ_ID AND V1570.PARAM_ID = 1570 AND V1570.IS_DEL = 0
        WHERE L20.PARENT_ID = :PERSON_ID AND L20.OBJ_TYPE_ID = 20 AND L20.DATE_DEL IS NULL
        INTO :VAL;
        SUSPEND;

        TAG_NAME = 'wsdl&colon;PersonInput:snils';
        VAL = SNILS;
        SUSPEND;

        TAG_NAME = 'wsdl&colon;PersonInput:ovz';
        VAL = IIF(OVZ IS NULL OR OVZ = 13289, 0, 1);
        -- Инвалидность ?
        IF(EXISTS(
          SELECT FIRST 1 1
          FROM LINKS L295
          JOIN VALL V2373 ON V2373.OBJ_ID = L295.OBJ_ID AND V2373.PARAM_ID = 2373 AND V2373.IS_DEL = 0
          LEFT JOIN VALD V2375 ON V2375.OBJ_ID = L295.OBJ_ID AND V2375.PARAM_ID = 2375 AND V2375.IS_DEL = 0
          WHERE L295.PARENT_ID = :PERSON_ID AND L295.OBJ_TYPE_ID = 295 AND L295.DATE_DEL IS NULL
            AND (V2375.VAL IS NULL OR V2375.VAL > CURRENT_DATE)
        ))
        THEN
          VAL = 1;
        SUSPEND;

        TAG_NAME = 'wsdl&colon;PersonInput:citizenship';
        VAL = CITIZENSHIP;
        SUSPEND;

    END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_PORTAL_CONTENT (
    T_FROM TIMESTAMP,
    T_TO TIMESTAMP NOT NULL = current_timestamp,
    ID1 VARCHAR(40) = null,
    ID2 VARCHAR(40) = null,
    I$MODE SMALLINT = 0)
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(2000))
AS
declare variable YEAR_ID bigint;
declare variable LESSON_ID bigint;
declare variable GROUP_ID bigint;
declare variable LESSON_THEME varchar(1000);
declare variable LESSON_EXTRA varchar(2000);
declare variable INST_LINK varchar(400);
declare variable N integer;
declare variable V$DT timestamp;
begin

  N = 0;

  SELECT FIRST 1 V1236.LISTVAL_ID
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :YEAR_ID;

  FOR
      SELECT L.OBJ_ID, L.LESSON_THEME, L.LESSON_EXTRA, L.INST_LINK
      FROM CJ2_JOURNAL J
      JOIN CJ2_JOURNAL_LESSONS L ON L.CJ_ID = J.OBJ_ID AND L.DATE_DEL IS NULL
      JOIN LINKS L179 ON L179.OBJ_ID = J.GRADE_ID AND L179.OBJ_TYPE_ID = 179 AND L179.PARENT_TYPE_ID = 2 AND L179.DATE_DEL IS NULL
      -- Признак группы ЦОПП
      LEFT JOIN VALL V3064 ON V3064.OBJ_ID = L179.OBJ_ID AND V3064.PARAM_ID = 3064 AND V3064.IS_DEL = 0
      WHERE J.DATE_DEL IS NULL AND J.JOURNAL_TYPE IN (0/*, 1*/) AND J.YEAR_ID = :YEAR_ID
          AND (L.IS_COMPLETED = 1 OR L.IS_PUBLISHED = 1) AND ((:T_FROM IS NULL OR L.DATE_MODIFY >= :T_FROM) AND L.DATE_MODIFY < :T_TO) --AND GS.PLAN_TYPE_ID IN (5465, 5466)
          AND ((:I$MODE = 0 AND (V3064.LISTVAL_ID IS NULL OR V3064.LISTVAL_ID = 3)) OR (:I$MODE = 1 AND V3064.LISTVAL_ID = 2))
      ORDER BY L.LESSON_DATE, L.CJ_ID
      INTO :LESSON_ID, :LESSON_THEME, :LESSON_EXTRA, :INST_LINK
  DO
  BEGIN

      TAG_NAME = 'wsdl&colon;ContentInput';
      VAL = NULL;
      SUSPEND;

      TAG_NAME = 'wsdl&colon;ContentInput:identity:external_id';
      VAL = LESSON_ID;
      SUSPEND;

      TAG_NAME = 'wsdl&colon;ContentInput:name';
      VAL = LESSON_THEME;
      SUSPEND;

      IF(LESSON_EXTRA IS NOT NULL) THEN
      BEGIN
          TAG_NAME = 'wsdl&colon;ContentInput:description';
          VAL = LESSON_EXTRA;
          SUSPEND;
      END

      IF(INST_LINK IS NOT NULL) THEN
      BEGIN
          TAG_NAME = 'wsdl&colon;ContentInput:additional_material';
          VAL = INST_LINK;
          SUSPEND;
      END

      N = N + 1;
      IF(N >= 10000) THEN
      BEGIN
          N = 0;
          TAG_NAME = NULL;
          VAL = 'DIVIDE';
          SUSPEND;
      END

  END

  -- Воспитательная работа
  FOR
      SELECT L.OBJ_ID, M.OBJ_ID, L.LESSON_THEME, MAXVALUE(V3373.DATE_MODIFY, L.DATE_MODIFY, M.DATE_MODIFY)
      FROM CJ2_JOURNAL J
      JOIN VALL V3373 ON V3373.OBJ_ID = J.REF_ID AND V3373.PARAM_ID = 3373 AND V3373.IS_DEL = 0 AND V3373.LISTVAL_ID = 11715
      JOIN CJ2_JOURNAL_LESSONS L ON L.DATE_DEL IS NULL AND L.CJ_ID = J.OBJ_ID AND L.IS_ONLINE = 1 AND L.LESSON_DATE > '01.01.2000'
        AND L.LESSON_EXTRA <> '' AND (L.IS_PUBLISHED = 1 OR L.IS_COMPLETED = 1)
      LEFT JOIN CJ2_LESSON_ATTRS A ON A.DATE_DEL IS NULL AND A.LESSON_ID = L.OBJ_ID AND A.ATTR_NAME = 'date_to'
      LEFT JOIN VOSP_MEMBERS_LIST(L.OBJ_ID) M ON 1 = 1
      WHERE J.DATE_DEL IS NULL AND J.JOURNAL_TYPE = 20 AND J.YEAR_ID = :YEAR_ID
          AND (A.ATTR_VALUE IS NULL OR A.ATTR_VALUE = '')
      INTO :LESSON_ID, :GROUP_ID, :LESSON_THEME, :V$DT
  DO
  BEGIN

      IF(T_FROM IS NULL OR V$DT >= T_FROM) THEN
      BEGIN

          TAG_NAME = 'wsdl&colon;ContentInput';
          VAL = NULL;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;ContentInput:identity:external_id';
          VAL = 'V' || LESSON_ID || '+' || GROUP_ID;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;ContentInput:name';
          VAL = LESSON_THEME;
          SUSPEND;

          N = N + 1;
          IF(N >= 10000) THEN
          BEGIN
              N = 0;
              TAG_NAME = NULL;
              VAL = 'DIVIDE';
              SUSPEND;
          END

      END

  END


end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_PORTAL_CONTENT_DELETE (
    T_FROM TIMESTAMP,
    T_TO TIMESTAMP NOT NULL = current_timestamp,
    ID1 VARCHAR(40) = null,
    ID2 VARCHAR(40) = null,
    I$MODE INTEGER = 0)
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(2000))
AS
declare variable YEAR_ID bigint;
declare variable IS_OK smallint;
declare variable LESSON_ID bigint;
declare variable LESSON_DT timestamp;
declare variable N integer;
begin

  IF(T_FROM IS NULL) THEN EXIT;

  SELECT FIRST 1 V1236.LISTVAL_ID
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :YEAR_ID;

  N = 0;

  -- Реально удаленные уроки
  FOR
      SELECT L.OBJ_ID, L.DATE_DEL
      FROM CJ2_JOURNAL J
      JOIN CJ2_JOURNAL_LESSONS L ON L.CJ_ID = J.OBJ_ID AND L.DATE_DEL IS NOT NULL
      JOIN LINKS L179 ON L179.OBJ_ID = J.GRADE_ID AND L179.OBJ_TYPE_ID = 179 AND L179.PARENT_TYPE_ID = 2 AND L179.DATE_DEL IS NULL
      -- Признак группы ЦОПП
      LEFT JOIN VALL V3064 ON V3064.OBJ_ID = L179.OBJ_ID AND V3064.PARAM_ID = 3064 AND V3064.IS_DEL = 0
      WHERE J.DATE_DEL IS NOT NULL AND J.JOURNAL_TYPE IN (0, 1) AND J.YEAR_ID = :YEAR_ID
          AND ((:I$MODE = 0 AND (V3064.LISTVAL_ID IS NULL OR V3064.LISTVAL_ID = 3)) OR (:I$MODE = 1 AND V3064.LISTVAL_ID = 2))
      INTO :LESSON_ID, :LESSON_DT
  DO
  BEGIN

      IS_OK = 0;
      IF(
          ((T_FROM IS NULL OR LESSON_DT >= T_FROM) AND LESSON_DT < T_TO)
      )
      THEN
          IS_OK = 1;

      IF(IS_OK = 1) THEN
      BEGIN

          TAG_NAME = 'wsdl&colon;IdentityElementInput';
          VAL = NULL;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;IdentityElementInput:identity:external_id';
          VAL = LESSON_ID;
          SUSPEND;

          N = N + 1;
          IF(N >= 10000) THEN
          BEGIN
              N = 0;
              TAG_NAME = NULL;
              VAL = 'DIVIDE';
              SUSPEND;
          END

      END

  END

  -- Уроки, где снят флаг проведения
  -- ...

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_PORTAL_CONTENT_TASKS (
    T_FROM TIMESTAMP,
    T_TO TIMESTAMP NOT NULL = current_timestamp,
    ID1 VARCHAR(40) = null,
    ID2 VARCHAR(40) = null,
    I$MODE SMALLINT = 0)
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(2000))
AS
declare variable YEAR_ID bigint;
declare variable LESSON_ID bigint;
declare variable S varchar(1000);
declare variable N integer;
begin

  SELECT FIRST 1 V1236.LISTVAL_ID
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :YEAR_ID;

  N = 0;

  FOR
      SELECT L.OBJ_ID, L.LESSON_HOMEWORK
      FROM CJ2_JOURNAL J
      JOIN CJ2_JOURNAL_LESSONS L ON L.CJ_ID = J.OBJ_ID AND L.DATE_DEL IS NULL
      JOIN LINKS L179 ON L179.OBJ_ID = J.GRADE_ID AND L179.OBJ_TYPE_ID = 179 AND L179.PARENT_TYPE_ID = 2 AND L179.DATE_DEL IS NULL
      -- Признак группы ЦОПП
      LEFT JOIN VALL V3064 ON V3064.OBJ_ID = L179.OBJ_ID AND V3064.PARAM_ID = 3064 AND V3064.IS_DEL = 0
      WHERE J.DATE_DEL IS NULL AND J.JOURNAL_TYPE IN (0/*, 1*/) AND J.YEAR_ID = :YEAR_ID
          AND (L.IS_COMPLETED = 1 OR L.IS_PUBLISHED = 1) AND ((:T_FROM IS NULL OR L.DATE_MODIFY >= :T_FROM) AND L.DATE_MODIFY < :T_TO) --AND GS.PLAN_TYPE_ID IN (5465, 5466)
          AND ((:I$MODE = 0 AND (V3064.LISTVAL_ID IS NULL OR V3064.LISTVAL_ID = 3)) OR (:I$MODE = 1 AND V3064.LISTVAL_ID = 2))
      INTO :LESSON_ID, :S
  DO
  BEGIN

      S = REPLACE(S, ASCII_CHAR(13), '');
      S = REPLACE(S, ASCII_CHAR(10), '');
      S = REPLACE(S, ASCII_CHAR(9), '');
      S = TRIM(S);

      IF(CHAR_LENGTH(S) > 0) THEN
      BEGIN

          TAG_NAME = 'wsdl&colon;ContentTaskInput';
          VAL = NULL;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;ContentTaskInput:identity:external_id';
          VAL = LESSON_ID;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;ContentTaskInput:content_id:external_id';
          VAL = LESSON_ID;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;ContentTaskInput:task_id:external_id';
          VAL = LESSON_ID;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;ContentTaskInput:kind:code';
          VAL = 'homework';
          SUSPEND;

          N = N + 1;
          IF(N >= 10000) THEN
          BEGIN
              N = 0;
              TAG_NAME = NULL;
              VAL = 'DIVIDE';
              SUSPEND;
          END

      END

  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_PORTAL_CONTENT_TASKS_DELETE (
    T_FROM TIMESTAMP,
    T_TO TIMESTAMP NOT NULL = CURRENT_TIMESTAMP,
    ID1 VARCHAR(40) = NULL,
    ID2 VARCHAR(40) = NULL,
    I$MODE SMALLINT = 0)
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(2000))
AS
DECLARE VARIABLE YEAR_ID BIGINT;
DECLARE VARIABLE IS_OK SMALLINT;
DECLARE VARIABLE LESSON_ID BIGINT;
DECLARE VARIABLE LESSON_DT TIMESTAMP;
DECLARE VARIABLE N INTEGER;
begin

  IF(T_FROM IS NULL) THEN EXIT;

  SELECT FIRST 1 V1236.LISTVAL_ID
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :YEAR_ID;

  N = 0;

  -- Реально удаленные уроки
  FOR
      SELECT L.OBJ_ID, L.DATE_DEL
      FROM CJ2_JOURNAL J
      JOIN CJ2_JOURNAL_LESSONS L ON L.CJ_ID = J.OBJ_ID AND L.DATE_DEL IS NOT NULL
      JOIN LINKS L179 ON L179.OBJ_ID = J.GRADE_ID AND L179.OBJ_TYPE_ID = 179 AND L179.PARENT_TYPE_ID = 2 AND L179.DATE_DEL IS NULL
      -- Признак группы ЦОПП
      LEFT JOIN VALL V3064 ON V3064.OBJ_ID = L179.OBJ_ID AND V3064.PARAM_ID = 3064 AND V3064.IS_DEL = 0
      WHERE J.DATE_DEL IS NOT NULL AND J.JOURNAL_TYPE IN (0, 1) AND J.YEAR_ID = :YEAR_ID
          AND ((:I$MODE = 0 AND (V3064.LISTVAL_ID IS NULL OR V3064.LISTVAL_ID = 3)) OR (:I$MODE = 1 AND V3064.LISTVAL_ID = 2))
      INTO :LESSON_ID, :LESSON_DT
  DO
  BEGIN

      IS_OK = 0;
      IF(
          ((T_FROM IS NULL OR LESSON_DT >= T_FROM) AND LESSON_DT < T_TO)
      )
      THEN
          IS_OK = 1;

      IF(IS_OK = 1) THEN
      BEGIN

          TAG_NAME = 'wsdl&colon;IdentityElementInput';
          VAL = NULL;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;IdentityElementInput:identity:external_id';
          VAL = LESSON_ID;
          SUSPEND;

          N = N + 1;
          IF(N >= 10000) THEN
          BEGIN
              N = 0;
              TAG_NAME = NULL;
              VAL = 'DIVIDE';
              SUSPEND;
          END

      END

  END

  -- Уроки, где снят флаг проведения
  -- ...

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_PORTAL_EDUCATION (
    T_FROM TIMESTAMP,
    T_TO TIMESTAMP NOT NULL = current_timestamp,
    ID1 VARCHAR(40) = null,
    ID2 VARCHAR(40) = null,
    I$MODE SMALLINT = 0)
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(2000))
AS
declare variable LEVEL_DT timestamp;
declare variable STAGE_DT timestamp;
declare variable CLASS_DT timestamp;
declare variable IS_OK smallint;
declare variable STUDENT_ID bigint;
declare variable STUDENT_DT timestamp;
declare variable DATE_P_UID1 timestamp;
declare variable DATE_P_UID2 timestamp;
declare variable YEAR_ID bigint;
declare variable YEAR_START date;
declare variable DM4X timestamp;
declare variable N integer;
declare variable V$COPP bigint;
declare variable V4X varchar(100);
begin

  -- Суть выгрузки: связка персоналий с учебными заведениями, уровнем и этапом обучения
  -- изменение в любом сечении {ОУ, уровень, этап} формирует новую запись
  -- в качестве ID записей используем ID ученика

  IF(ID1 IS NULL) THEN
  BEGIN
      SELECT FIRST 1 V2910.VAL
      FROM LINKS L2
      JOIN VALS V2910 ON V2910.OBJ_ID = L2.OBJ_ID AND V2910.PARAM_ID = 2910 AND V2910.IS_DEL = 0
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      INTO :ID1;
  END

  SELECT FIRST 1 V1236.LISTVAL_ID, '01.09.' || CAST(LV.COST AS INTEGER)
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :YEAR_ID, :YEAR_START;

  N = 0;

  -- Действующие учащиеся
  FOR
      SELECT L7.DATE_MODIFY, L8.DATE_MODIFY, L9.DATE_MODIFY, L10.OBJ_ID, L10.DATE_MODIFY
      FROM LINKS L2
      -- Уровень образования
      JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
      JOIN VALL V43 ON V43.OBJ_ID = L7.OBJ_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0
      -- Этап обучения
      JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
      JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
      -- Класс
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 125, 187) AND L9.DATE_DEL IS NULL
      -- Признак группы ЦОПП
      LEFT JOIN VALL V3063 ON V3063.OBJ_ID = L9.OBJ_ID AND V3063.PARAM_ID = 3063 AND V3063.IS_DEL = 0
      JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
          AND ((:I$MODE = 0 AND (V3063.LISTVAL_ID IS NULL OR V3063.LISTVAL_ID = 3)) OR (:I$MODE = 1 AND V3063.LISTVAL_ID = 2))
      INTO :LEVEL_DT, :STAGE_DT, :CLASS_DT, :STUDENT_ID, :STUDENT_DT
  DO
  BEGIN

      -- Наличие и дата изменения кодов - выгружаем только данные по учащимся, у которых есть портальные идентификаторы
      DATE_P_UID1 = NULL;
      DATE_P_UID2 = NULL;
      SELECT MAX(V1570.DATE_MODIFY), MAX(V155.DATE_MODIFY)
      FROM LINKS L20
      JOIN VALS V1570 ON V1570.OBJ_ID = L20.EXT_OBJ_ID AND V1570.PARAM_ID = 1570 AND V1570.IS_DEL = 0
      JOIN VALS V155 ON V155.OBJ_ID = L20.OBJ_ID AND V155.PARAM_ID = 155 AND V155.IS_DEL = 0
      WHERE L20.PARENT_ID = :STUDENT_ID AND L20.OBJ_TYPE_ID = 20 AND L20.DATE_DEL IS NULL
      INTO :DATE_P_UID1, :DATE_P_UID2;

      SELECT V3060.SVAL, V3060.DATE_MODIFY
      FROM RDB$DATABASE
      LEFT JOIN VALS V3060 ON V3060.OBJ_ID = :STUDENT_ID AND V3060.PARAM_ID = 3060 AND V3060.IS_DEL = 0
      INTO :V4X, :DM4X;

      -- В ЦОПП заменяем код ученика на код сотрудника, если он же внесен
      IF(I$MODE = 1) THEN
      BEGIN
          SELECT FIRST 1 V3061.OBJ_ID
          FROM VALS V3061
          WHERE V3061.PARAM_ID = 3061 AND V3061.IS_DEL = 0 AND V3061.SVAL = :V4X
          INTO :STUDENT_ID;
      END

      IS_OK = 0;
      IF(((DATE_P_UID1 IS NOT NULL AND DATE_P_UID2 IS NOT NULL AND I$MODE = 0) OR (DM4X IS NOT NULL AND I$MODE = 1)) AND
        (
          ((T_FROM IS NULL OR LEVEL_DT >= T_FROM) AND (LEVEL_DT < T_TO)) OR
          ((T_FROM IS NULL OR STAGE_DT >= T_FROM) AND (STAGE_DT < T_TO)) OR
          ((T_FROM IS NULL OR CLASS_DT >= T_FROM) AND (CLASS_DT < T_TO)) OR
          ((T_FROM IS NULL OR STUDENT_DT >= T_FROM) AND (STUDENT_DT < T_TO)) OR
          ((T_FROM IS NULL OR DATE_P_UID1 >= T_FROM) AND (DATE_P_UID1 < T_TO)) OR
          ((T_FROM IS NULL OR DATE_P_UID2 >= T_FROM) AND (DATE_P_UID2 < T_TO)) OR
          ((T_FROM IS NULL OR DM4X >= T_FROM) AND (DM4X < T_TO))
        )
      )
      THEN
          IS_OK = 1;

      IF(IS_OK = 1) THEN
      BEGIN

          TAG_NAME = 'wsdl&colon;EducationInput';
          VAL = NULL;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;EducationInput:identity:external_id';
          VAL = STUDENT_ID;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;EducationInput:person_id:external_id';
          VAL = STUDENT_ID;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;EducationInput:institution_id:id';
          VAL = ID1;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;EducationInput:date_from';
          VAL = NULL;
          SELECT FIRST 1 D.VAL
          FROM PERSON_MOVEMENTS M
          JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
          -- нет записи зачисления с более поздней датой
          LEFT JOIN PERSON_MOVEMENTS M2 ON M2.DATE_DEL IS NULL AND M2.PERSON_ID = M.PERSON_ID AND M2.DATE_IN > M.DATE_IN AND M2.REASON_IN IN (805, 806)
          LEFT JOIN DATE2ISO(M.DATE_IN, 0) D ON 1 = 1
          WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :STUDENT_ID AND M2.OBJ_ID IS NULL
          ORDER BY M.DATE_IN
          INTO :VAL;
          SUSPEND;

          N = N + 1;
          IF(N >= 10000) THEN
          BEGIN
              N = 0;
              TAG_NAME = NULL;
              VAL = 'DIVIDE';
              SUSPEND;
          END

      END

  END

  -- Выбывшие учащиеся
  -- Для ЦОПП шлем только тех, кто был в группах ЦОПП
  FOR
      -- Выбывшие в учебном году
      SELECT L10.OBJ_ID, L10.DATE_MODIFY
      FROM LINKS L2
      JOIN LINKS L78 ON L78.PARENT_ID = L2.OBJ_ID AND L78.OBJ_TYPE_ID = 78 AND L78.DATE_DEL IS NULL
      JOIN LINKS L82 ON L82.PARENT_ID = L78.OBJ_ID AND L82.OBJ_TYPE_ID = 82 AND L82.DATE_DEL IS NULL
      JOIN VALI V448 ON V448.OBJ_ID = L82.OBJ_ID AND V448.PARAM_ID = 448 AND V448.IS_DEL = 0 AND V448.VAL = EXTRACT(YEAR FROM :YEAR_START)
      JOIN LINKS L10 ON L10.PARENT_ID = L82.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      -- Выпуск календарного года
      INTO :STUDENT_ID, :STUDENT_DT
  DO
  BEGIN

      -- Числился ли ученик в группе ЦОПП
      V$COPP = 3;
      SELECT MIN(V3063.LISTVAL_ID)
      FROM LINKS LP9
      JOIN VALL V3063 ON V3063.OBJ_ID = LP9.PARENT_ID AND V3063.PARAM_ID = 3063 AND V3063.IS_DEL = 0
      WHERE LP9.OBJ_ID = :STUDENT_ID AND LP9.PARENT_TYPE_ID = 9
      INTO :V$COPP;

      -- Наличие и дата изменения кодов - выгружаем только данные по учащимся, у которых есть портальные идентификаторы
      DATE_P_UID1 = NULL;
      DATE_P_UID2 = NULL;
      SELECT MAX(V1570.DATE_MODIFY), MAX(V155.DATE_MODIFY)
      FROM LINKS L20
      JOIN VALS V1570 ON V1570.OBJ_ID = L20.EXT_OBJ_ID AND V1570.PARAM_ID = 1570 AND V1570.IS_DEL = 0
      JOIN VALS V155 ON V155.OBJ_ID = L20.OBJ_ID AND V155.PARAM_ID = 155 AND V155.IS_DEL = 0
      WHERE L20.PARENT_ID = :STUDENT_ID AND L20.OBJ_TYPE_ID = 20 AND L20.DATE_DEL IS NULL
      INTO :DATE_P_UID1, :DATE_P_UID2;

      SELECT V3060.SVAL, V3060.DATE_MODIFY
      FROM RDB$DATABASE
      LEFT JOIN VALS V3060 ON V3060.OBJ_ID = :STUDENT_ID AND V3060.PARAM_ID = 3060 AND V3060.IS_DEL = 0
      INTO :V4X, :DM4X;

      -- В ЦОПП заменяем код ученика на код сотрудника, если он же внесен
      IF(I$MODE = 1) THEN
      BEGIN
          SELECT FIRST 1 V3061.OBJ_ID
          FROM VALS V3061
          WHERE V3061.PARAM_ID = 3061 AND V3061.IS_DEL = 0 AND V3061.SVAL = :V4X
          INTO :STUDENT_ID;
      END

      IS_OK = 0;
      IF(((DATE_P_UID1 IS NOT NULL AND DATE_P_UID2 IS NOT NULL AND I$MODE = 0) OR (I$MODE = 1 AND V$COPP = 2)) AND
        (
          ((T_FROM IS NULL OR STUDENT_DT >= T_FROM) AND (STUDENT_DT < T_TO)) OR
          ((T_FROM IS NULL OR DATE_P_UID1 >= T_FROM) AND (DATE_P_UID1 < T_TO)) OR
          ((T_FROM IS NULL OR DATE_P_UID2 >= T_FROM) AND (DATE_P_UID2 < T_TO)) OR
          ((T_FROM IS NULL OR DM4X >= T_FROM) AND (DM4X < T_TO))
        )
      )
      THEN
          IS_OK = 1;

      IF(IS_OK = 1) THEN
      BEGIN

          TAG_NAME = 'wsdl&colon;EducationInput';
          VAL = NULL;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;EducationInput:identity:external_id';
          VAL = STUDENT_ID;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;EducationInput:person_id:external_id';
          VAL = STUDENT_ID;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;EducationInput:institution_id:id';
          VAL = ID1;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;EducationInput:date_from';
          VAL = NULL;
          SELECT FIRST 1 D.VAL
          FROM PERSON_MOVEMENTS M
          JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
          -- нет записи зачисления с более поздней датой
          LEFT JOIN PERSON_MOVEMENTS M2 ON M2.DATE_DEL IS NULL AND M2.PERSON_ID = M.PERSON_ID AND M2.DATE_IN > M.DATE_IN AND M2.REASON_IN IN (805, 806)
          LEFT JOIN DATE2ISO(M.DATE_IN, 0) D ON 1 = 1
          WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :STUDENT_ID AND M2.OBJ_ID IS NULL
          ORDER BY M.DATE_IN
          INTO :VAL;
          SUSPEND;

          N = N + 1;
          IF(N >= 10000) THEN
          BEGIN
              N = 0;
              TAG_NAME = NULL;
              VAL = 'DIVIDE';
              SUSPEND;
          END

      END

  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_PORTAL_EDUCATION_DELETE (
    T_FROM TIMESTAMP,
    T_TO TIMESTAMP NOT NULL = current_timestamp,
    ID1 VARCHAR(40) = null,
    ID2 VARCHAR(40) = null,
    I$MODE SMALLINT = 0)
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(2000))
AS
declare variable CURRENT_PERIOD_ID bigint;
declare variable CURRENT_YEAR integer;
declare variable CURRENT_PERIOD_START date;
declare variable PERSON_ID bigint;
declare variable PERSON_EXIT_DT timestamp;
declare variable N integer;
declare variable N_REFS integer;
begin

  IF(T_FROM IS NULL) THEN EXIT;

  IF(ID1 IS NULL) THEN
  BEGIN
      SELECT FIRST 1 V2910.VAL
      FROM LINKS L2
      JOIN VALS V2910 ON V2910.OBJ_ID = L2.OBJ_ID AND V2910.PARAM_ID = 2910 AND V2910.IS_DEL = 0
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      INTO :ID1;
  END

  SELECT FIRST 1 V1236.LISTVAL_ID, LV.COST
  FROM LINKS L2
  LEFT JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  LEFT JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :CURRENT_PERIOD_ID, :CURRENT_YEAR;

  CURRENT_PERIOD_START = '20.08.' || CURRENT_YEAR;

  N = 0;

  FOR
      -- Все актуальные учащиеся
      SELECT L10.OBJ_ID, NULL
      FROM LINKS L2
      JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
      JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 125, 187) AND L9.DATE_DEL IS NULL
      JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      -- Учащиеся, удаленные отовсюду (смотрим только основную ветку) - не ранее чем начало текущего учебного года
      UNION
      SELECT L10.OBJ_ID, MAX(L10.DATE_MODIFY)
      FROM LINKS L2
      JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
      JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 125, 187) AND L9.DATE_DEL IS NULL
      JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL > :CURRENT_PERIOD_START
      LEFT JOIN LINKS LPG ON LPG.OBJ_ID = L10.OBJ_ID AND LPG.PARENT_TYPE_ID IN (9, 125, 187, 82, 83) AND LPG.DATE_DEL IS NULL
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND LPG.PARENT_ID IS NULL
      GROUP BY 1
      ORDER BY 1
      INTO :PERSON_ID, :PERSON_EXIT_DT
  DO
  BEGIN

      -- Для действующих учащихся проверяем наличие пары портальных кодов хотя бы у одного из родителей
      IF(PERSON_EXIT_DT IS NULL) THEN
      BEGIN

          SELECT COUNT(*)
          FROM LINKS L20
          JOIN VALS V1570 ON V1570.OBJ_ID = L20.EXT_OBJ_ID AND V1570.PARAM_ID = 1570 AND V1570.IS_DEL = 0
          JOIN VALS V155 ON V155.OBJ_ID = L20.OBJ_ID AND V155.PARAM_ID = 155 AND V155.IS_DEL = 0
          WHERE L20.PARENT_ID = :PERSON_ID AND L20.OBJ_TYPE_ID = 20 AND L20.DATE_DEL IS NULL
          INTO :N_REFS;

          -- Кодов нет. Проверяем, были ли коды или родители вообще заданы когда-либо
          IF(N_REFS = 0) THEN
          BEGIN

              SELECT COUNT(*)
              FROM LINKS L20
              JOIN VALS V1570 ON V1570.OBJ_ID = L20.EXT_OBJ_ID AND V1570.PARAM_ID = 1570
              JOIN VALS V155 ON V155.OBJ_ID = L20.OBJ_ID AND V155.PARAM_ID = 155
              WHERE L20.PARENT_ID = :PERSON_ID AND L20.OBJ_TYPE_ID = 20
              INTO :N_REFS;

              IF(N_REFS > 0) THEN
              BEGIN

                  SELECT MAX(DATE_MODIFY) FROM (
                      SELECT L20.DATE_MODIFY
                      FROM LINKS L20
                      WHERE L20.PARENT_ID = :PERSON_ID AND L20.OBJ_TYPE_ID = 20
                      UNION
                      SELECT V1570.DATE_MODIFY
                      FROM LINKS L20
                      JOIN VALS V1570 ON V1570.OBJ_ID = L20.EXT_OBJ_ID AND V1570.PARAM_ID = 1570
                      WHERE L20.PARENT_ID = :PERSON_ID AND L20.OBJ_TYPE_ID = 20
                      UNION
                      SELECT V155.DATE_MODIFY
                      FROM LINKS L20
                      JOIN VALS V155 ON V155.OBJ_ID = L20.OBJ_ID AND V155.PARAM_ID = 155
                      WHERE L20.PARENT_ID = :PERSON_ID AND L20.OBJ_TYPE_ID = 20
                  )
                  INTO :PERSON_EXIT_DT;

              END

          END

      END

      IF(PERSON_EXIT_DT IS NOT NULL AND (T_FROM IS NULL OR PERSON_EXIT_DT >= T_FROM)) THEN
      BEGIN

          TAG_NAME = 'wsdl&colon;IdentityElementInput';
          VAL = NULL;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;IdentityElementInput:identity:external_id';
          VAL = PERSON_ID;
          SUSPEND;

          N = N + 1;
          IF(N >= 10000) THEN
          BEGIN
              N = 0;
              TAG_NAME = NULL;
              VAL = 'DIVIDE';
              SUSPEND;
          END

      END

  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_PORTAL_EDUCATION_GROUPS (
    T_FROM TIMESTAMP,
    T_TO TIMESTAMP NOT NULL = current_timestamp,
    ID1 VARCHAR(40) = null,
    ID2 VARCHAR(40) = null,
    I$MODE SMALLINT = 0)
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(2000))
AS
declare variable IS_OK smallint;
declare variable LEVEL_DT timestamp;
declare variable STAGE_DT timestamp;
declare variable CLASS_DT timestamp;
declare variable STUDENT_ID bigint;
declare variable REAL_STUDENT_ID bigint;
declare variable CURRENT_LC_ID bigint;
declare variable STUDENT_DT timestamp;
declare variable DATE_P_UID1 timestamp;
declare variable DATE_P_UID2 timestamp;
declare variable DM4X timestamp;
declare variable GROUP_ID bigint;
declare variable GROUP_DT timestamp;
declare variable GROUP_TYPE bigint;
declare variable MOVE_ID bigint;
declare variable IN_DATE date;
declare variable OUT_DATE date;
declare variable YEAR_START date;
declare variable IS_GROUP smallint;
declare variable YEAR_ID bigint;
declare variable CURRENT_YEAR integer;
declare variable N integer;
declare variable V$ADM_GROUP_ID bigint;
declare variable V4X varchar(100);
begin

  -- Возвращаем все группы, где ученик побывал, по реестру движения

  N = 0;

  SELECT FIRST 1 V1236.LISTVAL_ID, '25.08.' || CAST(LV.COST AS INTEGER), LV.COST
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :YEAR_ID, :YEAR_START, :CURRENT_YEAR;

  FOR
      -- Действующие учащиеся
      SELECT L7.DATE_MODIFY, L8.DATE_MODIFY, L9.DATE_MODIFY, L10.OBJ_ID, L10.DATE_MODIFY, L10.PARENT_TYPE_ID, L9.OBJ_ID
      FROM LINKS L2
      -- Уровень образования
      JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
      JOIN VALL V43 ON V43.OBJ_ID = L7.OBJ_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0
      -- Этап обучения
      JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
      JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
      -- Класс
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 125, 187) AND L9.DATE_DEL IS NULL
      -- Признак группы ЦОПП
      LEFT JOIN VALL V3063 ON V3063.OBJ_ID = L9.OBJ_ID AND V3063.PARAM_ID = 3063 AND V3063.IS_DEL = 0
      JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
          AND ((:I$MODE = 0 AND (V3063.LISTVAL_ID IS NULL OR V3063.LISTVAL_ID = 3)) OR (:I$MODE = 1 AND V3063.LISTVAL_ID = 2))
      -- Выбывшие или окончившие в текущем году
      UNION
      SELECT '01.01.2018', '01.01.2018', L82.DATE_MODIFY, L10.OBJ_ID, L10.DATE_MODIFY, L10.PARENT_TYPE_ID, NULL
      FROM LINKS L2
      JOIN LINKS L78 ON L78.PARENT_ID = L2.OBJ_ID AND L78.OBJ_TYPE_ID = 78 AND L78.DATE_DEL IS NULL
      JOIN LINKS L82 ON L82.PARENT_ID = L78.OBJ_ID AND L82.OBJ_TYPE_ID = 82 AND L82.DATE_DEL IS NULL
      JOIN VALI V448 ON V448.OBJ_ID = L82.OBJ_ID AND V448.PARAM_ID = 448 AND V448.IS_DEL = 0 AND V448.VAL = :CURRENT_YEAR
      JOIN LINKS L10 ON L10.PARENT_ID = L82.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      -- Выпуск календарного года
      UNION
      SELECT '01.01.2018', '01.01.2018', L83.DATE_MODIFY, L10.OBJ_ID, L10.DATE_MODIFY, L10.PARENT_TYPE_ID, NULL
      FROM LINKS L2
      JOIN LINKS L78 ON L78.PARENT_ID = L2.OBJ_ID AND L78.OBJ_TYPE_ID = 78 AND L78.DATE_DEL IS NULL
      JOIN LINKS L83 ON L83.PARENT_ID = L78.OBJ_ID AND L83.OBJ_TYPE_ID = 83 AND L83.DATE_DEL IS NULL
      JOIN VALI V451 ON V451.OBJ_ID = L83.OBJ_ID AND V451.PARAM_ID = 451 AND V451.IS_DEL = 0 AND V451.VAL = EXTRACT(YEAR FROM CURRENT_DATE)
      JOIN LINKS L10 ON L10.PARENT_ID = L83.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      INTO :LEVEL_DT, :STAGE_DT, :CLASS_DT, :STUDENT_ID, :STUDENT_DT, :CURRENT_LC_ID, :V$ADM_GROUP_ID
  DO
  BEGIN

      /*TAG_NAME = '!!!! student !!!!';
      VAL = STUDENT_ID;
      SUSPEND;*/

      -- Если выбывший, проверяем, был ли он в группе ЦОПП или нет
      IF(V$ADM_GROUP_ID IS NULL) THEN
      BEGIN
        -- TODO !!!
      END

      -- Наличие и дата изменения кодов - выгружаем только данные по учащимся, у которых есть портальные идентификаторы
      DATE_P_UID1 = NULL;
      DATE_P_UID2 = NULL;
      SELECT MAX(V1570.DATE_MODIFY), MAX(V155.DATE_MODIFY)
      FROM LINKS L20
      JOIN VALS V1570 ON V1570.OBJ_ID = L20.EXT_OBJ_ID AND V1570.PARAM_ID = 1570 AND V1570.IS_DEL = 0
      JOIN VALS V155 ON V155.OBJ_ID = L20.OBJ_ID AND V155.PARAM_ID = 155 AND V155.IS_DEL = 0
      WHERE L20.PARENT_ID = :STUDENT_ID AND L20.OBJ_TYPE_ID = 20 AND L20.DATE_DEL IS NULL
      INTO :DATE_P_UID1, :DATE_P_UID2;

      SELECT V3060.SVAL, V3060.DATE_MODIFY
      FROM RDB$DATABASE
      LEFT JOIN VALS V3060 ON V3060.OBJ_ID = :STUDENT_ID AND V3060.PARAM_ID = 3060 AND V3060.IS_DEL = 0
      INTO :V4X, :DM4X;

      -- Есть ли изменения в связях с группами ?
      GROUP_DT = NULL;
      SELECT MAX(LPG.DATE_MODIFY)
      FROM LINKS LPG
      WHERE LPG.OBJ_ID = :STUDENT_ID AND LPG.PARENT_TYPE_ID IN (9, 125, 179, 187, 256, 48, 347)
      INTO :GROUP_DT;

      -- В ЦОПП заменяем код ученика на код сотрудника, если он же внесен
      REAL_STUDENT_ID = STUDENT_ID;
      IF(I$MODE = 1) THEN
      BEGIN
          SELECT FIRST 1 V3061.OBJ_ID
          FROM VALS V3061
          WHERE V3061.PARAM_ID = 3061 AND V3061.IS_DEL = 0 AND V3061.SVAL = :V4X
          INTO :REAL_STUDENT_ID;
      END

      IS_OK = 0;
      IF(((DATE_P_UID1 IS NOT NULL AND DATE_P_UID2 IS NOT NULL AND I$MODE = 0) OR (DM4X IS NOT NULL AND I$MODE = 1)) AND
        (
          ((T_FROM IS NULL OR LEVEL_DT >= T_FROM) AND (LEVEL_DT < T_TO)) OR
          ((T_FROM IS NULL OR STAGE_DT >= T_FROM) AND (STAGE_DT < T_TO)) OR
          ((T_FROM IS NULL OR CLASS_DT >= T_FROM) AND (CLASS_DT < T_TO)) OR
          ((T_FROM IS NULL OR STUDENT_DT >= T_FROM) AND (STUDENT_DT < T_TO)) OR
          ((T_FROM IS NULL OR DATE_P_UID1 >= T_FROM) AND (DATE_P_UID1 < T_TO)) OR
          ((T_FROM IS NULL OR DATE_P_UID2 >= T_FROM) AND (DATE_P_UID2 < T_TO)) OR
          ((T_FROM IS NULL OR DM4X >= T_FROM) AND (DM4X < T_TO)) OR
          ((T_FROM IS NULL OR GROUP_DT >= T_FROM) AND (GROUP_DT < T_TO))
        )
      )
      THEN
          IS_OK = 1;

      IF(IS_OK = 1) THEN
      BEGIN

          -- Идем по всем группам, где ученик числился (в том числе по удаленным), и далее по реестру движений
          -- но сама группа должна существовать, иначе сама группа не будет присутствовать в выгрузке
          FOR
              SELECT DISTINCT LPG.PARENT_ID, LPG.PARENT_TYPE_ID
              FROM LINKS LPG
              JOIN LINKS LPS ON LPS.OBJ_ID = LPG.PARENT_ID AND LPS.PARENT_TYPE_ID IN (2, 8, 54, 346) AND LPS.DATE_DEL IS NULL
              WHERE LPG.OBJ_ID = :STUDENT_ID AND LPG.PARENT_TYPE_ID IN (9, 125, 179, 187, 256, 48, 347)
              ORDER BY 2
              INTO :GROUP_ID, :GROUP_TYPE
          DO
          BEGIN

              /* TAG_NAME = '!!!! group !!!!';
              VAL = GROUP_TYPE || ' // ' || GROUP_ID;
              SUSPEND; */

              -- Фильтруем только групповые УП, а также отсекаем не-общеобразовательные
              IS_GROUP = 0;
              IF(GROUP_TYPE = 256) THEN
              BEGIN
                  SELECT FIRST 1 1
                  FROM LINKS LP54
                  JOIN LINKS LP400 ON LP400.OBJ_ID = LP54.PARENT_ID AND LP400.PARENT_TYPE_ID = 400 AND LP400.DATE_DEL IS NULL
                  JOIN VALL V3016 ON V3016.OBJ_ID = LP400.PARENT_ID AND V3016.PARAM_ID = 3016 AND V3016.IS_DEL = 0 AND V3016.LISTVAL_ID IN (5465, 5466)
                  WHERE LP54.OBJ_ID = :GROUP_ID AND LP54.PARENT_TYPE_ID = 54 AND LP54.DATE_DEL IS NULL
                  INTO :IS_GROUP;

                  IF(IS_GROUP IS NULL OR IS_GROUP = 0) THEN GROUP_ID = NULL;
                  IF(YEAR_ID >= 10981) THEN GROUP_ID = NULL;
              END
              ELSE IF(GROUP_TYPE = 347) THEN
              BEGIN
                  SELECT FIRST 1 1
                  FROM LINKS LP346
                  JOIN LINKS LP54 ON LP54.OBJ_ID = LP346.PARENT_ID AND LP54.PARENT_TYPE_ID = 54 AND LP54.DATE_DEL IS NULL
                  JOIN LINKS LP400 ON LP400.OBJ_ID = LP54.PARENT_ID AND LP400.PARENT_TYPE_ID = 400 AND LP400.DATE_DEL IS NULL
                  JOIN VALL V3016 ON V3016.OBJ_ID = LP400.PARENT_ID AND V3016.PARAM_ID = 3016 AND V3016.IS_DEL = 0 AND V3016.LISTVAL_ID IN (5465, 5466)
                  WHERE LP346.OBJ_ID = :GROUP_ID AND LP346.PARENT_TYPE_ID = 346 AND LP346.DATE_DEL IS NULL
                  INTO :IS_GROUP;

                  IF(IS_GROUP IS NULL OR IS_GROUP = 0) THEN GROUP_ID = NULL;
                  IF(YEAR_ID >= 10981) THEN GROUP_ID = NULL;
              END
              ELSE IF(GROUP_TYPE = 179) THEN
              BEGIN
                  -- Добавляем сюда ВД и мероприятия
                  SELECT FIRST 1 1
                  FROM CJ2_JOURNAL J
                  WHERE J.DATE_DEL IS NULL AND J.GRADE_ID = :GROUP_ID AND J.JOURNAL_TYPE IN (0, 1, 10, 11) AND J.YEAR_ID = :YEAR_ID
                  INTO :IS_GROUP;

                  IF(IS_GROUP IS NULL OR IS_GROUP = 0) THEN GROUP_ID = NULL;
              END

              FOR
                  SELECT M.OBJ_ID, M.DATE_IN, M.DATE_OUT
                  FROM PERSON_MOVEMENTS M
                  WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :STUDENT_ID AND M.GROUP_ID = :GROUP_ID AND M.DATE_IN >= :YEAR_START
                  ORDER BY M.OBJ_ID
                  INTO :MOVE_ID, :IN_DATE, :OUT_DATE
              DO
              BEGIN

                  TAG_NAME = 'wsdl&colon;EducationGroupInput';
                  VAL = NULL;
                  SUSPEND;

                  /* TAG_NAME = 'wsdl&colon;EducationGroupInput:group_type';
                  VAL = GROUP_TYPE;
                  SUSPEND; */

                  TAG_NAME = 'wsdl&colon;EducationGroupInput:identity:external_id';
                  VAL = MOVE_ID;
                  SUSPEND;

                  TAG_NAME = 'wsdl&colon;EducationGroupInput:education_id:external_id';
                  VAL = REAL_STUDENT_ID;
                  SUSPEND;

                  TAG_NAME = 'wsdl&colon;EducationGroupInput:group_id:external_id';
                  VAL = GROUP_ID;
                  SUSPEND;

                  TAG_NAME = 'wsdl&colon;EducationGroupInput:date_from';
                  VAL = (SELECT VAL FROM DATE2ISO(:IN_DATE, 0));
                  SUSPEND;

                  TAG_NAME = 'wsdl&colon;EducationGroupInput:date_to';
                  VAL = (SELECT VAL FROM DATE2ISO(:OUT_DATE, 0));
                  SUSPEND;

                  N = N + 1;
                  IF(N >= 10000) THEN
                  BEGIN
                      N = 0;
                      TAG_NAME = NULL;
                      VAL = 'DIVIDE';
                      SUSPEND;
                  END

              END

          END

          -- Кроме выбывших и экстернатников
          /*
          IF(CURRENT_LC_ID IN (9, 125) AND N1 = 0) THEN
              EXCEPTION DATA_ERROR 'Учащийся ' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:STUDENT_ID)) || ' был зачислен некорректной датой за пределами текущего учебного года';
          */

      END

  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_PORTAL_EDUCATION_GR_DELETE (
    T_FROM TIMESTAMP,
    T_TO TIMESTAMP NOT NULL = current_timestamp,
    ID1 VARCHAR(40) = null,
    ID2 VARCHAR(40) = null,
    I$MODE SMALLINT = 0)
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(2000))
AS
declare variable STUDENT_ID bigint;
declare variable MOVE_ID varchar(40);
declare variable MOVE_DT timestamp;
declare variable IS_OK smallint;
declare variable N integer;
begin

  IF(T_FROM IS NULL) THEN EXIT;

  N = 0;

  -- Здесь отрабатываем только реальные отмены участия в группах
  FOR
      SELECT L10.OBJ_ID
      FROM LINKS L2
      -- Уровень образования
      JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
      JOIN VALL V43 ON V43.OBJ_ID = L7.OBJ_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0
      -- Этап обучения
      JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
      JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
      -- Класс
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 125, 187) AND L9.DATE_DEL IS NULL
      -- Признак группы ЦОПП
      LEFT JOIN VALL V3063 ON V3063.OBJ_ID = L9.OBJ_ID AND V3063.PARAM_ID = 3063 AND V3063.IS_DEL = 0
      JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
          AND ((:I$MODE = 0 AND (V3063.LISTVAL_ID IS NULL OR V3063.LISTVAL_ID = 3)) OR (:I$MODE = 1 AND V3063.LISTVAL_ID = 2))
      INTO :STUDENT_ID
  DO
  BEGIN

      -- Идем по всем удаленным записям движения
      FOR
          SELECT 'M' || M.OBJ_ID, M.DATE_MODIFY
          FROM PERSON_MOVEMENTS M
          WHERE M.PERSON_ID = :STUDENT_ID AND M.DATE_DEL IS NOT NULL
          INTO :MOVE_ID, :MOVE_DT
      DO
      BEGIN

          IS_OK = 0;
          IF(
              ((T_FROM IS NULL OR MOVE_DT >= T_FROM) AND MOVE_DT < T_TO)
          )
          THEN
              IS_OK = 1;

          IF(IS_OK = 1) THEN
          BEGIN

              TAG_NAME = 'wsdl&colon;IdentityElementInput';
              VAL = NULL;
              SUSPEND;

              TAG_NAME = 'wsdl&colon;IdentityElementInput:identity:external_id';
              VAL = MOVE_ID;
              SUSPEND;

              N = N + 1;
              IF(N >= 10000) THEN
              BEGIN
                  N = 0;
                  TAG_NAME = NULL;
                  VAL = 'DIVIDE';
                  SUSPEND;
              END

          END

      END

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_PORTAL_ESTIMATES (
    T_FROM TIMESTAMP,
    T_TO TIMESTAMP NOT NULL = CURRENT_TIMESTAMP,
    ID1 VARCHAR(40) = NULL,
    ID2 VARCHAR(40) = NULL,
    I$MODE SMALLINT = 0)
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(2000))
AS
DECLARE VARIABLE MARK_ID VARCHAR(60);
DECLARE VARIABLE MARK_TYPE_ID BIGINT;
DECLARE VARIABLE TASK_ID BIGINT;
DECLARE VARIABLE MARK_COST FLOAT;
DECLARE VARIABLE SUBJECT_ID BIGINT;
DECLARE VARIABLE LESSON_ID BIGINT;
DECLARE VARIABLE MARK_DATE DATE;
DECLARE VARIABLE STUDENT_ID BIGINT;
DECLARE VARIABLE TEACHER_ID BIGINT;
DECLARE VARIABLE MARK_REF_CODE VARCHAR(30);
DECLARE VARIABLE MARK_TYPE_CODE VARCHAR(30);
DECLARE VARIABLE CONTROL_TYPE_ID BIGINT;
DECLARE VARIABLE MSG_TEXT VARCHAR(2000);
DECLARE VARIABLE FLAG_ABSENT SMALLINT;
DECLARE VARIABLE FLAG_LC SMALLINT;
DECLARE VARIABLE FLAG_MSG SMALLINT;
DECLARE VARIABLE DATE_ABSENT DATE;
DECLARE VARIABLE DATE_LC DATE;
DECLARE VARIABLE DATE_MSG DATE;
DECLARE VARIABLE ABSENT_REASON BIGINT;
DECLARE VARIABLE V$EVENT_DATE TIMESTAMP;
DECLARE VARIABLE V$LESSON_DATE TIMESTAMP;
DECLARE VARIABLE DATE_P_UID1 TIMESTAMP;
DECLARE VARIABLE DATE_P_UID2 TIMESTAMP;
DECLARE VARIABLE GROUP_ID BIGINT;
DECLARE VARIABLE YEAR_ID BIGINT;
DECLARE VARIABLE PERIOD_ID VARCHAR(60);
DECLARE VARIABLE MODULE_ID BIGINT;
DECLARE VARIABLE PERIOD_YEAR INTEGER;
DECLARE VARIABLE CURRENT_YEAR INTEGER;
DECLARE VARIABLE DM4X TIMESTAMP;
DECLARE VARIABLE PD1 DATE;
DECLARE VARIABLE PD2 DATE;
DECLARE VARIABLE IS_OK SMALLINT;
DECLARE VARIABLE N INTEGER;
DECLARE VARIABLE V$PLAN_ID BIGINT;
DECLARE VARIABLE V$PERIOD_TYPE BIGINT;
DECLARE VARIABLE V$PERIOD_FROM DATE;
DECLARE VARIABLE V$PERIOD_TO DATE;
DECLARE VARIABLE V4X VARCHAR(100);
DECLARE VARIABLE V$RATE_DATE DATE;
DECLARE VARIABLE V$INFO_ID BIGINT;
DECLARE VARIABLE V$INFO_DATE TIMESTAMP;
DECLARE VARIABLE CJ_ID BIGINT;
DECLARE VARIABLE S VARCHAR(1000);
begin

  IF(ID1 IS NULL) THEN
  BEGIN
      SELECT FIRST 1 V2910.VAL
      FROM LINKS L2
      JOIN VALS V2910 ON V2910.OBJ_ID = L2.OBJ_ID AND V2910.PARAM_ID = 2910 AND V2910.IS_DEL = 0
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      INTO :ID1;
  END

  SELECT FIRST 1 V1236.LISTVAL_ID, LV.COST
  FROM LINKS L2
  LEFT JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  LEFT JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :YEAR_ID, :CURRENT_YEAR;

  N = 0;

  -- Дополнение: не выгружаем оценки, по которым урок изменен позднее оценки - они прогрузятся в следующем пакете вместе с уроком

  -- Замечания и пропуски
  -- В качестве даты всегда ставим дату урока, а не дату внесения события
  FOR
      SELECT 'LX' || M.MARK_ID, IIF(M.MARK_TYPE_ID > 90 AND M.MARK_TYPE_ID < 99, 1, 0), IIF(M.MARK_TYPE_ID = 90, 1, 0), IIF(M.MARK_TYPE_ID = -1, 1, 0),
              M.STUDENT_ID, L.OBJ_ID, J.SUBJECT_ID, L.TEACHER_ID, J.GRADE_ID,
          M.COMMENTS_TEXT, L.LESSON_DATE, L.LESSON_DATE, L.LESSON_DATE,
          M.MARK_TYPE_ID, M.DATE_MODIFY, L.DATE_MODIFY
      FROM CJ2_JOURNAL J
      JOIN CJ2_JOURNAL_LESSONS L ON L.CJ_ID = J.OBJ_ID AND L.DATE_DEL IS NULL
      -- Признак группы ЦОПП
      LEFT JOIN VALL V3064 ON V3064.OBJ_ID = J.GRADE_ID AND V3064.PARAM_ID = 3064 AND V3064.IS_DEL = 0
      --
      JOIN CJ2_CONTROL C ON C.LESSON_ID = L.OBJ_ID AND C.DATE_DEL IS NULL AND C.CONTROL_TYPE_ID = 0
      JOIN CJ2_MARK M ON M.CONTROL_ID = C.CONTROL_ID AND M.DATE_DEL IS NULL AND (:I$MODE = 0 OR M.MARK_TYPE_ID > 0) -- замечания в ЦОПП не передаем
      WHERE J.DATE_DEL IS NULL AND J.JOURNAL_TYPE IN (0/*, 1*/) AND J.YEAR_ID = :YEAR_ID
          AND L.IS_COMPLETED = 1 --AND GS.PLAN_TYPE_ID IN (5465, 5466)
          AND ((:I$MODE = 0 AND (V3064.LISTVAL_ID IS NULL OR V3064.LISTVAL_ID = 3)) OR (:I$MODE = 1 AND V3064.LISTVAL_ID = 2))
      INTO :MARK_ID, :FLAG_ABSENT, :FLAG_LC, :FLAG_MSG, :STUDENT_ID, :LESSON_ID, :SUBJECT_ID, :TEACHER_ID, :GROUP_ID,
        :MSG_TEXT, :DATE_ABSENT, :DATE_LC, :DATE_MSG, :ABSENT_REASON, :V$EVENT_DATE, :V$LESSON_DATE
  DO
  BEGIN

      -- Наличие и дата изменения кодов
      DATE_P_UID1 = NULL;
      DATE_P_UID2 = NULL;
      SELECT MAX(V1570.DATE_MODIFY), MAX(V155.DATE_MODIFY)
      FROM LINKS L20
      JOIN VALS V1570 ON V1570.OBJ_ID = L20.EXT_OBJ_ID AND V1570.PARAM_ID = 1570 AND V1570.IS_DEL = 0
      JOIN VALS V155 ON V155.OBJ_ID = L20.OBJ_ID AND V155.PARAM_ID = 155 AND V155.IS_DEL = 0
      --JOIN LINKS LP9 ON LP9.OBJ_ID = L20.PARENT_ID AND LP9.PARENT_TYPE_ID IN (9, 125, 187) AND LP9.DATE_DEL IS NULL
      WHERE L20.PARENT_ID = :STUDENT_ID AND L20.OBJ_TYPE_ID = 20 AND L20.DATE_DEL IS NULL
      INTO :DATE_P_UID1, :DATE_P_UID2;

      SELECT V3060.SVAL, V3060.DATE_MODIFY
      FROM RDB$DATABASE
      LEFT JOIN VALS V3060 ON V3060.OBJ_ID = :STUDENT_ID AND V3060.PARAM_ID = 3060 AND V3060.IS_DEL = 0
      INTO :V4X, :DM4X;

      -- В ЦОПП заменяем код ученика на код сотрудника, если он же внесен
      IF(I$MODE = 1) THEN
      BEGIN
          SELECT FIRST 1 V3061.OBJ_ID
          FROM VALS V3061
          WHERE V3061.PARAM_ID = 3061 AND V3061.IS_DEL = 0 AND V3061.SVAL = :V4X
          INTO :STUDENT_ID;
      END

      IS_OK = 0;
      IF(((DATE_P_UID1 IS NOT NULL AND DATE_P_UID2 IS NOT NULL AND I$MODE = 0) OR (DM4X IS NOT NULL AND I$MODE = 1)) AND V$LESSON_DATE < T_TO
        AND (
          ((T_FROM IS NULL OR V$EVENT_DATE >= T_FROM) AND V$EVENT_DATE < T_TO) OR
          ((T_FROM IS NULL OR V$LESSON_DATE >= T_FROM) AND V$LESSON_DATE < T_TO) OR
          ((T_FROM IS NULL OR DATE_P_UID1 >= T_FROM) AND (DATE_P_UID1 < T_TO)) OR
          ((T_FROM IS NULL OR DATE_P_UID2 >= T_FROM) AND (DATE_P_UID2 < T_TO)) OR
          ((T_FROM IS NULL OR DM4X >= T_FROM) AND (DM4X < T_TO))
        )
      )
      THEN
          IS_OK = 1;

      -- Для НЕ-ЦОПП убираем выгрузку отметки "присутствовал", если ее умудрились выставить
      IF(I$MODE = 0 AND ABSENT_REASON = 99) THEN IS_OK = 0;

      IF(IS_OK = 1) THEN
      BEGIN

          TAG_NAME = 'wsdl&colon;EstimateInput';
          VAL = NULL;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;EstimateInput:identity:external_id';
          VAL = MARK_ID;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;EstimateInput:subject_id:external_id';
          VAL = SUBJECT_ID;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;EstimateInput:lesson_id:external_id';
          VAL = LESSON_ID;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;EstimateInput:student_id:external_id';
          VAL = STUDENT_ID;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;EstimateInput:teacher_id:external_id';
          VAL = TEACHER_ID;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;EstimateInput:group_id:external_id';
          VAL = GROUP_ID;
          SUSPEND;

          MARK_TYPE_CODE = 'absent';
          IF(FLAG_MSG = 1) THEN
          BEGIN
              MARK_DATE = DATE_MSG;
              MARK_REF_CODE = '12000';
              MARK_TYPE_CODE = 'assimilation';
              MARK_TYPE_ID = IIF(I$MODE = 1, 40002, 1058); -- считаем что за работу на уроке, для ЦОПП как Иное
          END
          ELSE IF(FLAG_ABSENT = 1) THEN
          BEGIN
              MARK_DATE = DATE_ABSENT;
              -- Неуказанная причина -> считаем неизвестной
              MARK_REF_CODE = TRIM(CASE ABSENT_REASON
                  WHEN 2196 THEN '493'
                  WHEN 91 THEN '493'
                  WHEN 2197 THEN '494'
                  WHEN 93 THEN '494'
                  WHEN 2198 THEN '495'
                  WHEN 94 THEN '495'
                  WHEN 2199 THEN '496'
                  WHEN 92 THEN '496'
                  ELSE '493'
                  END
              );
              MARK_TYPE_ID = 30000;
          END
          ELSE IF(FLAG_LC = 1) THEN
          BEGIN
              -- Код опоздания = 0
              MARK_DATE = DATE_LC;
              MARK_REF_CODE = '0';
              MARK_TYPE_ID = 30000;
          END

          TAG_NAME = 'wsdl&colon;EstimateInput:date';
          VAL = (SELECT VAL FROM DATE2ISO(:MARK_DATE, 0));
          SUSPEND;

          TAG_NAME = 'wsdl&colon;EstimateInput:institution_id:id';
          VAL = ID1;
          SUSPEND;

          IF(MARK_REF_CODE = '' OR MARK_TYPE_CODE IS NULL) THEN EXCEPTION DATA_ERROR 'Неизвестный тип оценки';

          TAG_NAME = 'wsdl&colon;EstimateInput:value:code';
          VAL = MARK_REF_CODE;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;EstimateInput:system:code';
          VAL = MARK_TYPE_CODE;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;EstimateInput:type:code';
          VAL = MARK_TYPE_ID;
          SUSPEND;

          MSG_TEXT = REPLACE(MSG_TEXT, ASCII_CHAR(13), '');
          MSG_TEXT = REPLACE(MSG_TEXT, ASCII_CHAR(10), '');
          MSG_TEXT = REPLACE(MSG_TEXT, ASCII_CHAR(9), '');
          MSG_TEXT = TRIM(MSG_TEXT);

          IF(MSG_TEXT IS NOT NULL AND CHAR_LENGTH(MSG_TEXT) > 0) THEN
          BEGIN
              TAG_NAME = 'wsdl&colon;EstimateInput:estimate_comment';
              VAL = MSG_TEXT;
              SUSPEND;
          END

          N = N + 1;
          IF(N >= 10000) THEN
          BEGIN
              N = 0;
              TAG_NAME = NULL;
              VAL = 'DIVIDE';
              SUSPEND;
          END

      END

  END

  -- Оценки текущего года (пока считаем что оценку поставил учитель, который проводил урок)
  -- Дату всегда ставим датой урока

  FOR
      -- + новый формат, коды отметок делаем минусовыми
      SELECT 'MX' || M.MARK_ID, - M.MARK_TYPE_ID, C.CONTROL_ID, C.LESSON_ID, C.CONTROL_COST, L.LESSON_DATE,
          J.SUBJECT_ID, M.STUDENT_ID, L.TEACHER_ID, J.GRADE_ID, C.CONTROL_TYPE_ID, M.DATE_MODIFY, L.DATE_MODIFY, J.REF_ID, J.PERIOD_ID
      FROM CJ2_JOURNAL J
      JOIN CJ2_JOURNAL_LESSONS L ON L.CJ_ID = J.OBJ_ID AND L.DATE_DEL IS NULL
      -- Признак группы ЦОПП
      LEFT JOIN VALL V3064 ON V3064.OBJ_ID = J.GRADE_ID AND V3064.PARAM_ID = 3064 AND V3064.IS_DEL = 0
      --
      JOIN CJ2_CONTROL C ON C.LESSON_ID = L.OBJ_ID AND C.DATE_DEL IS NULL AND C.CONTROL_TYPE_ID <> 0 AND C.CONTROL_TYPE_ID <> 30000
      JOIN CJ2_MARK M ON M.CONTROL_ID = C.CONTROL_ID AND M.DATE_DEL IS NULL
          -- Блокируем выдачу викторины и более чем 5-балльной системы оценивания, блокируем шкалу голосование
          AND (:I$MODE = 1 OR (C.CONTROL_TYPE_ID NOT IN (2001, 2002, 2003, 40000) AND M.MARK_TYPE_ID < 450 AND M.MARK_TYPE_ID NOT IN (201, 202)))
      WHERE J.DATE_DEL IS NULL AND J.JOURNAL_TYPE = 0 AND J.YEAR_ID = :YEAR_ID
          AND L.IS_COMPLETED = 1 --AND GS.PLAN_TYPE_ID IN (5465, 5466)
          AND ((:I$MODE = 0 AND (V3064.LISTVAL_ID IS NULL OR V3064.LISTVAL_ID = 3)) OR (:I$MODE = 1 AND V3064.LISTVAL_ID = 2))
      -- + новый формат итоговые, только глобальные типы отметок
      UNION ALL
      SELECT 'FX' || M.MARK_ID, - M.MARK_TYPE_ID, NULL, NULL, 1, F.FINAL_DATE, J.SUBJECT_ID, M.STUDENT_ID, NULL, J.GRADE_ID,
          F.FINAL_TYPE, M.DATE_MODIFY, F.DATE_MODIFY, J.REF_ID, J.PERIOD_ID
      FROM CJ2_JOURNAL J
      JOIN CJ2_JOURNAL_FINALS F ON F.CJ_ID = J.OBJ_ID AND F.DATE_DEL IS NULL AND F.FINAL_TYPE < 1000000000
      -- Признак группы ЦОПП
      LEFT JOIN VALL V3064 ON V3064.OBJ_ID = J.GRADE_ID AND V3064.PARAM_ID = 3064 AND V3064.IS_DEL = 0
      --
      JOIN CJ2_MARK M ON M.FINAL_ID = F.OBJ_ID AND M.DATE_DEL IS NULL
      WHERE J.DATE_DEL IS NULL AND J.JOURNAL_TYPE = 0 AND J.YEAR_ID = :YEAR_ID
          -- AND F.IS_PUBLISHED = 1 --AND GS.PLAN_TYPE_ID IN (5465, 5466)
          AND ((:I$MODE = 0 AND (V3064.LISTVAL_ID IS NULL OR V3064.LISTVAL_ID = 3)) OR (:I$MODE = 1 AND V3064.LISTVAL_ID = 2))
      INTO :MARK_ID, :MARK_TYPE_ID, :TASK_ID, :LESSON_ID, :MARK_COST, :MARK_DATE, :SUBJECT_ID, :STUDENT_ID, :TEACHER_ID, :GROUP_ID,
          :CONTROL_TYPE_ID, :V$EVENT_DATE, :V$LESSON_DATE, :V$PLAN_ID, :PERIOD_ID
  DO
  BEGIN

      -- Наличие и дата изменения кодов
      DATE_P_UID1 = NULL;
      DATE_P_UID2 = NULL;
      SELECT MAX(V1570.DATE_MODIFY), MAX(V155.DATE_MODIFY)
      FROM LINKS L20
      JOIN VALS V1570 ON V1570.OBJ_ID = L20.EXT_OBJ_ID AND V1570.PARAM_ID = 1570 AND V1570.IS_DEL = 0
      JOIN VALS V155 ON V155.OBJ_ID = L20.OBJ_ID AND V155.PARAM_ID = 155 AND V155.IS_DEL = 0
      --JOIN LINKS LP9 ON LP9.OBJ_ID = L20.PARENT_ID AND LP9.PARENT_TYPE_ID IN (9, 125, 187) AND LP9.DATE_DEL IS NULL
      WHERE L20.PARENT_ID = :STUDENT_ID AND L20.OBJ_TYPE_ID = 20 AND L20.DATE_DEL IS NULL
      INTO :DATE_P_UID1, :DATE_P_UID2;

      SELECT V3060.SVAL, V3060.DATE_MODIFY
      FROM RDB$DATABASE
      LEFT JOIN VALS V3060 ON V3060.OBJ_ID = :STUDENT_ID AND V3060.PARAM_ID = 3060 AND V3060.IS_DEL = 0
      INTO :V4X, :DM4X;

      -- В ЦОПП заменяем код ученика на код сотрудника, если он же внесен
      IF(I$MODE = 1) THEN
      BEGIN
          SELECT FIRST 1 V3061.OBJ_ID
          FROM VALS V3061
          WHERE V3061.PARAM_ID = 3061 AND V3061.IS_DEL = 0 AND V3061.SVAL = :V4X
          INTO :STUDENT_ID;
      END

      IS_OK = 0;
      IF(((DATE_P_UID1 IS NOT NULL AND DATE_P_UID2 IS NOT NULL AND I$MODE = 0) OR (DM4X IS NOT NULL AND I$MODE = 1)) AND V$LESSON_DATE < T_TO
        AND (
          ((T_FROM IS NULL OR V$EVENT_DATE >= T_FROM) AND V$EVENT_DATE < T_TO) OR
          ((T_FROM IS NULL OR V$LESSON_DATE >= T_FROM) AND V$LESSON_DATE < T_TO) OR
          ((T_FROM IS NULL OR DATE_P_UID1 >= T_FROM) AND (DATE_P_UID1 < T_TO)) OR
          ((T_FROM IS NULL OR DATE_P_UID2 >= T_FROM) AND (DATE_P_UID2 < T_TO)) OR
          ((T_FROM IS NULL OR DM4X >= T_FROM) AND (DM4X < T_TO))
        )
      )
      THEN
          IS_OK = 1;

      -- Для итоговых подбираем код периода. Если не найдется, шлем с соответствующим годовым периодом
      IF(IS_OK = 1 AND LESSON_ID IS NULL) THEN
      BEGIN

          -- Для итоговых периодов берем год и дату не трогаем, для остальных соответствующий период 2 уровня и подгоняем дату
          IF(I$MODE = 1) THEN
          BEGIN
              -- Для ЦОПП выдаем период "курс" для корня, либо нужный модуль в подразделах
              SELECT FIRST 1 LP9.PARENT_ID, V3071.VAL, V3072.VAL
              FROM LINKS LP9
              JOIN VALL V3063 ON V3063.OBJ_ID = LP9.PARENT_ID AND V3063.PARAM_ID = 3063 AND V3063.IS_DEL = 0 AND V3063.LISTVAL_ID = 2
              JOIN VALD V3071 ON V3071.OBJ_ID = LP9.PARENT_ID AND V3071.PARAM_ID = 3071 AND V3071.IS_DEL = 0
              JOIN VALD V3072 ON V3072.OBJ_ID = LP9.PARENT_ID AND V3072.PARAM_ID = 3072 AND V3072.IS_DEL = 0
              WHERE LP9.OBJ_ID = :STUDENT_ID AND LP9.PARENT_TYPE_ID = 9 AND LP9.DATE_DEL IS NULL
              INTO :PERIOD_ID, :PD1, :PD2;

              V$PERIOD_TYPE = NULL;
              MODULE_ID = NULL;
              SELECT FIRST 1 PF.FIELD_ID, PF.OBJ_ID
              FROM PLAN_SUBJECTS PS
              JOIN PLAN_SUBJECTS PF ON PF.OBJ_ID = PS.PARENT_ID AND PF.DATE_DEL IS NULL AND PF.LEVEL_INDEX = 0
              WHERE PS.DATE_DEL IS NULL AND PS.PLAN_ID = :V$PLAN_ID AND PS.SUBJECT_ID = :SUBJECT_ID
              INTO :V$PERIOD_TYPE, :MODULE_ID;

              IF(V$PERIOD_TYPE IS NULL) THEN PERIOD_ID = NULL;
              ELSE IF(V$PERIOD_TYPE <> 12975) THEN PERIOD_ID = PERIOD_ID || '-' || MODULE_ID;
          END
          ELSE IF(CONTROL_TYPE_ID IN (3011, 3012, 5544, 3013, 110, 120, 121, 130)) THEN
          BEGIN
              -- Для итоговых всегда идет корневой период
              -- PERIOD_ID и так указывает на корневой период, а старой схемы выгрузки у нас больше нет
              -- SELECT FIRST 1 LP151.PARENT_ID
              -- FROM LINKS LP151
              -- WHERE LP151.OBJ_ID = :GROUP_ID AND LP151.PARENT_TYPE_ID = 151 AND LP151.DATE_DEL IS NULL
              -- INTO :PERIOD_ID;

              PD1 = NULL;
              PD2 = NULL;
          END
          ELSE
          BEGIN
              -- Старой схемы периодов больше нет
              SELECT FIRST 1 L154.OBJ_ID, V1169.VAL, V1174.VAL
              FROM LINKS L154
              JOIN VALL V1170 ON V1170.OBJ_ID = L154.OBJ_ID AND V1170.PARAM_ID = 1170 AND V1170.IS_DEL = 0 AND V1170.LISTVAL_ID = (
                  CASE :CONTROL_TYPE_ID
                      -- перекодируем CJ_FINAL_TYPE в LIST18
                      WHEN 20 THEN 12 -- Q
                      WHEN 30 THEN 13
                      WHEN 40 THEN 14
                      WHEN 50 THEN 15
                      WHEN 60 THEN 16 -- T
                      WHEN 70 THEN 17
                      WHEN 80 THEN 18
                      WHEN 90 THEN 10 -- H
                      WHEN 100 THEN 11
                      -- перекодируем новый формат
                      WHEN 3002 THEN 12 -- Q
                      WHEN 3003 THEN 13
                      WHEN 3004 THEN 14
                      WHEN 3005 THEN 15
                      WHEN 3006 THEN 16 -- T
                      WHEN 3007 THEN 17
                      WHEN 3008 THEN 18
                      WHEN 3009 THEN 10 -- H
                      WHEN 3010 THEN 11
                      WHEN 12973 THEN 19 -- S
                      WHEN 12974 THEN 20
                      ELSE NULL
                  END
              )
              JOIN VALD V1169 ON V1169.OBJ_ID = L154.OBJ_ID AND V1169.PARAM_ID = 1169 AND V1169.IS_DEL = 0
              JOIN VALD V1174 ON V1174.OBJ_ID = L154.OBJ_ID AND V1174.PARAM_ID = 1174 AND V1174.IS_DEL = 0
              WHERE L154.PARENT_ID = :PERIOD_ID AND L154.OBJ_TYPE_ID = 154 AND L154.DATE_DEL IS NULL
              ORDER BY 1 DESC
              INTO :PERIOD_ID, :PD1, :PD2;
          END

          -- Если реальный под-период не нашелся, не выдаем эту отметку вовсе
          IF(PERIOD_ID IS NULL) THEN IS_OK = 0;

          -- Вгоняем отметку в указанный диапазон дат периода
          IF(PD1 IS NOT NULL AND PD2 IS NOT NULL) THEN
          BEGIN
              IF(MARK_DATE < PD1) THEN MARK_DATE = PD1;
              IF(MARK_DATE > PD2) THEN MARK_DATE = PD2;
          END

      END

      IF(IS_OK = 1) THEN
      BEGIN

          TAG_NAME = 'wsdl&colon;EstimateInput';
          VAL = NULL;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;EstimateInput:identity:external_id';
          VAL = MARK_ID;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;EstimateInput:subject_id:external_id';
          VAL = SUBJECT_ID;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;EstimateInput:lesson_id:external_id';
          VAL = LESSON_ID;
          IF(LESSON_ID IS NOT NULL) THEN SUSPEND;

          TAG_NAME = 'wsdl&colon;EstimateInput:task_id:external_id';
          VAL = TASK_ID;
          IF(TASK_ID IS NOT NULL) THEN SUSPEND;

          TAG_NAME = 'wsdl&colon;EstimateInput:student_id:external_id';
          VAL = STUDENT_ID;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;EstimateInput:teacher_id:external_id';
          VAL = TEACHER_ID;
          SUSPEND;

          -- Группы шлем только для реальных отметок, итоговым не нужно
          TAG_NAME = 'wsdl&colon;EstimateInput:group_id:external_id';
          VAL = GROUP_ID;
          IF(LESSON_ID IS NOT NULL) THEN SUSPEND;

          TAG_NAME = 'wsdl&colon;EstimateInput:date';
          VAL = (SELECT VAL FROM DATE2ISO(:MARK_DATE, 0));
          SUSPEND;

          -- weight не посылаем

          TAG_NAME = 'wsdl&colon;EstimateInput:institution_id:id';
          VAL = ID1;
          SUSPEND;

          -- Перекодируем отметки
          MARK_REF_CODE = '';
          MARK_TYPE_CODE = '';
          IF(MARK_TYPE_ID IN (10, -401)) THEN
          BEGIN
              MARK_REF_CODE = '1/5';
              MARK_TYPE_CODE = 'five_point';
          END
          ELSE IF(MARK_TYPE_ID IN (20, -402)) THEN
          BEGIN
              MARK_REF_CODE = '2/5';
              MARK_TYPE_CODE = 'five_point';
          END
          ELSE IF(MARK_TYPE_ID IN (30, -403)) THEN
          BEGIN
              MARK_REF_CODE = '3/5';
              MARK_TYPE_CODE = 'five_point';
          END
          ELSE IF(MARK_TYPE_ID IN (40, -404)) THEN
          BEGIN
              MARK_REF_CODE = '4/5';
              MARK_TYPE_CODE = 'five_point';
          END
          ELSE IF(MARK_TYPE_ID IN (50, -405)) THEN
          BEGIN
              MARK_REF_CODE = '5/5';
              MARK_TYPE_CODE = 'five_point';
          END
          -- 12-балльная шкала 1..12
          ELSE IF(ABS(MARK_TYPE_ID) >= 451 AND ABS(MARK_TYPE_ID) <= 462) THEN
          BEGIN
              MARK_REF_CODE = CAST(ABS(MARK_TYPE_ID) - 450 AS INTEGER) || '/12';
              MARK_TYPE_CODE = 'twelve_point';
          END
          -- 20-балльная шкала (почему-то она у нас от нуля)
          ELSE IF(ABS(MARK_TYPE_ID) >= 500 AND ABS(MARK_TYPE_ID) <= 620) THEN
          BEGIN
              MARK_REF_CODE = CAST(ABS(MARK_TYPE_ID) - 500 AS INTEGER) || '/20';
              MARK_TYPE_CODE = 'twenty_point';
          END
          -- 100-балльная шкала
          ELSE IF(ABS(MARK_TYPE_ID) >= 600 AND ABS(MARK_TYPE_ID) <= 700) THEN
          BEGIN
              MARK_REF_CODE = CAST(ABS(MARK_TYPE_ID) - 600 AS INTEGER) || '/100';
              MARK_TYPE_CODE = 'hundred_point';
          END
          ELSE IF(MARK_TYPE_ID IN (60, -101)) THEN
          BEGIN
              MARK_REF_CODE = 'positive';
              MARK_TYPE_CODE = 'grade';
          END
          ELSE IF(MARK_TYPE_ID IN (70, -102)) THEN
          BEGIN
              MARK_REF_CODE = 'negative';
              MARK_TYPE_CODE = 'grade';
          END
          ELSE IF(MARK_TYPE_ID IN (80)) THEN
          BEGIN
              -- Отметки ОСВ в новом журнале нет
              MARK_REF_CODE = '3021';
              MARK_TYPE_CODE = 'certification';
          END
          ELSE IF(MARK_TYPE_ID IN (90, -103)) THEN
          BEGIN
              MARK_REF_CODE = '3022';
              MARK_TYPE_CODE = 'certification';
          END
          ELSE IF(MARK_TYPE_ID IN (100, -104)) THEN
          BEGIN
              MARK_REF_CODE = '3023';
              MARK_TYPE_CODE = 'certification';
          END
          ELSE IF(MARK_TYPE_ID IN (110, -105)) THEN
          BEGIN
              MARK_REF_CODE = '11040';
              MARK_TYPE_CODE = 'assimilation';
          END
          ELSE IF(MARK_TYPE_ID IN (120, -106)) THEN
          BEGIN
              MARK_REF_CODE = '11041';
              MARK_TYPE_CODE = 'assimilation';
          END
          ELSE IF(MARK_TYPE_ID IN (130, -107)) THEN
          BEGIN
              MARK_REF_CODE = '11042';
              MARK_TYPE_CODE = 'assimilation';
          END

          IF(MARK_REF_CODE = '' OR MARK_TYPE_CODE IS NULL) THEN
          BEGIN
              MSG_TEXT = NULL;
              MARK_ID = SUBSTRING(MARK_ID FROM 3);
              SELECT FIRST 1 J.JOURNAL_NAME || ' ' || C.CAPTION
              FROM CJ2_MARK M
              JOIN CJ2_JOURNAL_FINALS F ON F.OBJ_ID = M.FINAL_ID
              JOIN CJ2_JOURNAL J ON J.OBJ_ID = F.CJ_ID
              LEFT JOIN OBJECT_CAPTION_GET(J.SUBJECT_ID) C ON 1 = 1
              WHERE M.MARK_ID = :MARK_ID
              INTO :MSG_TEXT;

              MSG_TEXT = COALESCE(' в журнале ' || MSG_TEXT, '');
              EXCEPTION DATA_ERROR 'Неизвестный тип оценки для ' || MARK_ID || ' - ' || COALESCE(MARK_TYPE_ID, '?') || MSG_TEXT;
          END

          TAG_NAME = 'wsdl&colon;EstimateInput:value:code';
          VAL = MARK_REF_CODE;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;EstimateInput:system:code';
          VAL = MARK_TYPE_CODE;
          SUSPEND;

          -- По-разному шлем итоговые и обычные отметки
          TAG_NAME = 'wsdl&colon;EstimateInput:type:code';
          IF(LESSON_ID IS NULL) THEN
          BEGIN
              IF(I$MODE = 1) THEN
              BEGIN
                  IF(CONTROL_TYPE_ID IN (3012, 3013)) THEN BEGIN END
                  ELSE IF(CONTROL_TYPE_ID = 5544) THEN CONTROL_TYPE_ID = 40001;
                  ELSE IF(CONTROL_TYPE_ID = 13018) THEN CONTROL_TYPE_ID = 11080;
                  ELSE IF(CONTROL_TYPE_ID = 13019) THEN CONTROL_TYPE_ID = 40000;
                  ELSE CONTROL_TYPE_ID = 3013;
              END
              ELSE
              BEGIN
                  IF(CONTROL_TYPE_ID = 10) THEN CONTROL_TYPE_ID = 3011;       -- за период, но это элемент раздела, не может существовать
                  ELSE IF(CONTROL_TYPE_ID = 20) THEN CONTROL_TYPE_ID = 3002;  -- 1Q
                  ELSE IF(CONTROL_TYPE_ID = 30) THEN CONTROL_TYPE_ID = 3003;  -- 2Q
                  ELSE IF(CONTROL_TYPE_ID = 40) THEN CONTROL_TYPE_ID = 3004;  -- 3Q
                  ELSE IF(CONTROL_TYPE_ID = 50) THEN CONTROL_TYPE_ID = 3005;  -- 4Q
                  ELSE IF(CONTROL_TYPE_ID = 60) THEN CONTROL_TYPE_ID = 3006;  -- 1T
                  ELSE IF(CONTROL_TYPE_ID = 70) THEN CONTROL_TYPE_ID = 3007;  -- 2T
                  ELSE IF(CONTROL_TYPE_ID = 80) THEN CONTROL_TYPE_ID = 3008;  -- 3T
                  ELSE IF(CONTROL_TYPE_ID = 90) THEN CONTROL_TYPE_ID = 3009;  -- 1H
                  ELSE IF(CONTROL_TYPE_ID = 100) THEN CONTROL_TYPE_ID = 3010; -- 2H
                  ELSE IF(CONTROL_TYPE_ID = 110) THEN CONTROL_TYPE_ID = 3011; -- Y
                  ELSE IF(CONTROL_TYPE_ID = 120) THEN CONTROL_TYPE_ID = 3012; -- EXAM
                  ELSE IF(CONTROL_TYPE_ID = 121) THEN CONTROL_TYPE_ID = 5544; -- QE
                  ELSE IF(CONTROL_TYPE_ID = 130) THEN CONTROL_TYPE_ID = 3013; -- FINAL
              END
          END
          ELSE
          BEGIN
              -- Коррекция справочников для портала
              IF(I$MODE = 1) THEN CONTROL_TYPE_ID = 40002;                  -- Иное (ЦОПП)
              ELSE IF(CONTROL_TYPE_ID = 5471) THEN CONTROL_TYPE_ID = 1058;  -- зан. -> работа на уроке (занятие)
              ELSE IF(CONTROL_TYPE_ID = 5472) THEN CONTROL_TYPE_ID = 1063;  -- ДЗ (практика) -> д.з.
              ELSE IF(CONTROL_TYPE_ID = 5473) THEN CONTROL_TYPE_ID = 1063;  -- К -> д.з. ???
              ELSE IF(CONTROL_TYPE_ID = 5474) THEN CONTROL_TYPE_ID = 1063;  -- Эл.О -> д.з. ???
              ELSE IF(CONTROL_TYPE_ID = 5475) THEN CONTROL_TYPE_ID = 1088;  -- сочинение -> классное сочинение
              ELSE IF(CONTROL_TYPE_ID = 5476) THEN CONTROL_TYPE_ID = 11204; -- пр. -> практическая работа
              ELSE IF(CONTROL_TYPE_ID = 5477) THEN CONTROL_TYPE_ID = 1063;  -- Кв.И -> д.з. ???
              ELSE IF(CONTROL_TYPE_ID = 5478) THEN CONTROL_TYPE_ID = 1063;  -- Ин. -> д.з. ???
          END

          IF(I$MODE = 1 AND CONTROL_TYPE_ID NOT IN (11080, 3012, 40000, 40001, 40002, 3013)) THEN CONTROL_TYPE_ID = 40002; -- меняем все лишнее на Иное

          VAL = CONTROL_TYPE_ID;
          SUSPEND;

          -- Период только для итоговых отметок
          IF(LESSON_ID IS NULL) THEN
          BEGIN
              TAG_NAME = 'wsdl&colon;EstimateInput:period_id:external_id';
              VAL = PERIOD_ID;
              SUSPEND;
          END

          N = N + 1;
          IF(N >= 10000) THEN
          BEGIN
              N = 0;
              TAG_NAME = NULL;
              VAL = 'DIVIDE';
              SUSPEND;
          END

      END

  END

  -- Отметки действующих учащихся за прошлые учебные годы, только по тем ученикам где есть коды портала
  -- текущий учебный год не выгружаем
  FOR
      SELECT 'H' || M.MARK_ID, M.YEAR_ID, LV29.COST, M.MARKTYPE_ID, M.MARKVAL_ID, M.SUBJECT_ID, M.PUPIL_ID, M.DATE_MODIFY, M.PERIOD_FROM, M.PERIOD_TO
      FROM VALM M
      JOIN LISTVALS LV29 ON LV29.LISTVAL_ID = M.YEAR_ID AND LV29.IS_DEL = 0 -- кривые удаленные периоды
      -- Ученик в действующем классе
      JOIN LINKS L10 ON L10.OBJ_ID = M.PUPIL_ID AND L10.PARENT_TYPE_ID = 9 AND L10.DATE_DEL IS NULL
      WHERE M.IS_DEL = 0 AND LV29.COST < :CURRENT_YEAR AND M.MARKVAL_ID < 13020
      INTO :MARK_ID, :PERIOD_ID, :PERIOD_YEAR, :CONTROL_TYPE_ID, :MARK_TYPE_ID, :SUBJECT_ID, :STUDENT_ID, :V$EVENT_DATE, :V$PERIOD_FROM, :V$PERIOD_TO
  DO
  BEGIN

      -- Наличие и дата изменения кодов
      DATE_P_UID1 = NULL;
      DATE_P_UID2 = NULL;
      SELECT MAX(V1570.DATE_MODIFY), MAX(V155.DATE_MODIFY)
      FROM LINKS L20
      JOIN VALS V1570 ON V1570.OBJ_ID = L20.EXT_OBJ_ID AND V1570.PARAM_ID = 1570 AND V1570.IS_DEL = 0
      JOIN VALS V155 ON V155.OBJ_ID = L20.OBJ_ID AND V155.PARAM_ID = 155 AND V155.IS_DEL = 0
      --JOIN LINKS LP9 ON LP9.OBJ_ID = L20.PARENT_ID AND LP9.PARENT_TYPE_ID IN (9, 125, 187) AND LP9.DATE_DEL IS NULL
      WHERE L20.PARENT_ID = :STUDENT_ID AND L20.OBJ_TYPE_ID = 20 AND L20.DATE_DEL IS NULL
      INTO :DATE_P_UID1, :DATE_P_UID2;

      IS_OK = 0;
      SELECT V3060.DATE_MODIFY
      FROM RDB$DATABASE
      LEFT JOIN VALS V3060 ON V3060.OBJ_ID = :STUDENT_ID AND V3060.PARAM_ID = 3060 AND V3060.IS_DEL = 0
      INTO :DM4X;

      IS_OK = 0;
      IF(((DATE_P_UID1 IS NOT NULL AND DATE_P_UID2 IS NOT NULL AND I$MODE = 0) OR (DM4X IS NOT NULL AND I$MODE = 1))
        AND (
          ((T_FROM IS NULL OR V$EVENT_DATE >= T_FROM) AND V$EVENT_DATE < T_TO) OR
          ((T_FROM IS NULL OR DATE_P_UID1 >= T_FROM) AND (DATE_P_UID1 < T_TO)) OR
          ((T_FROM IS NULL OR DATE_P_UID2 >= T_FROM) AND (DATE_P_UID2 < T_TO)) OR
          ((T_FROM IS NULL OR DM4X >= T_FROM) AND (DM4X < T_TO))
        )
      )
      THEN
          IS_OK = 1;

      IF(IS_OK = 1) THEN
      BEGIN

          TAG_NAME = 'wsdl&colon;EstimateInput';
          VAL = NULL;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;EstimateInput:identity:external_id';
          VAL = MARK_ID;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;EstimateInput:subject_id:external_id';
          VAL = SUBJECT_ID;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;EstimateInput:student_id:external_id';
          VAL = STUDENT_ID;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;EstimateInput:teacher_id:external_id';
          VAL = '';
          SUSPEND;

          -- Подбираем дату отметки, соответствующую виртуальному окончанию периода
          IF(CONTROL_TYPE_ID = 3001) THEN CONTROL_TYPE_ID = 3011;

          TAG_NAME = 'wsdl&colon;EstimateInput:date';
          IF(CONTROL_TYPE_ID = 3002) THEN MARK_DATE = PERIOD_YEAR || '-10-31';            -- 1Q
          ELSE IF(CONTROL_TYPE_ID = 3003) THEN MARK_DATE = PERIOD_YEAR || '-12-31';       -- 2Q
          ELSE IF(CONTROL_TYPE_ID = 3004) THEN MARK_DATE = (PERIOD_YEAR + 1) || '-03-31'; -- 3Q
          ELSE IF(CONTROL_TYPE_ID = 3005) THEN MARK_DATE = (PERIOD_YEAR + 1) || '-05-31'; -- 4Q
          ELSE IF(CONTROL_TYPE_ID = 3006) THEN MARK_DATE = PERIOD_YEAR || '-11-14';       -- 1T
          ELSE IF(CONTROL_TYPE_ID = 3007) THEN MARK_DATE = (PERIOD_YEAR + 1) || '-02-14'; -- 2T
          ELSE IF(CONTROL_TYPE_ID = 3008) THEN MARK_DATE = (PERIOD_YEAR + 1) || '-05-31'; -- 3T
          ELSE IF(CONTROL_TYPE_ID = 3009) THEN MARK_DATE = PERIOD_YEAR || '-12-31';       -- 1H
          ELSE IF(CONTROL_TYPE_ID = 3010) THEN MARK_DATE = (PERIOD_YEAR + 1) || '-05-31'; -- 2H
          ELSE IF(CONTROL_TYPE_ID = 3011) THEN MARK_DATE = (PERIOD_YEAR + 1) || '-05-31'; -- Y
          ELSE IF(CONTROL_TYPE_ID = 3012) THEN MARK_DATE = (PERIOD_YEAR + 1) || '-05-31'; -- EXAM
          ELSE IF(CONTROL_TYPE_ID = 5544) THEN MARK_DATE = (PERIOD_YEAR + 1) || '-05-31'; -- QE
          ELSE IF(CONTROL_TYPE_ID = 3013) THEN MARK_DATE = (PERIOD_YEAR + 1) || '-05-31'; -- FINAL
          ELSE IF(CONTROL_TYPE_ID = 12973) THEN MARK_DATE = PERIOD_YEAR || '-12-31';      -- 1S
          ELSE IF(CONTROL_TYPE_ID = 12974) THEN MARK_DATE = (PERIOD_YEAR + 1) || '-05-31';-- 2S
          ELSE MARK_DATE = V$PERIOD_TO;
          VAL = (SELECT VAL FROM DATE2ISO(:MARK_DATE, 0));
          SUSPEND;

          TAG_NAME = 'wsdl&colon;EstimateInput:period_id:external_id';
          VAL = PERIOD_ID;
          IF(CONTROL_TYPE_ID IS NOT NULL AND CONTROL_TYPE_ID NOT IN (3011, 3012, 3013, 5544)) THEN VAL = VAL || '-' || CONTROL_TYPE_ID;
          IF(VAL IS NOT NULL) THEN SUSPEND;

          TAG_NAME = 'wsdl&colon;EstimateInput:institution_id:id';
          VAL = ID1;
          SUSPEND;

          MARK_REF_CODE = '';
          MARK_TYPE_CODE = '';
          IF(MARK_TYPE_ID = 3014) THEN
          BEGIN
            MARK_REF_CODE = '1/5';
            MARK_TYPE_CODE = 'five_point';
          END
          ELSE IF(MARK_TYPE_ID = 3015) THEN
          BEGIN
            MARK_REF_CODE = '2/5';
            MARK_TYPE_CODE = 'five_point';
          END
          ELSE IF(MARK_TYPE_ID = 3016) THEN
          BEGIN
            MARK_REF_CODE = '3/5';
            MARK_TYPE_CODE = 'five_point';
          END
          ELSE IF(MARK_TYPE_ID = 3017) THEN
          BEGIN
            MARK_REF_CODE = '4/5';
            MARK_TYPE_CODE = 'five_point';
          END
          ELSE IF(MARK_TYPE_ID = 3018) THEN
          BEGIN
            MARK_REF_CODE = '5/5';
            MARK_TYPE_CODE = 'five_point';
          END
          -- 12-балльная шкала 1..12
          ELSE IF(MARK_TYPE_ID >= 13309 AND MARK_TYPE_ID <= 13220) THEN
          BEGIN
              MARK_REF_CODE = CAST(MARK_TYPE_ID - 13308 AS INTEGER) || '/12';
              MARK_TYPE_CODE = 'twelve_point';
          END
          -- 20-балльная шкала 1..20
          ELSE IF(MARK_TYPE_ID >= 28964 AND MARK_TYPE_ID <= 28983) THEN
          BEGIN
              MARK_REF_CODE = CAST(MARK_TYPE_ID - 28963 AS INTEGER) || '/20';
              MARK_TYPE_CODE = 'twenty_point';
          END
          -- 100-балльная шкала
          -- !!!
          ELSE IF(MARK_TYPE_ID = 3019) THEN
          BEGIN
            MARK_REF_CODE = 'positive';
            MARK_TYPE_CODE = 'grade';
          END
          ELSE IF(MARK_TYPE_ID = 3020) THEN
          BEGIN
            MARK_REF_CODE = 'negative';
            MARK_TYPE_CODE = 'grade';
          END
          ELSE IF(MARK_TYPE_ID = 3021) THEN
          BEGIN
            MARK_REF_CODE = '3021';
            MARK_TYPE_CODE = 'certification';
          END
          ELSE IF(MARK_TYPE_ID = 3022) THEN
          BEGIN
            MARK_REF_CODE = '3022';
            MARK_TYPE_CODE = 'certification';
          END
          ELSE IF(MARK_TYPE_ID = 3023) THEN
          BEGIN
            MARK_REF_CODE = '3023';
            MARK_TYPE_CODE = 'certification';
          END
          ELSE IF(MARK_TYPE_ID = 11040) THEN
          BEGIN
            MARK_REF_CODE = '11040';
            MARK_TYPE_CODE = 'assimilation';
          END
          ELSE IF(MARK_TYPE_ID = 11041) THEN
          BEGIN
            MARK_REF_CODE = '11041';
            MARK_TYPE_CODE = 'assimilation';
          END
          ELSE IF(MARK_TYPE_ID = 11042) THEN
          BEGIN
            MARK_REF_CODE = '11042';
            MARK_TYPE_CODE = 'assimilation';
          END

          IF(MARK_REF_CODE = '' OR MARK_TYPE_CODE IS NULL) THEN EXCEPTION DATA_ERROR 'Неизвестный тип оценки для ' || MARK_ID || ' - ' || COALESCE(MARK_TYPE_ID, '?');

          TAG_NAME = 'wsdl&colon;EstimateInput:value:code';
          VAL = MARK_REF_CODE;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;EstimateInput:system:code';
          VAL = MARK_TYPE_CODE;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;EstimateInput:type:code';
          IF(I$MODE = 0) THEN
          BEGIN
              -- перекодировать не нужно, код из того же справочника
              VAL = CONTROL_TYPE_ID;
          END
          ELSE
          BEGIN
              -- все итоговые отметки делим на экзамен, демонстрационный экзамен и итоговая
              IF(CONTROL_TYPE_ID = 3012) THEN VAL = 3012;
              ELSE IF(CONTROL_TYPE_ID = 5544) THEN VAL = 40001;
              ELSE VAL = 3013;
          END
          SUSPEND;

          N = N + 1;
          IF(N >= 10000) THEN
          BEGIN
              N = 0;
              TAG_NAME = NULL;
              VAL = 'DIVIDE';
              SUSPEND;
          END

      END

  END

  -- Рейтинги обучающихся. Расчитываются по всем предметам одновременно
  -- id ставим как сборку из id предмета и ученика, чтобы оно все обновлялось

  FOR
      SELECT R.STUDENT_ID, R.PERIOD_ID, MAX(R.RATE_DATE)
      FROM CJ2_STUDENT_RATING R
      WHERE R.DATE_DEL IS NULL AND R.FIELD_ID IS NULL AND R.PERIOD_ID IS NOT NULL AND 0 = 1
      GROUP BY 1, 2
      INTO :STUDENT_ID, :PERIOD_ID, :V$RATE_DATE
  DO
  BEGIN

      -- Наличие и дата изменения кодов
      DATE_P_UID1 = NULL;
      DATE_P_UID2 = NULL;
      SELECT MAX(V1570.DATE_MODIFY), MAX(V155.DATE_MODIFY)
      FROM LINKS L20
      JOIN VALS V1570 ON V1570.OBJ_ID = L20.EXT_OBJ_ID AND V1570.PARAM_ID = 1570 AND V1570.IS_DEL = 0
      JOIN VALS V155 ON V155.OBJ_ID = L20.OBJ_ID AND V155.PARAM_ID = 155 AND V155.IS_DEL = 0
      --JOIN LINKS LP9 ON LP9.OBJ_ID = L20.PARENT_ID AND LP9.PARENT_TYPE_ID IN (9, 125, 187) AND LP9.DATE_DEL IS NULL
      WHERE L20.PARENT_ID = :STUDENT_ID AND L20.OBJ_TYPE_ID = 20 AND L20.DATE_DEL IS NULL
      INTO :DATE_P_UID1, :DATE_P_UID2;

      SELECT V3060.DATE_MODIFY
      FROM RDB$DATABASE
      LEFT JOIN VALS V3060 ON V3060.OBJ_ID = :STUDENT_ID AND V3060.PARAM_ID = 3060 AND V3060.IS_DEL = 0
      INTO :DM4X;

      FOR
          SELECT 'R' || :STUDENT_ID || '_' || R.SUBJECT_ID || '_' || :PERIOD_ID, R.SUBJECT_ID, R.RATE_VALUE, R.DATE_MODIFY
          FROM CJ2_STUDENT_RATING R
          WHERE R.DATE_DEL IS NULL AND R.FIELD_ID IS NULL AND R.STUDENT_ID = :STUDENT_ID AND R.PERIOD_ID = :PERIOD_ID AND R.RATE_DATE = :V$RATE_DATE
          INTO :MARK_ID, :SUBJECT_ID, :MARK_COST, :V$EVENT_DATE
      DO
      BEGIN

          IS_OK = 0;
          IF(((DATE_P_UID1 IS NOT NULL AND DATE_P_UID2 IS NOT NULL AND I$MODE = 0) OR (DM4X IS NOT NULL AND I$MODE = 1))
            AND (
              ((T_FROM IS NULL OR V$EVENT_DATE >= T_FROM) AND V$EVENT_DATE < T_TO) OR
              ((T_FROM IS NULL OR DATE_P_UID1 >= T_FROM) AND (DATE_P_UID1 < T_TO)) OR
              ((T_FROM IS NULL OR DATE_P_UID2 >= T_FROM) AND (DATE_P_UID2 < T_TO)) OR
              ((T_FROM IS NULL OR DM4X >= T_FROM) AND (DM4X < T_TO))
            )
          )
          THEN
              IS_OK = 1;

          IF(IS_OK = 1) THEN
          BEGIN

              TAG_NAME = 'wsdl&colon;EstimateInput';
              VAL = NULL;
              SUSPEND;

              TAG_NAME = 'wsdl&colon;EstimateInput:identity:external_id';
              VAL = MARK_ID;
              SUSPEND;

              TAG_NAME = 'wsdl&colon;EstimateInput:subject_id:external_id';
              VAL = SUBJECT_ID;
              SUSPEND;

              TAG_NAME = 'wsdl&colon;EstimateInput:student_id:external_id';
              VAL = STUDENT_ID;
              SUSPEND;

              TAG_NAME = 'wsdl&colon;EstimateInput:teacher_id:external_id';
              VAL = '';
              SUSPEND;

              TAG_NAME = 'wsdl&colon;EstimateInput:date';
              VAL = (SELECT VAL FROM DATE2ISO(:MARK_DATE, 0));
              SUSPEND;

              TAG_NAME = 'wsdl&colon;EstimateInput:period_id:external_id';
              IF(PERIOD_ID = 12) THEN VAL = 3002;  -- 1Q
              ELSE IF(PERIOD_ID = 13) THEN VAL = 3003;  -- 2Q
              ELSE IF(PERIOD_ID = 14) THEN VAL = 3004;  -- 3Q
              ELSE IF(PERIOD_ID = 15) THEN VAL = 3005;  -- 4Q
              ELSE IF(PERIOD_ID = 16) THEN VAL = 3006;  -- 1T
              ELSE IF(PERIOD_ID = 17) THEN VAL = 3007;  -- 2T
              ELSE IF(PERIOD_ID = 18) THEN VAL = 3008;  -- 3T
              ELSE IF(PERIOD_ID = 10) THEN VAL = 3009;  -- 1H
              ELSE IF(PERIOD_ID = 11) THEN VAL = 3010;  -- 2H
              ELSE VAL = 3011; -- годового быть не должно
              SUSPEND;

              TAG_NAME = 'wsdl&colon;EstimateInput:institution_id:id';
              VAL = ID1;
              SUSPEND;

              TAG_NAME = 'wsdl&colon;EstimateInput:value:code';
              IF(MARK_COST < 0.1) THEN MARK_COST = 0.1;
              IF(MARK_COST > 5.0) THEN MARK_COST = 5.0;
              VAL = CAST(MARK_COST AS NUMERIC(18, 1));
              VAL = REPLACE(VAL, '.', ',') || '/5,0';
              SUSPEND;

              TAG_NAME = 'wsdl&colon;EstimateInput:system:code';
              VAL = 'fractional_point';
              SUSPEND;

              TAG_NAME = 'wsdl&colon;EstimateInput:type:code';
              VAL = 3014;
              SUSPEND;

              N = N + 1;
              IF(N >= 10000) THEN
              BEGIN
                  N = 0;
                  TAG_NAME = NULL;
                  VAL = 'DIVIDE';
                  SUSPEND;
              END
          END
      END
  END

  -- Успехи, напоминания и прочее выдаем раз в сутки, либо при полной выгрузке
  SELECT FIRST 1 INFO_ID, CAST(INFO_VAL AS TIMESTAMP)
  FROM INFO
  WHERE INFO_CODE = 'PORTAL_UPDATE_HINTS'
  INTO :V$INFO_ID, :V$INFO_DATE;

  IF(T_FROM IS NULL OR V$INFO_DATE < DATEADD(-1 DAY TO CURRENT_TIMESTAMP)) THEN
  BEGIN

      FOR
          SELECT DISTINCT L10.OBJ_ID
          FROM LINKS L2
          JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
          JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
          JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 125, 187) AND L9.DATE_DEL IS NULL
          JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
          -- Должны быть фамилия и имя
          JOIN VALS V1 ON V1.OBJ_ID = L10.OBJ_ID AND V1.PARAM_ID = 55 AND V1.IS_DEL = 0
          JOIN VALS V2 ON V2.OBJ_ID = L10.OBJ_ID AND V2.PARAM_ID = 56 AND V2.IS_DEL = 0
          WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND 0 = 1
          GROUP BY 1
          INTO :STUDENT_ID
      DO
      BEGIN

          -- Наличие и дата изменения кодов
          DATE_P_UID1 = NULL;
          DATE_P_UID2 = NULL;
          SELECT MAX(V1570.DATE_MODIFY), MAX(V155.DATE_MODIFY)
          FROM LINKS L20
          JOIN VALS V1570 ON V1570.OBJ_ID = L20.EXT_OBJ_ID AND V1570.PARAM_ID = 1570 AND V1570.IS_DEL = 0
          JOIN VALS V155 ON V155.OBJ_ID = L20.OBJ_ID AND V155.PARAM_ID = 155 AND V155.IS_DEL = 0
          WHERE L20.PARENT_ID = :STUDENT_ID AND L20.OBJ_TYPE_ID = 20 AND L20.DATE_DEL IS NULL
          INTO :DATE_P_UID1, :DATE_P_UID2;

          IF(DATE_P_UID1 IS NOT NULL AND DATE_P_UID2 IS NOT NULL AND I$MODE = 0) THEN
          BEGIN

              FOR
                  SELECT J.SUBJECT_ID, MAX(J.OBJ_ID)
                  FROM PERSON_MOVEMENTS M
                  JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.JOURNAL_TYPE = 0 AND J.GRADE_ID = M.GROUP_ID
                  WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :STUDENT_ID AND M.DATE_OUT IS NULL
                  GROUP BY 1
                  INTO :SUBJECT_ID, :CJ_ID
              DO
              BEGIN

                  -- Напоминания (темы для повторения) - выбираем последние 3 плохие отметки по датам, не старше 2 месяцев
                  MSG_TEXT = '';
                  FOR
                      SELECT FIRST 3 C.CONTROL_TYPE_ID, L.LESSON_THEME, L.LESSON_DATE
                      FROM CJ2_JOURNAL_LESSONS L
                      JOIN CJ2_CONTROL C ON C.DATE_DEL IS NULL AND C.LESSON_ID = L.OBJ_ID AND C.CONTROL_ID IN (1058, 1063)
                      JOIN CJ2_MARK M ON M.DATE_DEL IS NULL AND M.CONTROL_ID = C.CONTROL_ID AND M.STUDENT_ID = :STUDENT_ID
                      JOIN CJ2_MARK_TYPE MT ON MT.MARK_TYPE_ID = M.MARK_TYPE_ID AND MT.MARK_COST < 3
                      WHERE L.DATE_DEL IS NULL AND L.CJ_ID = :CJ_ID AND L.LESSON_DATE >= DATEADD(-2 MONTH TO CURRENT_DATE)
                      ORDER BY L.LESSON_DATE DESC
                      INTO :CONTROL_TYPE_ID, :S, :DATE_ABSENT
                  DO
                  BEGIN
                      IF(CONTROL_TYPE_ID = 1063) THEN
                      BEGIN
                          S = NULL;
                          SELECT FIRST 1 L.LESSON_HOMEWORK
                          FROM CJ2_JOURNAL_LESSONS L
                          WHERE L.DATE_DEL IS NULL AND L.CJ_ID = :CJ_ID AND L.LESSON_DATE < :DATE_ABSENT
                          ORDER BY L.LESSON_DATE DESC
                          INTO :S;

                          S = 'ДЗ: ' || S;
                      END
                      IF(S IS NOT NULL) THEN
                      BEGIN
                          IF(CHAR_LENGTH(MSG_TEXT) + CHAR_LENGTH(S) + 2 < 2000) THEN
                          BEGIN
                              IF(MSG_TEXT <> '') THEN MSG_TEXT = MSG_TEXT || '; ';
                              MSG_TEXT = MSG_TEXT || S;
                          END
                      END
                  END

                  TAG_NAME = 'wsdl&colon;EstimateInput';
                  VAL = NULL;
                  SUSPEND;

                  TAG_NAME = 'wsdl&colon;EstimateInput:identity:external_id';
                  VAL = 'miss_' || STUDENT_ID || '_' || SUBJECT_ID;
                  SUSPEND;

                  TAG_NAME = 'wsdl&colon;EstimateInput:subject_id:external_id';
                  VAL = SUBJECT_ID;
                  SUSPEND;

                  TAG_NAME = 'wsdl&colon;EstimateInput:student_id:external_id';
                  VAL = STUDENT_ID;
                  SUSPEND;

                  TAG_NAME = 'wsdl&colon;EstimateInput:teacher_id:external_id';
                  VAL = '';
                  SUSPEND;

                  TAG_NAME = 'wsdl&colon;EstimateInput:date';
                  VAL = (SELECT VAL FROM DATE2ISO(CURRENT_DATE, 0));
                  SUSPEND;

                  TAG_NAME = 'wsdl&colon;EstimateInput:institution_id:id';
                  VAL = ID1;
                  SUSPEND;

                  TAG_NAME = 'wsdl&colon;EstimateInput:value:code';
                  VAL = '12000';
                  SUSPEND;

                  TAG_NAME = 'wsdl&colon;EstimateInput:system:code';
                  VAL = 'assimilation';
                  SUSPEND;

                  TAG_NAME = 'wsdl&colon;EstimateInput:type:code';
                  VAL = 1096;
                  SUSPEND;

                  TAG_NAME = 'wsdl&colon;EstimateInput:estimate_comment';
                  IF(MSG_TEXT = '') THEN MSG_TEXT = 'Напоминаний нет';
                  VAL = MSG_TEXT;
                  SUSPEND;

                  N = N + 1;
                  IF(N >= 10000) THEN
                  BEGIN
                      N = 0;
                      TAG_NAME = NULL;
                      VAL = 'DIVIDE';
                      SUSPEND;
                  END

                  -- Дефициты по ПЭС, нормировано к 5-балльной шкале
                  MSG_TEXT = '';
                  FOR
                      SELECT FIRST 3 CI.CAPTION
                      FROM VALX V
                      JOIN CEC_ITEMS CI ON CI.OBJ_ID = V.CEC_ID AND CI.DATE_DEL IS NULL
                      JOIN CEC C ON C.OBJ_ID = CI.CEC_ID AND C.DATE_DEL IS NULL AND C.SUBJECT_ID = :SUBJECT_ID
                      WHERE V.PUPIL_ID = :STUDENT_ID AND V.CEC_ID <> 0 AND V.YEAR_ID = :YEAR_ID AND V.LVAL < 3
                      ORDER BY V.LVAL
                      INTO :S
                  DO
                  BEGIN
                      IF(CHAR_LENGTH(MSG_TEXT) + CHAR_LENGTH(S) + 2 < 2000) THEN
                      BEGIN
                          IF(MSG_TEXT <> '') THEN MSG_TEXT = MSG_TEXT || '; ';
                          MSG_TEXT = MSG_TEXT || S;
                      END
                  END

                  TAG_NAME = 'wsdl&colon;EstimateInput';
                  VAL = NULL;
                  SUSPEND;

                  TAG_NAME = 'wsdl&colon;EstimateInput:identity:external_id';
                  VAL = 'def_' || STUDENT_ID || '_' || SUBJECT_ID;
                  SUSPEND;

                  TAG_NAME = 'wsdl&colon;EstimateInput:subject_id:external_id';
                  VAL = SUBJECT_ID;
                  SUSPEND;

                  TAG_NAME = 'wsdl&colon;EstimateInput:student_id:external_id';
                  VAL = STUDENT_ID;
                  SUSPEND;

                  TAG_NAME = 'wsdl&colon;EstimateInput:teacher_id:external_id';
                  VAL = '';
                  SUSPEND;

                  TAG_NAME = 'wsdl&colon;EstimateInput:date';
                  VAL = (SELECT VAL FROM DATE2ISO(CURRENT_DATE, 0));
                  SUSPEND;

                  TAG_NAME = 'wsdl&colon;EstimateInput:institution_id:id';
                  VAL = ID1;
                  SUSPEND;

                  TAG_NAME = 'wsdl&colon;EstimateInput:value:code';
                  VAL = '12000';
                  SUSPEND;

                  TAG_NAME = 'wsdl&colon;EstimateInput:system:code';
                  VAL = 'assimilation';
                  SUSPEND;

                  TAG_NAME = 'wsdl&colon;EstimateInput:type:code';
                  VAL = 1094;
                  SUSPEND;

                  TAG_NAME = 'wsdl&colon;EstimateInput:estimate_comment';
                  IF(MSG_TEXT = '') THEN MSG_TEXT = 'Дефицитов нет';
                  VAL = MSG_TEXT;
                  SUSPEND;

                  N = N + 1;
                  IF(N >= 10000) THEN
                  BEGIN
                      N = 0;
                      TAG_NAME = NULL;
                      VAL = 'DIVIDE';
                      SUSPEND;
                  END

                  -- Результат освоения ОП, в виде позитива по УУД
                  MSG_TEXT = '';
                  FOR
                      SELECT FIRST 3 DISTINCT R.VAL
                      FROM VALX V
                      JOIN LISTVALS LV ON LV.LISTVAL_ID = V.USA_SUBGROUP AND LV.IS_DEL = 0
                      JOIN CJ2_JOURNAL_LESSONS L ON L.DATE_DEL IS NULL AND L.CJ_ID = :CJ_ID
                      JOIN CJ2_CONTROL C ON C.DATE_DEL IS NULL AND C.LESSON_ID = L.OBJ_ID AND C.CONTROL_TYPE_ID = 30000
                      JOIN CJ2_LESSON_UUD LU ON LU.CONTROL_ID = C.CONTROL_ID AND LU.USA_ID = V.USA_ID AND LU.IS_DEL = 0
                      JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
                      WHERE V.PUPIL_ID = :STUDENT_ID AND V.USA_ID <> 0 AND V.YEAR_ID = :YEAR_ID AND V.LVAL > 0
                      ORDER BY V.LVAL
                      INTO :S
                  DO
                  BEGIN
                      IF(CHAR_LENGTH(MSG_TEXT) + CHAR_LENGTH(S) + 2 < 2000) THEN
                      BEGIN
                          IF(MSG_TEXT <> '') THEN MSG_TEXT = MSG_TEXT || '; ';
                          MSG_TEXT = MSG_TEXT || S;
                      END
                  END

                  TAG_NAME = 'wsdl&colon;EstimateInput';
                  VAL = NULL;
                  SUSPEND;

                  TAG_NAME = 'wsdl&colon;EstimateInput:identity:external_id';
                  VAL = 'rs_' || STUDENT_ID || '_' || SUBJECT_ID;
                  SUSPEND;

                  TAG_NAME = 'wsdl&colon;EstimateInput:subject_id:external_id';
                  VAL = SUBJECT_ID;
                  SUSPEND;

                  TAG_NAME = 'wsdl&colon;EstimateInput:student_id:external_id';
                  VAL = STUDENT_ID;
                  SUSPEND;

                  TAG_NAME = 'wsdl&colon;EstimateInput:teacher_id:external_id';
                  VAL = '';
                  SUSPEND;

                  TAG_NAME = 'wsdl&colon;EstimateInput:date';
                  VAL = (SELECT VAL FROM DATE2ISO(CURRENT_DATE, 0));
                  SUSPEND;

                  TAG_NAME = 'wsdl&colon;EstimateInput:institution_id:id';
                  VAL = ID1;
                  SUSPEND;

                  TAG_NAME = 'wsdl&colon;EstimateInput:value:code';
                  VAL = '12000';
                  SUSPEND;

                  TAG_NAME = 'wsdl&colon;EstimateInput:system:code';
                  VAL = 'assimilation';
                  SUSPEND;

                  TAG_NAME = 'wsdl&colon;EstimateInput:type:code';
                  VAL = 1095;
                  SUSPEND;

                  TAG_NAME = 'wsdl&colon;EstimateInput:estimate_comment';
                  IF(MSG_TEXT = '') THEN MSG_TEXT = '-';
                  VAL = MSG_TEXT;
                  SUSPEND;

                  N = N + 1;
                  IF(N >= 10000) THEN
                  BEGIN
                      N = 0;
                      TAG_NAME = NULL;
                      VAL = 'DIVIDE';
                      SUSPEND;
                  END

              END

          END

      END

  END

  IF(V$INFO_ID IS NULL) THEN
  INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL) VALUES ('PORTAL_UPDATE_HINTS', 'PORTAL_UPDATE_HINTS', CURRENT_TIMESTAMP);
  ELSE
  UPDATE INFO SET INFO_VAL = CURRENT_TIMESTAMP WHERE INFO_ID = :V$INFO_ID;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_PORTAL_ESTIMATES_DELETE (
    T_FROM TIMESTAMP,
    T_TO TIMESTAMP NOT NULL = current_timestamp,
    ID1 VARCHAR(40) = null,
    ID2 VARCHAR(40) = null,
    I$MODE SMALLINT = 0)
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(2000))
AS
declare variable YEAR_ID bigint;
declare variable IS_OK smallint;
declare variable MARK_ID varchar(40);
declare variable MARK_DT timestamp;
declare variable V$STUDENT_ID bigint;
declare variable V$CLASS_ID bigint;
declare variable V$CLASS_TYPE_ID bigint;
declare variable V$STUDENT_DT timestamp;
declare variable V$STUDENT_DT2 timestamp;
declare variable N integer;
begin

  IF(T_FROM IS NULL) THEN EXIT;

  SELECT FIRST 1 V1236.LISTVAL_ID
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :YEAR_ID;

  N = 0;

  -- Реальные удаленные отметки
  -- Тут может быть полная хрень, т.к. мы не знаем чья отметка была удалена и был ли он вообще в выгрузке
  -- удаленные отметки грузим и как M, и как F - непонятно какая из них
  FOR
      SELECT 'MX' || M.MARK_ID, M.DATE_DEL
      FROM CJ2_JOURNAL J
      JOIN CJ2_JOURNAL_LESSONS L ON L.CJ_ID = J.OBJ_ID
      JOIN LINKS L179 ON L179.OBJ_ID = J.GRADE_ID AND L179.OBJ_TYPE_ID = 179 AND L179.PARENT_TYPE_ID = 2 AND L179.DATE_DEL IS NULL
      -- Признак группы ЦОПП
      LEFT JOIN VALL V3064 ON V3064.OBJ_ID = L179.OBJ_ID AND V3064.PARAM_ID = 3064 AND V3064.IS_DEL = 0
      JOIN CJ2_CONTROL C ON C.LESSON_ID = L.OBJ_ID
      JOIN CJ2_MARK M ON M.CONTROL_ID = C.CONTROL_ID AND M.DATE_DEL IS NOT NULL
      WHERE J.DATE_DEL IS NULL AND J.JOURNAL_TYPE = 0 AND J.YEAR_ID = :YEAR_ID
          AND ((:I$MODE = 0 AND (V3064.LISTVAL_ID IS NULL OR V3064.LISTVAL_ID = 3)) OR (:I$MODE = 1 AND V3064.LISTVAL_ID = 2))
      -- Удаленные итоговые
      UNION ALL
      SELECT 'FX' || M.MARK_ID, M.DATE_DEL
      FROM CJ2_JOURNAL J
      JOIN CJ2_JOURNAL_FINALS F ON F.CJ_ID = J.OBJ_ID
      JOIN LINKS L179 ON L179.OBJ_ID = J.GRADE_ID AND L179.OBJ_TYPE_ID = 179 AND L179.PARENT_TYPE_ID = 2 AND L179.DATE_DEL IS NULL
      -- Признак группы ЦОПП
      LEFT JOIN VALL V3064 ON V3064.OBJ_ID = L179.OBJ_ID AND V3064.PARAM_ID = 3064 AND V3064.IS_DEL = 0
      JOIN CJ2_MARK M ON M.FINAL_ID = F.OBJ_ID AND M.DATE_DEL IS NOT NULL
      WHERE J.DATE_DEL IS NULL AND J.JOURNAL_TYPE = 0 AND J.YEAR_ID = :YEAR_ID
          AND ((:I$MODE = 0 AND (V3064.LISTVAL_ID IS NULL OR V3064.LISTVAL_ID = 3)) OR (:I$MODE = 1 AND V3064.LISTVAL_ID = 2))
      -- !!! удаленные итоговые прошлых лет !!!
      INTO :MARK_ID, :MARK_DT
  DO
  BEGIN

      IS_OK = 0;
      IF(
          ((T_FROM IS NULL OR MARK_DT >= T_FROM) AND MARK_DT < T_TO)
      )
      THEN
          IS_OK = 1;

      IF(IS_OK = 1) THEN
      BEGIN

          TAG_NAME = 'wsdl&colon;IdentityElementInput';
          VAL = NULL;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;IdentityElementInput:identity:external_id';
          VAL = MARK_ID;
          SUSPEND;

          N = N + 1;
          IF(N >= 10000) THEN
          BEGIN
              N = 0;
              TAG_NAME = NULL;
              VAL = 'DIVIDE';
              SUSPEND;
          END

      END

  END

  -- Отметки по урокам, где был снят флаг проведения урока - невозможно понять, точно ли это был снят флаг проведения урока
  -- Итоговые отметки с перенесенной датой пока идут лесом
  /* FOR
      SELECT
      FROM CJ_LESSON CJL
      WHERE CJL.IS_FINISHED = 0
  DO
  BEGIN
  END */

  -- Отметки по ученикам с затертыми кодами удалять не надо, удаляем только самого ученика

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_PORTAL_GROUPS (
    T_FROM TIMESTAMP,
    T_TO TIMESTAMP NOT NULL = current_timestamp,
    ID1 VARCHAR(40) = null,
    ID2 VARCHAR(40) = null,
    I$MODE SMALLINT = 0)
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(2000))
AS
declare variable OU_ID bigint;
declare variable GROUP_NAME varchar(1000);
declare variable NAME_DT timestamp;
declare variable GROUP_ID bigint;
declare variable CM_ID bigint;
declare variable GROUP_DT timestamp;
declare variable CM_DT timestamp;
declare variable PORTAL_DT timestamp;
declare variable IS_OK smallint;
declare variable IS_ACTIVE smallint;
declare variable FINAL_LV bigint;
declare variable FINAL_DT timestamp;
declare variable SUBJECT_NAME varchar(1000);
declare variable SUBJECT_DT timestamp;
declare variable LEVEL_NAME varchar(100);
declare variable PERIOD_ID bigint;
declare variable PERIOD_DT timestamp;
declare variable STAGE_ID bigint;
declare variable YEAR_ID bigint;
declare variable LOAD_ID bigint;
declare variable JT integer;
begin

  IF(ID1 IS NULL) THEN
  BEGIN
      SELECT FIRST 1 V2910.VAL
      FROM LINKS L2
      JOIN VALS V2910 ON V2910.OBJ_ID = L2.OBJ_ID AND V2910.PARAM_ID = 2910 AND V2910.IS_DEL = 0
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      INTO :ID1;
  END

  SELECT FIRST 1 V1236.LISTVAL_ID
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :YEAR_ID;

  -- Все рабочие учебные коллективы в течение учебного года чистятся, перманентно только административное деление

  -- #9, #125, #187 - классы, актуальные (классы не должны удаляться в течение учебного года)
  FOR
      SELECT DISTINCT L2.OBJ_ID, L9.OBJ_ID, V53.VAL, L9.DATE_MODIFY, V53.DATE_MODIFY, VF.LISTVAL_ID, VF.DATE_MODIFY, V49.LISTVAL_ID
      FROM LINKS L2
      JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
      JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
      JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 125, 187) AND L9.DATE_DEL IS NULL
      -- Классный руководитель
      LEFT JOIN VALR V53 ON V53.OBJ_ID = L9.OBJ_ID AND V53.PARAM_ID = 53 AND V53.IS_DEL = 0
      -- Признак выпускного класса
      LEFT JOIN VALL VF ON VF.OBJ_ID = L9.OBJ_ID AND VF.PARAM_ID IN (2388, 2418, 2419) AND VF.IS_DEL = 0
      -- Признак группы ЦОПП
      LEFT JOIN VALL V3063 ON V3063.OBJ_ID = L9.OBJ_ID AND V3063.PARAM_ID = 3063 AND V3063.IS_DEL = 0
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
          AND ((:I$MODE = 0 AND (V3063.LISTVAL_ID IS NULL OR V3063.LISTVAL_ID = 3)) OR (:I$MODE = 1 AND V3063.LISTVAL_ID = 2))
      ORDER BY V49.LISTVAL_ID
      INTO :OU_ID, :GROUP_ID, :CM_ID, :GROUP_DT, :CM_DT, :FINAL_LV, :FINAL_DT, :STAGE_ID
  DO
  BEGIN
      -- Проверяем название коллектива и метку времени изменения
      GROUP_NAME = NULL;
      SELECT V54.VAL, V54.DATE_MODIFY
      FROM VALS V54
      WHERE V54.OBJ_ID = :GROUP_ID AND V54.PARAM_ID IN (54, 820, 1652) AND V54.IS_DEL = 0
      INTO :GROUP_NAME, :NAME_DT;

      -- Если параметр был удален, смотрим момент последнего удаления
      IF(GROUP_NAME IS NULL) THEN
      BEGIN
          SELECT MAX(V54.DATE_MODIFY)
          FROM VALS V54
          WHERE V54.OBJ_ID = :GROUP_ID AND V54.PARAM_ID IN (54, 820, 1652)
          INTO :NAME_DT;
      END
      IF(NAME_DT IS NULL) THEN NAME_DT = '01.01.2000';

      -- К названию прикрепляем номер параллели
      SELECT LV.TAG || COALESCE(' ' || :GROUP_NAME, ''), MAXVALUE(V49.DATE_MODIFY, :NAME_DT)
      FROM LINKS LP8
      JOIN VALL V49 ON V49.OBJ_ID = LP8.PARENT_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
      JOIN LISTVALS LV ON LV.LISTVAL_ID = V49.LISTVAL_ID
      WHERE LP8.OBJ_ID = :GROUP_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
      INTO :GROUP_NAME, :NAME_DT;

      -- Период привязываем через учащихся
      -- В качестве периода пытаемся найти период из ГУП (первый найденный); если нет, то ищем первый из потоков
      -- По новой схеме учебных периодов для ГУП больше нет, надо смотреть группы переменного состава
      -- Убираем из поиска журналы по предметам, которые содержат символ @ в названии (хитрые мультивозрастные предметы)
      PERIOD_ID = NULL;
      PERIOD_DT = NULL;

      IF(I$MODE = 0) THEN
      BEGIN
          SELECT FIRST 1 J.PERIOD_ID, MAX(J.DATE_MODIFY), COUNT(*)
          FROM LINKS L10
          JOIN LINKS LPG ON LPG.OBJ_ID = L10.OBJ_ID AND LPG.PARENT_TYPE_ID = 179 AND LPG.DATE_DEL IS NULL
          JOIN CJ2_JOURNAL J ON J.GRADE_ID = LPG.PARENT_ID AND J.DATE_DEL IS NULL AND J.JOURNAL_TYPE = 0
          LEFT JOIN VALS V376 ON V376.OBJ_ID = J.SUBJECT_ID AND V376.PARAM_ID = 376 AND V376.IS_DEL = 0
          WHERE L10.PARENT_ID = :GROUP_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL AND (V376.SVAL IS NULL OR POSITION('@' IN V376.SVAL) <= 0)
          GROUP BY 1
          ORDER BY 3 DESC
          INTO :PERIOD_ID, :PERIOD_DT, :LOAD_ID;

          -- Если период не нашелся, возвращаем первый попавшийся учебный период
          IF(PERIOD_ID IS NULL) THEN
          BEGIN
              SELECT FIRST 1 L151.OBJ_ID, L151.DATE_MODIFY
              FROM LINKS L150
              JOIN LINKS L151 ON L151.PARENT_ID = L150.OBJ_ID AND L151.OBJ_TYPE_ID = 151 AND L151.DATE_DEL IS NULL
              WHERE L150.PARENT_TYPE_ID = 2 AND L150.OBJ_TYPE_ID IN (150, 481) AND L150.DATE_DEL IS NULL
              ORDER BY 2
              INTO :PERIOD_ID, :PERIOD_DT;
          END
      END
      ELSE
      BEGIN
          PERIOD_ID = GROUP_ID;
          PERIOD_DT = GROUP_DT;
      END

      -- Метка изменения id петеробра или фиас у классного руководителя
      PORTAL_DT = NULL;
      SELECT MAX(V267.DATE_MODIFY)
      FROM VALS V267
      WHERE V267.OBJ_ID = :CM_ID AND V267.PARAM_ID IN (267, 3061)
      INTO :PORTAL_DT;

      IS_OK = 0;

      IF((GROUP_NAME IS NOT NULL) AND
          ((T_FROM IS NULL OR GROUP_DT >= T_FROM) AND (GROUP_DT < T_TO)) OR
          ((T_FROM IS NULL OR PERIOD_DT >= T_FROM) AND (PERIOD_DT < T_TO)) OR
          ((T_FROM IS NULL OR CM_DT >= T_FROM) AND (CM_DT < T_TO)) OR
          ((T_FROM IS NULL OR PORTAL_DT >= T_FROM) AND (PORTAL_DT < T_TO)) OR
          ((T_FROM IS NULL OR FINAL_DT >= T_FROM) AND (FINAL_DT < T_TO))
      )
      THEN
          IS_OK = 1;

      IF(IS_OK = 1) THEN
      BEGIN

          -- Начинаем новую группу
          TAG_NAME = 'wsdl&colon;GroupInput';
          VAL = NULL;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;GroupInput:identity:external_id';
          VAL = GROUP_ID;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;GroupInput:name';
          VAL = GROUP_NAME;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;GroupInput:type:code';
          VAL = '1';
          SUSPEND;

          TAG_NAME = 'wsdl&colon;GroupInput:period_id:external_id';
          VAL = PERIOD_ID;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;GroupInput:stage:code';
          VAL = NULL;
          IF(I$MODE = 0) THEN
          BEGIN
              VAL = CASE STAGE_ID WHEN 12765 THEN '00' WHEN 37 THEN '01' WHEN 38 THEN '02' WHEN 39 THEN '03' WHEN 40 THEN '04' WHEN 41 THEN '05'
                  WHEN 42 THEN '06' WHEN 43 THEN '07' WHEN 44 THEN '08' WHEN 45 THEN '09' WHEN 46 THEN '10' WHEN 47 THEN '11' WHEN 48 THEN '13'
                  -- Колледжи
                  WHEN 13145 THEN '14' WHEN 49 THEN '01' WHEN 50 THEN '02' WHEN 51 THEN '03' WHEN 52 THEN '04' WHEN 53 THEN '05' WHEN 54 THEN '06'
                  END;
          END
          ELSE IF(I$MODE = 1) THEN
          BEGIN
              -- В режиме ЦОПП коды для школ вызовут ошибку, и черт с ней
              VAL = CASE STAGE_ID WHEN 12765 THEN '00' WHEN 37 THEN '01' WHEN 38 THEN '02' WHEN 39 THEN '03' WHEN 40 THEN '04' WHEN 41 THEN '05'
                  WHEN 42 THEN '06' WHEN 43 THEN '07' WHEN 44 THEN '08' WHEN 45 THEN '09' WHEN 46 THEN '10' WHEN 47 THEN '11' WHEN 48 THEN '13'
                  -- Колледжи ЦОПП
                  WHEN 13145 THEN '14' WHEN 49 THEN '14' WHEN 50 THEN '15' WHEN 51 THEN '16' WHEN 52 THEN '17' WHEN 53 THEN '18' WHEN 54 THEN '19'
                  END;
          END
          SUSPEND;

          -- Классный руководитель, если есть (берем только явно заданных в классе)
          IF(CM_ID IS NOT NULL) THEN
          BEGIN
              -- Надо проверить, что классный руководитель действующий
              IS_ACTIVE = 0;
              SELECT FIRST 1 1
              FROM LINKS L14
              WHERE L14.PARENT_ID = :OU_ID AND L14.OBJ_ID = :CM_ID AND L14.DATE_DEL IS NULL
              INTO :IS_ACTIVE;

              IF(IS_ACTIVE = 1) THEN
              BEGIN
                  TAG_NAME = 'wsdl&colon;GroupInput:head_id:external_id';
                  VAL = CM_ID;
                  SUSPEND;
              END
          END

          -- Признак выпускного класса
          IF(FINAL_LV IN (2, 11202, 11203)) THEN FINAL_LV = 1; ELSE FINAL_LV = 0;
          TAG_NAME = 'wsdl&colon;GroupInput:is_finish';
          VAL = FINAL_LV;
          SUSPEND;

          -- Список предметников (teacher-subject) тут не формируем

          TAG_NAME = 'wsdl&colon;GroupInput:institution_id:id';
          VAL = ID1;
          SUSPEND;

          -- Признак внеурочности
          TAG_NAME = 'wsdl&colon;GroupInput:activity_kind:code';
          VAL = 1;
          SELECT FIRST 1 2
          FROM CJ2_JOURNAL J
          WHERE J.DATE_DEL IS NULL AND J.GRADE_ID = :GROUP_ID AND J.JOURNAL_TYPE = 1
          INTO :VAL;
          SUSPEND;

      END

  END

  -- ГУП и Потоки пока оставляем, но только для нативной выгрузки
  -- для ЦОПП добавляем новый механизм журналов

  -- #256 ГУП всех сортов, актуальные
  FOR
      SELECT L256.OBJ_ID, L256.DATE_MODIFY, V2162.VAL, V2162.DATE_MODIFY, V381.LISTVAL_ID
      FROM LINKS L2
      JOIN LINKS L69 ON L69.PARENT_ID = L2.OBJ_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL
      JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
      JOIN LINKS L50 ON L50.PARENT_ID = L57.OBJ_ID AND L50.OBJ_TYPE_ID = 50 AND L50.DATE_DEL IS NULL
      -- Только групповые УП
      JOIN VALL V2101 ON V2101.OBJ_ID = L50.OBJ_ID AND V2101.PARAM_ID = 2101 AND V2101.IS_DEL = 0 AND V2101.LISTVAL_ID IN (5465, 5466)
      JOIN LINKS L54 ON L54.PARENT_ID = L50.OBJ_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
      JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
      JOIN LINKS L256 ON L256.PARENT_ID = L54.OBJ_ID AND L256.OBJ_TYPE_ID = 256 AND L256.DATE_DEL IS NULL
      JOIN VALS V2162 ON V2162.OBJ_ID = L256.OBJ_ID AND V2162.PARAM_ID = 2162 AND V2162.IS_DEL = 0
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND :I$MODE = 0 AND :YEAR_ID < 10981
      ORDER BY V381.LISTVAL_ID
      INTO :GROUP_ID, :GROUP_DT, :GROUP_NAME, :NAME_DT, :STAGE_ID
  DO
  BEGIN

      -- Выбираем метку времени последних изменений предметников
      CM_ID = NULL;
      SELECT MAX(LP14.DATE_MODIFY)
      FROM LINKS L58
      JOIN LINKS LP14 ON LP14.OBJ_ID = L58.OBJ_ID AND LP14.PARENT_TYPE_ID = 14 AND LP14.DATE_DEL IS NULL
      WHERE L58.PARENT_ID = :GROUP_ID AND L58.OBJ_TYPE_ID = 58 AND L58.DATE_DEL IS NULL
      INTO :CM_DT;

      -- Привязка к учебному периоду
      PERIOD_ID = NULL;
      PERIOD_DT = NULL;

      SELECT FIRST 1 J.PERIOD_ID, J.DATE_MODIFY
      FROM CJ2_JOURNAL J
      WHERE J.GRADE_ID = :GROUP_ID AND J.DATE_DEL IS NULL
      INTO :PERIOD_ID, :PERIOD_DT;

      -- Если период не нашелся, возвращаем первый попавшийся учебный период
      IF(PERIOD_ID IS NULL) THEN
      BEGIN
          SELECT FIRST 1 L151.OBJ_ID, L151.DATE_MODIFY
          FROM LINKS L150
          JOIN LINKS L151 ON L151.PARENT_ID = L150.OBJ_ID AND L151.OBJ_TYPE_ID = 151 AND L151.DATE_DEL IS NULL
          WHERE L150.PARENT_TYPE_ID = 2 AND L150.OBJ_TYPE_ID IN (150, 481) AND L150.DATE_DEL IS NULL
          ORDER BY 2
          INTO :PERIOD_ID, :PERIOD_DT;
      END

      -- Не поменялся ли предметник ?
      PORTAL_DT = NULL;
      SELECT MAX(V267.DATE_MODIFY)
      FROM LINKS L58
      JOIN LINKS LP14 ON LP14.OBJ_ID = L58.OBJ_ID AND LP14.PARENT_TYPE_ID = 14 AND LP14.DATE_DEL IS NULL
      JOIN LINKS LP2 ON LP2.OBJ_ID = LP14.PARENT_ID AND LP2.PARENT_TYPE_ID = 2 AND LP2.DATE_DEL IS NULL
      JOIN VALS V267 ON V267.OBJ_ID = LP14.PARENT_ID AND V267.PARAM_ID = 267
      WHERE L58.PARENT_ID = :GROUP_ID AND L58.OBJ_TYPE_ID = 58 AND L58.DATE_DEL IS NULL
      INTO :PORTAL_DT;

      IS_OK = 0;

      IF(
          ((T_FROM IS NULL OR GROUP_DT >= T_FROM) AND (GROUP_DT < T_TO)) OR
          ((T_FROM IS NULL OR PERIOD_DT >= T_FROM) AND (PERIOD_DT < T_TO)) OR
          ((T_FROM IS NULL OR NAME_DT >= T_FROM) AND (NAME_DT < T_TO)) OR
          ((T_FROM IS NULL OR CM_DT >= T_FROM) AND (CM_DT < T_TO)) OR
          ((T_FROM IS NULL OR PORTAL_DT >= T_FROM) AND (PORTAL_DT < T_TO))
      )
      THEN
          IS_OK = 1;

      IF(IS_OK = 1) THEN
      BEGIN

          -- Начинаем новую группу
          TAG_NAME = 'wsdl&colon;GroupInput';
          VAL = NULL;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;GroupInput:identity:external_id';
          VAL = GROUP_ID;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;GroupInput:name';
          VAL = GROUP_NAME;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;GroupInput:type:code';
          VAL = '2';
          SUSPEND;

          TAG_NAME = 'wsdl&colon;GroupInput:period_id:external_id';
          VAL = PERIOD_ID;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;GroupInput:stage:code';
          VAL = CASE STAGE_ID WHEN 12765 THEN '00' WHEN 37 THEN '01' WHEN 38 THEN '02' WHEN 39 THEN '03' WHEN 40 THEN '04' WHEN 41 THEN '05'
            WHEN 42 THEN '06' WHEN 43 THEN '07' WHEN 44 THEN '08' WHEN 45 THEN '09' WHEN 46 THEN '10' WHEN 47 THEN '11' WHEN 48 THEN '13' ELSE NULL END;
          SUSPEND;

          -- Список предметников, не забываем n3ArrayField
          -- Их тут у нас вообще нет
          /*FOR
              SELECT LP14.LINK_ID
              FROM LINKS L58
              JOIN LINKS LP14 ON LP14.OBJ_ID = L58.OBJ_ID AND LP14.PARENT_TYPE_ID = 14 AND LP14.DATE_DEL IS NULL
              JOIN LINKS LP2 ON LP2.OBJ_ID = LP14.PARENT_ID AND LP2.PARENT_TYPE_ID = 2 AND LP2.DATE_DEL IS NULL
              WHERE L58.PARENT_ID = :GROUP_ID AND L58.OBJ_TYPE_ID = 58 AND L58.DATE_DEL IS NULL
              INTO :CM_ID
          DO
          BEGIN
              TAG_NAME = 'wsdl&colon;GroupInput:teacher_subject_id';
              VAL = NULL;
              SUSPEND;

              TAG_NAME = 'wsdl&colon;GroupInput:teacher_subject_id::n3ArrayField';
              VAL = 'true';
              SUSPEND;

              TAG_NAME = 'wsdl&colon;GroupInput:teacher_subject_id:external_id';
              VAL = CM_ID;
              SUSPEND;
          END*/

          TAG_NAME = 'wsdl&colon;GroupInput:institution_id:id';
          VAL = ID1;
          SUSPEND;

          -- Признак внеурочности
          TAG_NAME = 'wsdl&colon;GroupInput:activity_kind:code';
          VAL = 1;
          SELECT FIRST 1 2
          FROM CJ2_JOURNAL J
          WHERE J.DATE_DEL IS NULL AND J.GRADE_ID = :GROUP_ID AND J.JOURNAL_TYPE = 1
          INTO :VAL;
          SUSPEND;

      END
  END

  -- Новая схема выборки для нового формата журналов - пока берем только общеобразовательные текущего учебного года
  FOR
      SELECT L179.OBJ_ID, L179.DATE_MODIFY, J.DATE_MODIFY, COALESCE(V2927.VAL, 'Без названия'), V2927.DATE_MODIFY, J.STAGE_INDEX,
          J.TEACHER_ID, IIF(J.SUBJECT_ID IS NULL, NULL, J.OBJ_ID), J.PERIOD_ID, J.DATE_MODIFY, J.JOURNAL_TYPE
      FROM CJ2_JOURNAL J
      JOIN LINKS L179 ON L179.OBJ_ID = J.GRADE_ID AND L179.OBJ_TYPE_ID = 179 AND L179.PARENT_TYPE_ID = 2 AND L179.DATE_DEL IS NULL
      -- Название
      LEFT JOIN VALS V2927 ON V2927.OBJ_ID = L179.OBJ_ID AND V2927.PARAM_ID = 2927 AND V2927.IS_DEL = 0
      -- Признак группы ЦОПП
      LEFT JOIN VALL V3064 ON V3064.OBJ_ID = L179.OBJ_ID AND V3064.PARAM_ID = 3064 AND V3064.IS_DEL = 0
      WHERE J.DATE_DEL IS NULL AND J.YEAR_ID = :YEAR_ID AND J.JOURNAL_TYPE IN (0, 1, 10, 11)
          AND ((:I$MODE = 0 AND (V3064.LISTVAL_ID IS NULL OR V3064.LISTVAL_ID = 3)) OR (:I$MODE = 1 AND V3064.LISTVAL_ID = 2))
      ORDER BY J.STAGE_INDEX
      INTO :GROUP_ID, :GROUP_DT, :CM_DT, :GROUP_NAME, :NAME_DT, :STAGE_ID,
          :CM_ID, :LOAD_ID, :PERIOD_ID, :PERIOD_DT, :JT
  DO
  BEGIN

      -- Привязка к учебному периоду
      IF(I$MODE = 0) THEN
      BEGIN
          -- Если период не нашелся, возвращаем первый попавшийся учебный период
          IF(PERIOD_ID IS NULL) THEN
          BEGIN
              SELECT FIRST 1 L151.OBJ_ID, L151.DATE_MODIFY
              FROM LINKS L150
              JOIN LINKS L151 ON L151.PARENT_ID = L150.OBJ_ID AND L151.OBJ_TYPE_ID = 151 AND L151.DATE_DEL IS NULL
              WHERE L150.PARENT_TYPE_ID = 2 AND L150.OBJ_TYPE_ID IN (150, 481) AND L150.DATE_DEL IS NULL
              ORDER BY 2
              INTO :PERIOD_ID, :PERIOD_DT;
          END
      END
      ELSE
      BEGIN
          -- Упаси бог тут будут переходы между группами
          SELECT FIRST 1 LP9.PARENT_ID, LP8.DATE_MODIFY
          FROM LINKS L10
          JOIN LINKS LP9 ON LP9.OBJ_ID = L10.OBJ_ID AND LP9.PARENT_TYPE_ID = 9
          JOIN LINKS LP8 ON LP8.OBJ_ID = LP9.PARENT_ID AND LP8.PARENT_TYPE_ID = 8
          WHERE L10.PARENT_ID = :GROUP_ID AND L10.OBJ_TYPE_ID = 10
          ORDER BY LP9.DATE_INS DESC, LP8.DATE_INS DESC
          INTO :PERIOD_ID, :PERIOD_DT;
      END

      -- Метка изменения id петеробра или фиас у предметника
      PORTAL_DT = NULL;
      SELECT MAX(V267.DATE_MODIFY)
      FROM VALS V267
      WHERE V267.OBJ_ID = :CM_ID AND V267.PARAM_ID IN (267, 3061)
      INTO :PORTAL_DT;

      IS_OK = 0;

      IF(
          ((T_FROM IS NULL OR GROUP_DT >= T_FROM) AND (GROUP_DT < T_TO)) OR
          ((T_FROM IS NULL OR PERIOD_DT >= T_FROM) AND (PERIOD_DT < T_TO)) OR
          ((T_FROM IS NULL OR NAME_DT >= T_FROM) AND (NAME_DT < T_TO)) OR
          ((T_FROM IS NULL OR CM_DT >= T_FROM) AND (CM_DT < T_TO)) OR
          ((T_FROM IS NULL OR PORTAL_DT >= T_FROM) AND (PORTAL_DT < T_TO))
      )
      THEN
          IS_OK = 1;

      IF(IS_OK = 1) THEN
      BEGIN

          -- Начинаем новую группу
          TAG_NAME = 'wsdl&colon;GroupInput';
          VAL = NULL;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;GroupInput:identity:external_id';
          VAL = GROUP_ID;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;GroupInput:name';
          VAL = GROUP_NAME;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;GroupInput:type:code';
          VAL = '2';
          SUSPEND;

          TAG_NAME = 'wsdl&colon;GroupInput:period_id:external_id';
          VAL = PERIOD_ID;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;GroupInput:stage:code';
          VAL = NULL;
          IF(I$MODE = 0) THEN
          BEGIN
              VAL = CASE STAGE_ID WHEN 12765 THEN '00' WHEN 37 THEN '01' WHEN 38 THEN '02' WHEN 39 THEN '03' WHEN 40 THEN '04' WHEN 41 THEN '05'
                  WHEN 42 THEN '06' WHEN 43 THEN '07' WHEN 44 THEN '08' WHEN 45 THEN '09' WHEN 46 THEN '10' WHEN 47 THEN '11' WHEN 48 THEN '13'
                  -- Колледжи
                  WHEN 13145 THEN '14' WHEN 49 THEN '01' WHEN 50 THEN '02' WHEN 51 THEN '03' WHEN 52 THEN '04' WHEN 53 THEN '05' WHEN 54 THEN '06'
                  END;
          END
          ELSE IF(I$MODE = 1) THEN
          BEGIN
              -- В режиме ЦОПП коды для школ вызовут ошибку, и черт с ней
              VAL = CASE STAGE_ID WHEN 12765 THEN '00' WHEN 37 THEN '01' WHEN 38 THEN '02' WHEN 39 THEN '03' WHEN 40 THEN '04' WHEN 41 THEN '05'
                  WHEN 42 THEN '06' WHEN 43 THEN '07' WHEN 44 THEN '08' WHEN 45 THEN '09' WHEN 46 THEN '10' WHEN 47 THEN '11' WHEN 48 THEN '13'
                  -- Колледжи ЦОПП
                  WHEN 13145 THEN '14' WHEN 49 THEN '14' WHEN 50 THEN '15' WHEN 51 THEN '16' WHEN 52 THEN '17' WHEN 53 THEN '18' WHEN 54 THEN '19'
                  END;
          END
          SUSPEND;

          -- Список предметников, не забываем n3ArrayField - он тут из одного пункта
          -- Но id у него не самого учителя, а журнала - выдаем только если предметник назначен
          IF(CM_ID IS NOT NULL) THEN
          BEGIN
              TAG_NAME = 'wsdl&colon;GroupInput:teacher_subject_id';
              VAL = NULL;
              SUSPEND;

              TAG_NAME = 'wsdl&colon;GroupInput:teacher_subject_id::n3ArrayField';
              VAL = 'true';
              SUSPEND;

              TAG_NAME = 'wsdl&colon;GroupInput:teacher_subject_id:external_id';
              VAL = LOAD_ID;
              SUSPEND;
          END

          TAG_NAME = 'wsdl&colon;GroupInput:institution_id:id';
          VAL = ID1;
          SUSPEND;

          -- Признак внеурочности
          TAG_NAME = 'wsdl&colon;GroupInput:activity_kind:code';
          IF(JT = 1) THEN VAL = 2; ELSE VAL = 1;
          SUSPEND;

      END

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_PORTAL_GROUPS_DELETE (
    T_FROM TIMESTAMP,
    T_TO TIMESTAMP NOT NULL = current_timestamp,
    ID1 VARCHAR(40) = null,
    ID2 VARCHAR(40) = null,
    I$MODE SMALLINT = 0)
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(2000))
AS
declare variable GROUP_ID bigint;
declare variable GROUP_DT timestamp;
declare variable IS_OK smallint;
declare variable PERIOD_START date;
begin

  IF(T_FROM IS NULL) THEN EXIT;

  -- Удаление классов прогружаем с запасом в 1 месяц от реального начала учебного года
  IF(EXTRACT(MONTH FROM CURRENT_DATE) < 9) THEN PERIOD_START = '01.08.' || (EXTRACT(YEAR FROM CURRENT_DATE) - 1);
  ELSE PERIOD_START = '01.08.' || EXTRACT(YEAR FROM CURRENT_DATE);

  -- Сначала классы
  -- Уровни образования и этапы в течение года удаляться не должны, только классы
  FOR
      SELECT L9.OBJ_ID, MAX(L9.DATE_MODIFY)
      FROM LINKS L2
      JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
      JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 125, 187) AND L9.DATE_DEL IS NOT NULL AND L9.DATE_DEL > :PERIOD_START
      -- чтобы отловить смену параллелей классов
      LEFT JOIN LINKS LP8 ON LP8.OBJ_ID = L9.OBJ_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND LP8.PARENT_TYPE_ID IS NULL
      GROUP BY 1
      INTO :GROUP_ID, :GROUP_DT
  DO
  BEGIN

      IS_OK = 0;
      IF(
          ((T_FROM IS NULL OR GROUP_DT >= T_FROM) AND GROUP_DT < T_TO)
      )
      THEN
          IS_OK = 1;

      IF(IS_OK = 1) THEN
      BEGIN

          TAG_NAME = 'wsdl&colon;IdentityElementInput';
          VAL = NULL;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;IdentityElementInput:identity:external_id';
          VAL = GROUP_ID;
          SUSPEND;

      END

  END

  -- ГУП - идем по всем этапам и всем УП вне зависимости от их удаления
  FOR
      SELECT L256.OBJ_ID, L256.DATE_MODIFY
      FROM LINKS L2
      JOIN LINKS L69 ON L69.PARENT_ID = L2.OBJ_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL
      JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57
      JOIN LINKS L50 ON L50.PARENT_ID = L57.OBJ_ID AND L50.OBJ_TYPE_ID = 50
      -- Только групповые УП
      JOIN VALL V2101 ON V2101.OBJ_ID = L50.OBJ_ID AND V2101.PARAM_ID = 2101 AND V2101.IS_DEL = 0 AND V2101.LISTVAL_ID = 5465
      JOIN LINKS L54 ON L54.PARENT_ID = L50.OBJ_ID AND L54.OBJ_TYPE_ID = 54
      JOIN LINKS L256 ON L256.PARENT_ID = L54.OBJ_ID AND L256.OBJ_TYPE_ID = 256 AND L256.DATE_DEL IS NOT NULL
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      INTO :GROUP_ID, :GROUP_DT
  DO
  BEGIN

      IS_OK = 0;
      IF(
          ((T_FROM IS NULL OR GROUP_DT >= T_FROM) AND GROUP_DT < T_TO)
      )
      THEN
          IS_OK = 1;

      IF(IS_OK = 1) THEN
      BEGIN

          TAG_NAME = 'wsdl&colon;IdentityElementInput';
          VAL = NULL;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;IdentityElementInput:identity:external_id';
          VAL = GROUP_ID;
          SUSPEND;

      END

  END

  -- Деление на потоки и сами потоки
  FOR
      SELECT L347.OBJ_ID, L347.DATE_MODIFY
      FROM LINKS L2
      JOIN LINKS L69 ON L69.PARENT_ID = L2.OBJ_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL
      JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57
      JOIN LINKS L50 ON L50.PARENT_ID = L57.OBJ_ID AND L50.OBJ_TYPE_ID = 50
      -- Только групповые УП
      JOIN VALL V2101 ON V2101.OBJ_ID = L50.OBJ_ID AND V2101.PARAM_ID = 2101 AND V2101.IS_DEL = 0 AND V2101.LISTVAL_ID = 5465
      JOIN LINKS L54 ON L54.PARENT_ID = L50.OBJ_ID AND L54.OBJ_TYPE_ID = 54
      JOIN LINKS L346 ON L346.PARENT_ID = L54.OBJ_ID AND L346.OBJ_TYPE_ID = 346
      JOIN LINKS L347 ON L347.PARENT_ID = L346.OBJ_ID AND L347.OBJ_TYPE_ID = 347 AND L347.DATE_DEL IS NOT NULL
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      INTO :GROUP_ID, :GROUP_DT
  DO
  BEGIN

      IS_OK = 0;
      IF(
          ((T_FROM IS NULL OR GROUP_DT >= T_FROM) AND GROUP_DT < T_TO)
      )
      THEN
          IS_OK = 1;

      IF(IS_OK = 1) THEN
      BEGIN

          TAG_NAME = 'wsdl&colon;IdentityElementInput';
          VAL = NULL;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;IdentityElementInput:identity:external_id';
          VAL = GROUP_ID;
          SUSPEND;

      END

  END

  -- Новые журналы
  -- !!! TODO

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_PORTAL_INSTITUTION (
    T_FROM TIMESTAMP,
    T_TO TIMESTAMP NOT NULL)
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(2000))
AS
declare variable S_INN varchar(100);
declare variable S_OGRN varchar(100);
declare variable S_KPP varchar(100);
begin

  -- Выбираем ИНН, ОГРН, КПП
  SELECT V33.VAL, V9.VAL, V34.VAL
  FROM LINKS L2
  JOIN VALS V33 ON V33.OBJ_ID = L2.OBJ_ID AND V33.PARAM_ID = 33 AND V33.IS_DEL = 0
  JOIN VALS V9 ON V9.OBJ_ID = L2.OBJ_ID AND V9.PARAM_ID = 9 AND V9.IS_DEL = 0
  JOIN VALS V34 ON V34.OBJ_ID = L2.OBJ_ID AND V34.PARAM_ID = 34 AND V34.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :S_INN, :S_OGRN, :S_KPP;

  IF(S_INN IS NULL) THEN EXCEPTION DATA_ERROR 'Отсутствует обязательная идентификационная информация по ОО (ИНН, ОГРН, КПП)';

  TAG_NAME = 'wsdl&colon;RequestByPropsInput';
  VAL = NULL;
  SUSPEND;

  /*TAG_NAME = 'wsdl&colon;RequestByPropsInput:inn';
  VAL = S_INN;
  SUSPEND;*/

  TAG_NAME = 'wsdl&colon;RequestByPropsInput:ogrn';
  VAL = S_OGRN;
  SUSPEND;

  /*TAG_NAME = 'wsdl&colon;RequestByPropsInput:kpp';
  VAL = S_KPP;
  SUSPEND;*/

  -- Формируем материалы для уроков к зимним каникулам 2022
  EXECUTE PROCEDURE CJ2022_DO2_LINKS;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_PORTAL_JOB (
    T_FROM TIMESTAMP,
    T_TO TIMESTAMP NOT NULL,
    ID1 VARCHAR(40) = NULL,
    ID2 VARCHAR(40) = NULL,
    I$MODE SMALLINT = 0)
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(2000))
AS
DECLARE VARIABLE PERSON_ID BIGINT;
DECLARE VARIABLE PERSON_DT TIMESTAMP;
DECLARE VARIABLE PORTAL_DT TIMESTAMP;
DECLARE VARIABLE IS_OK SMALLINT;
DECLARE VARIABLE JOB_TITLE VARCHAR(1000);
DECLARE VARIABLE JOB_CODE VARCHAR(20);
DECLARE VARIABLE JOB_ORDER INTEGER;
DECLARE VARIABLE MV_DT TIMESTAMP;
DECLARE VARIABLE MD_D1_DT TIMESTAMP;
DECLARE VARIABLE MD_D2_DT TIMESTAMP;
DECLARE VARIABLE JOB_DT TIMESTAMP;
DECLARE VARIABLE DATE_TO DATE;
DECLARE VARIABLE YEAR_START DATE;
DECLARE VARIABLE JOB_DATE DATE;
DECLARE VARIABLE N INTEGER;
begin

  IF(ID2 IS NULL) THEN
  BEGIN
      SELECT FIRST 1 V2911.VAL
      FROM LINKS L2
      JOIN VALS V2911 ON V2911.OBJ_ID = L2.OBJ_ID AND V2911.PARAM_ID = 2911 AND V2911.IS_DEL = 0
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      INTO :ID2;
  END

  IF(EXTRACT(MONTH FROM CURRENT_DATE) < 9) THEN YEAR_START = '01.09.' || (EXTRACT(YEAR FROM CURRENT_DATE) - 1);
  ELSE YEAR_START = '01.09.' || EXTRACT(YEAR FROM CURRENT_DATE);

  N = 0;

  -- Выбираем действующих сотрудников
  FOR
      SELECT L14.OBJ_ID, L14.DATE_MODIFY
      FROM LINKS L2
      JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      INTO :PERSON_ID, :PERSON_DT
  DO
  BEGIN

      -- Момент последних изменений в назначениях и их датах
      MV_DT = NULL;
      MD_D1_DT = NULL;
      MD_D2_DT = NULL;
      SELECT MAX(L15.DATE_MODIFY), MAX(V73.DATE_MODIFY), MAX(V74.DATE_MODIFY)
      FROM LINKS L15
      JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0
      LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
      WHERE L15.PARENT_ID = :PERSON_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
      INTO :MV_DT, :MD_D1_DT, :MD_D2_DT;

      JOB_TITLE = NULL;
      JOB_CODE = NULL;
      JOB_DT = NULL;

      -- Название выдаем для основной должности, а само название берем из должности по штату
      -- Если основной должности нет, тут будет NULL и портал выдаст ошибку
      SELECT FIRST 1 V589.VAL, V589.DATE_MODIFY, FC.CODE
      FROM LINKS L15
      -- Основная должность
      JOIN VALL V72 ON V72.OBJ_ID = L15.OBJ_ID AND V72.PARAM_ID = 72 AND V72.IS_DEL = 0 AND V72.LISTVAL_ID = 934
      JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
      JOIN VALS V589 ON V589.OBJ_ID = LP13.PARENT_ID AND V589.PARAM_ID = 589 AND V589.IS_DEL = 0
      LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
      JOIN VALL V58 ON V58.OBJ_ID = LP13.PARENT_ID AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0
      JOIN LISTVALS LV ON LV.LISTVAL_ID = V58.LISTVAL_ID
      LEFT JOIN VALS V3543 ON V3543.OBJ_ID = L15.OBJ_ID AND V3543.PARAM_ID = 3543 AND V3543.IS_DEL = 0
      LEFT JOIN JOB_FUNCTION_TO_CODE(LV.LISTVAL_ID, V3543.SVAL) FC ON 1 = 1
      WHERE L15.PARENT_ID = :PERSON_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL AND (V74.VAL IS NULL OR V74.VAL > CURRENT_DATE)
      INTO :JOB_TITLE, :JOB_DT, :JOB_CODE;

      IF(JOB_TITLE IS NULL) THEN
      BEGIN
          JOB_TITLE = 'Не задана основная должность';
          JOB_CODE = '10.19';
      END

      IF(JOB_CODE IS NULL OR JOB_CODE = '') THEN JOB_CODE = '10.19';

      -- Формируем код и уровень доступа для самой старшей должности
      SELECT FIRST 1 IIF(LV.TAG = 'R1' OR LV."FILTER" = 'R1', 1, IIF((LV.TAG = 'R2' OR LV."FILTER" = 'R2') AND LV.LISTVAL_ID NOT IN (69, 95, 127, 141, 3300, 11095), 2, 9999))
      FROM LINKS L15
      JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
      LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
      JOIN VALL V58 ON V58.OBJ_ID = LP13.PARENT_ID AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0
      JOIN LISTVALS LV ON LV.LISTVAL_ID = V58.LISTVAL_ID
      WHERE L15.PARENT_ID = :PERSON_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL AND (V74.VAL IS NULL OR V74.VAL > CURRENT_DATE)
      ORDER BY 1
      INTO :JOB_ORDER;

      IF(JOB_ORDER > 2) THEN JOB_ORDER = NULL;

      -- Метка изменения id петеробра или есиа
      PORTAL_DT = NULL;
      SELECT MIN(V267.DATE_MODIFY)
      FROM VALS V267
      WHERE V267.OBJ_ID = :PERSON_ID AND V267.PARAM_ID IN (267, 3061)
      INTO :PORTAL_DT;

      IS_OK = 0;
      IF((JOB_TITLE IS NOT NULL) AND
          ((T_FROM IS NULL OR PERSON_DT >= T_FROM) AND (PERSON_DT < T_TO)) OR
          ((T_FROM IS NULL OR JOB_DT >= T_FROM) AND (JOB_DT < T_TO)) OR
          ((T_FROM IS NULL OR MV_DT >= T_FROM) AND (MV_DT < T_TO)) OR
          ((T_FROM IS NULL OR PORTAL_DT >= T_FROM) AND (PORTAL_DT < T_TO)) OR
          ((T_FROM IS NULL OR MD_D1_DT >= T_FROM) AND (MD_D1_DT < T_TO)) OR
          ((T_FROM IS NULL OR MD_D2_DT >= T_FROM) AND (MD_D2_DT < T_TO))
      )
      THEN
          IS_OK = 1;

      IF(IS_OK = 1) THEN
      BEGIN

          TAG_NAME = 'wsdl&colon;JobInput';
          VAL = NULL;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;JobInput:identity:external_id';
          VAL = PERSON_ID;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;JobInput:position_name';
          VAL = JOB_TITLE;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;JobInput:person_id:external_id';
          VAL = PERSON_ID;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;JobInput:organization_id:id';
          VAL = ID2;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;JobInput:position:code';
          VAL = JOB_CODE;
          -- VAL = JOB_ORDER; старый формат
          SUSPEND;

          -- Выгрузка в новом формате
          TAG_NAME = 'wsdl&colon;JobInput:position_type:code';
          VAL = JOB_ORDER;
          SUSPEND;

          -- Выбираем дату начала работы, дата окончания будет пустая
          JOB_DATE = NULL;

          SELECT MIN(V73.VAL)
          FROM LINKS L15
          JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
          JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0
          WHERE L15.PARENT_ID = :PERSON_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
          INTO :JOB_DATE;

          TAG_NAME = 'wsdl&colon;JobInput:date_from';
          VAL = (SELECT VAL FROM DATE2ISO(:JOB_DATE, 0));
          SUSPEND;

          N = N + 1;
          IF(N >= 10000) THEN
          BEGIN
              N = 0;
              TAG_NAME = NULL;
              VAL = 'DIVIDE';
              SUSPEND;
          END

      END

  END

  -- Выбираем уволенных сотрудников (дата увольнения не более 1 месяца от начала года)
  FOR
      SELECT L14.OBJ_ID, L14.DATE_MODIFY, L14.DATE_INS
      FROM LINKS L2
      JOIN LINKS L84 ON L84.PARENT_ID = L2.OBJ_ID AND L84.OBJ_TYPE_ID = 84 AND L84.DATE_DEL IS NULL
      JOIN LINKS L14 ON L14.PARENT_ID = L84.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL AND L14.DATE_INS > DATEADD(-1 MONTH TO :YEAR_START)
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      INTO :PERSON_ID, :PERSON_DT, :DATE_TO
  DO
  BEGIN

      -- Момент последних изменений в назначениях и их датах
      MV_DT = NULL;
      MD_D1_DT = NULL;
      MD_D2_DT = NULL;
      SELECT MAX(L15.DATE_MODIFY), MAX(V73.DATE_MODIFY), MAX(V74.DATE_MODIFY)
      FROM LINKS L15
      JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0
      LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
      WHERE L15.PARENT_ID = :PERSON_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
      INTO :MV_DT, :MD_D1_DT, :MD_D2_DT;

      JOB_TITLE = NULL;
      JOB_CODE = NULL;
      JOB_DT = NULL;

      -- Название выдаем для основной должности, а само название берем из должности по штату
      SELECT FIRST 1 V589.VAL, V589.DATE_MODIFY, FC.CODE
      FROM LINKS L15
      -- Основная должность
      JOIN VALL V72 ON V72.OBJ_ID = L15.OBJ_ID AND V72.PARAM_ID = 72 AND V72.IS_DEL = 0 AND V72.LISTVAL_ID = 934
      JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
      JOIN VALS V589 ON V589.OBJ_ID = LP13.PARENT_ID AND V589.PARAM_ID = 589 AND V589.IS_DEL = 0
      JOIN VALL V58 ON V58.OBJ_ID = LP13.PARENT_ID AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0
      JOIN LISTVALS LV ON LV.LISTVAL_ID = V58.LISTVAL_ID
      LEFT JOIN VALS V3543 ON V3543.OBJ_ID = L15.OBJ_ID AND V3543.PARAM_ID = 3543 AND V3543.IS_DEL = 0
      LEFT JOIN JOB_FUNCTION_TO_CODE(LV.LISTVAL_ID, V3543.SVAL) FC ON 1 = 1
      WHERE L15.PARENT_ID = :PERSON_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
      INTO :JOB_TITLE, :JOB_DT, :JOB_CODE;

      IF(JOB_TITLE IS NULL) THEN
      BEGIN
          JOB_TITLE = 'Не задана основная должность';
          JOB_CODE = '10.19';
      END

      IF(JOB_CODE IS NULL OR JOB_CODE = '') THEN JOB_CODE = '10.19';

      -- Формируем признак для директора и замдиректора
      SELECT FIRST 1 IIF(LV.TAG = 'R1' OR LV."FILTER" = 'R1', 1, IIF((LV.TAG = 'R2' OR LV."FILTER" = 'R2') AND LV.LISTVAL_ID NOT IN (69, 95, 127, 141, 3300, 11095), 2, 9999))
      FROM LINKS L15
      JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
      JOIN VALL V58 ON V58.OBJ_ID = LP13.PARENT_ID AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0
      JOIN LISTVALS LV ON LV.LISTVAL_ID = V58.LISTVAL_ID
      WHERE L15.PARENT_ID = :PERSON_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
      ORDER BY 1
      INTO :JOB_ORDER;

      IF(JOB_ORDER > 2) THEN JOB_ORDER = NULL;

      -- Метка изменения id петеробра или есиа
      PORTAL_DT = NULL;
      SELECT MIN(V267.DATE_MODIFY)
      FROM VALS V267
      WHERE V267.OBJ_ID = :PERSON_ID AND V267.PARAM_ID IN (267, 3061)
      INTO :PORTAL_DT;

      IS_OK = 0;
      IF((JOB_TITLE IS NOT NULL) AND
          ((T_FROM IS NULL OR PERSON_DT >= T_FROM) AND (PERSON_DT < T_TO)) OR
          ((T_FROM IS NULL OR JOB_DT >= T_FROM) AND (JOB_DT < T_TO)) OR
          ((T_FROM IS NULL OR MV_DT >= T_FROM) AND (MV_DT < T_TO)) OR
          ((T_FROM IS NULL OR PORTAL_DT >= T_FROM) AND (PORTAL_DT < T_TO)) OR
          ((T_FROM IS NULL OR MD_D1_DT >= T_FROM) AND (MD_D1_DT < T_TO)) OR
          ((T_FROM IS NULL OR MD_D2_DT >= T_FROM) AND (MD_D2_DT < T_TO))
      )
      THEN
          IS_OK = 1;

      IF(IS_OK = 1) THEN
      BEGIN

          TAG_NAME = 'wsdl&colon;JobInput';
          VAL = NULL;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;JobInput:identity:external_id';
          VAL = PERSON_ID;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;JobInput:position_name';
          VAL = JOB_TITLE;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;JobInput:person_id:external_id';
          VAL = PERSON_ID;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;JobInput:organization_id:id';
          VAL = ID2;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;JobInput:position:code';
          VAL = JOB_CODE;
          -- VAL = JOB_ORDER; старый формат
          SUSPEND;

          -- Выгрузка в новом формате
          TAG_NAME = 'wsdl&colon;JobInput:position_type:code';
          VAL = JOB_ORDER;
          SUSPEND;

          -- Выбираем дату начала работы
          JOB_DATE = NULL;

          SELECT MIN(V73.VAL)
          FROM LINKS L15
          JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
          JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0
          WHERE L15.PARENT_ID = :PERSON_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
          INTO :JOB_DATE;

          TAG_NAME = 'wsdl&colon;JobInput:date_from';
          VAL = (SELECT VAL FROM DATE2ISO(:JOB_DATE, 0));
          SUSPEND;

          -- Выбираем дату окончания работы
          JOB_DATE = NULL;

          SELECT MAX(V74.VAL)
          FROM LINKS L15
          JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
          JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
          WHERE L15.PARENT_ID = :PERSON_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
          INTO :JOB_DATE;

          TAG_NAME = 'wsdl&colon;JobInput:date_to';
          VAL = (SELECT VAL FROM DATE2ISO(:JOB_DATE, 0));
          SUSPEND;

          N = N + 1;
          IF(N >= 10000) THEN
          BEGIN
              N = 0;
              TAG_NAME = NULL;
              VAL = 'DIVIDE';
              SUSPEND;
          END

      END

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_PORTAL_JOB_DELETE (
    T_FROM TIMESTAMP,
    T_TO TIMESTAMP NOT NULL,
    ID1 VARCHAR(40) = null,
    ID2 VARCHAR(40) = null,
    I$MODE SMALLINT = 0)
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(2000))
AS
begin
  IF(T_FROM IS NULL) THEN EXIT;
  IF(0 = 1) THEN SUSPEND;
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_PORTAL_LESSONS (
    T_FROM TIMESTAMP,
    T_TO TIMESTAMP NOT NULL,
    ID1 VARCHAR(40) = null,
    ID2 VARCHAR(40) = null,
    I$MODE SMALLINT = 0)
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(2000))
AS
declare variable LESSON_ID bigint;
declare variable SUBJECT_ID bigint;
declare variable GROUP_ID bigint;
declare variable PERIOD_ID bigint;
declare variable N integer;
begin

  -- Отключено, выгрузка идет через meetings

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_PORTAL_LESSONS_DELETE (
    T_FROM TIMESTAMP,
    T_TO TIMESTAMP NOT NULL = current_timestamp,
    ID1 VARCHAR(40) = null,
    ID2 VARCHAR(40) = null,
    I$MODE SMALLINT = 0)
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(2000))
AS
declare variable YEAR_ID bigint;
declare variable IS_OK smallint;
declare variable LESSON_ID bigint;
declare variable LESSON_DT timestamp;
declare variable N integer;
begin

  IF(T_FROM IS NULL) THEN EXIT;

  SELECT FIRST 1 V1236.LISTVAL_ID
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :YEAR_ID;

  N = 0;

  -- Реально удаленные уроки
  FOR
      SELECT L.OBJ_ID, L.DATE_DEL
      FROM CJ2_JOURNAL J
      JOIN CJ2_JOURNAL_LESSONS L ON L.CJ_ID = J.OBJ_ID AND L.DATE_DEL IS NOT NULL
      JOIN LINKS L179 ON L179.OBJ_ID = J.GRADE_ID AND L179.OBJ_TYPE_ID = 179 AND L179.PARENT_TYPE_ID = 2 AND L179.DATE_DEL IS NULL
      -- Признак группы ЦОПП
      LEFT JOIN VALL V3064 ON V3064.OBJ_ID = L179.OBJ_ID AND V3064.PARAM_ID = 3064 AND V3064.IS_DEL = 0
      WHERE J.DATE_DEL IS NOT NULL AND J.JOURNAL_TYPE IN (0, 1) AND J.YEAR_ID = :YEAR_ID
          AND ((:I$MODE = 0 AND (V3064.LISTVAL_ID IS NULL OR V3064.LISTVAL_ID = 3)) OR (:I$MODE = 1 AND V3064.LISTVAL_ID = 2))
      INTO :LESSON_ID, :LESSON_DT
  DO
  BEGIN

      IS_OK = 0;
      IF(
          ((T_FROM IS NULL OR LESSON_DT >= T_FROM) AND LESSON_DT < T_TO)
      )
      THEN
          IS_OK = 1;

      IF(IS_OK = 1) THEN
      BEGIN

          TAG_NAME = 'wsdl&colon;IdentityElementInput';
          VAL = NULL;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;IdentityElementInput:identity:external_id';
          VAL = LESSON_ID;
          SUSPEND;

          N = N + 1;
          IF(N >= 10000) THEN
          BEGIN
              N = 0;
              TAG_NAME = NULL;
              VAL = 'DIVIDE';
              SUSPEND;
          END

      END

  END

  -- Уроки, где снят флаг проведения
  -- ...

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_PORTAL_LESSON_FILES (
    T_FROM TIMESTAMP,
    T_TO TIMESTAMP,
    I$MODE SMALLINT = 0)
RETURNS (
    LESSON_ID BIGINT,
    BLOB_ID BIGINT,
    FILE_NAME VARCHAR(4000),
    FILE_TYPE SMALLINT)
AS
declare variable YEAR_ID bigint;
begin

  SELECT FIRST 1 V1236.LISTVAL_ID
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :YEAR_ID;

  FOR
      SELECT B.LESSON_ID, B.OBJ_ID, B.FILE_NAME, B.FILE_TYPE
      FROM CJ2_JOURNAL J
      JOIN CJ2_JOURNAL_LESSONS L ON L.CJ_ID = J.OBJ_ID AND L.DATE_DEL IS NULL
      JOIN CJ2_BLOB B ON B.LESSON_ID = L.OBJ_ID AND B.DATE_DEL IS NULL
      JOIN LINKS L179 ON L179.OBJ_ID = J.GRADE_ID AND L179.OBJ_TYPE_ID = 179 AND L179.PARENT_TYPE_ID = 2 AND L179.DATE_DEL IS NULL
      -- Признак группы ЦОПП
      LEFT JOIN VALL V3064 ON V3064.OBJ_ID = L179.OBJ_ID AND V3064.PARAM_ID = 3064 AND V3064.IS_DEL = 0
      WHERE J.DATE_DEL IS NULL AND J.JOURNAL_TYPE IN (0/*, 1*/) AND J.YEAR_ID = :YEAR_ID
          AND (L.IS_COMPLETED = 1 OR L.IS_PUBLISHED = 1) AND ((:T_FROM IS NULL OR L.DATE_MODIFY >= :T_FROM) AND L.DATE_MODIFY < :T_TO) --AND GS.PLAN_TYPE_ID IN (5465, 5466)
          AND ((:I$MODE = 0 AND (V3064.LISTVAL_ID IS NULL OR V3064.LISTVAL_ID = 3)) OR (:I$MODE = 1 AND V3064.LISTVAL_ID = 2))
      ORDER BY 1
      INTO :LESSON_ID, :BLOB_ID, :FILE_NAME, :FILE_TYPE
  DO
  BEGIN
      SUSPEND;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_PORTAL_LESSON_FILES_DELETE (
    T_FROM TIMESTAMP,
    T_TO TIMESTAMP,
    I$MODE SMALLINT = 0)
RETURNS (
    BLOB_ID BIGINT)
AS
begin

  -- Материалы удаляем только фактические. Удаленные уроки, удаленные журналы - удаляются вышестоящие сущности

  FOR
      SELECT B.OBJ_ID
      FROM CJ2_BLOB B
      WHERE (:T_FROM IS NULL OR B.DATE_DEL >= :T_FROM) AND B.DATE_DEL <= :T_TO
      ORDER BY 1
      INTO :BLOB_ID
  DO
  BEGIN
      SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_PORTAL_MEETINGS (
    T_FROM TIMESTAMP,
    T_TO TIMESTAMP NOT NULL = CURRENT_TIMESTAMP,
    ID1 VARCHAR(40) = NULL,
    ID2 VARCHAR(40) = NULL,
    I$MODE SMALLINT = 0)
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(2000))
AS
DECLARE VARIABLE YEAR_ID BIGINT;
DECLARE VARIABLE LESSON_ID BIGINT;
DECLARE VARIABLE LESSON_DATE DATE;
DECLARE VARIABLE LESSON_NUMBER INTEGER;
DECLARE VARIABLE LESSON_THEME VARCHAR(1000);
DECLARE VARIABLE PLACE VARCHAR(1000);
DECLARE VARIABLE GROUP_ID BIGINT;
DECLARE VARIABLE PERIOD_ID BIGINT;
DECLARE VARIABLE MODULE_ID BIGINT;
DECLARE VARIABLE SUBJECT_ID BIGINT;
DECLARE VARIABLE V$CJ_ID BIGINT;
DECLARE VARIABLE V$WEEKDAY INTEGER;
DECLARE VARIABLE V$T1 TIME;
DECLARE VARIABLE V$T2 TIME;
DECLARE VARIABLE S VARCHAR(30);
DECLARE VARIABLE N INTEGER;
DECLARE VARIABLE V$PLAN_ID BIGINT;
DECLARE VARIABLE V$PERIOD_TYPE BIGINT;
DECLARE VARIABLE V$DT TIMESTAMP;
DECLARE VARIABLE V$DUR INTEGER;
DECLARE VARIABLE V$JT SMALLINT;
begin

  IF(ID1 IS NULL) THEN
  BEGIN
    SELECT FIRST 1 V2910.VAL
    FROM LINKS L2
    JOIN VALS V2910 ON V2910.OBJ_ID = L2.OBJ_ID AND V2910.PARAM_ID = 2910 AND V2910.IS_DEL = 0
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :ID1;
  END

  SELECT FIRST 1 V1236.LISTVAL_ID
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :YEAR_ID;

  N = 0;

  -- Новый формат журнала
  FOR
      SELECT L.OBJ_ID, L.LESSON_THEME, L.LESSON_DATE, L.LESSON_NUM, J.GRADE_ID, J.SUBJECT_ID, L.CJ_ID, J.REF_ID, J.PERIOD_ID, J.JOURNAL_TYPE, IIF(RO.TYPE_ID = 2, 'Вне ОООД', RC.CAPTION)
      FROM CJ2_JOURNAL J
      JOIN CJ2_JOURNAL_LESSONS L ON L.CJ_ID = J.OBJ_ID AND L.DATE_DEL IS NULL
      JOIN LINKS L179 ON L179.OBJ_ID = J.GRADE_ID AND L179.OBJ_TYPE_ID = 179 AND L179.PARENT_TYPE_ID = 2 AND L179.DATE_DEL IS NULL
      -- Признак группы ЦОПП
      LEFT JOIN VALL V3064 ON V3064.OBJ_ID = L179.OBJ_ID AND V3064.PARAM_ID = 3064 AND V3064.IS_DEL = 0
      LEFT JOIN OBJECTS RO ON RO.OBJ_ID = J.ROOM_ID AND J.ROOM_ID IS NOT NULL
      LEFT JOIN OBJECT_CAPTION_GET(J.ROOM_ID) RC ON J.ROOM_ID IS NOT NULL AND J.JOURNAL_TYPE = 1
      WHERE J.DATE_DEL IS NULL AND J.JOURNAL_TYPE IN (0 /*, 1 */) AND J.YEAR_ID = :YEAR_ID
          AND (L.IS_COMPLETED = 1 OR L.IS_PUBLISHED = 1) AND ((:T_FROM IS NULL OR L.DATE_MODIFY >= :T_FROM) AND L.DATE_MODIFY < :T_TO) --AND GS.PLAN_TYPE_ID IN (5465, 5466)
          AND ((:I$MODE = 0 AND (V3064.LISTVAL_ID IS NULL OR V3064.LISTVAL_ID = 3)) OR (:I$MODE = 1 AND V3064.LISTVAL_ID = 2))
      ORDER BY L.LESSON_DATE, L.CJ_ID
      INTO :LESSON_ID, :LESSON_THEME, :LESSON_DATE, :LESSON_NUMBER, :GROUP_ID, :SUBJECT_ID, :V$CJ_ID, :V$PLAN_ID, :PERIOD_ID, :V$JT, :PLACE
  DO
  BEGIN

      TAG_NAME = 'wsdl&colon;MeetingLessonInput';
      VAL = NULL;
      SUSPEND;

      TAG_NAME = 'wsdl&colon;MeetingLessonInput:meeting';
      VAL = NULL;
      SUSPEND;

      TAG_NAME = 'wsdl&colon;MeetingLessonInput:meeting:identity:external_id';
      VAL = LESSON_ID;
      SUSPEND;

      TAG_NAME = 'wsdl&colon;MeetingLessonInput:meeting:content_id:external_id';
      VAL = LESSON_ID;
      SUSPEND;

      TAG_NAME = 'wsdl&colon;MeetingLessonInput:meeting:institution_id:id';
      VAL = ID1;
      SUSPEND;

      TAG_NAME = 'wsdl&colon;MeetingLessonInput:meeting:name';
      VAL = LESSON_THEME;
      SUSPEND;

      TAG_NAME = 'wsdl&colon;MeetingLessonInput:meeting:number';
      VAL = LESSON_NUMBER;
      SUSPEND;

      -- Время урока
      V$T1 = NULL;
      V$T2 = NULL;
      V$WEEKDAY = EXTRACT(WEEKDAY FROM LESSON_DATE);
      IF(V$WEEKDAY = 0) THEN V$WEEKDAY = 6; ELSE V$WEEKDAY = V$WEEKDAY - 1;
      -- Недельную выписку смотреть бесполезно, сразу смотрим типовой шаблон
      -- попадающий по датам в интересующий нас период
      SELECT FIRST 1 V405.VAL, V406.VAL
      FROM SCHEDULE_ITEMS SI
      -- Шаблон расписания, чтобы исключить выписки, назначенный для выгрузки
      JOIN LINKS LP3 ON LP3.OBJ_ID = SI.SCHEDULE_ID AND LP3.PARENT_TYPE_ID = 3 AND LP3.DATE_DEL IS NULL
      JOIN VALL V1341 ON V1341.OBJ_ID = SI.SCHEDULE_ID AND V1341.PARAM_ID = 1341 AND V1341.IS_DEL = 0 AND V1341.LISTVAL_ID = 2
      JOIN VALL V37 ON V37.OBJ_ID = LP3.PARENT_ID AND V37.PARAM_ID = 37 AND V37.IS_DEL = 0 AND V37.LISTVAL_ID = :YEAR_ID
      LEFT JOIN VALD V3120 ON V3120.OBJ_ID = LP3.OBJ_ID AND V3120.PARAM_ID = 3120 AND V3120.IS_DEL = 0
      LEFT JOIN VALD V3121 ON V3121.OBJ_ID = LP3.OBJ_ID AND V3121.PARAM_ID = 3121 AND V3121.IS_DEL = 0
      -- День недели и номер урока у нас уже есть
      -- Время начала и окончания
      JOIN LINKS L60 ON L60.PARENT_ID = SI.SCHEDULE_ID AND L60.OBJ_TYPE_ID = 60 AND L60.DATE_DEL IS NULL
      JOIN VALI V404 ON V404.OBJ_ID = L60.OBJ_ID AND V404.PARAM_ID = 404 AND V404.IS_DEL = 0 AND V404.VAL = SI.LESSON_NUM
      JOIN VALT V405 ON V405.OBJ_ID = L60.OBJ_ID AND V405.PARAM_ID = 405 AND V405.IS_DEL = 0
      JOIN VALT V406 ON V406.OBJ_ID = L60.OBJ_ID AND V406.PARAM_ID = 406 AND V406.IS_DEL = 0
      WHERE SI.DATE_DEL IS NULL AND SI.CJ_ID = :V$CJ_ID AND SI.WEEKDAY_NUM = :V$WEEKDAY AND SI.LESSON_NUM = :LESSON_NUMBER
        AND (V3120.VAL IS NULL OR V3120.VAL <= :LESSON_DATE) AND (V3121.VAL IS NULL OR V3121.VAL >= :LESSON_DATE)
      INTO :V$T1, :V$T2;

      IF(V$T1 IS NULL) THEN
      BEGIN
        -- Не давать переполняться времени
        IF(LESSON_NUMBER < 1) THEN LESSON_NUMBER = 1;
        IF(LESSON_NUMBER > 15) THEN LESSON_NUMBER = 15;
        V$T1 = (LESSON_NUMBER + 8) || ':00';
        V$T2 = (LESSON_NUMBER + 8) || ':45';
      END

      TAG_NAME = 'wsdl&colon;MeetingLessonInput:meeting:datetime_from';
      S = LESSON_DATE || ' ' || V$T1;
      VAL = (SELECT VAL FROM DATE2ISO(:S));
      SUSPEND;

      TAG_NAME = 'wsdl&colon;MeetingLessonInput:meeting:datetime_to';
      S = LESSON_DATE || ' ' || V$T2;
      VAL = (SELECT VAL FROM DATE2ISO(:S));
      SUSPEND;

      IF(V$JT = 1) THEN
      BEGIN
        TAG_NAME = 'wsdl&colon;MeetingLessonInput:meeting:cabinet';
        VAL = PLACE;
        IF(VAL IS NULL) THEN VAL = 'По расписанию';
        SUSPEND;
      END

      -- Вторая часть - урок

      TAG_NAME = 'wsdl&colon;MeetingLessonInput:lesson';
      VAL = NULL;
      SUSPEND;

      TAG_NAME = 'wsdl&colon;MeetingLessonInput:lesson:identity:external_id';
      VAL = LESSON_ID;
      SUSPEND;

      TAG_NAME = 'wsdl&colon;MeetingLessonInput:lesson:meeting_id:external_id';
      VAL = LESSON_ID;
      SUSPEND;

      TAG_NAME = 'wsdl&colon;MeetingLessonInput:lesson:content_id:external_id';
      VAL = LESSON_ID;
      SUSPEND;

      TAG_NAME = 'wsdl&colon;MeetingLessonInput:lesson:subject_id:external_id';
      VAL = SUBJECT_ID;
      SUSPEND;

      -- Только для ЦОПП, в остальных случаях период у нас уже есть
      IF(I$MODE = 1) THEN
      BEGIN
        PERIOD_ID = NULL;

        -- Упаси бог тут будут переходы между группами
        SELECT FIRST 1 LP9.PARENT_ID
        FROM LINKS L10
        JOIN LINKS LP9 ON LP9.OBJ_ID = L10.OBJ_ID AND LP9.PARENT_TYPE_ID = 9
        JOIN LINKS LP8 ON LP8.OBJ_ID = LP9.PARENT_ID AND LP8.PARENT_TYPE_ID = 8
        WHERE L10.PARENT_ID = :GROUP_ID AND L10.OBJ_TYPE_ID = 10
        ORDER BY LP9.DATE_INS DESC, LP8.DATE_INS DESC
        INTO :PERIOD_ID;
      END

      /*TAG_NAME = 'wsdl&colon;MeetingLessonInput:lesson:period_id:g_id';
      VAL = GROUP_ID;
      SUSPEND;*/

      TAG_NAME = 'wsdl&colon;MeetingLessonInput:lesson:period_id:external_id';
      VAL = PERIOD_ID;
      SUSPEND;

      N = N + 1;
      IF(N >= 10000) THEN
      BEGIN
        N = 0;
        TAG_NAME = NULL;
        VAL = 'DIVIDE';
        SUSPEND;
      END

  END

  -- Воспитательная работа
  FOR
      SELECT L.OBJ_ID, M.OBJ_ID, L.LESSON_THEME, L.LESSON_DATE, CAST(L.LESSON_EXTRA AS TIME), L.LESSON_HOURS * 60,
          MAXVALUE(V3373.DATE_MODIFY, L.DATE_MODIFY, M.DATE_MODIFY), L.LESSON_HOMEWORK
      FROM CJ2_JOURNAL J
      JOIN VALL V3373 ON V3373.OBJ_ID = J.REF_ID AND V3373.PARAM_ID = 3373 AND V3373.IS_DEL = 0 AND V3373.LISTVAL_ID = 11715
      JOIN CJ2_JOURNAL_LESSONS L ON L.DATE_DEL IS NULL AND L.CJ_ID = J.OBJ_ID AND L.IS_ONLINE = 1 AND L.LESSON_DATE > '01.01.2000'
        AND L.LESSON_EXTRA <> '' AND (L.IS_PUBLISHED = 1 OR L.IS_COMPLETED = 1)
      LEFT JOIN CJ2_LESSON_ATTRS A ON A.DATE_DEL IS NULL AND A.LESSON_ID = L.OBJ_ID AND A.ATTR_NAME = 'date_to'
      LEFT JOIN VOSP_MEMBERS_LIST(L.OBJ_ID) M ON 1 = 1
      WHERE J.DATE_DEL IS NULL AND J.JOURNAL_TYPE = 20 AND J.YEAR_ID = :YEAR_ID
          AND (A.ATTR_VALUE IS NULL OR A.ATTR_VALUE = '')
      INTO :LESSON_ID, :GROUP_ID, :LESSON_THEME, :LESSON_DATE, :V$T1, :V$DUR, :V$DT, :PLACE
  DO
  BEGIN

      IF(T_FROM IS NULL OR V$DT >= T_FROM) THEN
      BEGIN

          V$T2 = DATEADD(V$DUR MINUTE TO V$T1);
          PERIOD_ID = NULL;

          SELECT FIRST 1 J.PERIOD_ID
          FROM LINKS L10
          JOIN LINKS LPG ON LPG.OBJ_ID = L10.OBJ_ID AND LPG.PARENT_TYPE_ID = 179 AND LPG.DATE_DEL IS NULL
          JOIN CJ2_JOURNAL J ON J.GRADE_ID = LPG.PARENT_ID AND J.DATE_DEL IS NULL AND J.JOURNAL_TYPE = 0
          LEFT JOIN VALS V376 ON V376.OBJ_ID = J.SUBJECT_ID AND V376.PARAM_ID = 376 AND V376.IS_DEL = 0
          WHERE L10.PARENT_ID = :GROUP_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL AND (V376.SVAL IS NULL OR POSITION('@' IN V376.SVAL) <= 0)
          ORDER BY LPG.DATE_INS DESC
          INTO :PERIOD_ID;

          -- Если период не нашелся, возвращаем первый попавшийся учебный период
          IF(PERIOD_ID IS NULL) THEN
          BEGIN
            SELECT FIRST 1 L151.OBJ_ID
            FROM LINKS L150
            JOIN LINKS L151 ON L151.PARENT_ID = L150.OBJ_ID AND L151.OBJ_TYPE_ID = 151 AND L151.DATE_DEL IS NULL
            WHERE L150.PARENT_TYPE_ID = 2 AND L150.OBJ_TYPE_ID IN (150, 481) AND L150.DATE_DEL IS NULL
            ORDER BY L151.DATE_MODIFY
            INTO :PERIOD_ID;
          END

          TAG_NAME = 'wsdl&colon;MeetingLessonInput';
          VAL = NULL;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;MeetingLessonInput:meeting';
          VAL = NULL;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;MeetingLessonInput:meeting:identity:external_id';
          VAL = 'V' || LESSON_ID || '+' || GROUP_ID;
          SUSPEND;

          /*TAG_NAME = 'wsdl&colon;MeetingLessonInput:meeting:content_id:external_id';
          VAL = 'V' || LESSON_ID || '+' || GROUP_ID;
          SUSPEND;*/

          TAG_NAME = 'wsdl&colon;MeetingLessonInput:meeting:institution_id:id';
          VAL = ID1;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;MeetingLessonInput:meeting:name';
          VAL = LESSON_THEME;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;MeetingLessonInput:meeting:number';
          VAL = LESSON_NUMBER;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;MeetingLessonInput:meeting:datetime_from';
          S = LESSON_DATE || ' ' || V$T1;
          VAL = (SELECT VAL FROM DATE2ISO(:S));
          SUSPEND;

          TAG_NAME = 'wsdl&colon;MeetingLessonInput:meeting:datetime_to';
          S = LESSON_DATE || ' ' || V$T2;
          VAL = (SELECT VAL FROM DATE2ISO(:S));
          SUSPEND;

          TAG_NAME = 'wsdl&colon;MeetingLessonInput:meeting:cabinet';
          VAL = PLACE;
          SUSPEND;

          -- Вторая часть - урок

          TAG_NAME = 'wsdl&colon;MeetingLessonInput:lesson';
          VAL = NULL;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;MeetingLessonInput:lesson:identity:external_id';
          VAL = 'V' || LESSON_ID || '+' || GROUP_ID;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;MeetingLessonInput:lesson:meeting_id:external_id';
          VAL = 'V' || LESSON_ID || '+' || GROUP_ID;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;MeetingLessonInput:lesson:content_id:external_id';
          VAL = 'V' || LESSON_ID || '+' || GROUP_ID;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;MeetingLessonInput:lesson:subject_id:external_id';
          VAL = 'event';
          SUSPEND;

          TAG_NAME = 'wsdl&colon;MeetingLessonInput:lesson:period_id:external_id';
          VAL = PERIOD_ID;
          SUSPEND;

          N = N + 1;
          IF(N >= 10000) THEN
          BEGIN
            N = 0;
            TAG_NAME = NULL;
            VAL = 'DIVIDE';
            SUSPEND;
          END

      END

  END

  WHEN SQLCODE -811 DO EXCEPTION DATA_ERROR 'Дубликат расписания для ' || GROUP_ID || ', предмет ' || SUBJECT_ID || ', день недели ' ||
      V$WEEKDAY || ', урок ' || LESSON_NUMBER;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_PORTAL_MEETINGS_DELETE (
    T_FROM TIMESTAMP,
    T_TO TIMESTAMP NOT NULL = CURRENT_TIMESTAMP,
    ID1 VARCHAR(40) = NULL,
    ID2 VARCHAR(40) = NULL,
    I$MODE SMALLINT = 0)
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(2000))
AS
DECLARE VARIABLE YEAR_ID BIGINT;
DECLARE VARIABLE LESSON_ID BIGINT;
DECLARE VARIABLE LESSON_DT TIMESTAMP;
DECLARE VARIABLE IS_OK SMALLINT;
DECLARE VARIABLE N INTEGER;
begin

  IF(T_FROM IS NULL) THEN EXIT;

  SELECT FIRST 1 V1236.LISTVAL_ID
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :YEAR_ID;

  N = 0;

  -- Реально удаленные уроки
  FOR
      SELECT L.OBJ_ID, L.DATE_DEL
      FROM CJ2_JOURNAL J
      JOIN CJ2_JOURNAL_LESSONS L ON L.CJ_ID = J.OBJ_ID AND L.DATE_DEL IS NOT NULL
      JOIN LINKS L179 ON L179.OBJ_ID = J.GRADE_ID AND L179.OBJ_TYPE_ID = 179 AND L179.PARENT_TYPE_ID = 2 AND L179.DATE_DEL IS NULL
      -- Признак группы ЦОПП
      LEFT JOIN VALL V3064 ON V3064.OBJ_ID = L179.OBJ_ID AND V3064.PARAM_ID = 3064 AND V3064.IS_DEL = 0
      WHERE J.DATE_DEL IS NOT NULL AND J.JOURNAL_TYPE IN (0, 1) AND J.YEAR_ID = :YEAR_ID
          AND ((:I$MODE = 0 AND (V3064.LISTVAL_ID IS NULL OR V3064.LISTVAL_ID = 3)) OR (:I$MODE = 1 AND V3064.LISTVAL_ID = 2))
      INTO :LESSON_ID, :LESSON_DT
  DO
  BEGIN

      IS_OK = 0;
      IF(
          ((T_FROM IS NULL OR LESSON_DT >= T_FROM) AND LESSON_DT < T_TO)
      )
      THEN
          IS_OK = 1;

      IF(IS_OK = 1) THEN
      BEGIN

          TAG_NAME = 'wsdl&colon;IdentityElementInput';
          VAL = NULL;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;IdentityElementInput:identity:external_id';
          VAL = LESSON_ID;
          SUSPEND;

          N = N + 1;
          IF(N >= 10000) THEN
          BEGIN
              N = 0;
              TAG_NAME = NULL;
              VAL = 'DIVIDE';
              SUSPEND;
          END

      END

  END

  -- Уроки, где снят флаг проведения
  -- ...

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_PORTAL_MEETING_MEMBERS (
    T_FROM TIMESTAMP,
    T_TO TIMESTAMP NOT NULL = current_timestamp,
    ID1 VARCHAR(40) = null,
    ID2 VARCHAR(40) = null,
    I$MODE SMALLINT = 0)
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(2000))
AS
declare variable YEAR_ID bigint;
declare variable LESSON_ID bigint;
declare variable GROUP_ID bigint;
declare variable TEACHER_ID bigint;
declare variable N integer;
declare variable V$DT timestamp;
begin

  IF(ID1 IS NULL) THEN
  BEGIN
      SELECT FIRST 1 V2910.VAL
      FROM LINKS L2
      JOIN VALS V2910 ON V2910.OBJ_ID = L2.OBJ_ID AND V2910.PARAM_ID = 2910 AND V2910.IS_DEL = 0
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      INTO :ID1;
  END

  SELECT FIRST 1 V1236.LISTVAL_ID
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :YEAR_ID;

  N = 0;

  -- Выгружаем уроки как мероприятия, только из числа проведенных
  FOR
      SELECT L.OBJ_ID, J.GRADE_ID, L.TEACHER_ID
      FROM CJ2_JOURNAL J
      JOIN CJ2_JOURNAL_LESSONS L ON L.CJ_ID = J.OBJ_ID AND L.DATE_DEL IS NULL
      JOIN LINKS L179 ON L179.OBJ_ID = J.GRADE_ID AND L179.OBJ_TYPE_ID = 179 AND L179.PARENT_TYPE_ID = 2 AND L179.DATE_DEL IS NULL
      -- Признак группы ЦОПП
      LEFT JOIN VALL V3064 ON V3064.OBJ_ID = L179.OBJ_ID AND V3064.PARAM_ID = 3064 AND V3064.IS_DEL = 0
      WHERE J.DATE_DEL IS NULL AND J.JOURNAL_TYPE IN (0/*, 1*/) AND J.YEAR_ID = :YEAR_ID
          AND (L.IS_COMPLETED = 1 OR L.IS_PUBLISHED = 1) AND ((:T_FROM IS NULL OR L.DATE_MODIFY >= :T_FROM) AND L.DATE_MODIFY < :T_TO) --AND GS.PLAN_TYPE_ID IN (5465, 5466)
          AND ((:I$MODE = 0 AND (V3064.LISTVAL_ID IS NULL OR V3064.LISTVAL_ID = 3)) OR (:I$MODE = 1 AND V3064.LISTVAL_ID = 2))
      ORDER BY L.LESSON_DATE, L.CJ_ID
      INTO :LESSON_ID, :GROUP_ID, :TEACHER_ID
  DO
  BEGIN

      TAG_NAME = 'wsdl&colon;MeetingMemberInput';
      VAL = NULL;
      SUSPEND;

      TAG_NAME = 'wsdl&colon;MeetingMemberInput:identity:external_id';
      VAL = LESSON_ID;
      SUSPEND;

      TAG_NAME = 'wsdl&colon;MeetingMemberInput:meeting_id:external_id';
      VAL = LESSON_ID;
      SUSPEND;

      TAG_NAME = 'wsdl&colon;MeetingMemberInput:teacher_id:external_id';
      VAL = TEACHER_ID;
      SUSPEND;

      TAG_NAME = 'wsdl&colon;MeetingMemberInput:group_id:external_id';
      VAL = GROUP_ID;
      SUSPEND;

      TAG_NAME = 'wsdl&colon;MeetingMemberInput:institution_id:id';
      VAL = ID1;
      SUSPEND;

      N = N + 1;
      IF(N >= 10000) THEN
      BEGIN
          N = 0;
          TAG_NAME = NULL;
          VAL = 'DIVIDE';
          SUSPEND;
      END

  END

  -- Воспитательная работа
  FOR
      SELECT L.OBJ_ID, M.OBJ_ID, V53.VAL, MAXVALUE(V3373.DATE_MODIFY, L.DATE_MODIFY, M.DATE_MODIFY)
      FROM CJ2_JOURNAL J
      JOIN VALL V3373 ON V3373.OBJ_ID = J.REF_ID AND V3373.PARAM_ID = 3373 AND V3373.IS_DEL = 0 AND V3373.LISTVAL_ID = 11715
      JOIN CJ2_JOURNAL_LESSONS L ON L.DATE_DEL IS NULL AND L.CJ_ID = J.OBJ_ID AND L.IS_ONLINE = 1 AND L.LESSON_DATE > '01.01.2000'
          AND L.LESSON_EXTRA <> '' AND (L.IS_PUBLISHED = 1 OR L.IS_COMPLETED = 1)
      LEFT JOIN CJ2_LESSON_ATTRS A ON A.DATE_DEL IS NULL AND A.LESSON_ID = L.OBJ_ID AND A.ATTR_NAME = 'date_to'
      LEFT JOIN VOSP_MEMBERS_LIST(L.OBJ_ID) M ON 1 = 1
      LEFT JOIN VALR V53 ON V53.OBJ_ID = M.OBJ_ID AND V53.PARAM_ID = 53 AND V53.IS_DEL = 0
      WHERE J.DATE_DEL IS NULL AND J.JOURNAL_TYPE = 20 AND J.YEAR_ID = :YEAR_ID
          AND (A.ATTR_VALUE IS NULL OR A.ATTR_VALUE = '')
      INTO :LESSON_ID, :GROUP_ID, :TEACHER_ID, :V$DT
  DO
  BEGIN

      IF(T_FROM IS NULL OR V$DT >= T_FROM) THEN
      BEGIN

          TAG_NAME = 'wsdl&colon;MeetingMemberInput';
          VAL = NULL;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;MeetingMemberInput:identity:external_id';
          VAL = 'V' || LESSON_ID || '+' || GROUP_ID;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;MeetingMemberInput:meeting_id:external_id';
          VAL = 'V' || LESSON_ID || '+' || GROUP_ID;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;MeetingMemberInput:teacher_id:external_id';
          VAL = TEACHER_ID;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;MeetingMemberInput:group_id:external_id';
          VAL = GROUP_ID;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;MeetingMemberInput:institution_id:id';
          VAL = ID1;
          SUSPEND;

          N = N + 1;
          IF(N >= 10000) THEN
          BEGIN
              N = 0;
              TAG_NAME = NULL;
              VAL = 'DIVIDE';
              SUSPEND;
          END

      END

  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_PORTAL_MEETING_MM_DELETE (
    T_FROM TIMESTAMP,
    T_TO TIMESTAMP NOT NULL = CURRENT_TIMESTAMP,
    ID1 VARCHAR(40) = NULL,
    ID2 VARCHAR(40) = NULL,
    I$MODE SMALLINT = 0)
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(2000))
AS
DECLARE VARIABLE LESSON_ID BIGINT;
DECLARE VARIABLE LESSON_DT TIMESTAMP;
DECLARE VARIABLE IS_OK SMALLINT;
DECLARE VARIABLE N INTEGER;
begin

  IF(T_FROM IS NULL) THEN EXIT;

  N = 0;

  -- Реально удаленные уроки
  /*FOR
      SELECT LD.LESSON_ID, LD.DATE_MODIFY
      FROM CJ_LESSON_DLT LD
      INTO :LESSON_ID, :LESSON_DT
  DO
  BEGIN

      IS_OK = 0;
      IF(
          ((T_FROM IS NULL OR LESSON_DT >= T_FROM) AND LESSON_DT < T_TO)
      )
      THEN
          IS_OK = 1;

      IF(IS_OK = 1) THEN
      BEGIN

          TAG_NAME = 'wsdl&colon;IdentityElementInput';
          VAL = NULL;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;IdentityElementInput:identity:external_id';
          VAL = LESSON_ID;
          SUSPEND;

          N = N + 1;
          IF(N >= 10000) THEN
          BEGIN
              N = 0;
              TAG_NAME = NULL;
              VAL = 'DIVIDE';
              SUSPEND;
          END

      END

  END */

  -- Уроки, где снят флаг проведения
  -- ...

  IF(0 = 1) THEN SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_PORTAL_PERIODS (
    T_FROM TIMESTAMP,
    T_TO TIMESTAMP NOT NULL = current_timestamp,
    ID1 VARCHAR(40) = null,
    ID2 VARCHAR(40) = null,
    I$MODE SMALLINT = 0)
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(2000))
AS
declare variable CURRENT_YEAR_ID bigint;
declare variable CURRENT_YEAR integer;
declare variable CAT_ID bigint;
declare variable CAT_NAME varchar(1000);
declare variable CAT_YEAR integer;
declare variable PERIOD_ID bigint;
declare variable PERIOD_NAME varchar(200);
declare variable P_FROM date;
declare variable P_TO date;
declare variable NAME_DT timestamp;
declare variable FROM_DT timestamp;
declare variable TO_DT timestamp;
declare variable IS_OK smallint;
declare variable PERIOD_TYPE bigint;
declare variable PERIOD_DT timestamp;
begin

  -- Текущий учебный год берем из настроек ОУ
  SELECT V1236.LISTVAL_ID, LV.COST
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :CURRENT_YEAR_ID, :CURRENT_YEAR;

  IF(CURRENT_YEAR_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не задан текущий учебный период. Если вы не делали перевод года, то задайте период вручную в приложении СМИР';

  -- Выдаем список учебных годов (только обрамляющий код периода) по справочнику #29, COST обязательно содержит год начала периода
  -- за исключением текущего учебного года
  -- DATE_MODIFY проверять нельзя, оно обновляется с каждым обновлением
  FOR
      SELECT LV29.LISTVAL_ID, R.VAL, LV29.COST
      FROM LISTVALS LV29
      JOIN RES R ON R.RES_ID = LV29.RES_ID AND R.LANG_CODE = 'RU'
      WHERE LV29.LIST_ID = 29 AND LV29.IS_DEL = 0 AND LV29.IS_DEL = 0 AND LV29.COST < :CURRENT_YEAR
         AND ((:T_FROM IS NULL OR LV29.DATE_MODIFY >= :T_FROM) AND LV29.DATE_MODIFY < :T_TO)
      INTO :CAT_ID, :CAT_NAME, :CAT_YEAR
  DO
  BEGIN

      TAG_NAME = 'wsdl&colon;PeriodInput';
      VAL = NULL;
      SUSPEND;

      TAG_NAME = 'wsdl&colon;PeriodInput:identity:external_id';
      VAL = CAT_ID;
      SUSPEND;

      TAG_NAME = 'wsdl&colon;PeriodInput:name';
      VAL = CAT_NAME;
      SUSPEND;

      TAG_NAME = 'wsdl&colon;PeriodInput:date_from';
      VAL = CAT_YEAR || '-09-01';
      SUSPEND;

      TAG_NAME = 'wsdl&colon;PeriodInput:date_to';
      VAL = (CAT_YEAR + 1) || '-08-31';
      SUSPEND;

      TAG_NAME = 'wsdl&colon;PeriodInput:education_period:code';
      VAL = 20;
      IF(I$MODE = 1) THEN VAL = 40000;
      SUSPEND;

  END

  -- Текущий учебный год
  -- Сначала уровни обучения, представляемые как учебные годы
  -- Изменение 2024: добавляем к старому маршруту выборки новый через КУГ
  -- путь через 150 больше не будет работать
  FOR
      SELECT L151.OBJ_ID, V1147.VAL, V1147.DATE_MODIFY
      FROM LINKS L2
      JOIN LINKS L150 ON L150.PARENT_ID = L2.OBJ_ID AND L150.OBJ_TYPE_ID IN (150, 481) AND L150.DATE_DEL IS NULL
      JOIN LINKS L151 ON L151.PARENT_ID = L150.OBJ_ID AND L151.OBJ_TYPE_ID = 151 AND L151.DATE_DEL IS NULL
      JOIN VALS V1147 ON V1147.OBJ_ID = L151.OBJ_ID AND V1147.PARAM_ID = 1147 AND V1147.IS_DEL = 0
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      INTO :CAT_ID, :CAT_NAME, :NAME_DT
  DO
  BEGIN

      IS_OK = 0;
      IF(
          ((T_FROM IS NULL OR NAME_DT >= T_FROM) AND (NAME_DT < T_TO))
      )
      THEN
          IS_OK = 1;

      IF(IS_OK = 1) THEN
      BEGIN

          TAG_NAME = 'wsdl&colon;PeriodInput';
          VAL = NULL;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;PeriodInput:identity:external_id';
          VAL = CAT_ID;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;PeriodInput:name';
          VAL = CAT_NAME;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;PeriodInput:date_from';
          VAL = CURRENT_YEAR || '-09-01';
          SUSPEND;

          TAG_NAME = 'wsdl&colon;PeriodInput:date_to';
          VAL = (CURRENT_YEAR + 1) || '-08-31';
          SUSPEND;

          TAG_NAME = 'wsdl&colon;PeriodInput:education_period:code';
          VAL = 20;
          IF(I$MODE = 1) THEN VAL = 40000; -- курс или год ЦОПП
          SUSPEND;

      END

  END

  -- Для ЦОПП отдаем периоды обучения "курс" в текущем году с конкретными датами из групп
  CAT_NAME = 'Курс';
  FOR
      SELECT L9.OBJ_ID, V3071.VAL, COALESCE(V3072.VAL, DATEADD(1 MONTH TO V3071.VAL)), V3071.DATE_MODIFY, V3072.DATE_MODIFY, L9.DATE_MODIFY
      FROM LINKS L2
      JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
      JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
      JOIN VALL V3063 ON V3063.OBJ_ID = L9.OBJ_ID AND V3063.PARAM_ID = 3063 AND V3063.IS_DEL = 0 AND V3063.LISTVAL_ID = 2
      JOIN VALD V3071 ON V3071.OBJ_ID = L9.OBJ_ID AND V3071.PARAM_ID = 3071 AND V3071.IS_DEL = 0
      LEFT JOIN VALD V3072 ON V3072.OBJ_ID = L9.OBJ_ID AND V3072.PARAM_ID = 3072 AND V3072.IS_DEL = 0
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND :I$MODE = 1
      INTO :CAT_ID, :P_FROM, :P_TO, :FROM_DT, :TO_DT, :NAME_DT
  DO
  BEGIN

      IS_OK = 0;
      IF(
          ((T_FROM IS NULL OR NAME_DT >= T_FROM) AND (NAME_DT < T_TO)) OR
          ((T_FROM IS NULL OR FROM_DT >= T_FROM) AND (FROM_DT < T_TO)) OR
          ((T_FROM IS NULL OR TO_DT >= T_FROM) AND (TO_DT < T_TO))
      )
      THEN
          IS_OK = 1;

      IF(IS_OK = 1) THEN
      BEGIN

          TAG_NAME = 'wsdl&colon;PeriodInput';
          VAL = NULL;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;PeriodInput:identity:external_id';
          VAL = CAT_ID;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;PeriodInput:name';
          VAL = CAT_NAME;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;PeriodInput:date_from';
          VAL = (SELECT VAL FROM DATE2ISO(:P_FROM, 0));
          SUSPEND;

          TAG_NAME = 'wsdl&colon;PeriodInput:date_to';
          VAL = (SELECT VAL FROM DATE2ISO(:P_TO, 0));
          SUSPEND;

          TAG_NAME = 'wsdl&colon;PeriodInput:education_period:code';
          VAL = 40000; -- курс
          SUSPEND;

      END

  END

  -- Выдаем разделитель, чтобы дочерние периоды ушли следующим пакетом
  TAG_NAME = NULL;
  VAL = 'DIVIDE';
  SUSPEND;

  -- Под-периоды текущего учебного года, только общеобр
  -- Изменение 2024: добавляем к старому маршруту выборки новый через КУГ
  -- путь через 150 больше не будет работать
  FOR
      -- Сами учебные периоды
      SELECT L151.OBJ_ID, V1147.VAL, L154.OBJ_ID, V1170.LISTVAL_ID, R.VAL, V1169.VAL, V1174.VAL, V1170.DATE_MODIFY, V1169.DATE_MODIFY, V1174.DATE_MODIFY
      FROM LINKS L2
      JOIN LINKS L150 ON L150.PARENT_ID = L2.OBJ_ID AND L150.OBJ_TYPE_ID IN (150, 481) AND L150.DATE_DEL IS NULL
      JOIN LINKS L151 ON L151.PARENT_ID = L150.OBJ_ID AND L151.OBJ_TYPE_ID = 151 AND L151.DATE_DEL IS NULL
      JOIN VALS V1147 ON V1147.OBJ_ID = L151.OBJ_ID AND V1147.PARAM_ID = 1147 AND V1147.IS_DEL = 0
      -- Интервалы времени
      JOIN LINKS L154 ON L154.PARENT_ID = L151.OBJ_ID AND L154.OBJ_TYPE_ID = 154 AND L154.DATE_DEL IS NULL
      JOIN VALL V1170 ON V1170.OBJ_ID = L154.OBJ_ID AND V1170.PARAM_ID = 1170 AND V1170.IS_DEL = 0
      JOIN LISTVALS LV ON LV.LISTVAL_ID = V1170.LISTVAL_ID
      JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
      JOIN VALD V1169 ON V1169.OBJ_ID = L154.OBJ_ID AND V1169.PARAM_ID = 1169 AND V1169.IS_DEL = 0
      JOIN VALD V1174 ON V1174.OBJ_ID = L154.OBJ_ID AND V1174.PARAM_ID = 1174 AND V1174.IS_DEL = 0
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND :I$MODE = 0
      -- Каникулы
      UNION
      SELECT L151.OBJ_ID, V1147.VAL, L450.OBJ_ID, -1, COALESCE(V3265.SVAL, 'каникулы'), V3263.VAL, V3264.VAL, V3265.DATE_MODIFY, V3263.DATE_MODIFY, V3264.DATE_MODIFY
      FROM LINKS L2
      JOIN LINKS L150 ON L150.PARENT_ID = L2.OBJ_ID AND L150.OBJ_TYPE_ID IN (150, 481) AND L150.DATE_DEL IS NULL
      JOIN LINKS L151 ON L151.PARENT_ID = L150.OBJ_ID AND L151.OBJ_TYPE_ID = 151 AND L151.DATE_DEL IS NULL
      JOIN VALS V1147 ON V1147.OBJ_ID = L151.OBJ_ID AND V1147.PARAM_ID = 1147 AND V1147.IS_DEL = 0
      -- Интервалы времени
      JOIN LINKS L450 ON L450.PARENT_ID = L151.OBJ_ID AND L450.OBJ_TYPE_ID = 450 AND L450.DATE_DEL IS NULL
      LEFT JOIN VALS V3265 ON V3265.OBJ_ID = L450.OBJ_ID AND V3265.PARAM_ID = 3265 AND V3265.IS_DEL = 0
      JOIN VALD V3263 ON V3263.OBJ_ID = L450.OBJ_ID AND V3263.PARAM_ID = 3263 AND V3263.IS_DEL = 0
      JOIN VALD V3264 ON V3264.OBJ_ID = L450.OBJ_ID AND V3264.PARAM_ID = 3264 AND V3264.IS_DEL = 0
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND :I$MODE = 0
        AND V3263.VAL < '20.05.' || (:CURRENT_YEAR + 1)
      INTO :CAT_ID, :CAT_NAME, :PERIOD_ID, :PERIOD_TYPE, :PERIOD_NAME, :P_FROM, :P_TO, :NAME_DT, :FROM_DT, :TO_DT
  DO
  BEGIN

      IS_OK = 0;
      IF(
          ((T_FROM IS NULL OR NAME_DT >= T_FROM) AND (NAME_DT < T_TO)) OR
          ((T_FROM IS NULL OR FROM_DT >= T_FROM) AND (FROM_DT < T_TO)) OR
          ((T_FROM IS NULL OR TO_DT >= T_FROM) AND (TO_DT < T_TO))
      )
      THEN
          IS_OK = 1;

      IF(IS_OK = 1) THEN
      BEGIN

          TAG_NAME = 'wsdl&colon;PeriodInput';
          VAL = NULL;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;PeriodInput:identity:external_id';
          VAL = PERIOD_ID;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;PeriodInput:name';
          VAL = CAT_NAME || ' - ' || PERIOD_NAME;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;PeriodInput:date_from';
          VAL = (SELECT VAL FROM DATE2ISO(:P_FROM, 0));
          SUSPEND;

          TAG_NAME = 'wsdl&colon;PeriodInput:date_to';
          VAL = (SELECT VAL FROM DATE2ISO(:P_TO, 0));
          SUSPEND;

          TAG_NAME = 'wsdl&colon;PeriodInput:parent:external_id';
          VAL = CAT_ID;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;PeriodInput:education_period:code';
          VAL = NULL;
          IF(I$MODE = 0) THEN
          BEGIN
              IF(PERIOD_TYPE = 12) THEN VAL = 1;       -- четверти
              ELSE IF(PERIOD_TYPE = 13) THEN VAL = 2;
              ELSE IF(PERIOD_TYPE = 14) THEN VAL = 3;
              ELSE IF(PERIOD_TYPE = 15) THEN VAL = 4;
              ELSE IF(PERIOD_TYPE = 10) THEN VAL = 8;  -- полугодия
              ELSE IF(PERIOD_TYPE = 11) THEN VAL = 9;
              ELSE IF(PERIOD_TYPE = 16) THEN VAL = 5;  -- триместры
              ELSE IF(PERIOD_TYPE = 17) THEN VAL = 6;
              ELSE IF(PERIOD_TYPE = 18) THEN VAL = 7;
              ELSE IF(PERIOD_TYPE = 19) THEN VAL = 18; -- семестры
              ELSE IF(PERIOD_TYPE = 20) THEN VAL = 19;
              ELSE IF(PERIOD_TYPE < 0) THEN VAL = 30; -- Каникулы
          END
          ELSE IF(I$MODE = 1) THEN
          BEGIN
              -- Сюда все равно не попадем, выборка только для типа 0
              IF(PERIOD_TYPE = 19) THEN VAL = 40101;       -- семестры
              ELSE IF(PERIOD_TYPE = 20) THEN VAL = 40102;
          END
          SUSPEND;

      END

  END

  -- Вложенные периоды для ЦОПП - тут только модули и сам курс
  FOR
      SELECT L9.OBJ_ID, PS.OBJ_ID, PS.FIELD_ID, V3071.VAL, V3072.VAL, V3071.DATE_MODIFY, V3072.DATE_MODIFY, L9.DATE_MODIFY, PS.DATE_MODIFY
      FROM LINKS L2
      JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
      JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
      JOIN VALL V3063 ON V3063.OBJ_ID = L9.OBJ_ID AND V3063.PARAM_ID = 3063 AND V3063.IS_DEL = 0 AND V3063.LISTVAL_ID = 2
      JOIN VALD V3071 ON V3071.OBJ_ID = L9.OBJ_ID AND V3071.PARAM_ID = 3071 AND V3071.IS_DEL = 0
      JOIN VALD V3072 ON V3072.OBJ_ID = L9.OBJ_ID AND V3072.PARAM_ID = 3072 AND V3072.IS_DEL = 0
      -- Пересекаем с УП
      JOIN VALR V3075 ON V3075.OBJ_ID = L9.OBJ_ID AND V3075.PARAM_ID = 3075 AND V3075.IS_DEL = 0
      -- Выбираем корневые узлы УП, относящиеся к делению на модули (кроме самого курса)
      JOIN PLAN_SUBJECTS PS ON PS.PLAN_ID = V3075.VAL AND PS.DATE_DEL IS NULL AND PS.ROW_TYPE = 0 AND
          PS.LEVEL_INDEX = 0 AND PS.FIELD_ID >= 12978 AND PS.FIELD_ID <= 12997
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND :I$MODE = 1
      INTO :CAT_ID, :PERIOD_ID, :PERIOD_TYPE, :P_FROM, :P_TO, :FROM_DT, :TO_DT, :NAME_DT, :PERIOD_DT
  DO
  BEGIN
      IS_OK = 0;
      IF(
          ((T_FROM IS NULL OR NAME_DT >= T_FROM) AND (NAME_DT < T_TO)) OR
          ((T_FROM IS NULL OR FROM_DT >= T_FROM) AND (FROM_DT < T_TO)) OR
          ((T_FROM IS NULL OR TO_DT >= T_FROM) AND (TO_DT < T_TO)) OR
          ((T_FROM IS NULL OR PERIOD_DT >= T_FROM) AND (PERIOD_DT < T_TO))
      )
      THEN
          IS_OK = 1;

      IF(IS_OK = 1) THEN
      BEGIN

          TAG_NAME = 'wsdl&colon;PeriodInput';
          VAL = NULL;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;PeriodInput:identity:external_id';
          VAL = CAT_ID || '-' || PERIOD_ID;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;PeriodInput:name';
          VAL = 'Модуль N'; -- название они все равно меняют на свое
          SUSPEND;

          TAG_NAME = 'wsdl&colon;PeriodInput:date_from';
          VAL = (SELECT VAL FROM DATE2ISO(:P_FROM, 0));
          SUSPEND;

          TAG_NAME = 'wsdl&colon;PeriodInput:date_to';
          VAL = (SELECT VAL FROM DATE2ISO(:P_TO, 0));
          SUSPEND;

          TAG_NAME = 'wsdl&colon;PeriodInput:parent:external_id';
          VAL = CAT_ID;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;PeriodInput:education_period:code';
          VAL = PERIOD_TYPE - 12978 + 40201; -- 12978 -> 40201
          SUSPEND;

      END
  END

  -- Старые периоды выдаем только в том составе, который присутствует в итоговых отметках (годовой период и так уже выдан)
  FOR
      SELECT DISTINCT M.YEAR_ID, M.MARKTYPE_ID
      FROM VALM M
      JOIN LISTVALS LV29 ON LV29.LISTVAL_ID = M.YEAR_ID AND LV29.IS_DEL = 0 AND LV29.COST < :CURRENT_YEAR
      WHERE M.IS_DEL = 0 AND M.MARKTYPE_ID NOT IN (3001, 3011, 3012, 3013, 5544) AND ((:T_FROM IS NULL OR M.DATE_MODIFY >= :T_FROM) AND M.DATE_MODIFY < :T_TO)
      INTO :CAT_ID, :PERIOD_TYPE
  DO
  BEGIN

      TAG_NAME = 'wsdl&colon;PeriodInput';
      VAL = NULL;
      SUSPEND;

      TAG_NAME = 'wsdl&colon;PeriodInput:identity:external_id';
      VAL = CAT_ID || '-' || PERIOD_TYPE;
      SUSPEND;

      TAG_NAME = 'wsdl&colon;PeriodInput:name';
      SELECT R.VAL
      FROM LISTVALS LV29
      JOIN RES R ON R.RES_ID = LV29.RES_ID AND R.LANG_CODE = 'RU'
      WHERE LV29.LISTVAL_ID = :PERIOD_TYPE
      INTO :VAL;
      SUSPEND;

      TAG_NAME = 'wsdl&colon;PeriodInput:parent:external_id';
      VAL = CAT_ID;
      SUSPEND;

      SELECT COST
      FROM LISTVALS
      WHERE LISTVAL_ID = :CAT_ID
      INTO :CAT_YEAR;

      -- Формируем код типа периода и условные даты начала-окончания
      TAG_NAME = 'wsdl&colon;PeriodInput:education_period:code';
      VAL = NULL; P_FROM = NULL; P_TO = NULL;
      IF(I$MODE = 0) THEN
      BEGIN
          IF(PERIOD_TYPE = 3002) THEN BEGIN VAL = 1; P_FROM = CAT_YEAR || '-09-01'; P_TO = CAT_YEAR || '-10-31'; END     -- четверти
          ELSE IF(PERIOD_TYPE = 3003) THEN BEGIN VAL = 2; P_FROM = CAT_YEAR || '-11-01'; P_TO = CAT_YEAR || '-12-31'; END
          ELSE IF(PERIOD_TYPE = 3004) THEN BEGIN VAL = 3; P_FROM = (CAT_YEAR + 1) || '-01-01'; P_TO = (CAT_YEAR + 1) || '-03-31'; END
          ELSE IF(PERIOD_TYPE = 3005) THEN BEGIN VAL = 4; P_FROM = (CAT_YEAR + 1) || '-04-01'; P_TO = (CAT_YEAR + 1) || '-05-31'; END
          ELSE IF(PERIOD_TYPE = 3009) THEN BEGIN VAL = 8; P_FROM = CAT_YEAR || '-09-01'; P_TO = CAT_YEAR || '-12-31'; END -- полугодия
          ELSE IF(PERIOD_TYPE = 3010) THEN BEGIN VAL = 9; P_FROM = (CAT_YEAR + 1) || '-01-01'; P_TO = (CAT_YEAR + 1) || '-05-31'; END
          ELSE IF(PERIOD_TYPE = 3006) THEN BEGIN VAL = 5; P_FROM = CAT_YEAR || '-09-01'; P_TO = CAT_YEAR || '-11-14'; END -- триместры
          ELSE IF(PERIOD_TYPE = 3007) THEN BEGIN VAL = 6; P_FROM = CAT_YEAR || '-11-15'; P_TO = (CAT_YEAR + 1) || '-02-14'; END
          ELSE IF(PERIOD_TYPE = 3008) THEN BEGIN VAL = 7; P_FROM = (CAT_YEAR + 1) || '-02-15'; P_TO = (CAT_YEAR + 1) || '-05-31'; END
          -- семестров у нас тут нет
      END
      ELSE IF(I$MODE = 1) THEN
      BEGIN
          IF(PERIOD_TYPE = 3009) THEN BEGIN VAL = 40101; P_FROM = CAT_YEAR || '-09-01'; P_TO = CAT_YEAR || '-12-31'; END -- полугодия кодируем как семестры
          ELSE IF(PERIOD_TYPE = 3010) THEN BEGIN VAL = 40102; P_FROM = (CAT_YEAR + 1) || '-01-01'; P_TO = (CAT_YEAR + 1) || '-05-31'; END
          ELSE IF(PERIOD_TYPE = 12973) THEN BEGIN VAL = 40101; P_FROM = CAT_YEAR || '-09-01'; P_TO = CAT_YEAR || '-12-31'; END -- семестры
          ELSE IF(PERIOD_TYPE = 12974) THEN BEGIN VAL = 40102; P_FROM = (CAT_YEAR + 1) || '-01-01'; P_TO = (CAT_YEAR + 1) || '-05-31'; END
      END
      SUSPEND;

      TAG_NAME = 'wsdl&colon;PeriodInput:date_from';
      VAL = (SELECT VAL FROM DATE2ISO(:P_FROM, 0));
      SUSPEND;

      TAG_NAME = 'wsdl&colon;PeriodInput:date_to';
      VAL = (SELECT VAL FROM DATE2ISO(:P_TO, 0));
      SUSPEND;

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_PORTAL_PERIODS_DELETE (
    T_FROM TIMESTAMP,
    T_TO TIMESTAMP NOT NULL = current_timestamp,
    ID1 VARCHAR(40) = null,
    ID2 VARCHAR(40) = null,
    I$MODE SMALLINT = 0)
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(2000))
AS
declare variable PERIOD_ID bigint;
declare variable PERIOD_DT timestamp;
declare variable IS_OK smallint;
begin

  IF(T_FROM IS NULL) THEN EXIT;

  FOR
      SELECT L154.OBJ_ID, L154.DATE_MODIFY
      FROM LINKS L2
      JOIN LINKS L150 ON L150.PARENT_ID = L2.OBJ_ID AND L150.OBJ_TYPE_ID IN (150, 481) AND L150.DATE_DEL IS NULL
      JOIN LINKS L151 ON L151.PARENT_ID = L150.OBJ_ID AND L151.OBJ_TYPE_ID = 151
      JOIN LINKS L154 ON L154.PARENT_ID = L151.OBJ_ID AND L154.OBJ_TYPE_ID = 154 AND L154.DATE_DEL IS NOT NULL
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND :I$MODE = 0
      -- Каникулы
      UNION
      SELECT L450.OBJ_ID, L450.DATE_MODIFY
      FROM LINKS L2
      JOIN LINKS L150 ON L150.PARENT_ID = L2.OBJ_ID AND L150.OBJ_TYPE_ID IN (150, 481) AND L150.DATE_DEL IS NULL
      JOIN LINKS L151 ON L151.PARENT_ID = L150.OBJ_ID AND L151.OBJ_TYPE_ID = 151 AND L151.DATE_DEL IS NULL
      JOIN LINKS L450 ON L450.PARENT_ID = L151.OBJ_ID AND L450.OBJ_TYPE_ID = 450 AND L450.DATE_DEL IS NOT NULL
      INTO :PERIOD_ID, :PERIOD_DT
  DO
  BEGIN

      IS_OK = 0;
      IF(
          ((T_FROM IS NULL OR PERIOD_DT >= T_FROM) AND PERIOD_DT < T_TO)
      )
      THEN
          IS_OK = 1;

      IF(IS_OK = 1) THEN
      BEGIN

          TAG_NAME = 'wsdl&colon;IdentityElementInput';
          VAL = NULL;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;IdentityElementInput:identity:external_id';
          VAL = PERIOD_ID;
          SUSPEND;

      END

  END

  -- Периоды для ЦОПП - удаленные группы, удаленные разделы

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_PORTAL_PERSONS (
    T_FROM TIMESTAMP,
    T_TO TIMESTAMP NOT NULL = current_timestamp,
    ID1 VARCHAR(40) = null,
    ID2 VARCHAR(40) = null,
    I$MODE SMALLINT = 0)
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(2000))
AS
declare variable PERSON_ID bigint;
declare variable IS_OK smallint;
declare variable DATE_MOVE timestamp;
declare variable DATE_P_UID1 timestamp;
declare variable DATE_P_UID2 timestamp;
declare variable DATE_MODIFY timestamp;
declare variable V1 varchar(1000);
declare variable V2 varchar(1000);
declare variable V3 varchar(1000);
declare variable V4 varchar(100);
declare variable V4X varchar(100);
declare variable VD date;
declare variable VS bigint;
declare variable DM1 timestamp;
declare variable DM2 timestamp;
declare variable DM3 timestamp;
declare variable DM4 timestamp;
declare variable DM4X timestamp;
declare variable DMD timestamp;
declare variable DMS timestamp;
declare variable DMCH timestamp;
declare variable REG_ID varchar(100);
declare variable REG_DM timestamp;
declare variable YEAR_START date;
declare variable N integer;
declare variable V$COPP bigint;
declare variable HS varchar(400);
declare variable HSN smallint;
begin

  -- I$MODE отвечает за переключение режима выгрузки для колледжей - 0 = обычный режим, 1 = выгрузка ЦОПП

  IF(EXTRACT(MONTH FROM CURRENT_DATE) < 9) THEN YEAR_START = '01.09.' || (EXTRACT(YEAR FROM CURRENT_DATE) - 1);
  ELSE YEAR_START = '01.09.' || EXTRACT(YEAR FROM CURRENT_DATE);

  N = 0;

  -- Актуальные сотрудники
  FOR
      SELECT L14.OBJ_ID, MAX(L14.DATE_MODIFY)
      FROM LINKS L2
      JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
      -- Должны быть фамилия и имя
      JOIN VALS V1 ON V1.OBJ_ID = L14.OBJ_ID AND V1.PARAM_ID = 59 AND V1.IS_DEL = 0
      JOIN VALS V2 ON V2.OBJ_ID = L14.OBJ_ID AND V2.PARAM_ID = 60 AND V2.IS_DEL = 0
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      GROUP BY 1
      INTO :PERSON_ID, :DATE_MODIFY
  DO
  BEGIN

    V4 = NULL;
    V4X = NULL;
    DM4 = NULL;
    VD = NULL;
    VS = NULL;
    DMD = NULL;
    DMS = NULL;

    SELECT V59.VAL, V59.DATE_MODIFY
    FROM RDB$DATABASE
    LEFT JOIN VALS V59 ON V59.OBJ_ID = :PERSON_ID AND V59.PARAM_ID = 59 AND V59.IS_DEL = 0
    INTO :V1, :DM1;

    SELECT V60.VAL, V60.DATE_MODIFY
    FROM RDB$DATABASE
    LEFT JOIN VALS V60 ON V60.OBJ_ID = :PERSON_ID AND V60.PARAM_ID = 60 AND V60.IS_DEL = 0
    INTO :V2, :DM2;

    SELECT V61.VAL, V61.DATE_MODIFY
    FROM RDB$DATABASE
    LEFT JOIN VALS V61 ON V61.OBJ_ID = :PERSON_ID AND V61.PARAM_ID = 61 AND V61.IS_DEL = 0
    INTO :V3, :DM3;

    SELECT V267.VAL, V267.DATE_MODIFY
    FROM RDB$DATABASE
    LEFT JOIN VALS V267 ON V267.OBJ_ID = :PERSON_ID AND V267.PARAM_ID = 267 AND V267.IS_DEL = 0
    INTO :V4, :DM4;

    SELECT V3061.VAL, V3061.DATE_MODIFY
    FROM RDB$DATABASE
    LEFT JOIN VALS V3061 ON V3061.OBJ_ID = :PERSON_ID AND V3061.PARAM_ID = 3061 AND V3061.IS_DEL = 0
    INTO :V4X, :DM4X;

    SELECT V2915.VAL, V2915.DATE_MODIFY
    FROM RDB$DATABASE
    LEFT JOIN VALS V2915 ON V2915.OBJ_ID = :PERSON_ID AND V2915.PARAM_ID = 2915 AND V2915.IS_DEL = 0
    INTO :REG_ID, :REG_DM;

    SELECT V241.VAL, V241.DATE_MODIFY
    FROM RDB$DATABASE
    LEFT JOIN VALD V241 ON V241.OBJ_ID = :PERSON_ID AND V241.PARAM_ID = 241 AND V241.IS_DEL = 0
    INTO :VD, :DMD;

    SELECT V239.LISTVAL_ID, V239.DATE_MODIFY
    FROM RDB$DATABASE
    LEFT JOIN VALL V239 ON V239.OBJ_ID = :PERSON_ID AND V239.PARAM_ID = 239 AND V239.IS_DEL = 0
    INTO :VS, :DMS;

    IF(POSITION(':' IN REG_ID) > 0) THEN REG_ID = SUBSTRING(REG_ID FROM 1 FOR POSITION(':' IN REG_ID) - 1);

    -- Сначала пробуем СНИЛС, потом паспорт, потом СОР
    HS = NULL;
    HSN = NULL;
    SELECT FIRST 1 REPLACE(REPLACE(V.VAL, '-', ''), ' ', ''), 1
    FROM VALS V
    WHERE V.OBJ_ID = :PERSON_ID AND V.PARAM_ID IN (1409, 2455, 2365) AND V.IS_DEL = 0
    INTO :HS, :HSN;

    IF(HS IS NULL) THEN
    SELECT FIRST 1 V1.SVAL || ' ' || V2.SVAL, 2
    FROM LINKS L79
    JOIN VALL V441 ON V441.OBJ_ID = L79.OBJ_ID AND V441.PARAM_ID = 441 AND V441.IS_DEL = 0 AND V441.LISTVAL_ID = 1368
    JOIN VALL V614 ON V614.OBJ_ID = L79.OBJ_ID AND V614.PARAM_ID = 614 AND V614.IS_DEL = 0 AND V614.LISTVAL_ID = 1982
    JOIN VALS V1 ON V1.OBJ_ID = L79.OBJ_ID AND V1.PARAM_ID = 442 AND V1.IS_DEL = 0
    JOIN VALS V2 ON V2.OBJ_ID = L79.OBJ_ID AND V2.PARAM_ID = 559 AND V2.IS_DEL = 0
    WHERE L79.PARENT_ID = :PERSON_ID AND L79.OBJ_TYPE_ID = 79 AND L79.DATE_DEL IS NULL
    INTO :HS, :HSN;

    IF(HS IS NULL) THEN
    SELECT FIRST 1 REPLACE(UPPER(V1.SVAL), '-', '') || ' ' || UPPER(V2.SVAL) || ' ' || REPLACE(D.VAL, '-', ''), 3
    FROM LINKS L79
    JOIN VALL V441 ON V441.OBJ_ID = L79.OBJ_ID AND V441.PARAM_ID = 441 AND V441.IS_DEL = 0 AND V441.LISTVAL_ID = 1370
    JOIN VALL V614 ON V614.OBJ_ID = L79.OBJ_ID AND V614.PARAM_ID = 614 AND V614.IS_DEL = 0 AND V614.LISTVAL_ID = 1982
    JOIN VALS V1 ON V1.OBJ_ID = L79.OBJ_ID AND V1.PARAM_ID = 442 AND V1.IS_DEL = 0
    JOIN VALS V2 ON V2.OBJ_ID = L79.OBJ_ID AND V2.PARAM_ID = 559 AND V2.IS_DEL = 0
    JOIN VALD V3 ON V3.OBJ_ID = L79.OBJ_ID AND V3.PARAM_ID = 560 AND V3.IS_DEL = 0
    LEFT JOIN DATE2ISO(V3.VAL, 0) D ON 1 = 1
    WHERE L79.PARENT_ID = :PERSON_ID AND L79.OBJ_TYPE_ID = 79 AND L79.DATE_DEL IS NULL
    INTO :HS, :HSN;

    IS_OK = 0;
    IF(
        ((T_FROM IS NULL OR DATE_MODIFY >= T_FROM) AND (DATE_MODIFY < T_TO)) OR
        ((T_FROM IS NULL OR DM1 >= T_FROM) AND (DM1 < T_TO)) OR
        ((T_FROM IS NULL OR DM2 >= T_FROM) AND (DM2 < T_TO)) OR
        ((T_FROM IS NULL OR DM3 >= T_FROM) AND (DM3 < T_TO)) OR
        ((T_FROM IS NULL OR DM4 >= T_FROM) AND (DM4 < T_TO)) OR
        ((T_FROM IS NULL OR DM4X >= T_FROM) AND (DM4X < T_TO)) OR
        ((T_FROM IS NULL OR DMD >= T_FROM) AND (DMD < T_TO)) OR
        ((T_FROM IS NULL OR DMS >= T_FROM) AND (DMS < T_TO)) OR
        ((T_FROM IS NULL OR REG_DM >= T_FROM) AND (REG_DM < T_TO))
    )
    THEN
        IS_OK = 1;

    IF(IS_OK = 1) THEN
    BEGIN

        TAG_NAME = 'wsdl&colon;PersonInput';
        VAL = NULL;
        SUSPEND;

        TAG_NAME = 'wsdl&colon;PersonInput:identity:uid';
        VAL = REG_ID;
        IF(REG_ID IS NOT NULL AND REG_ID <> '') THEN SUSPEND;

        TAG_NAME = 'wsdl&colon;PersonInput:identity:external_id';
        VAL = PERSON_ID;
        SUSPEND;

        TAG_NAME = 'wsdl&colon;PersonInput:firstname';
        VAL = COALESCE(V2, '');
        SUSPEND;

        TAG_NAME = 'wsdl&colon;PersonInput:surname';
        VAL = COALESCE(V1, '');
        SUSPEND;

        TAG_NAME = 'wsdl&colon;PersonInput:middlename';
        VAL = COALESCE(V3, '');
        SUSPEND;

        IF(V4X IS NOT NULL) THEN
        BEGIN
          TAG_NAME = 'wsdl&colon;PersonInput:esia_id';
          VAL = TRIM(COALESCE(V4X, ''));
          SUSPEND;
        END
        -- ELSE 
        IF(V4 IS NOT NULL) THEN
        BEGIN
          TAG_NAME = 'wsdl&colon;PersonInput:petrobr_id';
          VAL = COALESCE(V4, '');
          SUSPEND;
        END

        IF(VD IS NOT NULL) THEN
        BEGIN
          TAG_NAME = 'wsdl&colon;PersonInput:birth_date';
          VAL = (SELECT VAL FROM DATE2ISO(:VD, 0));
          SUSPEND;
        END

        IF(VS IS NOT NULL) THEN
        BEGIN
          TAG_NAME = 'wsdl&colon;PersonInput:sex:code';
          VAL = IIF(VS = 182, 'Ж', 'М');
          SUSPEND;
        END

        IF(HS IS NOT NULL) THEN
        BEGIN
          TAG_NAME = 'wsdl&colon;PersonInput:hash_gost2012';
          VAL = HS;
          SUSPEND;
          TAG_NAME = 'wsdl&colon;PersonInput:hash_num';
          VAL = HSN;
          SUSPEND;
        END

        N = N + 1;
        IF(N >= 10000) THEN
        BEGIN
            N = 0;
            TAG_NAME = NULL;
            VAL = 'DIVIDE';
            SUSPEND;
        END

    END

  END

  -- Актуальные ученики - только те, у которых прописаны пары кодов {родитель:учащийся}, либо в режиме ЦОПП учащиеся в специальных группах
  -- У учащихся портальные коды не нужны
  FOR
      SELECT L10.OBJ_ID, MAX(L10.DATE_MODIFY)
      FROM LINKS L2
      JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
      JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 125, 187) AND L9.DATE_DEL IS NULL
      JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      -- Должны быть фамилия и имя
      JOIN VALS V1 ON V1.OBJ_ID = L10.OBJ_ID AND V1.PARAM_ID = 55 AND V1.IS_DEL = 0
      JOIN VALS V2 ON V2.OBJ_ID = L10.OBJ_ID AND V2.PARAM_ID = 56 AND V2.IS_DEL = 0
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      GROUP BY 1
      INTO :PERSON_ID, :DATE_MODIFY
  DO
  BEGIN

    V3 = NULL;
    V4 = NULL;
    V4X = NULL;
    DM4 = NULL;
    VD = NULL;
    VS = NULL;
    DMD = NULL;
    DMS = NULL;

    -- Числится ли ученик в группе ЦОПП
    V$COPP = 3;
    SELECT MIN(V3063.LISTVAL_ID)
    FROM LINKS LP9
    JOIN VALL V3063 ON V3063.OBJ_ID = LP9.PARENT_ID AND V3063.PARAM_ID = 3063 AND V3063.IS_DEL = 0
    WHERE LP9.OBJ_ID = :PERSON_ID AND LP9.PARENT_TYPE_ID = 9 AND LP9.DATE_DEL IS NULL
    INTO :V$COPP;

    -- Проверяем последнее движение в классе
    SELECT MAX(LPG.DATE_INS)
    FROM LINKS LPG
    WHERE LPG.OBJ_ID = :PERSON_ID AND LPG.PARENT_TYPE_ID IN (9, 125, 187) AND LPG.DATE_DEL IS NULL
    INTO :DATE_MOVE;

    -- Наличие и дата изменения кодов
    DATE_P_UID1 = NULL;
    DATE_P_UID2 = NULL;
    SELECT MAX(V1570.DATE_MODIFY), MAX(V155.DATE_MODIFY)
    FROM LINKS L20
    JOIN VALS V1570 ON V1570.OBJ_ID = L20.EXT_OBJ_ID AND V1570.PARAM_ID = 1570 AND V1570.IS_DEL = 0
    JOIN VALS V155 ON V155.OBJ_ID = L20.OBJ_ID AND V155.PARAM_ID = 155 AND V155.IS_DEL = 0
    WHERE L20.PARENT_ID = :PERSON_ID AND L20.OBJ_TYPE_ID = 20 AND L20.DATE_DEL IS NULL
    INTO :DATE_P_UID1, :DATE_P_UID2;

    SELECT V55.VAL, V55.DATE_MODIFY
    FROM RDB$DATABASE
    LEFT JOIN VALS V55 ON V55.OBJ_ID = :PERSON_ID AND V55.PARAM_ID = 55 AND V55.IS_DEL = 0
    INTO :V1, :DM1;

    SELECT V56.VAL, V56.DATE_MODIFY
    FROM RDB$DATABASE
    LEFT JOIN VALS V56 ON V56.OBJ_ID = :PERSON_ID AND V56.PARAM_ID = 56 AND V56.IS_DEL = 0
    INTO :V2, :DM2;

    SELECT V57.VAL, V57.DATE_MODIFY
    FROM RDB$DATABASE
    LEFT JOIN VALS V57 ON V57.OBJ_ID = :PERSON_ID AND V57.PARAM_ID = 57 AND V57.IS_DEL = 0
    INTO :V3, :DM3;

    SELECT V3060.VAL, V3060.DATE_MODIFY
    FROM RDB$DATABASE
    LEFT JOIN VALS V3060 ON V3060.OBJ_ID = :PERSON_ID AND V3060.PARAM_ID = 3060 AND V3060.IS_DEL = 0
    INTO :V4X, :DM4X;

    SELECT V2912.VAL, V2912.DATE_MODIFY
    FROM RDB$DATABASE
    LEFT JOIN VALS V2912 ON V2912.OBJ_ID = :PERSON_ID AND V2912.PARAM_ID = 2912 AND V2912.IS_DEL = 0
    INTO :REG_ID, :REG_DM;

    SELECT V89.VAL, V89.DATE_MODIFY
    FROM RDB$DATABASE
    LEFT JOIN VALD V89 ON V89.OBJ_ID = :PERSON_ID AND V89.PARAM_ID = 89 AND V89.IS_DEL = 0
    INTO :VD, :DMD;

    SELECT V88.LISTVAL_ID, V88.DATE_MODIFY
    FROM RDB$DATABASE
    LEFT JOIN VALL V88 ON V88.OBJ_ID = :PERSON_ID AND V88.PARAM_ID = 88 AND V88.IS_DEL = 0
    INTO :VS, :DMS;

    IF(POSITION(':' IN REG_ID) > 0) THEN REG_ID = SUBSTRING(REG_ID FROM 1 FOR POSITION(':' IN REG_ID) - 1);

    -- Сначала пробуем СНИЛС, потом паспорт, потом СОР
    HS = NULL;
    HSN = NULL;
    SELECT FIRST 1 REPLACE(REPLACE(V.VAL, '-', ''), ' ', ''), 1
    FROM VALS V
    WHERE V.OBJ_ID = :PERSON_ID AND V.PARAM_ID IN (1409, 2455, 2365) AND V.IS_DEL = 0
    INTO :HS, :HSN;

    IF(HS IS NULL) THEN
    SELECT FIRST 1 V1.SVAL || ' ' || V2.SVAL, 2
    FROM LINKS L79
    JOIN VALL V441 ON V441.OBJ_ID = L79.OBJ_ID AND V441.PARAM_ID = 441 AND V441.IS_DEL = 0 AND V441.LISTVAL_ID = 1368
    JOIN VALL V614 ON V614.OBJ_ID = L79.OBJ_ID AND V614.PARAM_ID = 614 AND V614.IS_DEL = 0 AND V614.LISTVAL_ID = 1982
    JOIN VALS V1 ON V1.OBJ_ID = L79.OBJ_ID AND V1.PARAM_ID = 442 AND V1.IS_DEL = 0
    JOIN VALS V2 ON V2.OBJ_ID = L79.OBJ_ID AND V2.PARAM_ID = 559 AND V2.IS_DEL = 0
    WHERE L79.PARENT_ID = :PERSON_ID AND L79.OBJ_TYPE_ID = 79 AND L79.DATE_DEL IS NULL
    INTO :HS, :HSN;

    IF(HS IS NULL) THEN
    SELECT FIRST 1 REPLACE(UPPER(V1.SVAL), '-', '') || ' ' || UPPER(V2.SVAL) || ' ' || REPLACE(D.VAL, '-', ''), 3
    FROM LINKS L79
    JOIN VALL V441 ON V441.OBJ_ID = L79.OBJ_ID AND V441.PARAM_ID = 441 AND V441.IS_DEL = 0 AND V441.LISTVAL_ID = 1370
    JOIN VALL V614 ON V614.OBJ_ID = L79.OBJ_ID AND V614.PARAM_ID = 614 AND V614.IS_DEL = 0 AND V614.LISTVAL_ID = 1982
    JOIN VALS V1 ON V1.OBJ_ID = L79.OBJ_ID AND V1.PARAM_ID = 442 AND V1.IS_DEL = 0
    JOIN VALS V2 ON V2.OBJ_ID = L79.OBJ_ID AND V2.PARAM_ID = 559 AND V2.IS_DEL = 0
    JOIN VALD V3 ON V3.OBJ_ID = L79.OBJ_ID AND V3.PARAM_ID = 560 AND V3.IS_DEL = 0
    LEFT JOIN DATE2ISO(V3.VAL, 0) D ON 1 = 1
    WHERE L79.PARENT_ID = :PERSON_ID AND L79.OBJ_TYPE_ID = 79 AND L79.DATE_DEL IS NULL
    INTO :HS, :HSN;

    IS_OK = 0;
    IF(((DATE_P_UID1 IS NOT NULL AND DATE_P_UID2 IS NOT NULL AND I$MODE = 0) OR (I$MODE = 1 AND V$COPP = 2)) AND
      (
        ((T_FROM IS NULL OR DATE_MODIFY >= T_FROM) AND (DATE_MODIFY < T_TO)) OR
        ((T_FROM IS NULL OR DATE_MOVE >= T_FROM) AND (DATE_MOVE < T_TO)) OR
        ((T_FROM IS NULL OR DM1 >= T_FROM) AND (DM1 < T_TO)) OR
        ((T_FROM IS NULL OR DM2 >= T_FROM) AND (DM2 < T_TO)) OR
        ((T_FROM IS NULL OR DM3 >= T_FROM) AND (DM3 < T_TO)) OR
        ((T_FROM IS NULL OR DM4 >= T_FROM) AND (DM4 < T_TO)) OR
        ((T_FROM IS NULL OR DM4X >= T_FROM) AND (DM4X < T_TO)) OR
        ((T_FROM IS NULL OR DMD >= T_FROM) AND (DMD < T_TO)) OR
        ((T_FROM IS NULL OR DMS >= T_FROM) AND (DMS < T_TO)) OR
        ((T_FROM IS NULL OR REG_DM >= T_FROM) AND (REG_DM < T_TO)) OR
        ((T_FROM IS NULL OR DATE_P_UID1 >= T_FROM) AND (DATE_P_UID1 < T_TO)) OR
        ((T_FROM IS NULL OR DATE_P_UID2 >= T_FROM) AND (DATE_P_UID2 < T_TO))
      )
    )
    THEN
        IS_OK = 1;

    -- В ЦОПП запарываем выдачу ученика, если у нас уже есть как сотрудник
    IF(I$MODE = 1 AND EXISTS(
        SELECT FIRST 1 1
        FROM VALS V3061
        WHERE V3061.PARAM_ID = 3061 AND V3061.IS_DEL = 0 AND V3061.SVAL = :V4X
    ))
    THEN IS_OK = 0;

    IF(IS_OK = 1) THEN
    BEGIN

        TAG_NAME = 'wsdl&colon;PersonInput';
        VAL = NULL;
        SUSPEND;

        TAG_NAME = 'wsdl&colon;PersonInput:identity:uid';
        VAL = REG_ID;
        IF(REG_ID IS NOT NULL AND REG_ID <> '') THEN SUSPEND;

        TAG_NAME = 'wsdl&colon;PersonInput:identity:external_id';
        VAL = PERSON_ID;
        SUSPEND;

        TAG_NAME = 'wsdl&colon;PersonInput:firstname';
        VAL = COALESCE(V2, '');
        SUSPEND;

        TAG_NAME = 'wsdl&colon;PersonInput:surname';
        VAL = COALESCE(V1, '');
        SUSPEND;

        TAG_NAME = 'wsdl&colon;PersonInput:middlename';
        VAL = COALESCE(V3, '');
        SUSPEND;

        -- Для учеников только ЕСИА (ЦОПП)
        IF(V4X IS NOT NULL) THEN
        BEGIN
          TAG_NAME = 'wsdl&colon;PersonInput:esia_id';
          VAL = TRIM(COALESCE(V4X, ''));
          SUSPEND;
        END

        IF(VD IS NOT NULL) THEN
        BEGIN
          TAG_NAME = 'wsdl&colon;PersonInput:birth_date';
          VAL = (SELECT VAL FROM DATE2ISO(:VD, 0));
          SUSPEND;
        END

        IF(VS IS NOT NULL) THEN
        BEGIN
          TAG_NAME = 'wsdl&colon;PersonInput:sex:code';
          VAL = IIF(VS = 182, 'Ж', 'М');
          SUSPEND;
        END

        IF(HS IS NOT NULL) THEN
        BEGIN
          TAG_NAME = 'wsdl&colon;PersonInput:hash_gost2012';
          VAL = HS;
          SUSPEND;
          TAG_NAME = 'wsdl&colon;PersonInput:hash_num';
          VAL = HSN;
          SUSPEND;
        END

        N = N + 1;
        IF(N >= 10000) THEN
        BEGIN
            N = 0;
            TAG_NAME = NULL;
            VAL = 'DIVIDE';
            SUSPEND;
        END

    END

  END

  -- Представители актуальных учеников - только те, у которых прописаны пары кодов {родитель:учащийся}
  -- Для ЦОПП тут ничего не будет
  FOR
      SELECT L20.OBJ_ID, MAX(L20.DATE_MODIFY)
      FROM LINKS L2
      JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
      JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 125, 187) AND L9.DATE_DEL IS NULL
      JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      JOIN LINKS L20 ON L20.PARENT_ID = L10.OBJ_ID AND L20.OBJ_TYPE_ID = 20 AND L20.DATE_DEL IS NULL
      -- Должны быть фамилия и имя
      JOIN VALS V1 ON V1.OBJ_ID = L20.OBJ_ID AND V1.PARAM_ID = 128 AND V1.IS_DEL = 0
      JOIN VALS V2 ON V2.OBJ_ID = L20.OBJ_ID AND V2.PARAM_ID = 129 AND V2.IS_DEL = 0
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND :I$MODE = 0
      GROUP BY 1
      INTO :PERSON_ID, :DATE_MODIFY
  DO
  BEGIN

    V4 = NULL;
    V4X = NULL;
    DM4 = NULL;
    VD = NULL;
    VS = NULL;
    DMD = NULL;
    DMS = NULL;

    -- Наличие и дата изменения кодов
    DATE_P_UID1 = NULL;
    DATE_P_UID2 = NULL;
    SELECT MAX(V1570.DATE_MODIFY), MAX(V155.DATE_MODIFY)
    FROM LINKS L20
    -- Берем только родителей детей, которые есть в актуальных учебных коллективах (иначе зацепим тех, у кого ребенок есть, но коды не прописаны)
    JOIN LINKS LPC ON LPC.OBJ_ID = L20.PARENT_ID AND LPC.PARENT_TYPE_ID IN (9, 125, 187) AND LPC.DATE_DEL IS NULL
    JOIN VALS V1570 ON V1570.OBJ_ID = L20.EXT_OBJ_ID AND V1570.PARAM_ID = 1570 AND V1570.IS_DEL = 0
    JOIN VALS V155 ON V155.OBJ_ID = L20.OBJ_ID AND V155.PARAM_ID = 155 AND V155.IS_DEL = 0
    WHERE L20.OBJ_ID = :PERSON_ID AND L20.PARENT_TYPE_ID = 10 AND L20.DATE_DEL IS NULL
    INTO :DATE_P_UID1, :DATE_P_UID2;

    SELECT V128.VAL, V128.DATE_MODIFY
    FROM RDB$DATABASE
    LEFT JOIN VALS V128 ON V128.OBJ_ID = :PERSON_ID AND V128.PARAM_ID IN (59, 128) AND V128.IS_DEL = 0
    INTO :V1, :DM1;

    SELECT V129.VAL, V129.DATE_MODIFY
    FROM RDB$DATABASE
    LEFT JOIN VALS V129 ON V129.OBJ_ID = :PERSON_ID AND V129.PARAM_ID IN (60, 129) AND V129.IS_DEL = 0
    INTO :V2, :DM2;

    SELECT V130.VAL, V130.DATE_MODIFY
    FROM RDB$DATABASE
    LEFT JOIN VALS V130 ON V130.OBJ_ID = :PERSON_ID AND V130.PARAM_ID IN (61, 130) AND V130.IS_DEL = 0
    INTO :V3, :DM3;

    SELECT V155.VAL, V155.DATE_MODIFY
    FROM RDB$DATABASE
    LEFT JOIN VALS V155 ON V155.OBJ_ID = :PERSON_ID AND V155.PARAM_ID IN (267, 155) AND V155.IS_DEL = 0
    INTO :V4, :DM4;

    SELECT V2917.VAL, V2917.DATE_MODIFY
    FROM RDB$DATABASE
    LEFT JOIN VALS V2917 ON V2917.OBJ_ID = :PERSON_ID AND V2917.PARAM_ID IN (2915, 2917) AND V2917.IS_DEL = 0
    INTO :REG_ID, :REG_DM;

    -- Если родитель был добавлен давно, но ребенок вернулся в школу только что
    SELECT MAX(LP9.DATE_MODIFY)
    FROM LINKS LP10
    JOIN LINKS LP9 ON LP9.OBJ_ID = LP10.PARENT_ID AND LP9.PARENT_TYPE_ID IN (9, 125, 187) AND LP9.DATE_DEL IS NULL
    WHERE LP10.OBJ_ID = :PERSON_ID AND LP10.PARENT_TYPE_ID = 10 AND LP10.DATE_DEL IS NULL
    INTO :DMCH;

    SELECT V143.VAL, V143.DATE_MODIFY
    FROM RDB$DATABASE
    LEFT JOIN VALD V143 ON V143.OBJ_ID = :PERSON_ID AND V143.PARAM_ID = 143 AND V143.IS_DEL = 0
    INTO :VD, :DMD;

    SELECT V2544.LISTVAL_ID, V2544.DATE_MODIFY
    FROM RDB$DATABASE
    LEFT JOIN VALL V2544 ON V2544.OBJ_ID = :PERSON_ID AND V2544.PARAM_ID = 2544 AND V2544.IS_DEL = 0
    INTO :VS, :DMS;

    IF(POSITION(':' IN REG_ID) > 0) THEN REG_ID = SUBSTRING(REG_ID FROM 1 FOR POSITION(':' IN REG_ID) - 1);

    -- Если у родителя код совпадает с сотрудником, и совпадает ФИ - запарываем выдачу записи родителя
    IF(EXISTS(
        SELECT FIRST 1 1
        FROM VALS V267
        JOIN LINKS L14 ON L14.OBJ_ID = V267.OBJ_ID AND L14.PARENT_TYPE_ID = 2 AND L14.DATE_DEL IS NULL
        JOIN VALS V59 ON V59.OBJ_ID = L14.OBJ_ID AND V59.PARAM_ID = 59 AND V59.SVAL = :V1
        JOIN VALS V60 ON V60.OBJ_ID = L14.OBJ_ID AND V60.PARAM_ID = 60 AND V60.SVAL = :V2
        WHERE V267.PARAM_ID = 267 AND V267.IS_DEL = 0 AND V267.SVAL = :V4
    ))
    THEN DATE_P_UID1 = NULL;

    -- Сначала пробуем СНИЛС, потом паспорт, потом СОР
    HS = NULL;
    HSN = NULL;
    SELECT FIRST 1 REPLACE(REPLACE(V.VAL, '-', ''), ' ', ''), 1
    FROM VALS V
    WHERE V.OBJ_ID = :PERSON_ID AND V.PARAM_ID IN (1409, 2455, 2365) AND V.IS_DEL = 0
    INTO :HS, :HSN;

    IF(HS IS NULL) THEN
    SELECT FIRST 1 V1.SVAL || ' ' || V2.SVAL, 2
    FROM LINKS L79
    JOIN VALL V441 ON V441.OBJ_ID = L79.OBJ_ID AND V441.PARAM_ID = 441 AND V441.IS_DEL = 0 AND V441.LISTVAL_ID = 1368
    JOIN VALL V614 ON V614.OBJ_ID = L79.OBJ_ID AND V614.PARAM_ID = 614 AND V614.IS_DEL = 0 AND V614.LISTVAL_ID = 1982
    JOIN VALS V1 ON V1.OBJ_ID = L79.OBJ_ID AND V1.PARAM_ID = 442 AND V1.IS_DEL = 0
    JOIN VALS V2 ON V2.OBJ_ID = L79.OBJ_ID AND V2.PARAM_ID = 559 AND V2.IS_DEL = 0
    WHERE L79.PARENT_ID = :PERSON_ID AND L79.OBJ_TYPE_ID = 79 AND L79.DATE_DEL IS NULL
    INTO :HS, :HSN;

    IF(HS IS NULL) THEN
    SELECT FIRST 1 REPLACE(UPPER(V1.SVAL), '-', '') || ' ' || UPPER(V2.SVAL) || ' ' || REPLACE(D.VAL, '-', ''), 3
    FROM LINKS L79
    JOIN VALL V441 ON V441.OBJ_ID = L79.OBJ_ID AND V441.PARAM_ID = 441 AND V441.IS_DEL = 0 AND V441.LISTVAL_ID = 1370
    JOIN VALL V614 ON V614.OBJ_ID = L79.OBJ_ID AND V614.PARAM_ID = 614 AND V614.IS_DEL = 0 AND V614.LISTVAL_ID = 1982
    JOIN VALS V1 ON V1.OBJ_ID = L79.OBJ_ID AND V1.PARAM_ID = 442 AND V1.IS_DEL = 0
    JOIN VALS V2 ON V2.OBJ_ID = L79.OBJ_ID AND V2.PARAM_ID = 559 AND V2.IS_DEL = 0
    JOIN VALD V3 ON V3.OBJ_ID = L79.OBJ_ID AND V3.PARAM_ID = 560 AND V3.IS_DEL = 0
    LEFT JOIN DATE2ISO(V3.VAL, 0) D ON 1 = 1
    WHERE L79.PARENT_ID = :PERSON_ID AND L79.OBJ_TYPE_ID = 79 AND L79.DATE_DEL IS NULL
    INTO :HS, :HSN;

    IS_OK = 0;
    IF(DATE_P_UID1 IS NOT NULL AND DATE_P_UID2 IS NOT NULL AND
      (
        ((T_FROM IS NULL OR DATE_MODIFY >= T_FROM) AND (DATE_MODIFY < T_TO)) OR
        ((T_FROM IS NULL OR DM1 >= T_FROM) AND (DM1 < T_TO)) OR
        ((T_FROM IS NULL OR DM2 >= T_FROM) AND (DM2 < T_TO)) OR
        ((T_FROM IS NULL OR DM3 >= T_FROM) AND (DM3 < T_TO)) OR
        ((T_FROM IS NULL OR DM4 >= T_FROM) AND (DM4 < T_TO)) OR
        ((T_FROM IS NULL OR DMD >= T_FROM) AND (DMD < T_TO)) OR
        ((T_FROM IS NULL OR DMS >= T_FROM) AND (DMS < T_TO)) OR
        ((T_FROM IS NULL OR DMCH >= T_FROM) AND (DMCH < T_TO)) OR
        ((T_FROM IS NULL OR REG_DM >= T_FROM) AND (REG_DM < T_TO)) OR
        ((T_FROM IS NULL OR DATE_P_UID1 >= T_FROM) AND (DATE_P_UID1 < T_TO)) OR
        ((T_FROM IS NULL OR DATE_P_UID2 >= T_FROM) AND (DATE_P_UID2 < T_TO))
      )
    )
    THEN
        IS_OK = 1;

    IF(IS_OK = 1) THEN
    BEGIN

        TAG_NAME = 'wsdl&colon;PersonInput';
        VAL = NULL;
        SUSPEND;

        TAG_NAME = 'wsdl&colon;PersonInput:identity:uid';
        VAL = REG_ID;
        IF(REG_ID IS NOT NULL AND REG_ID <> '') THEN SUSPEND;

        TAG_NAME = 'wsdl&colon;PersonInput:identity:external_id';
        VAL = PERSON_ID;
        SUSPEND;

        TAG_NAME = 'wsdl&colon;PersonInput:firstname';
        VAL = COALESCE(V2, '');
        SUSPEND;

        TAG_NAME = 'wsdl&colon;PersonInput:surname';
        VAL = COALESCE(V1, '');
        SUSPEND;

        TAG_NAME = 'wsdl&colon;PersonInput:middlename';
        VAL = COALESCE(V3, '');
        SUSPEND;

        IF(V4X IS NOT NULL) THEN
        BEGIN
          TAG_NAME = 'wsdl&colon;PersonInput:esia_id';
          VAL = TRIM(COALESCE(V4X, ''));
          SUSPEND;
        END
        -- ELSE 
        IF(V4 IS NOT NULL) THEN
        BEGIN
          TAG_NAME = 'wsdl&colon;PersonInput:petrobr_id';
          VAL = COALESCE(V4, '');
          SUSPEND;
        END

        IF(VD IS NOT NULL) THEN
        BEGIN
          TAG_NAME = 'wsdl&colon;PersonInput:birth_date';
          VAL = (SELECT VAL FROM DATE2ISO(:VD, 0));
          SUSPEND;
        END

        IF(VS IS NOT NULL) THEN
        BEGIN
          TAG_NAME = 'wsdl&colon;PersonInput:sex:code';
          VAL = IIF(VS = 182, 'Ж', 'М');
          SUSPEND;
        END

        IF(HS IS NOT NULL) THEN
        BEGIN
          TAG_NAME = 'wsdl&colon;PersonInput:hash_gost2012';
          VAL = HS;
          SUSPEND;
          TAG_NAME = 'wsdl&colon;PersonInput:hash_num';
          VAL = HSN;
          SUSPEND;
        END

        N = N + 1;
        IF(N >= 10000) THEN
        BEGIN
            N = 0;
            TAG_NAME = NULL;
            VAL = 'DIVIDE';
            SUSPEND;
        END

    END

  END

  -- Уволенные сотрудники (дата увольнения не более 1 месяца до начала учебного года)
  FOR
      SELECT L14.OBJ_ID, MAX(L14.DATE_MODIFY)
      FROM LINKS L2
      JOIN LINKS L84 ON L84.PARENT_ID = L2.OBJ_ID AND L84.OBJ_TYPE_ID = 84 AND L84.DATE_DEL IS NULL
      JOIN LINKS L14 ON L14.PARENT_ID = L84.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL AND L14.DATE_INS > DATEADD(-1 MONTH TO :YEAR_START)
      -- Должны быть фамилия и имя
      JOIN VALS V1 ON V1.OBJ_ID = L14.OBJ_ID AND V1.PARAM_ID = 59 AND V1.IS_DEL = 0
      JOIN VALS V2 ON V2.OBJ_ID = L14.OBJ_ID AND V2.PARAM_ID = 60 AND V2.IS_DEL = 0
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      GROUP BY 1
      INTO :PERSON_ID, :DATE_MODIFY
  DO
  BEGIN

    V4 = NULL;
    V4X = NULL;
    DM4 = NULL;
    VD = NULL;
    VS = NULL;
    DMD = NULL;
    DMS = NULL;

    SELECT V59.VAL, V59.DATE_MODIFY
    FROM RDB$DATABASE
    LEFT JOIN VALS V59 ON V59.OBJ_ID = :PERSON_ID AND V59.PARAM_ID = 59 AND V59.IS_DEL = 0
    INTO :V1, :DM1;

    SELECT V60.VAL, V60.DATE_MODIFY
    FROM RDB$DATABASE
    LEFT JOIN VALS V60 ON V60.OBJ_ID = :PERSON_ID AND V60.PARAM_ID = 60 AND V60.IS_DEL = 0
    INTO :V2, :DM2;

    SELECT V61.VAL, V61.DATE_MODIFY
    FROM RDB$DATABASE
    LEFT JOIN VALS V61 ON V61.OBJ_ID = :PERSON_ID AND V61.PARAM_ID = 61 AND V61.IS_DEL = 0
    INTO :V3, :DM3;

    SELECT V267.VAL, V267.DATE_MODIFY
    FROM RDB$DATABASE
    LEFT JOIN VALS V267 ON V267.OBJ_ID = :PERSON_ID AND V267.PARAM_ID = 267 AND V267.IS_DEL = 0
    INTO :V4, :DM4;

    SELECT V3061.VAL, V3061.DATE_MODIFY
    FROM RDB$DATABASE
    LEFT JOIN VALS V3061 ON V3061.OBJ_ID = :PERSON_ID AND V3061.PARAM_ID = 3061 AND V3061.IS_DEL = 0
    INTO :V4X, :DM4X;

    SELECT V2915.VAL, V2915.DATE_MODIFY
    FROM RDB$DATABASE
    LEFT JOIN VALS V2915 ON V2915.OBJ_ID = :PERSON_ID AND V2915.PARAM_ID = 2915 AND V2915.IS_DEL = 0
    INTO :REG_ID, :REG_DM;

    SELECT V241.VAL, V241.DATE_MODIFY
    FROM RDB$DATABASE
    LEFT JOIN VALD V241 ON V241.OBJ_ID = :PERSON_ID AND V241.PARAM_ID = 241 AND V241.IS_DEL = 0
    INTO :VD, :DMD;

    SELECT V239.LISTVAL_ID, V239.DATE_MODIFY
    FROM RDB$DATABASE
    LEFT JOIN VALL V239 ON V239.OBJ_ID = :PERSON_ID AND V239.PARAM_ID = 239 AND V239.IS_DEL = 0
    INTO :VS, :DMS;

    IF(POSITION(':' IN REG_ID) > 0) THEN REG_ID = SUBSTRING(REG_ID FROM 1 FOR POSITION(':' IN REG_ID) - 1);

    -- Сначала пробуем СНИЛС, потом паспорт, потом СОР
    HS = NULL;
    HSN = NULL;
    SELECT FIRST 1 REPLACE(REPLACE(V.VAL, '-', ''), ' ', ''), 1
    FROM VALS V
    WHERE V.OBJ_ID = :PERSON_ID AND V.PARAM_ID IN (1409, 2455, 2365) AND V.IS_DEL = 0
    INTO :HS, :HSN;

    IF(HS IS NULL) THEN
    SELECT FIRST 1 V1.SVAL || ' ' || V2.SVAL, 2
    FROM LINKS L79
    JOIN VALL V441 ON V441.OBJ_ID = L79.OBJ_ID AND V441.PARAM_ID = 441 AND V441.IS_DEL = 0 AND V441.LISTVAL_ID = 1368
    JOIN VALL V614 ON V614.OBJ_ID = L79.OBJ_ID AND V614.PARAM_ID = 614 AND V614.IS_DEL = 0 AND V614.LISTVAL_ID = 1982
    JOIN VALS V1 ON V1.OBJ_ID = L79.OBJ_ID AND V1.PARAM_ID = 442 AND V1.IS_DEL = 0
    JOIN VALS V2 ON V2.OBJ_ID = L79.OBJ_ID AND V2.PARAM_ID = 559 AND V2.IS_DEL = 0
    WHERE L79.PARENT_ID = :PERSON_ID AND L79.OBJ_TYPE_ID = 79 AND L79.DATE_DEL IS NULL
    INTO :HS, :HSN;

    IF(HS IS NULL) THEN
    SELECT FIRST 1 REPLACE(UPPER(V1.SVAL), '-', '') || ' ' || UPPER(V2.SVAL) || ' ' || REPLACE(D.VAL, '-', ''), 3
    FROM LINKS L79
    JOIN VALL V441 ON V441.OBJ_ID = L79.OBJ_ID AND V441.PARAM_ID = 441 AND V441.IS_DEL = 0 AND V441.LISTVAL_ID = 1370
    JOIN VALL V614 ON V614.OBJ_ID = L79.OBJ_ID AND V614.PARAM_ID = 614 AND V614.IS_DEL = 0 AND V614.LISTVAL_ID = 1982
    JOIN VALS V1 ON V1.OBJ_ID = L79.OBJ_ID AND V1.PARAM_ID = 442 AND V1.IS_DEL = 0
    JOIN VALS V2 ON V2.OBJ_ID = L79.OBJ_ID AND V2.PARAM_ID = 559 AND V2.IS_DEL = 0
    JOIN VALD V3 ON V3.OBJ_ID = L79.OBJ_ID AND V3.PARAM_ID = 560 AND V3.IS_DEL = 0
    LEFT JOIN DATE2ISO(V3.VAL, 0) D ON 1 = 1
    WHERE L79.PARENT_ID = :PERSON_ID AND L79.OBJ_TYPE_ID = 79 AND L79.DATE_DEL IS NULL
    INTO :HS, :HSN;

    IS_OK = 0;
    IF(
        ((T_FROM IS NULL OR DATE_MODIFY >= T_FROM) AND (DATE_MODIFY < T_TO)) OR
        ((T_FROM IS NULL OR DM1 >= T_FROM) AND (DM1 < T_TO)) OR
        ((T_FROM IS NULL OR DM2 >= T_FROM) AND (DM2 < T_TO)) OR
        ((T_FROM IS NULL OR DM3 >= T_FROM) AND (DM3 < T_TO)) OR
        ((T_FROM IS NULL OR DM4 >= T_FROM) AND (DM4 < T_TO)) OR
        ((T_FROM IS NULL OR DM4X >= T_FROM) AND (DM4X < T_TO)) OR
        ((T_FROM IS NULL OR DMD >= T_FROM) AND (DMD < T_TO)) OR
        ((T_FROM IS NULL OR DMS >= T_FROM) AND (DMS < T_TO)) OR
        ((T_FROM IS NULL OR REG_DM >= T_FROM) AND (REG_DM < T_TO))
    )
    THEN
        IS_OK = 1;

    IF(IS_OK = 1) THEN
    BEGIN

        TAG_NAME = 'wsdl&colon;PersonInput';
        VAL = NULL;
        SUSPEND;

        TAG_NAME = 'wsdl&colon;PersonInput:identity:uid';
        VAL = REG_ID;
        IF(REG_ID IS NOT NULL AND REG_ID <> '') THEN SUSPEND;

        TAG_NAME = 'wsdl&colon;PersonInput:identity:external_id';
        VAL = PERSON_ID;
        SUSPEND;

        TAG_NAME = 'wsdl&colon;PersonInput:firstname';
        VAL = COALESCE(V2, '');
        SUSPEND;

        TAG_NAME = 'wsdl&colon;PersonInput:surname';
        VAL = COALESCE(V1, '');
        SUSPEND;

        TAG_NAME = 'wsdl&colon;PersonInput:middlename';
        VAL = COALESCE(V3, '');
        SUSPEND;

        IF(V4X IS NOT NULL) THEN
        BEGIN
          TAG_NAME = 'wsdl&colon;PersonInput:esia_id';
          VAL = TRIM(COALESCE(V4X, ''));
          SUSPEND;
        END
        -- ELSE
        IF(V4 IS NOT NULL) THEN
        BEGIN
          TAG_NAME = 'wsdl&colon;PersonInput:petrobr_id';
          VAL = COALESCE(V4, '');
          SUSPEND;
        END

        IF(VD IS NOT NULL) THEN
        BEGIN
          TAG_NAME = 'wsdl&colon;PersonInput:birth_date';
          VAL = (SELECT VAL FROM DATE2ISO(:VD, 0));
          SUSPEND;
        END

        IF(VS IS NOT NULL) THEN
        BEGIN
          TAG_NAME = 'wsdl&colon;PersonInput:sex:code';
          VAL = IIF(VS = 182, 'Ж', 'М');
          SUSPEND;
        END

        IF(HS IS NOT NULL) THEN
        BEGIN
          TAG_NAME = 'wsdl&colon;PersonInput:hash_gost2012';
          VAL = HS;
          SUSPEND;
          TAG_NAME = 'wsdl&colon;PersonInput:hash_num';
          VAL = HSN;
          SUSPEND;
        END

        N = N + 1;
        IF(N >= 10000) THEN
        BEGIN
            N = 0;
            TAG_NAME = NULL;
            VAL = 'DIVIDE';
            SUSPEND;
        END

    END

  END

  -- Выбывшие, окончившие ученики (только текущий учебный год или календарный год)
  -- Как бы не потерять потенциально выбывших в сентябре прошлым учебным годом
  FOR
      -- Выбывшие в текущем учебном году
      SELECT L10.OBJ_ID, L10.DATE_MODIFY
      FROM LINKS L2
      JOIN LINKS L78 ON L78.PARENT_ID = L2.OBJ_ID AND L78.OBJ_TYPE_ID = 78 AND L78.DATE_DEL IS NULL
      JOIN LINKS L82 ON L82.PARENT_ID = L78.OBJ_ID AND L82.OBJ_TYPE_ID = 82 AND L82.DATE_DEL IS NULL
      JOIN VALI V448 ON V448.OBJ_ID = L82.OBJ_ID AND V448.PARAM_ID = 448 AND V448.IS_DEL = 0 AND V448.VAL = EXTRACT(YEAR FROM :YEAR_START)
      JOIN LINKS L10 ON L10.PARENT_ID = L82.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      -- Должны быть фамилия и имя
      JOIN VALS V1 ON V1.OBJ_ID = L10.OBJ_ID AND V1.PARAM_ID = 55 AND V1.IS_DEL = 0
      JOIN VALS V2 ON V2.OBJ_ID = L10.OBJ_ID AND V2.PARAM_ID = 56 AND V2.IS_DEL = 0
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      -- Выпуск календарного года #83+#451, этих вообще не смотрим
      INTO :PERSON_ID, :DATE_MODIFY
  DO
  BEGIN

    V4 = NULL;
    V4X = NULL;
    DM4 = NULL;
    VD = NULL;
    VS = NULL;
    DMD = NULL;
    DMS = NULL;

    -- Числился ли ученик в группе ЦОПП
    V$COPP = 3;
    SELECT MIN(V3063.LISTVAL_ID)
    FROM LINKS LP9
    JOIN VALL V3063 ON V3063.OBJ_ID = LP9.PARENT_ID AND V3063.PARAM_ID = 3063 AND V3063.IS_DEL = 0
    WHERE LP9.OBJ_ID = :PERSON_ID AND LP9.PARENT_TYPE_ID = 9
    INTO :V$COPP;

    SELECT V55.VAL, V55.DATE_MODIFY
    FROM RDB$DATABASE
    LEFT JOIN VALS V55 ON V55.OBJ_ID = :PERSON_ID AND V55.PARAM_ID = 55 AND V55.IS_DEL = 0
    INTO :V1, :DM1;

    SELECT V56.VAL, V56.DATE_MODIFY
    FROM RDB$DATABASE
    LEFT JOIN VALS V56 ON V56.OBJ_ID = :PERSON_ID AND V56.PARAM_ID = 56 AND V56.IS_DEL = 0
    INTO :V2, :DM2;

    SELECT V57.VAL, V57.DATE_MODIFY
    FROM RDB$DATABASE
    LEFT JOIN VALS V57 ON V57.OBJ_ID = :PERSON_ID AND V57.PARAM_ID = 57 AND V57.IS_DEL = 0
    INTO :V3, :DM3;

    SELECT V3060.VAL, V3060.DATE_MODIFY
    FROM RDB$DATABASE
    LEFT JOIN VALS V3060 ON V3060.OBJ_ID = :PERSON_ID AND V3060.PARAM_ID = 3060 AND V3060.IS_DEL = 0
    INTO :V4X, :DM4X;

    SELECT V2912.VAL, V2912.DATE_MODIFY
    FROM RDB$DATABASE
    LEFT JOIN VALS V2912 ON V2912.OBJ_ID = :PERSON_ID AND V2912.PARAM_ID = 2912 AND V2912.IS_DEL = 0
    INTO :REG_ID, :REG_DM;

    SELECT V89.VAL, V89.DATE_MODIFY
    FROM RDB$DATABASE
    LEFT JOIN VALD V89 ON V89.OBJ_ID = :PERSON_ID AND V89.PARAM_ID = 89 AND V89.IS_DEL = 0
    INTO :VD, :DMD;

    SELECT V88.LISTVAL_ID, V88.DATE_MODIFY
    FROM RDB$DATABASE
    LEFT JOIN VALL V88 ON V88.OBJ_ID = :PERSON_ID AND V88.PARAM_ID = 88 AND V88.IS_DEL = 0
    INTO :VS, :DMS;

    IF(POSITION(':' IN REG_ID) > 0) THEN REG_ID = SUBSTRING(REG_ID FROM 1 FOR POSITION(':' IN REG_ID) - 1);

    -- Сначала пробуем СНИЛС, потом паспорт, потом СОР
    HS = NULL;
    HSN = NULL;
    SELECT FIRST 1 REPLACE(REPLACE(V.VAL, '-', ''), ' ', ''), 1
    FROM VALS V
    WHERE V.OBJ_ID = :PERSON_ID AND V.PARAM_ID IN (1409, 2455, 2365) AND V.IS_DEL = 0
    INTO :HS, :HSN;

    IF(HS IS NULL) THEN
    SELECT FIRST 1 V1.SVAL || ' ' || V2.SVAL, 2
    FROM LINKS L79
    JOIN VALL V441 ON V441.OBJ_ID = L79.OBJ_ID AND V441.PARAM_ID = 441 AND V441.IS_DEL = 0 AND V441.LISTVAL_ID = 1368
    JOIN VALL V614 ON V614.OBJ_ID = L79.OBJ_ID AND V614.PARAM_ID = 614 AND V614.IS_DEL = 0 AND V614.LISTVAL_ID = 1982
    JOIN VALS V1 ON V1.OBJ_ID = L79.OBJ_ID AND V1.PARAM_ID = 442 AND V1.IS_DEL = 0
    JOIN VALS V2 ON V2.OBJ_ID = L79.OBJ_ID AND V2.PARAM_ID = 559 AND V2.IS_DEL = 0
    WHERE L79.PARENT_ID = :PERSON_ID AND L79.OBJ_TYPE_ID = 79 AND L79.DATE_DEL IS NULL
    INTO :HS, :HSN;

    IF(HS IS NULL) THEN
    SELECT FIRST 1 REPLACE(UPPER(V1.SVAL), '-', '') || ' ' || UPPER(V2.SVAL) || ' ' || REPLACE(D.VAL, '-', ''), 3
    FROM LINKS L79
    JOIN VALL V441 ON V441.OBJ_ID = L79.OBJ_ID AND V441.PARAM_ID = 441 AND V441.IS_DEL = 0 AND V441.LISTVAL_ID = 1370
    JOIN VALL V614 ON V614.OBJ_ID = L79.OBJ_ID AND V614.PARAM_ID = 614 AND V614.IS_DEL = 0 AND V614.LISTVAL_ID = 1982
    JOIN VALS V1 ON V1.OBJ_ID = L79.OBJ_ID AND V1.PARAM_ID = 442 AND V1.IS_DEL = 0
    JOIN VALS V2 ON V2.OBJ_ID = L79.OBJ_ID AND V2.PARAM_ID = 559 AND V2.IS_DEL = 0
    JOIN VALD V3 ON V3.OBJ_ID = L79.OBJ_ID AND V3.PARAM_ID = 560 AND V3.IS_DEL = 0
    LEFT JOIN DATE2ISO(V3.VAL, 0) D ON 1 = 1
    WHERE L79.PARENT_ID = :PERSON_ID AND L79.OBJ_TYPE_ID = 79 AND L79.DATE_DEL IS NULL
    INTO :HS, :HSN;

    IS_OK = 0;
    IF(
        ((T_FROM IS NULL OR DATE_MODIFY >= T_FROM) AND (DATE_MODIFY < T_TO)) OR
        ((T_FROM IS NULL OR DM1 >= T_FROM) AND (DM1 < T_TO)) OR
        ((T_FROM IS NULL OR DM2 >= T_FROM) AND (DM2 < T_TO)) OR
        ((T_FROM IS NULL OR DM3 >= T_FROM) AND (DM3 < T_TO)) OR
        ((T_FROM IS NULL OR DM4 >= T_FROM) AND (DM4 < T_TO)) OR
        ((T_FROM IS NULL OR DMD >= T_FROM) AND (DMD < T_TO)) OR
        ((T_FROM IS NULL OR DMS >= T_FROM) AND (DMS < T_TO)) OR
        ((T_FROM IS NULL OR REG_DM >= T_FROM) AND (REG_DM < T_TO))
    )
    THEN
        IS_OK = 1;

    -- В ЦОПП запарываем выдачу ученика, если у нас уже есть как сотрудник
    IF(I$MODE = 1 AND EXISTS(
        SELECT FIRST 1 1
        FROM VALS V3061
        WHERE V3061.PARAM_ID = 3061 AND V3061.IS_DEL = 0 AND V3061.SVAL = :V4X
    ))
    THEN IS_OK = 0;

    IF(IS_OK = 1) THEN
    BEGIN

        TAG_NAME = 'wsdl&colon;PersonInput';
        VAL = NULL;
        SUSPEND;

        TAG_NAME = 'wsdl&colon;PersonInput:identity:uid';
        VAL = REG_ID;
        IF(REG_ID IS NOT NULL AND REG_ID <> '') THEN SUSPEND;

        TAG_NAME = 'wsdl&colon;PersonInput:identity:external_id';
        VAL = PERSON_ID;
        SUSPEND;

        TAG_NAME = 'wsdl&colon;PersonInput:firstname';
        VAL = COALESCE(V2, '');
        SUSPEND;

        TAG_NAME = 'wsdl&colon;PersonInput:surname';
        VAL = COALESCE(V1, '');
        SUSPEND;

        TAG_NAME = 'wsdl&colon;PersonInput:middlename';
        VAL = COALESCE(V3, '');
        SUSPEND;

        -- Для учеников только ЕСИА (ЦОПП)
        IF(V4X IS NOT NULL) THEN
        BEGIN
          TAG_NAME = 'wsdl&colon;PersonInput:esia_id';
          VAL = TRIM(COALESCE(V4X, ''));
          SUSPEND;
        END

        IF(VD IS NOT NULL) THEN
        BEGIN
          TAG_NAME = 'wsdl&colon;PersonInput:birth_date';
          VAL = (SELECT VAL FROM DATE2ISO(:VD, 0));
          SUSPEND;
        END

        IF(VS IS NOT NULL) THEN
        BEGIN
          TAG_NAME = 'wsdl&colon;PersonInput:sex:code';
          VAL = IIF(VS = 182, 'Ж', 'М');
          SUSPEND;
        END

        IF(HS IS NOT NULL) THEN
        BEGIN
          TAG_NAME = 'wsdl&colon;PersonInput:hash_gost2012';
          VAL = HS;
          SUSPEND;
          TAG_NAME = 'wsdl&colon;PersonInput:hash_num';
          VAL = HSN;
          SUSPEND;
        END

        N = N + 1;
        IF(N >= 10000) THEN
        BEGIN
            N = 0;
            TAG_NAME = NULL;
            VAL = 'DIVIDE';
            SUSPEND;
        END

    END

  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_PORTAL_PERSONS_DELETE (
    T_FROM TIMESTAMP,
    T_TO TIMESTAMP NOT NULL,
    ID1 VARCHAR(40) = null,
    ID2 VARCHAR(40) = null,
    I$MODE SMALLINT = 0)
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(2000))
AS
begin

  IF(T_FROM IS NULL) THEN EXIT;

  -- Сотрудники, уволенные более года назад
  -- Пока пропускаем

  -- Актуальные ученики, у которых затерли коды выгрузки, либо выбывшие более года назад

  -- Представители учеников с затертыми кодами или выбывших более года назад

    IF(0 = 1) THEN SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_PORTAL_PORTFOLIO (
    T_FROM TIMESTAMP,
    T_TO TIMESTAMP NOT NULL = current_timestamp,
    ID1 VARCHAR(40) = null,
    ID2 VARCHAR(40) = null,
    I$MODE SMALLINT = 0)
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(4000))
AS
declare variable STUDENT_ID bigint;
declare variable STUDENT_DT timestamp;
declare variable DATE_P_UID1 timestamp;
declare variable DATE_P_UID2 timestamp;
declare variable IS_OK smallint;
declare variable IS_FORCE smallint;
declare variable YEAR_START date;
declare variable EVENT_ID bigint;
declare variable EVENT_DT timestamp;
declare variable EVENT_NAME varchar(4000);
declare variable EVENT_NAME_DT timestamp;
declare variable EVENT_DATE date;
declare variable EVENT_DATE_DT timestamp;
declare variable EVENT_RES varchar(4000);
declare variable EVENT_RES_DT timestamp;
declare variable DM4X timestamp;
declare variable N integer;
declare variable V4X varchar(100);
declare variable DB varchar(400);
declare variable V$OBJ_ID bigint;
declare variable V$NUM varchar(100);
begin

  IF(EXTRACT(MONTH FROM CURRENT_DATE) < 8 OR (EXTRACT(MONTH FROM CURRENT_DATE) = 8 AND EXTRACT(DAY FROM CURRENT_DATE) < 31)) THEN
    YEAR_START = '31.08.' || (EXTRACT(YEAR FROM CURRENT_DATE) - 1);
  ELSE
    YEAR_START = '31.08.' || EXTRACT(YEAR FROM CURRENT_DATE);

  SELECT MON$DATABASE_NAME FROM MON$DATABASE INTO :DB;
  DB = REPLACE(DB, 'BASE.FDB', 'DOC.FDB');

  N = 0;

  -- Действующие учащиеся
  FOR
      SELECT L10.OBJ_ID, L10.DATE_MODIFY
      FROM LINKS L2
      -- Уровень образования
      JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
      -- Этап обучения
      JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
      -- Класс
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 125, 187) AND L9.DATE_DEL IS NULL
      -- Признак группы ЦОПП
      LEFT JOIN VALL V3063 ON V3063.OBJ_ID = L9.OBJ_ID AND V3063.PARAM_ID = 3063 AND V3063.IS_DEL = 0
      JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      INTO :STUDENT_ID, :STUDENT_DT
  DO
  BEGIN

      -- Наличие и дата изменения кодов - выгружаем только данные по учащимся, у которых есть портальные идентификаторы
      DATE_P_UID1 = NULL;
      DATE_P_UID2 = NULL;
      SELECT MAX(V1570.DATE_MODIFY), MAX(V155.DATE_MODIFY)
      FROM LINKS L20
      JOIN VALS V1570 ON V1570.OBJ_ID = L20.EXT_OBJ_ID AND V1570.PARAM_ID = 1570 AND V1570.IS_DEL = 0
      JOIN VALS V155 ON V155.OBJ_ID = L20.OBJ_ID AND V155.PARAM_ID = 155 AND V155.IS_DEL = 0
      WHERE L20.PARENT_ID = :STUDENT_ID AND L20.OBJ_TYPE_ID = 20 AND L20.DATE_DEL IS NULL
      INTO :DATE_P_UID1, :DATE_P_UID2;

      SELECT V3060.SVAL, V3060.DATE_MODIFY
      FROM RDB$DATABASE
      LEFT JOIN VALS V3060 ON V3060.OBJ_ID = :STUDENT_ID AND V3060.PARAM_ID = 3060 AND V3060.IS_DEL = 0
      INTO :V4X, :DM4X;

      -- В ЦОПП заменяем код ученика на код сотрудника, если он же внесен
      IF(I$MODE = 1) THEN
      BEGIN
          SELECT FIRST 1 V3061.OBJ_ID
          FROM VALS V3061
          WHERE V3061.PARAM_ID = 3061 AND V3061.IS_DEL = 0 AND V3061.SVAL = :V4X
          INTO :STUDENT_ID;
      END

      IS_FORCE = 0;
      IF(((DATE_P_UID1 IS NOT NULL AND DATE_P_UID2 IS NOT NULL AND I$MODE = 0) OR (DM4X IS NOT NULL AND I$MODE = 1)) AND
        (
          ((T_FROM IS NULL OR STUDENT_DT >= T_FROM) AND (STUDENT_DT < T_TO)) OR
          ((T_FROM IS NULL OR DATE_P_UID1 >= T_FROM) AND (DATE_P_UID1 < T_TO)) OR
          ((T_FROM IS NULL OR DATE_P_UID2 >= T_FROM) AND (DATE_P_UID2 < T_TO)) OR
          ((T_FROM IS NULL OR DM4X >= T_FROM) AND (DM4X < T_TO))
        )
      )
      THEN
          IS_FORCE = 1;

      -- Идем по всем достижениям и смотрим изменения
      FOR
          SELECT L22.OBJ_ID, L22.DATE_MODIFY, V1818.VAL, V1818.DATE_MODIFY, V166.VAL, V166.DATE_MODIFY, R.VAL, V237.DATE_MODIFY
          FROM LINKS L22
          JOIN VALS V1818 ON V1818.OBJ_ID = L22.OBJ_ID AND V1818.PARAM_ID = 1818 AND V1818.IS_DEL = 0
          JOIN VALD V166 ON V166.OBJ_ID = L22.OBJ_ID AND V166.PARAM_ID = 166 AND V166.IS_DEL = 0
          JOIN VALL V237 ON V237.OBJ_ID = L22.OBJ_ID AND V237.PARAM_ID = 237 AND V237.IS_DEL = 0
          JOIN LISTVALS LV ON LV.LISTVAL_ID = V237.LISTVAL_ID
          JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
          WHERE L22.PARENT_ID = :STUDENT_ID AND L22.OBJ_TYPE_ID = 22 AND L22.DATE_DEL IS NULL AND
            ((:DATE_P_UID1 IS NOT NULL AND :DATE_P_UID2 IS NOT NULL AND :I$MODE = 0) OR (:DM4X IS NOT NULL AND :I$MODE = 1))
          INTO :EVENT_ID, :EVENT_DT, :EVENT_NAME, :EVENT_NAME_DT, :EVENT_DATE, :EVENT_DATE_DT, :EVENT_RES, :EVENT_RES_DT
      DO
      BEGIN

          IS_OK = 0;

          IF(IS_FORCE = 1 OR
            (
              ((T_FROM IS NULL OR EVENT_DT >= T_FROM) AND (EVENT_DT < T_TO)) OR
              ((T_FROM IS NULL OR EVENT_NAME_DT >= T_FROM) AND (EVENT_NAME_DT < T_TO)) OR
              ((T_FROM IS NULL OR EVENT_DATE_DT >= T_FROM) AND (EVENT_DATE_DT < T_TO)) OR
              ((T_FROM IS NULL OR EVENT_RES_DT >= T_FROM) AND (EVENT_RES_DT < T_TO))
            )
          )
          THEN
              IS_OK = 1;

          IF(IS_OK = 1) THEN
          BEGIN

              TAG_NAME = 'wsdl&colon;PortfolioInput';
              VAL = NULL;
              SUSPEND;

              TAG_NAME = 'wsdl&colon;PortfolioInput:identity:external_id';
              VAL = EVENT_ID;
              SUSPEND;

              TAG_NAME = 'wsdl&colon;PortfolioInput:name';
              VAL = EVENT_NAME;
              SUSPEND;

              TAG_NAME = 'wsdl&colon;PortfolioInput:result';
              VAL = EVENT_RES;
              SUSPEND;

              TAG_NAME = 'wsdl&colon;PortfolioInput:datetime';
              VAL = (SELECT VAL FROM DATE2ISO(:EVENT_DATE));
              SUSPEND;

              TAG_NAME = 'wsdl&colon;PortfolioInput:person_id:external_id';
              VAL = STUDENT_ID;
              SUSPEND;

              N = N + 1;
              IF(N >= 10000) THEN
              BEGIN
                  N = 0;
                  TAG_NAME = NULL;
                  VAL = 'DIVIDE';
                  SUSPEND;
              END

          END

      END

      -- Документы об образовании персоны - их тут может быть ограниченное количество
      -- фактически ограничиваем выборку 2 штуками, по одному на каждый уровень образования
      EVENT_ID = NULL;
      EXECUTE STATEMENT 'SELECT FIRST 1 D.OBJ_ID, D.DATE_MODIFY, T.VAL, D.ORDER_ID, P.SERIE || B.BLANK_NUM
        FROM DOCUMENTS D
        JOIN BLANK_TYPES T ON T.LISTVAL_ID = D.DOC_TYPE_ID
        JOIN BLANKS B ON B.OBJ_ID = D.BLANK_ID
        JOIN BLANK_PACKS P ON P.OBJ_ID = B.PACK_ID
        WHERE D.DATE_DEL IS NULL AND D.PERSON_ID = ' || STUDENT_ID || ' AND D.DOC_TYPE_ID IN (5377, 5378) AND D.STATE_ID IN (1, 4)
        ORDER BY D.DATE_ADD DESC'
      ON EXTERNAL :DB
      WITH COMMON TRANSACTION
      INTO :EVENT_ID, :EVENT_DT, :EVENT_NAME, :V$OBJ_ID, :V$NUM;

      IF(EVENT_ID IS NOT NULL AND ((:DATE_P_UID1 IS NOT NULL AND :DATE_P_UID2 IS NOT NULL AND :I$MODE = 0) OR (:DM4X IS NOT NULL AND :I$MODE = 1))) THEN
      BEGIN
          IS_OK = 0;

          IF(IS_FORCE = 1 OR
            ((T_FROM IS NULL OR EVENT_DT >= T_FROM) AND (EVENT_DT < T_TO))
          )
          THEN
              IS_OK = 1;

          IF(IS_OK = 1) THEN
          BEGIN

              TAG_NAME = 'wsdl&colon;PortfolioInput';
              VAL = NULL;
              SUSPEND;

              TAG_NAME = 'wsdl&colon;PortfolioInput:identity:external_id';
              VAL = 'att' || EVENT_ID;
              SUSPEND;

              TAG_NAME = 'wsdl&colon;PortfolioInput:name';
              VAL = EVENT_NAME;
              SUSPEND;

              TAG_NAME = 'wsdl&colon;PortfolioInput:result';
              VAL = V$NUM || ' Санкт-Петербург';
              SUSPEND;

              TAG_NAME = 'wsdl&colon;PortfolioInput:datetime';
              -- Вытаскиваем дату выдачи из приказа
              SELECT D.ACTION_DATE
              FROM ORDERS D
              WHERE D.OBJ_ID = :V$OBJ_ID
              INTO :EVENT_DATE;
              VAL = (SELECT VAL FROM DATE2ISO(:EVENT_DATE));
              SUSPEND;

              TAG_NAME = 'wsdl&colon;PortfolioInput:person_id:external_id';
              VAL = STUDENT_ID;
              SUSPEND;

              N = N + 1;
              IF(N >= 10000) THEN
              BEGIN
                  N = 0;
                  TAG_NAME = NULL;
                  VAL = 'DIVIDE';
                  SUSPEND;
              END
          END
      END

      EVENT_ID = NULL;
      EXECUTE STATEMENT 'SELECT FIRST 1 D.OBJ_ID, D.DATE_MODIFY, T.VAL, D.ORDER_ID, P.SERIE || B.BLANK_NUM
        FROM DOCUMENTS D
        JOIN BLANK_TYPES T ON T.LISTVAL_ID = D.DOC_TYPE_ID
        JOIN BLANKS B ON B.OBJ_ID = D.BLANK_ID
        JOIN BLANK_PACKS P ON P.OBJ_ID = B.PACK_ID
        WHERE D.DATE_DEL IS NULL AND D.PERSON_ID = ' || STUDENT_ID || ' AND D.DOC_TYPE_ID IN (5379, 5380, 5385) AND D.STATE_ID IN (1, 4)
        ORDER BY D.DATE_ADD DESC'
      ON EXTERNAL :DB
      WITH COMMON TRANSACTION
      INTO :EVENT_ID, :EVENT_DT, :EVENT_NAME, :V$OBJ_ID, :V$NUM;

      IF(EVENT_ID IS NOT NULL AND ((:DATE_P_UID1 IS NOT NULL AND :DATE_P_UID2 IS NOT NULL AND :I$MODE = 0) OR (:DM4X IS NOT NULL AND :I$MODE = 1))) THEN
      BEGIN
          IS_OK = 0;

          IF(IS_FORCE = 1 OR
            ((T_FROM IS NULL OR EVENT_DT >= T_FROM) AND (EVENT_DT < T_TO))
          )
          THEN
              IS_OK = 1;

          IF(IS_OK = 1) THEN
          BEGIN

              TAG_NAME = 'wsdl&colon;PortfolioInput';
              VAL = NULL;
              SUSPEND;

              TAG_NAME = 'wsdl&colon;PortfolioInput:identity:external_id';
              VAL = 'att' || EVENT_ID;
              SUSPEND;

              TAG_NAME = 'wsdl&colon;PortfolioInput:name';
              VAL = EVENT_NAME;
              SUSPEND;

              TAG_NAME = 'wsdl&colon;PortfolioInput:result';
              VAL = V$NUM || ' Санкт-Петербург';
              SUSPEND;

              TAG_NAME = 'wsdl&colon;PortfolioInput:datetime';
              -- Вытаскиваем дату выдачи из приказа
              SELECT D.ACTION_DATE
              FROM ORDERS D
              WHERE D.OBJ_ID = :V$OBJ_ID
              INTO :EVENT_DATE;
              VAL = (SELECT VAL FROM DATE2ISO(:EVENT_DATE));
              SUSPEND;

              TAG_NAME = 'wsdl&colon;PortfolioInput:person_id:external_id';
              VAL = STUDENT_ID;
              SUSPEND;

              N = N + 1;
              IF(N >= 10000) THEN
              BEGIN
                  N = 0;
                  TAG_NAME = NULL;
                  VAL = 'DIVIDE';
                  SUSPEND;
              END
          END
      END

  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_PORTAL_PORTFOLIO_DELETE (
    T_FROM TIMESTAMP,
    T_TO TIMESTAMP NOT NULL = current_timestamp,
    ID1 VARCHAR(40) = null,
    ID2 VARCHAR(40) = null,
    I$MODE SMALLINT = 0)
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(2000))
AS
declare variable N integer;
declare variable N_REFS integer;
declare variable PERSON_ID bigint;
declare variable EVENT_ID bigint;
declare variable EVENT_DT timestamp;
declare variable V$COPP bigint;
begin

  IF(T_FROM IS NULL) THEN EXIT;

  N = 0;

  -- Действующие учащиеся, удаленные элементы портфолио
  FOR
      SELECT L10.OBJ_ID
      FROM LINKS L2
      JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
      JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 125, 187) AND L9.DATE_DEL IS NULL
      JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      INTO :PERSON_ID
  DO
  BEGIN

      -- Были ли в природе родители с полным набором кодов ?
      SELECT COUNT(*)
      FROM LINKS L20
      JOIN VALS V1570 ON V1570.OBJ_ID = L20.EXT_OBJ_ID AND V1570.PARAM_ID = 1570
      JOIN VALS V155 ON V155.OBJ_ID = L20.OBJ_ID AND V155.PARAM_ID = 155
      WHERE L20.PARENT_ID = :PERSON_ID AND L20.OBJ_TYPE_ID = 20
      INTO :N_REFS;

      -- Числится ли ученик в группе ЦОПП
      V$COPP = 3;
      SELECT MIN(V3063.LISTVAL_ID)
      FROM LINKS LP9
      JOIN VALL V3063 ON V3063.OBJ_ID = LP9.PARENT_ID AND V3063.PARAM_ID = 3063 AND V3063.IS_DEL = 0
      WHERE LP9.OBJ_ID = :PERSON_ID AND LP9.PARENT_TYPE_ID = 9 AND LP9.DATE_DEL IS NULL
      INTO :V$COPP;

      -- При выгрузке ЦОПП имитируем наличие кодов
      IF(V$COPP = 2) THEN
      BEGIN
          IF(I$MODE = 0) THEN N_REFS = 0; ELSE N_REFS = 1;
      END

      FOR
          SELECT L22.OBJ_ID, L22.DATE_MODIFY
          FROM LINKS L22
          WHERE L22.PARENT_ID = :PERSON_ID AND L22.OBJ_TYPE_ID = 22 AND L22.DATE_DEL IS NOT NULL AND :N_REFS > 0
          INTO :EVENT_ID, :EVENT_DT
      DO
      BEGIN

          IF(T_FROM IS NULL OR EVENT_DT >= T_FROM) THEN
          BEGIN

              TAG_NAME = 'wsdl&colon;IdentityElementInput';
              VAL = NULL;
              SUSPEND;

              TAG_NAME = 'wsdl&colon;IdentityElementInput:identity:external_id';
              VAL = EVENT_ID;
              SUSPEND;

              N = N + 1;
              IF(N >= 10000) THEN
              BEGIN
              N = 0;
                  TAG_NAME = NULL;
                  VAL = 'DIVIDE';
                  SUSPEND;
              END

          END

      END

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_PORTAL_REPRESENTATIVES (
    T_FROM TIMESTAMP,
    T_TO TIMESTAMP NOT NULL = current_timestamp,
    ID1 VARCHAR(40) = null,
    ID2 VARCHAR(40) = null,
    I$MODE SMALLINT = 0)
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(2000))
AS
declare variable STUDENT_ID bigint;
declare variable REP_ID bigint;
declare variable LINK_ID bigint;
declare variable IS_OK smallint;
declare variable DATE_MODIFY timestamp;
declare variable REP_DATE_MODIFY timestamp;
declare variable DATE_P_UID1 timestamp;
declare variable DATE_P_UID2 timestamp;
declare variable REL_CODE bigint;
declare variable REL_NAME varchar(400);
declare variable REL_MODIFY timestamp;
declare variable V$PORTAL_ID varchar(40);
declare variable V$CLAIM_ID varchar(40);
declare variable V$NAME_LAST varchar(400);
declare variable V$NAME_FIRST varchar(400);
declare variable V$TEACHER_ID bigint;
declare variable N integer;
begin

  N = 0;

  -- Для ЦОПП пакет будет обрабатываться, но сформируется пустым и будет пропущен
  IF(I$MODE = 1) THEN EXIT;

  -- Актуальные ученики - только те, у которых прописаны пары кодов {родитель:учащийся}
  FOR
      SELECT L10.OBJ_ID, MAX(L10.DATE_MODIFY)
      FROM LINKS L2
      JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
      JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 125, 187) AND L9.DATE_DEL IS NULL
      JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      GROUP BY 1
      INTO :STUDENT_ID, :DATE_MODIFY
  DO
  BEGIN

    -- Выбираем только родителей, где прописаны пара кодов и степень родства, а также фамилия и имя
    FOR
        SELECT L20.LINK_ID, L20.OBJ_ID, L20.DATE_MODIFY, V1570.DATE_MODIFY, V155.DATE_MODIFY, V1562.LISTVAL_ID, R1562.VAL, V1562.DATE_MODIFY,
            V155.VAL, V1570.VAL, V128.VAL, V129.VAL
        FROM LINKS L20
        JOIN VALS V1570 ON V1570.OBJ_ID = L20.EXT_OBJ_ID AND V1570.PARAM_ID = 1570 AND V1570.IS_DEL = 0
        JOIN VALS V155 ON V155.OBJ_ID = L20.OBJ_ID AND V155.PARAM_ID = 155 AND V155.IS_DEL = 0
        -- Ф+И
        JOIN VALS V128 ON V128.OBJ_ID = L20.OBJ_ID AND V128.PARAM_ID = 128 AND V128.IS_DEL = 0
        JOIN VALS V129 ON V129.OBJ_ID = L20.OBJ_ID AND V129.PARAM_ID = 129 AND V129.IS_DEL = 0
        -- Степень родства
        LEFT JOIN VALL V1562 ON V1562.OBJ_ID = L20.EXT_OBJ_ID AND V1562.PARAM_ID = 1562 AND V1562.IS_DEL = 0
        LEFT JOIN LISTVALS LV1562 ON LV1562.LISTVAL_ID = V1562.LISTVAL_ID
        LEFT JOIN RES R1562 ON R1562.RES_ID = LV1562.RES_ID AND R1562.LANG_CODE = 'RU'
        WHERE L20.PARENT_ID = :STUDENT_ID AND L20.OBJ_TYPE_ID = 20 AND L20.DATE_DEL IS NULL
        INTO :LINK_ID, :REP_ID, :REP_DATE_MODIFY, :DATE_P_UID1, :DATE_P_UID2, :REL_CODE, :REL_NAME, :REL_MODIFY,
            :V$PORTAL_ID, :V$CLAIM_ID, :V$NAME_LAST, :V$NAME_FIRST
    DO
    BEGIN

        -- Если код родителя совпадает с кодом действующего сотрудника, выдаем сотрудника вместо родителя
        -- при этом id линка оставляем тот что указывает на запись родителя
        V$TEACHER_ID = NULL;
        SELECT FIRST 1 L14.OBJ_ID
        FROM VALS V267
        JOIN LINKS L14 ON L14.OBJ_ID = V267.OBJ_ID AND L14.PARENT_TYPE_ID = 2 AND L14.DATE_DEL IS NULL
        JOIN VALS V59 ON V59.OBJ_ID = L14.OBJ_ID AND V59.PARAM_ID = 59 AND V59.VAL = :V$NAME_LAST
        JOIN VALS V60 ON V60.OBJ_ID = L14.OBJ_ID AND V60.PARAM_ID = 60 AND V60.VAL = :V$NAME_FIRST
        WHERE V267.PARAM_ID = 267 AND V267.IS_DEL = 0 AND V267.VAL = :V$PORTAL_ID
        INTO :V$TEACHER_ID;

        IF(V$TEACHER_ID IS NOT NULL) THEN REP_ID = V$TEACHER_ID;

        -- Перекодируем статус
        IF(REL_CODE = 1229) THEN REL_CODE = 1; -- родитель
        ELSE IF(REL_CODE = 1231) THEN REL_CODE = 2; -- опекун
        ELSE IF(REL_CODE = 1232) THEN REL_CODE = 3; -- попечитель
        ELSE IF(REL_CODE = 11175) THEN REL_CODE = 4; -- орган опеки и попечительства
        ELSE IF(REL_CODE = 11176) THEN REL_CODE = 5; -- приемный родитель
        ELSE IF(REL_CODE = 11177) THEN REL_CODE = 6; -- рукововодитель организации...
        ELSE REL_CODE = NULL; -- Все прочие идут лесом

        IS_OK = 0;
        IF(DATE_P_UID1 IS NOT NULL AND DATE_P_UID2 IS NOT NULL AND
          (
            ((T_FROM IS NULL OR DATE_MODIFY >= T_FROM) AND (DATE_MODIFY < T_TO)) OR
            ((T_FROM IS NULL OR REP_DATE_MODIFY >= T_FROM) AND (REP_DATE_MODIFY < T_TO)) OR
            ((T_FROM IS NULL OR REL_MODIFY >= T_FROM) AND (REL_MODIFY < T_TO)) OR
            ((T_FROM IS NULL OR DATE_P_UID1 >= T_FROM) AND (DATE_P_UID1 < T_TO)) OR
            ((T_FROM IS NULL OR DATE_P_UID2 >= T_FROM) AND (DATE_P_UID2 < T_TO))
          )
        )
        THEN
            IS_OK = 1;

        IF(IS_OK = 1) THEN
        BEGIN

            TAG_NAME = 'wsdl&colon;RepresentativeInput';
            VAL = NULL;
            SUSPEND;

            TAG_NAME = 'wsdl&colon;RepresentativeInput:identity:external_id';
            VAL = LINK_ID;
            SUSPEND;

            TAG_NAME = 'wsdl&colon;RepresentativeInput:parent_id:external_id';
            VAL = REP_ID;
            SUSPEND;

            TAG_NAME = 'wsdl&colon;RepresentativeInput:child_id:external_id';
            VAL = STUDENT_ID;
            SUSPEND;

            TAG_NAME = 'wsdl&colon;RepresentativeInput:claim:claim_id';
            VAL = V$CLAIM_ID;
            SUSPEND;

            TAG_NAME = 'wsdl&colon;RepresentativeInput:claim:parent_petrobr_id';
            VAL = V$PORTAL_ID;
            SUSPEND;

            TAG_NAME = 'wsdl&colon;RepresentativeInput:type:code';
            VAL = REL_CODE;
            IF(REL_CODE IS NOT NULL) THEN SUSPEND;

            TAG_NAME = 'wsdl&colon;RepresentativeInput:type:name';
            VAL = REL_NAME;
            IF(REL_CODE IS NOT NULL) THEN SUSPEND;

            N = N + 1;
            IF(N >= 10000) THEN
            BEGIN
                N = 0;
                TAG_NAME = NULL;
                VAL = 'DIVIDE';
                SUSPEND;
            END

        END

    END

  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_PORTAL_REPS__DELETE (
    T_FROM TIMESTAMP,
    T_TO TIMESTAMP NOT NULL,
    ID1 VARCHAR(40) = null,
    ID2 VARCHAR(40) = null,
    I$MODE SMALLINT = 0)
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(2000))
AS
declare variable CURRENT_PERIOD_ID bigint;
declare variable CURRENT_YEAR integer;
declare variable CURRENT_PERIOD_START date;
declare variable PERSON_ID bigint;
declare variable PERSON_EXIT_DT timestamp;
declare variable REP_ID bigint;
declare variable LINK_ID bigint;
declare variable REP_DT timestamp;
declare variable N integer;
declare variable IS_OK smallint;
begin

  IF(T_FROM IS NULL) THEN EXIT;

  -- Для ЦОПП представителей нет, пакет формируем пустой
  IF(I$MODE = 1) THEN EXIT;

  SELECT FIRST 1 V1236.LISTVAL_ID, LV.COST
  FROM LINKS L2
  LEFT JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  LEFT JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :CURRENT_PERIOD_ID, :CURRENT_YEAR;

  N = 0;

  FOR
      -- Актуальные ученики
      SELECT L10.OBJ_ID, NULL
      FROM LINKS L2
      JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
      JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 125, 187) AND L9.DATE_DEL IS NULL
      JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      -- Выбывшие в текущем учебном году
      UNION
      SELECT L10.OBJ_ID, L10.DATE_MODIFY
      FROM LINKS L2
      JOIN LINKS L78 ON L78.PARENT_ID = L2.OBJ_ID AND L78.OBJ_TYPE_ID = 78 AND L78.DATE_DEL IS NULL
      JOIN LINKS L82 ON L82.PARENT_ID = L78.OBJ_ID AND L82.OBJ_TYPE_ID = 82 AND L82.DATE_DEL IS NULL
      JOIN VALI V448 ON V448.OBJ_ID = L82.OBJ_ID AND V448.PARAM_ID = 448 AND V448.IS_DEL = 0 AND V448.VAL = :CURRENT_YEAR
      JOIN LINKS L10 ON L10.PARENT_ID = L82.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      -- Выпуск текущего года
      UNION
      SELECT L10.OBJ_ID, L10.DATE_MODIFY
      FROM LINKS L2
      JOIN LINKS L78 ON L78.PARENT_ID = L2.OBJ_ID AND L78.OBJ_TYPE_ID = 78 AND L78.DATE_DEL IS NULL
      JOIN LINKS L83 ON L83.PARENT_ID = L78.OBJ_ID AND L83.OBJ_TYPE_ID = 83 AND L83.DATE_DEL IS NULL
      JOIN VALI V451 ON V451.OBJ_ID = L83.OBJ_ID AND V451.PARAM_ID = 451 AND V451.IS_DEL = 0 AND V451.VAL = :CURRENT_YEAR
      JOIN LINKS L10 ON L10.PARENT_ID = L83.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      -- Учащиеся, удаленные отовсюду (смотрим только основную ветку) - не ранее чем начало текущего учебного года
      UNION
      SELECT L10.OBJ_ID, MAX(L10.DATE_MODIFY)
      FROM LINKS L2
      JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
      JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 125, 187) AND L9.DATE_DEL IS NULL
      JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL > :CURRENT_PERIOD_START
      LEFT JOIN LINKS LPG ON LPG.OBJ_ID = L10.OBJ_ID AND LPG.PARENT_TYPE_ID IN (9, 125, 187, 82, 83) AND LPG.DATE_DEL IS NULL
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND LPG.PARENT_ID IS NULL
      GROUP BY 1
      ORDER BY 1
      INTO :PERSON_ID, :PERSON_EXIT_DT
  DO
  BEGIN

      FOR
          -- Удаленные родители, у которых нет других живых связей с этим учеником
          SELECT L20.LINK_ID, L20.OBJ_ID
          FROM LINKS L20
          WHERE L20.PARENT_ID = :PERSON_ID AND L20.OBJ_TYPE_ID = 20 AND L20.DATE_DEL >= :CURRENT_PERIOD_START
          -- Действующие родители, у которых обнулен код родителя
          UNION
          SELECT L20.LINK_ID, L20.OBJ_ID
          FROM LINKS L20
          JOIN VALS V155 ON V155.OBJ_ID = L20.OBJ_ID AND V155.PARAM_ID = 155 AND V155.IS_DEL = 1 AND V155.DATE_MODIFY >= :CURRENT_PERIOD_START
          LEFT JOIN VALS V155_2 ON V155_2.OBJ_ID = L20.OBJ_ID AND V155_2.PARAM_ID = 155 AND V155_2.IS_DEL = 0
          WHERE L20.PARENT_ID = :PERSON_ID AND L20.OBJ_TYPE_ID = 20 AND L20.DATE_DEL IS NULL AND V155_2.VAL IS NULL
          -- Действующие родители, у которых обнулен код ребенка
          UNION
          SELECT L20.LINK_ID, L20.OBJ_ID
          FROM LINKS L20
          JOIN VALS V1570 ON V1570.OBJ_ID = L20.EXT_OBJ_ID AND V1570.PARAM_ID = 1570 AND V1570.IS_DEL = 1 AND V1570.DATE_MODIFY >= :CURRENT_PERIOD_START
          LEFT JOIN VALS V1570_2 ON V1570_2.OBJ_ID = L20.EXT_OBJ_ID AND V1570_2.PARAM_ID = 1570 AND V1570_2.IS_DEL = 0
          WHERE L20.PARENT_ID = :PERSON_ID AND L20.OBJ_TYPE_ID = 20 AND L20.DATE_DEL IS NULL AND V1570_2.VAL IS NULL
          -- Родители выбывших учеников вне зависимости от кодов, все сечения - как удаленные, так и актуальные
          UNION
          SELECT L20.LINK_ID, L20.OBJ_ID
          FROM LINKS L20
          WHERE L20.PARENT_ID = :PERSON_ID AND L20.OBJ_TYPE_ID = 20 AND :PERSON_EXIT_DT IS NOT NULL
          INTO :LINK_ID, :REP_ID
      DO
      BEGIN

          -- Выбираем метку времени последнего события, приведшего к удалению
          REP_DT = NULL;

          SELECT MAX(DT) FROM (
              SELECT L20.DATE_MODIFY DT
              FROM LINKS L20
              WHERE L20.OBJ_ID = :REP_ID AND L20.PARENT_TYPE_ID = 10
              UNION
              SELECT V155.DATE_MODIFY DT
              FROM LINKS L20
              JOIN VALS V155 ON V155.OBJ_ID = L20.OBJ_ID AND V155.PARAM_ID = 155
              WHERE L20.OBJ_ID = :REP_ID AND L20.PARENT_TYPE_ID = 10
              UNION
              SELECT V1570.DATE_MODIFY DT
              FROM LINKS L20
              JOIN VALS V1570 ON V1570.OBJ_ID = L20.EXT_OBJ_ID AND V1570.PARAM_ID = 1570
              WHERE L20.OBJ_ID = :REP_ID AND L20.PARENT_TYPE_ID = 10
          )
          INTO :REP_DT;

          IS_OK = 0;
          IF(
              ((T_FROM IS NULL OR REP_DT >= T_FROM) AND REP_DT < T_TO) OR
              ((T_FROM IS NULL OR PERSON_EXIT_DT >= T_FROM) AND PERSON_EXIT_DT < T_TO)
          )
          THEN
              IS_OK = 1;

          IF(IS_OK = 1) THEN
          BEGIN

              TAG_NAME = 'wsdl&colon;IdentityElementInput';
              VAL = NULL;
              SUSPEND;

              TAG_NAME = 'wsdl&colon;IdentityElementInput:identity:external_id';
              VAL = LINK_ID;
              SUSPEND;

              N = N + 1;
              IF(N >= 10000) THEN
              BEGIN
                  N = 0;
                  TAG_NAME = NULL;
                  VAL = 'DIVIDE';
                  SUSPEND;
              END

          END

      END

  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_PORTAL_SAVE_INST (
    IDENT_DATA VARCHAR(4000))
RETURNS (
    ERROR_TEXT VARCHAR(1000))
AS
declare variable V$OU_LICENCE_TYPE char(1);
declare variable SCHOOL_ID bigint;
declare variable P integer;
declare variable SS varchar(100);
declare variable TMP bigint;
declare variable ID1 varchar(100);
declare variable ID2 varchar(100);
begin

    -- Вызов неактуален начиная с июля 2019, параметры удалены

    -- Какой у нас тип лицензии ?
    SELECT FIRST 1 L.OBJ_ID
    FROM LINKS L
    WHERE L.PARENT_ID IS NULL AND L.OBJ_TYPE_ID = 2 AND L.DATE_DEL IS NULL
    INTO :SCHOOL_ID;

    SELECT STATUS FROM OU_LICENCE_TYPE INTO :V$OU_LICENCE_TYPE; -- O, C, U, D

    -- Ищем первую попавшуюся запись в списке и берем из нее код
    WHILE (CHAR_LENGTH(IDENT_DATA) > 0) DO
    BEGIN

      P = POSITION(',' IN IDENT_DATA);
      IF(P <= 0) THEN P = CHAR_LENGTH(IDENT_DATA) + 1;
      SS = SUBSTRING(IDENT_DATA FROM 1 FOR P - 1);
      IDENT_DATA = SUBSTRING(IDENT_DATA FROM P + 1);

      P = POSITION(':' IN SS);
      IF(P <= 0) THEN EXCEPTION DATA_ERROR 'Неверный формат параметров';
      ID1 = SUBSTRING(SS FROM 1 FOR P - 1);
      SS = SUBSTRING(SS FROM P + 1);
      P = POSITION(':' IN SS);
      IF(P <= 0) THEN EXCEPTION DATA_ERROR 'Неверный формат параметров';
      ID2 = SUBSTRING(SS FROM 1 FOR P - 1);

      SELECT BLOB_ID FROM VAL_ADD(2910, :SCHOOL_ID, :ID1) INTO :TMP;
      SELECT BLOB_ID FROM VAL_ADD(2911, :SCHOOL_ID, :ID2) INTO :TMP;

    END

    SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_PORTAL_SCHEDULES (
    T_FROM TIMESTAMP,
    T_TO TIMESTAMP NOT NULL = current_timestamp,
    ID1 VARCHAR(40) = null,
    ID2 VARCHAR(40) = null,
    I$MODE SMALLINT = 0)
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(2000))
AS
declare variable N integer;
declare variable V$SCHEDULE_ID bigint;
declare variable V$FLOW_ID bigint;
declare variable V$ITEM_ID bigint;
declare variable V$WEEK_DAY bigint;
declare variable V$DATE date;
declare variable V$LESSON_NUM integer;
declare variable V$TIME1 time;
declare variable V$TIME2 time;
declare variable V$DUR integer;
declare variable V$YEAR integer;
declare variable V$CJ_ID bigint;
declare variable V$JT smallint;
declare variable V$DT timestamp;
declare variable V$DT2 timestamp;
declare variable S varchar(400);
begin

  N = 0;

  -- Выгружаем только расписания, совпадающие с текущим активным учебным годом, с поставленным флагом выгрузки на портал
  FOR
      SELECT L59.OBJ_ID, L3.OBJ_ID
      FROM LINKS L2
      JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
      JOIN LINKS L68 ON L68.PARENT_ID = L2.OBJ_ID AND L68.OBJ_TYPE_ID = 68 AND L68.DATE_DEL IS NULL
      JOIN LINKS L3 ON L3.PARENT_ID = L68.OBJ_ID AND L3.OBJ_TYPE_ID = 3 AND L3.DATE_DEL IS NULL
      JOIN VALL V37 ON V37.OBJ_ID = L3.OBJ_ID AND V37.PARAM_ID = 37 AND V37.IS_DEL = 0 AND V37.LISTVAL_ID = V1236.LISTVAL_ID -- тот же учебный год
      JOIN LINKS L59 ON L59.PARENT_ID = L3.OBJ_ID AND L59.OBJ_TYPE_ID = 59 AND L59.DATE_DEL IS NULL
      JOIN VALL V1341 ON V1341.OBJ_ID = L59.OBJ_ID AND V1341.PARAM_ID = 1341 AND V1341.IS_DEL = 0 AND V1341.LISTVAL_ID = 2
      LEFT JOIN VALD V3120 ON V3120.OBJ_ID = L59.OBJ_ID AND V3120.PARAM_ID = 3120 AND V3120.IS_DEL = 0
      LEFT JOIN VALD V3121 ON V3121.OBJ_ID = L59.OBJ_ID AND V3121.PARAM_ID = 3121 AND V3121.IS_DEL = 0
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      INTO :V$SCHEDULE_ID, :V$FLOW_ID
  DO
  BEGIN

      FOR
          -- Новое расписание - общеобр и ЦОПП вместе, связи соберем по месту
          SELECT SI.OBJ_ID, SI.WEEKDAY_NUM, V42.VAL, SI.LESSON_NUM, V405.VAL, V406.VAL, J.OBJ_ID, J.JOURNAL_TYPE
          FROM SCHEDULE_ITEMS SI
          -- Учебный день (день недели или конкретное число)
          JOIN LINKS L6 ON L6.PARENT_ID = SI.SCHEDULE_ID AND L6.OBJ_TYPE_ID = 6 AND L6.DATE_DEL IS NULL
          JOIN VALL V402 ON V402.OBJ_ID = L6.OBJ_ID AND V402.PARAM_ID = 402 AND V402.IS_DEL = 0 AND V402.LISTVAL_ID = 798 + SI.WEEKDAY_NUM
          LEFT JOIN VALD V42 ON V42.OBJ_ID = L6.OBJ_ID AND V42.PARAM_ID = 42 AND V42.IS_DEL = 0
          -- Учебный час
          JOIN LINKS L60 ON L60.PARENT_ID = SI.SCHEDULE_ID AND L60.OBJ_TYPE_ID = 60 AND L60.DATE_DEL IS NULL
          JOIN VALI V404 ON V404.OBJ_ID = L60.OBJ_ID AND V404.PARAM_ID = 404 AND V404.IS_DEL = 0 AND V404.VAL = SI.LESSON_NUM
          LEFT JOIN VALT V405 ON V405.OBJ_ID = L60.OBJ_ID AND V405.PARAM_ID = 405 AND V405.IS_DEL = 0
          LEFT JOIN VALT V406 ON V406.OBJ_ID = L60.OBJ_ID AND V406.PARAM_ID = 406 AND V406.IS_DEL = 0
          JOIN CJ2_JOURNAL J ON J.OBJ_ID = SI.CJ_ID AND J.DATE_DEL IS NULL AND J.JOURNAL_TYPE IN (0, /*1,*/ 10, 11)
          WHERE SI.SCHEDULE_ID = :V$SCHEDULE_ID AND SI.DATE_DEL IS NULL AND SI.LESSON_NUM < 60 AND (
              (:T_FROM IS NULL OR SI.DATE_MODIFY >= :T_FROM) AND SI.DATE_MODIFY <= :T_TO
          )
          INTO :V$ITEM_ID, :V$WEEK_DAY, :V$DATE, :V$LESSON_NUM, :V$TIME1, :V$TIME2, :V$CJ_ID, :V$JT
      DO
      BEGIN

          TAG_NAME = 'wsdl&colon;ScheduleInput';
          VAL = NULL;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;ScheduleInput:identity:external_id';
          VAL = V$ITEM_ID;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;ScheduleInput:override_by_priority';
          VAL = 'true';
          SUSPEND;

          TAG_NAME = 'wsdl&colon;ScheduleInput:priority';
          VAL = 0; -- 0 = базовый шаблон расписания, 1 = оперативный шаблон расписания
          SUSPEND;

          TAG_NAME = 'wsdl&colon;ScheduleInput:day_of_the_week';
          VAL = V$WEEK_DAY + 1;
          SUSPEND;

          IF(V$DATE IS NOT NULL) THEN
          BEGIN
              TAG_NAME = 'wsdl&colon;ScheduleInput:day';
              VAL = EXTRACT(DAY FROM :V$DATE);
              SUSPEND;
              TAG_NAME = 'wsdl&colon;ScheduleInput:month';
              VAL = EXTRACT(MONTH FROM :V$DATE);
              SUSPEND;
              TAG_NAME = 'wsdl&colon;ScheduleInput:year';
              VAL = EXTRACT(YEAR FROM :V$DATE);
              SUSPEND;
          END

          TAG_NAME = 'wsdl&colon;ScheduleInput:lesson_number';
          VAL = V$LESSON_NUM;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;ScheduleInput:time';
          VAL = V$TIME1;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;ScheduleInput:duration';
          VAL = DATEDIFF(MINUTE FROM V$TIME1 TO V$TIME2);
          SUSPEND;

          IF(V$JT IN (10, 11)) THEN
          BEGIN
              TAG_NAME = 'wsdl&colon;ScheduleInput:description';
              VAL = (SELECT J.JOURNAL_NAME FROM CJ2_JOURNAL J WHERE J.OBJ_ID = :V$CJ_ID);
              SUSPEND;
          END

          N = N + 1;
          IF(N >= 10000) THEN
          BEGIN
              N = 0;
              TAG_NAME = NULL;
              VAL = 'DIVIDE';
              SUSPEND;
          END

      END

  END

  -- Лента расписания
  FOR
      SELECT L3.OBJ_ID, LV.COST
      FROM LINKS L2
      JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
      JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
      JOIN LINKS L68 ON L68.PARENT_ID = L2.OBJ_ID AND L68.OBJ_TYPE_ID = 68 AND L68.DATE_DEL IS NULL
      JOIN LINKS L3 ON L3.PARENT_ID = L68.OBJ_ID AND L3.OBJ_TYPE_ID = 3 AND L3.DATE_DEL IS NULL
      JOIN VALL V37 ON V37.OBJ_ID = L3.OBJ_ID AND V37.PARAM_ID = 37 AND V37.IS_DEL = 0 AND V37.LISTVAL_ID = V1236.LISTVAL_ID -- тот же учебный год
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      INTO :V$FLOW_ID, :V$YEAR
  DO
  BEGIN

      FOR
          -- Новое расписание - общеобр и ЦОПП вместе, связи соберем по месту
          SELECT SI.OBJ_ID, SD.DAY_DAY, SD.DAY_DATE, SI.LESSON_NUM, V405.VAL, V406.VAL, J.OBJ_ID, J.JOURNAL_TYPE
          FROM SCHEDULE_ITEMS SI
          LEFT JOIN SCHEDULE_TO_DATE(SI.WEEKDAY_NUM, :V$YEAR) SD ON 1 = 1
          -- Нужен шаблон, куда попадает нужная дата
          JOIN LINKS L59 ON L59.PARENT_ID = SI.SCHEDULE_ID AND L59.OBJ_TYPE_ID = 59 AND L59.DATE_DEL IS NULL
          JOIN VALL V1341 ON V1341.OBJ_ID = L59.OBJ_ID AND V1341.PARAM_ID = 1341 AND V1341.IS_DEL = 0 AND V1341.LISTVAL_ID = 2
          JOIN VALD V3120 ON V3120.OBJ_ID = L59.OBJ_ID AND V3120.PARAM_ID = 3120 AND V3120.IS_DEL = 0 AND V3120.VAL <= SD.DAY_DATE
          JOIN VALD V3121 ON V3121.OBJ_ID = L59.OBJ_ID AND V3121.PARAM_ID = 3121 AND V3121.IS_DEL = 0 AND V3121.VAL >= SD.DAY_DATE
          -- Учебный час
          JOIN LINKS L60 ON L60.PARENT_ID = L59.OBJ_ID AND L60.OBJ_TYPE_ID = 60 AND L60.DATE_DEL IS NULL
          JOIN VALI V404 ON V404.OBJ_ID = L60.OBJ_ID AND V404.PARAM_ID = 404 AND V404.IS_DEL = 0 AND V404.VAL = SI.LESSON_NUM
          LEFT JOIN VALT V405 ON V405.OBJ_ID = L60.OBJ_ID AND V405.PARAM_ID = 405 AND V405.IS_DEL = 0
          LEFT JOIN VALT V406 ON V406.OBJ_ID = L60.OBJ_ID AND V406.PARAM_ID = 406 AND V406.IS_DEL = 0
          JOIN CJ2_JOURNAL J ON J.OBJ_ID = SI.CJ_ID AND J.DATE_DEL IS NULL AND J.JOURNAL_TYPE IN (0, /*1,*/ 10, 11)
          WHERE SI.SCHEDULE_ID = :V$FLOW_ID AND SI.DATE_DEL IS NULL AND SI.LESSON_NUM < 60 AND (
              (:T_FROM IS NULL OR SI.DATE_MODIFY >= :T_FROM) AND SI.DATE_MODIFY <= :T_TO
          )
          INTO :V$ITEM_ID, :V$WEEK_DAY, :V$DATE, :V$LESSON_NUM, :V$TIME1, :V$TIME2, :V$CJ_ID, :V$JT
      DO
      BEGIN

          TAG_NAME = 'wsdl&colon;ScheduleInput';
          VAL = NULL;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;ScheduleInput:identity:external_id';
          VAL = V$ITEM_ID;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;ScheduleInput:override_by_priority';
          VAL = 'true';
          SUSPEND;

          TAG_NAME = 'wsdl&colon;ScheduleInput:priority';
          VAL = 1; -- 0 = базовый шаблон расписания, 1 = оперативный шаблон расписания
          SUSPEND;

          TAG_NAME = 'wsdl&colon;ScheduleInput:day_of_the_week';
          VAL = V$WEEK_DAY + 1;
          SUSPEND;

          IF(V$DATE IS NOT NULL) THEN
          BEGIN
              TAG_NAME = 'wsdl&colon;ScheduleInput:day';
              VAL = EXTRACT(DAY FROM :V$DATE);
              SUSPEND;
              TAG_NAME = 'wsdl&colon;ScheduleInput:month';
              VAL = EXTRACT(MONTH FROM :V$DATE);
              SUSPEND;
              TAG_NAME = 'wsdl&colon;ScheduleInput:year';
              VAL = EXTRACT(YEAR FROM :V$DATE);
              SUSPEND;
          END

          TAG_NAME = 'wsdl&colon;ScheduleInput:lesson_number';
          VAL = V$LESSON_NUM;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;ScheduleInput:time';
          VAL = V$TIME1;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;ScheduleInput:duration';
          VAL = DATEDIFF(MINUTE FROM V$TIME1 TO V$TIME2);
          SUSPEND;

          IF(V$JT IN (10, 11)) THEN
          BEGIN
              TAG_NAME = 'wsdl&colon;ScheduleInput:description';
              VAL = (SELECT J.JOURNAL_NAME FROM CJ2_JOURNAL J WHERE J.OBJ_ID = :V$CJ_ID);
              SUSPEND;
          END

          N = N + 1;
          IF(N >= 10000) THEN
          BEGIN
              N = 0;
              TAG_NAME = NULL;
              VAL = 'DIVIDE';
              SUSPEND;
          END

      END

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_PORTAL_SCHEDULES_DELETE (
    T_FROM TIMESTAMP,
    T_TO TIMESTAMP NOT NULL,
    ID1 VARCHAR(40) = null,
    ID2 VARCHAR(40) = null,
    I$MODE SMALLINT = 0)
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(2000))
AS
declare variable V$SCHEDULE_ID bigint;
declare variable V$ITEM_ID bigint;
declare variable V$EXISTS smallint;
declare variable V$DT timestamp;
declare variable N integer;
begin

  IF(T_FROM IS NULL) THEN EXIT;

  N = 0;

  -- Удаление шаблона целиком
  FOR
      -- Базовые расписания
      SELECT L59.OBJ_ID
      FROM LINKS L2
      JOIN LINKS L68 ON L68.PARENT_ID = L2.OBJ_ID AND L68.OBJ_TYPE_ID = 68 AND L68.DATE_DEL IS NULL
      JOIN LINKS L3 ON L3.PARENT_ID = L68.OBJ_ID AND L3.OBJ_TYPE_ID = 3
      JOIN LINKS L59 ON L59.PARENT_ID = L3.OBJ_ID AND L59.OBJ_TYPE_ID = 59
      LEFT JOIN VALL V1341 ON V1341.OBJ_ID = L59.OBJ_ID AND V1341.PARAM_ID = 1341 AND V1341.IS_DEL = 0
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
          AND (L3.DATE_DEL >= :T_FROM OR L59.DATE_DEL >= :T_FROM OR V1341.LISTVAL_ID IS NULL OR V1341.LISTVAL_ID <> 2)
      INTO :V$SCHEDULE_ID
  DO
  BEGIN

      FOR
          SELECT SI.OBJ_ID
          FROM SCHEDULE_ITEMS SI
          WHERE SI.SCHEDULE_ID = :V$SCHEDULE_ID AND SI.DATE_DEL IS NULL
          INTO :V$ITEM_ID
      DO
      BEGIN

          TAG_NAME = 'wsdl&colon;IdentityElementInput';
          VAL = NULL;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;IdentityElementInput:identity:external_id';
          VAL = V$ITEM_ID;
          SUSPEND;

          N = N + 1;
          IF(N >= 10000) THEN
          BEGIN
              N = 0;
              TAG_NAME = NULL;
              VAL = 'DIVIDE';
              SUSPEND;
          END

      END

  END

  -- Удаление элементов расписания рабочих шаблонов
  FOR
      -- Базовые расписания
      SELECT L59.OBJ_ID
      FROM LINKS L2
      JOIN LINKS L68 ON L68.PARENT_ID = L2.OBJ_ID AND L68.OBJ_TYPE_ID = 68 AND L68.DATE_DEL IS NULL
      JOIN LINKS L3 ON L3.PARENT_ID = L68.OBJ_ID AND L3.OBJ_TYPE_ID = 3 AND L3.DATE_DEL IS NULL
      JOIN LINKS L59 ON L59.PARENT_ID = L3.OBJ_ID AND L59.OBJ_TYPE_ID = 59 AND L59.DATE_DEL IS NULL
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      INTO :V$SCHEDULE_ID
  DO
  BEGIN

      FOR
          SELECT SI.OBJ_ID
          FROM SCHEDULE_ITEMS SI
          WHERE SI.SCHEDULE_ID = :V$SCHEDULE_ID AND SI.DATE_DEL >= :T_FROM
          INTO :V$ITEM_ID
      DO
      BEGIN

          TAG_NAME = 'wsdl&colon;IdentityElementInput';
          VAL = NULL;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;IdentityElementInput:identity:external_id';
          VAL = V$ITEM_ID;
          SUSPEND;

          N = N + 1;
          IF(N >= 10000) THEN
          BEGIN
              N = 0;
              TAG_NAME = NULL;
              VAL = 'DIVIDE';
              SUSPEND;
          END

      END

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_PORTAL_SCHEDULES_GROUPS (
    T_FROM TIMESTAMP,
    T_TO TIMESTAMP NOT NULL,
    ID1 VARCHAR(40) = NULL,
    ID2 VARCHAR(40) = NULL,
    I$MODE SMALLINT = 0)
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(2000))
AS
DECLARE VARIABLE N INTEGER;
DECLARE VARIABLE V$SCHEDULE_ID BIGINT;
DECLARE VARIABLE V$FLOW_ID BIGINT;
DECLARE VARIABLE V$ITEM_ID BIGINT;
DECLARE VARIABLE V$LINK_ID BIGINT;
DECLARE VARIABLE V$GROUP_ID BIGINT;
DECLARE VARIABLE V$PLAN_TYPE BIGINT;
DECLARE VARIABLE V$COPP BIGINT;
DECLARE VARIABLE V$DT TIMESTAMP;
DECLARE VARIABLE V$DT2 TIMESTAMP;
begin

  N = 0;

  FOR
      SELECT L59.OBJ_ID, L3.OBJ_ID
      FROM LINKS L2
      JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
      JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
      JOIN LINKS L68 ON L68.PARENT_ID = L2.OBJ_ID AND L68.OBJ_TYPE_ID = 68 AND L68.DATE_DEL IS NULL
      JOIN LINKS L3 ON L3.PARENT_ID = L68.OBJ_ID AND L3.OBJ_TYPE_ID = 3 AND L3.DATE_DEL IS NULL
      JOIN VALL V37 ON V37.OBJ_ID = L3.OBJ_ID AND V37.PARAM_ID = 37 AND V37.IS_DEL = 0 AND V37.LISTVAL_ID = V1236.LISTVAL_ID
      JOIN LINKS L59 ON L59.PARENT_ID = L3.OBJ_ID AND L59.OBJ_TYPE_ID = 59 AND L59.DATE_DEL IS NULL
      JOIN VALL V1341 ON V1341.OBJ_ID = L59.OBJ_ID AND V1341.PARAM_ID = 1341 AND V1341.IS_DEL = 0 AND V1341.LISTVAL_ID = 2
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      INTO :V$SCHEDULE_ID, :V$FLOW_ID
  DO
  BEGIN

      -- Фильтр только по групповым УП
      FOR
          SELECT SI.OBJ_ID, SI.OBJ_ID, J.GRADE_ID, V3064.LISTVAL_ID
          FROM SCHEDULE_ITEMS SI
          JOIN CJ2_JOURNAL J ON J.OBJ_ID = SI.CJ_ID AND J.JOURNAL_TYPE IN (0, /*1,*/ 10, 11) AND J.DATE_DEL IS NULL
          LEFT JOIN VALL V3064 ON V3064.OBJ_ID = J.GRADE_ID AND V3064.PARAM_ID = 3064 AND V3064.IS_DEL = 0
          WHERE SI.SCHEDULE_ID = :V$SCHEDULE_ID AND SI.DATE_DEL IS NULL AND (
              (:T_FROM IS NULL OR SI.DATE_MODIFY >= :T_FROM) AND SI.DATE_MODIFY <= :T_TO
          ) AND SI.LESSON_NUM < 60
          INTO :V$ITEM_ID, :V$LINK_ID, :V$GROUP_ID, :V$COPP
      DO
      BEGIN

          -- Пропускаем ссылки на УП индивидуального обучения
          V$PLAN_TYPE = NULL;
          SELECT FIRST 1 V3016.LISTVAL_ID
          FROM LINKS LP54
          JOIN LINKS LP400 ON LP400.OBJ_ID = LP54.PARENT_ID AND LP400.PARENT_TYPE_ID = 400 AND LP400.DATE_DEL IS NULL
          JOIN VALL V3016 ON V3016.OBJ_ID = LP400.PARENT_ID AND V3016.PARAM_ID = 3016 AND V3016.IS_DEL = 0
          WHERE LP54.OBJ_ID = :V$GROUP_ID AND LP54.PARENT_TYPE_ID = 54 AND LP54.DATE_DEL IS NULL
          INTO :V$PLAN_TYPE;

          -- Для ЦОПП проверяем, что сама группа ЦОПП
          -- Либо групповые УП, либо новые журналы
          IF((V$PLAN_TYPE = 5465 OR V$ITEM_ID = V$LINK_ID) AND ((I$MODE = 0 AND V$COPP = 3) OR (I$MODE = 1 AND V$COPP = 2))) THEN
          BEGIN

              TAG_NAME = 'wsdl&colon;GroupInput';
              VAL = NULL;
              SUSPEND;

              TAG_NAME = 'wsdl&colon;GroupInput:identity:external_id';
              VAL = V$LINK_ID;
              SUSPEND;

              TAG_NAME = 'wsdl&colon;GroupInput:schedule_id:external_id';
              VAL = V$ITEM_ID;
              SUSPEND;

              TAG_NAME = 'wsdl&colon;GroupInput:group_id:external_id';
              VAL = V$GROUP_ID;
              SUSPEND;

              N = N + 1;
              IF(N >= 10000) THEN
              BEGIN
                  N = 0;
                  TAG_NAME = NULL;
                  VAL = 'DIVIDE';
                  SUSPEND;
              END

          END

      END

  END

  -- Лента расписания
  FOR
      SELECT L3.OBJ_ID
      FROM LINKS L2
      JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
      JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
      JOIN LINKS L68 ON L68.PARENT_ID = L2.OBJ_ID AND L68.OBJ_TYPE_ID = 68 AND L68.DATE_DEL IS NULL
      JOIN LINKS L3 ON L3.PARENT_ID = L68.OBJ_ID AND L3.OBJ_TYPE_ID = 3 AND L3.DATE_DEL IS NULL
      JOIN VALL V37 ON V37.OBJ_ID = L3.OBJ_ID AND V37.PARAM_ID = 37 AND V37.IS_DEL = 0 AND V37.LISTVAL_ID = V1236.LISTVAL_ID
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      INTO :V$FLOW_ID
  DO
  BEGIN

      -- Фильтр только по групповым УП
      FOR
          SELECT SI.OBJ_ID, SI.OBJ_ID, J.GRADE_ID, V3064.LISTVAL_ID
          FROM SCHEDULE_ITEMS SI
          JOIN CJ2_JOURNAL J ON J.OBJ_ID = SI.CJ_ID AND J.JOURNAL_TYPE IN (0, /*1,*/ 10, 11) AND J.DATE_DEL IS NULL
          LEFT JOIN VALL V3064 ON V3064.OBJ_ID = J.GRADE_ID AND V3064.PARAM_ID = 3064 AND V3064.IS_DEL = 0
          WHERE SI.SCHEDULE_ID = :V$FLOW_ID AND SI.DATE_DEL IS NULL AND (
              (:T_FROM IS NULL OR SI.DATE_MODIFY >= :T_FROM) AND SI.DATE_MODIFY <= :T_TO
          ) AND SI.LESSON_NUM < 60
          INTO :V$ITEM_ID, :V$LINK_ID, :V$GROUP_ID, :V$COPP
      DO
      BEGIN

          -- Пропускаем ссылки на УП индивидуального обучения
          V$PLAN_TYPE = NULL;
          SELECT FIRST 1 V3016.LISTVAL_ID
          FROM LINKS LP54
          JOIN LINKS LP400 ON LP400.OBJ_ID = LP54.PARENT_ID AND LP400.PARENT_TYPE_ID = 400 AND LP400.DATE_DEL IS NULL
          JOIN VALL V3016 ON V3016.OBJ_ID = LP400.PARENT_ID AND V3016.PARAM_ID = 3016 AND V3016.IS_DEL = 0
          WHERE LP54.OBJ_ID = :V$GROUP_ID AND LP54.PARENT_TYPE_ID = 54 AND LP54.DATE_DEL IS NULL
          INTO :V$PLAN_TYPE;

          -- Для ЦОПП проверяем, что сама группа ЦОПП
          -- Либо групповые УП, либо новые журналы
          IF((V$PLAN_TYPE = 5465 OR V$ITEM_ID = V$LINK_ID) AND ((I$MODE = 0 AND V$COPP = 3) OR (I$MODE = 1 AND V$COPP = 2))) THEN
          BEGIN

              TAG_NAME = 'wsdl&colon;GroupInput';
              VAL = NULL;
              SUSPEND;

              TAG_NAME = 'wsdl&colon;GroupInput:identity:external_id';
              VAL = V$LINK_ID;
              SUSPEND;

              TAG_NAME = 'wsdl&colon;GroupInput:schedule_id:external_id';
              VAL = V$ITEM_ID;
              SUSPEND;

              TAG_NAME = 'wsdl&colon;GroupInput:group_id:external_id';
              VAL = V$GROUP_ID;
              SUSPEND;

              N = N + 1;
              IF(N >= 10000) THEN
              BEGIN
                  N = 0;
                  TAG_NAME = NULL;
                  VAL = 'DIVIDE';
                  SUSPEND;
              END

          END

      END

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_PORTAL_SCHEDULES_GROUPS_DEL (
    T_FROM TIMESTAMP,
    T_TO TIMESTAMP NOT NULL,
    ID1 VARCHAR(40) = null,
    ID2 VARCHAR(40) = null,
    I$MODE SMALLINT = 0)
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(2000))
AS
declare variable V$SCHEDULE_ID bigint;
declare variable V$LINK_ID bigint;
declare variable N integer;
begin

  IF(T_FROM IS NULL) THEN EXIT;

  N = 0;

  FOR
      -- Базовые расписания
      SELECT L59.OBJ_ID
      FROM LINKS L2
      JOIN LINKS L68 ON L68.PARENT_ID = L2.OBJ_ID AND L68.OBJ_TYPE_ID = 68 AND L68.DATE_DEL IS NULL
      JOIN LINKS L3 ON L3.PARENT_ID = L68.OBJ_ID AND L3.OBJ_TYPE_ID = 3 AND L3.DATE_DEL IS NULL
      JOIN LINKS L59 ON L59.PARENT_ID = L3.OBJ_ID AND L59.OBJ_TYPE_ID = 59 AND L59.DATE_DEL IS NULL
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      INTO :V$SCHEDULE_ID
  DO
  BEGIN

      FOR
          SELECT SI.OBJ_ID
          FROM SCHEDULE_ITEMS SI
          WHERE SI.SCHEDULE_ID = :V$SCHEDULE_ID AND SI.DATE_DEL >= :T_FROM
          INTO :V$LINK_ID
      DO
      BEGIN

          TAG_NAME = 'wsdl&colon;IdentityElementInput';
          VAL = NULL;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;IdentityElementInput:identity:external_id';
          VAL = V$LINK_ID;
          SUSPEND;

          N = N + 1;
          IF(N >= 10000) THEN
          BEGIN
              N = 0;
              TAG_NAME = NULL;
              VAL = 'DIVIDE';
              SUSPEND;
          END

      END

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_PORTAL_SCHEDULES_SUBJECTS (
    T_FROM TIMESTAMP,
    T_TO TIMESTAMP NOT NULL,
    ID1 VARCHAR(40) = null,
    ID2 VARCHAR(40) = null,
    I$MODE SMALLINT = 0)
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(2000))
AS
declare variable N integer;
declare variable V$SCHEDULE_ID bigint;
declare variable V$ITEM_ID bigint;
declare variable V$LINK_ID bigint;
declare variable V$SUBJECT_ID varchar(40);
declare variable V$FLOW_ID bigint;
declare variable V$DT timestamp;
declare variable V$DT2 timestamp;
begin

  N = 0;

  FOR
      SELECT L59.OBJ_ID, L3.OBJ_ID
      FROM LINKS L2
      JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
      JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
      JOIN LINKS L68 ON L68.PARENT_ID = L2.OBJ_ID AND L68.OBJ_TYPE_ID = 68 AND L68.DATE_DEL IS NULL
      JOIN LINKS L3 ON L3.PARENT_ID = L68.OBJ_ID AND L3.OBJ_TYPE_ID = 3 AND L3.DATE_DEL IS NULL
      JOIN VALL V37 ON V37.OBJ_ID = L3.OBJ_ID AND V37.PARAM_ID = 37 AND V37.IS_DEL = 0 AND V37.LISTVAL_ID = V1236.LISTVAL_ID
      JOIN LINKS L59 ON L59.PARENT_ID = L3.OBJ_ID AND L59.OBJ_TYPE_ID = 59 AND L59.DATE_DEL IS NULL
      JOIN VALL V1341 ON V1341.OBJ_ID = L59.OBJ_ID AND V1341.PARAM_ID = 1341 AND V1341.IS_DEL = 0 AND V1341.LISTVAL_ID = 2
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      INTO :V$SCHEDULE_ID, :V$FLOW_ID
  DO
  BEGIN

      FOR
          SELECT SI.OBJ_ID, SI.OBJ_ID, IIF(J.JOURNAL_TYPE IN (0, 1), J.SUBJECT_ID, 'event')
          FROM SCHEDULE_ITEMS SI
          JOIN CJ2_JOURNAL J ON J.OBJ_ID = SI.CJ_ID AND J.JOURNAL_TYPE IN (0, /*1,*/ 10, 11) AND J.DATE_DEL IS NULL
          WHERE SI.SCHEDULE_ID = :V$SCHEDULE_ID AND SI.DATE_DEL IS NULL AND (
              (:T_FROM IS NULL OR SI.DATE_MODIFY >= :T_FROM) AND SI.DATE_MODIFY <= :T_TO
          ) AND SI.LESSON_NUM < 60
          INTO :V$ITEM_ID, :V$LINK_ID, :V$SUBJECT_ID
      DO
      BEGIN

          TAG_NAME = 'wsdl&colon;SubjectInput';
          VAL = NULL;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;SubjectInput:identity:external_id';
          VAL = V$LINK_ID;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;SubjectInput:schedule_id:external_id';
          VAL = V$ITEM_ID;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;SubjectInput:subject_id:external_id';
          VAL = V$SUBJECT_ID;
          SUSPEND;

          N = N + 1;
          IF(N >= 10000) THEN
          BEGIN
              N = 0;
              TAG_NAME = NULL;
              VAL = 'DIVIDE';
              SUSPEND;
          END

      END

  END

  -- Лента расписания
  FOR
      SELECT L3.OBJ_ID
      FROM LINKS L2
      JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
      JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
      JOIN LINKS L68 ON L68.PARENT_ID = L2.OBJ_ID AND L68.OBJ_TYPE_ID = 68 AND L68.DATE_DEL IS NULL
      JOIN LINKS L3 ON L3.PARENT_ID = L68.OBJ_ID AND L3.OBJ_TYPE_ID = 3 AND L3.DATE_DEL IS NULL
      JOIN VALL V37 ON V37.OBJ_ID = L3.OBJ_ID AND V37.PARAM_ID = 37 AND V37.IS_DEL = 0 AND V37.LISTVAL_ID = V1236.LISTVAL_ID
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      INTO :V$FLOW_ID
  DO
  BEGIN

      FOR
          SELECT SI.OBJ_ID, SI.OBJ_ID, IIF(J.JOURNAL_TYPE IN (0, 1), J.SUBJECT_ID, 'event')
          FROM SCHEDULE_ITEMS SI
          JOIN CJ2_JOURNAL J ON J.OBJ_ID = SI.CJ_ID AND J.JOURNAL_TYPE IN (0, /*1,*/ 10, 11) AND J.DATE_DEL IS NULL
          WHERE SI.SCHEDULE_ID = :V$FLOW_ID AND SI.DATE_DEL IS NULL AND (
              (:T_FROM IS NULL OR SI.DATE_MODIFY >= :T_FROM) AND SI.DATE_MODIFY <= :T_TO
          ) AND SI.LESSON_NUM < 60
          INTO :V$ITEM_ID, :V$LINK_ID, :V$SUBJECT_ID
      DO
      BEGIN

          TAG_NAME = 'wsdl&colon;SubjectInput';
          VAL = NULL;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;SubjectInput:identity:external_id';
          VAL = V$LINK_ID;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;SubjectInput:schedule_id:external_id';
          VAL = V$ITEM_ID;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;SubjectInput:subject_id:external_id';
          VAL = V$SUBJECT_ID;
          SUSPEND;

          N = N + 1;
          IF(N >= 10000) THEN
          BEGIN
              N = 0;
              TAG_NAME = NULL;
              VAL = 'DIVIDE';
              SUSPEND;
          END

      END

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_PORTAL_SCHEDULES_SUBJ_DEL (
    T_FROM TIMESTAMP,
    T_TO TIMESTAMP NOT NULL,
    ID1 VARCHAR(40) = null,
    ID2 VARCHAR(40) = null,
    I$MODE SMALLINT = 0)
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(2000))
AS
declare variable V$SCHEDULE_ID bigint;
declare variable V$LINK_ID bigint;
declare variable N integer;
begin

  IF(T_FROM IS NULL) THEN EXIT;

  N = 0;

  FOR
      -- Базовые расписания
      SELECT L59.OBJ_ID
      FROM LINKS L2
      JOIN LINKS L68 ON L68.PARENT_ID = L2.OBJ_ID AND L68.OBJ_TYPE_ID = 68 AND L68.DATE_DEL IS NULL
      JOIN LINKS L3 ON L3.PARENT_ID = L68.OBJ_ID AND L3.OBJ_TYPE_ID = 3 AND L3.DATE_DEL IS NULL
      JOIN LINKS L59 ON L59.PARENT_ID = L3.OBJ_ID AND L59.OBJ_TYPE_ID = 59 AND L59.DATE_DEL IS NULL
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      INTO :V$SCHEDULE_ID
  DO
  BEGIN

      FOR
          SELECT SI.OBJ_ID
          FROM SCHEDULE_ITEMS SI
          WHERE SI.SCHEDULE_ID = :V$SCHEDULE_ID AND SI.DATE_DEL >= :T_FROM
          INTO :V$LINK_ID
      DO
      BEGIN

          TAG_NAME = 'wsdl&colon;IdentityElementInput';
          VAL = NULL;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;IdentityElementInput:identity:external_id';
          VAL = V$LINK_ID;
          SUSPEND;

          N = N + 1;
          IF(N >= 10000) THEN
          BEGIN
              N = 0;
              TAG_NAME = NULL;
              VAL = 'DIVIDE';
              SUSPEND;
          END

      END

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_PORTAL_SCHEDULES_TEACHERS (
    T_FROM TIMESTAMP,
    T_TO TIMESTAMP NOT NULL = current_timestamp,
    ID1 VARCHAR(40) = null,
    ID2 VARCHAR(40) = null,
    I$MODE SMALLINT = 0)
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(2000))
AS
declare variable N integer;
declare variable V$SCHEDULE_ID bigint;
declare variable V$FLOW_ID bigint;
declare variable V$ITEM_ID bigint;
declare variable V$LINK_ID bigint;
declare variable V$TEACHER_ID bigint;
declare variable PORTAL_DT timestamp;
begin

  N = 0;

  FOR
      SELECT L59.OBJ_ID, L3.OBJ_ID
      FROM LINKS L2
      JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
      JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
      JOIN LINKS L68 ON L68.PARENT_ID = L2.OBJ_ID AND L68.OBJ_TYPE_ID = 68 AND L68.DATE_DEL IS NULL
      JOIN LINKS L3 ON L3.PARENT_ID = L68.OBJ_ID AND L3.OBJ_TYPE_ID = 3 AND L3.DATE_DEL IS NULL
      JOIN VALL V37 ON V37.OBJ_ID = L3.OBJ_ID AND V37.PARAM_ID = 37 AND V37.IS_DEL = 0 AND V37.LISTVAL_ID = V1236.LISTVAL_ID
      JOIN LINKS L59 ON L59.PARENT_ID = L3.OBJ_ID AND L59.OBJ_TYPE_ID = 59 AND L59.DATE_DEL IS NULL
      JOIN VALL V1341 ON V1341.OBJ_ID = L59.OBJ_ID AND V1341.PARAM_ID = 1341 AND V1341.IS_DEL = 0 AND V1341.LISTVAL_ID = 2
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      INTO :V$SCHEDULE_ID, :V$FLOW_ID
  DO
  BEGIN

      FOR
          SELECT SI.OBJ_ID, SI.OBJ_ID, J.TEACHER_ID
          FROM SCHEDULE_ITEMS SI
          JOIN CJ2_JOURNAL J ON J.OBJ_ID = SI.CJ_ID AND J.JOURNAL_TYPE IN (0, /*1,*/ 10, 11) AND J.DATE_DEL IS NULL
          WHERE SI.SCHEDULE_ID = :V$SCHEDULE_ID AND SI.DATE_DEL IS NULL AND (
              (:T_FROM IS NULL OR SI.DATE_MODIFY >= :T_FROM) AND SI.DATE_MODIFY <= :T_TO
          ) AND SI.LESSON_NUM < 60
          INTO :V$ITEM_ID, :V$LINK_ID, :V$TEACHER_ID
      DO
      BEGIN

          -- Только если учителя есть портальный id или ФИАС id
          PORTAL_DT = NULL;
          SELECT MIN(V267.DATE_MODIFY)
          FROM VALS V267
          WHERE V267.OBJ_ID = :V$TEACHER_ID AND ((:I$MODE = 0 AND V267.PARAM_ID = 267) OR (:I$MODE = 1 AND V267.PARAM_ID = 3061))
          INTO :PORTAL_DT;

          IF(PORTAL_DT IS NOT NULL) THEN
          BEGIN

              TAG_NAME = 'wsdl&colon;TeacherInput';
              VAL = NULL;
              SUSPEND;

              TAG_NAME = 'wsdl&colon;TeacherInput:identity:external_id';
              VAL = V$LINK_ID;
              SUSPEND;

              TAG_NAME = 'wsdl&colon;TeacherInput:schedule_id:external_id';
              VAL = V$ITEM_ID;
              SUSPEND;

              TAG_NAME = 'wsdl&colon;TeacherInput:teacher_id:external_id';
              VAL = V$TEACHER_ID;
              SUSPEND;

              N = N + 1;
              IF(N >= 10000) THEN
              BEGIN
                  N = 0;
                  TAG_NAME = NULL;
                  VAL = 'DIVIDE';
                  SUSPEND;
              END

          END

      END

  END

  -- Лента расписания
  FOR
      SELECT L3.OBJ_ID
      FROM LINKS L2
      JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
      JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
      JOIN LINKS L68 ON L68.PARENT_ID = L2.OBJ_ID AND L68.OBJ_TYPE_ID = 68 AND L68.DATE_DEL IS NULL
      JOIN LINKS L3 ON L3.PARENT_ID = L68.OBJ_ID AND L3.OBJ_TYPE_ID = 3 AND L3.DATE_DEL IS NULL
      JOIN VALL V37 ON V37.OBJ_ID = L3.OBJ_ID AND V37.PARAM_ID = 37 AND V37.IS_DEL = 0 AND V37.LISTVAL_ID = V1236.LISTVAL_ID
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      INTO :V$FLOW_ID
  DO
  BEGIN

      FOR
          SELECT SI.OBJ_ID, SI.OBJ_ID, J.TEACHER_ID
          FROM SCHEDULE_ITEMS SI
          JOIN CJ2_JOURNAL J ON J.OBJ_ID = SI.CJ_ID AND J.JOURNAL_TYPE IN (0, /*1,*/ 10, 11) AND J.DATE_DEL IS NULL
          WHERE SI.SCHEDULE_ID = :V$FLOW_ID AND SI.DATE_DEL IS NULL AND (
              (:T_FROM IS NULL OR SI.DATE_MODIFY >= :T_FROM) AND SI.DATE_MODIFY <= :T_TO
          ) AND SI.LESSON_NUM < 60
          INTO :V$ITEM_ID, :V$LINK_ID, :V$TEACHER_ID
      DO
      BEGIN

          -- Только если учителя есть портальный id или ФИАС id
          PORTAL_DT = NULL;
          SELECT MIN(V267.DATE_MODIFY)
          FROM VALS V267
          WHERE V267.OBJ_ID = :V$TEACHER_ID AND ((:I$MODE = 0 AND V267.PARAM_ID = 267) OR (:I$MODE = 1 AND V267.PARAM_ID = 3061))
          INTO :PORTAL_DT;

          IF(PORTAL_DT IS NOT NULL) THEN
          BEGIN

              TAG_NAME = 'wsdl&colon;TeacherInput';
              VAL = NULL;
              SUSPEND;

              TAG_NAME = 'wsdl&colon;TeacherInput:identity:external_id';
              VAL = V$LINK_ID;
              SUSPEND;

              TAG_NAME = 'wsdl&colon;TeacherInput:schedule_id:external_id';
              VAL = V$ITEM_ID;
              SUSPEND;

              TAG_NAME = 'wsdl&colon;TeacherInput:teacher_id:external_id';
              VAL = V$TEACHER_ID;
              SUSPEND;

              N = N + 1;
              IF(N >= 10000) THEN
              BEGIN
                  N = 0;
                  TAG_NAME = NULL;
                  VAL = 'DIVIDE';
                  SUSPEND;
              END

          END

      END

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_PORTAL_SCHEDULES_TEACH_DEL (
    T_FROM TIMESTAMP,
    T_TO TIMESTAMP NOT NULL,
    ID1 VARCHAR(40) = null,
    ID2 VARCHAR(40) = null,
    I$MODE SMALLINT = 0)
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(2000))
AS
declare variable V$SCHEDULE_ID bigint;
declare variable V$LINK_ID bigint;
declare variable N integer;
begin

  IF(T_FROM IS NULL) THEN EXIT;

  N = 0;

  FOR
      -- Базовые расписания
      SELECT L59.OBJ_ID
      FROM LINKS L2
      JOIN LINKS L68 ON L68.PARENT_ID = L2.OBJ_ID AND L68.OBJ_TYPE_ID = 68 AND L68.DATE_DEL IS NULL
      JOIN LINKS L3 ON L3.PARENT_ID = L68.OBJ_ID AND L3.OBJ_TYPE_ID = 3 AND L3.DATE_DEL IS NULL
      JOIN LINKS L59 ON L59.PARENT_ID = L3.OBJ_ID AND L59.OBJ_TYPE_ID = 59 AND L59.DATE_DEL IS NULL
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      INTO :V$SCHEDULE_ID
  DO
  BEGIN

      FOR
          SELECT SI.OBJ_ID
          FROM SCHEDULE_ITEMS SI
          WHERE SI.SCHEDULE_ID = :V$SCHEDULE_ID AND SI.DATE_DEL >= :T_FROM
          INTO :V$LINK_ID
      DO
      BEGIN

          TAG_NAME = 'wsdl&colon;IdentityElementInput';
          VAL = NULL;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;IdentityElementInput:identity:external_id';
          VAL = V$LINK_ID;
          SUSPEND;

          N = N + 1;
          IF(N >= 10000) THEN
          BEGIN
              N = 0;
              TAG_NAME = NULL;
              VAL = 'DIVIDE';
              SUSPEND;
          END

      END

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_PORTAL_STUDENT_MV (
    STUDENT_ID BIGINT,
    T_FROM TIMESTAMP,
    T_TO TIMESTAMP NOT NULL)
RETURNS (
    MOVE_ID BIGINT,
    DATE_IN DATE,
    DATE_OUT DATE,
    STAGE_LV BIGINT,
    GRADE_ID BIGINT)
AS
declare variable V$START_ID bigint;
declare variable V$MOVE_ID bigint;
declare variable V$MOVE_TYPE bigint;
declare variable V$MOVE_DATE date;
declare variable V$MOVE_STAGE bigint;
declare variable V$PREV_STAGE bigint;
declare variable V$GRADE_ID bigint;
begin

  -- Смысл утрачен

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_PORTAL_SUBJECTS (
    T_FROM TIMESTAMP,
    T_TO TIMESTAMP NOT NULL = current_timestamp,
    ID1 VARCHAR(40) = null,
    ID2 VARCHAR(40) = null,
    I$MODE SMALLINT = 0)
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(2000))
AS
declare variable SUBJECT_ID bigint;
declare variable SUBJECT_DT timestamp;
declare variable PARENT_ID bigint;
declare variable IS_OK smallint;
declare variable N integer;
begin

  IF(ID1 IS NULL) THEN
  BEGIN
      SELECT FIRST 1 V2910.VAL
      FROM LINKS L2
      JOIN VALS V2910 ON V2910.OBJ_ID = L2.OBJ_ID AND V2910.PARAM_ID = 2910 AND V2910.IS_DEL = 0
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      INTO :ID1;
  END

  N = 0;

  -- Выдаем полный список предметов
  FOR
      -- Текущие актуальные предметы
      SELECT L51.OBJ_ID, L51.PARENT_ID, L51.DATE_MODIFY
      FROM LINKS L53
      JOIN LINKS L301 ON L301.PARENT_ID = L53.OBJ_ID AND L301.OBJ_TYPE_ID = 301 AND L301.DATE_DEL IS NULL
      JOIN LINKS L51 ON L51.PARENT_ID = L301.OBJ_ID AND L51.OBJ_TYPE_ID = 51 AND L51.DATE_DEL IS NULL
      WHERE L53.PARENT_ID IS NULL AND L53.OBJ_TYPE_ID = 53 AND L53.DATE_DEL IS NULL
      -- Текущие дисциплины
      UNION
      SELECT L197.OBJ_ID, NULL, L197.DATE_MODIFY
      FROM LINKS L193
      JOIN LINKS L197 ON L197.PARENT_ID = L193.OBJ_ID AND L197.OBJ_TYPE_ID = 197 AND L197.DATE_DEL IS NULL
      WHERE L193.PARENT_ID IS NULL AND L193.OBJ_TYPE_ID = 193 AND L193.DATE_DEL IS NULL
      -- Удаленные предметы из итоговых отметок
      UNION
      SELECT M.SUBJECT_ID, L51.PARENT_ID, COALESCE(MAX(L51.DATE_MODIFY), '01.09.2010')
      FROM VALM M
      LEFT JOIN LINKS L51 ON L51.OBJ_ID = M.SUBJECT_ID AND L51.PARENT_TYPE_ID IN (51, 53, 301, 193)
      GROUP BY 1, 2
      INTO :SUBJECT_ID, :PARENT_ID, :SUBJECT_DT
  DO
  BEGIN

      IS_OK = 0;
      IF(
          ((T_FROM IS NULL OR SUBJECT_DT >= T_FROM) AND (SUBJECT_DT < T_TO))
      )
      THEN
          IS_OK = 1;

      IF(IS_OK = 1) THEN
      BEGIN

          TAG_NAME = 'wsdl&colon;SubjectInput';
          VAL = NULL;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;SubjectInput:identity:external_id';
          VAL = SUBJECT_ID;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;SubjectInput:institution_id:id';
          VAL = ID1;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;SubjectInput:name';
          VAL = NULL;
          SELECT V376.VAL
          FROM VALS V376
          WHERE V376.OBJ_ID = :SUBJECT_ID AND V376.PARAM_ID IN (376, 1751) AND V376.IS_DEL = 0
          INTO :VAL;
          VAL = REPLACE(VAL, '@', '');
          SUSPEND;

          TAG_NAME = 'wsdl&colon;SubjectInput:additional_name';
          VAL = NULL;
          SELECT V377.VAL
          FROM VALS V377
          WHERE V377.OBJ_ID = :SUBJECT_ID AND V377.PARAM_ID = 377 AND V377.IS_DEL = 0
          INTO :VAL;
          IF(VAL IS NULL) THEN VAL = 'Н/Д';
          SUSPEND;

          -- Признак внеурочности
          TAG_NAME = 'wsdl&colon;SubjectInput:not_lesson_activities';
          IF(PARENT_ID = 32772) THEN VAL = 'true'; ELSE VAL = 'false';
          SUSPEND;

          IF(SUBJECT_ID < 1000000000) THEN
          BEGIN
             VAL = NULL;

             IF(SUBJECT_ID = 185) THEN VAL = 1; -- Русский язык
             IF(SUBJECT_ID = 187) THEN VAL = 2; -- Литература
             ELSE IF(SUBJECT_ID = 929) THEN VAL = 3; -- Родной язык
             ELSE IF(SUBJECT_ID = 32787) THEN VAL = 4; -- Родная литература
             ELSE IF(SUBJECT_ID = 186) THEN VAL = 5; -- Русский язык и литературное чтение
             ELSE IF(SUBJECT_ID = 32789) THEN VAL = 6; -- Родной язык и литературное чтение на родном языке
             ELSE IF(SUBJECT_ID IN (178, 32810, 188, 3136, 3154, 5522, 3090, 3137, 3131, 3155, 3132, 5521, 2129, 3153, 3133, 3130, 189, 3135, 5520)) THEN VAL = 7; -- Иностранный язык
             ELSE IF(SUBJECT_ID = 190) THEN VAL = 8; -- Математика
             ELSE IF(SUBJECT_ID = 191) THEN VAL = 9; -- Информатика и ИКТ
             ELSE IF(SUBJECT_ID = 196) THEN VAL = 10; -- Обществознание и естествознание (Окружающий мир)
             ELSE IF(SUBJECT_ID IN (9000, 32856, 32854, 32858, 32859, 32852, 32862)) THEN VAL = 11; -- Основы религиозных культур и светской этики
             ELSE IF(SUBJECT_ID = 181) THEN VAL = 12; -- Искусство
             ELSE IF(SUBJECT_ID = 202) THEN VAL = 13; -- Изобразительное искусство
             ELSE IF(SUBJECT_ID = 200) THEN VAL = 14; -- Технология
             ELSE IF(SUBJECT_ID = 205) THEN VAL = 15; -- Физическая культура
             -- ELSE IF(SUBJECT_ID = ) THEN VAL = 16; -- Общественно-научные предметы
             ELSE IF(SUBJECT_ID = 5532) THEN VAL = 17; -- Основы духовно-нравственной культуры народов России
             ELSE IF(SUBJECT_ID = 198) THEN VAL = 18; -- Физика
             ELSE IF(SUBJECT_ID = 199) THEN VAL = 19; -- Химия
             ELSE IF(SUBJECT_ID = 197) THEN VAL = 20; -- Биология
             ELSE IF(SUBJECT_ID IN (194, 175)) THEN VAL = 21; -- Обществознание
             ELSE IF(SUBJECT_ID = 174) THEN VAL = 22; -- История
             ELSE IF(SUBJECT_ID = 3151) THEN VAL = 23; -- История России
             ELSE IF(SUBJECT_ID = 3150) THEN VAL = 24; -- Всеобщая история
             ELSE IF(SUBJECT_ID = 3139) THEN VAL = 25; -- География
             ELSE IF(SUBJECT_ID = 172) THEN VAL = 26; -- Алгебра
             ELSE IF(SUBJECT_ID = 173) THEN VAL = 27; -- Геометрия
             ELSE IF(SUBJECT_ID = 206) THEN VAL = 28; -- Основы безопасности жизнедеятельности
             ELSE IF(SUBJECT_ID = 32843) THEN VAL = 29; -- Экономика
             ELSE IF(SUBJECT_ID = 3138) THEN VAL = 30; -- Право
             ELSE IF(SUBJECT_ID = 32840) THEN VAL = 31; -- Россия в мире
             ELSE IF(SUBJECT_ID = 32819) THEN VAL = 32; -- Математика: алгебра и начала математического анализа, геометрия
             ELSE IF(SUBJECT_ID = 177) THEN VAL = 33; -- Естествознание
             ELSE IF(SUBJECT_ID = 3160) THEN VAL = 34; -- Экология

             TAG_NAME = 'wsdl&colon;SubjectInput:discipline:code';
             IF(VAL IS NOT NULL) THEN SUSPEND;
          END

          N = N + 1;
          IF(N >= 10000) THEN
          BEGIN
              N = 0;
              TAG_NAME = NULL;
              VAL = 'DIVIDE';
              SUSPEND;
          END

      END

  END

  -- Только при полной выгрузке отправляем предмет Мероприятия
  IF(T_FROM IS NULL) THEN
  BEGIN
      TAG_NAME = 'wsdl&colon;SubjectInput';
      VAL = NULL;
      SUSPEND;

      TAG_NAME = 'wsdl&colon;SubjectInput:identity:external_id';
      VAL = 'event';
      SUSPEND;

      TAG_NAME = 'wsdl&colon;SubjectInput:institution_id:id';
      VAL = ID1;
      SUSPEND;

      TAG_NAME = 'wsdl&colon;SubjectInput:name';
      VAL = 'Мероприятия';
      SUSPEND;

      TAG_NAME = 'wsdl&colon;SubjectInput:additional_name';
      VAL = 'Н/Д';
      SUSPEND;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_PORTAL_SUBJECTS_DELETE (
    T_FROM TIMESTAMP,
    T_TO TIMESTAMP NOT NULL,
    ID1 VARCHAR(40) = null,
    ID2 VARCHAR(40) = null,
    I$MODE SMALLINT = 0)
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(2000))
AS
begin

  -- Пока удаление предметов не делаем

  IF(T_FROM IS NULL) THEN EXIT;

  IF(0 = 1) THEN SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_PORTAL_TASKS (
    T_FROM TIMESTAMP,
    T_TO TIMESTAMP NOT NULL = current_timestamp,
    ID1 VARCHAR(40) = null,
    ID2 VARCHAR(40) = null,
    I$MODE SMALLINT = 0)
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(2000))
AS
declare variable YEAR_ID bigint;
declare variable LESSON_ID bigint;
declare variable HOMEWORK_TEXT varchar(1000);
declare variable S varchar(1000);
declare variable N integer;
begin

  SELECT FIRST 1 V1236.LISTVAL_ID
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :YEAR_ID;

  N = 0;

  FOR
      SELECT L.OBJ_ID, L.LESSON_HOMEWORK
      FROM CJ2_JOURNAL J
      JOIN CJ2_JOURNAL_LESSONS L ON L.CJ_ID = J.OBJ_ID AND L.DATE_DEL IS NULL
      JOIN LINKS L179 ON L179.OBJ_ID = J.GRADE_ID AND L179.OBJ_TYPE_ID = 179 AND L179.PARENT_TYPE_ID = 2 AND L179.DATE_DEL IS NULL
      -- Признак группы ЦОПП
      LEFT JOIN VALL V3064 ON V3064.OBJ_ID = L179.OBJ_ID AND V3064.PARAM_ID = 3064 AND V3064.IS_DEL = 0
      -- а не надо ли тут дофильтровывать по типу ОП ?!!!
      WHERE J.DATE_DEL IS NULL AND J.JOURNAL_TYPE IN (0/*, 1*/) AND J.YEAR_ID = :YEAR_ID
          AND (L.IS_COMPLETED = 1 OR L.IS_PUBLISHED = 1) AND CHAR_LENGTH(L.LESSON_HOMEWORK) > 0 AND ((:T_FROM IS NULL OR L.DATE_MODIFY >= :T_FROM) AND L.DATE_MODIFY < :T_TO)
          AND ((:I$MODE = 0 AND (V3064.LISTVAL_ID IS NULL OR V3064.LISTVAL_ID = 3)) OR (:I$MODE = 1 AND V3064.LISTVAL_ID = 2))
      INTO :LESSON_ID, :HOMEWORK_TEXT
  DO
  BEGIN

      S = REPLACE(HOMEWORK_TEXT, ASCII_CHAR(13), '');
      S = REPLACE(S, ASCII_CHAR(10), '');
      S = REPLACE(S, ASCII_CHAR(9), '');
      S = TRIM(S);

      IF(CHAR_LENGTH(S) > 0) THEN
      BEGIN

          TAG_NAME = 'wsdl&colon;TaskInput';
          VAL = NULL;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;TaskInput:identity:external_id';
          VAL = LESSON_ID;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;TaskInput:name';
          VAL = S;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;TaskInput:content_task:task_kind:code';
          VAL = 'homework'; -- practice, test, classwork
          SUSPEND;

          N = N + 1;
          IF(N >= 10000) THEN
          BEGIN
              N = 0;
              TAG_NAME = NULL;
              VAL = 'DIVIDE';
              SUSPEND;
          END

      END

  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_PORTAL_TASKS_DELETE (
    T_FROM TIMESTAMP,
    T_TO TIMESTAMP NOT NULL = CURRENT_TIMESTAMP,
    ID1 VARCHAR(40) = NULL,
    ID2 VARCHAR(40) = NULL,
    I$MODE SMALLINT = 0)
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(2000))
AS
DECLARE VARIABLE YEAR_ID BIGINT;
DECLARE VARIABLE LESSON_ID BIGINT;
DECLARE VARIABLE LESSON_DT TIMESTAMP;
DECLARE VARIABLE IS_OK SMALLINT;
DECLARE VARIABLE N INTEGER;
begin

  IF(T_FROM IS NULL) THEN EXIT;

  SELECT FIRST 1 V1236.LISTVAL_ID
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :YEAR_ID;

  N = 0;

  -- Реально удаленные уроки
  FOR
      SELECT L.OBJ_ID, L.DATE_DEL
      FROM CJ2_JOURNAL J
      JOIN CJ2_JOURNAL_LESSONS L ON L.CJ_ID = J.OBJ_ID AND L.DATE_DEL IS NOT NULL
      JOIN LINKS L179 ON L179.OBJ_ID = J.GRADE_ID AND L179.OBJ_TYPE_ID = 179 AND L179.PARENT_TYPE_ID = 2 AND L179.DATE_DEL IS NULL
      -- Признак группы ЦОПП
      LEFT JOIN VALL V3064 ON V3064.OBJ_ID = L179.OBJ_ID AND V3064.PARAM_ID = 3064 AND V3064.IS_DEL = 0
      WHERE J.DATE_DEL IS NOT NULL AND J.JOURNAL_TYPE IN (0, 1) AND J.YEAR_ID = :YEAR_ID
          AND ((:I$MODE = 0 AND (V3064.LISTVAL_ID IS NULL OR V3064.LISTVAL_ID = 3)) OR (:I$MODE = 1 AND V3064.LISTVAL_ID = 2))
      INTO :LESSON_ID, :LESSON_DT
  DO
  BEGIN

      IS_OK = 0;
      IF(
          ((T_FROM IS NULL OR LESSON_DT >= T_FROM) AND LESSON_DT < T_TO)
      )
      THEN
          IS_OK = 1;

      IF(IS_OK = 1) THEN
      BEGIN

          TAG_NAME = 'wsdl&colon;IdentityElementInput';
          VAL = NULL;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;IdentityElementInput:identity:external_id';
          VAL = LESSON_ID;
          SUSPEND;

          N = N + 1;
          IF(N >= 10000) THEN
          BEGIN
              N = 0;
              TAG_NAME = NULL;
              VAL = 'DIVIDE';
              SUSPEND;
          END

      END

  END

  -- Уроки, где снят флаг проведения
  -- ...

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_PORTAL_TEACHERS (
    T_FROM TIMESTAMP,
    T_TO TIMESTAMP NOT NULL = current_timestamp,
    ID1 VARCHAR(40) = null,
    ID2 VARCHAR(40) = null,
    I$MODE SMALLINT = 0)
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(2000))
AS
declare variable PERSON_ID bigint;
declare variable PERSON_DT timestamp;
declare variable PORTAL_DT timestamp;
declare variable MV_DT timestamp;
declare variable MD_D1_DT timestamp;
declare variable MD_D2_DT timestamp;
declare variable IS_OK smallint;
declare variable JOB_NAME varchar(1000);
declare variable YEAR_START date;
declare variable N integer;
begin

  -- Поскольку любой сотрудник потенциально может вести любой урок (ГПД или внеурочку), выдаем всех учителей
  -- Название должности для работающих берем на 1 уровень вверх по дереву, с наименьшим значением
  -- для уволенных берем последнюю должность

  IF(ID1 IS NULL) THEN
  BEGIN
      SELECT FIRST 1 V2910.VAL
      FROM LINKS L2
      JOIN VALS V2910 ON V2910.OBJ_ID = L2.OBJ_ID AND V2910.PARAM_ID = 2910 AND V2910.IS_DEL = 0
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      INTO :ID1;
  END

  IF(EXTRACT(MONTH FROM CURRENT_DATE) < 9) THEN YEAR_START = '01.09.' || (EXTRACT(YEAR FROM CURRENT_DATE) - 1);
  ELSE YEAR_START = '01.09.' || EXTRACT(YEAR FROM CURRENT_DATE);

  N = 0;

  -- Выбираем действующих сотрудников
  FOR
      SELECT L14.OBJ_ID, L14.DATE_MODIFY
      FROM LINKS L2
      JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      INTO :PERSON_ID, :PERSON_DT
  DO
  BEGIN

      -- Момент последних изменений в назначениях и их датах
      MV_DT = NULL;
      MD_D1_DT = NULL;
      MD_D2_DT = NULL;
      SELECT MAX(L15.DATE_MODIFY), MAX(V73.DATE_MODIFY), MAX(V74.DATE_MODIFY)
      FROM LINKS L15
      JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0
      LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
      WHERE L15.PARENT_ID = :PERSON_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
      INTO :MV_DT, :MD_D1_DT, :MD_D2_DT;

      -- Только действующие должности. На изменения не обращаем внимания
      -- Изменено: были только причем только педагогические+, сейчас все кроме рабочих
      JOB_NAME = NULL;
      SELECT FIRST 1 1
      FROM LINKS L15
      JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
      JOIN VALL V63 ON V63.OBJ_ID = LP13.PARENT_ID AND V63.PARAM_ID = 63 AND V63.IS_DEL = 0 AND (V63.LISTVAL_ID NOT IN (1310, 1323) OR V63.LISTVAL_ID IN (1335, 3035))
      LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
      WHERE L15.PARENT_ID = :PERSON_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL AND (V74.VAL IS NULL OR V74.VAL > CURRENT_DATE)
      INTO :JOB_NAME;

      -- Метка изменения id петеробра или есиа
      PORTAL_DT = NULL;
      SELECT MIN(V267.DATE_MODIFY)
      FROM VALS V267
      WHERE V267.OBJ_ID = :PERSON_ID AND V267.PARAM_ID IN (267, 3061)
      INTO :PORTAL_DT;

      IS_OK = 0;
      IF((JOB_NAME IS NOT NULL) AND (
          ((T_FROM IS NULL OR PERSON_DT >= T_FROM) AND (PERSON_DT < T_TO)) OR
          ((T_FROM IS NULL OR MV_DT >= T_FROM) AND (MV_DT < T_TO)) OR
          ((T_FROM IS NULL OR PORTAL_DT >= T_FROM) AND (PORTAL_DT < T_TO)) OR
          ((T_FROM IS NULL OR MD_D1_DT >= T_FROM) AND (MD_D1_DT < T_TO)) OR
          ((T_FROM IS NULL OR MD_D2_DT >= T_FROM) AND (MD_D2_DT < T_TO))
        )
      )
      THEN
          IS_OK = 1;

      IF(IS_OK = 1) THEN
      BEGIN

          TAG_NAME = 'wsdl&colon;TeacherInput';
          VAL = NULL;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;TeacherInput:identity:external_id';
          VAL = PERSON_ID;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;TeacherInput:job_id:external_id';
          VAL = PERSON_ID;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;TeacherInput:institution_id:id';
          VAL = ID1;
          SUSPEND;

          N = N + 1;
          IF(N >= 10000) THEN
          BEGIN
              N = 0;
              TAG_NAME = NULL;
              VAL = 'DIVIDE';
              SUSPEND;
          END

      END

  END

  -- Выбираем сотрудников, уволенных не ранее 1 месяца от начала текущего учебного года
  FOR
      SELECT L14.OBJ_ID, L14.DATE_MODIFY
      FROM LINKS L2
      JOIN LINKS L84 ON L84.PARENT_ID = L2.OBJ_ID AND L84.OBJ_TYPE_ID = 84 AND L84.DATE_DEL IS NULL
      JOIN LINKS L14 ON L14.PARENT_ID = L84.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL AND L14.DATE_INS > DATEADD(-1 MONTH TO :YEAR_START)
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      INTO :PERSON_ID, :PERSON_DT
  DO
  BEGIN

      -- Момент последних изменений в назначениях и их датах
      MV_DT = NULL;
      MD_D1_DT = NULL;
      MD_D2_DT = NULL;
      SELECT MAX(L15.DATE_MODIFY), MAX(V73.DATE_MODIFY), MAX(V74.DATE_MODIFY)
      FROM LINKS L15
      JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0
      LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
      WHERE L15.PARENT_ID = :PERSON_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
      INTO :MV_DT, :MD_D1_DT, :MD_D2_DT;

      -- Берем последнюю должность, причем только педагогическую+
      JOB_NAME = NULL;
      SELECT FIRST 1 1
      FROM LINKS L15
      JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
      JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
      JOIN VALL V63 ON V63.OBJ_ID = LP13.PARENT_ID AND V63.PARAM_ID = 63 AND V63.IS_DEL = 0 AND (V63.LISTVAL_ID NOT IN (1310, 1323) OR V63.LISTVAL_ID IN (1335, 3035))
      WHERE L15.PARENT_ID = :PERSON_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
      INTO :JOB_NAME;

      -- Метка изменения id петеробра или есиа
      PORTAL_DT = NULL;
      SELECT MIN(V267.DATE_MODIFY)
      FROM VALS V267
      WHERE V267.OBJ_ID = :PERSON_ID AND V267.PARAM_ID IN (267, 3061)
      INTO :PORTAL_DT;

      IS_OK = 0;
      IF((JOB_NAME IS NOT NULL) AND (
          ((T_FROM IS NULL OR PERSON_DT >= T_FROM) AND (PERSON_DT < T_TO)) OR
          ((T_FROM IS NULL OR MV_DT >= T_FROM) AND (MV_DT < T_TO)) OR
          ((T_FROM IS NULL OR PORTAL_DT >= T_FROM) AND (PORTAL_DT < T_TO)) OR
          ((T_FROM IS NULL OR MD_D1_DT >= T_FROM) AND (MD_D1_DT < T_TO)) OR
          ((T_FROM IS NULL OR MD_D2_DT >= T_FROM) AND (MD_D2_DT < T_TO))
        )
      )
      THEN
          IS_OK = 1;

      IF(IS_OK = 1) THEN
      BEGIN

          TAG_NAME = 'wsdl&colon;TeacherInput';
          VAL = NULL;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;TeacherInput:identity:external_id';
          VAL = PERSON_ID;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;TeacherInput:job_id:external_id';
          VAL = PERSON_ID;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;TeacherInput:institution_id:id';
          VAL = ID1;
          SUSPEND;

          N = N + 1;
          IF(N >= 10000) THEN
          BEGIN
              N = 0;
              TAG_NAME = NULL;
              VAL = 'DIVIDE';
              SUSPEND;
          END

      END

  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_PORTAL_TEACHERS_DELETE (
    T_FROM TIMESTAMP,
    T_TO TIMESTAMP NOT NULL,
    ID1 VARCHAR(40) = null,
    ID2 VARCHAR(40) = null,
    I$MODE SMALLINT = 0)
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(2000))
AS
begin
  IF(T_FROM IS NULL) THEN EXIT;
  IF(0 = 1) THEN SUSPEND;
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_PORTAL_TEACHER_TO_SUBJECTS (
    T_FROM TIMESTAMP,
    T_TO TIMESTAMP NOT NULL,
    ID1 VARCHAR(40) = null,
    ID2 VARCHAR(40) = null,
    I$MODE SMALLINT = 0)
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(2000))
AS
declare variable YEAR_ID bigint;
declare variable PERSON_ID bigint;
declare variable PERSON_DT timestamp;
declare variable PORTAL_DT timestamp;
declare variable LOAD_ID bigint;
declare variable LOAD_DT timestamp;
declare variable SUBJECT_ID bigint;
declare variable IS_OK smallint;
declare variable N integer;
begin

  -- Выбираем список всех привязок учитель-предмет исходя из настроек учебных планов

  N = 0;

  -- Новая схема выгрузки по новому формату журналов
  SELECT FIRST 1 V1236.LISTVAL_ID
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :YEAR_ID;

  FOR
      SELECT J.TEACHER_ID, J.DATE_MODIFY, J.OBJ_ID, J.SUBJECT_ID
      FROM CJ2_JOURNAL J
      JOIN LINKS L179 ON L179.OBJ_ID = J.GRADE_ID AND L179.OBJ_TYPE_ID = 179 AND L179.PARENT_TYPE_ID = 2 AND L179.DATE_DEL IS NULL
      -- Признак группы ЦОПП
      LEFT JOIN VALL V3064 ON V3064.OBJ_ID = L179.OBJ_ID AND V3064.PARAM_ID = 3064 AND V3064.IS_DEL = 0
      WHERE J.DATE_DEL IS NULL AND J.JOURNAL_TYPE IN (0, 1, 10, 11) AND J.YEAR_ID = :YEAR_ID AND J.TEACHER_ID IS NOT NULL AND J.SUBJECT_ID IS NOT NULL
          AND ((:I$MODE = 0 AND (V3064.LISTVAL_ID IS NULL OR V3064.LISTVAL_ID = 3)) OR (:I$MODE = 1 AND V3064.LISTVAL_ID = 2))
      INTO :PERSON_ID, :PERSON_DT, :LOAD_ID, :SUBJECT_ID
  DO
  BEGIN

      -- Метка изменения id петеробра или ФИАС
      PORTAL_DT = NULL;
      SELECT MIN(V267.DATE_MODIFY)
      FROM VALS V267
      WHERE V267.OBJ_ID = :PERSON_ID AND V267.PARAM_ID IN (267, 3061)
      INTO :PORTAL_DT;

      IS_OK = 0;
      IF(
          ((T_FROM IS NULL OR PERSON_DT >= T_FROM) AND (PERSON_DT < T_TO)) OR
          ((T_FROM IS NULL OR PORTAL_DT >= T_FROM) AND (PORTAL_DT < T_TO))
      )
      THEN
          IS_OK = 1;

      IF(IS_OK = 1) THEN
      BEGIN

          TAG_NAME = 'wsdl&colon;TeacherSubjectInput';
          VAL = NULL;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;TeacherSubjectInput:identity:external_id';
          VAL = LOAD_ID;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;TeacherSubjectInput:teacher_id:external_id';
          VAL = PERSON_ID;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;TeacherSubjectInput:subject_id:external_id';
          VAL = SUBJECT_ID;
          SUSPEND;

          N = N + 1;
          IF(N >= 10000) THEN
          BEGIN
              N = 0;
              TAG_NAME = NULL;
              VAL = 'DIVIDE';
              SUSPEND;
          END

      END

  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_PORTAL_TTS__DELETE (
    T_FROM TIMESTAMP,
    T_TO TIMESTAMP NOT NULL,
    ID1 VARCHAR(40) = null,
    ID2 VARCHAR(40) = null,
    I$MODE SMALLINT = 0)
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(2000))
AS
declare variable LOAD_ID bigint;
declare variable LOAD_DT timestamp;
declare variable IS_OK smallint;
declare variable N integer;
begin

  IF(T_FROM IS NULL) THEN EXIT;

  N = 0;

  -- Выбираем все удаленные нагрузки и удаленные связи нагрузка-учитель
  FOR
      SELECT L58.OBJ_ID, L58.DATE_DEL
      FROM LINKS L58
      WHERE L58.OBJ_TYPE_ID = 58 AND L58.PARENT_TYPE_ID = 14 AND L58.DATE_DEL >= :T_FROM
      UNION ALL
      SELECT L.OBJ_ID, L.DATE_DEL
      FROM PLAN_LOADS L
      WHERE L.DATE_DEL >= :T_FROM
      INTO :LOAD_ID, :LOAD_DT
  DO
  BEGIN

      IS_OK = 0;
      IF(
          ((T_FROM IS NULL OR LOAD_DT >= T_FROM) AND LOAD_DT < T_TO)
      )
      THEN
          IS_OK = 1;

      IF(IS_OK = 1) THEN
      BEGIN

          TAG_NAME = 'wsdl&colon;IdentityElementInput';
          VAL = NULL;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;IdentityElementInput:identity:external_id';
          VAL = LOAD_ID;
          SUSPEND;

          N = N + 1;
          IF(N >= 10000) THEN
          BEGIN
              N = 0;
              TAG_NAME = NULL;
              VAL = 'DIVIDE';
              SUSPEND;
          END

      END

  END

  -- Выбираем все удаленные журналы - истории нагрузок у нас нет
  FOR
      SELECT J.OBJ_ID, J.DATE_MODIFY
      FROM CJ2_JOURNAL J
      JOIN LINKS L179 ON L179.OBJ_ID = J.GRADE_ID AND L179.OBJ_TYPE_ID = 179 AND L179.PARENT_TYPE_ID = 2 AND L179.DATE_DEL IS NULL
      -- Признак группы ЦОПП
      LEFT JOIN VALL V3064 ON V3064.OBJ_ID = L179.OBJ_ID AND V3064.PARAM_ID = 3064 AND V3064.IS_DEL = 0
      WHERE J.DATE_DEL IS NOT NULL AND J.JOURNAL_TYPE = 0 -- AND J.YEAR_ID = :YEAR_ID
          AND ((:I$MODE = 0 AND (V3064.LISTVAL_ID IS NULL OR V3064.LISTVAL_ID = 3)) OR (:I$MODE = 1 AND V3064.LISTVAL_ID = 2))
      INTO :LOAD_ID, :LOAD_DT
  DO
  BEGIN

      IS_OK = 0;
      IF(
          ((T_FROM IS NULL OR LOAD_DT >= T_FROM) AND LOAD_DT < T_TO)
      )
      THEN
          IS_OK = 1;

      IF(IS_OK = 1) THEN
      BEGIN

          TAG_NAME = 'wsdl&colon;IdentityElementInput';
          VAL = NULL;
          SUSPEND;

          TAG_NAME = 'wsdl&colon;IdentityElementInput:identity:external_id';
          VAL = LOAD_ID;
          SUSPEND;

          N = N + 1;
          IF(N >= 10000) THEN
          BEGIN
              N = 0;
              TAG_NAME = NULL;
              VAL = 'DIVIDE';
              SUSPEND;
          END

      END

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_PUPIL_GRADUATE_LIST (
    I$GRADE_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
declare variable V$OBJ_ID bigint;
declare variable V$N1 varchar(400);
declare variable V$N2 varchar(400);
declare variable V$N3 varchar(400);
begin

  TAG_NAME = 'data::json&colon;array';
  VAL = 1;
  SUSPEND;

  FOR
    SELECT L10.OBJ_ID, V55.SVAL, V56.SVAL, V57.SVAL
    FROM LINKS L10
    JOIN VALS V55 ON V55.OBJ_ID = L10.OBJ_ID AND V55.PARAM_ID = 55 AND V55.IS_DEL = 0
    JOIN VALS V56 ON V56.OBJ_ID = L10.OBJ_ID AND V56.PARAM_ID = 56 AND V56.IS_DEL = 0
    LEFT JOIN VALS V57 ON V57.OBJ_ID = L10.OBJ_ID AND V57.PARAM_ID = 57 AND V57.IS_DEL = 0
    WHERE L10.PARENT_ID = :I$GRADE_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    ORDER BY 2, 3, 4
    INTO :V$OBJ_ID, :V$N1, :V$N2, :V$N3
  DO
  BEGIN
    TAG_NAME = 'data:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'data:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'data:r:name_last';
    VAL = V$N1;
    SUSPEND;
    TAG_NAME = 'data:r:name_first';
    VAL = V$N2;
    SUSPEND;
    TAG_NAME = 'data:r:name_mid';
    VAL = V$N3;
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_PUPIL_LEAVE_LIST (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$LEVEL_ID BIGINT;
DECLARE VARIABLE V$STATUS VARCHAR(1);
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$PARENT_ID BIGINT;
DECLARE VARIABLE V$ACAD_ID BIGINT;
DECLARE VARIABLE V$AREA_ID BIGINT;
DECLARE VARIABLE PF BIGINT;
DECLARE VARIABLE TT BIGINT;
DECLARE VARIABLE S VARCHAR(1000);
DECLARE VARIABLE S2 VARCHAR(1000);
DECLARE VARIABLE S3 VARCHAR(100);
DECLARE VARIABLE V VARCHAR(1000);
DECLARE VARIABLE N INTEGER;
DECLARE VARIABLE NN INTEGER;
begin

  V$STATUS = (SELECT STATUS FROM OU_LICENCE_TYPE);
  TAG_NAME = 'lic_type';
  VAL = V$STATUS;
  SUSPEND;

  -- Мой район
  TAG_NAME = 'area_id';
  VAL = NULL;
  SELECT FIRST 1 V2163.LISTVAL_ID
  FROM LINKS L2
  JOIN VALL V2163 ON V2163.OBJ_ID = L2.OBJ_ID AND V2163.PARAM_ID = 2163 AND V2163.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :VAL;
  SUSPEND;

  SELECT FIRST 1 LP289.PARENT_ID
  FROM LINKS LP289
  WHERE LP289.OBJ_ID = :I$OBJ_ID AND LP289.PARENT_TYPE_ID = 289 AND LP289.DATE_DEL IS NULL
  INTO :V$ACAD_ID;

  -- В каком уровне образования находится обучающийся
  TAG_NAME = 'level_id';
  SELECT FIRST 1 V43.LISTVAL_ID
  FROM LINKS LP9
  JOIN LINKS LP8 ON LP8.OBJ_ID = LP9.PARENT_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
  JOIN LINKS LP7 ON LP7.OBJ_ID = LP8.PARENT_ID AND LP7.PARENT_TYPE_ID = 7 AND LP7.DATE_DEL IS NULL
  JOIN VALL V43 ON V43.OBJ_ID = LP7.PARENT_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0
  WHERE LP9.OBJ_ID = :I$OBJ_ID AND LP9.PARENT_TYPE_ID IN (9, 187) AND LP9.DATE_DEL IS NULL
  INTO :V$LEVEL_ID;
  -- Для академического отпуска
  IF(V$ACAD_ID IS NOT NULL) THEN V$LEVEL_ID = 29;
  VAL = V$LEVEL_ID;
  SUSPEND;

  -- Выбор типа движения - вместо FILTRED_LIST берем текущий уровень
  TAG_NAME = 'action_type:selection::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L.LISTVAL_ID, L.VAL
    FROM LISTVALS_LIST(122) L
    WHERE L.IS_DEL = 0 AND L."FILTER" LIKE '%LEAVED%' AND
    (
      (:V$LEVEL_ID IN (22, 26, 27) AND L."FILTER" LIKE '%GOU%') OR
      (:V$LEVEL_ID IN (28, 29, 13129, 13131) AND L."FILTER" LIKE '%COLLEGE%') OR
      (:V$LEVEL_ID IN (3263, 3264) AND L."FILTER" LIKE '%DOU%')
    )
    INTO :V$OBJ_ID, :S
  DO
  BEGIN
    -- Прячем академический отпуск, если мы уже там
    IF(V$OBJ_ID = 5319 AND V$ACAD_ID IS NOT NULL) THEN S = NULL;
    IF(S IS NOT NULL) THEN
    BEGIN
      TAG_NAME = 'action_type:selection:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'action_type:selection:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'action_type:selection:r:value';
      VAL = S;
      SUSPEND;
    END
  END
  TAG_NAME = 'action_type:values:value';
  IF(V$STATUS = 'O' OR V$LEVEL_ID IN (22, 26, 27)) THEN VAL = 811;
  ELSE IF(V$STATUS = 'C' OR V$LEVEL_ID IN (28, 29, 13129, 13131)) THEN VAL = 5316; -- по личному заявлению
  ELSE IF(V$STATUS = 'D' OR V$LEVEL_ID IN (3263, 3264)) THEN VAL = 811;
  ELSE IF(V$STATUS = 'U') THEN VAL = 5548;
  ELSE IF(V$STATUS = 'P') THEN VAL = 5548;
  SUSPEND;

  -- Выбыл в, параметр 105
  -- сразу фильтруем исходя из того, на каком уровне сейчас находится обучающийся
  TAG_NAME = 'leave_for:selection::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L.LISTVAL_ID, L.VAL
    FROM LISTVALS_LIST(127) L
    WHERE L.IS_DEL = 0 AND
    (
      (:V$LEVEL_ID IN (22, 26, 27) AND L."FILTER" LIKE '%GOU%') OR
      (:V$LEVEL_ID IN (28, 29, 13129, 13131) AND L."FILTER" LIKE '%COLLEGE%') OR
      (:V$LEVEL_ID IN (3263, 3264) AND L."FILTER" LIKE '%DOU%')
    )
    INTO :V$OBJ_ID, :S
  DO
  BEGIN
    TAG_NAME = 'leave_for:selection:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'leave_for:selection:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'leave_for:selection:r:value';
    VAL = S;
    SUSPEND;
  END
  TAG_NAME = 'leave_for:values:value';
  VAL = NULL;
  SUSPEND;

  TAG_NAME = 'have_doc:selection::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L.LISTVAL_ID, L.VAL
    FROM LISTVALS_LIST(3) L
    WHERE L.IS_DEL = 0
    INTO :V$OBJ_ID, :S
  DO
  BEGIN
    TAG_NAME = 'have_doc:selection:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'have_doc:selection:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'have_doc:selection:r:value';
    VAL = S;
    SUSPEND;
  END
  TAG_NAME = 'have_doc:values:value';
  VAL = NULL;
  SUSPEND;

  -- Списки выбора
  TAG_NAME = 'oood_area:selection::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L.LISTVAL_ID, L.VAL
    FROM LISTVALS_LIST(7) L
    WHERE L.IS_DEL = 0
    INTO :V$OBJ_ID, :S
  DO
  BEGIN
    TAG_NAME = 'oood_area:selection:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'oood_area:selection:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'oood_area:selection:r:value';
    VAL = S;
    SUSPEND;
  END
  TAG_NAME = 'oood_area:values:value';
  VAL = NULL;
  SUSPEND;

  TAG_NAME = 'oood_kind:selection::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L.LISTVAL_ID, L.PARENT_ID, L.VAL
    FROM LISTVALS_LIST(6) L
    WHERE L.IS_DEL = 0
    INTO :V$OBJ_ID, :V$PARENT_ID, :S
  DO
  BEGIN
    TAG_NAME = 'oood_kind:selection:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'oood_kind:selection:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'oood_kind:selection:r:parent_id';
    VAL = V$PARENT_ID;
    SUSPEND;
    TAG_NAME = 'oood_kind:selection:r:value';
    VAL = S;
    SUSPEND;
  END
  TAG_NAME = 'oood_kind:values:value';
  VAL = NULL;
  SUSPEND;

  TAG_NAME = 'oood_opfr:selection::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L.LISTVAL_ID, L.VAL
    FROM LISTVALS_LIST(4) L
    WHERE L.IS_DEL = 0
    INTO :V$OBJ_ID, :S
  DO
  BEGIN
    TAG_NAME = 'oood_opfr:selection:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'oood_opfr:selection:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'oood_opfr:selection:r:value';
    VAL = S;
    SUSPEND;
  END
  TAG_NAME = 'oood_opfr:values:value';
  VAL = NULL;
  SUSPEND;

  TAG_NAME = 'leave_to_class:selection::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L.LISTVAL_ID, L.VAL
    FROM LISTVALS_LIST(32) L
    WHERE L.IS_DEL = 0
    INTO :V$OBJ_ID, :S
  DO
  BEGIN
    TAG_NAME = 'leave_to_class:selection:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'leave_to_class:selection:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'leave_to_class:selection:r:value';
    VAL = S;
    SUSPEND;
  END
  TAG_NAME = 'leave_to_class:values:value';
  VAL = NULL;
  SUSPEND;

  -- Списки выбора по типам ОУ
  -- Для СПО нам вообще пофиг, для ДОУ могут быть и школы и ДОУ; для школ школы и СПО
  SELECT MON$DATABASE_NAME FROM MON$DATABASE INTO :V;
  V = REPLACE(V, 'BASE.FDB', 'BIN.FDB');

  IF(V$LEVEL_ID IN (3263, 3264)) THEN
  BEGIN
    -- Для садов только название
    TAG_NAME = 'list_dou::json&colon;array';
    VAL = 1;
    SUSPEND;
    N = 0;
    WHILE (N IS NOT NULL) DO
    BEGIN
      NN = N;
      N = NULL;
      EXECUTE STATEMENT 'SELECT FIRST 1 SCHOOLID, SCHOOLNO, FULLNAME, SHORTNAME, DISTRICTID, PROPERTYFORMID, NEWTYPEID FROM SCHOOL WHERE OU_TYPE = 3 AND SCHOOLID > ' || NN || ' ORDER BY 1'
      ON EXTERNAL :V
      WITH COMMON TRANSACTION
      INTO :N, :S3, :S, :S2, :V$AREA_ID, :PF, :TT;

      IF(N IS NOT NULL) THEN
      BEGIN
        TAG_NAME = 'list_dou:r';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'list_dou:r:num';
        VAL = S3;
        SUSPEND;
        TAG_NAME = 'list_dou:r:name_full';
        VAL = S;
        SUSPEND;
        TAG_NAME = 'list_dou:r:name_short';
        VAL = S2;
        SUSPEND;
        TAG_NAME = 'list_dou:r:area_id';
        VAL = V$AREA_ID;
        SUSPEND;
        TAG_NAME = 'list_dou:r:prop_type';
        VAL = PF;
        SUSPEND;
        TAG_NAME = 'list_dou:r:type';
        VAL = TT;
        SUSPEND;
      END
    END
  END

  IF(V$LEVEL_ID IN (3263, 3264, 22, 26, 27)) THEN
  BEGIN
    -- Для школ кроме названия еще форма собственности, тип и район
    TAG_NAME = 'list_ou::json&colon;array';
    VAL = 1;
    SUSPEND;
    N = 0;
    WHILE (N IS NOT NULL) DO
    BEGIN
      NN = N;
      N = NULL;
      EXECUTE STATEMENT 'SELECT FIRST 1 SCHOOLID, SCHOOLNO, FULLNAME, SHORTNAME, DISTRICTID, PROPERTYFORMID, NEWTYPEID FROM SCHOOL WHERE OU_TYPE = 1 AND SCHOOLID > ' || NN || ' ORDER BY 1'
      ON EXTERNAL :V
      WITH COMMON TRANSACTION
      INTO :N, :S3, :S, :S2, :V$AREA_ID, :PF, :TT;

      IF(N IS NOT NULL) THEN
      BEGIN
        TAG_NAME = 'list_ou:r';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'list_ou:r:num';
        VAL = S3;
        SUSPEND;
        TAG_NAME = 'list_ou:r:name_full';
        VAL = S;
        SUSPEND;
        TAG_NAME = 'list_ou:r:name_short';
        VAL = S2;
        SUSPEND;
        TAG_NAME = 'list_ou:r:area_id';
        VAL = V$AREA_ID;
        SUSPEND;
        TAG_NAME = 'list_ou:r:prop_type';
        IF(PF = 5393) THEN PF = 7;
        IF(PF = 5394) THEN PF = 6;
        IF(PF = 5398) THEN PF = 945;
        IF(PF = 5401) THEN PF = 3256;
        IF(PF = 5402) THEN PF = 3257;
        IF(PF = 5404) THEN PF = 1734;
        IF(PF = 5407) THEN PF = NULL;
        IF(PF = 5408) THEN PF = 1734;
        IF(PF = 5415) THEN PF = 1734;
        VAL = PF;
        SUSPEND;
        TAG_NAME = 'list_ou:r:type';
        VAL = TT;
        SUSPEND;
      END
    END
  END

  IF(V$LEVEL_ID IN (22, 26, 27)) THEN
  BEGIN
    TAG_NAME = 'list_spo::json&colon;array';
    VAL = 1;
    SUSPEND;
    N = 0;
    WHILE (N IS NOT NULL) DO
    BEGIN
      NN = N;
      N = NULL;
      EXECUTE STATEMENT 'SELECT FIRST 1 SCHOOLID, SCHOOLNO, FULLNAME, SHORTNAME, DISTRICTID, PROPERTYFORMID, NEWTYPEID FROM SCHOOL WHERE OU_TYPE = 2 AND SCHOOLID > ' || NN || ' ORDER BY 1'
      ON EXTERNAL :V
      WITH COMMON TRANSACTION
      INTO :N, :S3, :S, :S2, :V$AREA_ID, :PF, :TT;

      IF(N IS NOT NULL) THEN
      BEGIN
        TAG_NAME = 'list_spo:r';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'list_spo:r:num';
        VAL = S3;
        SUSPEND;
        TAG_NAME = 'list_spo:r:name_full';
        VAL = S;
        SUSPEND;
        TAG_NAME = 'list_spo:r:name_short';
        VAL = S2;
        SUSPEND;
      END
    END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_PUPIL_MOVEMENTS (
    I$STUDENT_ID BIGINT,
    I$GROUP_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
declare variable V$YEAR integer;
declare variable V$OBJ_ID bigint;
declare variable V$REASON_IN_ID bigint;
declare variable V$REASON_OUT_ID bigint;
declare variable V$DATE_IN date;
declare variable V$ORDER_DATE_IN date;
declare variable V$ORDER_NUM_IN varchar(400);
declare variable V$DATE_OUT date;
declare variable V$ORDER_DATE_OUT date;
declare variable V$ORDER_NUM_OUT varchar(400);
declare variable V$NAME_IN varchar(1000);
declare variable V$R1 varchar(400);
declare variable V$R2 varchar(400);
declare variable V$STAGE_ID bigint;
declare variable V$VS varchar(400);
declare variable V$USER1 varchar(100);
declare variable V$USER2 varchar(100);
begin

  -- Менять движения можно только в пределах текущего учебного года
  SELECT FIRST 1 LV.COST
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$YEAR;

  IF(V$YEAR IS NULL) THEN EXCEPTION DATA_ERROR 'Не задан текущий учебный год';

  -- Выбираем данные сразу из нового реестра движения
  TAG_NAME = 'data::json&colon;array';
  VAL = 1;
  SUSPEND;

  FOR
    SELECT M.OBJ_ID, M.DATE_IN, M.ORDER_DATE_IN, M.ORDER_NUM_IN, M.DATE_OUT, M.ORDER_DATE_OUT, M.ORDER_NUM_OUT, M.NAME_IN,
      M.REASON_IN, M.REASON_OUT, R1.VAL, R2.VAL, M.STAGE_ID, RS.VAL, U1.USER_NAME, U2.USER_NAME
    FROM PERSON_MOVEMENTS M
    JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID IN (9, 125, 187, 289)
    JOIN LISTVALS LV1 ON LV1.LISTVAL_ID = M.REASON_IN
    JOIN RES R1 ON R1.RES_ID = LV1.RES_ID AND R1.LANG_CODE = 'RU'
    LEFT JOIN LISTVALS LV2 ON LV2.LISTVAL_ID = M.REASON_OUT
    LEFT JOIN RES R2 ON R2.RES_ID = LV2.RES_ID AND R2.LANG_CODE = 'RU'
    LEFT JOIN LISTVALS LVS ON LVS.LISTVAL_ID = M.STAGE_ID
    LEFT JOIN RES RS ON RS.RES_ID = LVS.RES_ID AND RS.LANG_CODE = 'RU'
    LEFT JOIN USERS U1 ON U1.USER_ID = M.USER_IN
    LEFT JOIN USERS U2 ON U2.USER_ID = M.USER_OUT
    WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :I$STUDENT_ID
    ORDER BY M.OBJ_ID
    INTO :V$OBJ_ID, :V$DATE_IN, :V$ORDER_DATE_IN, :V$ORDER_NUM_IN, :V$DATE_OUT, :V$ORDER_DATE_OUT, :V$ORDER_NUM_OUT, :V$NAME_IN,
      :V$REASON_IN_ID, :V$REASON_OUT_ID, :V$R1, :V$R2, :V$STAGE_ID, :V$VS, :V$USER1, :V$USER2
  DO
  BEGIN
    -- Прием
    TAG_NAME = 'data:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'data:r:id';
    VAL = V$OBJ_ID || '-in';
    SUSPEND;
    TAG_NAME = 'data:r:reason_id';
    VAL = V$REASON_IN_ID;
    SUSPEND;
    TAG_NAME = 'data:r:reason_name';
    VAL = V$R1;
    SUSPEND;
    TAG_NAME = 'data:r:grade_name';
    VAL = V$NAME_IN;
    SUSPEND;
    TAG_NAME = 'data:r:date';
    VAL = (SELECT VAL FROM DATE2ISO(:V$DATE_IN, 0));
    SUSPEND;
    TAG_NAME = 'data:r:order_date';
    VAL = (SELECT VAL FROM DATE2ISO(:V$ORDER_DATE_IN, 0));
    SUSPEND;
    TAG_NAME = 'data:r:order_num';
    VAL = V$ORDER_NUM_IN;
    SUSPEND;
    TAG_NAME = 'data:r:stage_id';
    VAL = V$STAGE_ID;
    SUSPEND;
    TAG_NAME = 'data:r:stage_name';
    VAL = V$VS;
    SUSPEND;
    TAG_NAME = 'data:r:enabled';
    VAL = IIF(V$DATE_IN >= '01.09.' || V$YEAR, '1', '0');
    SUSPEND;
    TAG_NAME = 'data:r:author';
    VAL = V$USER1;
    SUSPEND;
    -- Выбытие
    IF(V$DATE_OUT IS NOT NULL) THEN
    BEGIN
    TAG_NAME = 'data:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'data:r:id';
    VAL = V$OBJ_ID || '-out';
    SUSPEND;
    TAG_NAME = 'data:r:reason_id';
    VAL = V$REASON_OUT_ID;
    SUSPEND;
    TAG_NAME = 'data:r:reason_name';
    VAL = V$R2;
    SUSPEND;
    TAG_NAME = 'data:r:grade_name';
    VAL = V$NAME_IN;
    SUSPEND;
    TAG_NAME = 'data:r:date';
    VAL = (SELECT VAL FROM DATE2ISO(:V$DATE_OUT, 0));
    SUSPEND;
    TAG_NAME = 'data:r:order_date';
    VAL = (SELECT VAL FROM DATE2ISO(:V$ORDER_DATE_OUT, 0));
    SUSPEND;
    TAG_NAME = 'data:r:order_num';
    VAL = V$ORDER_NUM_OUT;
    SUSPEND;
    TAG_NAME = 'data:r:stage_id';
    VAL = V$STAGE_ID;
    SUSPEND;
    TAG_NAME = 'data:r:stage_name';
    VAL = V$VS;
    SUSPEND;
    TAG_NAME = 'data:r:enabled';
    VAL = IIF(V$DATE_OUT >= '01.09.' || V$YEAR, '1', '0');
    SUSPEND;
    TAG_NAME = 'data:r:author';
    VAL = V$USER2;
    SUSPEND;
    END
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_RBOOK_ESTIMATIONS (
    I$DT1 TIMESTAMP,
    I$DT2 TIMESTAMP = CURRENT_TIMESTAMP)
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$PERSON_ID BIGINT;
DECLARE VARIABLE V$REGID VARCHAR(100);
DECLARE VARIABLE V$GROUP_ID BIGINT;
DECLARE VARIABLE V$OGRN VARCHAR(100);
DECLARE VARIABLE V$STAGE_ID BIGINT;
DECLARE VARIABLE V$DT TIMESTAMP;
DECLARE VARIABLE V$DT1 TIMESTAMP;
DECLARE VARIABLE V$DT2 TIMESTAMP;
DECLARE VARIABLE V$DT3 TIMESTAMP;
DECLARE VARIABLE V$DT4 TIMESTAMP;
DECLARE VARIABLE V$DT5 TIMESTAMP;
DECLARE VARIABLE V$NAME_LAST VARCHAR(400);
DECLARE VARIABLE V$NAME_FIRST VARCHAR(400);
DECLARE VARIABLE V$NAME_MID VARCHAR(400);
DECLARE VARIABLE V$DATE DATE;
DECLARE VARIABLE P INTEGER;
DECLARE VARIABLE V$YEAR_DATE DATE;
DECLARE VARIABLE S VARCHAR(1000);
DECLARE VARIABLE T VARCHAR(1000);
DECLARE VARIABLE V$ASSN_ID BIGINT;
DECLARE VARIABLE ST SMALLINT;
DECLARE VARIABLE V BIGINT;
DECLARE VARIABLE CT BIGINT;
begin

  -- Только текущие студенты
  -- Корневой элемент формируется json массивом снаружи выборки

  SELECT FIRST 1 V9.VAL, CAST(LV.TAG AS DATE)
  FROM LINKS L2
  JOIN VALS V9 ON V9.OBJ_ID = L2.OBJ_ID AND V9.PARAM_ID = 9 AND V9.IS_DEL = 0
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$OGRN, :V$YEAR_DATE;

  FOR
    SELECT M.OBJ_ID, M.PERSON_ID, V2912.SVAL, M.GROUP_ID, M.STAGE_ID, M.DATE_ADD,
      V55.SVAL, V55.DATE_MODIFY, V56.SVAL, V56.DATE_MODIFY, V57.SVAL, V57.DATE_MODIFY, V89.VAL, V89.DATE_MODIFY
    FROM PERSON_MOVEMENTS M
    JOIN VALS V2912 ON V2912.OBJ_ID = M.PERSON_ID AND V2912.PARAM_ID = 2912 AND V2912.IS_DEL = 0
    JOIN VALS V55 ON V55.OBJ_ID = M.PERSON_ID AND V55.PARAM_ID = 55 AND V55.IS_DEL = 0
    JOIN VALS V56 ON V56.OBJ_ID = M.PERSON_ID AND V56.PARAM_ID = 56 AND V56.IS_DEL = 0
    LEFT JOIN VALS V57 ON V57.OBJ_ID = M.PERSON_ID AND V57.PARAM_ID = 57 AND V57.IS_DEL = 0
    JOIN VALD V89 ON V89.OBJ_ID = M.PERSON_ID AND V89.PARAM_ID = 89 AND V89.IS_DEL = 0
    WHERE M.DATE_DEL IS NULL AND M.GROUP_TYPE_ID = 9 AND M.DATE_OUT IS NULL AND M.LEVEL_ID = 29
    ORDER BY 4, 3
    INTO :V$OBJ_ID, :V$PERSON_ID, :V$REGID, :V$GROUP_ID, :V$STAGE_ID, :V$DT,
      :V$NAME_LAST, :V$DT1, :V$NAME_FIRST, :V$DT2, :V$NAME_MID, :V$DT3, :V$DATE, :V$DT4
  DO
  BEGIN
    V$DT5 = NULL;
    SELECT MAX(M.DATE_MODIFY)
    FROM ATT_REGISTER_STDS S
    JOIN ATT_REGISTER R ON R.DATE_DEL IS NULL AND R.OBJ_ID = S.ATT_ID AND R.STATE_ID <> 3
    JOIN VALM M ON M.MARK_ID = S.MARK_ID
    WHERE S.DATE_DEL IS NULL AND S.PERSON_ID = :V$PERSON_ID AND R.ATT_DATE >= :V$YEAR_DATE AND S.DATE_MODIFY >= :I$DT1
    INTO :V$DT5;

    IF(I$DT1 IS NULL OR V$DT >= I$DT1 OR V$DT1 >= I$DT1 OR V$DT2 >= I$DT1 OR V$DT3 >= I$DT1 OR V$DT4 >= I$DT1 OR V$DT5 >= I$DT1) THEN
    BEGIN
      TAG_NAME = 'r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'r:regID';
      VAL = REPLACE(REPLACE(LOWER(V$REGID), '{', ''), '}', '');
      P = POSITION(':' IN VAL);
      IF(P > 0) THEN VAL = SUBSTRING(VAL FROM 1 FOR P - 1);
      SUSPEND;
      TAG_NAME = 'r:last_name';
      VAL = V$NAME_LAST;
      SUSPEND;
      TAG_NAME = 'r:first_name';
      VAL = V$NAME_FIRST;
      SUSPEND;
      TAG_NAME = 'r:middle_name';
      VAL = V$NAME_MID;
      SUSPEND;
      TAG_NAME = 'r:birthdate';
      VAL = (SELECT VAL FROM DATE2ISO(:V$DATE, 0));
      SUSPEND;
      TAG_NAME = 'r:results_info::json&colon;array';
      VAL = 1;
      SUSPEND;
      FOR
        SELECT M.MARK_ID, M.DATE_MODIFY, SC.SCAPTION, M.MARK_DATE, I.STUFF_NAME, R.SUBSTAGE_ID, R.CONTROL_TYPE_ID, M.MARKVAL_ID
        FROM ATT_REGISTER_STDS S
        JOIN ATT_REGISTER R ON R.DATE_DEL IS NULL AND R.OBJ_ID = S.ATT_ID AND R.STATE_ID <> 3
        JOIN VALM M ON M.MARK_ID = S.MARK_ID AND M.IS_DEL = 0
        LEFT JOIN OBJECT_CAPTION_GET(R.SUBJECT_ID) SC ON 1 = 1
        LEFT JOIN ATT_INFO_GET(R.OBJ_ID, R.STATE_ID) I ON 1 = 1
        WHERE S.DATE_DEL IS NULL AND S.PERSON_ID = :V$PERSON_ID AND R.ATT_DATE >= :V$YEAR_DATE AND M.DATE_MODIFY >= :I$DT1
        ORDER BY 4
        INTO :V$ASSN_ID, :V$DT, :S, :V$DATE, :T, :ST, :CT, :V
      DO
      BEGIN
        TAG_NAME = 'r:results_info:r';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'r:results_info:r:result_id';
        VAL = V$ASSN_ID;
        SUSPEND;
        TAG_NAME = 'r:results_info:r:institution_ogrn';
        VAL = V$OGRN;
        SUSPEND;
        TAG_NAME = 'r:results_info:r:datetime';
        VAL = (SELECT VAL FROM DATE2ISO(:V$DATE, 1)); -- времени у нас нет !
        SUSPEND;
        TAG_NAME = 'r:results_info:r:subject';
        VAL = S;
        SUSPEND;
        TAG_NAME = 'r:results_info:r:control_type';
        VAL = (SELECT VAL FROM LISTVAL_TEXT(:CT));
        SUSPEND;
        TAG_NAME = 'r:results_info:r:examiner';
        VAL = T;
        SUSPEND;
        TAG_NAME = 'r:results_info:r:result';
        IF(V IN (3014, 3015)) THEN VAL = 'Не удовлетворительно';
        ELSE IF(V = 3016) THEN VAL = 'Удовлетворительно';
        ELSE IF(V = 3017) THEN VAL = 'Хорошо';
        ELSE IF(V = 3018) THEN VAL = 'Отлично';
        ELSE IF(V = 3019) THEN VAL = 'Зачет';
        ELSE IF(V = 3020) THEN VAL = 'Незачет';
        ELSE IF(V = 3021) THEN VAL = 'Освобожден';
        ELSE IF(V = 3022) THEN VAL = 'НАН';
        ELSE IF(V = 3023) THEN VAL = 'НАУ';
        ELSE VAL = (SELECT VAL FROM LISTVAL_TEXT(:V));
        SUSPEND;
        TAG_NAME = 'r:results_info:r:created_at';
        VAL = (SELECT VAL FROM DATE2ISO(:V$DT, 1));
        SUSPEND;
        TAG_NAME = 'r:results_info:r:is_deleted+boolean';
        VAL = 'false';
        SUSPEND;
      END
    END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_RBOOK_EXAMS (
    I$DT1 TIMESTAMP,
    I$DT2 TIMESTAMP = CURRENT_TIMESTAMP)
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$PERSON_ID BIGINT;
DECLARE VARIABLE V$REGID VARCHAR(100);
DECLARE VARIABLE V$GROUP_ID BIGINT;
DECLARE VARIABLE V$OGRN VARCHAR(100);
DECLARE VARIABLE V$STAGE_ID BIGINT;
DECLARE VARIABLE V$DT TIMESTAMP;
DECLARE VARIABLE V$DT1 TIMESTAMP;
DECLARE VARIABLE V$DT2 TIMESTAMP;
DECLARE VARIABLE V$DT3 TIMESTAMP;
DECLARE VARIABLE V$DT4 TIMESTAMP;
DECLARE VARIABLE V$DT5 TIMESTAMP;
DECLARE VARIABLE V$NAME_LAST VARCHAR(400);
DECLARE VARIABLE V$NAME_FIRST VARCHAR(400);
DECLARE VARIABLE V$NAME_MID VARCHAR(400);
DECLARE VARIABLE V$DATE DATE;
DECLARE VARIABLE P INTEGER;
DECLARE VARIABLE V$YEAR_DATE DATE;
DECLARE VARIABLE S VARCHAR(1000);
DECLARE VARIABLE R VARCHAR(1000);
DECLARE VARIABLE T VARCHAR(1000);
DECLARE VARIABLE V$ASSN_ID BIGINT;
DECLARE VARIABLE V$TS VARCHAR(100);
DECLARE VARIABLE V$T TIME;
DECLARE VARIABLE ST SMALLINT;
DECLARE VARIABLE CT BIGINT;
begin

  -- Только текущие студенты
  -- Корневой элемент формируется json массивом снаружи выборки

  SELECT FIRST 1 V9.VAL, CAST(LV.TAG AS DATE)
  FROM LINKS L2
  JOIN VALS V9 ON V9.OBJ_ID = L2.OBJ_ID AND V9.PARAM_ID = 9 AND V9.IS_DEL = 0
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$OGRN, :V$YEAR_DATE;

  FOR
    SELECT M.OBJ_ID, M.PERSON_ID, V2912.SVAL, M.GROUP_ID, M.STAGE_ID, M.DATE_ADD,
      V55.SVAL, V55.DATE_MODIFY, V56.SVAL, V56.DATE_MODIFY, V57.SVAL, V57.DATE_MODIFY, V89.VAL, V89.DATE_MODIFY
    FROM PERSON_MOVEMENTS M
    JOIN VALS V2912 ON V2912.OBJ_ID = M.PERSON_ID AND V2912.PARAM_ID = 2912 AND V2912.IS_DEL = 0
    JOIN VALS V55 ON V55.OBJ_ID = M.PERSON_ID AND V55.PARAM_ID = 55 AND V55.IS_DEL = 0
    JOIN VALS V56 ON V56.OBJ_ID = M.PERSON_ID AND V56.PARAM_ID = 56 AND V56.IS_DEL = 0
    LEFT JOIN VALS V57 ON V57.OBJ_ID = M.PERSON_ID AND V57.PARAM_ID = 57 AND V57.IS_DEL = 0
    JOIN VALD V89 ON V89.OBJ_ID = M.PERSON_ID AND V89.PARAM_ID = 89 AND V89.IS_DEL = 0
    WHERE M.DATE_DEL IS NULL AND M.GROUP_TYPE_ID = 9 AND M.DATE_OUT IS NULL AND M.LEVEL_ID = 29
    ORDER BY 4, 3
    INTO :V$OBJ_ID, :V$PERSON_ID, :V$REGID, :V$GROUP_ID, :V$STAGE_ID, :V$DT,
      :V$NAME_LAST, :V$DT1, :V$NAME_FIRST, :V$DT2, :V$NAME_MID, :V$DT3, :V$DATE, :V$DT4
  DO
  BEGIN
    V$DT5 = NULL;
    SELECT MAX(S.DATE_ADD)
    FROM ATT_REGISTER_STDS S
    JOIN ATT_REGISTER R ON R.DATE_DEL IS NULL AND R.OBJ_ID = S.ATT_ID AND R.STATE_ID <> 3
    WHERE S.DATE_DEL IS NULL AND S.PERSON_ID = :V$PERSON_ID AND R.ATT_DATE >= :V$YEAR_DATE
    INTO :V$DT5;

    IF(I$DT1 IS NULL OR V$DT >= I$DT1 OR V$DT1 >= I$DT1 OR V$DT2 >= I$DT1 OR V$DT3 >= I$DT1 OR V$DT4 >= I$DT1 OR V$DT5 >= I$DT1) THEN
    BEGIN
      TAG_NAME = 'r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'r:regID';
      VAL = REPLACE(REPLACE(LOWER(V$REGID), '{', ''), '}', '');
      P = POSITION(':' IN VAL);
      IF(P > 0) THEN VAL = SUBSTRING(VAL FROM 1 FOR P - 1);
      SUSPEND;
      TAG_NAME = 'r:last_name';
      VAL = V$NAME_LAST;
      SUSPEND;
      TAG_NAME = 'r:first_name';
      VAL = V$NAME_FIRST;
      SUSPEND;
      TAG_NAME = 'r:middle_name';
      VAL = V$NAME_MID;
      SUSPEND;
      TAG_NAME = 'r:birthdate';
      VAL = (SELECT VAL FROM DATE2ISO(:V$DATE, 0));
      SUSPEND;
      TAG_NAME = 'r:schedule_info::json&colon;array';
      VAL = 1;
      SUSPEND;
      FOR
        SELECT S.OBJ_ID, S.DATE_ADD, SC.SCAPTION, R.ATT_DATE, R.TIME_VAL, SR.CAPTION, I.STUFF_NAME, R.SUBSTAGE_ID, R.CONTROL_TYPE_ID
        FROM ATT_REGISTER_STDS S
        JOIN ATT_REGISTER R ON R.DATE_DEL IS NULL AND R.OBJ_ID = S.ATT_ID AND R.STATE_ID <> 3
        LEFT JOIN OBJECT_CAPTION_GET(R.SUBJECT_ID) SC ON 1 = 1
        LEFT JOIN OBJECT_CAPTION_GET(R.ROOM_ID) SR ON R.ROOM_ID IS NOT NULL
        LEFT JOIN ATT_INFO_GET(R.OBJ_ID, R.STATE_ID) I ON 1 = 1
        WHERE S.DATE_DEL IS NULL AND S.PERSON_ID = :V$PERSON_ID AND R.ATT_DATE >= :V$YEAR_DATE
        ORDER BY 4
        INTO :V$ASSN_ID, :V$DT, :S, :V$DATE, :V$TS, :R, :T, :ST, :CT
      DO
      BEGIN
        TAG_NAME = 'r:schedule_info:r';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'r:schedule_info:r:schedule_id';
        VAL = V$ASSN_ID;
        SUSPEND;
        TAG_NAME = 'r:schedule_info:r:institution_ogrn';
        VAL = V$OGRN;
        SUSPEND;
        TAG_NAME = 'r:schedule_info:r:datetime';
        BEGIN
          V$T = V$TS;
          WHEN ANY DO V$T = NULL;
        END
        -- времени может не быть !
        IF(V$T IS NULL) THEN VAL = (SELECT VAL FROM DATE2ISO(:V$DATE, 1)); ELSE VAL = (SELECT VAL FROM DATE2ISO(:V$DATE + :V$T, 1));
        SUSPEND;
        TAG_NAME = 'r:schedule_info:r:place';
        VAL = R;
        SUSPEND;
        TAG_NAME = 'r:schedule_info:r:subject';
        VAL = S;
        SUSPEND;
        TAG_NAME = 'r:schedule_info:r:control_type';
        VAL = (SELECT VAL FROM LISTVAL_TEXT(:CT));
        SUSPEND;
        TAG_NAME = 'r:schedule_info:r:education_period';
        IF(ST = 1) THEN VAL = '1 семестр'; ELSE VAL = '2 семестр';
        SUSPEND;
        TAG_NAME = 'r:schedule_info:r:examiner';
        VAL = T;
        SUSPEND;
        TAG_NAME = 'r:schedule_info:r:created_at';
        VAL = (SELECT VAL FROM DATE2ISO(:V$DT, 1));
        SUSPEND;
        TAG_NAME = 'r:schedule_info:r:is_deleted+boolean';
        VAL = 'false';
        SUSPEND;
      END
    END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_RBOOK_STUDENTS (
    I$DT1 TIMESTAMP,
    I$DT2 TIMESTAMP = CURRENT_TIMESTAMP)
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$PERSON_ID BIGINT;
DECLARE VARIABLE V$REGID VARCHAR(100);
DECLARE VARIABLE V$GROUP_ID BIGINT;
DECLARE VARIABLE V$DT TIMESTAMP;
DECLARE VARIABLE P INTEGER;
DECLARE VARIABLE V$NAME_LAST VARCHAR(400);
DECLARE VARIABLE V$NAME_FIRST VARCHAR(400);
DECLARE VARIABLE V$NAME_MID VARCHAR(400);
DECLARE VARIABLE V$DATE DATE;
DECLARE VARIABLE S VARCHAR(1000);
DECLARE VARIABLE V$DT1 TIMESTAMP;
DECLARE VARIABLE V$DT2 TIMESTAMP;
DECLARE VARIABLE V$DT3 TIMESTAMP;
DECLARE VARIABLE V$DT4 TIMESTAMP;
DECLARE VARIABLE V$OGRN VARCHAR(100);
DECLARE VARIABLE V$STAGE_ID BIGINT;
begin

  -- Только текущие студенты
  -- Корневой элемент формируется json массивом снаружи выборки

  SELECT FIRST 1 V9.VAL
  FROM LINKS L2
  JOIN VALS V9 ON V9.OBJ_ID = L2.OBJ_ID AND V9.PARAM_ID = 9 AND V9.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$OGRN;

  FOR
    SELECT M.OBJ_ID, M.PERSON_ID, V2912.SVAL, M.GROUP_ID, M.STAGE_ID, M.DATE_ADD,
      V55.SVAL, V55.DATE_MODIFY, V56.SVAL, V56.DATE_MODIFY, V57.SVAL, V57.DATE_MODIFY, V89.VAL, V89.DATE_MODIFY
    FROM PERSON_MOVEMENTS M
    JOIN VALS V2912 ON V2912.OBJ_ID = M.PERSON_ID AND V2912.PARAM_ID = 2912 AND V2912.IS_DEL = 0
    JOIN VALS V55 ON V55.OBJ_ID = M.PERSON_ID AND V55.PARAM_ID = 55 AND V55.IS_DEL = 0
    JOIN VALS V56 ON V56.OBJ_ID = M.PERSON_ID AND V56.PARAM_ID = 56 AND V56.IS_DEL = 0
    LEFT JOIN VALS V57 ON V57.OBJ_ID = M.PERSON_ID AND V57.PARAM_ID = 57 AND V57.IS_DEL = 0
    JOIN VALD V89 ON V89.OBJ_ID = M.PERSON_ID AND V89.PARAM_ID = 89 AND V89.IS_DEL = 0
    WHERE M.DATE_DEL IS NULL AND M.GROUP_TYPE_ID = 9 AND M.DATE_OUT IS NULL AND M.LEVEL_ID = 29
    ORDER BY 4, 3
    INTO :V$OBJ_ID, :V$PERSON_ID, :V$REGID, :V$GROUP_ID, :V$STAGE_ID, :V$DT,
      :V$NAME_LAST, :V$DT1, :V$NAME_FIRST, :V$DT2, :V$NAME_MID, :V$DT3, :V$DATE, :V$DT4
  DO
  BEGIN
    IF(I$DT1 IS NULL OR V$DT >= I$DT1 OR V$DT1 >= I$DT1 OR V$DT2 >= I$DT1 OR V$DT3 >= I$DT1 OR V$DT4 >= I$DT1) THEN
    BEGIN
      TAG_NAME = 'r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'r:regID';
      VAL = REPLACE(REPLACE(LOWER(V$REGID), '{', ''), '}', '');
      P = POSITION(':' IN VAL);
      IF(P > 0) THEN VAL = SUBSTRING(VAL FROM 1 FOR P - 1);
      SUSPEND;
      TAG_NAME = 'r:last_name';
      VAL = V$NAME_LAST;
      SUSPEND;
      TAG_NAME = 'r:first_name';
      VAL = V$NAME_FIRST;
      SUSPEND;
      TAG_NAME = 'r:middle_name';
      VAL = V$NAME_MID;
      SUSPEND;
      TAG_NAME = 'r:birthdate';
      VAL = (SELECT VAL FROM DATE2ISO(:V$DATE, 0));
      SUSPEND;
      TAG_NAME = 'r:educations_info::json&colon;array';
      VAL = 1;
      SUSPEND;
      TAG_NAME = 'r:educations_info:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'r:educations_info:r:education_id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'r:educations_info:r:institution_ogrn';
      VAL = V$OGRN;
      SUSPEND;
      TAG_NAME = 'r:educations_info:r:speciality_code';
      VAL = NULL;
      S = NULL;
      SELECT FIRST 1 C.VAL, V.SVAL
      FROM VALS V
      JOIN VALL V2 ON V2.OBJ_ID = V.OBJ_ID AND V2.PARAM_ID IN (2165, 2821, 3367) AND V2.IS_DEL = 0
      LEFT JOIN LISTVAL_TEXT(V2.LISTVAL_ID) C ON 1 = 1
      WHERE V.OBJ_ID = :V$GROUP_ID AND V.PARAM_ID = 2822 AND V.IS_DEL = 0
      INTO :S, :VAL;
      IF(VAL IS NULL) THEN
      SELECT FIRST 1 C.VAL, V.SVAL
      FROM VALR V3075
      JOIN VALS V ON V.OBJ_ID = V3075.VAL AND V3075.PARAM_ID = 3476 AND V3075.IS_DEL = 0
      JOIN VALL V2 ON V2.OBJ_ID = V3075.VAL AND V2.PARAM_ID IN (3474, 3475, 3476) AND V2.IS_DEL = 0
      LEFT JOIN LISTVAL_TEXT(V2.LISTVAL_ID) C ON 1 = 1
      WHERE V3075.OBJ_ID = :V$GROUP_ID AND V3075.PARAM_ID = 3075 AND V3075.IS_DEL = 0
      INTO :S, :VAL;
      SUSPEND;
      TAG_NAME = 'r:educations_info:r:speciality_name';
      VAL = S;
      SUSPEND;
      TAG_NAME = 'r:educations_info:r:group';
      VAL = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$GROUP_ID));
      SUSPEND;
      TAG_NAME = 'r:educations_info:r:academic_period';
      VAL = (SELECT VAL FROM LISTVAL_TEXT(:V$STAGE_ID));
      SUSPEND;
      TAG_NAME = 'r:educations_info:r:created_at';
      VAL = (SELECT VAL FROM DATE2ISO(:V$DT, 1));
      SUSPEND;
      -- Признак выпускного курса ?
      TAG_NAME = 'r:educations_info:r:is_released+boolean';
      VAL = 'false';
      SELECT FIRST 1 'true'
      FROM VALL V3344
      WHERE V3344.OBJ_ID = :V$GROUP_ID AND V3344.PARAM_ID = 3344 AND V3344.IS_DEL = 0 AND V3344.LISTVAL_ID = 2
      INTO :VAL;
      SUSPEND;
    END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_REPORT_VERSION (
    I$VERSION VARCHAR(100))
RETURNS (
    INST_NAME VARCHAR(1000),
    INST_VERSION VARCHAR(100))
AS
declare variable OBJ_ID bigint;
declare variable TMP bigint;
declare variable V varchar(1000);
declare variable V$LC varchar(10);
begin

  IF(I$VERSION IS NOT NULL) THEN
  BEGIN

    -- Обновляем версию DG в текущем срезе СМИР
    SELECT FIRST 1 I.INFO_ID, I.INFO_VAL
    FROM INFO I
    WHERE I.INFO_CODE = 'PORTAL_SERVICE_VERSION'
    INTO :OBJ_ID, :V;

    IF(OBJ_ID IS NULL) THEN
    BEGIN
      INSERT INTO INFO
      (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('PORTAL_SERVICE_VERSION', 'PORTAL_SERVICE_VERSION', :I$VERSION);
    END
    ELSE IF(COALESCE(V, '') <> COALESCE(I$VERSION, '')) THEN
    BEGIN
      UPDATE INFO
      SET INFO_VAL = :I$VERSION
      WHERE INFO_ID = :OBJ_ID;
    END

    V$LC = (SELECT STATUS FROM OU_LICENCE_TYPE);

    SELECT FIRST 1 V.VAL
    FROM LINKS L
    JOIN VALS V ON V.OBJ_ID = L.OBJ_ID AND V.IS_DEL = 0 AND V.PARAM_ID IN (764, 666, 672, 2, 999)
    WHERE L.PARENT_ID IS NULL AND L.OBJ_TYPE_ID IN (2, 111, 112, 124) AND L.DATE_DEL IS NULL
    ORDER BY IIF(:V$LC = 'C' AND V.PARAM_ID = 999, 0, V.PARAM_ID)
    INTO :INST_NAME;

    SELECT FIRST 1 V.VER_MAJOR || '.' || V.VER_MINOR || '.' || V.VER_RELEASE || '.' || V.VER_BUILD
    FROM VER V
    INTO :INST_VERSION;

    SUSPEND;

  END
  ELSE
  BEGIN

    -- Обновляем метку времени последней выгрузки оценок
    OBJ_ID = NULL;

    SELECT FIRST 1 L162.OBJ_ID
    FROM LINKS L2
    JOIN LINKS L162 ON L162.PARENT_ID = L2.OBJ_ID AND L162.OBJ_TYPE_ID = 162 AND L162.DATE_DEL IS NULL
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :OBJ_ID;

    IF(OBJ_ID IS NOT NULL) THEN
    BEGIN
      SELECT BLOB_ID FROM VAL_ADD(1506, :OBJ_ID, CURRENT_TIMESTAMP) INTO :TMP;
    END

  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_SCUD_UPDATE (
    SUID VARCHAR(100),
    DIRECTION VARCHAR(100),
    EVENT_DATE VARCHAR(100))
AS
declare variable V$PERSON_ID bigint;
begin

  IF(CHAR_LENGTH(SUID) < 15) THEN
  BEGIN
      -- Идентификация по SUID
      V$PERSON_ID = CAST(SUID AS BIGINT);
  END
  ELSE
  BEGIN
      -- Идентификация по RegID - всегда в верхнем регистре, и с фигурными скобками
      SUID = UPPER(SUID);
      IF(SUBSTRING(SUID FROM 1 FOR 1) <> '{') THEN SUID = '{' || SUID || '}';

      SELECT FIRST 1 V.OBJ_ID
      FROM VALS V
      JOIN LINKS LP ON LP.OBJ_ID = V.OBJ_ID AND LP.PARENT_TYPE_ID IN (2, 211, 9, 125, 187, 10) AND LP.DATE_DEL IS NULL
      WHERE V.PARAM_ID IN (2912, 2915, 2917) AND V.IS_DEL = 0 AND V.VAL = :SUID
      INTO :V$PERSON_ID;

      IF(V$PERSON_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Персона с указанным RegID не найдена';
  END

  -- Перекодируем direction
  IF(DIRECTION = 'input' OR DIRECTION = '0' OR DIRECTION = '6') THEN DIRECTION = 'input';
  ELSE IF(DIRECTION = 'output' OR DIRECTION = '1' OR DIRECTION = '7') THEN DIRECTION = 'output';
  ELSE EXCEPTION DATA_ERROR 'Недопустимый код направления движения';

  -- Сохраняем сырые данные
  UPDATE OR INSERT INTO SCUD_RAW (PERSON_ID, EVENT_DATE, EVENT_VAL)
  VALUES (:V$PERSON_ID, CAST(:EVENT_DATE AS TIMESTAMP), CASE WHEN (:DIRECTION = 'input') THEN 1 ELSE 0 END)
  MATCHING (PERSON_ID, EVENT_DATE);

  -- Для классного журнала
  if (DIRECTION = 'input') then
  begin /* Ученик пришел в ОО */
    UPDATE OR INSERT INTO SCUD_PUPILS (PUPIL_ID, UPDATED)
    VALUES (:V$PERSON_ID, CURRENT_TIMESTAMP)
    MATCHING (PUPIL_ID);
  end
  else
  begin /* Ученик покинул ОО */
    DELETE FROM SCUD_PUPILS
    WHERE (PUPIL_ID = :V$PERSON_ID) or (UPDATED < DATEADD(-7 DAY TO CURRENT_DATE));
  end

  -- При key vilation подменяем сообщение
  WHEN SQLCODE -530 DO
  BEGIN
    EXCEPTION DATA_ERROR 'Персона не найдена в базе';
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_SFERUM_CALLS RETURNS (
    CHAT_ID VARCHAR(40),
    CJ_ID BIGINT,
    LESSON_ID BIGINT,
    USER_ID VARCHAR(40),
    LESSON_NAME VARCHAR(1000),
    TIME_FROM TIMESTAMP,
    TIME_TO TIMESTAMP)
AS
declare variable V$LDATE date;
declare variable V$LNUM integer;
declare variable V$DL date;
declare variable V$T time;
declare variable V$TN integer;
declare variable S varchar(400);
declare variable V$LTHEME varchar(1000);
declare variable CALL_ID varchar(400);
declare variable CURRENT_NUM integer;
begin

  V$DL = DATEADD(1 DAY TO CURRENT_DATE);
  V$T = DATEADD(- 20 MINUTE TO CURRENT_TIME);

  -- Количество минут с начала суток, но точно не раньше 01:00 чтобы не пересечься с номерами уроков
  V$TN = EXTRACT(MINUTE FROM V$T) + 60 * EXTRACT(HOUR FROM V$T);
  IF(V$TN < 60) THEN V$TN = NULL;

  FOR
    SELECT DISTINCT J.OBJ_ID, J.CHAT_ID, V3355.SVAL
    FROM CJ2_JOURNAL J
    JOIN CJ2_JOURNAL_LESSONS L ON L.DATE_DEL IS NULL AND L.CJ_ID = J.OBJ_ID AND L.LESSON_DATE >= CURRENT_DATE AND L.LESSON_DATE <= :V$DL AND (L.IS_PUBLISHED = 1 OR L.IS_COMPLETED = 1) AND L.IS_ONLINE = 1
    JOIN VALS V3355 ON V3355.OBJ_ID = L.TEACHER_ID AND V3355.PARAM_ID = 3355 AND V3355.IS_DEL = 0
    WHERE J.DATE_DEL IS NULL AND J.VK_ENABLED = 1 AND J.CHAT_ID IS NOT NULL
    INTO :CJ_ID, :S, :USER_ID
  DO
  BEGIN
    S = SUBSTRING(S FROM 1 FOR POSITION(',' IN S) - 1);
    CHAT_ID = S;

    CURRENT_NUM = NULL;
    SELECT FIRST 1 V404.VAL
    FROM SCHEDULE_ITEMS SI
    JOIN VALD V3120 ON V3120.OBJ_ID = SI.SCHEDULE_ID AND V3120.PARAM_ID = 3120 AND V3120.IS_DEL = 0 AND V3120.VAL <= CURRENT_DATE
    JOIN VALD V3121 ON V3121.OBJ_ID = SI.SCHEDULE_ID AND V3121.PARAM_ID = 3121 AND V3121.IS_DEL = 0 AND V3121.VAL >= CURRENT_DATE
    JOIN VALL V1341 ON V1341.OBJ_ID = SI.SCHEDULE_ID AND V1341.PARAM_ID = 1341 AND V1341.IS_DEL = 0 AND V1341.LISTVAL_ID = 2
    JOIN LINKS L60 ON L60.PARENT_ID = SI.SCHEDULE_ID AND L60.OBJ_TYPE_ID = 60 AND L60.DATE_DEL IS NULL
    JOIN VALT V405 ON V405.OBJ_ID = L60.OBJ_ID AND V405.PARAM_ID = 405 AND V405.IS_DEL = 0 AND V405.VAL >= :V$T
    JOIN VALI V404 ON V404.OBJ_ID = L60.OBJ_ID AND V404.PARAM_ID = 404 AND V404.IS_DEL = 0
    WHERE SI.DATE_DEL IS NULL AND SI.CJ_ID = :CJ_ID
    ORDER BY V405.VAL
    INTO :CURRENT_NUM;

    -- Смотрим ближайший номер онлайн-урока по шаблону расписания
    LESSON_ID = NULL;
    SELECT FIRST 1 L.OBJ_ID, L.INST_ID, L.LESSON_DATE, L.LESSON_NUM, L.LESSON_THEME
    FROM CJ2_JOURNAL_LESSONS L
    WHERE L.DATE_DEL IS NULL AND L.CJ_ID = :CJ_ID AND L.LESSON_DATE >= CURRENT_DATE AND L.LESSON_DATE <= :V$DL AND (L.IS_PUBLISHED = 1 OR L.IS_COMPLETED = 1) AND L.IS_ONLINE = 1
      AND ((L.LESSON_NUM > :CURRENT_NUM AND L.LESSON_NUM < 60) OR L.LESSON_NUM > :V$TN OR :CURRENT_NUM IS NULL OR L.LESSON_DATE > CURRENT_DATE)
    ORDER BY L.LESSON_DATE, L.LESSON_NUM
    INTO :LESSON_ID, :CALL_ID, :V$LDATE, :V$LNUM, :V$LTHEME;

    LESSON_NAME = 'Урок ' || (SELECT RESULT FROM DATE2STR(:V$LDATE)) || ' - ' || V$LTHEME;

    IF(LESSON_ID IS NOT NULL AND CALL_ID IS NULL) THEN SUSPEND;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_SFERUM_CLASSCHATS (
    I$OBJ_ID BIGINT,
    I$TIMEMARK TIMESTAMP = CURRENT_TIMESTAMP)
RETURNS (
    CLASS_ID BIGINT,
    CLASS_CAPTION VARCHAR(400),
    CLASS_INDEX INTEGER,
    CLASS_DIGIT VARCHAR(100),
    CLASS_CODE VARCHAR(100),
    PARENTS_CHAT_ID VARCHAR(100),
    CHILD_CHAT_ID VARCHAR(100),
    CHANGE_MASK INTEGER,
    OBJ_ID BIGINT,
    OBJ_TYPE_ID BIGINT,
    ADD_ID VARCHAR(100),
    DEL_ID VARCHAR(100),
    FORCE_WM SMALLINT,
    DEL_REASON VARCHAR(20),
    OU_TITLE VARCHAR(1000))
AS
DECLARE VARIABLE V$DATE_OUT DATE;
DECLARE VARIABLE V$DEL_DATE TIMESTAMP;
DECLARE VARIABLE V$TEACHER_ID BIGINT;
DECLARE VARIABLE V$BASE_TEACHER BIGINT;
DECLARE VARIABLE V$F1 VARCHAR(100);
DECLARE VARIABLE V$F2 VARCHAR(100);
DECLARE VARIABLE V$TM_STUDENTS TIMESTAMP;
DECLARE VARIABLE V$TM_PARENTS TIMESTAMP;
DECLARE VARIABLE V$CHANGE_TM TIMESTAMP;
DECLARE VARIABLE V$ZTM TIMESTAMP;
DECLARE VARIABLE V$Y INTEGER;
DECLARE VARIABLE V$YEAR_TM TIMESTAMP;
DECLARE VARIABLE V$ALT_TM TIMESTAMP;
begin

  V$DATE_OUT = DATEADD(-1 YEAR TO CURRENT_DATE);

  IF(I$OBJ_ID IS NULL) THEN
  SELECT FIRST 1 L2.OBJ_ID
  FROM LINKS L2
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :I$OBJ_ID;

  -- Нулевая метка времени
  V$ZTM = '2024-01-01';

  -- Главную метку сдвигаем на 1 день назад, потому что иначе обновления меток будут идти постоянно
  -- по сути нам важно NULL или не-NULL
  I$TIMEMARK = DATEADD(1 DAY TO I$TIMEMARK);

  SELECT FIRST 1 LV.COST, V1236.DATE_MODIFY
  FROM VALL V1236
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE V1236.OBJ_ID = :I$OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  INTO :V$Y, :V$YEAR_TM;

  SELECT FIRST 1 V2.VAL
  FROM VALS V2
  WHERE V2.OBJ_ID = :I$OBJ_ID AND V2.PARAM_ID = 2 AND V2.IS_DEL = 0
  INTO :OU_TITLE;

  -- Для СПО берем наименование из другого параметра
  IF(SUBSTRING(OU_TITLE FROM 1 FOR 2) = '19') THEN
  SELECT FIRST 1 V999.VAL
  FROM VALS V999
  WHERE V999.OBJ_ID = :I$OBJ_ID AND V999.PARAM_ID = 999 AND V999.IS_DEL = 0
  INTO :OU_TITLE;

  IF(OU_TITLE IS NULL) THEN EXCEPTION DATA_ERROR 'Не внесено наименование ОУ';

  -- Первой строкой отдаем ID чатов и класса
  -- далее отдаем списки участников
  -- в поле XVAL параметра id чата храним флаг форсирования для обновления приглашений участников чата
  FOR
    SELECT L9.OBJ_ID, C.CAPTION, LV.COST, V54.SVAL, V3359.SVAL, V3336.SVAL, V3359.XVAL, V3336.XVAL, V3471.VAL, V3472.VAL,
      MAXVALUE(COALESCE(L9.DATE_MODIFY, :V$ZTM), COALESCE(V54.DATE_MODIFY, :V$ZTM), COALESCE(V49.DATE_MODIFY, :V$ZTM))
    FROM LINKS L7
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V49.LISTVAL_ID
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
    LEFT JOIN VALS V54 ON V54.OBJ_ID = L9.OBJ_ID AND V54.PARAM_ID = 54 AND V54.IS_DEL = 0
    LEFT JOIN VALS V3359 ON V3359.OBJ_ID = L9.OBJ_ID AND V3359.PARAM_ID = 3359 AND V3359.IS_DEL = 0
    LEFT JOIN VALS V3336 ON V3336.OBJ_ID = L9.OBJ_ID AND V3336.PARAM_ID = 3336 AND V3336.IS_DEL = 0
    LEFT JOIN VALDT V3471 ON V3471.OBJ_ID = L9.OBJ_ID AND V3471.PARAM_ID = 3471 AND V3471.IS_DEL = 0
    LEFT JOIN VALDT V3472 ON V3472.OBJ_ID = L9.OBJ_ID AND V3472.PARAM_ID = 3472 AND V3472.IS_DEL = 0
    LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C ON 1 = 1
    WHERE L7.PARENT_ID = :I$OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    INTO :CLASS_ID, :CLASS_CAPTION, :CLASS_INDEX, :CLASS_DIGIT, :PARENTS_CHAT_ID, :CHILD_CHAT_ID, :V$F1, :V$F2, :V$TM_STUDENTS, :V$TM_PARENTS,
      :V$ALT_TM
  DO
  BEGIN
    -- Исправляем косяк с ограничениями на digit
    CLASS_CAPTION = CLASS_INDEX;
    IF(CLASS_DIGIT IS NOT NULL AND CLASS_DIGIT <> '') THEN CLASS_CAPTION = CLASS_CAPTION || ' ' || CLASS_DIGIT;
    CLASS_DIGIT = NULL;

    IF(I$TIMEMARK IS NULL) THEN V$TM_STUDENTS = NULL;
    IF(I$TIMEMARK < V$TM_STUDENTS) THEN V$TM_STUDENTS = I$TIMEMARK;
    IF(I$TIMEMARK IS NULL) THEN V$TM_PARENTS = NULL;
    IF(I$TIMEMARK < V$TM_PARENTS) THEN V$TM_PARENTS = I$TIMEMARK;

    OBJ_ID = NULL;
    ADD_ID = NULL;
    DEL_ID = NULL;
    FORCE_WM = 0;
    IF(V$F1 = '1') THEN FORCE_WM = FORCE_WM + 1; -- флаг обновления родительского чата
    IF(V$F2 = '1') THEN FORCE_WM = FORCE_WM + 2; -- флаг обновления ученического чата
    CLASS_CODE = CLASS_ID || 'Y' || V$Y;
    CHANGE_MASK = 0;
    -- Маска изменения чата, тут смотрим только бит 0 - изменение учебного года
    -- бит 1 = изменение атрибутов чата
    IF(V$ALT_TM IS NULL OR V$ALT_TM > V$TM_STUDENTS OR V$ALT_TM > V$TM_PARENTS OR V$F1 = '1') THEN CHANGE_MASK = BIN_OR(CHANGE_MASK, 1);
    IF(V$TM_STUDENTS IS NULL OR V$TM_STUDENTS < DATEADD(1 MINUTE TO V$YEAR_TM) OR V$F2 = '1') THEN CHANGE_MASK = BIN_OR(CHANGE_MASK, 2);
    IF(V$TM_PARENTS IS NULL OR V$TM_PARENTS < DATEADD(1 MINUTE TO V$YEAR_TM)) THEN CHANGE_MASK = BIN_OR(CHANGE_MASK, 2);
    SUSPEND;

    -- Удаление юзеров
    ADD_ID = NULL;
    FOR
      SELECT OBJ_ID, OBJ_TYPE_ID, ID, DEL_REASON, MAX(TMV) FROM (
        -- Запоротые id учеников
        SELECT L10.OBJ_ID, L10.OBJ_TYPE_ID, E.ID, 'mistake' DEL_REASON, MAXVALUE(COALESCE(L10.DATE_MODIFY, :V$ZTM), COALESCE(V3363.DATE_MODIFY, :V$ZTM)) TMV
        FROM LINKS L10
        JOIN VALS V3363 ON V3363.OBJ_ID = L10.OBJ_ID AND V3363.PARAM_ID = 3363 AND V3363.IS_DEL = 0
        LEFT JOIN EXPLODE_STR(V3363.VAL, ',') E ON 1 = 1
        WHERE L10.PARENT_ID = :CLASS_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        -- Запоротые id родителей
        UNION
        SELECT L20.OBJ_ID, L20.OBJ_TYPE_ID, E.ID, 'mistake', MAXVALUE(COALESCE(L10.DATE_MODIFY, :V$ZTM), COALESCE(L20.DATE_MODIFY, :V$ZTM), COALESCE(V3365.DATE_MODIFY, :V$ZTM)) TMV
        FROM LINKS L10
        JOIN LINKS L20 ON L20.PARENT_ID = L10.OBJ_ID AND L20.OBJ_TYPE_ID = 20 AND L20.DATE_DEL IS NULL
        JOIN VALS V3365 ON V3365.OBJ_ID = L20.OBJ_ID AND V3365.PARAM_ID = 3365 AND V3365.IS_DEL = 0
        LEFT JOIN EXPLODE_STR(V3365.VAL, ',') E ON 1 = 1
        WHERE L10.PARENT_ID = :CLASS_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        -- Удаленные родители
        -- !!!
        -- Выбывшие ученики
        UNION
        SELECT DISTINCT M.PERSON_ID, 10, V3354.SVAL, 'change_class', MAXVALUE(COALESCE(M.DATE_MODIFY, :V$ZTM), COALESCE(V3354.DATE_MODIFY, :V$ZTM)) TMV
        FROM PERSON_MOVEMENTS M
        LEFT JOIN PERSON_MOVEMENTS M2 ON M2.DATE_DEL IS NULL AND M2.GROUP_ID = M.GROUP_ID AND M2.PERSON_ID = M.PERSON_ID AND M2.DATE_OUT IS NULL
        JOIN VALS V3354 ON V3354.OBJ_ID = M.PERSON_ID AND V3354.PARAM_ID = 3354 AND V3354.IS_DEL = 0
        WHERE M.DATE_DEL IS NULL AND M.GROUP_ID = :CLASS_ID AND M.DATE_OUT >= :V$DATE_OUT AND M2.OBJ_ID IS NULL
        -- Родители выбывших учеников
        -- !!! отдельно надо учесть случай родителей-сотрудников выбывших учеников
        UNION
        SELECT DISTINCT L20.OBJ_ID, L20.OBJ_TYPE_ID, V3356.SVAL, 'other', MAXVALUE(COALESCE(M.DATE_MODIFY, :V$ZTM), COALESCE(V3356.DATE_MODIFY, :V$ZTM)) TMV
        FROM PERSON_MOVEMENTS M
        LEFT JOIN PERSON_MOVEMENTS M2 ON M2.DATE_DEL IS NULL AND M2.GROUP_ID = M.GROUP_ID AND M2.PERSON_ID = M.PERSON_ID AND M2.DATE_OUT IS NULL
        JOIN LINKS L20 ON L20.PARENT_ID = M.PERSON_ID AND L20.OBJ_TYPE_ID = 20 AND L20.DATE_DEL IS NULL
        JOIN VALS V3356 ON V3356.OBJ_ID = L20.OBJ_ID AND V3356.PARAM_ID = 3356 AND V3356.IS_DEL = 0
        WHERE M.DATE_DEL IS NULL AND M.GROUP_ID = :CLASS_ID AND M.DATE_OUT >= :V$DATE_OUT AND M2.OBJ_ID IS NULL
        -- Уволенный классрук
        -- этого кейса быть не может !!! при увольнении классрука нагрузка уже будет снята
        UNION
        SELECT L14.OBJ_ID, L14.OBJ_TYPE_ID, V3355.SVAL, 'fired', :V$ZTM
        FROM VALR V53
        JOIN LINKS L14 ON L14.OBJ_ID = V53.VAL AND L14.PARENT_TYPE_ID = 84 AND L14.DATE_DEL IS NULL
        JOIN VALS V3355 ON V3355.OBJ_ID = L14.OBJ_ID AND V3355.PARAM_ID = 3355 AND V3355.IS_DEL = 0
        WHERE V53.OBJ_ID = :CLASS_ID AND V53.PARAM_ID = 53 AND V53.IS_DEL = 0
      )
      GROUP BY 1, 2, 3, 4
      INTO :OBJ_ID, :OBJ_TYPE_ID, :DEL_ID, :DEL_REASON, :V$CHANGE_TM
    DO
    BEGIN
      DEL_REASON = TRIM(DEL_REASON);
      IF(
        (OBJ_TYPE_ID = 10 AND (V$TM_STUDENTS IS NULL OR V$CHANGE_TM > V$TM_STUDENTS OR V$F2 = '1')) OR
        (OBJ_TYPE_ID = 20 AND (V$TM_PARENTS IS NULL OR V$CHANGE_TM > V$TM_PARENTS OR V$F1 = '1')) OR
        (OBJ_TYPE_ID = 14 AND (V$TM_STUDENTS IS NULL OR V$CHANGE_TM > V$TM_STUDENTS OR V$TM_PARENTS IS NULL OR V$CHANGE_TM > V$TM_PARENTS OR V$F1 = '1'))
      )
      THEN
      SUSPEND;
    END

    -- Действующие ученики и родители
    DEL_ID = NULL;
    DEL_REASON = NULL;
    V$TEACHER_ID = NULL;
    FOR
      -- Ученики
      SELECT L10.OBJ_ID, L10.OBJ_TYPE_ID, V3354.SVAL, MAXVALUE(COALESCE(L10.DATE_MODIFY, :V$ZTM), COALESCE(V3354.DATE_MODIFY, :V$ZTM))
      FROM LINKS L10
      JOIN VALS V3354 ON V3354.OBJ_ID = L10.OBJ_ID AND V3354.PARAM_ID = 3354 AND V3354.IS_DEL = 0
      WHERE L10.PARENT_ID = :CLASS_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      -- Родители - выдаем вообще всех, чтобы не потерять тех кто является учителем
      UNION
      SELECT L20.OBJ_ID, L20.OBJ_TYPE_ID, V3356.SVAL, MAXVALUE(COALESCE(L10.DATE_MODIFY, :V$ZTM), COALESCE(L20.DATE_MODIFY, :V$ZTM), COALESCE(V3356.DATE_MODIFY, :V$ZTM))
      FROM LINKS L10
      JOIN LINKS L20 ON L20.PARENT_ID = L10.OBJ_ID AND L20.OBJ_TYPE_ID = 20 AND L20.DATE_DEL IS NULL
      LEFT JOIN VALS V3356 ON V3356.OBJ_ID = L20.OBJ_ID AND V3356.PARAM_ID = 3356 AND V3356.IS_DEL = 0
      WHERE L10.PARENT_ID = :CLASS_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      -- Классный руководитель
      UNION
      SELECT L14.OBJ_ID, L14.OBJ_TYPE_ID, V3355.SVAL, MAXVALUE(COALESCE(V53.DATE_MODIFY, :V$ZTM), COALESCE(L14.DATE_MODIFY, :V$ZTM), COALESCE(V3355.DATE_MODIFY, :V$ZTM))
      FROM VALR V53
      JOIN LINKS L14 ON L14.OBJ_ID = V53.VAL AND L14.PARENT_TYPE_ID = 2 AND L14.DATE_DEL IS NULL
      JOIN VALS V3355 ON V3355.OBJ_ID = L14.OBJ_ID AND V3355.PARAM_ID = 3355 AND V3355.IS_DEL = 0
      WHERE V53.OBJ_ID = :CLASS_ID AND V53.PARAM_ID = 53 AND V53.IS_DEL = 0
      -- Специально сортируем так, что учитель будет идти перед родителями
      ORDER BY 2
      INTO :OBJ_ID, :OBJ_TYPE_ID, :ADD_ID, :V$CHANGE_TM
    DO
    BEGIN
      IF(OBJ_TYPE_ID = 14) THEN V$TEACHER_ID = OBJ_ID;
      -- Если родитель является сотрудником - добавляем с id сотрудника
      IF(OBJ_TYPE_ID = 20 AND ADD_ID IS NULL) THEN
      BEGIN
        V$BASE_TEACHER = NULL;
        SELECT FIRST 1 L14.OBJ_ID, V3355.SVAL
        FROM VALS V155
        JOIN VALS V128 ON V128.OBJ_ID = V155.OBJ_ID AND V128.PARAM_ID = 128 AND V128.IS_DEL = 0
        JOIN VALS V129 ON V129.OBJ_ID = V155.OBJ_ID AND V129.PARAM_ID = 129 AND V129.IS_DEL = 0
        -- учитель с тем же id и ФИО
        JOIN VALS V267 ON V267.PARAM_ID = 267 AND V267.SVAL = V155.SVAL AND V267.IS_DEL = 0
        JOIN VALS V59 ON V59.OBJ_ID = V267.OBJ_ID AND V59.PARAM_ID = 59 AND V59.IS_DEL = 0 AND V59.SVAL = V128.SVAL
        JOIN VALS V60 ON V60.OBJ_ID = V267.OBJ_ID AND V60.PARAM_ID = 60 AND V60.IS_DEL = 0 AND V60.SVAL = V129.SVAL
        JOIN LINKS L14 ON L14.OBJ_ID = V267.OBJ_ID AND L14.PARENT_TYPE_ID = 2 AND L14.DATE_DEL IS NULL
        --
        JOIN VALS V3355 ON V3355.OBJ_ID = L14.OBJ_ID AND V3355.PARAM_ID = 3355 AND V3355.IS_DEL = 0
        WHERE V155.OBJ_ID = :OBJ_ID AND V155.PARAM_ID = 155 AND V155.IS_DEL = 0
        INTO :V$BASE_TEACHER, :ADD_ID;
        IF(V$BASE_TEACHER IS NOT NULL) THEN
        BEGIN
          IF(V$BASE_TEACHER <> V$TEACHER_ID OR V$TEACHER_ID IS NULL) THEN
          BEGIN
            -- OBJ_TYPE_ID все равно отдаем как 20
            OBJ_ID = V$BASE_TEACHER;
          END
          ELSE
            -- Повторно того же учителя не выдаем
            ADD_ID = NULL;
        END
      END
      IF(ADD_ID IS NOT NULL AND (
        (OBJ_TYPE_ID = 10 AND (V$TM_STUDENTS IS NULL OR V$CHANGE_TM > V$TM_STUDENTS OR V$F2 = '1')) OR
        (OBJ_TYPE_ID = 20 AND (V$TM_PARENTS IS NULL OR V$CHANGE_TM > V$TM_PARENTS OR V$F1 = '1')) OR
        (OBJ_TYPE_ID = 14 AND (V$TM_STUDENTS IS NULL OR V$CHANGE_TM > V$TM_STUDENTS OR V$TM_PARENTS IS NULL OR V$CHANGE_TM > V$TM_PARENTS OR V$F1 = '1'))
      ))
      THEN
      SUSPEND;
    END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_SFERUM_CLEANUP (
    I$TIMEMARK TIMESTAMP)
AS
begin

  -- Даем запас в 1 час, чтобы не грохнуть лишнее
  I$TIMEMARK = DATEADD(-1 HOUR TO I$TIMEMARK);

  -- Очищаем обработанные старые vk_id
  UPDATE VALS
  SET IS_DEL = 1
  WHERE IS_DEL = 0 AND DATE_MODIFY < :I$TIMEMARK AND PARAM_ID IN (3363, 3364, 3365);

  -- Очищаем флаги обновления чатов
  UPDATE VALS
  SET XVAL = NULL
  WHERE IS_DEL = 0 AND DATE_MODIFY < :I$TIMEMARK AND PARAM_ID IN (3357, 3336, 3359) AND XVAL = '1';

  -- CJ2_JOURNAL

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_SFERUM_DELETE RETURNS (
    OBJ_ID BIGINT,
    TYPE_ID VARCHAR(40),
    CHAT_ID VARCHAR(400))
AS
declare variable S1 varchar(400);
declare variable S2 varchar(400);
begin

  -- Чаты удаленных журналов текущего учебного года
  TYPE_ID = 'CJ2_JOURNAL';
  FOR
    SELECT J.OBJ_ID, J.CHAT_ID
    FROM CJ2_JOURNAL J
    LEFT JOIN CJ2_JOURNAL J2 ON J2.DATE_DEL IS NOT NULL AND J2.CHAT_ID = J.CHAT_ID
    WHERE J.DATE_DEL IS NOT NULL AND J.CHAT_ID IS NOT NULL AND J2.OBJ_ID IS NULL
    ORDER BY 1
    INTO :OBJ_ID, :CHAT_ID
  DO
  BEGIN
    SUSPEND;
  END

  -- Чаты удаленных журналов прошлого учебного года
  -- USER_ID используем для зачистки уже обработанных записей
  TYPE_ID = 'CJ2_JOURNAL_HST';
  FOR
    SELECT V.HST_ID, V.VAL
    FROM HISTVALS V
    WHERE V.TABLE_NAME = 'CJ2_JOURNAL' AND V.PARAM_ID = -25 AND V.USER_ID IS NULL
    ORDER BY 1
    INTO :OBJ_ID, :CHAT_ID
  DO
  BEGIN
    SUSPEND;
  END

  -- Чаты удаленных, окончивших или распущенных учебных коллективов
  -- Надо удалить по два чата в каждом
  TYPE_ID = 'GRADE';
  FOR
    SELECT L9.OBJ_ID, V3336.SVAL, V3359.SVAL
    FROM LINKS L9
    LEFT JOIN VALS V3336 ON V3336.OBJ_ID = L9.OBJ_ID AND V3336.PARAM_ID = 3336 AND V3336.IS_DEL = 0
    LEFT JOIN VALS V3359 ON V3359.OBJ_ID = L9.OBJ_ID AND V3359.PARAM_ID = 3359 AND V3359.IS_DEL = 0
    LEFT JOIN LINKS LP8 ON LP8.OBJ_ID = L9.OBJ_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
    WHERE L9.OBJ_TYPE_ID = 9 AND L9.PARENT_TYPE_ID = 8 AND L9.DATE_DEL IS NOT NULL AND LP8.LINK_ID IS NULL
      AND (V3336.SVAL IS NOT NULL OR V3359.SVAL IS NOT NULL)
    INTO :OBJ_ID, :S1, :S2
  DO
  BEGIN
    CHAT_ID = S1;
    IF(CHAT_ID IS NOT NULL) THEN SUSPEND;
    CHAT_ID = S2;
    IF(CHAT_ID IS NOT NULL) THEN SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_SFERUM_LINKS (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
declare variable V$OBJ_ID bigint;
declare variable S varchar(1000);
declare variable S1 varchar(1000);
declare variable S2 varchar(1000);
begin

  TAG_NAME = 'grades::json&colon;array';
  VAL = '1';
  SUSPEND;

  TAG_NAME = 'grades:r';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'grades:r:id';
  VAL = '0';
  SUSPEND;
  TAG_NAME = 'grades:r:name';
  VAL = 'Учительская';
  SUSPEND;
  TAG_NAME = 'grades:r:p_chat';
  VAL = NULL;
  SELECT FIRST 1 V.VAL
  FROM VALS V
  WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 3357 AND V.IS_DEL = 0
  INTO :VAL;
  SUSPEND;
  TAG_NAME = 'grades:r:c_chat';
  VAL = NULL;
  SUSPEND;

  FOR
    SELECT L9.OBJ_ID, C.CAPTION, V3336.VAL, V3359.VAL
    FROM LINKS L7
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
    LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C ON 1 = 1
    LEFT JOIN VALS V3336 ON V3336.OBJ_ID = L9.OBJ_ID AND V3336.PARAM_ID = 3336 AND V3336.IS_DEL = 0
    LEFT JOIN VALS V3359 ON V3359.OBJ_ID = L9.OBJ_ID AND V3359.PARAM_ID = 3359 AND V3359.IS_DEL = 0
    WHERE L7.PARENT_ID = :I$OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    ORDER BY C.SORT_ORDER, C.CAPTION
    INTO :V$OBJ_ID, :S, :S2, :S1
  DO
  BEGIN
    TAG_NAME = 'grades:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'grades:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'grades:r:name';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'grades:r:p_chat';
    VAL = S1;
    SUSPEND;
    TAG_NAME = 'grades:r:c_chat';
    VAL = S2;
    SUSPEND;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_SFERUM_RESET_DONE
AS
DECLARE VARIABLE V$ID BIGINT;
DECLARE VARIABLE S VARCHAR(4000);
DECLARE VARIABLE P INTEGER;
DECLARE VARIABLE P2 INTEGER;
DECLARE VARIABLE C VARCHAR(10);
DECLARE VARIABLE CR VARCHAR(10);
begin

  -- Выставляем флаги принудительного обновления всех чатов
  UPDATE VALS
  SET XVAL = '1'
  WHERE PARAM_ID IN (3357, 3336, 3359) AND IS_DEL = 0;

  -- Сбрасываем метки во всех предметных чатах
  UPDATE CJ2_JOURNAL
  SET CHAT_TIMEMARK = NULL
  WHERE VK_ENABLED = 1 AND CHAT_ID IS NOT NULL;

  -- Зачищаем текст в задаче Сферум, убираем слово reset
  SELECT FIRST 1 T.ID, T.TASKPARAMS
  FROM DC_TASKS T
  WHERE T.TASK_REF = 'paragraf.dnevnik2018:sferum'
  INTO :V$ID, :S;

  CR = ASCII_CHAR(10);

  P = POSITION('reset' IN LOWER(S));
  IF(P > 0) THEN
  BEGIN
    P2 = P;
    WHILE(P2 <= CHAR_LENGTH(S)) DO
    BEGIN
      C = SUBSTRING(S FROM P2 FOR 1);
      IF(C = CR) THEN
      BEGIN
        P2 = P2 + 1;
        BREAK;
      END
      P2 = P2 + 1;
    END

    S = SUBSTRING(S FROM 1 FOR P - 1) || SUBSTRING(S FROM P2);

    UPDATE DC_TASKS
    SET TASKPARAMS = :S
    WHERE ID = :V$ID;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_SFERUM_RESET_USERS RETURNS (
    CHAT_ID VARCHAR(400),
    USER_ID VARCHAR(100))
AS
begin

  -- Учительский чат - все учителя
  FOR
    SELECT V3357.VAL, V3355.VAL
    FROM LINKS L2
    JOIN VALS V3357 ON V3357.OBJ_ID = L2.OBJ_ID AND V3357.PARAM_ID = 3357 AND V3357.IS_DEL = 0
    JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
    JOIN VALS V3355 ON V3355.OBJ_ID = L14.OBJ_ID AND V3355.PARAM_ID = 3355 AND V3355.IS_DEL = 0
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    UNION
    SELECT V3357.VAL, V3355.VAL
    FROM LINKS L2
    JOIN LINKS L211 ON L211.PARENT_ID = L2.OBJ_ID AND L211.OBJ_TYPE_ID = 211 AND L211.DATE_DEL IS NULL
    JOIN VALS V3357 ON V3357.OBJ_ID = L2.OBJ_ID AND V3357.PARAM_ID = 3357 AND V3357.IS_DEL = 0
    JOIN LINKS L14 ON L14.PARENT_ID = L211.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
    JOIN VALS V3355 ON V3355.OBJ_ID = L14.OBJ_ID AND V3355.PARAM_ID = 3355 AND V3355.IS_DEL = 0
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    ORDER BY 2
    INTO :CHAT_ID, :USER_ID
  DO
  BEGIN
    IF(POSITION(',' IN CHAT_ID) > 0) THEN CHAT_ID = SUBSTRING(CHAT_ID FROM 1 FOR POSITION(',' IN CHAT_ID) - 1);
    SUSPEND;
  END

  -- Классные чаты
  FOR
    -- Ученики
    SELECT V3336.VAL, V3354.VAL
    FROM LINKS L2
    JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
    JOIN VALS V3336 ON V3336.OBJ_ID = L9.OBJ_ID AND V3336.PARAM_ID = 3336 AND V3336.IS_DEL = 0
    JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    JOIN VALS V3354 ON V3354.OBJ_ID = L10.OBJ_ID AND V3354.PARAM_ID = 3354 AND V3354.IS_DEL = 0
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    -- Родители - могут повторяться в одном классе
    UNION
    SELECT DISTINCT V3359.VAL, V3356.VAL
    FROM LINKS L2
    JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V49.LISTVAL_ID
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
    JOIN VALS V3359 ON V3359.OBJ_ID = L9.OBJ_ID AND V3359.PARAM_ID = 3359 AND V3359.IS_DEL = 0
    JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    JOIN LINKS L20 ON L20.PARENT_ID = L10.OBJ_ID AND L20.OBJ_TYPE_ID = 20 AND L20.DATE_DEL IS NULL
    JOIN VALS V3356 ON V3356.OBJ_ID = L20.OBJ_ID AND V3356.PARAM_ID = 3356 AND V3356.IS_DEL = 0
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    -- Классные руководители - два чата
    UNION
    SELECT V3336.VAL, V3355.VAL
    FROM LINKS L2
    JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
    JOIN VALS V3336 ON V3336.OBJ_ID = L9.OBJ_ID AND V3336.PARAM_ID IN (3336, 3359) AND V3336.IS_DEL = 0
    JOIN VALR V53 ON V53.OBJ_ID = L9.OBJ_ID AND V53.PARAM_ID = 53 AND V53.IS_DEL = 0
    JOIN VALS V3355 ON V3355.OBJ_ID = V53.VAL AND V3355.PARAM_ID = 3355 AND V3355.IS_DEL = 0
    ORDER BY 2
    INTO :CHAT_ID, :USER_ID
  DO
  BEGIN
    IF(POSITION(',' IN CHAT_ID) > 0) THEN CHAT_ID = SUBSTRING(CHAT_ID FROM 1 FOR POSITION(',' IN CHAT_ID) - 1);
    SUSPEND;
  END

  -- Предметные чаты
  FOR
    -- предметник
    SELECT J.CHAT_ID, V3355.VAL
    FROM CJ2_JOURNAL J
    JOIN VALS V3355 ON V3355.OBJ_ID = J.TEACHER_ID AND V3355.PARAM_ID = 3355 AND V3355.IS_DEL = 0
    WHERE J.DATE_DEL IS NULL AND J.CHAT_ID IS NOT NULL AND J.VK_ENABLED = 1
    -- ученики
    UNION
    SELECT J.CHAT_ID, V3354.VAL
    FROM CJ2_JOURNAL J
    JOIN LINKS L10 ON L10.PARENT_ID = J.GRADE_ID AND L10.DATE_DEL IS NULL AND L10.DATE_DEL IS NULL
    JOIN VALS V3354 ON V3354.OBJ_ID = L10.OBJ_ID AND V3354.PARAM_ID = 3354 AND V3354.IS_DEL = 0
    WHERE J.DATE_DEL IS NULL AND J.CHAT_ID IS NOT NULL AND J.VK_ENABLED = 1
    ORDER BY 2
    INTO :CHAT_ID, :USER_ID
  DO
  BEGIN
    IF(POSITION(',' IN CHAT_ID) > 0) THEN CHAT_ID = SUBSTRING(CHAT_ID FROM 1 FOR POSITION(',' IN CHAT_ID) - 1);
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_SFERUM_SUBJCHATS (
    I$OBJ_ID BIGINT,
    I$TIMEMARK TIMESTAMP = CURRENT_TIMESTAMP)
RETURNS (
    CLASS_ID BIGINT,
    CLASS_CAPTION VARCHAR(400),
    CLASS_INDEX INTEGER,
    SUBJECT_NAME VARCHAR(400),
    CHANGE_MASK INTEGER,
    CHAT_ID VARCHAR(100),
    OBJ_ID BIGINT,
    OBJ_TYPE_ID BIGINT,
    ADD_ID VARCHAR(100),
    DEL_ID VARCHAR(100),
    FORCE_WM SMALLINT,
    DEL_REASON VARCHAR(20),
    CHAT_TITLE VARCHAR(4000))
AS
DECLARE VARIABLE V$YEAR_ID BIGINT;
DECLARE VARIABLE V$DATE DATE;
DECLARE VARIABLE V$TEACHER_ID BIGINT;
DECLARE VARIABLE V$GRADE_ID BIGINT;
DECLARE VARIABLE V$CHANGE_TM TIMESTAMP;
DECLARE VARIABLE V$TM TIMESTAMP;
DECLARE VARIABLE V$YEAR_TM TIMESTAMP;
DECLARE VARIABLE V$ZTM TIMESTAMP;
DECLARE VARIABLE V$OU_TITLE VARCHAR(1000);
begin

  IF(I$OBJ_ID IS NULL) THEN
  SELECT FIRST 1 L2.OBJ_ID
  FROM LINKS L2
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :I$OBJ_ID;

  SELECT FIRST 1 V1236.LISTVAL_ID, CAST(LV.TAG AS DATE), V1236.DATE_MODIFY
  FROM VALL V1236
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE V1236.OBJ_ID = :I$OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  INTO :V$YEAR_ID, :V$DATE, :V$YEAR_TM;

  SELECT FIRST 1 V2.VAL
  FROM VALS V2
  WHERE V2.OBJ_ID = :I$OBJ_ID AND V2.PARAM_ID = 2 AND V2.IS_DEL = 0
  INTO :V$OU_TITLE;

  -- Для СПО берем наименование из другого параметра
  IF(SUBSTRING(V$OU_TITLE FROM 1 FOR 2) = '19') THEN
  SELECT FIRST 1 V999.VAL
  FROM VALS V999
  WHERE V999.OBJ_ID = :I$OBJ_ID AND V999.PARAM_ID = 999 AND V999.IS_DEL = 0
  INTO :V$OU_TITLE;

  IF(V$OU_TITLE IS NULL) THEN EXCEPTION DATA_ERROR 'Не внесено наименование ОУ';

  -- Нулевая метка времени
  V$ZTM = '2024-01-01';

  -- Главную метку сдвигаем на 1 день назад, потому что иначе обновления меток будут идти постоянно
  -- по сути нам важно NULL или не-NULL
  I$TIMEMARK = DATEADD(1 DAY TO I$TIMEMARK);

  FORCE_WM = 0;

  FOR
    SELECT J.OBJ_ID, J.JOURNAL_NAME || ' ' || C.CAPTION, J.CHAT_ID, J.TEACHER_ID, J.GRADE_ID, C.CAPTION, LV.COST, J.CHAT_TIMEMARK
    FROM CJ2_JOURNAL J
    JOIN LISTVALS LV ON LV.LISTVAL_ID = J.STAGE_INDEX
    LEFT JOIN OBJECT_CAPTION_GET(J.SUBJECT_ID) C ON 1 = 1
    WHERE J.DATE_DEL IS NULL AND J.JOURNAL_TYPE = 0 AND J.YEAR_ID = :V$YEAR_ID AND J.VK_ENABLED = 1
    AND (J.CHAT_ID IS NOT NULL OR EXISTS(
      SELECT FIRST 1 1
      FROM CJ2_JOURNAL_LESSONS L
      WHERE L.DATE_DEL IS NULL AND L.CJ_ID = J.OBJ_ID AND L.IS_ONLINE = 1 AND (L.IS_PUBLISHED = 1 OR L.IS_COMPLETED = 1)
    ))
    ORDER BY 1
    INTO :CLASS_ID, :CLASS_CAPTION, :CHAT_ID, :V$TEACHER_ID, :V$GRADE_ID, :SUBJECT_NAME, :CLASS_INDEX, :V$TM
  DO
  BEGIN
    OBJ_ID = NULL;
    ADD_ID = NULL;
    DEL_ID = NULL;
    CHANGE_MASK = 0;
    CHAT_TITLE = CLASS_CAPTION || ' · ' || V$OU_TITLE;

    IF(I$TIMEMARK IS NULL) THEN V$TM = NULL;
    IF(I$TIMEMARK < V$TM) THEN V$TM = I$TIMEMARK;

    -- Маска изменения чата, тут смотрим только бит 0 - изменение учебного года
    IF(V$TM IS NULL OR V$TM < DATEADD(1 DAY TO V$YEAR_TM)) THEN CHANGE_MASK = BIN_OR(CHANGE_MASK, 1);
    SUSPEND;
    CHANGE_MASK = 0;

    -- Удаление юзеров
    ADD_ID = NULL;
    FOR
      -- Выбывшие ученики
      SELECT DISTINCT M.PERSON_ID, 10, V3354.SVAL, 'change_class', MAXVALUE(COALESCE(M.DATE_MODIFY, :V$ZTM), COALESCE(V3354.DATE_MODIFY, :V$ZTM)) TMV
      FROM PERSON_MOVEMENTS M
      JOIN VALS V3354 ON V3354.OBJ_ID = M.PERSON_ID AND V3354.PARAM_ID = 3354 AND V3354.IS_DEL = 0
      LEFT JOIN PERSON_MOVEMENTS M2 ON M2.DATE_DEL IS NULL AND M2.GROUP_ID = M.GROUP_ID AND M2.PERSON_ID = M.PERSON_ID AND M2.DATE_OUT IS NULL
      WHERE M.DATE_DEL IS NULL AND M.GROUP_ID = :V$GRADE_ID AND M.DATE_OUT >= :V$DATE AND M2.OBJ_ID IS NULL
      -- Аннулированные id действующих учеников
      UNION
      SELECT DISTINCT M.PERSON_ID, 10, E.ID, 'mistake', MAXVALUE(COALESCE(M.DATE_MODIFY, :V$ZTM), COALESCE(V3363.DATE_MODIFY, :V$ZTM)) TMV
      FROM PERSON_MOVEMENTS M
      JOIN VALS V3363 ON V3363.OBJ_ID = M.PERSON_ID AND V3363.PARAM_ID = 3363 AND V3363.IS_DEL = 0
      LEFT JOIN EXPLODE_STR(V3363.VAL, ',') E ON 1 = 1
      WHERE M.DATE_DEL IS NULL AND M.GROUP_ID = :V$GRADE_ID AND M.DATE_OUT IS NULL
      -- Уволенный учитель
      UNION
      SELECT L14.OBJ_ID, L14.OBJ_TYPE_ID, V3355.SVAL, 'fired', MAXVALUE(COALESCE(L14.DATE_MODIFY, :V$ZTM), COALESCE(V3355.DATE_MODIFY, :V$ZTM)) TMV
      FROM LINKS L14
      JOIN VALS V3355 ON V3355.OBJ_ID = L14.OBJ_ID AND V3355.PARAM_ID = 3355 AND V3355.IS_DEL = 0
      WHERE L14.OBJ_ID = :V$TEACHER_ID AND L14.PARENT_TYPE_ID = 84 AND L14.DATE_DEL IS NULL
      -- Аннулированные id учителя
      UNION
      SELECT L14.OBJ_ID, L14.OBJ_TYPE_ID, E.ID, 'mistake', MAXVALUE(COALESCE(L14.DATE_MODIFY, :V$ZTM), COALESCE(V3364.DATE_MODIFY, :V$ZTM)) TMV
      FROM LINKS L14
      JOIN VALS V3364 ON V3364.OBJ_ID = L14.OBJ_ID AND V3364.PARAM_ID = 3364 AND V3364.IS_DEL = 0
      LEFT JOIN EXPLODE_STR(V3364.VAL, ',') E ON 1 = 1
      WHERE L14.OBJ_ID = :V$TEACHER_ID AND L14.PARENT_TYPE_ID = 2 AND L14.DATE_DEL IS NULL
      -- Пока неясно что делать со сменившимися учителями
      INTO :OBJ_ID, :OBJ_TYPE_ID, :DEL_ID, :DEL_REASON, :V$CHANGE_TM
    DO
    BEGIN
      DEL_REASON = TRIM(DEL_REASON);
      IF(V$TM IS NULL OR V$CHANGE_TM > V$TM) THEN
      SUSPEND;
    END

    -- Действующие ученики, учитель ??? и классный руководитель
    DEL_ID = NULL;
    DEL_REASON = NULL;
    FOR
      -- Ученики
      SELECT DISTINCT M.PERSON_ID, 10, V3354.SVAL, MAXVALUE(COALESCE(M.DATE_MODIFY, :V$ZTM), COALESCE(V3354.DATE_MODIFY, :V$ZTM)) TMV
      FROM PERSON_MOVEMENTS M
      JOIN VALS V3354 ON V3354.OBJ_ID = M.PERSON_ID AND V3354.PARAM_ID = 3354 AND V3354.IS_DEL = 0
      WHERE M.DATE_DEL IS NULL AND M.GROUP_ID = :V$GRADE_ID AND M.DATE_OUT IS NULL
      -- Учитель-предметник
      UNION
      SELECT L14.OBJ_ID, L14.OBJ_TYPE_ID, V3355.SVAL, MAXVALUE(COALESCE(L14.DATE_MODIFY, :V$ZTM), COALESCE(V3355.DATE_MODIFY, :V$ZTM)) TMV
      FROM LINKS L14
      JOIN VALS V3355 ON V3355.OBJ_ID = L14.OBJ_ID AND V3355.PARAM_ID = 3355 AND V3355.IS_DEL = 0
      WHERE L14.OBJ_ID = :V$TEACHER_ID AND L14.PARENT_TYPE_ID = 2 AND L14.DATE_DEL IS NULL
      INTO :OBJ_ID, :OBJ_TYPE_ID, :ADD_ID, :V$CHANGE_TM
    DO
    BEGIN
      IF(V$TM IS NULL OR V$CHANGE_TM > V$TM) THEN
      SUSPEND;
    END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_SFERUM_TEACHERS (
    I$OBJ_ID BIGINT,
    I$TIMEMARK TIMESTAMP = current_timestamp)
RETURNS (
    OBJ_ID BIGINT,
    ADD_ID VARCHAR(100),
    DEL_ID VARCHAR(100),
    CHANGE_MASK INTEGER,
    IS_ADMIN SMALLINT,
    DEL_REASON VARCHAR(20))
AS
declare variable V$TM timestamp;
declare variable V$ZTM timestamp;
declare variable V$CHANGE_TM timestamp;
declare variable V$ROLE_TM timestamp;
declare variable V$ALT_TM timestamp;
declare variable V$YEAR_TM timestamp;
begin

  IF(I$OBJ_ID IS NULL) THEN
  SELECT FIRST 1 L2.OBJ_ID
  FROM LINKS L2
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :I$OBJ_ID;

  -- Метка времени изменения учительского чата
  SELECT FIRST 1 V.VAL
  FROM VALDT V
  WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 3470 AND V.IS_DEL = 0
  INTO :V$TM;

  -- Главную метку сдвигаем на 1 день назад, потому что иначе обновления меток будут идти постоянно
  -- по сути нам важно NULL или не-NULL
  I$TIMEMARK = DATEADD(1 DAY TO I$TIMEMARK);
  IF(I$TIMEMARK IS NULL) THEN V$TM = NULL;
  IF(I$TIMEMARK < V$TM) THEN V$TM = I$TIMEMARK;

  -- Метка изменения учебного года
  SELECT FIRST 1 V1236.DATE_MODIFY
  FROM VALL V1236
  WHERE V1236.OBJ_ID = :I$OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  INTO :V$YEAR_TM;

  -- Нулевая метка времени
  V$ZTM = '2024-01-01';

  -- Самая первая строка в выдаче теперь пустая и идет для идентификации смены учебного года
  CHANGE_MASK = 0;
  -- Маска изменения чата, тут смотрим только бит 0 - изменение учебного года
  -- бит 1 = изменение атрибутов чата
  IF(V$TM IS NULL OR V$TM < DATEADD(1 MINUTE TO V$YEAR_TM)) THEN CHANGE_MASK = BIN_OR(CHANGE_MASK, 1);
  SUSPEND;
  CHANGE_MASK = 0;

  -- Сначала удаленные ID и ID выбывших сотрудников
  -- ??? надо ли дофильтровать, чтобы ID не было среди действующих
  FOR
    SELECT OBJ_ID, ID, DEL_REASON, MAX(TMV) FROM (
      SELECT V3364.OBJ_ID, E.ID, 'mistake' DEL_REASON, MAXVALUE(COALESCE(L14.DATE_MODIFY, :V$ZTM), COALESCE(V3364.DATE_MODIFY, :V$ZTM)) TMV
      FROM LINKS L14
      JOIN VALS V3364 ON V3364.OBJ_ID = L14.OBJ_ID AND V3364.PARAM_ID = 3364 AND V3364.IS_DEL = 0
      LEFT JOIN EXPLODE_STR(V3364.VAL, ',') E ON 1 = 1
      WHERE L14.PARENT_ID = :I$OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
      UNION
      -- подразделения
      SELECT V3364.OBJ_ID, E.ID, 'mistake', MAXVALUE(COALESCE(L14.DATE_MODIFY, :V$ZTM), COALESCE(V3364.DATE_MODIFY, :V$ZTM)) TMV
      FROM LINKS L211
      JOIN LINKS L14 ON L14.PARENT_ID = L211.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
      JOIN VALS V3364 ON V3364.OBJ_ID = L14.OBJ_ID AND V3364.PARAM_ID = 3364 AND V3364.IS_DEL = 0
      LEFT JOIN EXPLODE_STR(V3364.VAL, ',') E ON 1 = 1
      WHERE L211.PARENT_ID = :I$OBJ_ID AND L211.OBJ_TYPE_ID = 211 AND L211.DATE_DEL IS NULL
      UNION
      SELECT L14.OBJ_ID, V3355.SVAL, 'fired', MAXVALUE(COALESCE(L14.DATE_MODIFY, :V$ZTM), COALESCE(V3355.DATE_MODIFY, :V$ZTM)) TMV
      FROM LINKS L84
      JOIN LINKS L14 ON L14.PARENT_ID = L84.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
      JOIN VALS V3355 ON V3355.OBJ_ID = L14.OBJ_ID AND V3355.PARAM_ID = 3355 AND V3355.IS_DEL = 0
      WHERE L84.PARENT_ID = :I$OBJ_ID AND L84.OBJ_TYPE_ID = 84 AND L84.DATE_DEL IS NULL
    )
    GROUP BY 1, 2, 3
    INTO :OBJ_ID, :DEL_ID, :DEL_REASON, :V$CHANGE_TM
  DO
  BEGIN
    DEL_REASON = TRIM(DEL_REASON);
    IF(V$TM IS NULL OR V$CHANGE_TM > V$TM) THEN
    SUSPEND;
  END

  DEL_ID = NULL;
  DEL_REASON = NULL;

  -- ID действующих сотрудников
  -- Админа даем руководителям 1 уровня, а также юзерам с ролью директор или администратор
  FOR
    SELECT L14.OBJ_ID, V3355.SVAL, MAXVALUE(COALESCE(L14.DATE_MODIFY, :V$ZTM), COALESCE(V3355.DATE_MODIFY, :V$ZTM)) TMV
    FROM LINKS L14
    JOIN VALS V3355 ON V3355.OBJ_ID = L14.OBJ_ID AND V3355.PARAM_ID = 3355 AND V3355.IS_DEL = 0
    WHERE L14.PARENT_ID = :I$OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
    UNION
    SELECT L14.OBJ_ID, V3355.SVAL, MAXVALUE(COALESCE(L14.DATE_MODIFY, :V$ZTM), COALESCE(V3355.DATE_MODIFY, :V$ZTM)) TMV
    FROM LINKS L211
    JOIN LINKS L14 ON L14.PARENT_ID = L211.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
    JOIN VALS V3355 ON V3355.OBJ_ID = L14.OBJ_ID AND V3355.PARAM_ID = 3355 AND V3355.IS_DEL = 0
    WHERE L211.PARENT_ID = :I$OBJ_ID AND L211.OBJ_TYPE_ID = 211 AND L211.DATE_DEL IS NULL
    INTO :OBJ_ID, :ADD_ID, :V$CHANGE_TM
  DO
  BEGIN
    IS_ADMIN = 0;
    SELECT FIRST 1 1
    FROM LINKS L15
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
    JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
    JOIN VALL V64 ON V64.OBJ_ID = LP13.PARENT_ID AND V64.PARAM_ID = 64 AND V64.IS_DEL = 0 AND V64.LISTVAL_ID = 56
    WHERE L15.PARENT_ID = :OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL AND V74.VAL IS NULL
    INTO :IS_ADMIN;

    -- Проверяем метку времени последнего изменения должности
    V$ROLE_TM = NULL;
    SELECT MAX(MAXVALUE(COALESCE(L15.DATE_MODIFY, :V$ZTM), COALESCE(V74.DATE_MODIFY, :V$ZTM)))
    FROM LINKS L15
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
    WHERE L15.PARENT_ID = :OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
    INTO :V$ROLE_TM;

    -- Метка времени последнего изменения роли
    IF(IS_ADMIN = 0) THEN
    SELECT FIRST 1 1
    FROM USERS U
    WHERE U.DATE_DEL IS NULL AND U.OBJ_ID = :OBJ_ID AND U.IS_BLOCKED = 0 AND (U.EXP_DATE IS NULL OR U.EXP_DATE > CURRENT_DATE) AND U.USER_TYPE IN (1, 5)
    INTO :IS_ADMIN;

    V$ALT_TM = NULL;
    SELECT MAX(U.DATE_MODIFY)
    FROM USERS U
    WHERE U.OBJ_ID = :OBJ_ID
    INTO :V$ALT_TM;

    IF(V$TM IS NULL OR V$CHANGE_TM > V$TM OR V$ROLE_TM > V$TM OR V$ALT_TM > V$TM) THEN
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_SFERUM_TIMEDOUT RETURNS (
    CHAT_ID VARCHAR(40),
    CJ_ID BIGINT,
    LESSON_ID BIGINT,
    CALL_ID VARCHAR(40))
AS
declare variable V$TODAY smallint;
declare variable V$DATE date;
declare variable V$N integer;
declare variable V$T time;
declare variable V$TN integer;
declare variable V$END_TIME time;
declare variable V$LE time;
declare variable V$H float;
declare variable CURRENT_NUM integer;
declare variable H integer;
declare variable M integer;
declare variable S varchar(400);
begin

  V$T = DATEADD(- 20 MINUTE TO CURRENT_TIME);
  --V$T = DATEADD(- 20 MINUTE TO CAST('04.09.2023 12:45' AS TIMESTAMP));

  -- Количество минут с начала суток, но точно не раньше 01:00 чтобы не пересечься с номерами уроков
  V$TN = EXTRACT(MINUTE FROM V$T) + 60 * EXTRACT(HOUR FROM V$T);
  IF(V$TN < 60) THEN V$TN = NULL;

  FOR
    SELECT J.OBJ_ID, J.CHAT_ID, L.OBJ_ID, L.INST_ID, IIF(L.LESSON_DATE < CURRENT_DATE, 0, 1), L.LESSON_DATE, L.LESSON_NUM, L.LESSON_HOURS
    FROM CJ2_JOURNAL J
    JOIN CJ2_JOURNAL_LESSONS L ON L.CJ_ID = J.OBJ_ID AND L.IS_ONLINE = 1 AND L.INST_ID IS NOT NULL AND L.INST_STATUS = 1 AND L.LESSON_DATE <= CURRENT_DATE
    WHERE J.DATE_DEL IS NULL AND J.VK_ENABLED = 1 AND J.CHAT_ID IS NOT NULL
    ORDER BY L.LESSON_DATE, L.LESSON_NUM
    INTO :CJ_ID, :S, :LESSON_ID, :CALL_ID, :V$TODAY, :V$DATE, :V$N, :V$H
  DO
  BEGIN
    S = SUBSTRING(S FROM 1 FOR POSITION(',' IN S) - 1);
    CHAT_ID = S;

    -- Сегодняшние уроки проверяем по времени окончания
    IF(V$TODAY = 1) THEN
    BEGIN

      -- Для уроков короче часа ставим все равно 1 час
      IF(V$H = 0) THEN V$H = 1;

      IF(V$N < 60) THEN
      BEGIN
        -- Урок по номеру
        -- Ищем номер урока и время окончания урока, который должен сейчас идти
        -- если мы вышли за сетку времени, то будет последний по времени урок в сетке
        CURRENT_NUM = NULL;
        SELECT FIRST 1 V404.VAL, V406.VAL
        FROM SCHEDULE_ITEMS SI
        JOIN VALD V3120 ON V3120.OBJ_ID = SI.SCHEDULE_ID AND V3120.PARAM_ID = 3120 AND V3120.IS_DEL = 0 AND V3120.VAL <= CURRENT_DATE
        JOIN VALD V3121 ON V3121.OBJ_ID = SI.SCHEDULE_ID AND V3121.PARAM_ID = 3121 AND V3121.IS_DEL = 0 AND V3121.VAL >= CURRENT_DATE
        JOIN VALL V1341 ON V1341.OBJ_ID = SI.SCHEDULE_ID AND V1341.PARAM_ID = 1341 AND V1341.IS_DEL = 0 AND V1341.LISTVAL_ID = 2
        JOIN LINKS L60 ON L60.PARENT_ID = SI.SCHEDULE_ID AND L60.OBJ_TYPE_ID = 60 AND L60.DATE_DEL IS NULL
        JOIN VALT V405 ON V405.OBJ_ID = L60.OBJ_ID AND V405.PARAM_ID = 405 AND V405.IS_DEL = 0 AND V405.VAL <= CURRENT_TIME
        JOIN VALT V406 ON V406.OBJ_ID = L60.OBJ_ID AND V406.PARAM_ID = 406 AND V406.IS_DEL = 0
        JOIN VALI V404 ON V404.OBJ_ID = L60.OBJ_ID AND V404.PARAM_ID = 404 AND V404.IS_DEL = 0
        WHERE SI.DATE_DEL IS NULL AND SI.CJ_ID = :CJ_ID
        ORDER BY V405.VAL DESC
        INTO :CURRENT_NUM, :V$END_TIME;

        -- Если данный журнал не нашелся в расписании, пытаемся отыскать первую попавшуюся сетку расписания текущего года
        IF(CURRENT_NUM IS NULL) THEN
        SELECT FIRST 1 V404.VAL, V406.VAL
        FROM LINKS L2
        JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
        JOIN LINKS L68 ON L68.PARENT_ID = L2.OBJ_ID AND L68.OBJ_TYPE_ID = 68 AND L68.DATE_DEL IS NULL
        JOIN LINKS L3 ON L3.PARENT_ID = L68.OBJ_ID AND L3.OBJ_TYPE_ID = 3 AND L3.DATE_DEL IS NULL
        JOIN VALL V37 ON V37.OBJ_ID = L3.OBJ_ID AND V37.PARAM_ID = 37 AND V37.IS_DEL = 0 AND V37.LISTVAL_ID = V1236.LISTVAL_ID
        JOIN LINKS L59 ON L59.PARENT_ID = L3.OBJ_ID AND L59.OBJ_TYPE_ID = 59 AND L59.DATE_DEL IS NULL
        JOIN VALL V1341 ON V1341.OBJ_ID = L59.OBJ_ID AND V1341.PARAM_ID = 1341 AND V1341.IS_DEL = 0 AND V1341.LISTVAL_ID = 2
        JOIN VALD V3120 ON V3120.OBJ_ID = L59.OBJ_ID AND V3120.PARAM_ID = 3120 AND V3120.IS_DEL = 0 AND V3120.VAL <= CURRENT_DATE
        JOIN VALD V3121 ON V3121.OBJ_ID = L59.OBJ_ID AND V3121.PARAM_ID = 3121 AND V3121.IS_DEL = 0 AND V3121.VAL >= CURRENT_DATE
        JOIN LINKS L60 ON L60.PARENT_ID = L59.OBJ_ID AND L60.OBJ_TYPE_ID = 60 AND L60.DATE_DEL IS NULL
        JOIN VALT V405 ON V405.OBJ_ID = L60.OBJ_ID AND V405.PARAM_ID = 405 AND V405.IS_DEL = 0 AND V405.VAL <= CURRENT_TIME
        JOIN VALT V406 ON V406.OBJ_ID = L60.OBJ_ID AND V406.PARAM_ID = 406 AND V406.IS_DEL = 0
        JOIN VALI V404 ON V404.OBJ_ID = L60.OBJ_ID AND V404.PARAM_ID = 404 AND V404.IS_DEL = 0
        WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
        ORDER BY V405.VAL DESC
        INTO :CURRENT_NUM, :V$END_TIME;

        -- Если урок поставлен более 1 часа, корректируем время окончания
        -- дробные доли не работают, разделяем на часы и минуты
        H = V$H;
        M = (V$H - H) * 60;
        IF(V$H > 1) THEN V$END_TIME = DATEADD(M MINUTE TO DATEADD(H HOUR TO V$END_TIME));

        IF(V$END_TIME < V$T) THEN V$TODAY = NULL;
        IF(CURRENT_NUM IS NULL) THEN V$TODAY = NULL;
      END
      ELSE
      BEGIN
        -- Урок по времени, переводим минуты с начала суток во время
        -- ко времени начала урока добавляем длительность
        V$N = V$N + V$H * 60;

        H = V$N / 60;
        M = V$N - H * 60;
        S = M;
        IF(CHAR_LENGTH(S) < 2) THEN S = '0' || S;
        S = H || ':' || S;
        IF(CHAR_LENGTH(5) < 2) THEN S = '0' || S;
        V$END_TIME = S;

        IF(V$END_TIME < V$T) THEN V$TODAY = NULL;
      END

    END

    IF(V$TODAY IS NOT NULL) THEN SUSPEND;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_SFERUM_WM (
    I$OBJ_ID VARCHAR(400),
    I$USER_ID VARCHAR(40))
AS
declare variable V$OBJ_ID bigint;
declare variable V$PARAM_ID bigint;
begin

  SELECT FIRST 1 V.OBJ_ID, V.PARAM_ID
  FROM VALS V
  WHERE V.PARAM_ID IN (3357, 3336, 3359) AND V.IS_DEL = 0 AND V.SVAL = :I$OBJ_ID
  INTO :V$OBJ_ID, :V$PARAM_ID;

  IF(V$OBJ_ID IS NOT NULL) THEN
  BEGIN
    -- Выставляем признак обновления
    UPDATE VALS
    SET XVAL = '1'
    WHERE OBJ_ID = :V$OBJ_ID AND PARAM_ID = :V$PARAM_ID AND XVAL IS NULL;
  END
  ELSE
  BEGIN
    -- Объект не нашелся, значит это предметный чат (либо объект удален)
    SELECT FIRST 1 J.OBJ_ID
    FROM CJ2_JOURNAL J
    WHERE J.DATE_DEL IS NULL AND J.CHAT_ID = :I$OBJ_ID
    INTO :V$OBJ_ID;

    IF(V$OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Указанный чат Сферум не найден';

    -- Скидываем метку времени
    UPDATE CJ2_JOURNAL
    SET CHAT_TIMEMARK = NULL
    WHERE OBJ_ID = :V$OBJ_ID AND CHAT_TIMEMARK IS NOT NULL;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_SOCIAL_DELETE (
    I$OBJ_ID BIGINT)
AS
DECLARE VARIABLE V$TYPE_ID BIGINT;
DECLARE VARIABLE V$PARAM_ID BIGINT;
DECLARE VARIABLE V$SPARE_ID BIGINT;
DECLARE VARIABLE V$OLD_ID BIGINT;
DECLARE VARIABLE V$OLD_CODE VARCHAR(100);
DECLARE VARIABLE S VARCHAR(4000);
DECLARE VARIABLE S2 VARCHAR(4000);
begin

  SELECT TYPE_ID
  FROM OBJECTS
  WHERE OBJ_ID = :I$OBJ_ID
  INTO :V$TYPE_ID;

  IF(V$TYPE_ID = 10) THEN
  BEGIN
    V$PARAM_ID = 3354;
    V$SPARE_ID = 3363;
  END
  ELSE IF(V$TYPE_ID = 14) THEN
  BEGIN
    V$PARAM_ID = 3355;
    V$SPARE_ID = 3364;
  END
  ELSE IF(V$TYPE_ID = 20) THEN
  BEGIN
    V$PARAM_ID = 3356;
    V$SPARE_ID = 3365;
  END
  -- Все прочие варианты просто игнорируем, в том числе если NULL
  ELSE
    EXIT;

  SELECT FIRST 1 V.VAL
  FROM VALS V
  WHERE V.PARAM_ID = :V$PARAM_ID AND V.OBJ_ID = :I$OBJ_ID AND V.IS_DEL = 0
  INTO :V$OLD_CODE;

  -- Если старый код - мусор (не число), выкидываем его
  IF(V$OLD_CODE IS NOT NULL) THEN
  BEGIN
    S = V$OLD_CODE;
    WHILE(CHAR_LENGTH(S) > 0) DO
    BEGIN
      IF(POSITION(SUBSTRING(S FROM 1 FOR 1) IN '0123456789') <= 0) THEN V$OLD_CODE = NULL;
      S = SUBSTRING(S FROM 2);
    END
  END

  -- Переносим текущий код в старые (добавляем, если там уже что-то было)
  IF(V$OLD_CODE IS NOT NULL) THEN
  BEGIN
    SELECT FIRST 1 V.VAL
    FROM VALS V
    WHERE V.PARAM_ID = :V$SPARE_ID AND V.OBJ_ID = :I$OBJ_ID AND V.IS_DEL = 0
    INTO :S;

    -- Убираем возможные повторы
    S2 = '';
    FOR
      SELECT DISTINCT ID
      FROM STR_TO_ID_LIST(:S)
      UNION
      SELECT CAST(:V$OLD_CODE AS BIGINT)
      FROM RDB$DATABASE
      ORDER BY 1
      INTO :V$OLD_ID
    DO
    BEGIN
      IF(S2 <> '') THEN S2 = S2 || ',';
      S2 = S2 || V$OLD_ID;
    END

    -- Что-то поменялось ?
    IF(S <> S2) THEN
    BEGIN
      SELECT 1 FROM VAL_ADD(:V$SPARE_ID, :I$OBJ_ID, :S2) INTO :V$TYPE_ID;
    END
  END

  -- Удаляем сам текущий код, на всякий случай вообще все варианты кода
  UPDATE VALS SET IS_DEL = 1 WHERE OBJ_ID = :I$OBJ_ID AND PARAM_ID IN (3354, 3355, 3356) AND IS_DEL = 0;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_SOCIAL_SAVE (
    I$OBJ_ID BIGINT,
    I$CODE VARCHAR(100),
    I$SN VARCHAR(100))
RETURNS (
    OBJ_ID BIGINT)
AS
DECLARE VARIABLE V$TYPE_ID BIGINT;
DECLARE VARIABLE V$PARAM_ID BIGINT;
DECLARE VARIABLE V$SPARE_ID BIGINT;
DECLARE VARIABLE V$OLD_CODE VARCHAR(4000);
DECLARE VARIABLE V$IS_OLD SMALLINT;
DECLARE VARIABLE V$TEACHER_ID BIGINT;
DECLARE VARIABLE V$NAME_LAST VARCHAR(200);
DECLARE VARIABLE V$NAME_FIRST VARCHAR(200);
DECLARE VARIABLE V$PID VARCHAR(100);
DECLARE VARIABLE S VARCHAR(4000);
begin

  -- Заменить на MAX ?
  IF(I$SN <> 'VK') THEN EXIT;

  -- На выходе выдаем реальные OBJ_ID персоны, для которой будет записан код
  -- поскольку персона на входе может не совпадать в следующих случаях:
  -- 1 если на входе код чата родителя, но он является сотрудником
  -- 2 если родитель внесен в систему несколько раз, и код размножится по всем инкарнациям
  OBJ_ID = I$OBJ_ID;

  SELECT TYPE_ID
  FROM OBJECTS
  WHERE OBJ_ID = :I$OBJ_ID
  INTO :V$TYPE_ID;

  IF(V$TYPE_ID = 10) THEN
  BEGIN
    V$PARAM_ID = 3354;
    V$SPARE_ID = 3363;
  END
  ELSE IF(V$TYPE_ID = 14) THEN
  BEGIN
    V$PARAM_ID = 3355;
    V$SPARE_ID = 3364;
  END
  ELSE IF(V$TYPE_ID = 20) THEN
  BEGIN
    V$PARAM_ID = 3356;
    V$SPARE_ID = 3365;
  END
  -- Вероятно тут вообще не нашлось - выходим чтобы не упало дальше
  ELSE
    EXIT;

  SELECT FIRST 1 V.VAL
  FROM VALS V
  WHERE V.PARAM_ID = :V$PARAM_ID AND V.OBJ_ID = :I$OBJ_ID AND V.IS_DEL = 0
  INTO :V$OLD_CODE;

  -- Переносим текущий код в старые (добавляем, если там уже что-то было)
  -- История с возможной сменой vk_id является крайне проблемной, и в реальной жизни существовать не должна
  -- в особенности если код одной персоны переписывается на код другой персоны
  IF(V$OLD_CODE IS NOT NULL AND V$OLD_CODE <> COALESCE(I$CODE, '')) THEN
  BEGIN
    SELECT FIRST 1 V.VAL
    FROM VALS V
    WHERE V.PARAM_ID = :V$SPARE_ID AND V.OBJ_ID = :I$OBJ_ID AND V.IS_DEL = 0
    INTO :S;

    -- Проверяем, не были ли код уже упомянут среди старых кодов персоны
    IF(EXISTS(SELECT 1 FROM STR_IN_LIST(:I$CODE, :S, ',') WHERE IS_PRESENT = 1)) THEN V$IS_OLD = 1; ELSE V$IS_OLD = 0;

    -- Если пошел повтор ранее отмененного кода - удаляем код вовсе
    -- и ждем, пока он отработает на портале - запишем новый только когда все зачистится
    IF(V$IS_OLD = 1 OR I$CODE = '' OR I$CODE IS NULL) THEN
    BEGIN
      SELECT 1 FROM VAL_ADD(:V$PARAM_ID, :I$OBJ_ID, '') INTO :V$TYPE_ID;
      EXIT;
    END

    IF(S IS NULL) THEN S = ''; ELSE S = S || ',';
    S = S || V$OLD_CODE;

    SELECT 1 FROM VAL_ADD(:V$SPARE_ID, :I$OBJ_ID, :S) INTO :V$TYPE_ID;
  END

  -- Если это ученик - проверяем уникальность кода глобально
  -- для старых учеников коды должны быть зачищены после выбытия в кратчайшие сроки
  IF(V$TYPE_ID = 10) THEN
  BEGIN
    -- Ни в коем случае не должно быть повторений id для актуальных персон
    IF(EXISTS(
      SELECT FIRST 1 1
      FROM VALS V
      JOIN LINKS LP ON LP.OBJ_ID = V.OBJ_ID AND LP.PARENT_TYPE_ID IN (2, 9, 10, 125, 187, 81, 82, 83, 84) AND LP.DATE_DEL IS NULL
      WHERE V.PARAM_ID IN (3354, 3355, 3356) AND V.OBJ_ID <> :I$OBJ_ID AND V.IS_DEL = 0 AND V.SVAL = :I$CODE
    ))
    THEN
      EXCEPTION DATA_ERROR 'Дублирование кода VK ' || I$CODE || ' для ученика ' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$OBJ_ID));

    SELECT 1 FROM VAL_ADD(3354, :I$OBJ_ID, :I$CODE) INTO :V$TYPE_ID;
    SUSPEND;
  END
  -- Если это родитель или сотрудник
  ELSE
  BEGIN
    -- Прибить этот код у всех инкарнаций персоны как у ученика
    UPDATE VALS
    SET IS_DEL = 1
    WHERE PARAM_ID = 3354 AND IS_DEL = 0 AND SVAL = :I$CODE;
    -- Какие у нас ФИО и портальный код персоны ?
    SELECT FIRST 1 V1.VAL, V2.VAL, V3.VAL
    FROM VALS V1
    JOIN VALS V2 ON V2.OBJ_ID = V1.OBJ_ID AND V2.PARAM_ID IN (60, 129) AND V2.IS_DEL = 0
    JOIN VALS V3 ON V3.OBJ_ID = V1.OBJ_ID AND V3.PARAM_ID IN (155, 267) AND V3.IS_DEL = 0
    WHERE V1.OBJ_ID = :I$OBJ_ID AND V1.PARAM_ID IN (59, 128) AND V1.IS_DEL = 0
    INTO :V$NAME_LAST, :V$NAME_FIRST, :V$PID;
    -- Если есть действующая инкарнация персоны в виде учителя - она становится приоритетной
    SELECT FIRST 1 L14.OBJ_ID
    FROM VALS V267
    JOIN LINKS L14 ON L14.OBJ_ID = V267.OBJ_ID AND L14.PARENT_TYPE_ID = 2 AND L14.DATE_DEL IS NULL
    JOIN VALS V59 ON V59.OBJ_ID = L14.OBJ_ID AND V59.PARAM_ID = 59 AND V59.SVAL = :V$NAME_LAST
    JOIN VALS V60 ON V60.OBJ_ID = L14.OBJ_ID AND V60.PARAM_ID = 60 AND V60.SVAL = :V$NAME_FIRST
    WHERE V267.PARAM_ID = 267 AND V267.IS_DEL = 0 AND V267.SVAL = :V$PID
    INTO :V$TEACHER_ID;

    IF(V$TEACHER_ID IS NOT NULL) THEN
    BEGIN
      -- Ни в коем случае не должно быть повторений id для других учителей
      IF(EXISTS(
        SELECT FIRST 1 1
        FROM VALS V
        JOIN LINKS LP ON LP.OBJ_ID = V.OBJ_ID AND LP.PARENT_TYPE_ID = 2 AND LP.DATE_DEL IS NULL
        WHERE V.PARAM_ID = 3355 AND V.OBJ_ID <> :I$OBJ_ID AND V.IS_DEL = 0 AND V.SVAL = :I$CODE
      ))
      THEN
        EXCEPTION DATA_ERROR 'Дублирование кода VK ' || I$CODE || ' для учителя ' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$OBJ_ID));
      -- Удаляем коды у всех инкарнаций в виде родителя
      UPDATE VALS
      SET IS_DEL = 1
      WHERE PARAM_ID = 3356 AND IS_DEL = 0 AND SVAL = :I$CODE;
      -- Обновляем код у учителя
      V$OLD_CODE = NULL;
      SELECT FIRST 1 V.VAL
      FROM VALS V
      WHERE V.PARAM_ID = 3355 AND V.OBJ_ID = :V$TEACHER_ID AND V.IS_DEL = 0
      INTO :V$OLD_CODE;

      IF(COALESCE(I$CODE, '') <> COALESCE(V$OLD_CODE, '')) THEN
      SELECT 1 FROM VAL_ADD(:V$PARAM_ID, :I$OBJ_ID, :I$CODE) INTO :V$TYPE_ID;
      SUSPEND;
    END
    ELSE
    BEGIN
      -- Персона является только родителем
      -- проверку уникальности делаем с учетом возможных нескольких инкарнаций в виде родителя
      IF(EXISTS(
        SELECT FIRST 1 1
        FROM VALS V
        JOIN LINKS LP ON LP.OBJ_ID = V.OBJ_ID AND LP.PARENT_TYPE_ID = 10 AND LP.DATE_DEL IS NULL
        LEFT JOIN VALS V155 ON V155.OBJ_ID = V.OBJ_ID AND V155.PARAM_ID = 155 AND V155.IS_DEL = 0
        WHERE V.PARAM_ID = 3356 AND V.OBJ_ID <> :I$OBJ_ID AND V.IS_DEL = 0 AND V.SVAL = :I$CODE
          AND (V155.SVAL IS NULL OR V155.SVAL <> :V$PID OR :V$PID IS NULL)
      ))
      THEN
        EXCEPTION DATA_ERROR 'Дублирование кода VK ' || I$CODE || ' для родителя ' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$OBJ_ID));
      -- Удаляем коды у всех инкарнаций в виде учителя
      UPDATE VALS
      SET IS_DEL = 1
      WHERE PARAM_ID = 3355 AND IS_DEL = 0 AND SVAL = :I$CODE;
      -- Обновляем код у всех инкарнаций данной персоны в виде копий родителя
      FOR
        SELECT DISTINCT V155.OBJ_ID, V3356.SVAL
        FROM VALS V155
        JOIN LINKS LP10 ON LP10.OBJ_ID = V155.OBJ_ID AND LP10.PARENT_TYPE_ID = 10 AND LP10.DATE_DEL IS NULL
        LEFT JOIN VALS V3356 ON V3356.OBJ_ID = V155.OBJ_ID AND V3356.PARAM_ID = 3356 AND V3356.IS_DEL = 0
        WHERE V155.PARAM_ID = 155 AND V155.IS_DEL = 0 AND V155.SVAL = :V$PID
        -- если вдруг портальный id исчез
        UNION
        SELECT :I$OBJ_ID, V3356.SVAL
        FROM RDB$DATABASE
        LEFT JOIN VALS V3356 ON V3356.OBJ_ID = :I$OBJ_ID AND V3356.PARAM_ID = 3356 AND V3356.IS_DEL = 0
        WHERE 1 = 1
        INTO :OBJ_ID, :S
      DO
      BEGIN
        IF(S IS NULL OR S <> I$CODE) THEN
          SELECT 1 FROM VAL_ADD(3356, :OBJ_ID, :I$CODE) INTO :V$TYPE_ID;
        SUSPEND;
      END
    END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_SOP_UPDATE (
    SUID BIGINT,
    MEAL_ID BIGINT,
    EVENT_DATE VARCHAR(100),
    FOOD_TYPE VARCHAR(100),
    FOOD_NAME VARCHAR(1000),
    FOOD_QTY FLOAT)
AS
declare variable PERSON_ID bigint;
declare variable EVENT_VAL integer;
begin

    -- Проверяем наличие указанного ученика или учителя в ОУ, а также преобразуем ID из глобального в локальный
    SELECT L10.OBJ_ID
    FROM LINKS L10
    WHERE L10.OBJ_ID = :SUID AND L10.OBJ_TYPE_ID IN (10, 14) AND L10.PARENT_TYPE_ID IN (2, 211, 9, 187) AND L10.DATE_DEL IS NULL
    INTO :PERSON_ID;

    IF(PERSON_ID IS NULL) THEN EXIT;

    IF(FOOD_TYPE = 'Буфет') THEN EVENT_VAL = 1;
    ELSE IF(FOOD_TYPE = 'Горячее') THEN EVENT_VAL = 2;
    ELSE IF(FOOD_TYPE = 'Льготное питание') THEN EVENT_VAL = 3;
    ELSE EXIT;

    FOOD_NAME = SUBSTRING(FOOD_NAME FROM 1 FOR 200);

    UPDATE OR INSERT INTO SOP_RAW
    (PERSON_ID, EVENT_DATE, EVENT_VAL, EVENT_ID, FOOD_NAME, FOOD_QTY)
    VALUES (:PERSON_ID, :EVENT_DATE, :EVENT_VAL, :MEAL_ID, :FOOD_NAME, :FOOD_QTY)
    MATCHING (EVENT_ID);

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_TRANSFER_CLASS (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(1000))
AS
declare variable V$GRADE_LV bigint;
declare variable V$YEAR_ID bigint;
declare variable V$TYPE_ID bigint;
declare variable V$OBJ_ID bigint;
declare variable S varchar(1000);
begin

  SELECT LP8.OBJ_TYPE_ID, LV.COST, V3024.LISTVAL_ID
  FROM LINKS LP8
  JOIN VALL V49 ON V49.OBJ_ID = LP8.PARENT_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V49.LISTVAL_ID
  LEFT JOIN VALL V3024 ON V3024.OBJ_ID = LP8.OBJ_ID AND V3024.PARAM_ID = 3024 AND V3024.IS_DEL = 0
  WHERE LP8.OBJ_ID = :I$OBJ_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
  INTO :V$TYPE_ID, :V$GRADE_LV, :V$YEAR_ID;

  TAG_NAME = 'stage';
  VAL = V$GRADE_LV;
  SUSPEND;

  TAG_NAME = 'year';
  VAL = V$YEAR_ID;
  SUSPEND;

  TAG_NAME = 'grades::json&colon;array';
  VAL = 1;
  SUSPEND;
  IF(V$TYPE_ID = 187) THEN
  BEGIN
    -- Все экстернаты следующей ступени
    FOR
      SELECT L187.OBJ_ID, C.CAPTION
      FROM LINKS L2
      JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
      JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L7.DATE_DEL IS NULL
      JOIN VALL V49 ON V49.OBJ_ID = L8.PARENT_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
      JOIN LISTVALS LV ON LV.LISTVAL_ID = V49.LISTVAL_ID AND LV.COST = :V$GRADE_LV + 1
      JOIN LINKS L187 ON L187.PARENT_ID = L8.OBJ_ID AND L187.OBJ_TYPE_ID = 187 AND L187.DATE_DEL IS NULL
      LEFT JOIN OBJECT_CAPTION_GET(L187.OBJ_ID) C ON 1 = 1
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      ORDER BY LV.COST, C.CAPTION
      INTO :V$OBJ_ID, :S
    DO
    BEGIN
      TAG_NAME = 'grades:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'grades:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'grades:r:name';
      VAL = S;
      SUSPEND;
    END
  END
  ELSE
  BEGIN
    -- Все классы ОВЗ той же ступени и следующей ступени обучения (без указания и первый год обучения)
    FOR
      SELECT L9.OBJ_ID, C.CAPTION -- || R.VAL
      FROM LINKS L2
      JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
      JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L7.DATE_DEL IS NULL
      JOIN VALL V49 ON V49.OBJ_ID = L8.PARENT_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
      JOIN LISTVALS LV ON LV.LISTVAL_ID = V49.LISTVAL_ID
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
      JOIN VALL V3024 ON V3024.OBJ_ID = L9.OBJ_ID AND V3024.PARAM_ID = 3024 AND V3024.IS_DEL = 0
      JOIN LISTVALS LV3024 ON LV3024.LISTVAL_ID = V3024.LISTVAL_ID
      JOIN RES R ON R.RES_ID = LV3024.RES_ID AND R.LANG_CODE = 'RU'
      LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C ON 1 = 1
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
        AND (LV.COST = :V$GRADE_LV OR LV.COST = :V$GRADE_LV + 1)
      ORDER BY LV.COST, C.CAPTION
      INTO :V$OBJ_ID, :S
    DO
    BEGIN
      TAG_NAME = 'grades:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'grades:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'grades:r:name';
      VAL = S;
      SUSPEND;
    END
  END

  TAG_NAME = 'students::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L10.OBJ_ID, V55.SVAL || ' ' || V56.SVAL || COALESCE(' ' || V57.SVAL, '')
    FROM LINKS L10
    JOIN VALS V55 ON V55.OBJ_ID = L10.OBJ_ID AND V55.PARAM_ID = 55 AND V55.IS_DEL = 0
    JOIN VALS V56 ON V56.OBJ_ID = L10.OBJ_ID AND V56.PARAM_ID = 56 AND V56.IS_DEL = 0
    LEFT JOIN VALS V57 ON V57.OBJ_ID = L10.OBJ_ID AND V57.PARAM_ID = 57 AND V57.IS_DEL = 0
    WHERE L10.PARENT_ID = :I$OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    ORDER BY 2
    INTO :V$OBJ_ID, :S
  DO
  BEGIN
    TAG_NAME = 'students:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'students:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'students:r:name';
    VAL = S;
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_UNDO_LEAVE (
    I$VACANCY_ID BIGINT,
    I$USER_ID VARCHAR(40))
AS
DECLARE VARIABLE TMP BIGINT;
DECLARE VARIABLE V$PERSON_ID BIGINT;
DECLARE VARIABLE V$ID BIGINT;
DECLARE VARIABLE V$JOB_ID BIGINT;
DECLARE VARIABLE V$PLACE_ID BIGINT;
DECLARE VARIABLE V$LINK_ID BIGINT;
DECLARE VARIABLE V$DATE_DEL TIMESTAMP;
DECLARE VARIABLE S VARCHAR(1000);
begin

  -- Есть ли права у пользователя ?
  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  SELECT FIRST 1 LP14.PARENT_ID
  FROM LINKS LP14
  WHERE LP14.OBJ_ID = :I$VACANCY_ID AND LP14.OBJ_TYPE_ID = 15 AND LP14.PARENT_TYPE_ID = 14 AND LP14.DATE_DEL IS NULL
  INTO :V$PERSON_ID;

  IF(V$PERSON_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Недопустимый объект, или назначение на должность было уже удалено';

  -- Найдем приказ, согласно которому прошло увольнение
  SELECT O.OBJ_ID, OD.JOB_ID
  FROM ORDERS O
  JOIN ORDER_DATA OD ON OD.ORDER_ID = O.OBJ_ID AND OD.DATE_DEL IS NULL AND OD.REF_ID = :V$PERSON_ID
  WHERE O.DATE_DEL IS NULL AND O.TYPE_ID = 14257 AND O.STATE_ID = 11715  -- действующий приказ на увольнение
  INTO :V$ID, :V$JOB_ID;

  IF(V$ID IS NOT NULL) THEN
  BEGIN
    -- Отмена увольнения через отмену приказа на увольнение
    FOR
      SELECT VAL FROM ORDER_SET_STATE(:V$ID, 11717, :I$USER_ID) INTO :S  -- недействующий
    DO
    BEGIN
      -- Если увольнение было со всех должностей, то и при отмене увольнения будет отменен приказ, а сотрудник будет восстановлен по всем должностям
    END
  END
  ELSE
  BEGIN
    -- Если приказа на увольнение нет, то отмену увольнения делаем все равно

    -- Восстанавливаем в нужном подразделении, попутно проверяем что оно вообще живо
    -- Сначала находим подразделение
    SELECT FIRST 1 LPG.PARENT_ID
    FROM LINKS LP
    JOIN LINKS LPG ON LPG.OBJ_ID = LP.PARENT_ID AND LPG.PARENT_TYPE_ID IN (2, 211) AND LPG.DATE_DEL IS NULL
    WHERE LP.OBJ_ID = :I$VACANCY_ID AND LP.PARENT_TYPE_ID = 13 AND LP.DATE_DEL IS NULL
    INTO :V$PLACE_ID;

    IF(V$PLACE_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не найдена сама должность, либо подразделение в которой имелась эта должность';

    -- Находим связь с подразделением
    SELECT FIRST 1 L14.LINK_ID, L14.DATE_DEL
    FROM LINKS L14
    WHERE L14.PARENT_ID = :V$PLACE_ID AND L14.OBJ_ID = :V$PERSON_ID
    ORDER BY DATE_DEL NULLS FIRST, 1
    INTO :V$LINK_ID, :V$DATE_DEL;

    IF(V$LINK_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Утрачена связь сотрудника с ОУ или подразделением, требуется ремонт базы';

    -- Восстанавливаем связь, если это требуется
    IF(V$DATE_DEL IS NOT NULL) THEN
    BEGIN
      UPDATE LINKS
      SET DATE_DEL = NULL
      WHERE LINK_ID = :V$LINK_ID;
    END

    -- Очищаем поля, связанные с увольнением - должность становится действующей
    SELECT BLOB_ID FROM VAL_ADD(74, :I$VACANCY_ID, '', :I$USER_ID) INTO :TMP;
    SELECT BLOB_ID FROM VAL_ADD(456, :I$VACANCY_ID, '', :I$USER_ID) INTO :TMP;
    SELECT BLOB_ID FROM VAL_ADD(457, :I$VACANCY_ID, '', :I$USER_ID) INTO :TMP;
    SELECT BLOB_ID FROM VAL_ADD(458, :I$VACANCY_ID, '', :I$USER_ID) INTO :TMP;
    SELECT BLOB_ID FROM VAL_ADD(461, :I$VACANCY_ID, '', :I$USER_ID) INTO :TMP;

    -- Убираем из уволенных
    V$LINK_ID = NULL;
    SELECT FIRST 1 LP84.LINK_ID
    FROM LINKS LP84
    WHERE LP84.OBJ_ID = :V$PERSON_ID AND LP84.PARENT_TYPE_ID = 84 AND LP84.DATE_DEL IS NULL
    INTO :V$LINK_ID;

    IF(V$LINK_ID IS NOT NULL) THEN
    BEGIN
      UPDATE LINKS
      SET DATE_DEL = CURRENT_TIMESTAMP
      WHERE LINK_ID = :V$LINK_ID;
    END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DC_VAL_SET (
    I$OBJ_ID BIGINT,
    I$PARAM_ID BIGINT,
    I$VAL VARCHAR(4000),
    I$USER_ID VARCHAR(40),
    I$IS_DEL SMALLINT = 0,
    I$LINK_ID BIGINT = NULL,
    I$LEVEL_ID BIGINT = NULL)
RETURNS (
    BLOB_ID BIGINT,
    REFRESH_FLAG VARCHAR(100),
    PARAM_TYPE SMALLINT,
    MSGTEXT VARCHAR(4000),
    VAL VARCHAR(4000),
    LISTVAL_ID BIGINT)
AS
DECLARE VARIABLE V$USER_ID BIGINT;
DECLARE VARIABLE V$DY SMALLINT;
DECLARE VARIABLE V$DM SMALLINT;
DECLARE VARIABLE V$DD SMALLINT;
DECLARE VARIABLE V$GEN BIGINT;
DECLARE VARIABLE V$MULT BIGINT;
DECLARE VARIABLE V$DC SMALLINT;
DECLARE VARIABLE V$DCEV SMALLINT;
DECLARE VARIABLE V$OK SMALLINT;
DECLARE VARIABLE V$TYPE_ID BIGINT;
DECLARE VARIABLE V$PARENT_ID BIGINT;
DECLARE VARIABLE N INTEGER;
begin

  IF(I$USER_ID = 'Веб-администратор') THEN V$USER_ID = 1; ELSE V$USER_ID = CAST(I$USER_ID AS BIGINT);

  -- Есть ли доступ к данному параметру в каком-нибудь приложении ?
  -- !!! тут надо ограничить доступ !!!
  SELECT FIRST 1 P.PARAM_TYPE, P.DO_CHECK, P.DO_CHECK_EVENT
  FROM USERS U
  JOIN LUSERS LU ON LU.USER_ID = U.USER_ID AND LU.READ_ONLY = 0
  JOIN LPARAMS LP ON LP.LEVEL_ID = LU.LEVEL_ID AND LP.IS_DEL = 0 AND LP.PARAM_ID = :I$PARAM_ID
  JOIN PARAMS P ON P.PARAM_ID = LP.PARAM_ID AND P.IS_DEL = 0
  WHERE U.USER_ID = :V$USER_ID AND U.DATE_DEL IS NULL AND U.IS_BLOCKED = 0 AND (U.EXP_DATE IS NULL OR U.EXP_DATE > CURRENT_DATE)
  INTO :PARAM_TYPE, :V$DC, :V$DCEV;

  -- Разрешаем сотруднику менять параметры аттестации в своем личном кабинете
  IF(PARAM_TYPE IS NULL) THEN
  BEGIN
    SELECT OBJ.TYPE_ID
    FROM OBJECTS OBJ
    WHERE OBJ.OBJ_ID = :I$OBJ_ID
    INTO :V$TYPE_ID;

    IF(V$TYPE_ID = 458) THEN
    BEGIN
      SELECT LP14.PARENT_ID
      FROM LINKS LP14
      WHERE LP14.OBJ_ID = :I$OBJ_ID AND LP14.PARENT_TYPE_ID = 14 AND LP14.DATE_DEL IS NULL
      INTO :V$PARENT_ID;
    END
    ELSE IF(V$TYPE_ID = 459) THEN
    BEGIN
      SELECT LP14.PARENT_ID
      FROM LINKS LP458
      JOIN LINKS LP14 ON LP14.OBJ_ID = LP458.PARENT_ID AND LP14.PARENT_TYPE_ID = 14 AND LP14.DATE_DEL IS NULL
      WHERE LP458.OBJ_ID = :I$OBJ_ID AND LP458.PARENT_TYPE_ID = 458 AND LP458.DATE_DEL IS NULL
      INTO :V$PARENT_ID;
    END

    -- Совпадает ли сотрудник с нашим текущим пользователем ?
    IF(V$PARENT_ID IS NOT NULL AND EXISTS(
      SELECT FIRST 1 1
      FROM USERS U
      WHERE U.USER_ID = :V$USER_ID AND U.DATE_DEL IS NULL AND U.IS_BLOCKED = 0 AND (U.EXP_DATE IS NULL OR U.EXP_DATE > CURRENT_DATE) AND U.OBJ_ID = :V$PARENT_ID
    ))
    THEN
      SELECT FIRST 1 P.PARAM_TYPE, P.DO_CHECK, P.DO_CHECK_EVENT
      FROM PARAMS P
      WHERE P.PARAM_ID = :I$PARAM_ID
      INTO :PARAM_TYPE, :V$DC, :V$DCEV;
  END

  IF(PARAM_TYPE IS NULL) THEN EXCEPTION DATA_ERROR 'У вас нет доступа для изменения параметра';
  IF(PARAM_TYPE IN (9, 10, 14, 15, 17, 19)) THEN EXCEPTION DATA_ERROR 'Тип параметра не допускает записи значения';

  -- Нельзя редактировать объекты из чужой базы данных
  SELECT GEN, MULTIPLIER
  FROM GEN
  INTO :V$GEN, :V$MULT;

  IF(TRUNC(I$OBJ_ID / V$MULT) <> V$GEN) THEN EXCEPTION DATA_ERROR 'Нельзя изменять объект, созданный в другой базе данных';

  -- Верификация введенного значения
  -- DO_CHECK
  IF(V$DC <> 0 AND I$VAL <> '' AND I$IS_DEL = 0) THEN
  BEGIN
    SELECT IS_OK, MSG
    FROM DO_CHECK(:I$OBJ_ID, :I$PARAM_ID, :I$VAL, :V$DC, :V$DCEV)
    INTO :V$OK, :MSGTEXT;

    IF(V$OK = 0) THEN EXCEPTION DATA_ERROR MSGTEXT;

    --
    SELECT CAN_CHANGE, ERR_MSG
    FROM PARAGRAF_CAN_CHANGE_VAL(:I$OBJ_ID, :I$PARAM_ID, :I$VAL, :I$IS_DEL, :V$USER_ID)
    INTO :V$OK, :MSGTEXT;

    IF(V$OK = 0) THEN EXCEPTION DATA_ERROR MSGTEXT;
  END

  -- При ограниченном доступе - проверить наличие прав доступа к данному конкретному объекту

  -- Корректируем формат для полей даты/времени. Для полей адреса все вообще иначе
  IF(I$VAL IS NOT NULL AND CHAR_LENGTH(I$VAL) > 0) THEN
  BEGIN
      IF(PARAM_TYPE = 3) THEN
      BEGIN
          -- TIMESTAMP
          V$DY = SUBSTRING(I$VAL FROM 1 FOR 4);
          V$DM = SUBSTRING(I$VAL FROM 6 FOR 2);
          V$DD = SUBSTRING(I$VAL FROM 9 FOR 2);
          -- Требуется коррекция таймзоны ?
          I$VAL = V$DD || '.' || V$DM || '.' || V$DY || ' ' || SUBSTRING(I$VAL FROM 12 FOR 8);
      END
      ELSE IF(PARAM_TYPE = 4) THEN
      BEGIN
          -- DATE, достаем формат из ISO
          V$DY = SUBSTRING(I$VAL FROM 1 FOR 4);
          V$DM = SUBSTRING(I$VAL FROM 6 FOR 2);
          V$DD = SUBSTRING(I$VAL FROM 9 FOR 2);
          -- Требуется коррекция таймзоны ?
          IF(CHAR_LENGTH(I$VAL) > 13) THEN N = SUBSTRING(I$VAL FROM 12 FOR 2); ELSE N = 0;
          I$VAL = V$DD || '.' || V$DM || '.' || V$DY;
          IF(N > 12) THEN I$VAL = DATEADD(1 DAY TO CAST(I$VAL AS DATE));
      END
      ELSE IF(PARAM_TYPE = 5) THEN
      BEGIN
          -- TIME - ничего не меняем
      END
      ELSE IF(PARAM_TYPE IN (11, 12)) THEN
      BEGIN
          -- FILE, IMAGE
      END
      -- Поля адреса - сохраняем особо другим методом снаружи
      ELSE IF(PARAM_TYPE = 18) THEN
      BEGIN
          SUSPEND;
          EXIT;
      END
  END

  -- Для параметров 3006, 3007, 3008 в случае документа надо поменять OBJ_ID на родительский
  -- А также если все компоненты ФИО сброшены в <=2 символов, очищаем РегИД и УЛС
  IF(I$PARAM_ID IN (3006, 3007, 3008)) THEN
  BEGIN
    IF(EXISTS(SELECT 1 FROM OBJECTS WHERE OBJ_ID = :I$OBJ_ID AND TYPE_ID = 79)) THEN
    BEGIN
      SELECT FIRST 1 LP.PARENT_ID
      FROM LINKS LP
      WHERE LP.OBJ_ID = :I$OBJ_ID AND LP.PARENT_TYPE_ID IN (10, 14, 20)
      INTO :I$OBJ_ID;
    END

    SELECT COUNT(*)
    FROM VALS
    WHERE OBJ_ID = :I$OBJ_ID AND PARAM_ID IN (55, 56, 57, 59, 60, 61, 128, 129, 130) AND IS_DEL = 0 AND CHAR_LENGTH(VAL) <= 2
    INTO :N;

    IF(N = 3) THEN
    BEGIN
      UPDATE VALS
      SET IS_DEL = 1
      WHERE OBJ_ID = :I$OBJ_ID AND PARAM_ID IN (2912, 2915, 2917, 3482) AND IS_DEL = 0;
      -- Удаляем запись из предупреждений синхронизации по этой персоне
      DELETE FROM SYNC_LOG
      WHERE PERSON_ID = :I$OBJ_ID;
    END
  END

  --Redmine #1113. Ограничения на редактирование полей СНИЛС
  IF (I$PARAM_ID = 51) THEN
  BEGIN
    IF (I$VAL = 1384) THEN
    BEGIN
      --Получим данные персоны
      SELECT FIRST 1 L.PARENT_ID
      FROM LINKS L
      WHERE L.OBJ_ID = :I$OBJ_ID AND L.DATE_DEL IS NULL AND L.PARENT_TYPE_ID IN (10, 14)
      INTO :V$PARENT_ID;

      --Redmine #1113 п. 6 запрещено добавлять более 1 документа с типом снилс в персоне
      IF (EXISTS(
        SELECT FIRST 1 1 FROM LINKS L12
        JOIN VALL V51 ON V51.OBJ_ID = L12.OBJ_ID AND V51.PARAM_ID = 51 AND V51.IS_DEL = 0 AND V51.LISTVAL_ID = 1384
        WHERE L12.OBJ_TYPE_ID = 12 AND L12.DATE_DEL IS NULL AND L12.PARENT_ID = :V$PARENT_ID
      )) THEN
      BEGIN
        EXCEPTION DATA_ERROR 'Нельзя добавить более одного документа СНИЛС к персоне';
      END
    END
    ELSE IF (I$VAL IS NULL OR CHAR_LENGTH(I$VAL) > 0) THEN
    BEGIN
      --Redmine #1113 п. 8. Запретить изменение типа документа, если внесен номер
      IF (EXISTS(
        SELECT FIRST 1 1
        FROM VALL V51
        WHERE V51.OBJ_ID = :I$OBJ_ID AND V51.PARAM_ID = 51 AND V51.IS_DEL = 0 AND V51.LISTVAL_ID = 1384
      )) THEN
      BEGIN
        EXCEPTION DATA_ERROR 'Нельзя изменять тип документа, если внесен его номер';
      END
    END
  END
  --Redmine #1113 п. 8. Запретить ввод номера документа (тип 12), если не внесен тип, а также п. 5 - запретить вводить номер СНИЛС в документе сотрудника/обучающегося
  ELSE IF (I$PARAM_ID = 571 AND CHAR_LENGTH(I$VAL) > 0) THEN
  BEGIN
    V$TYPE_ID = NULL;
    SELECT FIRST 1 V51.LISTVAL_ID
    FROM VALL V51
    WHERE V51.OBJ_ID = :I$OBJ_ID AND V51.PARAM_ID = 51 AND V51.IS_DEL = 0
    INTO :V$TYPE_ID;

    IF (V$TYPE_ID IS NULL) THEN
    BEGIN
      EXCEPTION DATA_ERROR 'Необходимо сначала задать тип документа';
    END
    ELSE IF (V$TYPE_ID = 1384) THEN
    BEGIN
      EXCEPTION DATA_ERROR 'Номер СНИЛС необходимо вводить в личном деле сотрудника/обучающегося';
    END
  END

  SELECT BLOB_ID, REFRESH_FLAG
  FROM VAL_ADD(:I$PARAM_ID, :I$OBJ_ID, :I$VAL, :V$USER_ID, :I$IS_DEL, 1, :I$LINK_ID)
  INTO :BLOB_ID, :REFRESH_FLAG;

  -- Достаем изменившееся значение для возврата на фронт
  IF(I$IS_DEL = 0 AND I$VAL IS NOT NULL AND I$VAL <> '') THEN
  BEGIN
    IF(I$LINK_ID IS NULL) THEN
    BEGIN
      SELECT V.V, V.I
      FROM VAL_GET(:I$OBJ_ID, :I$PARAM_ID) V
      WHERE V.IS_EXISTS = 1
      INTO :VAL, :LISTVAL_ID;
    END
    ELSE
    BEGIN
      SELECT P.TYPE_ID
      FROM PARAMS P
      WHERE P.PARAM_ID = :I$PARAM_ID
      INTO :V$TYPE_ID;

      SELECT V.V, V.I
      FROM LINKS L
      LEFT JOIN VAL_GET(IIF(L.OBJ_TYPE_ID = :V$TYPE_ID, L.OBJ_ID, L.EXT_OBJ_ID), :I$PARAM_ID) V ON 1 = 1
      WHERE L.LINK_ID = :I$LINK_ID AND (L.OBJ_ID = :I$OBJ_ID OR L.EXT_OBJ_ID = :I$OBJ_ID) AND V.IS_EXISTS = 1
      INTO :VAL, :LISTVAL_ID;
    END
  END

  SUSPEND;
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DELETE_STAY_DOCUMENTS (
    I$PUPIL_ID BIGINT)
AS
declare variable V$DOC_ID bigint;
declare variable TMP integer;
begin

  FOR
      SELECT L293.OBJ_ID
      FROM LINKS L293
      WHERE L293.PARENT_ID = :I$PUPIL_ID AND L293.OBJ_TYPE_ID = 293 AND L293.DATE_DEL IS NULL
      INTO :V$DOC_ID
  DO
  BEGIN
      SELECT DEL_COUNT FROM OBJECT_DEL(:I$PUPIL_ID, :V$DOC_ID) INTO :TMP;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DG_FOODEVENTS_LAST_ID RETURNS (
    LAST_ID BIGINT)
AS
begin
  SELECT MAX(EVENT_ID) FROM SOP_RAW INTO :LAST_ID;
  IF(LAST_ID IS NULL) THEN LAST_ID = 0;
  SUSPEND;
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DG_FOOD_BENEFITS (
    DATE_START TIMESTAMP,
    DATE_END TIMESTAMP,
    MODE SMALLINT = 0)
RETURNS (
    TAG_NAME VARCHAR(255),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE SCHOOL_ID BIGINT;
DECLARE VARIABLE PFX VARCHAR(20);
DECLARE VARIABLE CLASS_ID BIGINT;
DECLARE VARIABLE CLASS_TYPE BIGINT;
DECLARE VARIABLE OBJ_ID BIGINT;
DECLARE VARIABLE PERSON_NAME1 VARCHAR(500);
DECLARE VARIABLE PERSON_NAME2 VARCHAR(500);
DECLARE VARIABLE PERSON_NAME3 VARCHAR(500);
DECLARE VARIABLE PERSON_DATE DATE;
DECLARE VARIABLE BENEFIT_CODE INTEGER;
DECLARE VARIABLE BENEFIT_DATE_START DATE;
DECLARE VARIABLE BENEFIT_DATE_END DATE;
DECLARE VARIABLE LAST_MOVE_DATE DATE;
DECLARE VARIABLE PORTAL_DATE DATE;
DECLARE VARIABLE CARD_ID VARCHAR(100);
DECLARE VARIABLE FORCED_EXPORT BIGINT;
DECLARE VARIABLE EVENT_TYPE VARCHAR(100);
DECLARE VARIABLE P INTEGER;
DECLARE VARIABLE L10_D_INS TIMESTAMP;
DECLARE VARIABLE L10_D_CHANGE TIMESTAMP;
DECLARE VARIABLE V55_CHANGE TIMESTAMP;
DECLARE VARIABLE V56_CHANGE TIMESTAMP;
DECLARE VARIABLE V57_CHANGE TIMESTAMP;
DECLARE VARIABLE V89_CHANGE TIMESTAMP;
DECLARE VARIABLE V2855_CHANGE TIMESTAMP;
DECLARE VARIABLE V2091_CHANGE TIMESTAMP;
DECLARE VARIABLE V2088_CHANGE TIMESTAMP;
DECLARE VARIABLE V2092_CHANGE TIMESTAMP;
DECLARE VARIABLE THIS_YEAR TIMESTAMP;
DECLARE VARIABLE REG_ID VARCHAR(100);
DECLARE VARIABLE LAST_LEAVE_DATE DATE;
DECLARE VARIABLE SNILS VARCHAR(40);
DECLARE VARIABLE SNILS_CHANGE TIMESTAMP;
DECLARE VARIABLE V$OVZ BIGINT;
DECLARE VARIABLE V$RKDT TIMESTAMP;
DECLARE VARIABLE ULS VARCHAR(100);
DECLARE VARIABLE V$ULSDT TIMESTAMP;
begin
  -- MODE определяет режим экспорта:
  -- 0 = для mealbenefits (СКУД, SOAP) - полная выгрузка всех, без поля bdate и списка событий, для не-учеников без даты рождения, без выбывших
  -- 1 = для food_benefits (оплата питания, JSON) - инкрементальная, полный набор полей + всегда добавляем DATA
  -- 2 = для food_benefits_full (оплата питания, SOAP) - инкрементальная, с уровня района по всем ОУ

  IF(EXTRACT(MONTH FROM CURRENT_DATE) < 9) THEN THIS_YEAR = '01.09.' || (EXTRACT(MONTH FROM CURRENT_DATE) - 1);
  ELSE THIS_YEAR = '01.09.' || EXTRACT(MONTH FROM CURRENT_DATE);

  IF(MODE = 2) THEN PFX = 'school:pupils:'; ELSE PFX = '';

  -- Цикл по ОУ (реально только для MODE = 2)
  FOR
    SELECT L2.OBJ_ID
    FROM LINKS L2
    WHERE L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND (L2.PARENT_ID IS NULL OR L2.PARENT_TYPE_ID = 111)
    INTO :SCHOOL_ID
  DO
  BEGIN

  -- При полной выгрузке формируем уровень вложения школы и выдаем ее id
  IF(MODE = 2) THEN
  BEGIN
      TAG_NAME = 'school';
      VAL = NULL;
      SUSPEND;

      TAG_NAME = 'school:school_id';
      VAL = SCHOOL_ID;
      SUSPEND;

      TAG_NAME = 'school:pupils';
      VAL = NULL;
      SUSPEND;
  END

  -- Учащиеся (актуальные) и предварительный прием
  FOR
      SELECT L10.PARENT_ID, L10.PARENT_TYPE_ID, L10.OBJ_ID, V55.SVAL, V56.SVAL, V57.SVAL, V89.VAL,
        LV2091.COST, V2088.VAL, V2092.VAL, CAST(V2855.VAL AS VARCHAR(100)), V2899.LISTVAL_ID, CAST(VG.VAL AS VARCHAR(100)), CAST(VU.VAL AS VARCHAR(100)),
        L10.DATE_INS, L10.DATE_MODIFY, V55.DATE_MODIFY, V56.DATE_MODIFY, V57.DATE_MODIFY, V89.DATE_MODIFY,
        V2855.DATE_MODIFY, V2091.DATE_MODIFY, V2088.DATE_MODIFY, V2092.DATE_MODIFY,
        VS.SVAL, VS.DATE_MODIFY, V592.LISTVAL_ID, VG.DATE_MODIFY, VU.DATE_MODIFY
      FROM LINKS L7
      JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 125, 187) AND L9.DATE_DEL IS NULL
      LEFT JOIN VALL V592 ON V592.OBJ_ID = L9.OBJ_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0
      JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      -- Фамилия
      JOIN VALS V55 ON V55.OBJ_ID = L10.OBJ_ID AND V55.PARAM_ID = 55 AND V55.IS_DEL = 0
      -- Имя
      JOIN VALS V56 ON V56.OBJ_ID = L10.OBJ_ID AND V56.PARAM_ID = 56 AND V56.IS_DEL = 0
      -- Отчество - опционально
      LEFT JOIN VALS V57 ON V57.OBJ_ID = L10.OBJ_ID AND V57.PARAM_ID = 57 AND V57.IS_DEL = 0
      -- Дата рождения
      LEFT JOIN VALD V89 ON V89.OBJ_ID = L10.OBJ_ID AND V89.PARAM_ID = 89 AND V89.IS_DEL = 0
      -- Подтвержденная льгота - название и код
      LEFT JOIN VALL V2091 ON V2091.OBJ_ID = L10.OBJ_ID AND V2091.PARAM_ID = 2091 AND V2091.IS_DEL = 0
      LEFT JOIN LISTVALS LV2091 ON LV2091.LISTVAL_ID = V2091.LISTVAL_ID
      -- Дата получения ответа по льготе
      LEFT JOIN VALD V2088 ON V2088.OBJ_ID = L10.OBJ_ID AND V2088.PARAM_ID = 2088 AND V2088.IS_DEL = 0
      -- Дата окончания льготы
      LEFT JOIN VALD V2092 ON V2092.OBJ_ID = L10.OBJ_ID AND V2092.PARAM_ID = 2092 AND V2092.IS_DEL = 0
      -- ID карты
      LEFT JOIN VALS V2855 ON V2855.OBJ_ID = L10.OBJ_ID AND V2855.PARAM_ID = 2855 AND V2855.IS_DEL = 0
      -- Принудительная выгрузка
      LEFT JOIN VALL V2899 ON V2899.OBJ_ID = L10.OBJ_ID AND V2899.PARAM_ID = 2899 AND V2899.IS_DEL = 0
      -- RegID
      LEFT JOIN VALS VG ON VG.OBJ_ID = L10.OBJ_ID AND VG.PARAM_ID = 2912 AND VG.IS_DEL = 0
      -- СНИЛС
      LEFT JOIN VALS VS ON VS.OBJ_ID = L10.OBJ_ID AND VS.PARAM_ID = 1409 AND VS.IS_DEL = 0
      -- УЛС
      LEFT JOIN VALS VU ON VU.OBJ_ID = L10.OBJ_ID AND VU.PARAM_ID = 3482 AND VU.IS_DEL = 0
      WHERE L7.PARENT_ID = :SCHOOL_ID AND L7.OBJ_TYPE_ID IN (7, 502) AND L7.DATE_DEL IS NULL
      UNION
      SELECT L10.PARENT_ID, L10.PARENT_TYPE_ID, L10.OBJ_ID, V55.SVAL, V56.SVAL, V57.SVAL, V89.VAL,
        LV2091.COST, V2088.VAL, V2092.VAL, CAST(V2855.VAL AS VARCHAR(100)), V2899.LISTVAL_ID, CAST(VG.VAL AS VARCHAR(100)), CAST(VU.VAL AS VARCHAR(100)),
        L10.DATE_INS, L10.DATE_MODIFY, V55.DATE_MODIFY, V56.DATE_MODIFY, V57.DATE_MODIFY, V89.DATE_MODIFY,
        V2855.DATE_MODIFY, V2091.DATE_MODIFY, V2088.DATE_MODIFY, V2092.DATE_MODIFY,
        VS.SVAL, VS.DATE_MODIFY, IIF(V2346.LISTVAL_ID > 48, 13275, 0), VG.DATE_MODIFY, VU.DATE_MODIFY
      FROM LINKS L77
      JOIN LINKS L290 ON L290.PARENT_ID = L77.OBJ_ID AND L290.OBJ_TYPE_ID = 290 AND L290.DATE_DEL IS NULL
      LEFT JOIN VALL V2346 ON V2346.OBJ_ID = L290.OBJ_ID AND V2346.PARAM_ID = 2346 AND V2346.IS_DEL = 0
      JOIN LINKS L10 ON L10.PARENT_ID = L290.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      -- Фамилия
      JOIN VALS V55 ON V55.OBJ_ID = L10.OBJ_ID AND V55.PARAM_ID = 55 AND V55.IS_DEL = 0
      -- Имя
      JOIN VALS V56 ON V56.OBJ_ID = L10.OBJ_ID AND V56.PARAM_ID = 56 AND V56.IS_DEL = 0
      -- Отчество - опционально
      LEFT JOIN VALS V57 ON V57.OBJ_ID = L10.OBJ_ID AND V57.PARAM_ID = 57 AND V57.IS_DEL = 0
      -- Дата рождения
      LEFT JOIN VALD V89 ON V89.OBJ_ID = L10.OBJ_ID AND V89.PARAM_ID = 89 AND V89.IS_DEL = 0
      -- Подтвержденная льгота - название и код
      LEFT JOIN VALL V2091 ON V2091.OBJ_ID = L10.OBJ_ID AND V2091.PARAM_ID = 2091 AND V2091.IS_DEL = 0
      LEFT JOIN LISTVALS LV2091 ON LV2091.LISTVAL_ID = V2091.LISTVAL_ID
      -- Дата получения ответа по льготе
      LEFT JOIN VALD V2088 ON V2088.OBJ_ID = L10.OBJ_ID AND V2088.PARAM_ID = 2088 AND V2088.IS_DEL = 0
      -- Дата окончания льготы
      LEFT JOIN VALD V2092 ON V2092.OBJ_ID = L10.OBJ_ID AND V2092.PARAM_ID = 2092 AND V2092.IS_DEL = 0
      -- ID карты
      LEFT JOIN VALS V2855 ON V2855.OBJ_ID = L10.OBJ_ID AND V2855.PARAM_ID = 2855 AND V2855.IS_DEL = 0
      -- Принудительная выгрузка
      LEFT JOIN VALL V2899 ON V2899.OBJ_ID = L10.OBJ_ID AND V2899.PARAM_ID = 2899 AND V2899.IS_DEL = 0
      -- RegID - обязательное поле, без регид предварительный прием не выгружаем
      JOIN VALS VG ON VG.OBJ_ID = L10.OBJ_ID AND VG.PARAM_ID = 2912 AND VG.IS_DEL = 0
      -- СНИЛС
      LEFT JOIN VALS VS ON VS.OBJ_ID = L10.OBJ_ID AND VS.PARAM_ID = 1409 AND VS.IS_DEL = 0
      -- УЛС
      LEFT JOIN VALS VU ON VU.OBJ_ID = L10.OBJ_ID AND VU.PARAM_ID = 3482 AND VU.IS_DEL = 0
      WHERE L77.PARENT_ID = :SCHOOL_ID AND L77.OBJ_TYPE_ID = 77 AND L77.DATE_DEL IS NULL
      ORDER BY 14 -- L10.DATE_INS
      INTO :CLASS_ID, :CLASS_TYPE, :OBJ_ID, :PERSON_NAME1, :PERSON_NAME2, :PERSON_NAME3, :PERSON_DATE,
        :BENEFIT_CODE, :BENEFIT_DATE_START, :BENEFIT_DATE_END, :CARD_ID, :FORCED_EXPORT, :REG_ID, :ULS,
        :L10_D_INS, :L10_D_CHANGE, :V55_CHANGE, :V56_CHANGE, :V57_CHANGE, :V89_CHANGE,
        :V2855_CHANGE, :V2091_CHANGE, :V2088_CHANGE, :V2092_CHANGE,
        :SNILS, :SNILS_CHANGE, :V$OVZ, :V$RKDT, :V$ULSDT
  DO
  BEGIN

      EVENT_TYPE = '';

      -- Дата последнего движения ученика в классе (раз он еще там, то это не выбытие)
      SELECT MAX(M.DATE_IN)
      FROM PERSON_MOVEMENTS M
      JOIN OBJECTS O ON O.OBJ_ID = M.GROUP_ID AND O.TYPE_ID IN (9, 125, 187)
      WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :OBJ_ID
      INTO :LAST_MOVE_DATE;

      -- Дата регистрации на Портале, берем младшую по всем представителям
      SELECT MIN(IIF(V1.DATE_MODIFY <= V2.DATE_MODIFY, V1.DATE_MODIFY, V2.DATE_MODIFY))
      FROM LINKS L
      JOIN VALS V1 ON V1.OBJ_ID = L.EXT_OBJ_ID AND V1.PARAM_ID = 1570 AND V1.IS_DEL = 0
      JOIN VALS V2 ON V2.OBJ_ID = L.OBJ_ID AND V2.PARAM_ID = 155 AND V2.IS_DEL = 0
      WHERE L.PARENT_ID = :OBJ_ID AND L.OBJ_TYPE_ID = 20 AND L.DATE_DEL IS NULL
      INTO :PORTAL_DATE;

      IF(FORCED_EXPORT = 2 OR DATE_START IS NULL OR LAST_MOVE_DATE >= DATE_START OR L10_D_INS >= DATE_START OR L10_D_CHANGE >= DATE_START OR V2855_CHANGE >= DATE_START) THEN
          EVENT_TYPE = EVENT_TYPE || 'IN,';

      -- На всякий случай добавляем DATA для полной выгрузки
      IF(DATE_START IS NULL OR V55_CHANGE >= DATE_START OR V56_CHANGE >= DATE_START OR V57_CHANGE >= DATE_START OR V89_CHANGE >= DATE_START OR SNILS_CHANGE >= DATE_START
          OR V$RKDT >= DATE_START OR V$ULSDT >= DATE_START)
      THEN
          EVENT_TYPE = EVENT_TYPE || 'DATA,';

      IF(V2091_CHANGE >= DATE_START OR V2088_CHANGE >= DATE_START OR V2092_CHANGE >= DATE_START) THEN
          EVENT_TYPE = EVENT_TYPE || 'BENEFIT,';

      IF(EVENT_TYPE <> '') THEN
      BEGIN

          TAG_NAME = PFX || 'pupil';
          VAL = NULL;
          SUSPEND;

          TAG_NAME = PFX || 'pupil:suid';
          VAL = OBJ_ID;
          SUSPEND;

          -- Подчищаем введенный ID карты от левых символов
          CARD_ID = REPLACE(CARD_ID, ' ', '');
          CARD_ID = REPLACE(CARD_ID, '-', '');
          CARD_ID = REPLACE(CARD_ID, '.', '');
          TAG_NAME = PFX || 'pupil:card_id';
          VAL = CARD_ID;
          SUSPEND;

          TAG_NAME = PFX || 'pupil:surname';
          VAL = PERSON_NAME1;
          SUSPEND;

          TAG_NAME = PFX || 'pupil:name';
          VAL = PERSON_NAME2;
          SUSPEND;

          TAG_NAME = PFX || 'pupil:patronymic';
          VAL = COALESCE(PERSON_NAME3, '');
          SUSPEND;

          TAG_NAME = PFX || 'pupil:class';
          VAL = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:CLASS_ID));
          SUSPEND;

          TAG_NAME = PFX || 'pupil:class_type';
          VAL = CLASS_TYPE;
          SUSPEND;

          TAG_NAME = PFX || 'pupil:person_type';
          VAL = 10;
          SUSPEND;

          TAG_NAME = PFX || 'pupil:class_ovz';
          VAL = IIF(V$OVZ = 13275, '1', '0');
          SUSPEND;

          TAG_NAME = PFX || 'pupil:dob';
          VAL = (SELECT VAL FROM DATE2ISO(:PERSON_DATE, 0));
          SUSPEND;

          TAG_NAME = PFX || 'pupil:snils';
          VAL = COALESCE(SNILS, '');
          SUSPEND;

          TAG_NAME = PFX || 'pupil:reg_id';
          IF(POSITION(':' IN REG_ID) > 0) THEN REG_ID = SUBSTRING(REG_ID FROM 1 FOR POSITION(':' IN REG_ID) - 1);
          VAL = REG_ID;
          SUSPEND;

          TAG_NAME = PFX || 'pupil:uls';
          VAL = COALESCE(ULS, '');
          SUSPEND;

          IF(MODE IN (1, 2)) THEN
          BEGIN
              TAG_NAME = PFX || 'pupil:portal';
              VAL = COALESCE((SELECT VAL FROM DATE2ISO(:PORTAL_DATE, 0)), '');
              SUSPEND;

              TAG_NAME = PFX || 'pupil:accept_date';
              VAL = COALESCE((SELECT VAL FROM DATE2ISO(:LAST_MOVE_DATE, 0)), '');
              SUSPEND;

              TAG_NAME = PFX || 'pupil:leave_date';
              VAL = NULL;
              SUSPEND;

              TAG_NAME = PFX || 'pupil:event';
              VAL = NULL;
              SUSPEND;

              IF(MODE = 1) THEN
              BEGIN
                TAG_NAME = PFX || 'pupil:event::json&colon;array';
                VAL = '1';
                SUSPEND;
              END

              WHILE(EVENT_TYPE <> '') DO
              BEGIN
                  P = POSITION(',' IN EVENT_TYPE);
                  IF(P = 0) THEN P = CHARACTER_LENGTH(EVENT_TYPE) + 1;

                  TAG_NAME = PFX || 'pupil:event:directionType';
                  VAL = SUBSTRING(EVENT_TYPE FROM 1 FOR P - 1);
                  SUSPEND;

                  EVENT_TYPE = SUBSTRING(EVENT_TYPE FROM P + 1);
              END
          END

          TAG_NAME = PFX || 'pupil:benefit';
          VAL = NULL;
          SUSPEND;

          TAG_NAME = PFX || 'pupil:benefit:code';
          VAL = COALESCE(BENEFIT_CODE, '');
          SUSPEND;

          TAG_NAME = PFX || 'pupil:benefit:adate';
          VAL = COALESCE((SELECT RESULT FROM DATE2STR(:BENEFIT_DATE_START)), '');
          SUSPEND;

          IF(MODE IN (1, 2)) THEN
          BEGIN
              TAG_NAME = PFX || 'pupil:benefit:bdate';
              VAL = COALESCE((SELECT RESULT FROM DATE2STR(:BENEFIT_DATE_END)), '');
              SUSPEND;
          END

      END

      -- Гасим флаг принудительной выгрузки
      IF(FORCED_EXPORT = 2) THEN
      BEGIN
          SELECT BLOB_ID from VAL_ADD(2899, :OBJ_ID, 3) INTO :FORCED_EXPORT;
      END

  END

  -- Покинувшие школу ученики (записи с изменениями позднее указанной даты)
  -- Выбывших берем только в текущем учебном году
  -- Если у ребенка есть действующая инкарнация с таким же guid, не выдаем выбытие по его плохой копии
  FOR
      SELECT L10.PARENT_TYPE_ID, L10.OBJ_ID, V55.SVAL, V56.SVAL, V57.SVAL, V89.VAL, CAST(V2855.VAL AS VARCHAR(100)), V2899.LISTVAL_ID, CAST(VG.VAL AS VARCHAR(100)), VS.SVAL,
        CAST(VU.VAL AS VARCHAR(100))
      FROM LINKS L78
      JOIN LINKS L8X ON L8X.PARENT_ID = L78.OBJ_ID AND L8X.OBJ_TYPE_ID IN (81, 82, 83) AND L8X.DATE_DEL IS NULL
      JOIN LINKS L10 ON L10.PARENT_ID = L8X.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      -- Фамилия
      JOIN VALS V55 ON V55.OBJ_ID = L10.OBJ_ID AND V55.PARAM_ID = 55 AND V55.IS_DEL = 0
      -- Имя
      JOIN VALS V56 ON V56.OBJ_ID = L10.OBJ_ID AND V56.PARAM_ID = 56 AND V56.IS_DEL = 0
      -- Отчество - опционально
      LEFT JOIN VALS V57 ON V57.OBJ_ID = L10.OBJ_ID AND V57.PARAM_ID = 57 AND V57.IS_DEL = 0
      -- Дата рождения
      LEFT JOIN VALD V89 ON V89.OBJ_ID = L10.OBJ_ID AND V89.PARAM_ID = 89 AND V89.IS_DEL = 0
      -- ID карты
      LEFT JOIN VALS V2855 ON V2855.OBJ_ID = L10.OBJ_ID AND V2855.PARAM_ID = 2855 AND V2855.IS_DEL = 0
      -- Принудительная выгрузка
      LEFT JOIN VALL V2899 ON V2899.OBJ_ID = L10.OBJ_ID AND V2899.PARAM_ID = 2899 AND V2899.IS_DEL = 0
      -- RegID
      LEFT JOIN VALS VG ON VG.OBJ_ID = L10.OBJ_ID AND VG.PARAM_ID = 2912 AND VG.IS_DEL = 0
      -- СНИЛС
      LEFT JOIN VALS VS ON VS.OBJ_ID = L10.OBJ_ID AND VS.PARAM_ID = 1409 AND VS.IS_DEL = 0
      -- УЛС
      LEFT JOIN VALS VU ON VU.OBJ_ID = L10.OBJ_ID AND VU.PARAM_ID = 3482 AND VU.IS_DEL = 0
      WHERE L78.PARENT_ID = :SCHOOL_ID AND L78.OBJ_TYPE_ID = 78 AND L78.DATE_DEL IS NULL
        AND (L10.DATE_INS >= DATEADD(-4 MONTH TO :THIS_YEAR))
        AND (:DATE_START IS NULL OR L10.DATE_INS >= :DATE_START OR L10.DATE_MODIFY >= :DATE_START OR V2899.LISTVAL_ID = 2)
        -- для СКУД не нужно
        AND (:MODE <> 0)
      INTO :CLASS_TYPE, :OBJ_ID, :PERSON_NAME1, :PERSON_NAME2, :PERSON_NAME3, :PERSON_DATE, :CARD_ID, :FORCED_EXPORT, :REG_ID, :SNILS, :ULS
  DO
  BEGIN

      EVENT_TYPE = 'OUT';

      -- Клон ученика ?
      IF(REG_ID <> '') THEN
      BEGIN
          IF(EXISTS(
              SELECT FIRST 1 1
              FROM LINKS L7
              JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
              JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 125, 187) AND L9.DATE_DEL IS NULL
              JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
              JOIN VALS V55 ON V55.OBJ_ID = L10.OBJ_ID AND V55.PARAM_ID = 55 AND V55.IS_DEL = 0
              JOIN VALS V56 ON V56.OBJ_ID = L10.OBJ_ID AND V56.PARAM_ID = 56 AND V56.IS_DEL = 0
              JOIN VALS VG ON VG.OBJ_ID = L10.OBJ_ID AND VG.PARAM_ID = 2912 AND VG.IS_DEL = 0 AND VG.VAL = :REG_ID
              WHERE L7.PARENT_ID = :SCHOOL_ID AND L7.OBJ_TYPE_ID IN (7, 502) AND L7.DATE_DEL IS NULL
          )) THEN EVENT_TYPE = '';
      END

      -- Экстернат ? Если записи и в экстернате, и в выбытии
      IF(EVENT_TYPE <> '') THEN
      BEGIN
          IF(EXISTS(
              SELECT FIRST 1 1
              FROM LINKS L10
              WHERE L10.OBJ_ID = :OBJ_ID AND L10.PARENT_TYPE_ID IN (9, 125, 46) AND L10.DATE_DEL IS NULL
          )) THEN EVENT_TYPE = '';
      END

      IF(EVENT_TYPE <> '') THEN
      BEGIN

          TAG_NAME = PFX || 'pupil';
          VAL = NULL;
          SUSPEND;

          TAG_NAME = PFX || 'pupil:suid';
          VAL = OBJ_ID;
          SUSPEND;

          -- Подчищаем введенный ID карты от левых символов
          CARD_ID = REPLACE(CARD_ID, ' ', '');
          CARD_ID = REPLACE(CARD_ID, '-', '');
          CARD_ID = REPLACE(CARD_ID, '.', '');
          TAG_NAME = PFX || 'pupil:card_id';
          VAL = CARD_ID;
          SUSPEND;

          TAG_NAME = PFX || 'pupil:surname';
          VAL = PERSON_NAME1;
          SUSPEND;

          TAG_NAME = PFX || 'pupil:name';
          VAL = PERSON_NAME2;
          SUSPEND;

          TAG_NAME = PFX || 'pupil:patronymic';
          VAL = COALESCE(PERSON_NAME3, '');
          SUSPEND;

          TAG_NAME = PFX || 'pupil:class';
          VAL = '';
          SUSPEND;

          TAG_NAME = PFX || 'pupil:class_type';
          VAL = CLASS_TYPE;
          SUSPEND;

          TAG_NAME = PFX || 'pupil:person_type';
          VAL = 10;
          SUSPEND;

          TAG_NAME = PFX || 'pupil:dob';
          VAL = (SELECT VAL FROM DATE2ISO(:PERSON_DATE, 0));
          SUSPEND;

          TAG_NAME = PFX || 'pupil:snils';
          VAL = COALESCE(SNILS, '');
          SUSPEND;

          TAG_NAME = PFX || 'pupil:reg_id';
          IF(POSITION(':' IN REG_ID) > 0) THEN REG_ID = SUBSTRING(REG_ID FROM 1 FOR POSITION(':' IN REG_ID) - 1);
          VAL = REG_ID;
          SUSPEND;

          TAG_NAME = PFX || 'pupil:uls';
          VAL = COALESCE(ULS, '');
          SUSPEND;

          IF(MODE IN (1, 2)) THEN
          BEGIN

              -- Дата выбытия
              SELECT MAX(M.DATE_OUT)
              FROM PERSON_MOVEMENTS M
              JOIN OBJECTS O ON O.OBJ_ID = M.GROUP_ID AND O.TYPE_ID IN (9, 125, 187)
              WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :OBJ_ID
              INTO :LAST_LEAVE_DATE;

              TAG_NAME = PFX || 'pupil:leave_date';
              VAL = (SELECT VAL FROM DATE2ISO(:LAST_LEAVE_DATE, 0));
              SUSPEND;

              TAG_NAME = PFX || 'pupil:event';
              VAL = NULL;
              SUSPEND;

              IF(MODE = 1) THEN
              BEGIN
                TAG_NAME = PFX || 'pupil:event::json&colon;array';
                VAL = '1';
                SUSPEND;
              END

              TAG_NAME = PFX || 'pupil:event:directionType';
              VAL = EVENT_TYPE;
              SUSPEND;
          END

      END

      -- Гасим флаг принудительной выгрузки
      IF(FORCED_EXPORT = 2) THEN
      BEGIN
          SELECT BLOB_ID FROM VAL_ADD(2899, :OBJ_ID, 3) INTO :FORCED_EXPORT;
      END

  END

  -- Представители детей
  FOR
      SELECT DISTINCT L20.OBJ_ID, CAST(V128.VAL AS VARCHAR(400)), CAST(V129.VAL AS VARCHAR(400)), CAST(V130.VAL AS VARCHAR(400)), V143.VAL, VS.SVAL
      FROM LINKS L7
      JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 125, 187) AND L9.DATE_DEL IS NULL
      JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      JOIN LINKS L20 ON L20.PARENT_ID = L10.OBJ_ID AND L20.OBJ_TYPE_ID = 20 AND L10.DATE_DEL IS NULL
      -- Отмеченных как постоянные сопровождающие
      JOIN VALL V2818 on V2818.OBJ_ID = L20.OBJ_ID and V2818.PARAM_ID = 2818 and V2818.IS_DEL = 0 and V2818.LISTVAL_ID = 2
      -- Фамилия
      JOIN VALS V128 ON V128.OBJ_ID = L20.OBJ_ID AND V128.PARAM_ID = 128 AND V128.IS_DEL = 0
      -- Имя
      JOIN VALS V129 ON V129.OBJ_ID = L20.OBJ_ID AND V129.PARAM_ID = 129 AND V129.IS_DEL = 0
      -- Отчество - опционально
      LEFT JOIN VALS V130 ON V130.OBJ_ID = L20.OBJ_ID AND V130.PARAM_ID = 130 AND V130.IS_DEL = 0
      -- Дата рождения
      LEFT JOIN VALD V143 ON V143.OBJ_ID = L20.OBJ_ID AND V143.PARAM_ID = 143 AND V143.IS_DEL = 0
      -- СНИЛС
      LEFT JOIN VALS VS ON VS.OBJ_ID = L20.OBJ_ID AND VS.PARAM_ID = 2365 AND VS.IS_DEL = 0
      WHERE L7.PARENT_ID = :SCHOOL_ID AND L7.OBJ_TYPE_ID IN (7, 502) AND L7.DATE_DEL IS NULL
          AND (:DATE_START IS NULL OR L20.DATE_INS >= :DATE_START OR L20.DATE_MODIFY >= :DATE_START OR
            V128.DATE_MODIFY >= :DATE_START OR V129.DATE_MODIFY >= :DATE_START OR V130.DATE_MODIFY >= :DATE_START OR V143.DATE_MODIFY >= :DATE_START OR VS.DATE_MODIFY >= :DATE_START
          )
      INTO :OBJ_ID, :PERSON_NAME1, :PERSON_NAME2, :PERSON_NAME3, :PERSON_DATE, :SNILS
  DO
  BEGIN

      -- RegID
      REG_ID = NULL;
      SELECT VG.VAL
      FROM VALS VG
      WHERE VG.OBJ_ID = :OBJ_ID AND VG.PARAM_ID = 2917 AND VG.IS_DEL = 0
      INTO :REG_ID;

      -- ID карты
      CARD_ID = NULL;
      SELECT V2918.VAL
      FROM VALS V2918
      WHERE V2918.OBJ_ID = :OBJ_ID AND V2918.PARAM_ID = 2918 AND V2918.IS_DEL = 0
      INTO :CARD_ID;

      -- Есть ли изменения в текущих связях с учениками, или это изменились ФИО/дата ?
      P = 0;
      SELECT FIRST 1 1
      FROM LINKS LP10
      JOIN LINKS LPC ON LPC.OBJ_ID = LP10.PARENT_ID AND LPC.PARENT_TYPE_ID IN (9, 125, 187) AND LPC.DATE_DEL IS NULL
      WHERE LP10.OBJ_ID = :OBJ_ID AND LP10.PARENT_TYPE_ID = 10 AND LP10.DATE_DEL IS NULL AND LP10.DATE_MODIFY >= :DATE_START
      INTO :P;

      IF(P = 1) THEN EVENT_TYPE = 'IN'; ELSE EVENT_TYPE = 'DATA';

      IF(EVENT_TYPE <> '') THEN
      BEGIN

          TAG_NAME = PFX || 'pupil';
          VAL = NULL;
          SUSPEND;

          TAG_NAME = PFX || 'pupil:suid';
          VAL = OBJ_ID;
          SUSPEND;

          -- Подчищаем введенный ID карты от левых символов
          CARD_ID = REPLACE(CARD_ID, ' ', '');
          CARD_ID = REPLACE(CARD_ID, '-', '');
          CARD_ID = REPLACE(CARD_ID, '.', '');
          TAG_NAME = PFX || 'pupil:card_id';
          VAL = CARD_ID;
          SUSPEND;

          TAG_NAME = PFX || 'pupil:surname';
          VAL = PERSON_NAME1;
          SUSPEND;

          TAG_NAME = PFX || 'pupil:name';
          VAL = PERSON_NAME2;
          SUSPEND;

          TAG_NAME = PFX || 'pupil:patronymic';
          VAL = COALESCE(PERSON_NAME3, '');
          SUSPEND;

          TAG_NAME = PFX || 'pupil:snils';
          VAL = COALESCE(SNILS, '');
          SUSPEND;

          TAG_NAME = PFX || 'pupil:class';
          VAL = 'РДТЛ';
          SUSPEND;

          TAG_NAME = PFX || 'pupil:class_type';
          VAL = 10;
          SUSPEND;

          TAG_NAME = PFX || 'pupil:person_type';
          VAL = 20;
          SUSPEND;

          TAG_NAME = PFX || 'pupil:reg_id';
          IF(POSITION(':' IN REG_ID) > 0) THEN REG_ID = SUBSTRING(REG_ID FROM 1 FOR POSITION(':' IN REG_ID) - 1);
          VAL = REG_ID;
          SUSPEND;

          IF(MODE IN (1, 2)) THEN
          BEGIN
              TAG_NAME = PFX || 'pupil:dob';
              VAL = (SELECT VAL FROM DATE2ISO(:PERSON_DATE, 0));
              SUSPEND;

              TAG_NAME = PFX || 'pupil:event';
              VAL = NULL;
              SUSPEND;

              IF(MODE = 1) THEN
              BEGIN
                TAG_NAME = PFX || 'pupil:event::json&colon;array';
                VAL = '1';
                SUSPEND;
              END

              TAG_NAME = PFX || 'pupil:event:directionType';
              VAL = EVENT_TYPE;
              SUSPEND;
          END

      END

  END

  -- Представители детей, покинувших школу, если больше детей не осталось
  FOR
      SELECT DISTINCT L20.OBJ_ID, CAST(V128.VAL AS VARCHAR(400)), CAST(V129.VAL AS VARCHAR(400)), CAST(V130.VAL AS VARCHAR(400)), V143.VAL, VS.SVAL
      FROM LINKS L78
      JOIN LINKS L8X ON L8X.PARENT_ID = L78.OBJ_ID AND L8X.OBJ_TYPE_ID IN (81, 82, 83) AND L8X.DATE_DEL IS NULL
      JOIN LINKS L10 ON L10.PARENT_ID = L8X.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      -- Ссылка на родителя после выбытия не исправляется
      JOIN LINKS L20 ON L20.PARENT_ID = L10.OBJ_ID AND L20.OBJ_TYPE_ID = 20 AND L10.DATE_DEL IS NULL
      -- Отмеченных как постоянные сопровождающие
      JOIN VALL V2818 on V2818.OBJ_ID = L20.OBJ_ID and V2818.PARAM_ID = 2818 and V2818.IS_DEL = 0 and V2818.LISTVAL_ID = 2
      -- Фамилия
      JOIN VALS V128 ON V128.OBJ_ID = L20.OBJ_ID AND V128.PARAM_ID = 128 AND V128.IS_DEL = 0
      -- Имя
      JOIN VALS V129 ON V129.OBJ_ID = L20.OBJ_ID AND V129.PARAM_ID = 129 AND V129.IS_DEL = 0
      -- Отчество - опционально
      LEFT JOIN VALS V130 ON V130.OBJ_ID = L20.OBJ_ID AND V130.PARAM_ID = 130 AND V130.IS_DEL = 0
      -- Дата рождения
      LEFT JOIN VALD V143 ON V143.OBJ_ID = L20.OBJ_ID AND V143.PARAM_ID = 143 AND V143.IS_DEL = 0
      -- СНИЛС
      LEFT JOIN VALS VS ON VS.OBJ_ID = L20.OBJ_ID AND VS.PARAM_ID = 2365 AND VS.IS_DEL = 0
      WHERE L78.PARENT_ID = :SCHOOL_ID AND L78.OBJ_TYPE_ID = 78 AND L78.DATE_DEL IS NULL
        AND (L10.DATE_INS >= DATEADD(-4 MONTH TO :THIS_YEAR))
        AND (:DATE_START IS NULL OR L10.DATE_INS >= :DATE_START OR L10.DATE_MODIFY >= :DATE_START OR L20.DATE_MODIFY >= :DATE_START)
        -- для СКУД не нужно
        AND (:MODE <> 0)
      INTO :OBJ_ID, :PERSON_NAME1, :PERSON_NAME2, :PERSON_NAME3, :PERSON_DATE, :SNILS
  DO
  BEGIN

      -- RegID
      REG_ID = NULL;
      SELECT VG.VAL
      FROM VALS VG
      WHERE VG.OBJ_ID = :OBJ_ID AND VG.PARAM_ID = 2917 AND VG.IS_DEL = 0
      INTO :REG_ID;

      -- ID карты
      CARD_ID = NULL;
      SELECT V2918.VAL
      FROM VALS V2918
      WHERE V2918.OBJ_ID = :OBJ_ID AND V2918.PARAM_ID = 2918 AND V2918.IS_DEL = 0
      INTO :CARD_ID;

      -- Проверяем, что не осталось связей с другими детьми
      P = 0;
      SELECT FIRST 1 1
      FROM LINKS LP10
      JOIN LINKS LPC ON LPC.OBJ_ID = LP10.PARENT_ID AND LPC.PARENT_TYPE_ID IN (9, 125, 187) AND LPC.DATE_DEL IS NULL
      WHERE LP10.OBJ_ID = :OBJ_ID AND LP10.PARENT_TYPE_ID = 10 AND LP10.DATE_DEL IS NULL
      INTO :P;

      IF(P = 1) THEN EVENT_TYPE = 'OUT'; ELSE EVENT_TYPE = '';

      IF(EVENT_TYPE <> '') THEN
      BEGIN

          TAG_NAME = 'pupil';
          VAL = NULL;
          SUSPEND;

          -- Подмены ID тут пока не предусмотрено

          TAG_NAME = PFX || 'pupil:suid';
          VAL = OBJ_ID;
          SUSPEND;

          -- Подчищаем введенный ID карты от левых символов
          CARD_ID = REPLACE(CARD_ID, ' ', '');
          CARD_ID = REPLACE(CARD_ID, '-', '');
          CARD_ID = REPLACE(CARD_ID, '.', '');
          TAG_NAME = PFX || 'pupil:card_id';
          VAL = CARD_ID;
          SUSPEND;

          TAG_NAME = PFX || 'pupil:surname';
          VAL = PERSON_NAME1;
          SUSPEND;

          TAG_NAME = PFX || 'pupil:name';
          VAL = PERSON_NAME2;
          SUSPEND;

          TAG_NAME = PFX || 'pupil:patronymic';
          VAL = COALESCE(PERSON_NAME3, '');
          SUSPEND;

          TAG_NAME = PFX || 'pupil:class';
          VAL = 'РДТЛ';
          SUSPEND;

          TAG_NAME = PFX || 'pupil:class_type';
          VAL = 10;
          SUSPEND;

          TAG_NAME = PFX || 'pupil:person_type';
          VAL = 20;
          SUSPEND;

          TAG_NAME = PFX || 'pupil:dob';
          VAL = (SELECT VAL FROM DATE2ISO(:PERSON_DATE, 0));
          SUSPEND;

          TAG_NAME = PFX || 'pupil:snils';
          VAL = COALESCE(SNILS, '');
          SUSPEND;

          TAG_NAME = PFX || 'pupil:reg_id';
          IF(POSITION(':' IN REG_ID) > 0) THEN REG_ID = SUBSTRING(REG_ID FROM 1 FOR POSITION(':' IN REG_ID) - 1);
          VAL = REG_ID;
          SUSPEND;

          IF(MODE IN (1, 2)) THEN
          BEGIN
              TAG_NAME = PFX || 'pupil:event';
              VAL = NULL;
              SUSPEND;

              IF(MODE = 1) THEN
              BEGIN
                TAG_NAME = PFX || 'pupil:event::json&colon;array';
                VAL = '1';
                SUSPEND;
              END

              TAG_NAME = PFX || 'pupil:event:directionType';
              VAL = EVENT_TYPE;
              SUSPEND;
          END

      END

  END

  -- Сотрудники
  FOR
      SELECT L14.OBJ_ID, V59.SVAL, V60.SVAL, V61.SVAL, V241.VAL, CAST(VG.VAL AS VARCHAR(100)), V2857.VAL,
        L14.DATE_INS, L14.DATE_MODIFY, V59.DATE_MODIFY, V60.DATE_MODIFY, V61.DATE_MODIFY, V241.DATE_MODIFY,
        VS.SVAL, VS.DATE_MODIFY, VG.DATE_MODIFY
      FROM LINKS L14
      -- Фамилия
      JOIN VALS V59 ON V59.OBJ_ID = L14.OBJ_ID AND V59.PARAM_ID = 59 AND V59.IS_DEL = 0
      -- Имя
      JOIN VALS V60 ON V60.OBJ_ID = L14.OBJ_ID AND V60.PARAM_ID = 60 AND V60.IS_DEL = 0
      -- Отчество - опционально
      LEFT JOIN VALS V61 ON V61.OBJ_ID = L14.OBJ_ID AND V61.PARAM_ID = 61 AND V61.IS_DEL = 0
      -- Дата рождения
      LEFT JOIN VALD V241 ON V241.OBJ_ID = L14.OBJ_ID AND V241.PARAM_ID = 241 AND V241.IS_DEL = 0
      -- ID карты
      LEFT JOIN VALS V2857 ON V2857.OBJ_ID = L14.OBJ_ID AND V2857.PARAM_ID = 2857 AND V2857.IS_DEL = 0
      -- RegID
      LEFT JOIN VALS VG ON VG.OBJ_ID = L14.OBJ_ID AND VG.PARAM_ID = 2915 AND VG.IS_DEL = 0
      -- СНИЛС
      LEFT JOIN VALS VS ON VS.OBJ_ID = L14.OBJ_ID AND VS.PARAM_ID = 2455 AND VS.IS_DEL = 0
      WHERE L14.PARENT_ID = :SCHOOL_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
      ORDER BY L14.DATE_INS
      INTO :OBJ_ID, :PERSON_NAME1, :PERSON_NAME2, :PERSON_NAME3, :PERSON_DATE, :REG_ID, :CARD_ID,
        :L10_D_INS, :L10_D_CHANGE, :V55_CHANGE, :V56_CHANGE, :V57_CHANGE, :V89_CHANGE,
        :SNILS, :SNILS_CHANGE, :V$RKDT
  DO
  BEGIN

      EVENT_TYPE = '';

      IF(DATE_START IS NULL OR L10_D_INS >= DATE_START OR L10_D_CHANGE >= DATE_START) THEN
          EVENT_TYPE = EVENT_TYPE || 'IN,';

      IF(DATE_START IS NULL OR V55_CHANGE >= DATE_START OR V56_CHANGE >= DATE_START OR V57_CHANGE >= DATE_START OR V89_CHANGE >= DATE_START OR SNILS_CHANGE >= DATE_START
          OR V$RKDT >= DATE_START)
      THEN
          EVENT_TYPE = EVENT_TYPE || 'DATA,';

      -- Не выгружаем запись сотрудника, если есть парный ему действующий ученик с теми же ФИО+ДР, либо СНИЛС, либо регид
      IF(EVENT_TYPE <> '' AND REG_ID IS NOT NULL AND EXISTS(
        SELECT FIRST 1 1
        FROM LINKS L7
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 125, 187) AND L9.DATE_DEL IS NULL
        JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        JOIN VALS V55 ON V55.OBJ_ID = L10.OBJ_ID AND V55.PARAM_ID = 55 AND V55.IS_DEL = 0
        JOIN VALS V56 ON V56.OBJ_ID = L10.OBJ_ID AND V56.PARAM_ID = 56 AND V56.IS_DEL = 0
        JOIN VALS VG ON VG.OBJ_ID = L10.OBJ_ID AND VG.PARAM_ID = 2912 AND VG.IS_DEL = 0 AND VG.VAL = :REG_ID
        WHERE L7.PARENT_ID = :SCHOOL_ID AND L7.OBJ_TYPE_ID IN (7, 502) AND L7.DATE_DEL IS NULL
      ))
      THEN
        EVENT_TYPE = '';

      IF(EVENT_TYPE <> '' AND SNILS IS NOT NULL AND EXISTS(
        SELECT FIRST 1 1
        FROM LINKS L7
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 125, 187) AND L9.DATE_DEL IS NULL
        JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        JOIN VALS V55 ON V55.OBJ_ID = L10.OBJ_ID AND V55.PARAM_ID = 55 AND V55.IS_DEL = 0
        JOIN VALS V56 ON V56.OBJ_ID = L10.OBJ_ID AND V56.PARAM_ID = 56 AND V56.IS_DEL = 0
        JOIN VALS VG ON VG.OBJ_ID = L10.OBJ_ID AND VG.PARAM_ID = 1409 AND VG.IS_DEL = 0 AND VG.VAL = :SNILS
        WHERE L7.PARENT_ID = :SCHOOL_ID AND L7.OBJ_TYPE_ID IN (7, 502) AND L7.DATE_DEL IS NULL
      ))
      THEN
        EVENT_TYPE = '';

      IF(EVENT_TYPE <> '' AND EXISTS(
        SELECT FIRST 1 1
        FROM LINKS L7
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 125, 187) AND L9.DATE_DEL IS NULL
        JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        JOIN VALS V55 ON V55.OBJ_ID = L10.OBJ_ID AND V55.PARAM_ID = 55 AND V55.IS_DEL = 0 AND V55.SVAL = :PERSON_NAME1
        JOIN VALS V56 ON V56.OBJ_ID = L10.OBJ_ID AND V56.PARAM_ID = 56 AND V56.IS_DEL = 0 AND V56.SVAL = :PERSON_NAME2
        LEFT JOIN VALS V57 ON V57.OBJ_ID = L10.OBJ_ID AND V57.PARAM_ID = 57 AND V57.IS_DEL = 0
        JOIN VALD V89 ON V89.OBJ_ID = L10.OBJ_ID AND V89.PARAM_ID = 89 AND V89.IS_DEL = 0 AND V89.VAL = :PERSON_DATE
        WHERE L7.PARENT_ID = :SCHOOL_ID AND L7.OBJ_TYPE_ID IN (7, 502) AND L7.DATE_DEL IS NULL
          AND (V57.SVAL = :PERSON_NAME3 OR (V57.SVAL IS NULL AND :PERSON_NAME3 IS NULL))
      ))
      THEN
        EVENT_TYPE = '';

      IF(EVENT_TYPE <> '') THEN
      BEGIN

          TAG_NAME = PFX || 'pupil';
          VAL = NULL;
          SUSPEND;

          TAG_NAME = PFX || 'pupil:suid';
          VAL = OBJ_ID;
          SUSPEND;

          -- Подчищаем введенный ID карты от левых символов
          CARD_ID = REPLACE(CARD_ID, ' ', '');
          CARD_ID = REPLACE(CARD_ID, '-', '');
          CARD_ID = REPLACE(CARD_ID, '.', '');
          TAG_NAME = PFX || 'pupil:card_id';
          VAL = CARD_ID;
          SUSPEND;

          TAG_NAME = PFX || 'pupil:surname';
          VAL = PERSON_NAME1;
          SUSPEND;

          TAG_NAME = PFX || 'pupil:name';
          VAL = PERSON_NAME2;
          SUSPEND;

          TAG_NAME = PFX || 'pupil:patronymic';
          VAL = COALESCE(PERSON_NAME3, '');
          SUSPEND;

          TAG_NAME = PFX || 'pupil:class';
          VAL = 'СОТР';
          SUSPEND;

          TAG_NAME = PFX || 'pupil:class_type';
          VAL = 2;
          SUSPEND;

          TAG_NAME = PFX || 'pupil:person_type';
          VAL = 14;
          -- Проверяем, есть ли у сотрудника основная должность или он везде совместитель ?
          IF(NOT EXISTS(
              SELECT FIRST 1 1
              FROM LINKS L15
              JOIN VALL V587 ON V587.OBJ_ID = L15.OBJ_ID AND V587.PARAM_ID = 587 AND V587.IS_DEL = 0 AND V587.LISTVAL_ID IN (207, 1720)
              -- неактуальные ставки пропускаем
              LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
              WHERE L15.PARENT_ID = :OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL AND V74.VAL IS NULL
          ))
          THEN VAL = 1014;
          SUSPEND;

          TAG_NAME = PFX || 'pupil:dob';
          VAL = (SELECT VAL FROM DATE2ISO(:PERSON_DATE, 0));
          SUSPEND;

          TAG_NAME = PFX || 'pupil:snils';
          VAL = COALESCE(SNILS, '');
          SUSPEND;

          TAG_NAME = PFX || 'pupil:reg_id';
          IF(POSITION(':' IN REG_ID) > 0) THEN REG_ID = SUBSTRING(REG_ID FROM 1 FOR POSITION(':' IN REG_ID) - 1);
          VAL = REG_ID;
          SUSPEND;

          IF(MODE IN (1, 2)) THEN
          BEGIN

              TAG_NAME = PFX || 'pupil:event';
              VAL = NULL;
              SUSPEND;

              IF(MODE = 1) THEN
              BEGIN
                TAG_NAME = PFX || 'pupil:event::json&colon;array';
                VAL = '1';
                SUSPEND;
              END

              WHILE(EVENT_TYPE <> '') DO
              BEGIN
                  P = POSITION(',' IN EVENT_TYPE);
                  IF(P = 0) THEN P = CHARACTER_LENGTH(EVENT_TYPE) + 1;

                  TAG_NAME = PFX || 'pupil:event:directionType';
                  VAL = SUBSTRING(EVENT_TYPE FROM 1 FOR P - 1);
                  SUSPEND;

                  EVENT_TYPE = SUBSTRING(EVENT_TYPE FROM P + 1);
              END

          END

      END

  END

  -- Уволенные сотрудники
  FOR
      SELECT L14.OBJ_ID, V59.SVAL, V60.SVAL, V61.SVAL, V241.VAL, CAST(VG.VAL AS VARCHAR(100)), V2857.VAL,
        L14.DATE_INS, L14.DATE_MODIFY, V59.DATE_MODIFY, V60.DATE_MODIFY, V61.DATE_MODIFY, V241.DATE_MODIFY,
        VS.SVAL, VS.DATE_MODIFY, VG.DATE_MODIFY
      FROM LINKS L84
      JOIN LINKS L14 ON L14.PARENT_ID = L84.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
      -- Фамилия
      JOIN VALS V59 ON V59.OBJ_ID = L14.OBJ_ID AND V59.PARAM_ID = 59 AND V59.IS_DEL = 0
      -- Имя
      JOIN VALS V60 ON V60.OBJ_ID = L14.OBJ_ID AND V60.PARAM_ID = 60 AND V60.IS_DEL = 0
      -- Отчество - опционально
      LEFT JOIN VALS V61 ON V61.OBJ_ID = L14.OBJ_ID AND V61.PARAM_ID = 61 AND V61.IS_DEL = 0
      -- Дата рождения
      LEFT JOIN VALD V241 ON V241.OBJ_ID = L14.OBJ_ID AND V241.PARAM_ID = 241 AND V241.IS_DEL = 0
      -- ID карты
      LEFT JOIN VALS V2857 ON V2857.OBJ_ID = L14.OBJ_ID AND V2857.PARAM_ID = 2857 AND V2857.IS_DEL = 0
      -- RegID
      LEFT JOIN VALS VG ON VG.OBJ_ID = L14.OBJ_ID AND VG.PARAM_ID = 2915 AND VG.IS_DEL = 0
      -- СНИЛС
      LEFT JOIN VALS VS ON VS.OBJ_ID = L14.OBJ_ID AND VS.PARAM_ID = 2455 AND VS.IS_DEL = 0
      WHERE L84.PARENT_ID = :SCHOOL_ID AND L84.OBJ_TYPE_ID = 84 AND L84.DATE_DEL IS NULL
        AND L14.DATE_INS > DATEADD(YEAR, -1, CURRENT_DATE) -- за последний год
        AND (:DATE_START IS NULL OR L14.DATE_INS >= :DATE_START OR L14.DATE_MODIFY >= :DATE_START)
        -- для СКУД не нужно
        AND (:MODE <> 0)
      INTO :OBJ_ID, :PERSON_NAME1, :PERSON_NAME2, :PERSON_NAME3, :PERSON_DATE, :REG_ID, :CARD_ID,
        :L10_D_INS, :L10_D_CHANGE, :V55_CHANGE, :V56_CHANGE, :V57_CHANGE, :V89_CHANGE,
        :SNILS, :SNILS_CHANGE, :V$RKDT
  DO
  BEGIN

      EVENT_TYPE = 'OUT';

      -- Не выгружаем запись сотрудника, если есть парный ему действующий ученик с теми же ФИО+ДР, либо СНИЛС, либо регид
      IF(EVENT_TYPE <> '' AND REG_ID IS NOT NULL AND EXISTS(
        SELECT FIRST 1 1
        FROM LINKS L7
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 125, 187) AND L9.DATE_DEL IS NULL
        JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        JOIN VALS V55 ON V55.OBJ_ID = L10.OBJ_ID AND V55.PARAM_ID = 55 AND V55.IS_DEL = 0
        JOIN VALS V56 ON V56.OBJ_ID = L10.OBJ_ID AND V56.PARAM_ID = 56 AND V56.IS_DEL = 0
        JOIN VALS VG ON VG.OBJ_ID = L10.OBJ_ID AND VG.PARAM_ID = 2912 AND VG.IS_DEL = 0 AND VG.VAL = :REG_ID
        WHERE L7.PARENT_ID = :SCHOOL_ID AND L7.OBJ_TYPE_ID IN (7, 502) AND L7.DATE_DEL IS NULL
      ))
      THEN
        EVENT_TYPE = '';

      IF(EVENT_TYPE <> '' AND SNILS IS NOT NULL AND EXISTS(
        SELECT FIRST 1 1
        FROM LINKS L7
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 125, 187) AND L9.DATE_DEL IS NULL
        JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        JOIN VALS V55 ON V55.OBJ_ID = L10.OBJ_ID AND V55.PARAM_ID = 55 AND V55.IS_DEL = 0
        JOIN VALS V56 ON V56.OBJ_ID = L10.OBJ_ID AND V56.PARAM_ID = 56 AND V56.IS_DEL = 0
        JOIN VALS VG ON VG.OBJ_ID = L10.OBJ_ID AND VG.PARAM_ID = 1409 AND VG.IS_DEL = 0 AND VG.VAL = :SNILS
        WHERE L7.PARENT_ID = :SCHOOL_ID AND L7.OBJ_TYPE_ID IN (7, 502) AND L7.DATE_DEL IS NULL
      ))
      THEN
        EVENT_TYPE = '';

      IF(EVENT_TYPE <> '' AND EXISTS(
        SELECT FIRST 1 1
        FROM LINKS L7
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 125, 187) AND L9.DATE_DEL IS NULL
        JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        JOIN VALS V55 ON V55.OBJ_ID = L10.OBJ_ID AND V55.PARAM_ID = 55 AND V55.IS_DEL = 0 AND V55.SVAL = :PERSON_NAME1
        JOIN VALS V56 ON V56.OBJ_ID = L10.OBJ_ID AND V56.PARAM_ID = 56 AND V56.IS_DEL = 0 AND V56.SVAL = :PERSON_NAME2
        LEFT JOIN VALS V57 ON V57.OBJ_ID = L10.OBJ_ID AND V57.PARAM_ID = 57 AND V57.IS_DEL = 0
        JOIN VALD V89 ON V89.OBJ_ID = L10.OBJ_ID AND V89.PARAM_ID = 89 AND V89.IS_DEL = 0 AND V89.VAL = :PERSON_DATE
        WHERE L7.PARENT_ID = :SCHOOL_ID AND L7.OBJ_TYPE_ID IN (7, 502) AND L7.DATE_DEL IS NULL
          AND (V57.SVAL = :PERSON_NAME3 OR (V57.SVAL IS NULL AND :PERSON_NAME3 IS NULL))
      ))
      THEN
        EVENT_TYPE = '';

      IF(EVENT_TYPE <> '') THEN
      BEGIN

          TAG_NAME = PFX || 'pupil';
          VAL = NULL;
          SUSPEND;

          -- Подмены ID тут пока не предусмотрено

          TAG_NAME = PFX || 'pupil:suid';
          VAL = OBJ_ID;
          SUSPEND;

          -- Подчищаем введенный ID карты от левых символов
          CARD_ID = REPLACE(CARD_ID, ' ', '');
          CARD_ID = REPLACE(CARD_ID, '-', '');
          CARD_ID = REPLACE(CARD_ID, '.', '');
          TAG_NAME = PFX || 'pupil:card_id';
          VAL = CARD_ID;
          SUSPEND;

          TAG_NAME = PFX || 'pupil:surname';
          VAL = PERSON_NAME1;
          SUSPEND;

          TAG_NAME = PFX || 'pupil:name';
          VAL = PERSON_NAME2;
          SUSPEND;

          TAG_NAME = PFX || 'pupil:patronymic';
          VAL = COALESCE(PERSON_NAME3, '');
          SUSPEND;

          TAG_NAME = PFX || 'pupil:snils';
          VAL = COALESCE(SNILS, '');
          SUSPEND;

          TAG_NAME = PFX || 'pupil:class';
          VAL = 'СОТР';
          SUSPEND;

          TAG_NAME = PFX || 'pupil:class_type';
          VAL = 2;
          SUSPEND;

          TAG_NAME = PFX || 'pupil:person_type';
          VAL = 14;
          SUSPEND;

          TAG_NAME = PFX || 'pupil:reg_id';
          IF(POSITION(':' IN REG_ID) > 0) THEN REG_ID = SUBSTRING(REG_ID FROM 1 FOR POSITION(':' IN REG_ID) - 1);
          VAL = REG_ID;
          SUSPEND;

          IF(MODE IN (1, 2)) THEN
          BEGIN
              TAG_NAME = PFX || 'pupil:dob';
              VAL = (SELECT VAL FROM DATE2ISO(:PERSON_DATE, 0));
              SUSPEND;

              -- Дата выбытия
              SELECT MAX(V74.VAL)
              FROM LINKS L15
              JOIN VALD V74 ON V74.PARAM_ID = 74 AND V74.OBJ_ID = L15.OBJ_ID AND V74.IS_DEL = 0
              WHERE L15.PARENT_ID = :OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
              INTO :LAST_LEAVE_DATE;

              TAG_NAME = PFX || 'pupil:leave_date';
              VAL = (SELECT VAL FROM DATE2ISO(:LAST_LEAVE_DATE, 0));
              SUSPEND;

              TAG_NAME = PFX || 'pupil:event';
              VAL = NULL;
              SUSPEND;

              IF(MODE = 1) THEN
              BEGIN
                TAG_NAME = PFX || 'pupil:event::json&colon;array';
                VAL = '1';
                SUSPEND;
              END

              TAG_NAME = PFX || 'pupil:event:directionType';
              VAL = EVENT_TYPE;
              SUSPEND;
          END

      END

  END

  -- Учащиеся секции ДО, не являющиеся штатными учениками (кроме ГПД)
  FOR
      SELECT L46.OBJ_ID, L10.OBJ_ID, V55.SVAL, V56.SVAL, V57.SVAL, V89.VAL, V2855.VAL, V2899.LISTVAL_ID, VG.VAL,
        L10.DATE_INS, L10.DATE_MODIFY, V55.DATE_MODIFY, V56.DATE_MODIFY, V57.DATE_MODIFY, V89.DATE_MODIFY, V2855.DATE_MODIFY,
        VS.SVAL, VS.DATE_MODIFY, VG.DATE_MODIFY
      FROM LINKS L86
      JOIN LINKS L46 ON L46.PARENT_ID = L86.OBJ_ID AND L46.OBJ_TYPE_ID = 46 AND L46.DATE_DEL IS NULL
      -- Исключаем ГПД
      JOIN VALL V369 ON V369.OBJ_ID = L46.OBJ_ID AND V369.PARAM_ID = 369 AND V369.IS_DEL = 0 AND V369.LISTVAL_ID <> 1246
      JOIN LINKS L10 ON L10.PARENT_ID = L46.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      LEFT JOIN LINKS LP9 ON LP9.OBJ_ID = L10.OBJ_ID AND LP9.PARENT_TYPE_ID IN (9, 125, 187) AND LP9.DATE_DEL IS NULL
      -- Фамилия
      JOIN VALS V55 ON V55.OBJ_ID = L10.OBJ_ID AND V55.PARAM_ID = 55 AND V55.IS_DEL = 0
      -- Имя
      JOIN VALS V56 ON V56.OBJ_ID = L10.OBJ_ID AND V56.PARAM_ID = 56 AND V56.IS_DEL = 0
      -- Отчество - опционально
      LEFT JOIN VALS V57 ON V57.OBJ_ID = L10.OBJ_ID AND V57.PARAM_ID = 57 AND V57.IS_DEL = 0
      -- Дата рождения
      LEFT JOIN VALD V89 ON V89.OBJ_ID = L10.OBJ_ID AND V89.PARAM_ID = 89 AND V89.IS_DEL = 0
      -- ID карты
      LEFT JOIN VALS V2855 ON V2855.OBJ_ID = L10.OBJ_ID AND V2855.PARAM_ID = 2855 AND V2855.IS_DEL = 0
      -- Принудительная выгрузка
      LEFT JOIN VALL V2899 ON V2899.OBJ_ID = L10.OBJ_ID AND V2899.PARAM_ID = 2899 AND V2899.IS_DEL = 0
      -- RegID
      LEFT JOIN VALS VG ON VG.OBJ_ID = L10.OBJ_ID AND VG.PARAM_ID = 2912 AND VG.IS_DEL = 0
      -- СНИЛС
      LEFT JOIN VALS VS ON VS.OBJ_ID = L10.OBJ_ID AND VS.PARAM_ID = 1409 AND VS.IS_DEL = 0
      WHERE L86.PARENT_ID = :SCHOOL_ID AND L86.OBJ_TYPE_ID = 86 AND L86.DATE_DEL IS NULL AND LP9.PARENT_ID IS NULL
      INTO :CLASS_ID, :OBJ_ID, :PERSON_NAME1, :PERSON_NAME2, :PERSON_NAME3, :PERSON_DATE, :CARD_ID, :FORCED_EXPORT, :REG_ID,
        :L10_D_INS, :L10_D_CHANGE, :V55_CHANGE, :V56_CHANGE, :V57_CHANGE, :V89_CHANGE, :V2855_CHANGE,
        :SNILS, :SNILS_CHANGE, :V$RKDT
  DO
  BEGIN

      EVENT_TYPE = '';

      IF(FORCED_EXPORT = 2 OR DATE_START IS NULL OR L10_D_INS >= DATE_START OR L10_D_CHANGE >= DATE_START OR V2855_CHANGE >= DATE_START) THEN
          EVENT_TYPE = EVENT_TYPE || 'IN,';

      -- На всякий случай добавляем DATA для полной выгрузки
      IF(DATE_START IS NULL OR V55_CHANGE >= DATE_START OR V56_CHANGE >= DATE_START OR V57_CHANGE >= DATE_START OR V89_CHANGE >= DATE_START OR SNILS_CHANGE >= DATE_START
          OR V$RKDT >= DATE_START)
      THEN
          EVENT_TYPE = EVENT_TYPE || 'DATA,';

      IF(EVENT_TYPE <> '') THEN
      BEGIN

          TAG_NAME = PFX || 'pupil';
          VAL = NULL;
          SUSPEND;

          TAG_NAME = PFX || 'pupil:suid';
          VAL = OBJ_ID;
          SUSPEND;

          -- Подчищаем введенный ID карты от левых символов
          CARD_ID = REPLACE(CARD_ID, ' ', '');
          CARD_ID = REPLACE(CARD_ID, '-', '');
          CARD_ID = REPLACE(CARD_ID, '.', '');
          TAG_NAME = PFX || 'pupil:card_id';
          VAL = CARD_ID;
          SUSPEND;

          TAG_NAME = PFX || 'pupil:surname';
          VAL = PERSON_NAME1;
          SUSPEND;

          TAG_NAME = PFX || 'pupil:name';
          VAL = PERSON_NAME2;
          SUSPEND;

          TAG_NAME = PFX || 'pupil:patronymic';
          VAL = COALESCE(PERSON_NAME3, '');
          SUSPEND;

          TAG_NAME = PFX || 'pupil:class';
          VAL = 'ОДО: ' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:CLASS_ID));
          SUSPEND;

          TAG_NAME = PFX || 'pupil:class_type';
          VAL = 46;
          SUSPEND;

          TAG_NAME = PFX || 'pupil:person_type';
          VAL = 10;
          SUSPEND;

          TAG_NAME = PFX || 'pupil:dob';
          VAL = (SELECT VAL FROM DATE2ISO(:PERSON_DATE, 0));
          SUSPEND;

          TAG_NAME = PFX || 'pupil:snils';
          VAL = COALESCE(SNILS, '');
          SUSPEND;

          TAG_NAME = PFX || 'pupil:reg_id';
          IF(POSITION(':' IN REG_ID) > 0) THEN REG_ID = SUBSTRING(REG_ID FROM 1 FOR POSITION(':' IN REG_ID) - 1);
          VAL = REG_ID;
          SUSPEND;

          IF(MODE IN (1, 2)) THEN
          BEGIN
              TAG_NAME = PFX || 'pupil:portal';
              VAL = '';
              SUSPEND;

              TAG_NAME = PFX || 'pupil:event';
              VAL = NULL;
              SUSPEND;

              IF(MODE = 1) THEN
              BEGIN
                TAG_NAME = PFX || 'pupil:event::json&colon;array';
                VAL = '1';
                SUSPEND;
              END

              WHILE(EVENT_TYPE <> '') DO
              BEGIN
                  P = POSITION(',' IN EVENT_TYPE);
                  IF(P = 0) THEN P = CHARACTER_LENGTH(EVENT_TYPE) + 1;

                  TAG_NAME = PFX || 'pupil:event:directionType';
                  VAL = SUBSTRING(EVENT_TYPE FROM 1 FOR P - 1);
                  SUSPEND;

                  EVENT_TYPE = SUBSTRING(EVENT_TYPE FROM P + 1);
              END
          END

          TAG_NAME = PFX || 'pupil:benefit';
          VAL = NULL;
          SUSPEND;

          TAG_NAME = PFX || 'pupil:benefit:code';
          VAL = '';
          SUSPEND;

          TAG_NAME = PFX || 'pupil:benefit:adate';
          VAL = '';
          SUSPEND;

          IF(MODE IN (1, 2)) THEN
          BEGIN
              TAG_NAME = PFX || 'pupil:benefit:bdate';
              VAL = '';
              SUSPEND;
          END

      END

      -- Выбывшие учащиеся секции ДО, не являющиеся учениками школы

  END


  -- Конец цикла по ОУ
  END

  -- Обработка ошибок - пропускаем
  WHEN ANY DO
  BEGIN
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DG_GIA_CODES RETURNS (
    TAG_NAME VARCHAR(255),
    VAL VARCHAR(1000))
AS
declare variable SCHOOL_ID bigint;
declare variable OGRN varchar(100);
declare variable OU_CODE bigint;
declare variable PPE_CODE bigint;
declare variable G9 bigint;
declare variable G11 bigint;
declare variable OU_ADDRESS varchar(1000);
declare variable OU_RESP varchar(1000);
begin
  -- Список актуальных ОУ
  FOR
    SELECT DISTINCT L2.OBJ_ID, V9.VAL, V1364.VAL, V1365.VAL, V1367.VAL, V1368.VAL, V1371.VAL, C1369.CAPTION
    FROM LINKS L2
    JOIN VALS V9 ON V9.OBJ_ID = L2.OBJ_ID AND V9.PARAM_ID = 9 AND V9.IS_DEL = 0
    JOIN VALI V1364 ON V1364.OBJ_ID = L2.OBJ_ID AND V1364.PARAM_ID = 1364 AND V1364.IS_DEL = 0
    JOIN VALI V1365 ON V1365.OBJ_ID = L2.OBJ_ID AND V1365.PARAM_ID = 1365 AND V1365.IS_DEL = 0
    LEFT JOIN VALI V1367 ON V1367.OBJ_ID = L2.OBJ_ID AND V1367.PARAM_ID = 1367 AND V1367.IS_DEL = 0
    LEFT JOIN VALI V1368 ON V1368.OBJ_ID = L2.OBJ_ID AND V1368.PARAM_ID = 1368 AND V1368.IS_DEL = 0
    LEFT JOIN ADR_GET(1371, L2.OBJ_ID) V1371 ON 1 = 1
    JOIN VALR V1369 ON V1369.OBJ_ID = L2.OBJ_ID AND V1369.PARAM_ID = 1369 AND V1369.IS_DEL = 0
    LEFT JOIN OBJECT_CAPTION_GET(V1369.VAL) C1369 ON 1 = 1
    WHERE L2.OBJ_TYPE_ID = 2 AND (L2.PARENT_ID IS NULL OR L2.PARENT_TYPE_ID = 111) AND L2.DATE_DEL IS NULL
    INTO :SCHOOL_ID, :OGRN, :OU_CODE, :PPE_CODE, :G9, :G11, :OU_ADDRESS, :OU_RESP
  DO
  BEGIN
    -- Очередная запись
    TAG_NAME = 'wsdl&colon;school';
    VAL = NULL;
    SUSPEND;

    TAG_NAME = 'wsdl&colon;school::suid';
    VAL = SCHOOL_ID;
    SUSPEND;

    TAG_NAME = 'wsdl&colon;school::ogrn';
    VAL = OGRN;
    SUSPEND;

    TAG_NAME = 'wsdl&colon;school::ou_code';
    VAL = OU_CODE;
    SUSPEND;

    TAG_NAME = 'wsdl&colon;school::ppe_code';
    VAL = PPE_CODE;
    SUSPEND;

    TAG_NAME = 'wsdl&colon;school::allow_to_exam_9';
    IF(G9 IS NULL OR G9 = 0) THEN VAL = 'false'; ELSE VAL = 'true';
    SUSPEND;

    TAG_NAME = 'wsdl&colon;school::allow_to_exam_11';
    IF(G11 IS NULL OR G11 = 0) THEN VAL = 'false'; ELSE VAL = 'true';
    SUSPEND;

    TAG_NAME = 'wsdl&colon;school::address';
    VAL = OU_ADDRESS;
    SUSPEND;

    TAG_NAME = 'wsdl&colon;school::responsible';
    VAL = OU_RESP;
    SUSPEND;

    TAG_NAME = 'wsdl&colon;school::removed';
    VAL = 'false';
    SUSPEND;
  END
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DG_RC_EDUCATION (
    DATE_START TIMESTAMP,
    DATE_END TIMESTAMP)
RETURNS (
    TAG_NAME VARCHAR(255),
    VAL VARCHAR(1000))
AS
begin
  /* Procedure Text */
  suspend;
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DG_RC_EMPLOYEE (
    DATE_START TIMESTAMP,
    DATE_END TIMESTAMP)
RETURNS (
    TAG_NAME VARCHAR(255),
    VAL VARCHAR(1000))
AS
begin
  /* Procedure Text */
  suspend;
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DG_RC_GET_ADDRESS (
    TAG_PREFIX VARCHAR(255),
    OBJ_ID BIGINT,
    PARAM_ID BIGINT)
RETURNS (
    TAG_NAME VARCHAR(255),
    VAL VARCHAR(1000))
AS
declare variable REGION varchar(255);
declare variable DISTRICT varchar(255);
declare variable TOWN varchar(255);
declare variable SETTLEMENT varchar(255);
declare variable STREET varchar(255);
declare variable HOUSE varchar(10);
declare variable CORP varchar(10);
declare variable LITER varchar(10);
declare variable FLAT varchar(10);
declare variable POST_INDEX varchar(20);
declare variable FULLVAL varchar(2000);
declare variable OCATD varchar(11);
declare variable HOUSEGUID varchar(36);
declare variable STREETGUID varchar(36);
begin
  -- Открываем тег
  TAG_NAME = TAG_PREFIX;
  VAL = NULL;
  SUSPEND;

  SELECT REGION, DISTRICT, TOWN, SETTLEMENT, STREET, HOUSE, CORP, LITER, FLAT, POST_INDEX, OCATD, HOUSEGUID, STREETGUID, VAL
  FROM ADR_GET(:PARAM_ID, :OBJ_ID)
  INTO :REGION, :DISTRICT, :TOWN, :SETTLEMENT, :STREET, :HOUSE, :CORP, :LITER, :FLAT, :POST_INDEX, :OCATD, :HOUSEGUID, :STREETGUID, :FULLVAL;

  IF(FULLVAL IS NULL OR CHAR_LENGTH(FULLVAL) = 0) THEN EXIT;

  IF(HOUSEGUID IS NOT NULL AND CHAR_LENGTH(HOUSEGUID) > 0) THEN
  BEGIN
    TAG_NAME = TAG_PREFIX || ':guid';
      VAL = HOUSEGUID;
      SUSPEND;
  END

  -- Полное написание адреса
  TAG_NAME = TAG_PREFIX || ':name';
  VAL = FULLVAL;
  SUSPEND;

  -- Компоненты адреса

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DG_RC_GET_DICT (
    TAG_PREFIX VARCHAR(255),
    OBJ_ID BIGINT,
    PARAM_ID BIGINT,
    CODING_TYPE SMALLINT = 0,
    ALT_PARAM_ID BIGINT = null)
RETURNS (
    TAG_NAME VARCHAR(255),
    VAL VARCHAR(1000))
AS
declare variable LISTVAL_ID bigint;
declare variable TAG_VALUE varchar(100);
declare variable COST_VALUE double precision;
declare variable LISTVAL_VAL varchar(1000);
begin

  -- CODING_TYPE задает списоб кодирования
  -- 0 - используется значение LISTVAL_ID
  -- 1 - используется значение TAG_ID
  -- 2 - используется значение COST, обрезанное до целого числа
  -- 100+ - на перспективу, будет использоваться внешняя таблица перекодирования

  SELECT V.LISTVAL_ID, L.TAG, L.COST, R.VAL
  FROM VALL V
  JOIN LISTVALS L ON L.LISTVAL_ID = V.LISTVAL_ID AND L.IS_DEL = 0
  JOIN RES R ON R.RES_ID = L.RES_ID AND R.LANG_CODE = 'RU' AND R.IS_DEL = 0
  WHERE V.OBJ_ID = :OBJ_ID AND (V.PARAM_ID = :PARAM_ID OR V.PARAM_ID = :ALT_PARAM_ID) AND V.IS_DEL = 0
  INTO :LISTVAL_ID, :TAG_VALUE, :COST_VALUE, :LISTVAL_VAL;

  IF(LISTVAL_ID IS NULL) THEN EXIT;
  IF(CODING_TYPE = 1 AND (TAG_VALUE IS NULL OR CHAR_LENGTH(TAG_VALUE) = 0)) THEN EXIT;
  IF(CODING_TYPE = 2 AND COST_VALUE IS NULL) THEN EXIT;

  TAG_NAME = TAG_PREFIX;
  VAL = NULL;
  SUSPEND;

  TAG_NAME = TAG_PREFIX || ':code';
  IF(CODING_TYPE = 0) THEN VAL = LISTVAL_ID;
  ELSE IF(CODING_TYPE = 1) THEN VAL = TAG_VALUE;
  ELSE IF(CODING_TYPE = 2) THEN VAL = TRUNC(COST_VALUE);
  ELSE VAL = 'NOT_IMPLEMENTED';
  SUSPEND;

  TAG_NAME = TAG_PREFIX || ':name';
  VAL = LISTVAL_VAL;
  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DG_RC_INSTITUTION (
    DATE_START TIMESTAMP = NULL,
    DATE_END TIMESTAMP = NULL)
RETURNS (
    TAG_NAME VARCHAR(255),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE ORG_ID BIGINT;
DECLARE VARIABLE S1 VARCHAR(400);
DECLARE VARIABLE S2 VARCHAR(400);
DECLARE VARIABLE S3 VARCHAR(400);
DECLARE VARIABLE OBJ_ID BIGINT;
DECLARE VARIABLE C2 BIGINT;
DECLARE VARIABLE D1 DATE;
DECLARE VARIABLE D2 DATE;
DECLARE VARIABLE ID8 BIGINT;
DECLARE VARIABLE ID69 BIGINT;
DECLARE VARIABLE BASE_ID BIGINT;
begin

  -- Список ОУ (данные возвращаются одним общим запросом)
  FOR
    SELECT L2.OBJ_ID, V2.VAL, V5.VAL, COALESCE(V999.VAL, '')
    FROM LINKS L2
    JOIN VALS V2 ON V2.OBJ_ID = L2.OBJ_ID AND V2.PARAM_ID = 2 AND V2.IS_DEL = 0
    JOIN VALS V5 ON V5.OBJ_ID = L2.OBJ_ID AND V5.PARAM_ID = 5 AND V5.IS_DEL = 0
    LEFT JOIN VALS V999 ON V999.OBJ_ID = L2.OBJ_ID AND V999.PARAM_ID = 999 AND V999.IS_DEL = 0
    WHERE L2.OBJ_TYPE_ID = 2 AND (L2.PARENT_TYPE_ID IS NULL OR L2.PARENT_TYPE_ID IN (111, 112)) AND L2.DATE_DEL IS NULL
    INTO :ORG_ID, :S1, :S2, :S3
  DO
  BEGIN

    TAG_NAME = 'institution';
    VAL = NULL;
    SUSPEND;

    TAG_NAME = 'institution:externalKey';
    VAL = ORG_ID;
    SUSPEND;

    -- Для колледжей возвращаем альтернативное название, для остальных - обычное
    TAG_NAME = 'institution:name';
    VAL = S1;
    SUSPEND;

    TAG_NAME = 'institution:fullName';
    VAL = S2;
    SUSPEND;

    TAG_NAME = 'institution:additionalName';
    VAL = S3;
    SUSPEND;

    -- Адрес фактический
    FOR
      SELECT TAG_NAME, VAL
      FROM DG_RC_GET_ADDRESS('institution:address', :ORG_ID, 27)
      INTO :TAG_NAME, :VAL
    DO
    BEGIN
      SUSPEND;
    END

    -- Адрес юридический
    FOR
      SELECT TAG_NAME, VAL
      FROM DG_RC_GET_ADDRESS('institution:legalAddress', :ORG_ID, 27)
      INTO :TAG_NAME, :VAL
    DO
    BEGIN
      SUSPEND;
    END

    TAG_NAME = 'institution:ogrn';
    VAL = NULL;
    VAL = (SELECT VAL FROM VALS WHERE OBJ_ID = :ORG_ID AND PARAM_ID = 9 AND IS_DEL = 0);
    IF(VAL IS NOT NULL) THEN SUSPEND;

    TAG_NAME = 'institution:inn';
    VAL = NULL;
    VAL = (SELECT VAL FROM VALS WHERE OBJ_ID = :ORG_ID AND PARAM_ID = 33 AND IS_DEL = 0);
    IF(VAL IS NOT NULL) THEN SUSPEND;

    TAG_NAME = 'institution:kpp';
    VAL = NULL;
    VAL = (SELECT VAL FROM VALS WHERE OBJ_ID = :ORG_ID AND PARAM_ID = 34 AND IS_DEL = 0);
    IF(VAL IS NOT NULL) THEN SUSPEND;

    TAG_NAME = 'institution:okato';
    VAL = NULL;
    VAL = (SELECT VAL FROM VALS WHERE OBJ_ID = :ORG_ID AND PARAM_ID = 18 AND IS_DEL = 0);
    IF(VAL IS NOT NULL) THEN SUSPEND;

    TAG_NAME = 'institution:oktmo'; -- 8 или 11 символов длиной
    VAL = NULL;
    VAL = (SELECT VAL FROM VALS WHERE OBJ_ID = :ORG_ID AND PARAM_ID = 2440 AND IS_DEL = 0);
    IF(VAL IS NOT NULL AND (CHAR_LENGTH(VAL) = 8 OR CHAR_LENGTH(VAL) = 11)) THEN SUSPEND;

    TAG_NAME = 'institution:okfs'; -- 5 символов
    VAL = NULL;
    VAL = (SELECT VAL FROM VALS WHERE OBJ_ID = :ORG_ID AND PARAM_ID = 21 AND IS_DEL = 0);
    IF(VAL IS NOT NULL) THEN SUSPEND;

    TAG_NAME = 'institution:okved'; -- 2-8 символов
    VAL = NULL;
    VAL = (SELECT VAL FROM VALS WHERE OBJ_ID = :ORG_ID AND PARAM_ID = 20 AND IS_DEL = 0);
    IF(VAL IS NOT NULL) THEN SUSPEND;

    TAG_NAME = 'institution:okopf';
    VAL = NULL;
    VAL = (SELECT VAL FROM VALS WHERE OBJ_ID = :ORG_ID AND PARAM_ID = 22 AND IS_DEL = 0);
    IF(VAL IS NOT NULL) THEN SUSPEND;

    TAG_NAME = 'institution:okogu';
    VAL = NULL;
    VAL = (SELECT VAL FROM VALS WHERE OBJ_ID = :ORG_ID AND PARAM_ID = 19 AND IS_DEL = 0);
    IF(VAL IS NOT NULL) THEN SUSPEND;

    -- Директор
    TAG_NAME = 'institution:chiefFIO';
    VAL = (SELECT (F || ' ' || I || ' ' || O) as V FROM R_SPB_POST_DIRECTOR(:ORG_ID, 1));
    IF(VAL IS NOT NULL) THEN SUSPEND;

    TAG_NAME = 'institution:siteUrl';
    VAL = NULL;
    VAL = (SELECT VAL FROM VALS WHERE OBJ_ID = :ORG_ID AND PARAM_ID = 36 AND IS_DEL = 0);
    IF(VAL IS NOT NULL) THEN SUSPEND;

    TAG_NAME = 'institution:email';
    VAL = NULL;
    VAL = (SELECT VAL FROM VALS WHERE OBJ_ID = :ORG_ID AND PARAM_ID = 35 AND IS_DEL = 0);
    IF(VAL IS NOT NULL) THEN SUSPEND;

    TAG_NAME = 'institution:phone';
    VAL = NULL;
    VAL = (SELECT VAL FROM VALS WHERE OBJ_ID = :ORG_ID AND PARAM_ID = 29 AND IS_DEL = 0);
    IF(VAL IS NOT NULL) THEN SUSPEND;

    -- Статус ОУ
    FOR
      SELECT TAG_NAME, VAL
      FROM DG_RC_GET_DICT('institution:status', :ORG_ID, 2371, 1)
      INTO :TAG_NAME, :VAL
    DO
    BEGIN
      SUSPEND;
    END

    -- Тип ОУ, требуется перекодирование
    OBJ_ID = (SELECT I FROM VAL_GET(:ORG_ID, 1890));

    IF(OBJ_ID IS NOT NULL) THEN
    BEGIN

        IF(OBJ_ID = 5424) THEN OBJ_ID = 1;
        ELSE IF(OBJ_ID = 5425) THEN OBJ_ID = 11;
        ELSE IF(OBJ_ID = 5426) THEN OBJ_ID = 12;
        ELSE IF(OBJ_ID = 5427) THEN OBJ_ID = 14;
        ELSE IF(OBJ_ID = 5428) THEN OBJ_ID = 15;
        ELSE IF(OBJ_ID = 5429) THEN OBJ_ID = 16;
        ELSE IF(OBJ_ID = 5430) THEN OBJ_ID = 17;
        ELSE IF(OBJ_ID = 5432) THEN OBJ_ID = 23;
        ELSE IF(OBJ_ID = 5435) THEN OBJ_ID = 21;
        ELSE IF(OBJ_ID = 5433) THEN OBJ_ID = 22;
        ELSE IF(OBJ_ID = 5434) THEN OBJ_ID = 22;
        ELSE OBJ_ID = 0;

        IF(OBJ_ID = 12) THEN BEGIN
            C2 = (SELECT I FROM VAL_GET(:ORG_ID, 11));
            IF(C2 = 978) THEN OBJ_ID = 13;
            ELSE BEGIN
                S1 = (SELECT V FROM VAL_GET(:ORG_ID, 937));

                IF (S1 LIKE '%для глухих детей%') THEN OBJ_ID = 1301;
                ELSE IF (S1 LIKE '%для слабослышащих и позднооглохших детей%') THEN OBJ_ID = 1302;
                ELSE IF (S1 LIKE '%для слепых детей%') THEN OBJ_ID = 1304;
                ELSE IF (S1 LIKE '%для слабовидящих и поздноослепших детей%') THEN OBJ_ID = 1305;
                ELSE IF (S1 LIKE '%для детей с тяжелыми нарушениями речи%') THEN OBJ_ID = 1306;
                ELSE IF (S1 LIKE '%для детей с нарушением опорно-двигательного аппарата%') THEN OBJ_ID = 1307;
                ELSE IF (S1 LIKE '%для детей с задержкой психического развития%') THEN OBJ_ID = 1308;
                ELSE IF (S1 LIKE '%для умственно отсталых детей%') THEN OBJ_ID = 1309;

            END
        END

        S1 = CASE OBJ_ID
        WHEN 1 THEN 'Образовательные организации'
        WHEN 11 THEN 'Дошкольная образовательная организация'
        WHEN 12 THEN 'Общеобразовательная организация'
        WHEN 13 THEN 'Общеобразовательная организация, осуществляющая образовательную деятельность по адаптированным основным общеобразовательным программам'
        WHEN 1301 THEN 'Общеобразовательная организация, осуществляющая образовательную деятельность по адаптированным основным общеобразовательным программам для глухих'
        WHEN 1302 THEN 'Общеобразовательная организация, осуществляющая образовательную деятельность по адаптированным основным общеобразовательным программам для слабослышащих'
        WHEN 1303 THEN 'Общеобразовательная организация, осуществляющая образовательную деятельность по адаптированным основным общеобразовательным программам для позднооглохших'
        WHEN 1304 THEN 'Общеобразовательная организация, осуществляющая образовательную деятельность по адаптированным основным общеобразовательным программам для слепых'
        WHEN 1305 THEN 'Общеобразовательная организация, осуществляющая образовательную деятельность по адаптированным основным общеобразовательным программам для слабовидящих'
        WHEN 1306 THEN 'Общеобразовательная организация, осуществляющая образовательную деятельность по адаптированным основным общеобразовательным программам с тяжелыми нарушениями речи'
        WHEN 1307 THEN 'Общеобразовательная организация, осуществляющая образовательную деятельность по адаптированным основным общеобразовательным программам с нарушениями опорно-двигательного аппарата'
        WHEN 1308 THEN 'Общеобразовательная организация, осуществляющая образовательную деятельность по адаптированным основным общеобразовательным программам с задержкой психического развития'
        WHEN 1309 THEN 'Общеобразовательная организация, осуществляющая образовательную деятельность по адаптированным основным общеобразовательным программам с умственной отсталостью'
        WHEN 1310 THEN 'Общеобразовательная организация, осуществляющая образовательную деятельность по адаптированным основным общеобразовательным программам с расстройствами аутистического спектра'
        WHEN 1311 THEN 'Общеобразовательная организация, осуществляющая образовательную деятельность по адаптированным основным общеобразовательным программам со сложными дефектами'
        WHEN 1312 THEN 'Общеобразовательная организация, осуществляющая образовательную деятельность по адаптированным основным общеобразовательным программам для других обучающихся с ограниченными возможностями здоровья'
        WHEN 14 THEN 'Профессиональная образовательная организация'
        WHEN 15 THEN 'Образовательная организация высшего образования'
        WHEN 16 THEN 'Организация дополнительного образования'
        WHEN 17 THEN 'Организация дополнительного профессионального образования'
        WHEN 21 THEN 'Научная организация'
        WHEN 22 THEN 'Центр психолого-педагогической, медицинской и социальной помощи'
        WHEN 23 THEN 'Организация для детей-сирот и детей, оставшихся без попечения родителей'
        ELSE 'Неизвестный тип организации'
        END;

        TAG_NAME = 'institution:type';
        VAL = NULL;
        SUSPEND;

        TAG_NAME = 'institution:type:code';
        VAL = OBJ_ID;
        SUSPEND;
        TAG_NAME = 'institution:type:name';
        VAL = S1;
        SUSPEND;

    END

    -- Аккредитация
    FOR
        SELECT L17.OBJ_ID, V482.VAL, V483.VAL, V479.VAL, V480.VAL, V481.VAL
        FROM LINKS L17
        JOIN VALL V471 ON V471.OBJ_ID = L17.OBJ_ID AND V471.PARAM_ID = 471 AND V471.IS_DEL = 0 AND V471.LISTVAL_ID IN (1053, 18625)
        JOIN VALD V482 ON V482.OBJ_ID = L17.OBJ_ID AND V482.PARAM_ID = 482 AND V482.IS_DEL = 0
        LEFT JOIN VALD V483 ON V483.OBJ_ID = L17.OBJ_ID AND V483.PARAM_ID = 483 AND V483.IS_DEL = 0
        LEFT JOIN VALS V479 ON V479.OBJ_ID = L17.OBJ_ID AND V479.PARAM_ID = 479 AND V479.IS_DEL = 0
        JOIN VALS V480 ON V480.OBJ_ID = L17.OBJ_ID AND V480.PARAM_ID = 480 AND V480.IS_DEL = 0
        JOIN VALS V481 ON V481.OBJ_ID = L17.OBJ_ID AND V481.PARAM_ID = 481 AND V481.IS_DEL = 0
        WHERE L17.PARENT_ID = :ORG_ID AND L17.OBJ_TYPE_ID = 17 AND L17.DATE_DEL = 0
        ORDER BY V482.VAL DESC
        INTO :OBJ_ID, :D1, :D2, :S1, :S2, :S3
    DO
    BEGIN
        TAG_NAME = 'institution:accreditation';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'institution:accreditation:externalKey';
        VAL = OBJ_ID;
        SUSPEND;
        TAG_NAME = 'institution:accreditation:series';
        VAL = S1;
        SUSPEND;
        TAG_NAME = 'institution:accreditation:number';
        VAL = S2;
        SUSPEND;
        TAG_NAME = 'institution:accreditation:issueDate';
        VAL = D1;
        SUSPEND;
        TAG_NAME = 'institution:accreditation:issuedBy';
        VAL = S3;
        SUSPEND;
        TAG_NAME = 'institution:accreditation:expirationDate';
        VAL = D2;
        SUSPEND;
        TAG_NAME = 'institution:accreditation:deleted';
        VAL = '0';
        SUSPEND;
    END

    -- Лицензия
    FOR
        SELECT L17.OBJ_ID, V482.VAL, V483.VAL, V479.VAL, V480.VAL, V481.VAL
        FROM LINKS L17
        JOIN VALL V471 ON V471.OBJ_ID = L17.OBJ_ID AND V471.PARAM_ID = 471 AND V471.IS_DEL = 0 AND V471.LISTVAL_ID IN (1052, 18624)
        JOIN VALD V482 ON V482.OBJ_ID = L17.OBJ_ID AND V482.PARAM_ID = 482 AND V482.IS_DEL = 0
        LEFT JOIN VALD V483 ON V483.OBJ_ID = L17.OBJ_ID AND V483.PARAM_ID = 483 AND V483.IS_DEL = 0
        LEFT JOIN VALS V479 ON V479.OBJ_ID = L17.OBJ_ID AND V479.PARAM_ID = 479 AND V479.IS_DEL = 0
        JOIN VALS V480 ON V480.OBJ_ID = L17.OBJ_ID AND V480.PARAM_ID = 480 AND V480.IS_DEL = 0
        JOIN VALS V481 ON V481.OBJ_ID = L17.OBJ_ID AND V481.PARAM_ID = 481 AND V481.IS_DEL = 0
        WHERE L17.PARENT_ID = :ORG_ID AND L17.OBJ_TYPE_ID = 17 AND L17.DATE_DEL = 0
        ORDER BY V482.VAL DESC
        INTO :OBJ_ID, :D1, :D2, :S1, :S2, :S3
    DO
    BEGIN
        TAG_NAME = 'institution:license';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'institution:license:externalKey';
        VAL = OBJ_ID;
        SUSPEND;
        TAG_NAME = 'institution:license:series';
        VAL = S1;
        SUSPEND;
        TAG_NAME = 'institution:license:number';
        VAL = S2;
        SUSPEND;
        TAG_NAME = 'institution:license:issueDate';
        VAL = D1;
        SUSPEND;
        TAG_NAME = 'institution:license:issuedBy';
        VAL = S3;
        SUSPEND;
        TAG_NAME = 'institution:license:expirationDate';
        VAL = D2;
        SUSPEND;
        TAG_NAME = 'institution:license:deleted';
        VAL = '0';
        SUSPEND;
    END

    -- Численность учащихся фактическая
    C2 = 0;
    SELECT COUNT(DISTINCT L10.OBJ_ID)
    FROM LINKS L7
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
    JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    WHERE L7.PARENT_ID = :ORG_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    INTO :C2;

    TAG_NAME = 'institution:occupiedPlace';
    VAL = C2;
    SUSPEND;

    -- Численность учащихся нормативная
    C2 = 0;
    SELECT SUM(V503.VAL)
    FROM LINKS L73
    JOIN LINKS L16 ON L16.PARENT_ID = L73.OBJ_ID AND L16.OBJ_TYPE_ID = 16 AND L16.DATE_DEL IS NULL
    JOIN VALI V503 ON V503.OBJ_ID = L16.OBJ_ID AND V503.PARAM_ID = 503 AND V503.IS_DEL = 0
    WHERE L73.PARENT_ID = :ORG_ID AND L73.OBJ_TYPE_ID = 73 AND L73.DATE_DEL IS NULL
    INTO :C2;

    TAG_NAME = 'institution:totalPlace';
    VAL = C2;
    SUSPEND;

    -- Все ОУ - юридические лица (2 = филиал)
    TAG_NAME = 'institution:legal';
    VAL = '1';
    SUSPEND;

    -- Образовательные программы
    TAG_NAME = 'institution:programs';
    VAL = NULL;
    SUSPEND;

    FOR
        -- Школы, сады, колледжи
        SELECT L57.OBJ_ID, V386.VAL
        FROM LINKS L69
        JOIN LINKS L57 on L57.PARENT_ID = L69.OBJ_ID and L57.OBJ_TYPE_ID = 57 and L57.DATE_DEL is null
        JOIN VALS V386 ON V386.OBJ_ID = L57.OBJ_ID AND V386.PARAM_ID = 386 AND V386.IS_DEL = 0
        WHERE L69.PARENT_ID = :ORG_ID and L69.OBJ_TYPE_ID = 69 and L69.DATE_DEL is null
        UNION
        -- УДОД, выборка с учетом подразделений
        SELECT L252.OBJ_ID, V2144.VAL
        FROM LINKS L252
        JOIN VALS V2144 ON V2144.OBJ_ID = L252.OBJ_ID AND V2144.PARAM_ID = 2144 AND V2144.IS_DEL = 0
        LEFT JOIN LINKS L211 on L211.OBJ_ID = L252.PARENT_ID and L211.PARENT_TYPE_ID = 2 and L211.DATE_DEL is null
        WHERE L252.OBJ_TYPE_ID = 252 and L252.PARENT_TYPE_ID in (2, 211) and L252.DATE_DEL is null and (L252.PARENT_ID = :ORG_ID OR L211.PARENT_ID = :ORG_ID)
        INTO :OBJ_ID, :S1
    DO
    BEGIN
        TAG_NAME = 'institution:programs:program';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'institution:programs:program:externalKey';
        VAL = OBJ_ID;
        SUSPEND;
        TAG_NAME = 'institution:programs:program:name';
        VAL = S1;
        SUSPEND;
        -- Связь с ОУ
        TAG_NAME = 'institution:programs:program:institution';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'institution:programs:program:institution:externalKey';
        VAL = ORG_ID;
        SUSPEND;
        -- Тип ОП
        FOR
            SELECT TAG_NAME, VAL
            FROM DG_RC_GET_DICT('institution:programs:program:type', :OBJ_ID, 1832, 1, 2147)
            INTO :TAG_NAME, :VAL
        DO
        BEGIN
            SUSPEND;
        END
        -- Уровень ОП
        FOR
            SELECT TAG_NAME, VAL
            FROM DG_RC_GET_DICT('institution:programs:program:studyLevel', :OBJ_ID, 1594, 1, 2146)
            INTO :TAG_NAME, :VAL
        DO
        BEGIN
            SUSPEND;
        END
        -- Адаптированность ОП
        FOR
            SELECT TAG_NAME, VAL
            FROM DG_RC_GET_DICT('institution:programs:program:adaptability', :OBJ_ID, 2379, 1, 2381)
            INTO :TAG_NAME, :VAL
        DO
        BEGIN
            SUSPEND;
        END
        -- Специализация
        FOR
            SELECT TAG_NAME, VAL
            FROM DG_RC_GET_DICT('institution:programs:program:speciality', :OBJ_ID, 2460, 1)
            INTO :TAG_NAME, :VAL
        DO
        BEGIN
            SUSPEND;
        END
        -- Профессия
        -- Ориентированность (кодирование через TAG)
        FOR
            SELECT TAG_NAME, VAL
            FROM DG_RC_GET_DICT('institution:programs:program:orientation', :OBJ_ID, 390, 1, 2148)
            INTO :TAG_NAME, :VAL
        DO
        BEGIN
            SUSPEND;
        END
        -- Нормативный срок освоения
        S1 = '';
        S1 = (SELECT VAL FROM VALS WHERE OBJ_ID = :OBJ_ID AND PARAM_ID IN (399, 2149) AND IS_DEL = 0);
        TAG_NAME = 'institution:programs:program:durationYears';
        IF(CHAR_LENGTH(S1) = 1 OR CHAR_LENGTH(S1) = 2) THEN
        BEGIN
            S2 = SUBSTRING(S1 FROM 1 FOR 1);
            S3 = SUBSTRING(S1 FROM 2 FOR 1);
            IF(S2 IN ('1', '2', '3', '4', '5', '6', '7', '8', '9') AND S3 IN ('', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9')) THEN
            BEGIN
                VAL = CAST(S1 AS INTEGER);
                SUSPEND;
            END
        END
        -- Здесь только не-удаленные
        TAG_NAME = 'institution:programs:program:deleted';
        VAL = '0';
        SUSPEND;
    END
    -- Отдельно - удаленные ОП

    -- Группы
    TAG_NAME = 'institution:groups';
    VAL = NULL;
    SUSPEND;

    FOR
        SELECT L9.OBJ_ID, C.CAPTION, L8.OBJ_ID
        FROM LINKS L7
        JOIN LINKS L8 on L8.PARENT_ID = L7.OBJ_ID and L8.OBJ_TYPE_ID = 8 and L8.DATE_DEL is null
        JOIN LINKS L9 on L9.PARENT_ID = L8.OBJ_ID and L9.OBJ_TYPE_ID = 9 and L9.DATE_DEL is null
        LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C on 1 = 1
        WHERE L7.PARENT_ID = :ORG_ID and L7.OBJ_TYPE_ID = 7 and L7.DATE_DEL is null
        UNION
        -- УДОД
        SELECT L243.OBJ_ID, C.CAPTION, L243.OBJ_ID
        FROM LINKS L243
        JOIN LINKS L242 on L242.OBJ_ID = L243.PARENT_ID and L242.PARENT_TYPE_ID in (2, 211) and L242.DATE_DEL is null
        LEFT JOIN LINKS L2 on L2.OBJ_ID = L242.PARENT_ID and L2.PARENT_TYPE_ID = 2 and L2.DATE_DEL is null
        LEFT JOIN OBJECT_CAPTION_GET(L242.OBJ_ID) C on 1=1
        WHERE L243.OBJ_TYPE_ID = 243 and L243.PARENT_TYPE_ID = 242 and L243.DATE_DEL is null and (L242.PARENT_ID = :ORG_ID or L2.PARENT_ID = :ORG_ID)
        INTO :OBJ_ID, :S1, :ID8
    DO
    BEGIN
        TAG_NAME = 'institution:groups:group';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'institution:groups:group:externalKey';
        VAL = OBJ_ID;
        SUSPEND;
        TAG_NAME = 'institution:groups:group:name';
        VAL = S1;
        SUSPEND;
        -- Уровень образования
        FOR
            SELECT TAG_NAME, VAL
            FROM DG_RC_GET_DICT('institution:groups:group:studyLevel', :ID8, 49, 1, 2114)
            INTO :TAG_NAME, :VAL
        DO
        BEGIN
            SUSPEND;
        END
        -- Направленность
        FOR
            SELECT TAG_NAME, VAL
            FROM DG_RC_GET_DICT('institution:groups:group:direction', :OBJ_ID, 1655, 0)
            INTO :TAG_NAME, :VAL
        DO
        BEGIN
            SUSPEND;
        END
        -- Форма
        FOR
            SELECT TAG_NAME, VAL
            FROM DG_RC_GET_DICT('institution:groups:group:form', :OBJ_ID, 1768, 0)
            INTO :TAG_NAME, :VAL
        DO
        BEGIN
            SUSPEND;
        END
        -- Ссылка на ОП
        FOR
            -- школы (через ГУП или потоки)
            select distinct L57.PARENT_ID as OBJ_ID 
            from LINKS L10
            join LINKS L256 on L256.OBJ_ID = L10.OBJ_ID and L256.PARENT_TYPE_ID in (256, 46, 347) and L256.DATE_DEL is null
            join LINKS L54 on L54.PARENT_TYPE_ID = 54 and L54.OBJ_ID = L256.PARENT_ID and L54.DATE_DEL is null
            join LINKS L50 on L50.PARENT_TYPE_ID = 50 and L50.OBJ_ID = L54.PARENT_ID and L50.DATE_DEL is null
            join LINKS L57 on L57.PARENT_TYPE_ID = 57 and L57.OBJ_ID = L50.PARENT_ID and L57.DATE_DEL is null
            where L10.PARENT_ID = :OBJ_ID and L10.OBJ_TYPE_ID = 10 and L10.DATE_DEL is null
            union
            -- УДОД
            select distinct L252.PARENT_ID as OBJ_ID 
            from LINKS L54 
            join LINKS L50 on L50.PARENT_TYPE_ID = 50 and L50.OBJ_ID = L54.PARENT_ID and L50.DATE_DEL is null
            join LINKS L252 on L252.PARENT_TYPE_ID = 252 and L252.OBJ_ID = L50.PARENT_ID and L252.DATE_DEL is null
            where L54.PARENT_TYPE_ID = 54 and L54.OBJ_ID = :OBJ_ID and L54.DATE_DEL is null
            INTO :C2
        DO
        BEGIN
            TAG_NAME = 'institution:groups:group:program';
            VAL = NULL;
            SUSPEND;
            TAG_NAME = 'institution:groups:group:program:externalKey';
            VAL = C2;
            SUSPEND;
        END
    END

    -- Предметы - выгружаем список предметов, где по данной организации есть оценки. Список может только пополняться
    TAG_NAME = 'institution:courses';
    VAL = NULL;
    SUSPEND;

    BASE_ID = TRUNC(ORG_ID / 1000000000) * 1000000000;
    FOR
        SELECT DISTINCT V.SUBJECT_ID, C.CAPTION
        FROM VALM V
        LEFT JOIN OBJECT_CAPTION_GET(V.SUBJECT_ID) C on 1 = 1
        WHERE (V.MARK_ID >= :BASE_ID) and (V.MARK_ID < (:BASE_ID + 1000000000))
        INTO :OBJ_ID, :S1
    DO
    BEGIN

        TAG_NAME = 'institution:courses:course';
        VAL = NULL;
        SUSPEND;

        TAG_NAME = 'institution:courses:course:externalKey';
        VAL = :OBJ_ID;
        SUSPEND;
        TAG_NAME = 'institution:courses:course:name';
        VAL = :S1;
        SUSPEND;

        FOR
            -- школы
            SELECT DISTINCT L57.PARENT_ID
            FROM LINKS L49
            JOIN LINKS L50 on L50.PARENT_TYPE_ID = 50 and L50.OBJ_ID = L49.PARENT_ID and L50.DATE_DEL is null
            JOIN LINKS L57 on L57.PARENT_TYPE_ID = 57 and L57.OBJ_ID = L50.PARENT_ID and L57.DATE_DEL is null
            JOIN LINKS L69 on L69.PARENT_TYPE_ID = 69 and L69.OBJ_ID = L57.PARENT_ID and L69.DATE_DEL is null
            JOIN LINKS L2 on L2.PARENT_ID = :ORG_ID and L2.OBJ_ID = L69.PARENT_ID and L2.DATE_DEL is null
            WHERE L49.PARENT_TYPE_ID = 49 and L49.OBJ_ID = :OBJ_ID and L49.DATE_DEL is null
            -- УДОД
            UNION
            SELECT DISTINCT L252.PARENT_ID as ID
            FROM LINKS L49
            JOIN LINKS L50 on L50.PARENT_TYPE_ID = 50 and L50.OBJ_ID = L49.PARENT_ID and L50.DATE_DEL is null
            JOIN LINKS L252 on L252.PARENT_TYPE_ID = 252 and L252.OBJ_ID = L50.PARENT_ID and L252.DATE_DEL is null
            JOIN LINKS L211 on L211.PARENT_TYPE_ID in (211, 2) and L211.OBJ_ID = L252.PARENT_ID and L211.DATE_DEL is null
            LEFT JOIN LINKS L2 on L2.PARENT_TYPE_ID = 2 and L2.OBJ_ID = L211.PARENT_ID and L2.DATE_DEL is null
            WHERE L49.PARENT_TYPE_ID = 49 and L49.OBJ_ID = :OBJ_ID and L49.DATE_DEL is null and (L211.PARENT_ID = :ORG_ID or L2.PARENT_ID = :ORG_ID)
            INTO :ID69
        DO
        BEGIN
            TAG_NAME = 'institution:courses:course:program';
            VAL = NULL;
            SUSPEND;
            TAG_NAME = 'institution:courses:course:program:externalKey';
            VAL = ID69;
            SUSPEND;
        END

    END

    -- Удаленных ОУ у нас не бывает
    TAG_NAME = 'institution:deleted';
    VAL = '0';
    SUSPEND;

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DG_RC_PERSON (
    DATE_START TIMESTAMP,
    DATE_END TIMESTAMP)
RETURNS (
    TAG_NAME VARCHAR(255),
    VAL VARCHAR(1000))
AS
declare variable PERSON_ID bigint;
declare variable PERSON_TYPE_ID bigint;
declare variable S varchar(1000);
declare variable D date;
declare variable LV bigint;
declare variable OBJ_ID bigint;
declare variable PARAM_ID bigint;
declare variable DOC_ID bigint;
declare variable EXT_ID bigint;
begin

    -- Данные содержат: сотрудники, учащиеся, родители учащихся
    FOR
        -- Учащиеся (только основные актуальные в данное время коллективы, выбывшгих и окончивших пропускаем)
        -- Пока без УДОД !
        SELECT DISTINCT L10.OBJ_ID, L10.OBJ_TYPE_ID
        FROM LINKS L2
        JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
        JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        WHERE L2.OBJ_TYPE_ID = 2 AND (L2.PARENT_TYPE_ID IS NULL OR L2.PARENT_TYPE_ID IN (111, 112)) AND L2.DATE_DEL IS NULL
        -- Сотрудники (только актуальные в данный момент)
        UNION
        SELECT DISTINCT L14.OBJ_ID, L14.OBJ_TYPE_ID
        FROM LINKS L2
        JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
        WHERE L2.OBJ_TYPE_ID = 2 AND (L2.PARENT_TYPE_ID IS NULL OR L2.PARENT_TYPE_ID IN (111, 112)) AND L2.DATE_DEL IS NULL
        -- Родственники
        UNION
        SELECT DISTINCT L20.OBJ_ID, L20.OBJ_TYPE_ID
        FROM LINKS L2
        JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
        JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        JOIN LINKS L20 ON L20.PARENT_ID = L10.OBJ_ID AND L20.OBJ_TYPE_ID = 20 AND L20.DATE_DEL IS NULL
        WHERE L2.OBJ_TYPE_ID = 2 AND (L2.PARENT_TYPE_ID IS NULL OR L2.PARENT_TYPE_ID IN (111, 112)) AND L2.DATE_DEL IS NULL
        INTO :PERSON_ID, :PERSON_TYPE_ID
    DO
    BEGIN

        TAG_NAME = 'person';
        VAL = NULL;
        SUSPEND;

        TAG_NAME = 'person:externalKey';
        VAL = PERSON_ID;
        SUSPEND;

        -- Выбираем статические атрибуты
        S = (SELECT VAL FROM VALS WHERE OBJ_ID = :PERSON_ID AND PARAM_ID IN (55, 59, 128) AND IS_DEL = 0);
        IF(S IS NOT NULL) THEN
        BEGIN
            TAG_NAME = 'person:surname';
            VAL = S;
            SUSPEND;
        END

        S = (SELECT VAL FROM VALS WHERE OBJ_ID = :PERSON_ID AND PARAM_ID IN (56, 60, 129) AND IS_DEL = 0);
        IF(S IS NOT NULL) THEN
        BEGIN
            TAG_NAME = 'person:name';
            VAL = S;
            SUSPEND;
        END

        S = (SELECT VAL FROM VALS WHERE OBJ_ID = :PERSON_ID AND PARAM_ID IN (57, 61, 130) AND IS_DEL = 0);
        IF(S IS NOT NULL) THEN
        BEGIN
            TAG_NAME = 'person:patronymic';
            VAL = S;
            SUSPEND;
        END

        LV = (SELECT LISTVAL_ID FROM VALL WHERE OBJ_ID = :PERSON_ID AND PARAM_ID IN (88, 239, 2544) AND IS_DEL = 0);
        IF(LV IS NOT NULL) THEN
        BEGIN
            TAG_NAME = 'person:sex';
            IF(LV = 182) THEN VAL = 'f'; ELSE VAL = 'm';
            SUSPEND;
        END

        D = (SELECT VAL FROM VALD WHERE OBJ_ID = :PERSON_ID AND PARAM_ID IN (89, 241, 143) AND IS_DEL = 0);
        IF(D IS NOT NULL) THEN
        BEGIN
            TAG_NAME = 'person:birthDate';
            VAL = D;
            SUSPEND;
        END

        S = (SELECT VAL FROM VALS WHERE OBJ_ID = :PERSON_ID AND PARAM_ID IN (1409, 2455, 2365) AND IS_DEL = 0);
        IF(S IS NOT NULL) THEN
        BEGIN
            TAG_NAME = 'person:snils';
            VAL = S;
            SUSPEND;
        END

        -- Гражданство
        IF(PERSON_TYPE_ID = 10) THEN PARAM_ID = 91; ELSE IF(PERSON_TYPE_ID = 14) THEN PARAM_ID = 243; ELSE PARAM_ID = 1559;
        FOR
            SELECT TAG_NAME, VAL
            FROM DG_RC_GET_DICT('person:nationality', :PERSON_ID, :PARAM_ID, 1)
            INTO :TAG_NAME, :VAL
        DO
        BEGIN
            SUSPEND;
        END

        -- Идентифицирующие документы
        FOR
            SELECT LD.OBJ_ID
            FROM LINKS LD
            WHERE LD.PARENT_ID = :PERSON_ID AND LD.OBJ_TYPE_ID = 79 AND LD.DATE_DEL IS NULL
            INTO :OBJ_ID
        DO
        BEGIN
            TAG_NAME = 'person:identityDocument';
            VAL = NULL;
            SUSPEND;

            TAG_NAME = 'person:identityDocument:externalKey';
            VAL = OBJ_ID;
            SUSPEND;

            S = (SELECT VAL FROM VALS WHERE OBJ_ID = :OBJ_ID AND PARAM_ID = 442 AND IS_DEL = 0);
            IF(S IS NOT NULL) THEN
            BEGIN
                TAG_NAME = 'person:identityDocument:series';
                VAL = S;
                SUSPEND;
            END

            S = (SELECT VAL FROM VALS WHERE OBJ_ID = :OBJ_ID AND PARAM_ID = 559 AND IS_DEL = 0);
            IF(S IS NOT NULL) THEN
            BEGIN
                TAG_NAME = 'person:identityDocument:number';
                VAL = S;
                SUSPEND;
            END

            D = (SELECT VAL FROM VALD WHERE OBJ_ID = :OBJ_ID AND PARAM_ID = 560 AND IS_DEL = 0);
            IF(D IS NOT NULL) THEN
            BEGIN
                TAG_NAME = 'person:identityDocument:issueDate';
                VAL = D;
                SUSPEND;
            END

            S = (SELECT VAL FROM VALS WHERE OBJ_ID = :OBJ_ID AND PARAM_ID = 562 AND IS_DEL = 0);
            IF(S IS NOT NULL) THEN
            BEGIN
                TAG_NAME = 'person:identityDocument:issuedBy';
                VAL = S;
                SUSPEND;
            END

            D = (SELECT VAL FROM VALD WHERE OBJ_ID = :OBJ_ID AND PARAM_ID = 561 AND IS_DEL = 0);
            IF(D IS NOT NULL) THEN
            BEGIN
                TAG_NAME = 'person:identityDocument:expireDate';
                VAL = D;
                SUSPEND;
            END

            S = (
                SELECT R.VAL
                FROM VALL L
                JOIN LISTVALS LV ON LV.LISTVAL_ID = L.LISTVAL_ID
                JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
                WHERE L.OBJ_ID = :OBJ_ID AND L.PARAM_ID = 441 AND L.IS_DEL = 0
            );
            IF(S IS NOT NULL) THEN
            BEGIN
                TAG_NAME = 'person:identityDocument:type';
                VAL = S;
                SUSPEND;
            END

            TAG_NAME = 'person:identityDocument:deleted';
            VAL = '0';
            SUSPEND;
        END

        -- Удаленные документы
        FOR
            SELECT LD.OBJ_ID
            FROM LINKS LD
            WHERE LD.PARENT_ID = :PERSON_ID AND LD.OBJ_TYPE_ID = 79 AND LD.DATE_DEL IS NOT NULL
            INTO :OBJ_ID
        DO
        BEGIN
            TAG_NAME = 'person:identityDocument';
            VAL = NULL;
            SUSPEND;

            TAG_NAME = 'person:identityDocument:externalKey';
            VAL = OBJ_ID;
            SUSPEND;

            TAG_NAME = 'person:identityDocument:deleted';
            VAL = '1';
            SUSPEND;
        END

        -- Адреса
        TAG_NAME = 'person:addresses';
        VAL = NULL;
        SUSPEND;

        IF(PERSON_TYPE_ID = 10) THEN PARAM_ID = 111; ELSE IF(PERSON_TYPE_ID = 14) THEN PARAM_ID = 262; ELSE PARAM_ID = 1561;
        FOR
            SELECT TAG_NAME, VAL
            FROM DG_RC_GET_ADDRESS('person:addresses:registrationAddress', :PERSON_ID, :PARAM_ID)
            INTO :TAG_NAME, :VAL
        DO
        BEGIN
            SUSPEND;
        END

        IF(PERSON_TYPE_ID = 10) THEN PARAM_ID = 103; ELSE IF(PERSON_TYPE_ID = 14) THEN PARAM_ID = 255; ELSE PARAM_ID = 147;
        FOR
            SELECT TAG_NAME, VAL
            FROM DG_RC_GET_ADDRESS('person:addresses:residenceAddress', :PERSON_ID, :PARAM_ID)
            INTO :TAG_NAME, :VAL
        DO
        BEGIN
            SUSPEND;
        END

        IF(PERSON_TYPE_ID = 10) THEN PARAM_ID = 2357; ELSE IF(PERSON_TYPE_ID = 14) THEN PARAM_ID = NULL; ELSE PARAM_ID = NULL;
        FOR
            -- Регистрация по месту пребывания
            SELECT TAG_NAME, VAL
            FROM DG_RC_GET_ADDRESS('person:addresses:stayAddress', :PERSON_ID, :PARAM_ID)
            WHERE :PARAM_ID IS NOT NULL
            INTO :TAG_NAME, :VAL
        DO
        BEGIN
            SUSPEND;
        END

        -- Только для учащихся
        IF(PERSON_TYPE_ID = 10) THEN 
        BEGIN

            -- Представители учащихся (тут может быть проблема при повторном добавлении родственника - EXT_OBJ_ID будет новый)
            FOR
                SELECT DISTINCT L20.OBJ_ID, L20.EXT_OBJ_ID
                FROM LINKS L20
                WHERE L20.PARENT_ID = :PERSON_ID AND L20.OBJ_TYPE_ID = 20 AND L20.DATE_DEL IS NULL
                INTO :OBJ_ID, :EXT_ID
            DO
            BEGIN

                TAG_NAME = 'person:representative';
                VAL = NULL;
                SUSPEND;

                TAG_NAME = 'person:representative:externalKey';
                VAL = OBJ_ID;
                SUSPEND;

                TAG_NAME = 'person:representative:person';
                VAL = NULL;
                SUSPEND;

                TAG_NAME = 'person:representative:person:externalKey';
                VAL = OBJ_ID;
                SUSPEND;

                -- Подтверждающий документ
                FOR
                    SELECT L294.OBJ_ID
                    FROM LINKS L294
                    WHERE L294.PARENT_ID = :OBJ_ID AND L294.OBJ_TYPE_ID = 294 AND L294.DATE_DEL IS NULL
                    INTO :DOC_ID
                DO
                BEGIN

                    TAG_NAME = 'person:representative:relationDocument';
                    VAL = NULL;
                    SUSPEND;

                    TAG_NAME = 'person:representative:relationDocument:externalKey';
                    VAL = OBJ_ID;
                    SUSPEND;

                    S = (SELECT VAL FROM VALS WHERE OBJ_ID = :DOC_ID AND PARAM_ID = 2367 AND IS_DEL = 0);
                    IF(S IS NOT NULL) THEN
                    BEGIN
                        TAG_NAME = 'person:representative:relationDocument:number';
                        VAL = S;
                        SUSPEND;
                    END

                    D = (SELECT VAL FROM VALD WHERE OBJ_ID = :DOC_ID AND PARAM_ID = 2368 AND IS_DEL = 0);
                    IF(D IS NOT NULL) THEN
                    BEGIN
                        TAG_NAME = 'person:representative:relationDocument:issueDate';
                        VAL = D;
                        SUSPEND;
                    END

                    S = (SELECT VAL FROM VALS WHERE OBJ_ID = :DOC_ID AND PARAM_ID = 2369 AND IS_DEL = 0);
                    IF(S IS NOT NULL) THEN
                    BEGIN
                        TAG_NAME = 'person:representative:relationDocument:issuedBy';
                        VAL = S;
                        SUSPEND;
                    END

                END

                -- Степень родства
                IF(EXT_ID IS NOT NULL) THEN
                BEGIN
                    FOR
                        SELECT TAG_NAME, VAL
                        FROM DG_RC_GET_DICT('person:representative:type', :EXT_ID, 1573, 1)
                        INTO :TAG_NAME, :VAL
                    DO
                    BEGIN
                        SUSPEND;
                    END
                END

                TAG_NAME = 'person:representative:deleted';
                VAL = '0';
                SUSPEND;

            END

            -- Удаленные представители (проверяем, что представитель не был добавлен снова)
            FOR
                SELECT L20.OBJ_ID
                FROM LINKS L20
                WHERE L20.PARENT_ID = :PERSON_ID AND L20.OBJ_TYPE_ID = 20 AND L20.DATE_DEL IS NOT NULL
                    AND NOT EXISTS (SELECT FIRST 1 1 FROM LINKS L20X WHERE L20X.PARENT_ID = :PERSON_ID AND L20X.OBJ_ID = L20.OBJ_ID AND L20X.DATE_DEL IS NULL)
                INTO :OBJ_ID
            DO
            BEGIN

                TAG_NAME = 'person:representative';
                VAL = NULL;
                SUSPEND;

                TAG_NAME = 'person:representative:externalKey';
                VAL = OBJ_ID;
                SUSPEND;

                TAG_NAME = 'person:representative:deleted';
                VAL = '1';
                SUSPEND;

            END

            -- Трудная жизненная ситуация
            FOR
                SELECT TAG_NAME, VAL
                FROM DG_RC_GET_DICT('person:hardSituation', :PERSON_ID, 2364, 1)
                INTO :TAG_NAME, :VAL
            DO
            BEGIN
                SUSPEND;
            END

            -- Здоровье
            TAG_NAME = 'person:health';
            VAL = NULL;
            SUSPEND;

            -- Группа здоровья
            FOR
                SELECT TAG_NAME, VAL
                FROM DG_RC_GET_DICT('person:health:group', :PERSON_ID, 208, 1)
                INTO :TAG_NAME, :VAL
            DO
            BEGIN
                SUSPEND;
            END

            -- Категория для занятий спортом
            FOR
                SELECT TAG_NAME, VAL
                FROM DG_RC_GET_DICT('person:health:sportGroup', :PERSON_ID, 176, 1)
                INTO :TAG_NAME, :VAL
            DO
            BEGIN
                SUSPEND;
            END

            -- Инвалидность
            FOR
                SELECT OBJ_ID
                FROM LINKS
                WHERE PARENT_ID = :PERSON_ID AND OBJ_TYPE_ID = 295 AND DATE_DEL IS NULL
                INTO :OBJ_ID
            DO
            BEGIN

                TAG_NAME = 'person:disability';
                VAL = NULL;
                SUSPEND;

                FOR
                    SELECT TAG_NAME, VAL
                    FROM DG_RC_GET_DICT('person:disability:group', :OBJ_ID, 2373, 1)
                    INTO :TAG_NAME, :VAL
                DO
                BEGIN
                    SUSPEND;
                END

                FOR
                    SELECT TAG_NAME, VAL
                    FROM DG_RC_GET_DICT('person:disability:category', :OBJ_ID, 2374, 1)
                    INTO :TAG_NAME, :VAL
                DO
                BEGIN
                    SUSPEND;
                END

                D = (SELECT VAL FROM VALD WHERE OBJ_ID = :OBJ_ID AND PARAM_ID = 2375 AND IS_DEL = 0);
                IF(D IS NOT NULL) THEN
                BEGIN
                    TAG_NAME = 'person:disability:expirationDate';
                    VAL = D;
                    SUSPEND;
                END

            END

            -- Адаптивная категория
            FOR
                SELECT TAG_NAME, VAL
                FROM DG_RC_GET_DICT('person:health:needAdapt', :PERSON_ID, 2377, 1)
                INTO :TAG_NAME, :VAL
            DO
            BEGIN
                SUSPEND;
            END

            -- Адаптивная категория
            FOR
                SELECT TAG_NAME, VAL
                FROM DG_RC_GET_DICT('person:health:needTreatment', :PERSON_ID, 2378, 1)
                INTO :TAG_NAME, :VAL
            DO
            BEGIN
                SUSPEND;
            END

        END

        TAG_NAME = 'person:deleted';
        VAL = '0';
        SUSPEND;

    END

    -- Удаленные данные
    -- Ученики или удаленные, или выбывшие

    -- Учителя или в уволенных, или совсем удаленные
    FOR
        SELECT DISTINCT L14.OBJ_ID
        FROM LINKS L2
        JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NOT NULL
            AND NOT EXISTS (SELECT FIRST 1 1 FROM LINKS L14X WHERE L14X.PARENT_ID = L2.OBJ_ID AND L14X.OBJ_ID = L14.OBJ_ID AND L14X.DATE_DEL IS NULL)
        WHERE L2.OBJ_TYPE_ID = 2 AND (L2.PARENT_TYPE_ID IS NULL OR L2.PARENT_TYPE_ID IN (111, 112)) AND L2.DATE_DEL IS NULL
        INTO :PERSON_ID
    DO
    BEGIN
        TAG_NAME = 'person';
        VAL = NULL;
        SUSPEND;

        TAG_NAME = 'person:externalKey';
        VAL = PERSON_ID;
        SUSPEND;

        TAG_NAME = 'person:deleted';
        VAL = '1';
        SUSPEND;
    END

    -- Родственники только удаляются

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DISCIPLINE_ADD (
    I$OBJ_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT)
AS
DECLARE VARIABLE V$I BIGINT;
BEGIN
    OBJ_ID = :I$OBJ_ID;

    SELECT TYPE_ID
    FROM OBJECTS
    WHERE OBJ_ID = :I$OBJ_ID
    INTO :V$I;

    IF (:V$I <> 201) THEN
    BEGIN
        INSERT INTO OBJECTS (TYPE_ID)
        VALUES (201)
        RETURNING OBJ_ID
        INTO :OBJ_ID;

        SELECT BLOB_ID
        FROM VAL_ADD(1766, :OBJ_ID, :I$OBJ_ID)
        INTO :V$I;
    END

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DISCIPLINE_CHECK (
    I$PARENT_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    CAPTION VARCHAR(4000))
AS
DECLARE VARIABLE V$I BIGINT;
BEGIN
    IF ((SELECT TYPE_ID
         FROM OBJECTS
         WHERE OBJ_ID = :I$OBJ_ID) = 201) THEN
    BEGIN
        SELECT I
        FROM VAL_GET(:I$OBJ_ID, 1766, 0, :I$USER_ID)
        INTO :I$OBJ_ID;
    END

    SELECT I
    FROM VAL_GET(:I$OBJ_ID, 1750, 0, :I$USER_ID)
    INTO :V$I;
    -- ERROR_TEXT message
    IF (:V$I IN (3406, 3408) AND EXISTS (
        SELECT FIRST 1 1
        FROM LINKS
        WHERE PARENT_ID = :I$PARENT_ID
          AND OBJ_TYPE_ID = 201
          AND DATE_DEL IS NULL
          AND (
            SELECT I
            FROM VAL_GET((
                SELECT I
                FROM VAL_GET(OBJ_ID, 1766, 0, :I$USER_ID)), 1750, 0, :I$USER_ID)) = :V$I)
    ) THEN
    BEGIN
        SELECT V
        FROM VAL_GET((
            SELECT I
            FROM VAL_GET(:I$PARENT_ID, 1766, 0, :I$USER_ID)), 1750, 0, :I$USER_ID)
        INTO :CAPTION;

        CAPTION = :CAPTION||' может иметь только один пункт данного Вида учебной деятельности.';
        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DISCIPLINE_INDEX_SET (
    I$PARENT_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$NORD INTEGER,
    I$USER_ID BIGINT)
RETURNS (
    OBJ_CAPTION VARCHAR(4000))
AS
DECLARE VARIABLE V$I BIGINT;
DECLARE VARIABLE V$INDEX_VAL VARCHAR(4000);
DECLARE VARIABLE V$TYPE_ID BIGINT;
DECLARE VARIABLE V$PRIOR_I BIGINT;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$CNT SMALLINT;
BEGIN
    SELECT TYPE_ID
    FROM OBJECTS
    WHERE OBJ_ID = :I$PARENT_ID
    INTO :V$TYPE_ID;

    V$INDEX_VAL = '';
    V$CNT = 0;

    IF (:V$TYPE_ID = 201) THEN
    BEGIN
        SELECT I, TRIM(
            CASE I
                WHEN 3404 THEN 'МДК.'
                WHEN 3406 THEN 'УП.'
                WHEN 3408 THEN 'ПП.'
                ELSE ''
            END)
        FROM VAL_GET((
            SELECT I
            FROM VAL_GET(:I$OBJ_ID, 1766, 0, :I$USER_ID)), 1750, 0, :I$USER_ID)
        INTO :V$I, :V$INDEX_VAL;
    END

    IF (:V$INDEX_VAL <> '') THEN
    BEGIN
        IF (:V$I <> 3404 AND :I$NORD = 1) THEN
        BEGIN
            SELECT COUNT(1)
            FROM LINKS
            WHERE PARENT_ID = :I$PARENT_ID
              AND OBJ_TYPE_ID = 201
              AND DATE_DEL IS NULL
              AND (SELECT I FROM VAL_GET((
                      SELECT I
                      FROM VAL_GET(OBJ_ID, 1766, 0, :I$USER_ID)), 1750, 0, :I$USER_ID)) = :V$I
            INTO :V$CNT;
        END
        --IF (:V$I = 3404) THEN
        BEGIN
            SELECT V
            FROM VAL_GET(:I$PARENT_ID, 1765, 0, :I$USER_ID)
            INTO :OBJ_CAPTION;

            V$I = CHAR_LENGTH(:OBJ_CAPTION);
            WHILE (:V$I > 0 AND SUBSTRING(:OBJ_CAPTION FROM :V$I FOR 1) <> '.') DO
            BEGIN
                V$I = :V$I - 1;
            END
            IF (:V$I < CHAR_LENGTH(:OBJ_CAPTION)) THEN
            BEGIN
                V$INDEX_VAL = :V$INDEX_VAL||SUBSTRING(:OBJ_CAPTION FROM :V$I + 1 FOR 10);
            END
        END
    END
    ELSE
    BEGIN
        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:I$PARENT_ID,NULL,NULL,:I$USER_ID)
        INTO :OBJ_CAPTION;

        V$I = CHAR_LENGTH(:OBJ_CAPTION);
        WHILE (:V$I > 0 AND SUBSTRING(:OBJ_CAPTION FROM :V$I FOR 1) <> '.') DO
        BEGIN
            V$I = :V$I - 1;
        END
        V$I = :V$I - 1;

        IF (:V$I > 1) THEN
        BEGIN
            WHILE (:V$I > 0 AND SUBSTRING(:OBJ_CAPTION FROM :V$I FOR 1) <> ' ') DO
            BEGIN
                V$INDEX_VAL = SUBSTRING(:OBJ_CAPTION FROM :V$I FOR 1)||:V$INDEX_VAL;
                V$I = :V$I - 1;
            END
        END
    END

    IF (:V$CNT <> 1) THEN
    BEGIN
        V$INDEX_VAL = :V$INDEX_VAL||'.';
        IF (:I$NORD < 10) THEN
        BEGIN
            V$INDEX_VAL = :V$INDEX_VAL||'0';
        END
        V$INDEX_VAL = :V$INDEX_VAL||:I$NORD;
    END

    SELECT BLOB_ID
    FROM VAL_ADD(1765, :I$OBJ_ID, :V$INDEX_VAL)
    INTO :V$I;

    SELECT CAPTION
    FROM OBJECT_CAPTION_GET(:I$OBJ_ID,NULL,NULL,:I$USER_ID)
    INTO :OBJ_CAPTION;

    SUSPEND;
    -- cascad index set
    V$PRIOR_I = -1;

    FOR SELECT OBJ_ID, (
            SELECT I
            FROM VAL_GET((
                SELECT I
                FROM VAL_GET(OBJ_ID, 1766, 0, :I$USER_ID)), 1750, 0, :I$USER_ID))
        FROM LINKS
        WHERE PARENT_ID = :I$OBJ_ID
          AND OBJ_TYPE_ID = 201
          AND DATE_DEL IS NULL
        ORDER BY (SELECT CAPTION FROM OBJECT_CAPTION_GET(OBJ_ID, NULL, NULL, :I$USER_ID))
        INTO :V$OBJ_ID, :V$I
    DO
    BEGIN
        IF (:V$PRIOR_I <> :V$I) THEN
        BEGIN
            V$PRIOR_I = :V$I;
            I$NORD = 1;
        END

        SELECT OBJ_CAPTION
        FROM DISCIPLINE_INDEX_SET(:I$OBJ_ID, :V$OBJ_ID, :I$NORD, :I$USER_ID)
        INTO :OBJ_CAPTION;

        I$NORD = :I$NORD + 1;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DISCIPLINE_LIST (
    I$OBJ_ID BIGINT,
    I$TYPE_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    OBJ_CAPTION VARCHAR(4000))
AS
DECLARE VARIABLE V$PLANE_TYPE_ID BIGINT;
BEGIN
    IF (:I$TYPE_ID = 185) THEN
    BEGIN
        SELECT I FROM VAL_GET(:I$OBJ_ID, 1608,0,:I$USER_ID)
        INTO :V$PLANE_TYPE_ID;
    END

    FOR SELECT OBJ_ID,
            (SELECT CAPTION FROM OBJECT_CAPTION_GET(OBJ_ID,NULL,NULL,:I$USER_ID)) OBJ_CAPTION
        FROM (
            SELECT
                L197.OBJ_ID,
                (SELECT I FROM VAL_GET(OBJ_ID, 1750,0,:I$USER_ID)) DISCIPLINE_VID_ID
            FROM LINKS L197
            WHERE L197.OBJ_TYPE_ID = 197
              AND L197.PARENT_TYPE_ID = 193
              AND L197.DATE_DEL IS NULL)
        WHERE ((:I$TYPE_ID = 185 AND
                  ((DISCIPLINE_VID_ID = 3401 AND :V$PLANE_TYPE_ID BETWEEN 5241 AND 5244)
                OR (DISCIPLINE_VID_ID = 3402 AND :V$PLANE_TYPE_ID = 5246)
                OR (DISCIPLINE_VID_ID = 3403 AND :V$PLANE_TYPE_ID = 5247)
                OR (DISCIPLINE_VID_ID = 3409 AND :V$PLANE_TYPE_ID = 5248)
                OR (DISCIPLINE_VID_ID = 3411 AND :V$PLANE_TYPE_ID = 5249)
                OR NOT(:V$PLANE_TYPE_ID BETWEEN 5241 AND 5249)))
           OR (:I$TYPE_ID = 201 AND DISCIPLINE_VID_ID IN (3404, 3406, 3408)))
           AND OBJ_ID NOT IN (
               SELECT
                   (SELECT I FROM VAL_GET(OBJ_ID, 1766,0,:I$USER_ID))
               FROM LINKS L
               WHERE L.PARENT_ID = :I$OBJ_ID
                 AND L.DATE_DEL IS NULL
                 AND L.OBJ_TYPE_ID IN (185, 201))
        ORDER BY OBJ_CAPTION
        INTO :OBJ_ID, :OBJ_CAPTION
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DISCIPLINE_LOADING_ADD (
    I$OBJ_ID BIGINT,
    I$USER_ID BIGINT,
    I$IS_NEW SMALLINT = 0,
    I$VAL1_ID BIGINT = NULL,
    VAL4 INTEGER = NULL,
    VAL5 INTEGER = NULL,
    VAL6 INTEGER = NULL,
    VAL7 INTEGER = NULL,
    VAL8 INTEGER = NULL,
    VAL9 INTEGER = NULL,
    VAL10_ID BIGINT = NULL,
    VAL11 INTEGER = NULL,
    VAL12_ID BIGINT = NULL,
    VAL13 INTEGER = NULL,
    VAL14_ID BIGINT = NULL,
    VAL15 INTEGER = NULL,
    VAL16_ID BIGINT = NULL,
    VAL17 INTEGER = NULL,
    VAL18_ID BIGINT = NULL,
    VAL19 INTEGER = NULL,
    VAL20_ID BIGINT = NULL,
    VAL21 INTEGER = NULL,
    VAL22_ID BIGINT = NULL,
    VAL23 INTEGER = NULL,
    VAL24_ID BIGINT = NULL,
    VAL25 INTEGER = NULL,
    VAL26_ID BIGINT = NULL,
    VAL27 INTEGER = NULL,
    VAL28_ID BIGINT = NULL,
    I$VAL29 SMALLINT = NULL)
RETURNS (
    VAL1 VARCHAR(4000),
    VAL1_ID BIGINT,
    BRUSHCOLOR CHAR(7),
    LOADING_ID BIGINT,
    VAL29 SMALLINT)
AS
DECLARE VARIABLE V$I BIGINT;
DECLARE VARIABLE V$COST SMALLINT;
DECLARE VARIABLE V$VAL9 INTEGER;
DECLARE VARIABLE V$VAL10 BIGINT;
DECLARE VARIABLE V$VAL11 INTEGER;
DECLARE VARIABLE V$VAL12 BIGINT;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$BLOB_ID BIGINT;
DECLARE VARIABLE V$IS_DEL SMALLINT;
BEGIN
    IF (:I$IS_NEW = 1) THEN
    BEGIN
        SELECT OBJ_ID
        FROM OBJECT_ADD(:I$OBJ_ID, 203)
        INTO :LOADING_ID;
        -- 1
        SELECT BLOB_ID
        FROM VAL_ADD(1769, :LOADING_ID, IIF(:I$VAL1_ID = 780, 782, 780))
        INTO :V$I;

        SELECT I, V_LONG
        FROM VAL_GET(:LOADING_ID, 1769, 0, :I$USER_ID)
        INTO :VAL1_ID, :VAL1;

        BRUSHCOLOR = IIF(:VAL1_ID = 780, '$00FFFF', '$F1E5DB');
        -- 29
        VAL29 = 0;
        SELECT BLOB_ID
        FROM VAL_ADD(1772, :LOADING_ID, 3)
        INTO :V$I;

        SUSPEND;
        EXIT;
    END
    -- 1
    SELECT BLOB_ID
    FROM VAL_ADD(1769, :I$OBJ_ID, :I$VAL1_ID)
    INTO :V$I;
    -- 4
    SELECT BLOB_ID
    FROM VAL_ADD(1770, :I$OBJ_ID, COALESCE(:VAL4, 0))
    INTO :V$I;
    -- 5
    SELECT BLOB_ID
    FROM VAL_ADD(1771, :I$OBJ_ID, COALESCE(:VAL5, 0))
    INTO :V$I;
    -- 6
    SELECT BLOB_ID
    FROM VAL_ADD(1773, :I$OBJ_ID, COALESCE(:VAL6, 0))
    INTO :V$I;
    -- 7
    SELECT BLOB_ID
    FROM VAL_ADD(1774, :I$OBJ_ID, COALESCE(:VAL7, 0))
    INTO :V$I;
    -- 8
    SELECT BLOB_ID
    FROM VAL_ADD(1775, :I$OBJ_ID, COALESCE(:VAL8, 0))
    INTO :V$I;
    -- 9 - 28 obj_id = 205
    V$I = 1;

    WHILE (:V$I <= 5) DO
    BEGIN
        V$VAL9  = CASE :V$I WHEN 1 THEN :VAL9     WHEN 2 THEN :VAL13    WHEN 3 THEN :VAL17    WHEN 4 THEN :VAL21    WHEN 5 THEN :VAL25    END;
        V$VAL10 = CASE :V$I WHEN 1 THEN :VAL10_ID WHEN 2 THEN :VAL14_ID WHEN 3 THEN :VAL18_ID WHEN 4 THEN :VAL22_ID WHEN 5 THEN :VAL26_ID END;
        V$VAL11 = CASE :V$I WHEN 1 THEN :VAL11    WHEN 2 THEN :VAL15    WHEN 3 THEN :VAL19    WHEN 4 THEN :VAL23    WHEN 5 THEN :VAL27    END;
        V$VAL12 = CASE :V$I WHEN 1 THEN :VAL12_ID WHEN 2 THEN :VAL16_ID WHEN 3 THEN :VAL20_ID WHEN 4 THEN :VAL24_ID WHEN 5 THEN :VAL28_ID END;

        V$OBJ_ID = NULL;
        -- add object type_id = 205
        SELECT L205.OBJ_ID
        FROM LINKS L205
        WHERE L205.PARENT_ID = :I$OBJ_ID
          AND L205.OBJ_TYPE_ID = 205
          AND L205.DATE_DEL IS NULL
          AND (SELECT I
               FROM VAL_GET(L205.OBJ_ID, 1776, 0, :I$USER_ID)) = :V$I + 48
        INTO :V$OBJ_ID;

        IF (:V$OBJ_ID IS NULL AND (:V$VAL9 IS NOT NULL OR :V$VAL10 IS NOT NULL OR
            :V$VAL11 IS NOT NULL OR :V$VAL12 IS NOT NULL OR :V$VAL9 <> 0 OR :V$VAL11 <> 0)) THEN
        BEGIN
            SELECT OBJ_ID
            FROM OBJECT_ADD(:I$OBJ_ID, 205)
            INTO :V$OBJ_ID;
            SELECT BLOB_ID
            FROM VAL_ADD(1776, :V$OBJ_ID, :V$I + 48)
            INTO :V$BLOB_ID;
        END
        IF (:V$OBJ_ID IS NOT NULL) THEN
        BEGIN
            -- 9
            SELECT BLOB_ID
            FROM VAL_ADD(1777, :V$OBJ_ID, COALESCE(:V$VAL9, 0))
            INTO :V$BLOB_ID;
            -- 10
            V$IS_DEL = IIF(:V$VAL10 < 0, IIF((SELECT IS_EXISTS FROM VAL_GET(:V$OBJ_ID, 1778)) > 0, 1, 2), 0);
            IF (:V$IS_DEL < 2) THEN
            BEGIN
                SELECT BLOB_ID
                FROM VAL_ADD(1778, :V$OBJ_ID, IIF(:V$VAL10 IS NULL, NULL, ABS(:V$VAL10)), NULL, :V$IS_DEL)
                INTO :V$BLOB_ID;
            END
            -- 11
            SELECT BLOB_ID
            FROM VAL_ADD(1779, :V$OBJ_ID, COALESCE(:V$VAL11, 0))
            INTO :V$BLOB_ID;
            -- 12
            V$IS_DEL = IIF(:V$VAL12 < 0, IIF((SELECT IS_EXISTS FROM VAL_GET(:V$OBJ_ID, 1780)) > 0, 1, 2), 0);
            IF (:V$IS_DEL < 2) THEN
            BEGIN
                SELECT BLOB_ID
                FROM VAL_ADD(1780, :V$OBJ_ID, IIF(:V$VAL12 IS NULL, NULL, ABS(:V$VAL12)), NULL, :V$IS_DEL)
                INTO :V$BLOB_ID;
            END
        END

        V$I = :V$I + 1;
    END
    -- 29
    SELECT I, COST
    FROM VAL_GET(:I$OBJ_ID, 1772, 0, :I$USER_ID)
    INTO :V$I, :V$COST;

    IF (:V$COST <> :I$VAL29) THEN
    BEGIN
        SELECT BLOB_ID
        FROM VAL_ADD(1772, :I$OBJ_ID, IIF(:V$I = 2, 3, 2))
        INTO :V$I;
    END

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DISCIPLINE_LOADING_LIST (
    I$OBJ_ID BIGINT NOT NULL,
    I$TYPE_ID BIGINT = NULL,
    I$USER_ID BIGINT = 1)
RETURNS (
    OBJ_ID BIGINT,
    TYPE_ID BIGINT,
    VAL1 VARCHAR(4000),
    VAL1_ID BIGINT,
    VAL2 VARCHAR(4000),
    VAL3 VARCHAR(4000),
    VAL4 INTEGER,
    VAL5 INTEGER,
    VAL6 INTEGER,
    VAL7 INTEGER,
    VAL8 INTEGER,
    VAL9 INTEGER,
    VAL10_ID BIGINT,
    VAL10 VARCHAR(40),
    VAL11 INTEGER,
    VAL12_ID BIGINT,
    VAL12 VARCHAR(40),
    VAL13 INTEGER,
    VAL14_ID BIGINT,
    VAL14 VARCHAR(40),
    VAL15 INTEGER,
    VAL16_ID BIGINT,
    VAL16 VARCHAR(40),
    VAL17 INTEGER,
    VAL18_ID BIGINT,
    VAL18 VARCHAR(40),
    VAL19 INTEGER,
    VAL20_ID BIGINT,
    VAL20 VARCHAR(40),
    VAL21 INTEGER,
    VAL22_ID BIGINT,
    VAL22 VARCHAR(40),
    VAL23 INTEGER,
    VAL24_ID BIGINT,
    VAL24 VARCHAR(40),
    VAL25 INTEGER,
    VAL26_ID BIGINT,
    VAL26 VARCHAR(40),
    VAL27 INTEGER,
    VAL28_ID BIGINT,
    VAL28 VARCHAR(40),
    VAL29 SMALLINT,
    COLOR INTEGER,
    BRUSHCOLOR CHAR(7),
    IS_LAST SMALLINT,
    LOADING_ID BIGINT,
    LEVEL_NUM SMALLINT)
AS
DECLARE VARIABLE V$I BIGINT;
DECLARE VARIABLE V$KURS INTEGER;
DECLARE VARIABLE V$VAL9 INTEGER;
DECLARE VARIABLE V$VAL10_ID BIGINT;
DECLARE VARIABLE V$VAL10 VARCHAR(40);
DECLARE VARIABLE V$VAL11 INTEGER;
DECLARE VARIABLE V$VAL12_ID BIGINT;
DECLARE VARIABLE V$VAL12 VARCHAR(40);
BEGIN
    FOR SELECT
            OBJ_ID,
            TYPE_ID,
            IIF (TYPE_ID = 201, (
                SELECT V
                FROM VAL_GET(OBJ_ID, 1765, 0, :I$USER_ID)), '') INDEX_VAL,
            IIF (TYPE_ID = 201, (
                SELECT V
                FROM VAL_GET((
                    SELECT I
                    FROM VAL_GET(OBJ_ID, 1766, 0, :I$USER_ID)), 1751, 0, :I$USER_ID)), OBJ_CAPTION) OBJ_CAPTION,
            COLOR,
            LEVEL_NUM,
            IS_LAST
        FROM (
            SELECT
                DT.*,
                IIF(DT.TYPE_ID = 201 AND DT.HAS_CHILD = 0 AND (
                    SELECT I
                    FROM VAL_GET((
                        SELECT I
                        FROM VAL_GET(DT.OBJ_ID, 1766)), 1750)) <> 3403, 1, 0) IS_LAST
            FROM (
                SELECT
                    DT.OBJ_ID,
                    DT.TYPE_ID,
                    DT.OBJ_CAPTION,
                    DT.COLOR,
                    DT.LEVEL_NUM,
                    IIF(EXISTS(
                        SELECT FIRST 1 1
                        FROM OBJECT_TREE(DT.OBJ_ID) OT
                        WHERE OT.TYPE_ID = 201
                          AND OT.IS_DEL = 0
                          AND (
                            SELECT I
                            FROM VAL_GET((
                                SELECT I
                                FROM VAL_GET(OT.OBJ_ID, 1766)), 1750)) <> 3403), 1, 0) HAS_CHILD
                FROM DISCIPLINE_TREE(:I$OBJ_ID, :I$TYPE_ID) DT) DT)
        WHERE HAS_CHILD = 1
           OR IS_LAST = 1
        INTO :OBJ_ID,
             :TYPE_ID,
             :VAL2,
             :VAL3,
             :COLOR,
             :LEVEL_NUM,
             :IS_LAST
    DO
    BEGIN
        IF (:TYPE_ID = 185) THEN
        BEGIN
            VAL2 = '';
            V$I = CHAR_LENGTH(:VAL3);
            WHILE (:V$I > 0 AND SUBSTRING(:VAL3 FROM :V$I FOR 1) <> ' ') DO
            BEGIN
                VAL2 = SUBSTRING(:VAL3 FROM :V$I FOR 1)||:VAL2;
                V$I = :V$I - 1;
            END
            VAL3 = SUBSTRING(:VAL3 FROM 1 FOR :V$I - 1);
        END
        -- loading
        IF (:IS_LAST = 1) THEN
        BEGIN
            V$I = -1;

            FOR SELECT OBJ_ID
                FROM LINKS
                WHERE PARENT_ID = :OBJ_ID
                  AND OBJ_TYPE_ID = 203
                  AND DATE_DEL IS NULL
                UNION ALL
                SELECT NULL
                FROM RDB$DATABASE
                INTO :LOADING_ID
            DO
            BEGIN
                -- create loading
                IF (:LOADING_ID IS NULL AND :V$I = -1) THEN
                BEGIN
                    SELECT OBJ_ID
                    FROM OBJECT_ADD(:OBJ_ID, 203)
                    INTO :LOADING_ID;
                    -- 1
                    SELECT BLOB_ID
                    FROM VAL_ADD(1769, :LOADING_ID, 780)
                    INTO :V$I;
                    -- 29
                    SELECT BLOB_ID
                    FROM VAL_ADD(1772, :LOADING_ID, 3)
                    INTO :V$I;

                    V$I = -2;
                END

                IF (:LOADING_ID IS NOT NULL) THEN
                BEGIN
                    -- 1
                    SELECT I, V_LONG
                    FROM VAL_GET(:LOADING_ID, 1769, 0, :I$USER_ID)
                    INTO :VAL1_ID, :VAL1;

                    BRUSHCOLOR = IIF(:VAL1_ID = 780, '$00FFFF', '$F1E5DB');
                    -- 4
                    SELECT IIF(I = 0, NULL, I)
                    FROM VAL_GET(:LOADING_ID, 1770, 0, :I$USER_ID)
                    INTO :VAL4;
                    -- 5
                    SELECT IIF(I = 0, NULL, I)
                    FROM VAL_GET(:LOADING_ID, 1771, 0, :I$USER_ID)
                    INTO :VAL5;
                    -- 6
                    SELECT IIF(I = 0, NULL, I)
                    FROM VAL_GET(:LOADING_ID, 1773, 0, :I$USER_ID)
                    INTO :VAL6;
                    -- 7
                    SELECT IIF(I = 0, NULL, I)
                    FROM VAL_GET(:LOADING_ID, 1774, 0, :I$USER_ID)
                    INTO :VAL7;
                    -- 8
                    SELECT IIF(I = 0, NULL, I)
                    FROM VAL_GET(:LOADING_ID, 1775, 0, :I$USER_ID)
                    INTO :VAL8;
                    -- 9 - 28 obj_id = 205
                    IF (V$I <> -2) THEN
                    BEGIN
                        FOR SELECT L205.OBJ_ID, KURS
                            FROM (
                                SELECT
                                    L205.OBJ_ID,
                                   (SELECT I
                                    FROM VAL_GET(L205.OBJ_ID, 1776, 0, :I$USER_ID)) - 48 KURS
                                FROM LINKS L205
                                WHERE L205.PARENT_ID = :LOADING_ID
                                  AND L205.OBJ_TYPE_ID = 205
                                  AND L205.DATE_DEL IS NULL) L205
                            WHERE L205.KURS <= (
                                SELECT I
                                FROM VAL_GET(:I$OBJ_ID, 1760, 0, :I$USER_ID))
                            INTO :V$I, :V$KURS
                        DO
                        BEGIN
                            SELECT IIF(I = 0, NULL, I)
                            FROM VAL_GET(:V$I, 1777, 0, :I$USER_ID)
                            INTO :V$VAL9;

                            SELECT IIF(I = 0, NULL, I), V_LONG
                            FROM VAL_GET(:V$I, 1778, 0, :I$USER_ID)
                            INTO :V$VAL10_ID, :V$VAL10;

                            SELECT IIF(I = 0, NULL, I)
                            FROM VAL_GET(:V$I, 1779, 0, :I$USER_ID)
                            INTO :V$VAL11;

                            SELECT IIF(I = 0, NULL, I), V_LONG
                            FROM VAL_GET(:V$I, 1780, 0, :I$USER_ID)
                            INTO :V$VAL12_ID, :V$VAL12;

                            IF (:V$KURS = 1) THEN
                            BEGIN
                                VAL9 = :V$VAL9; VAL10_ID = :V$VAL10_ID; VAL10 = :V$VAL10; VAL11 = :V$VAL11; VAL12_ID = :V$VAL12_ID; VAL12 = :V$VAL12;
                            END
                            IF (:V$KURS = 2) THEN
                            BEGIN
                                VAL13 = :V$VAL9; VAL14_ID = :V$VAL10_ID; VAL14 = :V$VAL10; VAL15 = :V$VAL11; VAL16_ID = :V$VAL12_ID; VAL16 = :V$VAL12;
                            END
                            IF (:V$KURS = 3) THEN
                            BEGIN
                                VAL17 = :V$VAL9; VAL18_ID = :V$VAL10_ID; VAL18 = :V$VAL10; VAL19 = :V$VAL11; VAL20_ID = :V$VAL12_ID; VAL20 = :V$VAL12;
                            END
                            IF (:V$KURS = 4) THEN
                            BEGIN
                                VAL21 = :V$VAL9; VAL22_ID = :V$VAL10_ID; VAL22 = :V$VAL10; VAL23 = :V$VAL11; VAL24_ID = :V$VAL12_ID; VAL24 = :V$VAL12;
                            END
                            IF (:V$KURS = 5) THEN
                            BEGIN
                                VAL25 = :V$VAL9; VAL26_ID = :V$VAL10_ID; VAL26 = :V$VAL10; VAL27 = :V$VAL11; VAL28_ID = :V$VAL12_ID; VAL28 = :V$VAL12;
                            END
                        END
                    END
                    -- 29
                    SELECT COST
                    FROM VAL_GET(:LOADING_ID, 1772, 0, :I$USER_ID)
                    INTO :VAL29;

                    SUSPEND;
                    V$I = :LOADING_ID;
                    VAL1 = NULL;  VAL1_ID = NULL;
                    VAL9 = NULL;  VAL10_ID = NULL; VAL10 = NULL; VAL11 = NULL; VAL12_ID = NULL; VAL12 = NULL;
                    VAL13 = NULL; VAL14_ID = NULL; VAL14 = NULL; VAL15 = NULL; VAL16_ID = NULL; VAL16 = NULL;
                    VAL17 = NULL; VAL18_ID = NULL; VAL18 = NULL; VAL19 = NULL; VAL20_ID = NULL; VAL20 = NULL;
                    VAL21 = NULL; VAL22_ID = NULL; VAL22 = NULL; VAL23 = NULL; VAL24_ID = NULL; VAL24 = NULL;
                    VAL25 = NULL; VAL26_ID = NULL; VAL26 = NULL; VAL27 = NULL; VAL28_ID = NULL; VAL28 = NULL;
                    VAL29 = NULL;
                    BRUSHCOLOR = NULL;
                END
            END
        END
        ELSE
        BEGIN
            SUSPEND;
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DISCIPLINE_LOADING_LIST_REPORT (
    I$OBJ_ID BIGINT,
    I$TYPE_ID BIGINT,
    I$USER_ID BIGINT = 1,
    I$N SMALLINT = NULL)
RETURNS (
    VAL01 VARCHAR(4000),
    VAL02 VARCHAR(4000),
    VAL03 VARCHAR(4000),
    VAL04 INTEGER,
    VAL05 INTEGER,
    VAL06 INTEGER,
    VAL07 INTEGER,
    VAL08 INTEGER,
    VAL09 INTEGER,
    VAL10 INTEGER,
    VAL11 INTEGER,
    VAL12 INTEGER,
    VAL13 INTEGER,
    VAL14 INTEGER,
    VAL15 INTEGER,
    VAL16 INTEGER,
    VAL17 INTEGER,
    VAL18 INTEGER,
    VAL19 INTEGER)
AS
DECLARE VARIABLE V$1760 SMALLINT;
DECLARE VARIABLE V$1786KURS1 FLOAT;
DECLARE VARIABLE V$1786KURS2 FLOAT;
DECLARE VARIABLE V$1786KURS3 FLOAT;
DECLARE VARIABLE V$1786KURS4 FLOAT;
DECLARE VARIABLE V$1786KURS5 FLOAT;
DECLARE VARIABLE V$PARAM_CODE VARCHAR(40);
DECLARE VARIABLE V$PARAM_VALUE INTEGER;
BEGIN
    IF (:I$N = 10) THEN
    BEGIN
        FOR SELECT
                VAL2 VAL01, VAL3 VAL02,
                IIF(IS_LAST = 0, 'N/N/N, ',
                    IIF(VAL10_ID IS NULL, '', VAL10||', ')||IIF(VAL12_ID IS NULL, '', VAL12||', ')||
                    IIF(VAL14_ID IS NULL, '', VAL14||', ')||IIF(VAL16_ID IS NULL, '', VAL16||', ')||
                    IIF(VAL18_ID IS NULL, '', VAL18||', ')||IIF(VAL20_ID IS NULL, '', VAL20||', ')||
                    IIF(VAL22_ID IS NULL, '', VAL22||', ')||IIF(VAL24_ID IS NULL, '', VAL24||', ')||
                    IIF(VAL26_ID IS NULL, '', VAL26||', ')||IIF(VAL28_ID IS NULL, '', VAL28||', ')) VAL03,
                VAL5 VAL04,
                COALESCE(VAL9 , 0) + COALESCE(VAL11, 0) +
                    COALESCE(VAL13, 0) + COALESCE(VAL15, 0) +
                    COALESCE(VAL17, 0) + COALESCE(VAL19, 0) +
                    COALESCE(VAL21, 0) + COALESCE(VAL23, 0) +
                    COALESCE(VAL25, 0) + COALESCE(VAL27, 0) VAL6,
                VAL7  VAL08, VAL8  VAL09, VAL9  VAL10, VAL11 VAL11,
                VAL13 VAL12, VAL15 VAL13, VAL17 VAL14, VAL19 VAL15,
                VAL21 VAL16, VAL23 VAL17, VAL25 VAL18, VAL27 VAL19
            FROM DISCIPLINE_LOADING_LIST(:I$OBJ_ID, :I$TYPE_ID, :I$USER_ID)
            INTO :VAL01, :VAL02, :VAL03, :VAL04, :VAL06, :VAL08, :VAL09, :VAL10, :VAL11,
                 :VAL12, :VAL13, :VAL14, :VAL15, :VAL16, :VAL17, :VAL18, :VAL19
        DO
        BEGIN
            IF (:VAL03 <> '') THEN
            BEGIN
                VAL03 = SUBSTRING(:VAL03 FROM 1 FOR (CHAR_LENGTH(:VAL03) - 2));
            END

            VAL04 = COALESCE(:VAL04, 1.5 * :VAL06);
            VAL05 = MAXVALUE(:VAL04 - MAXVALUE(:VAL06, COALESCE(:VAL08, 0) + COALESCE(:VAL09, 0)), 0);
            VAL07 = MAXVALUE(:VAL06 - COALESCE(:VAL08, 0) - COALESCE(:VAL09, 0), 0);

            VAL04 = IIF(:VAL04 = 0, NULL, :VAL04);
            VAL05 = IIF(:VAL05 = 0, NULL, :VAL05);
            VAL06 = IIF(:VAL06 = 0, NULL, :VAL06);
            VAL07 = IIF(:VAL07 = 0, NULL, :VAL07);

            SUSPEND;
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DISCIPLINE_LOADING_PARAMS (
    I$OBJ_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    PARAM_CODE VARCHAR(40),
    PARAM_VALUE VARCHAR(4000))
AS
BEGIN
    SELECT '1760', I
    FROM VAL_GET(:I$OBJ_ID, 1760, 0, :I$USER_ID)
    INTO :PARAM_CODE, :PARAM_VALUE;

    SUSPEND;

    IF (:PARAM_VALUE = 0) THEN
    BEGIN
        IF ((SELECT TYPE_ID FROM OBJECTS WHERE OBJ_ID = :I$OBJ_ID) = 50) THEN
        BEGIN
            PARAM_CODE = 'ERROR';

            SELECT 'Для объекта "'||CAPTION||'" не задан параметр "'
            FROM OBJECT_CAPTION_GET(:I$OBJ_ID,NULL,NULL,:I$USER_ID)
            INTO :PARAM_VALUE;

            SELECT :PARAM_VALUE||CAPTION||'"'
            FROM PARAM_CAPTION_GET(:I$OBJ_ID, 1760, NULL, NULL)
            INTO :PARAM_VALUE;

            SUSPEND;
        END

        EXIT;
    END
    -- max loaling per week
    FOR SELECT '1786KURS'||((
            SELECT I
            FROM VAL_GET(L208.OBJ_ID, 1785, 0, :I$USER_ID)) - 48), (
            SELECT IIF(I = 0, NULL, I)
            FROM VAL_GET(L208.OBJ_ID, 1786, 0, :I$USER_ID))
        FROM LINKS L208
        WHERE L208.PARENT_ID = :I$OBJ_ID
          AND L208.OBJ_TYPE_ID = 208
          AND L208.DATE_DEL IS NULL
        INTO :PARAM_CODE, :PARAM_VALUE
    DO
    BEGIN
        IF (:PARAM_VALUE IS NOT NULL) THEN
        BEGIN
            SUSPEND;
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DISCIPLINE_SUBTREE (
    I$STAGE_ID BIGINT)
RETURNS (
    SUBJECT_ID BIGINT)
AS
declare variable V$PLAN_ID bigint;
declare variable V$STAGE_LV bigint;
begin

    -- ID учебного плана и номер этапа
    SELECT FIRST 1 LP50.PARENT_ID, V381.LISTVAL_ID
    FROM LINKS LP50
    JOIN VALL V381 ON V381.OBJ_ID = LP50.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
    WHERE LP50.OBJ_ID = :I$STAGE_ID AND LP50.PARENT_TYPE_ID = 50 AND LP50.DATE_DEL IS NULL
    INTO :V$PLAN_ID, :V$STAGE_LV;

    -- Выбираем предметы по дереву и смотрим наличие учебной нагрузки в нужном этапе
    FOR
        SELECT T.SUBJECT_ID
        FROM DISCIPLINE_SUBTREE_IN(:V$PLAN_ID, NULL, 0) T
        -- Учебная нагрузка (предполагаем что если она есть, то что-то в часах не пусто)
        JOIN LINKS L203 ON L203.PARENT_ID = T.ASSN_ID AND L203.OBJ_TYPE_ID = 203 AND L203.DATE_DEL IS NULL
        -- Распределение обязательной нагрузки - по числу этапов, где задействовано
        JOIN LINKS L205 ON L205.PARENT_ID = L203.OBJ_ID AND L205.OBJ_TYPE_ID = 205 AND L205.DATE_DEL IS NULL
        JOIN VALL V1776 ON V1776.OBJ_ID = L205.OBJ_ID AND V1776.PARAM_ID = 1776 AND V1776.IS_DEL = 0 AND V1776.LISTVAL_ID = :V$STAGE_LV
        INTO :SUBJECT_ID
    DO
    BEGIN
        SUSPEND;
    END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DISCIPLINE_SUBTREE_IN (
    I$PLAN_ID BIGINT,
    I$PARENT_ID BIGINT = null,
    I$LEVEL INTEGER NOT NULL = 0)
RETURNS (
    SUBJECT_ID BIGINT,
    ASSN_ID BIGINT,
    LEVEL_NUM INTEGER)
AS
declare variable V$OBJ_ID bigint;
declare variable V$TYPE_ID bigint;
begin

  IF(I$LEVEL > 10) THEN EXCEPTION DATA_ERROR 'Зацикливание в дереве дисциплин';
  LEVEL_NUM = I$LEVEL;

  IF(I$PARENT_ID IS NULL) THEN I$PARENT_ID = I$PLAN_ID;

  FOR
      SELECT LX.OBJ_ID, LX.OBJ_TYPE_ID
      FROM LINKS LX
      WHERE LX.PARENT_ID = :I$PARENT_ID AND LX.OBJ_TYPE_ID IN (185, 201) AND LX.DATE_DEL IS NULL
      INTO :V$OBJ_ID, :V$TYPE_ID
  DO
  BEGIN

      FOR
          SELECT SUBJECT_ID, LEVEL_NUM, ASSN_ID
          FROM DISCIPLINE_SUBTREE_IN(:I$PLAN_ID, :V$OBJ_ID, :I$LEVEL + 1)
          INTO :SUBJECT_ID, :LEVEL_NUM, :ASSN_ID
      DO
      BEGIN
          SUSPEND;
      END

      -- Нашли наконец предмет
      -- Внимание: тут кроме честных предметов можеь еще быть предметный модуль, внутри которого лежат сами предметы
      IF(V$TYPE_ID = 201) THEN
      BEGIN
          ASSN_ID = V$OBJ_ID;
          SUBJECT_ID = NULL;

          SELECT V1766.VAL
          FROM VALR V1766
          WHERE V1766.OBJ_ID = :V$OBJ_ID AND V1766.PARAM_ID = 1766 AND V1766.IS_DEL = 0
          INTO :SUBJECT_ID;

          IF(SUBJECT_ID IS NOT NULL) THEN SUSPEND;
      END

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DISCIPLINE_TIME_BUDGET (
    I$OBJ_ID BIGINT NOT NULL,
    I$TYPE_ID BIGINT = null,
    I$USER_ID BIGINT = 1)
RETURNS (
    OBJ_ID BIGINT,
    VAL1 VARCHAR(4000),
    VAL2 INTEGER,
    VAL3 INTEGER,
    VAL4 INTEGER,
    VAL5 INTEGER,
    VAL6 INTEGER,
    VAL7 INTEGER,
    VAL8 INTEGER,
    VAL9 INTEGER)
AS
declare variable V$BLOB_ID bigint;
declare variable V$KURS integer;
declare variable V$VAL2 integer;
declare variable V$VAL3 integer;
declare variable V$VAL4 integer;
declare variable V$VAL5 integer;
declare variable V$VAL6 integer;
declare variable V$VAL7 integer;
declare variable V$VAL2_ALL integer;
declare variable V$VAL3_ALL integer;
declare variable V$VAL4_ALL integer;
declare variable V$VAL5_ALL integer;
declare variable V$VAL6_ALL integer;
declare variable V$VAL7_ALL integer;
declare variable V$VAL8_ALL integer;
BEGIN
    V$VAL2_ALL = 0; V$VAL3_ALL = 0; V$VAL4_ALL = 0;
    V$VAL5_ALL = 0; V$VAL6_ALL = 0; V$VAL7_ALL = 0;
    V$VAL8_ALL = 0;

    FOR SELECT
            KURS,
            SUM(IIF(NOT(VID_UD BETWEEN 3406 AND 3411), KURS_TIME, 0)) VAL2,
            SUM(IIF(VID_UD = 3406, KURS_TIME, 0)) VAL3,
            SUM(IIF(VID_UD = 3408, KURS_TIME, 0)) VAL4,
            SUM(IIF(VID_UD = 3409, KURS_TIME, 0)) VAL5,
            SUM(IIF(VID_UD = 3410, KURS_TIME, 0)) VAL6,
            SUM(IIF(VID_UD = 3411, KURS_TIME, 0)) VAL7,
            SUM(IIF(ALL_TIME = 0 AND NOT(VID_UD BETWEEN 3406 AND 3411), KURS_TIME, 0)) VAL2_ALL,
            SUM(IIF(ALL_TIME = 0 AND VID_UD = 3406, KURS_TIME, 0)) VAL3_ALL,
            SUM(IIF(ALL_TIME = 0 AND VID_UD = 3408, KURS_TIME, 0)) VAL4_ALL,
            SUM(IIF(ALL_TIME = 0 AND VID_UD = 3409, KURS_TIME, 0)) VAL5_ALL,
            SUM(IIF(ALL_TIME = 0 AND VID_UD = 3410, KURS_TIME, 0)) VAL6_ALL,
            SUM(IIF(ALL_TIME = 0 AND VID_UD = 3411, KURS_TIME, 0)) VAL7_ALL
        FROM
       (SELECT
            L205.KURS,
            CAST(((SELECT I FROM VAL_GET(L205.OBJ_ID, 1777, 0, :I$USER_ID)) +
                  (SELECT I FROM VAL_GET(L205.OBJ_ID, 1779, 0, :I$USER_ID)))/L208.WEEK_LOADING AS INT) KURS_TIME,
           (SELECT I
            FROM VAL_GET((
                SELECT I FROM VAL_GET(L201_ID, 1766)), 1750)) VID_UD,
            ALL_TIME
        FROM (
            SELECT
                L205.OBJ_ID,
                DT.OBJ_ID L201_ID,
               (SELECT I FROM VAL_GET(L205.OBJ_ID, 1776, 0, :I$USER_ID)) KURS,
               (SELECT I FROM VAL_GET(L203.OBJ_ID, 1770, 0, :I$USER_ID)) ALL_TIME -- ?!!!!
            FROM DISCIPLINE_TREE(:I$OBJ_ID, :I$TYPE_ID) DT
            JOIN LINKS L203 ON L203.PARENT_ID = DT.OBJ_ID AND L203.OBJ_TYPE_ID = 203 AND L203.DATE_DEL IS NULL
            JOIN LINKS L205 ON L205.PARENT_ID = L203.OBJ_ID AND L205.OBJ_TYPE_ID = 205 AND L205.DATE_DEL IS NULL
            WHERE DT.TYPE_ID = 201) L205
        JOIN (
            SELECT (
                SELECT I
                FROM VAL_GET(L208.OBJ_ID, 1785, 0, :I$USER_ID)) KURS, (
                SELECT CAST(IIF(I = 0, NULL, I) AS FLOAT)
                FROM VAL_GET(L208.OBJ_ID, 1786, 0, :I$USER_ID)) WEEK_LOADING
            FROM LINKS L208
            WHERE L208.PARENT_ID = :I$OBJ_ID AND L208.OBJ_TYPE_ID = 208 AND L208.DATE_DEL IS NULL) L208 ON L205.KURS = L208.KURS)
        GROUP BY KURS
        INTO :V$KURS, :VAL2, :VAL3, :VAL4, :VAL5, :VAL6, :VAL7,
             :V$VAL2, :V$VAL3, :V$VAL4, :V$VAL5, :V$VAL6, :V$VAL7
    DO
    BEGIN
        VAL1 = CASE :V$KURS - 48
                   WHEN 1 THEN 'I'
                   WHEN 2 THEN 'II'
                   WHEN 3 THEN 'III'
                   WHEN 4 THEN 'IV'
                   WHEN 5 THEN 'V'
                   WHEN 6 THEN 'VI'
                   ELSE :V$KURS - 48
               END||' курс';

        VAL2 = IIF(:VAL2 = 0, NULL, :VAL2);
        VAL3 = IIF(:VAL3 = 0, NULL, :VAL3);
        VAL4 = IIF(:VAL4 = 0, NULL, :VAL4);
        VAL5 = IIF(:VAL5 = 0, NULL, :VAL5);
        VAL6 = IIF(:VAL6 = 0, NULL, :VAL6);
        VAL7 = IIF(:VAL7 = 0, NULL, :VAL7);

        V$VAL2_ALL = :V$VAL2_ALL + :V$VAL2;
        V$VAL3_ALL = :V$VAL3_ALL + :V$VAL3;
        V$VAL4_ALL = :V$VAL4_ALL + :V$VAL4;
        V$VAL5_ALL = :V$VAL5_ALL + :V$VAL5;
        V$VAL6_ALL = :V$VAL6_ALL + :V$VAL6;
        V$VAL7_ALL = :V$VAL7_ALL + :V$VAL7;

        OBJ_ID = NULL;
        VAL8 = 0;

        SELECT L215.OBJ_ID
        FROM LINKS L215
        WHERE L215.PARENT_ID = :I$OBJ_ID
          AND L215.OBJ_TYPE_ID = 215
          AND L215.DATE_DEL IS NULL
          AND (SELECT I
               FROM VAL_GET(L215.OBJ_ID, 1803, 0, :I$USER_ID)) = :V$KURS
        INTO :OBJ_ID;
        -- add object type_id = 215
        IF (:OBJ_ID IS NULL) THEN
        BEGIN
            SELECT OBJ_ID FROM OBJECT_ADD(:I$OBJ_ID, 215) INTO :OBJ_ID;
            SELECT BLOB_ID FROM VAL_ADD(1803, :OBJ_ID, :V$KURS) INTO :V$BLOB_ID;
        END
        ELSE
        BEGIN
            SELECT I FROM VAL_GET(:OBJ_ID, 1810, 0, :I$USER_ID) INTO :VAL8;
        END

        V$VAL8_ALL = :V$VAL8_ALL + :VAL8;
        VAL8 = IIF(:VAL8 = 0, NULL, :VAL8);

        SUSPEND;
    END

    OBJ_ID = NULL;
    VAL1 = 'Всего';

    SELECT
        :V$VAL2_ALL + SUM(IIF(NOT(VID_UD BETWEEN 3406 AND 3411), ALL_TIME, 0)) VAL2,
        :V$VAL3_ALL + SUM(IIF(VID_UD = 3406, ALL_TIME, 0)) VAL3,
        :V$VAL4_ALL + SUM(IIF(VID_UD = 3408, ALL_TIME, 0)) VAL4,
        :V$VAL5_ALL + SUM(IIF(VID_UD = 3409, ALL_TIME, 0)) VAL5,
        :V$VAL6_ALL + SUM(IIF(VID_UD = 3410, ALL_TIME, 0)) VAL6,
        :V$VAL7_ALL + SUM(IIF(VID_UD = 3411, ALL_TIME, 0)) VAL7
    FROM (
        SELECT
           (SELECT I FROM VAL_GET((SELECT I FROM VAL_GET(DT.OBJ_ID, 1766)), 1750)) VID_UD, -- вид учебной деятельности (1750) для дисциплины (1766)
           (SELECT I FROM VAL_GET(L203.OBJ_ID, 1770, 0, :I$USER_ID)) ALL_TIME -- учебная нагрузка в неделях ?!!!
        FROM DISCIPLINE_TREE(:I$OBJ_ID, :I$TYPE_ID) DT
        JOIN LINKS L203 ON L203.PARENT_ID = DT.OBJ_ID AND L203.OBJ_TYPE_ID = 203 AND L203.DATE_DEL IS NULL
        WHERE DT.TYPE_ID = 201 -- выбираем только непосредственно дисциплины
    )
    INTO :VAL2, :VAL3, :VAL4, :VAL5, :VAL6, :VAL7;

    VAL2 = IIF(:VAL2 = 0, NULL, :VAL2);
    VAL3 = IIF(:VAL3 = 0, NULL, :VAL3);
    VAL4 = IIF(:VAL4 = 0, NULL, :VAL4);
    VAL5 = IIF(:VAL5 = 0, NULL, :VAL5);
    VAL6 = IIF(:VAL6 = 0, NULL, :VAL6);
    VAL7 = IIF(:VAL7 = 0, NULL, :VAL7);
    VAL8 = IIF(:V$VAL8_ALL = 0, NULL, :V$VAL8_ALL);

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DISCIPLINE_TIME_BUDGET_REPORT (
    I$OBJ_ID BIGINT,
    I$TYPE_ID BIGINT,
    I$USER_ID BIGINT = 1,
    I$N SMALLINT = NULL)
RETURNS (
    V1 VARCHAR(4000))
AS
DECLARE VARIABLE V$V2 INTEGER;
DECLARE VARIABLE V$V3 INTEGER;
DECLARE VARIABLE V$V4 INTEGER;
DECLARE VARIABLE V$V5 INTEGER;
DECLARE VARIABLE V$V6 INTEGER;
DECLARE VARIABLE V$V7 INTEGER;
DECLARE VARIABLE V$V8 INTEGER;
BEGIN
    IF (:I$N = 1) THEN
    BEGIN
        WHILE (COALESCE(:I$TYPE_ID, 2) <> 2)
        DO
        BEGIN
            I$TYPE_ID = NULL;

            SELECT FIRST 1
                PARENT_ID,
                PARENT_TYPE_ID
            FROM LINKS
            WHERE OBJ_ID = :I$OBJ_ID
              AND DATE_DEL IS NULL
            INTO :I$OBJ_ID, :I$TYPE_ID;
        END

        SELECT V
        FROM VAL_GET(:I$OBJ_ID, 5)
        INTO :V1;
    END

    IF (:I$N BETWEEN 2 AND 4) THEN
    BEGIN
        WHILE (COALESCE(:I$TYPE_ID, 57) <> 57)
        DO
        BEGIN
            I$TYPE_ID = NULL;

            SELECT FIRST 1
                PARENT_ID,
                PARENT_TYPE_ID
            FROM LINKS
            WHERE OBJ_ID = :I$OBJ_ID
              AND DATE_DEL IS NULL
            INTO :I$OBJ_ID, :I$TYPE_ID;
        END

        IF (:I$N = 2) THEN
        BEGIN
            SELECT V
            FROM VAL_GET(:I$OBJ_ID, 1754)
            INTO :V1;

            SELECT :V1||' '||V
            FROM VAL_GET(:I$OBJ_ID, 386)
            INTO :V1;
        END

        IF (:I$N = 3) THEN
        BEGIN
            SELECT V
            FROM VAL_GET(:I$OBJ_ID, 1756)
            INTO :V1;
        END

        IF (:I$N = 4) THEN
        BEGIN
            SELECT V
            FROM VAL_GET(:I$OBJ_ID, 1755)
            INTO :V1;
        END
    END

    IF (:I$N = 5) THEN
    BEGIN
        SELECT V
        FROM VAL_GET(:I$OBJ_ID, 1759)
        INTO :V1;
    END

    IF (:I$N = 10) THEN
    BEGIN
        SELECT FIRST 1 VAL2, VAL3, VAL4, VAL5, VAL6, VAL7, VAL8,
            COALESCE(VAL2, 0) + COALESCE(VAL3, 0) + COALESCE(VAL4, 0) + COALESCE(VAL5, 0) +
            COALESCE(VAL6, 0) + COALESCE(VAL7, 0) + COALESCE(VAL8, 0)
        FROM DISCIPLINE_TIME_BUDGET(:I$OBJ_ID, :I$TYPE_ID, :I$USER_ID)
        WHERE OBJ_ID IS NULL
        INTO :V1, :V$V2, :V$V3, :V$V4, :V$V5, :V$V6, :V$V7, :V$V8;

        SUSPEND;
        V1 = :V$V2;
        SUSPEND;
        V1 = :V$V3;
        SUSPEND;
        V1 = :V$V4;
        SUSPEND;
        V1 = :V$V5;
        SUSPEND;
        V1 = :V$V6;
        SUSPEND;
        V1 = :V$V7;
        SUSPEND;
        V1 = :V$V8;
    END

    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DISCIPLINE_TREE (
    I$OBJ_ID BIGINT NOT NULL,
    I$TYPE_ID BIGINT = null,
    I$USER_ID BIGINT = 1,
    I$LEVEL_NUM SMALLINT = 0)
RETURNS (
    OBJ_ID BIGINT,
    TYPE_ID BIGINT,
    PARENT_ID BIGINT,
    OBJ_CAPTION VARCHAR(4000),
    IS_LAST SMALLINT,
    SORT_ORDER DOUBLE PRECISION,
    COLOR INTEGER,
    LEVEL_NUM SMALLINT)
AS
declare variable V$PARENT_ID bigint;
declare variable V$LISTVAL_ID bigint;
BEGIN
    FOR
        SELECT L.OBJ_ID, L.OBJ_TYPE_ID, L.PARENT_ID,
            IIF((L.OBJ_TYPE_ID = 185 AND NOT EXISTS(
                    SELECT FIRST 1 1
                    FROM LINKS L185
                    WHERE L185.PARENT_ID = L.OBJ_ID AND L185.DATE_DEL IS NULL AND L185.OBJ_TYPE_ID = 185))
             OR (L.OBJ_TYPE_ID = 201 AND (
                    SELECT I FROM VAL_GET((SELECT I FROM VAL_GET(L.OBJ_ID, 1766)), 1750)) = 3403), 1, 0) IS_LAST
        FROM LINKS L
        WHERE L.PARENT_ID = :I$OBJ_ID AND L.DATE_DEL IS NULL AND L.OBJ_TYPE_ID IN (185, 201)
        ORDER BY (SELECT IIF(L.OBJ_TYPE_ID = 185, SORT_ORDER, (
                      SELECT I FROM VAL_GET((SELECT I FROM VAL_GET(L.OBJ_ID, 1766)), 1750)) || CAPTION)
                  FROM OBJECT_CAPTION_GET(L.OBJ_ID, NULL, NULL, :I$USER_ID))
        INTO :OBJ_ID, :TYPE_ID, :PARENT_ID, :IS_LAST
    DO
    BEGIN
        SELECT CAPTION, SORT_ORDER, COLOR
        FROM OBJECT_CAPTION_GET(:OBJ_ID, NULL, NULL, :I$USER_ID)
        INTO :OBJ_CAPTION, :SORT_ORDER, :COLOR;

        LEVEL_NUM = :I$LEVEL_NUM;
        I$TYPE_ID = NULL;

        SUSPEND;

        FOR
            SELECT OBJ_ID, TYPE_ID, PARENT_ID, OBJ_CAPTION, IS_LAST, SORT_ORDER, COLOR, LEVEL_NUM
            FROM DISCIPLINE_TREE(:OBJ_ID, NULL, :I$USER_ID, :I$LEVEL_NUM + 1)
            INTO :OBJ_ID, :TYPE_ID, :PARENT_ID, :OBJ_CAPTION, :IS_LAST, :SORT_ORDER, :COLOR, :LEVEL_NUM
        DO
        BEGIN
            SUSPEND;
        END
    END

    IF (I$TYPE_ID IN (50, 245)) THEN
    BEGIN
        -- Создаем 2-уровневое начальное дерево дисциплин, выдача уже отсортированная как надо
        V$PARENT_ID = I$OBJ_ID;
        FOR
            SELECT LISTVAL_ID
            FROM OO_FILTRED_LIST(245)
            WHERE LISTVAL_ID <> 12975 -- убираем новую запись
            INTO :V$LISTVAL_ID
        DO
        BEGIN
            IS_LAST = IIF(V$LISTVAL_ID IN (5241, 5242, 5243, 5246, 5247), 1, 0);

            SELECT OBJ_ID
            FROM OBJECT_ADD(IIF(:IS_LAST = 1, :V$PARENT_ID, :I$OBJ_ID), 185)
            INTO :OBJ_ID;

            SELECT IIF(:IS_LAST = 1, :V$PARENT_ID, :OBJ_ID)
            FROM VAL_ADD(1608, :OBJ_ID, :V$LISTVAL_ID)
            INTO :V$PARENT_ID;
        END

        FOR
            SELECT OBJ_ID, TYPE_ID, PARENT_ID, OBJ_CAPTION, IS_LAST, SORT_ORDER, COLOR, LEVEL_NUM
            FROM DISCIPLINE_TREE(:I$OBJ_ID, NULL, :I$USER_ID, :I$LEVEL_NUM + 1)
            INTO :OBJ_ID, :TYPE_ID, :PARENT_ID, :OBJ_CAPTION, :IS_LAST, :SORT_ORDER, :COLOR, :LEVEL_NUM
        DO
        BEGIN
            SUSPEND;
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DISTRICT_VERIFICATION_REP2_DTL (
    I$SCHOOL_ID BIGINT,
    I$ROW_NUM SMALLINT,
    I$PARAM_ID BIGINT = NULL)
RETURNS (
    DOCUMENT_ID BIGINT,
    NAME VARCHAR(4000))
AS
DECLARE VARIABLE V$PARAM_ID BIGINT;
DECLARE VARIABLE V$TYPE_ID BIGINT;
DECLARE VARIABLE T BIGINT;
DECLARE VARIABLE T2 BIGINT;
DECLARE VARIABLE T3 BIGINT;
BEGIN
  IF(I$PARAM_ID IS NULL) THEN
  BEGIN
    I$ROW_NUM = I$ROW_NUM - 1;

    FOR
      SELECT DISTINCT P.PARAM_ID, P.TYPE_ID, P.GRID_ORDER
      FROM PARAMS P
      JOIN LPARAMS LP ON LP.PARAM_ID = P.PARAM_ID AND LP.IS_DEL = 0 AND LP.EDIT_TYPE >= 0
      JOIN LEVELS L ON L.LEVEL_ID = LP.LEVEL_ID AND L.IS_DEL = 0
      JOIN TASKS T ON T.TASK_ID = L.TASK_ID AND T.IS_DEL = 0
      JOIN MODULES M ON M.MODULE_ID = T.MODULE_ID AND M.IS_DEL = 0 AND M.IS_ACTIVE = 1
      JOIN TYPES OBJT ON OBJT.TYPE_ID = P.TYPE_ID
      JOIN RES R ON R.RES_ID = P.RES_ID AND R.LANG_CODE = 'RU'
      JOIN RES RT ON RT.RES_ID = OBJT.RES_ID AND RT.LANG_CODE = 'RU'
      WHERE P.TYPE_ID IN (2, 17) AND P.IS_DEL = 0 AND P.IS_REQUIRED > 0 -- тут как просто обязательные, но контролирумые
        -- AND ((P.TYPE_ID = 2 AND P.PARAM_ID IN (13, 470)) OR P.TYPE_ID <> 2) -- для ОУ смотрим только лицевой счет
      -- Виртуальные параметры по документам - в конец списка
      UNION
      SELECT LV.LISTVAL_ID, 100000, LV.LISTVAL_ID + 100000
      FROM LISTVALS LV
      JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
      WHERE LV.LIST_ID = 9 AND LV.IS_DEL = 0 AND LV.LISTVAL_ID IN (1047, 1049, 1050, 1051, 1053, 18625)
      ORDER BY 2, 3
      INTO :T, :T2, :T3
    DO
    BEGIN             
      IF(I$ROW_NUM = 0) THEN V$PARAM_ID = T;
      I$ROW_NUM = I$ROW_NUM - 1;
    END
  END
  ELSE
  BEGIN
    V$PARAM_ID = I$PARAM_ID;
  END

  SELECT TYPE_ID
  FROM PARAMS
  WHERE PARAM_ID = :V$PARAM_ID
  INTO :V$TYPE_ID;

  -- !!! надо допроверять, может быть проблема по мере наполнения
  IF(V$TYPE_ID IS NULL AND V$PARAM_ID < 1000) THEN EXCEPTION DATA_ERROR 'По данному показателю не предусмотрен просмотр детализации';

  IF(V$TYPE_ID = 2) THEN
  BEGIN
    FOR
      SELECT L2.OBJ_ID
      FROM OBJECTS L2
      LEFT JOIN VAL_GET(L2.OBJ_ID, :V$PARAM_ID) VL ON 1 = 1
      WHERE L2.OBJ_ID = :I$SCHOOL_ID AND VL.V = ''
      INTO :DOCUMENT_ID
    DO
    BEGIN
      SELECT CAPTION
      FROM OBJECT_CAPTION_GET(:DOCUMENT_ID)
      INTO :NAME;

      SUSPEND;
    END
  END
  ELSE IF(V$TYPE_ID = 17) THEN
  BEGIN
    FOR
      SELECT L17.OBJ_ID
      FROM LINKS L17
      LEFT JOIN VAL_GET(L17.OBJ_ID, :V$PARAM_ID) VL ON 1 = 1
      WHERE L17.PARENT_ID = :I$SCHOOL_ID AND L17.OBJ_TYPE_ID = 17 AND L17.DATE_DEL IS NULL AND VL.V = ''
      INTO :DOCUMENT_ID
    DO
    BEGIN
      SELECT CAPTION
      FROM OBJECT_CAPTION_GET(:DOCUMENT_ID)
      INTO :NAME;

      SUSPEND;
    END
  END
  ELSE IF(V$TYPE_ID IS NULL) THEN
  BEGIN
  END

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DISTRICT_VERIFICATION_REP3_DTL (
    I$SCHOOL_ID BIGINT,
    I$ROW_NUM SMALLINT,
    I$PARAM_ID BIGINT = null)
RETURNS (
    PUPIL_ID BIGINT,
    VAL1 VARCHAR(4000),
    VAL3 VARCHAR(4000))
AS
declare variable V$PARAM_ID bigint;
declare variable V$TYPE_ID bigint;
declare variable V$OBJ_ID bigint;
declare variable Y integer;
declare variable T bigint;
declare variable T2 bigint;
declare variable T3 integer;
declare variable T4 integer;
declare variable V$Y date;
declare variable V$DATE14 date;
declare variable V$YL date;
BEGIN

  IF(I$PARAM_ID IS NULL) THEN
  BEGIN
    I$ROW_NUM = I$ROW_NUM - 1;

    FOR
      SELECT DISTINCT P.PARAM_ID, P.TYPE_ID, IIF(P.TYPE_ID = 10, -1, P.TYPE_ID), P.GRID_ORDER
      FROM PARAMS P
      JOIN LPARAMS LP ON LP.PARAM_ID = P.PARAM_ID AND LP.IS_DEL = 0 AND LP.EDIT_TYPE >= 0
      JOIN LEVELS L ON L.LEVEL_ID = LP.LEVEL_ID AND L.IS_DEL = 0
      JOIN TASKS T ON T.TASK_ID = L.TASK_ID AND T.IS_DEL = 0
      JOIN MODULES M ON M.MODULE_ID = T.MODULE_ID AND M.IS_DEL = 0 AND M.IS_ACTIVE = 1
      JOIN TYPES OBJT ON OBJT.TYPE_ID = P.TYPE_ID
      JOIN RES R ON R.RES_ID = P.RES_ID AND R.LANG_CODE = 'RU'
      JOIN RES RT ON RT.RES_ID = OBJT.RES_ID AND RT.LANG_CODE = 'RU'
      WHERE P.TYPE_ID IN (10, 79, 11) AND P.IS_DEL = 0 AND P.IS_REQUIRED > 0 -- тут как просто обязательные, но контролирумые
      -- Виртуальные параметры по наличию чего-нибудь - в конец списка
      UNION
      SELECT LV.LISTVAL_ID, 100000, 100000, LV.LISTVAL_ID + 100000
      FROM LISTVALS LV
      JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
      WHERE LV.LIST_ID = 360 AND LV.IS_DEL = 0 AND LV.TAG = 10
      ORDER BY 3, 4
      INTO :T, :T2, :T3, :T4
    DO
    BEGIN             
      IF(I$ROW_NUM = 0) THEN V$PARAM_ID = T;
      I$ROW_NUM = I$ROW_NUM - 1;
    END
  END
  ELSE
  BEGIN
    V$PARAM_ID = I$PARAM_ID;
  END

  SELECT TYPE_ID
  FROM PARAMS
  WHERE PARAM_ID = :V$PARAM_ID
  INTO :V$TYPE_ID;

  -- !!! надо допроверять, может быть проблема по мере наполнения
  IF(V$TYPE_ID IS NULL AND V$PARAM_ID < 1000) THEN EXCEPTION DATA_ERROR 'По данному показателю не предусмотрен просмотр детализации';

  Y = EXTRACT(YEAR FROM CURRENT_DATE);
  IF (EXTRACT(MONTH FROM CURRENT_DATE) < 9) THEN Y = Y - 1;
  V$Y = '25.08.' || Y;
  V$YL = '01.01.' || Y;

  V$DATE14 = DATEADD(-14 YEAR TO CURRENT_DATE);
  V$DATE14 = DATEADD(-2 MONTH TO V$DATE14); -- зазор в 2 месяца

  IF(V$TYPE_ID = 10) THEN
  BEGIN
    FOR
      SELECT DISTINCT L10.PERSON_ID
      FROM PERSON_MOVEMENTS L10
      LEFT JOIN VAL_GET(L10.PERSON_ID, :V$PARAM_ID) VL ON 1 = 1
      WHERE L10.OU_ID = :I$SCHOOL_ID AND L10.GROUP_TYPE_ID = 9 AND L10.DATE_DEL IS NULL AND L10.DATE_IN >= :V$Y
        AND VL.V = ''
      INTO :PUPIL_ID
    DO
    BEGIN
      SELECT CAPTION
      FROM OBJECT_CAPTION_GET(:PUPIL_ID, 23)
      INTO :VAL1;

      VAL3 = NULL;
      SELECT FIRST 1 C.CAPTION
      FROM LINKS LPG
      LEFT JOIN OBJECT_CAPTION_GET(LPG.PARENT_ID) C ON 1 = 1
      WHERE LPG.OBJ_ID = :PUPIL_ID AND LPG.PARENT_TYPE_ID IN (9, 187, 125, 81, 82, 83, 290) AND LPG.DATE_DEL IS NULL
      ORDER BY LPG.PARENT_TYPE_ID
      INTO :VAL3;

      SUSPEND;
    END
  END
  ELSE IF(V$TYPE_ID IS NULL) THEN
  BEGIN
    IF(V$PARAM_ID IN (14325, 14326)) THEN V$TYPE_ID = 79;
    ELSE IF(V$PARAM_ID = 14327) THEN V$TYPE_ID = 11;

    FOR
      SELECT DISTINCT L10.PERSON_ID
      FROM PERSON_MOVEMENTS L10
      LEFT JOIN VALD V89 ON V89.OBJ_ID = L10.PERSON_ID AND V89.PARAM_ID = 89 AND V89.IS_DEL = 0
      WHERE L10.OU_ID = :I$SCHOOL_ID AND L10.GROUP_TYPE_ID = 9 AND L10.DATE_DEL IS NULL AND (L10.DATE_IN >= :V$Y OR (:V$TYPE_ID = 11 AND L10.DATE_OUT >= :V$YL))
        AND (:V$TYPE_ID <> 11 OR L10.REASON_OUT IN (812, 5549))
        AND (:V$PARAM_ID <> 14326 OR V89.VAL < :V$DATE14)
        AND NOT EXISTS(
          SELECT FIRST 1 1
          FROM LINKS LT
          LEFT JOIN VALL V614 ON V614.OBJ_ID = LT.OBJ_ID AND V614.PARAM_ID = 614 AND V614.IS_DEL = 0 AND :V$TYPE_ID = 79 -- статус документа
          LEFT JOIN VALL V441 ON V441.OBJ_ID = LT.OBJ_ID AND V441.PARAM_ID = 441 AND V441.IS_DEL = 0 AND :V$PARAM_ID = 14326 -- тип документа
          WHERE LT.PARENT_ID = L10.PERSON_ID AND LT.OBJ_TYPE_ID = :V$TYPE_ID AND LT.DATE_DEL IS NULL
            AND (:V$TYPE_ID <> 79 OR V614.LISTVAL_ID IN (1982, 1984)) -- только для документа - нужен действующий
            AND (:V$PARAM_ID <> 14326 OR V441.LISTVAL_ID = 1368) -- паспорт РФ
        )
      INTO :PUPIL_ID
    DO
    BEGIN
      SELECT CAPTION
      FROM OBJECT_CAPTION_GET(:PUPIL_ID, 23)
      INTO :VAL1;

      VAL3 = NULL;
      SELECT FIRST 1 C.CAPTION
      FROM LINKS LPG
      LEFT JOIN OBJECT_CAPTION_GET(LPG.PARENT_ID) C ON 1 = 1
      WHERE LPG.OBJ_ID = :PUPIL_ID AND LPG.PARENT_TYPE_ID IN (9, 187, 125, 81, 82, 83, 290) AND LPG.DATE_DEL IS NULL
      ORDER BY LPG.PARENT_TYPE_ID
      INTO :VAL3;

      SUSPEND;
    END
  END
  ELSE BEGIN
    FOR
      SELECT DISTINCT L10.PERSON_ID
      FROM PERSON_MOVEMENTS L10
      JOIN LINKS LT ON LT.PARENT_ID = L10.PERSON_ID AND LT.OBJ_TYPE_ID = :V$TYPE_ID AND LT.DATE_DEL IS NULL
      LEFT JOIN VAL_GET(LT.OBJ_ID, :V$PARAM_ID) VL ON 1 = 1
      WHERE L10.OU_ID = :I$SCHOOL_ID AND L10.GROUP_TYPE_ID = 9 AND L10.DATE_DEL IS NULL AND L10.DATE_IN >= :V$Y
        AND VL.V = ''
      INTO :PUPIL_ID
    DO
    BEGIN
      SELECT CAPTION
      FROM OBJECT_CAPTION_GET(:PUPIL_ID, 23)
      INTO :VAL1;

      VAL3 = NULL;
      SELECT FIRST 1 C.CAPTION
      FROM LINKS LPG
      LEFT JOIN OBJECT_CAPTION_GET(LPG.PARENT_ID) C ON 1 = 1
      WHERE LPG.OBJ_ID = :PUPIL_ID AND LPG.PARENT_TYPE_ID IN (9, 187, 125, 81, 82, 83, 290) AND LPG.DATE_DEL IS NULL
      ORDER BY LPG.PARENT_TYPE_ID
      INTO :VAL3;

      SUSPEND;
    END
  END

  /*  IF (I$ROW_NUM IN (1,3,4,5,6,7,8,9)) THEN
    BEGIN
        V$PARAM_ID =
            CASE I$ROW_NUM
                WHEN 1 THEN 108
                WHEN 3 THEN 103
                WHEN 4 THEN 111
                WHEN 5 THEN 1343
                WHEN 6 THEN 1409
                WHEN 7 THEN 80
                WHEN 8 THEN 176
                WHEN 9 THEN 208
            END;
        FOR
            SELECT L10.PARENT_ID,
                   L10.OBJ_ID
            FROM LINKS L7

            JOIN LINKS L8
            ON L8.PARENT_ID = L7.OBJ_ID
            AND L8.DATE_DEL IS NULL
            AND L8.OBJ_TYPE_ID = 8

            JOIN LINKS L9
            ON L9.PARENT_ID = L8.OBJ_ID
            AND L9.DATE_DEL IS NULL
            AND L9.OBJ_TYPE_ID = 9

            JOIN LINKS L10
            ON L10.PARENT_ID = L9.OBJ_ID
            AND L10.DATE_DEL IS NULL
            AND L10.OBJ_TYPE_ID = 10

            LEFT JOIN VAL_GET(L10.OBJ_ID, :V$PARAM_ID) VL
            ON 1=1

            WHERE L7.PARENT_ID = :I$SCHOOL_ID
            AND L7.DATE_DEL IS NULL
            AND L7.OBJ_TYPE_ID = 7
            AND VL.V = ''
                
            INTO :V$OBJ_ID,
                 :PUPIL_ID
        DO
        BEGIN
            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:PUPIL_ID)
            INTO :VAL1;

            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:V$OBJ_ID)
            INTO :VAL3;
            SUSPEND;
        END
    END
    ELSE IF (I$ROW_NUM = 2) THEN
    BEGIN
        V$PARAM_ID = 101;
        FOR
            SELECT L10.PARENT_ID,
                   L10.OBJ_ID
            FROM LINKS L7

            JOIN LINKS L8
            ON L8.PARENT_ID = L7.OBJ_ID
            AND L8.DATE_DEL IS NULL
            AND L8.OBJ_TYPE_ID = 8

            JOIN LINKS L9
            ON L9.PARENT_ID = L8.OBJ_ID
            AND L9.DATE_DEL IS NULL
            AND L9.OBJ_TYPE_ID = 9

            JOIN LINKS L10
            ON L10.PARENT_ID = L9.OBJ_ID
            AND L10.DATE_DEL IS NULL
            AND L10.OBJ_TYPE_ID = 10

            LEFT JOIN VAL_GET(L10.OBJ_ID, :V$PARAM_ID) VL
            ON 1=1

            LEFT JOIN ADR_GET(103, L10.OBJ_ID) VA
            ON 1=1

            WHERE L7.PARENT_ID = :I$SCHOOL_ID
            AND L7.DATE_DEL IS NULL
            AND L7.OBJ_TYPE_ID = 7
            AND VL.V = ''
            AND VA.REGION LIKE 'Санкт-Петербург%'
                
            INTO :V$OBJ_ID,
                 :PUPIL_ID
        DO
        BEGIN
            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:PUPIL_ID)
            INTO :VAL1;

            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:V$OBJ_ID)
            INTO :VAL3;

            SUSPEND;
        END
    END
    ELSE IF (I$ROW_NUM = 10) THEN
    BEGIN
        FOR
            SELECT L10.PARENT_ID,
                   L10.OBJ_ID
            FROM LINKS L7
    
            JOIN LINKS L8
            ON L8.PARENT_ID = L7.OBJ_ID
            AND L8.DATE_DEL IS NULL
            AND L8.OBJ_TYPE_ID = 8
    
            JOIN LINKS L9
            ON L9.PARENT_ID = L8.OBJ_ID
            AND L9.DATE_DEL IS NULL
            AND L9.OBJ_TYPE_ID = 9
    
            JOIN LINKS L10
            ON L10.PARENT_ID = L9.OBJ_ID
            AND L10.DATE_DEL IS NULL
            AND L10.OBJ_TYPE_ID = 10
    
            LEFT JOIN VALL V78
            ON V78.OBJ_ID = L10.OBJ_ID
            AND V78.PARAM_ID = 78
            AND V78.IS_DEL = 0

            WHERE L7.PARENT_ID = :I$SCHOOL_ID
            AND L7.DATE_DEL IS NULL
            AND L7.OBJ_TYPE_ID = 7
            AND V78.OBJ_ID IS NULL

            UNION ALL
    
            SELECT L10.PARENT_ID,
                   L10.OBJ_ID
            FROM LINKS L78
    
            JOIN LINKS L82
            ON L82.PARENT_ID = L78.OBJ_ID
            AND L82.DATE_DEL IS NULL
            AND L82.OBJ_TYPE_ID = 82
    
            JOIN VALI V448
            ON V448.OBJ_ID = L82.OBJ_ID
            AND V448.PARAM_ID = 448
            AND V448.IS_DEL = 0
            AND V448.VAL = :Y
    
            JOIN LINKS L10
            ON L10.PARENT_ID = L82.OBJ_ID
            AND L10.DATE_DEL IS NULL
            AND L10.OBJ_TYPE_ID = 10
    
            LEFT JOIN VALL V78
            ON V78.OBJ_ID = L10.OBJ_ID
            AND V78.PARAM_ID = 78
            AND V78.IS_DEL = 0

            WHERE L78.PARENT_ID = :I$SCHOOL_ID
            AND L78.DATE_DEL IS NULL
            AND L78.OBJ_TYPE_ID = 78
            AND V78.OBJ_ID IS NULL

            INTO :V$OBJ_ID,
                 :PUPIL_ID
        DO
        BEGIN
            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:PUPIL_ID)
            INTO :VAL1;

            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:V$OBJ_ID)
            INTO :VAL3;

            SUSPEND;
        END
    END
    ELSE IF (I$ROW_NUM = 11) THEN
    BEGIN
        V$PARAM_ID = 105;

        M = EXTRACT(MONTH FROM CURRENT_DATE);
        Y = EXTRACT(YEAR FROM CURRENT_DATE);
        IF (M < 9) THEN
        BEGIN
            Y = Y - 1;
        END

        FOR
            SELECT L10.PARENT_ID,
                   L10.OBJ_ID
            FROM LINKS L78
    
            JOIN LINKS L82
            ON L82.PARENT_ID = L78.OBJ_ID
            AND L82.DATE_DEL IS NULL
            AND L82.OBJ_TYPE_ID = 82
    
            JOIN VALI V448
            ON V448.OBJ_ID = L82.OBJ_ID
            AND V448.PARAM_ID = 448
            AND V448.IS_DEL = 0
            AND V448.VAL = :Y
    
            JOIN LINKS L10
            ON L10.PARENT_ID = L82.OBJ_ID
            AND L10.DATE_DEL IS NULL
            AND L10.OBJ_TYPE_ID = 10
    
            LEFT JOIN VAL_GET(L10.OBJ_ID, :V$PARAM_ID) VL
            ON 1=1

            WHERE L78.PARENT_ID = :I$SCHOOL_ID
            AND L78.DATE_DEL IS NULL
            AND L78.OBJ_TYPE_ID = 78
            AND VL.V = ''

            INTO :V$OBJ_ID,
                 :PUPIL_ID
        DO
        BEGIN
            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:PUPIL_ID)
            INTO :VAL1;

            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:V$OBJ_ID)
            INTO :VAL3;

            SUSPEND;
        END
    END
    ELSE IF (I$ROW_NUM = 12) THEN
    BEGIN
        FOR
            SELECT L10.PARENT_ID,
                   L10.OBJ_ID
            FROM LINKS L7

            JOIN LINKS L8
            ON L8.PARENT_ID = L7.OBJ_ID
            AND L8.DATE_DEL IS NULL
            AND L8.OBJ_TYPE_ID = 8

            JOIN LINKS L9
            ON L9.PARENT_ID = L8.OBJ_ID
            AND L9.DATE_DEL IS NULL
            AND L9.OBJ_TYPE_ID = 9

            JOIN LINKS L10
            ON L10.PARENT_ID = L9.OBJ_ID
            AND L10.DATE_DEL IS NULL
            AND L10.OBJ_TYPE_ID = 10

            WHERE L7.PARENT_ID = :I$SCHOOL_ID
            AND L7.DATE_DEL IS NULL
            AND L7.OBJ_TYPE_ID = 7
            AND (
                SELECT COUNT(L79.OBJ_ID)
                FROM LINKS L79
                WHERE L79.OBJ_TYPE_ID = 79
                AND L79.PARENT_ID = L10.OBJ_ID
                AND L79.DATE_DEL IS NULL
            ) = 0
            INTO :V$OBJ_ID,
                 :PUPIL_ID
        DO
        BEGIN
            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:PUPIL_ID)
            INTO :VAL1;

            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:V$OBJ_ID)
            INTO :VAL3;

            SUSPEND;
        END
    END
    ELSE IF (I$ROW_NUM IN (13,14)) THEN
    BEGIN
        V$PARAM_ID =
            CASE I$ROW_NUM
                WHEN 13 THEN 442
                WHEN 14 THEN 559
            END;
        FOR
            SELECT L10.PARENT_ID,
                   L10.OBJ_ID
            FROM LINKS L7

            JOIN LINKS L8
            ON L8.PARENT_ID = L7.OBJ_ID
            AND L8.DATE_DEL IS NULL
            AND L8.OBJ_TYPE_ID = 8

            JOIN LINKS L9
            ON L9.PARENT_ID = L8.OBJ_ID
            AND L9.DATE_DEL IS NULL
            AND L9.OBJ_TYPE_ID = 9

            JOIN LINKS L10
            ON L10.PARENT_ID = L9.OBJ_ID
            AND L10.DATE_DEL IS NULL
            AND L10.OBJ_TYPE_ID = 10

            WHERE L7.PARENT_ID = :I$SCHOOL_ID
            AND L7.DATE_DEL IS NULL
            AND L7.OBJ_TYPE_ID = 7
            AND EXISTS(
                SELECT FIRST 1 1
                FROM LINKS L79

                LEFT JOIN VAL_GET(L79.OBJ_ID, :V$PARAM_ID) VL
                ON 1=1

                WHERE L79.OBJ_TYPE_ID = 79
                AND L79.PARENT_ID = L10.OBJ_ID
                AND L79.DATE_DEL IS NULL
                AND VL.V = ''
            )
            INTO :V$OBJ_ID,
                 :PUPIL_ID
        DO
        BEGIN
            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:PUPIL_ID)
            INTO :VAL1;

            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:V$OBJ_ID)
            INTO :VAL3;

            SUSPEND;
        END
    END
    ELSE IF (I$ROW_NUM = 15) THEN
    BEGIN
        FOR
            SELECT L10.PARENT_ID,
                   L10.OBJ_ID
            FROM LINKS L78
    
            JOIN LINKS L83
            ON L83.PARENT_ID = L78.OBJ_ID
            AND L83.DATE_DEL IS NULL
            AND L83.OBJ_TYPE_ID = 83
    
            JOIN VALI V451
            ON V451.OBJ_ID = L83.OBJ_ID
            AND V451.PARAM_ID = 451
            AND V451.IS_DEL = 0
            AND V451.VAL = :Y
    
            JOIN LINKS L10
            ON L10.PARENT_ID = L83.OBJ_ID
            AND L10.DATE_DEL IS NULL
            AND L10.OBJ_TYPE_ID = 10
    
            WHERE L78.PARENT_ID = :I$SCHOOL_ID
            AND L78.DATE_DEL IS NULL
            AND L78.OBJ_TYPE_ID = 78
            AND (
                SELECT COUNT(L11.OBJ_ID)
                FROM LINKS L11
                WHERE L11.OBJ_TYPE_ID = 11
                AND L11.PARENT_ID = L10.OBJ_ID
                AND L11.DATE_DEL IS NULL
            ) = 0
            INTO :V$OBJ_ID,
                 :PUPIL_ID
        DO
        BEGIN
            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:PUPIL_ID)
            INTO :VAL1;

            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:V$OBJ_ID)
            INTO :VAL3;

            SUSPEND;
        END
    END
    ELSE IF (I$ROW_NUM IN (16,17,18,19)) THEN
    BEGIN
        V$PARAM_ID =
            CASE I$ROW_NUM
                WHEN 16 THEN 50
                WHEN 17 THEN 564
                WHEN 18 THEN 565
                WHEN 19 THEN 566
            END;
        FOR
            SELECT L10.PARENT_ID,
                   L10.OBJ_ID
            FROM LINKS L78
    
            JOIN LINKS L83
            ON L83.PARENT_ID = L78.OBJ_ID
            AND L83.DATE_DEL IS NULL
            AND L83.OBJ_TYPE_ID = 83
    
            JOIN VALI V451
            ON V451.OBJ_ID = L83.OBJ_ID
            AND V451.PARAM_ID = 451
            AND V451.IS_DEL = 0
            AND V451.VAL = :Y
    
            JOIN LINKS L10
            ON L10.PARENT_ID = L83.OBJ_ID
            AND L10.DATE_DEL IS NULL
            AND L10.OBJ_TYPE_ID = 10
    
            WHERE L78.PARENT_ID = :I$SCHOOL_ID
            AND L78.DATE_DEL IS NULL
            AND L78.OBJ_TYPE_ID = 78
            AND EXISTS(
                SELECT FIRST 1 1
                FROM LINKS L11

                LEFT JOIN VAL_GET(L11.OBJ_ID, :V$PARAM_ID) VL
                ON 1=1

                WHERE L11.OBJ_TYPE_ID = 11
                AND L11.PARENT_ID = L10.OBJ_ID
                AND L11.DATE_DEL IS NULL
                AND VL.V = ''
            )
            INTO :V$OBJ_ID,
                 :PUPIL_ID
        DO
        BEGIN
            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:PUPIL_ID)
            INTO :VAL1;

            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:V$OBJ_ID)
            INTO :VAL3;

            SUSPEND;
        END
    END

  */

END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DISTRICT_VERIFICATION_REP4_DTL (
    I$SCHOOL_ID BIGINT,
    I$ROW_NUM SMALLINT,
    I$PARAM_ID BIGINT = null)
RETURNS (
    WORKER_ID BIGINT,
    NAME VARCHAR(4000))
AS
declare variable V$Y1 date;
declare variable V$TYPE_ID bigint;
declare variable V$PARAM_ID bigint;
declare variable T bigint;
declare variable T2 bigint;
declare variable T3 integer;
declare variable T4 integer;
declare variable V$CC bigint;
BEGIN

  V$Y1 = DATEADD(-1 YEAR TO CURRENT_DATE);

  IF(I$PARAM_ID IS NULL) THEN
  BEGIN
    I$ROW_NUM = I$ROW_NUM - 1;

    FOR
      SELECT DISTINCT P.PARAM_ID, P.TYPE_ID, IIF(P.TYPE_ID = 14, -1, P.TYPE_ID), P.GRID_ORDER
      FROM PARAMS P
      JOIN LPARAMS LP ON LP.PARAM_ID = P.PARAM_ID AND LP.IS_DEL = 0 AND LP.EDIT_TYPE >= 0
      JOIN LEVELS L ON L.LEVEL_ID = LP.LEVEL_ID AND L.IS_DEL = 0
      JOIN TASKS T ON T.TASK_ID = L.TASK_ID AND T.IS_DEL = 0
      JOIN MODULES M ON M.MODULE_ID = T.MODULE_ID AND M.IS_DEL = 0 AND M.IS_ACTIVE = 1
      JOIN TYPES OBJT ON OBJT.TYPE_ID = P.TYPE_ID
      JOIN RES R ON R.RES_ID = P.RES_ID AND R.LANG_CODE = 'RU'
      JOIN RES RT ON RT.RES_ID = OBJT.RES_ID AND RT.LANG_CODE = 'RU'
      WHERE P.TYPE_ID IN (14, 79, 12, 15, 33, 34, 35, 36) AND P.IS_DEL = 0 AND P.IS_REQUIRED > 0 -- тут как просто обязательные, но контролирумые
      -- AND ((P.TYPE_ID = 2 AND P.PARAM_ID IN (13, 470)) OR P.TYPE_ID <> 2) -- для ОУ смотрим только лицевой счет
      -- Виртуальные параметры по наличию чего-нибудь - в конец списка
      UNION
      SELECT LV.LISTVAL_ID, 100000, 100000, LV.LISTVAL_ID + 100000
      FROM LISTVALS LV
      JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
      WHERE LV.LIST_ID = 360 AND LV.IS_DEL = 0 AND LV.TAG = 14
      ORDER BY 3, 4
      INTO :T, :T2, :T3, :T4
    DO
    BEGIN             
      IF(I$ROW_NUM = 0) THEN V$PARAM_ID = T;
      I$ROW_NUM = I$ROW_NUM - 1;
    END
  END
  ELSE
  BEGIN
    V$PARAM_ID = I$PARAM_ID;
  END

  SELECT TYPE_ID
  FROM PARAMS
  WHERE PARAM_ID = :V$PARAM_ID
  INTO :V$TYPE_ID;

  -- !!! надо допроверять, может быть проблема по мере наполнения
  IF(V$TYPE_ID IS NULL AND V$PARAM_ID < 1000) THEN EXCEPTION DATA_ERROR 'По данному показателю не предусмотрен просмотр детализации';

  IF(V$TYPE_ID = 14) THEN
  BEGIN
    FOR
      SELECT DISTINCT L14.OBJ_ID
      FROM LINKS L14
      LEFT JOIN VAL_GET(L14.OBJ_ID, :V$PARAM_ID) VL ON 1 = 1
      WHERE L14.PARENT_ID = :I$SCHOOL_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL AND VL.V = ''
      INTO :WORKER_ID
    DO
    BEGIN
      SELECT CAPTION
      FROM OBJECT_CAPTION_GET(:WORKER_ID)
      INTO :NAME;

      SUSPEND;
    END
  END
  ELSE IF(V$TYPE_ID = 15) THEN
  BEGIN
    FOR
      SELECT DISTINCT L14.OBJ_ID
      FROM LINKS L14
      JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
      LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
      LEFT JOIN VAL_GET(L15.OBJ_ID, :V$PARAM_ID) VL ON 1 = 1
      WHERE L14.PARENT_ID = :I$SCHOOL_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL AND VL.V = ''
        AND (V74.VAL IS NULL OR V74.VAL > :V$Y1)
      INTO :WORKER_ID
    DO
    BEGIN
      SELECT CAPTION
      FROM OBJECT_CAPTION_GET(:WORKER_ID)
      INTO :NAME;

      SUSPEND;
    END
  END
  ELSE IF(V$TYPE_ID IS NULL) THEN
  BEGIN
    IF(V$PARAM_ID = 14319) THEN V$TYPE_ID = 79;
    ELSE IF(V$PARAM_ID = 14320) THEN V$TYPE_ID = 15;
    ELSE IF(V$PARAM_ID = 14321) THEN V$TYPE_ID = 34;
    ELSE IF(V$PARAM_ID = 14322) THEN V$TYPE_ID = 36;
    ELSE IF(V$PARAM_ID = 14323) THEN V$TYPE_ID = 85; -- общий стаж
    ELSE IF(V$PARAM_ID = 14324) THEN V$TYPE_ID = 85; -- пед стаж

    IF(V$PARAM_ID = 14323) THEN V$CC = 941;
    IF(V$PARAM_ID = 14324) THEN V$CC = 942;

    FOR
      SELECT DISTINCT L14.OBJ_ID
      FROM LINKS L14
      LEFT JOIN IS_TEACHER(L14.OBJ_ID) IS_T ON :V$TYPE_ID IN (15, 79)
      LEFT JOIN IS_MANAGER(L14.OBJ_ID) IS_M ON :V$TYPE_ID IN (15, 79)
      WHERE L14.PARENT_ID = :I$SCHOOL_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
      AND (:V$TYPE_ID IN (15, 79) OR (:V$PARAM_ID = 14323 AND IS_T.X = 1) OR IS_T.X = 1 OR IS_M.X = 1) -- документы и общий стаж у всех, все прочее только у учителей или руководителей
      AND NOT EXISTS(
        SELECT FIRST 1 1
        FROM LINKS LT
        LEFT JOIN VALD V74 ON V74.OBJ_ID = LT.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0 AND :V$TYPE_ID = 15 -- дата увольнения
        LEFT JOIN VALL V72 ON V72.OBJ_ID = LT.OBJ_ID AND V72.PARAM_ID = 72 AND V72.IS_DEL = 0 AND :V$TYPE_ID = 15 -- основная или дополнительная
        LEFT JOIN VALL V614 ON V614.OBJ_ID = LT.OBJ_ID AND V614.PARAM_ID = 614 AND V614.IS_DEL = 0 AND :V$TYPE_ID = 79 -- статус документа
        LEFT JOIN VALL V465 ON V465.OBJ_ID = LT.OBJ_ID AND V465.PARAM_ID = 465 AND V465.IS_DEL = 0 AND :V$TYPE_ID = 85 AND V465.LISTVAL_ID = :V$CC -- тип стажа
        WHERE LT.PARENT_ID = L14.OBJ_ID AND LT.OBJ_TYPE_ID = :V$TYPE_ID AND LT.DATE_DEL IS NULL
          AND (:V$TYPE_ID <> 15 OR V74.VAL IS NULL) -- только для должности - нужна действующая
          AND (:V$TYPE_ID <> 15 OR V72.LISTVAL_ID = 934) -- только для должности - нужна основная
          AND (:V$TYPE_ID <> 79 OR V614.LISTVAL_ID IN (1982, 1984)) -- только для документа - нужен действующий
          AND (:V$TYPE_ID <> 85 OR V465.LISTVAL_ID IS NULL) -- только для стажа - нужно чтобы был
        )
      INTO :WORKER_ID
    DO
    BEGIN
      SELECT CAPTION
      FROM OBJECT_CAPTION_GET(:WORKER_ID)
      INTO :NAME;

      SUSPEND;
    END
  END
  ELSE
  BEGIN
    FOR
      SELECT DISTINCT L14.OBJ_ID
      FROM LINKS L14
      JOIN LINKS LT ON LT.PARENT_ID = L14.OBJ_ID AND LT.OBJ_TYPE_ID = :V$TYPE_ID AND LT.DATE_DEL IS NULL
      LEFT JOIN VAL_GET(LT.OBJ_ID, :V$PARAM_ID) VL ON 1 = 1
      WHERE L14.PARENT_ID = :I$SCHOOL_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL AND VL.V = ''
      INTO :WORKER_ID
    DO
    BEGIN
      SELECT CAPTION
      FROM OBJECT_CAPTION_GET(:WORKER_ID)
      INTO :NAME;

      SUSPEND;
    END
  END


/*             (:I$ROW_NUM = 1 AND NOT EXISTS(SELECT FIRST 1 1 FROM VALL V243 WHERE V243.OBJ_ID=L14.OBJ_ID AND V243.PARAM_ID=243 AND V243.IS_DEL=0))
             OR (:I$ROW_NUM = 2 AND EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND NOT EXISTS(SELECT FIRST 1 1 FROM VALS V244 WHERE V244.OBJ_ID=L14.OBJ_ID AND V244.PARAM_ID=244 AND V244.IS_DEL=0))
             OR (:I$ROW_NUM = 3 AND EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND NOT EXISTS(SELECT FIRST 1 1 FROM VALA V255 WHERE V255.OBJ_ID=L14.OBJ_ID AND V255.PARAM_ID=255 AND V255.IS_DEL=0))
             OR (:I$ROW_NUM = 4 AND EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND NOT EXISTS(SELECT FIRST 1 1 FROM VALA V262 WHERE V262.OBJ_ID=L14.OBJ_ID AND V262.PARAM_ID=262 AND V262.IS_DEL=0))
             OR (:I$ROW_NUM = 5 AND EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND NOT EXISTS(SELECT FIRST 1 1 FROM VALS V250 WHERE V250.OBJ_ID=L14.OBJ_ID AND V250.PARAM_ID=250 AND V250.IS_DEL=0))
             OR (:I$ROW_NUM = 6 AND EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND NOT EXISTS(SELECT FIRST 1 1 FROM LINKS L85 JOIN VALL V465 ON V465.OBJ_ID = L85.OBJ_ID AND V465.PARAM_ID = 465 AND V465.IS_DEL = 0 JOIN VALD V466 ON V466.OBJ_ID = L85.OBJ_ID AND V466.PARAM_ID = 466 AND V466.IS_DEL = 0 WHERE L85.PARENT_ID=L14.OBJ_ID AND L85.OBJ_TYPE_ID = 85 AND L85.DATE_DEL IS NULL AND V465.LISTVAL_ID = 941))
             OR (:I$ROW_NUM = 7 AND EXISTS(SELECT FIRST 1 1 FROM IS_TEACHER(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) STAFF WHERE STAFF.X=1) AND NOT EXISTS(SELECT FIRST 1 1 FROM LINKS L85 JOIN VALL V465 ON V465.OBJ_ID = L85.OBJ_ID AND V465.PARAM_ID = 465 AND V465.IS_DEL = 0 JOIN VALD V466 ON V466.OBJ_ID = L85.OBJ_ID AND V466.PARAM_ID = 466 AND V466.IS_DEL = 0 WHERE L85.PARENT_ID=L14.OBJ_ID AND L85.OBJ_TYPE_ID = 85 AND L85.DATE_DEL IS NULL AND V465.LISTVAL_ID = 942))
             OR (:I$ROW_NUM = 8 AND EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) STAFF WHERE STAFF.X=1) AND NOT EXISTS(SELECT FIRST 1 1 FROM LINKS L79 WHERE L79.OBJ_TYPE_ID = 79 AND L79.PARENT_ID = L14.OBJ_ID AND L79.DATE_DEL IS NULL))
             OR (:I$ROW_NUM = 9 AND EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) STAFF WHERE STAFF.X=1) AND EXISTS(SELECT FIRST 1 1 FROM LINKS L79 WHERE L79.OBJ_TYPE_ID = 79 AND L79.PARENT_ID = L14.OBJ_ID AND L79.DATE_DEL IS NULL AND NOT EXISTS(SELECT FIRST 1 1 FROM VALS VS WHERE VS.PARAM_ID = 442 AND VS.IS_DEL = 0 AND VS.OBJ_ID = L79.OBJ_ID)))
             OR (:I$ROW_NUM = 10 AND EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) STAFF WHERE STAFF.X=1) AND EXISTS(SELECT FIRST 1 1 FROM LINKS L79 WHERE L79.OBJ_TYPE_ID = 79 AND L79.PARENT_ID = L14.OBJ_ID AND L79.DATE_DEL IS NULL AND NOT EXISTS(SELECT FIRST 1 1 FROM VALS VS WHERE VS.PARAM_ID = 559 AND VS.IS_DEL = 0 AND VS.OBJ_ID = L79.OBJ_ID)))
             OR (:I$ROW_NUM = 11 AND NOT EXISTS(SELECT FIRST 1 1 FROM LINKS L15 JOIN VALL VLL ON VLL.OBJ_ID = L15.OBJ_ID AND VLL.PARAM_ID = 72 AND VLL.IS_DEL = 0 AND VLL.LISTVAL_ID = 934 LEFT JOIN VALD V74 ON V74.PARAM_ID = 74 AND V74.OBJ_ID = L15.OBJ_ID AND V74.IS_DEL = 0 WHERE L15.OBJ_TYPE_ID = 15 AND L15.PARENT_ID = L14.OBJ_ID AND L15.DATE_DEL IS NULL AND V74.VAL IS NULL))
             OR (:I$ROW_NUM = 12 AND EXISTS(SELECT FIRST 1 1 FROM LINKS L15 LEFT JOIN VALF V ON V.OBJ_ID=L15.OBJ_ID AND V.PARAM_ID=71 AND V.IS_DEL=0 WHERE L15.PARENT_ID=L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL AND V.VAL IS NULL))
             OR (:I$ROW_NUM = 13 AND EXISTS(SELECT FIRST 1 1 FROM LINKS L15 LEFT JOIN VALL V ON V.OBJ_ID=L15.OBJ_ID AND V.PARAM_ID=587 AND V.IS_DEL=0 WHERE L15.PARENT_ID=L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL AND V.LISTVAL_ID IS NULL))
             OR (:I$ROW_NUM = 14 AND EXISTS(SELECT FIRST 1 1 FROM LINKS L15 LEFT JOIN VALL V ON V.OBJ_ID=L15.OBJ_ID AND V.PARAM_ID=72 AND V.IS_DEL=0 WHERE L15.PARENT_ID=L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL AND V.LISTVAL_ID IS NULL))
             OR (:I$ROW_NUM = 15 AND EXISTS(SELECT FIRST 1 1 FROM LINKS L15 LEFT JOIN VALD V ON V.OBJ_ID=L15.OBJ_ID AND V.PARAM_ID=73 AND V.IS_DEL=0 WHERE L15.PARENT_ID=L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL AND V.VAL IS NULL))
             OR (:I$ROW_NUM = 16 AND EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM LINKS L33 WHERE L33.OBJ_TYPE_ID = 33 AND L33.PARENT_ID = L14.OBJ_ID AND L33.DATE_DEL IS NULL AND NOT EXISTS(SELECT FIRST 1 1 FROM VALL VS WHERE VS.PARAM_ID = 284 AND VS.IS_DEL = 0 AND VS.OBJ_ID = L33.OBJ_ID)))
             OR (:I$ROW_NUM = 17 AND EXISTS(SELECT FIRST 1 1 FROM IS_TEACHER(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM LINKS L33 WHERE L33.OBJ_TYPE_ID = 33 AND L33.PARENT_ID = L14.OBJ_ID AND L33.DATE_DEL IS NULL AND NOT EXISTS(SELECT FIRST 1 1 FROM VALS V WHERE V.PARAM_ID = 285 AND V.IS_DEL = 0 AND V.OBJ_ID = L33.OBJ_ID)))
             OR (:I$ROW_NUM = 18 AND EXISTS(SELECT FIRST 1 1 FROM IS_TEACHER(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM LINKS L33 WHERE L33.OBJ_TYPE_ID = 33 AND L33.PARENT_ID = L14.OBJ_ID AND L33.DATE_DEL IS NULL AND NOT EXISTS(SELECT FIRST 1 1 FROM VALS V WHERE V.PARAM_ID = 287 AND V.IS_DEL = 0 AND V.OBJ_ID = L33.OBJ_ID)))
             OR (:I$ROW_NUM = 19 AND EXISTS(SELECT FIRST 1 1 FROM IS_TEACHER(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM LINKS L33 WHERE L33.OBJ_TYPE_ID = 33 AND L33.PARENT_ID = L14.OBJ_ID AND L33.DATE_DEL IS NULL AND NOT EXISTS(SELECT FIRST 1 1 FROM VALL V WHERE V.PARAM_ID = 286 AND V.IS_DEL = 0 AND V.OBJ_ID = L33.OBJ_ID)))
             OR (:I$ROW_NUM = 20 AND EXISTS(SELECT FIRST 1 1 FROM IS_TEACHER(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM LINKS L33 WHERE L33.OBJ_TYPE_ID = 33 AND L33.PARENT_ID = L14.OBJ_ID AND L33.DATE_DEL IS NULL AND NOT EXISTS(SELECT FIRST 1 1 FROM VALS V WHERE V.PARAM_ID = 288 AND V.IS_DEL = 0 AND V.OBJ_ID = L33.OBJ_ID)))
             OR (:I$ROW_NUM = 21 AND EXISTS(SELECT FIRST 1 1 FROM IS_TEACHER(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM LINKS L33 WHERE L33.OBJ_TYPE_ID = 33 AND L33.PARENT_ID = L14.OBJ_ID AND L33.DATE_DEL IS NULL AND NOT EXISTS(SELECT FIRST 1 1 FROM VALD V WHERE V.PARAM_ID = 290 AND V.IS_DEL = 0 AND V.OBJ_ID = L33.OBJ_ID)))
             OR (:I$ROW_NUM = 22 AND EXISTS(SELECT FIRST 1 1 FROM IS_TEACHER(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM LINKS L33 WHERE L33.OBJ_TYPE_ID = 33 AND L33.PARENT_ID = L14.OBJ_ID AND L33.DATE_DEL IS NULL AND NOT EXISTS(SELECT FIRST 1 1 FROM VALS V WHERE V.PARAM_ID = 291 AND V.IS_DEL = 0 AND V.OBJ_ID = L33.OBJ_ID)))
             OR (:I$ROW_NUM = 23 AND EXISTS(SELECT FIRST 1 1 FROM IS_TEACHER(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM LINKS L33 WHERE L33.OBJ_TYPE_ID = 33 AND L33.PARENT_ID = L14.OBJ_ID AND L33.DATE_DEL IS NULL AND NOT EXISTS(SELECT FIRST 1 1 FROM VALS V WHERE V.PARAM_ID = 292 AND V.IS_DEL = 0 AND V.OBJ_ID = L33.OBJ_ID)))
             OR (:I$ROW_NUM = 24 AND EXISTS(SELECT FIRST 1 1 FROM IS_TEACHER(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM LINKS L33 WHERE L33.OBJ_TYPE_ID = 33 AND L33.PARENT_ID = L14.OBJ_ID AND L33.DATE_DEL IS NULL AND NOT EXISTS(SELECT FIRST 1 1 FROM VALL V WHERE V.PARAM_ID = 293 AND V.IS_DEL = 0 AND V.OBJ_ID = L33.OBJ_ID)))
             OR (:I$ROW_NUM = 25 AND EXISTS(SELECT FIRST 1 1 FROM IS_TEACHER(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND NOT EXISTS(SELECT FIRST 1 1 FROM LINKS L34 WHERE L34.OBJ_TYPE_ID = 34 AND L34.PARENT_ID = L14.OBJ_ID AND L34.DATE_DEL IS NULL))
             OR (:I$ROW_NUM = 26 AND EXISTS(SELECT FIRST 1 1 FROM IS_TEACHER(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM LINKS L34 WHERE L34.OBJ_TYPE_ID = 34 AND L34.PARENT_ID = L14.OBJ_ID AND L34.DATE_DEL IS NULL AND NOT EXISTS(SELECT FIRST 1 1 FROM VALD V WHERE V.PARAM_ID = 544 AND V.IS_DEL = 0 AND V.OBJ_ID = L34.OBJ_ID)))
             OR (:I$ROW_NUM = 27 AND EXISTS(SELECT FIRST 1 1 FROM IS_TEACHER(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM LINKS L34 WHERE L34.OBJ_TYPE_ID = 34 AND L34.PARENT_ID = L14.OBJ_ID AND L34.DATE_DEL IS NULL AND NOT EXISTS(SELECT FIRST 1 1 FROM VALL V WHERE V.PARAM_ID = 545 AND V.IS_DEL = 0 AND V.OBJ_ID = L34.OBJ_ID)))
             OR (:I$ROW_NUM = 28 AND EXISTS(SELECT FIRST 1 1 FROM IS_TEACHER(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM LINKS L34 WHERE L34.OBJ_TYPE_ID = 34 AND L34.PARENT_ID = L14.OBJ_ID AND L34.DATE_DEL IS NULL AND NOT EXISTS(SELECT FIRST 1 1 FROM VALS V WHERE V.PARAM_ID = 294 AND V.IS_DEL = 0 AND V.OBJ_ID = L34.OBJ_ID)))
             OR (:I$ROW_NUM = 29 AND NOT EXISTS(SELECT FIRST 1 1 FROM LINKS L15 WHERE L15.OBJ_TYPE_ID = 15 AND L15.PARENT_ID = L14.OBJ_ID AND L15.DATE_DEL IS NULL))
             OR (:I$ROW_NUM = 30 AND EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND (EXISTS(SELECT FIRST 1 1 FROM IS_TEACHER(L14.OBJ_ID) WHERE X=1) OR EXISTS(SELECT FIRST 1 1 FROM IS_MANAGER(L14.OBJ_ID) WHERE X=1)) AND NOT EXISTS(SELECT FIRST 1 1 FROM LINKS L36 WHERE L36.OBJ_TYPE_ID = 36 AND L36.PARENT_ID = L14.OBJ_ID AND L36.DATE_DEL IS NULL))
             OR (:I$ROW_NUM = 31 AND EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND (EXISTS(SELECT FIRST 1 1 FROM IS_TEACHER(L14.OBJ_ID) WHERE X=1) OR EXISTS(SELECT FIRST 1 1 FROM IS_MANAGER(L14.OBJ_ID) WHERE X=1)) AND EXISTS(SELECT FIRST 1 1 FROM LINKS L36 WHERE L36.OBJ_TYPE_ID = 36 AND L36.PARENT_ID = L14.OBJ_ID AND L36.DATE_DEL IS NULL AND NOT EXISTS(SELECT FIRST 1 1 FROM VALL V WHERE V.PARAM_ID = 303 AND V.IS_DEL = 0 AND V.OBJ_ID = L36.OBJ_ID)))
             OR (:I$ROW_NUM = 32 AND EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND (EXISTS(SELECT FIRST 1 1 FROM IS_TEACHER(L14.OBJ_ID) WHERE X=1) OR EXISTS(SELECT FIRST 1 1 FROM IS_MANAGER(L14.OBJ_ID) WHERE X=1)) AND EXISTS(SELECT FIRST 1 1 FROM LINKS L36 WHERE L36.OBJ_TYPE_ID = 36 AND L36.PARENT_ID = L14.OBJ_ID AND L36.DATE_DEL IS NULL AND NOT EXISTS(SELECT FIRST 1 1 FROM VALS V WHERE V.PARAM_ID = 304 AND V.IS_DEL = 0 AND V.OBJ_ID = L36.OBJ_ID)))
             OR (:I$ROW_NUM = 33 AND EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND (EXISTS(SELECT FIRST 1 1 FROM IS_TEACHER(L14.OBJ_ID) WHERE X=1) OR EXISTS(SELECT FIRST 1 1 FROM IS_MANAGER(L14.OBJ_ID) WHERE X=1)) AND EXISTS(SELECT FIRST 1 1 FROM LINKS L36 WHERE L36.OBJ_TYPE_ID = 36 AND L36.PARENT_ID = L14.OBJ_ID AND L36.DATE_DEL IS NULL AND NOT EXISTS(SELECT FIRST 1 1 FROM VALL V WHERE V.PARAM_ID = 1024 AND V.IS_DEL = 0 AND V.OBJ_ID = L36.OBJ_ID)))
             OR (:I$ROW_NUM = 34 AND EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND (EXISTS(SELECT FIRST 1 1 FROM IS_TEACHER(L14.OBJ_ID) WHERE X=1) OR EXISTS(SELECT FIRST 1 1 FROM IS_MANAGER(L14.OBJ_ID) WHERE X=1)) AND EXISTS(SELECT FIRST 1 1 FROM LINKS L36 WHERE L36.OBJ_TYPE_ID = 36 AND L36.PARENT_ID = L14.OBJ_ID AND L36.DATE_DEL IS NULL AND NOT EXISTS(SELECT FIRST 1 1 FROM VALI V WHERE V.PARAM_ID = 306 AND V.IS_DEL = 0 AND V.OBJ_ID = L36.OBJ_ID)))
             OR (:I$ROW_NUM = 35 AND EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND (EXISTS(SELECT FIRST 1 1 FROM IS_TEACHER(L14.OBJ_ID) WHERE X=1) OR EXISTS(SELECT FIRST 1 1 FROM IS_MANAGER(L14.OBJ_ID) WHERE X=1)) AND EXISTS(SELECT FIRST 1 1 FROM LINKS L36 WHERE L36.OBJ_TYPE_ID = 36 AND L36.PARENT_ID = L14.OBJ_ID AND L36.DATE_DEL IS NULL AND NOT EXISTS(SELECT FIRST 1 1 FROM VALD V WHERE V.PARAM_ID = 310 AND V.IS_DEL = 0 AND V.OBJ_ID = L36.OBJ_ID)))
*/

END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DISTRICT_VERIFICATION_REPORT (
    I$DISTRICT_ID BIGINT,
    I$INDEX INTEGER = -1)
RETURNS (
    SCHOOL_ID BIGINT,
    COL_NUM SMALLINT,
    VAL VARCHAR(4000),
    DATA VARCHAR(4000),
    ORIENTATION VARCHAR(20),
    PARAM_ID BIGINT,
    TYPE_ID BIGINT,
    ALLVAL INTEGER)
AS
declare variable T smallint;
declare variable V$ORDER integer;
declare variable V1 double precision;
declare variable V2 double precision;
BEGIN

    -- INDEX задает объем обрабатываемых данных
    -- -1 = выдать все данные разом
    -- NULL - выдать только список строк и столбцов
    -- >= 0 - выдать только данные по конкретному столбцу (в I$DISTRICT_ID отдаем столбец)

    ORIENTATION = 'MIXED';
    DATA = NULL;

    IF(I$INDEX < 0 OR I$INDEX IS NULL) THEN
    BEGIN
      -- Список строк
      -- В старом варанте этого вообще не было, и коды были жестко забиты
      SCHOOL_ID = NULL;
      COL_NUM = 0;
      FOR
        SELECT DISTINCT P.PARAM_ID, P.TYPE_ID, R.VAL, RT.VAL, P.GRID_ORDER, P.IS_REQUIRED
        FROM PARAMS P
        JOIN LPARAMS LP ON LP.PARAM_ID = P.PARAM_ID AND LP.IS_DEL = 0 AND LP.EDIT_TYPE >= 0
        JOIN LEVELS L ON L.LEVEL_ID = LP.LEVEL_ID AND L.IS_DEL = 0
        JOIN TASKS T ON T.TASK_ID = L.TASK_ID AND T.IS_DEL = 0
        JOIN MODULES M ON M.MODULE_ID = T.MODULE_ID AND M.IS_DEL = 0 AND M.IS_ACTIVE = 1
        JOIN TYPES OBJT ON OBJT.TYPE_ID = P.TYPE_ID
        JOIN RES R ON R.RES_ID = P.RES_ID AND R.LANG_CODE = 'RU'
        JOIN RES RT ON RT.RES_ID = OBJT.RES_ID AND RT.LANG_CODE = 'RU'
        WHERE P.TYPE_ID IN (16, 61, 492, 490) AND P.IS_DEL = 0 AND P.IS_REQUIRED > 0 -- тут как просто обязательные, но контролирумые
        ORDER BY 2, 5
        INTO :PARAM_ID, :TYPE_ID, :VAL, :DATA, :V$ORDER, :T
      DO
      BEGIN
        IF(T = 2) THEN VAL = VAL || '@';

        -- Добавляем к VAL данные о пределах раскраски
        -- Параметр >>v1>v2
        V1 = NULL;
        V2 = NULL;
        SELECT FIRST 1 V3451.VAL, V3452.VAL
        FROM LINKS LTOP
        JOIN LINKS L498 ON L498.PARENT_ID = LTOP.OBJ_ID AND L498.OBJ_TYPE_ID = 498 AND L498.DATE_DEL IS NULL
        JOIN VALI V3449 ON V3449.OBJ_ID = L498.OBJ_ID AND V3449.PARAM_ID = 3449 AND V3449.IS_DEL = 0 AND V3449.VAL = :PARAM_ID
        LEFT JOIN VALF V3451 ON V3451.OBJ_ID = L498.OBJ_ID AND V3451.PARAM_ID = 3451 AND V3451.IS_DEL = 0
        LEFT JOIN VALF V3452 ON V3452.OBJ_ID = L498.OBJ_ID AND V3452.PARAM_ID = 3452 AND V3452.IS_DEL = 0
        WHERE LTOP.PARENT_ID IS NULL AND LTOP.OBJ_TYPE_ID IN (111, 112) AND LTOP.DATE_DEL IS NULL
        INTO :V1, :V2;

        IF(V1 IS NOT NULL OR V2 IS NOT NULL) THEN VAL = VAL || '>>' || COALESCE(CAST(V1 AS NUMERIC(18, 2)), '') || '>' || COALESCE(CAST(V2 AS NUMERIC(18, 2)), '');

        SUSPEND;
      END

      -- Список столбцов
      DATA = NULL;
      PARAM_ID = NULL;
      TYPE_ID = NULL;
      COL_NUM = 1;
      FOR
        SELECT L2.OBJ_ID
        FROM LINKS L2
        WHERE L2.PARENT_ID = :I$DISTRICT_ID AND L2.DATE_DEL IS NULL AND L2.OBJ_TYPE_ID = 2
        INTO :SCHOOL_ID
      DO
      BEGIN
        VAL = NULL;
        SELECT V.VAL
        FROM VALI V
        WHERE V.OBJ_ID = :SCHOOL_ID AND V.PARAM_ID = 17 AND V.IS_DEL = 0 AND V.VAL > 0
        INTO :VAL;

        IF(VAL IS NULL) THEN
        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:SCHOOL_ID)
        INTO :VAL;

        SUSPEND;
        COL_NUM = COL_NUM + 1;
      END
    END

    -- Если хотим только заголовки - выходим
    IF(I$INDEX IS NULL) THEN EXIT;
    DATA = NULL;

    /*
            CASE V$ROW_NUM
                WHEN 1 THEN 504
                WHEN 2 THEN 505
                WHEN 3 THEN 542
                WHEN 4 THEN 508
                WHEN 5 THEN 486
                WHEN 6 THEN 487
                WHEN 7 THEN 488
                WHEN 8 THEN 489
                WHEN 9 THEN 490
                WHEN 10 THEN 491
                WHEN 11 THEN 492
                WHEN 12 THEN 493
                WHEN 13 THEN 494
                WHEN 14 THEN 495
                WHEN 15 THEN 496
                WHEN 16 THEN 497
                WHEN 17 THEN 498
                WHEN 18 THEN 499
                WHEN 19 THEN 500
                WHEN 20 THEN 501
                WHEN 21 THEN 502
                WHEN 22 THEN 503
                WHEN 23 THEN 509
                WHEN 24 THEN 510
                WHEN 25 THEN 511
                WHEN 26 THEN 512
                WHEN 27 THEN 520
                WHEN 28 THEN 522
                WHEN 29 THEN 521
            END;
    */

    FOR
      SELECT DISTINCT P.PARAM_ID, P.TYPE_ID
      FROM PARAMS P
      JOIN LPARAMS LP ON LP.PARAM_ID = P.PARAM_ID AND LP.IS_DEL = 0 AND LP.EDIT_TYPE >= 0
      JOIN LEVELS L ON L.LEVEL_ID = LP.LEVEL_ID AND L.IS_DEL = 0
      JOIN TASKS T ON T.TASK_ID = L.TASK_ID AND T.IS_DEL = 0
      JOIN MODULES M ON M.MODULE_ID = T.MODULE_ID AND M.IS_DEL = 0 AND M.IS_ACTIVE = 1
      JOIN TYPES OBJT ON OBJT.TYPE_ID = P.TYPE_ID
      WHERE P.TYPE_ID IN (16, 61, 492, 490) AND P.IS_DEL = 0 AND P.IS_REQUIRED > 0 -- тут как просто обязательные, так и контролирумые
      ORDER BY P.TYPE_ID, P.GRID_ORDER
      INTO :PARAM_ID, :TYPE_ID
    DO
    BEGIN
      COL_NUM = 1;

      FOR
        SELECT L2.OBJ_ID
        FROM LINKS L2
        WHERE L2.PARENT_ID = :I$DISTRICT_ID AND L2.DATE_DEL IS NULL AND L2.OBJ_TYPE_ID = 2 AND :I$INDEX < 0
        UNION
        SELECT L2.OBJ_ID
        FROM OBJECTS L2
        WHERE L2.OBJ_ID = :I$DISTRICT_ID AND L2.TYPE_ID = 2 AND :I$INDEX >= 0
        INTO :SCHOOL_ID
      DO
      BEGIN
        IF(TYPE_ID = 16) THEN
        BEGIN
          SELECT COUNT(*), CAST(SUM(IIF(VL.V = '', 1, 0)) AS INTEGER)
          FROM LINKS L73
          JOIN LINKS L16 ON L16.PARENT_ID = L73.OBJ_ID AND L16.DATE_DEL IS NULL AND L16.OBJ_TYPE_ID = 16
          LEFT JOIN VAL_GET(L16.OBJ_ID, :PARAM_ID) VL ON 1 = 1
          WHERE L73.PARENT_ID = :SCHOOL_ID AND L73.OBJ_TYPE_ID = 73 AND L73.DATE_DEL IS NULL
          INTO :ALLVAL, :VAL;
        END
        ELSE IF(TYPE_ID = 61) THEN
        BEGIN
          SELECT COUNT(*), CAST(SUM(IIF(VL.V = '', 1, 0)) AS INTEGER)
          FROM LINKS L73
          JOIN LINKS L16 ON L16.PARENT_ID = L73.OBJ_ID AND L16.DATE_DEL IS NULL AND L16.OBJ_TYPE_ID = 16
          JOIN LINKS L61 ON L61.PARENT_ID = L16.OBJ_ID AND L61.DATE_DEL IS NULL AND L61.OBJ_TYPE_ID = 61
          LEFT JOIN VAL_GET(L61.OBJ_ID, :PARAM_ID) VL ON 1 = 1
          WHERE L73.PARENT_ID = :SCHOOL_ID AND L73.OBJ_TYPE_ID = 73 AND L73.DATE_DEL IS NULL
          INTO :ALLVAL, :VAL;
        END
        ELSE IF(TYPE_ID = 492) THEN
        BEGIN
          SELECT COUNT(*), CAST(SUM(IIF(VL.V = '', 1, 0)) AS INTEGER)
          FROM LINKS L73
          JOIN LINKS L492 ON L492.PARENT_ID = L73.OBJ_ID AND L492.DATE_DEL IS NULL AND L492.OBJ_TYPE_ID = 492
          LEFT JOIN VAL_GET(L492.OBJ_ID, :PARAM_ID) VL ON 1 = 1
          WHERE L73.PARENT_ID = :SCHOOL_ID AND L73.OBJ_TYPE_ID = 73 AND L73.DATE_DEL IS NULL
          INTO :ALLVAL, :VAL;
        END
        ELSE IF(TYPE_ID = 490) THEN
        BEGIN
          SELECT COUNT(*), CAST(SUM(IIF(VL.V = '', 1, 0)) AS INTEGER)
          FROM LINKS L496
          JOIN LINKS L490 ON L490.PARENT_ID = L496.OBJ_ID AND L490.DATE_DEL IS NULL AND L490.OBJ_TYPE_ID = 490
          LEFT JOIN VAL_GET(L490.OBJ_ID, :PARAM_ID) VL ON 1 = 1
          WHERE L496.PARENT_ID = :SCHOOL_ID AND L496.OBJ_TYPE_ID = 496 AND L496.DATE_DEL IS NULL
          INTO :ALLVAL, :VAL;
        END
        SUSPEND;
        COL_NUM = COL_NUM + 1;
      END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DISTRICT_VERIFICATION_REPORT2 (
    I$DISTRICT_ID BIGINT,
    I$INDEX INTEGER = -1)
RETURNS (
    SCHOOL_ID BIGINT,
    COL_NUM SMALLINT,
    VAL VARCHAR(4000),
    DATA VARCHAR(4000),
    ORIENTATION VARCHAR(20),
    PARAM_ID BIGINT,
    TYPE_ID BIGINT,
    ALLVAL INTEGER)
AS
DECLARE VARIABLE V$ROW_NUM SMALLINT;
DECLARE VARIABLE V$PARAM_ID BIGINT;
DECLARE VARIABLE V$ORDER INTEGER;
DECLARE VARIABLE T SMALLINT;
DECLARE VARIABLE V1 DOUBLE PRECISION;
DECLARE VARIABLE V2 DOUBLE PRECISION;
BEGIN

    -- INDEX задает объем обрабатываемых данных
    -- -1 = выдать все данные разом
    -- NULL - выдать только список строк и столбцов
    -- >= 0 - выдать только данные по конкретному столбцу (в I$DISTRICT_ID отдаем столбец)

    ORIENTATION = 'MIXED';
    DATA = NULL;

    IF(I$INDEX < 0 OR I$INDEX IS NULL) THEN
    BEGIN
      -- Список строк
      -- В старом варанте этого вообще не было, и коды были жестко забиты
      SCHOOL_ID = NULL;
      COL_NUM = 0;
      FOR
        SELECT DISTINCT P.PARAM_ID, P.TYPE_ID, R.VAL, RT.VAL, P.GRID_ORDER, P.IS_REQUIRED
        FROM PARAMS P
        JOIN LPARAMS LP ON LP.PARAM_ID = P.PARAM_ID AND LP.IS_DEL = 0 AND LP.EDIT_TYPE >= 0
        JOIN LEVELS L ON L.LEVEL_ID = LP.LEVEL_ID AND L.IS_DEL = 0
        JOIN TASKS T ON T.TASK_ID = L.TASK_ID AND T.IS_DEL = 0
        JOIN MODULES M ON M.MODULE_ID = T.MODULE_ID AND M.IS_DEL = 0 AND M.IS_ACTIVE = 1
        JOIN TYPES OBJT ON OBJT.TYPE_ID = P.TYPE_ID
        JOIN RES R ON R.RES_ID = P.RES_ID AND R.LANG_CODE = 'RU'
        JOIN RES RT ON RT.RES_ID = OBJT.RES_ID AND RT.LANG_CODE = 'RU'
        WHERE P.TYPE_ID IN (2, 17) AND P.IS_DEL = 0 AND P.IS_REQUIRED > 0 -- тут как просто обязательные, но контролирумые
          -- AND ((P.TYPE_ID = 2 AND P.PARAM_ID IN (13, 470)) OR P.TYPE_ID <> 2) -- для ОУ смотрим только лицевой счет
        -- Виртуальные параметры по документам - в конец списка
        UNION
        SELECT LV.LISTVAL_ID, 100000, R.VAL, 'Наличие документов', LV.LISTVAL_ID + 100000, 1
        FROM LISTVALS LV
        JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
        WHERE LV.LIST_ID = 9 AND LV.IS_DEL = 0 AND LV.LISTVAL_ID IN (1047, 1049, 1050, 1051, 1053, 18625)
        ORDER BY 2, 5
        INTO :PARAM_ID, :TYPE_ID, :VAL, :DATA, :V$ORDER, :T
      DO
      BEGIN
        IF(T = 2) THEN VAL = VAL || '@';

        -- Добавляем к VAL данные о пределах раскраски
        -- Параметр >>v1>v2
        V1 = NULL;
        V2 = NULL;
        SELECT FIRST 1 V3451.VAL, V3452.VAL
        FROM LINKS LTOP
        JOIN LINKS L498 ON L498.PARENT_ID = LTOP.OBJ_ID AND L498.OBJ_TYPE_ID = 498 AND L498.DATE_DEL IS NULL
        JOIN VALI V3449 ON V3449.OBJ_ID = L498.OBJ_ID AND V3449.PARAM_ID = 3449 AND V3449.IS_DEL = 0 AND V3449.VAL = :PARAM_ID
        LEFT JOIN VALF V3451 ON V3451.OBJ_ID = L498.OBJ_ID AND V3451.PARAM_ID = 3451 AND V3451.IS_DEL = 0
        LEFT JOIN VALF V3452 ON V3452.OBJ_ID = L498.OBJ_ID AND V3452.PARAM_ID = 3452 AND V3452.IS_DEL = 0
        WHERE LTOP.PARENT_ID IS NULL AND LTOP.OBJ_TYPE_ID IN (111, 112) AND LTOP.DATE_DEL IS NULL
        INTO :V1, :V2;

        IF(V1 IS NOT NULL OR V2 IS NOT NULL) THEN VAL = VAL || '>>' || COALESCE(CAST(V1 AS NUMERIC(18, 2)), '') || '>' || COALESCE(CAST(V2 AS NUMERIC(18, 2)), '');

        SUSPEND;
      END

      -- Список столбцов
      DATA = NULL;
      PARAM_ID = NULL;
      TYPE_ID = NULL;
      COL_NUM = 1;
      FOR
        SELECT L2.OBJ_ID
        FROM LINKS L2
        WHERE L2.PARENT_ID = :I$DISTRICT_ID AND L2.DATE_DEL IS NULL AND L2.OBJ_TYPE_ID = 2
        INTO :SCHOOL_ID
      DO
      BEGIN
        VAL = NULL;
        SELECT V.VAL
        FROM VALI V
        WHERE V.OBJ_ID = :SCHOOL_ID AND V.PARAM_ID = 17 AND V.IS_DEL = 0 AND V.VAL > 0
        INTO :VAL;

        IF(VAL IS NULL) THEN
        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:SCHOOL_ID)
        INTO :VAL;

        SUSPEND;
        COL_NUM = COL_NUM + 1;
      END
    END

    -- Если хотим только заголовки - выходим
    IF(I$INDEX IS NULL) THEN EXIT;
    DATA = NULL;

    FOR
      SELECT DISTINCT P.PARAM_ID, P.TYPE_ID, P.GRID_ORDER
      FROM PARAMS P
      JOIN LPARAMS LP ON LP.PARAM_ID = P.PARAM_ID AND LP.IS_DEL = 0 AND LP.EDIT_TYPE >= 0
      JOIN LEVELS L ON L.LEVEL_ID = LP.LEVEL_ID AND L.IS_DEL = 0
      JOIN TASKS T ON T.TASK_ID = L.TASK_ID AND T.IS_DEL = 0
      JOIN MODULES M ON M.MODULE_ID = T.MODULE_ID AND M.IS_DEL = 0 AND M.IS_ACTIVE = 1
      JOIN TYPES OBJT ON OBJT.TYPE_ID = P.TYPE_ID
      WHERE P.TYPE_ID IN (2, 17) AND P.IS_DEL = 0 AND P.IS_REQUIRED > 0 -- тут как просто обязательные, так и контролирумые
      -- Виртуальные параметры по документам - в конец списка
      UNION
      SELECT LV.LISTVAL_ID, 100000, LV.LISTVAL_ID + 100000
      FROM LISTVALS LV
      JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
      WHERE LV.LIST_ID = 9 AND LV.IS_DEL = 0 AND LV.LISTVAL_ID IN (1047, 1049, 1050, 1051, 1053)
      ORDER BY 2, 3
      INTO :PARAM_ID, :TYPE_ID, :V$ORDER
    DO
    BEGIN
      COL_NUM = 1;

      FOR
        SELECT L2.OBJ_ID
        FROM LINKS L2
        WHERE L2.PARENT_ID = :I$DISTRICT_ID AND L2.DATE_DEL IS NULL AND L2.OBJ_TYPE_ID = 2 AND :I$INDEX < 0
        UNION
        SELECT L2.OBJ_ID
        FROM OBJECTS L2
        WHERE L2.OBJ_ID = :I$DISTRICT_ID AND L2.TYPE_ID = 2 AND :I$INDEX >= 0
        INTO :SCHOOL_ID
      DO
      BEGIN
        IF(TYPE_ID = 2) THEN
        BEGIN
          VAL = '';
          IF(EXISTS(
            SELECT FIRST 1 1
            FROM VAL_GET(:SCHOOL_ID, :PARAM_ID) VL
            WHERE VL.V = ''
          ))
          THEN VAL = 'Нет';
        END
        ELSE IF(TYPE_ID = 17) THEN
        BEGIN
          SELECT COUNT(DISTINCT L17.OBJ_ID)
          FROM LINKS L17
          LEFT JOIN VAL_GET(L17.OBJ_ID, :PARAM_ID) VL ON 1 = 1
          WHERE L17.PARENT_ID = :SCHOOL_ID AND L17.OBJ_TYPE_ID = 17 AND L17.DATE_DEL IS NULL AND VL.V = ''
          INTO :VAL;
        END
        ELSE IF(TYPE_ID = 100000) THEN
        BEGIN
          VAL = '';
          IF(NOT EXISTS(
            SELECT FIRST 1 1
            FROM LINKS L17
            JOIN VALL V613 ON V613.OBJ_ID = L17.OBJ_ID AND V613.PARAM_ID = 613 AND V613.IS_DEL = 0 AND V613.LISTVAL_ID IN (1982, 1984)
            JOIN VALL V471 ON V471.OBJ_ID = L17.OBJ_ID AND V471.PARAM_ID = 471 AND V471.IS_DEL = 0 AND V471.LISTVAL_ID = :PARAM_ID
            WHERE L17.PARENT_ID = :SCHOOL_ID AND L17.OBJ_TYPE_ID = 17 AND L17.DATE_DEL IS NULL
          ))
          THEN VAL = 'Нет';
        END
        SUSPEND;
        COL_NUM = COL_NUM + 1;
      END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DISTRICT_VERIFICATION_REPORT2X (
    I$DISTRICT_ID BIGINT,
    I$INDEX INTEGER = -1)
RETURNS (
    SCHOOL_ID BIGINT,
    COL_NUM SMALLINT,
    VAL VARCHAR(4000),
    DATA VARCHAR(4000),
    ORIENTATION VARCHAR(20),
    PARAM_ID BIGINT,
    TYPE_ID BIGINT,
    ALLVAL INTEGER)
AS
declare variable V$ROOT_ID bigint;
declare variable V1 double precision;
declare variable V2 double precision;
declare variable VCHK varchar(1000);
declare variable V$PT smallint;
declare variable N integer;
begin

  -- Новая версия отчета, работающая по схеме предрасчета и кастомизируемая пользователем
  -- все отчеты DISTRICT_VERIFICATION_REPORTnX совершенно идентичны, отличие только в фильтре по TYPE_ID

  -- INDEX задает объем обрабатываемых данных
  -- -1 = выдать все данные разом
  -- NULL - выдать только список строк и столбцов
  -- >= 0 - этот режим (получение данных по столбцу конкретной ОУ) больше неактуален

  ORIENTATION = 'MIXED';
  DATA = NULL;

  SELECT FIRST 1 L.OBJ_ID
  FROM LINKS L
  WHERE L.PARENT_ID IS NULL AND L.OBJ_TYPE_ID IN (2, 111, 112) AND L.DATE_DEL IS NULL
  INTO :V$ROOT_ID;

  IF(I$INDEX < 0 OR I$INDEX IS NULL) THEN
  BEGIN
    -- Список строк, вместо PARAM_ID выдаем id строки
    SCHOOL_ID = NULL;
    COL_NUM = 0;
    FOR
      SELECT L498.OBJ_ID, T.TYPE_ID, R.VAL || ' (' || PC.VAL || ')', RT.VAL, V3451.VAL, V3452.VAL, V3455.VAL, P.PARAM_TYPE
      FROM LINKS L498
      -- скрываем отключенные проверки
      JOIN VALL V3454 ON V3454.OBJ_ID = L498.OBJ_ID AND V3454.PARAM_ID = 3454 AND V3454.IS_DEL = 0 AND V3454.LISTVAL_ID <> 15821
      JOIN VALL V3468 ON V3468.OBJ_ID = L498.OBJ_ID AND V3468.PARAM_ID = 3468 AND V3468.IS_DEL = 0
      LEFT JOIN LISTVAL_TEXT(V3468.LISTVAL_ID) PC ON 1 = 1
      JOIN VALI V3449 ON V3449.OBJ_ID = L498.OBJ_ID AND V3449.PARAM_ID = 3449 AND V3449.IS_DEL = 0
      JOIN PARAMS P ON P.PARAM_ID = V3449.VAL AND P.IS_DEL = 0
      JOIN VALI V3453 ON V3453.OBJ_ID = L498.OBJ_ID AND V3453.PARAM_ID = 3453 AND V3453.IS_DEL = 0
      JOIN TYPES T ON T.TYPE_ID = V3453.VAL AND T.IS_DEL = 0 AND T.TYPE_ID IN (2, 17, 406, 441, 442, 443, 444, 447, 453, 495)
      JOIN RES R ON R.RES_ID = P.RES_ID AND R.LANG_CODE = 'RU'
      JOIN RES RT ON RT.RES_ID = T.RES_ID AND RT.LANG_CODE = 'RU'
      LEFT JOIN VALF V3451 ON V3451.OBJ_ID = L498.OBJ_ID AND V3451.PARAM_ID = 3451 AND V3451.IS_DEL = 0
      LEFT JOIN VALF V3452 ON V3452.OBJ_ID = L498.OBJ_ID AND V3452.PARAM_ID = 3452 AND V3452.IS_DEL = 0
      LEFT JOIN VALS V3455 ON V3455.OBJ_ID = L498.OBJ_ID AND V3455.PARAM_ID = 3455 AND V3455.IS_DEL = 0
      WHERE L498.PARENT_ID = :V$ROOT_ID AND L498.OBJ_TYPE_ID = 498 AND L498.DATE_DEL IS NULL
      ORDER BY T.SORT_ORDER, P.GRID_ORDER
      INTO :PARAM_ID, :TYPE_ID, :VAL, :DATA, :V1, :V2, :VCHK, :V$PT
    DO
    BEGIN
      IF(VCHK IS NOT NULL) THEN
      BEGIN
        -- Параметр типа LISTVAL, добавляем в текст
        IF(V$PT = 6) THEN
        BEGIN
          SELECT :VAL || ' = ' || C.VAL
          FROM LISTVAL_TEXT(CAST(:VCHK AS BIGINT)) C
          INTO :VAL;
        END
      END

      -- Контролируемый, но не обязательный ?
      -- IF(T = 2) THEN VAL = VAL || '@';

      -- Добавляем к VAL данные о пределах раскраски
      -- Параметр >>v1>v2
      IF(V1 IS NOT NULL OR V2 IS NOT NULL) THEN VAL = VAL || '>>' || COALESCE(CAST(V1 AS NUMERIC(18, 2)), '') || '>' || COALESCE(CAST(V2 AS NUMERIC(18, 2)), '');

      SUSPEND;
    END

    -- Список столбцов
    DATA = NULL;
    PARAM_ID = NULL;
    TYPE_ID = NULL;
    COL_NUM = 1;
    FOR
      SELECT L2.OBJ_ID, VN.VAL, C.CAPTION
      FROM LINKS L2
      LEFT JOIN VALI VN ON VN.OBJ_ID = L2.OBJ_ID AND VN.PARAM_ID = 17 AND VN.IS_DEL = 0 AND VN.VAL > 0
      LEFT JOIN OBJECT_CAPTION_GET(L2.OBJ_ID) C ON 1 = 1
      WHERE L2.PARENT_ID = :I$DISTRICT_ID AND L2.DATE_DEL IS NULL AND L2.OBJ_TYPE_ID = 2
      UNION
      SELECT L2.OBJ_ID, VN.VAL, C.CAPTION
      FROM LINKS L111
      JOIN LINKS L2 ON L2.PARENT_ID = L111.OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      LEFT JOIN VALI VN ON VN.OBJ_ID = L2.OBJ_ID AND VN.PARAM_ID = 17 AND VN.IS_DEL = 0 AND VN.VAL > 0
      LEFT JOIN OBJECT_CAPTION_GET(L2.OBJ_ID) C ON 1 = 1
      WHERE L111.PARENT_ID = :I$DISTRICT_ID AND L111.DATE_DEL IS NULL AND L111.OBJ_TYPE_ID = 111
      ORDER BY 2 NULLS LAST, 1
      INTO :SCHOOL_ID, :N, :DATA
    DO
    BEGIN
      VAL = N;

      IF(VAL IS NULL) THEN VAL = DATA;

      SUSPEND;
      COL_NUM = COL_NUM + 1;
    END
  END

  -- Если хотим только заголовки - выходим
  IF(I$INDEX IS NULL) THEN EXIT;
  DATA = NULL;

  -- Выборка данных по всем ОУ района
  FOR
    SELECT L498.OBJ_ID, P.TYPE_ID
    FROM LINKS L498
    -- скрываем отключенные проверки
    JOIN VALL V3454 ON V3454.OBJ_ID = L498.OBJ_ID AND V3454.PARAM_ID = 3454 AND V3454.IS_DEL = 0 AND V3454.LISTVAL_ID <> 15821
    JOIN VALI V3449 ON V3449.OBJ_ID = L498.OBJ_ID AND V3449.PARAM_ID = 3449 AND V3449.IS_DEL = 0
    JOIN PARAMS P ON P.PARAM_ID = V3449.VAL AND P.IS_DEL = 0
    JOIN VALI V3453 ON V3453.OBJ_ID = L498.OBJ_ID AND V3453.PARAM_ID = 3453 AND V3453.IS_DEL = 0
    JOIN TYPES T ON T.TYPE_ID = V3453.VAL AND T.IS_DEL = 0 AND T.TYPE_ID IN (2, 17, 406, 441, 442, 443, 444, 447, 453, 495)
    WHERE L498.PARENT_ID = :V$ROOT_ID AND L498.OBJ_TYPE_ID = 498 AND L498.DATE_DEL IS NULL
    ORDER BY T.SORT_ORDER, P.GRID_ORDER
    INTO :PARAM_ID, :TYPE_ID
  DO
  BEGIN
    COL_NUM = 1;
    FOR
      SELECT L2.OBJ_ID, VN.VAL, V.CNT, V.FCNT
      FROM LINKS L2
      LEFT JOIN VALI VN ON VN.OBJ_ID = L2.OBJ_ID AND VN.PARAM_ID = 17 AND VN.IS_DEL = 0 AND VN.VAL > 0
      LEFT JOIN VERIFY_VALS V ON V.OBJ_ID = L2.OBJ_ID AND V.PARAM_ID = :PARAM_ID
      WHERE L2.PARENT_ID = :I$DISTRICT_ID AND L2.DATE_DEL IS NULL AND L2.OBJ_TYPE_ID = 2 AND :I$INDEX < 0
      UNION
      SELECT L2.OBJ_ID, VN.VAL, V.CNT, V.FCNT
      FROM LINKS L111
      JOIN LINKS L2 ON L2.PARENT_ID = L111.OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      LEFT JOIN VALI VN ON VN.OBJ_ID = L2.OBJ_ID AND VN.PARAM_ID = 17 AND VN.IS_DEL = 0 AND VN.VAL > 0
      LEFT JOIN VERIFY_VALS V ON V.OBJ_ID = L2.OBJ_ID AND V.PARAM_ID = :PARAM_ID
      WHERE L111.PARENT_ID = :I$DISTRICT_ID AND L111.DATE_DEL IS NULL AND L111.OBJ_TYPE_ID = 111 AND :I$INDEX < 0
      /*UNION
      SELECT L2.OBJ_ID, VN.VAL, V.CNT, V.FCNT
      FROM OBJECTS L2
      LEFT JOIN VALI VN ON VN.OBJ_ID = L2.OBJ_ID AND VN.PARAM_ID = 17 AND VN.IS_DEL = 0 AND VN.VAL > 0
      LEFT JOIN VERIFY_VALS V ON V.OBJ_ID = L2.OBJ_ID AND V.PARAM_ID = :PARAM_ID
      WHERE L2.OBJ_ID = :I$DISTRICT_ID AND L2.TYPE_ID = 2 AND :I$INDEX >= 0*/
      ORDER BY 2 NULLS LAST, 1
      INTO :SCHOOL_ID, :N, :ALLVAL, :VAL
    DO
    BEGIN
      SUSPEND;
      COL_NUM = COL_NUM + 1;
    END
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DISTRICT_VERIFICATION_REPORT3 (
    I$DISTRICT_ID BIGINT,
    I$INDEX INTEGER = -1)
RETURNS (
    SCHOOL_ID BIGINT,
    COL_NUM SMALLINT,
    VAL VARCHAR(4000),
    DATA VARCHAR(4000),
    ORIENTATION VARCHAR(20),
    PARAM_ID BIGINT,
    TYPE_ID BIGINT,
    ALLVAL INTEGER)
AS
declare variable Y integer;
declare variable V$ORDER integer;
declare variable V$ORDER2 integer;
declare variable V$CTYPE bigint;
declare variable V$DATE14 date;
declare variable T smallint;
declare variable V1 double precision;
declare variable V2 double precision;
BEGIN
    ORIENTATION = 'MIXED';
    DATA = NULL;

    -- INDEX задает объем обрабатываемых данных
    -- -1 = выдать все данные разом
    -- NULL - выдать только список строк и столбцов
    -- >= 0 - выдать только данные по конкретному столбцу (в I$DISTRICT_ID отдаем столбец)

    IF(I$INDEX < 0 OR I$INDEX IS NULL) THEN
    BEGIN
      -- Список строк
      -- В старом варанте этого вообще не было, и коды были жестко забиты
      SCHOOL_ID = NULL;
      COL_NUM = 0;
      FOR
        SELECT DISTINCT P.PARAM_ID, P.TYPE_ID, R.VAL, RT.VAL, IIF(P.TYPE_ID = 10, -1, P.TYPE_ID), P.GRID_ORDER, P.IS_REQUIRED
        FROM PARAMS P
        JOIN LPARAMS LP ON LP.PARAM_ID = P.PARAM_ID AND LP.IS_DEL = 0 AND LP.EDIT_TYPE >= 0
        JOIN LEVELS L ON L.LEVEL_ID = LP.LEVEL_ID AND L.IS_DEL = 0
        JOIN TASKS T ON T.TASK_ID = L.TASK_ID AND T.IS_DEL = 0
        JOIN MODULES M ON M.MODULE_ID = T.MODULE_ID AND M.IS_DEL = 0 AND M.IS_ACTIVE = 1
        JOIN TYPES OBJT ON OBJT.TYPE_ID = P.TYPE_ID
        JOIN RES R ON R.RES_ID = P.RES_ID AND R.LANG_CODE = 'RU'
        JOIN RES RT ON RT.RES_ID = OBJT.RES_ID AND RT.LANG_CODE = 'RU'
        WHERE P.TYPE_ID IN (10, 79, 11) AND P.IS_DEL = 0 AND P.IS_REQUIRED > 0 -- тут как просто обязательные, но контролирумые
        -- Виртуальные параметры по наличию чего-нибудь - в конец списка
        UNION
        SELECT LV.LISTVAL_ID, 100000, R.VAL, 'Выполнение контрольных условий', 100000, LV.LISTVAL_ID + 100000, 1
        FROM LISTVALS LV
        JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
        WHERE LV.LIST_ID = 360 AND LV.IS_DEL = 0 AND LV.TAG = 10
        ORDER BY 5, 6
        INTO :PARAM_ID, :TYPE_ID, :VAL, :DATA, :V$ORDER, :V$ORDER2, :T
      DO
      BEGIN
        IF(T = 2) THEN VAL = VAL || '@';

        -- Добавляем к VAL данные о пределах раскраски
        -- Параметр >>v1>v2
        V1 = NULL;
        V2 = NULL;
        SELECT FIRST 1 V3451.VAL, V3452.VAL
        FROM LINKS LTOP
        JOIN LINKS L498 ON L498.PARENT_ID = LTOP.OBJ_ID AND L498.OBJ_TYPE_ID = 498 AND L498.DATE_DEL IS NULL
        JOIN VALI V3449 ON V3449.OBJ_ID = L498.OBJ_ID AND V3449.PARAM_ID = 3449 AND V3449.IS_DEL = 0 AND V3449.VAL = :PARAM_ID
        LEFT JOIN VALF V3451 ON V3451.OBJ_ID = L498.OBJ_ID AND V3451.PARAM_ID = 3451 AND V3451.IS_DEL = 0
        LEFT JOIN VALF V3452 ON V3452.OBJ_ID = L498.OBJ_ID AND V3452.PARAM_ID = 3452 AND V3452.IS_DEL = 0
        WHERE LTOP.PARENT_ID IS NULL AND LTOP.OBJ_TYPE_ID IN (111, 112) AND LTOP.DATE_DEL IS NULL
        INTO :V1, :V2;

        IF(V1 IS NOT NULL OR V2 IS NOT NULL) THEN VAL = VAL || '>>' || COALESCE(CAST(V1 AS NUMERIC(18, 2)), '') || '>' || COALESCE(CAST(V2 AS NUMERIC(18, 2)), '');

        SUSPEND;
      END

      -- Список столбцов
      DATA = NULL;
      PARAM_ID = NULL;
      TYPE_ID = NULL;
      COL_NUM = 1;
      FOR
        SELECT L2.OBJ_ID
        FROM LINKS L2
        WHERE L2.PARENT_ID = :I$DISTRICT_ID AND L2.DATE_DEL IS NULL AND L2.OBJ_TYPE_ID = 2
        INTO :SCHOOL_ID
      DO
      BEGIN
        VAL = NULL;
        SELECT V.VAL
        FROM VALI V
        WHERE V.OBJ_ID = :SCHOOL_ID AND V.PARAM_ID = 17 AND V.IS_DEL = 0 AND V.VAL > 0
        INTO :VAL;

        IF(VAL IS NULL) THEN
        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:SCHOOL_ID)
        INTO :VAL;

        SUSPEND;
        COL_NUM = COL_NUM + 1;
      END
    END

    -- Если хотим только заголовки - выходим
    IF(I$INDEX IS NULL) THEN EXIT;
    DATA = NULL;

    Y = EXTRACT(YEAR FROM CURRENT_DATE);
    IF (EXTRACT(MONTH FROM CURRENT_DATE) < 9) THEN Y = Y - 1;
    V$DATE14 = DATEADD(-14 YEAR TO CURRENT_DATE);
    V$DATE14 = DATEADD(-2 MONTH TO V$DATE14); -- зазор в 2 месяца

    -- Формируем промежуточную таблицу
    INSERT INTO AGREGATE_PUPIL (PUPIL_ID, SCHOOL_ID, PARENT_TYPE_ID, F1)
    -- Действующие ученики
    SELECT L10.OBJ_ID, L2.OBJ_ID, L10.PARENT_TYPE_ID, 0
    FROM LINKS L2
    JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.DATE_DEL IS NULL AND L7.OBJ_TYPE_ID = 7
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
    JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    WHERE ((L2.PARENT_ID = :I$DISTRICT_ID AND :I$INDEX < 0) OR (L2.OBJ_ID = :I$DISTRICT_ID AND L2.PARENT_TYPE_ID IN (111, 112) AND :I$INDEX >= 0)) AND L2.DATE_DEL IS NULL AND L2.OBJ_TYPE_ID = 2
    -- Выбывшие текущего года
    UNION ALL
    SELECT L10.OBJ_ID, L2.OBJ_ID, L10.PARENT_TYPE_ID, 1
    FROM LINKS L2
    JOIN LINKS L78 ON L78.PARENT_ID = L2.OBJ_ID AND L78.DATE_DEL IS NULL AND L78.OBJ_TYPE_ID = 78
    JOIN LINKS L82 ON L82.PARENT_ID = L78.OBJ_ID AND L82.DATE_DEL IS NULL AND L82.OBJ_TYPE_ID = 82
    JOIN VALI V448 ON V448.OBJ_ID = L82.OBJ_ID AND V448.PARAM_ID = 448 AND V448.IS_DEL = 0 AND V448.VAL = :Y
    JOIN LINKS L10 ON L10.PARENT_ID = L82.OBJ_ID AND L10.DATE_DEL IS NULL AND L10.OBJ_TYPE_ID = 10
    WHERE ((L2.PARENT_ID = :I$DISTRICT_ID AND :I$INDEX < 0) OR (L2.OBJ_ID = :I$DISTRICT_ID AND L2.PARENT_TYPE_ID IN (111, 112) AND :I$INDEX >= 0)) AND L2.DATE_DEL IS NULL AND L2.OBJ_TYPE_ID = 2
    -- Окончившие текущего года
    UNION ALL
    SELECT L10.OBJ_ID, L2.OBJ_ID, L10.PARENT_TYPE_ID, 2
    FROM LINKS L2
    JOIN LINKS L78 ON L78.PARENT_ID = L2.OBJ_ID AND L78.DATE_DEL IS NULL AND L78.OBJ_TYPE_ID = 78
    JOIN LINKS L83 ON L83.PARENT_ID = L78.OBJ_ID AND L83.DATE_DEL IS NULL AND L83.OBJ_TYPE_ID = 83
    JOIN VALI V451 ON V451.OBJ_ID = L83.OBJ_ID AND V451.PARAM_ID = 451 AND V451.IS_DEL = 0 AND V451.VAL = :Y
    JOIN LINKS L10 ON L10.PARENT_ID = L83.OBJ_ID AND L10.DATE_DEL IS NULL AND L10.OBJ_TYPE_ID = 10
    WHERE ((L2.PARENT_ID = :I$DISTRICT_ID AND :I$INDEX < 0) OR (L2.OBJ_ID = :I$DISTRICT_ID AND L2.PARENT_TYPE_ID IN (111, 112) AND :I$INDEX >= 0)) AND L2.DATE_DEL IS NULL AND L2.OBJ_TYPE_ID = 2;

    FOR
      SELECT DISTINCT P.PARAM_ID, P.TYPE_ID, IIF(P.TYPE_ID = 10, -1, P.TYPE_ID), P.GRID_ORDER
      FROM PARAMS P
      JOIN LPARAMS LP ON LP.PARAM_ID = P.PARAM_ID AND LP.IS_DEL = 0 AND LP.EDIT_TYPE >= 0
      JOIN LEVELS L ON L.LEVEL_ID = LP.LEVEL_ID AND L.IS_DEL = 0
      JOIN TASKS T ON T.TASK_ID = L.TASK_ID AND T.IS_DEL = 0
      JOIN MODULES M ON M.MODULE_ID = T.MODULE_ID AND M.IS_DEL = 0 AND M.IS_ACTIVE = 1
      JOIN TYPES OBJT ON OBJT.TYPE_ID = P.TYPE_ID
      WHERE P.TYPE_ID IN (10, 79, 11) AND P.IS_DEL = 0 AND P.IS_REQUIRED > 0 -- тут как просто обязательные, но контролирумые
      -- Виртуальные параметры по наличию чего-нибудь - в конец списка
      UNION
      SELECT LV.LISTVAL_ID, 100000, 100000, LV.LISTVAL_ID + 100000
      FROM LISTVALS LV
      JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
      WHERE LV.LIST_ID = 360 AND LV.IS_DEL = 0 AND LV.TAG = 10
      ORDER BY 3, 4
      INTO :PARAM_ID, :TYPE_ID, :V$ORDER, :V$ORDER2
    DO
    BEGIN
      COL_NUM = 1;

      FOR
        SELECT L2.OBJ_ID
        FROM LINKS L2
        WHERE L2.PARENT_ID = :I$DISTRICT_ID AND L2.DATE_DEL IS NULL AND L2.OBJ_TYPE_ID = 2 AND :I$INDEX < 0
        UNION
        SELECT L2.OBJ_ID
        FROM OBJECTS L2
        WHERE L2.OBJ_ID = :I$DISTRICT_ID AND L2.TYPE_ID = 2 AND :I$INDEX >= 0
        INTO :SCHOOL_ID
      DO
      BEGIN
        IF(TYPE_ID = 10) THEN
        BEGIN
          SELECT COUNT(*), CAST(SUM(IIF(VL.V = '', 1, 0)) AS INTEGER)
          FROM AGREGATE_PUPIL L10
          LEFT JOIN VAL_GET(L10.PUPIL_ID, :PARAM_ID) VL ON 1 = 1
          WHERE L10.SCHOOL_ID = :SCHOOL_ID
          INTO :ALLVAL, :VAL;
        END
        ELSE IF(TYPE_ID = 100000) THEN
        BEGIN
          IF(PARAM_ID = 14325) THEN V$CTYPE = 79;
          ELSE IF(PARAM_ID = 14326) THEN V$CTYPE = 79;
          ELSE IF(PARAM_ID = 14327) THEN V$CTYPE = 11;
          ALLVAL = NULL;

          SELECT COUNT(*) -- LIST(L10.PUPIL_ID, ',')
          FROM AGREGATE_PUPIL L10
          LEFT JOIN VALD V89 ON V89.OBJ_ID = L10.PUPIL_ID AND V89.PARAM_ID = 89 AND V89.IS_DEL = 0
          WHERE L10.SCHOOL_ID = :SCHOOL_ID
          AND (:V$CTYPE <> 11 OR L10.F1 = 2)
          AND (:PARAM_ID <> 14326 OR V89.VAL < :V$DATE14)
          AND NOT EXISTS(
            SELECT FIRST 1 1
            FROM LINKS LT
            LEFT JOIN VALL V614 ON V614.OBJ_ID = LT.OBJ_ID AND V614.PARAM_ID = 614 AND V614.IS_DEL = 0 AND :V$CTYPE = 79 -- статус документа
            LEFT JOIN VALL V441 ON V441.OBJ_ID = LT.OBJ_ID AND V441.PARAM_ID = 441 AND V441.IS_DEL = 0 AND :PARAM_ID = 14326 -- тип документа
            WHERE LT.PARENT_ID = L10.PUPIL_ID AND LT.OBJ_TYPE_ID = :V$CTYPE AND LT.DATE_DEL IS NULL
              AND (:V$CTYPE <> 79 OR V614.LISTVAL_ID IN (1982, 1984)) -- только для документа - нужен действующий
              AND (:PARAM_ID <> 14326 OR V441.LISTVAL_ID = 1368) -- паспорт РФ
          )
          INTO :VAL; -- :DATA
        END
        ELSE
        BEGIN
          -- Все прочие данные берем из прямых потомков
          SELECT COUNT(*), CAST(SUM(IIF(VL.V = '', 1, 0)) AS INTEGER)
          FROM AGREGATE_PUPIL L10
          JOIN LINKS LT ON LT.PARENT_ID = L10.PUPIL_ID AND LT.OBJ_TYPE_ID = :TYPE_ID AND LT.DATE_DEL IS NULL
          LEFT JOIN VAL_GET(LT.OBJ_ID, :PARAM_ID) VL ON 1 = 1
          WHERE L10.SCHOOL_ID = :SCHOOL_ID
          INTO :ALLVAL, :VAL;
        END
        SUSPEND;
        COL_NUM = COL_NUM + 1;
      END
    END


    /*
            SELECT SUM(IIF((AP.PARENT_TYPE_ID = 9) AND EXISTS(SELECT FIRST 1 1 FROM VAL_GET(AP.PUPIL_ID, 108) WHERE V=''),1,0)),
                   SUM(IIF((AP.PARENT_TYPE_ID = 9) AND EXISTS(SELECT FIRST 1 1 FROM ADR_GET(103, AP.PUPIL_ID) WHERE REGION LIKE 'Санкт-Петербург%') AND EXISTS(SELECT FIRST 1 1 FROM VAL_GET(AP.PUPIL_ID, 101) WHERE V=''),1,0)),
                   SUM(IIF((AP.PARENT_TYPE_ID = 9) AND EXISTS(SELECT FIRST 1 1 FROM VAL_GET(AP.PUPIL_ID, 103) WHERE V=''),1,0)),
                   SUM(IIF((AP.PARENT_TYPE_ID = 9) AND EXISTS(SELECT FIRST 1 1 FROM VAL_GET(AP.PUPIL_ID, 111) WHERE V=''),1,0)),
                   SUM(IIF((AP.PARENT_TYPE_ID = 9) AND EXISTS(SELECT FIRST 1 1 FROM VAL_GET(AP.PUPIL_ID, 1343) WHERE V=''),1,0)),
                   SUM(IIF((AP.PARENT_TYPE_ID = 9) AND EXISTS(SELECT FIRST 1 1 FROM VAL_GET(AP.PUPIL_ID, 1409) WHERE V=''),1,0)),
                   SUM(IIF((AP.PARENT_TYPE_ID = 9) AND EXISTS(SELECT FIRST 1 1 FROM VAL_GET(AP.PUPIL_ID, 80) WHERE V=''),1,0)),
                   SUM(IIF((AP.PARENT_TYPE_ID = 9) AND EXISTS(SELECT FIRST 1 1 FROM VAL_GET(AP.PUPIL_ID, 176) WHERE V=''),1,0)),
                   SUM(IIF((AP.PARENT_TYPE_ID = 9) AND EXISTS(SELECT FIRST 1 1 FROM VAL_GET(AP.PUPIL_ID, 208) WHERE V=''),1,0)),
                   SUM(IIF((AP.PARENT_TYPE_ID IN (9,82)) AND EXISTS(SELECT FIRST 1 1 FROM VAL_GET(AP.PUPIL_ID, 78) WHERE V=''),1,0)),
                   SUM(IIF((AP.PARENT_TYPE_ID = 82) AND EXISTS(SELECT FIRST 1 1 FROM VAL_GET(AP.PUPIL_ID, 105) WHERE V=''),1,0)),
                   SUM(IIF((AP.PARENT_TYPE_ID = 9) AND AP.F1=1,1,0)),
                   SUM(IIF((AP.PARENT_TYPE_ID = 9) AND AP.F2=1,1,0)),
                   SUM(IIF((AP.PARENT_TYPE_ID = 9) AND AP.F3=1,1,0)),
                   SUM(IIF((AP.PARENT_TYPE_ID = 83) AND AP.F1=1,1,0)),
                   SUM(IIF((AP.PARENT_TYPE_ID = 83) AND AP.F2=1,1,0)),
                   SUM(IIF((AP.PARENT_TYPE_ID = 83) AND AP.F3=1,1,0)),
                   SUM(IIF((AP.PARENT_TYPE_ID = 83) AND AP.F4=1,1,0)),
                   SUM(IIF((AP.PARENT_TYPE_ID = 83) AND AP.F5=1,1,0))
            FROM AGREGATE_PUPIL AP
            WHERE AP.SCHOOL_ID = :SCHOOL_ID
    */

END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DISTRICT_VERIFICATION_REPORT3X (
    I$DISTRICT_ID BIGINT,
    I$INDEX INTEGER = -1)
RETURNS (
    SCHOOL_ID BIGINT,
    COL_NUM SMALLINT,
    VAL VARCHAR(4000),
    DATA VARCHAR(4000),
    ORIENTATION VARCHAR(20),
    PARAM_ID BIGINT,
    TYPE_ID BIGINT,
    ALLVAL INTEGER)
AS
declare variable V$ROOT_ID bigint;
declare variable V1 double precision;
declare variable V2 double precision;
declare variable VCHK varchar(1000);
declare variable V$PT smallint;
declare variable N integer;
begin

  -- Новая версия отчета, работающая по схеме предрасчета и кастомизируемая пользователем
  -- все отчеты DISTRICT_VERIFICATION_REPORTnX совершенно идентичны, отличие только в фильтре по TYPE_ID

  -- INDEX задает объем обрабатываемых данных
  -- -1 = выдать все данные разом
  -- NULL - выдать только список строк и столбцов
  -- >= 0 - этот режим (получение данных по столбцу конкретной ОУ) больше неактуален

  ORIENTATION = 'MIXED';
  DATA = NULL;

  SELECT FIRST 1 L.OBJ_ID
  FROM LINKS L
  WHERE L.PARENT_ID IS NULL AND L.OBJ_TYPE_ID IN (2, 111, 112) AND L.DATE_DEL IS NULL
  INTO :V$ROOT_ID;

  IF(I$INDEX < 0 OR I$INDEX IS NULL) THEN
  BEGIN
    -- Список строк, вместо PARAM_ID выдаем id строки
    SCHOOL_ID = NULL;
    COL_NUM = 0;
    FOR
      SELECT L498.OBJ_ID, T.TYPE_ID, R.VAL || ' (' || PC.VAL || ')', RT.VAL, V3451.VAL, V3452.VAL, V3455.VAL, P.PARAM_TYPE
      FROM LINKS L498
      -- скрываем отключенные проверки
      JOIN VALL V3454 ON V3454.OBJ_ID = L498.OBJ_ID AND V3454.PARAM_ID = 3454 AND V3454.IS_DEL = 0 AND V3454.LISTVAL_ID <> 15821
      JOIN VALL V3468 ON V3468.OBJ_ID = L498.OBJ_ID AND V3468.PARAM_ID = 3468 AND V3468.IS_DEL = 0 AND V3468.LISTVAL_ID IN (14550, 14551, 15815, 15824, 15825, 15826)
      LEFT JOIN LISTVAL_TEXT(V3468.LISTVAL_ID) PC ON 1 = 1
      JOIN VALI V3449 ON V3449.OBJ_ID = L498.OBJ_ID AND V3449.PARAM_ID = 3449 AND V3449.IS_DEL = 0
      JOIN PARAMS P ON P.PARAM_ID = V3449.VAL AND P.IS_DEL = 0
      JOIN VALI V3453 ON V3453.OBJ_ID = L498.OBJ_ID AND V3453.PARAM_ID = 3453 AND V3453.IS_DEL = 0
      JOIN TYPES T ON T.TYPE_ID = V3453.VAL AND T.IS_DEL = 0
      JOIN RES R ON R.RES_ID = P.RES_ID AND R.LANG_CODE = 'RU'
      JOIN RES RT ON RT.RES_ID = T.RES_ID AND RT.LANG_CODE = 'RU'
      LEFT JOIN VALF V3451 ON V3451.OBJ_ID = L498.OBJ_ID AND V3451.PARAM_ID = 3451 AND V3451.IS_DEL = 0
      LEFT JOIN VALF V3452 ON V3452.OBJ_ID = L498.OBJ_ID AND V3452.PARAM_ID = 3452 AND V3452.IS_DEL = 0
      LEFT JOIN VALS V3455 ON V3455.OBJ_ID = L498.OBJ_ID AND V3455.PARAM_ID = 3455 AND V3455.IS_DEL = 0
      WHERE L498.PARENT_ID = :V$ROOT_ID AND L498.OBJ_TYPE_ID = 498 AND L498.DATE_DEL IS NULL
      ORDER BY T.SORT_ORDER, P.GRID_ORDER
      INTO :PARAM_ID, :TYPE_ID, :VAL, :DATA, :V1, :V2, :VCHK, :V$PT
    DO
    BEGIN
      IF(VCHK IS NOT NULL) THEN
      BEGIN
        -- Параметр типа LISTVAL, добавляем в текст
        IF(V$PT = 6) THEN
        BEGIN
          SELECT :VAL || ' = ' || C.VAL
          FROM LISTVAL_TEXT(CAST(:VCHK AS BIGINT)) C
          INTO :VAL;
        END
      END

      -- Контролируемый, но не обязательный ?
      -- IF(T = 2) THEN VAL = VAL || '@';

      -- Добавляем к VAL данные о пределах раскраски
      -- Параметр >>v1>v2
      IF(V1 IS NOT NULL OR V2 IS NOT NULL) THEN VAL = VAL || '>>' || COALESCE(CAST(V1 AS NUMERIC(18, 2)), '') || '>' || COALESCE(CAST(V2 AS NUMERIC(18, 2)), '');

      SUSPEND;
    END

    -- Список столбцов
    DATA = NULL;
    PARAM_ID = NULL;
    TYPE_ID = NULL;
    COL_NUM = 1;
    FOR
      SELECT L2.OBJ_ID, VN.VAL, C.CAPTION
      FROM LINKS L2
      LEFT JOIN VALI VN ON VN.OBJ_ID = L2.OBJ_ID AND VN.PARAM_ID = 17 AND VN.IS_DEL = 0 AND VN.VAL > 0
      LEFT JOIN OBJECT_CAPTION_GET(L2.OBJ_ID) C ON 1 = 1
      WHERE L2.PARENT_ID = :I$DISTRICT_ID AND L2.DATE_DEL IS NULL AND L2.OBJ_TYPE_ID = 2
      UNION
      SELECT L2.OBJ_ID, VN.VAL, C.CAPTION
      FROM LINKS L111
      JOIN LINKS L2 ON L2.PARENT_ID = L111.OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      LEFT JOIN VALI VN ON VN.OBJ_ID = L2.OBJ_ID AND VN.PARAM_ID = 17 AND VN.IS_DEL = 0 AND VN.VAL > 0
      LEFT JOIN OBJECT_CAPTION_GET(L2.OBJ_ID) C ON 1 = 1
      WHERE L111.PARENT_ID = :I$DISTRICT_ID AND L111.DATE_DEL IS NULL AND L111.OBJ_TYPE_ID = 111
      ORDER BY 2 NULLS LAST, 1
      INTO :SCHOOL_ID, :N, :DATA
    DO
    BEGIN
      VAL = N;

      IF(VAL IS NULL) THEN VAL = DATA;

      SUSPEND;
      COL_NUM = COL_NUM + 1;
    END
  END

  -- Если хотим только заголовки - выходим
  IF(I$INDEX IS NULL) THEN EXIT;
  DATA = NULL;

  -- Выборка данных по всем ОУ района
  FOR
    SELECT L498.OBJ_ID, P.TYPE_ID
    FROM LINKS L498
    -- скрываем отключенные проверки
    JOIN VALL V3454 ON V3454.OBJ_ID = L498.OBJ_ID AND V3454.PARAM_ID = 3454 AND V3454.IS_DEL = 0 AND V3454.LISTVAL_ID <> 15821
    JOIN VALL V3468 ON V3468.OBJ_ID = L498.OBJ_ID AND V3468.PARAM_ID = 3468 AND V3468.IS_DEL = 0 AND V3468.LISTVAL_ID IN (14550, 14551, 15815, 15824, 15825, 15826)
    JOIN VALI V3449 ON V3449.OBJ_ID = L498.OBJ_ID AND V3449.PARAM_ID = 3449 AND V3449.IS_DEL = 0
    JOIN PARAMS P ON P.PARAM_ID = V3449.VAL AND P.IS_DEL = 0
    JOIN VALI V3453 ON V3453.OBJ_ID = L498.OBJ_ID AND V3453.PARAM_ID = 3453 AND V3453.IS_DEL = 0
    LEFT JOIN VALI V3455 ON V3455.OBJ_ID = L498.OBJ_ID AND V3455.PARAM_ID = 3455 AND V3455.IS_DEL = 0
    JOIN TYPES T ON T.TYPE_ID = V3453.VAL AND T.IS_DEL = 0
    WHERE L498.PARENT_ID = :V$ROOT_ID AND L498.OBJ_TYPE_ID = 498 AND L498.DATE_DEL IS NULL
    ORDER BY T.SORT_ORDER, P.GRID_ORDER
    INTO :PARAM_ID, :TYPE_ID
  DO
  BEGIN
    COL_NUM = 1;
    FOR
      SELECT L2.OBJ_ID, VN.VAL, V.CNT, V.FCNT
      FROM LINKS L2
      LEFT JOIN VALI VN ON VN.OBJ_ID = L2.OBJ_ID AND VN.PARAM_ID = 17 AND VN.IS_DEL = 0 AND VN.VAL > 0
      LEFT JOIN VERIFY_VALS V ON V.OBJ_ID = L2.OBJ_ID AND V.PARAM_ID = :PARAM_ID
      WHERE L2.PARENT_ID = :I$DISTRICT_ID AND L2.DATE_DEL IS NULL AND L2.OBJ_TYPE_ID = 2 AND :I$INDEX < 0
      UNION
      SELECT L2.OBJ_ID, VN.VAL, V.CNT, V.FCNT
      FROM LINKS L111
      JOIN LINKS L2 ON L2.PARENT_ID = L111.OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      LEFT JOIN VALI VN ON VN.OBJ_ID = L2.OBJ_ID AND VN.PARAM_ID = 17 AND VN.IS_DEL = 0 AND VN.VAL > 0
      LEFT JOIN VERIFY_VALS V ON V.OBJ_ID = L2.OBJ_ID AND V.PARAM_ID = :PARAM_ID
      WHERE L111.PARENT_ID = :I$DISTRICT_ID AND L111.DATE_DEL IS NULL AND L111.OBJ_TYPE_ID = 111 AND :I$INDEX < 0
      /*UNION
      SELECT L2.OBJ_ID, VN.VAL, V.CNT, V.FCNT
      FROM OBJECTS L2
      LEFT JOIN VALI VN ON VN.OBJ_ID = L2.OBJ_ID AND VN.PARAM_ID = 17 AND VN.IS_DEL = 0 AND VN.VAL > 0
      LEFT JOIN VERIFY_VALS V ON V.OBJ_ID = L2.OBJ_ID AND V.PARAM_ID = :PARAM_ID
      WHERE L2.OBJ_ID = :I$DISTRICT_ID AND L2.TYPE_ID = 2 AND :I$INDEX >= 0*/
      ORDER BY 2 NULLS LAST, 1
      INTO :SCHOOL_ID, :N, :ALLVAL, :VAL
    DO
    BEGIN
      SUSPEND;
      COL_NUM = COL_NUM + 1;
    END
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DISTRICT_VERIFICATION_REPORT4 (
    I$DISTRICT_ID BIGINT,
    I$INDEX SMALLINT = -1)
RETURNS (
    SCHOOL_ID BIGINT,
    COL_NUM SMALLINT,
    VAL VARCHAR(4000),
    DATA VARCHAR(4000),
    ORIENTATION VARCHAR(20),
    PARAM_ID BIGINT,
    TYPE_ID BIGINT,
    ALLVAL INTEGER)
AS
declare variable V$ORDER integer;
declare variable V$ORDER2 integer;
declare variable V$Y1 date;
declare variable V$CTYPE bigint;
declare variable V$CC bigint;
declare variable T smallint;
declare variable V1 double precision;
declare variable V2 double precision;
BEGIN

    -- INDEX задает объем обрабатываемых данных
    -- -1 = выдать все данные разом
    -- NULL - выдать только список строк и столбцов
    -- >= 0 - выдать только данные по конкретному столбцу (в I$DISTRICT_ID отдаем столбец)

    ORIENTATION = 'MIXED';
    DATA = NULL;

    V$Y1 = DATEADD(-1 YEAR TO CURRENT_DATE);

    IF(I$INDEX < 0 OR I$INDEX IS NULL) THEN
    BEGIN
      -- Список строк
      -- В старом варанте этого вообще не было, и коды были жестко забиты
      SCHOOL_ID = NULL;
      COL_NUM = 0;
      FOR
        SELECT DISTINCT P.PARAM_ID, P.TYPE_ID, R.VAL, RT.VAL, IIF(P.TYPE_ID = 14, -1, P.TYPE_ID), P.GRID_ORDER, P.IS_REQUIRED
        FROM PARAMS P
        JOIN LPARAMS LP ON LP.PARAM_ID = P.PARAM_ID AND LP.IS_DEL = 0 AND LP.EDIT_TYPE >= 0
        JOIN LEVELS L ON L.LEVEL_ID = LP.LEVEL_ID AND L.IS_DEL = 0
        JOIN TASKS T ON T.TASK_ID = L.TASK_ID AND T.IS_DEL = 0
        JOIN MODULES M ON M.MODULE_ID = T.MODULE_ID AND M.IS_DEL = 0 AND M.IS_ACTIVE = 1
        JOIN TYPES OBJT ON OBJT.TYPE_ID = P.TYPE_ID
        JOIN RES R ON R.RES_ID = P.RES_ID AND R.LANG_CODE = 'RU'
        JOIN RES RT ON RT.RES_ID = OBJT.RES_ID AND RT.LANG_CODE = 'RU'
        WHERE P.TYPE_ID IN (14, 79, 12, 15, 33, 34, 35, 36) AND P.IS_DEL = 0 AND P.IS_REQUIRED > 0 -- тут как просто обязательные, но контролирумые
        -- Виртуальные параметры по наличию чего-нибудь - в конец списка
        UNION
        SELECT LV.LISTVAL_ID, 100000, R.VAL, 'Выполнение контрольных условий', 100000, LV.LISTVAL_ID + 100000, 1
        FROM LISTVALS LV
        JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
        WHERE LV.LIST_ID = 360 AND LV.IS_DEL = 0 AND LV.TAG = 14
        ORDER BY 5, 6
        INTO :PARAM_ID, :TYPE_ID, :VAL, :DATA, :V$ORDER, :V$ORDER2, :T
      DO
      BEGIN
        IF(T = 2) THEN VAL = VAL || '@';

        -- Добавляем к VAL данные о пределах раскраски
        -- Параметр >>v1>v2
        V1 = NULL;
        V2 = NULL;
        SELECT FIRST 1 V3451.VAL, V3452.VAL
        FROM LINKS LTOP
        JOIN LINKS L498 ON L498.PARENT_ID = LTOP.OBJ_ID AND L498.OBJ_TYPE_ID = 498 AND L498.DATE_DEL IS NULL
        JOIN VALI V3449 ON V3449.OBJ_ID = L498.OBJ_ID AND V3449.PARAM_ID = 3449 AND V3449.IS_DEL = 0 AND V3449.VAL = :PARAM_ID
        LEFT JOIN VALF V3451 ON V3451.OBJ_ID = L498.OBJ_ID AND V3451.PARAM_ID = 3451 AND V3451.IS_DEL = 0
        LEFT JOIN VALF V3452 ON V3452.OBJ_ID = L498.OBJ_ID AND V3452.PARAM_ID = 3452 AND V3452.IS_DEL = 0
        WHERE LTOP.PARENT_ID IS NULL AND LTOP.OBJ_TYPE_ID IN (111, 112) AND LTOP.DATE_DEL IS NULL
        INTO :V1, :V2;

        IF(V1 IS NOT NULL OR V2 IS NOT NULL) THEN VAL = VAL || '>>' || COALESCE(CAST(V1 AS NUMERIC(18, 2)), '') || '>' || COALESCE(CAST(V2 AS NUMERIC(18, 2)), '');

        SUSPEND;
      END

      -- Список столбцов
      DATA = NULL;
      PARAM_ID = NULL;
      TYPE_ID = NULL;
      COL_NUM = 1;
      FOR
        SELECT L2.OBJ_ID
        FROM LINKS L2
        WHERE L2.PARENT_ID = :I$DISTRICT_ID AND L2.DATE_DEL IS NULL AND L2.OBJ_TYPE_ID = 2
        INTO :SCHOOL_ID
      DO
      BEGIN
        VAL = NULL;
        SELECT V.VAL
        FROM VALI V
        WHERE V.OBJ_ID = :SCHOOL_ID AND V.PARAM_ID = 17 AND V.IS_DEL = 0 AND V.VAL > 0
        INTO :VAL;

        IF(VAL IS NULL) THEN
        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:SCHOOL_ID)
        INTO :VAL;

        SUSPEND;
        COL_NUM = COL_NUM + 1;
      END
    END

    -- Если хотим только заголовки - выходим
    IF(I$INDEX IS NULL) THEN EXIT;
    DATA = NULL;

    FOR
      SELECT DISTINCT P.PARAM_ID, P.TYPE_ID, IIF(P.TYPE_ID = 14, -1, P.TYPE_ID), P.GRID_ORDER
      FROM PARAMS P
      JOIN LPARAMS LP ON LP.PARAM_ID = P.PARAM_ID AND LP.IS_DEL = 0 AND LP.EDIT_TYPE >= 0
      JOIN LEVELS L ON L.LEVEL_ID = LP.LEVEL_ID AND L.IS_DEL = 0
      JOIN TASKS T ON T.TASK_ID = L.TASK_ID AND T.IS_DEL = 0
      JOIN MODULES M ON M.MODULE_ID = T.MODULE_ID AND M.IS_DEL = 0 AND M.IS_ACTIVE = 1
      JOIN TYPES OBJT ON OBJT.TYPE_ID = P.TYPE_ID
      WHERE P.TYPE_ID IN (14, 79, 12, 15, 33, 34, 35, 36) AND P.IS_DEL = 0 AND P.IS_REQUIRED > 0 -- тут как просто обязательные, но контролирумые
      -- Виртуальные параметры по наличию чего-нибудь - в конец списка
      UNION
      SELECT LV.LISTVAL_ID, 100000, 100000, LV.LISTVAL_ID + 100000
      FROM LISTVALS LV
      JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
      WHERE LV.LIST_ID = 360 AND LV.IS_DEL = 0 AND LV.TAG = 14
      ORDER BY 3, 4
      INTO :PARAM_ID, :TYPE_ID, :V$ORDER, :V$ORDER2
    DO
    BEGIN
      COL_NUM = 1;

      FOR
        SELECT L2.OBJ_ID
        FROM LINKS L2
        WHERE L2.PARENT_ID = :I$DISTRICT_ID AND L2.DATE_DEL IS NULL AND L2.OBJ_TYPE_ID = 2 AND :I$INDEX < 0
        UNION
        SELECT L2.OBJ_ID
        FROM OBJECTS L2
        WHERE L2.OBJ_ID = :I$DISTRICT_ID AND L2.TYPE_ID = 2 AND :I$INDEX >= 0
        INTO :SCHOOL_ID
      DO
      BEGIN
        IF(TYPE_ID = 14) THEN
        BEGIN
          SELECT COUNT(*), CAST(SUM(IIF(VL.V = '', 1, 0)) AS INTEGER)
          FROM LINKS L14
          LEFT JOIN VAL_GET(L14.OBJ_ID, :PARAM_ID) VL ON 1 = 1
          WHERE L14.PARENT_ID = :SCHOOL_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
          INTO :ALLVAL, :VAL;
        END
        ELSE IF(TYPE_ID = 15) THEN
        BEGIN
          -- Должности берем только действующие, либо уволенные < 1 года назад
          SELECT COUNT(*), CAST(SUM(IIF(VL.V = '', 1, 0)) AS INTEGER)
          FROM LINKS L14
          JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
          LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
          LEFT JOIN VAL_GET(L15.OBJ_ID, :PARAM_ID) VL ON 1 = 1
          WHERE L14.PARENT_ID = :SCHOOL_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
            AND (V74.VAL IS NULL OR V74.VAL > :V$Y1)
          INTO :ALLVAL, :VAL;
        END
        ELSE IF(TYPE_ID = 100000) THEN
        BEGIN
          ALLVAL = NULL;
          IF(PARAM_ID = 14319) THEN V$CTYPE = 79;
          ELSE IF(PARAM_ID = 14320) THEN V$CTYPE = 15;
          ELSE IF(PARAM_ID = 14321) THEN V$CTYPE = 34;
          ELSE IF(PARAM_ID = 14322) THEN V$CTYPE = 36;
          ELSE IF(PARAM_ID = 14323) THEN V$CTYPE = 85; -- общий стаж
          ELSE IF(PARAM_ID = 14324) THEN V$CTYPE = 85; -- пед стаж

          IF(PARAM_ID = 14323) THEN V$CC = 941;
          IF(PARAM_ID = 14324) THEN V$CC = 942;

          SELECT COUNT(DISTINCT L14.OBJ_ID)
          FROM LINKS L14
          LEFT JOIN IS_TEACHER(L14.OBJ_ID) IS_T ON :V$CTYPE IN (15, 79)
          LEFT JOIN IS_MANAGER(L14.OBJ_ID) IS_M ON :V$CTYPE IN (15, 79)
          WHERE L14.PARENT_ID = :SCHOOL_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
          AND (:V$CTYPE IN (15, 79) OR (:PARAM_ID = 14323 AND IS_T.X = 1) OR IS_T.X = 1 OR IS_M.X = 1) -- документы и общий стаж у всех, все прочее только у учителей или руководителей
          AND NOT EXISTS(
            SELECT FIRST 1 1
            FROM LINKS LT
            LEFT JOIN VALD V74 ON V74.OBJ_ID = LT.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0 AND :V$CTYPE = 15 -- дата увольнения
            LEFT JOIN VALL V72 ON V72.OBJ_ID = LT.OBJ_ID AND V72.PARAM_ID = 72 AND V72.IS_DEL = 0 AND :V$CTYPE = 15 -- основная или дополнительная
            LEFT JOIN VALL V614 ON V614.OBJ_ID = LT.OBJ_ID AND V614.PARAM_ID = 614 AND V614.IS_DEL = 0 AND :V$CTYPE = 79 -- статус документа
            LEFT JOIN VALL V465 ON V465.OBJ_ID = LT.OBJ_ID AND V465.PARAM_ID = 465 AND V465.IS_DEL = 0 AND :V$CTYPE = 85 AND V465.LISTVAL_ID = :V$CC -- тип стажа
            WHERE LT.PARENT_ID = L14.OBJ_ID AND LT.OBJ_TYPE_ID = :V$CTYPE AND LT.DATE_DEL IS NULL
              AND (:V$CTYPE <> 15 OR V74.VAL IS NULL) -- только для должности - нужна действующая
              AND (:V$CTYPE <> 15 OR V72.LISTVAL_ID = 934) -- только для должности - нужна основная
              AND (:V$CTYPE <> 79 OR V614.LISTVAL_ID IN (1982, 1984)) -- только для документа - нужен действующий
              AND (:V$CTYPE <> 85 OR V465.LISTVAL_ID IS NULL) -- только для стажа - нужно чтобы был
          )
          INTO :VAL;
        END
        ELSE
        BEGIN
          -- Все прочие данные берем из прямых потомков
          SELECT COUNT(*), CAST(SUM(IIF(VL.V = '', 1, 0)) AS INTEGER)
          FROM LINKS L14
          JOIN LINKS LT ON LT.PARENT_ID = L14.OBJ_ID AND LT.OBJ_TYPE_ID = :TYPE_ID AND LT.DATE_DEL IS NULL
          LEFT JOIN VAL_GET(LT.OBJ_ID, :PARAM_ID) VL ON 1 = 1
          WHERE L14.PARENT_ID = :SCHOOL_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
          INTO :ALLVAL, :VAL;
        END
        SUSPEND;
        COL_NUM = COL_NUM + 1;
      END
    END

/*
            SELECT SUM(IIF(NOT EXISTS(SELECT FIRST 1 1 FROM VALL V243 WHERE V243.OBJ_ID=L14.OBJ_ID AND V243.PARAM_ID=243 AND V243.IS_DEL=0),1,0)),
                   SUM(IIF(EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND NOT EXISTS(SELECT FIRST 1 1 FROM VALS V244 WHERE V244.OBJ_ID=L14.OBJ_ID AND V244.PARAM_ID=244 AND V244.IS_DEL=0),1,0)),
                   SUM(IIF(EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND NOT EXISTS(SELECT FIRST 1 1 FROM VALA V255 WHERE V255.OBJ_ID=L14.OBJ_ID AND V255.PARAM_ID=255 AND V255.IS_DEL=0),1,0)),
                   SUM(IIF(EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND NOT EXISTS(SELECT FIRST 1 1 FROM VALA V262 WHERE V262.OBJ_ID=L14.OBJ_ID AND V262.PARAM_ID=262 AND V262.IS_DEL=0),1,0)),
                   SUM(IIF(EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND NOT EXISTS(SELECT FIRST 1 1 FROM VALS V250 WHERE V250.OBJ_ID=L14.OBJ_ID AND V250.PARAM_ID=250 AND V250.IS_DEL=0),1,0)),
                   SUM(IIF(EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND NOT EXISTS(SELECT FIRST 1 1 FROM LINKS L85 JOIN VALL V465 ON V465.OBJ_ID = L85.OBJ_ID AND V465.PARAM_ID = 465 AND V465.IS_DEL = 0 JOIN VALD V466 ON V466.OBJ_ID = L85.OBJ_ID AND V466.PARAM_ID = 466 AND V466.IS_DEL = 0 WHERE L85.PARENT_ID=L14.OBJ_ID AND L85.OBJ_TYPE_ID = 85 AND L85.DATE_DEL IS NULL AND V465.LISTVAL_ID = 941),1,0)),
                   SUM(IIF(EXISTS(SELECT FIRST 1 1 FROM IS_TEACHER(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) STAFF WHERE STAFF.X=1) AND NOT EXISTS(SELECT FIRST 1 1 FROM LINKS L85 JOIN VALL V465 ON V465.OBJ_ID = L85.OBJ_ID AND V465.PARAM_ID = 465 AND V465.IS_DEL = 0 JOIN VALD V466 ON V466.OBJ_ID = L85.OBJ_ID AND V466.PARAM_ID = 466 AND V466.IS_DEL = 0 WHERE L85.PARENT_ID=L14.OBJ_ID AND L85.OBJ_TYPE_ID = 85 AND L85.DATE_DEL IS NULL AND V465.LISTVAL_ID = 942),1,0)),
                   SUM(IIF(EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) STAFF WHERE STAFF.X=1) AND NOT EXISTS(SELECT FIRST 1 1 FROM LINKS L79 WHERE L79.OBJ_TYPE_ID = 79 AND L79.PARENT_ID = L14.OBJ_ID AND L79.DATE_DEL IS NULL),1,0)),
                   SUM(IIF(EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) STAFF WHERE STAFF.X=1) AND EXISTS(SELECT FIRST 1 1 FROM LINKS L79 WHERE L79.OBJ_TYPE_ID = 79 AND L79.PARENT_ID = L14.OBJ_ID AND L79.DATE_DEL IS NULL AND NOT EXISTS(SELECT FIRST 1 1 FROM VALS VS WHERE VS.PARAM_ID = 442 AND VS.IS_DEL = 0 AND VS.OBJ_ID = L79.OBJ_ID)),1,0)),
                   SUM(IIF(EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) STAFF WHERE STAFF.X=1) AND EXISTS(SELECT FIRST 1 1 FROM LINKS L79 WHERE L79.OBJ_TYPE_ID = 79 AND L79.PARENT_ID = L14.OBJ_ID AND L79.DATE_DEL IS NULL AND NOT EXISTS(SELECT FIRST 1 1 FROM VALS VS WHERE VS.PARAM_ID = 559 AND VS.IS_DEL = 0 AND VS.OBJ_ID = L79.OBJ_ID)),1,0)),
                   SUM(IIF(NOT EXISTS(SELECT FIRST 1 1 FROM LINKS L15 JOIN VALL VLL ON VLL.OBJ_ID = L15.OBJ_ID AND VLL.PARAM_ID = 72 AND VLL.IS_DEL = 0 AND VLL.LISTVAL_ID = 934 LEFT JOIN VALD V74 ON V74.PARAM_ID = 74 AND V74.OBJ_ID = L15.OBJ_ID AND V74.IS_DEL = 0 WHERE L15.OBJ_TYPE_ID = 15 AND L15.PARENT_ID = L14.OBJ_ID AND L15.DATE_DEL IS NULL AND V74.VAL IS NULL),1,0)),
                   SUM(IIF(EXISTS(SELECT FIRST 1 1 FROM LINKS L15 LEFT JOIN VALF V ON V.OBJ_ID=L15.OBJ_ID AND V.PARAM_ID=71 AND V.IS_DEL=0 WHERE L15.PARENT_ID=L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL AND V.VAL IS NULL),1,0)),
                   SUM(IIF(EXISTS(SELECT FIRST 1 1 FROM LINKS L15 LEFT JOIN VALL V ON V.OBJ_ID=L15.OBJ_ID AND V.PARAM_ID=587 AND V.IS_DEL=0 WHERE L15.PARENT_ID=L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL AND V.LISTVAL_ID IS NULL),1,0)),
                   SUM(IIF(EXISTS(SELECT FIRST 1 1 FROM LINKS L15 LEFT JOIN VALL V ON V.OBJ_ID=L15.OBJ_ID AND V.PARAM_ID=72 AND V.IS_DEL=0 WHERE L15.PARENT_ID=L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL AND V.LISTVAL_ID IS NULL),1,0)),
                   SUM(IIF(EXISTS(SELECT FIRST 1 1 FROM LINKS L15 LEFT JOIN VALD V ON V.OBJ_ID=L15.OBJ_ID AND V.PARAM_ID=73 AND V.IS_DEL=0 WHERE L15.PARENT_ID=L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL AND V.VAL IS NULL),1,0)),
                   SUM(IIF(EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM LINKS L33 WHERE L33.OBJ_TYPE_ID = 33 AND L33.PARENT_ID = L14.OBJ_ID AND L33.DATE_DEL IS NULL AND NOT EXISTS(SELECT FIRST 1 1 FROM VALL VS WHERE VS.PARAM_ID = 284 AND VS.IS_DEL = 0 AND VS.OBJ_ID = L33.OBJ_ID)),1,0)),
                   SUM(IIF(EXISTS(SELECT FIRST 1 1 FROM IS_TEACHER(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM LINKS L33 WHERE L33.OBJ_TYPE_ID = 33 AND L33.PARENT_ID = L14.OBJ_ID AND L33.DATE_DEL IS NULL AND NOT EXISTS(SELECT FIRST 1 1 FROM VALS V WHERE V.PARAM_ID = 285 AND V.IS_DEL = 0 AND V.OBJ_ID = L33.OBJ_ID)),1,0)),
                   SUM(IIF(EXISTS(SELECT FIRST 1 1 FROM IS_TEACHER(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM LINKS L33 WHERE L33.OBJ_TYPE_ID = 33 AND L33.PARENT_ID = L14.OBJ_ID AND L33.DATE_DEL IS NULL AND NOT EXISTS(SELECT FIRST 1 1 FROM VALS V WHERE V.PARAM_ID = 287 AND V.IS_DEL = 0 AND V.OBJ_ID = L33.OBJ_ID)),1,0)),
                   SUM(IIF(EXISTS(SELECT FIRST 1 1 FROM IS_TEACHER(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM LINKS L33 WHERE L33.OBJ_TYPE_ID = 33 AND L33.PARENT_ID = L14.OBJ_ID AND L33.DATE_DEL IS NULL AND NOT EXISTS(SELECT FIRST 1 1 FROM VALL V WHERE V.PARAM_ID = 286 AND V.IS_DEL = 0 AND V.OBJ_ID = L33.OBJ_ID)),1,0)),
                   SUM(IIF(EXISTS(SELECT FIRST 1 1 FROM IS_TEACHER(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM LINKS L33 WHERE L33.OBJ_TYPE_ID = 33 AND L33.PARENT_ID = L14.OBJ_ID AND L33.DATE_DEL IS NULL AND NOT EXISTS(SELECT FIRST 1 1 FROM VALS V WHERE V.PARAM_ID = 288 AND V.IS_DEL = 0 AND V.OBJ_ID = L33.OBJ_ID)),1,0)),
                   SUM(IIF(EXISTS(SELECT FIRST 1 1 FROM IS_TEACHER(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM LINKS L33 WHERE L33.OBJ_TYPE_ID = 33 AND L33.PARENT_ID = L14.OBJ_ID AND L33.DATE_DEL IS NULL AND NOT EXISTS(SELECT FIRST 1 1 FROM VALD V WHERE V.PARAM_ID = 290 AND V.IS_DEL = 0 AND V.OBJ_ID = L33.OBJ_ID)),1,0)),
                   SUM(IIF(EXISTS(SELECT FIRST 1 1 FROM IS_TEACHER(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM LINKS L33 WHERE L33.OBJ_TYPE_ID = 33 AND L33.PARENT_ID = L14.OBJ_ID AND L33.DATE_DEL IS NULL AND NOT EXISTS(SELECT FIRST 1 1 FROM VALS V WHERE V.PARAM_ID = 291 AND V.IS_DEL = 0 AND V.OBJ_ID = L33.OBJ_ID)),1,0)),
                   SUM(IIF(EXISTS(SELECT FIRST 1 1 FROM IS_TEACHER(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM LINKS L33 WHERE L33.OBJ_TYPE_ID = 33 AND L33.PARENT_ID = L14.OBJ_ID AND L33.DATE_DEL IS NULL AND NOT EXISTS(SELECT FIRST 1 1 FROM VALS V WHERE V.PARAM_ID = 292 AND V.IS_DEL = 0 AND V.OBJ_ID = L33.OBJ_ID)),1,0)),
                   SUM(IIF(EXISTS(SELECT FIRST 1 1 FROM IS_TEACHER(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM LINKS L33 WHERE L33.OBJ_TYPE_ID = 33 AND L33.PARENT_ID = L14.OBJ_ID AND L33.DATE_DEL IS NULL AND NOT EXISTS(SELECT FIRST 1 1 FROM VALL V WHERE V.PARAM_ID = 293 AND V.IS_DEL = 0 AND V.OBJ_ID = L33.OBJ_ID)),1,0)),
                   SUM(IIF(EXISTS(SELECT FIRST 1 1 FROM IS_TEACHER(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND NOT EXISTS(SELECT FIRST 1 1 FROM LINKS L34 WHERE L34.OBJ_TYPE_ID = 34 AND L34.PARENT_ID = L14.OBJ_ID AND L34.DATE_DEL IS NULL),1,0)),
                   SUM(IIF(EXISTS(SELECT FIRST 1 1 FROM IS_TEACHER(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM LINKS L34 WHERE L34.OBJ_TYPE_ID = 34 AND L34.PARENT_ID = L14.OBJ_ID AND L34.DATE_DEL IS NULL AND NOT EXISTS(SELECT FIRST 1 1 FROM VALD V WHERE V.PARAM_ID = 544 AND V.IS_DEL = 0 AND V.OBJ_ID = L34.OBJ_ID)),1,0)),
                   SUM(IIF(EXISTS(SELECT FIRST 1 1 FROM IS_TEACHER(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM LINKS L34 WHERE L34.OBJ_TYPE_ID = 34 AND L34.PARENT_ID = L14.OBJ_ID AND L34.DATE_DEL IS NULL AND NOT EXISTS(SELECT FIRST 1 1 FROM VALL V WHERE V.PARAM_ID = 545 AND V.IS_DEL = 0 AND V.OBJ_ID = L34.OBJ_ID)),1,0)),
                   SUM(IIF(EXISTS(SELECT FIRST 1 1 FROM IS_TEACHER(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM LINKS L34 WHERE L34.OBJ_TYPE_ID = 34 AND L34.PARENT_ID = L14.OBJ_ID AND L34.DATE_DEL IS NULL AND NOT EXISTS(SELECT FIRST 1 1 FROM VALS V WHERE V.PARAM_ID = 294 AND V.IS_DEL = 0 AND V.OBJ_ID = L34.OBJ_ID)),1,0)),
                   SUM(IIF(NOT EXISTS(SELECT FIRST 1 1 FROM LINKS L15 WHERE L15.OBJ_TYPE_ID = 15 AND L15.PARENT_ID = L14.OBJ_ID AND L15.DATE_DEL IS NULL),1,0)),
                   SUM(IIF(EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND (EXISTS(SELECT FIRST 1 1 FROM IS_TEACHER(L14.OBJ_ID) WHERE X=1) OR EXISTS(SELECT FIRST 1 1 FROM IS_MANAGER(L14.OBJ_ID) WHERE X=1)) AND NOT EXISTS(SELECT FIRST 1 1 FROM LINKS L36 WHERE L36.OBJ_TYPE_ID = 36 AND L36.PARENT_ID = L14.OBJ_ID AND L36.DATE_DEL IS NULL),1,0)),
                   SUM(IIF(EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND (EXISTS(SELECT FIRST 1 1 FROM IS_TEACHER(L14.OBJ_ID) WHERE X=1) OR EXISTS(SELECT FIRST 1 1 FROM IS_MANAGER(L14.OBJ_ID) WHERE X=1)) AND EXISTS(SELECT FIRST 1 1 FROM LINKS L36 WHERE L36.OBJ_TYPE_ID = 36 AND L36.PARENT_ID = L14.OBJ_ID AND L36.DATE_DEL IS NULL AND NOT EXISTS(SELECT FIRST 1 1 FROM VALL V WHERE V.PARAM_ID = 303 AND V.IS_DEL = 0 AND V.OBJ_ID = L36.OBJ_ID)),1,0)),
                   SUM(IIF(EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND (EXISTS(SELECT FIRST 1 1 FROM IS_TEACHER(L14.OBJ_ID) WHERE X=1) OR EXISTS(SELECT FIRST 1 1 FROM IS_MANAGER(L14.OBJ_ID) WHERE X=1)) AND EXISTS(SELECT FIRST 1 1 FROM LINKS L36 WHERE L36.OBJ_TYPE_ID = 36 AND L36.PARENT_ID = L14.OBJ_ID AND L36.DATE_DEL IS NULL AND NOT EXISTS(SELECT FIRST 1 1 FROM VALS V WHERE V.PARAM_ID = 304 AND V.IS_DEL = 0 AND V.OBJ_ID = L36.OBJ_ID)),1,0)),
                   SUM(IIF(EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND (EXISTS(SELECT FIRST 1 1 FROM IS_TEACHER(L14.OBJ_ID) WHERE X=1) OR EXISTS(SELECT FIRST 1 1 FROM IS_MANAGER(L14.OBJ_ID) WHERE X=1)) AND EXISTS(SELECT FIRST 1 1 FROM LINKS L36 WHERE L36.OBJ_TYPE_ID = 36 AND L36.PARENT_ID = L14.OBJ_ID AND L36.DATE_DEL IS NULL AND NOT EXISTS(SELECT FIRST 1 1 FROM VALL V WHERE V.PARAM_ID = 1024 AND V.IS_DEL = 0 AND V.OBJ_ID = L36.OBJ_ID)),1,0)),
                   SUM(IIF(EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND (EXISTS(SELECT FIRST 1 1 FROM IS_TEACHER(L14.OBJ_ID) WHERE X=1) OR EXISTS(SELECT FIRST 1 1 FROM IS_MANAGER(L14.OBJ_ID) WHERE X=1)) AND EXISTS(SELECT FIRST 1 1 FROM LINKS L36 WHERE L36.OBJ_TYPE_ID = 36 AND L36.PARENT_ID = L14.OBJ_ID AND L36.DATE_DEL IS NULL AND NOT EXISTS(SELECT FIRST 1 1 FROM VALI V WHERE V.PARAM_ID = 306 AND V.IS_DEL = 0 AND V.OBJ_ID = L36.OBJ_ID)),1,0)),
                   SUM(IIF(EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND (EXISTS(SELECT FIRST 1 1 FROM IS_TEACHER(L14.OBJ_ID) WHERE X=1) OR EXISTS(SELECT FIRST 1 1 FROM IS_MANAGER(L14.OBJ_ID) WHERE X=1)) AND EXISTS(SELECT FIRST 1 1 FROM LINKS L36 WHERE L36.OBJ_TYPE_ID = 36 AND L36.PARENT_ID = L14.OBJ_ID AND L36.DATE_DEL IS NULL AND NOT EXISTS(SELECT FIRST 1 1 FROM VALD V WHERE V.PARAM_ID = 310 AND V.IS_DEL = 0 AND V.OBJ_ID = L36.OBJ_ID)),1,0))
*/

END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DISTRICT_VERIFICATION_REPORT4X (
    I$DISTRICT_ID BIGINT,
    I$INDEX INTEGER = -1)
RETURNS (
    SCHOOL_ID BIGINT,
    COL_NUM SMALLINT,
    VAL VARCHAR(4000),
    DATA VARCHAR(4000),
    ORIENTATION VARCHAR(20),
    PARAM_ID BIGINT,
    TYPE_ID BIGINT,
    ALLVAL INTEGER)
AS
declare variable V$ROOT_ID bigint;
declare variable V1 double precision;
declare variable V2 double precision;
declare variable VCHK varchar(1000);
declare variable V$PT smallint;
declare variable N integer;
begin

  -- Новая версия отчета, работающая по схеме предрасчета и кастомизируемая пользователем
  -- все отчеты DISTRICT_VERIFICATION_REPORTnX совершенно идентичны, отличие только в фильтре по TYPE_ID

  -- INDEX задает объем обрабатываемых данных
  -- -1 = выдать все данные разом
  -- NULL - выдать только список строк и столбцов
  -- >= 0 - этот режим (получение данных по столбцу конкретной ОУ) больше неактуален

  ORIENTATION = 'MIXED';
  DATA = NULL;

  SELECT FIRST 1 L.OBJ_ID
  FROM LINKS L
  WHERE L.PARENT_ID IS NULL AND L.OBJ_TYPE_ID IN (2, 111, 112) AND L.DATE_DEL IS NULL
  INTO :V$ROOT_ID;

  IF(I$INDEX < 0 OR I$INDEX IS NULL) THEN
  BEGIN
    -- Список строк, вместо PARAM_ID выдаем id строки
    SCHOOL_ID = NULL;
    COL_NUM = 0;
    FOR
      SELECT L498.OBJ_ID, T.TYPE_ID, R.VAL || ' (' || PC.VAL || ')', RT.VAL, V3451.VAL, V3452.VAL, V3455.VAL, P.PARAM_TYPE
      FROM LINKS L498
      -- скрываем отключенные проверки
      JOIN VALL V3454 ON V3454.OBJ_ID = L498.OBJ_ID AND V3454.PARAM_ID = 3454 AND V3454.IS_DEL = 0 AND V3454.LISTVAL_ID <> 15821
      JOIN VALL V3468 ON V3468.OBJ_ID = L498.OBJ_ID AND V3468.PARAM_ID = 3468 AND V3468.IS_DEL = 0 AND V3468.LISTVAL_ID IN (15816, 15817, 15818)
      LEFT JOIN LISTVAL_TEXT(V3468.LISTVAL_ID) PC ON 1 = 1
      JOIN VALI V3449 ON V3449.OBJ_ID = L498.OBJ_ID AND V3449.PARAM_ID = 3449 AND V3449.IS_DEL = 0
      JOIN PARAMS P ON P.PARAM_ID = V3449.VAL AND P.IS_DEL = 0
      JOIN VALI V3453 ON V3453.OBJ_ID = L498.OBJ_ID AND V3453.PARAM_ID = 3453 AND V3453.IS_DEL = 0
      JOIN TYPES T ON T.TYPE_ID = V3453.VAL AND T.IS_DEL = 0
      JOIN RES R ON R.RES_ID = P.RES_ID AND R.LANG_CODE = 'RU'
      JOIN RES RT ON RT.RES_ID = T.RES_ID AND RT.LANG_CODE = 'RU'
      LEFT JOIN VALF V3451 ON V3451.OBJ_ID = L498.OBJ_ID AND V3451.PARAM_ID = 3451 AND V3451.IS_DEL = 0
      LEFT JOIN VALF V3452 ON V3452.OBJ_ID = L498.OBJ_ID AND V3452.PARAM_ID = 3452 AND V3452.IS_DEL = 0
      LEFT JOIN VALS V3455 ON V3455.OBJ_ID = L498.OBJ_ID AND V3455.PARAM_ID = 3455 AND V3455.IS_DEL = 0
      WHERE L498.PARENT_ID = :V$ROOT_ID AND L498.OBJ_TYPE_ID = 498 AND L498.DATE_DEL IS NULL
      ORDER BY T.SORT_ORDER, P.GRID_ORDER
      INTO :PARAM_ID, :TYPE_ID, :VAL, :DATA, :V1, :V2, :VCHK, :V$PT
    DO
    BEGIN
      IF(VCHK IS NOT NULL) THEN
      BEGIN
        -- Параметр типа LISTVAL, добавляем в текст
        IF(V$PT = 6) THEN
        BEGIN
          SELECT :VAL || ' = ' || C.VAL
          FROM LISTVAL_TEXT(CAST(:VCHK AS BIGINT)) C
          INTO :VAL;
        END
      END

      -- Контролируемый, но не обязательный ?
      -- IF(T = 2) THEN VAL = VAL || '@';

      -- Добавляем к VAL данные о пределах раскраски
      -- Параметр >>v1>v2
      IF(V1 IS NOT NULL OR V2 IS NOT NULL) THEN VAL = VAL || '>>' || COALESCE(CAST(V1 AS NUMERIC(18, 2)), '') || '>' || COALESCE(CAST(V2 AS NUMERIC(18, 2)), '');

      SUSPEND;
    END

    -- Список столбцов
    DATA = NULL;
    PARAM_ID = NULL;
    TYPE_ID = NULL;
    COL_NUM = 1;
    FOR
      SELECT L2.OBJ_ID, VN.VAL, C.CAPTION
      FROM LINKS L2
      LEFT JOIN VALI VN ON VN.OBJ_ID = L2.OBJ_ID AND VN.PARAM_ID = 17 AND VN.IS_DEL = 0 AND VN.VAL > 0
      LEFT JOIN OBJECT_CAPTION_GET(L2.OBJ_ID) C ON 1 = 1
      WHERE L2.PARENT_ID = :I$DISTRICT_ID AND L2.DATE_DEL IS NULL AND L2.OBJ_TYPE_ID = 2
      UNION
      SELECT L2.OBJ_ID, VN.VAL, C.CAPTION
      FROM LINKS L111
      JOIN LINKS L2 ON L2.PARENT_ID = L111.OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      LEFT JOIN VALI VN ON VN.OBJ_ID = L2.OBJ_ID AND VN.PARAM_ID = 17 AND VN.IS_DEL = 0 AND VN.VAL > 0
      LEFT JOIN OBJECT_CAPTION_GET(L2.OBJ_ID) C ON 1 = 1
      WHERE L111.PARENT_ID = :I$DISTRICT_ID AND L111.DATE_DEL IS NULL AND L111.OBJ_TYPE_ID = 111
      ORDER BY 2 NULLS LAST, 1
      INTO :SCHOOL_ID, :N, :DATA
    DO
    BEGIN
      VAL = N;

      IF(VAL IS NULL) THEN VAL = DATA;

      SUSPEND;
      COL_NUM = COL_NUM + 1;
    END
  END

  -- Если хотим только заголовки - выходим
  IF(I$INDEX IS NULL) THEN EXIT;
  DATA = NULL;

  -- Выборка данных по всем ОУ района
  FOR
    SELECT L498.OBJ_ID, P.TYPE_ID
    FROM LINKS L498
    -- скрываем отключенные проверки
    JOIN VALL V3454 ON V3454.OBJ_ID = L498.OBJ_ID AND V3454.PARAM_ID = 3454 AND V3454.IS_DEL = 0 AND V3454.LISTVAL_ID <> 15821
    JOIN VALI V3449 ON V3449.OBJ_ID = L498.OBJ_ID AND V3449.PARAM_ID = 3449 AND V3449.IS_DEL = 0
    JOIN PARAMS P ON P.PARAM_ID = V3449.VAL AND P.IS_DEL = 0
    JOIN VALI V3453 ON V3453.OBJ_ID = L498.OBJ_ID AND V3453.PARAM_ID = 3453 AND V3453.IS_DEL = 0
    LEFT JOIN VALI V3455 ON V3455.OBJ_ID = L498.OBJ_ID AND V3455.PARAM_ID = 3455 AND V3455.IS_DEL = 0
    JOIN TYPES T ON T.TYPE_ID = V3453.VAL AND T.IS_DEL = 0 AND T.TYPE_ID IN (13, 14, 15, 12, 79, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 85, 376)
    WHERE L498.PARENT_ID = :V$ROOT_ID AND L498.OBJ_TYPE_ID = 498 AND L498.DATE_DEL IS NULL
    ORDER BY T.SORT_ORDER, P.GRID_ORDER
    INTO :PARAM_ID, :TYPE_ID
  DO
  BEGIN
    COL_NUM = 1;
    FOR
      SELECT L2.OBJ_ID, VN.VAL, V.CNT, V.FCNT
      FROM LINKS L2
      LEFT JOIN VALI VN ON VN.OBJ_ID = L2.OBJ_ID AND VN.PARAM_ID = 17 AND VN.IS_DEL = 0 AND VN.VAL > 0
      LEFT JOIN VERIFY_VALS V ON V.OBJ_ID = L2.OBJ_ID AND V.PARAM_ID = :PARAM_ID
      WHERE L2.PARENT_ID = :I$DISTRICT_ID AND L2.DATE_DEL IS NULL AND L2.OBJ_TYPE_ID = 2 AND :I$INDEX < 0
      UNION
      SELECT L2.OBJ_ID, VN.VAL, V.CNT, V.FCNT
      FROM LINKS L111
      JOIN LINKS L2 ON L2.PARENT_ID = L111.OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      LEFT JOIN VALI VN ON VN.OBJ_ID = L2.OBJ_ID AND VN.PARAM_ID = 17 AND VN.IS_DEL = 0 AND VN.VAL > 0
      LEFT JOIN VERIFY_VALS V ON V.OBJ_ID = L2.OBJ_ID AND V.PARAM_ID = :PARAM_ID
      WHERE L111.PARENT_ID = :I$DISTRICT_ID AND L111.DATE_DEL IS NULL AND L111.OBJ_TYPE_ID = 111 AND :I$INDEX < 0
      /*UNION
      SELECT L2.OBJ_ID, VN.VAL, V.CNT, V.FCNT
      FROM OBJECTS L2
      LEFT JOIN VALI VN ON VN.OBJ_ID = L2.OBJ_ID AND VN.PARAM_ID = 17 AND VN.IS_DEL = 0 AND VN.VAL > 0
      LEFT JOIN VERIFY_VALS V ON V.OBJ_ID = L2.OBJ_ID AND V.PARAM_ID = :PARAM_ID
      WHERE L2.OBJ_ID = :I$DISTRICT_ID AND L2.TYPE_ID = 2 AND :I$INDEX >= 0*/
      ORDER BY 2 NULLS LAST, 1
      INTO :SCHOOL_ID, :N, :ALLVAL, :VAL
    DO
    BEGIN
      SUSPEND;
      COL_NUM = COL_NUM + 1;
    END
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DISTRICT_VERIFICATION_REPORT5X (
    I$DISTRICT_ID BIGINT,
    I$INDEX INTEGER = -1)
RETURNS (
    SCHOOL_ID BIGINT,
    COL_NUM SMALLINT,
    VAL VARCHAR(4000),
    DATA VARCHAR(4000),
    ORIENTATION VARCHAR(20),
    PARAM_ID BIGINT,
    TYPE_ID BIGINT,
    ALLVAL INTEGER)
AS
declare variable V$ROOT_ID bigint;
declare variable V1 double precision;
declare variable V2 double precision;
declare variable VCHK varchar(1000);
declare variable V$PT smallint;
declare variable N integer;
begin

  -- Новая версия отчета, работающая по схеме предрасчета и кастомизируемая пользователем
  -- все отчеты DISTRICT_VERIFICATION_REPORTnX совершенно идентичны, отличие только в фильтре по TYPE_ID

  -- INDEX задает объем обрабатываемых данных
  -- -1 = выдать все данные разом
  -- NULL - выдать только список строк и столбцов
  -- >= 0 - этот режим (получение данных по столбцу конкретной ОУ) больше неактуален

  ORIENTATION = 'MIXED';
  DATA = NULL;

  SELECT FIRST 1 L.OBJ_ID
  FROM LINKS L
  WHERE L.PARENT_ID IS NULL AND L.OBJ_TYPE_ID IN (2, 111, 112) AND L.DATE_DEL IS NULL
  INTO :V$ROOT_ID;

  IF(I$INDEX < 0 OR I$INDEX IS NULL) THEN
  BEGIN
    -- Список строк, вместо PARAM_ID выдаем id строки
    SCHOOL_ID = NULL;
    COL_NUM = 0;
    FOR
      SELECT L498.OBJ_ID, T.TYPE_ID, R.VAL || ' (' || PC.VAL || ')', RT.VAL, V3451.VAL, V3452.VAL, V3455.VAL, P.PARAM_TYPE
      FROM LINKS L498
      -- скрываем отключенные проверки
      JOIN VALL V3454 ON V3454.OBJ_ID = L498.OBJ_ID AND V3454.PARAM_ID = 3454 AND V3454.IS_DEL = 0 AND V3454.LISTVAL_ID <> 15821
      JOIN VALL V3468 ON V3468.OBJ_ID = L498.OBJ_ID AND V3468.PARAM_ID = 3468 AND V3468.IS_DEL = 0 AND V3468.LISTVAL_ID IN (15816, 15817, 15818)
      LEFT JOIN LISTVAL_TEXT(V3468.LISTVAL_ID) PC ON 1 = 1
      JOIN VALI V3449 ON V3449.OBJ_ID = L498.OBJ_ID AND V3449.PARAM_ID = 3449 AND V3449.IS_DEL = 0
      JOIN PARAMS P ON P.PARAM_ID = V3449.VAL AND P.IS_DEL = 0
      JOIN VALI V3453 ON V3453.OBJ_ID = L498.OBJ_ID AND V3453.PARAM_ID = 3453 AND V3453.IS_DEL = 0
      JOIN TYPES T ON T.TYPE_ID = V3453.VAL AND T.IS_DEL = 0 AND T.TYPE_ID IN (51, 197, 69, 57, 400, 154, 487, 107, 97, 106, 109, 114)
      JOIN RES R ON R.RES_ID = P.RES_ID AND R.LANG_CODE = 'RU'
      JOIN RES RT ON RT.RES_ID = T.RES_ID AND RT.LANG_CODE = 'RU'
      LEFT JOIN VALF V3451 ON V3451.OBJ_ID = L498.OBJ_ID AND V3451.PARAM_ID = 3451 AND V3451.IS_DEL = 0
      LEFT JOIN VALF V3452 ON V3452.OBJ_ID = L498.OBJ_ID AND V3452.PARAM_ID = 3452 AND V3452.IS_DEL = 0
      LEFT JOIN VALS V3455 ON V3455.OBJ_ID = L498.OBJ_ID AND V3455.PARAM_ID = 3455 AND V3455.IS_DEL = 0
      WHERE L498.PARENT_ID = :V$ROOT_ID AND L498.OBJ_TYPE_ID = 498 AND L498.DATE_DEL IS NULL
      ORDER BY T.SORT_ORDER, P.GRID_ORDER
      INTO :PARAM_ID, :TYPE_ID, :VAL, :DATA, :V1, :V2, :VCHK, :V$PT
    DO
    BEGIN
      IF(VCHK IS NOT NULL) THEN
      BEGIN
        -- Параметр типа LISTVAL, добавляем в текст
        IF(V$PT = 6) THEN
        BEGIN
          SELECT :VAL || ' = ' || C.VAL
          FROM LISTVAL_TEXT(CAST(:VCHK AS BIGINT)) C
          INTO :VAL;
        END
      END

      -- Контролируемый, но не обязательный ?
      -- IF(T = 2) THEN VAL = VAL || '@';

      -- Добавляем к VAL данные о пределах раскраски
      -- Параметр >>v1>v2
      IF(V1 IS NOT NULL OR V2 IS NOT NULL) THEN VAL = VAL || '>>' || COALESCE(CAST(V1 AS NUMERIC(18, 2)), '') || '>' || COALESCE(CAST(V2 AS NUMERIC(18, 2)), '');

      SUSPEND;
    END

    -- Список столбцов
    DATA = NULL;
    PARAM_ID = NULL;
    TYPE_ID = NULL;
    COL_NUM = 1;
    FOR
      SELECT L2.OBJ_ID, VN.VAL, C.CAPTION
      FROM LINKS L2
      LEFT JOIN VALI VN ON VN.OBJ_ID = L2.OBJ_ID AND VN.PARAM_ID = 17 AND VN.IS_DEL = 0 AND VN.VAL > 0
      LEFT JOIN OBJECT_CAPTION_GET(L2.OBJ_ID) C ON 1 = 1
      WHERE L2.PARENT_ID = :I$DISTRICT_ID AND L2.DATE_DEL IS NULL AND L2.OBJ_TYPE_ID = 2
      UNION
      SELECT L2.OBJ_ID, VN.VAL, C.CAPTION
      FROM LINKS L111
      JOIN LINKS L2 ON L2.PARENT_ID = L111.OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      LEFT JOIN VALI VN ON VN.OBJ_ID = L2.OBJ_ID AND VN.PARAM_ID = 17 AND VN.IS_DEL = 0 AND VN.VAL > 0
      LEFT JOIN OBJECT_CAPTION_GET(L2.OBJ_ID) C ON 1 = 1
      WHERE L111.PARENT_ID = :I$DISTRICT_ID AND L111.DATE_DEL IS NULL AND L111.OBJ_TYPE_ID = 111
      ORDER BY 2 NULLS LAST, 1
      INTO :SCHOOL_ID, :N, :DATA
    DO
    BEGIN
      VAL = N;

      IF(VAL IS NULL) THEN VAL = DATA;

      SUSPEND;
      COL_NUM = COL_NUM + 1;
    END
  END

  -- Если хотим только заголовки - выходим
  IF(I$INDEX IS NULL) THEN EXIT;
  DATA = NULL;

  -- Выборка данных по всем ОУ района
  FOR
    SELECT L498.OBJ_ID, P.TYPE_ID
    FROM LINKS L498
    -- скрываем отключенные проверки
    JOIN VALL V3454 ON V3454.OBJ_ID = L498.OBJ_ID AND V3454.PARAM_ID = 3454 AND V3454.IS_DEL = 0 AND V3454.LISTVAL_ID <> 15821
    JOIN VALI V3449 ON V3449.OBJ_ID = L498.OBJ_ID AND V3449.PARAM_ID = 3449 AND V3449.IS_DEL = 0
    JOIN PARAMS P ON P.PARAM_ID = V3449.VAL AND P.IS_DEL = 0
    JOIN VALI V3453 ON V3453.OBJ_ID = L498.OBJ_ID AND V3453.PARAM_ID = 3453 AND V3453.IS_DEL = 0
    JOIN TYPES T ON T.TYPE_ID = V3453.VAL AND T.IS_DEL = 0 AND T.TYPE_ID IN (51, 197, 69, 57, 400, 154, 487, 107, 97, 106, 109, 114)
    WHERE L498.PARENT_ID = :V$ROOT_ID AND L498.OBJ_TYPE_ID = 498 AND L498.DATE_DEL IS NULL
    ORDER BY T.SORT_ORDER, P.GRID_ORDER
    INTO :PARAM_ID, :TYPE_ID
  DO
  BEGIN
    COL_NUM = 1;
    FOR
      SELECT L2.OBJ_ID, VN.VAL, V.CNT, V.FCNT
      FROM LINKS L2
      LEFT JOIN VALI VN ON VN.OBJ_ID = L2.OBJ_ID AND VN.PARAM_ID = 17 AND VN.IS_DEL = 0 AND VN.VAL > 0
      LEFT JOIN VERIFY_VALS V ON V.OBJ_ID = L2.OBJ_ID AND V.PARAM_ID = :PARAM_ID
      WHERE L2.PARENT_ID = :I$DISTRICT_ID AND L2.DATE_DEL IS NULL AND L2.OBJ_TYPE_ID = 2 AND :I$INDEX < 0
      UNION
      SELECT L2.OBJ_ID, VN.VAL, V.CNT, V.FCNT
      FROM LINKS L111
      JOIN LINKS L2 ON L2.PARENT_ID = L111.OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      LEFT JOIN VALI VN ON VN.OBJ_ID = L2.OBJ_ID AND VN.PARAM_ID = 17 AND VN.IS_DEL = 0 AND VN.VAL > 0
      LEFT JOIN VERIFY_VALS V ON V.OBJ_ID = L2.OBJ_ID AND V.PARAM_ID = :PARAM_ID
      WHERE L111.PARENT_ID = :I$DISTRICT_ID AND L111.DATE_DEL IS NULL AND L111.OBJ_TYPE_ID = 111 AND :I$INDEX < 0
      /*UNION
      SELECT L2.OBJ_ID, VN.VAL, V.CNT, V.FCNT
      FROM OBJECTS L2
      LEFT JOIN VALI VN ON VN.OBJ_ID = L2.OBJ_ID AND VN.PARAM_ID = 17 AND VN.IS_DEL = 0 AND VN.VAL > 0
      LEFT JOIN VERIFY_VALS V ON V.OBJ_ID = L2.OBJ_ID AND V.PARAM_ID = :PARAM_ID
      WHERE L2.OBJ_ID = :I$DISTRICT_ID AND L2.TYPE_ID = 2 AND :I$INDEX >= 0*/
      ORDER BY 2 NULLS LAST, 1
      INTO :SCHOOL_ID, :N, :ALLVAL, :VAL
    DO
    BEGIN
      SUSPEND;
      COL_NUM = COL_NUM + 1;
    END
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DISTRICT_VERIFICATION_REPORTX (
    I$DISTRICT_ID BIGINT,
    I$INDEX INTEGER = -1)
RETURNS (
    SCHOOL_ID BIGINT,
    COL_NUM SMALLINT,
    VAL VARCHAR(4000),
    DATA VARCHAR(4000),
    ORIENTATION VARCHAR(20),
    PARAM_ID BIGINT,
    TYPE_ID BIGINT,
    ALLVAL INTEGER)
AS
declare variable V$ROOT_ID bigint;
declare variable V1 double precision;
declare variable V2 double precision;
declare variable VCHK varchar(1000);
declare variable V$PT smallint;
declare variable N integer;
begin

  -- Новая версия отчета, работающая по схеме предрасчета и кастомизируемая пользователем
  -- все отчеты DISTRICT_VERIFICATION_REPORTnX совершенно идентичны, отличие только в фильтре по TYPE_ID

  -- INDEX задает объем обрабатываемых данных
  -- -1 = выдать все данные разом
  -- NULL - выдать только список строк и столбцов
  -- >= 0 - этот режим (получение данных по столбцу конкретной ОУ) больше неактуален

  ORIENTATION = 'MIXED';
  DATA = NULL;

  SELECT FIRST 1 L.OBJ_ID
  FROM LINKS L
  WHERE L.PARENT_ID IS NULL AND L.OBJ_TYPE_ID IN (2, 111, 112) AND L.DATE_DEL IS NULL
  INTO :V$ROOT_ID;

  IF(I$INDEX < 0 OR I$INDEX IS NULL) THEN
  BEGIN
    -- Список строк, вместо PARAM_ID выдаем id строки
    SCHOOL_ID = NULL;
    COL_NUM = 0;
    FOR
      SELECT L498.OBJ_ID, T.TYPE_ID, R.VAL || ' (' || PC.VAL || ')', RT.VAL, V3451.VAL, V3452.VAL, V3455.VAL, P.PARAM_TYPE
      FROM LINKS L498
      -- скрываем отключенные проверки
      JOIN VALL V3454 ON V3454.OBJ_ID = L498.OBJ_ID AND V3454.PARAM_ID = 3454 AND V3454.IS_DEL = 0 AND V3454.LISTVAL_ID <> 15821
      JOIN VALL V3468 ON V3468.OBJ_ID = L498.OBJ_ID AND V3468.PARAM_ID = 3468 AND V3468.IS_DEL = 0
      LEFT JOIN LISTVAL_TEXT(V3468.LISTVAL_ID) PC ON 1 = 1
      JOIN VALI V3449 ON V3449.OBJ_ID = L498.OBJ_ID AND V3449.PARAM_ID = 3449 AND V3449.IS_DEL = 0
      JOIN PARAMS P ON P.PARAM_ID = V3449.VAL AND P.IS_DEL = 0
      JOIN VALI V3453 ON V3453.OBJ_ID = L498.OBJ_ID AND V3453.PARAM_ID = 3453 AND V3453.IS_DEL = 0
      JOIN TYPES T ON T.TYPE_ID = V3453.VAL AND T.IS_DEL = 0 AND T.TYPE_ID IN (16, 492, 61, 121, 257, 490)
      JOIN RES R ON R.RES_ID = P.RES_ID AND R.LANG_CODE = 'RU'
      JOIN RES RT ON RT.RES_ID = T.RES_ID AND RT.LANG_CODE = 'RU'
      LEFT JOIN VALF V3451 ON V3451.OBJ_ID = L498.OBJ_ID AND V3451.PARAM_ID = 3451 AND V3451.IS_DEL = 0
      LEFT JOIN VALF V3452 ON V3452.OBJ_ID = L498.OBJ_ID AND V3452.PARAM_ID = 3452 AND V3452.IS_DEL = 0
      LEFT JOIN VALS V3455 ON V3455.OBJ_ID = L498.OBJ_ID AND V3455.PARAM_ID = 3455 AND V3455.IS_DEL = 0
      WHERE L498.PARENT_ID = :V$ROOT_ID AND L498.OBJ_TYPE_ID = 498 AND L498.DATE_DEL IS NULL
      ORDER BY T.SORT_ORDER, P.GRID_ORDER
      INTO :PARAM_ID, :TYPE_ID, :VAL, :DATA, :V1, :V2, :VCHK, :V$PT
    DO
    BEGIN
      IF(VCHK IS NOT NULL) THEN
      BEGIN
        -- Параметр типа LISTVAL, добавляем в текст
        IF(V$PT = 6) THEN
        BEGIN
          SELECT :VAL || ' = ' || C.VAL
          FROM LISTVAL_TEXT(CAST(:VCHK AS BIGINT)) C
          INTO :VAL;
        END
      END

      -- Контролируемый, но не обязательный ?
      -- IF(T = 2) THEN VAL = VAL || '@';

      -- Добавляем к VAL данные о пределах раскраски
      -- Параметр >>v1>v2
      IF(V1 IS NOT NULL OR V2 IS NOT NULL) THEN VAL = VAL || '>>' || COALESCE(CAST(V1 AS NUMERIC(18, 2)), '') || '>' || COALESCE(CAST(V2 AS NUMERIC(18, 2)), '');

      SUSPEND;
    END

    -- Список столбцов
    DATA = NULL;
    PARAM_ID = NULL;
    TYPE_ID = NULL;
    COL_NUM = 1;
    FOR
      SELECT L2.OBJ_ID, VN.VAL, C.CAPTION
      FROM LINKS L2
      LEFT JOIN VALI VN ON VN.OBJ_ID = L2.OBJ_ID AND VN.PARAM_ID = 17 AND VN.IS_DEL = 0 AND VN.VAL > 0
      LEFT JOIN OBJECT_CAPTION_GET(L2.OBJ_ID) C ON 1 = 1
      WHERE L2.PARENT_ID = :I$DISTRICT_ID AND L2.DATE_DEL IS NULL AND L2.OBJ_TYPE_ID = 2
      UNION
      SELECT L2.OBJ_ID, VN.VAL, C.CAPTION
      FROM LINKS L111
      JOIN LINKS L2 ON L2.PARENT_ID = L111.OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      LEFT JOIN VALI VN ON VN.OBJ_ID = L2.OBJ_ID AND VN.PARAM_ID = 17 AND VN.IS_DEL = 0 AND VN.VAL > 0
      LEFT JOIN OBJECT_CAPTION_GET(L2.OBJ_ID) C ON 1 = 1
      WHERE L111.PARENT_ID = :I$DISTRICT_ID AND L111.DATE_DEL IS NULL AND L111.OBJ_TYPE_ID = 111
      ORDER BY 2 NULLS LAST, 1
      INTO :SCHOOL_ID, :N, :DATA
    DO
    BEGIN
      VAL = N;

      IF(VAL IS NULL) THEN VAL = DATA;

      SUSPEND;
      COL_NUM = COL_NUM + 1;
    END
  END

  -- Если хотим только заголовки - выходим
  IF(I$INDEX IS NULL) THEN EXIT;
  DATA = NULL;

  -- Выборка данных по всем ОУ района
  FOR
    SELECT L498.OBJ_ID, P.TYPE_ID
    FROM LINKS L498
    -- скрываем отключенные проверки
    JOIN VALL V3454 ON V3454.OBJ_ID = L498.OBJ_ID AND V3454.PARAM_ID = 3454 AND V3454.IS_DEL = 0 AND V3454.LISTVAL_ID <> 15821
    JOIN VALI V3449 ON V3449.OBJ_ID = L498.OBJ_ID AND V3449.PARAM_ID = 3449 AND V3449.IS_DEL = 0
    JOIN PARAMS P ON P.PARAM_ID = V3449.VAL AND P.IS_DEL = 0
    JOIN VALI V3453 ON V3453.OBJ_ID = L498.OBJ_ID AND V3453.PARAM_ID = 3453 AND V3453.IS_DEL = 0
    JOIN TYPES T ON T.TYPE_ID = V3453.VAL AND T.IS_DEL = 0 AND T.TYPE_ID IN (16, 492, 61, 121, 257, 490)
    WHERE L498.PARENT_ID = :V$ROOT_ID AND L498.OBJ_TYPE_ID = 498 AND L498.DATE_DEL IS NULL
    ORDER BY T.SORT_ORDER, P.GRID_ORDER
    INTO :PARAM_ID, :TYPE_ID
  DO
  BEGIN
    COL_NUM = 1;
    FOR
      SELECT L2.OBJ_ID, VN.VAL, V.CNT, V.FCNT
      FROM LINKS L2
      LEFT JOIN VALI VN ON VN.OBJ_ID = L2.OBJ_ID AND VN.PARAM_ID = 17 AND VN.IS_DEL = 0 AND VN.VAL > 0
      LEFT JOIN VERIFY_VALS V ON V.OBJ_ID = L2.OBJ_ID AND V.PARAM_ID = :PARAM_ID
      WHERE L2.PARENT_ID = :I$DISTRICT_ID AND L2.DATE_DEL IS NULL AND L2.OBJ_TYPE_ID = 2 AND :I$INDEX < 0
      UNION
      SELECT L2.OBJ_ID, VN.VAL, V.CNT, V.FCNT
      FROM LINKS L111
      JOIN LINKS L2 ON L2.PARENT_ID = L111.OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      LEFT JOIN VALI VN ON VN.OBJ_ID = L2.OBJ_ID AND VN.PARAM_ID = 17 AND VN.IS_DEL = 0 AND VN.VAL > 0
      LEFT JOIN VERIFY_VALS V ON V.OBJ_ID = L2.OBJ_ID AND V.PARAM_ID = :PARAM_ID
      WHERE L111.PARENT_ID = :I$DISTRICT_ID AND L111.DATE_DEL IS NULL AND L111.OBJ_TYPE_ID = 111 AND :I$INDEX < 0
      /*UNION
      SELECT L2.OBJ_ID, VN.VAL, V.CNT, V.FCNT
      FROM OBJECTS L2
      LEFT JOIN VALI VN ON VN.OBJ_ID = L2.OBJ_ID AND VN.PARAM_ID = 17 AND VN.IS_DEL = 0 AND VN.VAL > 0
      LEFT JOIN VERIFY_VALS V ON V.OBJ_ID = L2.OBJ_ID AND V.PARAM_ID = :PARAM_ID
      WHERE L2.OBJ_ID = :I$DISTRICT_ID AND L2.TYPE_ID = 2 AND :I$INDEX >= 0*/
      ORDER BY 2 NULLS LAST, 1
      INTO :SCHOOL_ID, :N, :ALLVAL, :VAL
    DO
    BEGIN
      SUSPEND;
      COL_NUM = COL_NUM + 1;
    END
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DISTRICT_VERIFICATION_REPX_DTL (
    I$SCHOOL_ID BIGINT,
    I$ROW_NUM SMALLINT,
    I$PARAM_ID BIGINT = null)
RETURNS (
    OBJ_ID BIGINT,
    NAME VARCHAR(4000))
AS
declare variable V$PARAM_ID bigint;
declare variable V$TYPE_ID bigint;
declare variable V$PATH bigint;
declare variable V$PARAMTYPE smallint;
declare variable V$FLT varchar(1000);
declare variable V$N1 bigint;
declare variable V$N2 bigint;
declare variable V$GEN bigint;
declare variable V$LV bigint;
declare variable V$GRID bigint;
declare variable V$ROOT_TYPE bigint;
BEGIN

  -- I$ROW_NUM больше неактуален, выбираем всегда через I$PARAM_ID

  SELECT FIRST 1 P.PARAM_ID, T.TYPE_ID, V3455.VAL, V3468.LISTVAL_ID, P.PARAM_TYPE
  FROM LINKS L498
  JOIN VALI V3449 ON V3449.OBJ_ID = L498.OBJ_ID AND V3449.PARAM_ID = 3449 AND V3449.IS_DEL = 0
  JOIN PARAMS P ON P.PARAM_ID = V3449.VAL AND P.IS_DEL = 0
  JOIN VALI V3453 ON V3453.OBJ_ID = L498.OBJ_ID AND V3453.PARAM_ID = 3453 AND V3453.IS_DEL = 0
  JOIN TYPES T ON T.TYPE_ID = V3453.VAL AND T.IS_DEL = 0
  JOIN VALL V3468 ON V3468.OBJ_ID = L498.OBJ_ID AND V3468.PARAM_ID = 3468 AND V3468.IS_DEL = 0
  LEFT JOIN VALS V3455 ON V3455.OBJ_ID = L498.OBJ_ID AND V3455.PARAM_ID = 3455 AND V3455.IS_DEL = 0
  WHERE L498.PARENT_TYPE_ID IN (2, 111, 112) AND L498.OBJ_TYPE_ID = 498 AND L498.OBJ_ID = :I$PARAM_ID AND L498.DATE_DEL IS NULL
  INTO :V$PARAM_ID, :V$TYPE_ID, :V$FLT, :V$PATH, :V$PARAMTYPE;

  IF(V$PARAM_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Параметр не найден или был удален';

  -- Если данный тип отображается только в виде таблицы - будем возвращать название родителя
  -- если всегда в дереве, то его самого
  V$GRID = 1;
  IF(V$TYPE_ID = 2) THEN V$GRID = 0;
  SELECT FIRST 1 0
  FROM PARENTS P
  WHERE P.CHILD_ID = :V$TYPE_ID AND P.IS_DEL = 0 AND (P.IS_ADD = 1 OR P.IS_INTERNAL_ADD = 1) AND P.TAB_ID IS NULL
  INTO :V$GRID;

  SELECT MULTIPLIER
  FROM GEN
  INTO :V$GEN;

  V$N1 = I$SCHOOL_ID / V$GEN;
  V$N2 = (V$N1 + 1) * V$GEN;
  V$N1 = V$N1 * V$GEN;

  IF(V$PARAMTYPE = 6 AND V$FLT IS NOT NULL) THEN
  BEGIN
    -- Отдельная ветка на EXISTS(LISTVAL_ID), общий счетчик нас будет интересовать только в особых случаях
    -- Подсчет идет по родительским сущностям !
    -- Перебираем все возможные связи, где может присутствовать указанный дочерний тип
    V$LV = V$FLT;

    -- Выборка обучающихся - выбираем все типы обучающихся
    IF(V$PATH IN (14550, 14551, 15815)) THEN V$ROOT_TYPE = NULL;
    ELSE IF(V$PATH IN (15816, 15817, 15818)) THEN V$ROOT_TYPE = 14;
    ELSE IF(V$PATH IN (15824, 15825, 15826)) THEN V$ROOT_TYPE = 20;
    ELSE IF(V$TYPE_ID = 17) THEN V$ROOT_TYPE = 2;
    ELSE V$ROOT_TYPE = 2; -- !!!

    FOR
      SELECT DISTINCT L.OBJ_ID, C.CAPTION
      FROM PROCESS_VERIFY_OBJ(:I$SCHOOL_ID, :V$N1, :V$N2, :V$ROOT_TYPE, :V$PATH) L
      LEFT JOIN PROCESS_VERIFY_SUBFLT(L.TYPE_ID, L.OBJ_ID, NULL, NULL, :V$PARAM_ID, :V$LV) SF ON 1 = 1
      LEFT JOIN OBJECT_CAPTION_GET(L.OBJ_ID) C ON 1 = 1
      WHERE SF.IS_MATCH = 1 AND NOT EXISTS (
        SELECT FIRST 1 1
        FROM LINKS LC
        JOIN VALL V ON V.OBJ_ID = LC.OBJ_ID AND V.PARAM_ID = :V$PARAM_ID AND V.IS_DEL = 0 AND V.LISTVAL_ID = :V$LV
        WHERE LC.PARENT_ID = L.OBJ_ID AND LC.OBJ_TYPE_ID = :V$TYPE_ID AND LC.DATE_DEL IS NULL
      )
      ORDER BY 2
      INTO :OBJ_ID, :NAME
    DO
    BEGIN
      SUSPEND;
    END
  END
  ELSE
  BEGIN
    IF(V$FLT IS NULL) THEN
    BEGIN
      FOR
        -- Название самого объекта
        SELECT DISTINCT L.OBJ_ID, C.CAPTION
        FROM PROCESS_VERIFY_OBJ(:I$SCHOOL_ID, :V$N1, :V$N2, :V$TYPE_ID, :V$PATH) L
        LEFT JOIN VAL_GET(L.OBJ_ID, :V$PARAM_ID) V ON 1 = 1
        LEFT JOIN OBJECT_CAPTION_GET(L.OBJ_ID) C ON 1 = 1
        WHERE V.IS_EXISTS = 1 AND :V$GRID = 0
        -- Название родительского объекта
        UNION
        SELECT DISTINCT L.OBJ_ID, C.CAPTION
        FROM PROCESS_VERIFY_OBJ(:I$SCHOOL_ID, :V$N1, :V$N2, :V$TYPE_ID, :V$PATH) L
        JOIN LINKS LP ON LP.OBJ_ID = L.OBJ_ID AND LP.DATE_DEL IS NULL -- предполагается что родитель тут уникален
        LEFT JOIN VAL_GET(L.OBJ_ID, :V$PARAM_ID) V ON 1 = 1
        LEFT JOIN OBJECT_CAPTION_GET(LP.PARENT_ID) C ON 1 = 1
        WHERE V.IS_EXISTS = 1 AND :V$GRID = 1
        ORDER BY 2
        INTO :OBJ_ID, :NAME
      DO
      BEGIN
        SUSPEND;
      END
    END
    -- ELSE
  END

END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DISTRICT_VERIFICATION_REP_DTL (
    I$SCHOOL_ID BIGINT,
    I$ROW_NUM SMALLINT,
    I$PARAM_ID BIGINT = null)
RETURNS (
    BUILDING_ID BIGINT,
    NAME VARCHAR(4000))
AS
declare variable V$PARAM_ID bigint;
declare variable V$TYPE_ID bigint;
declare variable T bigint;
BEGIN

  IF(I$PARAM_ID IS NULL) THEN
  BEGIN
    I$ROW_NUM = I$ROW_NUM - 1;

    FOR
      SELECT DISTINCT P.PARAM_ID
      FROM PARAMS P
      JOIN LPARAMS LP ON LP.PARAM_ID = P.PARAM_ID AND LP.IS_DEL = 0 AND LP.EDIT_TYPE >= 0
      JOIN LEVELS L ON L.LEVEL_ID = LP.LEVEL_ID AND L.IS_DEL = 0
      JOIN TASKS T ON T.TASK_ID = L.TASK_ID AND T.IS_DEL = 0
      JOIN MODULES M ON M.MODULE_ID = T.MODULE_ID AND M.IS_DEL = 0 AND M.IS_ACTIVE = 1
      JOIN TYPES OBJT ON OBJT.TYPE_ID = P.TYPE_ID
      WHERE P.TYPE_ID IN (16, 61, 492, 490) AND P.IS_DEL = 0 AND P.IS_REQUIRED > 0 -- тут как просто обязательные, так и контролирумые
      ORDER BY P.TYPE_ID, P.GRID_ORDER
      INTO :T
    DO
    BEGIN             
      IF(I$ROW_NUM = 0) THEN V$PARAM_ID = T;
      I$ROW_NUM = I$ROW_NUM - 1;
    END
  END
  ELSE
  BEGIN
    V$PARAM_ID = I$PARAM_ID;
  END

  SELECT TYPE_ID
  FROM PARAMS
  WHERE PARAM_ID = :V$PARAM_ID
  INTO :V$TYPE_ID;

  IF(V$TYPE_ID IS NULL) THEN EXCEPTION DATA_ERROR 'По данному показателю не предусмотрен просмотр детализации';

  IF(V$TYPE_ID = 16) THEN
  BEGIN
    FOR
      SELECT L16.OBJ_ID
      FROM LINKS L73
      JOIN LINKS L16 ON L16.PARENT_ID = L73.OBJ_ID AND L16.DATE_DEL IS NULL AND L16.OBJ_TYPE_ID = 16
      LEFT JOIN VAL_GET(L16.OBJ_ID, :V$PARAM_ID) VL ON 1 = 1
      WHERE L73.PARENT_ID = :I$SCHOOL_ID AND L73.OBJ_TYPE_ID = 73 AND L73.DATE_DEL IS NULL AND VL.V = ''
      INTO :BUILDING_ID
    DO
    BEGIN
      SELECT CAPTION
      FROM OBJECT_CAPTION_GET(:BUILDING_ID)
      INTO :NAME;

      SUSPEND;
    END
  END
  ELSE IF(V$TYPE_ID = 61) THEN
  BEGIN
    FOR
      SELECT L61.OBJ_ID
      FROM LINKS L73
      JOIN LINKS L16 ON L16.PARENT_ID = L73.OBJ_ID AND L16.DATE_DEL IS NULL AND L16.OBJ_TYPE_ID = 16
      JOIN LINKS L61 ON L61.PARENT_ID = L16.OBJ_ID AND L61.DATE_DEL IS NULL AND L61.OBJ_TYPE_ID = 61
      LEFT JOIN VAL_GET(L61.OBJ_ID, :V$PARAM_ID) VL ON 1 = 1
      WHERE L73.PARENT_ID = :I$SCHOOL_ID AND L73.OBJ_TYPE_ID = 73 AND L73.DATE_DEL IS NULL AND VL.V = ''
      INTO :BUILDING_ID
    DO
    BEGIN
      SELECT CAPTION
      FROM OBJECT_CAPTION_GET(:BUILDING_ID)
      INTO :NAME;

      SUSPEND;
    END
  END
  ELSE IF(V$TYPE_ID = 492) THEN
  BEGIN
    FOR
      SELECT L492.OBJ_ID
      FROM LINKS L73
      JOIN LINKS L492 ON L492.PARENT_ID = L73.OBJ_ID AND L492.DATE_DEL IS NULL AND L492.OBJ_TYPE_ID = 492
      LEFT JOIN VAL_GET(L492.OBJ_ID, :V$PARAM_ID) VL ON 1 = 1
      WHERE L73.PARENT_ID = :I$SCHOOL_ID AND L73.OBJ_TYPE_ID = 73 AND L73.DATE_DEL IS NULL AND VL.V = ''
      INTO :BUILDING_ID
    DO
    BEGIN
      SELECT CAPTION
      FROM OBJECT_CAPTION_GET(:BUILDING_ID)
      INTO :NAME;

      SUSPEND;
    END
  END
  ELSE IF(V$TYPE_ID = 490) THEN
  BEGIN
    FOR
      SELECT L490.OBJ_ID
      FROM LINKS L496
      JOIN LINKS L490 ON L490.PARENT_ID = L496.OBJ_ID AND L490.DATE_DEL IS NULL AND L490.OBJ_TYPE_ID = 490
      LEFT JOIN VAL_GET(L490.OBJ_ID, :V$PARAM_ID) VL ON 1 = 1
      WHERE L496.PARENT_ID = :I$SCHOOL_ID AND L496.OBJ_TYPE_ID = 496 AND L496.DATE_DEL IS NULL AND VL.V = ''
      INTO :BUILDING_ID
    DO
    BEGIN
      SELECT CAPTION
      FROM OBJECT_CAPTION_GET(:BUILDING_ID)
      INTO :NAME;

      SUSPEND;
    END
  END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DOU_CHECK_PARENT_STATUS (
    I$PARENT_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$STATUS_ID BIGINT)
RETURNS (
    OK SMALLINT)
AS
BEGIN
    OK = 0;

    SELECT FIRST 1 1
    FROM LINKS L

    JOIN VALL VL
    ON VL.OBJ_ID = L.EXT_OBJ_ID
    AND VL.PARAM_ID = 1573
    AND VL.lISTVAL_ID = :I$STATUS_ID
    AND VL.IS_DEL = 0

    WHERE L.PARENT_ID = :I$PARENT_ID
    AND L.OBJ_ID = :I$OBJ_ID
    AND L.DATE_DEL IS NULL
    AND L.EXT_OBJ_TYPE_ID = 168
    INTO :OK;
    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DOU_DISTR_VERIFICATION_REP2_DTL (
    I$SCHOOL_ID BIGINT,
    I$ROW_NUM SMALLINT)
RETURNS (
    DOCUMENT_ID BIGINT,
    NAME VARCHAR(4000))
AS
declare variable V$PARAM_ID bigint;
BEGIN
    V$PARAM_ID =
        CASE I$ROW_NUM
            WHEN 12 THEN 596
            WHEN 13 THEN 479
            WHEN 14 THEN 480
            WHEN 15 THEN 482
            WHEN 16 THEN 613
            ELSE NULL
        END;

    FOR
        SELECT L17.OBJ_ID
        FROM LINKS L17

        JOIN VALL V613
        ON V613.OBJ_ID = L17.OBJ_ID
        AND V613.PARAM_ID = 613
        AND V613.IS_DEL = 0
        AND V613.LISTVAL_ID = 1982

        LEFT JOIN VAL_GET(L17.OBJ_ID, :V$PARAM_ID) VL
        ON 1=1

        WHERE L17.PARENT_ID = :I$SCHOOL_ID
        AND L17.DATE_DEL IS NULL
        AND L17.OBJ_TYPE_ID = 17
        AND VL.V = ''
            
        INTO :DOCUMENT_ID
    DO
    BEGIN
        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:DOCUMENT_ID)
        INTO :NAME;

        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DOU_DISTR_VERIFICATION_REP3_DTL (
    I$SCHOOL_ID BIGINT,
    I$ROW_NUM SMALLINT)
RETURNS (
    PUPIL_ID BIGINT,
    VAL1 VARCHAR(4000),
    VAL3 VARCHAR(4000))
AS
declare variable V$PARAM_ID bigint;
declare variable V$OBJ_ID bigint;
declare variable Y integer;
declare variable M integer;
BEGIN
    M = EXTRACT(MONTH FROM CURRENT_DATE);
    Y = EXTRACT(YEAR FROM CURRENT_DATE);
    IF (M < 9) THEN
    BEGIN
        Y = Y - 1;
    END

    IF (I$ROW_NUM IN (1,3,4,5,6,8)) THEN   -- 8
    BEGIN
        V$PARAM_ID =
            CASE I$ROW_NUM
                WHEN 1 THEN 108
                WHEN 3 THEN 103
                WHEN 4 THEN 111
                WHEN 5 THEN 118
                WHEN 6 THEN 119
              --  WHEN 7 THEN 1552
                WHEN 8 THEN 208
            END;
        FOR
            SELECT L10.PARENT_ID,
                   L10.OBJ_ID
            FROM LINKS L7

            JOIN LINKS L8
            ON L8.PARENT_ID = L7.OBJ_ID
            AND L8.DATE_DEL IS NULL
            AND L8.OBJ_TYPE_ID = 8

            JOIN LINKS L9
            ON L9.PARENT_ID = L8.OBJ_ID
            AND L9.DATE_DEL IS NULL
            AND L9.OBJ_TYPE_ID = 9

            JOIN LINKS L10
            ON L10.PARENT_ID = L9.OBJ_ID
            AND L10.DATE_DEL IS NULL
            AND L10.OBJ_TYPE_ID = 10

            LEFT JOIN VAL_GET(L10.OBJ_ID, :V$PARAM_ID) VL
            ON 1=1

            WHERE L7.PARENT_ID = :I$SCHOOL_ID
            AND L7.DATE_DEL IS NULL
            AND L7.OBJ_TYPE_ID = 7
            AND VL.V = ''
                
            INTO :V$OBJ_ID,
                 :PUPIL_ID
        DO
        BEGIN
            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:PUPIL_ID, 187)
            INTO :VAL1;

            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:V$OBJ_ID)
            INTO :VAL3;
            SUSPEND;
        END
    END ELSE
    IF (I$ROW_NUM = 7) THEN
    BEGIN
        V$PARAM_ID =
            CASE I$ROW_NUM
                WHEN 7 THEN 1552
            END;
        FOR
            SELECT L10.PARENT_ID,
                   L10.OBJ_ID
            FROM LINKS L7

            JOIN LINKS L8
            ON L8.PARENT_ID = L7.OBJ_ID
            AND L8.DATE_DEL IS NULL
            AND L8.OBJ_TYPE_ID = 8

            JOIN LINKS L9
            ON L9.PARENT_ID = L8.OBJ_ID
            AND L9.DATE_DEL IS NULL
            AND L9.OBJ_TYPE_ID = 9

            JOIN LINKS L10
            ON L10.PARENT_ID = L9.OBJ_ID
            AND L10.DATE_DEL IS NULL
            AND L10.OBJ_TYPE_ID = 10

            LEFT JOIN VAL_GET(L10.OBJ_ID, :V$PARAM_ID) VL
            ON 1=1

            WHERE L7.PARENT_ID = :I$SCHOOL_ID
            AND L7.DATE_DEL IS NULL
            AND L7.OBJ_TYPE_ID = 7
            AND (VL.V = '' or VL.V = '0%')
                
            INTO :V$OBJ_ID,
                 :PUPIL_ID
        DO
        BEGIN
            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:PUPIL_ID, 187)
            INTO :VAL1;

            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:V$OBJ_ID)
            INTO :VAL3;
            SUSPEND;
        END
    END
    ELSE IF (I$ROW_NUM = 2) THEN
    BEGIN
        V$PARAM_ID = 101;
        FOR
            SELECT L10.PARENT_ID,
                   L10.OBJ_ID
            FROM LINKS L7

            JOIN LINKS L8
            ON L8.PARENT_ID = L7.OBJ_ID
            AND L8.DATE_DEL IS NULL
            AND L8.OBJ_TYPE_ID = 8

            JOIN LINKS L9
            ON L9.PARENT_ID = L8.OBJ_ID
            AND L9.DATE_DEL IS NULL
            AND L9.OBJ_TYPE_ID = 9

            JOIN LINKS L10
            ON L10.PARENT_ID = L9.OBJ_ID
            AND L10.DATE_DEL IS NULL
            AND L10.OBJ_TYPE_ID = 10

            LEFT JOIN VAL_GET(L10.OBJ_ID, :V$PARAM_ID) VL
            ON 1=1

            LEFT JOIN ADR_GET(103, L10.OBJ_ID) VA
            ON 1=1

            WHERE L7.PARENT_ID = :I$SCHOOL_ID
            AND L7.DATE_DEL IS NULL
            AND L7.OBJ_TYPE_ID = 7
            AND VL.V = ''
            AND VA.REGION LIKE 'Санкт-Петербург%'
                
            INTO :V$OBJ_ID,
                 :PUPIL_ID
        DO
        BEGIN
            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:PUPIL_ID, 187)
            INTO :VAL1;

            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:V$OBJ_ID)
            INTO :VAL3;

            SUSPEND;
        END
    END
    ELSE IF (I$ROW_NUM = 9) THEN   --10
    BEGIN
        FOR
            SELECT L10.PARENT_ID,
                   L10.OBJ_ID
            FROM LINKS L7
    
            JOIN LINKS L8
            ON L8.PARENT_ID = L7.OBJ_ID
            AND L8.DATE_DEL IS NULL
            AND L8.OBJ_TYPE_ID = 8
    
            JOIN LINKS L9
            ON L9.PARENT_ID = L8.OBJ_ID
            AND L9.DATE_DEL IS NULL
            AND L9.OBJ_TYPE_ID = 9
    
            JOIN LINKS L10
            ON L10.PARENT_ID = L9.OBJ_ID
            AND L10.DATE_DEL IS NULL
            AND L10.OBJ_TYPE_ID = 10
    
            LEFT JOIN VALL V78
            ON V78.OBJ_ID = L10.OBJ_ID
            AND V78.PARAM_ID = 78
            AND V78.IS_DEL = 0

            WHERE L7.PARENT_ID = :I$SCHOOL_ID
            AND L7.DATE_DEL IS NULL
            AND L7.OBJ_TYPE_ID = 7
            AND V78.OBJ_ID IS NULL

            UNION ALL
    
            SELECT L10.PARENT_ID,
                   L10.OBJ_ID
            FROM LINKS L78
    
            JOIN LINKS L82
            ON L82.PARENT_ID = L78.OBJ_ID
            AND L82.DATE_DEL IS NULL
            AND L82.OBJ_TYPE_ID = 82
    
            JOIN VALI V448
            ON V448.OBJ_ID = L82.OBJ_ID
            AND V448.PARAM_ID = 448
            AND V448.IS_DEL = 0
            AND V448.VAL = :Y
    
            JOIN LINKS L10
            ON L10.PARENT_ID = L82.OBJ_ID
            AND L10.DATE_DEL IS NULL
            AND L10.OBJ_TYPE_ID = 10
    
            LEFT JOIN VALL V78
            ON V78.OBJ_ID = L10.OBJ_ID
            AND V78.PARAM_ID = 78
            AND V78.IS_DEL = 0

            WHERE L78.PARENT_ID = :I$SCHOOL_ID
            AND L78.DATE_DEL IS NULL
            AND L78.OBJ_TYPE_ID = 78
            AND V78.OBJ_ID IS NULL

            INTO :V$OBJ_ID,
                 :PUPIL_ID
        DO
        BEGIN
            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:PUPIL_ID, 187)
            INTO :VAL1;

            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:V$OBJ_ID)
            INTO :VAL3;

            SUSPEND;
        END
    END
    ELSE IF (I$ROW_NUM = 12) THEN    --11
    BEGIN
        V$PARAM_ID = 105;

        M = EXTRACT(MONTH FROM CURRENT_DATE);
        Y = EXTRACT(YEAR FROM CURRENT_DATE);
        IF (M < 9) THEN
        BEGIN
            Y = Y - 1;
        END

        FOR
            SELECT L10.PARENT_ID,
                   L10.OBJ_ID
            FROM LINKS L78
    
            JOIN LINKS L82
            ON L82.PARENT_ID = L78.OBJ_ID
            AND L82.DATE_DEL IS NULL
            AND L82.OBJ_TYPE_ID = 82
    
            JOIN VALI V448
            ON V448.OBJ_ID = L82.OBJ_ID
            AND V448.PARAM_ID = 448
            AND V448.IS_DEL = 0
            AND V448.VAL = :Y
    
            JOIN LINKS L10
            ON L10.PARENT_ID = L82.OBJ_ID
            AND L10.DATE_DEL IS NULL
            AND L10.OBJ_TYPE_ID = 10
    
            LEFT JOIN VAL_GET(L10.OBJ_ID, :V$PARAM_ID) VL
            ON 1=1

            WHERE L78.PARENT_ID = :I$SCHOOL_ID
            AND L78.DATE_DEL IS NULL
            AND L78.OBJ_TYPE_ID = 78
            AND VL.V = ''

            INTO :V$OBJ_ID,
                 :PUPIL_ID
        DO
        BEGIN
            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:PUPIL_ID, 187)
            INTO :VAL1;

            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:V$OBJ_ID)
            INTO :VAL3;

            SUSPEND;
        END
    END
    ELSE IF (I$ROW_NUM = 13) THEN     --12
    BEGIN
        FOR
            SELECT L10.PARENT_ID,
                   L10.OBJ_ID
            FROM LINKS L7

            JOIN LINKS L8
            ON L8.PARENT_ID = L7.OBJ_ID
            AND L8.DATE_DEL IS NULL
            AND L8.OBJ_TYPE_ID = 8

            JOIN LINKS L9
            ON L9.PARENT_ID = L8.OBJ_ID
            AND L9.DATE_DEL IS NULL
            AND L9.OBJ_TYPE_ID = 9

            JOIN LINKS L10
            ON L10.PARENT_ID = L9.OBJ_ID
            AND L10.DATE_DEL IS NULL
            AND L10.OBJ_TYPE_ID = 10

            WHERE L7.PARENT_ID = :I$SCHOOL_ID
            AND L7.DATE_DEL IS NULL
            AND L7.OBJ_TYPE_ID = 7
            AND (
                SELECT COUNT(L20.OBJ_ID)
                FROM LINKS L20
                WHERE L20.OBJ_TYPE_ID = 20
                AND L20.PARENT_ID = L10.OBJ_ID
                AND L20.DATE_DEL IS NULL
            ) = 0
            INTO :V$OBJ_ID,
                 :PUPIL_ID
        DO
        BEGIN
            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:PUPIL_ID, 187)
            INTO :VAL1;

            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:V$OBJ_ID)
            INTO :VAL3;

            SUSPEND;
        END
    END
    ELSE IF (I$ROW_NUM IN (14,15)) THEN  -- 13,14
    BEGIN
        V$PARAM_ID =
            CASE I$ROW_NUM
                WHEN 13 THEN 1573
                WHEN 14 THEN 2453
            END;
        FOR
            SELECT L10.PARENT_ID,
                   L10.OBJ_ID
            FROM LINKS L7

            JOIN LINKS L8
            ON L8.PARENT_ID = L7.OBJ_ID
            AND L8.DATE_DEL IS NULL
            AND L8.OBJ_TYPE_ID = 8

            JOIN LINKS L9
            ON L9.PARENT_ID = L8.OBJ_ID
            AND L9.DATE_DEL IS NULL
            AND L9.OBJ_TYPE_ID = 9

            JOIN LINKS L10
            ON L10.PARENT_ID = L9.OBJ_ID
            AND L10.DATE_DEL IS NULL
            AND L10.OBJ_TYPE_ID = 10

            WHERE L7.PARENT_ID = :I$SCHOOL_ID
            AND L7.DATE_DEL IS NULL
            AND L7.OBJ_TYPE_ID = 7
            AND EXISTS(
                SELECT FIRST 1 1
                FROM LINKS L20

                LEFT JOIN VAL_GET(L20.EXT_OBJ_ID, :V$PARAM_ID) VL
                ON 1=1

                WHERE L20.OBJ_TYPE_ID = 20
                AND L20.PARENT_ID = L10.OBJ_ID
                AND L20.DATE_DEL IS NULL
                AND VL.V = ''
            )
            INTO :V$OBJ_ID,
                 :PUPIL_ID
        DO
        BEGIN
            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:PUPIL_ID, 187)
            INTO :VAL1;

            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:V$OBJ_ID)
            INTO :VAL3;

            SUSPEND;
        END
    END
    ELSE IF (I$ROW_NUM = 10) THEN
    BEGIN
        FOR
            SELECT L10.PARENT_ID,
                   L10.OBJ_ID
            FROM LINKS L7

            JOIN LINKS L8
            ON L8.PARENT_ID = L7.OBJ_ID
            AND L8.DATE_DEL IS NULL
            AND L8.OBJ_TYPE_ID = 8

            JOIN LINKS L9
            ON L9.PARENT_ID = L8.OBJ_ID
            AND L9.DATE_DEL IS NULL
            AND L9.OBJ_TYPE_ID = 9

            JOIN LINKS L10
            ON L10.PARENT_ID = L9.OBJ_ID
            AND L10.DATE_DEL IS NULL
            AND L10.OBJ_TYPE_ID = 10

            WHERE L7.PARENT_ID = :I$SCHOOL_ID
            AND L7.DATE_DEL IS NULL
            AND L7.OBJ_TYPE_ID = 7
            AND NOT EXISTS(
                SELECT FIRST 1 1
                FROM LINKS L76

                JOIN VALL V432
                ON V432.OBJ_ID=L76.OBJ_ID
                AND V432.PARAM_ID=432
                AND V432.IS_DEL=0
                AND v432.LISTVAL_ID = 3276

                WHERE L76.OBJ_TYPE_ID = 76
                AND L76.PARENT_ID = L10.OBJ_ID
                AND L76.DATE_DEL IS NULL
            )
            INTO :V$OBJ_ID,
                 :PUPIL_ID
        DO
        BEGIN
            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:PUPIL_ID, 187)
            INTO :VAL1;

            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:V$OBJ_ID)
            INTO :VAL3;

            SUSPEND;
        END
    END
    ELSE IF (I$ROW_NUM = 11) THEN
    BEGIN
        FOR
            SELECT L10.PARENT_ID,
                   L10.OBJ_ID
            FROM LINKS L7

            JOIN LINKS L8
            ON L8.PARENT_ID = L7.OBJ_ID
            AND L8.DATE_DEL IS NULL
            AND L8.OBJ_TYPE_ID = 8

            JOIN LINKS L9
            ON L9.PARENT_ID = L8.OBJ_ID
            AND L9.DATE_DEL IS NULL
            AND L9.OBJ_TYPE_ID = 9

            JOIN LINKS L10
            ON L10.PARENT_ID = L9.OBJ_ID
            AND L10.DATE_DEL IS NULL
            AND L10.OBJ_TYPE_ID = 10

            WHERE L7.PARENT_ID = :I$SCHOOL_ID
            AND L7.DATE_DEL IS NULL
            AND L7.OBJ_TYPE_ID = 7
            AND EXISTS(
                SELECT FIRST 1 1
                FROM LINKS L76

                LEFT JOIN VAL_GET(L76.OBJ_ID, 433) VL
                ON 1=1

                WHERE L76.OBJ_TYPE_ID = 76
                AND L76.PARENT_ID = L10.OBJ_ID
                AND L76.DATE_DEL IS NULL
                AND VL.V = ''
            )
            INTO :V$OBJ_ID,
                 :PUPIL_ID
        DO
        BEGIN
            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:PUPIL_ID, 187)
            INTO :VAL1;

            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:V$OBJ_ID)
            INTO :VAL3;

            SUSPEND;
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DOU_DISTR_VERIFICATION_REP4_DTL (
    I$SCHOOL_ID BIGINT,
    I$ROW_NUM SMALLINT)
RETURNS (
    WORKER_ID BIGINT,
    NAME VARCHAR(4000))
AS
BEGIN
    FOR
        SELECT L14.OBJ_ID
        FROM LINKS L14

        WHERE L14.PARENT_ID = :I$SCHOOL_ID
        AND L14.OBJ_TYPE_ID = 14
        AND L14.DATE_DEL IS NULL
        AND (
             (:I$ROW_NUM = 1 AND NOT EXISTS(SELECT FIRST 1 1 FROM VALL V243 WHERE V243.OBJ_ID=L14.OBJ_ID AND V243.PARAM_ID=243 AND V243.IS_DEL=0))
             OR (:I$ROW_NUM = 2 AND EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND NOT EXISTS(SELECT FIRST 1 1 FROM VALS V244 WHERE V244.OBJ_ID=L14.OBJ_ID AND V244.PARAM_ID=244 AND V244.IS_DEL=0))
             OR (:I$ROW_NUM = 3 AND EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND NOT EXISTS(SELECT FIRST 1 1 FROM VALA V255 WHERE V255.OBJ_ID=L14.OBJ_ID AND V255.PARAM_ID=255 AND V255.IS_DEL=0))
             OR (:I$ROW_NUM = 4 AND EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND NOT EXISTS(SELECT FIRST 1 1 FROM VALA V262 WHERE V262.OBJ_ID=L14.OBJ_ID AND V262.PARAM_ID=262 AND V262.IS_DEL=0))
             OR (:I$ROW_NUM = 5 AND EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND NOT EXISTS(SELECT FIRST 1 1 FROM VALS V250 WHERE V250.OBJ_ID=L14.OBJ_ID AND V250.PARAM_ID=250 AND V250.IS_DEL=0))
             OR (:I$ROW_NUM = 6 AND EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND NOT EXISTS(SELECT FIRST 1 1 FROM LINKS L85 JOIN VALL V465 ON V465.OBJ_ID = L85.OBJ_ID AND V465.PARAM_ID = 465 AND V465.IS_DEL = 0 JOIN VALD V466 ON V466.OBJ_ID = L85.OBJ_ID AND V466.PARAM_ID = 466 AND V466.IS_DEL = 0 WHERE L85.PARENT_ID=L14.OBJ_ID AND L85.OBJ_TYPE_ID = 85 AND L85.DATE_DEL IS NULL AND V465.LISTVAL_ID = 941))
             OR (:I$ROW_NUM = 7 AND EXISTS(SELECT FIRST 1 1 FROM IS_TEACHER(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) STAFF WHERE STAFF.X=1) AND NOT EXISTS(SELECT FIRST 1 1 FROM LINKS L85 JOIN VALL V465 ON V465.OBJ_ID = L85.OBJ_ID AND V465.PARAM_ID = 465 AND V465.IS_DEL = 0 JOIN VALD V466 ON V466.OBJ_ID = L85.OBJ_ID AND V466.PARAM_ID = 466 AND V466.IS_DEL = 0 WHERE L85.PARENT_ID=L14.OBJ_ID AND L85.OBJ_TYPE_ID = 85 AND L85.DATE_DEL IS NULL AND V465.LISTVAL_ID = 942))
             OR (:I$ROW_NUM = 8 AND EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) STAFF WHERE STAFF.X=1) AND NOT EXISTS(SELECT FIRST 1 1 FROM LINKS L79 WHERE L79.OBJ_TYPE_ID = 79 AND L79.PARENT_ID = L14.OBJ_ID AND L79.DATE_DEL IS NULL))
             OR (:I$ROW_NUM = 9 AND EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) STAFF WHERE STAFF.X=1) AND EXISTS(SELECT FIRST 1 1 FROM LINKS L79 WHERE L79.OBJ_TYPE_ID = 79 AND L79.PARENT_ID = L14.OBJ_ID AND L79.DATE_DEL IS NULL AND NOT EXISTS(SELECT FIRST 1 1 FROM VALS VS WHERE VS.PARAM_ID = 442 AND VS.IS_DEL = 0 AND VS.OBJ_ID = L79.OBJ_ID)))
             OR (:I$ROW_NUM = 10 AND EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) STAFF WHERE STAFF.X=1) AND EXISTS(SELECT FIRST 1 1 FROM LINKS L79 WHERE L79.OBJ_TYPE_ID = 79 AND L79.PARENT_ID = L14.OBJ_ID AND L79.DATE_DEL IS NULL AND NOT EXISTS(SELECT FIRST 1 1 FROM VALS VS WHERE VS.PARAM_ID = 559 AND VS.IS_DEL = 0 AND VS.OBJ_ID = L79.OBJ_ID)))
             OR (:I$ROW_NUM = 11 AND NOT EXISTS(SELECT FIRST 1 1 FROM LINKS L15 JOIN VALL VLL ON VLL.OBJ_ID = L15.OBJ_ID AND VLL.PARAM_ID = 72 AND VLL.IS_DEL = 0 AND VLL.LISTVAL_ID = 934 LEFT JOIN VALD V74 ON V74.PARAM_ID = 74 AND V74.OBJ_ID = L15.OBJ_ID AND V74.IS_DEL = 0 WHERE L15.OBJ_TYPE_ID = 15 AND L15.PARENT_ID = L14.OBJ_ID AND L15.DATE_DEL IS NULL AND V74.VAL IS NULL))
             OR (:I$ROW_NUM = 12 AND EXISTS(SELECT FIRST 1 1 FROM LINKS L15 LEFT JOIN VALF V ON V.OBJ_ID=L15.OBJ_ID AND V.PARAM_ID=71 AND V.IS_DEL=0 WHERE L15.PARENT_ID=L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL AND V.VAL IS NULL))
             OR (:I$ROW_NUM = 13 AND EXISTS(SELECT FIRST 1 1 FROM LINKS L15 LEFT JOIN VALL V ON V.OBJ_ID=L15.OBJ_ID AND V.PARAM_ID=587 AND V.IS_DEL=0 WHERE L15.PARENT_ID=L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL AND V.LISTVAL_ID IS NULL))
             OR (:I$ROW_NUM = 14 AND EXISTS(SELECT FIRST 1 1 FROM LINKS L15 LEFT JOIN VALL V ON V.OBJ_ID=L15.OBJ_ID AND V.PARAM_ID=72 AND V.IS_DEL=0 WHERE L15.PARENT_ID=L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL AND V.LISTVAL_ID IS NULL))
             OR (:I$ROW_NUM = 15 AND EXISTS(SELECT FIRST 1 1 FROM LINKS L15 LEFT JOIN VALD V ON V.OBJ_ID=L15.OBJ_ID AND V.PARAM_ID=73 AND V.IS_DEL=0 WHERE L15.PARENT_ID=L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL AND V.VAL IS NULL))
             OR (:I$ROW_NUM = 16 AND EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM LINKS L33 WHERE L33.OBJ_TYPE_ID = 33 AND L33.PARENT_ID = L14.OBJ_ID AND L33.DATE_DEL IS NULL AND NOT EXISTS(SELECT FIRST 1 1 FROM VALL VS WHERE VS.PARAM_ID = 284 AND VS.IS_DEL = 0 AND VS.OBJ_ID = L33.OBJ_ID)))
             OR (:I$ROW_NUM = 17 AND EXISTS(SELECT FIRST 1 1 FROM IS_TEACHER(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM LINKS L33 WHERE L33.OBJ_TYPE_ID = 33 AND L33.PARENT_ID = L14.OBJ_ID AND L33.DATE_DEL IS NULL AND NOT EXISTS(SELECT FIRST 1 1 FROM VALS V WHERE V.PARAM_ID = 285 AND V.IS_DEL = 0 AND V.OBJ_ID = L33.OBJ_ID)))
             OR (:I$ROW_NUM = 18 AND EXISTS(SELECT FIRST 1 1 FROM IS_TEACHER(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM LINKS L33 WHERE L33.OBJ_TYPE_ID = 33 AND L33.PARENT_ID = L14.OBJ_ID AND L33.DATE_DEL IS NULL AND NOT EXISTS(SELECT FIRST 1 1 FROM VALS V WHERE V.PARAM_ID = 287 AND V.IS_DEL = 0 AND V.OBJ_ID = L33.OBJ_ID)))
             OR (:I$ROW_NUM = 19 AND EXISTS(SELECT FIRST 1 1 FROM IS_TEACHER(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM LINKS L33 WHERE L33.OBJ_TYPE_ID = 33 AND L33.PARENT_ID = L14.OBJ_ID AND L33.DATE_DEL IS NULL AND NOT EXISTS(SELECT FIRST 1 1 FROM VALL V WHERE V.PARAM_ID = 286 AND V.IS_DEL = 0 AND V.OBJ_ID = L33.OBJ_ID)))
             OR (:I$ROW_NUM = 20 AND EXISTS(SELECT FIRST 1 1 FROM IS_TEACHER(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM LINKS L33 WHERE L33.OBJ_TYPE_ID = 33 AND L33.PARENT_ID = L14.OBJ_ID AND L33.DATE_DEL IS NULL AND NOT EXISTS(SELECT FIRST 1 1 FROM VALS V WHERE V.PARAM_ID = 288 AND V.IS_DEL = 0 AND V.OBJ_ID = L33.OBJ_ID)))
             OR (:I$ROW_NUM = 21 AND EXISTS(SELECT FIRST 1 1 FROM IS_TEACHER(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM LINKS L33 WHERE L33.OBJ_TYPE_ID = 33 AND L33.PARENT_ID = L14.OBJ_ID AND L33.DATE_DEL IS NULL AND NOT EXISTS(SELECT FIRST 1 1 FROM VALD V WHERE V.PARAM_ID = 290 AND V.IS_DEL = 0 AND V.OBJ_ID = L33.OBJ_ID)))
             OR (:I$ROW_NUM = 22 AND EXISTS(SELECT FIRST 1 1 FROM IS_TEACHER(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM LINKS L33 WHERE L33.OBJ_TYPE_ID = 33 AND L33.PARENT_ID = L14.OBJ_ID AND L33.DATE_DEL IS NULL AND NOT EXISTS(SELECT FIRST 1 1 FROM VALS V WHERE V.PARAM_ID = 291 AND V.IS_DEL = 0 AND V.OBJ_ID = L33.OBJ_ID)))
             OR (:I$ROW_NUM = 23 AND EXISTS(SELECT FIRST 1 1 FROM IS_TEACHER(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM LINKS L33 WHERE L33.OBJ_TYPE_ID = 33 AND L33.PARENT_ID = L14.OBJ_ID AND L33.DATE_DEL IS NULL AND NOT EXISTS(SELECT FIRST 1 1 FROM VALS V WHERE V.PARAM_ID = 292 AND V.IS_DEL = 0 AND V.OBJ_ID = L33.OBJ_ID)))
             OR (:I$ROW_NUM = 24 AND EXISTS(SELECT FIRST 1 1 FROM IS_TEACHER(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM LINKS L33 WHERE L33.OBJ_TYPE_ID = 33 AND L33.PARENT_ID = L14.OBJ_ID AND L33.DATE_DEL IS NULL AND NOT EXISTS(SELECT FIRST 1 1 FROM VALL V WHERE V.PARAM_ID = 293 AND V.IS_DEL = 0 AND V.OBJ_ID = L33.OBJ_ID)))
             OR (:I$ROW_NUM = 25 AND EXISTS(SELECT FIRST 1 1 FROM IS_TEACHER(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND NOT EXISTS(SELECT FIRST 1 1 FROM LINKS L34 WHERE L34.OBJ_TYPE_ID = 34 AND L34.PARENT_ID = L14.OBJ_ID AND L34.DATE_DEL IS NULL))
             OR (:I$ROW_NUM = 26 AND EXISTS(SELECT FIRST 1 1 FROM IS_TEACHER(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM LINKS L34 WHERE L34.OBJ_TYPE_ID = 34 AND L34.PARENT_ID = L14.OBJ_ID AND L34.DATE_DEL IS NULL AND NOT EXISTS(SELECT FIRST 1 1 FROM VALD V WHERE V.PARAM_ID = 544 AND V.IS_DEL = 0 AND V.OBJ_ID = L34.OBJ_ID)))
             OR (:I$ROW_NUM = 27 AND EXISTS(SELECT FIRST 1 1 FROM IS_TEACHER(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM LINKS L34 WHERE L34.OBJ_TYPE_ID = 34 AND L34.PARENT_ID = L14.OBJ_ID AND L34.DATE_DEL IS NULL AND NOT EXISTS(SELECT FIRST 1 1 FROM VALL V WHERE V.PARAM_ID = 545 AND V.IS_DEL = 0 AND V.OBJ_ID = L34.OBJ_ID)))
             OR (:I$ROW_NUM = 28 AND EXISTS(SELECT FIRST 1 1 FROM IS_TEACHER(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM LINKS L34 WHERE L34.OBJ_TYPE_ID = 34 AND L34.PARENT_ID = L14.OBJ_ID AND L34.DATE_DEL IS NULL AND NOT EXISTS(SELECT FIRST 1 1 FROM VALS V WHERE V.PARAM_ID = 294 AND V.IS_DEL = 0 AND V.OBJ_ID = L34.OBJ_ID)))
             OR (:I$ROW_NUM = 29 AND NOT EXISTS(SELECT FIRST 1 1 FROM LINKS L15 WHERE L15.OBJ_TYPE_ID = 15 AND L15.PARENT_ID = L14.OBJ_ID AND L15.DATE_DEL IS NULL))
             OR (:I$ROW_NUM = 30 AND EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND (EXISTS(SELECT FIRST 1 1 FROM IS_TEACHER(L14.OBJ_ID) WHERE X=1) OR EXISTS(SELECT FIRST 1 1 FROM IS_MANAGER(L14.OBJ_ID) WHERE X=1)) AND NOT EXISTS(SELECT FIRST 1 1 FROM LINKS L36 WHERE L36.OBJ_TYPE_ID = 36 AND L36.PARENT_ID = L14.OBJ_ID AND L36.DATE_DEL IS NULL))
             OR (:I$ROW_NUM = 31 AND EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND (EXISTS(SELECT FIRST 1 1 FROM IS_TEACHER(L14.OBJ_ID) WHERE X=1) OR EXISTS(SELECT FIRST 1 1 FROM IS_MANAGER(L14.OBJ_ID) WHERE X=1)) AND EXISTS(SELECT FIRST 1 1 FROM LINKS L36 WHERE L36.OBJ_TYPE_ID = 36 AND L36.PARENT_ID = L14.OBJ_ID AND L36.DATE_DEL IS NULL AND NOT EXISTS(SELECT FIRST 1 1 FROM VALL V WHERE V.PARAM_ID = 303 AND V.IS_DEL = 0 AND V.OBJ_ID = L36.OBJ_ID)))
             OR (:I$ROW_NUM = 32 AND EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND (EXISTS(SELECT FIRST 1 1 FROM IS_TEACHER(L14.OBJ_ID) WHERE X=1) OR EXISTS(SELECT FIRST 1 1 FROM IS_MANAGER(L14.OBJ_ID) WHERE X=1)) AND EXISTS(SELECT FIRST 1 1 FROM LINKS L36 WHERE L36.OBJ_TYPE_ID = 36 AND L36.PARENT_ID = L14.OBJ_ID AND L36.DATE_DEL IS NULL AND NOT EXISTS(SELECT FIRST 1 1 FROM VALS V WHERE V.PARAM_ID = 304 AND V.IS_DEL = 0 AND V.OBJ_ID = L36.OBJ_ID)))
             OR (:I$ROW_NUM = 33 AND EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND (EXISTS(SELECT FIRST 1 1 FROM IS_TEACHER(L14.OBJ_ID) WHERE X=1) OR EXISTS(SELECT FIRST 1 1 FROM IS_MANAGER(L14.OBJ_ID) WHERE X=1)) AND EXISTS(SELECT FIRST 1 1 FROM LINKS L36 WHERE L36.OBJ_TYPE_ID = 36 AND L36.PARENT_ID = L14.OBJ_ID AND L36.DATE_DEL IS NULL AND NOT EXISTS(SELECT FIRST 1 1 FROM VALL V WHERE V.PARAM_ID = 1024 AND V.IS_DEL = 0 AND V.OBJ_ID = L36.OBJ_ID)))
             OR (:I$ROW_NUM = 34 AND EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND (EXISTS(SELECT FIRST 1 1 FROM IS_TEACHER(L14.OBJ_ID) WHERE X=1) OR EXISTS(SELECT FIRST 1 1 FROM IS_MANAGER(L14.OBJ_ID) WHERE X=1)) AND EXISTS(SELECT FIRST 1 1 FROM LINKS L36 WHERE L36.OBJ_TYPE_ID = 36 AND L36.PARENT_ID = L14.OBJ_ID AND L36.DATE_DEL IS NULL AND NOT EXISTS(SELECT FIRST 1 1 FROM VALI V WHERE V.PARAM_ID = 306 AND V.IS_DEL = 0 AND V.OBJ_ID = L36.OBJ_ID)))
             OR (:I$ROW_NUM = 35 AND EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND (EXISTS(SELECT FIRST 1 1 FROM IS_TEACHER(L14.OBJ_ID) WHERE X=1) OR EXISTS(SELECT FIRST 1 1 FROM IS_MANAGER(L14.OBJ_ID) WHERE X=1)) AND EXISTS(SELECT FIRST 1 1 FROM LINKS L36 WHERE L36.OBJ_TYPE_ID = 36 AND L36.PARENT_ID = L14.OBJ_ID AND L36.DATE_DEL IS NULL AND NOT EXISTS(SELECT FIRST 1 1 FROM VALD V WHERE V.PARAM_ID = 310 AND V.IS_DEL = 0 AND V.OBJ_ID = L36.OBJ_ID)))
            )

        INTO :WORKER_ID
    DO
    BEGIN
        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:WORKER_ID)
        INTO :NAME;

        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DOU_DISTR_VERIFICATION_REPORT (
    I$DISTRICT_ID BIGINT)
RETURNS (
    SCHOOL_ID BIGINT,
    COL_NUM SMALLINT,
    VAL VARCHAR(4000),
    DATA VARCHAR(4000),
    ORIENTATION VARCHAR(20))
AS
DECLARE VARIABLE V$ROW_NUM smallint;
DECLARE VARIABLE V$PARAM_ID bigint;
BEGIN
    ORIENTATION = 'MIXED';
    DATA = NULL;
    COL_NUM = 1;
    FOR
        SELECT L2.OBJ_ID
        FROM LINKS L2

        WHERE L2.PARENT_ID = :I$DISTRICT_ID
        AND L2.DATE_DEL IS NULL
        AND L2.OBJ_TYPE_ID = 2
        INTO :SCHOOL_ID
    DO
    BEGIN
        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:SCHOOL_ID)
        INTO :VAL;

        SUSPEND;
        COL_NUM = COL_NUM + 1;
    END

    V$ROW_NUM = 1;
    WHILE (V$ROW_NUM < 30) DO
    BEGIN
        V$PARAM_ID =
            CASE V$ROW_NUM
                WHEN 1 THEN 504
                WHEN 2 THEN 505
                WHEN 3 THEN 542
                WHEN 4 THEN 508
                WHEN 5 THEN 486
                WHEN 6 THEN 487
                WHEN 7 THEN 488
                WHEN 8 THEN 489
                WHEN 9 THEN 490
                WHEN 10 THEN 491
                WHEN 11 THEN 492
                WHEN 12 THEN 493
                WHEN 13 THEN 494
                WHEN 14 THEN 495
                WHEN 15 THEN 496
                WHEN 16 THEN 497
                WHEN 17 THEN 498
                WHEN 18 THEN 499
                WHEN 19 THEN 500
                WHEN 20 THEN 501
                WHEN 21 THEN 502
                WHEN 22 THEN 503
                WHEN 23 THEN 509
                WHEN 24 THEN 510
                WHEN 25 THEN 511
                WHEN 26 THEN 512
                WHEN 27 THEN 520
                WHEN 28 THEN 522
                WHEN 29 THEN 521
            END;
        COL_NUM = 1;
        FOR
            SELECT L2.OBJ_ID
            FROM LINKS L2
    
            WHERE L2.PARENT_ID = :I$DISTRICT_ID
            AND L2.DATE_DEL IS NULL
            AND L2.OBJ_TYPE_ID = 2
            INTO :SCHOOL_ID
        DO
        BEGIN
            FOR
                SELECT COUNT(DISTINCT L16.OBJ_ID)
                FROM LINKS L73
    
                JOIN LINKS L16
                ON L16.PARENT_ID = L73.OBJ_ID
                AND L16.DATE_DEL IS NULL
                AND L16.OBJ_TYPE_ID = 16
    
                LEFT JOIN VAL_GET(L16.OBJ_ID, :V$PARAM_ID) VL
                ON 1=1

                WHERE L73.PARENT_ID = :SCHOOL_ID
                AND L73.OBJ_TYPE_ID = 73
                AND L73.DATE_DEL IS NULL
                AND VL.V = ''
            
                INTO :VAL
            DO
            BEGIN
                SUSPEND;
                COL_NUM = COL_NUM + 1;
            END
        END

        V$ROW_NUM = V$ROW_NUM + 1;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DOU_DISTR_VERIFICATION_REPORT2 (
    I$DISTRICT_ID BIGINT)
RETURNS (
    SCHOOL_ID BIGINT,
    COL_NUM SMALLINT,
    VAL VARCHAR(4000),
    DATA VARCHAR(4000),
    ORIENTATION VARCHAR(20))
AS
declare variable V$ROW_NUM smallint;
declare variable V$PARAM_ID bigint;
declare variable V$C0 BIGINT;
BEGIN
    ORIENTATION = 'MIXED';
    DATA = NULL;
    COL_NUM = 1;
    FOR
        SELECT L2.OBJ_ID
        FROM LINKS L2

        WHERE L2.PARENT_ID = :I$DISTRICT_ID
        AND L2.DATE_DEL IS NULL
        AND L2.OBJ_TYPE_ID = 2
        INTO :SCHOOL_ID
    DO
    BEGIN
        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:SCHOOL_ID)
        INTO :VAL;

        SUSPEND;
        COL_NUM = COL_NUM + 1;
    END

    V$ROW_NUM = 1;
    WHILE (V$ROW_NUM < 17) DO
    BEGIN
        COL_NUM = 1;

        FOR
            SELECT L2.OBJ_ID
            FROM LINKS L2
    
            WHERE L2.PARENT_ID = :I$DISTRICT_ID
            AND L2.DATE_DEL IS NULL
            AND L2.OBJ_TYPE_ID = 2
            INTO :SCHOOL_ID
        DO
        BEGIN
          SELECT I
          FROM VAL_GET(:SCHOOL_ID, 11)
          INTO :V$C0;

          IF (V$ROW_NUM BETWEEN 1 and 11) THEN
            BEGIN
                V$PARAM_ID =
                    CASE V$ROW_NUM
                        WHEN 1 THEN 16
                        WHEN 2 THEN 18
                        WHEN 3 THEN 19
                        WHEN 4 THEN 20
                        WHEN 5 THEN 21
                        WHEN 6 THEN 22
                        WHEN 7 THEN 34
                        WHEN 8 THEN 23
                        WHEN 9 THEN 397
                        WHEN 10 THEN 470
                        WHEN 11 THEN 13
                    END;
                IF (EXISTS(
                    SELECT FIRST 1 1
                    FROM VAL_GET(:SCHOOL_ID, :V$PARAM_ID)
                    WHERE V = ''
                ) AND (:V$C0 = 947)) THEN
                BEGIN
                    VAL = 'Нет';
                END
                ELSE
                BEGIN
                    VAL = '';
                END
                SUSPEND;
            END
            ELSE
            BEGIN
                V$PARAM_ID =
                    CASE V$ROW_NUM
                        WHEN 12 THEN 596
                        WHEN 13 THEN 479
                        WHEN 14 THEN 480
                        WHEN 15 THEN 482
                        WHEN 16 THEN 613
                    END;
                FOR
                    SELECT COUNT(DISTINCT L17.OBJ_ID)
                    FROM LINKS L17

                    JOIN VALL V613
                    ON V613.OBJ_ID = L17.OBJ_ID
                    AND V613.PARAM_ID = 613
                    AND V613.IS_DEL = 0
                    AND V613.LISTVAL_ID = 1982

                    LEFT JOIN VAL_GET(L17.OBJ_ID, :V$PARAM_ID) VL
                    ON 1=1

                    WHERE L17.PARENT_ID = :SCHOOL_ID
                    AND L17.DATE_DEL IS NULL
                    AND L17.OBJ_TYPE_ID = 17
                    AND VL.V = ''
                
                    INTO :VAL
                DO
                BEGIN
                    IF (:V$C0 <> 947) THEN
                    BEGIN
                        VAL = 0;
                    END
                    SUSPEND;    
                END
            END
            COL_NUM = COL_NUM + 1;
        END

        V$ROW_NUM = V$ROW_NUM + 1;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DOU_DISTR_VERIFICATION_REPORT3 (
    I$DISTRICT_ID BIGINT)
RETURNS (
    SCHOOL_ID BIGINT,
    COL_NUM SMALLINT,
    ROW_NUM SMALLINT,
    VAL VARCHAR(4000),
    DATA VARCHAR(4000),
    ORIENTATION VARCHAR(20))
AS
declare variable VAL1 integer;
declare variable VAL2 integer;
declare variable VAL3 integer;
declare variable VAL4 integer;
declare variable VAL5 integer;
declare variable VAL6 integer;
declare variable VAL7 integer;
declare variable VAL8 integer;
declare variable VAL9 integer;
declare variable VAL10 integer;
declare variable VAL11 integer;
declare variable VAL12 integer;
declare variable VAL13 integer;
declare variable VAL14 integer;
declare variable VAL15 integer;
declare variable Y integer;
declare variable M integer;
BEGIN
    ORIENTATION = 'MIXED';
    DATA = NULL;
    COL_NUM = 1;
    ROW_NUM = 1;
    FOR
        SELECT L2.OBJ_ID
        FROM LINKS L2

        WHERE L2.PARENT_ID = :I$DISTRICT_ID
        AND L2.DATE_DEL IS NULL
        AND L2.OBJ_TYPE_ID = 2
        INTO :SCHOOL_ID
    DO
    BEGIN
        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:SCHOOL_ID)
        INTO :VAL;

        SUSPEND;
        COL_NUM = COL_NUM + 1;
    END

    M = EXTRACT(MONTH FROM CURRENT_DATE);
    Y = EXTRACT(YEAR FROM CURRENT_DATE);
    IF (M < 9) THEN
    BEGIN
        Y = Y - 1;
    END

    INSERT INTO AGREGATE_PUPIL(PUPIL_ID,SCHOOL_ID,PARENT_TYPE_ID,F1,F2,F3,F4,F5)
        SELECT L10.OBJ_ID,
               L2.OBJ_ID,
               L10.PARENT_TYPE_ID,
               IIF(NOT EXISTS(SELECT FIRST 1 1 FROM LINKS L76 JOIN VALL V432 ON V432.OBJ_ID=L76.OBJ_ID AND V432.PARAM_ID=432 AND V432.IS_DEL=0 WHERE L76.OBJ_TYPE_ID = 76 AND L76.PARENT_ID = L10.OBJ_ID AND L76.DATE_DEL IS NULL AND v432.LISTVAL_ID = 3276),1,0),
               IIF(EXISTS(SELECT FIRST 1 1 FROM LINKS L76 JOIN VALL V432 ON V432.OBJ_ID=L76.OBJ_ID AND V432.PARAM_ID=432 AND V432.IS_DEL=0 AND v432.LISTVAL_ID = 3276
                LEFT JOIN VALD VD433 ON VD433.OBJ_ID=L76.OBJ_ID AND VD433.PARAM_ID=433 AND VD433.IS_DEL=0 WHERE L76.OBJ_TYPE_ID = 76 AND L76.PARENT_ID = L10.OBJ_ID AND L76.DATE_DEL IS NULL  AND VD433.OBJ_ID IS NULL),1,0),
               IIF(NOT EXISTS(SELECT FIRST 1 1 FROM LINKS L20 WHERE L20.OBJ_TYPE_ID = 20 AND L20.PARENT_ID = L10.OBJ_ID AND L20.DATE_DEL IS NULL),1,0),
               IIF(EXISTS(SELECT  FIRST 1 1 FROM LINKS L20 JOIN LINKS L168 ON L168.OBJ_ID = L20.OBJ_ID AND L168.PARENT_ID = L10.OBJ_ID AND L168.EXT_OBJ_TYPE_ID = 168 AND L168.DATE_DEL IS NULL LEFT JOIN VALL V1573 ON V1573.OBJ_ID=L168.EXT_OBJ_ID AND V1573.PARAM_ID=1573 AND V1573.IS_DEL=0 WHERE L20.OBJ_TYPE_ID = 20 AND L20.PARENT_ID = L10.OBJ_ID AND L20.DATE_DEL IS NULL AND V1573.OBJ_ID IS NULL),1,0),
               IIF(EXISTS(SELECT FIRST 1 1 FROM LINKS L20 LEFT JOIN VALL V2453 ON V2453.OBJ_ID=L20.EXT_OBJ_ID AND V2453.PARAM_ID=2453 AND V2453.IS_DEL=0 WHERE L20.OBJ_TYPE_ID = 20 AND L20.PARENT_ID = L10.OBJ_ID AND L20.DATE_DEL IS NULL AND V2453.OBJ_ID IS NULL),1,0)

        FROM LINKS L2

        JOIN LINKS L7
        ON L7.PARENT_ID = L2.OBJ_ID
        AND L7.DATE_DEL IS NULL
        AND L7.OBJ_TYPE_ID = 7

        JOIN LINKS L8
        ON L8.PARENT_ID = L7.OBJ_ID
        AND L8.OBJ_TYPE_ID = 8
        AND L8.DATE_DEL IS NULL

        JOIN LINKS L9
        ON L9.PARENT_ID = L8.OBJ_ID
        AND L9.OBJ_TYPE_ID = 9
        AND L9.DATE_DEL IS NULL

        JOIN LINKS L10
        ON L10.PARENT_ID = L9.OBJ_ID
        AND L10.OBJ_TYPE_ID = 10
        AND L10.DATE_DEL IS NULL

        WHERE L2.PARENT_ID = :I$DISTRICT_ID
        AND L2.DATE_DEL IS NULL
        AND L2.OBJ_TYPE_ID = 2

        UNION

        SELECT DISTINCT L10.OBJ_ID,
               L2.OBJ_ID,
               L10.PARENT_TYPE_ID,
               0, 0, 0, 0, 0
        FROM LINKS L2

        JOIN LINKS L78
        ON L78.PARENT_ID = L2.OBJ_ID
        AND L78.DATE_DEL IS NULL
        AND L78.OBJ_TYPE_ID = 78
    
        JOIN LINKS L82
        ON L82.PARENT_ID = L78.OBJ_ID
        AND L82.DATE_DEL IS NULL
        AND L82.OBJ_TYPE_ID = 82
    
        JOIN VALI V448
        ON V448.OBJ_ID = L82.OBJ_ID
        AND V448.PARAM_ID = 448
        AND V448.IS_DEL = 0
        AND V448.VAL = :Y
    
        JOIN LINKS L10
        ON L10.PARENT_ID = L82.OBJ_ID
        AND L10.DATE_DEL IS NULL
        AND L10.OBJ_TYPE_ID = 10

        WHERE L2.PARENT_ID = :I$DISTRICT_ID
        AND L2.DATE_DEL IS NULL
        AND L2.OBJ_TYPE_ID = 2;

    COL_NUM = 1;

    FOR
        SELECT L2.OBJ_ID
        FROM LINKS L2

        WHERE L2.PARENT_ID = :I$DISTRICT_ID
        AND L2.DATE_DEL IS NULL
        AND L2.OBJ_TYPE_ID = 2

        INTO :SCHOOL_ID
    DO
    BEGIN
        FOR 
            SELECT SUM(IIF((AP.PARENT_TYPE_ID = 9) AND EXISTS(SELECT FIRST 1 1 FROM VAL_GET(AP.PUPIL_ID, 108) WHERE V=''),1,0)),
                   SUM(IIF((AP.PARENT_TYPE_ID = 9) AND EXISTS(SELECT FIRST 1 1 FROM ADR_GET(103, AP.PUPIL_ID) WHERE REGION LIKE 'Санкт-Петербург%')
                   AND EXISTS(SELECT FIRST 1 1 FROM VAL_GET(AP.PUPIL_ID, 101) WHERE V=''),1,0)),
                   SUM(IIF((AP.PARENT_TYPE_ID = 9) AND EXISTS(SELECT FIRST 1 1 FROM VAL_GET(AP.PUPIL_ID, 103) WHERE V=''),1,0)),
                   SUM(IIF((AP.PARENT_TYPE_ID = 9) AND EXISTS(SELECT FIRST 1 1 FROM VAL_GET(AP.PUPIL_ID, 111) WHERE V=''),1,0)),
                   SUM(IIF((AP.PARENT_TYPE_ID = 9) AND EXISTS(SELECT FIRST 1 1 FROM VAL_GET(AP.PUPIL_ID, 118) WHERE V=''),1,0)),
                   SUM(IIF((AP.PARENT_TYPE_ID = 9) AND EXISTS(SELECT FIRST 1 1 FROM VAL_GET(AP.PUPIL_ID, 119) WHERE V=''),1,0)),
                   SUM(IIF((AP.PARENT_TYPE_ID = 9) AND EXISTS(SELECT FIRST 1 1 FROM VAL_GET(AP.PUPIL_ID, 1552) WHERE (V='' or V='0%') ),1,0)),
                   SUM(IIF((AP.PARENT_TYPE_ID = 9) AND EXISTS(SELECT FIRST 1 1 FROM VAL_GET(AP.PUPIL_ID, 208) WHERE V=''),1,0)),
                   SUM(IIF((AP.PARENT_TYPE_ID IN (9,82)) AND EXISTS(SELECT FIRST 1 1 FROM VAL_GET(AP.PUPIL_ID, 78) WHERE V=''),1,0)),
                   SUM(IIF((AP.PARENT_TYPE_ID = 9) AND AP.F1=1,1,0)),
                   SUM(IIF((AP.PARENT_TYPE_ID = 9) AND AP.F2=1,1,0)),
                   SUM(IIF((AP.PARENT_TYPE_ID = 82) AND EXISTS(SELECT FIRST 1 1 FROM VAL_GET(AP.PUPIL_ID, 105) WHERE V=''),1,0)),
                   SUM(IIF((AP.PARENT_TYPE_ID = 9) AND AP.F3=1,1,0)),
                   SUM(IIF((AP.PARENT_TYPE_ID = 9) AND AP.F4=1,1,0)),
                   SUM(IIF((AP.PARENT_TYPE_ID = 9) AND AP.F5=1,1,0))

            FROM AGREGATE_PUPIL AP

            WHERE AP.SCHOOL_ID = :SCHOOL_ID

            INTO :VAL1,
                 :VAL2,
                 :VAL3,
                 :VAL4,
                 :VAL5,
                 :VAL6,
                 :VAL7,
                 :VAL8,
                 :VAL9,
                 :VAL10,
                 :VAL11,
                 :VAL12,
                 :VAL13,
                 :VAL14,
                 :VAL15
        DO
        BEGIN
            VAL = VAL1;
            ROW_NUM = 2;
            SUSPEND;

            VAL = VAL2;
            ROW_NUM = 3;
            SUSPEND;

            VAL = VAL3;
            ROW_NUM = 4;
            SUSPEND;

            VAL = VAL4;
            ROW_NUM = 5;
            SUSPEND;

            VAL = VAL5;
            ROW_NUM = 6;
            SUSPEND;

            VAL = VAL6;
            ROW_NUM = 7;
            SUSPEND;

            VAL = VAL7;
            ROW_NUM = 8;
            SUSPEND;

            VAL = VAL8;
            ROW_NUM = 9;
            SUSPEND;

            VAL = VAL9;
            ROW_NUM = 10;
            SUSPEND;

            VAL = VAL10;
            ROW_NUM = 11;
            SUSPEND;

            VAL = VAL11;
            ROW_NUM = 12;
            SUSPEND;

            VAL = VAL12;
            ROW_NUM = 13;
            SUSPEND;

            VAL = VAL13;
            ROW_NUM = 14;
            SUSPEND;

            VAL = VAL14;
            ROW_NUM = 15;
            SUSPEND;

            VAL = VAL15;
            ROW_NUM = 16;
            SUSPEND;

            COL_NUM = COL_NUM + 1;
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DOU_DISTR_VERIFICATION_REPORT4 (
    I$DISTRICT_ID BIGINT)
RETURNS (
    SCHOOL_ID BIGINT,
    COL_NUM SMALLINT,
    ROW_NUM SMALLINT,
    VAL VARCHAR(4000),
    DATA VARCHAR(4000),
    ORIENTATION VARCHAR(20))
AS
DECLARE VARIABLE VAL1 INTEGER;
DECLARE VARIABLE VAL2 INTEGER;
DECLARE VARIABLE VAL3 INTEGER;
DECLARE VARIABLE VAL4 INTEGER;
DECLARE VARIABLE VAL5 INTEGER;
DECLARE VARIABLE VAL6 INTEGER;
DECLARE VARIABLE VAL7 INTEGER;
DECLARE VARIABLE VAL8 INTEGER;
DECLARE VARIABLE VAL9 INTEGER;
DECLARE VARIABLE VAL10 INTEGER;
DECLARE VARIABLE VAL11 INTEGER;
DECLARE VARIABLE VAL12 INTEGER;
DECLARE VARIABLE VAL13 INTEGER;
DECLARE VARIABLE VAL14 INTEGER;
DECLARE VARIABLE VAL15 INTEGER;
DECLARE VARIABLE VAL16 INTEGER;
DECLARE VARIABLE VAL17 INTEGER;
DECLARE VARIABLE VAL18 INTEGER;
DECLARE VARIABLE VAL19 INTEGER;
DECLARE VARIABLE VAL20 INTEGER;
DECLARE VARIABLE VAL21 INTEGER;
DECLARE VARIABLE VAL22 INTEGER;
DECLARE VARIABLE VAL23 INTEGER;
DECLARE VARIABLE VAL24 INTEGER;
DECLARE VARIABLE VAL25 INTEGER;
DECLARE VARIABLE VAL26 INTEGER;
DECLARE VARIABLE VAL27 INTEGER;
DECLARE VARIABLE VAL28 INTEGER;
DECLARE VARIABLE VAL29 INTEGER;
DECLARE VARIABLE VAL30 INTEGER;
DECLARE VARIABLE VAL31 INTEGER;
DECLARE VARIABLE VAL32 INTEGER;
DECLARE VARIABLE VAL33 INTEGER;
DECLARE VARIABLE VAL34 INTEGER;
DECLARE VARIABLE VAL35 INTEGER;
BEGIN
    ORIENTATION = 'MIXED';
    DATA = NULL;
    COL_NUM = 1;
    ROW_NUM = 1;
    FOR
        SELECT L2.OBJ_ID
        FROM LINKS L2

        WHERE L2.PARENT_ID = :I$DISTRICT_ID
        AND L2.DATE_DEL IS NULL
        AND L2.OBJ_TYPE_ID = 2
        INTO :SCHOOL_ID
    DO
    BEGIN
        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:SCHOOL_ID)
        INTO :VAL;

        SUSPEND;
        COL_NUM = COL_NUM + 1;
    END

    COL_NUM = 1;
    FOR
        SELECT L2.OBJ_ID
        FROM LINKS L2
    
        WHERE L2.PARENT_ID = :I$DISTRICT_ID
        AND L2.DATE_DEL IS NULL
        AND L2.OBJ_TYPE_ID = 2
        INTO :SCHOOL_ID
    DO
    BEGIN
        FOR
            SELECT SUM(IIF(NOT EXISTS(SELECT FIRST 1 1 FROM VALL V243 WHERE V243.OBJ_ID=L14.OBJ_ID AND V243.PARAM_ID=243 AND V243.IS_DEL=0),1,0)),
                   SUM(IIF(EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND NOT EXISTS(SELECT FIRST 1 1 FROM VALS V244 WHERE V244.OBJ_ID=L14.OBJ_ID AND V244.PARAM_ID=244 AND V244.IS_DEL=0),1,0)),
                   SUM(IIF(EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND NOT EXISTS(SELECT FIRST 1 1 FROM VALA V255 WHERE V255.OBJ_ID=L14.OBJ_ID AND V255.PARAM_ID=255 AND V255.IS_DEL=0),1,0)),
                   SUM(IIF(EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND NOT EXISTS(SELECT FIRST 1 1 FROM VALA V262 WHERE V262.OBJ_ID=L14.OBJ_ID AND V262.PARAM_ID=262 AND V262.IS_DEL=0),1,0)),
                   SUM(IIF(EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND NOT EXISTS(SELECT FIRST 1 1 FROM VALS V250 WHERE V250.OBJ_ID=L14.OBJ_ID AND V250.PARAM_ID=250 AND V250.IS_DEL=0),1,0)),
                   SUM(IIF(EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND NOT EXISTS(SELECT FIRST 1 1 FROM LINKS L85 JOIN VALL V465 ON V465.OBJ_ID = L85.OBJ_ID AND V465.PARAM_ID = 465 AND V465.IS_DEL = 0 JOIN VALD V466 ON V466.OBJ_ID = L85.OBJ_ID AND V466.PARAM_ID = 466 AND V466.IS_DEL = 0 WHERE L85.PARENT_ID=L14.OBJ_ID AND L85.OBJ_TYPE_ID = 85 AND L85.DATE_DEL IS NULL AND V465.LISTVAL_ID = 941),1,0)),
                   SUM(IIF(EXISTS(SELECT FIRST 1 1 FROM IS_TEACHER(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) STAFF WHERE STAFF.X=1) AND NOT EXISTS(SELECT FIRST 1 1 FROM LINKS L85 JOIN VALL V465 ON V465.OBJ_ID = L85.OBJ_ID AND V465.PARAM_ID = 465 AND V465.IS_DEL = 0 JOIN VALD V466 ON V466.OBJ_ID = L85.OBJ_ID AND V466.PARAM_ID = 466 AND V466.IS_DEL = 0 WHERE L85.PARENT_ID=L14.OBJ_ID AND L85.OBJ_TYPE_ID = 85 AND L85.DATE_DEL IS NULL AND V465.LISTVAL_ID = 942),1,0)),
                   SUM(IIF(EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) STAFF WHERE STAFF.X=1) AND NOT EXISTS(SELECT FIRST 1 1 FROM LINKS L79 WHERE L79.OBJ_TYPE_ID = 79 AND L79.PARENT_ID = L14.OBJ_ID AND L79.DATE_DEL IS NULL),1,0)),
                   SUM(IIF(EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) STAFF WHERE STAFF.X=1) AND EXISTS(SELECT FIRST 1 1 FROM LINKS L79 WHERE L79.OBJ_TYPE_ID = 79 AND L79.PARENT_ID = L14.OBJ_ID AND L79.DATE_DEL IS NULL AND NOT EXISTS(SELECT FIRST 1 1 FROM VALS VS WHERE VS.PARAM_ID = 442 AND VS.IS_DEL = 0 AND VS.OBJ_ID = L79.OBJ_ID)),1,0)),
                   SUM(IIF(EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) STAFF WHERE STAFF.X=1) AND EXISTS(SELECT FIRST 1 1 FROM LINKS L79 WHERE L79.OBJ_TYPE_ID = 79 AND L79.PARENT_ID = L14.OBJ_ID AND L79.DATE_DEL IS NULL AND NOT EXISTS(SELECT FIRST 1 1 FROM VALS VS WHERE VS.PARAM_ID = 559 AND VS.IS_DEL = 0 AND VS.OBJ_ID = L79.OBJ_ID)),1,0)),
                   SUM(IIF(NOT EXISTS(SELECT FIRST 1 1 FROM LINKS L15 JOIN VALL VLL ON VLL.OBJ_ID = L15.OBJ_ID AND VLL.PARAM_ID = 72 AND VLL.IS_DEL = 0 AND VLL.LISTVAL_ID = 934 LEFT JOIN VALD V74 ON V74.PARAM_ID = 74 AND V74.OBJ_ID = L15.OBJ_ID AND V74.IS_DEL = 0 WHERE L15.OBJ_TYPE_ID = 15 AND L15.PARENT_ID = L14.OBJ_ID AND L15.DATE_DEL IS NULL AND V74.VAL IS NULL),1,0)),
                   SUM(IIF(EXISTS(SELECT FIRST 1 1 FROM LINKS L15 LEFT JOIN VALF V ON V.OBJ_ID=L15.OBJ_ID AND V.PARAM_ID=71 AND V.IS_DEL=0 WHERE L15.PARENT_ID=L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL AND V.VAL IS NULL),1,0)),
                   SUM(IIF(EXISTS(SELECT FIRST 1 1 FROM LINKS L15 LEFT JOIN VALL V ON V.OBJ_ID=L15.OBJ_ID AND V.PARAM_ID=587 AND V.IS_DEL=0 WHERE L15.PARENT_ID=L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL AND V.LISTVAL_ID IS NULL),1,0)),
                   SUM(IIF(EXISTS(SELECT FIRST 1 1 FROM LINKS L15 LEFT JOIN VALL V ON V.OBJ_ID=L15.OBJ_ID AND V.PARAM_ID=72 AND V.IS_DEL=0 WHERE L15.PARENT_ID=L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL AND V.LISTVAL_ID IS NULL),1,0)),
                   SUM(IIF(EXISTS(SELECT FIRST 1 1 FROM LINKS L15 LEFT JOIN VALD V ON V.OBJ_ID=L15.OBJ_ID AND V.PARAM_ID=73 AND V.IS_DEL=0 WHERE L15.PARENT_ID=L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL AND V.VAL IS NULL),1,0)),
                   SUM(IIF(EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM LINKS L33 WHERE L33.OBJ_TYPE_ID = 33 AND L33.PARENT_ID = L14.OBJ_ID AND L33.DATE_DEL IS NULL AND NOT EXISTS(SELECT FIRST 1 1 FROM VALL VS WHERE VS.PARAM_ID = 284 AND VS.IS_DEL = 0 AND VS.OBJ_ID = L33.OBJ_ID)),1,0)),
                   SUM(IIF(EXISTS(SELECT FIRST 1 1 FROM IS_TEACHER(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM LINKS L33 WHERE L33.OBJ_TYPE_ID = 33 AND L33.PARENT_ID = L14.OBJ_ID AND L33.DATE_DEL IS NULL AND NOT EXISTS(SELECT FIRST 1 1 FROM VALS V WHERE V.PARAM_ID = 285 AND V.IS_DEL = 0 AND V.OBJ_ID = L33.OBJ_ID)),1,0)),
                   SUM(IIF(EXISTS(SELECT FIRST 1 1 FROM IS_TEACHER(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM LINKS L33 WHERE L33.OBJ_TYPE_ID = 33 AND L33.PARENT_ID = L14.OBJ_ID AND L33.DATE_DEL IS NULL AND NOT EXISTS(SELECT FIRST 1 1 FROM VALS V WHERE V.PARAM_ID = 287 AND V.IS_DEL = 0 AND V.OBJ_ID = L33.OBJ_ID)),1,0)),
                   SUM(IIF(EXISTS(SELECT FIRST 1 1 FROM IS_TEACHER(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM LINKS L33 WHERE L33.OBJ_TYPE_ID = 33 AND L33.PARENT_ID = L14.OBJ_ID AND L33.DATE_DEL IS NULL AND NOT EXISTS(SELECT FIRST 1 1 FROM VALL V WHERE V.PARAM_ID = 286 AND V.IS_DEL = 0 AND V.OBJ_ID = L33.OBJ_ID)),1,0)),
                   SUM(IIF(EXISTS(SELECT FIRST 1 1 FROM IS_TEACHER(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM LINKS L33 WHERE L33.OBJ_TYPE_ID = 33 AND L33.PARENT_ID = L14.OBJ_ID AND L33.DATE_DEL IS NULL AND NOT EXISTS(SELECT FIRST 1 1 FROM VALS V WHERE V.PARAM_ID = 288 AND V.IS_DEL = 0 AND V.OBJ_ID = L33.OBJ_ID)),1,0)),
                   SUM(IIF(EXISTS(SELECT FIRST 1 1 FROM IS_TEACHER(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM LINKS L33 WHERE L33.OBJ_TYPE_ID = 33 AND L33.PARENT_ID = L14.OBJ_ID AND L33.DATE_DEL IS NULL AND NOT EXISTS(SELECT FIRST 1 1 FROM VALD V WHERE V.PARAM_ID = 290 AND V.IS_DEL = 0 AND V.OBJ_ID = L33.OBJ_ID)),1,0)),
                   SUM(IIF(EXISTS(SELECT FIRST 1 1 FROM IS_TEACHER(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM LINKS L33 WHERE L33.OBJ_TYPE_ID = 33 AND L33.PARENT_ID = L14.OBJ_ID AND L33.DATE_DEL IS NULL AND NOT EXISTS(SELECT FIRST 1 1 FROM VALS V WHERE V.PARAM_ID = 291 AND V.IS_DEL = 0 AND V.OBJ_ID = L33.OBJ_ID)),1,0)),
                   SUM(IIF(EXISTS(SELECT FIRST 1 1 FROM IS_TEACHER(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM LINKS L33 WHERE L33.OBJ_TYPE_ID = 33 AND L33.PARENT_ID = L14.OBJ_ID AND L33.DATE_DEL IS NULL AND NOT EXISTS(SELECT FIRST 1 1 FROM VALS V WHERE V.PARAM_ID = 292 AND V.IS_DEL = 0 AND V.OBJ_ID = L33.OBJ_ID)),1,0)),
                   SUM(IIF(EXISTS(SELECT FIRST 1 1 FROM IS_TEACHER(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM LINKS L33 WHERE L33.OBJ_TYPE_ID = 33 AND L33.PARENT_ID = L14.OBJ_ID AND L33.DATE_DEL IS NULL AND NOT EXISTS(SELECT FIRST 1 1 FROM VALL V WHERE V.PARAM_ID = 293 AND V.IS_DEL = 0 AND V.OBJ_ID = L33.OBJ_ID)),1,0)),
                   SUM(IIF(EXISTS(SELECT FIRST 1 1 FROM IS_TEACHER(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND NOT EXISTS(SELECT FIRST 1 1 FROM LINKS L34 WHERE L34.OBJ_TYPE_ID = 34 AND L34.PARENT_ID = L14.OBJ_ID AND L34.DATE_DEL IS NULL),1,0)),
                   SUM(IIF(EXISTS(SELECT FIRST 1 1 FROM IS_TEACHER(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM LINKS L34 WHERE L34.OBJ_TYPE_ID = 34 AND L34.PARENT_ID = L14.OBJ_ID AND L34.DATE_DEL IS NULL AND NOT EXISTS(SELECT FIRST 1 1 FROM VALD V WHERE V.PARAM_ID = 544 AND V.IS_DEL = 0 AND V.OBJ_ID = L34.OBJ_ID)),1,0)),
                   SUM(IIF(EXISTS(SELECT FIRST 1 1 FROM IS_TEACHER(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM LINKS L34 WHERE L34.OBJ_TYPE_ID = 34 AND L34.PARENT_ID = L14.OBJ_ID AND L34.DATE_DEL IS NULL AND NOT EXISTS(SELECT FIRST 1 1 FROM VALL V WHERE V.PARAM_ID = 545 AND V.IS_DEL = 0 AND V.OBJ_ID = L34.OBJ_ID)),1,0)),
                   SUM(IIF(EXISTS(SELECT FIRST 1 1 FROM IS_TEACHER(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND EXISTS(SELECT FIRST 1 1 FROM LINKS L34 WHERE L34.OBJ_TYPE_ID = 34 AND L34.PARENT_ID = L14.OBJ_ID AND L34.DATE_DEL IS NULL AND NOT EXISTS(SELECT FIRST 1 1 FROM VALS V WHERE V.PARAM_ID = 294 AND V.IS_DEL = 0 AND V.OBJ_ID = L34.OBJ_ID)),1,0)),
                   SUM(IIF(NOT EXISTS(SELECT FIRST 1 1 FROM LINKS L15 WHERE L15.OBJ_TYPE_ID = 15 AND L15.PARENT_ID = L14.OBJ_ID AND L15.DATE_DEL IS NULL),1,0)),
                   SUM(IIF(EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND (EXISTS(SELECT FIRST 1 1 FROM IS_TEACHER(L14.OBJ_ID) WHERE X=1) OR EXISTS(SELECT FIRST 1 1 FROM IS_MANAGER(L14.OBJ_ID) WHERE X=1)) AND NOT EXISTS(SELECT FIRST 1 1 FROM LINKS L36 WHERE L36.OBJ_TYPE_ID = 36 AND L36.PARENT_ID = L14.OBJ_ID AND L36.DATE_DEL IS NULL),1,0)),
                   SUM(IIF(EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND (EXISTS(SELECT FIRST 1 1 FROM IS_TEACHER(L14.OBJ_ID) WHERE X=1) OR EXISTS(SELECT FIRST 1 1 FROM IS_MANAGER(L14.OBJ_ID) WHERE X=1)) AND EXISTS(SELECT FIRST 1 1 FROM LINKS L36 WHERE L36.OBJ_TYPE_ID = 36 AND L36.PARENT_ID = L14.OBJ_ID AND L36.DATE_DEL IS NULL AND NOT EXISTS(SELECT FIRST 1 1 FROM VALL V WHERE V.PARAM_ID = 303 AND V.IS_DEL = 0 AND V.OBJ_ID = L36.OBJ_ID)),1,0)),
                   SUM(IIF(EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND (EXISTS(SELECT FIRST 1 1 FROM IS_TEACHER(L14.OBJ_ID) WHERE X=1) OR EXISTS(SELECT FIRST 1 1 FROM IS_MANAGER(L14.OBJ_ID) WHERE X=1)) AND EXISTS(SELECT FIRST 1 1 FROM LINKS L36 WHERE L36.OBJ_TYPE_ID = 36 AND L36.PARENT_ID = L14.OBJ_ID AND L36.DATE_DEL IS NULL AND NOT EXISTS(SELECT FIRST 1 1 FROM VALS V WHERE V.PARAM_ID = 304 AND V.IS_DEL = 0 AND V.OBJ_ID = L36.OBJ_ID)),1,0)),
                   SUM(IIF(EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND (EXISTS(SELECT FIRST 1 1 FROM IS_TEACHER(L14.OBJ_ID) WHERE X=1) OR EXISTS(SELECT FIRST 1 1 FROM IS_MANAGER(L14.OBJ_ID) WHERE X=1)) AND EXISTS(SELECT FIRST 1 1 FROM LINKS L36 WHERE L36.OBJ_TYPE_ID = 36 AND L36.PARENT_ID = L14.OBJ_ID AND L36.DATE_DEL IS NULL AND NOT EXISTS(SELECT FIRST 1 1 FROM VALL V WHERE V.PARAM_ID = 1024 AND V.IS_DEL = 0 AND V.OBJ_ID = L36.OBJ_ID)),1,0)),
                   SUM(IIF(EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND (EXISTS(SELECT FIRST 1 1 FROM IS_TEACHER(L14.OBJ_ID) WHERE X=1) OR EXISTS(SELECT FIRST 1 1 FROM IS_MANAGER(L14.OBJ_ID) WHERE X=1)) AND EXISTS(SELECT FIRST 1 1 FROM LINKS L36 WHERE L36.OBJ_TYPE_ID = 36 AND L36.PARENT_ID = L14.OBJ_ID AND L36.DATE_DEL IS NULL AND NOT EXISTS(SELECT FIRST 1 1 FROM VALI V WHERE V.PARAM_ID = 306 AND V.IS_DEL = 0 AND V.OBJ_ID = L36.OBJ_ID)),1,0)),
                   SUM(IIF(EXISTS(SELECT FIRST 1 1 FROM IS_ON_THE_STAFF(L14.OBJ_ID) WHERE X=1) AND (EXISTS(SELECT FIRST 1 1 FROM IS_TEACHER(L14.OBJ_ID) WHERE X=1) OR EXISTS(SELECT FIRST 1 1 FROM IS_MANAGER(L14.OBJ_ID) WHERE X=1)) AND EXISTS(SELECT FIRST 1 1 FROM LINKS L36 WHERE L36.OBJ_TYPE_ID = 36 AND L36.PARENT_ID = L14.OBJ_ID AND L36.DATE_DEL IS NULL AND NOT EXISTS(SELECT FIRST 1 1 FROM VALD V WHERE V.PARAM_ID = 310 AND V.IS_DEL = 0 AND V.OBJ_ID = L36.OBJ_ID)),1,0))

            FROM LINKS L14

            WHERE L14.PARENT_ID = :SCHOOL_ID
            AND L14.OBJ_TYPE_ID = 14
            AND L14.DATE_DEL IS NULL

            INTO :VAL1,
                 :VAL2,
                 :VAL3,
                 :VAL4,
                 :VAL5,
                 :VAL6,
                 :VAL7,
                 :VAL8,
                 :VAL9,
                 :VAL10,
                 :VAL11,
                 :VAL12,
                 :VAL13,
                 :VAL14,
                 :VAL15,
                 :VAL16,
                 :VAL17,
                 :VAL18,
                 :VAL19,
                 :VAL20,
                 :VAL21,
                 :VAL22,
                 :VAL23,
                 :VAL24,
                 :VAL25,
                 :VAL26,
                 :VAL27,
                 :VAL28,
                 :VAL29,
                 :VAL30,
                 :VAL31,
                 :VAL32,
                 :VAL33,
                 :VAL34,
                 :VAL35
        DO
        BEGIN
            ROW_NUM = 2;
            VAL = VAL1;
            SUSPEND;

            ROW_NUM = 3;
            VAL = VAL2;
            SUSPEND;

            ROW_NUM = 4;
            VAL = VAL3;
            SUSPEND;

            ROW_NUM = 5;
            VAL = VAL4;
            SUSPEND;

            ROW_NUM = 6;
            VAL = VAL5;
            SUSPEND;

            ROW_NUM = 7;
            VAL = VAL6;
            SUSPEND;

            ROW_NUM = 8;
            VAL = VAL7;
            SUSPEND;

            ROW_NUM = 9;
            VAL = VAL8;
            SUSPEND;

            ROW_NUM = 10;
            VAL = VAL9;
            SUSPEND;

            ROW_NUM = 11;
            VAL = VAL10;
            SUSPEND;

            ROW_NUM = 12;
            VAL = VAL11;
            SUSPEND;

            ROW_NUM = 13;
            VAL = VAL12;
            SUSPEND;

            ROW_NUM = 14;
            VAL = VAL13;
            SUSPEND;

            ROW_NUM = 15;
            VAL = VAL14;
            SUSPEND;

            ROW_NUM = 16;
            VAL = VAL15;
            SUSPEND;

            ROW_NUM = 17;
            VAL = VAL16;
            SUSPEND;

            ROW_NUM = 18;
            VAL = VAL17;
            SUSPEND;

            ROW_NUM = 19;
            VAL = VAL18;
            SUSPEND;

            ROW_NUM = 20;
            VAL = VAL19;
            SUSPEND;

            ROW_NUM = 21;
            VAL = VAL20;
            SUSPEND;

            ROW_NUM = 22;
            VAL = VAL21;
            SUSPEND;

            ROW_NUM = 23;
            VAL = VAL22;
            SUSPEND;

            ROW_NUM = 24;
            VAL = VAL23;
            SUSPEND;

            ROW_NUM = 25;
            VAL = VAL24;
            SUSPEND;

            ROW_NUM = 26;
            VAL = VAL25;
            SUSPEND;

            ROW_NUM = 27;
            VAL = VAL26;
            SUSPEND;

            ROW_NUM = 28;
            VAL = VAL27;
            SUSPEND;

            ROW_NUM = 29;
            VAL = VAL28;
            SUSPEND;

            ROW_NUM = 30;
            VAL = VAL29;
            SUSPEND;

            ROW_NUM = 31;
            VAL = VAL30;
            SUSPEND;

            ROW_NUM = 32;
            VAL = VAL31;
            SUSPEND;

            ROW_NUM = 33;
            VAL = VAL32;
            SUSPEND;

            ROW_NUM = 34;
            VAL = VAL33;
            SUSPEND;

            ROW_NUM = 35;
            VAL = VAL34;
            SUSPEND;

            ROW_NUM = 36;
            VAL = VAL35;
            SUSPEND;

            COL_NUM = COL_NUM + 1;
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DOU_DISTR_VERIFICATION_REP_DTL (
    I$SCHOOL_ID BIGINT,
    I$ROW_NUM SMALLINT)
RETURNS (
    BUILDING_ID BIGINT,
    NAME VARCHAR(4000))
AS
DECLARE VARIABLE V$PARAM_ID bigint;
BEGIN
    V$PARAM_ID =
        CASE I$ROW_NUM
            WHEN 1 THEN 504
            WHEN 2 THEN 505
            WHEN 3 THEN 542
            WHEN 4 THEN 508
            WHEN 5 THEN 486
            WHEN 6 THEN 487
            WHEN 7 THEN 488
            WHEN 8 THEN 489
            WHEN 9 THEN 490
            WHEN 10 THEN 491
            WHEN 11 THEN 492
            WHEN 12 THEN 493
            WHEN 13 THEN 494
            WHEN 14 THEN 495
            WHEN 15 THEN 496
            WHEN 16 THEN 497
            WHEN 17 THEN 498
            WHEN 18 THEN 499
            WHEN 19 THEN 500
            WHEN 20 THEN 501
            WHEN 21 THEN 502
            WHEN 22 THEN 503
            WHEN 23 THEN 509
            WHEN 24 THEN 510
            WHEN 25 THEN 511
            WHEN 26 THEN 512
            WHEN 27 THEN 520
            WHEN 28 THEN 522
            WHEN 29 THEN 521
            ELSE NULL
        END;

    FOR
        SELECT L16.OBJ_ID
        FROM LINKS L73
    
        JOIN LINKS L16
        ON L16.PARENT_ID = L73.OBJ_ID
        AND L16.DATE_DEL IS NULL
        AND L16.OBJ_TYPE_ID = 16
    
        LEFT JOIN VAL_GET(L16.OBJ_ID, :V$PARAM_ID) VL
        ON 1=1

        WHERE L73.PARENT_ID = :I$SCHOOL_ID
        AND L73.OBJ_TYPE_ID = 73
        AND L73.DATE_DEL IS NULL
        AND VL.V = ''
            
        INTO :BUILDING_ID
    DO
    BEGIN
        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:BUILDING_ID)
        INTO :NAME;

        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DOU_GROUP_DIRECTION_LIST (
    I$OBJ_ID BIGINT,
    I$PARAM_ID BIGINT,
    I$USER_ID BIGINT = NULL)
RETURNS (
    LISTVAL_ID BIGINT,
    PARENT_ID BIGINT,
    VAL VARCHAR(4000),
    VAL_LONG VARCHAR(4000))
AS
DECLARE VARIABLE RES_ID BIGINT;
DECLARE VARIABLE LANG_CODE VARCHAR(2);
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :LANG_CODE;
    -- Для класса (тип 9) выведем отдельно значения 0-го уровня вложенности для 1549, и 1-го уровня - для 1655
    FOR
      SELECT L.LISTVAL_ID, NULL, L.RES_ID
      FROM LISTVALS L
      WHERE L.LIST_ID = 224 AND L.IS_DEL = 0
        AND ((L.PARENT_ID IS NULL AND :I$PARAM_ID = 1549) OR
          (:I$PARAM_ID = 1655 AND :I$OBJ_ID IS NOT NULL AND L.PARENT_ID = (SELECT V.LISTVAL_ID FROM VALL V WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 1549 AND V.IS_DEL = 0)) OR
          (:I$PARAM_ID = 1655 AND :I$OBJ_ID IS NULL AND L.PARENT_ID IS NOT NULL))
      ORDER BY L.SORT_ORDER
      INTO :LISTVAL_ID, :PARENT_ID, :RES_ID
    DO
    BEGIN
      SELECT VAL, VAL_LONG
      FROM RES_GET(:RES_ID, :LANG_CODE)
      INTO :VAL, :VAL_LONG;
      SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DOU_SCHOOLAR_IN (
    I$SCHOOL_ID BIGINT,
    I$FROM DATE,
    I$TO DATE)
RETURNS (
    C1 DATE,
    C2 VARCHAR(1000),
    C31 VARCHAR(1000),
    C41 DATE,
    C3 VARCHAR(1000),
    C4 DATE,
    C5 VARCHAR(1000),
    C6 VARCHAR(1000),
    C7 VARCHAR(1000),
    C8 VARCHAR(1000),
    C9 VARCHAR(1000))
AS
declare variable V$SCHOOLAR_ID bigint;
declare variable V$MOVEMENT_ID bigint;
BEGIN
  FOR
    SELECT DISTINCT L10.OBJ_ID
    FROM LINKS L7
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
    JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    WHERE L7.PARENT_ID = :I$SCHOOL_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    UNION
    SELECT DISTINCT L10.OBJ_ID
    FROM LINKS L78
    JOIN LINKS L ON L.PARENT_ID = L78.OBJ_ID AND L.OBJ_TYPE_ID IN (81, 82, 83) AND L.DATE_DEL IS NULL
    JOIN LINKS L10 ON L10.PARENT_ID = L.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    WHERE L78.PARENT_ID = :I$SCHOOL_ID AND L78.OBJ_TYPE_ID = 78 AND L78.DATE_DEL IS NULL
    INTO :V$SCHOOLAR_ID
  DO
  BEGIN
    C2 = NULL;

    FOR
      SELECT M.OBJ_ID, M.DATE_IN, M.ORDER_NUM_IN, M.ORDER_DATE_IN, STC.VAL, M.NAME_IN
      FROM PERSON_MOVEMENTS M
      JOIN LISTVALS LV ON LV.LISTVAL_ID = M.REASON_IN AND LV."FILTER" SIMILAR TO '%ACCEPTED%'
      LEFT JOIN LISTVAL_TEXT(M.STAGE_ID) STC ON 1 = 1
      WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :V$SCHOOLAR_ID AND M.GROUP_TYPE_ID = 9 AND M.DATE_IN >= :I$FROM AND M.DATE_IN <= :I$TO
      ORDER BY 2
      INTO :V$MOVEMENT_ID, :C1, :C3, C4, :C8, :C9
    DO
    BEGIN

      IF(C2 IS NULL) THEN
      BEGIN
        SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$SCHOOLAR_ID, 49) INTO :C2;
        SELECT V FROM VAL_GET(:V$SCHOOLAR_ID, 1581) INTO :C31;
        SELECT D FROM VAL_GET(:V$SCHOOLAR_ID, 1582) INTO :C41;
        SELECT V FROM VAL_GET(:V$SCHOOLAR_ID, 78) INTO :C5;
        SELECT V FROM VAL_GET(:V$SCHOOLAR_ID, 104) INTO :C6;
        SELECT V FROM VAL_GET(:V$SCHOOLAR_ID, 1554) INTO :C7;
      END

      SUSPEND;

    END
  END

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DOU_VERIFY_ALL (
    I$OBJ_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    LINK_ID BIGINT,
    OBJECT_ID BIGINT,
    NAME_TASK VARCHAR(1000),
    ERROR_NAME VARCHAR(1000),
    PARAMS_NAME VARCHAR(1000),
    ERROR_TEXT VARCHAR(1000),
    ERROR_TYPE SMALLINT)
AS
BEGIN
    FOR
        SELECT LINK_ID,
               OBJECT_ID,
               NAME_TASK,
               ERROR_NAME,
               PARAMS_NAME,
               ERROR_TEXT,
               ERROR_TYPE
        FROM DOU_VERIFY_BUILDING(:I$OBJ_ID, :I$USER_ID)
        INTO :LINK_ID,
             :OBJECT_ID,
             :NAME_TASK,
             :ERROR_NAME,
             :PARAMS_NAME,
             :ERROR_TEXT,
             :ERROR_TYPE
    DO
    BEGIN
        SUSPEND;
    END

    FOR
        SELECT LINK_ID,
               OBJECT_ID,
               NAME_TASK,
               ERROR_NAME,
               PARAMS_NAME,
               ERROR_TEXT,
               ERROR_TYPE
        FROM DOU_VERIFY_CLASS(:I$OBJ_ID)
        INTO :LINK_ID,
             :OBJECT_ID,
             :NAME_TASK,
             :ERROR_NAME,
             :PARAMS_NAME,
             :ERROR_TEXT,
             :ERROR_TYPE
    DO
    BEGIN
        SUSPEND;
    END

    FOR
        SELECT LINK_ID,
               OBJECT_ID,
               NAME_TASK,
               ERROR_NAME,
               PARAMS_NAME,
               ERROR_TEXT,
               ERROR_TYPE
        FROM DOU_VERIFY_DOCS(:I$OBJ_ID)
        INTO :LINK_ID,
             :OBJECT_ID,
             :NAME_TASK,
             :ERROR_NAME,
             :PARAMS_NAME,
             :ERROR_TEXT,
             :ERROR_TYPE
    DO
    BEGIN
        SUSPEND;
    END

    FOR
        SELECT LINK_ID,
               OBJECT_ID,
               NAME_TASK,
               ERROR_NAME,
               PARAMS_NAME,
               ERROR_TEXT,
               ERROR_TYPE
        FROM VERIFY_POST(:I$OBJ_ID)
        INTO :LINK_ID,
             :OBJECT_ID,
             :NAME_TASK,
             :ERROR_NAME,
             :PARAMS_NAME,
             :ERROR_TEXT,
             :ERROR_TYPE
    DO
    BEGIN
        SUSPEND;
    END

    FOR
        SELECT LINK_ID,
               OBJECT_ID,
               NAME_TASK,
               ERROR_NAME,
               PARAMS_NAME,
               ERROR_TEXT,
               ERROR_TYPE
        FROM DOU_VERIFY_PUPIL(:I$OBJ_ID)
        INTO :LINK_ID,
             :OBJECT_ID,
             :NAME_TASK,
             :ERROR_NAME,
             :PARAMS_NAME,
             :ERROR_TEXT,
             :ERROR_TYPE
    DO
    BEGIN
        SUSPEND;
    END

    FOR
        SELECT LINK_ID,
               OBJECT_ID,
               NAME_TASK,
               ERROR_NAME,
               PARAMS_NAME,
               ERROR_TEXT,
               ERROR_TYPE
        FROM DOU_VERIFY_WORKERS(:I$OBJ_ID)
        INTO :LINK_ID,
             :OBJECT_ID,
             :NAME_TASK,
             :ERROR_NAME,
             :PARAMS_NAME,
             :ERROR_TEXT,
             :ERROR_TYPE
    DO
    BEGIN
        SUSPEND;
    END

/*   FOR
        SELECT LINK_ID,
               SCHOOLAR_ID,
               NAME_TASK,
               PARAMS_NAME,
               LOCATION || ', ' || PUPIL || ', ' || ERROR_TEXT,
               ERROR_TYPE
        FROM VERIFY_MOVEMENT(:I$OBJ_ID)
        INTO :LINK_ID,
             :OBJECT_ID,
             :NAME_TASK,
             :PARAMS_NAME,
             :ERROR_TEXT,
             :ERROR_TYPE
    DO
    BEGIN
        SUSPEND;
    END*/
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DOU_VERIFY_BUILDING (
    I$OBJ_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    LINK_ID BIGINT,
    OBJECT_ID BIGINT,
    NAME_TASK VARCHAR(1000),
    ERROR_NAME VARCHAR(1000),
    PARAMS_NAME VARCHAR(1000),
    ERROR_TEXT VARCHAR(1000),
    ERROR_TYPE SMALLINT)
AS
declare variable V$BLOB_ID bigint;
declare variable V$TEMP integer;
declare variable V$VALS varchar(1000);
declare variable V$TVALS varchar(1000);
declare variable V$TVALS2 varchar(1000);
declare variable LANG_CODE varchar(2);
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :LANG_CODE;

    NAME_TASK = 'Образовательное учреждение, здания, помещения';
    ERROR_TYPE = 1;

    SELECT FIRST 1 L2.OBJ_ID, L2.LINK_ID
    FROM LINKS L2
    WHERE L2.OBJ_ID = :I$OBJ_ID
    AND L2.OBJ_TYPE_ID = 2
    AND L2.DATE_DEL IS NULL
    INTO :OBJECT_ID, :LINK_ID;

 V$VALS = NULL;
    SELECT V
    FROM VAL_GET(:OBJECT_ID, 8)
    INTO :V$VALS;

    IF (V$VALS = '') THEN
    BEGIN
        ERROR_TEXT = 'Поле «Организационно-правовая форма» должно быть заполнено!';
        ERROR_NAME = :ERROR_TEXT;
        PARAMS_NAME = 'Организационно-правовая форма';
        ERROR_TYPE = 3;
        SUSPEND;
    END

    V$VALS = NULL;
    SELECT V
    FROM VAL_GET(:OBJECT_ID, 14)
    INTO :V$VALS;

    IF (V$VALS = '') THEN
    BEGIN
        ERROR_TEXT = 'Поле «Общая площадь территории» должно быть заполнено!';
        ERROR_NAME = :ERROR_TEXT;
        PARAMS_NAME = 'Общая площадь территории';
        ERROR_TYPE = 3;
        SUSPEND;
    END

    V$VALS = NULL;
    SELECT V
    FROM VAL_GET(:OBJECT_ID, 29)
    INTO :V$VALS;

    IF (V$VALS = '') THEN
    BEGIN
        ERROR_TEXT = 'Поле «Телефон приёмной» должно быть заполнено!';
        ERROR_NAME = :ERROR_TEXT;
        PARAMS_NAME = 'Телефон приёмной';
        ERROR_TYPE = 3;
        SUSPEND;
    END

    V$VALS = NULL;
    SELECT V
    FROM VAL_GET(:OBJECT_ID, 35)
    INTO :V$VALS;

    IF (V$VALS = '') THEN
    BEGIN
        ERROR_TEXT = 'Поле «Электронная почта» должно быть заполнено!';
        ERROR_NAME = :ERROR_TEXT;
        PARAMS_NAME = 'Электронная почта';
        ERROR_TYPE = 3;
        SUSPEND;
    END

    V$VALS = NULL;
    SELECT V
    FROM VAL_GET(:OBJECT_ID, 36)
    INTO :V$VALS;

    IF (V$VALS = '') THEN
    BEGIN
        ERROR_TEXT = 'Поле «Адрес сайта» должно быть заполнено!';
        ERROR_NAME = :ERROR_TEXT;
        PARAMS_NAME = 'Адрес сайта';
        ERROR_TYPE = 3;
        SUSPEND;
    END

/*
    #566
    IF (EXISTS(
        SELECT FIRST 1 1

        FROM VALL VLL

        WHERE VLL.OBJ_ID = :OBJECT_ID
        AND VLL.PARAM_ID = 11
        AND VLL.IS_DEL = 0
        AND VLL.LISTVAL_ID = 947
    ) AND NOT EXISTS(
        SELECT FIRST 1 1
        FROM R_SPB_POST_DIRECTOR(:OBJECT_ID, :I$USER_ID)
        WHERE POST_ID IN (66, 3301)
    )) THEN
    BEGIN
        ERROR_TEXT = 'Ошибочная должность руководителя';
        ERROR_NAME = :ERROR_TEXT;
        PARAMS_NAME = 'Руководитель образовательного учреждения';
        ERROR_TYPE = 3;
        SUSPEND;
    END  */

    -- 1 --
    SELECT V
    FROM VAL_GET(:OBJECT_ID, 2)
    INTO :V$VALS;

    V$TVALS = REPLACE(TRIM(V$VALS), '  ', ' ');
    WHILE(V$TVALS <> V$VALS) DO
    BEGIN
        V$TVALS2 = V$TVALS;
        V$TVALS = REPLACE(TRIM(V$TVALS), '  ', ' ');
        IF (V$TVALS2 = V$TVALS) THEN
        BEGIN
            BREAK;
        END
    END

    IF (V$TVALS <> V$VALS) THEN
    BEGIN
        SELECT BLOB_ID
        FROM VAL_ADD(2, :OBJECT_ID, :V$TVALS)
        INTO :V$BLOB_ID;
    
        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:OBJECT_ID)
        INTO :V$TVALS;

        ERROR_TEXT = 'Поле «Краткое наименование ОООД» объекта «' || V$TVALS || '» исправлено.';
        ERROR_NAME = 'Поле «Краткое наименование ОООД» объекта исправлено.';
        PARAMS_NAME = 'Краткое наименование ОООД';
        ERROR_TYPE = 1;
        SUSPEND;
    END
    IF (V$TVALS = '') THEN
    BEGIN
        ERROR_TEXT = 'Поле «Краткое наименование ОООД» должно быть заполнено!';
        ERROR_NAME = :ERROR_TEXT;
        PARAMS_NAME = 'Краткое наименование ОООД';
        ERROR_TYPE = 3;
        SUSPEND;
    END
    -- 2 --
    V$VALS = NULL;
    SELECT V
    FROM VAL_GET(:OBJECT_ID, 5)
    INTO :V$VALS;
    V$TVALS = REPLACE(TRIM(V$VALS), '  ', ' ');
    WHILE(V$TVALS <> V$VALS) DO
    BEGIN
        V$TVALS2 = V$TVALS;
        V$TVALS = REPLACE(TRIM(V$TVALS), '  ', ' ');
        IF (V$TVALS2 = V$TVALS) THEN
        BEGIN
            BREAK;
        END
    END

    IF (V$TVALS <> V$VALS) THEN
    BEGIN
        SELECT BLOB_ID
        FROM VAL_ADD(5, :OBJECT_ID, :V$TVALS)
        INTO :V$BLOB_ID;
    
        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:OBJECT_ID)
        INTO :V$TVALS;

        ERROR_TEXT = 'Поле «Полное наименование ОООД» объекта «' || V$TVALS || '» исправлено.';
        ERROR_NAME = 'Поле «Полное наименование ОООД» объекта исправлено.';
        PARAMS_NAME = 'Полное наименование ОООД';
        ERROR_TYPE = 1;
        SUSPEND;
    END
    IF (V$TVALS = '') THEN
    BEGIN
        ERROR_TEXT = 'Поле «Полное наименование ОООД» должно быть заполнено!';
        ERROR_NAME = :ERROR_TEXT;
        PARAMS_NAME = 'Полное наименование ОООД';
        ERROR_TYPE = 3;
        SUSPEND;
    END
    -- 3 --
    V$VALS = NULL;
    SELECT V
    FROM VAL_GET(:OBJECT_ID, 999)
    INTO :V$VALS;
    V$TVALS = REPLACE(TRIM(V$VALS), '  ', ' ');
    WHILE(V$TVALS <> V$VALS) DO
    BEGIN
        V$TVALS2 = V$TVALS;
        V$TVALS = REPLACE(TRIM(V$TVALS), '  ', ' ');
        IF (V$TVALS2 = V$TVALS) THEN
        BEGIN
            BREAK;
        END
    END

    IF (V$VALS <> V$TVALS) THEN
    BEGIN
        SELECT BLOB_ID
        FROM VAL_ADD(999, :OBJECT_ID, :V$TVALS)
        INTO :V$BLOB_ID;

        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:OBJECT_ID)
        INTO :V$TVALS;

        ERROR_TEXT = 'Поле «Сокращённое наименование ОООД по Уставу» объекта «' || V$TVALS || '» исправлено.';
        ERROR_NAME = 'Поле «Сокращённое наименование ОООД по Уставу» объекта исправлено.';
        PARAMS_NAME = 'Сокращённое наименование ОООД по Уставу';
        ERROR_TYPE = 1;
        SUSPEND;
    END
    IF (V$TVALS = '') THEN
    BEGIN
        ERROR_TEXT = 'Поле «Сокращённое наименование ОООД по Уставу» должно быть заполнено!';
        ERROR_NAME = :ERROR_TEXT;
        PARAMS_NAME = 'Сокращённое наименование ОООД по Уставу';
        ERROR_TYPE = 3;
        SUSPEND;
    END
    -- 4 --
    V$VALS = NULL;
    SELECT V
    FROM VAL_GET(:OBJECT_ID, 6)
    INTO :V$VALS;
    V$TVALS = REPLACE(TRIM(V$VALS), '  ', ' ');
    WHILE(V$TVALS <> V$VALS) DO
    BEGIN
        V$TVALS2 = V$TVALS;
        V$TVALS = REPLACE(TRIM(V$TVALS), '  ', ' ');
        IF (V$TVALS2 = V$TVALS) THEN
        BEGIN
            BREAK;
        END
    END

    IF (V$VALS <> V$TVALS) THEN
    BEGIN
        SELECT BLOB_ID
        FROM VAL_ADD(6, :OBJECT_ID, :V$TVALS)
        INTO :V$BLOB_ID;

        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:OBJECT_ID)
        INTO :V$TVALS;

        ERROR_TEXT = 'Поле «Подчинение» объекта «' || V$TVALS || '» исправлено.';
        ERROR_NAME = 'Поле «Подчинение» объекта исправлено.';
        PARAMS_NAME = 'Подчинение';
        ERROR_TYPE = 1;
        SUSPEND;
    END
    IF (V$TVALS NOT LIKE 'Комитет по образованию Санкт-Петербурга')  THEN
    BEGIN
        IF (NOT EXISTS(
            SELECT FIRST 1 1
            FROM VALL VLL
            WHERE VLL.PARAM_ID = 8
            AND VLL.IS_DEL = 0
            AND VLL.LISTVAL_ID IN (1734, 1735)
            AND VLL.OBJ_ID = :OBJECT_ID
        )) THEN
        BEGIN
            IF (V$TVALS = '') THEN
            BEGIN
                ERROR_TEXT = 'Поле «Подчинение» должно быть заполнено!';
                ERROR_NAME = :ERROR_TEXT;
                PARAMS_NAME = 'Подчинение';
                ERROR_TYPE = 3;
                SUSPEND;
            END
            ELSE
            BEGIN
            ERROR_TEXT = 'Значение в поле «Подчинение» не соответствует стандартному "Комитет по образованию Санкт-Петербурга"';
            ERROR_NAME = :ERROR_TEXT;
            PARAMS_NAME = 'Подчинение';
            ERROR_TYPE = 2;
            SUSPEND;
        END
    END
    END

    -- 5 --
    V$VALS = NULL;
    SELECT V
    FROM VAL_GET(:OBJECT_ID, 7)
    INTO :V$VALS;
    V$TVALS = REPLACE(TRIM(V$VALS), '  ', ' ');
    WHILE(V$TVALS <> V$VALS) DO
    BEGIN
        V$TVALS2 = V$TVALS;
        V$TVALS = REPLACE(TRIM(V$TVALS), '  ', ' ');
        IF (V$TVALS2 = V$TVALS) THEN
        BEGIN
            BREAK;
        END
    END

    IF (V$VALS <> V$TVALS) THEN
    BEGIN
        SELECT BLOB_ID
        FROM VAL_ADD(7, :OBJECT_ID, :V$TVALS)
        INTO :V$BLOB_ID;

        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:OBJECT_ID)
        INTO :V$TVALS;

        ERROR_TEXT = 'Поле «Вышестоящий орган» объекта «' || V$TVALS || '» исправлено.';
        ERROR_NAME = 'Поле «Вышестоящий орган» исправлено.';
        PARAMS_NAME = 'Вышестоящий орган';
        ERROR_TYPE = 1;
        SUSPEND;
    END
  IF (NOT EXISTS(
        SELECT FIRST 1 1
        FROM VALL VLL
        WHERE VLL.PARAM_ID = 8
        AND VLL.IS_DEL = 0
        AND VLL.LISTVAL_ID IN (1734, 1735)
        AND VLL.OBJ_ID = :OBJECT_ID
    )) THEN
    BEGIN
        IF (V$TVALS = '') THEN
        BEGIN
            ERROR_TEXT = 'Поле «Вышестоящий орган» должно быть заполнено!';
            ERROR_NAME = :ERROR_TEXT;
            PARAMS_NAME = 'Вышестоящий орган';
            ERROR_TYPE = 3;
            SUSPEND;
        END
        ELSE
        BEGIN
            IF (NOT EXISTS(
                SELECT FIRST 1 1
        FROM VALS VS
        INNER JOIN LISTVALS LV ON LV.LIST_ID = 168
          AND (SELECT VAL FROM RES_GET(LV.RES_ID, :LANG_CODE)) = VS.VAL
        WHERE VS.IS_DEL = 0
          AND VS.PARAM_ID = 7
          AND VS.OBJ_ID = :OBJECT_ID
    )) THEN
        BEGIN
            ERROR_TEXT = 'Значение не соответствует рекомендуемому (не выбрано из списка значений)';
            ERROR_NAME = :ERROR_TEXT;
            PARAMS_NAME = 'Вышестоящий орган';
            ERROR_TYPE = 2;
            SUSPEND;
        END
    END
    END
    -- 6 --
    V$TEMP = NULL;

    SELECT VI.VAL
    FROM VALI VI
    WHERE VI.PARAM_ID = 17
    AND VI.IS_DEL = 0
    AND VI.OBJ_ID = :OBJECT_ID
    INTO :V$TEMP;

    IF (:V$TEMP = 0) THEN
    BEGIN
        UPDATE VALI VI
        SET VI.IS_DEL = 1
        WHERE VI.PARAM_ID = 17
        AND VI.OBJ_ID = :OBJECT_ID
        AND VI.IS_DEL = 0;
        ERROR_TEXT = 'Номер ОООД не может содержать значение "0". Поле было очищено';
        ERROR_NAME = :ERROR_TEXT;
        PARAMS_NAME = 'Номер ОООД';
        ERROR_TYPE = 1;
        SUSPEND;
    END

    -- 7 --
    IF (:V$TEMP > 0) THEN
    BEGIN
        SELECT COUNT(VS.VAL)
        FROM VALS VS
        WHERE VS.PARAM_ID = 5
        AND VS.IS_DEL = 0
        AND VS.OBJ_ID = :OBJECT_ID
        AND VS.VAL LIKE '%' || :V$TEMP || '%'
        INTO :V$TEMP;

        IF (:V$TEMP = 0) THEN
        BEGIN
            ERROR_TEXT = 'Номер ОООД не содержится в полном наименовании ОУ!';
            ERROR_NAME = :ERROR_TEXT;
            PARAMS_NAME = 'Полное наименование ОООД';
            ERROR_TYPE = 2;
            SUSPEND;
        END
    END

    -- 8 --
    V$TEMP = NULL;
    SELECT COUNT(VLL.LISTVAL_ID)
    FROM VALL VLL
    WHERE VLL.PARAM_ID IN (10, 11)
    AND VLL.IS_DEL = 0
    AND VLL.OBJ_ID = :OBJECT_ID
    INTO :V$TEMP;
    IF (:V$TEMP < 2) THEN
    BEGIN
        ERROR_TEXT = 'Поля «Тип ОООД» и «Вид ОООД» должны быть заполнены';
        ERROR_NAME = :ERROR_TEXT;
        PARAMS_NAME = 'Тип ОООД, Вид ОООД';
        ERROR_TYPE = 3;
        SUSPEND;
    END

    -- 11 --
    V$TEMP = NULL;
    SELECT COUNT(VS.VAL)
    FROM VALS VS
    WHERE VS.PARAM_ID = 28
    AND VS.IS_DEL = 0
    AND VS.OBJ_ID = :OBJECT_ID
    AND TRIM(VS.VAL) > ''
    INTO :V$TEMP;

    IF (:V$TEMP = 0) THEN
    BEGIN
        ERROR_TEXT = 'Поле «Телефон руководителя» должно быть заполнено!';
        ERROR_NAME = :ERROR_TEXT;
        PARAMS_NAME = 'Телефон руководителя';
        ERROR_TYPE = 3;
        SUSPEND;
    END
    ELSE
    BEGIN
        SELECT COUNT(VS.VAL)
        FROM VALS VS
        WHERE VS.IS_DEL = 0
        AND VS.PARAM_ID = 28
        AND VS.OBJ_ID = :OBJECT_ID
        AND VS.VAL SIMILAR TO '[0-9]{1}\-[0-9]{3}\-[0-9]{2,3}\-[0-9]{2}\-[0-9]{2}' ESCAPE '\'
        INTO :V$TEMP;

        IF (:V$TEMP = 0) THEN
        BEGIN
            ERROR_TEXT = 'Поле «Телефон руководителя» заполнено некорректно (не соответствует маске ввода)';
            ERROR_NAME = :ERROR_TEXT;
            PARAMS_NAME = 'Телефон руководителя';
            ERROR_TYPE = 2;
            SUSPEND;
        END
    END

    -- 9 --
/*    V$TEMP = NULL;
    SELECT V
    FROM VAL_GET(:OBJECT_ID, 2167, 0, :I$USER_ID)
    INTO :V$TEMP;

    IF ((V$TEMP IS NULL) OR (:V$TEMP < 0)) THEN
    BEGIN
        ERROR_TEXT = 'Поле «Проектная мощность (чел.)» должно быть заполнено';
        ERROR_NAME = :ERROR_TEXT;
        PARAMS_NAME = 'Проектная мощность (чел.)';
        ERROR_TYPE = 3;
        SUSPEND;
    END*/

    -- 10 --
    SELECT TRIM(V)
    FROM VAL_GET(:OBJECT_ID, 27)
    INTO :V$VALS;

    IF (V$VALS <> '') THEN
    BEGIN
        V$VALS = NULL;
        SELECT FIRST 1 TRIM(VA.REGION)
        FROM VALA VA
        WHERE VA.PARAM_ID = 27
        AND VA.OBJ_ID = :OBJECT_ID
        AND VA.IS_DEL = 0
        INTO :V$VALS;

        IF (V$VALS IS NULL) THEN
        BEGIN
            V$VALS = '';
        END

        IF (V$VALS = '') THEN
        BEGIN
            ERROR_TEXT = 'Значение поля «Регион» в юридическом адресе ОООД не может быть пустым!';
            ERROR_NAME = :ERROR_TEXT;
            PARAMS_NAME = 'Юридический адрес';
            ERROR_TYPE = 3;
        END
        ELSE IF (:V$VALS != 'Санкт-Петербург г') THEN
        BEGIN
            ERROR_TEXT = 'Поле «Регион» в юридическом адресе ОООД ="' || :V$VALS || '", Вы уверены?';
            ERROR_NAME = 'Поле «Регион» в юридическом адресе ОООД <> "Санкт-Петербург г", Вы уверены?';
            PARAMS_NAME = 'Юридический адрес';
            ERROR_TYPE = 2;
            SUSPEND;
        END
        ELSE
        BEGIN
            SELECT COUNT(VA.DISTRICT)
            FROM VALA VA
            WHERE VA.PARAM_ID = 27
            AND VA.OBJ_ID = :OBJECT_ID
            AND VA.IS_DEL = 0
            AND VA.DISTRICT > ''
            INTO :V$TEMP;
    
            IF (:V$TEMP > 0) THEN
            BEGIN
                UPDATE VALA VA
                SET VA.DISTRICT = NULL
                WHERE VA.PARAM_ID = 27
                AND VA.OBJ_ID = :OBJECT_ID;
                ERROR_TEXT = 'Поле «Район» в юридическом адресе должно быть пустым. Поле было очищено.';
                ERROR_NAME = :ERROR_TEXT;
                PARAMS_NAME = 'Юридический адрес';
                ERROR_TYPE = 1;
                SUSPEND;
            END
        END
        SELECT FIRST 1 VLL.LISTVAL_ID
        FROM VALL VLL
        WHERE VLL.PARAM_ID = 8
        AND VLL.IS_DEL = 0
        AND VLL.OBJ_ID = :OBJECT_ID
        INTO :V$TEMP;
    
        IF (:V$TEMP != 1734) THEN
        BEGIN
            UPDATE VALA VA
            SET VA.FLAT = ''
            WHERE VA.PARAM_ID = 27
            AND VA.OBJ_ID = :OBJECT_ID
            AND VA.IS_DEL = 0
            AND VA.FLAT > '';
    
            IF (ROW_COUNT > 0) THEN
            BEGIN
                ERROR_TEXT = 'Поле «Квартира» в юридическом адресе государственного ОООД должно быть пустым. Поле было очищено.';
                ERROR_NAME = :ERROR_TEXT;
                PARAMS_NAME = 'Юридический адрес';
                ERROR_TYPE = 1;
                SUSPEND;
            END
        END

        IF (EXISTS(
            SELECT FIRST 1 1
        FROM VALA VA
        WHERE VA.PARAM_ID = 27
        AND VA.OBJ_ID = :OBJECT_ID
        AND VA.IS_DEL = 0
        AND ((VA.STREET = '') OR (VA.STREET IS NULL))
        )) THEN
    
        BEGIN
            ERROR_TEXT = 'Значение поля «Улица» в юридическом адресе ОООД не может быть пустым!';
            ERROR_NAME = :ERROR_TEXT;
            PARAMS_NAME = 'Юридический адрес';
            ERROR_TYPE = 3;
            SUSPEND;
        END

        IF (EXISTS(
            SELECT FIRST 1 1
        FROM VALA VA
        WHERE VA.PARAM_ID = 27
        AND VA.OBJ_ID = :OBJECT_ID
        AND VA.IS_DEL = 0
        AND ((VA.POST_INDEX = '') OR (VA.POST_INDEX IS NULL))
        )) THEN
    
        BEGIN
            ERROR_TEXT = 'Значение поля «Индекс» в юридическом адресе ОООД не может быть пустым!';
            ERROR_NAME = :ERROR_TEXT;
            PARAMS_NAME = 'Юридический адрес';
            ERROR_TYPE = 3;
            SUSPEND;
        END
    END
    ELSE
    BEGIN
        ERROR_TEXT = 'Поле «Юридический адрес» должно быть заполнено!';
        ERROR_NAME = :ERROR_TEXT;
        PARAMS_NAME = 'Юридический адрес';
        ERROR_TYPE = 3;
        SUSPEND;
    END
    -- 12 --

    V$TEMP = NULL;
    SELECT COUNT(VS.VAL)
    FROM VALS VS
    WHERE VS.PARAM_ID = 29
    AND VS.IS_DEL = 0
    AND VS.OBJ_ID = :OBJECT_ID
    AND VS.VAL > ''
    INTO :V$TEMP;

    IF (:V$TEMP > 0) THEN
    BEGIN
        SELECT COUNT(VS.VAL)
        FROM VALS VS
        WHERE VS.IS_DEL = 0
        AND VS.PARAM_ID = 29
        AND VS.OBJ_ID = :OBJECT_ID
        AND VS.VAL SIMILAR TO '[0-9]{1}\-[0-9]{3}\-[0-9]{2,3}\-[0-9]{2}\-[0-9]{2}' ESCAPE '\'
        INTO :V$TEMP;

        IF (:V$TEMP = 0) THEN
        BEGIN
            ERROR_TEXT = 'Поле «Телефон приемной» заполнено некорректно (не соответствует маске ввода!';
            ERROR_NAME = :ERROR_TEXT;
            PARAMS_NAME = 'Телефон приемной';
            ERROR_TYPE = 2;
            SUSPEND;
        END
    END

    -- 13 --
    V$TEMP = NULL;
    SELECT COUNT(VS.VAL)
    FROM VALS VS
    WHERE VS.PARAM_ID = 30
    AND VS.IS_DEL = 0
    AND VS.OBJ_ID = :OBJECT_ID
    AND VS.VAL > ''
    INTO :V$TEMP;

    IF (:V$TEMP > 0) THEN
    BEGIN
        SELECT COUNT(VS.VAL)
        FROM VALS VS
        WHERE VS.IS_DEL = 0
        AND VS.PARAM_ID = 30
        AND VS.OBJ_ID = :OBJECT_ID
        AND VS.VAL SIMILAR TO '[0-9]{1}\-[0-9]{3}\-[0-9]{2,3}\-[0-9]{2}\-[0-9]{2}' ESCAPE '\'
        INTO :V$TEMP;

        IF (:V$TEMP = 0) THEN
        BEGIN
            ERROR_TEXT = 'Поле «Факс» заполнено некорректно (не соответствует маске ввода)';
            ERROR_NAME = :ERROR_TEXT;
            PARAMS_NAME = 'Факс';
            ERROR_TYPE = 2;
            SUSPEND;
        END
    END

    -- 14 --
    V$TEMP = NULL;
    SELECT COUNT(VS.VAL)
    FROM VALS VS
    WHERE VS.PARAM_ID = 31
    AND VS.IS_DEL = 0
    AND VS.OBJ_ID = :OBJECT_ID
    AND VS.VAL > ''
    INTO :V$TEMP;

    IF (:V$TEMP > 0) THEN
    BEGIN
        SELECT COUNT(VS.VAL)
        FROM VALS VS
        WHERE VS.IS_DEL = 0
        AND VS.PARAM_ID = 31
        AND VS.OBJ_ID = :OBJECT_ID
        AND VS.VAL SIMILAR TO '[0-9]{1}\-[0-9]{3}\-[0-9]{2,3}\-[0-9]{2}\-[0-9]{2}' ESCAPE '\'
        INTO :V$TEMP;

        IF (:V$TEMP = 0) THEN
        BEGIN
            ERROR_TEXT = 'Поле «Телефон главного бухгалтера» заполнено некорректно (не соответствует маске ввода)';
            ERROR_NAME = :ERROR_TEXT;
            PARAMS_NAME = 'Телефон главного бухгалтера';
            ERROR_TYPE = 2;
            SUSPEND;
        END
    END

    -- 15 --
    V$VALS = NULL;
    SELECT V
    FROM VAL_GET(:OBJECT_ID, 35)
    INTO :V$VALS;
    V$TVALS = REPLACE(TRIM(V$VALS), '  ', ' ');
    WHILE(V$TVALS <> V$VALS) DO
    BEGIN
        V$TVALS2 = V$TVALS;
        V$TVALS = REPLACE(TRIM(V$TVALS), '  ', ' ');
        IF (V$TVALS2 = V$TVALS) THEN
        BEGIN
            BREAK;
        END
    END

    IF (V$TVALS <> V$VALS) THEN
    BEGIN
        SELECT BLOB_ID
        FROM VAL_ADD(35, :OBJECT_ID, :V$TVALS)
        INTO :V$BLOB_ID;
    
        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:OBJECT_ID)
        INTO :V$TVALS;

        ERROR_TEXT = 'Поле «Электронная почта» объекта «' || V$TVALS || '» исправлено.';
        ERROR_NAME = 'Поле «Электронная почта» исправлено.';
        PARAMS_NAME = 'Электронная почта';
        ERROR_TYPE = 1;
        SUSPEND;
    END

    V$TEMP = NULL;
    SELECT COUNT(VS.VAL)
    FROM VALS VS
    WHERE VS.PARAM_ID = 35
    AND VS.IS_DEL = 0
    AND VS.OBJ_ID = :OBJECT_ID
    AND VS.VAL > ''
    INTO :V$TEMP;

    IF (:V$TEMP > 0) THEN
    BEGIN
        SELECT COUNT(VS.VAL)
        FROM VALS VS
        WHERE VS.IS_DEL = 0
        AND VS.PARAM_ID = 35
        AND VS.OBJ_ID = :OBJECT_ID
        AND VS.VAL SIMILAR TO '[0-9a-zа-я_.\-]{2,}@[0-9a-zа-я_.\-]{2,}' ESCAPE '\'
        INTO :V$TEMP;
        IF (:V$TEMP = 0) THEN
        BEGIN
            ERROR_TEXT = '«Электронная почта» заполнено некорректно (не соответствует маске ввода)';
            ERROR_NAME = :ERROR_TEXT;
            PARAMS_NAME = 'Электронная почта';
            ERROR_TYPE = 2;
            SUSPEND;
        END
    END


    IF (NOT EXISTS(
        SELECT FIRST 1 1
        FROM R_SPB_POST_DIRECTOR(:I$OBJ_ID, :I$USER_ID)
    )) THEN
    BEGIN
        ERROR_TEXT = 'Не указан действующий (исполняющий обязанности) руководитель ОООД';
        ERROR_NAME = :ERROR_TEXT;
        PARAMS_NAME = 'Руководитель образовательного учереждения';
        ERROR_TYPE = 3;
        SUSPEND;
    END

    -- 17 --
    V$TEMP = NULL;
    SELECT COUNT(L51.OBJ_ID)
    FROM LINKS L51
    WHERE L51.PARENT_ID = :OBJECT_ID
    AND L51.OBJ_TYPE_ID = 51
    AND L51.DATE_DEL IS NULL
    INTO :V$TEMP;

    IF ((V$TEMP = 0) AND EXISTS(
        SELECT FIRST 1 1
        FROM LINKS L51
        WHERE L51.PARENT_ID = :OBJECT_ID
        AND L51.OBJ_TYPE_ID = 51
        AND L51.DATE_DEL IS NULL
    )) THEN
    BEGIN
        ERROR_TEXT = 'Не указаны предметы, изучаемые углубленно';
        ERROR_NAME = :ERROR_TEXT;
        PARAMS_NAME = 'Предмет';
        ERROR_TYPE = 2;
        SUSPEND;
    END
    IF (:V$TEMP > 10) THEN
    BEGIN
        ERROR_TEXT = 'Список предметов, изучаемых углубленно, не может содержать более 10 предметов';
        ERROR_NAME = :ERROR_TEXT;
        PARAMS_NAME = 'Предмет';
        ERROR_TYPE = 2;
        SUSPEND;
    END
    -- 18 --
    IF (EXISTS(
        SELECT FIRST 1 1

        FROM VALL VLL

        WHERE VLL.OBJ_ID = :OBJECT_ID
        AND VLL.PARAM_ID = 11
        AND VLL.IS_DEL = 0
        AND VLL.LISTVAL_ID = 947
    ) AND NOT EXISTS(
        SELECT FIRST 1 1

        FROM LINKS L73

        JOIN LINKS L16
        ON L16.PARENT_ID = L73.OBJ_ID
        AND L16.OBJ_TYPE_ID = 16
        AND L16.DATE_DEL IS NULL

        WHERE L73.DATE_DEL IS NULL
        AND L73.PARENT_ID = :OBJECT_ID
        AND L73.OBJ_TYPE_ID = 73

    )) THEN
    BEGIN
        ERROR_TEXT = 'Должно быть введено хотя бы одно здание образовательного учреждения';
        ERROR_NAME = :ERROR_TEXT;
        PARAMS_NAME = 'Здание';
        ERROR_TYPE = 3;
        SUSPEND;
    END
    -- 19 --
    FOR
        SELECT L16.OBJ_ID, L16.LINK_ID
        FROM LINKS L73
        INNER JOIN LINKS L16 ON L16.PARENT_ID = L73.OBJ_ID
        WHERE L73.DATE_DEL IS NULL
        AND L73.PARENT_ID = :OBJECT_ID
        AND L73.OBJ_TYPE_ID = 73
        AND L16.OBJ_TYPE_ID = 16
        AND L16.DATE_DEL IS NULL
        INTO :OBJECT_ID, :LINK_ID
    DO
    BEGIN
        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:OBJECT_ID)
        INTO :V$VALS;

  ERROR_NAME = V$VALS;
        ERROR_TYPE = 5;

        FOR
            SELECT R.VAL
            FROM PARAMS P
            
            JOIN LPARAMS LP
            ON LP.PARAM_ID = P.PARAM_ID
            AND LP.IS_DEL = 0
            AND LP.LEVEL_ID = 15
            
            JOIN RES R
            ON R.RES_ID = P.RES_ID
            AND R.LANG_CODE = 'RU'
            
            LEFT JOIN VAL_GET(:OBJECT_ID, P.PARAM_ID) VL
            ON 1=1

            WHERE P.TYPE_ID = 16
            AND P.IS_DEL = 0                  -- , 497, 498, 499, 500, 501, 502, 503, 509, 510, 511, 512, 522, 521
            AND P.PARAM_ID IN (504, 505, 542, 508, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 520)
            AND VL.V = ''

            INTO :V$TVALS
        DO
        BEGIN
            ERROR_TEXT = 'Не заполнено поле «' || :V$TVALS || '» для здания «' || :V$VALS || '»';
            PARAMS_NAME = V$TVALS;
            SUSPEND;
        END
        --

        V$TVALS = NULL;
        SELECT V
        FROM VAL_GET(:OBJECT_ID, 485)
        INTO :V$TVALS;

        IF (V$TVALS = '') THEN
        BEGIN
            ERROR_TEXT = 'Поле «Назначение здания» для здания «' || :V$VALS || '» должно быть заполнено!';
            ERROR_NAME = 'Поле «Назначение здания» для здания должно быть заполнено!';
            PARAMS_NAME = 'Назначение здания';
            ERROR_TYPE = 3;
            SUSPEND;
        END

        -- Вынесены в новую сущность
        /*V$TVALS = NULL;
        SELECT V
        FROM VAL_GET(:OBJECT_ID, 1441)
        INTO :V$TVALS;

        IF (V$TVALS = '') THEN
        BEGIN
            ERROR_TEXT = 'Поле «Наличие стадиона с естественным покрытием» для здания «' || :V$VALS || '» должно быть заполнено!';
            ERROR_NAME = 'Поле «Наличие стадиона с естественным покрытием» для здания должно быть заполнено!';
            PARAMS_NAME = 'Наличие стадиона с естественным покрытием';
            ERROR_TYPE = 3;
            SUSPEND;
        END

        V$TVALS = NULL;
        SELECT V
        FROM VAL_GET(:OBJECT_ID, 1443)
        INTO :V$TVALS;

        IF (V$TVALS = '') THEN
        BEGIN
            ERROR_TEXT = 'Поле «Наличие стадиона с искусственным покрытием» для здания «' || :V$VALS || '» должно быть заполнено!';
            ERROR_NAME = 'Поле «Наличие стадиона с искусственным покрытием» для здания должно быть заполнено!';
            PARAMS_NAME = 'Наличие стадиона с искусственным покрытием';
            ERROR_TYPE = 3;
            SUSPEND;
        END

        V$TVALS = NULL;
        SELECT V
        FROM VAL_GET(:OBJECT_ID, 1446)
        INTO :V$TVALS;

        IF (V$TVALS = '') THEN
        BEGIN
            ERROR_TEXT = 'Поле «Наличие спортплощадки» для здания «' || :V$VALS || '» должно быть заполнено!';
            ERROR_NAME = 'Поле «Наличие спортплощадки» для здания должно быть заполнено!';
            PARAMS_NAME = 'Наличие спортплощадки';
            ERROR_TYPE = 3;
            SUSPEND;
        END*/

        IF (:V$VALS = '<  ...  >') THEN
        BEGIN
            ERROR_TEXT = 'Не указано название здания, обозначенного как "<  ...  >"';
            ERROR_NAME = 'Поле «Название» для здания должно быть заполнено';
            PARAMS_NAME = '«Название»';
            ERROR_TYPE = 3;
            SUSPEND;
        END
        ELSE
        BEGIN
            IF (NOT EXISTS(
                SELECT FIRST 1 1
                FROM VALA V
                WHERE V.PARAM_ID = 420
                AND V.OBJ_ID = :OBJECT_ID
                AND V.IS_DEL = 0
            )) THEN
            BEGIN
                ERROR_TEXT = 'Не указан адрес для здания «' || :V$VALS || '»!';
                ERROR_NAME = 'Не указан адрес для здания!';
                PARAMS_NAME = 'Адрес';
                ERROR_TYPE = 3;
                SUSPEND;
            END
            ELSE
            BEGIN
                IF (NOT EXISTS(
                    SELECT FIRST 1 1
                    FROM VALA VA
                    WHERE VA.PARAM_ID = 420
                    AND VA.OBJ_ID = :OBJECT_ID
                    AND VA.IS_DEL = 0
                    AND TRIM(COALESCE(VA.STREET,'')) != ''
                )) THEN
                BEGIN
                    ERROR_TEXT = 'Значение поля «Улица» в адресе здания «' || :V$VALS || '» не может быть пустым!';
                    ERROR_NAME = 'Значение поля «Улица» в адресе здания не может быть пустым!';
                    PARAMS_NAME = 'Адрес';
                    ERROR_TYPE = 3;
                    SUSPEND;
                END

                IF (NOT EXISTS(
                    SELECT FIRST 1 1
                    FROM VALA VA
                    WHERE VA.PARAM_ID = 420
                    AND VA.OBJ_ID = :OBJECT_ID
                    AND VA.IS_DEL = 0
                    AND TRIM(COALESCE(VA.POST_INDEX,'')) != ''
                )) THEN
                BEGIN
                    ERROR_TEXT = 'Значение поля «Индекс» в адресе здания «' || :V$VALS || '» не может быть пустым!';
                    ERROR_NAME = 'Значение поля «Индекс» в адресе здания не может быть пустым!';
                    PARAMS_NAME = 'Адрес';
                    ERROR_TYPE = 3;
                    SUSPEND;
                END
            END
        END
    END

    IF (EXISTS(SELECT FIRST 1 1 FROM LINKS WHERE PARENT_ID = :I$OBJ_ID AND DATE_DEL IS NULL AND OBJ_TYPE_ID = 51)) THEN
    BEGIN
        SELECT I
        FROM VAL_GET(:I$OBJ_ID, 10)
        INTO :V$BLOB_ID;
        IF (V$BLOB_ID NOT IN(964,2212)) THEN
        BEGIN
            ERROR_TEXT = 'Указаны предметы изучаемые углубленно, что не соответствует виду ОООД. Вы уверены?';
            ERROR_NAME = :ERROR_TEXT;
            PARAMS_NAME = 'Углубленное изучение предметов';
            ERROR_TYPE = 2;
            LINK_ID = NULL;
            OBJECT_ID = I$OBJ_ID;
            SUSPEND;
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DOU_VERIFY_CLASS (
    I$OBJ_ID BIGINT)
RETURNS (
    LINK_ID BIGINT,
    OBJECT_ID BIGINT,
    NAME_TASK VARCHAR(1000),
    ERROR_NAME VARCHAR(1000),
    PARAMS_NAME VARCHAR(1000),
    ERROR_TEXT VARCHAR(1000),
    ERROR_TYPE SMALLINT)
AS
declare variable I integer;
declare variable V varchar(1000);
declare variable SCHOOL_OBJECT_ID bigint;
declare variable SCHOOL_LINK_ID bigint;
declare variable V$EMPTY_RECORD_COUNT integer;
declare variable V$LISTVAL_ID bigint;
declare variable L7_OBJ_ID bigint;
declare variable L8_OBJ_ID bigint;
declare variable L9_OBJ_ID bigint;
BEGIN
    NAME_TASK = 'Учебные коллективы';
    ERROR_TYPE = 1;

    SELECT FIRST 1 L2.OBJ_ID, L2.LINK_ID
    FROM LINKS L2
    WHERE L2.OBJ_ID = :I$OBJ_ID
    AND L2.OBJ_TYPE_ID = 2
    AND L2.DATE_DEL IS NULL
    INTO :SCHOOL_OBJECT_ID, :SCHOOL_LINK_ID;

    -- 23 --
    V$EMPTY_RECORD_COUNT = 0;
    FOR
        SELECT L7.OBJ_ID, L7.LINK_ID
        FROM LINKS L7

        LEFT JOIN VALL V43
        ON V43.OBJ_ID = L7.OBJ_ID
        AND V43.PARAM_ID = 43
        AND V43.IS_DEL = 0

        WHERE L7.PARENT_ID = :I$OBJ_ID
        AND L7.OBJ_TYPE_ID = 7
        AND L7.DATE_DEL IS NULL
        AND V43.LISTVAL_ID IS NULL
        INTO :OBJECT_ID, :LINK_ID
    DO
    BEGIN
        SELECT COUNT(*)
        FROM LINKS L8

        WHERE L8.PARENT_ID = :OBJECT_ID
        AND L8.OBJ_TYPE_ID = 8
        AND L8.DATE_DEL IS NULL
        INTO :I;

        IF (:I = 0) THEN
        BEGIN
            UPDATE LINKS L
            SET L.DATE_DEL = CURRENT_TIMESTAMP
            WHERE L.OBJ_ID = :OBJECT_ID
            AND L.OBJ_TYPE_ID = 7
            AND DATE_DEL IS NULL;

            V$EMPTY_RECORD_COUNT = V$EMPTY_RECORD_COUNT + 1;
        END
        ELSE
        BEGIN
            ERROR_TEXT = 'Обнаружена неназванная ступень обучения, обозначенная как "< ... >"';
            ERROR_NAME = :ERROR_TEXT;
            PARAMS_NAME = 'Ступень обучения';
            ERROR_TYPE = 3;
            SUSPEND;
        END
    END
    IF (V$EMPTY_RECORD_COUNT > 0) THEN
    BEGIN
        OBJECT_ID = SCHOOL_OBJECT_ID;
        LINK_ID = SCHOOL_LINK_ID;

        ERROR_TEXT = 'Список ступеней обучения был очищен от пустых записей';
        ERROR_NAME = :ERROR_TEXT;
        PARAMS_NAME = 'Ступень обучения';
        ERROR_TYPE = 1;
        SUSPEND;
    END

    -- 24 --
    V$EMPTY_RECORD_COUNT = 0;
    FOR
        SELECT L8.OBJ_ID, L8.LINK_ID
        FROM LINKS L7

        JOIN LINKS L8
        ON L8.PARENT_ID = L7.OBJ_ID

        LEFT JOIN VALL V49
        ON V49.OBJ_ID = L8.OBJ_ID
        AND V49.PARAM_ID = 49
        AND V49.IS_DEL = 0

        WHERE L7.PARENT_ID = :I$OBJ_ID
        AND L7.OBJ_TYPE_ID = 7
        AND L7.DATE_DEL IS NULL
        AND L8.OBJ_TYPE_ID = 8
        AND L8.DATE_DEL IS NULL
        AND V49.LISTVAL_ID IS NULL
        INTO :OBJECT_ID, :LINK_ID
    DO
    BEGIN
        SELECT COUNT(*)
        FROM LINKS L9
        WHERE L9.PARENT_ID = :OBJECT_ID
        AND L9.OBJ_TYPE_ID = 9
        AND L9.DATE_DEL IS NULL
        INTO :I;

        IF (:I = 0) THEN
        BEGIN
            UPDATE LINKS L
            SET L.DATE_DEL = CURRENT_TIMESTAMP
            WHERE L.OBJ_ID = :OBJECT_ID
            AND L.OBJ_TYPE_ID = 8
            AND DATE_DEL IS NULL;

            V$EMPTY_RECORD_COUNT = V$EMPTY_RECORD_COUNT + 1;
        END
        ELSE
        BEGIN
            ERROR_TEXT = 'Обнаружен неназванный этап обучения, обозначенный как "< ... >"';
            ERROR_NAME = :ERROR_TEXT;
            PARAMS_NAME = 'Список этапов';
            ERROR_TYPE = 3;
            SUSPEND;
        END
    END
    IF (V$EMPTY_RECORD_COUNT > 0) THEN
    BEGIN
        OBJECT_ID = SCHOOL_OBJECT_ID;
        LINK_ID = SCHOOL_LINK_ID;

        OBJECT_ID = SCHOOL_OBJECT_ID;
        LINK_ID = SCHOOL_LINK_ID;

        ERROR_TEXT = 'Список этапов обучения был очищен от пустых записей.';
        ERROR_NAME = :ERROR_TEXT;
        PARAMS_NAME = 'Список этапов';
        ERROR_TYPE = 1;
        SUSPEND;
    END

    -- 25 --

    FOR
        SELECT L8.OBJ_ID, L8.LINK_ID
        FROM LINKS L7

        JOIN LINKS L8
        ON L8.PARENT_ID = L7.OBJ_ID

        WHERE L7.PARENT_ID = :I$OBJ_ID
        AND L7.OBJ_TYPE_ID = 7
        AND L7.DATE_DEL IS NULL
        AND L8.OBJ_TYPE_ID = 8
        AND L8.DATE_DEL IS NULL
        INTO :OBJECT_ID, :LINK_ID
    DO
    BEGIN
        FOR
            SELECT VS.VAL
            FROM LINKS L9
            JOIN VALS VS ON VS.OBJ_ID = L9.OBJ_ID
            WHERE L9.OBJ_TYPE_ID = 9
            AND L9.DATE_DEL IS NULL
            AND L9.PARENT_ID = :OBJECT_ID
            AND VS.PARAM_ID = 54
            AND VS.IS_DEL = 0
            GROUP BY VS.VAL
            HAVING COUNT(VS.VAL) > 1
            INTO :V
        DO
        BEGIN
            SELECT CAST(LV.COST AS INTEGER) || ' ' || :V
            FROM VALL V

            JOIN LISTVALS LV
            ON LV.LISTVAL_ID = V.LISTVAL_ID

            WHERE V.OBJ_ID = :OBJECT_ID
            AND V.PARAM_ID = 49
            AND V.IS_DEL = 0
            INTO :V;

            ERROR_TEXT = 'Существуют два учебных коллектива с кодом ' || :V;
            ERROR_NAME = 'Существуют два учебных коллектива с одинаковым кодом';
            PARAMS_NAME = 'Учебный коллектив';
            ERROR_TYPE = 3;
            SUSPEND;
        END
    END

    --#1546
    FOR
        SELECT L7.OBJ_ID, L8.OBJ_ID
        FROM LINKS L7

        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL

        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
        LEFT JOIN VALS VS ON VS.OBJ_ID = L9.OBJ_ID AND VS.PARAM_ID = 54 AND VS.IS_DEL = 0

        WHERE L7.PARENT_ID = :I$OBJ_ID
        AND L7.OBJ_TYPE_ID = 7
        AND L7.DATE_DEL IS NULL
        AND COALESCE(VS.VAL, '') = ''

        INTO :L7_OBJ_ID, :L8_OBJ_ID
    DO
    BEGIN
        SELECT 'Уровень: ' || CAPTION FROM OBJECT_CAPTION_GET(:L7_OBJ_ID)
        INTO :V;

        SELECT :V || '; этап: ' || CAPTION FROM OBJECT_CAPTION_GET(:L8_OBJ_ID)
        INTO :V;

        ERROR_TEXT = TRIM(:V) || ' - обнаружен неназванный учебный коллектив ';
        ERROR_NAME = 'Не указано наименование учебного коллектива';
        PARAMS_NAME = 'Наименование';
        ERROR_TYPE = 3;
        SUSPEND;
    END

    FOR
        SELECT L7.OBJ_ID, L8.OBJ_ID, L9.OBJ_ID
        FROM LINKS L7

        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL

        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
        LEFT JOIN VALL VL ON VL.OBJ_ID = L9.OBJ_ID AND VL.PARAM_ID = 1558 AND VL.IS_DEL = 0

        WHERE L7.PARENT_ID = :I$OBJ_ID
        AND L7.OBJ_TYPE_ID = 7
        AND L7.DATE_DEL IS NULL
        AND VL.LISTVAL_ID IS NULL

        INTO :L7_OBJ_ID, :L8_OBJ_ID, :L9_OBJ_ID
    DO
    BEGIN
        SELECT 'Уровень: ' || CAPTION FROM OBJECT_CAPTION_GET(:L7_OBJ_ID)
        INTO :V;

        SELECT :V || '; этап: ' || CAPTION FROM OBJECT_CAPTION_GET(:L8_OBJ_ID)
        INTO :V;

        SELECT :V || '; коллектив: ' || CAPTION FROM OBJECT_CAPTION_GET(:L9_OBJ_ID)
        INTO :V;

        ERROR_TEXT = TRIM(:V) || ' - не указан режим работы ';
        ERROR_NAME = 'Не указан режим работы';
        PARAMS_NAME = 'Режим работы';
        ERROR_TYPE = 3;
        SUSPEND;
    END

    -- 25.2 --
    FOR
        SELECT L9.OBJ_ID, L9.LINK_ID
        FROM LINKS L7

        JOIN LINKS L8
        ON L8.PARENT_ID = L7.OBJ_ID

        JOIN LINKS L9
        ON L9.PARENT_ID = L8.OBJ_ID

        LEFT JOIN LINKS L165
        ON L165.PARENT_ID = L9.OBJ_ID
        AND L165.OBJ_TYPE_ID = 165
        AND L165.DATE_DEL IS NULL

        LEFT JOIN VALR V1556
        ON V1556.OBJ_ID = L165.OBJ_ID
        AND V1556.PARAM_ID = 1556
        AND V1556.IS_DEL = 0

        WHERE L7.PARENT_ID = :I$OBJ_ID
        AND L7.OBJ_TYPE_ID = 7
        AND L7.DATE_DEL IS NULL
        AND L8.OBJ_TYPE_ID = 8
        AND L8.DATE_DEL IS NULL
        AND L9.OBJ_TYPE_ID = 9
        AND L9.DATE_DEL IS NULL
        AND V1556.VAL IS NULL
        INTO :OBJECT_ID, :LINK_ID
    DO
    BEGIN
        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:OBJECT_ID)
        INTO :V;

        ERROR_TEXT = 'Для "' || :V || '" не указан классный руководитель (воспитатель)';
        ERROR_NAME = 'Не указан классный руководитель (воспитатель)';
        PARAMS_NAME = 'Учебный коллектив';
        ERROR_TYPE = 2;
        SUSPEND;
    END
    -- #1096
    FOR
        SELECT L9.OBJ_ID, L9.LINK_ID,
               V1549.LISTVAL_ID, V1655.LISTVAL_ID
        FROM LINKS L7

        JOIN LINKS L8
        ON L8.PARENT_ID = L7.OBJ_ID

        JOIN LINKS L9
        ON L9.PARENT_ID = L8.OBJ_ID

        LEFT JOIN VALL V1549
        ON V1549.OBJ_ID = L9.OBJ_ID
        AND V1549.PARAM_ID = 1549
        AND V1549.IS_DEL = 0

        LEFT JOIN VALL V1655
        ON V1655.OBJ_ID = L9.OBJ_ID
        AND V1655.PARAM_ID = 1655
        AND V1655.IS_DEL = 0

        WHERE L7.PARENT_ID = :I$OBJ_ID
        AND L7.OBJ_TYPE_ID = 7
        AND L7.DATE_DEL IS NULL
        AND L8.OBJ_TYPE_ID = 8
        AND L8.DATE_DEL IS NULL
        AND L9.OBJ_TYPE_ID = 9
        AND L9.DATE_DEL IS NULL
        INTO :OBJECT_ID, :LINK_ID,
             :I, :V$LISTVAL_ID
    DO
    BEGIN
        IF (:I IS NULL) THEN
        BEGIN
            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:OBJECT_ID)
            INTO :V;
    
            ERROR_TEXT = 'Для "' || :V || '" не указан Вид группы';
            ERROR_NAME = 'Не указан Вид группы';
            PARAMS_NAME = 'Вид группы';
            ERROR_TYPE = 3;
            SUSPEND;
        END

        IF (:I IN (3266, 3267) AND :V$LISTVAL_ID IS NULL) THEN
        BEGIN
            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:OBJECT_ID)
            INTO :V;
    
            ERROR_TEXT = 'Для "' || :V || '" не указана Направленность';
            ERROR_NAME = 'Не указана Направленность';
            PARAMS_NAME = 'Направленность';
            ERROR_TYPE = 3;
            SUSPEND;
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DOU_VERIFY_DOCS (
    I$OBJ_ID BIGINT)
RETURNS (
    LINK_ID BIGINT,
    OBJECT_ID BIGINT,
    NAME_TASK VARCHAR(1000),
    ERROR_NAME VARCHAR(1000),
    PARAMS_NAME VARCHAR(1000),
    ERROR_TEXT VARCHAR(1000),
    ERROR_TYPE SMALLINT)
AS
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$LINK_ID BIGINT;
DECLARE VARIABLE V$TEMP BIGINT;
DECLARE VARIABLE V$VALS VARCHAR(1000);
DECLARE VARIABLE V$EMPTY_RECORD_COUNT INTEGER;
DECLARE VARIABLE V$TVALS VARCHAR(1000);
DECLARE VARIABLE V$TVALS2 VARCHAR(1000);
DECLARE VARIABLE V$BLOB_ID BIGINT;
DECLARE VARIABLE V$C0 BIGINT;
DECLARE VARIABLE V$C INTEGER;
DECLARE VARIABLE V$C1 INTEGER;
DECLARE VARIABLE V$C2 INTEGER;
DECLARE VARIABLE V$S VARCHAR(1000);
DECLARE VARIABLE V$S1 VARCHAR(1000);
DECLARE VARIABLE V$S2 VARCHAR(1000);
DECLARE VARIABLE V$S3 VARCHAR(1000);
BEGIN
    NAME_TASK = 'Документы образовательного учреждения';
    ERROR_TYPE = 1;

    SELECT FIRST 1 L2.OBJ_ID, L2.LINK_ID
    FROM LINKS L2
    WHERE L2.OBJ_ID = :I$OBJ_ID
    AND L2.OBJ_TYPE_ID = 2
    AND L2.DATE_DEL IS NULL
    INTO :OBJECT_ID, :LINK_ID;

    -- 20 --
    SELECT COUNT(VS.VAL)
    FROM VALS VS
    WHERE VS.IS_DEL = 0
    AND VS.OBJ_ID = :OBJECT_ID
    AND VS.PARAM_ID = 33
    INTO :V$TEMP;

    IF (:V$TEMP = 0) THEN
    BEGIN
        ERROR_TEXT = 'Не заполнено поле «ИНН» образовательного учреждения!';
        ERROR_NAME = :ERROR_TEXT;
        PARAMS_NAME = 'ИНН';
        ERROR_TYPE = 3;
        SUSPEND;
    END
    ELSE
    BEGIN
        SELECT COUNT(VS.VAL)
        FROM VALS VS
        WHERE VS.IS_DEL = 0
          AND VS.OBJ_ID = :OBJECT_ID
          AND VS.PARAM_ID = 33
          AND VS.VAL SIMILAR TO '[0-9]{10}'
        INTO :V$TEMP;

        IF (:V$TEMP = 0) THEN
        BEGIN
            ERROR_TEXT = 'Поле «ИНН» образовательного учреждения заполнено некорректно (не соответствует маске ввода)';
            ERROR_NAME = :ERROR_TEXT;
            PARAMS_NAME = 'ИНН';
            ERROR_TYPE = 3;
            SUSPEND;
        END
    END

    -- 21 --
    SELECT COUNT(VS.VAL)
    FROM VALS VS
    WHERE VS.IS_DEL = 0
      AND VS.PARAM_ID = 9
      AND VS.OBJ_ID = :OBJECT_ID
    INTO :V$TEMP;

    IF (:V$TEMP = 0) THEN
    BEGIN
        ERROR_TEXT = 'Не заполнено поле «ОГРН» образовательного учреждения';
        ERROR_NAME = :ERROR_TEXT;
        PARAMS_NAME = 'ОГРН';
        ERROR_TYPE = 3;
        SUSPEND;
    END
    ELSE
    BEGIN
        SELECT COUNT(VS.VAL)
        FROM VALS VS
        WHERE VS.IS_DEL = 0
        AND VS.OBJ_ID = :OBJECT_ID
        AND VS.PARAM_ID = 9
        AND VS.VAL SIMILAR TO '[0-9]{13}'
        INTO :V$TEMP;

        IF (:V$TEMP = 0) THEN
        BEGIN
            ERROR_TEXT = 'Поле «ОГРН» образовательного учреждения заполнено некорректно (не соответствует маске ввода)';
            ERROR_NAME = :ERROR_TEXT;
            PARAMS_NAME = 'ОГРН';
            ERROR_TYPE = 3;
            SUSPEND;
        END
    END

    -- 22 --
    V$EMPTY_RECORD_COUNT = 0;
    FOR
        SELECT L5.OBJ_ID,
               L5.LINK_ID
        FROM LINKS L5
        WHERE L5.DATE_DEL IS NULL
        AND L5.OBJ_TYPE_ID = 5
        AND L5.PARENT_ID = :OBJECT_ID
        INTO :V$OBJ_ID,
             :V$LINK_ID
    DO
    BEGIN
        SELECT COUNT(VS.VAL)
        FROM VALS VS
        WHERE VS.PARAM_ID IN (24, 25, 26)
        AND VS.OBJ_ID = :V$OBJ_ID
        AND VS.IS_DEL = 0
        AND TRIM(VS.VAL) <> ''
        INTO :V$TEMP;

        IF (:V$TEMP = 0) THEN
        BEGIN
            UPDATE LINKS L
            SET L.DATE_DEL = CURRENT_TIMESTAMP
            WHERE L.LINK_ID = :V$LINK_ID
            AND L.OBJ_TYPE_ID = 5
            AND L.DATE_DEL IS NULL;

            V$EMPTY_RECORD_COUNT = V$EMPTY_RECORD_COUNT + 1;
        END
        ELSE
        BEGIN
            -- 22.2 --
            SELECT TRIM(V)
            FROM VAL_GET(:V$OBJ_ID, 24)
            INTO :V$VALS;
            V$TVALS = REPLACE(TRIM(V$VALS), '  ', ' ');
            WHILE(V$TVALS <> V$VALS) DO
            BEGIN
                V$TVALS2 = V$TVALS;
                V$TVALS = REPLACE(TRIM(V$TVALS), '  ', ' ');
                IF (V$TVALS2 = V$TVALS) THEN
                BEGIN
                    BREAK;
                END
            END

            IF (V$TVALS <> V$VALS) THEN
            BEGIN
                SELECT BLOB_ID
                FROM VAL_ADD(24, :V$OBJ_ID, :V$TVALS)
                INTO :V$BLOB_ID;
    
                SELECT CAPTION
                FROM OBJECT_CAPTION_GET(:V$OBJ_ID)
                INTO :V$TVALS;

                ERROR_TEXT = 'Поле «Название или ФИО учредителя» объекта «' || V$TVALS || '» исправлено.';
                ERROR_NAME = 'Поле «Название или ФИО учредителя» исправлено.';
                PARAMS_NAME = 'Название или ФИО учредителя';
                ERROR_TYPE = 1;
                SUSPEND;
            END
            -- 22.3 --
            SELECT TRIM(V)
            FROM VAL_GET(:V$OBJ_ID, 25)
            INTO :V$VALS;
            V$TVALS = REPLACE(TRIM(V$VALS), '  ', ' ');
            WHILE(V$TVALS <> V$VALS) DO
            BEGIN
                V$TVALS2 = V$TVALS;
                V$TVALS = REPLACE(TRIM(V$TVALS), '  ', ' ');
                IF (V$TVALS2 = V$TVALS) THEN
                BEGIN
                    BREAK;
                END
            END

            IF (V$TVALS <> V$VALS) THEN
            BEGIN
                SELECT BLOB_ID
                FROM VAL_ADD(25, :V$OBJ_ID, :V$TVALS)
                INTO :V$BLOB_ID;
    
                SELECT CAPTION
                FROM OBJECT_CAPTION_GET(:V$OBJ_ID)
                INTO :V$TVALS;

                ERROR_TEXT = 'Поле «Адрес» объекта «' || V$TVALS || '» исправлено.';
                ERROR_NAME = 'Поле «Адрес» исправлено.';
                PARAMS_NAME = 'Адрес';
                ERROR_TYPE = 1;
                SUSPEND;
            END
            -- 22.4
            SELECT COUNT(VS.VAL)
            FROM VALS VS
            WHERE VS.PARAM_ID = 26
            AND VS.OBJ_ID = :V$OBJ_ID
            AND VS.IS_DEL = 0
            AND TRIM(VS.VAL) <> ''
            INTO :V$TEMP;

            IF (:V$TEMP = 1) THEN
            BEGIN
                SELECT COUNT(VS.VAL)
                FROM VALS VS
                WHERE VS.IS_DEL = 0
                AND VS.PARAM_ID = 26
                AND VS.OBJ_ID = :V$OBJ_ID
                AND VS.VAL SIMILAR TO '[0-9]{1}\-[0-9]{3}\-[0-9]{2,3}\-[0-9]{2}\-[0-9]{2}' ESCAPE '\'
                INTO :V$TEMP;

                IF (:V$TEMP = 0) THEN
                BEGIN
                    SELECT CAPTION
                    FROM OBJECT_CAPTION_GET(:V$OBJ_ID)
                    INTO :V$VALS;
                    ERROR_TEXT = 'Поле «Телефон» для учредителя ' || :V$VALS || 'заполнено некорректно (не соответствует маске ввода)';
                    ERROR_NAME = 'Поле «Телефон» для учредителя заполнено некорректно (не соответствует маске ввода)';
                    PARAMS_NAME = 'Телефон учредителя';
                    ERROR_TYPE = 2;
                    SUSPEND;
                END
            END
        END
    END
    IF (V$EMPTY_RECORD_COUNT > 0) THEN
    BEGIN
        ERROR_TEXT = 'Список учредителей был очищен от пустых записей.';
        ERROR_NAME = :ERROR_TEXT;
        PARAMS_NAME = 'Список учредителей';
        ERROR_TYPE = 1;
        SUSPEND;
    END
    IF (NOT EXISTS(SELECT FIRST 1 1 FROM LINKS WHERE DATE_DEL IS NULL AND OBJ_TYPE_ID = 5 AND PARENT_ID = :OBJECT_ID)) THEN
    BEGIN
        ERROR_TEXT = 'Не указаны учредители образовательного учреждения.';
        ERROR_NAME = :ERROR_TEXT;
        PARAMS_NAME = 'Список учредителей';
        ERROR_TYPE = 2;
        SUSPEND;
    END

    --
    FOR
        SELECT R.VAL
        FROM PARAMS P
            
        JOIN LPARAMS LP
        ON LP.PARAM_ID = P.PARAM_ID
        AND LP.IS_DEL = 0 
        AND LP.LEVEL_ID in (159, /* Apostrof */ 355)
            
        JOIN RES R
        ON R.RES_ID = P.RES_ID
        AND R.LANG_CODE = 'RU'
            
        LEFT JOIN VAL_GET(:OBJECT_ID, P.PARAM_ID) VL
        ON 1=1

        WHERE P.TYPE_ID = 2
        AND P.IS_DEL = 0
        AND P.PARAM_ID IN (16, 18, 19, 20, 21, 22, 34, 470, 13, 23, 397)
        AND VL.V = ''

        INTO :V$TVALS
        DO
        BEGIN
            ERROR_NAME = 'Реквизиты ОУ';
            ERROR_TEXT = 'Не заполнено поле «' || :V$TVALS || '» реквизита ОУ ';
            PARAMS_NAME = V$TVALS;
            ERROR_TYPE = 5;
            SUSPEND;
        END
    --

    V$EMPTY_RECORD_COUNT = 0;
    V$C = 0;
    V$C1 = 0;
    V$C2 = 0;
    SELECT I
        FROM VAL_GET(:OBJECT_ID, 11)
        INTO :V$C0;

    FOR
        SELECT L17.OBJ_ID,
               L17.LINK_ID
        FROM LINKS L17
        WHERE L17.PARENT_ID = :I$OBJ_ID
        AND L17.OBJ_TYPE_ID = 17
        AND L17.DATE_DEL IS NULL
        INTO :OBJECT_ID,
             :LINK_ID
    DO
    BEGIN
        SELECT TRIM(V)
        FROM VAL_GET(:OBJECT_ID, 596)
        INTO :V$VALS;

        SELECT I
        FROM VAL_GET(:OBJECT_ID, 471)
        INTO V$TEMP;

      /*  SELECT TRIM(V),I
        FROM VAL_GET(:OBJECT_ID, 597)
        INTO :V$TVALS, :V$BLOB_ID; */

        SELECT TRIM(V)
        FROM VAL_GET(:OBJECT_ID, 479)
        INTO :V$S;

        SELECT TRIM(V)
        FROM VAL_GET(:OBJECT_ID, 480)
        INTO :V$S1;

        SELECT TRIM(V)
        FROM VAL_GET(:OBJECT_ID, 482)
        INTO :V$S2;

        SELECT TRIM(V)
        FROM VAL_GET(:OBJECT_ID, 613)
        INTO :V$S3;

        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:OBJECT_ID)
        INTO :V$TVALS2;

        IF ((V$VALS = '') AND (V$TEMP = 0) AND (V$TVALS = '')) THEN
        BEGIN
            UPDATE LINKS L
            SET L.DATE_DEL = CURRENT_TIMESTAMP
            WHERE L.LINK_ID = :LINK_ID
            AND L.OBJ_TYPE_ID = 17
            AND L.DATE_DEL IS NULL;

            V$EMPTY_RECORD_COUNT = V$EMPTY_RECORD_COUNT + 1;
        END
        ELSE IF (V$TEMP = 0) THEN
        BEGIN
            ERROR_TEXT = 'Список документов содержит документ не имеющий типа (обозначен как "< ... >")';
            ERROR_NAME = :ERROR_TEXT;
            PARAMS_NAME = 'Документы';
            ERROR_TYPE = 3;
            SUSPEND;
        END
        ELSE
        BEGIN
            IF (V$VALS = '') THEN
            BEGIN
                ERROR_TEXT = 'Для документа «' || V$TVALS2 || '» не указано «Название»!';
                ERROR_NAME = 'Для документа не указано «Название»!';
                PARAMS_NAME = 'Документы';
                ERROR_TYPE = 2;
                SUSPEND;
            END
          /*  IF (V$TVALS = '') THEN
            BEGIN
                ERROR_TEXT = 'Для документа «' || V$TVALS2 || '» не загружен файл с образом документа';
                ERROR_NAME = 'Для документа не загружен файл с образом документа';
                PARAMS_NAME = 'Документы';
                ERROR_TYPE = 2;
                SUSPEND;
            END  */
            IF (EXISTS(SELECT FIRST 1 1 FROM VALD WHERE PARAM_ID = 483 AND OBJ_ID = :OBJECT_ID AND VAL < CURRENT_TIMESTAMP)) THEN
            BEGIN
                ERROR_TEXT = 'Дата окончания действия документа «' || V$TVALS2 || '» прошла. Необходимо изменить статус документа.';
                ERROR_NAME = 'Дата окончания действия документа прошла. Необходимо изменить статус документа.';
                PARAMS_NAME = 'Документы';
                ERROR_TYPE = 2;
                SUSPEND;
            END
            ERROR_TYPE = 5;
            IF (:V$VALS = '') THEN
            BEGIN
                ERROR_TEXT = 'Для документа «' || V$TVALS2 || '» не заполнено поле «Название»';
                ERROR_NAME = 'Для документа не заполнено поле «Название»';
                PARAMS_NAME = 'Название';
                SUSPEND;
            END
            IF (:V$S = '') THEN
            BEGIN
                ERROR_TEXT = 'Для документа «' || V$TVALS2 || '» не заполнено поле «Серия»';
                ERROR_NAME = 'Для документа не заполнено поле «Серия»';
                PARAMS_NAME = 'Серия';
                SUSPEND;
            END
            IF (:V$S1 = '') THEN
            BEGIN
                ERROR_TEXT = 'Для документа «' || V$TVALS2 || '» не заполнено поле «Номер»';
                ERROR_NAME = 'Для документа не заполнено поле «Номер»';
                PARAMS_NAME = 'Номер';
                SUSPEND;
            END
            IF (:V$S2 = '') THEN
            BEGIN
                ERROR_TEXT = 'Для документа «' || V$TVALS2 || '» не заполнено поле «Дата выдачи»';
                ERROR_NAME = 'Для документа не заполнено поле «Дата выдачи»';
                PARAMS_NAME = 'Дата выдачи';
                SUSPEND;
            END
            IF (:V$S3 = '') THEN
            BEGIN
                ERROR_TEXT = 'Для документа «' || V$TVALS2 || '» не заполнено поле «Статус документа»';
                ERROR_NAME = 'Для документа не заполнено поле «Статус документа»';
                PARAMS_NAME = 'Статус документа';
                SUSPEND;
            END
        END
        if (:V$TEMP = 1047) then V$C = :V$C + 1;
        if (:V$TEMP IN (1052, 18624)) then V$C1 = :V$C1 + 1;
        if (:V$TEMP = 1079) then V$C2 = :V$C2 + 1;
    END
    IF (V$EMPTY_RECORD_COUNT > 0) THEN
    BEGIN
        OBJECT_ID = NULL;
        ERROR_TEXT = 'Список документов был очищен от пустых записей';
        ERROR_NAME = :ERROR_TEXT;
        PARAMS_NAME = 'Тип документа ОУ';
        ERROR_TYPE = 1;
        SUSPEND;
    END

    IF (:V$C0 = 947) THEN
    BEGIN
        IF (V$C = 0) THEN
        BEGIN
            ERROR_TEXT = 'В списке документов отсутствует "Устав"';
            ERROR_NAME = :ERROR_TEXT;
            PARAMS_NAME = 'Тип документа ОУ';
            ERROR_TYPE = 3;
            SUSPEND;
        END
        IF (V$C1 = 0) THEN
        BEGIN
            ERROR_TEXT = 'В списке документов отсутствует "Лицензия"';
            ERROR_NAME = :ERROR_TEXT;
            PARAMS_NAME = 'Тип документа ОУ';
            ERROR_TYPE = 3;
            SUSPEND;
        END
        IF (V$C2 = 0) THEN
        BEGIN
            ERROR_TEXT = 'В списке документов отсутствует "Приложение для лицензии"';
            ERROR_NAME = :ERROR_TEXT;
            PARAMS_NAME = 'Тип документа ОУ';
            ERROR_TYPE = 3;
            SUSPEND;
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DOU_VERIFY_PUPIL (
    I$OBJ_ID BIGINT)
RETURNS (
    LINK_ID BIGINT,
    OBJECT_ID BIGINT,
    NAME_TASK VARCHAR(1000),
    ERROR_NAME VARCHAR(1000),
    PARAMS_NAME VARCHAR(1000),
    ERROR_TEXT VARCHAR(1000),
    ERROR_TYPE SMALLINT)
AS
declare variable OBJ_ID bigint;
declare variable V$OBJ_ID bigint;
declare variable V$EXT_OBJ_ID bigint;
declare variable I integer;
declare variable V$C integer;
declare variable CLASS varchar(1000);
declare variable FIO varchar(1000);
declare variable V varchar(4000);
declare variable V$FIO_P varchar(4000);
declare variable V$VALS varchar(4000);
declare variable V$Y1 smallint;
declare variable V$Y2 smallint;
declare variable V$DT1 date;
BEGIN
    NAME_TASK = 'Личные дела обучающихся, воспитанников ';
    ERROR_TYPE = 1;

    FOR
        SELECT L9.OBJ_ID, L10.OBJ_ID, L10.LINK_ID
        FROM LINKS L7
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
        JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        WHERE L7.PARENT_ID = :I$OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
        INTO :OBJ_ID, :OBJECT_ID, :LINK_ID
    DO
    BEGIN
        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:OBJ_ID)
        INTO :CLASS;

        SELECT C1
        FROM BUILD_REP_FIO(:OBJECT_ID, 55, 56, 57, 0)
        INTO FIO;

        -- 2 --
        SELECT COUNT(VLL.LISTVAL_ID)
        FROM VALL VLL
        WHERE VLL.PARAM_ID = 88 AND VLL.IS_DEL = 0 AND VLL.OBJ_ID = :OBJECT_ID
        INTO :I;
        IF (:I = 0) THEN
        BEGIN
            ERROR_TEXT = 'Поле «ПОЛ» для воспитанника «' || :FIO || '», «' || :CLASS || '» должно быть заполнено';
            ERROR_NAME = 'Поле «ПОЛ» для воспитанника должно быть заполнено';
            PARAMS_NAME = 'Пол';
            ERROR_TYPE = 3;
            SUSPEND;
        END
        -- 3 --
        SELECT COUNT(VD.VAL)
        FROM VALD VD
        WHERE VD.PARAM_ID = 89 AND VD.IS_DEL = 0 AND VD.OBJ_ID = :OBJECT_ID
        INTO :I;
        IF (:I = 0) THEN
        BEGIN
            ERROR_TEXT = 'Поле «Дата рождения» для воспитанника «' || :FIO || '», «' || :CLASS || '» должно быть заполнено';
            ERROR_NAME = 'Поле «Дата рождения» для воспитанника должно быть заполнено';
            PARAMS_NAME = 'Дата рождения';
            ERROR_TYPE = 3;
            SUSPEND;
        END
        -- 4 --
        SELECT COUNT(VLL.LISTVAL_ID)
        FROM VALL VLL
        WHERE VLL.PARAM_ID = 91 AND VLL.IS_DEL = 0 AND VLL.OBJ_ID = :OBJECT_ID
        INTO :I;
        IF (:I = 0) THEN
        BEGIN
            ERROR_TEXT = 'Поле «Гражданство» для воспитанника «' || :FIO || '», «' || :CLASS || '» должно быть заполнено';
            ERROR_NAME = 'Поле «Гражданство» для воспитанника должно быть заполнено';
            PARAMS_NAME = 'Гражданство';
            ERROR_TYPE = 3;
            SUSPEND;
        END
        -- 5 --
      /*  SELECT COUNT(VS.VAL)
        FROM VALS VS
        WHERE VS.PARAM_ID = 1343 AND VS.IS_DEL = 0 AND VS.OBJ_ID = :OBJECT_ID
        INTO :I;
        IF (:I = 0) THEN
        BEGIN
            ERROR_TEXT = 'Поле «Место рождения» для воспитанника «' || :FIO || '», «' || :CLASS || '» должно быть заполнено';
            ERROR_NAME = 'Поле «Место рождения» для воспитанника должно быть заполнено';
            PARAMS_NAME = 'Место рождения';
            ERROR_TYPE = 2;
            SUSPEND;
        END  */
        -- 6 --
        SELECT COUNT(VLL.LISTVAL_ID)
        FROM VALL VLL
        WHERE VLL.PARAM_ID = 127 AND VLL.IS_DEL = 0 AND VLL.OBJ_ID = :OBJECT_ID
        INTO :I;
        IF (:I = 0) THEN
        BEGIN
            ERROR_TEXT = 'Поле «Родной язык» для воспитанника «' || :FIO || '», «' || :CLASS || '» должно быть заполнено';
            ERROR_NAME = 'Поле «Родной язык» для воспитанника должно быть заполнено';
            PARAMS_NAME = 'Родной язык';
            ERROR_TYPE = 2;
            SUSPEND;
        END
        -- 7 --
        SELECT COUNT(VL.LISTVAL_ID)
        FROM VALL VL
        WHERE VL.PARAM_ID = 108 AND VL.IS_DEL = 0 AND VL.OBJ_ID = :OBJECT_ID
        INTO :I;
        IF (:I = 0) THEN
        BEGIN
            ERROR_TEXT = 'Поле «Регистрация» для воспитанника «' || :FIO || '», «' || :CLASS || '» должно быть заполнено';
            ERROR_NAME = 'Не заполнено поле «Регистрация»';
            PARAMS_NAME = 'Регистрация';
            ERROR_TYPE = 5;
            SUSPEND;
        END
        -- 8 --
        SELECT TRIM(V)
        FROM VAL_GET(:OBJECT_ID, 103)
        INTO :V$VALS;

        IF (V$VALS != '') THEN
        BEGIN
            V$VALS = NULL;
            SELECT FIRST 1 TRIM(VA.REGION)
            FROM VALA VA
            WHERE VA.PARAM_ID = 103 AND VA.OBJ_ID = :OBJECT_ID AND VA.IS_DEL = 0
            INTO :V$VALS;

            IF (V$VALS IS NULL) THEN
            BEGIN
                V$VALS = '';
            END

            IF (:V$VALS = 'Санкт-Петербург г') THEN
            BEGIN
                SELECT V FROM VAL_GET(:OBJECT_ID, 101)
                INTO :V$VALS;

                if (:V$VALS = '') then
                BEGIN
                    ERROR_TEXT = 'Поле «Район города» для воспитанника «' || :FIO || '», «' || :CLASS || '» должно быть заполнено';
                    ERROR_NAME = 'Не заполнено поле "Район города"';
                    PARAMS_NAME = 'Район города';
                    ERROR_TYPE = 5;
                    SUSPEND;
                END
            END
         END
         ELSE
         BEGIN
             ERROR_TEXT = 'Поле «Адрес фактического проживания» для воспитанника «' || :FIO || '», «' || :CLASS || '» должно быть заполнено';
             ERROR_NAME = 'Не заполнено поле «Адрес фактического проживания»';
             PARAMS_NAME = 'Адрес фактического проживания';
             ERROR_TYPE = 5;
            SUSPEND;
         END
        -- 9 --
         SELECT TRIM(V)
         FROM VAL_GET(:OBJECT_ID, 111)
         INTO :V$VALS;

         if (:V$VALS = '') then
         BEGIN
             ERROR_TEXT = 'Поле «Адрес регистрации» для воспитанника «' || :FIO || '», «' || :CLASS || '» должно быть заполнено';
             ERROR_NAME = 'Не заполнено поле «Адрес регистрации»';
             PARAMS_NAME = 'Адрес регистрации';
             ERROR_TYPE = 5;
            SUSPEND;
         END
        -- 10 --
         SELECT TRIM(V)
         FROM VAL_GET(:OBJECT_ID, 118)
         INTO :V$VALS;

         if (:V$VALS = '') then
         BEGIN
             ERROR_TEXT = 'Поле «Семья» для воспитанника «' || :FIO || '», «' || :CLASS || '» должно быть заполнено';
             ERROR_NAME = 'Не заполнено поле «Семья»';
             PARAMS_NAME = 'Семья';
             ERROR_TYPE = 5;
            SUSPEND;
         END

          SELECT TRIM(V)
         FROM VAL_GET(:OBJECT_ID, 119)
         INTO :V$VALS;

         if (:V$VALS = '') then
         BEGIN
             ERROR_TEXT = 'Поле «Количество детей в семье» для воспитанника «' || :FIO || '», «' || :CLASS || '» должно быть заполнено';
             ERROR_NAME = 'Не заполнено поле «Количество детей в семье»';
             PARAMS_NAME = 'Количество детей в семье';
             ERROR_TYPE = 5;
            SUSPEND;
         END

         SELECT TRIM(V)
         FROM VAL_GET(:OBJECT_ID, 1552)
         INTO :V$VALS;

         if ((:V$VALS = '') or (:V$VALS = '0%') ) then
         BEGIN
             ERROR_TEXT = 'Поле «Компенсация оплаты содержания» для воспитанника «' || :FIO || '», «' || :CLASS || '» должно быть заполнено';
             ERROR_NAME = 'Не заполнено поле «Компенсация оплаты содержания»';
             PARAMS_NAME = 'Компенсация оплаты содержания';
             ERROR_TYPE = 5;
            SUSPEND;
         END

         SELECT TRIM(V)
         FROM VAL_GET(:OBJECT_ID, 208)
         INTO :V$VALS;

         if (:V$VALS = '') then
         BEGIN
             ERROR_TEXT = 'Поле «Группа здоровья» для воспитанника «' || :FIO || '», «' || :CLASS || '» должно быть заполнено';
             ERROR_NAME = 'Не заполнено поле «Группа здоровья»';
             PARAMS_NAME = 'Группа здоровья';
             ERROR_TYPE = 5;
            SUSPEND;
         END

         SELECT TRIM(V)
         FROM VAL_GET(:OBJECT_ID, 78)
         INTO :V$VALS;

         IF (:V$VALS = '') THEN
         BEGIN
             ERROR_TEXT = 'Поле «Принят(а) из» для воспитанника «' || :FIO || '», «' || :CLASS || '» должно быть заполнено';
             ERROR_NAME = 'Не заполнено поле «Принят(а) из»';
             PARAMS_NAME = 'Принят(а) из';
             ERROR_TYPE = 5;
            SUSPEND;
         END
         -- Записи о приеме не могут не быть сформированы, два блока проверок удалены

         -- --
        -- 11 --
     /*   SELECT COUNT(L79.OBJ_ID)
        FROM LINKS L79
        WHERE L79.OBJ_TYPE_ID = 79
        AND L79.PARENT_ID = :OBJECT_ID
        AND L79.DATE_DEL IS NULL
        INTO :I;

        IF (:I = 0) THEN
        BEGIN
            ERROR_TEXT = 'Для воспитанника «' || :FIO || '», «' || :CLASS || '» не введены данные документа, удостоверяющего личность';
            ERROR_NAME = 'Для воспитанника не введены данные документа, удостоверяющего личность';
            PARAMS_NAME = 'Документ удостоверяющий личность';
            ERROR_TYPE = 2;
            SUSPEND;
        END
        -- 12 --
        SELECT COUNT(*)
        FROM VALS VLL
        WHERE VLL.OBJ_ID = :OBJECT_ID
        AND VLL.PARAM_ID = 1409
        AND VLL.IS_DEL = 0
        INTO :I;
        IF (:I = 0) THEN
        BEGIN
            ERROR_TEXT = 'Не заполнено поле СНИЛС для воспитанника «' || :FIO || '», «' || :CLASS || '»';
            ERROR_NAME = 'Не заполнено поле СНИЛС для воспитанника';
            PARAMS_NAME = 'Документ';
            ERROR_TYPE = 2;
            SUSPEND;
        END  */


        --7 --
        FOR
            SELECT L79.OBJ_ID,
                   (SELECT COUNT(VS.VAL)
                    FROM VALS VS
                    WHERE VS.PARAM_ID IN (442, 559, 562, 563)
                    AND VS.IS_DEL = 0
                    AND VS.OBJ_ID = L79.OBJ_ID
                   ) +
                   (SELECT COUNT(VLL.LISTVAL_ID)
                    FROM VALL VLL
                    WHERE VLL.PARAM_ID = 441
                    AND VLL.IS_DEL = 0
                    AND VLL.OBJ_ID = L79.OBJ_ID
                   ) +
                   (SELECT COUNT(VD.VAL)
                    FROM VALD VD
                    WHERE VD.PARAM_ID IN (560, 561)
                    AND VD.IS_DEL = 0
                    AND VD.OBJ_ID = L79.OBJ_ID
                   ) +
                   (SELECT COUNT(VB.VAL)
                    FROM VALB VB
                    WHERE VB.PARAM_ID = 576
                    AND VB.IS_DEL = 0
                    AND VB.OBJ_ID = L79.OBJ_ID
                   )
            FROM LINKS L79
            WHERE L79.OBJ_TYPE_ID = 79
            AND L79.PARENT_ID = :OBJECT_ID
            AND L79.DATE_DEL IS NULL
            INTO :OBJ_ID, :I
        DO
        BEGIN
            IF (:I = 0) THEN
            BEGIN
                UPDATE LINKS L
                SET L.DATE_DEL = CURRENT_TIMESTAMP
                WHERE L.OBJ_ID = :OBJ_ID
                AND L.OBJ_TYPE_ID = 79
                AND DATE_DEL IS NULL;
                ERROR_TEXT = 'Для воспитанника «' || :FIO || '», «' || :CLASS || '» удалены пустые записи в поле Документ удостоверяющий личность.';
                ERROR_NAME = 'Для воспитанника удалены пустые записи в поле Документ удостоверяющий личность.';
                PARAMS_NAME = 'Документ удостоверяющий личность';
                ERROR_TYPE = 1;
                SUSPEND;
            END
        END
        -- 9 --
     /*   FOR
            SELECT (SELECT COUNT(VS.VAL)
                    FROM VALS VS
                    WHERE VS.PARAM_ID = 442
                    AND VS.IS_DEL = 0
                    AND VS.OBJ_ID = L79.OBJ_ID)
            FROM LINKS L79
            WHERE L79.OBJ_TYPE_ID = 79
            AND L79.PARENT_ID = :OBJECT_ID
            AND L79.DATE_DEL IS NULL
            INTO :I
        DO
        BEGIN
            IF (:I = 0) THEN
            BEGIN
                ERROR_TEXT = 'Для воспитанника «' || :FIO || '», «' || :CLASS || '» не введены Серия документа, удостоверяющего личность';
                ERROR_NAME = 'Для воспитанника не введены Серия документа, удостоверяющего личность';
                PARAMS_NAME = 'Документ удостоверяющий личность';
                ERROR_TYPE = 2;
                SUSPEND;
            END
        END
        -- 10 --
        FOR
            SELECT (SELECT COUNT(VS.VAL)
                    FROM VALS VS
                    WHERE VS.PARAM_ID = 559
                    AND VS.IS_DEL = 0
                    AND VS.OBJ_ID = L79.OBJ_ID)
            FROM LINKS L79
            WHERE L79.OBJ_TYPE_ID = 79
            AND L79.PARENT_ID = :OBJECT_ID
            AND L79.DATE_DEL IS NULL
            INTO :I
        DO
        BEGIN
            IF (:I = 0) THEN
            BEGIN
                ERROR_TEXT = 'Для воспитанника «' || :FIO || '», «' || :CLASS || '» не введены Номер документа, удостоверяющего личность';
                ERROR_NAME = 'Для воспитанника не введены Номер документа, удостоверяющего личность';
                PARAMS_NAME = 'Документ удостоверяющий личность';
                ERROR_TYPE = 2;
                SUSPEND;
            END
        END   */
        -- 11 --
        FOR
            SELECT L12.OBJ_ID,
                   (SELECT COUNT(VS.VAL)
                    FROM VALS VS
                    WHERE VS.PARAM_ID IN (570, 571, 574, 575)
                    AND VS.IS_DEL = 0
                    AND VS.OBJ_ID = L12.OBJ_ID
                   ) +
                   (SELECT COUNT(VLL.LISTVAL_ID)
                    FROM VALL VLL
                    WHERE VLL.PARAM_ID = 51
                    AND VLL.IS_DEL = 0
                    AND VLL.OBJ_ID = L12.OBJ_ID
                   ) +
                   (SELECT COUNT(VD.VAL)
                    FROM VALD VD
                    WHERE VD.PARAM_ID IN (572, 573)
                    AND VD.IS_DEL = 0
                    AND VD.OBJ_ID = L12.OBJ_ID
                   ) +
                   (SELECT COUNT(VB.VAL)
                    FROM VALB VB
                    WHERE VB.PARAM_ID = 578
                    AND VB.IS_DEL = 0
                    AND VB.OBJ_ID = L12.OBJ_ID
                   )
            FROM LINKS L12
            WHERE L12.OBJ_TYPE_ID = 12
            AND L12.PARENT_ID = :OBJECT_ID
            AND L12.DATE_DEL IS NULL
            INTO :OBJ_ID, :I
        DO
        BEGIN
            IF (:I = 0) THEN
            BEGIN
                UPDATE LINKS L
                SET L.DATE_DEL = CURRENT_TIMESTAMP
                WHERE L.OBJ_ID = :OBJ_ID
                AND L.OBJ_TYPE_ID = 12
                AND DATE_DEL IS NULL;
                ERROR_TEXT = 'Для воспитанника «' || :FIO || '», «' || :CLASS || '» удалены пустые записи в поле Документ.';
                ERROR_NAME = 'Для воспитанника удалены пустые записи в поле Документ.';
                PARAMS_NAME = 'Документ';
                ERROR_TYPE = 1;
                SUSPEND;
            END
        END

        V$OBJ_ID = NULL;
        FOR SELECT l20.OBJ_ID,l20.EXT_OBJ_ID
            FROM LINKS l20
            WHERE l20.PARENT_ID = :object_id and
            l20.OBJ_TYPE_ID = 20 and l20.DATE_DEL IS NULL
            INTO :V$OBJ_ID, :V$EXT_OBJ_ID DO
            BEGIN
                SELECT C1
                FROM BUILD_REP_FIO(:V$OBJ_ID, 128, 129, 130, 0)
                INTO V$FIO_P;

                SELECT FIRST 1 TRIM(V)
                FROM LINKS L168
                LEFT JOIN VAL_GET(L168.EXT_OBJ_ID, 1573) ON 1=1
                WHERE l168.obj_ID = :V$OBJ_ID AND
                    L168.PARENT_ID = :object_id AND
                    L168.EXT_OBJ_TYPE_ID = 168 AND
                    l168.DATE_DEL is NULL
                INTO :V$VALS;

                IF (:V$VALS = '') THEN
                BEGIN
                    ERROR_TEXT = 'Поле «Степень родства» для родителя «' || :V$FIO_P || '» должно быть заполнено';
                    ERROR_NAME = 'Не заполнено поле «Степень родства»';
                    PARAMS_NAME = 'Степень родства';
                    ERROR_TYPE = 5;
                    SUSPEND;
                END

                SELECT TRIM(V)
                FROM VAL_GET(:V$EXT_OBJ_ID, 2453)
                INTO :V$VALS;
                IF (:V$VALS = '') Then
                BEGIN
                    ERROR_TEXT = 'Поле «Основание получения компенсации» для родителя «' || :V$FIO_P || '» должно быть заполнено';
                    ERROR_NAME = 'Не заполнено поле «Основание получения компенсации»';
                    PARAMS_NAME = 'Основание получения компенсации';
                    ERROR_TYPE = 5;
                    SUSPEND;
                END
            END
            IF ((:V$OBJ_ID IS NULL) OR (:V$FIO_P = '')) then
            BEGIN
                ERROR_TEXT = 'Не введены данные родителя для воспитанника «' || :FIO || '», «' || :CLASS || '» ';
                ERROR_NAME = 'Не введены данные родителя»';
                PARAMS_NAME = 'Родственник';
                ERROR_TYPE = 5;
                SUSPEND;
            END
    END
    V$Y1 = EXTRACT(YEAR FROM CURRENT_DATE);
    V$DT1 = V$Y1 || '-09-01';
    IF (CURRENT_DATE < V$DT1) THEN
    BEGIN
        V$Y2 = V$Y1;
        V$Y1 = V$Y1 - 1;
    END
    ELSE
    BEGIN
        V$Y2 = V$Y1 + 1;
    END

    -- Записи о выбытии не быть не может, проверка удалена

    FOR
        SELECT V1570.VAL
        FROM LINKS L20
        JOIN LINKS L10 ON L10.OBJ_ID = L20.PARENT_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL AND L10.PARENT_TYPE_ID = 9
        JOIN LINKS L9 ON L9.OBJ_ID = L10.PARENT_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL AND L9.PARENT_TYPE_ID = 8
        JOIN VALS V1570 ON V1570.OBJ_ID = L20.EXT_OBJ_ID AND V1570.PARAM_ID = 1570 AND V1570.IS_DEL = 0
        WHERE L20.PARENT_TYPE_ID = 10 AND L20.DATE_DEL IS NULL AND L20.OBJ_TYPE_ID = 20
        GROUP BY V1570.VAL
        HAVING COUNT(*) > 1
        INTO :V
    DO
    BEGIN
        ERROR_TYPE = 3;
        PARAMS_NAME = 'Идентификатор для экспорта на портал «Петербургское образование» (ученика)';
        ERROR_TEXT = 'Идентификатор ' || :V || ' введен для нескольких воспитанников: ';
        ERROR_NAME = 'Идентификатор введен для нескольких воспитанников';
        I = 0;
        FOR
            SELECT L20.PARENT_ID,
                   L20.OBJ_ID,
                   L20.LINK_ID
            FROM LINKS L20

            JOIN VALS V1570
            ON V1570.OBJ_ID = L20.EXT_OBJ_ID
            AND V1570.PARAM_ID = 1570
            AND V1570.IS_DEL = 0

            WHERE L20.PARENT_TYPE_ID = 10
            AND L20.DATE_DEL IS NULL
            AND L20.OBJ_TYPE_ID = 20

            AND V1570.VAL LIKE :V

            INTO :OBJ_ID,
                 :OBJECT_ID,
                 :LINK_ID
        DO
        BEGIN
            IF (I = 1) THEN
            BEGIN
                ERROR_TEXT = ERROR_TEXT || ', ';
            END
            SELECT V
            FROM VAL_GET(:OBJ_ID, 55)
            INTO :FIO;
            ERROR_TEXT = ERROR_TEXT || FIO || ' ';
            SELECT VAL
            FROM DO_FUNC(:OBJ_ID, 1348, 21)
            INTO :FIO;
            IF (FIO IS NULL) THEN
            BEGIN
                FIO = '';
            END
            ERROR_TEXT = ERROR_TEXT || FIO || ' (родитель: ';
            SELECT V
            FROM VAL_GET(:OBJECT_ID, 128)
            INTO :FIO;
            ERROR_TEXT = ERROR_TEXT || FIO || ' ';
            SELECT VAL
            FROM DO_FUNC(:OBJECT_ID, 136, 21)
            INTO :FIO;
            IF (FIO IS NULL) THEN
            BEGIN
                FIO = '';
            END
            ERROR_TEXT = ERROR_TEXT || FIO || ')';
            I = 1;
        END
        ERROR_TEXT = ERROR_TEXT || '.';
        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DOU_VERIFY_WORKERS (
    I$OBJ_ID BIGINT)
RETURNS (
    LINK_ID BIGINT,
    OBJECT_ID BIGINT,
    NAME_TASK VARCHAR(1000),
    ERROR_NAME VARCHAR(1000),
    PARAMS_NAME VARCHAR(1000),
    ERROR_TEXT VARCHAR(1000),
    ERROR_TYPE SMALLINT)
AS
declare variable V$OBJ_ID bigint;
declare variable V$TEMP integer;
declare variable V$VALI integer;
declare variable V$FIO varchar(1000);
declare variable V$STAVKA numeric(10,2);
declare variable V$TEACHER smallint;
declare variable V$MANAGER smallint;
declare variable V$STAFFER smallint;
declare variable V$VALS varchar(1000);
declare variable V$DD date;
declare variable V$DR date;
BEGIN
    NAME_TASK = 'Личные дела сотрудников ';
    ERROR_TYPE = 1;

    FOR
        SELECT L14.OBJ_ID, L14.LINK_ID

        FROM LINKS L14

        WHERE L14.PARENT_ID = :I$OBJ_ID
        AND L14.OBJ_TYPE_ID = 14
        AND L14.DATE_DEL IS NULL
        INTO :OBJECT_ID, :LINK_ID
    DO
    BEGIN
        SELECT C1
        FROM BUILD_REP_FIO(:OBJECT_ID, 59, 60, 61, 0)
        INTO V$FIO;

        FOR
            SELECT R.VAL
            FROM PARAMS P
            
            JOIN LPARAMS LP
            ON LP.PARAM_ID = P.PARAM_ID
            AND LP.IS_DEL = 0
            AND LP.LEVEL_ID in (48, /* Apostrof */ 301)
            
            JOIN RES R
            ON R.RES_ID = P.RES_ID
            AND R.LANG_CODE = 'RU'
            
            LEFT JOIN VAL_GET(:OBJECT_ID, P.PARAM_ID) VL
            ON 1=1

            WHERE P.TYPE_ID = 14
            AND P.IS_DEL = 0
            AND P.PARAM_ID IN (274, 239, 241)
            AND VL.V = ''

            INTO :V$VALS
        DO
        BEGIN
            ERROR_TEXT = 'Поле «' || :V$VALS || '» для сотрудника «' || :V$FIO || '» должно быть заполнено.';
            ERROR_NAME = 'Поле «' || :V$VALS || '» для сотрудника должно быть заполнено.';
            PARAMS_NAME = V$VALS;
            ERROR_TYPE = 3;
            SUSPEND;
        END

        -- 4 --
        FOR
            SELECT L79.OBJ_ID,
                   (SELECT COUNT(VS.VAL)
                    FROM VALS VS
                    WHERE VS.PARAM_ID IN (442, 559, 562, 563)
                    AND VS.IS_DEL = 0
                    AND VS.OBJ_ID = L79.OBJ_ID
                   ) +
                   (SELECT COUNT(VLL.LISTVAL_ID)
                    FROM VALL VLL
                    WHERE VLL.PARAM_ID IN (441)
                    AND VLL.IS_DEL = 0
                    AND VLL.OBJ_ID = L79.OBJ_ID
                   ) +
                   (SELECT COUNT(VD.VAL)
                    FROM VALD VD
                    WHERE VD.PARAM_ID IN (560, 561)
                    AND VD.IS_DEL = 0
                    AND VD.OBJ_ID = L79.OBJ_ID
                   ) +
                   (SELECT COUNT(VB.VAL)
                    FROM VALB VB
                    WHERE VB.PARAM_ID = 576
                    AND VB.IS_DEL = 0
                    AND VB.OBJ_ID = L79.OBJ_ID
                   )
            FROM LINKS L79
            WHERE L79.OBJ_TYPE_ID = 79
            AND L79.PARENT_ID = :OBJECT_ID
            AND L79.DATE_DEL IS NULL
            INTO :V$OBJ_ID, :V$TEMP
        DO
        BEGIN
            IF (:V$TEMP = 0) THEN
            BEGIN
                UPDATE LINKS L
                SET L.DATE_DEL = CURRENT_TIMESTAMP
                WHERE L.OBJ_ID = :V$OBJ_ID
                AND L.OBJ_TYPE_ID = 79
                AND DATE_DEL IS NULL;
                ERROR_TEXT = 'Для сотрудника «' || :V$FIO || '» удалены пустые записи в поле Документ удостоверяющий личность.';
                ERROR_NAME = 'Для сотрудника удалены пустые записи в поле Документ удостоверяющий личность.';
                PARAMS_NAME = 'Документ удостоверяющий личность';
                ERROR_TYPE = 1;
                SUSPEND;
            END
        END
        -- 5 --
        V$TEACHER = 0;
        SELECT X
        FROM IS_TEACHER(:OBJECT_ID)
        INTO :V$TEACHER;-- отсюда

        V$MANAGER = 0;
        SELECT X FROM IS_MANAGER(:OBJECT_ID)
        INTO :V$MANAGER;

        V$STAFFER = 0;
        SELECT FIRST 1 1
        FROM LINKS l15
        JOIN VALL VL ON VL.OBJ_ID = L15.OBJ_ID and VL.PARAM_ID = 587
        WHERE L15.PARENT_ID = :OBJECT_ID and l15.OBJ_TYPE_ID = 15 and l15.DATE_DEL IS NULL
        INTO :V$STAFFER;

        -- Задание квалификационной категории для всех педагогических сотрудников, по основной должности
        V$VALS = NULL;

        SELECT FIRST 1 V1790.LISTVAL_ID
        FROM LINKS L14_L15
        -- Только основные должности
        JOIN VALL V72 ON V72.OBJ_ID = L14_L15.OBJ_ID AND V72.PARAM_ID = 72 AND V72.IS_DEL = 0 AND V72.LISTVAL_ID = 934
        -- Активные в данный момент
        LEFT JOIN VALD V74 ON V74.OBJ_ID = L14_L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
        JOIN VALL V1790 ON V1790.OBJ_ID = L14_L15.OBJ_ID AND V1790.PARAM_ID = 1790 AND V1790.IS_DEL = 0
        WHERE L14_L15.PARENT_ID = :OBJECT_ID AND L14_L15.OBJ_TYPE_ID = 15 AND L14_L15.DATE_DEL IS NULL AND (V74.VAL IS NULL OR V74.VAL > CURRENT_TIMESTAMP)
        INTO :V$VALS;

        IF(V$VALS IS NULL) THEN V$VALS = '';

        if ((V$VALS = '') AND (V$TEACHER = 1) AND (V$STAFFER = 1)) then
        BEGIN
            ERROR_TEXT = 'Для штатного педагогического сотрудника «' || :V$FIO || '» не заполнено поле "Квалификационная категория".';
            ERROR_NAME = 'Для штатного педагогического сотрудника не заполнено поле "Квалификационная категория".';
            PARAMS_NAME = 'Квалификационная категория';
            ERROR_TYPE = 3;
            SUSPEND;
        END

        -- 79 --
        if (V$STAFFER = 1) then
        BEGIN
            SELECT COUNT(*)
            FROM LINKS L79
            WHERE L79.OBJ_TYPE_ID = 79 AND L79.PARENT_ID = :OBJECT_ID AND L79.DATE_DEL IS NULL
            INTO :V$TEMP;
            IF (:V$TEMP = 0) THEN
            BEGIN
                ERROR_TEXT = 'Для сотрудника «' || :V$FIO || '» не введены данные документа, удостоверяющего личность';
                ERROR_NAME = 'Для сотрудника не введены данные документа, удостоверяющего личность';
                PARAMS_NAME = 'Документ удостоверяющий личность';
                ERROR_TYPE = 5;
                SUSPEND;
            END
        -- 6 --
            FOR
                SELECT (SELECT COUNT(VS.VAL)
                        FROM VALS VS
                        WHERE VS.PARAM_ID = 442
                        AND VS.IS_DEL = 0
                        AND VS.OBJ_ID = L79.OBJ_ID
                    )
                FROM LINKS L79
                WHERE L79.OBJ_TYPE_ID = 79
                AND L79.PARENT_ID = :OBJECT_ID
                AND L79.DATE_DEL IS NULL
                INTO :V$TEMP
            DO
            BEGIN
                IF (:V$TEMP = 0) THEN
                BEGIN
                    ERROR_TEXT = 'Для сотрудника «' || :V$FIO || '» не введена серия документа, удостоверяющего личность';
                    ERROR_NAME = 'Для сотрудника не введена серия документа, удостоверяющего личность';
                    PARAMS_NAME = 'Документ удостоверяющий личность';
                    ERROR_TYPE = 5;
                    SUSPEND;
                END
            END
            --7 --
            FOR SELECT (SELECT COUNT(VS.VAL)
                    FROM VALS VS
                    WHERE VS.PARAM_ID = 559
                    AND VS.IS_DEL = 0
                    AND VS.OBJ_ID = L79.OBJ_ID
                   )
                FROM LINKS L79
                WHERE L79.OBJ_TYPE_ID = 79
                AND L79.PARENT_ID = :OBJECT_ID
                AND L79.DATE_DEL IS NULL
                INTO :V$TEMP
            DO
            BEGIN
                IF (:V$TEMP = 0) THEN
                BEGIN
                    ERROR_TEXT = 'Для сотрудника «' || :V$FIO || '» не введен номер документа, удостоверяющего личность';
                    ERROR_NAME = 'Для сотрудника не введен номер документа, удостоверяющего личность';
                    PARAMS_NAME = 'Документ удостоверяющий личность';
                    ERROR_TYPE = 5;
                    SUSPEND;
                END
            END
        END

        -- 8 --
        FOR
            SELECT L12.OBJ_ID,
                   (SELECT COUNT(VS.VAL)
                    FROM VALS VS
                    WHERE VS.PARAM_ID IN (570, 571, 574, 575)
                    AND VS.IS_DEL = 0
                    AND VS.OBJ_ID = L12.OBJ_ID
                   ) +
                   (SELECT COUNT(VLL.LISTVAL_ID)
                    FROM VALL VLL
                    WHERE VLL.PARAM_ID = 51
                    AND VLL.IS_DEL = 0
                    AND VLL.OBJ_ID = L12.OBJ_ID
                   ) +
                   (SELECT COUNT(VD.VAL)
                    FROM VALD VD
                    WHERE VD.PARAM_ID IN (572, 573)
                    AND VD.IS_DEL = 0
                    AND VD.OBJ_ID = L12.OBJ_ID
                   ) +
                   (SELECT COUNT(VB.VAL)
                    FROM VALB VB
                    WHERE VB.PARAM_ID = 578
                    AND VB.IS_DEL = 0
                    AND VB.OBJ_ID = L12.OBJ_ID
                   )
            FROM LINKS L12
            WHERE L12.OBJ_TYPE_ID = 12
            AND L12.PARENT_ID = :OBJECT_ID
            AND L12.DATE_DEL IS NULL
            INTO :V$OBJ_ID, :V$TEMP
        DO
        BEGIN
            IF (:V$TEMP = 0) THEN
            BEGIN
                UPDATE LINKS L
                SET L.DATE_DEL = CURRENT_TIMESTAMP
                WHERE L.OBJ_ID = :V$OBJ_ID
                AND L.OBJ_TYPE_ID = 12
                AND DATE_DEL IS NULL;
                ERROR_TEXT = 'Для сотрудника «' || :V$FIO || '» удалены пустые записи в поле документ.';
                ERROR_NAME = 'Для сотрудника удалены пустые записи в поле документ.';
                PARAMS_NAME = 'Документ';
                ERROR_TYPE = 1;
                SUSPEND;
            END
        END
        -- 9 --
        SELECT COUNT(VLL.LISTVAL_ID)
        FROM LINKS L15

        JOIN VALL VLL
        ON VLL.OBJ_ID = L15.OBJ_ID
        AND VLL.PARAM_ID = 72
        AND VLL.IS_DEL = 0
        AND VLL.LISTVAL_ID = 934

        LEFT JOIN VALD V74
        ON V74.PARAM_ID = 74
        AND V74.OBJ_ID = L15.OBJ_ID
        AND V74.IS_DEL = 0

        WHERE L15.OBJ_TYPE_ID = 15
        AND L15.PARENT_ID = :OBJECT_ID
        AND L15.DATE_DEL IS NULL
        AND V74.VAL IS NULL
        INTO :V$TEMP;

        IF (:V$TEMP > 1) THEN
        BEGIN
            ERROR_TEXT = 'Сотрудник «' || :V$FIO || '» занимает несколько основных должностей';
            ERROR_NAME = 'Сотрудник занимает несколько основных должностей';
            PARAMS_NAME = 'Должность основная или дополнительная';
            ERROR_TYPE = 3;
            SUSPEND;
        END ELSE
        IF (:V$TEMP = 0) THEN
        BEGIN
            ERROR_TEXT = 'У сотрудника «' || :V$FIO || '» не указана основная должность';
            ERROR_NAME = 'У сотрудника не указана основная должность';
            PARAMS_NAME = 'Должность основная или дополнительная';
            ERROR_TYPE = 5;
            SUSPEND;
        END

        -- 10 --
        FOR
            SELECT SUM(VF.VAL), VR.VAL
            FROM LINKS L15

            JOIN VALF VF
            ON VF.OBJ_ID = L15.OBJ_ID
            AND VF.PARAM_ID = 71
            AND VF.IS_DEL = 0

            JOIN VALR VR
            ON VR.OBJ_ID = L15.OBJ_ID
            AND VR.PARAM_ID = 69
            AND VR.IS_DEL = 0

            LEFT JOIN VALD VD74
            ON VD74.OBJ_ID = L15.OBJ_ID
            AND VD74.PARAM_ID = 74
            AND VD74.IS_DEL = 0

            LEFT JOIN VALD VD456
            ON VD456.OBJ_ID = L15.OBJ_ID
            AND VD456.PARAM_ID = 456
            AND VD456.IS_DEL = 0

            WHERE L15.OBJ_TYPE_ID = 15
            AND L15.PARENT_ID = :OBJECT_ID
            AND L15.DATE_DEL IS NULL
            AND VD74.OBJ_ID IS NULL
            AND VD456.OBJ_ID IS NULL

            GROUP BY VR.VAL
            INTO :V$STAVKA, :V$OBJ_ID
        DO
        BEGIN
            IF (:V$STAVKA > 2) THEN
            BEGIN
                SELECT CAPTION
                FROM OBJECT_CAPTION_GET(:V$OBJ_ID)
                INTO :V$VALS;

                ERROR_TEXT = 'Сотрудник «' || :V$FIO || '» имеет ' || :V$STAVKA || ' ставки по должности ' || :V$VALS;
                ERROR_NAME = 'Сотрудник имеет более двух ставок по должности';
                PARAMS_NAME = 'Количество занимаемых ставок';
                ERROR_TYPE = 3;
                SUSPEND;
            END ELSE
            IF (:V$STAVKA = 0) THEN
            BEGIN
                ERROR_TEXT = 'У сотрудника «' || :V$FIO || '» не указано количество занимаемых ставок по должности ' || :V$VALS;
                ERROR_NAME = 'У сотрудника не указано количество занимаемых ставок по должности';
                PARAMS_NAME = 'Количество занимаемых ставок';
                ERROR_TYPE = 3;
                SUSPEND;
            END
        END
        -- 11 --
        FOR
            SELECT (SELECT VD.VAL
                    FROM VALD VD
                    WHERE VD.IS_DEL = 0
                    AND VD.PARAM_ID = 73
                    AND VD.OBJ_ID = L15.OBJ_ID
                   ),
                   VD1.VAL + 4748
            FROM LINKS L15
            JOIN VALD VD1
            ON VD1.OBJ_ID = :OBJECT_ID
            AND VD1.IS_DEL = 0
            AND VD1.PARAM_ID = 241

            WHERE L15.OBJ_TYPE_ID = 15
            AND L15.PARENT_ID = :OBJECT_ID
            AND L15.DATE_DEL IS NULL
            INTO :V$DD, :V$DR
        DO
        BEGIN
            IF (:V$DD IS NULL) THEN
            BEGIN
                ERROR_TEXT = 'Не указана дата вступления в должность у сотрудника «' || :V$FIO || '»';
                ERROR_NAME = 'Не указана дата вступления в должность у сотрудника';
                PARAMS_NAME = 'Дата вступления в должность';
                ERROR_TYPE = 5;
                SUSPEND;
            END ELSE
            IF ((:V$DD > CURRENT_DATE) OR (:V$DD < :V$DR)) THEN
            BEGIN
                ERROR_TEXT = 'Некорректная дата вступления в должность у сотрудника «' || :V$FIO || '»';
                ERROR_NAME = 'Некорректная дата вступления в должность у сотрудника';
                PARAMS_NAME = 'Дата вступления в должность';
                ERROR_TYPE = 3;
                SUSPEND;
            END
        END
        -- 12 -- заполненность поля образование - исключено
        -- 13 -- заполненность квалификационной категории - исключено (см. выше)
        -- 14 --
        FOR
            SELECT L33.OBJ_ID,
                   (SELECT COUNT(VS.VAL)
                    FROM VALS VS
                    WHERE VS.PARAM_ID IN (285, 287, 288, 291, 292)
                    AND VS.IS_DEL = 0
                    AND VS.OBJ_ID = L33.OBJ_ID
                   ) +
                   (SELECT COUNT(VLL.LISTVAL_ID)
                    FROM VALL VLL
                    WHERE VLL.PARAM_ID IN (284, 286, 289, 293)
                    AND VLL.IS_DEL = 0
                    AND VLL.OBJ_ID = L33.OBJ_ID
                   ) +
                   (SELECT COUNT(VD.VAL)
                    FROM VALD VD
                    WHERE VD.PARAM_ID = 290
                    AND VD.IS_DEL = 0
                    AND VD.OBJ_ID = L33.OBJ_ID
                   )
            FROM LINKS L33
            WHERE L33.OBJ_TYPE_ID = 33
            AND L33.PARENT_ID = :OBJECT_ID
            AND L33.DATE_DEL IS NULL
            INTO :V$OBJ_ID, :V$TEMP
        DO
        BEGIN
            IF (:V$TEMP = 0) THEN
            BEGIN
                UPDATE LINKS L
                SET L.DATE_DEL = CURRENT_TIMESTAMP
                WHERE L.OBJ_ID = :V$OBJ_ID
                AND L.OBJ_TYPE_ID = 33
                AND DATE_DEL IS NULL;
                ERROR_TEXT = 'Для сотрудника «' || :V$FIO || '» удалены пустые записи в поле «Полученное образование»';
                ERROR_NAME = 'Для сотрудника удалены пустые записи в поле «Полученное образование»';
                PARAMS_NAME = 'Полученное образование';
                ERROR_TYPE = 1;
                SUSPEND;
            END
        END
        -- 15 --
        FOR SELECT L35.OBJ_ID,
                   (SELECT COUNT(VS.VAL)
                    FROM VALS VS
                    WHERE VS.PARAM_ID IN (298, 299, 301, 302)
                    AND VS.IS_DEL = 0
                    AND VS.OBJ_ID = L35.OBJ_ID
                   ) +
                   (SELECT COUNT(VLL.LISTVAL_ID)
                    FROM VALL VLL
                    WHERE VLL.PARAM_ID IN (297, 296)
                    AND VLL.IS_DEL = 0
                    AND VLL.OBJ_ID = L35.OBJ_ID
                   ) +
                   (SELECT COUNT(VD.VAL)
                    FROM VALD VD
                    WHERE VD.PARAM_ID = 300
                    AND VD.IS_DEL = 0
                    AND VD.OBJ_ID = L35.OBJ_ID
                   )
            FROM LINKS L35
            WHERE L35.OBJ_TYPE_ID = 35
            AND L35.PARENT_ID = :OBJECT_ID
            AND L35.DATE_DEL IS NULL
            INTO :V$OBJ_ID, :V$TEMP
        DO
        BEGIN
            IF (:V$TEMP = 0) THEN
            BEGIN
                UPDATE LINKS L
                SET L.DATE_DEL = CURRENT_TIMESTAMP
                WHERE L.OBJ_ID = :V$OBJ_ID
                AND L.OBJ_TYPE_ID = 35
                AND DATE_DEL IS NULL;
                ERROR_TEXT = 'Для сотрудника «' || :V$FIO || '» удалены пустые записи в поле «Профессиональная переподготовка»';
                ERROR_NAME = 'Для сотрудника удалены пустые записи в поле «Профессиональная переподготовка»';
                PARAMS_NAME = 'Профессиональная переподготовка';
                ERROR_TYPE = 1;
                SUSPEND;
            END
        END
        --16 --
        FOR
            SELECT L36.OBJ_ID,
                   (SELECT COUNT(VS.VAL)
                    FROM VALS VS
                    WHERE VS.PARAM_ID IN (305, 308, 309)
                    AND VS.IS_DEL = 0
                    AND VS.OBJ_ID = L36.OBJ_ID
                   ) +
                   (SELECT COUNT(VLL.LISTVAL_ID)
                    FROM VALL VLL
                    WHERE VLL.PARAM_ID IN (303, 304, 1024, 307)
                    AND VLL.IS_DEL = 0
                    AND VLL.OBJ_ID = L36.OBJ_ID
                   ) +
                   (SELECT COUNT(VD.VAL)
                    FROM VALD VD
                    WHERE VD.PARAM_ID = 310
                    AND VD.IS_DEL = 0
                    AND VD.OBJ_ID = L36.OBJ_ID
                   ) +
                   (SELECT COUNT(VI.VAL)
                    FROM VALD VI
                    WHERE VI.PARAM_ID = 306
                    AND VI.IS_DEL = 0
                    AND VI.OBJ_ID = L36.OBJ_ID
                   )
            FROM LINKS L36
            WHERE L36.OBJ_TYPE_ID = 36
            AND L36.PARENT_ID = :OBJECT_ID
            AND L36.DATE_DEL IS NULL
            INTO :V$OBJ_ID, :V$TEMP
        DO
        BEGIN
            IF (:V$TEMP = 0) THEN
            BEGIN
                UPDATE LINKS L
                SET L.DATE_DEL = CURRENT_TIMESTAMP
                WHERE L.OBJ_ID = :V$OBJ_ID
                AND L.OBJ_TYPE_ID = 36
                AND DATE_DEL IS NULL;
                ERROR_TEXT = 'Для сотрудника «' || :V$FIO || '» удалены пустые записи в поле «Повышение квалификации»';
                ERROR_NAME = 'Для сотрудника удалены пустые записи в поле «Повышение квалификации»';
                PARAMS_NAME = 'Повышение квалификации';
                ERROR_TYPE = 1;
                SUSPEND;
            END
        END
        --17 --
     /*   SELECT COUNT(L36.OBJ_ID)
        FROM LINKS L36
        WHERE L36.OBJ_TYPE_ID = 36
        AND L36.PARENT_ID = :OBJECT_ID
        AND L36.DATE_DEL IS NULL
        INTO :V$TEMP;
        IF ((:V$TEMP = 0) AND (:V$TEACHER = 1) AND (:V$STAFFER = 1)) THEN
        BEGIN
            ERROR_TEXT = 'Нет информации о курсах повышения квалификации для педагогического сотрудника «' || :V$FIO || '»';
            ERROR_NAME = 'Нет информации о курсах повышения квалификации для педагогического сотрудника';
            PARAMS_NAME = 'Повышение квалификации';
            ERROR_TYPE = 2;
            SUSPEND;
        END  */
        -- 18 --
        V$VALI = 0;
        FOR
            SELECT L34.OBJ_ID,
                   (SELECT COUNT(VS.VAL)
                    FROM VALS VS
                    WHERE VS.PARAM_ID = 294
                    AND VS.IS_DEL = 0
                    AND VS.OBJ_ID = L34.OBJ_ID
                   ) +
                   (SELECT COUNT(VLL.LISTVAL_ID)
                    FROM VALL VLL
                    WHERE VLL.PARAM_ID = 545
                    AND VLL.IS_DEL = 0
                    AND VLL.OBJ_ID = L34.OBJ_ID
                   ) +
                   (SELECT COUNT(VD.VAL)
                    FROM VALD VD
                    WHERE VD.PARAM_ID = 544
                    AND VD.IS_DEL = 0
                    AND VD.OBJ_ID = L34.OBJ_ID
                   ) +
                   (SELECT COUNT(VR.VAL)
                    FROM VALR VR
                    WHERE VR.PARAM_ID = 295
                    AND VR.IS_DEL = 0
                    AND VR.OBJ_ID = L34.OBJ_ID
                   )
            FROM LINKS L34
            WHERE L34.OBJ_TYPE_ID = 34
            AND L34.PARENT_ID = :OBJECT_ID
            AND L34.DATE_DEL IS NULL
            INTO :V$OBJ_ID, :V$TEMP
        DO
        BEGIN
            IF (:V$TEMP = 0) THEN
            BEGIN
                UPDATE LINKS L
                SET L.DATE_DEL = CURRENT_TIMESTAMP
                WHERE L.OBJ_ID = :V$OBJ_ID
                AND L.DATE_DEL IS NULL;
                V$VALI = 1;
            END
        END

        FOR
            SELECT L156.OBJ_ID,
                   (SELECT COUNT(*)
                    FROM VALS VS
                    WHERE VS.PARAM_ID = 1234
                    AND VS.IS_DEL = 0
                    AND VS.OBJ_ID = L156.OBJ_ID
                   ) +
                   (SELECT COUNT(*)
                    FROM VALL VLL
                    WHERE VLL.PARAM_ID = 1233
                    AND VLL.IS_DEL = 0
                    AND VLL.OBJ_ID = L156.OBJ_ID
                   ) +
                   (SELECT COUNT(*)
                    FROM VALD VD
                    WHERE VD.PARAM_ID = 1232
                    AND VD.IS_DEL = 0
                    AND VD.OBJ_ID = L156.OBJ_ID
                   ) +
                   (SELECT COUNT(*)
                    FROM VALR VR
                    WHERE VR.PARAM_ID = 1235
                    AND VR.IS_DEL = 0
                    AND VR.OBJ_ID = L156.OBJ_ID
                   )
            FROM LINKS L156
            WHERE L156.OBJ_TYPE_ID = 156
            AND L156.PARENT_ID = :OBJECT_ID
            AND L156.DATE_DEL IS NULL
            INTO :V$OBJ_ID, :V$TEMP
        DO
        BEGIN
            IF (:V$TEMP = 0) THEN
            BEGIN
                UPDATE LINKS L
                SET L.DATE_DEL = CURRENT_TIMESTAMP
                WHERE L.OBJ_ID = :V$OBJ_ID
                AND L.DATE_DEL IS NULL;
                V$VALI = 1;
            END
        END
        IF (:V$VALI = 1) THEN
        BEGIN
            ERROR_TEXT = 'Для сотрудника «' || :V$FIO || '» удалены пустые записи в поле «Прохождение аттестации»';
            ERROR_NAME = 'Для сотрудника удалены пустые записи в поле «Прохождение аттестации»';
            PARAMS_NAME = 'Прохождение аттестации';
            ERROR_TYPE = 1;
            SUSPEND;
        END
        -- 19 --
        IF (NOT EXISTS(
            SELECT FIRST 1 1
            FROM LINKS L15
    
            JOIN VALL VLL
            ON VLL.OBJ_ID = L15.OBJ_ID
            AND VLL.PARAM_ID = 72
            AND VLL.IS_DEL = 0
            AND VLL.LISTVAL_ID = 934
    
            LEFT JOIN VALD V74
            ON V74.PARAM_ID = 74
            AND V74.OBJ_ID = L15.OBJ_ID
            AND V74.IS_DEL = 0
    
            WHERE L15.OBJ_TYPE_ID = 15
            AND L15.PARENT_ID = :OBJECT_ID
            AND L15.DATE_DEL IS NULL
            AND V74.VAL IS NULL
        )) THEN
        BEGIN
            ERROR_TEXT = 'У сотрудника «' || :V$FIO || '» отсутствует основная должность';
            ERROR_NAME = 'Отсутствует основная должность';
            PARAMS_NAME = 'Должность основная или дополнительная';
            ERROR_TYPE = 5;
            SUSPEND;
        END
        FOR
            SELECT L15.OBJ_ID
            FROM LINKS L15
            WHERE L15.OBJ_TYPE_ID = 15
            AND L15.PARENT_ID = :OBJECT_ID
            AND L15.DATE_DEL IS NULL

            INTO :V$OBJ_ID
        DO
        BEGIN
            FOR
                SELECT R.VAL
                FROM PARAMS P
                        
                JOIN LPARAMS LP
                ON LP.PARAM_ID = P.PARAM_ID
                AND LP.IS_DEL = 0
                AND LP.LEVEL_ID in (48, /* Apostrof */ 301)
                        
                JOIN RES R
                ON R.RES_ID = P.RES_ID
                AND R.LANG_CODE = 'RU'
                        
                LEFT JOIN VAL_GET(:V$OBJ_ID, P.PARAM_ID) VL
                ON 1=1
            
                WHERE P.TYPE_ID = 15
                AND P.IS_DEL = 0
                AND P.PARAM_ID IN (71, 587, 72)  -- 73,
                AND VL.V = ''
            
                INTO :V$VALS
            DO
            BEGIN
                ERROR_TEXT = 'В данных о должности для педагогического сотрудника «' || :V$FIO || '» не заполнено поле «' || :V$VALS || '»';
                ERROR_NAME = 'В данных о должности для педагогического сотрудника не заполнено поле «' || :V$VALS || '»';
                PARAMS_NAME = V$VALS;
                ERROR_TYPE = 5;
                SUSPEND;
            END
        END
        IF ((V$MANAGER = 1) OR ((:V$STAFFER = 1) AND (V$TEACHER = 1))) THEN
        BEGIN
            IF (NOT EXISTS(
                SELECT FIRST 1 1
                FROM LINKS L36
                WHERE L36.OBJ_TYPE_ID = 36
                AND L36.PARENT_ID = :OBJECT_ID
                AND L36.DATE_DEL IS NULL
            )) THEN
            BEGIN
                ERROR_TEXT = 'Не введены данные о повышении квалификации для педагогического и руководящего сотрудника «' || :V$FIO || '»';
                ERROR_NAME = 'Не введены данные о повышении квалификации для педагогического и руководящего сотрудника';
                PARAMS_NAME = 'Прохождение аттестации';
                ERROR_TYPE = 5;
                SUSPEND;
            END
            ELSE
            BEGIN
                FOR
                    SELECT L36.OBJ_ID
                    FROM LINKS L36
                    WHERE L36.OBJ_TYPE_ID = 36
                    AND L36.PARENT_ID = :OBJECT_ID
                    AND L36.DATE_DEL IS NULL
        
                    INTO :V$OBJ_ID
                DO
                BEGIN
                    FOR
                        SELECT R.VAL
                        FROM PARAMS P
                                
                        JOIN LPARAMS LP
                        ON LP.PARAM_ID = P.PARAM_ID
                        AND LP.IS_DEL = 0
                        AND LP.LEVEL_ID in (48, /* Apostrof */ 301)
                                
                        JOIN RES R
                        ON R.RES_ID = P.RES_ID
                        AND R.LANG_CODE = 'RU'
                                
                        LEFT JOIN VAL_GET(:V$OBJ_ID, P.PARAM_ID) VL
                        ON 1=1
                    
                        WHERE P.TYPE_ID = 36
                        AND P.IS_DEL = 0
                        AND P.PARAM_ID IN (303, 304, 1024, 306, 310)
                        AND VL.V = ''
                    
                        INTO :V$VALS
                    DO
                    BEGIN
                        ERROR_TEXT = 'В данных о повышении квалификации для штатного педагогического и руководящего сотрудника «' || :V$FIO || '» не заполнено поле «' || :V$VALS || '»';
                        ERROR_NAME = 'В данных о повышении квалификации штатного педагогического и руководящего сотрудника не заполнено поле «' || :V$VALS || '»';
                        PARAMS_NAME = V$VALS;
                        ERROR_TYPE = 5;
                        SUSPEND;
                    END
                END
            END
        END
        -- 33 --
        IF ((:V$STAFFER = 1) and (:V$TEACHER = 1)) THEN
        BEGIN
            FOR
                SELECT L33.OBJ_ID
                FROM LINKS L33
                WHERE L33.OBJ_TYPE_ID = 33
                AND L33.PARENT_ID = :OBJECT_ID
                AND L33.DATE_DEL IS NULL
    
                INTO :V$OBJ_ID
            DO
            BEGIN
                FOR
                    SELECT R.VAL
                    FROM PARAMS P
                            
                    JOIN LPARAMS LP
                    ON LP.PARAM_ID = P.PARAM_ID
                    AND LP.IS_DEL = 0
                    AND LP.LEVEL_ID in (48, /* Apostrof */ 301)
                            
                    JOIN RES R
                    ON R.RES_ID = P.RES_ID
                    AND R.LANG_CODE = 'RU'
                            
                    LEFT JOIN VAL_GET(:V$OBJ_ID, P.PARAM_ID) VL
                    ON 1=1
                
                    WHERE P.TYPE_ID = 33
                    AND P.IS_DEL = 0
                    AND P.PARAM_ID IN (284, 285, 287, 286, 288, 290, 291, 292, 293)
                    AND VL.V = ''
                
                    INTO :V$VALS
                DO
                BEGIN
                    ERROR_TEXT = 'В данных о полученном образовании для штатного педагогического сотрудника «' || :V$FIO || '» не заполнено поле «' || :V$VALS || '»';
                    ERROR_NAME = 'В данных о полученном образовании для штатного педагогического сотрудника не заполнено поле «' || :V$VALS || '»';
                    PARAMS_NAME = V$VALS;
                    ERROR_TYPE = 5;
                    SUSPEND;
                END
            END
        END
        -- 14 --
        IF (:V$STAFFER = 1) THEN
        BEGIN
            FOR
                SELECT R.VAL
                FROM PARAMS P
                
                JOIN LPARAMS LP
                ON LP.PARAM_ID = P.PARAM_ID
                AND LP.IS_DEL = 0
                AND LP.LEVEL_ID in (48, /* Apostrof */ 301)
                
                JOIN RES R
                ON R.RES_ID = P.RES_ID
                AND R.LANG_CODE = 'RU'
                
                LEFT JOIN VAL_GET(:OBJECT_ID, P.PARAM_ID) VL
                ON 1=1
    
                WHERE P.TYPE_ID = 14
                AND P.IS_DEL = 0
                AND P.PARAM_ID IN (243, 244, 255, 262, 250)
                AND VL.V = ''
    
                INTO :V$VALS
            DO
            BEGIN
                ERROR_TEXT = 'Не заполнено поле «' || :V$VALS || '» для педагогического сотрудника «' || :V$FIO || '»';
                ERROR_NAME = 'Не заполнено поле «' || :V$VALS || '»';
                PARAMS_NAME = V$VALS;
                ERROR_TYPE = 5;
                SUSPEND;
            END
        END
        -- 34 --
        if ((:V$TEACHER = 1) AND (:V$STAFFER = 1)) then
        BEGIN
            IF (NOT EXISTS(
                SELECT FIRST 1 1
                FROM LINKS L34
                WHERE L34.OBJ_TYPE_ID = 34
                AND L34.PARENT_ID = :OBJECT_ID
                AND L34.DATE_DEL IS NULL
            )) THEN
            BEGIN
                ERROR_TEXT = 'Не введены данные о прохождении аттестации для штатного педагогического сотрудника «' || :V$FIO || '»';
                ERROR_NAME = 'Не введены данные о прохождении аттестации для педагогического сотрудника';
                PARAMS_NAME = 'Прохождение аттестации';
                ERROR_TYPE = 5;
                SUSPEND;
            END
            ELSE
            BEGIN
                FOR
                    SELECT L34.OBJ_ID
                    FROM LINKS L34
                    WHERE L34.OBJ_TYPE_ID = 34
                    AND L34.PARENT_ID = :OBJECT_ID
                    AND L34.DATE_DEL IS NULL

                    INTO :V$OBJ_ID
                DO
                BEGIN
                    FOR
                        SELECT R.VAL
                        FROM PARAMS P
                        
                        JOIN LPARAMS LP
                        ON LP.PARAM_ID = P.PARAM_ID
                        AND LP.IS_DEL = 0
                        AND LP.LEVEL_ID in (48, /* Apostrof */ 301)
                        
                        JOIN RES R
                        ON R.RES_ID = P.RES_ID
                        AND R.LANG_CODE = 'RU'
                        
                        LEFT JOIN VAL_GET(:V$OBJ_ID, P.PARAM_ID) VL
                        ON 1=1
            
                        WHERE P.TYPE_ID = 34
                        AND P.IS_DEL = 0
                        AND P.PARAM_ID IN (295, 544, 545, 294)
                        AND VL.V = ''
            
                        INTO :V$VALS
                    DO
                    BEGIN
                        if ((:V$TEACHER = 1) AND (:V$STAFFER = 1)) then
                        BEGIN
                            ERROR_TEXT = 'В данных о прохождении аттестации для штатного педагогического сотрудника «' || :V$FIO || '» не заполнено поле «' || :V$VALS || '»';
                            ERROR_NAME = 'В данных о прохождении аттестации для штатного педагогического сотрудника не заполнено поле «' || :V$VALS || '»';
                            PARAMS_NAME = V$VALS;
                            ERROR_TYPE = 5;
                            SUSPEND;
                        END
                    END
                END
            END
        END
        -- 20 --
        IF (:V$STAFFER = 1) THEN
        BEGIN
            SELECT COUNT(L85.OBJ_ID)

            FROM LINKS L85

            JOIN VALL V465
            ON V465.OBJ_ID = L85.OBJ_ID
            AND V465.PARAM_ID = 465
            AND V465.IS_DEL = 0
            AND V465.LISTVAL_ID = 941

            WHERE L85.PARENT_ID = :OBJECT_ID
            AND L85.OBJ_TYPE_ID = 85
            AND L85.DATE_DEL IS NULL
            INTO :V$TEMP;
            IF (:V$TEMP = 0) THEN
            BEGIN
                ERROR_TEXT = 'Для штатного сотрудника «' || :V$FIO || '» не введён общий стаж';
                ERROR_NAME = 'Не заполнено поле «Общий стаж»';
                PARAMS_NAME = 'Общий стаж';
                ERROR_TYPE = 5;
                SUSPEND;
            END
        END
        -- 21 --
        IF (:V$TEACHER = 1) THEN
        BEGIN
            SELECT COUNT(L85.OBJ_ID)
            FROM LINKS L85
            JOIN VALL V465
            ON V465.OBJ_ID = L85.OBJ_ID
            AND V465.PARAM_ID = 465
            AND V465.IS_DEL = 0
            AND V465.LISTVAL_ID = 942
            WHERE L85.PARENT_ID = :OBJECT_ID
            AND L85.OBJ_TYPE_ID = 85
            AND L85.DATE_DEL IS NULL
            INTO :V$TEMP;
            IF (:V$TEMP = 0) THEN
            BEGIN
                ERROR_TEXT = 'Для штатного педагогического сотрудника «' || :V$FIO || '» не введён педагогический стаж';
                ERROR_NAME = 'Не заполнено поле «Педагогический стаж»';
                PARAMS_NAME = 'Педагогический стаж';
                ERROR_TYPE = 5;
                SUSPEND;
            END
        END
        -- 22 --
        FOR
            SELECT L38.OBJ_ID,
                   (SELECT COUNT(VS.VAL)
                    FROM VALS VS
                    WHERE VS.PARAM_ID IN (338, 340)
                    AND VS.IS_DEL = 0
                    AND VS.OBJ_ID = L38.OBJ_ID
                   ) +
                   (SELECT COUNT(VLL.LISTVAL_ID)
                    FROM VALL VLL
                    WHERE VLL.PARAM_ID = 337
                    AND VLL.IS_DEL = 0
                    AND VLL.OBJ_ID = L38.OBJ_ID
                   ) +
                   (SELECT COUNT(VD.VAL)
                    FROM VALD VD
                    WHERE VD.PARAM_ID = 339
                    AND VD.IS_DEL = 0
                    AND VD.OBJ_ID = L38.OBJ_ID
                   )
            FROM LINKS L38
            WHERE L38.OBJ_TYPE_ID = 38
            AND L38.PARENT_ID = :OBJECT_ID
            AND L38.DATE_DEL IS NULL
            INTO :V$OBJ_ID, :V$TEMP
        DO
        BEGIN
            IF (:V$TEMP = 0) THEN
            BEGIN
                UPDATE LINKS L
                SET L.DATE_DEL = CURRENT_TIMESTAMP
                WHERE L.OBJ_ID = :V$OBJ_ID
                AND L.OBJ_TYPE_ID = 38
                AND DATE_DEL IS NULL;
            END
        END
        --
        FOR
            SELECT L39.OBJ_ID,
                   (SELECT COUNT(VS.VAL)
                    FROM VALS VS
                    WHERE VS.PARAM_ID IN (346, 348)
                    AND VS.IS_DEL = 0
                    AND VS.OBJ_ID = L39.OBJ_ID
                   ) +
                   (SELECT COUNT(VLL.LISTVAL_ID)
                    FROM VALL VLL
                    WHERE VLL.PARAM_ID = 345
                    AND VLL.IS_DEL = 0
                    AND VLL.OBJ_ID = L39.OBJ_ID
                   ) +
                   (SELECT COUNT(VD.VAL)
                    FROM VALD VD
                    WHERE VD.PARAM_ID = 347
                    AND VD.IS_DEL = 0
                    AND VD.OBJ_ID = L39.OBJ_ID
                   )
            FROM LINKS L39
            WHERE L39.OBJ_TYPE_ID = 39
            AND L39.PARENT_ID = :OBJECT_ID
            AND L39.DATE_DEL IS NULL
            INTO :V$OBJ_ID, :V$TEMP
        DO
        BEGIN
            IF (:V$TEMP = 0) THEN
            BEGIN
                UPDATE LINKS L
                SET L.DATE_DEL = CURRENT_TIMESTAMP
                WHERE L.OBJ_ID = :V$OBJ_ID
                AND L.OBJ_TYPE_ID = 39
                AND DATE_DEL IS NULL;
            END
        END

        FOR
            SELECT L40.OBJ_ID,
                   (SELECT COUNT(VS.VAL)
                    FROM VALS VS
                    WHERE VS.PARAM_ID IN (342, 344)
                    AND VS.IS_DEL = 0
                    AND VS.OBJ_ID = L40.OBJ_ID
                   ) +
                   (SELECT COUNT(VLL.LISTVAL_ID)
                    FROM VALL VLL
                    WHERE VLL.PARAM_ID = 341
                    AND VLL.IS_DEL = 0
                    AND VLL.OBJ_ID = L40.OBJ_ID
                   ) +
                   (SELECT COUNT(VD.VAL)
                    FROM VALD VD
                    WHERE VD.PARAM_ID = 343
                    AND VD.IS_DEL = 0
                    AND VD.OBJ_ID = L40.OBJ_ID
                   )
            FROM LINKS L40
            WHERE L40.OBJ_TYPE_ID = 40
            AND L40.PARENT_ID = :OBJECT_ID
            AND L40.DATE_DEL IS NULL
            INTO :V$OBJ_ID, :V$TEMP
        DO
        BEGIN
            IF (:V$TEMP = 0) THEN
            BEGIN
                UPDATE LINKS L
                SET L.DATE_DEL = CURRENT_TIMESTAMP
                WHERE L.OBJ_ID = :V$OBJ_ID
                AND L.OBJ_TYPE_ID = 40
                AND DATE_DEL IS NULL;
            END
        END

        FOR
            SELECT L41.OBJ_ID,
                   (SELECT COUNT(VLL.LISTVAL_ID)
                    FROM VALL VLL
                    WHERE VLL.PARAM_ID IN (350, 351)
                    AND VLL.IS_DEL = 0
                    AND VLL.OBJ_ID = L41.OBJ_ID
                   ) +
                   (SELECT COUNT(VI.VAL)
                    FROM VALI VI
                    WHERE VI.PARAM_ID = 349
                    AND VI.IS_DEL = 0
                    AND VI.OBJ_ID = L41.OBJ_ID
                   )
            FROM LINKS L41
            WHERE L41.OBJ_TYPE_ID = 41
            AND L41.PARENT_ID = :OBJECT_ID
            AND L41.DATE_DEL IS NULL
            INTO :V$OBJ_ID, :V$TEMP
        DO
        BEGIN
            IF (:V$TEMP = 0) THEN
            BEGIN
                UPDATE LINKS L
                SET L.DATE_DEL = CURRENT_TIMESTAMP
                WHERE L.OBJ_ID = :V$OBJ_ID
                AND L.OBJ_TYPE_ID = 41
                AND DATE_DEL IS NULL;
            END
        END

        FOR
            SELECT L42.OBJ_ID,
                   (SELECT COUNT(VLL.LISTVAL_ID)
                    FROM VALL VLL
                    WHERE VLL.PARAM_ID = 353
                    AND VLL.IS_DEL = 0
                    AND VLL.OBJ_ID = L42.OBJ_ID
                   ) +
                   (SELECT COUNT(VI.VAL)
                    FROM VALI VI
                    WHERE VI.PARAM_ID = 352
                    AND VI.IS_DEL = 0
                    AND VI.OBJ_ID = L42.OBJ_ID
                   )
            FROM LINKS L42
            WHERE L42.OBJ_TYPE_ID = 42
            AND L42.PARENT_ID = :OBJECT_ID
            AND L42.DATE_DEL IS NULL
            INTO :V$OBJ_ID, :V$TEMP
        DO
        BEGIN
            IF (:V$TEMP = 0) THEN
            BEGIN
                UPDATE LINKS L
                SET L.DATE_DEL = CURRENT_TIMESTAMP
                WHERE L.OBJ_ID = :V$OBJ_ID
                AND L.OBJ_TYPE_ID = 42
                AND DATE_DEL IS NULL;
            END
        END

        FOR
            SELECT L43.OBJ_ID,
                   (SELECT COUNT(VS.VAL)
                    FROM VALS VS
                    WHERE VS.PARAM_ID IN (355, 356)
                    AND VS.IS_DEL = 0
                    AND VS.OBJ_ID = L43.OBJ_ID
                   ) +
                   (SELECT COUNT(VD.VAL)
                    FROM VALD VD
                    WHERE VD.PARAM_ID = 354
                    AND VD.IS_DEL = 0
                    AND VD.OBJ_ID = L43.OBJ_ID
                   )
            FROM LINKS L43
            WHERE L43.OBJ_TYPE_ID = 43
            AND L43.PARENT_ID = :OBJECT_ID
            AND L43.DATE_DEL IS NULL
            INTO :V$OBJ_ID, :V$TEMP
        DO
        BEGIN
            IF (:V$TEMP = 0) THEN
            BEGIN
                UPDATE LINKS L
                SET L.DATE_DEL = CURRENT_TIMESTAMP
                WHERE L.OBJ_ID = :V$OBJ_ID
                AND L.OBJ_TYPE_ID = 43
                AND DATE_DEL IS NULL;
            END
        END

        FOR
            SELECT L44.OBJ_ID,
                   (SELECT COUNT(VS.VAL)
                    FROM VALS VS
                    WHERE VS.PARAM_ID = 358
                    AND VS.IS_DEL = 0
                    AND VS.OBJ_ID = L44.OBJ_ID
                   ) +
                   (SELECT COUNT(VD.VAL)
                    FROM VALD VD
                    WHERE VD.PARAM_ID = 357
                    AND VD.IS_DEL = 0
                    AND VD.OBJ_ID = L44.OBJ_ID
                   )
            FROM LINKS L44
            WHERE L44.OBJ_TYPE_ID = 44
            AND L44.PARENT_ID = :OBJECT_ID
            AND L44.DATE_DEL IS NULL
            INTO :V$OBJ_ID, :V$TEMP
        DO
        BEGIN
            IF (:V$TEMP = 0) THEN
            BEGIN
                UPDATE LINKS L
                SET L.DATE_DEL = CURRENT_TIMESTAMP
                WHERE L.OBJ_ID = :V$OBJ_ID
                AND L.OBJ_TYPE_ID = 44
                AND DATE_DEL IS NULL;
            END
        END

        FOR
            SELECT L31.OBJ_ID,
                   (SELECT COUNT(VS.VAL)
                    FROM VALS VS
                    WHERE VS.PARAM_ID IN (215, 324)
                    AND VS.IS_DEL = 0
                    AND VS.OBJ_ID = L31.OBJ_ID
                   ) +
                   (SELECT COUNT(VLL.LISTVAL_ID)
                    FROM VALL VLL
                    WHERE VLL.PARAM_ID = 214
                    AND VLL.IS_DEL = 0
                    AND VLL.OBJ_ID = L31.OBJ_ID
                   ) +
                   (SELECT COUNT(VD.VAL)
                    FROM VALD VD
                    WHERE VD.PARAM_ID = 213
                    AND VD.IS_DEL = 0
                    AND VD.OBJ_ID = L31.OBJ_ID
                   )
            FROM LINKS L31
            WHERE L31.OBJ_TYPE_ID = 31
            AND L31.PARENT_ID = :OBJECT_ID
            AND L31.DATE_DEL IS NULL
            INTO :V$OBJ_ID, :V$TEMP
        DO
        BEGIN
            IF (:V$TEMP = 0) THEN
            BEGIN
                UPDATE LINKS L
                SET L.DATE_DEL = CURRENT_TIMESTAMP
                WHERE L.OBJ_ID = :V$OBJ_ID
                AND L.OBJ_TYPE_ID = 31
                AND DATE_DEL IS NULL;
            END
        END

        FOR
            SELECT L37.OBJ_ID,
                   (SELECT COUNT(VS.VAL)
                    FROM VALS VS
                    WHERE VS.PARAM_ID = 1401
                    AND VS.IS_DEL = 0
                    AND VS.OBJ_ID = L37.OBJ_ID
                   ) +
                   (SELECT COUNT(VLL.LISTVAL_ID)
                    FROM VALL VLL
                    WHERE VLL.PARAM_ID IN (325, 326, 330)
                    AND VLL.IS_DEL = 0
                    AND VLL.OBJ_ID = L37.OBJ_ID
                   ) +
                   (SELECT COUNT(VD.VAL)
                    FROM VALD VD
                    WHERE VD.PARAM_ID IN (327, 328)
                    AND VD.IS_DEL = 0
                    AND VD.OBJ_ID = L37.OBJ_ID
                   )
            FROM LINKS L37
            WHERE L37.OBJ_TYPE_ID = 37
            AND L37.PARENT_ID = :OBJECT_ID
            AND L37.DATE_DEL IS NULL
            INTO :V$OBJ_ID, :V$TEMP
        DO
        BEGIN
            IF (:V$TEMP = 0) THEN
            BEGIN
                UPDATE LINKS L
                SET L.DATE_DEL = CURRENT_TIMESTAMP
                WHERE L.OBJ_ID = :V$OBJ_ID
                AND L.OBJ_TYPE_ID = 37
                AND DATE_DEL IS NULL;
            END
        END

        FOR
            SELECT L100.OBJ_ID,
                   (SELECT COUNT(VS.VAL)
                    FROM VALS VS
                    WHERE VS.PARAM_ID = 619
                    AND VS.IS_DEL = 0
                    AND VS.OBJ_ID = L100.OBJ_ID
                    AND TRIM(VS.VAL) <> ''
                   ) +
                   (SELECT COUNT(VLL.LISTVAL_ID)
                    FROM VALL VLL
                    WHERE VLL.PARAM_ID IN (615, 616, 617)
                    AND VLL.IS_DEL = 0
                    AND VLL.OBJ_ID = L100.OBJ_ID
                   ) +
                   (SELECT 1
                    FROM VAL_GET(L100.OBJ_ID, 618)
                    WHERE TRIM(V) <> ''
                   )
            FROM LINKS L100
            WHERE L100.OBJ_TYPE_ID = 100
            AND L100.PARENT_ID = :OBJECT_ID
            AND L100.DATE_DEL IS NULL
            INTO :V$OBJ_ID, :V$TEMP
        DO
        BEGIN
            IF (:V$TEMP = 0) THEN
            BEGIN
                UPDATE LINKS L
                SET L.DATE_DEL = CURRENT_TIMESTAMP
                WHERE L.OBJ_ID = :V$OBJ_ID
                AND L.OBJ_TYPE_ID = 100
                AND DATE_DEL IS NULL;
            END
        END

        FOR
            SELECT L101.OBJ_ID,
                   (SELECT COUNT(VS.VAL)
                    FROM VALS VS
                    WHERE VS.PARAM_ID = 622
                    AND VS.IS_DEL = 0
                    AND VS.OBJ_ID = L101.OBJ_ID
                    AND TRIM(VS.VAL) <> ''
                   ) +
                   (SELECT COUNT(VLI.VAL)
                    FROM VALI VLI
                    WHERE VLI.PARAM_ID IN (904)
                    AND VLI.IS_DEL = 0
                    AND VLI.OBJ_ID = L101.OBJ_ID
                    AND VLI.VAL > 0
                   ) +
                   (SELECT COUNT(VLL.LISTVAL_ID)
                    FROM VALL VLL
                    WHERE VLL.PARAM_ID IN (620)
                    AND VLL.IS_DEL = 0
                    AND VLL.OBJ_ID = L101.OBJ_ID
                   ) +
                   (SELECT 1
                    FROM VAL_GET(L101.OBJ_ID, 621)
                    WHERE TRIM(V) <> ''
                   )
            FROM LINKS L101
            WHERE L101.OBJ_TYPE_ID = 101
            AND L101.PARENT_ID = :OBJECT_ID
            AND L101.DATE_DEL IS NULL
            INTO :V$OBJ_ID, :V$TEMP
        DO
        BEGIN
            IF (:V$TEMP = 0) THEN
            BEGIN
                UPDATE LINKS L
                SET L.DATE_DEL = CURRENT_TIMESTAMP
                WHERE L.OBJ_ID = :V$OBJ_ID
                AND L.OBJ_TYPE_ID = 101
                AND DATE_DEL IS NULL;
            END
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DO_CHECK (
    I$OBJ_ID BIGINT,
    I$PARAM_ID BIGINT,
    I$VAL VARCHAR(4000),
    I$DO_CHECK SMALLINT = 0,
    I$DO_CHECK_EVENT SMALLINT = 0)
RETURNS (
    IS_OK SMALLINT,
    MSG VARCHAR(4000))
AS
DECLARE VARIABLE V$DT DATE;
DECLARE VARIABLE V$X SMALLINT;
DECLARE VARIABLE V$CAPTION VARCHAR(1000);
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$OBJ_ID1 BIGINT;
DECLARE VARIABLE V$OBJ_ID2 BIGINT;
DECLARE VARIABLE V$OU_LICENCE_TYPE VARCHAR(1);
DECLARE VARIABLE V$VAL DOUBLE PRECISION;
DECLARE VARIABLE N INTEGER;
DECLARE VARIABLE S VARCHAR(100);
DECLARE VARIABLE V$ALLOWED VARCHAR(400);
BEGIN
    /* I$DO_CHECK_EVENT = 1 - before open edit window*/
    /* I$DO_CHECK_EVENT = 2 - after OK button click in edit window*/
    IS_OK = 1;
    V$X = 0;
    MSG = '';

    IF (I$DO_CHECK = 1) THEN
    /* Лимит по дате рождения ученика */
    BEGIN
        V$DT = I$VAL;
        SELECT STATUS FROM OU_LICENCE_TYPE INTO :V$OU_LICENCE_TYPE;
        V$X = IIF(:V$OU_LICENCE_TYPE IN ('D', 'U'), 0, 3);
        -- V$X = 0;
        IF ((CURRENT_DATE - V$DT) <= (365 * :V$X)) THEN
        BEGIN
            IS_OK = 0;
            SELECT WORD
            FROM REPORT_WORDS
            WHERE ID = 1001
            INTO :MSG;
        END

        -- 100
        V$X = CASE :V$OU_LICENCE_TYPE WHEN 'D' THEN 20 WHEN 'U' THEN 50 WHEN 'C' THEN 100 ELSE 70 END;

        IF ((CURRENT_DATE - V$DT) > (365 * :V$X)) THEN
        BEGIN
            IS_OK = 0;
            SELECT WORD
            FROM REPORT_WORDS
            WHERE ID = 1001
            INTO :MSG;
        END
    END
    ELSE IF (I$DO_CHECK = 2) THEN
    /* birthday of worker */
    BEGIN
        V$DT = I$VAL;
        IF ((CURRENT_DATE -V$DT) < (365 * 14)) THEN
        BEGIN
            IS_OK = 0;
            SELECT WORD
            FROM REPORT_WORDS
            WHERE ID = 1001
            INTO :MSG;
        END
        IF ((CURRENT_DATE -V$DT) > (365 * 100)) THEN
        BEGIN
            IS_OK = 0;
            SELECT WORD
            FROM REPORT_WORDS
            WHERE ID = 1001
            INTO :MSG;
        END
    END
    ELSE IF (I$DO_CHECK = 3) THEN
    /* educational period */
    BEGIN
        IF (:I$DO_CHECK_EVENT = 1) THEN
        BEGIN
            SELECT COUNT(*)
            FROM VALD V
            WHERE V.PARAM_ID = 1169
            AND V.OBJ_ID = :I$OBJ_ID
            AND V.IS_DEL = 0
            INTO IS_OK;

            IF (IS_OK = 0) THEN
            BEGIN
                SELECT WORD
                FROM REPORT_WORDS
                WHERE ID = 1003
                INTO :MSG;
            END
        END

        IF (:I$DO_CHECK_EVENT = 2) THEN
        BEGIN
            SELECT COUNT(*)
            FROM VALD V
            WHERE V.PARAM_ID = 1169
            AND V.OBJ_ID = :I$OBJ_ID
            AND V.IS_DEL = 0
            AND V.VAL < :I$VAL
            INTO :IS_OK;

            IF (IS_OK = 0) THEN
            BEGIN
                SELECT WORD
                FROM REPORT_WORDS
                WHERE ID = 1004
                INTO :MSG;
            END
        END
    END
    ELSE IF (I$DO_CHECK = 4) THEN
    /* class name */
    BEGIN
        V$X = 0;

        SELECT FIRST 1 1
        FROM LINKS L8
        JOIN LINKS L9 ON L9.PARENT_ID = L8.PARENT_ID AND L9.OBJ_ID <> :I$OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
        JOIN VALS V54 ON V54.OBJ_ID = L9.OBJ_ID AND V54.PARAM_ID = 54 AND V54.IS_DEL = 0 AND V54.VAL = :I$VAL
        WHERE L8.OBJ_ID = :I$OBJ_ID AND L8.PARENT_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
        INTO :V$X;

        SELECT FIRST 1 1
        FROM LINKS L8
        JOIN LINKS L125 ON L125.PARENT_ID = L8.PARENT_ID AND L125.OBJ_ID <> :I$OBJ_ID AND L125.OBJ_TYPE_ID = 125 AND L125.DATE_DEL IS NULL
        JOIN VALS V820 ON V820.OBJ_ID = L125.OBJ_ID AND V820.PARAM_ID = 820 AND V820.IS_DEL = 0 AND V820.VAL = :I$VAL
        WHERE L8.OBJ_ID = :I$OBJ_ID AND L8.PARENT_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
        INTO :V$X;

        IF (V$X = 1) THEN
        BEGIN
            IS_OK = 0;
            SELECT WORD
            FROM REPORT_WORDS
            WHERE ID = 1005
            INTO :MSG;
        END
    END
    ELSE IF (I$DO_CHECK = 5) THEN
    /* stage name */
    BEGIN
        V$X = 0;

        SELECT FIRST 1 L7.OBJ_ID
        FROM LINKS L2
        JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.OBJ_ID = :I$OBJ_ID AND L8.DATE_DEL IS NULL
        WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
        INTO :V$OBJ_ID;

        SELECT FIRST 1 1
        FROM LINKS L8
        JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0 AND V49.LISTVAL_ID = :I$VAL
        WHERE L8.PARENT_ID = :V$OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.OBJ_ID <> :I$OBJ_ID AND L8.DATE_DEL IS NULL
        INTO :V$X;

        IF (V$X = 1) THEN
        BEGIN
            IS_OK = 0;
            SELECT WORD
            FROM REPORT_WORDS
            WHERE ID = 1006
            INTO :MSG;
        END
    END
    ELSE IF (I$DO_CHECK = 6) THEN
    /* grade name */
    BEGIN
        V$X = 0;

        SELECT FIRST 1 L2.OBJ_ID
        FROM LINKS L2
        WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
        INTO :V$OBJ_ID;

        SELECT FIRST 1 1
        FROM LINKS L7
        JOIN VALL V43 ON V43.OBJ_ID = L7.OBJ_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0 AND V43.LISTVAL_ID = :I$VAL
        WHERE L7.PARENT_ID = :V$OBJ_ID AND L7.OBJ_ID <> :I$OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
        INTO :V$X;

        IF (V$X = 1) THEN
        BEGIN
            IS_OK = 0;
            SELECT WORD
            FROM REPORT_WORDS
            WHERE ID = 1007
            INTO :MSG;
        END
    END
    ELSE IF (I$DO_CHECK = 7) THEN
    /* SNILS */
    BEGIN
        SELECT IS_REAL
        FROM CHECK_SNILS(:I$VAL)
        INTO :IS_OK;

        IF (IS_OK = 0) THEN
        BEGIN
            SELECT WORD
            FROM REPORT_WORDS
            WHERE ID = 1008
            INTO :MSG;
        END
    END
    ELSE IF (I$DO_CHECK = 8) THEN
    BEGIN
        IF (I$DO_CHECK_EVENT = 2) THEN
        BEGIN
            /*ИНВЕНТАРИЗАЦИОННАЯ КАРТОЧКА, ИНВЕНТАРНЫЙ НОМЕР*/
            FOR
                SELECT FIRST 1 VS.OBJ_ID
                FROM VALS VS
                JOIN LINKS L ON L.OBJ_ID = VS.OBJ_ID AND L.DATE_DEL IS NULL
                WHERE VS.OBJ_ID <> :I$OBJ_ID AND VS.PARAM_ID = :I$PARAM_ID AND VS.VAL LIKE :I$VAL AND VS.IS_DEL = 0
                INTO :V$OBJ_ID
            DO
            BEGIN
                IS_OK = 0;
                SELECT CAPTION
                FROM OBJECT_CAPTION_GET(:V$OBJ_ID)
                INTO :V$CAPTION;
    
                MSG = 'Вводимый номер присутствует в базе: ' || V$CAPTION;
            END
        END
    END
    ELSE IF (I$DO_CHECK = 9) THEN
    BEGIN
        IF (I$DO_CHECK_EVENT = 2) THEN
        BEGIN
            /*Должность, название*/
            -- Для УДОД и Мультипараграфа необходимо вести учет должностей в рамках своего подразделения
            IF ((SELECT STATUS FROM OU_LICENCE_TYPE) = 'U') THEN
            BEGIN
                SELECT FIRST 1 L13.PARENT_ID
                FROM LINKS L13
                WHERE L13.PARENT_TYPE_ID = 211 AND L13.OBJ_ID = :I$OBJ_ID AND L13.DATE_DEL IS NULL
                INTO :V$OBJ_ID1;
            END
            ELSE IF ((SELECT STATUS FROM OU_LICENCE_TYPE) = 'S') THEN
            BEGIN
                SELECT FIRST 1 L13.PARENT_ID
                FROM LINKS L13
                WHERE L13.PARENT_TYPE_ID IN (2, 211) AND L13.OBJ_ID = :I$OBJ_ID AND L13.DATE_DEL IS NULL
                INTO :V$OBJ_ID1;
            END

            -- Ищем есть ли должность с такие названием
            FOR
                SELECT FIRST 1 VS.OBJ_ID
                FROM VALS VS
                JOIN LINKS L ON L.OBJ_ID = VS.OBJ_ID AND L.DATE_DEL IS NULL
                WHERE VS.OBJ_ID <> :I$OBJ_ID AND VS.PARAM_ID = :I$PARAM_ID AND UPPER(TRIM(VS.VAL)) = UPPER(TRIM(:I$VAL))
                  AND VS.IS_DEL = 0 AND (:V$OBJ_ID1 IS NULL OR L.PARENT_ID = :V$OBJ_ID1)
                INTO :V$OBJ_ID
            DO
            BEGIN
                IS_OK = 0;

                MSG = 'Такая должность уже существует.';
            END
        END
    END
    ELSE IF (I$DO_CHECK = 10) THEN
    BEGIN
        IF (I$DO_CHECK_EVENT = 2) THEN
        BEGIN
            /*Идентификатор ученика на портале, должен быть уникальным*/
            FOR
                SELECT FIRST 1 LP10.OBJ_ID, LP10.PARENT_ID, LP9.PARENT_ID
                FROM VALS VS
                JOIN LINKS LP10 ON LP10.EXT_OBJ_ID = VS.OBJ_ID AND LP10.DATE_DEL IS NULL AND LP10.PARENT_TYPE_ID = 10 AND LP10.OBJ_TYPE_ID = 20
                JOIN LINKS LP9 ON LP9.OBJ_ID = LP10.PARENT_ID AND LP9.DATE_DEL IS NULL AND LP9.PARENT_TYPE_ID = 9
                WHERE VS.OBJ_ID <> :I$OBJ_ID AND VS.PARAM_ID = :I$PARAM_ID AND VS.VAL = :I$VAL AND VS.IS_DEL = 0
                INTO :V$OBJ_ID, :V$OBJ_ID1, :V$OBJ_ID2
            DO
            BEGIN
                IS_OK = 0;
                SELECT CAPTION
                FROM OBJECT_CAPTION_GET(:V$OBJ_ID2, 50)
                INTO :V$CAPTION;

                MSG = 'Идентификатор уже используется: ' || V$CAPTION;
                SELECT CAPTION
                FROM OBJECT_CAPTION_GET(:V$OBJ_ID1, 50)
                INTO :V$CAPTION;
                MSG = MSG || ', ученик ' || V$CAPTION;
                SELECT CAPTION
                FROM OBJECT_CAPTION_GET(:V$OBJ_ID, 50)
                INTO :V$CAPTION;
                MSG = MSG || ', родитель ' || V$CAPTION || '.';
            END
        END
    END
    ELSE IF (I$DO_CHECK = 11) THEN
    /* additional education group type */
    BEGIN
        V$X = 0;

        SELECT FIRST 1 L2.OBJ_ID
        FROM LINKS L2
        WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
        INTO :V$OBJ_ID;

        SELECT FIRST 1 1
        FROM LINKS L86
        JOIN VALL V1579 ON V1579.OBJ_ID = L86.OBJ_ID AND V1579.PARAM_ID = 1579 AND V1579.IS_DEL = 0 AND V1579.LISTVAL_ID = :I$VAL
        WHERE L86.PARENT_ID = :V$OBJ_ID AND L86.OBJ_ID <> :I$OBJ_ID AND L86.OBJ_TYPE_ID = 86 AND L86.DATE_DEL IS NULL
        INTO :V$X;

        IF (V$X = 1) THEN
        BEGIN
            IS_OK = 0;
            SELECT WORD
            FROM REPORT_WORDS
            WHERE ID = 1009
            INTO :MSG;
        END
    END
    ELSE IF (I$DO_CHECK = 12) THEN
    /* education program code check */
    BEGIN
        IF(NOT EXISTS(
            SELECT LISTVAL_ID
            FROM LISTVALS
            WHERE LIST_ID IN (244, 298) AND TAG = :I$VAL
        )) THEN
        BEGIN
            IS_OK = 0;
            SELECT WORD
            FROM REPORT_WORDS
            WHERE ID = 1011
            INTO :MSG;
        END
    END
    ELSE IF (I$DO_CHECK = 13) THEN
    BEGIN
        IF (EXISTS(
            SELECT FIRST 1 1
            FROM VALR
            WHERE OBJ_ID <> :I$OBJ_ID AND PARAM_ID = :I$PARAM_ID AND IS_DEL = 0 AND VAL = :I$VAL
        )) THEN
        BEGIN
            IS_OK = 2;
            SELECT WORD
            FROM REPORT_WORDS
            WHERE ID = 1012
            INTO :MSG;
        END
    END
    ELSE IF (I$DO_CHECK = 101) THEN
    BEGIN
        SELECT WORD
        FROM REPORT_WORDS
        WHERE ID = 1010
        INTO :MSG;

        IS_OK = 69;
    END
    ELSE IF (I$DO_CHECK = 102) THEN
    BEGIN
        -- Проверка номера и серии идентифицирующего документа
        -- Номер должен быть из 6 цифр
        SELECT FIRST 1 V441.LISTVAL_ID
        FROM VALL V441
        WHERE V441.OBJ_ID = :I$OBJ_ID AND V441.PARAM_ID = 441 AND V441.IS_DEL = 0
        INTO :V$OBJ_ID;

        IS_OK = 1;

        -- Все поля - не допускаются пробелы в начале, конце, двойные в середине
        IF(SUBSTRING(I$VAL FROM 1 FOR 1) = ' ' OR SUBSTRING(I$VAL FROM CHAR_LENGTH(I$VAL) FOR 1) = ' ' OR POSITION('  ' IN I$VAL) > 0) THEN
        BEGIN
          IS_OK = 0;
          MSG = 'Номер и серия не могут начинаться с пробела, оканчиваться пробелом или содержать двойные пробелы';
        END

        -- Номер (свидетельство о рождении, паспорт РФ)
        -- требуется непустое значение
        IF(I$PARAM_ID = 559 AND V$OBJ_ID IN (1370, 1368)) THEN
        BEGIN
          IF(I$VAL IS NULL OR I$VAL NOT SIMILAR TO '[0-9]{6}' ESCAPE '\') THEN
          BEGIN
            IS_OK = 0;
            MSG = 'Некорректный формат номера для свидетельства о рождении или паспорта РФ';
          END
        END
        -- Серия, свидетельство о рождении
        ELSE IF(I$PARAM_ID = 442 AND V$OBJ_ID = 1370) THEN
        BEGIN
          IF(I$VAL IS NULL OR CHAR_LENGTH(I$VAL) < 3 OR POSITION('-' IN I$VAL) <= 0 OR POSITION(' ' IN I$VAL) > 0) THEN
          BEGIN
            IS_OK = 0;
            MSG = 'Некорректный формат серии для свидетельства о рождении';
          END
        END
        -- Серия, паспорт
        ELSE IF(I$PARAM_ID = 442 AND V$OBJ_ID = 1368) THEN
        BEGIN
          IF(I$VAL IS NULL OR I$VAL NOT SIMILAR TO '[0-9]{4}' ESCAPE '\') THEN
          BEGIN
            IS_OK = 0;
            MSG = 'Некорректный формат серии для паспорта РФ';
          END
        END

        -- Шаблон номера
        V$ALLOWED = '0123456789';
        -- Для российского свидетельства разрешаем некоторое количество букв
        IF(I$PARAM_ID = 442 AND V$OBJ_ID = 1370) THEN V$ALLOWED = V$ALLOWED || '-IVXCLMАБВГДЕЖЗИКЛМНОПРСТУФХЦЧШЩЪЬЫЭЮЯ';
        -- Для остальных документов разрешаем полную раскладку, паспорт уже учтен
        ELSE V$ALLOWED = V$ALLOWED || ' -.,/\АБВГДЕЖЗИКЛМНОПРСТУФХЦЧШЩЪЬЫЭЮЯABCDEFGHIJKLMNOPQRSTUVWXYZ#*:;';

        -- Разрешаются только русские и латинские буквы, цифры, пробел, слэши, дефис, точка, запятая
        WHILE(CHAR_LENGTH(I$VAL) > 0) DO
        BEGIN
          S = UPPER(SUBSTRING(I$VAL FROM 1 FOR 1));
          IF(POSITION(S IN V$ALLOWED) <= 0) THEN
          BEGIN
            IS_OK = 0;
            MSG = 'Недопустимый символ ' || S || ' в серии или номере документа';
          END

          I$VAL = SUBSTRING(I$VAL FROM 2);
        END
    END
    ELSE IF (I$DO_CHECK = 103) THEN
    /* ИНН */
    BEGIN
        SELECT IS_REAL
        FROM CHECK_INN(:I$VAL)
        INTO :IS_OK;

        IF (IS_OK = 0) THEN
        BEGIN
            SELECT WORD
            FROM REPORT_WORDS
            WHERE ID = 1008
            INTO :MSG;
        END
    END
    ELSE IF (I$DO_CHECK = 104) THEN
    /* ОГРН */
    BEGIN
        SELECT IS_REAL
        FROM CHECK_OGRN(:I$VAL)
        INTO :IS_OK;

        IF (IS_OK = 0) THEN
        BEGIN
            SELECT WORD
            FROM REPORT_WORDS
            WHERE ID = 1008
            INTO :MSG;
        END
    END
    ELSE IF (I$DO_CHECK = 105) THEN
    /* Площадь здания, помещения */
    BEGIN
        V$VAL = I$VAL;
        IS_OK = 1;
        IF(V$VAL < 1 OR V$VAL > 100000) THEN
        BEGIN
          IS_OK = 0;
          MSG = 'Недопустимое значение площади';
        END
    END
    -- Кадастовый номер
    -- Проверяем на 3..6 групп цифр, разделенных двоеточиями
    ELSE IF (I$DO_CHECK = 106) THEN
    BEGIN
        N = 0;
        IF(RIGHT(I$VAL, 1) = ':') THEN EXCEPTION DATA_ERROR 'Кадастовый номер не может оканчиваться двоеточием';
        WHILE(CHAR_LENGTH(I$VAL) > 0) DO
        BEGIN
            V$X = POSITION(':' IN I$VAL);
            IF(V$X <= 0) THEN V$X = CHAR_LENGTH(I$VAL) + 1;
            V$CAPTION = SUBSTRING(I$VAL FROM 1 FOR V$X - 1);
            I$VAL = SUBSTRING(I$VAL FROM V$X + 1);
            N = N + 1;
            IF(CHAR_LENGTH(V$CAPTION) < 1 OR CHAR_LENGTH(V$CAPTION) > 7) THEN EXCEPTION DATA_ERROR 'Каждая группа цифр в номере может быть от 1 до 7 символов';
            WHILE(CHAR_LENGTH(V$CAPTION) > 0) DO
            BEGIN
                IF(SUBSTRING(V$CAPTION FROM 1 FOR 1) NOT IN ('0', '1', '2', '3', '4', '5', '6', '7', '8', '9')) THEN EXCEPTION DATA_ERROR 'Номер может содержать только цифры и двоеточия';
                V$CAPTION = SUBSTRING(V$CAPTION FROM 2);
            END
        END
        IF(N < 3 OR N > 6) THEN EXCEPTION DATA_ERROR 'Кадастовый номер может содержать от 3 до 6 групп цифр';
    END

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DO_FAM_FIELD (
    I$OBJ_ID BIGINT,
    I$PARAM_ID BIGINT)
RETURNS (
    VAL VARCHAR(400))
AS
declare variable V$STUDENT_ID bigint;
declare variable V$SUBJECT_ID bigint;
declare variable V$STAGE_ID bigint;
declare variable V$MARK_DATE date;
declare variable V$MT varchar(100);
begin

  SELECT LP10.PARENT_ID
  FROM LINKS LP10
  WHERE LP10.OBJ_ID = :I$OBJ_ID AND LP10.PARENT_TYPE_ID = 10 AND LP10.DATE_DEL IS NULL
  INTO :V$STUDENT_ID;

  SELECT V.LISTVAL_ID
  FROM VALL V
  WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 3142 AND V.IS_DEL = 0
  INTO :V$STAGE_ID;

  SELECT V.VAL
  FROM VALR V
  WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 3143 AND V.IS_DEL = 0
  INTO :V$SUBJECT_ID;

  SELECT FIRST 1 M.MARK_DATE, R.VAL
  FROM VALM M
  JOIN LISTVALS LV ON LV.LISTVAL_ID = M.MARKVAL_ID
  JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
  WHERE M.PUPIL_ID = :V$STUDENT_ID AND M.SUBJECT_ID = :V$SUBJECT_ID AND M.STAGE_ID = :V$STAGE_ID
  INTO :V$MARK_DATE, :V$MT;

  IF(I$PARAM_ID = 3145) THEN VAL = V$MT;
  ELSE IF(I$PARAM_ID = 3146) THEN VAL = (SELECT RESULT FROM DATE2STR(:V$MARK_DATE));

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DO_FUNC (
    I$OBJ_ID BIGINT,
    I$PARAM_ID BIGINT,
    I$DO_FUNC BIGINT = null,
    I$AUTO_LISTVAL_ID BIGINT = null,
    I$USER_ID BIGINT = null,
    I$PARENT_ID BIGINT = null)
RETURNS (
    VAL VARCHAR(4000),
    I BIGINT,
    SORT_ORDER DOUBLE PRECISION)
AS
declare variable V$Y1 smallint;
declare variable V$M1 smallint;
declare variable V$D1 smallint;
declare variable V$Y2 smallint;
declare variable V$M2 smallint;
declare variable V$D2 smallint;
declare variable V$VAL smallint;
declare variable BEGIN_DATE date;
declare variable END_DATE date;
declare variable DAYS360 integer;
declare variable V varchar(4000);
declare variable V$OBJ_ID bigint;
declare variable KEY_LEVEL varchar(1);
declare variable LANG_CODE varchar(2);
declare variable CNT integer;
declare variable V$I integer;
declare variable V$PARENT_ID bigint;
declare variable N bigint;
BEGIN
    I = 0;
    SELECT K.KEY_VAL
    FROM KEYS K
    WHERE K.KEY_CODE = 'LEVEL'
    INTO :KEY_LEVEL;

    LANG_CODE = 'RU';

    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :LANG_CODE;

    SORT_ORDER = 0;
    IF (I$DO_FUNC IS NULL OR I$AUTO_LISTVAL_ID IS NULL) THEN
    BEGIN
        SELECT FIRST 1 P.DO_FUNC, P.AUTO_LISTVAL_ID
        FROM OBJECTS O
        JOIN PARAMS P ON P.TYPE_ID = O.TYPE_ID AND P.PARAM_ID = :I$PARAM_ID AND P.IS_DEL = 0
        JOIN LPARAMS L ON P.PARAM_ID = L.PARAM_ID AND L.IS_DEL = 0
        JOIN PARAMTYPES PT ON PT.PARAM_TYPE = P.PARAM_TYPE
        WHERE O.OBJ_ID = :I$OBJ_ID AND P.PARAM_ID = :I$PARAM_ID
        INTO :I$DO_FUNC, :I$AUTO_LISTVAL_ID;
    END

    IF (I$DO_FUNC IS NOT NULL) THEN
    BEGIN
        IF (I$DO_FUNC IN (1, 48)) THEN
        /*OLD*/
        BEGIN
            SELECT FIRST 1 EXTRACT(YEAR FROM D), EXTRACT(MONTH FROM D), EXTRACT(DAY FROM D), EXTRACT(YEAR FROM CURRENT_DATE), EXTRACT(MONTH FROM CURRENT_DATE), EXTRACT(DAY FROM CURRENT_DATE)
            FROM VAL_TAG_GET(:I$OBJ_ID, 'BIRTHDATE')
            INTO :V$Y1, :V$M1, :V$D1, :V$Y2, :V$M2, :V$D2;
            V$VAL = V$Y2 - V$Y1;
            IF ((V$M2 * 32 + V$D2) < (V$M1 * 32 + V$D1)) THEN
            BEGIN
                V$VAL = V$VAL - 1;
            END
            VAL = CAST(V$VAL AS VARCHAR(4000));
            SORT_ORDER = V$VAL;
            IF (I$DO_FUNC = 48) THEN
            BEGIN
                -- year
                IF (V$VAL > 0) THEN
                BEGIN
                    VAL = V$VAL || IIF(V$VAL = 1, ' г. ', ' л. ');
                END
                -- month
                V$VAL = V$M2 - V$M1;
                IF (V$D2 < V$D1) THEN
                BEGIN
                    V$VAL = V$VAL - 1;
                END
                IF (V$VAL < 0) THEN
                BEGIN
                    V$VAL = V$VAL + 12;
                END
                IF (V$VAL > 0) THEN
                BEGIN
                    VAL = VAL || V$VAL ||  ' м. ';
                END
                -- day
                V$VAL = V$D2 - V$D1;
                IF (V$VAL < 0) THEN
                BEGIN
                    V$VAL = V$VAL + 32;
                END
                IF (V$VAL > 0) THEN
                BEGIN
                    VAL = VAL || V$VAL || ' д.';
                END
                VAL = TRIM(VAL);
            END
        END
        ELSE
        IF (I$DO_FUNC = 2) THEN
        /*SENIORITY*/
        BEGIN
            DAYS360 = 0;
            FOR
                SELECT V466.VAL, V467.VAL
                FROM LINKS L85
                JOIN VALL V465 ON V465.OBJ_ID = L85.OBJ_ID AND V465.PARAM_ID = 465 AND V465.IS_DEL = 0
                JOIN VALD V466 ON V466.OBJ_ID = L85.OBJ_ID AND V466.PARAM_ID = 466 AND V466.IS_DEL = 0
                LEFT JOIN VALD V467 ON V467.OBJ_ID = L85.OBJ_ID AND V467.PARAM_ID = 467 AND V467.IS_DEL = 0
                WHERE L85.PARENT_ID = :I$OBJ_ID AND L85.OBJ_TYPE_ID = 85 AND L85.DATE_DEL IS NULL AND V465.LISTVAL_ID = :I$AUTO_LISTVAL_ID
                INTO :BEGIN_DATE, :END_DATE
            DO
            BEGIN
                /* PROCEDURE GET_DAYS360_COUNT */
                SELECT :DAYS360 + DAYS360_COUNT
                FROM GET_DAYS360_COUNT(:BEGIN_DATE, :END_DATE)
                INTO :DAYS360;
            END
            VAL = DAYS360;
            SORT_ORDER = 1;
        END
        ELSE IF (I$DO_FUNC = 3) THEN
        /*CLASS PUPILCOUNT*/
        BEGIN
            SELECT COUNT(*)
            FROM LINKS L
            WHERE L.PARENT_ID = :I$OBJ_ID AND L.DATE_DEL IS NULL AND L.OBJ_TYPE_ID = 10
            INTO :VAL;

            SORT_ORDER = VAL;
        END
        ELSE IF (I$DO_FUNC = 4) THEN
        /*CLASS GIRLS PUPILCOUNT*/
        BEGIN
            SELECT COUNT(*)
            FROM LINKS L
            JOIN VALL V ON V.OBJ_ID = L.OBJ_ID AND V.PARAM_ID = 88 AND V.LISTVAL_ID = 182 AND V.IS_DEL = 0
            WHERE L.PARENT_ID = :I$OBJ_ID AND L.DATE_DEL IS NULL AND L.OBJ_TYPE_ID = 10
            INTO :VAL;
            SORT_ORDER = VAL;
        END
        ELSE IF (I$DO_FUNC = 5) THEN
        /*CLASS BOYS PUPILCOUNT*/
        BEGIN
            SELECT COUNT(*)
            FROM LINKS L
            JOIN VALL V ON V.OBJ_ID = L.OBJ_ID AND V.PARAM_ID = 88 AND V.LISTVAL_ID = 183 AND V.IS_DEL = 0
            WHERE L.PARENT_ID = :I$OBJ_ID AND L.DATE_DEL IS NULL AND L.OBJ_TYPE_ID = 10
            INTO :VAL;
            SORT_ORDER = VAL;
        END
        ELSE IF (I$DO_FUNC = 9) THEN
        /* STAGE PUPILCOUNT*/
        BEGIN
            SELECT COUNT(*)
            FROM LINKS L9
            JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
            WHERE L9.PARENT_ID = :I$OBJ_ID AND L9.OBJ_TYPE_ID IN (9,243) AND L9.DATE_DEL IS NULL
            INTO :VAL;
            SORT_ORDER = VAL;
        END
        ELSE IF (I$DO_FUNC = 10) THEN
        /* STAGE GIRLS PUPILCOUNT*/
        BEGIN
            SELECT COUNT(*)
            FROM LINKS L9
            JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
            JOIN VALL V88 ON V88.OBJ_ID = L10.OBJ_ID AND V88.PARAM_ID = 88 AND V88.LISTVAL_ID = 182 AND V88.IS_DEL = 0
            WHERE L9.PARENT_ID = :I$OBJ_ID AND L9.OBJ_TYPE_ID IN (9,243) AND L9.DATE_DEL IS NULL
            INTO :VAL;
            SORT_ORDER = VAL;
        END
        ELSE IF (I$DO_FUNC = 11) THEN
        /* STAGE BOY PUPILCOUNT*/
        BEGIN
            SELECT COUNT(*)
            FROM LINKS L9
            JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
            JOIN VALL V88 ON V88.OBJ_ID = L10.OBJ_ID AND V88.PARAM_ID = 88 AND V88.LISTVAL_ID = 183 AND V88.IS_DEL = 0
            WHERE L9.PARENT_ID = :I$OBJ_ID AND L9.OBJ_TYPE_ID IN (9,243) AND L9.DATE_DEL IS NULL
            INTO :VAL;

            SORT_ORDER = VAL;
        END
        ELSE IF (I$DO_FUNC IN (6, 7, 8, 12, 13, 14, 58, 61, 62, 63, 1039)) THEN
        -- чтобы уменьшить количество вложенных вызовов
        --  6 - SCHOOL PUPILCOUNT
        --  7 - SCHOOL GIRLS PUPILCOUNT
        --  8 - SCHOOL BOY PUPILCOUNT
        -- 12 - GRADE PUPILCOUNT
        -- 13 - GRADE GIRLS PUPILCOUNT
        -- 13 - GRADE BOY PUPILCOUNT
        -- 58 - FOR PARAM_ID = 2341 (akademicheski otpusk)
        -- 61 - DISRICT PUPILCOUNT
        -- 62 - DISRICT GIRLS PUPILCOUNT
        -- 63 - DISRICT BOY PUPILCOUNT
        -- 1039 - Количество учеников по учебному плану
        BEGIN
            SELECT VAL
            FROM DO_FUNC_COUNT(:I$OBJ_ID, :I$DO_FUNC)
            INTO :VAL;

            SORT_ORDER = VAL;
        END
        ELSE IF (I$DO_FUNC = 15) THEN
        /* Признак педагог/не-педагог */
        BEGIN
            SELECT X, VALID FROM IS_TEACHER(:I$OBJ_ID) INTO :SORT_ORDER, :V$I;
            IF(V$I = 0) THEN VAL = 'Не определено';
            ELSE IF(SORT_ORDER = 1) THEN VAL = 'Да';
            ELSE VAL = 'Нет';
        END
        ELSE IF (I$DO_FUNC = 16) THEN
        /* Количество сотрудников ОО или выбранного отдела ОО */
        BEGIN
            SELECT COUNT(*) FROM (
                SELECT DISTINCT L14.OBJ_ID
                FROM LINKS L14
                WHERE L14.DATE_DEL IS NULL AND L14.OBJ_TYPE_ID = 14 AND L14.PARENT_ID = :I$OBJ_ID
                UNION
                SELECT DISTINCT L14.OBJ_ID
                FROM LINKS L211
                JOIN LINKS L14 ON L14.DATE_DEL IS NULL AND L14.OBJ_TYPE_ID = 14 AND L14.PARENT_ID = L211.OBJ_ID
                WHERE L211.DATE_DEL IS NULL AND L211.OBJ_TYPE_ID = 211 AND L211.PARENT_ID = :I$OBJ_ID
            )
            INTO :VAL;

            SORT_ORDER = VAL;
        END
        ELSE IF (I$DO_FUNC = 17) THEN
        /* SPB DIRECTOR*/
        BEGIN
            SELECT POST || ': ' || F || ' ' || I || ' ' || O
            FROM R_SPB_POST_DIRECTOR(:I$OBJ_ID, :I$USER_ID)
            INTO :VAL;
        END
        ELSE IF (I$DO_FUNC = 18) THEN
        /* SPB BUHGALTER*/
        BEGIN
            SELECT F || ' ' || I || ' ' || O
            FROM R_SPB_POST_BUHGALTER(:I$OBJ_ID, :I$USER_ID)
            INTO :VAL;
        END
        ELSE IF (I$DO_FUNC = 19) THEN
        /* SPB FULL_CLASS_NAME */
        BEGIN
            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:I$OBJ_ID, NULL, NULL, :I$USER_ID)
            INTO :VAL;
        END
        ELSE IF (I$DO_FUNC = 20) THEN
        /* YEAR OF BIRTHDATE */
        BEGIN
            SELECT FIRST 1 EXTRACT(YEAR FROM D)
            FROM VAL_TAG_GET(:I$OBJ_ID, 'BIRTHDATE')
            INTO :VAL;
            SORT_ORDER = VAL;
        END
        ELSE IF (I$DO_FUNC = 21) THEN
        /* INITIALS I.O. */
        BEGIN
            SELECT FIRST 1 TRIM(V)
            FROM VAL_TAG_GET(:I$OBJ_ID, 'I.')
            INTO :V;
            IF (V > '') THEN VAL = SUBSTRING(V FROM 1 FOR 1) || '.';
            V = '';
            SELECT FIRST 1 TRIM(V)
            FROM VAL_TAG_GET(:I$OBJ_ID, 'O.')
            INTO :V;
            IF (V > '') THEN VAL = VAL || SUBSTRING(V FROM 1 FOR 1) || '.';
        END
        ELSE IF (I$DO_FUNC = 22) THEN
        /* Количество сотрудников женщин */
        BEGIN
            SELECT COUNT(*) FROM (
                SELECT DISTINCT L14.OBJ_ID
                FROM LINKS L14
                JOIN VALL V239 ON V239.OBJ_ID = L14.OBJ_ID AND V239.PARAM_ID = 239 AND V239.IS_DEL = 0 AND V239.LISTVAL_ID = 182
                WHERE L14.DATE_DEL IS NULL AND L14.OBJ_TYPE_ID = 14 AND L14.PARENT_ID = :I$OBJ_ID
                UNION
                SELECT DISTINCT L14.OBJ_ID
                FROM LINKS L211
                JOIN LINKS L14 ON L14.DATE_DEL IS NULL AND L14.OBJ_TYPE_ID = 14 AND L14.PARENT_ID = L211.OBJ_ID
                JOIN VALL V239 ON V239.OBJ_ID = L14.OBJ_ID AND V239.PARAM_ID = 239 AND V239.IS_DEL = 0 AND V239.LISTVAL_ID = 182
                WHERE L211.DATE_DEL IS NULL AND L211.OBJ_TYPE_ID = 211 AND L211.PARENT_ID = :I$OBJ_ID
            )
            INTO :VAL;

            SORT_ORDER = VAL;
        END
        ELSE IF (I$DO_FUNC = 23) THEN
        /* Количество сотрудников мужчин */
        BEGIN
            SELECT COUNT(*) FROM (
                SELECT DISTINCT L14.OBJ_ID
                FROM LINKS L14
                JOIN VALL V239 ON V239.OBJ_ID = L14.OBJ_ID AND V239.PARAM_ID = 239 AND V239.IS_DEL = 0 AND V239.LISTVAL_ID = 183
                WHERE L14.DATE_DEL IS NULL AND L14.OBJ_TYPE_ID = 14 AND L14.PARENT_ID = :I$OBJ_ID
                UNION
                SELECT DISTINCT L14.OBJ_ID
                FROM LINKS L211
                JOIN LINKS L14 ON L14.DATE_DEL IS NULL AND L14.OBJ_TYPE_ID = 14 AND L14.PARENT_ID = L211.OBJ_ID
                JOIN VALL V239 ON V239.OBJ_ID = L14.OBJ_ID AND V239.PARAM_ID = 239 AND V239.IS_DEL = 0 AND V239.LISTVAL_ID = 183
                WHERE L211.DATE_DEL IS NULL AND L211.OBJ_TYPE_ID = 211 AND L211.PARENT_ID = :I$OBJ_ID
            )
            INTO :VAL;

            SORT_ORDER = VAL;
        END
        ELSE IF (I$DO_FUNC = 24) THEN
        /* Количество педагогов ОО (см. также 28) */
        BEGIN
            SELECT X FROM PARAGRAF_TEACHERS_COUNT(:I$OBJ_ID)
            INTO :VAL;
            SORT_ORDER = VAL;
        END
        ELSE IF (I$DO_FUNC = 25) THEN
        /* Количество сотрудников ОО района */
        BEGIN
            SELECT COUNT(*) FROM (
                SELECT DISTINCT L14.OBJ_ID
                FROM LINKS L2
                JOIN LINKS L14 ON L14.DATE_DEL IS NULL AND L14.OBJ_TYPE_ID = 14 AND L14.PARENT_ID = L2.OBJ_ID
                --JOIN VALL V239 ON V239.OBJ_ID = L14.OBJ_ID AND V239.PARAM_ID = 239 AND V239.IS_DEL = 0 AND V239.LISTVAL_ID = 182
                WHERE L2.PARENT_ID = :I$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
                UNION
                SELECT DISTINCT L14.OBJ_ID
                FROM LINKS L2
                JOIN LINKS L211 ON L211.DATE_DEL IS NULL AND L211.OBJ_TYPE_ID = 211 AND L211.PARENT_ID = L2.OBJ_ID
                JOIN LINKS L14 ON L14.DATE_DEL IS NULL AND L14.OBJ_TYPE_ID = 14 AND L14.PARENT_ID = L211.OBJ_ID
                --JOIN VALL V239 ON V239.OBJ_ID = L14.OBJ_ID AND V239.PARAM_ID = 239 AND V239.IS_DEL = 0 AND V239.LISTVAL_ID = 182
                WHERE L2.PARENT_ID = :I$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
            )
            INTO :VAL;

            SORT_ORDER = VAL;
        END
        ELSE IF (I$DO_FUNC = 26) THEN
        /* Количеств сотрудников женщин ОО района */
        BEGIN
            SELECT COUNT(*) FROM (
                SELECT DISTINCT L14.OBJ_ID
                FROM LINKS L2
                JOIN LINKS L14 ON L14.DATE_DEL IS NULL AND L14.OBJ_TYPE_ID = 14 AND L14.PARENT_ID = L2.OBJ_ID
                JOIN VALL V239 ON V239.OBJ_ID = L14.OBJ_ID AND V239.PARAM_ID = 239 AND V239.IS_DEL = 0 AND V239.LISTVAL_ID = 182
                WHERE L2.PARENT_ID = :I$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
                UNION
                SELECT DISTINCT L14.OBJ_ID
                FROM LINKS L2
                JOIN LINKS L211 ON L211.DATE_DEL IS NULL AND L211.OBJ_TYPE_ID = 211 AND L211.PARENT_ID = L2.OBJ_ID
                JOIN LINKS L14 ON L14.DATE_DEL IS NULL AND L14.OBJ_TYPE_ID = 14 AND L14.PARENT_ID = L211.OBJ_ID
                JOIN VALL V239 ON V239.OBJ_ID = L14.OBJ_ID AND V239.PARAM_ID = 239 AND V239.IS_DEL = 0 AND V239.LISTVAL_ID = 182
                WHERE L2.PARENT_ID = :I$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
            )
            INTO :VAL;

            SORT_ORDER = VAL;
        END
        ELSE IF (I$DO_FUNC = 27) THEN
        /* Количество сотрудников мужчин района */
        BEGIN
            SELECT COUNT(*) FROM (
                SELECT DISTINCT L14.OBJ_ID
                FROM LINKS L2
                JOIN LINKS L14 ON L14.DATE_DEL IS NULL AND L14.OBJ_TYPE_ID = 14 AND L14.PARENT_ID = L2.OBJ_ID
                JOIN VALL V239 ON V239.OBJ_ID = L14.OBJ_ID AND V239.PARAM_ID = 239 AND V239.IS_DEL = 0 AND V239.LISTVAL_ID = 183
                WHERE L2.PARENT_ID = :I$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
                UNION
                SELECT DISTINCT L14.OBJ_ID
                FROM LINKS L2
                JOIN LINKS L211 ON L211.DATE_DEL IS NULL AND L211.OBJ_TYPE_ID = 211 AND L211.PARENT_ID = L2.OBJ_ID
                JOIN LINKS L14 ON L14.DATE_DEL IS NULL AND L14.OBJ_TYPE_ID = 14 AND L14.PARENT_ID = L211.OBJ_ID
                JOIN VALL V239 ON V239.OBJ_ID = L14.OBJ_ID AND V239.PARAM_ID = 239 AND V239.IS_DEL = 0 AND V239.LISTVAL_ID = 183
                WHERE L2.PARENT_ID = :I$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
            )
            INTO :VAL;

            SORT_ORDER = VAL;
        END
        ELSE IF (I$DO_FUNC = 28) THEN
        /* Количество сотрудников педагогов (район) */
        BEGIN
            SELECT X FROM PARAGRAF_TEACHERS_COUNT_DISTR(:I$OBJ_ID)
            INTO :VAL;
            SORT_ORDER = VAL;
        END
        ELSE
        IF (I$DO_FUNC = 29) THEN
        /* GIA SUBJECT */
        BEGIN
            SELECT L.PARENT_ID

            FROM LINKS L

            WHERE L.PARENT_TYPE_ID = 120
            AND L.OBJ_ID = :I$OBJ_ID
            AND L.DATE_DEL IS NULL

            INTO :V$OBJ_ID;

            SELECT V, SORT_ORDER
            FROM VAL_GET(:V$OBJ_ID, 803, 0, :I$USER_ID)
            INTO :VAL, :SORT_ORDER;
        END
        ELSE IF (I$DO_FUNC = 30) THEN
        /* GIA DATE */
        BEGIN
            SELECT L.PARENT_ID

            FROM LINKS L

            WHERE L.PARENT_TYPE_ID = 120
            AND L.OBJ_ID = :I$OBJ_ID
            AND L.DATE_DEL IS NULL

            INTO :V$OBJ_ID;

            SELECT V, SORT_ORDER
            FROM VAL_GET(:V$OBJ_ID, 804, 0, :I$USER_ID)
            INTO :VAL, :SORT_ORDER;
        END
        ELSE IF (I$DO_FUNC = 31) THEN
        /* GIA TYPE */
        BEGIN
            SELECT L.PARENT_ID

            FROM LINKS L

            WHERE L.PARENT_TYPE_ID = 120
            AND L.OBJ_ID = :I$OBJ_ID
            AND L.DATE_DEL IS NULL

            INTO :V$OBJ_ID;

            SELECT V, SORT_ORDER
            FROM VAL_GET(:V$OBJ_ID, 802, 0, :I$USER_ID)
            INTO :VAL, :SORT_ORDER;
        END
        ELSE IF (I$DO_FUNC = 32) THEN
        /* GIA_VIRTUAL_CLASS_NAME */
        BEGIN
            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:I$OBJ_ID, NULL, NULL, :I$USER_ID)
            INTO :VAL;
        END
        ELSE IF (I$DO_FUNC = 33) THEN
        /* PPE ROOM PLACE COUNT*/
        BEGIN
            SELECT COALESCE(SUM(V.VAL),0)

            FROM LINKS L

            JOIN VALI V
            ON V.OBJ_ID = L.OBJ_ID
            AND V.PARAM_ID = 1372
            AND V.IS_DEL = 0

            WHERE L.PARENT_ID = :I$OBJ_ID
            AND L.OBJ_TYPE_ID = 122
            AND L.DATE_DEL IS NULL

            INTO :VAL;

            SORT_ORDER = VAL;
        END
        ELSE IF (I$DO_FUNC = 34) THEN
        /* STAGE BY INTEGER*/
        BEGIN
            VAL = 0;
            SELECT CAST(TRUNC(LV.COST) AS INTEGER)
            FROM VALL V
            JOIN LISTVALS LV ON LV.LISTVAL_ID = V.LISTVAL_ID
            WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 49 AND V.IS_DEL = 0
            INTO :VAL;
            SORT_ORDER = VAL;
        END
        ELSE IF (I$DO_FUNC = 35) THEN
        /* WORKER IS CLASS-MASTER */
        BEGIN
            VAL = '';
            V$OBJ_ID = NULL;

            SELECT FIRST 1 L9.OBJ_ID
            FROM LINKS L2
            JOIN LINKS L7 ON L7.PARENT_ID = L2.PARENT_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
            JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
            JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
            JOIN VALR V53 ON V53.OBJ_ID = L9.OBJ_ID AND V53.PARAM_ID = 53 AND V53.IS_DEL = 0
            WHERE L2.OBJ_ID = :I$OBJ_ID AND L2.PARENT_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND V53.VAL = :I$OBJ_ID
            INTO :V$OBJ_ID;

            IF (V$OBJ_ID IS NOT NULL) THEN
            BEGIN
                SELECT CAPTION, SORT_ORDER
                FROM OBJECT_CAPTION_GET(:V$OBJ_ID, NULL, NULL, :I$USER_ID)
                INTO :VAL, :SORT_ORDER;
            END
        END
        ELSE IF (I$DO_FUNC = 36) THEN
        /* PPE ROOM PLACE COUNT*/
        BEGIN
            SELECT V529.VAL
            FROM VALR V748
            JOIN VALI V529 ON V529.OBJ_ID = V748.VAL AND V529.PARAM_ID = 529 AND V529.IS_DEL = 0
            WHERE V748.PARAM_ID = 748 AND V748.OBJ_ID = :I$OBJ_ID AND V748.IS_DEL = 0
            INTO :VAL;

            SORT_ORDER = VAL;
        END
        ELSE IF (I$DO_FUNC = 37) THEN
        /* PUNKT VPL CODE*/
        BEGIN
            SELECT CAST(LV.COST AS INTEGER) || '999'

            FROM VALL V839

            JOIN LISTVALS LV
            ON LV.LISTVAL_ID = V839.LISTVAL_ID

            WHERE V839.PARAM_ID = 839
            AND V839.OBJ_ID = :I$OBJ_ID
            AND V839.IS_DEL = 0

            INTO :VAL;

            SORT_ORDER = VAL;
        END
        ELSE IF (I$DO_FUNC = 38) THEN
        /* DOLJNOST PO STATU*/
        BEGIN
            VAL = '';
            SELECT FIRST 1
                   V589.VAL

            FROM VALR V295

            LEFT JOIN VALS V589
            ON V589.OBJ_ID = V295.VAL
            AND V589.PARAM_ID = 589
            AND V589.IS_DEL = 0

            WHERE V295.PARAM_ID = 295
            AND V295.OBJ_ID = :I$OBJ_ID
            AND V295.IS_DEL = 0

            INTO :VAL;

            SORT_ORDER = 0;
        END
        ELSE IF (I$DO_FUNC = 39) THEN
        /* KOMPENSACIA*/
        BEGIN
            VAL = '';
            SELECT FIRST 1
                CASE WHEN ((VL.I = 3307 AND VG.I = 3384) OR
                (VL.I = 3308 AND VG.I = 3384)) THEN  '20%'
                WHEN ((VL.I = 3307 AND VG.I = 3385) OR
                (VL.I = 3308 AND VG.I = 3385))  THEN  '50%'
                WHEN (VL.I = 3308 AND VG.I = 3386)   THEN  '70%'
                ELSE  VL.V_LONG
                END
            --SELECT VL.I, VG.I
            FROM LINKS L20
            LEFT JOIN VAL_GET(L20.EXT_OBJ_ID, 2453, 0, :I$USER_ID) VL ON 1=1
            LEFT JOIN VAL_GET(:I$OBJ_ID, 1642, 0, :I$USER_ID) VG ON 1=1
            WHERE L20.OBJ_TYPE_ID = 20
            AND L20.PARENT_ID = :I$OBJ_ID
            AND L20.DATE_DEL IS NULL

            INTO :VAL;

            SORT_ORDER = 0;
        END
        ELSE IF (I$DO_FUNC = 40) THEN
        /* GPD, PUPIL CLASS*/
        BEGIN
            VAL = '';
            FOR
                SELECT FIRST 1
                       LP9.PARENT_ID
                FROM LINKS LP9

                WHERE LP9.OBJ_ID = :I$OBJ_ID
                AND LP9.PARENT_TYPE_ID = 9
                AND LP9.DATE_DEL IS NULL

                INTO :V$OBJ_ID
            DO
            BEGIN
                SELECT CAPTION
                FROM OBJECT_CAPTION_GET(:V$OBJ_ID, NULL, NULL, :I$USER_ID)
                INTO :VAL;
            END

            SORT_ORDER = 0;
        END
        ELSE IF (I$DO_FUNC = 41) THEN
        /* EXTERNAL_VIRTUAL_CLASS_NAME */
        BEGIN
            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:I$OBJ_ID, NULL, NULL, :I$USER_ID)
            INTO :VAL;
        END
        ELSE IF (I$DO_FUNC = 42) THEN
        /* LAN EXIST (FOR PARAM_ID = 537)*/
        BEGIN
            SORT_ORDER = 5;

            SELECT FIRST 1 4
            FROM LINKS L117
            INNER JOIN VALR V703 ON V703.PARAM_ID = 703 AND V703.OBJ_ID = L117.OBJ_ID
            WHERE L117.OBJ_TYPE_ID = 117
              AND L117.DATE_DEL IS NULL
              AND V703.VAL = :I$OBJ_ID
              AND V703.IS_DEL = 0
            INTO :SORT_ORDER;

            SELECT FIRST 1
                   R.VAL
            FROM LISTVALS LV

            JOIN RES R
            ON R.RES_ID = LV.RES_ID
            AND R.LANG_CODE = 'RU'

            WHERE LV.LIST_ID = 3
            AND LV.LISTVAL_ID = :SORT_ORDER
            AND LV.IS_DEL = 0

            INTO :VAL;
        END
        ELSE IF (I$DO_FUNC = 43) THEN
        /* LAN EXIST (FOR PARAM_ID = 1767)*/
        BEGIN
            SELECT FIRST 1 LV.TAG
            FROM LINKS L
            JOIN VALL V ON V.PARAM_ID = 49 AND V.OBJ_ID = L.PARENT_ID AND V.IS_DEL = 0
            JOIN LISTVALS LV ON V.LISTVAL_ID = LV.LISTVAL_ID
            WHERE L.OBJ_ID = :I$OBJ_ID AND L.DATE_DEL IS NULL AND L.PARENT_TYPE_ID = 8
            INTO :VAL;
        END
        ELSE IF (I$DO_FUNC = 44) THEN
        BEGIN
            SELECT COUNT(L10.OBJ_ID)
            FROM LINKS L9
            JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
            WHERE L9.PARENT_ID = :I$OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
            INTO :VAL;
        END
        ELSE IF (I$DO_FUNC = 45) THEN
        BEGIN
            -- 21.06.2017 отцепляем квалификацию по приему на должность от расчета и делаем вводимым вручную
            /*VAL = 'НЕТ';
            SELECT FIRST 1
                (
                    SELECT VAL FROM RES_GET(
                        (
                            SELECT RES_ID FROM LISTVALS WHERE LISTVAL_ID =
                            (
                                CASE V545.LISTVAL_ID
                                    WHEN 1208 THEN 635
                                    WHEN 1209 THEN 634
                                    WHEN 1210 THEN 633
                                END
                            )
                        ),
                        :LANG_CODE
                    )
                )
            FROM LINKS LP14

            JOIN LINKS L34
            ON L34.PARENT_ID = LP14.PARENT_ID
            AND L34.OBJ_TYPE_ID = 34
            AND L34.DATE_DEL IS NULL

            JOIN VALD V544
            ON V544.OBJ_ID = L34.OBJ_ID
            AND V544.PARAM_ID = 544
            AND V544.IS_DEL = 0
            AND DATEADD(5 YEAR TO V544.VAL) >= CURRENT_TIMESTAMP

            JOIN VALL V545
            ON V545.OBJ_ID = L34.OBJ_ID
            AND V545.PARAM_ID = 545
            AND V545.IS_DEL = 0
            AND V545.LISTVAL_ID IN (1208,1209,1210)

            WHERE LP14.OBJ_ID = :I$OBJ_ID
            AND LP14.PARENT_TYPE_ID = 14
            AND LP14.DATE_DEL IS NULL

            ORDER BY V544.VAL DESC
            INTO :VAL;*/
        END
        ELSE IF (I$DO_FUNC = 46) THEN
        BEGIN
            -- ДАТА ЗАЧИСЛЕНИЯ В ОУ, ДЛЯ ЗАДАЧИ ЛЬГОТНОЕ ПИТАНИЕ. НА ОСНОВЕ ЗАПИСЕЙ ДВИЖЕНИЯ ОБУЧАЮЩЕГОСЯ
            SELECT FIRST 1 M.DATE_IN, M.OBJ_ID
            FROM PERSON_MOVEMENTS M
            JOIN OBJECTS O ON O.OBJ_ID = M.GROUP_ID AND O.TYPE_ID = 9
            JOIN LISTVALS LV ON LV.LISTVAL_ID = M.REASON_IN AND LV.IS_DEL = 0 AND LV.LIST_ID = 122 AND LV."FILTER" LIKE 'ACCEPTED%'
            WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :I$OBJ_ID
            ORDER BY M.DATE_IN DESC
            INTO :VAL, :I;
        END
        ELSE IF (I$DO_FUNC = 47) THEN
        BEGIN
            -- ДАТА ВЫБЫТИЯ ИЗ ОУ, ДЛЯ ЗАДАЧИ ЛЬГОТНОЕ ПИТАНИЕ. НА ОСНОВЕ ЗАПИСЕЙ ДВИЖЕНИЯ ОБУЧАЮЩЕГОСЯ
            SELECT FIRST 1 M.DATE_OUT
            FROM PERSON_MOVEMENTS M
            JOIN OBJECTS O ON O.OBJ_ID = M.GROUP_ID AND O.TYPE_ID = 9
            WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :I$OBJ_ID AND M.DATE_OUT IS NOT NULL
            ORDER BY M.DATE_OUT DESC
            INTO :VAL;
        END
        ELSE IF (I$DO_FUNC = 49) THEN
        BEGIN
            -- Проектная мощность ОООД из полей «Количество ученических мест (проектное)» по всем зданиям
            -- для новых параметров по ДОУ в мультипараграфе берем счетчик из другого поля
            IF(I$PARAM_ID = 3609) THEN N = 3607; ELSE N = 502;
            SELECT SUM(V502.VAL)
            FROM LINKS L73
            JOIN LINKS L16 ON L16.PARENT_ID = L73.OBJ_ID AND L16.OBJ_TYPE_ID = 16 AND L16.DATE_DEL IS NULL
            JOIN VALI V502 ON V502.OBJ_ID = L16.OBJ_ID AND V502.PARAM_ID = :N AND V502.IS_DEL = 0
            WHERE L73.PARENT_ID = :I$OBJ_ID AND L73.OBJ_TYPE_ID = 73 AND L73.DATE_DEL IS NULL
            INTO :VAL;
        END
        ELSE IF (I$DO_FUNC = 50) THEN
        BEGIN
            -- Количество ученических мест (нормативное) ОООД из полей «Количество ученических мест (нормативное)» по всем зданиям
            -- для новых параметров по ДОУ в мультипараграфе берем счетчик из другого поля
            IF(I$PARAM_ID = 3610) THEN N = 3608; ELSE N = 503;
            SELECT SUM(V503.VAL)
            FROM LINKS L73
            JOIN LINKS L16 ON L16.PARENT_ID = L73.OBJ_ID AND L16.OBJ_TYPE_ID = 16 AND L16.DATE_DEL IS NULL
            JOIN VALI V503 ON V503.OBJ_ID = L16.OBJ_ID AND V503.PARAM_ID = :N AND V503.IS_DEL = 0
            WHERE L73.PARENT_ID = :I$OBJ_ID AND L73.OBJ_TYPE_ID = 73 AND L73.DATE_DEL IS NULL
            INTO :VAL;
        END
        ELSE IF (I$DO_FUNC = 51) THEN
        BEGIN
            -- Вычисление количества объединений ДО (СМИР)
            V$I = 0;

            -- Какой из типов был запрошен ? А также получаем ID школы
            SELECT L265.OBJ_TYPE_ID, V2196.LISTVAL_ID, R2196.VAL, L162.PARENT_ID
            FROM LINKS L265
            JOIN VALL V2196 ON V2196.PARAM_ID IN (2196, 2826) AND V2196.OBJ_ID = L265.OBJ_ID AND V2196.IS_DEL = 0
            JOIN LISTVALS LV2196 ON LV2196.LISTVAL_ID = V2196.LISTVAL_ID
            JOIN RES R2196 ON R2196.RES_ID = LV2196.RES_ID AND R2196.LANG_CODE = 'RU'
            JOIN LINKS L162 ON L162.OBJ_ID = L265.PARENT_ID AND L162.PARENT_TYPE_ID = 2 AND L162.DATE_DEL IS NULL
            WHERE L265.OBJ_TYPE_ID IN (265, 368) AND L265.OBJ_ID = :I$OBJ_ID AND L265.DATE_DEL IS NULL
            INTO :V$OBJ_ID, :CNT, :V, :V$PARENT_ID;

            -- Преобразуем тип в LISTVAL_ID
            IF(V$OBJ_ID = 265) THEN V$OBJ_ID = 3315; ELSE V$OBJ_ID = 3316;

            IF (CNT = 10974) THEN
            BEGIN
                -- ИТОГО
                SELECT COUNT(DISTINCT L46.OBJ_ID)
                FROM LINKS L86
                JOIN VALL V1579 ON V1579.OBJ_ID = L86.OBJ_ID AND V1579.PARAM_ID = 1579 AND V1579.IS_DEL = 0 AND V1579.LISTVAL_ID = :V$OBJ_ID
                JOIN LINKS L46 ON L46.PARENT_ID = L86.OBJ_ID AND L46.OBJ_TYPE_ID = 46 AND L46.DATE_DEL IS NULL
                JOIN VALR V2823 ON V2823.OBJ_ID = L46.OBJ_ID AND V2823.PARAM_ID = 2823 AND V2823.IS_DEL = 0
                -- Связь с ОП
                -- JOIN LINKS L57 ON L57.PARENT_TYPE_ID = 69 AND L57.OBJ_ID = V2823.VAL AND L57.DATE_DEL IS NULL
                -- JOIN VALS V390 ON V390.OBJ_ID = L57.OBJ_ID AND V390.PARAM_ID = 390 AND V390.IS_DEL = 0
                -- Ученики
                JOIN LINKS L10 ON L10.PARENT_ID = L46.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
                WHERE L86.PARENT_ID = :V$PARENT_ID AND L86.OBJ_TYPE_ID = 86 AND L86.DATE_DEL IS NULL
                INTO :V$I;
            END
            ELSE
            BEGIN
                -- Конкретный тип
                SELECT COUNT(DISTINCT L46.OBJ_ID)
                FROM LINKS L86
                JOIN VALL V1579 ON V1579.OBJ_ID = L86.OBJ_ID AND V1579.PARAM_ID = 1579 AND V1579.IS_DEL = 0 AND V1579.LISTVAL_ID = :V$OBJ_ID
                JOIN LINKS L46 ON L46.PARENT_ID = L86.OBJ_ID AND L46.OBJ_TYPE_ID = 46 AND L46.DATE_DEL IS NULL
                JOIN VALR V2823 ON V2823.OBJ_ID = L46.OBJ_ID AND V2823.PARAM_ID = 2823 AND V2823.IS_DEL = 0
                -- Связь с ОП
                JOIN LINKS L57 ON L57.PARENT_TYPE_ID = 69 AND L57.OBJ_ID = V2823.VAL AND L57.DATE_DEL IS NULL
                JOIN VALS V390 ON V390.OBJ_ID = L57.OBJ_ID AND V390.PARAM_ID = 390 AND V390.IS_DEL = 0 AND V390.SVAL = :V
                -- Ученики
                JOIN LINKS L10 ON L10.PARENT_ID = L46.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
                WHERE L86.PARENT_ID = :V$PARENT_ID AND L86.OBJ_TYPE_ID = 86 AND L86.DATE_DEL IS NULL
                INTO :V$I;
            END
            VAL = V$I;
        END
        ELSE IF (I$DO_FUNC = 52) THEN
        BEGIN
            -- Вычисление количества учащихся коллективов ДО (СМИР)
            V$I = 0;

            -- Какой из типов был запрошен ? А также получаем ID школы
            SELECT L265.OBJ_TYPE_ID, V2196.LISTVAL_ID, R2196.VAL, L162.PARENT_ID
            FROM LINKS L265
            JOIN VALL V2196 ON V2196.PARAM_ID IN (2196, 2826) AND V2196.OBJ_ID = L265.OBJ_ID AND V2196.IS_DEL = 0
            JOIN LISTVALS LV2196 ON LV2196.LISTVAL_ID = V2196.LISTVAL_ID
            JOIN RES R2196 ON R2196.RES_ID = LV2196.RES_ID AND R2196.LANG_CODE = 'RU'
            JOIN LINKS L162 ON L162.OBJ_ID = L265.PARENT_ID AND L162.PARENT_TYPE_ID = 2 AND L162.DATE_DEL IS NULL
            WHERE L265.OBJ_TYPE_ID IN (265, 368) AND L265.OBJ_ID = :I$OBJ_ID AND L265.DATE_DEL IS NULL
            INTO :V$OBJ_ID, :CNT, :V, :V$PARENT_ID;

            -- Преобразуем тип в LISTVAL_ID
            IF(V$OBJ_ID = 265) THEN V$OBJ_ID = 3315; ELSE V$OBJ_ID = 3316;

            IF (CNT = 10974) THEN
            BEGIN
                -- ИТОГО
                SELECT COUNT(DISTINCT L10.OBJ_ID)
                FROM LINKS L86
                JOIN VALL V1579 ON V1579.OBJ_ID = L86.OBJ_ID AND V1579.PARAM_ID = 1579 AND V1579.IS_DEL = 0 AND V1579.LISTVAL_ID = :V$OBJ_ID
                JOIN LINKS L46 ON L46.PARENT_ID = L86.OBJ_ID AND L46.OBJ_TYPE_ID = 46 AND L46.DATE_DEL IS NULL
                JOIN VALR V2823 ON V2823.OBJ_ID = L46.OBJ_ID AND V2823.PARAM_ID = 2823 AND V2823.IS_DEL = 0
                -- Связь с ОП
                -- JOIN LINKS L57 ON L57.PARENT_TYPE_ID = 69 AND L57.OBJ_ID = V2823.VAL AND L57.DATE_DEL IS NULL
                -- JOIN VALL V390 ON V390.OBJ_ID = L57.OBJ_ID AND V390.PARAM_ID = 390 AND V390.IS_DEL = 0
                -- Ученики
                JOIN LINKS L10 ON L10.PARENT_ID = L46.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
                WHERE L86.PARENT_ID = :V$PARENT_ID AND L86.OBJ_TYPE_ID = 86 AND L86.DATE_DEL IS NULL
                INTO :V$I;
            END
            ELSE
            BEGIN
                -- Конкретный тип
                SELECT COUNT(DISTINCT L10.OBJ_ID)
                FROM LINKS L86
                JOIN VALL V1579 ON V1579.OBJ_ID = L86.OBJ_ID AND V1579.PARAM_ID = 1579 AND V1579.IS_DEL = 0 AND V1579.LISTVAL_ID = :V$OBJ_ID
                JOIN LINKS L46 ON L46.PARENT_ID = L86.OBJ_ID AND L46.OBJ_TYPE_ID = 46 AND L46.DATE_DEL IS NULL
                JOIN VALR V2823 ON V2823.OBJ_ID = L46.OBJ_ID AND V2823.PARAM_ID = 2823 AND V2823.IS_DEL = 0
                -- Связь с ОП
                JOIN LINKS L57 ON L57.PARENT_TYPE_ID = 69 AND L57.OBJ_ID = V2823.VAL AND L57.DATE_DEL IS NULL
                JOIN VALS V390 ON V390.OBJ_ID = L57.OBJ_ID AND V390.PARAM_ID = 390 AND V390.IS_DEL = 0 AND V390.SVAL = :V
                -- Ученики
                JOIN LINKS L10 ON L10.PARENT_ID = L46.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
                WHERE L86.PARENT_ID = :V$PARENT_ID AND L86.OBJ_TYPE_ID = 86 AND L86.DATE_DEL IS NULL
                INTO :V$I;
            END
            VAL = V$I;
        END
        ELSE IF (I$DO_FUNC = 53) THEN
        BEGIN
            SELECT V
            FROM LINKS L270
            
            LEFT JOIN VAL_GET(L270.PARENT_ID, 1433) ON 1=1
            
            WHERE L270.OBJ_TYPE_ID = 270
            AND L270.DATE_DEL IS NULL
            AND L270.OBJ_ID = :I$OBJ_ID
            INTO :VAL;
        END
        ELSE IF (I$DO_FUNC = 54) THEN
        BEGIN
            SELECT V1483.VAL
            FROM LINKS L270
            
            JOIN VALI V1483
            ON V1483.PARAM_ID = 1483
            AND V1483.IS_DEL = 0
            AND V1483.OBJ_ID = L270.PARENT_ID
            
            WHERE L270.OBJ_TYPE_ID = 270
            AND L270.DATE_DEL IS NULL
            AND L270.OBJ_ID = :I$OBJ_ID
            INTO :VAL;
        END
        ELSE IF (I$DO_FUNC = 55) THEN
        BEGIN
            SELECT V
            FROM LINKS L270
            
            LEFT JOIN VAL_GET(L270.PARENT_ID, 1432) ON 1=1
            
            WHERE L270.OBJ_TYPE_ID = 270
            AND L270.DATE_DEL IS NULL
            AND L270.OBJ_ID = :I$OBJ_ID
            INTO :VAL;
        END
        ELSE IF (I$DO_FUNC = 56) THEN
        BEGIN
            SELECT CAST(CAST(V1433.V AS NUMERIC(10,2)) / CAST(V1432.V AS NUMERIC(10,2)) * 100 AS INTEGER)
            FROM LINKS L270
            
            LEFT JOIN VAL_GET(L270.PARENT_ID, 1433) V1433 ON 1=1
            
            LEFT JOIN VAL_GET(L270.PARENT_ID, 1432) V1432 ON 1=1
            
            WHERE L270.OBJ_TYPE_ID = 270
            AND L270.DATE_DEL IS NULL
            AND L270.OBJ_ID = :I$OBJ_ID
            INTO :VAL;
        END
        ELSE IF (I$DO_FUNC = 57) THEN
        BEGIN
            -- Функция потеряла актуальность, и заменена другим параметром !!!
            V$I = EXTRACT(YEAR FROM CURRENT_DATE);
            BEGIN_DATE = '1.09.' || V$I;
            
            IF (CURRENT_DATE < BEGIN_DATE) THEN
            BEGIN
                VAL = (V$I - 1) || '-' || V$I;
            END
            ELSE
            BEGIN
                VAL = V$I || '-' ||(V$I + 1);
            END
        END
        ELSE IF (I$DO_FUNC = 59) THEN
        BEGIN
            VAL = I$OBJ_ID / 1000000000;
        END
        ELSE IF (I$DO_FUNC = 60) THEN
        BEGIN
            IF (EXISTS(
                SELECT FIRST 1 1
                FROM LINKS L295
                JOIN VALL V2373 ON V2373.OBJ_ID = L295.OBJ_ID AND V2373.PARAM_ID = 2373 AND V2373.IS_DEL = 0
                LEFT JOIN VALD V2375 ON V2375.OBJ_ID = L295.OBJ_ID AND V2375.PARAM_ID = 2375 AND V2375.IS_DEL = 0
                WHERE L295.PARENT_ID = :I$OBJ_ID AND L295.OBJ_TYPE_ID = 295 AND L295.DATE_DEL IS NULL
                    AND (V2375.VAL IS NULL OR V2375.VAL > CURRENT_DATE)
            )) THEN
            BEGIN
                SELECT VAL FROM RES_GET(12289, :LANG_CODE) INTO :VAL;
            END
            ELSE
            BEGIN
                SELECT VAL FROM RES_GET(12290, :LANG_CODE) INTO :VAL;
            END
        END
        ELSE IF (I$DO_FUNC = 64) THEN
        BEGIN
            FOR
                SELECT LP10.PARENT_ID
                FROM LINKS LP10
                WHERE LP10.OBJ_ID = :I$OBJ_ID
                AND LP10.PARENT_TYPE_ID = 10
                AND LP10.DATE_DEL IS NULL
                INTO :V$PARENT_ID
            DO
            BEGIN
                CNT = 1;
                FOR
                    SELECT L297.OBJ_ID
                    FROM LINKS L297

                    LEFT JOIN OBJECT_CAPTION_GET(L297.OBJ_ID) OC ON 1=1

                    WHERE L297.PARENT_ID = :V$PARENT_ID
                    AND L297.OBJ_TYPE_ID = 297
                    AND L297.DATE_DEL IS NULL

                    ORDER BY OC.SORT_ORDER, L297.OBJ_ID
                    INTO :V$OBJ_ID
                DO
                BEGIN
                    IF (V$OBJ_ID = I$OBJ_ID) THEN
                    BEGIN
                        VAL = CNT;
                        SORT_ORDER = CNT;
                        BREAK;
                    END
                    CNT = CNT + 1;
                END
            END
        END
        ELSE IF (I$DO_FUNC = 1024) THEN
        BEGIN
            FOR
                SELECT LP2.PARENT_ID
                FROM LINKS LP2
                WHERE LP2.OBJ_ID = :I$OBJ_ID
                AND LP2.PARENT_TYPE_ID=2
                AND LP2.DATE_DEL IS NULL
                INTO :V$OBJ_ID
            DO
            BEGIN
                SELECT VAL, SORT_ORDER
                FROM MONITORING_DO_FUNC(:V$OBJ_ID, :I$PARAM_ID, :I$USER_ID)
                INTO :VAL, :SORT_ORDER;
            END
        END
        ELSE IF (I$DO_FUNC = 1025) THEN
        BEGIN
            SELECT LP2.PARENT_ID
            FROM LINKS LP2
            WHERE LP2.OBJ_ID = :I$OBJ_ID
            AND LP2.PARENT_TYPE_ID in  (2, 111)
            AND LP2.DATE_DEL IS NULL
            INTO :V$OBJ_ID;

            SELECT VAL
            FROM PLAN_DO_FUNC(:V$OBJ_ID, :I$OBJ_ID, :I$PARAM_ID)
            INTO :VAL;
        END
        ELSE IF (I$DO_FUNC = 1026) THEN
        BEGIN
            FOR
                SELECT LP2.PARENT_ID
                FROM LINKS LP2
                WHERE LP2.OBJ_ID = :I$OBJ_ID
                AND LP2.PARENT_TYPE_ID=2
                AND LP2.DATE_DEL IS NULL

                UNION

                SELECT LP2.PARENT_ID
                FROM LINKS LP162

                JOIN LINKS LP2
                ON LP2.OBJ_ID = LP162.PARENT_ID
                AND LP2.PARENT_TYPE_ID = 2
                AND LP2.DATE_DEL IS NULL

                WHERE LP162.OBJ_ID = :I$OBJ_ID
                AND LP162.PARENT_TYPE_ID=162
                AND LP162.DATE_DEL IS NULL

                INTO :V$OBJ_ID
            DO
            BEGIN
                SELECT VAL, SORT_ORDER
                FROM MONITORING_DO_FUNC2(:V$OBJ_ID, :I$OBJ_ID, :I$PARAM_ID, :I$USER_ID)
                INTO :VAL, :SORT_ORDER;
            END
        END
        ELSE IF (I$DO_FUNC = 1027) THEN
        BEGIN
            SELECT VAL
            FROM VALD
            WHERE OBJ_ID = :I$OBJ_ID
            AND PARAM_ID = :I$PARAM_ID
            AND IS_DEL = 0
            AND DATEADD(1 MINUTE TO VAL) > CURRENT_TIMESTAMP
            INTO :BEGIN_DATE;

            SELECT LP2.PARENT_ID
            FROM LINKS LP2
            WHERE LP2.OBJ_ID = :I$OBJ_ID
            AND LP2.PARENT_TYPE_ID in  (2, 111)
            AND LP2.DATE_DEL IS NULL
            INTO :V$OBJ_ID;

            SELECT VAL
            FROM MONITORING_DO_FUNC3(:V$OBJ_ID, :I$USER_ID)
            INTO :VAL;
        END
        ELSE IF (I$DO_FUNC = 1028) THEN
        BEGIN
            SELECT VAL
            FROM MONITORING_DO_FUNC4(:I$OBJ_ID)
            INTO :VAL;
        END
        ELSE IF (I$DO_FUNC = 1029) THEN
        BEGIN
            SELECT VAL
            FROM MONITORING_DO_FUNC5(:I$OBJ_ID)
            INTO :VAL;
        END
        ELSE IF (I$DO_FUNC = 1030) THEN
        BEGIN
            SELECT VAL
            FROM LIB_FP_BOOK_INFO_GET(:I$OBJ_ID, :I$PARAM_ID)
            INTO :VAL;
        END
        ELSE IF (I$DO_FUNC = 1031) THEN
        BEGIN
            SELECT VAL
            FROM MONITORING_DO_FUNC6(:I$OBJ_ID)
            INTO :VAL;
        END
        ELSE IF (I$DO_FUNC = 1032) THEN
        BEGIN
            SELECT VAL
            FROM MONITORING_DO_FUNC7(:I$OBJ_ID)
            INTO :VAL;
        END
        ELSE IF (I$DO_FUNC = 1033) THEN
        BEGIN
            SELECT VAL
            FROM LIB_FP_BOOK_INFO_GET(:I$OBJ_ID, :I$PARAM_ID)
            INTO :VAL;
        END
        ELSE IF (I$DO_FUNC = 1034) then
        BEGIN
            SELECT VAL, I
            FROM CURRICULUM_SUBJECT_TO_FGOS(:I$OBJ_ID)
            INTO :VAL, :I;
        END
        ELSE IF (I$DO_FUNC = 1035) then
        BEGIN
            -- Направленность для ДО
            SELECT VAL
            FROM PARAM_GET_DO_OP_DIRECTION(:I$OBJ_ID)
            INTO :VAL;
        END
        /*ELSE if (I$DO_FUNC = 1036) then
        BEGIN
            -- Квалификационная категория по основной должности - схема расчета перенесена из функционального параметра в VAL_ADD
            SELECT VAL FROM VACANCY_GET_CAT(:I$OBJ_ID) INTO :VAL;
        END*/
        ELSE IF (I$DO_FUNC = 9999991) THEN
        BEGIN
            IF (KEY_LEVEL = 1) THEN
            BEGIN
                IF (I$PARAM_ID = 1510) THEN VAL = (I$OBJ_ID / 1000000000);
                ELSE IF(I$PARAM_ID = 1503) THEN VAL = (SELECT V.VER_MAJOR || '.' || V.VER_MINOR || '.' || V.VER_RELEASE || '.' || V.VER_BUILD FROM VER V);
                ELSE IF (I$PARAM_ID = 1505) THEN
                BEGIN
                    -- Выбираем сохраненную версию программы экспорта
                    SELECT FIRST 1 INFO_VAL FROM INFO WHERE INFO_CODE = 'PORTAL_SERVICE_VERSION' INTO :VAL;
                    -- Копируем сигнатуру экзаменов из текущего года
                    V$I = EXTRACT(YEAR FROM CURRENT_DATE);
                    IF(EXTRACT(MONTH FROM CURRENT_DATE) < 9) THEN V$I = V$I - 1;

                    V = NULL;
                    SELECT FIRST 1 V2930.VAL
                    FROM LINKS L119
                    JOIN VALL V742 ON V742.OBJ_ID = L119.OBJ_ID AND V742.PARAM_ID = 742 AND V742.IS_DEL = 0
                    JOIN LISTVALS LV ON LV.LISTVAL_ID = V742.LISTVAL_ID AND LV.COST = :V$I
                    JOIN VALS V2930 ON V2930.OBJ_ID = L119.OBJ_ID AND V2930.PARAM_ID = 2930 AND V2930.IS_DEL = 0
                    WHERE L119.PARENT_ID = 3866 AND L119.OBJ_TYPE_ID = 119 AND L119.DATE_DEL IS NULL
                    INTO :V;
                    SELECT BLOB_ID FROM VAL_ADD(2933, :I$OBJ_ID, :V) INTO :V$OBJ_ID;
                END
                ELSE IF (I$PARAM_ID = 1504) THEN
                BEGIN
                    SELECT MON$DATABASE_NAME
                    FROM MON$DATABASE
                    INTO :V;

                    V = REPLACE(V, 'BASE.FDB', 'BIN.FDB');
                    EXECUTE STATEMENT
                        'SELECT M.VER_MAJOR || ''.'' || M.VER_MINOR || ''.'' || M.VER_RELEASE || ''.'' || M.VER_BUILD
                        FROM MODULES M WHERE M.MODULE_CODE LIKE ''PARAGRAF'''
                    ON EXTERNAL :V
                    -- ROLE 'INISSOFT_ROLE'
                    WITH COMMON TRANSACTION
                    INTO :VAL;

                    -- Сводная информация о базе данных и версии
                    V = (SELECT V.VER_MAJOR || '.' || V.VER_MINOR || '.' || V.VER_RELEASE || '.' || V.VER_BUILD FROM VER V) || ' #' || (I$OBJ_ID / 1000000000) || ' ' || (SELECT STATUS FROM OU_LICENCE_TYPE);
                    SELECT BLOB_ID FROM VAL_ADD(3611, :I$OBJ_ID, :V) INTO :V$OBJ_ID;
                END
            END
            ELSE
            BEGIN
                SELECT VAL
                FROM VALS
                WHERE OBJ_ID = :I$OBJ_ID AND PARAM_ID = :I$PARAM_ID AND IS_DEL = 0
                INTO :VAL;
            END
        END
        ELSE
        BEGIN
            SELECT VAL, I, SORT_ORDER
            FROM DO_FUNC2(
                :I$OBJ_ID,
                :I$PARAM_ID,
                :I$DO_FUNC,
                :I$AUTO_LISTVAL_ID,
                :I$USER_ID,
                :I$PARENT_ID)
            INTO :VAL, :I, :SORT_ORDER;
        END
    END
    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DO_FUNC2 (
    I$OBJ_ID BIGINT,
    I$PARAM_ID BIGINT,
    I$DO_FUNC BIGINT = NULL,
    I$AUTO_LISTVAL_ID BIGINT = NULL,
    I$USER_ID BIGINT = NULL,
    I$PARENT_ID BIGINT = NULL)
RETURNS (
    VAL VARCHAR(4000),
    I BIGINT,
    SORT_ORDER DOUBLE PRECISION)
AS
DECLARE VARIABLE V$Y SMALLINT;
DECLARE VARIABLE V$DT DATE;
DECLARE VARIABLE V$YEAR_VAL VARCHAR(100);
DECLARE VARIABLE V$YEAR_ID BIGINT;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$PARENT_ID BIGINT;
DECLARE VARIABLE V$DATE_INS TIMESTAMP;
DECLARE VARIABLE V$DATE_MODIFY TIMESTAMP;
DECLARE VARIABLE V$NUM_INS SMALLINT;
DECLARE VARIABLE V$NUM_MODIFY SMALLINT;
DECLARE VARIABLE V$TYPE_ID BIGINT;
DECLARE VARIABLE N1 BIGINT;
DECLARE VARIABLE N2 BIGINT;
DECLARE VARIABLE V$S1 VARCHAR(400);
DECLARE VARIABLE V$S2 VARCHAR(400);
BEGIN
    I = 0;
    IF(I$DO_FUNC IS NOT NULL) THEN
    BEGIN
        V$Y = EXTRACT(YEAR FROM CURRENT_DATE);
        V$DT = '1.09.' || V$Y;
            
        IF(CURRENT_DATE < V$DT) THEN
        BEGIN
            V$YEAR_VAL = (V$Y - 1) || '-' || V$Y;
        END
        ELSE
        BEGIN
            V$YEAR_VAL = V$Y || '-' ||(V$Y + 1);
        END
            
        SELECT FIRST 1 LV.LISTVAL_ID
        FROM LISTVALS LV
        JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
        WHERE LV.LIST_ID = 29 AND R.VAL LIKE :V$YEAR_VAL
        INTO :V$YEAR_ID;

        IF(I$DO_FUNC = 65) THEN
        BEGIN
            IF(EXISTS(
                SELECT FIRST 1 1
                FROM LINKS L297
                JOIN VALL V2394 ON V2394.OBJ_ID = L297.OBJ_ID AND V2394.PARAM_ID = 2394 AND V2394.IS_DEL = 0
                JOIN VALL V2391 ON V2391.OBJ_ID = L297.OBJ_ID AND V2391.PARAM_ID = 2391 AND V2391.IS_DEL = 0
                JOIN VALL V2392 ON V2392.OBJ_ID = L297.OBJ_ID AND V2392.PARAM_ID = 2392 AND V2392.IS_DEL = 0
                JOIN VALL V2393 ON V2393.OBJ_ID = L297.OBJ_ID AND V2393.PARAM_ID = 2393 AND V2393.IS_DEL = 0
                WHERE L297.PARENT_ID = :I$OBJ_ID AND L297.OBJ_TYPE_ID = 297 AND L297.DATE_DEL IS NULL AND V2394.LISTVAL_ID = :V$YEAR_ID
            )) THEN
            BEGIN
                VAL = '1';
            END
            ELSE
            BEGIN
                VAL = '0';
            END
        END
        ELSE IF(I$DO_FUNC = 66) THEN
        BEGIN
            SELECT COUNT(*)
            FROM LINKS L297
            JOIN VALL V2394 ON V2394.OBJ_ID = L297.OBJ_ID AND V2394.PARAM_ID = 2394 AND V2394.IS_DEL = 0
            JOIN VALL V2391 ON V2391.OBJ_ID = L297.OBJ_ID AND V2391.PARAM_ID = 2391 AND V2391.IS_DEL = 0
            JOIN VALL V2392 ON V2392.OBJ_ID = L297.OBJ_ID AND V2392.PARAM_ID = 2392 AND V2392.IS_DEL = 0
            JOIN VALL V2393 ON V2393.OBJ_ID = L297.OBJ_ID AND V2393.PARAM_ID = 2393 AND V2393.IS_DEL = 0
            WHERE L297.PARENT_ID = :I$OBJ_ID AND L297.OBJ_TYPE_ID = 297 AND L297.DATE_DEL IS NULL AND V2394.LISTVAL_ID = :V$YEAR_ID AND V2393.LISTVAL_ID = 11327
            INTO :VAL;
        END
        ELSE IF(I$DO_FUNC = 67) THEN
        BEGIN
            SELECT COUNT(*)
            FROM LINKS L297
            JOIN VALL V2394 ON V2394.OBJ_ID = L297.OBJ_ID AND V2394.PARAM_ID = 2394 AND V2394.IS_DEL = 0
            JOIN VALL V2391 ON V2391.OBJ_ID = L297.OBJ_ID AND V2391.PARAM_ID = 2391 AND V2391.IS_DEL = 0
            JOIN VALL V2392 ON V2392.OBJ_ID = L297.OBJ_ID AND V2392.PARAM_ID = 2392 AND V2392.IS_DEL = 0
            JOIN VALL V2393 ON V2393.OBJ_ID = L297.OBJ_ID AND V2393.PARAM_ID = 2393 AND V2393.IS_DEL = 0
            WHERE L297.PARENT_ID = :I$OBJ_ID AND L297.OBJ_TYPE_ID = 297 AND L297.DATE_DEL IS NULL AND V2394.LISTVAL_ID = :V$YEAR_ID AND V2393.LISTVAL_ID = 11328
            INTO :VAL;
        END
        ELSE IF(I$DO_FUNC = 68) THEN
        BEGIN
            -- Педагогическая должность, исключаем преподавателя-организатора ОБЖ
            SELECT LV.LIST_ID, LV.PARENT_ID, LV.LISTVAL_ID, LV.TAG, LV."FILTER"
            FROM VALL V58
            JOIN LISTVALS LV ON LV.LISTVAL_ID = V58.LISTVAL_ID AND LV.IS_DEL = 0
            WHERE V58.OBJ_ID = :I$OBJ_ID AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0
            INTO :V$TYPE_ID, :V$PARENT_ID, :V$OBJ_ID, :V$S1, :V$S2;

            -- Так как списков с должностями теперь 3, это 21, 369 и 370, то признак педагогической должности рассчитывается по разному для списка 21 и для двух других
            -- Для списка 21 опираемся на идентификаторы, а для списков 369 и 370 - на тэги
            -- Признак самой педагогической должности оставляем в SORT_ORDER, а текст в VAL
            SORT_ORDER = IIF(V$PARENT_ID IN (98, 125, 129, 131) OR V$OBJ_ID IN (127, 1281) OR V$S1 = 'U' OR V$S2 = 'U', 2, 3);
            SELECT WORD FROM REPORT_WORDS WHERE ID = IIF(:SORT_ORDER = 2, 26, 27) INTO :VAL;

            -- Расширенный признак возвращаем в I: 0 / 1 + все руководящие должности
            I = IIF(V$PARENT_ID IN (98, 125, 129, 131, 56, 113, 70) OR V$OBJ_ID IN (127, 1281) OR V$S1 IN ('U', 'R1', 'R2', 'R3') OR V$S2 IN ('U', 'R1', 'R2', 'R3'), 1, 0);
        END
        ELSE IF(I$DO_FUNC = 69) THEN
        BEGIN
            SELECT VAL
            FROM VALR V69
            WHERE V69.OBJ_ID = :I$OBJ_ID AND V69.PARAM_ID = 69 AND V69.IS_DEL = 0
            INTO :VAL;

            SELECT VAL, SORT_ORDER
            FROM DO_FUNC(:VAL, 400)
            INTO :VAL, :SORT_ORDER;
        END
        ELSE IF(I$DO_FUNC = 70) THEN
        BEGIN
            -- Непонятно что эта функция делает
            EXCEPTION DATA_ERROR 'Функция 70';
        END
        ELSE IF(I$DO_FUNC = 71) THEN
        BEGIN
            FOR
                SELECT LP242.PARENT_ID
                FROM LINKS LP242
                WHERE LP242.OBJ_ID = :I$PARENT_ID AND LP242.PARENT_TYPE_ID = 242 AND LP242.DATE_DEL IS NULL
                INTO :V$OBJ_ID
            DO
            BEGIN
                SELECT V,I
                FROM VAL_GET(:V$OBJ_ID, 2451, 0, :I$USER_ID)
                INTO :VAL,:SORT_ORDER;
            END
        END
        ELSE IF(I$DO_FUNC = 72) THEN
        BEGIN
            FOR
                SELECT FIRST 1 LP51.PARENT_ID
                FROM LINKS LP51
                WHERE LP51.OBJ_ID = :I$OBJ_ID AND LP51.PARENT_TYPE_ID = 51 AND LP51.DATE_DEL IS NULL
                INTO :V$OBJ_ID
            DO
            BEGIN
                SELECT CAPTION, SORT_ORDER
                FROM OBJECT_CAPTION_GET(:V$OBJ_ID, NULL, NULL, :I$USER_ID)
                INTO :VAL,:SORT_ORDER;
            END
        END
        ELSE IF(I$DO_FUNC = 73) THEN
        BEGIN
            -- ГУП или поток
            V$TYPE_ID = (SELECT TYPE_ID FROM OBJECTS WHERE OBJ_ID = :I$PARENT_ID);
            IF(V$TYPE_ID = 256) THEN
            BEGIN
                FOR
                    -- Основная связь предмет -> ПТП
                    SELECT FIRST 1 LP51.PARENT_ID
                    FROM LINKS LP51
                    WHERE LP51.OBJ_ID = :I$OBJ_ID AND LP51.PARENT_TYPE_ID = 51 AND LP51.DATE_DEL IS NULL
                    INTO :V$OBJ_ID
                DO
                BEGIN
                    SELECT SUM(VI.VAL)
                    FROM LINKS LP54
                    JOIN LINKS LP50 ON LP50.OBJ_ID = LP54.PARENT_ID AND LP50.PARENT_TYPE_ID = 50 AND LP50.DATE_DEL IS NULL
                    JOIN LINKS L49 ON L49.PARENT_ID = LP50.PARENT_ID AND L49.OBJ_TYPE_ID = 49 AND L49.DATE_DEL IS NULL
                    JOIN LINKS L51 ON L51.PARENT_ID = L49.OBJ_ID AND L51.OBJ_TYPE_ID = 51 AND L51.DATE_DEL IS NULL AND L51.OBJ_ID = :V$OBJ_ID
                    JOIN LINKS L56 ON L56.PARENT_ID = LP54.PARENT_ID AND L56.OBJ_TYPE_ID = 56 AND L56.DATE_DEL IS NULL
                    JOIN LINKS L51_56 ON L51_56.OBJ_ID = L56.OBJ_ID AND L51_56.PARENT_ID = L51.OBJ_ID AND L51_56.DATE_DEL IS NULL
                    JOIN LINKS L49_56 ON L49_56.OBJ_ID = L56.OBJ_ID AND L49_56.PARENT_ID = L49.OBJ_ID AND L49_56.DATE_DEL IS NULL
                    JOIN VALI VI ON VI.OBJ_ID = L56.OBJ_ID AND VI.PARAM_ID = 385 AND VI.IS_DEL = 0 AND VI.VAL > 0
                    JOIN VALL VL ON VL.OBJ_ID = L49.OBJ_ID AND VL.PARAM_ID = 372 AND VL.IS_DEL = 0
                    WHERE LP54.OBJ_ID = :I$PARENT_ID AND LP54.PARENT_TYPE_ID = 54 AND LP54.DATE_DEL IS NULL
                    GROUP BY L51.OBJ_ID
                    INTO :VAL;
                END
            END
            ELSE IF(V$TYPE_ID = 347) THEN
            BEGIN
                FOR
                    -- Основная связь предмет -> ПТП
                    SELECT FIRST 1 LP51.PARENT_ID
                    FROM LINKS LP51
                    WHERE LP51.OBJ_ID = :I$OBJ_ID AND LP51.PARENT_TYPE_ID = 51 AND LP51.DATE_DEL IS NULL
                    INTO :V$OBJ_ID
                DO
                BEGIN
                    SELECT SUM(VI.VAL)
                    FROM LINKS LP346
                    JOIN LINKS LP54 ON LP54.OBJ_ID = LP346.PARENT_ID AND LP54.PARENT_TYPE_ID = 54 AND LP54.DATE_DEL IS NULL
                    JOIN LINKS LP50 ON LP50.OBJ_ID = LP54.PARENT_ID AND LP50.PARENT_TYPE_ID = 50 AND LP50.DATE_DEL IS NULL
                    JOIN LINKS L49 ON L49.PARENT_ID = LP50.PARENT_ID AND L49.OBJ_TYPE_ID = 49 AND L49.DATE_DEL IS NULL
                    JOIN LINKS L51 ON L51.PARENT_ID = L49.OBJ_ID AND L51.OBJ_TYPE_ID = 51 AND L51.DATE_DEL IS NULL AND L51.OBJ_ID = :V$OBJ_ID
                    JOIN LINKS L56 ON L56.PARENT_ID = LP54.PARENT_ID AND L56.OBJ_TYPE_ID = 56 AND L56.DATE_DEL IS NULL
                    JOIN LINKS L51_56 ON L51_56.OBJ_ID = L56.OBJ_ID AND L51_56.PARENT_ID = L51.OBJ_ID AND L51_56.DATE_DEL IS NULL
                    JOIN LINKS L49_56 ON L49_56.OBJ_ID = L56.OBJ_ID AND L49_56.PARENT_ID = L49.OBJ_ID AND L49_56.DATE_DEL IS NULL
                    JOIN VALI VI ON VI.OBJ_ID = L56.OBJ_ID AND VI.PARAM_ID = 385 AND VI.IS_DEL = 0 AND VI.VAL > 0
                    JOIN VALL VL ON VL.OBJ_ID = L49.OBJ_ID AND VL.PARAM_ID = 372 AND VL.IS_DEL = 0
                    WHERE LP346.OBJ_ID = :I$PARENT_ID AND LP346.PARENT_TYPE_ID = 346 AND LP346.DATE_DEL IS NULL
                    GROUP BY L51.OBJ_ID
                    INTO :VAL;
                END
            END
        END
        ELSE IF(I$DO_FUNC = 1037) THEN
        BEGIN
            -- Количество занятых ставок (для должности или для ОУ в целом для учительских ставок)
            SELECT VAL FROM VACANCY_NUM_OCCUPIED(:I$OBJ_ID) INTO :VAL;
        END
        ELSE IF(I$DO_FUNC = 1038) THEN
        BEGIN
            -- Количество временно свободных ставок (для должности или для ОУ в целом для учительских ставок)
            SELECT VAL FROM VACANCY_NUM_TEMPFREE(:I$OBJ_ID) INTO :VAL;
        END
        -- 1040 ДПО больше не используется
        ELSE IF(I$DO_FUNC = 1041) THEN
        BEGIN
            -- Должности самого или наставляемого
            IF(I$PARAM_ID = 2986) THEN I$OBJ_ID = (SELECT FIRST 1 VAL FROM VALR WHERE OBJ_ID = :I$OBJ_ID AND PARAM_ID = 2985 AND IS_DEL = 0);
            SELECT VAL FROM EMPLOYEE_JOBS_LIST(:I$OBJ_ID) INTO :VAL;
        END
        ELSE IF(I$DO_FUNC = 1042) THEN
        BEGIN
            -- Наставничество
            IF(EXISTS(
                SELECT FIRST 1 1
                FROM LINKS L397
                LEFT JOIN VALD V2989 ON V2989.OBJ_ID = L397.OBJ_ID AND V2989.PARAM_ID = 2989 AND V2989.IS_DEL = 0
                WHERE L397.PARENT_ID = :I$OBJ_ID AND L397.OBJ_TYPE_ID = 397 AND L397.DATE_DEL IS NULL AND (V2989.VAL IS NULL OR V2989.VAL > CURRENT_DATE)
            )) THEN VAL = 'Да'; ELSE VAL = 'Нет';
        END
        ELSE IF(I$DO_FUNC = 1043) THEN
        BEGIN
            -- Даты дистанционного обучения
            IF(I$PARAM_ID = 1148) THEN
                VAL = (SELECT RESULT FROM PERSON_MOVEMENTS M LEFT JOIN DATE2STR(M.DATE_IN) ON 1 = 1 WHERE M.OBJ_ID = :I$OBJ_ID);
            ELSE IF(I$PARAM_ID = 1149) THEN
                VAL = (SELECT RESULT FROM PERSON_MOVEMENTS M LEFT JOIN DATE2STR(M.DATE_OUT) ON 1 = 1 WHERE M.OBJ_ID = :I$OBJ_ID);
        END
        ELSE IF(I$DO_FUNC = 1044) THEN
        BEGIN
            -- Результат синхронизации РК
            SELECT D.RESULT || ' ' || SUBSTRING(100 + EXTRACT(HOUR FROM L.DATE_MODIFY) FROM 2) || ':' || SUBSTRING(100 + EXTRACT(MINUTE FROM L.DATE_MODIFY) FROM 2),
              L.STATE_ID, COALESCE(L.MSG, '') || COALESCE(', ' || L.VER_MSG, '')
            FROM SYNC_LOG L
            LEFT JOIN DATE2STR(L.DATE_MODIFY) D ON 1 = 1
            WHERE L.PERSON_ID = :I$OBJ_ID
            INTO :V$YEAR_VAL, :V$Y, :VAL;

            IF(V$Y = 0) THEN V$YEAR_VAL = V$YEAR_VAL || ', без изменений';
            ELSE IF(V$Y = 1) THEN V$YEAR_VAL = V$YEAR_VAL || ', успешно обновлено';
            ELSE IF(V$Y = 2) THEN V$YEAR_VAL = V$YEAR_VAL || ', учетные записи склеены';
            ELSE IF(V$Y = 3) THEN V$YEAR_VAL = V$YEAR_VAL || ', связано с новой учетной записью';
            ELSE IF(V$Y = -1) THEN V$YEAR_VAL = V$YEAR_VAL || ', ошибка, требуется перерегистрация';
            ELSE IF(V$Y = -2) THEN V$YEAR_VAL = V$YEAR_VAL || ', ошибка, конфликт идентификации';
            ELSE V$YEAR_VAL = NULL;

            IF(CHAR_LENGTH(VAL) > 0) THEN VAL = V$YEAR_VAL || ': ' || VAL; ELSE VAL = V$YEAR_VAL;
        END
        ELSE IF(I$DO_FUNC = 1045) THEN
        BEGIN
            -- Название здания по помещению
            SELECT V421.VAL
            FROM VALR V558
            JOIN LINKS LP16 ON LP16.OBJ_ID = V558.VAL AND LP16.PARENT_TYPE_ID = 16 AND LP16.DATE_DEL IS NULL
            JOIN VALS V421 ON V421.OBJ_ID = LP16.PARENT_ID AND V421.PARAM_ID = 421 AND V421.IS_DEL = 0
            WHERE V558.IS_DEL = 0 AND V558.PARAM_ID IN (558, 679) AND V558.OBJ_ID = :I$OBJ_ID
            INTO :VAL;
        END
        ELSE IF(I$DO_FUNC = 1046) THEN
        BEGIN
            -- Сумма посадочных мест в здании
            SELECT SUM(V532.VAL)
            FROM LINKS L61
            JOIN VALI V532 ON V532.OBJ_ID = L61.OBJ_ID AND V532.PARAM_ID = 562 AND V532.IS_DEL = 0
            WHERE L61.PARENT_ID = :I$OBJ_ID AND L61.OBJ_TYPE_ID = 61 AND L61.DATE_DEL IS NULL
            INTO :I;
            VAL = I;
        END
        ELSE IF(I$DO_FUNC = 1047) THEN
        BEGIN
            SELECT COALESCE(VAL, 0) FROM VALI WHERE OBJ_ID = :I$OBJ_ID AND PARAM_ID = 3101 INTO :N1;
            SELECT COALESCE(VAL, 0) FROM VALI WHERE OBJ_ID = :I$OBJ_ID AND PARAM_ID = 3102 INTO :N2;

            IF(N1 > 0 AND N2 > 0) THEN I = 1000.0 * N2 / N1; ELSE I = 0;
            VAL = CAST(0.1 * I AS NUMERIC(18, 1));
            I = I / 10;
        END
        ELSE IF(I$DO_FUNC = 1048) THEN
        BEGIN
            SELECT VAL
            FROM MONITORING_DO_FUNC8(:I$OBJ_ID)
            INTO :VAL;
        END
        ELSE IF(I$DO_FUNC = 1049) THEN
        BEGIN
            SELECT USER_NAME, IS_BLOCKED FROM PARENT_ACCOUNT_INFO(:I$OBJ_ID) INTO :VAL, :V$OBJ_ID;
            IF(VAL IS NOT NULL) THEN
            BEGIN
                IF(V$OBJ_ID = 0) THEN VAL = VAL || ' - действующий'; ELSE VAL = VAL || ' - заблокирован';
            END
        END
        ELSE IF(I$DO_FUNC = 1050) THEN
        BEGIN
            SELECT LISTVAL_ID, VAL
            FROM DO_FUNC_MOVEMENT(:I$OBJ_ID, :I$PARAM_ID)
            INTO :I, :VAL;
        END
        ELSE IF(I$DO_FUNC = 1051) THEN
        BEGIN
            SELECT VAL
            FROM DO_FAM_FIELD(:I$OBJ_ID, :I$PARAM_ID)
            INTO :VAL;
        END
        ELSE IF(I$DO_FUNC = 1052) THEN
        BEGIN
            SELECT FIRST 1 C.CAPTION
            FROM LINKS LP400
            LEFT JOIN OBJECT_CAPTION_GET(LP400.PARENT_ID) C ON 1 = 1
            WHERE LP400.OBJ_ID = :I$OBJ_ID AND LP400.PARENT_TYPE_ID IN (50, 400) AND LP400.DATE_DEL IS NULL
            INTO :VAL;
        END
        ELSE IF(I$DO_FUNC = 1053) THEN
        BEGIN
            SELECT VAL, I
            FROM GZ_FUNC(:I$OBJ_ID, :I$PARAM_ID)
            INTO :VAL, :I;
        END
        ELSE IF(I$DO_FUNC = 1054) THEN
        BEGIN
            -- Максимальное количество баллов для критерия аттестации
            SELECT CAST(LV.COST AS INTEGER), CAST(LV.COST AS INTEGER)
            FROM VALL V
            JOIN LISTVALS LV ON LV.LISTVAL_ID = V.LISTVAL_ID
            WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 3292 AND V.IS_DEL = 0
            INTO :VAL, :I;
        END
        ELSE IF(I$DO_FUNC = 1055) THEN
        BEGIN
          -- Группа лет по стажу (общий или педагогический)
          SELECT V FROM VAL_GET(:I$OBJ_ID, IIF(:I$PARAM_ID = 3311, 462, 463)) INTO :VAL;
          IF(VAL IS NULL OR VAL = '') THEN VAL = 0;
          -- Группируем по 5-леткам, минимально 5 лет, максимально 50 лет
          I = VAL;
          I = CAST(I / (360 * 5) AS INTEGER) * 5;
          IF(I > 50) THEN I = 50;
          -- Добавляем к коду 100000 чтобы не наложилось на реальные LISTVAL
          I = I + 100000;

          VAL = I;
        END
        ELSE IF(I$DO_FUNC = 1056) THEN
        BEGIN
          IF(I$PARAM_ID = 3450) THEN
          BEGIN
            -- Получение названия параметра в настройках лимитов
            SELECT R2.VAL || ' - ' || R.VAL
            FROM VALI V3449
            JOIN PARAMS P ON P.PARAM_ID = V3449.VAL
            JOIN RES R ON R.RES_ID = P.RES_ID AND R.LANG_CODE = 'RU'
            JOIN TYPES T ON T.TYPE_ID = P.TYPE_ID
            JOIN RES R2 ON R2.RES_ID = T.RES_ID AND R2.LANG_CODE = 'RU'
            WHERE V3449.OBJ_ID = :I$OBJ_ID AND V3449.PARAM_ID = 3449 AND V3449.IS_DEL = 0
            INTO :VAL;
          END
          ELSE
          BEGIN
            -- Значение или формула для контроля
            SELECT FIRST 1 V3455.VAL
            FROM VALS V3455
            WHERE V3455.OBJ_ID = :I$OBJ_ID AND V3455.PARAM_ID = 3455 AND V3455.IS_DEL = 0
            INTO :VAL;

            -- Если поле типа LISTVAL, достаем текстовое наименование по id
            IF(EXISTS(
              SELECT FIRST 1 1
              FROM VALI V3449
              JOIN PARAMS P ON P.PARAM_ID = V3449.VAL AND P.PARAM_TYPE = 6
              WHERE V3449.OBJ_ID = :I$OBJ_ID AND V3449.PARAM_ID = 3449 AND V3449.IS_DEL = 0
            ))
            THEN
            BEGIN
              IF(VAL IS NULL) THEN VAL = 'Наличие значения';
              ELSE
              BEGIN
                SELECT C.VAL
                FROM LISTVAL_TEXT(CAST(:VAL AS BIGINT)) C
                INTO :VAL;
              END
            END
          END
        END
        -- Название учебного коллектива связанного с УП
        ELSE IF(I$DO_FUNC = 1057) THEN
        BEGIN
          SELECT C.CAPTION
          FROM OBJECT_CAPTION_GET(:I$OBJ_ID) C
          INTO :VAL;
        END
        -- Рабочий год в отпусках
        ELSE IF(I$DO_FUNC = 1058) THEN
        BEGIN
        END
        -- Остаток дней отпуска в календарном году
        ELSE IF(I$DO_FUNC = 1059) THEN
        BEGIN
          SELECT N, N
          FROM VACATION_DAYS_REST(:I$OBJ_ID)
          INTO :VAL, :I;
        END
    END
    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DO_FUNC_COUNT (
    I$OBJ_ID BIGINT,
    I$DO_FUNC BIGINT)
RETURNS (
    VAL INTEGER)
AS
declare variable V$OBJ_ID bigint;
BEGIN
    VAL = 0;

    IF (I$DO_FUNC IN (6, 61)) THEN
    /* Общее количество учащихся */
    BEGIN
        FOR
            -- Все ОО района
            SELECT OBJ_ID
            FROM OBJECT_CHILDREN_GET_DEEP(:I$OBJ_ID, 2, 1)
            WHERE :I$DO_FUNC = 61
            UNION ALL
            -- Конкретное ОО
            SELECT FIRST 1 OBJ_ID
            FROM OBJECT_PARENTS_GET(:I$OBJ_ID, 2)
            WHERE :I$DO_FUNC = 6
            INTO :V$OBJ_ID
        DO
        BEGIN
            SELECT :VAL + COUNT(*)
            FROM (
                SELECT L8.OBJ_ID
                FROM LINKS L7
                JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.DATE_DEL IS NULL AND L8.OBJ_TYPE_ID IN (8, 242)
                WHERE L7.PARENT_ID = :V$OBJ_ID AND L7.DATE_DEL IS NULL AND L7.OBJ_TYPE_ID IN (7, 211)
                UNION
                -- УДОД
                SELECT L242.OBJ_ID
                FROM LINKS L242
                WHERE L242.PARENT_ID = :V$OBJ_ID AND L242.OBJ_TYPE_ID = 242 AND L242.DATE_DEL IS NULL
            ) L8

            JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.DATE_DEL IS NULL AND L9.OBJ_TYPE_ID IN (9, 243)
            JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.DATE_DEL IS NULL AND L10.OBJ_TYPE_ID = 10
            INTO :VAL;
            -- Колледж - академический отпуск
            SELECT :VAL + COUNT(*)
            FROM LINKS L7
            JOIN LINKS L289 ON L289.PARENT_ID = L7.OBJ_ID AND L289.DATE_DEL IS NULL AND L289.OBJ_TYPE_ID = 289
            JOIN LINKS L10 ON L10.PARENT_ID = L289.OBJ_ID AND L10.DATE_DEL IS NULL AND L10.OBJ_TYPE_ID = 10
            WHERE L7.PARENT_ID = :V$OBJ_ID AND L7.DATE_DEL IS NULL AND L7.OBJ_TYPE_ID = 7

            INTO :VAL;
        END
    END
    ELSE IF (I$DO_FUNC IN (7, 62)) THEN
    /* Количество учащихся девочек */
    BEGIN
        FOR
            -- Все ОО района
            SELECT OBJ_ID
            FROM OBJECT_CHILDREN_GET_DEEP(:I$OBJ_ID, 2, 1)
            WHERE :I$DO_FUNC = 62
            UNION ALL
            -- Конкретное ОО
            SELECT FIRST 1 OBJ_ID
            FROM OBJECT_PARENTS_GET(:I$OBJ_ID, 2)
            INTO :V$OBJ_ID
        DO
        BEGIN
            SELECT :VAL + COUNT(*)
            FROM (
                SELECT L8.OBJ_ID
                FROM LINKS L7
                JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.DATE_DEL IS NULL AND L8.OBJ_TYPE_ID IN (8, 242)
                WHERE L7.PARENT_ID = :V$OBJ_ID AND L7.DATE_DEL IS NULL AND L7.OBJ_TYPE_ID IN (7, 211)
                UNION
                -- УДОД
                SELECT L242.OBJ_ID
                FROM LINKS L242
                WHERE L242.PARENT_ID = :V$OBJ_ID AND L242.OBJ_TYPE_ID = 242 AND L242.DATE_DEL IS NULL
            ) L8

            JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.DATE_DEL IS NULL AND L9.OBJ_TYPE_ID IN (9, 243)
            JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.DATE_DEL IS NULL AND L10.OBJ_TYPE_ID = 10
            JOIN VALL V88 ON V88.OBJ_ID = L10.OBJ_ID AND V88.PARAM_ID = 88 AND V88.LISTVAL_ID = 182 AND V88.IS_DEL = 0

            INTO :VAL;
            -- Колледж - академический отпуск
            SELECT :VAL + COUNT(*)
            FROM LINKS L7
            JOIN LINKS L289 ON L289.PARENT_ID = L7.OBJ_ID AND L289.DATE_DEL IS NULL AND L289.OBJ_TYPE_ID = 289
            JOIN LINKS L10 ON L10.PARENT_ID = L289.OBJ_ID AND L10.DATE_DEL IS NULL AND L10.OBJ_TYPE_ID = 10
            JOIN VALL V88 ON V88.OBJ_ID = L10.OBJ_ID AND V88.PARAM_ID = 88 AND V88.LISTVAL_ID = 182 AND V88.IS_DEL = 0
            WHERE L7.PARENT_ID = :V$OBJ_ID AND L7.DATE_DEL IS NULL AND L7.OBJ_TYPE_ID = 7
            INTO :VAL;
        END
    END
    ELSE IF (I$DO_FUNC IN (8, 63)) THEN
    /* Количество учащихся мальчиков */
    BEGIN
        FOR
            SELECT OBJ_ID
            FROM OBJECT_CHILDREN_GET_DEEP(:I$OBJ_ID, 2, 1)
            WHERE :I$DO_FUNC = 63

            UNION ALL

            SELECT FIRST 1 OBJ_ID
            FROM OBJECT_PARENTS_GET(:I$OBJ_ID, 2)
            INTO :V$OBJ_ID
        DO
        BEGIN
            SELECT :VAL + COUNT(*)
            FROM (
                SELECT L8.OBJ_ID
                FROM LINKS L7
                JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.DATE_DEL IS NULL AND L8.OBJ_TYPE_ID IN (8, 242)
                WHERE L7.PARENT_ID = :V$OBJ_ID AND L7.DATE_DEL IS NULL AND L7.OBJ_TYPE_ID IN (7, 211)
                UNION
                SELECT L242.OBJ_ID
                FROM LINKS L242
                WHERE L242.PARENT_ID = :V$OBJ_ID AND L242.OBJ_TYPE_ID = 242 AND L242.DATE_DEL IS NULL
            ) L8

            JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.DATE_DEL IS NULL AND L9.OBJ_TYPE_ID IN (9, 243)
            JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.DATE_DEL IS NULL AND L10.OBJ_TYPE_ID = 10
            JOIN VALL V88 ON V88.OBJ_ID = L10.OBJ_ID AND V88.PARAM_ID = 88 AND V88.LISTVAL_ID = 183 AND V88.IS_DEL = 0
            INTO :VAL;
            -- Колледж - академический отпуск
            SELECT :VAL + COUNT(*)
            FROM LINKS L7
            JOIN LINKS L289 ON L289.PARENT_ID = L7.OBJ_ID AND L289.DATE_DEL IS NULL AND L289.OBJ_TYPE_ID = 289
            JOIN LINKS L10 ON L10.PARENT_ID = L289.OBJ_ID AND L10.DATE_DEL IS NULL AND L10.OBJ_TYPE_ID = 10
            JOIN VALL V88 ON V88.OBJ_ID = L10.OBJ_ID AND V88.PARAM_ID = 88 AND V88.LISTVAL_ID = 183 AND V88.IS_DEL = 0
            WHERE L7.PARENT_ID = :V$OBJ_ID AND L7.DATE_DEL IS NULL AND L7.OBJ_TYPE_ID = 7
            INTO :VAL;
        END
    END
    IF (I$DO_FUNC = 12) THEN
    /* GRADE PUPILCOUNT*/
    BEGIN
        SELECT COUNT(*)
        FROM LINKS L8
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 243) AND L9.DATE_DEL IS NULL
        JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        WHERE L8.PARENT_ID = :I$OBJ_ID AND L8.OBJ_TYPE_ID IN (8, 242) AND L8.DATE_DEL IS NULL
        INTO :VAL;
        -- Колледж - академический отпуск
        SELECT :VAL + COUNT(1)
        FROM LINKS L289
        JOIN LINKS L10 ON L10.PARENT_ID = L289.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        WHERE L289.PARENT_ID = :I$OBJ_ID AND L289.OBJ_TYPE_ID = 289 AND L289.DATE_DEL IS NULL
        INTO :VAL;
    END
    ELSE IF (I$DO_FUNC = 13) THEN
    /* GRADE GIRLS PUPILCOUNT*/
    BEGIN
        SELECT COUNT(*)
        FROM LINKS L8
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 243) AND L9.DATE_DEL IS NULL
        JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        JOIN VALL V88 ON V88.OBJ_ID = L10.OBJ_ID AND V88.PARAM_ID = 88 AND V88.LISTVAL_ID = 182 AND V88.IS_DEL = 0
        WHERE L8.PARENT_ID = :I$OBJ_ID AND L8.OBJ_TYPE_ID IN (8, 242) AND L8.DATE_DEL IS NULL
        INTO :VAL;
        -- Колледж - академический отпуск
        SELECT :VAL + COUNT(1)
        FROM LINKS L289
        JOIN LINKS L10 ON L10.PARENT_ID = L289.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        JOIN VALL V88 ON V88.OBJ_ID = L10.OBJ_ID AND V88.PARAM_ID = 88 AND V88.LISTVAL_ID = 182 AND V88.IS_DEL = 0
        WHERE L289.PARENT_ID = :I$OBJ_ID AND L289.OBJ_TYPE_ID = 289 AND L289.DATE_DEL IS NULL
        INTO :VAL;
    END
    ELSE IF (I$DO_FUNC = 14) THEN
    /* GRADE BOY PUPILCOUNT*/
    BEGIN
        SELECT COUNT(*)
        FROM LINKS L8
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 243) AND L9.DATE_DEL IS NULL
        JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        JOIN VALL V88 ON V88.OBJ_ID = L10.OBJ_ID AND V88.PARAM_ID = 88 AND V88.LISTVAL_ID = 183 AND V88.IS_DEL = 0
        WHERE L8.PARENT_ID = :I$OBJ_ID AND L8.OBJ_TYPE_ID IN (8, 242) AND L8.DATE_DEL IS NULL
        INTO :VAL;
        -- Колледж - академический отпуск
        SELECT :VAL + COUNT(1)
        FROM LINKS L289
        JOIN LINKS L10 ON L10.PARENT_ID = L289.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        JOIN VALL V88 ON V88.OBJ_ID = L10.OBJ_ID AND V88.PARAM_ID = 88 AND V88.LISTVAL_ID = 183 AND V88.IS_DEL = 0
        WHERE L289.PARENT_ID = :I$OBJ_ID AND L289.OBJ_TYPE_ID = 289 AND L289.DATE_DEL IS NULL
        INTO :VAL;
    END
    ELSE IF (I$DO_FUNC = 58) THEN
    BEGIN
        -- FOR PARAM_ID = 2341 (кол-во студентов в академическом отпуске)
        SELECT COUNT(DISTINCT OBJ_ID)
        FROM (
            /*SELECT L10.OBJ_ID
            FROM LINKS L7
            JOIN LINKS L78 ON L78.PARENT_ID = L7.PARENT_ID AND L78.OBJ_TYPE_ID = 78 AND L78.DATE_DEL IS NULL
            JOIN LINKS L82 ON L82.PARENT_ID = L78.OBJ_ID AND L82.OBJ_TYPE_ID = 82 AND L82.DATE_DEL IS NULL
            JOIN LINKS L10 ON L10.PARENT_ID = L82.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
            JOIN PERSON_MOVEMENTS M ON M.DATE_DEL IS NULL AND M.PERSON_ID = L10.OBJ_ID AND M.DATE_OUT IS NOT NULL AND M.REASON_OUT = 5319
            WHERE L7.OBJ_ID = :I$OBJ_ID AND L7.PARENT_TYPE_ID = 2 AND L7.DATE_DEL IS NULL
              AND M.OBJ_ID = (
                  SELECT FIRST 1 M.OBJ_ID
                  FROM PERSON_MOVEMENTS MM
                  JOIN OBJECTS O ON O.OBJ_ID = MM.GROUP_ID AND O.TYPE_ID = 9
                  WHERE MM.DATE_DEL IS NULL AND MM.PERSON_ID = L10.OBJ_ID
                  ORDER BY MM.DATE_OUT DESC
              )
            UNION*/
            SELECT L10.OBJ_ID
            FROM LINKS L289
            JOIN LINKS L10 ON L10.PARENT_ID = L289.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
            WHERE L289.PARENT_ID = :I$OBJ_ID AND L289.OBJ_TYPE_ID = 289 AND L289.DATE_DEL IS NULL
        )
        INTO :VAL;
    END
    /* Количество учащихся по учебному плану */
    ELSE IF (I$DO_FUNC = 1039) THEN
    BEGIN
        SELECT COUNT(DISTINCT OBJ_ID)
        FROM (
            SELECT L10.OBJ_ID
            FROM LINKS L54
            JOIN LINKS L256 ON L256.PARENT_ID = L54.OBJ_ID AND L256.OBJ_TYPE_ID = 256 AND L256.DATE_DEL IS NULL
            JOIN LINKS L10 ON L10.PARENT_ID = L256.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
            WHERE L54.PARENT_ID = :I$OBJ_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
            UNION
            SELECT L10.OBJ_ID
            FROM LINKS L54
            JOIN LINKS L346 ON L346.PARENT_ID = L54.OBJ_ID AND L346.OBJ_TYPE_ID = 346 AND L346.DATE_DEL IS NULL
            JOIN LINKS L347 ON L346.PARENT_ID = L346.OBJ_ID AND L347.OBJ_TYPE_ID = 347 AND L347.DATE_DEL IS NULL
            JOIN LINKS L10 ON L10.PARENT_ID = L347.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
            WHERE L54.PARENT_ID = :I$OBJ_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
        )
        INTO :VAL;
    END
    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DO_FUNC_MOVEMENT (
    I$OBJ_ID BIGINT,
    I$PARAM_ID BIGINT)
RETURNS (
    LISTVAL_ID BIGINT,
    VAL VARCHAR(1000))
AS
begin

  IF(I$PARAM_ID = 3124) THEN
  BEGIN
    -- Дата зачисления
    SELECT D.RESULT
    FROM PERSON_MOVEMENTS M
    LEFT JOIN DATE2STR(M.DATE_IN) D ON 1 = 1
    WHERE M.OBJ_ID = :I$OBJ_ID
    INTO :VAL;
  END
  ELSE IF(I$PARAM_ID = 3125) THEN
  BEGIN
    -- Дата приказа о зачислении
    SELECT D.RESULT
    FROM PERSON_MOVEMENTS M
    LEFT JOIN DATE2STR(M.ORDER_DATE_IN) D ON 1 = 1
    WHERE M.OBJ_ID = :I$OBJ_ID
    INTO :VAL;
  END
  ELSE IF(I$PARAM_ID = 3126) THEN
  BEGIN
    -- Номер приказа о зачислении
    SELECT M.ORDER_NUM_IN
    FROM PERSON_MOVEMENTS M
    WHERE M.OBJ_ID = :I$OBJ_ID
    INTO :VAL;
  END
  ELSE IF(I$PARAM_ID = 3127) THEN
  BEGIN
    -- Дата отчисления
    SELECT D.RESULT
    FROM PERSON_MOVEMENTS M
    LEFT JOIN DATE2STR(M.DATE_OUT) D ON 1 = 1
    WHERE M.OBJ_ID = :I$OBJ_ID
    INTO :VAL;
  END
  ELSE IF(I$PARAM_ID = 3128) THEN
  BEGIN
    -- Дата приказа об отчислении
    SELECT D.RESULT
    FROM PERSON_MOVEMENTS M
    LEFT JOIN DATE2STR(M.ORDER_DATE_OUT) D ON 1 = 1
    WHERE M.OBJ_ID = :I$OBJ_ID
    INTO :VAL;
  END
  ELSE IF(I$PARAM_ID = 3129) THEN
  BEGIN
    -- Номер приказа об отчислении
    SELECT M.ORDER_NUM_OUT
    FROM PERSON_MOVEMENTS M
    WHERE M.OBJ_ID = :I$OBJ_ID
    INTO :VAL;
  END
  ELSE IF(I$PARAM_ID = 3130) THEN
  BEGIN
    -- Название коллектива
    SELECT M.GROUP_ID, M.NAME_IN
    FROM PERSON_MOVEMENTS M
    WHERE M.OBJ_ID = :I$OBJ_ID
    INTO :LISTVAL_ID, :VAL;
  END
  ELSE IF(I$PARAM_ID = 3131) THEN
  BEGIN
    -- id коллектива
    SELECT M.GROUP_ID, M.GROUP_ID
    FROM PERSON_MOVEMENTS M
    WHERE M.OBJ_ID = :I$OBJ_ID
    INTO :LISTVAL_ID, :VAL;
  END
  ELSE IF(I$PARAM_ID = 3132) THEN
  BEGIN
    -- Тип зачисления
    SELECT M.REASON_IN, C.VAL
    FROM PERSON_MOVEMENTS M
    LEFT JOIN LISTVAL_TEXT(M.REASON_IN) C ON 1 = 1
    WHERE M.OBJ_ID = :I$OBJ_ID
    INTO :LISTVAL_ID, :VAL;
  END
  ELSE IF(I$PARAM_ID = 3133) THEN
  BEGIN
    -- Тип отчисления
    SELECT M.REASON_OUT, C.VAL
    FROM PERSON_MOVEMENTS M
    LEFT JOIN LISTVAL_TEXT(M.REASON_OUT) C ON 1 = 1
    WHERE M.OBJ_ID = :I$OBJ_ID
    INTO :LISTVAL_ID, :VAL;
  END
  ELSE IF(I$PARAM_ID = 3134) THEN
  BEGIN
    -- Является ли классом
    SELECT IIF(G.TYPE_ID = 9, 2, 3), IIF(G.TYPE_ID = 9, 'Да', 'Нет')
    FROM PERSON_MOVEMENTS M
    JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID
    WHERE M.OBJ_ID = :I$OBJ_ID
    INTO :LISTVAL_ID, :VAL;
  END
  ELSE IF(I$PARAM_ID = 3135) THEN
  BEGIN
    -- id типа коллектива
    SELECT G.TYPE_ID, G.TYPE_ID
    FROM PERSON_MOVEMENTS M
    JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID
    WHERE M.OBJ_ID = :I$OBJ_ID
    INTO :LISTVAL_ID, :VAL;
  END
  ELSE IF(I$PARAM_ID = 3136) THEN
  BEGIN
    -- Этап
    SELECT M.STAGE_ID, C.VAL
    FROM PERSON_MOVEMENTS M
    LEFT JOIN LISTVAL_TEXT(M.STAGE_ID) C ON 1 = 1
    WHERE M.OBJ_ID = :I$OBJ_ID
    INTO :LISTVAL_ID, :VAL;
  END
  ELSE IF(I$PARAM_ID = 3137) THEN
  BEGIN
    -- Тип коллектива
    SELECT M.TYPE_IN, C.VAL
    FROM PERSON_MOVEMENTS M
    LEFT JOIN LISTVAL_TEXT(M.TYPE_IN) C ON 1 = 1
    WHERE M.OBJ_ID = :I$OBJ_ID
    INTO :LISTVAL_ID, :VAL;
  END
  ELSE IF(I$PARAM_ID = 3138) THEN
  BEGIN
    -- Причина зачисления
    SELECT M.SOURCE_IN, C.VAL
    FROM PERSON_MOVEMENTS M
    LEFT JOIN LISTVAL_TEXT(M.SOURCE_IN) C ON 1 = 1
    WHERE M.OBJ_ID = :I$OBJ_ID
    INTO :LISTVAL_ID, :VAL;
  END
  ELSE IF(I$PARAM_ID = 3139) THEN
  BEGIN
    -- Причина отчисления
    SELECT M.SOURCE_OUT, C.VAL
    FROM PERSON_MOVEMENTS M
    LEFT JOIN LISTVAL_TEXT(M.SOURCE_OUT) C ON 1 = 1
    WHERE M.OBJ_ID = :I$OBJ_ID
    INTO :LISTVAL_ID, :VAL;
  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DO_OBJECT_FILLED_CHECK (
    I$OBJ_ID BIGINT)
RETURNS (
    IS_OK SMALLINT,
    MSG VARCHAR(4000))
AS
BEGIN
    IS_OK = 1;
    FOR
        SELECT CASE
                   WHEN CHAR_LENGTH(VG.V) > 0 THEN 1
                   ELSE 0
               END

        FROM OBJECTS O

        JOIN PARAMS P
        ON P.TYPE_ID = O.TYPE_ID
        AND P.IS_REQUIRED = 1

        JOIN VAL_GET(:I$OBJ_ID, P.PARAM_ID) VG
        ON 1=1

        WHERE O.OBJ_ID = :I$OBJ_ID
        INTO :IS_OK
    DO
    BEGIN
        IF (IS_OK = 0) THEN
        BEGIN
            BREAK;
        END
    END
    IF (IS_OK = 0) THEN
    BEGIN
        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:I$OBJ_ID)
        INTO :MSG;
    END

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DPO_DOCUMENTS_LIST (
    I$OBJ_ID BIGINT)
RETURNS (
    SERIE VARCHAR(100),
    NUMBER VARCHAR(100),
    ISSUE_DATE DATE,
    ISSUED_BY VARCHAR(1000),
    COURSE_NAME VARCHAR(1000),
    COURSE_HOURS INTEGER,
    DATE_FROM DATE,
    DATE_TO DATE)
AS
declare variable V$GROUP_ID bigint;
declare variable V$COURSE_NAME varchar(1000);
begin

  -- Неясно, актуальна ли еще процедура

  FOR
      SELECT V564.VAL, V565.VAL, V566.VAL, V568.VAL
      FROM LINKS L11
      JOIN VALS V564 ON V564.OBJ_ID = L11.OBJ_ID AND V564.PARAM_ID = 564 AND V564.IS_DEL = 0
      JOIN VALS V565 ON V565.OBJ_ID = L11.OBJ_ID AND V565.PARAM_ID = 565 AND V565.IS_DEL = 0
      JOIN VALD V566 ON V566.OBJ_ID = L11.OBJ_ID AND V566.PARAM_ID = 566 AND V566.IS_DEL = 0
      JOIN VALS V568 ON V568.OBJ_ID = L11.OBJ_ID AND V568.PARAM_ID = 568 AND V568.IS_DEL = 0
      WHERE L11.PARENT_ID = :I$OBJ_ID AND L11.OBJ_TYPE_ID = 11 AND L11.DATE_DEL IS NULL
      INTO :SERIE, :NUMBER, :ISSUE_DATE, :ISSUED_BY
  DO
  BEGIN
      V$GROUP_ID = NULL;
      COURSE_NAME = NULL;
      COURSE_HOURS = NULL;
      DATE_FROM = NULL;
      DATE_TO = NULL;

      SELECT FIRST 1 M.GROUP_ID, V2963.VAL, V2959.VAL, V2960.VAL
      FROM PERSON_MOVEMENTS M
      JOIN OBJECTS O ON O.OBJ_ID = M.GROUP_ID AND O.TYPE_ID = 46
      -- Оригинальное название и даты группы - либо из V1610, либо из УП
      JOIN VALD V2959 ON V2959.OBJ_ID = M.GROUP_ID AND V2959.PARAM_ID = 2959 AND V2959.IS_DEL = 0
      JOIN VALD V2960 ON V2960.OBJ_ID = M.GROUP_ID AND V2960.PARAM_ID = 2960 AND V2960.IS_DEL = 0
      LEFT JOIN VALS V2963 ON V2963.OBJ_ID = M.GROUP_ID AND V2963.PARAM_ID = 2963 AND V2963.IS_DEL = 0
      WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :I$OBJ_ID
          AND :ISSUE_DATE >= V2959.VAL AND :ISSUE_DATE <= DATEADD(1 MONTH TO V2960.VAL)
      INTO :V$GROUP_ID, :COURSE_NAME, :DATE_FROM, :DATE_TO;

      -- Достаем часы пока из УП
      SELECT FIRST 1 V2961.VAL, V374.VAL
      FROM VALR V2823
      JOIN VALI V2961 ON V2961.OBJ_ID = V2823.VAL AND V2961.PARAM_ID = 2961 AND V2961.IS_DEL = 0
      JOIN VALS V374 ON V374.OBJ_ID = V2823.VAL AND V374.PARAM_ID = 374 AND V374.IS_DEL = 0
      WHERE V2823.OBJ_ID = :V$GROUP_ID AND V2823.PARAM_ID = 2823 AND V2823.IS_DEL = 0
      INTO :COURSE_HOURS, :V$COURSE_NAME;

      IF(COURSE_NAME IS NULL) THEN COURSE_NAME = V$COURSE_NAME;

      IF(COURSE_NAME IS NOT NULL) THEN SUSPEND;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DPO_GROUP_FINISH (
    I$GROUP_ID BIGINT,
    I$ORDER_DATE DATE,
    I$ORDER_NUM VARCHAR(100),
    I$USER_ID BIGINT)
AS
declare variable V$DATE_FROM date;
declare variable V$DATE_TO date;
declare variable V$STUDENT_ID bigint;
declare variable V$PLAN_ID bigint;
declare variable V$PLAN_STATE bigint;
declare variable V$CAPTION varchar(1000);
declare variable V$DOC_TYPE bigint;
declare variable BLOB_ID bigint;
declare variable V$D date;
begin

  -- Проверяем, что даты попадают в допустимый диапазон
  SELECT VAL FROM VALD WHERE OBJ_ID = :I$GROUP_ID AND PARAM_ID = 2959 AND IS_DEL = 0 INTO :V$DATE_FROM;
  SELECT VAL FROM VALD WHERE OBJ_ID = :I$GROUP_ID AND PARAM_ID = 2960 AND IS_DEL = 0 INTO :V$DATE_TO;
  IF(V$DATE_FROM IS NULL OR V$DATE_TO IS NULL) THEN EXCEPTION DATA_ERROR 'Не заполнены даты начала и (или) окончания обучения';
  IF(V$DATE_FROM > CURRENT_DATE) THEN EXCEPTION DATA_ERROR 'Нельзя выполнять выпуск группы ранее, чем наступила дата начала обучения';

  IF(I$ORDER_DATE < V$DATE_FROM) THEN EXCEPTION DATA_ERROR 'Нельзя выпустить приказ с датой ранее начала обучения';
  IF(I$ORDER_DATE > DATEADD(1 MONTH TO V$DATE_TO)) THEN EXCEPTION DATA_ERROR 'Нельзя выпустить приказ с датой позднее 1 месяца с момента окончания обучения';

  -- Учебный план
  SELECT V2823.VAL, V3013.LISTVAL_ID
  FROM VALR V2823
  LEFT JOIN VALL V3013 ON V3013.OBJ_ID = V2823.VAL AND V3013.PARAM_ID = 3013 AND V3013.IS_DEL = 0
  WHERE V2823.OBJ_ID = :I$GROUP_ID AND V2823.PARAM_ID = 2823 AND V2823.IS_DEL = 0
  INTO :V$PLAN_ID, :V$PLAN_STATE;

  IF(V$PLAN_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Нельзя выпустить группу, для которой не назначен учебный план';
  IF(V$PLAN_STATE IS NULL OR V$PLAN_STATE <> 11715) THEN EXCEPTION DATA_ERROR 'Нельзя выпустить группу с неутвержденным учебным планом';

  IF(NOT EXISTS(
      SELECT FIRST 1 1
      FROM LINKS LP86
      WHERE LP86.OBJ_ID = :I$GROUP_ID AND LP86.PARENT_TYPE_ID = 86 AND LP86.DATE_DEL IS NULL
  )) THEN EXCEPTION DATA_ERROR 'Группа не найдена. Возможно что отметка завершения обучения уже выполнена';

  -- Проверка дат зачисления в группу
  FOR
      SELECT M.PERSON_ID, M.DATE_IN
      FROM PERSON_MOVEMENTS M
      WHERE M.DATE_DEL IS NULL AND M.GROUP_ID = :I$GROUP_ID AND M.DATE_OUT IS NULL
      INTO :V$STUDENT_ID, :V$D
  DO
  BEGIN
      IF(V$D > V$DATE_TO) THEN EXCEPTION DATA_ERROR 'Дата зачисления ' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$STUDENT_ID)) ||
          ' выставлена позже, чем дата окончания обучения в группе';
  END

  -- Выполняем выбытие
  FOR
      SELECT L10.OBJ_ID
      FROM LINKS L10
      WHERE L10.PARENT_ID = :I$GROUP_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      INTO :V$STUDENT_ID
  DO
  BEGIN
      V$DOC_TYPE = NULL;
      SELECT FIRST 1 V50.LISTVAL_ID
      FROM LINKS L11
      JOIN VALD V566 ON V566.OBJ_ID = L11.OBJ_ID AND V566.PARAM_ID = 566 AND V566.IS_DEL = 0 AND V566.VAL >= :V$DATE_FROM AND V566.VAL <= DATEADD(7 DAY TO :V$DATE_TO)
      JOIN VALL V50 ON V50.OBJ_ID = L11.OBJ_ID AND V50.PARAM_ID = 50 AND V50.IS_DEL = 0
      WHERE L11.PARENT_ID = :V$STUDENT_ID AND L11.OBJ_TYPE_ID = 11 AND L11.DATE_DEL IS NULL
      ORDER BY V566.VAL
      INTO :V$DOC_TYPE;

      IF(V$DOC_TYPE IS NULL) THEN EXCEPTION DATA_ERROR 'По обучающемуся ' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$STUDENT_ID)) ||
          ' не внесен документ об образовании';

      SELECT OBJ_ID FROM VARGRP_MOVE_PUPIL(:V$STUDENT_ID, :I$GROUP_ID, :I$ORDER_NUM, :I$ORDER_DATE, :V$DATE_TO, 1, :I$USER_ID, NULL,
          IIF(:V$DOC_TYPE = 11137, 12908, 12907), 3325) INTO :BLOB_ID;
  END

  -- Запоминаем название курса для истории
  SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$PLAN_ID) INTO :V$CAPTION;
  SELECT BLOB_ID FROM VAL_ADD(2963, :I$GROUP_ID, :V$CAPTION) INTO :BLOB_ID;

  -- Удаляем группу
  UPDATE LINKS LP86
  SET LP86.DATE_DEL = CURRENT_TIMESTAMP
  WHERE LP86.OBJ_ID = :I$GROUP_ID AND LP86.PARENT_TYPE_ID = 86 AND LP86.DATE_DEL IS NULL;

  -- Удаляем журналы группы, останутся только итоговые отметки
  UPDATE CJ2_JOURNAL J
  SET J.DATE_DEL = CURRENT_TIMESTAMP
  WHERE J.DATE_DEL IS NULL AND J.GRADE_ID = :I$GROUP_ID;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DPO_GROUP_MEMBERS (
    I$GROUP_ID BIGINT)
RETURNS (
    PERSON_ID BIGINT,
    LINK_ID BIGINT,
    PERSON_REGID VARCHAR(40),
    PERSON_NAME VARCHAR(1000))
AS
begin

  -- Неясно, актуальна ли еще процедура

  FOR
      SELECT L10.LINK_ID, L10.OBJ_ID, V2912.VAL, V55.VAL || ' ' || V56.VAL || COALESCE(' ' || V57.VAL, '')
      FROM LINKS L10
      JOIN VALS V55 ON V55.OBJ_ID = L10.OBJ_ID AND V55.PARAM_ID = 55 AND V55.IS_DEL = 0
      JOIN VALS V56 ON V56.OBJ_ID = L10.OBJ_ID AND V56.PARAM_ID = 56 AND V56.IS_DEL = 0
      LEFT JOIN VALS V57 ON V57.OBJ_ID = L10.OBJ_ID AND V57.PARAM_ID = 57 AND V57.IS_DEL = 0
      LEFT JOIN VALS V2912 ON V2912.OBJ_ID = L10.OBJ_ID AND V2912.PARAM_ID = 2912 AND V2912.IS_DEL = 0
      WHERE L10.PARENT_ID = :I$GROUP_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      INTO :LINK_ID, :PERSON_ID, :PERSON_REGID, :PERSON_NAME
  DO
  BEGIN
      SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DPO_GROUP_RESULTS (
    I$GROUP_ID BIGINT)
RETURNS (
    DATE_FROM DATE,
    DATE_TO DATE,
    STUDENT_ID BIGINT,
    STUDENT_NAME VARCHAR(1000),
    DOCUMENT_DATE DATE,
    DOCUMENT_SERIE VARCHAR(100),
    DOCUMENT_NUM VARCHAR(100),
    DOCUMENT_TYPE BIGINT,
    DOCUMENT_REG VARCHAR(100))
AS
begin

  IF(NOT EXISTS(
      SELECT 1
      FROM VALR V
      WHERE V.IS_DEL = 0 AND V.OBJ_ID = :I$GROUP_ID AND V.PARAM_ID = 2823
  ))
  THEN EXCEPTION DATA_ERROR 'Группа не связана с учебным планом, нечего завершать. Пустые группы можно просто удалить';

  SELECT VAL FROM VALD WHERE OBJ_ID = :I$GROUP_ID AND PARAM_ID = 2959 AND IS_DEL = 0 INTO :DATE_FROM;
  SELECT VAL FROM VALD WHERE OBJ_ID = :I$GROUP_ID AND PARAM_ID = 2960 AND IS_DEL = 0 INTO :DATE_TO;
  IF(DATE_FROM IS NULL OR DATE_TO IS NULL) THEN EXCEPTION DATA_ERROR 'Не заполнены даты начала и (или) окончания обучения';
  IF(DATE_FROM > CURRENT_DATE) THEN EXCEPTION DATA_ERROR 'Нельзя выполнять выпуск группы ранее, чем наступила дата начала обучения';

  -- Дату аттестата смотрим по дате окончания обучения в группе

  FOR
      SELECT L46.OBJ_ID, V55.VAL || ' ' || V56.VAL || COALESCE(' ' || V57.VAL, '')
      FROM LINKS L46
      JOIN VALS V55 ON V55.OBJ_ID = L46.OBJ_ID AND V55.PARAM_ID = 55 AND V55.IS_DEL = 0
      JOIN VALS V56 ON V56.OBJ_ID = L46.OBJ_ID AND V56.PARAM_ID = 56 AND V56.IS_DEL = 0
      LEFT JOIN VALS V57 ON V57.OBJ_ID = L46.OBJ_ID AND V57.PARAM_ID = 57 AND V57.IS_DEL = 0
      WHERE L46.PARENT_ID = :I$GROUP_ID AND L46.OBJ_TYPE_ID = 10 AND L46.DATE_DEL IS NULL
      INTO :STUDENT_ID, :STUDENT_NAME
  DO
  BEGIN
      DOCUMENT_DATE = NULL;
      DOCUMENT_SERIE = NULL;
      DOCUMENT_NUM = NULL;
      DOCUMENT_TYPE = NULL;

      SELECT FIRST 1 V566.VAL, V564.VAL, V565.VAL, V2969.VAL, V50.LISTVAL_ID
      FROM LINKS L11
      JOIN VALD V566 ON V566.OBJ_ID = L11.OBJ_ID AND V566.PARAM_ID = 566 AND V566.IS_DEL = 0 AND V566.VAL >= :DATE_FROM AND V566.VAL <= DATEADD(7 DAY TO :DATE_TO)
      JOIN VALL V50 ON V50.OBJ_ID = L11.OBJ_ID AND V50.PARAM_ID = 50 AND V50.IS_DEL = 0
      LEFT JOIN VALS V564 ON V564.OBJ_ID = L11.OBJ_ID AND V564.PARAM_ID = 564 AND V564.IS_DEL = 0
      LEFT JOIN VALS V565 ON V565.OBJ_ID = L11.OBJ_ID AND V565.PARAM_ID = 565 AND V565.IS_DEL = 0
      LEFT JOIN VALS V2969 ON V2969.OBJ_ID = L11.OBJ_ID AND V2969.PARAM_ID = 2969 AND V2969.IS_DEL = 0
      WHERE L11.PARENT_ID = :STUDENT_ID AND L11.OBJ_TYPE_ID = 11 AND L11.DATE_DEL IS NULL
      ORDER BY 1
      INTO :DOCUMENT_DATE, :DOCUMENT_SERIE, :DOCUMENT_NUM, :DOCUMENT_REG, :DOCUMENT_TYPE;

      IF(DOCUMENT_TYPE <> 11137 AND (DOCUMENT_SERIE IS NULL OR DOCUMENT_NUM IS NULL OR DOCUMENT_REG IS NULL)) THEN
          EXCEPTION DATA_ERROR 'Не внесены обязательные серия, номер бланка или регистрационный номер документа об образовании по ' || STUDENT_NAME;

      -- Надо еще проверить дату зачисления в группу
      -- !!!

      SUSPEND;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DPO_GROUP_SYNC (
    I$PLAN_ID BIGINT,
    I$LINK_ID BIGINT,
    I$GROUP_ID BIGINT,
    I$PARENT_ID BIGINT,
    I$OBJ_NAME VARCHAR(1000),
    I$DATE_FROM DATE,
    I$DATE_TO DATE,
    I$GROUP_TYPE_ID BIGINT,
    I$FORM_ID BIGINT,
    I$FINANCING_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$PARENT_ID bigint;
declare variable V$DATE_DEL timestamp;
declare variable TMP bigint;
begin

  -- Проверять, что это уровень региона
  -- !!!

  SELECT FIRST 1 L86.OBJ_ID, L46.OBJ_ID, L46.DATE_DEL
  FROM LINKS L86
  LEFT JOIN LINKS L46 ON L46.PARENT_ID = L86.OBJ_ID AND L46.OBJ_TYPE_ID = 46 AND L46.OBJ_ID = :I$GROUP_ID
  WHERE L86.PARENT_TYPE_ID = 2 AND L86.OBJ_TYPE_ID = 86 AND L86.OBJ_ID = :I$PARENT_ID AND L86.DATE_DEL IS NULL
  INTO :V$PARENT_ID, :OBJ_ID, :V$DATE_DEL;

  IF(V$PARENT_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не найден каталог образовательных программ. Необходимо выполнить передачу данных через экспорт-импорт';
  IF(V$DATE_DEL IS NOT NULL) THEN EXCEPTION DATA_ERROR 'Данный объект уже был удален в региональной базе, конфликт версий';

  -- Если объекта нет - создаем новый
  IF(OBJ_ID IS NULL) THEN
  BEGIN
      OBJ_ID = I$GROUP_ID;
      INSERT INTO OBJECTS (OBJ_ID, TYPE_ID) VALUES (:I$GROUP_ID, 46);
      INSERT INTO LINKS (LINK_ID, PARENT_ID, PARENT_TYPE_ID, OBJ_ID, OBJ_TYPE_ID, DATE_INS) VALUES (:I$LINK_ID, :I$PARENT_ID, 86, :I$GROUP_ID, 46, CURRENT_TIMESTAMP);
  END

  -- Обновляем параметры
  SELECT BLOB_ID FROM VAL_ADD(549, :I$GROUP_ID, :I$OBJ_NAME) INTO :TMP;
  SELECT BLOB_ID FROM VAL_ADD(2959, :I$GROUP_ID, :I$DATE_FROM) INTO :TMP;
  SELECT BLOB_ID FROM VAL_ADD(2960, :I$GROUP_ID, :I$DATE_TO) INTO :TMP;
  SELECT BLOB_ID FROM VAL_ADD(369, :I$GROUP_ID, :I$GROUP_TYPE_ID) INTO :TMP;
  SELECT BLOB_ID FROM VAL_ADD(2137, :I$GROUP_ID, :I$FORM_ID) INTO :TMP;
  SELECT BLOB_ID FROM VAL_ADD(2825, :I$GROUP_ID, :I$FINANCING_ID) INTO :TMP;

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DPO_PERSON_GROUP_ADD (
    I$GROUP_ID BIGINT NOT NULL,
    I$PERSON_REGID VARCHAR(40),
    I$NAME_LAST VARCHAR(400),
    I$NAME_FIRST VARCHAR(400),
    I$NAME_MID VARCHAR(400),
    I$BIRTH_DATE DATE,
    I$SEX BIGINT,
    I$SNILS VARCHAR(40),
    I$PHONE_NUMBER VARCHAR(400))
AS
declare variable V$PLAN_ID bigint;
declare variable V$OBJ_ID bigint;
declare variable TMP bigint;
begin

  SELECT V2823.VAL
  FROM VALR V2823
  WHERE V2823.OBJ_ID = :I$GROUP_ID AND V2823.PARAM_ID = 2823 AND V2823.IS_DEL = 0
  INTO :V$PLAN_ID;

  IF(V$PLAN_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Группе не назначен учебный план';

  -- Проверить, что у всех участников назначены РК
  -- !!!

  -- Нет ли этого участника уже в какой-нибудь другой группе этой программы ?
  IF(EXISTS(
      SELECT FIRST 1 1
      FROM LINKS L86
      JOIN LINKS L46 ON L46.PARENT_ID = L86.OBJ_ID AND L46.OBJ_TYPE_ID = 46 AND L46.DATE_DEL IS NULL AND L46.OBJ_ID <> :I$GROUP_ID
      JOIN VALR V2823 ON V2823.OBJ_ID = L46.OBJ_ID AND V2823.PARAM_ID = 2823 AND V2823.IS_DEL = 0 AND V2823.VAL = :V$PLAN_ID
      JOIN LINKS L10 ON L10.PARENT_ID = L46.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      JOIN VALS V2912 ON V2912.OBJ_ID = L10.OBJ_ID AND V2912.PARAM_ID = 2912 AND V2912.IS_DEL = 0 AND V2912.VAL = :I$PERSON_REGID
      WHERE L86.PARENT_TYPE_ID = 2 AND L86.OBJ_TYPE_ID = 86 AND L86.DATE_DEL IS NULL
  )) THEN EXCEPTION DATA_ERROR I$NAME_FIRST || ' ' || I$NAME_LAST || ' уже зачислен в другую группу этой же программы';

  SELECT OBJ_ID FROM OBJECT_ADD(:I$GROUP_ID, 10) INTO :V$OBJ_ID;
  SELECT BLOB_ID FROM VAL_ADD(55, :V$OBJ_ID, :I$NAME_LAST) INTO :TMP;
  SELECT BLOB_ID FROM VAL_ADD(56, :V$OBJ_ID, :I$NAME_FIRST) INTO :TMP;
  SELECT BLOB_ID FROM VAL_ADD(57, :V$OBJ_ID, :I$NAME_MID) INTO :TMP;
  SELECT BLOB_ID FROM VAL_ADD(89, :V$OBJ_ID, :I$BIRTH_DATE) INTO :TMP;
  SELECT BLOB_ID FROM VAL_ADD(88, :V$OBJ_ID, :I$SEX) INTO :TMP;
  SELECT BLOB_ID FROM VAL_ADD(1409, :V$OBJ_ID, :I$SNILS) INTO :TMP;
  SELECT BLOB_ID FROM VAL_ADD(102, :V$OBJ_ID, :I$PHONE_NUMBER) INTO :TMP;
  SELECT BLOB_ID FROM VAL_ADD(2912, :V$OBJ_ID, :I$PERSON_REGID) INTO :TMP;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DPO_PLAN_EXPORT RETURNS (
    OP_ID BIGINT,
    OBJ_ID BIGINT,
    OBJ_NAME VARCHAR(1000),
    STATE_ID BIGINT,
    PROGRAM_TYPE_ID BIGINT,
    DPO_CODE VARCHAR(100),
    DESCRIPTION VARCHAR(4000),
    STUDY_METHOD_ID BIGINT,
    ORDER_DATE DATE,
    ORDER_NUM VARCHAR(100),
    LOAD_HOURS SMALLINT)
AS
begin

  FOR
      SELECT L57.OBJ_ID, L50.OBJ_ID, V374.VAL, V2470.LISTVAL_ID, NULL, V2962.VAL, V2970.VAL, V1759.LISTVAL_ID, V2473.VAL, V2472.VAL, V2961.VAL
      FROM LINKS L2
      JOIN LINKS L69 ON L69.PARENT_ID = L2.OBJ_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL
      JOIN VALL V2450 ON V2450.OBJ_ID = L69.OBJ_ID AND V2450.PARAM_ID = 2450 AND V2450.IS_DEL = 0 -- только где заполнено
      JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
      JOIN LINKS L50 ON L50.PARENT_ID = L57.OBJ_ID AND L50.OBJ_TYPE_ID = 50 AND L50.DATE_DEL IS NULL
      JOIN VALS V374 ON V374.OBJ_ID = L50.OBJ_ID AND V374.PARAM_ID = 374 AND V374.IS_DEL = 0
      JOIN VALL V2470 ON V2470.OBJ_ID = L50.OBJ_ID AND V2470.PARAM_ID = 2470 AND V2470.IS_DEL = 0
      -- JOIN VALL V2470 ON V2470.OBJ_ID = L50.OBJ_ID AND V2470.PARAM_ID = 2470 AND V2470.IS_DEL = 0
      LEFT JOIN VALS V2962 ON V2962.OBJ_ID = L50.OBJ_ID AND V2962.PARAM_ID = 2962 AND V2962.IS_DEL = 0
      JOIN VALS V2970 ON V2970.OBJ_ID = L50.OBJ_ID AND V2970.PARAM_ID = 2970 AND V2970.IS_DEL = 0
      JOIN VALL V1759 ON V1759.OBJ_ID = L50.OBJ_ID AND V1759.PARAM_ID = 1759 AND V1759.IS_DEL = 0
      JOIN VALD V2473 ON V2473.OBJ_ID = L50.OBJ_ID AND V2473.PARAM_ID = 2473 AND V2473.IS_DEL = 0
      JOIN VALS V2472 ON V2472.OBJ_ID = L50.OBJ_ID AND V2472.PARAM_ID = 2472 AND V2472.IS_DEL = 0
      LEFT JOIN VALI V2961 ON V2961.OBJ_ID = L50.OBJ_ID AND V2961.PARAM_ID = 2961 AND V2961.IS_DEL = 0
      WHERE L2.PARENT_TYPE_ID IN (111, 112) AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      INTO :OP_ID, :OBJ_ID, :OBJ_NAME, :STATE_ID, :PROGRAM_TYPE_ID, :DESCRIPTION, :DPO_CODE, :STUDY_METHOD_ID, :ORDER_DATE, :ORDER_NUM, :LOAD_HOURS
  DO
  BEGIN
      SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DPO_PROGRAMS_EXPORT RETURNS (
    OU_ID BIGINT,
    OBJ_ID BIGINT,
    OBJ_NAME VARCHAR(1000),
    PROGRAM_TYPE_ID BIGINT)
AS
declare variable V$MULT bigint;
begin

  SELECT MULTIPLIER FROM GEN INTO :V$MULT;

  FOR
      SELECT L2.OBJ_ID, L69.OBJ_ID, R.VAL, V2450.LISTVAL_ID
      FROM LINKS L2
      JOIN LINKS L69 ON L69.PARENT_ID = L2.OBJ_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL
      JOIN VALL V2450 ON V2450.OBJ_ID = L69.OBJ_ID AND V2450.PARAM_ID = 2450 AND V2450.IS_DEL = 0
      JOIN LISTVALS LV ON LV.LISTVAL_ID = V2450.LISTVAL_ID
      JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
      WHERE L2.PARENT_TYPE_ID IN (111, 112) AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      INTO :OU_ID, :OBJ_ID, :OBJ_NAME, :PROGRAM_TYPE_ID
  DO
  BEGIN
      OU_ID = OU_ID / V$MULT;
      SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DPO_PROGRAM_EXPORT RETURNS (
    CATALOG_ID BIGINT,
    OBJ_ID BIGINT,
    OBJ_NAME VARCHAR(1000),
    TYPE_ID BIGINT,
    STUDY_TYPE_ID BIGINT,
    IS_NETWORK SMALLINT,
    IS_REMOTE SMALLINT,
    DURATION_STAGES SMALLINT)
AS
begin

  FOR
      SELECT L69.OBJ_ID, L57.OBJ_ID, V386.VAL
      FROM LINKS L2
      JOIN LINKS L69 ON L69.PARENT_ID = L2.OBJ_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL
      JOIN VALL V2450 ON V2450.OBJ_ID = L69.OBJ_ID AND V2450.PARAM_ID = 2450 AND V2450.IS_DEL = 0 -- только где заполнено
      JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
      JOIN VALS V386 ON V386.OBJ_ID = L57.OBJ_ID AND V386.PARAM_ID = 386 AND V386.IS_DEL = 0
      WHERE L2.PARENT_TYPE_ID IN (111, 112) AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      INTO :CATALOG_ID, :OBJ_ID, :OBJ_NAME
  DO
  BEGIN
      SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DPO_STUDENT_LEAVE (
    I$GROUP_ID BIGINT,
    I$PERSON_ID BIGINT,
    I$USER_ID VARCHAR(40))
AS
declare variable V$OBJ_ID bigint;
begin

  FOR
    SELECT C.CONTROL_ID
    FROM LINKS LP46
    JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.GRADE_ID = LP46.PARENT_ID
    JOIN CJ2_JOURNAL_LESSONS L ON L.DATE_DEL IS NULL AND L.CJ_ID = J.OBJ_ID
    JOIN CJ2_CONTROL C ON C.DATE_DEL IS NULL AND C.LESSON_ID = L.OBJ_ID
    WHERE LP46.OBJ_ID = :I$PERSON_ID AND LP46.PARENT_ID = :I$GROUP_ID
    INTO :V$OBJ_ID
  DO
  BEGIN
    UPDATE CJ2_MARK
    SET DATE_DEL = CURRENT_TIMESTAMP
    WHERE DATE_DEL IS NULL AND STUDENT_ID = :I$PERSON_ID AND CONTROL_ID = :V$OBJ_ID;
  END

  FOR
    SELECT L.OBJ_ID
    FROM LINKS LP46
    JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.GRADE_ID = LP46.PARENT_ID
    JOIN CJ2_JOURNAL_FINALS L ON L.DATE_DEL IS NULL AND L.CJ_ID = J.OBJ_ID
    WHERE LP46.OBJ_ID = :I$PERSON_ID AND LP46.PARENT_ID = :I$GROUP_ID
    INTO :V$OBJ_ID
  DO
  BEGIN
    UPDATE CJ2_MARK
    SET DATE_DEL = CURRENT_TIMESTAMP
    WHERE DATE_DEL IS NULL AND STUDENT_ID = :I$PERSON_ID AND FINAL_ID = :V$OBJ_ID;
  END

  SELECT COUNT(*) FROM VARGRP_MOVE_PUPIL(:I$PERSON_ID, :I$GROUP_ID, NULL, NULL, CURRENT_DATE, 3, :I$USER_ID, NULL, 811) INTO :V$OBJ_ID;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DPS_PERSON_GET (
    I$LIC_ID BIGINT,
    I$PERSON_LASTNAME VARCHAR(1000),
    I$PERSON_NAME VARCHAR(1000),
    I$PERSON_PATRONYMIC VARCHAR(1000),
    I$BIRTH_DATE DATE,
    I$PERSON_TYPE SMALLINT = 0)
RETURNS (
    PERSON_ID BIGINT,
    ORG_ID BIGINT,
    GRADE_ID BIGINT,
    GRADE_NAME VARCHAR(1000),
    BIRTH_DATE DATE,
    SEX CHAR(1))
AS
declare variable GEN_MULTIPLIER bigint;
begin

  -- PERSON_TYPE: 0 = ученик, 1 = сотрудник

  -- Преобразуем ID в нужный нам
  SELECT FIRST 1 MULTIPLIER
  FROM GEN
  INTO :GEN_MULTIPLIER;

  SELECT FIRST 1 L2.OBJ_ID
  FROM LINKS L2
  WHERE (L2.PARENT_ID IS NULL OR L2.PARENT_TYPE_ID IN (111, 112)) AND L2.DATE_DEL IS NULL AND L2.OBJ_TYPE_ID IN (2, 124) AND
    (L2.OBJ_ID >= :GEN_MULTIPLIER * :I$LIC_ID) AND (L2.OBJ_ID < :GEN_MULTIPLIER * (:I$LIC_ID + 1))
  INTO :ORG_ID;

  IF(ORG_ID IS NULL) THEN EXIT;

  IF(I$PERSON_TYPE = 0) THEN
  BEGIN

    -- Ученики
    FOR
      SELECT LP9.OBJ_ID, V89.VAL, IIF(V88.LISTVAL_ID = 182, 'Ж', 'М'), LP9.PARENT_ID
      FROM VALD V89
      JOIN VALS V55 ON V55.OBJ_ID = V89.OBJ_ID AND V55.PARAM_ID = 55 AND V55.IS_DEL = 0 AND V55.VAL = :I$PERSON_LASTNAME
      JOIN VALS V56 ON V56.OBJ_ID = V89.OBJ_ID AND V56.PARAM_ID = 56 AND V56.IS_DEL = 0 AND V56.VAL = :I$PERSON_NAME
      LEFT JOIN VALS V57 ON V57.OBJ_ID = V89.OBJ_ID AND V57.PARAM_ID = 57 AND V57.IS_DEL = 0
      JOIN VALL V88 ON V88.OBJ_ID = V89.OBJ_ID AND V88.PARAM_ID = 88 AND V88.IS_DEL = 0
      JOIN LINKS LP9 ON LP9.OBJ_ID = V89.OBJ_ID AND LP9.PARENT_TYPE_ID = 9 AND LP9.DATE_DEL IS NULL
      JOIN LINKS LP8 ON LP8.OBJ_ID = LP9.PARENT_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
      JOIN LINKS LP7 ON LP7.OBJ_ID = LP8.PARENT_ID AND LP7.PARENT_TYPE_ID = 7 AND LP7.DATE_DEL IS NULL
      JOIN LINKS LP2 ON LP2.OBJ_ID = LP7.PARENT_ID AND LP2.PARENT_ID = :ORG_ID AND LP2.DATE_DEL IS NULL
      WHERE V89.PARAM_ID = 89 AND V89.IS_DEL = 0 AND V89.VAL = :I$BIRTH_DATE
      INTO :PERSON_ID, :BIRTH_DATE, :SEX, :GRADE_ID
    DO
    BEGIN
      -- Название класса
      GRADE_NAME = NULL;
      SELECT CAPTION FROM OBJECT_CAPTION_GET(:GRADE_ID) INTO :GRADE_NAME;

      SUSPEND;
    END

  END
  ELSE
  BEGIN

    -- Сотрудники, обязательны все части ФИО
    FOR
      -- Работающие сотрудники в самой ОО
      SELECT LP2.OBJ_ID, V241.VAL, IIF(V239.LISTVAL_ID = 182, 'Ж', 'М')
      FROM VALD V241
      JOIN VALS V59 ON V59.OBJ_ID = V241.OBJ_ID AND V59.PARAM_ID = 59 AND V59.IS_DEL = 0 AND V59.VAL = :I$PERSON_LASTNAME
      JOIN VALS V60 ON V60.OBJ_ID = V241.OBJ_ID AND V60.PARAM_ID = 60 AND V60.IS_DEL = 0 AND V60.VAL = :I$PERSON_NAME
      LEFT JOIN VALS V61 ON V61.OBJ_ID = V241.OBJ_ID AND V61.PARAM_ID = 61 AND V61.IS_DEL = 0
      JOIN VALL V239 ON V239.OBJ_ID = V241.OBJ_ID AND V239.PARAM_ID = 239 AND V239.IS_DEL = 0
      JOIN LINKS LP2 ON LP2.OBJ_ID = V241.OBJ_ID AND LP2.PARENT_ID = :ORG_ID AND LP2.DATE_DEL IS NULL
      WHERE V241.PARAM_ID = 241 AND V241.IS_DEL = 0 AND V241.VAL = :I$BIRTH_DATE
      -- Работающие сотрудники в подразделениях первого уровня
      UNION
      SELECT LP211.OBJ_ID, V241.VAL, IIF(V239.LISTVAL_ID = 182, 'Ж', 'М')
      FROM VALD V241
      JOIN VALS V59 ON V59.OBJ_ID = V241.OBJ_ID AND V59.PARAM_ID = 59 AND V59.IS_DEL = 0 AND V59.VAL = :I$PERSON_LASTNAME
      JOIN VALS V60 ON V60.OBJ_ID = V241.OBJ_ID AND V60.PARAM_ID = 60 AND V60.IS_DEL = 0 AND V60.VAL = :I$PERSON_NAME
      LEFT JOIN VALS V61 ON V61.OBJ_ID = V241.OBJ_ID AND V61.PARAM_ID = 61 AND V61.IS_DEL = 0
      JOIN VALL V239 ON V239.OBJ_ID = V241.OBJ_ID AND V239.PARAM_ID = 239 AND V239.IS_DEL = 0
      JOIN LINKS LP211 ON LP211.OBJ_ID = V241.OBJ_ID AND LP211.PARENT_TYPE_ID = 211 AND LP211.DATE_DEL IS NULL
      JOIN LINKS LP2 ON LP2.OBJ_ID = LP211.PARENT_ID AND LP2.PARENT_ID = :ORG_ID AND LP2.DATE_DEL IS NULL
      WHERE V241.PARAM_ID = 241 AND V241.IS_DEL = 0 AND V241.VAL = :I$BIRTH_DATE
      -- Выбывшие сотрудники
      -- ...
      INTO :PERSON_ID, :BIRTH_DATE, :SEX
    DO
    BEGIN
      -- Находим первую основную или хоть какую-нибудь должность, актуальную на данный момент
      GRADE_ID = NULL;
      GRADE_NAME = '';

      SELECT FIRST 1 LP14.PARENT_ID, C.CAPTION
      FROM LINKS L15
      JOIN LINKS LP14 ON LP14.OBJ_ID = L15.OBJ_ID AND LP14.PARENT_TYPE_ID = 14 AND LP14.DATE_DEL IS NULL
      JOIN VALL V72 ON V72.OBJ_ID = L15.OBJ_ID AND V72.PARAM_ID = 72 AND V72.IS_DEL = 0 AND V72.LISTVAL_ID = 934
      LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
      LEFT JOIN OBJECT_CAPTION_GET(LP14.PARENT_ID) C ON 1 = 1
      WHERE L15.PARENT_ID = :PERSON_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL AND V74.VAL IS NULL
      INTO :GRADE_ID, :GRADE_NAME;


      IF(GRADE_ID IS NULL) THEN GRADE_NAME = 'Не-действующий';
      SUSPEND;
    END

  END


end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DROP_CLASS_LEADERSHIP (
    I$EMPLOYEE_ID BIGINT NOT NULL,
    I$CLASS_ID BIGINT,
    I$USER_ID BIGINT)
AS
declare variable V$OBJ_ID bigint;
begin
  FOR
    SELECT V.OBJ_ID
    FROM VALR V
    JOIN LINKS LP ON LP.OBJ_ID = V.OBJ_ID AND LP.PARENT_TYPE_ID = 8 AND LP.DATE_DEL IS NULL    --этап обучения
    WHERE V.VAL = :I$EMPLOYEE_ID AND V.PARAM_ID = 53 AND V.IS_DEL = 0 AND (:I$CLASS_ID IS NULL OR LP.OBJ_ID = :I$CLASS_ID)
    INTO :V$OBJ_ID
  DO
  BEGIN
    UPDATE VALR
    SET IS_DEL = 1, DATE_MODIFY = CURRENT_TIMESTAMP, USER_ID = :I$USER_ID
    WHERE OBJ_ID = :V$OBJ_ID AND PARAM_ID = 53;
  END
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DROP_STUDENT_MOVEMENTS (
    I$OBJ_ID BIGINT)
AS
declare variable V$MOVE_ID bigint;
begin

  FOR
    SELECT M.OBJ_ID
    FROM PERSON_MOVEMENTS M
    JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
    WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :I$OBJ_ID
    INTO :V$MOVE_ID
  DO
  BEGIN
    UPDATE PERSON_MOVEMENTS
    SET DATE_DEL = CURRENT_TIMESTAMP
    WHERE OBJ_ID = :V$MOVE_ID;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE DROP_TEACHING_LOADS (
    I$EMPLOYEE_ID BIGINT NOT NULL,
    I$JOURNAL_ID BIGINT)
AS
begin
  UPDATE CJ2_JOURNAL J
    SET J.TEACHER_ID = NULL, J.DATE_MODIFY = CURRENT_TIMESTAMP
  WHERE J.DATE_DEL IS NULL AND J.TEACHER_ID = :I$EMPLOYEE_ID
    AND (:I$JOURNAL_ID IS NULL OR J.OBJ_ID = :I$JOURNAL_ID);
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE D_12 (
    I$OBJ_ID BIGINT,
    LBL INTEGER,
    I$DT DATE = current_date)
RETURNS (
    V1 VARCHAR(10),
    V2 VARCHAR(10),
    V3 VARCHAR(10),
    VS VARCHAR(10))
AS
declare variable C1 integer = 0;
declare variable C2 integer = 0;
declare variable C3 integer = 0;
declare variable CS integer = 0;
declare variable SCHOLAR_ID bigint;
declare variable KUDA_ID bigint;
declare variable OU_VID_ID bigint;
declare variable STAGE_ID bigint;
declare variable DT1 date;
declare variable DT2 date;
declare variable IS_CURR_MOVE smallint = 0;
declare variable MOVE_DATE date;
declare variable CLASS_TYPE bigint;
declare variable IS_CORRECT smallint = 1;
BEGIN
    IS_CURR_MOVE = EXTRACT(YEAR FROM :I$DT) - 1;
    DT1 = IS_CURR_MOVE || '-09-20';
    IS_CURR_MOVE = EXTRACT(YEAR FROM :I$DT);
    DT2 = IS_CURR_MOVE || '-09-19';

    FOR SELECT L10.OBJ_ID, V105.LISTVAL_ID, V107.LISTVAL_ID
        FROM LINKS L7
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
        JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        JOIN VALL V105 ON V105.OBJ_ID = L10.OBJ_ID AND V105.PARAM_ID = 105 AND V105.IS_DEL = 0
        LEFT JOIN VALL V107 ON V107.OBJ_ID = L10.OBJ_ID AND V107.PARAM_ID = 107 AND V107.IS_DEL = 0
        WHERE L7.PARENT_ID = :I$OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
          --AND :LBL <> 7
          AND :LBL <> 8

        UNION

        SELECT L10.OBJ_ID, V105.LISTVAL_ID, V107.LISTVAL_ID
        FROM LINKS L78
        JOIN LINKS L81 ON L81.PARENT_ID = L78.OBJ_ID AND L81.OBJ_TYPE_ID = 81 AND L81.DATE_DEL IS NULL
        JOIN LINKS L10 ON L10.PARENT_ID = L81.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        JOIN VALL V105 ON V105.OBJ_ID = L10.OBJ_ID AND V105.PARAM_ID = 105 AND V105.IS_DEL = 0
        LEFT JOIN VALL V107 ON V107.OBJ_ID = L10.OBJ_ID AND V107.PARAM_ID = 107 AND V107.IS_DEL = 0
        WHERE L78.PARENT_ID = :I$OBJ_ID AND L78.OBJ_TYPE_ID = 78 AND L78.DATE_DEL IS NULL
          --AND :LBL <> 7
          AND :LBL <> 8

        UNION

        SELECT L10.OBJ_ID, V105.LISTVAL_ID, V107.LISTVAL_ID
        FROM LINKS L78
        JOIN LINKS L82 ON L82.PARENT_ID = L78.OBJ_ID AND L82.OBJ_TYPE_ID = 82AND L82.DATE_DEL IS NULL
        JOIN LINKS L10 ON L10.PARENT_ID = L82.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        JOIN VALL V105 ON V105.OBJ_ID = L10.OBJ_ID AND V105.PARAM_ID = 105 AND V105.IS_DEL = 0
        LEFT JOIN VALL V107 ON V107.OBJ_ID = L10.OBJ_ID AND V107.PARAM_ID = 107 AND V107.IS_DEL = 0
        WHERE L78.PARENT_ID = :I$OBJ_ID AND L78.OBJ_TYPE_ID = 78AND L78.DATE_DEL IS NULL
          --AND :LBL <> 7
          AND :LBL <> 8

        UNION

        SELECT L10.OBJ_ID, V105.LISTVAL_ID, V107.LISTVAL_ID
        FROM LINKS L78
        JOIN LINKS L83 ON L83.PARENT_ID = L78.OBJ_ID AND L83.OBJ_TYPE_ID = 83 AND L83.DATE_DEL IS NULL
        JOIN LINKS L9 ON L9.PARENT_ID = L83.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
        JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        JOIN VALL V105 ON V105.OBJ_ID = L10.OBJ_ID AND V105.PARAM_ID = 105 AND V105.IS_DEL = 0
        LEFT JOIN VALL V107 ON V107.OBJ_ID = L10.OBJ_ID AND V107.PARAM_ID = 107 AND V107.IS_DEL = 0
        WHERE L78.PARENT_ID = :I$OBJ_ID AND L78.OBJ_TYPE_ID = 78 AND L78.DATE_DEL IS NULL
         -- AND :LBL <> 7
          AND :LBL <> 8

        INTO :SCHOLAR_ID, :KUDA_ID, :OU_VID_ID
    DO
    BEGIN
        MOVE_DATE = NULL;
        STAGE_ID = NULL;
        CLASS_TYPE = NULL;

        SELECT FIRST 1 M.DATE_OUT, M.STAGE_ID, M.TYPE_IN
        FROM PERSON_MOVEMENTS M
        JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
        WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :SCHOLAR_ID AND M.REASON_OUT IN (811, 812) AND M.DATE_OUT >= :DT1 AND M.DATE_OUT <= :DT2
        ORDER BY M.DATE_OUT DESC
        INTO :MOVE_DATE, :STAGE_ID, :CLASS_TYPE;

        IF (MOVE_DATE IS NOT NULL) THEN
        BEGIN
            IS_CORRECT = 1;
            IF (COALESCE(CLASS_TYPE, -1) > 197) THEN IS_CORRECT = 0;

            IF ((STAGE_ID IS NOT NULL) AND (IS_CORRECT = 1)) THEN
            BEGIN
                IF (LBL = 1) THEN
                BEGIN
                    IF (STAGE_ID IN (37, 38, 39, 40)) THEN
                        C1 = C1 + 1;
                    IF (STAGE_ID IN (41, 42, 43, 44, 45)) THEN
                        C2 = C2 + 1;
                    IF (STAGE_ID IN (46, 47, 48)) THEN
                        C3 = C3 + 1;
                END
                ELSE
                IF ((LBL = 2) AND (KUDA_ID IN (904, 905, 906, 907, 3143))) THEN
                BEGIN
                    IF ((OU_VID_ID IS NULL) OR (OU_VID_ID NOT IN (965, 966, 967, 979, 980, 985, 986, 1010, 1011, 1014, 1016, 2216, 2219, 2220, 2222, 2223, 2224, 2225))) THEN
                    BEGIN
                        IF (STAGE_ID IN (37, 38, 39, 40)) THEN
                            C1 = C1 + 1;
                        IF (STAGE_ID IN (41, 42, 43, 44, 45)) THEN
                            C2 = C2 + 1;
                        IF (STAGE_ID IN (46, 47, 48)) THEN
                            C3 = C3 + 1;
                    END
                END
                ELSE
                IF ((LBL = 3) AND (KUDA_ID IN (904, 905, 906, 907, 3143))) THEN
                BEGIN
                    IF (OU_VID_ID IN (2216, 979, 980, 985, 986)) THEN
                    BEGIN
                        IF (STAGE_ID IN (37, 38, 39, 40)) THEN
                            C1 = C1 + 1;
                        IF (STAGE_ID IN (41, 42, 43, 44, 45)) THEN
                            C2 = C2 + 1;
                        IF (STAGE_ID IN (46, 47, 48)) THEN
                            C3 = C3 + 1;
                    END
                END
                ELSE
                IF ((LBL = 4) AND (KUDA_ID IN (904, 905, 906, 907, 3143))) THEN
                BEGIN
                    IF (OU_VID_ID IN (965, 966, 967)) THEN
                    BEGIN
                        IF (STAGE_ID IN (37, 38, 39, 40)) THEN
                            C1 = C1 + 1;
                        IF (STAGE_ID IN (41, 42, 43, 44, 45)) THEN
                            C2 = C2 + 1;
                        IF (STAGE_ID IN (46, 47, 48)) THEN
                            C3 = C3 + 1;
                    END
                END
                ELSE
                IF ((LBL = 5) AND (KUDA_ID IN (904, 905, 906, 907, 3143))) THEN
                BEGIN
                    IF (OU_VID_ID IN (1014, 1016)) THEN
                    BEGIN
                        IF (STAGE_ID IN (37, 38, 39, 40)) THEN
                            C1 = C1 + 1;
                        IF (STAGE_ID IN (41, 42, 43, 44, 45)) THEN
                            C2 = C2 + 1;
                        IF (STAGE_ID IN (46, 47, 48)) THEN
                            C3 = C3 + 1;
                    END
                END
                ELSE
                IF ((LBL IN (6, 7)) AND (KUDA_ID IN (904, 905, 906, 907, 3143))) THEN
                BEGIN
                    IF (OU_VID_ID IN (1010, 1011)) THEN
                    BEGIN
                        IF (STAGE_ID IN (37, 38, 39, 40)) THEN
                            C1 = C1 + 1;
                        IF (STAGE_ID IN (41, 42, 43, 44, 45)) THEN
                            C2 = C2 + 1;
                        IF (STAGE_ID IN (46, 47, 48)) THEN
                            C3 = C3 + 1;
                    END
                END
                ELSE
                IF ((LBL = 9) AND (KUDA_ID IN (914, 915))) THEN
                BEGIN
                    IF (STAGE_ID IN (37, 38, 39, 40)) THEN
                        C1 = C1 + 1;
                    IF (STAGE_ID IN (41, 42, 43, 44, 45)) THEN
                        C2 = C2 + 1;
                    IF (STAGE_ID IN (46, 47, 48)) THEN
                        C3 = C3 + 1;
                END
                ELSE
                IF ((LBL = 10) AND (KUDA_ID IN (910))) THEN
                BEGIN
                    IF (STAGE_ID IN (37, 38, 39, 40)) THEN
                        C1 = C1 + 1;
                    IF (STAGE_ID IN (41, 42, 43, 44, 45)) THEN
                        C2 = C2 + 1;
                    IF (STAGE_ID IN (46, 47, 48)) THEN
                        C3 = C3 + 1;
                END
                ELSE
                IF ((LBL = 11) AND (KUDA_ID IN (904, 905, 906, 907))) THEN
                BEGIN
                    IF (OU_VID_ID IN (2219, 2220, 2222, 2223, 2224, 2225)) THEN
                    BEGIN
                        IF (STAGE_ID IN (37, 38, 39, 40)) THEN
                            C1 = C1 + 1;
                        IF (STAGE_ID IN (41, 42, 43, 44, 45)) THEN
                            C2 = C2 + 1;
                        IF (STAGE_ID IN (46, 47, 48)) THEN
                            C3 = C3 + 1;
                    END
                END
                ELSE
                IF ((LBL = 12) AND (KUDA_ID IN (908))) THEN
                BEGIN
                    IF (STAGE_ID IN (37, 38, 39, 40)) THEN
                        C1 = C1 + 1;
                    IF (STAGE_ID IN (41, 42, 43, 44, 45)) THEN
                        C2 = C2 + 1;
                    IF (STAGE_ID IN (46, 47, 48)) THEN
                        C3 = C3 + 1;
                END
                ELSE
                IF ((LBL = 13) AND (KUDA_ID IN (909))) THEN
                BEGIN
                    IF (STAGE_ID IN (37, 38, 39, 40)) THEN
                        C1 = C1 + 1;
                    IF (STAGE_ID IN (41, 42, 43, 44, 45)) THEN
                        C2 = C2 + 1;
                    IF (STAGE_ID IN (46, 47, 48)) THEN
                        C3 = C3 + 1;
                END
                ELSE
                IF ((LBL = 14) AND (KUDA_ID IN (916))) THEN
                BEGIN
                    IF (STAGE_ID IN (37, 38, 39, 40)) THEN
                        C1 = C1 + 1;
                    IF (STAGE_ID IN (41, 42, 43, 44, 45)) THEN
                        C2 = C2 + 1;
                    IF (STAGE_ID IN (46, 47, 48)) THEN
                        C3 = C3 + 1;
                END
                ELSE
                IF ((LBL = 15) AND (KUDA_ID IN (911))) THEN
                BEGIN
                    IF (STAGE_ID IN (37, 38, 39, 40)) THEN
                        C1 = C1 + 1;
                    IF (STAGE_ID IN (41, 42, 43, 44, 45)) THEN
                        C2 = C2 + 1;
                    IF (STAGE_ID IN (46, 47, 48)) THEN
                        C3 = C3 + 1;
                END
                ELSE
                IF ((LBL = 16) AND (KUDA_ID IN (912, 913, 11200, 917))) THEN
                BEGIN
                    IF (STAGE_ID IN (37, 38, 39, 40)) THEN
                        C1 = C1 + 1;
                    IF (STAGE_ID IN (41, 42, 43, 44, 45)) THEN
                        C2 = C2 + 1;
                    IF (STAGE_ID IN (46, 47, 48)) THEN
                        C3 = C3 + 1;
                END
            END

        END
    END

    CS = C1 + C2 + C3;

    V1 = C1;
    V2 = C2;
    V3 = C3;
    VS = CS;

    IF (:LBL = 7) THEN
    BEGIN
        V1 = IIF(V1 = '0', ' ', '0');
        V2 = IIF(V2 = '0', ' ', '0');
        V3 = IIF(V3 = '0', ' ', '0');
        VS = IIF(VS = '0', ' ', '0');
    END
    ELSE
    BEGIN
        IF (V1 = '0') THEN
            V1 = ' ';
        IF (V2 = '0') THEN
            V2 = ' ';
        IF (V3 = '0') THEN
            V3 = ' ';
        IF (VS = '0') THEN
            VS = ' ';
    END

    SUSPEND;

END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE D_12_ADD_CALC_DISTR (
    I$OBJ_ID BIGINT,
    I$DT1 DATE,
    I$DT2 DATE = NULL,
    I$C1 VARCHAR(1000) = 'YES',
    I$C2 VARCHAR(1000) = 'YES',
    I$C3 VARCHAR(1000) = 'YES',
    I$C4 VARCHAR(3) = 'YES')
RETURNS (
    N CHAR(1))
AS
DECLARE VARIABLE SCHOOL_ID BIGINT;
DECLARE VARIABLE PARAM6VAL VARCHAR(100);
DECLARE VARIABLE V$POD_NAME VARCHAR(1000);
DECLARE VARIABLE V$OPF_ID BIGINT;
DECLARE VARIABLE V$STAGE_ID BIGINT;
DECLARE VARIABLE NUM BIGINT;
BEGIN
    DELETE FROM REPORT_D12 WHERE 1=1;

    -- Передача параметров через одно место
    -- Если I$DT2 задан, то I$C1 фильтр по коррекционным классам и ОУ (да = включать)
    -- Если I$DT2 не задан, то I$C1 фильтр по подчинению
    -- Если I$DT2 задан, то I$C2 фильтр по вечерним ОУ (да = включать)
    -- Если I$DT2 не задан, то I$C2 фильтр по частным ОУ (да = включать)

    -- Внимание: по параметру I$C2 14.01.2019 изменена логика

    PARAM6VAL = 'комитет по %образованию%санкт-петербурга';

    IF(I$C1 = 'YES') THEN I$C1 = 'Да';
    IF(I$C2 = 'YES') THEN I$C2 = 'Да';
    IF(I$C3 = 'YES') THEN I$C3 = 'Да';
    IF(I$C4 = 'YES') THEN I$C4 = 'Да';

    -- Если DT2 = NULL, то это отчет контингент на дату или контингент по параллели на дату, и меняем назначение фильтров
    IF (I$DT2 IS NULL) THEN
    BEGIN
        -- контингент на дату, фильтр по подчинению, либо default
        BEGIN
          -- если передали listvalue_id, то найдем текст к нему
          NUM = I$C1;
          SELECT VAL FROM LISTVALS_LIST(166) WHERE IS_DEL = 0 AND LISTVAL_ID = :NUM INTO :V$POD_NAME;
          -- если сразу передали текст
          WHEN ANY DO V$POD_NAME = IIF(I$C1 IS NULL OR I$C1 IN ('', 'Да'), NULL, I$C1);
        END

        -- включать или не включать частные ОУ
        IF(I$C2 = 'Нет' OR I$C2 = '3') THEN V$OPF_ID = 5404;

        -- контингент по параллели на дату, код параллели
        BEGIN
          V$STAGE_ID = I$C3;
          WHEN ANY DO SELECT LISTVAL_ID FROM LISTVALS_LIST(25) WHERE VAL = :I$C3 INTO :V$STAGE_ID;
        END

        I$C1 = 'Да';
        I$C2 = 'Да';
        I$C3 = 'Да';
    END

    -- Промежуточной фильтрации списков больше не делаем

    FOR
        SELECT L2.OBJ_ID
        FROM LINKS L2
        LEFT JOIN VALL V10 ON V10.OBJ_ID = L2.OBJ_ID AND V10.PARAM_ID = 10 AND V10.IS_DEL = 0
        LEFT JOIN VALL V8 ON V8.OBJ_ID = L2.OBJ_ID AND V8.PARAM_ID = 8 AND V8.IS_DEL = 0
        LEFT JOIN VALS V6 ON V6.OBJ_ID = L2.OBJ_ID AND V6.PARAM_ID = 6 AND V6.IS_DEL = 0
        WHERE L2.PARENT_ID = :I$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
            AND ((:I$C1 = 'Да') OR (V10.LISTVAL_ID NOT IN (956,979,980,985,986,2216)))
            AND ((:I$C2 = 'Да') OR (V10.LISTVAL_ID NOT IN (965,966,967)))
            AND ((:I$C3 = 'Да') OR (V8.LISTVAL_ID NOT IN (1734,5404,5405,5406,5407,5408,5414,5415,5416))) --Организационно-правовая форма
            AND ((:I$C4 = 'Да') OR (LOWER(V6.VAL) LIKE :PARAM6VAL))
            AND (:V$POD_NAME IS NULL OR V6.VAL = :V$POD_NAME)                            --Подчинение, проверка по названию
            AND (:V$OPF_ID IS NULL OR V8.LISTVAL_ID <> 5404)                             --Включать в выборку чатсные школы
        ORDER BY L2.OBJ_ID DESC
        INTO :SCHOOL_ID
    DO
    BEGIN
        IF (I$DT2 IS NULL) THEN
        BEGIN
            -- Контингент на дату по району
            EXECUTE PROCEDURE SCHOLAR_CNT_DISTR_INS(:SCHOOL_ID, :I$DT1, :V$STAGE_ID);
        END
        ELSE
        BEGIN
            -- Приложение Д12
            EXECUTE PROCEDURE D_12_ADD_INSERT_ROWS_DISTR(:SCHOOL_ID, :I$DT1, :I$DT2, :I$C1);
        END
    END

    N = ' ';

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE D_12_ADD_CALC_OU (
    I$OBJ_ID BIGINT,
    I$DT1 DATE,
    I$DT2 DATE,
    I$CORRECTION VARCHAR(3))
RETURNS (
    N CHAR(1))
AS
declare variable KEY_LEVEL varchar(1);
BEGIN
    SELECT K.KEY_VAL FROM KEYS K WHERE K.KEY_CODE = 'LEVEL' INTO :KEY_LEVEL;

    DELETE FROM REPORT_D12;

    IF (KEY_LEVEL = '2') THEN
    BEGIN
        EXECUTE PROCEDURE D_12_ADD_INSERT_MOVEMENT(:I$OBJ_ID);
        EXECUTE PROCEDURE D_12_ADD_INSERT_ROWS_DISTR(:I$OBJ_ID, :I$DT1, :I$DT2, :I$CORRECTION);
    END
    ELSE
    BEGIN
        EXECUTE PROCEDURE D_12_ADD_INSERT_ROWS(:I$OBJ_ID, :I$DT1, :I$DT2, :I$CORRECTION);
    END
    N = ' ';

    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE D_12_ADD_GET_LBL (
    LBL INTEGER)
RETURNS (
    C1 INTEGER,
    C2 INTEGER,
    C3 INTEGER,
    CS INTEGER)
AS
BEGIN
    C1 = 0;
    C2 = 0;
    C3 = 0;
    CS = 0;

    SELECT SUM(C1), SUM(C2), SUM(C3)
    FROM REPORT_D12
    WHERE ROW_NUM = :LBL
    INTO :C1, :C2, :C3;

    IF (C1 IS NULL) THEN C1 = 0;
    IF (C2 IS NULL) THEN C2 = 0;
    IF (C3 IS NULL) THEN C3 = 0;

    CS = C1 + C2 + C3;

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE D_12_ADD_GET_MOVEMENT (
    I$OBJ_ID BIGINT)
RETURNS (
    SCHOOL_ID BIGINT,
    SCHOLAR_ID BIGINT,
    CLASS_TYPE BIGINT,
    STAGE_ID BIGINT,
    CLASS_ID BIGINT,
    REASON_IN BIGINT,
    DATE_IN DATE,
    REASON_OUT BIGINT,
    DATE_OUT DATE)
AS
BEGIN
    SCHOOL_ID = I$OBJ_ID;

    FOR
        -- Действующие ученики
        SELECT L10.OBJ_ID, M.TYPE_IN, M.STAGE_ID, M.GROUP_ID, M.REASON_IN, M.DATE_IN, M.REASON_OUT, M.DATE_OUT
        FROM LINKS L7
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
        JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        JOIN PERSON_MOVEMENTS M ON M.DATE_DEL IS NULL AND M.PERSON_ID = L10.OBJ_ID
        JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
        WHERE L7.PARENT_ID = :SCHOOL_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
        -- Выбывшие
        UNION
        SELECT L10.OBJ_ID, M.TYPE_IN, M.STAGE_ID, M.GROUP_ID, M.REASON_IN, M.DATE_IN, M.REASON_OUT, M.DATE_OUT
        FROM LINKS L78
        JOIN LINKS L81_2_3 ON L81_2_3.PARENT_ID = L78.OBJ_ID AND L81_2_3.OBJ_TYPE_ID IN (81, 82, 83) AND L81_2_3.DATE_DEL IS NULL
        JOIN LINKS L10 ON L10.PARENT_ID = L81_2_3.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        JOIN PERSON_MOVEMENTS M ON M.DATE_DEL IS NULL AND M.PERSON_ID = L10.OBJ_ID
        JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
        WHERE L78.PARENT_ID = :SCHOOL_ID AND L78.OBJ_TYPE_ID = 78 AND L78.DATE_DEL IS NULL
        INTO :SCHOLAR_ID, :CLASS_TYPE, :STAGE_ID, :CLASS_ID, :REASON_IN, :DATE_IN, :REASON_OUT, :DATE_OUT
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE D_12_ADD_GET_STAGES (
    I$OBJ_ID BIGINT)
RETURNS (
    BEGIN_STAGE1 BIGINT,
    FINAL_STAGE1 BIGINT,
    BEGIN_STAGE2 BIGINT,
    FINAL_STAGE2 BIGINT,
    BEGIN_STAGE3 BIGINT,
    FINAL_STAGE3 BIGINT,
    HAS_ZERO SMALLINT)
AS
declare variable GRADE_ID bigint;
declare variable GRADE_TYPE_ID bigint;
BEGIN
    BEGIN_STAGE1 = NULL;
    FINAL_STAGE1 = NULL;
    BEGIN_STAGE2 = NULL;
    FINAL_STAGE2 = NULL;
    BEGIN_STAGE3 = NULL;
    FINAL_STAGE3 = NULL;
    HAS_ZERO = 0;

    -- Из всех выборок исключаем 0-й уровень образования

    FOR
        SELECT V43.OBJ_ID, V43.LISTVAL_ID
        FROM LINKS L7
        JOIN VALL V43 ON V43.OBJ_ID = L7.OBJ_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0
        WHERE L7.PARENT_ID = :I$OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
        INTO :GRADE_ID, :GRADE_TYPE_ID
    DO
    BEGIN
        IF (GRADE_TYPE_ID = 22) THEN
        BEGIN
            -- Начальное образование
            SELECT MIN(V49.LISTVAL_ID)
            FROM LINKS L8
            JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0 AND V49.LISTVAL_ID <> 12765
            WHERE L8.PARENT_ID = :GRADE_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
            INTO :BEGIN_STAGE1;

            SELECT MAX(V49.LISTVAL_ID)
            FROM LINKS L8
            JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0 AND V49.LISTVAL_ID <> 12765
            WHERE L8.PARENT_ID = :GRADE_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
            INTO :FINAL_STAGE1;

            -- Особая проверка для нулевой параллели
            SELECT FIRST 1 1
            FROM LINKS L8
            JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0 AND V49.LISTVAL_ID = 12765
            WHERE L8.PARENT_ID = :GRADE_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
            INTO :HAS_ZERO;

        END
        ELSE IF (GRADE_TYPE_ID = 26) THEN
        BEGIN
            -- Общее образование
            SELECT MIN(V49.LISTVAL_ID)
            FROM LINKS L8
            JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0 AND V49.LISTVAL_ID <> 12765
            WHERE L8.PARENT_ID = :GRADE_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
            INTO :BEGIN_STAGE2;

            SELECT MAX(V49.LISTVAL_ID)
            FROM LINKS L8
            JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0 AND V49.LISTVAL_ID <> 12765
            WHERE L8.PARENT_ID = :GRADE_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
            INTO :FINAL_STAGE2;
        END
        ELSE IF (GRADE_TYPE_ID = 27) THEN
        BEGIN
            -- Среднее
            SELECT MIN(V49.LISTVAL_ID)
            FROM LINKS L8
            JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0 AND V49.LISTVAL_ID <> 12765
            WHERE L8.PARENT_ID = :GRADE_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
            INTO :BEGIN_STAGE3;

            SELECT MAX(V49.LISTVAL_ID)
            FROM LINKS L8
            JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0 AND V49.LISTVAL_ID <> 12765
            WHERE L8.PARENT_ID = :GRADE_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
            INTO :FINAL_STAGE3;

            IF (FINAL_STAGE3 IN (46, 47)) THEN FINAL_STAGE3 = 48;

        END
    END

    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE D_12_ADD_INSERT_MOVEMENT (
    SCHOOL_ID BIGINT)
AS
declare variable DATE_MODIFY date;
declare variable DATE_INSERT date;
BEGIN
    SELECT DATE_MODIFY
    FROM OBJECTS O
    WHERE O.OBJ_ID = :SCHOOL_ID
    INTO :DATE_MODIFY;

    SELECT FIRST 1 DATE_MODIFY
    FROM REPORT_D12_ADD O
    WHERE O.SCHOOL_ID = :SCHOOL_ID
    INTO :DATE_INSERT;

    IF (DATE_MODIFY < DATE_INSERT) THEN EXIT;

    DELETE FROM REPORT_D12_ADD O
    WHERE O.SCHOOL_ID = :SCHOOL_ID;

    INSERT INTO REPORT_D12_ADD (SCHOOL_ID, SCHOLAR_ID, CLASS_TYPE, STAGE_ID, DATE_MODIFY, CLASS_ID, REASON_IN, DATE_IN, REASON_OUT, DATE_OUT)
    SELECT SCHOOL_ID, SCHOLAR_ID, CLASS_TYPE, STAGE_ID, CURRENT_TIMESTAMP, CLASS_ID, REASON_IN, DATE_IN, REASON_OUT, DATE_OUT
    FROM D_12_ADD_GET_MOVEMENT(:SCHOOL_ID)
    ORDER BY SCHOOL_ID DESC, SCHOLAR_ID DESC, DATE_IN DESC, REASON_IN DESC;

END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE D_12_ADD_INSERT_ROW (
    SCHOOL_ID BIGINT,
    SCHOLAR_ID BIGINT,
    ROW_NUM INTEGER,
    STAGE_ID BIGINT,
    BEGIN_STAGE1 BIGINT,
    FINAL_STAGE1 BIGINT,
    BEGIN_STAGE2 BIGINT,
    FINAL_STAGE2 BIGINT,
    BEGIN_STAGE3 BIGINT,
    FINAL_STAGE3 BIGINT,
    CLASS_ID BIGINT = null,
    CLASS_TYPE_ID INTEGER = null)
AS
declare variable C1 integer;
declare variable C2 integer;
declare variable C3 integer;
BEGIN

    C1 = 0;
    C2 = 0;
    C3 = 0;

    -- Для первой ступени дополнительно проверяем нулевую параллель
    IF ((STAGE_ID BETWEEN BEGIN_STAGE1 AND FINAL_STAGE1) OR (BEGIN_STAGE1 = 37 AND STAGE_ID = 12765)) THEN
    BEGIN
        C1 = 1;
    END
    ELSE
    IF (STAGE_ID BETWEEN BEGIN_STAGE2 AND FINAL_STAGE2) THEN
    BEGIN
        C2 = 1;
    END
    ELSE
    IF (STAGE_ID BETWEEN BEGIN_STAGE3 AND FINAL_STAGE3 OR (SELECT STATUS FROM OU_LICENCE_TYPE) = 'D') THEN
    BEGIN
        C3 = 1;
    END

    IF (STAGE_ID IS NOT NULL) THEN
    BEGIN
        INSERT INTO REPORT_D12 (SCHOOL_ID, SCHOLAR_ID, ROW_NUM, C1, C2, C3, CLASS_ID, CLASS_TYPE_ID)
        VALUES (:SCHOOL_ID, :SCHOLAR_ID, :ROW_NUM, :C1, :C2, :C3, :CLASS_ID, :CLASS_TYPE_ID);
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE D_12_ADD_INSERT_ROWS (
    I$OBJ_ID BIGINT,
    I$DT1 DATE,
    I$DT2 DATE,
    I$CORRECTION VARCHAR(3) = '3')
AS
declare variable SCHOOL_ID bigint;
declare variable SCHOLAR_ID bigint;
declare variable V$MOVE_ID bigint;
declare variable V$CLASS_TYPE integer;
declare variable V$STAGE_ID bigint;
declare variable V$STAGE_NUM integer;
declare variable V$DATE_IN date;
declare variable V$DATE_OUT date;
declare variable V$REASON_IN bigint;
declare variable V$REASON_OUT bigint;
declare variable OTKUDA_ID bigint;
declare variable OTKUDA_TYPE_ID bigint;
declare variable OTKUDA_OPF_ID bigint;
declare variable OTKUDA_OU_NAME varchar(500);
declare variable KUDA_ID bigint;
declare variable KUDA_TYPE_ID bigint;
declare variable KUDA_OPF_ID bigint;
declare variable KUDA_DOCS_ID bigint;
declare variable KUDA_OU_NAME varchar(500);
declare variable BS1 bigint;
declare variable FS1 bigint;
declare variable BS2 bigint;
declare variable FS2 bigint;
declare variable BS3 bigint;
declare variable FS3 bigint;
declare variable IS_WITHOUT_CORRECTION smallint = 0;
declare variable STOP_1 smallint = 0;
declare variable STOP_2 smallint = 0;
declare variable STOP_3 smallint = 0;
declare variable STOP_4 smallint = 0;
declare variable STOP_5 smallint = 0;
declare variable STOP_22 smallint = 0;
declare variable STOP_23 smallint = 0;
declare variable STOP_52 smallint = 0;
declare variable CHECK_1 smallint;
declare variable CHECK_4 smallint;
declare variable CHECK_22 smallint;
declare variable CHECK_52 smallint;
BEGIN
    SCHOOL_ID = I$OBJ_ID;

    -- НЕТ ?
    IS_WITHOUT_CORRECTION = 0;
    SELECT 1 FROM REPORT_WORDS R WHERE R.ID = 27 AND R.WORD = :I$CORRECTION INTO :IS_WITHOUT_CORRECTION;
    IF(I$CORRECTION = '3') THEN IS_WITHOUT_CORRECTION = 1;

    SELECT BEGIN_STAGE1, FINAL_STAGE1, IIF(BEGIN_STAGE2 > 41, 41, BEGIN_STAGE2), FINAL_STAGE2, BEGIN_STAGE3, FINAL_STAGE3
    FROM D_12_ADD_GET_STAGES(:I$OBJ_ID)
    INTO :BS1, :FS1, :BS2, :FS2, :BS3, :FS3;

    IF (ROW_COUNT = 0) THEN EXIT;

    -- Выбираем всех учеников, которые были в школе указанный период
    I$OBJ_ID = I$OBJ_ID / 1000000000;

    FOR
        SELECT DISTINCT M.PERSON_ID
        FROM PERSON_MOVEMENTS M
        JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
        WHERE M.DATE_DEL IS NULL AND M.DATE_IN <= :I$DT2 AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :I$DT1)
            AND M.OBJ_ID >= :I$OBJ_ID * 1000000000 AND M.OBJ_ID < (:I$OBJ_ID + 1) * 1000000000
        INTO :SCHOLAR_ID
    DO
    BEGIN
        STOP_1 = 0;
        STOP_2 = 0;
        STOP_3 = 0;
        STOP_4 = 0;
        STOP_5 = 0;
        STOP_22 = 0;
        STOP_23 = 0;
        STOP_52 = 0;
        KUDA_ID = NULL;
        OTKUDA_ID = NULL;

        SELECT FIRST 1 V105.LISTVAL_ID
        FROM VALL V105
        WHERE V105.PARAM_ID = 105 AND V105.OBJ_ID = :SCHOLAR_ID AND V105.IS_DEL = 0
        INTO :KUDA_ID;

        SELECT FIRST 1 V78.LISTVAL_ID
        FROM VALL V78
        WHERE V78.PARAM_ID = 78 AND V78.OBJ_ID = :SCHOLAR_ID AND V78.IS_DEL = 0
        INTO :OTKUDA_ID;

        FOR
            SELECT M.OBJ_ID, M.TYPE_IN, M.STAGE_ID, M.REASON_IN, M.DATE_IN, M.REASON_OUT, M.DATE_OUT, LVS.COST
            FROM PERSON_MOVEMENTS M
            JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
            JOIN LISTVALS LVS ON LVS.LISTVAL_ID = M.STAGE_ID
            WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :SCHOLAR_ID AND M.DATE_IN <= :I$DT2 AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :I$DT1)
            ORDER BY M.DATE_OUT DESC
            INTO :V$MOVE_ID, :V$CLASS_TYPE, :V$STAGE_ID, :V$REASON_IN, :V$DATE_IN, :V$REASON_OUT, :V$DATE_OUT, :V$STAGE_NUM
        DO
        BEGIN
            -- Если "переведен на следующий этап обучения" вместо "переведен в другой учебный коллектив" ?
            /*IF (MOVE_TYPE_ID = 807 AND V$STAGE_ID IN (BS2, BS3)) THEN
            BEGIN
                STAGE_ID_PRIOR = NULL;

                SELECT FIRST 1 M.STAGE_ID
                FROM PERSON_MOVEMENTS M
                JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
                WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :SCHOLAR_ID AND M.DATE_IN < :MOVE_DATE
                ORDER BY M.DATE_IN DESC
                INTO :V$STAGE_ID_PRIOR;

                IF (STAGE_ID <> STAGE_ID_PRIOR) THEN MOVE_TYPE_ID = 808;
            END*/

            IF ((IS_WITHOUT_CORRECTION = 0) OR (V$CLASS_TYPE <= 197)) THEN
            BEGIN

                -- [1] Численность на начальную дату
                IF (STOP_1 = 0 AND V$DATE_IN <= I$DT1 AND (V$DATE_OUT IS NULL OR V$DATE_OUT > I$DT1)) THEN
                BEGIN
                    EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 1, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                    STOP_1 = 1;
                END

                -- [52] Численность на конечную дату
                IF (STOP_52 = 0 AND V$DATE_IN < I$DT2 AND (V$DATE_OUT IS NULL OR V$DATE_OUT >= I$DT2)) THEN
                BEGIN
                    EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 52, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                    STOP_52 = 1;
                END

                -- Прибытие обучающихся за период
                IF(V$DATE_IN > I$DT1 AND V$DATE_IN < I$DT2) THEN
                BEGIN

                    -- [2] Окончили обучение по ОП - НОО и ООО, id этапа занижаем чтобы попасть в предыдущий уровень (поскольку зачисление, а не выбытие)
                    IF(STOP_2 = 0 AND V$REASON_IN IN (808, 809) AND V$STAGE_ID IN (BS2, BS3)) THEN
                    BEGIN
                        EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 2, :V$STAGE_ID - 1, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                        STOP_2 = 1;
                    END

                    -- [3] Принят на обучение по ОП
                    IF(STOP_3 = 0 AND (V$REASON_IN = 805 OR (V$REASON_IN IN (808, 809) AND V$STAGE_ID IN (BS2, BS3)))) THEN
                    BEGIN
                        EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 3, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                        STOP_3 = 1;
                    END

                    -- [4] Прибыло всего
                    IF (STOP_4 = 0 AND V$REASON_IN = 806 AND OTKUDA_ID IS NOT NULL) THEN
                    BEGIN
                        EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 4, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                        --STOP_4 = 1;
                    END

                    -- [5-21] Прибыло, детализация
                    IF (STOP_5 = 0 AND V$REASON_IN = 806 AND OTKUDA_ID IS NOT NULL) THEN
                    BEGIN
                        IF (OTKUDA_ID = 818) THEN
                        BEGIN
                            EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 21, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2,:BS3, :FS3);
                        END
                        ELSE IF (OTKUDA_ID = 817) THEN
                        BEGIN
                            EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 20, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                        END
                        ELSE IF (OTKUDA_ID = 816) THEN
                        BEGIN
                            EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 19, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                        END
                        ELSE IF (OTKUDA_ID = 815) THEN
                        BEGIN
                            EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 18, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                        END
                        ELSE IF (OTKUDA_ID IN (813, 814, 3144, 11201, 11362)) THEN
                        BEGIN
                            OTKUDA_OPF_ID = NULL;
                            OTKUDA_TYPE_ID = NULL;

                            SELECT FIRST 1 V160.LISTVAL_ID
                            FROM VALL V160
                            WHERE V160.PARAM_ID = 160 AND V160.OBJ_ID = :SCHOLAR_ID AND V160.IS_DEL = 0
                            INTO :OTKUDA_OPF_ID;

                            SELECT FIRST 1 V104.LISTVAL_ID
                            FROM VALL V104
                            WHERE V104.PARAM_ID = 104 AND V104.OBJ_ID = :SCHOLAR_ID AND V104.IS_DEL = 0
                            INTO :OTKUDA_TYPE_ID;

                            EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 5, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);

                            SELECT FIRST 1 V117.SVAL
                            FROM VALS V117
                            WHERE V117.PARAM_ID = 117 AND V117.OBJ_ID = :SCHOLAR_ID AND V117.IS_DEL = 0
                            INTO :OTKUDA_OU_NAME;

                            IF (OTKUDA_OU_NAME LIKE '%КОР%' OR OTKUDA_OU_NAME LIKE '%АРБ%') THEN
                            BEGIN
                                -- учреждения спорта, Колледж олимпийского резерва
                                -- учреждения культуры, Академия Русского балета
                                EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 13, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                            END
                            ELSE IF (OTKUDA_OPF_ID = 1734) THEN
                            BEGIN
                                EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 12, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                            END
                            ELSE IF (OTKUDA_TYPE_ID IN (965, 966, 967)) THEN
                            BEGIN
                                IF (OTKUDA_ID = 813) THEN
                                BEGIN
                                    EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 10, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                                END
                                IF (OTKUDA_ID = 814) THEN
                                BEGIN
                                    EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 11, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                                END
                            END
                            ELSE IF (OTKUDA_TYPE_ID IN (979, 980, 985, 986, 2216)) THEN
                            BEGIN
                                IF (OTKUDA_ID = 813) THEN
                                BEGIN
                                    EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 8, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                                END
                                IF (OTKUDA_ID = 814) THEN
                                BEGIN
                                    EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 9, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                                END
                            END
                            ELSE IF (OTKUDA_ID = 813) THEN
                            BEGIN
                                EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 6, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                            END
                            ELSE IF (OTKUDA_ID = 11201) THEN
                            BEGIN
                                EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 16, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                            END
                            ELSE IF (OTKUDA_ID = 814) THEN
                            BEGIN
                                EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 7, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                            END
                            ELSE IF (OTKUDA_ID = 11362) THEN
                            BEGIN
                                EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 13, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                            END
                            ELSE IF (OTKUDA_ID = 3144) THEN
                            BEGIN
                                IF (OTKUDA_TYPE_ID IN (988, 989, 990, 991)) THEN
                                BEGIN
                                    EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 13, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                                END
                                ELSE IF (OTKUDA_TYPE_ID IN (1010, 1011, 1014, 1016)) THEN
                                BEGIN
                                    EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 14, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                                END
                                ELSE IF (OTKUDA_TYPE_ID IN (2222, 2223, 2224, 2225)) THEN
                                BEGIN
                                    EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 15, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                                END
                            END
                            ELSE
                            BEGIN
                                EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 17, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                            END
                        END
                        --STOP_5 = 1;
                    END

                END

                -- Выбытие обучающихся за период
                IF(V$DATE_OUT > I$DT1 AND V$DATE_OUT < I$DT2) THEN
                BEGIN

                    -- [2] Окончили обучение по ОП, СОО; НОО и ООО учитываем по зачислению на следующий уровень, а не по выбытию
                    IF(STOP_2 = 0 AND V$REASON_OUT = 812 AND V$STAGE_ID IN (46, 47, 48)) THEN
                    BEGIN
                        EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 2, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                        STOP_2 = 1;
                    END

                    -- [22] Выбыло всего
                    IF (STOP_22 = 0 AND V$REASON_OUT IN (811, 812) AND KUDA_ID IS NOT NULL) THEN
                    BEGIN
                        IF (V$REASON_OUT = 811 OR (V$REASON_OUT = 812 AND V$STAGE_NUM < 10)) THEN
                        BEGIN
                            EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 22, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                        END
                        -- STOP_22 = 1;
                    END

                    -- [23-51] Выбыло детализация
                    IF (STOP_23 = 0 AND V$REASON_OUT IN (811, 812) AND KUDA_ID IS NOT NULL) THEN
                    BEGIN
                        IF (V$REASON_OUT = 811 OR (V$REASON_OUT = 812 AND V$STAGE_NUM < 10)) THEN
                        BEGIN
                            IF ((KUDA_ID >= 910 AND KUDA_ID <= 913) OR KUDA_ID = 917)  THEN
                            BEGIN
                                EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 45, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);

                                IF (KUDA_ID = 913) THEN
                                BEGIN
                                    EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 46, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2,:BS3, :FS3);
                                END
                                ELSE IF (KUDA_ID = 917) THEN
                                BEGIN
                                    EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 47, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                                END
                                ELSE IF (KUDA_ID = 912) THEN
                                BEGIN
                                    EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 48, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                                END
                                ELSE IF (KUDA_ID = 911) THEN
                                BEGIN
                                    EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 50, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                                END
                                ELSE IF (KUDA_ID = 910) THEN
                                BEGIN
                                    EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 49, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                                END
                            END
                            ELSE IF (KUDA_ID IN (908, 909, 914, 915, 916)) THEN
                            BEGIN
                                IF (V$STAGE_ID < BS3) THEN
                                BEGIN
                                    EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 51, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                                END

                                IF (KUDA_ID = 908) THEN
                                BEGIN
                                    EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 42, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                                END
                                ELSE IF (KUDA_ID = 909) THEN
                                BEGIN
                                    EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 43, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                                END
                                ELSE IF (KUDA_ID IN (914, 915)) THEN
                                BEGIN
                                    EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 41, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                                END
                                ELSE IF (KUDA_ID = 916) THEN
                                BEGIN
                                    EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 44, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                                END
                            END
                            ELSE IF (KUDA_ID = 907) THEN
                            BEGIN
                                EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 39, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);

                                KUDA_DOCS_ID = NULL;

                                SELECT FIRST 1 V106.LISTVAL_ID
                                FROM VALL V106
                                WHERE V106.PARAM_ID = 106 AND V106.OBJ_ID = :SCHOLAR_ID AND V106.IS_DEL = 0
                                INTO :KUDA_DOCS_ID;

                                IF (KUDA_DOCS_ID <> 4) THEN
                                BEGIN
                                    EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 40, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                                END
                            END
                            ELSE IF (KUDA_ID = 906) THEN
                            BEGIN
                                EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 37, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                            END
                            ELSE IF (KUDA_ID = 906) THEN
                            BEGIN
                                KUDA_DOCS_ID = NULL;

                                SELECT FIRST 1 V106.LISTVAL_ID
                                FROM VALL V106
                                WHERE V106.PARAM_ID = 106 AND V106.OBJ_ID = :SCHOLAR_ID AND V106.IS_DEL = 0
                                INTO :KUDA_DOCS_ID;

                                IF (KUDA_DOCS_ID <> 4) THEN
                                BEGIN
                                    EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 38, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                                END
                            END
                            ELSE IF (KUDA_ID IN (904, 905, 3143, 11200, 11363)) THEN
                            BEGIN

                                KUDA_OPF_ID = NULL;
                                KUDA_TYPE_ID = NULL;

                                SELECT FIRST 1 V188.LISTVAL_ID
                                FROM VALL V188
                                WHERE V188.PARAM_ID = 188 AND V188.OBJ_ID = :SCHOLAR_ID AND V188.IS_DEL = 0
                                INTO :KUDA_OPF_ID;

                                SELECT FIRST 1 V107.LISTVAL_ID
                                FROM VALL V107
                                WHERE V107.PARAM_ID = 107 AND V107.OBJ_ID = :SCHOLAR_ID AND V107.IS_DEL = 0
                                INTO :KUDA_TYPE_ID;

                                EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 23, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);

                                KUDA_DOCS_ID = NULL;

                                SELECT FIRST 1 V106.LISTVAL_ID
                                FROM VALL V106
                                WHERE V106.PARAM_ID = 106 AND V106.OBJ_ID = :SCHOLAR_ID AND V106.IS_DEL = 0
                                INTO :KUDA_DOCS_ID;

                                IF (KUDA_DOCS_ID <> 4) THEN
                                BEGIN
                                    EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 24, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                                END

                                SELECT FIRST 1 V161.SVAL
                                FROM VALS V161
                                WHERE V161.PARAM_ID = 161 AND V161.OBJ_ID = :SCHOLAR_ID AND V161.IS_DEL = 0
                                INTO :KUDA_OU_NAME;

                                IF (KUDA_OU_NAME LIKE '%КОР%' OR KUDA_OU_NAME LIKE '%АРБ%') THEN
                                BEGIN
                                    -- учреждения спорта, Колледж олимпийского резерва
                                    -- учреждения культуры, Академия Русского балета
                                    EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 32, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                                END
                                ELSE IF (KUDA_OPF_ID = 1734) THEN
                                BEGIN
                                    EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 31, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                                END
                                ELSE IF (KUDA_ID = 11200) THEN
                                BEGIN
                                    EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 36, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                                END
                                ELSE IF (KUDA_ID = 11363) THEN
                                BEGIN
                                    EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 32, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                                END
                                ELSE IF (KUDA_ID = 3143) THEN
                                BEGIN
                                    IF (KUDA_TYPE_ID IN (988, 989, 990, 991)) THEN
                                    BEGIN
                                        EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 32, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                                    END
                                    ELSE IF (KUDA_TYPE_ID IN (1010, 1011, 1014, 1016)) THEN
                                    BEGIN
                                        EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 33, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                                    END
                                    ELSE IF (KUDA_TYPE_ID IN (2222, 2223, 2224, 2225)) THEN
                                    BEGIN
                                        EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 34, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                                    END
                                    ELSE
                                    BEGIN
                                        EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 35, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                                    END
                                END
                                ELSE IF (KUDA_TYPE_ID IN (965, 966, 967)) THEN
                                BEGIN
                                    IF (KUDA_ID = 904) THEN
                                    BEGIN
                                    EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 29, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                                        END
                                    IF (KUDA_ID = 905) THEN
                                    BEGIN
                                        EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 30, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                                    END
                                END
                                ELSE IF (KUDA_TYPE_ID IN (979, 980, 985, 986, 2216)) THEN
                                BEGIN
                                    IF (KUDA_ID = 904) THEN
                                    BEGIN
                                        EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 27, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                                    END
                                    ELSE IF (KUDA_ID = 905) THEN
                                    BEGIN
                                        EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 28, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                                    END
                                END
                                ELSE IF (KUDA_ID = 904) THEN
                                BEGIN
                                    EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 25, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                                END
                                ELSE IF (KUDA_ID = 905) THEN
                                BEGIN
                                    EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 26, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                                END
                            END
                        END
                        -- STOP_23 = 1;
                    END

                END

            END
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE D_12_ADD_INSERT_ROWS_DISTR (
    I$OBJ_ID BIGINT,
    I$DT1 DATE,
    I$DT2 DATE,
    I$CORRECTION VARCHAR(3))
AS
declare variable SCHOOL_ID bigint;
declare variable SCHOLAR_ID bigint;
declare variable V$STAGE_ID bigint;
declare variable V$STAGE_NUM integer;
declare variable V$REASON_IN bigint;
declare variable V$DATE_IN date;
declare variable V$REASON_OUT bigint;
declare variable V$DATE_OUT date;
declare variable OTKUDA_ID bigint;
declare variable OTKUDA_TYPE_ID bigint;
declare variable OTKUDA_OPF_ID bigint;
declare variable OTKUDA_OU_NAME varchar(500);
declare variable KUDA_ID bigint;
declare variable KUDA_TYPE_ID bigint;
declare variable KUDA_OPF_ID bigint;
declare variable KUDA_DOCS_ID bigint;
declare variable KUDA_OU_NAME varchar(500);
declare variable BS1 bigint;
declare variable FS1 bigint;
declare variable BS2 bigint;
declare variable FS2 bigint;
declare variable BS3 bigint;
declare variable FS3 bigint;
declare variable IS_WITHOUT_CORRECTION smallint = 0;
declare variable V$CLASS_TYPE bigint;
declare variable STOP_1 smallint = 0;
declare variable STOP_2 smallint = 0;
declare variable STOP_3 smallint = 0;
declare variable STOP_4 smallint = 0;
declare variable STOP_5 smallint = 0;
declare variable STOP_22 smallint = 0;
declare variable STOP_23 smallint = 0;
declare variable STOP_52 smallint = 0;
declare variable CHECK_1 smallint;
declare variable CHECK_4 smallint;
declare variable CHECK_22 smallint;
declare variable CHECK_52 smallint;
BEGIN
    SCHOOL_ID = :I$OBJ_ID;

    -- НЕТ ?
    IS_WITHOUT_CORRECTION = 0;
    SELECT 1 FROM REPORT_WORDS R WHERE R.ID = 27 AND R.WORD = :I$CORRECTION INTO :IS_WITHOUT_CORRECTION;
    IF(I$CORRECTION = '3') THEN IS_WITHOUT_CORRECTION = 1;

    SELECT BEGIN_STAGE1, FINAL_STAGE1, IIF(BEGIN_STAGE2 > 41, 41, BEGIN_STAGE2), FINAL_STAGE2, BEGIN_STAGE3, FINAL_STAGE3
    FROM D_12_ADD_GET_STAGES(:I$OBJ_ID)
    INTO :BS1, :FS1, :BS2, :FS2, :BS3, :FS3;

    IF (ROW_COUNT = 0) THEN EXIT;

    I$OBJ_ID = I$OBJ_ID / 1000000000;

    FOR
        SELECT DISTINCT M.PERSON_ID
        FROM PERSON_MOVEMENTS M
        JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
        WHERE M.DATE_DEL IS NULL AND M.OBJ_ID >= :I$OBJ_ID * 1000000000 AND M.OBJ_ID < (:I$OBJ_ID + 1) * 1000000000
            AND M.DATE_IN <= :I$DT2 AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :I$DT1)
        ORDER BY M.PERSON_ID, M.DATE_IN
        INTO :SCHOLAR_ID
    DO
    BEGIN

        FOR
            SELECT M.TYPE_IN, M.STAGE_ID, M.REASON_IN, M.DATE_IN, M.REASON_OUT, M.DATE_OUT, LVS.COST
            FROM PERSON_MOVEMENTS M
            JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
            JOIN LISTVALS LVS ON LVS.LISTVAL_ID = M.STAGE_ID
            WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :SCHOLAR_ID AND M.DATE_IN <= :I$DT2 AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :I$DT1)
            ORDER BY M.DATE_OUT DESC
            INTO :V$CLASS_TYPE, :V$STAGE_ID, :V$REASON_IN, :V$DATE_IN, :V$REASON_OUT, :V$DATE_OUT, V$STAGE_NUM
        DO
        BEGIN

            STOP_1 = 0;
            STOP_2 = 0;
            STOP_3 = 0;
            STOP_4 = 0;
            STOP_5 = 0;
            STOP_22 = 0;
            STOP_23 = 0;
            STOP_52 = 0;
            KUDA_ID = NULL;
            OTKUDA_ID = NULL;
    
            SELECT FIRST 1 V105.LISTVAL_ID
            FROM VALL V105
            WHERE V105.PARAM_ID = 105 AND V105.OBJ_ID = :SCHOLAR_ID AND V105.IS_DEL = 0
            INTO :KUDA_ID;

            SELECT FIRST 1 V78.LISTVAL_ID
            FROM VALL V78
            WHERE V78.PARAM_ID = 78 AND V78.OBJ_ID = :SCHOLAR_ID AND V78.IS_DEL = 0
            INTO :OTKUDA_ID;

        -- Если "переведен на следующий этап обучения" вместо "переведен в другой учебный коллектив" ?
        /*IF (MOVE_TYPE_ID = 807 AND STAGE_ID IN (BS2, BS3)) THEN
        BEGIN
            STAGE_ID_PRIOR = NULL;

            SELECT FIRST 1 M.STAGE_ID
            FROM PERSON_MOVEMENTS M
            JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
            WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :SCHOLAR_ID AND (M.DATE_IN < :MOVE_DATE OR M.DATE_OUT < :MOVE_DATE)
            ORDER BY COALESCE(M.DATE_OUT, M.DATE_IN) DESC
            INTO :STAGE_ID_PRIOR;

            IF (STAGE_ID <> STAGE_ID_PRIOR) THEN
            BEGIN
                MOVE_TYPE_ID = 808;
            END
        END*/

            IF (IS_WITHOUT_CORRECTION = 0 OR V$CLASS_TYPE <= 197) THEN
            BEGIN

                IF ((IS_WITHOUT_CORRECTION = 0) OR (V$CLASS_TYPE <= 197)) THEN
                BEGIN

                    -- [1] Численность на начальную дату
                    IF (STOP_1 = 0 AND V$DATE_IN <= I$DT1 AND (V$DATE_OUT IS NULL OR V$DATE_OUT > I$DT1)) THEN
                    BEGIN
                        EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 1, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                        STOP_1 = 1;
                    END

                    -- [52] Численность на конечную дату
                    IF (STOP_52 = 0 AND V$DATE_IN < I$DT2 AND (V$DATE_OUT IS NULL OR V$DATE_OUT >= I$DT2)) THEN
                    BEGIN
                        EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 52, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                        STOP_52 = 1;
                    END

                    -- Прибытие обучающихся за период
                    IF(V$DATE_IN > I$DT1 AND V$DATE_IN < I$DT2) THEN
                    BEGIN

                        -- [2] Окончили обучение по ОП - НОО и ООО, id этапа занижаем чтобы попасть в предыдущий уровень (поскольку зачисление, а не выбытие)
                        IF(STOP_2 = 0 AND V$REASON_IN IN (808, 809) AND V$STAGE_ID IN (BS2, BS3)) THEN
                        BEGIN
                            EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 2, :V$STAGE_ID - 1, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                            STOP_2 = 1;
                        END

                        -- [3] Принят на обучение по ОП
                        IF(STOP_3 = 0 AND (V$REASON_IN = 805 OR (V$REASON_IN IN (808, 809) AND V$STAGE_ID IN (BS2, BS3)))) THEN
                        BEGIN
                            EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 3, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                            STOP_3 = 1;
                        END

                        -- [4] Прибыло всего
                        IF (STOP_4 = 0 AND V$REASON_IN = 806 AND OTKUDA_ID IS NOT NULL) THEN
                        BEGIN
                            EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 4, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                            --STOP_4 = 1;
                        END

                        -- [5-21] Прибыло, детализация
                        IF (STOP_5 = 0 AND V$REASON_IN = 806 AND OTKUDA_ID IS NOT NULL) THEN
                        BEGIN
                            IF (OTKUDA_ID = 818) THEN
                            BEGIN
                                EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 21, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2,:BS3, :FS3);
                            END
                            ELSE IF (OTKUDA_ID = 817) THEN
                            BEGIN
                                EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 20, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                            END
                            ELSE IF (OTKUDA_ID = 816) THEN
                            BEGIN
                                EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 19, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                            END
                            ELSE IF (OTKUDA_ID = 815) THEN
                            BEGIN
                                EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 18, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                            END
                            ELSE IF (OTKUDA_ID IN (813, 814, 3144, 11201, 11362)) THEN
                            BEGIN
                                OTKUDA_OPF_ID = NULL;
                                OTKUDA_TYPE_ID = NULL;

                                SELECT FIRST 1 V160.LISTVAL_ID
                                FROM VALL V160
                                WHERE V160.PARAM_ID = 160 AND V160.OBJ_ID = :SCHOLAR_ID AND V160.IS_DEL = 0
                                INTO :OTKUDA_OPF_ID;

                                SELECT FIRST 1 V104.LISTVAL_ID
                                FROM VALL V104
                                WHERE V104.PARAM_ID = 104 AND V104.OBJ_ID = :SCHOLAR_ID AND V104.IS_DEL = 0
                                INTO :OTKUDA_TYPE_ID;

                                EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 5, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);

                                SELECT FIRST 1 V117.SVAL
                                FROM VALS V117
                                WHERE V117.PARAM_ID = 117 AND V117.OBJ_ID = :SCHOLAR_ID AND V117.IS_DEL = 0
                                INTO :OTKUDA_OU_NAME;

                                IF (OTKUDA_OU_NAME LIKE '%КОР%' OR OTKUDA_OU_NAME LIKE '%АРБ%') THEN
                                BEGIN
                                    -- учреждения спорта, Колледж олимпийского резерва
                                    -- учреждения культуры, Академия Русского балета
                                    EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 13, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                                END
                                ELSE IF (OTKUDA_OPF_ID = 1734) THEN
                                BEGIN
                                    EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 12, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                                END
                                ELSE IF (OTKUDA_TYPE_ID IN (965, 966, 967)) THEN
                                BEGIN
                                    IF (OTKUDA_ID = 813) THEN
                                    BEGIN
                                        EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 10, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                                    END
                                    IF (OTKUDA_ID = 814) THEN
                                    BEGIN
                                        EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 11, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                                    END
                                END
                                ELSE IF (OTKUDA_TYPE_ID IN (979, 980, 985, 986, 2216)) THEN
                                BEGIN
                                    IF (OTKUDA_ID = 813) THEN
                                    BEGIN
                                        EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 8, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                                    END
                                    IF (OTKUDA_ID = 814) THEN
                                    BEGIN
                                        EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 9, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                                    END
                                END
                                ELSE IF (OTKUDA_ID = 813) THEN
                                BEGIN
                                    EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 6, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                                END
                                ELSE IF (OTKUDA_ID = 11201) THEN
                                BEGIN
                                    EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 16, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                                END
                                ELSE IF (OTKUDA_ID = 814) THEN
                                BEGIN
                                    EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 7, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                                END
                                ELSE IF (OTKUDA_ID = 11362) THEN
                                BEGIN
                                    EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 13, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                               END
                                ELSE IF (OTKUDA_ID = 3144) THEN
                                BEGIN
                                    IF (OTKUDA_TYPE_ID IN (988, 989, 990, 991)) THEN
                                    BEGIN
                                        EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 13, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                                    END
                                    ELSE IF (OTKUDA_TYPE_ID IN (1010, 1011, 1014, 1016)) THEN
                                    BEGIN
                                        EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 14, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                                    END
                                    ELSE IF (OTKUDA_TYPE_ID IN (2222, 2223, 2224, 2225)) THEN
                                    BEGIN
                                        EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 15, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                                    END
                                END
                                ELSE
                                BEGIN
                                    EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 17, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                                END
                            END
                            --STOP_5 = 1;
                        END

                    END

                    -- Выбытие обучающихся за период
                    IF(V$DATE_OUT > I$DT1 AND V$DATE_OUT < I$DT2) THEN
                    BEGIN

                        -- [2] Окончили обучение по ОП, СОО; НОО и ООО учитываем по зачислению на следующий уровень, а не по выбытию
                        IF(STOP_2 = 0 AND V$REASON_OUT = 812 AND V$STAGE_ID IN (46, 47, 48)) THEN
                        BEGIN
                            EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 2, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                            STOP_2 = 1;
                        END

                        -- [22] Выбыло всего
                        IF (STOP_22 = 0 AND V$REASON_OUT IN (811, 812) AND KUDA_ID IS NOT NULL) THEN
                        BEGIN
                            IF (V$REASON_OUT = 811 OR (V$REASON_OUT = 812 AND V$STAGE_NUM < 10)) THEN
                            BEGIN
                                EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 22, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                            END
                            -- STOP_22 = 1;
                        END

                        -- [23-51] Выбыло детализация
                        IF (STOP_23 = 0 AND V$REASON_OUT IN (811, 812) AND KUDA_ID IS NOT NULL) THEN
                        BEGIN
                            IF (V$REASON_OUT = 811 OR (V$REASON_OUT = 812 AND V$STAGE_NUM < 10)) THEN
                            BEGIN
                                IF ((KUDA_ID >= 910 AND KUDA_ID <= 913) OR KUDA_ID = 917)  THEN
                                BEGIN
                                    EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 45, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);

                                    IF (KUDA_ID = 913) THEN
                                    BEGIN
                                        EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 46, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2,:BS3, :FS3);
                                    END
                                    ELSE IF (KUDA_ID = 917) THEN
                                    BEGIN
                                        EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 47, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                                    END
                                    ELSE IF (KUDA_ID = 912) THEN
                                    BEGIN
                                        EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 48, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                                    END
                                    ELSE IF (KUDA_ID = 911) THEN
                                    BEGIN
                                        EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 50, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                                    END
                                    ELSE IF (KUDA_ID = 910) THEN
                                    BEGIN
                                        EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 49, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                                    END
                                END
                                ELSE IF (KUDA_ID IN (908, 909, 914, 915, 916)) THEN
                                BEGIN
                                    IF (V$STAGE_ID < BS3) THEN
                                    BEGIN
                                        EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 51, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                                    END

                                    IF (KUDA_ID = 908) THEN
                                    BEGIN
                                        EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 42, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                                    END
                                    ELSE IF (KUDA_ID = 909) THEN
                                    BEGIN
                                        EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 43, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                                    END
                                    ELSE IF (KUDA_ID IN (914, 915)) THEN
                                    BEGIN
                                        EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 41, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                                    END
                                    ELSE IF (KUDA_ID = 916) THEN
                                    BEGIN
                                        EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 44, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                                    END
                                END
                                ELSE IF (KUDA_ID = 907) THEN
                                BEGIN
                                    EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 39, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);

                                    KUDA_DOCS_ID = NULL;

                                    SELECT FIRST 1 V106.LISTVAL_ID
                                    FROM VALL V106
                                    WHERE V106.PARAM_ID = 106 AND V106.OBJ_ID = :SCHOLAR_ID AND V106.IS_DEL = 0
                                    INTO :KUDA_DOCS_ID;

                                    IF (KUDA_DOCS_ID <> 4) THEN
                                    BEGIN
                                        EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 40, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                                    END
                                END
                                ELSE IF (KUDA_ID = 906) THEN
                                BEGIN
                                    EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 37, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                                END
                                ELSE IF (KUDA_ID = 906) THEN
                                BEGIN
                                    KUDA_DOCS_ID = NULL;

                                    SELECT FIRST 1 V106.LISTVAL_ID
                                    FROM VALL V106
                                    WHERE V106.PARAM_ID = 106 AND V106.OBJ_ID = :SCHOLAR_ID AND V106.IS_DEL = 0
                                    INTO :KUDA_DOCS_ID;

                                    IF (KUDA_DOCS_ID <> 4) THEN
                                    BEGIN
                                        EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 38, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                                    END
                                END
                                ELSE IF (KUDA_ID IN (904, 905, 3143, 11200, 11363)) THEN
                                BEGIN

                                    KUDA_OPF_ID = NULL;
                                    KUDA_TYPE_ID = NULL;

                                    SELECT FIRST 1 V188.LISTVAL_ID
                                    FROM VALL V188
                                    WHERE V188.PARAM_ID = 188 AND V188.OBJ_ID = :SCHOLAR_ID AND V188.IS_DEL = 0
                                    INTO :KUDA_OPF_ID;

                                    SELECT FIRST 1 V107.LISTVAL_ID
                                    FROM VALL V107
                                    WHERE V107.PARAM_ID = 107 AND V107.OBJ_ID = :SCHOLAR_ID AND V107.IS_DEL = 0
                                    INTO :KUDA_TYPE_ID;

                                    EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 23, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);

                                    KUDA_DOCS_ID = NULL;

                                    SELECT FIRST 1 V106.LISTVAL_ID
                                    FROM VALL V106
                                    WHERE V106.PARAM_ID = 106 AND V106.OBJ_ID = :SCHOLAR_ID AND V106.IS_DEL = 0
                                    INTO :KUDA_DOCS_ID;

                                    IF (KUDA_DOCS_ID <> 4) THEN
                                    BEGIN
                                        EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 24, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                                    END

                                    SELECT FIRST 1 V161.SVAL
                                    FROM VALS V161
                                    WHERE V161.PARAM_ID = 161 AND V161.OBJ_ID = :SCHOLAR_ID AND V161.IS_DEL = 0
                                    INTO :KUDA_OU_NAME;

                                    IF (KUDA_OU_NAME LIKE '%КОР%' OR KUDA_OU_NAME LIKE '%АРБ%') THEN
                                    BEGIN
                                        -- учреждения спорта, Колледж олимпийского резерва
                                        -- учреждения культуры, Академия Русского балета
                                        EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 32, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                                    END
                                    ELSE IF (KUDA_OPF_ID = 1734) THEN
                                    BEGIN
                                        EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 31, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                                    END
                                    ELSE IF (KUDA_ID = 11200) THEN
                                    BEGIN
                                        EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 36, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                                    END
                                    ELSE IF (KUDA_ID = 11363) THEN
                                    BEGIN
                                        EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 32, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                                    END
                                    ELSE IF (KUDA_ID = 3143) THEN
                                    BEGIN
                                        IF (KUDA_TYPE_ID IN (988, 989, 990, 991)) THEN
                                        BEGIN
                                            EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 32, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                                        END
                                        ELSE IF (KUDA_TYPE_ID IN (1010, 1011, 1014, 1016)) THEN
                                        BEGIN
                                            EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 33, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                                        END
                                        ELSE IF (KUDA_TYPE_ID IN (2222, 2223, 2224, 2225)) THEN
                                        BEGIN
                                            EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 34, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                                        END
                                        ELSE
                                        BEGIN
                                            EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 35, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                                        END
                                    END
                                    ELSE IF (KUDA_TYPE_ID IN (965, 966, 967)) THEN
                                    BEGIN
                                        IF (KUDA_ID = 904) THEN
                                        BEGIN
                                            EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 29, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                                        END
                                        IF (KUDA_ID = 905) THEN
                                        BEGIN
                                            EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 30, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                                        END
                                    END
                                    ELSE IF (KUDA_TYPE_ID IN (979, 980, 985, 986, 2216)) THEN
                                    BEGIN
                                        IF (KUDA_ID = 904) THEN
                                        BEGIN
                                            EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 27, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                                        END
                                        ELSE IF (KUDA_ID = 905) THEN
                                        BEGIN
                                            EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 28, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                                        END
                                    END
                                    ELSE IF (KUDA_ID = 904) THEN
                                    BEGIN
                                        EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 25, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                                    END
                                    ELSE IF (KUDA_ID = 905) THEN
                                    BEGIN
                                        EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 26, :V$STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3);
                                    END
                                END
                            END
                            -- STOP_23 = 1;
                        END
                    END
                END
            END
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE D_12_LIST (
    I$OBJ_ID BIGINT,
    I$DT1 DATE,
    I$DT2 DATE,
    I$LBL INTEGER,
    I$USER_ID BIGINT)
RETURNS (
    V1 VARCHAR(4000),
    V2 VARCHAR(400),
    V3 VARCHAR(4000),
    V4 VARCHAR(100),
    V5 VARCHAR(400))
AS
declare variable SCHOOL_ID bigint;
declare variable SCHOLAR_ID bigint;
declare variable MOVE_ID bigint;
declare variable STAGE_ID bigint;
declare variable MOVE_DATE date;
declare variable OTKUDA_ID bigint;
declare variable KUDA_ID bigint;
declare variable BEGIN_STAGE1 bigint;
declare variable FINAL_STAGE1 bigint;
declare variable BEGIN_STAGE2 bigint;
declare variable FINAL_STAGE2 bigint;
declare variable BEGIN_STAGE3 bigint;
declare variable FINAL_STAGE3 bigint;
declare variable HAS_ZERO smallint;
BEGIN
    SCHOOL_ID = :I$OBJ_ID;

    V1 = '';
    V2 = '';
    V3 = '';
    V4 = '';
    V5 = '';

    SELECT BEGIN_STAGE1, FINAL_STAGE1, BEGIN_STAGE2, FINAL_STAGE2, BEGIN_STAGE3, FINAL_STAGE3, HAS_ZERO
    FROM D_12_ADD_GET_STAGES(:I$OBJ_ID)
    INTO :BEGIN_STAGE1, :FINAL_STAGE1, :BEGIN_STAGE2, :FINAL_STAGE2, :BEGIN_STAGE3, :FINAL_STAGE3, :HAS_ZERO;

    IF (ROW_COUNT = 0) THEN EXIT;

    FOR
        SELECT L10.OBJ_ID
        FROM LINKS L7
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
        JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        WHERE L7.PARENT_ID = :SCHOOL_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL

        UNION

        SELECT L10.OBJ_ID
        FROM LINKS L78
        JOIN LINKS L81 ON L81.PARENT_ID = L78.OBJ_ID AND L81.OBJ_TYPE_ID = 81 AND L81.DATE_DEL IS NULL
        JOIN LINKS L10 ON L10.PARENT_ID = L81.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        WHERE L78.PARENT_ID = :SCHOOL_ID AND L78.OBJ_TYPE_ID = 78 AND L78.DATE_DEL IS NULL

        UNION

        SELECT L10.OBJ_ID
        FROM LINKS L78
        JOIN LINKS L82 ON L82.PARENT_ID = L78.OBJ_ID AND L82.OBJ_TYPE_ID = 82 AND L82.DATE_DEL IS NULL
        JOIN LINKS L10 ON L10.PARENT_ID = L82.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        WHERE L78.PARENT_ID = :SCHOOL_ID AND L78.OBJ_TYPE_ID = 78 AND L78.DATE_DEL IS NULL

        UNION

        SELECT L10.OBJ_ID
        FROM LINKS L78
        JOIN LINKS L83 ON L83.PARENT_ID = L78.OBJ_ID AND L83.OBJ_TYPE_ID = 83 AND L83.DATE_DEL IS NULL
        JOIN LINKS L10 ON L10.PARENT_ID = L83.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        WHERE L78.PARENT_ID = :SCHOOL_ID AND L78.OBJ_TYPE_ID = 78 AND L78.DATE_DEL IS NULL

        INTO :SCHOLAR_ID
    DO
    BEGIN
        IF (I$LBL IN (100, 110, 120, 130, 200, 210, 220, 230, 300, 310, 320, 330)) THEN
        BEGIN
            MOVE_DATE = NULL;
            MOVE_ID = NULL;
            STAGE_ID = NULL;

            SELECT FIRST 1 M.OBJ_ID, M.DATE_IN, M.STAGE_ID
            FROM PERSON_MOVEMENTS M
            JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
            WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :SCHOLAR_ID AND M.DATE_IN >= :I$DT1 AND M.DATE_IN <= :I$DT2 AND M.REASON_IN = 806
            ORDER BY M.DATE_IN DESC
            INTO :MOVE_ID, :MOVE_DATE, :STAGE_ID;

            IF (MOVE_ID IS NOT NULL) THEN
            BEGIN

                OTKUDA_ID = NULL;

                SELECT FIRST 1 V78.LISTVAL_ID
                FROM VALL V78
                WHERE V78.PARAM_ID = 78 AND V78.OBJ_ID = :SCHOLAR_ID AND V78.IS_DEL = 0
                INTO :OTKUDA_ID;

                IF ((I$LBL IN (100, 110, 120, 130)) AND ((STAGE_ID BETWEEN BEGIN_STAGE1 AND FINAL_STAGE1) OR (HAS_ZERO = 1 AND STAGE_ID = 12765)) ) THEN
                BEGIN
                    IF ((I$LBL = 100) AND (OTKUDA_ID = 813)) THEN
                    BEGIN
                        SELECT V1, V2, V3, V4, V5
                        FROM D_12_LIST_GET_SCHOOLAR(:SCHOLAR_ID, :MOVE_ID, :I$USER_ID, 0)
                        INTO :V1, :V2, :V3, :V4, :V5;
                        IF (ROW_COUNT > 0) THEN SUSPEND;
                    END
                    ELSE
                    IF ((I$LBL = 110) AND (OTKUDA_ID = 814)) THEN
                    BEGIN
                        SELECT V1, V2, V3, V4, V5
                        FROM D_12_LIST_GET_SCHOOLAR(:SCHOLAR_ID, :MOVE_ID, :I$USER_ID, 0)
                        INTO :V1, :V2, :V3, :V4, :V5;
                        IF (ROW_COUNT > 0) THEN SUSPEND;
                    END
                    ELSE
                    IF ((I$LBL = 120) AND (OTKUDA_ID = 815)) THEN
                    BEGIN
                        SELECT V1, V2, V3, V4, V5
                        FROM D_12_LIST_GET_SCHOOLAR(:SCHOLAR_ID, :MOVE_ID, :I$USER_ID, 0)
                        INTO :V1, :V2, :V3, :V4, :V5;
                        IF (ROW_COUNT > 0) THEN SUSPEND;
                    END
                    ELSE
                    IF ((I$LBL = 130) AND
                        (((OTKUDA_ID <> 813) AND
                        (OTKUDA_ID <> 814) AND
                        (OTKUDA_ID <> 815)) OR (OTKUDA_ID IS NULL))) THEN
                    BEGIN
                        SELECT V1, V2, V3, V4, V5
                        FROM D_12_LIST_GET_SCHOOLAR(:SCHOLAR_ID, :MOVE_ID, :I$USER_ID, 0)
                        INTO :V1, :V2, :V3, :V4, :V5;
                        IF (ROW_COUNT > 0) THEN SUSPEND;
                    END
                END
                ELSE
                IF ((I$LBL IN (200, 210, 220, 230)) AND
                    (STAGE_ID BETWEEN BEGIN_STAGE2 AND FINAL_STAGE2)) THEN
                BEGIN
                    IF ((I$LBL = 200) AND (OTKUDA_ID = 813)) THEN
                    BEGIN
                        SELECT V1, V2, V3, V4, V5
                        FROM D_12_LIST_GET_SCHOOLAR(:SCHOLAR_ID, :MOVE_ID, :I$USER_ID, 0)
                        INTO :V1, :V2, :V3, :V4, :V5;
                        IF (ROW_COUNT > 0) THEN SUSPEND;
                    END
                    ELSE
                    IF ((I$LBL = 210) AND (OTKUDA_ID = 814)) THEN
                    BEGIN
                        SELECT V1, V2, V3, V4, V5
                        FROM D_12_LIST_GET_SCHOOLAR(:SCHOLAR_ID, :MOVE_ID, :I$USER_ID, 0)
                        INTO :V1, :V2, :V3, :V4, :V5;
                        IF (ROW_COUNT > 0) THEN SUSPEND;
                    END
                    ELSE
                    IF ((I$LBL = 220) AND (OTKUDA_ID = 815)) THEN
                    BEGIN
                        SELECT V1, V2, V3, V4, V5
                        FROM D_12_LIST_GET_SCHOOLAR(:SCHOLAR_ID, :MOVE_ID, :I$USER_ID, 0)
                        INTO :V1, :V2, :V3, :V4, :V5;
                        IF (ROW_COUNT > 0) THEN SUSPEND;
                    END
                    ELSE
                    IF ((I$LBL = 230) AND
                        (((OTKUDA_ID <> 813) AND
                        (OTKUDA_ID <> 814) AND
                        (OTKUDA_ID <> 815)) OR (OTKUDA_ID IS NULL))) THEN
                    BEGIN
                        SELECT V1, V2, V3, V4, V5
                        FROM D_12_LIST_GET_SCHOOLAR(:SCHOLAR_ID, :MOVE_ID, :I$USER_ID, 0)
                        INTO :V1, :V2, :V3, :V4, :V5;
                        IF (ROW_COUNT > 0) THEN SUSPEND;
                    END
                END
                ELSE
                IF ((I$LBL IN (300, 310, 320, 330)) AND
                    (STAGE_ID BETWEEN BEGIN_STAGE3 AND FINAL_STAGE3)) THEN
                BEGIN
                    IF ((I$LBL = 300) AND (OTKUDA_ID = 813)) THEN
                    BEGIN
                        SELECT V1, V2, V3, V4, V5
                        FROM D_12_LIST_GET_SCHOOLAR(:SCHOLAR_ID, :MOVE_ID, :I$USER_ID, 0)
                        INTO :V1, :V2, :V3, :V4, :V5;
                        IF (ROW_COUNT > 0) THEN SUSPEND;
                    END
                    ELSE
                    IF ((I$LBL = 310) AND (OTKUDA_ID = 814)) THEN
                    BEGIN
                        SELECT V1, V2, V3, V4, V5
                        FROM D_12_LIST_GET_SCHOOLAR(:SCHOLAR_ID, :MOVE_ID, :I$USER_ID, 0)
                        INTO :V1, :V2, :V3, :V4, :V5;
                        IF (ROW_COUNT > 0) THEN SUSPEND;
                    END
                    ELSE
                    IF ((I$LBL = 320) AND (OTKUDA_ID = 815)) THEN
                    BEGIN
                        SELECT V1, V2, V3, V4, V5
                        FROM D_12_LIST_GET_SCHOOLAR(:SCHOLAR_ID, :MOVE_ID, :I$USER_ID, 0)
                        INTO :V1, :V2, :V3, :V4, :V5;
                        IF (ROW_COUNT > 0) THEN SUSPEND;
                    END
                    ELSE
                    IF ((I$LBL = 330) AND
                        (((OTKUDA_ID <> 813) AND
                        (OTKUDA_ID <> 814) AND
                        (OTKUDA_ID <> 815)) OR (OTKUDA_ID IS NULL))) THEN
                    BEGIN
                        SELECT V1, V2, V3, V4, V5
                        FROM D_12_LIST_GET_SCHOOLAR(:SCHOLAR_ID, :MOVE_ID, :I$USER_ID, 0)
                        INTO :V1, :V2, :V3, :V4, :V5;
                        IF (ROW_COUNT > 0) THEN SUSPEND;
                    END
                END
            END
        END

        IF (I$LBL IN (500, 510, 520, 530, 600, 610, 620, 630, 700, 710, 720, 730)) THEN
        BEGIN
            MOVE_DATE = NULL;
            MOVE_ID = NULL;
            STAGE_ID = NULL;

            SELECT FIRST 1 M.OBJ_ID, M.DATE_IN, M.STAGE_ID, M.NAME_IN
            FROM PERSON_MOVEMENTS M
            JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
            JOIN LINKS L10 ON L10.OBJ_ID = M.PERSON_ID AND L10.DATE_DEL IS NULL AND L10.PARENT_TYPE_ID IN (81, 82, 9)
            WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :SCHOLAR_ID AND M.DATE_OUT >= :I$DT1 AND M.DATE_OUT <= :I$DT2 AND M.REASON_OUT IN (811, 812)
            ORDER BY M.DATE_OUT DESC
            INTO :MOVE_ID, :MOVE_DATE, :STAGE_ID, :V2;

            IF (MOVE_ID IS NOT NULL) THEN
            BEGIN
                KUDA_ID = NULL;

                SELECT FIRST 1 V105.LISTVAL_ID
                FROM VALL V105
                WHERE V105.PARAM_ID = 105 AND V105.OBJ_ID = :SCHOLAR_ID AND V105.IS_DEL = 0
                INTO :KUDA_ID;

--                IF ((I$LBL IN (500, 510, 520, 530)) AND ((STAGE_ID BETWEEN BEGIN_STAGE1 AND FINAL_STAGE1) OR (HAS_ZERO = 1 AND STAGE_ID = 1))) THEN
                IF ((I$LBL IN (500, 510, 520, 530)) AND ((STAGE_ID BETWEEN BEGIN_STAGE1 AND FINAL_STAGE1) OR (HAS_ZERO = 1 AND STAGE_ID = 12765))) THEN
                BEGIN
                    IF ((I$LBL = 500) AND (KUDA_ID = 904)) THEN
                    BEGIN
                        SELECT V1, V6, V4, V5
                        FROM D_12_LIST_GET_SCHOOLAR(:SCHOLAR_ID, :MOVE_ID, :I$USER_ID, 1)
                        INTO :V1, :V3, :V4, :V5;
                        IF (ROW_COUNT > 0) THEN SUSPEND;
                    END
                    ELSE
                    IF ((I$LBL = 510) AND (KUDA_ID = 905)) THEN
                    BEGIN
                        SELECT V1, V6, V4, V5
                        FROM D_12_LIST_GET_SCHOOLAR(:SCHOLAR_ID, :MOVE_ID, :I$USER_ID, 1)
                        INTO :V1, :V3, :V4, :V5;
                        IF (ROW_COUNT > 0) THEN SUSPEND;
                    END
                    ELSE
                    IF ((I$LBL = 520) AND (KUDA_ID = 906)) THEN
                    BEGIN
                        SELECT V1, V6, V4, V5
                        FROM D_12_LIST_GET_SCHOOLAR(:SCHOLAR_ID, :MOVE_ID, :I$USER_ID, 1)
                        INTO :V1, :V3, :V4, :V5;
                        IF (ROW_COUNT > 0) THEN SUSPEND;
                    END
                    ELSE
                    IF ((I$LBL = 530) AND
                        (((KUDA_ID <> 904) AND
                        (KUDA_ID <> 905) AND
                        (KUDA_ID <> 906)) OR (KUDA_ID IS NULL))) THEN
                    BEGIN
                        SELECT V1, V6, V4, V5
                        FROM D_12_LIST_GET_SCHOOLAR(:SCHOLAR_ID, :MOVE_ID, :I$USER_ID, 1)
                        INTO :V1, :V3, :V4, :V5;
                        IF (ROW_COUNT > 0) THEN SUSPEND;
                    END
                END
                ELSE
                IF ((I$LBL IN (600, 610, 620, 630)) AND
                    (STAGE_ID BETWEEN BEGIN_STAGE2 AND FINAL_STAGE2)) THEN
                BEGIN
                    IF ((I$LBL = 600) AND (KUDA_ID = 904)) THEN
                    BEGIN
                        SELECT V1, V6, V4, V5
                        FROM D_12_LIST_GET_SCHOOLAR(:SCHOLAR_ID, :MOVE_ID, :I$USER_ID, 1)
                        INTO :V1, :V3, :V4, :V5;
                        IF (ROW_COUNT > 0) THEN SUSPEND;
                    END
                    ELSE
                    IF ((I$LBL = 610) AND (KUDA_ID = 905)) THEN
                    BEGIN
                        SELECT V1, V6, V4, V5
                        FROM D_12_LIST_GET_SCHOOLAR(:SCHOLAR_ID, :MOVE_ID, :I$USER_ID, 1)
                        INTO :V1, :V3, :V4, :V5;
                        IF (ROW_COUNT > 0) THEN SUSPEND;
                    END
                    ELSE
                    IF ((I$LBL = 620) AND (KUDA_ID = 906)) THEN
                    BEGIN
                        SELECT V1, V6, V4, V5
                        FROM D_12_LIST_GET_SCHOOLAR(:SCHOLAR_ID, :MOVE_ID, :I$USER_ID, 1)
                        INTO :V1, :V3, :V4, :V5;
                        IF (ROW_COUNT > 0) THEN SUSPEND;
                    END
                    ELSE
                    IF ((I$LBL = 630) AND
                        (((KUDA_ID <> 904) AND
                        (KUDA_ID <> 905) AND
                        (KUDA_ID <> 906)) OR (KUDA_ID IS NULL))) THEN
                    BEGIN
                        SELECT V1, V6, V4, V5
                        FROM D_12_LIST_GET_SCHOOLAR(:SCHOLAR_ID, :MOVE_ID, :I$USER_ID, 1)
                        INTO :V1, :V3, :V4, :V5;
                        IF (ROW_COUNT > 0) THEN SUSPEND;
                    END
                END
                ELSE
                IF ((I$LBL IN (700, 710, 720, 730)) AND
                    (STAGE_ID BETWEEN BEGIN_STAGE3 AND FINAL_STAGE3)) THEN
                BEGIN
                    IF ((I$LBL = 700) AND (KUDA_ID = 904)) THEN
                    BEGIN
                        SELECT V1, V6, V4, V5
                        FROM D_12_LIST_GET_SCHOOLAR(:SCHOLAR_ID, :MOVE_ID, :I$USER_ID, 1)
                        INTO :V1, :V3, :V4, :V5;
                        IF (ROW_COUNT > 0) THEN SUSPEND;
                    END
                    ELSE
                    IF ((I$LBL = 710) AND (KUDA_ID = 905)) THEN
                    BEGIN
                        SELECT V1, V6, V4, V5
                        FROM D_12_LIST_GET_SCHOOLAR(:SCHOLAR_ID, :MOVE_ID, :I$USER_ID, 1)
                        INTO :V1, :V3, :V4, :V5;
                        IF (ROW_COUNT > 0) THEN SUSPEND;
                    END
                    ELSE
                    IF ((I$LBL = 720) AND (KUDA_ID = 906)) THEN
                    BEGIN
                        SELECT V1, V6, V4, V5
                        FROM D_12_LIST_GET_SCHOOLAR(:SCHOLAR_ID, :MOVE_ID, :I$USER_ID, 1)
                        INTO :V1, :V3, :V4, :V5;
                        IF (ROW_COUNT > 0) THEN SUSPEND;
                    END
                    ELSE
                    IF ((I$LBL = 730) AND
                        (((KUDA_ID <> 904) AND
                        (KUDA_ID <> 905) AND
                        (KUDA_ID <> 906)) OR (KUDA_ID IS NULL))) THEN
                    BEGIN
                        SELECT V1, V6, V4, V5
                        FROM D_12_LIST_GET_SCHOOLAR(:SCHOLAR_ID, :MOVE_ID, :I$USER_ID, 1)
                        INTO :V1, :V3, :V4, :V5;
                        IF (ROW_COUNT > 0) THEN SUSPEND;
                    END
                END
            END
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE D_12_LIST_GET_SCHOOLAR (
    I$SCHOLAR_ID BIGINT,
    I$MOVE_ID BIGINT,
    I$USER_ID BIGINT,
    I$MT SMALLINT = 0)
RETURNS (
    V1 VARCHAR(4000),
    V2 VARCHAR(400),
    V3 VARCHAR(4000),
    V4 VARCHAR(100),
    V5 VARCHAR(400),
    V6 VARCHAR(4000))
AS
declare variable S varchar(4000);
declare variable LANG_CODE varchar(2);
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :LANG_CODE;

    V1 = '';
    V2 = '';
    V3 = '';
    V4 = '';
    V5 = '';
    V6 = '';

    S = '';
    SELECT V.VAL FROM VALS V WHERE V.PARAM_ID = 55 AND V.OBJ_ID = :I$SCHOLAR_ID AND V.IS_DEL = 0 INTO :S;
    V1 = S;

    S = '';
    SELECT V.VAL FROM VALS V WHERE V.PARAM_ID = 56 AND V.OBJ_ID = :I$SCHOLAR_ID AND V.IS_DEL = 0 INTO :S;
    IF (S <> '') THEN V1 = V1 || ' ' || S;

    S = '';
    SELECT V.VAL FROM VALS V WHERE V.PARAM_ID = 57 AND V.OBJ_ID = :I$SCHOLAR_ID AND V.IS_DEL = 0 INTO :S;
    IF (S <> '') THEN V1 = V1 || ' ' || S;

    S = '';
    SELECT V FROM VAL_GET(:I$SCHOLAR_ID, 89) INTO :S;
    IF (S <> '') THEN V1 = V1 || ', ' || S;

    SELECT V.VAL FROM VALS V WHERE V.PARAM_ID = 117 AND V.OBJ_ID = :I$SCHOLAR_ID AND V.IS_DEL = 0 INTO :V3;

    SELECT FIRST 1 :V3 || ', ' || R.VAL || ' ' || RW.WORD
    FROM VALL V
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V.LISTVAL_ID
    LEFT JOIN RES_GET(LV.RES_ID,  :LANG_CODE) R ON 1=1
    JOIN REPORT_WORDS RW ON RW.ID = 29
    WHERE V.PARAM_ID = 1345 AND V.OBJ_ID = :I$SCHOLAR_ID AND V.IS_DEL = 0
    INTO :V3;

    SELECT M.NAME_IN, IIF(:I$MT = 0, M.DATE_IN, M.DATE_OUT), IIF(:I$MT = 0, M.ORDER_NUM_IN, M.ORDER_NUM_OUT), IIF(:I$MT = 0, M.ORDER_DATE_IN, M.ORDER_DATE_OUT)
    FROM PERSON_MOVEMENTS M
    WHERE M.OBJ_ID = :I$MOVE_ID
    INTO :V2, :V4, :V5, :S;

    IF (S <> '') THEN V5 = V5 || ' от ' || S;

    SELECT V.VAL FROM VALS V WHERE V.PARAM_ID = 161 AND V.OBJ_ID = :I$SCHOLAR_ID AND V.IS_DEL = 0 INTO :V6;

    IF (V6 = '') THEN
    BEGIN
        SELECT V FROM VAL_GET(:I$SCHOLAR_ID, 105) INTO :V6;
    END

    SELECT FIRST 1 :V6 || ', ' || R.VAL || ' ' || RW.WORD
    FROM VALL V
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V.LISTVAL_ID
    LEFT JOIN RES_GET(LV.RES_ID,  :LANG_CODE) R ON 1=1
    JOIN REPORT_WORDS RW ON RW.ID = 29
    WHERE V.PARAM_ID = 1346 AND V.OBJ_ID = :I$SCHOLAR_ID AND V.IS_DEL = 0
    INTO :V6;

    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE D_12_LIST_SUMM (
    I$OBJ_ID BIGINT,
    I$DT1 DATE,
    I$DT2 DATE,
    LBL INTEGER)
RETURNS (
    CS INTEGER)
AS
declare variable SCHOOL_ID bigint;
declare variable SCHOLAR_ID bigint;
declare variable MOVE_ID bigint;
declare variable STAGE_ID bigint;
declare variable MOVE_DATE date;
declare variable BEGIN_STAGE1 bigint;
declare variable FINAL_STAGE1 bigint;
declare variable BEGIN_STAGE2 bigint;
declare variable FINAL_STAGE2 bigint;
declare variable BEGIN_STAGE3 bigint;
declare variable FINAL_STAGE3 bigint;
declare variable PARENT_TYPE_ID bigint;
declare variable HAS_ZERO smallint;
BEGIN
    SCHOOL_ID = :I$OBJ_ID;
    CS = 0;

    SELECT BEGIN_STAGE1, FINAL_STAGE1, BEGIN_STAGE2, FINAL_STAGE2, BEGIN_STAGE3, FINAL_STAGE3, HAS_ZERO
    FROM D_12_ADD_GET_STAGES(:I$OBJ_ID)
    INTO :BEGIN_STAGE1, :FINAL_STAGE1, :BEGIN_STAGE2, :FINAL_STAGE2, :BEGIN_STAGE3, :FINAL_STAGE3, :HAS_ZERO;

    IF (ROW_COUNT = 0) THEN EXIT;

    FOR
        SELECT L10.OBJ_ID, 9
        FROM LINKS L7
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
        JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        WHERE L7.PARENT_ID = :SCHOOL_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL

        UNION

        SELECT L10.OBJ_ID, L81.OBJ_TYPE_ID
        FROM LINKS L78
        JOIN LINKS L81 ON L81.PARENT_ID = L78.OBJ_ID AND L81.OBJ_TYPE_ID IN (81, 82, 83) AND L81.DATE_DEL IS NULL
        JOIN LINKS L10 ON L10.PARENT_ID = L81.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        WHERE L78.PARENT_ID = :SCHOOL_ID AND L78.OBJ_TYPE_ID = 78 AND L78.DATE_DEL IS NULL

        INTO :SCHOLAR_ID, :PARENT_TYPE_ID
    DO
    BEGIN
        -- Прибывшие
        IF (LBL IN (140, 240, 340, 400)) THEN
        BEGIN
            MOVE_DATE = NULL;
            MOVE_ID = NULL;
            STAGE_ID = NULL;

            SELECT FIRST 1 M.OBJ_ID, M.DATE_IN, M.STAGE_ID
            FROM PERSON_MOVEMENTS M
            JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
            WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :SCHOLAR_ID AND M.DATE_IN >= :I$DT1 AND M.DATE_IN <= :I$DT2 AND M.REASON_IN = 806
            ORDER BY M.DATE_IN DESC
            INTO :MOVE_ID, :MOVE_DATE, :STAGE_ID;

            IF (MOVE_ID IS NOT NULL) THEN
            BEGIN
                IF ((LBL = 140) AND ((STAGE_ID BETWEEN BEGIN_STAGE1 AND FINAL_STAGE1) OR (HAS_ZERO = 1 AND STAGE_ID = 12765))) THEN
                BEGIN
                    CS = CS + 1;
                END
                ELSE IF ((LBL = 240) AND (STAGE_ID BETWEEN BEGIN_STAGE2 AND FINAL_STAGE2)) THEN
                BEGIN
                    CS = CS + 1;
                END
                ELSE IF ((LBL = 340) AND (STAGE_ID BETWEEN BEGIN_STAGE3 AND FINAL_STAGE3)) THEN
                BEGIN
                    CS = CS + 1;
                END
                ELSE
                IF ((LBL = 400) AND
                    (((STAGE_ID BETWEEN BEGIN_STAGE1 AND FINAL_STAGE3) AND (FINAL_STAGE3 IS NOT NULL)) OR
                     ((STAGE_ID BETWEEN BEGIN_STAGE1 AND FINAL_STAGE2) AND (FINAL_STAGE2 IS NOT NULL)) OR
                     (((STAGE_ID BETWEEN BEGIN_STAGE1 AND FINAL_STAGE1) OR (HAS_ZERO = 1 AND STAGE_ID = 12765)) AND (FINAL_STAGE1 IS NOT NULL))
                    )) THEN
                BEGIN
                    CS = CS + 1;
                END
            END
        END

        -- Выбывшие
        IF (LBL IN (540, 640, 740, 800)) THEN
        BEGIN
            MOVE_DATE = NULL;
            MOVE_ID = NULL;
            STAGE_ID = NULL;

            SELECT FIRST 1 M.OBJ_ID, M.DATE_OUT, M.STAGE_ID
            FROM PERSON_MOVEMENTS M
            JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
            WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :SCHOLAR_ID AND M.DATE_OUT >= :I$DT1 AND M.DATE_OUT <= :I$DT2 AND ((M.REASON_OUT = 811) OR ((:PARENT_TYPE_ID <> 83) AND (M.REASON_OUT = 812)))
            ORDER BY M.DATE_OUT DESC
            INTO :MOVE_ID, :MOVE_DATE, :STAGE_ID;

            IF (MOVE_ID IS NOT NULL) THEN
            BEGIN
                IF ((LBL = 540) AND ((STAGE_ID BETWEEN BEGIN_STAGE1 AND FINAL_STAGE1) OR (HAS_ZERO = 1 AND STAGE_ID = 12765))) THEN
                BEGIN
                    CS = CS + 1;
                END
                ELSE IF ((LBL = 640) AND (STAGE_ID BETWEEN BEGIN_STAGE2 AND FINAL_STAGE2)) THEN
                BEGIN
                    CS = CS + 1;
                END
                ELSE IF ((LBL = 740) AND (STAGE_ID BETWEEN BEGIN_STAGE3 AND FINAL_STAGE3)) THEN
                BEGIN
                    CS = CS + 1;
                END
                ELSE
                IF ((LBL = 800) AND
                    (((STAGE_ID BETWEEN BEGIN_STAGE1 AND FINAL_STAGE3) AND (FINAL_STAGE3 IS NOT NULL)) OR
                     ((STAGE_ID BETWEEN BEGIN_STAGE1 AND FINAL_STAGE2) AND (FINAL_STAGE2 IS NOT NULL)) OR
                     (((STAGE_ID BETWEEN BEGIN_STAGE1 AND FINAL_STAGE1) OR (HAS_ZERO = 1 AND STAGE_ID = 12765)) AND (FINAL_STAGE1 IS NOT NULL))
                    )) THEN
                BEGIN
                    CS = CS + 1;
                END
            END
        END
    END

    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE D_12_MAIN_CALC_DISTR (
    I$OBJ_ID BIGINT,
    DT1 DATE,
    DT2 DATE)
RETURNS (
    N CHAR(1))
AS
declare variable SCHOOL_ID bigint;
declare variable IS_SCHOOL_NE_CORRECT smallint = 1;
BEGIN
    DELETE FROM REPORT_D12;

    FOR
        SELECT L2.OBJ_ID
        FROM LINKS L2
        WHERE L2.PARENT_ID = :I$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
        ORDER BY L2.OBJ_ID DESC
        INTO :SCHOOL_ID
    DO
    BEGIN
        IS_SCHOOL_NE_CORRECT = 1;

        SELECT FIRST 1 0
        FROM VALL V
        WHERE V.PARAM_ID = 10 AND V.OBJ_ID = :SCHOOL_ID AND V.IS_DEL = 0 AND V.LISTVAL_ID IN (979,980,985,986,2216)
        INTO :IS_SCHOOL_NE_CORRECT;

        IF (IS_SCHOOL_NE_CORRECT = 1) THEN
        BEGIN
            EXECUTE PROCEDURE D_12_ADD_INSERT_MOVEMENT(:SCHOOL_ID);
            EXECUTE PROCEDURE D_12_MAIN_INSERT_ROWS_DISTR(:SCHOOL_ID, :DT1, :DT2);
        END
    END

    N = ' ';

    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE D_12_MAIN_CALC_OU (
    I$OBJ_ID BIGINT,
    DT1 DATE,
    DT2 DATE)
RETURNS (
    N CHAR(1))
AS
DECLARE VARIABLE SCHOOL_ID BIGINT;
DECLARE VARIABLE KEY_LEVEL VARCHAR(1);
BEGIN
    SCHOOL_ID = I$OBJ_ID;

    SELECT K.KEY_VAL
    FROM KEYS K
    WHERE K.KEY_CODE = 'LEVEL'
    INTO :KEY_LEVEL;

    DELETE FROM REPORT_D12;

    IF (KEY_LEVEL = '1') THEN
    BEGIN
        EXECUTE PROCEDURE D_12_MAIN_INSERT_ROWS(:SCHOOL_ID, :DT1, :DT2);
    END
    ELSE
    BEGIN
        EXECUTE PROCEDURE D_12_ADD_INSERT_MOVEMENT(:SCHOOL_ID);
        EXECUTE PROCEDURE D_12_MAIN_INSERT_ROWS_DISTR(:SCHOOL_ID, :DT1, :DT2);
    END

    N = ' ';

    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE D_12_MAIN_CALC_REGION (
    I$OBJ_ID BIGINT,
    DT1 DATE,
    DT2 DATE = NULL,
    I$C1 VARCHAR(1000) = NULL,
    I$C2 VARCHAR(1000) = NULL,
    I$C3 VARCHAR(1000) = NULL)
RETURNS (
    N CHAR(1))
AS
DECLARE VARIABLE SCHOOL_ID BIGINT;
DECLARE VARIABLE IS_SCHOOL_NE_CORRECT SMALLINT = 1;
DECLARE VARIABLE V$POD_NAME VARCHAR(1000);
DECLARE VARIABLE V$OPF_ID BIGINT;
DECLARE VARIABLE V$STAGE_ID BIGINT;
DECLARE VARIABLE NUM BIGINT;
BEGIN
    DELETE FROM REPORT_D12 WHERE 1=1;

    IF (:DT2 IS NULL) THEN
    BEGIN
        -- контингент на дату, фильтр по подчинению, либо default
        BEGIN
        -- если передали listvalue_id, то найдем текст к нему
          NUM = I$C1;
          SELECT VAL FROM LISTVALS_LIST(166) WHERE IS_DEL = 0 AND LISTVAL_ID = :NUM INTO :V$POD_NAME;
          -- если сразу передали текст
          WHEN ANY DO V$POD_NAME = IIF(I$C1 IS NULL OR I$C1 IN ('', 'Да'), NULL, I$C1);
        END

        -- включать или не включать частные ОУ
        IF(I$C2 = 'Нет' OR I$C2 = '3') THEN V$OPF_ID = 5404;

        -- контингент по параллели на дату, код параллели
        BEGIN
          V$STAGE_ID = I$C3;
          WHEN ANY DO SELECT LISTVAL_ID FROM LISTVALS_LIST(25) WHERE VAL = :I$C3 INTO :V$STAGE_ID;
        END
    END

    FOR
        SELECT L2.OBJ_ID
        FROM LINKS L111
        JOIN LINKS L2 ON L2.PARENT_ID =  L111.OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
        LEFT JOIN VALL V8 ON V8.OBJ_ID = L2.OBJ_ID AND V8.PARAM_ID = 8 AND V8.IS_DEL = 0
        LEFT JOIN VALS V6 ON V6.OBJ_ID = L2.OBJ_ID AND V6.PARAM_ID = 6 AND V6.IS_DEL = 0
        WHERE L111.PARENT_ID = :I$OBJ_ID AND L111.OBJ_TYPE_ID = 111 AND L111.DATE_DEL IS NULL
          AND (:V$POD_NAME IS NULL OR V6.VAL = :V$POD_NAME)
          AND (:V$OPF_ID IS NULL OR V8.LISTVAL_ID <> :V$OPF_ID)

        UNION

        SELECT L2.OBJ_ID
        FROM LINKS L2
        LEFT JOIN VALL V8 ON V8.OBJ_ID = L2.OBJ_ID AND V8.PARAM_ID = 8 AND V8.IS_DEL = 0
        LEFT JOIN VALS V6 ON V6.OBJ_ID = L2.OBJ_ID AND V6.PARAM_ID = 6 AND V6.IS_DEL = 0
        WHERE L2.PARENT_ID = :I$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
          AND (:V$POD_NAME IS NULL OR V6.VAL = :V$POD_NAME)
          AND (:V$OPF_ID IS NULL OR V8.LISTVAL_ID <> :V$OPF_ID)
        ORDER BY 1 DESC

        INTO :SCHOOL_ID
    DO
    BEGIN
        IS_SCHOOL_NE_CORRECT = 1;

        IF (DT2 IS NOT NULL) THEN
        BEGIN
            SELECT FIRST 1 0
            FROM VALL V
            WHERE V.PARAM_ID = 10 AND V.OBJ_ID = :SCHOOL_ID AND V.IS_DEL = 0 AND V.LISTVAL_ID IN (979,980,985,986,2216)
            INTO :IS_SCHOOL_NE_CORRECT;
        END

        IF (IS_SCHOOL_NE_CORRECT = 1) THEN
        BEGIN
            EXECUTE PROCEDURE D_12_ADD_INSERT_MOVEMENT(:SCHOOL_ID);
            IF (DT2 IS NULL) THEN
            BEGIN
                EXECUTE PROCEDURE SCHOLAR_CNT_DISTR_INS(:SCHOOL_ID, :DT1, :V$STAGE_ID);
            END
            ELSE
            BEGIN
                EXECUTE PROCEDURE D_12_MAIN_INSERT_ROWS_DISTR(:SCHOOL_ID, :DT1, :DT2);
            END
        END
    END

    N = ' ';

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE D_12_MAIN_GET_LBL (
    LBL INTEGER)
RETURNS (
    C1 INTEGER,
    C2 INTEGER,
    C3 INTEGER,
    CS INTEGER)
AS
BEGIN
    C1 = 0;
    C2 = 0;
    C3 = 0;
    CS = 0;

    SELECT SUM(C1), SUM(C2), SUM(C3)
    FROM REPORT_D12
    WHERE ROW_NUM = :LBL
    INTO :C1, :C2, :C3;

    CS = C1 + C2 + C3;

    IF (C1 = 0) THEN C1 = NULL;
    IF (C2 = 0) THEN C2 = NULL;
    IF (C3 = 0) THEN C3 = NULL;
    IF (CS = 0) THEN CS = NULL;

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE D_12_MAIN_INSERT_ROW (
    SCHOOL_ID BIGINT,
    SCHOLAR_ID BIGINT,
    ROW_NUM INTEGER,
    STAGE_ID BIGINT)
AS
declare variable C1 integer;
declare variable C2 integer;
declare variable C3 integer;
BEGIN

    C1 = 0;
    C2 = 0;
    C3 = 0;

    IF (STAGE_ID IN (12765, 37, 38, 39, 40)) THEN
    BEGIN
        C1 = 1;
    END
    ELSE
    IF (STAGE_ID IN (41, 42, 43, 44, 45)) THEN
    BEGIN
        C2 = 1;
    END
    ELSE
    IF (STAGE_ID IN (46, 47, 48)) THEN
    BEGIN
        C3 = 1;
    END

    INSERT INTO REPORT_D12 (SCHOOL_ID, SCHOLAR_ID, ROW_NUM, C1, C2, C3)
    VALUES (:SCHOOL_ID, :SCHOLAR_ID, :ROW_NUM, :C1, :C2, :C3);

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE D_12_MAIN_INSERT_ROWS (
    I$OBJ_ID BIGINT,
    DT1 DATE,
    DT2 DATE)
AS
declare variable SCHOOL_ID bigint;
declare variable SCHOLAR_ID bigint;
declare variable STAGE_ID bigint;
declare variable CLASS_TYPE bigint;
declare variable IS_CORRECT smallint;
declare variable KUDA_ID bigint;
declare variable KUDA_TYPE_ID bigint;
declare variable MOVE_DATE date;
declare variable V$M1 bigint;
declare variable V$M2 bigint;
BEGIN
    SCHOOL_ID = I$OBJ_ID;

    -- Выбираем всех учеников, которые были в школе указанный период
    I$OBJ_ID = I$OBJ_ID / 1000000000;
    V$M1 = I$OBJ_ID * 1000000000;
    V$M2 = (I$OBJ_ID + 1) * 1000000000;

    FOR
        SELECT DISTINCT M.PERSON_ID
        FROM PERSON_MOVEMENTS M
        JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
        WHERE M.DATE_DEL IS NULL AND M.DATE_IN <= :DT2 AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :DT1) AND M.OBJ_ID >= :V$M1 AND M.OBJ_ID < :V$M2
        INTO :SCHOLAR_ID
    DO
    BEGIN
        MOVE_DATE = NULL;
        STAGE_ID = NULL;
        CLASS_TYPE = NULL;

        SELECT FIRST 1 M.STAGE_ID, M.TYPE_IN
        FROM PERSON_MOVEMENTS M
        JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
        WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :SCHOLAR_ID AND M.DATE_IN <= :DT2 AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :DT1)
        ORDER BY M.DATE_OUT DESC
        INTO :STAGE_ID, :CLASS_TYPE;

        IS_CORRECT = 1;
        IF (CLASS_TYPE > 197) THEN IS_CORRECT = 0;

        IF (STAGE_ID IS NOT NULL AND IS_CORRECT = 1) THEN
        BEGIN

            KUDA_ID = NULL;

            SELECT FIRST 1 V105.LISTVAL_ID
            FROM VALL V105
            WHERE V105.PARAM_ID = 105 AND V105.OBJ_ID = :SCHOLAR_ID AND V105.IS_DEL = 0
            INTO :KUDA_ID;

            IF (KUDA_ID IS NOT NULL) THEN
            BEGIN
                EXECUTE PROCEDURE D_12_MAIN_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 1, :STAGE_ID);
            END

            KUDA_TYPE_ID = NULL;

            SELECT FIRST 1 V107.LISTVAL_ID
            FROM VALL V107
            WHERE V107.PARAM_ID = 107 AND V107.OBJ_ID = :SCHOLAR_ID AND V107.IS_DEL = 0
            INTO :KUDA_TYPE_ID;

            IF (KUDA_ID IN (904, 905, 906, 907, 3143)) THEN
            BEGIN
                IF ((KUDA_TYPE_ID IS NULL) OR (KUDA_TYPE_ID NOT IN (965, 966, 967, 979, 980, 985, 986, 1010, 1011, 1014, 1016, 2216, 2219, 2220, 2222, 2223, 2224, 2225))) THEN
                BEGIN
                    EXECUTE PROCEDURE D_12_MAIN_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 2, :STAGE_ID);
                END
            END

            IF (KUDA_ID IN (904, 905, 906, 907, 3143)) THEN
            BEGIN
                IF (KUDA_TYPE_ID IN (2216, 979, 980, 985, 986)) THEN
                BEGIN
                    EXECUTE PROCEDURE D_12_MAIN_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 3, :STAGE_ID);
                END
            END

            IF (KUDA_ID IN (904, 905, 906, 907, 3143)) THEN
            BEGIN
                IF (KUDA_TYPE_ID IN (965, 966, 967)) THEN
                BEGIN
                    EXECUTE PROCEDURE D_12_MAIN_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 4, :STAGE_ID);
                END
            END

            IF (KUDA_ID IN (904, 905, 906, 907, 3143)) THEN
            BEGIN
                IF (KUDA_TYPE_ID IN (1014, 1016)) THEN
                BEGIN
                    EXECUTE PROCEDURE D_12_MAIN_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 5, :STAGE_ID);
                END
            END

            IF (KUDA_ID IN (904, 905, 906, 907, 3143)) THEN
            BEGIN
                IF (KUDA_TYPE_ID IN (1010, 1011)) THEN
                BEGIN
                    EXECUTE PROCEDURE D_12_MAIN_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 6, :STAGE_ID);
                END
            END

            -- IF ((LBL = 7) AND (KUDA_ID IN (904,905,906,907))) THEN
            -- IF ((LBL = 8) AND (KUDA_ID IN (904,905,906,907))) THEN

            IF (KUDA_ID IN (914, 915)) THEN
            BEGIN
                EXECUTE PROCEDURE D_12_MAIN_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 9, :STAGE_ID);
            END

            IF (KUDA_ID IN (910)) THEN
            BEGIN
                EXECUTE PROCEDURE D_12_MAIN_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 10, :STAGE_ID);
            END

            IF (KUDA_ID IN (904, 905, 906, 907)) THEN
            BEGIN
                IF (KUDA_TYPE_ID IN (2219, 2220, 2222, 2223, 2224, 2225)) THEN
                BEGIN
                    EXECUTE PROCEDURE D_12_MAIN_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 11, :STAGE_ID);
                END
            END

            IF (KUDA_ID IN (908)) THEN
            BEGIN
                EXECUTE PROCEDURE D_12_MAIN_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 12, :STAGE_ID);
            END

            IF (KUDA_ID IN (909)) THEN
            BEGIN
                EXECUTE PROCEDURE D_12_MAIN_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 13, :STAGE_ID);
            END

            IF (KUDA_ID IN (916)) THEN
            BEGIN
                EXECUTE PROCEDURE D_12_MAIN_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 14, :STAGE_ID);
            END

            IF (KUDA_ID IN (911, 912, 913, 11200, 917)) THEN
            BEGIN
                EXECUTE PROCEDURE D_12_MAIN_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 16, :STAGE_ID);
            END

        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE D_12_MAIN_INSERT_ROWS_DISTR (
    I$OBJ_ID BIGINT,
    DT1 DATE,
    DT2 DATE)
AS
declare variable SCHOOL_ID bigint;
declare variable SCHOLAR_ID bigint;
declare variable SCHOLAR_TEMP_ID bigint;
declare variable STAGE_ID bigint;
declare variable CLASS_TYPE bigint;
declare variable IS_CORRECT smallint;
declare variable KUDA_ID bigint;
declare variable KUDA_TYPE_ID bigint;
declare variable MOVE_DATE date;
BEGIN
    SCHOOL_ID = I$OBJ_ID;
    SCHOLAR_TEMP_ID = 0;

    FOR
        SELECT SCHOLAR_ID, DATE_OUT, CLASS_TYPE, STAGE_ID
        FROM REPORT_D12_ADD
        WHERE SCHOOL_ID = :SCHOOL_ID AND DATE_OUT >= :DT1 AND DATE_OUT <= :DT2 AND REASON_OUT = 811
        ORDER BY SCHOOL_ID DESC, SCHOLAR_ID DESC, DATE_OUT DESC
        INTO :SCHOLAR_ID, :MOVE_DATE, :CLASS_TYPE, :STAGE_ID
    DO
    BEGIN
        IF (SCHOLAR_TEMP_ID <> SCHOLAR_ID) THEN
        BEGIN
            SCHOLAR_TEMP_ID = SCHOLAR_ID;

            IS_CORRECT = 1;
            IF (CLASS_TYPE > 197) THEN IS_CORRECT = 0;

            IF ((STAGE_ID IS NOT NULL) AND (IS_CORRECT = 1) AND NOT(STAGE_ID IN (40, 45, 48) AND EXTRACT(MONTH FROM MOVE_DATE) BETWEEN 6 AND 8)) THEN
            BEGIN

                EXECUTE PROCEDURE D_12_MAIN_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 1, :STAGE_ID);

                KUDA_ID = NULL;

                SELECT FIRST 1 V105.LISTVAL_ID
                FROM VALL V105
                WHERE V105.PARAM_ID = 105 AND V105.OBJ_ID = :SCHOLAR_ID AND V105.IS_DEL = 0
                INTO :KUDA_ID;

                KUDA_TYPE_ID = NULL;

                SELECT FIRST 1 V107.LISTVAL_ID
                FROM VALL V107
                WHERE V107.PARAM_ID = 107 AND V107.OBJ_ID = :SCHOLAR_ID AND V107.IS_DEL = 0
                INTO :KUDA_TYPE_ID;

                IF (KUDA_ID IN (904, 905, 906, 907, 3143)) THEN
                BEGIN
                    IF ((KUDA_TYPE_ID IS NULL) OR (KUDA_TYPE_ID NOT IN (965, 966, 967, 979, 980, 985, 986, 1010, 1011, 1014, 1016, 2216, 2219, 2220, 2222, 2223, 2224, 2225))) THEN
                    BEGIN
                        EXECUTE PROCEDURE D_12_MAIN_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 2, :STAGE_ID);
                    END
                END

                IF (KUDA_ID IN (904, 905, 906, 907, 3143)) THEN
                BEGIN
                    IF (KUDA_TYPE_ID IN (2216, 979, 980, 985, 986)) THEN
                    BEGIN
                        EXECUTE PROCEDURE D_12_MAIN_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 3, :STAGE_ID);
                    END
                END

                IF (KUDA_ID IN (904, 905, 906, 907, 3143)) THEN
                BEGIN
                    IF (KUDA_TYPE_ID IN (965, 966, 967)) THEN
                    BEGIN
                        EXECUTE PROCEDURE D_12_MAIN_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 4, :STAGE_ID);
                    END
                END

                IF (KUDA_ID IN (904, 905, 906, 907, 3143)) THEN
                BEGIN
                    IF (KUDA_TYPE_ID IN (1014, 1016)) THEN
                    BEGIN
                        EXECUTE PROCEDURE D_12_MAIN_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 5, :STAGE_ID);
                    END
                END

                IF (KUDA_ID IN (904, 905, 906, 907, 3143)) THEN
                BEGIN
                    IF (KUDA_TYPE_ID IN (1010, 1011)) THEN
                    BEGIN
                        EXECUTE PROCEDURE D_12_MAIN_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 6, :STAGE_ID);
                    END
                END

                -- IF ((LBL = 7) AND (KUDA_ID IN (904,905,906,907))) THEN
                -- IF ((LBL = 8) AND (KUDA_ID IN (904,905,906,907))) THEN

                IF (KUDA_ID IN (914, 915)) THEN
                BEGIN
                    EXECUTE PROCEDURE D_12_MAIN_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 9, :STAGE_ID);
                END

                IF (KUDA_ID IN (910)) THEN
                BEGIN
                    EXECUTE PROCEDURE D_12_MAIN_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 10, :STAGE_ID);
                END

                IF (KUDA_ID IN (904, 905, 906, 907)) THEN
                BEGIN
                    IF (KUDA_TYPE_ID IN (2219, 2220, 2222, 2223, 2224, 2225)) THEN
                    BEGIN
                        EXECUTE PROCEDURE D_12_MAIN_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 11, :STAGE_ID);
                    END
                END

                IF (KUDA_ID IN (908)) THEN
                BEGIN
                    EXECUTE PROCEDURE D_12_MAIN_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 12, :STAGE_ID);
                END

                IF (KUDA_ID IN (909)) THEN
                BEGIN
                    EXECUTE PROCEDURE D_12_MAIN_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 13, :STAGE_ID);
                END

                IF (KUDA_ID IN (916)) THEN
                BEGIN
                    EXECUTE PROCEDURE D_12_MAIN_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 14, :STAGE_ID);
                END

                IF (KUDA_ID IN (911, 912, 913, 11200, 917)) THEN
                BEGIN
                    EXECUTE PROCEDURE D_12_MAIN_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 16, :STAGE_ID);
                END
            END
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE EDITTYPES_LIST RETURNS (
    EDIT_TYPE SMALLINT,
    EDIT_NAME VARCHAR(100),
    EDIT_LEVEL SMALLINT)
AS
BEGIN
    FOR
        SELECT EDIT_TYPE,
               EDIT_NAME,
               EDIT_LEVEL
        FROM EDITTYPES
        INTO   :EDIT_TYPE,
               :EDIT_NAME,
               :EDIT_LEVEL
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE EDUCATION_PROGRAM_DIR_LIST (
    I$OBJ_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    LISTVAL_ID BIGINT,
    PARENT_ID BIGINT,
    VAL VARCHAR(4000),
    VAL_LONG VARCHAR(4000),
    TAG VARCHAR(100),
    "FILTER" VARCHAR(255))
AS
declare variable LANG_CODE varchar(2);
declare variable RES_ID bigint;
declare variable V$TYPE_ID bigint;
declare variable V$EDUCATION_PROGRAM_TYPE_ID bigint;
declare variable V$FILTER varchar(255);
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :LANG_CODE;

    SELECT TYPE_ID FROM OBJECTS WHERE OBJ_ID = :I$OBJ_ID INTO :V$TYPE_ID;

    SELECT I
    FROM VAL_GET(:I$OBJ_ID, IIF(:V$TYPE_ID = 252, 2145, 1593))
    INTO :V$EDUCATION_PROGRAM_TYPE_ID;

    IF(I$OBJ_ID IS NULL) THEN V$FILTER = '';
    ELSE IF (V$EDUCATION_PROGRAM_TYPE_ID = 5336) THEN V$FILTER = 'OO';
    ELSE V$FILTER = 'DO';

    FOR
        SELECT LISTVAL_ID, PARENT_ID, TAG, RES_ID, "FILTER"
        FROM LISTVALS
        WHERE LIST_ID = 22 AND "FILTER" LIKE :V$FILTER || '%' AND IS_DEL = 0
        ORDER BY SORT_ORDER
        INTO :LISTVAL_ID, :PARENT_ID, :TAG, :RES_ID, :"FILTER"
    DO
    BEGIN
        SELECT VAL, VAL_LONG
        FROM RES_GET(:RES_ID, :LANG_CODE)
        INTO :VAL, :VAL_LONG;
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE EDULOAD_APPROVE (
    I$OBJ_ID BIGINT,
    I$STATE_ID BIGINT,
    I$USER_ID BIGINT)
AS
DECLARE VARIABLE V$Y INTEGER;
DECLARE VARIABLE V$CY INTEGER;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$PERSON_ID BIGINT;
DECLARE VARIABLE V$JOB_ID BIGINT;
DECLARE VARIABLE V$ORDER_ID BIGINT;
DECLARE VARIABLE V$ORDER_STATE_ID BIGINT;
DECLARE VARIABLE V$SIGNED_BY BIGINT;
DECLARE VARIABLE V$YEAR_ID BIGINT;
DECLARE VARIABLE V$YEAR_CUR BIGINT;
DECLARE VARIABLE V$PLAN_ID BIGINT;
DECLARE VARIABLE V$STAGE_ID BIGINT;
DECLARE VARIABLE V$SUBJECT_ID BIGINT;
DECLARE VARIABLE V$GROUP_TYPE_ID BIGINT;
DECLARE VARIABLE V$LOAD_VAL FLOAT;
DECLARE VARIABLE V$STREAM SMALLINT;
DECLARE VARIABLE V$CJ_ID BIGINT;
DECLARE VARIABLE V$DT TIMESTAMP;
DECLARE VARIABLE V$TEACHER_ID BIGINT;
DECLARE VARIABLE H_PLAN FLOAT;
DECLARE VARIABLE W_PLAN INTEGER;
DECLARE VARIABLE V$GUP_ID BIGINT;
DECLARE VARIABLE V$GROUP_ID BIGINT;
DECLARE VARIABLE V$PERIOD_ID BIGINT;
DECLARE VARIABLE V$SCHOOL_ID BIGINT;
DECLARE VARIABLE V$LINK_ID BIGINT;
DECLARE VARIABLE V$MOVE_DATE DATE;
DECLARE VARIABLE V$ORDER_DATE DATE;
DECLARE VARIABLE V$ORDER_NUM VARCHAR(200);
DECLARE VARIABLE V$GS_ID BIGINT;
DECLARE VARIABLE M BIGINT;
DECLARE VARIABLE H FLOAT;
DECLARE VARIABLE S VARCHAR(1000);
DECLARE VARIABLE T INTEGER;
DECLARE VARIABLE VI VARCHAR(100);
DECLARE VARIABLE VT1 VARCHAR(100);
DECLARE VARIABLE VT2 VARCHAR(100);
DECLARE VARIABLE VP BIGINT;
begin

  -- Статус могут менять: админ, директор, завуч, кадровик
  IF(NOT EXISTS(
    SELECT FIRST 1 1
    FROM USERS U
    WHERE U.USER_ID = :I$USER_ID AND U.DATE_DEL IS NULL AND U.USER_TYPE IN (1, 5, 6, 10)
  ))
  THEN
    EXCEPTION DATA_ERROR 'У вас нет прав доступа для изменения статуса';

  IF(I$STATE_ID = 11717) THEN EXCEPTION DATA_ERROR 'Статус Не действующий не может быть установлен';

  -- При переводе в архив вообще ничего не надо
  IF(I$STATE_ID = 14261) THEN EXIT;

  -- Связь с приказом хранится в контенте приказа
  SELECT FIRST 1 D.OBJ_ID, D.STATE_ID
  FROM ORDERS D
  WHERE D.DATE_DEL IS NULL AND D.REF_ID = :I$OBJ_ID
  INTO :V$ORDER_ID, :V$ORDER_STATE_ID;

  SELECT V3567.LISTVAL_ID, LV.COST
  FROM VALL V3567
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V3567.LISTVAL_ID
  WHERE V3567.OBJ_ID = :I$OBJ_ID AND V3567.PARAM_ID = 3567 AND V3567.IS_DEL = 0
  INTO :V$YEAR_ID, :V$Y;

  SELECT FIRST 1 L2.OBJ_ID, V1236.LISTVAL_ID, LV.COST
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$SCHOOL_ID, :V$YEAR_CUR, :V$CY;

  -- В проект можно переводить только для текущего или будущего года
  IF(I$STATE_ID = 11716) THEN
  BEGIN
    IF(V$Y < V$CY) THEN EXCEPTION DATA_ERROR 'Архивные Распределения нагрузки в статус проекта вернуть нельзя';

    -- Возвращаем в статус проекта сам приказ
    IF(V$ORDER_STATE_ID = 11715) THEN
    UPDATE ORDERS
    SET STATE_ID = 11716
    WHERE OBJ_ID = :V$ORDER_ID;

    EXIT;
  END

  -- Удаляем возможные старые хвосты
  UPDATE EDULOAD_DATA
  SET DATE_DEL = CURRENT_TIMESTAMP
  WHERE DATE_DEL IS NULL AND PARENT_ID = :I$OBJ_ID AND REF_ID IS NULL;

  -- Сохраняем список активных персон (ФИО) и их активных должностей, в записи с REF_ID, REF_TYPE_ID = NULL
  FOR
    SELECT DISTINCT D.PERSON_ID, C.CAPTION
    FROM EDULOAD_DATA D
    JOIN OBJECTS OBJ ON OBJ.OBJ_ID = D.PERSON_ID AND OBJ.TYPE_ID = 14 -- исключаем вакантную строку = ОУ
    LEFT JOIN OBJECT_CAPTION_GET(D.PERSON_ID) C ON 1 = 1
    WHERE D.DATE_DEL IS NULL AND D.PARENT_ID = :I$OBJ_ID
    ORDER BY 2
    INTO :V$PERSON_ID, :S
  DO
  BEGIN
    V$OBJ_ID = NULL;
    SELECT FIRST 1 D.OBJ_ID
    FROM EDULOAD_DATA D
    WHERE D.PARENT_ID = :I$OBJ_ID AND D.PERSON_ID = :V$PERSON_ID AND D.REF_ID IS NULL
    INTO :V$OBJ_ID;

    V$JOB_ID = NULL;
    SELECT FIRST 1 L15.OBJ_ID
    FROM LINKS L15
    JOIN VALL V72 ON V72.OBJ_ID = L15.OBJ_ID AND V72.PARAM_ID = 72 AND V72.IS_DEL = 0 AND V72.LISTVAL_ID = 934 -- основная
    LEFT JOIN VALD V74 ON V74.PARAM_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
    WHERE L15.PARENT_ID = :V$PERSON_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL AND V74.VAL IS NULL
    INTO :V$JOB_ID;

    IF(V$OBJ_ID IS NULL) THEN
    BEGIN
      INSERT INTO EDULOAD_DATA
      (PARENT_ID, PERSON_ID, GROUP_NAME, PLAN_ID)
      VALUES (:I$OBJ_ID, :V$PERSON_ID, :S, :V$JOB_ID);
    END
    ELSE
    BEGIN
      UPDATE EDULOAD_DATA
      SET DATE_DEL = NULL, GROUP_NAME = :S, PLAN_ID = :V$JOB_ID
      WHERE OBJ_ID = :V$OBJ_ID;
    END
  END

  -- Переводим в архив все старые действующие распределения
  FOR
    SELECT L531.OBJ_ID
    FROM LINKS LP527
    JOIN LINKS L531 ON L531.PARENT_ID = LP527.PARENT_ID AND L531.OBJ_TYPE_ID = 531 AND L531.DATE_DEL IS NULL AND L531.OBJ_ID <> :I$OBJ_ID
    JOIN VALL V3567 ON V3567.OBJ_ID = L531.OBJ_ID AND V3567.PARAM_ID = 3567 AND V3567.IS_DEL = 0 AND V3567.LISTVAL_ID = 11715
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V3567.LISTVAL_ID
    WHERE LP527.OBJ_ID = :I$OBJ_ID AND LP527.PARENT_TYPE_ID = 527 AND LP527.DATE_DEL IS NULL
    ORDER BY 1
    INTO :V$OBJ_ID
  DO
  BEGIN
    UPDATE VALL SET LISTVAL_ID = 14261 WHERE OBJ_ID = :V$OBJ_ID AND PARAM_ID = 3567;
  END

  -- Создаем запись приказа, связка через PARENT_ID
  -- Номер и дата приказа тут не формируются - их запишем отложенно в момент сохранения реквизитов приказа
  -- Сейчас только правило нумерации проверим - специальное значение для номера
  IF(V$ORDER_ID IS NULL) THEN
  BEGIN
    -- Берем директора
    SELECT FIRST 1 D.OBJ_ID
    FROM LINKS L2
    LEFT JOIN R_SPB_POST_DIRECTOR(L2.OBJ_ID, 1) D ON 1 = 1
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :V$SIGNED_BY;

    -- Хоть и указывается статус действующего, все равно добавится как проект - после сохранения номера статус обновим
    SELECT OBJ_ID FROM ORDER_SET(NULL, :I$USER_ID, NULL, 14260, 11715, '01.09.' || :V$Y, 'VALIDATE', '01.09.' || :V$Y, :V$SIGNED_BY, NULL, NULL) INTO :V$ORDER_ID;
    UPDATE ORDERS SET REF_ID = :I$OBJ_ID WHERE OBJ_ID = :V$ORDER_ID;
  END
  ELSE
  BEGIN
    UPDATE ORDERS
    SET STATE_ID = 11715
    WHERE OBJ_ID = :V$ORDER_ID;
  END

  -- Отрабатываем классное руководство и ответственных за кабинеты - только если учебный год = текущему
  IF(V$YEAR_ID = V$YEAR_CUR) THEN EXECUTE PROCEDURE EDULOAD_PROCESS_DEFER(:V$YEAR_CUR);

  -- КУГ нужного года
  SELECT FIRST 1 L481.OBJ_ID
  FROM LINKS L481
  JOIN VALL V3390 ON V3390.OBJ_ID = L481.OBJ_ID AND V3390.PARAM_ID = 3390 AND V3390.IS_DEL = 0 AND V3390.LISTVAL_ID NOT IN (11717, 14261) -- не архивный !
  JOIN VALL V3389 ON V3389.OBJ_ID = L481.OBJ_ID AND V3389.PARAM_ID = 3389 AND V3389.IS_DEL = 0 AND V3389.LISTVAL_ID = :V$YEAR_ID
  WHERE L481.PARENT_ID = :V$SCHOOL_ID AND L481.OBJ_TYPE_ID = 481 AND L481.DATE_DEL IS NULL
  INTO :V$GS_ID;

  -- Отрабатываем журналы - текущий или будущий год (общие и ВД)
  -- ГУП текущие или будущие должны быть созданы заранее - если их нет, журналы не обновятся
  -- Название групп всегда закэшировано в group_name - после перевода года группы пропадут, а название останется
  -- Вакансия кодируется PERSON_ID = ID ОУ (заменяем на null при выборке)
  FOR
    SELECT D.PLAN_ID, D.STAGE_ID, D.REF_ID, D.GROUP_NAME, D.GROUP_TYPE_ID, D.LOAD_VAL, IIF(OBJ.TYPE_ID = 2, NULL, D.PERSON_ID)
    FROM EDULOAD_DATA D
    JOIN OBJECTS OBJ ON OBJ.OBJ_ID = D.PERSON_ID
    WHERE D.DATE_DEL IS NULL AND D.PARENT_ID = :I$OBJ_ID AND D.REF_TYPE_ID = 51
    ORDER BY 1, 2, 3
    INTO :V$PLAN_ID, :V$STAGE_ID, :V$SUBJECT_ID, :S, :V$GROUP_TYPE_ID, :V$LOAD_VAL, :V$PERSON_ID
  DO
  BEGIN
    -- Потоковость предмета обязательно одинаковая по всему УП
    V$STREAM = 0;
    SELECT FIRST 1 PS.IS_STM
    FROM PLAN_SUBJECTS PS
    WHERE PS.DATE_DEL IS NULL AND PS.PLAN_ID = :V$PLAN_ID AND PS.SUBJECT_ID = :V$SUBJECT_ID
    INTO :V$STREAM;

    -- Сколько часов нагрузки по предмету в параллели ?
    H_PLAN = 0;
    W_PLAN = 0;
    SELECT MIN(PL.WEEKS), SUM(PL.LOAD_HOURS)
    FROM PLAN_SUBJECTS PS
    JOIN PLAN_LOADS PL ON PL.DATE_DEL IS NULL AND PL.SUBJECT_ID = PS.OBJ_ID
    JOIN VALL V381 ON V381.OBJ_ID = PL.STAGE_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0 AND V381.LISTVAL_ID = :V$STAGE_ID
    WHERE PS.DATE_DEL IS NULL AND PS.PLAN_ID = :V$PLAN_ID AND PS.SUBJECT_ID = :V$SUBJECT_ID
    INTO :H_PLAN, :W_PLAN;

    -- Ищем ГУП
    V$GUP_ID = NULL;
    SELECT FIRST 1 L256.OBJ_ID, BIN_SHL(1, CAST(LV.COST AS INTEGER))
    FROM LINKS L54
    JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0 AND V381.LISTVAL_ID = :V$STAGE_ID
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V381.LISTVAL_ID
    JOIN LINKS L256 ON L256.PARENT_ID = L54.OBJ_ID AND L256.OBJ_TYPE_ID = 256 AND L256.DATE_DEL IS NULL
    JOIN VALS V2162 ON V2162.OBJ_ID = L54.OBJ_ID AND V2162.PARAM_ID = 2162 AND V2162.IS_DEL = 0 AND UPPER(REPLACE(V2162.SVAL, 'будущий ', '')) = UPPER(:S)
    WHERE L54.PARENT_ID = :V$PLAN_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
    INTO :V$GUP_ID, :M;

    -- На случай скачков туда-сюда корректируем удаление
    -- Пока только для не-потоковых групп, с потоковыми название формируется сложнее
    -- Предполагается что недели в журнале не изменяются в процессе
    -- Что делаем если вдруг часы надо разделять на двух преподавателей в классе ??? Пока всегда ставим часы по УП
    V$CJ_ID = NULL;
    SELECT FIRST 1 J.OBJ_ID, J.DATE_DEL, J.TEACHER_ID, J.HOURS
    FROM CJ2_JOURNAL J
    WHERE J.YEAR_ID = :V$YEAR_ID AND J.SUBJECT_ID = :V$SUBJECT_ID AND J.REF_ID = :V$PLAN_ID AND J.JOURNAL_TYPE = :V$GROUP_TYPE_ID AND UPPER(J.JOURNAL_NAME) = UPPER(:S)
    ORDER BY J.DATE_DEL NULLS FIRST
    INTO :V$CJ_ID, :V$DT, :V$TEACHER_ID, :H;

    IF(V$GUP_ID IS NOT NULL) THEN
    BEGIN
      IF(V$GUP_ID IS NOT NULL) THEN
      BEGIN
        -- Создаем группу переменного состава
        SELECT OBJ_ID, LINK_ID FROM OBJECT_ADD(:V$SCHOOL_ID, 179) INTO :V$GROUP_ID, :V$LINK_ID;
        SELECT 1 FROM VAL_ADD(2927, :V$GROUP_ID, :S) INTO :T;
        -- Раз группа на основе ГУП, то все ученики точно оттуда - сразу фиксируем ссылку
        SELECT 1 FROM VAL_ADD(3370, :V$GROUP_ID, :V$GUP_ID) INTO :T;
        -- Ссылка также фиксируется в EXT_OBJ_ID ддя не-потоковых
        IF(V$STREAM = 0) THEN UPDATE LINKS SET EXT_OBJ_ID = :V$GUP_ID WHERE LINK_ID = :V$LINK_ID;

        -- Стараемся подобрать расписание исходя из номера параллели и этапа
        -- Сразу же конвертируем сетку ОВЗ в сетку журналов
        SELECT FIRST 1 CAST(LV.COST AS INTEGER), LV.PARENT_ID
        FROM LISTVALS LV
        WHERE LV.LISTVAL_ID = :V$STAGE_ID
        INTO :VI, :VP;

        IF(VP = 12941) THEN
        BEGIN
          SELECT FIRST 1 LV2.LISTVAL_ID
          FROM LISTVALS LV1
          JOIN LISTVALS LV2 ON LV2.PARENT_ID = 2141 AND LV2.COST = LV1.COST
          WHERE LV1.LISTVAL_ID = :V$STAGE_ID
          INTO :V$STAGE_ID;
        END

        IF(V$STAGE_ID IN (37, 38, 39, 40)) THEN
        BEGIN
          VT1 = 'НАЧАЛЬН';
          VT2 = 'НОО';
        END
        ELSE IF(V$STAGE_ID IN (41, 42, 43, 44, 45)) THEN
        BEGIN
          VT1 = 'ОСНОВ';
          VT2 = 'ООО';
        END
        ELSE IF(V$STAGE_ID IN (46, 47, 48)) THEN
        BEGIN
          VT1 = 'СРЕДН';
          VT2 = 'СОО';
        END

        -- Периоды
        V$PERIOD_ID = NULL;
        SELECT FIRST 1 L151.OBJ_ID
        -- Просто выбор между четвертями, полугодиями и семестрами
        FROM LINKS L151
        JOIN VALS V1147 ON V1147.OBJ_ID = L151.OBJ_ID AND V1147.PARAM_ID = 1147 AND V1147.IS_DEL = 0
        WHERE L151.PARENT_ID = :V$GS_ID AND L151.OBJ_TYPE_ID = 151 AND L151.DATE_DEL IS NULL AND EXISTS(
          SELECT FIRST 1 1
          FROM LINKS L154
          JOIN VALD V1169 ON V1169.OBJ_ID = L154.OBJ_ID AND V1169.PARAM_ID = 1169 AND V1169.IS_DEL = 0 AND V1169.VAL >= '01.09.' || :V$Y AND V1169.VAL < '01.09.' || (:V$Y + 1)
          JOIN VALL V1170 ON V1170.OBJ_ID = L154.OBJ_ID AND V1170.PARAM_ID = 1170 AND V1170.IS_DEL = 0 AND (
            (:V$STAGE_ID <= 45 AND V1170.LISTVAL_ID IN (12, 13, 14, 15)) OR
            (:V$STAGE_ID IN (46, 47, 48) AND V1170.LISTVAL_ID IN (10, 11)) OR
            (:V$STAGE_ID IN (49, 50, 51, 52, 53, 54, 13145) AND V1170.LISTVAL_ID IN (19, 20))
          )
          WHERE L154.PARENT_ID = L151.OBJ_ID AND L154.OBJ_TYPE_ID = 154 AND L154.DATE_DEL IS NULL
        )
        -- Высший приоритет если период с номером параллели - записано как 1 класс или 1,2,3 классы
        -- Далее по этапу обучения - НОО/ООО/СОО или название этапа
        ORDER BY IIF(POSITION(:VI || ' ' IN V1147.VAL) > 0 OR POSITION(:VI || ',' IN V1147.VAL) > 0 AND POSITION('КЛАСС' IN UPPER(V1147.VAL)) > 0, 0,
          IIF(POSITION(:VT1 IN UPPER(V1147.VAL)) > 0 OR POSITION(:VT2 IN UPPER(V1147.VAL)) > 0, 1, 3))
        INTO :V$PERIOD_ID;

        INSERT INTO CJ2_JOURNAL
        (JOURNAL_TYPE, JOURNAL_NAME, SUBJECT_ID, GRADE_ID, GRADE_TYPE_ID, STAGE_INDEX, STAGE_MASK, TEACHER_ID, WEEKS, HOURS, REF_ID, PERIOD_ID)
        VALUES (:V$GROUP_TYPE_ID, :S, :V$SUBJECT_ID, :V$GROUP_ID, 179, :V$STAGE_ID, :M, :V$PERSON_ID, :H_PLAN, :W_PLAN, :V$PLAN_ID, :V$PERIOD_ID);

        -- Если год = текущему, то добавляем всех учеников ГУП в данную группу
        -- но не в потоковые !

        IF(V$YEAR_CUR = V$YEAR_ID AND V$STREAM = 0) THEN
        BEGIN
          FOR
            SELECT L10.OBJ_ID
            FROM LINKS L10
            WHERE L10.PARENT_ID = :V$GUP_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
            INTO :V$OBJ_ID
          DO
          BEGIN
            V$MOVE_DATE = NULL;
            SELECT FIRST 1 M.DATE_IN, M.ORDER_NUM_IN, M.ORDER_DATE_IN
            FROM PERSON_MOVEMENTS M
            WHERE M.DATE_DEL IS NULL AND M.DATE_OUT IS NULL AND M.PERSON_ID = :V$OBJ_ID AND M.GROUP_ID = :V$GUP_ID
            ORDER BY M.OBJ_ID DESC
            INTO :V$MOVE_DATE, :V$ORDER_NUM, :V$ORDER_DATE;

            IF(V$MOVE_DATE IS NOT NULL) THEN
            BEGIN
              SELECT 1 FROM VARGRP_MOVE_PUPIL(:V$OBJ_ID, :V$GROUP_ID, :V$ORDER_NUM, :V$ORDER_DATE, :V$MOVE_DATE, 0, :I$USER_ID) INTO :T;
            END
          END
        END
      END
    END
    ELSE IF(V$DT IS NOT NULL OR COALESCE(H, 0) <> COALESCE(H_PLAN, 0) OR COALESCE(V$PERSON_ID, 0) <> COALESCE(V$TEACHER_ID, 0)) THEN
    BEGIN
      UPDATE CJ2_JOURNAL
      SET DATE_DEL = NULL, HOURS = :H_PLAN, TEACHER_ID = :V$PERSON_ID
      WHERE OBJ_ID = :V$CJ_ID;
    END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE EDULOAD_GET (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$YEAR_ID BIGINT;
DECLARE VARIABLE V$PYEAR_ID BIGINT;
DECLARE VARIABLE V$STATE_ID BIGINT;
DECLARE VARIABLE V$OU_ID BIGINT;
DECLARE VARIABLE V$DATE1 DATE;
DECLARE VARIABLE V$DATE2 DATE;
DECLARE VARIABLE V$PERSON_ID BIGINT;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$STAGE_ID BIGINT;
DECLARE VARIABLE V$PLAN_ID BIGINT;
DECLARE VARIABLE V$GROUP_TYPE_ID BIGINT;
DECLARE VARIABLE V$REF_ID BIGINT;
DECLARE VARIABLE V$REF_TYPE_ID BIGINT;
DECLARE VARIABLE V$Y INTEGER;
DECLARE VARIABLE V$PY INTEGER;
DECLARE VARIABLE V$SUBJECT_ID BIGINT;
DECLARE VARIABLE S VARCHAR(1000);
DECLARE VARIABLE S2 VARCHAR(1000);
DECLARE VARIABLE S3 VARCHAR(1000);
DECLARE VARIABLE N INTEGER;
DECLARE VARIABLE V$STM SMALLINT;
DECLARE VARIABLE V$STG BIGINT;
DECLARE VARIABLE W FLOAT;
DECLARE VARIABLE R FLOAT;
begin

  -- В статусе проекта данные выбираем из текущего состояния
  -- в статусе действующего - из сохраненного слепка данных

  -- Если на входе указан отрицательный ID, то выбираем данные за предыдущий год от указанного
  -- или за последний год где данные были
  IF(I$OBJ_ID < 0) THEN
  BEGIN
    V$OBJ_ID = -I$OBJ_ID;
    I$OBJ_ID = NULL;
    SELECT FIRST 1 L531.OBJ_ID
    FROM LINKS LP527
    JOIN VALL V3567 ON V3567.OBJ_ID = LP527.OBJ_ID AND V3567.PARAM_ID = 3567 AND V3567.IS_DEL = 0
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V3567.LISTVAL_ID
    JOIN LISTVALS LV2 ON LV2.LIST_ID = LV.LIST_ID AND LV2.IS_DEL = 0 AND LV2.COST <= LV.COST -- !!! Исправить потом
    JOIN LINKS L531 ON L531.PARENT_ID = LP527.PARENT_ID AND L531.OBJ_TYPE_ID = 527 AND L531.DATE_DEL IS NULL
    JOIN VALL V3567G ON V3567G.OBJ_ID = L531.OBJ_ID AND V3567G.PARAM_ID = 3567 AND V3567G.IS_DEL = 0 AND V3567G.LISTVAL_ID = LV2.LISTVAL_ID
    WHERE LP527.OBJ_ID = :V$OBJ_ID AND LP527.PARENT_TYPE_ID = 527 AND LP527.DATE_DEL IS NULL
    ORDER BY LV2.COST DESC
    INTO :I$OBJ_ID;

    IF(I$OBJ_ID IS NULL) THEN
    BEGIN
      TAG_NAME = 'nodata';
      VAL = 1;
      SUSPEND;
      EXIT;
    END
  END

  SELECT LP2.PARENT_ID, V3567.LISTVAL_ID, LV.COST, V3568.LISTVAL_ID, V1236.LISTVAL_ID, PLV.COST
  FROM LINKS LP527
  JOIN LINKS LP2 ON LP2.OBJ_ID = LP527.PARENT_ID AND LP2.PARENT_TYPE_ID = 2 AND LP2.DATE_DEL IS NULL
  JOIN VALL V3567 ON V3567.OBJ_ID = LP527.OBJ_ID AND V3567.PARAM_ID = 3567 AND V3567.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V3567.LISTVAL_ID
  JOIN VALL V3568 ON V3568.OBJ_ID = LP527.OBJ_ID AND V3568.PARAM_ID = 3568 AND V3568.IS_DEL = 0
  JOIN VALL V1236 ON V1236.OBJ_ID = LP2.PARENT_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS PLV ON PLV.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE LP527.OBJ_ID = :I$OBJ_ID AND LP527.PARENT_TYPE_ID = 527 AND LP527.DATE_DEL IS NULL
  INTO :V$OU_ID, :V$YEAR_ID, :V$Y, :V$STATE_ID, :V$PYEAR_ID, :V$PY;

  IF(V$YEAR_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Запись не найдена или была удалена';
  V$DATE1 = '01.09.' || V$Y;
  V$DATE2 = '31.08.' || (V$Y + 1);

  TAG_NAME = 'id';
  VAL = I$OBJ_ID;
  SUSPEND;

  TAG_NAME = 'state_id';
  VAL = V$STATE_ID;
  SUSPEND;

  TAG_NAME = 'year_id';
  VAL = V$YEAR_ID;
  SUSPEND;

  TAG_NAME = 'year';
  VAL = V$Y;
  SUSPEND;

  TAG_NAME = 'persons::json&colon;array';
  VAL = 1;
  SUSPEND;

  IF(V$STATE_ID = 11716) THEN
  BEGIN
    -- Проект
    -- Выбираем всех действующих на данный момент и добавляем к ним уже сохраненных, но утраченных
    FOR
      SELECT DISTINCT L14.OBJ_ID, C.CAPTION, V273.SVAL
      FROM LINKS L14
      JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
      JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0 AND V73.VAL <= :V$DATE2
      LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
      JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
      JOIN VALL V58 ON V58.OBJ_ID = LP13.PARENT_ID AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0
      JOIN LISTVALS LV ON LV.LISTVAL_ID = V58.LISTVAL_ID
        -- руководители всех уровней и педагоги
        AND (LV.TAG = 'U' OR LV.TAG = 'R1' OR LV.TAG = 'R2' OR LV.TAG = 'R3' OR LV."FILTER" = 'U' OR LV."FILTER" = 'R1' OR LV."FILTER" = 'R2' OR LV."FILTER" = 'R3')
      LEFT JOIN OBJECT_CAPTION_GET(L14.OBJ_ID) C ON 1 = 1
      LEFT JOIN VALS V273 ON V273.OBJ_ID = L14.OBJ_ID AND V273.PARAM_ID = 273 AND V273.IS_DEL = 0 -- табельный номер
      WHERE L14.PARENT_ID = :V$OU_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
        AND (V74.VAL IS NULL OR V74.VAL >= :V$DATE1)
      -- UNION
      ORDER BY 2
      INTO :V$PERSON_ID, :S, :S2
    DO
    BEGIN
      TAG_NAME = 'persons:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'persons:r:id';
      VAL = V$PERSON_ID;
      SUSPEND;
      TAG_NAME = 'persons:r:name';
      VAL = S;
      SUSPEND;
      TAG_NAME = 'persons:r:tabnum';
      VAL = S2;
      SUSPEND;

      -- Выбираем данные по основной должности и количество ставок по ней
      S = NULL;
      R = NULL;
      SELECT FIRST 1 COALESCE(V3543.VAL, V66.VAL), V71.VAL
      FROM LINKS L15
      JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0 AND V73.VAL <= :V$DATE2
      LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
      JOIN VALF V71 ON V71.OBJ_ID = L15.OBJ_ID AND V71.PARAM_ID = 71 AND V71.IS_DEL = 0
      JOIN VALL V72 ON V72.OBJ_ID = L15.OBJ_ID AND V72.PARAM_ID = 72 AND V72.IS_DEL = 0 AND V72.LISTVAL_ID = 934 -- основная
      JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
      LEFT JOIN VALS V3543 ON V3543.OBJ_ID = L15.OBJ_ID AND V3543.PARAM_ID = 3543 AND V3543.IS_DEL = 0
      LEFT JOIN VALS V66 ON V66.OBJ_ID = LP13.PARENT_ID AND V66.PARAM_ID = 66 AND V66.IS_DEL = 0
      WHERE L15.PARENT_ID = :V$PERSON_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
        AND (V74.VAL IS NULL OR V74.VAL >= :V$DATE1)
      ORDER BY V73.VAL DESC
      INTO :S, :R;

      TAG_NAME = 'persons:r:job_name';
      VAL = S;
      SUSPEND;
      TAG_NAME = 'persons:r:job_rate';
      VAL = CAST(R AS NUMERIC(18, 2));
      SUSPEND;

      TAG_NAME = 'persons:r:subjects';
      VAL = NULL;
      SELECT LIST(L51.OBJ_ID, ',')
      FROM LINKS L51
      WHERE L51.PARENT_ID = :V$PERSON_ID AND L51.OBJ_TYPE_ID = 51 AND L51.DATE_DEL IS NULL
      INTO :VAL;
      SUSPEND;
    END
    -- Вакантная должность - делаем ссылку на ОУ
    TAG_NAME = 'persons:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'persons:r:id';
    VAL = V$OU_ID;
    SUSPEND;
    TAG_NAME = 'persons:r:name';
    VAL = 'Вакансия';
    SUSPEND;

    -- Учебные коллективы на будущий период
    TAG_NAME = 'grades::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT V.GRADE_ID, V.STAGE_ID_NEW, V.GRADE_NAME_NEW
      FROM YCHANGE_REVIEW_GRADES(NULL) V
      JOIN LISTVALS LV ON LV.LISTVAL_ID = V.STAGE_ID_NEW AND LV.PARENT_ID IN (2141, 12941)
      WHERE V.STAGE_ID_NEW IS NOT NULL
      ORDER BY V.STAGE_COST_NEW, V.GRADE_NAME_NEW
      INTO :V$OBJ_ID, :V$STAGE_ID, :S
    DO
    BEGIN
      TAG_NAME = 'grades:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'grades:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'grades:r:stage_id';
      VAL = V$STAGE_ID;
      SUSPEND;
      TAG_NAME = 'grades:r:name';
      VAL = S;
      SUSPEND;
    END

    -- Действующие учебные коллективы и статусы классного руководства
    TAG_NAME = 'old_grades::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT V.GRADE_ID, V.STAGE_ID_OLD, V.GRADE_NAME_OLD, V53.VAL
      FROM YCHANGE_REVIEW_GRADES(NULL) V
      LEFT JOIN VALR V53 ON V53.OBJ_ID = V.GRADE_ID AND V53.PARAM_ID = 53 AND V53.IS_DEL = 0
      JOIN LISTVALS LV ON LV.LISTVAL_ID = V.STAGE_ID_OLD AND LV.PARENT_ID IN (2141, 12941)
      WHERE V.STAGE_ID_OLD IS NOT NULL
      ORDER BY V.STAGE_COST_OLD, V.GRADE_NAME_OLD
      INTO :V$OBJ_ID, :V$STAGE_ID, :S, :V$REF_ID
    DO
    BEGIN
      TAG_NAME = 'old_grades:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'old_grades:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'old_grades:r:stage_id';
      VAL = V$STAGE_ID;
      SUSPEND;
      TAG_NAME = 'old_grades:r:name';
      VAL = S;
      SUSPEND;
      TAG_NAME = 'old_grades:r:person_id';
      VAL = V$REF_ID;
      SUSPEND;
    END

    -- Помещения
    TAG_NAME = 'rooms::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT L61.OBJ_ID, V421.SVAL || ' - ' || COALESCE(V407.SVAL, V408.SVAL), V1344.VAL
      FROM LINKS L73
      JOIN LINKS L16 ON L16.PARENT_ID = L73.OBJ_ID AND L16.OBJ_TYPE_ID = 16 AND L16.DATE_DEL IS NULL
      JOIN VALS V421 ON V421.OBJ_ID = L16.OBJ_ID AND V421.PARAM_ID = 421 AND V421.IS_DEL = 0
      LEFT JOIN VALD V3164 ON V3164.OBJ_ID = L16.OBJ_ID AND V3164.PARAM_ID = 3164 AND V3164.IS_DEL = 0
      JOIN LINKS L61 ON L61.PARENT_ID = L16.OBJ_ID AND L61.OBJ_TYPE_ID = 61 AND L61.DATE_DEL IS NULL
      LEFT JOIN VALS V407 ON V407.OBJ_ID = L61.OBJ_ID AND V407.PARAM_ID = 407 AND V407.IS_DEL = 0
      JOIN VALS V408 ON V408.OBJ_ID = L61.OBJ_ID AND V408.PARAM_ID = 408 AND V408.IS_DEL = 0
      -- Учебные кабинеты, учебные лаборатории, учебные мастерские, спортивный зал, тренажерный зал
      JOIN VALL V526 ON V526.OBJ_ID = L61.OBJ_ID AND V526.PARAM_ID = 526 AND V526.IS_DEL = 0
      JOIN LISTVALS LV526 ON LV526.LISTVAL_ID = V526.LISTVAL_ID
      LEFT JOIN VALR V1344 ON V1344.OBJ_ID = L61.OBJ_ID AND V1344.PARAM_ID = 1344 AND V1344.IS_DEL = 0
      WHERE L73.PARENT_ID = :V$OU_ID AND L73.OBJ_TYPE_ID = 73 AND L73.DATE_DEL IS NULL AND V3164.VAL IS NULL
        AND (LV526.PARENT_ID = 24 OR V526.LISTVAL_ID IN (1130, 1131, 1146, 1147))
      ORDER BY V421.SVAL, 2
      INTO :V$OBJ_ID, :S, :V$PERSON_ID
    DO
    BEGIN
      TAG_NAME = 'rooms:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'rooms:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'rooms:r:name';
      VAL = S;
      SUSPEND;
      -- Текущий ответственный
      TAG_NAME = 'rooms:r:person_id';
      VAL = V$PERSON_ID;
      SUSPEND;
    END

    -- Предметы - обычные и ВД
    TAG_NAME = 'subjects::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT L51.OBJ_ID, C.CAPTION
      FROM LINKS L51
      LEFT JOIN OBJECT_CAPTION_GET(L51.OBJ_ID) C ON 1 = 1
      WHERE L51.PARENT_ID IN (32771, 32772) AND L51.OBJ_TYPE_ID = 51 AND L51.DATE_DEL IS NULL
      ORDER BY 2
      INTO :V$OBJ_ID, :S
    DO
    BEGIN
      TAG_NAME = 'subjects:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'subjects:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'subjects:r:name';
      VAL = S;
      SUSPEND;
    END

    -- Учебные планы на будущий период
    -- выдаем только с заранее настроенными будущими ГУП, иначе непонятно откуда это все брать
    -- для потоковых групп необходимо создать будущие журналы, для самих ГУП не нужно
    TAG_NAME = 'plans::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      -- Обычные УП
      SELECT DISTINCT L400.OBJ_ID, C.CAPTION, L54.OBJ_ID, V381.LISTVAL_ID, C256.CAPTION, 0
      FROM LINKS L69
      JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
      JOIN VALL V1594 ON V1594.OBJ_ID = L57.OBJ_ID AND V1594.PARAM_ID = 1594 AND V1594.IS_DEL = 0 AND V1594.LISTVAL_ID IN (5339, 5341, 5343)
      JOIN VALI V3115 ON V3115.OBJ_ID = L57.OBJ_ID AND V3115.PARAM_ID = 3115 AND V3115.IS_DEL = 0 AND V3115.VAL = :V$Y
      JOIN LINKS L400 ON L400.PARENT_ID = L57.OBJ_ID AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL
      JOIN VALL V3013 ON V3013.OBJ_ID = L400.OBJ_ID AND V3013.PARAM_ID = 3013 AND V3013.IS_DEL = 0 AND V3013.LISTVAL_ID = 11715 -- действующий УП
      JOIN VALL V3016 ON V3016.OBJ_ID = L400.OBJ_ID AND V3016.PARAM_ID = 3016 AND V3016.IS_DEL = 0 AND V3016.LISTVAL_ID = 5465 -- групповой
      JOIN LINKS L54 ON L54.PARENT_ID = L400.OBJ_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
      JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
      -- В УП ВД просто не должно быть ГУП
      JOIN LINKS L256 ON L256.PARENT_ID = L54.OBJ_ID AND L256.OBJ_TYPE_ID = 256 AND L256.DATE_DEL IS NULL
      LEFT JOIN OBJECT_CAPTION_GET(L400.OBJ_ID) C ON 1 = 1
      LEFT JOIN OBJECT_CAPTION_GET(L256.OBJ_ID) C256 ON 1 = 1
      WHERE L69.PARENT_ID = :V$OU_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL
      UNION
      -- УП ВД - тут ГУП берем сборную солянку из УП той же ОП
      SELECT DISTINCT L400.OBJ_ID, C.CAPTION, L54.OBJ_ID, V381.LISTVAL_ID, C256.CAPTION, 1
      FROM LINKS L69
      JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
      JOIN VALL V1594 ON V1594.OBJ_ID = L57.OBJ_ID AND V1594.PARAM_ID = 1594 AND V1594.IS_DEL = 0 AND V1594.LISTVAL_ID IN (5339, 5341, 5343)
      JOIN VALI V3115 ON V3115.OBJ_ID = L57.OBJ_ID AND V3115.PARAM_ID = 3115 AND V3115.IS_DEL = 0 AND V3115.VAL = :V$Y
      JOIN LINKS L400 ON L400.PARENT_ID = L57.OBJ_ID AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL
      JOIN VALL V3013 ON V3013.OBJ_ID = L400.OBJ_ID AND V3013.PARAM_ID = 3013 AND V3013.IS_DEL = 0 AND V3013.LISTVAL_ID = 11715 -- действующий УП
      JOIN VALL V3022 ON V3022.OBJ_ID = L400.OBJ_ID AND V3022.PARAM_ID = 3022 AND V3022.IS_DEL = 0 AND V3022.LISTVAL_ID = 2 -- ВД
      JOIN LINKS L54 ON L54.PARENT_ID = L400.OBJ_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
      JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
      -- А вот ГУП собираем из общеобра и его этапов, чтобы этапы попадали в этапы УП ВД
      JOIN LINKS L400G ON L400G.PARENT_ID = L57.OBJ_ID AND L400G.OBJ_TYPE_ID = 400 AND L400G.DATE_DEL IS NULL
      JOIN VALL V3013G ON V3013G.OBJ_ID = L400G.OBJ_ID AND V3013G.PARAM_ID = 3013 AND V3013G.IS_DEL = 0 AND V3013G.LISTVAL_ID = 11715 -- действующий УП
      JOIN VALL V3016G ON V3016G.OBJ_ID = L400G.OBJ_ID AND V3016G.PARAM_ID = 3016 AND V3016G.IS_DEL = 0 AND V3016G.LISTVAL_ID = 5465 -- групповой
      JOIN LINKS L54G ON L54G.PARENT_ID = L400G.OBJ_ID AND L54G.OBJ_TYPE_ID = 54 AND L54G.DATE_DEL IS NULL
      JOIN VALL V381G ON V381G.OBJ_ID = L54G.OBJ_ID AND V381G.PARAM_ID = 381 AND V381G.IS_DEL = 0 AND V381G.LISTVAL_ID = V381.LISTVAL_ID
      -- В УП ВД просто не должно быть ГУП
      JOIN LINKS L256 ON L256.PARENT_ID = L54G.OBJ_ID AND L256.OBJ_TYPE_ID = 256 AND L256.DATE_DEL IS NULL
      LEFT JOIN OBJECT_CAPTION_GET(L400.OBJ_ID) C ON 1 = 1
      LEFT JOIN OBJECT_CAPTION_GET(L256.OBJ_ID) C256 ON 1 = 1
      WHERE L69.PARENT_ID = :V$OU_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL
      ORDER BY 6, 2, 3, 4
      INTO :V$PLAN_ID, :S, :V$REF_ID, :V$STAGE_ID, :S2, :V$GROUP_TYPE_ID
    DO
    BEGIN
      S2 = REPLACE(S2, 'будущий ', '');
      FOR
        -- Кроме элективов
        -- Обычные предметы в рамках ГУП
        SELECT PS.GLOBAL_INDEX, PS.SUBJECT_ID, PL.WEEKS, PL.LOAD_HOURS, :S2, 0
        FROM PLAN_SUBJECTS PS
        JOIN PLAN_LOADS PL ON PL.DATE_DEL IS NULL AND PL.SUBJECT_ID = PS.OBJ_ID AND PL.STAGE_ID = :V$REF_ID AND PL.LOAD_HOURS > 0
        WHERE PS.DATE_DEL IS NULL AND PS.IS_STM = 0 AND PS.PLAN_ID = :V$PLAN_ID AND PS.ROW_TYPE = 10
          AND PS.SUBJECT_ID <> 34607
        -- Потоковые предметы только через журналы
        UNION
        SELECT PS.GLOBAL_INDEX, PS.SUBJECT_ID, PL.WEEKS, PL.LOAD_HOURS, REPLACE(J.JOURNAL_NAME, 'будущий ', ''), 1
        FROM PLAN_SUBJECTS PS
        JOIN PLAN_LOADS PL ON PL.DATE_DEL IS NULL AND PL.SUBJECT_ID = PS.OBJ_ID AND PL.STAGE_ID = :V$REF_ID AND PL.LOAD_HOURS > 0
        JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.REF_ID = PS.PLAN_ID AND J.STAGE_INDEX = :V$STAGE_ID AND J.SUBJECT_ID = PS.SUBJECT_ID
          AND J.JOURNAL_TYPE = 0 AND J.YEAR_ID = :V$YEAR_ID
        WHERE PS.DATE_DEL IS NULL AND PS.IS_STM = 1 AND PS.PLAN_ID = :V$PLAN_ID AND PS.ROW_TYPE = 10
          AND PS.SUBJECT_ID <> 34607
        ORDER BY 1
        INTO :N, :V$SUBJECT_ID, :W, :R, :S3, :V$STM
      DO
      BEGIN
        TAG_NAME = 'plans:r';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'plans:r:plan_id';
        VAL = V$PLAN_ID;
        SUSPEND;
        TAG_NAME = 'plans:r:plan_name';
        VAL = S;
        SUSPEND;
        TAG_NAME = 'plans:r:stage_id';
        VAL = V$STAGE_ID;
        SUSPEND;
        TAG_NAME = 'plans:r:subject_id';
        VAL = V$SUBJECT_ID;
        SUSPEND;
        TAG_NAME = 'plans:r:group_name';
        VAL = S3;
        SUSPEND;
        TAG_NAME = 'plans:r:group_type_id';
        VAL = V$GROUP_TYPE_ID;
        SUSPEND;
        TAG_NAME = 'plans:r:is_stm';
        VAL = V$STM;
        SUSPEND;
        TAG_NAME = 'plans:r:hours';
        VAL = CAST(R / W AS NUMERIC(18, 2));
        VAL = REPLACE(VAL, '.00', '');
        SUSPEND;
        -- Пытаемся определить что было в прошлом (текущем) году
        -- На название УП нам все равно, смотрим по названию группы - должно быть название класса или курса + пробел + произвольный суффикс
        -- Для кружков оставляем название как есть без изменений
        -- С УДОД будем разбираться потом
        TAG_NAME = 'plans:r:person_id';
        VAL = NULL;
        IF(V$YEAR_ID <> V$PYEAR_ID) THEN
        BEGIN
          V$STG = V$STAGE_ID;
          IF(V$GROUP_TYPE_ID <> 2) THEN
          BEGIN
            N = POSITION(' ' IN S3);
            IF(N <= 0) THEN N = CHAR_LENGTH(S3) + 1;
            S2 = SUBSTRING(S3 FROM 1 FOR N - 1);
            S3 = SUBSTRING(S3 FROM N);
            BEGIN
              N = CAST(S2 AS INTEGER) - 1;
              WHEN ANY DO N = -1;
            END
            IF(N <= 0) THEN S3 = NULL;
            ELSE S3 = N || S3;
            -- Пока предполагаем что этапы идут строго по очередности, с АООП будет все плохо
            V$STG = V$STG - 1;
          END
          IF(S3 IS NOT NULL) THEN
          BEGIN
            SELECT FIRST 1 J.TEACHER_ID
            FROM CJ2_JOURNAL J
            WHERE J.DATE_DEL IS NULL AND J.YEAR_ID = :V$PYEAR_ID AND J.JOURNAL_TYPE = :V$GROUP_TYPE_ID AND J.SUBJECT_ID = :V$SUBJECT_ID
              AND J.JOURNAL_NAME = :S3 AND J.STAGE_INDEX = :V$STG
            INTO :VAL;
          END
        END
        SUSPEND;
      END
    END
    -- Идентичен plans, но с данными текущего учебного года
    -- чтобы выдать все предметы, включая те по которым предподавание закончилось
    TAG_NAME = 'cplans::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      -- Обычные УП
      SELECT DISTINCT L400.OBJ_ID, L54.OBJ_ID, V381.LISTVAL_ID, 0
      FROM LINKS L69
      JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
      JOIN VALL V1594 ON V1594.OBJ_ID = L57.OBJ_ID AND V1594.PARAM_ID = 1594 AND V1594.IS_DEL = 0 AND V1594.LISTVAL_ID IN (5339, 5341, 5343)
      JOIN VALI V3115 ON V3115.OBJ_ID = L57.OBJ_ID AND V3115.PARAM_ID = 3115 AND V3115.IS_DEL = 0 AND V3115.VAL = :V$PY
      JOIN LINKS L400 ON L400.PARENT_ID = L57.OBJ_ID AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL
      JOIN VALL V3013 ON V3013.OBJ_ID = L400.OBJ_ID AND V3013.PARAM_ID = 3013 AND V3013.IS_DEL = 0 AND V3013.LISTVAL_ID = 11715 -- действующий УП
      JOIN VALL V3016 ON V3016.OBJ_ID = L400.OBJ_ID AND V3016.PARAM_ID = 3016 AND V3016.IS_DEL = 0 AND V3016.LISTVAL_ID = 5465 -- групповой
      JOIN LINKS L54 ON L54.PARENT_ID = L400.OBJ_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
      JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
      -- В УП ВД просто не должно быть ГУП
      JOIN LINKS L256 ON L256.PARENT_ID = L54.OBJ_ID AND L256.OBJ_TYPE_ID = 256 AND L256.DATE_DEL IS NULL
      WHERE L69.PARENT_ID = :V$OU_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL
      UNION
      -- УП ВД - тут ГУП берем сборную солянку из УП той же ОП
      SELECT DISTINCT L400.OBJ_ID, L54.OBJ_ID, V381.LISTVAL_ID, 1
      FROM LINKS L69
      JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
      JOIN VALL V1594 ON V1594.OBJ_ID = L57.OBJ_ID AND V1594.PARAM_ID = 1594 AND V1594.IS_DEL = 0 AND V1594.LISTVAL_ID IN (5339, 5341, 5343)
      JOIN VALI V3115 ON V3115.OBJ_ID = L57.OBJ_ID AND V3115.PARAM_ID = 3115 AND V3115.IS_DEL = 0 AND V3115.VAL = :V$PY
      JOIN LINKS L400 ON L400.PARENT_ID = L57.OBJ_ID AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL
      JOIN VALL V3013 ON V3013.OBJ_ID = L400.OBJ_ID AND V3013.PARAM_ID = 3013 AND V3013.IS_DEL = 0 AND V3013.LISTVAL_ID = 11715 -- действующий УП
      JOIN VALL V3022 ON V3022.OBJ_ID = L400.OBJ_ID AND V3022.PARAM_ID = 3022 AND V3022.IS_DEL = 0 AND V3022.LISTVAL_ID = 2 -- ВД
      JOIN LINKS L54 ON L54.PARENT_ID = L400.OBJ_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
      JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
      -- А вот ГУП собираем из общеобра и его этапов, чтобы этапы попадали в этапы УП ВД
      JOIN LINKS L400G ON L400G.PARENT_ID = L57.OBJ_ID AND L400G.OBJ_TYPE_ID = 400 AND L400G.DATE_DEL IS NULL
      JOIN VALL V3013G ON V3013G.OBJ_ID = L400G.OBJ_ID AND V3013G.PARAM_ID = 3013 AND V3013G.IS_DEL = 0 AND V3013G.LISTVAL_ID = 11715 -- действующий УП
      JOIN VALL V3016G ON V3016G.OBJ_ID = L400G.OBJ_ID AND V3016G.PARAM_ID = 3016 AND V3016G.IS_DEL = 0 AND V3016G.LISTVAL_ID = 5465 -- групповой
      JOIN LINKS L54G ON L54G.PARENT_ID = L400G.OBJ_ID AND L54G.OBJ_TYPE_ID = 54 AND L54G.DATE_DEL IS NULL
      JOIN VALL V381G ON V381G.OBJ_ID = L54G.OBJ_ID AND V381G.PARAM_ID = 381 AND V381G.IS_DEL = 0 AND V381G.LISTVAL_ID = V381.LISTVAL_ID
      -- В УП ВД просто не должно быть ГУП
      JOIN LINKS L256 ON L256.PARENT_ID = L54G.OBJ_ID AND L256.OBJ_TYPE_ID = 256 AND L256.DATE_DEL IS NULL
      WHERE L69.PARENT_ID = :V$OU_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL
      ORDER BY 4, 1, 3
      INTO :V$PLAN_ID, :V$REF_ID, :V$STAGE_ID, :V$GROUP_TYPE_ID
    DO
    BEGIN
      FOR
        -- Кроме элективов. Связка группы с УП чисто по сочетанию предмета и связи с УП
        -- если будут пары ГУП и потоковый с одним названием - молиться
        SELECT PS.GLOBAL_INDEX, PS.SUBJECT_ID, J.JOURNAL_NAME, J.TEACHER_ID
        FROM PLAN_SUBJECTS PS
        JOIN PLAN_LOADS PL ON PL.DATE_DEL IS NULL AND PL.SUBJECT_ID = PS.OBJ_ID AND PL.STAGE_ID = :V$REF_ID AND PL.LOAD_HOURS > 0
        JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.REF_ID = PS.PLAN_ID AND J.STAGE_INDEX = :V$STAGE_ID AND J.SUBJECT_ID = PS.SUBJECT_ID
          AND J.JOURNAL_TYPE = 0 AND J.YEAR_ID = :V$PYEAR_ID
        WHERE PS.DATE_DEL IS NULL AND PS.PLAN_ID = :V$PLAN_ID AND PS.ROW_TYPE = 10
          AND PS.SUBJECT_ID <> 34607
        ORDER BY 1
        INTO :N, :V$SUBJECT_ID, :S3, :V$PERSON_ID
      DO
      BEGIN
        TAG_NAME = 'cplans:r';
        VAL = NULL;
        SUSPEND;
        -- plan_id и plan_name нам тут не нужны
        TAG_NAME = 'cplans:r:stage_id';
        VAL = V$STAGE_ID;
        SUSPEND;
        TAG_NAME = 'cplans:r:subject_id';
        VAL = V$SUBJECT_ID;
        SUSPEND;
        TAG_NAME = 'cplans:r:group_name';
        VAL = S3;
        SUSPEND;
        TAG_NAME = 'cplans:r:group_type_id';
        VAL = V$GROUP_TYPE_ID;
        SUSPEND;
        TAG_NAME = 'cplans:r:person_id';
        VAL = V$PERSON_ID;
        SUSPEND;
      END
    END
  END
  ELSE
  BEGIN
    -- Действующий
    -- Выбираем из ранее сохраненных
    FOR
      SELECT D.PERSON_ID, D.PLAN_ID, D.GROUP_NAME, V273.SVAL, D.VERIFIED
      FROM EDULOAD_DATA D
      LEFT JOIN VALS V273 ON V273.OBJ_ID = D.PERSON_ID AND V273.PARAM_ID = 273 AND V273.IS_DEL = 0 -- табельный номер
      WHERE D.PARENT_ID = :I$OBJ_ID AND D.REF_ID IS NULL AND D.DATE_DEL IS NULL
      ORDER BY 2
      INTO :V$PERSON_ID, :V$OBJ_ID, :S, :S2, :N
    DO
    BEGIN
      TAG_NAME = 'persons:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'persons:r:id';
      VAL = V$PERSON_ID;
      SUSPEND;
      TAG_NAME = 'persons:r:name';
      VAL = S;
      SUSPEND;
      TAG_NAME = 'persons:r:tabnum';
      VAL = S2;
      SUSPEND;
      TAG_NAME = 'persons:r:verified';
      VAL = N;
      SUSPEND;

      -- Выбираем данные по основной должности и количество ставок по ней
      S = NULL;
      R = NULL;
      SELECT FIRST 1 COALESCE(V3543.VAL, V66.VAL), V71.VAL
      FROM LINKS LP13
      JOIN VALF V71 ON V71.OBJ_ID = LP13.OBJ_ID AND V71.PARAM_ID = 71 AND V71.IS_DEL = 0
      LEFT JOIN VALS V3543 ON V3543.OBJ_ID = LP13.OBJ_ID AND V3543.PARAM_ID = 3543 AND V3543.IS_DEL = 0
      LEFT JOIN VALS V66 ON V66.OBJ_ID = LP13.PARENT_ID AND V66.PARAM_ID = 66 AND V66.IS_DEL = 0
      WHERE LP13.OBJ_ID = :V$OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
      INTO :S, :R;

      TAG_NAME = 'persons:r:job_name';
      VAL = S;
      SUSPEND;
      TAG_NAME = 'persons:r:job_rate';
      VAL = CAST(R AS NUMERIC(18, 2));
      SUSPEND;
    END
    -- Вакантная должность - делаем ссылку на ОУ
    TAG_NAME = 'persons:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'persons:r:id';
    VAL = V$OU_ID;
    SUSPEND;
    TAG_NAME = 'persons:r:name';
    VAL = 'Вакансия';
    SUSPEND;

    -- Учебные коллективы на будущий период
    TAG_NAME = 'grades::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT D.REF_ID, D.STAGE_ID, D.GROUP_NAME
      FROM EDULOAD_DATA D
      WHERE D.PARENT_ID = :I$OBJ_ID AND D.REF_TYPE_ID = 9 AND D.DATE_DEL IS NULL
      ORDER BY 2, 3
      INTO :V$OBJ_ID, :V$STAGE_ID, :S
    DO
    BEGIN
      TAG_NAME = 'grades:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'grades:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'grades:r:stage_id';
      VAL = V$STAGE_ID;
      SUSPEND;
      TAG_NAME = 'grades:r:name';
      VAL = S;
      SUSPEND;
    END

    -- Помещения
    TAG_NAME = 'rooms::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT D.REF_ID, D.GROUP_NAME, D.PERSON_ID
      FROM EDULOAD_DATA D
      WHERE D.PARENT_ID = :I$OBJ_ID AND D.REF_TYPE_ID = 61 AND D.DATE_DEL IS NULL
      ORDER BY 2
      INTO :V$OBJ_ID, :S, :V$PERSON_ID
    DO
    BEGIN
      TAG_NAME = 'rooms:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'rooms:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'rooms:r:name';
      VAL = S;
      SUSPEND;
      TAG_NAME = 'rooms:r:person_id';
      VAL = V$PERSON_ID;
      SUSPEND;
    END

    -- Предметы - все упомянутые
    TAG_NAME = 'subjects::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT DISTINCT D.REF_ID, C.CAPTION
      FROM EDULOAD_DATA D
      LEFT JOIN OBJECT_CAPTION_GET(D.REF_ID) C ON 1 = 1
      WHERE D.PARENT_ID = :I$OBJ_ID AND D.REF_TYPE_ID = 51 AND D.DATE_DEL IS NULL
      ORDER BY 2
      INTO :V$OBJ_ID, :S
    DO
    BEGIN
      TAG_NAME = 'subjects:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'subjects:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'subjects:r:name';
      VAL = S;
      SUSPEND;
    END

    -- Учебные планы на будущий период
    -- выдаем только с заранее настроенными будущими ГУП, иначе непонятно откуда это все брать
    -- для потоковых групп необходимо создать будущие журналы, для самих ГУП не нужно
    TAG_NAME = 'plans::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      -- Обычные УП
      SELECT D.PLAN_ID, D.REF_ID, D.STAGE_ID, D.PLAN_ID, D.GROUP_NAME, D.GROUP_TYPE_ID, D.LOAD_VAL
      FROM EDULOAD_DATA D
      WHERE D.PARENT_ID = :I$OBJ_ID AND D.REF_TYPE_ID = 51 AND D.DATE_DEL IS NULL
      ORDER BY 6, 2, 3, 4
      INTO :V$PLAN_ID, :V$SUBJECT_ID, :V$STAGE_ID, :V$PLAN_ID, :S3, :V$GROUP_TYPE_ID, :R
    DO
    BEGIN
      TAG_NAME = 'plans:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'plans:r:plan_id';
      VAL = V$PLAN_ID;
      SUSPEND;
      TAG_NAME = 'plans:r:plan_name';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'plans:r:stage_id';
      VAL = V$STAGE_ID;
      SUSPEND;
      TAG_NAME = 'plans:r:subject_id';
      VAL = V$SUBJECT_ID;
      SUSPEND;
      TAG_NAME = 'plans:r:group_name';
      VAL = S3;
      SUSPEND;
      TAG_NAME = 'plans:r:group_type_id';
      VAL = V$GROUP_TYPE_ID;
      SUSPEND;
      TAG_NAME = 'plans:r:is_stm';
      VAL = NULL; -- тут уже непонятно
      SUSPEND;
      TAG_NAME = 'plans:r:hours';
      VAL = CAST(R AS NUMERIC(18, 2));
      VAL = REPLACE(VAL, '.00', '');
      SUSPEND;
      TAG_NAME = 'plans:r:person_id';
      VAL = NULL;
      SUSPEND;
    END
  END

  -- Записи нагрузок - это уже только из сохраненных
  TAG_NAME = 'load::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT D.OBJ_ID, D.PERSON_ID, D.STAGE_ID, D.PLAN_ID, D.GROUP_TYPE_ID, D.GROUP_NAME, D.REF_ID, D.REF_TYPE_ID, D.LOAD_VAL
    FROM EDULOAD_DATA D
    WHERE D.DATE_DEL IS NULL AND D.PARENT_ID = :I$OBJ_ID AND D.REF_TYPE_ID IS NOT NULL
    ORDER BY 2, 3
    INTO :V$OBJ_ID, :V$PERSON_ID, :V$STAGE_ID, :V$PLAN_ID, :V$GROUP_TYPE_ID, :S, :V$REF_ID, :V$REF_TYPE_ID, :R
  DO
  BEGIN
    TAG_NAME = 'load:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'load:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'load:r:person_id';
    VAL = V$PERSON_ID;
    SUSPEND;
    TAG_NAME = 'load:r:stage_id';
    VAL = V$STAGE_ID;
    SUSPEND;
    TAG_NAME = 'load:r:plan_id';
    VAL = V$PLAN_ID;
    SUSPEND;
    TAG_NAME = 'load:r:group_type_id';
    VAL = V$GROUP_TYPE_ID;
    SUSPEND;
    TAG_NAME = 'load:r:group_name';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'load:r:ref_type_id';
    VAL = V$REF_TYPE_ID;
    SUSPEND;
    TAG_NAME = 'load:r:ref_id';
    VAL = V$REF_ID;
    SUSPEND;
    TAG_NAME = 'load:r:val';
    VAL = CAST(R AS NUMERIC(18, 2));
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE EDULOAD_PROCESS_DEFER (
    I$YEAR_ID BIGINT)
AS
DECLARE VARIABLE V$EDULOAD_ID BIGINT;
DECLARE VARIABLE V$OU_ID BIGINT;
DECLARE VARIABLE V$PERSON_ID BIGINT;
DECLARE VARIABLE V$GRADE_ID BIGINT;
DECLARE VARIABLE V$VAL BIGINT;
DECLARE VARIABLE T INTEGER;
begin

  -- Ищем действующую нагрузку на текущий год
  SELECT FIRST 1 L2.OBJ_ID, L531.OBJ_ID
  FROM LINKS L2
  JOIN LINKS L527 ON L527.PARENT_ID = L2.OBJ_ID AND L527.OBJ_TYPE_ID = 527 AND L527.DATE_DEL IS NULL
  JOIN LINKS L531 ON L531.PARENT_ID = L527.OBJ_ID AND L531.OBJ_TYPE_ID = 531 AND L531.DATE_DEL IS NULL
  JOIN VALL V3567 ON V3567.OBJ_ID = L531.OBJ_ID AND V3567.PARAM_ID = 3567 AND V3567.IS_DEL = 0 AND V3567.LISTVAL_ID = :I$YEAR_ID
  JOIN VALL V3568 ON V3568.OBJ_ID = L531.OBJ_ID AND V3568.PARAM_ID = 3568 AND V3568.IS_DEL = 0 AND V3568.LISTVAL_ID = 11715
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$OU_ID, :V$EDULOAD_ID;

  IF(V$EDULOAD_ID IS NULL) THEN EXIT;

  -- Классное руководство
  FOR
    SELECT D.REF_ID, IIF(OBJ.TYPE_ID = 2, NULL, D.PERSON_ID), V53.VAL
    FROM EDULOAD_DATA D
    JOIN OBJECTS OBJ ON OBJ.OBJ_ID = D.PERSON_ID
    LEFT JOIN VALR V53 ON V53.OBJ_ID = D.REF_ID AND V53.PARAM_ID = 53 AND V53.IS_DEL = 0
    WHERE D.DATE_DEL IS NULL AND D.PARENT_ID = :V$EDULOAD_ID AND D.REF_TYPE_ID = 9
    ORDER BY 1
    INTO :V$GRADE_ID, :V$PERSON_ID, :V$VAL
  DO
  BEGIN
    IF(COALESCE(V$VAL, 0) <> COALESCE(V$PERSON_ID, 0)) THEN
    SELECT 1 FROM VAL_ADD(53, :V$GRADE_ID, :V$PERSON_ID) INTO :T;
  END

  EXECUTE PROCEDURE FIXER_JOURNAL_GRANTS;

  -- Ответственные за кабинеты
  FOR
    SELECT D.REF_ID, IIF(OBJ.TYPE_ID = 2, NULL, D.PERSON_ID), V1344.VAL
    FROM EDULOAD_DATA D
    JOIN OBJECTS OBJ ON OBJ.OBJ_ID = D.PERSON_ID
    LEFT JOIN VALR V1344 ON V1344.OBJ_ID = D.REF_ID AND V1344.PARAM_ID = 1344 AND V1344.IS_DEL = 0
    WHERE D.DATE_DEL IS NULL AND D.PARENT_ID = :V$EDULOAD_ID AND D.REF_TYPE_ID = 61
    ORDER BY 1
    INTO :V$GRADE_ID, :V$PERSON_ID, :V$VAL
  DO
  BEGIN
    IF(COALESCE(V$VAL, 0) <> COALESCE(V$PERSON_ID, 0)) THEN
    SELECT 1 FROM VAL_ADD(1344, :V$GRADE_ID, :V$PERSON_ID) INTO :T;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE EDULOAD_SET (
    I$PARENT_ID BIGINT NOT NULL,
    I$PERSON_ID BIGINT,
    I$REF_TYPE_ID BIGINT NOT NULL,
    I$REF_ID BIGINT NOT NULL,
    I$PLAN_ID BIGINT,
    I$GROUP_TYPE_ID BIGINT,
    I$GROUP_NAME VARCHAR(400),
    I$STAGE_ID BIGINT,
    I$VAL FLOAT)
RETURNS (
    OBJ_ID BIGINT)
AS
DECLARE VARIABLE V$OU_ID BIGINT;
DECLARE VARIABLE V$YEAR_ID BIGINT;
DECLARE VARIABLE V$Y INTEGER;
DECLARE VARIABLE V$STATE_ID BIGINT;
DECLARE VARIABLE V$DT TIMESTAMP;
DECLARE VARIABLE V FLOAT;
DECLARE VARIABLE V$PERSON_ID BIGINT;
begin

  SELECT LP2.PARENT_ID, V3567.LISTVAL_ID, LV.COST, V3568.LISTVAL_ID
  FROM LINKS LP527
  JOIN LINKS LP2 ON LP2.OBJ_ID = LP527.PARENT_ID AND LP2.PARENT_TYPE_ID = 2 AND LP2.DATE_DEL IS NULL
  JOIN VALL V3567 ON V3567.OBJ_ID = LP527.OBJ_ID AND V3567.PARAM_ID = 3567 AND V3567.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V3567.LISTVAL_ID
  JOIN VALL V3568 ON V3568.OBJ_ID = LP527.OBJ_ID AND V3568.PARAM_ID = 3568 AND V3568.IS_DEL = 0
  WHERE LP527.OBJ_ID = :I$PARENT_ID AND LP527.PARENT_TYPE_ID = 527 AND LP527.DATE_DEL IS NULL
  INTO :V$OU_ID, :V$YEAR_ID, :V$Y, :V$STATE_ID;

  IF(V$YEAR_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Распределение нагрузки не найдено или была удалено';
  IF(V$STATE_ID <> 11716) THEN EXCEPTION DATA_ERROR 'Данные можно редактировать только в статусе проекта';
  if(I$REF_TYPE_ID NOT IN (9, 61, 51)) THEN EXCEPTION DATA_ERROR 'Недопустимый тип данных для записи';

  SELECT FIRST 1 D.OBJ_ID, D.DATE_DEL, D.LOAD_VAL, D.PERSON_ID
  FROM EDULOAD_DATA D
  WHERE D.PARENT_ID = :I$PARENT_ID AND D.REF_ID = :I$REF_ID AND D.REF_TYPE_ID = :I$REF_TYPE_ID
    AND (D.PLAN_ID = :I$PLAN_ID OR (:I$PLAN_ID IS NULL AND D.PLAN_ID IS NULL))
    AND (D.STAGE_ID = :I$STAGE_ID OR (:I$STAGE_ID IS NULL AND D.STAGE_ID IS NULL))
    AND (D.GROUP_TYPE_ID = :I$GROUP_TYPE_ID OR (:I$GROUP_TYPE_ID IS NULL AND D.GROUP_TYPE_ID IS NULL))
    AND (D.GROUP_NAME = :I$GROUP_NAME OR (:I$GROUP_NAME IS NULL AND D.GROUP_NAME IS NULL))
  ORDER BY 1 NULLS FIRST
  INTO :OBJ_ID, :V$DT, :V, :V$PERSON_ID;

  IF(I$PERSON_ID IS NULL) THEN
  BEGIN
    -- Удаляем запись распределения
    IF(OBJ_ID IS NOT NULL AND V$DT IS NULL) THEN
    BEGIN
      UPDATE EDULOAD_DATA
      SET DATE_DEL = CURRENT_TIMESTAMP
      WHERE OBJ_ID = :OBJ_ID;
    END
  END
  ELSE
  BEGIN
    -- Обновляем запись распределения
    IF(OBJ_ID IS NULL) THEN
    BEGIN
      -- Новая запись
      INSERT INTO EDULOAD_DATA
      (PARENT_ID, PERSON_ID, STAGE_ID, GROUP_TYPE_ID, GROUP_NAME, PLAN_ID, REF_ID, REF_TYPE_ID, LOAD_VAL)
      VALUES (:I$PARENT_ID, :I$PERSON_ID, :I$STAGE_ID, :I$GROUP_TYPE_ID, :I$GROUP_NAME, :I$PLAN_ID, :I$REF_ID, :I$REF_TYPE_ID, :I$VAL)
      RETURNING OBJ_ID INTO :OBJ_ID;
    END
    ELSE IF(V$PERSON_ID <> I$PERSON_ID OR COALESCE(I$VAL, -1) <> COALESCE(V, -1) OR V$DT IS NOT NULL) THEN
    BEGIN
      -- Кроме указанных полей поменяться тут ничего не может
      -- По идее в случае изменений нужно снимать флаг VERIFIED
      UPDATE EDULOAD_DATA
      SET LOAD_VAL = :V, PERSON_ID = :I$PERSON_ID, STAGE_ID = :I$STAGE_ID, DATE_DEL = NULL, VERIFIED = 0
      WHERE OBJ_ID = :OBJ_ID;
    END
  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE EDULOAD_UPDATE_ORDER (
    I$OBJ_ID BIGINT)
AS
DECLARE VARIABLE V$DATE DATE;
DECLARE VARIABLE V$NUM VARCHAR(100);
DECLARE VARIABLE V$ORDER_ID BIGINT;
DECLARE VARIABLE V$Y INTEGER;
DECLARE VARIABLE V$ORDER_STATE_ID BIGINT;
begin

  -- Год самого распределения
  SELECT LV.COST
  FROM VALL V3567
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V3567.LISTVAL_ID
  WHERE V3567.OBJ_ID = :I$OBJ_ID AND V3567.PARAM_ID = 3567 AND V3567.IS_DEL = 0
  INTO :V$Y;

  -- Реквизиты приказа
  SELECT V3569.VAL
  FROM VALS V3569
  WHERE V3569.OBJ_ID = :I$OBJ_ID AND V3569.PARAM_ID = 3569 AND V3569.IS_DEL = 0
  INTO :V$NUM;

  SELECT V3570.VAL
  FROM VALD V3570
  WHERE V3570.OBJ_ID = :I$OBJ_ID AND V3570.PARAM_ID = 3570 AND V3570.IS_DEL = 0
  INTO :V$DATE;

  SELECT FIRST 1 D.OBJ_ID, D.STATE_ID
  FROM ORDERS D
  WHERE D.DATE_DEL IS NULL AND D.REF_ID = :I$OBJ_ID
  INTO :V$ORDER_ID, :V$ORDER_STATE_ID;

  -- Проверяем что дата приказа попадает в допустимый диапазон
  -- Год утверждения не может быть раньше года начала (то есть нельзя 2025-2026 год утвердить приказом в 2024 году)
  -- Но оставляем возможность утвердить следующим годом - то есть 2025-2026 год можно утвердить до конца мая 2026 года
  IF(EXTRACT(YEAR FROM V$DATE) < V$Y OR V$DATE > '31.05.' || (V$Y + 1)) THEN EXCEPTION DATA_ERROR 'Недопустимая дата приказа';

  IF(UPPER(V$NUM) = 'АВТО') THEN
  BEGIN
    -- Формируем номер приказа и пересохраняем его
    SELECT ORDER_NUM
    FROM ORDER_MK_NUM(14260, 0, :V$NUM)
    INTO :V$NUM;

    UPDATE VALS
    SET VAL = :V$NUM
    WHERE OBJ_ID = :I$OBJ_ID AND PARAM_ID = 3569 AND IS_DEL = 0;
  END

  -- Дату действия ставим 01 сентября
  UPDATE ORDERS
  SET STATE_ID = 11715, ORDER_NUM = :V$NUM, ORDER_DATE = :V$DATE, ACTION_DATE = '01.09.' || :V$Y
  WHERE OBJ_ID = :V$ORDER_ID;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE EDU_REPORT_LEVELS (
    I$OBJ_ID BIGINT)
RETURNS (
    PARENT_ID BIGINT,
    LISTVAL_ID BIGINT,
    VAL VARCHAR(400))
AS
DECLARE VARIABLE V$STATUS VARCHAR(10);
DECLARE VARIABLE V$TYPE_ID BIGINT;
DECLARE VARIABLE V$HAS_OO SMALLINT;
DECLARE VARIABLE V$HAS_DOO SMALLINT;
DECLARE VARIABLE V$HAS_SPO SMALLINT;
begin

  V$STATUS = (SELECT STATUS FROM OU_LICENCE_TYPE);
  SELECT TYPE_ID FROM OBJECTS WHERE OBJ_ID = :I$OBJ_ID INTO :V$TYPE_ID;

  IF(V$TYPE_ID IS NULL) THEN V$TYPE_ID = 111;

  V$HAS_DOO = 0;
  V$HAS_SPO = 0;
  V$HAS_OO = 0;

  IF(V$STATUS = 'D') THEN V$HAS_DOO = 1;
  IF(V$STATUS = 'C') THEN V$HAS_SPO = 1;
  IF(V$STATUS = 'O') THEN V$HAS_OO = 1;

  IF(V$TYPE_ID = 2 AND V$STATUS = 'S') THEN
  BEGIN
    SELECT FIRST 1 1
    FROM LINKS L472
    JOIN VALL V3327 ON V3327.OBJ_ID = L472.OBJ_ID AND V3327.PARAM_ID = 3327 AND V3327.IS_DEL = 0 AND V3327.LISTVAL_ID IN (22, 26, 27)
    WHERE L472.PARENT_TYPE_ID = 2 AND L472.OBJ_TYPE_ID = 472 AND L472.DATE_DEL IS NULL
    INTO :V$HAS_OO;

    SELECT FIRST 1 1
    FROM LINKS L472
    JOIN VALL V3327 ON V3327.OBJ_ID = L472.OBJ_ID AND V3327.PARAM_ID = 3327 AND V3327.IS_DEL = 0 AND V3327.LISTVAL_ID IN (21, 3263, 3264)
    WHERE L472.PARENT_TYPE_ID = 2 AND L472.OBJ_TYPE_ID = 472 AND L472.DATE_DEL IS NULL
    INTO :V$HAS_DOO;

    SELECT FIRST 1 1
    FROM LINKS L472
    JOIN VALL V3327 ON V3327.OBJ_ID = L472.OBJ_ID AND V3327.PARAM_ID = 3327 AND V3327.IS_DEL = 0 AND V3327.LISTVAL_ID IN (28, 29, 13129, 13131)
    WHERE L472.PARENT_TYPE_ID = 2 AND L472.OBJ_TYPE_ID = 472 AND L472.DATE_DEL IS NULL
    INTO :V$HAS_SPO;
  END

  -- Для района или региона
  IF(V$TYPE_ID IN (111, 112) AND V$STATUS = 'O') THEN
  BEGIN
    SELECT FIRST 1 1
    FROM VALL V3327
    WHERE V3327.PARAM_ID = 3327 AND V3327.IS_DEL = 0 AND V3327.LISTVAL_ID IN (21, 3263, 3264)
    INTO :V$HAS_DOO;

    SELECT FIRST 1 1
    FROM VALL V3327
    WHERE V3327.PARAM_ID = 3327 AND V3327.IS_DEL = 0 AND V3327.LISTVAL_ID IN (28, 29, 13129, 13131)
    INTO :V$HAS_SPO;
  END

  IF(V$HAS_OO = 1) THEN
  BEGIN
    LISTVAL_ID = 22;
    VAL = 'ОО';
    SUSPEND;
  END
  IF(V$HAS_DOO = 1) THEN
  BEGIN
    LISTVAL_ID = 21;
    VAL = 'ДОО';
    SUSPEND;
  END
  IF(V$HAS_SPO = 1) THEN
  BEGIN
    LISTVAL_ID = 29;
    VAL = 'СПО';
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE EDU_REPORT_STAGES (
    I$OBJ_ID BIGINT)
RETURNS (
    PARENT_ID BIGINT,
    LISTVAL_ID BIGINT,
    VAL VARCHAR(400))
AS
DECLARE VARIABLE V$STATUS VARCHAR(10);
DECLARE VARIABLE V$TYPE_ID BIGINT;
DECLARE VARIABLE V$HAS_DOO SMALLINT;
DECLARE VARIABLE V$HAS_OO SMALLINT;
DECLARE VARIABLE V$HAS_SPO SMALLINT;
DECLARE VARIABLE V$HAS_OVZ SMALLINT;
begin
  V$STATUS = (SELECT STATUS FROM OU_LICENCE_TYPE);
  SELECT TYPE_ID FROM OBJECTS WHERE OBJ_ID = :I$OBJ_ID INTO :V$TYPE_ID;

  IF(V$TYPE_ID IS NULL) THEN V$TYPE_ID = 111;

  V$HAS_DOO = 0;
  V$HAS_SPO = 0;
  V$HAS_OO = 0;

  IF(V$STATUS = 'D') THEN V$HAS_DOO = 1;
  IF(V$STATUS = 'C') THEN V$HAS_SPO = 1;
  IF(V$STATUS = 'O') THEN V$HAS_OO = 1;

  IF(V$TYPE_ID = 2 AND V$STATUS = 'S') THEN
  BEGIN
    SELECT FIRST 1 1
    FROM LINKS L472
    JOIN VALL V3327 ON V3327.OBJ_ID = L472.OBJ_ID AND V3327.PARAM_ID = 3327 AND V3327.IS_DEL = 0 AND V3327.LISTVAL_ID IN (22, 26, 27)
    WHERE L472.PARENT_TYPE_ID = 2 AND L472.OBJ_TYPE_ID = 472 AND L472.DATE_DEL IS NULL
    INTO :V$HAS_OO;

    SELECT FIRST 1 1
    FROM LINKS L472
    JOIN VALL V3327 ON V3327.OBJ_ID = L472.OBJ_ID AND V3327.PARAM_ID = 3327 AND V3327.IS_DEL = 0 AND V3327.LISTVAL_ID IN (21, 3263, 3264)
    WHERE L472.PARENT_TYPE_ID = 2 AND L472.OBJ_TYPE_ID = 472 AND L472.DATE_DEL IS NULL
    INTO :V$HAS_DOO;

    SELECT FIRST 1 1
    FROM LINKS L472
    JOIN VALL V3327 ON V3327.OBJ_ID = L472.OBJ_ID AND V3327.PARAM_ID = 3327 AND V3327.IS_DEL = 0 AND V3327.LISTVAL_ID IN (28, 29, 13129, 13131)
    WHERE L472.PARENT_TYPE_ID = 2 AND L472.OBJ_TYPE_ID = 472 AND L472.DATE_DEL IS NULL
    INTO :V$HAS_SPO;

    SELECT FIRST 1 1
    FROM LINKS L8
    JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V49.LISTVAL_ID AND LV.LIST_ID = 25 AND LV.IS_DEL = 0 AND LV.PARENT_ID = 12941
    WHERE L8.OBJ_TYPE_ID = 8 AND L8.PARENT_TYPE_ID = 7 AND L8.DATE_DEL IS NULL
    INTO :V$HAS_OVZ;
  END

  -- Для района или региона
  IF(V$TYPE_ID IN (111, 112) AND V$STATUS = 'O') THEN
  BEGIN
    SELECT FIRST 1 1
    FROM VALL V3327
    WHERE V3327.PARAM_ID = 3327 AND V3327.IS_DEL = 0 AND V3327.LISTVAL_ID IN (21, 3263, 3264)
    INTO :V$HAS_DOO;

    SELECT FIRST 1 1
    FROM VALL V3327
    WHERE V3327.PARAM_ID = 3327 AND V3327.IS_DEL = 0 AND V3327.LISTVAL_ID IN (28, 29, 13129, 13131)
    INTO :V$HAS_SPO;
  END

  FOR
    SELECT LS.LISTVAL_ID, LS.PARENT_ID, LS.VAL
    FROM LISTVALS_LIST(25) LS
    WHERE (
      (:V$HAS_DOO = 1 AND (LS.PARENT_ID = 2140 OR LS.LISTVAL_ID = 2140)) OR -- дошкольные этапы обучения
      (:V$HAS_OO = 1 AND (LS.PARENT_ID = 2141 OR LS.LISTVAL_ID = 2141)) OR -- школьные этапы обучения
      (:V$HAS_OVZ = 1 AND (LS.PARENT_ID = 12941 OR LS.LISTVAL_ID = 12941)) OR -- школьные этапы обучения, ОВЗ
      (:V$HAS_SPO = 1 AND (LS.PARENT_ID = 2142 OR LS.LISTVAL_ID = 2142))) -- этапы СПО
      AND IS_DEL = 0
    ORDER BY SORT_ORDER
    INTO :LISTVAL_ID, :PARENT_ID, :VAL
  DO
  BEGIN
    SUSPEND;
  END
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE EINSPECTOR_COINCIDE_LIST (
    I$MONITORING_ID BIGINT,
    I$ROOMDEMAND_TYPE_ID BIGINT)
RETURNS (
    ROOMDEMAND_ID BIGINT,
    ROOMDEMAND_NAME VARCHAR(1000),
    ROOMDEMAND_ROOM_TYPE VARCHAR(5000),
    ROOMDEMAND_SUBJECTS VARCHAR(5000),
    ROOM_ID BIGINT,
    ROOM_NAME VARCHAR(1000),
    ROOM_TYPE VARCHAR(1000),
    ROOM_ADDRESS VARCHAR(1000),
    ROOM_OWNERSHIP_TYPE VARCHAR(1000),
    ROOM_PERIOD_OF_VALIDITY VARCHAR(1000),
    ROOM_SQUARE FLOAT,
    SORT_ORDER DOUBLE PRECISION)
AS
declare variable V$OBJ_ID bigint;
declare variable V$BUILDING_ID bigint;
declare variable V$SRT varchar(1000);
BEGIN
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L

        WHERE L.PARENT_ID = :I$MONITORING_ID
        AND L.OBJ_TYPE_ID = :I$ROOMDEMAND_TYPE_ID
        AND L.DATE_DEL IS NULL

        INTO :V$OBJ_ID
    DO
    BEGIN
        SELECT I
        FROM VAL_GET(
            :V$OBJ_ID,
            CASE :I$ROOMDEMAND_TYPE_ID
                WHEN 325 THEN 2592
                WHEN 326 THEN 2593
                WHEN 328 THEN 2594
                WHEN 329 THEN 2595
            END
        )
        INTO :ROOMDEMAND_ID;

        SELECT I
        FROM VAL_GET(
            :V$OBJ_ID,
            CASE :I$ROOMDEMAND_TYPE_ID
                WHEN 325 THEN 2596
                WHEN 326 THEN 2597
                WHEN 328 THEN 2598
                WHEN 329 THEN 2599
            END
        )
        INTO :ROOM_ID;

        SELECT V
        FROM VAL_GET(:ROOMDEMAND_ID, 2550)
        INTO :ROOMDEMAND_NAME;

        ROOMDEMAND_ROOM_TYPE = '';

        FOR
            SELECT R.VAL
            FROM LINKS L322

            JOIN VALL V2553
            ON V2553.OBJ_ID = L322.OBJ_ID
            AND V2553.PARAM_ID = 2553
            AND V2553.IS_DEL = 0

            JOIN LISTVALS LV2553
            ON LV2553.LISTVAL_ID = V2553.LISTVAL_ID

            LEFT JOIN RES_GET(LV2553.RES_ID, 'RU') R ON 1=1

            WHERE L322.PARENT_ID = :ROOMDEMAND_ID
            AND L322.OBJ_TYPE_ID = 322
            AND L322.DATE_DEL IS NULL

            ORDER BY LV2553.SORT_ORDER

            INTO :V$SRT
        DO
        BEGIN
            IF (ROOMDEMAND_ROOM_TYPE <> '') THEN
            BEGIN
                ROOMDEMAND_ROOM_TYPE = ROOMDEMAND_ROOM_TYPE || '; ';
            END
            ROOMDEMAND_ROOM_TYPE = ROOMDEMAND_ROOM_TYPE || V$SRT;
        END

        ROOMDEMAND_SUBJECTS = '';

        FOR
            SELECT C.CAPTION
            FROM LINKS L323

            JOIN VALR V2554
            ON V2554.OBJ_ID = L323.OBJ_ID
            AND V2554.PARAM_ID = 2554
            AND V2554.IS_DEL = 0

            LEFT JOIN OBJECT_CAPTION_GET(V2554.VAL) C ON 1=1

            WHERE L323.PARENT_ID = :ROOMDEMAND_ID
            AND L323.OBJ_TYPE_ID = 323
            AND L323.DATE_DEL IS NULL

            ORDER BY C.SORT_ORDER

            INTO :V$SRT
        DO
        BEGIN
            IF (ROOMDEMAND_SUBJECTS <> '') THEN
            BEGIN
                ROOMDEMAND_SUBJECTS = ROOMDEMAND_SUBJECTS || '; ';
            END
            ROOMDEMAND_SUBJECTS = ROOMDEMAND_SUBJECTS || V$SRT;
        END

        SELECT CAPTION,
               SORT_ORDER
        FROM OBJECT_CAPTION_GET(:ROOM_ID)
        INTO :ROOM_NAME,
             :SORT_ORDER;

        SELECT V
        FROM VAL_GET(:ROOM_ID, 526)
        INTO :ROOM_TYPE;

        FOR
            SELECT LP16.PARENT_ID
            FROM LINKS LP16

            WHERE LP16.OBJ_ID = :ROOM_ID
            AND LP16.PARENT_TYPE_ID = 16
            AND LP16.DATE_DEL IS NULL

            INTO :V$BUILDING_ID
        DO
        BEGIN
            SELECT V
            FROM VAL_GET(:V$BUILDING_ID, 420)
            INTO :ROOM_ADDRESS;
    
            SELECT V
            FROM VAL_GET(:V$BUILDING_ID, 504)
            INTO :ROOM_OWNERSHIP_TYPE;
    
            SELECT V
            FROM VAL_GET(:V$BUILDING_ID, 505)
            INTO :ROOM_PERIOD_OF_VALIDITY;
        END

        SELECT F
        FROM VAL_GET(:ROOM_ID, 533)
        INTO :ROOM_SQUARE;

        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE EINSPECTOR_EQDEMAND_ADD (
    I$EQDEMAND_TYPE_ID BIGINT,
    I$MONITORING_ID BIGINT,
    I$EQ_ID BIGINT,
    I$EQDEMAND_ID BIGINT)
AS
declare variable V$STR varchar(5000);
declare variable V$I bigint;
declare variable V$OBJ_ID bigint;
declare variable V$TYPE_ID bigint;
declare variable V$BLOB_ID bigint;
BEGIN
    FOR
        SELECT OBJ_ID
        FROM OBJECT_ADD(:I$MONITORING_ID, :I$EQDEMAND_TYPE_ID)
        INTO :V$OBJ_ID
    DO
    BEGIN
        SELECT BLOB_ID
        FROM VAL_ADD(
            CASE :I$EQDEMAND_TYPE_ID
                WHEN 332 THEN 2645
                WHEN 333 THEN 2647
                WHEN 335 THEN 2648
                WHEN 337 THEN 2651
            END,
            :V$OBJ_ID,
            :I$EQDEMAND_ID
        )
        INTO :V$BLOB_ID;

        SELECT BLOB_ID
        FROM VAL_ADD(
            CASE :I$EQDEMAND_TYPE_ID
                WHEN 332 THEN 2646
                WHEN 333 THEN 2649
                WHEN 335 THEN 2650
                WHEN 337 THEN 2652
            END,
            :V$OBJ_ID,
            :I$EQ_ID
        )
        INTO :V$BLOB_ID;

        SELECT I
        FROM VAL_GET(:I$EQDEMAND_ID, 2602)
        INTO :V$I;

        IF (V$I > 0) THEN
        BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD(
                CASE :I$EQDEMAND_TYPE_ID
                    WHEN 332 THEN 2609
                    WHEN 333 THEN 2618
                    WHEN 335 THEN 2627
                    WHEN 337 THEN 2628
                END,
                :V$OBJ_ID,
                :V$I
            )
            INTO :V$BLOB_ID;
        END

        SELECT I
        FROM VAL_GET(:I$EQDEMAND_ID, 2603)
        INTO :V$I;

        IF (V$I > 0) THEN
        BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD(
                CASE :I$EQDEMAND_TYPE_ID
                    WHEN 332 THEN 2610
                    WHEN 333 THEN 2619
                    WHEN 335 THEN 2629
                    WHEN 337 THEN 2630
                END,
                :V$OBJ_ID,
                :V$I
            )
            INTO :V$BLOB_ID;
        END

        SELECT I
        FROM VAL_GET(:I$EQDEMAND_ID, 2604)
        INTO :V$I;

        IF (V$I > 0) THEN
        BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD(
                CASE :I$EQDEMAND_TYPE_ID
                    WHEN 332 THEN 2611
                    WHEN 333 THEN 2620
                    WHEN 335 THEN 2631
                    WHEN 337 THEN 2632
                END,
                :V$OBJ_ID,
                :V$I
            )
            INTO :V$BLOB_ID;
        END

        SELECT I
        FROM VAL_GET(:I$EQDEMAND_ID, 2605)
        INTO :V$I;

        IF (V$I > 0) THEN
        BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD(
                CASE :I$EQDEMAND_TYPE_ID
                    WHEN 332 THEN 2612
                    WHEN 333 THEN 2621
                    WHEN 335 THEN 2633
                    WHEN 337 THEN 2634
                END,
                :V$OBJ_ID,
                :V$I
            )
            INTO :V$BLOB_ID;
        END

        SELECT V
        FROM VAL_GET(:I$EQDEMAND_ID, 2606)
        INTO :V$STR;

        IF (V$STR <> '') THEN
        BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD(
                CASE :I$EQDEMAND_TYPE_ID
                    WHEN 332 THEN 2613
                    WHEN 333 THEN 2622
                    WHEN 335 THEN 2635
                    WHEN 337 THEN 2636
                END,
                :V$OBJ_ID,
                :V$STR
            )
            INTO :V$BLOB_ID;
        END

        --

        FOR
            SELECT TYPE_ID
            FROM OBJECTS
            WHERE OBJ_ID = :I$EQ_ID

            INTO :V$TYPE_ID
        DO
        BEGIN
            SELECT V
            FROM VAL_GET(
                :I$EQ_ID,
                CASE :V$TYPE_ID
                    WHEN 94 THEN 601
                    WHEN 95 THEN 627
                    WHEN 128 THEN 877
                    WHEN 97 THEN 606
                    WHEN 109 THEN 656
                    WHEN 106 THEN 639
                    WHEN 107 THEN 647
                END
            )
            INTO :V$STR;
    
            IF (V$STR <> '') THEN
            BEGIN
                SELECT BLOB_ID
                FROM VAL_ADD(
                    CASE :I$EQDEMAND_TYPE_ID
                        WHEN 332 THEN 2614
                        WHEN 333 THEN 2623
                        WHEN 335 THEN 2637
                        WHEN 337 THEN 2638
                    END,
                    :V$OBJ_ID,
                    :V$STR
                )
                INTO :V$BLOB_ID;
            END

            IF (V$TYPE_ID IN (94,95,97,109,106,107)) THEN
            BEGIN
                SELECT V
                FROM VAL_GET(
                    :I$EQ_ID,
                    CASE :V$TYPE_ID
                        WHEN 94 THEN 603
                        WHEN 95 THEN 605
                        WHEN 97 THEN 607
                        WHEN 109 THEN 657
                        WHEN 106 THEN 640
                        WHEN 107 THEN 648
                    END
                )
                INTO :V$STR;
        
                IF (V$STR <> '') THEN
                BEGIN
                    SELECT BLOB_ID
                    FROM VAL_ADD(
                        CASE :I$EQDEMAND_TYPE_ID
                            WHEN 332 THEN 2615
                            WHEN 333 THEN 2624
                            WHEN 335 THEN 2639
                            WHEN 337 THEN 2640
                        END,
                        :V$OBJ_ID,
                        :V$STR
                    )
                    INTO :V$BLOB_ID;
                END
            END

            SELECT V
            FROM VAL_GET(
                :I$EQ_ID,
                CASE :V$TYPE_ID
                    WHEN 94 THEN 634
                    WHEN 95 THEN 630
                    WHEN 128 THEN 878
                    WHEN 97 THEN 636
                    WHEN 109 THEN 659
                    WHEN 106 THEN 642
                    WHEN 107 THEN 650
                END
            )
            INTO :V$STR;
    
            IF (V$STR <> '') THEN
            BEGIN
                SELECT BLOB_ID
                FROM VAL_ADD(
                    CASE :I$EQDEMAND_TYPE_ID
                        WHEN 332 THEN 2616
                        WHEN 333 THEN 2625
                        WHEN 335 THEN 2641
                        WHEN 337 THEN 2642
                    END,
                    :V$OBJ_ID,
                    :V$STR
                )
                INTO :V$BLOB_ID;
            END

            IF ((V$TYPE_ID IN (97,106,107)) AND (I$EQDEMAND_TYPE_ID IN (333,335,337))) THEN
            BEGIN
                SELECT I
                FROM VAL_GET(
                    :I$EQ_ID,
                    CASE :V$TYPE_ID
                        WHEN 97 THEN 643
                        WHEN 106 THEN 644
                        WHEN 107 THEN 654
                    END
                )
                INTO :V$I;
        
                IF (V$I > 0) THEN
                BEGIN
                    SELECT BLOB_ID
                    FROM VAL_ADD(
                        CASE :I$EQDEMAND_TYPE_ID
                            WHEN 333 THEN 2617
                            WHEN 335 THEN 2643
                            WHEN 337 THEN 2644
                        END,
                        :V$OBJ_ID,
                        :V$I
                    )
                    INTO :V$BLOB_ID;
                END
            END
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE EINSPECTOR_EQDEMAND_COINCIDE (
    I$EQDEMAND_ID BIGINT)
RETURNS (
    EQ_ID BIGINT,
    EQ_NAME VARCHAR(1000),
    EQ_COUNT VARCHAR(10),
    EQ_YEAR VARCHAR(20),
    EQ_SUBJECT VARCHAR(1000),
    SORT_ORDER DOUBLE PRECISION)
AS
declare variable V$TYPE_ID bigint;
BEGIN
    FOR
        SELECT L94.OBJ_ID,
               L94.OBJ_TYPE_ID

        FROM LINKS L2

        JOIN LINKS L74
        ON L74.PARENT_ID = L2.OBJ_ID
        AND L74.OBJ_TYPE_ID = 74
        AND L74.DATE_DEL IS NULL

        JOIN LINKS L94
        ON L94.PARENT_ID = L74.OBJ_ID
        AND L94.OBJ_TYPE_ID = 94
        AND L94.DATE_DEL IS NULL

        LEFT JOIN VAL_GET(L94.OBJ_ID, 601) V601 ON 1=1

        JOIN VALL V2602
        ON V2602.OBJ_ID = :I$EQDEMAND_ID
        AND V2602.PARAM_ID = 2602
        AND V2602.IS_DEL = 0
        AND V2602.LISTVAL_ID = 11321

        JOIN VALS V2606
        ON V2606.OBJ_ID = V2602.OBJ_ID
        AND V2606.PARAM_ID = 2606
        AND V2606.IS_DEL = 0
        AND V2606.VAL LIKE V601.V
        AND V601.V <> ''

        WHERE L2.PARENT_ID IS NULL
        AND L2.OBJ_TYPE_ID = 2
        AND L2.DATE_DEL IS NULL

        UNION ALL

        SELECT L95.OBJ_ID,
               L95.OBJ_TYPE_ID

        FROM LINKS L2

        JOIN LINKS L23
        ON L23.PARENT_ID = L2.OBJ_ID
        AND L23.OBJ_TYPE_ID = 23
        AND L23.DATE_DEL IS NULL

        JOIN LINKS L95
        ON L95.PARENT_ID = L23.OBJ_ID
        AND L95.OBJ_TYPE_ID = 95
        AND L95.DATE_DEL IS NULL

        JOIN VALL V2602
        ON V2602.OBJ_ID = :I$EQDEMAND_ID
        AND V2602.PARAM_ID = 2602
        AND V2602.IS_DEL = 0
        AND V2602.LISTVAL_ID = 11322

        JOIN VALL V2604
        ON V2604.OBJ_ID = V2602.OBJ_ID
        AND V2604.PARAM_ID = 2604
        AND V2604.IS_DEL = 0

        JOIN LISTVALS LV2604
        ON LV2604.LISTVAL_ID = V2604.LISTVAL_ID

        JOIN VALL V604
        ON V604.OBJ_ID = L95.OBJ_ID
        AND V604.PARAM_ID = 604
        AND V604.IS_DEL = 0
        AND V604.LISTVAL_ID = LV2604.COST

        WHERE L2.PARENT_ID IS NULL
        AND L2.OBJ_TYPE_ID = 2
        AND L2.DATE_DEL IS NULL

        UNION ALL

        SELECT L128.OBJ_ID,
               L128.OBJ_TYPE_ID

        FROM LINKS L2

        JOIN LINKS L23
        ON L23.PARENT_ID = L2.OBJ_ID
        AND L23.OBJ_TYPE_ID = 23
        AND L23.DATE_DEL IS NULL

        JOIN LINKS L128
        ON L128.PARENT_ID = L23.OBJ_ID
        AND L128.OBJ_TYPE_ID = 128
        AND L128.DATE_DEL IS NULL

        JOIN VALL V2602
        ON V2602.OBJ_ID = :I$EQDEMAND_ID
        AND V2602.PARAM_ID = 2602
        AND V2602.IS_DEL = 0
        AND V2602.LISTVAL_ID = 11322

        JOIN VALL V2605
        ON V2605.OBJ_ID = V2602.OBJ_ID
        AND V2605.PARAM_ID = 2605
        AND V2605.IS_DEL = 0

        JOIN VALL V876
        ON V876.OBJ_ID = L128.OBJ_ID
        AND V876.PARAM_ID = 876
        AND V876.IS_DEL = 0
        AND V876.LISTVAL_ID = V2605.LISTVAL_ID

        WHERE L2.PARENT_ID IS NULL
        AND L2.OBJ_TYPE_ID = 2
        AND L2.DATE_DEL IS NULL

        UNION ALL

        SELECT L97.OBJ_ID,
               L97.OBJ_TYPE_ID

        FROM LINKS L2

        JOIN LINKS L92
        ON L92.PARENT_ID = L2.OBJ_ID
        AND L92.OBJ_TYPE_ID = 92
        AND L92.DATE_DEL IS NULL

        JOIN LINKS L97
        ON L97.PARENT_ID = L92.OBJ_ID
        AND L97.OBJ_TYPE_ID = 97
        AND L97.DATE_DEL IS NULL

        LEFT JOIN VAL_GET(L97.OBJ_ID, 606) V606 ON 1=1

        JOIN VALL V2602
        ON V2602.OBJ_ID = :I$EQDEMAND_ID
        AND V2602.PARAM_ID = 2602
        AND V2602.IS_DEL = 0
        AND V2602.LISTVAL_ID = 11323

        JOIN VALS V2606
        ON V2606.OBJ_ID = V2602.OBJ_ID
        AND V2606.PARAM_ID = 2606
        AND V2606.IS_DEL = 0
        AND V2606.VAL LIKE V606.V
        AND V606.V <> ''

        JOIN VALL V2603
        ON V2603.OBJ_ID = V2602.OBJ_ID
        AND V2603.PARAM_ID = 2603
        AND V2603.IS_DEL = 0

        JOIN LISTVALS LV2603
        ON LV2603.LISTVAL_ID = V2603.LISTVAL_ID

        JOIN VALL V645
        ON V645.OBJ_ID = L97.OBJ_ID
        AND V645.PARAM_ID = 645
        AND V645.IS_DEL = 0
        AND V645.LISTVAL_ID = LV2603.COST

        WHERE L2.PARENT_ID IS NULL
        AND L2.OBJ_TYPE_ID = 2
        AND L2.DATE_DEL IS NULL

        AND (EXISTS(
            SELECT FIRST 1 1
            FROM VALL V2608

            WHERE V2608.OBJ_ID = :I$EQDEMAND_ID
            AND V2608.PARAM_ID = 2608
            AND V2608.IS_DEL = 0
            AND V2608.LISTVAL_ID IN (
                SELECT V2462.LISTVAL_ID
                FROM VALR V643

                JOIN LINKS L302
                ON L302.PARENT_ID = V643.VAL
                AND L302.OBJ_TYPE_ID = 302
                AND L302.DATE_DEL IS NULL

                JOIN VALL V2462
                ON V2462.OBJ_ID = L302.OBJ_ID
                AND V2462.PARAM_ID = 2462
                AND V2462.IS_DEL = 0

                WHERE V643.OBJ_ID = L97.OBJ_ID
                AND V643.PARAM_ID = 643
                AND V643.IS_DEL =0
            )
        )

        OR NOT EXISTS(
            SELECT FIRST 1 1
            FROM VALL V2608

            WHERE V2608.OBJ_ID = :I$EQDEMAND_ID
            AND V2608.PARAM_ID = 2608
            AND V2608.IS_DEL = 0
        ))

        UNION ALL

        SELECT L109.OBJ_ID,
               L109.OBJ_TYPE_ID

        FROM LINKS L2

        JOIN LINKS L108
        ON L108.PARENT_ID = L2.OBJ_ID
        AND L108.OBJ_TYPE_ID = 108
        AND L108.DATE_DEL IS NULL

        JOIN LINKS L109
        ON L109.PARENT_ID = L108.OBJ_ID
        AND L109.OBJ_TYPE_ID = 109
        AND L109.DATE_DEL IS NULL

        LEFT JOIN VAL_GET(L109.OBJ_ID, 656) V656 ON 1=1

        JOIN VALL V2602
        ON V2602.OBJ_ID = :I$EQDEMAND_ID
        AND V2602.PARAM_ID = 2602
        AND V2602.IS_DEL = 0
        AND V2602.LISTVAL_ID = 11324

        JOIN VALS V2606
        ON V2606.OBJ_ID = V2602.OBJ_ID
        AND V2606.PARAM_ID = 2606
        AND V2606.IS_DEL = 0
        AND V2606.VAL LIKE V656.V
        AND V656.V <> ''

        WHERE L2.PARENT_ID IS NULL
        AND L2.OBJ_TYPE_ID = 2
        AND L2.DATE_DEL IS NULL

        UNION ALL

        SELECT L106.OBJ_ID,
               L106.OBJ_TYPE_ID

        FROM LINKS L2

        JOIN LINKS L104
        ON L104.PARENT_ID = L2.OBJ_ID
        AND L104.OBJ_TYPE_ID = 104
        AND L104.DATE_DEL IS NULL

        JOIN LINKS L106
        ON L106.PARENT_ID = L104.OBJ_ID
        AND L106.OBJ_TYPE_ID = 106
        AND L106.DATE_DEL IS NULL

        LEFT JOIN VAL_GET(L106.OBJ_ID, 639) V639 ON 1=1

        JOIN VALL V2602
        ON V2602.OBJ_ID = :I$EQDEMAND_ID
        AND V2602.PARAM_ID = 2602
        AND V2602.IS_DEL = 0
        AND V2602.LISTVAL_ID = 11325

        JOIN VALS V2606
        ON V2606.OBJ_ID = V2602.OBJ_ID
        AND V2606.PARAM_ID = 2606
        AND V2606.IS_DEL = 0
        AND V2606.VAL LIKE V639.V
        AND V639.V <> ''

        JOIN VALL V2603
        ON V2603.OBJ_ID = V2602.OBJ_ID
        AND V2603.PARAM_ID = 2603
        AND V2603.IS_DEL = 0

        JOIN LISTVALS LV2603
        ON LV2603.LISTVAL_ID = V2603.LISTVAL_ID

        JOIN VALL V637
        ON V637.OBJ_ID = L106.OBJ_ID
        AND V637.PARAM_ID = 637
        AND V637.IS_DEL = 0
        AND V637.LISTVAL_ID = LV2603.COST

        WHERE L2.PARENT_ID IS NULL
        AND L2.OBJ_TYPE_ID = 2
        AND L2.DATE_DEL IS NULL

        AND (EXISTS(
            SELECT FIRST 1 1
            FROM VALL V2608

            WHERE V2608.OBJ_ID = :I$EQDEMAND_ID
            AND V2608.PARAM_ID = 2608
            AND V2608.IS_DEL = 0
            AND V2608.LISTVAL_ID IN (
                SELECT V2462.LISTVAL_ID
                FROM VALR V644

                JOIN LINKS L302
                ON L302.PARENT_ID = V644.VAL
                AND L302.OBJ_TYPE_ID = 302
                AND L302.DATE_DEL IS NULL

                JOIN VALL V2462
                ON V2462.OBJ_ID = L302.OBJ_ID
                AND V2462.PARAM_ID = 2462
                AND V2462.IS_DEL = 0

                WHERE V644.OBJ_ID = L106.OBJ_ID
                AND V644.PARAM_ID = 644
                AND V644.IS_DEL =0
            )
        )

        OR NOT EXISTS(
            SELECT FIRST 1 1
            FROM VALL V2608

            WHERE V2608.OBJ_ID = :I$EQDEMAND_ID
            AND V2608.PARAM_ID = 2608
            AND V2608.IS_DEL = 0
        ))

        UNION ALL

        SELECT L107.OBJ_ID,
               L107.OBJ_TYPE_ID

        FROM LINKS L2

        JOIN LINKS L105
        ON L105.PARENT_ID = L2.OBJ_ID
        AND L105.OBJ_TYPE_ID = 105
        AND L105.DATE_DEL IS NULL

        JOIN LINKS L107
        ON L107.PARENT_ID = L105.OBJ_ID
        AND L107.OBJ_TYPE_ID = 107
        AND L107.DATE_DEL IS NULL

        LEFT JOIN VAL_GET(L107.OBJ_ID, 647) V647 ON 1=1

        JOIN VALL V2602
        ON V2602.OBJ_ID = :I$EQDEMAND_ID
        AND V2602.PARAM_ID = 2602
        AND V2602.IS_DEL = 0
        AND V2602.LISTVAL_ID = 11325

        JOIN VALS V2606
        ON V2606.OBJ_ID = V2602.OBJ_ID
        AND V2606.PARAM_ID = 2606
        AND V2606.IS_DEL = 0
        AND V2606.VAL LIKE V647.V
        AND V647.V <> ''

        JOIN VALL V2603
        ON V2603.OBJ_ID = V2602.OBJ_ID
        AND V2603.PARAM_ID = 2603
        AND V2603.IS_DEL = 0

        JOIN LISTVALS LV2603
        ON LV2603.LISTVAL_ID = V2603.LISTVAL_ID

        JOIN VALL V646
        ON V646.OBJ_ID = L107.OBJ_ID
        AND V646.PARAM_ID = 646
        AND V646.IS_DEL = 0
        AND V646.LISTVAL_ID = LV2603.COST

        WHERE L2.PARENT_ID IS NULL
        AND L2.OBJ_TYPE_ID = 2
        AND L2.DATE_DEL IS NULL

        AND (EXISTS(
            SELECT FIRST 1 1
            FROM VALL V2608

            WHERE V2608.OBJ_ID = :I$EQDEMAND_ID
            AND V2608.PARAM_ID = 2608
            AND V2608.IS_DEL = 0
            AND V2608.LISTVAL_ID IN (
                SELECT V2462.LISTVAL_ID
                FROM VALR V654

                JOIN LINKS L302
                ON L302.PARENT_ID = V654.VAL
                AND L302.OBJ_TYPE_ID = 302
                AND L302.DATE_DEL IS NULL

                JOIN VALL V2462
                ON V2462.OBJ_ID = L302.OBJ_ID
                AND V2462.PARAM_ID = 2462
                AND V2462.IS_DEL = 0

                WHERE V654.OBJ_ID = L107.OBJ_ID
                AND V654.PARAM_ID = 654
                AND V654.IS_DEL =0
            )
        )

        OR NOT EXISTS(
            SELECT FIRST 1 1
            FROM VALL V2608

            WHERE V2608.OBJ_ID = :I$EQDEMAND_ID
            AND V2608.PARAM_ID = 2608
            AND V2608.IS_DEL = 0
        ))

        INTO :EQ_ID,
             :V$TYPE_ID
    DO
    BEGIN
        SELECT SORT_ORDER
        FROM OBJECT_CAPTION_GET(:EQ_ID)
        INTO :SORT_ORDER;

        SELECT V
        FROM VAL_GET(
            :EQ_ID,
            CASE :V$TYPE_ID
                WHEN 94 THEN 601
                WHEN 95 THEN 627
                WHEN 97 THEN 606
                WHEN 109 THEN 656
                WHEN 106 THEN 639
                WHEN 107 THEN 647
                WHEN 128 THEN 876
            END
        )
        INTO :EQ_NAME;

        SELECT SORT_ORDER
        FROM OBJECT_CAPTION_GET(:EQ_ID)
        INTO :SORT_ORDER;

        IF (V$TYPE_ID IN (94,95,97,109,106,107)) THEN
        BEGIN
            SELECT V
            FROM VAL_GET(
                :EQ_ID,
                CASE :V$TYPE_ID
                    WHEN 94 THEN 603
                    WHEN 95 THEN 605
                    WHEN 97 THEN 607
                    WHEN 109 THEN 657
                    WHEN 106 THEN 640
                    WHEN 107 THEN 648
                END
            )
            INTO :EQ_COUNT;
        END
        ELSE
        BEGIN
            EQ_COUNT = '';
        END

        SELECT V
        FROM VAL_GET(
            :EQ_ID,
            CASE :V$TYPE_ID
                WHEN 94 THEN 634
                WHEN 95 THEN 630
                WHEN 97 THEN 636
                WHEN 109 THEN 659
                WHEN 106 THEN 642
                WHEN 107 THEN 650
                WHEN 128 THEN 878
            END
        )
        INTO :EQ_YEAR;

        IF (V$TYPE_ID IN (97,106,107)) THEN
        BEGIN
            SELECT V
            FROM VAL_GET(
                :EQ_ID,
                CASE :V$TYPE_ID
                    WHEN 97 THEN 643
                    WHEN 106 THEN 644
                    WHEN 107 THEN 654
                END
            )
            INTO :EQ_SUBJECT;
        END
        ELSE
        BEGIN
            EQ_SUBJECT = '';
        END

        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE EINSPECTOR_EQDEMAND_INIT (
    I$EQDEMAND_TYPE_ID BIGINT)
RETURNS (
    EQDEMAND_ID BIGINT,
    EQDEMAND_TYPE_LEVEL1 VARCHAR(1000),
    EQDEMAND_TYPE_LEVEL2 VARCHAR(1000),
    EQDEMAND_TYPE_LEVEL3 VARCHAR(1000),
    EQDEMAND_TYPE_COMPLEX VARCHAR(1000),
    EQDEMAND_NAME VARCHAR(1000),
    EQDEMAND_SUBJECTS VARCHAR(5000))
AS
declare variable V$PARENT_ID bigint;
BEGIN
    IF (I$EQDEMAND_TYPE_ID = 332) THEN
    BEGIN
        V$PARENT_ID = 258;
    END
    ELSE IF (I$EQDEMAND_TYPE_ID = 333) THEN
    BEGIN
        V$PARENT_ID = 3178;
    END
    ELSE IF (I$EQDEMAND_TYPE_ID = 335) THEN
    BEGIN
        V$PARENT_ID = 3216;
    END
    ELSE IF (I$EQDEMAND_TYPE_ID = 337) THEN
    BEGIN
        V$PARENT_ID = 13408;
    END

    FOR
        SELECT L331.OBJ_ID
        FROM LINKS L331

        WHERE L331.PARENT_ID = :V$PARENT_ID
        AND L331.OBJ_TYPE_ID = 331
        AND L331.DATE_DEL IS NULL

        INTO :EQDEMAND_ID
    DO
    BEGIN
        SELECT V
        FROM VAL_GET(:EQDEMAND_ID, 2602)
        INTO :EQDEMAND_TYPE_LEVEL1;

        SELECT V
        FROM VAL_GET(:EQDEMAND_ID, 2603)
        INTO :EQDEMAND_TYPE_LEVEL2;

        SELECT V
        FROM VAL_GET(:EQDEMAND_ID, 2604)
        INTO :EQDEMAND_TYPE_LEVEL3;

        SELECT V
        FROM VAL_GET(:EQDEMAND_ID, 2605)
        INTO :EQDEMAND_TYPE_COMPLEX;

        SELECT V
        FROM VAL_GET(:EQDEMAND_ID, 2606)
        INTO :EQDEMAND_NAME;

        SELECT V
        FROM VAL_GET(:EQDEMAND_ID, 2608)
        INTO :EQDEMAND_SUBJECTS;

        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE EINSPECTOR_EQ_COINCIDE_LIST (
    I$MONITORING_ID BIGINT,
    I$EQDEMAND_TYPE_ID BIGINT)
RETURNS (
    EQDEMAND_ID BIGINT,
    EQDEMAND_TYPE_LEVEL1 VARCHAR(1000),
    EQDEMAND_TYPE_LEVEL2 VARCHAR(1000),
    EQDEMAND_TYPE_LEVEL3 VARCHAR(1000),
    EQDEMAND_TYPE_COMPLEX VARCHAR(1000),
    EQDEMAND_NAME VARCHAR(1000),
    EQDEMAND_SUBJECTS VARCHAR(5000),
    EQ_ID BIGINT,
    EQ_NAME VARCHAR(1000),
    EQ_COUNT VARCHAR(10),
    EQ_YEAR VARCHAR(20),
    EQ_SUBJECT VARCHAR(1000),
    SORT_ORDER DOUBLE PRECISION)
AS
declare variable V$OBJ_ID bigint;
declare variable V$TYPE_ID bigint;
BEGIN
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L

        WHERE L.PARENT_ID = :I$MONITORING_ID
        AND L.OBJ_TYPE_ID = :I$EQDEMAND_TYPE_ID
        AND L.DATE_DEL IS NULL

        INTO :V$OBJ_ID
    DO
    BEGIN
        SELECT I
        FROM VAL_GET(
            :V$OBJ_ID,
            CASE :I$EQDEMAND_TYPE_ID
                WHEN 332 THEN 2645
                WHEN 333 THEN 2647
                WHEN 335 THEN 2648
                WHEN 337 THEN 2651
            END
        )
        INTO :EQDEMAND_ID;

        SELECT I,
               O.TYPE_ID
        FROM VAL_GET(
            :V$OBJ_ID,
            CASE :I$EQDEMAND_TYPE_ID
                WHEN 332 THEN 2646
                WHEN 333 THEN 2649
                WHEN 335 THEN 2650
                WHEN 337 THEN 2652
            END
        ) V
        JOIN OBJECTS O
        ON O.OBJ_ID = V.I
        INTO :EQ_ID,
             :V$TYPE_ID;

        SELECT V
        FROM VAL_GET(:EQDEMAND_ID, 2602)
        INTO :EQDEMAND_TYPE_LEVEL1;

        SELECT V
        FROM VAL_GET(:EQDEMAND_ID, 2603)
        INTO :EQDEMAND_TYPE_LEVEL2;

        SELECT V
        FROM VAL_GET(:EQDEMAND_ID, 2604)
        INTO :EQDEMAND_TYPE_LEVEL3;

        SELECT V
        FROM VAL_GET(:EQDEMAND_ID, 2605)
        INTO :EQDEMAND_TYPE_COMPLEX;

        SELECT V
        FROM VAL_GET(:EQDEMAND_ID, 2606)
        INTO :EQDEMAND_NAME;

        SELECT V
        FROM VAL_GET(:EQDEMAND_ID, 2608)
        INTO :EQDEMAND_SUBJECTS;

        SELECT V
        FROM VAL_GET(
            :EQ_ID,
            CASE :V$TYPE_ID
                WHEN 94 THEN 601
                WHEN 95 THEN 627
                WHEN 97 THEN 606
                WHEN 109 THEN 656
                WHEN 106 THEN 639
                WHEN 107 THEN 647
                WHEN 128 THEN 876
            END
        )
        INTO :EQ_NAME;

        SELECT SORT_ORDER
        FROM OBJECT_CAPTION_GET(:EQ_ID)
        INTO :SORT_ORDER;

        IF (V$TYPE_ID IN (94,95,97,109,106,107)) THEN
        BEGIN
            SELECT V
            FROM VAL_GET(
                :EQ_ID,
                CASE :V$TYPE_ID
                    WHEN 94 THEN 603
                    WHEN 95 THEN 605
                    WHEN 97 THEN 607
                    WHEN 109 THEN 657
                    WHEN 106 THEN 640
                    WHEN 107 THEN 648
                END
            )
            INTO :EQ_COUNT;
        END
        ELSE
        BEGIN
            EQ_COUNT = '';
        END

        SELECT V
        FROM VAL_GET(
            :EQ_ID,
            CASE :V$TYPE_ID
                WHEN 94 THEN 634
                WHEN 95 THEN 630
                WHEN 97 THEN 636
                WHEN 109 THEN 659
                WHEN 106 THEN 642
                WHEN 107 THEN 650
                WHEN 128 THEN 878
            END
        )
        INTO :EQ_YEAR;

        IF (V$TYPE_ID IN (97,106,107)) THEN
        BEGIN
            SELECT V
            FROM VAL_GET(
                :EQ_ID,
                CASE :V$TYPE_ID
                    WHEN 97 THEN 643
                    WHEN 106 THEN 644
                    WHEN 107 THEN 654
                END
            )
            INTO :EQ_SUBJECT;
        END
        ELSE
        BEGIN
            EQ_SUBJECT = '';
        END

        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE EINSPECTOR_ROOMDEMAND_ADD (
    I$ROOMDEMAND_TYPE_ID BIGINT,
    I$MONITORING_ID BIGINT,
    I$ROOM_ID BIGINT,
    I$ROOMDEMAND_ID BIGINT)
AS
declare variable V$STR varchar(4000);
declare variable V$STR2 varchar(4000);
declare variable V$I bigint;
declare variable V$F double precision;
declare variable V$OBJ_ID bigint;
declare variable V$BUILDING_ID bigint;
declare variable V$BLOB_ID bigint;
declare variable V$REGION varchar(255);
declare variable V$DISTRICT varchar(255);
declare variable V$TOWN varchar(255);
declare variable V$SETTLEMENT varchar(255);
declare variable V$STREET varchar(255);
declare variable V$HOUSE varchar(10);
declare variable V$CORP varchar(10);
declare variable V$LITER varchar(10);
declare variable V$FLAT varchar(10);
declare variable V$POST_INDEX varchar(20);
declare variable V$OCATD varchar(11);
declare variable V$HOUSEGUID varchar(36);
declare variable V$STREETGUID varchar(36);
BEGIN

    -- Проверяем, нет ли такого помещения уже в списке в комбинации (тип, помещение, требование)
    SELECT FIRST 1 L.OBJ_ID
    FROM LINKS L
    -- требование
    JOIN VALR V2592 ON V2592.OBJ_ID = L.OBJ_ID AND V2592.PARAM_ID IN (2592, 2593, 2594, 2595) AND V2592.IS_DEL = 0 AND V2592.VAL = :I$ROOMDEMAND_ID
    -- помещение
    JOIN VALR V2596 ON V2596.OBJ_ID = L.OBJ_ID AND V2596.PARAM_ID IN (2596, 2597, 2598, 2599) AND V2596.IS_DEL = 0 AND V2596.VAL = :I$ROOM_ID
    -- тип
    WHERE L.PARENT_ID = :I$MONITORING_ID AND L.OBJ_TYPE_ID = :I$ROOMDEMAND_TYPE_ID AND L.DATE_DEL IS NOT NULL
    INTO :V$OBJ_ID;

    IF(V$OBJ_ID IS NOT NULL) THEN
    BEGIN
        -- Восстанавливаем из ранее удаленных
        UPDATE LINKS
        SET DATE_DEL = NULL, DATE_INS = CURRENT_TIMESTAMP
        WHERE PARENT_ID = :I$MONITORING_ID AND OBJ_ID = :V$OBJ_ID;
    END
    ELSE
    BEGIN
        -- Создаем новый объект
        SELECT OBJ_ID
        FROM OBJECT_ADD(:I$MONITORING_ID, :I$ROOMDEMAND_TYPE_ID)
        INTO :V$OBJ_ID;
        -- требование
        SELECT BLOB_ID
        FROM VAL_ADD(CASE :I$ROOMDEMAND_TYPE_ID WHEN 325 THEN 2592 WHEN 326 THEN 2593 WHEN 328 THEN 2594 WHEN 329 THEN 2595 END, :V$OBJ_ID, :I$ROOMDEMAND_ID)
        INTO :V$BLOB_ID;
        -- помещение
        SELECT BLOB_ID
        FROM VAL_ADD(CASE :I$ROOMDEMAND_TYPE_ID WHEN 325 THEN 2596 WHEN 326 THEN 2597 WHEN 328 THEN 2598 WHEN 329 THEN 2599 END, :V$OBJ_ID, :I$ROOM_ID)
        INTO :V$BLOB_ID;
    END

    -- Обновляем текстовую часть
    SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$ROOMDEMAND_ID) INTO :V$STR;

    SELECT BLOB_ID
    FROM VAL_ADD(CASE :I$ROOMDEMAND_TYPE_ID WHEN 325 THEN 2555 WHEN 326 THEN 2562 WHEN 328 THEN 2572 WHEN 329 THEN 2582 END, :V$OBJ_ID, :V$STR)
    INTO :V$BLOB_ID;

    V$STR2 = '';

    FOR
        SELECT R.VAL
        FROM LINKS L322
        JOIN VALL V2553 ON V2553.OBJ_ID = L322.OBJ_ID AND V2553.PARAM_ID = 2553 AND V2553.IS_DEL = 0
        JOIN LISTVALS LV2553 ON LV2553.LISTVAL_ID = V2553.LISTVAL_ID
        LEFT JOIN RES_GET(LV2553.RES_ID, 'RU') R ON 1=1
        WHERE L322.PARENT_ID = :I$ROOMDEMAND_ID AND L322.OBJ_TYPE_ID = 322 AND L322.DATE_DEL IS NULL
        ORDER BY LV2553.SORT_ORDER
        INTO :V$STR
    DO
    BEGIN
        IF (V$STR2 <> '') THEN V$STR2 = V$STR2 || '; ';
        V$STR2 = V$STR2 || V$STR;
    END

    IF (V$STR2 <> '') THEN
    BEGIN
        SELECT BLOB_ID
        FROM VAL_ADD(CASE :I$ROOMDEMAND_TYPE_ID WHEN 325 THEN 2600 WHEN 326 THEN 2563 WHEN 328 THEN 2573 WHEN 329 THEN 2583 END, :V$OBJ_ID, :V$STR2)
        INTO :V$BLOB_ID;
    END

    V$STR2 = '';

    FOR
        SELECT C.CAPTION
        FROM LINKS L323
        JOIN VALR V2554 ON V2554.OBJ_ID = L323.OBJ_ID AND V2554.PARAM_ID = 2554 AND V2554.IS_DEL = 0
        LEFT JOIN OBJECT_CAPTION_GET(V2554.VAL) C ON 1=1
        WHERE L323.PARENT_ID = :I$ROOMDEMAND_ID AND L323.OBJ_TYPE_ID = 323 AND L323.DATE_DEL IS NULL
        ORDER BY C.SORT_ORDER
        INTO :V$STR
    DO
    BEGIN
        IF(CHAR_LENGTH(V$STR2) + CHAR_LENGTH(V$STR) < 3998) THEN
        BEGIN
            IF (V$STR2 <> '') THEN V$STR2 = V$STR2 || '; ';
            V$STR2 = V$STR2 || V$STR;
        END
    END

    IF (V$STR2 <> '' AND I$ROOMDEMAND_TYPE_ID <> 325) THEN
    BEGIN
        -- только если заданы предметы
        SELECT BLOB_ID
        FROM VAL_ADD(CASE :I$ROOMDEMAND_TYPE_ID WHEN 326 THEN 2564 WHEN 328 THEN 2574 WHEN 329 THEN 2584 END, :V$OBJ_ID, :V$STR2)
        INTO :V$BLOB_ID;
    END

    SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$ROOM_ID) INTO :V$STR;

    SELECT BLOB_ID
    FROM VAL_ADD(CASE :I$ROOMDEMAND_TYPE_ID WHEN 325 THEN 2556 WHEN 326 THEN 2565 WHEN 328 THEN 2575 WHEN 329 THEN 2585 END, :V$OBJ_ID, :V$STR)
    INTO :V$BLOB_ID;

    -- Назначение кабинета (наличие)
    SELECT I FROM VAL_GET(:I$ROOM_ID, 526) INTO :V$I;
    IF (V$I > 0) THEN
    BEGIN
        SELECT BLOB_ID
        FROM VAL_ADD(CASE :I$ROOMDEMAND_TYPE_ID WHEN 325 THEN 2557 WHEN 326 THEN 2566 WHEN 328 THEN 2576 WHEN 329 THEN 2586 END, :V$OBJ_ID, :V$I)
        INTO :V$BLOB_ID;
    END

    -- Предметы (наличие)
    V$STR2 = '';
    FOR
        SELECT V376.VAL
        FROM LINKS L
        JOIN VALS V376 ON V376.OBJ_ID = L.OBJ_ID AND V376.PARAM_ID = 376 AND V376.IS_DEL = 0
        WHERE L.PARENT_ID = :I$ROOM_ID AND L.OBJ_TYPE_ID = 51 AND L.DATE_DEL IS NULL
        INTO :V$STR
    DO
    BEGIN
        IF(CHAR_LENGTH(V$STR2) + CHAR_LENGTH(V$STR) < 3998) THEN
        BEGIN
            IF (V$STR2 <> '') THEN V$STR2 = V$STR2 || '; ';
            V$STR2 = V$STR2 || V$STR;
        END
    END
    IF (I$ROOMDEMAND_TYPE_ID <> 325) THEN
    BEGIN
        SELECT BLOB_ID
        FROM VAL_ADD(CASE :I$ROOMDEMAND_TYPE_ID WHEN 326 THEN 2567 WHEN 328 THEN 2577 WHEN 329 THEN 2587 END, :V$OBJ_ID, :V$STR2)
        INTO :V$BLOB_ID;
    END

    -- Адрес помещения (наличие)
    FOR
        SELECT ADR.REGION, ADR.DISTRICT, ADR.TOWN, ADR.SETTLEMENT, ADR.STREET, ADR.HOUSE, ADR.CORP, ADR.LITER, ADR.FLAT, ADR.POST_INDEX, ADR.OCATD,
            ADR.HOUSEGUID, ADR.STREETGUID, LP16.PARENT_ID
        FROM LINKS LP16
        LEFT JOIN ADR_GET(420, LP16.PARENT_ID) ADR ON 1=1
        WHERE LP16.OBJ_ID = :I$ROOM_ID AND LP16.PARENT_TYPE_ID = 16 AND LP16.DATE_DEL IS NULL
        INTO :V$REGION, :V$DISTRICT, :V$TOWN, :V$SETTLEMENT, :V$STREET, :V$HOUSE, :V$CORP, :V$LITER, :V$FLAT, :V$POST_INDEX, :V$OCATD,
            :V$HOUSEGUID, :V$STREETGUID, :V$BUILDING_ID
    DO
    BEGIN
        SELECT BLOB_ID
        FROM ADR_ADD(CASE :I$ROOMDEMAND_TYPE_ID WHEN 325 THEN 2558 WHEN 326 THEN 2568 WHEN 328 THEN 2578 WHEN 329 THEN 2588 END,
            :V$OBJ_ID, :V$REGION, :V$DISTRICT, :V$TOWN, :V$SETTLEMENT, :V$STREET, :V$HOUSE, :V$LITER, :V$CORP, :V$FLAT, :V$POST_INDEX, :V$OCATD,
            :V$HOUSEGUID, :V$STREETGUID
        )
        INTO :V$BLOB_ID;

        -- Форма владения зданием
        SELECT I FROM VAL_GET(:V$BUILDING_ID, 504) INTO :V$I;
    
        IF (V$I > 0) THEN
        BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD( CASE :I$ROOMDEMAND_TYPE_ID WHEN 325 THEN 2559 WHEN 326 THEN 2569 WHEN 328 THEN 2579 WHEN 329 THEN 2589 END, :V$OBJ_ID, :V$I)
            INTO :V$BLOB_ID;
        END

        -- Правоустанавливающий документ
        SELECT I FROM VAL_GET(:V$BUILDING_ID, 505) INTO :V$I;
    
        IF (V$I > 0) THEN
        BEGIN
            SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$I) INTO :V$STR;

            SELECT BLOB_ID
            FROM VAL_ADD(CASE :I$ROOMDEMAND_TYPE_ID WHEN 325 THEN 2560 WHEN 326 THEN 2570 WHEN 328 THEN 2580 WHEN 329 THEN 2590 END, :V$OBJ_ID, :V$STR)
            INTO :V$BLOB_ID;
        END

    END

    -- Площадь
    SELECT F FROM VAL_GET(:I$ROOM_ID, 533) INTO :V$F;
    
    SELECT BLOB_ID
    FROM VAL_ADD(CASE :I$ROOMDEMAND_TYPE_ID WHEN 325 THEN 2561 WHEN 326 THEN 2571 WHEN 328 THEN 2581 WHEN 329 THEN 2591 END, :V$OBJ_ID, :V$F)
    INTO :V$BLOB_ID;

END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE EINSPECTOR_ROOMDEMAND_CLEAR (
    I$MONITORING_ID BIGINT,
    I$ROOMDEMAND_TYPE_ID BIGINT)
AS
BEGIN
    UPDATE LINKS
    SET DATE_DEL = CURRENT_TIMESTAMP
    WHERE PARENT_ID = :I$MONITORING_ID AND OBJ_TYPE_ID = :I$ROOMDEMAND_TYPE_ID AND DATE_DEL IS NULL;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE EINSPECTOR_ROOMDEMAND_COINCIDE (
    I$ROOMDEMAND_ID BIGINT,
    I$ROOMDEMAND_TYPE_ID BIGINT)
RETURNS (
    ROOM_ID BIGINT,
    ROOM_NAME VARCHAR(1000),
    ROOM_TYPE VARCHAR(1000),
    ROOM_SUBJECTS VARCHAR(4000),
    ROOM_ADDRESS VARCHAR(1000),
    ROOM_OWNERSHIP_TYPE VARCHAR(1000),
    ROOM_PERIOD_OF_VALIDITY VARCHAR(1000),
    ROOM_SQUARE FLOAT,
    SORT_ORDER DOUBLE PRECISION)
AS
declare variable V$BUILDING_ID bigint;
declare variable V$STR varchar(1000);
declare variable V$LEVEL_ID bigint;
BEGIN
    IF (I$ROOMDEMAND_TYPE_ID = 325) THEN
    BEGIN
        -- Общие требования к помещениям
        V$LEVEL_ID = NULL;
    END
    ELSE IF (I$ROOMDEMAND_TYPE_ID = 326) THEN
    BEGIN
        -- Начальное общее образование
        V$LEVEL_ID = 5339;
    END
    ELSE IF (I$ROOMDEMAND_TYPE_ID = 328) THEN
    BEGIN
        -- Основное общее образование
        V$LEVEL_ID = 5341;
    END
    ELSE IF (I$ROOMDEMAND_TYPE_ID = 329) THEN
    BEGIN
        -- Среднее образование
        V$LEVEL_ID = 5343;
    END
    -- Цикл по имеющимся помещениям
    FOR
        SELECT L61.OBJ_ID, L16.OBJ_ID, SUBSTRING(C.CAPTION FROM 1 FOR 1000), C.SORT_ORDER, SUBSTRING(R526.VAL FROM 1 FOR 1000)
        -- ОУ
        FROM LINKS L2
        -- Здания
        JOIN LINKS L73 ON L73.PARENT_ID = L2.OBJ_ID AND L73.OBJ_TYPE_ID = 73 AND L73.DATE_DEL IS NULL
        -- Здание
        JOIN LINKS L16 ON L16.PARENT_ID = L73.OBJ_ID AND L16.OBJ_TYPE_ID = 16 AND L16.DATE_DEL IS NULL
        -- Помещение
        JOIN LINKS L61 ON L61.PARENT_ID = L16.OBJ_ID AND L61.OBJ_TYPE_ID = 61 AND L61.DATE_DEL IS NULL
        -- Назначение помещения
        JOIN VALL V526 ON V526.OBJ_ID = L61.OBJ_ID AND V526.PARAM_ID = 526 AND V526.IS_DEL = 0
        JOIN LISTVALS LV526 ON LV526.LISTVAL_ID = V526.LISTVAL_ID
        JOIN RES R526 ON R526.RES_ID = LV526.RES_ID AND R526.LANG_CODE = 'RU'
        -- Наименование помещения
        LEFT JOIN OBJECT_CAPTION_GET(L61.OBJ_ID) C ON 1=1
        WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
        AND EXISTS(
            -- В шаблоне есть такое назначение помещения
            SELECT FIRST 1 1
            FROM LINKS L322
            JOIN VALL V2553 ON V2553.OBJ_ID = L322.OBJ_ID AND V2553.PARAM_ID = 2553 AND V2553.IS_DEL = 0 AND V2553.LISTVAL_ID = V526.LISTVAL_ID
            WHERE L322.PARENT_ID = :I$ROOMDEMAND_ID AND L322.OBJ_TYPE_ID = 322 AND L322.DATE_DEL IS NULL
        )
        AND (EXISTS(
                -- В шаблоне есть такой предмет
                SELECT FIRST 1 1
                FROM LINKS L323
                JOIN VALR V2554 ON V2554.OBJ_ID = L323.OBJ_ID AND V2554.PARAM_ID = 2554 AND V2554.IS_DEL = 0 AND V2554.VAL IN (SELECT L51.OBJ_ID FROM LINKS L51 WHERE L51.PARENT_ID = L61.OBJ_ID AND L51.OBJ_TYPE_ID = 51 AND L51.DATE_DEL IS NULL)
                WHERE L323.PARENT_ID = :I$ROOMDEMAND_ID AND L323.OBJ_TYPE_ID = 323 AND L323.DATE_DEL IS NULL
            )
            OR NOT EXISTS(
                -- Или вообще нет предметов в шаблоне
                SELECT FIRST 1 1
                FROM LINKS L323
                JOIN VALR V2554 ON V2554.OBJ_ID = L323.OBJ_ID AND V2554.PARAM_ID = 2554 AND V2554.IS_DEL = 0
                WHERE L323.PARENT_ID = :I$ROOMDEMAND_ID AND L323.OBJ_TYPE_ID = 323 AND L323.DATE_DEL IS NULL
            )
        )
        AND (:V$LEVEL_ID IS NULL
            OR (:V$LEVEL_ID IS NOT NULL AND :V$LEVEL_ID IN (
                SELECT V1594.LISTVAL_ID
                FROM LINKS L57
                JOIN VALL V1594 ON V1594.OBJ_ID = L57.OBJ_ID AND V1594.PARAM_ID = 1594 AND V1594.IS_DEL = 0
                WHERE L57.PARENT_ID = L61.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
            ))
        )
        INTO :ROOM_ID, :V$BUILDING_ID, :ROOM_NAME, :SORT_ORDER, :ROOM_TYPE
    DO
    BEGIN

        -- Проверяем соответствие помещения шаблону

        SELECT SUBSTRING(V FROM 1 FOR 1000) FROM VAL_GET(:V$BUILDING_ID, 420) INTO :ROOM_ADDRESS;
        SELECT SUBSTRING(V FROM 1 FOR 1000) FROM VAL_GET(:V$BUILDING_ID, 504) INTO :ROOM_OWNERSHIP_TYPE;
        SELECT SUBSTRING(V FROM 1 FOR 1000) FROM VAL_GET(:V$BUILDING_ID, 505) INTO :ROOM_PERIOD_OF_VALIDITY;
        SELECT F FROM VAL_GET(:ROOM_ID, 533) INTO :ROOM_SQUARE;

        -- Список предметов, закрепленных за данным помещением
        ROOM_SUBJECTS = '';
        FOR
            SELECT C.CAPTION
            FROM LINKS L51
            LEFT JOIN OBJECT_CAPTION_GET(L51.OBJ_ID) C ON 1=1
            WHERE L51.PARENT_ID = :ROOM_ID AND L51.OBJ_TYPE_ID = 51 AND L51.DATE_DEL IS NULL
            ORDER BY C.SORT_ORDER
            INTO :V$STR
        DO
        BEGIN
            IF((CHAR_LENGTH(ROOM_SUBJECTS) + CHAR_LENGTH(V$STR)) < 3998) THEN
            BEGIN
                IF (ROOM_SUBJECTS <> '') THEN ROOM_SUBJECTS = ROOM_SUBJECTS || '; ';
                ROOM_SUBJECTS = ROOM_SUBJECTS || V$STR;
            END
        END

        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE EINSPECTOR_ROOMDEMAND_INIT (
    I$ROOMDEMAND_TYPE_ID BIGINT)
RETURNS (
    ROOMDEMAND_ID BIGINT,
    ROOMDEMAND_NAME VARCHAR(1000),
    ROOMDEMAND_ROOM_TYPE VARCHAR(5000),
    ROOMDEMAND_SUBJECTS VARCHAR(5000))
AS
DECLARE VARIABLE V$STR VARCHAR(1000);
DECLARE VARIABLE V$PARENT_ID BIGINT;
BEGIN
    -- Внимание !!!
    -- Учебные планы, ID которых используются ниже, помечены в дереве как удаленные 16.05.2025
    -- Вероятно нужно перевесить настройки помещений в более свежие шаблоны, либо вообще в другое место дерева

    IF (I$ROOMDEMAND_TYPE_ID = 325) THEN
    BEGIN
        -- Общие требования к помещениям
        V$PARENT_ID = 34105;
    END
    ELSE IF (I$ROOMDEMAND_TYPE_ID = 326) THEN
    BEGIN
        -- Начальное общее образование ФГОС
        V$PARENT_ID = 34106;
    END
    ELSE IF (I$ROOMDEMAND_TYPE_ID = 328) THEN
    BEGIN
        -- Основное общее образование ФГУП-2004
        V$PARENT_ID = 34108;
    END
    ELSE IF (I$ROOMDEMAND_TYPE_ID = 329) THEN
    BEGIN
        -- Среднее образование. УП универсального обучения
        V$PARENT_ID = 34109;
    END

    FOR
        -- Выборка по прописанным в шаблоне типам помещений
        SELECT L320.OBJ_ID, V2550.VAL
        FROM LINKS L320
        JOIN VALS V2550 ON V2550.OBJ_ID = L320.OBJ_ID AND V2550.PARAM_ID = 2550 AND V2550.IS_DEL = 0
        WHERE L320.PARENT_ID = :V$PARENT_ID AND L320.OBJ_TYPE_ID = 320 AND L320.DATE_DEL IS NULL
        INTO :ROOMDEMAND_ID, :ROOMDEMAND_NAME
    DO
    BEGIN
        ROOMDEMAND_ROOM_TYPE = '';

        FOR
            SELECT R.VAL
            -- Основной цикл по назначениям помещений
            FROM LINKS L322
            -- Собственно само назначение
            JOIN VALL V2553 ON V2553.OBJ_ID = L322.OBJ_ID AND V2553.PARAM_ID = 2553 AND V2553.IS_DEL = 0
            JOIN LISTVALS LV2553 ON LV2553.LISTVAL_ID = V2553.LISTVAL_ID
            LEFT JOIN RES_GET(LV2553.RES_ID, 'RU') R ON 1=1
            WHERE L322.PARENT_ID = :ROOMDEMAND_ID AND L322.OBJ_TYPE_ID = 322 AND L322.DATE_DEL IS NULL
            ORDER BY LV2553.SORT_ORDER
            INTO :V$STR
        DO
        BEGIN
            IF (ROOMDEMAND_ROOM_TYPE <> '') THEN
            BEGIN
                ROOMDEMAND_ROOM_TYPE = ROOMDEMAND_ROOM_TYPE || '; ';
            END
            ROOMDEMAND_ROOM_TYPE = ROOMDEMAND_ROOM_TYPE || V$STR;
        END

        ROOMDEMAND_SUBJECTS = '';

        FOR
            SELECT C.CAPTION
            -- Предметы по учебному кабинету
            FROM LINKS L323
            JOIN VALR V2554 ON V2554.OBJ_ID = L323.OBJ_ID AND V2554.PARAM_ID = 2554 AND V2554.IS_DEL = 0
            LEFT JOIN OBJECT_CAPTION_GET(V2554.VAL) C ON 1=1
            WHERE L323.PARENT_ID = :ROOMDEMAND_ID AND L323.OBJ_TYPE_ID = 323 AND L323.DATE_DEL IS NULL
            ORDER BY C.SORT_ORDER
            INTO :V$STR
        DO
        BEGIN
            IF (ROOMDEMAND_SUBJECTS <> '') THEN
            BEGIN
                ROOMDEMAND_SUBJECTS = ROOMDEMAND_SUBJECTS || '; ';
            END
            ROOMDEMAND_SUBJECTS = ROOMDEMAND_SUBJECTS || V$STR;
        END

        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE EMPLOYEES_LIST (
    I$OBJ_ID BIGINT,
    I$MODE SMALLINT = 0)
RETURNS (
    PARENT_ID BIGINT,
    OBJ_ID BIGINT,
    OBJ_TYPE_ID BIGINT,
    CAPTION VARCHAR(1000))
AS
begin

  FOR
    SELECT L14.OBJ_ID, L14.OBJ_TYPE_ID, C.CAPTION
    FROM LINKS L14
    LEFT JOIN OBJECT_CAPTION_GET(L14.OBJ_ID) C ON 1 =  1
    WHERE L14.PARENT_ID = :I$OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
    ORDER BY 3
    INTO :OBJ_ID, :OBJ_TYPE_ID, :CAPTION
  DO
  BEGIN
    SUSPEND;
  END

  FOR
    SELECT L211.OBJ_ID, L211.OBJ_TYPE_ID, C.CAPTION
    FROM LINKS L211
    LEFT JOIN OBJECT_CAPTION_GET(L211.OBJ_ID) C ON 1 =  1
    WHERE L211.PARENT_ID = :I$OBJ_ID AND L211.OBJ_TYPE_ID = 211 AND L211.DATE_DEL IS NULL
    ORDER BY L211.COST, C.CAPTION
    INTO :OBJ_ID, :OBJ_TYPE_ID, :CAPTION
  DO
  BEGIN
    PARENT_ID = NULL;
    SUSPEND;
    PARENT_ID = OBJ_ID;

    FOR
      SELECT L14.OBJ_ID, L14.OBJ_TYPE_ID, C.CAPTION
      FROM LINKS L14
      LEFT JOIN OBJECT_CAPTION_GET(L14.OBJ_ID) C ON 1 =  1
      WHERE L14.PARENT_ID = :PARENT_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
      ORDER BY 3
      INTO :OBJ_ID, :OBJ_TYPE_ID, :CAPTION
    DO
    BEGIN
      SUSPEND;
    END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE EMPLOYEE_COURSE_IMPORT (
    I$SCHOOL_ID BIGINT,
    I$EMPLOYEE_ID BIGINT,
    I$TEACHING_ORGANIZATION VARCHAR(1000),
    I$TEACHING_ORGANIZATION_SHORT VARCHAR(1000),
    I$STUDY_GROUP VARCHAR(1000),
    I$STUDY_COURSE VARCHAR(1000),
    I$EDUCATION_TYPE VARCHAR(255),
    I$COURSE_CATEGORY VARCHAR(255),
    I$TOTAL_HOURS INTEGER,
    I$DOCUMENT_TYPE BIGINT,
    I$DOCUMENT_SERIES VARCHAR(20),
    I$DOCUMENT_NUMBER VARCHAR(50),
    I$DOCUMENT_ISSUE_DATE DATE,
    I$USER_ID BIGINT)
RETURNS (
    STATUS INTEGER,
    MSG VARCHAR(1000))
AS
declare variable V$DOCUMENT_ID bigint;
declare variable V$BLOB_ID bigint;
declare variable V$COURSE_CATEGORY_ID bigint;
declare variable V$LANG_CODE varchar(2);
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :V$LANG_CODE;
    STATUS = 1;
    IF (NOT EXISTS(
        SELECT FIRST 1 1
        FROM LINKS
        WHERE PARENT_ID = :I$SCHOOL_ID
        AND OBJ_ID = :I$EMPLOYEE_ID
        AND DATE_DEL IS NULL)) THEN
    BEGIN
        STATUS = 0;
        MSG = 'Сотрудник не найден!';
    END
    IF (STATUS = 1) THEN
    BEGIN
/*        SELECT LISTVAL_ID
        FROM LISTVALS LV
        LEFT JOIN RES_GET(LV.RES_ID, :V$LANG_CODE) R
        ON 1=1
        WHERE R.VAL LIKE :I$TEACHING_ORGANIZATION
        INTO :V$TEACHING_ORGANIZATION_ID;*/

        SELECT LISTVAL_ID
        FROM LISTVALS LV
        LEFT JOIN RES_GET(LV.RES_ID, :V$LANG_CODE) R
        ON 1=1
        WHERE R.VAL LIKE :I$COURSE_CATEGORY
        INTO :V$COURSE_CATEGORY_ID;

        IF (I$EDUCATION_TYPE = 'Дополнительная образовательная программа профессиональной переподготовки') THEN
        BEGIN
            IF (NOT EXISTS(
                SELECT FIRST 1 1
                FROM LINKS L35

                JOIN VALS V298
                ON V298.OBJ_ID = L35.OBJ_ID
                AND V298.PARAM_ID = 298
                AND V298.IS_DEL = 0
                AND V298.VAL = :I$DOCUMENT_SERIES

                JOIN VALS V299
                ON V299.OBJ_ID = L35.OBJ_ID
                AND V299.PARAM_ID = 299
                AND V299.IS_DEL = 0
                AND V299.VAL = :I$DOCUMENT_NUMBER

                JOIN VALD V300
                ON V300.OBJ_ID = L35.OBJ_ID
                AND V300.PARAM_ID = 300
                AND V300.IS_DEL = 0
                AND V300.VAL = :I$DOCUMENT_ISSUE_DATE

                WHERE L35.PARENT_ID = :I$EMPLOYEE_ID
                AND L35.OBJ_TYPE_ID = 35
                AND L35.DATE_DEL IS NULL
            )) THEN
            BEGIN
                SELECT OBJ_ID
                FROM OBJECT_ADD(:I$EMPLOYEE_ID, 35, NULL, NULL, :I$USER_ID)
                INTO :V$DOCUMENT_ID;

                IF (I$DOCUMENT_TYPE IS NOT NULL) THEN
                BEGIN
                    SELECT BLOB_ID
                    FROM VAL_ADD(297, :V$DOCUMENT_ID, :I$DOCUMENT_TYPE, :I$USER_ID)
                    INTO :V$BLOB_ID;
                END

                IF (I$DOCUMENT_SERIES IS NOT NULL) THEN
                BEGIN
                    SELECT BLOB_ID
                    FROM VAL_ADD(298, :V$DOCUMENT_ID, :I$DOCUMENT_SERIES, :I$USER_ID)
                    INTO :V$BLOB_ID;
                END

                IF (I$DOCUMENT_NUMBER IS NOT NULL) THEN
                BEGIN
                    SELECT BLOB_ID
                    FROM VAL_ADD(299, :V$DOCUMENT_ID, :I$DOCUMENT_NUMBER, :I$USER_ID)
                    INTO :V$BLOB_ID;
                END

                IF (I$DOCUMENT_ISSUE_DATE IS NOT NULL) THEN
                BEGIN
                    SELECT BLOB_ID
                    FROM VAL_ADD(300, :V$DOCUMENT_ID, :I$DOCUMENT_ISSUE_DATE, :I$USER_ID)
                    INTO :V$BLOB_ID;
                END

                IF (I$STUDY_COURSE IS NOT NULL) THEN
                BEGIN
                    SELECT BLOB_ID
                    FROM VAL_ADD(301, :V$DOCUMENT_ID, :I$STUDY_COURSE, :I$USER_ID)
                    INTO :V$BLOB_ID;
                END

                IF (I$COURSE_CATEGORY IS NOT NULL) THEN
                BEGIN
                    SELECT BLOB_ID
                    FROM VAL_ADD(302, :V$DOCUMENT_ID, :I$COURSE_CATEGORY, :I$USER_ID)
                    INTO :V$BLOB_ID;
                END

                IF (I$TEACHING_ORGANIZATION IS NOT NULL) THEN
                BEGIN
                    SELECT BLOB_ID
                    FROM VAL_ADD(296, :V$DOCUMENT_ID, :I$TEACHING_ORGANIZATION, :I$USER_ID)
                    INTO :V$BLOB_ID;    
                END
                IF (I$TEACHING_ORGANIZATION_SHORT IS NOT NULL) THEN
                BEGIN
                    SELECT BLOB_ID
                    FROM VAL_ADD(2334, :V$DOCUMENT_ID, :I$TEACHING_ORGANIZATION_SHORT, :I$USER_ID)
                    INTO :V$BLOB_ID;    
                END
            END
            ELSE
            BEGIN
                MSG = 'Запись о данной переподготовке уже существует. Пропущено.';
            END
        END
        ELSE IF (I$EDUCATION_TYPE = 'Дополнительная образовательная программа повышения квалификации') THEN
        BEGIN
            IF (NOT EXISTS(
                SELECT FIRST 1 1
                FROM LINKS L36

                JOIN VALS V308
                ON V308.OBJ_ID = L36.OBJ_ID
                AND V308.PARAM_ID = 308
                AND V308.IS_DEL = 0
                AND V308.VAL = :I$DOCUMENT_SERIES

                JOIN VALS V309
                ON V309.OBJ_ID = L36.OBJ_ID
                AND V309.PARAM_ID = 309
                AND V309.IS_DEL = 0
                AND V309.VAL = :I$DOCUMENT_NUMBER

                JOIN VALD V310
                ON V310.OBJ_ID = L36.OBJ_ID
                AND V310.PARAM_ID = 310
                AND V310.IS_DEL = 0
                AND V310.VAL = :I$DOCUMENT_ISSUE_DATE

                WHERE L36.PARENT_ID = :I$EMPLOYEE_ID
                AND L36.OBJ_TYPE_ID = 36
                AND L36.DATE_DEL IS NULL
            )) THEN
            BEGIN
                SELECT OBJ_ID
                FROM OBJECT_ADD(:I$EMPLOYEE_ID, 36, NULL, NULL, :I$USER_ID)
                INTO :V$DOCUMENT_ID;

                IF (I$DOCUMENT_TYPE IS NOT NULL) THEN
                BEGIN
                    SELECT BLOB_ID
                    FROM VAL_ADD(307, :V$DOCUMENT_ID, :I$DOCUMENT_TYPE, :I$USER_ID)
                    INTO :V$BLOB_ID;
                END

                IF (I$DOCUMENT_SERIES IS NOT NULL) THEN
                BEGIN
                    SELECT BLOB_ID
                    FROM VAL_ADD(308, :V$DOCUMENT_ID, :I$DOCUMENT_SERIES, :I$USER_ID)
                    INTO :V$BLOB_ID;
                END

                IF (I$DOCUMENT_NUMBER IS NOT NULL) THEN
                BEGIN
                    SELECT BLOB_ID
                    FROM VAL_ADD(309, :V$DOCUMENT_ID, :I$DOCUMENT_NUMBER, :I$USER_ID)
                    INTO :V$BLOB_ID;
                END

                IF (I$DOCUMENT_ISSUE_DATE IS NOT NULL) THEN
                BEGIN
                    SELECT BLOB_ID
                    FROM VAL_ADD(310, :V$DOCUMENT_ID, :I$DOCUMENT_ISSUE_DATE, :I$USER_ID)
                    INTO :V$BLOB_ID;
                END

                IF (I$STUDY_COURSE IS NOT NULL) THEN
                BEGIN
                    SELECT BLOB_ID
                    FROM VAL_ADD(305, :V$DOCUMENT_ID, :I$STUDY_COURSE, :I$USER_ID)
                    INTO :V$BLOB_ID;
                END

                IF (V$COURSE_CATEGORY_ID IS NOT NULL) THEN
                BEGIN
                    SELECT BLOB_ID
                    FROM VAL_ADD(1024, :V$DOCUMENT_ID, :V$COURSE_CATEGORY_ID, :I$USER_ID)
                    INTO :V$BLOB_ID;
                END

                IF (I$TOTAL_HOURS IS NOT NULL) THEN
                BEGIN
                    SELECT BLOB_ID
                    FROM VAL_ADD(306, :V$DOCUMENT_ID, :I$TOTAL_HOURS, :I$USER_ID)
                    INTO :V$BLOB_ID;
                END

                IF (I$TEACHING_ORGANIZATION IS NOT NULL) THEN
                BEGIN
                    SELECT BLOB_ID
                    FROM VAL_ADD(304, :V$DOCUMENT_ID, :I$TEACHING_ORGANIZATION, :I$USER_ID)
                    INTO :V$BLOB_ID;    
                END
                IF (I$TEACHING_ORGANIZATION_SHORT IS NOT NULL) THEN
                BEGIN
                    SELECT BLOB_ID
                    FROM VAL_ADD(2335, :V$DOCUMENT_ID, :I$TEACHING_ORGANIZATION_SHORT, :I$USER_ID)
                    INTO :V$BLOB_ID;    
                END
            END
            ELSE
            BEGIN
                MSG = 'Запись о данном повышении квалификации уже существует. Пропущено.';
            END
        END
    END
    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE EMPLOYEE_JOBS_LIST (
    I$OBJ_ID BIGINT)
RETURNS (
    VAL VARCHAR(4000))
AS
declare variable V$S varchar(1000);
begin

  VAL = '';

  FOR
      SELECT C.CAPTION
      FROM LINKS L15
      JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
      JOIN VALL V72 ON V72.OBJ_ID = L15.OBJ_ID AND V72.PARAM_ID = 72 AND V72.IS_DEL = 0
      JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0 AND V73.VAL <= CURRENT_DATE
      LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
      LEFT JOIN OBJECT_CAPTION_GET(LP13.PARENT_ID) C ON 1 = 1
      WHERE L15.PARENT_ID = :I$OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL AND (V74.VAL IS NULL OR V74.VAL > CURRENT_DATE)
      ORDER BY V72.LISTVAL_ID -- сначала основная должность
      INTO :V$S
  DO
  BEGIN
      IF(CHAR_LENGTH(V$S) + CHAR_LENGTH(VAL) < 3990) THEN
      BEGIN
          IF(VAL <> '') THEN VAL = VAL || ', ';
          VAL = VAL || V$S;
      END
  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE EMPLOYEE_JOB_GET (
    I$OBJ_ID BIGINT,
    I$JOB_ID BIGINT,
    I$PARENT_ID BIGINT,
    I$ACTION SMALLINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE ID BIGINT;
DECLARE VARIABLE S VARCHAR(4000);
DECLARE VARIABLE V$JOB_ID BIGINT;
DECLARE VARIABLE V$RATE DOUBLE PRECISION;
DECLARE VARIABLE V$TERMS BIGINT;
DECLARE VARIABLE V$IS_MAIN BIGINT;
DECLARE VARIABLE V$ACCEPT_DATE DATE;
DECLARE VARIABLE V$ACCEPT_ORDER_NUM VARCHAR(400);
DECLARE VARIABLE V$ACCEPT_ORDER_DATE DATE;
DECLARE VARIABLE V$CONTRACT_DATE DATE;
DECLARE VARIABLE V$CONTRACT_NUM VARCHAR(400);
DECLARE VARIABLE V$CONTRACT_TO_DATE DATE;
DECLARE VARIABLE V$CATEGORY BIGINT;
DECLARE VARIABLE V$LEAVE_DATE DATE;
DECLARE VARIABLE V$LEAVE_ORDER_DATE DATE;
DECLARE VARIABLE V$LEAVE_ORDER_NUM VARCHAR(400);
DECLARE VARIABLE V$LEAVE_REASON BIGINT;
DECLARE VARIABLE V$LEAVE_CAUSE BIGINT;
DECLARE VARIABLE V$DEPT_ID BIGINT;
DECLARE VARIABLE S2 VARCHAR(100);
DECLARE VARIABLE V$TYPE_ID BIGINT;
DECLARE VARIABLE V$BOOK_NAME VARCHAR(1000);
DECLARE VARIABLE V$CAT_ID BIGINT;
begin

  -- Для приема нового сотрудника передается OBJ_ID = null, для существующего - id этого сотрудника

  SELECT LP13.PARENT_ID, V71.VAL, V587.LISTVAL_ID, V72.LISTVAL_ID, V73.VAL, V454.VAL, V455.VAL, V583.VAL,
    V1639.VAL, V1638.VAL, V1790.LISTVAL_ID, V74.VAL, V456.VAL, V457.VAL,
    V458.LISTVAL_ID, V461.LISTVAL_ID, V3543.VAL, V58.LISTVAL_ID
  FROM LINKS L15
  JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
  JOIN VALF V71 ON V71.OBJ_ID = L15.OBJ_ID AND V71.PARAM_ID = 71 AND V71.IS_DEL = 0
  JOIN VALL V587 ON V587.OBJ_ID = L15.OBJ_ID AND V587.PARAM_ID = 587 AND V587.IS_DEL = 0
  JOIN VALL V72 ON V72.OBJ_ID = L15.OBJ_ID AND V72.PARAM_ID = 72 AND V72.IS_DEL = 0
  JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0
  LEFT JOIN VALL V58 ON V58.OBJ_ID = LP13.PARENT_ID AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0
  LEFT JOIN VALD V454 ON V454.OBJ_ID = L15.OBJ_ID AND V454.PARAM_ID = 454 AND V454.IS_DEL = 0
  LEFT JOIN VALS V455 ON V455.OBJ_ID = L15.OBJ_ID AND V455.PARAM_ID = 455 AND V455.IS_DEL = 0
  LEFT JOIN VALD V583 ON V583.OBJ_ID = L15.OBJ_ID AND V583.PARAM_ID = 583 AND V583.IS_DEL = 0
  LEFT JOIN VALS V1638 ON V1638.OBJ_ID = L15.OBJ_ID AND V1638.PARAM_ID = 1638 AND V1638.IS_DEL = 0
  LEFT JOIN VALD V1639 ON V1639.OBJ_ID = L15.OBJ_ID AND V1639.PARAM_ID = 1639 AND V1639.IS_DEL = 0
  LEFT JOIN VALL V1790 ON V1790.OBJ_ID = L15.OBJ_ID AND V1790.PARAM_ID = 1790 AND V1790.IS_DEL = 0
  LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
  LEFT JOIN VALD V456 ON V456.OBJ_ID = L15.OBJ_ID AND V456.PARAM_ID = 456 AND V456.IS_DEL = 0
  LEFT JOIN VALD V457 ON V457.OBJ_ID = L15.OBJ_ID AND V457.PARAM_ID = 457 AND V457.IS_DEL = 0
  LEFT JOIN VALL V458 ON V458.OBJ_ID = L15.OBJ_ID AND V458.PARAM_ID = 458 AND V458.IS_DEL = 0
  LEFT JOIN VALL V461 ON V461.OBJ_ID = L15.OBJ_ID AND V461.PARAM_ID = 461 AND V461.IS_DEL = 0
  LEFT JOIN VALS V3543 ON V3543.OBJ_ID = L15.OBJ_ID AND V3543.PARAM_ID = 3543 AND V3543.IS_DEL = 0
  WHERE L15.PARENT_ID = :I$OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.OBJ_ID = :I$JOB_ID AND L15.DATE_DEL IS NULL
  INTO :V$JOB_ID, :V$RATE, :V$TERMS, :V$IS_MAIN, :V$ACCEPT_DATE, :V$ACCEPT_ORDER_DATE, :V$ACCEPT_ORDER_NUM, :V$CONTRACT_TO_DATE,
    :V$CONTRACT_DATE, :V$CONTRACT_NUM, :V$CATEGORY, :V$LEAVE_DATE, :V$LEAVE_ORDER_DATE, :V$LEAVE_ORDER_NUM,
    :V$LEAVE_REASON, :V$LEAVE_CAUSE, :V$BOOK_NAME, :V$CAT_ID;

  IF(V$LEAVE_REASON IS NULL) THEN
  BEGIN
    IF(I$ACTION = 3) THEN V$LEAVE_REASON = 3141; -- перевод
    IF(I$ACTION = 4) THEN V$LEAVE_REASON = 12757; -- изменение ставок
  END

  TAG_NAME = 'db_type';
  VAL = (SELECT STATUS FROM OU_LICENCE_TYPE);
  SUSPEND;

  -- Сначала данные по указанной должности (если job_id не пустой)
  TAG_NAME = 'obj_id';
  VAL = I$OBJ_ID;
  SUSPEND;

  TAG_NAME = 'vacancy_id';
  VAL = I$JOB_ID;
  SUSPEND;

  TAG_NAME = 'job_id';
  VAL = V$JOB_ID;
  SUSPEND;

  TAG_NAME = 'job_cat_id';
  VAL = V$CAT_ID;
  SUSPEND;

  TAG_NAME = 'job_name';
  IF(V$JOB_ID IS NULL) THEN VAL = NULL; ELSE VAL = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$JOB_ID));
  SUSPEND;

  TAG_NAME = 'job_book_name';
  VAL = V$BOOK_NAME;
  SUSPEND;

  TAG_NAME = 'is_main:selection::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT LISTVAL_ID, VAL
    FROM LISTVALS_LIST(129)
    WHERE IS_DEL = 0
    INTO :ID, :S
  DO
  BEGIN
    TAG_NAME = 'is_main:selection:option';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'is_main:selection:option:id';
    VAL = ID;
    SUSPEND;
    TAG_NAME = 'is_main:selection:option:value';
    VAL = S;
    SUSPEND;
  END
  TAG_NAME = 'is_main:values:value';
  VAL = V$IS_MAIN;
  SUSPEND;

  TAG_NAME = 'rate';
  VAL = V$RATE;
  SUSPEND;

  TAG_NAME = 'terms:selection::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT LISTVAL_ID, VAL
    FROM LISTVALS_LIST(38)
    WHERE IS_DEL = 0
    INTO :ID, :S
  DO
  BEGIN
    TAG_NAME = 'terms:selection:option';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'terms:selection:option:id';
    VAL = ID;
    SUSPEND;
    TAG_NAME = 'terms:selection:option:value';
    VAL = S;
    SUSPEND;
  END
  TAG_NAME = 'terms:values:value';
  VAL = V$TERMS;
  SUSPEND;

  TAG_NAME = 'category:selection::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT LISTVAL_ID, VAL
    FROM LISTVALS_LIST(90)
    WHERE IS_DEL = 0
    INTO :ID, :S
  DO
  BEGIN
    TAG_NAME = 'category:selection:option';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'category:selection:option:id';
    VAL = ID;
    SUSPEND;
    TAG_NAME = 'category:selection:option:value';
    VAL = S;
    SUSPEND;
  END
  TAG_NAME = 'category:values:value';
  VAL = V$CATEGORY;
  SUSPEND;

  TAG_NAME = 'accept_date';
  VAL = (SELECT VAL FROM DATE2ISO(:V$ACCEPT_DATE, 0));
  SUSPEND;

  TAG_NAME = 'accept_order_num';
  VAL = V$ACCEPT_ORDER_NUM;
  SUSPEND;

  TAG_NAME = 'accept_order_date';
  VAL = (SELECT VAL FROM DATE2ISO(:V$ACCEPT_ORDER_DATE, 0));
  SUSPEND;

  TAG_NAME = 'contract_date';
  VAL = (SELECT VAL FROM DATE2ISO(:V$CONTRACT_DATE, 0));
  SUSPEND;

  TAG_NAME = 'contract_num';
  VAL = V$CONTRACT_NUM;
  SUSPEND;

  TAG_NAME = 'contract_to_date';
  VAL = (SELECT VAL FROM DATE2ISO(:V$CONTRACT_TO_DATE, 0));
  SUSPEND;

  TAG_NAME = 'leave_date';
  VAL = (SELECT VAL FROM DATE2ISO(:V$LEAVE_DATE, 0));
  SUSPEND;

  TAG_NAME = 'leave_order_num';
  VAL = V$LEAVE_ORDER_NUM;
  SUSPEND;

  TAG_NAME = 'leave_order_date';
  VAL = (SELECT VAL FROM DATE2ISO(:V$LEAVE_ORDER_DATE, 0));
  SUSPEND;

  -- Причины увольнения
  TAG_NAME = 'leave_reason:selection::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT LISTVAL_ID, VAL
    FROM LISTVALS_LIST(128)
    WHERE IS_DEL = 0
    INTO :ID, :S
  DO
  BEGIN
    TAG_NAME = 'leave_reason:selection:option';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'leave_reason:selection:option:id';
    VAL = ID;
    SUSPEND;
    TAG_NAME = 'leave_reason:selection:option:value';
    VAL = S;
    SUSPEND;
  END
  TAG_NAME = 'leave_reason:values:value';
  VAL = V$LEAVE_REASON;
  SUSPEND;

  -- Основания увольнения
  TAG_NAME = 'leave_cause:selection::json&colon;array';
  VAL = 1;
  SUSPEND;
    TAG_NAME = 'leave_cause:selection:option';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'leave_cause:selection:option:id';
    VAL = '*';
    SUSPEND;
    TAG_NAME = 'leave_cause:selection:option:value';
    VAL = '';
    SUSPEND;
  FOR
    SELECT LISTVAL_ID, VAL
    FROM LISTVALS_LIST(130)
    WHERE IS_DEL = 0
    INTO :ID, :S
  DO
  BEGIN
    TAG_NAME = 'leave_cause:selection:option';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'leave_cause:selection:option:id';
    VAL = ID;
    SUSPEND;
    TAG_NAME = 'leave_cause:selection:option:value';
    VAL = S;
    SUSPEND;
  END
  TAG_NAME = 'leave_cause:values:value';
  VAL = V$LEAVE_CAUSE;
  SUSPEND;

  -- Список доступных должностей, в зависимости от действия
  IF(I$ACTION IN (0, 1, 3, 4)) THEN
  BEGIN
    -- 0 - Прием на новую должность
    -- 1 - Редактирование существующей должности
    -- 3 - Перевод на другую должность
    -- 4 - Изменение количества ставок
    TAG_NAME = 'jobs::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT OBJ_ID, PARENT_ID, OBJ_CAPTION, COLUMN1, COLUMN2, CAT_ID
      FROM PARAGRAF_VACANCY_LIST3(:I$PARENT_ID, :I$OBJ_ID, NULL, :I$JOB_ID)
      INTO :V$JOB_ID, :V$DEPT_ID, :S, :V$RATE, :S2, :V$CAT_ID
    DO
    BEGIN
      TAG_NAME = 'jobs:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'jobs:r:job_id';
      VAL = V$JOB_ID;
      SUSPEND;
      TAG_NAME = 'jobs:r:dept_id';
      VAL = V$DEPT_ID;
      SUSPEND;
      TAG_NAME = 'jobs:r:dept_name';
      IF(V$DEPT_ID IS NULL) THEN VAL = NULL; ELSE VAL = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$DEPT_ID));
      SUSPEND;
      TAG_NAME = 'jobs:r:name';
      VAL = S;
      SUSPEND;
      TAG_NAME = 'jobs:r:rate';
      VAL = V$RATE;
      SUSPEND;
      TAG_NAME = 'jobs:r:state';
      VAL = S2;
      SUSPEND;
      TAG_NAME = 'jobs:r:cat_id';
      VAL = V$CAT_ID;
      SUSPEND;
    END
  END
  --ELSE IF(I$ACTION = 2) THEN
  --BEGIN
    -- Уволить - тут ничего не нужно
  --END

  IF(I$ACTION = 4) THEN
  BEGIN
    -- Изменить количество ставок - возвращаем количество ставок в пределах текущей должности и типа должности
    TAG_NAME = 'max_rate';
    VAL = (SELECT FREERATECOUNT FROM PARAGRAF_EMPLOYEE_VACANCY_GET(:I$JOB_ID, NULL));
    SUSPEND;
  END
  ELSE IF (I$ACTION IN (2, 3)) THEN
  BEGIN
    -- Классное руководство и преподавательские нагрузки  Redmine #1063
    TAG_NAME = 'teacher_loads::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT OBJ_ID, LOAD_MSG, LOAD_TYPE_ID
      FROM PARAGRAF_EMPLOYEE_CANBE_FIRED(:I$OBJ_ID, 0)
      INTO :ID, :S, :V$TYPE_ID
    DO
    BEGIN
      TAG_NAME = 'teacher_loads:option';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'teacher_loads:option:id';
      VAL = ID;
      SUSPEND;
      TAG_NAME = 'teacher_loads:option:type';
      VAL = V$TYPE_ID;
      SUSPEND;
      TAG_NAME = 'teacher_loads:option:value';
      VAL = S;
      SUSPEND;
    END
  END

  -- Для приема нового сотрудника
  TAG_NAME = 'sex:selection::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT LISTVAL_ID, VAL
    FROM LISTVALS_LIST(30)
    WHERE IS_DEL = 0
    INTO :ID, :S
  DO
  BEGIN
    TAG_NAME = 'sex:selection:option';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'sex:selection:option:id';
    VAL = ID;
    SUSPEND;
    TAG_NAME = 'sex:selection:option:value';
    VAL = S;
    SUSPEND;
  END
  TAG_NAME = 'sex:values:value';
  VAL = NULL;
  SUSPEND;

  -- Есть ли действующие должности у персоны - для диалога приема на новую должность
  TAG_NAME = 'is_employed';
  VAL = 0;
  SELECT FIRST 1 1
  FROM LINKS L15
  LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
  WHERE L15.PARENT_ID = :I$OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL AND V74.VAL IS NULL
  INTO :VAL;
  SUSPEND;

  -- Список учительских должностей для выборе в трудовую
  TAG_NAME = 'teacher_jobs::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L.VAL
    FROM LISTVALS_LIST(370) L
    WHERE L.IS_DEL = 0
    INTO :S
  DO
  BEGIN
    TAG_NAME = 'teacher_jobs:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'teacher_jobs:r:value';
    VAL = S;
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE EMPLOYEE_JOB_LIST (
    I$OBJ_ID BIGINT)
RETURNS (
    ID BIGINT,
    CAPTION VARCHAR(1000),
    RATE NUMERIC(15,2),
    DATE_ACCEPT DATE,
    DATE_LEAVE DATE,
    JOB_LEVEL VARCHAR(100),
    CND_ID BIGINT,
    CAT_ID BIGINT,
    CND_CAPTION VARCHAR(100),
    CAT_CAPTION VARCHAR(100),
    BOOK_NAME VARCHAR(400))
AS
begin

  FOR
    SELECT L15.OBJ_ID, V73.VAL, V74.VAL, C.CAPTION, V71.VAL, R.VAL, V587.LISTVAL_ID, V1790.LISTVAL_ID, C1.VAL, C2.VAL, V3543.SVAL
    FROM LINKS L15
    JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
    JOIN VALF V71 ON V71.OBJ_ID = L15.OBJ_ID AND V71.PARAM_ID = 71 AND V71.IS_DEL = 0
    JOIN VALL V72 ON V72.OBJ_ID = L15.OBJ_ID AND V72.PARAM_ID = 72 AND V72.IS_DEL = 0
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V72.LISTVAL_ID
    JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
    JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
    LEFT JOIN VALL V587 ON V587.OBJ_ID = L15.OBJ_ID AND V587.PARAM_ID = 587 AND V587.IS_DEL = 0
    LEFT JOIN VALL V1790 ON V1790.OBJ_ID = L15.OBJ_ID AND V1790.PARAM_ID = 1790 AND V1790.IS_DEL = 0
    LEFT JOIN OBJECT_CAPTION_GET(LP13.PARENT_ID) C ON 1 = 1
    LEFT JOIN LISTVAL_TEXT(V587.LISTVAL_ID) C1 ON 1 = 1
    LEFT JOIN LISTVAL_TEXT(V1790.LISTVAL_ID) C2 ON 1 = 1
    LEFT JOIN VALS V3543 ON V3543.OBJ_ID = L15.OBJ_ID AND V3543.PARAM_ID = 3543 AND V3543.IS_DEL = 0
    WHERE L15.PARENT_ID = :I$OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
    INTO :ID, :DATE_ACCEPT, :DATE_LEAVE, :CAPTION, :RATE, :JOB_LEVEL, :CND_ID, :CAT_ID, :CND_CAPTION, :CAT_CAPTION, :BOOK_NAME
  DO
  BEGIN
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE EMPLOYEE_LEAVE_JOB_GET (
    I$OBJ_ID BIGINT,
    I$PARENT_ID BIGINT,
    I$USER_ID VARCHAR(40),
    I$ORDER SMALLINT = 0)
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$DATE DATE;
DECLARE VARIABLE V$TYPE_ID BIGINT;
DECLARE VARIABLE V$CAT_ID BIGINT;
DECLARE VARIABLE V VARCHAR(400);
DECLARE VARIABLE S VARCHAR(1000);
DECLARE VARIABLE V$RATE FLOAT;
DECLARE VARIABLE V$CND BIGINT;
DECLARE VARIABLE S2 VARCHAR(200);
DECLARE VARIABLE V$JOB_ID BIGINT;
begin

  -- I$PARENT_ID сейчас нигде не участвует, это id подразделения
  -- I$ORDER указывает, что вызов идет не из кнопки, а из формы приказа, чтобы не передавать лишние данные

  TAG_NAME = 'job_selection::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L15.OBJ_ID, LP13.PARENT_ID, V73.VAL, V72.LISTVAL_ID, V1790.LISTVAL_ID, V71.VAL, C.CAPTION, CT.VAL, V587.LISTVAL_ID, CN.VAL
    FROM LINKS L15
    JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
    JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0
    JOIN VALL V72 ON V72.OBJ_ID = L15.OBJ_ID AND V72.PARAM_ID = 72 AND V72.IS_DEL = 0
    JOIN VALF V71 ON V71.OBJ_ID = L15.OBJ_ID AND V71.PARAM_ID = 71 AND V71.IS_DEL = 0
    LEFT JOIN VALL V1790 ON V1790.OBJ_ID = L15.OBJ_ID AND V1790.PARAM_ID = 1790 AND V1790.IS_DEL = 0
    LEFT JOIN LISTVAL_TEXT(V1790.LISTVAL_ID) CT ON V1790.LISTVAL_ID IS NOT NULL
    LEFT JOIN VALL V587 ON V587.OBJ_ID = L15.OBJ_ID AND V587.PARAM_ID = 587 AND V587.IS_DEL = 0
    LEFT JOIN LISTVAL_TEXT(V587.LISTVAL_ID) CN ON V587.LISTVAL_ID IS NOT NULL
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
    LEFT JOIN OBJECT_CAPTION_GET(LP13.PARENT_ID) C ON 1 = 1
    WHERE L15.PARENT_ID = :I$OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL AND :I$OBJ_ID IS NOT NULL
      AND V74.VAL IS NULL
    ORDER BY 4, 6
    INTO :V$OBJ_ID, :V$JOB_ID, :V$DATE, :V$TYPE_ID, :V$CAT_ID, :V$RATE, :S, :V, :V$CND, :S2
  DO
  BEGIN
    TAG_NAME = 'job_selection:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'job_selection:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'job_selection:r:job_id';
    VAL = V$JOB_ID;
    SUSPEND;
    TAG_NAME = 'job_selection:r:name';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'job_selection:r:date';
    VAL = (SELECT VAL FROM DATE2ISO(:V$DATE, 0));
    SUSPEND;
    TAG_NAME = 'job_selection:r:type_id';
    VAL = V$TYPE_ID;
    SUSPEND;
    TAG_NAME = 'job_selection:r:cat_id';
    VAL = V$CAT_ID;
    SUSPEND;
    TAG_NAME = 'job_selection:r:cat_name';
    VAL = V;
    SUSPEND;
    TAG_NAME = 'job_selection:r:cnd_id';
    VAL = V$CND;
    SUSPEND;
    TAG_NAME = 'job_selection:r:cnd_name';
    VAL = S2;
    SUSPEND;
    TAG_NAME = 'job_selection:r:rate';
    VAL = CAST(V$RATE AS NUMERIC(18, 2));
    SUSPEND;
  END

  -- Причины увольнения
  IF(I$ORDER = 0) THEN
  BEGIN
    TAG_NAME = 'leave_reason:selection::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT LISTVAL_ID, VAL
      FROM LISTVALS_LIST(128)
      INTO :V$OBJ_ID, :S
    DO
    BEGIN
      TAG_NAME = 'leave_reason:selection:option';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'leave_reason:selection:option:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'leave_reason:selection:option:value';
      VAL = S;
      SUSPEND;
    END
    TAG_NAME = 'leave_reason:values:value';
    VAL = NULL;
    SUSPEND;

    -- Основания увольнения
    TAG_NAME = 'leave_cause:selection::json&colon;array';
    VAL = 1;
    SUSPEND;
      TAG_NAME = 'leave_cause:selection:option';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'leave_cause:selection:option:id';
      VAL = '*';
      SUSPEND;
      TAG_NAME = 'leave_cause:selection:option:value';
      VAL = '-';
      SUSPEND;
    FOR
      SELECT LISTVAL_ID, VAL
      FROM LISTVALS_LIST(130)
      INTO :V$OBJ_ID, :S
    DO
    BEGIN
      TAG_NAME = 'leave_cause:selection:option';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'leave_cause:selection:option:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'leave_cause:selection:option:value';
      VAL = S;
      SUSPEND;
    END
    TAG_NAME = 'leave_cause:values:value';
    VAL = NULL;
    SUSPEND;

    -- Классное руководство и преподавательские нагрузки  Redmine #1063
    TAG_NAME = 'teacher_loads::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT OBJ_ID, LOAD_MSG, LOAD_TYPE_ID
      FROM PARAGRAF_EMPLOYEE_CANBE_FIRED(:I$OBJ_ID, 0)
      INTO :V$OBJ_ID, :S, :V$TYPE_ID
    DO
    BEGIN
      TAG_NAME = 'teacher_loads:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'teacher_loads:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'teacher_loads:r:type';
      VAL = V$TYPE_ID;
      SUSPEND;
      TAG_NAME = 'teacher_loads:r:value';
      VAL = S;
      SUSPEND;
    END

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE EMPLOYEE_LOAD_GET (
    I$PERSON_ID BIGINT,
    I$DATE DATE)
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(100))
AS
declare variable V$YEAR_ID bigint;
declare variable V$Y integer;
declare variable V$OBJ_ID bigint;
declare variable V$H float;
begin

  IF(I$DATE IS NULL) THEN I$DATE = CURRENT_DATE;
  IF(EXTRACT(MONTH FROM I$DATE) IN (6, 7, 8)) THEN I$DATE = '01.09.' || EXTRACT(YEAR FROM I$DATE);

  V$Y = EXTRACT(YEAR FROM I$DATE);
  IF(EXTRACT(MONTH FROM I$DATE) < 9) THEN V$Y = V$Y - 1;

  SELECT FIRST 1 LV.LISTVAL_ID
  FROM LISTVALS LV
  WHERE LV.LIST_ID = 29 AND LV.IS_DEL = 0 AND LV.COST = :V$Y
  INTO :V$YEAR_ID;

  TAG_NAME = 'load::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT J.SUBJECT_ID, SUM(J.HOURS)
    FROM CJ2_JOURNAL J
    WHERE J.DATE_DEL IS NULL AND J.JOURNAL_TYPE = 0 AND J.TEACHER_ID = :I$PERSON_ID AND J.YEAR_ID = :V$YEAR_ID
    GROUP BY 1
    ORDER BY 1
    INTO :V$OBJ_ID, :V$H
  DO
  BEGIN
    TAG_NAME = 'load:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'load:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'load:r:hours';
    VAL = REPLACE(CAST(V$H AS NUMERIC(18, 2)), '.00', '');
    SUSPEND;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE ENROLLEE_FIND_PUPIL (
    I$LASTNAME VARCHAR(100) NOT NULL,
    I$FIRSTNAME VARCHAR(100) NOT NULL,
    I$BIRTHDATE DATE NOT NULL,
    I$SCHOOL_ID BIGINT NOT NULL)
RETURNS (
    PUPIL_ID BIGINT)
AS
begin
  SELECT FIRST(1) L10.OBJ_ID
  FROM LINKS L7
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID IN (8, 290) AND L8.DATE_DEL IS NULL
    LEFT JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
    JOIN LINKS L10 ON L10.PARENT_ID IN (L8.OBJ_ID, L9.OBJ_ID) AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    JOIN VALD V89 ON V89.OBJ_ID = L10.OBJ_ID AND V89.PARAM_ID = 89 AND V89.IS_DEL = 0 AND V89.VAL = :I$BIRTHDATE
    JOIN VALS V55 ON V55.OBJ_ID = L10.OBJ_ID AND V55.PARAM_ID = 55 AND V55.IS_DEL = 0 AND REPLACE(UPPER(CAST(V55.VAL AS VARCHAR(200))), 'Ё', 'Е') = REPLACE(UPPER(CAST(:I$LASTNAME AS VARCHAR(200))), 'Ё', 'Е')
    JOIN VALS V56 ON V56.OBJ_ID = L10.OBJ_ID AND V56.PARAM_ID = 56 AND V56.IS_DEL = 0 AND REPLACE(UPPER(CAST(V56.VAL AS VARCHAR(200))), 'Ё', 'Е') = REPLACE(UPPER(CAST(:I$FIRSTNAME AS VARCHAR(200))), 'Ё', 'Е')
  WHERE L7.PARENT_ID = :I$SCHOOL_ID AND L7.OBJ_TYPE_ID IN (7, 77) AND L7.DATE_DEL IS NULL
  INTO PUPIL_ID;
  SUSPEND;
end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE ENROLLEE_SCHOOL_LIST (
    I$OBJ_ID BIGINT)
RETURNS (
    SCHOOL_ID BIGINT,
    SCHOOL_OGRN VARCHAR(20))
AS
DECLARE VARIABLE V$OBJ_TYPE BIGINT;
begin
  SELECT O.TYPE_ID FROM OBJECTS O WHERE O.OBJ_ID = :I$OBJ_ID INTO V$OBJ_TYPE;

  IF (V$OBJ_TYPE = 111) THEN
  BEGIN
    --район
    FOR
      SELECT V9.OBJ_ID, CAST(V9.VAL AS VARCHAR(20)) OGRN
      FROM LINKS L2
      JOIN VALS V9 ON V9.OBJ_ID = L2.OBJ_ID AND V9.PARAM_ID = 9 AND V9.IS_DEL = 0
      WHERE L2.PARENT_ID = :I$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      INTO :SCHOOL_ID, :SCHOOL_OGRN
    DO
      SUSPEND;
  END
  ELSE BEGIN
    --школа
    FOR
      SELECT V9.OBJ_ID, CAST(V9.VAL AS VARCHAR(20)) OGRN
      FROM LINKS L2
      JOIN VALS V9 ON V9.OBJ_ID = L2.OBJ_ID AND V9.PARAM_ID = 9 AND V9.IS_DEL = 0
      WHERE L2.OBJ_ID = :I$OBJ_ID AND ((L2.PARENT_TYPE_ID = 111) OR (L2.PARENT_TYPE_ID IS NULL)) AND L2.DATE_DEL IS NULL
      INTO SCHOOL_ID, SCHOOL_OGRN
    DO
      SUSPEND;
  END
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE ENROLLEE_SET (
    I$SCHOOL_ID BIGINT,
    I$REG_ID VARCHAR(50),
    I$BIRTHDATE DATE,
    I$FIRSTNAME VARCHAR(100),
    I$SECONDNAME VARCHAR(100),
    I$LASTNAME VARCHAR(100),
    I$GENDER BIGINT,
    I$CITIZENSHIP BIGINT,
    I$PLACEOFBIRTH VARCHAR(200),
    I$REGISTRATIONADDRESS VARCHAR(200),
    I$ACTUALADDRESS VARCHAR(200),
    I$DATENUMBERORDER VARCHAR(10),
    I$APPLICATIONDATE TIMESTAMP,
    I$SNILS VARCHAR(20),
    I$DOCTYPECODE BIGINT,
    I$DOCSERIES VARCHAR(10),
    I$DOCNUMBER VARCHAR(20),
    I$DOCDATE DATE,
    I$DOCDELIVERY VARCHAR(200),
    I$P_FIRSTNAME VARCHAR(100),
    I$P_SECONDNAME VARCHAR(100),
    I$P_LASTNAME VARCHAR(100),
    I$P_BIRTHDATE DATE,
    I$NATIVELANGUAGE BIGINT,
    I$EDUCATIONTYPE BIGINT,
    I$USER_ID BIGINT = 1)
RETURNS (
    PUPIL_ID BIGINT,
    IS_NEW_RECORD SMALLINT)
AS
DECLARE VARIABLE V$LEVEL_ID BIGINT;
DECLARE VARIABLE V$STAGE_ID BIGINT;
DECLARE VARIABLE BLOB_ID BIGINT;
DECLARE VARIABLE V$PARENT_ID BIGINT;
DECLARE VARIABLE V$DOC_ID BIGINT;
begin
  --Проверяем ученика
  SELECT PUPIL_ID FROM ENROLLEE_FIND_PUPIL(:I$LASTNAME, :I$FIRSTNAME, :I$BIRTHDATE, :I$SCHOOL_ID)
  INTO PUPIL_ID;

  IF (PUPIL_ID IS NULL) THEN
  BEGIN

    SELECT FIRST(1) OBJ_ID FROM LINKS L77
    WHERE L77.PARENT_ID = :I$SCHOOL_ID AND L77.OBJ_TYPE_ID = 77 AND L77.DATE_DEL IS NULL
    INTO :V$LEVEL_ID;
  
    IF (V$LEVEL_ID IS NULL) THEN
    SELECT OBJ_ID FROM OBJECT_ADD(:I$SCHOOL_ID, 77) INTO :V$LEVEL_ID;
  
    SELECT FIRST(1) L290.OBJ_ID
    FROM LINKS L290
    JOIN VALL V2346 ON V2346.OBJ_ID = L290.OBJ_ID AND V2346.PARAM_ID = 2346 AND V2346.IS_DEL = 0
    WHERE L290.PARENT_ID = :V$LEVEL_ID AND L290.OBJ_TYPE_ID = 290 AND L290.DATE_DEL IS NULL
    INTO :V$STAGE_ID;
  
    IF (V$STAGE_ID IS NULL) THEN
    BEGIN
      SELECT OBJ_ID FROM OBJECT_ADD(:V$LEVEL_ID, 290) INTO :V$STAGE_ID;
      SELECT BLOB_ID FROM VAL_ADD(2346, :V$STAGE_ID, 37, :I$USER_ID) INTO :BLOB_ID;
    END

    SELECT OBJ_ID FROM OBJECT_ADD(:V$STAGE_ID, 10) INTO PUPIL_ID;
    SELECT BLOB_ID FROM VAL_ADD(55, :PUPIL_ID, :I$LASTNAME, :I$USER_ID) INTO :BLOB_ID; --Ф
    SELECT BLOB_ID FROM VAL_ADD(56, :PUPIL_ID, :I$FIRSTNAME, :I$USER_ID) INTO :BLOB_ID; --И
    SELECT BLOB_ID FROM VAL_ADD(57, :PUPIL_ID, :I$SECONDNAME, :I$USER_ID) INTO :BLOB_ID; --О
    SELECT BLOB_ID FROM VAL_ADD(88, :PUPIL_ID, :I$GENDER, :I$USER_ID) INTO :BLOB_ID; --ПОЛ
    SELECT BLOB_ID FROM VAL_ADD(89, :PUPIL_ID, :I$BIRTHDATE, :I$USER_ID) INTO :BLOB_ID; --ДАТА РОЖД
    SELECT BLOB_ID FROM VAL_ADD(91, :PUPIL_ID, :I$CITIZENSHIP, :I$USER_ID) INTO :BLOB_ID; --ГРАЖДАНСТВО
    SELECT BLOB_ID FROM VAL_ADD(1343, :PUPIL_ID, :I$PLACEOFBIRTH, :I$USER_ID) INTO :BLOB_ID; --Место рождения
    SELECT BLOB_ID FROM VAL_ADD(1409, :PUPIL_ID, :I$SNILS, :I$USER_ID) INTO :BLOB_ID; --Снилс
    SELECT BLOB_ID FROM VAL_ADD(80, :PUPIL_ID, :I$EDUCATIONTYPE, :I$USER_ID) INTO :BLOB_ID; --форма обучения
    SELECT BLOB_ID FROM VAL_ADD(127, :PUPIL_ID, :I$NATIVELANGUAGE, :I$USER_ID) INTO :BLOB_ID; --родной язык

    UPDATE OR INSERT INTO VALA (PARAM_ID, OBJ_ID, USER_ID, REGION, STREET, HOUSE, FLAT) --АДРЕС РЕГИСТРАЦИИ
    VALUES (111, :PUPIL_ID, :I$USER_ID, '', :I$REGISTRATIONADDRESS, '', '');
  
    UPDATE OR INSERT INTO VALA (PARAM_ID, OBJ_ID, USER_ID, REGION, STREET, HOUSE, FLAT) --ФАКТ. АДРЕС
    VALUES (103, :PUPIL_ID, :I$USER_ID, '', :I$ACTUALADDRESS, '', '');
  
    SELECT BLOB_ID FROM VAL_ADD(2912, :PUPIL_ID, :I$REG_ID, :I$USER_ID) INTO :BLOB_ID; --Идентификатор в системе Контингент
  
    SELECT OBJ_ID FROM OBJECT_ADD(:PUPIL_ID, 20) INTO V$PARENT_ID;
    SELECT BLOB_ID FROM VAL_ADD(128, :V$PARENT_ID, :I$P_LASTNAME, :I$USER_ID) INTO :BLOB_ID; --Ф
    SELECT BLOB_ID FROM VAL_ADD(129, :V$PARENT_ID, :I$P_FIRSTNAME, :I$USER_ID) INTO :BLOB_ID; --И
    SELECT BLOB_ID FROM VAL_ADD(130, :V$PARENT_ID, :I$P_SECONDNAME, :I$USER_ID) INTO :BLOB_ID; --О
    SELECT BLOB_ID FROM VAL_ADD(143, :V$PARENT_ID, :I$P_BIRTHDATE, :I$USER_ID) INTO :BLOB_ID; --ДАТА РОЖД
  
    SELECT OBJ_ID FROM OBJECT_ADD(:PUPIL_ID, 79) INTO V$DOC_ID;
    SELECT BLOB_ID FROM VAL_ADD(441, :V$DOC_ID, :I$DOCTYPECODE, :I$USER_ID) INTO :BLOB_ID; --Тип документа
    SELECT BLOB_ID FROM VAL_ADD(442, :V$DOC_ID, :I$DOCSERIES, :I$USER_ID) INTO :BLOB_ID; --Серия
    SELECT BLOB_ID FROM VAL_ADD(559, :V$DOC_ID, :I$DOCNUMBER, :I$USER_ID) INTO :BLOB_ID; --Номер
    SELECT BLOB_ID FROM VAL_ADD(560, :V$DOC_ID, :I$DOCDATE, :I$USER_ID) INTO :BLOB_ID; --Дата выдачи
    SELECT BLOB_ID FROM VAL_ADD(562, :V$DOC_ID, :I$DOCDELIVERY, :I$USER_ID) INTO :BLOB_ID; --Кем выдан

    IS_NEW_RECORD = 1;
  END
  ELSE
  BEGIN
    IS_NEW_RECORD = 0;
  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE ENTRANCE_STAGE_LIST (
    I$STAGE_ID BIGINT,
    I$CURRENT_STAGE_TYPE_FL SMALLINT = 0)
RETURNS (
    STAGE_ID BIGINT,
    STAGE_TYPE_ID BIGINT)
AS
BEGIN
    FOR SELECT
            LL290.OBJ_ID,
            V2346.LISTVAL_ID
        FROM LINKS L290
        JOIN LINKS LL290 ON LL290.PARENT_ID = L290.PARENT_ID
          AND LL290.OBJ_TYPE_ID = 290
          AND LL290.DATE_DEL IS NULL
        JOIN VALL V2346 ON V2346.OBJ_ID = LL290.OBJ_ID
          AND V2346.PARAM_ID = 2346
          AND V2346.IS_DEL = 0
          AND (:I$CURRENT_STAGE_TYPE_FL = 1 OR V2346.LISTVAL_ID <> (SELECT I FROM VAL_GET(:I$STAGE_ID, 2346)))
        WHERE L290.OBJ_ID = :I$STAGE_ID
          AND L290.DATE_DEL IS NULL
          AND L290.PARENT_TYPE_ID = 77
        INTO :STAGE_ID, :STAGE_TYPE_ID
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE EPT_FILTRED_LIST (
    I$OBJ_ID BIGINT,
    I$LIST_ID BIGINT,
    I$USER_ID BIGINT = NULL)
RETURNS (
    LISTVAL_ID BIGINT,
    PARENT_ID BIGINT,
    VAL VARCHAR(4000),
    VAL_LONG VARCHAR(4000),
    TAG VARCHAR(100),
    "FILTER" VARCHAR(255))
AS
DECLARE VARIABLE V$PROGRAMS_TYPE_ID BIGINT;
DECLARE VARIABLE V$STATUS VARCHAR(2);
BEGIN
    V$STATUS = (SELECT STATUS FROM OU_LICENCE_TYPE);

    IF (I$OBJ_ID IS NOT NULL) THEN
    BEGIN
        SELECT FIRST 1 V2450.LISTVAL_ID
        FROM LINKS LP69
        JOIN VALL V2450 ON V2450.OBJ_ID = LP69.PARENT_ID AND V2450.PARAM_ID = 2450 AND V2450.IS_DEL = 0
        WHERE LP69.OBJ_ID = :I$OBJ_ID AND LP69.PARENT_TYPE_ID = 69 AND LP69.DATE_DEL IS NULL
        INTO :V$PROGRAMS_TYPE_ID;

        FOR
            SELECT LISTVAL_ID, VAL, VAL_LONG, TAG, "FILTER"
            FROM LISTVALS_LIST(:I$LIST_ID)
            WHERE IS_DEL = 0 AND (
                ((:V$PROGRAMS_TYPE_ID = 11385) AND (LISTVAL_ID IN (5338, 5340, 5342, 5344, 13287))) OR
                ((:V$PROGRAMS_TYPE_ID = 11386) AND (LISTVAL_ID IN (5359, 5360, 5362, 5363))) OR
                ((:V$PROGRAMS_TYPE_ID = 11387) AND (LISTVAL_ID IN (5347, 11389, 11390))) OR
                ((:V$PROGRAMS_TYPE_ID = 11388) AND (LISTVAL_ID IN (5366, 5367, 5368))) OR
                ((:V$PROGRAMS_TYPE_ID = 12909) AND (LISTVAL_ID IN (5362, 5363, 5366, 5367, 5368, 11389, 11390))) OR
                ((:V$PROGRAMS_TYPE_ID = 12976) AND (LISTVAL_ID IN (5362, 5363, 5366, 5367, 5368, 11389, 11390)))
            )
            INTO :LISTVAL_ID, :VAL, :VAL_LONG, :TAG, :"FILTER"
        DO
        BEGIN
            SUSPEND;
        END
    END
    ELSE BEGIN
        -- это фильтры для нового списка
        FOR
            SELECT DISTINCT V1832.LISTVAL_ID
            FROM LINKS L57
            JOIN VALL V1832 ON V1832.OBJ_ID = L57.OBJ_ID AND V1832.PARAM_ID = 1832 AND V1832.IS_DEL = 0
            WHERE L57.OBJ_TYPE_ID = 57 AND L57.PARENT_TYPE_ID = 69 AND L57.DATE_DEL IS NULL
            INTO :V$PROGRAMS_TYPE_ID
        DO
        BEGIN
            LISTVAL_ID = NULL;
            SELECT LV.LISTVAL_ID, R.VAL, R.VAL_LONG, LV.TAG, LV."FILTER"
            FROM LISTVALS LV
            JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
            WHERE LV.LISTVAL_ID = :V$PROGRAMS_TYPE_ID
            INTO :LISTVAL_ID, :VAL, :VAL_LONG, :TAG, :"FILTER";

            IF(LISTVAL_ID IS NOT NULL) THEN SUSPEND;
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE ESCAPE_STR (
    S VARCHAR(4000))
RETURNS (
    VAL VARCHAR(4000))
AS
begin
  VAL = S;
  -- Заменяем амперсанды на &amp;
  VAL = REPLACE(VAL, '&', '&amp;');
  -- Заменяем двойные кавычки на &quot;
  VAL = REPLACE(VAL, '"', '&quot;');
  -- Заменяем одинарные кавычки на &apos;
  VAL = REPLACE(VAL, '''', '&apos;');
  -- Заменяем < на &lt;
  VAL = REPLACE(VAL, '<', '&lt;');
  -- Заменяем > на &gt;
  VAL = REPLACE(VAL, '>', '&gt;');

  SUSPEND;
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE EVENT_STAGE_LIST (
    I$LIST_ID BIGINT)
RETURNS (
    PARENT_ID BIGINT,
    LISTVAL_ID BIGINT,
    VAL VARCHAR(1000))
AS
begin

  -- Выбираем из числа этапов, имеющихся в данной ОУ
  FOR
    SELECT DISTINCT V49.LISTVAL_ID, C.VAL
    FROM LINKS L8
    JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
    LEFT JOIN LISTVAL_TEXT(V49.LISTVAL_ID) C ON 1 = 1
    WHERE L8.PARENT_TYPE_ID = 7 AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    ORDER BY C.SORT_ORDER
    INTO :LISTVAL_ID, :VAL
  DO
  BEGIN
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE EXPLODE_STR (
    S VARCHAR(4000),
    DELIM VARCHAR(1) = ';')
RETURNS (
    ID VARCHAR(100),
    V VARCHAR(1000))
AS
declare variable P integer;
begin

  WHILE(CHAR_LENGTH(S) > 0) DO
  BEGIN
      P = POSITION(DELIM IN S);
      IF(P <= 0) THEN P = CHAR_LENGTH(S) + 1;

      V = SUBSTRING(S FROM 1 FOR P - 1);
      S = SUBSTRING(S FROM P + 1);

      P = POSITION(':' IN V);
      IF(P > 0) THEN
      BEGIN
          ID = SUBSTRING(V FROM 1 FOR P - 1);
          V = SUBSTRING(V FROM P + 1);
      END
      ELSE
      BEGIN
          ID = V;
          V = NULL;
      END

      SUSPEND;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE EXPORT_CJ2_JOURNAL (
    I$REPL_DATE TIMESTAMP = null)
RETURNS (
    OBJ_ID BIGINT,
    DATE_ADD TIMESTAMP,
    DATE_MODIFY TIMESTAMP,
    DATE_DEL TIMESTAMP,
    GRADE_ID BIGINT,
    SUBJECT_ID BIGINT,
    TEACHER_ID BIGINT,
    JOURNAL_TYPE SMALLINT,
    GRADE_TYPE_ID BIGINT,
    STAGE_INDEX BIGINT,
    JOURNAL_NAME VARCHAR(1000),
    STAGE_MASK BIGINT,
    REF_ID BIGINT,
    YEAR_ID BIGINT,
    WEEKS INTEGER,
    HOURS FLOAT,
    IS_ENABLED SMALLINT,
    RCM_MODE SMALLINT,
    DURATION SMALLINT,
    DAYMASK SMALLINT,
    PERIOD_ID BIGINT,
    EXT_INFO VARCHAR(1000))
AS
begin

  FOR
    SELECT OBJ_ID, DATE_ADD, DATE_MODIFY, DATE_DEL, GRADE_ID, SUBJECT_ID, TEACHER_ID, JOURNAL_TYPE, GRADE_TYPE_ID, STAGE_INDEX, JOURNAL_NAME, STAGE_MASK,
      REF_ID, YEAR_ID, WEEKS, HOURS, IS_ENABLED, RCM_MODE, DURATION, DAYMASK, PERIOD_ID, EXT_INFO
    FROM CJ2_JOURNAL
    WHERE :I$REPL_DATE IS NULL OR DATE_MODIFY >= :I$REPL_DATE
    INTO :OBJ_ID, :DATE_ADD, :DATE_MODIFY, :DATE_DEL, :GRADE_ID, :SUBJECT_ID, :TEACHER_ID, :JOURNAL_TYPE, :GRADE_TYPE_ID, :STAGE_INDEX, :JOURNAL_NAME, :STAGE_MASK,
      :REF_ID, :YEAR_ID, :WEEKS, :HOURS, :IS_ENABLED, :RCM_MODE, :DURATION, :DAYMASK, :PERIOD_ID, :EXT_INFO
  DO
  BEGIN
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE EXPORT_CONTINGENT_CALC RETURNS (
    SCHOOL_ID BIGINT)
AS
DECLARE VARIABLE GRADE_ID BIGINT;
DECLARE VARIABLE STAGE_ID BIGINT;
DECLARE VARIABLE CLASS_ID BIGINT;
DECLARE VARIABLE LISTVAL_ID BIGINT;

DECLARE VARIABLE SCHOOL_C INTEGER;
DECLARE VARIABLE SCHOOL_M INTEGER;
DECLARE VARIABLE SCHOOL_W INTEGER;
DECLARE VARIABLE GRADE_C INTEGER;
DECLARE VARIABLE GRADE_M INTEGER;
DECLARE VARIABLE GRADE_W INTEGER;
DECLARE VARIABLE STAGE_C INTEGER;
DECLARE VARIABLE STAGE_M INTEGER;
DECLARE VARIABLE STAGE_W INTEGER;
DECLARE VARIABLE CLASS_C INTEGER;
DECLARE VARIABLE CLASS_M INTEGER;
DECLARE VARIABLE CLASS_W INTEGER;

DECLARE VARIABLE GRADE_NUM BIGINT;
DECLARE VARIABLE STAGE_NUM BIGINT;
DECLARE VARIABLE CLASS_NUM BIGINT;

DECLARE VARIABLE BLOB_ID BIGINT;
BEGIN
    SELECT FIRST 1 L.OBJ_ID
    FROM LINKS L
    WHERE L.PARENT_ID IS NULL
      AND L.OBJ_TYPE_ID = 2
      AND L.DATE_DEL IS NULL
    INTO :SCHOOL_ID;

    SCHOOL_C = 0;
    SCHOOL_M = 0;
    SCHOOL_W = 0;
    GRADE_C = 0;
    GRADE_M = 0;
    GRADE_W = 0;
    STAGE_C = 0;
    STAGE_M = 0;
    STAGE_W = 0;
    CLASS_C = 0;
    CLASS_M = 0;
    CLASS_W = 0;

    GRADE_NUM = 0;
    STAGE_NUM = 0;
    CLASS_NUM = 0;

    /* clear */

    FOR SELECT L7.OBJ_ID
        FROM LINKS L7
        WHERE L7.PARENT_ID = :SCHOOL_ID
          AND L7.OBJ_TYPE_ID = 7
          AND L7.DATE_DEL IS NULL
        INTO :GRADE_ID
    DO
    BEGIN
        SELECT BLOB_ID
        FROM VAL_ADD(47, :GRADE_ID, 0)
        INTO :BLOB_ID;
        SELECT BLOB_ID
        FROM VAL_ADD(48, :GRADE_ID, 0)
        INTO :BLOB_ID;
        SELECT BLOB_ID
        FROM VAL_ADD(1384, :GRADE_ID, 0)
        INTO :BLOB_ID;

        FOR SELECT L8.OBJ_ID
            FROM LINKS L8
            WHERE L8.PARENT_ID = :GRADE_ID
              AND L8.OBJ_TYPE_ID = 8
              AND L8.DATE_DEL IS NULL
            INTO :STAGE_ID
        DO
        BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD(1385, :STAGE_ID, 0)
            INTO :BLOB_ID;
            SELECT BLOB_ID
            FROM VAL_ADD(1386, :STAGE_ID, 0)
            INTO :BLOB_ID;
            SELECT BLOB_ID
            FROM VAL_ADD(1387, :STAGE_ID, 0)
            INTO :BLOB_ID;

            FOR SELECT L9.OBJ_ID
                FROM LINKS L9
                WHERE L9.PARENT_ID = :STAGE_ID
                  AND L9.OBJ_TYPE_ID = 9
                  AND L9.DATE_DEL IS NULL
                INTO :CLASS_ID
            DO
            BEGIN
                SELECT BLOB_ID
                FROM VAL_ADD(1379, :CLASS_ID, 0)
                INTO :BLOB_ID;
                SELECT BLOB_ID
                FROM VAL_ADD(1388, :CLASS_ID, 0)
                INTO :BLOB_ID;
                SELECT BLOB_ID
                FROM VAL_ADD(1389, :CLASS_ID, 0)
                INTO :BLOB_ID;
            END
        END
    END

    /* calc */

    FOR SELECT L7.OBJ_ID, L8.OBJ_ID, L9.OBJ_ID, V.LISTVAL_ID
        FROM LINKS L7
        INNER JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID
        INNER JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID
        INNER JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID
        LEFT JOIN VALL V ON V.PARAM_ID = 88 AND V.OBJ_ID = L10.OBJ_ID AND V.IS_DEL = 0
        WHERE L7.PARENT_ID = :SCHOOL_ID
          AND L7.OBJ_TYPE_ID = 7
          AND L7.DATE_DEL IS NULL
          AND L8.OBJ_TYPE_ID = 8
          AND L8.DATE_DEL IS NULL
          AND L9.OBJ_TYPE_ID = 9
          AND L9.DATE_DEL IS NULL
          AND L10.OBJ_TYPE_ID = 10
          AND L10.DATE_DEL IS NULL
        ORDER BY L7.OBJ_ID, L8.OBJ_ID, L9.OBJ_ID, L10.OBJ_ID
        INTO :GRADE_ID, :STAGE_ID, :CLASS_ID, :LISTVAL_ID
    DO
    BEGIN
        IF (GRADE_NUM = 0) THEN
            GRADE_NUM = GRADE_ID;
        IF (STAGE_NUM = 0) THEN
            STAGE_NUM = STAGE_ID;
        IF (CLASS_NUM = 0) THEN
            CLASS_NUM = CLASS_ID;

        IF (GRADE_NUM <> GRADE_ID) THEN
        BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD(47, :GRADE_NUM, :GRADE_C)
            INTO :BLOB_ID;
            SELECT BLOB_ID
            FROM VAL_ADD(48, :GRADE_NUM, :GRADE_M)
            INTO :BLOB_ID;
            SELECT BLOB_ID
            FROM VAL_ADD(1384, :GRADE_NUM, :GRADE_W)
            INTO :BLOB_ID;
            GRADE_C = 0;
            GRADE_M = 0;
            GRADE_W = 0;
            GRADE_NUM = GRADE_ID;
        END

        IF (STAGE_NUM <> STAGE_ID) THEN
        BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD(1385, :STAGE_NUM, :STAGE_C)
            INTO :BLOB_ID;
            SELECT BLOB_ID
            FROM VAL_ADD(1386, :STAGE_NUM, :STAGE_M)
            INTO :BLOB_ID;
            SELECT BLOB_ID
            FROM VAL_ADD(1387, :STAGE_NUM, :STAGE_W)
            INTO :BLOB_ID;
            STAGE_C = 0;
            STAGE_M = 0;
            STAGE_W = 0;
            STAGE_NUM = STAGE_ID;
        END

        IF (CLASS_NUM <> CLASS_ID) THEN
        BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD(1379, :CLASS_NUM, :CLASS_C)
            INTO :BLOB_ID;
            SELECT BLOB_ID
            FROM VAL_ADD(1388, :CLASS_NUM, :CLASS_M)
            INTO :BLOB_ID;
            SELECT BLOB_ID
            FROM VAL_ADD(1389, :CLASS_NUM, :CLASS_W)
            INTO :BLOB_ID;
            CLASS_C = 0;
            CLASS_M = 0;
            CLASS_W = 0;
            CLASS_NUM = CLASS_ID;
        END

        SCHOOL_C = SCHOOL_C + 1;
        GRADE_C = GRADE_C + 1;
        STAGE_C = STAGE_C + 1;
        CLASS_C = CLASS_C + 1;

        IF (LISTVAL_ID = 183) THEN
        BEGIN
            SCHOOL_M = SCHOOL_M + 1;
            GRADE_M = GRADE_M + 1;
            STAGE_M = STAGE_M + 1;
            CLASS_M = CLASS_M + 1;
        END

        IF (LISTVAL_ID = 182) THEN
        BEGIN
            SCHOOL_W = SCHOOL_W + 1;
            GRADE_W = GRADE_W + 1;
            STAGE_W = STAGE_W + 1;
            CLASS_W = CLASS_W + 1;
        END

    END

    IF (SCHOOL_ID IS NOT NULL) THEN
    BEGIN
        SELECT BLOB_ID
        FROM VAL_ADD(1381, :SCHOOL_ID, :SCHOOL_C)
        INTO :BLOB_ID;
        SELECT BLOB_ID
        FROM VAL_ADD(1382, :SCHOOL_ID, :SCHOOL_M)
        INTO :BLOB_ID;
        SELECT BLOB_ID
        FROM VAL_ADD(1383, :SCHOOL_ID, :SCHOOL_W)
        INTO :BLOB_ID;
    END

    IF (GRADE_ID IS NOT NULL) THEN
    BEGIN
        SELECT BLOB_ID
        FROM VAL_ADD(47, :GRADE_ID, :GRADE_C)
        INTO :BLOB_ID;
        SELECT BLOB_ID
        FROM VAL_ADD(48, :GRADE_ID, :GRADE_M)
        INTO :BLOB_ID;
        SELECT BLOB_ID
        FROM VAL_ADD(1384, :GRADE_ID, :GRADE_W)
        INTO :BLOB_ID;
    END

    IF (STAGE_ID IS NOT NULL) THEN
    BEGIN
        SELECT BLOB_ID
        FROM VAL_ADD(1385, :STAGE_ID, :STAGE_C)
        INTO :BLOB_ID;
        SELECT BLOB_ID
        FROM VAL_ADD(1386, :STAGE_ID, :STAGE_M)
        INTO :BLOB_ID;
        SELECT BLOB_ID
        FROM VAL_ADD(1387, :STAGE_ID, :STAGE_W)
        INTO :BLOB_ID;
    END

    IF (CLASS_ID IS NOT NULL) THEN
    BEGIN
        SELECT BLOB_ID
        FROM VAL_ADD(1379, :CLASS_ID, :CLASS_C)
        INTO :BLOB_ID;
        SELECT BLOB_ID
        FROM VAL_ADD(1388, :CLASS_ID, :CLASS_M)
        INTO :BLOB_ID;
        SELECT BLOB_ID
        FROM VAL_ADD(1389, :CLASS_ID, :CLASS_W)
        INTO :BLOB_ID;
    END

    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE EXPORT_HASHES (
    I$OBJ_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    PARAM_ID BIGINT,
    VAL VARCHAR(1000),
    H VARCHAR(200))
AS
declare variable S1 varchar(100);
declare variable S2 varchar(100);
declare variable S3 varchar(100);
declare variable DS varchar(20);
begin

  FOR
    SELECT L10.OBJ_ID, 3056, SUBSTRING(V55.VAL FROM 1 FOR 100), SUBSTRING(V56.VAL FROM 1 FOR 100), SUBSTRING(V57.VAL FROM 1 FOR 100), D.VAL, V3056.VAL
    FROM OBJECTS L10
    JOIN VALS V55 ON V55.OBJ_ID = L10.OBJ_ID AND V55.PARAM_ID = 55 AND V55.IS_DEL = 0
    JOIN VALS V56 ON V56.OBJ_ID = L10.OBJ_ID AND V56.PARAM_ID = 56 AND V56.IS_DEL = 0
    LEFT JOIN VALS V57 ON V57.OBJ_ID = L10.OBJ_ID AND V57.PARAM_ID = 57 AND V57.IS_DEL = 0
    JOIN VALD V89 ON V89.OBJ_ID = L10.OBJ_ID AND V89.PARAM_ID = 89 AND V89.IS_DEL = 0
    LEFT JOIN DATE2ISO(V89.VAL, 0) D ON 1 = 1
    LEFT JOIN VALS V3056 ON V3056.OBJ_ID = L10.OBJ_ID AND V3056.PARAM_ID = 3056 AND V3056.IS_DEL = 0
    WHERE L10.TYPE_ID = 10
    UNION ALL
    SELECT L14.OBJ_ID, 3057, SUBSTRING(V59.VAL FROM 1 FOR 100), SUBSTRING(V60.VAL FROM 1 FOR 100), SUBSTRING(V61.VAL FROM 1 FOR 100), D.VAL, V3057.VAL
    FROM OBJECTS L14
    JOIN VALS V59 ON V59.OBJ_ID = L14.OBJ_ID AND V59.PARAM_ID = 59 AND V59.IS_DEL = 0
    JOIN VALS V60 ON V60.OBJ_ID = L14.OBJ_ID AND V60.PARAM_ID = 60 AND V60.IS_DEL = 0
    LEFT JOIN VALS V61 ON V61.OBJ_ID = L14.OBJ_ID AND V61.PARAM_ID = 61 AND V61.IS_DEL = 0
    JOIN VALD V241 ON V241.OBJ_ID = L14.OBJ_ID AND V241.PARAM_ID = 241 AND V241.IS_DEL = 0
    LEFT JOIN DATE2ISO(V241.VAL, 0) D ON 1 = 1
    LEFT JOIN VALS V3057 ON V3057.OBJ_ID = L14.OBJ_ID AND V3057.PARAM_ID = 3057 AND V3057.IS_DEL = 0
    WHERE L14.TYPE_ID = 14
    INTO :OBJ_ID, :PARAM_ID, :S1, :S2, :S3, :DS, :H
  DO
  BEGIN
    S1 = REPLACE(REPLACE(REPLACE(REPLACE(UPPER(S1), ' ', ''), '-', ''), 'Ё', 'Е'), 'Й', 'И');
    S2 = REPLACE(REPLACE(REPLACE(REPLACE(UPPER(S2), ' ', ''), '-', ''), 'Ё', 'Е'), 'Й', 'И');
    S3 = COALESCE(S3, '');
    S3 = REPLACE(REPLACE(REPLACE(REPLACE(UPPER(S3), ' ', ''), '-', ''), 'Ё', 'Е'), 'Й', 'И');
    DS = REPLACE(DS, '-', '');
    VAL = S1 || S2 || S3 || DS;
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE EXPORT_INSPECTOR RETURNS (
    PRG_CODE VARCHAR(10),
    PARAM_NAME VARCHAR(100),
    PARAM_VALUE VARCHAR(30))
AS
declare variable MON_ID bigint;
begin
  for
    select L162.OBJ_ID, (L2.OBJ_ID / 1000000000)
    from links L112
    -- Район
    join links L111 on L111.PARENT_ID = L112.OBJ_ID and L111.OBJ_TYPE_ID = 111 and L111.DATE_DEL is null
    -- Школы
    join links L2 on L2.PARENT_ID = L111.OBJ_ID and L2.OBJ_TYPE_ID = 2 and L2.DATE_DEL is null
    -- Мониторинг текущего года
    join LINKS L162 on L162.PARENT_ID = L2.OBJ_ID and L162.OBJ_TYPE_ID = 162 and L162.DATE_DEL is null
    where L112.PARENT_ID is null and L112.OBJ_TYPE_ID = 112 and L112.DATE_DEL is null
    into :MON_ID, :PRG_CODE
  do
  begin

    PARAM_NAME = 'N_CLASSES_00';
    PARAM_VALUE = (select V from VAL_GET(:MON_ID, 2908));
    SUSPEND;
    PARAM_NAME = 'N_CLASSES_01';
    PARAM_VALUE = (select V from VAL_GET(:MON_ID, 1528));
    SUSPEND;
    PARAM_NAME = 'N_CLASSES_02';
    PARAM_VALUE = (select V from VAL_GET(:MON_ID, 1529));
    SUSPEND;
    PARAM_NAME = 'N_CLASSES_03';
    PARAM_VALUE = (select V from VAL_GET(:MON_ID, 1530));
    SUSPEND;
    PARAM_NAME = 'N_CLASSES_04';
    PARAM_VALUE = (select V from VAL_GET(:MON_ID, 1531));
    SUSPEND;
    PARAM_NAME = 'N_CLASSES_05';
    PARAM_VALUE = (select V from VAL_GET(:MON_ID, 1532));
    SUSPEND;
    PARAM_NAME = 'N_CLASSES_06';
    PARAM_VALUE = (select V from VAL_GET(:MON_ID, 1533));
    SUSPEND;
    PARAM_NAME = 'N_CLASSES_07';
    PARAM_VALUE = (select V from VAL_GET(:MON_ID, 1534));
    SUSPEND;
    PARAM_NAME = 'N_CLASSES_08';
    PARAM_VALUE = (select V from VAL_GET(:MON_ID, 1535));
    SUSPEND;
    PARAM_NAME = 'N_CLASSES_09';
    PARAM_VALUE = (select V from VAL_GET(:MON_ID, 1536));
    SUSPEND;
    PARAM_NAME = 'N_CLASSES_10';
    PARAM_VALUE = (select V from VAL_GET(:MON_ID, 1537));
    SUSPEND;
    PARAM_NAME = 'N_CLASSES_11';
    PARAM_VALUE = (select V from VAL_GET(:MON_ID, 1538));
    SUSPEND;
    PARAM_NAME = 'N_CLASSES_12';
    PARAM_VALUE = (select V from VAL_GET(:MON_ID, 1539));
    SUSPEND;

    PARAM_NAME = 'N_STUDENTS_00';
    PARAM_VALUE = (select V from VAL_GET(:MON_ID, 2909));
    SUSPEND;
    PARAM_NAME = 'N_STUDENTS_01';
    PARAM_VALUE = (select V from VAL_GET(:MON_ID, 1513));
    SUSPEND;
    PARAM_NAME = 'N_STUDENTS_02';
    PARAM_VALUE = (select V from VAL_GET(:MON_ID, 1514));
    SUSPEND;
    PARAM_NAME = 'N_STUDENTS_03';
    PARAM_VALUE = (select V from VAL_GET(:MON_ID, 1515));
    SUSPEND;
    PARAM_NAME = 'N_STUDENTS_04';
    PARAM_VALUE = (select V from VAL_GET(:MON_ID, 1516));
    SUSPEND;
    PARAM_NAME = 'N_STUDENTS_05';
    PARAM_VALUE = (select V from VAL_GET(:MON_ID, 1517));
    SUSPEND;
    PARAM_NAME = 'N_STUDENTS_06';
    PARAM_VALUE = (select V from VAL_GET(:MON_ID, 1518));
    SUSPEND;
    PARAM_NAME = 'N_STUDENTS_07';
    PARAM_VALUE = (select V from VAL_GET(:MON_ID, 1519));
    SUSPEND;
    PARAM_NAME = 'N_STUDENTS_08';
    PARAM_VALUE = (select V from VAL_GET(:MON_ID, 1520));
    SUSPEND;
    PARAM_NAME = 'N_STUDENTS_09';
    PARAM_VALUE = (select V from VAL_GET(:MON_ID, 1521));
    SUSPEND;
    PARAM_NAME = 'N_STUDENTS_10';
    PARAM_VALUE = (select V from VAL_GET(:MON_ID, 1522));
    SUSPEND;
    PARAM_NAME = 'N_STUDENTS_11';
    PARAM_VALUE = (select V from VAL_GET(:MON_ID, 1524));
    SUSPEND;
    PARAM_NAME = 'N_STUDENTS_12';
    PARAM_VALUE = (select V from VAL_GET(:MON_ID, 1525));
    SUSPEND;
    PARAM_NAME = 'N_STUDENTS_TOTAL';
    PARAM_VALUE = (select V from VAL_GET(:MON_ID, 1433));
    SUSPEND;
    PARAM_NAME = 'N_STUDENTS_STD';
    PARAM_VALUE = (select V from VAL_GET(:MON_ID, 1432));
    SUSPEND;
    PARAM_NAME = 'N_STUDENTS_PRJ';
    PARAM_VALUE = (select V from VAL_GET(:MON_ID, 2193));
    SUSPEND;

    PARAM_NAME = 'N_PUPIL_IN';
    PARAM_VALUE = (select V from VAL_GET(:MON_ID, 1596));
    SUSPEND;

    PARAM_NAME = 'N_PUPIL_OUT';
    PARAM_VALUE = (select V from VAL_GET(:MON_ID, 1597));
    SUSPEND;

    PARAM_NAME = 'N_PUPIL_HOME';
    PARAM_VALUE = (select V from VAL_GET(:MON_ID, 1486));
    SUSPEND;

    PARAM_NAME = 'N_EMP_TOTAL';
    PARAM_VALUE = (select V from VAL_GET(:MON_ID, 1541));
    SUSPEND;

    PARAM_NAME = 'N_EMP_MANAGEMENT';
    PARAM_VALUE = (select V from VAL_GET(:MON_ID, 1547));
    SUSPEND;

    PARAM_NAME = 'N_EMP_EDU';
    PARAM_VALUE = (select V from VAL_GET(:MON_ID, 1542));
    SUSPEND;

    PARAM_NAME = 'N_EMP_WORK';
    PARAM_VALUE = (select V from VAL_GET(:MON_ID, 1544));
    SUSPEND;

    PARAM_NAME = 'N_EMP_TEACHERS';
    PARAM_VALUE = (select V from VAL_GET(:MON_ID, 1546));
    SUSPEND;

    PARAM_NAME = 'n_emp_notedu';
    PARAM_VALUE = 0;

    SELECT SUM(V2664.VAL)
    FROM LINKS L340
    JOIN VALI V2664 ON V2664.OBJ_ID = L340.OBJ_ID AND V2664.PARAM_ID = 2664 AND V2664.IS_DEL = 0
    WHERE L340.PARENT_ID = :MON_ID AND L340.OBJ_TYPE_ID = 340 AND L340.DATE_DEL IS NULL
    INTO :PARAM_VALUE;

    SUSPEND;

    PARAM_NAME = 'n_emp_studyup';
    PARAM_VALUE = 0;

    SELECT SUM(V2665.VAL)
    FROM LINKS L340
    JOIN VALI V2665 ON V2665.OBJ_ID = L340.OBJ_ID AND V2665.PARAM_ID = 2665 AND V2665.IS_DEL = 0
    WHERE L340.PARENT_ID = :MON_ID AND L340.OBJ_TYPE_ID = 340 AND L340.DATE_DEL IS NULL
    INTO :PARAM_VALUE;

    SUSPEND;

    -- Учебные планы

    PARAM_NAME = 'n_plans_total';
    PARAM_VALUE = 0;

    SELECT COUNT(*)
    FROM LINKS L305
    WHERE L305.PARENT_ID = :MON_ID AND L305.OBJ_TYPE_ID = 305 AND L305.DATE_DEL IS NULL
    INTO :PARAM_VALUE;

    SUSPEND;

    PARAM_NAME = 'n_plans_miss_hours';
    PARAM_VALUE = 0;

    SELECT COUNT(*)
    FROM LINKS L305
    JOIN VALL V2486 ON V2486.OBJ_ID = L305.OBJ_ID AND V2486.PARAM_ID = 2486 AND V2486.IS_DEL = 0 AND V2486.LISTVAL_ID = 3
    WHERE L305.PARENT_ID = :MON_ID AND L305.OBJ_TYPE_ID = 305 AND L305.DATE_DEL IS NULL
    INTO :PARAM_VALUE;

    SUSPEND;

    PARAM_NAME = 'n_plans_miss_subj';
    PARAM_VALUE = 0;

    SELECT COUNT(*)
    FROM LINKS L305
    JOIN VALL V2487 ON V2487.OBJ_ID = L305.OBJ_ID AND V2487.PARAM_ID = 2487 AND V2487.IS_DEL = 0 AND V2487.LISTVAL_ID = 3
    WHERE L305.PARENT_ID = :MON_ID AND L305.OBJ_TYPE_ID = 305 AND L305.DATE_DEL IS NULL
    INTO :PARAM_VALUE;

    SUSPEND;

    PARAM_NAME = 'n_plans_miss_h1';
    PARAM_VALUE = 0;

    SELECT COUNT(*)
    FROM LINKS L305
    JOIN VALL V2488 ON V2488.OBJ_ID = L305.OBJ_ID AND V2488.PARAM_ID = 2488 AND V2488.IS_DEL = 0 AND V2488.LISTVAL_ID = 3
    WHERE L305.PARENT_ID = :MON_ID AND L305.OBJ_TYPE_ID = 305 AND L305.DATE_DEL IS NULL
    INTO :PARAM_VALUE;

    SUSPEND;

    PARAM_NAME = 'n_plans_miss_h2';
    PARAM_VALUE = 0;

    SELECT COUNT(*)
    FROM LINKS L305
    JOIN VALL V2489 ON V2489.OBJ_ID = L305.OBJ_ID AND V2489.PARAM_ID = 2489 AND V2489.IS_DEL = 0 AND V2489.LISTVAL_ID = 3
    WHERE L305.PARENT_ID = :MON_ID AND L305.OBJ_TYPE_ID = 305 AND L305.DATE_DEL IS NULL
    INTO :PARAM_VALUE;

    SUSPEND;

    PARAM_NAME = 'n_journals_total';
    PARAM_VALUE = 0;

    SELECT COUNT(*)
    FROM LINKS L316
    WHERE L316.PARENT_ID = :MON_ID AND L316.OBJ_TYPE_ID = 316 AND L316.DATE_DEL IS NULL
    INTO :PARAM_VALUE;

    SUSPEND;

    PARAM_NAME = 'n_journals_miss_ptp';
    PARAM_VALUE = 0;

    SELECT COUNT(*)
    FROM LINKS L313
    WHERE L313.PARENT_ID = :MON_ID AND L313.OBJ_TYPE_ID = 313 AND L313.DATE_DEL IS NULL
    INTO :PARAM_VALUE;

    SUSPEND;

    -- Учебники
    PARAM_NAME = 'n_students_miss_books1';
    PARAM_VALUE = 0;

    SELECT SUM(V2688.VAL)
    FROM LINKS L345
    JOIN VALI V2688 ON V2688.OBJ_ID = L345.OBJ_ID AND V2688.PARAM_ID = 2688 AND V2688.IS_DEL = 0
    WHERE L345.PARENT_ID = :MON_ID AND L345.OBJ_TYPE_ID = 345 AND L345.DATE_DEL IS NULL
    INTO :PARAM_VALUE;

    SUSPEND;

    PARAM_NAME = 'n_students_miss_books2';
    PARAM_VALUE = 0;

    SELECT SUM(V2689.VAL)
    FROM LINKS L345
    JOIN VALI V2689 ON V2689.OBJ_ID = L345.OBJ_ID AND V2689.PARAM_ID = 2689 AND V2689.IS_DEL = 0
    WHERE L345.PARENT_ID = :MON_ID AND L345.OBJ_TYPE_ID = 345 AND L345.DATE_DEL IS NULL
    INTO :PARAM_VALUE;

    SUSPEND;

    PARAM_NAME = 'n_students_miss_books3';
    PARAM_VALUE = 0;

    SELECT SUM(V2690.VAL)
    FROM LINKS L345
    JOIN VALI V2690 ON V2690.OBJ_ID = L345.OBJ_ID AND V2690.PARAM_ID = 2690 AND V2690.IS_DEL = 0
    WHERE L345.PARENT_ID = :MON_ID AND L345.OBJ_TYPE_ID = 345 AND L345.DATE_DEL IS NULL
    INTO :PARAM_VALUE;

    SUSPEND;

    PARAM_NAME = 'n_students_miss_books4';
    PARAM_VALUE = 0;

    SELECT SUM(V2691.VAL)
    FROM LINKS L345
    JOIN VALI V2691 ON V2691.OBJ_ID = L345.OBJ_ID AND V2691.PARAM_ID = 2691 AND V2691.IS_DEL = 0
    WHERE L345.PARENT_ID = :MON_ID AND L345.OBJ_TYPE_ID = 345 AND L345.DATE_DEL IS NULL
    INTO :PARAM_VALUE;

    SUSPEND;

    PARAM_NAME = 'n_students_miss_books5x';
    PARAM_VALUE = 0;

    SELECT SUM(V2772.VAL)
    FROM LINKS L345
    JOIN VALI V2772 ON V2772.OBJ_ID = L345.OBJ_ID AND V2772.PARAM_ID = 2772 AND V2772.IS_DEL = 0
    WHERE L345.PARENT_ID = :MON_ID AND L345.OBJ_TYPE_ID = 345 AND L345.DATE_DEL IS NULL
    INTO :PARAM_VALUE;

    SUSPEND;

  end
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE EXPORT_LINKS (
    I$REPL_DATE TIMESTAMP = NULL,
    I$SUBTYPE VARCHAR(1) = NULL)
RETURNS (
    LINK_ID BIGINT,
    PARENT_ID BIGINT,
    OBJ_ID BIGINT,
    EXT_OBJ_ID BIGINT,
    REASON_ID BIGINT,
    LISTVAL_ID BIGINT,
    USER_ID BIGINT,
    DATE_INS TIMESTAMP,
    DATE_DEL TIMESTAMP,
    COST FLOAT,
    IS_REPL SMALLINT)
AS
DECLARE VARIABLE G BIGINT;
DECLARE VARIABLE M BIGINT;
DECLARE VARIABLE L SMALLINT;
DECLARE VARIABLE LC VARCHAR(2);
DECLARE VARIABLE V$PARENT_TYPE_ID BIGINT;
DECLARE VARIABLE V$OBJ_TYPE_ID BIGINT;
DECLARE VARIABLE V BIGINT;
DECLARE VARIABLE D DATE;
DECLARE VARIABLE Y INTEGER;
BEGIN

  -- I$SUBTYPE указыват на ограничение выгрузки
  -- O - только общее образование (школы)
  -- D - только дошкольное
  -- NULL - без ограничений, полная выгрузка

  IS_REPL = 0;
  COST = 0;
  LISTVAL_ID = NULL;
  USER_ID = NULL;

  SELECT GEN, MULTIPLIER FROM GEN INTO :G, :M;
  SELECT K.KEY_VAL FROM KEYS K WHERE K.KEY_CODE = 'LEVEL' INTO :L;
  SELECT STATUS FROM OU_LICENCE_TYPE INTO :LC;

  -- Оптимизация от 15.09.2017 - исключаем из выгрузок мусор, связанный с печатью аттестатов (конвейер, предметы в аттестате и приложении)
  -- 23.12.2019 - включаем выгрузку удаленных линков для корректной работы отчетов
  FOR
    SELECT L.LINK_ID, L.PARENT_ID, L.OBJ_ID, L.EXT_OBJ_ID, L.REASON_ID, L.DATE_INS, L.DATE_DEL, L.PARENT_TYPE_ID, L.OBJ_TYPE_ID
    FROM LINKS L
    JOIN TYPES T ON T.TYPE_ID = L.OBJ_TYPE_ID AND T.FOR_REPL_UP = 1
    LEFT JOIN TYPES P ON P.TYPE_ID = L.PARENT_TYPE_ID
    WHERE
      (:I$REPL_DATE IS NULL OR L.DATE_MODIFY >= :I$REPL_DATE)
      AND (P.TYPE_ID IS NULL OR P.FOR_REPL_UP = 1 OR L.PARENT_ID < :M)
      -- AND ((:I$REPL_DATE IS NULL AND L.DATE_DEL IS NULL) OR :I$REPL_DATE IS NOT NULL)
      AND L.OBJ_TYPE_ID NOT IN (155, 227, 229, 292)
      AND (L.PARENT_TYPE_ID IS NULL OR L.PARENT_TYPE_ID NOT IN (155, 227, 229, 292))
    ORDER BY 1
    INTO :LINK_ID, :PARENT_ID, :OBJ_ID, :EXT_OBJ_ID, :REASON_ID, :DATE_INS, :DATE_DEL, :V$PARENT_TYPE_ID, :V$OBJ_TYPE_ID
  DO
  BEGIN
    -- Ограничение выгрузки в мультипараграфе
    IF(L = 1 AND LC = 'S' AND DATE_DEL IS NULL AND I$SUBTYPE IS NOT NULL) THEN
    BEGIN
      V = NULL;
      -- Образовательные программы и УП
      IF(V$PARENT_TYPE_ID = 69 AND V$OBJ_TYPE_ID = 57) THEN
      BEGIN
        SELECT FIRST 1 V.LISTVAL_ID
        FROM VALL V
        WHERE V.OBJ_ID = :OBJ_ID AND V.PARAM_ID = 1594 AND V.IS_DEL = 0
        INTO :V;
        IF(V = 5337 AND I$SUBTYPE = 'O') THEN LINK_ID = NULL;
        IF(V IN (5339, 5341, 5343, 13272, 5346, 5361) AND I$SUBTYPE = 'D') THEN LINK_ID = NULL;
      END
      -- Уровни образования
      IF(V$PARENT_TYPE_ID = 2 AND V$OBJ_TYPE_ID = 7) THEN
      BEGIN
        SELECT FIRST 1 V.LISTVAL_ID
        FROM VALL V
        WHERE V.OBJ_ID = :OBJ_ID AND V.PARAM_ID = 43 AND V.IS_DEL = 0
        INTO :V;
        IF(V IN (3263, 3264) AND I$SUBTYPE = 'O') THEN LINK_ID = NULL;
        IF(V IN (22, 26, 27, 28, 29, 13129, 13131) AND I$SUBTYPE = 'D') THEN LINK_ID = NULL;
      END
      -- Предварительный прием
      IF(V$PARENT_TYPE_ID = 77 AND V$OBJ_TYPE_ID = 290) THEN
      BEGIN
        SELECT FIRST 1 LV.PARENT_ID
        FROM VALL V
        JOIN LISTVALS LV ON LV.LISTVAL_ID = V.LISTVAL_ID
        WHERE V.OBJ_ID = :OBJ_ID AND V.PARAM_ID = 2346 AND V.IS_DEL = 0
        INTO :V;
        IF(V IN (2140) AND I$SUBTYPE = 'O') THEN LINK_ID = NULL;
        IF(V IN (2141, 12941, 2142) AND I$SUBTYPE = 'D') THEN LINK_ID = NULL;
      END
      -- Обучающиеся в учебных коллективах
      IF(V$PARENT_TYPE_ID = 9 AND V$OBJ_TYPE_ID = 10) THEN
      BEGIN
        -- Это класс школы ?
        SELECT FIRST 1 V.LISTVAL_ID
        FROM LINKS LP8
        JOIN LINKS LP7 ON LP7.OBJ_ID = LP8.PARENT_ID AND LP7.PARENT_TYPE_ID = 7 AND LP7.DATE_DEL IS NULL
        JOIN VALL V ON V.OBJ_ID = LP7.PARENT_ID AND V.PARAM_ID = 43 AND V.IS_DEL = 0
        WHERE LP8.OBJ_ID = :PARENT_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
        INTO :V;
        -- Ученики классов, если они засветились в ДОУ
        IF(I$SUBTYPE = 'D' AND V IN (22, 26, 27)) THEN
        BEGIN
          V = NULL;
          D = NULL;
          SELECT FIRST 1 M.DATE_OUT, M.REASON_OUT
          FROM PERSON_MOVEMENTS M
          WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :OBJ_ID AND M.GROUP_TYPE_ID = 9 AND M.LEVEL_ID IN (3263, 3264)
          ORDER BY M.DATE_OUT DESC
          INTO :D, :V;
          -- Вообще не был в ДОУ - убираем
          IF(V IS NULL) THEN LINK_ID = NULL;
          -- Когда-то ушел из ДОУ и вернулся уже в школу, должна быть папка выбытия ДОУ
          ELSE IF(V IN (3278, 808)) THEN
          BEGIN
            SELECT FIRST 1 L8X.OBJ_ID
            FROM LINKS L2
            JOIN LINKS L79 ON L79.PARENT_ID = L2.OBJ_ID AND L79.OBJ_TYPE_ID = 79 AND L79.DATE_DEL IS NULL
            JOIN LINKS L8X ON L8X.PARENT_ID = L79.OBJ_ID AND L8X.OBJ_TYPE_ID IN (81, 82, 83) AND L8X.DATE_DEL IS NULL
            JOIN LINKS L10 ON L10.PARENT_ID = L8X.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.OBJ_ID = :OBJ_ID
            WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
            ORDER BY L10.DATE_INS DESC
            INTO :PARENT_ID;
          END
          -- Все остальные случаи заменяем на папку Окончил ДОУ того года
          ELSE
          BEGIN
            Y = EXTRACT(YEAR FROM D);
            SELECT FIRST 1 L83.OBJ_ID
            FROM LINKS L2
            JOIN LINKS L79 ON L79.PARENT_ID = L2.OBJ_ID AND L79.OBJ_TYPE_ID = 79 AND L79.DATE_DEL IS NULL
            JOIN LINKS L83 ON L83.PARENT_ID = L79.OBJ_ID AND L83.OBJ_TYPE_ID = 83 AND L83.DATE_DEL IS NULL
            JOIN VALL V450 ON V450.OBJ_ID = L83.OBJ_ID AND V450.PARAM_ID = 450 AND V450.IS_DEL = 0 AND V450.LISTVAL_ID = 3320
            JOIN VALI V451 ON V451.OBJ_ID = L83.OBJ_ID AND V451.PARAM_ID = 451 AND V451.IS_DEL = 0 AND V451.VAL = :Y
            WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
            INTO :PARENT_ID;
          END
        END
        -- Школьники, вернувшиеся обратно в ДОУ
        ELSE IF(I$SUBTYPE = 'O' AND V IN (3263, 3264)) THEN
        BEGIN
          V = NULL;
          D = NULL;
          SELECT FIRST 1 M.DATE_OUT, M.REASON_OUT
          FROM PERSON_MOVEMENTS M
          WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :OBJ_ID AND M.GROUP_TYPE_ID = 9 AND M.LEVEL_ID IN (22, 26, 27)
          ORDER BY M.DATE_OUT DESC
          INTO :D, :V;
          -- Вообще не был в школе - убираем
          IF(V IS NULL) THEN LINK_ID = NULL;
          -- Когда-то ушел из школы и вернулся в сад, должна быть папка выбытия школы
          ELSE
          BEGIN
            SELECT FIRST 1 L8X.OBJ_ID
            FROM LINKS L2
            JOIN LINKS L79 ON L79.PARENT_ID = L2.OBJ_ID AND L79.OBJ_TYPE_ID = 79 AND L79.DATE_DEL IS NULL
            JOIN LINKS L8X ON L8X.PARENT_ID = L79.OBJ_ID AND L8X.OBJ_TYPE_ID IN (81, 82, 83) AND L8X.DATE_DEL IS NULL
            JOIN LINKS L10 ON L10.PARENT_ID = L8X.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.OBJ_ID = :OBJ_ID
            WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
            ORDER BY L10.DATE_INS DESC
            INTO :PARENT_ID;
          END
        END
      END
      -- Обучающиеся в выбывших или окончивших
      IF(V$PARENT_TYPE_ID IN (81, 82, 83) AND V$OBJ_TYPE_ID = 10) THEN
      BEGIN
        SELECT FIRST 1 V.LISTVAL_ID
        FROM VALL V
        WHERE V.OBJ_ID = :PARENT_ID AND V.PARAM_ID IN (446, 447, 450) AND V.IS_DEL = 0
        INTO :V;
        -- Прячем в папках ДОУ
        IF(I$SUBTYPE = 'O' AND V IN (3320, 3321)) THEN LINK_ID = NULL;
        -- Прячем в папках ОУ
        IF(I$SUBTYPE = 'D' AND V NOT IN (3320, 3321)) THEN LINK_ID = NULL;
      END
      -- Должности
      IF(V$PARENT_TYPE_ID IN (2, 211) AND V$OBJ_TYPE_ID = 13) THEN
      BEGIN
        SELECT FIRST 1 V.LISTVAL_ID
        FROM VALL V
        WHERE V.OBJ_ID = :PARENT_ID AND V.PARAM_ID = 2102 AND V.IS_DEL = 0
        INTO :V;
        -- В ДОУ оставляем только директора (руководитель 1 уровня) и подразделение, в школьной оставляем всех
        IF(I$SUBTYPE = 'D') THEN
        BEGIN
          IF(V <> 14245 OR V IS NULL) THEN
          BEGIN
            V = NULL;
            SELECT FIRST 1 V.LISTVAL_ID
            FROM VALL V
            WHERE V.OBJ_ID = :OBJ_ID AND V.PARAM_ID = 64 AND V.IS_DEL = 0
            INTO :V;
            IF(V IS NULL OR V <> 56) THEN LINK_ID = NULL;
          END
        END
      END
      -- Сотрудники
      IF(V$PARENT_TYPE_ID IN (2, 211, 84) AND V$OBJ_TYPE_ID = 14) THEN
      BEGIN
        IF(I$SUBTYPE = 'D') THEN
        BEGIN
          IF(NOT EXISTS(
            SELECT FIRST 1 1
            FROM LINKS L15
            JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
            JOIN VALL V64 ON V64.OBJ_ID = LP13.PARENT_ID AND V64.PARAM_ID = 64 AND V64.IS_DEL = 0
            LEFT JOIN LINKS LP211 ON LP211.OBJ_ID = LP13.PARENT_ID AND LP211.PARENT_TYPE_ID = 211
            LEFT JOIN VALL V2102 ON V2102.OBJ_ID = LP211.PARENT_ID AND V2102.PARAM_ID = 2102 AND V2102.IS_DEL = 0
            WHERE L15.PARENT_ID = :OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
              AND (V2102.LISTVAL_ID = 14245 OR V64.LISTVAL_ID = 56)
          ))
          THEN
            LINK_ID = NULL;
        END
      END
      -- Назначение на должность
      IF(V$PARENT_TYPE_ID = 14 AND V$OBJ_TYPE_ID = 15) THEN
      BEGIN
        IF(I$SUBTYPE = 'D') THEN
        BEGIN
          IF(NOT EXISTS(
            SELECT FIRST 1 1
            FROM LINKS LP13
            JOIN VALL V64 ON V64.OBJ_ID = LP13.PARENT_ID AND V64.PARAM_ID = 64 AND V64.IS_DEL = 0
            LEFT JOIN LINKS LP211 ON LP211.OBJ_ID = LP13.PARENT_ID AND LP211.PARENT_TYPE_ID = 211
            LEFT JOIN VALL V2102 ON V2102.OBJ_ID = LP211.PARENT_ID AND V2102.PARAM_ID = 2102 AND V2102.IS_DEL = 0
            WHERE LP13.OBJ_ID = :OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
              AND (V2102.LISTVAL_ID = 14245 OR V64.LISTVAL_ID = 56)
          ))
          THEN
            LINK_ID = NULL;
        END
      END
    END
    IF (LINK_ID IS NOT NULL AND ((L = 2) OR (L = 3) OR ((LINK_ID / M) = G))) THEN SUSPEND;
  END

  -- Назначения на экзамены
  FOR
    SELECT L.LINK_ID, L.PARENT_ID, L.OBJ_ID, L.EXT_OBJ_ID, L.REASON_ID, L.DATE_INS, L.DATE_DEL
    FROM LINKS L
    JOIN TYPES T ON T.TYPE_ID = L.OBJ_TYPE_ID
    LEFT JOIN TYPES P ON P.TYPE_ID = L.PARENT_TYPE_ID
    WHERE L.OBJ_TYPE_ID = 120
      AND (L.PARENT_TYPE_ID = 10 OR L.PARENT_TYPE_ID = 126)
      AND (:I$REPL_DATE IS NULL OR L.DATE_MODIFY >= :I$REPL_DATE)
      AND ((:I$REPL_DATE IS NULL AND L.DATE_DEL IS NULL) OR :I$REPL_DATE IS NOT NULL)
    ORDER BY 1
    INTO :LINK_ID, :PARENT_ID, :OBJ_ID, :EXT_OBJ_ID, :REASON_ID, :DATE_INS, :DATE_DEL
  DO
  BEGIN
    IF ((L = 2) OR (L = 3) OR ((LINK_ID / M) = G)) THEN SUSPEND;
  END

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE EXPORT_LISTVALS (
    I$REPL_DATE TIMESTAMP = null)
RETURNS (
    LISTVAL_ID BIGINT,
    LIST_ID BIGINT,
    RES_ID BIGINT,
    PARENT_ID BIGINT,
    TAG VARCHAR(100),
    SORT_ORDER SMALLINT,
    COST FLOAT,
    IS_REPL SMALLINT,
    IS_DEL SMALLINT)
AS
declare variable G bigint;
declare variable M bigint;
declare variable L char(1);
BEGIN
    IS_REPL = 0;

    SELECT GEN, MULTIPLIER FROM GEN INTO :G, :M;
    SELECT K.KEY_VAL FROM KEYS K WHERE K.KEY_CODE = 'LEVEL' INTO :L;

    FOR
        SELECT
            LV.LISTVAL_ID,
            LV.LIST_ID,
            LV.RES_ID,
            LV.PARENT_ID,
            LV.TAG,
            LV.SORT_ORDER,
            LV.COST,
            LV.IS_DEL
        FROM LISTVALS LV
        JOIN LISTS L
        ON L.LIST_ID = LV.LIST_ID

        WHERE L.FOR_REPL_UP = 1
        AND ((:I$REPL_DATE IS NULL) OR (LV.DATE_MODIFY >= :I$REPL_DATE))
        INTO :LISTVAL_ID,
            :LIST_ID,
            :PARENT_ID,
            :RES_ID,
            :TAG,
            :SORT_ORDER,
            :COST,
            :IS_DEL
    DO
    BEGIN
        IF ((L = '2') OR (L = '3') OR ((LISTVAL_ID / M) = G))  THEN SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE EXPORT_LOCAL_DO_FUNC RETURNS (
    OBJ_ID BIGINT,
    PARAM_ID BIGINT,
    DO_FUNC BIGINT,
    VAL VARCHAR(4000))
AS
declare variable CALC_ORDER bigint;
BEGIN
    FOR
        SELECT O.OBJ_ID, P.PARAM_ID, P.DO_FUNC, IIF(P.DO_FUNC = 1034, 0, P.DO_FUNC)
        FROM PARAMS P
        JOIN OBJECTS O ON O.TYPE_ID = P.TYPE_ID
        LEFT JOIN IS_NATIVE_ID(O.OBJ_ID) N ON 1 = 1
        -- Перерасчет делается только для нативных объектов (созданных в текущей базе)
        -- СМИР, изменения в названиях предметов УП (изменения в предметах стоят первые по порядку в пересчете)
        WHERE N.IS_NATIVE = 1 AND ((P.DO_FUNC > 9999990) OR (P.DO_FUNC IN (1027, 1028, 1029, 1031, 1032, 1034, 1048))) AND P.IS_DEL = 0
        ORDER BY 4
        INTO :OBJ_ID, :PARAM_ID, :DO_FUNC, :CALC_ORDER
    DO
    BEGIN
        SELECT VAL
        FROM DO_FUNC(:OBJ_ID, :PARAM_ID, :DO_FUNC)
        INTO :VAL;
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE EXPORT_METADATA RETURNS (
    OBJ_ID BIGINT,
    ATTRNAME VARCHAR(100),
    ATTRVALUE VARCHAR(4000))
AS
declare variable KEY_LEVEL smallint;
declare variable KEY_TYPE char(1);
declare variable V$PUPIL_ID bigint;
declare variable V$CLASS_ID bigint;
declare variable V$MARK_DATE date;
declare variable V$APPLY_DATE date;
declare variable V$SUBJECT_ID bigint;
declare variable V$MARK_OLD varchar(1000);
declare variable V$MARK_NEW varchar(1000);
declare variable V$REASON varchar(1000);
declare variable V$USER_ID bigint;
declare variable V$LESSON_ID bigint;
declare variable V$FINAL_ID bigint;
begin
  -- На уровне ОУ формируем первичные данные, на уровне района просто выбираем ранее загруженные данные
  SELECT KEY_VAL FROM KEYS WHERE KEY_CODE = 'LEVEL' INTO :KEY_LEVEL;
  IF(KEY_LEVEL IS NULL) THEN EXCEPTION DATA_ERROR 'Уровень лицензии неизвестен, выгрузка невозможна';

  SELECT STATUS FROM OU_LICENCE_TYPE INTO :KEY_TYPE;
  IF(KEY_TYPE <> 'O') THEN EXIT;

  IF(KEY_LEVEL >= 2) THEN
  BEGIN

    -- Просто перегружаем ранее загруженное
    FOR
        SELECT OBJ_ID, ATTRNAME, ATTRVALUE
        FROM CS_METADATA
        INTO :OBJ_ID, :ATTRNAME, :ATTRVALUE
    DO
    BEGIN
        SUSPEND;
    END

  END
  ELSE
  BEGIN

    -- Исправления КЖ - только основные ОП
    /*FOR
        SELECT CJMH.MARK_HST_ID, CJMH.PUPIL_ID, LP9.PARENT_ID, CJMH.MARK_DATE, CJMH.DATE_MODIFY, CJM.SUBJECT_ID,
            TRIM(CJMH.MARK_OLD), TRIM(CJMH.MARK_NEW), TRIM(CJMH.REASON), U.OBJ_ID, CJMH.LESSON_ID, CJMH.FINAL_ID
        FROM CJ_MARK_HST CJMH
        LEFT JOIN CJ_LESSON CJL ON CJMH.LESSON_ID = CJL.LESSON_ID
        LEFT JOIN CJ_FINAL CJF ON CJMH.FINAL_ID = CJF.FINAL_ID
        JOIN CJ_MAIN CJM ON CJM.CJ_ID = COALESCE(CJL.CJ_ID, CJF.CJ_ID)
        JOIN LINKS LP9 ON LP9.OBJ_ID = CJMH.PUPIL_ID AND LP9.PARENT_TYPE_ID IN (9, 125, 187) AND LP9.DATE_DEL IS NULL
        LEFT JOIN USERS U ON U.USER_ID = CJMH.USER_ID
        WHERE CJMH.PUPIL_ID IS NOT NULL
        INTO :OBJ_ID, :V$PUPIL_ID, :V$CLASS_ID, :V$MARK_DATE, :V$APPLY_DATE, :V$SUBJECT_ID, :V$MARK_OLD, :V$MARK_NEW,
            :V$REASON, :V$USER_ID, :V$LESSON_ID, :V$FINAL_ID
    DO
    BEGIN
        ATTRNAME = 'PUPIL_ID';
        ATTRVALUE = V$PUPIL_ID;
        SUSPEND;
        ATTRNAME = 'CLASS_ID';
        ATTRVALUE = V$CLASS_ID;
        SUSPEND;
        ATTRNAME = 'MARK_DATE';
        SELECT RESULT FROM DATE2STR(:V$MARK_DATE) INTO :ATTRVALUE;
        SUSPEND;
        ATTRNAME = 'APPLY_DATE';
        SELECT RESULT FROM DATE2STR(:V$APPLY_DATE) INTO :ATTRVALUE;
        SUSPEND;
        ATTRNAME = 'USER_ID';
        ATTRVALUE = COALESCE(V$USER_ID, '');
        SUSPEND;
        ATTRNAME = 'SUBJECT_ID';
        ATTRVALUE = V$SUBJECT_ID;
        SUSPEND;
        ATTRNAME = 'MARK_OLD';
        ATTRVALUE = V$MARK_OLD;
        SUSPEND;
        ATTRNAME = 'MARK_NEW';
        ATTRVALUE = V$MARK_NEW;
        SUSPEND;
        ATTRNAME = 'REASON';
        ATTRVALUE = V$REASON;
        SUSPEND;
        ATTRNAME = 'CONTROL';
        IF(V$LESSON_ID IS NULL) THEN ATTRVALUE = '';
        ELSE ATTRVALUE = (
            SELECT LIST(R.VAL, ', ')
            FROM CJ_CONTROL CJC
            JOIN LISTVALS LV ON LV.LISTVAL_ID = CJC.CONTROL_TYPE_ID
            JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
            WHERE CJC.LESSON_ID = :V$LESSON_ID
        );
        SUSPEND;
    END*/

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE EXPORT_MI RETURNS (
    ORG_ID BIGINT,
    PARAM_ID VARCHAR(100),
    VAL VARCHAR(400))
AS
DECLARE VARIABLE V$MD DATE;
DECLARE VARIABLE V$MON_ID BIGINT;
DECLARE VARIABLE ORG_ID_MIN BIGINT;
DECLARE VARIABLE ORG_ID_MAX BIGINT;
DECLARE VARIABLE N_EMP INTEGER;
DECLARE VARIABLE N_EMP_PREV INTEGER;
DECLARE VARIABLE N_EMP_EDU INTEGER;
DECLARE VARIABLE N_EMP_EDU35 INTEGER;
DECLARE VARIABLE N_ADAPT INTEGER;
DECLARE VARIABLE N_ADAPT_TEACHERS INTEGER;
DECLARE VARIABLE I BIGINT;
DECLARE VARIABLE ITOTAL INTEGER;
DECLARE VARIABLE IPREV INTEGER;
DECLARE VARIABLE V1 DOUBLE PRECISION;
DECLARE VARIABLE V2 DOUBLE PRECISION;
begin

  V$MD = DATEADD(-1 MONTH TO CURRENT_DATE);

  FOR
    SELECT L2.OBJ_ID, L162.OBJ_ID
    FROM LINKS L2
    JOIN LINKS L162 ON L162.PARENT_ID = L2.OBJ_ID AND L162.OBJ_TYPE_ID = 162 AND L162.DATE_DEL IS NULL
    WHERE L2.PARENT_TYPE_ID = 111 AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    ORDER BY 1
    INTO :ORG_ID, :V$MON_ID
  DO
  BEGIN
    ORG_ID_MIN = ORG_ID / 1000000000;
    ORG_ID_MAX = (ORG_ID_MIN + 1) * 1000000000;
    ORG_ID_MIN = ORG_ID_MIN * 1000000000;

    PARAM_ID = 'director_name';
    SELECT FIRST 1 F || ' ' || I || COALESCE(' ' || O, '')
    FROM R_SPB_POST_DIRECTOR(:ORG_ID, 1)
    INTO :VAL;
    SUSPEND;

    PARAM_ID = 'director_phone';
    VAL = NULL;
    SELECT FIRST 1 V.VAL
    FROM VALS V
    WHERE V.OBJ_ID = :ORG_ID AND V.PARAM_ID = 28 AND V.IS_DEL = 0
    INTO :VAL;
    SUSPEND;

    PARAM_ID = 'contact_phone';
    VAL = NULL;
    SELECT FIRST 1 V.VAL
    FROM VALS V
    WHERE V.OBJ_ID = :ORG_ID AND V.PARAM_ID = 29 AND V.IS_DEL = 0
    INTO :VAL;
    SUSPEND;

    PARAM_ID = 'contact_fax';
    VAL = NULL;
    SELECT FIRST 1 V.VAL
    FROM VALS V
    WHERE V.OBJ_ID = :ORG_ID AND V.PARAM_ID = 30 AND V.IS_DEL = 0
    INTO :VAL;
    SUSPEND;

    PARAM_ID = 'n_buildings';
    VAL = NULL;
    --SELECT V FROM VAL_GET(:V$MON_ID, 1435) INTO :VAL;
    SELECT COUNT(*)
    FROM LINKS L73
    JOIN LINKS L16 ON L16.PARENT_ID = L73.OBJ_ID AND L16.OBJ_TYPE_ID = 16 AND L16.DATE_DEL IS NULL
    JOIN VALL V485 ON V485.OBJ_ID = L16.OBJ_ID AND V485.PARAM_ID = 485 AND V485.IS_DEL = 0 AND V485.LISTVAL_ID = 1093
    JOIN VALS V421 ON V421.OBJ_ID = L16.OBJ_ID AND V421.PARAM_ID = 421 AND V421.IS_DEL = 0 AND NOT V421.VAL LIKE '%ошкольн%'
    WHERE L73.PARENT_ID = :ORG_ID AND L73.OBJ_TYPE_ID = 73 AND L73.DATE_DEL IS NULL
    INTO :VAL;
    SUSPEND;

    PARAM_ID = 'square_total';
    VAL = NULL;
    SELECT V
    FROM VAL_GET(:V$MON_ID, 1436)
    INTO :VAL;
    SUSPEND;

    PARAM_ID = 'square_edu';
    VAL = NULL;
    SELECT V
    FROM VAL_GET(:V$MON_ID, 1437)
    INTO :VAL;
    SUSPEND;

    PARAM_ID = 'square_land';
    VAL = NULL;
    SELECT V
    FROM VAL_GET(:V$MON_ID, 1437)
    INTO :VAL;
    SUSPEND;

    PARAM_ID = 'has_land_fence';
    VAL = NULL;
    SELECT V
    FROM VAL_GET(:V$MON_ID, 1477)
    INTO :VAL;
    IF(VAL = 'Да') THEN VAL = '1'; ELSE VAL = '0';
    SUSPEND;

    PARAM_ID = 'n_computer_classes';
    VAL = NULL;
    SELECT V
    FROM VAL_GET(:V$MON_ID, 1452)
    INTO :VAL;
    SUSPEND;

    PARAM_ID = 'n_computers_total';
    VAL = NULL;
    SELECT V
    FROM VAL_GET(:V$MON_ID, 1727)
    INTO :VAL;
    SUSPEND;

    PARAM_ID = 'n_computers_adm';
    VAL = NULL;
    SELECT V
    FROM VAL_GET(:V$MON_ID, 1728)
    INTO :VAL;
    SUSPEND;

    PARAM_ID = 'n_computers_cls';
    VAL = NULL;
    SELECT V
    FROM VAL_GET(:V$MON_ID, 1453)
    INTO :VAL;
    SUSPEND;

    PARAM_ID = 'n_sport_rooms';
    VAL = NULL;
    SELECT V
    FROM VAL_GET(:V$MON_ID, 1460)
    INTO :VAL;
    SUSPEND;

    PARAM_ID = 'square_sport_rooms';
    VAL = NULL;
    SELECT V
    FROM VAL_GET(:V$MON_ID, 1464)
    INTO :VAL;
    SUSPEND;

    PARAM_ID = 'has_swimpool';
    VAL = NULL;
    SELECT V
    FROM VAL_GET(:V$MON_ID, 1468)
    INTO :VAL;
    IF(VAL = 'Да') THEN VAL = '1'; ELSE VAL = '0';
    SUSPEND;

    PARAM_ID = 'square_swimpool';
    VAL = NULL;
    SELECT V
    FROM VAL_GET(:V$MON_ID, 2521)
    INTO :VAL;
    SUSPEND;

    PARAM_ID = 'has_museum';
    VAL = NULL;
    SELECT V
    FROM VAL_GET(:V$MON_ID, 1469)
    INTO :VAL;
    IF(VAL = 'Да') THEN VAL = '1'; ELSE VAL = '0';
    SUSPEND;

    PARAM_ID = 'has_diningroom';
    VAL = NULL;
    SELECT V
    FROM VAL_GET(:V$MON_ID, 1471)
    INTO :VAL;
    IF(VAL = 'Да') THEN VAL = '1'; ELSE VAL = '0';
    SUSPEND;

    PARAM_ID = 'diningroom_pers';
    VAL = NULL;
    SELECT V
    FROM VAL_GET(:V$MON_ID, 1472)
    INTO :VAL;
    SUSPEND;

    PARAM_ID = 'has_sps_room';
    VAL = NULL;
    SELECT V
    FROM VAL_GET(:V$MON_ID, 1470)
    INTO :VAL;
    IF(VAL = 'Да') THEN VAL = '1'; ELSE VAL = '0';
    SUSPEND;

    PARAM_ID = 'n_workrooms';
    VAL = NULL;
    SELECT V
    FROM VAL_GET(:V$MON_ID, 1473)
    INTO :VAL;
    SUSPEND;

    PARAM_ID = 'has_playground';
    VAL = NULL;
    SELECT V
    FROM VAL_GET(:V$MON_ID, 1474)
    INTO :VAL;
    IF(VAL = 'Да') THEN VAL = '1'; ELSE VAL = '0';
    SUSPEND;

    PARAM_ID = 'has_stadium';
    VAL = NULL;
    SELECT V
    FROM VAL_GET(:V$MON_ID, 1475)
    INTO :VAL;
    IF(VAL = 'Да') THEN VAL = '1'; ELSE VAL = '0';
    SUSPEND;

    PARAM_ID = 'has_cars';
    VAL = NULL;
    SELECT V
    FROM VAL_GET(:V$MON_ID, 1492)
    INTO :VAL;
    IF(VAL = 'Да') THEN VAL = '1'; ELSE VAL = '0';
    SUSPEND;

    PARAM_ID = 'n_buses';
    VAL = NULL;
    SELECT V
    FROM VAL_GET(:V$MON_ID, 1493)
    INTO :VAL;
    IF(VAL = 'Да') THEN VAL = '1'; ELSE VAL = '0';
    SUSPEND;

    PARAM_ID = 'has_odod';
    VAL = NULL;
    SELECT V
    FROM VAL_GET(:V$MON_ID, 1479)
    INTO :VAL;
    IF(VAL = 'Да') THEN VAL = '1'; ELSE VAL = '0';
    SUSPEND;

    PARAM_ID = 'n_pupil_in';
    VAL = NULL;
    SELECT V
    FROM VAL_GET(:V$MON_ID, 1596)
    INTO :VAL;
    SUSPEND;

    PARAM_ID = 'n_pupil_out';
    VAL = NULL;
    SELECT V
    FROM VAL_GET(:V$MON_ID, 1597)
    INTO :VAL;
    SUSPEND;

    PARAM_ID = 'n_pupil_home';
    VAL = NULL;
    SELECT COUNT(*)
    FROM LINKS L7
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN LINKS L187 ON L187.PARENT_ID = L8.OBJ_ID AND L187.OBJ_TYPE_ID = 187 AND L187.DATE_DEL IS NULL
    JOIN LINKS L10 ON L10.PARENT_ID = L187.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    WHERE L7.PARENT_ID = :ORG_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    INTO :VAL;
    SUSPEND;

    -- Всего сотрудников
    PARAM_ID = 'n_emp_total';
    N_EMP = NULL;
    SELECT COUNT(*)
    FROM LINKS L14
    WHERE L14.PARENT_ID = :ORG_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
    INTO :N_EMP;
    VAL = N_EMP;
    SUSPEND;

    PARAM_ID = 'n_emp_management';
    VAL = NULL;
    SELECT V
    FROM VAL_GET(:V$MON_ID, 1547)
    INTO :VAL;
    SUSPEND;

    -- Педагогических сотрудников
    PARAM_ID = 'n_emp_edu';
    N_EMP_EDU = NULL;
    SELECT V
    FROM VAL_GET(:V$MON_ID, 1542)
    INTO :N_EMP_EDU;
    VAL = N_EMP_EDU;
    SUSPEND;

    PARAM_ID = 'n_emp_work';
    VAL = NULL;
    SELECT V
    FROM VAL_GET(:V$MON_ID, 1544)
    INTO :VAL;
    SUSPEND;

    PARAM_ID = 'n_emp_teachers';
    VAL = NULL;
    SELECT V
    FROM VAL_GET(:V$MON_ID, 1546)
    INTO :VAL;
    SUSPEND;

    -- 1..12
    I = 1;
    WHILE(I <= 12) DO
    BEGIN
      PARAM_ID = 'n_classes_' || IIF(I < 10, '0' || I, I);
      VAL = NULL;
      SELECT COUNT(DISTINCT M.GROUP_ID)
      FROM PERSON_MOVEMENTS M
      JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
      WHERE M.DATE_DEL IS NULL AND M.STAGE_ID = :I + 36 AND M.DATE_OUT IS NULL AND M.OBJ_ID >= :ORG_ID_MIN AND M.OBJ_ID < :ORG_ID_MAX
      INTO :VAL;
      SUSPEND;

      PARAM_ID = 'n_students_' || IIF(I < 10, '0' || I, I);
      VAL = NULL;
      SELECT COUNT(*)
      FROM PERSON_MOVEMENTS M
      JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
      WHERE M.DATE_DEL IS NULL AND M.STAGE_ID = :I + 36 AND M.DATE_OUT IS NULL AND M.OBJ_ID >= :ORG_ID_MIN AND M.OBJ_ID < :ORG_ID_MAX
      INTO :VAL;
      SUSPEND;

      I = I + 1;
    END

    PARAM_ID = 'n_emp_notedu';
    VAL = NULL;
    SELECT FIRST 1 V.VAL
    FROM LINKS L340
    JOIN VALI V ON V.OBJ_ID = L340.OBJ_ID AND V.PARAM_ID = 2664 AND V.IS_DEL = 0
    WHERE L340.PARENT_ID = :V$MON_ID AND L340.OBJ_TYPE_ID = 340 AND L340.DATE_DEL IS NULL
    INTO :VAL;
    SUSPEND;

    PARAM_ID = 'n_emp_studyup';
    VAL = NULL;
    SELECT FIRST 1 V.VAL
    FROM LINKS L340
    JOIN VALI V ON V.OBJ_ID = L340.OBJ_ID AND V.PARAM_ID = 2665 AND V.IS_DEL = 0
    WHERE L340.PARENT_ID = :V$MON_ID AND L340.OBJ_TYPE_ID = 340 AND L340.DATE_DEL IS NULL
    INTO :VAL;
    SUSPEND;

    PARAM_ID = 'n_students_total';
    ITOTAL = NULL;
    SELECT V
    FROM VAL_GET(:V$MON_ID, 1433)
    INTO :ITOTAL;
    VAL = ITOTAL;
    SUSPEND;

    PARAM_ID = 'n_students_std';
    VAL = NULL;
    SELECT V
    FROM VAL_GET(:V$MON_ID, 1432)
    INTO :VAL;
    SUSPEND;

    PARAM_ID = 'n_students_prj';
    VAL = NULL;
    SELECT V
    FROM VAL_GET(:V$MON_ID, 2193)
    INTO :VAL;
    SUSPEND;

    PARAM_ID = 'n_plans_miss_hours';
    VAL = NULL;
    SELECT COUNT(*)
    FROM (
      SELECT L305.OBJ_ID
      FROM LINKS L305
      JOIN VALL V2486 ON V2486.OBJ_ID = L305.OBJ_ID AND V2486.PARAM_ID = 2486 AND V2486.IS_DEL = 0 AND V2486.LISTVAL_ID = 3
      WHERE L305.PARENT_ID = :V$MON_ID AND L305.OBJ_TYPE_ID = 305 AND L305.DATE_DEL IS NULL
      UNION
      SELECT L357.OBJ_ID
      FROM LINKS L357
      JOIN VALL V2926 ON V2926.OBJ_ID = L357.OBJ_ID AND V2926.PARAM_ID = 2926 AND V2926.IS_DEL = 0 AND V2926.LISTVAL_ID = 3
      WHERE L357.PARENT_ID = :V$MON_ID AND L357.OBJ_TYPE_ID = 357 AND L357.DATE_DEL IS NULL
    )
    INTO :VAL;
    SUSPEND;

    PARAM_ID = 'n_plans_miss_subj';
    VAL = NULL;
    SELECT COUNT(*)
    FROM (
      SELECT L305.OBJ_ID
      FROM LINKS L305
      JOIN VALL V2487 ON V2487.OBJ_ID = L305.OBJ_ID AND V2487.PARAM_ID = 2486 AND V2487.IS_DEL = 0 AND V2487.LISTVAL_ID = 3
      WHERE L305.PARENT_ID = :V$MON_ID AND L305.OBJ_TYPE_ID = 305 AND L305.DATE_DEL IS NULL
      UNION
      SELECT L357.OBJ_ID
      FROM LINKS L357
      JOIN VALL V2725 ON V2725.OBJ_ID = L357.OBJ_ID AND V2725.PARAM_ID = 2752 AND V2725.IS_DEL = 0 AND V2725.LISTVAL_ID = 3
      WHERE L357.PARENT_ID = :V$MON_ID AND L357.OBJ_TYPE_ID = 357 AND L357.DATE_DEL IS NULL
    )
    INTO :VAL;
    SUSPEND;

    PARAM_ID = 'n_plans_miss_h1';
    VAL = NULL;
    SELECT COUNT(*)
    FROM (
      SELECT L305.OBJ_ID
      FROM LINKS L305
      JOIN VALL V2488 ON V2488.OBJ_ID = L305.OBJ_ID AND V2488.PARAM_ID = 2486 AND V2488.IS_DEL = 0 AND V2488.LISTVAL_ID = 3
      WHERE L305.PARENT_ID = :V$MON_ID AND L305.OBJ_TYPE_ID = 305 AND L305.DATE_DEL IS NULL
      UNION
      SELECT L357.OBJ_ID
      FROM LINKS L357
      JOIN VALL V2756 ON V2756.OBJ_ID = L357.OBJ_ID AND V2756.PARAM_ID = 2752 AND V2756.IS_DEL = 0 AND V2756.LISTVAL_ID = 3
      WHERE L357.PARENT_ID = :V$MON_ID AND L357.OBJ_TYPE_ID = 357 AND L357.DATE_DEL IS NULL
    )
    INTO :VAL;
    SUSPEND;

    PARAM_ID = 'n_plans_miss_h2';
    VAL = NULL;
    SELECT COUNT(*)
    FROM (
      SELECT L305.OBJ_ID
      FROM LINKS L305
      JOIN VALL V2489 ON V2489.OBJ_ID = L305.OBJ_ID AND V2489.PARAM_ID = 2486 AND V2489.IS_DEL = 0 AND V2489.LISTVAL_ID = 3
      WHERE L305.PARENT_ID = :V$MON_ID AND L305.OBJ_TYPE_ID = 305 AND L305.DATE_DEL IS NULL
      UNION
      SELECT L357.OBJ_ID
      FROM LINKS L357
      JOIN VALL V2757 ON V2757.OBJ_ID = L357.OBJ_ID AND V2757.PARAM_ID = 2752 AND V2757.IS_DEL = 0 AND V2757.LISTVAL_ID = 3
      WHERE L357.PARENT_ID = :V$MON_ID AND L357.OBJ_TYPE_ID = 357 AND L357.DATE_DEL IS NULL
    )
    INTO :VAL;
    SUSPEND;

    PARAM_ID = 'n_plans_total';
    VAL = NULL;
    SELECT COUNT(*)
    FROM (
      SELECT L305.OBJ_ID
      FROM LINKS L305
      WHERE L305.PARENT_ID = :V$MON_ID AND L305.OBJ_TYPE_ID = 305 AND L305.DATE_DEL IS NULL
      UNION
      SELECT L357.OBJ_ID
      FROM LINKS L357
      WHERE L357.PARENT_ID = :V$MON_ID AND L357.OBJ_TYPE_ID = 357 AND L357.DATE_DEL IS NULL
    )
    INTO :VAL;
    SUSPEND;

    -- Берем из списка 316 - в 315 было пусто на момент создания отчета
    PARAM_ID = 'n_journals_total';
    VAL = NULL;
    SELECT COUNT(*)
    FROM LINKS L315
    WHERE L315.PARENT_ID = :V$MON_ID AND L315.OBJ_TYPE_ID = 316 AND L315.DATE_DEL IS NULL
    INTO :VAL;
    SUSPEND;

    PARAM_ID = 'n_journals_miss_ptp';
    VAL = NULL;
    SELECT COUNT(*)
    FROM LINKS L313
    WHERE L313.PARENT_ID = :V$MON_ID AND L313.OBJ_TYPE_ID = 313 AND L313.DATE_DEL IS NULL
    INTO :VAL;
    SUSPEND;

    PARAM_ID = 'n_students_miss_books1';
    VAL = NULL;
    SELECT SUM(V.VAL)
    FROM LINKS L345
    JOIN VALI V ON V.OBJ_ID = L345.OBJ_ID AND V.PARAM_ID = 2688 AND V.IS_DEL = 0
    WHERE L345.PARENT_ID = :V$MON_ID AND L345.OBJ_TYPE_ID = 345 AND L345.DATE_DEL IS NULL
    INTO :VAL;
    SUSPEND;

    PARAM_ID = 'n_students_miss_books2';
    VAL = NULL;
    SELECT SUM(V.VAL)
    FROM LINKS L345
    JOIN VALI V ON V.OBJ_ID = L345.OBJ_ID AND V.PARAM_ID = 2689 AND V.IS_DEL = 0
    WHERE L345.PARENT_ID = :V$MON_ID AND L345.OBJ_TYPE_ID = 345 AND L345.DATE_DEL IS NULL
    INTO :VAL;
    SUSPEND;

    PARAM_ID = 'n_students_miss_books3';
    VAL = NULL;
    SELECT SUM(V.VAL)
    FROM LINKS L345
    JOIN VALI V ON V.OBJ_ID = L345.OBJ_ID AND V.PARAM_ID = 2690 AND V.IS_DEL = 0
    WHERE L345.PARENT_ID = :V$MON_ID AND L345.OBJ_TYPE_ID = 345 AND L345.DATE_DEL IS NULL
    INTO :VAL;
    SUSPEND;

    PARAM_ID = 'n_students_miss_books4';
    VAL = NULL;
    SELECT SUM(V.VAL)
    FROM LINKS L345
    JOIN VALI V ON V.OBJ_ID = L345.OBJ_ID AND V.PARAM_ID = 2691 AND V.IS_DEL = 0
    WHERE L345.PARENT_ID = :V$MON_ID AND L345.OBJ_TYPE_ID = 345 AND L345.DATE_DEL IS NULL
    INTO :VAL;
    SUSPEND;

    PARAM_ID = 'n_students_miss_books5x';
    VAL = NULL;
    SELECT SUM(V.VAL)
    FROM LINKS L345
    JOIN VALI V ON V.OBJ_ID = L345.OBJ_ID AND V.PARAM_ID = 2692 AND V.IS_DEL = 0
    WHERE L345.PARENT_ID = :V$MON_ID AND L345.OBJ_TYPE_ID = 345 AND L345.DATE_DEL IS NULL
    INTO :VAL;
    SUSPEND;

    -- Новые параметры 01.2022
    -- Темп роста количества обучающихся на одного работника. Текущее количество учеников хранится в I
    IPREV = NULL;
    SELECT COUNT(*)
    FROM PERSON_MOVEMENTS M
    JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
    WHERE M.DATE_DEL IS NULL AND M.OBJ_ID >= :ORG_ID_MIN AND M.OBJ_ID < :ORG_ID_MAX
      AND M.DATE_IN <= :V$MD AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :V$MD)
    INTO :IPREV;

    N_EMP_PREV = NULL;
    SELECT COUNT(DISTINCT L14.OBJ_ID)
    FROM LINKS L14
    JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
    JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0 AND V73.VAL <= :V$MD
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
    WHERE L14.PARENT_ID = :ORG_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL AND (V74.VAL IS NULL OR V74.VAL >= :V$MD)
    INTO :N_EMP_PREV;

    IF(N_EMP = 0 OR N_EMP IS NULL) THEN V1 = NULL; ELSE V1 = 1.0 * ITOTAL / N_EMP;
    IF(N_EMP_PREV = 0 OR N_EMP_PREV IS NULL) THEN V2 = NULL; ELSE V2 = 1.0 * IPREV / N_EMP_PREV;
    PARAM_ID = 'r_std_per_teacher_grow';
    IF(V1 IS NULL OR V2 IS NULL OR V2 = 0) THEN VAL = NULL;
    ELSE VAL = 100.0 * (V1 - V2) / V2;
    SUSPEND;

    -- Доля педагогических работников до 35 лет
    N_EMP_EDU35 = NULL;
    SELECT COUNT(DISTINCT L14.OBJ_ID)
    FROM LINKS L14
    JOIN VALD V241 ON V241.OBJ_ID = L14.OBJ_ID AND V241.PARAM_ID = 241 AND V241.IS_DEL = 0 AND V241.VAL >= DATEADD(-35 YEAR TO CURRENT_DATE)
    JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
    JOIN VALL V1394 ON V1394.OBJ_ID = L15.OBJ_ID AND V1394.PARAM_ID = 1394 AND V1394.IS_DEL = 0
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V1394.LISTVAL_ID AND (LV.LISTVAL_ID IN (127, 1281) OR LV.PARENT_ID IN (98, 125, 129, 131, 56, 113, 70))
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
    WHERE L14.PARENT_ID = :ORG_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL AND V74.VAL IS NULL
    INTO :N_EMP_EDU35;

    PARAM_ID = 'r_emp_edu_35';
    IF(N_EMP_EDU35 IS NULL OR N_EMP_EDU IS NULL OR N_EMP_EDU = 0) THEN VAL = '';
    ELSE VAL = 100.0 * N_EMP_EDU35 / N_EMP_EDU;
    SUSPEND;

    -- Количество обучающихся на одного дефектолога/логопеда
    N_ADAPT_TEACHERS = NULL;
    SELECT COUNT(DISTINCT L14.OBJ_ID)
    FROM LINKS L14
    JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
    JOIN VALL V1394 ON V1394.OBJ_ID = L15.OBJ_ID AND V1394.PARAM_ID = 1394 AND V1394.IS_DEL = 0
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V1394.LISTVAL_ID AND LV.LISTVAL_ID IN (119, 120)
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
    WHERE L14.PARENT_ID = :ORG_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL AND V74.VAL IS NULL
    INTO :N_ADAPT_TEACHERS;

    N_ADAPT = NULL;
    SELECT COUNT(*)
    FROM LINKS L7
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
    JOIN VALL V554 ON V554.OBJ_ID = L9.OBJ_ID AND V554.PARAM_ID = 554 AND V554.IS_DEL = 0 AND V554.LISTVAL_ID <> 1355
    JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L8.DATE_DEL IS NULL
    WHERE L7.PARENT_ID = :ORG_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    INTO :N_ADAPT;

    PARAM_ID = 'n_emp_adapt_stdpertch';
    IF(N_ADAPT IS NULL OR N_ADAPT_TEACHERS IS NULL OR N_ADAPT_TEACHERS = 0) THEN VAL = '';
    ELSE VAL = 1.0 * N_ADAPT / N_ADAPT_TEACHERS;
    SUSPEND;

    -- То же, но для умственной отсталости
    N_ADAPT = NULL;
    SELECT COUNT(*)
    FROM LINKS L7
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
    JOIN VALL V554 ON V554.OBJ_ID = L9.OBJ_ID AND V554.PARAM_ID = 554 AND V554.IS_DEL = 0 AND V554.LISTVAL_ID = 13283
    JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L8.DATE_DEL IS NULL
    WHERE L7.PARENT_ID = :ORG_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    INTO :N_ADAPT;

    PARAM_ID = 'n_emp_adapt2_stdpertch';
    IF(N_ADAPT IS NULL OR N_ADAPT_TEACHERS IS NULL OR N_ADAPT_TEACHERS = 0) THEN VAL = '';
    ELSE VAL = 1.0 * N_ADAPT / N_ADAPT_TEACHERS;
    SUSPEND;

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE EXPORT_MOVEMENTS (
    I$REPL_DATE TIMESTAMP = null)
RETURNS (
    OBJ_ID BIGINT,
    DATE_ADD TIMESTAMP,
    DATE_MODIFY TIMESTAMP,
    DATE_DEL TIMESTAMP,
    PERSON_ID BIGINT,
    GROUP_ID BIGINT,
    REASON_IN BIGINT,
    DATE_IN DATE,
    DATE_OUT DATE,
    STAGE_ID BIGINT,
    ORDER_DATE_IN DATE,
    ORDER_NUM_IN VARCHAR(40),
    ORDER_DATE_OUT DATE,
    ORDER_NUM_OUT VARCHAR(40),
    ORDER_ID_IN BIGINT,
    ORDER_ID_OUT BIGINT,
    NAME_IN VARCHAR(400),
    REASON_OUT BIGINT,
    USER_IN BIGINT,
    USER_OUT BIGINT,
    TYPE_IN BIGINT,
    IS_VD SMALLINT,
    SOURCE_IN BIGINT,
    SOURCE_OUT BIGINT,
    PLAN_STAGES SMALLINT,
    STAGE_YEAR SMALLINT,
    GROUP_TYPE_ID BIGINT,
    LEVEL_ID BIGINT,
    OU_ID BIGINT)
AS
begin

  -- Движения выгружаем только по живым ученикам

  FOR
    SELECT OBJ_ID, DATE_ADD, DATE_MODIFY, DATE_DEL, PERSON_ID, GROUP_ID, REASON_IN, DATE_IN, DATE_OUT, STAGE_ID,
      ORDER_DATE_IN, ORDER_NUM_IN, ORDER_DATE_OUT, ORDER_NUM_OUT, ORDER_ID_IN, ORDER_ID_OUT, NAME_IN, REASON_OUT, USER_IN, USER_OUT, TYPE_IN, IS_VD, SOURCE_IN, SOURCE_OUT,
      PLAN_STAGES, STAGE_YEAR, GROUP_TYPE_ID, LEVEL_ID, OU_ID
    FROM PERSON_MOVEMENTS
    WHERE :I$REPL_DATE IS NULL OR DATE_MODIFY >= :I$REPL_DATE
    INTO :OBJ_ID, :DATE_ADD, :DATE_MODIFY, :DATE_DEL, :PERSON_ID, :GROUP_ID, :REASON_IN, :DATE_IN, :DATE_OUT, :STAGE_ID,
      :ORDER_DATE_IN, :ORDER_NUM_IN, :ORDER_DATE_OUT, :ORDER_NUM_OUT, :ORDER_ID_IN, :ORDER_ID_OUT, :NAME_IN, :REASON_OUT, :USER_IN, :USER_OUT, :TYPE_IN, :IS_VD, :SOURCE_IN, :SOURCE_OUT,
      :PLAN_STAGES, :STAGE_YEAR, :GROUP_TYPE_ID, :LEVEL_ID, :OU_ID
  DO
  BEGIN
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE EXPORT_OBJECTS (
    I$REPL_DATE TIMESTAMP = null)
RETURNS (
    OBJ_ID BIGINT,
    TYPE_ID BIGINT,
    IS_REPL SMALLINT)
AS
declare variable G bigint;
declare variable M bigint;
declare variable L smallint;
BEGIN
    IS_REPL = 0;

    SELECT GEN, MULTIPLIER FROM GEN INTO :G, :M;

    SELECT K.KEY_VAL FROM KEYS K WHERE K.KEY_CODE = 'LEVEL' INTO :L;

    FOR
        SELECT O.OBJ_ID, O.TYPE_ID
        FROM OBJECTS O
        -- Оптимизация от 15.09.2017 - исключаем из выгрузок мусор, связанный с печатью аттестатов (конвейер, предметы в аттестате и приложении)
        JOIN TYPES T ON T.TYPE_ID = O.TYPE_ID AND T.TYPE_ID NOT IN (155, 227, 229, 292)
        WHERE T.FOR_REPL_UP = 1 AND (:I$REPL_DATE IS NULL OR O.DATE_MODIFY >= :I$REPL_DATE)
          -- FIX 23.12.2019 - выгружаем вообще все линки, включая удаленные
        INTO :OBJ_ID, :TYPE_ID
    DO
    BEGIN
        IF ((L = 2) OR (L = 3) OR ((OBJ_ID / M) = G)) THEN
        BEGIN
            SUSPEND;
        END
    END

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE EXPORT_ORDERS (
    I$REPL_DATE TIMESTAMP = null)
RETURNS (
    OBJ_ID BIGINT,
    DATE_ADD TIMESTAMP,
    DATE_MODIFY TIMESTAMP,
    DATE_DEL TIMESTAMP,
    PARENT_ID BIGINT,
    TYPE_ID BIGINT,
    SIGNED_BY BIGINT,
    ORDER_DATE DATE,
    ORDER_NUM VARCHAR(100),
    DETAILS_TEXT VARCHAR(1000),
    STATE_ID BIGINT,
    CANCEL_DATE DATE,
    USER_ID BIGINT,
    ACTION_DATE DATE,
    PROJECT_NUM VARCHAR(40),
    COMMENTS VARCHAR(1000))
AS
begin

  -- Приказы выгружаем вообще все

  FOR
    SELECT OBJ_ID, DATE_ADD, DATE_MODIFY, DATE_DEL, PARENT_ID, TYPE_ID, SIGNED_BY, ORDER_DATE, ORDER_NUM, DETAILS_TEXT, STATE_ID, CANCEL_DATE, USER_ID, ACTION_DATE, PROJECT_NUM, COMMENTS
    FROM ORDERS
    WHERE :I$REPL_DATE IS NULL OR DATE_MODIFY >= :I$REPL_DATE
    INTO :OBJ_ID, :DATE_ADD, :DATE_MODIFY, :DATE_DEL, :PARENT_ID, :TYPE_ID, :SIGNED_BY, :ORDER_DATE, :ORDER_NUM, :DETAILS_TEXT, :STATE_ID, :CANCEL_DATE, :USER_ID, :ACTION_DATE, :PROJECT_NUM, :COMMENTS
  DO
  BEGIN
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE EXPORT_ORDER_DATA (
    I$REPL_DATE TIMESTAMP = null)
RETURNS (
    OBJ_ID BIGINT,
    DATE_ADD TIMESTAMP,
    DATE_MODIFY TIMESTAMP,
    DATE_DEL TIMESTAMP,
    ORDER_ID BIGINT,
    ACTION_ID BIGINT,
    ACTION_TYPE SMALLINT,
    REF_ID BIGINT,
    IS_PRESENT SMALLINT,
    GRADE_NAME VARCHAR(400))
AS
begin

  -- Приказы выгружаем вообще все

  FOR
    SELECT OBJ_ID, DATE_ADD, DATE_MODIFY, DATE_DEL, ORDER_ID, ACTION_ID, ACTION_TYPE, REF_ID, IS_PRESENT, GRADE_NAME
    FROM ORDER_DATA
    WHERE :I$REPL_DATE IS NULL OR DATE_MODIFY >= :I$REPL_DATE
    INTO :OBJ_ID, :DATE_ADD, :DATE_MODIFY, :DATE_DEL, :ORDER_ID, :ACTION_ID, :ACTION_TYPE, :REF_ID, :IS_PRESENT, :GRADE_NAME
  DO
  BEGIN
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE EXPORT_PLAN_LOADS (
    I$REPL_DATE TIMESTAMP = null)
RETURNS (
    OBJ_ID BIGINT,
    SUBJECT_ID BIGINT,
    STAGE_ID BIGINT,
    DATE_ADD TIMESTAMP,
    DATE_MODIFY TIMESTAMP,
    DATE_DEL TIMESTAMP,
    WEEKS SMALLINT,
    LOAD_HOURS FLOAT,
    LOAD_HOURS_S1 FLOAT,
    LOAD_HOURS_S2 FLOAT,
    CONTROL_Q1 BIGINT,
    CONTROL_Q2 BIGINT,
    HOURS_THEORY1 FLOAT,
    HOURS_PR1 FLOAT,
    HOURS_DX1 FLOAT,
    HOURS_IND1 FLOAT,
    HOURS_MAX FLOAT,
    HOURS_CR1 FLOAT,
    HOURS_ATT1 FLOAT,
    HOURS_GIA FLOAT,
    HOURS_REST FLOAT)
AS
begin

  FOR
    SELECT OBJ_ID, SUBJECT_ID, STAGE_ID, DATE_ADD, DATE_MODIFY, DATE_DEL, WEEKS, LOAD_HOURS, LOAD_HOURS_S1, LOAD_HOURS_S2, CONTROL_Q1, CONTROL_Q2,
      HOURS_THEORY1, HOURS_PR1, HOURS_DX1, HOURS_IND1, HOURS_MAX, HOURS_CR1, HOURS_ATT1, HOURS_GIA, HOURS_REST
    FROM PLAN_LOADS
    INTO :OBJ_ID, :SUBJECT_ID, :STAGE_ID, :DATE_ADD, :DATE_MODIFY, :DATE_DEL, :WEEKS, :LOAD_HOURS, :LOAD_HOURS_S1, :LOAD_HOURS_S2, :CONTROL_Q1, :CONTROL_Q2,
      :HOURS_THEORY1, :HOURS_PR1, :HOURS_DX1, :HOURS_IND1, :HOURS_MAX, :HOURS_CR1, :HOURS_ATT1, :HOURS_GIA, :HOURS_REST
  DO
  BEGIN
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE EXPORT_PLAN_RESOURCES (
    I$REPL_DATE TIMESTAMP = null)
RETURNS (
    OBJ_ID BIGINT,
    DATE_ADD TIMESTAMP,
    DATE_MODIFY TIMESTAMP,
    DATE_DEL TIMESTAMP,
    LOAD_ID BIGINT,
    RES_ID BIGINT,
    QTY DOUBLE PRECISION,
    RES_TYPE_ID SMALLINT)
AS
begin

  FOR
    SELECT OBJ_ID, DATE_ADD, DATE_MODIFY, DATE_DEL, LOAD_ID, RES_ID, QTY, RES_TYPE_ID
    FROM PLAN_RESOURCES
    INTO :OBJ_ID, :DATE_ADD, :DATE_MODIFY, :DATE_DEL, :LOAD_ID, :RES_ID, :QTY, :RES_TYPE_ID
  DO
  BEGIN
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE EXPORT_PLAN_SUBJECTS (
    I$REPL_DATE TIMESTAMP = null)
RETURNS (
    OBJ_ID BIGINT,
    PLAN_ID BIGINT,
    SUBJECT_ID BIGINT,
    FIELD_ID BIGINT,
    DATE_ADD TIMESTAMP,
    DATE_MODIFY TIMESTAMP,
    DATE_DEL TIMESTAMP,
    SORT_INDEX SMALLINT,
    PARENT_ID BIGINT,
    LEVEL_INDEX SMALLINT,
    GLOBAL_INDEX INTEGER,
    IS_ADV SMALLINT,
    ROW_TYPE SMALLINT,
    SRC_SUBJECT_ID BIGINT,
    IS_STM SMALLINT)
AS
begin

  FOR
    SELECT OBJ_ID, PLAN_ID, SUBJECT_ID, FIELD_ID, DATE_ADD, DATE_MODIFY, DATE_DEL, SORT_INDEX, PARENT_ID, LEVEL_INDEX, GLOBAL_INDEX, IS_ADV, ROW_TYPE, SRC_SUBJECT_ID, IS_STM
    FROM PLAN_SUBJECTS
    INTO :OBJ_ID, :PLAN_ID, :SUBJECT_ID, :FIELD_ID, :DATE_ADD, :DATE_MODIFY, :DATE_DEL, :SORT_INDEX, :PARENT_ID, :LEVEL_INDEX, :GLOBAL_INDEX, :IS_ADV, :ROW_TYPE, :SRC_SUBJECT_ID, :IS_STM
  DO
  BEGIN
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE EXPORT_POST_AS_WORK_FUNC RETURNS (
    BLOB_ID BIGINT)
AS
DECLARE VARIABLE SCHOOL_ID BIGINT;
DECLARE VARIABLE OBJ_ID BIGINT;
DECLARE VARIABLE ID_1394 BIGINT;
DECLARE VARIABLE ID_1398 BIGINT;
DECLARE VARIABLE ID_1399 BIGINT;
BEGIN
    SELECT FIRST 1 L.OBJ_ID
    FROM LINKS L
    WHERE L.PARENT_ID IS NULL
    AND L.OBJ_TYPE_ID = 2
    AND L.DATE_DEL IS NULL
    INTO :SCHOOL_ID;

    FOR
        SELECT L15.OBJ_ID, V58.LISTVAL_ID, V63.LISTVAL_ID, V64.LISTVAL_ID
        FROM (
            SELECT L14.OBJ_ID
            FROM LINKS L14
            WHERE L14.PARENT_ID = :SCHOOL_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
            UNION ALL
            SELECT L14.OBJ_ID
            FROM LINKS L
            JOIN LINKS L14 ON L14.PARENT_ID = L.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
            WHERE L.PARENT_ID = :SCHOOL_ID AND L.OBJ_TYPE_ID IN (211, 84) AND L.DATE_DEL IS NULL
        ) L14
        JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
        JOIN VALR V69 ON V69.OBJ_ID = L15.OBJ_ID AND V69.PARAM_ID = 69 AND V69.IS_DEL = 0
        JOIN VALL V58 ON V58.OBJ_ID = V69.VAL AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0
        JOIN VALL V63 ON V63.OBJ_ID = V69.VAL AND V63.PARAM_ID = 63 AND V63.IS_DEL = 0
        JOIN VALL V64 ON V64.OBJ_ID = V69.VAL AND V64.PARAM_ID = 64 AND V64.IS_DEL = 0
        INTO :OBJ_ID, :ID_1394, :ID_1398, :ID_1399
    DO
    BEGIN
        SELECT BLOB_ID
        FROM VAL_ADD(1394, :OBJ_ID, :ID_1394)
        INTO :BLOB_ID;

        SELECT BLOB_ID
        FROM VAL_ADD(1398, :OBJ_ID, :ID_1398)
        INTO :BLOB_ID;

        SELECT BLOB_ID
        FROM VAL_ADD(1399, :OBJ_ID, :ID_1399)
        INTO :BLOB_ID;
    END

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE EXPORT_RES (
    I$REPL_DATE TIMESTAMP = null)
RETURNS (
    RES_ID BIGINT,
    LANG_CODE CHAR(2),
    VAL VARCHAR(4000),
    VAL_LONG VARCHAR(4000),
    IS_REPL SMALLINT,
    IS_DEL SMALLINT)
AS
declare variable G bigint;
declare variable M bigint;
declare variable L char(1);
BEGIN
    IS_REPL = 0;

    SELECT GEN, MULTIPLIER FROM GEN INTO :G, :M;
    SELECT K.KEY_VAL FROM KEYS K WHERE K.KEY_CODE = 'LEVEL' INTO :L;

    FOR
        SELECT R.RES_ID,
               R.LANG_CODE,
               R.VAL,
               R.VAL_LONG,
               R.IS_REPL,
               R.IS_DEL
        FROM RES R
        WHERE R.RES_ID IN (
            SELECT LV.RES_ID
            FROM LISTVALS LV
            JOIN LISTS L
            ON L.LIST_ID = LV.LIST_ID

            WHERE L.FOR_REPL_UP = 1
            AND ((:I$REPL_DATE IS NULL) OR (LV.DATE_MODIFY >= :I$REPL_DATE))
            AND ((:L = '2') OR (:L = '3') OR ((LV.LISTVAL_ID / :M) = :G))
        )
        INTO :RES_ID,
             :LANG_CODE,
             :VAL,
             :VAL_LONG,
             :IS_REPL,
             :IS_DEL
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE EXPORT_RETRAININGS_BY_SCHOOL (
    I$SCHOOL_ID BIGINT)
RETURNS (
    TAG_NAME VARCHAR(255),
    VAL VARCHAR(4000))
AS
declare variable V$OBJ_ID bigint;
BEGIN
--35
    FOR
        SELECT L35_36.OBJ_ID
        FROM LINKS L112
        
        JOIN LINKS L111
        ON L111.OBJ_TYPE_ID = 111
        AND L111.DATE_DEL IS NULL
        AND L111.PARENT_ID = L112.OBJ_ID
        
        JOIN LINKS L2
        ON L2.OBJ_TYPE_ID = 2
        AND L2.DATE_DEL IS NULL
        AND L2.PARENT_ID = L111.OBJ_ID
        AND L2.OBJ_ID = :I$SCHOOL_ID

        JOIN LINKS L14
        ON L14.OBJ_TYPE_ID = 14
        AND L14.DATE_DEL IS NULL
        AND L14.PARENT_ID = L2.OBJ_ID

        JOIN LINKS L35_36
        ON L35_36.OBJ_TYPE_ID = 35
        AND L35_36.DATE_DEL IS NULL
        AND L35_36.PARENT_ID = L14.OBJ_ID
        
        WHERE L112.OBJ_TYPE_ID = 112
        AND L112.DATE_DEL IS NULL
        AND L112.PARENT_ID IS NULL
        INTO :V$OBJ_ID
    DO
    BEGIN
        TAG_NAME = 'po:val::id';
        VAL = V$OBJ_ID;
        SUSPEND;

        TAG_NAME = 'po:val::type_id';
        VAL = 35;
        SUSPEND;

        VAL = NULL;
        TAG_NAME = 'po:val::val';
        SELECT V.VAL FROM VALS V
        WHERE V.OBJ_ID = :V$OBJ_ID
        AND V.PARAM_ID = 296
        INTO VAL;
        SUSPEND;
    END
--36
    FOR
        SELECT L35_36.OBJ_ID
        FROM LINKS L112
        
        JOIN LINKS L111
        ON L111.OBJ_TYPE_ID = 111
        AND L111.DATE_DEL IS NULL
        AND L111.PARENT_ID = L112.OBJ_ID
        
        JOIN LINKS L2
        ON L2.OBJ_TYPE_ID = 2
        AND L2.DATE_DEL IS NULL
        AND L2.PARENT_ID = L111.OBJ_ID
        AND L2.OBJ_ID = :I$SCHOOL_ID

        JOIN LINKS L14
        ON L14.OBJ_TYPE_ID = 14
        AND L14.DATE_DEL IS NULL
        AND L14.PARENT_ID = L2.OBJ_ID

        JOIN LINKS L35_36
        ON L35_36.OBJ_TYPE_ID = 36
        AND L35_36.DATE_DEL IS NULL
        AND L35_36.PARENT_ID = L14.OBJ_ID
        
        WHERE L112.OBJ_TYPE_ID = 112
        AND L112.DATE_DEL IS NULL
        AND L112.PARENT_ID IS NULL
        INTO :V$OBJ_ID
    DO
    BEGIN
        TAG_NAME = 'po:val::id';
        VAL = V$OBJ_ID;
        SUSPEND;

        TAG_NAME = 'po:val::type_id';
        VAL = 36;
        SUSPEND;

        VAL = NULL;
        TAG_NAME = 'po:val::val';
        SELECT V.VAL FROM VALS V
        WHERE V.OBJ_ID = :V$OBJ_ID
        AND V.PARAM_ID = 304
        INTO VAL;
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE EXPORT_RSOKO_INDICATORS RETURNS (
    TAG_NAME VARCHAR(255),
    VAL VARCHAR(4000))
AS
begin
    TAG_NAME = 'indicator::id';
    VAL = '15';
    SUSPEND;

    TAG_NAME = 'indicator:lists:list::number';
    VAL = '1';
    SUSPEND;

    TAG_NAME = 'indicator:lists:list::name';
    VAL = 'Уровни образования';
    SUSPEND;

    TAG_NAME = 'indicator:lists:list:value::id';
    VAL = '1';
    SUSPEND;

    TAG_NAME = 'indicator:lists:list:value::name';
    VAL = 'Начальное общее образование';
    SUSPEND;

    TAG_NAME = 'indicator:lists:list:value::id';
    VAL = '2';
    SUSPEND;

    TAG_NAME = 'indicator:lists:list:value::name';
    VAL = 'Основное общее образование';
    SUSPEND;

    TAG_NAME = 'indicator:lists:list:value::id';
    VAL = '3';
    SUSPEND;

    TAG_NAME = 'indicator:lists:list:value::name';
    VAL = 'Среднее общее  образование';
    SUSPEND;

    TAG_NAME = 'indicator:fields:field::id';
    VAL = '1';
    SUSPEND;

    TAG_NAME = 'indicator:fields:field::list_number';
    VAL = '1';
    SUSPEND;

    TAG_NAME = 'indicator:fields:field::name';
    VAL = 'Уровень образования';
    SUSPEND;

    TAG_NAME = 'indicator:fields:field::id';
    VAL = '2';
    SUSPEND;

    TAG_NAME = 'indicator:fields:field::name';
    VAL = 'Количество пропусков';
    SUSPEND;
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE EXPORT_RSOKO_SCHOOL_INDICATORS (
    I$SCHOOL_ID BIGINT = null)
RETURNS (
    TAG_NAME VARCHAR(255),
    VAL VARCHAR(4000))
AS
declare variable V$MONITORING_ID bigint;
declare variable V$STAGE_TYPE_ID bigint;
declare variable V$PUPIL_ID bigint;
BEGIN
    IF (I$SCHOOL_ID IS NULL) THEN
    BEGIN
        SELECT OBJ_ID
        FROM LINKS
        WHERE PARENT_ID IS NULL
        AND OBJ_TYPE_ID = 2
        AND DATE_DEL IS NULL

        INTO :I$SCHOOL_ID;
    END
    EXECUTE PROCEDURE RSOKO_CALC_PUPIL_ABSENCES_COUNT(:I$SCHOOL_ID);

    SELECT FIRST 1 OBJ_ID
    FROM LINKS
    WHERE PARENT_ID = :I$SCHOOL_ID
    AND OBJ_TYPE_ID = 162
    AND DATE_DEL IS NULL
    INTO :V$MONITORING_ID;

    TAG_NAME = 'indicator::id';
    VAL = '15';
    SUSPEND;


    TAG_NAME = 'indicator::license_id';
    VAL = CAST(I$SCHOOL_ID / 1000000000 AS INT);
    SUSPEND;

    FOR
        SELECT V43.LISTVAL_ID,
               L10.OBJ_ID
        FROM LINKS L7

        JOIN VALL V43
        ON V43.OBJ_ID = L7.OBJ_ID
        AND V43.PARAM_ID = 43
        AND V43.IS_DEL = 0

        JOIN LINKS L8
        ON L8.PARENT_ID = L7.OBJ_ID
        AND L8.OBJ_TYPE_ID = 8
        AND L8.DATE_DEL IS NULL

        JOIN LINKS L9
        ON L9.PARENT_ID = L8.OBJ_ID
        AND L9.OBJ_TYPE_ID = 9
        AND L9.DATE_DEL IS NULL

        JOIN LINKS L10
        ON L10.PARENT_ID = L9.OBJ_ID
        AND L10.OBJ_TYPE_ID = 10
        AND L10.DATE_DEL IS NULL

        WHERE L7.PARENT_ID = :I$SCHOOL_ID
        AND L7.OBJ_TYPE_ID = 7
        AND L7.DATE_DEL IS NULL

        INTO :V$STAGE_TYPE_ID,
             :V$PUPIL_ID
    DO
    BEGIN
        TAG_NAME = 'indicator:params:param::internal_index';
        VAL = V$PUPIL_ID - CAST(V$PUPIL_ID / 1000000000 AS INT) * 1000000000;
        SUSPEND;

        TAG_NAME = 'indicator:params:param:value::field_id';
        VAL = '1';
        SUSPEND;

        TAG_NAME = 'indicator:params:param:value::value';
        IF(V$STAGE_TYPE_ID = 22) THEN
        BEGIN
            VAL = '1';
        END
        ELSE IF(V$STAGE_TYPE_ID = 26) THEN
        BEGIN
            VAL = '2';
        END
        ELSE IF(V$STAGE_TYPE_ID = 27) THEN
        BEGIN
            VAL = '3';
        END
        SUSPEND;

        TAG_NAME = 'indicator:params:param:value::field_id';
        VAL = '2';
        SUSPEND;

        TAG_NAME = 'indicator:params:param:value::value';
        SELECT I FROM VAL_GET(:V$PUPIL_ID, 1600) INTO :VAL;
        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE EXPORT_VALA (
    I$REPL_DATE TIMESTAMP = null)
RETURNS (
    PARAM_ID BIGINT,
    OBJ_ID BIGINT,
    USER_ID BIGINT,
    IS_REPL SMALLINT,
    IS_DEL SMALLINT,
    REGION VARCHAR(255),
    DISTRICT VARCHAR(255),
    TOWN VARCHAR(255),
    SETTLEMENT VARCHAR(255),
    STREET VARCHAR(255),
    HOUSE VARCHAR(10),
    LITER VARCHAR(10),
    CORP VARCHAR(10),
    FLAT VARCHAR(10),
    POST_INDEX VARCHAR(20),
    OCATD VARCHAR(11),
    FIAS_UID VARCHAR(36),
    STREET_UID VARCHAR(36))
AS
BEGIN
    IS_REPL = 0;

    FOR
        SELECT V.PARAM_ID, V.OBJ_ID, NULL, V.IS_DEL, V.REGION, V.DISTRICT, V.TOWN, V.SETTLEMENT, V.STREET, V.HOUSE, V.LITER, V.CORP, V.FLAT, V.POST_INDEX, V.OCATD, V.FIAS_UID, V.STREET_UID
        FROM VALA V
        JOIN PARAMS P ON P.PARAM_ID = V.PARAM_ID
        JOIN EXPORT_OBJECTS(NULL) E ON E.OBJ_ID = V.OBJ_ID
        WHERE P.FOR_REPL_UP = 1 AND V.IS_DEL = 0 AND ((:I$REPL_DATE IS NULL) OR (V.DATE_MODIFY >= :I$REPL_DATE))
        INTO :PARAM_ID, :OBJ_ID, :USER_ID, :IS_DEL, :REGION, :DISTRICT, :TOWN, :SETTLEMENT, :STREET, :HOUSE, :LITER, :CORP, :FLAT, :POST_INDEX, :OCATD, :FIAS_UID, :STREET_UID
    DO
    BEGIN
        SUSPEND;
    END

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE EXPORT_VALB (
    I$REPL_DATE TIMESTAMP = null)
RETURNS (
    PARAM_ID BIGINT,
    OBJ_ID BIGINT,
    USER_ID BIGINT,
    IS_REPL SMALLINT,
    IS_DEL SMALLINT,
    VAL VARCHAR(4000),
    BLOB_ID BIGINT)
AS
BEGIN
    IS_REPL = 0;

    FOR SELECT
            V.PARAM_ID,
            V.OBJ_ID,
            NULL,
            V.IS_DEL,
            V.VAL,
            V.BLOB_ID
        FROM VALB V
        INNER JOIN PARAMS P ON P.PARAM_ID = V.PARAM_ID
        INNER JOIN EXPORT_OBJECTS(NULL) E ON E.OBJ_ID = V.OBJ_ID
        WHERE P.FOR_REPL_UP = 1
        AND V.IS_DEL = 0
        AND ((:I$REPL_DATE IS NULL) OR (V.DATE_MODIFY >= :I$REPL_DATE))
        INTO
            :PARAM_ID,
            :OBJ_ID,
            :USER_ID,
            :IS_DEL,
            :VAL,
            :BLOB_ID
    DO BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE EXPORT_VALD (
    I$REPL_DATE TIMESTAMP = null)
RETURNS (
    PARAM_ID BIGINT,
    OBJ_ID BIGINT,
    USER_ID BIGINT,
    IS_REPL SMALLINT,
    IS_DEL SMALLINT,
    VAL DATE)
AS
BEGIN
    IS_REPL = 0;

    FOR SELECT
            V.PARAM_ID,
            V.OBJ_ID,
            NULL,
            V.IS_DEL,
            V.VAL
        FROM VALD V
        INNER JOIN PARAMS P ON P.PARAM_ID = V.PARAM_ID
        INNER JOIN EXPORT_OBJECTS(NULL) E ON E.OBJ_ID = V.OBJ_ID
        WHERE P.FOR_REPL_UP = 1
        AND V.IS_DEL = 0
        AND ((:I$REPL_DATE IS NULL) OR (V.DATE_MODIFY >= :I$REPL_DATE))
        INTO
            :PARAM_ID,
            :OBJ_ID,
            :USER_ID,
            :IS_DEL,
            :VAL
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE EXPORT_VALDT (
    I$REPL_DATE TIMESTAMP = null)
RETURNS (
    PARAM_ID BIGINT,
    OBJ_ID BIGINT,
    USER_ID BIGINT,
    IS_REPL SMALLINT,
    IS_DEL SMALLINT,
    VAL TIMESTAMP)
AS
BEGIN
    IS_REPL = 0;

    FOR
        SELECT V.PARAM_ID, V.OBJ_ID, NULL, V.IS_DEL, V.VAL
        FROM VALDT V
        JOIN PARAMS P ON P.PARAM_ID = V.PARAM_ID
        JOIN EXPORT_OBJECTS(NULL) E ON E.OBJ_ID = V.OBJ_ID
        WHERE P.FOR_REPL_UP = 1 AND V.IS_DEL = 0 AND ((:I$REPL_DATE IS NULL) OR (V.DATE_MODIFY >= :I$REPL_DATE))
        INTO :PARAM_ID, :OBJ_ID, :USER_ID, :IS_DEL, :VAL
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE EXPORT_VALF (
    I$REPL_DATE TIMESTAMP = null)
RETURNS (
    PARAM_ID BIGINT,
    OBJ_ID BIGINT,
    USER_ID BIGINT,
    IS_REPL SMALLINT,
    IS_DEL SMALLINT,
    VAL DOUBLE PRECISION)
AS
BEGIN
    IS_REPL = 0;

    FOR SELECT
            V.PARAM_ID,
            V.OBJ_ID,
            NULL,
            V.IS_DEL,
            V.VAL
        FROM VALF V
        INNER JOIN PARAMS P ON P.PARAM_ID = V.PARAM_ID
        INNER JOIN EXPORT_OBJECTS(NULL) E ON E.OBJ_ID = V.OBJ_ID
        WHERE P.FOR_REPL_UP = 1
        AND V.IS_DEL = 0
        AND ((:I$REPL_DATE IS NULL) OR (V.DATE_MODIFY >= :I$REPL_DATE))
        INTO
            :PARAM_ID,
            :OBJ_ID,
            :USER_ID,
            :IS_DEL,
            :VAL
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE EXPORT_VALI (
    I$REPL_DATE TIMESTAMP = null)
RETURNS (
    PARAM_ID BIGINT,
    OBJ_ID BIGINT,
    USER_ID BIGINT,
    IS_REPL SMALLINT,
    IS_DEL SMALLINT,
    VAL INTEGER)
AS
declare variable L char(1);
BEGIN
    IS_REPL = 0;

    SELECT K.KEY_VAL
    FROM KEYS K
    WHERE K.KEY_CODE = 'LEVEL'
    INTO :L;

    FOR
        SELECT V.PARAM_ID,
               V.OBJ_ID,
               NULL,
               V.IS_DEL,
               V.VAL
        FROM VALI V
        JOIN PARAMS P
        ON P.PARAM_ID = V.PARAM_ID
        JOIN EXPORT_OBJECTS(NULL) E
        ON E.OBJ_ID = V.OBJ_ID
        WHERE ((P.FOR_REPL_UP = 1) OR ((:L = '2') AND (V.PARAM_ID IN (1364, 1365, 1366, 1367, 1368)))) /* CODES OU, PPE, PPE in class */
        AND ((:I$REPL_DATE IS NULL) OR (V.DATE_MODIFY >= :I$REPL_DATE))
        AND V.IS_DEL = 0
        INTO :PARAM_ID, :OBJ_ID, :USER_ID, :IS_DEL, :VAL
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE EXPORT_VALL (
    I$REPL_DATE TIMESTAMP = null)
RETURNS (
    PARAM_ID BIGINT,
    OBJ_ID BIGINT,
    USER_ID BIGINT,
    IS_REPL SMALLINT,
    IS_DEL SMALLINT,
    LISTVAL_ID BIGINT)
AS
BEGIN
    IS_REPL = 0;

    FOR
        SELECT V.PARAM_ID,
               V.OBJ_ID,
               NULL,
               V.IS_DEL,
               V.LISTVAL_ID
        FROM VALL V

        JOIN PARAMS P
        ON P.PARAM_ID = V.PARAM_ID

        JOIN EXPORT_OBJECTS(NULL) E
        ON E.OBJ_ID = V.OBJ_ID

        WHERE P.FOR_REPL_UP = 1
        AND V.IS_DEL = 0
        AND V.LISTVAL_ID < 1000000000 /* ???? */
        AND ((:I$REPL_DATE IS NULL) OR (V.DATE_MODIFY >= :I$REPL_DATE))
        INTO :PARAM_ID, :OBJ_ID, :USER_ID, :IS_DEL, :LISTVAL_ID
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE EXPORT_VALM (
    I$REPL_DATE TIMESTAMP = null)
RETURNS (
    MARK_ID BIGINT,
    PUPIL_ID BIGINT,
    SUBJECT_ID BIGINT,
    TEACHER_ID BIGINT,
    YEAR_ID BIGINT,
    MARKTYPE_ID BIGINT,
    MARKVAL_ID BIGINT,
    IS_DEL SMALLINT,
    PERIOD_FROM DATE,
    PERIOD_TO DATE,
    GRADE_ID BIGINT,
    MARK_DATE DATE,
    IS_NATIVE SMALLINT)
AS
declare variable CURRENT_Y integer;
declare variable Y1 bigint;
declare variable Y2 bigint;
declare variable Y3 bigint;
declare variable Y4 bigint;
declare variable RUN_Y bigint;
declare variable S varchar(100);
BEGIN
    -- Выгружаем только текущий и предыдущий учебный год
    CURRENT_Y = EXTRACT(YEAR FROM CURRENT_DATE);
    IF(EXTRACT(MONTH FROM CURRENT_DATE) < 9) THEN CURRENT_Y = CURRENT_Y - 1;

    FOR
        SELECT LV.LISTVAL_ID, SUBSTRING(LV.VAL FROM 1 FOR 4)
        FROM LISTVALS_LIST(29) LV
        INTO :RUN_Y, :S
    DO
    BEGIN
        IF(S = CURRENT_Y) THEN Y1 = RUN_Y;
        IF(S = (CURRENT_Y - 1)) THEN Y2 = RUN_Y;
        IF(S = (CURRENT_Y - 2)) THEN Y3 = RUN_Y;
        IF(S = (CURRENT_Y - 3)) THEN Y4 = RUN_Y;
    END

    FOR
        SELECT MARK_ID, PUPIL_ID, SUBJECT_ID, TEACHER_ID, YEAR_ID, MARKTYPE_ID, MARKVAL_ID, IS_DEL, PERIOD_FROM, PERIOD_TO, GRADE_ID, MARK_DATE, IS_NATIVE
        FROM VALM V
        -- Выгрузка только "живых" предметов, находящихся в одной из папок предметов или дисциплин
        JOIN LINKS L51 ON L51.OBJ_ID = V.SUBJECT_ID AND L51.DATE_DEL IS NULL AND L51.PARENT_ID IN (32771, 32772, 12313)
        WHERE ((:I$REPL_DATE IS NULL) OR (V.DATE_MODIFY >= :I$REPL_DATE)) AND V.IS_DEL = 0 AND (V.YEAR_ID = :Y1 OR V.YEAR_ID = :Y2 OR V.YEAR_ID = :Y3 OR V.YEAR_ID = :Y4)
        -- Выгрузка только "живых" учеников, упомянутых в одном из коллективов или папках выбывших
        AND EXISTS (
            SELECT FIRST 1 1
            FROM LINKS LPG
            WHERE LPG.OBJ_ID = V.PUPIL_ID AND LPG.DATE_DEL IS NULL AND LPG.PARENT_TYPE_ID IN (9, 187, 81, 82, 83)
        )
        -- Выгрузка только "живых" учителей, работающих в данный момент или уволенных
        AND EXISTS (
            SELECT FIRST 1 1
            FROM LINKS LPT
            WHERE LPT.OBJ_ID = V.TEACHER_ID AND LPT.DATE_DEL IS NULL AND LPT.PARENT_TYPE_ID IN (2, 211, 84)
        )
        INTO :MARK_ID, :PUPIL_ID, :SUBJECT_ID, :TEACHER_ID, :YEAR_ID, :MARKTYPE_ID, :MARKVAL_ID, :IS_DEL, :PERIOD_FROM, :PERIOD_TO, :GRADE_ID, :MARK_DATE, :IS_NATIVE
    DO
    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE EXPORT_VALR (
    I$REPL_DATE TIMESTAMP = null)
RETURNS (
    PARAM_ID BIGINT,
    OBJ_ID BIGINT,
    USER_ID BIGINT,
    IS_REPL SMALLINT,
    IS_DEL SMALLINT,
    VAL BIGINT)
AS
BEGIN
    IS_REPL = 0;

    FOR SELECT
            V.PARAM_ID,
            V.OBJ_ID,
            NULL,
            V.IS_DEL,
            V.VAL
        FROM VALR V
        INNER JOIN PARAMS P ON P.PARAM_ID = V.PARAM_ID
        INNER JOIN EXPORT_OBJECTS(NULL) E ON E.OBJ_ID = V.OBJ_ID
        WHERE P.FOR_REPL_UP = 1
        AND V.IS_DEL = 0
        AND ((:I$REPL_DATE IS NULL) OR (V.DATE_MODIFY >= :I$REPL_DATE))
        INTO
            :PARAM_ID,
            :OBJ_ID,
            :USER_ID,
            :IS_DEL,
            :VAL
    DO BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE EXPORT_VALS (
    I$REPL_DATE TIMESTAMP = null)
RETURNS (
    PARAM_ID BIGINT,
    OBJ_ID BIGINT,
    USER_ID BIGINT,
    IS_REPL SMALLINT,
    IS_DEL SMALLINT,
    VAL VARCHAR(4000))
AS
BEGIN
    IS_REPL = 0;

    FOR
        SELECT V.PARAM_ID, V.OBJ_ID, NULL, V.IS_DEL, V.VAL
        FROM VALS V
        JOIN PARAMS P ON P.PARAM_ID = V.PARAM_ID
        JOIN EXPORT_OBJECTS(NULL) E ON E.OBJ_ID = V.OBJ_ID
        WHERE P.FOR_REPL_UP = 1 AND V.IS_DEL = 0 AND ((:I$REPL_DATE IS NULL) OR (V.DATE_MODIFY >= :I$REPL_DATE))
        INTO :PARAM_ID, :OBJ_ID, :USER_ID, :IS_DEL, :VAL
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE EXPORT_VALT (
    I$REPL_DATE TIMESTAMP = null)
RETURNS (
    PARAM_ID BIGINT,
    OBJ_ID BIGINT,
    USER_ID BIGINT,
    IS_REPL SMALLINT,
    IS_DEL SMALLINT,
    VAL TIME)
AS
BEGIN
    IS_REPL = 0;

    FOR SELECT
            V.PARAM_ID,
            V.OBJ_ID,
            NULL,
            V.IS_DEL,
            V.VAL
        FROM VALT V
        INNER JOIN PARAMS P ON P.PARAM_ID = V.PARAM_ID
        INNER JOIN EXPORT_OBJECTS(NULL) E ON E.OBJ_ID = V.OBJ_ID
        WHERE P.FOR_REPL_UP = 1
        AND V.IS_DEL = 0
        AND ((:I$REPL_DATE IS NULL) OR (V.DATE_MODIFY >= :I$REPL_DATE))
        INTO
            :PARAM_ID,
            :OBJ_ID,
            :USER_ID,
            :IS_DEL,
            :VAL
    DO BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE EXTERNAT_PUPIL_MOVEMENT (
    I$PUPIL_ID BIGINT,
    I$GROUP_ID BIGINT,
    I$ORDER_NUMBER VARCHAR(100),
    I$ORDER_DATE DATE,
    I$ACTION_DATE DATE,
    I$ACTION_TYPE BIGINT,
    I$USER_ID BIGINT)
AS
declare variable V$BLOB_ID bigint;
declare variable V$MOVEMENT_ID bigint;
declare variable V$TYPE_ID bigint;
declare variable V$CAPTION varchar(1000);
declare variable V$LINK_ID bigint;
declare variable V$STAGE_ID integer;
declare variable V$FOLDER_ID bigint;
declare variable V$OUT_FOLDER_ID bigint;
declare variable V$YEAR integer;
BEGIN

    -- Все заменено на VARGRP*

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FGOS_SPECIALITY_LIST (
    I$LIST_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    LISTVAL_ID BIGINT,
    PARENT_ID BIGINT,
    VAL VARCHAR(4000),
    VAL_LONG VARCHAR(4000),
    TAG VARCHAR(100))
AS
declare variable RES_ID bigint;
declare variable LANG_CODE varchar(2);
begin
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :LANG_CODE;

    FOR
      SELECT LISTVAL_ID, PARENT_ID, TAG, RES_ID
      FROM LISTVALS
      WHERE LIST_ID = :I$LIST_ID AND IS_DEL = 0
      ORDER BY SORT_ORDER
      INTO :LISTVAL_ID, :PARENT_ID, :TAG, :RES_ID
    DO
    BEGIN
      SELECT VAL || COALESCE(' (' || :TAG || ')', ''), VAL_LONG
      FROM RES_GET(:RES_ID, :LANG_CODE)
      INTO :VAL, :VAL_LONG;

      SUSPEND;
    END
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FGOS_SPECIALITY_SET (
    I$OBJ_ID BIGINT,
    I$PARAM_ID BIGINT,
    I$LISTVAL_ID BIGINT,
    I$USER_ID BIGINT,
    I$IS_DEL SMALLINT)
AS
declare variable V$BLOB_ID bigint;
begin
    IF (I$IS_DEL = 1) THEN
    BEGIN
        -- При удалении специальности обнуляем код, но если заполнено сразу два поля специальности - смотрим по второму
        V$BLOB_ID = NULL;
        SELECT FIRST 1 LISTVAL_ID, PARAM_ID
        FROM VALL V
        WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID IN (2460, 1753, 3378, 2165, 2821, 3367, 3386) AND V.IS_DEL = 0
        INTO :V$BLOB_ID, :I$PARAM_ID;

        IF(V$BLOB_ID IS NULL) THEN
        BEGIN
            UPDATE VALS
            SET IS_DEL = 1
            WHERE OBJ_ID = :I$OBJ_ID AND PARAM_ID IN (1754, 2822, 3387) AND IS_DEL = 0;
        END
        ELSE
        BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD(CASE :I$PARAM_ID
              WHEN 1753 THEN 1754 -- ОП
              WHEN 2460 THEN 1754
              WHEN 3378 THEN 1754
              WHEN 2165 THEN 2822 -- группа
              WHEN 2821 THEN 2822
              WHEN 3367 THEN 2822
              WHEN 3386 THEN 3387 -- профессия УП
            END,
            :I$OBJ_ID, (SELECT TAG FROM LISTVALS WHERE LISTVAL_ID = :V$BLOB_ID), :I$USER_ID, 0, 0)
            INTO :V$BLOB_ID;
        END
    END
    ELSE
    BEGIN
        -- Проверяем, что альтернативное поле не заполнено
        V$BLOB_ID = 0;
        SELECT FIRST 1 1
        FROM VALL V
        WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID IN (2460, 1753, 3378, 3386) AND V.IS_DEL = 0 AND V.PARAM_ID <> :I$PARAM_ID
        INTO :V$BLOB_ID;
        IF(V$BLOB_ID <> 0) THEN EXCEPTION DATA_ERROR 'Допускается заполнение поля профессии/специальности только по одному кодификатору';

        -- При выборе специальности заполняем код
        SELECT BLOB_ID
        FROM VAL_ADD(CASE :I$PARAM_ID
            WHEN 1753 THEN 1754 -- ОП
            WHEN 2460 THEN 1754
            WHEN 3378 THEN 1754
            WHEN 2165 THEN 2822 -- группа
            WHEN 2821 THEN 2822
            WHEN 3367 THEN 2822
            WHEN 3386 THEN 3387 -- профессия УП
          END,
          :I$OBJ_ID, (SELECT TAG FROM LISTVALS WHERE LISTVAL_ID = :I$LISTVAL_ID), :I$USER_ID, 0, 0)
        INTO :V$BLOB_ID;
    END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FILTERFIELDSSETS_LIST (
    I$USER_ID BIGINT,
    I$LEVEL_ID BIGINT,
    I$TYPE_ID BIGINT)
RETURNS (
    FILTERFIELDSSET_ID BIGINT,
    USER_ID BIGINT,
    TYPE_ID BIGINT,
    LEVEL_ID BIGINT,
    FILTERFIELDSSET_NAME VARCHAR(100),
    IS_LAST SMALLINT,
    IS_ACTIVE SMALLINT)
AS
BEGIN
    FOR
        SELECT FILTERFIELDSSET_ID,
               USER_ID,
               TYPE_ID,
               LEVEL_ID,
               FILTERFIELDSSET_NAME,
               IS_LAST,
               IS_ACTIVE
        FROM FILTERFIELDSSETS
        WHERE USER_ID = :I$USER_ID
        AND LEVEL_ID = :I$LEVEL_ID
        AND TYPE_ID = :I$TYPE_ID
        INTO   :FILTERFIELDSSET_ID,
               :USER_ID,
               :TYPE_ID,
               :LEVEL_ID,
               :FILTERFIELDSSET_NAME,
               :IS_LAST,
               :IS_ACTIVE
    DO
    BEGIN
        IF (IS_LAST = 1) THEN
        BEGIN
            FILTERFIELDSSET_NAME = '<...>';
        END
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FILTERFIELDSSET_ADD (
    I$FILTERFIELDSSET_ID BIGINT,
    I$USER_ID BIGINT,
    I$LEVEL_ID BIGINT,
    I$TYPE_ID BIGINT,
    I$FILTERFIELDSSET_NAME VARCHAR(100),
    I$IS_LAST SMALLINT)
RETURNS (
    FILTERFIELDSSET_ID BIGINT)
AS
BEGIN
    IF (I$FILTERFIELDSSET_NAME IS NULL) THEN
    BEGIN
        I$FILTERFIELDSSET_NAME = '';
    END
    UPDATE FILTERFIELDSSETS
    SET IS_ACTIVE = 0
    WHERE USER_ID = :I$USER_ID
    AND LEVEL_ID = :I$LEVEL_ID;
    IF (I$FILTERFIELDSSET_ID IS NULL AND I$IS_LAST = 1) THEN
    BEGIN
        SELECT FILTERFIELDSSET_ID
        FROM FILTERFIELDSSETS
        WHERE USER_ID = :I$USER_ID
        AND LEVEL_ID = :I$LEVEL_ID
        AND IS_LAST = 1
        INTO   :I$FILTERFIELDSSET_ID;
    END
    IF (I$FILTERFIELDSSET_ID IS NOT NULL) THEN
    BEGIN
        FILTERFIELDSSET_ID = :I$FILTERFIELDSSET_ID;
        UPDATE FILTERFIELDSSETS
        SET TYPE_ID = :I$TYPE_ID,
        FILTERFIELDSSET_NAME = :I$FILTERFIELDSSET_NAME,
        IS_ACTIVE = 1
        WHERE FILTERFIELDSSET_ID = :I$FILTERFIELDSSET_ID;
    END
    ELSE
    BEGIN
        INSERT
        INTO FILTERFIELDSSETS
                    (
                     USER_ID,
                     TYPE_ID,
                     LEVEL_ID,
                     FILTERFIELDSSET_NAME,
                     IS_LAST,
                     IS_ACTIVE
                    )
              VALUES
                    (
                     :I$USER_ID,
                     :I$TYPE_ID,
                     :I$LEVEL_ID,
                     :I$FILTERFIELDSSET_NAME,
                     :I$IS_LAST,
                     1
                    )
        RETURNING FILTERFIELDSSET_ID
        INTO :FILTERFIELDSSET_ID;
    END
    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FILTERFIELDSSET_DEL (
    I$FILTERFIELDSSET_ID BIGINT,
    I$USER_ID BIGINT,
    I$LEVEL_ID BIGINT,
    I$TYPE_ID BIGINT)
AS
BEGIN
    DELETE
    FROM FILTERFIELDSSETS
    WHERE FILTERFIELDSSET_ID = :I$FILTERFIELDSSET_ID
    AND USER_ID = :I$USER_ID
    AND LEVEL_ID = :I$LEVEL_ID
    AND TYPE_ID = :I$TYPE_ID
    AND IS_LAST = 0;
    UPDATE FILTERFIELDSSETS
    SET IS_ACTIVE = 1
    WHERE USER_ID = :I$USER_ID
    AND LEVEL_ID = :I$LEVEL_ID
    AND TYPE_ID = :I$TYPE_ID
    AND IS_LAST = 1;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FILTERFIELDSSET_GET (
    I$FILTERFIELDSSET_ID BIGINT,
    I$USER_ID BIGINT,
    I$LEVEL_ID BIGINT,
    I$TYPE_ID BIGINT,
    I$FILTERFIELDSSET_NAME VARCHAR(100) = NULL)
RETURNS (
    FILTERFIELDSSET_ID BIGINT,
    USER_ID BIGINT,
    TYPE_ID BIGINT,
    LEVEL_ID BIGINT,
    FILTERFIELDSSET_NAME VARCHAR(100),
    IS_LAST SMALLINT,
    IS_ACTIVE SMALLINT)
AS
DECLARE VARIABLE V$COUNT SMALLINT;
BEGIN
    IF (I$FILTERFIELDSSET_NAME IS NOT NULL) THEN
    BEGIN
        FOR
            SELECT FIRST 1
                   FILTERFIELDSSET_ID,
                   USER_ID,
                   TYPE_ID,
                   LEVEL_ID,
                   FILTERFIELDSSET_NAME,
                   IS_LAST,
                   IS_ACTIVE
            FROM FILTERFIELDSSETS
            WHERE USER_ID = :I$USER_ID
            AND LEVEL_ID = :I$LEVEL_ID
            AND TYPE_ID = :I$TYPE_ID
            AND FILTERFIELDSSET_NAME LIKE :I$FILTERFIELDSSET_NAME
            INTO :FILTERFIELDSSET_ID,
                 :USER_ID,
                 :TYPE_ID,
                 :LEVEL_ID,
                 :FILTERFIELDSSET_NAME,
                 :IS_LAST,
                 :IS_ACTIVE
        DO
        BEGIN
            SUSPEND;
        END
    END
    ELSE
    BEGIN
        V$COUNT = 1;
        FOR
            SELECT FILTERFIELDSSET_ID,
                   USER_ID,
                   TYPE_ID,
                   LEVEL_ID,
                   FILTERFIELDSSET_NAME,
                   IS_LAST,
                   IS_ACTIVE
            FROM FILTERFIELDSSETS
            WHERE FILTERFIELDSSET_ID = :I$FILTERFIELDSSET_ID
            UNION ALL
            SELECT FILTERFIELDSSET_ID,
                   USER_ID,
                   TYPE_ID,
                   LEVEL_ID,
                   FILTERFIELDSSET_NAME,
                   IS_LAST,
                   IS_ACTIVE
            FROM FILTERFIELDSSETS
            WHERE USER_ID = :I$USER_ID
            AND LEVEL_ID = :I$LEVEL_ID
            AND TYPE_ID = :I$TYPE_ID
            AND IS_LAST = 1
            INTO :FILTERFIELDSSET_ID,
                 :USER_ID,
                 :TYPE_ID,
                 :LEVEL_ID,
                 :FILTERFIELDSSET_NAME,
                 :IS_LAST,
                 :IS_ACTIVE
        DO
        BEGIN
            IF (V$COUNT = 1) THEN
            BEGIN
                SUSPEND;
            END
            V$COUNT = V$COUNT + 1;
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FILTERFIELDS_LIST (
    I$FILTERFIELDSSET_ID BIGINT,
    I$USER_ID BIGINT,
    I$LEVEL_ID BIGINT,
    I$TYPE_ID BIGINT)
RETURNS (
    FILTERFIELDSSET_ID BIGINT,
    FILTERFIELD_NUM SMALLINT,
    PARAM_ID BIGINT,
    PARAM_CAPTION VARCHAR(4000),
    IS_TREEVIEW SMALLINT,
    IS_CHECKED SMALLINT)
AS
DECLARE VARIABLE V$RES_ID BIGINT;
DECLARE VARIABLE V$SIZE_RES_ID BIGINT;
DECLARE VARIABLE V$LANG_CODE CHAR(2) = 'RU';
DECLARE VARIABLE V$PARAM_SIZE VARCHAR(4000);
DECLARE VARIABLE V$PARAM_BLOCK_NAME VARCHAR(4000);
DECLARE VARIABLE V$TAB_ID BIGINT;
DECLARE VARIABLE V$PREV_TAB_ID BIGINT;
DECLARE VARIABLE V$PARAM_TYPE SMALLINT;
BEGIN
    V$PREV_TAB_ID = NULL;
    V$PARAM_BLOCK_NAME = '';
    FILTERFIELDSSET_ID = I$FILTERFIELDSSET_ID;
    SELECT LANG_CODE FROM USERS WHERE USER_ID = :I$USER_ID INTO :V$LANG_CODE;
    FOR
        SELECT P.PARAM_ID,
               P.RES_ID,
               P.SIZE_RES_ID,
               P.IS_TREEVIEW,
               P.TAB_ID,
               P.PARAM_TYPE,
               FV.FILTERFIELD_NUM
        FROM PARAMS P
        INNER JOIN PARAMTYPES T
        ON T.PARAM_TYPE = P.PARAM_TYPE
        INNER JOIN LPARAMS LP
        ON LP.PARAM_ID = P.PARAM_ID
        AND LP.LEVEL_ID = :I$LEVEL_ID
        AND LP.EDIT_TYPE > -1
        LEFT OUTER JOIN FILTERFIELDS FV
        ON FV.PARAM_ID = P.PARAM_ID
        AND FV.FILTERFIELDSSET_ID = :I$FILTERFIELDSSET_ID
        WHERE P.TYPE_ID = :I$TYPE_ID
        AND P.IS_DEL = 0
        ORDER BY P.GRID_ORDER
        INTO   :PARAM_ID,
               :V$RES_ID,
               :V$SIZE_RES_ID,
               :IS_TREEVIEW,
               :V$TAB_ID,
               :V$PARAM_TYPE,
               :FILTERFIELD_NUM
    DO
    BEGIN
        IF(V$PREV_TAB_ID <> V$TAB_ID) THEN
        BEGIN
            V$PARAM_BLOCK_NAME = '';
        END
        IS_CHECKED = 0;
        IF (FILTERFIELD_NUM IS NOT NULL) THEN
        BEGIN
            IS_CHECKED = 1;
        END
        PARAM_CAPTION = '';
        SELECT VAL
        FROM RES_GET(:V$RES_ID, :V$LANG_CODE)
        INTO :PARAM_CAPTION;

        IF (V$PARAM_TYPE IN (14,15)) THEN/*SEPARATORS*/
        BEGIN
            V$PARAM_BLOCK_NAME = PARAM_CAPTION || ' - ';
            V$PREV_TAB_ID = V$TAB_ID;
        END
        ELSE
        BEGIN
            PARAM_CAPTION = V$PARAM_BLOCK_NAME || PARAM_CAPTION;

            V$PARAM_SIZE = '';
            SELECT VAL
            FROM RES_GET(:V$SIZE_RES_ID, :V$LANG_CODE)
            INTO :V$PARAM_SIZE;

            IF (V$PARAM_SIZE != '' ) THEN
            BEGIN
                PARAM_CAPTION = PARAM_CAPTION || ' (' || V$PARAM_SIZE || ')';
            END
            SUSPEND;
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FILTERFIELDS_LIST2 (
    I$FILTERFIELDSSET_ID BIGINT,
    I$USER_ID BIGINT,
    I$LEVEL_ID BIGINT,
    I$TYPE_ID BIGINT)
RETURNS (
    FILTERFIELDSSET_ID BIGINT,
    FILTERFIELD_NUM SMALLINT,
    PARENT_ID VARCHAR(40),
    PARAM_ID VARCHAR(40),
    PARAM_CAPTION VARCHAR(4000),
    IS_TREEVIEW SMALLINT,
    IS_CHECKED SMALLINT)
AS
DECLARE VARIABLE V$RES_ID BIGINT;
DECLARE VARIABLE V$SIZE_RES_ID BIGINT;
DECLARE VARIABLE V$LANG_CODE CHAR(2) = 'RU';
DECLARE VARIABLE V$PARAM_SIZE VARCHAR(4000);
DECLARE VARIABLE V$PARAM_BLOCK_NAME VARCHAR(4000);
DECLARE VARIABLE V$TAB_ID BIGINT;
DECLARE VARIABLE V$PREV_TAB_ID BIGINT;
DECLARE VARIABLE V$PARAM_TYPE SMALLINT;
DECLARE VARIABLE V$GRID_ORDER SMALLINT;
DECLARE VARIABLE V$TAB_NUM SMALLINT;
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :V$LANG_CODE;

    FILTERFIELDSSET_ID = I$FILTERFIELDSSET_ID;

    PARENT_ID = NULL;
    IS_TREEVIEW = 0;
    IS_CHECKED = 0;

    FOR
        SELECT DISTINCT
               'T' || T.TAB_ID,
               T.RES_ID,
               T.TAB_NUM
        FROM TABS T
        INNER JOIN PARAMS P
        ON P.TAB_ID = T.TAB_ID
        AND P.PARAM_TYPE NOT IN (17,14,15)
        INNER JOIN LPARAMS LP
        ON LP.PARAM_ID = P.PARAM_ID
        AND LP.LEVEL_ID = :I$LEVEL_ID
        AND LP.EDIT_TYPE > -1
        WHERE T.TYPE_ID = :I$TYPE_ID
        AND T.IS_DEL = 0

        UNION

        SELECT DISTINCT
               'T' || T.TAB_ID,
               T.RES_ID,
               T.TAB_NUM
        FROM TABS T
        INNER JOIN PARENTS PR
        ON PR.TAB_ID = T.TAB_ID
        INNER JOIN PARAMS P
        ON P.TYPE_ID = PR.CHILD_ID
        AND P.PARAM_TYPE NOT IN (17,14,15)
        INNER JOIN LPARAMS LP
        ON LP.PARAM_ID = P.PARAM_ID
        AND LP.LEVEL_ID = :I$LEVEL_ID
        AND LP.EDIT_TYPE > -1
        WHERE T.TYPE_ID = :I$TYPE_ID
        AND T.IS_DEL = 0

        ORDER BY 3
        INTO :PARAM_ID,
             :V$RES_ID,
             :FILTERFIELD_NUM
    DO
    BEGIN
        SELECT UPPER(VAL) || ':'
        FROM RES_GET(:V$RES_ID,  :V$LANG_CODE)
        INTO :PARAM_CAPTION;
        SUSPEND;
    END

    V$PREV_TAB_ID = NULL;
    V$PARAM_BLOCK_NAME = '';

    FOR
        SELECT P.PARAM_ID,
               P.RES_ID,
               P.SIZE_RES_ID,
               P.IS_TREEVIEW,
               P.TAB_ID,
               P.PARAM_TYPE,
               FV.FILTERFIELD_NUM,
               'T' || P.TAB_ID,
               P.GRID_ORDER,
               TB.TAB_NUM
        FROM TABS TB
        INNER JOIN PARAMS P
        ON P.TAB_ID = TB.TAB_ID
        AND P.IS_DEL = 0
        INNER JOIN PARAMTYPES T
        ON T.PARAM_TYPE = P.PARAM_TYPE
        INNER JOIN LPARAMS LP
        ON LP.PARAM_ID = P.PARAM_ID
        AND LP.LEVEL_ID = :I$LEVEL_ID
        AND LP.EDIT_TYPE > -1
        LEFT OUTER JOIN FILTERFIELDS FV
        ON FV.PARAM_ID = P.PARAM_ID
        AND FV.FILTERFIELDSSET_ID = :I$FILTERFIELDSSET_ID
        WHERE TB.TYPE_ID = :I$TYPE_ID
        AND TB.IS_DEL = 0

        UNION

        SELECT P.PARAM_ID,
               P.RES_ID,
               P.SIZE_RES_ID,
               P.IS_TREEVIEW,
               P.TAB_ID,
               P.PARAM_TYPE,
               FV.FILTERFIELD_NUM,
               'T' || P.TAB_ID,
               P.GRID_ORDER,
               TB.TAB_NUM
        FROM PARAMS P
        LEFT OUTER JOIN TABS TB
        ON TB.TAB_ID = P.TAB_ID
        INNER JOIN PARAMTYPES T
        ON T.PARAM_TYPE = P.PARAM_TYPE
        INNER JOIN LPARAMS LP
        ON LP.PARAM_ID = P.PARAM_ID
        AND LP.LEVEL_ID = :I$LEVEL_ID
        AND LP.EDIT_TYPE > -1
        LEFT OUTER JOIN FILTERFIELDS FV
        ON FV.PARAM_ID = P.PARAM_ID
        AND FV.FILTERFIELDSSET_ID = :I$FILTERFIELDSSET_ID
        WHERE P.TYPE_ID = :I$TYPE_ID
        AND P.TAB_ID IS NULL
        AND P.IS_DEL = 0

        ORDER BY 10,9

        INTO   :PARAM_ID,
               :V$RES_ID,
               :V$SIZE_RES_ID,
               :IS_TREEVIEW,
               :V$TAB_ID,
               :V$PARAM_TYPE,
               :FILTERFIELD_NUM,
               :PARENT_ID,
               :V$GRID_ORDER,
               :V$TAB_NUM
    DO
    BEGIN
        IF(V$PREV_TAB_ID <> V$TAB_ID) THEN
        BEGIN
            V$PARAM_BLOCK_NAME = '';
        END
        IS_CHECKED = 0;
        IF (FILTERFIELD_NUM IS NOT NULL) THEN
        BEGIN
            IS_CHECKED = 1;
        END
        PARAM_CAPTION = '';
        SELECT VAL
        FROM RES_GET(:V$RES_ID, :V$LANG_CODE)
        INTO :PARAM_CAPTION;

        IF (V$PARAM_TYPE IN (14,15)) THEN/*SEPARATORS*/
        BEGIN
            V$PARAM_BLOCK_NAME = PARAM_CAPTION || ' - ';
            V$PREV_TAB_ID = V$TAB_ID;
        END
        ELSE
        BEGIN
            PARAM_CAPTION = V$PARAM_BLOCK_NAME || PARAM_CAPTION;

            V$PARAM_SIZE = '';
            SELECT VAL
            FROM RES_GET(:V$SIZE_RES_ID, :V$LANG_CODE)
            INTO :V$PARAM_SIZE;

            IF (V$PARAM_SIZE != '' ) THEN
            BEGIN
                PARAM_CAPTION = PARAM_CAPTION || ' (' || V$PARAM_SIZE || ')';
            END
            SUSPEND;
        END
    END
    FOR
        SELECT DISTINCT
               'T' || T.TAB_ID,
               'TTT' || PR.CHILD_ID,
               TY.RES_ID
        FROM TABS T
        INNER JOIN PARENTS PR
        ON PR.TAB_ID = T.TAB_ID
        INNER JOIN PARAMS P
        ON P.TYPE_ID = PR.CHILD_ID
        AND P.PARAM_TYPE NOT IN (17,14,15)
        INNER JOIN LPARAMS LP
        ON LP.PARAM_ID = P.PARAM_ID
        AND LP.LEVEL_ID = :I$LEVEL_ID
        AND LP.EDIT_TYPE > -1
        INNER JOIN TYPES TY
        ON TY.TYPE_ID = PR.CHILD_ID
        WHERE T.TYPE_ID = :I$TYPE_ID
        AND T.IS_DEL = 0

        ORDER BY T.TAB_NUM, P.GRID_ORDER
        INTO :PARENT_ID,
             :PARAM_ID,
             :V$RES_ID
    DO
    BEGIN
        SELECT UPPER(VAL) || ':'
        FROM RES_GET(:V$RES_ID,  :V$LANG_CODE)
        INTO :PARAM_CAPTION;
        SUSPEND;
    END

    V$PREV_TAB_ID = NULL;
    V$PARAM_BLOCK_NAME = '';
    FOR
        SELECT P.PARAM_ID,
               P.RES_ID,
               P.SIZE_RES_ID,
               P.IS_TREEVIEW,
               P.TAB_ID,
               P.PARAM_TYPE,
               FV.FILTERFIELD_NUM,
               'TTT' || PR.CHILD_ID
        FROM TABS TB
        INNER JOIN PARENTS PR
        ON PR.TAB_ID = TB.TAB_ID
        INNER JOIN PARAMS P
        ON P.TYPE_ID = PR.CHILD_ID
        AND P.IS_DEL = 0
        INNER JOIN PARAMTYPES T
        ON T.PARAM_TYPE = P.PARAM_TYPE
        INNER JOIN LPARAMS LP
        ON LP.PARAM_ID = P.PARAM_ID
        AND LP.LEVEL_ID = :I$LEVEL_ID
        AND LP.EDIT_TYPE > -1
        LEFT OUTER JOIN FILTERFIELDS FV
        ON FV.PARAM_ID = P.PARAM_ID
        AND FV.FILTERFIELDSSET_ID = :I$FILTERFIELDSSET_ID
        WHERE TB.TYPE_ID = :I$TYPE_ID
        AND TB.IS_DEL = 0
        ORDER BY P.GRID_ORDER, TB.TAB_NUM
        INTO   :PARAM_ID,
               :V$RES_ID,
               :V$SIZE_RES_ID,
               :IS_TREEVIEW,
               :V$TAB_ID,
               :V$PARAM_TYPE,
               :FILTERFIELD_NUM,
               :PARENT_ID
    DO
    BEGIN
        IF(V$PREV_TAB_ID <> V$TAB_ID) THEN
        BEGIN
            V$PARAM_BLOCK_NAME = '';
        END
        IS_CHECKED = 0;
        IF (FILTERFIELD_NUM IS NOT NULL) THEN
        BEGIN
            IS_CHECKED = 1;
        END
        PARAM_CAPTION = '';
        SELECT VAL
        FROM RES_GET(:V$RES_ID, :V$LANG_CODE)
        INTO :PARAM_CAPTION;

        IF (V$PARAM_TYPE IN (14,15)) THEN/*SEPARATORS*/
        BEGIN
            V$PARAM_BLOCK_NAME = PARAM_CAPTION || ' - ';
            V$PREV_TAB_ID = V$TAB_ID;
        END
        ELSE
        BEGIN
            PARAM_CAPTION = V$PARAM_BLOCK_NAME || PARAM_CAPTION;

            V$PARAM_SIZE = '';
            SELECT VAL
            FROM RES_GET(:V$SIZE_RES_ID, :V$LANG_CODE)
            INTO :V$PARAM_SIZE;

            IF (V$PARAM_SIZE != '' ) THEN
            BEGIN
                PARAM_CAPTION = PARAM_CAPTION || ' (' || V$PARAM_SIZE || ')';
            END
            SUSPEND;
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FILTERFIELD_ADD (
    I$FILTERFIELDSSET_ID BIGINT,
    I$PARAM_ID BIGINT)
RETURNS (
    FILTERFIELD_NUM SMALLINT)
AS
BEGIN
    FILTERFIELD_NUM = NULL;

    SELECT MAX(FILTERFIELD_NUM) + 1
    FROM FILTERFIELDS
    WHERE FILTERFIELDSSET_ID = :I$FILTERFIELDSSET_ID
    INTO :FILTERFIELD_NUM;

    IF (FILTERFIELD_NUM IS NULL) THEN FILTERFIELD_NUM = 1;

    INSERT
    INTO FILTERFIELDS
                   (
                    FILTERFIELDSSET_ID,
                    FILTERFIELD_NUM,
                    PARAM_ID
                   )
            VALUES
                   (
                     :I$FILTERFIELDSSET_ID,
                     :FILTERFIELD_NUM,
                     :I$PARAM_ID
                    );

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FILTERFIELD_DEL (
    I$FILTERFIELDSSET_ID BIGINT,
    I$USER_ID BIGINT,
    I$LEVEL_ID BIGINT,
    I$TYPE_ID BIGINT)
AS
DECLARE VARIABLE V$COUNT INTEGER;
BEGIN
    SELECT COUNT(*)
    FROM FILTERFIELDSSETS
    WHERE FILTERFIELDSSET_ID = :I$FILTERFIELDSSET_ID
    AND USER_ID = :I$USER_ID
    AND LEVEL_ID = :I$LEVEL_ID
    AND TYPE_ID = :I$TYPE_ID
    INTO :V$COUNT;
    IF (V$COUNT > 0) THEN
    BEGIN
        DELETE
        FROM FILTERFIELDS
        WHERE FILTERFIELDSSET_ID = :I$FILTERFIELDSSET_ID;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FILTERS_LIST (
    I$USER_ID BIGINT,
    I$LEVEL_ID BIGINT)
RETURNS (
    FILTER_ID BIGINT,
    USER_ID BIGINT,
    TYPE_ID BIGINT,
    LEVEL_ID BIGINT,
    FILTER_NAME VARCHAR(100),
    PARENT_TYPE_ID BIGINT,
    IS_LAST SMALLINT,
    IS_ACTIVE SMALLINT)
AS
BEGIN
    FOR
        SELECT FILTER_ID,
               USER_ID,
               TYPE_ID,
               LEVEL_ID,
               FILTER_NAME,
               PARENT_TYPE_ID,
               IS_LAST,
               IS_ACTIVE
        FROM FILTERS
        WHERE USER_ID = :I$USER_ID
        AND LEVEL_ID = :I$LEVEL_ID
        ORDER BY IS_LAST DESC, FILTER_NAME
        INTO   :FILTER_ID,
               :USER_ID,
               :TYPE_ID,
               :LEVEL_ID,
               :FILTER_NAME,
               :PARENT_TYPE_ID,
               :IS_LAST,
               :IS_ACTIVE
    DO
    BEGIN
        IF (IS_LAST = 1) THEN
        BEGIN
            FILTER_NAME = '<...>';
        END
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FILTERVALS_LIST (
    I$FILTER_ID BIGINT,
    I$LANG_CODE VARCHAR(2) = 'RU')
RETURNS (
    FILTER_ID BIGINT,
    FILTER_NUM SMALLINT,
    PARAM_ID BIGINT,
    PARAM_TYPE SMALLINT,
    CAPTION VARCHAR(4000),
    VAL_TYPE VARCHAR(100),
    VAL VARCHAR(4000),
    LIST_ID BIGINT,
    LISTVAL_ID BIGINT,
    OPERATOR SMALLINT,
    REGION VARCHAR(255),
    DISTRICT VARCHAR(255),
    TOWN VARCHAR(255),
    SETTLEMENT VARCHAR(255),
    STREET VARCHAR(255),
    HOUSE VARCHAR(10),
    LITER VARCHAR(10),
    CORP VARCHAR(10),
    FLAT VARCHAR(10),
    POST_INDEX VARCHAR(20),
    RUN_SQL VARCHAR(1000))
AS
declare variable V$RES_ID bigint;
BEGIN
    FOR
        SELECT FV.FILTER_ID,
               FV.FILTER_NUM,
               FV.PARAM_ID,
               FV.VAL_TYPE,
               FV.VAL,
               FV.OPERATOR,
               FV.REGION,
               FV.DISTRICT,
               FV.TOWN,
               FV.SETTLEMENT,
               FV.STREET,
               FV.HOUSE,
               FV.LITER,
               FV.CORP,
               FV.FLAT,
               FV.POST_INDEX,
               P.LIST_ID,
               P.PARAM_TYPE,
               P.RES_ID,
               P.RUN_SQL
        FROM FILTERVALS FV
        INNER JOIN PARAMS P
        ON P.PARAM_ID = FV.PARAM_ID
        WHERE FV.FILTER_ID = :I$FILTER_ID
        INTO   :FILTER_ID,
               :FILTER_NUM,
               :PARAM_ID,
               :VAL_TYPE,
               :VAL,
               :OPERATOR,
               :REGION,
               :DISTRICT,
               :TOWN,
               :SETTLEMENT,
               :STREET,
               :HOUSE,
               :LITER,
               :CORP,
               :FLAT,
               :POST_INDEX,
               :LIST_ID,
               :PARAM_TYPE,
               :V$RES_ID,
               :RUN_SQL
    DO
    BEGIN
        LISTVAL_ID = NULL;

        SELECT VAL FROM RES_GET(:V$RES_ID,  :I$LANG_CODE) INTO :CAPTION;

        IF (VAL_TYPE = 'LIST_VALUE' AND VAL <> '') THEN
        BEGIN
            LISTVAL_ID = CAST(VAL AS BIGINT);

            FOR
                SELECT RES_ID
                FROM LISTVALS
                WHERE LIST_ID = :LIST_ID
                AND LISTVAL_ID = :LISTVAL_ID
                INTO :V$RES_ID
            DO
            BEGIN
                SELECT VAL FROM RES_GET(:V$RES_ID,  :I$LANG_CODE) INTO :VAL;
            END

        END
        ELSE IF (VAL_TYPE = 'REFERENCE' AND VAL <> '') THEN
        BEGIN
            LISTVAL_ID = CAST(VAL AS BIGINT);
            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:LISTVAL_ID)
            INTO :VAL;
        END

        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FILTERVAL_ADD (
    I$FILTER_ID BIGINT,
    I$PARAM_ID BIGINT,
    I$VAL VARCHAR(4000),
    I$OPERATOR SMALLINT,
    I$REGION VARCHAR(255) = NULL,
    I$DISTRICT VARCHAR(255) = NULL,
    I$TOWN VARCHAR(255) = NULL,
    I$SETTLEMENT VARCHAR(255) = NULL,
    I$STREET VARCHAR(255) = NULL,
    I$HOUSE VARCHAR(10) = NULL,
    I$LITER VARCHAR(10) = NULL,
    I$CORP VARCHAR(10) = NULL,
    I$FLAT VARCHAR(10) = NULL,
    I$POST_INDEX VARCHAR(20) = NULL)
RETURNS (
    FILTER_NUM SMALLINT)
AS
DECLARE VARIABLE VAL_TYPE VARCHAR(100);
BEGIN
    VAL_TYPE = NULL;
    FILTER_NUM = NULL;

    SELECT PT.VAL_TYPE
    FROM PARAMS P
    INNER JOIN PARAMTYPES PT
    ON PT.PARAM_TYPE = P.PARAM_TYPE
    WHERE P.PARAM_ID = :I$PARAM_ID
    INTO :VAL_TYPE;

    IF (VAL_TYPE IS NULL) THEN SUSPEND;

    SELECT MAX(FILTER_NUM) + 1
    FROM FILTERVALS
    WHERE FILTER_ID = :I$FILTER_ID
    INTO :FILTER_NUM;

    IF (FILTER_NUM IS NULL) THEN FILTER_NUM = 1;

    INSERT
    INTO FILTERVALS
                   (
                    FILTER_ID,
                    FILTER_NUM,
                    PARAM_ID,
                    VAL_TYPE,
                    VAL,
                    OPERATOR,
                    REGION,
                    DISTRICT,
                    TOWN,
                    SETTLEMENT,
                    STREET,
                    HOUSE,
                    LITER,
                    CORP,
                    FLAT,
                    POST_INDEX
                   )
            VALUES
                   (
                    :I$FILTER_ID,
                    :FILTER_NUM,
                    :I$PARAM_ID,
                    :VAL_TYPE,
                    :I$VAL,
                    :I$OPERATOR,
                    :I$REGION,
                    :I$DISTRICT,
                    :I$TOWN,
                    :I$SETTLEMENT,
                    :I$STREET,
                    :I$HOUSE,
                    :I$LITER,
                    :I$CORP,
                    :I$FLAT,
                    :I$POST_INDEX
                    );

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FILTERVAL_DEL (
    I$FILTER_ID BIGINT,
    I$USER_ID BIGINT,
    I$LEVEL_ID BIGINT)
AS
DECLARE VARIABLE V$COUNT INT;
BEGIN
    SELECT COUNT(*)
    FROM FILTERS
    WHERE FILTER_ID = :I$FILTER_ID
    AND USER_ID = :I$USER_ID
    AND LEVEL_ID = :I$LEVEL_ID
    INTO :V$COUNT;
    IF (V$COUNT > 0) THEN
    BEGIN
        DELETE
        FROM FILTERVALS
        WHERE FILTER_ID = :I$FILTER_ID;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FILTER_ADD (
    I$FILTER_ID BIGINT,
    I$USER_ID BIGINT,
    I$TYPE_ID BIGINT,
    I$LEVEL_ID BIGINT,
    I$FILTER_NAME VARCHAR(100),
    I$IS_LAST SMALLINT,
    I$LOGICAL_OPERATOR SMALLINT,
    I$PARENT_TYPE_ID BIGINT,
    I$ACTUAL_DATE DATE,
    I$IS_ACTUAL_DATE_USED SMALLINT)
RETURNS (
    FILTER_ID BIGINT)
AS
BEGIN
    IF (I$FILTER_NAME IS NULL) THEN
    BEGIN
        I$FILTER_NAME = '';
    END
    UPDATE FILTERS
    SET IS_ACTIVE = 0
    WHERE USER_ID = :I$USER_ID
    AND LEVEL_ID = :I$LEVEL_ID;
    IF (I$FILTER_ID IS NULL AND I$IS_LAST = 1) THEN
    BEGIN
        SELECT FILTER_ID
        FROM FILTERS
        WHERE USER_ID = :I$USER_ID
        AND LEVEL_ID = :I$LEVEL_ID
        AND IS_LAST = 1
        INTO   :I$FILTER_ID;
    END
    IF (I$FILTER_ID IS NOT NULL) THEN
    BEGIN
        FILTER_ID = :I$FILTER_ID;
        UPDATE FILTERS
        SET TYPE_ID = :I$TYPE_ID,
        FILTER_NAME = :I$FILTER_NAME,
        LOGICAL_OPERATOR = :I$LOGICAL_OPERATOR,
        PARENT_TYPE_ID = :I$PARENT_TYPE_ID,
        IS_ACTIVE = 1,
        ACTUAL_DATE = :I$ACTUAL_DATE,
        IS_ACTUAL_DATE_USED = :I$IS_ACTUAL_DATE_USED
        WHERE FILTER_ID = :I$FILTER_ID;
    END
    ELSE
    BEGIN
        INSERT
        INTO FILTERS
                    (
                     USER_ID,
                     TYPE_ID,
                     LEVEL_ID,
                     FILTER_NAME,
                     IS_LAST,
                     LOGICAL_OPERATOR,
                     PARENT_TYPE_ID,
                     IS_ACTIVE,
                     ACTUAL_DATE,
                     IS_ACTUAL_DATE_USED
                    )
              VALUES
                    (
                     :I$USER_ID,
                     :I$TYPE_ID,
                     :I$LEVEL_ID,
                     :I$FILTER_NAME,
                     :I$IS_LAST,
                     :I$LOGICAL_OPERATOR,
                     :I$PARENT_TYPE_ID,
                     1,
                     :I$ACTUAL_DATE,
                     :I$IS_ACTUAL_DATE_USED
                    )
        RETURNING FILTER_ID
        INTO :FILTER_ID;
    END
    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FILTER_APARAM_CHECK (
    I$PARAM_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$OP SMALLINT,
    I$TYPE_ID BIGINT,
    I$PARAM_OBJ_TYPE_ID BIGINT,
    I$REGION VARCHAR(255),
    I$DISTRICT VARCHAR(255),
    I$TOWN VARCHAR(255),
    I$SETTLEMENT VARCHAR(255),
    I$STREET VARCHAR(255),
    I$HOUSE VARCHAR(10),
    I$LITER VARCHAR(10),
    I$CORP VARCHAR(10),
    I$FLAT VARCHAR(10),
    I$POST_INDEX VARCHAR(20))
RETURNS (
    C INTEGER,
    OBJ_ID BIGINT)
AS
BEGIN
    C = 0;
    IF (I$OP = 1) THEN
    BEGIN
        IF (I$PARAM_OBJ_TYPE_ID = I$TYPE_ID) THEN
        BEGIN
            SELECT FIRST 1
                   1,
                   OBJ_ID
            FROM VALA
            WHERE PARAM_ID = :I$PARAM_ID
            AND OBJ_ID = :I$OBJ_ID
            AND IS_DEL = 0
            AND REGION LIKE :I$REGION
            AND ((:I$DISTRICT IS NULL) OR (:I$DISTRICT = '') OR (DISTRICT LIKE :I$DISTRICT))
            AND ((:I$TOWN IS NULL) OR (:I$TOWN = '') OR TOWN LIKE :I$TOWN)
            AND ((:I$SETTLEMENT IS NULL) OR (:I$TOWN = '')  OR (SETTLEMENT LIKE :I$SETTLEMENT))
            AND ((:I$STREET IS NULL) OR (:I$STREET = '') OR (STREET LIKE :I$STREET))
            AND ((:I$HOUSE IS NULL) OR (:I$HOUSE = '') OR (HOUSE LIKE :I$HOUSE))
            AND ((:I$LITER IS NULL) OR (:I$LITER = '') OR (LITER LIKE :I$LITER))
            AND ((:I$CORP IS NULL) OR (:I$CORP = '') OR (CORP LIKE :I$CORP))
            AND ((:I$FLAT IS NULL) OR (:I$FLAT = '') OR (FLAT LIKE :I$FLAT))
            AND ((:I$POST_INDEX IS NULL) OR (:I$POST_INDEX = '') OR (POST_INDEX LIKE :I$POST_INDEX))
            INTO :C,
                 :OBJ_ID;
        END
        ELSE
        BEGIN
            SELECT FIRST 1
                   1,
                   L.OBJ_ID
            FROM LINKS L
            INNER JOIN VALA V
            ON PARAM_ID = :I$PARAM_ID
            AND V.OBJ_ID = L.OBJ_ID
            AND V.IS_DEL = 0
            AND V.REGION LIKE :I$REGION
            AND ((:I$DISTRICT IS NULL) OR (:I$DISTRICT = '') OR (V.DISTRICT LIKE :I$DISTRICT))
            AND ((:I$TOWN IS NULL) OR (:I$TOWN = '') OR V.TOWN LIKE :I$TOWN)
            AND ((:I$SETTLEMENT IS NULL) OR (:I$TOWN = '')  OR (V.SETTLEMENT LIKE :I$SETTLEMENT))
            AND ((:I$STREET IS NULL) OR (:I$STREET = '') OR (V.STREET LIKE :I$STREET))
            AND ((:I$HOUSE IS NULL) OR (:I$HOUSE = '') OR (V.HOUSE LIKE :I$HOUSE))
            AND ((:I$LITER IS NULL) OR (:I$LITER = '') OR (V.LITER LIKE :I$LITER))
            AND ((:I$CORP IS NULL) OR (:I$CORP = '') OR (V.CORP LIKE :I$CORP))
            AND ((:I$FLAT IS NULL) OR (:I$FLAT = '') OR (V.FLAT LIKE :I$FLAT))
            AND ((:I$POST_INDEX IS NULL) OR (:I$POST_INDEX = '') OR (V.POST_INDEX LIKE :I$POST_INDEX))
            WHERE L.PARENT_ID = :I$OBJ_ID
            AND L.OBJ_TYPE_ID = :I$PARAM_OBJ_TYPE_ID
            AND L.DATE_DEL IS NULL
            INTO :C,
                 :OBJ_ID;
        END
    END
    ELSE IF (I$OP = 2) THEN
    BEGIN /* NULL */
        IF (I$PARAM_OBJ_TYPE_ID = I$TYPE_ID) THEN
        BEGIN
            SELECT FIRST 1
                   1,
                   OBJ_ID
            FROM VALA
            WHERE PARAM_ID=:I$PARAM_ID
            AND OBJ_ID=:I$OBJ_ID
            AND IS_DEL = 0
            INTO :C,
                 :OBJ_ID;
        END
        ELSE
        BEGIN
            SELECT FIRST 1
                   1,
                   L.OBJ_ID
            FROM LINKS L
            INNER JOIN VALA V
            ON V.PARAM_ID = :I$PARAM_ID
            AND V.OBJ_ID = L.OBJ_ID
            AND V.IS_DEL = 0
            WHERE L.PARENT_ID = :I$OBJ_ID
            AND L.DATE_DEL IS NULL
            AND L.OBJ_TYPE_ID = :I$PARAM_OBJ_TYPE_ID
            INTO :C,
                 :OBJ_ID;
        END
        IF (C = 1) THEN
        BEGIN
            C = 0;
        END
        ELSE
        BEGIN
            C = 1;
        END
    END
    ELSE IF (I$OP = 3) THEN
    BEGIN /* NOT NULL */
        IF (I$PARAM_OBJ_TYPE_ID = I$TYPE_ID) THEN
        BEGIN
            SELECT FIRST 1
                   1,
                   OBJ_ID
            FROM VALA
            WHERE PARAM_ID = :I$PARAM_ID
            AND OBJ_ID = :I$OBJ_ID
            AND IS_DEL = 0
            INTO :C,
                 :OBJ_ID;
        END
        ELSE
        BEGIN
            SELECT FIRST 1
                   1,
                   L.OBJ_ID
            FROM LINKS L
            INNER JOIN VALA V
            ON V.PARAM_ID = :I$PARAM_ID
            AND V.OBJ_ID = L.OBJ_ID
            AND V.IS_DEL = 0
            WHERE L.PARENT_ID = :I$OBJ_ID
            AND L.DATE_DEL IS NULL
            AND L.OBJ_TYPE_ID = :I$PARAM_OBJ_TYPE_ID
            INTO :C,
                 :OBJ_ID;
        END
    END
    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FILTER_APPLY (
    I$OBJ_ID BIGINT,
    I$USER_ID BIGINT,
    I$LEVEL_ID BIGINT)
RETURNS (
    ROW_NUM INTEGER,
    COL_NUM INTEGER,
    OBJ_ID BIGINT,
    TYPE_ID BIGINT,
    TAB_ID BIGINT,
    PARENT_ID BIGINT,
    PARENT_TYPE_ID BIGINT,
    PARENT_LINK_ID BIGINT,
    PARENT_CAPTION VARCHAR(3000),
    LINK_ID BIGINT,
    PARAM_ID BIGINT,
    PARAM_TYPE SMALLINT,
    PARAM_CAPTION VARCHAR(3000),
    HINT_CAPTION VARCHAR(3000),
    EDIT_MASK VARCHAR(200),
    VAL VARCHAR(4000),
    DO_FUNC BIGINT,
    IS_DEL SMALLINT,
    EDIT_TYPE SMALLINT,
    LISTVAL_ID BIGINT,
    LIST_ID BIGINT,
    LIST_EDIT_TYPE SMALLINT,
    REGION VARCHAR(255),
    DISTRICT VARCHAR(255),
    TOWN VARCHAR(255),
    SETTLEMENT VARCHAR(255),
    STREET VARCHAR(255),
    HOUSE VARCHAR(10),
    LITER VARCHAR(10),
    CORP VARCHAR(10),
    FLAT VARCHAR(10),
    POST_INDEX VARCHAR(20))
AS
declare variable V$FILTER_ID bigint;
declare variable V$PARAM_ID bigint;
declare variable V$VAL varchar(4000);
declare variable V$REGION varchar(255);
declare variable V$DISTRICT varchar(255);
declare variable V$TOWN varchar(255);
declare variable V$SETTLEMENT varchar(255);
declare variable V$STREET varchar(255);
declare variable V$HOUSE varchar(10);
declare variable V$CORP varchar(10);
declare variable V$LITER varchar(10);
declare variable V$FLAT varchar(10);
declare variable V$POST_INDEX varchar(20);
declare variable OP smallint;
declare variable C integer;
declare variable X smallint;
declare variable VAL_TYPE varchar(100);
declare variable IS_EXISTS integer;
declare variable SO smallint;
declare variable SOF smallint;
declare variable I bigint;
declare variable V$TYPE_ID bigint;
declare variable V$PARAM_OBJECT_TYPE_ID bigint;
declare variable V$PARENT_TYPE_ID bigint;
declare variable V$LANG_CODE varchar(2);
declare variable V$LOGICAL_OPERATOR smallint;
declare variable V$ACTUAL_DATE date;
declare variable V$IS_ACTUAL_DATE_USED smallint;
declare variable V$DATE_DEL date;
declare variable V$HINT_RES_ID bigint;
BEGIN
    ROW_NUM = 0;
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :V$LANG_CODE;
    SELECT FIRST 1
           TYPE_ID,
           PARENT_TYPE_ID,
           FILTER_ID,
           LOGICAL_OPERATOR,
           ACTUAL_DATE,
           IS_ACTUAL_DATE_USED
    FROM FILTERS
    WHERE USER_ID = :I$USER_ID
    AND LEVEL_ID = :I$LEVEL_ID
    AND IS_ACTIVE = 1
    INTO :V$TYPE_ID,
         :V$PARENT_TYPE_ID,
         :V$FILTER_ID,
         :V$LOGICAL_OPERATOR,
         :V$ACTUAL_DATE,
         :V$IS_ACTUAL_DATE_USED;
    FOR
        SELECT DISTINCT
               F.OBJ_ID,
               O2.TYPE_ID,
               F.LINK_ID,
               L.PARENT_ID,
               O.TYPE_ID,
               P.TAB_ID,
               L.DATE_DEL
        FROM FILTER_OBJECT_CHILDREN_GET(:I$OBJ_ID, NULL, :V$TYPE_ID, :I$LEVEL_ID) F
        INNER JOIN LINKS L
        ON L.LINK_ID = F.LINK_ID
        AND (:V$IS_ACTUAL_DATE_USED = 0 OR ((L.DATE_INS <= :V$ACTUAL_DATE)
        AND ((L.DATE_DEL IS NULL) OR (:V$ACTUAL_DATE <= L.DATE_DEL) )))
        LEFT OUTER JOIN OBJECTS O
        ON O.OBJ_ID = L.PARENT_ID
        LEFT OUTER JOIN OBJECTS O2
        ON O2.OBJ_ID = F.OBJ_ID
        INNER JOIN PARENTS P
        ON P.CHILD_ID = O2.TYPE_ID
        AND P.TYPE_ID = O.TYPE_ID
        AND P.IS_DEL = 0

        WHERE (:V$PARENT_TYPE_ID IS NULL OR :V$PARENT_TYPE_ID = O.TYPE_ID)
        INTO   :OBJ_ID,
               :TYPE_ID,
               :LINK_ID,
               :PARENT_ID,
               :PARENT_TYPE_ID,
               :TAB_ID,
               :V$DATE_DEL
    DO
    BEGIN
        IF (V$DATE_DEL IS NULL) THEN
        BEGIN
            IS_DEL = 0;
        END
        ELSE
        BEGIN
            IS_DEL = 1;
        END
        SELECT FIRST 1
               L.LINK_ID
        FROM LINKS L
        LEFT OUTER JOIN OBJECTS O
        ON O.OBJ_ID = L.PARENT_ID
        LEFT OUTER JOIN LTYPES LT
        ON LT.TYPE_ID = O.TYPE_ID
        AND LT.LEVEL_ID = :I$LEVEL_ID
        WHERE L.OBJ_ID = :PARENT_ID
        AND L.DATE_DEL IS NULL
        AND :TAB_ID IS NOT NULL
        INTO :PARENT_LINK_ID;


        IF (V$LOGICAL_OPERATOR = 1) THEN/*AND*/
        BEGIN
            X = 1;
        END
        ELSE/*OR*/
        BEGIN
            SELECT COUNT(*)
            FROM FILTERVALS F
            WHERE FILTER_ID = :V$FILTER_ID
            INTO  :X;
            IF(X = 0) THEN
            BEGIN
                X = 1;
            END
        END
        IF (X = 1) THEN
        BEGIN
            V$LOGICAL_OPERATOR = 1;
        END
        FOR
            SELECT F.PARAM_ID,
                   F.VAL,
                   F.VAL_TYPE,
                   F.OPERATOR,
                   F.REGION,
                   F.DISTRICT,
                   F.TOWN,
                   F.SETTLEMENT,
                   F.STREET,
                   F.HOUSE,
                   F.LITER,
                   F.CORP,
                   F.FLAT,
                   F.POST_INDEX,
                   T.TYPE_ID
            FROM FILTERVALS F
            LEFT OUTER JOIN PARAMS P
            ON P.PARAM_ID = F.PARAM_ID
            LEFT OUTER JOIN TYPES T
            ON T.TYPE_ID = P.TYPE_ID
            WHERE FILTER_ID = :V$FILTER_ID
            ORDER BY FILTER_NUM
            INTO  :V$PARAM_ID,
                  :V$VAL,
                  :VAL_TYPE,
                  :OP,
                  :V$REGION,
                  :V$DISTRICT,
                  :V$TOWN,
                  :V$SETTLEMENT,
                  :V$STREET,
                  :V$HOUSE,
                  :V$LITER,
                  :V$CORP,
                  :V$FLAT,
                  :V$POST_INDEX,
                  :V$PARAM_OBJECT_TYPE_ID
        DO
        BEGIN
            IF ((X = 1 AND V$LOGICAL_OPERATOR = 1) OR (X = 0 AND V$LOGICAL_OPERATOR = 2)) THEN
            BEGIN
                IF (VAL_TYPE = 'ADDRESS') THEN
                BEGIN
                    IF (OP = 1) THEN
                    BEGIN
                        SELECT COUNT(*)
                        FROM VALA
                        WHERE PARAM_ID=:V$PARAM_ID
                        AND OBJ_ID=:OBJ_ID
                        AND IS_DEL = 0
                        AND REGION LIKE :V$REGION
                        AND ((:V$DISTRICT IS NULL) OR (:V$DISTRICT = '') OR (DISTRICT LIKE :V$DISTRICT))
                        AND ((:V$TOWN IS NULL) OR (:V$TOWN = '') OR TOWN LIKE :V$TOWN)
                        AND ((:V$SETTLEMENT IS NULL) OR (:V$TOWN = '')  OR (SETTLEMENT LIKE :V$SETTLEMENT))
                        AND ((:V$STREET IS NULL) OR (:V$STREET = '') OR (STREET LIKE :V$STREET))
                        AND ((:V$HOUSE IS NULL) OR (:V$HOUSE = '') OR (HOUSE LIKE :V$HOUSE))
                        AND ((:V$LITER IS NULL) OR (:V$LITER = '') OR (LITER LIKE :V$LITER))
                        AND ((:V$CORP IS NULL) OR (:V$CORP = '') OR (CORP LIKE :V$CORP))
                        AND ((:V$FLAT IS NULL) OR (:V$FLAT = '') OR (FLAT LIKE :V$FLAT))
                        AND ((:V$POST_INDEX IS NULL) OR (:V$POST_INDEX = '') OR (POST_INDEX LIKE :V$POST_INDEX))
                        INTO :C;
                    END
                    ELSE IF (OP = 2) THEN
                    BEGIN /* NULL */
                        SELECT COUNT(*)
                        FROM VALA
                        WHERE PARAM_ID=:V$PARAM_ID
                        AND OBJ_ID=:OBJ_ID
                        AND IS_DEL = 0
                        INTO :C;
                        IF (C = 1) THEN
                        BEGIN
                            C = 0;
                        END
                        ELSE
                        BEGIN
                            C = 1;
                        END
                    END
                    ELSE IF (OP = 3) THEN
                    BEGIN /* NOT NULL */
                        SELECT COUNT(*)
                        FROM VALA
                        WHERE PARAM_ID=:V$PARAM_ID
                        AND OBJ_ID=:OBJ_ID
                        AND IS_DEL = 0
                        INTO :C;
                    END
                END
                ELSE IF (VAL_TYPE = 'INTEGER') THEN
                BEGIN
                    IF (OP = 1) THEN
                    BEGIN /* = */
                        SELECT COUNT(*)
                        FROM VALI
                        WHERE PARAM_ID=:V$PARAM_ID
                        AND OBJ_ID=:OBJ_ID
                        AND IS_DEL = 0
                        AND VAL = CAST(:V$VAL AS INTEGER)
                        INTO :C;
                    END
                    ELSE IF (OP = 2) THEN
                    BEGIN /* <> */
                        SELECT COUNT(*)
                        FROM VALI
                        WHERE PARAM_ID=:V$PARAM_ID
                        AND OBJ_ID=:OBJ_ID
                        AND IS_DEL = 0
                        AND VAL <> CAST(:V$VAL AS INTEGER)
                        INTO :C;
                    END
                    ELSE IF (OP = 3) THEN
                    BEGIN /* > */
                        SELECT COUNT(*)
                        FROM VALI
                        WHERE PARAM_ID=:V$PARAM_ID
                        AND OBJ_ID=:OBJ_ID
                        AND IS_DEL = 0
                        AND VAL > CAST(:V$VAL AS INTEGER)
                        INTO :C;
                    END
                    ELSE IF (OP = 4) THEN
                    BEGIN /* < */
                        SELECT COUNT(*)
                        FROM VALI
                        WHERE PARAM_ID=:V$PARAM_ID
                        AND OBJ_ID=:OBJ_ID
                        AND IS_DEL = 0
                        AND VAL < CAST(:V$VAL AS INTEGER)
                        INTO :C;
                    END
                    ELSE IF (OP = 5) THEN
                    BEGIN /* >= */
                        SELECT COUNT(*)
                        FROM VALI
                        WHERE PARAM_ID=:V$PARAM_ID
                        AND OBJ_ID=:OBJ_ID
                        AND IS_DEL = 0
                        AND VAL >= CAST(:V$VAL AS INTEGER)
                        INTO :C;
                    END
                    ELSE IF (OP = 6) THEN
                    BEGIN /* <= */
                        SELECT COUNT(*)
                        FROM VALI
                        WHERE PARAM_ID=:V$PARAM_ID
                        AND OBJ_ID=:OBJ_ID
                        AND IS_DEL = 0
                        AND VAL <= CAST(:V$VAL AS INTEGER)
                        INTO :C;
                    END
                    ELSE IF (OP = 7) THEN
                    BEGIN /* NULL */
                        SELECT COUNT(*)
                        FROM VALI
                        WHERE PARAM_ID=:V$PARAM_ID
                        AND OBJ_ID=:OBJ_ID
                        AND IS_DEL = 0
                        INTO :C;
                        IF (C = 1) THEN
                        BEGIN
                            C = 0;
                        END
                        ELSE
                        BEGIN
                            C = 1;
                        END
                    END
                    ELSE IF (OP = 8) THEN
                    BEGIN /* NOT NULL */
                        SELECT COUNT(*)
                        FROM VALI
                        WHERE PARAM_ID=:V$PARAM_ID
                        AND OBJ_ID=:OBJ_ID
                        AND IS_DEL = 0
                        INTO :C;
                    END
                END
                ELSE IF (VAL_TYPE = 'FLOAT') THEN
                BEGIN
                    IF (OP = 1) THEN
                    BEGIN /* = */
                        SELECT COUNT(*)
                        FROM VALF
                        WHERE PARAM_ID=:V$PARAM_ID
                        AND OBJ_ID=:OBJ_ID
                        AND IS_DEL = 0
                        AND VAL = CAST(:V$VAL AS DOUBLE PRECISION)
                        INTO :C;
                    END
                    ELSE IF (OP = 2) THEN
                    BEGIN /* <> */
                        SELECT COUNT(*)
                        FROM VALF
                        WHERE PARAM_ID=:V$PARAM_ID
                        AND OBJ_ID=:OBJ_ID
                        AND IS_DEL = 0
                        AND VAL <> CAST(:V$VAL AS DOUBLE PRECISION)
                        INTO :C;
                    END
                    ELSE IF (OP = 3) THEN
                    BEGIN /* > */
                        SELECT COUNT(*)
                        FROM VALF
                        WHERE PARAM_ID=:V$PARAM_ID
                        AND OBJ_ID=:OBJ_ID
                        AND IS_DEL = 0
                        AND VAL > CAST(:V$VAL AS DOUBLE PRECISION)
                        INTO :C;
                    END
                    ELSE IF (OP = 4) THEN
                    BEGIN /* < */
                        SELECT COUNT(*)
                        FROM VALF
                        WHERE PARAM_ID=:V$PARAM_ID
                        AND OBJ_ID=:OBJ_ID
                        AND IS_DEL = 0
                        AND VAL < CAST(:V$VAL AS DOUBLE PRECISION)
                        INTO :C;
                    END
                    ELSE IF (OP = 5) THEN
                    BEGIN /* >= */
                        SELECT COUNT(*)
                        FROM VALF
                        WHERE PARAM_ID=:V$PARAM_ID
                        AND OBJ_ID=:OBJ_ID
                        AND IS_DEL = 0
                        AND VAL >= CAST(:V$VAL AS DOUBLE PRECISION)
                        INTO :C;
                    END
                    ELSE IF (OP = 6) THEN
                    BEGIN /* <= */
                        SELECT COUNT(*)
                        FROM VALF
                        WHERE PARAM_ID=:V$PARAM_ID
                        AND OBJ_ID=:OBJ_ID
                        AND IS_DEL = 0
                        AND VAL <= CAST(:V$VAL AS DOUBLE PRECISION)
                        INTO :C;
                    END
                    ELSE IF (OP = 7) THEN
                    BEGIN /* NULL */
                        SELECT COUNT(*)
                        FROM VALF
                        WHERE PARAM_ID=:V$PARAM_ID
                        AND OBJ_ID=:OBJ_ID
                        AND IS_DEL = 0
                        INTO :C;
                        IF (C = 1) THEN
                        BEGIN
                            C = 0;
                        END
                        ELSE
                        BEGIN
                            C = 1;
                        END
                    END
                    ELSE IF (OP = 8) THEN
                    BEGIN /* NOT NULL */
                        SELECT COUNT(*)
                        FROM VALF
                        WHERE PARAM_ID=:V$PARAM_ID
                        AND OBJ_ID=:OBJ_ID
                        AND IS_DEL = 0
                        INTO :C;
                    END
                END
                ELSE IF (VAL_TYPE = 'TIMESTAMP') THEN
                BEGIN
                    IF (OP = 1) THEN
                    BEGIN /* = */
                        SELECT COUNT(*)
                        FROM VALDT
                        WHERE PARAM_ID=:V$PARAM_ID
                        AND OBJ_ID=:OBJ_ID
                        AND IS_DEL = 0
                        AND VAL = CAST(:V$VAL AS TIMESTAMP)
                        INTO :C;
                    END
                    ELSE IF (OP = 2) THEN
                    BEGIN /* <> */
                        SELECT COUNT(*)
                        FROM VALDT
                        WHERE PARAM_ID=:V$PARAM_ID
                        AND OBJ_ID=:OBJ_ID
                        AND IS_DEL = 0
                        AND VAL <> CAST(:V$VAL AS TIMESTAMP)
                        INTO :C;
                    END
                    ELSE IF (OP = 3) THEN
                    BEGIN /* > */
                        SELECT COUNT(*)
                        FROM VALDT
                        WHERE PARAM_ID=:V$PARAM_ID
                        AND OBJ_ID=:OBJ_ID
                        AND IS_DEL = 0
                        AND VAL > CAST(:V$VAL AS TIMESTAMP)
                        INTO :C;
                    END
                    ELSE IF (OP = 4) THEN
                    BEGIN /* < */
                        SELECT COUNT(*)
                        FROM VALDT
                        WHERE PARAM_ID=:V$PARAM_ID
                        AND OBJ_ID=:OBJ_ID
                        AND IS_DEL = 0
                        AND VAL < CAST(:V$VAL AS TIMESTAMP)
                        INTO :C;
                    END
                    ELSE IF (OP = 5) THEN
                    BEGIN /* >= */
                        SELECT COUNT(*)
                        FROM VALDT
                        WHERE PARAM_ID=:V$PARAM_ID
                        AND OBJ_ID=:OBJ_ID
                        AND IS_DEL = 0
                        AND VAL >= CAST(:V$VAL AS TIMESTAMP)
                        INTO :C;
                    END
                    ELSE IF (OP = 6) THEN
                    BEGIN /* <= */
                        SELECT COUNT(*)
                        FROM VALDT
                        WHERE PARAM_ID=:V$PARAM_ID
                        AND OBJ_ID=:OBJ_ID
                        AND IS_DEL = 0
                        AND VAL <= CAST(:V$VAL AS TIMESTAMP)
                        INTO :C;
                    END
                    ELSE IF (OP = 7) THEN
                    BEGIN /* NULL */
                        SELECT COUNT(*)
                        FROM VALDT
                        WHERE PARAM_ID=:V$PARAM_ID
                        AND OBJ_ID=:OBJ_ID
                        AND IS_DEL = 0
                        INTO :C;
                        IF (C = 1) THEN
                        BEGIN
                            C = 0;
                        END
                        ELSE
                        BEGIN
                            C = 1;
                        END
                    END
                    ELSE IF (OP = 8) THEN
                    BEGIN /* NOT NULL */
                        SELECT COUNT(*)
                        FROM VALDT
                        WHERE PARAM_ID=:V$PARAM_ID
                        AND OBJ_ID=:OBJ_ID
                        AND IS_DEL = 0
                        INTO :C;
                    END
                END
                ELSE IF (VAL_TYPE = 'DATE') THEN
                BEGIN
                    IF (OP = 1) THEN
                    BEGIN /* = */
                        SELECT COUNT(*)
                        FROM VALD
                        WHERE PARAM_ID=:V$PARAM_ID
                        AND OBJ_ID=:OBJ_ID
                        AND IS_DEL = 0
                        AND VAL = CAST(:V$VAL AS DATE)
                        INTO :C;
                    END
                    ELSE IF (OP = 2) THEN
                    BEGIN /* <> */
                        SELECT COUNT(*)
                        FROM VALD
                        WHERE PARAM_ID=:V$PARAM_ID
                        AND OBJ_ID=:OBJ_ID
                        AND IS_DEL = 0
                        AND VAL <> CAST(:V$VAL AS DATE)
                        INTO :C;
                    END
                    ELSE IF (OP = 3) THEN
                    BEGIN /* > */
                        SELECT COUNT(*)
                        FROM VALD
                        WHERE PARAM_ID=:V$PARAM_ID
                        AND OBJ_ID=:OBJ_ID
                        AND IS_DEL = 0
                        AND VAL > CAST(:V$VAL AS DATE)
                        INTO :C;
                    END
                    ELSE IF (OP = 4) THEN
                    BEGIN /* < */
                        SELECT COUNT(*)
                        FROM VALD
                        WHERE PARAM_ID=:V$PARAM_ID
                        AND OBJ_ID=:OBJ_ID
                        AND IS_DEL = 0
                        AND VAL < CAST(:V$VAL AS DATE)
                        INTO :C;
                    END
                    ELSE IF (OP = 5) THEN
                    BEGIN /* >= */
                        SELECT COUNT(*)
                        FROM VALD
                        WHERE PARAM_ID=:V$PARAM_ID
                        AND OBJ_ID=:OBJ_ID
                        AND IS_DEL = 0
                        AND VAL >= CAST(:V$VAL AS DATE)
                        INTO :C;
                    END
                    ELSE IF (OP = 6) THEN
                    BEGIN /* <= */
                        SELECT COUNT(*)
                        FROM VALD
                        WHERE PARAM_ID=:V$PARAM_ID
                        AND OBJ_ID=:OBJ_ID
                        AND IS_DEL = 0
                        AND VAL <= CAST(:V$VAL AS DATE)
                        INTO :C;
                    END
                    ELSE IF (OP = 7) THEN
                    BEGIN /* NULL */
                        SELECT COUNT(*)
                        FROM VALD
                        WHERE PARAM_ID=:V$PARAM_ID
                        AND OBJ_ID=:OBJ_ID
                        AND IS_DEL = 0
                        INTO :C;
                        IF (C = 1) THEN
                        BEGIN
                            C = 0;
                        END
                        ELSE
                        BEGIN
                            C = 1;
                        END
                    END
                    ELSE IF (OP = 8) THEN
                    BEGIN /* NOT NULL */
                        SELECT COUNT(*)
                        FROM VALD
                        WHERE PARAM_ID=:V$PARAM_ID
                        AND OBJ_ID=:OBJ_ID
                        AND IS_DEL = 0
                        INTO :C;
                    END
                    ELSE IF (OP = 9) THEN
                    BEGIN /* ~ */
                       SELECT COUNT(*)
                        FROM VALD
                        WHERE PARAM_ID=:V$PARAM_ID
                        AND OBJ_ID=:OBJ_ID
                        AND IS_DEL = 0
                        AND VAL LIKE :V$VAL
                        INTO :C;
                    END
                END
                ELSE IF (VAL_TYPE = 'TIME') THEN
                BEGIN
                    IF (OP = 1) THEN
                    BEGIN /* = */
                        SELECT COUNT(*)
                        FROM VALT
                        WHERE PARAM_ID=:V$PARAM_ID
                        AND OBJ_ID=:OBJ_ID
                        AND IS_DEL = 0
                        AND VAL = CAST(:V$VAL AS TIME)
                        INTO :C;
                    END
                    ELSE IF (OP = 2) THEN
                    BEGIN /* <> */
                        SELECT COUNT(*)
                        FROM VALT
                        WHERE PARAM_ID=:V$PARAM_ID
                        AND OBJ_ID=:OBJ_ID
                        AND IS_DEL = 0
                        AND VAL <> CAST(:V$VAL AS TIME)
                        INTO :C;
                    END
                    ELSE IF (OP = 3) THEN
                    BEGIN /* > */
                        SELECT COUNT(*)
                        FROM VALT
                        WHERE PARAM_ID=:V$PARAM_ID
                        AND OBJ_ID=:OBJ_ID
                        AND IS_DEL = 0
                        AND VAL > CAST(:V$VAL AS TIME)
                        INTO :C;
                    END
                    ELSE IF (OP = 4) THEN
                    BEGIN /* < */
                        SELECT COUNT(*)
                        FROM VALT
                        WHERE PARAM_ID=:V$PARAM_ID
                        AND OBJ_ID=:OBJ_ID
                        AND IS_DEL = 0
                        AND VAL < CAST(:V$VAL AS TIME)
                        INTO :C;
                    END
                    ELSE IF (OP = 5) THEN
                    BEGIN /* >= */
                        SELECT COUNT(*)
                        FROM VALT
                        WHERE PARAM_ID=:V$PARAM_ID
                        AND OBJ_ID=:OBJ_ID
                        AND IS_DEL = 0
                        AND VAL >= CAST(:V$VAL AS TIME)
                        INTO :C;
                    END
                    ELSE IF (OP = 6) THEN
                    BEGIN /* <= */
                        SELECT COUNT(*)
                        FROM VALT
                        WHERE PARAM_ID=:V$PARAM_ID
                        AND OBJ_ID=:OBJ_ID
                        AND IS_DEL = 0
                        AND VAL <= CAST(:V$VAL AS TIME)
                        INTO :C;
                    END
                    ELSE IF (OP = 7) THEN
                    BEGIN /* NULL */
                        SELECT COUNT(*)
                        FROM VALT
                        WHERE PARAM_ID=:V$PARAM_ID
                        AND OBJ_ID=:OBJ_ID
                        AND IS_DEL = 0
                        INTO :C;
                        IF (C = 1) THEN
                        BEGIN
                            C = 0;
                        END
                        ELSE
                        BEGIN
                            C = 1;
                        END
                    END
                    ELSE IF (OP = 8) THEN
                    BEGIN /* NOT NULL */
                        SELECT COUNT(*)
                        FROM VALT
                        WHERE PARAM_ID=:V$PARAM_ID
                        AND OBJ_ID=:OBJ_ID
                        AND IS_DEL = 0
                        INTO :C;
                    END
                END
                ELSE IF (VAL_TYPE = 'REFERENCE') THEN
                BEGIN
                    IF (OP = 1) THEN
                    BEGIN /* = */
                        SELECT COUNT(*)
                        FROM VALR
                        WHERE PARAM_ID=:V$PARAM_ID
                        AND OBJ_ID=:OBJ_ID
                        AND IS_DEL = 0
                        AND VAL = CAST(:V$VAL AS BIGINT)
                        INTO :C;
                    END
                    ELSE IF (OP = 2) THEN
                    BEGIN /* <> */
                        SELECT COUNT(*)
                        FROM VALR
                        WHERE PARAM_ID=:V$PARAM_ID
                        AND OBJ_ID=:OBJ_ID
                        AND IS_DEL = 0
                        AND VAL <> CAST(:V$VAL AS BIGINT)
                        INTO :C;
                    END
                    ELSE IF (OP = 3) THEN
                    BEGIN /* NULL */
                        SELECT COUNT(*)
                        FROM VALR
                        WHERE PARAM_ID=:V$PARAM_ID
                        AND OBJ_ID=:OBJ_ID
                        AND IS_DEL = 0
                        INTO :C;
                        IF (C = 1) THEN
                        BEGIN
                            C = 0;
                        END
                        ELSE
                        BEGIN
                            C = 1;
                        END
                    END
                    ELSE IF (OP = 4) THEN
                    BEGIN /* NOT NULL */
                        SELECT COUNT(*)
                        FROM VALR
                        WHERE PARAM_ID=:V$PARAM_ID
                        AND OBJ_ID=:OBJ_ID
                        AND IS_DEL = 0
                        INTO :C;
                    END
                END
                ELSE IF (VAL_TYPE = 'LIST_VALUE') THEN
                BEGIN
                    IF (OP = 1) THEN
                    BEGIN /* = */
                        SELECT COUNT(*)
                        FROM VALL
                        WHERE PARAM_ID=:V$PARAM_ID
                        AND OBJ_ID=:OBJ_ID
                        AND IS_DEL = 0
                        AND LISTVAL_ID = CAST(:V$VAL AS BIGINT)
                        INTO :C;
                    END
                    ELSE IF (OP = 2) THEN
                    BEGIN /* <> */
                        SELECT COUNT(*)
                        FROM VALL
                        WHERE PARAM_ID=:V$PARAM_ID
                        AND OBJ_ID=:OBJ_ID
                        AND IS_DEL = 0
                        AND LISTVAL_ID <> CAST(:V$VAL AS BIGINT)
                        INTO :C;
                    END
                    ELSE IF ((OP > 2) AND (OP < 7)) THEN
                    BEGIN
                        I = NULL;
                        C = 0;
                        SELECT SORT_ORDER
                        FROM LISTVALS
                        WHERE LISTVAL_ID = CAST (:V$VAL AS BIGINT)
                        INTO :SOF;

                        SELECT LISTVAL_ID
                        FROM VALL
                        WHERE PARAM_ID=:V$PARAM_ID
                        AND OBJ_ID=:OBJ_ID
                        AND IS_DEL = 0
                        INTO :I;

                        IS_EXISTS = ROW_COUNT;

                        IF (IS_EXISTS > 0) THEN
                        BEGIN
                            SELECT SORT_ORDER
                            FROM LISTVALS
                            WHERE LISTVAL_ID = :I
                            INTO :SO;

                            IF (((OP = 3) AND (IS_EXISTS > 0) AND (SO > SOF)) OR
                                ((OP = 4) AND (IS_EXISTS > 0) AND (SO < SOF)) OR
                                ((OP = 5) AND (IS_EXISTS > 0) AND (SO >= SOF)) OR
                                ((OP = 6) AND (IS_EXISTS > 0) AND (SO >= SOF))) THEN
                            BEGIN
                                C = 1;
                            END
                        END
                    END
                    ELSE IF (OP = 7) THEN
                    BEGIN /* NULL */
                        SELECT COUNT(*)
                        FROM VALL
                        WHERE PARAM_ID=:V$PARAM_ID
                        AND OBJ_ID=:OBJ_ID
                        AND IS_DEL = 0
                        INTO :C;
                        IF (C = 1) THEN
                        BEGIN
                            C = 0;
                        END
                        ELSE
                        BEGIN
                            C = 1;
                        END
                    END
                    ELSE IF (OP = 8) THEN
                    BEGIN /* NOT NULL */
                        SELECT COUNT(*)
                        FROM VALL
                        WHERE PARAM_ID=:V$PARAM_ID
                        AND OBJ_ID=:OBJ_ID
                        AND IS_DEL = 0
                        INTO :C;
                    END
                END
                ELSE IF (VAL_TYPE IN ('STRING_OR_LIST_VALUE', 'STRING_OR_LIST_VALUE_RO', 'STRING', 'SQL_QUERY', 'FUNCTION')) THEN
                BEGIN
                    IF (OP = 1) THEN
                    BEGIN /* = */
                        SELECT COUNT(*)
                        FROM VALS
                        WHERE PARAM_ID=:V$PARAM_ID
                        AND OBJ_ID=:OBJ_ID
                        AND IS_DEL = 0
                        AND UPPER(VAL) = UPPER(:V$VAL)
                        INTO :C;
                    END
                    ELSE IF (OP = 2) THEN
                    BEGIN /* <> */
                        SELECT COUNT(*)
                        FROM VALS
                        WHERE PARAM_ID=:V$PARAM_ID
                        AND OBJ_ID=:OBJ_ID
                        AND IS_DEL = 0
                        AND UPPER(VAL) <> UPPER(:V$VAL)
                        INTO :C;
                    END
                    ELSE IF (OP = 3) THEN
                    BEGIN /* > */
                        SELECT COUNT(*)
                        FROM VALS
                        WHERE PARAM_ID=:V$PARAM_ID
                        AND OBJ_ID=:OBJ_ID
                        AND IS_DEL = 0
                        AND UPPER(VAL) > UPPER(:V$VAL)
                        INTO :C;
                    END
                    ELSE IF (OP = 4) THEN
                    BEGIN /* < */
                        SELECT COUNT(*)
                        FROM VALS
                        WHERE PARAM_ID=:V$PARAM_ID
                        AND OBJ_ID=:OBJ_ID
                        AND IS_DEL = 0
                        AND UPPER(VAL) < UPPER(:V$VAL)
                        INTO :C;
                    END
                    ELSE IF (OP = 5) THEN
                    BEGIN /* >= */
                        SELECT COUNT(*)
                        FROM VALS
                        WHERE PARAM_ID=:V$PARAM_ID
                        AND OBJ_ID=:OBJ_ID
                        AND IS_DEL = 0
                        AND UPPER(VAL) >= UPPER(:V$VAL)
                        INTO :C;
                    END
                    ELSE IF (OP = 6) THEN
                    BEGIN /* <= */
                        SELECT COUNT(*)
                        FROM VALS
                        WHERE PARAM_ID=:V$PARAM_ID
                        AND OBJ_ID=:OBJ_ID
                        AND IS_DEL = 0
                        AND UPPER(VAL) <= UPPER(:V$VAL)
                        INTO :C;
                    END
                    ELSE IF (OP = 7) THEN
                    BEGIN /* NULL */
                        SELECT COUNT(*)
                        FROM VALS
                        WHERE PARAM_ID=:V$PARAM_ID
                        AND OBJ_ID=:OBJ_ID
                        AND IS_DEL = 0
                        INTO :C;
                        IF (C = 1) THEN
                        BEGIN
                            C = 0;
                        END
                        ELSE
                        BEGIN
                            C = 1;
                        END
                    END
                    ELSE IF (OP = 8) THEN
                    BEGIN /* NOT NULL */
                        SELECT COUNT(*)
                        FROM VALS
                        WHERE PARAM_ID=:V$PARAM_ID
                        AND OBJ_ID=:OBJ_ID
                        AND IS_DEL = 0
                        INTO :C;
                    END
                    ELSE IF (OP = 9) THEN
                    BEGIN /* ~ */
                        SELECT COUNT(*)
                        FROM VALS
                        WHERE PARAM_ID=:V$PARAM_ID
                        AND OBJ_ID=:OBJ_ID
                        AND IS_DEL = 0
                        AND UPPER(VAL) LIKE UPPER(:V$VAL)
                        INTO :C;
                    END
                END
            END

            IF (C < 1) THEN
            BEGIN
                X = 0;
            END
            ELSE
            BEGIN
                X = 1;
            END
        END

        IF (X = 1) THEN
        BEGIN
            COL_NUM = 0;
            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:PARENT_ID, NULL, NULL, :I$USER_ID)
            INTO :PARENT_CAPTION;
            X = 0;
            FOR
                SELECT FF.PARAM_ID,
                       P.PARAM_TYPE,
                       LP.EDIT_TYPE,
                       P.LIST_ID,
                       P."DO_FUNC",
                       P.HINT_RES_ID,
                       P.EDIT_MASK
                FROM FILTERFIELDSSETS FFS
                INNER JOIN FILTERFIELDS FF
                ON FF.FILTERFIELDSSET_ID = FFS.FILTERFIELDSSET_ID
                INNER JOIN PARAMS P
                ON P.PARAM_ID = FF.PARAM_ID
                INNER JOIN LPARAMS LP
                ON LP.PARAM_ID = P.PARAM_ID
                AND LP.LEVEL_ID = :I$LEVEL_ID
                WHERE FFS.USER_ID = :I$USER_ID
                AND FFS.LEVEL_ID = :I$LEVEL_ID
                AND FFS.TYPE_ID = :V$TYPE_ID
                AND FFS.IS_ACTIVE = 1
                INTO   :PARAM_ID,
                       :PARAM_TYPE,
                       :EDIT_TYPE,
                       :LIST_ID,
                       :DO_FUNC,
                       :V$HINT_RES_ID,
                       :EDIT_MASK
            DO
            BEGIN
                LIST_EDIT_TYPE = -1;
                IF (PARAM_TYPE = 6) THEN  /* LIST_VALUE */
                BEGIN
                    SELECT L.EDIT_TYPE
                    FROM LLISTS L
                    WHERE L.LEVEL_ID = :I$LEVEL_ID
                    AND L.LIST_ID = :LIST_ID
                    AND L.IS_DEL = 0
                    INTO :LIST_EDIT_TYPE;
                END

                LISTVAL_ID = NULL;
                REGION = NULL;
                DISTRICT = NULL;
                TOWN = NULL;
                SETTLEMENT = NULL;
                STREET = NULL;
                HOUSE = NULL;
                LITER = NULL;
                CORP = NULL;
                FLAT = NULL;
                POST_INDEX = NULL;

                IF (PARAM_TYPE = 17 OR PARAM_TYPE = 19) THEN
                BEGIN
                    SELECT VAL
                    FROM DO_FUNC(:OBJ_ID,:PARAM_ID,:DO_FUNC,NULL,:I$USER_ID,:PARENT_ID)
                    INTO :VAL;
                END
                ELSE IF (PARAM_TYPE = 18) THEN
                BEGIN
                    SELECT VAL,
                           REGION,
                           DISTRICT,
                           TOWN,
                           SETTLEMENT,
                           STREET,
                           HOUSE,
                           LITER,
                           CORP,
                           FLAT,
                           POST_INDEX
                    FROM ADR_GET(:PARAM_ID,:OBJ_ID)
                    INTO :VAL,
                         :REGION,
                         :DISTRICT,
                         :TOWN,
                         :SETTLEMENT,
                         :STREET,
                         :HOUSE,
                         :LITER,
                         :CORP,
                         :FLAT,
                         :POST_INDEX;
                END
                ELSE
                BEGIN
                    SELECT V,I
                    FROM VAL_GET(:OBJ_ID, :PARAM_ID, 0, :I$USER_ID)
                    INTO :VAL,:LISTVAL_ID;
                END

                SELECT CAPTION
                FROM PARAM_CAPTION_GET(:OBJ_ID, :PARAM_ID, :I$LEVEL_ID,:V$LANG_CODE, 1)
                INTO   :PARAM_CAPTION;

                SELECT VAL
                FROM RES_GET(:V$HINT_RES_ID, :V$LANG_CODE)
                INTO :HINT_CAPTION;

                X = X + 1;
                IF (COL_NUM > 0) THEN
                BEGIN
                    PARENT_CAPTION = NULL;
                END
                IF (VAL = '') THEN
                BEGIN
                    VAL = NULL;
                END
                SUSPEND;
                COL_NUM = COL_NUM + 1;
            END
            IF(X = 0) THEN
            BEGIN
                SELECT COUNT(*)
                FROM PARAMS P
                INNER JOIN LPARAMS LP
                ON LP.PARAM_ID = P.PARAM_ID
                AND LP.LEVEL_ID = :I$LEVEL_ID
                AND LP.EDIT_TYPE > -1
                WHERE P.TYPE_ID = :V$TYPE_ID
                AND P.IS_DEL = 0
                AND P.IS_TREEVIEW = 1
                INTO   :X;

                FOR
                    SELECT P.PARAM_ID,
                           P.PARAM_TYPE,
                           LP.EDIT_TYPE,
                           P.LIST_ID,
                           P.HINT_RES_ID,
                           P.DO_FUNC,
                           P.EDIT_MASK
                    FROM PARAMS P
                    INNER JOIN LPARAMS LP
                    ON LP.PARAM_ID = P.PARAM_ID
                    AND LP.LEVEL_ID = :I$LEVEL_ID
                    AND LP.EDIT_TYPE > -1
                    WHERE P.TYPE_ID = :V$TYPE_ID
                    AND P.IS_DEL = 0
                    AND (P.IS_TREEVIEW = 1 OR :X = 0)
                    ORDER BY P.GRID_ORDER
                    INTO   :PARAM_ID,
                           :PARAM_TYPE,
                           :EDIT_TYPE,
                           :LIST_ID,
                           :V$HINT_RES_ID,
                           :DO_FUNC,
                           :EDIT_MASK
                DO
                BEGIN

                    LISTVAL_ID = NULL;
                    REGION = NULL;
                    DISTRICT = NULL;
                    TOWN = NULL;
                    SETTLEMENT = NULL;
                    STREET = NULL;
                    HOUSE = NULL;
                    LITER = NULL;
                    CORP = NULL;
                    FLAT = NULL;
                    POST_INDEX = NULL;

                    IF (PARAM_TYPE = 17 OR PARAM_TYPE = 19) THEN
                    BEGIN
                        SELECT VAL
                        FROM DO_FUNC(:OBJ_ID,:PARAM_ID,:DO_FUNC,NULL,:I$USER_ID, :PARENT_ID)
                        INTO :VAL;
                    END
                    ELSE IF (PARAM_TYPE = 18) THEN
                    BEGIN
                        SELECT VAL,
                               REGION,
                               DISTRICT,
                               TOWN,
                               SETTLEMENT,
                               STREET,
                               HOUSE,
                               LITER,
                               CORP,
                               FLAT,
                               POST_INDEX
                        FROM ADR_GET(:PARAM_ID,:OBJ_ID)
                        INTO :VAL,
                             :REGION,
                             :DISTRICT,
                             :TOWN,
                             :SETTLEMENT,
                             :STREET,
                             :HOUSE,
                             :LITER,
                             :CORP,
                             :FLAT,
                             :POST_INDEX;
                    END
                    ELSE
                    BEGIN
                        SELECT V,I
                        FROM VAL_GET(:OBJ_ID, :PARAM_ID, 0, :I$USER_ID)
                        INTO :VAL,:LISTVAL_ID;
                    END

                    SELECT CAPTION
                    FROM PARAM_CAPTION_GET(:OBJ_ID, :PARAM_ID, :I$LEVEL_ID,:V$LANG_CODE, 1)
                    INTO   :PARAM_CAPTION;

                    SELECT VAL
                    FROM RES_GET(:V$HINT_RES_ID, :V$LANG_CODE)
                    INTO :HINT_CAPTION;

                    IF (COL_NUM > 0) THEN
                    BEGIN
                        PARENT_CAPTION = NULL;
                    END
                    IF (VAL = '') THEN
                    BEGIN
                        VAL = NULL;
                    END
                    SUSPEND;
                    COL_NUM = COL_NUM + 1;
                END
            END
            ROW_NUM = ROW_NUM + 1;
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FILTER_APPLY2 (
    I$OBJ_ID BIGINT,
    I$USER_ID BIGINT,
    I$LEVEL_ID BIGINT)
RETURNS (
    ROW_NUM INTEGER,
    COL_NUM INTEGER,
    OBJ_ID BIGINT,
    TYPE_ID BIGINT,
    TAB_ID BIGINT,
    CHILD_ID BIGINT,
    CHILD_TYPE_ID BIGINT,
    PARENT_ID BIGINT,
    PARENT_TYPE_ID BIGINT,
    PARENT_LINK_ID BIGINT,
    PARENT_CAPTION VARCHAR(3000),
    LINK_ID BIGINT,
    PARAM_ID BIGINT,
    PARAM_TYPE SMALLINT,
    PARAM_CAPTION VARCHAR(3000),
    HINT_CAPTION VARCHAR(3000),
    EDIT_MASK VARCHAR(200),
    VAL VARCHAR(4000),
    DO_FUNC BIGINT,
    IS_DEL SMALLINT,
    EDIT_TYPE SMALLINT,
    LISTVAL_ID BIGINT,
    LIST_ID BIGINT,
    LIST_EDIT_TYPE SMALLINT,
    REGION VARCHAR(255),
    DISTRICT VARCHAR(255),
    TOWN VARCHAR(255),
    SETTLEMENT VARCHAR(255),
    STREET VARCHAR(255),
    HOUSE VARCHAR(10),
    LITER VARCHAR(10),
    CORP VARCHAR(10),
    FLAT VARCHAR(10),
    POST_INDEX VARCHAR(20))
AS
declare variable V$CHILD_ID bigint;
declare variable V$FILTER_ID bigint;
declare variable V$PARAM_ID bigint;
declare variable V$VAL varchar(4000);
declare variable V$REGION varchar(255);
declare variable V$DISTRICT varchar(255);
declare variable V$TOWN varchar(255);
declare variable V$SETTLEMENT varchar(255);
declare variable V$STREET varchar(255);
declare variable V$HOUSE varchar(10);
declare variable V$CORP varchar(10);
declare variable V$LITER varchar(10);
declare variable V$FLAT varchar(10);
declare variable V$POST_INDEX varchar(20);
declare variable OP smallint;
declare variable C integer;
declare variable X smallint;
declare variable VAL_TYPE varchar(100);
declare variable V$TYPE_ID bigint;
declare variable V$PARAM_OBJECT_TYPE_ID bigint;
declare variable V$PARAM_OBJ_ID bigint;
declare variable V$PARENT_TYPE_ID bigint;
declare variable V$LANG_CODE varchar(2);
declare variable V$LOGICAL_OPERATOR smallint;
declare variable V$ACTUAL_DATE date;
declare variable V$IS_ACTUAL_DATE_USED smallint;
declare variable V$DATE_DEL date;
declare variable V$HINT_RES_ID bigint;
declare variable Y integer;
declare variable M integer;
declare variable D integer;
declare variable N integer;
declare variable GCHAR char(3);
declare variable LCHAR char(3);
declare variable MCHAR char(3);
declare variable DCHAR char(3);
BEGIN
    ROW_NUM = 0;

    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :V$LANG_CODE;

    SELECT FIRST 1 TYPE_ID, PARENT_TYPE_ID, FILTER_ID, LOGICAL_OPERATOR, ACTUAL_DATE, IS_ACTUAL_DATE_USED
    FROM FILTERS
    WHERE USER_ID = :I$USER_ID
      AND LEVEL_ID = :I$LEVEL_ID
      AND IS_ACTIVE = 1
    INTO :V$TYPE_ID, :V$PARENT_TYPE_ID, :V$FILTER_ID, :V$LOGICAL_OPERATOR, :V$ACTUAL_DATE, :V$IS_ACTUAL_DATE_USED;

    FOR SELECT DISTINCT F.OBJ_ID, O2.TYPE_ID, F.LINK_ID, L.PARENT_ID, O.TYPE_ID, P.TAB_ID, L.DATE_DEL
        FROM FILTER_OBJECT_CHILDREN_GET(:I$OBJ_ID, NULL, :V$TYPE_ID, :I$LEVEL_ID) F
        INNER JOIN LINKS L ON L.LINK_ID = F.LINK_ID AND (:V$IS_ACTUAL_DATE_USED = 0 OR ((L.DATE_INS <= :V$ACTUAL_DATE) AND ((L.DATE_DEL IS NULL) OR (:V$ACTUAL_DATE <= L.DATE_DEL))))
        LEFT OUTER JOIN OBJECTS O ON O.OBJ_ID = L.PARENT_ID
        LEFT OUTER JOIN OBJECTS O2 ON O2.OBJ_ID = F.OBJ_ID
        INNER JOIN PARENTS P ON P.CHILD_ID = O2.TYPE_ID AND P.TYPE_ID = O.TYPE_ID AND P.IS_DEL = 0
        WHERE (:V$PARENT_TYPE_ID IS NULL OR :V$PARENT_TYPE_ID = O.TYPE_ID)
        INTO :OBJ_ID, :TYPE_ID, :LINK_ID, :PARENT_ID, :PARENT_TYPE_ID, :TAB_ID, :V$DATE_DEL
    DO
    BEGIN
        IF (V$DATE_DEL IS NULL) THEN
        BEGIN
            IS_DEL = 0;
        END
        ELSE
        BEGIN
            IS_DEL = 1;
        END
        SELECT FIRST 1 L.LINK_ID
        FROM LINKS L
        LEFT OUTER JOIN OBJECTS O ON O.OBJ_ID = L.PARENT_ID
        LEFT OUTER JOIN LTYPES LT ON LT.TYPE_ID = O.TYPE_ID AND LT.LEVEL_ID = :I$LEVEL_ID
        WHERE L.OBJ_ID = :PARENT_ID
          AND L.DATE_DEL IS NULL
              --AND :TAB_ID IS NOT NULL
        INTO :PARENT_LINK_ID;

        IF (V$LOGICAL_OPERATOR = 1) THEN
        /*AND*/
        BEGIN
            X = 1;
        END
        ELSE
        /*OR*/
        BEGIN
            SELECT COUNT(*)
            FROM FILTERVALS F
            WHERE FILTER_ID = :V$FILTER_ID
            INTO :X;
            IF (X = 0) THEN
            BEGIN
                X = 1;
            END
        END
        IF (X = 1) THEN
        BEGIN
            V$LOGICAL_OPERATOR = 1;
        END

        DELETE FROM FILTER_SESSION_VALS
        WHERE 1 = 1;

        FOR SELECT F.PARAM_ID, F.VAL, F.VAL_TYPE, F.OPERATOR, F.REGION, F.DISTRICT, F.TOWN, F.SETTLEMENT, F.STREET,
                   F.HOUSE, F.LITER, F.CORP, F.FLAT, F.POST_INDEX, P.TYPE_ID
            FROM FILTERVALS F
            LEFT OUTER JOIN PARAMS P ON P.PARAM_ID = F.PARAM_ID
            WHERE FILTER_ID = :V$FILTER_ID
            ORDER BY FILTER_NUM
            INTO :V$PARAM_ID, :V$VAL, :VAL_TYPE, :OP, :V$REGION, :V$DISTRICT, :V$TOWN, :V$SETTLEMENT, :V$STREET,
                 :V$HOUSE, :V$LITER, :V$CORP, :V$FLAT, :V$POST_INDEX, :V$PARAM_OBJECT_TYPE_ID
        DO
        BEGIN
            IF ((X = 1 AND
                V$LOGICAL_OPERATOR = 1) OR (X = 0 AND
                V$LOGICAL_OPERATOR = 2)) THEN
            BEGIN
                IF (VAL_TYPE = 'ADDRESS') THEN
                BEGIN
                    SELECT C, OBJ_ID
                    FROM FILTER_APARAM_CHECK(:V$PARAM_ID, :OBJ_ID, :OP, :TYPE_ID, :V$PARAM_OBJECT_TYPE_ID, :V$REGION, :V$DISTRICT, :V$TOWN, :V$SETTLEMENT, :V$STREET, :V$HOUSE, :V$LITER, :V$CORP, :V$FLAT, :V$POST_INDEX)
                    INTO :C, :V$PARAM_OBJ_ID;
                END
                ELSE
                IF (VAL_TYPE = 'INTEGER') THEN
                BEGIN
                    SELECT C, OBJ_ID
                    FROM FILTER_IPARAM_CHECK(:V$PARAM_ID, :OBJ_ID, :OP, :TYPE_ID, :V$PARAM_OBJECT_TYPE_ID, :V$VAL)
                    INTO :C, :V$PARAM_OBJ_ID;
                END
                ELSE
                IF (VAL_TYPE = 'FLOAT') THEN
                BEGIN
                    SELECT C, OBJ_ID
                    FROM FILTER_FPARAM_CHECK(:V$PARAM_ID, :OBJ_ID, :OP, :TYPE_ID, :V$PARAM_OBJECT_TYPE_ID, :V$VAL)
                    INTO :C, :V$PARAM_OBJ_ID;
                END
                ELSE
                IF (VAL_TYPE = 'TIMESTAMP') THEN
                BEGIN
                    SELECT C, OBJ_ID
                    FROM FILTER_DTPARAM_CHECK(:V$PARAM_ID, :OBJ_ID, :OP, :TYPE_ID, :V$PARAM_OBJECT_TYPE_ID, :V$VAL)
                    INTO :C, :V$PARAM_OBJ_ID;
                END
                ELSE
                IF (VAL_TYPE = 'DATE') THEN
                BEGIN
                    SELECT C, OBJ_ID
                    FROM FILTER_DPARAM_CHECK(:V$PARAM_ID, :OBJ_ID, :OP, :TYPE_ID, :V$PARAM_OBJECT_TYPE_ID, :V$VAL)
                    INTO :C, :V$PARAM_OBJ_ID;
                END
                ELSE
                IF (VAL_TYPE = 'TIME') THEN
                BEGIN
                    SELECT C, OBJ_ID
                    FROM FILTER_TPARAM_CHECK(:V$PARAM_ID, :OBJ_ID, :OP, :TYPE_ID, :V$PARAM_OBJECT_TYPE_ID, :V$VAL)
                    INTO :C, :V$PARAM_OBJ_ID;
                END
                ELSE
                IF (VAL_TYPE = 'REFERENCE') THEN
                BEGIN
                    SELECT C, OBJ_ID
                    FROM FILTER_RPARAM_CHECK(:V$PARAM_ID, :OBJ_ID, :OP, :TYPE_ID, :V$PARAM_OBJECT_TYPE_ID, :V$VAL)
                    INTO :C, :V$PARAM_OBJ_ID;
                END
                ELSE
                IF (VAL_TYPE = 'LIST_VALUE') THEN
                BEGIN
                    SELECT C, OBJ_ID
                    FROM FILTER_LPARAM_CHECK(:V$PARAM_ID, :OBJ_ID, :OP, :TYPE_ID, :V$PARAM_OBJECT_TYPE_ID, :V$VAL)
                    INTO :C, :V$PARAM_OBJ_ID;
                END
                ELSE
                IF (VAL_TYPE = 'CALC_FUNCTION') THEN
                BEGIN
                    SELECT C, OBJ_ID
                    FROM FILTER_CPARAM_CHECK(:V$PARAM_ID, :OBJ_ID, :OP, :TYPE_ID, :V$PARAM_OBJECT_TYPE_ID, :V$VAL)
                    INTO :C, :V$PARAM_OBJ_ID;
                END
                ELSE
                IF (VAL_TYPE IN ('STRING_OR_LIST_VALUE_RO', 'STRING_OR_LIST_VALUE', 'STRING', 'SQL_QUERY', 'FUNCTION')) THEN
                BEGIN
                    SELECT C, OBJ_ID
                    FROM FILTER_SPARAM_CHECK(:V$PARAM_ID, :OBJ_ID, :OP, :TYPE_ID, :V$PARAM_OBJECT_TYPE_ID, :V$VAL)
                    INTO :C, :V$PARAM_OBJ_ID;
                END
            END

            IF (C < 1) THEN
            BEGIN
                X = 0;
            END
            ELSE
            BEGIN
                X = 1;
            END
            IF ((X = 1) AND
                (V$PARAM_OBJECT_TYPE_ID IS NOT NULL) AND
                (V$PARAM_OBJ_ID IS NOT NULL) AND
                (V$PARAM_OBJECT_TYPE_ID <> TYPE_ID)) THEN
            BEGIN
                INSERT INTO FILTER_SESSION_VALS (TYPE_ID, OBJ_ID)
                VALUES (:V$PARAM_OBJECT_TYPE_ID, :V$PARAM_OBJ_ID);
            END
        END

        IF (X = 1) THEN
        BEGIN
            CHILD_ID = NULL;
            CHILD_TYPE_ID = NULL;

            COL_NUM = 0;

            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:PARENT_ID, NULL, NULL, :I$USER_ID)
            INTO :PARENT_CAPTION;

            X = 0;

            FOR SELECT FF.PARAM_ID, P.PARAM_TYPE, LP.EDIT_TYPE, P.LIST_ID, P."DO_FUNC", P.HINT_RES_ID, P.EDIT_MASK,
                       T.TYPE_ID
                FROM FILTERFIELDSSETS FFS
                INNER JOIN FILTERFIELDS FF ON FF.FILTERFIELDSSET_ID = FFS.FILTERFIELDSSET_ID
                INNER JOIN PARAMS P ON P.PARAM_ID = FF.PARAM_ID AND P.TYPE_ID = FFS.TYPE_ID
                INNER JOIN LPARAMS LP ON LP.PARAM_ID = P.PARAM_ID AND LP.LEVEL_ID = :I$LEVEL_ID
                INNER JOIN TYPES T ON T.TYPE_ID = P.TYPE_ID
                LEFT OUTER JOIN TABS TB ON TB.TAB_ID = P.TAB_ID
                WHERE FFS.USER_ID = :I$USER_ID
                  AND FFS.LEVEL_ID = :I$LEVEL_ID
                  AND FFS.TYPE_ID = :TYPE_ID
                  AND FFS.IS_ACTIVE = 1
                ORDER BY T.SORT_ORDER, TB.TAB_NUM, P.GRID_ORDER
                INTO :PARAM_ID, :PARAM_TYPE, :EDIT_TYPE, :LIST_ID, :DO_FUNC, :V$HINT_RES_ID, :EDIT_MASK,
                     :CHILD_TYPE_ID
            DO
            BEGIN
                IF (CHILD_TYPE_ID = TYPE_ID) THEN
                BEGIN
                    CHILD_TYPE_ID = NULL;
                END
                LIST_EDIT_TYPE = -1;
                IF (PARAM_TYPE = 6) THEN
                /* LIST_VALUE */
                BEGIN
                    SELECT L.EDIT_TYPE
                    FROM LLISTS L
                    WHERE L.LEVEL_ID = :I$LEVEL_ID
                      AND L.LIST_ID = :LIST_ID
                      AND L.IS_DEL = 0
                    INTO :LIST_EDIT_TYPE;
                END

                LISTVAL_ID = NULL;
                REGION = NULL;
                DISTRICT = NULL;
                TOWN = NULL;
                SETTLEMENT = NULL;
                STREET = NULL;
                HOUSE = NULL;
                LITER = NULL;
                CORP = NULL;
                FLAT = NULL;
                POST_INDEX = NULL;

                IF (PARAM_TYPE = 17 OR PARAM_TYPE = 19) THEN
                BEGIN
                    SELECT VAL
                    FROM DO_FUNC(:OBJ_ID, :PARAM_ID, :DO_FUNC, NULL, :I$USER_ID, :PARENT_ID)
                    INTO :VAL;

                    IF ((:DO_FUNC = 2) AND
                        (:VAL IS NOT NULL) AND
                        (:VAL <> '')) THEN
                    BEGIN
                        N = VAL;
                        VAL = '';
                        Y = N / 360;
                        N = N - Y * 360;
                        M = N / 30;
                        N = N - M * 30;
                        D = N;

                        SELECT WORD FROM REPORT_WORDS WHERE ID = 22 INTO :LCHAR;
                        SELECT WORD FROM REPORT_WORDS WHERE ID = 23 INTO :GCHAR;
                        SELECT WORD FROM REPORT_WORDS WHERE ID = 24 INTO :MCHAR;
                        SELECT WORD FROM REPORT_WORDS WHERE ID = 25 INTO :DCHAR;

                        IF (Y > 0) THEN
                        BEGIN
                            VAL = Y || LCHAR;
                            IF (Y < 5) THEN
                            BEGIN
                                VAL = Y || GCHAR;
                            END
                        END
                        IF (M > 0) THEN
                        BEGIN
                            VAL = VAL || M || MCHAR;
                        END
                        IF (D > 0) THEN
                        BEGIN
                            VAL = VAL || D || DCHAR;
                        END
                    END
                END
                ELSE
                IF (PARAM_TYPE = 18) THEN
                BEGIN
                    SELECT VAL, REGION, DISTRICT, TOWN, SETTLEMENT, STREET, HOUSE, LITER, CORP, FLAT, POST_INDEX
                    FROM ADR_GET(:PARAM_ID, :OBJ_ID)
                    INTO :VAL, :REGION, :DISTRICT, :TOWN, :SETTLEMENT, :STREET, :HOUSE, :LITER, :CORP, :FLAT,
                         :POST_INDEX;
                END
                ELSE
                BEGIN
                    SELECT V, I
                    FROM VAL_GET(:OBJ_ID, :PARAM_ID, 0, :I$USER_ID)
                    INTO :VAL, :LISTVAL_ID;
                END

                SELECT CAPTION
                FROM PARAM_CAPTION_GET(:OBJ_ID, :PARAM_ID, :I$LEVEL_ID, :V$LANG_CODE, 1)
                INTO :PARAM_CAPTION;

                SELECT VAL
                FROM RES_GET(:V$HINT_RES_ID, :V$LANG_CODE)
                INTO :HINT_CAPTION;

                IF (COL_NUM > 0) THEN
                BEGIN
                    PARENT_CAPTION = NULL;
                END
                IF (VAL = '') THEN
                BEGIN
                    VAL = NULL;
                END
                SUSPEND;
                X = X + 1;
                COL_NUM = COL_NUM + 1;
            END

            FOR SELECT DISTINCT FF.PARAM_ID, P.PARAM_TYPE, LP.EDIT_TYPE, P.LIST_ID, P."DO_FUNC", P.HINT_RES_ID,
                                P.EDIT_MASK, P.TYPE_ID
                FROM FILTERFIELDSSETS FFS
                INNER JOIN FILTERFIELDS FF ON FF.FILTERFIELDSSET_ID = FFS.FILTERFIELDSSET_ID
                INNER JOIN PARAMS P ON P.PARAM_ID = FF.PARAM_ID
                INNER JOIN LPARAMS LP ON LP.PARAM_ID = P.PARAM_ID AND LP.LEVEL_ID = :I$LEVEL_ID
                INNER JOIN TYPES T ON T.TYPE_ID = P.TYPE_ID
                LEFT OUTER JOIN TABS TB ON TB.TAB_ID = P.TAB_ID
                WHERE FFS.USER_ID = :I$USER_ID
                  AND FFS.LEVEL_ID = :I$LEVEL_ID
                  AND FFS.TYPE_ID = :V$TYPE_ID
                  AND FFS.IS_ACTIVE = 1
                  AND P.TYPE_ID IN (SELECT DISTINCT P.TYPE_ID
                                    FROM FILTERFIELDSSETS FFS
                                    INNER JOIN FILTERFIELDS FF ON FF.FILTERFIELDSSET_ID = FFS.FILTERFIELDSSET_ID
                                    INNER JOIN PARAMS P ON P.PARAM_ID = FF.PARAM_ID
                                    INNER JOIN LPARAMS LP ON LP.PARAM_ID = P.PARAM_ID AND LP.LEVEL_ID = :I$LEVEL_ID
                                    WHERE FFS.USER_ID = :I$USER_ID
                                      AND FFS.LEVEL_ID = :I$LEVEL_ID
                                      AND FFS.TYPE_ID = :V$TYPE_ID
                                      AND FFS.IS_ACTIVE = 1
                                      AND P.TYPE_ID <> :TYPE_ID)
                ORDER BY T.SORT_ORDER, TB.TAB_NUM, P.GRID_ORDER
                INTO :PARAM_ID, :PARAM_TYPE, :EDIT_TYPE, :LIST_ID, :DO_FUNC, :V$HINT_RES_ID, :EDIT_MASK,
                     :CHILD_TYPE_ID
            DO
            BEGIN
                CHILD_ID = NULL;
                VAL = NULL;
                REGION = NULL;
                DISTRICT = NULL;
                TOWN = NULL;
                SETTLEMENT = NULL;
                STREET = NULL;
                HOUSE = NULL;
                LITER = NULL;
                CORP = NULL;
                FLAT = NULL;
                POST_INDEX = NULL;

                SELECT FIRST 1 L.OBJ_ID, FSV.OBJ_ID
                FROM LINKS L
                LEFT OUTER JOIN FILTER_SESSION_VALS FSV ON FSV.TYPE_ID = :CHILD_TYPE_ID
                WHERE L.PARENT_ID = :OBJ_ID
                  AND L.OBJ_TYPE_ID = :CHILD_TYPE_ID
                  AND L.DATE_DEL IS NULL
                ORDER BY FSV.OBJ_ID DESC
                INTO :CHILD_ID, :V$CHILD_ID;

                IF (V$CHILD_ID IS NOT NULL) THEN
                BEGIN
                    CHILD_ID = V$CHILD_ID;
                END

                SELECT CAPTION
                FROM PARAM_CAPTION_GET(:CHILD_ID, :PARAM_ID, :I$LEVEL_ID, :V$LANG_CODE, 1)
                INTO :PARAM_CAPTION;

                IF (CHILD_ID IS NOT NULL) THEN
                BEGIN
                    IF (PARAM_TYPE = 17 OR PARAM_TYPE = 19) THEN
                    BEGIN
                        SELECT VAL
                        FROM DO_FUNC(:CHILD_ID, :PARAM_ID, :DO_FUNC, NULL, :I$USER_ID, :OBJ_ID)
                        INTO :VAL;
                    END
                    ELSE
                    IF (PARAM_TYPE = 18) THEN
                    BEGIN
                        SELECT VAL, REGION, DISTRICT, TOWN, SETTLEMENT, STREET, HOUSE, LITER, CORP, FLAT, POST_INDEX
                        FROM ADR_GET(:PARAM_ID, :CHILD_ID)
                        INTO :VAL, :REGION, :DISTRICT, :TOWN, :SETTLEMENT, :STREET, :HOUSE, :LITER, :CORP, :FLAT,
                             :POST_INDEX;
                    END
                    ELSE
                    BEGIN
                        SELECT V, I
                        FROM VAL_GET(:CHILD_ID, :PARAM_ID, 0, :I$USER_ID)
                        INTO :VAL, :LISTVAL_ID;
                    END

                    SELECT CAPTION
                    FROM PARAM_CAPTION_GET(:CHILD_ID, :PARAM_ID, :I$LEVEL_ID, :V$LANG_CODE, 1)
                    INTO :PARAM_CAPTION;

                    IF (VAL = '') THEN
                    BEGIN
                        VAL = NULL;
                    END
                END
                SUSPEND;
                X = X + 1;
                COL_NUM = COL_NUM + 1;
            END

            IF (X = 0) THEN
            BEGIN
                SELECT COUNT(*)
                FROM PARAMS P
                INNER JOIN LPARAMS LP ON LP.PARAM_ID = P.PARAM_ID AND LP.LEVEL_ID = :I$LEVEL_ID AND LP.EDIT_TYPE > -1
                WHERE P.TYPE_ID = :V$TYPE_ID
                  AND P.IS_DEL = 0
                  AND P.IS_TREEVIEW = 1
                INTO :X;

                FOR SELECT P.PARAM_ID, P.PARAM_TYPE, LP.EDIT_TYPE, P.LIST_ID, P.HINT_RES_ID, P.DO_FUNC, P.EDIT_MASK
                    FROM PARAMS P
                    INNER JOIN LPARAMS LP ON LP.PARAM_ID = P.PARAM_ID AND LP.LEVEL_ID = :I$LEVEL_ID AND LP.EDIT_TYPE > -1
                    WHERE P.TYPE_ID = :V$TYPE_ID
                      AND P.IS_DEL = 0
                      AND (P.IS_TREEVIEW = 1 OR :X = 0)
                    ORDER BY P.GRID_ORDER
                    INTO :PARAM_ID, :PARAM_TYPE, :EDIT_TYPE, :LIST_ID, :V$HINT_RES_ID, :DO_FUNC, :EDIT_MASK
                DO
                BEGIN

                    LISTVAL_ID = NULL;
                    REGION = NULL;
                    DISTRICT = NULL;
                    TOWN = NULL;
                    SETTLEMENT = NULL;
                    STREET = NULL;
                    HOUSE = NULL;
                    LITER = NULL;
                    CORP = NULL;
                    FLAT = NULL;
                    POST_INDEX = NULL;

                    IF (PARAM_TYPE = 17 OR PARAM_TYPE = 19) THEN
                    BEGIN
                        SELECT VAL
                        FROM DO_FUNC(:OBJ_ID, :PARAM_ID, :DO_FUNC, NULL, :I$USER_ID, :PARENT_ID)
                        INTO :VAL;
                    END
                    ELSE
                    IF (PARAM_TYPE = 18) THEN
                    BEGIN
                        SELECT VAL, REGION, DISTRICT, TOWN, SETTLEMENT, STREET, HOUSE, LITER, CORP, FLAT, POST_INDEX
                        FROM ADR_GET(:PARAM_ID, :OBJ_ID)
                        INTO :VAL, :REGION, :DISTRICT, :TOWN, :SETTLEMENT, :STREET, :HOUSE, :LITER, :CORP, :FLAT,
                             :POST_INDEX;
                    END
                    ELSE
                    BEGIN
                        SELECT V, I
                        FROM VAL_GET(:OBJ_ID, :PARAM_ID, 0, :I$USER_ID)
                        INTO :VAL, :LISTVAL_ID;
                    END

                    SELECT CAPTION
                    FROM PARAM_CAPTION_GET(:OBJ_ID, :PARAM_ID, :I$LEVEL_ID, :V$LANG_CODE, 1)
                    INTO :PARAM_CAPTION;

                    SELECT VAL
                    FROM RES_GET(:V$HINT_RES_ID, :V$LANG_CODE)
                    INTO :HINT_CAPTION;

                    IF (COL_NUM > 0) THEN
                    BEGIN
                        PARENT_CAPTION = NULL;
                    END
                    IF (VAL = '') THEN
                    BEGIN
                        VAL = NULL;
                    END
                    SUSPEND;
                    COL_NUM = COL_NUM + 1;
                END
            END

            ROW_NUM = ROW_NUM + 1;
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FILTER_APPLY3 (
    I$OBJ_ID BIGINT,
    I$USER_ID BIGINT,
    I$LEVEL_ID BIGINT)
RETURNS (
    ROW_NUM INTEGER,
    COL_NUM INTEGER,
    OBJ_ID BIGINT,
    TYPE_ID BIGINT,
    TAB_ID BIGINT,
    CHILD_ID BIGINT,
    CHILD_TYPE_ID BIGINT,
    PARENT_ID BIGINT,
    PARENT_TYPE_ID BIGINT,
    PARENT_LINK_ID BIGINT,
    PARENT_CAPTION VARCHAR(3000),
    LINK_ID BIGINT,
    PARAM_ID BIGINT,
    PARAM_TYPE SMALLINT,
    PARAM_CAPTION VARCHAR(3000),
    HINT_CAPTION VARCHAR(3000),
    EDIT_MASK VARCHAR(200),
    VAL VARCHAR(4000),
    DO_FUNC BIGINT,
    IS_DEL SMALLINT,
    EDIT_TYPE SMALLINT,
    LISTVAL_ID BIGINT,
    LIST_ID BIGINT,
    LIST_EDIT_TYPE SMALLINT,
    REGION VARCHAR(255),
    DISTRICT VARCHAR(255),
    TOWN VARCHAR(255),
    SETTLEMENT VARCHAR(255),
    STREET VARCHAR(255),
    HOUSE VARCHAR(10),
    LITER VARCHAR(10),
    CORP VARCHAR(10),
    FLAT VARCHAR(10),
    POST_INDEX VARCHAR(20))
AS
declare variable V$CHILD_ID bigint;
declare variable V$FILTER_ID bigint;
declare variable V$PARAM_ID bigint;
declare variable V$VAL varchar(4000);
declare variable V$REGION varchar(255);
declare variable V$DISTRICT varchar(255);
declare variable V$TOWN varchar(255);
declare variable V$SETTLEMENT varchar(255);
declare variable V$STREET varchar(255);
declare variable V$HOUSE varchar(10);
declare variable V$CORP varchar(10);
declare variable V$LITER varchar(10);
declare variable V$FLAT varchar(10);
declare variable V$POST_INDEX varchar(20);
declare variable OP smallint;
declare variable C integer;
declare variable X smallint;
declare variable VAL_TYPE varchar(100);
declare variable V$TYPE_ID bigint;
declare variable V$PARAM_OBJECT_TYPE_ID bigint;
declare variable V$PARAM_OBJ_ID bigint;
declare variable V$PARENT_TYPE_ID bigint;
declare variable V$LANG_CODE varchar(2);
declare variable V$LOGICAL_OPERATOR smallint;
declare variable V$ACTUAL_DATE date;
declare variable V$IS_ACTUAL_DATE_USED smallint;
declare variable V$DATE_DEL date;
declare variable V$HINT_RES_ID bigint;
declare variable Y integer;
declare variable M integer;
declare variable D integer;
declare variable N integer;
declare variable GCHAR char(3);
declare variable LCHAR char(3);
declare variable MCHAR char(3);
declare variable DCHAR char(3);
declare variable IS_CONTINUE smallint;
declare variable IS_OK smallint;
BEGIN
    ROW_NUM = 0;

    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :V$LANG_CODE;

    SELECT FIRST 1 TYPE_ID, PARENT_TYPE_ID, FILTER_ID, LOGICAL_OPERATOR, ACTUAL_DATE, IS_ACTUAL_DATE_USED
    FROM FILTERS
    WHERE USER_ID = :I$USER_ID
      AND LEVEL_ID = :I$LEVEL_ID
      AND IS_ACTIVE = 1
    INTO :V$TYPE_ID, :V$PARENT_TYPE_ID, :V$FILTER_ID, :V$LOGICAL_OPERATOR, :V$ACTUAL_DATE, :V$IS_ACTUAL_DATE_USED;

    FOR SELECT DISTINCT L.LINK_ID, L.OBJ_ID, L.OBJ_TYPE_ID, L.PARENT_ID, L.PARENT_TYPE_ID, L.DATE_DEL, P.TAB_ID
        FROM FILTER_OBJECT_CHILDREN_GET(:I$OBJ_ID, NULL, :V$TYPE_ID, :I$LEVEL_ID) F
        INNER JOIN LINKS L ON L.LINK_ID = F.LINK_ID
        INNER JOIN PARENTS P ON P.CHILD_ID = L.OBJ_TYPE_ID AND P.TYPE_ID = L.PARENT_TYPE_ID AND P.IS_DEL = 0
        WHERE (:V$PARENT_TYPE_ID IS NULL OR :V$PARENT_TYPE_ID = L.PARENT_TYPE_ID)
          AND (:V$IS_ACTUAL_DATE_USED = 0 OR ((L.DATE_INS <= :V$ACTUAL_DATE) AND ((L.DATE_DEL IS NULL) OR (:V$ACTUAL_DATE <= L.DATE_DEL))))
        INTO :LINK_ID, :OBJ_ID, :TYPE_ID, :PARENT_ID, :PARENT_TYPE_ID, :V$DATE_DEL, :TAB_ID
    DO
    BEGIN
        IS_DEL = 0;
        IF (V$DATE_DEL IS NOT NULL) THEN IS_DEL = 1;

        SELECT FIRST 1 L.LINK_ID
        FROM LINKS L
        INNER JOIN LTYPES LT ON LT.TYPE_ID = L.PARENT_TYPE_ID AND LT.LEVEL_ID = :I$LEVEL_ID
        WHERE L.OBJ_ID = :PARENT_ID
          AND L.DATE_DEL IS NULL
        INTO :PARENT_LINK_ID;

        DELETE FROM FILTER_SESSION_VALS WHERE 1 = 1;

        IS_CONTINUE = 1;
        IS_OK = 1;

        FOR SELECT F.PARAM_ID, F.VAL, F.VAL_TYPE, F.OPERATOR, F.REGION, F.DISTRICT, F.TOWN, F.SETTLEMENT, F.STREET,
                   F.HOUSE, F.LITER, F.CORP, F.FLAT, F.POST_INDEX, P.TYPE_ID
            FROM FILTERVALS F
            INNER JOIN PARAMS P ON P.PARAM_ID = F.PARAM_ID
            WHERE FILTER_ID = :V$FILTER_ID
            ORDER BY FILTER_NUM
            INTO :V$PARAM_ID, :V$VAL, :VAL_TYPE, :OP, :V$REGION, :V$DISTRICT, :V$TOWN, :V$SETTLEMENT, :V$STREET,
                 :V$HOUSE, :V$LITER, :V$CORP, :V$FLAT, :V$POST_INDEX, :V$PARAM_OBJECT_TYPE_ID
        DO
        BEGIN
            C = 0;
            X = 0;
            IF (IS_CONTINUE = 1) THEN
            BEGIN
                IF (VAL_TYPE = 'ADDRESS') THEN
                BEGIN
                    SELECT C, OBJ_ID
                    FROM FILTER_APARAM_CHECK(:V$PARAM_ID, :OBJ_ID, :OP, :TYPE_ID, :V$PARAM_OBJECT_TYPE_ID, :V$REGION, :V$DISTRICT, :V$TOWN, :V$SETTLEMENT, :V$STREET, :V$HOUSE, :V$LITER, :V$CORP, :V$FLAT, :V$POST_INDEX)
                    INTO :C, :V$PARAM_OBJ_ID;
                END
                ELSE
                IF (VAL_TYPE = 'INTEGER') THEN
                BEGIN
                    SELECT C, OBJ_ID
                    FROM FILTER_IPARAM_CHECK(:V$PARAM_ID, :OBJ_ID, :OP, :TYPE_ID, :V$PARAM_OBJECT_TYPE_ID, :V$VAL)
                    INTO :C, :V$PARAM_OBJ_ID;
                END
                ELSE
                IF (VAL_TYPE = 'FLOAT') THEN
                BEGIN
                    SELECT C, OBJ_ID
                    FROM FILTER_FPARAM_CHECK(:V$PARAM_ID, :OBJ_ID, :OP, :TYPE_ID, :V$PARAM_OBJECT_TYPE_ID, :V$VAL)
                    INTO :C, :V$PARAM_OBJ_ID;
                END
                ELSE
                IF (VAL_TYPE = 'TIMESTAMP') THEN
                BEGIN
                    SELECT C, OBJ_ID
                    FROM FILTER_DTPARAM_CHECK(:V$PARAM_ID, :OBJ_ID, :OP, :TYPE_ID, :V$PARAM_OBJECT_TYPE_ID, :V$VAL)
                    INTO :C, :V$PARAM_OBJ_ID;
                END
                ELSE
                IF (VAL_TYPE = 'DATE') THEN
                BEGIN
                    SELECT C, OBJ_ID
                    FROM FILTER_DPARAM_CHECK(:V$PARAM_ID, :OBJ_ID, :OP, :TYPE_ID, :V$PARAM_OBJECT_TYPE_ID, :V$VAL)
                    INTO :C, :V$PARAM_OBJ_ID;
                END
                ELSE
                IF (VAL_TYPE = 'TIME') THEN
                BEGIN
                    SELECT C, OBJ_ID
                    FROM FILTER_TPARAM_CHECK(:V$PARAM_ID, :OBJ_ID, :OP, :TYPE_ID, :V$PARAM_OBJECT_TYPE_ID, :V$VAL)
                    INTO :C, :V$PARAM_OBJ_ID;
                END
                ELSE
                IF (VAL_TYPE = 'REFERENCE') THEN
                BEGIN
                    SELECT C, OBJ_ID
                    FROM FILTER_RPARAM_CHECK(:V$PARAM_ID, :OBJ_ID, :OP, :TYPE_ID, :V$PARAM_OBJECT_TYPE_ID, :V$VAL)
                    INTO :C, :V$PARAM_OBJ_ID;
                END
                ELSE
                IF (VAL_TYPE = 'LIST_VALUE') THEN
                BEGIN
                    SELECT C, OBJ_ID
                    FROM FILTER_LPARAM_CHECK(:V$PARAM_ID, :OBJ_ID, :OP, :TYPE_ID, :V$PARAM_OBJECT_TYPE_ID, :V$VAL)
                    INTO :C, :V$PARAM_OBJ_ID;
                END
                ELSE
                IF (VAL_TYPE = 'CALC_FUNCTION') THEN
                BEGIN
                    SELECT C, OBJ_ID
                    FROM FILTER_CPARAM_CHECK(:V$PARAM_ID, :OBJ_ID, :OP, :TYPE_ID, :V$PARAM_OBJECT_TYPE_ID, :V$VAL)
                    INTO :C, :V$PARAM_OBJ_ID;
                END
                ELSE
                IF (VAL_TYPE IN ('STRING_OR_LIST_VALUE_RO', 'STRING_OR_LIST_VALUE', 'STRING', 'SQL_QUERY', 'FUNCTION')) THEN
                BEGIN
                    SELECT C, OBJ_ID
                    FROM FILTER_SPARAM_CHECK(:V$PARAM_ID, :OBJ_ID, :OP, :TYPE_ID, :V$PARAM_OBJECT_TYPE_ID, :V$VAL)
                    INTO :C, :V$PARAM_OBJ_ID;
                END

                IF (V$LOGICAL_OPERATOR = 1) THEN /* AND */
                BEGIN
                    IF (C = 0) THEN
                    BEGIN
                        IS_CONTINUE = 0;
                        IS_OK = 0;
                    END
                    IF (C > 0) THEN
                    BEGIN
                        IS_CONTINUE = 1;
                        IS_OK = 1;
                    END
                END
                IF (V$LOGICAL_OPERATOR = 2) THEN /* OR */
                BEGIN
                    IF (C = 0) THEN
                    BEGIN
                        IS_CONTINUE = 1;
                        IS_OK = 0;
                    END
                    IF (C > 0) THEN
                    BEGIN
                        IS_CONTINUE = 0;
                        IS_OK = 1;
                    END
                END
            END

            /* in this place or move it into if */

            IF ((IS_OK = 1) AND
                (V$PARAM_OBJECT_TYPE_ID IS NOT NULL) AND
                (V$PARAM_OBJ_ID IS NOT NULL) AND
                (V$PARAM_OBJECT_TYPE_ID <> TYPE_ID)) THEN
            BEGIN
                INSERT INTO FILTER_SESSION_VALS (TYPE_ID, OBJ_ID)
                VALUES (:V$PARAM_OBJECT_TYPE_ID, :V$PARAM_OBJ_ID);
            END
        END

        IF (IS_OK = 1) THEN
        BEGIN
            CHILD_ID = NULL;
            CHILD_TYPE_ID = NULL;

            COL_NUM = 0;

            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:PARENT_ID, NULL, NULL, :I$USER_ID)
            INTO :PARENT_CAPTION;

            X = 0;

            FOR SELECT FF.PARAM_ID, P.PARAM_TYPE, LP.EDIT_TYPE, P.LIST_ID, P."DO_FUNC", P.HINT_RES_ID, P.EDIT_MASK,
                       T.TYPE_ID
                FROM FILTERFIELDSSETS FFS
                INNER JOIN FILTERFIELDS FF ON FF.FILTERFIELDSSET_ID = FFS.FILTERFIELDSSET_ID
                INNER JOIN PARAMS P ON P.PARAM_ID = FF.PARAM_ID AND P.TYPE_ID = FFS.TYPE_ID
                INNER JOIN LPARAMS LP ON LP.PARAM_ID = P.PARAM_ID AND LP.LEVEL_ID = :I$LEVEL_ID
                INNER JOIN TYPES T ON T.TYPE_ID = P.TYPE_ID
                LEFT OUTER JOIN TABS TB ON TB.TAB_ID = P.TAB_ID
                WHERE FFS.USER_ID = :I$USER_ID
                  AND FFS.LEVEL_ID = :I$LEVEL_ID
                  AND FFS.TYPE_ID = :TYPE_ID
                  AND FFS.IS_ACTIVE = 1
                ORDER BY T.SORT_ORDER, TB.TAB_NUM, P.GRID_ORDER
                INTO :PARAM_ID, :PARAM_TYPE, :EDIT_TYPE, :LIST_ID, :DO_FUNC, :V$HINT_RES_ID, :EDIT_MASK,
                     :CHILD_TYPE_ID
            DO
            BEGIN
                IF (CHILD_TYPE_ID = TYPE_ID) THEN
                BEGIN
                    CHILD_TYPE_ID = NULL;
                END
                LIST_EDIT_TYPE = -1;
                IF (PARAM_TYPE = 6) THEN
                /* LIST_VALUE */
                BEGIN
                    SELECT L.EDIT_TYPE
                    FROM LLISTS L
                    WHERE L.LEVEL_ID = :I$LEVEL_ID
                      AND L.LIST_ID = :LIST_ID
                      AND L.IS_DEL = 0
                    INTO :LIST_EDIT_TYPE;
                END

                LISTVAL_ID = NULL;
                REGION = NULL;
                DISTRICT = NULL;
                TOWN = NULL;
                SETTLEMENT = NULL;
                STREET = NULL;
                HOUSE = NULL;
                LITER = NULL;
                CORP = NULL;
                FLAT = NULL;
                POST_INDEX = NULL;

                IF (PARAM_TYPE = 17 OR PARAM_TYPE = 19) THEN
                BEGIN
                    SELECT VAL
                    FROM DO_FUNC(:OBJ_ID, :PARAM_ID, :DO_FUNC, NULL, :I$USER_ID, :PARENT_ID)
                    INTO :VAL;

                    IF ((:DO_FUNC = 2) AND
                        (:VAL IS NOT NULL) AND
                        (:VAL <> '')) THEN
                    BEGIN
                        N = VAL;
                        VAL = '';
                        Y = N / 360;
                        N = N - Y * 360;
                        M = N / 30;
                        N = N - M * 30;
                        D = N;

                        SELECT WORD FROM REPORT_WORDS WHERE ID = 22 INTO :LCHAR;
                        SELECT WORD FROM REPORT_WORDS WHERE ID = 23 INTO :GCHAR;
                        SELECT WORD FROM REPORT_WORDS WHERE ID = 24 INTO :MCHAR;
                        SELECT WORD FROM REPORT_WORDS WHERE ID = 25 INTO :DCHAR;

                        IF (Y > 0) THEN
                        BEGIN
                            VAL = Y || LCHAR;
                            IF (Y < 5) THEN
                            BEGIN
                                VAL = Y || GCHAR;
                            END
                        END
                        IF (M > 0) THEN
                        BEGIN
                            VAL = VAL || M || MCHAR;
                        END
                        IF (D > 0) THEN
                        BEGIN
                            VAL = VAL || D || DCHAR;
                        END
                    END
                END
                ELSE
                IF (PARAM_TYPE = 18) THEN
                BEGIN
                    SELECT VAL, REGION, DISTRICT, TOWN, SETTLEMENT, STREET, HOUSE, LITER, CORP, FLAT, POST_INDEX
                    FROM ADR_GET(:PARAM_ID, :OBJ_ID)
                    INTO :VAL, :REGION, :DISTRICT, :TOWN, :SETTLEMENT, :STREET, :HOUSE, :LITER, :CORP, :FLAT,
                         :POST_INDEX;
                END
                ELSE
                BEGIN
                    SELECT V, I
                    FROM VAL_GET(:OBJ_ID, :PARAM_ID, 0, :I$USER_ID)
                    INTO :VAL, :LISTVAL_ID;
                END

                SELECT CAPTION
                FROM PARAM_CAPTION_GET(:OBJ_ID, :PARAM_ID, :I$LEVEL_ID, :V$LANG_CODE, 1)
                INTO :PARAM_CAPTION;

                SELECT VAL
                FROM RES_GET(:V$HINT_RES_ID, :V$LANG_CODE)
                INTO :HINT_CAPTION;

                IF (COL_NUM > 0) THEN
                BEGIN
                    PARENT_CAPTION = NULL;
                END
                IF (VAL = '') THEN
                BEGIN
                    VAL = NULL;
                END
                SUSPEND;
                X = X + 1;
                COL_NUM = COL_NUM + 1;
            END

            FOR SELECT DISTINCT FF.PARAM_ID, P.PARAM_TYPE, LP.EDIT_TYPE, P.LIST_ID, P."DO_FUNC", P.HINT_RES_ID,
                                P.EDIT_MASK, P.TYPE_ID
                FROM FILTERFIELDSSETS FFS
                INNER JOIN FILTERFIELDS FF ON FF.FILTERFIELDSSET_ID = FFS.FILTERFIELDSSET_ID
                INNER JOIN PARAMS P ON P.PARAM_ID = FF.PARAM_ID
                INNER JOIN LPARAMS LP ON LP.PARAM_ID = P.PARAM_ID AND LP.LEVEL_ID = :I$LEVEL_ID
                INNER JOIN TYPES T ON T.TYPE_ID = P.TYPE_ID
                LEFT OUTER JOIN TABS TB ON TB.TAB_ID = P.TAB_ID
                WHERE FFS.USER_ID = :I$USER_ID
                  AND FFS.LEVEL_ID = :I$LEVEL_ID
                  AND FFS.TYPE_ID = :V$TYPE_ID
                  AND FFS.IS_ACTIVE = 1
                  AND P.TYPE_ID IN (SELECT DISTINCT P.TYPE_ID
                                    FROM FILTERFIELDSSETS FFS
                                    INNER JOIN FILTERFIELDS FF ON FF.FILTERFIELDSSET_ID = FFS.FILTERFIELDSSET_ID
                                    INNER JOIN PARAMS P ON P.PARAM_ID = FF.PARAM_ID
                                    INNER JOIN LPARAMS LP ON LP.PARAM_ID = P.PARAM_ID AND LP.LEVEL_ID = :I$LEVEL_ID
                                    WHERE FFS.USER_ID = :I$USER_ID
                                      AND FFS.LEVEL_ID = :I$LEVEL_ID
                                      AND FFS.TYPE_ID = :V$TYPE_ID
                                      AND FFS.IS_ACTIVE = 1
                                      AND P.TYPE_ID <> :TYPE_ID)
                ORDER BY T.SORT_ORDER, TB.TAB_NUM, P.GRID_ORDER
                INTO :PARAM_ID, :PARAM_TYPE, :EDIT_TYPE, :LIST_ID, :DO_FUNC, :V$HINT_RES_ID, :EDIT_MASK,
                     :CHILD_TYPE_ID
            DO
            BEGIN
                CHILD_ID = NULL;
                VAL = NULL;
                REGION = NULL;
                DISTRICT = NULL;
                TOWN = NULL;
                SETTLEMENT = NULL;
                STREET = NULL;
                HOUSE = NULL;
                LITER = NULL;
                CORP = NULL;
                FLAT = NULL;
                POST_INDEX = NULL;

                SELECT FIRST 1 L.OBJ_ID, FSV.OBJ_ID
                FROM LINKS L
                LEFT OUTER JOIN FILTER_SESSION_VALS FSV ON FSV.TYPE_ID = :CHILD_TYPE_ID
                WHERE L.PARENT_ID = :OBJ_ID
                  AND L.OBJ_TYPE_ID = :CHILD_TYPE_ID
                  AND L.DATE_DEL IS NULL
                ORDER BY FSV.OBJ_ID DESC
                INTO :CHILD_ID, :V$CHILD_ID;

                IF (V$CHILD_ID IS NOT NULL) THEN
                BEGIN
                    CHILD_ID = V$CHILD_ID;
                END

                SELECT CAPTION
                FROM PARAM_CAPTION_GET(:CHILD_ID, :PARAM_ID, :I$LEVEL_ID, :V$LANG_CODE, 1)
                INTO :PARAM_CAPTION;

                IF (CHILD_ID IS NOT NULL) THEN
                BEGIN
                    IF (PARAM_TYPE = 17 OR PARAM_TYPE = 19) THEN
                    BEGIN
                        SELECT VAL
                        FROM DO_FUNC(:CHILD_ID, :PARAM_ID, :DO_FUNC, NULL, :I$USER_ID, :OBJ_ID)
                        INTO :VAL;
                    END
                    ELSE
                    IF (PARAM_TYPE = 18) THEN
                    BEGIN
                        SELECT VAL, REGION, DISTRICT, TOWN, SETTLEMENT, STREET, HOUSE, LITER, CORP, FLAT, POST_INDEX
                        FROM ADR_GET(:PARAM_ID, :CHILD_ID)
                        INTO :VAL, :REGION, :DISTRICT, :TOWN, :SETTLEMENT, :STREET, :HOUSE, :LITER, :CORP, :FLAT,
                             :POST_INDEX;
                    END
                    ELSE
                    BEGIN
                        SELECT V, I
                        FROM VAL_GET(:CHILD_ID, :PARAM_ID, 0, :I$USER_ID)
                        INTO :VAL, :LISTVAL_ID;
                    END

                    SELECT CAPTION
                    FROM PARAM_CAPTION_GET(:CHILD_ID, :PARAM_ID, :I$LEVEL_ID, :V$LANG_CODE, 1)
                    INTO :PARAM_CAPTION;

                    IF (VAL = '') THEN
                    BEGIN
                        VAL = NULL;
                    END
                END
                SUSPEND;
                X = X + 1;
                COL_NUM = COL_NUM + 1;
            END

            IF (X = 0) THEN
            BEGIN
                SELECT COUNT(*)
                FROM PARAMS P
                INNER JOIN LPARAMS LP ON LP.PARAM_ID = P.PARAM_ID AND LP.LEVEL_ID = :I$LEVEL_ID AND LP.EDIT_TYPE > -1
                WHERE P.TYPE_ID = :V$TYPE_ID
                  AND P.IS_DEL = 0
                  AND P.IS_TREEVIEW = 1
                INTO :X;

                FOR SELECT P.PARAM_ID, P.PARAM_TYPE, LP.EDIT_TYPE, P.LIST_ID, P.HINT_RES_ID, P.DO_FUNC, P.EDIT_MASK
                    FROM PARAMS P
                    INNER JOIN LPARAMS LP ON LP.PARAM_ID = P.PARAM_ID AND LP.LEVEL_ID = :I$LEVEL_ID AND LP.EDIT_TYPE > -1
                    WHERE P.TYPE_ID = :V$TYPE_ID
                      AND P.IS_DEL = 0
                      AND (P.IS_TREEVIEW = 1 OR :X = 0)
                    ORDER BY P.GRID_ORDER
                    INTO :PARAM_ID, :PARAM_TYPE, :EDIT_TYPE, :LIST_ID, :V$HINT_RES_ID, :DO_FUNC, :EDIT_MASK
                DO
                BEGIN

                    LISTVAL_ID = NULL;
                    REGION = NULL;
                    DISTRICT = NULL;
                    TOWN = NULL;
                    SETTLEMENT = NULL;
                    STREET = NULL;
                    HOUSE = NULL;
                    LITER = NULL;
                    CORP = NULL;
                    FLAT = NULL;
                    POST_INDEX = NULL;

                    IF (PARAM_TYPE = 17 OR PARAM_TYPE = 19) THEN
                    BEGIN
                        SELECT VAL
                        FROM DO_FUNC(:OBJ_ID, :PARAM_ID, :DO_FUNC, NULL, :I$USER_ID, :PARENT_ID)
                        INTO :VAL;
                    END
                    ELSE
                    IF (PARAM_TYPE = 18) THEN
                    BEGIN
                        SELECT VAL, REGION, DISTRICT, TOWN, SETTLEMENT, STREET, HOUSE, LITER, CORP, FLAT, POST_INDEX
                        FROM ADR_GET(:PARAM_ID, :OBJ_ID)
                        INTO :VAL, :REGION, :DISTRICT, :TOWN, :SETTLEMENT, :STREET, :HOUSE, :LITER, :CORP, :FLAT,
                             :POST_INDEX;
                    END
                    ELSE
                    BEGIN
                        SELECT V, I
                        FROM VAL_GET(:OBJ_ID, :PARAM_ID, 0, :I$USER_ID)
                        INTO :VAL, :LISTVAL_ID;
                    END

                    SELECT CAPTION
                    FROM PARAM_CAPTION_GET(:OBJ_ID, :PARAM_ID, :I$LEVEL_ID, :V$LANG_CODE, 1)
                    INTO :PARAM_CAPTION;

                    SELECT VAL
                    FROM RES_GET(:V$HINT_RES_ID, :V$LANG_CODE)
                    INTO :HINT_CAPTION;

                    IF (COL_NUM > 0) THEN
                    BEGIN
                        PARENT_CAPTION = NULL;
                    END
                    IF (VAL = '') THEN
                    BEGIN
                        VAL = NULL;
                    END
                    SUSPEND;
                    COL_NUM = COL_NUM + 1;
                END
            END

            ROW_NUM = ROW_NUM + 1;
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FILTER_CPARAM_CHECK (
    I$PARAM_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$OP SMALLINT,
    I$TYPE_ID BIGINT,
    I$PARAM_OBJ_TYPE_ID BIGINT,
    I$VAL VARCHAR(4000))
RETURNS (
    C INTEGER,
    OBJ_ID BIGINT)
AS
DECLARE VARIABLE V$VAL VARCHAR(4000);
DECLARE VARIABLE V$SORT_ORDER DOUBLE PRECISION;
DECLARE VARIABLE V$SORT_ORDER2 DOUBLE PRECISION;
DECLARE VARIABLE V$IS_NUMBER SMALLINT;
BEGIN
    C = 0;
    FOR SELECT VAL, SORT_ORDER, :I$OBJ_ID
        FROM DO_FUNC(:I$OBJ_ID, :I$PARAM_ID)
        WHERE :I$PARAM_OBJ_TYPE_ID = :I$TYPE_ID
          AND :C = 0

        UNION ALL

        SELECT VAL, SORT_ORDER, L.OBJ_ID
        FROM LINKS L
        JOIN DO_FUNC(L.OBJ_ID, :I$PARAM_ID) ON 1 = 1
        WHERE L.PARENT_ID = :I$OBJ_ID
          AND L.DATE_DEL IS NULL
          AND L.OBJ_TYPE_ID = :I$PARAM_OBJ_TYPE_ID
          AND :I$PARAM_OBJ_TYPE_ID <> :I$TYPE_ID
          AND :C = 0
        INTO :V$VAL, :V$SORT_ORDER, :OBJ_ID
    DO
    BEGIN
        V$IS_NUMBER = 1;
        BEGIN
            V$SORT_ORDER2 = CAST(:I$VAL AS DOUBLE PRECISION);

            WHEN ANY DO
            BEGIN
                V$SORT_ORDER2 = 0;
                V$IS_NUMBER = 0;
            END
        END

        IF (V$IS_NUMBER = 1) THEN
        BEGIN
            IF (I$OP = 1) THEN
            BEGIN /* = */
                IF (:V$SORT_ORDER = V$SORT_ORDER2) THEN
                BEGIN
                    C = 1;
                END
            END
            ELSE
            IF (I$OP = 2) THEN
            BEGIN /* <> */
                IF (:V$SORT_ORDER <> V$SORT_ORDER2) THEN
                BEGIN
                    C = 1;
                END
            END
            ELSE
            IF (I$OP = 3) THEN
            BEGIN /* > */
                IF (:V$SORT_ORDER > V$SORT_ORDER2) THEN
                BEGIN
                    C = 1;
                END
            END
            ELSE
            IF (I$OP = 4) THEN
            BEGIN /* < */
                IF (:V$SORT_ORDER < V$SORT_ORDER2) THEN
                BEGIN
                    C = 1;
                END
            END
            ELSE
            IF (I$OP = 5) THEN
            BEGIN /* >= */
                IF (:V$SORT_ORDER >= V$SORT_ORDER2) THEN
                BEGIN
                    C = 1;
                END
            END
            ELSE
            IF (I$OP = 6) THEN
            BEGIN /* <= */
                IF (:V$SORT_ORDER <= V$SORT_ORDER2) THEN
                BEGIN
                    C = 1;
                END
            END
        END
        ELSE
        BEGIN
            IF (I$OP = 1) THEN
            BEGIN /* = */
                IF (:V$VAL = I$VAL) THEN
                BEGIN
                    C = 1;
                END
            END
            ELSE
            IF (I$OP = 2) THEN
            BEGIN /* <> */
                IF (:V$VAL <> I$VAL) THEN
                BEGIN
                    C = 1;
                END
            END
            ELSE
            IF (I$OP = 7) THEN
            BEGIN /* NULL */
                IF (:V$VAL = '') THEN
                BEGIN
                    C = 1;
                END
            END
            ELSE
            IF (I$OP = 8) THEN
            BEGIN /* NOT NULL */
                IF (:V$VAL <> '') THEN
                BEGIN
                    C = 1;
                END
            END
        END
    END

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FILTER_DEL (
    I$FILTER_ID BIGINT,
    I$USER_ID BIGINT,
    I$LEVEL_ID BIGINT)
AS
BEGIN
    DELETE
    FROM FILTERS
    WHERE FILTER_ID = :I$FILTER_ID
    AND USER_ID = :I$USER_ID
    AND LEVEL_ID = :I$LEVEL_ID
    AND IS_LAST = 0;
    UPDATE FILTERS
    SET IS_ACTIVE = 1
    WHERE USER_ID = :I$USER_ID
    AND LEVEL_ID = :I$LEVEL_ID
    AND IS_LAST = 1;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FILTER_DPARAM_CHECK (
    I$PARAM_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$OP SMALLINT,
    I$TYPE_ID BIGINT,
    I$PARAM_OBJ_TYPE_ID BIGINT,
    I$VAL VARCHAR(4000))
RETURNS (
    C INTEGER,
    OBJ_ID BIGINT)
AS
BEGIN
    C = 0;
    IF (I$OP = 1) THEN
    BEGIN /* = */
        IF (I$PARAM_OBJ_TYPE_ID = I$TYPE_ID) THEN
        BEGIN
            SELECT FIRST 1
                   1,
                   OBJ_ID
            FROM VALD
            WHERE PARAM_ID = :I$PARAM_ID
            AND OBJ_ID = :I$OBJ_ID
            AND IS_DEL = 0
            AND VAL = CAST(:I$VAL AS DATE)
            INTO :C,
                 :OBJ_ID;
        END
        ELSE
        BEGIN
            SELECT FIRST 1
                   1,
                   L.OBJ_ID
            FROM LINKS L
            INNER JOIN VALD V
            ON V.PARAM_ID = :I$PARAM_ID
            AND V.OBJ_ID = L.OBJ_ID
            AND V.IS_DEL = 0
            AND V.VAL = CAST(:I$VAL AS DATE)
            WHERE L.PARENT_ID = :I$OBJ_ID
            AND L.DATE_DEL IS NULL
            AND L.OBJ_TYPE_ID = :I$PARAM_OBJ_TYPE_ID
            INTO :C,
                 :OBJ_ID;
        END
    END
    ELSE IF (I$OP = 2) THEN
    BEGIN /* <> */
        IF (I$PARAM_OBJ_TYPE_ID = I$TYPE_ID) THEN
        BEGIN
            SELECT FIRST 1
                   1,
                   OBJ_ID
            FROM VALD
            WHERE PARAM_ID = :I$PARAM_ID
            AND OBJ_ID = :I$OBJ_ID
            AND IS_DEL = 0
            AND VAL <> CAST(:I$VAL AS DATE)
            INTO :C,
                 :OBJ_ID;
        END
        ELSE
        BEGIN
            SELECT FIRST 1
                   1,
                   L.OBJ_ID
            FROM LINKS L
            INNER JOIN VALD V
            ON V.PARAM_ID = :I$PARAM_ID
            AND V.OBJ_ID = L.OBJ_ID
            AND V.IS_DEL = 0
            AND V.VAL <> CAST(:I$VAL AS DATE)
            WHERE L.PARENT_ID = :I$OBJ_ID
            AND L.DATE_DEL IS NULL
            AND L.OBJ_TYPE_ID = :I$PARAM_OBJ_TYPE_ID
            INTO :C,
                 :OBJ_ID;
        END
    END
    ELSE IF (I$OP = 3) THEN
    BEGIN /* > */
        IF (I$PARAM_OBJ_TYPE_ID = I$TYPE_ID) THEN
        BEGIN
            SELECT FIRST 1
                   1,
                   OBJ_ID
            FROM VALD
            WHERE PARAM_ID = :I$PARAM_ID
            AND OBJ_ID = :I$OBJ_ID
            AND IS_DEL = 0
            AND VAL > CAST(:I$VAL AS DATE)
            INTO :C,
                 :OBJ_ID;
        END
        ELSE
        BEGIN
            SELECT FIRST 1
                   1,
                   L.OBJ_ID
            FROM LINKS L
            INNER JOIN VALD V
            ON V.PARAM_ID = :I$PARAM_ID
            AND V.OBJ_ID = L.OBJ_ID
            AND V.IS_DEL = 0
            AND V.VAL > CAST(:I$VAL AS DATE)
            WHERE L.PARENT_ID = :I$OBJ_ID
            AND L.DATE_DEL IS NULL
            AND L.OBJ_TYPE_ID = :I$PARAM_OBJ_TYPE_ID
            INTO :C,
                 :OBJ_ID;
        END
    END
    ELSE IF (I$OP = 4) THEN
    BEGIN /* < */
        IF (I$PARAM_OBJ_TYPE_ID = I$TYPE_ID) THEN
        BEGIN
            SELECT FIRST 1
                   1,
                   OBJ_ID
            FROM VALD
            WHERE PARAM_ID = :I$PARAM_ID
            AND OBJ_ID = :I$OBJ_ID
            AND IS_DEL = 0
            AND VAL < CAST(:I$VAL AS DATE)
            INTO :C,
                 :OBJ_ID;
        END
        ELSE
        BEGIN
            SELECT FIRST 1
                   1,
                   L.OBJ_ID
            FROM LINKS L
            INNER JOIN VALD V
            ON V.PARAM_ID = :I$PARAM_ID
            AND V.OBJ_ID = L.OBJ_ID
            AND V.IS_DEL = 0
            AND V.VAL < CAST(:I$VAL AS DATE)
            WHERE L.PARENT_ID = :I$OBJ_ID
            AND L.DATE_DEL IS NULL
            AND L.OBJ_TYPE_ID = :I$PARAM_OBJ_TYPE_ID
            INTO :C,
                 :OBJ_ID;
        END
    END
    ELSE IF (I$OP = 5) THEN
    BEGIN /* >= */
        IF (I$PARAM_OBJ_TYPE_ID = I$TYPE_ID) THEN
        BEGIN
            SELECT FIRST 1
                   1,
                   OBJ_ID
            FROM VALD
            WHERE PARAM_ID = :I$PARAM_ID
            AND OBJ_ID = :I$OBJ_ID
            AND IS_DEL = 0
            AND VAL >= CAST(:I$VAL AS DATE)
            INTO :C,
                 :OBJ_ID;
        END
        ELSE
        BEGIN
            SELECT FIRST 1
                   1,
                   L.OBJ_ID
            FROM LINKS L
            INNER JOIN VALD V
            ON V.PARAM_ID = :I$PARAM_ID
            AND V.OBJ_ID = L.OBJ_ID
            AND V.IS_DEL = 0
            AND V.VAL >= CAST(:I$VAL AS DATE)
            WHERE L.PARENT_ID = :I$OBJ_ID
            AND L.DATE_DEL IS NULL
            AND L.OBJ_TYPE_ID = :I$PARAM_OBJ_TYPE_ID
            INTO :C,
                 :OBJ_ID;
        END
    END
    ELSE IF (I$OP = 6) THEN
    BEGIN /* <= */
        IF (I$PARAM_OBJ_TYPE_ID = I$TYPE_ID) THEN
        BEGIN
            SELECT FIRST 1
                   1,
                   OBJ_ID
            FROM VALD
            WHERE PARAM_ID = :I$PARAM_ID
            AND OBJ_ID = :I$OBJ_ID
            AND IS_DEL = 0
            AND VAL <= CAST(:I$VAL AS DATE)
            INTO :C,
                 :OBJ_ID;
        END
        ELSE
        BEGIN
            SELECT FIRST 1
                   1,
                   L.OBJ_ID
            FROM LINKS L
            INNER JOIN VALD V
            ON V.PARAM_ID = :I$PARAM_ID
            AND V.OBJ_ID = L.OBJ_ID
            AND V.IS_DEL = 0
            AND V.VAL <= CAST(:I$VAL AS DATE)
            WHERE L.PARENT_ID = :I$OBJ_ID
            AND L.DATE_DEL IS NULL
            AND L.OBJ_TYPE_ID = :I$PARAM_OBJ_TYPE_ID
            INTO :C,
                 :OBJ_ID;
        END
    END
    ELSE IF (I$OP = 7) THEN
    BEGIN /* NULL */
        IF (I$PARAM_OBJ_TYPE_ID = I$TYPE_ID) THEN
        BEGIN
            SELECT FIRST 1
                   1,
                   OBJ_ID
            FROM VALD
            WHERE PARAM_ID = :I$PARAM_ID
            AND OBJ_ID = :I$OBJ_ID
            AND IS_DEL = 0
            INTO :C,
                 :OBJ_ID;
        END
        ELSE
        BEGIN
            SELECT FIRST 1
                   1,
                   L.OBJ_ID
            FROM LINKS L
            INNER JOIN VALD V
            ON V.PARAM_ID = :I$PARAM_ID
            AND V.OBJ_ID = L.OBJ_ID
            AND V.IS_DEL = 0
            WHERE L.PARENT_ID = :I$OBJ_ID
            AND L.DATE_DEL IS NULL
            AND L.OBJ_TYPE_ID = :I$PARAM_OBJ_TYPE_ID
            INTO :C,
                 :OBJ_ID;
        END
        
        IF (C = 1) THEN
        BEGIN
            C = 0;
        END
        ELSE
        BEGIN
            C = 1;
        END
    END
    ELSE IF (I$OP = 8) THEN
    BEGIN /* NOT NULL */
        IF (I$PARAM_OBJ_TYPE_ID = I$TYPE_ID) THEN
        BEGIN
            SELECT FIRST 1
                   1,
                   OBJ_ID
            FROM VALD
            WHERE PARAM_ID = :I$PARAM_ID
            AND OBJ_ID = :I$OBJ_ID
            AND IS_DEL = 0
            INTO :C,
                 :OBJ_ID;
        END
        ELSE
        BEGIN
            SELECT FIRST 1
                   1,
                   L.OBJ_ID
            FROM LINKS L
            INNER JOIN VALD V
            ON V.PARAM_ID = :I$PARAM_ID
            AND V.OBJ_ID = L.OBJ_ID
            AND V.IS_DEL = 0
            WHERE L.PARENT_ID = :I$OBJ_ID
            AND L.DATE_DEL IS NULL
            AND L.OBJ_TYPE_ID = :I$PARAM_OBJ_TYPE_ID
            INTO :C,
                 :OBJ_ID;
        END
    END
    ELSE IF (I$OP = 9) THEN
    BEGIN /* ~ */
        IF (I$PARAM_OBJ_TYPE_ID = I$TYPE_ID) THEN
        BEGIN
            SELECT FIRST 1
                   1,
                   OBJ_ID
            FROM VALD
            WHERE PARAM_ID = :I$PARAM_ID
            AND OBJ_ID = :I$OBJ_ID
            AND IS_DEL = 0
            AND VAL LIKE :I$VAL
            INTO :C,
                 :OBJ_ID;
        END
        ELSE
        BEGIN
            SELECT FIRST 1
                   1,
                   L.OBJ_ID
            FROM LINKS L
            INNER JOIN VALD V
            ON V.PARAM_ID = :I$PARAM_ID
            AND V.OBJ_ID = L.OBJ_ID
            AND V.IS_DEL = 0
            AND V.VAL LIKE :I$VAL
            WHERE L.PARENT_ID = :I$OBJ_ID
            AND L.DATE_DEL IS NULL
            AND L.OBJ_TYPE_ID = :I$PARAM_OBJ_TYPE_ID
            INTO :C,
                 :OBJ_ID;
        END
    END
    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FILTER_DTPARAM_CHECK (
    I$PARAM_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$OP SMALLINT,
    I$TYPE_ID BIGINT,
    I$PARAM_OBJ_TYPE_ID BIGINT,
    I$VAL TIMESTAMP)
RETURNS (
    C INTEGER,
    OBJ_ID BIGINT)
AS
BEGIN
    C = 0;
    IF (I$OP = 1) THEN
    BEGIN /* = */
        IF (I$PARAM_OBJ_TYPE_ID = I$TYPE_ID) THEN
        BEGIN
            SELECT FIRST 1
                   1,
                   OBJ_ID
            FROM VALDT
            WHERE PARAM_ID = :I$PARAM_ID
            AND OBJ_ID = :I$OBJ_ID
            AND IS_DEL = 0
            AND VAL = :I$VAL
            INTO :C,
                 :OBJ_ID;
        END
        ELSE
        BEGIN
            SELECT FIRST 1
                   1,
                   L.OBJ_ID
            FROM LINKS L
            INNER JOIN VALDT V
            ON V.PARAM_ID = :I$PARAM_ID
            AND V.OBJ_ID = L.OBJ_ID
            AND V.IS_DEL = 0
            AND V.VAL = :I$VAL
            WHERE L.PARENT_ID = :I$OBJ_ID
            AND L.DATE_DEL IS NULL
            AND L.OBJ_TYPE_ID = :I$PARAM_OBJ_TYPE_ID
            INTO :C,
                 :OBJ_ID;
        END
    END
    ELSE IF (I$OP = 2) THEN
    BEGIN /* <> */
        IF (I$PARAM_OBJ_TYPE_ID = I$TYPE_ID) THEN
        BEGIN
            SELECT FIRST 1
                   1,
                   OBJ_ID
            FROM VALDT
            WHERE PARAM_ID = :I$PARAM_ID
            AND OBJ_ID = :I$OBJ_ID
            AND IS_DEL = 0
            AND VAL <> :I$VAL
            INTO :C,
                 :OBJ_ID;
        END
        ELSE
        BEGIN
            SELECT FIRST 1
                   1,
                   L.OBJ_ID
            FROM LINKS L
            INNER JOIN VALDT V
            ON V.PARAM_ID = :I$PARAM_ID
            AND V.OBJ_ID = L.OBJ_ID
            AND V.IS_DEL = 0
            AND V.VAL <> :I$VAL
            WHERE L.PARENT_ID = :I$OBJ_ID
            AND L.DATE_DEL IS NULL
            AND L.OBJ_TYPE_ID = :I$PARAM_OBJ_TYPE_ID
            INTO :C,
                 :OBJ_ID;
        END
    END
    ELSE IF (I$OP = 3) THEN
    BEGIN /* > */
        IF (I$PARAM_OBJ_TYPE_ID = I$TYPE_ID) THEN
        BEGIN
            SELECT FIRST 1
                   1,
                   OBJ_ID
            FROM VALDT
            WHERE PARAM_ID = :I$PARAM_ID
            AND OBJ_ID = :I$OBJ_ID
            AND IS_DEL = 0
            AND VAL > :I$VAL
            INTO :C,
                 :OBJ_ID;
        END
        ELSE
        BEGIN
            SELECT FIRST 1
                   1,
                   L.OBJ_ID
            FROM LINKS L
            INNER JOIN VALDT V
            ON V.PARAM_ID = :I$PARAM_ID
            AND V.OBJ_ID = L.OBJ_ID
            AND V.IS_DEL = 0
            AND V.VAL > :I$VAL
            WHERE L.PARENT_ID = :I$OBJ_ID
            AND L.DATE_DEL IS NULL
            AND L.OBJ_TYPE_ID = :I$PARAM_OBJ_TYPE_ID
            INTO :C,
                 :OBJ_ID;
        END
    END
    ELSE IF (I$OP = 4) THEN
    BEGIN /* < */
        IF (I$PARAM_OBJ_TYPE_ID = I$TYPE_ID) THEN
        BEGIN
            SELECT FIRST 1
                   1,
                   OBJ_ID
            FROM VALDT
            WHERE PARAM_ID = :I$PARAM_ID
            AND OBJ_ID = :I$OBJ_ID
            AND IS_DEL = 0
            AND VAL < :I$VAL
            INTO :C,
                 :OBJ_ID;
        END
        ELSE
        BEGIN
            SELECT FIRST 1
                   1,
                   L.OBJ_ID
            FROM LINKS L
            INNER JOIN VALDT V
            ON V.PARAM_ID = :I$PARAM_ID
            AND V.OBJ_ID = L.OBJ_ID
            AND V.IS_DEL = 0
            AND V.VAL < :I$VAL
            WHERE L.PARENT_ID = :I$OBJ_ID
            AND L.DATE_DEL IS NULL
            AND L.OBJ_TYPE_ID = :I$PARAM_OBJ_TYPE_ID
            INTO :C,
                 :OBJ_ID;
        END
    END
    ELSE IF (I$OP = 5) THEN
    BEGIN /* >= */
        IF (I$PARAM_OBJ_TYPE_ID = I$TYPE_ID) THEN
        BEGIN
            SELECT FIRST 1
                   1,
                   OBJ_ID
            FROM VALDT
            WHERE PARAM_ID = :I$PARAM_ID
            AND OBJ_ID = :I$OBJ_ID
            AND IS_DEL = 0
            AND VAL >= :I$VAL
            INTO :C,
                 :OBJ_ID;
        END
        ELSE
        BEGIN
            SELECT FIRST 1
                   1,
                   L.OBJ_ID
            FROM LINKS L
            INNER JOIN VALDT V
            ON V.PARAM_ID = :I$PARAM_ID
            AND V.OBJ_ID = L.OBJ_ID
            AND V.IS_DEL = 0
            AND V.VAL >= :I$VAL
            WHERE L.PARENT_ID = :I$OBJ_ID
            AND L.DATE_DEL IS NULL
            AND L.OBJ_TYPE_ID = :I$PARAM_OBJ_TYPE_ID
            INTO :C,
                 :OBJ_ID;
        END
    END
    ELSE IF (I$OP = 6) THEN
    BEGIN /* <= */
        IF (I$PARAM_OBJ_TYPE_ID = I$TYPE_ID) THEN
        BEGIN
            SELECT FIRST 1
                   1,
                   OBJ_ID
            FROM VALDT
            WHERE PARAM_ID = :I$PARAM_ID
            AND OBJ_ID = :I$OBJ_ID
            AND IS_DEL = 0
            AND VAL <= :I$VAL
            INTO :C,
                 :OBJ_ID;
        END
        ELSE
        BEGIN
            SELECT FIRST 1
                   1,
                   L.OBJ_ID
            FROM LINKS L
            INNER JOIN VALDT V
            ON V.PARAM_ID = :I$PARAM_ID
            AND V.OBJ_ID = L.OBJ_ID
            AND V.IS_DEL = 0
            AND V.VAL <= :I$VAL
            WHERE L.PARENT_ID = :I$OBJ_ID
            AND L.DATE_DEL IS NULL
            AND L.OBJ_TYPE_ID = :I$PARAM_OBJ_TYPE_ID
            INTO :C,
                 :OBJ_ID;
        END
    END
    ELSE IF (I$OP = 7) THEN
    BEGIN /* NULL */
        IF (I$PARAM_OBJ_TYPE_ID = I$TYPE_ID) THEN
        BEGIN
            SELECT FIRST 1
                   1,
                   OBJ_ID
            FROM VALDT
            WHERE PARAM_ID = :I$PARAM_ID
            AND OBJ_ID = :I$OBJ_ID
            AND IS_DEL = 0
            INTO :C,
                 :OBJ_ID;
        END
        ELSE
        BEGIN
            SELECT FIRST 1
                   1,
                   L.OBJ_ID
            FROM LINKS L
            INNER JOIN VALDT V
            ON V.PARAM_ID = :I$PARAM_ID
            AND V.OBJ_ID = L.OBJ_ID
            AND V.IS_DEL = 0
            WHERE L.PARENT_ID = :I$OBJ_ID
            AND L.DATE_DEL IS NULL
            AND L.OBJ_TYPE_ID = :I$PARAM_OBJ_TYPE_ID
            INTO :C,
                 :OBJ_ID;
        END
        
        IF (C = 1) THEN
        BEGIN
            C = 0;
        END
        ELSE
        BEGIN
            C = 1;
        END
    END
    ELSE IF (I$OP = 8) THEN
    BEGIN /* NOT NULL */
        IF (I$PARAM_OBJ_TYPE_ID = I$TYPE_ID) THEN
        BEGIN
            SELECT FIRST 1
                   1,
                   OBJ_ID
            FROM VALDT
            WHERE PARAM_ID = :I$PARAM_ID
            AND OBJ_ID = :I$OBJ_ID
            AND IS_DEL = 0
            INTO :C,
                 :OBJ_ID;
        END
        ELSE
        BEGIN
            SELECT FIRST 1
                   1,
                   L.OBJ_ID
            FROM LINKS L
            INNER JOIN VALDT V
            ON V.PARAM_ID = :I$PARAM_ID
            AND V.OBJ_ID = L.OBJ_ID
            AND V.IS_DEL = 0
            WHERE L.PARENT_ID = :I$OBJ_ID
            AND L.DATE_DEL IS NULL
            AND L.OBJ_TYPE_ID = :I$PARAM_OBJ_TYPE_ID
            INTO :C,
                 :OBJ_ID;
        END
    END
    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FILTER_FPARAM_CHECK (
    I$PARAM_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$OP SMALLINT,
    I$TYPE_ID BIGINT,
    I$PARAM_OBJ_TYPE_ID BIGINT,
    I$VAL DOUBLE PRECISION)
RETURNS (
    C INTEGER,
    OBJ_ID BIGINT)
AS
BEGIN
    C = 0;
    IF (I$OP = 1) THEN
    BEGIN /* = */
        IF (I$PARAM_OBJ_TYPE_ID = I$TYPE_ID) THEN
        BEGIN
            SELECT FIRST 1
                   1,
                   OBJ_ID
            FROM VALF
            WHERE PARAM_ID = :I$PARAM_ID
            AND OBJ_ID = :I$OBJ_ID
            AND IS_DEL = 0
            AND VAL = :I$VAL
            INTO :C,
                 :OBJ_ID;
        END
        ELSE
        BEGIN
            SELECT FIRST 1
                   1,
                   L.OBJ_ID
            FROM LINKS L
            INNER JOIN VALF V
            ON V.PARAM_ID = :I$PARAM_ID
            AND V.OBJ_ID = L.OBJ_ID
            AND V.IS_DEL = 0
            AND V.VAL = :I$VAL
            WHERE L.PARENT_ID = :I$OBJ_ID
            AND L.DATE_DEL IS NULL
            AND L.OBJ_TYPE_ID = :I$PARAM_OBJ_TYPE_ID
            INTO :C,
                 :OBJ_ID;
        END
    END
    ELSE IF (I$OP = 2) THEN
    BEGIN /* <> */
        IF (I$PARAM_OBJ_TYPE_ID = I$TYPE_ID) THEN
        BEGIN
            SELECT FIRST 1
                   1,
                   OBJ_ID
            FROM VALF
            WHERE PARAM_ID = :I$PARAM_ID
            AND OBJ_ID = :I$OBJ_ID
            AND IS_DEL = 0
            AND VAL <> :I$VAL
            INTO :C,
                 :OBJ_ID;
        END
        ELSE
        BEGIN
            SELECT FIRST 1
                   1,
                   L.OBJ_ID
            FROM LINKS L
            INNER JOIN VALF V
            ON V.PARAM_ID = :I$PARAM_ID
            AND V.OBJ_ID = L.OBJ_ID
            AND V.IS_DEL = 0
            AND V.VAL <> :I$VAL
            WHERE L.PARENT_ID = :I$OBJ_ID
            AND L.DATE_DEL IS NULL
            AND L.OBJ_TYPE_ID = :I$PARAM_OBJ_TYPE_ID
            INTO :C,
                 :OBJ_ID;
        END
    END
    ELSE IF (I$OP = 3) THEN
    BEGIN /* > */
        IF (I$PARAM_OBJ_TYPE_ID = I$TYPE_ID) THEN
        BEGIN
            SELECT FIRST 1
                   1,
                   OBJ_ID
            FROM VALF
            WHERE PARAM_ID = :I$PARAM_ID
            AND OBJ_ID = :I$OBJ_ID
            AND IS_DEL = 0
            AND VAL > :I$VAL
            INTO :C,
                 :OBJ_ID;
        END
        ELSE
        BEGIN
            SELECT FIRST 1
                   1,
                   L.OBJ_ID
            FROM LINKS L
            INNER JOIN VALF V
            ON V.PARAM_ID = :I$PARAM_ID
            AND V.OBJ_ID = L.OBJ_ID
            AND V.IS_DEL = 0
            AND V.VAL > :I$VAL
            WHERE L.PARENT_ID = :I$OBJ_ID
            AND L.DATE_DEL IS NULL
            AND L.OBJ_TYPE_ID = :I$PARAM_OBJ_TYPE_ID
            INTO :C,
                 :OBJ_ID;
        END
    END
    ELSE IF (I$OP = 4) THEN
    BEGIN /* < */
        IF (I$PARAM_OBJ_TYPE_ID = I$TYPE_ID) THEN
        BEGIN
            SELECT FIRST 1
                   1,
                   OBJ_ID
            FROM VALF
            WHERE PARAM_ID = :I$PARAM_ID
            AND OBJ_ID = :I$OBJ_ID
            AND IS_DEL = 0
            AND VAL < :I$VAL
            INTO :C,
                 :OBJ_ID;
        END
        ELSE
        BEGIN
            SELECT FIRST 1
                   1,
                   L.OBJ_ID
            FROM LINKS L
            INNER JOIN VALF V
            ON V.PARAM_ID = :I$PARAM_ID
            AND V.OBJ_ID = L.OBJ_ID
            AND V.IS_DEL = 0
            AND V.VAL < :I$VAL
            WHERE L.PARENT_ID = :I$OBJ_ID
            AND L.DATE_DEL IS NULL
            AND L.OBJ_TYPE_ID = :I$PARAM_OBJ_TYPE_ID
            INTO :C,
                 :OBJ_ID;
        END
    END
    ELSE IF (I$OP = 5) THEN
    BEGIN /* >= */
        IF (I$PARAM_OBJ_TYPE_ID = I$TYPE_ID) THEN
        BEGIN
            SELECT FIRST 1
                   1,
                   OBJ_ID
            FROM VALF
            WHERE PARAM_ID = :I$PARAM_ID
            AND OBJ_ID = :I$OBJ_ID
            AND IS_DEL = 0
            AND VAL >= :I$VAL
            INTO :C,
                 :OBJ_ID;
        END
        ELSE
        BEGIN
            SELECT FIRST 1
                   1,
                   L.OBJ_ID
            FROM LINKS L
            INNER JOIN VALF V
            ON V.PARAM_ID = :I$PARAM_ID
            AND V.OBJ_ID = L.OBJ_ID
            AND V.IS_DEL = 0
            AND V.VAL >= :I$VAL
            WHERE L.PARENT_ID = :I$OBJ_ID
            AND L.DATE_DEL IS NULL
            AND L.OBJ_TYPE_ID = :I$PARAM_OBJ_TYPE_ID
            INTO :C,
                 :OBJ_ID;
        END
    END
    ELSE IF (I$OP = 6) THEN
    BEGIN /* <= */
        IF (I$PARAM_OBJ_TYPE_ID = I$TYPE_ID) THEN
        BEGIN
            SELECT FIRST 1
                   1,
                   OBJ_ID
            FROM VALF
            WHERE PARAM_ID = :I$PARAM_ID
            AND OBJ_ID = :I$OBJ_ID
            AND IS_DEL = 0
            AND VAL <= :I$VAL
            INTO :C,
                 :OBJ_ID;
        END
        ELSE
        BEGIN
            SELECT FIRST 1
                   1,
                   L.OBJ_ID
            FROM LINKS L
            INNER JOIN VALF V
            ON V.PARAM_ID = :I$PARAM_ID
            AND V.OBJ_ID = L.OBJ_ID
            AND V.IS_DEL = 0
            AND V.VAL <= :I$VAL
            WHERE L.PARENT_ID = :I$OBJ_ID
            AND L.DATE_DEL IS NULL
            AND L.OBJ_TYPE_ID = :I$PARAM_OBJ_TYPE_ID
            INTO :C,
                 :OBJ_ID;
        END
    END
    ELSE IF (I$OP = 7) THEN
    BEGIN /* NULL */
        IF (I$PARAM_OBJ_TYPE_ID = I$TYPE_ID) THEN
        BEGIN
            SELECT FIRST 1
                   1,
                   OBJ_ID
            FROM VALF
            WHERE PARAM_ID = :I$PARAM_ID
            AND OBJ_ID = :I$OBJ_ID
            AND IS_DEL = 0
            INTO :C,
                 :OBJ_ID;
        END
        ELSE
        BEGIN
            SELECT FIRST 1
                   1,
                   L.OBJ_ID
            FROM LINKS L
            INNER JOIN VALF V
            ON V.PARAM_ID = :I$PARAM_ID
            AND V.OBJ_ID = L.OBJ_ID
            AND V.IS_DEL = 0
            WHERE L.PARENT_ID = :I$OBJ_ID
            AND L.DATE_DEL IS NULL
            AND L.OBJ_TYPE_ID = :I$PARAM_OBJ_TYPE_ID
            INTO :C,
                 :OBJ_ID;
        END
        
        IF (C = 1) THEN
        BEGIN
            C = 0;
        END
        ELSE
        BEGIN
            C = 1;
        END
    END
    ELSE IF (I$OP = 8) THEN
    BEGIN /* NOT NULL */
        IF (I$PARAM_OBJ_TYPE_ID = I$TYPE_ID) THEN
        BEGIN
            SELECT FIRST 1
                   1,
                   OBJ_ID
            FROM VALF
            WHERE PARAM_ID = :I$PARAM_ID
            AND OBJ_ID = :I$OBJ_ID
            AND IS_DEL = 0
            INTO :C,
                 :OBJ_ID;
        END
        ELSE
        BEGIN
            SELECT FIRST 1
                   1,
                   L.OBJ_ID
            FROM LINKS L
            INNER JOIN VALF V
            ON V.PARAM_ID = :I$PARAM_ID
            AND V.OBJ_ID = L.OBJ_ID
            AND V.IS_DEL = 0
            WHERE L.PARENT_ID = :I$OBJ_ID
            AND L.DATE_DEL IS NULL
            AND L.OBJ_TYPE_ID = :I$PARAM_OBJ_TYPE_ID
            INTO :C,
                 :OBJ_ID;
        END
    END
    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FILTER_GET (
    I$FILTER_ID BIGINT,
    I$USER_ID BIGINT,
    I$LEVEL_ID BIGINT,
    I$FILTER_NAME VARCHAR(100) = NULL)
RETURNS (
    FILTER_ID BIGINT,
    USER_ID BIGINT,
    TYPE_ID BIGINT,
    LEVEL_ID BIGINT,
    FILTER_NAME VARCHAR(100),
    IS_LAST SMALLINT,
    LOGICAL_OPERATOR SMALLINT,
    PARENT_TYPE_ID BIGINT,
    ACTUAL_DATE DATE,
    IS_ACTUAL_DATE_USED SMALLINT)
AS
BEGIN
    IF (I$FILTER_NAME IS NOT NULL) THEN
    BEGIN
        FOR
            SELECT FIRST 1
                   FILTER_ID,
                   USER_ID,
                   TYPE_ID,
                   LEVEL_ID,
                   FILTER_NAME,
                   IS_LAST,
                   LOGICAL_OPERATOR,
                   PARENT_TYPE_ID,
                   ACTUAL_DATE,
                   IS_ACTUAL_DATE_USED
            FROM FILTERS
            WHERE USER_ID = :I$USER_ID
            AND LEVEL_ID = :I$LEVEL_ID
            AND FILTER_NAME LIKE :I$FILTER_NAME
            INTO :FILTER_ID,
                 :USER_ID,
                 :TYPE_ID,
                 :LEVEL_ID,
                 :FILTER_NAME,
                 :IS_LAST,
                 :LOGICAL_OPERATOR,
                 :PARENT_TYPE_ID,
                 :ACTUAL_DATE,
                 :IS_ACTUAL_DATE_USED
        DO
        BEGIN
            SUSPEND;
        END
    END
    ELSE
    BEGIN
        FOR
            SELECT FILTER_ID,
                   USER_ID,
                   TYPE_ID,
                   LEVEL_ID,
                   FILTER_NAME,
                   IS_LAST,
                   LOGICAL_OPERATOR,
                   PARENT_TYPE_ID,
                   ACTUAL_DATE,
                   IS_ACTUAL_DATE_USED
            FROM FILTERS
            WHERE FILTER_ID=:I$FILTER_ID
            UNION ALL
            SELECT FILTER_ID,
                   USER_ID,
                   TYPE_ID,
                   LEVEL_ID,
                   FILTER_NAME,
                   IS_LAST,
                   LOGICAL_OPERATOR,
                   PARENT_TYPE_ID,
                   ACTUAL_DATE,
                   IS_ACTUAL_DATE_USED
            FROM FILTERS
            WHERE USER_ID=:I$USER_ID
            AND LEVEL_ID=:I$LEVEL_ID
            AND IS_LAST=1
            INTO :FILTER_ID,
                 :USER_ID,
                 :TYPE_ID,
                 :LEVEL_ID,
                 :FILTER_NAME,
                 :IS_LAST,
                 :LOGICAL_OPERATOR,
                 :PARENT_TYPE_ID,
                 :ACTUAL_DATE,
                 :IS_ACTUAL_DATE_USED
        DO
        BEGIN
            SUSPEND;
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FILTER_IPARAM_CHECK (
    I$PARAM_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$OP SMALLINT,
    I$TYPE_ID BIGINT,
    I$PARAM_OBJ_TYPE_ID BIGINT,
    I$VAL INTEGER)
RETURNS (
    C INTEGER,
    OBJ_ID BIGINT)
AS
BEGIN
    C = 0;
    IF (I$OP = 1) THEN
    BEGIN /* = */
        IF (I$PARAM_OBJ_TYPE_ID = I$TYPE_ID) THEN
        BEGIN
            SELECT FIRST 1
                   1,
                   OBJ_ID
            FROM VALI
            WHERE PARAM_ID = :I$PARAM_ID
            AND OBJ_ID = :I$OBJ_ID
            AND IS_DEL = 0
            AND VAL = :I$VAL
            INTO :C,
                 :OBJ_ID;
        END
        ELSE
        BEGIN
            SELECT FIRST 1
                   1,
                   L.OBJ_ID
            FROM LINKS L
            INNER JOIN VALI V
            ON V.PARAM_ID = :I$PARAM_ID
            AND V.OBJ_ID = L.OBJ_ID
            AND V.IS_DEL = 0
            AND V.VAL = :I$VAL
            WHERE L.PARENT_ID = :I$OBJ_ID
            AND L.DATE_DEL IS NULL
            AND L.OBJ_TYPE_ID = :I$PARAM_OBJ_TYPE_ID
            INTO :C,
                 :OBJ_ID;
        END
    END
    ELSE IF (I$OP = 2) THEN
    BEGIN /* <> */
        IF (I$PARAM_OBJ_TYPE_ID = I$TYPE_ID) THEN
        BEGIN
            SELECT FIRST 1
                   1,
                   OBJ_ID
            FROM VALI
            WHERE PARAM_ID = :I$PARAM_ID
            AND OBJ_ID = :I$OBJ_ID
            AND IS_DEL = 0
            AND VAL <> :I$VAL
            INTO :C,
                 :OBJ_ID;
        END
        ELSE
        BEGIN
            SELECT FIRST 1
                   1,
                   L.OBJ_ID
            FROM LINKS L
            INNER JOIN VALI V
            ON V.PARAM_ID = :I$PARAM_ID
            AND V.OBJ_ID = L.OBJ_ID
            AND V.IS_DEL = 0
            AND V.VAL <> :I$VAL
            WHERE L.PARENT_ID = :I$OBJ_ID
            AND L.DATE_DEL IS NULL
            AND L.OBJ_TYPE_ID = :I$PARAM_OBJ_TYPE_ID
            INTO :C,
                 :OBJ_ID;
        END
    END
    ELSE IF (I$OP = 3) THEN
    BEGIN /* > */
        IF (I$PARAM_OBJ_TYPE_ID = I$TYPE_ID) THEN
        BEGIN
            SELECT FIRST 1
                   1,
                   OBJ_ID
            FROM VALI
            WHERE PARAM_ID = :I$PARAM_ID
            AND OBJ_ID = :I$OBJ_ID
            AND IS_DEL = 0
            AND VAL > :I$VAL
            INTO :C,
                 :OBJ_ID;
        END
        ELSE
        BEGIN
            SELECT FIRST 1
                   1,
                   L.OBJ_ID
            FROM LINKS L
            INNER JOIN VALI V
            ON V.PARAM_ID = :I$PARAM_ID
            AND V.OBJ_ID = L.OBJ_ID
            AND V.IS_DEL = 0
            AND V.VAL > :I$VAL
            WHERE L.PARENT_ID = :I$OBJ_ID
            AND L.DATE_DEL IS NULL
            AND L.OBJ_TYPE_ID = :I$PARAM_OBJ_TYPE_ID
            INTO :C,
                 :OBJ_ID;
        END
    END
    ELSE IF (I$OP = 4) THEN
    BEGIN /* < */
        IF (I$PARAM_OBJ_TYPE_ID = I$TYPE_ID) THEN
        BEGIN
            SELECT FIRST 1
                   1,
                   OBJ_ID
            FROM VALI
            WHERE PARAM_ID = :I$PARAM_ID
            AND OBJ_ID = :I$OBJ_ID
            AND IS_DEL = 0
            AND VAL < :I$VAL
            INTO :C,
                 :OBJ_ID;
        END
        ELSE
        BEGIN
            SELECT FIRST 1
                   1,
                   L.OBJ_ID
            FROM LINKS L
            INNER JOIN VALI V
            ON V.PARAM_ID = :I$PARAM_ID
            AND V.OBJ_ID = L.OBJ_ID
            AND V.IS_DEL = 0
            AND V.VAL < :I$VAL
            WHERE L.PARENT_ID = :I$OBJ_ID
            AND L.DATE_DEL IS NULL
            AND L.OBJ_TYPE_ID = :I$PARAM_OBJ_TYPE_ID
            INTO :C,
                 :OBJ_ID;
        END
    END
    ELSE IF (I$OP = 5) THEN
    BEGIN /* >= */
        IF (I$PARAM_OBJ_TYPE_ID = I$TYPE_ID) THEN
        BEGIN
            SELECT FIRST 1
                   1,
                   OBJ_ID
            FROM VALI
            WHERE PARAM_ID = :I$PARAM_ID
            AND OBJ_ID = :I$OBJ_ID
            AND IS_DEL = 0
            AND VAL >= :I$VAL
            INTO :C,
                 :OBJ_ID;
        END
        ELSE
        BEGIN
            SELECT FIRST 1
                   1,
                   L.OBJ_ID
            FROM LINKS L
            INNER JOIN VALI V
            ON V.PARAM_ID = :I$PARAM_ID
            AND V.OBJ_ID = L.OBJ_ID
            AND V.IS_DEL = 0
            AND V.VAL >= :I$VAL
            WHERE L.PARENT_ID = :I$OBJ_ID
            AND L.DATE_DEL IS NULL
            AND L.OBJ_TYPE_ID = :I$PARAM_OBJ_TYPE_ID
            INTO :C,
                 :OBJ_ID;
        END
    END
    ELSE IF (I$OP = 6) THEN
    BEGIN /* <= */
        IF (I$PARAM_OBJ_TYPE_ID = I$TYPE_ID) THEN
        BEGIN
            SELECT FIRST 1
                   1,
                   OBJ_ID
            FROM VALI
            WHERE PARAM_ID = :I$PARAM_ID
            AND OBJ_ID = :I$OBJ_ID
            AND IS_DEL = 0
            AND VAL <= :I$VAL
            INTO :C,
                 :OBJ_ID;
        END
        ELSE
        BEGIN
            SELECT FIRST 1
                   1,
                   L.OBJ_ID
            FROM LINKS L
            INNER JOIN VALI V
            ON V.PARAM_ID = :I$PARAM_ID
            AND V.OBJ_ID = L.OBJ_ID
            AND V.IS_DEL = 0
            AND V.VAL <= :I$VAL
            WHERE L.PARENT_ID = :I$OBJ_ID
            AND L.DATE_DEL IS NULL
            AND L.OBJ_TYPE_ID = :I$PARAM_OBJ_TYPE_ID
            INTO :C,
                 :OBJ_ID;
        END
    END
    ELSE IF (I$OP = 7) THEN
    BEGIN /* NULL */
        IF (I$PARAM_OBJ_TYPE_ID = I$TYPE_ID) THEN
        BEGIN
            SELECT FIRST 1
                   1,
                   OBJ_ID
            FROM VALI
            WHERE PARAM_ID = :I$PARAM_ID
            AND OBJ_ID = :I$OBJ_ID
            AND IS_DEL = 0
            INTO :C,
                 :OBJ_ID;
        END
        ELSE
        BEGIN
            SELECT FIRST 1
                   1,
                   L.OBJ_ID
            FROM LINKS L
            INNER JOIN VALI V
            ON V.PARAM_ID = :I$PARAM_ID
            AND V.OBJ_ID = L.OBJ_ID
            AND V.IS_DEL = 0
            WHERE L.PARENT_ID = :I$OBJ_ID
            AND L.DATE_DEL IS NULL
            AND L.OBJ_TYPE_ID = :I$PARAM_OBJ_TYPE_ID
            INTO :C,
                 :OBJ_ID;
        END
        
        IF (C = 1) THEN
        BEGIN
            C = 0;
        END
        ELSE
        BEGIN
            C = 1;
        END
    END
    ELSE IF (I$OP = 8) THEN
    BEGIN /* NOT NULL */
        IF (I$PARAM_OBJ_TYPE_ID = I$TYPE_ID) THEN
        BEGIN
            SELECT FIRST 1
                   1,
                   OBJ_ID
            FROM VALI
            WHERE PARAM_ID = :I$PARAM_ID
            AND OBJ_ID = :I$OBJ_ID
            AND IS_DEL = 0
            INTO :C,
                 :OBJ_ID;
        END
        ELSE
        BEGIN
            SELECT FIRST 1
                   1,
                   L.OBJ_ID
            FROM LINKS L
            INNER JOIN VALI V
            ON V.PARAM_ID = :I$PARAM_ID
            AND V.OBJ_ID = L.OBJ_ID
            AND V.IS_DEL = 0
            WHERE L.PARENT_ID = :I$OBJ_ID
            AND L.DATE_DEL IS NULL
            AND L.OBJ_TYPE_ID = :I$PARAM_OBJ_TYPE_ID
            INTO :C,
                 :OBJ_ID;
        END
    END
    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FILTER_LPARAM_CHECK (
    I$PARAM_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$OP SMALLINT,
    I$TYPE_ID BIGINT,
    I$PARAM_OBJ_TYPE_ID BIGINT,
    I$VAL BIGINT)
RETURNS (
    C INTEGER,
    OBJ_ID BIGINT)
AS
DECLARE VARIABLE I BIGINT;
DECLARE VARIABLE SO SMALLINT;
DECLARE VARIABLE SOF SMALLINT;
BEGIN
    C = 0;
    IF (I$OP = 1) THEN
    BEGIN /* = */
        IF (I$PARAM_OBJ_TYPE_ID = I$TYPE_ID) THEN
        BEGIN
            SELECT FIRST 1
                   1,
                   OBJ_ID
            FROM VALL
            WHERE PARAM_ID = :I$PARAM_ID
            AND OBJ_ID = :I$OBJ_ID
            AND IS_DEL = 0
            AND LISTVAL_ID = :I$VAL
            INTO :C,
                 :OBJ_ID;
        END
        ELSE
        BEGIN
            SELECT FIRST 1
                   1,
                   L.OBJ_ID
            FROM LINKS L
            INNER JOIN VALL V
            ON V.PARAM_ID = :I$PARAM_ID
            AND V.OBJ_ID = L.OBJ_ID
            AND V.IS_DEL = 0
            AND V.LISTVAL_ID = :I$VAL
            WHERE L.PARENT_ID = :I$OBJ_ID
            AND L.DATE_DEL IS NULL
            AND L.OBJ_TYPE_ID = :I$PARAM_OBJ_TYPE_ID
            INTO :C,
                 :OBJ_ID;
        END
    END
    ELSE IF (I$OP = 2) THEN
    BEGIN /* <> */
        IF (I$PARAM_OBJ_TYPE_ID = I$TYPE_ID) THEN
        BEGIN
            SELECT FIRST 1
                   1,
                   OBJ_ID
            FROM VALL
            WHERE PARAM_ID = :I$PARAM_ID
            AND OBJ_ID=:I$OBJ_ID
            AND IS_DEL = 0
            AND LISTVAL_ID <> :I$VAL
            INTO :C,
                 :OBJ_ID;
        END
        ELSE
        BEGIN
            SELECT FIRST 1
                   1,
                   L.OBJ_ID
            FROM LINKS L
            INNER JOIN VALL V
            ON V.PARAM_ID = :I$PARAM_ID
            AND V.OBJ_ID = L.OBJ_ID
            AND V.IS_DEL = 0
            AND V.LISTVAL_ID <> :I$VAL
            WHERE L.PARENT_ID = :I$OBJ_ID
            AND L.DATE_DEL IS NULL
            AND L.OBJ_TYPE_ID = :I$PARAM_OBJ_TYPE_ID
            INTO :C,
                 :OBJ_ID;
        END
    END
    ELSE IF ((I$OP > 2) AND (I$OP < 7)) THEN
    BEGIN
        I = NULL;
        C = 0;
        SELECT SORT_ORDER
        FROM LISTVALS
        WHERE LISTVAL_ID = :I$VAL
        INTO :SOF;
        
        IF (I$PARAM_OBJ_TYPE_ID = I$TYPE_ID) THEN
        BEGIN
            FOR
                SELECT LISTVAL_ID
                FROM VALL
                WHERE PARAM_ID = :I$PARAM_ID
                AND OBJ_ID=:I$OBJ_ID
                AND IS_DEL = 0
                INTO :I
            DO
            BEGIN
                SELECT SORT_ORDER
                FROM LISTVALS
                WHERE LISTVAL_ID = :I
                INTO :SO;
    
                IF (((I$OP = 3) AND (SO > SOF)) OR
                    ((I$OP = 4) AND (SO < SOF)) OR
                    ((I$OP = 5) AND (SO >= SOF)) OR
                    ((I$OP = 6) AND (SO >= SOF))) THEN
                BEGIN
                    C = 1;
                END
            END
        END
        ELSE
        BEGIN
            FOR
                SELECT V.LISTVAL_ID
                FROM LINKS L
                INNER JOIN VALL V
                ON V.PARAM_ID = :I$PARAM_ID
                AND V.OBJ_ID = L.OBJ_ID
                AND V.IS_DEL = 0
                WHERE L.PARENT_ID = :I$OBJ_ID
                AND L.DATE_DEL IS NULL
                AND L.OBJ_TYPE_ID = :I$PARAM_OBJ_TYPE_ID
                INTO :I
            DO
            BEGIN
                SELECT SORT_ORDER
                FROM LISTVALS
                WHERE LISTVAL_ID = :I
                INTO :SO;
    
                IF (((I$OP = 3) AND (SO > SOF)) OR
                    ((I$OP = 4) AND (SO < SOF)) OR
                    ((I$OP = 5) AND (SO >= SOF)) OR
                    ((I$OP = 6) AND (SO >= SOF))) THEN
                BEGIN
                    C = 1;
                END
            END
        END
    END
    ELSE IF (I$OP = 7) THEN
    BEGIN /* NULL */
        IF (I$PARAM_OBJ_TYPE_ID = I$TYPE_ID) THEN
        BEGIN
            SELECT FIRST 1
                   1,
                   OBJ_ID
            FROM VALL
            WHERE PARAM_ID = :I$PARAM_ID
            AND OBJ_ID = :I$OBJ_ID
            AND IS_DEL = 0
            INTO :C,
                 :OBJ_ID;
        END
        ELSE
        BEGIN
            SELECT FIRST 1
                   1,
                   L.OBJ_ID
            FROM LINKS L
            INNER JOIN VALL V
            ON V.PARAM_ID = :I$PARAM_ID
            AND V.OBJ_ID = L.OBJ_ID
            AND V.IS_DEL = 0
            WHERE L.PARENT_ID = :I$OBJ_ID
            AND L.DATE_DEL IS NULL
            AND L.OBJ_TYPE_ID = :I$PARAM_OBJ_TYPE_ID
            INTO :C,
                 :OBJ_ID;
        END
        IF (C = 1) THEN
        BEGIN
            C = 0;
        END
        ELSE
        BEGIN
            C = 1;
        END
    END
    ELSE IF (I$OP = 8) THEN
    BEGIN /* NOT NULL */
        IF (I$PARAM_OBJ_TYPE_ID = I$TYPE_ID) THEN
        BEGIN
            SELECT FIRST 1
                   1,
                   OBJ_ID
            FROM VALL
            WHERE PARAM_ID = :I$PARAM_ID
            AND OBJ_ID = :I$OBJ_ID
            AND IS_DEL = 0
            INTO :C,
                 :OBJ_ID;
        END
        ELSE
        BEGIN
            SELECT FIRST 1
                   1,
                   L.OBJ_ID
            FROM LINKS L
            INNER JOIN VALL V
            ON V.PARAM_ID = :I$PARAM_ID
            AND V.OBJ_ID = L.OBJ_ID
            AND V.IS_DEL = 0
            WHERE L.PARENT_ID = :I$OBJ_ID
            AND L.DATE_DEL IS NULL
            AND L.OBJ_TYPE_ID = :I$PARAM_OBJ_TYPE_ID
            INTO :C,
                 :OBJ_ID;
        END
    END
    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FILTER_OBJECT_CHILDREN_GET (
    I$OBJ_ID BIGINT,
    I$LINK_ID BIGINT,
    I$CHILDREN_TYPE_ID BIGINT,
    I$LEVEL_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    LINK_ID BIGINT)
AS
DECLARE VARIABLE T BIGINT;
DECLARE VARIABLE X BIGINT;
DECLARE VARIABLE Y BIGINT;
BEGIN
    SELECT TYPE_ID
    FROM OBJECTS
    WHERE OBJ_ID = :I$OBJ_ID
    INTO :T;

    IF (:T = :I$CHILDREN_TYPE_ID) THEN
    BEGIN
        OBJ_ID = :I$OBJ_ID;
        LINK_ID = :I$LINK_ID;
        SUSPEND;
    END

    FOR SELECT L.OBJ_ID, L.LINK_ID
        FROM LINKS L
        INNER JOIN LTYPES LT ON LT.TYPE_ID = L.PARENT_TYPE_ID
        WHERE L.PARENT_ID = :I$OBJ_ID
          AND L.DATE_DEL IS NULL
          AND LT.LEVEL_ID = :I$LEVEL_ID
          AND LT.EDIT_TYPE > -1
          AND LT.IS_DEL = 0
        INTO :X, :Y
    DO
    BEGIN
        FOR SELECT OBJ_ID, LINK_ID
            FROM FILTER_OBJECT_CHILDREN_GET(:X, :Y, :I$CHILDREN_TYPE_ID, :I$LEVEL_ID)
            INTO :OBJ_ID, :LINK_ID
        DO
            SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FILTER_OBJECT_PARENTS_GET (
    I$LINK_ID BIGINT,
    I$ROOT_LINK_ID BIGINT,
    I$LEVEL_ID BIGINT)
RETURNS (
    LINK_ID BIGINT)
AS
declare variable V$LINK_ID bigint;
BEGIN
    IF (I$LINK_ID IS NOT NULL) THEN
    BEGIN
        LINK_ID = I$LINK_ID;
        SUSPEND;

        IF (I$LINK_ID = I$ROOT_LINK_ID) THEN
        BEGIN
            EXIT;
        END

        FOR
            SELECT L2.LINK_ID

            FROM LINKS L

            JOIN LTYPES LT
            ON L.PARENT_TYPE_ID = LT.TYPE_ID
            AND LT.LEVEL_ID = :I$LEVEL_ID
            AND LT.EDIT_TYPE > -1
            AND LT.IS_DEL = 0

            JOIN LINKS L2
            ON L2.OBJ_ID = L.PARENT_ID
            AND L2.DATE_DEL IS NULL

            WHERE L.LINK_ID = :I$LINK_ID
            AND L.DATE_DEL IS NULL

            INTO :V$LINK_ID
        DO
        BEGIN
            IF (EXISTS(
                SELECT FIRST 1 1
                FROM FILTER_OBJECT_PARENTS_GET(:V$LINK_ID, :I$ROOT_LINK_ID, :I$LEVEL_ID)
                WHERE LINK_ID = :I$ROOT_LINK_ID
            )) THEN
            BEGIN
                FOR
                    SELECT LINK_ID
                    FROM FILTER_OBJECT_PARENTS_GET(:V$LINK_ID, :I$ROOT_LINK_ID, :I$LEVEL_ID)
                    INTO :LINK_ID
                DO
                BEGIN
                    SUSPEND;
                END
                EXIT;
            END
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FILTER_RPARAM_CHECK (
    I$PARAM_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$OP SMALLINT,
    I$TYPE_ID BIGINT,
    I$PARAM_OBJ_TYPE_ID BIGINT,
    I$VAL BIGINT)
RETURNS (
    C INTEGER,
    OBJ_ID BIGINT)
AS
BEGIN
    C = 0;
    IF (I$OP = 1) THEN
    BEGIN /* = */
        IF (I$PARAM_OBJ_TYPE_ID = I$TYPE_ID) THEN
        BEGIN
            SELECT FIRST 1
                   1,
                   OBJ_ID
            FROM VALR
            WHERE PARAM_ID = :I$PARAM_ID
            AND OBJ_ID = :I$OBJ_ID
            AND IS_DEL = 0
            AND VAL = :I$VAL
            INTO :C,
                 :OBJ_ID;
        END
        ELSE
        BEGIN
            SELECT FIRST 1
                   1,
                   L.OBJ_ID
            FROM LINKS L
            INNER JOIN VALR V
            ON V.PARAM_ID = :I$PARAM_ID
            AND V.OBJ_ID = L.OBJ_ID
            AND V.IS_DEL = 0
            AND V.VAL = :I$VAL
            WHERE L.PARENT_ID = :I$OBJ_ID
            AND L.DATE_DEL IS NULL
            AND L.OBJ_TYPE_ID = :I$PARAM_OBJ_TYPE_ID
            INTO :C,
                 :OBJ_ID;
        END
    END
    ELSE IF (I$OP = 2) THEN
    BEGIN /* <> */
        IF (I$PARAM_OBJ_TYPE_ID = I$TYPE_ID) THEN
        BEGIN
            SELECT FIRST 1
                   1,
                   OBJ_ID
            FROM VALR
            WHERE PARAM_ID = :I$PARAM_ID
            AND OBJ_ID = :I$OBJ_ID
            AND IS_DEL = 0
            AND VAL <> :I$VAL
            INTO :C,
                 :OBJ_ID;
        END
        ELSE
        BEGIN
            SELECT FIRST 1
                   1,
                   L.OBJ_ID
            FROM LINKS L
            INNER JOIN VALR V
            ON V.PARAM_ID = :I$PARAM_ID
            AND V.OBJ_ID = L.OBJ_ID
            AND V.IS_DEL = 0
            AND V.VAL <> :I$VAL
            WHERE L.PARENT_ID = :I$OBJ_ID
            AND L.DATE_DEL IS NULL
            AND L.OBJ_TYPE_ID = :I$PARAM_OBJ_TYPE_ID
            INTO :C,
                 :OBJ_ID;
        END
    END
    ELSE IF (I$OP = 3) THEN
    BEGIN /* NULL */
        IF (I$PARAM_OBJ_TYPE_ID = I$TYPE_ID) THEN
        BEGIN
            SELECT FIRST 1
                   1,
                   OBJ_ID
            FROM VALR
            WHERE PARAM_ID = :I$PARAM_ID
            AND OBJ_ID = :I$OBJ_ID
            AND IS_DEL = 0
            INTO :C,
                 :OBJ_ID;
        END
        ELSE
        BEGIN
            SELECT FIRST 1
                   1,
                   L.OBJ_ID
            FROM LINKS L
            INNER JOIN VALR V
            ON V.PARAM_ID = :I$PARAM_ID
            AND V.OBJ_ID = L.OBJ_ID
            AND V.IS_DEL = 0
            WHERE L.PARENT_ID = :I$OBJ_ID
            AND L.DATE_DEL IS NULL
            AND L.OBJ_TYPE_ID = :I$PARAM_OBJ_TYPE_ID
            INTO :C,
                 :OBJ_ID;
        END
        IF (C = 1) THEN
        BEGIN
            C = 0;
        END
        ELSE
        BEGIN
            C = 1;
        END
    END
    ELSE IF (I$OP = 4) THEN
    BEGIN /* NOT NULL */
        IF (I$PARAM_OBJ_TYPE_ID = I$TYPE_ID) THEN
        BEGIN
            SELECT FIRST 1
                   1,
                   OBJ_ID
            FROM VALR
            WHERE PARAM_ID = :I$PARAM_ID
            AND OBJ_ID = :I$OBJ_ID
            AND IS_DEL = 0
            INTO :C,
                 :OBJ_ID;
        END
        ELSE
        BEGIN
            SELECT FIRST 1
                   1,
                   L.OBJ_ID
            FROM LINKS L
            INNER JOIN VALR V
            ON V.PARAM_ID = :I$PARAM_ID
            AND V.OBJ_ID = L.OBJ_ID
            AND V.IS_DEL = 0
            WHERE L.PARENT_ID = :I$OBJ_ID
            AND L.DATE_DEL IS NULL
            AND L.OBJ_TYPE_ID = :I$PARAM_OBJ_TYPE_ID
            INTO :C,
                 :OBJ_ID;
        END
    END
    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FILTER_SPARAM_CHECK (
    I$PARAM_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$OP SMALLINT,
    I$TYPE_ID BIGINT,
    I$PARAM_OBJ_TYPE_ID BIGINT,
    I$VAL VARCHAR(4000))
RETURNS (
    C INTEGER,
    OBJ_ID BIGINT)
AS
BEGIN
    C = 0;
    IF (I$OP = 1) THEN
    BEGIN /* = */
        IF (I$PARAM_OBJ_TYPE_ID = I$TYPE_ID) THEN
        BEGIN
            SELECT FIRST 1
                   1,
                   OBJ_ID
            FROM VALS
            WHERE PARAM_ID = :I$PARAM_ID
            AND OBJ_ID = :I$OBJ_ID
            AND IS_DEL = 0
            AND UPPER(VAL) = UPPER(:I$VAL)
            INTO :C,
                 :OBJ_ID;
        END
        ELSE
        BEGIN
            SELECT FIRST 1
                   1,
                   L.OBJ_ID
            FROM LINKS L
            INNER JOIN VALS V
            ON V.PARAM_ID = :I$PARAM_ID
            AND V.OBJ_ID = L.OBJ_ID
            AND V.IS_DEL = 0
            AND UPPER(V.VAL) = UPPER(:I$VAL)
            WHERE L.PARENT_ID = :I$OBJ_ID
            AND L.DATE_DEL IS NULL
            AND L.OBJ_TYPE_ID = :I$PARAM_OBJ_TYPE_ID
            INTO :C,
                 :OBJ_ID;
        END
    END
    ELSE IF (I$OP = 2) THEN
    BEGIN /* <> */
        IF (I$PARAM_OBJ_TYPE_ID = I$TYPE_ID) THEN
        BEGIN
            SELECT FIRST 1
                   1,
                   OBJ_ID
            FROM VALS
            WHERE PARAM_ID = :I$PARAM_ID
            AND OBJ_ID = :I$OBJ_ID
            AND IS_DEL = 0
            AND UPPER(VAL) <> UPPER(:I$VAL)
            INTO :C,
                 :OBJ_ID;
        END
        ELSE
        BEGIN
            SELECT FIRST 1
                   1,
                   L.OBJ_ID
            FROM LINKS L
            INNER JOIN VALS V
            ON V.PARAM_ID = :I$PARAM_ID
            AND V.OBJ_ID = L.OBJ_ID
            AND V.IS_DEL = 0
            AND UPPER(V.VAL) <> UPPER(:I$VAL)
            WHERE L.PARENT_ID = :I$OBJ_ID
            AND L.DATE_DEL IS NULL
            AND L.OBJ_TYPE_ID = :I$PARAM_OBJ_TYPE_ID
            INTO :C,
                 :OBJ_ID;
        END
    END
    ELSE IF (I$OP = 3) THEN
    BEGIN /* > */
        IF (I$PARAM_OBJ_TYPE_ID = I$TYPE_ID) THEN
        BEGIN
            SELECT FIRST 1
                   1,
                   OBJ_ID
            FROM VALS
            WHERE PARAM_ID = :I$PARAM_ID
            AND OBJ_ID = :I$OBJ_ID
            AND IS_DEL = 0
            AND UPPER(VAL) > UPPER(:I$VAL)
            INTO :C,
                 :OBJ_ID;
        END
        ELSE
        BEGIN
            SELECT FIRST 1
                   1,
                   L.OBJ_ID
            FROM LINKS L
            INNER JOIN VALS V
            ON V.PARAM_ID = :I$PARAM_ID
            AND V.OBJ_ID = L.OBJ_ID
            AND V.IS_DEL = 0
            AND UPPER(V.VAL) > UPPER(:I$VAL)
            WHERE L.PARENT_ID = :I$OBJ_ID
            AND L.DATE_DEL IS NULL
            AND L.OBJ_TYPE_ID = :I$PARAM_OBJ_TYPE_ID
            INTO :C,
                 :OBJ_ID;
        END
    END
    ELSE IF (I$OP = 4) THEN
    BEGIN /* < */
        IF (I$PARAM_OBJ_TYPE_ID = I$TYPE_ID) THEN
        BEGIN
            SELECT FIRST 1
                   1,
                   OBJ_ID
            FROM VALS
            WHERE PARAM_ID = :I$PARAM_ID
            AND OBJ_ID = :I$OBJ_ID
            AND IS_DEL = 0
            AND UPPER(VAL) < UPPER(:I$VAL)
            INTO :C,
                 :OBJ_ID;
        END
        ELSE
        BEGIN
            SELECT FIRST 1
                   1,
                   L.OBJ_ID
            FROM LINKS L
            INNER JOIN VALS V
            ON V.PARAM_ID = :I$PARAM_ID
            AND V.OBJ_ID = L.OBJ_ID
            AND V.IS_DEL = 0
            AND UPPER(V.VAL) < UPPER(:I$VAL)
            WHERE L.PARENT_ID = :I$OBJ_ID
            AND L.DATE_DEL IS NULL
            AND L.OBJ_TYPE_ID = :I$PARAM_OBJ_TYPE_ID
            INTO :C,
                 :OBJ_ID;
        END
    END
    ELSE IF (I$OP = 5) THEN
    BEGIN /* >= */
        IF (I$PARAM_OBJ_TYPE_ID = I$TYPE_ID) THEN
        BEGIN
            SELECT FIRST 1
                   1,
                   OBJ_ID
            FROM VALS
            WHERE PARAM_ID = :I$PARAM_ID
            AND OBJ_ID = :I$OBJ_ID
            AND IS_DEL = 0
            AND UPPER(VAL) >= UPPER(:I$VAL)
            INTO :C,
                 :OBJ_ID;
        END
        ELSE
        BEGIN
            SELECT FIRST 1
                   1,
                   L.OBJ_ID
            FROM LINKS L
            INNER JOIN VALS V
            ON V.PARAM_ID = :I$PARAM_ID
            AND V.OBJ_ID = L.OBJ_ID
            AND V.IS_DEL = 0
            AND UPPER(V.VAL) >= UPPER(:I$VAL)
            WHERE L.PARENT_ID = :I$OBJ_ID
            AND L.DATE_DEL IS NULL
            AND L.OBJ_TYPE_ID = :I$PARAM_OBJ_TYPE_ID
            INTO :C,
                 :OBJ_ID;
        END
    END
    ELSE IF (I$OP = 6) THEN
    BEGIN /* <= */
        IF (I$PARAM_OBJ_TYPE_ID = I$TYPE_ID) THEN
        BEGIN
            SELECT FIRST 1
                   1,
                   OBJ_ID
            FROM VALS
            WHERE PARAM_ID = :I$PARAM_ID
            AND OBJ_ID = :I$OBJ_ID
            AND IS_DEL = 0
            AND UPPER(VAL) <= UPPER(:I$VAL)
            INTO :C,
                 :OBJ_ID;
        END
        ELSE
        BEGIN
            SELECT FIRST 1
                   1,
                   L.OBJ_ID
            FROM LINKS L
            INNER JOIN VALS V
            ON V.PARAM_ID = :I$PARAM_ID
            AND V.OBJ_ID = L.OBJ_ID
            AND V.IS_DEL = 0
            AND UPPER(V.VAL) <= UPPER(:I$VAL)
            WHERE L.PARENT_ID = :I$OBJ_ID
            AND L.DATE_DEL IS NULL
            AND L.OBJ_TYPE_ID = :I$PARAM_OBJ_TYPE_ID
            INTO :C,
                 :OBJ_ID;
        END
    END
    ELSE IF (I$OP = 7) THEN
    BEGIN /* NULL */
        IF (I$PARAM_OBJ_TYPE_ID = I$TYPE_ID) THEN
        BEGIN
            SELECT FIRST 1
                   1,
                   OBJ_ID
            FROM VALS
            WHERE PARAM_ID = :I$PARAM_ID
            AND OBJ_ID = :I$OBJ_ID
            AND IS_DEL = 0
            INTO :C,
                 :OBJ_ID;
        END
        ELSE
        BEGIN
            SELECT FIRST 1
                   1,
                   L.OBJ_ID
            FROM LINKS L
            INNER JOIN VALS V
            ON V.PARAM_ID = :I$PARAM_ID
            AND V.OBJ_ID = L.OBJ_ID
            AND V.IS_DEL = 0
            WHERE L.PARENT_ID = :I$OBJ_ID
            AND L.DATE_DEL IS NULL
            AND L.OBJ_TYPE_ID = :I$PARAM_OBJ_TYPE_ID
            INTO :C,
                 :OBJ_ID;
        END
        
        IF (C = 1) THEN
        BEGIN
            C = 0;
        END
        ELSE
        BEGIN
            C = 1;
        END
    END
    ELSE IF (I$OP = 8) THEN
    BEGIN /* NOT NULL */
        IF (I$PARAM_OBJ_TYPE_ID = I$TYPE_ID) THEN
        BEGIN
            SELECT FIRST 1
                   1,
                   OBJ_ID
            FROM VALS
            WHERE PARAM_ID = :I$PARAM_ID
            AND OBJ_ID = :I$OBJ_ID
            AND IS_DEL = 0
            INTO :C,
                 :OBJ_ID;
        END
        ELSE
        BEGIN
            SELECT FIRST 1
                   1,
                   L.OBJ_ID
            FROM LINKS L
            INNER JOIN VALS V
            ON V.PARAM_ID = :I$PARAM_ID
            AND V.OBJ_ID = L.OBJ_ID
            AND V.IS_DEL = 0
            WHERE L.PARENT_ID = :I$OBJ_ID
            AND L.DATE_DEL IS NULL
            AND L.OBJ_TYPE_ID = :I$PARAM_OBJ_TYPE_ID
            INTO :C,
                 :OBJ_ID;
        END
    END
    ELSE IF (I$OP = 9) THEN
    BEGIN /* ~ */
        IF (I$PARAM_OBJ_TYPE_ID = I$TYPE_ID) THEN
        BEGIN
            SELECT FIRST 1
                   1,
                   OBJ_ID
            FROM VALS
            WHERE PARAM_ID = :I$PARAM_ID
            AND OBJ_ID = :I$OBJ_ID
            AND IS_DEL = 0
            AND UPPER(VAL) LIKE UPPER(:I$VAL)
            INTO :C,
                 :OBJ_ID;
        END
        ELSE
        BEGIN
            SELECT FIRST 1
                   1,
                   L.OBJ_ID
            FROM LINKS L
            INNER JOIN VALS V
            ON V.PARAM_ID = :I$PARAM_ID
            AND V.OBJ_ID = L.OBJ_ID
            AND V.IS_DEL = 0
            AND UPPER(V.VAL) LIKE UPPER(:I$VAL)
            WHERE L.PARENT_ID = :I$OBJ_ID
            AND L.DATE_DEL IS NULL
            AND L.OBJ_TYPE_ID = :I$PARAM_OBJ_TYPE_ID
            INTO :C,
                 :OBJ_ID;
        END
    END
    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FILTER_TPARAM_CHECK (
    I$PARAM_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$OP SMALLINT,
    I$TYPE_ID BIGINT,
    I$PARAM_OBJ_TYPE_ID BIGINT,
    I$VAL TIME)
RETURNS (
    C INTEGER,
    OBJ_ID BIGINT)
AS
BEGIN
    C = 0;
    IF (I$OP = 1) THEN
    BEGIN /* = */
        IF (I$PARAM_OBJ_TYPE_ID = I$TYPE_ID) THEN
        BEGIN
            SELECT FIRST 1
                   1,
                   OBJ_ID
            FROM VALT
            WHERE PARAM_ID = :I$PARAM_ID
            AND OBJ_ID = :I$OBJ_ID
            AND IS_DEL = 0
            AND VAL = :I$VAL
            INTO :C,
                 :OBJ_ID;
        END
        ELSE
        BEGIN
            SELECT FIRST 1
                   1,
                   L.OBJ_ID
            FROM LINKS L
            INNER JOIN VALT V
            ON V.PARAM_ID = :I$PARAM_ID
            AND V.OBJ_ID = L.OBJ_ID
            AND V.IS_DEL = 0
            AND V.VAL = :I$VAL
            WHERE L.PARENT_ID = :I$OBJ_ID
            AND L.DATE_DEL IS NULL
            AND L.OBJ_TYPE_ID = :I$PARAM_OBJ_TYPE_ID
            INTO :C,
                 :OBJ_ID;
        END
    END
    ELSE IF (I$OP = 2) THEN
    BEGIN /* <> */
        IF (I$PARAM_OBJ_TYPE_ID = I$TYPE_ID) THEN
        BEGIN
            SELECT FIRST 1
                   1,
                   OBJ_ID
            FROM VALT
            WHERE PARAM_ID = :I$PARAM_ID
            AND OBJ_ID = :I$OBJ_ID
            AND IS_DEL = 0
            AND VAL <> :I$VAL
            INTO :C,
                 :OBJ_ID;
        END
        ELSE
        BEGIN
            SELECT FIRST 1
                   1,
                   L.OBJ_ID
            FROM LINKS L
            INNER JOIN VALT V
            ON V.PARAM_ID = :I$PARAM_ID
            AND V.OBJ_ID = L.OBJ_ID
            AND V.IS_DEL = 0
            AND V.VAL <> :I$VAL
            WHERE L.PARENT_ID = :I$OBJ_ID
            AND L.DATE_DEL IS NULL
            AND L.OBJ_TYPE_ID = :I$PARAM_OBJ_TYPE_ID
            INTO :C,
                 :OBJ_ID;
        END
    END
    ELSE IF (I$OP = 3) THEN
    BEGIN /* > */
        IF (I$PARAM_OBJ_TYPE_ID = I$TYPE_ID) THEN
        BEGIN
            SELECT FIRST 1
                   1,
                   OBJ_ID
            FROM VALT
            WHERE PARAM_ID = :I$PARAM_ID
            AND OBJ_ID = :I$OBJ_ID
            AND IS_DEL = 0
            AND VAL > :I$VAL
            INTO :C,
                 :OBJ_ID;
        END
        ELSE
        BEGIN
            SELECT FIRST 1
                   1,
                   L.OBJ_ID
            FROM LINKS L
            INNER JOIN VALT V
            ON V.PARAM_ID = :I$PARAM_ID
            AND V.OBJ_ID = L.OBJ_ID
            AND V.IS_DEL = 0
            AND V.VAL > :I$VAL
            WHERE L.PARENT_ID = :I$OBJ_ID
            AND L.DATE_DEL IS NULL
            AND L.OBJ_TYPE_ID = :I$PARAM_OBJ_TYPE_ID
            INTO :C,
                 :OBJ_ID;
        END
    END
    ELSE IF (I$OP = 4) THEN
    BEGIN /* < */
        IF (I$PARAM_OBJ_TYPE_ID = I$TYPE_ID) THEN
        BEGIN
            SELECT FIRST 1
                   1,
                   OBJ_ID
            FROM VALT
            WHERE PARAM_ID = :I$PARAM_ID
            AND OBJ_ID = :I$OBJ_ID
            AND IS_DEL = 0
            AND VAL < :I$VAL
            INTO :C,
                 :OBJ_ID;
        END
        ELSE
        BEGIN
            SELECT FIRST 1
                   1,
                   L.OBJ_ID
            FROM LINKS L
            INNER JOIN VALT V
            ON V.PARAM_ID = :I$PARAM_ID
            AND V.OBJ_ID = L.OBJ_ID
            AND V.IS_DEL = 0
            AND V.VAL < :I$VAL
            WHERE L.PARENT_ID = :I$OBJ_ID
            AND L.DATE_DEL IS NULL
            AND L.OBJ_TYPE_ID = :I$PARAM_OBJ_TYPE_ID
            INTO :C,
                 :OBJ_ID;
        END
    END
    ELSE IF (I$OP = 5) THEN
    BEGIN /* >= */
        IF (I$PARAM_OBJ_TYPE_ID = I$TYPE_ID) THEN
        BEGIN
            SELECT FIRST 1
                   1,
                   OBJ_ID
            FROM VALT
            WHERE PARAM_ID = :I$PARAM_ID
            AND OBJ_ID = :I$OBJ_ID
            AND IS_DEL = 0
            AND VAL >= :I$VAL
            INTO :C,
                 :OBJ_ID;
        END
        ELSE
        BEGIN
            SELECT FIRST 1
                   1,
                   L.OBJ_ID
            FROM LINKS L
            INNER JOIN VALT V
            ON V.PARAM_ID = :I$PARAM_ID
            AND V.OBJ_ID = L.OBJ_ID
            AND V.IS_DEL = 0
            AND V.VAL >= :I$VAL
            WHERE L.PARENT_ID = :I$OBJ_ID
            AND L.DATE_DEL IS NULL
            AND L.OBJ_TYPE_ID = :I$PARAM_OBJ_TYPE_ID
            INTO :C,
                 :OBJ_ID;
        END
    END
    ELSE IF (I$OP = 6) THEN
    BEGIN /* <= */
        IF (I$PARAM_OBJ_TYPE_ID = I$TYPE_ID) THEN
        BEGIN
            SELECT FIRST 1
                   1,
                   OBJ_ID
            FROM VALT
            WHERE PARAM_ID = :I$PARAM_ID
            AND OBJ_ID = :I$OBJ_ID
            AND IS_DEL = 0
            AND VAL <= :I$VAL
            INTO :C,
                 :OBJ_ID;
        END
        ELSE
        BEGIN
            SELECT FIRST 1
                   1,
                   L.OBJ_ID
            FROM LINKS L
            INNER JOIN VALT V
            ON V.PARAM_ID = :I$PARAM_ID
            AND V.OBJ_ID = L.OBJ_ID
            AND V.IS_DEL = 0
            AND V.VAL <= :I$VAL
            WHERE L.PARENT_ID = :I$OBJ_ID
            AND L.DATE_DEL IS NULL
            AND L.OBJ_TYPE_ID = :I$PARAM_OBJ_TYPE_ID
            INTO :C,
                 :OBJ_ID;
        END
    END
    ELSE IF (I$OP = 7) THEN
    BEGIN /* NULL */
        IF (I$PARAM_OBJ_TYPE_ID = I$TYPE_ID) THEN
        BEGIN
            SELECT FIRST 1
                   1,
                   OBJ_ID
            FROM VALT
            WHERE PARAM_ID = :I$PARAM_ID
            AND OBJ_ID = :I$OBJ_ID
            AND IS_DEL = 0
            INTO :C,
                 :OBJ_ID;
        END
        ELSE
        BEGIN
            SELECT FIRST 1
                   1,
                   L.OBJ_ID
            FROM LINKS L
            INNER JOIN VALT V
            ON V.PARAM_ID = :I$PARAM_ID
            AND V.OBJ_ID = L.OBJ_ID
            AND V.IS_DEL = 0
            WHERE L.PARENT_ID = :I$OBJ_ID
            AND L.DATE_DEL IS NULL
            AND L.OBJ_TYPE_ID = :I$PARAM_OBJ_TYPE_ID
            INTO :C,
                 :OBJ_ID;
        END
        
        IF (C = 1) THEN
        BEGIN
            C = 0;
        END
        ELSE
        BEGIN
            C = 1;
        END
    END
    ELSE IF (I$OP = 8) THEN
    BEGIN /* NOT NULL */
        IF (I$PARAM_OBJ_TYPE_ID = I$TYPE_ID) THEN
        BEGIN
            SELECT FIRST 1
                   1,
                   OBJ_ID
            FROM VALT
            WHERE PARAM_ID = :I$PARAM_ID
            AND OBJ_ID = :I$OBJ_ID
            AND IS_DEL = 0
            INTO :C,
                 :OBJ_ID;
        END
        ELSE
        BEGIN
            SELECT FIRST 1
                   1,
                   L.OBJ_ID
            FROM LINKS L
            INNER JOIN VALT V
            ON V.PARAM_ID = :I$PARAM_ID
            AND V.OBJ_ID = L.OBJ_ID
            AND V.IS_DEL = 0
            WHERE L.PARENT_ID = :I$OBJ_ID
            AND L.DATE_DEL IS NULL
            AND L.OBJ_TYPE_ID = :I$PARAM_OBJ_TYPE_ID
            INTO :C,
                 :OBJ_ID;
        END
    END
    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FILTRED_LIST (
    I$LIST_ID BIGINT,
    I$FILTER VARCHAR(255),
    I$USER_ID BIGINT = NULL)
RETURNS (
    LISTVAL_ID BIGINT,
    PARENT_ID BIGINT,
    VAL VARCHAR(4000),
    VAL_LONG VARCHAR(4000),
    TAG VARCHAR(100),
    "FILTER" VARCHAR(255))
AS
DECLARE VARIABLE RES_ID BIGINT;
DECLARE VARIABLE LANG_CODE VARCHAR(2);
BEGIN
    FOR
        SELECT LISTVAL_ID, PARENT_ID, TAG, RES_ID, "FILTER"
        FROM LISTVALS
        WHERE "FILTER" SIMILAR TO '%' || :I$FILTER || '%' AND LIST_ID = :I$LIST_ID AND IS_DEL = 0
        ORDER BY SORT_ORDER
        INTO :LISTVAL_ID, :PARENT_ID, :TAG, :RES_ID, :"FILTER"
    DO
    BEGIN
        SELECT VAL, VAL_LONG
        FROM RES_GET(:RES_ID, :LANG_CODE)
        INTO :VAL, :VAL_LONG;
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FINALMARKS_CLASSES (
    I$OBJ_ID BIGINT,
    I$DATE DATE)
RETURNS (
    OBJ_ID BIGINT)
AS
begin

  -- Список пока всегда на текущую дату

  -- I$OBJ_ID относится к текущему выбранному в дереве объекту
  SELECT FIRST 1 L.OBJ_ID
  FROM OBJECT_PARENTS_GET(:I$OBJ_ID, 2) L
  INTO :I$OBJ_ID;

  FOR
    SELECT L9.OBJ_ID
    FROM LINKS L7
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V49.LISTVAL_ID
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 187) AND L9.DATE_DEL IS NULL
    LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C ON 1 = 1
    WHERE L7.PARENT_ID = :I$OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    ORDER BY LV.COST, C.CAPTION
    INTO :OBJ_ID
  DO
  BEGIN
    SUSPEND;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FINALMARKS_DATA (
    I$USER_ID VARCHAR(40),
    I$OBJ_ID BIGINT)
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(1000))
AS
declare variable V$CURRENT_YEAR integer;
declare variable V$YEAR_START date;
declare variable V$OBJ_ID bigint;
declare variable V$YEAR_ID bigint;
declare variable V$STAGE_ID bigint;
declare variable V$SUBJECT_ID bigint;
declare variable V$TEACHER_ID bigint;
declare variable V$MARKTYPE_ID bigint;
declare variable V$MARKVAL_ID bigint;
declare variable V$DT date;
declare variable V$DT2 date;
declare variable V$NATIVE smallint;
declare variable V$EXT smallint;
declare variable V$SEQ_INDEX integer;
declare variable V$HOURS float;
declare variable V$CT bigint;
declare variable V$STATUS varchar(10);
declare variable S varchar(1000);
declare variable S2 varchar(400);
declare variable S3 varchar(400);
declare variable S4 varchar(400);
declare variable S5 varchar(400);
declare variable S6 varchar(400);
declare variable V varchar(400);
begin

  SELECT FIRST 1 V1236.LISTVAL_ID, LV.COST, CAST(LV.TAG AS DATE)
  FROM OBJECT_PARENTS_GET(:I$OBJ_ID, 2) P
  JOIN VALL V1236 ON V1236.OBJ_ID = P.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  INTO :V$YEAR_ID, :V$CURRENT_YEAR, :V$YEAR_START;

  V$STATUS = (SELECT STATUS FROM OU_LICENCE_TYPE);

  -- !!! Доделать проверки уровня доступа для СПО

  TAG_NAME = 'year_id';
  VAL = V$YEAR_ID;
  SUSPEND;

  -- Класс, в котором учится сейчас
  TAG_NAME = 'grade_id';
  VAL = NULL;
  SELECT FIRST 1 M.GROUP_ID
  FROM PERSON_MOVEMENTS M
  JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID IN (9, 187)
  WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :I$OBJ_ID AND M.DATE_OUT IS NULL
  INTO :VAL;
  SUSPEND;

  -- Числится ли вообще в ОУ сейчас
  TAG_NAME = 'is_in_ou';
  IF(VAL IS NULL) THEN VAL = '0'; ELSE VAL = '1';
  SUSPEND;

  -- Класс, в котором был последним в текущем учебном году (и числится сейчас, либо уже выбыл)
  TAG_NAME = 'last_grade_id';
  VAL = NULL;
  SELECT FIRST 1 M.GROUP_ID
  FROM PERSON_MOVEMENTS M
  JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID IN (9, 187)
  WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :I$OBJ_ID AND M.DATE_IN >= DATEADD(-1 MONTH TO :V$YEAR_START)
  ORDER BY M.DATE_OUT DESC NULLS FIRST
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'years::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT DISTINCT M.YEAR_ID
    FROM VALM M
    WHERE M.IS_DEL = 0 AND M.PUPIL_ID = :I$OBJ_ID
    ORDER BY 1
    INTO :V$OBJ_ID
  DO
  BEGIN
    TAG_NAME = 'years:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'years:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'years:r:name';
    VAL = (SELECT VAL FROM LISTVAL_TEXT(:V$OBJ_ID));
    SUSPEND;
  END

  TAG_NAME = 'markstages::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT V.LISTVAL_ID, V.VAL
    FROM LISTVALS_LIST(220) V
    WHERE V.IS_DEL = 0
    ORDER BY 1
    INTO :V$OBJ_ID, :S
  DO
  BEGIN
    TAG_NAME = 'markstages:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'markstages:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'markstages:r:name';
    VAL = S;
    SUSPEND;
  END

  TAG_NAME = 'marktypes::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT V.LISTVAL_ID, V.VAL
    FROM LISTVALS_LIST(221) V
    WHERE V.IS_DEL = 0
    ORDER BY 1
    INTO :V$OBJ_ID, :S
  DO
  BEGIN
    TAG_NAME = 'marktypes:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'marktypes:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'marktypes:r:name';
    VAL = S;
    SUSPEND;
  END

  TAG_NAME = 'stages::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT V.LISTVAL_ID, V.VAL
    FROM OO_FILTRED_LIST(25) V
    WHERE V.PARENT_ID IN (2141, 2142) -- пока только школьные и СПО
    ORDER BY V.SORT_ORDER
    INTO :V$OBJ_ID, :S
  DO
  BEGIN
    TAG_NAME = 'stages:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'stages:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'stages:r:name';
    VAL = S;
    SUSPEND;
  END

  TAG_NAME = 'control_types::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT V.LISTVAL_ID, V.VAL
    FROM LISTVALS_LIST(246) V
    WHERE V.IS_DEL = 0
    ORDER BY V.SORT_ORDER
    INTO :V$OBJ_ID, :S
  DO
  BEGIN
    TAG_NAME = 'control_types:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'control_types:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'control_types:r:name';
    VAL = S;
    SUSPEND;
  END

  TAG_NAME = 'subjects::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT DISTINCT M.SUBJECT_ID
    FROM VALM M
    WHERE M.IS_DEL = 0 AND M.PUPIL_ID = :I$OBJ_ID
    ORDER BY 1
    INTO :V$OBJ_ID
  DO
  BEGIN
    TAG_NAME = 'subjects:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'subjects:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'subjects:r:name';
    VAL = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$OBJ_ID));
    SUSPEND;
  END

  TAG_NAME = 'marks::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT M.MARK_ID, M.YEAR_ID, M.STAGE_ID, M.SUBJECT_ID, M.TEACHER_ID, M.MARKTYPE_ID, M.MARKVAL_ID, M.MARK_DATE, V.VAL, COALESCE(M.IS_NATIVE, 1),
      M.IS_EXT, MC.CAPTION, M.SEQ_INDEX, M.PLAN_HOURS, M.CONTROL_TYPE_ID
    FROM VALM M
    LEFT JOIN LISTVAL_TEXT(M.MARKVAL_ID) V ON 1 = 1
    LEFT JOIN OBJECT_CAPTION_GET(M.MARK_TEACHER_ID) MC ON M.MARK_TEACHER_ID IS NOT NULL
    WHERE M.IS_DEL = 0 AND M.PUPIL_ID = :I$OBJ_ID
    ORDER BY M.YEAR_ID, M.SUBJECT_ID, M.MARKTYPE_ID
    INTO :V$OBJ_ID, :V$YEAR_ID, :V$STAGE_ID, :V$SUBJECT_ID, :V$TEACHER_ID, :V$MARKTYPE_ID, :V$MARKVAL_ID, :V$DT, :S, :V$NATIVE,
      :V$EXT, :S2, :V$SEQ_INDEX, :V$HOURS, :V$CT
  DO
  BEGIN
    TAG_NAME = 'marks:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'marks:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'marks:r:year';
    VAL = V$YEAR_ID;
    SUSPEND;
    TAG_NAME = 'marks:r:stage_id';
    VAL = V$STAGE_ID;
    SUSPEND;
    TAG_NAME = 'marks:r:subject_id';
    VAL = V$SUBJECT_ID;
    SUSPEND;
    TAG_NAME = 'marks:r:teacher_id';
    VAL = V$TEACHER_ID;
    SUSPEND;
    TAG_NAME = 'marks:r:mt_id';
    VAL = V$MARKTYPE_ID;
    SUSPEND;
    TAG_NAME = 'marks:r:val';
    VAL = V$MARKVAL_ID;
    SUSPEND;
    TAG_NAME = 'marks:r:text';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'marks:r:teacher_name';
    VAL = S2;
    SUSPEND;
    TAG_NAME = 'marks:r:date';
    VAL = (SELECT VAL FROM DATE2ISO(:V$DT, 0));
    SUSPEND;
    TAG_NAME = 'marks:r:is_native';
    VAL = V$NATIVE;
    SUSPEND;
    TAG_NAME = 'marks:r:is_adv';
    VAL = V$EXT;
    SUSPEND;
    TAG_NAME = 'marks:r:seq_index';
    VAL = V$SEQ_INDEX;
    SUSPEND;
    TAG_NAME = 'marks:r:hours';
    VAL = CAST(V$HOURS AS NUMERIC(18, 1));
    SUSPEND;
    TAG_NAME = 'marks:r:control_type_id';
    VAL = V$CT;
    SUSPEND;
  END

  -- Список предметов для плановой аттестации экстернатников, которые не попали в обычные отметки
  FOR
    SELECT V3142.LISTVAL_ID, V3143.VAL, V3144.VAL
    FROM LINKS L427
    JOIN VALL V3142 ON V3142.OBJ_ID = L427.OBJ_ID AND V3142.PARAM_ID = 3142 AND V3142.IS_DEL = 0
    JOIN VALR V3143 ON V3143.OBJ_ID = L427.OBJ_ID AND V3143.PARAM_ID = 3143 AND V3143.IS_DEL = 0
    JOIN VALD V3144 ON V3144.OBJ_ID = L427.OBJ_ID AND V3144.PARAM_ID = 3144 AND V3144.IS_DEL = 0
    WHERE L427.PARENT_ID = :I$OBJ_ID AND L427.OBJ_TYPE_ID = 427 AND L427.DATE_DEL IS NULL
    INTO :V$STAGE_ID, :V$SUBJECT_ID, :V$DT
  DO
  BEGIN
    -- В какой учебный год попадает аттестация ?
    V$YEAR_ID = NULL;
    SELECT FIRST 1 LV.LISTVAL_ID
    FROM LISTVALS LV
    WHERE LV.IS_DEL = 0 AND LV.LIST_ID = 29 AND :V$DT >= CAST(LV.TAG AS DATE) AND :V$DT < DATEADD(1 YEAR TO CAST(LV.TAG AS DATE))
    INTO :V$YEAR_ID;

    IF(NOT EXISTS(
      SELECT FIRST 1 1
      FROM VALM M
      WHERE M.IS_DEL = 0 AND M.PUPIL_ID = :I$OBJ_ID AND M.SUBJECT_ID = :V$SUBJECT_ID AND M.STAGE_ID = :V$STAGE_ID AND M.YEAR_ID = :V$YEAR_ID
    )) THEN
    BEGIN
      TAG_NAME = 'marks:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'marks:r:id';
      VAL = '*';
      SUSPEND;
      TAG_NAME = 'marks:r:year';
      VAL = V$YEAR_ID;
      SUSPEND;
      TAG_NAME = 'marks:r:stage_id';
      VAL = V$STAGE_ID;
      SUSPEND;
      TAG_NAME = 'marks:r:subject_id';
      VAL = V$SUBJECT_ID;
      SUSPEND;
      TAG_NAME = 'marks:r:teacher_id';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'marks:r:mt_id';
      VAL = 3011;
      SUSPEND;
      TAG_NAME = 'marks:r:val';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'marks:r:text';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'marks:r:date';
      VAL = (SELECT VAL FROM DATE2ISO(:V$DT, 0));
      SUSPEND;
    END
  END

  -- Курсовые работы
  TAG_NAME = 'cw::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L217.OBJ_ID, V1821.VAL, V1822.LISTVAL_ID, V1823.VAL, MC.VAL, TC.CAPTION, V3413.VAL
    FROM LINKS L217
    JOIN VALS V1821 ON V1821.OBJ_ID = L217.OBJ_ID AND V1821.PARAM_ID = 1821 AND V1821.IS_DEL = 0
    JOIN VALL V1822 ON V1822.OBJ_ID = L217.OBJ_ID AND V1822.PARAM_ID = 1822 AND V1822.IS_DEL = 0
    LEFT JOIN VALD V1823 ON V1823.OBJ_ID = L217.OBJ_ID AND V1823.PARAM_ID = 1823 AND V1823.IS_DEL = 0
    LEFT JOIN VALL V1825 ON V1825.OBJ_ID = L217.OBJ_ID AND V1825.PARAM_ID = 1825 AND V1825.IS_DEL = 0
    LEFT JOIN LISTVAL_TEXT(V1825.LISTVAL_ID) MC ON 1 = 1
    LEFT JOIN VALR V1824 ON V1824.OBJ_ID = L217.OBJ_ID AND V1824.PARAM_ID = 1824 AND V1824.IS_DEL = 0
    LEFT JOIN OBJECT_CAPTION_GET(V1824.VAL) TC ON V1824.VAL IS NOT NULL
    LEFT JOIN VALR V3413 ON V3413.OBJ_ID = L217.OBJ_ID AND V3413.PARAM_ID = 3413 AND V3413.IS_DEL = 0
    WHERE L217.PARENT_ID = :I$OBJ_ID AND L217.OBJ_TYPE_ID = 217 AND L217.DATE_DEL IS NULL
    ORDER BY V1822.LISTVAL_ID, V1823.VAL
    INTO :V$OBJ_ID, :S, :V$STAGE_ID, :V$DT, :S2, :S3, :V$SUBJECT_ID
  DO
  BEGIN
    TAG_NAME = 'cw:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'cw:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'cw:r:theme';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'cw:r:stage_id';
    VAL = V$STAGE_ID;
    SUSPEND;
    TAG_NAME = 'cw:r:date';
    VAL = (SELECT VAL FROM DATE2ISO(:V$DT));
    SUSPEND;
    TAG_NAME = 'cw:r:mark';
    VAL = S2;
    SUSPEND;
    TAG_NAME = 'cw:r:teacher_name';
    VAL = S3;
    SUSPEND;
    TAG_NAME = 'cw:r:subject_id';
    VAL = V$SUBJECT_ID;
    SUSPEND;
    TAG_NAME = 'cw:r:subject_name';
    IF(V$SUBJECT_ID IS NULL) THEN VAL = NULL; ELSE VAL = (SELECT VAL FROM VALS WHERE OBJ_ID = :V$SUBJECT_ID AND PARAM_ID = 1751 AND IS_DEL = 0);
    SUSPEND;
  END

  -- Практика
  TAG_NAME = 'practice::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L474.OBJ_ID, V3419.LISTVAL_ID, V3420.VAL, SC.VAL, TC.VAL, V3333.VAL, V3414.VAL, V3416.VAL, V3415.SVAL, V3417.SVAL, V3418.SVAL
    FROM LINKS L474
    LEFT JOIN VALL V3419 ON V3419.OBJ_ID = L474.OBJ_ID AND V3419.PARAM_ID = 3419 AND V3419.IS_DEL = 0
    LEFT JOIN LISTVAL_TEXT(V3419.LISTVAL_ID) SC ON V3419.LISTVAL_ID IS NOT NULL
    LEFT JOIN VALI V3420 ON V3420.OBJ_ID = L474.OBJ_ID AND V3420.PARAM_ID = 3420 AND V3420.IS_DEL = 0
    LEFT JOIN VALL V3334 ON V3334.OBJ_ID = L474.OBJ_ID AND V3334.PARAM_ID = 3334 AND V3334.IS_DEL = 0
    LEFT JOIN LISTVAL_TEXT(V3334.LISTVAL_ID) TC ON V3334.LISTVAL_ID IS NOT NULL
    LEFT JOIN VALS V3333 ON V3333.OBJ_ID = L474.OBJ_ID AND V3333.PARAM_ID = 3333 AND V3333.IS_DEL = 0
    LEFT JOIN VALF V3414 ON V3414.OBJ_ID = L474.OBJ_ID AND V3414.PARAM_ID = 3414 AND V3414.IS_DEL = 0
    LEFT JOIN VALD V3416 ON V3416.OBJ_ID = L474.OBJ_ID AND V3416.PARAM_ID = 3416 AND V3416.IS_DEL = 0
    LEFT JOIN VALS V3415 ON V3415.OBJ_ID = L474.OBJ_ID AND V3415.PARAM_ID = 3415 AND V3415.IS_DEL = 0
    LEFT JOIN VALS V3417 ON V3417.OBJ_ID = L474.OBJ_ID AND V3417.PARAM_ID = 3417 AND V3417.IS_DEL = 0
    LEFT JOIN VALS V3418 ON V3418.OBJ_ID = L474.OBJ_ID AND V3418.PARAM_ID = 3418 AND V3418.IS_DEL = 0
    WHERE L474.PARENT_ID = :I$OBJ_ID AND L474.OBJ_TYPE_ID = 474 AND L474.DATE_DEL IS NULL
    ORDER BY 2, 3, 8
    INTO :V$OBJ_ID, :V$STAGE_ID, :V$SEQ_INDEX, :S2, :S3, :S, :V$HOURS, :V$DT, :S4, :S5, :S6
  DO
  BEGIN
    TAG_NAME = 'practice:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'practice:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'practice:r:stage_id';
    VAL = V$STAGE_ID;
    SUSPEND;
    TAG_NAME = 'practice:r:stage_name';
    VAL = S2;
    SUSPEND;
    TAG_NAME = 'practice:r:sem_no';
    VAL = V$SEQ_INDEX;
    SUSPEND;
    TAG_NAME = 'practice:r:type_name';
    VAL = S3;
    SUSPEND;
    TAG_NAME = 'practice:r:subject_id';
    VAL = V$SUBJECT_ID;
    SUSPEND;
    TAG_NAME = 'practice:r:subject_name';
    IF(V$SUBJECT_ID IS NULL) THEN VAL = NULL; ELSE VAL = (SELECT VAL FROM VALS WHERE OBJ_ID = :V$SUBJECT_ID AND PARAM_ID = 1751 AND IS_DEL = 0);
    SUSPEND;
    TAG_NAME = 'practice:r:place_name';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'practice:r:hours';
    VAL = CAST(V$HOURS AS NUMERIC(18, 1));
    SUSPEND;
    TAG_NAME = 'practice:r:date';
    VAL = (SELECT RESULT FROM DATE2STR(:V$DT));
    SUSPEND;
    TAG_NAME = 'practice:r:mark';
    VAL = S4;
    SUSPEND;
    TAG_NAME = 'practice:r:resp_fio';
    VAL = S5;
    SUSPEND;
    TAG_NAME = 'practice:r:oo_resp_fio';
    VAL = S6;
    SUSPEND;
  END

  -- Демонстрационный экзамен
  TAG_NAME = 'dexam_level';
  VAL = NULL;
  SELECT C.VAL
  FROM VALL V3340
  LEFT JOIN LISTVAL_TEXT(V3340.LISTVAL_ID) C ON V3340.LISTVAL_ID IS NOT NULL
  WHERE V3340.OBJ_ID = :I$OBJ_ID AND V3340.PARAM_ID = 3340 AND V3340.IS_DEL = 0
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'dexam_mark';
  VAL = NULL;
  SELECT V3341.VAL
  FROM VALI V3341
  WHERE V3341.OBJ_ID = :I$OBJ_ID AND V3341.PARAM_ID = 3341 AND V3341.IS_DEL = 0
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'dexam_max';
  VAL = NULL;
  SELECT V3342.VAL
  FROM VALI V3342
  WHERE V3342.OBJ_ID = :I$OBJ_ID AND V3342.PARAM_ID = 3342 AND V3342.IS_DEL = 0
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'dexam_theme';
  VAL = NULL;
  SELECT V3360.VAL
  FROM VALI V3360
  WHERE V3360.OBJ_ID = :I$OBJ_ID AND V3360.PARAM_ID = 3360 AND V3360.IS_DEL = 0
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'dproj_theme';
  VAL = NULL;
  SELECT V3328.VAL
  FROM VALI V3328
  WHERE V3328.OBJ_ID = :I$OBJ_ID AND V3328.PARAM_ID = 3328 AND V3328.IS_DEL = 0
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'dexam_allow';
  VAL = NULL;
  SELECT C.RESULT
  FROM VALD V3424
  LEFT JOIN DATE2STR(V3424.VAL) C ON 1 = 1
  WHERE V3424.OBJ_ID = :I$OBJ_ID AND V3424.PARAM_ID = 3424 AND V3424.IS_DEL = 0
  INTO :VAL;
  SUSPEND;

  -- ???
  TAG_NAME = 'qual_exam';
  VAL = NULL;
  SELECT V2139.VAL
  FROM VALI V2139
  WHERE V2139.OBJ_ID = :I$OBJ_ID AND V2139.PARAM_ID = 2139 AND V2139.IS_DEL = 0
  INTO :VAL;
  SUSPEND;

  -- Госэкзамен
  TAG_NAME = 'gex::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L493.OBJ_ID, V3421.VAL, V1751.VAL, V3422.LISTVAL_ID, MC.VAL, V3423.VAL
    FROM LINKS L493
    JOIN VALR V3421 ON V3421.OBJ_ID = L493.OBJ_ID AND V3421.PARAM_ID = 3421 AND V3421.IS_DEL = 0
    JOIN VALS V1751 ON V1751.OBJ_ID = V3421.VAL AND V1751.PARAM_ID = 1751 AND V1751.IS_DEL = 0
    LEFT JOIN VALL V3422 ON V3422.OBJ_ID = L493.OBJ_ID AND V3422.PARAM_ID = 3422 AND V3422.IS_DEL = 0
    LEFT JOIN LISTVAL_TEXT(V3422.LISTVAL_ID) MC ON 1 = 1
    LEFT JOIN VALD V3423 ON V3423.OBJ_ID = L493.OBJ_ID AND V3423.PARAM_ID = 3423 AND V3423.IS_DEL = 0
    WHERE L493.PARENT_ID = :I$OBJ_ID AND L493.OBJ_TYPE_ID = 493 AND L493.DATE_DEL IS NULL
    ORDER BY 1
    INTO :V$OBJ_ID, :V$SUBJECT_ID, :S, :V$MARKVAL_ID, :S2, :V$DT
  DO
  BEGIN
    TAG_NAME = 'gex:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'gex:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'gex:r:subject_id';
    VAL = V$SUBJECT_ID;
    SUSPEND;
    TAG_NAME = 'gex:r:subject_name';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'gex:r:mark_id';
    VAL = V$MARKVAL_ID;
    SUSPEND;
    TAG_NAME = 'gex:r:mark_name';
    VAL = S2;
    SUSPEND;
    TAG_NAME = 'gex:r:date';
    VAL = (SELECT RESULT FROM DATE2STR(:V$DT));
    SUSPEND;
  END

  -- Данные по диплому СПО - тащим из базы DOC, только СПО
  IF(V$STATUS = 'C') THEN
  BEGIN
    SELECT MON$DATABASE_NAME FROM MON$DATABASE INTO :V;
    V = REPLACE(V, 'BASE.FDB', 'DOC.FDB');

    V$OBJ_ID = NULL;
    V$DT = NULL;
    V$DT2 = NULL;
    S2 = NULL;
    S3 = NULL;
    S4 = NULL;
    S5 = NULL;
    S = NULL;
    EXECUTE STATEMENT
      'SELECT FIRST 1 D.OBJ_ID, D.ACTION_DATE, B.BLANK_NUM, BP.SERIE, D.GAK_DATE, D.GAK_FIO, D.QUALIFICATION, D.SPO_REGNUM
      FROM DOCUMENTS D
      JOIN BLANKS B ON B.OBJ_ID = D.BLANK_ID AND B.STATE_ID = 1
      JOIN BLANK_PACKS BP ON BP.OBJ_ID = B.PACK_ID
      WHERE D.DATE_DEL IS NULL AND D.PERSON_ID = ' || I$OBJ_ID || ' AND D.STATE_ID = 1
      ORDER BY D.ACTION_DATE'
    ON EXTERNAL :V
    WITH COMMON TRANSACTION
    INTO :V$OBJ_ID, :V$DT, :S2, :S3, :V$DT2, :S4, :S, :S5;

    TAG_NAME = 'dpl_id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'dpl_date';
    VAL = (SELECT RESULT FROM DATE2STR(:V$DT));
    SUSPEND;
    TAG_NAME = 'dpl_num';
    VAL = S2;
    SUSPEND;
    TAG_NAME = 'dpl_serie';
    VAL = S3;
    SUSPEND;
    TAG_NAME = 'dpl_regnum';
    VAL = S5;
    SUSPEND;
    TAG_NAME = 'dpl_gak_date';
    VAL = (SELECT RESULT FROM DATE2STR(:V$DT2));
    SUSPEND;
    TAG_NAME = 'dpl_gak_fio';
    VAL = S4;
    SUSPEND;
    TAG_NAME = 'dpl_qual';
    VAL = S;
    SUSPEND;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FINALMARKS_DELETE (
    I$USER_ID VARCHAR(40),
    I$MARK_ID BIGINT)
AS
declare variable V$IS_DEL smallint;
declare variable V$IS_NATIVE smallint;
declare variable V$PUPIL_ID bigint;
declare variable V$YEAR_ID bigint;
declare variable V$SUBJECT_ID bigint;
declare variable V$STAGE_ID bigint;
declare variable V$MARKTYPE_ID bigint;
declare variable V$CURRENT_YEAR bigint;
begin

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  -- Удалять отметки может только завуч+
  IF(NOT EXISTS(
    SELECT FIRST 1 1
    FROM USERS U
    WHERE U.DATE_DEL IS NULL AND U.USER_ID = :I$USER_ID AND U.USER_TYPE IN (1, 5, 6)
  ))
  THEN EXCEPTION DATA_ERROR 'Удалять отметки может только администратор, директор или завуч';

  SELECT FIRST 1 M.IS_DEL, M.IS_NATIVE, M.PUPIL_ID, M.YEAR_ID, M.SUBJECT_ID, M.STAGE_ID, M.MARKTYPE_ID
  FROM VALM M
  WHERE M.MARK_ID = :I$MARK_ID
  INTO :V$IS_DEL, :V$IS_NATIVE, :V$PUPIL_ID, :V$YEAR_ID, :V$SUBJECT_ID, :V$STAGE_ID, :V$MARKTYPE_ID;

  IF(V$IS_DEL IS NULL OR V$IS_DEL <> 0) THEN EXCEPTION DATA_ERROR 'Отметка не найдена или была удалена';

  SELECT FIRST 1 V1236.LISTVAL_ID
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$CURRENT_YEAR;

  -- Отметки текущего года можно удалять только для чужих школ или для экстернатов
  IF(V$CURRENT_YEAR = V$YEAR_ID AND V$IS_NATIVE = 1) THEN
  BEGIN

  END

  UPDATE VALM
  SET IS_DEL = 1, USER_DEL = :I$USER_ID
  WHERE MARK_ID = :I$MARK_ID;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FINALMARKS_GET (
    I$USER_ID VARCHAR(40),
    I$MARK_ID BIGINT,
    I$PERSON_ID BIGINT,
    I$YEAR_ID BIGINT,
    I$SUBJECT_ID BIGINT,
    I$STAGE_ID BIGINT,
    I$MT_ID BIGINT)
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(1000))
AS
declare variable V$OU_STATUS char(1);
declare variable V$OU_LEVEL smallint;
declare variable V$IS_NATIVE smallint;
declare variable V$PUPIL_ID bigint;
declare variable V$YEAR_ID bigint;
declare variable V$SUBJECT_ID bigint;
declare variable V$STAGE_ID bigint;
declare variable V$MARKTYPE_ID bigint;
declare variable V$TEACHER_ID bigint;
declare variable V$MARKVAL_ID bigint;
declare variable V$MARK_DATE date;
declare variable V$CURRENT_YEAR integer;
declare variable V$ID bigint;
declare variable S varchar(1000);
declare variable N integer;
declare variable V$YEAR_START date;
declare variable V$SORT_ORDER bigint;
declare variable V$OU_ID bigint;
declare variable V$HAS_OO smallint;
declare variable V$HAS_SPO smallint;
declare variable V$HAS_PO smallint;
begin

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  SELECT KEY_VAL FROM KEYS WHERE KEY_CODE = 'LEVEL' INTO :V$OU_LEVEL;
  V$OU_STATUS = (SELECT STATUS FROM OU_LICENCE_TYPE);

  SELECT FIRST 1 M.IS_NATIVE, M.PUPIL_ID, M.YEAR_ID, M.SUBJECT_ID, M.STAGE_ID, M.MARKTYPE_ID, M.TEACHER_ID, M.MARKVAL_ID, M.MARK_DATE
  FROM VALM M
  WHERE M.MARK_ID = :I$MARK_ID AND M.IS_DEL = 0
  INTO :V$IS_NATIVE, :V$PUPIL_ID, :V$YEAR_ID, :V$SUBJECT_ID, :V$STAGE_ID, :V$MARKTYPE_ID, :V$TEACHER_ID, :V$MARKVAL_ID, :V$MARK_DATE;

  IF(I$MARK_ID IS NOT NULL) THEN
  BEGIN
    IF(V$PUPIL_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Отметка не найдена или была удалена';
  END

  SELECT FIRST 1 P.OBJ_ID
  FROM OBJECT_PARENTS_GET(:I$PERSON_ID, 2) P
  INTO :V$OU_ID;

  SELECT FIRST 1 LV.COST, CAST(LV.TAG AS DATE)
  FROM VALL V1236
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE V1236.OBJ_ID = :V$OU_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  INTO :V$CURRENT_YEAR, :V$YEAR_START;

  V$HAS_OO = 0;
  V$HAS_SPO = 0;
  V$HAS_PO = 0;
  SELECT FIRST 1 1
  FROM LINKS L472
  JOIN VALL V3327 ON V3327.OBJ_ID = L472.OBJ_ID AND V3327.PARAM_ID = 3327 AND V3327.IS_DEL = 0 AND V3327.LISTVAL_ID IN (22, 26, 27)
  WHERE L472.PARENT_ID = :V$OU_ID AND L472.OBJ_TYPE_ID = 472 AND L472.DATE_DEL IS NULL
  INTO :V$HAS_OO;

  SELECT FIRST 1 1
  FROM LINKS L472
  JOIN VALL V3327 ON V3327.OBJ_ID = L472.OBJ_ID AND V3327.PARAM_ID = 3327 AND V3327.IS_DEL = 0 AND V3327.LISTVAL_ID IN (28, 29, 13129)
  WHERE L472.PARENT_ID = :V$OU_ID AND L472.OBJ_TYPE_ID = 472 AND L472.DATE_DEL IS NULL
  INTO :V$HAS_SPO;

  SELECT FIRST 1 1
  FROM LINKS L472
  JOIN VALL V3327 ON V3327.OBJ_ID = L472.OBJ_ID AND V3327.PARAM_ID = 3327 AND V3327.IS_DEL = 0 AND V3327.LISTVAL_ID IN (13129, 13131)
  WHERE L472.PARENT_ID = :V$OU_ID AND L472.OBJ_TYPE_ID = 472 AND L472.DATE_DEL IS NULL
  INTO :V$HAS_PO;

  TAG_NAME = 'obj_id';
  VAL = I$MARK_ID;
  SUSPEND;

  TAG_NAME = 'date';
  VAL = (SELECT VAL FROM DATE2ISO(:V$MARK_DATE, 0));
  SUSPEND;

  TAG_NAME = 'is_native';
  VAL = V$IS_NATIVE;
  SUSPEND;

  TAG_NAME = 'person_id';
  VAL = COALESCE(V$PUPIL_ID, I$PERSON_ID);
  SUSPEND;

  TAG_NAME = 'year_id:selection::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT LV.LISTVAL_ID, R.VAL
    FROM LISTVALS LV
    JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
    WHERE LV.LIST_ID = 29 AND LV.IS_DEL = 0 AND LV.COST <= :V$CURRENT_YEAR
    ORDER BY LV.SORT_ORDER
    INTO :V$ID, :S
  DO
  BEGIN
    TAG_NAME = 'year_id:selection:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'year_id:selection:r:id';
    VAL = V$ID;
    SUSPEND;
    TAG_NAME = 'year_id:selection:r:value';
    VAL = S;
    SUSPEND;
  END
  TAG_NAME = 'year_id:values:value';
  VAL = COALESCE(V$YEAR_ID, I$YEAR_ID);
  SUSPEND;

  TAG_NAME = 'subject_id:selection::json&colon;array';
  VAL = 1;
  SUSPEND;
  V$SUBJECT_ID = COALESCE(V$SUBJECT_ID, I$SUBJECT_ID);
  FOR
    -- Для уровня школы показываем список, для уровня район-регион только конкретный
    SELECT :V$SUBJECT_ID, C.CAPTION, 0
    FROM OBJECT_CAPTION_GET(:V$SUBJECT_ID) C
    WHERE :V$SUBJECT_ID IS NOT NULL
    -- Предметы для школ
    UNION
    SELECT L51.OBJ_ID, C.CAPTION, 1
    FROM LINKS L51
    LEFT JOIN OBJECT_CAPTION_GET(L51.OBJ_ID) C ON 1 = 1
    WHERE L51.PARENT_TYPE_ID = 301 AND L51.OBJ_TYPE_ID = 51 AND L51.DATE_DEL IS NULL AND :V$OU_LEVEL = 1 AND :V$OU_STATUS IN ('O', 'S')
    -- Дисциплины для колледжей
    UNION
    SELECT L197.OBJ_ID, C.CAPTION, 2
    FROM LINKS L197
    LEFT JOIN OBJECT_CAPTION_GET(L197.OBJ_ID) C ON 1 = 1
    WHERE L197.PARENT_TYPE_ID = 193 AND L197.OBJ_TYPE_ID = 197 AND L197.DATE_DEL IS NULL AND :V$OU_LEVEL = 1 AND :V$OU_STATUS IN ('C', 'S')
    ORDER BY 3, 2
    INTO :V$ID, :S, :N
  DO
  BEGIN
    TAG_NAME = 'subject_id:selection:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'subject_id:selection:r:id';
    VAL = V$ID;
    SUSPEND;
    TAG_NAME = 'subject_id:selection:r:value';
    VAL = S;
    SUSPEND;
  END
  TAG_NAME = 'subject_id:values:value';
  VAL = COALESCE(V$SUBJECT_ID, I$SUBJECT_ID);
  SUSPEND;

  TAG_NAME = 'stage_id:selection::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    -- Старая схема выборки
    SELECT LV.LISTVAL_ID, LV.VAL, LV.COST, LV.SORT_ORDER
    FROM OO_FILTRED_LIST(25) LV
    WHERE LV.PARENT_ID IN (2141) AND :V$OU_STATUS = 'O'
    -- Новая схема выборки, мультипараграф
    UNION
    SELECT LV.LISTVAL_ID, C.VAL, LV.COST, LV.SORT_ORDER
    FROM LISTVALS LV
    LEFT JOIN LISTVAL_TEXT(LV.LISTVAL_ID) C ON 1 = 1
    WHERE LV.LIST_ID = 25 AND LV.IS_DEL = 0 AND :V$OU_STATUS = 'S'
    AND (LV.LISTVAL_ID = :V$STAGE_ID
      OR (LV.PARENT_ID = 2141 AND :V$HAS_OO = 1)
      OR (LV.PARENT_ID = 2142 AND :V$HAS_SPO = 1 AND LV.LISTVAL_ID <> 13145)
      OR (LV.LISTVAL_ID = 13145 AND :V$HAS_PO = 1) -- весь курс обучения - только в ДПО или курсах
    )
    ORDER BY 4
    INTO :V$ID, :S, :N, :V$SORT_ORDER
  DO
  BEGIN
    TAG_NAME = 'stage_id:selection:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'stage_id:selection:r:id';
    VAL = V$ID;
    SUSPEND;
    TAG_NAME = 'stage_id:selection:r:value';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'stage_id:selection:r:subset_id';
    VAL = N;
    SUSPEND;
 END
  TAG_NAME = 'stage_id:values:value';
  VAL = COALESCE(V$STAGE_ID, I$STAGE_ID);
  SUSPEND;

  -- В какой параллели находится сейчас ? нужно для расчета этапа при смене учебного года
  TAG_NAME = 'current_stage_id';
  VAL = NULL;
  SELECT FIRST 1 V49.LISTVAL_ID
  FROM LINKS LP9
  JOIN LINKS LP8 ON LP8.OBJ_ID = LP9.PARENT_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
  JOIN VALL V49 ON V49.OBJ_ID = LP8.PARENT_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
  WHERE LP9.OBJ_ID = :I$PERSON_ID AND LP9.PARENT_TYPE_ID IN (9, 125, 187) AND LP9.DATE_DEL IS NULL
  INTO :VAL;
  SUSPEND;

  -- Был ли в обычном классе в текущем учебном году ?
  TAG_NAME = 'was_in_class';
  VAL = 0;
  SELECT FIRST 1 1
  FROM PERSON_MOVEMENTS M
  JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
  WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :I$PERSON_ID AND M.DATE_IN >= DATEADD(-1 MONTH TO :V$YEAR_START)
    AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :V$YEAR_START)
  INTO :VAL;
  SUSPEND;

  -- Числится ли в экстернате в данный момент ? нужно для разрешения выбора предметов
  TAG_NAME = 'is_in_ext';
  VAL = 0;
  SELECT FIRST 1 1
  FROM LINKS LP187
  WHERE LP187.OBJ_ID = :I$PERSON_ID AND LP187.PARENT_TYPE_ID = 187 AND LP187.DATE_DEL IS NULL
  INTO :VAL;
  SUSPEND;

  -- Класс, в котором учится сейчас
  TAG_NAME = 'grade_id';
  VAL = NULL;
  SELECT FIRST 1 M.GROUP_ID
  FROM PERSON_MOVEMENTS M
  JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID IN (9, 187)
  WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :I$PERSON_ID AND M.DATE_OUT IS NULL
  INTO :VAL;
  SUSPEND;

  -- Числится ли вообще в ОУ сейчас
  TAG_NAME = 'is_in_ou';
  IF(VAL IS NULL) THEN VAL = '0'; ELSE VAL = '1';
  SUSPEND;

  -- Класс, в котором был последним в текущем учебном году (и числится сейчас, либо уже выбыл)
  TAG_NAME = 'last_grade_id';
  VAL = NULL;
  SELECT FIRST 1 M.GROUP_ID
  FROM PERSON_MOVEMENTS M
  JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID IN (9, 187)
  WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :I$PERSON_ID AND M.DATE_IN >= DATEADD(-1 MONTH TO :V$YEAR_START)
  ORDER BY M.DATE_OUT DESC NULLS FIRST
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'mt_id:selection::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    -- Старая схема выборки
    SELECT LV.LISTVAL_ID, LV.VAL, LV.SORT_ORDER
    FROM OO_FILTRED_LIST(220) LV
    WHERE LV.LISTVAL_ID <> 3001 AND :V$OU_STATUS = 'O'
    -- Новая схема выборки
    UNION
    SELECT LV.LISTVAL_ID, C.VAL, LV.SORT_ORDER
    FROM LISTVALS LV
    LEFT JOIN LISTVAL_TEXT(LV.LISTVAL_ID) C ON 1 = 1
    WHERE LV.LIST_ID = 220 AND LV.IS_DEL = 0 AND :V$OU_STATUS = 'S'
    AND (LV.LISTVAL_ID = COALESCE(:V$MARKTYPE_ID, :I$MT_ID)
      OR (LV."FILTER" LIKE '%GOU%' AND :V$HAS_OO = 1)
      OR (LV."FILTER" LIKE '%COLLEGE%' AND :V$HAS_SPO = 1 AND C.VAL NOT LIKE '%Модуль%') -- тут без модулей
      OR (LV."FILTER" LIKE '%COLLEGE%' AND :V$HAS_PO = 1 AND (C.VAL LIKE '%Модуль%' OR LV.COST BETWEEN 120 AND 150)) -- модули + итоги
    )
    ORDER BY 3
    INTO :V$ID, :S, :V$SORT_ORDER
  DO
  BEGIN
    TAG_NAME = 'mt_id:selection:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'mt_id:selection:r:id';
    VAL = V$ID;
    SUSPEND;
    TAG_NAME = 'mt_id:selection:r:value';
    VAL = S;
    SUSPEND;
  END
  TAG_NAME = 'mt_id:values:value';
  VAL = COALESCE(V$MARKTYPE_ID, I$MT_ID);
  SUSPEND;

  TAG_NAME = 'val:selection::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT LV.LISTVAL_ID, LV.VAL
    FROM OO_FILTRED_LIST(221) LV
    ORDER BY LV.SORT_ORDER
    INTO :V$ID, :S
  DO
  BEGIN
    TAG_NAME = 'val:selection:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'val:selection:r:id';
    VAL = V$ID;
    SUSPEND;
    TAG_NAME = 'val:selection:r:value';
    VAL = S;
    SUSPEND;
  END
  TAG_NAME = 'val:values:value';
  VAL = V$MARKVAL_ID;
  SUSPEND;

  TAG_NAME = 'teacher_id';
  VAL = V$TEACHER_ID;
  SUSPEND;

  TAG_NAME = 'teacher_name';
  IF(V$TEACHER_ID IS NULL) THEN VAL = NULL;
  ELSE VAL = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$TEACHER_ID));
  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FINALMARKS_MENU (
    I$USER_ID VARCHAR(40),
    I$OBJ_ID BIGINT,
    I$WHERE SMALLINT = 0)
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$OU_LEVEL SMALLINT;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$TYPE_ID BIGINT;
DECLARE VARIABLE V$ROOT_TYPE BIGINT;
DECLARE VARIABLE V$ROLE BIGINT;
DECLARE VARIABLE V$TEACHER_ID BIGINT;
DECLARE VARIABLE V$STATUS VARCHAR(1);
DECLARE VARIABLE V$RESP_ID BIGINT;
DECLARE VARIABLE V$ATT_RO SMALLINT;
DECLARE VARIABLE V$OK SMALLINT;
DECLARE VARIABLE V$AREA_ID BIGINT;
DECLARE VARIABLE V$LEVEL_ID BIGINT;
DECLARE VARIABLE S VARCHAR(1000);
begin

  -- I$WHERE - 0 для школьных итоговых, 1 для СПО
  IF(I$WHERE IS NULL) THEN I$WHERE = 0;

  SELECT KEY_VAL FROM KEYS WHERE KEY_CODE = 'LEVEL' INTO :V$OU_LEVEL;

  TAG_NAME = 'db_level';
  VAL = V$OU_LEVEL;
  SUSPEND;

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  SELECT FIRST 1 U.USER_TYPE, U.OBJ_ID
  FROM USERS U
  WHERE U.USER_ID = :I$USER_ID AND U.DATE_DEL IS NULL
  INTO :V$ROLE, :V$TEACHER_ID;

  -- Аттестация в СПО
  SELECT FIRST 1 L.READ_ONLY
  FROM LUSERS L
  WHERE L.USER_ID = :I$USER_ID AND L.LEVEL_ID IN (530)
  INTO :V$ATT_RO;

  -- Ограничение по доступу к уровню района или учебного коллектива
  SELECT FIRST 1 L.ROOT_OBJ_ID
  FROM LUSERS L
  WHERE L.USER_ID = :I$USER_ID AND L.ROOT_OBJ_ID IS NOT NULL
  INTO :V$AREA_ID;

  V$STATUS = (SELECT STATUS FROM OU_LICENCE_TYPE);

  TAG_NAME = 'items::json&colon;array';
  VAL = 1;
  SUSPEND;

  -- Ограничение по дереву - может быть и для ОУ, и для региона
  -- надо проверить что ограничение вообще живо
  IF(V$AREA_ID IS NOT NULL) THEN
  BEGIN
    IF(NOT EXISTS(
      SELECT FIRST 1 1
      FROM LINKS LP
      WHERE LP.OBJ_ID = :V$AREA_ID AND LP.PARENT_TYPE_ID IN (112, 8) AND LP.DATE_DEL IS NULL
    ))
    THEN
      EXCEPTION DATA_ERROR 'Указанный уровень доступа для пользователя был утрачен, обратитесь к администратору';

    IF(I$OBJ_ID IS NULL) THEN
    BEGIN
      -- Сразу отдаем ограниченный уровень
      I$OBJ_ID = V$AREA_ID;
    END
    ELSE
    BEGIN
      -- Проверяем что кто-то руками не запросил неположенное
      SELECT TYPE_ID
      FROM OBJECTS
      WHERE OBJ_ID = :I$OBJ_ID
      INTO :V$TYPE_ID;

      -- TODO
    END
  END

  -- Когда не указан корень - выбираем актуальный
  IF(I$OBJ_ID IS NULL) THEN
  BEGIN
    SELECT FIRST 1 L.OBJ_ID, L.OBJ_TYPE_ID
    FROM LINKS L
    WHERE L.PARENT_ID IS NULL AND L.OBJ_TYPE_ID IN (112, 111, 2) AND L.DATE_DEL IS NULL
    INTO :I$OBJ_ID, :V$ROOT_TYPE;
  END
  ELSE
  BEGIN
    SELECT TYPE_ID
    FROM OBJECTS
    WHERE OBJ_ID = :I$OBJ_ID
    INTO :V$ROOT_TYPE;
  END

  -- Выбираем список дочерних папок - районы, школы
  FOR
    SELECT L.OBJ_ID, L.OBJ_TYPE_ID, C.CAPTION
    FROM LINKS L
    LEFT JOIN OBJECT_CAPTION_GET(L.OBJ_ID) C ON 1 = 1
    WHERE L.PARENT_ID = :I$OBJ_ID AND L.OBJ_TYPE_ID IN (111, 2) AND L.DATE_DEL IS NULL
    ORDER BY 3
    INTO :V$OBJ_ID, :V$TYPE_ID, :S
  DO
  BEGIN
    TAG_NAME = 'items:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'items:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'items:r:type_id';
    VAL = V$TYPE_ID;
    SUSPEND;
    TAG_NAME = 'items:r:name';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'items:r:has_children';
    VAL = '0';
    IF(V$TYPE_ID = 2) THEN
      SELECT FIRST 1 1
      FROM LINKS L7
      JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 187) AND L9.DATE_DEL IS NULL
      WHERE L7.PARENT_ID = :V$OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
      UNION
      SELECT FIRST 1 1
      FROM LINKS L78
      JOIN LINKS L8X ON L8X.PARENT_ID = L78.OBJ_ID AND L8X.OBJ_TYPE_ID IN (81, 82, 83) AND L8X.DATE_DEL IS NULL
      WHERE L78.PARENT_ID = :V$OBJ_ID AND L78.OBJ_TYPE_ID = 78 AND L78.DATE_DEL IS NULL
      INTO :VAL;
    ELSE
      SELECT FIRST 1 1
      FROM LINKS L
      WHERE L.PARENT_ID = :V$OBJ_ID AND L.OBJ_TYPE_ID IN (111, 2, 10) AND L.DATE_DEL IS NULL
      INTO :VAL;
    SUSPEND;
  END

  IF(V$ROOT_TYPE = 2) THEN
  BEGIN
    -- Классы, классы-экстернаты
    -- В СПО скрываем группы, к которым человеку не положено иметь доступ
    FOR
      SELECT L9.OBJ_ID, L9.OBJ_TYPE_ID, C.CAPTION, V53.VAL, V43.LISTVAL_ID
      FROM LINKS L7
      JOIN VALL V43 ON V43.OBJ_ID = L7.OBJ_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0
      JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
      JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
      JOIN LISTVALS LV ON LV.LISTVAL_ID = V49.LISTVAL_ID
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 187) AND L9.DATE_DEL IS NULL
      LEFT JOIN VALR V53 ON V53.OBJ_ID = L9.OBJ_ID AND V53.PARAM_ID = 53 AND V53.IS_DEL = 0
      LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C ON 1 = 1
      WHERE L7.PARENT_ID = :I$OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
      AND (
        (:I$WHERE = 0 AND V43.LISTVAL_ID IN (22, 26, 27)) OR
        (:I$WHERE = 1 AND V43.LISTVAL_ID IN (28, 29, 13131))
      )
      ORDER BY LV.COST, 3
      INTO :V$OBJ_ID, :V$TYPE_ID, :S, :V$RESP_ID, :V$LEVEL_ID
    DO
    BEGIN
      V$OK = 1;

      -- СПО
      IF(V$STATUS = 'C' OR V$LEVEL_ID IN (28, 29, 13131)) THEN
      BEGIN
        -- Если человек не является ответственным, и имеет доступ RO к аттестации (не-админ)
        IF(V$ATT_RO = 1 AND V$TEACHER_ID IS NOT NULL AND V$TEACHER_ID <> COALESCE(V$RESP_ID, 0)) THEN
        BEGIN
          -- Не показываем, если нет открытых аттестаций хотя бы для одного студента
          IF(NOT EXISTS(
            SELECT FIRST 1 1
            FROM LINKS L10
            JOIN ATT_REGISTER_STDS S ON S.DATE_DEL IS NULL AND S.PERSON_ID = L10.OBJ_ID
            JOIN ATT_REGISTER R ON R.DATE_DEL IS NULL AND R.STATE_ID IN (0, 1) AND R.OBJ_ID = S.ATT_ID
            JOIN ATT_REGISTER_STUFF F ON F.DATE_DEL IS NULL AND F.ATT_ID = R.OBJ_ID AND F.PERSON_ID = :V$TEACHER_ID
            WHERE L10.PARENT_ID = :V$OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
          ))
          THEN
            V$OK = 0;
        END
      END

      IF(V$OK = 1) THEN
      BEGIN
        TAG_NAME = 'items:r';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'items:r:id';
        VAL = V$OBJ_ID;
        SUSPEND;
        TAG_NAME = 'items:r:type_id';
        VAL = V$TYPE_ID;
        SUSPEND;
        TAG_NAME = 'items:r:name';
        VAL = S;
        SUSPEND;
        TAG_NAME = 'items:r:has_children';
        VAL = '0';
        SELECT FIRST 1 1
        FROM LINKS L
        WHERE L.PARENT_ID = :V$OBJ_ID AND L.OBJ_TYPE_ID = 10 AND L.DATE_DEL IS NULL
        INTO :VAL;
        SUSPEND;
      END
    END
    -- Выбывшие и окончившие
    -- Не показываем для роли "преподаватель" в СПО, кроме случая когда у человека полный доступ
    IF(V$ROLE NOT IN (9, 12, 22) OR V$ATT_RO = 0 OR V$STATUS <> 'C' OR V$LEVEL_ID NOT IN (28, 29, 13131) OR V$OU_LEVEL > 1) THEN
    FOR
      SELECT L8X.OBJ_ID, L8X.OBJ_TYPE_ID, C.CAPTION
      FROM LINKS L78
      JOIN LINKS L8X ON L8X.PARENT_ID = L78.OBJ_ID AND L8X.OBJ_TYPE_ID IN (81, 82, 83) AND L8X.DATE_DEL IS NULL
      LEFT JOIN OBJECT_CAPTION_GET(L8X.OBJ_ID) C ON 1 = 1
      WHERE L78.PARENT_ID = :I$OBJ_ID AND L78.OBJ_TYPE_ID = 78 AND L78.DATE_DEL IS NULL
      ORDER BY L8X.OBJ_TYPE_ID, 3
      INTO :V$OBJ_ID, :V$TYPE_ID, :S
    DO
    BEGIN
      TAG_NAME = 'items:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'items:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'items:r:type_id';
      VAL = V$TYPE_ID;
      SUSPEND;
      TAG_NAME = 'items:r:name';
      VAL = S;
      SUSPEND;
      TAG_NAME = 'items:r:has_children';
      VAL = '0';
      SELECT FIRST 1 1
      FROM LINKS L
      WHERE L.PARENT_ID = :V$OBJ_ID AND L.OBJ_TYPE_ID = 10 AND L.DATE_DEL IS NULL
      INTO :VAL;
      SUSPEND;
      SELECT FIRST 1 C.VAL
      FROM PERSON_MOVEMENTS M
      JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID IN (9, 187)
      LEFT JOIN DATE2ISO(M.DATE_OUT, 0) C ON 1 = 1
      WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :V$OBJ_ID
      ORDER BY M.DATE_OUT DESC NULLS FIRST
      INTO :VAL;
      SUSPEND;
    END
  END

  -- Класс или экстернат - выбираем по реестру движения
  IF(V$ROOT_TYPE IN (9, 187)) THEN
  BEGIN
    V$OK = 1;

    -- СПО
    IF(V$STATUS = 'C' OR I$WHERE = 1) THEN
    BEGIN
      -- Если человек не является ответственным, и имеет доступ RO к аттестации (не-админ)
      IF(V$ATT_RO = 1 AND V$TEACHER_ID IS NOT NULL AND V$TEACHER_ID <> COALESCE(V$RESP_ID, 0)) THEN
      BEGIN
        -- Не показываем, если нет открытых аттестаций хотя бы для одного студента
        IF(NOT EXISTS(
          SELECT FIRST 1 1
          FROM LINKS L10
          JOIN ATT_REGISTER_STDS S ON S.DATE_DEL IS NULL AND S.PERSON_ID = L10.OBJ_ID
          JOIN ATT_REGISTER R ON R.DATE_DEL IS NULL AND R.STATE_ID IN (0, 1) AND R.OBJ_ID = S.ATT_ID
          JOIN ATT_REGISTER_STUFF F ON F.DATE_DEL IS NULL AND F.ATT_ID = R.OBJ_ID AND F.PERSON_ID = :V$TEACHER_ID
          WHERE L10.PARENT_ID = :I$OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        ))
        THEN
          V$OK = 0;
      END
    END

    IF(V$OK = 1) THEN
    FOR
      SELECT DISTINCT M.PERSON_ID, 10, C.CAPTION
      FROM PERSON_MOVEMENTS M
      LEFT JOIN OBJECT_CAPTION_GET(M.PERSON_ID, 23) C ON 1 = 1
      WHERE M.DATE_DEL IS NULL AND M.GROUP_ID = :I$OBJ_ID
      ORDER BY 3
      INTO :V$OBJ_ID, :V$TYPE_ID, :S
    DO
    BEGIN
      TAG_NAME = 'items:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'items:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'items:r:type_id';
      VAL = V$TYPE_ID;
      SUSPEND;
      TAG_NAME = 'items:r:name';
      VAL = S;
      SUSPEND;
      TAG_NAME = 'items:r:has_children';
      VAL = '0';
      SUSPEND;
      TAG_NAME = 'items:r:leave_date';
      VAL = NULL;
      SELECT FIRST 1 C.VAL
      FROM PERSON_MOVEMENTS M
      LEFT JOIN DATE2ISO(M.DATE_OUT, 0) C ON 1 = 1
      WHERE M.DATE_DEL IS NULL AND M.GROUP_ID = :I$OBJ_ID AND M.PERSON_ID = :V$OBJ_ID
      ORDER BY M.DATE_OUT DESC NULLS FIRST
      INTO :VAL;
      SUSPEND;
    END
  END

  -- Выбывших показывать ограниченно
  IF(V$ROOT_TYPE IN (81, 82, 83)) THEN
  IF(V$ROLE NOT IN (9, 12, 22) OR V$ATT_RO = 0 OR V$STATUS <> 'C' OR I$WHERE <> 0 OR V$OU_LEVEL > 1) THEN
  BEGIN
    FOR
      SELECT DISTINCT L.OBJ_ID, L.OBJ_TYPE_ID, C.CAPTION
      FROM LINKS L
      LEFT JOIN OBJECT_CAPTION_GET(L.OBJ_ID, 23) C ON 1 = 1
      WHERE L.DATE_DEL IS NULL AND L.PARENT_ID = :I$OBJ_ID AND L.OBJ_TYPE_ID = 10
      ORDER BY 3
      INTO :V$OBJ_ID, :V$TYPE_ID, :S
    DO
    BEGIN
      TAG_NAME = 'items:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'items:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'items:r:type_id';
      VAL = V$TYPE_ID;
      SUSPEND;
      TAG_NAME = 'items:r:name';
      VAL = S;
      SUSPEND;
      TAG_NAME = 'items:r:has_children';
      VAL = '0';
      SUSPEND;
      TAG_NAME = 'items:r:leave_date';
      VAL = NULL;
      SUSPEND;
    END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FINALMARKS_PM (
    I$OBJ_ID BIGINT,
    I$DATE DATE)
RETURNS (
    PERSON_ID BIGINT,
    CAPTION VARCHAR(1000),
    PERIOD_ID BIGINT,
    PERIOD_NAME VARCHAR(100),
    SUBJECT_ID BIGINT,
    MARK_VAL VARCHAR(100),
    MARK_YEAR INTEGER,
    LEAVE_TEXT VARCHAR(1000),
    STAGE_NAME VARCHAR(200))
AS
declare variable V$TYPE_ID bigint;
declare variable V$YEAR_ID bigint;
declare variable V$YSTART date;
declare variable V$LD date;
declare variable V$LDO date;
declare variable V$LDN varchar(200);
declare variable N integer;
begin

  -- На входе может быть комбинация класс+дата или ученик+дата или ученик без даты
  SELECT TYPE_ID
  FROM OBJECTS
  WHERE OBJ_ID = :I$OBJ_ID
  INTO :V$TYPE_ID;

  -- Если дата не указана - V$YEAR_ID будет NULL
  SELECT FIRST 1 LV.LISTVAL_ID
  FROM LISTVALS LV
  WHERE LV.LIST_ID = 29 AND LV.IS_DEL = 0 AND :I$DATE >= CAST(LV.TAG AS DATE)
  ORDER BY 1 DESC
  INTO :V$YEAR_ID;

  IF(EXTRACT(MONTH FROM I$DATE) >= 9) THEN V$YSTART = '01.09.' || EXTRACT(YEAR FROM I$DATE);
  ELSE V$YSTART = '01.09.' || (EXTRACT(YEAR FROM I$DATE) - 1);

  FOR
    SELECT PL.PERSON_ID, C.CAPTION
    FROM (
      SELECT DISTINCT M.PERSON_ID
      FROM PERSON_MOVEMENTS M
      WHERE M.DATE_DEL IS NULL AND M.GROUP_ID = :I$OBJ_ID AND M.DATE_IN <= :I$DATE AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :V$YSTART)
      UNION
      SELECT :I$OBJ_ID
      FROM RDB$DATABASE
      WHERE :V$TYPE_ID = 10
    ) PL
    LEFT JOIN OBJECT_CAPTION_GET(PL.PERSON_ID, 23) C ON 1 = 1
    INTO :PERSON_ID, :CAPTION
  DO
  BEGIN
    N = 0;

    -- Действующий или выбывший ученик ?
    LEAVE_TEXT = NULL;
    V$LD = NULL;
    V$LDO = NULL;
    V$LDN = NULL;
    SELECT M.DATE_OUT, M.ORDER_DATE_OUT, M.ORDER_NUM_OUT
    FROM PERSON_MOVEMENTS M
    LEFT JOIN PERSON_MOVEMENTS M2 ON M2.DATE_DEL IS NULL AND M2.PERSON_ID = M.PERSON_ID AND M2.GROUP_ID = M.GROUP_ID
      AND M2.DATE_IN <= :I$DATE AND M2.DATE_IN > M.DATE_IN AND (M2.DATE_OUT IS NULL OR M2.DATE_OUT > M.DATE_IN)
    WHERE M.DATE_DEL IS NULL AND M.GROUP_ID = :I$OBJ_ID AND M.PERSON_ID = :PERSON_ID AND M.DATE_IN <= :I$DATE AND M.DATE_OUT >= :V$YSTART AND M.DATE_OUT < :I$DATE
      AND M2.OBJ_ID IS NULL
    INTO :V$LD, :V$LDO, :V$LDN;

    IF(V$LD IS NOT NULL) THEN BEGIN
      LEAVE_TEXT = 'выбыл ' || (SELECT RESULT FROM DATE2STR(:V$LD)) || 'г.';
      IF(V$LDO IS NOT NULL AND V$LDN IS NOT NULL) THEN
      BEGIN
        LEAVE_TEXT = LEAVE_TEXT || ASCII_CHAR(10) || 'приказ № ' || COALESCE(V$LDN, '') || ' от ' || (SELECT RESULT FROM DATE2STR(:V$LDO)) || 'г.';
      END
    END

    FOR
      SELECT LVY.COST, V.MARKTYPE_ID, R.VAL, V.SUBJECT_ID, VC.VAL, VST.VAL
      FROM VALM V
      LEFT JOIN LISTVALS LVY ON LVY.LISTVAL_ID = V.YEAR_ID
      JOIN LISTVALS LVP ON LVP.LISTVAL_ID = V.MARKTYPE_ID
      JOIN RES R ON R.RES_ID = LVP.RES_ID AND R.LANG_CODE = 'RU'
      LEFT JOIN LISTVAL_TEXT(V.MARKVAL_ID) VC ON 1 = 1
      LEFT JOIN LISTVAL_TEXT(V.STAGE_ID) VST ON 1 = 1
      WHERE V.IS_DEL = 0 AND V.PUPIL_ID = :PERSON_ID AND (V.IS_NATIVE = 1 OR V.IS_NATIVE IS NULL) AND (V.YEAR_ID = :V$YEAR_ID OR :V$YEAR_ID IS NULL)
      ORDER BY 1, 2, 4
      INTO :MARK_YEAR, :PERIOD_ID, :PERIOD_NAME, :SUBJECT_ID, :MARK_VAL, :STAGE_NAME
    DO
    BEGIN
      SUSPEND;
      N = N + 1;
    END

    -- Если нет отметок - выдаем одну пустую запись персоны
    IF(N = 0) THEN
    BEGIN
      MARK_YEAR = NULL;
      PERIOD_ID = NULL;
      PERIOD_NAME = NULL;
      SUBJECT_ID = NULL;
      MARK_VAL = NULL;
      STAGE_NAME = NULL;
      SUSPEND;
    END
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FINALMARKS_REPORT (
    I$OBJ_ID BIGINT,
    I$APPNAME VARCHAR(100),
    I$USER_ID VARCHAR(40))
RETURNS (
    VAL VARCHAR(4000))
AS
declare variable V$MARK_ID bigint;
declare variable V$SUBJECT varchar(1000);
declare variable V$T varchar(400);
declare variable V$M varchar(100);
declare variable N integer;
declare variable C integer;
begin

  VAL = '<div style="font-weight: 700; font-size: 1rem; margin-bottom: 0.5rem">Итоговые отметки</div>';
  SUSPEND;

  VAL = '<table class="ui small celled striped table">';
  VAL = VAL || '<tbody>';
  SUSPEND;

  C = 0;
  FOR
    SELECT V.MARK_ID, CS.CAPTION, RT.VAL, RM.VAL
    FROM VALM V
    JOIN LISTVALS LVT ON LVT.LISTVAL_ID = V.MARKTYPE_ID
    JOIN RES RT ON RT.RES_ID = LVT.RES_ID AND RT.LANG_CODE = 'RU'
    JOIN LISTVALS LVM ON LVM.LISTVAL_ID = V.MARKVAL_ID
    JOIN RES RM ON RM.RES_ID = LVM.RES_ID AND RT.LANG_CODE = 'RU'
    LEFT JOIN OBJECT_CAPTION_GET(V.SUBJECT_ID) CS ON 1 = 1
    WHERE V.IS_DEL = 0 AND V.PUPIL_ID = :I$OBJ_ID
    ORDER BY V.DATE_MODIFY
    INTO :V$MARK_ID, :V$SUBJECT, :V$T, :V$M
  DO
  BEGIN
    VAL = '<tr>';
    VAL = VAL || '<td>' || (SELECT VAL FROM ESCAPE_STR(:V$SUBJECT)) || '</td>';
    VAL = VAL || '<td>' || (SELECT VAL FROM ESCAPE_STR(:V$T)) || '</td>';
    VAL = VAL || '<td>' || (SELECT VAL FROM ESCAPE_STR(:V$M)) || '</td>';
    VAL = VAL || '</tr>';
    SUSPEND;
    C = C + 1;
  END

  IF(C = 0) THEN
  BEGIN
    VAL = '<tr>';
    VAL = VAL || '<td>Нет данных по итоговым отметкам</td>';
    VAL = VAL || '</tr>';
    SUSPEND;
  END

  VAL = '</tbody></table>';
  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FINALMARKS_SET (
    I$USER_ID VARCHAR(40),
    I$MARK_ID BIGINT,
    I$PERSON_ID BIGINT,
    I$YEAR_ID BIGINT,
    I$SUBJECT_ID BIGINT,
    I$STAGE_ID BIGINT,
    I$TEACHER_ID BIGINT,
    I$MT_ID BIGINT,
    I$DATE DATE,
    I$VAL BIGINT,
    I$IS_NATIVE SMALLINT)
RETURNS (
    OBJ_ID BIGINT)
AS
DECLARE VARIABLE V$OU_LEVEL SMALLINT;
DECLARE VARIABLE V$IS_NATIVE SMALLINT;
DECLARE VARIABLE V$PUPIL_ID BIGINT;
DECLARE VARIABLE V$YEAR_ID BIGINT;
DECLARE VARIABLE V$SUBJECT_ID BIGINT;
DECLARE VARIABLE V$STAGE_ID BIGINT;
DECLARE VARIABLE V$MARKTYPE_ID BIGINT;
DECLARE VARIABLE V$TEACHER_ID BIGINT;
DECLARE VARIABLE V$MARKVAL_ID BIGINT;
DECLARE VARIABLE V$MARK_DATE DATE;
DECLARE VARIABLE V$GRADE_ID BIGINT;
DECLARE VARIABLE V$CURRENT_YEAR INTEGER;
DECLARE VARIABLE V$YEAR_START DATE;
DECLARE VARIABLE V$CURRENT_YEAR_ID BIGINT;
DECLARE VARIABLE V$IS_IND SMALLINT;
begin

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  SELECT KEY_VAL FROM KEYS WHERE KEY_CODE = 'LEVEL' INTO :V$OU_LEVEL;

  SELECT FIRST 1 LV.COST, CAST(LV.TAG AS DATE), LV.LISTVAL_ID
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$CURRENT_YEAR, :V$YEAR_START, :V$CURRENT_YEAR_ID;

  SELECT FIRST 1 M.IS_NATIVE, M.PUPIL_ID, M.YEAR_ID, M.SUBJECT_ID, M.STAGE_ID, M.MARKTYPE_ID, M.TEACHER_ID, M.MARKVAL_ID, M.MARK_DATE
  FROM VALM M
  WHERE M.MARK_ID = :I$MARK_ID AND M.IS_DEL = 0
  INTO :V$IS_NATIVE, :V$PUPIL_ID, :V$YEAR_ID, :V$SUBJECT_ID, :V$STAGE_ID, :V$MARKTYPE_ID, :V$TEACHER_ID, :V$MARKVAL_ID, :V$MARK_DATE;

  V$IS_IND = 0;
  SELECT FIRST 1 1
  FROM LINKS LP187
  WHERE LP187.OBJ_ID = :I$PERSON_ID AND LP187.PARENT_TYPE_ID = 187 AND LP187.DATE_DEL IS NULL
  INTO :V$IS_IND;

  IF(I$MARK_ID IS NOT NULL) THEN
  BEGIN
    -- Поменялось ли что-то в данных ? Если поменялось - обнуляем OBJ_ID
    OBJ_ID = I$MARK_ID;
    IF(V$PUPIL_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Отметка не найдена или была удалена';

    IF(I$DATE <> V$MARK_DATE OR V$MARK_DATE IS NULL) THEN OBJ_ID = NULL;
    IF(I$STAGE_ID <> V$STAGE_ID OR V$STAGE_ID IS NULL) THEN OBJ_ID = NULL;
    IF(I$IS_NATIVE <> V$IS_NATIVE OR V$IS_NATIVE IS NULL) THEN OBJ_ID = NULL;
    IF(I$TEACHER_ID <> V$TEACHER_ID) THEN OBJ_ID = NULL;
    IF(I$YEAR_ID <> V$YEAR_ID) THEN OBJ_ID = NULL;
    IF(I$SUBJECT_ID <> V$SUBJECT_ID) THEN OBJ_ID = NULL;
    IF(I$MT_ID <> V$MARKTYPE_ID) THEN OBJ_ID = NULL;
    IF(I$VAL <> V$MARKVAL_ID) THEN OBJ_ID = NULL;

    IF(I$IS_NATIVE = 1 AND V$IS_IND = 0) THEN
    BEGIN
      -- Изменять уже внесенные отметки, относящиеся к текущей школе, может только завуч
      IF(NOT EXISTS(
        SELECT FIRST 1 1
        FROM USERS U
        WHERE U.DATE_DEL IS NULL AND U.USER_ID = :I$USER_ID AND U.USER_TYPE IN (1, 5, 6)
      ))
      THEN EXCEPTION DATA_ERROR 'Изменять уже внесенные отметки данной ОУ (для учеников не на семейном обучении) может только администратор, директор или завуч';
    END

    IF(OBJ_ID IS NULL) THEN
    BEGIN
      UPDATE VALM
      SET IS_DEL = 1, USER_DEL = :I$USER_ID
      WHERE MARK_ID = :I$MARK_ID;
      I$MARK_ID = NULL;
    END

  END
  ELSE
  BEGIN

    -- Ставим новую отметку - не должно быть такой же существующей отметки
    IF(EXISTS(
      SELECT FIRST 1 1
      FROM VALM M
      WHERE M.IS_DEL = 0 AND M.PUPIL_ID = :I$PERSON_ID AND M.SUBJECT_ID = :I$SUBJECT_ID AND M.YEAR_ID = :I$YEAR_ID AND M.MARKTYPE_ID = :I$MT_ID
        AND (M.STAGE_ID IS NULL OR M.STAGE_ID = :I$STAGE_ID)
    ))
    THEN EXCEPTION DATA_ERROR 'Нельзя ставить отметку, закрывающую существующую отметку по тому же предмету и периоду';

    -- Если ученик не в экстернате - за текущий год ставить отметку текущей школы руками нельзя
    IF(I$IS_NATIVE = 1 AND I$YEAR_ID = V$CURRENT_YEAR_ID AND V$IS_IND = 0) THEN
      EXCEPTION DATA_ERROR 'Отметку текущего года можно выставлять только учащемуся на семейном обучении или для предыдущего ОУ';

  END

  -- Если отметка новая или изменение старой
  -- GRADE_ID при ручном выставлении не заполняется
  IF(I$MARK_ID IS NULL) THEN BEGIN

    INSERT INTO VALM
    (IS_NATIVE, PUPIL_ID, YEAR_ID, SUBJECT_ID, STAGE_ID, MARKTYPE_ID, TEACHER_ID, MARKVAL_ID, MARK_DATE, USER_ADD)
    VALUES (:I$IS_NATIVE, :I$PERSON_ID, :I$YEAR_ID, :I$SUBJECT_ID, :I$STAGE_ID, :I$MT_ID, :I$TEACHER_ID, :I$VAL, :I$DATE, :I$USER_ID)
    RETURNING MARK_ID INTO :OBJ_ID;

  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FINALMARKS_SUBJECTS (
    I$OBJ_ID BIGINT,
    I$DATE DATE)
RETURNS (
    OBJ_ID BIGINT,
    CAPTION VARCHAR(1000))
AS
declare variable V$YEAR_ID bigint;
declare variable V$YSTART date;
declare variable V$TYPE_ID bigint;
begin

  -- На входе может быть комбинация класс+дата или ученик+дата или ученик без даты
  SELECT TYPE_ID
  FROM OBJECTS
  WHERE OBJ_ID = :I$OBJ_ID
  INTO :V$TYPE_ID;

  SELECT FIRST 1 LV.LISTVAL_ID
  FROM LISTVALS LV
  WHERE LV.LIST_ID = 29 AND LV.IS_DEL = 0 AND :I$DATE >= CAST(LV.TAG AS DATE)
  ORDER BY 1 DESC
  INTO :V$YEAR_ID;

  IF(I$DATE IS NULL) THEN I$DATE = CURRENT_DATE;

  IF(EXTRACT(MONTH FROM I$DATE) >= 9) THEN V$YSTART = '01.09.' || EXTRACT(YEAR FROM I$DATE);
  ELSE V$YSTART = '01.09.' || (EXTRACT(YEAR FROM I$DATE) - 1);

  IF(V$TYPE_ID = 10) THEN
  FOR
    SELECT SL.SUBJECT_ID, C.CAPTION
    FROM (
      SELECT DISTINCT V.SUBJECT_ID
      FROM VALM V
      WHERE V.PUPIL_ID = :I$OBJ_ID AND V.IS_DEL = 0 AND (V.YEAR_ID = :V$YEAR_ID OR :V$YEAR_ID IS NULL) AND (V.IS_NATIVE = 1 OR V.IS_NATIVE IS NULL)
    ) SL
    LEFT JOIN VALI V375 ON V375.OBJ_ID = SL.SUBJECT_ID AND V375.PARAM_ID = 375 AND V375.IS_DEL = 0
    LEFT JOIN OBJECT_CAPTION_GET(SL.SUBJECT_ID) C ON 1 = 1
    ORDER BY V375.VAL, 2
    INTO :OBJ_ID, :CAPTION
  DO
  BEGIN
    SUSPEND;
  END
  ELSE
  FOR
    SELECT SL.SUBJECT_ID, C.CAPTION
    FROM (
      SELECT DISTINCT V.SUBJECT_ID
      FROM PERSON_MOVEMENTS M
      JOIN VALM V ON V.PUPIL_ID = M.PERSON_ID AND V.IS_DEL = 0 AND (V.YEAR_ID = :V$YEAR_ID OR :V$YEAR_ID IS NULL) AND (V.IS_NATIVE = 1 OR V.IS_NATIVE IS NULL)
      WHERE M.DATE_DEL IS NULL AND M.GROUP_ID = :I$OBJ_ID AND M.DATE_IN <= :I$DATE AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :V$YSTART)
    ) SL
    LEFT JOIN VALI V375 ON V375.OBJ_ID = SL.SUBJECT_ID AND V375.PARAM_ID = 375 AND V375.IS_DEL = 0
    LEFT JOIN OBJECT_CAPTION_GET(SL.SUBJECT_ID) C ON 1 = 1
    ORDER BY V375.VAL, 2
    INTO :OBJ_ID, :CAPTION
  DO
  BEGIN
    SUSPEND;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FINALMARK_ADD (
    PUPIL_ID BIGINT,
    SUBJECT_ID BIGINT NOT NULL,
    TEACHER_ID BIGINT,
    YEAR_ID BIGINT NOT NULL,
    MARK_TYPE_ID BIGINT,
    MARK_VALUE_ID BIGINT)
AS
BEGIN

    -- Хвост от истории, сейчас всегда должен быть тип
    IF (MARK_TYPE_ID IS NULL) THEN MARK_TYPE_ID = 3011;

    IF (MARK_VALUE_ID IS NULL) THEN
    BEGIN
        UPDATE VALM
        SET IS_DEL = 1
        WHERE PUPIL_ID = :PUPIL_ID
          AND SUBJECT_ID = :SUBJECT_ID
          AND YEAR_ID = :YEAR_ID
          AND MARKTYPE_ID = :MARK_TYPE_ID;
    END
    ELSE
    BEGIN
        UPDATE OR INSERT INTO VALM (PUPIL_ID, SUBJECT_ID, TEACHER_ID, YEAR_ID, MARKTYPE_ID, MARKVAL_ID, IS_DEL)
        VALUES (:PUPIL_ID, :SUBJECT_ID, :TEACHER_ID, :YEAR_ID, :MARK_TYPE_ID, :MARK_VALUE_ID, 0)
        MATCHING (PUPIL_ID, SUBJECT_ID, YEAR_ID, MARKTYPE_ID);
    END

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FINALMARK_CLASS_LIST (
    I$SCHOOL_ID BIGINT,
    I$YEAR_ID BIGINT = null)
RETURNS (
    CLASS_ID BIGINT,
    CLASS_CAPTION VARCHAR(4000),
    SORT_ORDER DOUBLE PRECISION)
AS
declare variable I integer;
declare variable C char(1);
declare variable S varchar(1000);
declare variable FROM_DATE timestamp;
declare variable TO_DATE timestamp;
declare variable FROM_DATE1 timestamp;
declare variable TO_DATE1 timestamp;
declare variable Y integer;
BEGIN
    IF (I$SCHOOL_ID IS NULL) THEN
    BEGIN
        SELECT FIRST 1 L.OBJ_ID
        FROM LINKS L
        WHERE L.PARENT_ID IS NULL
        AND L.DATE_DEL IS NULL
        AND L.OBJ_TYPE_ID = 2
        INTO :I$SCHOOL_ID;
    END

    IF (I$YEAR_ID IS NULL) THEN
    BEGIN
        FOR
            SELECT L9.OBJ_ID
            FROM LINKS L7
            JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
            JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
            WHERE L7.PARENT_ID = :I$SCHOOL_ID AND L7.DATE_DEL IS NULL AND L7.OBJ_TYPE_ID = 7
            UNION ALL
            SELECT L187.OBJ_ID
            FROM LINKS L7
            JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
            JOIN LINKS L187 ON L187.PARENT_ID = L8.OBJ_ID AND L187.OBJ_TYPE_ID = 187 AND L187.DATE_DEL IS NULL
            WHERE L7.PARENT_ID = :I$SCHOOL_ID AND L7.DATE_DEL IS NULL AND L7.OBJ_TYPE_ID = 7
            UNION ALL
            SELECT L81_82.OBJ_ID
            FROM LINKS L78
            JOIN LINKS L81_82 ON L81_82.PARENT_ID = L78.OBJ_ID AND L81_82.OBJ_TYPE_ID IN (81, 82) AND L81_82.DATE_DEL IS NULL
            WHERE L78.PARENT_ID = :I$SCHOOL_ID AND L78.OBJ_TYPE_ID = 78 AND L78.DATE_DEL IS NULL
            INTO :CLASS_ID
        DO
        BEGIN
            SELECT CAPTION, SORT_ORDER
            FROM OBJECT_CAPTION_GET(:CLASS_ID)
            INTO :CLASS_CAPTION, :SORT_ORDER;
    
            IF (SORT_ORDER = 0) THEN
            BEGIN
                SORT_ORDER = 1000000000;
            END
    
            SUSPEND;
        END
    END
    ELSE
    BEGIN
        SELECT COST
        FROM LISTVALS
        WHERE LISTVAL_ID = :I$YEAR_ID
        INTO Y;

        FROM_DATE = Y || '-06-01';
        TO_DATE = (Y + 1) || '-06-01';

        FROM_DATE1 = (Y + 1) || '-06-01';
        TO_DATE1 = (Y + 1) || '-10-01';

        FOR
            SELECT DISTINCT M.NAME_IN, L9.OBJ_ID
            FROM LINKS L9
            JOIN PERSON_MOVEMENTS M ON M.DATE_DEL IS NULL AND M.GROUP_ID = L9.OBJ_ID
            JOIN VALL V49 ON V49.OBJ_ID = L9.PARENT_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0 AND V49.LISTVAL_ID = M.STAGE_ID
            WHERE L9.PARENT_TYPE_ID = 8 AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NOT NULL AND L9.DATE_DEL >= :FROM_DATE1 AND L9.DATE_DEL <= :TO_DATE1
            INTO :CLASS_CAPTION, :CLASS_ID
        DO
        BEGIN
            S = '';
            I = 1;
            SORT_ORDER = 1000000000;
            WHILE (I <= CHARACTER_LENGTH(CLASS_CAPTION)) DO
            BEGIN
                C = SUBSTRING(CLASS_CAPTION FROM I FOR 1);
                I = I + 1;
                IF (C NOT SIMILAR TO '[[:DIGIT:]]') THEN
                BEGIN
                    BREAK;
                END
                S = S || C;
            END
            IF (S <> '') THEN
            BEGIN
                SORT_ORDER = CAST(S AS DOUBLE PRECISION);
            END
            SUSPEND;
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FINALMARK_DISTRICT_LIST (
    I$USER_ID BIGINT = null)
RETURNS (
    DISTRICT_ID BIGINT,
    DISTRICT_CAPTION VARCHAR(4000),
    SORT_ORDER DOUBLE PRECISION)
AS
declare variable V$SREGION_ID bigint;
declare variable V$OU_LICENCE_TYPE varchar(1);
declare variable V$AREA_ID bigint;
BEGIN
    SELECT STATUS FROM OU_LICENCE_TYPE INTO :V$OU_LICENCE_TYPE;
    V$SREGION_ID = NULL;

    -- Надо район пользователя
    SELECT FIRST 1 U.ROOT_OBJ_ID
    FROM LUSERS U
    WHERE U.USER_ID = :I$USER_ID AND U.ROOT_OBJ_ID IS NOT NULL
    INTO :V$AREA_ID;

    SELECT FIRST 1 L.OBJ_ID
    FROM LINKS L
    WHERE L.DATE_DEL IS NULL AND L.OBJ_TYPE_ID = 112
    INTO :V$SREGION_ID;

    IF ((V$SREGION_ID IS NOT NULL) AND (V$OU_LICENCE_TYPE = 'C')) THEN
    BEGIN
        DISTRICT_ID = :V$SREGION_ID;
        SELECT CAPTION, SORT_ORDER
        FROM OBJECT_CAPTION_GET(:DISTRICT_ID)
        INTO :DISTRICT_CAPTION, :SORT_ORDER;
    
        SUSPEND;
    END
    ELSE
    BEGIN
        IF (V$SREGION_ID IS NULL) THEN
        BEGIN
            SELECT FIRST 1 L.PARENT_ID
            FROM LINKS L
            WHERE L.DATE_DEL IS NULL AND L.PARENT_TYPE_ID = 112
            INTO :V$SREGION_ID;
        END
    
        IF (V$SREGION_ID IS NOT NULL) THEN
        BEGIN
            FOR
                SELECT L.OBJ_ID
                FROM LINKS L
                WHERE L.PARENT_ID = :V$SREGION_ID AND L.DATE_DEL IS NULL AND L.OBJ_TYPE_ID = 111 AND (:V$AREA_ID IS NULL OR L.OBJ_ID = :V$AREA_ID)
                INTO :DISTRICT_ID
            DO
            BEGIN
                SELECT CAPTION, SORT_ORDER
                FROM OBJECT_CAPTION_GET(:DISTRICT_ID)
                INTO :DISTRICT_CAPTION, :SORT_ORDER;
    
                SUSPEND;
            END
        END
        ELSE
        BEGIN
            FOR
                SELECT L.OBJ_ID
                FROM LINKS L
                WHERE L.PARENT_ID IS NULL AND L.DATE_DEL IS NULL AND L.OBJ_TYPE_ID = 111
                INTO :DISTRICT_ID
            DO
            BEGIN
                SELECT CAPTION, SORT_ORDER
                FROM OBJECT_CAPTION_GET(:DISTRICT_ID)
                INTO :DISTRICT_CAPTION, :SORT_ORDER;
    
                SUSPEND;
            END
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FINALMARK_LIST (
    I$PUPIL_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    FINALMARK_ID BIGINT,
    SUBJECT_ID BIGINT,
    SUBJECT_CAPTION VARCHAR(500),
    SCHOOL_YEAR_ID BIGINT,
    FINAL_TYPE_ID BIGINT,
    MARK_TYPE_ID BIGINT,
    SCHOOL_YEAR_CAPTION VARCHAR(20),
    FINAL_TYPE_CAPTION VARCHAR(500),
    MARK_TYPE_CAPTION VARCHAR(500),
    SCHOOL_YEAR_COST DOUBLE PRECISION,
    FINAL_TYPE_COST DOUBLE PRECISION)
AS
declare variable LANG_CODE varchar(2);
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :LANG_CODE;

    FOR
        SELECT V.MARK_ID, V.SUBJECT_ID, C.CAPTION, V.YEAR_ID, V.MARKTYPE_ID, V.MARKVAL_ID
        FROM VALM V
        JOIN LISTVALS LV ON LV.LISTVAL_ID = V.YEAR_ID AND LV.IS_DEL = 0
        LEFT JOIN OBJECT_CAPTION_GET(V.SUBJECT_ID) C ON 1 = 1
        WHERE V.PUPIL_ID = :I$PUPIL_ID AND V.IS_DEL = 0
        INTO :FINALMARK_ID, :SUBJECT_ID, :SUBJECT_CAPTION, :SCHOOL_YEAR_ID, :FINAL_TYPE_ID, :MARK_TYPE_ID
    DO
    BEGIN
        SCHOOL_YEAR_CAPTION = '';
        SCHOOL_YEAR_COST = 0;

        SELECT R.VAL, LV.COST
        FROM LISTVALS LV
        LEFT JOIN RES_GET(LV.RES_ID,  :LANG_CODE) R ON 1=1
        WHERE LV.LISTVAL_ID = :SCHOOL_YEAR_ID
        INTO :SCHOOL_YEAR_CAPTION, :SCHOOL_YEAR_COST;

        FINAL_TYPE_CAPTION = '';
        FINAL_TYPE_COST = 0;

        SELECT R.VAL, LV.COST
        FROM LISTVALS LV
        LEFT JOIN RES_GET(LV.RES_ID,  :LANG_CODE) R ON 1=1
        WHERE LV.LISTVAL_ID = :FINAL_TYPE_ID
        INTO :FINAL_TYPE_CAPTION, :FINAL_TYPE_COST;

        MARK_TYPE_CAPTION = '';

        SELECT R.VAL
        FROM LISTVALS LV
        LEFT JOIN RES_GET(LV.RES_ID,  :LANG_CODE) R ON 1=1
        WHERE LV.LISTVAL_ID = :MARK_TYPE_ID
        INTO :MARK_TYPE_CAPTION;

        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FINALMARK_LIST2 (
    I$CLASS_ID BIGINT,
    I$SUBJECT_ID BIGINT,
    I$SCHOOL_YEAR VARCHAR(20),
    I$USER_ID BIGINT)
RETURNS (
    FINALMARK_ID BIGINT,
    PUPIL_ID BIGINT,
    PUPIL_CAPTION VARCHAR(500),
    SUBJECT_ID BIGINT,
    SUBJECT_CAPTION VARCHAR(500),
    SCHOOL_YEAR_ID BIGINT,
    FINAL_TYPE_ID BIGINT,
    MARK_TYPE_ID BIGINT,
    SCHOOL_YEAR_CAPTION VARCHAR(20),
    FINAL_TYPE_CAPTION VARCHAR(500),
    MARK_TYPE_CAPTION VARCHAR(500),
    SCHOOL_YEAR_COST DOUBLE PRECISION,
    FINAL_TYPE_COST DOUBLE PRECISION)
AS
declare variable V$SCHOOL_YEAR_ID bigint;
declare variable LANG_CODE varchar(2);
declare variable V$DATE_DEL date;
declare variable V$LEAVED_INFO varchar(1000);
BEGIN
    SELECT LANG_CODE FROM USERS WHERE USER_ID = :I$USER_ID INTO :LANG_CODE;

    -- Ищем ID учебного года
    SELECT FIRST 1 LV.LISTVAL_ID, R.VAL, LV.COST
    FROM LISTVALS LV
    JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
    WHERE LV.LIST_ID = 29 AND R.VAL LIKE :I$SCHOOL_YEAR
    INTO :V$SCHOOL_YEAR_ID, :SCHOOL_YEAR_CAPTION, :SCHOOL_YEAR_COST;

    FOR
        SELECT L10.OBJ_ID, PC.CAPTION, V.MARK_ID, V.YEAR_ID, V.MARKTYPE_ID, V.MARKVAL_ID, V.SUBJECT_ID, C.CAPTION, L10.DATE_DEL
        FROM LINKS L10
        JOIN VALM V ON V.PUPIL_ID = L10.OBJ_ID AND (:I$SUBJECT_ID IS NULL OR V.SUBJECT_ID = :I$SUBJECT_ID) AND V.YEAR_ID = :V$SCHOOL_YEAR_ID AND V.IS_DEL = 0
        LEFT JOIN OBJECT_CAPTION_GET(L10.OBJ_ID) PC ON 1 = 1
        LEFT JOIN OBJECT_CAPTION_GET(V.SUBJECT_ID) C ON 1 = 1
        WHERE L10.PARENT_ID = :I$CLASS_ID AND L10.OBJ_TYPE_ID = 10
        -- либо ученик в классе сейчас, либо это последний класс, в котором он был
        AND (L10.DATE_DEL IS NULL OR :I$CLASS_ID = (
            SELECT FIRST 1 M.GROUP_ID
            FROM PERSON_MOVEMENTS M
            JOIN LINKS L9 ON L9.OBJ_ID = M.GROUP_ID AND L9.OBJ_TYPE_ID IN (9, 187) AND L9.PARENT_TYPE_ID = 8 AND L9.DATE_DEL IS NULL
            WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = L10.OBJ_ID AND M.DATE_OUT IS NOT NULL
            ORDER BY M.DATE_OUT DESC
          )
        )
        INTO :PUPIL_ID, :PUPIL_CAPTION, :FINALMARK_ID, :SCHOOL_YEAR_ID, :FINAL_TYPE_ID, :MARK_TYPE_ID, :SUBJECT_ID, :SUBJECT_CAPTION, :V$DATE_DEL
    DO
    BEGIN
        -- нужно указывать дату выбытия и номер приказа
        IF (V$DATE_DEL IS NOT NULL) THEN
        BEGIN
            FOR
                SELECT LEAVED_INFO
                FROM PUPIL_LEAVED_INFO_GET(:PUPIL_ID)
                INTO :V$LEAVED_INFO
            DO
            BEGIN
                PUPIL_CAPTION = PUPIL_CAPTION || ASCII_CHAR(10) || V$LEAVED_INFO;
            END
        END

        FINAL_TYPE_CAPTION = '';
        FINAL_TYPE_COST = 0;

        SELECT R.VAL, LV.COST
        FROM LISTVALS LV
        LEFT JOIN RES_GET(LV.RES_ID, :LANG_CODE) R ON 1 = 1
        WHERE LV.LISTVAL_ID = :FINAL_TYPE_ID
        INTO :FINAL_TYPE_CAPTION, :FINAL_TYPE_COST;

        MARK_TYPE_CAPTION = '';

        SELECT R.VAL
        FROM LISTVALS LV
        LEFT JOIN RES_GET(LV.RES_ID, :LANG_CODE) R ON 1=1
        WHERE LV.LISTVAL_ID = :MARK_TYPE_ID
        INTO :MARK_TYPE_CAPTION;

        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FINALMARK_LIST3 (
    I$CLASS_ID BIGINT NOT NULL,
    I$SUBJECT_ID BIGINT,
    I$SCHOOL_YEAR BIGINT,
    I$MARK_TYPE_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    FINALMARK_ID BIGINT,
    PUPIL_ID BIGINT,
    PUPIL_CAPTION VARCHAR(500),
    MARK_VALUE_ID BIGINT,
    FINAL_TYPE_CAPTION VARCHAR(500),
    MARK_TYPE_CAPTION VARCHAR(500),
    FINAL_TYPE_ID BIGINT)
AS
declare variable FROM_DATE timestamp;
declare variable TO_DATE timestamp;
declare variable Y integer;
declare variable LANG_CODE varchar(2);
declare variable N integer;
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :LANG_CODE;

    --IF (I$MARK_TYPE_ID IS NULL) THEN I$MARK_TYPE_ID = 3011;

    SELECT R.VAL
    FROM LISTVALS LV
    LEFT JOIN RES_GET(LV.RES_ID,  :LANG_CODE) R ON 1 = 1
    WHERE LV.LISTVAL_ID = :I$MARK_TYPE_ID
    INTO :FINAL_TYPE_CAPTION;

    SELECT LV.COST
    FROM LISTVALS LV
    WHERE LV.LISTVAL_ID = :I$SCHOOL_YEAR
    INTO :Y;

    FROM_DATE = Y || '-06-01';
    TO_DATE = (Y + 1) || '-06-01';

    FOR
        SELECT DISTINCT M.PERSON_ID
        FROM PERSON_MOVEMENTS M
        JOIN OBJECTS O ON O.OBJ_ID = M.GROUP_ID AND O.TYPE_ID IN (9, 187)
        WHERE M.DATE_DEL IS NULL AND M.GROUP_ID = :I$CLASS_ID AND
            ((M.DATE_IN >= :FROM_DATE AND M.DATE_IN <= :TO_DATE) OR (M.DATE_OUT >= :FROM_DATE AND M.DATE_OUT <= :TO_DATE))
        INTO :PUPIL_ID
    DO
    BEGIN
        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:PUPIL_ID, 36)
        INTO :PUPIL_CAPTION;

        FINALMARK_ID = NULL;
        MARK_VALUE_ID = NULL;
        MARK_TYPE_CAPTION = NULL;
        N = 0;

        FOR
            SELECT V.MARK_ID, V.MARKVAL_ID, R.VAL, V.MARKTYPE_ID, R2.VAL
            FROM VALM V
            JOIN LISTVALS LV ON LV.LISTVAL_ID = V.MARKVAL_ID
            LEFT JOIN RES_GET(LV.RES_ID, :LANG_CODE) R ON 1 = 1
            JOIN LISTVALS LV2 ON LV2.LISTVAL_ID = V.MARKTYPE_ID
            LEFT JOIN RES_GET(LV2.RES_ID, :LANG_CODE) R2 ON 1 = 1
            WHERE V.PUPIL_ID = :PUPIL_ID AND V.SUBJECT_ID = :I$SUBJECT_ID AND V.YEAR_ID = :I$SCHOOL_YEAR AND V.IS_DEL = 0 AND
              (V.MARKTYPE_ID = :I$MARK_TYPE_ID OR :I$MARK_TYPE_ID IS NULL)
            INTO :FINALMARK_ID, :MARK_VALUE_ID, :MARK_TYPE_CAPTION, :FINAL_TYPE_ID, :FINAL_TYPE_CAPTION
        DO
        BEGIN
            N = N + 1;
            SUSPEND;
        END

        IF(N = 0) THEN SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FINALMARK_PUPIL_LIST (
    I$CLASS_ID BIGINT,
    I$SHOW_LEFT SMALLINT = 0)
RETURNS (
    PUPIL_ID BIGINT,
    PUPIL_CAPTION VARCHAR(4000))
AS
declare variable V$YEAR integer;
declare variable V$MOVE_TYPE bigint;
declare variable V$MOVE_DATE date;
BEGIN

    -- I$SHOW_LEFT - отображать выбывших учеников

    V$YEAR = EXTRACT(YEAR FROM CURRENT_DATE);
    IF(EXTRACT(MONTH FROM CURRENT_DATE) < 9) THEN V$YEAR = V$YEAR - 1;

    FOR
        -- Возвращаем как актуальных учеников, так и выбывших в текущем году из этого класса
        SELECT DISTINCT L10.OBJ_ID
        FROM LINKS L10
        JOIN PERSON_MOVEMENTS M ON M.DATE_DEL IS NULL AND M.PERSON_ID = L10.OBJ_ID
           AND M.GROUP_ID = :I$CLASS_ID AND M.DATE_IN >= '25.08.' || :V$YEAR AND M.DATE_IN < '31.08.' || (:V$YEAR + 1)
        WHERE L10.PARENT_ID = :I$CLASS_ID AND L10.OBJ_TYPE_ID = 10 AND (:I$SHOW_LEFT <> 0 OR L10.DATE_DEL IS NULL)
        INTO :PUPIL_ID
    DO
    BEGIN
        SELECT CAPTION FROM OBJECT_CAPTION_GET(:PUPIL_ID, 49) INTO :PUPIL_CAPTION;
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FINALMARK_SCHOOL_LIST (
    I$DISTRICT_ID BIGINT)
RETURNS (
    SCHOOL_ID BIGINT,
    SCHOOL_CAPTION VARCHAR(4000),
    SORT_ORDER DOUBLE PRECISION)
AS
BEGIN
    FOR SELECT L.OBJ_ID
        FROM LINKS L
        WHERE ((L.PARENT_ID = :I$DISTRICT_ID) OR ((:I$DISTRICT_ID IS NULL) AND (L.PARENT_ID IS NULL)))
          AND L.DATE_DEL IS NULL
          AND L.OBJ_TYPE_ID = 2
        INTO :SCHOOL_ID
    DO
    BEGIN
        SELECT CAPTION, SORT_ORDER
        FROM OBJECT_CAPTION_GET(:SCHOOL_ID)
        INTO :SCHOOL_CAPTION, :SORT_ORDER;

        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FINALMARK_SGC_LIST (
    I$SCHOOL_ID BIGINT,
    I$SHOW_STAGES SMALLINT,
    I$SHOW_GRADES SMALLINT,
    I$SHOW_CLASSES SMALLINT)
RETURNS (
    ID BIGINT,
    TYPE_ID BIGINT,
    CAPTION VARCHAR(4000),
    CHILD_COUNT INTEGER,
    SORT_ORDER_STAGES DOUBLE PRECISION,
    SORT_ORDER_GRADES DOUBLE PRECISION,
    SORT_ORDER_CLASSES DOUBLE PRECISION)
AS
DECLARE VARIABLE V$STAGE_ID BIGINT;
DECLARE VARIABLE V$GRADE_ID BIGINT;
DECLARE VARIABLE V$CLASS_ID BIGINT;
DECLARE VARIABLE CNT INTEGER;
BEGIN
    CNT = 0;
    FOR SELECT L7.OBJ_ID, L7.OBJ_ID, NULL, NULL, 7, COUNT(DISTINCT L10.OBJ_ID)
        FROM LINKS L7
        LEFT JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
        LEFT JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
        LEFT JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        WHERE L7.PARENT_ID = :I$SCHOOL_ID
          AND L7.OBJ_TYPE_ID = 7
          AND L7.DATE_DEL IS NULL
          AND :I$SHOW_STAGES = 1
        GROUP BY 1, 2, 3, 4, 5

        UNION ALL

        SELECT L8.OBJ_ID, L7.OBJ_ID, L8.OBJ_ID, NULL, 8, COUNT(DISTINCT L10.OBJ_ID)
        FROM LINKS L7
        INNER JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
        LEFT JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
        LEFT JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        WHERE L7.PARENT_ID = :I$SCHOOL_ID
          AND L7.OBJ_TYPE_ID = 7
          AND L7.DATE_DEL IS NULL
          AND :I$SHOW_GRADES = 1
        GROUP BY 1, 2, 3, 4, 5

        UNION ALL

        SELECT L9.OBJ_ID, L7.OBJ_ID, L8.OBJ_ID, L9.OBJ_ID, 9, COUNT(DISTINCT L10.OBJ_ID)
        FROM LINKS L7
        INNER JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
        INNER JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
        LEFT JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        WHERE L7.PARENT_ID = :I$SCHOOL_ID
          AND L7.OBJ_TYPE_ID = 7
          AND L7.DATE_DEL IS NULL
          AND :I$SHOW_CLASSES = 1
        GROUP BY 1, 2, 3, 4, 5

        INTO :ID, :V$STAGE_ID, :V$GRADE_ID, :V$CLASS_ID, :TYPE_ID, :CHILD_COUNT
    DO
    BEGIN
        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:ID)
        INTO :CAPTION;

        IF (V$GRADE_ID IS NULL) THEN
        BEGIN
            SORT_ORDER_GRADES = 0;
        END
        ELSE
        BEGIN
            SELECT SORT_ORDER
            FROM OBJECT_CAPTION_GET(:V$GRADE_ID)
            INTO :SORT_ORDER_GRADES;
        END

        IF (V$CLASS_ID IS NULL) THEN
        BEGIN
            SORT_ORDER_CLASSES = 0;
        END
        ELSE
        BEGIN
            SELECT SORT_ORDER
            FROM OBJECT_CAPTION_GET(:V$CLASS_ID)
            INTO :SORT_ORDER_CLASSES;
        END

        SELECT SORT_ORDER
        FROM OBJECT_CAPTION_GET(:V$STAGE_ID)
        INTO :SORT_ORDER_STAGES;

        IF (I$SHOW_STAGES = 1) THEN
        BEGIN
            IF (TYPE_ID = 7) THEN
                CNT = CNT + CHILD_COUNT;
        END
        ELSE
        IF (I$SHOW_GRADES = 1) THEN
        BEGIN
            IF (TYPE_ID = 8) THEN
                CNT = CNT + CHILD_COUNT;
        END
        ELSE
        IF (I$SHOW_CLASSES = 1) THEN
        BEGIN
            IF (TYPE_ID = 9) THEN
                CNT = CNT + CHILD_COUNT;
        END

        SUSPEND;
    END

    IF ((I$SHOW_STAGES = 1) OR (I$SHOW_GRADES = 1) OR (I$SHOW_CLASSES = 1)) THEN
    BEGIN
        ID = 0;
        TYPE_ID = 0;
        SELECT WORD
        FROM REPORT_WORDS
        WHERE ID = 36
        INTO :CAPTION;
        CHILD_COUNT = CNT;
        SORT_ORDER_STAGES = 1000000;
        SORT_ORDER_GRADES = 1000000;
        SORT_ORDER_CLASSES = 1000000;
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FINALMARK_SUBJECT_CLASS_LIST (
    I$CLASS_ID BIGINT,
    I$USER_ID BIGINT,
    I$SCHOOL_YEAR VARCHAR(20))
RETURNS (
    SUBJECT_ID BIGINT,
    SUBJECT_CAPTION VARCHAR(1000),
    SUBJECT_SHORTNAME VARCHAR(100),
    SORT_ORDER DOUBLE PRECISION)
AS
declare variable V$SCHOOL_YEAR_ID bigint;
declare variable V$SUBJECT_PARENT bigint;
declare variable V$SCHOOL_YEAR integer;
declare variable V$DATE_START date;
declare variable V$CURRENT_YEAR integer;
BEGIN
    -- Ищем ID учебного года
    IF(EXTRACT(MONTH FROM CURRENT_DATE) < 9) THEN V$CURRENT_YEAR = EXTRACT(YEAR FROM CURRENT_DATE) - 1;
    ELSE V$CURRENT_YEAR = EXTRACT(YEAR FROM CURRENT_DATE);

    IF(I$SCHOOL_YEAR IS NULL) THEN
    BEGIN
        I$SCHOOL_YEAR = V$CURRENT_YEAR || '-' || (V$CURRENT_YEAR + 1);
    END

    SELECT FIRST 1 LV.LISTVAL_ID, LV.COST
    FROM LISTVALS LV
    JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
    WHERE LV.LIST_ID = 29 AND R.VAL LIKE :I$SCHOOL_YEAR
    INTO :V$SCHOOL_YEAR_ID, :V$SCHOOL_YEAR;

    V$DATE_START = '01.09.' || V$DATE_START;

    IF(V$SCHOOL_YEAR = V$CURRENT_YEAR) THEN
    BEGIN
        -- Текущий учебный год
        FOR
            SELECT DISTINCT PS.SUBJECT_ID
            FROM LINKS L10
            JOIN PERSON_MOVEMENTS M ON M.DATE_DEL IS NULL AND M.PERSON_ID = L10.OBJ_ID AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :V$DATE_START)
            JOIN LINKS LP54 ON LP54.OBJ_ID = M.GROUP_ID AND LP54.PARENT_TYPE_ID = 54 AND LP54.DATE_DEL IS NULL
            JOIN LINKS LP400 ON LP400.OBJ_ID = LP54.PARENT_ID AND LP400.PARENT_TYPE_ID = 400 AND LP400.DATE_DEL IS NULL
            -- Только обычные планы, не ВД
            JOIN VALL V3022 ON V3022.OBJ_ID = LP400.PARENT_ID AND V3022.PARAM_ID = 3022 AND V3022.IS_DEL = 0 AND V3022.LISTVAL_ID = 3
            JOIN PLAN_SUBJECTS PS ON PS.DATE_DEL IS NULL AND PS.PLAN_ID = LP400.PARENT_ID AND PS.ROW_TYPE = 10
            JOIN PLAN_LOADS PL ON PL.DATE_DEL IS NULL AND PL.SUBJECT_ID = PS.OBJ_ID AND PL.STAGE_ID = LP54.PARENT_ID AND (PL.LOAD_HOURS_S1 > 0 OR PL.LOAD_HOURS_S2 > 0)
            WHERE L10.PARENT_ID = :I$CLASS_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
            UNION
            SELECT DISTINCT MM.SUBJECT_ID
            FROM LINKS L10
            JOIN PERSON_MOVEMENTS M ON M.DATE_DEL IS NULL AND M.PERSON_ID = L10.OBJ_ID AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :V$DATE_START)
            JOIN VALM MM ON MM.PUPIL_ID = L10.OBJ_ID AND MM.YEAR_ID = :V$SCHOOL_YEAR_ID AND MM.IS_DEL = 0
            WHERE L10.PARENT_ID = :I$CLASS_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
            INTO :SUBJECT_ID
        DO
        BEGIN
            SELECT FIRST 1 PS.GLOBAL_INDEX
            FROM LINKS L10
            JOIN PERSON_MOVEMENTS M ON M.DATE_DEL IS NULL AND M.PERSON_ID = L10.OBJ_ID AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :V$DATE_START)
            JOIN LINKS LP54 ON LP54.OBJ_ID = M.GROUP_ID AND LP54.PARENT_TYPE_ID = 54 AND LP54.DATE_DEL IS NULL
            JOIN LINKS LP400 ON LP400.OBJ_ID = LP54.PARENT_ID AND LP400.PARENT_TYPE_ID = 400 AND LP400.DATE_DEL IS NULL
            -- Только обычные планы, не ВД
            JOIN VALL V3022 ON V3022.OBJ_ID = LP400.PARENT_ID AND V3022.PARAM_ID = 3022 AND V3022.IS_DEL = 0 AND V3022.LISTVAL_ID = 3
            JOIN PLAN_SUBJECTS PS ON PS.DATE_DEL IS NULL AND PS.PLAN_ID = LP400.PARENT_ID AND PS.ROW_TYPE = 10 AND PS.SUBJECT_ID = :SUBJECT_ID
            JOIN PLAN_LOADS PL ON PL.DATE_DEL IS NULL AND PL.SUBJECT_ID = PS.OBJ_ID AND PL.STAGE_ID = LP54.PARENT_ID AND (PL.LOAD_HOURS_S1 > 0 OR PL.LOAD_HOURS_S2 > 0)
            WHERE L10.PARENT_ID = :I$CLASS_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
            ORDER BY 1
            INTO :SORT_ORDER;

            SELECT V FROM VAL_GET(:SUBJECT_ID, 376, 0, :I$USER_ID) INTO :SUBJECT_CAPTION;
            SELECT V FROM VAL_GET(:SUBJECT_ID, 377, 0, :I$USER_ID) INTO :SUBJECT_SHORTNAME;
            SUSPEND;
        END
    END
    ELSE
    BEGIN
        -- Прошлые учебные годы, берем по ученикам которые до сих пор остались в классе
        FOR
            SELECT DISTINCT V.SUBJECT_ID
            FROM VALM V
            JOIN LINKS L10 ON L10.PARENT_ID = :I$CLASS_ID AND L10.OBJ_ID = V.PUPIL_ID AND L10.DATE_DEL IS NULL
            WHERE V.YEAR_ID = :V$SCHOOL_YEAR_ID AND V.IS_DEL = 0
            INTO :SUBJECT_ID
        DO
        BEGIN

            -- Исключаем предметы ВД
            SELECT PARENT_ID
            FROM LINKS LP301
            WHERE LP301.OBJ_ID = :SUBJECT_ID AND LP301.PARENT_TYPE_ID = 301 AND LP301.DATE_DEL IS NULL
            INTO :V$SUBJECT_PARENT;

            IF(V$SUBJECT_PARENT IS NULL OR V$SUBJECT_PARENT = 32771) THEN
            BEGIN
                SELECT CAPTION, SORT_ORDER FROM OBJECT_CAPTION_GET(:SUBJECT_ID) INTO :SUBJECT_CAPTION, :SORT_ORDER;
                SELECT V FROM VAL_GET(:SUBJECT_ID, 377, 0, :I$USER_ID) INTO :SUBJECT_SHORTNAME;
                SUSPEND;
            END

        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FINALMARK_SUBJECT_FULL_LIST RETURNS (
    SUBJECT_ID BIGINT,
    SUBJECT_CAPTION VARCHAR(1000),
    SUBJECT_SHORTNAME VARCHAR(100),
    SUBJECT_ORDER VARCHAR(100))
AS
BEGIN
    FOR SELECT OBJ_ID
        FROM OBJECT_CHILDREN_GET_DEEP(208, 51, 2)
        INTO :SUBJECT_ID
    DO
    BEGIN
        SELECT CAPTION, SORT_ORDER
        FROM OBJECT_CAPTION_GET(:SUBJECT_ID)
        INTO :SUBJECT_CAPTION, :SUBJECT_ORDER;

        SELECT V
        FROM VAL_GET(:SUBJECT_ID, 377)
        INTO :SUBJECT_SHORTNAME;

        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FINALMARK_SUBJECT_LIST (
    I$PUPIL_ID BIGINT,
    I$YEAR_ID BIGINT)
RETURNS (
    SUBJECT_ID BIGINT,
    SUBJECT_CAPTION VARCHAR(1000),
    SUBJECT_SHORTNAME VARCHAR(100),
    SORT_ORDER INTEGER)
AS
declare variable CID bigint;
BEGIN
    FOR
        SELECT DISTINCT
               VM.SUBJECT_ID
        FROM VALM VM

        WHERE VM.PUPIL_ID = :I$PUPIL_ID
        AND VM.YEAR_ID = :I$YEAR_ID

        INTO :SUBJECT_ID
    DO
    BEGIN
        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:SUBJECT_ID)
        INTO :SUBJECT_CAPTION;

        SELECT V
        FROM VAL_GET(:SUBJECT_ID,377)
        INTO :SUBJECT_SHORTNAME;

        SELECT I
        FROM VAL_GET(:SUBJECT_ID,375)
        INTO :SORT_ORDER;

        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FINALMARK_SUBJECT_LIST2 (
    I$CLASS_ID BIGINT,
    I$YEAR_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    SUBJECT_ID BIGINT,
    SUBJECT_CAPTION VARCHAR(1000),
    SUBJECT_SHORTNAME VARCHAR(100),
    SORT_ORDER INTEGER)
AS
declare variable V$Y1 smallint;
declare variable V$Y2 smallint;
declare variable V$DT1 date;
declare variable V$SCHOOL_YEAR varchar(20);
declare variable V$DATE date;
declare variable LANG_CODE char(2);
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :LANG_CODE;

    IF (I$YEAR_ID IS NULL) THEN
    BEGIN
        V$Y1 = EXTRACT(YEAR FROM CURRENT_DATE);
        V$DT1 = V$Y1 || '-09-01';
        IF (CURRENT_DATE < V$DT1) THEN
        BEGIN
            V$Y2 = V$Y1;
            V$Y1 = V$Y1 - 1;
        END
        ELSE
        BEGIN
            V$Y2 = V$Y1 + 1;
        END
        V$SCHOOL_YEAR = V$Y1 || '-' || V$Y2;

        SELECT FIRST 1 LV.LISTVAL_ID
        FROM LISTVALS LV
        JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
        WHERE LV.LIST_ID = 29 AND R.VAL LIKE :V$SCHOOL_YEAR
        INTO :I$YEAR_ID;
    END

    SELECT LV.TAG
    FROM LISTVALS LV
    WHERE LV.LISTVAL_ID = :I$YEAR_ID
    INTO :V$DATE;

    FOR
        SELECT DISTINCT VM.SUBJECT_ID
        FROM PERSON_MOVEMENTS M
        JOIN VALM VM ON VM.PUPIL_ID = M.PERSON_ID AND VM.YEAR_ID = :I$YEAR_ID
        WHERE M.DATE_DEL IS NULL AND M.GROUP_ID = :I$CLASS_ID AND (M.DATE_OUT IS NULL OR M.DATE_OUT > :V$DATE)
        INTO :SUBJECT_ID
    DO
    BEGIN
        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:SUBJECT_ID, NULL, NULL,:I$USER_ID)
        INTO :SUBJECT_CAPTION;

        SELECT V
        FROM VAL_GET(:SUBJECT_ID,377,0,:I$USER_ID)
        INTO :SUBJECT_SHORTNAME;

        SELECT I
        FROM VAL_GET(:SUBJECT_ID,375,0,:I$USER_ID)
        INTO :SORT_ORDER;

        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FINALMARK_SYNCHRONIZE (
    I$FINAL_ID BIGINT)
AS
declare variable V$SUBJECT_ID bigint;
declare variable V$GROUP_ID bigint;
declare variable V$MARKTYPE_ID bigint;
declare variable V$MARKVAL_ID bigint;
declare variable V$TEACHER_ID bigint;
declare variable V$PUPIL_ID bigint;
declare variable V$Y smallint;
declare variable V$DT date;
declare variable V$YEAR_VAL varchar(100);
declare variable V$YEAR_ID bigint;
declare variable V$FINAL_DATE date;
declare variable V$STAGE_ID bigint;
declare variable V$GRADE_ID bigint;
declare variable V$MARK_DATE date;
declare variable V$IS_EXT smallint;
declare variable V$PLAN_ID bigint;
begin

    -- Процедура более неактуальна ! Была нужна только для переходного формата CJ

    V$SUBJECT_ID = NULL;
    V$GROUP_ID = NULL;
    V$MARKTYPE_ID = NULL;
    V$MARKVAL_ID = NULL;
    V$TEACHER_ID = NULL;
    V$YEAR_ID = NULL;

    -- Ищем SUBJECT, GROUP, MARK TYPE. TEACHER берем именно штатного предметника
    SELECT CJM.SUBJECT_ID, CJM.GRADE_ID, LV.LISTVAL_ID, CJF.FINAL_DATE, COALESCE(CJM.TEACHER_ID, CJF.TEACHER_ID), CJM.YEAR_ID, CJM.REF_ID
    FROM CJ2_JOURNAL CJM
    JOIN CJ2_JOURNAL_FINALS CJF ON CJM.OBJ_ID = CJF.CJ_ID
    JOIN LISTVALS LV ON LV.LIST_ID = 220 AND LV.LISTVAL_ID = CJF.FINAL_TYPE
    WHERE CJF.OBJ_ID = :I$FINAL_ID
    INTO :V$SUBJECT_ID, :V$GROUP_ID, :V$MARKTYPE_ID, :V$FINAL_DATE, :V$TEACHER_ID, :V$YEAR_ID, :V$PLAN_ID;

    -- Ищем учителя по старому формату - это больше не работает
    IF(V$TEACHER_ID IS NULL) THEN
    BEGIN
        SELECT FIRST 1 L14.PARENT_ID
        FROM LINKS L58
        JOIN LINKS L14 ON L14.OBJ_ID = L58.OBJ_ID AND L14.PARENT_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
        JOIN LINKS L56 ON L56.OBJ_ID = L58.OBJ_ID AND L56.PARENT_TYPE_ID = 56 AND L56.DATE_DEL IS NULL
        JOIN LINKS L51 ON L51.OBJ_ID = L56.PARENT_ID AND L51.PARENT_ID = :V$SUBJECT_ID AND L51.PARENT_TYPE_ID = 51 AND L51.DATE_DEL IS NULL
        WHERE L58.PARENT_ID = :V$GROUP_ID AND L58.OBJ_TYPE_ID = 58 AND L58.DATE_DEL IS NULL
        INTO :V$TEACHER_ID;
    END

    -- Учебный год
    IF(V$YEAR_ID IS NULL) THEN
    BEGIN
        V$Y = EXTRACT(YEAR FROM V$FINAL_DATE);
        V$DT = '31.08.' || V$Y;

        IF (V$FINAL_DATE < V$DT) THEN
        BEGIN
            V$YEAR_VAL = (V$Y - 1) || '-' || V$Y;
        END
        ELSE
        BEGIN
            V$YEAR_VAL = V$Y || '-' ||(V$Y + 1);
        END

        SELECT FIRST 1 LV.LISTVAL_ID
        FROM LISTVALS LV
        JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
        WHERE LV.LIST_ID = 29 AND R.VAL LIKE :V$YEAR_VAL
        INTO :V$YEAR_ID;
    END

    IF(V$MARKTYPE_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не удалось идентифицировать тип отметки';

    -- Кастомный тип оценки в школе
    IF(V$MARKTYPE_ID >= 1000000000) THEN EXIT;

    /*
    UPDATE VALM
    SET IS_DEL = 1
    WHERE YEAR_ID = :V$YEAR_ID
    AND SUBJECT_ID = :V$SUBJECT_ID
    AND MARKTYPE_ID = :V$MARKTYPE_ID;
    */

    FOR
        SELECT MT.FINAL_ID, CJM.STUDENT_ID, CJM.MARK_DATE
        FROM CJ2_MARK CJM
        JOIN CJ2_MARK_TYPE MT ON MT.MARK_TYPE_ID = CJM.MARK_TYPE_ID AND MT.FINAL_ID IS NOT NULL
        WHERE CJM.FINAL_ID = :I$FINAL_ID
        INTO :V$MARKVAL_ID, :V$PUPIL_ID, :V$MARK_DATE
    DO
    BEGIN
        -- Идентифицируем этап обучения на дату выставления отметки
        V$STAGE_ID = NULL;
        V$GRADE_ID = NULL;
        SELECT FIRST 1 M.STAGE_ID, G.OBJ_ID
        FROM PERSON_MOVEMENTS M
        JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID IN (9, 125, 187)
        WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :V$PUPIL_ID AND M.DATE_IN <= :V$FINAL_DATE AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :V$FINAL_DATE)
        INTO :V$STAGE_ID, :V$GRADE_ID;

        V$IS_EXT = 0;
        SELECT FIRST 1 1
        FROM PLAN_SUBJECTS PS
        WHERE PS.DATE_DEL IS NULL AND PS.PLAN_ID = :V$PLAN_ID AND PS.SUBJECT_ID = :V$SUBJECT_ID AND PS.IS_ADV = 1
        INTO :V$IS_EXT;

        UPDATE OR INSERT INTO VALM (PUPIL_ID, SUBJECT_ID, TEACHER_ID, YEAR_ID, MARKTYPE_ID, MARKVAL_ID, STAGE_ID, GRADE_ID, MARK_DATE, IS_DEL, IS_EXT)
        VALUES (:V$PUPIL_ID, :V$SUBJECT_ID, :V$TEACHER_ID, :V$YEAR_ID, :V$MARKTYPE_ID, :V$MARKVAL_ID, :V$STAGE_ID, :V$GRADE_ID, :V$MARK_DATE, 0, :V$IS_EXT)
        MATCHING (PUPIL_ID, SUBJECT_ID, YEAR_ID, MARKTYPE_ID);
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FINALMARK_TEACHER_LIST (
    I$SCHOOL_ID BIGINT,
    I$PLAN_ONLY SMALLINT = 0)
RETURNS (
    TEACHER_ID BIGINT,
    TEACHER_CAPTION VARCHAR(4000))
AS
declare variable C integer;
declare variable V$FIRED_ID bigint;
declare variable V$YEAR integer;
declare variable V$CURRENT_YEAR_ID bigint;
BEGIN
    SELECT FIRST 1 L.OBJ_ID
    FROM LINKS L
    WHERE L.PARENT_ID = :I$SCHOOL_ID AND L.OBJ_TYPE_ID = 84 AND L.DATE_DEL IS NULL
    INTO :V$FIRED_ID;

    V$YEAR = EXTRACT(YEAR FROM CURRENT_DATE);
    IF(EXTRACT(MONTH FROM CURRENT_DATE) < 9) THEN V$YEAR = V$YEAR - 1;

    SELECT FIRST 1 LISTVAL_ID
    FROM LISTVALS
    WHERE LIST_ID = 29 AND COST = :V$YEAR AND IS_DEL = 0
    INTO :V$CURRENT_YEAR_ID;

    FOR
        SELECT L14.OBJ_ID
        FROM LINKS L14
        WHERE L14.PARENT_ID = :I$SCHOOL_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL

        UNION

        SELECT L14.OBJ_ID
        FROM LINKS L14
        WHERE L14.PARENT_ID = :V$FIRED_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL

        INTO :TEACHER_ID
    DO
    BEGIN

        FOR
            SELECT FIRST 1 1
            FROM VALM V
            WHERE V.TEACHER_ID = :TEACHER_ID AND V.IS_DEL = 0 AND (:I$PLAN_ONLY = 0 OR V.YEAR_ID = :V$CURRENT_YEAR_ID)
            INTO :C
        DO
        BEGIN
            SELECT CAPTION FROM THE_CAPTION_TEACHER(:TEACHER_ID) INTO :TEACHER_CAPTION;

            SUSPEND;
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FINALMARK_YEAR_LIST RETURNS (
    LISTVAL_ID BIGINT,
    LIST_ID BIGINT,
    LANG_CODE CHAR(2),
    PARENT_ID BIGINT,
    VAL VARCHAR(4000),
    VAL_LONG VARCHAR(4000),
    TAG VARCHAR(100),
    SORT_ORDER SMALLINT,
    COST FLOAT,
    IS_REPL SMALLINT,
    IS_DEL SMALLINT,
    DATE_MODIFY TIMESTAMP)
AS
declare variable V$YEAR_ID integer;
declare variable V$TAG varchar(100);
BEGIN
    V$TAG = CURRENT_DATE -365;
    FOR
        SELECT DISTINCT
               YEAR_ID
        FROM VALM
        INTO :V$YEAR_ID
    DO
    BEGIN
        LISTVAL_ID = NULL;
       /* LIST_ID = NULL;
        LANG_CODE = NULL;
        PARENT_ID = NULL;
        VAL = NULL;
        VAL_LONG = NULL;
        TAG = NULL;
        SORT_ORDER = NULL;
        COST = NULL;
        IS_REPL = NULL;
        IS_DEL = NULL;
        DATE_MODIFY = NULL;  */

        SELECT FIRST 1
               LV.LISTVAL_ID,
               LV.LIST_ID,
               R.LANG_CODE,
               LV.PARENT_ID,
               R.VAL,
               R.VAL_LONG,
               LV.TAG,
               LV.SORT_ORDER,
               LV.COST,
               LV.IS_REPL,
               LV.IS_DEL,
               LV.DATE_MODIFY
        FROM LISTVALS LV

        JOIN RES R
        ON R.RES_ID = LV.RES_ID
        AND R.LANG_CODE = 'RU'

        WHERE LV.LISTVAL_ID = :V$YEAR_ID
        AND LV.IS_DEL = 0
        AND LV.TAG <= :V$TAG
        INTO LISTVAL_ID,
             LIST_ID,
             LANG_CODE,
             PARENT_ID,
             VAL,
             VAL_LONG,
             TAG,
             SORT_ORDER,
             COST,
             IS_REPL,
             IS_DEL,
             DATE_MODIFY;
        IF (:LISTVAL_ID IS NOT NULL) THEN
        BEGIN
            SUSPEND;
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIND_EMPLOYEE (
    I$FIRSTNAME VARCHAR(255),
    I$LASTNAME VARCHAR(255),
    I$MIDDLENAME VARCHAR(255),
    I$DOB DATE)
RETURNS (
    SCHOOL_ID BIGINT,
    SCHOOL_SHORTNAME VARCHAR(1000),
    EMPLOYEE_ID BIGINT,
    EMPLOYEE_FIRSTNAME VARCHAR(255),
    EMPLOYEE_LASTNAME VARCHAR(255),
    EMPLOYEE_MIDDLENAME VARCHAR(255),
    EMPLOYEE_DOB DATE,
    EMPLOYEE_VACANCYNAME VARCHAR(255),
    EMPLOYEE_TBL_NUM VARCHAR(100))
AS
DECLARE VARIABLE V$VACANCY_ID BIGINT;
BEGIN
    FOR
        SELECT V59.OBJ_ID,
               LP2.PARENT_ID,
               V59.VAL, 
               V60.VAL,
               V61.VAL,
               V241.VAL
        FROM VALS V59

        JOIN VALS V60
        ON V60.OBJ_ID = V59.OBJ_ID
        AND V60.PARAM_ID = 60
        AND V60.IS_DEL = 0
        AND UPPER(V60.SVAL) = UPPER(:I$FIRSTNAME)

        LEFT JOIN VALS V61
        ON V61.OBJ_ID = V59.OBJ_ID
        AND V61.PARAM_ID = 61
        AND V61.IS_DEL = 0

        JOIN VALD V241
        ON V241.OBJ_ID = V59.OBJ_ID
        AND V241.PARAM_ID = 241
        AND V241.IS_DEL = 0
        AND (:I$DOB IS NULL OR V241.VAL = :I$DOB)

        JOIN LINKS LP2
        ON LP2.OBJ_ID = V59.OBJ_ID
        AND LP2.PARENT_TYPE_ID IN (2, 211)
        AND LP2.DATE_DEL IS NULL

        WHERE UPPER(V59.SVAL) = UPPER(:I$LASTNAME)
        AND V59.PARAM_ID = 59
        AND V59.IS_DEL = 0
        AND ((:I$MIDDLENAME IS NULL) OR (UPPER(V61.SVAL) = UPPER(:I$MIDDLENAME)))

        INTO :EMPLOYEE_ID,
             :SCHOOL_ID,
             :EMPLOYEE_LASTNAME,
             :EMPLOYEE_FIRSTNAME,
             :EMPLOYEE_MIDDLENAME,
             :EMPLOYEE_DOB
    DO
    BEGIN
        SELECT V
        FROM VAL_GET(:EMPLOYEE_ID, 273)
        INTO :EMPLOYEE_TBL_NUM;

        SELECT V
        FROM VAL_GET(:SCHOOL_ID, 2)
        INTO :SCHOOL_SHORTNAME;

        EMPLOYEE_VACANCYNAME = NULL;

        FOR
            SELECT FIRST 1
                   L15.OBJ_ID
            FROM LINKS L15

            JOIN VALL V72
            ON V72.OBJ_ID = L15.OBJ_ID
            AND V72.PARAM_ID = 72
            AND V72.IS_DEL = 0
            AND V72.LISTVAL_ID = 934

            JOIN VALD V73
            ON V73.OBJ_ID = L15.OBJ_ID
            AND V73.PARAM_ID = 73
            AND V73.IS_DEL = 0
            AND V73.VAL <= CURRENT_DATE

            LEFT JOIN VALD V74
            ON V74.OBJ_ID = L15.OBJ_ID
            AND V74.PARAM_ID = 74
            AND V74.IS_DEL = 0

            WHERE L15.PARENT_ID = :EMPLOYEE_ID
            AND L15.OBJ_TYPE_ID = 15
            AND L15.DATE_DEL IS NULL
            AND ((V74.OBJ_ID IS NULL) OR (V74.VAL > CURRENT_DATE))

            INTO :V$VACANCY_ID
        DO
        BEGIN
            SELECT V
            FROM VAL_GET(:V$VACANCY_ID, 3543)
            INTO :EMPLOYEE_VACANCYNAME;
        END

        SUSPEND;
    END

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIN_CONFIG_GET (
    PARAM_NAME VARCHAR(100))
RETURNS (
    PARAM_VALUE VARCHAR(1000))
AS
begin

  IF(PARAM_NAME = 'CAT_NUM') THEN
  BEGIN
    -- Количество сечений для организаций
    PARAM_VALUE = '5';
    SUSPEND;
  END
  ELSE IF(PARAM_NAME = 'CAT_NAME_1') THEN
  BEGIN
    PARAM_VALUE = 'Район';
    SUSPEND;
  END
  ELSE IF(PARAM_NAME = 'CAT_NAME_2') THEN
  BEGIN
    PARAM_VALUE = 'Адаптивная УП';
    SUSPEND;
  END
  ELSE IF(PARAM_NAME = 'CAT_NAME_3') THEN
  BEGIN
    PARAM_VALUE = 'Начальное образование';
    SUSPEND;
  END
  ELSE IF(PARAM_NAME = 'CAT_NAME_4') THEN
  BEGIN
    PARAM_VALUE = 'Основное образование';
    SUSPEND;
  END
  ELSE IF(PARAM_NAME = 'CAT_NAME_5') THEN
  BEGIN
    PARAM_VALUE = 'Среднее образование';
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIN_LISTS_GET (
    PARENT_ID BIGINT)
RETURNS (
    ID BIGINT,
    OBJ_TYPE SMALLINT,
    NAME VARCHAR(1000),
    IS_ACTIVE SMALLINT)
AS
begin
  IF(PARENT_ID IS NULL) THEN PARENT_ID = 0;
  FOR
    SELECT FL.ID, FL.OBJ_TYPE, FL.NAME, FL.IS_ACTIVE
    FROM FIN_LISTS FL
    WHERE FL.PARENT_ID = :PARENT_ID AND FL.DATE_DEL IS NULL
    ORDER BY 2
    INTO :ID, :OBJ_TYPE, :NAME, :IS_ACTIVE
  DO
  BEGIN
    IF(OBJ_TYPE = 2) THEN
    BEGIN
        SELECT NAME
        FROM FIN_ORG_LIST
        WHERE ID = :ID
        INTO :NAME;
    END
    SUSPEND;
  END
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIN_LIST_DELETE (
    ID BIGINT NOT NULL)
AS
declare variable V$ID bigint;
begin
  -- Не давать удалять корень дерева
  IF(ID = 0) THEN EXIT;
  -- Удаляем все вложенные объекты
  FOR
    SELECT ID
    FROM FIN_LISTS
    WHERE PARENT_ID = :ID
    INTO :V$ID
  DO
  BEGIN
    EXECUTE PROCEDURE FIN_LIST_DELETE(:V$ID);
  END
  -- Удаляем сам родительский объект
  DELETE FROM FIN_LISTS WHERE ID = :ID;
end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIN_LIST_UPDATE (
    PARENT_ID BIGINT,
    ID BIGINT,
    OBJ_TYPE SMALLINT,
    NAME VARCHAR(1000),
    IS_ACTIVE SMALLINT)
RETURNS (
    O$ID BIGINT)
AS
begin

    IF(OBJ_TYPE in (0, 1)) THEN IS_ACTIVE = 1;

    UPDATE OR INSERT INTO FIN_LISTS
    (ID, PARENT_ID, OBJ_TYPE, NAME, IS_ACTIVE)
    VALUES (:ID, :PARENT_ID, :OBJ_TYPE, :NAME, :IS_ACTIVE)
    RETURNING ID into :O$ID;

    SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIN_ORG_APPLY_SETTINGS (
    ID BIGINT,
    SETTING_NAME VARCHAR(100),
    SETTING_VALUE VARCHAR(1000))
AS
declare variable TMP bigint;
begin

    IF(SETTING_NAME = 'IS_ACTIVE') THEN
    BEGIN
        IF(SETTING_VALUE = '1') THEN
        BEGIN
            select ID from VAL_ADD(2817, :ID, '3') into :TMP;
        END
        ELSE BEGIN
            select ID from VAL_ADD(2817, :ID, '2') into :TMP;
        END
    END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIN_ORG_LIST RETURNS (
    ID BIGINT,
    IS_ACTIVE INTEGER,
    NAME VARCHAR(1000),
    CAT1 VARCHAR(1000),
    CAT2 VARCHAR(1000),
    CAT3 VARCHAR(1000),
    CAT4 VARCHAR(1000),
    CAT5 VARCHAR(1000))
AS
declare variable V$ADAPT bigint;
declare variable V$OPTYPE bigint;
begin
  FOR
    SELECT L2.OBJ_ID, V2817.LISTVAL_ID, V2.VAL, COALESCE(R665.VAL, 'Текущий район')
    FROM LINKS L2
    JOIN VALS V2 on V2.OBJ_ID = L2.OBJ_ID and V2.PARAM_ID = 2 and V2.IS_DEL = 0
    LEFT JOIN VALL V2817 on V2817.OBJ_ID = L2.OBJ_ID and V2817.PARAM_ID = 2817 and V2817.IS_DEL = 0
    LEFT JOIN VALL V665 on V665.OBJ_ID = L2.PARENT_ID and V665.PARAM_ID IN (665, 1406) and V665.IS_DEL = 0
    LEFT JOIN LISTVALS LV665 on LV665.LISTVAL_ID = V665.LISTVAL_ID and LV665.IS_DEL = 0
    LEFT JOIN RES R665 on R665.RES_ID = LV665.RES_ID and R665.LANG_CODE = 'RU'
    WHERE L2.OBJ_TYPE_ID = 2 AND (L2.PARENT_TYPE_ID is null OR L2.PARENT_TYPE_ID = 111) and L2.DATE_DEL is null
    INTO :ID, :IS_ACTIVE, :NAME, :CAT1
  DO
  BEGIN
    IF(IS_ACTIVE is null) THEN IS_ACTIVE = 0;
    ELSE IF(IS_ACTIVE = 3) THEN IS_ACTIVE = 1;
    ELSE IS_ACTIVE = 0;

    CAT2 = '';
    CAT3 = '';
    CAT4 = '';
    CAT5 = '';

    -- Информация по реализуемым ОП
    FOR
        SELECT V2379.LISTVAL_ID, V1832.LISTVAL_ID
        FROM LINKS L69
        JOIN LINKS L57 on L57.PARENT_ID = L69.OBJ_ID and L57.OBJ_TYPE_ID = 57 and L57.DATE_DEL is null
        LEFT JOIN VALL V2379 on V2379.OBJ_ID = L57.OBJ_ID and V2379.PARAM_ID = 2379 and V2379.IS_DEL = 0
        JOIN VALL V1832 on V1832.OBJ_ID = L57.OBJ_ID and V1832.PARAM_ID = 1832 and V1832.IS_DEL = 0
        WHERE L69.PARENT_ID = :ID and L69.OBJ_TYPE_ID = 69 and L69.DATE_DEL is null
        INTO :V$ADAPT, :V$OPTYPE
    DO
    BEGIN
        IF(V$ADAPT = 11187) THEN CAT2 = 'Да';
        IF(V$OPTYPE IN (5339, 5340)) THEN CAT3 = 'Да';
        IF(V$OPTYPE IN (5341, 5342)) THEN CAT4 = 'Да';
        IF(V$OPTYPE IN (5343, 5344)) THEN CAT5 = 'Да';
    END

    SUSPEND;
  END
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIN_PARAMS_GET (
    GROUP_ID BIGINT)
RETURNS (
    PARAM_ID BIGINT,
    NAME VARCHAR(1000),
    PARAM_SOURCE VARCHAR(1000),
    PARAM_PATH VARCHAR(100),
    DIRECTION SMALLINT,
    K_WEIGHT DOUBLE PRECISION,
    DISPLAY_ORDER INTEGER)
AS
begin
  FOR
    SELECT PARAM_ID, NAME, PARAM_SOURCE, PARAM_PATH, DIRECTION, K_WEIGHT, DISPLAY_ORDER
    FROM FIN_PARAMS
    WHERE GROUP_ID = :GROUP_ID
    ORDER BY DISPLAY_ORDER
    INTO :PARAM_ID, :NAME, :PARAM_SOURCE, :PARAM_PATH, :DIRECTION, :K_WEIGHT, :DISPLAY_ORDER
  DO
  BEGIN
    SUSPEND;
  END
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIN_PARAM_DELETE (
    PARAM_ID BIGINT)
AS
begin
  UPDATE FIN_PARAMS
  SET DATE_DEL = CURRENT_TIMESTAMP
  WHERE PARAM_ID = :PARAM_ID;
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIN_PARAM_GROUPS_GET RETURNS (
    ID BIGINT,
    NAME VARCHAR(1000),
    DISPLAY_ORDER INTEGER)
AS
begin
  FOR
    SELECT DISPLAY_ORDER, ID, NAME
    FROM FIN_PARAM_GROUPS
    WHERE DATE_DEL IS NULL
    ORDER BY 1
    INTO :DISPLAY_ORDER, :ID, :NAME
  DO
  BEGIN
    SUSPEND;
  END
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIN_PARAM_GROUP_DELETE (
    GROUP_ID BIGINT)
AS
declare variable V$PARAM_ID bigint;
begin
  UPDATE FIN_PARAM_GROUPS
  SET DATE_DEL = CURRENT_TIMESTAMP
  WHERE ID = :GROUP_ID;

  FOR
    SELECT PARAM_ID
    FROM FIN_PARAMS
    WHERE GROUP_ID = :GROUP_ID
    INTO :V$PARAM_ID
  DO
  BEGIN
    EXECUTE PROCEDURE FIN_PARAM_DELETE(:V$PARAM_ID);
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIN_PARAM_GROUP_UPDATE (
    ID BIGINT,
    NAME VARCHAR(1000),
    DISPLAY_ORDER INTEGER)
RETURNS (
    O$ID BIGINT)
AS
begin
    IF(DISPLAY_ORDER IS NULL) THEN
    BEGIN
        IF(ID IS NULL) THEN
        BEGIN
            SELECT MAX(DISPLAY_ORDER) + 1
            FROM FIN_PARAM_GROUPS
            WHERE DATE_DEL IS NULL
            INTO :DISPLAY_ORDER;
        END
        ELSE
        BEGIN
            SELECT DISPLAY_ORDER
            FROM FIN_PARAM_GROUPS
            WHERE ID = :ID
            INTO :DISPLAY_ORDER;
        END

        IF(DISPLAY_ORDER IS NULL) THEN DISPLAY_ORDER = 0;
    END

    UPDATE OR INSERT INTO FIN_PARAM_GROUPS
    (ID, NAME, DISPLAY_ORDER)
    VALUES (:ID, :NAME, :DISPLAY_ORDER)
    RETURNING ID into :O$ID;

    SUSPEND;
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIN_PARAM_UPDATE (
    GROUP_ID BIGINT,
    PARAM_ID BIGINT,
    NAME VARCHAR(1000),
    PARAM_SOURCE VARCHAR(1000),
    PARAM_PATH VARCHAR(100),
    DIRECTION SMALLINT,
    K_WEIGHT DOUBLE PRECISION,
    DISPLAY_ORDER INTEGER)
RETURNS (
    O$PARAM_ID BIGINT)
AS
begin
    IF(DISPLAY_ORDER IS NULL) THEN
    BEGIN
        IF(PARAM_ID IS NULL) THEN
        BEGIN
            SELECT MAX(DISPLAY_ORDER) + 1
            FROM FIN_PARAMS
            WHERE DATE_DEL IS NULL AND GROUP_ID = :GROUP_ID
            INTO :DISPLAY_ORDER;
        END
        ELSE
        BEGIN
            SELECT DISPLAY_ORDER
            FROM FIN_PARAMS
            WHERE PARAM_ID = :PARAM_ID
            INTO :DISPLAY_ORDER;
        END

        IF(DISPLAY_ORDER IS NULL) THEN DISPLAY_ORDER = 0;
    END


    UPDATE OR INSERT INTO FIN_PARAMS
    (GROUP_ID, PARAM_ID, NAME, PARAM_SOURCE, PARAM_PATH, DIRECTION, K_WEIGHT, DISPLAY_ORDER)
    VALUES (:GROUP_ID, :PARAM_ID, :NAME, :PARAM_SOURCE, :PARAM_PATH, :DIRECTION, :K_WEIGHT, :DISPLAY_ORDER)
    RETURNING PARAM_ID into :O$PARAM_ID;

    SUSPEND;
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIN_VALUES_CLEAR (
    PARAM_ID BIGINT,
    RANGE_ID BIGINT)
AS
begin

    delete from FIN_VALUES
    where PARAM_ID = :PARAM_ID and RANGE_ID = :RANGE_ID;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIN_VALUE_GET (
    SCHOOL_ID BIGINT,
    PARAM_ID BIGINT,
    RANGE_ID BIGINT)
RETURNS (
    VAL DOUBLE PRECISION,
    K_WEIGHT DOUBLE PRECISION)
AS
declare variable V$PATH varchar(100);
declare variable V$DIRECTION smallint;
declare variable V$P integer;
declare variable V$I bigint;
declare variable V$PARAM varchar(100);
begin
  /* Для параметров, где указан путь - берем из мониторинга; гду путь пустой - берем непосредственно из значений */
  select PARAM_PATH, K_WEIGHT, DIRECTION
  from FIN_PARAMS
  where PARAM_ID = :PARAM_ID
  into :V$PATH, :K_WEIGHT, :V$DIRECTION;

  IF(K_WEIGHT is null) THEN EXIT;

  -- Инвертируем знак для параметров, по которым влияение падает с ростом параметра
  IF(V$DIRECTION = 1 and K_WEIGHT is not null) THEN K_WEIGHT = K_WEIGHT * -1;

  IF(V$PATH IS NULL or V$PATH = '') THEN
  BEGIN
    
    -- Берем из таблицы значений
    select VAL
    from FIN_VALUES
    where SCHOOL_ID = :SCHOOL_ID and PARAM_ID = :PARAM_ID and RANGE_ID = :RANGE_ID
    into :VAL;

    SUSPEND;

  END
  ELSE BEGIN

    -- Пытаемся выбрать значение из мониторинга
    -- Пока учебный период не учитываем !!!

    /*
    Возможные варианты значений:
    N - взять значение из параметра с номером N (INTEGER или DOUBLE)
    N.# - сумма количества строк вложенных объектов типа N
    N.M - значение параметра M вложенного объекта типа N

    */

    IF(POSITION('.' in V$PATH) = 0) THEN
    BEGIN
        -- Непосредственный код параметра
        select VI.I, VI.V
        from LINKS L162
        left join VAL_GET(L162.OBJ_ID, CAST(:V$PATH as integer)) VI on 1=1
        where L162.PARENT_ID = :SCHOOL_ID and L162.OBJ_TYPE_ID = 162 and L162.DATE_DEL is null
        into :V$I, :VAL;

        IF(VAL is null) THEN VAL = V$I;
        SUSPEND;
    END
    ELSE IF(POSITION('.#' in V$PATH) > 0) THEN
    BEGIN
        -- Формат N.#
        V$P = POSITION('.#' in V$PATH);
        V$PATH = SUBSTRING(V$PATH from 1 for (V$P - 1));

        select count(*)
        from LINKS L162
        join LINKS LX on LX.PARENT_ID = L162.OBJ_ID and LX.OBJ_TYPE_ID = CAST(:V$PATH as integer) and LX.DATE_DEL is null
        where L162.PARENT_ID = :SCHOOL_ID and L162.OBJ_TYPE_ID = 162 and L162.DATE_DEL is null
        into :VAL;
    END
    ELSE BEGIN
        -- Формат N.M
        V$P = POSITION('.' in V$PATH);
        V$PARAM = SUBSTRING(V$PATH from (V$P + 1));
        V$PATH = SUBSTRING(V$PATH from 1 for (V$P - 1));

        select VI.I, VI.V
        from LINKS L162
        join LINKS LX on LX.PARENT_ID = L162.OBJ_ID and LX.OBJ_TYPE_ID = CAST(:V$PATH as integer) and LX.DATE_DEL is null
        left join VAL_GET(LX.OBJ_ID, CAST(:V$PARAM as integer)) VI on 1=1
        where L162.PARENT_ID = :SCHOOL_ID and L162.OBJ_TYPE_ID = 162 and L162.DATE_DEL is null
        into :V$I, :VAL;

        IF(VAL is null) THEN VAL = V$I;
        SUSPEND;
    END

  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIN_VALUE_SET (
    SCHOOL_ID BIGINT,
    PARAM_ID BIGINT,
    RANGE_ID BIGINT,
    VAL DOUBLE PRECISION)
AS
begin

    UPDATE OR INSERT INTO FIN_VALUES
    (SCHOOL_ID, PARAM_ID, RANGE_ID, VAL)
    VALUES (:SCHOOL_ID, :PARAM_ID, :RANGE_ID, :VAL);

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIXER
AS
BEGIN
    -- EXECUTE PROCEDURE FIXER1;
    -- EXECUTE PROCEDURE FIXER2;
    -- EXECUTE PROCEDURE FIXER3;
    EXECUTE PROCEDURE FIXER4;
    EXECUTE PROCEDURE FIXER5;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIXER3
AS
declare variable CNT integer;
declare variable KEY_LEVEL varchar(100);
declare variable V$OU_LICENCE_TYPE varchar(1);
declare variable SCHOOL_ID bigint;
declare variable V$OBJ_ID bigint;
declare variable V$S varchar(1000);
declare variable V1 integer;
declare variable V2 integer;
BEGIN
    SELECT FIRST 1 L.OBJ_ID
    FROM LINKS L
    WHERE L.PARENT_ID IS NULL
      AND L.OBJ_TYPE_ID = 2
      AND L.DATE_DEL IS NULL
    INTO :SCHOOL_ID;

    SELECT K.KEY_VAL
    FROM KEYS K
    WHERE K.KEY_CODE = 'LEVEL'
    INTO :KEY_LEVEL;
    SELECT STATUS FROM OU_LICENCE_TYPE INTO :V$OU_LICENCE_TYPE;

    /*19.01.2015 -- ADD COUNT PUPILS DISTRICT PLAN*/
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX: ADD COUNT PUPILS DISTRICT PLAN'
    INTO :CNT;
    IF ((CNT = 0) AND (KEY_LEVEL = 2)) THEN
    BEGIN
        EXECUTE PROCEDURE PLAN_COUNT_PUPIL_DISTRICT_ADD;

        INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
        VALUES ('FIX: ADD COUNT PUPILS DISTRICT PLAN', 'ADD COUNT PUPILS DISTRICT PLAN', CURRENT_TIMESTAMP);
    END

    /*22.01.2015 -- ADD PROFILE PLAN*/
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX: ADD COUNT ODOD DISTRICT PLAN'
    INTO :CNT;
    IF ((CNT = 0) AND (KEY_LEVEL = 1)) THEN
    BEGIN
        EXECUTE PROCEDURE PLAN_COUNT_ODOD_DISTRICT_ADD;

        INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
        VALUES ('FIX: ADD COUNT ODOD DISTRICT PLAN', 'ADD COUNT ODOD DISTRICT PLAN', CURRENT_TIMESTAMP);
    END

    /*26.01.2015 -- ADD COUNT PUPILS REGION PLAN*/
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX: ADD COUNT PUPILS REGION PLAN'
    INTO :CNT;
    IF ((CNT = 0) AND (KEY_LEVEL = 3)) THEN
    BEGIN
        EXECUTE PROCEDURE PLAN_COUNT_PUPIL_REGION_ADD;

        INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
        VALUES ('FIX: ADD COUNT PUPILS REGION PLAN', 'ADD COUNT PUPILS REGION PLAN', CURRENT_TIMESTAMP);
    END

    /*27.01.2015 -- SKILL RAISER CHANGE OOOD NAMES*/
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX: SKILL RAISER CHANGE OOOD NAMES'
    INTO :CNT;
    IF ((CNT = 0) AND (KEY_LEVEL = 1)) THEN
    BEGIN
        EXECUTE PROCEDURE FIXER_RAISER_SKILL_OOOD(304, 2335);
        EXECUTE PROCEDURE FIXER_RAISER_SKILL_OOOD(296, 2334);

        INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
        VALUES ('FIX: SKILL RAISER CHANGE OOOD NAMES', 'SKILL RAISER CHANGE OOOD NAMES', CURRENT_TIMESTAMP);
    END

    /*10.02.2015 -- FIX HOSEBASED PUPIL EDUCATION ATTRIBUTE*/
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX: HOMEBASED PUPIL EDUCATION ATTRIBUTE'
    INTO :CNT;
    IF ((CNT = 0) AND (KEY_LEVEL = 1) AND (V$OU_LICENCE_TYPE = 'O')) THEN
    BEGIN
        EXECUTE PROCEDURE FIXER_HOMEBASED_EDU_ATTR;

        INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
        VALUES ('FIX: HOMEBASED PUPIL EDUCATION ATTRIBUTE', 'FIX HOMEBASED PUPIL EDUCATION ATTRIBUTE', CURRENT_TIMESTAMP);
    END

    /*06.04.2015 -- FIX ENTERING PUPILS TO STAGE */
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX: ENTERING PUPILS TO STAGE'
    INTO :CNT;
    IF ((CNT = 0) AND (KEY_LEVEL = 1)) THEN
    BEGIN
        EXECUTE PROCEDURE FIX_ENTERING_PUPILS_TO_STAGE(:SCHOOL_ID);

        INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
        VALUES ('FIX: ENTERING PUPILS TO STAGE', 'FIX ENTERING PUPILS TO STAGE', CURRENT_TIMESTAMP);
    END

    /* 04.05.2015, 06.02.2019 -- Должности при повышении квалификации. Второй цикл 06.02 для ДОУ */
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX: SKILL RAISER CHANGE JOB 2'
    INTO :CNT;
    IF ((CNT = 0) AND (KEY_LEVEL = 1)) THEN
    BEGIN
        EXECUTE PROCEDURE FIXER_RAISER_SKILL_JOB(34, 295, 2347);
        EXECUTE PROCEDURE FIXER_RAISER_SKILL_JOB(156, 1235, 2348);

        INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
        VALUES ('FIX: SKILL RAISER CHANGE JOB 2', 'SKILL RAISER CHANGE JOB2', CURRENT_TIMESTAMP);
    END

    /*12.05.2015 -- FIX DOU PUPIL INPUT TO NEW FORMAT */
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX: DOU PUPIL INPUT TO NEW FORMAT'
    INTO :CNT;
    IF ((CNT = 0) AND (KEY_LEVEL = 1) AND (V$OU_LICENCE_TYPE = 'D')) THEN
    BEGIN
        EXECUTE PROCEDURE FIXER_DOU_INPUT(:SCHOOL_ID);

        INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
        VALUES ('FIX: DOU PUPIL INPUT TO NEW FORMAT', 'FIX DOU PUPIL INPUT TO NEW FORMAT', CURRENT_TIMESTAMP);
    END

    /*07.09.2015 -- FIX PUPIL FINISH TO LEAVED */
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX: PUPIL FINISH TO LEAVED'
    INTO :CNT;
    IF ((CNT = 0) AND (KEY_LEVEL = 1)) THEN
    BEGIN
        EXECUTE PROCEDURE FIXER_PUPIL_FINISH_TO_LEAVED;

        INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
        VALUES ('FIX: PUPIL FINISH TO LEAVED', 'FIX PUPIL FINISH TO LEAVED', CURRENT_TIMESTAMP);
    END

    /*05.10.2015 -- FIX PUPIL LEAVED TO FAMILY */
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX: PUPIL LEAVED TO FAMILY'
    INTO :CNT;
    IF ((CNT = 0) AND (KEY_LEVEL = 1) AND (V$OU_LICENCE_TYPE = 'O')) THEN
    BEGIN
        UPDATE VALL V105
        SET LISTVAL_ID = 11200
        WHERE V105.PARAM_ID = 105
        AND V105.IS_DEL = 0
        AND V105.DATE_MODIFY >= '2015-09-20 00:00:00'
        AND V105.LISTVAL_ID = 913;

        INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
        VALUES ('FIX: PUPIL LEAVED TO FAMILY', 'FIX PUPIL LEAVED TO FAMILY', CURRENT_TIMESTAMP);
    END

    /*07.10.2015 -- FIX CLEAR TEACHER LABOR RATE */
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX: CLEAR TEACHER LABOR RATE'
    INTO :CNT;
    IF ((CNT = 0) AND (KEY_LEVEL = 1) AND (V$OU_LICENCE_TYPE = 'O')) THEN
    BEGIN
        EXECUTE PROCEDURE FIXER_CLEAR_TEACHER_LABOR_RATE(:SCHOOL_ID);

        INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
        VALUES ('FIX: CLEAR TEACHER LABOR RATE', 'FIX CLEAR TEACHER LABOR RATE', CURRENT_TIMESTAMP);
    END

    /*26.11.2015 -- ADD MONITORING CONTINGENT DO*/
    /*Исключено 06.12.2016*/
    /*SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX: ADD MONITORING CONTINGENT DO'
    INTO :CNT;
    IF ((CNT = 0) AND (KEY_LEVEL = 1)) THEN
    BEGIN
        EXECUTE PROCEDURE MONITORING_CONTINGENT_DO_ADD;

        INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
        VALUES ('FIX: ADD MONITORING CONTINGENT DO', 'FIX ADD MONITORING CONTINGENT DO', CURRENT_TIMESTAMP);
    END*/

    /*01.12.2015 -- NEW GIA CLASS TYPER*/
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX: NEW GIA CLASS TYPER'
    INTO :CNT;
    IF ((CNT = 0) AND (KEY_LEVEL = 1) AND (V$OU_LICENCE_TYPE IN ('O','C'))) THEN
    BEGIN
        EXECUTE PROCEDURE FIXER_GIA_CLASS_TYPE(:SCHOOL_ID);

        INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
        VALUES ('FIX: NEW GIA CLASS TYPER', 'FIX NEW GIA CLASS TYPER', CURRENT_TIMESTAMP);
    END

    /*02.12.2015 -- NEW GIA CLASS TYPER2*/
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX: NEW GIA CLASS TYPER2'
    INTO :CNT;
    IF ((CNT = 0) AND (KEY_LEVEL = 1) AND (V$OU_LICENCE_TYPE = 'O')) THEN
    BEGIN
        EXECUTE PROCEDURE FIXER_GIA_CLASS_TYPE2(:SCHOOL_ID);

        INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
        VALUES ('FIX: NEW GIA CLASS TYPER2', 'FIX NEW GIA CLASS TYPER2', CURRENT_TIMESTAMP);
    END

    /*15.12.2015 -- NEW GIA CLASS TYPER3*/
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX: NEW GIA CLASS TYPER3'
    INTO :CNT;
    IF ((CNT = 0) AND (KEY_LEVEL = 1) AND (V$OU_LICENCE_TYPE = 'O')) THEN
    BEGIN
        EXECUTE PROCEDURE FIXER_GIA_CLASS_TYPE3;

        INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
        VALUES ('FIX: NEW GIA CLASS TYPER3', 'FIX NEW GIA CLASS TYPER3', CURRENT_TIMESTAMP);
    END

    /*24.12.2015 -- FIX DEFAULT VALUE FOR PARAM_ID = 1340 IN COLLEGE */
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX: DEFAULT VALUE FOR PARAM_ID = 1340 IN COLLEGE'
    INTO :CNT;
    IF ((CNT = 0) AND (KEY_LEVEL = 1) AND (V$OU_LICENCE_TYPE = 'C')) THEN
    BEGIN
        EXECUTE PROCEDURE FIXER_PARAM_ID_1340;

        INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
        VALUES ('FIX: DEFAULT VALUE FOR PARAM_ID = 1340 IN COLLEGE', 'FIX DEFAULT VALUE FOR PARAM_ID = 1340 IN COLLEGE', CURRENT_TIMESTAMP);
    END

    /*18.01.2016 -- FIX FIZKULTURA INSTRUCTOR 1293 -> 150 */
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX: FIZKULTURA INSTRUCTOR 1293 -> 150'
    INTO :CNT;
    IF ((CNT = 0) AND (KEY_LEVEL = 1)) THEN
    BEGIN
        UPDATE VALL
        SET LISTVAL_ID = 150
        WHERE LISTVAL_ID = 1293
        AND IS_DEL = 0;

        INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
        VALUES ('FIX: FIZKULTURA INSTRUCTOR 1293 -> 150', 'FIX FIZKULTURA INSTRUCTOR 1293 -> 150', CURRENT_TIMESTAMP);
    END

    /*11.03.2016 -- FIX PARAM 2112 SET TYPE FROM LIST_VALUE TO STRING_OR_LIST_VALUE*/
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX: PARAM 2112 SET TYPE FROM LIST_VALUE TO STRING_OR_LIST_VALUE'
    INTO :CNT;
    IF ((CNT = 0) AND (V$OU_LICENCE_TYPE = 'U')) THEN
    BEGIN
        EXECUTE PROCEDURE FIXER_PARAM_TYPE_SET(2112, 7);

        INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
        VALUES ('FIX: PARAM 2112 SET TYPE FROM LIST_VALUE TO STRING_OR_LIST_VALUE', 'PARAM 2112 SET TYPE FROM LIST_VALUE TO STRING_OR_LIST_VALUE', CURRENT_TIMESTAMP);
    END

    /*25.03.2016 -- FIX PARAM 2448 SET VALUE*/
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX: PARAM 2448 SET VALUE'
    INTO :CNT;
    IF ((CNT = 0) AND (KEY_LEVEL = 1) AND (V$OU_LICENCE_TYPE = 'U')) THEN
    BEGIN
        EXECUTE PROCEDURE FIXER_UDOD_P2448;

        INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
        VALUES ('FIX: PARAM 2448 SET VALUE', 'FIX PARAM 2448 SET VALUE', CURRENT_TIMESTAMP);
    END

    /*29.03.2016 -- OPLATA SODERJANIA MOVE TO EXT*/
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX: OPLATA SODERJANIA MOVE TO EXT'
    INTO :CNT;
    IF ((CNT = 0) AND (KEY_LEVEL = 1)) THEN
    BEGIN
        EXECUTE PROCEDURE FIXER_PARENTS_DOU;

        INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
        VALUES ('FIX: OPLATA SODERJANIA MOVE TO EXT', 'OPLATA SODERJANIA MOVE TO EXT', CURRENT_TIMESTAMP);
    END

    /*26.04.2016 -- CLEAR LEEVED EMPLOYEE STATUS*/
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX: CLEAR LEEVED EMPLOYEE STATUS'
    INTO :CNT;
    IF (CNT = 0) THEN
    BEGIN
        EXECUTE PROCEDURE CLEAR_LEEVED_EMPLOYEE_STATUS;

        INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
        VALUES ('FIX: CLEAR LEEVED EMPLOYEE STATUS', 'CLEAR LEEVED EMPLOYEE STATUS', CURRENT_TIMESTAMP);
    END

    /*16.05.2016 -- FIX PARAM 2448 SET VALUE2*/
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX: PARAM 2448 SET VALUE2'
    INTO :CNT;
    IF ((CNT = 0) AND (KEY_LEVEL = 1) AND (V$OU_LICENCE_TYPE = 'U')) THEN
    BEGIN
        EXECUTE PROCEDURE FIXER_UDOD_P2448;

        INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
        VALUES ('FIX: PARAM 2448 SET VALUE2', 'FIX PARAM 2448 SET VALUE2', CURRENT_TIMESTAMP);
    END

    /*29.05.2016 -- OPLATA SODERJANIA MOVE TO EXT, FIX NULL EXT OBJECT*/
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX: OPLATA SODERJANIA MOVE TO EXT, FIX NULL EXT OBJECT'
    INTO :CNT;
    IF ((CNT = 0) AND (KEY_LEVEL = 1)) THEN
    BEGIN
        EXECUTE PROCEDURE FIXER_PARENT_EXT_DOU;

        INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
        VALUES ('FIX: OPLATA SODERJANIA MOVE TO EXT, FIX NULL EXT OBJECT', 'OPLATA SODERJANIA MOVE TO EXT, FIX NULL EXT OBJECT', CURRENT_TIMESTAMP);
    END

    /*24.06.2016 -- DOLJNOST PARAM 64*/
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX: DOLJNOST PARAM 64'
    INTO :CNT;
    IF ((CNT = 0) AND (KEY_LEVEL = 1)) THEN
    BEGIN
        EXECUTE PROCEDURE FIXER_P64;

        INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
        VALUES ('FIX: DOLJNOST PARAM 64', 'DOLJNOST PARAM 64', CURRENT_TIMESTAMP);
    END

    /*11.10.2016 -- FIX PUPIL STUDY FORM*/
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX PUPIL STUDY FORM'
    INTO :CNT;
    IF ((CNT = 0) AND (KEY_LEVEL = 1)) THEN
    BEGIN
        EXECUTE PROCEDURE FIXER_FIX_PUPIL_STUDY_FORM;

        INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
        VALUES ('FIX PUPIL STUDY FORM', 'FIX PUPIL STUDY FORM', CURRENT_TIMESTAMP);
    END

    /*14.10.2016 -- FIX REGION GIA*/
/*    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX REGION GIA'
    INTO :CNT;
    IF ((CNT = 0) AND (V$OU_LICENCE_TYPE = 'O')) THEN
    BEGIN
        EXECUTE PROCEDURE FIXER_FIX_REGION_GIA;

        INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
        VALUES ('FIX REGION GIA', 'FIX REGION GIA', CURRENT_TIMESTAMP);
    END*/

    /*18.10.2016 -- FIX COLLEGE CIRRICULUM DISTANCE*/
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX COLLEGE CIRRICULUM DISTANCE'
    INTO :CNT;
    IF ((CNT = 0) AND (KEY_LEVEL = 1) AND (V$OU_LICENCE_TYPE = 'C')) THEN
    BEGIN
        EXECUTE PROCEDURE FIXER_FIX_COLLEGE_CIR_DIST;

        INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
        VALUES ('FIX COLLEGE CIRRICULUM DISTANCE', 'FIX COLLEGE CIRRICULUM DISTANCE', CURRENT_TIMESTAMP);
    END

    /*19.10.2016 -- FIX REPAIR SCHOOL OBJ_ID GENERATOR*/
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX REPAIR SCHOOL OBJ_ID GENERATOR'
    INTO :CNT;
    IF ((CNT = 0) AND (V$OU_LICENCE_TYPE = 'O')) THEN
    BEGIN
        EXECUTE PROCEDURE FIXER_REPAIR_OBJ_GEN;

        INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
        VALUES ('FIX REPAIR SCHOOL OBJ_ID GENERATOR', 'FIX REPAIR SCHOOL OBJ_ID GENERATOR', CURRENT_TIMESTAMP);
    END

    /*25.10.2016 -- FIX UDOD CIRRICULUM DISTANCE*/
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX UDOD CIRRICULUM DISTANCE'
    INTO :CNT;
    IF ((CNT = 0) AND (KEY_LEVEL = 1) AND (V$OU_LICENCE_TYPE = 'U')) THEN
    BEGIN
        EXECUTE PROCEDURE FIXER_FIX_UDOD_CIR_DIST;

        INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
        VALUES ('FIX UDOD CIRRICULUM DISTANCE', 'FIX UDOD CIRRICULUM DISTANCE', CURRENT_TIMESTAMP);
    END

    /* 29.11.2016 Обновление номеров параллелей для учебников из ФПУ, где они не были заполнены - неактуально */

    /* 06.12.2016 Выполняем перегенерацию статистики контингента каждый раз - перенесено в FIXER5 */
    /*IF (KEY_LEVEL = 1) THEN
    BEGIN
        EXECUTE PROCEDURE MONITORING_CONTINGENT_ADD;
    END*/

    /* 03.02.2017 Удаление записей СМИР, попавших в разделы отличные от непосредственно ОО */
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX MONITORING LOCATION DIR'
    INTO :CNT;
    IF (CNT = 0) THEN
    BEGIN
        UPDATE LINKS
        SET DATE_DEL = CURRENT_TIMESTAMP
        WHERE OBJ_TYPE_ID = 238 AND PARENT_TYPE_ID <> 2 AND DATE_DEL IS NULL;

        INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
        VALUES ('FIX MONITORING LOCATION DIR', 'FIX MONITORING LOCATION DIR', CURRENT_TIMESTAMP);
    END

    /* 17.04.2017 Пересчет общей площади учебно-лабораторных помещений в ОО - повторно, первый патч снова сломался */
    /* 08.08.2017 Третье применение патча - перерасчет количества учебно-лабораторных помещений, а также исправление типа помещения для библиотек */
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX AREA SL3 ROOMS DIR'
    INTO :CNT;
    IF (CNT = 0) THEN
    BEGIN

      EXECUTE PROCEDURE FIX_LIBRARY_ROOTTYPE;

      FOR SELECT L61.OBJ_ID FROM LINKS L61
        WHERE L61.OBJ_TYPE_ID = 61 AND L61.PARENT_TYPE_ID = 16 AND L61.DATE_DEL IS NULL
        INTO :V$OBJ_ID
      DO BEGIN
        EXECUTE PROCEDURE AREA_SL_ROOMS_CALC(:V$OBJ_ID);
        EXECUTE PROCEDURE COUNT_SL_ROOMS_CALC(:V$OBJ_ID);
      END

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX AREA SL3 ROOMS DIR', 'FIX AREA SL3 ROOMS DIR', CURRENT_TIMESTAMP);
    END

    /* 12.05.2017 Чистка занесенных ветром объектов в ДОУ и колледж */
    IF(V$OU_LICENCE_TYPE = 'D') THEN
    BEGIN
        SELECT COUNT(*)
        FROM INFO I
        WHERE I.INFO_CODE = 'FIX DOU WIND TEAMS'
        INTO :CNT;
        IF (CNT = 0) THEN
        BEGIN
          DELETE FROM LINKS WHERE (PARENT_TYPE_ID = 111 OR PARENT_TYPE_ID is null) AND OBJ_TYPE_ID = 54 AND DATE_DEL IS NULL;

          INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
          VALUES ('FIX DOU WIND TEAMS', 'FIX DOU WIND TEAMS', CURRENT_TIMESTAMP);
        END
    END
    IF(V$OU_LICENCE_TYPE = 'C') THEN
    BEGIN
        SELECT COUNT(*)
        FROM INFO I
        WHERE I.INFO_CODE = 'FIX COLLEGE WIND TEAMS'
        INTO :CNT;
        IF (CNT = 0) THEN
        BEGIN
          DELETE FROM LINKS WHERE (PARENT_TYPE_ID = 112 OR PARENT_TYPE_ID is null) AND OBJ_TYPE_ID = 289 AND DATE_DEL IS NULL;

          INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
          VALUES ('FIX COLLEGE WIND TEAMS', 'FIX COLLEGE WIND TEAMS', CURRENT_TIMESTAMP);
        END
    END

END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIXER4
AS
DECLARE VARIABLE SCHOOL_ID BIGINT;
DECLARE VARIABLE KEY_LEVEL VARCHAR(100);
DECLARE VARIABLE V$OU_LICENCE_TYPE VARCHAR(1);
DECLARE VARIABLE COMPONENT_ID BIGINT;
DECLARE VARIABLE STAGE_ID BIGINT;
DECLARE VARIABLE SUBJECT_ID BIGINT;
DECLARE VARIABLE N INTEGER;
DECLARE VARIABLE OBJ_ID BIGINT;
DECLARE VARIABLE LINK_ID BIGINT;
DECLARE VARIABLE CNT INTEGER;
DECLARE VARIABLE S1 VARCHAR(1000);
DECLARE VARIABLE D1 DATE;
DECLARE VARIABLE HAS_SCHOOL INTEGER;
begin

    SELECT FIRST 1 L.OBJ_ID
    FROM LINKS L
    WHERE L.PARENT_ID IS NULL AND L.OBJ_TYPE_ID = 2 AND L.DATE_DEL IS NULL
    INTO :SCHOOL_ID;

    SELECT K.KEY_VAL
    FROM KEYS K
    WHERE K.KEY_CODE = 'LEVEL'
    INTO :KEY_LEVEL;
    SELECT STATUS FROM OU_LICENCE_TYPE INTO :V$OU_LICENCE_TYPE;

    /* 21.06.2017 Перенос категории из сотрудника в прием на должность */
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX MOVE CATEGORY TO VACANCY'
    INTO :CNT;
    IF (CNT = 0 AND KEY_LEVEL = 1) THEN
    BEGIN
      EXECUTE PROCEDURE FIX_VACANCY_CATEGORIES(:SCHOOL_ID);

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX MOVE CATEGORY TO VACANCY', 'FIX MOVE CATEGORY TO VACANCY', CURRENT_TIMESTAMP);
    END

    /* 12.07.2017 Удаление объектов #343 - СМИР, аттестация учащихся */
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX SMIR STUDENT ATTESTATION'
    INTO :CNT;
    IF (CNT = 0 AND KEY_LEVEL = 1) THEN
    BEGIN
      DELETE FROM OBJECTS WHERE TYPE_ID = 343;

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX SMIR STUDENT ATTESTATION', 'FIX SMIR STUDENT ATTESTATION', CURRENT_TIMESTAMP);
    END

    /* 14.08.2017 Формирование первоначального реестра длительных отпусков */
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX LONG VACATIONS'
    INTO :CNT;
    IF (CNT = 0 AND KEY_LEVEL = 1) THEN
    BEGIN
      EXECUTE PROCEDURE FIX_LONG_VACATIONS(:SCHOOL_ID);

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX LONG VACATIONS', 'FIX LONG VACATIONS', CURRENT_TIMESTAMP);
    END

    /* 23.08.2017 Удаление значений параметра "Юридический статус" для объектов типа "родственник", т.к. параметр недопустим (redmine #1729) */
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX 23082017'
    INTO :CNT;
    IF (CNT = 0 AND KEY_LEVEL = 1) THEN
    BEGIN
      DELETE FROM VALL WHERE PARAM_ID = 1562 and OBJ_ID IN (SELECT OBJ_ID FROM OBJECTS WHERE TYPE_ID = 20);

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX 23082017', 'FIX 23082017', CURRENT_TIMESTAMP);
    END

    /* 23.08.2017 Очистка нерабочих хвостов от СМИР (требования к аттестации учащихся) */
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX 23082017 SMIR 343'
    INTO :CNT;
    IF (CNT = 0 AND KEY_LEVEL = 1) THEN
    BEGIN
      DELETE FROM OBJECTS WHERE TYPE_ID = 343;

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX 23082017 SMIR 343', 'FIX 23082017 SMIR 343', CURRENT_TIMESTAMP);
    END

    /* 12.09.2017 Создание корневого объекта мероприятия для олимпиадного движения */
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX 12092017 OLYMP_'
    INTO :CNT;
    IF (CNT = 0 AND KEY_LEVEL = 1) THEN
    BEGIN
        UPDATE OR INSERT INTO OBJECTS("OBJ_ID", "TYPE_ID", "IS_REPL") VALUES(34628, 377, 0);
        SELECT ID FROM VAL_ADD(2867, 34628, 'Мероприятия') INTO :OBJ_ID;
        SELECT OBJ_ID FROM OBJECT_ADD_LINK(NULL, 34628, 377) INTO :OBJ_ID;

        INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
        VALUES ('FIX 12092017 OLYMP_', 'FIX 12092017 OLYMP_', CURRENT_TIMESTAMP);
    END

    /* 05.10.2017 Очередная починка генератора для городской базы */
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX REPAIR SCHOOL OBJ_ID GENERATOR 2'
    INTO :CNT;
    IF ((CNT = 0) AND (V$OU_LICENCE_TYPE = 'O') AND (KEY_LEVEL = 3)) THEN
    BEGIN
        EXECUTE PROCEDURE FIXER_REPAIR_OBJ_GEN;

        INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
        VALUES ('FIX REPAIR SCHOOL OBJ_ID GENERATOR 2', 'FIX REPAIR SCHOOL OBJ_ID GENERATOR 2', CURRENT_TIMESTAMP);
    END

    /* 25.10.2017 Чистка базы от неправильных объектов в корне дерева */
    DELETE FROM LINKS
    WHERE PARENT_ID IS NULL AND OBJ_TYPE_ID NOT IN (2, 53, 55, 111, 112, 118, 124, 224, 248, 251, 193, 241, 377);

    DELETE FROM LINKS
    WHERE (PARENT_ID IS NULL OR PARENT_TYPE_ID = 111) AND OBJ_ID = 3878;
    
    /* 01.03.2018 Обновление категорий #1932, повторно 16.06.2020 */
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX 16062020 STUFF_CATS'
    INTO :CNT;
    IF (CNT = 0 and KEY_LEVEL = 1) THEN
    BEGIN
      FOR
        SELECT L14.OBJ_ID
        FROM LINKS L14
        WHERE L14.OBJ_TYPE_ID = 14 AND L14.PARENT_TYPE_ID IN (2, 211) AND L14.DATE_DEL IS NULL
        INTO :OBJ_ID
      DO
      BEGIN
        SELECT LISTVAL_ID FROM VACANCY_GET_CAT(:OBJ_ID) INTO :LINK_ID;
        SELECT BLOB_ID FROM VAL_ADD(281, :OBJ_ID, :LINK_ID) INTO :OBJ_ID;
      END

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX 16062020 STUFF_CATS', 'FIX 16062020 STUFF_CATS', CURRENT_TIMESTAMP);
    END

    /* Пересчет количества ТСО #1941 */
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX 05032018 TCO'
    INTO :CNT;
    IF (CNT = 0 and KEY_LEVEL = 1) THEN
    BEGIN
      EXECUTE PROCEDURE FIX_RECALC_TCO;

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX 05032018 TCO', 'FIX 05032018 TCO', CURRENT_TIMESTAMP);
    END

    -- Создаем или корректируем строку выгрузки для DG для дневника и прочих сервисов
    IF(V$OU_LICENCE_TYPE = 'O' AND KEY_LEVEL = 1) THEN
    BEGIN
      EXECUTE PROCEDURE FIX_DC_TASKS;
    END
    IF(V$OU_LICENCE_TYPE = 'D' AND KEY_LEVEL = 1) THEN
    BEGIN
      EXECUTE PROCEDURE FIX_DC_TASKS_DOU;
    END

    /* 15.03.2018 заполнение текущего учебного года */
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'SET CURRENT_YEAR'
    INTO :CNT;
    IF (CNT = 0 AND KEY_LEVEL = 1 AND SCHOOL_ID IS NOT NULL) THEN
    BEGIN
      IF(EXTRACT(YEAR FROM CURRENT_DATE) < 2018) THEN EXCEPTION DATA_ERROR 'Нельзя устанавливать программу на компьютер с неадекватной датой';

      N = 0;
      SELECT FIRST 1 1
      FROM VALL V1236
      WHERE V1236.OBJ_ID = :SCHOOL_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
      INTO :N;

      IF(N = 0) THEN
      BEGIN
        OBJ_ID = 10977; -- 2017-1018

        SELECT FIRST 1 LV.LISTVAL_ID
        FROM LISTVALS LV
        WHERE LV.LIST_ID = 29 AND LV.IS_DEL = 0 AND LV.COST = IIF(EXTRACT(MONTH FROM CURRENT_DATE) < 9, EXTRACT(YEAR FROM CURRENT_DATE) - 1, EXTRACT(YEAR FROM CURRENT_DATE))
        INTO :OBJ_ID;

        SELECT ID FROM VAL_ADD(1236, :SCHOOL_ID, :OBJ_ID) INTO :OBJ_ID;
      END

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('SET CURRENT_YEAR', 'SET CURRENT_YEAR', CURRENT_TIMESTAMP);
    END

    /* 25.06.2018 Конвертация поля период отпуска из LV в INTEGER */
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX 25062018 VACATION_PERIOD'
    INTO :CNT;
    IF (CNT = 0) THEN
    BEGIN
      FOR
         SELECT OBJ_ID, R.VAL
         FROM VALL V325
         JOIN LISTVALS LV ON LV.LISTVAL_ID = V325.LISTVAL_ID
         JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
         WHERE V325.PARAM_ID = 325 AND V325.IS_DEL = 0
         INTO :OBJ_ID, :S1
      DO
      BEGIN
         -- Достаем первую цифру года
         N = SUBSTRING(S1 FROM 1 FOR 4);
         UPDATE OR INSERT INTO VALI (OBJ_ID, PARAM_ID, VAL, IS_DEL) VALUES (:OBJ_ID, 325, :N, 0);
      END

      DELETE FROM VALL WHERE PARAM_ID = 325;

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX 25062018 VACATION_PERIOD', 'FIX 25062018 VACATION_PERIOD', CURRENT_TIMESTAMP);
    END

    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX 09082018 UPGRADE RQ YEAR'
    INTO :CNT;
    IF (CNT = 0) THEN
    BEGIN
      EXECUTE PROCEDURE FIX_UPGRADE_REQUEST_YEAR;

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX 09082018 UPGRADE RQ YEAR', 'FIX 09082018 UPGRADE RQ YEAR', CURRENT_TIMESTAMP);
    END

    -- Удаляем испорченные этапы обучения для типовых шаблонов
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX 20082018 UP TEMPLATES'
    INTO :CNT;
    IF (CNT = 0) THEN
    BEGIN
      EXECUTE PROCEDURE FIX_TEMPLATE_UP_DAMAGED;

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX 20082018 UP TEMPLATES', 'FIX 20082018 UP TEMPLATES', CURRENT_TIMESTAMP);
    END

    -- Переносим СНИЛС сотрудников из документов в отдельное поле
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX 27082018 FIX_EMPLOYEES_SNILS'
    INTO :CNT;
    IF (CNT = 0) THEN
    BEGIN
      SELECT COUNT(*) FROM FIX_EMPLOYEES_SNILS INTO :CNT;

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX 27082018 FIX_EMPLOYEES_SNILS', 'FIX 27082018 FIX_EMPLOYEES_SNILS', CURRENT_TIMESTAMP);
    END

    -- Дата приказа о зачислении для поступивших
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX 12092018 ACCEPTED'
    INTO :CNT;
    IF (CNT = 0 and KEY_LEVEL = 1 AND V$OU_LICENCE_TYPE = 'O') THEN
    BEGIN
      EXECUTE PROCEDURE FIX_NEW_ACCEPTED_DATE;

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX 12092018 ACCEPTED', 'FIX 12092018 ACCEPTED', CURRENT_TIMESTAMP);
    END

    -- Восстановление потерянной связи с должностью
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX 21022019 JOB_LINK'
    INTO :CNT;
    IF (CNT = 0 and KEY_LEVEL = 1) THEN
    BEGIN
      EXECUTE PROCEDURE FIX_JOB_LINK;

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX 21022019 JOB_LINK', 'FIX 21022019 JOB_LINK', CURRENT_TIMESTAMP);
    END

    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX 06062019 SUBJ_AREAS'
    INTO :CNT;
    IF (CNT = 0 AND V$OU_LICENCE_TYPE = 'O') THEN
    BEGIN
      FOR
        SELECT L51.OBJ_ID
        FROM LINKS L51
        WHERE L51.PARENT_ID = 32771 AND L51.OBJ_TYPE_ID = 51 AND L51.DATE_DEL IS NULL AND L51.OBJ_ID < 1000000000
        INTO :OBJ_ID
      DO
      BEGIN
        DELETE FROM LINKS
        WHERE PARENT_ID = :OBJ_ID AND OBJ_TYPE_ID = 302 AND LINK_ID > 1000000000;
      END

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX 06062019 SUBJ_AREAS', 'FIX 06062019 SUBJ_AREAS', CURRENT_TIMESTAMP);
    END

    -- Перенос кодов ФПУ в печатных изданиях - неактуально

    -- Назначение кодов ФИС ОКО
    /*SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX 19082019 FISOKO'
    INTO :CNT;
    IF (CNT = 0 and KEY_LEVEL = 1 and V$OU_LICENCE_TYPE = 'O') THEN
    BEGIN
      EXECUTE PROCEDURE FIX_FISOKO_INIT(:SCHOOL_ID);

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX 19082019 FISOKO', 'FIX 19082019 FISOKO', CURRENT_TIMESTAMP);
    END*/

    -- Распределение времени выгрузки СОП
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX 20082019 SOP TIMELINE'
    INTO :CNT;
    IF (CNT = 0 and KEY_LEVEL = 1 and V$OU_LICENCE_TYPE = 'O') THEN
    BEGIN
      EXECUTE PROCEDURE FIX_SOP_TIMELINE;

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX 20082019 SOP TIMELINE', 'FIX 20082019 SOP TIMELINE', CURRENT_TIMESTAMP);
    END

    -- Ремонт залипших экстернатников
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX 07112019 EXTERNAT'
    INTO :CNT;
    IF (CNT = 0 and KEY_LEVEL = 1 and V$OU_LICENCE_TYPE = 'O') THEN
    BEGIN
      EXECUTE PROCEDURE FIX_EXTERNAT_LEAVED;

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX 07112019 EXTERNAT', 'FIX 07112019 EXTERNAT', CURRENT_TIMESTAMP);
    END

    -- Ремонт дубликатов отметок в новом КЖ
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX 18112019 CJ2_DUPL'
    INTO :CNT;
    IF (CNT = 0 and KEY_LEVEL = 1) THEN
    BEGIN
      EXECUTE PROCEDURE FIX_CJ2_DUPLICATES;

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX 18112019 CJ2_DUPL', 'FIX 18112019 CJ2_DUPL', CURRENT_TIMESTAMP);
    END

    -- Ремонт TMP кодов в ФПУ
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX 16012020 FPU_TMP'
    INTO :CNT;
    IF (CNT = 0 and KEY_LEVEL = 1) THEN
    BEGIN
      EXECUTE PROCEDURE FIXER_FPU_TMP;

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX 16012020 FPU_TMP', 'FIX 16012020 FPU_TMP', CURRENT_TIMESTAMP);
    END

    -- Убрать всех с дистанционки
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX 31082020 RMT_EDU'
    INTO :CNT;
    IF (CNT = 0 and KEY_LEVEL = 1) THEN
    BEGIN
      UPDATE VALL SET LISTVAL_ID = 3 WHERE PARAM_ID = 2992 AND IS_DEL = 0;

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX 31082020 RMT_EDU', 'FIX 31082020 RMT_EDU', CURRENT_TIMESTAMP);
    END

    -- Конвертация УП ВД
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX 31082020 CONVERT_VD'
    INTO :CNT;
    IF (CNT = 0 and KEY_LEVEL = 1) THEN
    BEGIN
      EXECUTE PROCEDURE FIXER_CONVERT_VD;

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX 31082020 CONVERT_VD', 'FIX 31082020 CONVERT_VD', CURRENT_TIMESTAMP);
    END

    -- Создание объекта для фиксации движения на дистанте
    IF(KEY_LEVEL = 1 AND NOT EXISTS(SELECT 1 FROM LINKS WHERE PARENT_ID = :SCHOOL_ID AND OBJ_TYPE_ID = 338) AND SCHOOL_ID IS NOT NULL) THEN
    BEGIN
      SELECT LINK_ID FROM OBJECT_ADD(:SCHOOL_ID, 338) INTO :LINK_ID;
    END

    -- Изменение привязки должности старший воспитатель
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX 06042020 MAJOR_TUTOR'
    INTO :CNT;
    IF (CNT = 0 and KEY_LEVEL = 1) THEN
    BEGIN
      EXECUTE PROCEDURE FIXER_MAJOR_TUTOR;

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX 06042020 MAJOR_TUTOR', 'FIX 06042020 MAJOR_TUTOR', CURRENT_TIMESTAMP);
    END

    -- Изменение адаптированности/ОВЗ
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX 18052021 OVZ'
    INTO :CNT;
    IF (CNT = 0 and KEY_LEVEL = 1) THEN
    BEGIN
      EXECUTE PROCEDURE FIXER_OVZ;

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX 18052021 OVZ', 'FIX 18052021 OVZ', CURRENT_TIMESTAMP);
    END

    -- Перенос реестров движения
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX 05082021 MOVEMENTS'
    INTO :CNT;
    IF (CNT = 0 and KEY_LEVEL = 1) THEN
    BEGIN
      EXECUTE PROCEDURE FIX_MOVEMENTS;

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX 05082021 MOVEMENTS', 'FIX 05082021 MOVEMENTS', CURRENT_TIMESTAMP);
    END

    -- Удаление старых учебников
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX 11082021 BOOKS'
    INTO :CNT;
    IF (CNT = 0 and KEY_LEVEL = 1) THEN
    BEGIN
      DELETE FROM LINKS WHERE OBJ_TYPE_ID = 107;
      DELETE FROM OBJECTS WHERE TYPE_ID = 107;

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX 11082021 BOOKS', 'FIX 11082021 BOOKS', CURRENT_TIMESTAMP);
    END

    -- Исправление косяка с выпускными экстернатами
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX 12082021 EXTGRADUATE'
    INTO :CNT;
    IF (CNT = 0 and KEY_LEVEL = 1 AND V$OU_LICENCE_TYPE = 'O') THEN
    BEGIN
      EXECUTE PROCEDURE FIXER_GRADUATE_CLASS(NULL);

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX 12082021 EXTGRADUATE', 'FIX 12082021 EXTGRADUATE', CURRENT_TIMESTAMP);
    END

    -- Исправление даты движения вновь зачисленных
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX 26082021 ENT_DATE'
    INTO :CNT;
    IF (CNT = 0 and KEY_LEVEL = 1 AND V$OU_LICENCE_TYPE = 'O') THEN
    BEGIN
      EXECUTE PROCEDURE FIXER_ENT_DATES;

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX 26082021 ENT_DATE', 'FIX 26082021 ENT_DATE', CURRENT_TIMESTAMP);
    END

    -- Исправление маски этапов в ГУП
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX 28082021 GUP MASK'
    INTO :CNT;
    IF (CNT = 0 and KEY_LEVEL = 1 AND V$OU_LICENCE_TYPE = 'O') THEN
    BEGIN
      EXECUTE PROCEDURE FIXER_GUP_MASKS;

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX 28082021 GUP MASK', 'FIX 28082021 GUP MASK', CURRENT_TIMESTAMP);
    END

    -- Удаление наплодившихся копий журналов
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX 08092021 CJ DUBLES'
    INTO :CNT;
    IF (CNT = 0 and KEY_LEVEL = 1 AND V$OU_LICENCE_TYPE = 'O') THEN
    BEGIN
      EXECUTE PROCEDURE FIXER_CJ_DUPLICATES;

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX 08092021 CJ DUBLES', 'FIX 08092021 CJ DUBLES', CURRENT_TIMESTAMP);
    END

    -- Отмена кривого признака выпускного класса, а также исправление ошибок в движении
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX 08092021 BAD RELEASE'
    INTO :CNT;
    IF (CNT = 0 and KEY_LEVEL = 1 AND V$OU_LICENCE_TYPE = 'O') THEN
    BEGIN
      EXECUTE PROCEDURE FIXER_BAD_RELEASE;

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX 08092021 BAD RELEASE', 'FIX 08092021 BAD RELEASE', CURRENT_TIMESTAMP);
    END

    -- Исправление типа класса ОВЗ в движении
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX 01102021 OVZ TYPE'
    INTO :CNT;
    IF (CNT = 0 and KEY_LEVEL = 1 AND V$OU_LICENCE_TYPE = 'O') THEN
    BEGIN
      EXECUTE PROCEDURE FIXER_OVZ_MOVE_TYPE;

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX 01102021 OVZ TYPE', 'FIX 01102021 OVZ TYPE', CURRENT_TIMESTAMP);
    END

    -- Заполнение часов в журналах
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX 20092021 JOURNAL HOURS'
    INTO :CNT;
    IF (CNT = 0 and KEY_LEVEL = 1 AND V$OU_LICENCE_TYPE = 'O') THEN
    BEGIN
      EXECUTE PROCEDURE FIXER_JOURNAL_JOURS;

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX 20092021 JOURNAL HOURS', 'FIX 20092021 JOURNAL HOURS', CURRENT_TIMESTAMP);
    END

    -- Исправления косяков в журналах
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX 14092023 CJ GRANTS'
    INTO :CNT;
    IF (CNT = 0 and KEY_LEVEL = 1 AND V$OU_LICENCE_TYPE = 'O') THEN
    BEGIN
      EXECUTE PROCEDURE FIXER_JOURNAL_GRANTS;

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX 14092023 CJ GRANTS', 'FIX 14092023 CJ GRANTS', CURRENT_TIMESTAMP);
    END

    -- Всегда включаем задачу выгрузки в DataID
    UPDATE DC_TASKS
    SET TASK_ENABLED = 1
    WHERE TASK_REF = 'paragraf.rks:update' AND TASK_ENABLED = 0;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIXER5
AS
DECLARE VARIABLE SCHOOL_ID BIGINT;
DECLARE VARIABLE KEY_LEVEL VARCHAR(100);
DECLARE VARIABLE V$OU_LICENCE_TYPE VARCHAR(1);
DECLARE VARIABLE N INTEGER;
DECLARE VARIABLE OBJ_ID BIGINT;
DECLARE VARIABLE LINK_ID BIGINT;
DECLARE VARIABLE CNT INTEGER;
DECLARE VARIABLE S1 VARCHAR(1000);
DECLARE VARIABLE D1 DATE;
begin

    SELECT FIRST 1 L.OBJ_ID
    FROM LINKS L
    WHERE L.PARENT_ID IS NULL AND L.OBJ_TYPE_ID = 2 AND L.DATE_DEL IS NULL
    INTO :SCHOOL_ID;

    SELECT K.KEY_VAL
    FROM KEYS K
    WHERE K.KEY_CODE = 'LEVEL'
    INTO :KEY_LEVEL;

    SELECT STATUS FROM OU_LICENCE_TYPE INTO :V$OU_LICENCE_TYPE;

    -- Исправления алиасов ГИА
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX 11112021 GIA ALIASES'
    INTO :CNT;
    IF (CNT = 0 and KEY_LEVEL = 1 AND V$OU_LICENCE_TYPE = 'O') THEN
    BEGIN
      EXECUTE PROCEDURE FIXER_GIA_ALIASES;

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX 11112021 GIA ALIASES', 'FIX 11112021 GIA ALIASES', CURRENT_TIMESTAMP);
    END

    -- Исправления потерянных движений семейки
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX 09112021 MISS MOVES'
    INTO :CNT;
    IF (CNT = 0 and KEY_LEVEL = 1 AND V$OU_LICENCE_TYPE = 'O') THEN
    BEGIN
      EXECUTE PROCEDURE FIXER_MISSING_MOVEMENTS;

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX 09112021 MISS MOVES', 'FIX 09112021 MISS MOVES', CURRENT_TIMESTAMP);
    END

    -- Направления для предметов ВД
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX 09112021 VDS'
    INTO :CNT;
    IF (CNT = 0 and KEY_LEVEL = 1 AND V$OU_LICENCE_TYPE = 'O') THEN
    BEGIN
      EXECUTE PROCEDURE FIXER_VD_DEST;

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX 09112021 VDS', 'FIX 09112021 VDS', CURRENT_TIMESTAMP);
    END

    -- Добавляем задачу расчета статистики
    -- пока только школы
    IF (KEY_LEVEL = 1 AND V$OU_LICENCE_TYPE = 'O') THEN
    BEGIN
      UPDATE OR INSERT INTO DC_TASKS
      (ID, TASK_NAME, TASK_REF, TASK_TIMING, TASK_ENABLED, RESTORE_MISSED, MISS_METHOD, TASK_METHOD, IS_PRIVATE)
      VALUES (10, 'Расчет статистики', 'cloudservices:updatestat', '1 0 * * 1', 1, 0, 0, '@', 1)
      MATCHING (ID);
    END

    -- Добавляем задачу выгрузки МояШкола
    IF (KEY_LEVEL = 1 AND V$OU_LICENCE_TYPE IN ('O', 'C')) THEN
    BEGIN
      UPDATE OR INSERT INTO DC_TASKS
      (ID, TASK_NAME, TASK_REF, TASK_TIMING, TASK_ENABLED, RESTORE_MISSED, MISS_METHOD, TASK_METHOD, IS_PRIVATE)
      VALUES (11, 'Выгрузка МояШкола', 'paragraf.dnevnik2018:myschool', '0 5,17 * * *', 1, 0, 0, '@', 1)
      MATCHING (ID);

      DELETE FROM DC_TASKS WHERE TASK_REF = 'paragraf.dnevnik2018:myschool' AND ID <> 11;
      DELETE FROM DC_TASKS WHERE TASK_REF = 'paragraf.rod:rod';
    END

    -- Исправление текста темы урока
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX 02122021 LESSON THEME'
    INTO :CNT;
    IF (CNT = 0 and KEY_LEVEL = 1 AND V$OU_LICENCE_TYPE = 'O') THEN
    BEGIN
      EXECUTE PROCEDURE FIXER_LESSON_THEME;

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX 02122021 LESSON THEME', 'FIX 02122021 LESSON THEME', CURRENT_TIMESTAMP);
    END

    -- Исправление типа приема в экстернаты
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX 09122021 EXT ACCEPT'
    INTO :CNT;
    IF (CNT = 0 and KEY_LEVEL = 1 AND V$OU_LICENCE_TYPE = 'O') THEN
    BEGIN
      EXECUTE PROCEDURE FIXER_EXTERNAT_ACCEPT_TYPE;

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX 09122021 EXT ACCEPT', 'FIX 09122021 EXT ACCEPT', CURRENT_TIMESTAMP);
    END

    -- Исправление выбывших или окончивших экстернаты
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX 09122021 EXT LEAVE'
    INTO :CNT;
    IF (CNT = 0 and KEY_LEVEL = 1 AND V$OU_LICENCE_TYPE = 'O') THEN
    BEGIN
      EXECUTE PROCEDURE FIXER_EXTERNAT_LEAVED;

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX 09122021 EXT LEAVE', 'FIX 09122021 EXT LEAVE', CURRENT_TIMESTAMP);
    END

    -- Исправление выбывших или окончивших экстернаты
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX 24122021 CLONE MARKS'
    INTO :CNT;
    IF (CNT = 0 and KEY_LEVEL = 1 AND V$OU_LICENCE_TYPE = 'O') THEN
    BEGIN
      EXECUTE PROCEDURE FIXER_CLONE_MARKS;

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX 24122021 CLONE MARKS', 'FIX 24122021 CLONE MARKS', CURRENT_TIMESTAMP);
    END

    -- Удаление хвостов для удаленных отовсюду учеников
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX 14012022 GHOST STUDENTS'
    INTO :CNT;
    IF (CNT = 0 and KEY_LEVEL = 1 AND V$OU_LICENCE_TYPE = 'O') THEN
    BEGIN
      EXECUTE PROCEDURE FIXER_GHOST_STUDENTS;

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX 14012022 GHOST STUDENTS', 'FIX 14012022 GHOST STUDENTS', CURRENT_TIMESTAMP);
    END

    -- Исправления алиасов ГИА
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX 020i2022 GIA ALIASES'
    INTO :CNT;
    IF (CNT = 0 and KEY_LEVEL = 1 AND V$OU_LICENCE_TYPE = 'O') THEN
    BEGIN
      IF(EXISTS(SELECT 1 FROM KEYS WHERE KEY_NAME = 'ГИА Вирт ОУ')) THEN EXECUTE PROCEDURE FIXER_GIA_ALIASES;

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX 020i2022 GIA ALIASES', 'FIX 020i2022 GIA ALIASES', CURRENT_TIMESTAMP);
    END

    -- Установка поля надомное обучение
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX 20042022 ATHOME'
    INTO :CNT;
    IF (CNT = 0 and KEY_LEVEL = 1 AND V$OU_LICENCE_TYPE = 'O') THEN
    BEGIN
      EXECUTE PROCEDURE FIXER_ATHOME_STUDENTS;

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX 20042022 ATHOME', 'FIX 20042022 ATHOME', CURRENT_TIMESTAMP);
    END

    -- Исправления перемещанных связей ПТП
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX 19052022 CJ PTP'
    INTO :CNT;
    IF (CNT = 0 and KEY_LEVEL = 1 AND V$OU_LICENCE_TYPE = 'O') THEN
    BEGIN
      EXECUTE PROCEDURE FIXER_JOURNAL_PTP_LINKS;

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX 19052022 CJ PTP', 'FIX 19052022 CJ PTP', CURRENT_TIMESTAMP);
    END

    -- Исправление незаполенных полей в итоговых отметках
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX 12122022 FINALS'
    INTO :CNT;
    IF (CNT = 0 and KEY_LEVEL = 1 AND V$OU_LICENCE_TYPE = 'O') THEN
    BEGIN
      EXECUTE PROCEDURE FIXER_FINALS_EF;

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX 12122022 FINALS', 'FIX 12122022 FINALS', CURRENT_TIMESTAMP);
    END

    -- Пересчет лимитов уже существующих УП
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX 20062022 STD2021'
    INTO :CNT;
    IF (CNT = 0 and KEY_LEVEL = 1 AND V$OU_LICENCE_TYPE = 'O') THEN
    BEGIN
      EXECUTE PROCEDURE FIXER_STD2021_RECALC;

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX 20062022 STD2021', 'FIX 20062022 STD2021', CURRENT_TIMESTAMP);
    END

    -- Исправление ошибок дебилов, руками менявших учебный год в 2021 году
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX 20220819X YEAR_CHANGE'
    INTO :CNT;
    IF (CNT = 0 and KEY_LEVEL = 1 AND V$OU_LICENCE_TYPE = 'O') THEN
    BEGIN
      EXECUTE PROCEDURE FIXER_YC2021;

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX 20220819X YEAR_CHANGE', 'FIX 20220819X YEAR_CHANGE', CURRENT_TIMESTAMP);
    END

    -- Заполнение счетчиков этапности для ОВЗ в 2022 году
    -- тут же обновляем вообще все записи движения
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX 20220919 OVZ_STAGES'
    INTO :CNT;
    IF (CNT = 0 and KEY_LEVEL = 1 AND V$OU_LICENCE_TYPE = 'O') THEN
    BEGIN
      EXECUTE PROCEDURE FIXER_OVZ_STAGES2022;

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX 20220919 OVZ_STAGES', 'FIX 20220919 OVZ_STAGES', CURRENT_TIMESTAMP);
    END

    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX 20221116 ODNKNR'
    INTO :CNT;
    IF (CNT = 0 AND KEY_LEVEL = 1 AND V$OU_LICENCE_TYPE = 'O') THEN
    BEGIN
      EXECUTE PROCEDURE FIXER_ODNKNR;

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX 20221116 ODNKNR', 'FIX 20221116 ODNKNR', CURRENT_TIMESTAMP);
    END

    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX 20221208 GPDJ'
    INTO :CNT;
    IF (CNT = 0 AND KEY_LEVEL = 1 AND V$OU_LICENCE_TYPE = 'O') THEN
    BEGIN
      EXECUTE PROCEDURE FIXER_GPDJ_PTP;

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX 20221208 GPDJ', 'FIX 20221208 GPDJ', CURRENT_TIMESTAMP);
    END

    -- Каталоги для госзадания
    IF (KEY_LEVEL = 1) THEN EXECUTE PROCEDURE CREATE_GZ_FOLDERS;

    -- Перенос данных по школьным картам - не позднее 01.04.2023
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX 20230110 SCUD CARDS'
    INTO :CNT;
    IF (CNT = 0 AND KEY_LEVEL = 1 AND V$OU_LICENCE_TYPE = 'O' AND CURRENT_DATE < '01.04.2023') THEN
    BEGIN
      EXECUTE PROCEDURE IMPORT_OLD_CARDS;

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX 20230110 SCUD CARDS', 'FIX 20230110 SCUD CARDS', CURRENT_TIMESTAMP);
    END

    -- Перенос данных по школьным картам - не позднее 01.04.2023
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX 20230110 SCUD CARDS'
    INTO :CNT;
    IF (CNT = 0 AND KEY_LEVEL = 1 AND V$OU_LICENCE_TYPE = 'O' AND CURRENT_DATE < '01.04.2023') THEN
    BEGIN
      EXECUTE PROCEDURE IMPORT_OLD_CARDS;

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX 20230110 SCUD CARDS', 'FIX 20230110 SCUD CARDS', CURRENT_TIMESTAMP);
    END

    -- Чистка потеряшек
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX 20230127 LOSTS'
    INTO :CNT;
    IF (CNT = 0 AND KEY_LEVEL = 1 AND V$OU_LICENCE_TYPE = 'O') THEN
    BEGIN
      EXECUTE PROCEDURE FIX_LOST_LINKS;

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX 20230127 LOSTS', 'FIX 20230127 LOSTS', CURRENT_TIMESTAMP);
    END

    -- Перенос аттестатов, пока без удаления. Кто не успел, тот опоздал
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX 20231004 ATT'
    INTO :CNT;
    IF (CNT = 0 AND KEY_LEVEL = 1 AND V$OU_LICENCE_TYPE IN ('O', 'C')) THEN
    BEGIN
      SELECT COUNT(*) FROM SDOCS_MIGRATE INTO :N;

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX 20231004 ATT', 'FIX 20231004 ATT', CURRENT_TIMESTAMP);
    END

    -- Прописывание связей с карточками аттестатов документов об образовании
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX 20231004 ATT_LINKS'
    INTO :CNT;
    IF (CNT = 0 AND KEY_LEVEL = 1 AND V$OU_LICENCE_TYPE IN ('O', 'C')) THEN
    BEGIN
      SELECT COUNT(*) FROM SDOCS_MIGRATE_LINKS INTO :N;

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX 20231004 ATT_LINKS', 'FIX 20231004 ATT_LINKS', CURRENT_TIMESTAMP);
    END

    -- Починка УП существующих, исправление поля часов, перерасчет действующих планов. Запускаем повторно
    -- повторно, было 20230613
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX 20240620 STPLANS'
    INTO :CNT;
    IF (CNT = 0 AND KEY_LEVEL = 1 AND V$OU_LICENCE_TYPE = 'O') THEN
    BEGIN
      N = 0;
      BEGIN
        EXECUTE PROCEDURE FIX_STUDY_PLANS;
        WHEN ANY DO N = 1;
      END

      -- Только если не упало при пересчете
      IF(N = 0) THEN
      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX 20240620 STPLANS', 'FIX 20240620 STPLANS', CURRENT_TIMESTAMP);
    END

    -- Фикс движения колледжей, повторно
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX 20240415 SPO MOVES'
    INTO :CNT;
    IF (CNT = 0 AND KEY_LEVEL = 1 AND V$OU_LICENCE_TYPE = 'C') THEN
    BEGIN
      EXECUTE PROCEDURE FIX_SPO_MOVEMENTS;

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX 20240415 SPO MOVES', 'FIX 20240415 SPO MOVES', CURRENT_TIMESTAMP);
    END

    -- Фикс параметров УП
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX 20230822 PLAN400'
    INTO :CNT;
    IF (CNT = 0 AND V$OU_LICENCE_TYPE = 'O') THEN
    BEGIN
      EXECUTE PROCEDURE FIX_PLANS400;

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX 20230822 PLAN400', 'FIX 20230822 PLAN400', CURRENT_TIMESTAMP);
    END

    -- Импорт данных при слиянии ОУ - теперь только кнопкой в DG
    /*IF (KEY_LEVEL = 1) THEN
    BEGIN
      SELECT COUNT(*) FROM FIX_MERGE_DB INTO :N;
    END*/

    -- Удаление хвостов расписаний
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX 20230908 SCHEDULE'
    INTO :CNT;
    IF (CNT = 0 AND KEY_LEVEL = 1) THEN
    BEGIN
      EXECUTE PROCEDURE FIX_SCHEDULE_ITEMS;

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX 20230908 SCHEDULE', 'FIX 20230908 SCHEDULE', CURRENT_TIMESTAMP);
    END

    -- Восстановление папки учебных периодов
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX 20230905 SCHEDULE FOLDER'
    INTO :CNT;
    IF (CNT = 0 AND KEY_LEVEL = 1) THEN
    BEGIN
      EXECUTE PROCEDURE FIX_SCHEDULE_FOLDER;

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX 20230905 SCHEDULE FOLDER', 'FIX 20230905 SCHEDULE FOLDER', CURRENT_TIMESTAMP);
    END

    -- Зачистка старых кодов специальностей СПО
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX 20230929 OLD CODES'
    INTO :CNT;
    IF (CNT = 0 AND KEY_LEVEL = 1 AND V$OU_LICENCE_TYPE = 'C') THEN
    BEGIN
      UPDATE VALS SET IS_DEL = 1 WHERE PARAM_ID IN (1753, 2165) AND IS_DEL = 0;

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX 20230929 OLD CODES', 'FIX 20230929 OLD CODES', CURRENT_TIMESTAMP);
    END

    -- Зачистка связей сотрудников
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX 20231004 LOST STUFF'
    INTO :CNT;
    IF (CNT = 0 AND KEY_LEVEL = 1 AND V$OU_LICENCE_TYPE IN ('O', 'C', 'D')) THEN
    BEGIN
      EXECUTE PROCEDURE FIX_LOST_STUFF;

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX 20231004 LOST STUFF', 'FIX 20231004 LOST STUFF', CURRENT_TIMESTAMP);
    END

    -- Новое поле в периодах
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX 20231009 PERIODS'
    INTO :CNT;
    IF (CNT = 0 AND KEY_LEVEL = 1 AND V$OU_LICENCE_TYPE IN ('O', 'C', 'D')) THEN
    BEGIN
      EXECUTE PROCEDURE FIX_PERIOD_FIELDS;

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX 20231009 PERIODS', 'FIX 20231009 PERIODS', CURRENT_TIMESTAMP);
    END

    -- Каталог земельных участков
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX 20231023 STEAD'
    INTO :CNT;
    IF (CNT = 0 AND KEY_LEVEL = 1 AND V$OU_LICENCE_TYPE IN ('O', 'C', 'D')) THEN
    BEGIN
      EXECUTE PROCEDURE FIX_STEAD_FOLDER;

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX 20231023 STEAD', 'FIX 20231023 STEAD', CURRENT_TIMESTAMP);
    END

    -- Движение при переводе в СПО
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX 20231023 SPO TRASFER'
    INTO :CNT;
    IF (CNT = 0 AND KEY_LEVEL = 1 AND V$OU_LICENCE_TYPE = 'C') THEN
    BEGIN
      EXECUTE PROCEDURE FIX_SPO_TRANSFER;

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX 20231023 SPO TRASFER', 'FIX 20231023 SPO TRASFER', CURRENT_TIMESTAMP);
    END

    -- Учебный год в олимпиадах
    -- тут был косяк - вместо школ фильтр поставлен на СПО, и период не прописался
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX 20240215 OD PERIOD'
    INTO :CNT;
    IF (CNT = 0 AND KEY_LEVEL = 1 AND V$OU_LICENCE_TYPE IN ('O', 'C')) THEN
    BEGIN
      EXECUTE PROCEDURE FIX_OD_PERIODS;

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX 20240215 OD PERIOD', 'FIX 20240215 OD PERIOD', CURRENT_TIMESTAMP);
    END

    -- Архив документов
    IF (SCHOOL_ID IS NOT NULL AND KEY_LEVEL = 1) THEN
    BEGIN
      IF(NOT EXISTS(
        SELECT FIRST 1 1
        FROM LINKS L496
        WHERE L496.PARENT_ID = :SCHOOL_ID AND L496.OBJ_TYPE_ID = 496 AND L496.DATE_DEL IS NULL
      ))
      THEN
        SELECT 1 FROM OBJECT_ADD(:SCHOOL_ID, 496) INTO :N;
    END

    -- Тип группы в движении всех ОУ
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX 20231204 MOVE TYPE'
    INTO :CNT;
    IF (CNT = 0 AND KEY_LEVEL = 1) THEN
    BEGIN
      EXECUTE PROCEDURE FIX_MOVE_GROUP_TYPE;

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX 20231204 MOVE TYPE', 'FIX 20231204 MOVE TYPE', CURRENT_TIMESTAMP);
    END

    -- Заполнение новых обязательных полей
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX 20240214 FILL FIELDS'
    INTO :CNT;
    IF (CNT = 0 AND KEY_LEVEL = 1) THEN
    BEGIN
      EXECUTE PROCEDURE FIX_FILL_REQ_FIELDS;

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX 20240214 FILL FIELDS', 'FIX 20240214 FILL FIELDS', CURRENT_TIMESTAMP);
    END

    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX 20240215 ACADEMIC'
    INTO :CNT;
    IF (CNT = 0 AND KEY_LEVEL = 1 AND V$OU_LICENCE_TYPE = 'C') THEN
    BEGIN
      EXECUTE PROCEDURE FIX_SPO_ACAD_MOVEMENTS;

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX 20240215 ACADEMIC', 'FIX 20240215 ACADEMIC', CURRENT_TIMESTAMP);
    END

    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX 20240215X3 SNILS'
    INTO :CNT;
    IF (CNT = 0 AND KEY_LEVEL = 1) THEN
    BEGIN
      -- Повторный вызов, первый был в FIXER4
      SELECT COUNT(*) FROM FIX_EMPLOYEES_SNILS INTO :CNT;

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX 20240215X3 SNILS', 'FIX 20240215X3 SNILS', CURRENT_TIMESTAMP);
    END

    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX 20240222 PTP'
    INTO :CNT;
    IF (CNT = 0 AND KEY_LEVEL = 1) THEN
    BEGIN
      EXECUTE PROCEDURE FIX_LESSON_THEME_PLAN_DEL;

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX 20240222 PTP', 'FIX 20240222 PTP', CURRENT_TIMESTAMP);
    END

    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX 20240306 VER_WARNING'
    INTO :CNT;
    IF (CNT = 0 AND KEY_LEVEL = 1) THEN
    BEGIN
      -- Затираем сообщения о верификации персональных данных, которые не работают
      UPDATE SYNC_LOG SET VER_MSG = NULL WHERE 1 = 1;

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX 20240306 VER_WARNING', 'FIX 20240306 VER_WARNING', CURRENT_TIMESTAMP);
    END

    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX 20240306 DOU LEAVES'
    INTO :CNT;
    IF (CNT = 0 AND KEY_LEVEL = 1 AND V$OU_LICENCE_TYPE = 'D') THEN
    BEGIN
      EXECUTE PROCEDURE FIX_DOU_LEAVES;

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX 20240306 DOU LEAVES', 'FIX 20240306 DOU LEAVES', CURRENT_TIMESTAMP);
    END

    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX 20240406 DOU GUP'
    INTO :CNT;
    IF (CNT = 0 AND KEY_LEVEL = 1 AND V$OU_LICENCE_TYPE = 'D') THEN
    BEGIN
      EXECUTE PROCEDURE FIX_DOU_GUP;

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX 20240406 DOU GUP', 'FIX 20240406 DOU GUP', CURRENT_TIMESTAMP);
    END

    -- В ДОУ зачищаем ошибочные разделы предметов от школьной версии
    IF (KEY_LEVEL = 1 AND V$OU_LICENCE_TYPE = 'D') THEN
    BEGIN
      UPDATE LINKS
      SET DATE_DEL = CURRENT_TIMESTAMP
      WHERE DATE_DEL IS NULL AND PARENT_ID = 208 AND OBJ_ID IN (32771, 32772);
    END

    -- Удаляем кривые записи движения в ДОУ
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX 20240306 DOU GUP'
    INTO :CNT;
    IF (CNT = 0 AND KEY_LEVEL = 1 AND V$OU_LICENCE_TYPE = 'D') THEN
    BEGIN
      EXECUTE PROCEDURE FIX_DOU_GUP;

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX 20240306 DOU GUP', 'FIX 20240306 DOU GUP', CURRENT_TIMESTAMP);
    END

    -- Трэш с кодами специальностей в СПО
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX 20240416 SPO SPEC CODES'
    INTO :CNT;
    IF (CNT = 0 AND KEY_LEVEL = 1 AND V$OU_LICENCE_TYPE = 'C') THEN
    BEGIN
      EXECUTE PROCEDURE FIX_SPO_SPEC_CODES;

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX 20240416 SPO SPEC CODES', 'FIX 20240416 SPO SPEC CODES', CURRENT_TIMESTAMP);
    END

    -- Удаление дублей СНИЛС, воссоздание записей СНИЛС в документах
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX 20240419 SNILS DUB'
    INTO :CNT;
    IF (CNT = 0 AND KEY_LEVEL = 1) THEN
    BEGIN
      EXECUTE PROCEDURE FIXER_SNILS_DUPLICATE;

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX 20240419 SNILS DUB', 'FIX 20240419 SNILS DUB', CURRENT_TIMESTAMP);
    END

    -- Удаление прав доступа к журналам, которые убраны из администрирования
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX 20240611 CJ GRANTS'
    INTO :CNT;
    IF (CNT = 0 AND KEY_LEVEL = 1) THEN
    BEGIN
      DELETE FROM LUSERS
      WHERE LEVEL_ID IN (
        SELECT L.LEVEL_ID
        FROM MODULES M
        JOIN TASKS T ON T.MODULE_ID = M.MODULE_ID AND T.IS_DEL = 0
        JOIN LEVELS L ON L.TASK_ID = T.TASK_ID AND L.IS_DEL = 0 AND L.LEVEL_ID NOT IN (46, 180, 230, 249, 254, 255)
        WHERE M.IS_ACTIVE = 1 AND M.IS_DEL = 0 AND M.MODULE_CODE = 'CJOURNAL'
      );

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX 20240611 CJ GRANTS', 'FIX 20240611 CJ GRANTS', CURRENT_TIMESTAMP);
    END

    -- Удаление прав доступа к журналам, которые убраны из администрирования
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX 20240619 STUDY LEVEL'
    INTO :CNT;
    IF (CNT = 0 AND KEY_LEVEL = 1 AND CURRENT_DATE < '2024-10-01') THEN
    BEGIN
      EXECUTE PROCEDURE FIX_OU_STUDY_LEVELS;

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX 20240619 STUDY LEVEL', 'FIX 20240619 STUDY LEVEL', CURRENT_TIMESTAMP);
    END

    -- Каталог штатных расписаний
    IF (SCHOOL_ID IS NOT NULL AND KEY_LEVEL = 1) THEN
    BEGIN
      IF(NOT EXISTS(
        SELECT FIRST 1 1
        FROM LINKS L508
        WHERE L508.PARENT_ID = :SCHOOL_ID AND L508.OBJ_TYPE_ID = 508 AND L508.DATE_DEL IS NULL
      ))
      THEN
        SELECT 1 FROM OBJECT_ADD(:SCHOOL_ID, 508) INTO :N;
    END

    -- Ошибка в предметных областях УП СОП СПО
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX 20240805 PLAN FIELD'
    INTO :CNT;
    IF (CNT = 0 AND KEY_LEVEL = 1) THEN
    BEGIN
      EXECUTE PROCEDURE FIX_PLAN_FIELD_ID;

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX 20240805 PLAN FIELD', 'FIX 20240805 PLAN FIELD', CURRENT_TIMESTAMP);
    END

    -- Папки для отчетов
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX 20250100 REPORT FOLDERS'
    INTO :CNT;
    IF (CNT = 0) THEN
    BEGIN
      EXECUTE PROCEDURE CREATE_REPORT_FOLDERS(NULL);

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX 20250100 REPORT FOLDERS', 'FIX 20250100 REPORT FOLDERS', CURRENT_TIMESTAMP);
    END

    -- Папки для локальных актов ОО и распределения учебной нагрузки
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX 20241029 LOCAL ACT FOLDER'
    INTO :CNT;
    IF (CNT = 0 AND KEY_LEVEL = 1) THEN
    BEGIN
      EXECUTE PROCEDURE CREATE_LOCAL_ACT_FOLDER;

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX 20241029 LOCAL ACT FOLDER', 'FIX 20241029 LOCAL ACT FOLDER', CURRENT_TIMESTAMP);
    END

    -- Зачистка значений ОВЗ ученика, затесавшихся из старого справочника
    -- Нет vs нет
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX 20250310 OVZ'
    INTO :CNT;
    IF (CNT = 0 AND KEY_LEVEL = 1) THEN
    BEGIN
      UPDATE VALL
      SET LISTVAL_ID = 13289
      WHERE LISTVAL_ID = 5 AND PARAM_ID = 207;

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX 20250310 OVZ', 'FIX 20250310 OVZ', CURRENT_TIMESTAMP);
    END

    -- Автодобавление общих правил нумерации приказов
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX 20250401 ORDER NUM RULE AUTO CREATE'
    INTO :CNT;
    IF (CNT = 0 AND KEY_LEVEL = 1) THEN
    BEGIN
      EXECUTE PROCEDURE ORD_NM_RULE_AUTO_CREATE(13266); -- для обучающихся
      EXECUTE PROCEDURE ORD_NM_RULE_AUTO_CREATE(14255); -- для сотрудников

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX 20250401 ORDER NUM RULE AUTO CREATE', 'FIX 20250401 ORDER NUM RULE AUTO CREATE', CURRENT_TIMESTAMP);
    END

    -- Замена параметров функций кадрового учета на строковые параметры
    S1 = NULL;
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX CALC JOB PARAMS'
    INTO :CNT;
    IF (CNT = 0 AND KEY_LEVEL = 1) THEN
    BEGIN
      SELECT COUNT(*) FROM FIX_CALC_JOB_PARAMS INTO :S1;

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX CALC JOB PARAMS', 'FIX CALC JOB PARAMS', CURRENT_TIMESTAMP);
    END

    -- восстановление групп и подгрупп должностей для каждой должности
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX RESTORE JOB GROUP'
    INTO :CNT;
    IF (CNT = 0 AND KEY_LEVEL = 1) THEN
    BEGIN
      SELECT COUNT(*) FROM FIX_RESTORE_JOB_GROUP INTO :N;

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX RESTORE JOB GROUP', 'FIX RESTORE JOB GROUP', CURRENT_TIMESTAMP);
    END

    -- Перестановка метки для переотправки всех текущих итоговых каждый раз
    IF(KEY_LEVEL = 1) THEN
    BEGIN
      UPDATE CJ2_MARK
      SET DATE_MODIFY = CURRENT_TIMESTAMP
      WHERE FINAL_ID IS NOT NULL;
    END

    -- Зачищаем старые учебные планы
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX PLAN CLEANUP 11092025'
    INTO :CNT;
    IF (CNT = 0 AND KEY_LEVEL = 1 AND CURRENT_DATE < '01.09.2025') THEN
    BEGIN
      EXECUTE PROCEDURE PLAN_CLEANUP;

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX PLAN CLEANUP 11092025', 'FIX PLAN CLEANUP 11092025', CURRENT_TIMESTAMP);
    END

    -- Генерация меток времени для уроков
    -- Повторно, с починкой ленты расписания
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX CJ2 LESSON TIME 2'
    INTO :CNT;
    IF (CNT = 0 AND KEY_LEVEL = 1) THEN
    BEGIN
      EXECUTE PROCEDURE FIX_CJ2_LESSON_TIME;

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX CJ2 LESSON TIME 2', 'FIX CJ2 LESSON TIME 2', CURRENT_TIMESTAMP);
    END

    -- Заполнение ступени обучения в PERSON_MOVEMENTS
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX MOVE LEVEL ID 2'
    INTO :CNT;
    IF (CNT = 0 AND KEY_LEVEL = 1) THEN
    BEGIN
      EXECUTE PROCEDURE FIX_MOVE_LEVEL_ID;

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX MOVE LEVEL ID 2', 'FIX MOVE LEVEL ID 2', CURRENT_TIMESTAMP);
    END

    -- Конвертация поля из INT в FLOAT для оценочного экзамена
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX DEMO_EXAM FORMAT'
    INTO :CNT;
    IF (CNT = 0 AND KEY_LEVEL = 1) THEN
    BEGIN
      EXECUTE PROCEDURE FIX_DEMO_EXAM_FORMAT;

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX DEMO_EXAM FORMAT', 'FIX DEMO_EXAM FORMAT', CURRENT_TIMESTAMP);
    END

    -- Перенос классов ГИА в отдельную папку в Мультипараграфе
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX GIA NEW FOLDER'
    INTO :CNT;
    IF (CNT = 0 AND KEY_LEVEL = 1 AND V$OU_LICENCE_TYPE = 'S') THEN
    BEGIN
      EXECUTE PROCEDURE FIX_GIA_NEW_FOLDER;

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX GIA NEW FOLDER', 'FIX GIA NEW FOLDER', CURRENT_TIMESTAMP);
    END

    -- Изменение уровня руководителей для рук структурных подразделений
    SELECT COUNT(*)
    FROM INFO I
    WHERE I.INFO_CODE = 'FIX JOBS R2 TO R3'
    INTO :CNT;
    IF (CNT = 0 AND KEY_LEVEL = 1 AND V$OU_LICENCE_TYPE = 'S') THEN
    BEGIN
      EXECUTE PROCEDURE FIX_JOB_R3;

      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('FIX JOBS R2 TO R3', 'FIX JOBS R2 TO R3', CURRENT_TIMESTAMP);
    END

    -- Дублируем форму обучения ученика из формы обучения класса   https://jira.netrika.ru/browse/PARAGRAPH-1229
    --SELECT COUNT(*)
    --FROM INFO I
    --WHERE I.INFO_CODE = 'FIX STUDENT EDU_FROM'
    --INTO :CNT;
    --IF (CNT = 0 AND KEY_LEVEL = 1 AND (V$OU_LICENCE_TYPE = 'S' OR V$OU_LICENCE_TYPE = 'C')) THEN
    --BEGIN
    --  EXECUTE PROCEDURE FIX_STUDENT_EDU_FROM;

    --  INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
    --  VALUES ('FIX STUDENT EDU_FROM', 'FIX STUDENT EDU_FROM', CURRENT_TIMESTAMP);
    --END

    -- Перегенерация контингента, перенесено из FIXER3
    -- Выполняется всегда
    IF (KEY_LEVEL = 1) THEN
    BEGIN
      EXECUTE PROCEDURE MONITORING_CONTINGENT_ADD;
    END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIXER_ALL_SNILS (
    SCHOOL_ID BIGINT = NULL)
AS
DECLARE VARIABLE V$OBJ_ID BIGINT;
BEGIN
    IF (SCHOOL_ID IS NULL) THEN
    BEGIN
        SELECT FIRST 1 L.OBJ_ID
        FROM LINKS L
        WHERE L.PARENT_ID IS NULL
        AND L.OBJ_TYPE_ID = 2
        AND L.DATE_DEL IS NULL
        INTO :SCHOOL_ID;
    END

    FOR
        SELECT L10.OBJ_ID
        FROM LINKS L7
        JOIN LINKS L8
        ON L8.PARENT_ID = L7.OBJ_ID
        JOIN LINKS L9
        ON L9.PARENT_ID = L8.OBJ_ID
        JOIN LINKS L10
        ON L10.PARENT_ID = L9.OBJ_ID
        LEFT JOIN VALS V1409
        ON V1409.OBJ_ID = L10.OBJ_ID
        AND V1409.PARAM_ID = 1409
        AND V1409.IS_DEL = 0
        WHERE L7.PARENT_ID = :SCHOOL_ID
        AND L7.OBJ_TYPE_ID = 7
        AND L7.DATE_DEL IS NULL
        AND L8.OBJ_TYPE_ID = 8
        AND L8.DATE_DEL IS NULL
        AND L9.OBJ_TYPE_ID = 9
        AND L9.DATE_DEL IS NULL
        AND L10.OBJ_TYPE_ID = 10
        AND L10.DATE_DEL IS NULL
        AND V1409.VAL IS NULL
        INTO :V$OBJ_ID
    DO
    BEGIN
        EXECUTE PROCEDURE FIXER_SNILS(:V$OBJ_ID);
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIXER_ATHOME_STUDENTS
AS
declare variable V$OBJ_ID bigint;
declare variable T bigint;
begin

  FOR
    SELECT O.OBJ_ID
    FROM OBJECTS O
    LEFT JOIN VALL V2169 ON V2169.OBJ_ID = O.OBJ_ID AND V2169.PARAM_ID = 2169 AND V2169.IS_DEL = 0
    WHERE O.TYPE_ID = 10 AND V2169.LISTVAL_ID IS NULL
    INTO :V$OBJ_ID
  DO
  BEGIN
    SELECT BLOB_ID FROM VAL_ADD(2169, :V$OBJ_ID, 3) INTO :T;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIXER_BAD_RELEASE
AS
declare variable V$OBJ_ID bigint;
declare variable V$PERSON_ID bigint;
declare variable V$TYPE bigint;
declare variable V$MOVEDATE date;
declare variable V$DATE date;
declare variable V$REASON bigint;
declare variable V$ORDER_DATE date;
declare variable V$ORDER_NUM varchar(100);
begin

  -- Зачистка кривого признака выпускного класса
  FOR
    SELECT L9.OBJ_ID, L9.OBJ_TYPE_ID
    FROM LINKS L2
    JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0 AND V49.LISTVAL_ID NOT IN (45, 47, 48)
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 187) AND L9.DATE_DEL IS NULL
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :V$OBJ_ID, :V$TYPE
  DO
  BEGIN
    UPDATE OR INSERT INTO VALL
    (OBJ_ID, PARAM_ID, LISTVAL_ID, IS_DEL)
    VALUES (:V$OBJ_ID, IIF(:V$TYPE = 9, 1362, 1747), 3, 0)
    MATCHING (OBJ_ID, PARAM_ID);
  END

  -- Пытаемся починить разовые потери в реестре движения
  FOR
    SELECT M.PERSON_ID, COUNT(*)
    FROM PERSON_MOVEMENTS M
    JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
    WHERE M.DATE_DEL IS NULL AND M.DATE_OUT IS NULL
    GROUP BY 1
    HAVING COUNT(*) > 1
    INTO :V$PERSON_ID, :V$TYPE
  DO
  BEGIN

    -- Пытаемся чинить ошибки
    WHILE(V$TYPE > 1) DO
    BEGIN

      SELECT FIRST 1 M.OBJ_ID, M.DATE_IN
      FROM PERSON_MOVEMENTS M
      JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
      WHERE M.DATE_DEL IS NULL AND M.DATE_OUT IS NULL AND M.PERSON_ID = :V$PERSON_ID
      ORDER BY M.DATE_IN
      INTO :V$OBJ_ID, :V$MOVEDATE;

      -- Пытаемся найти следующее движение
      V$REASON = NULL;
      V$DATE = NULL;
      V$ORDER_DATE = NULL;
      V$ORDER_NUM = NULL;
      SELECT FIRST 1 M.REASON_IN, M.DATE_IN, M.ORDER_DATE_IN, M.ORDER_NUM_IN
      FROM PERSON_MOVEMENTS M
      JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
      WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :V$PERSON_ID AND M.DATE_IN >= :V$MOVEDATE AND M.OBJ_ID <> :V$OBJ_ID
      ORDER BY M.DATE_IN
      INTO :V$REASON, :V$DATE, :V$ORDER_DATE, :V$ORDER_NUM;

      -- Если ученик в выбывших, и это последняя по датам запись - пытаемся найти когда он выбыл
      IF(V$REASON IS NULL) THEN 
      BEGIN

        SELECT FIRST 1 LP8X.DATE_INS, IIF(LP8X.PARENT_TYPE_ID IN (81, 82), 811, 812)
        FROM LINKS LP8X
        WHERE LP8X.OBJ_ID = :V$PERSON_ID AND LP8X.PARENT_TYPE_ID IN (81, 82, 83) AND LP8X.DATE_DEL IS NULL AND LP8X.DATE_INS >= :V$MOVEDATE
        ORDER BY LP8X.DATE_INS
        INTO :V$DATE, :V$REASON;

      END

      IF(V$REASON IS NULL) THEN EXCEPTION DATA_ERROR 'Не удалось восстановить реестр движения. Требуется откат на базу до обновления 26.08 для ' || V$PERSON_ID;

      UPDATE PERSON_MOVEMENTS
      SET REASON_OUT = :V$REASON, DATE_OUT = :V$DATE, ORDER_DATE_OUT = :V$ORDER_DATE, ORDER_NUM_OUT = :V$ORDER_NUM
      WHERE OBJ_ID = :V$OBJ_ID;

      V$TYPE = V$TYPE - 1;

    END

  END

  -- Подвисшие записи зачисления у выбывших
  FOR
    SELECT M.PERSON_ID, COUNT(*)
    FROM PERSON_MOVEMENTS M
    JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
    LEFT JOIN LINKS LP9 ON LP9.OBJ_ID = M.PERSON_ID AND LP9.PARENT_TYPE_ID = 9 AND LP9.DATE_DEL IS NULL
    WHERE M.DATE_DEL IS NULL AND M.DATE_OUT IS NULL AND LP9.PARENT_ID IS NULL
    GROUP BY 1
    INTO :V$PERSON_ID, :V$TYPE
  DO
  BEGIN

    -- Пытаемся чинить ошибки
    WHILE(V$TYPE > 0) DO
    BEGIN

      SELECT FIRST 1 M.OBJ_ID, M.DATE_IN
      FROM PERSON_MOVEMENTS M
      JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
      WHERE M.DATE_DEL IS NULL AND M.DATE_OUT IS NULL AND M.PERSON_ID = :V$PERSON_ID
      ORDER BY M.DATE_IN
      INTO :V$OBJ_ID, :V$MOVEDATE;

      -- Пытаемся найти следующее движение
      V$REASON = NULL;
      V$DATE = NULL;
      V$ORDER_DATE = NULL;
      V$ORDER_NUM = NULL;
      SELECT FIRST 1 M.REASON_IN, M.DATE_IN, M.ORDER_DATE_IN, M.ORDER_NUM_IN
      FROM PERSON_MOVEMENTS M
      JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
      WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :V$PERSON_ID AND M.DATE_IN >= :V$MOVEDATE AND M.OBJ_ID <> :V$OBJ_ID
      ORDER BY M.DATE_IN
      INTO :V$REASON, :V$DATE, :V$ORDER_DATE, :V$ORDER_NUM;

      -- Если ученик в выбывших, и это последняя по датам запись - пытаемся найти когда он выбыл
      IF(V$REASON IS NULL) THEN 
      BEGIN

        SELECT FIRST 1 LP8X.DATE_INS, IIF(LP8X.PARENT_TYPE_ID IN (81, 82), 811, 812)
        FROM LINKS LP8X
        WHERE LP8X.OBJ_ID = :V$PERSON_ID AND LP8X.PARENT_TYPE_ID IN (81, 82, 83) AND LP8X.DATE_DEL IS NULL AND LP8X.DATE_INS >= :V$MOVEDATE
        ORDER BY LP8X.DATE_INS
        INTO :V$DATE, :V$REASON;

      END

      -- Было кривое отчисление задним числом
      IF(V$REASON IS NULL) THEN 
      BEGIN
        V$DATE = V$MOVEDATE;
        V$REASON = 811;
      END

      IF(V$REASON IS NULL) THEN EXCEPTION DATA_ERROR 'Не удалось восстановить реестр движения. Требуется откат на базу до обновления 26.08 для ' || V$PERSON_ID;

      UPDATE PERSON_MOVEMENTS
      SET REASON_OUT = :V$REASON, DATE_OUT = :V$DATE, ORDER_DATE_OUT = :V$ORDER_DATE, ORDER_NUM_OUT = :V$ORDER_NUM
      WHERE OBJ_ID = :V$OBJ_ID;

      V$TYPE = V$TYPE - 1;

    END

  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIXER_CERTIFICATE_FINAL_MARKS (
    SCHOOL_ID BIGINT)
AS
declare variable V$PUPIL_ID bigint;
declare variable V$SUBJECT_ID bigint;
declare variable V$MARK varchar(255);
declare variable V$SORT_ORDER integer;
declare variable V$P_SUBJECT_ID bigint;
BEGIN
    FOR
        SELECT V1872.VAL,
               LM.SUBJECT_ID,
               LM.MARK,
               LM.SORT_ORDER
        FROM LINKS L7
        
        JOIN LINKS L234
        ON L234.PARENT_ID = L7.OBJ_ID
        AND L234.OBJ_TYPE_ID = 234
        AND L234.DATE_DEL IS NULL
        
        JOIN VALR V1872
        ON V1872.OBJ_ID = L234.OBJ_ID
        AND V1872.PARAM_ID = 1872
        AND V1872.IS_DEL = 0
        
        LEFT JOIN CERTIFICATE_PUPIL_LOAD_SUBJECTS(2014, L7.OBJ_ID, NULL, V1872.VAL, 1) LM
        ON 1=1
        
        WHERE L7.PARENT_ID = :SCHOOL_ID
        AND L7.OBJ_TYPE_ID = 7
        AND L7.DATE_DEL IS NULL
        
        AND LM.INCLUDING_TYPE_ID = 5381
        AND P_SUBJECT_ID IS NULL
        AND MARK IS NOT NULL
        INTO :V$PUPIL_ID,
             :V$SUBJECT_ID,
             :V$MARK,
             :V$SORT_ORDER
    DO
    BEGIN
        SELECT P_SUBJECT_ID
        FROM CERTIFICATE_PUPIL_LOAD_SUBJ_SET (
            2014,
            :V$PUPIL_ID,
            1,
            NULL,
            5381,
            :V$SUBJECT_ID,
            :V$MARK,
            :V$SORT_ORDER
        )
        INTO :V$P_SUBJECT_ID;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIXER_CERTIFICATE_MARK
AS
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$VAL VARCHAR(4000);
BEGIN
    FOR
        SELECT OBJ_ID,VAL
        FROM VALI
        WHERE PARAM_ID = 1870
        AND IS_DEL = 0

        INTO :V$OBJ_ID, :V$VAL
    DO
    BEGIN
        UPDATE OR INSERT INTO VALS(OBJ_ID,PARAM_ID,IS_DEL,VAL)
        VALUES(:V$OBJ_ID,1870,0,:V$VAL);

        DELETE FROM VALI
        WHERE OBJ_ID= :V$OBJ_ID
        AND PARAM_ID= 1870;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIXER_CHANGER_LOST
AS
declare variable V$OBJ_ID bigint;
declare variable V$ORDER_NUMBER varchar(100);
declare variable V$ORDER_DATE timestamp;
declare variable V$ACTION_DATE timestamp;
declare variable V$USER_ID bigint;
BEGIN

  -- Смысл утрачен

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIXER_CHANGER_LOST2
AS
declare variable V$SCHOOL_ID bigint;
declare variable V$MOVEMENT_ID bigint;
declare variable V$LINK_ID bigint;
declare variable V$ACTION_DATE date;
declare variable V$START_YEAR integer;
declare variable V$END_YEAR integer;
declare variable V$PUPIL_OUT_FOUND bigint;
declare variable V$USER_ID bigint;
declare variable V$CONTAINER_PUPIL_OUT_ID bigint;
declare variable V$BLOB_ID bigint;
declare variable V$CAPTION varchar(4000);
declare variable V$LAST_GRADE_TYPE_ID bigint;
BEGIN

  -- Смысл утрачен

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIXER_CJ_DUPLICATES
AS
declare variable V$GROUP_ID bigint;
declare variable V$SUBJECT_ID bigint;
declare variable V$OBJ_ID bigint;
declare variable V$DG_ID bigint;
declare variable N integer;
begin

  FOR
    SELECT LP2.EXT_OBJ_ID, J.SUBJECT_ID
    FROM CJ2_JOURNAL J
    JOIN LINKS LP2 ON LP2.OBJ_ID = J.GRADE_ID AND LP2.PARENT_TYPE_ID = 2 AND LP2.EXT_OBJ_ID IS NOT NULL
    GROUP BY 1, 2
    HAVING COUNT(*) > 1
    INTO :V$GROUP_ID, :V$SUBJECT_ID
  DO
  BEGIN

    N = 0;

    FOR
      SELECT J.OBJ_ID, J.GRADE_ID
      FROM CJ2_JOURNAL J
      JOIN LINKS LP2 ON LP2.OBJ_ID = J.GRADE_ID AND LP2.PARENT_TYPE_ID = 2 AND LP2.EXT_OBJ_ID = :V$GROUP_ID
      LEFT JOIN CJ2_JOURNAL_LESSONS L ON L.CJ_ID = J.OBJ_ID AND L.DATE_DEL IS NULL
      WHERE J.SUBJECT_ID = :V$SUBJECT_ID AND L.OBJ_ID IS NULL
      ORDER BY J.DATE_DEL NULLS FIRST, J.OBJ_ID
      INTO :V$OBJ_ID, :V$DG_ID
    DO
    BEGIN

      IF(N > 0) THEN
      BEGIN
        DELETE FROM CJ2_JOURNAL WHERE OBJ_ID = :V$OBJ_ID;
        DELETE FROM PERSON_MOVEMENTS WHERE GROUP_ID = :V$DG_ID;
        DELETE FROM LINKS WHERE PARENT_ID = :V$DG_ID OR OBJ_ID = :V$DG_ID;
        DELETE FROM OBJECTS WHERE OBJ_ID = :V$DG_ID;
      END

      N = N + 1;

    END

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIXER_CLEAR_TEACHER_LABOR_RATE (
    I$SCHOOL_ID BIGINT)
AS
declare variable V$OBJ_ID bigint;
BEGIN
    FOR
        SELECT L13.OBJ_ID
        FROM LINKS L13
        JOIN VALL V58 ON V58.OBJ_ID = L13.OBJ_ID AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0
        JOIN LISTVALS LV58 ON LV58.LISTVAL_ID = V58.LISTVAL_ID AND LV58.TAG = 'U' AND LV58.LISTVAL_ID <> 121
        WHERE L13.PARENT_ID = :I$SCHOOL_ID AND L13.OBJ_TYPE_ID = 13 AND L13.DATE_DEL IS NULL
        INTO :V$OBJ_ID
    DO
    BEGIN
        UPDATE VALF
        SET IS_DEL = 1
        WHERE OBJ_ID = :V$OBJ_ID
        AND PARAM_ID = 62
        AND IS_DEL = 0;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIXER_CLONE_MARKS
AS
declare variable V$CID bigint;
declare variable V$PERSON_ID bigint;
declare variable V$T timestamp;
begin

  FOR
    SELECT M.CONTROL_ID, M.STUDENT_ID, MAX(M.DATE_ADD)
    FROM CJ2_MARK M
    WHERE M.DATE_DEL IS NULL AND M.CONTROL_ID IS NOT NULL
    GROUP BY 1, 2
    HAVING COUNT(*) > 1
    INTO :V$CID, :V$PERSON_ID, :V$T
  DO
  BEGIN
    UPDATE CJ2_MARK
    SET DATE_DEL = CURRENT_TIMESTAMP, REASON_ID = 11084
    WHERE CONTROL_ID = :V$CID AND STUDENT_ID = :V$PERSON_ID AND DATE_ADD < :V$T AND DATE_DEL IS NULL;
  END

  FOR
    SELECT M.FINAL_ID, M.STUDENT_ID, MAX(M.DATE_ADD)
    FROM CJ2_MARK M
    WHERE M.DATE_DEL IS NULL AND M.FINAL_ID IS NOT NULL
    GROUP BY 1, 2
    HAVING COUNT(*) > 1
    INTO :V$CID, :V$PERSON_ID, :V$T
  DO
  BEGIN
    UPDATE CJ2_MARK
    SET DATE_DEL = CURRENT_TIMESTAMP, REASON_ID = 11084
    WHERE FINAL_ID = :V$CID AND STUDENT_ID = :V$PERSON_ID AND DATE_ADD < :V$T AND DATE_DEL IS NULL;

    EXECUTE PROCEDURE FINALMARK_SYNCHRONIZE(:V$CID);
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIXER_CONVERT_VD
AS
declare variable V$FOLDER_ID bigint;
declare variable V$PLAN_ID bigint;
declare variable V$STAGE_ID bigint;
declare variable V$SUBJECT_ID bigint;
declare variable V$NEW_ID bigint;
declare variable V$NEW_STAGE_ID bigint;
declare variable V$STAGE_INDEX bigint;
declare variable V$WEEK bigint;
declare variable V$HOURS bigint;
declare variable V$BLOCK_ID bigint;
declare variable V$NEW_SUBJECT_ID bigint;
declare variable TMP bigint;
declare variable S varchar(1000);
declare variable N integer;
begin

  FOR
    SELECT L57.OBJ_ID, L50.OBJ_ID
    FROM LINKS L69
    JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
    JOIN LINKS L50 ON L50.PARENT_ID = L57.OBJ_ID AND L50.OBJ_TYPE_ID = 50 AND L50.DATE_DEL IS NULL
    JOIN VALL V2545 ON V2545.OBJ_ID = L50.OBJ_ID AND V2545.PARAM_ID = 2545 AND V2545.IS_DEL = 0 AND V2545.LISTVAL_ID = 2
    WHERE L69.PARENT_TYPE_ID = 2 AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL
    INTO :V$FOLDER_ID, :V$PLAN_ID
  DO
  BEGIN

    SELECT OBJ_ID FROM OBJECT_ADD(:V$FOLDER_ID, 400) INTO :V$NEW_ID;

    -- Параметры плана
    SELECT BLOB_ID FROM VAL_ADD(3022, :V$NEW_ID, 2) INTO :TMP;

    S = NULL;
    SELECT V FROM VAL_GET(:V$PLAN_ID, 374) WHERE IS_EXISTS = 1 INTO :S;
    SELECT BLOB_ID FROM VAL_ADD(3012, :V$NEW_ID, :S) INTO :TMP;

    S = NULL;
    SELECT I FROM VAL_GET(:V$PLAN_ID, 2478) WHERE IS_EXISTS = 1 INTO :S;
    SELECT BLOB_ID FROM VAL_ADD(3014, :V$NEW_ID, :S) INTO :TMP;

    S = NULL;
    SELECT I FROM VAL_GET(:V$PLAN_ID, 1759) WHERE IS_EXISTS = 1 INTO :S;
    SELECT BLOB_ID FROM VAL_ADD(3015, :V$NEW_ID, :S) INTO :TMP;

    S = NULL;
    SELECT I FROM VAL_GET(:V$PLAN_ID, 2101) WHERE IS_EXISTS = 1 INTO :S;
    SELECT BLOB_ID FROM VAL_ADD(3016, :V$NEW_ID, :S) INTO :TMP;

    -- Этапы обучения
    FOR
      SELECT L54.OBJ_ID, V381.LISTVAL_ID, V2837.LISTVAL_ID, V382.VAL
      FROM LINKS L54
      JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
      JOIN VALL V2837 ON V2837.OBJ_ID = L54.OBJ_ID AND V2837.PARAM_ID = 2837 AND V2837.IS_DEL = 0
      JOIN VALI V382 ON V382.OBJ_ID = L54.OBJ_ID AND V382.PARAM_ID = 382 AND V382.IS_DEL = 0
      WHERE L54.PARENT_ID = :V$PLAN_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
      INTO :V$STAGE_ID, :V$STAGE_INDEX, :V$WEEK, :V$HOURS
    DO
    BEGIN
      SELECT OBJ_ID FROM OBJECT_ADD(:V$NEW_ID, 54) INTO :V$NEW_STAGE_ID;
      SELECT BLOB_ID FROM VAL_ADD(381, :V$NEW_STAGE_ID, :V$STAGE_INDEX) INTO :TMP;
      SELECT BLOB_ID FROM VAL_ADD(2837, :V$NEW_STAGE_ID, :V$WEEK) INTO :TMP;
      SELECT BLOB_ID FROM VAL_ADD(382, :V$NEW_STAGE_ID, :V$HOURS) INTO :TMP;
    END

    INSERT INTO PLAN_SUBJECTS
    (PLAN_ID, FIELD_ID, ROW_TYPE, SORT_INDEX, GLOBAL_INDEX)
    VALUES (:V$NEW_ID, 12927, 0, 0, 0)
    RETURNING OBJ_ID INTO :V$BLOCK_ID;

    N = 1;

    -- Предметы и нагрузки
    FOR
      SELECT L51.OBJ_ID
      FROM LINKS L49
      JOIN LINKS L51 ON L51.PARENT_ID = L49.OBJ_ID AND L51.OBJ_TYPE_ID = 51 AND L51.DATE_DEL IS NULL
      WHERE L49.PARENT_ID = :V$PLAN_ID AND L49.OBJ_TYPE_ID = 49
      INTO :V$SUBJECT_ID
    DO
    BEGIN

      INSERT INTO PLAN_SUBJECTS
      (PLAN_ID, PARENT_ID, SUBJECT_ID, FIELD_ID, ROW_TYPE, SORT_INDEX, GLOBAL_INDEX, LEVEL_INDEX)
      VALUES (:V$NEW_ID, :V$BLOCK_ID, :V$SUBJECT_ID, NULL, 10, :N - 1, :N, 1)
      RETURNING OBJ_ID INTO :V$NEW_SUBJECT_ID;

      N = N + 1;

      FOR
        SELECT L54N.OBJ_ID, V2547.VAL, V385.VAL
        FROM LINKS L56
        JOIN LINKS LP54 ON LP54.OBJ_ID = L56.OBJ_ID AND LP54.PARENT_TYPE_ID = 54 AND LP54.DATE_DEL IS NULL
        JOIN VALL V381 ON V381.OBJ_ID = LP54.PARENT_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
        JOIN LINKS L54N ON L54N.PARENT_ID = :V$NEW_ID AND L54N.OBJ_TYPE_ID = 54 AND L54N.DATE_DEL IS NULL
        JOIN VALL V381N ON V381N.OBJ_ID = L54N.OBJ_ID AND V381N.PARAM_ID = 381 AND V381N.IS_DEL = 0 AND V381N.LISTVAL_ID = V381.LISTVAL_ID
        JOIN VALI V2547 ON V2547.OBJ_ID = L56.OBJ_ID AND V2547.PARAM_ID = 2547 AND V2547.IS_DEL = 0
        JOIN VALI V385 ON V385.OBJ_ID = L56.OBJ_ID AND V385.PARAM_ID = 385 AND V385.IS_DEL = 0
        WHERE L56.PARENT_ID = :V$SUBJECT_ID AND L56.OBJ_TYPE_ID = 56 AND L56.DATE_DEL IS NULL
        INTO :V$STAGE_ID, :V$WEEK, :V$HOURS
      DO
      BEGIN
        INSERT INTO PLAN_LOADS
        (SUBJECT_ID, STAGE_ID, WEEKS, LOAD_HOURS, LOAD_HOURS_S1, CONTROL_Q1)
        VALUES (:V$NEW_SUBJECT_ID, :V$STAGE_ID, :V$WEEK, :V$HOURS, :V$HOURS, 5254);
      END

    END

  END

  -- Все старые удаляем
  UPDATE LINKS L50
  SET L50.DATE_DEL = CURRENT_TIMESTAMP
  WHERE L50.PARENT_TYPE_ID = 57 AND L50.OBJ_TYPE_ID = 50 AND L50.DATE_DEL IS NULL AND EXISTS(
    SELECT * FROM VALL V2545 WHERE V2545.OBJ_ID = L50.OBJ_ID AND V2545.PARAM_ID = 2545 AND V2545.IS_DEL = 0 AND V2545.LISTVAL_ID = 2
  );

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIXER_DELETED_CLASSES
AS
declare variable V$LINK_ID bigint;
BEGIN
    FOR
        SELECT LP9.LINK_ID
        FROM LINKS LP9
        
        LEFT JOIN LINKS LP8
        ON LP8.OBJ_ID = LP9.PARENT_ID
        AND LP8.PARENT_TYPE_ID IN (8, 77)
        AND LP8.DATE_DEL IS NULL
        
        WHERE LP9.OBJ_TYPE_ID = 10
        AND LP9.PARENT_TYPE_ID = 9
        AND LP9.DATE_DEL IS NULL
        AND LP8.PARENT_ID IS NULL

        INTO :V$LINK_ID
    DO
    BEGIN
        UPDATE LINKS
        SET DATE_DEL = CURRENT_TIMESTAMP
        WHERE LINK_ID = :V$LINK_ID;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIXER_DELETED_CLASSES2
AS
declare variable V$DATE_DEL TIMESTAMP;
declare variable V$COUNT integer;
declare variable V$LINK_ID bigint;
BEGIN
    FOR
        SELECT L10.DATE_DEL,
               COUNT(*)
        FROM LINKS L10
        
        JOIN LINKS L9
        ON L9.OBJ_ID = L10.PARENT_ID
        AND L9.PARENT_TYPE_ID = 77
        AND L9.DATE_DEL IS NULL
        
        WHERE L10.PARENT_TYPE_ID = 9
        AND L10.OBJ_TYPE_ID = 10
        AND L10.DATE_DEL IS NOT NULL
        AND DATEDIFF(DAY, L10.DATE_DEL, CURRENT_TIMESTAMP) < 10
        
        GROUP BY L10.DATE_DEL
        HAVING COUNT(*) > 1

        INTO :V$DATE_DEL,
             :V$COUNT
    DO
    BEGIN
        FOR
            SELECT L10.LINK_ID
            FROM LINKS L10
        
            JOIN LINKS L9
            ON L9.OBJ_ID = L10.PARENT_ID
            AND L9.PARENT_TYPE_ID = 77
            AND L9.DATE_DEL IS NULL
        
            WHERE L10.PARENT_TYPE_ID = 9
            AND L10.OBJ_TYPE_ID = 10
            AND DATEDIFF(MINUTE, L10.DATE_DEL, :V$DATE_DEL) = 0

            INTO :V$LINK_ID
        DO
        BEGIN
            UPDATE LINKS
            SET DATE_DEL = NULL
            WHERE LINK_ID = :V$LINK_ID
            AND DATE_DEL IS NOT NULL;
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIXER_DOU_INPUT (
    I$SCHOOL_ID BIGINT)
AS
declare variable V$LINK_ID bigint;
declare variable V$OBJ_ID bigint;
BEGIN
    IF (NOT EXISTS(                 
        SELECT FIRST 1 1
        FROM LINKS L77
        WHERE L77.PARENT_ID = :I$SCHOOL_ID
        AND L77.OBJ_TYPE_ID = 77
        AND L77.DATE_DEL IS NULL
    )) THEN
    BEGIN
        SELECT OBJ_ID
        FROM OBJECT_ADD(:I$SCHOOL_ID, 77)
        INTO :V$OBJ_ID;
    END
    FOR
        SELECT FIRST 1
               L77.OBJ_ID
        FROM LINKS L77
        WHERE L77.PARENT_ID = :I$SCHOOL_ID
        AND L77.OBJ_TYPE_ID = 77
        AND L77.DATE_DEL IS NULL

        INTO :V$OBJ_ID
    DO
    BEGIN
        FOR
            SELECT L10.LINK_ID
            FROM LINKS L173
    
            JOIN LINKS L10
            ON L10.PARENT_ID = L173.OBJ_ID
            AND L10.OBJ_TYPE_ID = 10
            AND L10.DATE_DEL IS NULL
    
            WHERE L173.PARENT_ID = :I$SCHOOL_ID
            AND L173.OBJ_TYPE_ID = 173
            AND L173.DATE_DEL IS NULL
    
            INTO :V$LINK_ID
        DO
        BEGIN
            UPDATE LINKS
            SET PARENT_ID = :V$OBJ_ID,
                PARENT_TYPE_ID = 77
            WHERE LINK_ID = :V$LINK_ID;
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIXER_DOU_OUT_FOLDERS
AS
declare variable V$LINK_ID bigint;
declare variable V$OBJ_ID bigint;
declare variable V$BLOB_ID bigint;
declare variable V$CONTAINER_PUPIL_OUT_ID bigint;
declare variable V$NEW_OBJ_ID bigint;
declare variable V$LISTVAL_ID bigint;
declare variable V$YEAR_FROM integer;
declare variable V$YEAR_TO integer;
BEGIN
    INSERT INTO FILTER_SESSION_VALS(OBJ_ID, TYPE_ID)
    SELECT L82.OBJ_ID, L82.LINK_ID
    FROM LINKS L82
    WHERE L82.OBJ_TYPE_ID = 82
    AND L82.DATE_DEL IS NULL
    AND (NOT EXISTS(
        SELECT FIRST 1 1
        FROM LINKS L
        WHERE L.PARENT_ID = L82.OBJ_ID
        AND L.DATE_DEL IS NULL
    ) OR EXISTS(
        SELECT FIRST 1 1
        FROM VALL V
        WHERE V.OBJ_ID = L82.OBJ_ID
        AND V.PARAM_ID = 447
        AND V.IS_DEL = 0
        AND V.LISTVAL_ID IN (899, 900)
    )) ;

    FOR
        SELECT OBJ_ID, TYPE_ID
        FROM FILTER_SESSION_VALS
        INTO :V$OBJ_ID, :V$LINK_ID
    DO
    BEGIN
        IF (NOT EXISTS(
            SELECT FIRST 1 1
            FROM LINKS
            WHERE PARENT_ID = :V$OBJ_ID
            AND DATE_DEL IS NULL
        )) THEN
        BEGIN
            UPDATE LINKS
            SET DATE_DEL = CURRENT_TIMESTAMP
            WHERE LINK_ID = :V$LINK_ID;
        END
        ELSE
        BEGIN
            FOR
                SELECT V447.LISTVAL_ID,
                       V448.VAL,
                       V449.VAL,
                       L.PARENT_ID
                FROM VALL V447
    
                JOIN VALI V448
                ON V448.OBJ_ID = V447.OBJ_ID
                AND V448.PARAM_ID = 448
                AND V448.IS_DEL = 0
    
                JOIN VALI V449
                ON V449.OBJ_ID = V447.OBJ_ID
                AND V449.PARAM_ID = 449
                AND V449.IS_DEL = 0
    
                JOIN LINKS L
                ON L.LINK_ID = :V$LINK_ID

                WHERE V447.OBJ_ID = :V$OBJ_ID
                AND V447.PARAM_ID = 447
                AND V447.IS_DEL = 0
    
                INTO :V$LISTVAL_ID,
                     :V$YEAR_FROM,
                     :V$YEAR_TO,
                     :V$CONTAINER_PUPIL_OUT_ID
            DO
            BEGIN
                IF (V$LISTVAL_ID = 899) THEN
                BEGIN
                    V$LISTVAL_ID = 3321;
                END
                ELSE IF (V$LISTVAL_ID = 900) THEN
                BEGIN
                    V$LISTVAL_ID = 3320;
                END
                V$NEW_OBJ_ID = NULL;

                SELECT L82.OBJ_ID
                FROM LINKS L82

                JOIN VALL V447
                ON V447.OBJ_ID = L82.OBJ_ID
                AND V447.PARAM_ID = 447
                AND V447.IS_DEL = 0
                AND V447.LISTVAL_ID = :V$LISTVAL_ID

                JOIN VALI V448
                ON V448.OBJ_ID = L82.OBJ_ID
                AND V448.PARAM_ID = 448
                AND V448.IS_DEL = 0
                AND V448.VAL = :V$YEAR_FROM
        
                JOIN VALI V449
                ON V449.OBJ_ID = L82.OBJ_ID
                AND V449.PARAM_ID = 449
                AND V449.IS_DEL = 0
                AND V449.VAL = :V$YEAR_TO

                WHERE L82.PARENT_ID = :V$CONTAINER_PUPIL_OUT_ID
                AND L82.OBJ_TYPE_ID = 82
                AND L82.DATE_DEL IS NULL
                AND L82.LINK_ID <> :V$LINK_ID
                INTO :V$NEW_OBJ_ID;

                IF (V$NEW_OBJ_ID IS NULL) THEN
                BEGIN
                    SELECT OBJ_ID
                    FROM OBJECT_ADD(:V$CONTAINER_PUPIL_OUT_ID, 81)
                    INTO :V$NEW_OBJ_ID;
        
                    IF (V$NEW_OBJ_ID IS NOT NULL) THEN
                    BEGIN
                        SELECT BLOB_ID
                        FROM VAL_ADD(447, :V$NEW_OBJ_ID, :V$LISTVAL_ID)
                        INTO :V$BLOB_ID;
        
                        SELECT BLOB_ID
                        FROM VAL_ADD(448, :V$NEW_OBJ_ID, :V$YEAR_FROM)
                        INTO :V$BLOB_ID;
        
                        SELECT BLOB_ID
                        FROM VAL_ADD(449, :V$NEW_OBJ_ID, :V$YEAR_TO)
                        INTO :V$BLOB_ID;
                    END
                END
                UPDATE LINKS L10
                SET L10.PARENT_ID = :V$NEW_OBJ_ID
                WHERE L10.PARENT_ID = :V$OBJ_ID
                AND L10.OBJ_TYPE_ID = 10
                AND L10.DATE_DEL IS NULL
                AND NOT EXISTS(
                    SELECT FIRST 1 1
                    FROM LINKS L10_2
                    WHERE L10_2.PARENT_ID = :V$NEW_OBJ_ID
                    AND L10_2.OBJ_ID = L10.OBJ_ID
                    AND L10_2.DATE_DEL IS NULL
                );
                SELECT DEL_COUNT
                FROM OBJECT_DEL(:V$CONTAINER_PUPIL_OUT_ID, :V$OBJ_ID)
                INTO V$BLOB_ID;
            END
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIXER_EDUCATION_PROGRAM (
    SCHOOL_ID BIGINT = null)
AS
declare variable V$OBJ_ID bigint;
declare variable V$LISTVAL_ID bigint;
declare variable V$NEW_LISTVAL_ID bigint;
BEGIN
    IF (SCHOOL_ID IS NULL) THEN
    BEGIN
        SELECT FIRST 1 L.OBJ_ID
        FROM LINKS L
        WHERE L.PARENT_ID IS NULL
        AND L.OBJ_TYPE_ID = 2
        AND L.DATE_DEL IS NULL
        INTO :SCHOOL_ID;
    END

    FOR
        SELECT L57.OBJ_ID,
               V1594.LISTVAL_ID

        FROM LINKS L69

        JOIN LINKS L57
        ON L57.PARENT_ID = L69.OBJ_ID
        AND L57.OBJ_TYPE_ID = 57
        AND L57.DATE_DEL IS NULL

        JOIN VALL V1594
        ON V1594.OBJ_ID = L57.OBJ_ID
        AND V1594.PARAM_ID = 1594
        AND V1594.IS_DEL = 0

        WHERE L69.PARENT_ID = :SCHOOL_ID
        AND L69.OBJ_TYPE_ID = 69
        AND L69.DATE_DEL IS NULL

        INTO :V$OBJ_ID,
             :V$LISTVAL_ID
    DO
    BEGIN
        V$NEW_LISTVAL_ID = V$LISTVAL_ID;

        IF (V$LISTVAL_ID = 3329) THEN
        BEGIN
            V$NEW_LISTVAL_ID = 5338;
        END
        ELSE IF (V$LISTVAL_ID = 3330) THEN
        BEGIN
            V$NEW_LISTVAL_ID = 5340;
        END
        ELSE IF (V$LISTVAL_ID = 3331) THEN
        BEGIN
            V$NEW_LISTVAL_ID = 5342;
        END
        ELSE IF (V$LISTVAL_ID = 3332) THEN
        BEGIN
            V$NEW_LISTVAL_ID = 5344;
        END

        ELSE IF (V$LISTVAL_ID = 3334) THEN
        BEGIN
            V$NEW_LISTVAL_ID = 5347;
        END
        ELSE IF (V$LISTVAL_ID = 3335) THEN
        BEGIN
            V$NEW_LISTVAL_ID = 5349;
        END
        ELSE IF (V$LISTVAL_ID = 3336) THEN
        BEGIN
            V$NEW_LISTVAL_ID = 5351;
        END
        ELSE IF (V$LISTVAL_ID = 3337) THEN
        BEGIN
            V$NEW_LISTVAL_ID = 5354;
        END

        ELSE IF (V$LISTVAL_ID = 3339) THEN
        BEGIN
            V$NEW_LISTVAL_ID = 5366;
        END
        ELSE IF (V$LISTVAL_ID = 3340) THEN
        BEGIN
            V$NEW_LISTVAL_ID = 5367;
        END
        ELSE IF (V$LISTVAL_ID = 3341) THEN
        BEGIN
            V$NEW_LISTVAL_ID = 5368;
        END

        ELSE IF (V$LISTVAL_ID = 3343) THEN
        BEGIN
            V$NEW_LISTVAL_ID = 5359;
        END
        ELSE IF (V$LISTVAL_ID = 3344) THEN
        BEGIN
            V$NEW_LISTVAL_ID = 5360;
        END

        ELSE IF (V$LISTVAL_ID = 3346) THEN
        BEGIN
            V$NEW_LISTVAL_ID = 5362;
        END
        ELSE IF (V$LISTVAL_ID = 3347) THEN
        BEGIN
            V$NEW_LISTVAL_ID = 5363;
        END

        IF(V$NEW_LISTVAL_ID IS NOT NULL) THEN
        BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD(1832, :V$OBJ_ID, :V$NEW_LISTVAL_ID, 1)
            INTO :V$LISTVAL_ID;
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIXER_ENTRANCE_AS_GIA
AS
BEGIN
    UPDATE VALL
    SET IS_DEL = 1,LISTVAL_ID = 3
    WHERE PARAM_ID = 1362
    AND IS_DEL = 0
    AND OBJ_ID IN (
        SELECT V1362.OBJ_ID

        FROM VALL V1362

        JOIN LINKS LP8
        ON LP8.OBJ_ID = V1362.OBJ_ID
        AND LP8.PARENT_TYPE_ID = 8
        AND LP8.DATE_DEL IS NULL

        JOIN VALL VL
        ON VL.OBJ_ID = LP8.PARENT_ID
        AND VL.PARAM_ID = 49
        AND VL.IS_DEL = 0
        AND VL.LISTVAL_ID IN (37,38,39,40,41,42,43,44,45,46)

        WHERE V1362.PARAM_ID = 1362
        AND V1362.LISTVAL_ID = 2
        AND V1362.IS_DEL = 0
    );
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIXER_ENT_DATES
AS
declare variable V$STUDENT_ID bigint;
declare variable V$CLASS_ID bigint;
declare variable V$MOVE_ID bigint;
begin

  FOR
    SELECT L10.OBJ_ID, L9.OBJ_ID
    FROM LINKS L2
    JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
    JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :V$STUDENT_ID, :V$CLASS_ID
  DO
  BEGIN
    V$MOVE_ID = NULL;
    SELECT FIRST 1 M.OBJ_ID
    FROM PERSON_MOVEMENTS M
    WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :V$STUDENT_ID AND M.GROUP_ID = :V$CLASS_ID AND M.DATE_IN = '31.08.2021'
    INTO :V$MOVE_ID;

    IF(V$MOVE_ID IS NULL) THEN LEAVE;

    IF(NOT EXISTS(
      SELECT FIRST 1 1
      FROM PERSON_MOVEMENTS M
      JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
      WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :V$STUDENT_ID AND M.OBJ_ID < :V$MOVE_ID
    )) THEN
    BEGIN
      UPDATE PERSON_MOVEMENTS
      SET DATE_IN = '01.09.2021'
      WHERE OBJ_ID = :V$MOVE_ID;
    END
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIXER_EXTERNAT_ACCEPT_TYPE
AS
declare variable ID bigint;
begin

  FOR
    SELECT M.OBJ_ID
    FROM PERSON_MOVEMENTS M
    JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 187
    WHERE M.REASON_IN <> 12905
    INTO :ID
  DO
  BEGIN
    UPDATE PERSON_MOVEMENTS SET REASON_IN = 12905 WHERE OBJ_ID = :ID;
  END

  FOR
    SELECT M.OBJ_ID
    FROM PERSON_MOVEMENTS M
    JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 187
    WHERE M.REASON_OUT <> 12906
    INTO :ID
  DO
  BEGIN
    UPDATE PERSON_MOVEMENTS SET REASON_OUT = 12906 WHERE OBJ_ID = :ID;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIXER_EXTERNAT_LEAVED
AS
declare variable V$MOVE_ID bigint;
declare variable V$PERSON_ID bigint;
declare variable V$GROUP_ID bigint;
declare variable V$DATE date;
begin

  FOR
    SELECT M.OBJ_ID, M.PERSON_ID, M.GROUP_ID
    FROM PERSON_MOVEMENTS M
    JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 187
    LEFT JOIN LINKS L ON L.OBJ_ID = M.PERSON_ID AND L.PARENT_ID = G.OBJ_ID AND L.DATE_DEL IS NULL
    WHERE M.DATE_DEL IS NULL AND M.DATE_OUT IS NULL AND L.LINK_ID IS NULL
    INTO :V$MOVE_ID, :V$PERSON_ID, :V$GROUP_ID
  DO
  BEGIN
    V$DATE = NULL;
    SELECT FIRST 1 L.DATE_DEL
    FROM LINKS L
    WHERE L.OBJ_ID = :V$PERSON_ID AND L.PARENT_ID = :V$GROUP_ID AND L.DATE_DEL IS NOT NULL
    ORDER BY 1 DESC
    INTO :V$DATE;

    UPDATE PERSON_MOVEMENTS
    SET DATE_OUT = :V$DATE, REASON_OUT = 12906
    WHERE OBJ_ID = :V$MOVE_ID;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIXER_FINALS_EF
AS
declare variable V$YEAR_ID bigint;
declare variable V$MARK_ID bigint;
declare variable V$PUPIL_ID bigint;
declare variable V$SUBJECT_ID bigint;
declare variable V$MARKTYPE_ID bigint;
declare variable V$TEACHER_ID bigint;
declare variable V$GRADE_ID bigint;
declare variable V$MARK_DATE date;
declare variable V$R_TEACHER_ID bigint;
declare variable V$R_DATE date;
declare variable V$R_GRADE_ID bigint;
declare variable V$R_STAGE_ID bigint;
begin

  SELECT FIRST 1 V1236.LISTVAL_ID
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$YEAR_ID;

  -- Было 10981 - первый раз должно было уже отработать, теперь правим 2022-23 год
  IF(V$YEAR_ID <> 10982) THEN EXIT;

  FOR
    SELECT M.MARK_ID, M.PUPIL_ID, M.SUBJECT_ID, M.MARKTYPE_ID, M.TEACHER_ID, M.GRADE_ID, M.MARK_DATE
    FROM VALM M
    WHERE M.YEAR_ID = :V$YEAR_ID AND M.STAGE_ID IS NULL AND (M.IS_NATIVE = 1 OR M.IS_NATIVE IS NULL) AND M.IS_DEL = 0
    INTO :V$MARK_ID, :V$PUPIL_ID, :V$SUBJECT_ID, :V$MARKTYPE_ID, :V$TEACHER_ID, :V$GRADE_ID, :V$MARK_DATE
  DO
  BEGIN

    -- Получаем дату итоговой отметки
    V$R_TEACHER_ID = NULL;
    V$R_DATE = NULL;
    SELECT FIRST 1 COALESCE(F.TEACHER_ID, J.TEACHER_ID), F.FINAL_DATE
    FROM CJ2_MARK MM
    JOIN CJ2_JOURNAL_FINALS F ON F.OBJ_ID = MM.FINAL_ID AND F.FINAL_TYPE = :V$MARKTYPE_ID
    JOIN CJ2_JOURNAL J ON J.OBJ_ID = F.CJ_ID AND J.SUBJECT_ID = :V$SUBJECT_ID
    WHERE MM.DATE_DEL IS NULL AND MM.STUDENT_ID = :V$PUPIL_ID
    INTO :V$R_TEACHER_ID, :V$R_DATE;

    -- В каком классе и этапе был ?
    SELECT FIRST 1 LPG.OBJ_ID, V49.LISTVAL_ID
    FROM PERSON_MOVEMENTS PM
    JOIN LINKS LPG ON LPG.OBJ_ID = PM.GROUP_ID AND LPG.OBJ_TYPE_ID IN (9, 187) AND LPG.PARENT_TYPE_ID = 8 AND LPG.DATE_DEL IS NULL
    JOIN VALL V49 ON V49.OBJ_ID = LPG.PARENT_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
    WHERE PM.DATE_DEL IS NULL AND PM.PERSON_ID = :V$PUPIL_ID AND PM.DATE_IN <= :V$R_DATE AND (PM.DATE_OUT IS NULL OR PM.DATE_OUT >= :V$R_DATE)
    INTO :V$R_GRADE_ID, :V$R_STAGE_ID;

    IF(V$R_GRADE_ID IS NOT NULL) THEN UPDATE VALM SET GRADE_ID = :V$R_GRADE_ID WHERE MARK_ID = :V$MARK_ID;
    IF(V$R_STAGE_ID IS NOT NULL) THEN UPDATE VALM SET STAGE_ID = :V$R_STAGE_ID WHERE MARK_ID = :V$MARK_ID;
    IF(V$R_TEACHER_ID IS NOT NULL) THEN UPDATE VALM SET TEACHER_ID = :V$R_TEACHER_ID WHERE MARK_ID = :V$MARK_ID;
    IF(V$R_DATE IS NOT NULL) THEN UPDATE VALM SET MARK_DATE = :V$R_DATE WHERE MARK_ID = :V$MARK_ID;

  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIXER_FIX_COLLEGE_CIR_DIST
AS
declare variable V$OBJ_ID bigint;
declare variable V$BLOB_ID bigint;
BEGIN
    FOR
        SELECT O57.OBJ_ID
        FROM OBJECTS O57
        LEFT JOIN VALL V2722 ON V2722.OBJ_ID = O57.OBJ_ID AND V2722.PARAM_ID = 2722 AND V2722.IS_DEL = 0
        WHERE O57.TYPE_ID = 57 AND V2722.LISTVAL_ID IS NULL
        INTO :V$OBJ_ID
    DO
    BEGIN
        SELECT BLOB_ID
        FROM VAL_ADD(2722, :V$OBJ_ID, 3)
        INTO :V$BLOB_ID;
    END

    FOR
        SELECT O244.OBJ_ID
        FROM OBJECTS O244
        LEFT JOIN VALL V2725 ON V2725.OBJ_ID = O244.OBJ_ID AND V2725.PARAM_ID = 2725 AND V2725.IS_DEL = 0
        WHERE O244.TYPE_ID = 244 AND V2725.LISTVAL_ID IS NULL
        INTO :V$OBJ_ID
    DO
    BEGIN
        SELECT BLOB_ID
        FROM VAL_ADD(2725, :V$OBJ_ID, 3)
        INTO :V$BLOB_ID;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIXER_FIX_PUPIL_STUDY_FORM
AS
declare variable V$PUPIL_ID bigint;
declare variable V$CAPTION varchar(1000);
declare variable V$LISTVAL_ID bigint;
declare variable V$BLOB_ID bigint;
BEGIN
    FOR
        SELECT DISTINCT
               L10.OBJ_ID,
               C.VAL

        FROM LINKS L10

        LEFT JOIN VALL V80
        ON V80.OBJ_ID = L10.OBJ_ID
        AND V80.IS_DEL = 0
        AND V80.PARAM_ID = 80

        LEFT JOIN LISTVALS LV80
        ON LV80.LISTVAL_ID = V80.LISTVAL_ID

        LEFT JOIN RES_GET(LV80.RES_ID, 'RU') C ON 1=1

        WHERE L10.DATE_DEL IS NULL
        AND L10.OBJ_TYPE_ID = 10
        AND ((V80.LISTVAL_ID IS NULL) OR (LV80.LIST_ID <> 259))

        INTO :V$PUPIL_ID,
             :V$CAPTION
    DO
    BEGIN
        V$LISTVAL_ID = 5418;
        IF (V$CAPTION <> '') THEN
        BEGIN
            SELECT LV259.LISTVAL_ID

            FROM LISTVALS LV259

            LEFT JOIN RES_GET(LV259.RES_ID, 'RU') C ON 1=1

            WHERE LV259.LIST_ID = 259
            AND LV259.IS_DEL = 0
            AND C.VAL = :V$CAPTION

            INTO :V$LISTVAL_ID;
        END

        SELECT BLOB_ID
        FROM VAL_ADD(80, :V$PUPIL_ID, :V$LISTVAL_ID)
        INTO :V$BLOB_ID;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIXER_FIX_REGION_GIA
AS
BEGIN

  -- Процедура более неактуальна

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIXER_FIX_UDOD_CIR_DIST
AS
declare variable V$OBJ_ID bigint;
declare variable V$BLOB_ID bigint;
BEGIN
    FOR
        SELECT O252.OBJ_ID
        FROM OBJECTS O252

        LEFT JOIN VALL V2744
        ON V2744.OBJ_ID = O252.OBJ_ID
        AND V2744.PARAM_ID = 2744
        AND V2744.IS_DEL = 0

        WHERE O252.TYPE_ID = 252
        AND V2744.LISTVAL_ID IS NULL

        INTO :V$OBJ_ID
    DO
    BEGIN
        SELECT BLOB_ID
        FROM VAL_ADD(2744, :V$OBJ_ID, 3)
        INTO :V$BLOB_ID;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIXER_FPU_TMP
AS
declare variable V$BOOK_ID bigint;
declare variable V$NAME varchar(1000);
declare variable V$AUTHORS varchar(1000);
declare variable V$ASSN varchar(100);
declare variable V$GRADE_FROM integer;
declare variable V$GRADE_TO integer;
declare variable V$C varchar(100);
declare variable V$N integer;
declare variable V$MISS integer;
begin

  -- Неактуально

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIXER_GHOST_STUDENTS
AS
declare variable V$OBJ_ID bigint;
begin

  FOR
    SELECT O10.OBJ_ID
    FROM OBJECTS O10
    LEFT JOIN LINKS LP ON LP.OBJ_ID = O10.OBJ_ID AND LP.PARENT_TYPE_ID IN (9, 187, 81, 82, 83) AND LP.DATE_DEL IS NULL
    WHERE O10.TYPE_ID = 10 AND LP.LINK_ID IS NULL
    INTO :V$OBJ_ID
  DO
  BEGIN
    EXECUTE PROCEDURE DROP_STUDENT_MOVEMENTS(:V$OBJ_ID);
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIXER_GIA_ALIASES
AS
declare variable V varchar(100);
declare variable V$OBJ_ID bigint;
declare variable V$TYPE_ID bigint;
begin

  UPDATE VALS V SET V.IS_DEL = 1 WHERE V.PARAM_ID IN (1363, 821, 1653);

  FOR
    SELECT L9.OBJ_ID, L9.OBJ_TYPE_ID
    FROM LINKS L9
    JOIN VALL V2388 ON V2388.OBJ_ID = L9.OBJ_ID AND V2388.PARAM_ID IN (2388, 2419, 2418) AND V2388.IS_DEL = 0 AND V2388.LISTVAL_ID <> 11217
    WHERE L9.PARENT_TYPE_ID IN (8, 124) AND L9.OBJ_TYPE_ID IN (9, 125, 187) AND L9.DATE_DEL IS NULL
    ORDER BY 2
    INTO :V$OBJ_ID, :V$TYPE_ID
  DO
  BEGIN
    SELECT SINONIM FROM GIA_CLASS_SINONIM_GET(:V$OBJ_ID) INTO :V;

    UPDATE OR INSERT INTO VALS (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
    VALUES (CASE WHEN :V$TYPE_ID = 9 THEN 1363 WHEN :V$TYPE_ID = 187 THEN 1653 WHEN :V$TYPE_ID = 125 THEN 821 END, :V$OBJ_ID, 1, 0, :V);
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIXER_GIA_CLASS_TYPE (
    I$SCHOOL_ID BIGINT)
AS
declare variable V$CLASS_ID bigint;
declare variable V$TYPE_ID bigint;
declare variable V$PARALLEL_ID bigint;
declare variable V$GRADUATE_ID bigint;
declare variable V$GIA_TYPE_ID bigint;
declare variable V$BLOB_ID bigint;
BEGIN
    FOR
        SELECT L9.OBJ_ID,
               L9.OBJ_TYPE_ID,
               V49.LISTVAL_ID,
               V1362.LISTVAL_ID
        FROM LINKS L7

        JOIN LINKS L8
        ON L8.PARENT_ID = L7.OBJ_ID
        AND L8.DATE_DEL IS NULL
        AND L8.OBJ_TYPE_ID = 8

        JOIN VALL V49
        ON V49.OBJ_ID = L8.OBJ_ID
        AND V49.PARAM_ID = 49
        AND V49.IS_DEL = 0

        JOIN LINKS L9
        ON L9.PARENT_ID = L8.OBJ_ID
        AND L9.DATE_DEL IS NULL
        AND L9.OBJ_TYPE_ID IN (9,187)

        LEFT JOIN VALL V1362
        ON V1362.OBJ_ID = L9.OBJ_ID
        AND V1362.PARAM_ID IN (1362,1747)
        AND V1362.IS_DEL = 0

        LEFT JOIN VALL V2388
        ON V2388.OBJ_ID = L9.OBJ_ID
        AND V2388.PARAM_ID IN (2388,2418)
        AND V2388.IS_DEL = 0

        WHERE L7.PARENT_ID = :I$SCHOOL_ID
        AND L7.OBJ_TYPE_ID = 7
        AND L7.DATE_DEL IS NULL
        AND V2388.LISTVAL_ID IS NULL

        INTO :V$CLASS_ID,
             :V$TYPE_ID,
             :V$PARALLEL_ID,
             :V$GRADUATE_ID
    DO
    BEGIN
        IF (V$PARALLEL_ID = 45) THEN
        BEGIN
            V$GIA_TYPE_ID = 11202;
        END
        ELSE IF (V$PARALLEL_ID IN (47,48)) THEN
        BEGIN
            IF (V$GRADUATE_ID = 2) THEN
            BEGIN
                V$GIA_TYPE_ID = 11203;
            END
            ELSE
            BEGIN
                V$GIA_TYPE_ID = 11217;
            END
        END
        ELSE IF (V$PARALLEL_ID IN (49,50,51,52,53,54)) THEN
        BEGIN
            IF (V$GRADUATE_ID = 2) THEN
            BEGIN
                V$GIA_TYPE_ID = 11203;
            END
            ELSE
            BEGIN
                V$GIA_TYPE_ID = 11217;
            END
        END
        ELSE
        BEGIN
            V$GIA_TYPE_ID = 11217;
        END

        SELECT BLOB_ID
        FROM VAL_ADD(IIF(:V$TYPE_ID = 9,2388,2418), :V$CLASS_ID, :V$GIA_TYPE_ID)
        INTO :V$BLOB_ID;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIXER_GIA_CLASS_TYPE2 (
    I$SCHOOL_ID BIGINT)
AS
declare variable V$CLASS_ID bigint;
declare variable V$PARALLEL_ID bigint;
declare variable V$GIA_TYPE_ID bigint;
declare variable V$BLOB_ID bigint;
BEGIN
    FOR
        SELECT L125.OBJ_ID,
               V49.LISTVAL_ID
        FROM LINKS L7

        JOIN LINKS L8
        ON L8.PARENT_ID = L7.OBJ_ID
        AND L8.DATE_DEL IS NULL
        AND L8.OBJ_TYPE_ID = 8

        JOIN VALL V49
        ON V49.OBJ_ID = L8.OBJ_ID
        AND V49.PARAM_ID = 49
        AND V49.IS_DEL = 0

        JOIN LINKS L125
        ON L125.PARENT_ID = L8.OBJ_ID
        AND L125.DATE_DEL IS NULL
        AND L125.OBJ_TYPE_ID = 125

        LEFT JOIN VALL V2419
        ON V2419.OBJ_ID = L125.OBJ_ID
        AND V2419.PARAM_ID = 2419
        AND V2419.IS_DEL = 0

        WHERE L7.PARENT_ID = :I$SCHOOL_ID
        AND L7.OBJ_TYPE_ID = 7
        AND L7.DATE_DEL IS NULL
        AND V2419.LISTVAL_ID IS NULL

        INTO :V$CLASS_ID,
             :V$PARALLEL_ID
    DO
    BEGIN
        IF (V$PARALLEL_ID = 45) THEN
        BEGIN
            V$GIA_TYPE_ID = 11202;
        END
        ELSE IF (V$PARALLEL_ID IN (47,48)) THEN
        BEGIN
            V$GIA_TYPE_ID = 11203;
        END
        ELSE
        BEGIN
            V$GIA_TYPE_ID = 11217;
        END

        SELECT BLOB_ID
        FROM VAL_ADD(2419, :V$CLASS_ID, :V$GIA_TYPE_ID)
        INTO :V$BLOB_ID;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIXER_GIA_CLASS_TYPE3
AS
declare variable V$CLASS_ID bigint;
declare variable V$BLOB_ID bigint;
BEGIN
    FOR
        SELECT L125.OBJ_ID
        FROM LINKS L124

        JOIN LINKS L125
        ON L125.PARENT_ID = L124.OBJ_ID
        AND L125.DATE_DEL IS NULL
        AND L125.OBJ_TYPE_ID = 125

        LEFT JOIN VALL V2419
        ON V2419.OBJ_ID = L125.OBJ_ID
        AND V2419.PARAM_ID = 2419
        AND V2419.IS_DEL = 0

        WHERE L124.PARENT_ID IS NULL
        AND L124.OBJ_TYPE_ID = 124
        AND L124.DATE_DEL IS NULL
        AND V2419.LISTVAL_ID IS NULL

        INTO :V$CLASS_ID
    DO
    BEGIN
        SELECT BLOB_ID
        FROM VAL_ADD(2419, :V$CLASS_ID, 11203)
        INTO :V$BLOB_ID;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIXER_GIA_INFORMATIKA_PARAMS (
    I$SCHOOL_ID BIGINT)
AS
declare variable V$CLASS_ID bigint;
declare variable V$TYPE_ID bigint;
declare variable V$BLOB_ID bigint;
BEGIN
    FOR
        SELECT L9.OBJ_ID,
               L9.OBJ_TYPE_ID
        FROM LINKS L7

        JOIN LINKS L8
        ON L8.PARENT_ID = L7.OBJ_ID
        AND L8.OBJ_TYPE_ID = 8
        AND L8.DATE_DEL IS NULL

        JOIN LINKS L9
        ON L9.PARENT_ID = L8.OBJ_ID
        AND L9.OBJ_TYPE_ID IN (9, 125)
        AND L9.DATE_DEL IS NULL

        WHERE L7.PARENT_ID = :I$SCHOOL_ID
        AND L7.OBJ_TYPE_ID = 7
        AND L7.DATE_DEL IS NULL

        INTO :V$CLASS_ID,
             :V$TYPE_ID
    DO
    BEGIN
        IF (V$TYPE_ID = 9) THEN
        BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD(1614, :V$CLASS_ID, 3355)
            INTO :V$BLOB_ID;
    
            SELECT BLOB_ID
            FROM VAL_ADD(1615, :V$CLASS_ID, 3367)
            INTO :V$BLOB_ID;
    
            SELECT BLOB_ID
            FROM VAL_ADD(1617, :V$CLASS_ID, 3377)
            INTO :V$BLOB_ID;
        END
        ELSE IF (V$TYPE_ID = 125) THEN
        BEGIN
            SELECT BLOB_ID  
            FROM VAL_ADD(1634, :V$CLASS_ID, 3355)
            INTO :V$BLOB_ID;
    
            SELECT BLOB_ID
            FROM VAL_ADD(1635, :V$CLASS_ID, 3367)
            INTO :V$BLOB_ID;
    
            SELECT BLOB_ID
            FROM VAL_ADD(1637, :V$CLASS_ID, 3377)
            INTO :V$BLOB_ID;
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIXER_GPDJ_PTP
AS
declare variable V$CJ_ID bigint;
declare variable V$ASSN_ID bigint;
begin

  -- Переводим в утвержденный статус все ПТП не-общеобр и не-ВД
  FOR
    SELECT P.OBJ_ID, P.CJ_ID
    FROM CJ2_JOURNAL_PTP P
    JOIN CJ2_JOURNAL J ON J.OBJ_ID = P.CJ_ID AND J.JOURNAL_TYPE NOT IN (0, 1)
    WHERE P.DATE_DEL IS NULL AND P.APPROVAL_STATE = 1
    ORDER BY 1
    INTO :V$ASSN_ID, :V$CJ_ID
  DO
  BEGIN
    UPDATE CJ2_JOURNAL_PTP SET APPROVAL_STATE = 3 WHERE DATE_DEL IS NULL AND CJ_ID = :V$CJ_ID AND APPROVAL_STATE = 2;
    UPDATE CJ2_JOURNAL_PTP SET APPROVAL_STATE = 2 WHERE OBJ_ID = :V$ASSN_ID;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIXER_GRADUATE_CLASS (
    SCHOOL_ID BIGINT = null)
AS
declare variable V$OU_LICENCE_TYPE varchar(1);
declare variable V$OBJ_ID bigint;
BEGIN
    SELECT STATUS FROM OU_LICENCE_TYPE INTO :V$OU_LICENCE_TYPE;
    IF (SCHOOL_ID IS NULL) THEN
    BEGIN
        SELECT FIRST 1 L.OBJ_ID
        FROM LINKS L
        WHERE L.PARENT_ID IS NULL AND L.OBJ_TYPE_ID = 2 AND L.DATE_DEL IS NULL
        INTO :SCHOOL_ID;
    END
    IF (V$OU_LICENCE_TYPE IN ('O', 'C')) THEN
    BEGIN
        /*
        FOR
            SELECT L9.OBJ_ID
            FROM LINKS L7
            JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
            JOIN VALL VL ON VL.OBJ_ID = L8.OBJ_ID AND VL.PARAM_ID = 49 AND VL.IS_DEL = 0 AND VL.LISTVAL_ID IN (37,38,39,40,41,42,43,44,45,46)
            JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
            JOIN VALL V1362 ON V1362.OBJ_ID = L9.OBJ_ID AND V1362.PARAM_ID = 1362 AND V1362.IS_DEL = 0 AND V1362.LISTVAL_ID = 2
            WHERE L7.PARENT_ID = :SCHOOL_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
            INTO :V$OBJ_ID
        DO
        BEGIN
            UPDATE VALL
            SET LISTVAL_ID = 3
            WHERE OBJ_ID = :V$OBJ_ID AND PARAM_ID = 1362 AND IS_DEL = 0;
        END
        */

        FOR
            SELECT L187.OBJ_ID
            FROM LINKS L7
            JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
            JOIN VALL VL ON VL.OBJ_ID = L8.OBJ_ID AND VL.PARAM_ID = 49 AND VL.IS_DEL = 0 AND VL.LISTVAL_ID IN (37,38,39,40,41,42,43,44,45,46)
            JOIN LINKS L187 ON L187.PARENT_ID = L8.OBJ_ID AND L187.OBJ_TYPE_ID = 187 AND L187.DATE_DEL IS NULL
            JOIN VALL V1747 ON V1747.OBJ_ID = L187.OBJ_ID AND V1747.PARAM_ID = 1747 AND V1747.IS_DEL = 0 AND V1747.LISTVAL_ID = 2
            WHERE L7.PARENT_ID = :SCHOOL_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
            INTO :V$OBJ_ID
        DO
        BEGIN
            UPDATE VALL
            SET LISTVAL_ID = 3
            WHERE OBJ_ID = :V$OBJ_ID AND PARAM_ID = 1747 AND IS_DEL = 0;
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIXER_GUP_MASKS
AS
declare variable V$OBJ_ID bigint;
declare variable V$LEVEL integer;
begin

  FOR
    SELECT L256.OBJ_ID, LV.COST
    FROM LINKS L256
    JOIN VALL V381 ON V381.OBJ_ID = L256.PARENT_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V381.LISTVAL_ID
    LEFT JOIN VALI V3062 ON V3062.OBJ_ID = L256.OBJ_ID AND V3062.PARAM_ID = 3062 AND V3062.IS_DEL = 0
    WHERE L256.PARENT_TYPE_ID = 54 AND L256.OBJ_TYPE_ID = 256 AND V3062.VAL = 0
    INTO :V$OBJ_ID, :V$LEVEL
  DO
  BEGIN
    V$LEVEL = BIN_SHL(1, V$LEVEL);
    SELECT BLOB_ID FROM VAL_ADD(3062, :V$OBJ_ID, :V$LEVEL) INTO :V$OBJ_ID;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIXER_HOMEBASED_EDU_ATTR
AS
declare variable V$OBJ_ID bigint;
declare variable V$BLOB_ID bigint;
BEGIN
    FOR
        SELECT L10.OBJ_ID
        
        FROM LINKS L10
        
        LEFT JOIN VALL V2169
        ON V2169.OBJ_ID = L10.OBJ_ID
        AND V2169.PARAM_ID = 2169
        AND V2169.IS_DEL = 0
        
        WHERE L10.OBJ_TYPE_ID = 10
        AND L10.DATE_DEL IS NULL
        AND V2169.LISTVAL_ID IS NULL
        INTO :V$OBJ_ID

    DO
    BEGIN
        SELECT BLOB_ID
        FROM VAL_ADD(2169, :V$OBJ_ID, 3)
        INTO :V$BLOB_ID;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIXER_JOURNAL_GRANTS
AS
declare variable CJ_ID bigint;
begin

  FOR
    SELECT OBJ_ID
    FROM CJ2_JOURNAL
    WHERE DATE_DEL IS NULL
    INTO :CJ_ID
  DO
  BEGIN
    EXECUTE PROCEDURE CJ2_JOURNAL_ACCESS_UPD(:CJ_ID, NULL);
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIXER_JOURNAL_JOURS
AS
declare variable V$OBJ_ID bigint;
declare variable H float;
begin

  FOR
    SELECT J.OBJ_ID, SUM(PL.LOAD_HOURS_S1)
    FROM CJ2_JOURNAL J
    JOIN LINKS L54 ON L54.PARENT_ID = J.REF_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
    JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0 AND V381.LISTVAL_ID = J.STAGE_INDEX
    JOIN PLAN_SUBJECTS PS ON PS.DATE_DEL IS NULL AND PS.PLAN_ID = J.REF_ID AND PS.SUBJECT_ID = J.SUBJECT_ID
    JOIN PLAN_LOADS PL ON PL.DATE_DEL IS NULL AND PL.STAGE_ID = L54.OBJ_ID AND PL.SUBJECT_ID = PS.OBJ_ID
    WHERE J.DATE_DEL IS NULL AND J.REF_ID IS NOT NULL AND (J.HOURS = 0 OR J.HOURS IS NULL)
    GROUP BY 1
    INTO :V$OBJ_ID, :H
  DO
  BEGIN
    UPDATE CJ2_JOURNAL SET HOURS = :H WHERE OBJ_ID = :V$OBJ_ID;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIXER_JOURNAL_PTP_LINKS
AS
declare variable V$PTP_ID bigint;
declare variable V$PARENT_ID bigint;
declare variable V$OBJ_ID bigint;
declare variable V$CJ_ID bigint;
declare variable V$ST smallint;
begin

  -- Удаляем все связи с журналами, которых не было в предыдущей инкарнации
  -- Идем по всем ПТП, которые являются коррекциями других
  FOR
    SELECT DISTINCT P.OBJ_ID, P.PARENT_ID
    FROM PTP P
    JOIN CJ2_JOURNAL_PTP J ON J.DATE_DEL IS NULL AND J.PTP_ID = P.OBJ_ID
    WHERE P.DATE_DEL IS NULL AND P.PARENT_ID IS NOT NULL
    INTO :V$PTP_ID, :V$PARENT_ID
  DO
  BEGIN
    FOR
      SELECT PJ.OBJ_ID, PJ.CJ_ID, PJ.APPROVAL_STATE
      FROM CJ2_JOURNAL_PTP PJ
      LEFT JOIN CJ2_JOURNAL_PTP PJ2 ON PJ2.DATE_DEL IS NULL AND PJ2.PTP_ID = :V$PARENT_ID AND PJ2.CJ_ID = PJ.CJ_ID
      WHERE PJ.DATE_DEL IS NULL AND PJ.PTP_ID = :V$PTP_ID AND PJ.APPROVAL_STATE IN (1, 2, 3) AND PJ2.OBJ_ID IS NULL
      INTO :V$OBJ_ID, :V$CJ_ID, :V$ST
    DO
    BEGIN
      -- Прибиваем некорректную связь с кривым журналом
      UPDATE CJ2_JOURNAL_PTP
      SET DATE_DEL = CURRENT_TIMESTAMP
      WHERE OBJ_ID = :V$OBJ_ID;

      -- Восстанавливаем предыдущую связь журнала с ПТП, если новая неправильная ее закрывала
      -- дополнительная сверка, что данный ПТП или корневой, или коллеквив был связан с предыдущей версией ПТП
      IF(V$ST = 2 AND NOT EXISTS(
        SELECT FIRST 1 1
        FROM CJ2_JOURNAL_PTP PJ
        WHERE PJ.DATE_DEL IS NULL AND PJ.CJ_ID = :V$CJ_ID AND PJ.APPROVAL_STATE = 2
      )) THEN
      BEGIN
        V$OBJ_ID = NULL;
        SELECT FIRST 1 PJ.OBJ_ID
        FROM CJ2_JOURNAL_PTP PJ
        JOIN PTP P ON P.OBJ_ID = PJ.PTP_ID
        WHERE PJ.DATE_DEL IS NULL AND PJ.CJ_ID = :V$CJ_ID AND PJ.APPROVAL_STATE = 3 AND
          (P.PARENT_ID IS NULL OR EXISTS(
            SELECT FIRST 1 1
            FROM CJ2_JOURNAL_PTP PJ2
            WHERE PJ2.DATE_DEL IS NULL AND PJ2.CJ_ID = PJ.CJ_ID AND PJ2.PTP_ID = P.PARENT_ID
          ))
        ORDER BY PJ.DATE_ADD DESC
        INTO :V$OBJ_ID;

        UPDATE CJ2_JOURNAL_PTP
        SET APPROVAL_STATE = 2
        WHERE OBJ_ID = :V$OBJ_ID;
      END
    END
  END

    -- Удаляем возможные дубликаты журналов
  FOR
    SELECT P.OBJ_ID, J.CJ_ID, COUNT(*)
    FROM PTP P
    JOIN CJ2_JOURNAL_PTP J ON J.DATE_DEL IS NULL AND J.PTP_ID = P.OBJ_ID
    WHERE P.DATE_DEL IS NULL AND P.PARENT_ID IS NOT NULL
    GROUP BY 1, 2
    HAVING COUNT(*) > 1
    INTO :V$PTP_ID, :V$CJ_ID, :V$PARENT_ID
  DO
  BEGIN
    FOR
      SELECT SKIP 1 J.OBJ_ID
      FROM PTP P
      JOIN CJ2_JOURNAL_PTP J ON J.DATE_DEL IS NULL AND J.PTP_ID = P.OBJ_ID AND J.CJ_ID = :V$CJ_ID
      WHERE P.OBJ_ID = :V$PTP_ID
      ORDER BY J.APPROVAL_STATE DESC, J.DATE_ADD
      INTO :V$OBJ_ID
    DO
    BEGIN
      UPDATE CJ2_JOURNAL_PTP
      SET DATE_DEL = CURRENT_TIMESTAMP
      WHERE OBJ_ID = :V$OBJ_ID;
    END
  END

  -- Восстанавливаем отмененный статус в журналах, в которых только отмененные и остались
  FOR
    SELECT J.OBJ_ID
    FROM CJ2_JOURNAL_PTP J
    LEFT JOIN CJ2_JOURNAL_PTP J2 ON J2.DATE_DEL IS NULL AND J2.CJ_ID = J.CJ_ID AND J2.APPROVAL_STATE < 3
    LEFT JOIN PTP P2 ON P2.PARENT_ID = J.PTP_ID AND P2.DATE_DEL IS NULL
    WHERE J.DATE_DEL IS NULL AND J.APPROVAL_STATE = 3 AND J2.OBJ_ID IS NULL AND P2.OBJ_ID IS NULL
    INTO :V$OBJ_ID
  DO
  BEGIN
    UPDATE CJ2_JOURNAL_PTP
    SET APPROVAL_STATE = 2
    WHERE OBJ_ID = :V$OBJ_ID;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIXER_KEY (
    KEY_OLD BIGINT,
    KEY_NEW BIGINT)
AS
declare variable INCREMENT bigint;
BEGIN
    INCREMENT = (KEY_NEW - KEY_OLD) * 1000000000;

    INSERT INTO OBJECTS (OBJ_ID, TYPE_ID, DATE_MODIFY)
    SELECT OBJ_ID + :INCREMENT, TYPE_ID, DATE_MODIFY
    FROM OBJECTS
    WHERE OBJ_ID >= :KEY_OLD * 1000000000
      AND OBJ_ID <  :KEY_NEW * 1000000000;

    /* LINKS */
    UPDATE LINKS
    SET PARENT_ID = PARENT_ID + :INCREMENT
    WHERE PARENT_ID >= :KEY_OLD * 1000000000
      AND PARENT_ID <  :KEY_NEW * 1000000000;

    UPDATE LINKS
    SET OBJ_ID = OBJ_ID + :INCREMENT
    WHERE OBJ_ID >= :KEY_OLD * 1000000000
      AND OBJ_ID <  :KEY_NEW * 1000000000;

    UPDATE LINKS
    SET REASON_ID = REASON_ID + :INCREMENT
    WHERE REASON_ID >= :KEY_OLD * 1000000000
      AND REASON_ID <  :KEY_NEW * 1000000000;

    UPDATE LINKS
    SET LINK_ID = LINK_ID + :INCREMENT
    WHERE LINK_ID >= :KEY_OLD * 1000000000
      AND LINK_ID <  :KEY_NEW * 1000000000;

    /* VAL */
    UPDATE VALA
    SET OBJ_ID = OBJ_ID + :INCREMENT
    WHERE OBJ_ID >= :KEY_OLD * 1000000000
      AND OBJ_ID <  :KEY_NEW * 1000000000;

    UPDATE VALB
    SET OBJ_ID = OBJ_ID + :INCREMENT
    WHERE OBJ_ID >= :KEY_OLD * 1000000000
      AND OBJ_ID <  :KEY_NEW * 1000000000;

    UPDATE VALB
    SET BLOB_ID = BLOB_ID + :INCREMENT;

    UPDATE VALD
    SET OBJ_ID = OBJ_ID + :INCREMENT
    WHERE OBJ_ID >= :KEY_OLD * 1000000000
      AND OBJ_ID <  :KEY_NEW * 1000000000;

    UPDATE VALDT
    SET OBJ_ID = OBJ_ID + :INCREMENT
    WHERE OBJ_ID >= :KEY_OLD * 1000000000
      AND OBJ_ID <  :KEY_NEW * 1000000000;

    UPDATE VALF
    SET OBJ_ID = OBJ_ID + :INCREMENT
    WHERE OBJ_ID >= :KEY_OLD * 1000000000
      AND OBJ_ID <  :KEY_NEW * 1000000000;

    UPDATE VALI
    SET OBJ_ID = OBJ_ID + :INCREMENT
    WHERE OBJ_ID >= :KEY_OLD * 1000000000
      AND OBJ_ID <  :KEY_NEW * 1000000000;

    UPDATE VALL
    SET OBJ_ID = OBJ_ID + :INCREMENT
    WHERE OBJ_ID >= :KEY_OLD * 1000000000
      AND OBJ_ID <  :KEY_NEW * 1000000000;

    UPDATE VALR
    SET OBJ_ID = OBJ_ID + :INCREMENT
    WHERE OBJ_ID >= :KEY_OLD * 1000000000
      AND OBJ_ID <  :KEY_NEW * 1000000000;

    UPDATE VALR
    SET VAL = VAL + :INCREMENT
    WHERE VAL >= :KEY_OLD * 1000000000
      AND VAL <  :KEY_NEW * 1000000000;

    UPDATE VALS
    SET OBJ_ID = OBJ_ID + :INCREMENT
    WHERE OBJ_ID >= :KEY_OLD * 1000000000
      AND OBJ_ID <  :KEY_NEW * 1000000000;

    UPDATE VALT
    SET OBJ_ID = OBJ_ID + :INCREMENT
    WHERE OBJ_ID >= :KEY_OLD * 1000000000
      AND OBJ_ID <  :KEY_NEW * 1000000000;

    UPDATE VALM
    SET PUPIL_ID = PUPIL_ID + :INCREMENT,
        TEACHER_ID = TEACHER_ID + :INCREMENT;

    UPDATE VALM
    SET SUBJECT_ID = SUBJECT_ID + :INCREMENT
    WHERE SUBJECT_ID >= :KEY_OLD * 1000000000
      AND SUBJECT_ID <  :KEY_NEW * 1000000000;

    /* DELETE */
    DELETE FROM OBJECTS
    WHERE OBJ_ID >= :KEY_OLD * 1000000000
      AND OBJ_ID <  :KEY_NEW * 1000000000;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIXER_LESSON_THEME
AS
declare variable V$ID bigint;
declare variable S varchar(1000);
begin

  FOR
    SELECT L.OBJ_ID, L.LESSON_THEME
    FROM CJ2_JOURNAL_LESSONS L
    WHERE POSITION('&nbsp;' IN L.LESSON_THEME) > 0 OR POSITION('&lt;' IN L.LESSON_THEME) > 0 OR POSITION('&gt;' IN L.LESSON_THEME) > 0
      OR POSITION('&quot;' IN L.LESSON_THEME) > 0 OR POSITION('&amp;' IN L.LESSON_THEME) > 0 OR POSITION('&#39;' IN L.LESSON_THEME) > 0
      OR POSITION('&#x2F;' IN L.LESSON_THEME) > 0 OR POSITION('&#x60;' IN L.LESSON_THEME) > 0 OR POSITION('&#x3D;' IN L.LESSON_THEME) > 0
    INTO :V$ID, :S
  DO
  BEGIN
    S = REPLACE(S, '&nbsp;', ' ');
    S = REPLACE(S, '&lt;', '<');
    S = REPLACE(S, '&gt;', '>');
    S = REPLACE(S, '&quot;', '"');
    S = REPLACE(S, '&amp;', '&');
    S = REPLACE(S, '&#39;', '''');
    S = REPLACE(S, '&#x2F;', '/');
    S = REPLACE(S, '&#x60;', '`');
    S = REPLACE(S, '&#x3D;', '=');

    UPDATE CJ2_JOURNAL_LESSONS
    SET LESSON_THEME = :S
    WHERE OBJ_ID = :V$ID;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIXER_MAJOR_TUTOR
AS
declare variable V$OBJ_ID bigint;
begin

  -- Изменение размещения должности старший воспитатель
  FOR
    SELECT OBJ.OBJ_ID
    FROM OBJECTS OBJ
    JOIN VALL V58 ON V58.OBJ_ID = OBJ.OBJ_ID AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0 AND V58.LISTVAL_ID = 127
    WHERE OBJ.TYPE_ID = 13
    INTO :V$OBJ_ID
  DO
  BEGIN
    UPDATE VALL SET LISTVAL_ID = 97 WHERE OBJ_ID = :V$OBJ_ID AND PARAM_ID = 63 AND IS_DEL = 0;
    UPDATE VALL SET LISTVAL_ID = 125 WHERE OBJ_ID = :V$OBJ_ID AND PARAM_ID = 64 AND IS_DEL = 0;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIXER_MICRODISTRICT (
    SCHOOL_ID BIGINT = null)
AS
declare variable V$SCHOOL_DISTRICT_ID bigint;
declare variable V$PUPIL_DISTRICT_ID bigint;
declare variable V$PUPIL_ID bigint;
BEGIN
    IF (SCHOOL_ID IS NULL) THEN
    BEGIN
        SELECT FIRST 1 L.OBJ_ID
        FROM LINKS L
        WHERE L.PARENT_ID IS NULL
        AND L.OBJ_TYPE_ID = 2
        AND L.DATE_DEL IS NULL
        INTO :SCHOOL_ID;
    END

    SELECT LV7.COST
    FROM VALL V7

    JOIN LISTVALS LV7
    ON LV7.LISTVAL_ID = V7.LISTVAL_ID

    WHERE V7.OBJ_ID = :SCHOOL_ID
    AND V7.PARAM_ID = 7
    AND V7.IS_DEL = 0

    INTO :V$SCHOOL_DISTRICT_ID;

    IF (V$SCHOOL_DISTRICT_ID IS NOT NULL) THEN
    BEGIN
        FOR
            SELECT L10.OBJ_ID,
                   V101.LISTVAL_ID

            FROM LINKS L10

            LEFT JOIN VALL V101
            ON V101.OBJ_ID = L10.OBJ_ID
            AND V101.PARAM_ID = 101
            AND V101.IS_DEL = 0

            WHERE L10.PARENT_TYPE_ID IN (9,187)
            AND L10.DATE_DEL IS NULL
            AND L10.OBJ_TYPE_ID = 10

            INTO :V$PUPIL_ID,
                 :V$PUPIL_DISTRICT_ID
        DO
        BEGIN
            IF ((V$PUPIL_DISTRICT_ID IS NULL)) THEN
            BEGIN
                UPDATE VALL
                SET IS_DEL = 1
                WHERE OBJ_ID = :V$PUPIL_ID
                AND PARAM_ID = 100
                AND IS_DEL = 0;
            END
            ELSE
            BEGIN
                UPDATE OR INSERT INTO VALL(
                    OBJ_ID,
                    PARAM_ID,
                    LISTVAL_ID,
                    IS_DEL
                )
                VALUES (
                    :V$PUPIL_ID,
                    100,
                    CASE
                        WHEN
                            (:V$PUPIL_DISTRICT_ID = :V$SCHOOL_DISTRICT_ID) OR
                            (:V$SCHOOL_DISTRICT_ID = 0) THEN 200 ELSE 201
                        END,
                    0
                );
            END
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIXER_MISSING_MOVEMENTS
AS
declare variable V$CLASS_ID bigint;
declare variable V$PERSON_ID bigint;
declare variable V$DATE date;
declare variable V$STAGE bigint;
declare variable V$OVZ bigint;
declare variable V$LAST_ID bigint;
declare variable V$DATE_OUT date;
begin

  -- Отсутствующие записи движения при добавлении сразу в коллектив
  FOR
    SELECT L10.PARENT_ID, L10.OBJ_ID, L10.DATE_INS, V49.LISTVAL_ID, V592.LISTVAL_ID
    FROM LINKS L2
    JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 187) AND L9.DATE_DEL IS NULL
    JOIN VALL V592 ON V592.OBJ_ID = L9.OBJ_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0
    JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    LEFT JOIN PERSON_MOVEMENTS M ON M.DATE_DEL IS NULL AND M.PERSON_ID = L10.OBJ_ID AND M.GROUP_ID = L10.PARENT_ID AND M.DATE_OUT IS NULL
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND M.OBJ_ID IS NULL
    INTO :V$CLASS_ID, :V$PERSON_ID, :V$DATE, :V$STAGE, :V$OVZ
  DO
  BEGIN
    INSERT INTO PERSON_MOVEMENTS
    (PERSON_ID, GROUP_ID, DATE_IN, STAGE_ID, REASON_IN, TYPE_IN, NAME_IN)
    VALUES (:V$PERSON_ID, :V$CLASS_ID, :V$DATE, :V$STAGE, IIF(:V$STAGE = 37, 805, 806), :V$OVZ, (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$CLASS_ID)));
  END

  -- Незакрытые записи движения
  FOR
    SELECT M.PERSON_ID
    FROM PERSON_MOVEMENTS M
    JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 187
    WHERE M.DATE_DEL IS NULL AND M.DATE_OUT IS NULL
    GROUP BY 1
    HAVING COUNT(*) > 1
    INTO :V$PERSON_ID
  DO
  BEGIN
    SELECT FIRST 1 M.OBJ_ID
    FROM PERSON_MOVEMENTS M
    JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 187
    WHERE M.DATE_DEL IS NULL AND M.DATE_OUT IS NULL AND M.PERSON_ID = :V$PERSON_ID
    ORDER BY 1 DESC
    INTO :V$LAST_ID;

    FOR
      SELECT M.OBJ_ID, M.GROUP_ID, M.DATE_IN
      FROM PERSON_MOVEMENTS M
      JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 187
      WHERE M.DATE_DEL IS NULL AND M.DATE_OUT IS NULL AND M.PERSON_ID = :V$PERSON_ID AND M.OBJ_ID < :V$LAST_ID
      INTO :V$STAGE, :V$CLASS_ID, :V$DATE
    DO
    BEGIN
      -- Пытаемся найти дату выбытия
      V$DATE_OUT = NULL;
      SELECT FIRST 1 LP187.DATE_DEL
      FROM LINKS LP187
      WHERE LP187.DATE_DEL >= :V$DATE AND LP187.PARENT_ID = :V$CLASS_ID AND LP187.OBJ_ID = :V$PERSON_ID
      INTO :V$DATE_OUT;

      -- Если не нашли выбытие, пытаемся найти зачисление
      IF(V$DATE_OUT IS NULL) THEN
      SELECT FIRST 1 LP9.DATE_INS
      FROM LINKS LP9
      WHERE LP9.DATE_INS >= :V$DATE AND LP9.PARENT_TYPE_ID IN (9, 187) AND LP9.OBJ_ID = :V$PERSON_ID
      INTO :V$DATE_OUT;

      IF(V$DATE_OUT IS NOT NULL) THEN
      UPDATE PERSON_MOVEMENTS
      SET DATE_OUT = :V$DATE_OUT, REASON_OUT = 12906
      WHERE OBJ_ID = :V$STAGE;
    END
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIXER_MONITORING_CHANGER (
    I$SCHOOL_ID BIGINT)
AS
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$CHANGER_YEAR_ID BIGINT;
DECLARE VARIABLE V$YEAR_ID BIGINT;
DECLARE VARIABLE Y SMALLINT;
DECLARE VARIABLE DT1 DATE;
DECLARE VARIABLE DT2 DATE;
DECLARE VARIABLE INS_DATE DATE;
DECLARE VARIABLE YEAR_VAL VARCHAR(100);
BEGIN
    FOR
        SELECT L238.OBJ_ID,
               V1895.LISTVAL_ID,
               L238.DATE_INS
        FROM LINKS L238

        JOIN VALL V1895
        ON V1895.OBJ_ID = L238.OBJ_ID
        AND V1895.PARAM_ID = 1895
        AND V1895.IS_DEL = 0

        WHERE L238.PARENT_ID = :I$SCHOOL_ID
        AND L238.OBJ_TYPE_ID = 238
        AND L238.DATE_DEL IS NULL

        INTO :V$OBJ_ID,
             :V$CHANGER_YEAR_ID,
             :INS_DATE
    DO
    BEGIN
        Y = EXTRACT(YEAR FROM INS_DATE);
        DT1 = '1.01.' || Y;
        DT2 = '1.01.' || (Y + 1);

        IF ((INS_DATE > DT1) AND (INS_DATE < DT2)) THEN
        BEGIN
            YEAR_VAL = (Y - 1) || '-' || Y;
        END
        ELSE
        BEGIN
            YEAR_VAL = Y || '-' ||(Y + 1);
        END

        SELECT FIRST 1
               LV.LISTVAL_ID
        FROM LISTVALS LV
    
        JOIN RES R
        ON R.RES_ID = LV.RES_ID
        AND R.LANG_CODE = 'RU'
    
        WHERE LV.LIST_ID = 29
        AND R.VAL LIKE :YEAR_VAL
        INTO :V$YEAR_ID;

        IF (V$YEAR_ID <> V$CHANGER_YEAR_ID) THEN
        BEGIN
            UPDATE VALL
            SET LISTVAL_ID = :V$YEAR_ID
            WHERE PARAM_ID = 1895
            AND OBJ_ID = :V$OBJ_ID
            AND IS_DEL = 0;
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIXER_ODNKNR
AS
declare variable V$MARK_ID bigint;
declare variable V$STUDENT_ID bigint;
begin

  -- Только отметки 2022-2023 учебного года
  FOR
    SELECT M.MARK_ID, M.PUPIL_ID
    FROM VALM M
    WHERE M.YEAR_ID = 10982 AND M.SUBJECT_ID = 9000
    ORDER BY 1
    INTO :V$MARK_ID, :V$STUDENT_ID
  DO
  BEGIN
    -- Если ученик был в группе по ОДНКНР - возвращаем отметку на этот премет
    IF(EXISTS(
      SELECT FIRST 1 1
      FROM PERSON_MOVEMENTS M2
      JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.GRADE_ID = M2.GROUP_ID AND J.SUBJECT_ID = 5532
      WHERE M2.DATE_DEL IS NULL AND M2.PERSON_ID = :V$STUDENT_ID AND M2.DATE_IN >= '20.08.2022' AND (M2.DATE_OUT IS NULL OR M2.DATE_OUT < '31.05.2023')
    ))
    THEN
    BEGIN
      UPDATE VALM
      SET SUBJECT_ID = 5532
      WHERE MARK_ID = :V$MARK_ID;
    END
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIXER_OOOD_TYPE (
    SCHOOL_ID BIGINT = null)
AS
declare variable V$LISTVAL_ID bigint;
declare variable V$BLOB_ID bigint;
BEGIN
    IF (SCHOOL_ID IS NULL) THEN
    BEGIN
        SELECT FIRST 1 L.OBJ_ID
        FROM LINKS L
        WHERE L.PARENT_ID IS NULL
        AND L.OBJ_TYPE_ID = 2
        AND L.DATE_DEL IS NULL
        INTO :SCHOOL_ID;
    END

    SELECT CASE I
        WHEN 948 THEN 5425
        WHEN 949 THEN 5425
        WHEN 950 THEN 5425
        WHEN 951 THEN 5425
        WHEN 952 THEN 5425
        WHEN 953 THEN 5425
        WHEN 2613 THEN 5425
        WHEN 2614 THEN 5425

        WHEN 955 THEN 5426
        WHEN 956 THEN 5426
        WHEN 957 THEN 5426

        WHEN 959 THEN 5426
        WHEN 960 THEN 5426
        WHEN 961 THEN 5426
        WHEN 962 THEN 5426
        WHEN 963 THEN 5426
        WHEN 964 THEN 5426
        WHEN 965 THEN 5426
        WHEN 966 THEN 5426
        WHEN 967 THEN 5426
        WHEN 968 THEN 5426
        WHEN 2219 THEN 5426
        WHEN 2220 THEN 5426

        WHEN 970 THEN 5426
        WHEN 971 THEN 5426
        WHEN 972 THEN 5426
        WHEN 973 THEN 5426
        WHEN 974 THEN 5426
        WHEN 2212 THEN 5426
        WHEN 2213 THEN 5426
        WHEN 2214 THEN 5426

        WHEN 976 THEN 5433
        WHEN 977 THEN 5433
        WHEN 2217 THEN 5433

        WHEN 979 THEN 5426
        WHEN 980 THEN 5426
        WHEN 2216 THEN 5426

        WHEN 982 THEN 5432
        WHEN 983 THEN 5432
        WHEN 984 THEN 5432
        WHEN 985 THEN 5432
        WHEN 986 THEN 5432
        WHEN 2215 THEN 5432

        WHEN 988 THEN 5426
        WHEN 989 THEN 5426
        WHEN 990 THEN 5426
        WHEN 991 THEN 5426
        WHEN 992 THEN 5426

        WHEN 995 THEN 5429
        WHEN 996 THEN 5429
        WHEN 997 THEN 5429
        WHEN 998 THEN 5429
        WHEN 999 THEN 5429
        WHEN 1000 THEN 5429
        WHEN 1001 THEN 5429
        WHEN 1002 THEN 5429

        WHEN 1010 THEN 5427
        WHEN 1011 THEN 5427
        WHEN 1012 THEN 5427

        WHEN 1014 THEN 5427
        WHEN 1015 THEN 5427
        WHEN 1016 THEN 5427

        WHEN 1018 THEN 5428
        WHEN 1019 THEN 5428
        WHEN 1020 THEN 5428

        WHEN 1022 THEN 5430
        WHEN 1023 THEN 5430
        WHEN 1024 THEN 5430
        WHEN 1025 THEN 5430

        WHEN 2222 THEN 5426
        WHEN 2223 THEN 5427
        WHEN 2224 THEN 5426
        WHEN 2225 THEN 5427
        ELSE NULL
    END
    FROM VAL_GET(:SCHOOL_ID, 10)
    INTO :V$LISTVAL_ID;
    
    IF (V$LISTVAL_ID IS NOT NULL) THEN
    BEGIN
        SELECT BLOB_ID
        FROM VAL_ADD(1890, :SCHOOL_ID, :V$LISTVAL_ID)
        INTO V$BLOB_ID;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIXER_ORGANIZATION_FORM (
    SCHOOL_ID BIGINT = NULL)
AS
DECLARE VARIABLE V$LISTVAL_ID BIGINT;
DECLARE VARIABLE V$BLOB_ID BIGINT;
BEGIN
    IF (SCHOOL_ID IS NULL) THEN
    BEGIN
        SELECT FIRST 1 L.OBJ_ID
        FROM LINKS L
        WHERE L.PARENT_ID IS NULL
        AND L.OBJ_TYPE_ID = 2
        AND L.DATE_DEL IS NULL
        INTO :SCHOOL_ID;
    END

    SELECT CASE I
                WHEN 7 THEN 5393
                WHEN 6 THEN 5394
                WHEN 8 THEN 5395
                WHEN 9 THEN 5397
                WHEN 945 THEN 5398
                WHEN 946 THEN 5399
                WHEN 3256 THEN 5401
                WHEN 3257 THEN 5402
                WHEN 3258 THEN 5403
                WHEN 1734 THEN 5404
                WHEN 1735 THEN 5405
                ELSE NULL
        END
    FROM VAL_GET(:SCHOOL_ID, 8)
    INTO :V$LISTVAL_ID;

    IF (V$LISTVAL_ID IS NOT NULL) THEN
    BEGIN
        SELECT BLOB_ID
        FROM VAL_ADD(8, :SCHOOL_ID, :V$LISTVAL_ID)
        INTO V$BLOB_ID;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIXER_OUTPUT_DOU (
    SCHOOL_ID BIGINT = null)
AS
declare variable V$OBJ_ID bigint;
declare variable V$BLOB_ID bigint;
BEGIN
    FOR
        SELECT L82.OBJ_ID
        FROM LINKS L78

        JOIN LINKS L82
        ON L82.PARENT_ID = L78.OBJ_ID
        AND L82.OBJ_TYPE_ID = 82
        AND L82.DATE_DEL IS NULL

        WHERE L78.PARENT_ID = :SCHOOL_ID
        AND L78.OBJ_TYPE_ID = 78
        AND L78.DATE_DEL IS NULL

        INTO :V$OBJ_ID
    DO
    BEGIN
        SELECT BLOB_ID
        FROM VAL_ADD(447, :V$OBJ_ID, '3321')
        INTO :V$BLOB_ID;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIXER_OVZ
AS
declare variable V$T bigint;
declare variable V$PERSON_ID bigint;
declare variable V$OVZ bigint;
declare variable V$CLASS_OVZ bigint;
declare variable V$CONTENT bigint;
begin

  -- Переносим атрибуты классов
  FOR
    SELECT L9.OBJ_ID, V592.OBJ_ID
    FROM LINKS L9
    JOIN VALL V592 ON V592.OBJ_ID = L9.OBJ_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 -- тип
    WHERE L9.PARENT_TYPE_ID = 8 AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
    INTO :V$T, :V$OVZ
  DO
  BEGIN
    V$CONTENT = (CASE V$OVZ
      WHEN 198 THEN 13283
      WHEN 199 THEN 13282
      WHEN 1732 THEN 13281
      WHEN 11398 THEN 13280
      WHEN 11399 THEN 13276
      WHEN 11400 THEN 13278
      WHEN 11401 THEN 13279
      WHEN 11402 THEN 13277
      ELSE 1355
    END);

    -- Обновляем прямо там, чтобы не трогать VAL_ADD
    UPDATE VALL SET LISTVAL_ID = :V$CONTENT WHERE OBJ_ID = :V$T AND PARAM_ID = 554 AND IS_DEL = 0;
  END

  -- Переносим данные по персонам
  FOR
    SELECT DISTINCT L10.PARENT_TYPE_ID, L10.OBJ_ID, V207.LISTVAL_ID, V592.LISTVAL_ID, V554.LISTVAL_ID
    FROM LINKS L10
    JOIN VALL V207 ON V207.OBJ_ID = L10.OBJ_ID AND V207.PARAM_ID = 207 AND V207.IS_DEL = 0
    LEFT JOIN VALL V592 ON V592.OBJ_ID = L10.PARENT_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 -- тип
    LEFT JOIN VALL V554 ON V554.OBJ_ID = L10.PARENT_ID AND V554.PARAM_ID = 554 AND V554.IS_DEL = 0 -- состав
    WHERE L10.DATE_DEL IS NULL AND L10.PARENT_TYPE_ID IN (9, 187, 82, 83) AND L10.OBJ_TYPE_ID = 10
    INTO :V$T, :V$PERSON_ID, :V$OVZ, :V$CLASS_OVZ, :V$CONTENT
  DO
  BEGIN

    -- Для общеобразовательных классов сбрасываем состав в обычный, если поле запорчено
    IF(V$CLASS_OVZ = 197) THEN V$CONTENT = 1355;

    IF(V$OVZ = 5) THEN V$OVZ = 13289; -- не ОВЗ
    ELSE
    BEGIN
      -- ОВЗ - выбираем по учебному коллективу, либо сбрасываем для выбывших
      IF(V$T = 9 AND V$CLASS_OVZ = 13275) THEN
      BEGIN
        V$OVZ = (CASE V$CONTENT
          WHEN 13276 THEN 13291
          WHEN 13277 THEN 13292
          WHEN 13278 THEN 13293
          WHEN 13279 THEN 13294
          WHEN 13280 THEN 13295
          WHEN 13281 THEN 13296
          WHEN 13282 THEN 13297
          WHEN 13283 THEN 13298
          WHEN 13284 THEN 13299
          WHEN 13285 THEN 13300
          WHEN 13286 THEN 13301
          ELSE NULL
        END);
      END
      ELSE V$OVZ = NULL;
    END

    SELECT BLOB_ID FROM VAL_ADD(207, :V$PERSON_ID, :V$OVZ) INTO :V$OVZ;

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIXER_OVZ_MOVE_TYPE
AS
declare variable V$GRADE_ID bigint;
declare variable V$TYPE bigint;
declare variable V$STAGE bigint;
declare variable S varchar(4000);
begin

  -- Закомментировано, чтобы не приводило к ошибкам в новых базах

  -- Исправление типа класса
  /*
  FOR
    SELECT M.OBJ_ID, V592.LISTVAL_ID
    FROM PERSON_MOVEMENTS M
    JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
    JOIN LINKS LP9 ON LP9.OBJ_ID = M.PERSON_ID AND LP9.PARENT_ID = M.GROUP_ID AND LP9.PARENT_TYPE_ID = 9 AND LP9.DATE_DEL IS NULL
    JOIN VALL V592 ON V592.OBJ_ID = LP9.PARENT_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0
    WHERE M.DATE_DEL IS NULL AND M.DATE_IN >= '01.06.2021' AND (M.TYPE_IN IS NULL OR M.TYPE_IN <> V592.LISTVAL_ID)
    INTO :V$GRADE_ID, :V$TYPE
  DO
  BEGIN
    IF(V$TYPE NOT IN (197, 196, 13275)) THEN EXCEPTION DATA_ERROR 'Неверно задан тип класса по ОВЗ';
    UPDATE PERSON_MOVEMENTS SET TYPE_IN = :V$TYPE WHERE OBJ_ID = :V$GRADE_ID;
  END

  -- Исправление движения ГПП (название и этап)
  FOR
    SELECT M.OBJ_ID, J.STAGE_INDEX, GC.CAPTION
    FROM PERSON_MOVEMENTS M
    JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 179
    JOIN CJ2_JOURNAL J ON J.GRADE_ID = M.GROUP_ID
    LEFT JOIN OBJECT_CAPTION_GET(J.GRADE_ID) GC ON 1 = 1
    WHERE M.DATE_DEL IS NULL
    INTO :V$GRADE_ID, :V$STAGE, :S
  DO
  BEGIN
    UPDATE PERSON_MOVEMENTS SET NAME_IN = :S, STAGE_ID = :V$STAGE WHERE OBJ_ID = :V$GRADE_ID;
  END
  */

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIXER_OVZ_STAGES2022
AS
declare variable V$MOVE_ID bigint;
declare variable V$PERSON_ID bigint;
declare variable V$GROUP_ID bigint;
declare variable V$TYPE_ID bigint;
declare variable V$SY bigint;
declare variable V$DATE timestamp;
declare variable N integer;
begin

  FOR
    SELECT M.OBJ_ID, M.PERSON_ID, M.GROUP_ID, G.TYPE_ID
    FROM PERSON_MOVEMENTS M
    JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID IN (9, 187)
    WHERE M.DATE_DEL IS NULL AND M.DATE_OUT IS NULL
    ORDER BY 1
    INTO :V$MOVE_ID, :V$PERSON_ID, :V$GROUP_ID, :V$TYPE_ID
  DO
  BEGIN

    SELECT COUNT(*)
    FROM PERSON_MOVEMENTS M
    JOIN LINKS LP54 ON LP54.OBJ_ID = M.GROUP_ID AND LP54.PARENT_TYPE_ID = 54 AND LP54.DATE_DEL IS NULL
    JOIN LINKS LP400 ON LP400.OBJ_ID = LP54.PARENT_ID AND LP400.PARENT_TYPE_ID = 400 AND LP400.DATE_DEL IS NULL
    JOIN LINKS L54 ON L54.PARENT_ID = LP400.PARENT_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
    WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :V$PERSON_ID AND M.DATE_OUT IS NULL
    INTO :N;

    -- Год обучения подставляем только при зачислении в класс, в прочих случаях будет NULL
    IF(V$TYPE_ID = 9) THEN
    BEGIN
      SELECT FIRST 1 V3024.LISTVAL_ID
      FROM VALL V3024
      JOIN VALL V592 ON V592.OBJ_ID = V3024.OBJ_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 13275
      WHERE V3024.OBJ_ID = :V$GROUP_ID AND V3024.PARAM_ID = 3024 AND V3024.IS_DEL = 0
      INTO :V$SY;

      IF(V$SY = 12938) THEN V$SY = 1;
      ELSE IF(V$SY = 12939) THEN V$SY = 2;
      ELSE V$SY = NULL;
    END

    UPDATE PERSON_MOVEMENTS
    SET PLAN_STAGES = :N, STAGE_YEAR = :V$SY, GROUP_TYPE_ID = :V$TYPE_ID
    WHERE OBJ_ID = :V$MOVE_ID;

  END

  -- Обновляем тип группы во всех остальных случаях
  FOR
    SELECT M.OBJ_ID, G.TYPE_ID
    FROM PERSON_MOVEMENTS M
    JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID
    WHERE M.GROUP_TYPE_ID IS NULL
    ORDER BY 1
    INTO :V$MOVE_ID, :V$TYPE_ID
  DO
  BEGIN
    UPDATE PERSON_MOVEMENTS
    SET GROUP_TYPE_ID = :V$TYPE_ID
    WHERE OBJ_ID = :V$MOVE_ID;
  END

  -- Обновляем уровень образования во всех записях движения
  -- только текущий учебный год
  FOR
    SELECT M.OBJ_ID, M.GROUP_ID, M.DATE_ADD
    FROM PERSON_MOVEMENTS M
    WHERE M.GROUP_TYPE_ID IN (9, 187) AND M.LEVEL_ID IS NULL
    ORDER BY 1
    INTO :V$MOVE_ID, :V$GROUP_ID, :V$DATE
  DO
  BEGIN

    -- Можно обновить текущий учебный год
    V$TYPE_ID = NULL;
    SELECT FIRST 1 V43.LISTVAL_ID
    FROM LINKS LP8
    JOIN LINKS LP7 ON LP7.OBJ_ID = LP8.PARENT_ID AND LP7.PARENT_TYPE_ID = 7 AND LP7.DATE_DEL IS NULL
    JOIN VALL V43 ON V43.OBJ_ID = LP7.PARENT_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0
    WHERE LP8.OBJ_ID = :V$GROUP_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_INS <= :V$DATE AND (LP8.DATE_DEL IS NULL OR LP8.DATE_DEL >= :V$DATE)
    ORDER BY LP8.DATE_INS
    INTO :V$TYPE_ID;

    UPDATE PERSON_MOVEMENTS
    SET LEVEL_ID = :V$TYPE_ID
    WHERE OBJ_ID = :V$MOVE_ID;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIXER_P64
AS
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$BLOB_ID BIGINT;
BEGIN
    FOR SELECT L13.OBJ_ID
        FROM LINKS L13
        JOIN VALL V58 ON V58.OBJ_ID =  L13.OBJ_ID
          AND V58.PARAM_ID = 58
          AND V58.IS_DEL = 0
          AND V58.LISTVAL_ID = 121
        WHERE L13.PARENT_TYPE_ID = 2
          AND L13.OBJ_TYPE_ID = 13
          AND L13.DATE_DEL IS NULL
        INTO :V$OBJ_ID
    DO
    BEGIN
        SELECT BLOB_ID
        FROM VAL_ADD(58, :V$OBJ_ID, 121)
        INTO :V$BLOB_ID;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIXER_PARAM_ID_1340
AS
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$BLOB_ID BIGINT;
BEGIN
    FOR SELECT L10.OBJ_ID
        FROM LINKS L10
        LEFT JOIN VALL V1340 ON V1340.OBJ_ID = L10.OBJ_ID
          AND V1340.PARAM_ID = 1340
          AND V1340.IS_DEL = 0
        WHERE L10.PARENT_TYPE_ID IN (9, 289)
          AND L10.OBJ_TYPE_ID = 10
          AND L10.DATE_DEL IS NULL
          AND V1340.PARAM_ID IS NULL
        INTO :V$OBJ_ID
    DO
    BEGIN
        SELECT BLOB_ID
        FROM VAL_ADD(1340, :V$OBJ_ID, 10874)
        INTO :V$BLOB_ID;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIXER_PARAM_TYPE_SET (
    I$PARAM_ID BIGINT,
    I$PARAM_TYPE SMALLINT)
AS
DECLARE VARIABLE V$LANG_CODE CHAR(2);
DECLARE VARIABLE V$PARAM_TYPE_OLD SMALLINT;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$VAL VARCHAR(4000);
DECLARE VARIABLE V$USER_ID BIGINT;
DECLARE VARIABLE V$BLOB_ID BIGINT;
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = 1
    INTO :V$LANG_CODE;

    SELECT PARAM_TYPE
    FROM PARAMS
    WHERE PARAM_ID = :I$PARAM_ID
    INTO :V$PARAM_TYPE_OLD;

    IF (:V$PARAM_TYPE_OLD IN (6, 7, 8) AND :I$PARAM_TYPE IN (7, 8)) THEN
    BEGIN
        IF (:V$PARAM_TYPE_OLD <> :I$PARAM_TYPE) THEN
        BEGIN
            UPDATE PARAMS
            SET PARAM_TYPE = :I$PARAM_TYPE
            WHERE PARAM_ID = :I$PARAM_ID;
        END

        FOR SELECT V.OBJ_ID, R.VAL, V.USER_ID
            FROM VALL V
            JOIN LISTVALS LV ON V.LISTVAL_ID = LV.LISTVAL_ID
            LEFT JOIN RES_GET(LV.RES_ID,  :V$LANG_CODE) R ON 1=1
            WHERE V.PARAM_ID = :I$PARAM_ID
              AND V.IS_DEL = 0
            INTO :V$OBJ_ID, :V$VAL, :V$USER_ID
        DO
        BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD(:I$PARAM_ID, :V$OBJ_ID, :V$VAL, :V$USER_ID)
            INTO :V$BLOB_ID;
        END

        UPDATE VALL
        SET IS_DEL = 1
        WHERE PARAM_ID = :I$PARAM_ID
          AND IS_DEL = 0;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIXER_PARENTS
AS
declare variable V$PARENTS_ID bigint;
declare variable V$NEW_PARENTS_ID bigint;
declare variable V$PUPIL_ID bigint;
declare variable V$LINK_ID bigint;
declare variable V$LASTNAME varchar(255);
declare variable V$FIRSTNAME varchar(255);
declare variable V$MIDDLENAME varchar(255);
declare variable V$DOB date;
declare variable V$I bigint;
declare variable V$S varchar(4000);
declare variable V$BLOB_ID bigint;
declare variable V$EXT_OBJ_ID bigint;
BEGIN
    INSERT INTO FILTER_SESSION_VALS(OBJ_ID, TYPE_ID)
    SELECT L20.LINK_ID,
           L20.OBJ_ID
    FROM LINKS L20

    WHERE L20.PARENT_TYPE_ID = 10
    AND L20.OBJ_TYPE_ID = 20
    AND L20.EXT_OBJ_ID IS NULL;

    FOR
        SELECT FSV.OBJ_ID
        FROM FILTER_SESSION_VALS FSV

        INTO :V$LINK_ID
    DO
    BEGIN
        SELECT L20.LINK_ID,
               L20.OBJ_ID,
               L20.PARENT_ID,
               CAST(L.VAL AS VARCHAR(255)),
               CAST(F.VAL AS VARCHAR(255)),
               CAST(M.VAL AS VARCHAR(255)),
               D.VAL
        FROM LINKS L20

        JOIN VALS L
        ON L.OBJ_ID = L20.OBJ_ID
        AND L.PARAM_ID = 128
        AND L.IS_DEL = 0

        JOIN VALS F
        ON F.OBJ_ID = L20.OBJ_ID
        AND F.PARAM_ID = 129
        AND F.IS_DEL = 0

        LEFT JOIN VALS M
        ON M.OBJ_ID = L20.OBJ_ID
        AND M.PARAM_ID = 130
        AND M.IS_DEL = 0

        LEFT JOIN VALD D
        ON D.OBJ_ID = L20.OBJ_ID
        AND D.PARAM_ID = 143
        AND D.IS_DEL = 0

        WHERE LINK_ID = :V$LINK_ID

        INTO :V$LINK_ID,
             :V$PARENTS_ID,
             :V$PUPIL_ID,
             :V$LASTNAME,
             :V$FIRSTNAME,
             :V$MIDDLENAME,
             :V$DOB;

        INSERT INTO OBJECTS(TYPE_ID) VALUES(168)
        RETURNING OBJ_ID
        INTO :V$EXT_OBJ_ID;

        SELECT I FROM VAL_GET(:V$PARENTS_ID, 131) INTO V$I;
        IF (V$I IN (224,225,3254)) THEN
        BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD(1573, :V$EXT_OBJ_ID, :V$I)
            INTO :V$BLOB_ID;
        END

        SELECT I FROM VAL_GET(:V$PARENTS_ID, 148) INTO V$I;
        IF (V$I > 0) THEN
        BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD(1562, :V$EXT_OBJ_ID, :V$I)
            INTO :V$BLOB_ID;
        END

        SELECT I FROM VAL_GET(:V$PARENTS_ID, 149) INTO V$I;
        IF (V$I > 0) THEN
        BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD(1563, :V$EXT_OBJ_ID, :V$I)
            INTO :V$BLOB_ID;
        END

        SELECT I FROM VAL_GET(:V$PARENTS_ID, 138) INTO V$I;
        IF (V$I > 0) THEN
        BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD(1564, :V$EXT_OBJ_ID, :V$I)
            INTO :V$BLOB_ID;
        END

        SELECT I FROM VAL_GET(:V$PARENTS_ID, 132) INTO V$I;
        IF (V$I > 0) THEN
        BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD(1565, :V$EXT_OBJ_ID, :V$I)
            INTO :V$BLOB_ID;
        END

        SELECT I FROM VAL_GET(:V$PARENTS_ID, 133) INTO V$I;
        IF (V$I > 0) THEN
        BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD(1566, :V$EXT_OBJ_ID, :V$I)
            INTO :V$BLOB_ID;
        END

        SELECT I FROM VAL_GET(:V$PARENTS_ID, 134) INTO V$I;
        IF (V$I > 0) THEN
        BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD(1567, :V$EXT_OBJ_ID, :V$I)
            INTO :V$BLOB_ID;
        END

        SELECT V FROM VAL_GET(:V$PARENTS_ID, 156) INTO V$S;
        IF (V$S <> '') THEN
        BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD(1568, :V$EXT_OBJ_ID, :V$S)
            INTO :V$BLOB_ID;
        END

        SELECT V FROM VAL_GET(:V$PARENTS_ID, 154) INTO V$S;
        IF (V$S <> '') THEN
        BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD(1570, :V$EXT_OBJ_ID, :V$S)
            INTO :V$BLOB_ID;
        END

        V$NEW_PARENTS_ID = NULL;
        SELECT FIRST 1
               PARENT_ID
        FROM PUPIL_PARENTS_LIST (
            :V$PUPIL_ID,
            :V$PARENTS_ID,
            :V$LASTNAME,
            :V$FIRSTNAME,
            :V$MIDDLENAME,
            :V$DOB
        )
        INTO :V$NEW_PARENTS_ID;
        IF (V$NEW_PARENTS_ID IS NOT NULL) THEN
        BEGIN
            UPDATE LINKS
            SET OBJ_ID = :V$NEW_PARENTS_ID,
                EXT_OBJ_ID = :V$EXT_OBJ_ID,
                EXT_OBJ_TYPE_ID = 168
            WHERE LINK_ID = :V$LINK_ID;
        END
        ELSE
        BEGIN
            UPDATE LINKS
            SET EXT_OBJ_ID = :V$EXT_OBJ_ID,
                EXT_OBJ_TYPE_ID = 168
            WHERE LINK_ID = :V$LINK_ID;
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIXER_PARENTS_DOU
AS
declare variable V$S varchar(4000);
declare variable V$BLOB_ID bigint;
declare variable V$LISTVAL_ID bigint;
declare variable V$EXT_OBJ_ID bigint;
BEGIN
    FOR
        SELECT L20.EXT_OBJ_ID,
               V1553.LISTVAL_ID,
               V1583.VAL
        FROM LINKS L20
    
        LEFT JOIN VALL V1553
        ON V1553.OBJ_ID = L20.OBJ_ID
        AND V1553.PARAM_ID = 1553
        AND V1553.IS_DEL = 0

        LEFT JOIN VALS V1583
        ON V1583.OBJ_ID = L20.OBJ_ID
        AND V1583.PARAM_ID = 1583
        AND V1583.IS_DEL = 0

        WHERE L20.PARENT_TYPE_ID = 10
        AND L20.OBJ_TYPE_ID = 20
        AND L20.DATE_DEL IS NULL
        AND L20.EXT_OBJ_TYPE_ID = 168

        INTO :V$EXT_OBJ_ID,
             :V$LISTVAL_ID,
             :V$S
    DO
    BEGIN
        IF (V$S IS NOT NULL) THEN
        BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD(2454, :V$EXT_OBJ_ID, :V$S)
            INTO :V$BLOB_ID;
        END
        IF (V$LISTVAL_ID IS NULL) THEN
        BEGIN
            V$LISTVAL_ID = 3303;
        END
        SELECT BLOB_ID
        FROM VAL_ADD(2453, :V$EXT_OBJ_ID, :V$LISTVAL_ID)
        INTO :V$BLOB_ID;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIXER_PARENTS_DUPLICATES
AS
declare variable V$PARENTS_ID bigint;
declare variable V$LINK_ID bigint;
declare variable V$LINK_ID2 bigint;
declare variable V$LASTNAME varchar(255);
declare variable V$FIRSTNAME varchar(255);
declare variable V$MIDDLENAME varchar(255);
declare variable V$S varchar(4000);
declare variable V$BLOB_ID bigint;
BEGIN
    INSERT INTO FILTER_SESSION_VALS(OBJ_ID, TYPE_ID)
    SELECT L20.LINK_ID,
           L20.OBJ_ID
    FROM LINKS L20

    WHERE L20.PARENT_TYPE_ID = 10
    AND L20.OBJ_TYPE_ID = 20
    AND L20.DATE_DEL IS NULL;

    FOR
        SELECT FSV.OBJ_ID
        FROM FILTER_SESSION_VALS FSV

        INTO :V$LINK_ID
    DO
    BEGIN
        SELECT L20.LINK_ID,
               L20.OBJ_ID,
               CAST(L.VAL AS VARCHAR(255)),
               CAST(F.VAL AS VARCHAR(255)),
               CAST(M.VAL AS VARCHAR(255))
        FROM LINKS L20

        JOIN VALS L
        ON L.OBJ_ID = L20.OBJ_ID
        AND L.PARAM_ID = 128
        AND L.IS_DEL = 0

        JOIN VALS F
        ON F.OBJ_ID = L20.OBJ_ID
        AND F.PARAM_ID = 129
        AND F.IS_DEL = 0

        LEFT JOIN VALS M
        ON M.OBJ_ID = L20.OBJ_ID
        AND M.PARAM_ID = 130
        AND M.IS_DEL = 0

        WHERE LINK_ID = :V$LINK_ID

        INTO :V$LINK_ID,
             :V$PARENTS_ID,
             :V$LASTNAME,
             :V$FIRSTNAME,
             :V$MIDDLENAME;

        FOR
            SELECT L20.LINK_ID,
                   V155.VAL

            FROM FILTER_SESSION_VALS FSV

            JOIN LINKS L20
            ON L20.LINK_ID = FSV.OBJ_ID

            JOIN VALS L
            ON L.OBJ_ID = L20.OBJ_ID
            AND L.PARAM_ID = 128
            AND L.IS_DEL = 0

            JOIN VALS F
            ON F.OBJ_ID = L20.OBJ_ID
            AND F.PARAM_ID = 129
            AND F.IS_DEL = 0

            LEFT JOIN VALS M
            ON M.OBJ_ID = L20.OBJ_ID
            AND M.PARAM_ID = 130
            AND M.IS_DEL = 0

            LEFT JOIN VALS V155
            ON V155.OBJ_ID = L20.OBJ_ID
            AND V155.PARAM_ID = 155
            AND V155.IS_DEL = 0

            WHERE L20.LINK_ID <> :V$LINK_ID

            AND TRIM(L.VAL) LIKE TRIM(:V$LASTNAME)
            AND TRIM(F.VAL) LIKE TRIM(:V$FIRSTNAME)
            AND ((:V$MIDDLENAME IS NULL) OR (M.VAL LIKE :V$MIDDLENAME))

            INTO :V$LINK_ID2,
                 :V$S
        DO
        BEGIN
            UPDATE LINKS
            SET OBJ_ID = :V$PARENTS_ID
            WHERE LINK_ID = :V$LINK_ID2;

            IF (V$S IS NOT NULL) THEN
            BEGIN
                SELECT BLOB_ID
                FROM VAL_ADD(155, :V$PARENTS_ID, :V$S)
                INTO :V$BLOB_ID;
            END
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIXER_PARENT_EXT_DOU
AS
declare variable V$S varchar(4000);
declare variable V$BLOB_ID bigint;
declare variable V$LINK_ID bigint;
declare variable V$LISTVAL_ID bigint;
declare variable V$EXT_OBJ_ID bigint;
BEGIN
    FOR
        SELECT L20.LINK_ID,
               V1553.LISTVAL_ID,
               V1583.VAL
        FROM LINKS L20
    
        LEFT JOIN VALL V1553
        ON V1553.OBJ_ID = L20.OBJ_ID
        AND V1553.PARAM_ID = 1553
        AND V1553.IS_DEL = 0

        LEFT JOIN VALS V1583
        ON V1583.OBJ_ID = L20.OBJ_ID
        AND V1583.PARAM_ID = 1583
        AND V1583.IS_DEL = 0

        WHERE L20.PARENT_TYPE_ID = 10
        AND L20.OBJ_TYPE_ID = 20
        AND L20.DATE_DEL IS NULL
        AND L20.EXT_OBJ_ID IS NULL

        INTO :V$LINK_ID,
             :V$LISTVAL_ID,
             :V$S
    DO
    BEGIN
        INSERT INTO OBJECTS(TYPE_ID) VALUES(168)
        RETURNING OBJ_ID
        INTO :V$EXT_OBJ_ID;

        UPDATE LINKS
        SET EXT_OBJ_ID = :V$EXT_OBJ_ID,
            EXT_OBJ_TYPE_ID = 168
        WHERE LINK_ID = :V$LINK_ID;

        IF (V$S IS NOT NULL) THEN
        BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD(2454, :V$EXT_OBJ_ID, :V$S)
            INTO :V$BLOB_ID;
        END
        IF (V$LISTVAL_ID IS NULL) THEN
        BEGIN
            V$LISTVAL_ID = 3303;
        END
        SELECT BLOB_ID
        FROM VAL_ADD(2453, :V$EXT_OBJ_ID, :V$LISTVAL_ID)
        INTO :V$BLOB_ID;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIXER_PARENT_REASONFORHELP
AS
declare variable V$OBJ_ID bigint;
declare variable V$BLOB_ID bigint;
BEGIN
    FOR
        SELECT L20.OBJ_ID
        FROM LINKS L20

        LEFT JOIN VALL V1553
        ON V1553.OBJ_ID = L20.OBJ_ID
        AND V1553.PARAM_ID = 1553
        AND V1553.IS_DEL = 0

        WHERE L20.OBJ_TYPE_ID = 20
        AND L20.DATE_DEL IS NULL
        AND V1553.LISTVAL_ID IS NULL

        INTO :V$OBJ_ID
    DO
    BEGIN
        SELECT BLOB_ID
        FROM VAL_ADD(1553, :V$OBJ_ID, '3303')
        INTO :V$BLOB_ID;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIXER_PLANING
AS
declare variable V$OBJ49_ID bigint;
declare variable V$OBJ51_ID bigint;
declare variable V$OBJ54_ID bigint;
declare variable V$OBJ56_ID bigint;
declare variable V$OBJ58_ID bigint;
declare variable V$OBJ58_2_ID bigint;
declare variable V$OBJ70_ID bigint;
declare variable V$OBJ60_ID bigint;
declare variable V$OBJ6_ID bigint;
declare variable V$GROUP_ID bigint;
declare variable V$OBJ56_2_ID bigint;
declare variable V$OLD_OBJ_ID bigint;
declare variable V$TMP integer;
BEGIN
    FOR
        SELECT DISTINCT
               L51.OBJ_ID,
               LP54.PARENT_ID,
               LP49.PARENT_ID
        FROM LINKS L51

        JOIN LINKS L56
        ON L56.PARENT_ID = L51.OBJ_ID
        AND L56.DATE_DEL IS NULL
        AND L56.OBJ_TYPE_ID = 56
        
        JOIN LINKS LP54
        ON LP54.OBJ_ID = L56.OBJ_ID
        AND LP54.DATE_DEL IS NULL
        AND LP54.PARENT_TYPE_ID = 54
        
        JOIN LINKS LP49
        ON LP49.OBJ_ID = L51.OBJ_ID
        AND LP49.PARENT_TYPE_ID = 49
        AND LP49.DATE_DEL IS NULL

        JOIN LINKS LP49_56
        ON LP49_56.PARENT_ID = LP49.PARENT_ID
        AND LP49_56.OBJ_ID = L56.OBJ_ID
        AND LP49_56.DATE_DEL IS NULL

        WHERE L51.OBJ_TYPE_ID = 51
        AND L51.DATE_DEL IS NULL
        AND L51.PARENT_TYPE_ID IN (53,51)
        --AND L51.OBJ_ID = 3139
        
        GROUP BY L51.OBJ_ID,LP54.PARENT_ID,LP49.PARENT_ID
        HAVING COUNT(DISTINCT L56.OBJ_ID) > 1
    
        INTO :V$OBJ51_ID,
             :V$OBJ54_ID,
             :V$OBJ49_ID
    DO
    BEGIN
        SELECT FIRST 1
               L56.OBJ_ID
        FROM LINKS L56

        JOIN LINKS L51_56
        ON L51_56.PARENT_ID = :V$OBJ51_ID
        AND L51_56.OBJ_ID = L56.OBJ_ID
        AND L51_56.DATE_DEL IS NULL

        JOIN LINKS L49_56
        ON L49_56.PARENT_ID = :V$OBJ49_ID
        AND L49_56.OBJ_ID = L56.OBJ_ID
        AND L49_56.DATE_DEL IS NULL

        WHERE L56.PARENT_ID = :V$OBJ54_ID
        AND L56.OBJ_TYPE_ID = 56
        AND L56.DATE_DEL IS NULL

/*        FROM LINKS L56

        JOIN LINKS LP51
        ON LP51.PARENT_ID = :V$OBJ51_ID
        AND LP51.OBJ_ID = L56.OBJ_ID
        AND LP51.DATE_DEL IS NULL

        WHERE L56.PARENT_ID = :V$OBJ54_ID
        AND L56.OBJ_TYPE_ID = 56
        AND L56.DATE_DEL IS NULL */

        INTO :V$OBJ56_ID;

        FOR
            SELECT L56.OBJ_ID

            FROM LINKS L56
    
            JOIN LINKS L51_56
            ON L51_56.PARENT_ID = :V$OBJ51_ID
            AND L51_56.OBJ_ID = L56.OBJ_ID
            AND L51_56.DATE_DEL IS NULL
    
            JOIN LINKS L49_56
            ON L49_56.PARENT_ID = :V$OBJ49_ID
            AND L49_56.OBJ_ID = L56.OBJ_ID
            AND L49_56.DATE_DEL IS NULL
    
            WHERE L56.PARENT_ID = :V$OBJ54_ID
            AND L56.OBJ_TYPE_ID = 56
            AND L56.DATE_DEL IS NULL
            AND L56.OBJ_ID <> :V$OBJ56_ID

/*            FROM LINKS L56

            JOIN LINKS LP51
            ON LP51.PARENT_ID = :V$OBJ51_ID
            AND LP51.OBJ_ID = L56.OBJ_ID
            AND LP51.DATE_DEL IS NULL

            WHERE L56.PARENT_ID = :V$OBJ54_ID
            AND L56.OBJ_TYPE_ID = 56
            AND L56.DATE_DEL IS NULL
            AND L56.OBJ_ID <> :V$OBJ56_ID*/

            INTO :V$OBJ56_2_ID
        DO
        BEGIN
            FOR
                SELECT L58.OBJ_ID,
                       LGR.PARENT_ID
                FROM LINKS L58

                JOIN LINKS LGR
                ON LGR.OBJ_ID = L58.OBJ_ID
                AND LGR.PARENT_TYPE_ID IN (9,46,48)

                JOIN LINKS LP51
                ON LP51.PARENT_ID = :V$OBJ51_ID
                AND LP51.OBJ_ID = L58.OBJ_ID
                AND LP51.DATE_DEL IS NULL

                WHERE L58.PARENT_ID = :V$OBJ56_2_ID
                AND L58.OBJ_TYPE_ID = 58
                AND L58.DATE_DEL IS NULL
                INTO :V$OBJ58_2_ID,
                     :V$GROUP_ID
            DO
            BEGIN
                IF (NOT EXISTS(
                    SELECT FIRST 1 1
                    FROM LINKS L58
    
                    JOIN LINKS LGR
                    ON LGR.OBJ_ID = L58.OBJ_ID
                    AND LGR.PARENT_TYPE_ID IN (9,46,48)
    
                    JOIN LINKS LP51
                    ON LP51.PARENT_ID = :V$OBJ51_ID
                    AND LP51.OBJ_ID = L58.OBJ_ID
                    AND LP51.DATE_DEL IS NULL

                    WHERE L58.PARENT_ID = :V$OBJ56_ID
                    AND L58.OBJ_TYPE_ID = 58
                    AND L58.DATE_DEL IS NULL
                    AND LGR.PARENT_ID = :V$GROUP_ID
                    AND L58.OBJ_ID <> :V$OBJ58_2_ID
                )) THEN
                BEGIN
                    UPDATE LINKS L
                    SET L.PARENT_ID = :V$OBJ56_ID
                    WHERE L.OBJ_ID = :V$OBJ58_2_ID
                    AND L.PARENT_ID = :V$OBJ56_2_ID
                    AND L.DATE_DEL IS NULL;
                END
                ELSE
                BEGIN
                    SELECT FIRST 1
                           L58.OBJ_ID
                    FROM LINKS L58
    
                    JOIN LINKS LGR
                    ON LGR.OBJ_ID = L58.OBJ_ID
                    AND LGR.PARENT_TYPE_ID IN (9,46,48)

                    JOIN LINKS LP51
                    ON LP51.PARENT_ID = :V$OBJ51_ID
                    AND LP51.OBJ_ID = L58.OBJ_ID
                    AND LP51.DATE_DEL IS NULL
    
                    WHERE L58.PARENT_ID = :V$OBJ56_ID
                    AND L58.OBJ_TYPE_ID = 58
                    AND L58.DATE_DEL IS NULL
                    AND LGR.PARENT_ID = :V$GROUP_ID
                    AND L58.OBJ_ID <> :V$OBJ58_2_ID
                    INTO :V$OBJ58_ID;

                    FOR
                        SELECT L70.OBJ_ID,
                               LP6.PARENT_ID,
                               LP60.PARENT_ID
                        FROM LINKS L70

                        JOIN LINKS LP60
                        ON LP60.OBJ_ID = L70.OBJ_ID
                        AND LP60.PARENT_TYPE_ID = 60
                        AND LP60.DATE_DEL IS NULL

                        JOIN LINKS LP6
                        ON LP6.OBJ_ID = L70.OBJ_ID
                        AND LP6.PARENT_TYPE_ID = 6
                        AND LP6.DATE_DEL IS NULL

                        WHERE L70.PARENT_ID = :V$OBJ58_2_ID
                        AND L70.OBJ_TYPE_ID = 70
                        AND L70.DATE_DEL IS NULL
                        INTO :V$OBJ70_ID,
                             :V$OBJ6_ID,
                             :V$OBJ60_ID
                    DO
                    BEGIN
                        IF (NOT EXISTS(
                            SELECT FIRST 1 1
                            FROM LINKS L70
    
                            JOIN LINKS LP60
                            ON LP60.OBJ_ID = L70.OBJ_ID
                            AND LP60.PARENT_TYPE_ID = 60
                            AND LP60.DATE_DEL IS NULL
    
                            JOIN LINKS LP6
                            ON LP6.OBJ_ID = L70.OBJ_ID
                            AND LP6.PARENT_TYPE_ID = 6
                            AND LP6.DATE_DEL IS NULL
    
                            WHERE L70.PARENT_ID = :V$OBJ58_ID
                            AND L70.OBJ_TYPE_ID = 70
                            AND L70.DATE_DEL IS NULL
                            AND LP6.PARENT_ID = :V$OBJ6_ID
                            AND LP60.PARENT_ID = :V$OBJ60_ID
                        )) THEN
                        BEGIN
                            UPDATE LINKS L
                            SET L.PARENT_ID = :V$OBJ58_ID
                            WHERE L.OBJ_ID = :V$OBJ70_ID
                            AND L.PARENT_ID = :V$OBJ58_2_ID
                            AND L.DATE_DEL IS NULL;  
                        END
                        ELSE
                        BEGIN
                            UPDATE LINKS L
                            SET L.DATE_DEL = CURRENT_TIMESTAMP
                            WHERE L.OBJ_ID = :V$OBJ70_ID
                            AND L.PARENT_ID = :V$OBJ58_2_ID
                            AND L.DATE_DEL IS NULL;                              
                        END
                    END

                    UPDATE LINKS L
                    SET L.DATE_DEL = CURRENT_TIMESTAMP
                    WHERE L.OBJ_ID = :V$OBJ58_2_ID
                    AND L.PARENT_ID = :V$OBJ56_2_ID
                    AND L.DATE_DEL IS NULL;
                END
            END

            FOR
                SELECT L.OBJ_ID
                FROM LINKS L
                WHERE L.PARENT_ID = :V$OBJ56_2_ID
                AND L.DATE_DEL IS NULL
                AND L.OBJ_TYPE_ID <> 58
                INTO :V$OLD_OBJ_ID
            DO
            BEGIN
                SELECT COUNT(*)
                FROM LINKS L
                WHERE L.PARENT_ID = :V$OBJ56_ID
                AND L.OBJ_ID = :V$OLD_OBJ_ID
                AND L.DATE_DEL IS NULL
                INTO :V$TMP;
        
                IF (V$TMP = 0) THEN
                BEGIN
                    UPDATE LINKS L
                    SET L.PARENT_ID = :V$OBJ56_ID
                    WHERE L.PARENT_ID = :V$OBJ56_2_ID
                    AND L.OBJ_ID = :V$OLD_OBJ_ID
                    AND L.DATE_DEL IS NULL;
                END
                ELSE
                BEGIN
                    UPDATE LINKS L
                    SET L.DATE_DEL = CURRENT_TIMESTAMP
                    WHERE L.PARENT_ID = :V$OBJ56_2_ID
                    AND L.OBJ_ID = :V$OLD_OBJ_ID
                    AND L.DATE_DEL IS NULL;
                END
            END
            UPDATE LINKS
            SET DATE_DEL = CURRENT_TIMESTAMP
            WHERE PARENT_ID = :V$OBJ54_ID
            AND OBJ_ID = :V$OBJ56_2_ID
            AND DATE_DEL IS NULL;
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIXER_POST (
    KEY_LEVEL VARCHAR(100))
RETURNS (
    BLOB_ID BIGINT)
AS
DECLARE VARIABLE ROOT_ID BIGINT;
DECLARE VARIABLE SCHOOL_ID BIGINT;
DECLARE VARIABLE OBJ_ID BIGINT;
DECLARE VARIABLE POST_ID BIGINT;
DECLARE VARIABLE LISTVAL_ID BIGINT;
DECLARE VARIABLE DEEP INTEGER;
BEGIN
    IF (KEY_LEVEL = '1') THEN
    BEGIN
        SELECT FIRST 1 L.OBJ_ID
        FROM LINKS L
        WHERE L.PARENT_ID IS NULL
          AND L.OBJ_TYPE_ID = 2
          AND L.DATE_DEL IS NULL
        INTO :ROOT_ID;

        DEEP = 0;
    END

    IF (KEY_LEVEL = '2') THEN
    BEGIN
        SELECT FIRST 1 L.OBJ_ID
        FROM LINKS L
        WHERE L.PARENT_ID IS NULL
          AND L.OBJ_TYPE_ID = 111
          AND L.DATE_DEL IS NULL
        INTO :ROOT_ID;

        DEEP = 1;
    END

    IF (KEY_LEVEL = '3') THEN
    BEGIN
        SELECT FIRST 1 L.OBJ_ID
        FROM LINKS L
        WHERE L.PARENT_ID IS NULL
          AND L.OBJ_TYPE_ID = 112
          AND L.DATE_DEL IS NULL
        INTO :ROOT_ID;

        DEEP = 2;
    END

    FOR SELECT OBJ_ID
        FROM OBJECT_CHILDREN_GET_DEEP(:ROOT_ID, 2, :DEEP)
        INTO :SCHOOL_ID
    DO
    BEGIN
        FOR SELECT L15.OBJ_ID, V58.LISTVAL_ID
            FROM LINKS L14
            INNER JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID
            INNER JOIN VALR V69 ON V69.OBJ_ID = L15.OBJ_ID
            INNER JOIN VALL V58 ON V58.OBJ_ID = V69.VAL
            WHERE L14.PARENT_ID = :SCHOOL_ID
              AND L14.OBJ_TYPE_ID = 14
              AND L14.DATE_DEL IS NULL
              AND L15.OBJ_TYPE_ID = 15
              AND L15.DATE_DEL IS NULL
              AND V69.PARAM_ID = 69
              AND V69.IS_DEL = 0
              AND V58.PARAM_ID = 58
              AND V58.IS_DEL = 0
            INTO :OBJ_ID, :LISTVAL_ID
        DO
        BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD(1394, :OBJ_ID, :LISTVAL_ID)
            INTO :BLOB_ID;
        END
    END
    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIXER_PUPIL_FINISH_TO_LEAVED
AS
declare variable V$CONTAINER_PUPIL_OUT_ID bigint;
declare variable V$OBJ_TO bigint;
declare variable V$OBJ_FROM bigint;
declare variable V$BLOB_ID bigint;
declare variable V$LINK_ID bigint;
declare variable V$PUPIL_ID bigint;
declare variable V$MOVE_ID bigint;
BEGIN

  -- Смысл утрачен

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIXER_RAISER_SKILL_JOB (
    I$TYPE_ID BIGINT,
    I$OLD_PARAM_ID BIGINT,
    I$NEW_PARAM_ID BIGINT)
AS
declare variable V$OBJ_ID bigint;
declare variable V$LISTVAL_ID bigint;
declare variable V$BLOB_ID bigint;
declare variable V$VAL varchar(1000);
declare variable V$LANG_CODE char(2) = 'RU';
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = 1
    INTO :V$LANG_CODE;

    -- Переносим данные аттестации на должность - меняем поле REF на LISTVAL
    -- Дополнительная проверка: только там, где поле еще не было заполнено при первой обработке в 2015 году !

    FOR
        SELECT L.OBJ_ID, V589.VAL
        FROM LINKS L
        JOIN VALR VR ON VR.OBJ_ID = L.OBJ_ID AND VR.PARAM_ID = :I$OLD_PARAM_ID AND VR.IS_DEL = 0
        JOIN VALS V589 ON V589.OBJ_ID = VR.VAL AND V589.PARAM_ID = 589 AND V589.IS_DEL = 0
        LEFT JOIN VALL VNEW ON VNEW.OBJ_ID = VR.VAL AND VNEW.PARAM_ID = :I$NEW_PARAM_ID AND VNEW.IS_DEL = 0
        WHERE L.OBJ_TYPE_ID = :I$TYPE_ID AND L.DATE_DEL IS NULL AND VNEW.LISTVAL_ID IS NULL
        INTO :V$OBJ_ID, :V$VAL
    DO
    BEGIN
        FOR
            SELECT LV.LISTVAL_ID
            FROM LISTVALS LV
            LEFT JOIN RES_GET(LV.RES_ID, :V$LANG_CODE) R ON 1 = 1
            WHERE LV.LIST_ID = 284 AND R.VAL LIKE :V$VAL
            INTO :V$LISTVAL_ID
        DO
        BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD(:I$NEW_PARAM_ID, :V$OBJ_ID, :V$LISTVAL_ID)
            INTO :V$BLOB_ID;
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIXER_RAISER_SKILL_OOOD (
    I$LONG_PARAM_ID BIGINT,
    I$SHORT_PARAM_ID BIGINT,
    I$OBJ_ID BIGINT = null,
    I$VAL VARCHAR(1000) = null)
AS
declare variable V$OBJ_ID bigint;
declare variable V$LISTVAL_ID bigint;
declare variable V$BLOB_ID bigint;
declare variable V$VAL varchar(1000);
declare variable V$SHORT varchar(1000);
declare variable V$LONG varchar(1000);
declare variable V$LANG_CODE char(2) = 'RU';
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = 1
    INTO :V$LANG_CODE;

    FOR
        SELECT V304.OBJ_ID,
               V304.VAL
        FROM VALS V304
        WHERE V304.PARAM_ID = :I$LONG_PARAM_ID
        AND V304.IS_DEL = 0
        AND ((:I$OBJ_ID IS NULL) OR (V304.OBJ_ID = :I$OBJ_ID))
        INTO :V$OBJ_ID,
             :V$VAL
    DO
    BEGIN
        IF (I$VAL IS NOT NULL) THEN
        BEGIN
            V$VAL = I$VAL;
        END
        IF (V$VAL = 'СПб государственный университет') THEN
        BEGIN
            V$LISTVAL_ID = 11052;
        END
        ELSE IF (V$VAL = 'Российский государственный педагогический университет им. А.И.Герцена') THEN
        BEGIN
            V$LISTVAL_ID = 11053;
        END
        ELSE IF (V$VAL = 'СПб государственный университет информационных технологий, механики и оптики') THEN
        BEGIN
            V$LISTVAL_ID = 11054;
        END
        ELSE IF (V$VAL = 'Государственное образовательное учреждение дополнительного профессионального образования (повышения квалификации специалистов) Санкт-Петербургская академия постдипломного педагогического образования (СПбАППО)') THEN
        BEGIN
            V$LISTVAL_ID = 11055;
        END
        ELSE IF (V$VAL = 'Государственное образовательное учреждение "Санкт-Петербургский городской Дворец творчества юных" (СПбГДТЮ)') THEN
        BEGIN
            V$LISTVAL_ID = 11056;
        END
        ELSE IF (V$VAL = 'Государственное образовательное учреждение дополнительного профессионального образования Центр повышения квалификации специалистов Санкт-Петербурга "Региональный центр оценки качества и информационных технологий" (РЦОКОиИТ)') THEN
        BEGIN
            V$LISTVAL_ID = 11057;
        END
        ELSE IF (V$VAL = 'Государственное образовательное учреждение дополнительного педагогического профессионального образования центр повышения квалификации специалистов Адмиралтейского района Санкт-Петербурга «Научно-методический Центр»') THEN
        BEGIN
            V$LISTVAL_ID = 11058;
        END
        ELSE IF (V$VAL = 'Государственное образовательное учреждение дополнительного педагогического и профессионального образования Центр повышения квалификации специалистов Василеостровского района Санкт-Петербурга') THEN
        BEGIN
            V$LISTVAL_ID = 11059;
        END
        ELSE IF (V$VAL = 'Государственное образовательное учреждение дополнительного педагогического профессионального образования Центр повышения квалификации специалистов Выборгского района Санкт-Петербурга "Научно-методический Центр"') THEN
        BEGIN
            V$LISTVAL_ID = 11060;
        END
        ELSE IF (V$VAL = 'Государственное образовательное учреждение дополнительного педагогического профессионального образования специалистов центр повышения квалификации Калининского района Санкт-Петербурга "Научно-методический Центр"') THEN
        BEGIN
            V$LISTVAL_ID = 11061;
        END
        ELSE IF (V$VAL = 'Государственное образовательное учреждение дополнительного педагогического профессионального образования Центр повышения квалификации специалистов "Научно-методический Центр" Кировского района') THEN
        BEGIN
            V$LISTVAL_ID = 11062;
        END
        ELSE IF (V$VAL = 'Государственное образовательное учреждение дополнительного педагогического профессионального образования Центр повышения квалификации специалистов Колпинского района Санкт-Петербурга') THEN
        BEGIN
            V$LISTVAL_ID = 11063;
        END
        ELSE IF (V$VAL = 'Государственное образовательное учреждение дополнительного педагогического профессионального образования Центр повышения квалификации специалистов Красногвардейского административного района "Научно-методический Центр"') THEN
        BEGIN
            V$LISTVAL_ID = 11064;
        END
        ELSE IF (V$VAL = 'Государственное образовательное учреждение дополнительного педагогического профессионального образования специалистов Центр повышения квалификации Красносельского района Санкт-Петербурга «Научно-методический Центр»') THEN
        BEGIN
            V$LISTVAL_ID = 11065;
        END
        ELSE IF (V$VAL = 'Государственное образовательное учреждение дополнительного педагогического профессионального образования Научно-методический Центр Кронштадтского района') THEN
        BEGIN
            V$LISTVAL_ID = 11066;
        END
        ELSE IF (V$VAL = 'Государственное образовательное учреждение дополнительного педагогического профессионального образования Центр повышения квалификации специалистов Курортного района "Научно-методический Центр"') THEN
        BEGIN
            V$LISTVAL_ID = 11067;
        END
        ELSE IF (V$VAL = 'Государственное образовательное учреждение дополнительного педагогического профессионального образования Научно-методический Центр Московского района') THEN
        BEGIN
            V$LISTVAL_ID = 11068;
        END
        ELSE IF (V$VAL = 'Государственное образовательное учреждение дополнительного педагогического профессионального образования центр повышения квалификации специалистов Невского административного района Санкт-Петербурга "Научно-методический центр"') THEN
        BEGIN
            V$LISTVAL_ID = 11069;
        END
        ELSE IF (V$VAL = 'Государственное образовательное учреждение дополнительного педагогического профессионального образования Центр повышения квалификации специалистов Петроградского района Санкт-Петербурга "Научно-методический Центр"') THEN
        BEGIN
            V$LISTVAL_ID = 11070;
        END
        ELSE IF (V$VAL = 'Государственное образовательное учреждение дополнительного педагогического профессионального образования центр повышения квалификации специалистов Петродворцового района Санкт-Петербурга «Научно-методический центр»') THEN
        BEGIN
            V$LISTVAL_ID = 11071;
        END
        ELSE IF (V$VAL = 'Государственное образовательное учреждение профессионального дополнительного педагогического образования Центр повышения квалификации специалистов «Научно-методический Центр» Приморского района Санкт-Петербурга') THEN
        BEGIN
            V$LISTVAL_ID = 11072;
        END
        ELSE IF (V$VAL = 'Государственное образовательное учреждение дополнительного педагогического профессионального образования центр повышения квалификации специалистов Пушкинского района Санкт-Петербурга "Научно-методический центр"') THEN
        BEGIN
            V$LISTVAL_ID = 11073;
        END
        ELSE IF (V$VAL = 'Государственное образовательное учреждение дополнительного педагогического профессионального образования (повышения квалификации) специалистов Научно-методический центр администрации Фрунзенского района Санкт-Петербурга') THEN
        BEGIN
            V$LISTVAL_ID = 11074;
        END
        ELSE IF (V$VAL = 'Государственное образовательное учреждение дополнительного педагогического профессионального образования Центр повышения квалификации специалистов Центрального района Санкт-Петербурга "Научно-методический Центр"') THEN
        BEGIN
            V$LISTVAL_ID = 11075;
        END
        ELSE
        BEGIN
            V$LISTVAL_ID = NULL;
            IF (I$OBJ_ID IS NOT NULL) THEN
            BEGIN
                SELECT BLOB_ID
                FROM VAL_ADD(:I$LONG_PARAM_ID, :I$OBJ_ID, :V$VAL, 1)
                INTO :V$BLOB_ID;

                UPDATE VALS
                SET IS_DEL = 1
                WHERE OBJ_ID = :I$OBJ_ID
                AND PARAM_ID IN (2334,2335)
                AND IS_DEL=0;
            END
        END
        FOR
            SELECT R.VAL,
                   R.VAL_LONG
            FROM LISTVALS LV
            LEFT JOIN RES_GET(LV.RES_ID, :V$LANG_CODE) R
            ON 1=1
            WHERE LV.LISTVAL_ID = :V$LISTVAL_ID
            INTO :V$SHORT,
                 :V$LONG
        DO
        BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD(:I$SHORT_PARAM_ID, :V$OBJ_ID, :V$SHORT, 1)
            INTO :V$BLOB_ID;
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIXER_REMOVE_DELETED_CERTIFICAT
AS
DECLARE VARIABLE V$LINK_ID BIGINT;
BEGIN
    FOR
        SELECT L234.LINK_ID
        
        FROM LINKS L228
        
        JOIN LINKS L236
        ON L236.PARENT_ID = L228.OBJ_ID
        AND L236.OBJ_TYPE_ID = 236
        AND L236.DATE_DEL IS NOT NULL
        
        JOIN VALR V1877
        ON V1877.VAL = L236.OBJ_ID
        AND V1877.PARAM_ID = 1877
        
        JOIN LINKS L234
        ON L234.OBJ_ID = V1877.OBJ_ID
        AND L234.OBJ_TYPE_ID = 234
        AND L234.DATE_DEL IS NULL
        
        WHERE L228.OBJ_TYPE_ID = 228
        AND L228.DATE_DEL IS NOT NULL

        INTO :V$LINK_ID
    DO
    BEGIN
        UPDATE LINKS
        SET DATE_DEL = CURRENT_TIMESTAMP
        WHERE LINK_ID = :V$LINK_ID;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIXER_REMOVE_FM_DUPLICATES
AS
declare variable V$PUPIL_ID bigint;
declare variable V$SUBJECT_ID bigint;
declare variable V$YEAR_ID bigint;
declare variable V$MARKTYPE_ID bigint;
BEGIN
    FOR
        SELECT PUPIL_ID, SUBJECT_ID, YEAR_ID, MARKTYPE_ID
        FROM VALM
        GROUP BY PUPIL_ID, SUBJECT_ID, YEAR_ID, MARKTYPE_ID
        HAVING COUNT(*) > 1
        INTO :V$PUPIL_ID, :V$SUBJECT_ID, :V$YEAR_ID, :V$MARKTYPE_ID
    DO
    BEGIN
        WHILE (EXISTS(
            SELECT FIRST 1 1
            FROM VALM
            WHERE PUPIL_ID = :V$PUPIL_ID
            AND SUBJECT_ID = :V$SUBJECT_ID
            AND YEAR_ID = :V$YEAR_ID
            AND MARKTYPE_ID = :V$MARKTYPE_ID
            HAVING COUNT(*) > 1
        ))
        DO
        BEGIN
            UPDATE VALM
            SET YEAR_ID = 3259
            WHERE MARK_ID = (
                SELECT FIRST 1
                       MARK_ID
                FROM VALM
                WHERE PUPIL_ID = :V$PUPIL_ID
                AND SUBJECT_ID = :V$SUBJECT_ID
                AND YEAR_ID = :V$YEAR_ID
                AND MARKTYPE_ID = :V$MARKTYPE_ID
            );
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIXER_REORGANIZE_DISTR_SUBJ
AS
BEGIN
    UPDATE LINKS
    SET DATE_DEL = CURRENT_TIMESTAMP
    WHERE PARENT_ID = 208
    AND OBJ_TYPE_ID = 51
    AND DATE_DEL IS NULL;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIXER_REPAIR_OBJ_GEN
AS
declare variable V$GENERATOR bigint;
declare variable V$GEN bigint;
declare variable V$MULTIPLIER bigint;
declare variable V$OBJ_ID bigint;
BEGIN
    FOR
        SELECT "GEN", MULTIPLIER
        FROM GEN
        INTO :V$GEN, :V$MULTIPLIER
    DO
    BEGIN
        SELECT MAX(OBJ_ID)
        FROM OBJECTS
        WHERE OBJ_ID > :V$GEN * :V$MULTIPLIER AND OBJ_ID < (:V$GEN + 1) * :V$MULTIPLIER
        INTO :V$OBJ_ID;
        IF(V$OBJ_ID IS NULL) THEN V$OBJ_ID = 0;

        V$GENERATOR = V$OBJ_ID - V$GEN * V$MULTIPLIER + 1;
        -- CODE IS NOT FUNCTIONAL IN FB3 !!!
        EXECUTE STATEMENT 'SET GENERATOR GEN_OBJ_ID TO ' || V$GENERATOR || ';';

        SELECT MAX(LINK_ID)
        FROM LINKS
        WHERE LINK_ID > :V$GEN * :V$MULTIPLIER AND LINK_ID < (:V$GEN + 1) * :V$MULTIPLIER
        INTO :V$OBJ_ID;
        IF(V$OBJ_ID IS NULL) THEN V$OBJ_ID = 0;

        V$GENERATOR = V$OBJ_ID - V$GEN * V$MULTIPLIER + 1;
        -- CODE IS NOT FUNCTIONAL IN FB3 !!!
        EXECUTE STATEMENT 'SET GENERATOR GEN_LINK_ID TO ' || V$GENERATOR || ';';
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIXER_SCHOOL_DISTRICT (
    I$SCHOOL_ID BIGINT,
    I$USER_ID BIGINT = 1)
AS
declare variable V$MICRODISTRICT_ID bigint;
declare variable V$DISTRICT_ID bigint;
declare variable V$SCHOOL_DISTRICT_ID bigint;
declare variable V$PUPIL_ID bigint;
declare variable LANG_CODE varchar(2);
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :LANG_CODE;

    SELECT LV.COST
    FROM VALS V7
    
    JOIN LISTVALS LV
    ON LV.LIST_ID = 168
    AND LV.IS_DEL = 0
    
    LEFT JOIN RES_GET(LV.RES_ID, :LANG_CODE) R
    ON 1=1

    WHERE V7.OBJ_ID = :I$SCHOOL_ID
    AND V7.PARAM_ID = 7
    AND V7.IS_DEL = 0
    AND R.VAL LIKE V7.VAL

    INTO :V$SCHOOL_DISTRICT_ID;

    FOR
        SELECT L10.OBJ_ID,
               V100.LISTVAL_ID,
               V101.LISTVAL_ID

        FROM LINKS L77

        JOIN LINKS L9
        ON L9.PARENT_ID = L77.OBJ_ID
        AND L9.OBJ_TYPE_ID = 9
        AND L9.DATE_DEL IS NULL

        JOIN LINKS L10
        ON L10.PARENT_ID = L9.OBJ_ID
        AND L10.OBJ_TYPE_ID = 10
        AND L10.DATE_DEL IS NULL

        LEFT JOIN VALL V100
        ON V100.OBJ_ID = L10.OBJ_ID
        AND V100.PARAM_ID = 100
        AND V100.IS_DEL = 0

        LEFT JOIN VALL V101
        ON V101.OBJ_ID = L10.OBJ_ID
        AND V101.PARAM_ID = 101
        AND V101.IS_DEL = 0

        WHERE L77.PARENT_ID = :I$SCHOOL_ID
        AND L77.OBJ_TYPE_ID = 77
        AND L77.DATE_DEL IS NULL

        UNION ALL

        SELECT L10.OBJ_ID,
               V100.LISTVAL_ID,
               V101.LISTVAL_ID

        FROM LINKS L7

        JOIN LINKS L8
        ON L8.PARENT_ID = L7.OBJ_ID
        AND L8.OBJ_TYPE_ID = 8
        AND L8.DATE_DEL IS NULL

        JOIN LINKS L9
        ON L9.PARENT_ID = L8.OBJ_ID
        AND L9.OBJ_TYPE_ID IN (9, 187)
        AND L9.DATE_DEL IS NULL

        JOIN LINKS L10
        ON L10.PARENT_ID = L9.OBJ_ID
        AND L10.OBJ_TYPE_ID = 10
        AND L10.DATE_DEL IS NULL

        LEFT JOIN VALL V100
        ON V100.OBJ_ID = L10.OBJ_ID
        AND V100.PARAM_ID = 100
        AND V100.IS_DEL = 0

        LEFT JOIN VALL V101
        ON V101.OBJ_ID = L10.OBJ_ID
        AND V101.PARAM_ID = 101
        AND V101.IS_DEL = 0

        WHERE L7.PARENT_ID = :I$SCHOOL_ID
        AND L7.OBJ_TYPE_ID = 7
        AND L7.DATE_DEL IS NULL

        INTO :V$PUPIL_ID,
             :V$MICRODISTRICT_ID,
             :V$DISTRICT_ID
    DO
    BEGIN
        IF ((V$DISTRICT_ID IS NOT NULL)) THEN
        BEGIN
            IF ((V$SCHOOL_DISTRICT_ID IS NULL) OR (:V$SCHOOL_DISTRICT_ID = 0) OR (:V$SCHOOL_DISTRICT_ID = :V$DISTRICT_ID)) THEN
            BEGIN
                IF ((V$MICRODISTRICT_ID IS NULL) OR (V$MICRODISTRICT_ID <> 200)) THEN
                BEGIN
                    UPDATE OR INSERT INTO VALL(OBJ_ID,PARAM_ID,IS_DEL,LISTVAL_ID)
                    VALUES (:V$PUPIL_ID,100,0,200);
                END
            END
            ELSE
            BEGIN
                IF ((V$MICRODISTRICT_ID IS NULL) OR (V$MICRODISTRICT_ID <> 201)) THEN
                BEGIN
                    UPDATE OR INSERT INTO VALL(OBJ_ID,PARAM_ID,IS_DEL,LISTVAL_ID)
                    VALUES (:V$PUPIL_ID,100,0,201);
                END
            END
        END
        ELSE IF (V$MICRODISTRICT_ID IS NOT NULL) THEN
        BEGIN
            UPDATE VALL
            SET IS_DEL = 1
            WHERE OBJ_ID = :V$PUPIL_ID
            AND PARAM_ID = 100
            AND IS_DEL = 0;
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIXER_SNILS (
    SCHOLAR_ID BIGINT)
AS
declare variable X bigint;
declare variable DOC_ID bigint;
declare variable S varchar(1000);
declare variable VAL varchar(1000);
declare variable SNILS varchar(1000);
BEGIN
    DOC_ID = NULL;

    SELECT FIRST 1 L12.OBJ_ID
    FROM LINKS L12
    INNER JOIN VALL V51 ON V51.OBJ_ID = L12.OBJ_ID
    WHERE L12.PARENT_ID = :SCHOLAR_ID
      AND L12.OBJ_TYPE_ID = 12
      AND L12.DATE_DEL IS NULL
      AND V51.PARAM_ID = 51
      AND V51.IS_DEL = 0
      AND V51.LISTVAL_ID = 1384
    INTO :DOC_ID;

    IF (DOC_ID IS NULL) THEN
        EXIT;

    SELECT V
    FROM VAL_GET(:SCHOLAR_ID, 1409)
    INTO :SNILS;

    SELECT IS_REAL
    FROM CHECK_SNILS(:SNILS)
    INTO :X;

    IF (X = 1) THEN
        EXIT;

    SELECT V
    FROM VAL_GET(:DOC_ID, 571)
    INTO :VAL;

    IF (VAL = '') THEN
    BEGIN
        SELECT V
        FROM VAL_GET(:DOC_ID, 570)
        INTO :VAL;
    END

    IF (VAL = '') THEN
        EXIT;

    X = 1;
    S = '';

    WHILE (X <= CHAR_LENGTH(VAL)) DO
    BEGIN
        IF (SUBSTRING(VAL FROM X FOR 1) SIMILAR TO '[0-9]') THEN
            S = S || SUBSTRING(VAL FROM X FOR 1);
        X = X + 1;
    END

    IF (S SIMILAR TO '[0-9]{11}' ESCAPE '\') THEN
    BEGIN
        SNILS = SUBSTRING(S FROM 1 FOR 3) || '-' || SUBSTRING(S FROM 4 FOR 3) || '-' || SUBSTRING(S FROM 7 FOR 3) || ' ' || SUBSTRING(S FROM 10 FOR 2);

        SELECT IS_REAL
        FROM CHECK_SNILS(:SNILS)
        INTO :X;

        IF (X = 1) THEN
        BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD(1409, :SCHOLAR_ID, :SNILS)
            INTO :X;
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIXER_SNILS_DUPLICATE
AS
declare variable V$SNILS_ID bigint;
declare variable V$PARENT_ID bigint;
declare variable V$SNILS varchar(4000) collate UNICODE;
declare variable V$_ID bigint;
declare variable V$DOC_ID bigint;
declare variable V$PERSON_ID bigint;
BEGIN

  FOR
    -- получим дублирующие записи СНИЛС, более старые, которые надо удалить
    SELECT L12.OBJ_ID, L12.PARENT_ID
    FROM LINKS L12
    JOIN VALL V51 ON V51.OBJ_ID = L12.OBJ_ID AND V51.PARAM_ID = 51 AND V51.IS_DEL = 0 AND V51.LISTVAL_ID = 1384
    WHERE L12.OBJ_TYPE_ID = 12 AND L12.PARENT_TYPE_ID IN (14, 10) AND L12.DATE_DEL IS NULL AND EXISTS(
      SELECT FIRST 1 1
      FROM LINKS L12X
      JOIN VALL V51X ON V51X.OBJ_ID = L12X.OBJ_ID AND V51X.PARAM_ID = 51 AND V51X.IS_DEL = 0 AND V51X.LISTVAL_ID = 1384
      WHERE L12X.PARENT_ID = L12.PARENT_ID AND L12X.OBJ_TYPE_ID = 12 AND L12X.DATE_DEL IS NULL AND L12X.OBJ_ID > L12.OBJ_ID
    )
    ORDER BY 1
    INTO :V$SNILS_ID, :V$PARENT_ID
  DO
  BEGIN
    SELECT DEL_COUNT FROM OBJECT_DEL(:V$SNILS_ID, :V$PARENT_ID) INTO :V$_ID;
  END 

  -- создать отсутствующие записи документов при наличии данных в личном деле для учеников и сотрудников
  FOR
    SELECT DISTINCT LP.OBJ_ID, V1409.VAL
    FROM LINKS LP
    JOIN VALS V1409 ON V1409.OBJ_ID = LP.OBJ_ID AND V1409.PARAM_ID IN (1409, 2455) AND V1409.IS_DEL = 0
    LEFT JOIN CHECK_SNILS(V1409.VAL) VV ON 1 = 1
    WHERE LP.OBJ_TYPE_ID IN (10, 14) AND LP.DATE_DEL IS NULL AND LP.PARENT_TYPE_ID IN (9, 187, 290, 2, 84) AND VV.IS_REAL = 1 AND NOT EXISTS (
      SELECT FIRST 1 1
      FROM LINKS L12
      JOIN VALL V51 ON V51.OBJ_ID = L12.OBJ_ID AND V51.PARAM_ID = 51 AND V51.IS_DEL = 0 AND V51.LISTVAL_ID = 1384
      JOIN VALS V571 ON V571.OBJ_ID = L12.OBJ_ID AND V571.PARAM_ID = 571 AND V571.IS_DEL = 0
      WHERE L12.PARENT_ID = LP.OBJ_ID AND L12.OBJ_TYPE_ID = 12 AND L12.DATE_DEL IS NULL
    )
    INTO :V$PERSON_ID, :V$SNILS
  DO
  BEGIN
    SELECT OBJ_ID FROM OBJECT_ADD(:V$PERSON_ID, 12) INTO :V$DOC_ID;
    SELECT 1 FROM VAL_ADD(51, :V$DOC_ID, 1384) INTO :V$_ID;
    SELECT 1 FROM VAL_ADD(571, :V$DOC_ID, :V$SNILS) INTO :V$_ID;
  END

END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIXER_STD2021_RECALC
AS
declare variable V$OBJ_ID bigint;
begin

  FOR
    SELECT L400.OBJ_ID
    FROM LINKS L400
    JOIN VALL V3022 ON V3022.OBJ_ID = L400.OBJ_ID AND V3022.PARAM_ID = 3022 AND V3022.IS_DEL = 0 AND V3022.LISTVAL_ID = 3
    WHERE L400.PARENT_TYPE_ID = 57 AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL
    INTO :V$OBJ_ID
  DO
  BEGIN
    EXECUTE PROCEDURE PLAN_RECALC(:V$OBJ_ID, 1);
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIXER_STUDY_FORM (
    SCHOOL_ID BIGINT = NULL)
AS
DECLARE VARIABLE V$LISTVAL_ID BIGINT;
DECLARE VARIABLE V$PUPIL_ID BIGINT;
DECLARE VARIABLE V$BLOB_ID BIGINT;
BEGIN
    IF (SCHOOL_ID IS NULL) THEN
    BEGIN
        SELECT FIRST 1 L.OBJ_ID
        FROM LINKS L
        WHERE L.PARENT_ID IS NULL
        AND L.OBJ_TYPE_ID = 2
        AND L.DATE_DEL IS NULL
        INTO :SCHOOL_ID;
    END

    FOR
        SELECT DISTINCT
               L10.OBJ_ID
        FROM LINKS L10

        WHERE L10.OBJ_TYPE_ID = 10
        AND L10.DATE_DEL IS NULL

        INTO :V$PUPIL_ID
    DO
    BEGIN
        SELECT CASE I
                    WHEN 153 THEN 5418
                    WHEN 1222 THEN 5418
                    WHEN 3150 THEN 5418
                    WHEN 154 THEN 5419
                    WHEN 155 THEN 5420
                    WHEN 1220 THEN 5422
                    WHEN 156 THEN 5422
                    WHEN 1221 THEN 5423
                    ELSE NULL
            END
        FROM VAL_GET(:V$PUPIL_ID, 80)
        INTO :V$LISTVAL_ID;
    
        IF (V$LISTVAL_ID IS NOT NULL) THEN
        BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD(80, :V$PUPIL_ID, :V$LISTVAL_ID)
            INTO V$BLOB_ID;
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIXER_UDOD_P2448
AS
declare variable V$OBJ_ID bigint;
declare variable V$PARAM_VAL bigint;
declare variable V$BLOB_ID bigint;
BEGIN

  -- Смысл утрачен

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIXER_USERS_LANGUAGE
AS
declare variable V$LANG_CODE char(2) = 'RU';
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = 1
    INTO :V$LANG_CODE;

    UPDATE USERS
    SET LANG_CODE = :V$LANG_CODE
    WHERE USER_ID <> 1;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIXER_VD_DEST
AS
declare variable V$OBJ_ID bigint;
declare variable V$FIELD_ID bigint;
begin

  FOR
    SELECT S.OBJ_ID, V2464.LISTVAL_ID
    FROM LINKS L400
    JOIN VALL V3022 ON V3022.OBJ_ID = L400.OBJ_ID AND V3022.PARAM_ID = 3022 AND V3022.IS_DEL = 0 AND V3022.LISTVAL_ID = 2
    JOIN PLAN_SUBJECTS S ON S.PLAN_ID = L400.OBJ_ID AND S.DATE_DEL IS NULL AND S.ROW_TYPE = 10 AND S.FIELD_ID IS NULL
    JOIN VALL V2464 ON V2464.OBJ_ID = S.SUBJECT_ID AND V2464.PARAM_ID = 2464 AND V2464.IS_DEL = 0
    WHERE L400.PARENT_TYPE_ID = 57 AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL
    INTO :V$OBJ_ID, :V$FIELD_ID
  DO
  BEGIN
    UPDATE PLAN_SUBJECTS
    SET FIELD_ID = :V$FIELD_ID
    WHERE OBJ_ID = :V$OBJ_ID;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIXER_YC2021
AS
declare variable V$MON_ID bigint;
declare variable V$MON2020_ID bigint;
declare variable V$DT timestamp;
declare variable V$DTOLD timestamp;
begin

  -- Ищем запись архива за 2021-2022 учебный год, который на самом деле 2020-2021
  SELECT FIRST 1 L238.OBJ_ID, L238.DATE_INS
  FROM LINKS L2
  JOIN LINKS L238 ON L238.PARENT_ID = L2.OBJ_ID AND L238.OBJ_TYPE_ID = 238 AND L238.DATE_DEL IS NULL
  JOIN VALL V1895 ON V1895.OBJ_ID = L238.OBJ_ID AND V1895.PARAM_ID = 1895 AND V1895.IS_DEL = 0 AND V1895.LISTVAL_ID = 10981
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$MON_ID, :V$DT;

  SELECT FIRST 1 L238.OBJ_ID, L238.DATE_INS
  FROM LINKS L2
  JOIN LINKS L238 ON L238.PARENT_ID = L2.OBJ_ID AND L238.OBJ_TYPE_ID = 238 AND L238.DATE_DEL IS NULL
  JOIN VALL V1895 ON V1895.OBJ_ID = L238.OBJ_ID AND V1895.PARAM_ID = 1895 AND V1895.IS_DEL = 0 AND V1895.LISTVAL_ID = 10980
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$MON2020_ID, :V$DTOLD;

  IF(V$MON_ID IS NOT NULL) THEN
  BEGIN
    IF(V$MON2020_ID IS NOT NULL) THEN
    BEGIN
      -- Удаляем новый
      DELETE FROM LINKS
      WHERE OBJ_ID = :V$MON_ID;
      DELETE FROM OBJECTS
      WHERE OBJ_ID = :V$MON_ID;
    END
    ELSE IF(V$DT < '01.01.2022') THEN
    BEGIN
      -- Просто переименовываем
      UPDATE VALL
      SET LISTVAL_ID = 10980
      WHERE OBJ_ID = :V$MON_ID AND PARAM_ID = 1895;
    END
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIXER_YEAR_IN_FINALMARK
AS
declare variable V$DT date;
declare variable V$Y smallint;
declare variable V$YEAR_ID bigint;
declare variable V$YEAR_VAL varchar(100);
declare variable V$YEARVALM_ID bigint;
declare variable V$DATEVALM_MODIFY timestamp;
declare variable V$DATE_BEGIN_VALM date;
BEGIN
    UPDATE RDB$TRIGGERS TRG
    SET TRG.RDB$TRIGGER_INACTIVE = 1
    WHERE TRG.RDB$TRIGGER_NAME = 'VALM_BU';

    FOR
        SELECT V.YEAR_ID, V.DATE_MODIFY
        FROM VALM V
        INTO :V$YEARVALM_ID, :V$DATEVALM_MODIFY
        AS CURSOR TCUR
    DO
    BEGIN
        V$DT = null;
        V$Y = EXTRACT(YEAR FROM V$DATEVALM_MODIFY);
        V$DT = '31.08.' || V$Y;
    
        IF (V$DATEVALM_MODIFY < V$DT) THEN
        BEGIN
            V$YEAR_VAL = (V$Y - 1) || '-' || V$Y;
        END
        ELSE
        BEGIN
            V$YEAR_VAL = V$Y || '-' ||(V$Y + 1);
        END
    
        SELECT FIRST 1
               LV.LISTVAL_ID
                
        FROM LISTVALS LV
    
        JOIN RES R
        ON R.RES_ID = LV.RES_ID
        AND R.LANG_CODE = 'RU'
    
        WHERE LV.LIST_ID = 29
        AND R.VAL LIKE :V$YEAR_VAL
    
        INTO :V$YEAR_ID;

        SELECT LV.TAG
            
        FROM LISTVALS LV
    
        JOIN RES R
        ON R.RES_ID = LV.RES_ID
        AND R.LANG_CODE = 'RU'
    
        WHERE LV.LIST_ID = 29
        AND LV.LISTVAL_ID = :V$YEARVALM_ID
        INTO :V$DATE_BEGIN_VALM;

        IF (V$DATE_BEGIN_VALM > V$DATEVALM_MODIFY) THEN
        BEGIN
            UPDATE VALM SET YEAR_ID = :V$YEAR_ID WHERE CURRENT OF TCUR;
        END
    END

    UPDATE RDB$TRIGGERS TRG
    SET TRG.RDB$TRIGGER_INACTIVE = 0
    WHERE TRG.RDB$TRIGGER_NAME = 'VALM_BU';
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIX_CALC_JOB_PARAMS RETURNS (
    VAL VARCHAR(400))
AS
DECLARE VARIABLE V$ID BIGINT;
DECLARE VARIABLE V$CAP VARCHAR(400);
DECLARE VARIABLE V$IS_TEACHER SMALLINT;
DECLARE VARIABLE V$IS_VALID SMALLINT;
DECLARE VARIABLE S VARCHAR(10);
DECLARE VARIABLE V$BLOB_ID BIGINT;
begin
  -- все должности ОУ и подразделений
  FOR
    SELECT DISTINCT L13.OBJ_ID, JB.SCAPTION, PD.VAL
    FROM LINKS L13
    LEFT JOIN OBJECT_CAPTION_GET(L13.OBJ_ID) JB ON 1 = 1
    LEFT JOIN DO_FUNC(L13.OBJ_ID, 400) PD ON 1 = 1
    WHERE L13.PARENT_TYPE_ID IN (2, 211) AND L13.OBJ_TYPE_ID = 13 AND L13.DATE_DEL IS NULL
    INTO :V$ID, :V$CAP, :S
  DO
  BEGIN
    UPDATE OR INSERT INTO VALL (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, LISTVAL_ID)
    VALUES (400, :V$ID, NULL, 0, IIF(:S = 'Да', 2, 3));
    VAL = 'Должность ' || V$CAP || ', является педагогической = ' || COALESCE(S, 'null');
    SUSPEND;
  END

  -- все назначения на должность
 FOR
    SELECT L15.OBJ_ID, JB.SCAPTION, PD.VAL
    FROM LINKS L15
    JOIN LINKS L13 ON L13.OBJ_ID = L15.OBJ_ID AND L13.PARENT_TYPE_ID = 13 AND L13.DATE_DEL IS NULL
    JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0 AND V73.VAL <= CURRENT_DATE
    LEFT JOIN OBJECT_CAPTION_GET(L13.PARENT_ID) JB ON 1 = 1
    LEFT JOIN DO_FUNC(L15.OBJ_ID, 2444) PD ON 1 = 1
    WHERE L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL AND L15.PARENT_TYPE_ID = 14
    INTO :V$ID, :V$CAP, :S
  DO
  BEGIN
    UPDATE OR INSERT INTO VALL (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, LISTVAL_ID)
    VALUES (2444, :V$ID, NULL, 0, IIF(:S = 'Да', 2, 3));
    VAL = 'Назначение на должность ' || V$CAP || ', признак педагогичности = ' || COALESCE(S, 'null');
    SUSPEND;
  END

  -- все сотрудники
  FOR
    SELECT DISTINCT L14.OBJ_ID
    FROM LINKS L14
    WHERE L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL AND L14.PARENT_TYPE_ID IN (2, 211, 84)
    INTO :V$ID
  DO
  BEGIN
    SELECT VALID, X FROM IS_TEACHER(:V$ID) INTO :V$IS_VALID, :V$IS_TEACHER;

    IF (V$IS_VALID = 1) THEN
    BEGIN
      UPDATE OR INSERT INTO VALL (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, LISTVAL_ID)
      VALUES (988, :V$ID, NULL, 0, IIF(:V$IS_TEACHER = 1, 2, 3));
      VAL = 'Сотрудник ' || V$ID || ', является педагогом = ' || V$IS_TEACHER;
    END
    SUSPEND;
  END
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIX_CJ2_DUPLICATES
AS
declare variable V$CONTROL_ID bigint;
declare variable V$STUDENT_ID bigint;
declare variable V$MARK_ID bigint;
declare variable N integer;
begin

  FOR
      SELECT M.CONTROL_ID, M.STUDENT_ID, COUNT(*)
      FROM CJ2_MARK M
      WHERE M.DATE_DEL IS NULL
      GROUP BY 1, 2
      HAVING COUNT(*) > 1
      INTO :V$CONTROL_ID, :V$STUDENT_ID, N
  DO
  BEGIN

      SELECT FIRST 1 M.MARK_ID
      FROM CJ2_MARK M
      WHERE M.CONTROL_ID = :V$CONTROL_ID AND M.STUDENT_ID = :V$STUDENT_ID AND M.DATE_DEL IS NULL
      ORDER BY M.DATE_ADD DESC
      INTO :V$MARK_ID;

      UPDATE CJ2_MARK M
      SET M.DATE_DEL = CURRENT_TIMESTAMP
      WHERE M.CONTROL_ID = :V$CONTROL_ID AND M.STUDENT_ID = :V$STUDENT_ID AND M.DATE_DEL IS NULL AND M.MARK_ID <> :V$MARK_ID;

  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIX_CJ2_LESSON_TIME
AS
DECLARE VARIABLE V$YEAR_ID BIGINT;
DECLARE VARIABLE V$CJ_ID BIGINT;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$DATE DATE;
DECLARE VARIABLE V$NUM INTEGER;
DECLARE VARIABLE V$TIME TIME;
DECLARE VARIABLE V$SCH_ID BIGINT;
DECLARE VARIABLE TH VARCHAR(2);
DECLARE VARIABLE TM VARCHAR(2);
DECLARE VARIABLE V$TYPE_ID BIGINT;
begin

  SELECT V1236.LISTVAL_ID
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$YEAR_ID;

  FOR
    SELECT J.OBJ_ID
    FROM CJ2_JOURNAL J
    WHERE J.DATE_DEL IS NULL
    INTO :V$CJ_ID
  DO
  BEGIN
    -- Уроки
    FOR
      SELECT L.OBJ_ID, L.LESSON_DATE, L.LESSON_NUM
      FROM CJ2_JOURNAL_LESSONS L
      WHERE L.DATE_DEL IS NULL AND L.CJ_ID = :V$CJ_ID AND L.LESSON_TIME IS NULL
      ORDER BY 1
      INTO :V$OBJ_ID, :V$DATE, :V$NUM
    DO
    BEGIN
      IF(V$NUM < 0) THEN V$NUM = 1;
      IF(V$NUM >= 1440) THEN V$NUM = 1;

      IF(V$NUM > 60) THEN
      BEGIN
        TH = TRUNC(V$NUM / 60);
        IF(CHAR_LENGTH(TH) < 2) THEN TH = '0' || TH;
        TM = V$NUM - TRUNC(V$NUM / 60) * 60;
        IF(CHAR_LENGTH(TM) < 2) THEN TM = '0' || TM;
        V$TIME = TH || ':' || TM;
      END
      ELSE
      BEGIN
        -- Ищем подходящий шаблон расписания
        SELECT FIRST 1 SI.SCHEDULE_ID
        FROM SCHEDULE_ITEMS SI
        JOIN LINKS LP3 ON LP3.OBJ_ID = SI.SCHEDULE_ID AND LP3.PARENT_TYPE_ID = 3 AND LP3.DATE_DEL IS NULL
        JOIN VALD V3120 ON V3120.OBJ_ID = SI.SCHEDULE_ID AND V3120.PARAM_ID = 3120 AND V3120.IS_DEL = 0 AND V3120.VAL <= :V$DATE
        JOIN VALD V3121 ON V3121.OBJ_ID = SI.SCHEDULE_ID AND V3121.PARAM_ID = 3121 AND V3121.IS_DEL = 0 AND V3121.VAL >= :V$DATE
        WHERE SI.DATE_DEL IS NULL AND SI.CJ_ID = :V$CJ_ID
        INTO :V$SCH_ID;

        -- Если нет расписания где упомянут данный журнал, ищем первый попавшийся
        IF(V$SCH_ID IS NULL) THEN
        SELECT FIRST 1 L59.OBJ_ID
        FROM LINKS L68
        JOIN LINKS L3 ON L3.PARENT_ID = L68.OBJ_ID AND L3.OBJ_TYPE_ID = 3 AND L3.DATE_DEL IS NULL
        JOIN VALL V37 ON V37.OBJ_ID = L3.OBJ_ID AND V37.PARAM_ID = 37 AND V37.IS_DEL = 0 AND V37.LISTVAL_ID = :V$YEAR_ID
        JOIN LINKS L59 ON L59.PARENT_ID = L3.OBJ_ID AND L59.OBJ_TYPE_ID = 59 AND L59.DATE_DEL IS NULL
        JOIN VALL V1341 ON V1341.OBJ_ID = L59.OBJ_ID AND V1341.PARAM_ID = 1341 AND V1341.IS_DEL = 0 AND V1341.LISTVAL_ID = 2
        JOIN VALD V3120 ON V3120.OBJ_ID = L59.OBJ_ID AND V3120.PARAM_ID = 3120 AND V3120.IS_DEL = 0 AND V3120.VAL <= :V$DATE
        JOIN VALD V3121 ON V3121.OBJ_ID = L59.OBJ_ID AND V3121.PARAM_ID = 3121 AND V3121.IS_DEL = 0 AND V3121.VAL >= :V$DATE
        WHERE L68.PARENT_TYPE_ID = 2 AND L68.OBJ_TYPE_ID = 68 AND L68.DATE_DEL IS NULL
        INTO :V$SCH_ID;

        V$TIME = NULL;
        SELECT FIRST 1 V405.VAL
        FROM LINKS L60
        JOIN VALI V404 ON V404.OBJ_ID = L60.OBJ_ID AND V404.PARAM_ID = 404 AND V404.IS_DEL = 0 AND V404.VAL = :V$NUM
        JOIN VALT V405 ON V405.OBJ_ID = L60.OBJ_ID AND V405.PARAM_ID = 405 AND V405.IS_DEL = 0
        WHERE L60.PARENT_ID = :V$SCH_ID AND L60.OBJ_TYPE_ID = 60 AND L60.DATE_DEL IS NULL
        INTO :V$TIME;
      END

      UPDATE CJ2_JOURNAL_LESSONS
      SET LESSON_TIME = :V$TIME
      WHERE OBJ_ID = :V$OBJ_ID;
    END

    -- Расписание занятий - битые записиь, внесенные в неверной версии
    -- день недели пофиг, смотрим всегда первый попавшийся шаблон
    FOR
      SELECT SI.OBJ_ID, SI.LESSON_NUM, SI.SCHEDULE_ID, OBJ.TYPE_ID
      FROM SCHEDULE_ITEMS SI
      JOIN OBJECTS OBJ ON OBJ.OBJ_ID = SI.SCHEDULE_ID
      WHERE SI.DATE_DEL IS NULL AND SI.LESSON_TIME IS NULL AND SI.CJ_ID = :V$CJ_ID
      ORDER BY 1
      INTO :V$OBJ_ID, :V$NUM, :V$SCH_ID, :V$TYPE_ID
    DO
    BEGIN
      V$TIME = NULL;
      IF(V$NUM < 0) THEN V$NUM = 1;
      IF(V$NUM >= 1440) THEN V$NUM = 1;

      -- Время явно задано ?
      IF(V$NUM > 60) THEN
      BEGIN
        TH = TRUNC(V$NUM / 60);
        IF(CHAR_LENGTH(TH) < 2) THEN TH = '0' || TH;
        TM = V$NUM - TRUNC(V$NUM / 60) * 60;
        IF(CHAR_LENGTH(TM) < 2) THEN TM = '0' || TM;
        V$TIME = TH || ':' || TM;
      END
      -- Шаблон ?
      ELSE IF(V$TYPE_ID = 59) THEN
      BEGIN
        SELECT FIRST 1 V405.VAL
        FROM LINKS L60
        JOIN VALI V404 ON V404.OBJ_ID = L60.OBJ_ID AND V404.PARAM_ID = 404 AND V404.IS_DEL = 0 AND V404.VAL = :V$NUM
        JOIN VALT V405 ON V405.OBJ_ID = L60.OBJ_ID AND V405.PARAM_ID = 405 AND V405.IS_DEL = 0
        WHERE L60.PARENT_ID = :V$SCH_ID AND L60.OBJ_TYPE_ID = 60 AND L60.DATE_DEL IS NULL
        INTO :V$TIME;
      END
      -- Лента ?
      ELSE IF(V$TYPE_ID = 3) THEN
      BEGIN
        SELECT FIRST 1 V405.VAL
        FROM LINKS L59
        JOIN LINKS L60 ON L60.PARENT_ID = L59.OBJ_ID AND L60.OBJ_TYPE_ID = 60 AND L60.DATE_DEL IS NULL
        JOIN VALI V404 ON V404.OBJ_ID = L60.OBJ_ID AND V404.PARAM_ID = 404 AND V404.IS_DEL = 0 AND V404.VAL = :V$NUM
        JOIN VALT V405 ON V405.OBJ_ID = L60.OBJ_ID AND V405.PARAM_ID = 405 AND V405.IS_DEL = 0
        WHERE L59.PARENT_ID = :V$SCH_ID AND L59.OBJ_TYPE_ID = 59 AND L59.DATE_DEL IS NULL
        INTO :V$TIME;
      END

      IF(V$TIME IS NOT NULL) THEN
      UPDATE SCHEDULE_ITEMS
      SET LESSON_TIME = :V$TIME
      WHERE OBJ_ID = :V$OBJ_ID;
    END

    -- Лента расписания
    FOR
      SELECT L.OBJ_ID, L.LESSON_NUM, JL.LESSON_TIME
      FROM CJ2_MS_LESSONS L
      LEFT JOIN CJ2_JOURNAL_LESSONS JL ON JL.MS_ID = L.OBJ_ID
      WHERE L.DATE_DEL IS NULL AND L.CJ_ID = :V$CJ_ID AND L.LESSON_TIME IS NULL
      ORDER BY 1
      INTO :V$OBJ_ID, :V$NUM, :V$TIME
    DO
    BEGIN
      IF(V$NUM < 0) THEN V$NUM = 1;
      IF(V$NUM >= 1440) THEN V$NUM = 1;

      -- Если время уже посчиталось в реальном уроке, ставим его же
      IF(V$TIME IS NULL) THEN
      BEGIN
        IF(V$NUM > 60) THEN
        BEGIN
          TH = TRUNC(V$NUM / 60);
          IF(CHAR_LENGTH(TH) < 2) THEN TH = '0' || TH;
          TM = V$NUM - TRUNC(V$NUM / 60) * 60;
          IF(CHAR_LENGTH(TM) < 2) THEN TM = '0' || TM;
          V$TIME = TH || ':' || TM;
        END
        ELSE
        BEGIN
          -- Ищем подходящий шаблон расписания
          SELECT FIRST 1 SI.SCHEDULE_ID
          FROM SCHEDULE_ITEMS SI
          JOIN LINKS LP3 ON LP3.OBJ_ID = SI.SCHEDULE_ID AND LP3.PARENT_TYPE_ID = 3 AND LP3.DATE_DEL IS NULL
          -- JOIN VALD V3120 ON V3120.OBJ_ID = SI.SCHEDULE_ID AND V3120.PARAM_ID = 3120 AND V3120.IS_DEL = 0 AND V3120.VAL <= :V$DATE
          -- JOIN VALD V3121 ON V3121.OBJ_ID = SI.SCHEDULE_ID AND V3121.PARAM_ID = 3121 AND V3121.IS_DEL = 0 AND V3121.VAL >= :V$DATE
          WHERE SI.DATE_DEL IS NULL AND SI.CJ_ID = :V$CJ_ID
          INTO :V$SCH_ID;

          -- Если нет расписания где упомянут данный журнал, ищем первый попавшийся
          IF(V$SCH_ID IS NULL) THEN
          SELECT FIRST 1 L59.OBJ_ID
          FROM LINKS L68
          JOIN LINKS L3 ON L3.PARENT_ID = L68.OBJ_ID AND L3.OBJ_TYPE_ID = 3 AND L3.DATE_DEL IS NULL
          JOIN VALL V37 ON V37.OBJ_ID = L3.OBJ_ID AND V37.PARAM_ID = 37 AND V37.IS_DEL = 0 AND V37.LISTVAL_ID = :V$YEAR_ID
          JOIN LINKS L59 ON L59.PARENT_ID = L3.OBJ_ID AND L59.OBJ_TYPE_ID = 59 AND L59.DATE_DEL IS NULL
          JOIN VALL V1341 ON V1341.OBJ_ID = L59.OBJ_ID AND V1341.PARAM_ID = 1341 AND V1341.IS_DEL = 0 AND V1341.LISTVAL_ID = 2
          -- JOIN VALD V3120 ON V3120.OBJ_ID = L59.OBJ_ID AND V3120.PARAM_ID = 3120 AND V3120.IS_DEL = 0 AND V3120.VAL <= :V$DATE
          -- JOIN VALD V3121 ON V3121.OBJ_ID = L59.OBJ_ID AND V3121.PARAM_ID = 3121 AND V3121.IS_DEL = 0 AND V3121.VAL >= :V$DATE
          WHERE L68.PARENT_TYPE_ID = 2 AND L68.OBJ_TYPE_ID = 68 AND L68.DATE_DEL IS NULL
          INTO :V$SCH_ID;

          SELECT FIRST 1 V405.VAL
          FROM LINKS L60
          JOIN VALI V404 ON V404.OBJ_ID = L60.OBJ_ID AND V404.PARAM_ID = 404 AND V404.IS_DEL = 0 AND V404.VAL = :V$NUM
          JOIN VALT V405 ON V405.OBJ_ID = L60.OBJ_ID AND V405.PARAM_ID = 405 AND V405.IS_DEL = 0
          WHERE L60.PARENT_ID = :V$SCH_ID AND L60.OBJ_TYPE_ID = 60 AND L60.DATE_DEL IS NULL
          INTO :V$TIME;
        END
      END

      IF(V$TIME IS NOT NULL) THEN
      UPDATE CJ2_MS_LESSONS
      SET LESSON_TIME = :V$TIME
      WHERE OBJ_ID = :V$OBJ_ID;
    END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIX_DC_TASKS
AS
DECLARE VARIABLE CNT INTEGER;
DECLARE VARIABLE OBJ_ID BIGINT;
begin

  -- Удаляем задачу выгрузки старого портала - уже неактуально, это уже другая задача
  -- DELETE FROM DC_TASKS WHERE TASK_REF = 'paragraf.dnevnik:portal';

  -- Добавляем задачу для нового портала
  SELECT COUNT(*) FROM DC_TASKS WHERE ID = 1 INTO :CNT;

  IF(CNT = 0) THEN
  BEGIN
    -- На второй адрес пока забили
    INSERT INTO DC_TASKS
    (ID, TASK_NAME, TASK_REF, TASK_TIMING, TASK_ENABLED, TASK_METHOD, RESTORE_MISSED, MISS_METHOD, TASKPARAMS)
    VALUES (1, 'Дневник2018', 'paragraf.dnevnik2018:portal', 'КАЖДЫЕ 20 МИНУТ', 0, '@', 0, 0, 'uri=https://10.146.141.78/api/eduws');
  END

  -- Переносим флаг разрешения в системную задачу
  FOR
    SELECT ID, TASK_ENABLED
    FROM DC_TASKS
    WHERE TASK_REF = 'paragraf.dnevnik2018:portal' AND ID <> 1
    INTO :OBJ_ID, :CNT
  DO
  BEGIN
    UPDATE DC_TASKS SET TASK_ENABLED = :CNT WHERE ID = 1;
  END

  -- Сносим все старые задачи, созданные вручную
  DELETE FROM DC_TASKS WHERE TASK_REF = 'paragraf.dnevnik2018:portal' AND ID <> 1;

  -- Обновляем задачу дневника
  UPDATE DC_TASKS
  SET TASKPARAMS = REPLACE(TASKPARAMS, 'dnevnik2.petersburgedu.ru', '10.146.141.78')
  WHERE TASK_REF = 'paragraf.dnevnik2018:portal';

  -- Обновляем задачу ОД
  UPDATE DC_TASKS
  SET TASKPARAMS = REPLACE(TASKPARAMS, 'olimp.kobr.gov.spb.ru', '10.146.138.175')
  WHERE TASK_REF = 'paragraf.od:olympic';

  -- Обновляем задачу СОП
  UPDATE DC_TASKS
  SET TASKPARAMS = REPLACE(TASKPARAMS, '100.127.255.6:8080', '10.178.208.27')
  WHERE TASK_REF = 'food_benefits:default';

  -- Выставляем принудительно тайминг в задаче МояШкола
  -- Смотри FIXER5

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIX_DC_TASKS_DOU
AS
DECLARE VARIABLE V$ID BIGINT;
DECLARE VARIABLE V$EN SMALLINT;
DECLARE VARIABLE V$PT BIGINT;
DECLARE VARIABLE V VARCHAR(400);
DECLARE VARIABLE PV VARCHAR(400);
begin

  -- Задачу прописываем только после создания лицензии
  SELECT FIRST 1 V8.LISTVAL_ID
  FROM LINKS L2
  JOIN VALL V8 ON V8.OBJ_ID = L2.OBJ_ID AND V8.PARAM_ID = 8 AND V8.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$PT;

  SELECT FIRST 1 T.ID, T.TASK_ENABLED, T.TASKPARAMS
  FROM DC_TASKS T
  WHERE T.TASK_REF = 'paragraf.rks:update'
  INTO :V$ID, :V$EN, :PV;

  -- Пока не задана форма - ничего не делаем
  IF(V$PT IS NULL) THEN EXIT;

  -- По указанию РЦОКО сделана замена адреса на stat.online.petersburgedu.ru
  -- Сама синхронизация DataID по этому адресу пройти не может, но требуется для работы статистики
  -- V = 'uri=http://10.146.143.33/';
  V = 'uri=https://stat.online.petersburgedu.ru/';

  IF(V$PT IN (5404, 5415)) THEN
  BEGIN
    IF(V$ID IS NOT NULL) THEN
    BEGIN
      DELETE FROM DC_TASKS WHERE ID = :V$ID;
    END
  END
  ELSE IF(V$ID IS NULL) THEN
  BEGIN
    INSERT INTO DC_TASKS
    (TASK_NAME, TASK_REF, TASK_TIMING, TASK_ENABLED, TASK_METHOD, RESTORE_MISSED, MISS_METHOD, TASKPARAMS)
    VALUES ('DataID', 'paragraf.rks:update', 'КАЖДЫЕ СУТКИ', 0, '@', 0, 0, :V);
  END
  ELSE IF(V$EN = 0 OR PV IS NULL OR POSITION('stat.online' IN PV) <= 0) THEN
  BEGIN
    UPDATE DC_TASKS
    SET TASK_ENABLED = 1, TASKPARAMS = :V
    WHERE ID = :V$ID;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIX_DEMO_EXAM_FORMAT
AS
begin

  INSERT INTO VALF
  (OBJ_ID, PARAM_ID, VAL, IS_REPL, IS_DEL, USER_ID, DATE_MODIFY)
  SELECT OBJ_ID, PARAM_ID, VAL, IS_REPL, IS_DEL, USER_ID, DATE_MODIFY
  FROM VALI
  WHERE PARAM_ID = 3341;

  DELETE FROM VALI
  WHERE PARAM_ID = 3341;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIX_DOU_GUP
AS
declare variable V$OBJ_ID bigint;
begin

  -- Отмечаем незакрытые записи движения как удаленные
  FOR
    SELECT M.OBJ_ID
    FROM PERSON_MOVEMENTS M
    JOIN LINKS LP8X ON LP8X.OBJ_ID = M.PERSON_ID AND LP8X.PARENT_TYPE_ID IN (81, 82, 83) AND LP8X.DATE_DEL IS NULL
    LEFT JOIN LINKS LP9 ON LP9.OBJ_ID = M.PERSON_ID AND LP9.PARENT_TYPE_ID IN (9, 290) AND LP9.DATE_DEL IS NULL
    WHERE M.DATE_DEL IS NULL AND M.DATE_OUT IS NULL AND M.GROUP_TYPE_ID = 9 AND LP9.LINK_ID IS NULL AND M.DATE_IN < '2023-06-01'
    ORDER BY 1
    INTO :V$OBJ_ID
  DO
  BEGIN
    UPDATE PERSON_MOVEMENTS
    SET DATE_DEL = '2024-01-01'
    WHERE OBJ_ID = :V$OBJ_ID;
  END

  -- Удаляем движение для учеников, которые оказались нигде
  FOR
    SELECT M.OBJ_ID
    FROM PERSON_MOVEMENTS M
    LEFT JOIN LINKS LP ON LP.OBJ_ID = M.PERSON_ID AND LP.PARENT_TYPE_ID IN (9, 290, 81, 82, 83) AND LP.DATE_DEL IS NULL
    WHERE M.DATE_DEL IS NULL AND M.DATE_OUT IS NULL AND M.GROUP_TYPE_ID = 9 AND LP.LINK_ID IS NULL
    ORDER BY 1
    INTO :V$OBJ_ID
  DO
  BEGIN
    UPDATE PERSON_MOVEMENTS
    SET DATE_DEL = '2024-01-02'
    WHERE OBJ_ID = :V$OBJ_ID;
  END

  -- Удаляем движение ГУП прошлых лет - совсем
  FOR
    SELECT M.OBJ_ID
    FROM PERSON_MOVEMENTS M
    WHERE M.DATE_DEL IS NULL AND M.GROUP_TYPE_ID = 256 AND M.DATE_IN < '2024-01-01'
    ORDER BY 1
    INTO :V$OBJ_ID
  DO
  BEGIN
    UPDATE PERSON_MOVEMENTS
    SET DATE_DEL = '2024-01-03'
    WHERE OBJ_ID = :V$OBJ_ID;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIX_DOU_LEAVES
AS
declare variable V$FOLDER_ID bigint;
declare variable V$YEAR_ID bigint;
declare variable V$ALT_ID bigint;
begin

  FOR
    SELECT L83.OBJ_ID, V451.VAL
    FROM LINKS L83
    JOIN VALL V450 ON V450.OBJ_ID = L83.OBJ_ID AND V450.PARAM_ID = 450 AND V450.IS_DEL = 0 AND V450.LISTVAL_ID = 900
    JOIN VALI V451 ON V451.OBJ_ID = L83.OBJ_ID AND V451.PARAM_ID = 451 AND V451.IS_DEL = 0
    WHERE L83.PARENT_TYPE_ID = 78 AND L83.OBJ_TYPE_ID = 83 AND L83.DATE_DEL IS NULL
    ORDER BY 1
    INTO :V$FOLDER_ID, :V$YEAR_ID
  DO
  BEGIN
    -- Если никого нет - просто удаляем
    IF(NOT EXISTS(
      SELECT FIRST 1 1
      FROM LINKS L10
      WHERE L10.PARENT_ID = :V$FOLDER_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    )) THEN
    BEGIN
      UPDATE LINKS
      SET DATE_DEL = CURRENT_TIMESTAMP
      WHERE OBJ_ID = :V$FOLDER_ID;
    END
    -- Есть ученики
    ELSE
    BEGIN
      -- Ищем такую же папку выпуск ДОУ
      V$ALT_ID = NULL;
      SELECT FIRST 1 1
      FROM LINKS L83
      JOIN VALL V450 ON V450.OBJ_ID = L83.OBJ_ID AND V450.PARAM_ID = 450 AND V450.IS_DEL = 0 AND V450.LISTVAL_ID = 3320
      JOIN VALI V451 ON V451.OBJ_ID = L83.OBJ_ID AND V451.PARAM_ID = 451 AND V451.IS_DEL = 0 AND V451.VAL = :V$YEAR_ID
      WHERE L83.PARENT_TYPE_ID = 78 AND L83.OBJ_TYPE_ID = 83 AND L83.DATE_DEL IS NULL
      INTO :V$ALT_ID;

      IF(V$ALT_ID IS NULL) THEN
      BEGIN
        -- Выпуска ДОУ нет, переименовываем себя
        UPDATE VALL
        SET LISTVAL_ID = 3320
        WHERE OBJ_ID = :V$FOLDER_ID;
      END
      ELSE
      BEGIN
        -- Выпуск ДОУ есть, переносим учеников
        UPDATE LINKS
        SET PARENT_ID = :V$ALT_ID
        WHERE PARENT_ID = :V$FOLDER_ID AND OBJ_TYPE_ID = 10 AND DATE_DEL IS NULL;
        -- Удаляем старую папку
        UPDATE LINKS
        SET DATE_DEL = CURRENT_TIMESTAMP
        WHERE OBJ_ID = :V$FOLDER_ID;
      END
    END

  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIX_DUPLICATES
AS
declare variable PARENT_ID bigint;
declare variable OBJ_ID bigint;
declare variable C integer;
declare variable LINK_ID bigint;
begin

  FOR
      SELECT PARENT_ID, OBJ_ID, COUNT(*)
      FROM LINKS
      WHERE DATE_DEL IS NULL
      GROUP BY 1, 2
      HAVING COUNT(*) > 1
      INTO :PARENT_ID, :OBJ_ID, :C
  DO
  BEGIN

      -- Удаляем нужное количество записей, кроме самой первой
      FOR
          SELECT FIRST (:C - 1) LINK_ID
          FROM LINKS
          WHERE PARENT_ID = :PARENT_ID AND OBJ_ID = :OBJ_ID AND DATE_DEL IS NULL
          ORDER BY LINK_ID DESC
          INTO :LINK_ID
      DO
      BEGIN
          DELETE FROM LINKS WHERE LINK_ID = :LINK_ID;
      END

  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIX_EMPLOYEES_SNILS RETURNS (
    OLD_SNILS VARCHAR(100),
    NEW_SNILS VARCHAR(100))
AS
declare variable V$PERSON_ID bigint;
declare variable V$SNILS varchar(100);
declare variable V$RAW_SNILS varchar(100);
declare variable TMP bigint;
declare variable V$CHANGE smallint;
declare variable V$DOC_ID bigint;
declare variable S varchar(100);
declare variable V$EQ smallint;
begin

  FOR
      --- Основные работники
      SELECT L14.OBJ_ID
      FROM LINKS L2
      JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
      -- LEFT JOIN VALS V2455 ON V2455.OBJ_ID = L14.OBJ_ID AND V2455.PARAM_ID = 2455 AND V2455.IS_DEL = 0
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL -- AND V2455.VAL IS NULL
      UNION
      -- Из подразделений
      SELECT L14.OBJ_ID
      FROM LINKS L2
      JOIN LINKS L211 ON L211.PARENT_ID = L2.OBJ_ID AND L211.OBJ_TYPE_ID = 211 AND L211.DATE_DEL IS NULL
      JOIN LINKS L14 ON L14.PARENT_ID = L211.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
      -- LEFT JOIN VALS V2455 ON V2455.OBJ_ID = L14.OBJ_ID AND V2455.PARAM_ID = 2455 AND V2455.IS_DEL = 0
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL -- AND V2455.VAL IS NULL
      UNION
      -- Уволенные
      SELECT L14.OBJ_ID
      FROM LINKS L2
      JOIN LINKS L84 ON L84.PARENT_ID = L2.OBJ_ID AND L84.OBJ_TYPE_ID = 84 AND L84.DATE_DEL IS NULL
      JOIN LINKS L14 ON L14.PARENT_ID = L84.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
      -- LEFT JOIN VALS V2455 ON V2455.OBJ_ID = L14.OBJ_ID AND V2455.PARAM_ID = 2455 AND V2455.IS_DEL = 0
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL -- AND V2455.VAL IS NULL
      INTO :V$PERSON_ID
  DO
  BEGIN

      V$SNILS = NULL;
      V$RAW_SNILS = NULL;
      V$DOC_ID = NULL;

      -- Смотрим в прямо в карточке
      SELECT FIRST 1 V2455.VAL
      FROM VALS V2455
      WHERE V2455.OBJ_ID = :V$PERSON_ID AND V2455.PARAM_ID = 2455 AND V2455.IS_DEL = 0
      INTO :V$RAW_SNILS;

      -- Смотрим из документов
      SELECT FIRST 1 V571.VAL, L12.OBJ_ID
      FROM LINKS L12
      JOIN VALL V51 ON V51.OBJ_ID = L12.OBJ_ID AND V51.PARAM_ID = 51 AND V51.IS_DEL = 0 AND V51.LISTVAL_ID = 1384
      JOIN VALS V571 ON V571.OBJ_ID = L12.OBJ_ID AND V571.PARAM_ID = 571 AND V571.IS_DEL = 0
      -- Пропускаем истекшие
      LEFT JOIN VALD V573 ON V573.OBJ_ID = L12.OBJ_ID AND V573.PARAM_ID = 573 AND V573.IS_DEL = 0
      WHERE L12.PARENT_ID = :V$PERSON_ID AND L12.OBJ_TYPE_ID = 12 AND L12.DATE_DEL IS NULL AND V573.VAL IS NULL
      INTO :V$SNILS, :V$DOC_ID;

      IF(V$SNILS IS NULL AND V$RAW_SNILS IS NULL) THEN
      BEGIN
          -- Вообще ничего не заполнено, пусть сами разбираются
      END
      ELSE IF(V$RAW_SNILS IS NOT NULL) THEN
      BEGIN
          -- Заполнен СНИЛС в карточке
          -- Если в документе тоже внесен и совпадает с карточкой - обновляем синхронно
          V$CHANGE = 0;
          V$EQ = 0;
          IF(V$SNILS IS NOT NULL AND REPLACE(REPLACE(V$RAW_SNILS, '-', ''), ' ', '') = REPLACE(REPLACE(V$SNILS, '-', ''), ' ', '')) THEN V$EQ = 1;
          IF(V$EQ = 1 AND V$SNILS <> V$RAW_SNILS) THEN V$CHANGE = 1;

          OLD_SNILS = V$RAW_SNILS || COALESCE(' / ' || V$SNILS, '');

          -- Убираем лишние пробелы и двойные пробелы
          S = TRIM(V$RAW_SNILS);
          S = REPLACE(S, '  ', '');
          IF(S <> V$RAW_SNILS) THEN
          BEGIN
              V$RAW_SNILS = S;
              V$CHANGE = 1;
          END
          IF(CHAR_LENGTH(V$RAW_SNILS) = 11) THEN
          BEGIN
              -- Внесен без форматирования ?
              -- Пробуем отформатировать и обновить
              V$CHANGE = 1;
              V$RAW_SNILS = SUBSTRING(V$RAW_SNILS FROM 1 FOR 3) || '-' || SUBSTRING(V$RAW_SNILS FROM 4 FOR 3) || '-' ||
                  SUBSTRING(V$RAW_SNILS FROM 7 FOR 3) || ' ' || SUBSTRING(V$RAW_SNILS FROM 10);
          END
          ELSE IF(CHAR_LENGTH(V$RAW_SNILS) = 14 AND (SUBSTRING(V$RAW_SNILS FROM 4 FOR 1) <> '-' OR SUBSTRING(V$RAW_SNILS FROM 8 FOR 1) <> '-')
            OR SUBSTRING(V$RAW_SNILS FROM 12 FOR 1) <> ' ') THEN
          BEGIN
              -- Внесен с дефисами не по месту или пробелами вместо дефиса
              -- Пробуем отформатировать и обновить
              V$CHANGE = 1;
              V$RAW_SNILS = SUBSTRING(V$RAW_SNILS FROM 1 FOR 3) || '-' || SUBSTRING(V$RAW_SNILS FROM 5 FOR 3) || '-' ||
                  SUBSTRING(V$RAW_SNILS FROM 9 FOR 3) || ' ' || SUBSTRING(V$RAW_SNILS FROM 13);
          END

          -- Если получился валидный, и надо что-то обновлять
          IF(V$CHANGE = 1 AND (SELECT IS_REAL FROM CHECK_SNILS(:V$RAW_SNILS)) = 1) THEN
          BEGIN
              -- Сначала обновляем в документе, непосредственно в таблице
              IF(V$SNILS IS NOT NULL AND V$EQ = 1) THEN
              BEGIN
                  UPDATE VALS
                  SET VAL = :V$RAW_SNILS
                  WHERE OBJ_ID = :V$DOC_ID AND PARAM_ID = 571;
              END
              -- Обновляем в карточке, также непосредственно в таблице
              UPDATE VALS
              SET VAL = :V$RAW_SNILS
              WHERE OBJ_ID = :V$PERSON_ID AND PARAM_ID = 2455;

              NEW_SNILS = V$RAW_SNILS;
              SUSPEND;
          END
      END
      ELSE IF(V$SNILS IS NOT NULL) THEN
      BEGIN
          -- Не заполнен в карточке, но заполнен в документе
          V$CHANGE = 0;
          OLD_SNILS = V$SNILS;
          -- Убираем лишние пробелы и двойные пробелы
          S = TRIM(V$SNILS);
          S = REPLACE(S, '  ', '');
          IF(S <> V$SNILS) THEN
          BEGIN
              V$SNILS = S;
              V$CHANGE = 1;
          END
          IF(CHAR_LENGTH(V$SNILS) = 11) THEN
          BEGIN
              -- Внесен без форматирования ?
              -- Пробуем отформатировать и обновить
              V$CHANGE = 1;
              V$SNILS = SUBSTRING(V$SNILS FROM 1 FOR 3) || '-' || SUBSTRING(V$SNILS FROM 4 FOR 3) || '-' ||
                  SUBSTRING(V$SNILS FROM 7 FOR 3) || ' ' || SUBSTRING(V$SNILS FROM 10);
          END
          ELSE IF(CHAR_LENGTH(V$SNILS) = 14 AND (SUBSTRING(V$SNILS FROM 4 FOR 1) <> '-' OR SUBSTRING(V$SNILS FROM 8 FOR 1) <> '-')
            OR SUBSTRING(V$SNILS FROM 12 FOR 1) <> ' ') THEN
          BEGIN
              -- Внесен с дефисами не по месту или пробелами вместо дефиса
              -- Пробуем отформатировать и обновить
              V$CHANGE = 1;
              V$SNILS = SUBSTRING(V$SNILS FROM 1 FOR 3) || '-' || SUBSTRING(V$SNILS FROM 5 FOR 3) || '-' ||
                  SUBSTRING(V$SNILS FROM 9 FOR 3) || ' ' || SUBSTRING(V$SNILS FROM 13);
          END

          -- Если получился валидный
          IF((SELECT IS_REAL FROM CHECK_SNILS(:V$SNILS)) = 1) THEN
          BEGIN
              -- Обновляем формат прямо в таблице (если в карточке записи нет, система не даст вносить в таблице)
              IF(V$CHANGE <> 0) THEN
              BEGIN
                  UPDATE VALS
                  SET VAL = :V$SNILS
                  WHERE OBJ_ID = :V$DOC_ID AND PARAM_ID = 571;
              END
              -- Вносим в личное дело
              SELECT BLOB_ID FROM VAL_ADD(2455, :V$PERSON_ID, :V$SNILS) INTO :TMP;

              NEW_SNILS = V$SNILS;
              SUSPEND;
          END
      END

  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIX_ENTERING_PUPILS_TO_STAGE (
    I$SCHOOL_ID BIGINT)
AS
declare variable V$CLASS_ID bigint;
declare variable V$LINK_ID bigint;
declare variable V$LINK_ID2 bigint;
declare variable V$LISTVAL_ID bigint;
declare variable V$OBJ_ID bigint;
declare variable V$STAGE_ID bigint;
declare variable V$BLOB_ID bigint;
BEGIN
    V$STAGE_ID = NULL;
    FOR
        SELECT FIRST 1
               V49.LISTVAL_ID
        FROM PARAGRAF_TYPE_LEVEL(:I$SCHOOL_ID, 8, 2) O8

        JOIN VALL V49
        ON V49.OBJ_ID = O8.OBJ_ID
        AND V49.PARAM_ID = 49
        AND V49.IS_DEL = 0

        ORDER BY O8.SORT_ORDER

        INTO :V$LISTVAL_ID
    DO
    BEGIN
        SELECT FIRST 1
               L77.OBJ_ID
        FROM LINKS L77

        WHERE L77.PARENT_ID = :I$SCHOOL_ID
        AND L77.OBJ_TYPE_ID = 77
        AND L77.DATE_DEL IS NULL
        INTO :V$OBJ_ID;

        IF (V$OBJ_ID IS NULL) THEN
        BEGIN
            SELECT OBJ_ID
            FROM OBJECT_ADD(:I$SCHOOL_ID, 77)
            INTO :V$OBJ_ID;
        END
        SELECT FIRST 1
               L290.OBJ_ID
        FROM LINKS L290

        JOIN VALL V2346
        ON V2346.OBJ_ID = L290.OBJ_ID
        AND V2346.PARAM_ID = 2346
        AND V2346.IS_DEL = 0
        AND V2346.LISTVAL_ID = :V$LISTVAL_ID

        WHERE L290.PARENT_ID = :V$OBJ_ID
        AND L290.OBJ_TYPE_ID = 290
        AND L290.DATE_DEL IS NULL
        INTO :V$STAGE_ID;

        IF (V$STAGE_ID IS NULL) THEN
        BEGIN
            SELECT OBJ_ID
            FROM OBJECT_ADD(:V$OBJ_ID, 290)
            INTO :V$STAGE_ID;

            SELECT BLOB_ID
            FROM VAL_ADD(2346, :V$STAGE_ID, :V$LISTVAL_ID)
            INTO V$BLOB_ID;
        END
    END
    IF (V$STAGE_ID IS NULL) THEN
    BEGIN
        EXIT;
    END
    FOR
        SELECT L9.OBJ_ID,
               L9.LINK_ID
        FROM LINKS L77

        JOIN LINKS L9
        ON L9.PARENT_ID = L77.OBJ_ID
        AND L9.OBJ_TYPE_ID = 9
        AND L9.DATE_DEL IS NULL

        WHERE L77.PARENT_ID = :I$SCHOOL_ID
        AND L77.OBJ_TYPE_ID IN (77,218)
        AND L77.DATE_DEL IS NULL

        INTO :V$CLASS_ID,
             :V$LINK_ID2
    DO
    BEGIN
        FOR
            SELECT L10.LINK_ID
            FROM LINKS L10
            WHERE L10.PARENT_ID = :V$CLASS_ID
            AND L10.OBJ_TYPE_ID = 10
            AND L10.DATE_DEL IS NULL

            INTO :V$LINK_ID
        DO
        BEGIN
            UPDATE LINKS
            SET PARENT_ID = :V$STAGE_ID,
                PARENT_TYPE_ID = 290
            WHERE LINK_ID = :V$LINK_ID;
        END
        UPDATE LINKS
        SET DATE_DEL = CURRENT_TIMESTAMP
        WHERE LINK_ID = :V$LINK_ID2;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIX_EXTERNAT_LEAVED
AS
declare variable V$OBJ_ID bigint;
declare variable V$GROUP_ID bigint;
declare variable V$GROUP_TYPE_ID bigint;
declare variable V$DATE_OUT timestamp;
begin

  -- Актуальность потеряна

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIX_FILL_REQ_FIELDS
AS
declare variable V$OBJ_ID bigint;
declare variable V$PARAM_ID bigint;
declare variable V varchar(1000);
declare variable V1 bigint;
declare variable V2 bigint;
declare variable V3 integer;
declare variable V4 bigint;
declare variable V5 integer;
declare variable V6 bigint;
declare variable V7 bigint;
begin

  -- Заполнение полей, на которые ругается валидатор
  -- Заполнение обязательных полей по работе с журналами
  FOR
    SELECT L2.OBJ_ID, V3321.LISTVAL_ID, V3322.LISTVAL_ID, V3323.VAL, V3324.LISTVAL_ID, V3368.VAL, V3369.LISTVAL_ID, V3055.LISTVAL_ID
    FROM LINKS L2
    LEFT JOIN VALL V3321 ON V3321.OBJ_ID = L2.OBJ_ID AND V3321.PARAM_ID = 3221 AND V3321.IS_DEL = 0
    LEFT JOIN VALL V3322 ON V3322.OBJ_ID = L2.OBJ_ID AND V3322.PARAM_ID = 3222 AND V3322.IS_DEL = 0
    LEFT JOIN VALI V3323 ON V3323.OBJ_ID = L2.OBJ_ID AND V3323.PARAM_ID = 3223 AND V3323.IS_DEL = 0
    LEFT JOIN VALL V3324 ON V3324.OBJ_ID = L2.OBJ_ID AND V3324.PARAM_ID = 3224 AND V3324.IS_DEL = 0
    LEFT JOIN VALI V3368 ON V3368.OBJ_ID = L2.OBJ_ID AND V3368.PARAM_ID = 3268 AND V3368.IS_DEL = 0
    LEFT JOIN VALL V3369 ON V3369.OBJ_ID = L2.OBJ_ID AND V3369.PARAM_ID = 3269 AND V3369.IS_DEL = 0
    LEFT JOIN VALL V3055 ON V3055.OBJ_ID = L2.OBJ_ID AND V3055.PARAM_ID = 3269 AND V3055.IS_DEL = 0
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :V$OBJ_ID, :V1, :V2, :V3, :V4, :V5, V6, :V7
  DO
  BEGIN
    -- При исправлении нужно синхронизировать значения с CJ2_MARK_ADD
    IF(V1 IS NULL) THEN SELECT 1 FROM VAL_ADD(3321, :V$OBJ_ID, 3) INTO :V;
    IF(V2 IS NULL) THEN SELECT 1 FROM VAL_ADD(3322, :V$OBJ_ID, 3) INTO :V;
    IF(V3 IS NULL) THEN SELECT 1 FROM VAL_ADD(3323, :V$OBJ_ID, 21) INTO :V;
    IF(V4 IS NULL) THEN SELECT 1 FROM VAL_ADD(3324, :V$OBJ_ID, 3) INTO :V;
    IF(V5 IS NULL) THEN SELECT 1 FROM VAL_ADD(3368, :V$OBJ_ID, 0) INTO :V;
    IF(V6 IS NULL) THEN SELECT 1 FROM VAL_ADD(3369, :V$OBJ_ID, 3) INTO :V;
    IF(V7 IS NULL) THEN SELECT 1 FROM VAL_ADD(3055, :V$OBJ_ID, 3) INTO :V;
  END

  -- Заполнение обязательных полей у сотрудников
  FOR
    SELECT L14.OBJ_ID, P.PARAM_ID, COALESCE(IIF(R.VAL = '', NULL, R.VAL), P.AUTO_LISTVAL_ID)
    FROM LINKS L14
    JOIN PARAMS P ON P.TYPE_ID = L14.OBJ_TYPE_ID AND P.IS_DEL = 0 AND P.IS_REQUIRED = 1 AND P.IS_AUTO_CREATE = 1
    JOIN LPARAMS LP ON LP.PARAM_ID = P.PARAM_ID AND LP.IS_DEL = 0 AND LP.EDIT_TYPE = 1
    JOIN LEVELS L ON L.LEVEL_ID = LP.LEVEL_ID AND L.IS_DEL = 0
    JOIN TASKS T ON T.TASK_ID = L.TASK_ID AND T.IS_DEL = 0
    JOIN MODULES M ON M.MODULE_ID = T.MODULE_ID AND M.IS_DEL = 0 AND M.IS_ACTIVE = 1
    LEFT JOIN RES R ON R.RES_ID = P.AUTO_RES_ID AND R.LANG_CODE = 'RU'
    LEFT JOIN VAL_GET(L14.OBJ_ID, P.PARAM_ID) V ON 1 = 1
    WHERE L14.PARENT_TYPE_ID IN (2, 211, 84) AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL AND V.V = ''
    INTO :V$OBJ_ID, :V$PARAM_ID, :V
  DO
  BEGIN
    SELECT 1 FROM VAL_ADD(:V$PARAM_ID, :V$OBJ_ID, :V) INTO :V;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIX_FISOKO_INIT (
    I$SCHOOL_ID BIGINT)
AS
declare variable V$LIC bigint;
declare variable V$VAL varchar(10);
begin

  IF(EXISTS(
      SELECT FIRST 1 1
      FROM VALS V2951
      WHERE V2951.OBJ_ID = :I$SCHOOL_ID AND V2951.PARAM_ID = 2951 AND V2951.IS_DEL = 0
  )) THEN EXIT;

  SELECT FIRST 1 GEN
  FROM GEN
  INTO :V$LIC;

  IF(V$LIC = 203) THEN V$VAL = '3018';
  IF(V$LIC = 204) THEN V$VAL = '3021';
  IF(V$LIC = 209) THEN V$VAL = '3003';
  IF(V$LIC = 211) THEN V$VAL = '3005';
  IF(V$LIC = 212) THEN V$VAL = '3006';
  IF(V$LIC = 214) THEN V$VAL = '0010';
  IF(V$LIC = 215) THEN V$VAL = '3008';
  IF(V$LIC = 219) THEN V$VAL = '3012';
  IF(V$LIC = 222) THEN V$VAL = '3015';
  IF(V$LIC = 223) THEN V$VAL = '3016';
  IF(V$LIC = 225) THEN V$VAL = '3020';
  IF(V$LIC = 227) THEN V$VAL = '3023';
  IF(V$LIC = 229) THEN V$VAL = '3025';
  IF(V$LIC = 230) THEN V$VAL = '0026';
  IF(V$LIC = 231) THEN V$VAL = '3026';
  IF(V$LIC = 232) THEN V$VAL = '3027';
  IF(V$LIC = 239) THEN V$VAL = '3035';
  IF(V$LIC = 304) THEN V$VAL = '3042';
  IF(V$LIC = 305) THEN V$VAL = '3044';
  IF(V$LIC = 306) THEN V$VAL = '3045';
  IF(V$LIC = 307) THEN V$VAL = '3046';
  IF(V$LIC = 308) THEN V$VAL = '3047';
  IF(V$LIC = 309) THEN V$VAL = '3048';
  IF(V$LIC = 310) THEN V$VAL = '0048';
  IF(V$LIC = 311) THEN V$VAL = '3037';
  IF(V$LIC = 312) THEN V$VAL = '3049';
  IF(V$LIC = 313) THEN V$VAL = '3051';
  IF(V$LIC = 316) THEN V$VAL = '3054';
  IF(V$LIC = 317) THEN V$VAL = '3056';
  IF(V$LIC = 318) THEN V$VAL = '0037';
  IF(V$LIC = 319) THEN V$VAL = '3039';
  IF(V$LIC = 320) THEN V$VAL = '3040';
  IF(V$LIC = 325) THEN V$VAL = '3058';
  IF(V$LIC = 326) THEN V$VAL = '3043';
  IF(V$LIC = 333) THEN V$VAL = '3066';
  IF(V$LIC = 334) THEN V$VAL = '3064';
  IF(V$LIC = 335) THEN V$VAL = '6060';
  IF(V$LIC = 401) THEN V$VAL = '3069';
  IF(V$LIC = 402) THEN V$VAL = '3071';
  IF(V$LIC = 403) THEN V$VAL = '3072';
  IF(V$LIC = 404) THEN V$VAL = '3075';
  IF(V$LIC = 405) THEN V$VAL = '3076';
  IF(V$LIC = 406) THEN V$VAL = '3077';
  IF(V$LIC = 407) THEN V$VAL = '3079';
  IF(V$LIC = 408) THEN V$VAL = '3080';
  IF(V$LIC = 409) THEN V$VAL = '3083';
  IF(V$LIC = 410) THEN V$VAL = '3084';
  IF(V$LIC = 411) THEN V$VAL = '0646';
  IF(V$LIC = 413) THEN V$VAL = '3089';
  IF(V$LIC = 414) THEN V$VAL = '3090';
  IF(V$LIC = 415) THEN V$VAL = '3092';
  IF(V$LIC = 416) THEN V$VAL = '3093';
  IF(V$LIC = 417) THEN V$VAL = '3094';
  IF(V$LIC = 418) THEN V$VAL = '3095';
  IF(V$LIC = 419) THEN V$VAL = '3096';
  IF(V$LIC = 420) THEN V$VAL = '3099';
  IF(V$LIC = 421) THEN V$VAL = '0660';
  IF(V$LIC = 422) THEN V$VAL = '0661';
  IF(V$LIC = 423) THEN V$VAL = '3100';
  IF(V$LIC = 425) THEN V$VAL = '3102';
  IF(V$LIC = 426) THEN V$VAL = '3103';
  IF(V$LIC = 427) THEN V$VAL = '0666';
  IF(V$LIC = 429) THEN V$VAL = '3105';
  IF(V$LIC = 430) THEN V$VAL = '3110';
  IF(V$LIC = 431) THEN V$VAL = '3111';
  IF(V$LIC = 432) THEN V$VAL = '3112';
  IF(V$LIC = 433) THEN V$VAL = '0675';
  IF(V$LIC = 434) THEN V$VAL = '3113';
  IF(V$LIC = 435) THEN V$VAL = '3114';
  IF(V$LIC = 436) THEN V$VAL = '3116';
  IF(V$LIC = 438) THEN V$VAL = '3070';
  IF(V$LIC = 439) THEN V$VAL = '3073';
  IF(V$LIC = 440) THEN V$VAL = '3074';
  IF(V$LIC = 441) THEN V$VAL = '3078';
  IF(V$LIC = 442) THEN V$VAL = '3086';
  IF(V$LIC = 443) THEN V$VAL = '3087';
  IF(V$LIC = 444) THEN V$VAL = '3091';
  IF(V$LIC = 445) THEN V$VAL = '3117';
  IF(V$LIC = 446) THEN V$VAL = '3119';
  IF(V$LIC = 447) THEN V$VAL = '3082';
  IF(V$LIC = 448) THEN V$VAL = '3107';
  IF(V$LIC = 449) THEN V$VAL = '3109';
  IF(V$LIC = 450) THEN V$VAL = '3118';
  IF(V$LIC = 451) THEN V$VAL = '3098';
  IF(V$LIC = 453) THEN V$VAL = '3097';
  IF(V$LIC = 454) THEN V$VAL = '3106';
  IF(V$LIC = 455) THEN V$VAL = '0676';
  IF(V$LIC = 462) THEN V$VAL = '6040';
  IF(V$LIC = 463) THEN V$VAL = '3122';
  IF(V$LIC = 501) THEN V$VAL = '3171';
  IF(V$LIC = 502) THEN V$VAL = '3132';
  IF(V$LIC = 503) THEN V$VAL = '3149';
  IF(V$LIC = 505) THEN V$VAL = '3162';
  IF(V$LIC = 507) THEN V$VAL = '3147';
  IF(V$LIC = 508) THEN V$VAL = '3148';
  IF(V$LIC = 509) THEN V$VAL = '3159';
  IF(V$LIC = 510) THEN V$VAL = '3170';
  IF(V$LIC = 511) THEN V$VAL = '3174';
  IF(V$LIC = 512) THEN V$VAL = '3134';
  IF(V$LIC = 513) THEN V$VAL = '3179';
  IF(V$LIC = 514) THEN V$VAL = '3137';
  IF(V$LIC = 517) THEN V$VAL = '3150';
  IF(V$LIC = 518) THEN V$VAL = '3151';
  IF(V$LIC = 519) THEN V$VAL = '3152';
  IF(V$LIC = 520) THEN V$VAL = '3153';
  IF(V$LIC = 521) THEN V$VAL = '3154';
  IF(V$LIC = 522) THEN V$VAL = '3156';
  IF(V$LIC = 523) THEN V$VAL = '3157';
  IF(V$LIC = 524) THEN V$VAL = '3161';
  IF(V$LIC = 526) THEN V$VAL = '3165';
  IF(V$LIC = 527) THEN V$VAL = '3166';
  IF(V$LIC = 528) THEN V$VAL = '3167';
  IF(V$LIC = 529) THEN V$VAL = '3169';
  IF(V$LIC = 530) THEN V$VAL = '3173';
  IF(V$LIC = 532) THEN V$VAL = '3176';
  IF(V$LIC = 534) THEN V$VAL = '3135';
  IF(V$LIC = 535) THEN V$VAL = '3136';
  IF(V$LIC = 536) THEN V$VAL = '3138';
  IF(V$LIC = 537) THEN V$VAL = '3140';
  IF(V$LIC = 538) THEN V$VAL = '3141';
  IF(V$LIC = 540) THEN V$VAL = '3145';
  IF(V$LIC = 542) THEN V$VAL = '3177';
  IF(V$LIC = 544) THEN V$VAL = '3158';
  IF(V$LIC = 545) THEN V$VAL = '3163';
  IF(V$LIC = 546) THEN V$VAL = '3155';
  IF(V$LIC = 547) THEN V$VAL = '3160';
  IF(V$LIC = 548) THEN V$VAL = '3168';
  IF(V$LIC = 549) THEN V$VAL = '3172';
  IF(V$LIC = 550) THEN V$VAL = '3143';
  IF(V$LIC = 556) THEN V$VAL = '3178';
  IF(V$LIC = 559) THEN V$VAL = '3127';
  IF(V$LIC = 601) THEN V$VAL = '0135';
  IF(V$LIC = 602) THEN V$VAL = '3184';
  IF(V$LIC = 603) THEN V$VAL = '0134';
  IF(V$LIC = 604) THEN V$VAL = '3194';
  IF(V$LIC = 605) THEN V$VAL = '0146';
  IF(V$LIC = 606) THEN V$VAL = '3200';
  IF(V$LIC = 607) THEN V$VAL = '3185';
  IF(V$LIC = 609) THEN V$VAL = '3205';
  IF(V$LIC = 611) THEN V$VAL = '0126';
  IF(V$LIC = 612) THEN V$VAL = '0127';
  IF(V$LIC = 613) THEN V$VAL = '3183';
  IF(V$LIC = 614) THEN V$VAL = '0129';
  IF(V$LIC = 615) THEN V$VAL = '3186';
  IF(V$LIC = 616) THEN V$VAL = '3187';
  IF(V$LIC = 617) THEN V$VAL = '0122';
  IF(V$LIC = 619) THEN V$VAL = '3189';
  IF(V$LIC = 620) THEN V$VAL = '3190';
  IF(V$LIC = 621) THEN V$VAL = '3191';
  IF(V$LIC = 623) THEN V$VAL = '0138';
  IF(V$LIC = 624) THEN V$VAL = '3193';
  IF(V$LIC = 625) THEN V$VAL = '0141';
  IF(V$LIC = 626) THEN V$VAL = '3196';
  IF(V$LIC = 627) THEN V$VAL = '3197';
  IF(V$LIC = 628) THEN V$VAL = '0167';
  IF(V$LIC = 629) THEN V$VAL = '3198';
  IF(V$LIC = 630) THEN V$VAL = '3199';
  IF(V$LIC = 632) THEN V$VAL = '3204';
  IF(V$LIC = 633) THEN V$VAL = '0156';
  IF(V$LIC = 635) THEN V$VAL = '0158';
  IF(V$LIC = 636) THEN V$VAL = '0159';
  IF(V$LIC = 637) THEN V$VAL = '3208';
  IF(V$LIC = 638) THEN V$VAL = '3209';
  IF(V$LIC = 639) THEN V$VAL = '3210';
  IF(V$LIC = 640) THEN V$VAL = '3211';
  IF(V$LIC = 643) THEN V$VAL = '3201';
  IF(V$LIC = 644) THEN V$VAL = '3195';
  IF(V$LIC = 645) THEN V$VAL = '0145';
  IF(V$LIC = 646) THEN V$VAL = '0147';
  IF(V$LIC = 648) THEN V$VAL = '3181';
  IF(V$LIC = 653) THEN V$VAL = '6048';
  IF(V$LIC = 655) THEN V$VAL = '6049';
  IF(V$LIC = 702) THEN V$VAL = '6036';
  IF(V$LIC = 705) THEN V$VAL = '3217';
  IF(V$LIC = 706) THEN V$VAL = '3220';
  IF(V$LIC = 707) THEN V$VAL = '3222';
  IF(V$LIC = 708) THEN V$VAL = '3223';
  IF(V$LIC = 709) THEN V$VAL = '3226';
  IF(V$LIC = 710) THEN V$VAL = '3227';
  IF(V$LIC = 711) THEN V$VAL = '3228';
  IF(V$LIC = 712) THEN V$VAL = '3229';
  IF(V$LIC = 713) THEN V$VAL = '3230';
  IF(V$LIC = 714) THEN V$VAL = '3231';
  IF(V$LIC = 715) THEN V$VAL = '3232';
  IF(V$LIC = 716) THEN V$VAL = '3233';
  IF(V$LIC = 717) THEN V$VAL = '3234';
  IF(V$LIC = 718) THEN V$VAL = '3236';
  IF(V$LIC = 720) THEN V$VAL = '3216';
  IF(V$LIC = 721) THEN V$VAL = '3221';
  IF(V$LIC = 722) THEN V$VAL = '3224';
  IF(V$LIC = 723) THEN V$VAL = '3218';
  IF(V$LIC = 724) THEN V$VAL = '3225';
  IF(V$LIC = 725) THEN V$VAL = '3235';
  IF(V$LIC = 728) THEN V$VAL = '3219';
  IF(V$LIC = 801) THEN V$VAL = '0196';
  IF(V$LIC = 802) THEN V$VAL = '3268';
  IF(V$LIC = 803) THEN V$VAL = '3241';
  IF(V$LIC = 804) THEN V$VAL = '3242';
  IF(V$LIC = 805) THEN V$VAL = '3243';
  IF(V$LIC = 806) THEN V$VAL = '3244';
  IF(V$LIC = 807) THEN V$VAL = '0200';
  IF(V$LIC = 808) THEN V$VAL = '3245';
  IF(V$LIC = 809) THEN V$VAL = '3246';
  IF(V$LIC = 810) THEN V$VAL = '3247';
  IF(V$LIC = 811) THEN V$VAL = '0204';
  IF(V$LIC = 812) THEN V$VAL = '3248';
  IF(V$LIC = 813) THEN V$VAL = '0206';
  IF(V$LIC = 814) THEN V$VAL = '3249';
  IF(V$LIC = 815) THEN V$VAL = '0208';
  IF(V$LIC = 816) THEN V$VAL = '3253';
  IF(V$LIC = 817) THEN V$VAL = '3254';
  IF(V$LIC = 818) THEN V$VAL = '0213';
  IF(V$LIC = 819) THEN V$VAL = '3255';
  IF(V$LIC = 820) THEN V$VAL = '0215';
  IF(V$LIC = 821) THEN V$VAL = '3256';
  IF(V$LIC = 822) THEN V$VAL = '3258';
  IF(V$LIC = 823) THEN V$VAL = '3259';
  IF(V$LIC = 824) THEN V$VAL = '0223';
  IF(V$LIC = 825) THEN V$VAL = '0224';
  IF(V$LIC = 826) THEN V$VAL = '3260';
  IF(V$LIC = 827) THEN V$VAL = '0226';
  IF(V$LIC = 828) THEN V$VAL = '3261';
  IF(V$LIC = 829) THEN V$VAL = '3262';
  IF(V$LIC = 830) THEN V$VAL = '0229';
  IF(V$LIC = 831) THEN V$VAL = '0230';
  IF(V$LIC = 833) THEN V$VAL = '3252';
  IF(V$LIC = 834) THEN V$VAL = '0217';
  IF(V$LIC = 835) THEN V$VAL = '0222';
  IF(V$LIC = 836) THEN V$VAL = '0231';
  IF(V$LIC = 838) THEN V$VAL = '0220';
  IF(V$LIC = 839) THEN V$VAL = '3263';
  IF(V$LIC = 841) THEN V$VAL = '3240';
  IF(V$LIC = 845) THEN V$VAL = '3267';
  IF(V$LIC = 902) THEN V$VAL = '3273';
  IF(V$LIC = 903) THEN V$VAL = '3288';
  IF(V$LIC = 922) THEN V$VAL = '3298';
  IF(V$LIC = 925) THEN V$VAL = '0259';
  IF(V$LIC = 926) THEN V$VAL = '3304';
  IF(V$LIC = 929) THEN V$VAL = '3286';
  IF(V$LIC = 944) THEN V$VAL = '3307';
  IF(V$LIC = 945) THEN V$VAL = '6026';
  IF(V$LIC = 1001) THEN V$VAL = '0283';
  IF(V$LIC = 1002) THEN V$VAL = '3309';
  IF(V$LIC = 1003) THEN V$VAL = '3310';
  IF(V$LIC = 1005) THEN V$VAL = '3312';
  IF(V$LIC = 1006) THEN V$VAL = '0288';
  IF(V$LIC = 1101) THEN V$VAL = '3316';
  IF(V$LIC = 1105) THEN V$VAL = '3320';
  IF(V$LIC = 1106) THEN V$VAL = '3322';
  IF(V$LIC = 1107) THEN V$VAL = '3323';
  IF(V$LIC = 1108) THEN V$VAL = '3324';
  IF(V$LIC = 1109) THEN V$VAL = '3325';
  IF(V$LIC = 1110) THEN V$VAL = '3326';
  IF(V$LIC = 1112) THEN V$VAL = '3321';
  IF(V$LIC = 1205) THEN V$VAL = '3335';
  IF(V$LIC = 1207) THEN V$VAL = '3337';
  IF(V$LIC = 1209) THEN V$VAL = '3339';
  IF(V$LIC = 1210) THEN V$VAL = '3340';
  IF(V$LIC = 1216) THEN V$VAL = '0317';
  IF(V$LIC = 1217) THEN V$VAL = '3348';
  IF(V$LIC = 1218) THEN V$VAL = '3349';
  IF(V$LIC = 1219) THEN V$VAL = '3350';
  IF(V$LIC = 1221) THEN V$VAL = '3352';
  IF(V$LIC = 1223) THEN V$VAL = '3355';
  IF(V$LIC = 1224) THEN V$VAL = '3357';
  IF(V$LIC = 1225) THEN V$VAL = '3359';
  IF(V$LIC = 1227) THEN V$VAL = '3363';
  IF(V$LIC = 1230) THEN V$VAL = '0333';
  IF(V$LIC = 1232) THEN V$VAL = '3356';
  IF(V$LIC = 1234) THEN V$VAL = '3341';
  IF(V$LIC = 1235) THEN V$VAL = '0331';
  IF(V$LIC = 1237) THEN V$VAL = '3360';
  IF(V$LIC = 1238) THEN V$VAL = '3361';
  IF(V$LIC = 1243) THEN V$VAL = '6002';
  IF(V$LIC = 1302) THEN V$VAL = '6015';
  IF(V$LIC = 1308) THEN V$VAL = '3369';
  IF(V$LIC = 1309) THEN V$VAL = '3370';
  IF(V$LIC = 1311) THEN V$VAL = '0360';
  IF(V$LIC = 1312) THEN V$VAL = '3373';
  IF(V$LIC = 1313) THEN V$VAL = '3376';
  IF(V$LIC = 1314) THEN V$VAL = '3377';
  IF(V$LIC = 1315) THEN V$VAL = '0356';
  IF(V$LIC = 1316) THEN V$VAL = '3378';
  IF(V$LIC = 1317) THEN V$VAL = '0354';
  IF(V$LIC = 1318) THEN V$VAL = '3381';
  IF(V$LIC = 1319) THEN V$VAL = '3382';
  IF(V$LIC = 1320) THEN V$VAL = '3383';
  IF(V$LIC = 1322) THEN V$VAL = '3385';
  IF(V$LIC = 1323) THEN V$VAL = '3386';
  IF(V$LIC = 1324) THEN V$VAL = '3387';
  IF(V$LIC = 1325) THEN V$VAL = '3388';
  IF(V$LIC = 1326) THEN V$VAL = '3389';
  IF(V$LIC = 1327) THEN V$VAL = '3390';
  IF(V$LIC = 1328) THEN V$VAL = '3391';
  IF(V$LIC = 1329) THEN V$VAL = '3394';
  IF(V$LIC = 1331) THEN V$VAL = '3396';
  IF(V$LIC = 1332) THEN V$VAL = '3397';
  IF(V$LIC = 1333) THEN V$VAL = '3398';
  IF(V$LIC = 1335) THEN V$VAL = '3399';
  IF(V$LIC = 1336) THEN V$VAL = '3400';
  IF(V$LIC = 1337) THEN V$VAL = '3402';
  IF(V$LIC = 1338) THEN V$VAL = '3403';
  IF(V$LIC = 1339) THEN V$VAL = '3404';
  IF(V$LIC = 1340) THEN V$VAL = '3406';
  IF(V$LIC = 1341) THEN V$VAL = '3407';
  IF(V$LIC = 1342) THEN V$VAL = '3408';
  IF(V$LIC = 1343) THEN V$VAL = '3409';
  IF(V$LIC = 1344) THEN V$VAL = '3410';
  IF(V$LIC = 1345) THEN V$VAL = '3411';
  IF(V$LIC = 1347) THEN V$VAL = '3413';
  IF(V$LIC = 1348) THEN V$VAL = '3414';
  IF(V$LIC = 1349) THEN V$VAL = '3418';
  IF(V$LIC = 1350) THEN V$VAL = '0389';
  IF(V$LIC = 1351) THEN V$VAL = '3420';
  IF(V$LIC = 1352) THEN V$VAL = '3375';
  IF(V$LIC = 1354) THEN V$VAL = '0352';
  IF(V$LIC = 1355) THEN V$VAL = '3392';
  IF(V$LIC = 1356) THEN V$VAL = '3401';
  IF(V$LIC = 1357) THEN V$VAL = '0376';
  IF(V$LIC = 1358) THEN V$VAL = '3405';
  IF(V$LIC = 1359) THEN V$VAL = '3379';
  IF(V$LIC = 1360) THEN V$VAL = '3393';
  IF(V$LIC = 1361) THEN V$VAL = '0384';
  IF(V$LIC = 1362) THEN V$VAL = '3416';
  IF(V$LIC = 1364) THEN V$VAL = '3417';
  IF(V$LIC = 1401) THEN V$VAL = '3426';
  IF(V$LIC = 1402) THEN V$VAL = '0420';
  IF(V$LIC = 1403) THEN V$VAL = '3427';
  IF(V$LIC = 1406) THEN V$VAL = '3422';
  IF(V$LIC = 1407) THEN V$VAL = '3423';
  IF(V$LIC = 1408) THEN V$VAL = '0406';
  IF(V$LIC = 1409) THEN V$VAL = '3425';
  IF(V$LIC = 1410) THEN V$VAL = '3429';
  IF(V$LIC = 1411) THEN V$VAL = '3430';
  IF(V$LIC = 1412) THEN V$VAL = '3431';
  IF(V$LIC = 1413) THEN V$VAL = '3433';
  IF(V$LIC = 1414) THEN V$VAL = '3436';
  IF(V$LIC = 1415) THEN V$VAL = '3437';
  IF(V$LIC = 1416) THEN V$VAL = '3435';
  IF(V$LIC = 1417) THEN V$VAL = '3439';
  IF(V$LIC = 1419) THEN V$VAL = '3434';
  IF(V$LIC = 1420) THEN V$VAL = '3432';
  IF(V$LIC = 1422) THEN V$VAL = '0687';
  IF(V$LIC = 1425) THEN V$VAL = '3438';
  IF(V$LIC = 1604) THEN V$VAL = '3484';
  IF(V$LIC = 1606) THEN V$VAL = '3486';
  IF(V$LIC = 1608) THEN V$VAL = '3489';
  IF(V$LIC = 1610) THEN V$VAL = '3468';
  IF(V$LIC = 1611) THEN V$VAL = '3472';
  IF(V$LIC = 1612) THEN V$VAL = '3492';
  IF(V$LIC = 1613) THEN V$VAL = '3473';
  IF(V$LIC = 1614) THEN V$VAL = '3493';
  IF(V$LIC = 1615) THEN V$VAL = '3474';
  IF(V$LIC = 1616) THEN V$VAL = '3475';
  IF(V$LIC = 1617) THEN V$VAL = '3476';
  IF(V$LIC = 1618) THEN V$VAL = '3479';
  IF(V$LIC = 1620) THEN V$VAL = '3480';
  IF(V$LIC = 1621) THEN V$VAL = '3496';
  IF(V$LIC = 1623) THEN V$VAL = '3483';
  IF(V$LIC = 1624) THEN V$VAL = '3498';
  IF(V$LIC = 1625) THEN V$VAL = '0477';
  IF(V$LIC = 1626) THEN V$VAL = '3501';
  IF(V$LIC = 1627) THEN V$VAL = '3502';
  IF(V$LIC = 1628) THEN V$VAL = '3503';
  IF(V$LIC = 1629) THEN V$VAL = '3505';
  IF(V$LIC = 1630) THEN V$VAL = '3506';
  IF(V$LIC = 1631) THEN V$VAL = '3507';
  IF(V$LIC = 1632) THEN V$VAL = '3508';
  IF(V$LIC = 1633) THEN V$VAL = '3509';
  IF(V$LIC = 1634) THEN V$VAL = '3510';
  IF(V$LIC = 1636) THEN V$VAL = '3512';
  IF(V$LIC = 1638) THEN V$VAL = '3514';
  IF(V$LIC = 1639) THEN V$VAL = '3515';
  IF(V$LIC = 1640) THEN V$VAL = '6010';
  IF(V$LIC = 1641) THEN V$VAL = '3516';
  IF(V$LIC = 1642) THEN V$VAL = '3517';
  IF(V$LIC = 1645) THEN V$VAL = '3487';
  IF(V$LIC = 1647) THEN V$VAL = '3471';
  IF(V$LIC = 1648) THEN V$VAL = '3477';
  IF(V$LIC = 1649) THEN V$VAL = '0454';
  IF(V$LIC = 1651) THEN V$VAL = '3482';
  IF(V$LIC = 1653) THEN V$VAL = '3494';
  IF(V$LIC = 1654) THEN V$VAL = '3499';
  IF(V$LIC = 1655) THEN V$VAL = '3504';
  IF(V$LIC = 1656) THEN V$VAL = '0459';
  IF(V$LIC = 1657) THEN V$VAL = '3491';
  IF(V$LIC = 1662) THEN V$VAL = '3520';
  IF(V$LIC = 1666) THEN V$VAL = '6004';
  IF(V$LIC = 1702) THEN V$VAL = '3545';
  IF(V$LIC = 1703) THEN V$VAL = '6007';
  IF(V$LIC = 1704) THEN V$VAL = '3537';
  IF(V$LIC = 1705) THEN V$VAL = '3541';
  IF(V$LIC = 1710) THEN V$VAL = '3528';
  IF(V$LIC = 1711) THEN V$VAL = '3529';
  IF(V$LIC = 1712) THEN V$VAL = '3530';
  IF(V$LIC = 1713) THEN V$VAL = '3531';
  IF(V$LIC = 1714) THEN V$VAL = '0519';
  IF(V$LIC = 1715) THEN V$VAL = '3534';
  IF(V$LIC = 1716) THEN V$VAL = '3535';
  IF(V$LIC = 1717) THEN V$VAL = '3536';
  IF(V$LIC = 1718) THEN V$VAL = '3538';
  IF(V$LIC = 1719) THEN V$VAL = '0510';
  IF(V$LIC = 1720) THEN V$VAL = '3539';
  IF(V$LIC = 1721) THEN V$VAL = '0512';
  IF(V$LIC = 1722) THEN V$VAL = '0513';
  IF(V$LIC = 1723) THEN V$VAL = '3540';
  IF(V$LIC = 1724) THEN V$VAL = '0515';
  IF(V$LIC = 1725) THEN V$VAL = '3542';
  IF(V$LIC = 1726) THEN V$VAL = '3532';
  IF(V$LIC = 1727) THEN V$VAL = '3533';
  IF(V$LIC = 1729) THEN V$VAL = '3546';
  IF(V$LIC = 1730) THEN V$VAL = '6003';
  IF(V$LIC = 1801) THEN V$VAL = '3598';
  IF(V$LIC = 1802) THEN V$VAL = '3556';
  IF(V$LIC = 1803) THEN V$VAL = '3560';
  IF(V$LIC = 1804) THEN V$VAL = '3589';
  IF(V$LIC = 1806) THEN V$VAL = '0537';
  IF(V$LIC = 1807) THEN V$VAL = '0539';
  IF(V$LIC = 1808) THEN V$VAL = '3550';
  IF(V$LIC = 1809) THEN V$VAL = '3551';
  IF(V$LIC = 1810) THEN V$VAL = '0528';
  IF(V$LIC = 1811) THEN V$VAL = '0529';
  IF(V$LIC = 1812) THEN V$VAL = '3554';
  IF(V$LIC = 1813) THEN V$VAL = '0531';
  IF(V$LIC = 1814) THEN V$VAL = '0535';
  IF(V$LIC = 1815) THEN V$VAL = '3558';
  IF(V$LIC = 1816) THEN V$VAL = '0541';
  IF(V$LIC = 1817) THEN V$VAL = '0543';
  IF(V$LIC = 1818) THEN V$VAL = '3564';
  IF(V$LIC = 1819) THEN V$VAL = '0545';
  IF(V$LIC = 1820) THEN V$VAL = '3566';
  IF(V$LIC = 1821) THEN V$VAL = '3568';
  IF(V$LIC = 1822) THEN V$VAL = '3569';
  IF(V$LIC = 1823) THEN V$VAL = '3570';
  IF(V$LIC = 1824) THEN V$VAL = '3571';
  IF(V$LIC = 1825) THEN V$VAL = '0552';
  IF(V$LIC = 1826) THEN V$VAL = '3573';
  IF(V$LIC = 1827) THEN V$VAL = '0554';
  IF(V$LIC = 1828) THEN V$VAL = '3575';
  IF(V$LIC = 1829) THEN V$VAL = '3576';
  IF(V$LIC = 1830) THEN V$VAL = '0557';
  IF(V$LIC = 1831) THEN V$VAL = '3579';
  IF(V$LIC = 1832) THEN V$VAL = '0560';
  IF(V$LIC = 1833) THEN V$VAL = '3581';
  IF(V$LIC = 1834) THEN V$VAL = '3582';
  IF(V$LIC = 1836) THEN V$VAL = '3585';
  IF(V$LIC = 1838) THEN V$VAL = '0567';
  IF(V$LIC = 1839) THEN V$VAL = '3588';
  IF(V$LIC = 1840) THEN V$VAL = '3590';
  IF(V$LIC = 1843) THEN V$VAL = '0523';
  IF(V$LIC = 1844) THEN V$VAL = '3552';
  IF(V$LIC = 1845) THEN V$VAL = '3578';
  IF(V$LIC = 1846) THEN V$VAL = '3584';
  IF(V$LIC = 1847) THEN V$VAL = '3555';
  IF(V$LIC = 1848) THEN V$VAL = '3562';
  IF(V$LIC = 1849) THEN V$VAL = '3567';
  IF(V$LIC = 1851) THEN V$VAL = '3593';
  IF(V$LIC = 1901) THEN V$VAL = '3635';
  IF(V$LIC = 1902) THEN V$VAL = '3625';
  IF(V$LIC = 1903) THEN V$VAL = '3632';
  IF(V$LIC = 1904) THEN V$VAL = '3636';
  IF(V$LIC = 1905) THEN V$VAL = '3597';
  IF(V$LIC = 1907) THEN V$VAL = '0578';
  IF(V$LIC = 1909) THEN V$VAL = '3603';
  IF(V$LIC = 1910) THEN V$VAL = '3605';
  IF(V$LIC = 1911) THEN V$VAL = '3606';
  IF(V$LIC = 1912) THEN V$VAL = '3607';
  IF(V$LIC = 1913) THEN V$VAL = '3608';
  IF(V$LIC = 1915) THEN V$VAL = '3610';
  IF(V$LIC = 1916) THEN V$VAL = '3612';
  IF(V$LIC = 1917) THEN V$VAL = '3613';
  IF(V$LIC = 1918) THEN V$VAL = '3614';
  IF(V$LIC = 1921) THEN V$VAL = '3618';
  IF(V$LIC = 1923) THEN V$VAL = '3621';
  IF(V$LIC = 1924) THEN V$VAL = '3622';
  IF(V$LIC = 1925) THEN V$VAL = '3624';
  IF(V$LIC = 1927) THEN V$VAL = '3627';
  IF(V$LIC = 1930) THEN V$VAL = '3630';
  IF(V$LIC = 1931) THEN V$VAL = '3631';
  IF(V$LIC = 1932) THEN V$VAL = '3633';
  IF(V$LIC = 1933) THEN V$VAL = '3640';
  IF(V$LIC = 1934) THEN V$VAL = '3596';
  IF(V$LIC = 1935) THEN V$VAL = '0576';
  IF(V$LIC = 1936) THEN V$VAL = '3599';
  IF(V$LIC = 1937) THEN V$VAL = '3600';
  IF(V$LIC = 1939) THEN V$VAL = '3604';
  IF(V$LIC = 1941) THEN V$VAL = '3634';
  IF(V$LIC = 1942) THEN V$VAL = '3611';
  IF(V$LIC = 1949) THEN V$VAL = '3643';
  IF(V$LIC = 1953) THEN V$VAL = '3641';
  IF(V$LIC = 1954) THEN V$VAL = '3638';
  IF(V$LIC = 1956) THEN V$VAL = '3642';
  IF(V$LIC = 4075) THEN V$VAL = '6031';
  IF(V$LIC = 4076) THEN V$VAL = '6006';
  IF(V$LIC = 4095) THEN V$VAL = '3123';
  IF(V$LIC = 4187) THEN V$VAL = '6005';

  IF(V$VAL IS NOT NULL) THEN
  BEGIN
      V$VAL = 'sch78' || V$VAL;
      SELECT BLOB_ID FROM VAL_ADD(2951, :I$SCHOOL_ID, :V$VAL) INTO :V$LIC;
  END
     
end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIX_FPU2019
AS
declare variable V$BOOK_ID bigint;
declare variable V$BOOK_CODE varchar(100);
declare variable TMP bigint;
begin

  -- Неактуально

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIX_GIA_NEW_FOLDER
AS
DECLARE VARIABLE V$OU_ID BIGINT;
DECLARE VARIABLE V$GIA_FOLDER BIGINT;
DECLARE VARIABLE V$GRADE_ID BIGINT;
DECLARE VARIABLE V$STAGE_ID BIGINT;
DECLARE VARIABLE V$FOLDER_ID BIGINT;
begin

  SELECT FIRST 1 L2.OBJ_ID, L502.OBJ_ID
  FROM LINKS L2
  LEFT JOIN LINKS L502 ON L502.PARENT_ID = L2.OBJ_ID AND L502.OBJ_TYPE_ID = 502 AND L502.DATE_DEL IS NULL
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$OU_ID, :V$GIA_FOLDER;

  IF(V$GIA_FOLDER IS NULL) THEN
  SELECT OBJ_ID FROM OBJECT_ADD(:V$OU_ID, 502) INTO :V$GIA_FOLDER;

  FOR
    SELECT L125.LINK_ID, V49.LISTVAL_ID
    FROM LINKS L7
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
    JOIN LINKS L125 ON L125.PARENT_ID = L7.OBJ_ID AND L125.OBJ_TYPE_ID = 125 AND L125.DATE_DEL IS NULL
    WHERE L7.PARENT_ID = :V$OU_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    ORDER BY 1
    INTO :V$GRADE_ID, :V$STAGE_ID
  DO
  BEGIN
    V$FOLDER_ID = NULL;
    SELECT FIRST 1 L8.OBJ_ID
    FROM LINKS L8
    JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0 AND V49.LISTVAL_ID = :V$STAGE_ID
    WHERE L8.PARENT_ID = :V$GIA_FOLDER AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    INTO :V$FOLDER_ID;

    IF(V$FOLDER_ID IS NULL) THEN
    SELECT OBJ_ID FROM OBJECT_ADD_WITH_PARAM(:V$GIA_FOLDER, NULL, 8, 49, :V$STAGE_ID) INTO :V$FOLDER_ID;

    UPDATE LINKS
    SET PARENT_ID = :V$FOLDER_ID
    WHERE LINK_ID = :V$GRADE_ID;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIX_GRADUATES
AS
declare variable V$CONTAINER_PUPIL_OUT_ID bigint;
declare variable V$SCHOOL_ID bigint;
declare variable V$GRADUATE_ID bigint;
declare variable V$PUPIL_OUT_FOUND bigint;
declare variable V$GRADUATES_YEAR integer;
declare variable V$BLOB_ID bigint;
declare variable V$PUPIL_ID bigint;
declare variable V$PARALEL_NUM bigint;
declare variable V$CAPTION varchar(4000);
declare variable V$OBJ_ID bigint;
declare variable V$KIND_SCHOOL_ID bigint;
declare variable V$TYPE_SCHOOL_ID bigint;
BEGIN

  -- Смысл утрачен

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIX_JOB_LINK
AS
declare variable V$ASSN_ID bigint;
declare variable V$JOB_ID bigint;
declare variable V$LINK_ID bigint;
begin

  FOR
      SELECT L15.OBJ_ID, V69.VAL
      FROM LINKS L15
      JOIN VALR V69 ON V69.OBJ_ID = L15.OBJ_ID AND V69.PARAM_ID = 69 AND V69.IS_DEL = 0
      LEFT JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
      WHERE L15.PARENT_TYPE_ID = 14 AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL AND LP13.OBJ_ID IS NULL
      INTO :V$ASSN_ID, :V$JOB_ID
  DO
  BEGIN

     -- Если была связь именно с этой должностью - восстанавливаем ее
     V$LINK_ID = NULL;

     SELECT FIRST 1 LINK_ID
     FROM LINKS
     WHERE PARENT_ID = :V$JOB_ID AND OBJ_ID = :V$ASSN_ID AND DATE_DEL IS NOT NULL
     INTO :V$LINK_ID;

     IF(V$LINK_ID IS NULL) THEN
     BEGIN
         SELECT LINK_ID FROM OBJECT_ADD_LINK(:V$JOB_ID, :V$ASSN_ID, 15) INTO :V$LINK_ID;
     END
     ELSE
     BEGIN
         UPDATE LINKS SET DATE_DEL = NULL WHERE LINK_ID = :V$LINK_ID;
     END

  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIX_JOB_R3
AS
DECLARE VARIABLE OBJ_ID BIGINT;
begin

  FOR
    SELECT L13.OBJ_ID
    FROM LINKS L13
    JOIN VALL V58 ON V58.OBJ_ID = L13.OBJ_ID AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0 AND V58.LISTVAL_ID IN (18499, 18534)
    JOIN VALL V64 ON V64.OBJ_ID = L13.OBJ_ID AND V64.PARAM_ID = 64 AND V64.IS_DEL = 0 AND V64.LISTVAL_ID <> 70
    WHERE L13.PARENT_TYPE_ID IN (2, 211) AND L13.OBJ_TYPE_ID = 13 AND L13.DATE_DEL IS NULL
    ORDER BY 1
    INTO :OBJ_ID
  DO
  BEGIN
    UPDATE VALL
    SET LISTVAL_ID = 70
    WHERE OBJ_ID = :OBJ_ID AND PARAM_ID = 64;
  END

  FOR
    SELECT L15.OBJ_ID
    FROM LINKS L15
    JOIN VALL V1394 ON V1394.OBJ_ID = L15.OBJ_ID AND V1394.PARAM_ID = 1394 AND V1394.IS_DEL = 0 AND V1394.LISTVAL_ID IN (18499, 18534)
    JOIN VALL V1399 ON V1399.OBJ_ID = L15.OBJ_ID AND V1399.PARAM_ID = 1399 AND V1399.IS_DEL = 0 AND V1399.LISTVAL_ID <> 70
    WHERE L15.PARENT_TYPE_ID = 13 AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
    ORDER BY 1
    INTO :OBJ_ID
  DO
  BEGIN
    UPDATE VALL
    SET LISTVAL_ID = 70
    WHERE OBJ_ID = :OBJ_ID AND PARAM_ID = 1399;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIX_LESSON_THEME_PLAN_DEL
AS
begin
  DELETE FROM OBJECTS
  WHERE TYPE_ID >= 87 AND TYPE_ID <= 90 --ПТП (поурочно-тематические планы (87) и связанные подтипы (88-90)
  ORDER BY TYPE_ID DESC;
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIX_LIBRARY_ROOTTYPE
AS
declare variable OBJ_ID bigint;
declare variable TMP bigint;
begin

    FOR
        SELECT L61.OBJ_ID
        FROM LINKS L61
        JOIN VALL V526 ON V526.OBJ_ID = L61.OBJ_ID AND V526.PARAM_ID = 526 AND V526.IS_DEL = 0 AND V526.LISTVAL_ID IN (1139, 1140, 1141, 1142, 1143, 1144)
        WHERE L61.OBJ_TYPE_ID = 61 AND L61.PARENT_TYPE_ID = 16 AND L61.DATE_DEL IS NULL
        INTO :OBJ_ID
    DO BEGIN

        -- Вместо учебно-лабораторных теперь учебно-вспомогательные
        SELECT BLOB_ID FROM VAL_ADD(525, :OBJ_ID, 12764) INTO :TMP;

    END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIX_LONG_VACATIONS (
    SCHOOL_ID BIGINT)
AS
declare variable PERSON_ID bigint;
declare variable VAC_STATE bigint;
declare variable HAS_REG integer;
declare variable REG_ID bigint;
declare variable TMP bigint;
begin

  FOR
      SELECT DISTINCT L14.OBJ_ID, V274.LISTVAL_ID
      FROM LINKS L14
      JOIN VALL V274 ON V274.OBJ_ID = L14.OBJ_ID AND V274.PARAM_ID = 274 AND V274.IS_DEL = 0 AND V274.LISTVAL_ID <> 602
      WHERE L14.OBJ_TYPE_ID = 14 AND L14.PARENT_TYPE_ID IN (2, 211) AND L14.DATE_DEL IS NULL
      INTO :PERSON_ID, :VAC_STATE
  DO
  BEGIN

      HAS_REG = 0;

      SELECT FIRST 1 1
      FROM LINKS L376
      WHERE L376.PARENT_ID = :PERSON_ID AND L376.OBJ_TYPE_ID = 376 AND L376.DATE_DEL IS NULL
      INTO :HAS_REG;

      IF(HAS_REG = 0) THEN
      BEGIN
          -- Добавляем запись длительного отпуска
          SELECT OBJ_ID FROM OBJECT_ADD(:PERSON_ID, 376) INTO :REG_ID;
          -- Фиксируем в ней статус
          SELECT BLOB_ID FROM VAL_ADD(2859, :REG_ID, :VAC_STATE) INTO :TMP;
      END

  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIX_LOST_LINKS
AS
declare variable V$OBJ_ID bigint;
begin

  -- Идем по ученикам, числящимся в удаленных группах
  FOR
    SELECT DISTINCT L10.OBJ_ID
    FROM LINKS L10
    LEFT JOIN LINKS LP ON LP.OBJ_ID = L10.PARENT_ID AND LP.PARENT_TYPE_ID IN (8, 77, 78, 86) AND LP.DATE_DEL IS NULL
    WHERE L10.OBJ_TYPE_ID = 10 AND L10.PARENT_TYPE_ID IN (9, 187, 290, 81, 82, 83, 46) AND L10.DATE_DEL IS NULL AND LP.LINK_ID IS NULL
    ORDER BY 1
    INTO :V$OBJ_ID
  DO
  BEGIN
    UPDATE LINKS
    SET DATE_DEL = CURRENT_TIMESTAMP
    WHERE OBJ_ID = :V$OBJ_ID AND PARENT_TYPE_ID IN (9, 187, 290, 81, 82, 83, 46) AND DATE_DEL IS NULL;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIX_LOST_STUFF
AS
declare variable V$LINK_ID bigint;
begin

  FOR
    SELECT L14.LINK_ID
    FROM LINKS L14
    JOIN LINKS LP2 ON LP2.OBJ_ID = L14.OBJ_ID AND LP2.PARENT_TYPE_ID = 2 AND LP2.DATE_DEL IS NULL
    JOIN LINKS L ON L.OBJ_ID = LP2.PARENT_ID AND L.PARENT_ID IS NULL AND L.DATE_DEL IS NULL
    WHERE L14.PARENT_TYPE_ID = 84 AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
    ORDER BY 1
    INTO :V$LINK_ID
  DO
  BEGIN
    UPDATE LINKS
    SET DATE_DEL = CURRENT_TIMESTAMP
    WHERE LINK_ID = :V$LINK_ID;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIX_MERGE_DB (
    I$FLAGS INTEGER = 1,
    I$DBNAME VARCHAR(400) NOT NULL = 'MERGE.FDB',
    I$ADJYEAR SMALLINT NOT NULL = 0)
RETURNS (
    OBJ_ID BIGINT,
    PERSON_ID BIGINT,
    STAGE_ID BIGINT,
    PARAM_ID BIGINT,
    N INTEGER)
AS
DECLARE VARIABLE V VARCHAR(400);
DECLARE VARIABLE V$PREV_ID BIGINT;
DECLARE VARIABLE V$OU_ID BIGINT;
DECLARE VARIABLE V$ROOT_ID BIGINT;
DECLARE VARIABLE V$FOLDER_ID BIGINT;
DECLARE VARIABLE V$CHILD_ID BIGINT;
DECLARE VARIABLE CHILD_ID BIGINT;
DECLARE VARIABLE V$REF_ID BIGINT;
DECLARE VARIABLE V$LEVEL_ID BIGINT;
DECLARE VARIABLE V$EXT_ID BIGINT;
DECLARE VARIABLE T INTEGER;
DECLARE VARIABLE S VARCHAR(1000);
DECLARE VARIABLE S2 VARCHAR(1000);
DECLARE VARIABLE V$SRC_LC VARCHAR(2);
DECLARE VARIABLE V$THIS_LC VARCHAR(2);
DECLARE VARIABLE V$DIV_ID BIGINT;
DECLARE VARIABLE V$JOB_ID BIGINT;
DECLARE VARIABLE V$DATE DATE;
DECLARE VARIABLE V$LEAVE_ID BIGINT;
DECLARE VARIABLE V$LEAVE_TYPE BIGINT;
DECLARE VARIABLE V$PARAM BIGINT;
DECLARE VARIABLE V$PARAM2 BIGINT;
DECLARE VARIABLE Y INTEGER;
begin

  -- FLAGS побитно:
  -- 0: обучающиеся
  -- 1: должности и сотрудники
  -- 2: учебные планы
  -- 3: здания, помещения, земельные участки
  -- 4: материальные ресурсы
  -- 5: родители

  IF(UPPER(I$DBNAME) = 'BASE.FDB' OR UPPER(I$DBNAME) = 'BLOB.FDB' OR UPPER(I$DBNAME) = 'DOC.FDB' OR UPPER(I$DBNAME) = 'BIN.FDB') THEN
    EXCEPTION DATA_ERROR 'Недопустимое имя базы данных';

  -- Проверяем id папки зачисляемых
  SELECT FIRST 1 L2.OBJ_ID, L77.OBJ_ID
  FROM LINKS L2
  JOIN LINKS L77 ON L77.PARENT_ID = L2.OBJ_ID AND L77.OBJ_TYPE_ID = 77 AND L77.DATE_DEL IS NULL
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$OU_ID, :V$ROOT_ID;

  IF(V$ROOT_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Системная ошибка: нет объекта ОООД или папки зачисляемых';

  SELECT MON$DATABASE_NAME
  FROM MON$DATABASE
  INTO :V;

  -- Получаем тип лицензии базы, откуда импортируем
  V$THIS_LC = (SELECT STATUS FROM OU_LICENCE_TYPE);
  V = REPLACE(V, 'BASE.FDB', I$DBNAME);
  EXECUTE STATEMENT 'SELECT STATUS FROM OU_LICENCE_TYPE' ON EXTERNAL :V
  WITH COMMON TRANSACTION
  INTO :V$SRC_LC;

  -- Предварительная проверка: Директор должен быть уволен, статус ИО снят
  OBJ_ID = NULL;
  EXECUTE STATEMENT
    'SELECT FIRST 1 L14.OBJ_ID
    FROM LINKS L2
    JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
    LEFT JOIN VALL V3343 ON V3343.OBJ_ID = L14.OBJ_ID AND V3343.PARAM_ID = 3343 AND V3343.IS_DEL = 0
    JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
    JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
    JOIN VALL V64 ON V64.OBJ_ID = LP13.PARENT_ID AND V64.PARAM_ID = 64 AND V64.IS_DEL = 0
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND V74.VAL IS NULL AND (V64.LISTVAL_ID = 56 OR V3343.LISTVAL_ID = 2)
    ORDER BY 1'
  ON EXTERNAL :V
  WITH COMMON TRANSACTION
  INTO :OBJ_ID;

  IF(OBJ_ID IS NOT NULL) THEN EXCEPTION DATA_ERROR 'При слиянии организаций на момент переноса данных руководитель должен быть уволен, признак "Является ИО руководителя" должен быть снят';

  -- Обучающиеся
  IF(BIN_AND(I$FLAGS, 1) <> 0) THEN
  BEGIN
    -- Учебные коллективы
    -- Только действущие. Уже выпустившиеся будут созданы только внутри движения
    OBJ_ID = 0;
    WHILE(OBJ_ID IS NOT NULL) DO
    BEGIN

      V$PREV_ID = OBJ_ID;
      OBJ_ID = NULL;
      N = 0;
      EXECUTE STATEMENT
        'SELECT FIRST 1 L9.OBJ_ID, V49.LISTVAL_ID, V54.VAL
        FROM LINKS L2
        JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
        JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
        LEFT JOIN VALS V54 ON V54.OBJ_ID = L9.OBJ_ID AND V54.PARAM_ID = 54 AND V54.IS_DEL = 0
        WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND L9.OBJ_ID > ' || V$PREV_ID || '
        AND EXISTS (
          SELECT FIRST 1 1
          FROM LINKS L10
          WHERE L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        )
        ORDER BY 1'
      ON EXTERNAL :V
      WITH COMMON TRANSACTION
      INTO :OBJ_ID, :STAGE_ID, :S;

      IF(OBJ_ID IS NOT NULL) THEN
      BEGIN
        -- Название класса - текущего или будущего
        -- садиковские группы - суффикс не добавляем, название будет идентично исходному
        S = COALESCE(S, '');
        IF(STAGE_ID IN (30, 31, 32, 33, 34, 35, 36, 3261, 3262)) THEN S = REPLACE(SUBSTRING(S FROM POSITION('«' IN S) + 1), '»', '');
        ELSE S = S || 'Ё';

        IF(I$ADJYEAR = 1) THEN
        BEGIN
          IF(STAGE_ID >= 37 AND STAGE_ID < 47) THEN STAGE_ID = STAGE_ID + 1;
          ELSE IF(STAGE_ID IN (47, 48)) THEN STAGE_ID = NULL;
          ELSE IF(STAGE_ID >= 49 AND STAGE_ID < 54) THEN STAGE_ID = STAGE_ID + 1;
          ELSE IF(STAGE_ID IN (54)) THEN STAGE_ID = NULL;
          -- Садиковские этапы не меняем
        END

        -- Этап должен быть заведен
        -- Если у нас уже выпустившаяся группа, создаем ее как удаленную в первом курсе
        IF(STAGE_ID IS NOT NULL) THEN
        BEGIN
          V$FOLDER_ID = NULL;
          SELECT FIRST 1 L8.OBJ_ID
          FROM LINKS L2
          JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
          JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
          JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0 AND V49.LISTVAL_ID = IIF(:STAGE_ID = 0, 49, :STAGE_ID)
          INTO :V$FOLDER_ID;

          IF(V$FOLDER_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не настроен раздел с требуемым уровнем образования ' || COALESCE((SELECT VAL FROM LISTVAL_TEXT(:STAGE_ID)), '?');

          -- Нет ли уже этого класса ?
          -- Проверку на DATE_DEL исключаем, чтобы работал импорт колледжей
          V$REF_ID = NULL;
          SELECT FIRST 1 L9.OBJ_ID
          FROM LINKS L9
          WHERE L9.PARENT_ID = :V$FOLDER_ID AND L9.OBJ_TYPE_ID = IIF(:I$ADJYEAR = 0, 9, 403) /*AND L9.DATE_DEL IS NULL*/ AND L9.LISTVAL_ID = :OBJ_ID
          INTO :V$REF_ID;

          -- На всякий случай не даем создавать классы с той же буквой
          IF(V$REF_ID IS NULL) THEN
          BEGIN
            SELECT FIRST 1 L9.OBJ_ID
            FROM LINKS L9
            JOIN VALS V ON V.OBJ_ID = L9.OBJ_ID AND V.PARAM_ID = IIF(:I$ADJYEAR = 0, 54, 3026) AND V.IS_DEL = 0 AND V.SVAL = :S
            WHERE L9.PARENT_ID = :V$FOLDER_ID AND L9.OBJ_TYPE_ID = IIF(:I$ADJYEAR = 0, 9, 403) AND L9.DATE_DEL IS NULL
            INTO :V$REF_ID;
          END

          IF(V$REF_ID IS NULL) THEN
          BEGIN
            SELECT OBJ_ID FROM OBJECT_ADD(:V$FOLDER_ID, IIF(:I$ADJYEAR = 0, 9, 403), NULL, NULL, 1) INTO :V$REF_ID;
            SELECT BLOB_ID FROM VAL_ADD(IIF(:I$ADJYEAR = 0, 54, 3026), :V$REF_ID, :S) INTO :T;
            UPDATE LINKS SET LISTVAL_ID = :OBJ_ID WHERE PARENT_ID = :V$FOLDER_ID AND OBJ_ID = :V$REF_ID;
            -- Выпустившиеся группы СПО отмечаем как удаленные
            -- они нужны только чтобы были ссылки в движении
            IF(STAGE_ID = 0) THEN UPDATE LINKS SET DATE_DEL = CURRENT_TIMESTAMP WHERE OBJ_ID = :V$REF_ID AND PARENT_TYPE_ID = 8 AND DATE_DEL IS NULL;
          END
        END

        PARAM_ID = NULL;
        SUSPEND;
      END

    END

    -- Сами обучающиеся
    OBJ_ID = 0;
    WHILE(OBJ_ID IS NOT NULL) DO
    BEGIN

      V$PREV_ID = OBJ_ID;
      OBJ_ID = NULL;
      V$EXT_ID = NULL;
      V$JOB_ID = NULL;
      N = 0;
      EXECUTE STATEMENT
        'SELECT FIRST 1 M.PERSON_ID, M.STAGE_ID, M.NAME_IN, M.GROUP_TYPE_ID, M.GROUP_ID
        FROM PERSON_MOVEMENTS M
        WHERE M.DATE_DEL IS NULL AND M.GROUP_TYPE_ID IN (9, 289) AND M.DATE_OUT IS NULL AND M.PERSON_ID > ' || V$PREV_ID || '
        ORDER BY 1'
      ON EXTERNAL :V
      WITH COMMON TRANSACTION
      INTO :OBJ_ID, :STAGE_ID, :S, :V$EXT_ID, :V$JOB_ID;

      IF(OBJ_ID IS NOT NULL) THEN
      BEGIN

        -- Если есть хоть один ученик - создаем проект приказа
        /*IF(V$ORDER_ID IS NULL) THEN
        BEGIN
          INSERT INTO ORDERS
          (TYPE_ID, STATE_ID, ORDER_NUM)
          VALUES (12929, 11716, 'АВТО')
          RETURNING OBJ_ID INTO :V$ORDER_ID;
        END*/

        -- Меняем +1 параллель, если указано. Также надо скорректировать название класса для планируемого движения
        IF(I$ADJYEAR = 1) THEN
        BEGIN
          IF(STAGE_ID >= 37 AND STAGE_ID < 47) THEN STAGE_ID = STAGE_ID + 1;
          ELSE IF(STAGE_ID IN (47, 48)) THEN STAGE_ID = NULL;
          ELSE IF(STAGE_ID >= 49 AND STAGE_ID < 54) THEN STAGE_ID = STAGE_ID + 1;
          ELSE IF(STAGE_ID IN (54)) THEN STAGE_ID = NULL;

          -- Только если правило нумерации попадает в школы и СПО
          T = POSITION(' ' IN S);
          IF(STAGE_ID IS NOT NULL AND (T IN (2, 3) OR (T = 0 AND CHAR_LENGTH(S) <= 2))) THEN
          BEGIN
            IF(T > 0) THEN S = (CAST(SUBSTRING(S FROM 1 FOR T - 1) AS INTEGER) + 1) || SUBSTRING(S FROM T);
            ELSE S = CAST(S AS INTEGER) + 1;
          END

          S = 'будущий ' || S || 'Ё'; -- Ё в конце для указания принятых классов
        END
        ELSE
        BEGIN
          IF(STAGE_ID NOT IN (30, 31, 32, 33, 34, 35, 36, 3261, 3262)) THEN S = S || 'Ё'; -- Ё в конце для указания принятых классов
        END

        -- Проверяем, что персона у нас еще не импортировалась
        -- сохраняем id в LISTVAL_ID
        IF(STAGE_ID IS NOT NULL AND NOT EXISTS(
          SELECT FIRST 1 1
          FROM LINKS L10
          WHERE L10.OBJ_TYPE_ID = 10 AND L10.PARENT_TYPE_ID IN (9, 81, 82, 83, 189, 289, 290) AND L10.DATE_DEL IS NULL AND L10.LISTVAL_ID = :OBJ_ID
        ))
        THEN
        BEGIN

          V$FOLDER_ID = NULL;

          -- При импорте из ДОУ в S-версию переносим не в предварительный этап, а прямо в группы - сами группы уже есть
          IF(((V$THIS_LC = 'S' AND V$SRC_LC = 'D') OR (V$THIS_LC = 'C' AND V$SRC_LC = 'C')) AND I$ADJYEAR = 0) THEN
          BEGIN
            IF(V$EXT_ID = 9) THEN
            BEGIN
              SELECT FIRST 1 L9.OBJ_ID
              FROM LINKS L2
              JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
              JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
              JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0 AND V49.LISTVAL_ID = :STAGE_ID
              JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
              LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C ON 1 = 1
              WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND C.CAPTION = :S
              INTO :V$FOLDER_ID;
            END
            ELSE
            BEGIN
              -- академический отпуск, создаем если его нет
              SELECT FIRST 1 L289.OBJ_ID
              FROM LINKS L2
              JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
              JOIN LINKS L289 ON L289.PARENT_ID = L7.OBJ_ID AND L289.OBJ_TYPE_ID = 289 AND L289.DATE_DEL IS NULL
              WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
              INTO :V$FOLDER_ID;

              IF(V$FOLDER_ID IS NULL)  THEN
              BEGIN
                SELECT FIRST 1 L7.OBJ_ID
                FROM LINKS L2
                JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
                WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
                INTO :V$LEVEL_ID;

                SELECT OBJ_ID FROM OBJECT_ADD(:V$LEVEL_ID, 289) INTO :V$FOLDER_ID;
                UPDATE LINKS SET LISTVAL_ID = :V$JOB_ID WHERE OBJ_ID = :V$FOLDER_ID;
              END
            END
            IF(V$FOLDER_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не удалось найти учебный коллектив назначения: ' || S;
          END
          ELSE
          BEGIN
            SELECT FIRST 1 L290.OBJ_ID
            FROM LINKS L290
            JOIN VALL V2346 ON V2346.OBJ_ID = L290.OBJ_ID AND V2346.PARAM_ID = 2346 AND V2346.IS_DEL = 0 AND V2346.LISTVAL_ID = :STAGE_ID
            WHERE L290.PARENT_ID = :V$ROOT_ID AND L290.OBJ_TYPE_ID = 290 AND L290.DATE_DEL IS NULL
            INTO :V$FOLDER_ID;

            IF(V$FOLDER_ID IS NULL) THEN
            BEGIN
              SELECT OBJ_ID FROM OBJECT_ADD(:V$ROOT_ID, 290, NULL, NULL, 1) INTO :V$FOLDER_ID;
              SELECT BLOB_ID FROM VAL_ADD(2346, :V$FOLDER_ID, :STAGE_ID) INTO :T;
            END
          END

          -- Вносим персону
          SELECT OBJ_ID FROM OBJECT_ADD(:V$FOLDER_ID, 10) INTO :PERSON_ID;
          UPDATE LINKS SET LISTVAL_ID = :OBJ_ID WHERE PARENT_ID = :V$FOLDER_ID AND OBJ_ID = :PERSON_ID;

          -- Копируем поля персоны
          FOR
            SELECT PARAM_ID
            FROM FIX_MERGE_DB_VALS(:OBJ_ID, :PERSON_ID, :V)
            INTO :PARAM_ID
          DO
          BEGIN
            SUSPEND;
          END

          -- Запоминаем название класса в #3025
          SELECT 1 FROM VAL_ADD(3025, :PERSON_ID, :S) INTO :T;

          -- Самого ученика кладем в проект приказа
          /*INSERT INTO ORDER_DATA
          (ORDER_ID, REF_ID, ACTION_TYPE, IS_PRESENT, DST_DATA)
          VALUES (:V$ORDER_ID, :PERSON_ID, 0, IIF(:I$ADJYEAR = 0, 1, 0), :S);*/

          -- Копируем подчиненные объекты на 1 уровень вложения
          V$CHILD_ID = 0;
          WHILE(V$CHILD_ID IS NOT NULL) DO
          BEGIN

            V$PREV_ID = V$CHILD_ID;
            V$CHILD_ID = NULL;

            EXECUTE STATEMENT
              'SELECT FIRST 1 L.OBJ_ID, L.OBJ_TYPE_ID
              FROM LINKS L
              WHERE L.PARENT_ID = ' || OBJ_ID || ' AND L.OBJ_TYPE_ID NOT IN (20, 120, 123, 292, 455) AND L.DATE_DEL IS NULL AND L.OBJ_ID > ' || V$PREV_ID || '
              ORDER BY 1'
            ON EXTERNAL :V
            WITH COMMON TRANSACTION
            INTO :V$CHILD_ID, :STAGE_ID;

            IF(V$CHILD_ID IS NOT NULL) THEN
            BEGIN
              SELECT OBJ_ID FROM OBJECT_ADD(:PERSON_ID, :STAGE_ID) INTO :CHILD_ID;
              FOR
                SELECT PARAM_ID
                FROM FIX_MERGE_DB_VALS(:V$CHILD_ID, :CHILD_ID, :V)
                INTO :PARAM_ID
              DO
              BEGIN
                SUSPEND;
              END
              N = N + 1;
            END

          END

          -- Записи движения
          IF(((V$THIS_LC = 'S' AND V$SRC_LC = 'D') OR (V$THIS_LC = 'C' AND V$SRC_LC = 'C')) AND I$ADJYEAR = 0) THEN
          BEGIN
            FOR
              SELECT MOVE_ID
              FROM FIX_MERGE_DB_MOVEMENTS(:OBJ_ID, :PERSON_ID, :V, :V$OU_ID)
              INTO :PARAM_ID
            DO
            BEGIN
              SUSPEND;
            END
          END

          PARAM_ID = NULL;
          SUSPEND;

        END
      END
    END

    -- При переносе садов - импорт выбывших и окончивших
    -- только при импорте в мультипараграф из базы ДОУ
    -- TODO добавить то же самое для колледжей
    -- Для СПО: включается при импорте из СПО в СПО
    OBJ_ID = 0;

    V$ROOT_ID = NULL;
    SELECT FIRST 1 L78.OBJ_ID
    FROM LINKS L2
    JOIN LINKS L78 ON L78.PARENT_ID = L2.OBJ_ID AND L78.OBJ_TYPE_ID = 78 AND L78.DATE_DEL IS NULL
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :V$ROOT_ID;

    IF(((V$THIS_LC = 'S' AND V$SRC_LC = 'D') OR (V$THIS_LC = 'C' AND V$SRC_LC = 'C')) AND I$ADJYEAR = 0) THEN
    WHILE(OBJ_ID IS NOT NULL) DO
    BEGIN

      -- С выбывшими ДОУ нельзя полагаться на регид, его там не будет
      -- Импортируем с надеждой что у нас нет полных тезок
      V$PREV_ID = OBJ_ID;
      OBJ_ID = NULL;
      N = 0;
      EXECUTE STATEMENT
        'SELECT FIRST 1 L10.OBJ_ID, L8X.OBJ_TYPE_ID, VT.LISTVAL_ID, V443.LISTVAL_ID, VY.VAL, C.C1 || D.RESULT
        FROM LINKS L2
        JOIN LINKS L78 ON L78.PARENT_ID = L2.OBJ_ID AND L78.OBJ_TYPE_ID = 78 AND L78.DATE_DEL IS NULL
        JOIN LINKS L8X ON L8X.PARENT_ID = L78.OBJ_ID AND L8X.OBJ_TYPE_ID IN (81, 82, 83) AND L8X.DATE_DEL IS NULL
        JOIN VALL VT ON VT.OBJ_ID = L8X.OBJ_ID AND VT.PARAM_ID IN (446, 447, 450) AND VT.IS_DEL = 0
        LEFT JOIN VALL V443 ON V443.OBJ_ID = L8X.OBJ_ID AND V443.PARAM_ID = 443 AND V443.IS_DEL = 0
        JOIN VALI VY ON VY.OBJ_ID = L8X.OBJ_ID AND VY.PARAM_ID IN (444, 448, 451) AND VY.IS_DEL = 0
        JOIN LINKS L10 ON L10.PARENT_ID = L8X.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        JOIN VALD V89 ON V89.OBJ_ID = L10.OBJ_ID AND V89.PARAM_ID = 89 AND V89.IS_DEL = 0
        LEFT JOIN BUILD_REP_FIO(L10.OBJ_ID, 55, 56, 57, 1) C ON 1 = 1
        LEFT JOIN DATE2STR(V89.VAL) D ON 1 = 1
        WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND L10.OBJ_ID > ' || V$PREV_ID || '
        ORDER BY 1'
      ON EXTERNAL :V
      WITH COMMON TRANSACTION
      INTO :OBJ_ID, :V$LEAVE_ID, :V$LEAVE_TYPE, :STAGE_ID, :Y, :S;

      IF(OBJ_ID IS NOT NULL) THEN
      BEGIN
        V$FOLDER_ID = NULL;
        IF(V$LEAVE_ID = 81) THEN BEGIN V$PARAM = 446; V$PARAM2 = 444; END
        IF(V$LEAVE_ID = 82) THEN BEGIN V$PARAM = 447; V$PARAM2 = 448; END
        IF(V$LEAVE_ID = 83) THEN BEGIN V$PARAM = 450; V$PARAM2 = 451; END

        SELECT FIRST 1 L8X.OBJ_ID
        FROM LINKS L8X
        JOIN VALL VT ON VT.OBJ_ID = L8X.OBJ_ID AND VT.PARAM_ID = :V$PARAM AND VT.IS_DEL = 0 AND VT.LISTVAL_ID = :V$LEAVE_TYPE
        LEFT JOIN VALL V443 ON V443.OBJ_ID = L8X.OBJ_ID AND V443.PARAM_ID = 443 AND V443.IS_DEL = 0
        JOIN VALI VY ON VY.OBJ_ID = L8X.OBJ_ID AND VY.PARAM_ID = :V$PARAM2 AND VY.IS_DEL = 0 AND VY.VAL = :Y
        WHERE L8X.PARENT_ID = :V$ROOT_ID AND L8X.OBJ_TYPE_ID = :V$LEAVE_ID AND L8X.DATE_DEL IS NULL AND (:V$LEAVE_ID <> 81 OR V443.LISTVAL_ID = :STAGE_ID)
        INTO :V$FOLDER_ID;

        IF(V$FOLDER_ID IS NULL) THEN
        BEGIN
          SELECT OBJ_ID FROM OBJECT_ADD(:V$ROOT_ID, :V$LEAVE_ID, NULL, NULL, 1) INTO :V$FOLDER_ID;
          SELECT BLOB_ID FROM VAL_ADD(:V$PARAM, :V$FOLDER_ID, :V$LEAVE_TYPE) INTO :T;
          IF(V$LEAVE_ID = 81) THEN SELECT BLOB_ID FROM VAL_ADD(443, :V$FOLDER_ID, :STAGE_ID) INTO :T;
          SELECT BLOB_ID FROM VAL_ADD(:V$PARAM2, :V$FOLDER_ID, :Y) INTO :T;
          IF(V$LEAVE_ID = 81) THEN SELECT BLOB_ID FROM VAL_ADD(445, :V$FOLDER_ID, :Y + 1) INTO :T;
          IF(V$LEAVE_ID = 82) THEN SELECT BLOB_ID FROM VAL_ADD(449, :V$FOLDER_ID, :Y + 1) INTO :T;
        END

        -- Проверяем, что персоны нет среди учащихся школы
        -- если она есть, то втягиваем только историю движения, а атрибутивный состав пропускаем
        PERSON_ID = NULL;
        SELECT FIRST 1 L10.OBJ_ID
        FROM LINKS L10
        JOIN VALD V89 ON V89.OBJ_ID = L10.OBJ_ID AND V89.PARAM_ID = 89 AND V89.IS_DEL = 0
        LEFT JOIN BUILD_REP_FIO(L10.OBJ_ID, 55, 56, 57, 1) C ON 1 = 1
        LEFT JOIN DATE2STR(V89.VAL) D ON 1 = 1
        WHERE L10.OBJ_TYPE_ID = 10 AND L10.PARENT_TYPE_ID IN (9, 81, 82, 83) AND L10.DATE_DEL IS NULL AND (C.C1 || D.RESULT) = :S
        INTO :PERSON_ID;

        IF(PERSON_ID IS NULL) THEN
        BEGIN
          -- Вносим персону
          SELECT OBJ_ID FROM OBJECT_ADD(:V$FOLDER_ID, 10) INTO :PERSON_ID;
          UPDATE LINKS SET LISTVAL_ID = :OBJ_ID WHERE PARENT_ID = :V$FOLDER_ID AND OBJ_ID = :PERSON_ID;

          -- Копируем поля персоны
          FOR
            SELECT PARAM_ID
            FROM FIX_MERGE_DB_VALS(:OBJ_ID, :PERSON_ID, :V)
            INTO :PARAM_ID
          DO
          BEGIN
            SUSPEND;
          END

          -- Копируем подчиненные объекты на 1 уровень вложения
          V$CHILD_ID = 0;
          WHILE(V$CHILD_ID IS NOT NULL) DO
          BEGIN

            V$PREV_ID = V$CHILD_ID;
            V$CHILD_ID = NULL;

            EXECUTE STATEMENT
              'SELECT FIRST 1 L.OBJ_ID, L.OBJ_TYPE_ID
              FROM LINKS L
              WHERE L.PARENT_ID = ' || OBJ_ID || ' AND L.OBJ_TYPE_ID NOT IN (20, 120, 123, 292, 455) AND L.DATE_DEL IS NULL AND L.OBJ_ID > ' || V$PREV_ID || '
              ORDER BY 1'
            ON EXTERNAL :V
            WITH COMMON TRANSACTION
            INTO :V$CHILD_ID, :STAGE_ID;

            IF(V$CHILD_ID IS NOT NULL) THEN
            BEGIN
              SELECT OBJ_ID FROM OBJECT_ADD(:PERSON_ID, :STAGE_ID) INTO :CHILD_ID;
              FOR
                SELECT PARAM_ID
                FROM FIX_MERGE_DB_VALS(:V$CHILD_ID, :CHILD_ID, :V)
                INTO :PARAM_ID
              DO
              BEGIN
                SUSPEND;
              END
              N = N + 1;
            END

          END
        END

        -- Записи движения
        FOR
          SELECT MOVE_ID
          FROM FIX_MERGE_DB_MOVEMENTS(:OBJ_ID, :PERSON_ID, :V, :V$OU_ID)
          INTO :PARAM_ID
        DO
        BEGIN
          SUSPEND;
        END

        PARAM_ID = NULL;
        SUSPEND;
      END
    END
  END

  -- Должности и сотрудники
  IF(BIN_AND(I$FLAGS, 2) <> 0) THEN
  BEGIN

    -- Если идет импорт из ДОУ в Мультипараграф, проверяем подразделение ДОУ
    -- если оно есть - импорт и должносей, и сотрудников будет идти в него
    V$DIV_ID = V$OU_ID;
    IF(V$THIS_LC = 'S' AND V$SRC_LC = 'D') THEN
    SELECT FIRST 1 L211.OBJ_ID
    FROM LINKS L211
    JOIN VALL V2102 ON V2102.OBJ_ID = L211.OBJ_ID AND V2102.PARAM_ID = 2102 AND V2102.IS_DEL = 0 AND V2102.LISTVAL_ID = 14245
    WHERE L211.PARENT_ID = :V$OU_ID AND L211.OBJ_TYPE_ID = 211 AND L211.DATE_DEL IS NULL
    INTO :V$DIV_ID;

    -- Должности, на которых есть хотя бы один сотрудник
    OBJ_ID = 0;
    WHILE(OBJ_ID IS NOT NULL) DO
    BEGIN

      V$PREV_ID = OBJ_ID;
      OBJ_ID = NULL;
      N = 0;

      EXECUTE STATEMENT
        'SELECT FIRST 1 L13.OBJ_ID, V58.LISTVAL_ID, C.CAPTION
        FROM LINKS L2
        JOIN LINKS L13 ON L13.PARENT_ID = L2.OBJ_ID AND L13.OBJ_TYPE_ID = 13 AND L13.DATE_DEL IS NULL
        JOIN VALL V58 ON V58.OBJ_ID = L13.OBJ_ID AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0
        LEFT JOIN OBJECT_CAPTION_GET(L13.OBJ_ID) C ON 1 = 1
        WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND L13.OBJ_ID > ' || V$PREV_ID || '
        AND EXISTS (
          SELECT FIRST 1 1
          FROM LINKS L15
          LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
          WHERE L15.PARENT_ID = L13.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL AND V74.VAL IS NULL
        )
        ORDER BY 1'
      ON EXTERNAL :V
      WITH COMMON TRANSACTION
      INTO :OBJ_ID, :STAGE_ID, :S;

      IF(OBJ_ID IS NOT NULL) THEN
      BEGIN

        -- Проверяем что такой у нас нет
        -- Нельзя через CAPTION, там добавляется название подразделения
        V$CHILD_ID = NULL;
        SELECT FIRST 1 L13.OBJ_ID
        FROM LINKS L13
        JOIN VALL V58 ON V58.OBJ_ID = L13.OBJ_ID AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0 AND V58.LISTVAL_ID = :STAGE_ID
        JOIN VALS V66 ON V66.OBJ_ID = L13.OBJ_ID AND V66.PARAM_ID = 66 AND V66.IS_DEL = 0 AND V66.VAL = :S
        WHERE L13.PARENT_ID = :V$DIV_ID AND L13.OBJ_TYPE_ID = 13 AND L13.DATE_DEL IS NULL
        INTO :V$CHILD_ID;

        IF(V$CHILD_ID IS NULL) THEN
        BEGIN
          -- Вносим должность
          SELECT OBJ_ID FROM OBJECT_ADD(:V$DIV_ID, 13) INTO :PERSON_ID;
          UPDATE LINKS SET LISTVAL_ID = :OBJ_ID WHERE PARENT_ID = :V$DIV_ID AND OBJ_ID = :PERSON_ID;

          -- Копируем поля должности
          FOR
            SELECT PARAM_ID
            FROM FIX_MERGE_DB_VALS(:OBJ_ID, :PERSON_ID, :V)
            INTO :PARAM_ID
          DO
          BEGIN
            SUSPEND;
          END

          PARAM_ID = NULL;
          SUSPEND;
        END
        ELSE
        BEGIN
          -- Надо запомнить ID должности в LISTVAL
          UPDATE LINKS
          SET LISTVAL_ID = :OBJ_ID
          WHERE OBJ_ID = :V$CHILD_ID AND (LISTVAL_ID IS NULL OR LISTVAL_ID <> :OBJ_ID);
        END
      END

    END

    -- Сотрудники, у которых есть хотя бы одна активная должность
    -- Только с заполненным СНИЛС
    OBJ_ID = 0;
    WHILE(OBJ_ID IS NOT NULL) DO
    BEGIN

      V$PREV_ID = OBJ_ID;
      OBJ_ID = NULL;
      N = 0;

      EXECUTE STATEMENT
        'SELECT FIRST 1 L14.OBJ_ID, V2455.VAL
        FROM LINKS L2
        JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
        JOIN VALS V2455 ON V2455.OBJ_ID = L14.OBJ_ID AND V2455.PARAM_ID = 2455 AND V2455.IS_DEL = 0
        WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND L14.OBJ_ID > ' || V$PREV_ID || '
        ORDER BY 1'
      ON EXTERNAL :V
      WITH COMMON TRANSACTION
      INTO :OBJ_ID, :S;

      IF(OBJ_ID IS NOT NULL) THEN
      BEGIN

        -- Проверяем что такого у нас нет
        V$CHILD_ID = NULL;
        SELECT FIRST 1 L14.OBJ_ID
        FROM LINKS L14
        JOIN VALS V2455 ON V2455.OBJ_ID = L14.OBJ_ID AND V2455.PARAM_ID = 2455 AND V2455.IS_DEL = 0 AND V2455.VAL = :S
        WHERE L14.PARENT_ID = :V$DIV_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
        INTO :V$CHILD_ID;

        -- Первая ветка - вдруг сотрудник есть в ОУ, но нет в подразделении ?
        IF(V$CHILD_ID IS NULL AND V$DIV_ID <> V$OU_ID) THEN
        BEGIN
          SELECT FIRST 1 L14.OBJ_ID
          FROM LINKS L14
          JOIN VALS V2455 ON V2455.OBJ_ID = L14.OBJ_ID AND V2455.PARAM_ID = 2455 AND V2455.IS_DEL = 0 AND V2455.VAL = :S
          WHERE L14.PARENT_ID = :V$OU_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
          INTO :V$CHILD_ID;

          IF(V$CHILD_ID IS NOT NULL) THEN
          BEGIN
            -- Добавляем связь, но данные самого сотрудника не трогаем
            SELECT OBJ_ID FROM OBJECT_ADD_LINK(:V$DIV_ID, :V$CHILD_ID, 14) INTO :PERSON_ID;
            UPDATE LINKS SET LISTVAL_ID = :OBJ_ID WHERE PARENT_ID = :V$DIV_ID AND OBJ_ID = :PERSON_ID;

            -- Копируем только должности в подразделении - раз сотрудник уже и так есть
            -- Копируем подчиненные объекты на 1 уровень вложения, включая активные должности
            V$CHILD_ID = 0;
            WHILE(V$CHILD_ID IS NOT NULL) DO
            BEGIN

              V$PREV_ID = V$CHILD_ID;
              V$CHILD_ID = NULL;

              EXECUTE STATEMENT
                'SELECT FIRST 1 L.OBJ_ID, L.OBJ_TYPE_ID, LP13.PARENT_ID, V73.VAL
                FROM LINKS L
                LEFT JOIN VALD V74 ON V74.OBJ_ID = L.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
                LEFT JOIN LINKS LP13 ON LP13.OBJ_ID = L.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
                LEFT JOIN VALD V73 ON V73.OBJ_ID = L.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0
                WHERE L.PARENT_ID = ' || OBJ_ID || ' AND L.OBJ_TYPE_ID = 15 AND L.DATE_DEL IS NULL AND L.OBJ_ID > ' || V$PREV_ID || '
                  AND (L.OBJ_TYPE_ID <> 15 OR V74.VAL IS NULL)
                ORDER BY 1'
              ON EXTERNAL :V
              WITH COMMON TRANSACTION
              INTO :V$CHILD_ID, :STAGE_ID, :V$FOLDER_ID, :V$DATE;

              IF(V$CHILD_ID IS NOT NULL) THEN
              BEGIN
                SELECT OBJ_ID FROM OBJECT_ADD(:PERSON_ID, :STAGE_ID) INTO :CHILD_ID;
                FOR
                  SELECT PARAM_ID
                  FROM FIX_MERGE_DB_VALS(:V$CHILD_ID, :CHILD_ID, :V)
                  INTO :PARAM_ID
                DO
                BEGIN
                  SUSPEND;
                END

                -- Должность - связываем с новой должностью, он не может не найтись
                IF(STAGE_ID = 15) THEN
                BEGIN
                  V$JOB_ID = NULL;
                  SELECT FIRST 1 L13.OBJ_ID
                  FROM LINKS L13
                  WHERE L13.PARENT_ID = :V$DIV_ID AND L13.OBJ_TYPE_ID = 13 AND L13.DATE_DEL IS NULL AND L13.LISTVAL_ID = :V$FOLDER_ID
                  INTO :V$JOB_ID;

                  INSERT INTO LINKS
                  (PARENT_ID, OBJ_ID, DATE_INS)
                  VALUES (:V$JOB_ID, :CHILD_ID, CURRENT_TIMESTAMP);

                  -- Прописываем вынесенные поля в самой должности
                  -- ссылка на саму должность
                  SELECT 1 FROM VAL_ADD(69, :CHILD_ID, :V$JOB_ID) INTO :T;
                  -- поля с кодификаторами должности пока не заполняем, но вероятно тоже будет нужно

                END

                N = N + 1;
              END

            END

            PARAM_ID = NULL;
            V$CHILD_ID = 0; -- чтобы не сработала вторая ветка
            SUSPEND;
          END
        END

        -- Вторая ветка - сотрудника вообще нет
        IF(V$CHILD_ID IS NULL) THEN
        BEGIN
          -- Вносим сотрудника
          SELECT OBJ_ID FROM OBJECT_ADD(:V$DIV_ID, 14) INTO :PERSON_ID;
          UPDATE LINKS SET LISTVAL_ID = :OBJ_ID WHERE PARENT_ID = :V$DIV_ID AND OBJ_ID = :PERSON_ID;

          -- Копируем поля сотрудника
          FOR
            SELECT PARAM_ID
            FROM FIX_MERGE_DB_VALS(:OBJ_ID, :PERSON_ID, :V)
            INTO :PARAM_ID
          DO
          BEGIN
            SUSPEND;
          END

          -- Копируем подчиненные объекты на 1 уровень вложения, включая активные должности
          V$CHILD_ID = 0;
          WHILE(V$CHILD_ID IS NOT NULL) DO
          BEGIN

            V$PREV_ID = V$CHILD_ID;
            V$CHILD_ID = NULL;

            EXECUTE STATEMENT
              'SELECT FIRST 1 L.OBJ_ID, L.OBJ_TYPE_ID, LP13.PARENT_ID, V73.VAL
              FROM LINKS L
              LEFT JOIN VALD V74 ON V74.OBJ_ID = L.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
              LEFT JOIN LINKS LP13 ON LP13.OBJ_ID = L.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
              LEFT JOIN VALD V73 ON V73.OBJ_ID = L.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0
              WHERE L.PARENT_ID = ' || OBJ_ID || ' AND L.OBJ_TYPE_ID NOT IN (37, 51, 57, 100, 101, 139, 156, 397, 455) AND L.DATE_DEL IS NULL AND L.OBJ_ID > ' || V$PREV_ID || '
                AND (L.OBJ_TYPE_ID <> 15 OR V74.VAL IS NULL)
              ORDER BY 1'
            ON EXTERNAL :V
            WITH COMMON TRANSACTION
            INTO :V$CHILD_ID, :STAGE_ID, :V$FOLDER_ID, :V$DATE;

            IF(V$CHILD_ID IS NOT NULL) THEN
            BEGIN
              SELECT OBJ_ID FROM OBJECT_ADD(:PERSON_ID, :STAGE_ID) INTO :CHILD_ID;
              FOR
                SELECT PARAM_ID
                FROM FIX_MERGE_DB_VALS(:V$CHILD_ID, :CHILD_ID, :V)
                INTO :PARAM_ID
              DO
              BEGIN
                SUSPEND;
              END

              -- Должность - связываем с новой должностью, он не может не найтись
              IF(STAGE_ID = 15) THEN
              BEGIN
                V$JOB_ID = NULL;
                SELECT FIRST 1 L13.OBJ_ID
                FROM LINKS L13
                WHERE L13.PARENT_ID = :V$DIV_ID AND L13.OBJ_TYPE_ID = 13 AND L13.DATE_DEL IS NULL AND L13.LISTVAL_ID = :V$FOLDER_ID
                INTO :V$JOB_ID;

                INSERT INTO LINKS
                (PARENT_ID, OBJ_ID, DATE_INS)
                VALUES (:V$JOB_ID, :CHILD_ID, CURRENT_TIMESTAMP);

                -- Прописываем вынесенные поля в самой должности
                -- ссылка на саму должность
                SELECT 1 FROM VAL_ADD(69, :CHILD_ID, :V$JOB_ID) INTO :T;
                -- поля с кодификаторами должности пока не заполняем, но вероятно тоже будет нужно

              END

              N = N + 1;
            END
          END

          PARAM_ID = NULL;
          SUSPEND;
        END
      END
    END
  END

  -- УП, только утвержденные и групповые, где есть ГУП (либо где не заполнено - ДОУ и СПО)
  IF(BIN_AND(I$FLAGS, 4) <> 0) THEN
  BEGIN

    OBJ_ID = 0;
    WHILE(OBJ_ID IS NOT NULL) DO
    BEGIN

      V$PREV_ID = OBJ_ID;
      OBJ_ID = NULL;
      N = 0;

      EXECUTE STATEMENT
        'SELECT FIRST 1 V2450.LISTVAL_ID, V1832.LISTVAL_ID, L57.OBJ_ID, L400.OBJ_ID, C.CAPTION, CP.CAPTION
        FROM LINKS L2
        JOIN LINKS L69 ON L69.PARENT_ID = L2.OBJ_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL
        JOIN VALL V2450 ON V2450.OBJ_ID = L69.OBJ_ID AND V2450.PARAM_ID = 2450 AND V2450.IS_DEL = 0
        JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
        JOIN VALL V1832 ON V1832.OBJ_ID = L57.OBJ_ID AND V1832.PARAM_ID = 1832 AND V1832.IS_DEL = 0
        LEFT JOIN OBJECT_CAPTION_GET(L57.OBJ_ID) C ON 1 = 1
        JOIN LINKS L400 ON L400.PARENT_ID = L57.OBJ_ID AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL
        JOIN VALL V3013 ON V3013.OBJ_ID = L400.OBJ_ID AND V3013.PARAM_ID = 3013 AND V3013.IS_DEL = 0 AND V3013.LISTVAL_ID = 11715
        JOIN VALL V3016 ON V3016.OBJ_ID = L400.OBJ_ID AND V3016.PARAM_ID = 3016 AND V3016.IS_DEL = 0
        LEFT JOIN OBJECT_CAPTION_GET(L400.OBJ_ID) CP ON 1 = 1
        WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND L400.OBJ_ID > ' || V$PREV_ID || '
          AND (V3016.LISTVAL_ID = 5465 OR V3016.LISTVAL_ID IS NULL)
        AND EXISTS (
          SELECT FIRST 1 1
          FROM LINKS L54
          JOIN LINKS L256 ON L256.PARENT_ID = L54.OBJ_ID AND L256.OBJ_TYPE_ID = 256 AND L256.DATE_DEL IS NULL
          WHERE L54.PARENT_ID = L400.OBJ_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
        )
        ORDER BY 4'
      ON EXTERNAL :V
      WITH COMMON TRANSACTION
      INTO :V$LEVEL_ID, :STAGE_ID, :V$ROOT_ID, :OBJ_ID, :S, :S2;

      IF(OBJ_ID IS NOT NULL) THEN
      BEGIN

        -- Ищем раздел ОП, который должен быть
        V$FOLDER_ID = NULL;
        SELECT FIRST 1 L69.OBJ_ID
        FROM LINKS L69
        JOIN VALL V2450 ON V2450.OBJ_ID = L69.OBJ_ID AND V2450.PARAM_ID = 2450 AND V2450.IS_DEL = 0 AND V2450.LISTVAL_ID = :V$LEVEL_ID
        WHERE L69.PARENT_ID = :V$OU_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL
        INTO :V$FOLDER_ID;

        IF(V$FOLDER_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Отсутствует раздел образовательных программ для одного или более типа образования';

        -- Ищем/создаем ОП нужного вида и названия
        V$REF_ID = NULL;
        SELECT FIRST 1 L57.OBJ_ID
        FROM LINKS L57
        JOIN VALL V1832 ON V1832.OBJ_ID = L57.OBJ_ID AND V1832.PARAM_ID = 1832 AND V1832.IS_DEL = 0 AND V1832.LISTVAL_ID = :STAGE_ID
        LEFT JOIN OBJECT_CAPTION_GET(L57.OBJ_ID) C ON 1 = 1
        WHERE L57.PARENT_ID = :V$FOLDER_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL AND C.CAPTION = :S
        INTO :V$REF_ID;

        IF(V$REF_ID IS NULL) THEN
        BEGIN
          SELECT OBJ_ID FROM OBJECT_ADD(:V$FOLDER_ID, 57) INTO :V$REF_ID;
          FOR
            SELECT PARAM_ID
            FROM FIX_MERGE_DB_VALS(:V$ROOT_ID, :V$REF_ID, :V, 57)
            INTO :PARAM_ID
          DO
          BEGIN
            SUSPEND;
          END
        END

        -- Проверяем наличие самого УП
        V$CHILD_ID = NULL;
        SELECT FIRST 1 L400.OBJ_ID
        FROM LINKS L400
        WHERE L400.PARENT_ID = :V$REF_ID AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL AND L400.LISTVAL_ID = :OBJ_ID
        INTO :V$CHILD_ID;

        IF(V$CHILD_ID IS NULL) THEN
        BEGIN
          -- Вносим УП
          SELECT OBJ_ID FROM OBJECT_ADD(:V$REF_ID, 400) INTO :PERSON_ID;
          UPDATE LINKS SET LISTVAL_ID = :OBJ_ID WHERE PARENT_ID = :V$REF_ID AND OBJ_ID = :PERSON_ID;

          -- Копируем поля УП
          FOR
            SELECT PARAM_ID
            FROM FIX_MERGE_DB_VALS(:OBJ_ID, :PERSON_ID, :V)
            INTO :PARAM_ID
          DO
          BEGIN
            SUSPEND;
          END

          -- Копируем содержимое УП
          FOR
            SELECT PARAM_ID
            FROM FIX_MERGE_PLAN(:OBJ_ID, :PERSON_ID, :V)
            INTO :PARAM_ID
          DO
          BEGIN
            SUSPEND;
          END

          PARAM_ID = NULL;
          SUSPEND;
        END
        ELSE
        BEGIN
          -- Надо запомнить ID должности в LISTVAL
          UPDATE LINKS
          SET LISTVAL_ID = :OBJ_ID
          WHERE OBJ_ID = :V$CHILD_ID AND PARENT_ID = :V$REF_ID AND (LISTVAL_ID IS NULL OR LISTVAL_ID <> :OBJ_ID);
        END
      END
    END
  END

  -- Здания и прочее
  IF(BIN_AND(I$FLAGS, 8) <> 0) THEN
  BEGIN

    -- Каталог земельных участков
    V$FOLDER_ID = NULL;
    SELECT FIRST 1 L488.OBJ_ID
    FROM LINKS L488
    WHERE L488.PARENT_ID = :V$OU_ID AND L488.OBJ_TYPE_ID = 488 AND L488.DATE_DEL IS NULL
    INTO :V$FOLDER_ID;

    OBJ_ID = 0;
    WHILE(OBJ_ID IS NOT NULL) DO
    BEGIN

      V$PREV_ID = OBJ_ID;
      OBJ_ID = NULL;
      N = 0;

      EXECUTE STATEMENT
        'SELECT FIRST 1 L490.OBJ_ID
        FROM LINKS L2
        JOIN LINKS L488 ON L488.PARENT_ID = L2.OBJ_ID AND L488.OBJ_TYPE_ID = 488 AND L488.DATE_DEL IS NULL
        JOIN LINKS L490 ON L490.PARENT_ID = L488.OBJ_ID AND L490.OBJ_TYPE_ID = 490 AND L490.DATE_DEL IS NULL
        WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND L490.OBJ_ID > ' || V$PREV_ID || '
        ORDER BY 1'
      ON EXTERNAL :V
      WITH COMMON TRANSACTION
      INTO :OBJ_ID;

      IF(OBJ_ID IS NOT NULL) THEN
      BEGIN

        -- Проверяем что такой у нас нет
        V$CHILD_ID = NULL;
        SELECT FIRST 1 L490.OBJ_ID
        FROM LINKS L490
        WHERE L490.PARENT_ID = :V$FOLDER_ID AND L490.OBJ_TYPE_ID = 490 AND L490.DATE_DEL IS NULL AND L490.LISTVAL_ID = :OBJ_ID
        INTO :V$CHILD_ID;

        IF(V$CHILD_ID IS NULL) THEN
        BEGIN
          -- Вносим участок
          SELECT OBJ_ID FROM OBJECT_ADD(:V$FOLDER_ID, 490) INTO :PERSON_ID;
          UPDATE LINKS SET LISTVAL_ID = :OBJ_ID WHERE PARENT_ID = :V$FOLDER_ID AND OBJ_ID = :PERSON_ID;

          -- Копируем поля участка
          FOR
            SELECT PARAM_ID
            FROM FIX_MERGE_DB_VALS(:OBJ_ID, :PERSON_ID, :V)
            INTO :PARAM_ID
          DO
          BEGIN
            SUSPEND;
          END

          PARAM_ID = NULL;
          SUSPEND;
        END
      END

    END

    -- Каталог зданий
    V$FOLDER_ID = NULL;
    SELECT FIRST 1 L73.OBJ_ID
    FROM LINKS L73
    WHERE L73.PARENT_ID = :V$OU_ID AND L73.OBJ_TYPE_ID = 73 AND L73.DATE_DEL IS NULL
    INTO :V$FOLDER_ID;

    OBJ_ID = 0;
    WHILE(OBJ_ID IS NOT NULL) DO
    BEGIN

      V$PREV_ID = OBJ_ID;
      OBJ_ID = NULL;
      N = 0;

      EXECUTE STATEMENT
        'SELECT FIRST 1 L16.OBJ_ID, L16.OBJ_TYPE_ID, V3408.VAL
        FROM LINKS L2
        JOIN LINKS L73 ON L73.PARENT_ID = L2.OBJ_ID AND L73.OBJ_TYPE_ID = 73 AND L73.DATE_DEL IS NULL
        JOIN LINKS L16 ON L16.PARENT_ID = L73.OBJ_ID AND L16.OBJ_TYPE_ID IN (16, 492) AND L16.DATE_DEL IS NULL
        LEFT JOIN VALR V3408 ON V3408.OBJ_ID = L16.OBJ_ID AND V3408.PARAM_ID = 3408 AND V3408.IS_DEL = 0
        WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND L16.OBJ_ID > ' || V$PREV_ID || '
        ORDER BY 1'
      ON EXTERNAL :V
      WITH COMMON TRANSACTION
      INTO :OBJ_ID, :STAGE_ID, :V$REF_ID;

      IF(OBJ_ID IS NOT NULL) THEN
      BEGIN

        -- Проверяем что такой у нас нет
        V$CHILD_ID = NULL;
        SELECT FIRST 1 L16.OBJ_ID
        FROM LINKS L16
        WHERE L16.PARENT_ID = :V$FOLDER_ID AND L16.OBJ_TYPE_ID IN (16, 492) AND L16.DATE_DEL IS NULL AND L16.LISTVAL_ID = :OBJ_ID
        INTO :V$CHILD_ID;

        IF(V$CHILD_ID IS NULL) THEN
        BEGIN
          -- Вносим здание
          SELECT OBJ_ID FROM OBJECT_ADD(:V$FOLDER_ID, :STAGE_ID) INTO :PERSON_ID;
          UPDATE LINKS SET LISTVAL_ID = :OBJ_ID WHERE PARENT_ID = :V$FOLDER_ID AND OBJ_ID = :PERSON_ID;

          -- Копируем поля здания
          FOR
            SELECT PARAM_ID
            FROM FIX_MERGE_DB_VALS(:OBJ_ID, :PERSON_ID, :V)
            INTO :PARAM_ID
          DO
          BEGIN
            SUSPEND;
          END

          -- Восстанавливаем ссылку на земельный участок
          V$CHILD_ID = NULL;
          SELECT FIRST 1 L490.OBJ_ID
          FROM LINKS L490
          WHERE L490.PARENT_TYPE_ID = 488 AND L490.OBJ_TYPE_ID = 490 AND L490.DATE_DEL IS NULL AND L490.LISTVAL_ID = :V$REF_ID
          INTO :V$CHILD_ID;

          IF(V$CHILD_ID IS NOT NULL) THEN
          SELECT 1 FROM VAL_ADD(3408, :PERSON_ID, :V$CHILD_ID) INTO :V$CHILD_ID;

          -- Переносим помещения здания
          V$CHILD_ID = 0;
          WHILE(V$CHILD_ID IS NOT NULL) DO
          BEGIN

            V$PREV_ID = V$CHILD_ID;
            V$CHILD_ID = NULL;

            EXECUTE STATEMENT
              'SELECT FIRST 1 L.OBJ_ID, L.OBJ_TYPE_ID
              FROM LINKS L
              WHERE L.PARENT_ID = ' || OBJ_ID || ' AND L.OBJ_TYPE_ID = 61 AND L.DATE_DEL IS NULL AND L.OBJ_ID > ' || V$PREV_ID || '
              ORDER BY 1'
            ON EXTERNAL :V
            WITH COMMON TRANSACTION
            INTO :V$CHILD_ID, :STAGE_ID;

            IF(V$CHILD_ID IS NOT NULL) THEN
            BEGIN
              SELECT OBJ_ID FROM OBJECT_ADD(:PERSON_ID, :STAGE_ID) INTO :CHILD_ID;
              FOR
                SELECT PARAM_ID
                FROM FIX_MERGE_DB_VALS(:V$CHILD_ID, :CHILD_ID, :V)
                INTO :PARAM_ID
              DO
              BEGIN
                SUSPEND;
              END

              N = N + 1;
            END

          END

          PARAM_ID = NULL;
          SUSPEND;
        END
      END

    END

  END

  -- Матресурсы - тянем только те разделы, которые у нас уже есть
  IF(BIN_AND(I$FLAGS, 16) <> 0) THEN
  BEGIN

    OBJ_ID = 0;
    WHILE(OBJ_ID IS NOT NULL) DO
    BEGIN

      V$PREV_ID = OBJ_ID;
      OBJ_ID = NULL;
      N = 0;

      EXECUTE STATEMENT
        'SELECT FIRST 1 LL1.OBJ_TYPE_ID, LL2.OBJ_ID, LL2.OBJ_TYPE_ID
        FROM LINKS L2
        JOIN LINKS LL1 ON LL1.PARENT_ID = L2.OBJ_ID AND LL1.OBJ_TYPE_ID IN (23, 74, 92, 104, 105, 108) AND LL1.DATE_DEL IS NULL
        JOIN LINKS LL2 ON LL2.PARENT_ID = LL1.OBJ_ID AND LL2.OBJ_TYPE_ID IN (95, 114, 94, 97, 106, 107, 109) AND LL2.DATE_DEL IS NULL
        WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND LL2.OBJ_ID > ' || V$PREV_ID || '
        ORDER BY 1'
      ON EXTERNAL :V
      WITH COMMON TRANSACTION
      INTO :V$REF_ID, :OBJ_ID, :STAGE_ID;

      V$FOLDER_ID = NULL;
      SELECT FIRST 1 LL1.OBJ_ID
      FROM LINKS LL1
      WHERE LL1.PARENT_ID = :V$OU_ID AND LL1.OBJ_TYPE_ID = :V$REF_ID AND LL1.DATE_DEL IS NULL
      INTO :V$FOLDER_ID;

      IF(V$FOLDER_ID IS NULL) THEN OBJ_ID = NULL;

      IF(OBJ_ID IS NOT NULL) THEN
      BEGIN

        -- Проверяем что такой у нас нет
        V$CHILD_ID = NULL;
        SELECT FIRST 1 LL2.OBJ_ID
        FROM LINKS LL2
        WHERE LL2.PARENT_ID = :V$FOLDER_ID AND LL2.OBJ_TYPE_ID = :STAGE_ID AND LL2.DATE_DEL IS NULL AND LL2.LISTVAL_ID = :OBJ_ID
        INTO :V$CHILD_ID;

        IF(V$CHILD_ID IS NULL) THEN
        BEGIN
          -- Вносим объект
          SELECT OBJ_ID FROM OBJECT_ADD(:V$FOLDER_ID, :STAGE_ID) INTO :PERSON_ID;
          UPDATE LINKS SET LISTVAL_ID = :OBJ_ID WHERE PARENT_ID = :V$FOLDER_ID AND OBJ_ID = :PERSON_ID;

          -- Копируем поля объекта
          FOR
            SELECT PARAM_ID
            FROM FIX_MERGE_DB_VALS(:OBJ_ID, :PERSON_ID, :V)
            INTO :PARAM_ID
          DO
          BEGIN
            SUSPEND;
          END

          -- Переносим карточки
          V$CHILD_ID = 0;
          WHILE(V$CHILD_ID IS NOT NULL) DO
          BEGIN

            V$PREV_ID = V$CHILD_ID;
            V$CHILD_ID = NULL;

            EXECUTE STATEMENT
              'SELECT FIRST 1 L.OBJ_ID, L.OBJ_TYPE_ID
              FROM LINKS L
              WHERE L.PARENT_ID = ' || OBJ_ID || ' AND L.OBJ_TYPE_ID = 114 AND L.DATE_DEL IS NULL AND L.OBJ_ID > ' || V$PREV_ID || '
              ORDER BY 1'
            ON EXTERNAL :V
            WITH COMMON TRANSACTION
            INTO :V$CHILD_ID, :STAGE_ID;

            IF(V$CHILD_ID IS NOT NULL) THEN
            BEGIN
              SELECT OBJ_ID FROM OBJECT_ADD(:PERSON_ID, :STAGE_ID) INTO :CHILD_ID;
              FOR
                SELECT PARAM_ID
                FROM FIX_MERGE_DB_VALS(:V$CHILD_ID, :CHILD_ID, :V)
                INTO :PARAM_ID
              DO
              BEGIN
                SUSPEND;
              END

              N = N + 1;
            END

          END

          PARAM_ID = NULL;
          SUSPEND;
        END
      END

    END

  END

  -- Родители
  IF(BIN_AND(I$FLAGS, 32) <> 0) THEN
  BEGIN

    OBJ_ID = 0;
    WHILE(OBJ_ID IS NOT NULL) DO
    BEGIN

      V$PREV_ID = OBJ_ID;
      OBJ_ID = NULL;
      N = 0;

      EXECUTE STATEMENT
        'SELECT FIRST 1 L20.OBJ_ID, L10.OBJ_ID, L20.EXT_OBJ_ID
        FROM LINKS L2
        JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
        JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
        JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        JOIN LINKS L20 ON L20.PARENT_ID = L10.OBJ_ID AND L20.OBJ_TYPE_ID = 20 AND L20.DATE_DEL IS NULL
        WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND L20.OBJ_ID > ' || V$PREV_ID || '
        ORDER BY 1'
      ON EXTERNAL :V
      WITH COMMON TRANSACTION
      INTO :OBJ_ID, :STAGE_ID, :V$REF_ID;

      IF(OBJ_ID IS NOT NULL) THEN
      BEGIN

        -- Ищем ребенка
        V$ROOT_ID = NULL;
        SELECT FIRST 1 L10.OBJ_ID
        FROM LINKS L10
        WHERE L10.PARENT_TYPE_ID = 290 AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL AND L10.LISTVAL_ID = :STAGE_ID
        INTO :V$ROOT_ID;

        -- Если вдруг ученика нет в предварительном приеме, смотрим в действующих учениках, но связи надо искать именно из предварительного
        IF(V$ROOT_ID IS NULL) THEN
        SELECT FIRST 1 L10.OBJ_ID
        FROM LINKS L10
        JOIN LINKS LP9 ON LP9.OBJ_ID = L10.OBJ_ID AND LP9.PARENT_TYPE_ID = 9 AND LP9.DATE_DEL IS NULL
        WHERE L10.PARENT_TYPE_ID = 290 AND L10.OBJ_TYPE_ID = 10 AND L10.LISTVAL_ID = :STAGE_ID
        INTO :V$ROOT_ID;

        -- Ищем этого родителя среди других детей
        V$FOLDER_ID = NULL;
        V$LEVEL_ID = NULL;
        SELECT FIRST 1 L20.OBJ_ID, L20.PARENT_ID
        FROM LINKS L20
        WHERE L20.PARENT_TYPE_ID = 10 AND L20.OBJ_TYPE_ID = 20 AND L20.DATE_DEL IS NULL AND L20.LISTVAL_ID = :OBJ_ID
        ORDER BY IIF(L20.PARENT_ID = :V$ROOT_ID, 0, 1)
        INTO :V$FOLDER_ID, :V$LEVEL_ID;

        -- Вносим только если еще не внесен
        IF(V$ROOT_ID IS NOT NULL AND (V$LEVEL_ID IS NULL OR V$LEVEL_ID <> V$ROOT_ID))
        THEN
        BEGIN

          -- Если родителя еще не нет - вносим его
          IF(V$FOLDER_ID IS NULL) THEN
          BEGIN
            SELECT OBJ_ID, EXT_OBJ_ID FROM OBJECT_ADD(:V$ROOT_ID, 20, NULL, NULL, NULL, 0, NULL, CURRENT_TIMESTAMP, 168) INTO :PERSON_ID, :V$EXT_ID;
            FOR
              SELECT PARAM_ID
              FROM FIX_MERGE_DB_VALS(:OBJ_ID, :PERSON_ID, :V)
              INTO :PARAM_ID
            DO
            BEGIN
              SUSPEND;
            END
          END
          -- Вносим только связь с уже имеющимся родителем, данные не меняем
          ELSE
          BEGIN
            SELECT OBJ_ID, EXT_OBJ_ID FROM OBJECT_ADD_LINK(:V$ROOT_ID, :V$FOLDER_ID, 20, NULL, NULL, NULL, 0, NULL, 168) INTO :PERSON_ID, :V$EXT_ID;
          END
          -- Обновляем ссылку на импортированный объект
          UPDATE LINKS SET LISTVAL_ID = :OBJ_ID WHERE PARENT_ID = :V$ROOT_ID AND OBJ_ID = :PERSON_ID;

          -- Обновляем связь родитель-ученик
          FOR
            SELECT PARAM_ID
            FROM FIX_MERGE_DB_VALS(:V$REF_ID, :V$EXT_ID, :V)
            INTO :PARAM_ID
          DO
          BEGIN
            SUSPEND;
          END

          PARAM_ID = NULL;
          SUSPEND;

        END

      END

    END

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIX_MERGE_DB_MOVEMENTS (
    I$OBJ_ID BIGINT,
    I$DEST_ID BIGINT,
    I$SRC VARCHAR(400),
    I$OU_ID BIGINT)
RETURNS (
    MOVE_ID BIGINT)
AS
DECLARE VARIABLE V$PREV_ID BIGINT;
DECLARE VARIABLE V$GROUP_ID BIGINT;
DECLARE VARIABLE V$REASON_IN BIGINT;
DECLARE VARIABLE V$DATE_IN DATE;
DECLARE VARIABLE V$DATE_OUT DATE;
DECLARE VARIABLE V$STAGE_ID BIGINT;
DECLARE VARIABLE V$ORDER_DATE_IN DATE;
DECLARE VARIABLE V$ORDER_NUM_IN VARCHAR(400);
DECLARE VARIABLE V$ORDER_DATE_OUT DATE;
DECLARE VARIABLE V$ORDER_NUM_OUT VARCHAR(400);
DECLARE VARIABLE V$NAME_IN VARCHAR(400);
DECLARE VARIABLE V$REASON_OUT BIGINT;
DECLARE VARIABLE V$TYPE_IN BIGINT;
DECLARE VARIABLE V$IS_VD BIGINT;
DECLARE VARIABLE V$SOURCE_IN BIGINT;
DECLARE VARIABLE V$SOURCE_OUT BIGINT;
DECLARE VARIABLE V$PLAN_STAGES SMALLINT;
DECLARE VARIABLE V$STAGE_YEAR SMALLINT;
DECLARE VARIABLE V$GROUP_TYPE_ID BIGINT;
DECLARE VARIABLE V$LEVEL_ID BIGINT;
DECLARE VARIABLE V$GROUP_ID_DST BIGINT;
DECLARE VARIABLE V$FOLDER_ID BIGINT;
begin

  MOVE_ID = 0;
  WHILE(MOVE_ID IS NOT NULL) DO
  BEGIN
    V$PREV_ID = MOVE_ID;
    MOVE_ID = NULL;
    EXECUTE STATEMENT
      'SELECT FIRST 1 OBJ_ID, GROUP_ID, REASON_IN, DATE_IN, DATE_OUT, STAGE_ID, ORDER_DATE_IN, ORDER_NUM_IN, ORDER_DATE_OUT,
        ORDER_NUM_OUT, NAME_IN, REASON_OUT, TYPE_IN, IS_VD, SOURCE_IN, SOURCE_OUT, PLAN_STAGES, STAGE_YEAR, GROUP_TYPE_ID, LEVEL_ID
      FROM PERSON_MOVEMENTS M
      WHERE M.DATE_DEL IS NULL AND M.GROUP_TYPE_ID IN (9, 289) AND M.OBJ_ID > ' || V$PREV_ID || ' AND M.PERSON_ID = ' || I$OBJ_ID
    ON EXTERNAL :I$SRC
    WITH COMMON TRANSACTION
    INTO :MOVE_ID, :V$GROUP_ID, :V$REASON_IN, :V$DATE_IN, :V$DATE_OUT, :V$STAGE_ID, :V$ORDER_DATE_IN, :V$ORDER_NUM_IN, :V$ORDER_DATE_OUT,
      :V$ORDER_NUM_OUT, :V$NAME_IN, :V$REASON_OUT, :V$TYPE_IN, :V$IS_VD, :V$SOURCE_IN, :V$SOURCE_OUT, :V$PLAN_STAGES, :V$STAGE_YEAR, :V$GROUP_TYPE_ID, :V$LEVEL_ID;

    IF(MOVE_ID IS NOT NULL) THEN
    BEGIN
      IF(NOT EXISTS(
        SELECT FIRST 1 1
        FROM PERSON_MOVEMENTS M
        WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :I$DEST_ID AND M.GROUP_TYPE_ID IN (9, 289) AND M.DATE_IN = :V$DATE_IN AND M.NAME_IN = :V$NAME_IN AND M.STAGE_ID = :V$STAGE_ID
      ))
      THEN
      BEGIN
        -- Подставляем ID учебного коллектива в новой базе
        -- для СПО надеемся что академический отпуск не исчез, и в нем есть хотя бы один студент
        V$GROUP_ID_DST = NULL;
        SELECT FIRST 1 L9.OBJ_ID
        FROM LINKS L9
        WHERE L9.OBJ_TYPE_ID IN (9, 289) AND L9.PARENT_TYPE_ID IN (7, 8) AND L9.DATE_DEL IS NULL AND L9.LISTVAL_ID = :V$GROUP_ID
        INTO :V$GROUP_ID_DST;

        -- Если учебного коллектива не нашлось среди актуальных, ставим фейковый как бы удаленный
        -- в первом попавшемся учебном этапе первого попавшегося уровня обучения
        IF(V$GROUP_ID_DST IS NULL) THEN
        BEGIN
          SELECT FIRST 1 L9.OBJ_ID
          FROM LINKS L7
          JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
          JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NOT NULL AND L9.LISTVAL_ID = 9999
          WHERE L7.PARENT_ID = :I$OU_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
          ORDER BY L7.DATE_INS, L8.DATE_INS, L9.DATE_INS
          INTO :V$GROUP_ID_DST;

          IF(V$GROUP_ID_DST IS NULL) THEN
          BEGIN
            SELECT FIRST 1 L8.OBJ_ID
            FROM LINKS L7
            JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
            WHERE L7.PARENT_ID = :I$OU_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
            ORDER BY L7.DATE_INS, L8.DATE_INS
            INTO :V$FOLDER_ID;

            -- Тут же отмечаем его как удаленный
            SELECT OBJ_ID FROM OBJECT_ADD(:V$FOLDER_ID, 9) INTO :V$GROUP_ID_DST;
            UPDATE LINKS SET LISTVAL_ID = 9999, DATE_DEL = CURRENT_TIMESTAMP WHERE PARENT_ID = :V$FOLDER_ID AND OBJ_ID = :V$GROUP_ID_DST;
          END
        END

        -- Ссылки на приказы не сохраняем, только номера и даты приказов
        INSERT INTO PERSON_MOVEMENTS
        (OU_ID, PERSON_ID, GROUP_ID, REASON_IN, DATE_IN, DATE_OUT, STAGE_ID, ORDER_DATE_IN, ORDER_NUM_IN, ORDER_DATE_OUT,
          ORDER_NUM_OUT, NAME_IN, REASON_OUT, TYPE_IN, IS_VD, SOURCE_IN, SOURCE_OUT, PLAN_STAGES, STAGE_YEAR, GROUP_TYPE_ID, LEVEL_ID)
        VALUES (:I$OU_ID, :I$DEST_ID, :V$GROUP_ID_DST, :V$REASON_IN, :V$DATE_IN, :V$DATE_OUT, :V$STAGE_ID, :V$ORDER_DATE_IN, :V$ORDER_NUM_IN, :V$ORDER_DATE_OUT,
          :V$ORDER_NUM_OUT, :V$NAME_IN, :V$REASON_OUT, :V$TYPE_IN, :V$IS_VD, :V$SOURCE_IN, :V$SOURCE_OUT, :V$PLAN_STAGES, :V$STAGE_YEAR, :V$GROUP_TYPE_ID, :V$LEVEL_ID);
      END

      SUSPEND;
    END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIX_MERGE_DB_VALS (
    I$OBJ_ID BIGINT,
    I$DEST_ID BIGINT,
    I$SRC VARCHAR(400),
    I$TYPE_ID BIGINT = NULL)
RETURNS (
    PARAM_ID BIGINT)
AS
DECLARE VARIABLE V$PREV_ID BIGINT;
DECLARE VARIABLE V$VAL VARCHAR(4000);
DECLARE VARIABLE T INTEGER;
DECLARE VARIABLE V$DISTRICT VARCHAR(255);
DECLARE VARIABLE V$TOWN VARCHAR(255);
DECLARE VARIABLE V$SETTLEMENT VARCHAR(255);
DECLARE VARIABLE V$STREET VARCHAR(255);
DECLARE VARIABLE V$HOUSE VARCHAR(10);
DECLARE VARIABLE V$LITER VARCHAR(10);
DECLARE VARIABLE V$CORP VARCHAR(10);
DECLARE VARIABLE V$FLAT VARCHAR(10);
DECLARE VARIABLE V$POST_INDEX VARCHAR(20);
DECLARE VARIABLE V$OCATD VARCHAR(11);
DECLARE VARIABLE V$FIAS_UID VARCHAR(40);
DECLARE VARIABLE V$STREET_UID VARCHAR(40);
DECLARE VARIABLE V$SUBJECT_ID BIGINT;
DECLARE VARIABLE V$YEAR_ID BIGINT;
DECLARE VARIABLE V$MARKTYPE_ID BIGINT;
DECLARE VARIABLE V$MARKVAL_ID BIGINT;
DECLARE VARIABLE V$STAGE_ID BIGINT;
DECLARE VARIABLE V$PERIOD_FROM DATE;
DECLARE VARIABLE V$PERIOD_TO DATE;
DECLARE VARIABLE V$MARK_DATE DATE;
DECLARE VARIABLE V$IS_NATIVE SMALLINT;
DECLARE VARIABLE V$IS_EXT SMALLINT;
DECLARE VARIABLE V$V2861 DATE;
DECLARE VARIABLE V$V51 BIGINT;
DECLARE VARIABLE V$PT INTEGER;
begin

  -- Для ОП надо обязательно сначала внести параметры 1832 и 2379
  IF(I$TYPE_ID = 57) THEN
  BEGIN
    EXECUTE STATEMENT
      'SELECT FIRST 1 V1832.LISTVAL_ID, V2379.LISTVAL_ID
      FROM VALL V1832
      JOIN VALL V2379 ON V2379.OBJ_ID = V1832.OBJ_ID AND V2379.PARAM_ID = 2379 AND V2379.IS_DEL = 0
      WHERE V1832.OBJ_ID = ' || I$OBJ_ID || ' AND V1832.PARAM_ID = 1832 AND V1832.IS_DEL = 0'
    ON EXTERNAL :I$SRC
    WITH COMMON TRANSACTION
    INTO :V$MARKTYPE_ID, :V$MARKVAL_ID;

    SELECT 1 FROM VAL_ADD(1832, :I$DEST_ID, :V$MARKTYPE_ID) INTO :T;
    SELECT 1 FROM VAL_ADD(2379, :I$DEST_ID, :V$MARKVAL_ID) INTO :T;
  END

  -- Вносим все атрибуты по одному за шаг, кроме регид, данных карт школьника
  -- STRING, INTEGER, FLOAT, DATETIME
  PARAM_ID = 0;
  V$V2861 = NULL;
  WHILE(PARAM_ID IS NOT NULL) DO
  BEGIN
    V$PREV_ID = PARAM_ID;
    PARAM_ID = NULL;
    EXECUTE STATEMENT
      'SELECT FIRST 1 PARAM_ID, VAL, PT
      FROM (
        SELECT V.PARAM_ID, V.VAL, 1 PT
        FROM VALS V
        WHERE V.IS_DEL = 0 AND V.OBJ_ID = ' || I$OBJ_ID || ' AND V.PARAM_ID > ' || V$PREV_ID || '
        UNION
        SELECT V.PARAM_ID, V.LISTVAL_ID, 2
        FROM VALL V
        WHERE V.IS_DEL = 0 AND V.OBJ_ID = ' || I$OBJ_ID || ' AND V.PARAM_ID > ' || V$PREV_ID || '
        UNION
        SELECT V.PARAM_ID, V.VAL, 3
        FROM VALI V
        WHERE V.IS_DEL = 0 AND V.OBJ_ID = ' || I$OBJ_ID || ' AND V.PARAM_ID > ' || V$PREV_ID || '
        UNION
        SELECT V.PARAM_ID, V.VAL, 4
        FROM VALF V
        WHERE V.IS_DEL = 0 AND V.OBJ_ID = ' || I$OBJ_ID || ' AND V.PARAM_ID > ' || V$PREV_ID || '
        UNION
        SELECT V.PARAM_ID, V.VAL, 5
        FROM VALT V
        WHERE V.IS_DEL = 0 AND V.OBJ_ID = ' || I$OBJ_ID || ' AND V.PARAM_ID > ' || V$PREV_ID || '
        UNION
        SELECT V.PARAM_ID, V.VAL, 6
        FROM VALD V
        WHERE V.IS_DEL = 0 AND V.OBJ_ID = ' || I$OBJ_ID || ' AND V.PARAM_ID > ' || V$PREV_ID || '
        UNION
        SELECT V.PARAM_ID, V.VAL, 7
        FROM VALDT V
        WHERE V.IS_DEL = 0 AND V.OBJ_ID = ' || I$OBJ_ID || ' AND V.PARAM_ID > ' || V$PREV_ID || '
      )
      ORDER BY 1'
    ON EXTERNAL :I$SRC
    WITH COMMON TRANSACTION
    INTO :PARAM_ID, :V$VAL, :V$PT;

    -- Не копируем параметры, связанные со школьной картой, ссылки на земельный участок
    -- статус эксперта, статус учебного плана
    -- дату возвращения из отпуска (2861) временно откладываем
    IF(PARAM_ID = 2861) THEN V$V2861 = V$VAL;
    IF(PARAM_ID = 51) THEN V$V51 = V$VAL;

    -- Пытаемся поправить СНИЛС, если в нем напорото что-то простое
    IF(PARAM_ID IN (571, 2455) AND (V$V51 IS NULL OR V$V51 = 1384)) THEN
    BEGIN
      -- Имеющееся значение невалидно
      IF(EXISTS(SELECT 1 FROM CHECK_SNILS(:V$VAL) WHERE IS_REAL = 0)) THEN
      BEGIN
        -- Дефис вместо пробела ?
        IF(CHAR_LENGTH(V$VAL) = 14 AND SUBSTRING(V$VAL FROM 4 FOR 1) = '-' AND SUBSTRING(V$VAL FROM 8 FOR 1) = '-' AND SUBSTRING(V$VAL FROM 12 FOR 1) = '-') THEN
        BEGIN
          V$VAL = SUBSTRING(V$VAL FROM 1 FOR 11) || ' ' || SUBSTRING(V$VAL FROM 13 FOR 2);
        END
        -- Просто цифры без разделителей ?
        ELSE IF(CHAR_LENGTH(V$VAL) = 11) THEN
        BEGIN
          V$VAL = SUBSTRING(V$VAL FROM 1 FOR 3) || '-' || SUBSTRING(V$VAL FROM 4 FOR 3) || '-' || SUBSTRING(V$VAL FROM 7 FOR 3) || ' ' || SUBSTRING(V$VAL FROM 10 FOR 2);
        END
      END
    END

    IF(PARAM_ID IS NOT NULL AND PARAM_ID NOT IN (2855, 2912, 2913, 2857, 2922, 2855, 2861, 2913, 2918, 2921, 2919, 2923, 3408, 2935, 3013, 3018, 3019)) THEN
    BEGIN
      -- Корректируем параметр 167, чтобы не летела ошибка
      IF(PARAM_ID = 167) THEN
      BEGIN
        IF(NOT EXISTS(
          SELECT FIRST 1 1
          FROM LISTVALS_LIST(53)
          WHERE VAL = :V$VAL
        ))
        THEN
          V$VAL = 'иное мероприятие';
      END

      -- Нельзя параметры вносить через VAL_ADD
      -- SELECT 1 FROM VAL_ADD(:PARAM_ID, :I$DEST_ID, :V$VAL) INTO :T;
      IF(V$PT = 1) THEN
        UPDATE OR INSERT
        INTO VALS
        (OBJ_ID, PARAM_ID, IS_DEL, VAL)
        VALUES (:I$DEST_ID, :PARAM_ID, 0, :V$VAL);
      ELSE IF(V$PT = 2) THEN
        UPDATE OR INSERT
        INTO VALL
        (OBJ_ID, PARAM_ID, IS_DEL, LISTVAL_ID)
        VALUES (:I$DEST_ID, :PARAM_ID, 0, :V$VAL);
      ELSE IF(V$PT = 3) THEN
        UPDATE OR INSERT
        INTO VALI
        (OBJ_ID, PARAM_ID, IS_DEL, VAL)
        VALUES (:I$DEST_ID, :PARAM_ID, 0, :V$VAL);
      ELSE IF(V$PT = 4) THEN
        UPDATE OR INSERT
        INTO VALF
        (OBJ_ID, PARAM_ID, IS_DEL, VAL)
        VALUES (:I$DEST_ID, :PARAM_ID, 0, :V$VAL);
      ELSE IF(V$PT = 5) THEN
        UPDATE OR INSERT
        INTO VALT
        (OBJ_ID, PARAM_ID, IS_DEL, VAL)
        VALUES (:I$DEST_ID, :PARAM_ID, 0, :V$VAL);
      ELSE IF(V$PT = 6) THEN
        UPDATE OR INSERT
        INTO VALD
        (OBJ_ID, PARAM_ID, IS_DEL, VAL)
        VALUES (:I$DEST_ID, :PARAM_ID, 0, :V$VAL);
      ELSE IF(V$PT = 7) THEN
        UPDATE OR INSERT
        INTO VALDT
        (OBJ_ID, PARAM_ID, IS_DEL, VAL)
        VALUES (:I$DEST_ID, :PARAM_ID, 0, :V$VAL);
      SUSPEND;
    END
  END

  -- Довносим дату возвращения из отпуска
  IF(V$V2861 IS NOT NULL) THEN
  BEGIN
    SELECT 1 FROM VAL_ADD(2861, :I$DEST_ID, :V$V2861) INTO :T;
    SUSPEND;
  END

  -- ADDR
  PARAM_ID = 0;
  WHILE(PARAM_ID IS NOT NULL) DO
  BEGIN
    V$PREV_ID = PARAM_ID;
    PARAM_ID = NULL;
    EXECUTE STATEMENT
      'SELECT FIRST 1 V.PARAM_ID, V.REGION, V.DISTRICT, V.TOWN, V.SETTLEMENT, V.STREET, V.HOUSE, V.LITER, V.CORP, V.FLAT, V.POST_INDEX, V.OCATD, V.FIAS_UID, V.STREET_UID
      FROM VALA V
      WHERE V.IS_DEL = 0 AND V.OBJ_ID = ' || I$OBJ_ID || ' AND V.PARAM_ID > ' || V$PREV_ID || '
      ORDER BY 1'
    ON EXTERNAL :I$SRC
    -- ROLE 'INISSOFT_ROLE'
    WITH COMMON TRANSACTION
    INTO :PARAM_ID, :V$VAL, :V$DISTRICT, :V$TOWN, :V$SETTLEMENT, :V$STREET, :V$HOUSE, :V$LITER, :V$CORP, :V$FLAT, :V$POST_INDEX, :V$OCATD, :V$FIAS_UID, :V$STREET_UID;

    IF(PARAM_ID IS NOT NULL) THEN
    BEGIN
      SELECT 1 FROM ADR_ADD(:PARAM_ID, :I$DEST_ID, :V$VAL, :V$DISTRICT, :V$TOWN, :V$SETTLEMENT, :V$STREET, :V$HOUSE, :V$LITER, :V$CORP, :V$FLAT, :V$POST_INDEX, :V$OCATD, :V$FIAS_UID, :V$STREET_UID) INTO :T;
      SUSPEND;
    END
  END

  -- VALM, без GRADE_ID
  PARAM_ID = 0;
  WHILE(PARAM_ID IS NOT NULL) DO
  BEGIN
    V$PREV_ID = PARAM_ID;
    PARAM_ID = NULL;
    EXECUTE STATEMENT
      'SELECT FIRST 1 V.MARK_ID, C.CAPTION, V.SUBJECT_ID, V.YEAR_ID, V.MARKTYPE_ID, V.MARKVAL_ID, V.STAGE_ID, V.PERIOD_FROM, V.PERIOD_TO, V.MARK_DATE, V.IS_NATIVE, V.IS_EXT
      FROM VALM V
      LEFT JOIN OBJECT_CAPTION_GET(V.SUBJECT_ID) C ON 1 = 1
      WHERE V.IS_DEL = 0 AND V.PUPIL_ID = ' || I$OBJ_ID || ' AND V.MARK_ID > ' || V$PREV_ID || ' AND (V.IS_NATIVE IS NULL OR V.IS_NATIVE = 1)
      ORDER BY 1'
    ON EXTERNAL :I$SRC
    -- ROLE 'INISSOFT_ROLE'
    WITH COMMON TRANSACTION
    INTO :PARAM_ID, :V$VAL, :V$SUBJECT_ID, :V$YEAR_ID, :V$MARKTYPE_ID, :V$MARKVAL_ID, :V$STAGE_ID, :V$PERIOD_FROM, :V$PERIOD_TO, :V$MARK_DATE, :V$IS_NATIVE, :V$IS_EXT;

    IF(PARAM_ID IS NOT NULL) THEN
    BEGIN
      IF(V$SUBJECT_ID > 1000000000) THEN
      BEGIN
        V$PREV_ID = V$SUBJECT_ID;
        V$SUBJECT_ID = NULL;
        SELECT FIRST 1 V.OBJ_ID
        FROM VALS V
        JOIN LINKS LP301 ON LP301.OBJ_ID = V.OBJ_ID AND LP301.PARENT_TYPE_ID = 301 AND LP301.DATE_DEL IS NULL
        WHERE V.IS_DEL = 0 AND V.PARAM_ID = 376 AND V.SVAL = :V$VAL AND V.OBJ_ID > 1000000000
        INTO :V$SUBJECT_ID;
      END

      IF(V$SUBJECT_ID IS NOT NULL) THEN
      BEGIN
        INSERT INTO VALM
        (PUPIL_ID, SUBJECT_ID, YEAR_ID, MARKTYPE_ID, MARKVAL_ID, STAGE_ID, PERIOD_FROM, PERIOD_TO, MARK_DATE, IS_NATIVE, IS_EXT)
        VALUES (:I$DEST_ID, :V$SUBJECT_ID, :V$YEAR_ID, :V$MARKTYPE_ID, :V$MARKVAL_ID, :V$STAGE_ID, :V$PERIOD_FROM, :V$PERIOD_TO, :V$MARK_DATE, :V$IS_NATIVE, :V$IS_EXT);

        SUSPEND;
      END
    END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIX_MERGE_PLAN (
    I$OBJ_ID BIGINT,
    I$DST_ID BIGINT,
    I$SRC VARCHAR(1000))
RETURNS (
    PARAM_ID BIGINT)
AS
DECLARE VARIABLE V$PREV_ID BIGINT;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$STAGE_ID BIGINT;
DECLARE VARIABLE V$FIELD_ID BIGINT;
DECLARE VARIABLE V$SUBJECT_ID BIGINT;
DECLARE VARIABLE V$SORT_INDEX INTEGER;
DECLARE VARIABLE V$PARENT_ID BIGINT;
DECLARE VARIABLE V$GLOBAL_INDEX INTEGER;
DECLARE VARIABLE V$LEVEL_INDEX INTEGER;
DECLARE VARIABLE V$SRC_SUBJECT_ID BIGINT;
DECLARE VARIABLE V$ROW_TYPE SMALLINT;
DECLARE VARIABLE V$IS_ADV SMALLINT;
DECLARE VARIABLE V$IS_STM SMALLINT;
DECLARE VARIABLE V$ROW_CODE VARCHAR(40);
DECLARE VARIABLE V$VAL VARCHAR(1000);
DECLARE VARIABLE V$DST_SUBJECT_ID BIGINT;
DECLARE VARIABLE V$FOLDER_ID BIGINT;
DECLARE VARIABLE V$SUBJECT_TYPE BIGINT;
DECLARE VARIABLE V$OP_ID BIGINT;
DECLARE VARIABLE V$DST_PARENT BIGINT;
DECLARE VARIABLE V$ROW_ID BIGINT;
DECLARE VARIABLE V$PGI INTEGER;
DECLARE VARIABLE V$WEEKS SMALLINT;
DECLARE VARIABLE V$LOAD_HOURS FLOAT;
DECLARE VARIABLE V$LOAD_HOURS_S1 FLOAT;
DECLARE VARIABLE V$LOAD_HOURS_S2 FLOAT;
DECLARE VARIABLE V$CONTROL_Q1 BIGINT;
DECLARE VARIABLE V$CONTROL_Q2 BIGINT;
DECLARE VARIABLE V$HOURS_THEORY1 FLOAT;
DECLARE VARIABLE V$HOURS_PR1 FLOAT;
DECLARE VARIABLE V$HOURS_DX1 FLOAT;
DECLARE VARIABLE V$HOURS_IND1 FLOAT;
DECLARE VARIABLE V$HOURS_MAX FLOAT;
DECLARE VARIABLE V$HOURS_CR1 FLOAT;
DECLARE VARIABLE V$HOURS_ATT1 FLOAT;
DECLARE VARIABLE V$HOURS_GIA FLOAT;
DECLARE VARIABLE V$HOURS_REST FLOAT;
DECLARE VARIABLE N INTEGER;
begin

  -- Какой у нас тип ОП в данном плане ? По нему запоминаем тип предмета и каталог, где будут предметы
  SELECT FIRST 1 V1594.LISTVAL_ID
  FROM LINKS LP57
  JOIN VALL V1594 ON V1594.OBJ_ID = LP57.PARENT_ID AND V1594.PARAM_ID = 1594 AND V1594.IS_DEL = 0
  WHERE LP57.OBJ_ID = :I$DST_ID AND LP57.PARENT_TYPE_ID = 57 AND LP57.DATE_DEL IS NULL
  INTO :V$OP_ID;

  V$SUBJECT_TYPE = 51;
  IF(V$OP_ID = 5337) THEN V$FOLDER_ID = 38699; -- ДОУ
  ELSE IF(V$OP_ID = 5346) THEN BEGIN V$FOLDER_ID = 12313; V$SUBJECT_TYPE = 197; END
  ELSE V$FOLDER_ID = 32771; -- обычные предметы

  -- Этапы обучения
  V$OBJ_ID = 0;
  WHILE(V$OBJ_ID IS NOT NULL) DO
  BEGIN

    V$PREV_ID = V$OBJ_ID;
    V$OBJ_ID = NULL;
    EXECUTE STATEMENT
      'SELECT FIRST 1 L54.OBJ_ID
      FROM LINKS L54
      WHERE L54.DATE_DEL IS NULL AND L54.PARENT_ID = ' || I$OBJ_ID || ' AND L54.OBJ_ID > ' || V$PREV_ID || '
      ORDER BY 1'
    ON EXTERNAL :I$SRC
    WITH COMMON TRANSACTION                                      
    INTO :V$OBJ_ID;

    IF(V$OBJ_ID IS NOT NULL) THEN
    BEGIN
      SELECT OBJ_ID FROM OBJECT_ADD(:I$DST_ID, 54) INTO :V$STAGE_ID;
      FOR
        SELECT PARAM_ID
        FROM FIX_MERGE_DB_VALS(:V$OBJ_ID, :V$STAGE_ID, :I$SRC)
        INTO :PARAM_ID
      DO
      BEGIN
        SUSPEND;
      END
    END

  END

  -- Предметы УП
  N = 0;
  V$OBJ_ID = 0;
  WHILE(V$OBJ_ID IS NOT NULL) DO
  BEGIN
    V$PREV_ID = V$OBJ_ID;
    V$OBJ_ID = NULL;
    EXECUTE STATEMENT
      'SELECT FIRST 1 PS.OBJ_ID, PS.FIELD_ID, PS.SUBJECT_ID, PS.SORT_INDEX, PS.PARENT_ID, PS.GLOBAL_INDEX, PS.LEVEL_INDEX, PS.SRC_SUBJECT_ID,
        PS.ROW_TYPE, PS.IS_ADV, PS.IS_STM, PS.ROW_CODE, V.VAL, PSP.GLOBAL_INDEX
      FROM PLAN_SUBJECTS PS
      LEFT JOIN PLAN_SUBJECTS PSP ON PS.PARENT_ID IS NOT NULL AND PSP.OBJ_ID = PS.PARENT_ID
      LEFT JOIN VALS V ON V.OBJ_ID = PS.SUBJECT_ID AND V.PARAM_ID IN (376, 1751) AND V.IS_DEL = 0
      WHERE PS.DATE_DEL IS NULL AND PS.PLAN_ID = ' || I$OBJ_ID || ' AND PS.OBJ_ID > ' || V$PREV_ID || '
      ORDER BY 1'
    ON EXTERNAL :I$SRC
    WITH COMMON TRANSACTION
    INTO :V$OBJ_ID, :V$FIELD_ID, :V$SUBJECT_ID, :V$SORT_INDEX, :V$PARENT_ID, :V$GLOBAL_INDEX, :V$LEVEL_INDEX, :V$SRC_SUBJECT_ID,
      :V$ROW_TYPE, :V$IS_ADV, :V$IS_STM, :V$ROW_CODE, :V$VAL, :V$PGI;

    IF(V$OBJ_ID IS NOT NULL) THEN
    BEGIN

      -- По FIELD_ID в СПО если модульного курса нет в базе - пока игнорируем и будет ошибка
      -- Есть ли предмет с нужным ID ?
      V$DST_SUBJECT_ID = NULL;
      IF(V$SUBJECT_ID IS NULL OR V$SUBJECT_ID < 1000000000) THEN V$DST_SUBJECT_ID = V$SUBJECT_ID;
      ELSE
      BEGIN
        SELECT FIRST 1 L51.OBJ_ID
        FROM LINKS L51
        JOIN VALS V ON V.OBJ_ID = L51.OBJ_ID AND V.PARAM_ID IN (376, 1751) AND V.IS_DEL = 0 AND V.VAL = :V$VAL
        WHERE L51.PARENT_TYPE_ID IN (193, 301) AND L51.OBJ_TYPE_ID IN (51, 197) AND L51.DATE_DEL IS NULL
        ORDER BY 1
        INTO :V$DST_SUBJECT_ID;

        IF(V$DST_SUBJECT_ID IS NULL) THEN
        BEGIN
          SELECT OBJ_ID FROM OBJECT_ADD(:V$FOLDER_ID, :V$SUBJECT_TYPE) INTO :V$DST_SUBJECT_ID;
          FOR
            SELECT PARAM_ID
            FROM FIX_MERGE_DB_VALS(:V$SUBJECT_ID, :V$DST_SUBJECT_ID, :I$SRC)
            INTO :PARAM_ID
          DO
          BEGIN
            SUSPEND;
          END
        END
      END

      -- Восстанавливаем PARENT_ID через GLOBAL_INDEX
      V$DST_PARENT = NULL;
      IF(V$PGI IS NOT NULL) THEN
      SELECT FIRST 1 PS.OBJ_ID
      FROM PLAN_SUBJECTS PS
      WHERE PS.DATE_DEL IS NULL AND PS.PLAN_ID = :I$DST_ID AND PS.GLOBAL_INDEX = :V$PGI
      INTO :V$DST_PARENT;

      -- Добавляем строку
      INSERT INTO PLAN_SUBJECTS
      (PLAN_ID, FIELD_ID, SUBJECT_ID, SORT_INDEX, PARENT_ID, GLOBAL_INDEX, LEVEL_INDEX, SRC_SUBJECT_ID,
        ROW_TYPE, IS_ADV, IS_STM, ROW_CODE)
      VALUES (:I$DST_ID, :V$FIELD_ID, :V$DST_SUBJECT_ID, :V$SORT_INDEX, :V$DST_PARENT, :V$GLOBAL_INDEX, :V$LEVEL_INDEX, :V$SRC_SUBJECT_ID,
        :V$ROW_TYPE, :V$IS_ADV, :V$IS_STM, :V$ROW_CODE)
      RETURNING OBJ_ID INTO :PARAM_ID;

      N = N + 1;
      if(N > 200) THEN EXCEPTION DATA_ERROR 'ASSERT TOO MANY SUBJECTS';
      SUSPEND;

    END

  END

  -- Нагрузка УП
  V$OBJ_ID = 0;
  WHILE(V$OBJ_ID IS NOT NULL) DO
  BEGIN

    V$PREV_ID = V$OBJ_ID;
    V$OBJ_ID = NULL;
    EXECUTE STATEMENT
      'SELECT FIRST 1 PL.OBJ_ID, PS.GLOBAL_INDEX, V381.LISTVAL_ID, PL.WEEKS, PL.LOAD_HOURS, PL.LOAD_HOURS_S1, PL.LOAD_HOURS_S2, PL.CONTROL_Q1, PL.CONTROL_Q2,
        PL.HOURS_THEORY1, PL.HOURS_PR1, PL.HOURS_DX1, PL.HOURS_IND1, PL.HOURS_MAX, PL.HOURS_CR1, PL.HOURS_ATT1, PL.HOURS_GIA, PL.HOURS_REST
      FROM PLAN_SUBJECTS PS
      JOIN PLAN_LOADS PL ON PL.DATE_DEL IS NULL AND PL.SUBJECT_ID = PS.OBJ_ID
      LEFT JOIN VALL V381 ON V381.OBJ_ID = PL.STAGE_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
      WHERE PS.DATE_DEL IS NULL AND PS.PLAN_ID = ' || I$OBJ_ID || ' AND PL.OBJ_ID > ' || V$PREV_ID || '
      ORDER BY 1'
    ON EXTERNAL :I$SRC
    WITH COMMON TRANSACTION
    INTO :V$OBJ_ID, :V$PGI, :V$STAGE_ID, :V$WEEKS, :V$LOAD_HOURS, :V$LOAD_HOURS_S1, :V$LOAD_HOURS_S2, :V$CONTROL_Q1, :V$CONTROL_Q2,
      :V$HOURS_THEORY1, :V$HOURS_PR1, :V$HOURS_DX1, :V$HOURS_IND1, :V$HOURS_MAX, :V$HOURS_CR1, :V$HOURS_ATT1, :V$HOURS_GIA, :V$HOURS_REST;

    -- Определяем предмет
    V$DST_SUBJECT_ID = NULL;
    SELECT FIRST 1 PS.OBJ_ID
    FROM PLAN_SUBJECTS PS
    WHERE PS.DATE_DEL IS NULL AND PS.PLAN_ID = :I$DST_ID AND PS.GLOBAL_INDEX = :V$PGI
    INTO :V$DST_SUBJECT_ID;

    IF(V$DST_SUBJECT_ID IS NULL) THEN EXCEPTION DATA_ERROR 'ASSERT SUBJECT AT ' || COALESCE(V$PGI, '?') || ', HAS ' || N || ' PLAN ' || I$OBJ_ID || ' ROW ' || V$OBJ_ID;

    -- Связь с этапом только если это не сумма
    V$ROW_ID = NULL;
    IF(V$STAGE_ID IS NOT NULL) THEN
    SELECT FIRST 1 L54.OBJ_ID
    FROM LINKS L54
    JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0 AND V381.LISTVAL_ID = :V$STAGE_ID
    WHERE L54.PARENT_ID = :I$DST_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
    INTO :V$ROW_ID;

    IF(V$OBJ_ID IS NOT NULL) THEN
    BEGIN
      INSERT INTO PLAN_LOADS
      (SUBJECT_ID, STAGE_ID, WEEKS, LOAD_HOURS, LOAD_HOURS_S1, LOAD_HOURS_S2, CONTROL_Q1, CONTROL_Q2,
        HOURS_THEORY1, HOURS_PR1, HOURS_DX1, HOURS_IND1, HOURS_MAX, HOURS_CR1, HOURS_ATT1, HOURS_GIA, HOURS_REST)
      VALUES (:V$DST_SUBJECT_ID, :V$ROW_ID, :V$WEEKS, :V$LOAD_HOURS, :V$LOAD_HOURS_S1, :V$LOAD_HOURS_S2, :V$CONTROL_Q1, :V$CONTROL_Q2,
        :V$HOURS_THEORY1, :V$HOURS_PR1, :V$HOURS_DX1, :V$HOURS_IND1, :V$HOURS_MAX, :V$HOURS_CR1, :V$HOURS_ATT1, :V$HOURS_GIA, :V$HOURS_REST)
      RETURNING OBJ_ID INTO :PARAM_ID;

      SUSPEND;
    END

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIX_MOVEMENTS
AS
declare variable V$OU_TYPE char(1);
declare variable V$STUDENT_ID bigint;
declare variable V$MOVE_ID bigint;
declare variable V$NEW_ID bigint;
declare variable V$MOVE_TYPE bigint;
declare variable V$ATTRS varchar(400);
declare variable V$MOVE_DATE date;
declare variable V$ORDER_DATE date;
declare variable V$ORDER_NUM varchar(400);
declare variable V$STAGE_ID bigint;
declare variable V$GRADE_TYPE bigint;
declare variable V$GRADE_NAME varchar(400);
declare variable V$GRADE_ID bigint;
declare variable V$REF_ID bigint;
declare variable V$VD bigint;
declare variable V$SOURCE_ID bigint;
declare variable V$DT timestamp;
declare variable V$COST integer;
declare variable V$GT_ID bigint;
begin

  V$OU_TYPE = (SELECT STATUS FROM OU_LICENCE_TYPE);

  FOR
    SELECT DISTINCT L10.OBJ_ID
    FROM LINKS L10
    WHERE L10.PARENT_TYPE_ID IN (9, 46, 81, 82, 83, 125, 173, 187, 243, 289, 290) AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    INTO :V$STUDENT_ID
  DO
  BEGIN

    -- Зачисление в классы #76
    FOR
      SELECT L76.OBJ_ID, V432.LISTVAL_ID, LV."FILTER", V433.VAL, V434.VAL, V435.VAL, V436.LISTVAL_ID, V1350.LISTVAL_ID, V437.VAL, V438.VAL, G.TYPE_ID, V2448.VAL, COALESCE(V452.LISTVAL_ID, 903)
      FROM LINKS L76
      JOIN VALL V432 ON V432.OBJ_ID = L76.OBJ_ID AND V432.PARAM_ID = 432 AND V432.IS_DEL = 0
      JOIN LISTVALS LV ON LV.LISTVAL_ID = V432.LISTVAL_ID
      JOIN VALD V433 ON V433.OBJ_ID = L76.OBJ_ID AND V433.PARAM_ID = 433 AND V433.IS_DEL = 0
      LEFT JOIN VALS V434 ON V434.OBJ_ID = L76.OBJ_ID AND V434.PARAM_ID = 434 AND V434.IS_DEL = 0
      LEFT JOIN VALD V435 ON V435.OBJ_ID = L76.OBJ_ID AND V435.PARAM_ID = 435 AND V435.IS_DEL = 0
      LEFT JOIN VALL V436 ON V436.OBJ_ID = L76.OBJ_ID AND V436.PARAM_ID = 436 AND V436.IS_DEL = 0
      LEFT JOIN VALL V1350 ON V1350.OBJ_ID = L76.OBJ_ID AND V1350.PARAM_ID = 1350 AND V1350.IS_DEL = 0
      LEFT JOIN VALS V437 ON V437.OBJ_ID = L76.OBJ_ID AND V437.PARAM_ID = 437 AND V437.IS_DEL = 0
      LEFT JOIN VALR V438 ON V438.OBJ_ID = L76.OBJ_ID AND V438.PARAM_ID = 438 AND V438.IS_DEL = 0
      LEFT JOIN OBJECTS G ON G.OBJ_ID = V438.VAL
      LEFT JOIN VALR V2448 ON V2448.OBJ_ID = L76.OBJ_ID AND V2448.PARAM_ID = 2448 AND V2448.IS_DEL = 0
      LEFT JOIN VALL V452 ON V452.OBJ_ID = L76.OBJ_ID AND V452.PARAM_ID = 452 AND V452.IS_DEL = 0
      WHERE L76.PARENT_ID = :V$STUDENT_ID AND L76.OBJ_TYPE_ID = 76 AND L76.DATE_DEL IS NULL
      ORDER BY L76.OBJ_ID
      INTO :V$MOVE_ID, :V$MOVE_TYPE, :V$ATTRS, :V$MOVE_DATE, :V$ORDER_NUM, :V$ORDER_DATE, :V$STAGE_ID, :V$GRADE_TYPE, :V$GRADE_NAME, :V$GRADE_ID, :V$GT_ID, :V$REF_ID, :V$SOURCE_ID
    DO
    BEGIN

      V$NEW_ID = NULL;

      -- В старом формате могло не быть GRADE_ID - ищем запись группы, которая была создана в пределах суток от записи движения
      IF(V$GRADE_ID IS NULL) THEN
      BEGIN
        SELECT FIRST 1 LPG.PARENT_ID, LPG.PARENT_TYPE_ID
        FROM LINKS L76
        JOIN LINKS LPG ON LPG.OBJ_ID = L76.PARENT_ID AND LPG.PARENT_TYPE_ID IN (9, 125, 187, 243, 290) AND LPG.DATE_INS <= L76.DATE_INS
        WHERE L76.OBJ_ID = :V$MOVE_ID
        ORDER BY LPG.DATE_INS DESC
        INTO :V$GRADE_ID, :V$GT_ID;

        -- Может быть ситуация с выбывшими, внесенными через механизм печати дубликатов, когда класса для них не найти
      END

      -- Закрываем последнюю запись движения
      IF(POSITION('LEAVED' IN V$ATTRS) > 0 OR POSITION('FINISHED' IN V$ATTRS) > 0 OR POSITION('TRANSFERED' IN V$ATTRS) > 0) THEN
      BEGIN

        -- В УДОД нужно сверять id группы
        SELECT FIRST 1 M.OBJ_ID
        FROM PERSON_MOVEMENTS M
        JOIN OBJECTS O ON O.OBJ_ID = M.GROUP_ID AND O.TYPE_ID IN (9, 243)
        WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :V$STUDENT_ID AND M.DATE_OUT IS NULL AND (:V$OU_TYPE <> 'U' OR M.GROUP_ID = :V$REF_ID)
        ORDER BY M.OBJ_ID DESC
        INTO :V$NEW_ID;

        UPDATE PERSON_MOVEMENTS
        SET REASON_OUT = :V$MOVE_TYPE, DATE_OUT = :V$MOVE_DATE, ORDER_DATE_OUT = :V$ORDER_DATE, ORDER_NUM_OUT = SUBSTRING(:V$ORDER_NUM FROM 1 FOR 40), SOURCE_OUT = :V$SOURCE_ID
        WHERE OBJ_ID = :V$NEW_ID;

      END

      IF(POSITION('ACCEPTED' IN V$ATTRS) > 0 OR POSITION('TRANSFERED' IN V$ATTRS) > 0 OR POSITION('CONTINUE' IN V$ATTRS) > 0) THEN
      BEGIN

        -- Есть странные косяки в базах, что по ученику старых лет в выбывших есть только запись зачисления
        -- EXCEPTION DATA_ERROR 'Не удалось сформировать запись движения для ' || V$MOVE_ID;
        IF(V$GRADE_ID IS NOT NULL AND EXISTS(SELECT FIRST 1 1 FROM OBJECTS WHERE OBJ_ID = :V$GRADE_ID)) THEN
        BEGIN
          INSERT INTO PERSON_MOVEMENTS
          (PERSON_ID, GROUP_ID, GROUP_TYPE_ID, TYPE_IN, NAME_IN, STAGE_ID, REASON_IN, DATE_IN, ORDER_DATE_IN, ORDER_NUM_IN, SOURCE_IN)
          VALUES (:V$STUDENT_ID, :V$GRADE_ID, :V$GT_ID, :V$GRADE_TYPE, :V$GRADE_NAME, :V$STAGE_ID, :V$MOVE_TYPE, :V$MOVE_DATE, :V$ORDER_DATE, SUBSTRING(:V$ORDER_NUM FROM 1 FOR 40), :V$SOURCE_ID);
        END

      END

    END

    -- Семейное обучение
    FOR
      SELECT L392.OBJ_ID, V2952.LISTVAL_ID, V2953.VAL, V2955.VAL, V2954.VAL, V2957.LISTVAL_ID, V2956.VAL, V2958.VAL
      FROM LINKS L392
      JOIN VALL V2952 ON V2952.OBJ_ID = L392.OBJ_ID AND V2952.PARAM_ID = 2952 AND V2952.IS_DEL = 0
      JOIN VALD V2953 ON V2953.OBJ_ID = L392.OBJ_ID AND V2953.PARAM_ID = 2953 AND V2953.IS_DEL = 0
      LEFT JOIN VALS V2955 ON V2955.OBJ_ID = L392.OBJ_ID AND V2955.PARAM_ID = 2955 AND V2955.IS_DEL = 0
      LEFT JOIN VALD V2954 ON V2954.OBJ_ID = L392.OBJ_ID AND V2954.PARAM_ID = 2954 AND V2954.IS_DEL = 0
      LEFT JOIN VALL V2957 ON V2957.OBJ_ID = L392.OBJ_ID AND V2957.PARAM_ID = 2957 AND V2957.IS_DEL = 0
      LEFT JOIN VALS V2956 ON V2956.OBJ_ID = L392.OBJ_ID AND V2956.PARAM_ID = 2956 AND V2956.IS_DEL = 0
      LEFT JOIN VALR V2958 ON V2958.OBJ_ID = L392.OBJ_ID AND V2958.PARAM_ID = 2958 AND V2958.IS_DEL = 0
      WHERE L392.PARENT_ID = :V$STUDENT_ID AND L392.OBJ_TYPE_ID = 392 AND L392.DATE_DEL IS NULL
      ORDER BY L392.OBJ_ID
      INTO :V$MOVE_ID, :V$MOVE_TYPE, :V$MOVE_DATE, :V$ORDER_NUM, :V$ORDER_DATE, :V$STAGE_ID, :V$GRADE_NAME, :V$GRADE_ID
    DO
    BEGIN

      V$NEW_ID = NULL;

      -- Закрываем последнюю запись движения
      -- Раньше семейка была вообще без реестра движения, поэтому первая запись будет выбытие - ее нужно шаманить
      IF(V$MOVE_TYPE IN (12906)) THEN
      BEGIN

        -- При выбытии косяк - указывался не класс-экстернат, а класс куда выбыл - то есть реальный класс, и этап обучения тоже не тот, все надо восстанавливать
        SELECT FIRST 1 M.OBJ_ID
        FROM PERSON_MOVEMENTS M
        JOIN OBJECTS O ON O.OBJ_ID = M.GROUP_ID AND O.TYPE_ID = 187
        WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :V$STUDENT_ID AND M.DATE_OUT IS NULL
        INTO :V$NEW_ID;

        IF(V$NEW_ID IS NULL) THEN
        BEGIN
          -- Шаманим - добавляем новую запись движения
          -- Дата добавления почему-то DATE, а не TIMESTAMP - нужно давать запас в 1 сутки
          V$DT = NULL;
          SELECT FIRST 1 LP187.DATE_INS, LP187.PARENT_ID, V1652.SVAL
          FROM LINKS LP187
          LEFT JOIN VALS V1652 ON V1652.OBJ_ID = LP187.PARENT_ID AND V1652.PARAM_ID = 1652 AND V1652.IS_DEL = 0
          WHERE LP187.OBJ_ID = :V$STUDENT_ID AND LP187.PARENT_TYPE_ID = 187 AND LP187.DATE_DEL IS NOT NULL AND LP187.DATE_INS <= :V$MOVE_DATE
          ORDER BY 1 DESC
          INTO :V$DT, :V$GRADE_ID, :V$GRADE_NAME;

          -- Восстанавливаем этап обучения и название на тот момент
          SELECT FIRST 1 V49.LISTVAL_ID, LV.COST
          FROM LINKS LP8
          JOIN VALL V49 ON V49.OBJ_ID = LP8.PARENT_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
          JOIN LISTVALS LV ON LV.LISTVAL_ID = V49.LISTVAL_ID
          WHERE LP8.OBJ_ID = :V$GRADE_ID AND LP8.DATE_INS < DATEADD(1 DAY TO :V$DT)
          ORDER BY LP8.DATE_INS DESC
          INTO :V$STAGE_ID, :V$COST;

          IF(V$DT IS NOT NULL) THEN
          BEGIN
            IF(V$GRADE_NAME IS NULL) THEN V$GRADE_NAME = V$COST; ELSE V$GRADE_NAME = V$COST || ' ' || V$GRADE_NAME;

            INSERT INTO PERSON_MOVEMENTS
            (PERSON_ID, GROUP_ID, GROUP_TYPE_ID, TYPE_IN, NAME_IN, STAGE_ID, REASON_IN, DATE_IN, ORDER_DATE_IN, ORDER_NUM_IN)
            VALUES (:V$STUDENT_ID, :V$GRADE_ID, 187, NULL, :V$GRADE_NAME, :V$STAGE_ID, 12905, :V$DT, NULL, 'FIX')
            RETURNING OBJ_ID INTO :V$NEW_ID;
          END
        END

        UPDATE PERSON_MOVEMENTS
        SET REASON_OUT = :V$MOVE_TYPE, DATE_OUT = :V$MOVE_DATE, ORDER_DATE_OUT = :V$ORDER_DATE, ORDER_NUM_OUT = SUBSTRING(:V$ORDER_NUM FROM 1 FOR 40)
        WHERE OBJ_ID = :V$NEW_ID;

      END

      IF(V$MOVE_TYPE IN (12905) AND EXISTS(SELECT FIRST 1 1 FROM OBJECTS WHERE OBJ_ID = :V$GRADE_ID)) THEN
      BEGIN

        INSERT INTO PERSON_MOVEMENTS
        (PERSON_ID, GROUP_ID, GROUP_TYPE_ID, TYPE_IN, NAME_IN, STAGE_ID, REASON_IN, DATE_IN, ORDER_DATE_IN, ORDER_NUM_IN)
        VALUES (:V$STUDENT_ID, :V$GRADE_ID, 187, NULL, :V$GRADE_NAME, :V$STAGE_ID, :V$MOVE_TYPE, :V$MOVE_DATE, :V$ORDER_DATE, SUBSTRING(:V$ORDER_NUM FROM 1 FOR 40));

      END

    END

    -- Движение в ГПД
    FOR
      SELECT L178.OBJ_ID, V1584.LISTVAL_ID, V1585.VAL, V1587.VAL, V1588.VAL, V1591.VAL, V1610.VAL, COALESCE(V1589.LISTVAL_ID, 903)
      FROM LINKS L178
      JOIN VALL V1584 ON V1584.OBJ_ID = L178.OBJ_ID AND V1584.PARAM_ID = 1584 AND V1584.IS_DEL = 0
      JOIN VALD V1585 ON V1585.OBJ_ID = L178.OBJ_ID AND V1585.PARAM_ID = 1585 AND V1585.IS_DEL = 0
      LEFT JOIN VALS V1587 ON V1587.OBJ_ID = L178.OBJ_ID AND V1587.PARAM_ID = 1587 AND V1587.IS_DEL = 0
      LEFT JOIN VALD V1588 ON V1588.OBJ_ID = L178.OBJ_ID AND V1588.PARAM_ID = 1588 AND V1588.IS_DEL = 0
      LEFT JOIN VALS V1591 ON V1591.OBJ_ID = L178.OBJ_ID AND V1591.PARAM_ID = 1591 AND V1591.IS_DEL = 0
      LEFT JOIN VALR V1610 ON V1610.OBJ_ID = L178.OBJ_ID AND V1610.PARAM_ID = 1610 AND V1610.IS_DEL = 0
      LEFT JOIN VALL V1589 ON V1589.OBJ_ID = L178.OBJ_ID AND V1589.PARAM_ID = 1589 AND V1589.IS_DEL = 0
      WHERE L178.PARENT_ID = :V$STUDENT_ID AND L178.OBJ_TYPE_ID = 178 AND L178.DATE_DEL IS NULL
      ORDER BY L178.OBJ_ID
      INTO :V$MOVE_ID, :V$MOVE_TYPE, :V$MOVE_DATE, :V$ORDER_NUM, :V$ORDER_DATE, :V$GRADE_NAME, :V$GRADE_ID, :V$SOURCE_ID
    DO
    BEGIN

      V$NEW_ID = NULL;

      -- Закрываем последнюю запись движения
      IF(V$MOVE_TYPE IN (3323, 5545, 12907, 12908)) THEN
      BEGIN

        SELECT FIRST 1 M.OBJ_ID
        FROM PERSON_MOVEMENTS M
        WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :V$STUDENT_ID AND M.DATE_OUT IS NULL AND M.GROUP_ID = :V$GRADE_ID
        INTO :V$NEW_ID;

        UPDATE PERSON_MOVEMENTS
        SET REASON_OUT = :V$MOVE_TYPE, DATE_OUT = :V$MOVE_DATE, ORDER_DATE_OUT = :V$ORDER_DATE, ORDER_NUM_OUT = SUBSTRING(:V$ORDER_NUM FROM 1 FOR 40), SOURCE_OUT = :V$SOURCE_ID
        WHERE OBJ_ID = :V$NEW_ID;

      END

      IF(V$MOVE_TYPE IN (3322, 5545) AND EXISTS(SELECT FIRST 1 1 FROM OBJECTS WHERE OBJ_ID = :V$GRADE_ID)) THEN
      BEGIN

        INSERT INTO PERSON_MOVEMENTS
        (PERSON_ID, GROUP_ID, GROUP_TYPE_ID, TYPE_IN, NAME_IN, STAGE_ID, REASON_IN, DATE_IN, ORDER_DATE_IN, ORDER_NUM_IN, SOURCE_IN)
        VALUES (:V$STUDENT_ID, :V$GRADE_ID, 46, :V$GRADE_TYPE, :V$GRADE_NAME, :V$STAGE_ID, :V$MOVE_TYPE, :V$MOVE_DATE, :V$ORDER_DATE, SUBSTRING(:V$ORDER_NUM FROM 1 FOR 40), :V$SOURCE_ID);

      END

    END

    -- Движение в ГУП
    FOR
      SELECT L258.OBJ_ID, V2172.LISTVAL_ID, V2173.VAL, V2174.VAL, V2175.VAL, V2176.LISTVAL_ID, V2177.VAL, V2178.VAL, V2548.LISTVAL_ID, COALESCE(V2179.LISTVAL_ID, 903)
      FROM LINKS L258
      JOIN VALL V2172 ON V2172.OBJ_ID = L258.OBJ_ID AND V2172.PARAM_ID = 2172 AND V2172.IS_DEL = 0
      JOIN VALD V2173 ON V2173.OBJ_ID = L258.OBJ_ID AND V2173.PARAM_ID = 2173 AND V2173.IS_DEL = 0
      LEFT JOIN VALS V2174 ON V2174.OBJ_ID = L258.OBJ_ID AND V2174.PARAM_ID = 2174 AND V2174.IS_DEL = 0
      LEFT JOIN VALD V2175 ON V2175.OBJ_ID = L258.OBJ_ID AND V2175.PARAM_ID = 2175 AND V2175.IS_DEL = 0
      LEFT JOIN VALL V2176 ON V2176.OBJ_ID = L258.OBJ_ID AND V2176.PARAM_ID = 2176 AND V2176.IS_DEL = 0
      LEFT JOIN VALS V2177 ON V2177.OBJ_ID = L258.OBJ_ID AND V2177.PARAM_ID = 2177 AND V2177.IS_DEL = 0
      LEFT JOIN VALR V2178 ON V2178.OBJ_ID = L258.OBJ_ID AND V2178.PARAM_ID = 2178 AND V2178.IS_DEL = 0
      LEFT JOIN VALL V2179 ON V2179.OBJ_ID = L258.OBJ_ID AND V2179.PARAM_ID = 2179 AND V2179.IS_DEL = 0
      LEFT JOIN VALL V2548 ON V2548.OBJ_ID = L258.OBJ_ID AND V2548.PARAM_ID = 2548 AND V2548.IS_DEL = 0
      WHERE L258.PARENT_ID = :V$STUDENT_ID AND L258.OBJ_TYPE_ID = 258 AND L258.DATE_DEL IS NULL
      ORDER BY L258.OBJ_ID
      INTO :V$MOVE_ID, :V$MOVE_TYPE, :V$MOVE_DATE, :V$ORDER_NUM, :V$ORDER_DATE, :V$STAGE_ID, :V$GRADE_NAME, :V$GRADE_ID, :V$VD, :V$SOURCE_ID
    DO
    BEGIN

      V$NEW_ID = NULL;

      IF(V$MOVE_TYPE = 10966 AND (POSITION('Выбывшие' IN V$GRADE_NAME) > 0 OR POSITION('Окончившие' IN V$GRADE_NAME) > 0)) THEN
      BEGIN

        -- При выбытии тут косяк - невозможно определить конкретный ГУП откуда выбыли, поэтому берем первый попавшийся
        -- предполагается что ученик выбыл из всех ГУП, и рано или поздно они все учтутся
        SELECT FIRST 1 M.GROUP_ID
        FROM PERSON_MOVEMENTS M
        JOIN OBJECTS O ON O.OBJ_ID = M.GROUP_ID AND O.TYPE_ID = 256
        WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :V$STUDENT_ID AND M.DATE_OUT IS NULL
        ORDER BY M.OBJ_ID
        INTO :V$GRADE_ID;

      END

      -- Закрываем последнюю запись движения
      IF(V$MOVE_TYPE IN (10966, 10967)) THEN
      BEGIN

        SELECT FIRST 1 M.OBJ_ID
        FROM PERSON_MOVEMENTS M
        WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :V$STUDENT_ID AND M.DATE_OUT IS NULL AND M.GROUP_ID = :V$GRADE_ID
        INTO :V$NEW_ID;

        UPDATE PERSON_MOVEMENTS
        SET REASON_OUT = :V$MOVE_TYPE, DATE_OUT = :V$MOVE_DATE, ORDER_DATE_OUT = :V$ORDER_DATE, ORDER_NUM_OUT = SUBSTRING(:V$ORDER_NUM FROM 1 FOR 40), SOURCE_OUT = :V$SOURCE_ID
        WHERE OBJ_ID = :V$NEW_ID;

      END

      IF(V$MOVE_TYPE IN (10965, 10967) AND EXISTS(SELECT FIRST 1 1 FROM OBJECTS WHERE OBJ_ID = :V$GRADE_ID)) THEN
      BEGIN

        INSERT INTO PERSON_MOVEMENTS
        (PERSON_ID, GROUP_ID, GROUP_TYPE_ID, TYPE_IN, NAME_IN, STAGE_ID, REASON_IN, DATE_IN, ORDER_DATE_IN, ORDER_NUM_IN, SOURCE_IN)
        VALUES (:V$STUDENT_ID, :V$GRADE_ID, 256, :V$VD, :V$GRADE_NAME, :V$STAGE_ID, :V$MOVE_TYPE, :V$MOVE_DATE, :V$ORDER_DATE, SUBSTRING(:V$ORDER_NUM FROM 1 FOR 40), :V$SOURCE_ID);

      END

    END

    -- Движение в потоках #348 более неактуально

  END

  -- Прибить все старые записи движения
  DELETE FROM OBJECTS
  WHERE TYPE_ID IN (76, 178, 258, 348, 392);

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIX_MOVEMENTS_OU
AS
declare variable V$ID bigint;
declare variable M1 bigint;
declare variable M2 bigint;
declare variable V$OU bigint;
begin

  FOR
    SELECT DISTINCT M.PERSON_ID
    FROM PERSON_MOVEMENTS M
    WHERE M.OU_ID IS NULL
    INTO :V$ID
  DO
  BEGIN

    M1 = V$ID / 1000000000;
    M2 = (M1 + 1) * 1000000000;
    M1 = M1 * 1000000000;

    SELECT FIRST 1 L2.OBJ_ID
    FROM LINKS L2
    WHERE L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND (L2.PARENT_ID IS NULL OR L2.PARENT_TYPE_ID = 111 OR L2.PARENT_TYPE_ID = 112)
    INTO :V$OU;

    UPDATE PERSON_MOVEMENTS
    SET OU_ID = :V$OU
    WHERE PERSON_ID = :V$ID AND OU_ID IS NULL;

  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIX_MOVE_GROUP_TYPE
AS
declare variable V$MOVE_ID bigint;
declare variable V$TYPE_ID bigint;
begin

  FOR
    SELECT M.OBJ_ID, G.TYPE_ID
    FROM PERSON_MOVEMENTS M
    JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID
    WHERE M.DATE_DEL IS NULL AND M.GROUP_TYPE_ID IS NULL
    ORDER BY 1
    INTO :V$MOVE_ID, :V$TYPE_ID
  DO
  BEGIN
    UPDATE PERSON_MOVEMENTS
    SET GROUP_TYPE_ID = :V$TYPE_ID
    WHERE OBJ_ID = :V$MOVE_ID;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIX_MOVE_LEVEL_ID
AS
declare variable V$MOVE_ID bigint;
declare variable V$LEVEL_ID bigint;
declare variable V$GROUP_ID bigint;
declare variable V$TYPE_ID bigint;
declare variable DT timestamp;
begin
  FOR
    SELECT M.OBJ_ID, M.GROUP_ID, M.GROUP_TYPE_ID, M.DATE_ADD
    FROM PERSON_MOVEMENTS M
    WHERE M.DATE_DEL IS NULL AND (M.LEVEL_ID IS NULL OR M.LEVEL_ID IN (5339, 5341, 5343, 5346)) AND M.GROUP_ID IS NOT NULL -- не указана ступень
      AND M.GROUP_TYPE_ID IN (9, 46, 125, 187, 256, 179) -- AND M.DATE_OUT IS NULL
    ORDER BY 1
    INTO :V$MOVE_ID, :V$GROUP_ID, :V$TYPE_ID, :DT
  DO
  BEGIN
    V$LEVEL_ID = NULL;

    IF(V$TYPE_ID IN (9, 125, 187)) THEN
    BEGIN
      SELECT V43.LISTVAL_ID
      FROM LINKS LP8
      JOIN VALL V49 ON V49.OBJ_ID = LP8.PARENT_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
      JOIN LINKS LP7 ON LP7.OBJ_ID = LP8.PARENT_ID AND LP7.PARENT_TYPE_ID = 7 AND LP7.DATE_DEL IS NULL
      JOIN VALL V43 ON V43.OBJ_ID = LP7.PARENT_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0
      JOIN LINKS LP2 ON LP2.OBJ_ID = LP7.PARENT_ID AND LP2.PARENT_TYPE_ID IN (2, 211) AND LP2.DATE_DEL IS NULL
      WHERE LP8.OBJ_ID = :V$GROUP_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_INS <= :DT AND (LP8.DATE_DEL >= :DT OR LP8.DATE_DEL IS NULL)
      INTO :V$LEVEL_ID;
    END
    ELSE IF(V$TYPE_ID = 46) THEN
    BEGIN
      -- ДОО ? Для ГПД останется NULL
      SELECT FIRST 1 V43.LISTVAL_ID
      FROM LINKS LP7
      JOIN VALL V43 ON V43.OBJ_ID = LP7.PARENT_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0
      WHERE LP7.OBJ_ID = :V$GROUP_ID AND LP7.PARENT_TYPE_ID = 7 AND LP7.DATE_DEL IS NULL
      INTO :V$LEVEL_ID;
    END
    ELSE
    BEGIN
      IF(V$TYPE_ID = 256) THEN
      BEGIN
        SELECT FIRST 1 V381.LISTVAL_ID
        FROM LINKS LP54
        JOIN VALL V381 ON V381.OBJ_ID = LP54.PARENT_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
        WHERE LP54.OBJ_ID = :V$GROUP_ID AND LP54.PARENT_TYPE_ID = 54 AND LP54.DATE_DEL IS NULL
        INTO :V$LEVEL_ID;
      END
      ELSE IF(V$TYPE_ID = 179) THEN
      BEGIN
        SELECT FIRST 1 J.STAGE_INDEX
        FROM CJ2_JOURNAL J
        WHERE J.GRADE_ID = :V$GROUP_ID
        INTO :V$LEVEL_ID;
      END

      IF(V$LEVEL_ID IN (37, 38, 39, 40, 12942, 12950)) THEN V$LEVEL_ID = 22;
      ELSE IF(V$LEVEL_ID IN (41, 42, 43, 44, 45, 12951, 12960)) THEN V$LEVEL_ID = 26;
      ELSE IF(V$LEVEL_ID IN (46, 47, 48, 12961)) THEN V$LEVEL_ID = 27;
      ELSE IF(V$LEVEL_ID IN (30, 31, 32, 33, 3261)) THEN V$LEVEL_ID = 3263;
      ELSE IF(V$LEVEL_ID IN (34, 35, 36, 3262)) THEN V$LEVEL_ID = 3264;
      ELSE IF(V$LEVEL_ID IN (49, 50, 51, 52, 53, 54)) THEN V$LEVEL_ID = 29;
      ELSE V$LEVEL_ID = NULL;
    END

    IF(V$LEVEL_ID IS NOT NULL) THEN
    UPDATE PERSON_MOVEMENTS
    SET LEVEL_ID = :V$LEVEL_ID
    WHERE OBJ_ID = :V$MOVE_ID;
  END
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIX_NEW_ACCEPTED_DATE
AS
declare variable V$OBJ_ID bigint;
declare variable V$TYPE_ID bigint;
declare variable V$MOVE_ID bigint;
declare variable V$MOVE_TYPE bigint;
declare variable V$MOVE_DATE date;
declare variable V$ORDER_DATE date;
declare variable N integer;
begin

  -- Смысл утрачен

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIX_OD_PERIODS
AS
declare variable V$YEAR_ID bigint;
declare variable V$OBJ_ID bigint;
begin

  -- Тут две починки сразу
  -- Присвоение учебного года старым олимпиадам где его вообще не было
  -- и удаление дублирующей записи где не прописался год когда у нас уже наслоились два комплекта олимпиад

  -- Сначала сносим дубли олимпиад, когда есть и без периодов, и с периодами
  IF(EXISTS(
    SELECT FIRST 1 1
    FROM UT_EXAM_DATES D
    WHERE D.DATE_DEL IS NULL AND D.METHOD_ID = 4 AND D.PERIOD_ID IS NULL
  ) AND EXISTS(
    SELECT FIRST 1 1
    FROM UT_EXAM_DATES D
    WHERE D.DATE_DEL IS NULL AND D.METHOD_ID = 4 AND D.PERIOD_ID IS NOT NULL
  )) THEN
  BEGIN
    -- Удаляем именно те, где период таки прописался - это более поздние записи где учеников еще не записано
    UPDATE UT_EXAM_DATES
    SET DATE_DEL = CURRENT_TIMESTAMP
    WHERE DATE_DEL IS NULL AND METHOD_ID = 4 AND PERIOD_ID IS NOT NULL;
  END

  FOR
    SELECT D.OBJ_ID, LV.LISTVAL_ID
    FROM UT_EXAM_DATES D
    JOIN LISTVALS LV ON LV.IS_DEL = 0 AND LV.LIST_ID = 29
      AND LV.COST = IIF(EXTRACT(MONTH FROM D.EXAM_DATE_START) < 9, EXTRACT(YEAR FROM D.EXAM_DATE_START) - 1, EXTRACT(YEAR FROM D.EXAM_DATE_START))
      AND D.PERIOD_ID IS NULL
    WHERE D.METHOD_ID = 4
    ORDER BY 1
    INTO :V$OBJ_ID, :V$YEAR_ID
  DO
  BEGIN
    UPDATE UT_EXAM_DATES
    SET PERIOD_ID = :V$YEAR_ID
    WHERE OBJ_ID = :V$OBJ_ID;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIX_OUTPUT_LAST_MOVEMENT
AS
declare variable V$CLASS_ID bigint;
declare variable V$SCHOOL_ID bigint;
declare variable V$BLOB_ID bigint;
declare variable V$PUPIL_ID bigint;
declare variable V$CAPTION varchar(4000);
declare variable V$OBJ_ID bigint;
BEGIN

  -- Смысл утрачен

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIX_OU_STUDY_LEVELS
AS
declare variable V$OU_ID bigint;
declare variable V$LEVEL_ID bigint;
declare variable T integer;
begin

  IF(EXISTS(
    SELECT FIRST 1 1
    FROM LINKS L472
    WHERE L472.PARENT_TYPE_ID = 2 AND L472.OBJ_TYPE_ID = 472 AND L472.DATE_DEL IS NULL
  ))
  THEN
    EXIT;

  FOR
    SELECT DISTINCT L2.OBJ_ID, V43.LISTVAL_ID
    FROM LINKS L2
    JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    JOIN VALL V43 ON V43.OBJ_ID = L7.OBJ_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    ORDER BY 2
    INTO :V$OU_ID, :V$LEVEL_ID
  DO
  BEGIN
    SELECT 1 FROM OBJECT_ADD_WITH_PARAM(:V$OU_ID, NULL, 472, 3327, :V$LEVEL_ID) INTO :T;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIX_PERIOD_FIELDS
AS
declare variable V$PERIOD_ID bigint;
declare variable V$PERIOD_VAL bigint;
begin

  FOR
    SELECT L154.OBJ_ID, V1170.LISTVAL_ID
    FROM LINKS L2
    JOIN LINKS L150 ON L150.PARENT_ID = L2.OBJ_ID AND L150.OBJ_TYPE_ID = 150 AND L150.DATE_DEL IS NULL
    JOIN LINKS L151 ON L151.PARENT_ID = L150.OBJ_ID AND L151.OBJ_TYPE_ID = 151 AND L151.DATE_DEL IS NULL
    JOIN LINKS L154 ON L154.PARENT_ID = L151.OBJ_ID AND L154.OBJ_TYPE_ID = 154 AND L154.DATE_DEL IS NULL
    JOIN VALL V1170 ON V1170.OBJ_ID = L154.OBJ_ID AND V1170.PARAM_ID = 1170 AND V1170.IS_DEL = 0
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :V$PERIOD_ID, :V$PERIOD_VAL
  DO
  BEGIN
    EXECUTE PROCEDURE PERIOD_VERIFY(:V$PERIOD_ID, :V$PERIOD_VAL);
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIX_PLANS400
AS
declare variable V$OBJ_ID bigint;
begin

  FOR
    SELECT L400.OBJ_ID
    FROM LINKS L400
    WHERE L400.OBJ_TYPE_ID = 400
    INTO :V$OBJ_ID
  DO
  BEGIN
    DELETE FROM VALL V
    WHERE V.OBJ_ID = :V$OBJ_ID AND NOT EXISTS (
      SELECT FIRST 1 1
      FROM PARAMS P
      WHERE P.PARAM_ID = V.PARAM_ID AND P.TYPE_ID = 400
    );

    DELETE FROM VALS V
    WHERE V.OBJ_ID = :V$OBJ_ID AND NOT EXISTS (
      SELECT FIRST 1 1
      FROM PARAMS P
      WHERE P.PARAM_ID = V.PARAM_ID AND P.TYPE_ID = 400
    );

    DELETE FROM VALI V
    WHERE V.OBJ_ID = :V$OBJ_ID AND NOT EXISTS (
      SELECT FIRST 1 1
      FROM PARAMS P
      WHERE P.PARAM_ID = V.PARAM_ID AND P.TYPE_ID = 400
    );

    DELETE FROM VALD V
    WHERE V.OBJ_ID = :V$OBJ_ID AND NOT EXISTS (
      SELECT FIRST 1 1
      FROM PARAMS P
      WHERE P.PARAM_ID = V.PARAM_ID AND P.TYPE_ID = 400
    );
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIX_PLAN_FIELD_ID
AS
declare variable V$PLAN_ID bigint;
begin

  FOR
    SELECT L400.OBJ_ID
    FROM LINKS L400
    JOIN VALL V3014 ON V3014.OBJ_ID = L400.OBJ_ID AND V3014.PARAM_ID = 3014 AND V3014.IS_DEL = 0 AND V3014.LISTVAL_ID IN (14184, 14186)
    JOIN VALL V3345 ON V3345.OBJ_ID = L400.OBJ_ID AND V3345.PARAM_ID = 3345 AND V3345.IS_DEL = 0 AND V3345.LISTVAL_ID = 5343
    WHERE L400.PARENT_TYPE_ID = 57 and L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL
    INTO :V$PLAN_ID
  DO
  BEGIN
    UPDATE PLAN_SUBJECTS
    SET FIELD_ID = 11687
    WHERE PLAN_ID = :V$PLAN_ID AND FIELD_ID = 11688;
    UPDATE PLAN_SUBJECTS
    SET FIELD_ID = 11691
    WHERE PLAN_ID = :V$PLAN_ID AND FIELD_ID = 11692;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIX_RECALC_TCO
AS
declare variable OBJ_ID bigint;
declare variable N_REFS integer;
declare variable TMP bigint;
begin

  FOR
      SELECT L95.OBJ_ID, COUNT(*)
      FROM LINKS L2
      JOIN LINKS L23 ON L23.PARENT_ID = L2.OBJ_ID AND L23.OBJ_TYPE_ID = 23 AND L23.DATE_DEL IS NULL
      JOIN LINKS L95 ON L95.PARENT_ID = L23.OBJ_ID AND L95.OBJ_TYPE_ID = 95 AND L95.DATE_DEL IS NULL
      JOIN LINKS L114 ON L114.PARENT_ID = L95.OBJ_ID AND L114.OBJ_TYPE_ID = 114 AND L114.DATE_DEL IS NULL
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      GROUP BY 1
      INTO :OBJ_ID, :N_REFS
  DO
  BEGIN
      SELECT BLOB_ID FROM VAL_ADD(605, :OBJ_ID, :N_REFS) INTO :TMP;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIX_RESTORE_JOB_GROUP RETURNS (
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$ID BIGINT;
DECLARE VARIABLE V$JOB BIGINT;
DECLARE VARIABLE V$GROUP BIGINT;
DECLARE VARIABLE V$SUBGROUP BIGINT;
DECLARE VARIABLE I1 BIGINT;
DECLARE VARIABLE I2 BIGINT;
DECLARE VARIABLE S VARCHAR(1000);
begin
  -- все должности ОУ и подразделений
  FOR
    SELECT DISTINCT L13.OBJ_ID, V58.LISTVAL_ID, V63.LISTVAL_ID, V64.LISTVAL_ID, V66.VAL
    FROM LINKS L13
    JOIN VALL V58 ON V58.OBJ_ID = L13.OBJ_ID AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0
    JOIN VALL V63 ON V63.OBJ_ID = L13.OBJ_ID AND V63.PARAM_ID = 63 AND V63.IS_DEL = 0
    JOIN VALL V64 ON V64.OBJ_ID = L13.OBJ_ID AND V64.PARAM_ID = 64 AND V64.IS_DEL = 0
    JOIN VALS V66 ON V66.OBJ_ID = L13.OBJ_ID AND V66.PARAM_ID = 66 AND V66.IS_DEL = 0
    WHERE L13.PARENT_TYPE_ID IN (2, 211) AND L13.OBJ_TYPE_ID = 13 AND L13.DATE_DEL IS NULL
    INTO :V$ID, :V$JOB, :V$GROUP, :V$SUBGROUP, :S
  DO
  BEGIN
    SELECT LISTVAL_ID FROM VALL WHERE OBJ_ID = :V$ID AND PARAM_ID = 63 AND IS_DEL = 0 INTO I1;
    SELECT LISTVAL_ID FROM VALL WHERE OBJ_ID = :V$ID AND PARAM_ID = 64 AND IS_DEL = 0 INTO I2;
    -- Если группа или подгруппа должностей не совпадает с имеющимися значениями, то перезапишем должность еще раз, чтобы они обновились.
    IF (V$GROUP <> I1 OR V$SUBGROUP <> I2) THEN
    BEGIN
      SELECT 1 FROM VAL_ADD(58, :V$ID, :V$JOB) INTO I1;
      VAL = 'Восстановлена группа и подгруппа должностей для ' || S;
      SUSPEND;
    END
  END
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIX_SCHEDULE_FOLDER
AS
declare variable V$OU_ID bigint;
declare variable V$SCH_ID bigint;
declare variable V$PERIOD_ID bigint;
begin

  SELECT FIRST 1 L2.OBJ_ID, L68.OBJ_ID, L150.OBJ_ID
  FROM LINKS L2
  LEFT JOIN LINKS L68 ON L68.PARENT_ID = L2.OBJ_ID AND L68.OBJ_TYPE_ID = 68 AND L68.DATE_DEL IS NULL
  LEFT JOIN LINKS L150 ON L150.PARENT_ID = L2.OBJ_ID AND L150.OBJ_TYPE_ID = 150 AND L150.DATE_DEL IS NULL
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$OU_ID, :V$SCH_ID, :V$PERIOD_ID;

  IF(V$OU_ID IS NULL) THEN EXIT;

  IF(V$SCH_ID IS NULL) THEN
  SELECT OBJ_ID FROM OBJECT_ADD(:V$OU_ID, 68) INTO :V$SCH_ID;

  IF(V$PERIOD_ID IS NULL) THEN
  SELECT OBJ_ID FROM OBJECT_ADD(:V$OU_ID, 150) INTO :V$PERIOD_ID;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIX_SCHEDULE_ITEMS
AS
declare variable V$OBJ_ID bigint;
begin

  FOR
    SELECT SI.OBJ_ID
    FROM SCHEDULE_ITEMS SI
    LEFT JOIN CJ2_JOURNAL J ON J.OBJ_ID = SI.CJ_ID AND J.DATE_DEL IS NULL
    WHERE J.OBJ_ID IS NULL
    ORDER BY 1
    INTO :V$OBJ_ID
  DO
  BEGIN
    DELETE FROM SCHEDULE_ITEMS WHERE OBJ_ID = :V$OBJ_ID;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIX_SOP_TIMELINE
AS
declare variable N integer;
declare variable NHR integer;
declare variable NMIN integer;
begin

  -- Случайное число в пределах 300 минут = 00:00...05:00
  N = TRUNC(RAND() * 300);

  NHR = TRUNC(N / 60);
  NMIN = N - NHR * 60;

  UPDATE DC_TASKS
  SET TASK_TIMING = :NMIN || ' ' || :NHR || ' * * *'
  WHERE TASK_REF = 'food_benefits:default';

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIX_SPO_ACAD_MOVEMENTS
AS
declare variable V$ACAD_ID bigint;
declare variable V$STUDENT_ID bigint;
declare variable V$REASON bigint;
declare variable V$STAGE_ID bigint;
declare variable V$LEVEL_ID bigint;
declare variable V$DATE_OUT date;
declare variable V$ORDER_DATE_OUT date;
declare variable V$ORDER_NUM_OUT varchar(100);
declare variable V$OU_ID bigint;
declare variable V$DATE_MISS date;
declare variable V$GROUP_ID bigint;
declare variable V$FOLDER_ID bigint;
declare variable V$CNT_ID bigint;
begin

  V$LEVEL_ID = 29;

  FOR
    SELECT L2.OBJ_ID, L289.OBJ_ID, L10.OBJ_ID
    FROM LINKS L2
    JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    JOIN LINKS L289 ON L289.PARENT_ID = L7.OBJ_ID AND L289.OBJ_TYPE_ID = 289 AND L289.DATE_DEL IS NULL
    JOIN LINKS L10 ON L10.PARENT_ID = L289.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :V$OU_ID, :V$ACAD_ID, :V$STUDENT_ID
  DO
  BEGIN

    -- Смотрим последнюю запись движения, проверяем два варианта
    V$REASON = NULL;
    SELECT FIRST 1 M.REASON_OUT, M.DATE_OUT, M.ORDER_NUM_OUT, M.ORDER_DATE_OUT, M.GROUP_ID
    FROM PERSON_MOVEMENTS M
    JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID IN (9, 289)
    WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :V$STUDENT_ID
    ORDER BY M.OBJ_ID DESC
    INTO :V$REASON, :V$DATE_OUT, :V$ORDER_NUM_OUT, :V$ORDER_DATE_OUT, :V$GROUP_ID;

    -- Вносим запись, если последняя запись числится как выбытие в академку, а не чистая
    IF(V$REASON = 5319) THEN
    BEGIN
      -- Надо восстановить этап и уровень обучения, где обучающийся был до этого
      V$STAGE_ID = NULL;
      SELECT FIRST 1 V49.LISTVAL_ID
      FROM LINKS LP9
      JOIN LINKS LP8 ON LP8.OBJ_ID = LP9.PARENT_ID AND LP8.PARENT_TYPE_ID = 8 AND LP9.DATE_INS <= :V$DATE_OUT
        AND (LP8.DATE_DEL IS NULL OR LP8.DATE_DEL >= DATEADD(1 DAY TO :V$DATE_OUT)) -- AND LP8.DATE_DEL IS NULL
      JOIN VALL V49 ON V49.OBJ_ID = LP8.PARENT_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
      WHERE LP9.OBJ_ID = :V$STUDENT_ID AND LP9.PARENT_TYPE_ID = 9 AND LP9.PARENT_ID = :V$GROUP_ID
      ORDER BY LP9.DATE_DEL DESC, LP8.DATE_INS
      INTO :V$STAGE_ID;

      INSERT INTO PERSON_MOVEMENTS
      (PERSON_ID, GROUP_ID, GROUP_TYPE_ID, REASON_IN, DATE_IN, ORDER_DATE_IN, ORDER_NUM_IN, ORDER_ID_IN, NAME_IN, STAGE_ID, TYPE_IN, USER_IN,
        IS_VD, SOURCE_IN, STAGE_YEAR, LEVEL_ID, OU_ID)
      VALUES (:V$STUDENT_ID, :V$ACAD_ID, 289, 5319, :V$DATE_OUT, :V$ORDER_DATE_OUT, :V$ORDER_NUM_OUT, NULL, 'Академический отпуск', :V$STAGE_ID, NULL, 1,
        0, 902, NULL, :V$LEVEL_ID, :V$OU_ID);
    END

  END

  -- Дополнительно проверяем уже отчисленных из академического отпуска
  -- где запись выбытия из коллектива в академку есть, но нет записи приема в академку
  SELECT FIRST 1 L2.OBJ_ID, L289.OBJ_ID
  FROM LINKS L2
  JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
  JOIN LINKS L289 ON L289.PARENT_ID = L7.OBJ_ID AND L289.OBJ_TYPE_ID = 289 AND L289.DATE_DEL IS NULL
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$OU_ID, :V$ACAD_ID;

  IF(V$ACAD_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не найден каталог Академический отпуск, требуется ремонт базы';

  FOR
    SELECT M.PERSON_ID, M.DATE_OUT, M.ORDER_NUM_OUT, M.ORDER_DATE_OUT, M.GROUP_ID
    FROM PERSON_MOVEMENTS M
    LEFT JOIN PERSON_MOVEMENTS M2 ON M2.DATE_DEL IS NULL AND M2.PERSON_ID = M.PERSON_ID AND M2.REASON_IN = 5319 AND M2.OBJ_ID > M.OBJ_ID
    WHERE M.DATE_DEL IS NULL AND M.REASON_OUT = 5319 AND M2.OBJ_ID IS NULL
    INTO :V$STUDENT_ID, :V$DATE_OUT, :V$ORDER_NUM_OUT, :V$ORDER_DATE_OUT, :V$GROUP_ID
  DO
  BEGIN
    -- Надо восстановить этап и уровень обучения, где обучающийся был до этого
    V$STAGE_ID = NULL;
    SELECT FIRST 1 V49.LISTVAL_ID
    FROM LINKS LP9
    JOIN LINKS LP8 ON LP8.OBJ_ID = LP9.PARENT_ID AND LP8.PARENT_TYPE_ID = 8 AND LP9.DATE_INS <= :V$DATE_OUT
      AND (LP8.DATE_DEL IS NULL OR LP8.DATE_DEL >= DATEADD(1 DAY TO :V$DATE_OUT)) -- AND LP8.DATE_DEL IS NULL
    JOIN VALL V49 ON V49.OBJ_ID = LP8.PARENT_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
    WHERE LP9.OBJ_ID = :V$STUDENT_ID AND LP9.PARENT_TYPE_ID = 9 AND LP9.PARENT_ID = :V$GROUP_ID
    ORDER BY LP9.DATE_DEL DESC, LP8.DATE_INS
    INTO :V$STAGE_ID;

    -- Причину ставим - по заявлению, дату отчисления подбираем по дате удаления связи
    -- Если почему-то не нашлось, берем из даты ухода в отпуск что не очень корректно
    V$DATE_MISS = NULL;
    SELECT FIRST 1 LP289.DATE_DEL
    FROM LINKS LP289
    WHERE LP289.OBJ_ID = :V$STUDENT_ID AND LP289.PARENT_TYPE_ID = 289 AND LP289.DATE_DEL IS NOT NULL
    ORDER BY LP289.DATE_DEL DESC
    INTO :V$DATE_MISS;

    IF(V$DATE_MISS IS NULL) THEN V$DATE_MISS = V$DATE_OUT;

    INSERT INTO PERSON_MOVEMENTS
    (PERSON_ID, GROUP_ID, GROUP_TYPE_ID, REASON_IN, DATE_IN, ORDER_DATE_IN, ORDER_NUM_IN, ORDER_ID_IN, NAME_IN, STAGE_ID, TYPE_IN, USER_IN,
      IS_VD, SOURCE_IN, STAGE_YEAR, LEVEL_ID, OU_ID, REASON_OUT, DATE_OUT)
    VALUES (:V$STUDENT_ID, :V$ACAD_ID, 289, 5319, :V$DATE_OUT, :V$ORDER_DATE_OUT, :V$ORDER_NUM_OUT, NULL, 'Академический отпуск', :V$STAGE_ID, NULL, 1,
      0, 902, NULL, :V$LEVEL_ID, :V$OU_ID, 5316, :V$DATE_MISS);
  END

  SELECT FIRST 1 L78.OBJ_ID
  FROM LINKS L78
  WHERE L78.PARENT_ID = :V$OU_ID AND L78.OBJ_TYPE_ID = 78 AND L78.DATE_DEL IS NULL
  INTO :V$FOLDER_ID;

  IF(V$FOLDER_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Отсутствует каталог для выбывших и окончивших, требуется ремонт базы';

  -- Отдельно надо перенести из папки Выбывших в Окончивших ошибочно туда попавших
  -- Код 812 сам по себе не очень корректный, но пока оставим (он пока вбит в приказах)
  FOR
    SELECT M.PERSON_ID, MAX(M.DATE_OUT)
    FROM PERSON_MOVEMENTS M
    JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
    JOIN LINKS LP82 ON LP82.OBJ_ID = M.PERSON_ID AND LP82.PARENT_TYPE_ID = 82 AND LP82.DATE_DEL IS NULL
    WHERE M.DATE_DEL IS NULL AND M.REASON_OUT = 812
    GROUP BY 1
    INTO :V$STUDENT_ID, :V$DATE_OUT
  DO
  BEGIN
    -- Удаляем из текущей папки выбывших
    UPDATE LINKS
    SET DATE_DEL = CURRENT_TIMESTAMP
    WHERE OBJ_ID = :V$STUDENT_ID AND PARENT_TYPE_ID = 82 AND DATE_DEL IS NULL;

    -- Создаем по необходимости папку окончивших
    V$CNT_ID = NULL;
    SELECT FIRST 1 L83.OBJ_ID
    FROM LINKS L83
    JOIN VALI V451 ON V451.OBJ_ID = L83.OBJ_ID AND V451.PARAM_ID = 451 AND V451.IS_DEL = 0 AND V451.VAL = EXTRACT(YEAR FROM :V$DATE_OUT)
    WHERE L83.PARENT_ID = :V$FOLDER_ID AND L83.OBJ_TYPE_ID = 83 AND L83.DATE_DEL IS NULL
    INTO :V$CNT_ID;

    IF(V$CNT_ID IS NULL) THEN
    BEGIN
      SELECT OBJ_ID FROM OBJECT_ADD(:V$FOLDER_ID, 83) INTO :V$CNT_ID;
      SELECT 1 FROM VAL_ADD(450, :V$CNT_ID, 900) INTO :V$LEVEL_ID;
      SELECT 1 FROM VAL_ADD(451, :V$CNT_ID, EXTRACT(YEAR FROM :V$DATE_OUT)) INTO :V$LEVEL_ID;
    END

    -- Кладем туда ученика
    SELECT 1 FROM OBJECT_ADD_LINK(:V$CNT_ID, :V$STUDENT_ID, 10) INTO :V$LEVEL_ID;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIX_SPO_LICDATA
AS
begin

  -- Лицензии
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(0, '7813384469', 'Л035-01271-78/00178870', '09.04.2015', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(0, '7816041340', 'Л035-01271-78/00346933', '18.06.2021', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(0, '7806026832', 'Л035-01271-78/00179099', '20.05.2014', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(0, '7816054243', 'Л035-01271-78/00354893', '10.09.2018', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(0, '7804038818', 'Л035-01271-78/00179125', '19.05.2014', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(0, '7807017647', 'Л035-01271-78/00179184', '15.04.2014', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(0, '7811063526', 'Л035-01271-78/00179183', '21.04.2014', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(0, '7804113173', 'Л035-01271-78/00178849', '14.08.2015', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(0, '7805010477', 'Л035-01271-78/00179103', '16.04.2014', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(0, '7810248637', 'Л035-01271-78/00179120', '04.08.2014', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(0, '7825017008', 'Л035-01271-78/00179140', '29.05.2014', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(0, '7805059017', 'Л035-01271-78/00179144', '20.05.2014', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(0, '7814022800', 'Л035-01271-78/00179118', '16.06.2014', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(0, '7811060211', 'Л035-01271-78/00179119', '16.04.2014', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(0, '7816030115', 'Л035-01271-78/00286312', '20.05.2014', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(0, '7805305350', 'Л035-01271-78/00330119', '05.11.2015', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(0, '7804041560', 'Л035-01271-78/00179113', '19.05.2014', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(0, '7804023441', 'Л035-01271-78/00176709', '23.11.2021', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(0, '7806003779', 'Л035-01271-78/00179131', '18.04.2014', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(0, '7807354089', 'Л035-01271-78/00179117', '22.05.2014', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(0, '7814001535', 'Л035-01271-78/00346640', '22.05.2014', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(0, '7810260296', 'Л035-01271-78/00179112', '23.07.2014', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(0, '7805016119', 'Л035-01271-78/00177761', '15.05.2017', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(0, '7810260169', 'Л035-01271-78/00178910', '25.06.2015', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(0, '7804031315', 'Л035-01271-78/00179102', '23.06.2014', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(0, '7804157893', 'Л035-01271-78/00179143', '18.04.2014', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(0, '7807014861', 'Л035-01271-78/00346632', '04.10.2013', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(0, '7813054703', 'Л035-01271-78/00179096', '19.11.2014', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(0, '7817005305', 'Л035-01271-78/00354886', '21.09.2018', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(0, '7802072235', 'Л035-01271-78/00179107', '01.07.2014', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(0, '7805011223', 'Л035-01271-78/00346876', '30.03.2020', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(0, '7821006750', 'Л035-01271-78/00346862', '10.11.2020', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(0, '7810191042', 'Л035-01271-78/00346642', '23.05.2014', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(0, '7816099357', 'Л035-01271-78/00179185', '26.05.2014', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(0, '7816058657', 'Л035-01271-78/00374465', '01.10.2018', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(0, '7802043724', 'Л035-01271-78/00354869', '11.04.2017', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(0, '7805030240', 'Л035-01271-78/00177756', '06.03.2017', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(0, '7804105239', 'Л035-01271-78/00273154', '06.10.2017', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(0, '7801025747', 'Л035-01271-78/00354878', '10.02.2017', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(0, '7812034630', 'Л035-01271-78/00346788', '31.01.2017', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(0, '7810235910', 'Л035-01271-78/00354871', '03.02.2017', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(0, '7817012912', 'Л035-01271-78/00346910', '09.07.2021', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(0, '7811034620', 'Л035-01271-78/00354900', '25.07.2018', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(0, '7805068269', 'Л035-01271-78/00178403', '01.03.2016', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(0, '7807007582', 'Л035-01271-78/00346698', '04.07.2016', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(0, '7802187589', 'Л035-01271-78/00178289', '16.05.2016', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(0, '7810260698', 'Л035-01271-78/00346696', '06.09.2016', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(0, '7804041056', 'Л035-01271-78/00346689', '22.07.2016', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(0, '7804031675', 'Л035-01271-78/00287503', '02.09.2014', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(0, '7816200871', 'Л035-01271-78/00346683', '21.06.2016', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(0, '7814126580', 'Л035-01271-78/00178660', '08.04.2016', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(0, '7825134223', 'Л035-01271-78/00346725', '08.11.2016', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(0, '7813131813', 'Л035-01271-78/00346736', '26.07.2016', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(0, '7812037430', 'Л035-01271-78/00346723', '29.07.2016', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(0, '7813498113', 'Л035-01271-78/00354890', '15.03.2018', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(0, '7825445123', 'Л035-01271-78/00346759', '01.09.2016', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(0, '7804080601', 'Л035-01271-78/00178407', '13.10.2016', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(0, '7826740065', 'Л035-01271-78/00346688', '06.09.2016', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(0, '7804029740', 'Л035-01271-78/00354888', '18.05.2018', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(0, '7806042802', 'Л035-01271-78/00354898', '23.04.2018', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(0, '7814110284', 'Л035-01271-78/00346895', '15.03.2021', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(0, '7801265957', 'Л035-01271-78/00346903', '19.04.2021', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(0, '7801074455', 'Л035-01271-78/00354881', '13.12.2017', NULL);

  -- Аккредитации
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1047800031355', 'А007-01271-78/01157514', '14.03.2011', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027801558113', 'А007-01271-78/01158210', '31.05.2016', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804869861', 'А007-01271-78/01158221', '29.05.2017', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037828005885', 'А007-01271-78/01158222', '14.06.2017', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037835004470', 'А007-01271-78/01158047', '29.05.2014', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037816042538', 'А007-01271-78/01158182', '29.12.2015', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802762778', 'А007-01271-78/01158181', '29.12.2015', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037832009346', 'А007-01271-78/01158145', '29.12.2015', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027809202948', 'А007-01271-78/01158123', '29.12.2015', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037828025179', 'А007-01271-78/01158231', '18.06.2018', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802769697', 'А007-01271-78/00000869', '29.05.2017', NULL); -- тут какая-то хрень
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804604222', 'А007-01271-78/01158217', '29.05.2017', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802518996', 'А007-01271-78/01158255', '30.05.2019', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037839001540', 'А007-01271-78/01158186', '29.12.2015', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027808003200', 'А007-01271-78/01158251', '21.03.2019', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804608810', 'А007-01271-78/01158253', '21.03.2019', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027807988427', 'А007-01271-78/01158209', '31.05.2016', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802493421', 'А007-01271-78/01158194', '29.12.2015', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802743858', 'А007-01271-78/01158234', '06.06.2018', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027801558047', 'А007-01271-78/01158105', '29.12.2015', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802518590', 'А007-01271-78/01158173', '29.12.2015', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027808001352', 'А007-01271-78/01158225', '29.05.2017', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804915027', 'А007-01271-78/01158185', '14.05.2015', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037808024847', 'А007-01271-78/01158152', '29.12.2015', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804874899', 'А007-01271-78/01158256', '30.05.2019', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037821013724', 'А007-01271-78/01158237', '18.06.2018', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037811065665', 'А007-01271-78/01158247', '30.05.2019', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027808004730', 'А007-01271-78/01158264', '24.03.2020', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804192085', 'А007-01271-78/01158148', '22.01.2015', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027806065044', 'А007-01271-78/01158292', '06.05.2020', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027807589633', 'А007-01271-78/01158245', '30.05.2019', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802494048', 'А007-01271-78/01158244', '18.06.2018', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037825025237', 'А007-01271-78/01158252', '21.03.2019', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1077847492909', 'А007-01271-78/01158246', '21.03.2019', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037816011463', 'А007-01271-78/01158125', '27.02.2015', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802519370', 'А007-01271-78/01158188', '19.03.2015', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027812401374', 'А007-01271-78/01158205', '26.12.2016', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037832010171', 'А007-01271-78/01157631', '17.02.2012', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027807581361', 'А007-01271-78/01158212', '31.05.2016', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802508128', 'А007-01271-78/01158223', '14.06.2017', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027810303311', 'А007-01271-78/01158179', '14.05.2015', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037821024152', 'А007-01271-78/01158216', '04.05.2016', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037843130764', 'А007-01271-78/01158262', '06.05.2020', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037851004620', 'А007-01271-78/01158228', '18.06.2018', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1107847298536', 'А007-01271-78/01158240', '18.06.2018', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037811031411', 'А007-01271-78/01158018', '20.06.2014', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037835008716', 'А007-01271-78/01158259', '07.05.2019', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037843056811', 'А007-01271-78/01158257', '30.05.2019', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037800002525', 'А007-01271-78/01158254', '07.05.2019', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037800006276', 'А007-01271-78/01158010', '02.06.2014', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037808021240', 'А007-01271-78/01158265', '06.05.2020', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027810254515', 'А007-01271-78/01158242', '07.06.2018', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037808013583', 'А007-01271-78/01158249', '07.05.2019', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037800049231', 'А007-01271-78/01158258', '30.05.2019', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802506753', 'А007-01271-78/01158229', '07.06.2018', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027807987987', 'А007-01271-78/01158230', '06.06.2012', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802723332', 'А007-01271-78/01158046', '20.06.2014', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027810268628', 'А007-01271-78/01158243', '18.06.2018', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027801555517', 'А007-01271-78/01158238', '07.06.2018', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037808002759', 'А007-01271-78/01158192', '29.12.2015', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037851030953', 'А007-01271-78/01158227', '23.04.2018', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037842001966', 'А007-01271-78/01158239', '18.06.2018', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027806073811', 'А007-01271-78/01157995', '27.05.2014', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037800033798', 'А007-01271-78/01158056', '02.06.2014', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027808759440', 'А007-01271-78/01158279', '12.02.2021', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037828035101', 'А007-01271-78/01158048', '10.12.2014', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804891707', 'А007-01271-78/01158151', '02.04.2015', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1157847036016', 'А007-01271-78/01158155', '29.12.2015', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804607241', 'А007-01271-78/01158122', '15.06.2015', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027808757921', 'А007-01271-78/01157558', '26.12.2011', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1117847113009', 'А007-01271-78/01158211', '29.06.2016', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1207800168014', 'А007-01271-78/01158284', '27.12.2022', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1167800050076', 'А007-01271-78/00958324', '05.12.2023', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802518996', 'А007-01271-78/00958327', '05.12.2023', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1077847492909', 'А007-01271-78/00980341', '19.12.2023', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804608810', 'А007-01271-78/00980317', '19.12.2023', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802743858', 'А007-01271-78/00980335', '19.12.2023', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027812401374', 'А007-01271-78/00980322', '19.12.2023', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027801558113', 'А007-01271-78/00980349', '19.12.2023', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037828025179', 'А007-01271-78/00980313', '19.12.2023', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1047800031355', 'А007-01271-78/00980308', '19.12.2023', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1157847036016', 'А007-01271-78/00980331', '19.12.2023', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037843086225', 'А007-01271-78/01066381', '15.02.2024', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802518996', 'А007-01271-78/01402596', '26.09.2024', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804608810', 'А007-01271-78/01566123', '27.11.2024', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027812401374', 'А007-01271-78/01595579', '05.12.2024', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037825025237', 'А007-01271-78/01595575', '05.12.2024', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804604222', 'А007-01271-78/01595584', '05.12.2024', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1107847298536', 'А007-01271-78/01595576', '05.12.2024', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802493421', 'А007-01271-78/01599748', '06.12.2024', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037821013724', 'А007-01271-78/01599743', '06.12.2024', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027808759440', 'А007-01271-78/01129346', '16.04.2024', NULL);
  EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1227800146529', 'А007-01271-78/01916723', '25.02.2025', NULL);

  -- Аккредитации школы
  IF(EXISTS(SELECT 1 FROM OU_LICENCE_TYPE WHERE STATUS = 'S')) THEN
  BEGIN
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027810346739', 'А007-01271-78/01157820', '27.05.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027810346387', 'А007-01271-78/01158043', '07.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027810298988', 'А007-01271-78/01157792', '27.05.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027809252130', 'А007-01271-78/01157560', '14.03.2011', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027810349368', 'А007-01271-78/01157716', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027810356221', 'А007-01271-78/01158101', '23.01.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027810291189', 'А007-01271-78/01157775', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027810334353', 'А007-01271-78/01157756', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037851004091', 'А007-01271-78/01158127', '23.01.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027810344100', 'А007-01271-78/01157834', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027810295237', 'А007-01271-78/01157604', '14.03.2012', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037851014233', 'А007-01271-78/01157744', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027810299021', 'А007-01271-78/01157648', '14.03.2012', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027810345310', 'А007-01271-78/01158027', '17.02.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027810346717', 'А007-01271-78/01158129', '23.01.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027810317590', 'А007-01271-78/01157513', '17.02.2011', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027810291541', 'А007-01271-78/01157837', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027810346211', 'А007-01271-78/01157520', '14.03.2011', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027810301606', 'А007-01271-78/01157515', '14.03.2011', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027810347773', 'А007-01271-78/01157530', '14.03.2011', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037851010977', 'А007-01271-78/01158139', '23.01.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037851014167', 'А007-01271-78/01157833', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027810332593', 'А007-01271-78/01157741', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027810340447', 'А007-01271-78/01157784', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027810345309', 'А007-01271-78/01157609', '14.03.2012', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027810332307', 'А007-01271-78/01158114', '23.01.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027810301243', 'А007-01271-78/01157987', '17.02.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027810305533', 'А007-01271-78/01157532', '17.02.2011', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027810287999', 'А007-01271-78/01157749', '27.05.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027810242910', 'А007-01271-78/01157979', '17.02.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037851005048', 'А007-01271-78/01157647', '14.03.2012', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027810344760', 'А007-01271-78/01158118', '26.02.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1047836034850', 'А007-01271-78/01157987', '17.02.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027800547610', 'А007-01271-78/01157603', '14.03.2012', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027800560303', 'А007-01271-78/01157519', '14.03.2011', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027800543407', 'А007-01271-78/01157814', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037800013789', 'А007-01271-78/01157599', '14.03.2012', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027800546795', 'А007-01271-78/01157846', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037800024690', 'А007-01271-78/01157531', '17.02.2011', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027800541735', 'А007-01271-78/01157955', '17.02.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037800017584', 'А007-01271-78/01157523', '14.03.2011', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037800017518', 'А007-01271-78/01157511', '17.02.2011', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037800062585', 'А007-01271-78/01157737', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037800007211', 'А007-01271-78/01157608', '26.03.2012', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802499119', 'А007-01271-78/01158112', '11.02.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037800018695', 'А007-01271-78/01157607', '14.03.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037800008784', 'А007-01271-78/01157805', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037800017243', 'А007-01271-78/01158030', '17.02.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037800021379', 'А007-01271-78/01157526', '14.03.2011', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027800551130', 'А007-01271-78/01157602', '26.03.2012', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037800017969', 'А007-01271-78/01158023', '17.02.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027800539470', 'А007-01271-78/01158108', '23.01.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037800050276', 'А007-01271-78/01157527', '17.02.2011', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037800004648', 'А007-01271-78/01157595', '14.03.2012', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1047800031355', 'А007-01271-78/01157514', '14.03.2011', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037800017551', 'А007-01271-78/01157508', '14.03.2011', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027800547510', 'А007-01271-78/01158031', '17.02.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027801583204', 'А007-01271-78/01157855', '27.05.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027801541602', 'А007-01271-78/01157779', '27.05.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027801583226', 'А007-01271-78/01157858', '27.05.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027801583336', 'А007-01271-78/01157852', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027801583347', 'А007-01271-78/01158038', '17.02.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027801583358', 'А007-01271-78/01157528', '14.03.2011', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027801583369', 'А007-01271-78/01157732', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027801583370', 'А007-01271-78/01158036', '17.02.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027801583380', 'А007-01271-78/01158049', '17.02.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027801583391', 'А007-01271-78/01157829', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027801583688', 'А007-01271-78/01157782', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027801583677', 'А007-01271-78/01157534', '14.03.2011', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027801583655', 'А007-01271-78/01158034', '17.02.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027801583644', 'А007-01271-78/01157856', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027801583633', 'А007-01271-78/01157842', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027801583611', 'А007-01271-78/01158153', '23.01.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027801583600', 'А007-01271-78/01158149', '23.01.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027801583890', 'А007-01271-78/01158169', '23.01.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027801583589', 'А007-01271-78/01157617', '14.03.2012', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027801583578', 'А007-01271-78/01157980', '17.02.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027801583567', 'А007-01271-78/01158074', '17.02.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027801583534', 'А007-01271-78/01157524', '17.02.2011', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027801583512', 'А007-01271-78/01158044', '17.02.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027801583501', 'А007-01271-78/01158042', '17.02.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027801583490', 'А007-01271-78/01157620', '17.02.2012', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027801583479', 'А007-01271-78/01157789', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027801583468', 'А007-01271-78/01158178', '23.01.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027801583457', 'А007-01271-78/01157614', '17.02.2012', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027801583446', 'А007-01271-78/01157777', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027801583424', 'А007-01271-78/01157624', '26.03.2012', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027801583160', 'А007-01271-78/01157857', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027806066034', 'А007-01271-78/01157990', '07.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027801583556', 'А007-01271-78/01157848', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027801582820', 'А007-01271-78/01158158', '23.01.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027801582929', 'А007-01271-78/01157548', '17.02.2011', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027801582930', 'А007-01271-78/01157850', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027801582940', 'А007-01271-78/01157700', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027801582951', 'А007-01271-78/01157551', '17.02.2011', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027801582962', 'А007-01271-78/01157853', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027801582973', 'А007-01271-78/01157851', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027801582984', 'А007-01271-78/01158041', '17.02.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027801582995', 'А007-01271-78/01158174', '23.01.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027801583006', 'А007-01271-78/01158165', '23.01.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027801583820', 'А007-01271-78/01157999', '17.02.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027801583787', 'А007-01271-78/01158150', '23.01.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027801583765', 'А007-01271-78/01158159', '23.01.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027801583754', 'А007-01271-78/01157626', '14.03.2012', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027801583732', 'А007-01271-78/01157622', '17.02.2012', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027801583721', 'А007-01271-78/01158171', '23.01.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027801583700', 'А007-01271-78/01157731', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027801583710', 'А007-01271-78/01157688', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037804019340', 'А007-01271-78/01157776', '00.01.1900', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027801583897', 'А007-01271-78/01157544', '14.03.2011', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027801583864', 'А007-01271-78/01158053', '17.02.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027801583908', 'А007-01271-78/01158045', '17.02.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027801583930', 'А007-01271-78/01157539', '17.02.2011', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037843093991', 'А007-01271-78/01158187', '11.02.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802496864', 'А007-01271-78/01157873', '15.03.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802496512', 'А007-01271-78/01158120', '11.02.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802497250', 'А007-01271-78/01157510', '14.03.2011', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802496809', 'А007-01271-78/01157655', '14.03.2012', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802496523', '78А010000481', '28.03.2012', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802497260', 'А007-01271-78/01157759', '15.03.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802496919', 'А007-01271-78/01157654', '14.03.2012', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802496590', 'А007-01271-78/01157910', '15.03.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802499207', 'А007-01271-78/01157665', '15.03.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802499185', 'А007-01271-78/01157575', '17.02.2012', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802496810', 'А007-01271-78/01157509', '14.03.2011', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802499141', 'А007-01271-78/01158011', '17.01.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802499372', 'А007-01271-78/01157908', '15.03.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802496842', 'А007-01271-78/01157656', '26.03.2012', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802496578', 'А007-01271-78/01158103', '11.02.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804194109', 'А007-01271-78/01157571', '17.02.2011', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802499020', 'А007-01271-78/01157581', '17.02.2012', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802499383', '78А010000001', '02.06.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802496930', 'А007-01271-78/01158116', '11.02.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027807583187', 'А007-01271-78/01157726', '15.03.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037816030966', 'А007-01271-78/01157783', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037816004335', 'А007-01271-78/01158190', '27.02.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802499130', 'А007-01271-78/01157997', '17.02.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802521262', 'А007-01271-78/01157904', '15.03.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802497909', 'А007-01271-78/01157913', '15.03.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802499306', 'А007-01271-78/01158012', '17.02.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802499152', 'А007-01271-78/01157900', '15.03.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802497898', 'А007-01271-78/01158007', '17.02.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802499339', 'А007-01271-78/01158162', '11.02.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802499120', 'А007-01271-78/01157787', '15.03.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802497601', 'А007-01271-78/01158124', '11.02.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802499944', 'А007-01271-78/01157763', '15.03.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802499328', 'А007-01271-78/01157725', '15.03.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802496765', 'А007-01271-78/01157932', '15.03.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802497337', 'А007-01271-78/01158060', '17.02.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802499295', 'А007-01271-78/01157640', '17.02.2012', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802497557', 'А007-01271-78/01157596', '17.02.2012', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802497282', 'А007-01271-78/01157540', '17.02.2011', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802497304', 'А007-01271-78/01158107', '11.02.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802499163', 'А007-01271-78/01157895', '15.03.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802500725', 'А007-01271-78/01157586', '14.03.2012', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802499196', 'А007-01271-78/01157721', '27.05.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037816031032', 'А007-01271-78/01157677', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802497546', 'А007-01271-78/01158051', '17.02.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802497447', 'А007-01271-78/01157931', '15.03.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802498877', 'А007-01271-78/01158111', '11.02.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802738413', 'А007-01271-78/01157767', '27.05.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802739447', 'А007-01271-78/01158040', '17.02.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802757608', 'А007-01271-78/01157545', '17.02.2011', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802739997', 'А007-01271-78/01157849', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802751822', 'А007-01271-78/01157507', '14.03.2011', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802740570', 'А007-01271-78/01158143', '11.02.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802725610', 'А007-01271-78/01157538', '17.02.2011', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802740635', 'А007-01271-78/01157838', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802726050', 'А007-01271-78/01157976', '03.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037811001062', 'А007-01271-78/01157993', '03.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037811059494', 'А007-01271-78/01157652', '14.03.2012', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802734926', 'А007-01271-78/01157750', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802742747', 'А007-01271-78/01157542', '14.03.2011', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802735993', 'А007-01271-78/01157836', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802730603', 'А007-01271-78/01157494', '17.02.2011', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802739470', 'А007-01271-78/01157826', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037811038682', 'А007-01271-78/01158138', '11.02.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802730614', 'А007-01271-78/01157496', '17.02.2011', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037811024349', 'А007-01271-78/01158037', '03.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802738985', 'А007-01271-78/01157781', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802728018', 'А007-01271-78/01157533', '17.02.2011', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802741185', 'А007-01271-78/01157984', '03.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037811007893', 'А007-01271-78/01157734', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802738590', 'А007-01271-78/01157985', '03.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802749248', 'А007-01271-78/01157771', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802749490', 'А007-01271-78/01157840', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802749204', 'А007-01271-78/01157517', '14.03.2011', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802737819', 'А007-01271-78/01157970', '03.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802760644', 'А007-01271-78/01157742', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802726522', 'А007-01271-78/01157753', '27.05.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802769708', 'А007-01271-78/01157547', '14.03.2011', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802737599', 'А007-01271-78/01157755', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802737863', 'А007-01271-78/01158033', '03.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802729195', 'А007-01271-78/01157823', '27.05.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802739557', 'А007-01271-78/01157785', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802767300', 'А007-01271-78/01157501', '14.03.2011', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802737885', 'А007-01271-78/01157555', '17.02.2011', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802740998', 'А007-01271-78/01157502', '14.03.2011', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802741988', 'А007-01271-78/01157529', '14.03.2011', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802730592', 'А007-01271-78/01157651', '14.03.2012', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802754440', 'А007-01271-78/01157971', '03.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802753880', 'А007-01271-78/01158091', '11.02.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802748665', 'А007-01271-78/01158024', '17.02.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802749402', 'А007-01271-78/01157653', '17.02.2012', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027808757855', 'А007-01271-78/01157762', '27.05.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027808758130', 'А007-01271-78/01157739', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027808757899', 'А007-01271-78/01157844', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027808757613', 'А007-01271-78/01158062', '03.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027808757602', 'А007-01271-78/01158100', '17.02.2012', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027808757371', 'А007-01271-78/01157632', '14.03.2012', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027808758603', 'А007-01271-78/01157556', '14.03.2011', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027808758372', 'А007-01271-78/01158059', '03.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027808757393', 'А007-01271-78/01157636', '14.03.2012', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027808757932', 'А007-01271-78/01157704', '27.05.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027808757250', 'А007-01271-78/01157553', '14.03.2011', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027808757866', 'А007-01271-78/01157635', '17.02.2012', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027808757778', 'А007-01271-78/01157630', '14.03.2012', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027808757646', 'А007-01271-78/01157521', '14.03.2011', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027808758647', 'А007-01271-78/01157516', '17.02.2011', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027808757877', 'А007-01271-78/01158057', '03.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027808758196', 'А007-01271-78/01157825', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027808758669', 'А007-01271-78/01158168', '17.02.2011', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027808757239', 'А007-01271-78/01158052', '03.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027808757492', 'А007-01271-78/01157625', '14.03.2012', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027808758383', 'А007-01271-78/01157573', '17.02.2012', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027808757833', 'А007-01271-78/01157628', ' 17.02.2012', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027808757701', 'А007-01271-78/01158054', '03.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027808758262', 'А007-01271-78/01157764', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027808758229', 'А007-01271-78/01157623', '14.03.2012', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027808757844', 'А007-01271-78/01157804', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037816011463', 'А007-01271-78/01158125', '27.02.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802519370', 'А007-01271-78/01158188', ' 19.03.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804177037', 'А007-01271-78/01157790', '27.05.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804187905', 'А007-01271-78/01157912', '27.05.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037816030890', 'А007-01271-78/01157939', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037816030922', 'А007-01271-78/01157694', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027801583413', 'А007-01271-78/01157605', '26.03.2012', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802496501', 'А007-01271-78/01157650', '14.03.2012', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037816055518', 'А007-01271-78/01158078', '07.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037816029393', 'А007-01271-78/01157664', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037816031000', 'А007-01271-78/01157809', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037816003664', 'А007-01271-78/01157497', '17.02.2011', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804182581', 'А007-01271-78/01157950', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037816029426', 'А007-01271-78/01157658', '14.03.2012', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804187971', 'А007-01271-78/01157933', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804188015', 'А007-01271-78/01157644', '14.03.2012', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037816029547', 'А007-01271-78/01158071', '07.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804197398', 'А007-01271-78/01158069', '07.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037816037775', 'А007-01271-78/01157951', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037816003686', 'А007-01271-78/01158117', '26.02.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037816002950', 'А007-01271-78/01157754', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037843019169', 'А007-01271-78/01157869', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037816029492', 'А007-01271-78/01157757', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027809251931', 'А007-01271-78/01157812', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804187950', 'А007-01271-78/01157569', '14.03.2011', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804194110', 'А007-01271-78/01158082', '07.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804187927', 'А007-01271-78/01157770', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804188004', 'А007-01271-78/01158121', '27.02.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804187894', 'А007-01271-78/01158021', '07.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037816037797', 'А007-01271-78/01157570', '17.02.2011', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037816019317', 'А007-01271-78/01157929', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037816001706', 'А007-01271-78/01157947', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1097847194939', 'А007-01271-78/01157645', '14.03.2012', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037816029460', 'А007-01271-78/01157948', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804182560', 'А007-01271-78/01157982', '07.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804182471', 'А007-01271-78/01157751', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804187916', 'А007-01271-78/01157952', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037816029415', 'А007-01271-78/01157915', '27.05.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804177060', 'А007-01271-78/01158175', '26.02.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804182559', 'А007-01271-78/01157923', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1057812376720', 'А007-01271-78/01157946', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802499340', 'А007-01271-78/01157914', '15.03.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804601538', 'А007-01271-78/01157816', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804605135', 'А007-01271-78/01158066', '07.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804603562', 'А007-01271-78/01158028', '07.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804605861', 'А007-01271-78/01157876', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804603650', 'А007-01271-78/01157877', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804606246', 'А007-01271-78/01157883', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804602980', 'А007-01271-78/01157930', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804600548', 'А007-01271-78/01157886', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804604002', 'А007-01271-78/01157638', '14.03.2012', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804603420', 'А007-01271-78/01157629', '14.03.2012', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804599460', 'А007-01271-78/01158160', '11.02.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802738985', 'А007-01271-78/01158166', '05.03.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804601990', 'А007-01271-78/01157909', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804605696', 'А007-01271-78/01157905', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804610107', 'А007-01271-78/01158055', '07.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804602396', 'А007-01271-78/01157892', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804599085', 'А007-01271-78/01158086', '07.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804601934', 'А007-01271-78/01157868', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804604695', 'А007-01271-78/01157549', '14.03.2011', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804605080', 'А007-01271-78/01157860', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804601131', 'А007-01271-78/01157885', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804605652', 'А007-01271-78/01157808', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804600526', 'А007-01271-78/01157874', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804607577', 'А007-01271-78/01157864', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804603672', 'А007-01271-78/01158157', '11.02.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804604255', 'А007-01271-78/01157894', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804604156', 'А007-01271-78/01157921', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804602715', 'А007-01271-78/01158064', '07.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804600713', 'А007-01271-78/01158167', '11.02.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804601483', 'А007-01271-78/01158022', '07.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804605443', 'А007-01271-78/01157859', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804599184', 'А007-01271-78/01158002', '07.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804607995', 'А007-01271-78/01157888', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804604541', 'А007-01271-78/01157866', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804602000', 'А007-01271-78/01158154', '11.02.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804599965', 'А007-01271-78/01158070', '07.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804606202', 'А007-01271-78/01158161', '11.02.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027808866580', 'А007-01271-78/01157591', '17.02.2012', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027808867052', 'А007-01271-78/01157615', '14.03.2012', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027808867041', 'А007-01271-78/01157601', '14.03.2012', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027808867350', 'А007-01271-78/01157701', '15.03.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027808867118', 'А007-01271-78/01157621', '14.03.2012', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027808867283', 'А007-01271-78/01157582', '14.03.2012', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027808868614', 'А007-01271-78/01157817', '27.05.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027812402386', 'А007-01271-78/01157679', '15.03.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027812401693', 'А007-01271-78/01157964', '07.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027812405390', 'А007-01271-78/01157671', '15.03.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027812404553', 'А007-01271-78/01157690', '15.03.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027812404212', 'А007-01271-78/01157706', '15.03.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027812406126', 'А007-01271-78/01157718', '15.03.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027812404971', 'А007-01271-78/01157968', '07.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027812405422', 'А007-01271-78/01157710', '15.03.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027812404663', 'А007-01271-78/01157696', '15.03.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027812403740', 'А007-01271-78/01157960', '07.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027812401539', '78А010000477', '15.03.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027812406280', 'А007-01271-78/01157714', '15.03.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027812404443', 'А007-01271-78/01157954', '07.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027812400923', 'А007-01271-78/01157666', '27.05.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027812404058', 'А007-01271-78/01157669', '15.03.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1117847074190', 'А007-01271-78/01157705', '27.05.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037841000955', 'А007-01271-78/01157535', '02.06.2011', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027808868933', 'А007-01271-78/01157543', '24.03.2011', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037821026429', 'А007-01271-78/01157597', '26.03.2012', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804895051', 'А007-01271-78/01158214', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804892500', 'А007-01271-78/01157720', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037821014428', 'А007-01271-78/01157819', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037821022040', 'А007-01271-78/01157832', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804894292', 'А007-01271-78/01157807', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037821001327', 'А007-01271-78/01157818', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804892345', 'А007-01271-78/01157730', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037821003769', 'А007-01271-78/01157847', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804895161', 'А007-01271-78/01157627', '26.03.2012', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037821057230', 'А007-01271-78/01157828', '27.05.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804892906', 'А007-01271-78/01157780', '26.04.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804895128', 'А007-01271-78/01157589', '14.03.2012', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804894281', 'А007-01271-78/01157752', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804895194', 'А007-01271-78/01157761', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804895150', 'А007-01271-78/01157786', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804903466', 'А007-01271-78/01157593', '17.02.2012', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037821003956', 'А007-01271-78/01157822', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804899209', 'А007-01271-78/01157843', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804894260', 'А007-01271-78/01157802', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804895030', 'А007-01271-78/01157815', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037821022084', 'А007-01271-78/01158203', '06.02.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027808913230', 'А007-01271-78/01157743', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804893071', 'А007-01271-78/01157585', '26.03.2012', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804906700', 'А007-01271-78/01158199', '06.02.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037821046273', 'А007-01271-78/01157830', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804895029', 'А007-01271-78/01157746', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804892939', 'А007-01271-78/01157841', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804894270', 'А007-01271-78/01157649', '26.03.2012', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037821044117', 'А007-01271-78/01157845', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804895073', 'А007-01271-78/01157811', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804853955', 'А007-01271-78/01157799', '27.05.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1117847367164', 'А007-01271-78/01157835', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804899253', 'А007-01271-78/01157991', '17.02.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037821001240', 'А007-01271-78/01157557', '14.03.2011', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802499350', 'А007-01271-78/01157641', '14.03.2012', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037825019616', 'А007-01271-78/01157891', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027806078266', 'А007-01271-78/01158218', '27.05.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027806069543', 'А007-01271-78/01157668', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027806084987', 'А007-01271-78/01157922', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037825019650', 'А007-01271-78/01157678', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027806075769', 'А007-01271-78/01157703', '27.05.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027806084790', 'А007-01271-78/01158015', '27.05.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037825009133', 'А007-01271-78/01157682', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802496732', 'А007-01271-78/01157512', '14.03.2011', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027806079201', 'А007-01271-78/01157660', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037825013820', 'А007-01271-78/01157661', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027806070038', 'А007-01271-78/01157662', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027806071457', 'А007-01271-78/01157719', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027806066056', 'А007-01271-78/01157988', '07.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037825013148', 'А007-01271-78/01158126', '26.02.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027806080367', 'А007-01271-78/01157729', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037825017603', 'А007-01271-78/01157681', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037825019506', 'А007-01271-78/01157675', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037825019891', 'А007-01271-78/01158285', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037825012235', 'А007-01271-78/01157981', '07.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037825012499', 'А007-01271-78/01157733', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037825018296', 'А007-01271-78/01157693', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037825019693', 'А007-01271-78/01157680', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037825021453', 'А007-01271-78/01157942', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027806072678', 'А007-01271-78/01157663', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027806085999', '78А010000293', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027806076671', 'А007-01271-78/01158135', '26.02.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027806066090', 'А007-01271-78/01158026', '07.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037825012202', 'А007-01271-78/01157674', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027806078343', 'А007-01271-78/01158207', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037825002368', 'А007-01271-78/01157574', '17.02.2012', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027806074768', '78А010000151', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037825011586', 'А007-01271-78/01157709', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037825008055', 'А007-01271-78/01157854', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027806074790', 'А007-01271-78/01157745', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027806082765', 'А007-01271-78/01158141', '26.02.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037825002049', 'А007-01271-78/01157711', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027808013310', 'А007-01271-78/01158180', '26.02.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027806070050', 'А007-01271-78/01157722', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037825015865', 'А007-01271-78/01157938', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027806066111', 'А007-01271-78/01158076', '07.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037825032420', 'А007-01271-78/01157945', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027806075736', 'А007-01271-78/01157715', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027806075296', 'А007-01271-78/01157673', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027806079927', 'А007-01271-78/01157687', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037825006394', 'А007-01271-78/01158080', '07.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027806082094', 'А007-01271-78/01157723', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037825007131', 'А007-01271-78/01157698', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027806068971', 'А007-01271-78/01157670', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037825003743', 'А007-01271-78/01157691', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037825004711', 'А007-01271-78/01157918', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027806066078', 'А007-01271-78/01157659', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037825016316', 'А007-01271-78/01157672', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037825009694', 'А007-01271-78/01157667', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027810272203', 'А007-01271-78/01157525', '17.02.2011', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037843025220', 'А007-01271-78/01158144', '27.02.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027801576406', 'А007-01271-78/01158094', '06.02.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037828016500', 'А007-01271-78/01158119', '26.02.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037843095421', 'А007-01271-78/01158088', '27.02.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1227800078307', 'А007-01271-78/01158092', '27.02.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037825035918', 'А007-01271-78/01158133', '27.02.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1157800005065', 'А007-01271-78/01158146', '27.02.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037843037858', 'А007-01271-78/01158005', '07.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037869004140', 'А007-01271-78/01157959', '07.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027807580063', 'А007-01271-78/01157713', '15.03.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804901497', 'А007-01271-78/01158000', '07.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027809184358', 'А007-01271-78/01157972', '07.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1047800029507', 'А007-01271-78/01158009', '07.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037816003389', 'А007-01271-78/01157974', '07.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037816006975', 'А007-01271-78/01158013', '07.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037843050024', 'А007-01271-78/01157963', '07.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804602132', 'А007-01271-78/01158017', '07.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037821049760', 'А007-01271-78/01157957', '07.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037821055931', 'А007-01271-78/01158130', '26.02.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1157800005780', 'А007-01271-78/01158110', '06.02.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027806893047', 'А007-01271-78/01157724', '27.05.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037828000980', 'А007-01271-78/01157801', '27.05.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037828004367', 'А007-01271-78/01158035', '07.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037828004389', 'А007-01271-78/01157611', '17.02.2012', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037828004411', 'А007-01271-78/01157594', '17.02.2012', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027806857561', 'А007-01271-78/01157738', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027806860674', 'А007-01271-78/01158115', '11.02.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037828040117', 'А007-01271-78/01157983', '07.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037828005775', 'А007-01271-78/01157924', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037828001166', 'А007-01271-78/01158147', '11.02.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027806887668', 'А007-01271-78/01157803', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037828005709', 'А007-01271-78/01158032', '07.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027806887371', 'А007-01271-78/01157590', '17.02.2012', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037828001265', 'А007-01271-78/01158008', '07.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027806892827', 'А007-01271-78/01157793', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037828001683', 'А007-01271-78/01157518', '14.03.2011', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037828002739', 'А007-01271-78/01157536', '17.02.2011', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '5067847274754', 'А007-01271-78/01157797', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037828004390', 'А007-01271-78/01157616', '17.02.2012', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027808913384', 'А007-01271-78/01157965', '17.02.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037821020159', 'А007-01271-78/01157831', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027808914121', 'А007-01271-78/01157707', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027808913318', 'А007-01271-78/01157747', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027807991573', 'А007-01271-78/01158084', '07.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027808913109', 'А007-01271-78/01157580', '14.03.2012', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027808913120', 'А007-01271-78/01157676', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802506071', 'А007-01271-78/01157920', '15.03.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027808913175', 'А007-01271-78/01157695', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027808910557', 'А007-01271-78/01157500', '14.03.2011', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037841003980', 'А007-01271-78/01157686', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027808914210', 'А007-01271-78/01157683', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027808916343', 'А007-01271-78/01157806', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027808913219', 'А007-01271-78/01158093', '11.02.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027808912560', 'А007-01271-78/01157576', '17.02.2012', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027808913373', 'А007-01271-78/01157791', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027808913043', 'А007-01271-78/01157646', '14.03.2012', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027808918752', 'А007-01271-78/01157684', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027808914704', 'А007-01271-78/01157961', '03.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027807570482', 'А007-01271-78/01157587', '17.02.2012', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037832010281', 'А007-01271-78/01157584', '26.03.2012', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027807579282', 'А007-01271-78/01158095', '19.03.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027807583968', 'А007-01271-78/01158029', '07.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027807587609', 'А007-01271-78/01157962', '07.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027807568392', 'А007-01271-78/01158102', '27.02.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027807584133', 'А007-01271-78/01157577', '17.02.2012', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037832009368', 'А007-01271-78/01158109', '19.03.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027807586113', 'А007-01271-78/01157978', '07.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027807585607', 'А007-01271-78/01157579', '14.03.2012', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027807587389', 'А007-01271-78/01157495', '17.02.2011', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027807588082', 'А007-01271-78/01157506', '17.02.2011', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027807571967', 'А007-01271-78/01157735', '27.05.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027807581460', 'А007-01271-78/01158099', '19.03.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027807583990', 'А007-01271-78/01158020', '07.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027807578765', 'А007-01271-78/01157935', '15.03.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037832009710', 'А007-01271-78/01157598', '08.06.2012', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027807582967', 'А007-01271-78/01157966', '07.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '5067847266328', '78А010000166', '19.03.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037832053665', 'А007-01271-78/01157578', '17.02.2012', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1097847218468', 'А007-01271-78/01157613', '14.03.2012', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037832010171', 'А007-01271-78/01157631', '17.02.2012', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027807587301', 'А007-01271-78/01158131', '19.03.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027807591459', 'А007-01271-78/01157592', '17.02.2012', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027807593758', 'А007-01271-78/01157498', '17.02.2011', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027807573200', 'А007-01271-78/01157702', '15.03.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027807586234', 'А007-01271-78/01157788', '15.03.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027807570790', 'А007-01271-78/01157504', '17.02.2011', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027807574827', 'А007-01271-78/01158003', '07.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027807593703', 'А007-01271-78/01157588', '17.02.2012', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037832008466', 'А007-01271-78/01157740', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037832007740', 'А007-01271-78/01157708', '15.03.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027807582461', 'А007-01271-78/01157774', '15.03.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037832012316', 'А007-01271-78/01157800', '15.03.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027807577467', 'А007-01271-78/01157958', '07.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027807586586', 'А007-01271-78/01157748', '15.03.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027807585948', 'А007-01271-78/01157778', '15.03.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027807586091', 'А007-01271-78/01158196', '19.03.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027807587895', 'А007-01271-78/01157766', '15.03.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027807584023', 'А007-01271-78/01158134', '19.03.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027807573925', 'А007-01271-78/01158104', '26.02.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027807585300', 'А007-01271-78/01157717', '15.03.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027807586740', 'А007-01271-78/01157758', '15.03.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027807581493', '78А010000405', '15.03.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1099847000527', 'А007-01271-78/01157583', '09.04.2012', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027807583132', 'А007-01271-78/01157692', '15.03.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027807585024', 'А007-01271-78/01157967', '07.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027809009997', 'А007-01271-78/01157936', '27.05.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027809009084', 'А007-01271-78/01157906', '27.05.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027809010041', 'А007-01271-78/01157712', '15.03.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027809003530', 'А007-01271-78/01157907', '15.03.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027809003562', 'А007-01271-78/01157902', '15.03.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1089847102817', 'А007-01271-78/01158156', '06.02.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027809003540', 'А007-01271-78/01157927', '15.03.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027809005454', 'А007-01271-78/01158075', '07.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027809003551', 'А007-01271-78/01157878', '15.03.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027809007940', 'А007-01271-78/01158077', '07.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027809003584', 'А007-01271-78/01157884', '15.03.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027809003507', 'А007-01271-78/01157911', '15.03.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027809003617', 'А007-01271-78/01157893', '15.03.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027809003628', 'А007-01271-78/01157917', '15.03.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027809003529', 'А007-01271-78/01157903', '15.03.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027809003496', 'А007-01271-78/01158073', '07.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027809003518', 'А007-01271-78/01158063', '07.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027809002968', 'А007-01271-78/01158067', '07.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027809003639', 'А007-01271-78/01158050', '07.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027809003606', 'А007-01271-78/01157795', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027809003595', 'А007-01271-78/01157928', '15.03.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027809007380', 'А007-01271-78/01157899', '15.03.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027809005850', 'А007-01271-78/01157889', '15.03.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1047855063849', 'А007-01271-78/01157896', '15.03.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027809012186', 'А007-01271-78/01157772', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037839004103', '78А010000757', '23.05.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027807997051', 'А007-01271-78/01157949', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027807992761', 'А007-01271-78/01157880', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037835013974', 'А007-01271-78/01158184', '19.03.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027807991518', 'А007-01271-78/01157562', '28.03.2012', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037835051561', 'А007-01271-78/01158014', '07.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037835020079', 'А007-01271-78/01157941', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037825019594', 'А007-01271-78/01157901', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027807992706', 'А007-01271-78/01158183', '27.02.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037825006087', 'А007-01271-78/01158193', '19.03.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037835027230', 'А007-01271-78/01158006', '07.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037835024820', 'А007-01271-78/01157643', '17.02.2012', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027807991331', 'А007-01271-78/01157568', '14.03.2011', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027807992772', 'А007-01271-78/01157561', '17.02.2011', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027807992453', 'А007-01271-78/01157566', '14.03.2011', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027807984863', 'А007-01271-78/01158083', '07.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027807992794', 'А007-01271-78/01157522', '17.02.2011', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027807997250', 'А007-01271-78/01157657', '17.02.2012', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027808003332', 'А007-01271-78/01158065', '07.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037835006318', 'А007-01271-78/01157925', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037835019012', 'А007-01271-78/01157610', '14.03.2012', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027807992850', 'А007-01271-78/01158085', '07.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027807997557', 'А007-01271-78/01157554', '14.03.2011', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037835036546', 'А007-01271-78/01158202', '26.02.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027808012715', 'А007-01271-78/01158068', '07.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037835052331', 'А007-01271-78/01157934', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804605905', 'А007-01271-78/01157881', '27.05.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037835036458', 'А007-01271-78/01158072', '07.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027807992838', 'А007-01271-78/01157567', '17.02.2011', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027807992937', 'А007-01271-78/01157642', '17.02.2012', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037835048041', 'А007-01271-78/01158195', '19.03.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027807992981', 'А007-01271-78/01157563', '14.03.2011', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037835013853', 'А007-01271-78/01157564', '15.03.2011', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027807992200', 'А007-01271-78/01157546', '14.03.2011', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027807991562', 'А007-01271-78/01158197', '19.03.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027807992783', 'А007-01271-78/01157940', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037835054575', 'А007-01271-78/01157552', '17.02.2011', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037835024589', 'А007-01271-78/01157916', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037835020156', 'А007-01271-78/01158198', '19.03.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027807992190', 'А007-01271-78/01157943', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027807991452', 'А007-01271-78/01157944', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027807991584', 'А007-01271-78/01157919', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027807992728', 'А007-01271-78/01158079', '07.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027807979693', 'А007-01271-78/01157937', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037835045258', 'А007-01271-78/01157565', '14.03.2011', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027807992827', 'А007-01271-78/01157639', '14.03.2012', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027809226312', 'А007-01271-78/01157862', '27.05.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1047844001446', 'А007-01271-78/01157824', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027809254593', 'А007-01271-78/01157871', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027809217480', 'А007-01271-78/01157975', '07.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027809238467', 'А007-01271-78/01157773', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037843033030', 'А007-01271-78/01158170', '14.03.2011', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027809226653', 'А007-01271-78/01157879', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037843004891', 'А007-01271-78/01157994', '07.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027809243571', 'А007-01271-78/01157503', '14.03.2011', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027809204169', 'А007-01271-78/01157977', '07.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037843012866', 'А007-01271-78/01157821', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037843005881', 'А007-01271-78/01157887', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037843011205', 'А007-01271-78/01157634', '17.02.2012', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027809246046', 'А007-01271-78/01157637', '26.03.2012', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037843029025', 'А007-01271-78/01158136', '26.02.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027810349841', 'А007-01271-78/01157727', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027808913142', 'А007-01271-78/01157989', '03.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037800021380', 'А007-01271-78/01157537', '17.02.2011', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027809215829', 'А007-01271-78/01158025', '07.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037843021446', 'А007-01271-78/01157827', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027809255891', 'А007-01271-78/01158016', '07.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027809230360', 'А007-01271-78/01158061', '07.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037843005441', 'А007-01271-78/01157882', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027809245860', 'А007-01271-78/01157863', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037843047450', 'А007-01271-78/01158019', '07.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027809249049', 'А007-01271-78/01157861', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027809191442', '78А010000010', '26.03.2012', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037843091208', 'А007-01271-78/01157865', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027809242493', 'А007-01271-78/01157633', '14.03.2012', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027809256617', 'А007-01271-78/01157867', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037843003428', 'А007-01271-78/01157875', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027809237246', 'А007-01271-78/01157728', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037843044601', 'А007-01271-78/01157872', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037843000898', 'А007-01271-78/01158058', '07.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037843060405', 'А007-01271-78/01157890', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1047841026177', 'А007-01271-78/01158164', '27.02.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027809255077', 'А007-01271-78/01157898', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037843076006', 'А007-01271-78/01158132', '26.02.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037843012790', 'А007-01271-78/01157897', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037843089602', 'А007-01271-78/01158004', '07.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804597765', 'А007-01271-78/01157499', '14.03.2011', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027801539237', 'А007-01271-78/01158098', '27.02.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037865008720', 'А007-01271-78/01157619', '28.02.2012', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037851004620', 'А007-01271-78/01158228', '18.06.2018', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037841000273', 'А007-01271-78/01157760', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037828008206', 'А007-01271-78/01157559 ', '02.06.2011', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1057812684280', 'А007-01271-78/01157618', '26.03.2012', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037843024768', 'А007-01271-78/01157612', '17.02.2012', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1107800001814', 'А007-01271-78/01157600', '17.02.2012', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802496480', 'А007-01271-78/01157765', '27.05.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037816004126', 'А007-01271-78/01157839', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027809210989', 'А007-01271-78/01157810', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037800012612', 'А007-01271-78/01157794', '16.01.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027809214685', 'А007-01271-78/01157926', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037851007512', 'А007-01271-78/01157953', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1087800005050', 'А007-01271-78/01157798', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1117847239839', 'А007-01271-78/01157870', '01.02.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1117847205189', 'А007-01271-78/01157689', '15.03.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1107847247694', 'А007-01271-78/01157736', '15.03.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037800034854', 'А007-01271-78/01157769', '15.03.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037835050362', 'А007-01271-78/01157996', '03.06.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027810241810', 'А007-01271-78/01157956', '02.06.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037843080417', 'А007-01271-78/01158220', '26.04.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027808913330', 'А007-01271-78/01158097', '11.02.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1087800008152', 'А007-01271-78/01157697', '19.06.2013', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1117847290824', 'А007-01271-78/01157973', '07.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804606400', 'А007-01271-78/01158087', '07.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1117847398338', 'А007-01271-78/01158081', '07.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037819004728', 'А007-01271-78/01157998', '07.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1097847278649', 'А007-01271-78/01158001', '07.05.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037800033798', 'А007-01271-78/01158056', '02.06.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037843105410', 'А007-01271-78/01158142', '26.02.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1107800001924', 'А007-01271-78/01158089', '27.02.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027806082391', 'А007-01271-78/01158201', '27.02.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802756607', 'А007-01271-78/01158090', '04.02.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1137847313009', 'А007-01271-78/01158204', '06.02.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804606191', 'А007-01271-78/01158163', '11.02.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1157847036016', 'А007-01271-78/01158155', '29.12.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1147847001829', 'А007-01271-78/01158268', '29.12.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037832007553', 'А007-01271-78/01158113', '14.05.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1137847052419', 'А007-01271-78/01158177', '14.05.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037832008477', 'А007-01271-78/01157969', '07.03.2014', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027802746828', 'А007-01271-78/01157541', '14.03.2011', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1157847088640', 'А007-01271-78/01158191', '29.12.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1147847198091', 'А007-01271-78/01158128', '29.12.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804187850', 'А007-01271-78/01158189', '29.12.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1147847199202', 'А007-01271-78/01158172', '29.12.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1147847043717', 'А007-01271-78/01158213', '25.04.2016', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1057811690122', 'А007-01271-78/01158208', '31.05.2016', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027808757921', 'А007-01271-78/01157558', '26.12.2011', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1117847113009', 'А007-01271-78/01158211', '29.06.2016', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037843056712', 'А007-01271-78/01158096', '04.02.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1047800002513', 'А007-01271-78/01158106', '04.02.2015', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027809008974', 'А007-01271-78/01158206', '27.09.2016', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1147847543084', 'А007-01271-78/01158215', '26.12.2016', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1147800010115', 'А007-01271-78/01158219', '19.04.2017', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037841002396', 'А007-01271-78/01158224', '20.03.2017', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1127800003605', 'А007-01271-78/01158241', '09.01.2018', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1167847218098', 'А007-01271-78/01158235', '09.01.2018', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1147847205681', 'А007-01271-78/01158236', '09.01.2018', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1177847116402', 'А007-01271-78/01158232', '03.07.2018', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1167847321861', 'А007-01271-78/01158226', '27.12.2018', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1157800002964', 'А007-01271-78/01158248', '03.07.2019', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027804874965', 'А007-01271-78/01158250', '03.07.2019', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1187847074843', 'А007-01271-78/01158263', '14.01.2020', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1177847346973', 'А007-01271-78/01158266', '14.01.2020', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1157847167840', 'А007-01271-78/01158261', '14.01.2020', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1187847210935', 'А007-01271-78/01158260', '14.01.2020', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1157800002414', 'А007-01271-78/01158280', '22.01.2021', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1197847080562', 'А007-01271-78/01158277', '24.02.2021', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1177847375639', 'А007-01271-78/01158278', '24.02.2021', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1147800005077', 'А007-01271-78/01158269', '11.06.2021', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1037843019609', 'А007-01271-78/01158282', '26.06.2021', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1177847315106', 'А007-01271-78/01158271', '11.06.2021', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1167800052584', 'А007-01271-78/01158276', '02.06.2021', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1197800002817', 'А007-01271-78/01158270', '22.12.2022', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1207800084425', 'А007-01271-78/01158273', '22.12.2021', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1217800074524', 'А007-01271-78/01158274', '22.12.2021', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1207700502525', 'А007-01271-78/01158281', '22.12.2021', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1197847106929', 'А007-01271-78/01158275', '22.12.2021', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1197847193466', 'А007-01271-78/01158272', '22.12.2021', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1197847238490', 'А007-01271-78/01158267', '22.12.2021', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027807591965', 'А007-01271-78/01157505', '14.03.2011', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1157800002590', 'А007-01271-78/01158283', '20.06.2022', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1027801583017', 'А007-01271-78/01158289', '20.06.2022', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1217800128171', 'А007-01271-78/01158291', '27.12.2023', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1217800055516', 'А007-01271-78/01158288', '27.12.2022', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1217800057166', 'А007-01271-78/01158286', '27.12.2022', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1217800059498', 'А007-01271-78/01158290', '27.12.2022', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1207800042780', 'А007-01271-78/01158287', '27.12.2022', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1227800056571', 'А007-01271-78/00956942', '30.11.2023', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1217800048290', 'А007-01271-78/00977043', '15.12.2023', NULL);
    EXECUTE PROCEDURE FIX_SPO_LICDATA_DTL(1, '1227800108491', 'А007-01271-78/01036958', '26.01.2024', NULL);
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIX_SPO_LICDATA_DTL (
    I$TYPE SMALLINT,
    I$OGRN VARCHAR(40),
    I$NUM VARCHAR(100),
    I$DATE DATE,
    I$DATE_TO DATE)
AS
DECLARE VARIABLE V$OU_ID BIGINT;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$DOC_TYPE BIGINT;
DECLARE VARIABLE V$LINK_ID BIGINT;
DECLARE VARIABLE S VARCHAR(400);
DECLARE VARIABLE D DATE;
DECLARE VARIABLE T1 BIGINT;
DECLARE VARIABLE T2 BIGINT;
begin

  SELECT FIRST 1 L.OBJ_ID
  FROM VALS V
  JOIN LINKS L ON L.OBJ_ID = V.OBJ_ID AND L.PARENT_TYPE_ID IN (111, 112) AND L.DATE_DEL IS NULL
  WHERE V.PARAM_ID IN (9, 33) AND V.IS_DEL = 0 AND V.SVAL = :I$OGRN -- ИНН или ОГРН
  INTO :V$OU_ID;

  -- Нет такой ОУ ?
  IF(V$OU_ID IS NULL) THEN EXIT;

  V$DOC_TYPE = IIF(I$TYPE = 0, 1052, 1053);

  SELECT FIRST 1 L17.OBJ_ID, V480.SVAL, V482.VAL
  FROM LINKS L17
  JOIN VALL V471 ON V471.OBJ_ID = L17.OBJ_ID AND V471.PARAM_ID = 471 AND V471.IS_DEL = 0 AND V471.LISTVAL_ID = :V$DOC_TYPE
  JOIN VALL V613 ON V613.OBJ_ID = L17.OBJ_ID AND V613.PARAM_ID = 613 AND V613.IS_DEL = 0 AND V613.LISTVAL_ID IN (1982, 1984)
  LEFT JOIN VALS V480 ON V480.OBJ_ID = L17.OBJ_ID AND V480.PARAM_ID = 480 AND V480.IS_DEL = 0
  LEFT JOIN VALD V482 ON V482.OBJ_ID = L17.OBJ_ID AND V482.PARAM_ID = 482 AND V482.IS_DEL = 0
  WHERE L17.PARENT_ID = :V$OU_ID AND L17.OBJ_TYPE_ID = 17 AND L17.DATE_DEL IS NULL
  INTO :V$OBJ_ID, :S, :D;

  IF(V$OBJ_ID IS NULL) THEN
  BEGIN
    -- Вставляем документ в адресной сетке организации
    T1 = V$OU_ID / 1000000000;
    T2 = T1 + 1;
    T1 = T1 * 1000000000;
    T2 = T2 * 1000000000;

    SELECT FIRST 1 OBJ.OBJ_ID + 1
    FROM OBJECTS OBJ
    WHERE OBJ.OBJ_ID >= :T1 AND OBJ.OBJ_ID < :T2
    ORDER BY 1 DESC
    INTO :V$OBJ_ID;

    SELECT FIRST 1 L.LINK_ID + 1
    FROM LINKS L
    WHERE L.LINK_ID >= :T1 AND L.LINK_ID < :T2
    ORDER BY 1 DESC
    INTO :V$LINK_ID;

    INSERT INTO OBJECTS
    (OBJ_ID, TYPE_ID)
    VALUES (:V$OBJ_ID, 17);

    INSERT INTO LINKS
    (LINK_ID, PARENT_ID, OBJ_ID, DATE_INS)
    VALUES (:V$LINK_ID, :V$OU_ID, :V$OBJ_ID, CURRENT_TIMESTAMP);

    UPDATE OR INSERT INTO VALL
    (OBJ_ID, PARAM_ID, IS_DEL, LISTVAL_ID)
    VALUES (:V$OBJ_ID, 613, 0, 1982)
    MATCHING (OBJ_ID, PARAM_ID);

    UPDATE OR INSERT INTO VALL
    (OBJ_ID, PARAM_ID, IS_DEL, LISTVAL_ID)
    VALUES (:V$OBJ_ID, 471, 0, :V$DOC_TYPE)
    MATCHING (OBJ_ID, PARAM_ID);
  END

  IF(S IS NULL) THEN
  UPDATE OR INSERT INTO VALS
  (OBJ_ID, PARAM_ID, IS_DEL, VAL)
  VALUES (:V$OBJ_ID, 480, 0, :I$NUM)
  MATCHING (OBJ_ID, PARAM_ID);

  IF(D IS NULL) THEN
  UPDATE OR INSERT INTO VALD
  (OBJ_ID, PARAM_ID, IS_DEL, VAL)
  VALUES (:V$OBJ_ID, 482, 0, :I$DATE)
  MATCHING (OBJ_ID, PARAM_ID);

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIX_SPO_MOVEMENTS
AS
declare variable V$STUDENT_ID bigint;
declare variable V$GRADE_ID bigint;
declare variable V$GRADE_TYPE bigint;
declare variable V$STAGE_ID bigint;
declare variable V$DATE date;
declare variable V$YDATE date;
declare variable V$DT timestamp;
declare variable V$REASON_ID bigint;
declare variable V$ACD_ID bigint;
declare variable V$DATE2 date;
declare variable V$ORDER_DATE date;
declare variable V$ORDER_NUM varchar(100);
declare variable V$MOVE_ID bigint;
begin

  IF(EXTRACT(MONTH FROM CURRENT_DATE) < 9) THEN V$YDATE = '01.09.' || (EXTRACT(YEAR FROM CURRENT_DATE) - 1);
  ELSE V$YDATE = '01.09.' || EXTRACT(YEAR FROM CURRENT_DATE);

  -- Обучающиеся вообще без записи в учебном коллективе
  -- Если запись есть, но проставлена дата выбытия - пофикшено не будет
  FOR
    SELECT L10.OBJ_ID, L9.OBJ_ID, L9.OBJ_TYPE_ID, V49.LISTVAL_ID, L10.DATE_INS
    FROM LINKS L2
    JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    LEFT JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 289) AND L9.DATE_DEL IS NULL
    JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    AND NOT EXISTS (
      SELECT FIRST 1 1
      FROM PERSON_MOVEMENTS M
      WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = L10.OBJ_ID AND M.GROUP_ID = L9.OBJ_ID
    )
    ORDER BY 1
    INTO :V$STUDENT_ID, :V$GRADE_ID, :V$GRADE_TYPE, :V$STAGE_ID, :V$DATE
  DO
  BEGIN
    IF(V$DATE < V$YDATE) THEN V$DATE = V$YDATE;

    INSERT INTO PERSON_MOVEMENTS
    (PERSON_ID, GROUP_ID, GROUP_TYPE_ID, REASON_IN, DATE_IN, NAME_IN, LEVEL_ID)
    VALUES (:V$STUDENT_ID, :V$GRADE_ID, :V$GRADE_TYPE, IIF(:V$GRADE_TYPE = 289, 5319, 5322), :V$DATE,
      (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$GRADE_ID)), 29);
  END

  -- Обучающиеся в учебных коллективах с незакрытыми записями академического отпуска
  FOR
    SELECT L10.OBJ_ID, L9.OBJ_ID, L9.OBJ_TYPE_ID, V49.LISTVAL_ID, L10.DATE_MODIFY
    FROM LINKS L2
    JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    LEFT JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
    JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    ORDER BY 1
    INTO :V$STUDENT_ID, :V$GRADE_ID, :V$GRADE_TYPE, :V$STAGE_ID, :V$DT
  DO
  BEGIN
    -- Какая стоит причина зачисления ?
    V$DATE = NULL;
    V$REASON_ID = NULL;
    SELECT FIRST 1 M.REASON_IN, M.DATE_IN, M.ORDER_DATE_IN, M.ORDER_NUM_IN
    FROM PERSON_MOVEMENTS M
    WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :V$STUDENT_ID AND M.GROUP_ID = :V$GRADE_ID AND M.DATE_OUT IS NULL
    ORDER BY M.DATE_IN DESC
    INTO :V$REASON_ID, :V$DATE, :V$ORDER_DATE, :V$ORDER_NUM;

    -- Что у нас с записью в академке ?
    V$MOVE_ID = NULL;
    V$DATE2 = NULL;
    V$ACD_ID = NULL;
    SELECT FIRST 1 M.GROUP_ID, M.DATE_IN, M.OBJ_ID
    FROM PERSON_MOVEMENTS M
    WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :V$STUDENT_ID AND M.GROUP_TYPE_ID = 289 AND M.DATE_OUT IS NULL
    INTO :V$ACD_ID, :V$DATE2, :V$MOVE_ID;

    IF(V$MOVE_ID IS NOT NULL) THEN
    BEGIN
      -- Если восстанавливались из отпуска с более поздней датой - закрываем академку как обычно
      IF(V$REASON_ID = 5320 AND V$DATE >= V$DATE2) THEN
      BEGIN
        UPDATE PERSON_MOVEMENTS
        SET REASON_OUT = 5320, DATE_OUT = :V$DATE, ORDER_DATE_OUT = :V$ORDER_DATE, ORDER_NUM_OUT = :V$ORDER_NUM
        WHERE OBJ_ID = :V$MOVE_ID;
      END
      -- Есть только обычное продолжение или начало обучения - удаляем запись академки
      ELSE IF(EXISTS(SELECT FIRST 1 1 FROM LISTVALS LV WHERE LV.LISTVAL_ID = :V$REASON_ID AND
        (POSITION('TRANSFERED' IN LV."FILTER") > 0 OR POSITION('ACCEPTED' IN LV."FILTER") > 0))) THEN
      BEGIN
        UPDATE PERSON_MOVEMENTS
        SET DATE_DEL = CURRENT_TIMESTAMP
        WHERE OBJ_ID = :V$MOVE_ID;
      END
    END
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIX_SPO_SPEC_CODES
AS
declare variable V$OU_ID bigint;
declare variable V$STD_FOLDER bigint;
declare variable V$GRADE_ID bigint;
declare variable V$LEVEL_ID bigint;
declare variable V$STAGE_ID bigint;
declare variable V$STAGE_FOLDER bigint;
declare variable V$C1 bigint;
declare variable V$C2 bigint;
declare variable V$C3 bigint;
declare variable V$LIST_ID bigint;
declare variable T integer;
begin

  SELECT FIRST 1 1
  FROM LINKS L2
  JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
  JOIN VALL V43 ON V43.OBJ_ID = L7.OBJ_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0 AND V43.LISTVAL_ID = 13131
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$STD_FOLDER;

  FOR
    SELECT L9.OBJ_ID, V43.LISTVAL_ID, V49.LISTVAL_ID, V2165.LISTVAL_ID, V2821.LISTVAL_ID, V3367.LISTVAL_ID, L2.OBJ_ID
    FROM LINKS L2
    JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    JOIN VALL V43 ON V43.OBJ_ID = L7.OBJ_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
    LEFT JOIN VALL V2165 ON V2165.OBJ_ID = L9.OBJ_ID AND V2165.PARAM_ID = 2165 AND V2165.IS_DEL = 0 -- старое поле, которое переделали на приказ 336
    LEFT JOIN VALL V2821 ON V2821.OBJ_ID = L9.OBJ_ID AND V2821.PARAM_ID = 2821 AND V2821.IS_DEL = 0 -- новое поле, приказ 1199
    LEFT JOIN VALL V3367 ON V3367.OBJ_ID = L9.OBJ_ID AND V3367.PARAM_ID = 3367 AND V3367.IS_DEL = 0 -- коды обучения
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :V$GRADE_ID, :V$LEVEL_ID, :V$STAGE_ID, :V$C1, :V$C2, :V$C3, :V$OU_ID
  DO
  BEGIN

    -- Если заполнено C3, то C1 и C2 зачищаем, и переносим в раздел обучения если группа не там
    IF(V$C3 IS NOT NULL) THEN
    BEGIN
      UPDATE VALL
      SET IS_DEL = 1
      WHERE OBJ_ID = :V$GRADE_ID AND PARAM_ID IN (2165, 2821) AND IS_DEL = 0;

      IF(V$LEVEL_ID <> 13131) THEN
      BEGIN
        -- Создаем раздел профессионального обучения
        IF(V$STD_FOLDER IS NULL) THEN
        BEGIN
          SELECT OBJ_ID FROM OBJECT_ADD(:V$OU_ID, 7) INTO :V$STD_FOLDER;
          SELECT 1 FROM VAL_ADD(43, :V$STD_FOLDER, 13131) INTO :T;
        END

        V$STAGE_FOLDER = NULL;
        SELECT FIRST 1 L8.OBJ_ID
        FROM LINKS L8
        JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0 AND V49.LISTVAL_ID = :V$STAGE_ID
        WHERE L8.PARENT_ID = :V$STD_FOLDER AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
        INTO :V$STAGE_FOLDER;

        IF(V$STAGE_FOLDER IS NULL) THEN
        BEGIN
          SELECT OBJ_ID FROM OBJECT_ADD(:V$STD_FOLDER, 8) INTO :V$STAGE_FOLDER;
          SELECT 1 FROM VAL_ADD(49, :V$STAGE_FOLDER, :V$STAGE_ID) INTO :T;
        END

        -- Перекладываем в раздел обучения
        UPDATE LINKS
        SET PARENT_ID = :V$STAGE_FOLDER
        WHERE OBJ_ID = :V$GRADE_ID AND PARENT_TYPE_ID = 8 AND DATE_DEL IS NULL;

        -- Изменяем код в реестре движения
        UPDATE PERSON_MOVEMENTS
        SET LEVEL_ID = 13131
        WHERE GROUP_ID = :V$GRADE_ID;
      END
    END
    -- Если заполнено C2, то сносим C1 (может быть хвост от старых данных)
    ELSE IF(V$C2 IS NOT NULL) THEN
    BEGIN
      UPDATE VALL
      SET IS_DEL = 1
      WHERE OBJ_ID = :V$GRADE_ID AND PARAM_ID IN (2165, 3367) AND IS_DEL = 0;

      -- Если вдруг значение оказалось из приказа 336, то изменяем id параметра
      -- значение самого кода остается неизменным
      SELECT LV.LIST_ID
      FROM LISTVALS LV
      WHERE LV.LISTVAL_ID = :V$C2
      INTO :V$LIST_ID;

      IF(V$LIST_ID = 366) THEN
      BEGIN
        -- Удаляем старое значение, чтобы не было конфликта
        DELETE FROM VALL WHERE OBJ_ID = :V$GRADE_ID AND PARAM_ID = 2165;
        -- Переставляем id параметра со старого приказа на новый, который теперь хранится в восстановленном старом поле
        UPDATE VALL SET PARAM_ID = 2165 WHERE OBJ_ID = :V$GRADE_ID AND PARAM_ID = 2821;
      END
    END
    -- Если заполнено C1 и оно не относится к новому справочнику, то это старый хвост - сносим и ссылку, и код
    ELSE IF(V$C1 IS NOT NULL) THEN
    BEGIN
      SELECT LV.LIST_ID
      FROM LISTVALS LV
      WHERE LV.LISTVAL_ID = :V$C1
      INTO :V$LIST_ID;

      IF(V$LIST_ID = 244) THEN
      BEGIN
        UPDATE VALL SET IS_DEL = 1 WHERE OBJ_ID = :V$GRADE_ID AND PARAM_ID = 2165 AND IS_DEL = 0;
        UPDATE VALS SET IS_DEL = 1 WHERE OBJ_ID = :V$GRADE_ID AND PARAM_ID = 2822 AND IS_DEL = 0;
      END
    END

  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIX_SPO_TRANSFER
AS
begin

  UPDATE PERSON_MOVEMENTS SET REASON_IN = 5310 WHERE REASON_IN = 807;
  UPDATE PERSON_MOVEMENTS SET REASON_OUT = 5310 WHERE REASON_OUT = 807;
  UPDATE PERSON_MOVEMENTS SET REASON_IN = 5310 WHERE REASON_IN = 5316;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIX_STEAD_FOLDER
AS
declare variable V$OBJ_ID bigint;
declare variable N integer;
begin

  FOR
    SELECT L2.OBJ_ID
    FROM LINKS L2
    LEFT JOIN LINKS L488 ON L488.PARENT_ID = L2.OBJ_ID AND L488.OBJ_TYPE_ID = 488 AND L488.DATE_DEL IS NULL
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND L488.LINK_ID IS NULL
    ORDER BY 1
    INTO :V$OBJ_ID
  DO
  BEGIN
    SELECT 1 FROM OBJECT_ADD(:V$OBJ_ID, 488) INTO :N;
  END

  UPDATE VALS
  SET VAL = 'Здания и сооружения'
  WHERE PARAM_ID = 423;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIX_STUDENT_EDU_FROM
AS
DECLARE VARIABLE V$STUDENT_ID BIGINT;
DECLARE VARIABLE V$CLASS_EDU_FORM BIGINT;
begin
  -- Зададим каждому студенту такую же форму обучения, какая задана у класса
  FOR
    SELECT DISTINCT L10.OBJ_ID, V1768.LISTVAL_ID
    FROM LINKS L2
    JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 and L7.DATE_DEL IS NULL
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 and L8.DATE_DEL IS NULL
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 and L9.DATE_DEL IS NULL
    JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 and L10.DATE_DEL IS NULL
    JOIN VALL V1768 ON V1768.OBJ_ID = L9.OBJ_ID AND V1768.PARAM_ID = 1768 AND V1768.IS_DEL = 0
    LEFT JOIN VALL V80 ON V80.OBJ_ID = L10.OBJ_ID AND V80.PARAM_ID = 80 AND V80.IS_DEL = 0
    WHERE L2.OBJ_TYPE_ID = 2 AND L2.PARENT_ID IS NULL AND L2.DATE_DEL IS NULL AND V1768.LISTVAL_ID <> COALESCE(V80.LISTVAL_ID, 0)
    INTO :V$STUDENT_ID, :V$CLASS_EDU_FORM
  DO
  BEGIN
    UPDATE VALL
    SET LISTVAL_ID = :V$CLASS_EDU_FORM
    WHERE OBJ_ID = :V$STUDENT_ID AND PARAM_ID = 80 AND IS_DEL = 0;
  END
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIX_STUDY_PLANS
AS
declare variable N integer;
begin

  UPDATE PLAN_LOADS
  SET LOAD_HOURS = COALESCE(LOAD_HOURS_S1, 0) + COALESCE(LOAD_HOURS_S2, 0)
  WHERE LOAD_HOURS_S1 IS NOT NULL AND LOAD_HOURS IS NULL;

  SELECT COUNT(*) FROM MONITORING_PLAN_UPD(NULL) INTO :N;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIX_TEMPLATE_UP_DAMAGED
AS
declare variable V$STAGE_ID bigint;
declare variable V$LOAD_ID bigint;
begin

  FOR
      SELECT L54.OBJ_ID
      FROM LINKS L50
      JOIN LINKS L54 ON L54.PARENT_ID = L50.OBJ_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL AND L54.OBJ_ID > 1000000000
      WHERE L50.PARENT_ID = 258 AND L50.OBJ_TYPE_ID = 50 AND L50.DATE_DEL IS NULL AND L50.OBJ_ID < 1000000000
      INTO :V$STAGE_ID
  DO
  BEGIN

      -- Удаляем все нагрузки
      FOR
          SELECT L56.OBJ_ID
          FROM LINKS L56
          WHERE L56.PARENT_ID = :V$STAGE_ID AND L56.OBJ_TYPE_ID = 56
          INTO :V$LOAD_ID
      DO
      BEGIN
          DELETE FROM LINKS WHERE OBJ_ID = :V$LOAD_ID;
          DELETE FROM LINKS WHERE PARENT_ID = :V$LOAD_ID;
          DELETE FROM OBJECTS WHERE OBJ_ID = :V$LOAD_ID;
      END

      DELETE FROM LINKS WHERE OBJ_ID = :V$STAGE_ID;
      DELETE FROM OBJECTS WHERE OBJ_ID = :V$STAGE_ID;

  END


end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIX_UPGRADE_REQUEST_YEAR
AS
declare variable OBJ_ID bigint;
declare variable PARAM_ID bigint;
declare variable V varchar(100);
declare variable IS_DEL integer;
declare variable VI integer;
begin

  FOR
      SELECT V.OBJ_ID, V.PARAM_ID, V.VAL, V.IS_DEL
      FROM VALS V
      WHERE V.PARAM_ID IN (618, 621) AND V.IS_DEL = 0
      INTO :OBJ_ID, :PARAM_ID, :V, :IS_DEL
  DO
  BEGIN

      VI = NULL;

      -- Значение как оно есть
      IF(CHAR_LENGTH(V) = 4) THEN VI = V;
      -- На всякий случай вариант двузначного года
      ELSE IF(CHAR_LENGTH(V) = 2) THEN VI = V;
      --
      ELSE IF(CHAR_LENGTH(V) > 4) THEN
      BEGIN

          -- Вариант с XXXX-YYYY
          IF(SUBSTRING(V FROM 5 FOR 1) = '-') THEN VI = SUBSTRING(V FROM 1 FOR 4);
          -- Вариант DD.MM.YYyy или MM.YYyy
          ELSE IF(SUBSTRING(V FROM 3 FOR 1) = '.') THEN
          BEGIN
              -- Вариант с числом
              IF(SUBSTRING(V FROM 5 FOR 1) = '.') THEN BEGIN
                -- Далее двузначный или четырехзначный год
                IF(SUBSTRING(V FROM 6 FOR 2) = '20') THEN VI = SUBSTRING(V FROM 6 FOR 4); ELSE VI = SUBSTRING(V FROM 6 FOR 2);
              END
              -- Вариант с месяцем
              ELSE
              BEGIN
                IF(SUBSTRING(V FROM 4 FOR 2) = '20') THEN VI = SUBSTRING(V FROM 4 FOR 4); ELSE VI = SUBSTRING(V FROM 4 FOR 2);
              END
          END

      END

      IF(VI IS NOT NULL) THEN
      BEGIN

          -- Коррекция двузначного года
          IF(VI < 100) THEN VI = 2000 + VI;

          UPDATE OR INSERT INTO VALI
          (OBJ_ID, PARAM_ID, VAL, IS_DEL)
          VALUES (:OBJ_ID, :PARAM_ID, :VI, :IS_DEL)
          MATCHING (OBJ_ID, PARAM_ID);

      END

  END

  -- Удаляем старые строковые значения
  DELETE FROM VALS WHERE PARAM_ID IN (618, 621);

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIX_USER_LEVELS
AS
DECLARE VARIABLE V$USER_ID BIGINT;
DECLARE VARIABLE V$LEVEL BIGINT;
DECLARE VARIABLE S1 VARCHAR(200);
DECLARE VARIABLE S2 VARCHAR(200);
DECLARE VARIABLE D BIGINT;
begin

  FOR
    SELECT LU.USER_ID, LU.LEVEL_ID, RT.VAL
    FROM LUSERS LU
    JOIN LEVELS L ON L.LEVEL_ID = LU.LEVEL_ID
    JOIN TASKS T ON T.TASK_ID = L.TASK_ID
    JOIN RES RT ON RT.RES_ID = T.RES_ID AND RT.LANG_CODE = 'RU'
    JOIN MODULES M ON M.MODULE_ID = T.MODULE_ID AND M.IS_ACTIVE = 0
    WHERE LU.USER_ID <> 1
    ORDER BY 1, 2
    INTO :V$USER_ID, :V$LEVEL, :S1
  DO
  BEGIN
    S2 = NULL;
    IF(S1 = 'Личные дела сотрудников') THEN S2 = 'Сотрудники';
    IF(S1 = 'Личные дела обучающихся, воспитанников') THEN S2 = 'Учебные коллективы и обучающиеся';
    IF(S1 = 'Личные дела воспитанников') THEN S2 = 'Учебные коллективы и обучающиеся';
    IF(S1 = 'Электронные журналы') THEN S2 = 'Управление электронными журналами';
    IF(S1 = 'Структура ОООД') THEN S2 = 'Структура и документы образовательной организации';

    D = NULL;
    SELECT FIRST 1 L.LEVEL_ID
    FROM MODULES M
    JOIN TASKS T ON T.MODULE_ID = M.MODULE_ID AND T.IS_DEL = 0
    JOIN RES RT ON RT.RES_ID = T.RES_ID AND RT.LANG_CODE = 'RU' AND (UPPER(RT.VAL) = UPPER(:S1) OR UPPER(RT.VAL) = UPPER(:S2))
    JOIN LEVELS L ON L.TASK_ID = T.TASK_ID AND L.IS_DEL = 0
    WHERE M.IS_DEL = 0 AND M.IS_ACTIVE = 1
    INTO :D;

    IF(D IS NULL OR EXISTS(SELECT FIRST 1 1 FROM LUSERS WHERE USER_ID = :V$USER_ID AND LEVEL_ID = :D)) THEN
    BEGIN
      DELETE FROM LUSERS
      WHERE USER_ID = :V$USER_ID AND LEVEL_ID = :V$LEVEL;
    END
    ELSE
    BEGIN
      UPDATE LUSERS
      SET LEVEL_ID = :D
      WHERE USER_ID = :V$USER_ID AND LEVEL_ID = :V$LEVEL;
    END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIX_VACANCY_CATEGORIES (
    SCHOOL_ID BIGINT)
AS
declare variable EMP_ID bigint;
declare variable CAT_ID bigint;
declare variable ASSN_ID bigint;
declare variable ASSN_TYPE bigint;
declare variable ASSN_CAT bigint;
declare variable TMP bigint;
begin

  FOR
    SELECT DISTINCT L14.OBJ_ID, V281.LISTVAL_ID
    FROM LINKS L14
    JOIN VALL V281 ON V281.OBJ_ID = L14.OBJ_ID AND V281.PARAM_ID = 281 AND V281.IS_DEL = 0
    WHERE L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
    INTO :EMP_ID, :CAT_ID
  DO
  BEGIN

    -- Обновляем все основные должности по сотруднику, а все дополнительные выставляем без категории
    -- только те должности, где сотрудник не уволен
    FOR
      SELECT L15.OBJ_ID, V72.LISTVAL_ID
      FROM LINKS L15
      LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
      JOIN VALL V72 ON V72.OBJ_ID = L15.OBJ_ID AND V72.PARAM_ID = 72 AND V72.IS_DEL = 0
      WHERE L15.PARENT_ID = :EMP_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL AND (V74.VAL IS NULL OR V74.VAL > CURRENT_TIMESTAMP)
      INTO :ASSN_ID, :ASSN_TYPE
    DO
    BEGIN

      IF(ASSN_TYPE = 934) THEN ASSN_CAT = CAT_ID; ELSE ASSN_CAT = 632;

      SELECT BLOB_ID FROM VAL_ADD(1790, :ASSN_ID, :ASSN_CAT) INTO :TMP;

    END

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FIX_VARGRP_MOVES RETURNS (
    LINK_ID BIGINT,
    PARENT_ID BIGINT,
    OBJ_ID BIGINT)
AS
declare variable V$N integer;
declare variable V$STUDENT_ID bigint;
declare variable V$GRADE_ID bigint;
declare variable V$MOVE_TYPE varchar(400);
begin

  -- Смысл утрачен

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FN_EXAM_DATE_DELETE (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    ERROR_TEXT VARCHAR(200))
AS
begin

    -- Пока без проверок

    IF(0 = 1) THEN SUSPEND;
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FOOD_BENEFIT_APP_EXPORT (
    I$SCHOOL_ID BIGINT = null)
RETURNS (
    TAG_NAME VARCHAR(255),
    VAL VARCHAR(4000))
AS
declare variable V$PUPIL_ID bigint;
declare variable V$DOC_ID bigint;
declare variable V$REGION varchar(255);
declare variable V$DISTRICT varchar(255);
declare variable V$TOWN varchar(255);
declare variable V$SETTLEMENT varchar(255);
declare variable V$STREET varchar(255);
declare variable V$HOUSE varchar(255);
declare variable V$LITER varchar(255);
declare variable V$CORP varchar(255);
declare variable V$FLAT varchar(255);
declare variable V$INDEX varchar(255);
declare variable V$YEAREND integer;
BEGIN

    -- Функционал утрачен и перенесен в FOOD_BENEFIT_APP_EXPORT_SCHOOL

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FOOD_BENEFIT_APP_EXPORT_PUPIL (
    I$PUPIL_ID BIGINT NOT NULL,
    I$USER_ID BIGINT)
RETURNS (
    TAG_NAME VARCHAR(255),
    VAL VARCHAR(4000))
AS
declare variable V$DOC_ID bigint;
declare variable V$REGION varchar(255);
declare variable V$DISTRICT varchar(255);
declare variable V$TOWN varchar(255);
declare variable V$SETTLEMENT varchar(255);
declare variable V$STREET varchar(255);
declare variable V$HOUSE varchar(255);
declare variable V$LITER varchar(255);
declare variable V$CORP varchar(255);
declare variable V$FLAT varchar(255);
declare variable V$INDEX varchar(255);
declare variable V$BLOB_ID bigint;
declare variable V$DECLARANT_ID bigint;
declare variable V$DECLARANT_FT bigint;
declare variable V$OLD_EXPORT_DATE date;
declare variable V$BENEFIT_CHANGE timestamp;
declare variable V$BENEFIT_CODE varchar(10);
declare variable V$LEAVE_DATE date;
BEGIN

    -- Текущий статус запроса на льготу
    SELECT LV2085.TAG, V2085.DATE_MODIFY
    FROM VALL V2085
    JOIN LISTVALS LV2085 ON LV2085.LISTVAL_ID = V2085.LISTVAL_ID
    WHERE V2085.OBJ_ID = :I$PUPIL_ID AND V2085.PARAM_ID = 2085 AND V2085.IS_DEL = 0
    INTO :V$BENEFIT_CODE, :V$BENEFIT_CHANGE;

    -- Если льготы вообще никогда не было, либо льгота затерта больше полугода назад - ученик в выгрузку не попадает
    -- Если льготу не затерли, а сняли также более полугода назад - также не выгружаем
    IF((V$BENEFIT_CODE IS NULL OR V$BENEFIT_CODE = '') AND NOT EXISTS(
        SELECT FIRST 1 1
        FROM VALL V2085
        WHERE V2085.OBJ_ID = :I$PUPIL_ID AND V2085.PARAM_ID = 2085 AND V2085.DATE_MODIFY < DATEADD(-6 MONTH TO CURRENT_DATE)
    ))
    THEN EXIT;

    -- Если действующей льготы нет - выставляем код 0
    IF(V$BENEFIT_CODE = '' OR V$BENEFIT_CODE IS NULL) THEN V$BENEFIT_CODE = '0';

    -- Начинаем выгрузку
    TAG_NAME = 'FoodApplicationItem';
    VAL = NULL;
    SUSPEND;

    -- Данные по самому учащемуся
    TAG_NAME = 'FoodApplicationItem:person';
    VAL = NULL;
    SUSPEND;

    TAG_NAME = 'FoodApplicationItem:person:PID';
    VAL = I$PUPIL_ID;
    SUSPEND;

    TAG_NAME = 'FoodApplicationItem:person:FirstName';
    VAL = NULL;
    SELECT V.VAL
    FROM VALS V
    WHERE V.OBJ_ID = :I$PUPIL_ID AND V.PARAM_ID = 56 AND V.IS_DEL = 0
    INTO :VAL;
    SUSPEND;

    TAG_NAME = 'FoodApplicationItem:person:SecondName';
    VAL = NULL;
    SELECT V.VAL FROM VALS V
    WHERE V.OBJ_ID = :I$PUPIL_ID AND V.PARAM_ID = 57 AND V.IS_DEL = 0
    INTO :VAL;
    SUSPEND;

    TAG_NAME = 'FoodApplicationItem:person:LastName';
    VAL = NULL;
    SELECT V.VAL FROM VALS V
    WHERE V.OBJ_ID = :I$PUPIL_ID AND V.PARAM_ID = 55 AND V.IS_DEL = 0
    INTO :VAL;
    SUSPEND;

    TAG_NAME = 'FoodApplicationItem:person:BirthDate';
    VAL = NULL;
    SELECT V.VAL FROM VALD V
    WHERE V.OBJ_ID = :I$PUPIL_ID AND V.PARAM_ID = 89 AND V.IS_DEL = 0
    INTO :VAL;
    SUSPEND;

    TAG_NAME = 'FoodApplicationItem:person:SNILS';
    VAL = NULL;
    SELECT V.VAL FROM VALS V
    WHERE V.OBJ_ID = :I$PUPIL_ID AND V.PARAM_ID = 1409 AND V.IS_DEL = 0
    INTO :VAL;
    SUSPEND;

    -- Документы воспитанника
    FOR
        SELECT L79.OBJ_ID
        FROM LINKS L79
        JOIN VALL V2457 ON V2457.OBJ_ID = L79.OBJ_ID AND V2457.PARAM_ID = 2457 AND V2457.IS_DEL = 0 AND V2457.LISTVAL_ID = 2
        WHERE L79.PARENT_ID = :I$PUPIL_ID AND L79.OBJ_TYPE_ID = 79 AND L79.DATE_DEL IS NULL
        INTO :V$DOC_ID
    DO
    BEGIN
        TAG_NAME = 'FoodApplicationItem:person:Documents:PersonDoc';
        VAL = NULL;
        SUSPEND;

        TAG_NAME = 'FoodApplicationItem:person:Documents:PersonDoc:DocTypeCode';
        VAL = NULL;
        SELECT
            CASE
                WHEN V441.LISTVAL_ID = 1368 THEN 1
                WHEN V441.LISTVAL_ID = 1369 THEN 8
                WHEN V441.LISTVAL_ID = 1370 THEN 3
                WHEN V441.LISTVAL_ID = 1371 THEN 99
                WHEN V441.LISTVAL_ID = 1372 THEN 7
                WHEN V441.LISTVAL_ID = 1373 THEN 9
                WHEN V441.LISTVAL_ID = 1374 THEN 99
                WHEN V441.LISTVAL_ID = 3172 THEN 2
                WHEN V441.LISTVAL_ID = 11343 THEN 5
            END
        FROM VALL V441
        WHERE V441.OBJ_ID = :V$DOC_ID AND V441.PARAM_ID = 441 AND V441.IS_DEL = 0
        INTO :VAL;
        SUSPEND;

        
        TAG_NAME = 'FoodApplicationItem:person:Documents:PersonDoc:DocSeries';
        VAL = NULL;
        SELECT V.VAL FROM VALS V
        WHERE V.OBJ_ID = :V$DOC_ID AND V.PARAM_ID = 442 AND V.IS_DEL = 0
        INTO :VAL;
        SUSPEND;

        TAG_NAME = 'FoodApplicationItem:person:Documents:PersonDoc:DocNumber';
        VAL = NULL;
        SELECT V.VAL FROM VALS V
        WHERE V.OBJ_ID = :V$DOC_ID AND V.PARAM_ID = 559 AND V.IS_DEL = 0
        INTO :VAL;
        SUSPEND;

        TAG_NAME = 'FoodApplicationItem:person:Documents:PersonDoc:DocDate';
        VAL = NULL;
        SELECT V.VAL FROM VALD V
        WHERE V.OBJ_ID = :V$DOC_ID AND V.PARAM_ID = 560 AND V.IS_DEL = 0
        INTO :VAL;
        SUSPEND;
    END

    -- Данные по законному представителю
    TAG_NAME = 'FoodApplicationItem:declarant:PID';
    VAL = NULL;
    SELECT V.VAL FROM VALR V
    WHERE V.OBJ_ID = :I$PUPIL_ID AND V.PARAM_ID = 2842 AND V.IS_DEL = 0
    INTO :V$DECLARANT_ID;
    VAL = V$DECLARANT_ID;
    SUSPEND;

    TAG_NAME = 'FoodApplicationItem:declarant:FirstName';
    VAL = NULL;
    SELECT V.VAL FROM VALS V
    WHERE V.OBJ_ID = :V$DECLARANT_ID AND V.PARAM_ID = 129 AND V.IS_DEL = 0
    INTO :VAL;
    SUSPEND;

    TAG_NAME = 'FoodApplicationItem:declarant:SecondName';
    VAL = NULL;
    SELECT V.VAL FROM VALS V
    WHERE V.OBJ_ID = :V$DECLARANT_ID AND V.PARAM_ID = 130 AND V.IS_DEL = 0
    INTO :VAL;
    SUSPEND;

    TAG_NAME = 'FoodApplicationItem:declarant:LastName';
    VAL = NULL;
    SELECT V.VAL FROM VALS V
    WHERE V.OBJ_ID = :V$DECLARANT_ID AND V.PARAM_ID = 128 AND V.IS_DEL = 0
    INTO :VAL;
    SUSPEND;

    TAG_NAME = 'FoodApplicationItem:declarant:BirthDate';
    VAL = NULL;
    SELECT V.VAL FROM VALD V
    WHERE V.OBJ_ID = :V$DECLARANT_ID AND V.PARAM_ID = 143 AND V.IS_DEL = 0
    INTO :VAL;
    SUSPEND;

    TAG_NAME = 'FoodApplicationItem:declarant:FamilyTies';
    SELECT FIRST(1) L168.EXT_OBJ_ID
    FROM LINKS L168
    WHERE L168.EXT_OBJ_TYPE_ID = 168 AND L168.PARENT_ID = :I$PUPIL_ID AND L168.OBJ_ID = :V$DECLARANT_ID AND L168.DATE_DEL IS NULL
    INTO :V$DECLARANT_FT;
    VAL = NULL;
    SELECT V FROM VAL_GET(:V$DECLARANT_FT, 1573)
    INTO :VAL;
    SUSPEND;

    -- Документы родителя (законного представителя)
    FOR
        SELECT L79.OBJ_ID
        FROM LINKS L79
        JOIN VALL V2457 ON V2457.OBJ_ID = L79.OBJ_ID AND V2457.PARAM_ID = 2457 AND V2457.IS_DEL = 0 AND V2457.LISTVAL_ID = 2
        WHERE L79.PARENT_ID = :V$DECLARANT_ID AND L79.OBJ_TYPE_ID = 79 AND L79.DATE_DEL IS NULL
        INTO :V$DOC_ID
    DO
    BEGIN
        TAG_NAME = 'FoodApplicationItem:declarant:Documents:PersonDoc';
        VAL = NULL;
        SUSPEND;

        TAG_NAME = 'FoodApplicationItem:declarant:Documents:PersonDoc:DocTypeCode';
        VAL = NULL;
        SELECT
            CASE
                WHEN V441.LISTVAL_ID = 1368 THEN 1
                WHEN V441.LISTVAL_ID = 1369 THEN 8
                WHEN V441.LISTVAL_ID = 1370 THEN 3
                WHEN V441.LISTVAL_ID = 1371 THEN 99
                WHEN V441.LISTVAL_ID = 1372 THEN 7
                WHEN V441.LISTVAL_ID = 1373 THEN 9
                WHEN V441.LISTVAL_ID = 1374 THEN 99
                WHEN V441.LISTVAL_ID = 3172 THEN 2
            END
        FROM VALL V441
        WHERE V441.OBJ_ID = :V$DOC_ID AND V441.PARAM_ID = 441 AND V441.IS_DEL = 0
        INTO :VAL;
        SUSPEND;

        
        TAG_NAME = 'FoodApplicationItem:declarant:Documents:PersonDoc:DocSeries';
        VAL = NULL;
        SELECT V.VAL FROM VALS V
        WHERE V.OBJ_ID = :V$DOC_ID AND V.PARAM_ID = 442 AND V.IS_DEL = 0
        INTO :VAL;
        SUSPEND;

        TAG_NAME = 'FoodApplicationItem:declarant:Documents:PersonDoc:DocNumber';
        VAL = NULL;
        SELECT V.VAL FROM VALS V
        WHERE V.OBJ_ID = :V$DOC_ID AND V.PARAM_ID = 559 AND V.IS_DEL = 0
        INTO :VAL;
        SUSPEND;

        TAG_NAME = 'FoodApplicationItem:declarant:Documents:PersonDoc:DocDate';
        VAL = NULL;
        SELECT V.VAL FROM VALD V
        WHERE V.OBJ_ID = :V$DOC_ID AND V.PARAM_ID = 560 AND V.IS_DEL = 0
        INTO :VAL;
        SUSPEND;
    END

    SELECT ADR.REGION,ADR.DISTRICT, ADR.TOWN, ADR.SETTLEMENT, ADR.STREET, ADR.HOUSE, ADR.LITER, ADR.CORP, ADR.FLAT, ADR.POST_INDEX
    FROM ADR_GET(1561, :V$DECLARANT_ID) ADR
    INTO :V$REGION, :V$DISTRICT, :V$TOWN, :V$SETTLEMENT, :V$STREET, :V$HOUSE, :V$LITER, :V$CORP, :V$FLAT, :V$INDEX;

    TAG_NAME = 'FoodApplicationItem:declarant:address:Region';
    VAL = V$REGION;
    SUSPEND;

    TAG_NAME = 'FoodApplicationItem:declarant:address:District';
    VAL = V$DISTRICT;
    SUSPEND;

    TAG_NAME = 'FoodApplicationItem:declarant:address:Town';
    VAL = V$TOWN;
    SUSPEND;

    TAG_NAME = 'FoodApplicationItem:declarant:address:Settlement';
    VAL = V$SETTLEMENT;
    SUSPEND;

    TAG_NAME = 'FoodApplicationItem:declarant:address:Street';
    VAL = V$STREET;
    SUSPEND;

    TAG_NAME = 'FoodApplicationItem:declarant:address:Building';
    VAL = V$HOUSE;
    SUSPEND;

    TAG_NAME = 'FoodApplicationItem:declarant:address:Liter';
    VAL = V$LITER;
    SUSPEND;

    TAG_NAME = 'FoodApplicationItem:declarant:address:Block';
    VAL = V$CORP;
    SUSPEND;

    TAG_NAME = 'FoodApplicationItem:declarant:address:Appartment';
    VAL = V$FLAT;
    SUSPEND;

    TAG_NAME = 'FoodApplicationItem:declarant:address:PostIndex';
    VAL = V$INDEX;
    SUSPEND;

    -- Адрес воспитанника
    SELECT ADR.REGION,ADR.DISTRICT, ADR.TOWN, ADR.SETTLEMENT, ADR.STREET, ADR.HOUSE, ADR.LITER, ADR.CORP, ADR.FLAT, ADR.POST_INDEX
    FROM ADR_GET(111, :I$PUPIL_ID) ADR
    INTO :V$REGION, :V$DISTRICT, :V$TOWN, :V$SETTLEMENT, :V$STREET, :V$HOUSE, :V$LITER, :V$CORP, :V$FLAT, :V$INDEX;

    TAG_NAME = 'FoodApplicationItem:address:Region';
    VAL = V$REGION;
    SUSPEND;

    TAG_NAME = 'FoodApplicationItem:address:District';
    VAL = V$DISTRICT;
    SUSPEND;

    TAG_NAME = 'FoodApplicationItem:address:Town';
    VAL = V$TOWN;
    SUSPEND;

    TAG_NAME = 'FoodApplicationItem:address:Settlement';
    VAL = V$SETTLEMENT;
    SUSPEND;

    TAG_NAME = 'FoodApplicationItem:address:Street';
    VAL = V$STREET;
    SUSPEND;

    TAG_NAME = 'FoodApplicationItem:address:Building';
    VAL = V$HOUSE;
    SUSPEND;

    TAG_NAME = 'FoodApplicationItem:address:Liter';
    VAL = V$LITER;
    SUSPEND;

    TAG_NAME = 'FoodApplicationItem:address:Block';
    VAL = V$CORP;
    SUSPEND;

    TAG_NAME = 'FoodApplicationItem:address:Appartment';
    VAL = V$FLAT;
    SUSPEND;

    TAG_NAME = 'FoodApplicationItem:address:PostIndex';
    VAL = V$INDEX;
    SUSPEND;

    -- Дата зачисления в ОУ воспитанника
    TAG_NAME = 'FoodApplicationItem:EnrollmentDate';
    VAL = NULL;
    SELECT V FROM VAL_GET(:I$PUPIL_ID, 2099)
    INTO :VAL;
    SUSPEND;

    -- Дата выбытия из ОУ воспитанника
    TAG_NAME = 'FoodApplicationItem:DeductionDate';
    VAL = NULL;
    SELECT V FROM VAL_GET(:I$PUPIL_ID, 2100)
    INTO :V$LEAVE_DATE;
    VAL = :V$LEAVE_DATE;
    SUSPEND;

    -- Код льготы
    TAG_NAME = 'FoodApplicationItem:BenefitCode';
    VAL = V$BENEFIT_CODE;
    SUSPEND;

    -- Параллель воспитанника
    TAG_NAME = 'FoodApplicationItem:ClassNumeral';
    VAL = NULL;
    SELECT FIRST 1 V.V
    FROM OBJECT_PARENTS_GET(:I$PUPIL_ID, 8) OPG
    LEFT JOIN VAL_GET(OPG.OBJ_ID, 1393) V ON 1 = 1
    INTO :VAL;
    SUSPEND;

    -- Класс воспитанника
    TAG_NAME = 'FoodApplicationItem:ClassLiteral';
    VAL = NULL;
    SELECT FIRST 1 V54.VAL
    FROM LINKS L9
    JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.DATE_DEL IS NULL AND L10.OBJ_TYPE_ID = 10 AND L10.OBJ_ID = :I$PUPIL_ID
    LEFT JOIN VALS V54 ON V54.OBJ_ID = L9.OBJ_ID AND V54.IS_DEL = 0 AND V54.PARAM_ID = 54
    WHERE L9.DATE_DEL IS NULL AND L9.OBJ_TYPE_ID = 9 AND L9.PARENT_TYPE_ID = 8
    INTO :VAL;
    SUSPEND;

    -- Признак состояния школьника (без изменений, новый, выбыл, изменение категории);
    TAG_NAME = 'FoodApplicationItem:Status';
    VAL = 0; -- Без изменений

    --читаем дату предыдущей выгрузки
    SELECT D FROM VAL_GET(:I$PUPIL_ID, 2086)
    INTO :V$OLD_EXPORT_DATE;

    IF (V$OLD_EXPORT_DATE IS NULL) THEN VAL = 1; --новый
    ELSE IF (V$LEAVE_DATE IS NOT NULL) THEN VAL = 2; --выбыл
    ELSE IF (V$BENEFIT_CHANGE > V$OLD_EXPORT_DATE) THEN VAL = 3; --изменение категории
    ELSE IF(V$BENEFIT_CODE = '0') THEN VAL = 2; -- учеников, у которых снята льготы, отмечаем как выбывших
    SUSPEND;

    -- дата начала питания
    TAG_NAME = 'FoodApplicationItem:FoodBeginDate';
    VAL = NULL;
    SELECT V FROM VAL_GET(:I$PUPIL_ID, 2843)
    INTO :VAL;
    SUSPEND;

    -- дата окончания питания
    TAG_NAME = 'FoodApplicationItem:FoodEndDate';
    VAL = NULL;
    SELECT V FROM VAL_GET(:I$PUPIL_ID, 2844)
    INTO :VAL;
    SUSPEND;

    -- процент возмещения
    TAG_NAME = 'FoodApplicationItem:BenefitPercent';
    VAL = NULL;
    -- SELECT V FROM VAL_GET(:I$PUPIL_ID, 2845)
    SELECT COST FROM VAL_GET(:I$PUPIL_ID, 2845)
    INTO :VAL;
    SUSPEND;

    -- форма обучения
    TAG_NAME = 'FoodApplicationItem:EducationType';
    VAL = NULL;
    SELECT V FROM VAL_GET(:I$PUPIL_ID, 80)
    INTO :VAL;
    SUSPEND;

    -- примечание
    TAG_NAME = 'FoodApplicationItem:Comment';
    VAL = NULL;
    SELECT V FROM VAL_GET(:I$PUPIL_ID, 2846)
    INTO :VAL;
    SUSPEND;

    -- признак питания (деньги / еда)
    FOR
        SELECT CASE V.LISTVAL_ID WHEN 2 THEN 'true' WHEN 3 THEN 'false' END
        FROM VALL V
        WHERE V.OBJ_ID = :I$PUPIL_ID AND V.PARAM_ID = 2456 AND V.IS_DEL = 0
        INTO :VAL
    DO
    BEGIN
        TAG_NAME = 'FoodApplicationItem:isFooding';
        SUSPEND;
    END

    -- Запоминаем дату формирования выгрузки
    SELECT BLOB_ID FROM VAL_ADD(2086, :I$PUPIL_ID, CURRENT_DATE, :I$USER_ID, IIF(:VAL IS NULL, 1, 0)) INTO :V$BLOB_ID;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FOOD_BENEFIT_APP_EXPORT_SCHOOL (
    I$SCHOOL_ID BIGINT = null)
RETURNS (
    TAG_NAME VARCHAR(255),
    VAL VARCHAR(4000))
AS
declare variable V$YEAR integer;
declare variable V$PUPIL_ID bigint;
BEGIN

  -- С августа начинаем выдачу текущего года
  V$YEAR = EXTRACT(YEAR FROM CURRENT_DATE);
  IF(EXTRACT(MONTH FROM CURRENT_DATE) < 8) THEN V$YEAR = V$YEAR - 1;

  -- Сначала данные по ОУ
  IF (I$SCHOOL_ID IS NULL) THEN
  BEGIN
    SELECT OBJ_ID
    FROM LINKS
    WHERE PARENT_ID IS NULL AND OBJ_TYPE_ID = 2 AND DATE_DEL IS NULL
    INTO :I$SCHOOL_ID;
  END

  TAG_NAME = 'SchoolShortName';
  SELECT V.VAL FROM VALS V
  WHERE V.OBJ_ID = :I$SCHOOL_ID AND V.PARAM_ID = 2
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'SchoolPID';
  SELECT FIRST 1 GEN FROM GEN
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'SchoolOGRN';
  SELECT V.VAL FROM VALS V
  WHERE V.OBJ_ID = :I$SCHOOL_ID AND V.PARAM_ID = 9
  INTO :VAL;
  SUSPEND;

  -- Данные по учащимся - идем по полному списку учащихся, действующие и выбывшие в текущем учебном году
  TAG_NAME = 'Items';
  VAL = NULL;
  SUSPEND;

  FOR
      SELECT L10.OBJ_ID
      FROM LINKS L7
      JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 187) AND L9.DATE_DEL IS NULL
      JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      WHERE L7.PARENT_ID = :I$SCHOOL_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
      UNION
      SELECT L10.OBJ_ID
      FROM LINKS L78
      JOIN LINKS L82 ON L82.PARENT_ID = L78.OBJ_ID AND L82.OBJ_TYPE_ID = 82 AND L82.DATE_DEL IS NULL
      JOIN VALI V449 ON V449.OBJ_ID = L82.OBJ_ID AND V449.PARAM_ID = 449 AND V449.IS_DEL = 0 AND V449.VAL = :V$YEAR
      JOIN LINKS L10 ON L10.PARENT_ID = L82.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      WHERE L78.PARENT_ID = :I$SCHOOL_ID AND L78.OBJ_TYPE_ID = 78 AND L78.DATE_DEL IS NULL
      ORDER BY 1
      INTO :V$PUPIL_ID
  DO
  BEGIN

      -- Фильтрация учеником идет внутри SP
      FOR
          SELECT TAG_NAME, VAL
          FROM FOOD_BENEFIT_APP_EXPORT_PUPIL(:V$PUPIL_ID, 1)
          INTO :TAG_NAME, :VAL
      DO
      BEGIN

          TAG_NAME = 'Items:' || TAG_NAME;
          SUSPEND;

      END

  END

END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FOOD_BENEFIT_APP_EXPORT_VERIFY1 (
    I$PUPIL_ID BIGINT)
RETURNS (
    CLASS_NAME VARCHAR(5),
    FIO CHAR(300))
AS
declare variable V$BENEFIT_ID bigint;
BEGIN
    SELECT V.LISTVAL_ID FROM VALL V
    WHERE V.PARAM_ID = 2085
    AND V.OBJ_ID = :I$PUPIL_ID
    AND V.IS_DEL = 0
    INTO :V$BENEFIT_ID;

    IF (V$BENEFIT_ID IS NULL) THEN
    BEGIN
        SELECT FIRST 1 V.V || V54.VAL FROM LINKS L9

        JOIN LINKS L10
        ON L10.PARENT_ID = L9.OBJ_ID
        AND L10.DATE_DEL IS NULL
        AND L10.OBJ_TYPE_ID = 10
        AND L10.OBJ_ID = :I$PUPIL_ID
        
        LEFT JOIN VALS V54
        ON V54.OBJ_ID = L9.OBJ_ID
        AND V54.IS_DEL = 0
        AND V54.PARAM_ID = 54
        
        LEFT JOIN OBJECT_PARENTS_GET(:I$PUPIL_ID, 8) OPG ON 1=1
    
        LEFT JOIN VAL_GET(OPG.OBJ_ID, 1393) V
        ON 1=1
    
        WHERE L9.DATE_DEL IS NULL
        AND L9.OBJ_TYPE_ID = 9
        AND L9.PARENT_TYPE_ID = 8

        INTO CLASS_NAME;

        SELECT V55.VAL || ' ' || V1348.V FROM VALS V55

        LEFT JOIN VAL_GET(:I$PUPIL_ID, 1348) V1348 ON 1=1

        WHERE V55.PARAM_ID = 55
        AND V55.IS_DEL = 0
        AND V55.OBJ_ID = :I$PUPIL_ID
        INTO FIO;

        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FOOD_BENEFIT_APP_EXPORT_VERIFY2 (
    I$PUPIL_ID BIGINT)
RETURNS (
    CLASS_NAME VARCHAR(5),
    FIO CHAR(300))
AS
declare variable V$REGION varchar(255);
declare variable V$DISTRICT varchar(255);
declare variable V$TOWN varchar(255);
declare variable V$SETTLEMENT varchar(255);
declare variable V$STREET varchar(255);
declare variable V$HOUSE varchar(255);
declare variable V$LITER varchar(255);
declare variable V$CORP varchar(255);
declare variable V$FLAT varchar(255);
declare variable V$INDEX varchar(255);
BEGIN
    SELECT ADR.REGION,ADR.DISTRICT, ADR.TOWN, ADR.SETTLEMENT, ADR.STREET, ADR.HOUSE, ADR.LITER, ADR.CORP, ADR.FLAT, ADR.POST_INDEX
    FROM ADR_GET(111, :I$PUPIL_ID) ADR
    INTO :V$REGION, :V$DISTRICT, :V$TOWN, :V$SETTLEMENT, :V$STREET, :V$HOUSE, :V$LITER, :V$CORP, :V$FLAT, :V$INDEX;

    IF
        ((((V$REGION LIKE '%обл%') AND (V$TOWN IS NOT NULL)) OR ((V$REGION LIKE '%обл%') AND (V$SETTLEMENT IS NOT NULL)) OR (V$REGION LIKE 'Санкт-Петербург%')) AND
        (V$STREET IS NOT NULL) AND
        (V$HOUSE IS NOT NULL) AND
        (V$FLAT IS NOT NULL))
    THEN
    BEGIN
                
    END
    ELSE
    BEGIN
        SELECT FIRST 1 V.V || V54.VAL FROM LINKS L9

        JOIN LINKS L10
        ON L10.PARENT_ID = L9.OBJ_ID
        AND L10.DATE_DEL IS NULL
        AND L10.OBJ_TYPE_ID = 10
        AND L10.OBJ_ID = :I$PUPIL_ID
        
        LEFT JOIN VALS V54
        ON V54.OBJ_ID = L9.OBJ_ID
        AND V54.IS_DEL = 0
        AND V54.PARAM_ID = 54
        
        LEFT JOIN OBJECT_PARENTS_GET(:I$PUPIL_ID, 8) OPG ON 1=1
    
        LEFT JOIN VAL_GET(OPG.OBJ_ID, 1393) V
        ON 1=1
    
        WHERE L9.DATE_DEL IS NULL
        AND L9.OBJ_TYPE_ID = 9
        AND L9.PARENT_TYPE_ID = 8

        INTO CLASS_NAME;

        SELECT V55.VAL || ' ' || V1348.V FROM VALS V55

        LEFT JOIN VAL_GET(:I$PUPIL_ID, 1348) V1348 ON 1=1

        WHERE V55.PARAM_ID = 55
        AND V55.IS_DEL = 0
        AND V55.OBJ_ID = :I$PUPIL_ID
        INTO FIO;

        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FOOD_BENEFIT_APP_PUPIL_SET (
    I$OBJ_ID BIGINT,
    I$DATE_ANSWER DATE,
    I$STATUS INTEGER,
    I$DESCRIPTION VARCHAR(300),
    I$BENEFIT INTEGER,
    I$DATE_UPD DATE,
    I$DATE_CHG DATE,
    I$DATE_EXP DATE,
    I$USER_ID BIGINT)
RETURNS (
    RESULT INTEGER,
    WARNING VARCHAR(500))
AS
declare variable V$BLOB_ID bigint;
declare variable V$PUPIL_ID bigint;
declare variable V$PARENT_TYPE_ID integer;
declare variable V$BENEFIT_CODE integer;
declare variable V$STATUS_CODE integer;
declare variable V$CLASS_NAME varchar(10);
declare variable V$FIO varchar(300);
BEGIN
    SELECT L10.OBJ_ID, L10.PARENT_TYPE_ID FROM LINKS L10
    WHERE  L10.OBJ_TYPE_ID = 10
    AND L10.DATE_DEL IS NULL  
    AND L10.PARENT_TYPE_ID IN (9,187,82)
    AND L10.OBJ_ID = :I$OBJ_ID
    INTO :V$PUPIL_ID, :V$PARENT_TYPE_ID;

    IF (V$PUPIL_ID IS NULL) THEN
    BEGIN
        RESULT = -1;
        SUSPEND;
    END
    ELSE
    BEGIN
        V$BENEFIT_CODE = (
            SELECT LISTVAL_ID
            FROM LISTVALS
            WHERE LIST_ID = 263
            AND IS_DEL = 0
            AND COST = :I$BENEFIT
        );
/*        V$BENEFIT_CODE = CASE
            WHEN I$BENEFIT = 0 THEN 5446
            WHEN I$BENEFIT = 1 THEN 5447
            WHEN I$BENEFIT = 2 THEN 5448
            WHEN I$BENEFIT = 3 THEN 5449
            WHEN I$BENEFIT = 4 THEN 5450
            WHEN I$BENEFIT = 5 THEN 5451
            WHEN I$BENEFIT = 6 THEN 5452
            WHEN I$BENEFIT = 7 THEN 5453
            WHEN I$BENEFIT = 8 THEN 5454
            WHEN I$BENEFIT = 9 THEN 5455
            WHEN I$BENEFIT = 10 THEN 5456
            WHEN I$BENEFIT = 11 THEN 5457
            WHEN I$BENEFIT = 12 THEN 5458
            WHEN I$BENEFIT = 13 THEN 5459
        END;*/

        V$STATUS_CODE = CASE
            WHEN I$STATUS = 1 THEN 5460
            WHEN I$STATUS = 2 THEN 5461
            WHEN I$STATUS = 3 THEN 5462
            WHEN I$STATUS = 4 THEN 5463
            WHEN I$STATUS = 5 THEN 5464
        END;

        IF (V$PARENT_TYPE_ID <> 82) THEN
        BEGIN
            SELECT V.BLOB_ID FROM VAL_ADD(2094, :V$PUPIL_ID,:I$DATE_ANSWER,:I$USER_ID) V
            INTO V$BLOB_ID;
        
            SELECT V.BLOB_ID FROM VAL_ADD(2095, :V$PUPIL_ID,:V$STATUS_CODE,:I$USER_ID) V
            INTO V$BLOB_ID;
        
            SELECT V.BLOB_ID FROM VAL_ADD(2096, :V$PUPIL_ID,:I$DESCRIPTION,:I$USER_ID) V
            INTO V$BLOB_ID;
        
            SELECT V.BLOB_ID FROM VAL_ADD(2097, :V$PUPIL_ID,:V$BENEFIT_CODE,:I$USER_ID) V
            INTO V$BLOB_ID;
        
            SELECT V.BLOB_ID FROM VAL_ADD(2847, :V$PUPIL_ID,:I$DATE_UPD,:I$USER_ID) V
            INTO V$BLOB_ID;
        
            SELECT V.BLOB_ID FROM VAL_ADD(2848, :V$PUPIL_ID,:I$DATE_CHG,:I$USER_ID) V
            INTO V$BLOB_ID;
        
            SELECT V.BLOB_ID FROM VAL_ADD(2098, :V$PUPIL_ID,:I$DATE_EXP,:I$USER_ID) V
            INTO V$BLOB_ID;

            IF ((I$STATUS = 2) OR (I$STATUS = 5)) THEN
            BEGIN
                SELECT V.BLOB_ID FROM VAL_ADD(2088, :V$PUPIL_ID,:I$DATE_ANSWER,:I$USER_ID) V
                INTO V$BLOB_ID;
            
                SELECT V.BLOB_ID FROM VAL_ADD(2089, :V$PUPIL_ID,:V$STATUS_CODE,:I$USER_ID) V
                INTO V$BLOB_ID;
            
                SELECT V.BLOB_ID FROM VAL_ADD(2090, :V$PUPIL_ID,:I$DESCRIPTION,:I$USER_ID) V
                INTO V$BLOB_ID;
            
                SELECT V.BLOB_ID FROM VAL_ADD(2091, :V$PUPIL_ID,:V$BENEFIT_CODE,:I$USER_ID) V
                INTO V$BLOB_ID;
            
                SELECT V.BLOB_ID FROM VAL_ADD(2092, :V$PUPIL_ID,:I$DATE_EXP,:I$USER_ID) V
                INTO V$BLOB_ID;
            END
        END

        RESULT = CASE
            WHEN I$STATUS = 3 THEN 1
            WHEN I$STATUS = 4 THEN 2
            WHEN I$STATUS = 1 THEN 3
            ELSE 0
        END;
        
        IF (RESULT = 1) THEN
        BEGIN
            V$CLASS_NAME = '';
            SELECT FIRST 1 V.V || V54.VAL FROM LINKS L9
    
            JOIN LINKS L10
            ON L10.PARENT_ID = L9.OBJ_ID
            AND L10.DATE_DEL IS NULL
            AND L10.OBJ_TYPE_ID = 10
            AND L10.OBJ_ID = :V$PUPIL_ID
            
            LEFT JOIN VALS V54
            ON V54.OBJ_ID = L9.OBJ_ID
            AND V54.IS_DEL = 0
            AND V54.PARAM_ID = 54
            
            LEFT JOIN OBJECT_PARENTS_GET(:V$PUPIL_ID, 8) OPG ON 1=1
        
            LEFT JOIN VAL_GET(OPG.OBJ_ID, 1393, 0, :I$USER_ID) V
            ON 1=1
        
            WHERE L9.DATE_DEL IS NULL
            AND L9.OBJ_TYPE_ID = 9
            AND L9.PARENT_TYPE_ID = 8
    
            INTO V$CLASS_NAME;
    
            V$FIO = '';
            SELECT V55.VAL || ' ' || V1348.V FROM VALS V55
    
            LEFT JOIN VAL_GET(:V$PUPIL_ID, 1348, 0, :I$USER_ID) V1348 ON 1=1
    
            WHERE V55.PARAM_ID = 55
            AND V55.IS_DEL = 0
            AND V55.OBJ_ID = :V$PUPIL_ID
            INTO V$FIO;

            IF (I$DESCRIPTION IS NULL) THEN
            BEGIN
                WARNING = 'Не подтверждена льгота ' || V$CLASS_NAME || ' обучающийся ' || V$FIO;
            END
            ELSE
            BEGIN
                WARNING = 'Не подтверждена льгота ' || V$CLASS_NAME || ' обучающийся ' || V$FIO || ' Описание: ' || I$DESCRIPTION;
            END
        END
        ELSE IF (RESULT = 2) THEN
        BEGIN
            V$CLASS_NAME = '';
            SELECT FIRST 1 V.V || V54.VAL FROM LINKS L9
    
            JOIN LINKS L10
            ON L10.PARENT_ID = L9.OBJ_ID
            AND L10.DATE_DEL IS NULL
            AND L10.OBJ_TYPE_ID = 10
            AND L10.OBJ_ID = :V$PUPIL_ID
            
            LEFT JOIN VALS V54
            ON V54.OBJ_ID = L9.OBJ_ID
            AND V54.IS_DEL = 0
            AND V54.PARAM_ID = 54
            
            LEFT JOIN OBJECT_PARENTS_GET(:V$PUPIL_ID, 8) OPG ON 1=1
        
            LEFT JOIN VAL_GET(OPG.OBJ_ID, 1393, 0, :I$USER_ID) V
            ON 1=1
        
            WHERE L9.DATE_DEL IS NULL
            AND L9.OBJ_TYPE_ID = 9
            AND L9.PARENT_TYPE_ID = 8
    
            INTO V$CLASS_NAME;
    
            V$FIO = '';
            SELECT V55.VAL || ' ' || V1348.V FROM VALS V55
    
            LEFT JOIN VAL_GET(:V$PUPIL_ID, 1348, 0, :I$USER_ID) V1348 ON 1=1
    
            WHERE V55.PARAM_ID = 55
            AND V55.IS_DEL = 0
            AND V55.OBJ_ID = :V$PUPIL_ID
            INTO V$FIO;

            IF (I$DESCRIPTION IS NULL) THEN
            BEGIN
                WARNING = 'Льгота подтверждена по другому основанию ' || V$CLASS_NAME || ' обучающийся ' || V$FIO;
            END
            ELSE
            BEGIN
                WARNING = 'Льгота подтверждена по другому основанию ' || V$CLASS_NAME || ' обучающийся ' || V$FIO || ' Описание: ' || I$DESCRIPTION;
            END
        END
        ELSE IF (RESULT = 3) THEN
        BEGIN
            V$CLASS_NAME = '';
            SELECT FIRST 1 V.V || V54.VAL FROM LINKS L9
    
            JOIN LINKS L10
            ON L10.PARENT_ID = L9.OBJ_ID
            AND L10.DATE_DEL IS NULL
            AND L10.OBJ_TYPE_ID = 10
            AND L10.OBJ_ID = :V$PUPIL_ID
            
            LEFT JOIN VALS V54
            ON V54.OBJ_ID = L9.OBJ_ID
            AND V54.IS_DEL = 0
            AND V54.PARAM_ID = 54
            
            LEFT JOIN OBJECT_PARENTS_GET(:V$PUPIL_ID, 8) OPG ON 1=1
        
            LEFT JOIN VAL_GET(OPG.OBJ_ID, 1393, 0, :I$USER_ID) V
            ON 1=1
        
            WHERE L9.DATE_DEL IS NULL
            AND L9.OBJ_TYPE_ID = 9
            AND L9.PARENT_TYPE_ID = 8
    
            INTO V$CLASS_NAME;
    
            V$FIO = '';
            SELECT V55.VAL || ' ' || V1348.V FROM VALS V55
    
            LEFT JOIN VAL_GET(:V$PUPIL_ID, 1348, 0, :I$USER_ID) V1348 ON 1=1
    
            WHERE V55.PARAM_ID = 55
            AND V55.IS_DEL = 0
            AND V55.OBJ_ID = :V$PUPIL_ID
            INTO V$FIO;

            IF (I$DESCRIPTION IS NULL) THEN
            BEGIN
                WARNING = 'Льгота не проверена ' || V$CLASS_NAME || ' обучающийся ' || V$FIO;
            END
            ELSE
            BEGIN
                WARNING = 'Льгота не проверена ' || V$CLASS_NAME || ' обучающийся ' || V$FIO || ' Описание: ' || I$DESCRIPTION;
            END
        END

        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FOOD_PUPIL_PARENTS_LIST (
    I$OBJ_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    PARENT_ID CHAR(1),
    OBJ_CAPTION VARCHAR(4000))
AS
BEGIN
  FOR
    SELECT L20.OBJ_ID, NULL AS PARENT_ID, OC20.CAPTION AS OBJ_CAPTION
    FROM LINKS L20 LEFT JOIN OBJECT_CAPTION_GET(L20.OBJ_ID) OC20 ON 1=1
    WHERE L20.PARENT_ID = :I$OBJ_ID AND L20.OBJ_TYPE_ID = 20 AND L20.DATE_DEL IS NULL
    INTO :OBJ_ID,
         :PARENT_ID,
         :OBJ_CAPTION
  DO
  BEGIN
    SUSPEND;
  END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FOOD_SERVICER_GET RETURNS (
    SRVC_NAME VARCHAR(1000),
    SRVC_INN VARCHAR(100))
AS
DECLARE VARIABLE S VARCHAR(4000);
DECLARE VARIABLE SS VARCHAR(4000);
DECLARE VARIABLE P INTEGER;
DECLARE VARIABLE P2 INTEGER;
DECLARE VARIABLE V VARCHAR(1000);
DECLARE VARIABLE C VARCHAR(2);
DECLARE VARIABLE STR_CR VARCHAR(2);
DECLARE VARIABLE STR_LF VARCHAR(2);
DECLARE VARIABLE STR_SEP VARCHAR(2);
begin
  -- Бубен с переводом строки - firebird 4 портит строку при любых действиях и добавляет LF там, где есть только CR
  -- сравнение с ASCII_CHAR не работает никогда вообще
  STR_CR = ASCII_CHAR(13);
  STR_LF = ASCII_CHAR(10);
  STR_SEP = '|';

  -- Выбираем позже всех добавленную действующую персону, у которой есть регид и памятка
  SELECT FIRST 1 VAL
  FROM (
    -- Классы
    SELECT L10.DATE_INS, V2921.VAL
    FROM LINKS L2
    JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 187) AND L9.DATE_DEL IS NULL
    JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    JOIN VALS V2912 ON V2912.OBJ_ID = L10.OBJ_ID AND V2912.PARAM_ID = 2912 AND V2912.IS_DEL = 0
    JOIN VALS V2921 ON V2921.OBJ_ID = L10.OBJ_ID AND V2921.PARAM_ID = 2921 AND V2921.IS_DEL = 0 AND V2921.VAL CONTAINING 'servicer_name'
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    UNION
    -- Предварительный прием
    SELECT L10.DATE_INS, V2921.VAL
    FROM LINKS L2
    JOIN LINKS L77 ON L77.PARENT_ID = L2.OBJ_ID AND L77.OBJ_TYPE_ID = 77 AND L77.DATE_DEL IS NULL
    JOIN LINKS L290 ON L290.PARENT_ID = L77.OBJ_ID AND L290.OBJ_TYPE_ID = 290 AND L290.DATE_DEL IS NULL
    JOIN LINKS L10 ON L10.PARENT_ID = L290.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    JOIN VALS V2912 ON V2912.OBJ_ID = L10.OBJ_ID AND V2912.PARAM_ID = 2912 AND V2912.IS_DEL = 0
    JOIN VALS V2921 ON V2921.OBJ_ID = L10.OBJ_ID AND V2921.PARAM_ID = 2921 AND V2921.IS_DEL = 0 AND V2921.VAL CONTAINING 'servicer_name'
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    -- Сотрудники
    UNION
    SELECT L14.DATE_INS, V2922.VAL
    FROM LINKS L2
    JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
    JOIN VALS V2915 ON V2915.OBJ_ID = L14.OBJ_ID AND V2915.PARAM_ID = 2915 AND V2915.IS_DEL = 0
    JOIN VALS V2922 ON V2922.OBJ_ID = L14.OBJ_ID AND V2922.PARAM_ID = 2922 AND V2922.IS_DEL = 0 AND V2922.VAL CONTAINING 'servicer_name'
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  ) SEL
  ORDER BY DATE_INS DESC
  INTO :S;

  S = REPLACE(S, STR_CR, STR_SEP);
  SS = '';
  V = '';
  P = 1;
  WHILE(P > 0 AND P <= CHAR_LENGTH(S) + 1) DO
  BEGIN
    IF(P > CHAR_LENGTH(S)) THEN C = STR_SEP; ELSE C = SUBSTRING(S FROM P FOR 1);
    P = P + 1;
    IF(C = STR_SEP) THEN -- STR_CR
    BEGIN
      -- Начало нового параметра
      P2 = POSITION('=' IN V);
      IF (P2 > 2 AND SUBSTRING(V FROM 1 FOR 14) = 'servicer_name=') THEN
      BEGIN
        SS = SUBSTRING(V FROM 15);
      END
      ELSE
      BEGIN
        IF(SS <> '') THEN SS = SS || STR_CR;
        SS = SS || V;
      END
      V = '';
    END
    ELSE
    BEGIN
      V = V || C;
    END
  END

  SRVC_NAME = NULL;
  SRVC_INN = NULL;
  IF (SS <> '') THEN
  BEGIN
    -- Отделим ИНН от названия поставщика
    V = SUBSTRING(SS FROM 1 FOR 10);
    IF (V SIMILAR TO '%[[:DIGIT:]]{1}%') THEN
    BEGIN
      SRVC_INN = V;
      SS = SUBSTRING(SS FROM 11);
    END
    SRVC_NAME = TRIM(SS);
  END
  SUSPEND;
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FOOD_UPDATE_SERVICER (
    I$SVCNAME VARCHAR(1000))
RETURNS (
    OBJ_ID BIGINT,
    TYPE_ID BIGINT)
AS
declare variable S varchar(4000);
declare variable SS varchar(4000);
declare variable P integer;
declare variable P2 integer;
declare variable PARAM_ID bigint;
declare variable V varchar(1000);
declare variable C varchar(2);
declare variable STR_CR varchar(2);
declare variable STR_LF varchar(2);
declare variable STR_SEP varchar(2);
begin

  -- Символ равенства все сломает, убираем его
  I$SVCNAME = REPLACE(I$SVCNAME, '=', ' ');

  -- Бубен с переводом строки - firebird 4 портит строку при любых действиях и добавляет LF там, где есть только CR
  -- сравнение с ASCII_CHAR не работает никогда вообще
  STR_CR = ASCII_CHAR(13);
  STR_LF = ASCII_CHAR(10);
  STR_SEP = '|';

  -- Идем только по действующим ученикам, родителям и сотрудникам, у которых есть регид и памятка
  FOR
    -- Классы
    SELECT L10.OBJ_ID, L10.OBJ_TYPE_ID, V2921.VAL, V2921.PARAM_ID
    FROM LINKS L2
    JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 187) AND L9.DATE_DEL IS NULL
    JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    JOIN VALS V2912 ON V2912.OBJ_ID = L10.OBJ_ID AND V2912.PARAM_ID = 2912 AND V2912.IS_DEL = 0
    JOIN VALS V2921 ON V2921.OBJ_ID = L10.OBJ_ID AND V2921.PARAM_ID = 2921 AND V2921.IS_DEL = 0
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    UNION
    -- Предварительный прием
    SELECT L10.OBJ_ID, L10.OBJ_TYPE_ID, V2921.VAL, V2921.PARAM_ID
    FROM LINKS L2
    JOIN LINKS L77 ON L77.PARENT_ID = L2.OBJ_ID AND L77.OBJ_TYPE_ID = 77 AND L77.DATE_DEL IS NULL
    JOIN LINKS L290 ON L290.PARENT_ID = L77.OBJ_ID AND L290.OBJ_TYPE_ID = 290 AND L290.DATE_DEL IS NULL
    JOIN LINKS L10 ON L10.PARENT_ID = L290.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    JOIN VALS V2912 ON V2912.OBJ_ID = L10.OBJ_ID AND V2912.PARAM_ID = 2912 AND V2912.IS_DEL = 0
    JOIN VALS V2921 ON V2921.OBJ_ID = L10.OBJ_ID AND V2921.PARAM_ID = 2921 AND V2921.IS_DEL = 0
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    -- Сотрудники
    UNION
    SELECT L14.OBJ_ID, L14.OBJ_TYPE_ID, V2922.VAL, V2922.PARAM_ID
    FROM LINKS L2
    JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
    JOIN VALS V2915 ON V2915.OBJ_ID = L14.OBJ_ID AND V2915.PARAM_ID = 2915 AND V2915.IS_DEL = 0
    JOIN VALS V2922 ON V2922.OBJ_ID = L14.OBJ_ID AND V2922.PARAM_ID = 2922 AND V2922.IS_DEL = 0
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    -- Родители - а зачем ?
    ORDER BY 1
    INTO :OBJ_ID, :TYPE_ID, :S, :PARAM_ID
  DO
  BEGIN
    S = REPLACE(S, STR_CR, STR_SEP);
    SS = '';
    V = '';
    P = 1;
    WHILE(P > 0 AND P <= CHAR_LENGTH(S) + 1) DO
    BEGIN
      IF(P > CHAR_LENGTH(S)) THEN C = STR_SEP; ELSE C = SUBSTRING(S FROM P FOR 1);
      P = P + 1;
      IF(C = STR_SEP) THEN -- STR_CR
      BEGIN
        -- Начало нового параметра
        P2 = POSITION('=' IN V);
        IF(P2 <= 2) THEN
        BEGIN
          -- Обход липовых LF
        END
        ELSE IF(SUBSTRING(V FROM 1 FOR 14) = 'servicer_name=') THEN
        BEGIN
          V = SUBSTRING(V FROM 15);
          IF(V = I$SVCNAME) THEN
          BEGIN
            -- Обновление не требуется
            SS = NULL;
            P = -1;
          END
          ELSE
          BEGIN
            IF(SS <> '') THEN SS = SS || STR_CR;
            SS = SS || 'servicer_name=' || I$SVCNAME;
          END
        END
        ELSE
        BEGIN
          IF(SS <> '') THEN SS = SS || STR_CR;
          SS = SS || V;
        END
        V = '';
      END
      ELSE IF(C = STR_LF) THEN
      BEGIN
        -- Игнорируем, и после изменения сепаратора сюда вообще не попадем
      END
      ELSE
      BEGIN
        V = V || C;
      END
    END

    -- Если изменилось - сохраняем
    IF(SS IS NOT NULL) THEN
    BEGIN
      SELECT 1 FROM VAL_ADD(:PARAM_ID, :OBJ_ID, :SS) INTO :P;
      SUSPEND;
    END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FPFIX (
    I$OLD_CODE VARCHAR(40),
    I$NEW_CODE VARCHAR(40),
    I$DATE VARCHAR(40))
AS
DECLARE VARIABLE V$ID BIGINT;
DECLARE VARIABLE V$DATE DATE;
begin

  I$OLD_CODE = I$OLD_CODE || ' (2)';

  SELECT C.BOOK_ID
  FROM LIB_FPU_CODES C
  WHERE C.BOOKCODE = :I$OLD_CODE AND C.DATE_ADD <> '06.11.2025'
  INTO :V$ID;

  IF(V$ID IS NULL) THEN EXCEPTION DATA_ERROR 'Book not found ' || I$OLD_CODE;

  I$NEW_CODE = TRIM(I$NEW_CODE) || ' (2)';
  I$NEW_CODE = REPLACE(I$NEW_CODE, '. ', ' ');

  I$DATE = UPPER(I$DATE);
  I$DATE = REPLACE(I$DATE, 'ДО', '');
  I$DATE = REPLACE(I$DATE, 'ГОДА', '');
  I$DATE = REPLACE(I$DATE, ' ', '');

  I$DATE = REPLACE(I$DATE, 'ЯНВАРЯ', '01');
  I$DATE = REPLACE(I$DATE, 'ФЕВРАЛЯ', '02');
  I$DATE = REPLACE(I$DATE, 'МАРТА', '03');
  I$DATE = REPLACE(I$DATE, 'АПРЕЛЯ', '04');
  I$DATE = REPLACE(I$DATE, 'МАЯ', '05');
  I$DATE = REPLACE(I$DATE, 'ИЮНЯ', '06');
  I$DATE = REPLACE(I$DATE, 'ИЮЛЯ', '07');
  I$DATE = REPLACE(I$DATE, 'АВГУСТА', '08');
  I$DATE = REPLACE(I$DATE, 'СЕНТЯБРЯ', '09');
  I$DATE = REPLACE(I$DATE, 'ОКТЯБРЯ', '10');
  I$DATE = REPLACE(I$DATE, 'НОЯБРЯ', '11');
  I$DATE = REPLACE(I$DATE, 'ДЕКАБРЯ', '12');
  IF(CHAR_LENGTH(I$DATE) <> 8) THEN EXCEPTION DATA_ERROR 'Bad date ' || I$OLD_CODE;
  V$DATE = SUBSTRING(I$DATE FROM 1 FOR 2) || '.' || SUBSTRING(I$DATE FROM 3 FOR 2) || '.' || SUBSTRING(I$DATE FROM 5);

  IF(NOT EXISTS(
    SELECT FIRST 1 1
    FROM LIB_FPU_CODES
    WHERE BOOK_ID = :V$ID AND DATE_ADD = '06.11.2024'
  ))
  THEN
  INSERT INTO LIB_FPU_CODES
  (DATE_ADD, BOOK_ID, BOOKCODE, ORDER_INFO)
  VALUES ('06.11.2024', :V$ID, :I$NEW_CODE, '№769 от 05.11.2024');

  UPDATE LIB_FPU
  SET VALID_BY = :V$DATE
  WHERE OBJ_ID = :V$ID AND VALID_BY <> :V$DATE;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FPU_CODE_GET (
    I$BOOKID BIGINT,
    I$YEAR SMALLINT)
RETURNS (
    BOOKCODE VARCHAR(40),
    ORDER_INFO VARCHAR(100))
AS
begin

  -- Учитывая что ФПУ стали меняться по 3 раза в год, тут уже не год, а дату надо брать

  SELECT FIRST 1 C.BOOKCODE, C.ORDER_INFO
  FROM LIB_FPU_CODES C
  WHERE C.DATE_DEL IS NULL AND C.BOOK_ID = :I$BOOKID AND C.DATE_ADD <= '31.12.' || :I$YEAR
  ORDER BY C.DATE_ADD DESC
  INTO :BOOKCODE, :ORDER_INFO;

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FULLLOAD_RQ_LIST (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
declare variable V$TYPE_ID bigint;
declare variable V$DIST_ID bigint;
declare variable V$DIST_CODE bigint;
declare variable V$M bigint;
declare variable V$OBJ_ID bigint;
declare variable V$STATUS smallint;
declare variable V$DT1 timestamp;
declare variable V$DT2 timestamp;
declare variable V$RC bigint;
declare variable S varchar(1000);
begin

  -- Функционал перенесен в pg
  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FULLLOAD_RQ_SET (
    I$LIC_CODE BIGINT,
    I$STATUS SMALLINT,
    I$USER_ID VARCHAR(40))
AS
declare variable V$DIST_CODE bigint;
declare variable V$STATUS smallint;
declare variable V$M bigint;
declare variable S varchar(400);
begin

  -- Перенесено на pg

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FULLOAD_REQUEST_CHECK (
    I$AREA_ID BIGINT NOT NULL,
    I$LIC_CODE INTEGER NOT NULL,
    I$ORG_NAME VARCHAR(400) NOT NULL)
RETURNS (
    STATUS SMALLINT)
AS
declare variable F smallint;
begin

  -- Перенесено в pg
  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FUTURE_GUP_CHECK (
    I$OBJ_ID BIGINT)
AS
declare variable V$LT varchar(2);
declare variable V$NAME varchar(1000);
declare variable V$PLAN_ID bigint;
declare variable V$PLAN_NAME varchar(1000);
begin

  V$LT = (SELECT STATUS FROM OU_LICENCE_TYPE);

  -- Есть ли ученики в классе ?
  IF(EXISTS(
    SELECT FIRST 1 1
    FROM LINKS L10
    WHERE L10.PARENT_ID = :I$OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
  ))
  THEN
    EXCEPTION DATA_ERROR 'Нельзя удалять учебный коллектив, в котором числятся обучающиеся';

  -- Какое у нас будущее название класса ?
  SELECT FIRST 1 GRADE_NAME_NEW
  FROM YCHANGE_REVIEW_GRADES(:V$LT, :I$OBJ_ID)
  INTO :V$NAME;

  IF(V$NAME IS NULL) THEN EXIT;

  -- Тут был косяк: название проверялось без префикса будущий
  V$NAME = 'будущий ' || V$NAME;

  SELECT FIRST 1 L400.OBJ_ID, C.CAPTION
  FROM LINKS L2
  JOIN LINKS L69 ON L69.PARENT_ID = L2.OBJ_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL
  JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
  JOIN LINKS L400 ON L400.PARENT_ID = L57.OBJ_ID AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL
  JOIN LINKS L54 ON L54.PARENT_ID = L400.OBJ_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
  JOIN LINKS L256 ON L256.PARENT_ID = L54.OBJ_ID AND L256.OBJ_TYPE_ID = 256 AND L256.DATE_DEL IS NULL
  JOIN VALS V2162 ON V2162.OBJ_ID = L256.OBJ_ID AND V2162.PARAM_ID = 2162 AND V2162.IS_DEL = 0 AND V2162.SVAL = :V$NAME
  LEFT JOIN OBJECT_CAPTION_GET(L400.OBJ_ID) C ON 1 = 1
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$PLAN_ID, :V$PLAN_NAME;

  IF(V$PLAN_ID IS NOT NULL) THEN EXCEPTION DATA_ERROR 'Был уже внесен будущий ГУП для этого коллектива, сначала нужно его удалить вручную';

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FUTURE_GUP_LIST RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$YEAR INTEGER;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$STAGE_ID BIGINT;
DECLARE VARIABLE V$STAGE BIGINT;
DECLARE VARIABLE V$GRADE_ID BIGINT;
DECLARE VARIABLE S VARCHAR(1000);
DECLARE VARIABLE C INTEGER;
begin

  -- Какой у нас сейчас учебный год ?
  SELECT FIRST 1 LV.COST
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$YEAR;

  IF(V$YEAR IS NULL) THEN V$YEAR = EXTRACT(YEAR FROM CURRENT_DATE);

  -- Список классов на будущий год, только общее образование
  TAG_NAME = 'grades::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT GRADE_ID, GRADE_NAME_NEW, STAGE_ID_NEW, STAGE_COST_NEW
    FROM YCHANGE_REVIEW_GRADES
    JOIN LISTVALS LV ON LV.LISTVAL_ID = STAGE_ID_NEW AND LV.PARENT_ID IN (2141, 12941)
    WHERE STAGE_ID_NEW IS NOT NULL
    ORDER BY 4, 2
    INTO :V$GRADE_ID, :S, :V$STAGE, :C
  DO
  BEGIN
    TAG_NAME = 'grades:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'grades:r:id';
    VAL = V$GRADE_ID;
    SUSPEND;
    TAG_NAME = 'grades:r:name';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'grades:r:stage';
    VAL = V$STAGE;
    SUSPEND;
    TAG_NAME = 'grades:r:stc';
    VAL = C;
    SUSPEND;
  END

  -- Список действующих УП на будущий год
  TAG_NAME = 'plan::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L400.OBJ_ID, C.CAPTION
    FROM LINKS L2
    JOIN LINKS L69 ON L69.PARENT_ID = L2.OBJ_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL
    JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
    JOIN VALI V3115 ON V3115.OBJ_ID = L57.OBJ_ID AND V3115.PARAM_ID = 3115 AND V3115.IS_DEL = 0 AND V3115.VAL = :V$YEAR + 1
    -- только школьные уровни
    JOIN VALL V1594 ON V1594.OBJ_ID = L57.OBJ_ID AND V1594.PARAM_ID = 1594 AND V1594.IS_DEL = 0 AND V1594.LISTVAL_ID IN (5339, 5341, 5343)
    JOIN LINKS L400 ON L400.PARENT_ID = L57.OBJ_ID AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL
    -- не внеурочка
    JOIN VALL V3022 ON V3022.OBJ_ID = L400.OBJ_ID AND V3022.PARAM_ID = 3022 AND V3022.IS_DEL = 0 AND V3022.LISTVAL_ID = 3
    -- только групповые, действующие
    JOIN VALL V3016 ON V3016.OBJ_ID = L400.OBJ_ID AND V3016.PARAM_ID = 3016 AND V3016.IS_DEL = 0 AND V3016.LISTVAL_ID = 5465
    JOIN VALL V3013 ON V3013.OBJ_ID = L400.OBJ_ID AND V3013.PARAM_ID = 3013 AND V3013.IS_DEL = 0 AND V3013.LISTVAL_ID = 11715
    LEFT JOIN OBJECT_CAPTION_GET(L400.OBJ_ID) C ON 1 = 1
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    ORDER BY V1594.LISTVAL_ID, 2
    INTO :V$OBJ_ID, :S
  DO
  BEGIN
    TAG_NAME = 'plan:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'plan:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'plan:r:name';
    VAL = S;
    SUSPEND;

    TAG_NAME = 'plan:r:stages::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT L54.OBJ_ID, V381.LISTVAL_ID, C.VAL, LV.COST
      FROM LINKS L54
      JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
      JOIN LISTVALS LV ON LV.LISTVAL_ID = V381.LISTVAL_ID
      LEFT JOIN LISTVAL_TEXT(V381.LISTVAL_ID) C ON 1 = 1
      WHERE L54.PARENT_ID = :V$OBJ_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
      ORDER BY 2
      INTO :V$STAGE_ID, :V$STAGE, :S, :C
    DO
    BEGIN
      TAG_NAME = 'plan:r:stages:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'plan:r:stages:r:id';
      VAL = V$STAGE;
      SUSPEND;
      TAG_NAME = 'plan:r:stages:r:name';
      VAL = S;
      SUSPEND;
      TAG_NAME = 'plan:r:stages:r:stc';
      VAL = C;
      SUSPEND;

      -- Список групп в этом этапе
      TAG_NAME = 'plan:r:stages:r:grades::json&colon;array';
      VAL = 1;
      SUSPEND;
      FOR
        SELECT L256.OBJ_ID, C.CAPTION
        FROM LINKS L256
        LEFT JOIN OBJECT_CAPTION_GET(L256.OBJ_ID) C ON 1 = 1
        WHERE L256.PARENT_ID = :V$STAGE_ID AND L256.OBJ_TYPE_ID = 256 AND L256.DATE_DEL IS NULL
          AND C.CAPTION LIKE 'будущий %'
        ORDER BY 2
        INTO :V$GRADE_ID, :S
      DO
      BEGIN
        TAG_NAME = 'plan:r:stages:r:grades:r';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'plan:r:stages:r:grades:r:id';
        VAL = V$GRADE_ID;
        SUSPEND;
        TAG_NAME = 'plan:r:stages:r:grades:r:name';
        VAL = S;
        SUSPEND;
      END
    END
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE FUTURE_GUP_SET (
    I$GRADE_ID BIGINT,
    I$GRADE_NAME VARCHAR(100),
    I$PLANS VARCHAR(1000))
RETURNS (
    OBJ_ID BIGINT)
AS
DECLARE VARIABLE S VARCHAR(1000);
DECLARE VARIABLE V VARCHAR(1000);
DECLARE VARIABLE VV VARCHAR(100);
DECLARE VARIABLE V$PLAN_ID BIGINT;
DECLARE VARIABLE V$STAGE_ID BIGINT;
DECLARE VARIABLE V$STAGE_NEED BIGINT;
DECLARE VARIABLE V$GUP_ID BIGINT;
DECLARE VARIABLE V$PARENT_ID BIGINT;
DECLARE VARIABLE P INTEGER;
DECLARE VARIABLE N INTEGER;
DECLARE VARIABLE M INTEGER;
begin

  -- IF(NOT EXISTS()) THEN EXCEPTION DATA_ERROR 'Один из учебных коллективов был удален или изменен';
  -- I$PLANS - строка пар id:stage, где id - id учебного плана, stage - stage_id этапа в плане

  S = 'будущий ' || I$GRADE_NAME;

  -- Сначала удаляем группу из тех УП, которые пропали в выборе
  FOR
    SELECT L400.OBJ_ID, L256.PARENT_ID, L256.OBJ_ID
    FROM LINKS L2
    JOIN LINKS L69 ON L69.PARENT_ID = L2.OBJ_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL
    JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
    JOIN LINKS L400 ON L400.PARENT_ID = L57.OBJ_ID AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL
    JOIN LINKS L54 ON L54.PARENT_ID = L400.OBJ_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
    JOIN LINKS L256 ON L256.PARENT_ID = L54.OBJ_ID AND L256.OBJ_TYPE_ID = 256 AND L256.DATE_DEL IS NULL
    JOIN VALS V2162 ON V2162.OBJ_ID = L256.OBJ_ID AND V2162.PARAM_ID = 2162 AND V2162.IS_DEL = 0 AND V2162.SVAL = :S
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    ORDER BY 2
    INTO :V$PLAN_ID, :V$PARENT_ID, :V$GUP_ID
  DO
  BEGIN
    IF(POSITION(V$PLAN_ID || ':' IN I$PLANS) <= 0) THEN
    BEGIN
      -- Если тут уже есть ученики - труба
      IF(EXISTS(
        SELECT FIRST 1 1
        FROM LINKS L10
        WHERE L10.PARENT_ID = :V$GUP_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      ))
      THEN
        EXCEPTION DATA_ERROR 'В ГУП ' || S || ' уже есть ученики, нельзя изменять';

      -- Если есть подчиненные группы с журналами ?
      IF(EXISTS(
        SELECT FIRST 1 1
        FROM LINKS L179
        WHERE L179.OBJ_TYPE_ID = 179 AND L179.EXT_OBJ_ID = :V$GUP_ID AND L179.DATE_DEL IS NULL
      ))
      THEN
        EXCEPTION DATA_ERROR 'В ГУП ' || S || ' есть подчиненные предметные группы/журналы';

      -- Удаляем
      UPDATE LINKS
      SET DATE_DEL = CURRENT_TIMESTAMP
      WHERE OBJ_ID = :V$GUP_ID AND PARENT_ID = :V$PARENT_ID AND DATE_DEL IS NULL;
    END
  END

  -- Вторым этапом добавляем или обновляем
  V = I$PLANS;
  WHILE(CHAR_LENGTH(V) > 0) DO
  BEGIN
    P = POSITION(',' IN V);
    IF(P <= 0) THEN P = CHAR_LENGTH(V) + 1;
    VV = SUBSTRING(V FROM 1 FOR P - 1);
    V = SUBSTRING(V FROM P + 1);

    P = POSITION(':' IN VV);
    IF(P <= 0) THEN EXCEPTION DATA_ERROR 'Неверный формат списка УП';

    V$PLAN_ID = SUBSTRING(VV FROM 1 FOR P - 1);
    V$STAGE_ID = SUBSTRING(VV FROM P + 1);

    -- Проверяем что УП существует
    IF(NOT EXISTS(
      SELECT FIRST 1 1
      FROM LINKS LP57
      JOIN LINKS LP69 ON LP69.OBJ_ID = LP57.PARENT_ID AND LP69.PARENT_TYPE_ID = 69 AND LP69.DATE_DEL IS NULL
      WHERE LP57.OBJ_ID = :V$PLAN_ID AND LP57.OBJ_TYPE_ID = 400 AND LP57.PARENT_TYPE_ID = 57 AND LP57.DATE_DEL IS NULL
    ))
    THEN
      EXCEPTION DATA_ERROR 'Учебный план не найден';

    V$STAGE_NEED = NULL;
    SELECT FIRST 1 L54.OBJ_ID
    FROM LINKS L54
    JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0 AND V381.LISTVAL_ID = :V$STAGE_ID
    WHERE L54.PARENT_ID = :V$PLAN_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
    INTO :V$STAGE_NEED;

    IF(V$STAGE_NEED IS NULL) THEN EXCEPTION DATA_ERROR 'Нужного этапа обучения в УП не найдено';

    -- Есть ли в УП ГУП с нужным названием, заодно смотрим в каком этапе ?
    N = 0;
    FOR
      SELECT L54.OBJ_ID, L256.OBJ_ID
      FROM LINKS L54
      JOIN LINKS L256 ON L256.PARENT_ID = L54.OBJ_ID AND L256.OBJ_TYPE_ID = 256 AND L256.DATE_DEL IS NULL
      JOIN VALS V2162 ON V2162.OBJ_ID = L256.OBJ_ID AND V2162.PARAM_ID = 2162 AND V2162.IS_DEL = 0 AND V2162.SVAL = :S
      WHERE L54.PARENT_ID = :V$PLAN_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
      ORDER BY 2
      INTO :V$PARENT_ID, :V$GUP_ID
    DO
    BEGIN
      N = N + 1;
      IF(N > 1) THEN EXCEPTION DATA_ERROR 'В УП найдено более одной ГУП: ' || S || ', необходимо вручную удалить лишние';

      IF(V$PARENT_ID <> V$STAGE_NEED) THEN
      BEGIN
        -- Если она не в том этапе - переносим в новый раздел
        -- Если тут уже есть ученики - труба
        IF(EXISTS(
          SELECT FIRST 1 1
          FROM LINKS L10
          WHERE L10.PARENT_ID = :V$GUP_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        ))
        THEN
          EXCEPTION DATA_ERROR 'В ГУП ' || S || ' уже есть ученики, нельзя изменять';

        -- Если есть подчиненные группы с журналами ?
        IF(EXISTS(
          SELECT FIRST 1 1
          FROM LINKS L179
          WHERE L179.OBJ_TYPE_ID = 179 AND L179.EXT_OBJ_ID = :V$GUP_ID AND L179.DATE_DEL IS NULL
        ))
        THEN
          EXCEPTION DATA_ERROR 'В ГУП ' || S || ' есть подчиненные предметные группы/журналы';

        UPDATE LINKS
        SET PARENT_ID = :V$STAGE_NEED
        WHERE OBJ_ID = :V$GUP_ID AND PARENT_ID = :V$PARENT_ID AND DATE_DEL IS NULL;

        OBJ_ID = V$GUP_ID;
        SUSPEND;
      END
    END
    -- Если вообще нет - создаем с нуля
    IF(N = 0) THEN
    BEGIN
      SELECT OBJ_ID FROM OBJECT_ADD(:V$STAGE_NEED, 256) INTO :OBJ_ID;
      SELECT 1 FROM VAL_ADD(2162, :OBJ_ID, :S) INTO :N;

      -- Задаем маску в нужном бите
      SELECT LV.COST
      FROM LISTVALS LV
      WHERE LV.LISTVAL_ID = :V$STAGE_ID
      INTO :M;

      SELECT 1 FROM VAL_ADD(3062, :OBJ_ID, BIN_SHL(1, :M)) INTO :N;
      SUSPEND;
    END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GENERATE_PTP_NAME (
    I$PTP_ID BIGINT)
RETURNS (
    PTP_NAME VARCHAR(4000))
AS
declare variable V$PTP_NAME varchar(4000);
declare variable P integer;
declare variable N integer;
declare variable V$FLAG smallint;
declare variable V$NUM integer;
BEGIN
  SELECT V FROM VAL_GET(:I$PTP_ID, 472)
  INTO :V$PTP_NAME;

  IF (COALESCE(V$PTP_NAME, '') = '') THEN V$PTP_NAME = 'Новый ПТП';

  P = POSITION('#',REVERSE(:V$PTP_NAME),1);
  IF (P > 0) then
  BEGIN
    N = CAST(SUBSTRING(V$PTP_NAME FROM (CHAR_LENGTH(V$PTP_NAME) - P + 2)) AS VARCHAR(10));
    PTP_NAME = SUBSTRING(V$PTP_NAME FROM 1 FOR (CHAR_LENGTH(V$PTP_NAME) - P));
    WHEN ANY DO PTP_NAME = V$PTP_NAME;
  END
  ELSE
    PTP_NAME = V$PTP_NAME;

  V$FLAG = 0;
  V$NUM = 1;
  WHILE (V$FLAG = 0) DO
  BEGIN
      -- Проверяем уникальность названия в мировых масштабах
      N = 0;
      SELECT FIRST 1 1
      FROM LINKS L2
      JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
      JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
      JOIN LINKS L87 ON L87.PARENT_ID = L8.OBJ_ID AND L87.OBJ_TYPE_ID = 87 AND L87.DATE_DEL IS NULL
      JOIN VALS V472 ON V472.OBJ_ID = L87.OBJ_ID AND V472.PARAM_ID = 472 AND V472.IS_DEL = 0 AND V472.VAL = (:PTP_NAME || '#' || CAST(:V$NUM AS VARCHAR(10)))
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      INTO :N;

      IF(N <> 0) THEN
        V$NUM = V$NUM + 1;
      ELSE
        V$FLAG = 1;
    END
    PTP_NAME = PTP_NAME || '#' || CAST(:V$NUM AS VARCHAR(10));
    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GET_DAYS360_COUNT (
    BEGIN_DATE DATE,
    END_DATE DATE)
RETURNS (
    DAYS360_COUNT INTEGER)
AS
DECLARE VARIABLE BEGIN_YEAR INTEGER;
DECLARE VARIABLE BEGIN_MONTH INTEGER;
DECLARE VARIABLE BEGIN_DAY INTEGER;
DECLARE VARIABLE END_YEAR INTEGER;
DECLARE VARIABLE END_MONTH INTEGER;
DECLARE VARIABLE END_DAY INTEGER;
DECLARE VARIABLE IS_END_DAY_LATER SMALLINT;
DECLARE VARIABLE IS_END_MONTH_DAY_LATER SMALLINT;
DECLARE VARIABLE RES_YEARS INTEGER;
DECLARE VARIABLE RES_MONTHS INTEGER;
DECLARE VARIABLE RES_DAYS INTEGER;
BEGIN
    IF (END_DATE IS NULL) THEN
    BEGIN
        END_DATE = CURRENT_DATE;
    END

    IF (BEGIN_DATE IS NULL) THEN
    BEGIN
        DAYS360_COUNT = 0;
        SUSPEND;
        EXIT;
    END

    IF (END_DATE < BEGIN_DATE) THEN
    BEGIN
        DAYS360_COUNT = 0;
        SUSPEND;
        EXIT;
    END

    BEGIN_YEAR = EXTRACT(YEAR FROM BEGIN_DATE);
    BEGIN_MONTH = EXTRACT(MONTH FROM BEGIN_DATE);
    BEGIN_DAY = EXTRACT(DAY FROM BEGIN_DATE);

    END_YEAR = EXTRACT(YEAR FROM END_DATE);
    END_MONTH = EXTRACT(MONTH FROM END_DATE);
    END_DAY = EXTRACT(DAY FROM END_DATE);

    IF (END_DAY = 31) THEN
    BEGIN
        IF (BEGIN_DAY < 30) THEN
        BEGIN
            END_DATE = END_DATE + 1;
            END_YEAR = EXTRACT (YEAR FROM END_DATE);
            END_MONTH = EXTRACT (MONTH FROM END_DATE);
            END_DAY  = EXTRACT (DAY FROM END_DATE);
        END
        ELSE
        BEGIN
            END_DAY = 30;
        END
    END

    IF (BEGIN_DAY > 30) THEN
    BEGIN
        BEGIN_DAY = 30;
    END

    IF (END_DAY >= BEGIN_DAY) THEN
    BEGIN
        IS_END_DAY_LATER = 1;
    END
    ELSE
    BEGIN
        IS_END_DAY_LATER = 0;
    END

    IF ((END_MONTH > BEGIN_MONTH) OR
       ((END_MONTH = BEGIN_MONTH) AND (IS_END_DAY_LATER = 1))) THEN
    BEGIN
        IS_END_MONTH_DAY_LATER = 1;
    END
    ELSE
    BEGIN
        IS_END_MONTH_DAY_LATER = 0;
    END

    IF (IS_END_MONTH_DAY_LATER = 1) THEN
    BEGIN
        RES_YEARS = END_YEAR - BEGIN_YEAR;
        RES_MONTHS = 0;
    END
    ELSE
    BEGIN
        RES_YEARS = END_YEAR - BEGIN_YEAR - 1;
        RES_MONTHS = 12;
    END

    IF (IS_END_DAY_LATER = 1) THEN
    BEGIN
        RES_MONTHS = RES_MONTHS + END_MONTH - BEGIN_MONTH;
        RES_DAYS = 0;
    END
    ELSE
    BEGIN
        RES_MONTHS = RES_MONTHS + END_MONTH - BEGIN_MONTH - 1;
        RES_DAYS = 30;
    END

    RES_DAYS = RES_DAYS + END_DAY - BEGIN_DAY;
    DAYS360_COUNT = RES_YEARS * 360 + RES_MONTHS * 30 + RES_DAYS + 1; -- NIP + 1 -- NIP + 1;

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GET_LAST_SCHOLAR_MOVE_ID (
    I$SCHOLAR_ID BIGINT,
    I$DATE_MAX DATE,
    I$MOVE_TYPE SMALLINT = 0,
    I$GROUP_ID BIGINT = null)
RETURNS (
    LINK_ID BIGINT,
    OBJ_ID BIGINT,
    EVENT_DATE DATE,
    EVENT_TYPE BIGINT)
AS
BEGIN

    -- I$GROUP_ID используется только в ГПД для проверки движения по конкретному коллективу
    -- 0 = учебные коллективы
    -- 1 = ГПД
    -- 2 = все виды ГПД и ДО

    SELECT FIRST 1 OBJ_ID, DT, MOVE_TYPE
    FROM (
      SELECT M.OBJ_ID, M.DATE_IN DT, M.REASON_IN MOVE_TYPE
      FROM PERSON_MOVEMENTS M
      LEFT JOIN VALL V369 ON V369.OBJ_ID = M.GROUP_ID AND V369.PARAM_ID = 369 AND V369.IS_DEL = 0
      JOIN OBJECTS O ON O.OBJ_ID = M.GROUP_ID
      WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :I$SCHOLAR_ID AND M.DATE_IN <= :I$DATE_MAX
          AND (:I$GROUP_ID IS NULL OR M.GROUP_ID = :I$GROUP_ID)
          AND (
              (:I$MOVE_TYPE = 0 AND O.TYPE_ID IN (9, 125, 187, 243)) OR
              (:I$MOVE_TYPE = 1 AND O.TYPE_ID IN (46) AND V369.LISTVAL_ID = 1246) OR
              (:I$MOVE_TYPE = 2 AND O.TYPE_ID IN (46))
          )
      UNION ALL
      SELECT M.OBJ_ID, M.DATE_OUT DT, M.REASON_OUT MOVE_TYPE
      FROM PERSON_MOVEMENTS M
      LEFT JOIN VALL V369 ON V369.OBJ_ID = M.GROUP_ID AND V369.PARAM_ID = 369 AND V369.IS_DEL = 0
      JOIN OBJECTS O ON O.OBJ_ID = M.GROUP_ID
      WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :I$SCHOLAR_ID AND M.DATE_OUT <= :I$DATE_MAX
          AND (:I$GROUP_ID IS NULL OR M.GROUP_ID = :I$GROUP_ID)
          AND (
              (:I$MOVE_TYPE = 0 AND O.TYPE_ID IN (9, 125, 187, 243)) OR
              (:I$MOVE_TYPE = 1 AND O.TYPE_ID IN (46) AND V369.LISTVAL_ID = 1246) OR
              (:I$MOVE_TYPE = 2 AND O.TYPE_ID IN (46))
          )
    )
    ORDER BY 2 DESC, 1 DESC
    INTO :OBJ_ID, :EVENT_DATE, :EVENT_TYPE;

    LINK_ID = OBJ_ID;

    SUSPEND;

END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GET_PIPIL_BY_SNILS (
    I$SNILS VARCHAR(50),
    I$F VARCHAR(50),
    I$I VARCHAR(50),
    I$O VARCHAR(50),
    I$DOB DATE,
    I$DOCTYPE INTEGER,
    I$SERIE VARCHAR(20),
    I$NUMBER VARCHAR(20),
    I$USER_ID BIGINT = 1)
RETURNS (
    STATUS INTEGER,
    LASTNAME VARCHAR(50),
    FIRSTNAME VARCHAR(50),
    SECONDNAME VARCHAR(50),
    GENDER INTEGER,
    BIRTHDATE DATE,
    DOCTYPE INTEGER,
    DOCSERIA VARCHAR(20),
    DOCNUMBER VARCHAR(20),
    NAMEEDUINSTITUTION VARCHAR(2000),
    ENROLLMENTDATE DATE,
    DEDUCTIONSDATE DATE,
    CURRICULUM VARCHAR(50),
    DISTRICT VARCHAR(50),
    SHORTNAMEEDUINSTITUTION VARCHAR(50),
    NUMBEREDUINSTITUTION VARCHAR(10),
    PHONEMASTER VARCHAR(50),
    PHONERECEPTION VARCHAR(50),
    RETIREDIN VARCHAR(4000),
    DROPOUT SMALLINT)
AS
declare variable SCHOOL_ID bigint;
declare variable PUPIL_ID bigint;
declare variable CLASS_ID bigint;
declare variable STR varchar(250);
declare variable LANG_CODE varchar(2);
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :LANG_CODE;

    SELECT COUNT(*)
    FROM SNILS_INDEX
    INTO :SCHOOL_ID;

    IF (SCHOOL_ID = 0) THEN
    BEGIN
        EXECUTE PROCEDURE CREATE_SNILS_INDEX;
    END

    STATUS = 0;

    IF (I$SNILS IS NOT NULL) THEN
    BEGIN
        FOR
            SELECT I.PUPIL_ID,I.DROPOUT,I.FIRSTNAME,I.SECONDNAME,I.LASTNAME,I.DOB
            FROM SNILS_INDEX I
            WHERE UPPER(I.SNILS) = UPPER(:I$SNILS)
            INTO :PUPIL_ID,:DROPOUT,:FIRSTNAME,:SECONDNAME,:LASTNAME,:BIRTHDATE
        DO
        BEGIN
            IF (DROPOUT != 0) THEN
            BEGIN
                STATUS = 2;
            END
            ELSE
            BEGIN
                STATUS = 1;
            END
            IF ( ((:I$F IS NOT NULL) AND (UPPER(:LASTNAME) NOT LIKE UPPER(:I$F))) OR
                 ((:I$I IS NOT NULL) AND (UPPER(:FIRSTNAME) NOT LIKE UPPER(:I$I))) OR
                 ((:I$O IS NOT NULL) AND (UPPER(:SECONDNAME) NOT LIKE UPPER(:I$O))) OR
                 ((:I$DOB IS NOT NULL) AND (BIRTHDATE <> I$DOB))
               )
            THEN
            BEGIN
                STATUS = STATUS + 2;
            END
    
            SELECT V
            FROM VAL_GET(:PUPIL_ID,55,0,:I$USER_ID)
            INTO :LASTNAME;
            SELECT V
            FROM VAL_GET(:PUPIL_ID,56,0,:I$USER_ID)
            INTO :FIRSTNAME;
            SELECT V
            FROM VAL_GET(:PUPIL_ID,57,0,:I$USER_ID)
            INTO :SECONDNAME;
            SELECT I
            FROM VAL_GET(:PUPIL_ID,88,0,:I$USER_ID)
            INTO :GENDER;
            SELECT D
            FROM VAL_GET(:PUPIL_ID,89,0,:I$USER_ID)
            INTO :BIRTHDATE;
        
            SELECT FIRST 1 LV.LISTVAL_ID, LS.VAL, LN.VAL
            FROM LINKS L79
            JOIN VALL LV ON LV.OBJ_ID = L79.OBJ_ID AND LV.PARAM_ID = 441 AND LV.IS_DEL = 0
            LEFT JOIN VALS LS ON LS.OBJ_ID = L79.OBJ_ID AND LS.PARAM_ID = 442 AND LS.IS_DEL = 0
            LEFT JOIN VALS LN ON LN.OBJ_ID = L79.OBJ_ID AND LN.PARAM_ID = 559 AND LN.IS_DEL = 0
            WHERE L79.PARENT_ID = :PUPIL_ID AND L79.DATE_DEL IS NULL AND L79.OBJ_TYPE_ID = 79
            INTO :DOCTYPE,:DOCSERIA,:DOCNUMBER;
        
            SELECT FIRST 1 P9.PARENT_ID
            FROM LINKS P9
            WHERE P9.PARENT_TYPE_ID = 9 AND P9.OBJ_ID = :PUPIL_ID AND P9.DATE_DEL IS NULL
            INTO :CLASS_ID;
        
            IF (CLASS_ID IS NOT NULL) THEN
            BEGIN
              SELECT CAPTION
              FROM OBJECT_CAPTION_GET(:CLASS_ID,NULL,NULL,:I$USER_ID)
              INTO :CURRICULUM;
        
              SELECT FIRST 1 P2.PARENT_ID
              FROM LINKS P8
              JOIN LINKS P7 ON P7.OBJ_ID = P8.PARENT_ID AND P7.PARENT_TYPE_ID = 7 AND P7.DATE_DEL IS NULL
              JOIN LINKS P2 ON P2.OBJ_ID = P7.PARENT_ID AND P2.PARENT_TYPE_ID = 2 AND P2.DATE_DEL IS NULL
              WHERE P8.PARENT_TYPE_ID = 8 AND P8.OBJ_ID = :CLASS_ID AND P8.DATE_DEL IS NULL
              INTO :SCHOOL_ID;
            END
            ELSE
            BEGIN
              CURRICULUM = NULL;
            END
        
            SELECT V
            FROM VAL_GET(:SCHOOL_ID,5,0,:I$USER_ID)
            INTO :NAMEEDUINSTITUTION;
            SELECT V
            FROM VAL_GET(:SCHOOL_ID,2,0,:I$USER_ID)
            INTO :SHORTNAMEEDUINSTITUTION;
            SELECT V
            FROM VAL_GET(:SCHOOL_ID,17,0,:I$USER_ID)
            INTO :NUMBEREDUINSTITUTION;
            SELECT V
            FROM VAL_GET(:SCHOOL_ID,28,0,:I$USER_ID)
            INTO :PHONEMASTER;
            SELECT V
            FROM VAL_GET(:SCHOOL_ID,29,0,:I$USER_ID)
            INTO :PHONERECEPTION;

            RETIREDIN = '';
            STR = '';
            SELECT R.VAL
            FROM VALL V
            JOIN LISTVALS LV
            ON LV.LISTVAL_ID = V.LISTVAL_ID
            LEFT JOIN RES_GET(LV.RES_ID,  :LANG_CODE) R ON 1=1
            WHERE V.OBJ_ID = :PUPIL_ID
            AND V.PARAM_ID = 105
            INTO :STR;
            if ((STR != '') AND (STR IS NOT NULL)) then
            BEGIN
                RETIREDIN = STR;
            END
            STR = '';
            SELECT R.VAL
            FROM VALL V
            JOIN LISTVALS LV ON LV.LISTVAL_ID = V.LISTVAL_ID
            LEFT JOIN RES_GET(LV.RES_ID,  :LANG_CODE) R ON 1=1
            WHERE V.OBJ_ID = :PUPIL_ID AND V.PARAM_ID = 107
            INTO :STR;
            if ((STR != '') AND (STR IS NOT NULL)) then
            BEGIN
                IF (RETIREDIN = '') THEN
                BEGIN
                    RETIREDIN = STR;
                END
                ELSE
                BEGIN
                    RETIREDIN = RETIREDIN || '; ' || STR;
                END
            END
            STR = '';
            SELECT R.VAL
            FROM VALL V
            JOIN LISTVALS LV
            ON LV.LISTVAL_ID = V.LISTVAL_ID
            LEFT JOIN RES_GET(LV.RES_ID,  :LANG_CODE) R ON 1=1
            WHERE V.OBJ_ID = :PUPIL_ID
            AND V.PARAM_ID = 188
            INTO :STR;
            if ((STR != '') AND (STR IS NOT NULL)) then
            BEGIN
                IF (RETIREDIN = '') THEN
                BEGIN
                    RETIREDIN = STR;
                END
                ELSE
                BEGIN
                    RETIREDIN = RETIREDIN || '; ' || STR;
                END
            END
            STR = '';
            SELECT R.VAL
            FROM VALL V
            JOIN LISTVALS LV
            ON LV.LISTVAL_ID = V.LISTVAL_ID
            LEFT JOIN RES_GET(LV.RES_ID,  :LANG_CODE) R ON 1=1
            WHERE V.OBJ_ID = :PUPIL_ID
            AND V.PARAM_ID = 1346
            INTO :STR;
            if ((STR != '') AND (STR IS NOT NULL)) then
            BEGIN
                IF (RETIREDIN = '') THEN
                BEGIN
                    RETIREDIN = STR;
                END
                ELSE
                BEGIN
                    RETIREDIN = RETIREDIN || '; ' || STR;
                END
            END
            STR = '';
            SELECT V.VAL
            FROM VALS V
            WHERE V.OBJ_ID = :PUPIL_ID
            AND V.PARAM_ID = 161
            INTO :STR;
            if ((STR != '') AND (STR IS NOT NULL)) then
            BEGIN
                IF (RETIREDIN = '') THEN
                BEGIN
                    RETIREDIN = STR;
                END
                ELSE
                BEGIN
                    RETIREDIN = RETIREDIN || '; ' || STR;
                END
            END

            DISTRICT = NULL;
            SELECT FIRST 1 L111.PARENT_ID
            FROM LINKS L111
            JOIN VALL L ON L.PARAM_ID = 665 AND L.OBJ_ID = L111.PARENT_ID AND L.IS_DEL = 0
            WHERE L111.OBJ_ID = :SCHOOL_ID AND L111.DATE_DEL IS NULL AND L111.PARENT_TYPE_ID = 111
            INTO :DISTRICT;

            ENROLLMENTDATE = NULL;
            SELECT MIN(M.DATE_IN)
            FROM PERSON_MOVEMENTS M
            JOIN OBJECTS O ON O.OBJ_ID = M.GROUP_ID AND O.TYPE_ID = 9
            JOIN LISTVALS LV ON LV.LISTVAL_ID = M.REASON_IN AND LV."FILTER" LIKE 'ACCEPTED%'
            WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :PUPIL_ID
            INTO :ENROLLMENTDATE;

            DEDUCTIONSDATE = NULL;
            SELECT MAX(M.DATE_OUT)
            FROM PERSON_MOVEMENTS M
            JOIN OBJECTS O ON O.OBJ_ID = M.GROUP_ID AND O.TYPE_ID = 9
            JOIN LISTVALS LV ON LV.LISTVAL_ID = M.REASON_OUT AND LV."FILTER" LIKE 'LEAVED%'
            WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :PUPIL_ID AND M.DATE_OUT IS NOT NULL
            INTO :DEDUCTIONSDATE;
    
            SUSPEND;
        END
    END

    IF ((STATUS = 0) AND
        (I$F IS NOT NULL) AND (I$I IS NOT NULL) AND (I$DOCTYPE IS NOT NULL) AND
        (I$SERIE IS NOT NULL) AND (I$NUMBER IS NOT NULL)) THEN
    BEGIN
        FOR
            SELECT I.PUPIL_ID,I.DROPOUT,D.DOCTYPE,D.DOCSERIE,D.DOCNUMBER
            FROM SNILS_INDEX I
            LEFT JOIN DOC_INDEX D
            ON D.PUPIL_ID = I.PUPIL_ID
            WHERE ((UPPER(I.FIRSTNAME) LIKE UPPER(:I$I))
            AND ((UPPER(I.SECONDNAME) LIKE UPPER(:I$O)) OR (:I$O IS NULL))
            AND ((I.DOB = :I$DOB) OR (:I$DOB IS NULL))
            AND (UPPER(I.LASTNAME) LIKE UPPER(:I$F)))
            INTO :PUPIL_ID,:DROPOUT,:DOCTYPE,:DOCSERIA,:DOCNUMBER
        DO
        BEGIN
            IF ((DOCTYPE = I$DOCTYPE) AND
                (UPPER(DOCSERIA) LIKE UPPER(I$SERIE)) AND
                (UPPER(DOCNUMBER) LIKE UPPER(I$NUMBER))) THEN
            BEGIN
              STATUS = 7;
            END
            ELSE
            BEGIN
              STATUS = 8;
            END
    
            SELECT V
            FROM VAL_GET(:PUPIL_ID,55,0,:I$USER_ID)
            INTO :LASTNAME;
            SELECT V
            FROM VAL_GET(:PUPIL_ID,56,0,:I$USER_ID)
            INTO :FIRSTNAME;
            SELECT V
            FROM VAL_GET(:PUPIL_ID,57,0,:I$USER_ID)
            INTO :SECONDNAME;
            SELECT I
            FROM VAL_GET(:PUPIL_ID,88,0,:I$USER_ID)
            INTO :GENDER;
            SELECT D
            FROM VAL_GET(:PUPIL_ID,89,0,:I$USER_ID)
            INTO :BIRTHDATE;
        
            SELECT FIRST 1 LV.LISTVAL_ID, LS.VAL, LN.VAL
            FROM LINKS L79
            JOIN VALL LV ON LV.OBJ_ID = L79.OBJ_ID AND LV.PARAM_ID = 441 AND LV.IS_DEL = 0
            LEFT JOIN VALS LS ON LS.OBJ_ID = L79.OBJ_ID AND LS.PARAM_ID = 442 AND LS.IS_DEL = 0
            LEFT JOIN VALS LN ON LN.OBJ_ID = L79.OBJ_ID AND LN.PARAM_ID = 559 AND LN.IS_DEL = 0
            WHERE L79.PARENT_ID = :PUPIL_ID AND L79.DATE_DEL IS NULL AND L79.OBJ_TYPE_ID = 79
            INTO :DOCTYPE,:DOCSERIA,:DOCNUMBER;
        
            SELECT FIRST 1 P9.PARENT_ID
            FROM LINKS P9
            WHERE P9.PARENT_TYPE_ID = 9 AND P9.OBJ_ID = :PUPIL_ID AND P9.DATE_DEL IS NULL
            INTO :CLASS_ID;
        
            IF (CLASS_ID IS NOT NULL) THEN
            BEGIN
                SELECT CAPTION
                FROM OBJECT_CAPTION_GET(:CLASS_ID,NULL,NULL,:I$USER_ID)
                INTO :CURRICULUM;
        
                SELECT FIRST 1 P2.PARENT_ID
                FROM LINKS P8
                JOIN LINKS P7
                ON P7.OBJ_ID = P8.PARENT_ID
                AND P7.PARENT_TYPE_ID = 7
                AND P7.DATE_DEL IS NULL
                JOIN LINKS P2
                ON P2.OBJ_ID = P7.PARENT_ID
                AND P2.PARENT_TYPE_ID = 2
                AND P2.DATE_DEL IS NULL
                WHERE P8.PARENT_TYPE_ID = 8
                AND P8.OBJ_ID = :CLASS_ID
                AND P8.DATE_DEL IS NULL
                INTO :SCHOOL_ID;
            END
            ELSE
            BEGIN
                CURRICULUM = NULL;
            END
        
            SELECT V
            FROM VAL_GET(:SCHOOL_ID,5,0,:I$USER_ID)
            INTO :NAMEEDUINSTITUTION;
            SELECT V
            FROM VAL_GET(:SCHOOL_ID,2,0,:I$USER_ID)
            INTO :SHORTNAMEEDUINSTITUTION;
            SELECT V
            FROM VAL_GET(:SCHOOL_ID,17,0,:I$USER_ID)
            INTO :NUMBEREDUINSTITUTION;
            SELECT V
            FROM VAL_GET(:SCHOOL_ID,28,0,:I$USER_ID)
            INTO :PHONEMASTER;
            SELECT V
            FROM VAL_GET(:SCHOOL_ID,29,0,:I$USER_ID)
            INTO :PHONERECEPTION;

            RETIREDIN = '';
            STR = '';
            SELECT R.VAL
            FROM VALL V
            JOIN LISTVALS LV
            ON LV.LISTVAL_ID = V.LISTVAL_ID
            LEFT JOIN RES_GET(LV.RES_ID,  :LANG_CODE) R ON 1=1
            WHERE V.OBJ_ID = :PUPIL_ID
            AND V.PARAM_ID = 105
            INTO :STR;
            if ((STR != '') AND (STR IS NOT NULL)) then
            BEGIN
                RETIREDIN = STR;
            END
            STR = '';
            SELECT R.VAL
            FROM VALL V
            JOIN LISTVALS LV
            ON LV.LISTVAL_ID = V.LISTVAL_ID
            LEFT JOIN RES_GET(LV.RES_ID,  :LANG_CODE) R ON 1=1
            WHERE V.OBJ_ID = :PUPIL_ID
            AND V.PARAM_ID = 107
            INTO :STR;
            if ((STR != '') AND (STR IS NOT NULL)) then
            BEGIN
                IF (RETIREDIN = '') THEN
                BEGIN
                    RETIREDIN = STR;
                END
                ELSE
                BEGIN
                    RETIREDIN = RETIREDIN || '; ' || STR;
                END
            END
            STR = '';
            SELECT R.VAL
            FROM VALL V
            JOIN LISTVALS LV
            ON LV.LISTVAL_ID = V.LISTVAL_ID
            LEFT JOIN RES_GET(LV.RES_ID,  :LANG_CODE) R ON 1=1
            WHERE V.OBJ_ID = :PUPIL_ID
            AND V.PARAM_ID = 188
            INTO :STR;
            if ((STR != '') AND (STR IS NOT NULL)) then
            BEGIN
                IF (RETIREDIN = '') THEN
                BEGIN
                    RETIREDIN = STR;
                END
                ELSE
                BEGIN
                    RETIREDIN = RETIREDIN || '; ' || STR;
                END
            END
            STR = '';
            SELECT R.VAL
            FROM VALL V
            JOIN LISTVALS LV
            ON LV.LISTVAL_ID = V.LISTVAL_ID
            LEFT JOIN RES_GET(LV.RES_ID,  :LANG_CODE) R ON 1=1
            WHERE V.OBJ_ID = :PUPIL_ID
            AND V.PARAM_ID = 1346
            INTO :STR;
            if ((STR != '') AND (STR IS NOT NULL)) then
            BEGIN
                IF (RETIREDIN = '') THEN
                BEGIN
                    RETIREDIN = STR;
                END
                ELSE
                BEGIN
                    RETIREDIN = RETIREDIN || '; ' || STR;
                END
            END
            STR = '';
            SELECT V.VAL
            FROM VALS V
            WHERE V.OBJ_ID = :PUPIL_ID
            AND V.PARAM_ID = 161
            INTO :STR;
            if ((STR != '') AND (STR IS NOT NULL)) then
            BEGIN
                IF (RETIREDIN = '') THEN
                BEGIN
                    RETIREDIN = STR;
                END
                ELSE
                BEGIN
                    RETIREDIN = RETIREDIN || '; ' || STR;
                END
            END
        
            DISTRICT = NULL;
            SELECT FIRST 1 L111.PARENT_ID
            FROM LINKS L111
            JOIN VALL L ON L.PARAM_ID = 665 AND L.OBJ_ID = L111.PARENT_ID AND L.IS_DEL = 0
            WHERE L111.OBJ_ID = :SCHOOL_ID AND L111.DATE_DEL IS NULL AND L111.PARENT_TYPE_ID = 111
            INTO :DISTRICT;

            ENROLLMENTDATE = NULL;
            SELECT MIN(M.DATE_IN)
            FROM PERSON_MOVEMENTS M
            JOIN OBJECTS O ON O.OBJ_ID = M.GROUP_ID AND O.TYPE_ID = 9
            JOIN LISTVALS LV ON LV.LISTVAL_ID = M.REASON_IN AND LV."FILTER" LIKE 'ACCEPTED%'
            WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :PUPIL_ID
            INTO :ENROLLMENTDATE;

            DEDUCTIONSDATE = NULL;
            SELECT MAX(M.DATE_OUT)
            FROM PERSON_MOVEMENTS M
            JOIN OBJECTS O ON O.OBJ_ID = M.GROUP_ID AND O.TYPE_ID = 9
            JOIN LISTVALS LV ON LV.LISTVAL_ID = M.REASON_OUT AND LV."FILTER" LIKE 'LEAVED%'
            WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :PUPIL_ID AND M.DATE_OUT IS NOT NULL
            INTO :DEDUCTIONSDATE;

            SUSPEND;
        END
    END

    IF ((STATUS = 0)
    AND (I$DOCTYPE IS NOT NULL)
    AND (I$SERIE IS NOT NULL)
    AND (I$NUMBER IS NOT NULL)) THEN
    BEGIN
        FOR
            SELECT I.PUPIL_ID,I.DROPOUT
            FROM SNILS_INDEX I
            JOIN DOC_INDEX D
            ON D.PUPIL_ID = I.PUPIL_ID
            WHERE D.DOCTYPE = :I$DOCTYPE
            AND UPPER(D.DOCSERIE) LIKE UPPER(:I$SERIE)
            AND UPPER(D.DOCNUMBER) LIKE UPPER(:I$NUMBER)
            INTO :PUPIL_ID,:DROPOUT
        DO
        BEGIN
            STATUS = 6;
    
            SELECT V
            FROM VAL_GET(:PUPIL_ID,55,0,:I$USER_ID)
            INTO :LASTNAME;
            SELECT V
            FROM VAL_GET(:PUPIL_ID,56,0,:I$USER_ID)
            INTO :FIRSTNAME;
            SELECT V
            FROM VAL_GET(:PUPIL_ID,57,0,:I$USER_ID)
            INTO :SECONDNAME;
            SELECT I
            FROM VAL_GET(:PUPIL_ID,88,0,:I$USER_ID)
            INTO :GENDER;
            SELECT D
            FROM VAL_GET(:PUPIL_ID,89,0,:I$USER_ID)
            INTO :BIRTHDATE;
        
            SELECT FIRST 1 LV.LISTVAL_ID, LS.VAL, LN.VAL
            FROM LINKS L79
            JOIN VALL LV
            ON LV.OBJ_ID = L79.OBJ_ID
            AND LV.PARAM_ID = 441
            AND LV.IS_DEL = 0
            LEFT JOIN VALS LS
            ON LS.OBJ_ID = L79.OBJ_ID
            AND LS.PARAM_ID = 442
            AND LS.IS_DEL = 0
            LEFT JOIN VALS LN
            ON LN.OBJ_ID = L79.OBJ_ID
            AND LN.PARAM_ID = 559
            AND LN.IS_DEL = 0
            WHERE L79.PARENT_ID = :PUPIL_ID
            AND L79.DATE_DEL IS NULL
            AND L79.OBJ_TYPE_ID = 79
            INTO :DOCTYPE,:DOCSERIA,:DOCNUMBER;
        
            SELECT FIRST 1 P9.PARENT_ID
            FROM LINKS P9
            WHERE P9.PARENT_TYPE_ID = 9
            AND P9.OBJ_ID = :PUPIL_ID
            AND P9.DATE_DEL IS NULL
            INTO :CLASS_ID;
        
            IF (CLASS_ID IS NOT NULL) THEN
            BEGIN
                SELECT CAPTION
                FROM OBJECT_CAPTION_GET(:CLASS_ID,NULL,NULL,:I$USER_ID)
                INTO :CURRICULUM;
        
                SELECT FIRST 1 P2.PARENT_ID
                FROM LINKS P8
                JOIN LINKS P7
                ON P7.OBJ_ID = P8.PARENT_ID
                AND P7.PARENT_TYPE_ID = 7
                AND P7.DATE_DEL IS NULL
                JOIN LINKS P2
                ON P2.OBJ_ID = P7.PARENT_ID
                AND P2.PARENT_TYPE_ID = 2
                AND P2.DATE_DEL IS NULL
                WHERE P8.PARENT_TYPE_ID = 8
                AND P8.OBJ_ID = :CLASS_ID
                AND P8.DATE_DEL IS NULL
                INTO :SCHOOL_ID;
            END
            ELSE
            BEGIN
                CURRICULUM = NULL;
            END
        
            SELECT V
            FROM VAL_GET(:SCHOOL_ID,5,0,:I$USER_ID)
            INTO :NAMEEDUINSTITUTION;
            SELECT V
            FROM VAL_GET(:SCHOOL_ID,2,0,:I$USER_ID)
            INTO :SHORTNAMEEDUINSTITUTION;
            SELECT V
            FROM VAL_GET(:SCHOOL_ID,17,0,:I$USER_ID)
            INTO :NUMBEREDUINSTITUTION;
            SELECT V
            FROM VAL_GET(:SCHOOL_ID,28,0,:I$USER_ID)
            INTO :PHONEMASTER;
            SELECT V
            FROM VAL_GET(:SCHOOL_ID,29,0,:I$USER_ID)
            INTO :PHONERECEPTION;

            RETIREDIN = '';
            STR = '';
            SELECT R.VAL
            FROM VALL V
            JOIN LISTVALS LV
            ON LV.LISTVAL_ID = V.LISTVAL_ID
            LEFT JOIN RES_GET(LV.RES_ID,  :LANG_CODE) R ON 1=1
            WHERE V.OBJ_ID = :PUPIL_ID
            AND V.PARAM_ID = 105
            INTO :STR;
            if ((STR != '') AND (STR IS NOT NULL)) then
            BEGIN
                RETIREDIN = STR;
            END
            STR = '';
            SELECT R.VAL
            FROM VALL V
            JOIN LISTVALS LV
            ON LV.LISTVAL_ID = V.LISTVAL_ID
            LEFT JOIN RES_GET(LV.RES_ID,  :LANG_CODE) R ON 1=1
            WHERE V.OBJ_ID = :PUPIL_ID
            AND V.PARAM_ID = 107
            INTO :STR;
            if ((STR != '') AND (STR IS NOT NULL)) then
            BEGIN
                IF (RETIREDIN = '') THEN
                BEGIN
                    RETIREDIN = STR;
                END
                ELSE
                BEGIN
                    RETIREDIN = RETIREDIN || '; ' || STR;
                END
            END
            STR = '';
            SELECT R.VAL
            FROM VALL V
            JOIN LISTVALS LV
            ON LV.LISTVAL_ID = V.LISTVAL_ID
            LEFT JOIN RES_GET(LV.RES_ID,  :LANG_CODE) R ON 1=1
            WHERE V.OBJ_ID = :PUPIL_ID
            AND V.PARAM_ID = 188
            INTO :STR;
            if ((STR != '') AND (STR IS NOT NULL)) then
            BEGIN
                IF (RETIREDIN = '') THEN
                BEGIN
                    RETIREDIN = STR;
                END
                ELSE
                BEGIN
                    RETIREDIN = RETIREDIN || '; ' || STR;
                END
            END
            STR = '';
            SELECT R.VAL
            FROM VALL V
            JOIN LISTVALS LV
            ON LV.LISTVAL_ID = V.LISTVAL_ID
            LEFT JOIN RES_GET(LV.RES_ID,  :LANG_CODE) R ON 1=1
            WHERE V.OBJ_ID = :PUPIL_ID
            AND V.PARAM_ID = 1346
            INTO :STR;
            if ((STR != '') AND (STR IS NOT NULL)) then
            BEGIN
                IF (RETIREDIN = '') THEN
                BEGIN
                    RETIREDIN = STR;
                END
                ELSE
                BEGIN
                    RETIREDIN = RETIREDIN || '; ' || STR;
                END
            END
            STR = '';
            SELECT V.VAL
            FROM VALS V
            WHERE V.OBJ_ID = :PUPIL_ID
            AND V.PARAM_ID = 161
            INTO :STR;
            if ((STR != '') AND (STR IS NOT NULL)) then
            BEGIN
                IF (RETIREDIN = '') THEN
                BEGIN
                    RETIREDIN = STR;
                END
                ELSE
                BEGIN
                    RETIREDIN = RETIREDIN || '; ' || STR;
                END
            END
        
            DISTRICT = NULL;
            SELECT FIRST 1 L111.PARENT_ID
            FROM LINKS L111
            JOIN VALL L ON L.PARAM_ID = 665 AND L.OBJ_ID = L111.PARENT_ID AND L.IS_DEL = 0
            WHERE L111.OBJ_ID = :SCHOOL_ID AND L111.DATE_DEL IS NULL AND L111.PARENT_TYPE_ID = 111
            INTO :DISTRICT;

            ENROLLMENTDATE = NULL;
            SELECT MIN(M.DATE_IN)
            FROM PERSON_MOVEMENTS M
            JOIN OBJECTS O ON O.OBJ_ID = M.GROUP_ID AND O.TYPE_ID = 9
            JOIN LISTVALS LV ON LV.LISTVAL_ID = M.REASON_IN AND LV."FILTER" LIKE 'ACCEPTED%'
            WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :PUPIL_ID
            INTO :ENROLLMENTDATE;

            DEDUCTIONSDATE = NULL;
            SELECT MAX(M.DATE_OUT)
            FROM PERSON_MOVEMENTS M
            JOIN OBJECTS O ON O.OBJ_ID = M.GROUP_ID AND O.TYPE_ID = 9
            JOIN LISTVALS LV ON LV.LISTVAL_ID = M.REASON_OUT AND LV."FILTER" LIKE 'LEAVED%'
            WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :PUPIL_ID AND M.DATE_OUT IS NOT NULL
            INTO :DEDUCTIONSDATE;
    
            SUSPEND;
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GIA_ACCEPT_CHECK_INT (
    I$GRADE_ID BIGINT)
AS
begin

  IF(EXISTS(
    SELECT FIRST 1 1
    FROM LINKS
    WHERE PARENT_ID = :I$GRADE_ID AND OBJ_TYPE_ID = 10 AND DATE_DEL IS NULL
  ))
  THEN EXCEPTION DATA_ERROR 'Сторонние и действующие обучающиеся не могут числиться в одном классе для сдачи ГИА';

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GIA_APPOINT_ASSIGN (
    CLASS_ID BIGINT,
    PUPIL_ID BIGINT,
    SUBJECT_ID BIGINT,
    EXAM_ID BIGINT,
    YEAR_ID BIGINT)
AS
declare variable OBJ_ID bigint;
declare variable OLD_EXAM_ID bigint;
BEGIN
    FOR
        SELECT OBJ_ID
        FROM GIA_CLASS_SCHOLAR_LIST(:CLASS_ID)

        UNION

        SELECT :PUPIL_ID
        FROM RDB$DATABASE
        INTO :OBJ_ID
    DO
    BEGIN
        OLD_EXAM_ID = NULL;

        SELECT L120.OBJ_ID

        FROM LINKS L120

        JOIN VALL V803
        ON V803.OBJ_ID = L120.OBJ_ID
        AND V803.PARAM_ID = 803
        AND V803.IS_DEL = 0
        AND V803.LISTVAL_ID = :SUBJECT_ID

        JOIN LINKS Y120
        ON Y120.OBJ_ID = L120.OBJ_ID
        AND Y120.PARENT_TYPE_ID = 119
        AND Y120.DATE_DEL IS NULL

        WHERE L120.PARENT_ID = :OBJ_ID
        AND L120.OBJ_TYPE_ID = 120
        AND L120.DATE_DEL IS NULL
        AND Y120.PARENT_ID = :YEAR_ID

        INTO :OLD_EXAM_ID;

        UPDATE LINKS L
        SET L.DATE_DEL = CURRENT_TIMESTAMP
        WHERE L.PARENT_ID = :OBJ_ID
        AND L.OBJ_ID = :OLD_EXAM_ID;

        IF (EXAM_ID IS NOT NULL) THEN
        BEGIN
            SELECT OBJ_ID
            FROM OBJECT_ADD_LINK(:OBJ_ID, :EXAM_ID, 120)
            INTO :OLD_EXAM_ID;
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GIA_APPOINT_CLASS_LIST (
    I$SCHOOL_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    OBJ_CAPTION VARCHAR(4000),
    STAGE_ID BIGINT,
    GRADUATE BIGINT,
    PARALLEL INTEGER,
    SYNONIM VARCHAR(500))
AS
DECLARE VARIABLE PARENT_ID BIGINT;
DECLARE VARIABLE OBJ_TYPE BIGINT;
DECLARE VARIABLE LANG_CODE VARCHAR(2);
DECLARE VARIABLE STAGE_TYPE_ID BIGINT;
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :LANG_CODE;

    FOR
        SELECT OBJ_ID, OBJ_CAPTION
        FROM GIA_CLASS_LIST(:I$SCHOOL_ID)
        INTO :OBJ_ID, :OBJ_CAPTION
    DO
    BEGIN
        SELECT L.PARENT_ID, L.OBJ_TYPE_ID
        FROM LINKS L
        WHERE L.PARENT_TYPE_ID IN (8, 124) AND L.OBJ_ID = :OBJ_ID AND L.DATE_DEL IS NULL
        INTO :PARENT_ID, :OBJ_TYPE;

        PARALLEL = NULL;
        SELECT COST, I
        FROM VAL_GET(:PARENT_ID, 49, 0, :I$USER_ID)
        INTO :PARALLEL, STAGE_TYPE_ID;

        SELECT CASE WHEN I = 11202 THEN 0 WHEN I = 11203 THEN 1 ELSE -1 END,
               CASE WHEN I = 11202 THEN 9 WHEN I = 11203 THEN 11 ELSE :PARALLEL END
        FROM VAL_GET(:OBJ_ID, CASE WHEN :OBJ_TYPE = 9 THEN 2388 WHEN :OBJ_TYPE = 187 THEN 2418 WHEN :OBJ_TYPE = 125 THEN 2419 END)
        INTO :GRADUATE,
             :PARALLEL;

        STAGE_ID = NULL;
        SELECT LV.LISTVAL_ID
        FROM LISTVALS_LIST(219, :LANG_CODE) LV
        WHERE (LV.VAL_LONG = :PARALLEL)
        OR ((:PARALLEL = 10) AND (LV.VAL_LONG = 11))
        INTO :STAGE_ID;

        IF (STAGE_TYPE_ID IN (49,50,51,52,53,54)) THEN
        BEGIN
            SYNONIM = OBJ_CAPTION;
        END
        ELSE
        BEGIN
            SYNONIM = NULL;
            SELECT V
            FROM VAL_GET(:OBJ_ID, CASE WHEN :OBJ_TYPE = 9 THEN 1363 WHEN :OBJ_TYPE = 187 THEN 1653 WHEN :OBJ_TYPE = 125 THEN 821 END, 0, :I$USER_ID)
            INTO :SYNONIM;
        END

        IF ((SYNONIM <> '') AND (GRADUATE in (0,1))) THEN
        BEGIN
            SUSPEND;
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GIA_APPOINT_CURRENT_YEAR (
    I$USER_ID BIGINT)
RETURNS (
    YEAR_ID BIGINT,
    LAST_YEAR INTEGER)
AS
declare variable LANG_CODE varchar(2);
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :LANG_CODE;

    SELECT GY.YEAR_ID,
           CY.Y1 + 1
    FROM CURRENT_SCHOOL_YEAR_GET CY

    JOIN LISTVALS LV
    ON LV.LIST_ID = 29
    AND LV.COST = CY.Y1
    AND LV.IS_DEL = 0

    LEFT JOIN RES_GET(LV.RES_ID,  :LANG_CODE) R ON 1=1

    JOIN GIA_EXAM_YEAR_GET(:I$USER_ID) GY
    ON GY.YEAR_CAPTION = R.VAL

    INTO :YEAR_ID, :LAST_YEAR;

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GIA_APPOINT_LIST (
    CLASS_ID BIGINT,
    YEAR_ID BIGINT,
    I$USER_ID BIGINT = 1)
RETURNS (
    OBJ_ID BIGINT,
    OBJ_CAPTION VARCHAR(4000),
    EXAM_ID BIGINT,
    EXAM_SUBJECT_ID BIGINT,
    EXAM_DATE DATE,
    EXAM_PERMIT VARCHAR(3),
    FOREIGN_LANG_VERBALLY VARCHAR(3),
    OLD_GRADUATE SMALLINT,
    SPECIAL_CONDITIONS SMALLINT,
    GIA_ONLY SMALLINT)
AS
DECLARE VARIABLE TYPE_ID BIGINT;
BEGIN
    FOR
        SELECT OBJ_ID, OBJ_CAPTION, TYPE_ID
        FROM GIA_CLASS_SCHOLAR_LIST(:CLASS_ID)
        INTO :OBJ_ID, :OBJ_CAPTION, :TYPE_ID
    DO
    BEGIN
        IF (TYPE_ID = 126) THEN
        BEGIN
            --Устная часть ин.яз.
            SELECT IIF(I IN (0,3),0,1)
            FROM VAL_GET(:OBJ_ID,2159,0,:I$USER_ID)
            INTO :FOREIGN_LANG_VERBALLY;

            --Допуск к ГИА
            SELECT IIF(I IN (0,2),1,0)
            FROM VAL_GET(:OBJ_ID,2160,0,:I$USER_ID)
            INTO :EXAM_PERMIT;

            --Требует особых условий при проведении ГИА
            SELECT IIF(I IN (0,2856),0,1)
            FROM VAL_GET(:OBJ_ID,832,0,:I$USER_ID)
            INTO :SPECIAL_CONDITIONS;

            --Выпускник прошлых лет
            SELECT IIF(I IN (2995),1,0)
            FROM VAL_GET(:OBJ_ID,835,0,:I$USER_ID)
            INTO :OLD_GRADUATE;

            --Принят только для сдачи ГИА
            GIA_ONLY = 1;
        END
        ELSE IF(TYPE_ID = 10) THEN
        BEGIN
            --Устная часть ин.яз.
            SELECT IIF(I IN (0,3),0,1)
            FROM VAL_GET(:OBJ_ID,2154,0,:I$USER_ID)
            INTO :FOREIGN_LANG_VERBALLY;

            --Допуск к ГИА
            SELECT IIF(I IN (0,2),1,0)
            FROM VAL_GET(:OBJ_ID,2155,0,:I$USER_ID)
            INTO :EXAM_PERMIT;

            --Требует особых условий при проведении ГИА
            SELECT IIF(I IN (0,2856),0,1)
            FROM VAL_GET(:OBJ_ID,1374,0,:I$USER_ID)
            INTO :SPECIAL_CONDITIONS;

            --Выпускник прошлых лет (Категория участника ГИА)
            SELECT IIF(I IN (2995),1,0)
            FROM VAL_GET(:OBJ_ID,1340,0,:I$USER_ID)
            INTO :OLD_GRADUATE;

            --Принят только для сдачи ГИА
            GIA_ONLY = 0;
        END

        EXAM_ID = NULL;
        EXAM_SUBJECT_ID = NULL;
        EXAM_DATE = NULL;
        FOR
            SELECT L120.OBJ_ID
            FROM LINKS L120
            LEFT JOIN LINKS Y120 ON Y120.OBJ_ID = L120.OBJ_ID AND Y120.PARENT_TYPE_ID = 119 AND Y120.DATE_DEL IS NULL
            WHERE L120.PARENT_ID = :OBJ_ID AND L120.OBJ_TYPE_ID = 120 AND L120.DATE_DEL IS NULL AND Y120.PARENT_ID = :YEAR_ID
            INTO :EXAM_ID
        DO
        BEGIN
            EXAM_SUBJECT_ID = NULL;
            SELECT I
            FROM VAL_GET(:EXAM_ID, 803)
            INTO :EXAM_SUBJECT_ID;

            EXAM_DATE = NULL;
            SELECT D
            FROM VAL_GET(:EXAM_ID, 804)
            INTO :EXAM_DATE;

            SUSPEND;
        END
        IF (EXAM_ID IS NULL) THEN
        BEGIN
            SUSPEND;
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GIA_APPOINT_REPORT_CONTENT (
    OBJ_ID BIGINT,
    YEAR_ID BIGINT,
    EXAM_TYPE_ID BIGINT = null)
RETURNS (
    EXAM_TYPE INTEGER,
    GIA_SUBJECT_ID INTEGER,
    EXAM_DATE DATE,
    EXAM_PERMIT SMALLINT,
    FOREIGN_LANG_VERBALLY SMALLINT)
AS
declare variable EXAM_ID bigint;
declare variable TYPE_ID bigint;
BEGIN
    FOR
        SELECT TYPE_ID
        FROM OBJECTS
        WHERE OBJ_ID = :OBJ_ID
        INTO :TYPE_ID
    DO
    BEGIN
        IF (TYPE_ID = 126) THEN
        BEGIN
            SELECT IIF(I IN (0,3),0,1)
            FROM VAL_GET(:OBJ_ID,2159)
            INTO :FOREIGN_LANG_VERBALLY;

            SELECT IIF(I IN (0,2),1,0)
            FROM VAL_GET(:OBJ_ID,2160)
            INTO :EXAM_PERMIT;
        END
        ELSE IF(TYPE_ID = 10) THEN
        BEGIN
            SELECT IIF(I IN (0,3),0,1)
            FROM VAL_GET(:OBJ_ID,2154)
            INTO :FOREIGN_LANG_VERBALLY;

            SELECT IIF(I IN (0,2),1,0)
            FROM VAL_GET(:OBJ_ID,2155)
            INTO :EXAM_PERMIT;
        END
    END

    FOR
        SELECT L120.OBJ_ID
        FROM LINKS L120
        LEFT JOIN LINKS Y120 ON Y120.OBJ_ID = L120.OBJ_ID AND Y120.PARENT_TYPE_ID = 119 AND Y120.DATE_DEL IS NULL
        WHERE L120.PARENT_ID = :OBJ_ID AND L120.OBJ_TYPE_ID = 120 AND L120.DATE_DEL IS NULL AND ((Y120.PARENT_ID = :YEAR_ID) OR (:YEAR_ID IS NULL))
        INTO :EXAM_ID
    DO
    BEGIN
        GIA_SUBJECT_ID = NULL;
        SELECT IIF(LV.TAG = 'FL', -19, LV.TAG)
        FROM VAL_GET(:EXAM_ID, 803) V
        JOIN LISTVALS LV ON LV.LISTVAL_ID = V.I
        INTO :GIA_SUBJECT_ID;

        EXAM_TYPE = NULL;
        SELECT CAST(COST AS INTEGER)
        FROM VAL_GET(:EXAM_ID, 802)
        INTO :EXAM_TYPE;

        EXAM_DATE = NULL;
        SELECT D
        FROM VAL_GET(:EXAM_ID, 804)
        INTO :EXAM_DATE;

        IF ((EXAM_TYPE = EXAM_TYPE_ID) OR (EXAM_TYPE_ID IS NULL)) THEN
        BEGIN
            SUSPEND;
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GIA_APPOINT_REPORT_HEADER (
    SCHOOL_ID BIGINT,
    OBJ_ID BIGINT NOT NULL,
    I$USER_ID BIGINT)
RETURNS (
    DIRECTOR VARCHAR(500),
    FULLNAME VARCHAR(500),
    MALE VARCHAR(1),
    FEMALE VARCHAR(1),
    PUPIL VARCHAR(20),
    FORM VARCHAR(500),
    BIRTHDAY DATE,
    SPECIAL_CONDITIONS SMALLINT,
    PASSPORT VARCHAR(500),
    PASSDATE DATE,
    PASSINFO VARCHAR(500),
    FIO VARCHAR(500),
    "DATE" DATE,
    CONTACT_PHONE VARCHAR(40),
    DOCTYPE VARCHAR(500),
    DOC_S VARCHAR(100),
    DOC_N VARCHAR(100),
    SCHOOLCODE VARCHAR(50))
AS
DECLARE VARIABLE SEX BIGINT;
DECLARE VARIABLE OBJ_TYPE BIGINT;
DECLARE VARIABLE FORM_ID BIGINT;
DECLARE VARIABLE DOCUMENT_ID BIGINT;
DECLARE VARIABLE F VARCHAR(500);
DECLARE VARIABLE I VARCHAR(500);
DECLARE VARIABLE O VARCHAR(500);
DECLARE VARIABLE FORM_TYPE BIGINT;
BEGIN
    SELECT FIO
    FROM GIA_GET_DIRECTOR_FIO(:SCHOOL_ID, :I$USER_ID)
    INTO :DIRECTOR;

    SELECT TYPE_ID
    FROM OBJECTS
    WHERE OBJ_ID = :OBJ_ID
    INTO :OBJ_TYPE;

    SELECT V
    FROM VAL_GET(:SCHOOL_ID, 1364)
    INTO :SCHOOLCODE;

    MALE = NULL;
    FEMALE = NULL;
    SEX = NULL;
    PUPIL = NULL;
    BIRTHDAY = NULL;
    SPECIAL_CONDITIONS = NULL;
    F = NULL;
    I = NULL;
    O = NULL;
    IF (OBJ_TYPE = 10) THEN
    BEGIN
        SELECT V FROM VAL_GET(:OBJ_ID, 55, 0, :I$USER_ID) INTO :F;
        SELECT V FROM VAL_GET(:OBJ_ID, 56, 0, :I$USER_ID) INTO :I;
        SELECT V FROM VAL_GET(:OBJ_ID, 57, 0, :I$USER_ID) INTO :O;
        SELECT I FROM VAL_GET(:OBJ_ID, 88, 0, :I$USER_ID) INTO :SEX;
        SELECT D FROM VAL_GET(:OBJ_ID, 89, 0, :I$USER_ID) INTO :BIRTHDAY;
        SELECT I FROM VAL_GET(:OBJ_ID, 1374, 0, :I$USER_ID) INTO :SPECIAL_CONDITIONS;
        SELECT V FROM VAL_GET(:OBJ_ID, 102, 0, :I$USER_ID) INTO :CONTACT_PHONE;
    END
    ELSE
    BEGIN
        SELECT V FROM VAL_GET(:OBJ_ID, 827, 0, :I$USER_ID) INTO :F;
        SELECT V FROM VAL_GET(:OBJ_ID, 828, 0, :I$USER_ID) INTO :I;
        SELECT V FROM VAL_GET(:OBJ_ID, 829, 0, :I$USER_ID) INTO :O;
        SELECT I FROM VAL_GET(:OBJ_ID, 1022, 0, :I$USER_ID) INTO :SEX;
        SELECT D FROM VAL_GET(:OBJ_ID, 830, 0, :I$USER_ID) INTO :BIRTHDAY;
        SELECT I FROM VAL_GET(:OBJ_ID, 832, 0, :I$USER_ID) INTO :SPECIAL_CONDITIONS;
        SELECT V FROM VAL_GET(:OBJ_ID, 831, 0, :I$USER_ID) INTO :CONTACT_PHONE;
    END
    IF (SEX = 183) THEN
    BEGIN
        MALE = 'V';
        PUPIL = 'ученик';
    END
    IF (SEX = 182) THEN
    BEGIN
        FEMALE = 'V';
        PUPIL = 'ученица';
    END
    IF (SPECIAL_CONDITIONS = 2856) THEN SPECIAL_CONDITIONS = 0;

    FORM_ID = NULL;
    FORM = NULL;

    SELECT FIRST 1 L9.OBJ_ID
    FROM LINKS L7
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
    JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_ID = :OBJ_ID AND L10.DATE_DEL IS NULL
    WHERE L7.PARENT_ID = :SCHOOL_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    INTO :FORM_ID;

    IF (FORM_ID IS NULL) THEN
    BEGIN
        SELECT FIRST 1 L.PARENT_ID
        FROM LINKS L
        WHERE L.OBJ_ID = :OBJ_ID AND L.PARENT_TYPE_ID = 125 AND L.DATE_DEL IS NULL
        INTO :FORM_ID;
    END

    IF (FORM_ID IS NULL) THEN
    BEGIN
        SELECT FIRST 1 L.PARENT_ID
        FROM LINKS L
        WHERE L.OBJ_ID = :OBJ_ID AND L.PARENT_TYPE_ID = 187 AND L.DATE_DEL IS NULL
        INTO :FORM_ID;
    END

    IF (FORM_ID IS NOT NULL) THEN
    BEGIN
        SELECT TYPE_ID
        FROM OBJECTS
        WHERE OBJ_ID = :FORM_ID
        INTO :FORM_TYPE;

        IF (FORM_TYPE = 9) THEN SELECT V FROM VAL_GET(:FORM_ID, 1363, 0, :I$USER_ID) INTO :FORM;
        ELSE IF (FORM_TYPE = 125) THEN SELECT V FROM VAL_GET(:FORM_ID, 821, 0, :I$USER_ID) INTO :FORM;
        ELSE IF (FORM_TYPE = 187) THEN SELECT V FROM VAL_GET(:FORM_ID, 1653, 0, :I$USER_ID) INTO :FORM;

        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:FORM_ID, NULL, NULL, :I$USER_ID)
        INTO :FORM;
    END

    DOCUMENT_ID = NULL;
    PASSPORT = NULL;
    PASSDATE = NULL;
    PASSINFO = NULL;

    SELECT FIRST 1 L.OBJ_ID
    FROM LINKS L
    -- только действующие докумекты !
    JOIN VALL V614 ON V614.OBJ_ID = L.OBJ_ID AND V614.PARAM_ID = 614 AND V614.IS_DEL = 0 AND V614.LISTVAL_ID = 1982
    JOIN VALL V ON V.OBJ_ID = L.OBJ_ID AND V.PARAM_ID = 441 AND V.IS_DEL = 0
    JOIN LISTVALS LV ON LV.LIST_ID = 143 AND LV.LISTVAL_ID = V.LISTVAL_ID AND LV.IS_DEL = 0
    WHERE L.PARENT_ID = :OBJ_ID AND L.OBJ_TYPE_ID = 79 AND L.DATE_DEL IS NULL --AND LV.COST <= 3.0
    ORDER BY LV.COST
    INTO :DOCUMENT_ID;

    IF (DOCUMENT_ID IS NOT NULL) THEN
    BEGIN
        SELECT V FROM VAL_GET(:DOCUMENT_ID, 441, 0, :I$USER_ID) INTO :DOCTYPE;
        SELECT V FROM VAL_GET(:DOCUMENT_ID, 442, 0, :I$USER_ID) INTO :DOC_S;
        SELECT V FROM VAL_GET(:DOCUMENT_ID, 559, 0, :I$USER_ID) INTO :DOC_N;
        PASSPORT = COALESCE(DOC_S, '') || ' ' || COALESCE(DOC_N, '');
        SELECT D FROM VAL_GET(:DOCUMENT_ID, 560, 0, :I$USER_ID) INTO :PASSDATE;
        SELECT V FROM VAL_GET(:DOCUMENT_ID, 562, 0, :I$USER_ID) INTO :PASSINFO;
    END

    FULLNAME = F || ' ' || I;
    IF (O IS NOT NULL) THEN FULLNAME = FULLNAME || ' ' || O;
    FIO = F || ' ' || SUBSTRING(I FROM 1 FOR 1) || '.';
    IF (O IS NOT NULL) THEN FIO = FIO || SUBSTRING(O FROM 1 FOR 1) || '.';

    "DATE" = CURRENT_DATE;

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GIA_BUILDING_LIST (
    I$PARENT_ID BIGINT = NULL)
RETURNS (
    OBJ_ID BIGINT,
    OBJ_CAPTION VARCHAR(4000),
    SORT_ORDER DOUBLE PRECISION)
AS
DECLARE VARIABLE SCHOOL_ID BIGINT;
BEGIN
    SELECT FIRST 1 L.OBJ_ID
    FROM LINKS L
    WHERE L.PARENT_ID IS NULL AND L.OBJ_TYPE_ID = 2 AND L.DATE_DEL IS NULL
    INTO :SCHOOL_ID;

    -- PARENT_ID нужен для исключения из списка выбора уже выбранных

    FOR
      SELECT DISTINCT L16.OBJ_ID
      FROM LINKS L73
      JOIN LINKS L16 ON L16.PARENT_ID = L73.OBJ_ID AND L16.OBJ_TYPE_ID = 16 AND L16.DATE_DEL IS NULL
      WHERE L73.PARENT_ID = :SCHOOL_ID AND L73.OBJ_TYPE_ID = 73 AND L73.DATE_DEL IS NULL
      AND (:I$PARENT_ID IS NULL OR NOT EXISTS(
        SELECT FIRST 1 1
        FROM LINKS LP
        WHERE LP.OBJ_ID = L16.OBJ_ID AND LP.PARENT_ID = :I$PARENT_ID AND LP.DATE_DEL IS NULL
      ))
      INTO :OBJ_ID
    DO
    BEGIN
      SELECT CAPTION, SORT_ORDER
      FROM OBJECT_CAPTION_GET(:OBJ_ID)
      INTO :OBJ_CAPTION, :SORT_ORDER;
      SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GIA_CHECK_CLASS_CHANGE (
    I$CLASS_ID BIGINT)
AS
declare variable HAS_ASSIGNMENTS integer;
declare variable PERIOD_YEAR integer;
declare variable DATE_RANGE varchar(100);
begin
  -- Любые изменения статуса выпускного класса возможно только при отсутствии назначения учеников
  HAS_ASSIGNMENTS = 0;

  -- Определяем текущий учебный период. Смену года производим с 01 июля
  PERIOD_YEAR = EXTRACT(YEAR FROM CURRENT_TIMESTAMP);
  IF(EXTRACT(MONTH FROM CURRENT_TIMESTAMP) <= 6) THEN PERIOD_YEAR = PERIOD_YEAR - 1;
  DATE_RANGE = PERIOD_YEAR || '-' || (PERIOD_YEAR + 1);

  SELECT FIRST 1 1
  -- Ученики в коллективе
  FROM LINKS L10
  -- Назначения на экзамены
  JOIN LINKS L120 ON L120.PARENT_ID = L10.OBJ_ID AND L120.OBJ_TYPE_ID = 120 AND L120.DATE_DEL IS NULL
  -- Год проведения
  JOIN LINKS LP119 ON LP119.OBJ_ID = L120.OBJ_ID AND LP119.PARENT_TYPE_ID = 119 AND LP119.DATE_DEL IS NULL
  -- Значение непосредственно учебного периода
  JOIN VALL V742 ON V742.OBJ_ID = LP119.PARENT_ID AND V742.PARAM_ID = 742 AND V742.IS_DEL = 0
  JOIN LISTVALS LV742 ON LV742.LISTVAL_ID = V742.LISTVAL_ID
  JOIN RES R742 ON R742.RES_ID = LV742.RES_ID AND R742.VAL = :DATE_RANGE
  WHERE L10.PARENT_ID = :I$CLASS_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
  INTO :HAS_ASSIGNMENTS;

  IF(HAS_ASSIGNMENTS <> 0) THEN EXCEPTION DATA_ERROR 'Нельзя изменять статус выпускного класса, если у учеников имеются назначения на экзамены';
end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GIA_CHECK_PUPIL_EXAMS (
    I$USER_ID BIGINT)
RETURNS (
    ERR INTEGER,
    SCHOOL VARCHAR(500),
    FORM VARCHAR(500),
    F VARCHAR(500),
    I VARCHAR(500),
    O VARCHAR(500))
AS
declare variable SCHOOL_ID bigint;
declare variable LEVEL_ID bigint;
declare variable PUPIL_ID bigint;
declare variable EXAM_ID bigint;
declare variable YEAR_ID bigint;
declare variable LAST_YEAR integer;
BEGIN
    SELECT KEY_VAL
    FROM KEYS
    WHERE KEY_CODE = 'LEVEL'
    INTO :LEVEL_ID;

    SELECT YEAR_ID, LAST_YEAR
    FROM GIA_APPOINT_CURRENT_YEAR(:I$USER_ID)
    INTO :YEAR_ID, :LAST_YEAR;

    FOR SELECT SCHOOL_ID, SCHOOL
        FROM GIA_OU_LIST(0, 1)
        INTO :SCHOOL_ID, :SCHOOL
    DO
    BEGIN
        FOR
            SELECT CODE_STUDENT_SCHOOL,
                   FORM,
                   FIO_SURNAME,
                   FIO_NAME,
                   FIO_PATRONYMIC
            FROM GIA_OU_EXPORT_STUDENT(:SCHOOL_ID, :I$USER_ID)
            INTO :PUPIL_ID,
                 :FORM,
                 :F,
                 :I,
                 :O
        DO
        BEGIN
            FOR
                SELECT L120.OBJ_ID

                FROM LINKS L120

                WHERE L120.PARENT_ID = :PUPIL_ID
                AND L120.OBJ_TYPE_ID = 120
                AND L120.DATE_DEL IS NULL

                INTO :EXAM_ID
            DO
            BEGIN
                IF (EXISTS(
                    SELECT FIRST 1 1

                    FROM LINKS L120

                    JOIN VALD V804
                    ON V804.OBJ_ID = L120.OBJ_ID
                    AND V804.PARAM_ID = 804
                    AND V804.IS_DEL = 0

                    WHERE L120.PARENT_TYPE_ID = 119
                    AND L120.OBJ_ID = :EXAM_ID
                    AND L120.DATE_DEL IS NULL
                    AND L120.PARENT_ID = :YEAR_ID
                    AND EXTRACT(YEAR FROM V804.VAL) <> :LAST_YEAR

                )) THEN
                BEGIN
                    ERR = 1;
                    SUSPEND;
                END
            END
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GIA_CLASS_GRADUATING_SET (
    I$FORCE_RESET INTEGER = 0)
RETURNS (
    OBJ_ID BIGINT)
AS
DECLARE VARIABLE SCHOOL_ID BIGINT;
DECLARE VARIABLE STAGE_ID BIGINT;
DECLARE VARIABLE TYPE_ID BIGINT;
DECLARE VARIABLE V VARCHAR(4000);
BEGIN
    SELECT FIRST 1 L.OBJ_ID
    FROM LINKS L
    WHERE L.PARENT_ID IS NULL AND L.OBJ_TYPE_ID = 2 AND L.DATE_DEL IS NULL
    INTO :SCHOOL_ID;

    -- Раньше вызывался при формировании экспорта, но сейчас вызов закомментирован
    -- Сейчас вызывается внутри preview, и с I$FORCE_RESET = 1 после перевода года

    -- Осторожно ! Тут проверяется только #7, ни в коем случае не добавлять 502
    FOR
      SELECT L9.OBJ_ID, L9.OBJ_TYPE_ID
      FROM LINKS L7
      JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
      JOIN VALL V ON V.OBJ_ID = L8.OBJ_ID AND V.PARAM_ID = 49 AND V.IS_DEL = 0
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 187) AND L9.DATE_DEL IS NULL
      LEFT JOIN VALS VL ON VL.OBJ_ID = L9.OBJ_ID AND VL.PARAM_ID IN (54, 1652) AND VL.IS_DEL = 0 -- сортируем по букве класса, чтобы синонимы были тоже по порядку
      LEFT JOIN VALS VS ON VS.OBJ_ID = L9.OBJ_ID AND VS.PARAM_ID IN (1363, 1653) AND VS.IS_DEL = 0
      WHERE L7.PARENT_ID = :SCHOOL_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL AND (:I$FORCE_RESET = 1 OR VS.VAL IS NULL)
      ORDER BY VL.SVAL
      INTO :OBJ_ID, :TYPE_ID
    DO
    BEGIN
      SELECT BLOB_ID FROM VAL_ADD(IIF(:TYPE_ID = 9, 2388, 2418), :OBJ_ID, 11217) INTO :STAGE_ID;
      SELECT SINONIM FROM GIA_CLASS_SINONIM_GET(:OBJ_ID) INTO :V;

      UPDATE OR INSERT INTO VALS (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
      VALUES (IIF(:TYPE_ID = 9, 1363, 1653), :OBJ_ID, 1, 0, :V);

      SUSPEND;
    END

    -- Осторожно ! Тут проверяется только #7, ни в коем случае не добавлять 502
    SELECT FIRST 1 L8.OBJ_ID
    FROM LINKS L7
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN VALL V ON V.OBJ_ID = L8.OBJ_ID AND V.PARAM_ID = 49 AND V.IS_DEL = 0 AND V.LISTVAL_ID IN (47, 48)
    WHERE L7.PARENT_ID = :SCHOOL_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    ORDER BY V.LISTVAL_ID DESC
    INTO :STAGE_ID;

    -- Все классы из последнего этапа в школе, и не являющиеся ОВЗ (экстернаты - вообще все), станут выпускными
    FOR
      SELECT L9.OBJ_ID, L9.OBJ_TYPE_ID
      FROM LINKS L9
      LEFT JOIN VALL V ON V.OBJ_ID = L9.OBJ_ID AND V.PARAM_ID = 592 AND V.IS_DEL = 0 AND V.LISTVAL_ID = 197
      WHERE L9.PARENT_ID = :STAGE_ID AND L9.OBJ_TYPE_ID IN (9, 187) AND L9.DATE_DEL IS NULL AND (V.LISTVAL_ID = 197 OR L9.OBJ_TYPE_ID = 187)
      UNION ALL
      SELECT L187.OBJ_ID, L187.OBJ_TYPE_ID
      FROM LINKS L187
      WHERE L187.PARENT_ID = :STAGE_ID AND L187.OBJ_TYPE_ID = 187 AND L187.DATE_DEL IS NULL
      INTO :OBJ_ID, :TYPE_ID
    DO
    BEGIN
      SELECT BLOB_ID FROM VAL_ADD(IIF(:TYPE_ID = 9, 1362, 1747), :OBJ_ID, '2') INTO :OBJ_ID;
    END

    -- А все классы не из этого последнего этапа станут не-выпускными
    FOR
      SELECT L.OBJ_ID, L.OBJ_TYPE_ID
      FROM LINKS L
      LEFT JOIN VALL V ON V.OBJ_ID = L.OBJ_ID AND V.PARAM_ID IN (1362, 1747) AND V.IS_DEL = 0
      WHERE L.PARENT_TYPE_ID = 8 AND L.PARENT_ID <> :STAGE_ID AND L.OBJ_TYPE_ID IN (9, 187) AND L.DATE_DEL IS NULL AND (V.LISTVAL_ID IS NULL OR V.LISTVAL_ID = 2)
      INTO :OBJ_ID, :TYPE_ID
    DO
    BEGIN
      SELECT BLOB_ID FROM VAL_ADD(IIF(:TYPE_ID = 9, 1362, 1747), :OBJ_ID, '3') INTO :OBJ_ID;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GIA_CLASS_LIST (
    I$SCHOOL_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    OBJ_CAPTION VARCHAR(4000))
AS
DECLARE VARIABLE STAGE_ID BIGINT;
DECLARE VARIABLE ROOT_TYPE BIGINT;
DECLARE VARIABLE LV BIGINT;
BEGIN
    SELECT O.TYPE_ID
    FROM OBJECTS O
    WHERE O.OBJ_ID = :I$SCHOOL_ID
    INTO :ROOT_TYPE;

    FOR
        SELECT L8.OBJ_ID, V.LISTVAL_ID
        FROM LINKS L7
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
        JOIN VALL V ON V.OBJ_ID = L8.OBJ_ID AND V.PARAM_ID = 49 AND V.IS_DEL = 0 AND V.LISTVAL_ID IN (37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54)
        WHERE L7.PARENT_ID = :I$SCHOOL_ID AND L7.OBJ_TYPE_ID IN (7, 502) AND L7.DATE_DEL IS NULL AND :ROOT_TYPE <> 124
        UNION
        SELECT :I$SCHOOL_ID, NULL
        FROM RDB$DATABASE
        WHERE :ROOT_TYPE = 124
        ORDER BY 2
        INTO :STAGE_ID, :LV
    DO
    BEGIN
        FOR
            SELECT L.OBJ_ID
            FROM LINKS L
            LEFT JOIN VALS V ON V.OBJ_ID = L.OBJ_ID AND V.PARAM_ID IN (54, 1652, 820) AND V.IS_DEL = 0
            WHERE L.PARENT_ID = :STAGE_ID AND L.OBJ_TYPE_ID IN (9, 187, 125) AND L.DATE_DEL IS NULL
            ORDER BY V.VAL
            INTO :OBJ_ID
        DO
        BEGIN
            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:OBJ_ID)
            INTO :OBJ_CAPTION;

            SUSPEND;
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GIA_CLASS_SCHOLAR_LIST (
    I$CLASS_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    TYPE_ID BIGINT,
    OBJ_CAPTION VARCHAR(4000))
AS
DECLARE VARIABLE V VARCHAR(4000);
BEGIN
    FOR
        SELECT L.OBJ_ID, F.VAL || ' ' || I.VAL, 10
        FROM LINKS L

        JOIN VALS F
        ON F.OBJ_ID = L.OBJ_ID
        AND F.PARAM_ID = 55
        AND F.IS_DEL = 0

        JOIN VALS I
        ON I.OBJ_ID = L.OBJ_ID
        AND I.PARAM_ID = 56
        AND I.IS_DEL = 0

        WHERE L.PARENT_ID = :I$CLASS_ID
        AND L.OBJ_TYPE_ID = 10
        AND L.DATE_DEL IS NULL

        ORDER BY F.VAL, I.VAL
        INTO :OBJ_ID, :OBJ_CAPTION, :TYPE_ID
    DO
    BEGIN
        V = '';
        SELECT V.VAL

        FROM VALS V

        WHERE V.PARAM_ID = 57
        AND V.OBJ_ID = :OBJ_ID
        AND V.IS_DEL = 0
        INTO :V;

        IF (V > '') THEN
        BEGIN
            OBJ_CAPTION = OBJ_CAPTION || ' ' || V;
        END

        SUSPEND;
    END

    FOR
        SELECT L.OBJ_ID, F.VAL || ' ' || I.VAL, 126

        FROM LINKS L

        JOIN VALS F
        ON F.OBJ_ID = L.OBJ_ID
        AND F.PARAM_ID = 827
        AND F.IS_DEL = 0

        JOIN VALS I
        ON I.OBJ_ID = L.OBJ_ID
        AND I.PARAM_ID = 828
        AND I.IS_DEL = 0

        WHERE L.PARENT_ID = :I$CLASS_ID
        AND L.OBJ_TYPE_ID = 126
        AND L.DATE_DEL IS NULL

        ORDER BY F.VAL, I.VAL
        INTO :OBJ_ID, :OBJ_CAPTION, :TYPE_ID
    DO
    BEGIN
        V = '';

        SELECT V.VAL
        FROM VALS V
        WHERE V.PARAM_ID = 829
        AND V.OBJ_ID = :OBJ_ID
        AND V.IS_DEL = 0
        INTO :V;

        IF (V > '') THEN
        BEGIN
            OBJ_CAPTION = OBJ_CAPTION || ' ' || V;
        END

        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GIA_CLASS_SINONIM_GET (
    I$OBJ_ID BIGINT)
RETURNS (
    SINONIM VARCHAR(30))
AS
DECLARE VARIABLE V$STAGE_ID BIGINT;
DECLARE VARIABLE V$TYPE_ID BIGINT;
DECLARE VARIABLE V$TAG VARCHAR(2);
DECLARE VARIABLE V$STR VARCHAR(28);
DECLARE VARIABLE V$GIA_TYPE_ID BIGINT;
BEGIN
  -- тип объекта
  SELECT TYPE_ID
  FROM OBJECTS
  WHERE OBJ_ID = :I$OBJ_ID
  INTO :V$TYPE_ID;

  V$STAGE_ID = NULL;
  SINONIM = '';

  -- находим этап обучения
  SELECT FIRST 1 PARENT_ID
  FROM LINKS
  WHERE OBJ_ID = :I$OBJ_ID AND DATE_DEL is null AND PARENT_TYPE_ID = 8
  INTO :V$STAGE_ID;

  -- если нашли
  IF (V$STAGE_ID IS NOT NULL) THEN
  BEGIN
    -- выпускной класс
    SELECT I
    FROM VAL_GET(:I$OBJ_ID, CASE WHEN :V$TYPE_ID = 9 THEN 2388 WHEN :V$TYPE_ID = 187 THEN 2418 WHEN :V$TYPE_ID = 125 THEN 2419 END)
    INTO :V$GIA_TYPE_ID;

    -- выпускной 9-ый
    IF (V$GIA_TYPE_ID = 11202) THEN
    BEGIN
      V$TAG = '9';
    END
    --выпускной 11-ый
    ELSE IF (V$GIA_TYPE_ID = 11203) THEN
    BEGIN
      V$TAG = '11';
    END
    --не выпускной
    --для колледжей будет 1...6
    ELSE IF (V$GIA_TYPE_ID = 11217) THEN
    BEGIN
      SELECT FIRST 1 SUBSTRING(IIF(LV.LISTVAL_ID IN (49, 50, 51, 52, 53, 54), 10, CAST(LV.COST AS INTEGER)) FROM 1 FOR 2)
      FROM VALL V
      JOIN LISTVALS LV on V.LISTVAL_ID = LV.LISTVAL_ID
      WHERE V.PARAM_ID = 49 AND V.OBJ_ID = :V$STAGE_ID
      INTO :V$TAG;
    END
  END

  -- если V$TAG не определен, считаем как 11
  IF (V$TAG = '' OR V$TAG IS NULL) THEN
  BEGIN
    /* V$STAGE_ID IS NULL */
    /* GIA_VIRTUAL_OU */
    V$TAG = '11';
  END

  -- Узнаем текущее наименование учебного коллектива и делаем его суффиксом (если оно задано; если не задано - будет действовать то, что было выше)
  -- проверяем суффикс по списку #214
  -- если значение отсутствует в списке, то V$STR = null и SINONIM = null
  /*SELECT FIRST 1 SUBSTRING(R.VAL FROM 1 FOR 28)
  FROM VALS V
  JOIN LISTVALS LV ON LV.LIST_ID = 214 AND LV.IS_DEL = 0
  JOIN RES R on R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU' AND LOWER(V.VAL) = SUBSTRING(R.VAL FROM 1 FOR 28)
  WHERE V.PARAM_ID IN (54, 820, 1652) AND V.OBJ_ID = :I$OBJ_ID AND V.IS_DEL = 0
  INTO :V$STR;*/

  SELECT FIRST 1 SUBSTRING(:V$TAG || R.VAL FROM 1 FOR 28)
  FROM LISTVALS LV
  JOIN RES R on R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
  -- Строки дальше нужны чтобы отсортировать выборку чтобы текущий алиас был первым по списку, если он валиден
  LEFT JOIN VALS V54 ON V54.PARAM_ID IN (54, 820, 1652) AND V54.IS_DEL = 0 AND V54.SVAL = SUBSTRING(R.VAL FROM 1 FOR 28)
  LEFT JOIN LINKS LP8 ON LP8.OBJ_ID = V54.OBJ_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
  LEFT JOIN VALL XV49 ON XV49.OBJ_ID = LP8.PARENT_ID AND XV49.PARAM_ID = 49 AND XV49.IS_DEL = 0
  LEFT JOIN LISTVALS XLV49 ON XLV49.LISTVAL_ID = XV49.LISTVAL_ID
  WHERE LV.LIST_ID = 214 AND LV.IS_DEL = 0 AND (XLV49.LISTVAL_ID IS NULL OR XLV49.TAG = :V$TAG)
    -- не является штатной буквой ни одного класса
    AND NOT EXISTS (
      SELECT FIRST 1 1
      FROM LINKS L9
      JOIN VALS V ON V.OBJ_ID = L9.OBJ_ID AND V.PARAM_ID IN (1363, 821, 1653) AND V.IS_DEL = 0 AND V.VAL = :V$TAG || R.VAL
      WHERE L9.PARENT_TYPE_ID IN (8, 124) AND L9.OBJ_TYPE_ID IN (9, 125, 187) AND L9.DATE_DEL IS NULL AND L9.OBJ_ID <> :I$OBJ_ID
    )
    -- не назначен алиасом в других классах
    AND NOT EXISTS (
      SELECT FIRST 1 1
      FROM LINKS L9
      JOIN VALL V49 ON V49.OBJ_ID = L9.PARENT_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
      JOIN LISTVALS LV49 ON LV49.LISTVAL_ID = V49.LISTVAL_ID AND LV49.TAG = :V$TAG
      JOIN VALS V ON V.OBJ_ID = L9.OBJ_ID AND V.PARAM_ID IN (54, 820, 1652) AND V.IS_DEL = 0 AND LOWER(V.VAL) = R.VAL
      WHERE L9.PARENT_TYPE_ID IN (8, 124) AND L9.OBJ_TYPE_ID IN (9, 125, 187) AND L9.DATE_DEL IS NULL AND L9.OBJ_ID <> :I$OBJ_ID
    )
  ORDER BY IIF(V54.OBJ_ID = :I$OBJ_ID, 0, 1), LV.SORT_ORDER
  INTO :SINONIM;

  SUSPEND;

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GIA_CODES_CHECK (
    SCHOOL_ID BIGINT,
    CODE_OU INTEGER,
    CODE_PPE INTEGER)
RETURNS (
    OBJ_ID BIGINT,
    CAPTION VARCHAR(4000))
AS
DECLARE VARIABLE LEVEL_ID SMALLINT;
BEGIN
    SELECT KEY_VAL
    FROM KEYS
    WHERE KEY_CODE = 'LEVEL'
    INTO :LEVEL_ID;

    OBJ_ID = NULL;
    IF (LEVEL_ID = 2) THEN
    BEGIN
        SELECT FIRST 1 L2.OBJ_ID
        FROM LINKS L111
        JOIN LINKS L2 ON L2.PARENT_ID = L111.OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
        LEFT JOIN GIA_CODE_GET(L2.OBJ_ID) R ON 1 = 1
        LEFT JOIN VALI V ON V.OBJ_ID = L2.OBJ_ID AND V.PARAM_ID = 1365 AND V.IS_DEL = 0
        WHERE L111.PARENT_ID IS NULL
          AND L111.OBJ_TYPE_ID = 111
          AND L111.DATE_DEL IS NULL
          AND ((:SCHOOL_ID IS NULL) OR (:SCHOOL_ID != L2.OBJ_ID))
          AND ((R.CODE = :CODE_OU) OR (V.VAL = :CODE_PPE))
        INTO :OBJ_ID;
    END
    IF (LEVEL_ID = 3) THEN
    BEGIN
        SELECT FIRST 1 L2.OBJ_ID
        FROM LINKS L112
        JOIN LINKS L111 ON L111.PARENT_ID = L112.OBJ_ID AND L111.OBJ_TYPE_ID = 111 AND L111.DATE_DEL IS NULL
        JOIN LINKS L2 ON L2.PARENT_ID = L111.OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
        LEFT JOIN GIA_CODE_GET(L2.OBJ_ID) R ON 1 = 1
        LEFT JOIN VALI V ON V.OBJ_ID = L2.OBJ_ID AND V.PARAM_ID = 1365 AND V.IS_DEL = 0
        WHERE L112.PARENT_ID IS NULL
          AND L112.OBJ_TYPE_ID = 112
          AND L112.DATE_DEL IS NULL
          AND ((:SCHOOL_ID IS NULL) OR (:SCHOOL_ID != L2.OBJ_ID))
          AND ((R.CODE = :CODE_OU) OR (V.VAL = :CODE_PPE))
        INTO :OBJ_ID;
    END
    IF (:OBJ_ID IS NOT NULL) THEN
    BEGIN
        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:OBJ_ID)
        INTO :CAPTION;

        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GIA_CODES_EXPORT RETURNS (
    OBJ_ID BIGINT,
    CODE BIGINT,
    PPE BIGINT,
    CLASS4 SMALLINT,
    CLASS9 SMALLINT,
    CLASS11 SMALLINT)
AS
BEGIN
    FOR SELECT SCHOOL_ID
        FROM GIA_OU_LIST(0, 1)
        INTO :OBJ_ID
    DO
    BEGIN
        CODE = NULL;
        SELECT CODE
        FROM GIA_CODE_GET(:OBJ_ID)
        INTO :CODE;

        PPE = NULL;
        SELECT V.VAL
        FROM VALI V
        WHERE V.PARAM_ID = 1365
          AND V.OBJ_ID = :OBJ_ID
          AND V.IS_DEL = 0
        INTO :PPE;

        CLASS4 = NULL;
        SELECT V.VAL
        FROM VALI V
        WHERE V.PARAM_ID = 1366
          AND V.OBJ_ID = :OBJ_ID
          AND V.IS_DEL = 0
        INTO :CLASS4;

        CLASS9 = NULL;
        SELECT V.VAL
        FROM VALI V
        WHERE V.PARAM_ID = 1367
          AND V.OBJ_ID = :OBJ_ID
          AND V.IS_DEL = 0
        INTO :CLASS9;

        CLASS11 = NULL;
        SELECT V.VAL
        FROM VALI V
        WHERE V.PARAM_ID = 1368
          AND V.OBJ_ID = :OBJ_ID
          AND V.IS_DEL = 0
        INTO :CLASS11;

        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GIA_CODES_EXPORT_CHECK (
    LEVEL_ID SMALLINT = null)
RETURNS (
    OPR SMALLINT,
    DESC_FIELD VARCHAR(500))
AS
declare variable OBJ_ID bigint;
declare variable CODE bigint;
declare variable PPE bigint;
declare variable CLASS4 smallint;
declare variable CLASS9 smallint;
declare variable CLASS11 smallint;
declare variable SHORTNAME varchar(500);
declare variable VAL integer;
declare variable CYB date;
declare variable CYE date;
declare variable Y smallint;
BEGIN
    Y = EXTRACT(YEAR FROM CURRENT_DATE);
    CYB = Y || '-09-01';
    IF (CURRENT_DATE > CYB) THEN
        Y = Y + 1;
    CYE = Y || '-07-15';

    FOR /*SELECT FIRST 1 L.OBJ_ID
        FROM LINKS L
        WHERE L.PARENT_ID IS NULL
          AND L.OBJ_TYPE_ID = 2
          AND L.DATE_DEL IS NULL
          AND ((:LEVEL_ID IS NULL) OR (:LEVEL_ID < 2))

        UNION      */

        SELECT L2.OBJ_ID
        FROM LINKS L111
        JOIN LINKS L2
        ON L2.PARENT_ID = L111.OBJ_ID
        AND L2.OBJ_TYPE_ID = 2
        AND L2.DATE_DEL IS NULL
        WHERE L111.PARENT_ID IS NULL
        AND L111.OBJ_TYPE_ID = 111
        AND L111.DATE_DEL IS NULL
   /*       AND :LEVEL_ID = 2

        UNION

        SELECT L2.OBJ_ID
        FROM LINKS L112
        JOIN LINKS L111 ON L111.PARENT_ID = L112.OBJ_ID AND L111.OBJ_TYPE_ID = 111 AND L111.DATE_DEL IS NULL
        JOIN LINKS L2 ON L2.PARENT_ID = L111.OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
        WHERE L112.PARENT_ID IS NULL
          AND L112.OBJ_TYPE_ID = 112
          AND L112.DATE_DEL IS NULL
          AND :LEVEL_ID = 3    */

        INTO :OBJ_ID
    DO
    BEGIN
        CODE = NULL;
        SELECT V.VAL
        FROM VALI V
        WHERE V.PARAM_ID = 1364
          AND V.OBJ_ID = :OBJ_ID
          AND V.IS_DEL = 0
        INTO :CODE;

        PPE = NULL;
        SELECT V.VAL
        FROM VALI V
        WHERE V.PARAM_ID = 1365
          AND V.OBJ_ID = :OBJ_ID
          AND V.IS_DEL = 0
        INTO :PPE;

        CLASS4 = NULL;
        SELECT V.VAL
        FROM VALI V
        WHERE V.PARAM_ID = 1366
          AND V.OBJ_ID = :OBJ_ID
          AND V.IS_DEL = 0
        INTO :CLASS4;

        CLASS9 = NULL;
        SELECT V.VAL
        FROM VALI V
        WHERE V.PARAM_ID = 1367
          AND V.OBJ_ID = :OBJ_ID
          AND V.IS_DEL = 0
        INTO :CLASS9;

        CLASS11 = NULL;
        SELECT V.VAL
        FROM VALI V
        WHERE V.PARAM_ID = 1368
          AND V.OBJ_ID = :OBJ_ID
          AND V.IS_DEL = 0
        INTO :CLASS11;

        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:OBJ_ID)
        INTO :SHORTNAME;

        IF (CODE IS NULL) THEN
        BEGIN
            IF ((PPE IS NOT NULL) OR (CLASS4 != 0) OR (CLASS9 != 0) OR (CLASS11 != 0)) THEN
            BEGIN
                DESC_FIELD = SHORTNAME;
                OPR = 1;
                SUSPEND;
            END

            SELECT COUNT(L9.OBJ_ID)

            FROM LINKS L7

            JOIN LINKS L8
            ON L8.PARENT_ID = L7.OBJ_ID
            AND L8.OBJ_TYPE_ID = 8
            AND L8.DATE_DEL IS NULL

            JOIN VALL V49
            ON V49.OBJ_ID = L8.OBJ_ID
            AND V49.PARAM_ID = 49
            AND V49.IS_DEL = 0
            AND V49.LISTVAL_ID IN (47,48)

            JOIN LINKS L9
            ON L9.PARENT_ID = L8.OBJ_ID
            AND L9.OBJ_TYPE_ID IN (9,187)
            AND L9.DATE_DEL IS NULL

            JOIN VALL V
            ON V.OBJ_ID = L9.OBJ_ID
            AND V.PARAM_ID IN (2388,2418)
            AND V.IS_DEL = 0
            AND V.LISTVAL_ID IN (11202, 11203)

            WHERE L7.OBJ_TYPE_ID = 7
            AND L7.PARENT_ID = :OBJ_ID
            AND L7.DATE_DEL IS NULL
            INTO :VAL;

            IF (VAL > 0) THEN
            BEGIN
                DESC_FIELD = SHORTNAME;
                OPR = 2;
                SUSPEND;
            END

            SELECT COUNT(*)
            FROM LINKS L7

            JOIN LINKS L8
            ON L8.PARENT_ID = L7.OBJ_ID
            AND L8.OBJ_TYPE_ID = 8
            AND L8.DATE_DEL IS NULL

            JOIN LINKS L9
            ON L9.PARENT_ID = L8.OBJ_ID
            AND L9.OBJ_TYPE_ID IN (9,187)
            AND L9.DATE_DEL IS NULL

            JOIN LINKS L10
            ON L10.PARENT_ID = L9.OBJ_ID
            AND L10.OBJ_TYPE_ID = 10
            AND L10.DATE_DEL IS NULL

            JOIN LINKS L120
            ON L120.PARENT_ID = L10.OBJ_ID
            AND L120.OBJ_TYPE_ID = 120
            AND L120.DATE_DEL IS NULL

            JOIN VALD V
            ON V.OBJ_ID = L120.OBJ_ID
            AND V.PARAM_ID = 804
            AND V.IS_DEL = 0
            AND (V.VAL >= :CYB)
            AND (V.VAL < :CYE)

            WHERE L7.OBJ_TYPE_ID = 7
            AND L7.PARENT_ID = :OBJ_ID
            AND L7.DATE_DEL IS NULL

            INTO :VAL;

            IF (VAL > 0) THEN
            BEGIN
                DESC_FIELD = SHORTNAME;
                OPR = 3;
                SUSPEND;
            END

            SELECT COUNT(*)

            FROM LINKS L14

            JOIN VALL V
            ON V.OBJ_ID = L14.OBJ_ID
            AND V.PARAM_ID = 1376
            AND V.IS_DEL = 0
            AND V.LISTVAL_ID != 2989

            WHERE L14.PARENT_ID = :OBJ_ID
            AND L14.OBJ_TYPE_ID = 14
            AND L14.DATE_DEL IS NULL

            INTO :VAL;

            IF (VAL > 0) THEN
            BEGIN
                DESC_FIELD = SHORTNAME;
                OPR = 4;
                SUSPEND;
            END
        END

        SELECT COUNT(L2.OBJ_ID)

        FROM LINKS L111

        JOIN LINKS L2
        ON L2.PARENT_ID = L111.OBJ_ID
        AND L2.OBJ_TYPE_ID = 2
        AND L2.DATE_DEL IS NULL
        AND L2.OBJ_ID != :OBJ_ID

        JOIN VALI V
        ON V.PARAM_ID = 1364
        AND V.OBJ_ID = L2.OBJ_ID
        AND V.IS_DEL = 0
        AND V.VAL = :CODE

        WHERE L111.OBJ_TYPE_ID = 111
        AND L111.DATE_DEL IS NULL

        INTO :VAL;

        IF (VAL > 0) THEN
        BEGIN
            DESC_FIELD = CODE;
            OPR = 5;
            SUSPEND;
        END

        SELECT COUNT(L2.OBJ_ID)

        FROM LINKS L111

        JOIN LINKS L2
        ON L2.PARENT_ID = L111.OBJ_ID
        AND L2.OBJ_TYPE_ID = 2
        AND L2.DATE_DEL IS NULL
        AND L2.OBJ_ID != :OBJ_ID

        JOIN VALI V
        ON V.PARAM_ID = 1365
        AND V.OBJ_ID = L2.OBJ_ID
        AND V.IS_DEL = 0
        AND V.VAL = :PPE

        WHERE L111.OBJ_TYPE_ID = 111
        AND L111.DATE_DEL IS NULL

        INTO :VAL;

        IF (VAL > 0) THEN
        BEGIN
            DESC_FIELD = PPE;
            OPR = 6;
            SUSPEND;
        END

        IF (PPE IS NOT NULL) THEN
        BEGIN
            IF (((CLASS4 IS NULL) OR (CLASS4 = 0)) AND ((CLASS9 IS NULL) OR (CLASS9 = 0)) AND ((CLASS11 IS NULL) OR (CLASS11 = 0))) THEN
            BEGIN
                DESC_FIELD = SHORTNAME;
                OPR = 7;
                SUSPEND;
            END
        END

        IF (PPE IS NULL) THEN
        BEGIN
            IF ((CLASS4 != 0) OR (CLASS9 != 0) OR (CLASS11 != 0)) THEN
            BEGIN
                DESC_FIELD = SHORTNAME;
                OPR = 8;
                SUSPEND;
            END
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GIA_CODES_IMPORT (
    OBJ_ID BIGINT,
    CODE BIGINT,
    PPE BIGINT,
    CLASS4 SMALLINT,
    CLASS9 SMALLINT,
    CLASS11 SMALLINT)
RETURNS (
    OPR SMALLINT)
AS
declare variable BLOB_ID bigint;
declare variable SCHOOL_ID bigint;
BEGIN
    OPR = -1;

    SELECT FIRST 1 0
    FROM OBJECTS O
    WHERE O.OBJ_ID = :OBJ_ID
    INTO OPR;

    IF (OPR = -1) THEN
    BEGIN
        SUSPEND;
        EXIT;
    END

    SCHOOL_ID = NULL;

    SELECT FIRST 1 L.OBJ_ID
    FROM LINKS L
    WHERE L.PARENT_ID IS NULL
    AND L.OBJ_TYPE_ID = 2
    AND L.DATE_DEL IS NULL
    INTO :SCHOOL_ID;

    IF ((SCHOOL_ID IS NULL) OR (SCHOOL_ID = OBJ_ID)) THEN
    BEGIN
        OPR = 1;
        IF ((SELECT TYPE_ID FROM OBJECTS WHERE OBJ_ID = :OBJ_ID) <> 124) THEN
        BEGIN
            IF (CODE IS NULL) THEN
            BEGIN
                UPDATE VALI
                SET IS_DEL = 1
                WHERE PARAM_ID = 1364
                AND OBJ_ID = :OBJ_ID;
            END
            ELSE
            BEGIN
                SELECT V.BLOB_ID
                FROM VAL_ADD(1364, :OBJ_ID, :CODE) V
                INTO :BLOB_ID;
    
                OPR = 2;
            END
        END
        IF (PPE IS NULL) THEN
        BEGIN
            UPDATE VALI
            SET IS_DEL = 1
            WHERE PARAM_ID = 1365
            AND OBJ_ID = :OBJ_ID;

            EXECUTE PROCEDURE CLEAR_PPE_ROOMS(:OBJ_ID);
        END
        ELSE
        BEGIN
            SELECT V.BLOB_ID
            FROM VAL_ADD(1365, :OBJ_ID, :PPE) V
            INTO :BLOB_ID;
        END
        IF (CLASS4 IS NOT NULL) THEN
        BEGIN
            SELECT V.BLOB_ID
            FROM VAL_ADD(1366, :OBJ_ID, :CLASS4) V
            INTO :BLOB_ID;
        END
        IF (CLASS9 IS NOT NULL) THEN
        BEGIN
            SELECT V.BLOB_ID
            FROM VAL_ADD(1367, :OBJ_ID, :CLASS9) V
            INTO :BLOB_ID;
        END
        IF (CLASS11 IS NOT NULL) THEN
        BEGIN
            SELECT V.BLOB_ID
            FROM VAL_ADD(1368, :OBJ_ID, :CLASS11) V
            INTO :BLOB_ID;
        END
    END
    ELSE
    BEGIN
        OPR = -1;
    END

    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GIA_CODES_LIST (
    LEVEL_ID INTEGER = null)
RETURNS (
    DISTRICT VARCHAR(500),
    SCHOOL_ID BIGINT,
    SHORTNAME VARCHAR(500),
    CODE_OU INTEGER,
    CODE_PPE INTEGER,
    FOR4 INTEGER,
    FOR9 INTEGER,
    FOR11 INTEGER,
    RESPONSIBLE VARCHAR(500),
    BUILDING VARCHAR(500),
    ADDRESS VARCHAR(500),
    SCHOOLNO INTEGER)
AS
declare variable OBJ_ID bigint;
declare variable DISTRICT_ID bigint;
declare variable ISVPL smallint;
declare variable VAL varchar(500);
BEGIN
    FOR
        SELECT SCHOOL_ID, DISTRICT_ID
        FROM GIA_OU_LIST(0, 1)
        INTO :SCHOOL_ID, :DISTRICT_ID
    DO
    BEGIN
        ADDRESS = NULL;
        IF (SCHOOL_ID IS NOT NULL) THEN
        BEGIN
            SELECT CAPTION FROM OBJECT_CAPTION_GET(:SCHOOL_ID) INTO :SHORTNAME;
            SELECT I FROM VAL_GET(:SCHOOL_ID, 17) INTO :SCHOOLNO;
        END
        ELSE
        BEGIN
            SHORTNAME = NULL;
        END

        IF (DISTRICT_ID IS NOT NULL) THEN
        BEGIN
            SELECT CAPTION FROM OBJECT_CAPTION_GET(:DISTRICT_ID) INTO :DISTRICT;
        END
        ELSE
        BEGIN
            DISTRICT = NULL;
        END

        CODE_OU = NULL;
        SELECT CODE, ISVPL
        FROM GIA_CODE_GET(:SCHOOL_ID)
        INTO :CODE_OU, :ISVPL;

        CODE_PPE = NULL;
        SELECT V.VAL
        FROM VALI V
        WHERE V.PARAM_ID = 1365 AND V.OBJ_ID = :SCHOOL_ID AND V.IS_DEL = 0
        INTO :CODE_PPE;

        FOR4 = NULL;
        SELECT V.VAL
        FROM VALI V
        WHERE V.PARAM_ID = 1366 AND V.OBJ_ID = :SCHOOL_ID AND V.IS_DEL = 0
        INTO :FOR4;

        FOR9 = NULL;
        SELECT V.VAL
        FROM VALI V
        WHERE V.PARAM_ID = 1367 AND V.OBJ_ID = :SCHOOL_ID AND V.IS_DEL = 0
        INTO :FOR9;

        FOR11 = NULL;
        SELECT V.VAL
        FROM VALI V
        WHERE V.PARAM_ID = 1368 AND V.OBJ_ID = :SCHOOL_ID AND V.IS_DEL = 0
        INTO :FOR11;

        OBJ_ID = NULL;
        SELECT V.VAL
        FROM VALR V
        WHERE V.PARAM_ID = 1369 AND V.OBJ_ID = :SCHOOL_ID AND V.IS_DEL = 0
        INTO :OBJ_ID;

        IF (OBJ_ID IS NOT NULL) THEN
        BEGIN
            SELECT CAPTION FROM OBJECT_CAPTION_GET(:OBJ_ID) INTO :RESPONSIBLE;
        END
        ELSE
        BEGIN
            RESPONSIBLE = NULL;
            IF (ISVPL > 0) THEN
            BEGIN
                SELECT V FROM VAL_GET(:SCHOOL_ID, 909) INTO :RESPONSIBLE;

                VAL = NULL;

                SELECT V FROM VAL_GET(:SCHOOL_ID, 910) INTO :VAL;

                RESPONSIBLE = RESPONSIBLE || ' ' || VAL;
                VAL = NULL;

                SELECT V
                FROM VAL_GET(:SCHOOL_ID, 911)
                INTO :VAL;

                IF (VAL IS NOT NULL) THEN
                BEGIN
                    RESPONSIBLE = RESPONSIBLE || ' ' || VAL;
                END

                SELECT VAL FROM ADR_GET(759, :SCHOOL_ID) INTO :ADDRESS;
            END
        END

        OBJ_ID = NULL;

        SELECT V.VAL
        FROM VALR V
        WHERE V.PARAM_ID = 1370 AND V.OBJ_ID = :SCHOOL_ID AND V.IS_DEL = 0
        INTO :OBJ_ID;

        IF (OBJ_ID IS NOT NULL) THEN
        BEGIN
            SELECT CAPTION FROM OBJECT_CAPTION_GET(:OBJ_ID) INTO :BUILDING;
        END
        ELSE
        BEGIN
            BUILDING = NULL;
        END

        IF (ISVPL = 0) THEN
        BEGIN
            SELECT VAL FROM ADR_GET(1371, :SCHOOL_ID) INTO :ADDRESS;
        END

        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GIA_CODES_SET (
    SCHOOL_ID BIGINT NOT NULL,
    RESPONSIBLE_ID BIGINT,
    BUILDING_ID BIGINT)
RETURNS (
    OLD_ROOM_COUNT INTEGER)
AS
DECLARE VARIABLE ROOM_ID BIGINT;
DECLARE VARIABLE BLOB_ID BIGINT;
DECLARE VARIABLE REGION VARCHAR(255);
DECLARE VARIABLE DISTRICT VARCHAR(255);
DECLARE VARIABLE TOWN VARCHAR(255);
DECLARE VARIABLE SETTLEMENT VARCHAR(255);
DECLARE VARIABLE STREET VARCHAR(255);
DECLARE VARIABLE HOUSE VARCHAR(10);
DECLARE VARIABLE CORP VARCHAR(10);
DECLARE VARIABLE LITER VARCHAR(10);
DECLARE VARIABLE FLAT VARCHAR(10);
DECLARE VARIABLE POST_INDEX VARCHAR(20);
DECLARE VARIABLE OLD_BUILDING_ID BIGINT;
BEGIN
    OLD_ROOM_COUNT = 0;

    IF ((RESPONSIBLE_ID IS NOT NULL) AND (RESPONSIBLE_ID <> 0)) THEN
    BEGIN
        SELECT BLOB_ID
        FROM VAL_ADD(1369, :SCHOOL_ID, :RESPONSIBLE_ID)
        INTO :BLOB_ID;
    END

    IF (RESPONSIBLE_ID IS NULL) THEN
    BEGIN
        UPDATE VALR R
        SET R.IS_DEL = 1
        WHERE R.OBJ_ID = :SCHOOL_ID
          AND R.PARAM_ID = 1369;
    END

    SELECT I
    FROM VAL_GET(:SCHOOL_ID, 1370)
    INTO :OLD_BUILDING_ID;

    IF (BUILDING_ID IS NULL) THEN
    BEGIN
        UPDATE VALR R
        SET R.IS_DEL = 1
        WHERE R.OBJ_ID = :SCHOOL_ID
          AND R.PARAM_ID = 1370;
    END

    IF ((BUILDING_ID IS NOT NULL) AND (BUILDING_ID <> 0)) THEN
    BEGIN
        IF ((OLD_BUILDING_ID <> 0) AND (BUILDING_ID <> OLD_BUILDING_ID)) THEN
        BEGIN
            FOR SELECT L61.OBJ_ID
                FROM LINKS L61
                WHERE L61.PARENT_ID = :OLD_BUILDING_ID
                  AND L61.OBJ_TYPE_ID = 61
                  AND L61.DATE_DEL IS NULL
                INTO :ROOM_ID
            DO
            BEGIN
                UPDATE VALS R
                SET R.IS_DEL = 1
                WHERE R.OBJ_ID = :ROOM_ID
                  AND R.PARAM_ID = 1403
                  AND R.IS_DEL = 0;

                IF (ROW_COUNT > 0) THEN
                BEGIN
                    OLD_ROOM_COUNT = OLD_ROOM_COUNT + 1;

                    UPDATE LINKS L122
                    SET L122.DATE_DEL = CURRENT_TIMESTAMP
                    WHERE L122.PARENT_ID = :ROOM_ID
                      AND L122.OBJ_TYPE_ID = 122
                      AND L122.DATE_DEL IS NULL;
                END
            END
        END

        SELECT BLOB_ID
        FROM VAL_ADD(1370, :SCHOOL_ID, :BUILDING_ID)
        INTO :BLOB_ID;

        SELECT REGION, DISTRICT, TOWN, SETTLEMENT, STREET, HOUSE, CORP, LITER, FLAT, POST_INDEX
        FROM ADR_GET(420, :BUILDING_ID)
        INTO :REGION, :DISTRICT, :TOWN, :SETTLEMENT, :STREET, :HOUSE, :CORP, :LITER, :FLAT, :POST_INDEX;

        SELECT BLOB_ID
        FROM ADR_ADD(1371, :SCHOOL_ID, :REGION, :DISTRICT, :TOWN, :SETTLEMENT, :STREET, :HOUSE, :LITER, :CORP, :FLAT, :POST_INDEX)
        INTO :BLOB_ID;
    END

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GIA_CODES_SET_DISTRICT (
    SCHOOL_ID BIGINT NOT NULL,
    CODEOU BIGINT,
    CODEPPE BIGINT,
    PPE4 SMALLINT,
    PPE9 SMALLINT,
    PPE11 SMALLINT)
AS
declare variable BLOB_ID bigint;
BEGIN
    IF (CODEOU IS NOT NULL) THEN
    BEGIN
        SELECT BLOB_ID
        FROM VAL_ADD(1364, :SCHOOL_ID, :CODEOU)
        INTO :BLOB_ID;
    END
    ELSE
    BEGIN
        UPDATE VALI R
        SET R.IS_DEL = 1
        WHERE R.OBJ_ID = :SCHOOL_ID
        AND R.PARAM_ID = 1364;
    END
    IF (CODEPPE IS NOT NULL) THEN
    BEGIN
        SELECT BLOB_ID
        FROM VAL_ADD(1365, :SCHOOL_ID, :CODEPPE)
        INTO :BLOB_ID;
    END
    ELSE
    BEGIN
        UPDATE VALI R
        SET R.IS_DEL = 1
        WHERE R.OBJ_ID = :SCHOOL_ID
        AND R.PARAM_ID = 1365;
    END
    IF (PPE4 IS NOT NULL) THEN
    BEGIN
        SELECT BLOB_ID
        FROM VAL_ADD(1366, :SCHOOL_ID, :PPE4)
        INTO :BLOB_ID;
    END
    IF (PPE9 IS NOT NULL) THEN
    BEGIN
        SELECT BLOB_ID
        FROM VAL_ADD(1367, :SCHOOL_ID, :PPE9)
        INTO :BLOB_ID;
    END
    IF (PPE11 IS NOT NULL) THEN
    BEGIN
        SELECT BLOB_ID
        FROM VAL_ADD(1368, :SCHOOL_ID, :PPE11)
        INTO :BLOB_ID;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GIA_CODE_GET (
    OBJ_ID BIGINT)
RETURNS (
    CODE BIGINT,
    ISVPL SMALLINT)
AS
declare variable OBJ_TYPE bigint;
BEGIN
    ISVPL = 0;
    CODE = NULL;
    OBJ_TYPE = NULL;

    FOR
        SELECT FIRST 1 TYPE_ID
        FROM OBJECTS
        WHERE OBJ_ID = :OBJ_ID
        INTO :OBJ_TYPE
    DO
    BEGIN
        IF (OBJ_TYPE = 124) THEN
        BEGIN
            SELECT FIRST 1 CAST(CAST(LV.COST AS INTEGER) || '999' AS INTEGER)
            FROM VALL L
            JOIN LISTVALS LV
            ON  LV.LISTVAL_ID = L.LISTVAL_ID
            AND LV.LIST_ID = 7
            AND LV.IS_DEL = 0

            WHERE L.OBJ_ID = :OBJ_ID
            AND L.PARAM_ID = 839
            AND L.IS_DEL = 0

            INTO :CODE;

            ISVPL = 1;
        END
        ELSE
        BEGIN
            SELECT FIRST 1 V.VAL
            FROM VALI V
            WHERE V.PARAM_ID = 1364
            AND V.OBJ_ID = :OBJ_ID
            AND V.IS_DEL = 0
            INTO :CODE;
        END
    END
    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GIA_COPY_INFO_EXAM_PARAMS (
    I$PUPIL_ID BIGINT,
    I$CLASS_ID BIGINT,
    I$USER_ID BIGINT)
AS
DECLARE VARIABLE I BIGINT;
DECLARE VARIABLE TYPE_ID BIGINT;
DECLARE VARIABLE PUPIL_TYPE_ID BIGINT;
BEGIN
    SELECT TYPE_ID
    FROM OBJECTS
    WHERE OBJ_ID = :I$CLASS_ID
    INTO :TYPE_ID;

    IF (TYPE_ID NOT IN (9, 125)) THEN
    BEGIN
        EXIT;
    END

    SELECT TYPE_ID
    FROM OBJECTS
    WHERE OBJ_ID = :I$PUPIL_ID
    INTO :PUPIL_TYPE_ID;

    IF (PUPIL_TYPE_ID NOT IN (10, 126)) THEN
    BEGIN
        EXIT;
    END

    I = 0;
    IF (TYPE_ID = 9) THEN
    BEGIN
        SELECT I
        FROM VAL_GET(:I$CLASS_ID, 1613)
        INTO :I;
    END
    ELSE IF (TYPE_ID = 125) THEN
    BEGIN
        SELECT I
        FROM VAL_GET(:I$CLASS_ID, 1633)
        INTO :I;
    END
    
    IF (I <> 0) THEN
    BEGIN
        IF (PUPIL_TYPE_ID = 10) THEN
        BEGIN
            UPDATE OR INSERT INTO VALL (PARAM_ID, OBJ_ID, USER_ID, LISTVAL_ID)
            VALUES (1620, :I$PUPIL_ID, :I$USER_ID, :I);
        END
        ELSE IF (PUPIL_TYPE_ID = 126) THEN
        BEGIN
            UPDATE OR INSERT INTO VALL (PARAM_ID, OBJ_ID, USER_ID, LISTVAL_ID)
            VALUES (1626, :I$PUPIL_ID, :I$USER_ID, :I);
        END
    END
    
    I = 0;
    IF (TYPE_ID = 9) THEN
    BEGIN
        SELECT I
        FROM VAL_GET(:I$CLASS_ID, 1614)
        INTO :I;
    END
    ELSE IF (TYPE_ID = 125) THEN
    BEGIN
        SELECT I
        FROM VAL_GET(:I$CLASS_ID, 1634)
        INTO :I;
    END

    
    IF (I <> 0) THEN
    BEGIN
        IF (PUPIL_TYPE_ID = 10) THEN
        BEGIN
            UPDATE OR INSERT INTO VALL (PARAM_ID, OBJ_ID, USER_ID, LISTVAL_ID)
            VALUES (1622, :I$PUPIL_ID, :I$USER_ID, :I);
        END
        ELSE IF (PUPIL_TYPE_ID = 126) THEN
        BEGIN
            UPDATE OR INSERT INTO VALL (PARAM_ID, OBJ_ID, USER_ID, LISTVAL_ID)
            VALUES (1628, :I$PUPIL_ID, :I$USER_ID, :I);
        END
    END
    
    I = 0;
    IF (TYPE_ID = 9) THEN
    BEGIN
        SELECT I
        FROM VAL_GET(:I$CLASS_ID, 1615)
        INTO :I;
    END
    ELSE IF (TYPE_ID = 125) THEN
    BEGIN
        SELECT I
        FROM VAL_GET(:I$CLASS_ID, 1635)
        INTO :I;
    END
    
    IF (I <> 0) THEN
    BEGIN
        IF (PUPIL_TYPE_ID = 10) THEN
        BEGIN
            UPDATE OR INSERT INTO VALL (PARAM_ID, OBJ_ID, USER_ID, LISTVAL_ID)
            VALUES (1624, :I$PUPIL_ID, :I$USER_ID, :I);
        END
        ELSE IF (PUPIL_TYPE_ID = 126) THEN
        BEGIN
            UPDATE OR INSERT INTO VALL (PARAM_ID, OBJ_ID, USER_ID, LISTVAL_ID)
            VALUES (1629, :I$PUPIL_ID, :I$USER_ID, :I);
        END
    END
    
    I = 0;
    IF (TYPE_ID = 9) THEN
    BEGIN
        SELECT I
        FROM VAL_GET(:I$CLASS_ID, 1617)
        INTO :I;
    END
    ELSE IF (TYPE_ID = 125) THEN
    BEGIN
        SELECT I
        FROM VAL_GET(:I$CLASS_ID, 1637)
        INTO :I;
    END
    
    IF (I <> 0) THEN
    BEGIN
        IF (PUPIL_TYPE_ID = 10) THEN
        BEGIN
            UPDATE OR INSERT INTO VALL (PARAM_ID, OBJ_ID, USER_ID, LISTVAL_ID)
            VALUES (1625, :I$PUPIL_ID, :I$USER_ID, :I);
        END
        ELSE IF (PUPIL_TYPE_ID = 126) THEN
        BEGIN
            UPDATE OR INSERT INTO VALL (PARAM_ID, OBJ_ID, USER_ID, LISTVAL_ID)
            VALUES (1630, :I$PUPIL_ID, :I$USER_ID, :I);
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GIA_EXAM_ATTACH_PPE (
    I$EXAM_ID BIGINT,
    I$STEP_ID BIGINT)
RETURNS (
    SCHOOL_ID BIGINT,
    CODE_OU INTEGER,
    CODE_PPE INTEGER,
    SHORTNAME_PPE VARCHAR(500),
    VMESTIM INTEGER,
    ATTACH_PPE INTEGER,
    ATTACH_RESERVE INTEGER,
    O_N INTEGER)
AS
declare variable V$code_ bigint;
declare variable V$Type_ integer;
begin
  if (:I$step_ID = 2999) then  V$code_ = 1366;
  if (:I$step_ID = 3000) then  V$code_ = 1367;
  if (:I$step_ID = 3162) then  V$code_ = 1368;
  for select SCHOOL_ID
      from GIA_OU_LIST(0,0)
      into :SCHOOL_ID
  do
  begin
    if (:SCHOOL_ID is not null) then
    begin
       CODE_OU = NULL;
        SELECT CODE
        FROM GIA_CODE_GET(:SCHOOL_ID)
        INTO :CODE_OU;

        CODE_PPE = NULL;
        SELECT V.VAL
        FROM VALI V
        WHERE V.PARAM_ID = 1365
          AND V.OBJ_ID = :SCHOOL_ID
          AND V.IS_DEL = 0
        INTO :CODE_PPE;

        V$Type_ = NULL;
        SELECT count(V.VAL)
        FROM VALI V
        WHERE V.PARAM_ID = :V$code_
          AND V.OBJ_ID = :SCHOOL_ID
          AND V.IS_DEL = 0
        INTO :V$type_;
        if (:V$type_ > 0) then
        begin
          SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:SCHOOL_ID)
            INTO :Shortname_ppe;

           Vmestim = 0;
           SELECT case when SUM(V.VAL) is null Then 0 else SUM(V.VAL) end
            FROM links l73
            inner join links l16 on (l73.Obj_id = l16.Parent_id)
            inner join LINKS L61 on (l16.obj_id = l61.parent_id)
            inner join links l122 on (l61.obj_id = l122.Parent_id)
            INNER JOIN VALI V ON V.OBJ_ID = L122.OBJ_ID
            WHERE L73.PARENT_ID = :School_id
              and l73.Obj_type_id = 73
              and l73.Date_del is null
              and l16.Date_del is null
              and l16.obj_type_id = 16
              AND L61.OBJ_TYPE_ID = 61
              AND L61.DATE_DEL IS NULL
              and l122.Obj_type_id = 122
              and l122.Date_del is null
              AND V.PARAM_ID = 1372
              AND V.IS_DEL = 0 into :Vmestim;

          Attach_ppe = 0;
          select count(L.PARENT_ID)
          from LINKS L
          where L.PARENT_TYPE_ID = 2 and
                L.OBJ_ID = :I$EXAM_ID and
                l.Parent_id = :School_id and
              --  l.Obj_type_id = 120 and
                L.DATE_DEL is null
          into :Attach_ppe;

          Attach_reserve = 0;
          select count(L.PARENT_ID)
          from LINKS L
          where L.PARENT_TYPE_ID = 2 and
                L.OBJ_ID = :I$EXAM_ID and
                l.Parent_id = :School_id and
                l.Obj_type_id = 120 and
                L.DATE_DEL is null and
                L.REASON_ID = 1
          into :Attach_reserve;

          O_n = 0;
          suspend;
        end
    end
  end
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GIA_EXAM_ATTACH_PPE_ADD (
    I$EXAM_ID BIGINT,
    I$SCHOOL_ID BIGINT,
    I$ATTACH_PPE INTEGER,
    I$ATTACH_RESERVE INTEGER)
RETURNS (
    LINK_ID BIGINT)
AS
begin
  select first 1 L.LINK_ID
  from LINKS L
  where L.PARENT_TYPE_ID = 2 and
        L.OBJ_ID = :I$EXAM_ID and
        L.PARENT_ID = :I$SCHOOL_ID and
        L.OBJ_TYPE_ID = 120
        -- and L.DATE_DEL is null
  into :LINK_ID;
  if (LINK_ID is not null) then
  begin
    if (I$ATTACH_PPE = 1) then
    begin
      update LINKS L
      set L.DATE_DEL = null,
          L.REASON_ID = :I$ATTACH_RESERVE
      where L.LINK_ID = :LINK_ID;
    end
    else
    begin
      update LINKS L
      set L.DATE_DEL = current_timestamp,
          L.REASON_ID = :I$ATTACH_RESERVE
      where L.LINK_ID = :LINK_ID;
    end
  end
  else
  begin
  if (I$ATTACH_PPE = 1) then
    begin
    insert into LINKS (PARENT_ID, OBJ_ID, REASON_ID, OBJ_TYPE_ID, PARENT_TYPE_ID, DATE_INS)
    values (:I$SCHOOL_ID, :I$EXAM_ID, :I$ATTACH_RESERVE, 120, 2, current_timestamp)
    returning LINK_ID
    into :LINK_ID;
    end
  end
  suspend;
end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GIA_EXAM_DATE_ADD (
    I$YEAR_ID BIGINT,
    I$EXAM_ID BIGINT,
    I$EXAM_CODE INTEGER,
    I$EXAM_STAGE_ID BIGINT,
    I$EXAM_TYPE_ID BIGINT,
    I$EXAM_SUBJECT_ID BIGINT,
    I$EXAM_DATE DATE)
RETURNS (
    EXAM_ID BIGINT)
AS
DECLARE VARIABLE BLOB_ID BIGINT;
BEGIN
    EXAM_ID = I$EXAM_ID;

    IF ((I$EXAM_CODE > 0) AND (I$EXAM_STAGE_ID > 0) AND (I$EXAM_TYPE_ID > 0) AND (I$EXAM_SUBJECT_ID > 0) AND (I$EXAM_DATE IS NOT NULL)) THEN
    BEGIN

        IF (EXAM_ID IS NULL) THEN
        BEGIN
            SELECT OBJ_ID
            FROM OBJECT_ADD(:I$YEAR_ID, 120)
            INTO :EXAM_ID;
        END

        IF (EXAM_ID IS NOT NULL) THEN
        BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD(800, :EXAM_ID, :I$EXAM_CODE)
            INTO :BLOB_ID;

            SELECT BLOB_ID
            FROM VAL_ADD(801, :EXAM_ID, :I$EXAM_STAGE_ID)
            INTO :BLOB_ID;

            SELECT BLOB_ID
            FROM VAL_ADD(802, :EXAM_ID, :I$EXAM_TYPE_ID)
            INTO :BLOB_ID;

            SELECT BLOB_ID
            FROM VAL_ADD(803, :EXAM_ID, :I$EXAM_SUBJECT_ID)
            INTO :BLOB_ID;

            SELECT BLOB_ID
            FROM VAL_ADD(804, :EXAM_ID, :I$EXAM_DATE)
            INTO :BLOB_ID;
        END
    END

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GIA_EXAM_DATE_CHECK (
    I$EXAM_ID BIGINT)
RETURNS (
    PUPIL_COUNT INTEGER,
    MARK_COUNT INTEGER)
AS
BEGIN
    SELECT COUNT(*)
    FROM LINKS L
    WHERE L.PARENT_ID = :I$EXAM_ID
      AND L.OBJ_TYPE_ID = 123
      AND L.DATE_DEL IS NULL
    INTO :MARK_COUNT;

    SELECT COUNT(*)
    FROM LINKS L
    WHERE L.PARENT_TYPE_ID = 10
      AND L.OBJ_ID = :I$EXAM_ID
      AND L.DATE_DEL IS NULL
    INTO :PUPIL_COUNT;


    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GIA_EXAM_DATE_DEL (
    I$EXAM_ID BIGINT)
RETURNS (
    DEL_COUNT INTEGER)
AS
DECLARE VARIABLE OBJ_ID BIGINT;
BEGIN
    UPDATE LINKS L
    SET L.DATE_DEL = CURRENT_TIMESTAMP
    WHERE L.OBJ_ID = :I$EXAM_ID
      AND L.OBJ_TYPE_ID = 120
      AND L.DATE_DEL IS NULL;

    DEL_COUNT = ROW_COUNT;

    FOR SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.PARENT_ID = :I$EXAM_ID
          AND L.OBJ_TYPE_ID = 123
          AND L.DATE_DEL IS NULL
        INTO :OBJ_ID
    DO
    BEGIN
        DEL_COUNT = DEL_COUNT + 1;

        UPDATE LINKS L
        SET L.DATE_DEL = CURRENT_TIMESTAMP
        WHERE L.OBJ_ID = :OBJ_ID
          AND L.OBJ_TYPE_ID = 123
          AND L.DATE_DEL IS NULL;
    END

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GIA_EXAM_DATE_EXPORT RETURNS (
    LINK_ID BIGINT,
    PARENT_ID BIGINT,
    OBJ_ID BIGINT,
    DATE_INS TIMESTAMP,
    DATE_DEL TIMESTAMP,
    EXAM_CODE INTEGER,
    EXAM_STAGE_ID BIGINT,
    EXAM_TYPE_ID BIGINT,
    EXAM_SUBJECT_ID BIGINT,
    EXAM_DATE DATE)
AS
BEGIN
    FOR SELECT L.LINK_ID, L.PARENT_ID, L.OBJ_ID, L.DATE_INS, L.DATE_DEL, V800.VAL, V801.LISTVAL_ID, V802.LISTVAL_ID, V803.LISTVAL_ID, V804.VAL
        FROM LINKS LY
        INNER JOIN LINKS L ON L.PARENT_ID = LY.OBJ_ID
        INNER JOIN VALI V800 ON V800.OBJ_ID = L.OBJ_ID
        INNER JOIN VALL V801 ON V801.OBJ_ID = L.OBJ_ID
        INNER JOIN VALL V802 ON V802.OBJ_ID = L.OBJ_ID
        INNER JOIN VALL V803 ON V803.OBJ_ID = L.OBJ_ID
        INNER JOIN VALD V804 ON V804.OBJ_ID = L.OBJ_ID
        WHERE LY.PARENT_ID = 3866
          AND LY.OBJ_TYPE_ID = 119
          AND L.OBJ_TYPE_ID = 120
          AND V800.PARAM_ID = 800
          AND V800.IS_DEL = 0
          AND V801.PARAM_ID = 801
          AND V801.IS_DEL = 0
          AND V802.PARAM_ID = 802
          AND V802.IS_DEL = 0
          AND V803.PARAM_ID = 803
          AND V803.IS_DEL = 0
          AND V804.PARAM_ID = 804
          AND V804.IS_DEL = 0
        INTO :LINK_ID, :PARENT_ID, :OBJ_ID, :DATE_INS, :DATE_DEL, :EXAM_CODE, :EXAM_STAGE_ID, :EXAM_TYPE_ID, :EXAM_SUBJECT_ID, :EXAM_DATE
    DO
        SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GIA_EXAM_DATE_EXPORT_CHECK (
    I$USER_ID BIGINT)
RETURNS (
    OPR INTEGER,
    YEAR_CAPTION VARCHAR(20),
    VAL VARCHAR(4000))
AS
declare variable YEAR_ID bigint;
declare variable EXAM_ID bigint;
declare variable LANG_CODE varchar(2);
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :LANG_CODE;

    OPR = 0;
    YEAR_CAPTION = '';
    VAL = '';

    FOR
        SELECT L.OBJ_ID, R.VAL

        FROM LINKS L
        JOIN VALL V742
        ON V742.OBJ_ID = L.OBJ_ID
        JOIN LISTVALS LV
        ON LV.LISTVAL_ID = V742.LISTVAL_ID

        LEFT JOIN RES_GET(LV.RES_ID,  :LANG_CODE) R ON 1=1

        WHERE L.PARENT_ID = 3866
        AND L.OBJ_TYPE_ID = 119
        AND V742.PARAM_ID = 742
        AND V742.IS_DEL = 0

        ORDER BY LV.SORT_ORDER
        INTO :YEAR_ID, :YEAR_CAPTION
    DO
    BEGIN
        FOR
            SELECT FIRST 1 G.EXAM_CODE
            FROM GIA_EXAM_DATE_EXPORT G
            JOIN GIA_EXAM_DATE_EXPORT H
            ON G.EXAM_CODE = H.EXAM_CODE
            AND G.OBJ_ID <> H.OBJ_ID

            WHERE G.PARENT_ID = :YEAR_ID
            AND G.DATE_DEL IS NULL
            AND H.PARENT_ID = :YEAR_ID
            AND H.DATE_DEL IS NULL
            INTO :VAL
        DO
        BEGIN
            OPR = 1;

            SUSPEND;

            EXIT;
        END

        FOR
            SELECT FIRST 1 G.OBJ_ID
            FROM GIA_EXAM_DATE_EXPORT G

            JOIN GIA_EXAM_DATE_EXPORT H
            ON G.EXAM_STAGE_ID = H.EXAM_STAGE_ID
            AND G.EXAM_TYPE_ID = H.EXAM_TYPE_ID
            AND G.EXAM_SUBJECT_ID = H.EXAM_SUBJECT_ID
            AND G.EXAM_DATE = H.EXAM_DATE
            AND G.OBJ_ID <> H.OBJ_ID

            WHERE G.PARENT_ID = :YEAR_ID
            AND G.DATE_DEL IS NULL
            AND H.PARENT_ID = :YEAR_ID
            AND H.DATE_DEL IS NULL
            INTO :EXAM_ID
        DO
        BEGIN
            OPR = 2;

            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:EXAM_ID)
            INTO :VAL;

            SUSPEND;

            EXIT;
        END
    END

    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GIA_EXAM_DATE_GET (
    I$YEAR_ID BIGINT,
    I$STEP_ID BIGINT,
    I$STAGE_ID BIGINT)
RETURNS (
    DATE_ID DATE,
    DATE_CAPTION VARCHAR(10))
AS
DECLARE VARIABLE V$C INTEGER;
begin
  select count(distinct VD.VAL)
  from LINKS L
  join VALL V801 on V801.OBJ_ID = L.OBJ_ID
  join VALD VD on VD.OBJ_ID = L.OBJ_ID
  where L.PARENT_ID = :I$YEAR_ID and
        L.OBJ_TYPE_ID = 120 and
        L.DATE_DEL is null and
        V801.PARAM_ID = 801 and
        V801.IS_DEL = 0 and
        V801.LISTVAL_ID = :I$STEP_ID and
        VD.PARAM_ID = 804 and
        VD.IS_DEL = 0
  into :V$C;
  if (V$C > 0) then
  begin
    DATE_ID = '2000-01-01';
    DATE_CAPTION = 'Все дни';
    suspend;
  end
  if (I$STAGE_ID = -1) then
  begin
    for select distinct VD.VAL, VD.VAL
        from LINKS L
        join VALL V801 on V801.OBJ_ID = L.OBJ_ID
        join VALD VD on VD.OBJ_ID = L.OBJ_ID
        where L.PARENT_ID = :I$YEAR_ID and
              L.OBJ_TYPE_ID = 120 and
              L.DATE_DEL is null and
              V801.PARAM_ID = 801 and
              V801.IS_DEL = 0 and
              V801.LISTVAL_ID = :I$STEP_ID and
              VD.PARAM_ID = 804 and
              VD.IS_DEL = 0
        order by VD.VAL desc
        into :DATE_ID, :DATE_CAPTION
    do
      suspend;
  end
  else
  begin
    for select distinct VD.VAL, VD.VAL
        from LINKS L
        inner join VALL V801 on V801.OBJ_ID = L.OBJ_ID
        inner join VALL V802 on V802.OBJ_ID = L.OBJ_ID
        inner join VALD VD on VD.OBJ_ID = L.OBJ_ID
        where L.PARENT_ID = :I$YEAR_ID and
              L.OBJ_TYPE_ID = 120 and
              L.DATE_DEL is null and
              V802.PARAM_ID = 802 and
              V802.IS_DEL = 0 and
              V802.LISTVAL_ID = :I$STAGE_ID and
              V801.PARAM_ID = 801 and
              V801.IS_DEL = 0 and
              V801.LISTVAL_ID = :I$STEP_ID and
              VD.PARAM_ID = 804 and
              VD.IS_DEL = 0
        order by VD.VAL desc
        into :Date_ID,  :DATE_CAPTION
    do
      suspend;
  end
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GIA_EXAM_DATE_IMPORT (
    LINK_ID BIGINT,
    PARENT_ID BIGINT,
    OBJ_ID BIGINT,
    DATE_INS TIMESTAMP,
    DATE_DEL TIMESTAMP,
    EXAM_CODE INTEGER,
    EXAM_STAGE_ID BIGINT,
    EXAM_TYPE_ID BIGINT,
    EXAM_SUBJECT_ID BIGINT,
    EXAM_DATE DATE)
RETURNS (
    OPR INTEGER,
    VAL VARCHAR(4000))
AS
declare variable BLOB_ID bigint;
BEGIN
    OPR = 0;/* 0 - equal, 1 - edit, 2 - add, 3 - del */
    VAL = '';

    BLOB_ID = 0;
    SELECT COUNT(*)
    FROM OBJECTS
    WHERE OBJ_ID = :OBJ_ID
    INTO :BLOB_ID;

    IF (BLOB_ID = 0) THEN
    BEGIN
        OPR = 2;

        INSERT INTO OBJECTS (OBJ_ID, TYPE_ID)
        VALUES (:OBJ_ID, 120);

        UPDATE OR INSERT INTO LINKS (LINK_ID, PARENT_ID, OBJ_ID, DATE_INS, DATE_DEL)
        VALUES (:LINK_ID, :PARENT_ID, :OBJ_ID, :DATE_INS, :DATE_DEL)
        MATCHING (LINK_ID);

        SELECT V.BLOB_ID
        FROM VAL_ADD(800, :OBJ_ID, :EXAM_CODE) V
        INTO :BLOB_ID;

        SELECT V.BLOB_ID
        FROM VAL_ADD(801, :OBJ_ID, :EXAM_STAGE_ID) V
        INTO :BLOB_ID;

        SELECT V.BLOB_ID
        FROM VAL_ADD(802, :OBJ_ID, :EXAM_TYPE_ID) V
        INTO :BLOB_ID;

        SELECT V.BLOB_ID
        FROM VAL_ADD(803, :OBJ_ID, :EXAM_SUBJECT_ID) V
        INTO :BLOB_ID;

        SELECT V.BLOB_ID
        FROM VAL_ADD(804, :OBJ_ID, :EXAM_DATE) V
        INTO :BLOB_ID;

        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:OBJ_ID)
        INTO :VAL;
    END
    ELSE
    BEGIN

        -- 15.12.2016 Проверяем, является ли найденный объект записью экзамена
        SELECT TYPE_ID
        FROM OBJECTS
        WHERE OBJ_ID = :OBJ_ID
        INTO :BLOB_ID;

        IF(BLOB_ID <> 120) THEN EXCEPTION DATA_ERROR 'Системная ошибка. Нарушение в нумерации дат экзаменов. Следует немедленно связаться с региональным координатором.';

        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:OBJ_ID)
        INTO :VAL;

        IF (DATE_DEL IS NULL) THEN
        BEGIN
            SELECT COUNT(*)
            FROM LINKS L
            WHERE LINK_ID = :LINK_ID AND DATE_DEL IS NULL
            INTO :BLOB_ID;

            -- Нет такого линка ? Проверяем наличие линка год-экзамен, и прибиваем его
            IF (BLOB_ID = 0) THEN
            BEGIN
                IF(EXISTS(
                    SELECT FIRST 1 1
                    FROM LINKS
                    WHERE PARENT_ID = :PARENT_ID AND OBJ_ID = :OBJ_ID
                ))
                THEN
                BEGIN
                    UPDATE LINKS
                    SET DATE_DEL = CURRENT_TIMESTAMP
                    WHERE PARENT_ID = :PARENT_ID AND OBJ_ID = :OBJ_ID AND DATE_DEL IS NULL;
                END
                ELSE OPR = 2;
            END

            UPDATE OR INSERT INTO LINKS (LINK_ID, PARENT_ID, OBJ_ID, DATE_INS, DATE_DEL)
            VALUES (:LINK_ID, :PARENT_ID, :OBJ_ID, :DATE_INS, :DATE_DEL)
            MATCHING (LINK_ID);

            SELECT COUNT(*)
            FROM VALI V
            WHERE V.PARAM_ID = 800 AND V.OBJ_ID = :OBJ_ID AND V.VAL = :EXAM_CODE AND V.IS_DEL = 0
            INTO :BLOB_ID;

            IF (BLOB_ID = 0) THEN
            BEGIN
                SELECT V.BLOB_ID
                FROM VAL_ADD(800, :OBJ_ID, :EXAM_CODE) V
                INTO :BLOB_ID;
                OPR = 1;
            END

            SELECT COUNT(*)
            FROM VALL V
            WHERE V.PARAM_ID = 801 AND V.OBJ_ID = :OBJ_ID AND V.LISTVAL_ID = :EXAM_STAGE_ID AND V.IS_DEL = 0
            INTO :BLOB_ID;

            IF (BLOB_ID = 0) THEN
            BEGIN
                SELECT V.BLOB_ID
                FROM VAL_ADD(801, :OBJ_ID, :EXAM_STAGE_ID) V
                INTO :BLOB_ID;
                OPR = 1;
            END

            SELECT COUNT(*)
            FROM VALL V
            WHERE V.PARAM_ID = 802 AND V.OBJ_ID = :OBJ_ID AND V.LISTVAL_ID = :EXAM_TYPE_ID AND V.IS_DEL = 0
            INTO :BLOB_ID;

            IF (BLOB_ID = 0) THEN
            BEGIN
                SELECT V.BLOB_ID
                FROM VAL_ADD(802, :OBJ_ID, :EXAM_TYPE_ID) V
                INTO :BLOB_ID;
                OPR = 1;
            END

            SELECT COUNT(*)
            FROM VALL V
            WHERE V.PARAM_ID = 803 AND V.OBJ_ID = :OBJ_ID AND V.LISTVAL_ID = :EXAM_SUBJECT_ID AND V.IS_DEL = 0
            INTO :BLOB_ID;

            IF (BLOB_ID = 0) THEN
            BEGIN
                SELECT V.BLOB_ID
                FROM VAL_ADD(803, :OBJ_ID, :EXAM_SUBJECT_ID) V
                INTO :BLOB_ID;
                OPR = 1;
            END

            SELECT COUNT(*)
            FROM VALD V
            WHERE V.PARAM_ID = 804 AND V.OBJ_ID = :OBJ_ID AND V.VAL = :EXAM_DATE AND V.IS_DEL = 0
            INTO :BLOB_ID;

            IF (BLOB_ID = 0) THEN
            BEGIN
                SELECT V.BLOB_ID
                FROM VAL_ADD(804, :OBJ_ID, :EXAM_DATE) V
                INTO :BLOB_ID;
                OPR = 1;
            END

            IF ((OPR = 1) OR (OPR = 2)) THEN
            BEGIN
                SELECT :VAL || ' -> ' || CAPTION
                FROM OBJECT_CAPTION_GET(:OBJ_ID)
                INTO :VAL;
            END
        END
        ELSE
        BEGIN
            SELECT DEL_COUNT
            FROM GIA_EXAM_DATE_DEL(:OBJ_ID)
            INTO :BLOB_ID;

            IF (BLOB_ID > 0) THEN OPR = 3;
        END
    END

    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GIA_EXAM_DATE_IMPORT_XML (
    YEAR_ID BIGINT,
    EXAM_CODE INTEGER,
    EXAM_STAGE INTEGER,
    EXAM_TYPE INTEGER,
    EXAM_SUBJECT INTEGER,
    EXAM_DATE DATE)
RETURNS (
    OPR INTEGER,
    VAL VARCHAR(4000))
AS
declare variable BLOB_ID bigint;
declare variable EXAM_ID bigint;
declare variable EXAM_STAGE_ID bigint;
declare variable EXAM_TYPE_ID bigint;
declare variable EXAM_SUBJECT_ID bigint;
declare variable V$GEN_BASE bigint;
declare variable V$GEN_MASK bigint;
declare variable S varchar(10);
declare variable V$SIG varchar(1000);
BEGIN
    OPR = 0;/* -1 - error, 0 - equal, 1 - edit, 2 - add */
    VAL = '';
    EXAM_STAGE_ID = NULL;
    EXAM_TYPE_ID = NULL;
    EXAM_SUBJECT_ID = NULL;

    SELECT LV.LISTVAL_ID
    FROM LISTVALS LV
    WHERE LV.LIST_ID = 219 AND LV.COST = :EXAM_STAGE
    INTO :EXAM_STAGE_ID;

    -- Добавление 05.10.2017 - выбор подраздела только в пределах основной сетки (для ГИА9 будут дублирующиеся коды)
    -- тип экзамена 3168 переезжает в ГИА9, для ГИА11 добавляется новый код
    IF (EXISTS (SELECT FIRST(1) 1 FROM GIA_EXAM_YEAR_GET(1) WHERE YEAR_CAPTION = '2016-2017' AND YEAR_ID < :YEAR_ID)) THEN
    BEGIN
      SELECT LV.LISTVAL_ID
      FROM LISTVALS LV
      WHERE LV.LIST_ID = 218 AND LV.COST = :EXAM_TYPE
          AND (
              -- 4 классы
              (:EXAM_STAGE = 1 AND LV."FILTER" = 'LIST219_ID2999') OR
              -- 9 классы
              (:EXAM_STAGE = 2 AND LV."FILTER" = 'LIST219_ID3000') OR
              -- выпускные классы
              (:EXAM_STAGE = 3 AND LV."FILTER" = 'LIST219_ID3162')
          )
      INTO :EXAM_TYPE_ID;
    end
    ELSE BEGIN
      SELECT LV.LISTVAL_ID
      FROM LISTVALS LV
      WHERE LV.LIST_ID = 218 AND LV.COST = :EXAM_TYPE AND LV.LISTVAL_ID <= 3168
      INTO :EXAM_TYPE_ID;
    END

    SELECT LV.LISTVAL_ID
    FROM LISTVALS LV
    WHERE LV.LIST_ID = 212 AND LV.TAG != 'FL' AND LV.TAG = :EXAM_SUBJECT
    INTO :EXAM_SUBJECT_ID;

    IF ((:EXAM_CODE IS NULL) OR (EXAM_STAGE_ID IS NULL) OR (EXAM_TYPE_ID IS NULL) OR (EXAM_SUBJECT_ID IS NULL) OR (:EXAM_DATE IS NULL)) THEN
    BEGIN
        OPR = -1;
        SUSPEND;
        EXIT;
    END

    SELECT FIRST 1 L.OBJ_ID
    FROM LINKS L
    JOIN VALI V ON V.OBJ_ID = L.OBJ_ID AND V.PARAM_ID = 800 AND V.IS_DEL = 0 AND V.VAL = :EXAM_CODE
    WHERE L.PARENT_ID = :YEAR_ID AND L.OBJ_TYPE_ID = 120 AND L.DATE_DEL IS NULL
    INTO :EXAM_ID;

    IF (EXAM_ID IS NULL) THEN
    BEGIN
        -- Проверяем, не переполнился ли опять GEN_ID, чтобы ID экзаменов не уехали в район
        SELECT G.GEN, G.MULTIPLIER
        FROM GEN G
        INTO :V$GEN_BASE, :V$GEN_MASK;

        IF(V$GEN_BASE >= V$GEN_MASK) THEN EXCEPTION DATA_ERROR 'Критическая ошибка: переполнился генератор ID объектов. Требуется ручное вмешательство.';

        SELECT O.OBJ_ID
        FROM OBJECT_ADD(:YEAR_ID, 120) O
        INTO :EXAM_ID;

        SELECT V.BLOB_ID
        FROM VAL_ADD(800, :EXAM_ID, :EXAM_CODE) V
        INTO :BLOB_ID;

        SELECT V.BLOB_ID
        FROM VAL_ADD(801, :EXAM_ID, :EXAM_STAGE_ID) V
        INTO :BLOB_ID;

        SELECT V.BLOB_ID
        FROM VAL_ADD(802, :EXAM_ID, :EXAM_TYPE_ID) V
        INTO :BLOB_ID;

        SELECT V.BLOB_ID
        FROM VAL_ADD(803, :EXAM_ID, :EXAM_SUBJECT_ID) V
        INTO :BLOB_ID;

        SELECT V.BLOB_ID
        FROM VAL_ADD(804, :EXAM_ID, :EXAM_DATE) V
        INTO :BLOB_ID;

        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:EXAM_ID)
        INTO :VAL;

        OPR = 2;
    END
    ELSE
    BEGIN
        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:EXAM_ID)
        INTO :VAL;

        SELECT COUNT(*)
        FROM VALL V
        WHERE V.PARAM_ID = 801 AND V.OBJ_ID = :EXAM_ID AND V.LISTVAL_ID = :EXAM_STAGE_ID AND V.IS_DEL = 0
        INTO :BLOB_ID;

        IF (BLOB_ID = 0) THEN
        BEGIN
            SELECT V.BLOB_ID
            FROM VAL_ADD(801, :EXAM_ID, :EXAM_STAGE_ID) V
            INTO :BLOB_ID;
            OPR = 1;
        END

        SELECT COUNT(*)
        FROM VALL V
        WHERE V.PARAM_ID = 802 AND V.OBJ_ID = :EXAM_ID AND V.LISTVAL_ID = :EXAM_TYPE_ID AND V.IS_DEL = 0
        INTO :BLOB_ID;

        IF (BLOB_ID = 0) THEN
        BEGIN
            SELECT V.BLOB_ID
            FROM VAL_ADD(802, :EXAM_ID, :EXAM_TYPE_ID) V
            INTO :BLOB_ID;
            OPR = 1;
        END

        SELECT COUNT(*)
        FROM VALL V
        WHERE V.PARAM_ID = 803 AND V.OBJ_ID = :EXAM_ID AND V.LISTVAL_ID = :EXAM_SUBJECT_ID AND V.IS_DEL = 0
        INTO :BLOB_ID;

        IF (BLOB_ID = 0) THEN
        BEGIN
            SELECT V.BLOB_ID
            FROM VAL_ADD(803, :EXAM_ID, :EXAM_SUBJECT_ID) V
            INTO :BLOB_ID;
            OPR = 1;
        END

        SELECT COUNT(*)
        FROM VALD V
        WHERE V.PARAM_ID = 804 AND V.OBJ_ID = :EXAM_ID AND V.VAL = :EXAM_DATE AND V.IS_DEL = 0
        INTO :BLOB_ID;

        IF (BLOB_ID = 0) THEN
        BEGIN
            SELECT V.BLOB_ID
            FROM VAL_ADD(804, :EXAM_ID, :EXAM_DATE) V
            INTO :BLOB_ID;
            OPR = 1;
        END

        IF (OPR = 1) THEN
        BEGIN
            SELECT :VAL || ' -> ' || CAPTION
            FROM OBJECT_CAPTION_GET(:EXAM_ID)
            INTO :VAL;
        END
    END

    -- Переформируем сигнатуру года при любых изменениях, формат сигнатуры DDMMYYYYHHNNSS
    IF(OPR > 0) THEN
    BEGIN

        V$SIG = '';
        S = EXTRACT(DAY FROM CURRENT_TIMESTAMP);
        IF(CHAR_LENGTH(S) = 1) THEN S = '0' || S;
        V$SIG = V$SIG || S;
        S = EXTRACT(MONTH FROM CURRENT_TIMESTAMP);
        IF(CHAR_LENGTH(S) = 1) THEN S = '0' || S;
        V$SIG = V$SIG || S;
        S = EXTRACT(YEAR FROM CURRENT_TIMESTAMP);
        V$SIG = V$SIG || S;
        S = EXTRACT(HOUR FROM CURRENT_TIMESTAMP);
        IF(CHAR_LENGTH(S) = 1) THEN S = '0' || S;
        V$SIG = V$SIG || S;
        S = EXTRACT(MINUTE FROM CURRENT_TIMESTAMP);
        IF(CHAR_LENGTH(S) = 1) THEN S = '0' || S;
        V$SIG = V$SIG || S;
        S = EXTRACT(SECOND FROM CURRENT_TIMESTAMP);
        IF(POSITION('.', S) > 0) THEN S = SUBSTRING(S FROM 1 FOR POSITION('.', S) - 1);
        IF(CHAR_LENGTH(S) = 1) THEN S = '0' || S;
        V$SIG = V$SIG || S;

        SELECT V.BLOB_ID
        FROM VAL_ADD(2930, :YEAR_ID, :V$SIG) V
        INTO :BLOB_ID;

    END

    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GIA_EXAM_DATE_LIST (
    I$YEAR_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    EXAM_ID BIGINT,
    EXAM_CODE INTEGER,
    EXAM_STAGE_ID BIGINT,
    EXAM_TYPE_ID BIGINT,
    EXAM_SUBJECT_ID BIGINT,
    EXAM_DATE DATE,
    EXAM_STAGE VARCHAR(255),
    EXAM_TYPE VARCHAR(255),
    EXAM_SUBJECT VARCHAR(255),
    EXAM_STAGE_ID_EX BIGINT,
    EXAM_TYPE_ID_EX BIGINT,
    EXAM_SUBJECT_ID_EX BIGINT)
AS
DECLARE VARIABLE LANG_CODE VARCHAR(2);
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :LANG_CODE;

    FOR
      SELECT L.OBJ_ID, V800.VAL, V801.LISTVAL_ID, V802.LISTVAL_ID, V803.LISTVAL_ID, V804.VAL, R1.VAL, R2.VAL, R3.VAL, CAST(LV2.COST AS INTEGER), CAST(LV3.TAG AS INTEGER)
      FROM LINKS L
      JOIN VALI V800 ON V800.OBJ_ID = L.OBJ_ID AND V800.PARAM_ID = 800 AND V800.IS_DEL = 0
      JOIN VALL V801 ON V801.OBJ_ID = L.OBJ_ID AND V801.PARAM_ID = 801 AND V801.IS_DEL = 0
      JOIN VALL V802 ON V802.OBJ_ID = L.OBJ_ID AND V802.PARAM_ID = 802 AND V802.IS_DEL = 0
      JOIN VALL V803 ON V803.OBJ_ID = L.OBJ_ID AND V803.PARAM_ID = 803 AND V803.IS_DEL = 0
      JOIN VALD V804 ON V804.OBJ_ID = L.OBJ_ID AND V804.PARAM_ID = 804 AND V804.IS_DEL = 0
      JOIN LISTVALS LV1 ON LV1.LISTVAL_ID = V801.LISTVAL_ID
      JOIN LISTVALS LV2 ON LV2.LISTVAL_ID = V802.LISTVAL_ID
      JOIN LISTVALS LV3 ON LV3.LISTVAL_ID = V803.LISTVAL_ID
      LEFT JOIN RES_GET(LV1.RES_ID, :LANG_CODE) R1 ON 1=1
      LEFT JOIN RES_GET(LV2.RES_ID, :LANG_CODE) R2 ON 1=1
      LEFT JOIN RES_GET(LV3.RES_ID, :LANG_CODE) R3 ON 1=1
      WHERE L.PARENT_ID = :I$YEAR_ID AND L.OBJ_TYPE_ID = 120 AND L.DATE_DEL IS NULL
      ORDER BY V804.VAL
      INTO :EXAM_ID, :EXAM_CODE, :EXAM_STAGE_ID, :EXAM_TYPE_ID, :EXAM_SUBJECT_ID, :EXAM_DATE, :EXAM_STAGE, :EXAM_TYPE, :EXAM_SUBJECT, :EXAM_TYPE_ID_EX, :EXAM_SUBJECT_ID_EX
    DO
    BEGIN
      IF(EXAM_STAGE_ID = 2999) THEN EXAM_STAGE_ID_EX = 1;
      ELSE IF(EXAM_STAGE_ID = 3000) THEN EXAM_STAGE_ID_EX = 2;
      ELSE EXAM_STAGE_ID_EX = 3;

      SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GIA_EXAM_GET (
    I$EXAM_CODE INTEGER,
    I$LEVEL_CODE BIGINT,
    I$SUBJ_CODE VARCHAR(400),
    I$EXAM_TYPE FLOAT,
    I$EXAM_DATE DATE)
RETURNS (
    EXAM_ID BIGINT,
    EXAM_DATE DATE,
    EXAM_IMPORT_DATE DATE)
AS
BEGIN
  
  -- Добавление 05.10.2017 - выбор подраздела только в пределах основной сетки (для ГИА9 будут дублирующиеся коды)
  -- тип экзамена 3168 переезжает в ГИА9, для ГИА11 добавляется новый код
  IF (I$EXAM_DATE > '2017-09-01') THEN
  BEGIN
    FOR
      select L120.OBJ_ID, P804.VAL, P2737.VAL
        from LINKS L120
        join VALI P800 on P800.OBJ_ID = L120.OBJ_ID and P800.PARAM_ID = 800 and P800.IS_DEL = 0 and P800.VAL = :I$EXAM_CODE
        join VALL P801 on P801.OBJ_ID = L120.OBJ_ID and P801.PARAM_ID = 801 and P801.IS_DEL = 0 and P801.LISTVAL_ID = :I$LEVEL_CODE
        join VALL P803 on P803.OBJ_ID = L120.OBJ_ID and P803.PARAM_ID = 803 and P803.IS_DEL = 0
        join LISTVALS L803 on L803.LISTVAL_ID = P803.LISTVAL_ID and L803.TAG = :I$SUBJ_CODE
        
        join VALL P802 on P802.OBJ_ID = L120.OBJ_ID and P802.PARAM_ID = 802 and P802.IS_DEL = 0
        join LISTVALS L802 on L802.LISTVAL_ID = P802.LISTVAL_ID and L802.COST = :I$EXAM_TYPE
          AND (
              -- 4 классы
              (:I$LEVEL_CODE = 2999 AND L802."FILTER" = 'LIST219_ID2999') OR
              -- 9 классы
              (:I$LEVEL_CODE = 3000 AND L802."FILTER" = 'LIST219_ID3000') OR
              -- выпускные классы
              (:I$LEVEL_CODE = 3162 AND L802."FILTER" = 'LIST219_ID3162')
          )
        
        join VALD P804 on P804.OBJ_ID = L120.OBJ_ID and P804.PARAM_ID = 804 and P804.IS_DEL = 0 and P804.VAL = :I$EXAM_DATE
        left join VALD P2737 on P2737.OBJ_ID = L120.OBJ_ID and P2737.PARAM_ID = 2737 and P2737.IS_DEL = 0
        where L120.PARENT_TYPE_ID = 119 and L120.OBJ_TYPE_ID = 120 and L120.DATE_DEL is null
      INTO :EXAM_ID,
           :EXAM_DATE,
           :EXAM_IMPORT_DATE
    DO
    BEGIN
      SUSPEND;
    END
  END
  ELSE BEGIN
    FOR
      select L120.OBJ_ID, P804.VAL, P2737.VAL
        from LINKS L120
        join VALI P800 on P800.OBJ_ID = L120.OBJ_ID and P800.PARAM_ID = 800 and P800.IS_DEL = 0 and P800.VAL = :I$EXAM_CODE
        join VALL P801 on P801.OBJ_ID = L120.OBJ_ID and P801.PARAM_ID = 801 and P801.IS_DEL = 0 and P801.LISTVAL_ID = :I$LEVEL_CODE
        join VALL P803 on P803.OBJ_ID = L120.OBJ_ID and P803.PARAM_ID = 803 and P803.IS_DEL = 0
        join LISTVALS L803 on L803.LISTVAL_ID = P803.LISTVAL_ID and L803.TAG = :I$SUBJ_CODE

        join VALL P802 on P802.OBJ_ID = L120.OBJ_ID and P802.PARAM_ID = 802 and P802.IS_DEL = 0
        join LISTVALS L802 on L802.LISTVAL_ID = P802.LISTVAL_ID and L802.COST = :I$EXAM_TYPE
          AND L802.LISTVAL_ID <= 3168
        
        join VALD P804 on P804.OBJ_ID = L120.OBJ_ID and P804.PARAM_ID = 804 and P804.IS_DEL = 0 and P804.VAL = :I$EXAM_DATE
        left join VALD P2737 on P2737.OBJ_ID = L120.OBJ_ID and P2737.PARAM_ID = 2737 and P2737.IS_DEL = 0
        where L120.PARENT_TYPE_ID = 119 and L120.OBJ_TYPE_ID = 120 and L120.DATE_DEL is null
      INTO :EXAM_ID,
           :EXAM_DATE,
           :EXAM_IMPORT_DATE
    DO
    BEGIN
      SUSPEND;
    END
  END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GIA_EXAM_PERMIT_ADD (
    I$PUPIL_ID BIGINT,
    I$EXAM_PERMIT SMALLINT,
    I$USER_ID BIGINT)
AS
declare variable V$TYPE_ID bigint;
declare variable V$BLOB_ID bigint;
BEGIN
    SELECT TYPE_ID
    FROM OBJECTS
    WHERE OBJ_ID = :I$PUPIL_ID
    INTO V$TYPE_ID;
    IF(V$TYPE_ID = 10) THEN
    BEGIN
        SELECT BLOB_ID
        FROM VAL_ADD(2155, :I$PUPIL_ID, IIF(:I$EXAM_PERMIT = 1,2,3), :I$USER_ID)
        INTO :V$BLOB_ID;
    END
    ELSE IF(V$TYPE_ID = 126) THEN
    BEGIN
        SELECT BLOB_ID
        FROM VAL_ADD(2160, :I$PUPIL_ID, IIF(:I$EXAM_PERMIT = 1,2,3), :I$USER_ID)
        INTO :V$BLOB_ID;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GIA_EXAM_PPE_LIST (
    I$YEAR_ID BIGINT,
    I$STEP BIGINT,
    I$STAGE BIGINT,
    I$DATE DATE,
    I$SUBJECT BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    STAGE_ID BIGINT,
    STAGE_NAME VARCHAR(200),
    SUBJ_ID BIGINT,
    SUBJ_NAME VARCHAR(200),
    DATE_EXAM VARCHAR(10),
    PARTAKER INTEGER,
    VMESTIM INTEGER,
    PPE INTEGER,
    RESERVE INTEGER,
    O_N INTEGER)
AS
declare variable LANG_CODE varchar(2);
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :LANG_CODE;

  IF (:I$STAGE = -1) THEN
  BEGIN
    IF (:I$DATE = '2000-01-01') THEN
    BEGIN
      IF (:I$SUBJECT = -1) THEN
      BEGIN
        FOR SELECT DISTINCT L.OBJ_ID, V802.LISTVAL_ID, R802.VAL, V803.LISTVAL_ID, R803.VAL, VD.VAL
            FROM LINKS L
            INNER JOIN VALL V801 ON V801.OBJ_ID = L.OBJ_ID
            INNER JOIN VALL V802 ON V802.OBJ_ID = L.OBJ_ID
            INNER JOIN VALD VD ON VD.OBJ_ID = L.OBJ_ID
            INNER JOIN VALL V803 ON V803.OBJ_ID = L.OBJ_ID
            INNER JOIN LISTVALS L802 ON L802.LISTVAL_ID = V802.LISTVAL_ID
            INNER JOIN LISTVALS L803 ON L803.LISTVAL_ID = V803.LISTVAL_ID
            LEFT JOIN RES_GET(L802.RES_ID,  :LANG_CODE) R802 ON 1=1
            LEFT JOIN RES_GET(L803.RES_ID,  :LANG_CODE) R803 ON 1=1
            WHERE L.PARENT_ID = :I$YEAR_ID AND
                  L.OBJ_TYPE_ID = 120 AND
                  L.DATE_DEL IS NULL AND
                  V801.PARAM_ID = 801 AND
                  V801.IS_DEL = 0 AND
                  V801.LISTVAL_ID = :I$STEP AND
                  V802.PARAM_ID = 802 AND
                  V802.IS_DEL = 0 AND
                  --  V802.LISTVAL_ID = :I$STAGE AND
                  VD.PARAM_ID = 804 AND
                  VD.IS_DEL = 0 AND
                  --  VD.VAL = :I$DATE AND
                  V803.PARAM_ID = 803 AND
                  V803.IS_DEL = 0 --AND
                  --  V803.LISTVAL_ID = :I$SUBJECT
            ORDER BY L802.SORT_ORDER, R803.VAL, VD.VAL
            INTO :OBJ_ID, :STAGE_ID, :STAGE_NAME, :SUBJ_ID, :SUBJ_NAME, :DATE_EXAM
        DO
        BEGIN
          SELECT COUNT(L.PARENT_ID)
          FROM LINKS L
          WHERE L.PARENT_TYPE_ID IN (10, 126) AND
                L.OBJ_ID = :OBJ_ID AND
                L.DATE_DEL IS NULL
          INTO :PARTAKER;
          SELECT
                 CASE
                   WHEN SUM(V.VAL) IS NULL THEN 0
                   ELSE SUM(V.VAL)
                 END
          FROM LINKS L
          INNER JOIN LINKS L73 ON (L.PARENT_ID = L.PARENT_ID)
          INNER JOIN LINKS L16 ON (L73.OBJ_ID = L16.PARENT_ID)
          INNER JOIN LINKS L61 ON (L16.OBJ_ID = L61.PARENT_ID)
          INNER JOIN LINKS L122 ON (L61.OBJ_ID = L122.PARENT_ID)
          INNER JOIN VALI V ON V.OBJ_ID = L122.OBJ_ID
          WHERE L.PARENT_TYPE_ID = 2 AND
                L.OBJ_ID = :OBJ_ID AND
                L.OBJ_TYPE_ID = 120 AND
                L.DATE_DEL IS NULL AND
                L73.OBJ_TYPE_ID = 73 AND
                L73.DATE_DEL IS NULL AND
                L16.DATE_DEL IS NULL AND
                L16.OBJ_TYPE_ID = 16 AND
                L61.OBJ_TYPE_ID = 61 AND
                L61.DATE_DEL IS NULL AND
                L122.OBJ_TYPE_ID = 122 AND
                L122.DATE_DEL IS NULL AND
                V.PARAM_ID = 1372 AND
                V.IS_DEL = 0
          INTO :VMESTIM;
          SELECT COUNT(L.PARENT_ID)
          FROM LINKS L
          WHERE L.PARENT_TYPE_ID = 2 AND
                L.OBJ_ID = :OBJ_ID AND
                L.OBJ_TYPE_ID = 120 AND
                L.DATE_DEL IS NULL
          INTO :PPE;
          SELECT COUNT(L.PARENT_ID)
          FROM LINKS L
          WHERE L.PARENT_TYPE_ID = 2 AND
                L.OBJ_ID = :OBJ_ID AND
                L.OBJ_TYPE_ID = 120 AND
                L.DATE_DEL IS NULL AND
                L.REASON_ID = 1
          INTO :RESERVE;
          O_N = 0;
          SUSPEND;
        END
      END
      ELSE
      BEGIN
        FOR SELECT DISTINCT L.OBJ_ID, V802.LISTVAL_ID, R802.VAL, V803.LISTVAL_ID, R803.VAL, VD.VAL
            FROM LINKS L
            INNER JOIN VALL V801 ON V801.OBJ_ID = L.OBJ_ID
            INNER JOIN VALL V802 ON V802.OBJ_ID = L.OBJ_ID
            INNER JOIN VALD VD ON VD.OBJ_ID = L.OBJ_ID
            INNER JOIN VALL V803 ON V803.OBJ_ID = L.OBJ_ID
            INNER JOIN LISTVALS L802 ON L802.LISTVAL_ID = V802.LISTVAL_ID
            INNER JOIN LISTVALS L803 ON L803.LISTVAL_ID = V803.LISTVAL_ID
            LEFT JOIN RES_GET(L802.RES_ID,  :LANG_CODE) R802 ON 1=1
            LEFT JOIN RES_GET(L803.RES_ID,  :LANG_CODE) R803 ON 1=1
            WHERE L.PARENT_ID = :I$YEAR_ID AND
                  L.OBJ_TYPE_ID = 120 AND
                  L.DATE_DEL IS NULL AND
                  V801.PARAM_ID = 801 AND
                  V801.IS_DEL = 0 AND
                  V801.LISTVAL_ID = :I$STEP AND
                  V802.PARAM_ID = 802 AND
                  V802.IS_DEL = 0 AND
                  --  V802.LISTVAL_ID = :I$STAGE AND
                  VD.PARAM_ID = 804 AND
                  VD.IS_DEL = 0 AND
                  --  VD.VAL = :I$DATE AND
                  V803.PARAM_ID = 803 AND
                  V803.IS_DEL = 0 AND
                  V803.LISTVAL_ID = :I$SUBJECT
            ORDER BY L802.SORT_ORDER, R803.VAL, VD.VAL
            INTO :OBJ_ID, :STAGE_ID, :STAGE_NAME, :SUBJ_ID, :SUBJ_NAME, :DATE_EXAM
        DO
        BEGIN
          SELECT COUNT(L.PARENT_ID)
          FROM LINKS L
          WHERE L.PARENT_TYPE_ID IN (10, 126) AND
                L.OBJ_ID = :OBJ_ID AND
                L.DATE_DEL IS NULL
          INTO :PARTAKER;
          SELECT
                 CASE
                   WHEN SUM(V.VAL) IS NULL THEN 0
                   ELSE SUM(V.VAL)
                 END
          FROM LINKS L
          INNER JOIN LINKS L73 ON (L.PARENT_ID = L.PARENT_ID)
          INNER JOIN LINKS L16 ON (L73.OBJ_ID = L16.PARENT_ID)
          INNER JOIN LINKS L61 ON (L16.OBJ_ID = L61.PARENT_ID)
          INNER JOIN LINKS L122 ON (L61.OBJ_ID = L122.PARENT_ID)
          INNER JOIN VALI V ON V.OBJ_ID = L122.OBJ_ID
          WHERE L.PARENT_TYPE_ID = 2 AND
                L.OBJ_ID = :OBJ_ID AND
                L.OBJ_TYPE_ID = 120 AND
                L.DATE_DEL IS NULL AND
                L73.OBJ_TYPE_ID = 73 AND
                L73.DATE_DEL IS NULL AND
                L16.DATE_DEL IS NULL AND
                L16.OBJ_TYPE_ID = 16 AND
                L61.OBJ_TYPE_ID = 61 AND
                L61.DATE_DEL IS NULL AND
                L122.OBJ_TYPE_ID = 122 AND
                L122.DATE_DEL IS NULL AND
                V.PARAM_ID = 1372 AND
                V.IS_DEL = 0
          INTO :VMESTIM;
          SELECT COUNT(L.PARENT_ID)
          FROM LINKS L
          WHERE L.PARENT_TYPE_ID = 2 AND
                L.OBJ_ID = :OBJ_ID AND
                L.OBJ_TYPE_ID = 120 AND
                L.DATE_DEL IS NULL
          INTO :PPE;
          SELECT COUNT(L.PARENT_ID)
          FROM LINKS L
          WHERE L.PARENT_TYPE_ID = 2 AND
                L.OBJ_ID = :OBJ_ID AND
                L.OBJ_TYPE_ID = 120 AND
                L.DATE_DEL IS NULL AND
                L.REASON_ID = 1
          INTO :RESERVE;
          O_N = 0;
          SUSPEND;
        END
      END

    END
    ELSE
    BEGIN
      IF (:I$SUBJECT = -1) THEN
      BEGIN
        FOR SELECT DISTINCT L.OBJ_ID, V802.LISTVAL_ID, R802.VAL, V803.LISTVAL_ID, R803.VAL, VD.VAL
            FROM LINKS L
            INNER JOIN VALL V801 ON V801.OBJ_ID = L.OBJ_ID
            INNER JOIN VALL V802 ON V802.OBJ_ID = L.OBJ_ID
            INNER JOIN VALD VD ON VD.OBJ_ID = L.OBJ_ID
            INNER JOIN VALL V803 ON V803.OBJ_ID = L.OBJ_ID
            INNER JOIN LISTVALS L802 ON L802.LISTVAL_ID = V802.LISTVAL_ID
            INNER JOIN LISTVALS L803 ON L803.LISTVAL_ID = V803.LISTVAL_ID
            LEFT JOIN RES_GET(L802.RES_ID,  :LANG_CODE) R802 ON 1=1
            LEFT JOIN RES_GET(L803.RES_ID,  :LANG_CODE) R803 ON 1=1
            WHERE L.PARENT_ID = :I$YEAR_ID AND
                  L.OBJ_TYPE_ID = 120 AND
                  L.DATE_DEL IS NULL AND
                  V801.PARAM_ID = 801 AND
                  V801.IS_DEL = 0 AND
                  V801.LISTVAL_ID = :I$STEP AND
                  V802.PARAM_ID = 802 AND
                  V802.IS_DEL = 0 AND
                  --  V802.LISTVAL_ID = :I$STAGE AND
                  VD.PARAM_ID = 804 AND
                  VD.IS_DEL = 0 AND
                  VD.VAL = :I$DATE AND
                  V803.PARAM_ID = 803 AND
                  V803.IS_DEL = 0 --AND
                  --  V803.LISTVAL_ID = :I$SUBJECT
            ORDER BY L802.SORT_ORDER, R803.VAL, VD.VAL
            INTO :OBJ_ID, :STAGE_ID, :STAGE_NAME, :SUBJ_ID, :SUBJ_NAME, :DATE_EXAM
        DO
        BEGIN
          SELECT COUNT(L.PARENT_ID)
          FROM LINKS L
          WHERE L.PARENT_TYPE_ID IN (10, 126) AND
                L.OBJ_ID = :OBJ_ID AND
                L.DATE_DEL IS NULL
          INTO :PARTAKER;
          SELECT
                 CASE
                   WHEN SUM(V.VAL) IS NULL THEN 0
                   ELSE SUM(V.VAL)
                 END
          FROM LINKS L
          INNER JOIN LINKS L73 ON (L.PARENT_ID = L.PARENT_ID)
          INNER JOIN LINKS L16 ON (L73.OBJ_ID = L16.PARENT_ID)
          INNER JOIN LINKS L61 ON (L16.OBJ_ID = L61.PARENT_ID)
          INNER JOIN LINKS L122 ON (L61.OBJ_ID = L122.PARENT_ID)
          INNER JOIN VALI V ON V.OBJ_ID = L122.OBJ_ID
          WHERE L.PARENT_TYPE_ID = 2 AND
                L.OBJ_ID = :OBJ_ID AND
                L.OBJ_TYPE_ID = 120 AND
                L.DATE_DEL IS NULL AND
                L73.OBJ_TYPE_ID = 73 AND
                L73.DATE_DEL IS NULL AND
                L16.DATE_DEL IS NULL AND
                L16.OBJ_TYPE_ID = 16 AND
                L61.OBJ_TYPE_ID = 61 AND
                L61.DATE_DEL IS NULL AND
                L122.OBJ_TYPE_ID = 122 AND
                L122.DATE_DEL IS NULL AND
                V.PARAM_ID = 1372 AND
                V.IS_DEL = 0
          INTO :VMESTIM;
          SELECT COUNT(L.PARENT_ID)
          FROM LINKS L
          WHERE L.PARENT_TYPE_ID = 2 AND
                L.OBJ_ID = :OBJ_ID AND
                L.OBJ_TYPE_ID = 120 AND
                L.DATE_DEL IS NULL
          INTO :PPE;
          SELECT COUNT(L.PARENT_ID)
          FROM LINKS L
          WHERE L.PARENT_TYPE_ID = 2 AND
                L.OBJ_ID = :OBJ_ID AND
                L.OBJ_TYPE_ID = 120 AND
                L.DATE_DEL IS NULL AND
                L.REASON_ID = 1
          INTO :RESERVE;
          O_N = 0;
          SUSPEND;
        END
      END
      ELSE
      BEGIN
        FOR SELECT DISTINCT L.OBJ_ID, V802.LISTVAL_ID, R802.VAL, V803.LISTVAL_ID, R803.VAL, VD.VAL
            FROM LINKS L
            INNER JOIN VALL V801 ON V801.OBJ_ID = L.OBJ_ID
            INNER JOIN VALL V802 ON V802.OBJ_ID = L.OBJ_ID
            INNER JOIN VALD VD ON VD.OBJ_ID = L.OBJ_ID
            INNER JOIN VALL V803 ON V803.OBJ_ID = L.OBJ_ID
            INNER JOIN LISTVALS L802 ON L802.LISTVAL_ID = V802.LISTVAL_ID
            INNER JOIN LISTVALS L803 ON L803.LISTVAL_ID = V803.LISTVAL_ID
            LEFT JOIN RES_GET(L802.RES_ID,  :LANG_CODE) R802 ON 1=1
            LEFT JOIN RES_GET(L803.RES_ID,  :LANG_CODE) R803 ON 1=1
            WHERE L.PARENT_ID = :I$YEAR_ID AND
                  L.OBJ_TYPE_ID = 120 AND
                  L.DATE_DEL IS NULL AND
                  V801.PARAM_ID = 801 AND
                  V801.IS_DEL = 0 AND
                  V801.LISTVAL_ID = :I$STEP AND
                  V802.PARAM_ID = 802 AND
                  V802.IS_DEL = 0 AND
                  --  V802.LISTVAL_ID = :I$STAGE AND
                  VD.PARAM_ID = 804 AND
                  VD.IS_DEL = 0 AND
                  VD.VAL = :I$DATE AND
                  V803.PARAM_ID = 803 AND
                  V803.IS_DEL = 0 AND
                  V803.LISTVAL_ID = :I$SUBJECT
            ORDER BY L802.SORT_ORDER, R803.VAL, VD.VAL
            INTO :OBJ_ID, :STAGE_ID, :STAGE_NAME, :SUBJ_ID, :SUBJ_NAME, :DATE_EXAM
        DO
        BEGIN
          SELECT COUNT(L.PARENT_ID)
          FROM LINKS L
          WHERE L.PARENT_TYPE_ID IN (10, 126) AND
                L.OBJ_ID = :OBJ_ID AND
                L.DATE_DEL IS NULL
          INTO :PARTAKER;
          SELECT
                 CASE
                   WHEN SUM(V.VAL) IS NULL THEN 0
                   ELSE SUM(V.VAL)
                 END
          FROM LINKS L
          INNER JOIN LINKS L73 ON (L.PARENT_ID = L.PARENT_ID)
          INNER JOIN LINKS L16 ON (L73.OBJ_ID = L16.PARENT_ID)
          INNER JOIN LINKS L61 ON (L16.OBJ_ID = L61.PARENT_ID)
          INNER JOIN LINKS L122 ON (L61.OBJ_ID = L122.PARENT_ID)
          INNER JOIN VALI V ON V.OBJ_ID = L122.OBJ_ID
          WHERE L.PARENT_TYPE_ID = 2 AND
                L.OBJ_ID = :OBJ_ID AND
                L.OBJ_TYPE_ID = 120 AND
                L.DATE_DEL IS NULL AND
                L73.OBJ_TYPE_ID = 73 AND
                L73.DATE_DEL IS NULL AND
                L16.DATE_DEL IS NULL AND
                L16.OBJ_TYPE_ID = 16 AND
                L61.OBJ_TYPE_ID = 61 AND
                L61.DATE_DEL IS NULL AND
                L122.OBJ_TYPE_ID = 122 AND
                L122.DATE_DEL IS NULL AND
                V.PARAM_ID = 1372 AND
                V.IS_DEL = 0
          INTO :VMESTIM;
          SELECT COUNT(L.PARENT_ID)
          FROM LINKS L
          WHERE L.PARENT_TYPE_ID = 2 AND
                L.OBJ_ID = :OBJ_ID AND
                L.OBJ_TYPE_ID = 120 AND
                L.DATE_DEL IS NULL
          INTO :PPE;
          SELECT COUNT(L.PARENT_ID)
          FROM LINKS L
          WHERE L.PARENT_TYPE_ID = 2 AND
                L.OBJ_ID = :OBJ_ID AND
                L.OBJ_TYPE_ID = 120 AND
                L.DATE_DEL IS NULL AND
                L.REASON_ID = 1
          INTO :RESERVE;
          O_N = 0;
          SUSPEND;
        END
      END
    END
  END
  ELSE
  BEGIN
    IF (:I$DATE = '2000-01-01') THEN
    BEGIN
      IF (:I$SUBJECT = -1) THEN
      BEGIN
        FOR SELECT DISTINCT L.OBJ_ID, V802.LISTVAL_ID, R802.VAL, V803.LISTVAL_ID, R803.VAL, VD.VAL
            FROM LINKS L
            INNER JOIN VALL V801 ON V801.OBJ_ID = L.OBJ_ID
            INNER JOIN VALL V802 ON V802.OBJ_ID = L.OBJ_ID
            INNER JOIN VALD VD ON VD.OBJ_ID = L.OBJ_ID
            INNER JOIN VALL V803 ON V803.OBJ_ID = L.OBJ_ID
            INNER JOIN LISTVALS L802 ON L802.LISTVAL_ID = V802.LISTVAL_ID
            INNER JOIN LISTVALS L803 ON L803.LISTVAL_ID = V803.LISTVAL_ID
            LEFT JOIN RES_GET(L802.RES_ID,  :LANG_CODE) R802 ON 1=1
            LEFT JOIN RES_GET(L803.RES_ID,  :LANG_CODE) R803 ON 1=1
            WHERE L.PARENT_ID = :I$YEAR_ID AND
                  L.OBJ_TYPE_ID = 120 AND
                  L.DATE_DEL IS NULL AND
                  V801.PARAM_ID = 801 AND
                  V801.IS_DEL = 0 AND
                  V801.LISTVAL_ID = :I$STEP AND
                  V802.PARAM_ID = 802 AND
                  V802.IS_DEL = 0 AND
                  V802.LISTVAL_ID = :I$STAGE AND
                  VD.PARAM_ID = 804 AND
                  VD.IS_DEL = 0 AND
                  -- VD.VAL = :I$DATE AND
                  V803.PARAM_ID = 803 AND
                  V803.IS_DEL = 0 --AND
                  --  V803.LISTVAL_ID = :I$SUBJECT
            ORDER BY L802.SORT_ORDER, R803.VAL, VD.VAL
            INTO :OBJ_ID, :STAGE_ID, :STAGE_NAME, :SUBJ_ID, :SUBJ_NAME, :DATE_EXAM
        DO
        BEGIN
          SELECT COUNT(L.PARENT_ID)
          FROM LINKS L
          WHERE L.PARENT_TYPE_ID IN (10, 126) AND
                L.OBJ_ID = :OBJ_ID AND
                L.DATE_DEL IS NULL
          INTO :PARTAKER;
          SELECT
                 CASE
                   WHEN SUM(V.VAL) IS NULL THEN 0
                   ELSE SUM(V.VAL)
                 END
          FROM LINKS L
          INNER JOIN LINKS L73 ON (L.PARENT_ID = L.PARENT_ID)
          INNER JOIN LINKS L16 ON (L73.OBJ_ID = L16.PARENT_ID)
          INNER JOIN LINKS L61 ON (L16.OBJ_ID = L61.PARENT_ID)
          INNER JOIN LINKS L122 ON (L61.OBJ_ID = L122.PARENT_ID)
          INNER JOIN VALI V ON V.OBJ_ID = L122.OBJ_ID
          WHERE L.PARENT_TYPE_ID = 2 AND
                L.OBJ_ID = :OBJ_ID AND
                L.OBJ_TYPE_ID = 120 AND
                L.DATE_DEL IS NULL AND
                L73.OBJ_TYPE_ID = 73 AND
                L73.DATE_DEL IS NULL AND
                L16.DATE_DEL IS NULL AND
                L16.OBJ_TYPE_ID = 16 AND
                L61.OBJ_TYPE_ID = 61 AND
                L61.DATE_DEL IS NULL AND
                L122.OBJ_TYPE_ID = 122 AND
                L122.DATE_DEL IS NULL AND
                V.PARAM_ID = 1372 AND
                V.IS_DEL = 0
          INTO :VMESTIM;
          SELECT COUNT(L.PARENT_ID)
          FROM LINKS L
          WHERE L.PARENT_TYPE_ID = 2 AND
                L.OBJ_ID = :OBJ_ID AND
                L.OBJ_TYPE_ID = 120 AND
                L.DATE_DEL IS NULL
          INTO :PPE;
          SELECT COUNT(L.PARENT_ID)
          FROM LINKS L
          WHERE L.PARENT_TYPE_ID = 2 AND
                L.OBJ_ID = :OBJ_ID AND
                L.OBJ_TYPE_ID = 120 AND
                L.DATE_DEL IS NULL AND
                L.REASON_ID = 1
          INTO :RESERVE;
          O_N = 0;
          SUSPEND;
        END
      END
      ELSE
      BEGIN
        FOR SELECT DISTINCT L.OBJ_ID, V802.LISTVAL_ID, R802.VAL, V803.LISTVAL_ID, R803.VAL, VD.VAL
            FROM LINKS L
            INNER JOIN VALL V801 ON V801.OBJ_ID = L.OBJ_ID
            INNER JOIN VALL V802 ON V802.OBJ_ID = L.OBJ_ID
            INNER JOIN VALD VD ON VD.OBJ_ID = L.OBJ_ID
            INNER JOIN VALL V803 ON V803.OBJ_ID = L.OBJ_ID
            INNER JOIN LISTVALS L802 ON L802.LISTVAL_ID = V802.LISTVAL_ID
            INNER JOIN LISTVALS L803 ON L803.LISTVAL_ID = V803.LISTVAL_ID
            LEFT JOIN RES_GET(L802.RES_ID,  :LANG_CODE) R802 ON 1=1
            LEFT JOIN RES_GET(L803.RES_ID,  :LANG_CODE) R803 ON 1=1
            WHERE L.PARENT_ID = :I$YEAR_ID AND
                  L.OBJ_TYPE_ID = 120 AND
                  L.DATE_DEL IS NULL AND
                  V801.PARAM_ID = 801 AND
                  V801.IS_DEL = 0 AND
                  V801.LISTVAL_ID = :I$STEP AND
                  V802.PARAM_ID = 802 AND
                  V802.IS_DEL = 0 AND
                  V802.LISTVAL_ID = :I$STAGE AND
                  VD.PARAM_ID = 804 AND
                  VD.IS_DEL = 0 AND
                  --   VD.VAL = :I$DATE AND
                  V803.PARAM_ID = 803 AND
                  V803.IS_DEL = 0 AND
                  V803.LISTVAL_ID = :I$SUBJECT
            ORDER BY L802.SORT_ORDER, R803.VAL, VD.VAL
            INTO :OBJ_ID, :STAGE_ID, :STAGE_NAME, :SUBJ_ID, :SUBJ_NAME, :DATE_EXAM
        DO
        BEGIN
          SELECT COUNT(L.PARENT_ID)
          FROM LINKS L
          WHERE L.PARENT_TYPE_ID IN (10, 126) AND
                L.OBJ_ID = :OBJ_ID AND
                L.DATE_DEL IS NULL
          INTO :PARTAKER;
          SELECT
                 CASE
                   WHEN SUM(V.VAL) IS NULL THEN 0
                   ELSE SUM(V.VAL)
                 END
          FROM LINKS L
          INNER JOIN LINKS L73 ON (L.PARENT_ID = L.PARENT_ID)
          INNER JOIN LINKS L16 ON (L73.OBJ_ID = L16.PARENT_ID)
          INNER JOIN LINKS L61 ON (L16.OBJ_ID = L61.PARENT_ID)
          INNER JOIN LINKS L122 ON (L61.OBJ_ID = L122.PARENT_ID)
          INNER JOIN VALI V ON V.OBJ_ID = L122.OBJ_ID
          WHERE L.PARENT_TYPE_ID = 2 AND
                L.OBJ_ID = :OBJ_ID AND
                L.OBJ_TYPE_ID = 120 AND
                L.DATE_DEL IS NULL AND
                L73.OBJ_TYPE_ID = 73 AND
                L73.DATE_DEL IS NULL AND
                L16.DATE_DEL IS NULL AND
                L16.OBJ_TYPE_ID = 16 AND
                L61.OBJ_TYPE_ID = 61 AND
                L61.DATE_DEL IS NULL AND
                L122.OBJ_TYPE_ID = 122 AND
                L122.DATE_DEL IS NULL AND
                V.PARAM_ID = 1372 AND
                V.IS_DEL = 0
          INTO :VMESTIM;
          SELECT COUNT(L.PARENT_ID)
          FROM LINKS L
          WHERE L.PARENT_TYPE_ID = 2 AND
                L.OBJ_ID = :OBJ_ID AND
                L.OBJ_TYPE_ID = 120 AND
                L.DATE_DEL IS NULL
          INTO :PPE;
          SELECT COUNT(L.PARENT_ID)
          FROM LINKS L
          WHERE L.PARENT_TYPE_ID = 2 AND
                L.OBJ_ID = :OBJ_ID AND
                L.OBJ_TYPE_ID = 120 AND
                L.DATE_DEL IS NULL AND
                L.REASON_ID = 1
          INTO :RESERVE;
          O_N = 0;
          SUSPEND;
        END
      END
    END
    ELSE
    BEGIN
      FOR SELECT DISTINCT L.OBJ_ID, V802.LISTVAL_ID, R802.VAL, V803.LISTVAL_ID, R803.VAL, VD.VAL
          FROM LINKS L
          INNER JOIN VALL V801 ON V801.OBJ_ID = L.OBJ_ID
          INNER JOIN VALL V802 ON V802.OBJ_ID = L.OBJ_ID
          INNER JOIN VALD VD ON VD.OBJ_ID = L.OBJ_ID
          INNER JOIN VALL V803 ON V803.OBJ_ID = L.OBJ_ID
          INNER JOIN LISTVALS L802 ON L802.LISTVAL_ID = V802.LISTVAL_ID
          INNER JOIN LISTVALS L803 ON L803.LISTVAL_ID = V803.LISTVAL_ID
          LEFT JOIN RES_GET(L802.RES_ID,  :LANG_CODE) R802 ON 1=1
          LEFT JOIN RES_GET(L803.RES_ID,  :LANG_CODE) R803 ON 1=1
          WHERE L.PARENT_ID = :I$YEAR_ID AND
                L.OBJ_TYPE_ID = 120 AND
                L.DATE_DEL IS NULL AND
                V801.PARAM_ID = 801 AND
                V801.IS_DEL = 0 AND
                V801.LISTVAL_ID = :I$STEP AND
                V802.PARAM_ID = 802 AND
                V802.IS_DEL = 0 AND
                V802.LISTVAL_ID = :I$STAGE AND
                VD.PARAM_ID = 804 AND
                VD.IS_DEL = 0 AND
                VD.VAL = :I$DATE AND
                V803.PARAM_ID = 803 AND
                V803.IS_DEL = 0 AND
                V803.LISTVAL_ID = :I$SUBJECT
          ORDER BY L802.SORT_ORDER, R803.VAL, VD.VAL
          INTO :OBJ_ID, :STAGE_ID, :STAGE_NAME, :SUBJ_ID, :SUBJ_NAME, :DATE_EXAM
      DO
      BEGIN
        SELECT COUNT(L.PARENT_ID)
        FROM LINKS L
        WHERE L.PARENT_TYPE_ID IN (10, 126) AND
              L.OBJ_ID = :OBJ_ID AND
              L.DATE_DEL IS NULL
        INTO :PARTAKER;
        SELECT
               CASE
                 WHEN SUM(V.VAL) IS NULL THEN 0
                 ELSE SUM(V.VAL)
               END
        FROM LINKS L
        INNER JOIN LINKS L73 ON (L.PARENT_ID = L.PARENT_ID)
        INNER JOIN LINKS L16 ON (L73.OBJ_ID = L16.PARENT_ID)
        INNER JOIN LINKS L61 ON (L16.OBJ_ID = L61.PARENT_ID)
        INNER JOIN LINKS L122 ON (L61.OBJ_ID = L122.PARENT_ID)
        INNER JOIN VALI V ON V.OBJ_ID = L122.OBJ_ID
        WHERE L.PARENT_TYPE_ID = 2 AND
              L.OBJ_ID = :OBJ_ID AND
              L.OBJ_TYPE_ID = 120 AND
              L.DATE_DEL IS NULL AND
              L73.OBJ_TYPE_ID = 73 AND
              L73.DATE_DEL IS NULL AND
              L16.DATE_DEL IS NULL AND
              L16.OBJ_TYPE_ID = 16 AND
              L61.OBJ_TYPE_ID = 61 AND
              L61.DATE_DEL IS NULL AND
              L122.OBJ_TYPE_ID = 122 AND
              L122.DATE_DEL IS NULL AND
              V.PARAM_ID = 1372 AND
              V.IS_DEL = 0
        INTO :VMESTIM;
        SELECT COUNT(L.PARENT_ID)
        FROM LINKS L
        WHERE L.PARENT_TYPE_ID = 2 AND
              L.OBJ_ID = :OBJ_ID AND
              L.OBJ_TYPE_ID = 120 AND
              L.DATE_DEL IS NULL
        INTO :PPE;
        SELECT COUNT(L.PARENT_ID)
        FROM LINKS L
        WHERE L.PARENT_TYPE_ID = 2 AND
              L.OBJ_ID = :OBJ_ID AND
              L.OBJ_TYPE_ID = 120 AND
              L.DATE_DEL IS NULL AND
              L.REASON_ID = 1
        INTO :RESERVE;
        O_N = 0;
          SUSPEND;
      END
    END
  END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GIA_EXAM_STAGE_GET (
    I$YEAR_ID BIGINT,
    I$STEP BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    STAGE_ID BIGINT,
    STAGE_CAPTION VARCHAR(100))
AS
declare variable V$C integer;
declare variable LANG_CODE varchar(2);
begin
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :LANG_CODE;

    SELECT COUNT(DISTINCT V802.LISTVAL_ID)
    FROM LINKS L
    INNER JOIN VALL V801 ON V801.OBJ_ID = L.OBJ_ID
    INNER JOIN VALL V802 ON V802.OBJ_ID = L.OBJ_ID
    WHERE L.PARENT_ID = :I$YEAR_ID
    AND L.OBJ_TYPE_ID = 120
    AND L.DATE_DEL IS NULL
    AND V801.PARAM_ID = 801
    AND V801.IS_DEL = 0
    AND V802.PARAM_ID = 802
    AND V802.IS_DEL = 0
    INTO :V$C;
    IF (V$C > 0) THEN
    BEGIN
        STAGE_ID = -1;
        STAGE_CAPTION = 'Все этапы';
        SUSPEND;
    END

    FOR
        SELECT DISTINCT
               VLL.LISTVAL_ID,
               R.VAL
        FROM LINKS L
        INNER JOIN VALL VLL ON VLL.OBJ_ID = L.OBJ_ID
        INNER JOIN LISTVALS LV ON LV.LISTVAL_ID = VLL.LISTVAL_ID
        LEFT JOIN RES_GET(LV.RES_ID,  :LANG_CODE) R ON 1=1
        INNER JOIN VALL V802 ON V802.OBJ_ID = L.OBJ_ID
        WHERE L.PARENT_ID = :I$YEAR_ID
        AND L.OBJ_TYPE_ID = 120
        AND L.DATE_DEL IS NULL
        AND VLL.PARAM_ID = 802
        AND VLL.IS_DEL = 0
        AND V802.PARAM_ID = 801
        AND V802.IS_DEL = 0
        AND V802.LISTVAL_ID = :I$STEP
        INTO :STAGE_ID, :STAGE_CAPTION
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GIA_EXAM_STATEMENT_IMPORT_XML (
    TRASFER_DT TIMESTAMP,
    YEAR_ID BIGINT,
    STATMENT VARCHAR(4000))
RETURNS (
    OPR INTEGER)
AS
DECLARE VARIABLE BLOB_ID BIGINT;
BEGIN
    OPR = 0;/* 0 - equal, 1 - edit */

    SELECT V.BLOB_ID
    FROM VAL_ADD(1211, 3866, :TRASFER_DT) V
    INTO :BLOB_ID;

    SELECT COUNT(*)
    FROM VALS V
    WHERE V.PARAM_ID = 1192
      AND V.OBJ_ID = :YEAR_ID
      AND V.VAL = :STATMENT
      AND V.IS_DEL = 0
    INTO :BLOB_ID;

    IF (BLOB_ID = 0) THEN
    BEGIN
        SELECT V.BLOB_ID
        FROM VAL_ADD(1192, :YEAR_ID, :STATMENT) V
        INTO :BLOB_ID;
        OPR = 1;
    END

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GIA_EXAM_STEP_GET (
    I$YEAR_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    STEP_ID BIGINT,
    STEP_CAPTION VARCHAR(20))
AS
declare variable LANG_CODE varchar(2);
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :LANG_CODE;
    FOR
        SELECT DISTINCT
               VLL.LISTVAL_ID,
               R.VAL
        FROM LINKS L
        INNER JOIN VALL VLL ON VLL.OBJ_ID = L.OBJ_ID
        INNER JOIN LISTVALS LV ON LV.LISTVAL_ID = VLL.LISTVAL_ID
        LEFT JOIN RES_GET(LV.RES_ID,  :LANG_CODE) R ON 1=1
        WHERE L.PARENT_ID = :I$YEAR_ID
        AND L.OBJ_TYPE_ID = 120
        AND L.DATE_DEL IS NULL
        AND VLL.PARAM_ID = 801
        AND VLL.IS_DEL = 0
        INTO :STEP_ID, :STEP_CAPTION
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GIA_EXAM_SUBJECT_GET (
    I$YEAR_ID BIGINT,
    I$STEP BIGINT,
    I$STAGE BIGINT,
    I$DATE DATE,
    I$USER_ID BIGINT)
RETURNS (
    SUBJECT_ID BIGINT,
    SUBJECT_CAPTION VARCHAR(100))
AS
declare variable V$C integer;
declare variable LANG_CODE varchar(2);
begin
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :LANG_CODE;

    SELECT COUNT(DISTINCT V803.LISTVAL_ID)
    FROM LINKS L
    JOIN VALL V801 ON V801.OBJ_ID = L.OBJ_ID AND V801.PARAM_ID = 801 AND V801.IS_DEL = 0 AND V801.LISTVAL_ID = :I$STEP
    JOIN VALL V802 ON V802.OBJ_ID = L.OBJ_ID AND V802.PARAM_ID = 802 AND V802.IS_DEL = 0 --  AND V802.LISTVAL_ID = :I$STAGE
    JOIN VALD VD ON VD.OBJ_ID = L.OBJ_ID AND VD.PARAM_ID = 804 AND VD.IS_DEL = 0
    JOIN VALL V803 ON V803.OBJ_ID = L.OBJ_ID AND V803.PARAM_ID = 803 AND V803.IS_DEL = 0
    WHERE L.PARENT_ID = :I$YEAR_ID AND L.OBJ_TYPE_ID = 120 AND L.DATE_DEL IS NULL
    INTO :V$C;

    IF (V$C > 0) THEN
    BEGIN
        SUBJECT_ID = -1;
        SUBJECT_CAPTION = 'Все предметы';
        SUSPEND;
    END
    IF (:I$STAGE = -1) THEN
    BEGIN
        IF (:I$DATE = '2000-01-01') THEN
        BEGIN
            FOR
                SELECT DISTINCT V803.LISTVAL_ID, R.VAL
                FROM LINKS L
                JOIN VALL V801 ON V801.OBJ_ID = L.OBJ_ID AND V801.PARAM_ID = 801 AND V801.IS_DEL = 0 AND V801.LISTVAL_ID = :I$STEP
                JOIN VALL V802 ON V802.OBJ_ID = L.OBJ_ID AND V802.PARAM_ID = 802 AND V802.IS_DEL = 0 -- AND V802.LISTVAL_ID = :I$STAGE
                JOIN VALD VD ON VD.OBJ_ID = L.OBJ_ID AND VD.PARAM_ID = 804 AND VD.IS_DEL = 0
                JOIN VALL V803 ON V803.OBJ_ID = L.OBJ_ID AND V803.PARAM_ID = 803 AND V803.IS_DEL = 0
                JOIN LISTVALS LV ON LV.LISTVAL_ID = V803.LISTVAL_ID
                LEFT JOIN RES_GET(LV.RES_ID,  :LANG_CODE) R ON 1=1
                WHERE L.PARENT_ID = :I$YEAR_ID AND L.OBJ_TYPE_ID = 120 AND L.DATE_DEL IS NULL
                ORDER BY R.VAL
                INTO :SUBJECT_ID, :SUBJECT_CAPTION
            DO
            BEGIN
                SUSPEND;
            END
        END
        ELSE
        BEGIN
            FOR
                SELECT DISTINCT V803.LISTVAL_ID, R.VAL
                FROM LINKS L
                JOIN VALL V801 ON V801.OBJ_ID = L.OBJ_ID AND V801.PARAM_ID = 801 AND V801.IS_DEL = 0 AND V801.LISTVAL_ID = :I$STEP
                JOIN VALL V802 ON V802.OBJ_ID = L.OBJ_ID AND V802.PARAM_ID = 802 AND V802.IS_DEL = 0 -- AND V802.LISTVAL_ID = :I$STAGE
                JOIN VALD VD ON VD.OBJ_ID = L.OBJ_ID AND VD.PARAM_ID = 804 AND VD.IS_DEL = 0 AND VD.VAL = :I$DATE
                JOIN VALL V803 ON V803.OBJ_ID = L.OBJ_ID AND V803.PARAM_ID = 803 AND V803.IS_DEL = 0
                JOIN LISTVALS LV ON LV.LISTVAL_ID = V803.LISTVAL_ID
                LEFT JOIN RES_GET(LV.RES_ID,  :LANG_CODE) R ON 1=1
                WHERE L.PARENT_ID = :I$YEAR_ID AND L.OBJ_TYPE_ID = 120 AND L.DATE_DEL IS NULL
                ORDER BY R.VAL
                INTO :SUBJECT_ID, :SUBJECT_CAPTION
            DO
            BEGIN
                SUSPEND;
            END
        END
    END
    ELSE
    BEGIN
        IF (:I$DATE = '2000-01-01') THEN
        BEGIN
            FOR
                SELECT DISTINCT
                       V803.LISTVAL_ID,
                       R.VAL
                FROM LINKS L
                JOIN VALL V801 ON V801.OBJ_ID = L.OBJ_ID AND V801.PARAM_ID = 801 AND V801.IS_DEL = 0 AND V801.LISTVAL_ID = :I$STEP
                JOIN VALL V802 ON V802.OBJ_ID = L.OBJ_ID AND V802.PARAM_ID = 802 AND V802.IS_DEL = 0 AND V802.LISTVAL_ID = :I$STAGE
                JOIN VALD VD ON VD.OBJ_ID = L.OBJ_ID AND VD.PARAM_ID = 804 AND VD.IS_DEL = 0 --AND VD.VAL = :I$DATE
                JOIN VALL V803 ON V803.OBJ_ID = L.OBJ_ID AND V803.PARAM_ID = 803 AND V803.IS_DEL = 0
                JOIN LISTVALS LV ON LV.LISTVAL_ID = V803.LISTVAL_ID
                LEFT JOIN RES_GET(LV.RES_ID,  :LANG_CODE) R ON 1=1
                WHERE L.PARENT_ID = :I$YEAR_ID AND L.OBJ_TYPE_ID = 120 AND L.DATE_DEL IS NULL
                ORDER BY R.VAL
                INTO :SUBJECT_ID, :SUBJECT_CAPTION
            DO
            BEGIN
                SUSPEND;
            END
        END
        ELSE
        BEGIN
            FOR
                SELECT DISTINCT V803.LISTVAL_ID, R.VAL
                FROM LINKS L
                JOIN VALL V801 ON V801.OBJ_ID = L.OBJ_ID AND V801.PARAM_ID = 801 AND V801.IS_DEL = 0 AND V801.LISTVAL_ID = :I$STEP
                JOIN VALL V802 ON V802.OBJ_ID = L.OBJ_ID AND V802.PARAM_ID = 802 AND V802.IS_DEL = 0 AND V802.LISTVAL_ID = :I$STAGE
                JOIN VALD VD ON VD.OBJ_ID = L.OBJ_ID AND VD.PARAM_ID = 804 AND VD.IS_DEL = 0 AND VD.VAL = :I$DATE
                JOIN VALL V803 ON V803.OBJ_ID = L.OBJ_ID AND V803.PARAM_ID = 803 AND V803.IS_DEL = 0
                JOIN LISTVALS LV ON LV.LISTVAL_ID = V803.LISTVAL_ID
                LEFT JOIN RES_GET(LV.RES_ID,  :LANG_CODE) R ON 1=1
                WHERE L.PARENT_ID = :I$YEAR_ID AND L.OBJ_TYPE_ID = 120 AND L.DATE_DEL IS NULL
                ORDER BY R.VAL
                INTO :SUBJECT_ID, :SUBJECT_CAPTION
            DO
            BEGIN
                SUSPEND;
            END
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GIA_EXAM_YEAR_EXPORT RETURNS (
    LINK_ID BIGINT,
    OBJ_ID BIGINT,
    DATE_INS TIMESTAMP,
    DATE_DEL TIMESTAMP,
    LISTVAL_ID BIGINT,
    VAL VARCHAR(4000),
    FILE_ID BIGINT)
AS
BEGIN
    FOR
        SELECT L.LINK_ID, L.OBJ_ID, L.DATE_INS, L.DATE_DEL, V742.LISTVAL_ID, V1192.VAL, V2930.VAL
        FROM LINKS L
        JOIN VALL V742 ON V742.OBJ_ID = L.OBJ_ID AND V742.PARAM_ID = 742 AND V742.IS_DEL = 0
        LEFT JOIN VALS V1192 ON V1192.OBJ_ID = L.OBJ_ID AND V1192.PARAM_ID = 1192 AND V1192.IS_DEL = 0
        LEFT JOIN VALS V2930 ON V2930.OBJ_ID = L.OBJ_ID AND V2930.PARAM_ID = 2930 AND V2930.IS_DEL = 0
        WHERE L.PARENT_ID = 3866 AND L.OBJ_TYPE_ID = 119
        INTO :LINK_ID, :OBJ_ID, :DATE_INS, :DATE_DEL, :LISTVAL_ID, :VAL, :FILE_ID
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GIA_EXAM_YEAR_GET (
    I$USER_ID BIGINT)
RETURNS (
    YEAR_ID BIGINT,
    YEAR_CAPTION VARCHAR(20),
    STATMENT VARCHAR(4000),
    FILE_ID VARCHAR(100))
AS
declare variable LANG_CODE varchar(2);
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :LANG_CODE;

    FOR
        SELECT L.OBJ_ID, R.VAL, V1192.VAL, V2930.VAL
        FROM LINKS L
        JOIN VALL V742 ON V742.OBJ_ID = L.OBJ_ID AND V742.PARAM_ID = 742 AND V742.IS_DEL = 0
        JOIN LISTVALS LV ON LV.LISTVAL_ID = V742.LISTVAL_ID
        LEFT JOIN RES_GET(LV.RES_ID,  :LANG_CODE) R ON 1=1
        LEFT JOIN VALS V1192 ON V1192.OBJ_ID = L.OBJ_ID AND V1192.PARAM_ID = 1192 AND V1192.IS_DEL = 0
        LEFT JOIN VALS V2930 ON V2930.OBJ_ID = L.OBJ_ID AND V2930.PARAM_ID = 2930 AND V2930.IS_DEL = 0
        WHERE L.PARENT_ID = 3866 AND L.OBJ_TYPE_ID = 119 AND L.DATE_DEL IS NULL
        ORDER BY R.VAL_LONG DESC
        INTO :YEAR_ID, :YEAR_CAPTION, :STATMENT, :FILE_ID
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GIA_EXAM_YEAR_IMPORT (
    LINK_ID BIGINT,
    OBJ_ID BIGINT,
    DATE_INS TIMESTAMP,
    DATE_DEL TIMESTAMP,
    LISTVAL_ID BIGINT,
    VAL VARCHAR(4000),
    FILE_ID VARCHAR(100) = null)
RETURNS (
    OPR INTEGER)
AS
declare variable BLOB_ID bigint;
BEGIN
    OPR = 0;/* 0 - equal, 1 - edit */

    UPDATE OR INSERT INTO OBJECTS (OBJ_ID, TYPE_ID)
    VALUES (:OBJ_ID, 119)
    MATCHING (OBJ_ID);

    /* В ряде баз отсутствует корневой объект 118 - восстанавливаем его */
    UPDATE OR INSERT INTO OBJECTS (OBJ_ID, TYPE_ID, IS_REPL, DATE_MODIFY)
    VALUES (3866, 118, 1, CURRENT_TIMESTAMP);

    UPDATE OR INSERT INTO LINKS (LINK_ID, OBJ_ID, DATE_INS)
    VALUES (9475, 3866, '02.09.2012');

    UPDATE OR INSERT INTO LINKS (LINK_ID, PARENT_ID, OBJ_ID, DATE_INS, DATE_DEL)
    VALUES (:LINK_ID, 3866, :OBJ_ID, :DATE_INS, :DATE_DEL)
    MATCHING (LINK_ID);

    SELECT V.BLOB_ID
    FROM VAL_ADD(742, :OBJ_ID, :LISTVAL_ID) V
    INTO :BLOB_ID;

    -- Данные по названию
    IF (VAL IS NULL) THEN
    BEGIN
        UPDATE VALS
        SET IS_DEL = 1
        WHERE PARAM_ID = 1192 AND OBJ_ID = :OBJ_ID;
    END
    ELSE
    BEGIN
        SELECT COUNT(*)
        FROM VALS V
        WHERE V.PARAM_ID = 1192 AND V.OBJ_ID = :OBJ_ID AND V.VAL = :VAL AND V.IS_DEL = 0
        INTO :BLOB_ID;

        IF (BLOB_ID = 0) THEN
        BEGIN
            SELECT V.BLOB_ID
            FROM VAL_ADD(1192, :OBJ_ID, :VAL) V
            INTO :BLOB_ID;
            OPR = 1;
        END
    END

    -- Обновляем сигнатуру года
    IF(FILE_ID IS NULL) THEN
    BEGIN
        UPDATE VALS
        SET IS_DEL = 1
        WHERE PARAM_ID = 2930 AND OBJ_ID = :OBJ_ID;
    END
    ELSE
    BEGIN
        SELECT V.BLOB_ID FROM VAL_ADD(2930, :OBJ_ID, :FILE_ID) V INTO :BLOB_ID;
    END

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GIA_EXAM_YEAR_IMPORT_XML (
    Y INTEGER)
RETURNS (
    YEAR_ID BIGINT)
AS
declare variable LISTVAL_ID bigint;
BEGIN
    YEAR_ID = NULL;

    SELECT LV.LISTVAL_ID
    FROM LISTVALS LV
    JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
    WHERE LV.LIST_ID = 29 AND R.VAL_LONG = :Y AND LV.IS_DEL = 0
    INTO :LISTVAL_ID;

    IF (LISTVAL_ID IS NULL) THEN
    BEGIN
        SUSPEND;
        EXIT;
    END

    SELECT FIRST 1 L.OBJ_ID
    FROM LINKS L
    JOIN VALL V ON V.OBJ_ID = L.OBJ_ID AND V.PARAM_ID = 742 AND V.IS_DEL = 0 AND V.LISTVAL_ID = :LISTVAL_ID
    WHERE L.PARENT_ID = 3866 AND L.OBJ_TYPE_ID = 119 AND L.DATE_DEL IS NULL
    INTO :YEAR_ID;

    IF (YEAR_ID IS NULL) THEN
    BEGIN

        /* В ряде баз отсутствует корневой объект 118 - восстанавливаем его */
        UPDATE OR INSERT INTO OBJECTS (OBJ_ID, TYPE_ID, IS_REPL, DATE_MODIFY)
        VALUES (3866, 118, 1, CURRENT_TIMESTAMP);

        UPDATE OR INSERT INTO LINKS (LINK_ID, OBJ_ID, DATE_INS)
        VALUES (9475, 3866, '02.09.2012');

        SELECT O.OBJ_ID
        FROM OBJECT_ADD(3866, 119) O
        INTO :YEAR_ID;

        SELECT V.BLOB_ID
        FROM VAL_ADD(742, :YEAR_ID, :LISTVAL_ID) V
        INTO :LISTVAL_ID;
    END

    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GIA_EXPORT_DATA (
    I$YEAR INTEGER,
    I$DATE_FROM DATE,
    I$JSON SMALLINT = 1)
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$ROOT_ID BIGINT;
DECLARE VARIABLE V$ROOT_TYPE BIGINT;
DECLARE VARIABLE V$OU_ID BIGINT;
DECLARE VARIABLE V$CODE_SCHOOL_EGE BIGINT;
DECLARE VARIABLE V$CODE_SCHOOL_PPE VARCHAR(500);
DECLARE VARIABLE K4 SMALLINT;
DECLARE VARIABLE K9 SMALLINT;
DECLARE VARIABLE K11 SMALLINT;
DECLARE VARIABLE FULLNAME VARCHAR(500);
DECLARE VARIABLE SHORTNAME VARCHAR(500);
DECLARE VARIABLE SCHOOL_NUMBER BIGINT;
DECLARE VARIABLE CODE_SCHOOL_TYPE SMALLINT;
DECLARE VARIABLE CODE_SCHOOL_KIND BIGINT;
DECLARE VARIABLE CODE_SCHOOL_OPF SMALLINT;
DECLARE VARIABLE ADDRESS VARCHAR(500);
DECLARE VARIABLE ADDRESS_PPE VARCHAR(500);
DECLARE VARIABLE LEADER_POSITION VARCHAR(500);
DECLARE VARIABLE LEADER_NAME VARCHAR(500);
DECLARE VARIABLE RESPONSIBLE_FOR_EGE VARCHAR(500);
DECLARE VARIABLE PHONES VARCHAR(500);
DECLARE VARIABLE FAX VARCHAR(500);
DECLARE VARIABLE EMAIL VARCHAR(500);
DECLARE VARIABLE WEB_SITE VARCHAR(500);
DECLARE VARIABLE NUMBER_GRADUATES INTEGER;
DECLARE VARIABLE NUMBER_PRE_GRADUATES INTEGER;
DECLARE VARIABLE LICENSE_NUMBER VARCHAR(50);
DECLARE VARIABLE LICENSE_COMMENCEMENT_DATE DATE;
DECLARE VARIABLE LICENSE_EXPIRATION_DATE DATE;
DECLARE VARIABLE ACCREDITATION_COMMENCEMENT_DATE DATE;
DECLARE VARIABLE ACCREDITATION_EXPIRATION_DATE DATE;
DECLARE VARIABLE OOOD_TYPE VARCHAR(500);
DECLARE VARIABLE OOOD_VID VARCHAR(500);
begin

  SELECT FIRST 1 L.OBJ_ID, L.OBJ_TYPE_ID
  FROM LINKS L
  WHERE L.PARENT_ID IS NULL AND L.OBJ_TYPE_ID IN (2, 111, 112, 124) AND L.DATE_DEL IS NULL
  INTO :V$ROOT_ID, :V$ROOT_TYPE;

  TAG_NAME = 'transfer:transfer-info:transfer-date';
  VAL = (SELECT RESULT FROM DATE2STR(CURRENT_DATE));
  SUSPEND;
  TAG_NAME = 'transfer:transfer-info:transfer-time';
  VAL = (SELECT VAL FROM DATE2ISO(CURRENT_TIMESTAMP));
  VAL = SUBSTRING(VAL FROM 12 FOR 8);
  SUSPEND;
  TAG_NAME = 'transfer:transfer-info:district-name';
  IF(V$ROOT_ID = 111) THEN VAL = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$ROOT_ID));
  ELSE VAL = NULL;
  SUSPEND;

  -- Будет массив при выгрузке json
  IF(I$JSON = 1) THEN
  BEGIN
    TAG_NAME = 'transfer:transfer-data::json&colon;array';
    VAL = 1;
    SUSPEND;
  END
  ELSE
  BEGIN
    TAG_NAME = 'transfer:transfer-data';
    VAL = NULL;
    SUSPEND;
  END

  FOR
    SELECT L.SCHOOL_ID, L.CODE_SCHOOL_EGE, L.CODE_SCHOOL_PPE, L.KL4, L.KL9, L.KL11,
      L.FULLNAME, L.SHORTNAME, L.SCHOOL_NUMBER, L.CODE_SCHOOL_TYPE, L.CODE_SCHOOL_KIND, L.CODE_SCHOOL_OPF, L.ADDRESS, L.ADDRESS_PPE,
      L.LEADER_POSITION, L.LEADER_NAME, L.RESPONSIBLE_FOR_EGE, L.PHONES, L.FAX, L.EMAIL, L.WEB_SITE, L.NUMBER_GRADUATES, L.NUMBER_PRE_GRADUATES,
      L.LICENSE_NUMBER, L.LICENSE_COMMENCEMENT_DATE, L.LICENSE_EXPIRATION_DATE, L.ACCREDITATION_COMMENCEMENT_DATE, L.ACCREDITATION_EXPIRATION_DATE,
      L.OOOD_TYPE, L.OOOD_VID
    FROM GIA_OU_EXPORT_XML(0, 1) L
    INTO :V$OU_ID, :V$CODE_SCHOOL_EGE, :V$CODE_SCHOOL_PPE, :K4, :K9, :K11,
      :FULLNAME, :SHORTNAME, :SCHOOL_NUMBER, :CODE_SCHOOL_TYPE, :CODE_SCHOOL_KIND, :CODE_SCHOOL_OPF, :ADDRESS, :ADDRESS_PPE,
      :LEADER_POSITION, :LEADER_NAME, :RESPONSIBLE_FOR_EGE, :PHONES, :FAX, :EMAIL, :WEB_SITE, :NUMBER_GRADUATES, :NUMBER_PRE_GRADUATES,
      :LICENSE_NUMBER, :LICENSE_COMMENCEMENT_DATE, :LICENSE_EXPIRATION_DATE, :ACCREDITATION_COMMENCEMENT_DATE, :ACCREDITATION_EXPIRATION_DATE,
      :OOOD_TYPE, :OOOD_VID
  DO
  BEGIN

    TAG_NAME = 'transfer:transfer-data:school';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'transfer:transfer-data:school:code-school-EGE';
    VAL = V$CODE_SCHOOL_EGE;
    SUSPEND;
    -- Для xml будут атрибуты, для json - отдельные узлы
    IF(I$JSON = 1) THEN
    BEGIN
      TAG_NAME = 'transfer:transfer-data:school:school-info:code-school-PPE:kl4';
      VAL = K4;
      IF(K4 IS NOT NULL) THEN SUSPEND;
      TAG_NAME = 'transfer:transfer-data:school:school-info:code-school-PPE:kl9';
      VAL = K9;
      IF(K9 IS NOT NULL) THEN SUSPEND;
      TAG_NAME = 'transfer:transfer-data:school:school-info:code-school-PPE:kl11';
      VAL = K11;
      IF(K11 IS NOT NULL) THEN SUSPEND;
      TAG_NAME = 'transfer:transfer-data:school:school-info:code-school-PPE:code';
      VAL = V$CODE_SCHOOL_PPE;
      SUSPEND;
    END
    ELSE
    BEGIN
      TAG_NAME = 'transfer:transfer-data:school:school-info:code-school-PPE::kl4';
      VAL = K4;
      IF(K4 IS NOT NULL) THEN SUSPEND;
      TAG_NAME = 'transfer:transfer-data:school:school-info:code-school-PPE::kl9';
      VAL = K9;
      IF(K9 IS NOT NULL) THEN SUSPEND;
      TAG_NAME = 'transfer:transfer-data:school:school-info:code-school-PPE::kl11';
      VAL = K11;
      IF(K11 IS NOT NULL) THEN SUSPEND;
      TAG_NAME = 'transfer:transfer-data:school:school-info:code-school-PPE';
      VAL = V$CODE_SCHOOL_PPE;
      SUSPEND;
    END

    -- Дополнительные столбцы меняем _ на дефис
    TAG_NAME = 'transfer:transfer-data:school:school-info:fullname';
    VAL = FULLNAME;
    SUSPEND;
    TAG_NAME = 'transfer:transfer-data:school:school-info:shortname';
    VAL = SHORTNAME;
    SUSPEND;
    TAG_NAME = 'transfer:transfer-data:school:school-info:school-number';
    VAL = SCHOOL_NUMBER;
    SUSPEND;
    TAG_NAME = 'transfer:transfer-data:school:school-info:code-school-type';
    VAL = CODE_SCHOOL_TYPE;
    SUSPEND;
    TAG_NAME = 'transfer:transfer-data:school:school-info:code-school-kind';
    VAL = CODE_SCHOOL_KIND;
    SUSPEND;
    TAG_NAME = 'transfer:transfer-data:school:school-info:code-school-opf';
    VAL = CODE_SCHOOL_OPF;
    SUSPEND;
    TAG_NAME = 'transfer:transfer-data:school:school-info:address';
    VAL = ADDRESS;
    SUSPEND;
    TAG_NAME = 'transfer:transfer-data:school:school-info:address-ppe';
    VAL = ADDRESS_PPE;
    SUSPEND;
    TAG_NAME = 'transfer:transfer-data:school:school-info:leader-position';
    VAL = LEADER_POSITION;
    SUSPEND;
    TAG_NAME = 'transfer:transfer-data:school:school-info:leader-name';
    VAL = LEADER_NAME;
    SUSPEND;
    TAG_NAME = 'transfer:transfer-data:school:school-info:responsible-for-ege';
    VAL = RESPONSIBLE_FOR_EGE;
    SUSPEND;
    TAG_NAME = 'transfer:transfer-data:school:school-info:phones';
    VAL = PHONES;
    SUSPEND;
    TAG_NAME = 'transfer:transfer-data:school:school-info:fax';
    VAL = FAX;
    SUSPEND;
    TAG_NAME = 'transfer:transfer-data:school:school-info:email';
    VAL = EMAIL;
    SUSPEND;
    TAG_NAME = 'transfer:transfer-data:school:school-info:web-site';
    VAL = WEB_SITE;
    SUSPEND;
    TAG_NAME = 'transfer:transfer-data:school:school-info:number-graduates';
    VAL = NUMBER_GRADUATES;
    SUSPEND;
    TAG_NAME = 'transfer:transfer-data:school:school-info:number-pre-graduates';
    VAL = NUMBER_PRE_GRADUATES;
    SUSPEND;
    TAG_NAME = 'transfer:transfer-data:school:school-info:license-number';
    VAL = LICENSE_NUMBER;
    SUSPEND;
    TAG_NAME = 'transfer:transfer-data:school:school-info:license-commencement-date';
    VAL = LICENSE_COMMENCEMENT_DATE;
    SUSPEND;
    TAG_NAME = 'transfer:transfer-data:school:school-info:license-expiration-date';
    VAL = LICENSE_EXPIRATION_DATE;
    SUSPEND;
    TAG_NAME = 'transfer:transfer-data:school:school-info:accreditation-commencement-date';
    VAL = ACCREDITATION_COMMENCEMENT_DATE;
    SUSPEND;
    TAG_NAME = 'transfer:transfer-data:school:school-info:accreditation-expiration-date';
    VAL = ACCREDITATION_EXPIRATION_DATE;
    SUSPEND;
    TAG_NAME = 'transfer:transfer-data:school:school-info:oood-type';
    VAL = OOOD_TYPE;
    SUSPEND;
    TAG_NAME = 'transfer:transfer-data:school:school-info:oood-vid';
    VAL = OOOD_VID;
    SUSPEND;

    -- Сотрудники
    -- Будет массив при выгрузке json
    IF(I$JSON = 1) THEN
    BEGIN
      TAG_NAME = 'transfer:transfer-data:school:school-persons::json&colon;array';
      VAL = 1;
      SUSPEND;
    END
    ELSE
    BEGIN
      TAG_NAME = 'transfer:transfer-data:school:school-persons';
      VAL = NULL;
      SUSPEND;
    END

    -- Помещения
    -- Будет массив при выгрузке json
    IF(I$JSON = 1) THEN
    BEGIN
      TAG_NAME = 'transfer:transfer-data:school:school-classrooms::json&colon;array';
      VAL = 1;
      SUSPEND;
    END
    ELSE
    BEGIN
      TAG_NAME = 'transfer:transfer-data:school:school-classrooms';
      VAL = NULL;
      SUSPEND;
    END

    -- Ученики
    -- Будет массив при выгрузке json
    IF(I$JSON = 1) THEN
    BEGIN
      TAG_NAME = 'transfer:transfer-data:school:school-students::json&colon;array';
      VAL = 1;
      SUSPEND;
    END
    ELSE
    BEGIN
      TAG_NAME = 'transfer:transfer-data:school:school-students';
      VAL = NULL;
      SUSPEND;
    END
    -- TODO проверять на дубли обучающихся
    FOR
      SELECT TAG_NAME, VAL
      FROM GIA_EXPORT_DATA_STUDENTS(:V$OU_ID, :I$DATE_FROM, :I$JSON)
      INTO :TAG_NAME, :VAL
    DO
    BEGIN
      TAG_NAME = 'transfer:transfer-data:school:school-students:' || TAG_NAME;
      SUSPEND;
    END

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GIA_EXPORT_DATA_STUDENTS (
    I$OU_ID BIGINT,
    I$DATE_FROM TIMESTAMP,
    I$JSON SMALLINT)
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE CODE_STUDENT_SCHOOL BIGINT;
DECLARE VARIABLE FORM VARCHAR(500);
DECLARE VARIABLE FIO_SURNAME VARCHAR(500);
DECLARE VARIABLE FIO_NAME VARCHAR(500);
DECLARE VARIABLE FIO_PATRONYMIC VARCHAR(500);
DECLARE VARIABLE SEX INTEGER;
DECLARE VARIABLE BIRTHDAY DATE;
DECLARE VARIABLE DOCUMENT_TYPE INTEGER;
DECLARE VARIABLE DOCUMENT_SERIES VARCHAR(500);
DECLARE VARIABLE DOCUMENT_NUMBER VARCHAR(500);
DECLARE VARIABLE SPECIAL_CONDITIONS INTEGER;
DECLARE VARIABLE MEDAL INTEGER;
DECLARE VARIABLE CATEGORY_PARTICIPATION INTEGER;
DECLARE VARIABLE RUS INTEGER;
DECLARE VARIABLE MAT INTEGER;
DECLARE VARIABLE INFO_LANG INTEGER;
DECLARE VARIABLE INFO_IDE INTEGER;
DECLARE VARIABLE INFO_WORD INTEGER;
DECLARE VARIABLE INFO_EXCEL INTEGER;
DECLARE VARIABLE ACCEPT_DATE DATE;
DECLARE VARIABLE VERBAL_FOREIGN_LANG INTEGER;
DECLARE VARIABLE ADMISSION_TO_EXAM INTEGER;
DECLARE VARIABLE SNILS VARCHAR(50);
DECLARE VARIABLE GIA_LEVEL SMALLINT;
DECLARE VARIABLE NATIONALITY VARCHAR(500);
DECLARE VARIABLE GRADUATE_OU VARCHAR(500);
DECLARE VARIABLE PHONE_MOBILE VARCHAR(100);
DECLARE VARIABLE EDUCATION_FORM VARCHAR(40);
DECLARE VARIABLE V$EXAM_ID BIGINT;
begin

  FOR
    SELECT D.CODE_STUDENT_SCHOOL, D.FORM, D.FIO_SURNAME, D.FIO_NAME, D.FIO_PATRONYMIC, D.SEX, D.BIRTHDAY,
      D.DOCUMENT_TYPE, D.DOCUMENT_SERIES, D.DOCUMENT_NUMBER, D.SPECIAL_CONDITIONS, D.MEDAL, D.CATEGORY_PARTICIPATION,
      D.RUS, D.MAT, D.INFO_LANG, D.INFO_IDE, D.INFO_WORD, D.INFO_EXCEL, D.ACCEPT_DATE,
      D.VERBAL_FOREIGN_LANG, D.ADMISSION_TO_EXAM, D.SNILS, D."GIA-LEVEL", D.NATIONALITY, D.GRADUATE_OU,
      D."PHONE-MOBILE", D."EDUCATION-FORM"
    FROM GIA_OU_EXPORT_STUDENT(:I$OU_ID, 1) D
    INTO :CODE_STUDENT_SCHOOL, :FORM, :FIO_SURNAME, :FIO_NAME, :FIO_PATRONYMIC, :SEX, :BIRTHDAY,
      :DOCUMENT_TYPE, :DOCUMENT_SERIES, :DOCUMENT_NUMBER, :SPECIAL_CONDITIONS, :MEDAL, :CATEGORY_PARTICIPATION,
      :RUS, :MAT, :INFO_LANG, :INFO_IDE, :INFO_WORD, :INFO_EXCEL, :ACCEPT_DATE,
      :VERBAL_FOREIGN_LANG, :ADMISSION_TO_EXAM, :SNILS, :GIA_LEVEL, :NATIONALITY, :GRADUATE_OU,
      :PHONE_MOBILE, :EDUCATION_FORM
  DO
  BEGIN
    TAG_NAME = 'student';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'student:fio:surname';
    VAL = FIO_SURNAME;
    SUSPEND;
    TAG_NAME = 'student:fio:name';
    VAL = FIO_NAME;
    SUSPEND;
    TAG_NAME = 'student:fio:patronymic';
    VAL = FIO_PATRONYMIC;
    SUSPEND;
    TAG_NAME = 'student:document:type';
    VAL = DOCUMENT_TYPE;
    SUSPEND;
    TAG_NAME = 'student:document:series';
    VAL = DOCUMENT_SERIES;
    SUSPEND;
    TAG_NAME = 'student:document:number';
    VAL = DOCUMENT_NUMBER;
    SUSPEND;
    TAG_NAME = 'student:informatics-params:lang';
    VAL = INFO_LANG;
    SUSPEND;
    TAG_NAME = 'student:informatics-params:ide';
    VAL = INFO_IDE;
    SUSPEND;
    TAG_NAME = 'student:informatics-params:word';
    VAL = INFO_WORD;
    SUSPEND;
    TAG_NAME = 'student:informatics-params:excel';
    VAL = INFO_EXCEL;
    SUSPEND;
    -- Остальные атрибуты - в корне
    TAG_NAME = 'student:code-student-school';
    VAL = CODE_STUDENT_SCHOOL;
    SUSPEND;
    TAG_NAME = 'student:form';
    VAL = FORM;
    SUSPEND;
    TAG_NAME = 'student:sex';
    VAL = SEX;
    SUSPEND;
    TAG_NAME = 'student:birthday';
    VAL = (SELECT VAL FROM DATE2ISO(:BIRTHDAY, 0));
    SUSPEND;
    TAG_NAME = 'student:special-conditions';
    VAL = SPECIAL_CONDITIONS;
    SUSPEND;
    TAG_NAME = 'student:medal';
    VAL = MEDAL;
    SUSPEND;
    TAG_NAME = 'student:category-participation';
    VAL = CATEGORY_PARTICIPATION;
    SUSPEND;
    TAG_NAME = 'student:rus';
    VAL = RUS;
    SUSPEND;
    TAG_NAME = 'student:mat';
    VAL = MAT;
    SUSPEND;
    TAG_NAME = 'student:accept-date';
    VAL = (SELECT VAL FROM DATE2ISO(:ACCEPT_DATE, 0));
    SUSPEND;
    TAG_NAME = 'student:verbal-foreign-lang';
    VAL = VERBAL_FOREIGN_LANG;
    SUSPEND;
    TAG_NAME = 'student:admission-to-exam';
    VAL = ADMISSION_TO_EXAM;
    SUSPEND;
    TAG_NAME = 'student:snils';
    VAL = SNILS;
    SUSPEND;
    TAG_NAME = 'student:gia-level';
    VAL = GIA_LEVEL;
    SUSPEND;
    TAG_NAME = 'student:nationality';
    VAL = NATIONALITY;
    SUSPEND;
    TAG_NAME = 'student:graduate-ou';
    VAL = GRADUATE_OU;
    SUSPEND;
    TAG_NAME = 'student:phone-mobile';
    VAL = PHONE_MOBILE;
    SUSPEND;
    TAG_NAME = 'student:education-form';
    VAL = EDUCATION_FORM;
    SUSPEND;

    -- Запись на экзамены
    -- Будет массив при выгрузке json
    IF(I$JSON = 1) THEN
    BEGIN
      TAG_NAME = 'student:student-exams::json&colon;array';
      VAL = 1;
      SUSPEND;
    END
    ELSE
    BEGIN
      TAG_NAME = 'student:student-exams';
      VAL = NULL;
      SUSPEND;
    END
    FOR
      SELECT E.EXAM_ID
      FROM GIA_OU_EXPORT_STUDENT_EXAM(:CODE_STUDENT_SCHOOL, 1) E
      INTO :V$EXAM_ID
    DO
    BEGIN
      TAG_NAME = 'student:student-exams:exam-id';
      VAL = V$EXAM_ID;
      SUSPEND;
    END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GIA_FIND_STUDENT (
    SCHOOL_ID BIGINT,
    NAME VARCHAR(200),
    SURNAME VARCHAR(200),
    LASTNAME VARCHAR(200),
    BIRTHDATE DATE,
    DOCUMENT_NUM VARCHAR(100))
RETURNS (
    OBJ_ID BIGINT,
    DATE_DEL1 TIMESTAMP,
    DATE_DEL2 TIMESTAMP,
    DATE_DEL3 TIMESTAMP,
    DATE_DEL4 TIMESTAMP)
AS
DECLARE VARIABLE V$SURNAME VARCHAR(200);
DECLARE VARIABLE N INTEGER;
begin

  -- Помимо ФИО и даты рождения обязательно проверяем номер документа

  FOR
    -- Действующие учащиеся
    SELECT L10.OBJ_ID, CAST(COALESCE(V57.VAL, '') as VARCHAR(200)), L10.DATE_DEL, L9.DATE_DEL, L8.DATE_DEL, L7.DATE_DEL
    FROM LINKS L10
    JOIN LINKS L9 on L9.OBJ_ID = L10.PARENT_ID and L9.PARENT_TYPE_ID = 8
    JOIN LINKS L8 on L8.OBJ_ID = L9.PARENT_ID and L8.PARENT_TYPE_ID IN (7, 502)
    JOIN LINKS L7 on L7.OBJ_ID = L8.PARENT_ID and L7.PARENT_TYPE_ID = 2 and L7.PARENT_ID = :SCHOOL_ID
    JOIN VALS V55 on V55.OBJ_ID = L10.OBJ_ID and V55.PARAM_ID = 55 and V55.IS_DEL = 0 and REPLACE(UPPER(CAST(V55.VAL as VARCHAR(200))), 'Ё', 'Е') = :LASTNAME
    JOIN VALS V56 on V56.OBJ_ID = L10.OBJ_ID and V56.PARAM_ID = 56 and V56.IS_DEL = 0 and REPLACE(UPPER(CAST(V56.VAL as VARCHAR(200))), 'Ё', 'Е') = :NAME
    LEFT JOIN VALS V57 on V57.OBJ_ID = L10.OBJ_ID and V57.PARAM_ID = 57 and V57.IS_DEL = 0 
    JOIN VALD V89 on V89.OBJ_ID = L10.OBJ_ID and V89.PARAM_ID = 89 and V89.IS_DEL = 0 and V89.VAL = :BIRTHDATE
    WHERE L10.OBJ_TYPE_ID = 10 and L10.PARENT_TYPE_ID = 9

    UNION

    -- Выбывшие или окончившие
    SELECT L10.OBJ_ID, CAST(COALESCE(V57.VAL, '') as VARCHAR(200)), L10.DATE_DEL, L78.DATE_DEL, NULL, NULL
    FROM LINKS L10
    JOIN LINKS L78 on L78.OBJ_ID = L78.PARENT_ID and L78.PARENT_TYPE_ID = 2 and L78.PARENT_ID = :SCHOOL_ID
    JOIN VALS V55 on V55.OBJ_ID = L10.OBJ_ID and V55.PARAM_ID = 55 and V55.IS_DEL = 0 and REPLACE(UPPER(CAST(V55.VAL as VARCHAR(200))), 'Ё', 'Е') = :LASTNAME
    JOIN VALS V56 on V56.OBJ_ID = L10.OBJ_ID and V56.PARAM_ID = 56 and V56.IS_DEL = 0 and REPLACE(UPPER(CAST(V56.VAL as VARCHAR(200))), 'Ё', 'Е') = :NAME
    LEFT JOIN VALS V57 on V57.OBJ_ID = L10.OBJ_ID and V57.PARAM_ID = 57 and V57.IS_DEL = 0
    JOIN VALD V89 on V89.OBJ_ID = L10.OBJ_ID and V89.PARAM_ID = 89 and V89.IS_DEL = 0 and V89.VAL = :BIRTHDATE
    WHERE L10.OBJ_TYPE_ID = 10 and L10.PARENT_TYPE_ID in (82, 83)

    UNION

    -- Принятые для сдачи
    SELECT L126.OBJ_ID, CAST(COALESCE(V829.VAL, '') as VARCHAR(200)), L126.DATE_DEL, L125.DATE_DEL, L8.DATE_DEL, L7.DATE_DEL
    FROM LINKS L126
    JOIN LINKS L125 on L125.OBJ_ID = L126.PARENT_ID and L125.PARENT_TYPE_ID = 125
    JOIN LINKS L8 on L8.OBJ_ID = L125.PARENT_ID and L8.PARENT_TYPE_ID IN (7, 502)
    JOIN LINKS L7 on L7.OBJ_ID = L8.PARENT_ID and L7.PARENT_TYPE_ID = 2 and L7.PARENT_ID = :SCHOOL_ID
    JOIN VALS V827 on V827.OBJ_ID = L126.OBJ_ID and V827.PARAM_ID = 827 and V827.IS_DEL = 0 and REPLACE(UPPER(CAST(V827.VAL as VARCHAR(200))), 'Ё', 'Е') = :LASTNAME
    JOIN VALS V828 on V828.OBJ_ID = L126.OBJ_ID and V828.PARAM_ID = 828 and V828.IS_DEL = 0 and REPLACE(UPPER(CAST(V828.VAL as VARCHAR(200))), 'Ё', 'Е') = :NAME
    LEFT JOIN VALS V829 on V829.OBJ_ID = L126.OBJ_ID and V829.PARAM_ID = 829 and V829.IS_DEL = 0
    JOIN VALD V830 on V830.OBJ_ID = L126.OBJ_ID and V830.PARAM_ID = 830 and V830.IS_DEL = 0 and V830.VAL = :BIRTHDATE
    WHERE L126.OBJ_TYPE_ID = 126 and L126.PARENT_TYPE_ID = 125

    INTO :OBJ_ID, :V$SURNAME, :DATE_DEL1, :DATE_DEL2, :DATE_DEL3, :DATE_DEL4

  DO
  BEGIN

      -- Проверяем номер документа
      N = 0;

      SELECT FIRST 1 1
      FROM LINKS D
      JOIN VALS V ON V.OBJ_ID = D.OBJ_ID AND V.PARAM_ID = 559 AND V.IS_DEL = 0 AND V.VAL = :DOCUMENT_NUM
      WHERE D.PARENT_ID = :OBJ_ID AND D.OBJ_ID = 79 AND D.DATE_DEL IS NULL
      INTO :N;

      -- Если отчество есть, то оно должно совпадать
      IF(N = 1 AND SURNAME = REPLACE(UPPER(V$SURNAME), 'Ё', 'Е')) THEN SUSPEND;

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GIA_FOREIGN_LANG_VERBALLY_ADD (
    I$PUPIL_ID BIGINT,
    I$FOREIGN_LANG_VERBALLY SMALLINT,
    I$USER_ID BIGINT)
AS
declare variable V$TYPE_ID bigint;
declare variable V$BLOB_ID bigint;
BEGIN
    SELECT TYPE_ID
    FROM OBJECTS
    WHERE OBJ_ID = :I$PUPIL_ID
    INTO V$TYPE_ID;
    IF(V$TYPE_ID = 10) THEN
    BEGIN
        SELECT BLOB_ID
        FROM VAL_ADD(2154, :I$PUPIL_ID, IIF(:I$FOREIGN_LANG_VERBALLY = 1,2,3), :I$USER_ID)
        INTO :V$BLOB_ID;
    END
    ELSE IF(V$TYPE_ID = 126) THEN
    BEGIN
        SELECT BLOB_ID
        FROM VAL_ADD(2159, :I$PUPIL_ID, IIF(:I$FOREIGN_LANG_VERBALLY = 1,2,3), :I$USER_ID)
        INTO :V$BLOB_ID;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GIA_FORMDATA (
    I$OBJ_ID BIGINT NOT NULL,
    I$YEAR_ID BIGINT NOT NULL,
    I$USER_ID VARCHAR(40) NOT NULL)
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$TYPE_ID BIGINT;
DECLARE VARIABLE V$EXAM_FOLDER BIGINT;
DECLARE VARIABLE V$DATE1 DATE;
DECLARE VARIABLE V$DATE2 DATE;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$OU_ID BIGINT;
DECLARE VARIABLE S VARCHAR(1000);
DECLARE VARIABLE V$FULLNAME VARCHAR(1000);
DECLARE VARIABLE V$MALE VARCHAR(10);
DECLARE VARIABLE V$FEMALE VARCHAR(10);
DECLARE VARIABLE V$BIRTHDAY DATE;
DECLARE VARIABLE V$PUPIL VARCHAR(40);
DECLARE VARIABLE V$FORM VARCHAR(500);
DECLARE VARIABLE V$SPECIAL_CONDITIONS VARCHAR(10);
DECLARE VARIABLE V$DOCTYPE VARCHAR(500);
DECLARE VARIABLE V$PASSSER VARCHAR(100);
DECLARE VARIABLE V$PASSNUM VARCHAR(100);
DECLARE VARIABLE V$PASSDATE DATE;
DECLARE VARIABLE V$PASSINFO VARCHAR(500);
DECLARE VARIABLE V$PHONE VARCHAR(400);
DECLARE VARIABLE V$STAGE_ID BIGINT;
DECLARE VARIABLE V$EXAM_ID BIGINT;
DECLARE VARIABLE V$SUBJECT_ID BIGINT;
DECLARE VARIABLE D DATE;
DECLARE VARIABLE V$ROLE INTEGER;
DECLARE VARIABLE V$PERSON_ID BIGINT;
DECLARE VARIABLE V$LV BIGINT;
DECLARE VARIABLE V$NN SMALLINT;
DECLARE VARIABLE V$NS SMALLINT;
begin

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  SELECT FIRST 1 U.USER_TYPE, U.OBJ_ID
  FROM USERS U
  WHERE U.USER_ID = :I$USER_ID AND U.DATE_DEL IS NULL AND U.IS_BLOCKED = 0 AND (U.EXP_DATE IS NULL OR U.EXP_DATE >= CURRENT_DATE)
  INTO :V$ROLE, :V$PERSON_ID;

  IF(V$ROLE IS NULL OR V$ROLE = 0 OR V$ROLE = 22) THEN EXCEPTION DATA_ERROR 'Пользователь не найден или роль не предполагает доступа к ГИА';
  IF(V$ROLE = 12 AND (V$PERSON_ID IS NULL OR V$PERSON_ID <> I$OBJ_ID)) THEN EXCEPTION DATA_ERROR 'Отказ в доступе к чужим данным';

  SELECT TYPE_ID
  FROM OBJECTS
  WHERE OBJ_ID = :I$OBJ_ID
  INTO :V$TYPE_ID;

  SELECT CAST(LV.TAG AS DATE)
  FROM LISTVALS LV
  WHERE LV.LISTVAL_ID = :I$YEAR_ID
  INTO :V$DATE1;

  V$DATE2 = DATEADD(1 YEAR TO V$DATE1);

  SELECT FIRST 1 L119.OBJ_ID
  FROM LINKS L119
  JOIN VALL V742 ON V742.OBJ_ID = L119.OBJ_ID AND V742.PARAM_ID = 742 AND V742.IS_DEL = 0 AND V742.LISTVAL_ID = :I$YEAR_ID
  WHERE L119.PARENT_ID = 3866 AND L119.OBJ_TYPE_ID = 119 AND L119.DATE_DEL IS NULL
  INTO :V$EXAM_FOLDER;

  IF(V$EXAM_FOLDER IS NULL) THEN EXCEPTION DATA_ERROR 'Нет расписания экзаменов для этого учебного года';

  -- Название ОУ = код ГИА + название
  SELECT FIRST 1 P.OBJ_ID
  FROM OBJECT_PARENTS_GET(:I$OBJ_ID, 2) P
  INTO :V$OU_ID;

  TAG_NAME = 'ou_title';
  SELECT V FROM VAL_GET(:V$OU_ID, 2) INTO :VAL;
  SUSPEND;

  TAG_NAME = 'ou_code';
  SELECT V FROM VAL_GET(:V$OU_ID, 1364) INTO :VAL;
  SUSPEND;

  TAG_NAME = 'director_fio';
  SELECT FIO FROM GIA_GET_DIRECTOR_FIO(:V$OU_ID, 1) INTO :VAL;
  SUSPEND;

  TAG_NAME = 'items::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT DISTINCT L10.OBJ_ID, NULL
    FROM LINKS L10
    WHERE L10.PARENT_TYPE_ID IN (9, 125, 187, 81, 82, 83) AND L10.OBJ_ID = :I$OBJ_ID AND L10.DATE_DEL IS NULL AND :V$TYPE_ID IN (10, 126)
    UNION
    SELECT DISTINCT M.PERSON_ID, C.CAPTION
    FROM PERSON_MOVEMENTS M
    LEFT JOIN OBJECT_CAPTION_GET(M.PERSON_ID) C ON 1 = 1
    WHERE M.DATE_DEL IS NULL AND M.GROUP_ID = :I$OBJ_ID AND :V$TYPE_ID IN (9, 125, 187)
      AND M.DATE_IN < :V$DATE2 AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :V$DATE1)
    ORDER BY 2
    INTO :V$OBJ_ID, :S
  DO
  BEGIN
    TAG_NAME = 'items:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'items:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;

    TAG_NAME = 'items:r:class_name';
    VAL = NULL;
    SELECT FIRST 1 M.NAME_IN, LV.COST
    FROM PERSON_MOVEMENTS M
    JOIN LISTVALS LV ON LV.LISTVAL_ID = M.STAGE_ID
    WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :V$OBJ_ID AND M.DATE_IN < :V$DATE2 AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :V$DATE1)
    ORDER BY M.DATE_IN DESC
    INTO :VAL, :V$STAGE_ID;
    SUSPEND;

    SELECT V.MALE, V.FEMALE, V.PUPIL, V.BIRTHDAY, V.FULLNAME, V.FIO, V.FORM, IIF(V.SPECIAL_CONDITIONS = 0, '', 'V'),
      V.DOCTYPE, V.DOC_S, V.DOC_N, V.PASSDATE, V.PASSINFO, V.CONTACT_PHONE
    FROM GIA_APPOINT_REPORT_HEADER(NULL, :V$OBJ_ID, 1) V
    INTO :V$MALE, :V$FEMALE, :V$PUPIL, :V$BIRTHDAY, :V$FULLNAME, :S, :V$FORM, :V$SPECIAL_CONDITIONS,
      :V$DOCTYPE, :V$PASSSER, :V$PASSNUM, :V$PASSDATE, :V$PASSINFO, :V$PHONE;

    TAG_NAME = 'items:r:male';
    VAL = V$MALE;
    SUSPEND;
    TAG_NAME = 'items:r:female';
    VAL = V$FEMALE;
    SUSPEND;
    TAG_NAME = 'items:r:gender_title';
    VAL = V$PUPIL;
    SUSPEND;
    TAG_NAME = 'items:r:name_full';
    VAL = V$FULLNAME;
    SUSPEND;
    TAG_NAME = 'items:r:name_short';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'items:r:birthdate';
    VAL = (SELECT VAL FROM DATE2SCRIPT(:V$BIRTHDAY));
    SUSPEND;
    TAG_NAME = 'items:r:form';
    VAL = V$FEMALE;
    SUSPEND;
    TAG_NAME = 'items:r:spterms';
    VAL = V$SPECIAL_CONDITIONS;
    SUSPEND;
    TAG_NAME = 'items:r:doc_type';
    VAL = V$DOCTYPE;
    SUSPEND;
    TAG_NAME = 'items:r:doc_serie';
    VAL = V$PASSSER;
    SUSPEND;
    TAG_NAME = 'items:r:doc_num';
    VAL = V$PASSNUM;
    SUSPEND;
    TAG_NAME = 'items:r:doc_date';
    VAL = (SELECT VAL FROM DATE2SCRIPT(:V$PASSDATE));
    SUSPEND;
    TAG_NAME = 'items:r:doc_info';
    VAL = V$PASSINFO;
    SUSPEND;
    TAG_NAME = 'items:r:phone';
    VAL = V$PHONE;
    SUSPEND;

    -- Уровень смотрим по номеру этапа
    -- младшие этапы относятся к СПО
    TAG_NAME = 'items:r:gia_level';
    IF(V$STAGE_ID IN (8, 9, 10)) THEN VAL = 'ГИА-9'; ELSE VAL = 'ГИА-11';
    SUSPEND;

    TAG_NAME = 'items:r:stage_name';
    IF(V$STAGE_ID IN (8, 9, 10)) THEN VAL = 'основного общего образования'; ELSE VAL = 'среднего общего образования';
    SUSPEND;

    V$NN = 0;
    V$NS = 0;

    TAG_NAME = 'items:r:selection::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT L120.OBJ_ID, V803.LISTVAL_ID, V804.VAL, L120.LISTVAL_ID
      FROM LINKS L120
      JOIN LINKS LP119 ON LP119.OBJ_ID = L120.OBJ_ID AND LP119.PARENT_ID = :V$EXAM_FOLDER
      JOIN VALL V803 ON V803.OBJ_ID = L120.OBJ_ID AND V803.PARAM_ID = 803 AND V803.IS_DEL = 0
      JOIN VALD V804 ON V804.OBJ_ID = L120.OBJ_ID AND V804.PARAM_ID = 804 AND V804.IS_DEL = 0
      WHERE L120.PARENT_ID = :V$OBJ_ID AND L120.OBJ_TYPE_ID = 120 AND L120.DATE_DEL IS NULL
      INTO :V$EXAM_ID, :V$SUBJECT_ID, :D, :V$LV
    DO
    BEGIN
      TAG_NAME = 'items:r:selection:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'items:r:selection:r:exam_id';
      VAL = V$EXAM_ID;
      SUSPEND;
      TAG_NAME = 'items:r:selection:r:subject_id';
      VAL = V$SUBJECT_ID;
      SUSPEND;
      TAG_NAME = 'items:r:selection:r:date';
      VAL = (SELECT RESULT FROM DATE2STR(:D));
      SUSPEND;
      -- После подтверждения все LISTVAL_ID выставляются вместо NULL в 0
      IF(V$LV IS NULL) THEN V$NN = 1; ELSE V$NS = 1;
    END

    TAG_NAME = 'items:r:modified';
    VAL = IIF(V$NN = 1 AND V$NS = 1, 1, 0);
    SUSPEND;

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GIA_GET_DIRECTOR_FIO (
    I$SCHOOL_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    F VARCHAR(500),
    I VARCHAR(500),
    O VARCHAR(500),
    FIO VARCHAR(2000),
    POST VARCHAR(500))
AS
DECLARE VARIABLE DIRECTOR_ID BIGINT;
DECLARE VARIABLE ISVPL SMALLINT;
DECLARE VARIABLE LEVEL_ID BIGINT;
BEGIN
    F = NULL;
    I = NULL;
    O = NULL;
    FIO = NULL;
    POST = NULL;
    SELECT KEY_VAL
    FROM KEYS
    WHERE KEY_CODE = 'LEVEL'
    INTO :LEVEL_ID;
    IF (LEVEL_ID = 2) THEN
    BEGIN
        SELECT FIRST 1 L111.OBJ_ID
        FROM LINKS L111
        JOIN LINKS L2 ON L2.PARENT_ID = L111.OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
        WHERE L111.PARENT_ID IS NULL AND L111.OBJ_TYPE_ID = 111 AND L111.DATE_DEL IS NULL AND :LEVEL_ID = 2
        INTO :I$SCHOOL_ID;
        SELECT V
        FROM VAL_GET(:I$SCHOOL_ID, 667, 0, :I$USER_ID)
        INTO :FIO;
        F = FIO;
        I = NULL;
        O = NULL;
        POST = 'Руководитель';
    END
    ELSE
    BEGIN
        SELECT ISVPL
        FROM GIA_IS_VPL
        INTO :ISVPL;

        IF (ISVPL = 0) THEN
        BEGIN
            SELECT OBJ_ID, F, I, O, POST
            FROM R_SPB_POST_DIRECTOR(:I$SCHOOL_ID, :I$USER_ID)
            INTO :DIRECTOR_ID, :F, :I, :O, :POST;

            IF (DIRECTOR_ID IS NOT NULL) THEN
            BEGIN
                SELECT CAPTION
                FROM OBJECT_CAPTION_GET(:DIRECTOR_ID, NULL, NULL, :I$USER_ID)
                INTO :FIO;
            END
        END
        ELSE
        BEGIN
            F = NULL;
            SELECT V
            FROM VAL_GET(:I$SCHOOL_ID, 756, 0, :I$USER_ID)
            INTO :F;
            I = NULL;
            SELECT V
            FROM VAL_GET(:I$SCHOOL_ID, 757, 0, :I$USER_ID)
            INTO :I;
            O = NULL;
            SELECT V
            FROM VAL_GET(:I$SCHOOL_ID, 758, 0, :I$USER_ID)
            INTO :O;
            FIO = F || ' ' || I;
            IF (O IS NOT NULL) THEN FIO = FIO || ' ' || O;
            POST = 'Ответственный за регистрацию ВПЛ';
        END
    END
    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GIA_IS_VPL RETURNS (
    ISVPL SMALLINT)
AS
BEGIN
    SELECT COUNT(L.OBJ_ID)
    FROM LINKS L
    WHERE L.PARENT_ID IS NULL
      AND L.OBJ_TYPE_ID = 124
      AND L.DATE_DEL IS NULL
    INTO :ISVPL;
    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GIA_NOT_PERMIT_LIST (
    I$SCHOOL_ID BIGINT,
    I$GRADUATE SMALLINT,
    I$USER_ID BIGINT)
RETURNS (
    NUMBER INTEGER,
    FIO VARCHAR(1000),
    E1 VARCHAR(1),
    E2 VARCHAR(1),
    E3 VARCHAR(1),
    E4 VARCHAR(1),
    SCHOOL_SHORT_NAME VARCHAR(1000),
    E5 VARCHAR(1),
    E6 VARCHAR(1),
    CLASS_NAME VARCHAR(255),
    BIRTHDAY DATE,
    DOCUMENT VARCHAR(255))
AS
declare variable V$CLASS_ID bigint;
declare variable V$PUPIL_ID bigint;
declare variable V$OBJ_TYPE bigint;
declare variable V$FIO_SURNAME varchar(500);
declare variable V$FIO_NAME varchar(500);
declare variable V$FIO_PATRONYMIC varchar(500);
declare variable V$HAS_PERMIT smallint;
BEGIN
    NUMBER = 1;
    E1 = NULL;
    E2 = NULL;
    E3 = NULL;
    E4 = NULL;
    E5 = NULL;
    E6 = NULL;

    SELECT V
    FROM VAL_GET(:I$SCHOOL_ID, 2, 0, :I$USER_ID)
    INTO :SCHOOL_SHORT_NAME;

    FOR
        SELECT OBJ_ID,
               OBJ_CAPTION
        FROM GIA_APPOINT_CLASS_LIST(:I$SCHOOL_ID, :I$USER_ID)
        WHERE GRADUATE = COALESCE(:I$GRADUATE, GRADUATE)
        INTO :V$CLASS_ID, :CLASS_NAME
    DO
    BEGIN
        FOR
            SELECT SL.OBJ_ID,
                   O.TYPE_ID
            FROM GIA_CLASS_SCHOLAR_LIST(:V$CLASS_ID) SL
            JOIN OBJECTS O
            ON O.OBJ_ID = SL.OBJ_ID
            INTO :V$PUPIL_ID,
                 :V$OBJ_TYPE
        DO
        BEGIN
            IF (:V$OBJ_TYPE = 10) THEN
            BEGIN
                SELECT V
                FROM VAL_GET(:V$PUPIL_ID, 55, 0, :I$USER_ID)
                INTO :V$FIO_SURNAME;

                SELECT V
                FROM VAL_GET(:V$PUPIL_ID, 56, 0, :I$USER_ID)
                INTO :V$FIO_NAME;

                SELECT V
                FROM VAL_GET(:V$PUPIL_ID, 57, 0, :I$USER_ID)
                INTO :V$FIO_PATRONYMIC;

                SELECT D
                FROM VAL_GET(:V$PUPIL_ID, 89, 0, :I$USER_ID)
                INTO :BIRTHDAY;

                SELECT IIF(I = 2, 1, 0)
                FROM VAL_GET(:V$PUPIL_ID, 2155, 0, :I$USER_ID)
                INTO :V$HAS_PERMIT;
            END
            ELSE
            BEGIN
                SELECT V
                FROM VAL_GET(:V$PUPIL_ID, 827, 0, :I$USER_ID)
                INTO :V$FIO_SURNAME;

                SELECT V
                FROM VAL_GET(:V$PUPIL_ID, 828, 0, :I$USER_ID)
                INTO :V$FIO_NAME;

                SELECT V
                FROM VAL_GET(:V$PUPIL_ID, 829, 0, :I$USER_ID)
                INTO :V$FIO_PATRONYMIC;

                SELECT D
                FROM VAL_GET(:V$PUPIL_ID, 830, 0, :I$USER_ID)
                INTO :BIRTHDAY;

                SELECT IIF(I = 2, 1, 0)
                FROM VAL_GET(:V$PUPIL_ID, 2160, 0, :I$USER_ID)
                INTO :V$HAS_PERMIT;
            END

            IF (V$HAS_PERMIT = 0) THEN
            BEGIN
                DOCUMENT = NULL;
                SELECT FIRST 1
                       V442.VAL || ' ' || V559.VAL
                FROM LINKS L79
    
                LEFT JOIN VALS V442
                ON V442.OBJ_ID = L79.OBJ_ID
                AND V442.PARAM_ID = 442
                AND V442.IS_DEL = 0
    
                LEFT JOIN VALS V559
                ON V559.OBJ_ID = L79.OBJ_ID
                AND V559.PARAM_ID = 559
                AND V559.IS_DEL = 0
    
                LEFT JOIN VALD V561
                ON V561.OBJ_ID = L79.OBJ_ID
                AND V561.PARAM_ID = 561
                AND V561.IS_DEL = 0
    
                WHERE L79.PARENT_ID = :V$PUPIL_ID
                AND L79.OBJ_TYPE_ID = 79
                AND L79.DATE_DEL IS NULL
                AND ((V561.VAL IS NULL) OR (V561.VAL > CURRENT_DATE))
                INTO :DOCUMENT;
    
                FIO = V$FIO_SURNAME || ' ' || V$FIO_NAME || ' ' || V$FIO_PATRONYMIC;
                SUSPEND;
                NUMBER = NUMBER + 1;
            END
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GIA_NOT_PERMIT_LIST_DISTR (
    I$DISTR_ID BIGINT,
    I$GRADUATE SMALLINT,
    I$USER_ID BIGINT)
RETURNS (
    NUMBER INTEGER,
    FIO VARCHAR(1000),
    E1 VARCHAR(1),
    E2 VARCHAR(1),
    E3 VARCHAR(1),
    E4 VARCHAR(1),
    SCHOOL_SHORT_NAME VARCHAR(1000),
    E5 VARCHAR(1),
    E6 VARCHAR(1),
    CLASS_NAME VARCHAR(255),
    BIRTHDAY DATE,
    DOCUMENT VARCHAR(255))
AS
DECLARE VARIABLE V$SCHOOL_ID BIGINT;
BEGIN
    NUMBER = 1;
    E1 = NULL;
    E2 = NULL;
    E3 = NULL;
    E4 = NULL;
    E5 = NULL;
    E6 = NULL;

    FOR
        SELECT OBJ_ID
        FROM LINKS
        WHERE PARENT_ID = :I$DISTR_ID
        AND OBJ_TYPE_ID = 2
        AND DATE_DEL IS NULL
        INTO :V$SCHOOL_ID
    DO
    BEGIN
        FOR
            SELECT FIO, SCHOOL_SHORT_NAME, CLASS_NAME, BIRTHDAY, DOCUMENT
            FROM GIA_NOT_PERMIT_LIST(:V$SCHOOL_ID, :I$GRADUATE, :I$USER_ID)
            INTO :FIO, :SCHOOL_SHORT_NAME, :CLASS_NAME, :BIRTHDAY, :DOCUMENT
        DO
        BEGIN
            SUSPEND;
            NUMBER = NUMBER + 1;
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GIA_OU_EXPORT_CHECK (
    I$USER_ID BIGINT)
RETURNS (
    ERR INTEGER,
    OPR INTEGER,
    VAL VARCHAR(4000),
    VAL2 VARCHAR(500))
AS
DECLARE VARIABLE PUNKT_ID BIGINT;
DECLARE VARIABLE SCHOOL_ID BIGINT;
DECLARE VARIABLE TEACHER_ID BIGINT;
DECLARE VARIABLE CODE_PPE INTEGER;
DECLARE VARIABLE CODE_OU INTEGER;
DECLARE VARIABLE C INTEGER;
DECLARE VARIABLE V VARCHAR(4000);
DECLARE VARIABLE DT DATE;
DECLARE VARIABLE Y SMALLINT;
DECLARE VARIABLE BUILDING_ID BIGINT;
DECLARE VARIABLE ROOM_OBJ_ID BIGINT;
DECLARE VARIABLE DOCUM_ID BIGINT;
DECLARE VARIABLE SCHOLAR_ID BIGINT;
DECLARE VARIABLE CLASS_ID BIGINT;
DECLARE VARIABLE STAGE_ID BIGINT;
DECLARE VARIABLE SCHOLAR_DATE DATE;
DECLARE VARIABLE SCHOLAR_SEX BIGINT;
DECLARE VARIABLE CLASS_ID1 BIGINT;
DECLARE VARIABLE CLASS_ID2 BIGINT;
DECLARE VARIABLE SCHOLAR_ID1 BIGINT;
DECLARE VARIABLE SCHOLAR_ID2 BIGINT;
DECLARE VARIABLE LANG_CODE VARCHAR(2);
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :LANG_CODE;

    SELECT FIRST 1 L.OBJ_ID
    FROM LINKS L
    WHERE L.PARENT_ID IS NULL
    AND L.OBJ_TYPE_ID = 2
    AND L.DATE_DEL IS NULL
    INTO :SCHOOL_ID;

    SELECT FIRST 1 L.OBJ_ID
    FROM LINKS L
    WHERE L.PARENT_ID IS NULL
    AND L.OBJ_TYPE_ID = 124
    AND L.DATE_DEL IS NULL
    INTO :PUNKT_ID;

    Y = EXTRACT(YEAR FROM CURRENT_DATE);
    DT = Y || '-09-01';
    IF (CURRENT_DATE > DT) THEN
    BEGIN
        Y = Y + 1;
    END
    DT = Y || '-07-15';

    /* 1 code PPE */

    SELECT COUNT(*)
    FROM VALI V
    WHERE V.PARAM_ID = 1365
    AND V.OBJ_ID = :SCHOOL_ID
    AND V.IS_DEL = 0
    INTO :CODE_PPE;

    IF (CODE_PPE > 0) THEN
    BEGIN
        SELECT COUNT(*)
        FROM VALA V
        WHERE V.PARAM_ID = 1371
        AND V.OBJ_ID = :SCHOOL_ID
        AND V.IS_DEL = 0
        INTO :C;

        IF (C = 0) THEN
        BEGIN
            ERR = 1;
            OPR = 1;
            VAL = '';
            SUSPEND;
        END

        BUILDING_ID = NULL;

        SELECT V.VAL
        FROM VALR V
        WHERE V.PARAM_ID = 1370
        AND V.OBJ_ID = :SCHOOL_ID
        AND V.IS_DEL = 0
        INTO :BUILDING_ID;

        IF (BUILDING_ID IS NOT NULL) THEN
        BEGIN
            FOR
                SELECT L61.OBJ_ID

                FROM LINKS L61

                JOIN VALS V1403
                ON V1403.OBJ_ID = L61.OBJ_ID
                AND V1403.PARAM_ID = 1403
                AND V1403.IS_DEL = 0

                WHERE L61.PARENT_ID = :BUILDING_ID
                AND L61.OBJ_TYPE_ID = 61
                AND L61.DATE_DEL IS NULL

                INTO :ROOM_OBJ_ID
            DO
            BEGIN
                SELECT COUNT(*)
                FROM VALI V529
                WHERE V529.OBJ_ID = :ROOM_OBJ_ID
                AND V529.PARAM_ID = 529
                AND V529.IS_DEL = 0
                AND V529.VAL > 0
                INTO :C;

                IF (C = 0) THEN
                BEGIN
                    SELECT CAPTION
                    FROM OBJECT_CAPTION_GET(:ROOM_OBJ_ID)
                    INTO :VAL;

                    ERR = 1;
                    OPR = 17;
                    SUSPEND;
                END

                SELECT SUM(V.VAL)

                FROM LINKS L

                JOIN VALI V
                ON V.OBJ_ID = L.OBJ_ID
                AND V.PARAM_ID = 1372
                AND V.IS_DEL = 0

                WHERE L.PARENT_ID = :ROOM_OBJ_ID
                AND L.OBJ_TYPE_ID = 122
                AND L.DATE_DEL IS NULL

                INTO :C;

                IF ((C IS NULL) OR (C = 0)) THEN
                BEGIN
                    SELECT CAPTION
                    FROM OBJECT_CAPTION_GET(:ROOM_OBJ_ID)
                    INTO :VAL;

                    ERR = 1;
                    OPR = 20;
                    SUSPEND;
                END
            END

            /* OPR = 18; OPR = 19;  */
        END
    END

    /* 2-11 code OU */

    SELECT COUNT(*)
    FROM VALI V
    WHERE V.PARAM_ID = 1364
    AND V.OBJ_ID = :SCHOOL_ID
    AND V.IS_DEL = 0
    INTO :CODE_OU;

    IF (CODE_OU > 0) THEN
    BEGIN
        SELECT COUNT(*)
        FROM VALR V
        WHERE V.PARAM_ID = 1369
        AND V.OBJ_ID = :SCHOOL_ID
        AND V.IS_DEL = 0
        INTO :C;

        IF (C = 0) THEN
        BEGIN
            ERR = 1;
            OPR = 2;
            VAL = '';
            SUSPEND;
        END

        SELECT COUNT(*)
        FROM VALS V
        WHERE V.PARAM_ID = 5
        AND V.OBJ_ID = :SCHOOL_ID
        AND V.IS_DEL = 0
        INTO :C;

        IF (C = 0) THEN
        BEGIN
            ERR = 1;
            OPR = 3;
            VAL = '';
            SUSPEND;
        END

        SELECT COUNT(*)
        FROM VALS V
        WHERE V.PARAM_ID = 2
        AND V.OBJ_ID = :SCHOOL_ID
        AND V.IS_DEL = 0
        INTO :C;

        IF (C = 0) THEN
        BEGIN
            ERR = 1;
            OPR = 4;
            VAL = '';
            SUSPEND;
        END

        V = '';

        SELECT F
        FROM R_SPB_POST_DIRECTOR(:SCHOOL_ID, :I$USER_ID)
        INTO :V;

        IF (V = '') THEN
        BEGIN
            ERR = 1;
            OPR = 6;
            VAL = '';
            SUSPEND;
        END

        SELECT COUNT(*)

        FROM LINKS L

        JOIN VALL V471
        ON L.OBJ_ID = V471.OBJ_ID
        AND V471.PARAM_ID = 471
        AND V471.IS_DEL = 0
        AND V471.LISTVAL_ID IN (1053, 18625)

        JOIN VALD V483
        ON L.OBJ_ID = V483.OBJ_ID
        AND V483.PARAM_ID = 483
        AND V483.IS_DEL = 0
        AND V483.VAL >= :DT

        WHERE L.PARENT_ID = :SCHOOL_ID
        AND L.OBJ_TYPE_ID = 17
        AND L.DATE_DEL IS NULL

        INTO :C;

        IF (C = 0) THEN
        BEGIN
            SELECT COUNT(*)

            FROM LINKS L

            JOIN VALL V471
            ON L.OBJ_ID = V471.OBJ_ID
            AND V471.PARAM_ID = 471
            AND V471.IS_DEL = 0
            AND V471.LISTVAL_ID IN (1053, 18625)

            JOIN VALD V483
            ON L.OBJ_ID = V483.OBJ_ID
            AND V483.PARAM_ID = 483
            AND V483.IS_DEL = 0

            WHERE L.PARENT_ID = :SCHOOL_ID
            AND L.OBJ_TYPE_ID = 17
            AND L.DATE_DEL IS NULL

            INTO :Y;

            IF (Y > 0) THEN
            BEGIN
                ERR = 0;
                OPR = 7;
                VAL = '';
            END
            ELSE
            BEGIN
                ERR = 0;
                OPR = 8;
                VAL = '';
            END
            SUSPEND;
        END

        SELECT COUNT(*)

        FROM LINKS L

        JOIN VALL V471
        ON L.OBJ_ID = V471.OBJ_ID
        AND V471.PARAM_ID = 471
        AND V471.IS_DEL = 0
        AND V471.LISTVAL_ID IN (1052, 1079, 18624)

        LEFT JOIN VALD V483
        ON L.OBJ_ID = V483.OBJ_ID
        AND V483.PARAM_ID = 483
        AND V483.IS_DEL = 0

        WHERE L.PARENT_ID = :SCHOOL_ID
        AND L.OBJ_TYPE_ID = 17
        AND L.DATE_DEL IS NULL

        AND ((V483.VAL >= :DT) OR (V483.VAL IS NULL))
        INTO :C;

        IF (C = 0) THEN
        BEGIN
            SELECT COUNT(*)

            FROM LINKS L

            JOIN VALL V471
            ON L.OBJ_ID = V471.OBJ_ID
            AND V471.PARAM_ID = 471
            AND V471.IS_DEL = 0
            AND V471.LISTVAL_ID IN (1052, 1079, 18624)

            JOIN VALD V483
            ON L.OBJ_ID = V483.OBJ_ID
            AND V483.PARAM_ID = 483
            AND V483.IS_DEL = 0

            WHERE L.PARENT_ID = :SCHOOL_ID
            AND L.OBJ_TYPE_ID = 17
            AND L.DATE_DEL IS NULL

            INTO :Y;

            IF (Y > 0) THEN
            BEGIN
                ERR = 0;
                OPR = 9;
                VAL = '';
            END
            ELSE
            BEGIN
                ERR = 0;
                OPR = 10;
                VAL = '';
            END
            SUSPEND;
        END

        SELECT COUNT(*)

        FROM LINKS L7

        JOIN LINKS L8
        ON L7.OBJ_ID = L8.PARENT_ID
        AND L8.OBJ_TYPE_ID = 8
        AND L8.DATE_DEL IS NULL

        JOIN LINKS L9
        ON L8.OBJ_ID = L9.PARENT_ID
        AND L9.OBJ_TYPE_ID IN (9,187)
        AND L9.DATE_DEL IS NULL

        JOIN VALL V2388
        ON L9.OBJ_ID = V2388.OBJ_ID
        AND V2388.PARAM_ID IN (2388,2418)
        AND V2388.IS_DEL = 0
        AND V2388.LISTVAL_ID IN (11202, 11203)

        WHERE L7.PARENT_ID = :SCHOOL_ID
        AND L7.OBJ_TYPE_ID = 7
        AND L7.DATE_DEL IS NULL

        INTO :C;

        IF (C = 0) THEN
        BEGIN
            ERR = 0;
            OPR = 11;
            VAL = '';
            SUSPEND;
        END

        /* 12-18  code OU + post in PPE or class_master */

        FOR
            SELECT L.OBJ_ID

            FROM LINKS L

            JOIN VALL V1376
            ON L.OBJ_ID = V1376.OBJ_ID
            AND V1376.PARAM_ID = 1376
            AND V1376.IS_DEL = 0
            AND V1376.LISTVAL_ID > 2989

            WHERE L.PARENT_ID = :SCHOOL_ID
            AND L.OBJ_TYPE_ID = 14
            AND L.DATE_DEL IS NULL

            UNION

            SELECT L14.OBJ_ID

            FROM LINKS L14

            JOIN LINKS L7
            ON L7.PARENT_ID = L14.PARENT_ID
            AND L7.OBJ_TYPE_ID = 7
            AND L7.DATE_DEL IS NULL

            JOIN LINKS L8
            ON L8.PARENT_ID = L7.OBJ_ID
            AND L8.OBJ_TYPE_ID = 8
            AND L8.DATE_DEL IS NULL

            JOIN LINKS L9
            ON L9.PARENT_ID = L8.OBJ_ID
            AND L9.OBJ_TYPE_ID = 9
            AND L9.DATE_DEL IS NULL

            JOIN VALR V53
            ON V53.OBJ_ID = L9.OBJ_ID
            AND V53.VAL = L14.OBJ_ID
            AND V53.PARAM_ID = 53
            AND V53.IS_DEL = 0

            WHERE L14.PARENT_ID = :SCHOOL_ID
            AND L14.OBJ_TYPE_ID = 14
            AND L14.DATE_DEL IS NULL

            INTO :TEACHER_ID
        DO
        BEGIN
            DOCUM_ID = NULL;

            SELECT FIRST 1 L.OBJ_ID

            FROM LINKS L

            JOIN VALL V
            ON V.OBJ_ID = L.OBJ_ID
            AND V.PARAM_ID = 441
            AND V.IS_DEL = 0

            WHERE L.PARENT_ID = :TEACHER_ID
            AND L.OBJ_TYPE_ID = 79
            AND L.DATE_DEL IS NULL

            ORDER BY V.LISTVAL_ID
            INTO :DOCUM_ID;

            IF (DOCUM_ID IS NULL) THEN
            BEGIN
                SELECT CAPTION
                FROM OBJECT_CAPTION_GET(:TEACHER_ID)
                INTO :VAL;

                ERR = 1;
                OPR = 31;
                SUSPEND;
            END
            ELSE
            BEGIN
                SELECT COUNT(*)
                FROM VALS V
                WHERE V.PARAM_ID = 442
                AND V.OBJ_ID = :DOCUM_ID
                AND V.IS_DEL = 0
                INTO :C;

                IF (C = 0) THEN
                BEGIN
                    SELECT CAPTION
                    FROM OBJECT_CAPTION_GET(:TEACHER_ID)
                    INTO :VAL;

                    ERR = 1;
                    OPR = 32;
                    SUSPEND;
                END

                SELECT COUNT(*)
                FROM VALS V
                WHERE V.PARAM_ID = 559
                AND V.OBJ_ID = :DOCUM_ID
                AND V.IS_DEL = 0
                INTO :C;

                IF (C = 0) THEN
                BEGIN
                    SELECT CAPTION
                    FROM OBJECT_CAPTION_GET(:TEACHER_ID)
                    INTO :VAL;

                    ERR = 1;
                    OPR = 33;
                    SUSPEND;
                END
            END

            SELECT COUNT(*)
            FROM VALL V1376
            WHERE V1376.OBJ_ID = :TEACHER_ID
            AND V1376.PARAM_ID = 1376
            AND V1376.IS_DEL = 0
            AND V1376.LISTVAL_ID > 2989
            INTO :C;

            IF (C > 0) THEN
            BEGIN
                SELECT COUNT(*)

                FROM VALL V1395

                JOIN VALL V1396
                ON V1395.OBJ_ID = V1396.OBJ_ID
                AND V1396.PARAM_ID = 1396
                AND V1396.OBJ_ID = :TEACHER_ID
                AND V1396.IS_DEL = 0

                WHERE V1395.PARAM_ID = 1395
                AND V1395.OBJ_ID = :TEACHER_ID
                AND V1395.IS_DEL = 0
                AND ((V1395.LISTVAL_ID = 2) OR (V1396.LISTVAL_ID = 2))
                INTO :C;

                IF (C = 0) THEN
                BEGIN
                    SELECT CAPTION
                    FROM OBJECT_CAPTION_GET(:TEACHER_ID)
                    INTO :VAL;

                    ERR = 1;
                    OPR = 34;
                    SUSPEND;
                END
            END
        END
    END

    /* All wokers check */

    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.PARENT_ID = :SCHOOL_ID
        AND L.OBJ_TYPE_ID = 14
        AND L.DATE_DEL IS NULL
        INTO :TEACHER_ID
    DO
    BEGIN
        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:TEACHER_ID)
        INTO :VAL;

        SELECT COUNT(*)
        FROM VALL V
        WHERE V.PARAM_ID = 239
        AND V.OBJ_ID = :TEACHER_ID
        AND V.IS_DEL = 0
        INTO :C;

        IF (C = 0) THEN
        BEGIN
            ERR = 1;
            OPR = 21;
            SUSPEND;
        END

        SELECT COUNT(*)
        FROM VALD V
        WHERE V.PARAM_ID = 241
        AND V.OBJ_ID = :TEACHER_ID
        AND V.IS_DEL = 0
        AND V.VAL >= '1900-01-01'
        INTO :C;

        IF (C = 0) THEN
        BEGIN
            ERR = 1;
            OPR = 22;
            SUSPEND;
        END

        SELECT COUNT(*)
        FROM VALL V
        WHERE V.PARAM_ID = 274
        AND V.OBJ_ID = :TEACHER_ID
        AND V.IS_DEL = 0
        INTO :C;

        IF (C = 0) THEN
        BEGIN
            ERR = 1;
            OPR = 23;
            SUSPEND;
        END

        SELECT COUNT(*)
        FROM VALL V
        WHERE V.PARAM_ID = 278
        AND V.OBJ_ID = :TEACHER_ID
        AND V.IS_DEL = 0
        INTO :C;

        IF (C = 0) THEN
        BEGIN
            ERR = 1;
            OPR = 24;
            SUSPEND;
        END

        -- Должна быть указана квалификационная категория
        C = NULL;
        SELECT COUNT(*)
        FROM LINKS L14_15
        JOIN LINKS L13_15 ON L13_15.OBJ_ID = L14_15.OBJ_ID AND L13_15.PARENT_TYPE_ID = 13 AND L13_15.DATE_DEL IS NULL
        -- только основная должность
        JOIN VALL V72 ON V72.OBJ_ID = L14_15.OBJ_ID AND V72.PARAM_ID = 72 AND V72.IS_DEL = 0 AND V72.LISTVAL_ID = 934
        -- числится на должности
        LEFT JOIN VALD V74 ON V74.OBJ_ID = L14_15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
        -- категория по должности
        JOIN VALL V1790 ON V1790.OBJ_ID = L14_15.OBJ_ID AND V1790.PARAM_ID = 1790 AND V1790.IS_DEL = 0
        WHERE L14_15.PARENT_ID = :TEACHER_ID AND L14_15.OBJ_TYPE_ID = 15 AND L14_15.DATE_DEL IS NULL AND (V74.VAL IS NULL OR V74.VAL > CURRENT_TIMESTAMP)
        INTO :C;

        IF (C IS NULL OR C = 0) THEN
        BEGIN
            ERR = 1;
            OPR = 25;
            SUSPEND;
        END

        SELECT COUNT(*)

        FROM VALL V

        JOIN VALL W
        ON V.OBJ_ID = W.OBJ_ID
        AND W.PARAM_ID = 278
        AND W.IS_DEL = 0
        AND W.LISTVAL_ID <> 620

        WHERE V.PARAM_ID = 279
        AND V.OBJ_ID = :TEACHER_ID
        AND V.IS_DEL = 0
        AND V.LISTVAL_ID > 626

        INTO :C;

        IF (C = 1) THEN
        BEGIN
            ERR = 1;
            OPR = 26;
            SUSPEND;
        END
    END

    FOR
        SELECT V.LISTVAL_ID,
               L9.OBJ_ID,
               L10.OBJ_ID,
               V89.VAL,
               V88.LISTVAL_ID

        FROM LINKS L7

        JOIN LINKS L8
        ON L8.PARENT_ID = L7.OBJ_ID
        AND L8.OBJ_TYPE_ID = 8
        AND L8.DATE_DEL IS NULL

        JOIN LINKS L9
        ON L9.PARENT_ID = L8.OBJ_ID
        AND L9.OBJ_TYPE_ID IN (9,187)
        AND L9.DATE_DEL IS NULL

        JOIN LINKS L10
        ON L10.PARENT_ID = L9.OBJ_ID
        AND L10.OBJ_TYPE_ID = 10
        AND L10.DATE_DEL IS NULL

        JOIN VALL V
        ON V.OBJ_ID = L8.OBJ_ID
        AND V.PARAM_ID = 49
        AND V.IS_DEL = 0

        LEFT JOIN VALD V89
        ON V89.PARAM_ID = 89
        AND V89.OBJ_ID = L10.OBJ_ID
        AND V89.IS_DEL = 0

        LEFT JOIN VALL V88
        ON V88.PARAM_ID = 88
        AND V88.OBJ_ID = L10.OBJ_ID
        AND V88.IS_DEL = 0

        WHERE L7.PARENT_ID = :SCHOOL_ID
        AND L7.OBJ_TYPE_ID = 7
        AND L7.DATE_DEL IS NULL

        UNION

        SELECT 47,
               L9.OBJ_ID,
               L126.OBJ_ID,
               V830.VAL,
               V1022.LISTVAL_ID

        FROM LINKS L7

        JOIN LINKS L8
        ON L8.PARENT_ID = L7.OBJ_ID
        AND L8.OBJ_TYPE_ID = 8
        AND L8.DATE_DEL IS NULL

        JOIN LINKS L9
        ON L9.PARENT_ID = L8.OBJ_ID
        AND L9.OBJ_TYPE_ID = 9
        AND L9.DATE_DEL IS NULL

        JOIN LINKS L126
        ON L126.PARENT_ID = L9.OBJ_ID
        AND L126.OBJ_TYPE_ID = 126
        AND L126.DATE_DEL IS NULL

        LEFT JOIN VALD V830
        ON V830.PARAM_ID = 830
        AND V830.OBJ_ID = L126.OBJ_ID
        AND V830.IS_DEL = 0

        LEFT JOIN VALL V1022
        ON V1022.PARAM_ID = 1022
        AND V1022.OBJ_ID = L126.OBJ_ID
        AND V1022.IS_DEL = 0

        WHERE L7.PARENT_ID = :SCHOOL_ID
        AND L7.OBJ_TYPE_ID = 7
        AND L7.DATE_DEL IS NULL

        UNION

        SELECT 47,
               L125.OBJ_ID,
               L126.OBJ_ID,
               V830.VAL,
               V1022.LISTVAL_ID

        FROM LINKS L7

        JOIN LINKS L8
        ON L8.PARENT_ID = L7.OBJ_ID
        AND L8.OBJ_TYPE_ID = 8
        AND L8.DATE_DEL IS NULL

        JOIN LINKS L125
        ON L125.PARENT_ID = L8.OBJ_ID
        AND L125.OBJ_TYPE_ID = 125
        AND L125.DATE_DEL IS NULL

        JOIN LINKS L126
        ON L126.PARENT_ID = L125.OBJ_ID
        AND L126.OBJ_TYPE_ID = 126
        AND L126.DATE_DEL IS NULL

        LEFT JOIN VALD V830
        ON V830.PARAM_ID = 830
        AND V830.OBJ_ID = L126.OBJ_ID
        AND V830.IS_DEL = 0

        LEFT JOIN VALL V1022
        ON V1022.PARAM_ID = 1022
        AND V1022.OBJ_ID = L126.OBJ_ID
        AND V1022.IS_DEL = 0

        WHERE L7.PARENT_ID = :SCHOOL_ID
        AND L7.OBJ_TYPE_ID = 7
        AND L7.DATE_DEL IS NULL

        UNION

        SELECT 47,
               L125.OBJ_ID,
               L126.OBJ_ID,
               V830.VAL,
               V1022.LISTVAL_ID

        FROM LINKS L125

        JOIN LINKS L126
        ON L126.PARENT_ID = L125.OBJ_ID
        AND L126.OBJ_TYPE_ID = 126
        AND L126.DATE_DEL IS NULL

        LEFT JOIN VALD V830
        ON V830.PARAM_ID = 830
        AND V830.OBJ_ID = L126.OBJ_ID
        AND V830.IS_DEL = 0

        LEFT JOIN VALL V1022
        ON V1022.PARAM_ID = 1022
        AND V1022.OBJ_ID = L126.OBJ_ID
        AND V1022.IS_DEL = 0

        WHERE L125.PARENT_ID = :PUNKT_ID
        AND L125.OBJ_TYPE_ID = 125
        AND L125.DATE_DEL IS NULL

        INTO :STAGE_ID,
             :CLASS_ID,
             :SCHOLAR_ID,
             :SCHOLAR_DATE,
             :SCHOLAR_SEX
    DO
    BEGIN
        IF ((SCHOLAR_DATE IS NULL) OR (SCHOLAR_DATE < '1900-01-01')) THEN
        BEGIN
            ERR = 1;
            OPR = 41;

            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:SCHOLAR_ID)
            INTO :VAL;

            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:CLASS_ID)
            INTO :VAL2;

            SUSPEND;

            VAL2 = NULL;
        END

        IF (SCHOLAR_SEX IS NULL) THEN
        BEGIN
            ERR = 1;
            OPR = 42;

            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:SCHOLAR_ID)
            INTO :VAL;

            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:CLASS_ID)
            INTO :VAL2;

            SUSPEND;

            VAL2 = NULL;
        END

        IF (STAGE_ID IN (45, 47, 48)) THEN
        BEGIN
            DOCUM_ID = NULL;

            SELECT FIRST 1
                   L.OBJ_ID

            FROM LINKS L

            JOIN VALL V
            ON V.OBJ_ID = L.OBJ_ID
            AND V.PARAM_ID = 441
            AND V.IS_DEL = 0

            WHERE L.PARENT_ID = :SCHOLAR_ID
            AND L.OBJ_TYPE_ID = 79
            AND L.DATE_DEL IS NULL

            ORDER BY V.LISTVAL_ID
            INTO :DOCUM_ID;

            IF (DOCUM_ID IS NULL) THEN
            BEGIN
                ERR = 1;
                OPR = 43;

                SELECT CAPTION
                FROM OBJECT_CAPTION_GET(:SCHOLAR_ID)
                INTO :VAL;

                SELECT CAPTION
                FROM OBJECT_CAPTION_GET(:CLASS_ID)
                INTO :VAL2;

                SUSPEND;

                VAL2 = NULL;
            END
            ELSE
            BEGIN
                SELECT COUNT(*)
                FROM VALS V
                WHERE V.PARAM_ID = 559
                AND V.OBJ_ID = :DOCUM_ID
                AND V.IS_DEL = 0
                INTO :C;

                IF (C = 0) THEN
                BEGIN
                    ERR = 1;
                    OPR = 45;

                    SELECT CAPTION
                    FROM OBJECT_CAPTION_GET(:SCHOLAR_ID)
                    INTO :VAL;

                    SELECT CAPTION
                    FROM OBJECT_CAPTION_GET(:CLASS_ID)
                    INTO :VAL2;

                    SUSPEND;

                    VAL2 = NULL;
                END
            END

            FOR
                SELECT COUNT(V804.VAL)

                FROM LINKS L120

                JOIN VALD V804
                ON V804.OBJ_ID = L120.OBJ_ID
                AND V804.PARAM_ID = 804
                AND V804.IS_DEL = 0

                WHERE L120.PARENT_ID = :SCHOLAR_ID
                AND L120.OBJ_TYPE_ID = 120
                AND L120.DATE_DEL IS NULL

                GROUP BY V804.VAL
                INTO :C
            DO
            BEGIN
                IF (C > 1) THEN
                BEGIN
                    ERR = 1;
                    OPR = 46;

                    SELECT CAPTION
                    FROM OBJECT_CAPTION_GET(:SCHOLAR_ID)
                    INTO :VAL;

                    SELECT CAPTION
                    FROM OBJECT_CAPTION_GET(:CLASS_ID)
                    INTO :VAL2;

                    SUSPEND;

                    VAL2 = NULL;
                END
            END

            FOR
                SELECT R.VAL

                FROM LINKS L120

                JOIN VALL V802
                ON V802.OBJ_ID = L120.OBJ_ID
                AND V802.PARAM_ID = 802
                AND V802.IS_DEL = 0
                AND V802.LISTVAL_ID IN (3165, 3166)

                JOIN VALL V803
                ON V803.OBJ_ID = L120.OBJ_ID
                AND V803.PARAM_ID = 803
                AND V803.IS_DEL = 0

                JOIN LISTVALS LV
                ON LV.LISTVAL_ID = V803.LISTVAL_ID

                LEFT JOIN RES_GET(LV.RES_ID,  :LANG_CODE) R ON 1=1

                WHERE L120.PARENT_ID = :SCHOLAR_ID
                AND L120.OBJ_TYPE_ID = 120
                AND L120.DATE_DEL IS NULL

                INTO :VAL2
            DO
            BEGIN
                ERR = 0;
                OPR = 47;

                SELECT CAPTION
                FROM OBJECT_CAPTION_GET(:SCHOLAR_ID)
                INTO :VAL;

                SELECT CAPTION || ' - ' || :VAL2
                FROM OBJECT_CAPTION_GET(:CLASS_ID)
                INTO :VAL2;

                SUSPEND;

            END
            VAL2 = NULL;
        END
    END

    FOR
        SELECT L17.OBJ_ID

        FROM LINKS L17

        LEFT JOIN VALD V482
        ON V482.PARAM_ID = 482
        AND V482.OBJ_ID = L17.OBJ_ID
        AND V482.IS_DEL = 0

        LEFT JOIN VALD V483
        ON V483.PARAM_ID = 483
        AND V483.OBJ_ID = L17.OBJ_ID
        AND V483.IS_DEL = 0

        WHERE L17.PARENT_ID = :SCHOOL_ID
        AND L17.OBJ_TYPE_ID = 17
        AND L17.DATE_DEL IS NULL
        AND ((V482.VAL < '1900-01-01') OR (V483.VAL < '1900-01-01'))

        INTO :DOCUM_ID
    DO
    BEGIN
        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:DOCUM_ID)
        INTO :VAL;

        ERR = 1;
        OPR = 51;
        SUSPEND;
    END

    FOR
        SELECT S1.CLASS_ID,
               S1.SCHOLAR_ID,
               S2.CLASS_ID,
               S2.SCHOLAR_ID

        FROM GIA_OU_EXPORT_CHECK_FIO S1

        JOIN GIA_OU_EXPORT_CHECK_FIO S2
        ON S1.F = S2.F
        AND S1.I = S2.I
        AND S1.SCHOLAR_ID > S2.SCHOLAR_ID

        INTO :CLASS_ID1,
             :SCHOLAR_ID1,
             :CLASS_ID2,
             :SCHOLAR_ID2
    DO
    BEGIN
        C = 0;

        SELECT COUNT(*)
        FROM LINKS L1
        JOIN VALL V1 ON V1.OBJ_ID = L1.OBJ_ID AND V1.PARAM_ID = 441 AND V1.IS_DEL = 0
        JOIN VALS N1 ON N1.OBJ_ID = L1.OBJ_ID AND N1.PARAM_ID = 559 AND N1.IS_DEL = 0
        JOIN LINKS L2 ON 1 = 1 AND L2.PARENT_ID = :SCHOLAR_ID2 AND L2.OBJ_TYPE_ID = 79 AND L2.DATE_DEL IS NULL
        JOIN VALL V2 ON V2.OBJ_ID = L2.OBJ_ID AND V2.PARAM_ID = 441 AND V2.IS_DEL = 0
        JOIN VALS N2 ON N2.OBJ_ID = L2.OBJ_ID AND N2.PARAM_ID = 559 AND N2.IS_DEL = 0
        LEFT JOIN VALS S1 ON S1.OBJ_ID = L1.OBJ_ID AND S1.PARAM_ID = 442 AND S1.IS_DEL = 0
        LEFT JOIN VALS S2 ON S2.OBJ_ID = L2.OBJ_ID AND S2.PARAM_ID = 442 AND S2.IS_DEL = 0
        WHERE L1.PARENT_ID = :SCHOLAR_ID1 AND L1.OBJ_TYPE_ID = 79 AND L1.DATE_DEL IS NULL AND V2.LISTVAL_ID = V1.LISTVAL_ID AND N2.VAL = N1.VAL
            AND ((S2.VAL = S1.VAL) OR ((S2.VAL IS NULL) AND (S1.VAL IS NULL)))
        INTO :C;

        IF (C > 0) THEN
        BEGIN
            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:SCHOLAR_ID1)
            INTO :VAL;

            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:CLASS_ID1)
            INTO :VAL2;

            SELECT :VAL2 || ', ' || CAPTION
            FROM OBJECT_CAPTION_GET(:CLASS_ID2)
            INTO :VAL2;

            ERR = 1;
            OPR = 48;
            SUSPEND;
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GIA_OU_EXPORT_CHECK_FIO RETURNS (
    CLASS_ID BIGINT,
    SCHOLAR_ID BIGINT,
    F VARCHAR(1000),
    I VARCHAR(1000))
AS
DECLARE VARIABLE PUNKT_ID BIGINT;
DECLARE VARIABLE SCHOOL_ID BIGINT;
BEGIN
    SELECT FIRST 1 L.OBJ_ID
    FROM LINKS L
    WHERE L.PARENT_ID IS NULL AND L.OBJ_TYPE_ID = 2 AND L.DATE_DEL IS NULL
    INTO :SCHOOL_ID;

    SELECT FIRST 1 L.OBJ_ID
    FROM LINKS L
    WHERE L.PARENT_ID IS NULL AND L.OBJ_TYPE_ID = 124 AND L.DATE_DEL IS NULL
    INTO :PUNKT_ID;

    -- А нахрена мы делаем такую кучу запросов ?
    -- надо собрать в одну выборку все

    FOR SELECT L9.OBJ_ID, L10.OBJ_ID, V55.VAL, V56.VAL
        FROM LINKS L7
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID
        JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID
        JOIN VALL V ON V.OBJ_ID = L8.OBJ_ID
        JOIN VALS V55 ON  V55.OBJ_ID = L10.OBJ_ID
        JOIN VALS V56 ON  V56.OBJ_ID = L10.OBJ_ID
        WHERE L7.PARENT_ID = :SCHOOL_ID
          AND L7.OBJ_TYPE_ID = 7
          AND L7.DATE_DEL IS NULL
          AND L8.OBJ_TYPE_ID = 8
          AND L8.DATE_DEL IS NULL
          AND L9.OBJ_TYPE_ID = 9
          AND L9.DATE_DEL IS NULL
          AND L10.OBJ_TYPE_ID = 10
          AND L10.DATE_DEL IS NULL
          AND V.PARAM_ID = 49
          AND V.IS_DEL = 0
          AND V.LISTVAL_ID IN (45, 47, 48)
          AND V55.PARAM_ID = 55
          AND V55.IS_DEL = 0
          AND V56.PARAM_ID = 56
          AND V56.IS_DEL = 0

        UNION

        SELECT L9.OBJ_ID, L126.OBJ_ID, V827.VAL, V828.VAL
        FROM LINKS L7
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID
        JOIN LINKS L126 ON L126.PARENT_ID = L9.OBJ_ID
        JOIN VALS V827 ON V827.OBJ_ID = L126.OBJ_ID
        JOIN VALS V828 ON V828.OBJ_ID = L126.OBJ_ID
        WHERE L7.PARENT_ID = :SCHOOL_ID
          AND L7.OBJ_TYPE_ID = 7
          AND L7.DATE_DEL IS NULL
          AND L8.OBJ_TYPE_ID = 8
          AND L8.DATE_DEL IS NULL
          AND L9.OBJ_TYPE_ID = 9
          AND L9.DATE_DEL IS NULL
          AND L126.OBJ_TYPE_ID = 126
          AND L126.DATE_DEL IS NULL
          AND V827.PARAM_ID = 827
          AND V827.IS_DEL = 0
          AND V828.PARAM_ID = 828
          AND V828.IS_DEL = 0

        UNION

        SELECT L125.OBJ_ID, L126.OBJ_ID, V827.VAL, V828.VAL
        FROM LINKS L7
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID
        JOIN LINKS L125 ON L125.PARENT_ID = L8.OBJ_ID
        JOIN LINKS L126 ON L126.PARENT_ID = L125.OBJ_ID
        JOIN VALS V827 ON V827.OBJ_ID = L126.OBJ_ID
        JOIN VALS V828 ON V828.OBJ_ID = L126.OBJ_ID
        WHERE L7.PARENT_ID = :SCHOOL_ID
          AND L7.OBJ_TYPE_ID IN (7, 502)
          AND L7.DATE_DEL IS NULL
          AND L8.OBJ_TYPE_ID = 8
          AND L8.DATE_DEL IS NULL
          AND L125.OBJ_TYPE_ID = 125
          AND L125.DATE_DEL IS NULL
          AND L126.OBJ_TYPE_ID = 126
          AND L126.DATE_DEL IS NULL
          AND V827.PARAM_ID = 827
          AND V827.IS_DEL = 0
          AND V828.PARAM_ID = 828
          AND V828.IS_DEL = 0

        UNION

        SELECT L125.OBJ_ID, L126.OBJ_ID, V827.VAL, V828.VAL
        FROM LINKS L125
        JOIN LINKS L126 ON L126.PARENT_ID = L125.OBJ_ID
        JOIN VALS V827 ON V827.OBJ_ID = L126.OBJ_ID
        JOIN VALS V828 ON V828.OBJ_ID = L126.OBJ_ID
        WHERE L125.PARENT_ID = :PUNKT_ID
          AND L125.OBJ_TYPE_ID = 125
          AND L125.DATE_DEL IS NULL
          AND L126.OBJ_TYPE_ID = 126
          AND L126.DATE_DEL IS NULL
          AND V827.PARAM_ID = 827
          AND V827.IS_DEL = 0
          AND V828.PARAM_ID = 828
          AND V828.IS_DEL = 0

        INTO :CLASS_ID, :SCHOLAR_ID, :F, :I
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GIA_OU_EXPORT_CLASSROOM (
    SCHOOL_ID BIGINT)
RETURNS (
    CODE_CLASSROOM_SCHOOL BIGINT,
    NAME VARCHAR(4000),
    CAPACITY INTEGER,
    "FLOOR" INTEGER)
AS
BEGIN
    FOR SELECT OBJ_ID, PPE_CODE, COLUMN_SUM, "FLOOR"
        FROM GIA_ROOM_LIST2(:SCHOOL_ID)
        INTO :CODE_CLASSROOM_SCHOOL, :NAME, :CAPACITY, :FLOOR
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GIA_OU_EXPORT_PERSON (
    I$USER_ID BIGINT)
RETURNS (
    SCHOOL_ID BIGINT,
    PPE_POS_CODE BIGINT,
    CODE_PERSON_SCHOOL BIGINT,
    FIO_SURNAME VARCHAR(500),
    FIO_NAME VARCHAR(500),
    FIO_PATRONYMIC VARCHAR(500),
    SEX INTEGER,
    BIRTHDAY DATE,
    STAFF INTEGER,
    DOCUMENT_TYPE INTEGER,
    DOCUMENT_SERIES VARCHAR(500),
    DOCUMENT_NUMBER VARCHAR(500),
    POSITION_PPE INTEGER,
    POSITION_PPE_KL9 INTEGER,
    POSITION_PPE_KL11 INTEGER,
    POSITION_SCHOOL VARCHAR(500),
    POSITION_LABOR_FUNC VARCHAR(500),
    EDUCATION_LEVEL INTEGER,
    ACADEMIC_RANK INTEGER,
    EXPERIENCE_TEACHING INTEGER,
    QUALIFICATION_CATEGORY INTEGER,
    FORM_MASTER VARCHAR(500),
    CLASSCOUNT INTEGER,
    EXPORT_FLAG INTEGER,
    PHONE_MOBILE VARCHAR(500),
    CONTACT_EMAIL VARCHAR(500),
    SNILS VARCHAR(40))
AS
DECLARE VARIABLE LANG_CODE VARCHAR(2);
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :LANG_CODE;

    FOR
        SELECT SCHOOL_ID
        FROM GIA_OU_LIST(0, 1)
        INTO :SCHOOL_ID
    DO
    BEGIN
        FOR
            SELECT L14.OBJ_ID
            FROM LINKS L14
            WHERE L14.PARENT_ID = :SCHOOL_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
            INTO :CODE_PERSON_SCHOOL
        DO
        BEGIN
            PPE_POS_CODE = NULL;

            SELECT I
            FROM VAL_GET(:CODE_PERSON_SCHOOL, 1376)
            INTO :PPE_POS_CODE;

            SELECT COUNT(L9.OBJ_ID)
            FROM LINKS L7
            JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
            JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
            JOIN VALR K ON K.OBJ_ID = L9.OBJ_ID AND K.PARAM_ID = 53 AND K.VAL = :CODE_PERSON_SCHOOL AND K.IS_DEL = 0
            LEFT JOIN VALL G ON G.OBJ_ID = L9.OBJ_ID AND G.PARAM_ID = 2388 AND G.IS_DEL = 0
            LEFT JOIN VALL P ON P.OBJ_ID = L8.OBJ_ID AND P.PARAM_ID = 49 AND P.IS_DEL = 0
            LEFT JOIN LISTVALS LV ON LV.LISTVAL_ID = P.LISTVAL_ID AND LV.LIST_ID = 25 AND LV.IS_DEL = 0
            WHERE L7.PARENT_ID = :SCHOOL_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL AND ((G.LISTVAL_ID IN (11202, 11203)) OR (CAST(LV.COST AS INTEGER) = 9))
            INTO :CLASSCOUNT;

            IF (((PPE_POS_CODE != 0) AND (PPE_POS_CODE != 2989)) OR (CLASSCOUNT > 0)) THEN
            BEGIN
                SELECT V
                FROM VAL_GET(:CODE_PERSON_SCHOOL, 59)
                INTO :FIO_SURNAME;

                SELECT V
                FROM VAL_GET(:CODE_PERSON_SCHOOL, 60)
                INTO :FIO_NAME;

                SELECT V
                FROM VAL_GET(:CODE_PERSON_SCHOOL, 61)
                INTO :FIO_PATRONYMIC;

                SELECT I
                FROM VAL_GET(:CODE_PERSON_SCHOOL, 239)
                INTO :SEX;
                IF (SEX = 0) THEN
                BEGIN
                    SEX = NULL;
                END
                ELSE
                IF (SEX = 183) THEN
                BEGIN
                    SEX = 1;
                END
                ELSE
                BEGIN
                    SEX = 2;
                END

                SELECT V
                FROM VAL_GET(:CODE_PERSON_SCHOOL, 2455)
                INTO :SNILS;

                STAFF = 0;
                SELECT COUNT(L15.OBJ_ID)
                FROM LINKS L15
                JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0 AND V73.VAL < CURRENT_DATE
                JOIN VALL S ON S.OBJ_ID = L15.OBJ_ID AND S.PARAM_ID = 587 AND S.IS_DEL = 0 AND S.LISTVAL_ID = 207
                LEFT JOIN VALD V74 ON V74.PARAM_ID = 74 AND V74.OBJ_ID = L15.OBJ_ID AND V74.IS_DEL = 0
                WHERE L15.PARENT_ID = :CODE_PERSON_SCHOOL AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL AND ((V74.VAL IS NULL) OR (V74.VAL >= CURRENT_DATE))
                INTO :STAFF;

                IF (STAFF > 0) THEN STAFF = 1;

                SELECT D FROM VAL_GET(:CODE_PERSON_SCHOOL, 241) INTO :BIRTHDAY;

                -- Телефон в формате (XXX) XXX-XX-XX
                SELECT V FROM VAL_GET(:CODE_PERSON_SCHOOL, 254) INTO :PHONE_MOBILE;
                IF(PHONE_MOBILE IS NOT NULL AND PHONE_MOBILE <> '') THEN
                BEGIN
                    IF(CHAR_LENGTH(PHONE_MOBILE) = 7 AND POSITION('-' IN PHONE_MOBILE) <= 0) THEN
                    BEGIN
                        -- XXXXXXX
                        PHONE_MOBILE = '(812)' || SUBSTRING(PHONE_MOBILE FROM 1 FOR 3) || '-' ||
                            SUBSTRING(PHONE_MOBILE FROM 4 FOR 2) || '-' || SUBSTRING(PHONE_MOBILE FROM 6 FOR 2);
                    END
                    ELSE IF(CHAR_LENGTH(PHONE_MOBILE) = 9 AND POSITION('-' IN PHONE_MOBILE) = 4) THEN
                    BEGIN
                        -- XXX-XX-XX
                        PHONE_MOBILE = '(812)' || PHONE_MOBILE;
                    END
                    ELSE IF(CHAR_LENGTH(PHONE_MOBILE) = 10 AND POSITION('-' IN PHONE_MOBILE) <= 0) THEN
                    BEGIN
                        -- xxxYYYYYYY
                        PHONE_MOBILE = '(' || SUBSTRING(PHONE_MOBILE FROM 1 FOR 3) || ')' || SUBSTRING(PHONE_MOBILE FROM 4 FOR 3) || '-' ||
                            SUBSTRING(PHONE_MOBILE FROM 7 FOR 2) || '-' || SUBSTRING(PHONE_MOBILE FROM 9 FOR 2);
                    END
                    ELSE IF(CHAR_LENGTH(PHONE_MOBILE) = 11 AND POSITION('-' IN PHONE_MOBILE) <= 0) THEN
                    BEGIN
                        -- 8xxxYYYYYYY
                        PHONE_MOBILE = '(' || SUBSTRING(PHONE_MOBILE FROM 2 FOR 3) || ')' || SUBSTRING(PHONE_MOBILE FROM 5 FOR 3) || '-' ||
                            SUBSTRING(PHONE_MOBILE FROM 8 FOR 2) || '-' || SUBSTRING(PHONE_MOBILE FROM 10 FOR 2);
                    END
                    ELSE IF(CHAR_LENGTH(PHONE_MOBILE) = 15 AND POSITION('-' IN PHONE_MOBILE) = 2) THEN
                    BEGIN
                        -- X-XXX-XXX-XX-XX
                        PHONE_MOBILE = '(' || SUBSTRING(PHONE_MOBILE FROM 3 FOR 3) || ')' || SUBSTRING(PHONE_MOBILE FROM 7 FOR 3) || '-' ||
                            SUBSTRING(PHONE_MOBILE FROM 11 FOR 2) || '-' || SUBSTRING(PHONE_MOBILE FROM 14 FOR 2);
                    END
                END

                SELECT V FROM VAL_GET(:CODE_PERSON_SCHOOL, 1180) INTO :CONTACT_EMAIL;

                DOCUMENT_TYPE = NULL;
                DOCUMENT_SERIES = NULL;
                DOCUMENT_NUMBER = NULL;

                -- исключены недействующие документы
                SELECT FIRST 1 CAST(LV.COST AS INTEGER), V442.VAL, V559.VAL
                FROM LINKS L79
                JOIN VALL V441 ON V441.PARAM_ID = 441 AND V441.OBJ_ID = L79.OBJ_ID AND V441.IS_DEL = 0
                JOIN LISTVALS LV ON LV.LISTVAL_ID = V441.LISTVAL_ID AND LV.LIST_ID = 143 AND LV.IS_DEL = 0
                LEFT JOIN VALS V442 ON V442.PARAM_ID = 442 AND V442.OBJ_ID = L79.OBJ_ID AND V442.IS_DEL = 0
                LEFT JOIN VALS V559 ON V559.PARAM_ID = 559 AND V559.OBJ_ID = L79.OBJ_ID AND V559.IS_DEL = 0
                LEFT JOIN VALL V614 ON V614.PARAM_ID = 614 AND V614.OBJ_ID = L79.OBJ_ID AND V614.IS_DEL = 0
                WHERE L79.PARENT_ID = :CODE_PERSON_SCHOOL AND L79.OBJ_TYPE_ID = 79 AND L79.DATE_DEL IS NULL AND (V614.LISTVAL_ID IS NULL OR V614.LISTVAL_ID <> 1983)
                ORDER BY CAST(LV.COST AS INTEGER)
                INTO :DOCUMENT_TYPE, :DOCUMENT_SERIES, :DOCUMENT_NUMBER;

                POSITION_PPE = NULL;
                SELECT CAST(LV.COST AS INTEGER)
                FROM VALL L
                JOIN LISTVALS LV ON LV.LISTVAL_ID = L.LISTVAL_ID AND LV.LIST_ID = 216 AND LV.IS_DEL = 0
                WHERE L.OBJ_ID = :CODE_PERSON_SCHOOL AND L.PARAM_ID = 1376 AND L.IS_DEL = 0
                INTO :POSITION_PPE;

                SELECT I
                FROM VAL_GET(:CODE_PERSON_SCHOOL, 1395)
                INTO :POSITION_PPE_KL9;
                IF (POSITION_PPE_KL9 = 2) THEN
                BEGIN
                    POSITION_PPE_KL9 = 1;
                END
                ELSE
                BEGIN
                    POSITION_PPE_KL9 = 0;
                END

                SELECT I
                FROM VAL_GET(:CODE_PERSON_SCHOOL, 1396)
                INTO :POSITION_PPE_KL11;

                IF (POSITION_PPE_KL11 = 2) THEN
                BEGIN
                    POSITION_PPE_KL11 = 1;
                END
                ELSE
                BEGIN
                    POSITION_PPE_KL11 = 0;
                END

                -- Название должности
                SELECT FIRST 1 PN.VAL, R.VAL
                FROM LINKS L15
                JOIN VALL L ON L.OBJ_ID = L15.OBJ_ID AND L.PARAM_ID = 72 AND L.LISTVAL_ID = 934 AND L.IS_DEL = 0
                JOIN VALR P ON P.OBJ_ID = L15.OBJ_ID AND P.PARAM_ID = 69 AND P.IS_DEL = 0
                JOIN VALS PN ON PN.OBJ_ID = P.VAL AND PN.PARAM_ID = 589 AND PN.IS_DEL = 0
                JOIN VALL LF ON LF.OBJ_ID = P.VAL AND LF.PARAM_ID = 58 AND LF.IS_DEL = 0
                JOIN LISTVALS LV ON LV.LISTVAL_ID = LF.LISTVAL_ID
                LEFT JOIN RES_GET(LV.RES_ID,  :LANG_CODE) R ON 1 = 1
                -- фильтр только по действующим должностям
                LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
                WHERE L15.PARENT_ID = :CODE_PERSON_SCHOOL AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
                    AND (V74.VAL IS NULL OR V74.VAL > CURRENT_DATE)
                INTO :POSITION_SCHOOL, :POSITION_LABOR_FUNC;

                SELECT LV.COST
                FROM VAL_GET(:CODE_PERSON_SCHOOL, 278) V
                JOIN LISTVALS LV ON LV.LISTVAL_ID = V.I
                INTO :EDUCATION_LEVEL;

                ACADEMIC_RANK = NULL;

                SELECT FIRST 1 CAST(LV.COST AS INTEGER)
                FROM VALL L
                JOIN LISTVALS LV ON LV.LISTVAL_ID = L.LISTVAL_ID AND LV.LIST_ID = 215 AND LV.IS_DEL = 0
                WHERE L.OBJ_ID = :CODE_PERSON_SCHOOL AND L.PARAM_ID = 1373 AND L.IS_DEL = 0
                INTO :ACADEMIC_RANK;

                EXPERIENCE_TEACHING = NULL;

                SELECT SUM(DAYS360_COUNT) / 360
                FROM PARAGRAF_EMPLOYEE_SENIORITY_LST(:CODE_PERSON_SCHOOL)
                WHERE SENIORITY_TYPE = 942
                INTO :EXPERIENCE_TEACHING;

                -- Квалификационную категорию выбираем по основной должности
                QUALIFICATION_CATEGORY = NULL;
                SELECT FIRST 1 CAST(LV.COST AS INTEGER)
                FROM LINKS L14_15
                JOIN LINKS L13_15 ON L13_15.OBJ_ID = L14_15.OBJ_ID AND L13_15.PARENT_TYPE_ID = 13 AND L13_15.DATE_DEL IS NULL
                -- только основная должность
                JOIN VALL V72 ON V72.OBJ_ID = L14_15.OBJ_ID AND V72.PARAM_ID = 72 AND V72.IS_DEL = 0 AND V72.LISTVAL_ID = 934
                -- числится на должности
                LEFT JOIN VALD V74 ON V74.OBJ_ID = L14_15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
                -- категория по должности
                JOIN VALL V1790 ON V1790.OBJ_ID = L14_15.OBJ_ID AND V1790.PARAM_ID = 1790 AND V1790.IS_DEL = 0
                -- перекодирование категории из LISTVALS
                JOIN LISTVALS LV ON LV.LISTVAL_ID = V1790.LISTVAL_ID AND LV.LIST_ID = 90 AND LV.IS_DEL = 0
                WHERE L14_15.PARENT_ID = :CODE_PERSON_SCHOOL AND L14_15.OBJ_TYPE_ID = 15 AND L14_15.DATE_DEL IS NULL
                    AND (V74.VAL IS NULL OR V74.VAL > CURRENT_DATE)
                INTO :QUALIFICATION_CATEGORY;

                FORM_MASTER = NULL;

                IF (CLASSCOUNT > 0) THEN
                BEGIN
                    SELECT FIRST 1 S.VAL
                    FROM LINKS L7
                    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
                    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
                    JOIN VALS S ON S.OBJ_ID = L9.OBJ_ID AND S.PARAM_ID = 1363 AND S.IS_DEL = 0
                    JOIN VALR K ON K.OBJ_ID = L9.OBJ_ID AND K.PARAM_ID = 53 AND K.VAL = :CODE_PERSON_SCHOOL AND K.IS_DEL = 0
                    LEFT JOIN VALL G ON G.OBJ_ID = L9.OBJ_ID AND G.PARAM_ID = 2388 AND G.IS_DEL = 0
                    LEFT JOIN VALL P ON P.OBJ_ID = L8.OBJ_ID AND P.PARAM_ID = 49 AND P.IS_DEL = 0
                    LEFT JOIN LISTVALS LV ON LV.LISTVAL_ID = P.LISTVAL_ID AND LV.LIST_ID = 25 AND LV.IS_DEL = 0
                    WHERE L7.PARENT_ID = :SCHOOL_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL AND ((G.LISTVAL_ID IN (11202, 11203)) OR (CAST(LV.COST AS INTEGER) = 9))

                    INTO :FORM_MASTER;
                END

                SELECT I
                FROM VAL_GET(:CODE_PERSON_SCHOOL, 1391)
                INTO :EXPORT_FLAG;

                IF ((EXPORT_FLAG != 0) AND (EXPORT_FLAG != 3)) THEN
                BEGIN
                    EXPORT_FLAG = 1;
                END
                ELSE
                BEGIN
                    EXPORT_FLAG = 0;
                END

                SUSPEND;
            END
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GIA_OU_EXPORT_STUDENT (
    I$SCHOOL_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    CODE_STUDENT_SCHOOL BIGINT,
    FORM VARCHAR(500),
    FIO_SURNAME VARCHAR(500),
    FIO_NAME VARCHAR(500),
    FIO_PATRONYMIC VARCHAR(500),
    SEX INTEGER,
    BIRTHDAY DATE,
    DOCUMENT_TYPE INTEGER,
    DOCUMENT_SERIES VARCHAR(500),
    DOCUMENT_NUMBER VARCHAR(500),
    SPECIAL_CONDITIONS INTEGER,
    MEDAL INTEGER,
    CATEGORY_PARTICIPATION INTEGER,
    RUS INTEGER,
    MAT INTEGER,
    IGNORE_FORMNAME VARCHAR(500),
    INFO_LANG INTEGER,
    INFO_IDE INTEGER,
    INFO_WORD INTEGER,
    INFO_EXCEL INTEGER,
    ACCEPT_DATE DATE,
    VERBAL_FOREIGN_LANG INTEGER,
    ADMISSION_TO_EXAM INTEGER,
    SNILS VARCHAR(500),
    "GIA-LEVEL" SMALLINT,
    NATIONALITY VARCHAR(500),
    GRADUATE_OU VARCHAR(500),
    "PHONE-MOBILE" VARCHAR(100),
    "EDUCATION-FORM" VARCHAR(40))
AS
declare variable CLASS_ID bigint;
declare variable OBJ_TYPE bigint;
BEGIN
    FOR
        SELECT OBJ_ID, OBJ_CAPTION, SYNONIM
        FROM GIA_APPOINT_CLASS_LIST(:I$SCHOOL_ID, :I$USER_ID)
        WHERE PARALLEL IN (9, 10) OR GRADUATE <> 0
        INTO :CLASS_ID, :IGNORE_FORMNAME, :FORM
    DO
    BEGIN
        SELECT TYPE_ID
        FROM OBJECTS
        WHERE OBJ_ID = :CLASS_ID
        INTO :OBJ_TYPE;

        SELECT CASE WHEN I = 11202 THEN 2 WHEN I = 11203 THEN 3 ELSE 0 END
        FROM VAL_GET(:CLASS_ID, CASE WHEN :OBJ_TYPE = 9 THEN 2388 WHEN :OBJ_TYPE = 187 THEN 2418 WHEN :OBJ_TYPE = 125 THEN 2419 END, 0, :I$USER_ID)
        INTO :"GIA-LEVEL";

        FOR
            SELECT OBJ_ID
            FROM GIA_CLASS_SCHOLAR_LIST(:CLASS_ID)
            INTO :CODE_STUDENT_SCHOOL
        DO
        BEGIN
            SELECT TYPE_ID
            FROM OBJECTS
            WHERE OBJ_ID = :CODE_STUDENT_SCHOOL
            INTO :OBJ_TYPE;

            FIO_SURNAME = NULL;
            FIO_NAME = NULL;
            FIO_PATRONYMIC = NULL;
            BIRTHDAY = NULL;
            SPECIAL_CONDITIONS = NULL;
            MEDAL = NULL;
            CATEGORY_PARTICIPATION = NULL;
            INFO_LANG = NULL;
            INFO_IDE = NULL;
            INFO_WORD = NULL;
            INFO_EXCEL = NULL;
            VERBAL_FOREIGN_LANG = NULL;
            ADMISSION_TO_EXAM = NULL;
            SNILS = NULL;
            NATIONALITY = NULL;
            GRADUATE_OU = NULL;

            IF (OBJ_TYPE = 10) THEN
            BEGIN
                SELECT V FROM VAL_GET(:CODE_STUDENT_SCHOOL, 55, 0, :I$USER_ID) INTO :FIO_SURNAME;
                SELECT V FROM VAL_GET(:CODE_STUDENT_SCHOOL, 56, 0, :I$USER_ID) INTO :FIO_NAME;
                SELECT V FROM VAL_GET(:CODE_STUDENT_SCHOOL, 57, 0, :I$USER_ID) INTO :FIO_PATRONYMIC;
                SELECT I FROM VAL_GET(:CODE_STUDENT_SCHOOL, 88, 0, :I$USER_ID) INTO :SEX;
                SELECT D FROM VAL_GET(:CODE_STUDENT_SCHOOL, 89, 0, :I$USER_ID) INTO :BIRTHDAY;

                SELECT CAST(LV.COST AS INTEGER) - 1
                FROM VALL L
                JOIN LISTVALS LV ON L.LISTVAL_ID = LV.LISTVAL_ID AND LV.LIST_ID = 205 AND LV.IS_DEL = 0
                WHERE L.OBJ_ID = :CODE_STUDENT_SCHOOL AND L.PARAM_ID = 1374 AND L.IS_DEL = 0
                INTO :SPECIAL_CONDITIONS;

                SELECT CAST(LV.COST AS INTEGER)
                FROM VALL L
                JOIN LISTVALS LV ON L.LISTVAL_ID = LV.LISTVAL_ID AND LV.LIST_ID = 204 AND LV.IS_DEL = 0
                WHERE L.OBJ_ID = :CODE_STUDENT_SCHOOL AND L.PARAM_ID = 1375 AND L.IS_DEL = 0
                INTO :MEDAL;

                SELECT CAST(LV.COST AS INTEGER)
                FROM VAL_GET(:CODE_STUDENT_SCHOOL, 1340)  L
                JOIN LISTVALS LV ON L.I = LV.LISTVAL_ID AND LV.LIST_ID = 217 AND LV.IS_DEL = 0
                INTO :CATEGORY_PARTICIPATION;

                SELECT I FROM VAL_GET(:CODE_STUDENT_SCHOOL, 1377, 0, :I$USER_ID) INTO :MAT;
                SELECT I FROM VAL_GET(:CODE_STUDENT_SCHOOL, 1378, 0, :I$USER_ID) INTO :RUS;
                SELECT IIF(I = 2, 1, 0) FROM VAL_GET(:CODE_STUDENT_SCHOOL, 2154, 0, :I$USER_ID) INTO :VERBAL_FOREIGN_LANG;

                IF(EXISTS(
                    SELECT FIRST 1 1
                    FROM LINKS LP8
                    JOIN VALL VL ON VL.OBJ_ID = LP8.PARENT_ID AND VL.PARAM_ID = 49 AND VL.IS_DEL = 0 AND VL.LISTVAL_ID IN (45,47,48)
                    WHERE LP8.OBJ_ID = :CLASS_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
                )) THEN
                BEGIN
                    SELECT IIF(I = 2, 1, 0) FROM VAL_GET(:CODE_STUDENT_SCHOOL, 2155, 0, :I$USER_ID) INTO :ADMISSION_TO_EXAM;
                END

                SELECT V FROM VAL_GET(:CODE_STUDENT_SCHOOL, 1409, 0, :I$USER_ID) INTO :SNILS;

                SELECT LV.COST
                FROM VALL V1620
                JOIN LISTVALS LV ON LV.LISTVAL_ID = V1620.LISTVAL_ID
                WHERE V1620.OBJ_ID = :CODE_STUDENT_SCHOOL AND V1620.PARAM_ID = 1620 AND V1620.IS_DEL = 0
                INTO :INFO_LANG;

                SELECT LV.COST
                FROM VALL V1622
                JOIN LISTVALS LV ON LV.LISTVAL_ID = V1622.LISTVAL_ID
                WHERE V1622.OBJ_ID = :CODE_STUDENT_SCHOOL AND V1622.PARAM_ID = 1622 AND V1622.IS_DEL = 0
                INTO :INFO_IDE;

                SELECT LV.COST
                FROM VALL V1624
                JOIN LISTVALS LV ON LV.LISTVAL_ID = V1624.LISTVAL_ID
                WHERE V1624.OBJ_ID = :CODE_STUDENT_SCHOOL AND V1624.PARAM_ID = 1624 AND V1624.IS_DEL = 0
                INTO :INFO_WORD;

                SELECT LV.COST
                FROM VALL V1625
                JOIN LISTVALS LV ON LV.LISTVAL_ID = V1625.LISTVAL_ID
                WHERE V1625.OBJ_ID = :CODE_STUDENT_SCHOOL AND V1625.PARAM_ID = 1625 AND V1625.IS_DEL = 0
                INTO :INFO_EXCEL;

                ACCEPT_DATE = NULL;
                SELECT FIRST 1 M.DATE_IN
                FROM PERSON_MOVEMENTS M
                JOIN OBJECTS O ON O.OBJ_ID = M.GROUP_ID AND O.TYPE_ID IN (9, 125, 187)
                WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :CODE_STUDENT_SCHOOL AND M.REASON_IN IN (3276, 805, 806, 3140)
                ORDER BY M.DATE_IN DESC
                INTO :ACCEPT_DATE;

                SELECT V FROM VAL_GET(:CODE_STUDENT_SCHOOL, 91, 0, :I$USER_ID) INTO :NATIONALITY;
                SELECT V FROM VAL_GET(:CODE_STUDENT_SCHOOL, 102, 0, :I$USER_ID) INTO :"PHONE-MOBILE";
                SELECT V FROM VAL_GET(:CODE_STUDENT_SCHOOL, 80, 0, :I$USER_ID) INTO :"EDUCATION-FORM";
            END
            ELSE
            BEGIN
                SELECT V FROM VAL_GET(:CODE_STUDENT_SCHOOL, 827, 0, :I$USER_ID) INTO :FIO_SURNAME;
                SELECT V FROM VAL_GET(:CODE_STUDENT_SCHOOL, 828, 0, :I$USER_ID) INTO :FIO_NAME;
                SELECT V FROM VAL_GET(:CODE_STUDENT_SCHOOL, 829, 0, :I$USER_ID) INTO :FIO_PATRONYMIC;
                SELECT I FROM VAL_GET(:CODE_STUDENT_SCHOOL, 1022, 0, :I$USER_ID) INTO :SEX;
                SELECT D FROM VAL_GET(:CODE_STUDENT_SCHOOL, 830, 0, :I$USER_ID) INTO :BIRTHDAY;
                SELECT V FROM VAL_GET(:CODE_STUDENT_SCHOOL, 3277, 0, :I$USER_ID) INTO :SNILS;

                SELECT CAST(LV.COST AS INTEGER) - 1
                FROM VALL L
                JOIN LISTVALS LV ON L.LISTVAL_ID = LV.LISTVAL_ID AND LV.LIST_ID = 205 AND LV.IS_DEL = 0
                WHERE L.OBJ_ID = :CODE_STUDENT_SCHOOL AND L.PARAM_ID = 832 AND L.IS_DEL = 0
                INTO :SPECIAL_CONDITIONS;

                SELECT CAST(LV.COST AS INTEGER)
                FROM VALL L
                JOIN LISTVALS LV ON L.LISTVAL_ID = LV.LISTVAL_ID AND LV.LIST_ID = 204 AND LV.IS_DEL = 0
                WHERE L.OBJ_ID = :CODE_STUDENT_SCHOOL AND L.PARAM_ID = 833 AND L.IS_DEL = 0
                INTO :MEDAL;

                SELECT CAST(LV.COST AS INTEGER)
                FROM VAL_GET(:CODE_STUDENT_SCHOOL, 835)  L
                JOIN LISTVALS LV ON L.I = LV.LISTVAL_ID AND LV.LIST_ID = 217 AND LV.IS_DEL = 0
                INTO :CATEGORY_PARTICIPATION;

                SELECT I FROM VAL_GET(:CODE_STUDENT_SCHOOL, 834, 0, :I$USER_ID) INTO :MAT;
                SELECT I FROM VAL_GET(:CODE_STUDENT_SCHOOL, 837, 0, :I$USER_ID) INTO :RUS;

                SELECT LV.COST
                FROM VALL V1626
                JOIN LISTVALS LV ON LV.LISTVAL_ID = V1626.LISTVAL_ID
                WHERE V1626.OBJ_ID = :CODE_STUDENT_SCHOOL AND V1626.PARAM_ID = 1626 AND V1626.IS_DEL = 0
                INTO :INFO_LANG;

                SELECT LV.COST
                FROM VALL V1628
                JOIN LISTVALS LV ON LV.LISTVAL_ID = V1628.LISTVAL_ID
                WHERE V1628.OBJ_ID = :CODE_STUDENT_SCHOOL AND V1628.PARAM_ID = 1628 AND V1628.IS_DEL = 0
                INTO :INFO_IDE;

                SELECT LV.COST
                FROM VALL V1629
                JOIN LISTVALS LV ON LV.LISTVAL_ID = V1629.LISTVAL_ID
                WHERE V1629.OBJ_ID = :CODE_STUDENT_SCHOOL AND V1629.PARAM_ID = 1629 AND V1629.IS_DEL = 0
                INTO :INFO_WORD;

                SELECT LV.COST
                FROM VALL V1630
                JOIN LISTVALS LV ON LV.LISTVAL_ID = V1630.LISTVAL_ID
                WHERE V1630.OBJ_ID = :CODE_STUDENT_SCHOOL AND V1630.PARAM_ID = 1630 AND V1630.IS_DEL = 0
                INTO :INFO_EXCEL;

                SELECT IIF(I = 2, 1, 0) FROM VAL_GET(:CODE_STUDENT_SCHOOL, 2159, 0, :I$USER_ID) INTO :VERBAL_FOREIGN_LANG;

                IF(EXISTS(
                    SELECT FIRST 1 1
                    FROM LINKS LP8
                    JOIN VALL VL ON VL.OBJ_ID = LP8.PARENT_ID AND VL.PARAM_ID = 49 AND VL.IS_DEL = 0 AND VL.LISTVAL_ID IN (45, 47, 48)
                    WHERE LP8.OBJ_ID = :CLASS_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
                )) THEN
                BEGIN
                    SELECT IIF(I = 2, 1, 0) FROM VAL_GET(:CODE_STUDENT_SCHOOL, 2160, 0, :I$USER_ID) INTO :ADMISSION_TO_EXAM;
                END

                SELECT V FROM VAL_GET(:CODE_STUDENT_SCHOOL, 2931, 0, :I$USER_ID) INTO :NATIONALITY;
                SELECT V FROM VAL_GET(:CODE_STUDENT_SCHOOL, 2932, 0, :I$USER_ID) INTO :GRADUATE_OU;

                -- SELECT V FROM VAL_GET(:CODE_STUDENT_SCHOOL, 102, 0, :I$USER_ID) INTO :"PHONE-MOBILE";
                "PHONE-MOBILE" = '';
                "EDUCATION-FORM" = '';
            END
            IF (SEX = 0) THEN SEX = NULL;
            ELSE IF (SEX = 183) THEN SEX = 1;
            ELSE SEX = 2;

            DOCUMENT_TYPE = NULL;
            DOCUMENT_SERIES = NULL;
            DOCUMENT_NUMBER = NULL;

            -- исключены недействующие документы
            SELECT FIRST 1 CAST(LV.COST AS INTEGER), V442.VAL, V559.VAL
            FROM LINKS L79
            JOIN VALL V441 ON V441.PARAM_ID = 441 AND V441.OBJ_ID = L79.OBJ_ID AND V441.IS_DEL = 0
            JOIN LISTVALS LV ON LV.LISTVAL_ID = V441.LISTVAL_ID AND LV.LIST_ID = 143 AND LV.IS_DEL = 0
            LEFT JOIN VALS V442 ON V442.PARAM_ID = 442 AND V442.OBJ_ID = L79.OBJ_ID AND V442.IS_DEL = 0
            LEFT JOIN VALS V559 ON V559.PARAM_ID = 559 AND V559.OBJ_ID = L79.OBJ_ID AND V559.IS_DEL = 0
            LEFT JOIN VALL V614 ON V614.PARAM_ID = 614 AND V614.OBJ_ID = L79.OBJ_ID AND V614.IS_DEL = 0
            WHERE L79.PARENT_ID = :CODE_STUDENT_SCHOOL AND L79.OBJ_TYPE_ID = 79 AND L79.DATE_DEL IS NULL AND (V614.LISTVAL_ID IS NULL OR V614.LISTVAL_ID <> 1983)
            ORDER BY CAST(LV.COST AS INTEGER)
            INTO :DOCUMENT_TYPE, :DOCUMENT_SERIES, :DOCUMENT_NUMBER;

            SUSPEND;
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GIA_OU_EXPORT_STUDENT_EXAM (
    I$STUDENT_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    EXAM_ID BIGINT)
AS
declare variable YEAR_ID bigint;
BEGIN
    SELECT YEAR_ID
    FROM GIA_APPOINT_CURRENT_YEAR(:I$USER_ID)
    INTO :YEAR_ID;

    FOR
        SELECT I.VAL

        FROM LINKS L120

        JOIN LINKS LP119
        ON LP119.OBJ_ID = L120.OBJ_ID
        AND LP119.PARENT_ID = :YEAR_ID
        AND LP119.PARENT_TYPE_ID = 119
        AND LP119.DATE_DEL IS NULL

        JOIN VALI I
        ON I.PARAM_ID = 800
        AND I.OBJ_ID = L120.OBJ_ID
        AND I.IS_DEL = 0

        WHERE L120.PARENT_ID = :I$STUDENT_ID
        AND L120.OBJ_TYPE_ID = 120
        AND L120.DATE_DEL IS NULL
        INTO :EXAM_ID
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GIA_OU_EXPORT_XML (
    LEVEL_ID SMALLINT = NULL,
    I$USER_ID BIGINT = NULL)
RETURNS (
    SCHOOL_ID BIGINT,
    CODE_SCHOOL_EGE BIGINT,
    CODE_SCHOOL_PPE VARCHAR(500),
    KL4 SMALLINT,
    KL9 SMALLINT,
    KL11 SMALLINT,
    FULLNAME VARCHAR(500),
    SHORTNAME VARCHAR(500),
    SCHOOL_NUMBER BIGINT,
    CODE_SCHOOL_TYPE SMALLINT,
    CODE_SCHOOL_KIND BIGINT,
    CODE_SCHOOL_OPF SMALLINT,
    ADDRESS VARCHAR(500),
    ADDRESS_PPE VARCHAR(500),
    LEADER_POSITION VARCHAR(500),
    LEADER_NAME VARCHAR(500),
    RESPONSIBLE_FOR_EGE VARCHAR(500),
    PHONES VARCHAR(500),
    FAX VARCHAR(500),
    EMAIL VARCHAR(500),
    WEB_SITE VARCHAR(500),
    NUMBER_GRADUATES INTEGER,
    NUMBER_PRE_GRADUATES INTEGER,
    LICENSE_NUMBER VARCHAR(50),
    LICENSE_COMMENCEMENT_DATE DATE,
    LICENSE_EXPIRATION_DATE DATE,
    ACCREDITATION_COMMENCEMENT_DATE DATE,
    ACCREDITATION_EXPIRATION_DATE DATE,
    OOOD_TYPE VARCHAR(500),
    OOOD_VID VARCHAR(500))
AS
DECLARE VARIABLE DIRECTOR BIGINT;
DECLARE VARIABLE OBJ_ID BIGINT;
DECLARE VARIABLE VAL VARCHAR(500);
DECLARE VARIABLE PPE BIGINT;
DECLARE VARIABLE LEN INTEGER;
DECLARE VARIABLE ISVPL SMALLINT;
BEGIN
    FOR
        SELECT SCHOOL_ID
        FROM GIA_OU_LIST(0, 1)
        INTO :SCHOOL_ID
    DO
    BEGIN
        CODE_SCHOOL_EGE = NULL;

        SELECT CODE, ISVPL
        FROM GIA_CODE_GET(:SCHOOL_ID)
        INTO :CODE_SCHOOL_EGE, :ISVPL;

        IF (CODE_SCHOOL_EGE IS NOT NULL) THEN
        BEGIN
            PPE = NULL;
            CODE_SCHOOL_PPE = NULL;
            KL4 = NULL;
            KL9 = NULL;
            KL11 = NULL;
            FULLNAME = NULL;
            SHORTNAME = NULL;
            CODE_SCHOOL_KIND = NULL;
            CODE_SCHOOL_TYPE = NULL;
            CODE_SCHOOL_OPF = NULL;
            ADDRESS = NULL;
            ADDRESS_PPE = NULL;
            LEADER_POSITION = NULL;
            LEADER_NAME = NULL;
            RESPONSIBLE_FOR_EGE = NULL;
            PHONES = NULL;
            FAX = NULL;
            EMAIL = NULL;
            WEB_SITE = NULL;
            NUMBER_GRADUATES = NULL;
            NUMBER_PRE_GRADUATES = NULL;
            LICENSE_NUMBER = NULL;
            LICENSE_COMMENCEMENT_DATE = NULL;
            LICENSE_EXPIRATION_DATE = NULL;
            ACCREDITATION_COMMENCEMENT_DATE = NULL;
            ACCREDITATION_EXPIRATION_DATE = NULL;
            SCHOOL_NUMBER = NULL;
            OOOD_TYPE = NULL;
            OOOD_VID = NULL;
            IF (ISVPL = 0) THEN
            BEGIN
                SELECT V.VAL
                FROM VALI V
                WHERE V.PARAM_ID = 1365 AND V.OBJ_ID = :SCHOOL_ID AND V.IS_DEL = 0
                INTO :PPE;

                CODE_SCHOOL_PPE = PPE;
                LEN = CHAR_LENGTH(CODE_SCHOOL_PPE);
                IF ((PPE IS NOT NULL) AND (PPE != 0)) THEN
                BEGIN
                    WHILE (LEN < 4) DO
                    BEGIN
                        CODE_SCHOOL_PPE = '0' || CODE_SCHOOL_PPE;
                        LEN = LEN + 1;
                    END
                END

                SELECT I FROM VAL_GET(:SCHOOL_ID, 1366, 0, :I$USER_ID) INTO :KL4;
                SELECT I FROM VAL_GET(:SCHOOL_ID, 1367, 0, :I$USER_ID) INTO :KL9;
                SELECT I FROM VAL_GET(:SCHOOL_ID, 1368, 0, :I$USER_ID) INTO :KL11;
                SELECT V FROM VAL_GET(:SCHOOL_ID, 5, 0, :I$USER_ID) INTO :FULLNAME;
                SELECT V FROM VAL_GET(:SCHOOL_ID, 2, 0, :I$USER_ID) INTO :SHORTNAME;

                SELECT CAST(L.TAG AS INTEGER)
                FROM VALL V
                JOIN LISTVALS L ON L.LIST_ID = 6 AND L.LISTVAL_ID = V.LISTVAL_ID AND L.IS_DEL = 0
                WHERE V.OBJ_ID = :SCHOOL_ID AND V.PARAM_ID = 10 AND V.IS_DEL = 0
                INTO :CODE_SCHOOL_KIND;

                IF ((CODE_SCHOOL_KIND IS NOT NULL) AND (CODE_SCHOOL_KIND > 1000000)) THEN
                BEGIN
                    CODE_SCHOOL_TYPE = CODE_SCHOOL_KIND / 1000000;
                    CODE_SCHOOL_KIND = 0;
                END
                ELSE
                BEGIN
                    IF ((CODE_SCHOOL_KIND IS NOT NULL) AND (CODE_SCHOOL_KIND > 0)) THEN
                    BEGIN
                        CODE_SCHOOL_TYPE = CODE_SCHOOL_KIND / 100;
                    END
                END

                SELECT V FROM VAL_GET(:SCHOOL_ID, 1889, 0, :I$USER_ID) INTO :OOOD_VID;
                SELECT V FROM VAL_GET(:SCHOOL_ID, 1890, 0, :I$USER_ID) INTO :OOOD_TYPE;

                SELECT L.TAG
                FROM VALL V
                JOIN LISTVALS L ON L.LIST_ID IN (4, 258) AND L.LISTVAL_ID = V.LISTVAL_ID AND L.IS_DEL = 0
                WHERE V.OBJ_ID = :SCHOOL_ID AND V.PARAM_ID = 8 AND V.IS_DEL = 0
                INTO :CODE_SCHOOL_OPF;

                SELECT VAL FROM ADR_GET(27, :SCHOOL_ID) INTO :ADDRESS;

                IF ((CODE_SCHOOL_PPE IS NOT NULL) AND (CODE_SCHOOL_PPE != 0)) THEN
                BEGIN
                    SELECT VAL FROM ADR_GET(1371, :SCHOOL_ID) INTO :ADDRESS_PPE;
                END

                SELECT OBJ_ID, POST
                FROM R_SPB_POST_DIRECTOR(:SCHOOL_ID,:I$USER_ID)
                INTO :DIRECTOR, :LEADER_POSITION;

                IF (DIRECTOR IS NOT NULL) THEN
                BEGIN
                    SELECT CAPTION
                    FROM OBJECT_CAPTION_GET(:DIRECTOR, NULL, NULL, :I$USER_ID)
                    INTO :LEADER_NAME;
                END

                OBJ_ID = NULL;
                SELECT V.VAL
                FROM VALR V
                WHERE V.PARAM_ID = 1369 AND V.OBJ_ID = :SCHOOL_ID AND V.IS_DEL = 0
                INTO :OBJ_ID;

                IF (OBJ_ID IS NOT NULL) THEN
                BEGIN
                    SELECT CAPTION
                    FROM OBJECT_CAPTION_GET(:OBJ_ID, NULL, NULL, :I$USER_ID)
                    INTO :RESPONSIBLE_FOR_EGE;
                END

                VAL = NULL;
                SELECT V FROM VAL_GET(:SCHOOL_ID, 28, 0, :I$USER_ID) INTO :PHONES;
                SELECT V FROM VAL_GET(:SCHOOL_ID, 29, 0, :I$USER_ID) INTO :VAL;

                IF ((PHONES IS NOT NULL) AND (VAL IS NOT NULL)) THEN
                BEGIN
                    PHONES = PHONES || '; ' || VAL;
                END
                ELSE
                BEGIN
                    PHONES = VAL;
                END

                SELECT V FROM VAL_GET(:SCHOOL_ID, 30, 0, :I$USER_ID) INTO :FAX;
                SELECT V FROM VAL_GET(:SCHOOL_ID, 35, 0, :I$USER_ID) INTO :EMAIL;
                SELECT V FROM VAL_GET(:SCHOOL_ID, 36, 0, :I$USER_ID) INTO :WEB_SITE;

                SELECT COUNT(L10.OBJ_ID)
                FROM LINKS L7
                JOIN LINKS L8 ON L8.OBJ_TYPE_ID = 8 AND L8.PARENT_ID = L7.OBJ_ID AND L8.DATE_DEL IS NULL
                JOIN LINKS L9 ON L9.OBJ_TYPE_ID IN (9, 187) AND L9.PARENT_ID = L8.OBJ_ID AND L9.DATE_DEL IS NULL
                JOIN LINKS L10 ON L10.OBJ_TYPE_ID = 10 AND L10.PARENT_ID = L9.OBJ_ID AND L10.DATE_DEL IS NULL
                JOIN VALL V ON V.PARAM_ID IN (2388, 2418) AND V.OBJ_ID = L9.OBJ_ID AND V.IS_DEL = 0
                WHERE L7.OBJ_TYPE_ID = 7 AND L7.PARENT_ID = :SCHOOL_ID AND L7.DATE_DEL IS NULL AND V.LISTVAL_ID IN (11202, 11203)
                INTO :NUMBER_GRADUATES;

                SELECT COUNT(L10.OBJ_ID)
                FROM LINKS L7
                JOIN LINKS L8 ON L8.OBJ_TYPE_ID = 8 AND L8.PARENT_ID = L7.OBJ_ID AND L8.DATE_DEL IS NULL
                JOIN LINKS L9 ON L9.OBJ_TYPE_ID = 9 AND L9.PARENT_ID = L8.OBJ_ID AND L9.DATE_DEL IS NULL
                JOIN LINKS L10 ON L10.OBJ_TYPE_ID = 10 AND L10.PARENT_ID = L9.OBJ_ID AND L10.DATE_DEL IS NULL
                JOIN VALL V ON V.PARAM_ID = 49 AND V.OBJ_ID = L8.OBJ_ID AND V.IS_DEL = 0
                JOIN LISTVALS LV ON LV.LISTVAL_ID = V.LISTVAL_ID AND LV.IS_DEL = 0
                WHERE L7.OBJ_TYPE_ID = 7 AND L7.PARENT_ID = :SCHOOL_ID AND L7.DATE_DEL IS NULL AND LV.TAG = 10
                INTO :NUMBER_PRE_GRADUATES;

                SELECT FIRST 1 V480.VAL, V482.VAL, V483.VAL
                FROM LINKS L
                JOIN VALL V471 ON L.OBJ_ID = V471.OBJ_ID AND V471.PARAM_ID = 471 AND V471.IS_DEL = 0 AND V471.LISTVAL_ID IN (1052, 1079, 18624)
                LEFT JOIN VALS V480 ON L.OBJ_ID = V480.OBJ_ID AND V480.PARAM_ID = 480 AND V480.IS_DEL = 0
                JOIN VALD V482 ON L.OBJ_ID = V482.OBJ_ID AND V482.PARAM_ID = 482 AND V482.IS_DEL = 0 AND (V482.VAL + (365.25 * 5)) >= CURRENT_DATE
                LEFT JOIN VALD V483 ON L.OBJ_ID = V483.OBJ_ID AND V483.PARAM_ID = 483 AND V483.IS_DEL = 0
                WHERE L.PARENT_ID = :SCHOOL_ID AND L.OBJ_TYPE_ID = 17 AND L.DATE_DEL IS NULL AND (V483.VAL IS NULL OR V483.VAL >= CURRENT_DATE)
                ORDER BY V482.VAL DESC--, V483.VAL DESC  --странно здесь сортировать по дате окончания, которая может быть и не заполнена
                INTO :LICENSE_NUMBER, :LICENSE_COMMENCEMENT_DATE, :LICENSE_EXPIRATION_DATE;

                IF ((LICENSE_NUMBER IS NOT NULL) AND (LICENSE_COMMENCEMENT_DATE IS NOT NULL) AND (LICENSE_EXPIRATION_DATE IS NULL)) THEN
                BEGIN
                    LICENSE_EXPIRATION_DATE = LICENSE_COMMENCEMENT_DATE + (365.25 * 5);
                END

                SELECT FIRST 1 V482.VAL, V483.VAL
                FROM LINKS L
                JOIN VALL V471 ON L.OBJ_ID = V471.OBJ_ID AND V471.PARAM_ID = 471 AND V471.IS_DEL = 0 AND V471.LISTVAL_ID IN (1053, 18625)
                LEFT JOIN VALD V482 ON L.OBJ_ID = V482.OBJ_ID AND V482.PARAM_ID = 482 AND V482.IS_DEL = 0
                LEFT JOIN VALD V483 ON L.OBJ_ID = V483.OBJ_ID AND V483.PARAM_ID = 483 AND V483.IS_DEL = 0
                WHERE L.PARENT_ID = :SCHOOL_ID AND L.OBJ_TYPE_ID = 17 AND L.DATE_DEL IS NULL
                ORDER BY V482.VAL DESC -- отсортируем по дате выдачи
                INTO :ACCREDITATION_COMMENCEMENT_DATE, :ACCREDITATION_EXPIRATION_DATE;

                SELECT I FROM VAL_GET(:SCHOOL_ID, 17, 0, :I$USER_ID) INTO :SCHOOL_NUMBER;
            END
            ELSE
            BEGIN
                SELECT V FROM VAL_GET(:SCHOOL_ID, 764, 0, :I$USER_ID) INTO :FULLNAME;

                SHORTNAME = FULLNAME;

                SELECT VAL FROM ADR_GET(759, :SCHOOL_ID) INTO :ADDRESS;

                LEADER_POSITION = 'Ответственный за регистрацию ВПЛ';

                SELECT V FROM VAL_GET(:SCHOOL_ID, 756, 0, :I$USER_ID) INTO :LEADER_NAME;

                VAL = NULL;
                SELECT V FROM VAL_GET(:SCHOOL_ID, 757, 0, :I$USER_ID) INTO :VAL;
                LEADER_NAME = LEADER_NAME || ' ' || VAL;

                VAL = NULL;
                SELECT V FROM VAL_GET(:SCHOOL_ID, 758, 0, :I$USER_ID) INTO :VAL;
                IF (VAL IS NOT NULL) THEN LEADER_NAME = LEADER_NAME || ' ' || VAL;

                SELECT V FROM VAL_GET(:SCHOOL_ID, 909, 0, :I$USER_ID) INTO :RESPONSIBLE_FOR_EGE;

                VAL = NULL;
                SELECT V FROM VAL_GET(:SCHOOL_ID, 910, 0, :I$USER_ID) INTO :VAL;
                RESPONSIBLE_FOR_EGE = RESPONSIBLE_FOR_EGE || ' ' || VAL;

                VAL = NULL;

                SELECT V FROM VAL_GET(:SCHOOL_ID, 911, 0, :I$USER_ID) INTO :VAL;

                IF (VAL IS NOT NULL) THEN RESPONSIBLE_FOR_EGE = RESPONSIBLE_FOR_EGE || ' ' || VAL;

                SELECT V FROM VAL_GET(:SCHOOL_ID, 761, 0, :I$USER_ID) INTO :PHONES;
                SELECT V FROM VAL_GET(:SCHOOL_ID, 760, 0, :I$USER_ID) INTO :FAX;
                SELECT V FROM VAL_GET(:SCHOOL_ID, 762, 0, :I$USER_ID) INTO :EMAIL;
                SELECT V FROM VAL_GET(:SCHOOL_ID, 763, 0, :I$USER_ID) INTO :WEB_SITE;

                SELECT COUNT(L126.OBJ_ID)
                FROM LINKS L125
                JOIN LINKS L126 ON L126.OBJ_TYPE_ID = 126 AND L126.PARENT_ID = L125.OBJ_ID AND L126.DATE_DEL IS NULL
                WHERE L125.OBJ_TYPE_ID = 125 AND L125.PARENT_ID = :SCHOOL_ID AND L125.DATE_DEL IS NULL
                INTO :NUMBER_GRADUATES;
            END

            SUSPEND;
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GIA_OU_EXPORT_XML_CHECK RETURNS (
    ERR SMALLINT,
    VAL VARCHAR(500))
AS
DECLARE VARIABLE SCHOOL_ID BIGINT;
DECLARE VARIABLE CNT INTEGER;
DECLARE VARIABLE CODE_SCHOOL_EGE BIGINT;
BEGIN
    FOR SELECT SCHOOL_ID
        FROM GIA_OU_LIST(0, 1)
        INTO :SCHOOL_ID
    DO
    BEGIN
        CNT = 0;

        CODE_SCHOOL_EGE = NULL;
        SELECT CODE
        FROM GIA_CODE_GET(:SCHOOL_ID)
        INTO :CODE_SCHOOL_EGE;
        IF (CODE_SCHOOL_EGE IS NOT NULL) THEN
        BEGIN
            SELECT COUNT(*)
            FROM GIA_ROOM_LIST2(:SCHOOL_ID)
            WHERE (PPE_CODE IS NULL) OR (PPE_CODE = '')
            INTO :CNT;
        END

        IF (CNT > 0) THEN
        BEGIN
            VAL = NULL;
            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:SCHOOL_ID)
            INTO :VAL;

            ERR = 1;
            SUSPEND;
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GIA_OU_ISVALID (
    OBJ_ID BIGINT = NULL)
RETURNS (
    ISVALID SMALLINT)
AS
DECLARE VARIABLE PPECODE BIGINT;
DECLARE VARIABLE PPEBUILDING BIGINT;
BEGIN
    IF (OBJ_ID IS NULL) THEN
    BEGIN
        SELECT FIRST 1 L.OBJ_ID
        FROM LINKS L
        WHERE L.PARENT_ID IS NULL AND L.OBJ_TYPE_ID = 2 AND L.DATE_DEL IS NULL
        INTO :OBJ_ID;
    END

    SELECT I
    FROM VAL_GET(:OBJ_ID, 1365)
    INTO :PPECODE;

    SELECT I
    FROM VAL_GET(:OBJ_ID, 1370)
    INTO :PPEBUILDING;

    IF ((PPECODE IS NOT NULL) AND (PPECODE <> 0) AND (PPEBUILDING IS NOT NULL) AND (PPEBUILDING <> 0)) THEN
        ISVALID = 1;
    ELSE
        ISVALID = 0;
    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GIA_OU_LIST (
    I$DISTRICT_ID BIGINT = 0,
    DISPLAY_ALL SMALLINT = 0)
RETURNS (
    SCHOOL_ID BIGINT,
    DISTRICT_ID BIGINT,
    SCHOOL VARCHAR(4000),
    DISTRICT VARCHAR(4000),
    SCHOOL_NUMBER INTEGER)
AS
declare variable LEVEL_ID smallint;
declare variable CODE_PPE integer;
declare variable V$OU_LICENCE_TYPE varchar(1);
BEGIN
    SELECT STATUS FROM OU_LICENCE_TYPE INTO :V$OU_LICENCE_TYPE;
    SELECT KEY_VAL
    FROM KEYS
    WHERE KEY_CODE = 'LEVEL'
    INTO :LEVEL_ID;

    FOR SELECT FIRST 1 L.OBJ_ID, NULL
        FROM LINKS L
        WHERE L.PARENT_ID IS NULL
          AND L.OBJ_TYPE_ID = 2
          AND L.DATE_DEL IS NULL
          AND ((:LEVEL_ID IS NULL) OR (:LEVEL_ID < 2))

        UNION

        SELECT FIRST 1 L.OBJ_ID, NULL
        FROM LINKS L
        WHERE L.PARENT_ID IS NULL
          AND L.OBJ_TYPE_ID = 124
          AND L.DATE_DEL IS NULL
          AND ((:LEVEL_ID IS NULL) OR (:LEVEL_ID < 2))
--------------------------------------------------------------------------------
        UNION

        SELECT L2.OBJ_ID, L112.OBJ_ID
        FROM LINKS L112
        JOIN LINKS L2 ON L2.PARENT_ID = L112.OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
        WHERE L112.PARENT_ID IS NULL
          AND L112.OBJ_TYPE_ID = 112
          AND L112.DATE_DEL IS NULL
          AND :LEVEL_ID = 3

        UNION

        SELECT L124.OBJ_ID, L112.OBJ_ID
        FROM LINKS L112
        JOIN LINKS L124 ON L124.PARENT_ID = L112.OBJ_ID AND L124.OBJ_TYPE_ID = 124 AND L124.DATE_DEL IS NULL
        WHERE L112.PARENT_ID IS NULL
          AND L112.OBJ_TYPE_ID = 112
          AND L112.DATE_DEL IS NULL
          AND :LEVEL_ID = 3
--------------------------------------------------------------------------------
        UNION

        SELECT L2.OBJ_ID, L111.OBJ_ID
        FROM LINKS L111
        JOIN LINKS L2 ON L2.PARENT_ID = L111.OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
        WHERE L111.PARENT_ID IS NULL
          AND L111.OBJ_TYPE_ID = 111
          AND L111.DATE_DEL IS NULL
          AND :LEVEL_ID = 2

        UNION

        SELECT L124.OBJ_ID, L111.OBJ_ID
        FROM LINKS L111
        JOIN LINKS L124 ON L124.PARENT_ID = L111.OBJ_ID AND L124.OBJ_TYPE_ID = 124 AND L124.DATE_DEL IS NULL
        WHERE L111.PARENT_ID IS NULL
          AND L111.OBJ_TYPE_ID = 111
          AND L111.DATE_DEL IS NULL
          AND :LEVEL_ID = 2

        UNION

        SELECT L2.OBJ_ID, L111.OBJ_ID
        FROM LINKS L112
        JOIN LINKS L111 ON L111.PARENT_ID = L112.OBJ_ID AND L111.OBJ_TYPE_ID = 111 AND L111.DATE_DEL IS NULL
        JOIN LINKS L2 ON L2.PARENT_ID = L111.OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
        WHERE L112.PARENT_ID IS NULL
          AND L112.OBJ_TYPE_ID = 112
          AND L112.DATE_DEL IS NULL
          AND :LEVEL_ID = 3
          AND ((:I$DISTRICT_ID IS NULL) OR (:I$DISTRICT_ID = 0) OR (:I$DISTRICT_ID = L111.OBJ_ID))

        UNION

        SELECT L124.OBJ_ID, L111.OBJ_ID
        FROM LINKS L112
        JOIN LINKS L111 ON L111.PARENT_ID = L112.OBJ_ID AND L111.OBJ_TYPE_ID = 111 AND L111.DATE_DEL IS NULL
        JOIN LINKS L124 ON L124.PARENT_ID = L111.OBJ_ID AND L124.OBJ_TYPE_ID = 124 AND L124.DATE_DEL IS NULL
        WHERE L112.PARENT_ID IS NULL
          AND L112.OBJ_TYPE_ID = 112
          AND L112.DATE_DEL IS NULL
          AND :LEVEL_ID = 3
          AND ((:I$DISTRICT_ID IS NULL) OR (:I$DISTRICT_ID = 0) OR (:I$DISTRICT_ID = L111.OBJ_ID))

        INTO :SCHOOL_ID, :DISTRICT_ID
    DO
    BEGIN
        SCHOOL_NUMBER = NULL;
        IF (SCHOOL_ID IS NOT NULL) THEN
        BEGIN
            CODE_PPE = NULL;
            SELECT V.VAL
            FROM VALI V
            WHERE V.PARAM_ID = 1365
              AND V.OBJ_ID = :SCHOOL_ID
              AND V.IS_DEL = 0
            INTO :CODE_PPE;

            IF ((CODE_PPE IS NULL) AND (DISPLAY_ALL = 0)) THEN
            BEGIN
                SCHOOL = NULL;
                SCHOOL_ID = NULL;
            END
            ELSE
            BEGIN
                SELECT CAPTION
                FROM OBJECT_CAPTION_GET(:SCHOOL_ID)
                INTO :SCHOOL;

                SELECT I
                FROM VAL_GET(:SCHOOL_ID, 17)
                INTO :SCHOOL_NUMBER;
            END
        END
        ELSE
            SCHOOL = NULL;

        IF (DISTRICT_ID IS NOT NULL) THEN
        BEGIN
            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:DISTRICT_ID)
            INTO :DISTRICT;
        END
        ELSE
            DISTRICT = NULL;

        IF ((I$DISTRICT_ID IS NULL) OR (SCHOOL IS NOT NULL)) THEN
            SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GIA_PPE_FLAGS (
    SCHOOL_ID BIGINT)
RETURNS (
    FOR9 SMALLINT,
    FOR11 SMALLINT)
AS
BEGIN
    FOR9 = NULL;
    SELECT V.VAL
    FROM VALI V
    WHERE V.PARAM_ID = 1367
      AND V.OBJ_ID = :SCHOOL_ID
      AND V.IS_DEL = 0
    INTO :FOR9;

    FOR11 = NULL;
    SELECT V.VAL
    FROM VALI V
    WHERE V.PARAM_ID = 1368
      AND V.OBJ_ID = :SCHOOL_ID
      AND V.IS_DEL = 0
    INTO :FOR11;

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GIA_PPE_LIST RETURNS (
    LINENO INTEGER,
    DISTRICT VARCHAR(500),
    SHORTNAME VARCHAR(500),
    SCHOOLNO INTEGER,
    CODE_OU INTEGER,
    CODE_PPE INTEGER,
    PPE_FOR9 INTEGER,
    PPE_FOR11 INTEGER,
    ROOM_COUNT INTEGER,
    SEATS_COUNT INTEGER,
    ADDRESS VARCHAR(500))
AS
declare variable LEVEL_ID smallint;
declare variable SCHOOL_ID bigint;
BEGIN
    SELECT KEY_VAL
    FROM KEYS
    WHERE KEY_CODE = 'LEVEL'
    INTO :LEVEL_ID;

    LINENO = 0;

    FOR SELECT DISTRICT, SCHOOL_ID, SHORTNAME, CODE_OU, CODE_PPE, COALESCE(FOR9, 0), COALESCE(FOR11, 0), ADDRESS, SCHOOLNO
        FROM GIA_CODES_LIST(:LEVEL_ID)
        WHERE CODE_PPE IS NOT NULL
        ORDER BY DISTRICT, SHORTNAME
        INTO :DISTRICT, :SCHOOL_ID, :SHORTNAME, :CODE_OU, :CODE_PPE, :PPE_FOR9, :PPE_FOR11, :ADDRESS, :SCHOOLNO
    DO
    BEGIN
        LINENO = LINENO + 1;

        SELECT COUNT(L.OBJ_ID), SUM(L.COLUMN_SUM)
        FROM GIA_ROOM_LIST2(:SCHOOL_ID) L
        INTO :ROOM_COUNT, :SEATS_COUNT;

        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GIA_REPORT_IF4_P1 (
    I$GRADUATE SMALLINT,
    I$USER_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    PARALLEL BIGINT,
    EXAM_SUBJECT_ID BIGINT,
    EXAM_ID BIGINT,
    EXAM_DATE DATE,
    OLD_GRADUATE SMALLINT,
    SPECIAL_CONDITIONS SMALLINT,
    GIA_ONLY SMALLINT)
AS
declare variable SCHOOL_ID bigint;
declare variable CLASS_ID bigint;
declare variable YEAR_ID bigint;
BEGIN
    SELECT YEAR_ID
    FROM GIA_APPOINT_CURRENT_YEAR(:I$USER_ID)
    INTO :YEAR_ID;

    FOR SELECT SCHOOL_ID
        FROM GIA_OU_LIST(0, 1)
        INTO :SCHOOL_ID
    DO
    BEGIN
        FOR SELECT OBJ_ID, PARALLEL
            FROM GIA_APPOINT_CLASS_LIST(:SCHOOL_ID, :I$USER_ID)
            WHERE (
                  ((PARALLEL = 9) AND (:I$GRADUATE = 0))
                  OR ((GRADUATE != 0) AND (:I$GRADUATE > 0))
                  )
                  OR (:I$GRADUATE IS NULL)
            INTO :CLASS_ID, :PARALLEL
        DO
        BEGIN
            FOR SELECT OBJ_ID, EXAM_SUBJECT_ID, EXAM_ID, EXAM_DATE, OLD_GRADUATE, SPECIAL_CONDITIONS, GIA_ONLY
                FROM GIA_APPOINT_LIST(:CLASS_ID, :YEAR_ID)
                INTO :OBJ_ID, :EXAM_SUBJECT_ID, :EXAM_ID, :EXAM_DATE, :OLD_GRADUATE, :SPECIAL_CONDITIONS, :GIA_ONLY
            DO
            BEGIN
                IF (EXAM_SUBJECT_ID IS NOT NULL) THEN
                    SUSPEND;
            END
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GIA_REPORT_IF4_P2 (
    I$GRADUATE SMALLINT,
    I$USER_ID BIGINT)
RETURNS (
    LINENO INTEGER,
    LINESTR VARCHAR(2000),
    LINEDATE DATE,
    CNT INTEGER,
    OLD_GRADUATE_SUM INTEGER,
    SPECIAL_CONDITIONS_SUM INTEGER,
    GIA_ONLY_SUM INTEGER,
    EXAM_ID BIGINT)
AS
declare variable LANG_CODE varchar(2);
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :LANG_CODE;

    LINENO = 0;
    FOR
        SELECT
          COUNT(DISTINCT P.OBJ_ID),
          SUM(P.OLD_GRADUATE) OLD_GRADUATE_SUM,
          SUM(P.SPECIAL_CONDITIONS) SPECIAL_CONDITIONS_SUM,
          SUM(P.GIA_ONLY) GIA_ONLY_SUM,
          P.PARALLEL || ' / ' || R.VAL,
          P.EXAM_ID,
          P.EXAM_DATE
        FROM GIA_REPORT_IF4_P1(:I$GRADUATE, :I$USER_ID) P

        JOIN LISTVALS LV
        ON LV.LIST_ID = 212
        AND LV.LISTVAL_ID = P.EXAM_SUBJECT_ID
        AND LV.IS_DEL = 0

        LEFT JOIN RES_GET(LV.RES_ID,  :LANG_CODE) R ON 1=1

        GROUP BY P.PARALLEL,
                 R.VAL,
                 P.EXAM_ID,
                 P.EXAM_DATE

        INTO :CNT, :OLD_GRADUATE_SUM, :SPECIAL_CONDITIONS_SUM, :GIA_ONLY_SUM,
             :LINESTR,
             :EXAM_ID,
             :LINEDATE
    DO
    BEGIN
        LINENO = LINENO + 1;
        SUSPEND;
    END

    LINENO = NULL;
    EXAM_ID = NULL;
    LINEDATE = NULL;

    SELECT FIRST 1 WORD
    FROM REPORT_WORDS
    WHERE ID = 35
    INTO :LINESTR;

    SELECT COUNT(DISTINCT P.OBJ_ID)
    FROM GIA_REPORT_IF4_P1(:I$GRADUATE, :I$USER_ID) P
    INTO :CNT;

    SELECT COUNT(DISTINCT P.OBJ_ID)
    FROM GIA_REPORT_IF4_P1(:I$GRADUATE, :I$USER_ID) P
    WHERE OLD_GRADUATE = 1
    INTO :OLD_GRADUATE_SUM;

    SELECT COUNT(DISTINCT P.OBJ_ID)
    FROM GIA_REPORT_IF4_P1(:I$GRADUATE, :I$USER_ID) P
    WHERE SPECIAL_CONDITIONS = 1
    INTO :SPECIAL_CONDITIONS_SUM;

    SELECT COUNT(DISTINCT P.OBJ_ID)
    FROM GIA_REPORT_IF4_P1(:I$GRADUATE, :I$USER_ID) P
    WHERE GIA_ONLY = 1
    INTO :GIA_ONLY_SUM;

    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GIA_RESET_GENERATORS RETURNS (
    MAX_GEN BIGINT,
    MAX_VAL BIGINT,
    CUR_GEN BIGINT,
    NEW_GEN BIGINT)
AS
declare variable V$GEN bigint;
declare variable V$MULTIPLIER bigint;
declare variable V$MIN_GEN bigint;
BEGIN
  SELECT G.GEN, G.MULTIPLIER
  FROM GEN G
  INTO :V$GEN, :V$MULTIPLIER;

  -- Предельный ID для проверки генерации
  MAX_GEN = (V$GEN + 1) * V$MULTIPLIER;
  V$MIN_GEN = V$GEN * V$MULTIPLIER;

  SELECT MAX(O.OBJ_ID) - :V$MIN_GEN
  FROM OBJECTS O
  WHERE O.OBJ_ID >= :V$MIN_GEN AND O.OBJ_ID < :MAX_GEN
  INTO :MAX_VAL;

  CUR_GEN = GEN_ID(GEN_OBJ_ID, 0);

  -- Если текущее значение генератора оказывается меньше реальных ID объектов, корректируем генератор
  IF(CUR_GEN < MAX_VAL) THEN NEW_GEN = GEN_ID(GEN_OBJ_ID, MAX_VAL - CUR_GEN);
  ELSE IF(CUR_GEN > V$MULTIPLIER) THEN EXCEPTION DATA_ERROR 'Переполнение генераторов ID. Требуется ручное вмешательство';

  SUSPEND;

  SELECT MAX(L.LINK_ID) - :V$MIN_GEN
  FROM LINKS L
  WHERE L.LINK_ID >= :V$MIN_GEN AND L.LINK_ID < :MAX_GEN
  INTO :MAX_VAL;

  CUR_GEN = GEN_ID(GEN_LINK_ID, 0);

  -- Если текущее значение генератора оказывается меньше реальных ID объектов, корректируем генератор
  IF(CUR_GEN < MAX_VAL) THEN NEW_GEN = GEN_ID(GEN_LINK_ID, MAX_VAL - CUR_GEN);
  ELSE IF(CUR_GEN > V$MULTIPLIER) THEN EXCEPTION DATA_ERROR 'Переполнение генераторов ID. Требуется ручное вмешательство';

  SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GIA_ROOM_ADD (
    ROOM_ID BIGINT,
    PPE_CODE VARCHAR(4000),
    COLUMN_COUNT INTEGER = null)
RETURNS (
    O$ROOM_ID BIGINT)
AS
declare variable V$BLOB_ID bigint;
declare variable V$PARENT_ID bigint;
begin
  /* IF (ROOM_ID IS NULL) THEN
    BEGIN

        SELECT FIRST 1 L.OBJ_ID
        FROM LINKS L
        WHERE L.PARENT_ID IS NULL
          AND L.OBJ_TYPE_ID = 2
          AND L.DATE_DEL IS NULL
        INTO :BLOB_ID;

        SELECT FIRST 1 L16.OBJ_ID
        FROM LINKS L73
        JOIN LINKS L16 ON L16.PARENT_ID = L73.OBJ_ID
        WHERE L73.PARENT_ID = :BLOB_ID
          AND L73.DATE_DEL IS NULL
          AND L16.OBJ_TYPE_ID = 16
          AND L16.DATE_DEL IS NULL
        INTO :PARENT_ID;


        SELECT FIRST 1 L16.PARENT_ID
        FROM LINKS L16
        WHERE L16.PARENT_TYPE_ID = 16
          AND L16.OBJ_ID = :ROOM_REF_ID
          AND L16.DATE_DEL IS NULL
        INTO :PARENT_ID;

        SELECT OBJ_ID
        FROM OBJECT_ADD(:PARENT_ID, 121)
        INTO :ROOM_ID;
    END  */

  O$ROOM_ID = ROOM_ID;

  if (ROOM_ID is not null) then
  begin
    select BLOB_ID
    from VAL_ADD(1403, :ROOM_ID, :PPE_CODE)
    into :V$BLOB_ID;

    /*   SELECT BLOB_ID
        FROM VAL_ADD(748, :ROOM_ID, :ROOM_REF_ID)
        INTO :BLOB_ID;  */
  end

  if (COLUMN_COUNT is not null) then
  begin
    for select L122.OBJ_ID
        from LINKS L122
        join VALI CN on CN.OBJ_ID = L122.OBJ_ID and CN.PARAM_ID = 750
        and CN.IS_DEL = 0 and CN.VAL >= :COLUMN_COUNT
        where L122.PARENT_ID = :ROOM_ID and
              L122.OBJ_TYPE_ID = 122 and
              L122.DATE_DEL is null
        into :V$BLOB_ID
    do
    begin
      update VALI CN
      set CN.IS_DEL = 1
      where CN.OBJ_ID = :V$BLOB_ID;

      update LINKS L122
      set L122.DATE_DEL = current_timestamp
      where L122.OBJ_ID = :V$BLOB_ID;
    end
  end

  suspend;
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GIA_ROOM_CHECK (
    OBJ_ID BIGINT,
    PPE_CODE VARCHAR(4000))
RETURNS (
    ERROR_LEVEL INTEGER)
AS
DECLARE VARIABLE PARENT_ID BIGINT;
DECLARE VARIABLE ROOT_ID BIGINT;
DECLARE VARIABLE ERR INTEGER;
BEGIN
    ERROR_LEVEL = 0;

    SELECT FIRST 1 L.OBJ_ID
    FROM LINKS L
    WHERE L.PARENT_ID IS NULL
    AND L.OBJ_TYPE_ID = 2
    AND L.DATE_DEL IS NULL
    INTO :ROOT_ID;

    SELECT FIRST 1 L16.OBJ_ID
    FROM LINKS L73

    JOIN LINKS L16
    ON L16.PARENT_ID = L73.OBJ_ID
    AND L16.OBJ_TYPE_ID = 16
    AND L16.DATE_DEL IS NULL

    WHERE L73.PARENT_ID = :ROOT_ID
    AND L73.DATE_DEL IS NULL
    INTO :PARENT_ID;

    IF (OBJ_ID IS NOT NULL) THEN
    BEGIN
        SELECT FIRST 1 VF.VAL
        FROM VALI VF
        WHERE VF.OBJ_ID = :OBJ_ID
        AND VF.PARAM_ID = 529
        AND VF.IS_DEL = 0
        INTO :ERR;

        IF (ERR IS NULL) THEN
        BEGIN
            ERROR_LEVEL = ERROR_LEVEL + 1;
        END

        SELECT COUNT(L61.OBJ_ID)
        FROM LINKS L73

        JOIN LINKS L16
        ON L16.PARENT_ID = L73.OBJ_ID
        AND L16.OBJ_TYPE_ID = 16
        AND L16.DATE_DEL IS NULL

        JOIN LINKS L61
        ON L61.PARENT_ID = L16.OBJ_ID
        AND L61.OBJ_TYPE_ID = 61
        AND L61.DATE_DEL IS NULL

        JOIN VALS VS
        ON VS.OBJ_ID = L61.OBJ_ID
        AND VS.PARAM_ID = 1403
        AND VS.IS_DEL = 0

        WHERE (VS.VAL IS NOT NULL)
        AND ((L61.OBJ_ID = :OBJ_ID) OR (:OBJ_ID IS NULL))
        INTO :ERR;

        IF (ERR > 0) THEN
        BEGIN
            ERROR_LEVEL = ERROR_LEVEL + 10;
        END
    END
    IF (PPE_CODE IS NOT NULL) THEN
    BEGIN
        SELECT COUNT(L61.LINK_ID)
        FROM LINKS L61

        JOIN VALS VS
        ON VS.PARAM_ID = 1403
        AND VS.OBJ_ID = L61.OBJ_ID
        AND VS.IS_DEL = 0

        WHERE L61.PARENT_ID = :PARENT_ID
        AND L61.DATE_DEL IS NULL
        AND L61.OBJ_TYPE_ID = 61
        AND VS.VAL = :PPE_CODE
        AND ((L61.OBJ_ID != :OBJ_ID) OR (:OBJ_ID IS NULL))
        INTO :ERR;

        IF (ERR > 0) THEN
        BEGIN
            ERROR_LEVEL = ERROR_LEVEL + 2;
        END
    END
    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GIA_ROOM_DEL (
    ROOM_ID BIGINT)
RETURNS (
    DEL_COUNT INTEGER)
AS
BEGIN
  /* UPDATE LINKS L
    SET L.DATE_DEL = CURRENT_TIMESTAMP
    WHERE L.OBJ_ID = :ROOM_ID
      AND L.OBJ_TYPE_ID = 121
      AND L.DATE_DEL IS NULL;   */

    UPDATE VALS VS
    SET VS.IS_DEL = 1
    WHERE VS.OBJ_ID = :ROOM_ID
    AND VS.IS_DEL = 0
    AND VS.PARAM_ID = 1403;

    UPDATE LINKS L
    SET L.DATE_DEL = CURRENT_TIMESTAMP
    WHERE L.PARENT_ID = :ROOM_ID
    AND L.OBJ_TYPE_ID = 122
    AND L.DATE_DEL IS NULL;

    DEL_COUNT = ROW_COUNT;
    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GIA_ROOM_EDIT_COL (
    OBJ_ID BIGINT NOT NULL,
    COLUMN_NUMBER INTEGER NOT NULL,
    COLUMN_VALUE INTEGER)
AS
DECLARE VARIABLE V$COL_OBJ_ID BIGINT;
DECLARE VARIABLE V$COL_VAL INTEGER;
DECLARE VARIABLE V$BLOB_ID BIGINT;
BEGIN
    SELECT FIRST 1 L122.OBJ_ID, CC.VAL
    FROM LINKS L122
    JOIN VALI CN ON CN.OBJ_ID = L122.OBJ_ID AND CN.PARAM_ID = 750 /* and cn.is_del = 0*/
    AND CN.VAL = :COLUMN_NUMBER
    LEFT JOIN VALI CC ON CC.OBJ_ID = L122.OBJ_ID AND CC.PARAM_ID = 1372 AND CC.IS_DEL = 0
    WHERE L122.PARENT_ID = :OBJ_ID
      AND L122.OBJ_TYPE_ID = 122
      AND L122.DATE_DEL IS NULL
    ORDER BY CN.VAL
    INTO :V$COL_OBJ_ID, :V$COL_VAL;

    IF (V$COL_OBJ_ID IS NULL) THEN
    BEGIN
        -- create column
        SELECT OBJ_ID
        FROM OBJECT_ADD(:OBJ_ID, 122)
        INTO :V$COL_OBJ_ID;
    END
    IF ((V$COL_OBJ_ID IS NOT NULL) AND (COLUMN_VALUE IS NULL)) THEN
    BEGIN
        -- delete column - mark as deleted
        UPDATE LINKS L122
        SET L122.DATE_DEL = CURRENT_TIMESTAMP
        WHERE L122.OBJ_ID = :V$COL_OBJ_ID;
    END
    ELSE
    BEGIN
        -- edit existing column
        SELECT BLOB_ID
        FROM VAL_ADD(750, :V$COL_OBJ_ID, :COLUMN_NUMBER)
        INTO :V$BLOB_ID;

        IF (COLUMN_VALUE IS NOT NULL) THEN
            SELECT BLOB_ID
            FROM VAL_ADD(1372, :V$COL_OBJ_ID, :COLUMN_VALUE)
            INTO :V$BLOB_ID;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GIA_ROOM_LIST (
    I$ROOM_ID BIGINT = null)
RETURNS (
    OBJ_ID BIGINT,
    OBJ_CAPTION VARCHAR(4000),
    SORT_ORDER DOUBLE PRECISION,
    "FLOOR" INTEGER)
AS
declare variable V$SCHOOL_ID bigint;
declare variable V$BUILDING_ID bigint;
declare variable V$PPE_CODE integer;
begin
    SELECT FIRST 1 L.OBJ_ID
    FROM LINKS L
    WHERE L.PARENT_ID IS NULL
    AND L.OBJ_TYPE_ID = 2
    AND L.DATE_DEL IS NULL
    INTO :V$SCHOOL_ID;

    SELECT V.VAL
    FROM VALR V
    WHERE V.PARAM_ID = 1370
    AND V.OBJ_ID = :V$SCHOOL_ID
    AND V.IS_DEL = 0
    INTO :V$BUILDING_ID;

    FOR
        SELECT DISTINCT L.OBJ_ID
        FROM LINKS L
        WHERE L.PARENT_ID = :V$BUILDING_ID
        AND L.OBJ_TYPE_ID = 61
        AND L.DATE_DEL IS NULL
        INTO :OBJ_ID
    DO
    BEGIN
        SELECT COUNT(VS.VAL)
        FROM VALS VS
        WHERE VS.OBJ_ID = :OBJ_ID
        AND VS.PARAM_ID = 1403
        AND VS.IS_DEL = 0
        INTO :V$PPE_CODE;
        IF ((:V$PPE_CODE = 0) OR (I$ROOM_ID = OBJ_ID))  THEN
        BEGIN
            SELECT CAPTION, SORT_ORDER
            FROM OBJECT_CAPTION_GET(:OBJ_ID)
            INTO :OBJ_CAPTION, :SORT_ORDER;

            SELECT I
            FROM VAL_GET(:OBJ_ID, 529)
            INTO :FLOOR;
            SUSPEND;
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GIA_ROOM_LIST2 (
    I$SCHOOL_ID BIGINT = null)
RETURNS (
    OBJ_ID BIGINT,
    ROOM_OBJ_CAPTION VARCHAR(4000),
    PPE_CODE VARCHAR(4000),
    COLUMN_COUNT INTEGER,
    COLUMN_STRING VARCHAR(200),
    COLUMN_SUM INTEGER,
    "FLOOR" SMALLINT)
AS
declare variable V$SCHOOL_ID bigint;
declare variable V$COLUMN_VALUE integer;
declare variable V$COLUMN_NUMBER integer;
begin
    IF ((I$SCHOOL_ID IS NULL) OR (I$SCHOOL_ID = 0)) THEN
    BEGIN
        SELECT FIRST 1 L.OBJ_ID
        FROM LINKS L
        WHERE L.PARENT_ID IS NULL
        AND L.OBJ_TYPE_ID = 2
        AND L.DATE_DEL IS NULL
        INTO :V$SCHOOL_ID;
    END
    ELSE
    BEGIN
        V$SCHOOL_ID = I$SCHOOL_ID;
    END

    FOR
        SELECT L61.OBJ_ID, RN.VAL -- RR.VAL,
        FROM LINKS L73
        JOIN LINKS L16 ON L16.PARENT_ID = L73.OBJ_ID AND L16.OBJ_TYPE_ID = 16 AND L16.DATE_DEL IS NULL
        JOIN LINKS L61 ON L61.PARENT_ID = L16.OBJ_ID AND L61.OBJ_TYPE_ID = 61 AND L61.DATE_DEL IS NULL
        --
        --  LEFT JOIN VALR RR ON RR.OBJ_ID = L121.OBJ_ID AND RR.PARAM_ID = 748 AND RR.IS_DEL = 0
        --
        LEFT JOIN VALS RN ON RN.OBJ_ID = L61.OBJ_ID AND RN.PARAM_ID = 1403 AND RN.IS_DEL = 0
        WHERE L73.OBJ_TYPE_ID = 73
        AND L73.PARENT_ID = :V$SCHOOL_ID
        AND L73.DATE_DEL IS NULL
        INTO :OBJ_ID, :PPE_CODE -- :ROOM_OBJ_ID,
    DO
    BEGIN
        IF (:PPE_CODE IS NOT NULL) THEN
        BEGIN
            SELECT FIRST 1 CAPTION
            FROM OBJECT_CAPTION_GET(:OBJ_ID) --
            INTO :ROOM_OBJ_CAPTION;

            SELECT I
            FROM VAL_GET(:OBJ_ID, 529) --
            INTO :FLOOR;

            COLUMN_COUNT = NULL;
            COLUMN_STRING = NULL;
            COLUMN_SUM = NULL;
            FOR
                SELECT C.COLUMN_VALUE, C.COLUMN_NUMBER
                FROM GIA_ROOM_LIST_COL(:OBJ_ID) C
                ORDER BY C.COLUMN_NUMBER
                INTO :V$COLUMN_VALUE, :V$COLUMN_NUMBER
            DO
            BEGIN
                IF (COLUMN_STRING IS NOT NULL) THEN
                BEGIN
                    COLUMN_STRING = COLUMN_STRING || ' - ';
                END
                ELSE
                BEGIN
                    COLUMN_COUNT = 0;
                    COLUMN_STRING = '';
                    COLUMN_SUM = 0;
                END
                IF (V$COLUMN_NUMBER > COLUMN_COUNT) THEN
                BEGIN
                    COLUMN_COUNT = V$COLUMN_NUMBER;
                END
                COLUMN_STRING = COLUMN_STRING || COALESCE(V$COLUMN_VALUE, '');
                COLUMN_SUM = COLUMN_SUM + V$COLUMN_VALUE;
            END
            IF (COLUMN_STRING > '') THEN
            BEGIN
                COLUMN_STRING = '[ ' || COLUMN_STRING || ' ]';
            END
            SUSPEND;
        END
    END
end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GIA_ROOM_LIST_COL (
    OBJ_ID BIGINT)
RETURNS (
    COLUMN_NUMBER INTEGER,
    COLUMN_VALUE INTEGER)
AS
BEGIN
    FOR SELECT CN.VAL, CC.VAL
        FROM LINKS L122
        JOIN VALI CN ON CN.OBJ_ID = L122.OBJ_ID AND CN.PARAM_ID = 750 /* and cn.is_del = 0 */
        LEFT JOIN VALI CC ON CC.OBJ_ID = L122.OBJ_ID AND CC.PARAM_ID = 1372 AND CC.IS_DEL = 0
        WHERE L122.PARENT_ID = :OBJ_ID
          AND L122.OBJ_TYPE_ID = 122
          AND L122.DATE_DEL IS NULL
        ORDER BY CN.VAL
        INTO :COLUMN_NUMBER, :COLUMN_VALUE
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GIA_SUBJECT_LIST (
    I$PARALLEL SMALLINT,
    I$USER_ID BIGINT = 1)
RETURNS (
    EXAM_SUBJECT_ID BIGINT,
    GIA_SUBJECT_ID BIGINT,
    GIA_SUBJECT_CAPTION VARCHAR(4000),
    GIA_SUBJECT_DESCRIPTION VARCHAR(4000))
AS
declare variable LANG_CODE varchar(2);
declare variable PARALLEL integer;
declare variable PARENT_ID bigint;
declare variable RES_ID bigint;
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :LANG_CODE;
        
    FOR
        SELECT LISTVAL_ID,
               RES_ID,
               IIF(TAG = 'FL', -19, TAG)
        FROM LISTVALS
        WHERE (
            ((:I$PARALLEL <> 9) AND ("FILTER" SIMILAR TO '%GRAD%')) OR
            ((:I$PARALLEL = 9) AND ("FILTER" SIMILAR TO '%9CLASS%'))
        )
        AND LIST_ID = 212
        AND IS_DEL = 0
        ORDER BY SORT_ORDER

        INTO :EXAM_SUBJECT_ID,
             :RES_ID,
             :GIA_SUBJECT_ID
    DO
    BEGIN
        SELECT VAL,
               VAL_LONG
        FROM RES_GET(:RES_ID, :LANG_CODE)
        INTO :GIA_SUBJECT_DESCRIPTION,
             :GIA_SUBJECT_CAPTION;
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GIA_TRANSFER_EXPORT (
    I$DT TIMESTAMP)
RETURNS (
    PARENT_ID BIGINT,
    EXAM_ID BIGINT,
    LINK_ID BIGINT,
    TYPE_ID BIGINT,
    DATE_ADD TIMESTAMP,
    DATE_MODIFY TIMESTAMP,
    DATE_DEL TIMESTAMP,
    EXAM_INDEX BIGINT,
    STAGE_ID BIGINT,
    EXAM_DATE DATE,
    SUBJECT_ID BIGINT,
    DAY_TYPE_ID BIGINT,
    EXPORT_DT TIMESTAMP,
    EXAM_YEAR BIGINT,
    EXAM_ST VARCHAR(1000),
    EXAM_ACC VARCHAR(1000),
    EXAM_FILE VARCHAR(1000))
AS
begin

  -- Годовые папки
  FOR
    SELECT L119.PARENT_ID, L119.OBJ_ID, L119.LINK_ID, L119.OBJ_TYPE_ID, L119.DATE_INS, L119.DATE_MODIFY, L119.DATE_DEL,
      V742.LISTVAL_ID, V1192.VAL, V1193.VAL, V2930.VAL
    FROM LINKS L119
    JOIN VALL V742 ON V742.OBJ_ID = L119.OBJ_ID AND V742.PARAM_ID = 742 AND V742.IS_DEL = 0
    LEFT JOIN VALS V1192 ON V1192.OBJ_ID = L119.OBJ_ID AND V1192.PARAM_ID = 1192 AND V1192.IS_DEL = 0
    LEFT JOIN VALS V1193 ON V1193.OBJ_ID = L119.OBJ_ID AND V1193.PARAM_ID = 1193 AND V1193.IS_DEL = 0
    LEFT JOIN VALS V2930 ON V2930.OBJ_ID = L119.OBJ_ID AND V2930.PARAM_ID = 2930 AND V2930.IS_DEL = 0
    WHERE L119.PARENT_ID = 3866 AND L119.OBJ_TYPE_ID = 119
    INTO :PARENT_ID, :EXAM_ID, :LINK_ID, :TYPE_ID, :DATE_ADD, :DATE_MODIFY, :DATE_DEL,
      :EXAM_YEAR, :EXAM_ST, :EXAM_ACC, :EXAM_FILE
  DO
  BEGIN
    SUSPEND;
  END

  -- Сами экзамены
  EXAM_YEAR = NULL;
  EXAM_ST = NULL;
  EXAM_ACC = NULL;
  EXAM_FILE = NULL;
  FOR
    SELECT L120.PARENT_ID, L120.OBJ_ID, L120.LINK_ID, L120.OBJ_TYPE_ID, L120.DATE_INS, L120.DATE_MODIFY, L120.DATE_DEL,
      V800.VAL, V801.LISTVAL_ID, V804.VAL, V803.LISTVAL_ID, V802.LISTVAL_ID, V2737.VAL
    FROM LINKS L120
    JOIN VALI V800 ON V800.OBJ_ID = L120.OBJ_ID AND V800.PARAM_ID = 800 AND V800.IS_DEL = 0
    JOIN VALL V801 ON V801.OBJ_ID = L120.OBJ_ID AND V801.PARAM_ID = 801 AND V801.IS_DEL = 0
    JOIN VALD V804 ON V804.OBJ_ID = L120.OBJ_ID AND V804.PARAM_ID = 804 AND V804.IS_DEL = 0
    JOIN VALL V803 ON V803.OBJ_ID = L120.OBJ_ID AND V803.PARAM_ID = 803 AND V803.IS_DEL = 0
    JOIN VALL V802 ON V802.OBJ_ID = L120.OBJ_ID AND V802.PARAM_ID = 802 AND V802.IS_DEL = 0
    LEFT JOIN VALDT V2737 ON V2737.OBJ_ID = L120.OBJ_ID AND V2737.PARAM_ID = 2737 AND V2737.IS_DEL = 0
    WHERE L120.PARENT_TYPE_ID = 119 AND L120.OBJ_TYPE_ID = 120 AND (L120.DATE_MODIFY >= :I$DT OR :I$DT IS NULL)
    INTO :PARENT_ID, :EXAM_ID, :LINK_ID, :TYPE_ID, :DATE_ADD, :DATE_MODIFY, :DATE_DEL,
      :EXAM_INDEX, :STAGE_ID, :EXAM_DATE, :SUBJECT_ID, :DAY_TYPE_ID, :EXPORT_DT
  DO
  BEGIN
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GIA_TRANSFER_IMPORT (
    I$PARENT_ID BIGINT,
    I$EXAM_ID BIGINT,
    I$LINK_ID BIGINT,
    I$TYPE_ID BIGINT,
    I$DATE_ADD TIMESTAMP,
    I$DATE_MODIFY TIMESTAMP,
    I$DATE_DEL TIMESTAMP,
    I$EXAM_INDEX BIGINT,
    I$STAGE_ID BIGINT,
    I$EXAM_DATE DATE,
    I$SUBJECT_ID BIGINT,
    I$DAY_TYPE_ID BIGINT,
    I$EXPORT_DT TIMESTAMP)
RETURNS (
    OBJ_ID BIGINT)
AS
begin

  OBJ_ID = I$EXAM_ID;
  IF(I$TYPE_ID <> 120) THEN EXCEPTION DATA_ERROR 'Недопустимый тип объекта ГИА';

  UPDATE OR INSERT INTO OBJECTS (OBJ_ID, TYPE_ID)
    VALUES (:I$EXAM_ID, :I$TYPE_ID);
  UPDATE OR INSERT INTO LINKS (LINK_ID, PARENT_ID, OBJ_ID, DATE_INS, DATE_MODIFY, DATE_DEL)
    VALUES (:I$LINK_ID, :I$PARENT_ID, :I$EXAM_ID, :I$DATE_ADD, :I$DATE_MODIFY, :I$DATE_DEL);
  UPDATE OR INSERT INTO VALI (OBJ_ID, PARAM_ID, VAL, IS_DEL)
    VALUES (:I$EXAM_ID, 800, :I$EXAM_INDEX, 0);
  UPDATE OR INSERT INTO VALL (OBJ_ID, PARAM_ID, LISTVAL_ID, IS_DEL)
    VALUES (:I$EXAM_ID, 801, :I$STAGE_ID, 0);
  UPDATE OR INSERT INTO VALD (OBJ_ID, PARAM_ID, VAL, IS_DEL)
    VALUES (:I$EXAM_ID, 804, :I$EXAM_DATE, 0);
  UPDATE OR INSERT INTO VALL (OBJ_ID, PARAM_ID, LISTVAL_ID, IS_DEL)
    VALUES (:I$EXAM_ID, 803, :I$SUBJECT_ID, 0);
  UPDATE OR INSERT INTO VALL (OBJ_ID, PARAM_ID, LISTVAL_ID, IS_DEL)
    VALUES (:I$EXAM_ID, 802, :I$DAY_TYPE_ID, 0);

  IF(I$EXPORT_DT IS NULL) THEN
  UPDATE VALDT SET IS_DEL = 1 WHERE OBJ_ID = :I$EXAM_ID AND PARAM_ID = 2737 AND IS_DEL = 0;
  ELSE
  UPDATE OR INSERT INTO VALDT (OBJ_ID, PARAM_ID, VAL, IS_DEL)
    VALUES (:I$EXAM_ID, 2737, :I$EXPORT_DT, 0);

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GIA_TRANSFER_IMPORT_FOLDER (
    I$PARENT_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$LINK_ID BIGINT,
    I$TYPE_ID BIGINT,
    I$DATE_ADD TIMESTAMP,
    I$DATE_MODIFY TIMESTAMP,
    I$DATE_DEL TIMESTAMP,
    I$YEAR_ID BIGINT,
    I$EXAM_ST VARCHAR(1000),
    I$EXAM_ACC VARCHAR(1000),
    I$EXAM_FILE VARCHAR(1000))
RETURNS (
    OBJ_ID BIGINT)
AS
begin

  OBJ_ID = I$OBJ_ID;
  IF(I$TYPE_ID <> 119) THEN EXCEPTION DATA_ERROR 'Недопустимый тип объекта ГИА';

  UPDATE OR INSERT INTO OBJECTS (OBJ_ID, TYPE_ID)
    VALUES (:I$OBJ_ID, :I$TYPE_ID);
  UPDATE OR INSERT INTO LINKS (LINK_ID, PARENT_ID, OBJ_ID, DATE_INS, DATE_MODIFY, DATE_DEL)
    VALUES (:I$LINK_ID, :I$PARENT_ID, :I$OBJ_ID, :I$DATE_ADD, :I$DATE_MODIFY, :I$DATE_DEL);
  UPDATE OR INSERT INTO VALL (OBJ_ID, PARAM_ID, LISTVAL_ID, IS_DEL)
    VALUES (:I$OBJ_ID, 742, :I$YEAR_ID, 0);

  IF(I$EXAM_ST IS NULL) THEN
  UPDATE VALS SET IS_DEL = 1 WHERE OBJ_ID = :I$OBJ_ID AND PARAM_ID = 1192 AND IS_DEL = 0;
  ELSE
  UPDATE OR INSERT INTO VALS (OBJ_ID, PARAM_ID, VAL, IS_DEL)
    VALUES (:I$OBJ_ID, 1192, :I$EXAM_ST, 0);

  IF(I$EXAM_ACC IS NULL) THEN
  UPDATE VALS SET IS_DEL = 1 WHERE OBJ_ID = :I$OBJ_ID AND PARAM_ID = 1193 AND IS_DEL = 0;
  ELSE
  UPDATE OR INSERT INTO VALS (OBJ_ID, PARAM_ID, VAL, IS_DEL)
    VALUES (:I$OBJ_ID, 1193, :I$EXAM_ACC, 0);

  IF(I$EXAM_FILE IS NULL) THEN
  UPDATE VALS SET IS_DEL = 1 WHERE OBJ_ID = :I$OBJ_ID AND PARAM_ID = 2930 AND IS_DEL = 0;
  ELSE
  UPDATE OR INSERT INTO VALS (OBJ_ID, PARAM_ID, VAL, IS_DEL)
    VALUES (:I$OBJ_ID, 2930, :I$EXAM_FILE, 0);

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GIA_WORKER_LIST RETURNS (
    OBJ_ID BIGINT,
    OBJ_CAPTION VARCHAR(4000),
    SORT_ORDER DOUBLE PRECISION)
AS
DECLARE VARIABLE SCHOOL_ID BIGINT;
BEGIN
    SELECT FIRST 1 L.OBJ_ID
    FROM LINKS L
    WHERE L.PARENT_ID IS NULL
      AND L.OBJ_TYPE_ID = 2
      AND L.DATE_DEL IS NULL
    INTO :SCHOOL_ID;

    FOR SELECT DISTINCT L.OBJ_ID
        FROM LINKS L
        WHERE L.PARENT_ID = :SCHOOL_ID
          AND L.OBJ_TYPE_ID = 14
          AND L.DATE_DEL IS NULL
        INTO :OBJ_ID
    DO
    BEGIN
        SELECT CAPTION, SORT_ORDER
        FROM OBJECT_CAPTION_GET(:OBJ_ID)
        INTO :OBJ_CAPTION, :SORT_ORDER;
        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GPD_ACCEPT_PUPIL_LIST (
    I$GROUP_ID BIGINT)
RETURNS (
    PUPIL_ID BIGINT,
    FIRSTNAME VARCHAR(255),
    MIDDLENAME VARCHAR(255),
    LASTNAME VARCHAR(255),
    CLASSNAME VARCHAR(255),
    GROUPNAME VARCHAR(1000))
AS
declare variable V$OBJ_ID bigint;
declare variable V$GROUP_TYPE bigint;
declare variable V$LICENCE_TYPE char(1);
declare variable V$S varchar(1000);
BEGIN

    SELECT STATUS FROM OU_LICENCE_TYPE
    INTO :V$LICENCE_TYPE;

    -- Получаем тип группы - ГПД или ВД, важно только для школ
    IF(V$LICENCE_TYPE = 'O') THEN
    BEGIN
        SELECT V.LISTVAL_ID
        FROM VALL V
        WHERE V.OBJ_ID = :I$GROUP_ID AND V.PARAM_ID = 369 AND V.IS_DEL = 0
        INTO :V$GROUP_TYPE;

        IF(V$GROUP_TYPE IS NULL) THEN EXCEPTION DATA_ERROR 'Не указан тип группы';
    END

    FOR
        SELECT L9.OBJ_ID, L10.OBJ_ID
        FROM LINKS L9
        JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        -- Скрываем учеников, которые уже числятся в этой группе
        LEFT JOIN LINKS L10_2 ON L10_2.PARENT_ID = :I$GROUP_ID AND L10_2.OBJ_ID = L10.OBJ_ID AND L10_2.DATE_DEL IS NULL
        WHERE L9.PARENT_ID = :I$GROUP_ID AND L9.DATE_DEL IS NULL AND L9.OBJ_TYPE_ID = 9 AND L10_2.LINK_ID IS NULL
        INTO :V$OBJ_ID, :PUPIL_ID
    DO
    BEGIN
        --
        IF(V$GROUP_TYPE = 1246) THEN
        BEGIN
            -- Формируем список ГПД, где ученик числится уже сейчас
            GROUPNAME = '';

            FOR
                SELECT V549.VAL
                FROM LINKS LP46
                JOIN VALL V369 ON V369.OBJ_ID = LP46.PARENT_ID AND V369.PARAM_ID = 369 AND V369.IS_DEL = 0 AND V369.LISTVAL_ID = :V$GROUP_TYPE
                JOIN VALS V549 ON V549.OBJ_ID = LP46.PARENT_ID AND V369.PARAM_ID = 369 AND V369.IS_DEL = 0
                WHERE LP46.OBJ_ID = :PUPIL_ID AND LP46.PARENT_TYPE_ID = 46 AND LP46.DATE_DEL IS NULL
                ORDER BY 1
                INTO :V$S
            DO
            BEGIN
                IF(CHAR_LENGTH(GROUPNAME) + CHAR_LENGTH(V$S) < 996) THEN
                BEGIN
                    IF(GROUPNAME <> '') THEN GROUPNAME = GROUPNAME || ', ';
                    GROUPNAME = GROUPNAME || V$S;
                END
            END

        END

        SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$OBJ_ID, 49) INTO :CLASSNAME;
        SELECT V FROM VAL_GET(:PUPIL_ID, 55) INTO :LASTNAME;
        SELECT V FROM VAL_GET(:PUPIL_ID, 56) INTO :FIRSTNAME;
        SELECT V FROM VAL_GET(:PUPIL_ID, 57) INTO :MIDDLENAME;
        SUSPEND;

    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GPD_MEMBERS_LIST (
    I$GPD_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    OBJ_ID BIGINT,
    CLASS_NAME VARCHAR(1000),
    NAME VARCHAR(1000),
    ACCEPT_DATE VARCHAR(20))
AS
declare variable V$DATE date;
begin

  FOR
    SELECT L10.OBJ_ID, CP.CAPTION, CS.CAPTION, M.DATE_IN
    FROM LINKS L9
    JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    JOIN PERSON_MOVEMENTS M ON M.DATE_DEL IS NULL AND M.PERSON_ID = L10.OBJ_ID AND M.GROUP_ID = L10.PARENT_ID AND M.DATE_OUT IS NULL
    LEFT JOIN LINKS LP46 ON LP46.OBJ_ID = L10.OBJ_ID AND LP46.PARENT_ID = :I$GPD_ID AND LP46.DATE_DEL IS NULL
    LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) CP ON 1 = 1
    LEFT JOIN OBJECT_CAPTION_GET(L10.OBJ_ID, 23) CS ON 1 = 1
    WHERE L9.PARENT_ID = :I$GPD_ID AND L9.OBJ_TYPE_ID IN (9, 187) AND L9.DATE_DEL IS NULL AND LP46.LINK_ID IS NULL
    ORDER BY 2, 3
    INTO :OBJ_ID, :CLASS_NAME, :NAME, :V$DATE
  DO
  BEGIN
    ACCEPT_DATE = (SELECT VAL FROM DATE2ISO(:V$DATE, 0));
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GPD_PARENT_SCHOLAR_LIST (
    I$GPD_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    PAR_OBJ_ID BIGINT,
    FIO VARCHAR(4000),
    PAR_WORK VARCHAR(1000),
    PAR_ADRES VARCHAR(1000))
AS
DECLARE VARIABLE TMP VARCHAR(500);
BEGIN
 -- NUM = 0;
  FOR SELECT L10.OBJ_ID, L20.OBJ_ID
      FROM LINKS L10
      JOIN LINKS L20 ON (L20.PARENT_ID = L10.OBJ_ID AND L20.DATE_DEL IS NULL AND L20.OBJ_TYPE_ID = 20)
      WHERE L10.PARENT_ID = :I$GPD_ID AND
            L10.OBJ_TYPE_ID = 10 AND
            L10.DATE_DEL IS NULL
      INTO :OBJ_ID, :PAR_OBJ_ID
  DO
  BEGIN
  --  NUM = :NUM + 1;
    SELECT C1
    FROM BUILD_REP_FIO(:PAR_OBJ_ID, 128, 129, 130)
    INTO :FIO;

    SELECT V
    FROM VAL_GET(:PAR_OBJ_ID, 139)
    INTO :PAR_WORK;

    SELECT V
    FROM VAL_GET(:PAR_OBJ_ID, 140)
    INTO :TMP;

    IF (NOT :TMP = '') THEN
    BEGIN
      PAR_WORK = :PAR_WORK || ', ' || :TMP;
    END

    SELECT V
    FROM VAL_GET(:PAR_OBJ_ID, 141)
    INTO :TMP;

    IF (NOT :TMP = '') THEN
    BEGIN
      PAR_WORK = :PAR_WORK || ', ' || :TMP;
    END

    SELECT VAL
    FROM ADR_GET(147, :PAR_OBJ_ID)
    INTO :PAR_ADRES;

    IF ((:PAR_ADRES IS NULL) OR (:PAR_ADRES = '')) THEN
    BEGIN
      SELECT I
      FROM VAL_GET(:PAR_OBJ_ID, 149)
      INTO :TMP;
      IF (:TMP = 2) THEN
      BEGIN
        SELECT VAL
        FROM ADR_GET(103, :OBJ_ID)
        INTO :PAR_ADRES;

        SELECT V
        FROM VAL_GET(:OBJ_ID, 102)
        INTO :TMP;

        IF (NOT :TMP = '') THEN
        BEGIN
          PAR_ADRES = :PAR_ADRES || ', ' || :TMP;
        END
      END
    END
    ELSE
    BEGIN
      SELECT V
      FROM VAL_GET(:PAR_OBJ_ID, 145)
      INTO :TMP;

      IF (NOT :TMP = '') THEN
      BEGIN
        PAR_ADRES = :PAR_ADRES || ', ' || :TMP;
      END
    END
    SUSPEND;
  END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GPD_PLAN_AUTHORS_LIST RETURNS (
    OBJ_ID BIGINT,
    OBJ_CAPTION VARCHAR(4000))
AS
declare variable V$SCHOOL_ID bigint;
declare variable V$VACANCY_ID bigint;
declare variable V$VACANCY_TYPE_ID bigint;
declare variable V$HAVE_TEACHERSVACANCY smallint;
BEGIN
    FOR
        SELECT L2.OBJ_ID
        FROM LINKS L2
        WHERE L2.PARENT_ID IS NULL
        AND L2.OBJ_TYPE_ID = 2
        AND L2.DATE_DEL IS NULL
        INTO :V$SCHOOL_ID
    DO
    BEGIN
        FOR
            SELECT L14.OBJ_ID
            FROM LINKS L14
            WHERE L14.OBJ_TYPE_ID = 14
            AND L14.PARENT_ID IN (
                SELECT :V$SCHOOL_ID
                FROM RDB$DATABASE
                UNION
                -- for UDOD
                SELECT L211.OBJ_ID
                FROM LINKS L211
                WHERE L211.PARENT_ID = :V$SCHOOL_ID
                  AND L211.OBJ_TYPE_ID = 211
                  AND L211.DATE_DEL IS NULL)
            AND L14.DATE_DEL IS NULL
            INTO :OBJ_ID
        DO
        BEGIN
            SELECT X FROM IS_TEACHER(:OBJ_ID) INTO :V$HAVE_TEACHERSVACANCY;
            IF (V$HAVE_TEACHERSVACANCY = 1) THEN
            BEGIN
                FOR
                    SELECT CAPTION
                    FROM OBJECT_CAPTION_GET(:OBJ_ID)
                    INTO :OBJ_CAPTION
                DO
                BEGIN
                    SUSPEND;
                END
            END
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GPD_REPORT_PARENT_SCHOLAR (
    I$GPD_ID BIGINT)
RETURNS (
    FIO VARCHAR(4000),
    PAR_WORK VARCHAR(1000),
    PAR_ADRES VARCHAR(1000),
    CHILD_FIO VARCHAR(1000))
AS
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$PAR_OBJ_ID BIGINT;
DECLARE VARIABLE V$TMP VARCHAR(500);
BEGIN
 -- NUM = 0;
  FOR SELECT L10.OBJ_ID, L20.OBJ_ID
      FROM LINKS L10
      JOIN LINKS L20 ON (L20.PARENT_ID = L10.OBJ_ID AND L20.DATE_DEL IS NULL AND L20.OBJ_TYPE_ID = 20)
      WHERE L10.PARENT_ID = :I$GPD_ID AND
            L10.OBJ_TYPE_ID = 10 AND
            L10.DATE_DEL IS NULL
      INTO :V$OBJ_ID, :V$PAR_OBJ_ID
  DO
  BEGIN
  --  NUM = :NUM + 1;
    SELECT C1
    FROM BUILD_REP_FIO(:V$OBJ_ID, 55, 56, 57)
    INTO :CHILD_FIO;

    SELECT C1
    FROM BUILD_REP_FIO(:V$PAR_OBJ_ID, 128, 129, 130)
    INTO :FIO;

    SELECT V
    FROM VAL_GET(:V$PAR_OBJ_ID, 139)
    INTO :PAR_WORK;

    SELECT V
    FROM VAL_GET(:V$PAR_OBJ_ID, 140)
    INTO :V$TMP;

    IF (NOT :V$TMP = '') THEN
    BEGIN
      PAR_WORK = :PAR_WORK || ', ' || :V$TMP;
    END

    SELECT V
    FROM VAL_GET(:V$PAR_OBJ_ID, 141)
    INTO :V$TMP;

    IF (NOT :V$TMP = '') THEN
    BEGIN
      PAR_WORK = :PAR_WORK || ', ' || :V$TMP;
    END

    SELECT VAL
    FROM ADR_GET(147, :V$PAR_OBJ_ID)
    INTO :PAR_ADRES;

    IF ((:PAR_ADRES IS NULL) OR (:PAR_ADRES = '')) THEN
    BEGIN
      SELECT I
      FROM VAL_GET(:V$PAR_OBJ_ID, 149)
      INTO :V$TMP;
      IF (:V$TMP = 2) THEN
      BEGIN
        SELECT VAL
        FROM ADR_GET(103, :V$OBJ_ID)
        INTO :PAR_ADRES;

        SELECT V
        FROM VAL_GET(:V$OBJ_ID, 102)
        INTO :V$TMP;

        IF (NOT :V$TMP = '') THEN
        BEGIN
          PAR_ADRES = :PAR_ADRES || ', ' || :V$TMP;
        END
      END
    END
    ELSE
    BEGIN
      SELECT V
      FROM VAL_GET(:V$PAR_OBJ_ID, 145)
      INTO :V$TMP;

      IF (NOT :V$TMP = '') THEN
      BEGIN
        PAR_ADRES = :PAR_ADRES || ', ' || :V$TMP;
      END
    END
    SUSPEND;
  END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GPD_REPORT_SCHOLAR_HEALTH (
    I$GPD_ID BIGINT)
RETURNS (
    SCHOLAR_CAPTION VARCHAR(1000),
    STATE_HEALTH VARCHAR(4000),
    HEALTH_GROUP VARCHAR(100))
AS
declare variable V$OBJ_ID bigint;
declare variable V$C1 varchar(500);
declare variable V$HEALTH bigint;
BEGIN
  -- NUM = 0;
  FOR SELECT L10.OBJ_ID
      FROM LINKS L10
      WHERE L10.PARENT_ID = :I$GPD_ID AND
            L10.OBJ_TYPE_ID = 10 AND
            L10.DATE_DEL IS NULL
            --   GROUP BY L10.OBJ_ID
      INTO :V$OBJ_ID
  DO
  BEGIN
    --  NUM = :NUM + 1;
    V$HEALTH = NULL;
    SELECT F || ' ' || I
    FROM BUILD_REP_FIO(:V$OBJ_ID, 55, 56, 57)
    INTO :SCHOLAR_CAPTION;

    SELECT COUNT(L30.OBJ_ID)
    FROM LINKS L30
    WHERE L30.PARENT_ID = :V$OBJ_ID AND
          L30.OBJ_TYPE_ID = 30 AND
          L30.DATE_DEL IS NULL
    INTO :V$HEALTH;

    IF (:V$HEALTH = 0) THEN
    BEGIN
      STATE_HEALTH = 'Здоров/а';
      HEALTH_GROUP = '';
    END
    ELSE
    BEGIN
      STATE_HEALTH = '';
      HEALTH_GROUP = '';
      FOR SELECT L30.OBJ_ID
          FROM LINKS L30
          INNER JOIN VALD DT ON DT.OBJ_ID = L30.OBJ_ID
          WHERE L30.PARENT_ID = :V$OBJ_ID AND
                L30.OBJ_TYPE_ID = 30 AND
                L30.DATE_DEL IS NULL AND
                DT.PARAM_ID = 209 AND
                DT.IS_DEL = 0
          ORDER BY DT.VAL
          INTO :V$HEALTH
      DO
      BEGIN

        SELECT
               CASE
                 WHEN CHAR_LENGTH(TRIM(V)) > 0 THEN TRIM(V)
                 ELSE ''
               END
        FROM VAL_GET(:V$HEALTH, 210)
        INTO :V$C1;
        IF (:V$C1 != '') THEN
        BEGIN
          IF (:STATE_HEALTH = '') THEN
          BEGIN
            STATE_HEALTH = :V$C1;
          END
          ELSE
          BEGIN
            STATE_HEALTH = :STATE_HEALTH || ', ' || :V$C1;
          END
        END
      END
      SELECT
             CASE
               WHEN CHAR_LENGTH(TRIM(V)) > 0 THEN TRIM(V)
               ELSE ''
             END
      FROM VAL_GET(:V$HEALTH, 211)
      INTO :HEALTH_GROUP;
    END
    SUSPEND;
  END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GPD_REPORT_SCHOLAR_LIST (
    I$GPD_ID BIGINT)
RETURNS (
    SCHOLAR_CAPTION VARCHAR(1000),
    BIRTHDAY DATE,
    FORMNUM VARCHAR(10),
    PRCHORG VARCHAR(1000),
    ADDRES VARCHAR(2000),
    DATEB DATE,
    DATEN DATE,
    SORT_ORDER INTEGER)
AS
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$Y SMALLINT;
DECLARE VARIABLE V$DT DATE;
DECLARE VARIABLE V$DT_TO DATE;
DECLARE VARIABLE V$DATE_DEL DATE;
BEGIN
  V$Y = EXTRACT(YEAR FROM CURRENT_DATE);
  V$DT = '31.08.' || V$Y;

  IF (CURRENT_DATE < V$DT) THEN
  BEGIN
    V$DT_TO = V$DT;
    V$DT = '01.09.' ||(V$Y - 1);
  END
  ELSE
  BEGIN
    V$DT = '01.09.' || V$Y;
    V$DT_TO = '31.08.' ||(V$Y + 1);
  END

  -- NUM = 0;
  FOR SELECT L10.OBJ_ID, MAX(L10.COST), MAX(L10.DATE_DEL)
      FROM LINKS L10
      WHERE L10.PARENT_ID = :I$GPD_ID AND
            L10.OBJ_TYPE_ID = 10
            --  AND ((L10.DATE_DEL IS NULL ) or ((L10.DATE_DEL >= :DT) and (L10.DATE_DEL <= :DT_TO)))
      GROUP BY L10.OBJ_ID
      INTO :V$OBJ_ID, :SORT_ORDER, V$DATE_DEL
  DO
  BEGIN
    --  NUM = :NUM + 1;
    SELECT F || ' ' || I
    FROM BUILD_REP_FIO(:V$OBJ_ID, 55, 56, 57)
    INTO :SCHOLAR_CAPTION;

    SELECT D
    FROM VAL_GET(:V$OBJ_ID, 89)
    INTO :BIRTHDAY;
    SELECT V
    FROM VAL_GET(:V$OBJ_ID, 1590)
    INTO :FORMNUM;
    PRCHORG = NULL;
    SELECT VAL
    FROM ADR_GET(103, :V$OBJ_ID)
    INTO :ADDRES;

    SELECT MIN(DT.VAL)
    FROM LINKS L178
    INNER JOIN VALL VLL ON VLL.OBJ_ID = L178.OBJ_ID
    INNER JOIN VALD DT ON DT.OBJ_ID = L178.OBJ_ID
    WHERE L178.PARENT_ID = :V$OBJ_ID AND
          L178.OBJ_TYPE_ID = 178 AND
          L178.DATE_DEL IS NULL AND
          VLL.PARAM_ID = 1584 AND
          VLL.IS_DEL = 0 AND
          VLL.LISTVAL_ID = 3322 AND
          DT.PARAM_ID = 1585 AND
          DT.IS_DEL = 0
    INTO :DATEB;

    SELECT MAX(DT.VAL)
    FROM LINKS L178
    INNER JOIN VALL VLL ON VLL.OBJ_ID = L178.OBJ_ID
    INNER JOIN VALD DT ON DT.OBJ_ID = L178.OBJ_ID
    WHERE L178.PARENT_ID = :V$OBJ_ID AND
          L178.OBJ_TYPE_ID = 178 AND
          L178.DATE_DEL IS NULL AND
          VLL.PARAM_ID = 1584 AND
          VLL.IS_DEL = 0 AND
          VLL.LISTVAL_ID = 3323 AND
          DT.PARAM_ID = 1585 AND
          DT.IS_DEL = 0
    INTO :DATEN;

    IF (((:V$DATE_DEL IS NULL) AND
        (:DATEN IS NULL)) OR ((NOT :V$DATE_DEL IS NULL) AND
        (DATEN >= :V$DT) AND
        (DATEN <= :V$DT_TO))) THEN
    BEGIN
      SUSPEND;
    END
  END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GPD_SUBJECTS_LIST (
    I$USER_ID BIGINT)
RETURNS (
    SUBJECT_ID BIGINT,
    SUBJECT_NAME VARCHAR(1000),
    SORT_ORDER DOUBLE PRECISION)
AS
BEGIN
    FOR
        SELECT DISTINCT L51.OBJ_ID
        FROM LINKS L2
        JOIN LINKS L69 ON L69.PARENT_ID = L2.OBJ_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL
        JOIN VALL V2450 ON V2450.OBJ_ID = L69.OBJ_ID AND V2450.PARAM_ID = 2450 AND V2450.IS_DEL = 0 AND V2450.LISTVAL_ID = 11385
        JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
        JOIN LINKS L50 ON L50.PARENT_ID = L57.OBJ_ID AND L50.OBJ_TYPE_ID = 50 AND L50.DATE_DEL IS NULL
        JOIN VALL V2545 ON V2545.OBJ_ID = L50.OBJ_ID AND V2545.PARAM_ID = 2545 AND V2545.IS_DEL = 0 AND V2545.LISTVAL_ID = 2
        JOIN LINKS L49 ON L49.PARENT_ID = L50.OBJ_ID AND L49.OBJ_TYPE_ID = 49 AND L49.DATE_DEL IS NULL
        JOIN LINKS L51 ON L51.PARENT_ID = L49.OBJ_ID AND L51.OBJ_TYPE_ID = 51 AND L51.DATE_DEL IS NULL
        WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
        INTO :SUBJECT_ID
    DO
    BEGIN
        SELECT CAPTION, SORT_ORDER
        FROM OBJECT_CAPTION_GET(:SUBJECT_ID, NULL, NULL, :I$USER_ID)
        INTO :SUBJECT_NAME, :SORT_ORDER;

        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GPD_TRANSFER_PUPIL (
    I$PUPIL_ID BIGINT,
    I$OLD_GPD_ID BIGINT,
    I$GPD_ID BIGINT,
    I$ORDER_NUMBER VARCHAR(100),
    I$ORDER_DATE DATE,
    I$ACTION_DATE DATE,
    I$REASON BIGINT,
    I$USER_ID BIGINT)
AS
declare variable V$BLOB_ID bigint;
BEGIN

  SELECT OBJ_ID FROM VARGRP_MOVE_PUPIL(:I$PUPIL_ID, :I$OLD_GPD_ID, :I$ORDER_NUMBER, :I$ORDER_DATE, :I$ACTION_DATE, 1, :I$USER_ID, 5545, :I$REASON) INTO :V$BLOB_ID;
  SELECT OBJ_ID FROM VARGRP_MOVE_PUPIL(:I$PUPIL_ID, :I$GPD_ID, :I$ORDER_NUMBER, :I$ORDER_DATE, :I$ACTION_DATE, 0, :I$USER_ID, 5545, :I$REASON) INTO :V$BLOB_ID;

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GRADES_SCHOOLARS_LIST (
    I$GRADE_ID BIGINT,
    I$USER_ID BIGINT,
    I$IN_CURRICULUM_GROUP_FL SMALLINT = null)
RETURNS (
    PARENT_ID BIGINT,
    TREE_PARENT_ID VARCHAR(255),
    OBJ_ID BIGINT,
    TREE_OBJ_ID VARCHAR(255),
    TYPE_ID BIGINT,
    OBJ_CAPTION VARCHAR(4000),
    COLOR INTEGER,
    SORT_ORDER VARCHAR(4000))
AS
declare variable V$I bigint;
declare variable V$TREE_PARENT_ID varchar(255);
declare variable V$OBJ_ID bigint;
declare variable V$SORT_ORDER varchar(4000);
declare variable V$SORT_ORDER_47 varchar(4000);
declare variable V$SORT_ORDER_48 varchar(4000);
declare variable V$PLAN_VD bigint;
declare variable V$PLAN_ID bigint;
BEGIN
    -- Получаем тип УП - обычный или ВД. По-умолчанию считаем что обычный
    SELECT LP57.PARENT_ID, V2545.LISTVAL_ID
    FROM LINKS LP50
    JOIN LINKS LP57 ON LP57.OBJ_ID = LP50.PARENT_ID AND LP57.PARENT_TYPE_ID = 57 AND LP57.DATE_DEL IS NULL
    JOIN VALL V2545 ON V2545.OBJ_ID = LP50.PARENT_ID AND V2545.PARAM_ID = 2545 AND V2545.IS_DEL = 0
    WHERE LP50.OBJ_ID = :I$GRADE_ID AND LP50.PARENT_TYPE_ID = 50 AND LP50.DATE_DEL IS NULL
    INTO :V$PLAN_ID, :V$PLAN_VD;

    IF(V$PLAN_VD IS NULL) THEN V$PLAN_VD = 3;

    IF (COALESCE(:I$IN_CURRICULUM_GROUP_FL, 0) = 0) THEN
    BEGIN
        -- Список учеников для выбора
        FOR
            -- Список классов указанной в этапе параллели (в случае ВД разрешаем выбор из любых параллелей, но в пределах одного уровня образования)
            SELECT DISTINCT L9.OBJ_ID
            FROM VALL V381
            -- Уровень образования для ОП
            JOIN LINKS LP50 ON LP50.OBJ_ID = V381.OBJ_ID AND LP50.PARENT_TYPE_ID = 50 AND LP50.DATE_DEL IS NULL
            JOIN LINKS LP57 ON LP57.OBJ_ID = LP50.PARENT_ID AND LP57.PARENT_TYPE_ID = 57 AND LP57.DATE_DEL IS NULL
            JOIN VALL V1594 ON V1594.OBJ_ID = LP57.PARENT_ID AND V1594.PARAM_ID = 1594 AND V1594.IS_DEL = 0
            JOIN LISTVALS L254 ON L254.LISTVAL_ID = V1594.LISTVAL_ID
            -- Учебные коллективы
            JOIN VALL V49 ON V49.LISTVAL_ID = V381.LISTVAL_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
            JOIN LINKS L9 ON L9.PARENT_ID = V49.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 187) AND L9.DATE_DEL IS NULL -- 8 => 9
            JOIN LINKS L8 ON L8.OBJ_ID = L9.PARENT_ID AND L8.PARENT_TYPE_ID = 7 AND L8.DATE_DEL IS NULL -- 7 => 8
            -- Уровень образования
            JOIN VALL V43 ON V43.OBJ_ID = L8.PARENT_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0
            JOIN LISTVALS L19 ON L19.LISTVAL_ID = V43.LISTVAL_ID
            WHERE V381.PARAM_ID = 381 AND V381.IS_DEL = 0 AND (V381.OBJ_ID = :I$GRADE_ID OR (:V$PLAN_VD = 2 AND LP57.PARENT_ID = :V$PLAN_ID AND L19.TAG = L254.TAG))
            INTO :OBJ_ID
        DO
        BEGIN
            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:OBJ_ID, 50, NULL, :I$USER_ID)
            INTO :V$SORT_ORDER;
            V$OBJ_ID = :OBJ_ID;
            V$I = 0;

            FOR
                SELECT L10.PARENT_ID, L10.PARENT_ID, L10.OBJ_ID, L10.OBJ_ID, L10.OBJ_TYPE_ID
                FROM LINKS L10
                WHERE L10.PARENT_ID = :V$OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL AND (
                    (:I$IN_CURRICULUM_GROUP_FL IS NULL)
                        -- Исключаем из списка уже входящих в ГУП (при этом внеурочку разрешаем многократно выбирать)
                        OR L10.OBJ_ID NOT IN (
                        SELECT L10.OBJ_ID
                        FROM LINKS L256
                        JOIN LINKS LP54 ON LP54.OBJ_ID = L256.OBJ_ID AND LP54.PARENT_TYPE_ID = 54 AND LP54.DATE_DEL IS NULL
                        JOIN LINKS LP50 ON LP50.OBJ_ID = LP54.PARENT_ID AND LP50.PARENT_TYPE_ID = 50 AND LP50.DATE_DEL IS NULL
                        JOIN VALL V2545 ON V2545.OBJ_ID = LP50.PARENT_ID AND V2545.PARAM_ID = 2545 AND V2545.IS_DEL = 0 AND V2545.LISTVAL_ID = 2
                        JOIN LINKS L10 ON L10.PARENT_ID = L256.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
                        JOIN LINKS L54 ON L256.PARENT_ID = L54.OBJ_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
                        WHERE L256.OBJ_TYPE_ID = 256 AND L256.DATE_DEL IS NULL AND L256.PARENT_ID = :I$GRADE_ID
                    )
                )
                INTO :PARENT_ID, :TREE_PARENT_ID, :OBJ_ID, :TREE_OBJ_ID, :TYPE_ID
            DO
            BEGIN
                V$I = 1;
                SELECT CAPTION, COLOR, :V$SORT_ORDER || '  ' ||CAPTION
                FROM OBJECT_CAPTION_GET(:OBJ_ID, 50, NULL, :I$USER_ID)
                INTO :OBJ_CAPTION, :COLOR, :SORT_ORDER;
                SUSPEND;
            END

            IF (V$I = 1) THEN
            BEGIN
                PARENT_ID = NULL;
                TREE_PARENT_ID = NULL;
                OBJ_ID = :V$OBJ_ID;
                TREE_OBJ_ID = :V$OBJ_ID;
                TYPE_ID = 9;

                SELECT CAPTION, COLOR, :V$SORT_ORDER
                FROM OBJECT_CAPTION_GET(:OBJ_ID, 50, NULL, :I$USER_ID)
                INTO :OBJ_CAPTION, :COLOR, :SORT_ORDER;
                SUSPEND;
            END
        END
    END
    ELSE
    BEGIN
        -- Список уже добавленных учеников
        FOR
            SELECT L256.PARENT_ID, L256.PARENT_ID, L256.OBJ_ID, L256.OBJ_ID, L256.OBJ_TYPE_ID
            FROM LINKS L256
            JOIN LINKS LP54 ON LP54.OBJ_ID = L256.OBJ_ID AND LP54.PARENT_TYPE_ID = 54 AND LP54.DATE_DEL IS NULL
            JOIN LINKS LP50 ON LP50.OBJ_ID = LP54.PARENT_ID AND LP50.PARENT_TYPE_ID = 50 AND LP50.DATE_DEL IS NULL
            -- не до конца понятно, почему здесь фильтр именно по внеурочке ???
            JOIN VALL V2545 ON V2545.OBJ_ID = LP50.PARENT_ID AND V2545.PARAM_ID = 2545 AND V2545.IS_DEL = 0 AND V2545.LISTVAL_ID = 2
            WHERE L256.PARENT_ID = :I$GRADE_ID AND L256.OBJ_TYPE_ID = 256 AND L256.DATE_DEL IS NULL
            INTO :PARENT_ID, :TREE_PARENT_ID, :OBJ_ID, :TREE_OBJ_ID, :TYPE_ID
        DO
        BEGIN
            V$OBJ_ID = :OBJ_ID;
            SELECT CAPTION, COLOR, CAPTION, CAPTION
            FROM OBJECT_CAPTION_GET(:OBJ_ID, NULL, NULL, :I$USER_ID)
            INTO :OBJ_CAPTION, :COLOR, :SORT_ORDER, :V$SORT_ORDER;
            SUSPEND;

            V$TREE_PARENT_ID = '0';
            FOR
                SELECT :V$OBJ_ID, L10_9.PARENT_ID, L10_9.OBJ_ID, L10_9.OBJ_ID, L10_9.OBJ_TYPE_ID
                FROM LINKS L10
                JOIN LINKS L10_9 ON L10_9.OBJ_ID = L10.OBJ_ID AND L10_9.OBJ_TYPE_ID = 10 AND L10_9.PARENT_TYPE_ID IN (9, 187) AND L10_9.DATE_DEL IS NULL
                WHERE L10.PARENT_ID = :V$OBJ_ID AND L10.OBJ_TYPE_ID+0 = 10 AND L10.DATE_DEL IS NULL
                ORDER BY L10_9.PARENT_ID
                INTO :PARENT_ID, :V$I, :OBJ_ID, :TREE_OBJ_ID, :TYPE_ID
            DO
            BEGIN
                TREE_PARENT_ID = :V$OBJ_ID || '_' || :V$I;

                SELECT :V$SORT_ORDER || '  ' || CAPTION
                FROM OBJECT_CAPTION_GET(:V$I, 50, NULL, :I$USER_ID)
                INTO :SORT_ORDER;

                SELECT CAPTION, COLOR, :SORT_ORDER || '  ' || CAPTION
                FROM OBJECT_CAPTION_GET(:OBJ_ID, 50, NULL, :I$USER_ID)
                INTO :OBJ_CAPTION, :COLOR, :SORT_ORDER;
                SUSPEND;

                IF (:TREE_PARENT_ID <> :V$TREE_PARENT_ID) THEN
                BEGIN
                    V$TREE_PARENT_ID = :TREE_PARENT_ID;
                    OBJ_ID = :V$I;
                    TREE_OBJ_ID = :TREE_PARENT_ID;
                    TREE_PARENT_ID = :V$OBJ_ID;
                    TYPE_ID = 9;

                    SELECT CAPTION, COLOR, :V$SORT_ORDER || '  ' || CAPTION
                    FROM OBJECT_CAPTION_GET(:OBJ_ID, 50, NULL, :I$USER_ID)
                    INTO :OBJ_CAPTION, :COLOR, :SORT_ORDER;
                    SUSPEND;
                END
                ELSE
                BEGIN
                    V$TREE_PARENT_ID = :TREE_PARENT_ID;
                END
            END
            -- Подгруппы
            FOR
                SELECT L47.PARENT_ID, L47.PARENT_ID, L47.OBJ_ID, L47.OBJ_ID, L47.OBJ_TYPE_ID
                FROM LINKS L47
                WHERE L47.PARENT_ID = :V$OBJ_ID AND L47.OBJ_TYPE_ID = 47 AND L47.DATE_DEL IS NULL
                INTO :PARENT_ID, :TREE_PARENT_ID, :OBJ_ID, :TREE_OBJ_ID, :TYPE_ID
            DO
            BEGIN
                V$I = :OBJ_ID;

                SELECT CAPTION, COLOR, :V$SORT_ORDER || '  ' || 'ЯЯЯ' || CAPTION
                FROM OBJECT_CAPTION_GET(:OBJ_ID, NULL, NULL, :I$USER_ID)
                INTO :OBJ_CAPTION, :COLOR, :SORT_ORDER;

                V$SORT_ORDER_47 = :SORT_ORDER;
                SUSPEND;

                FOR
                    SELECT L48.PARENT_ID, L48.PARENT_ID, L48.OBJ_ID, L48.OBJ_ID, L48.OBJ_TYPE_ID
                    FROM LINKS L48
                    WHERE L48.PARENT_ID = :V$I AND L48.OBJ_TYPE_ID = 48 AND L48.DATE_DEL IS NULL
                    INTO :PARENT_ID, :TREE_PARENT_ID, :OBJ_ID, :TREE_OBJ_ID, :TYPE_ID
                DO
                BEGIN
                    SELECT CAPTION, COLOR, :V$SORT_ORDER_47 || '  ' || CAPTION
                    FROM OBJECT_CAPTION_GET(:OBJ_ID, NULL, NULL, :I$USER_ID)
                    INTO :OBJ_CAPTION, :COLOR, :SORT_ORDER;

                    V$SORT_ORDER_48 = :SORT_ORDER;
                    SUSPEND;

                    FOR
                        SELECT PARENT_ID, TREE_PARENT_ID, OBJ_ID, TREE_OBJ_ID, TYPE_ID, OBJ_CAPTION, COLOR, :V$SORT_ORDER_48 || '  ' || SORT_ORDER
                        FROM SUBGROUP_SCHOOLARS_LIST(:OBJ_ID, :I$USER_ID, 1)
                        INTO :PARENT_ID, :TREE_PARENT_ID, :OBJ_ID, :TREE_OBJ_ID, :TYPE_ID, :OBJ_CAPTION, :COLOR, :SORT_ORDER
                    DO
                    BEGIN
                        SUSPEND;
                    END
                END
            END
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GRADE_SCHOOLARS_LIST (
    I$GRADE_ID BIGINT,
    I$USER_ID BIGINT,
    I$IN_CURRICULUM_GROUP_FL SMALLINT = null)
RETURNS (
    PARENT_ID BIGINT,
    TREE_PARENT_ID VARCHAR(255),
    OBJ_ID BIGINT,
    TREE_OBJ_ID VARCHAR(255),
    TYPE_ID BIGINT,
    OBJ_CAPTION VARCHAR(4000),
    COLOR INTEGER,
    SORT_ORDER VARCHAR(4000))
AS
declare variable V$I bigint;
declare variable V$TREE_PARENT_ID varchar(255);
declare variable V$OBJ_ID bigint;
declare variable V$SORT_ORDER varchar(4000);
declare variable V$SORT_ORDER_47 varchar(4000);
declare variable V$SORT_ORDER_48 varchar(4000);
BEGIN
    IF (COALESCE(:I$IN_CURRICULUM_GROUP_FL, 0) = 0) THEN
    BEGIN
        -- Список учеников, не входящих в ГУП (обычный УП)
        -- Уровень образования берем в расширенном смысле для детей с ОВЗ
        FOR
            SELECT L9.OBJ_ID
            FROM VALL V381
            JOIN LISTVALS LV1 ON LV1.LISTVAL_ID = V381.LISTVAL_ID
            JOIN LISTVALS LV2 ON LV2.LIST_ID = LV1.LIST_ID AND LV2.COST = LV1.COST
            JOIN VALL V49 ON V49.PARAM_ID = 49 AND V49.IS_DEL = 0 AND V49.LISTVAL_ID = LV2.LIST_ID
            JOIN LINKS L9 ON L9.PARENT_ID = V49.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 187) AND L9.DATE_DEL IS NULL
            WHERE V381.OBJ_ID = :I$GRADE_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
            INTO :OBJ_ID
        DO
        BEGIN
            SELECT CAPTION FROM OBJECT_CAPTION_GET(:OBJ_ID, 50, NULL, :I$USER_ID) INTO :V$SORT_ORDER;

            V$OBJ_ID = :OBJ_ID;
            V$I = 0;

            FOR
                SELECT L10.PARENT_ID, L10.PARENT_ID, L10.OBJ_ID, L10.OBJ_ID, L10.OBJ_TYPE_ID
                FROM LINKS L10
                WHERE L10.PARENT_ID = :V$OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
                AND (:I$IN_CURRICULUM_GROUP_FL IS NULL OR L10.OBJ_ID NOT IN (
                    SELECT L10.OBJ_ID
                    FROM LINKS L256
                    JOIN LINKS LP54 ON LP54.OBJ_ID = L256.OBJ_ID AND LP54.PARENT_TYPE_ID = 54 AND LP54.DATE_DEL IS NULL
                    JOIN LINKS LP50 ON LP50.OBJ_ID = LP54.PARENT_ID AND LP50.PARENT_TYPE_ID = 50 AND LP50.DATE_DEL IS NULL
                    LEFT JOIN VALL V2545 ON V2545.OBJ_ID = LP50.PARENT_ID AND V2545.PARAM_ID = 2545 AND V2545.IS_DEL = 0
                    JOIN LINKS L10 ON L10.PARENT_ID = L256.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
                    JOIN LINKS L54 ON L256.PARENT_ID = L54.OBJ_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
                    WHERE L256.OBJ_TYPE_ID = 256 AND L256.DATE_DEL IS NULL AND ((V2545.LISTVAL_ID IS NULL) OR (V2545.LISTVAL_ID = 3))
                ))
                INTO :PARENT_ID, :TREE_PARENT_ID, :OBJ_ID, :TREE_OBJ_ID, :TYPE_ID
            DO
            BEGIN
                V$I = 1;

                SELECT CAPTION, COLOR, :V$SORT_ORDER || '  ' || CAPTION
                FROM OBJECT_CAPTION_GET(:OBJ_ID, 50, NULL, :I$USER_ID)
                INTO :OBJ_CAPTION, :COLOR, :SORT_ORDER;

                SUSPEND;
            END

            IF (V$I = 1) THEN
            BEGIN
                PARENT_ID = NULL;
                TREE_PARENT_ID = NULL;
                OBJ_ID = :V$OBJ_ID;
                TREE_OBJ_ID = :V$OBJ_ID;
                TYPE_ID = 9;

                SELECT CAPTION, COLOR, :V$SORT_ORDER
                FROM OBJECT_CAPTION_GET(:OBJ_ID, 50, NULL, :I$USER_ID)
                INTO :OBJ_CAPTION, :COLOR, :SORT_ORDER;

                SUSPEND;
            END
        END
    END
    ELSE
    BEGIN
        -- Список учеников, входящих в ГУП
        FOR
            SELECT L256.PARENT_ID, L256.PARENT_ID, L256.OBJ_ID, L256.OBJ_ID, L256.OBJ_TYPE_ID
            FROM LINKS L256
            JOIN LINKS LP54 ON LP54.OBJ_ID = L256.OBJ_ID AND LP54.PARENT_TYPE_ID = 54 AND LP54.DATE_DEL IS NULL
            JOIN LINKS LP50 ON LP50.OBJ_ID = LP54.PARENT_ID AND LP50.PARENT_TYPE_ID = 50 AND LP50.DATE_DEL IS NULL
            LEFT JOIN VALL V2545 ON V2545.OBJ_ID = LP50.PARENT_ID AND V2545.PARAM_ID = 2545 AND V2545.IS_DEL = 0
            WHERE L256.PARENT_ID = :I$GRADE_ID AND L256.OBJ_TYPE_ID IN (256, 346) AND L256.DATE_DEL IS NULL AND ((V2545.LISTVAL_ID IS NULL) OR (V2545.LISTVAL_ID = 3))
            INTO :PARENT_ID, :TREE_PARENT_ID, :OBJ_ID, :TREE_OBJ_ID, :TYPE_ID
        DO
        BEGIN
            V$OBJ_ID = :OBJ_ID;

            SELECT CAPTION, COLOR, CAPTION, CAPTION
            FROM OBJECT_CAPTION_GET(:OBJ_ID, NULL, NULL, :I$USER_ID)
            INTO :OBJ_CAPTION, :COLOR, :SORT_ORDER, :V$SORT_ORDER;

            SUSPEND;

            V$TREE_PARENT_ID = '0';

            FOR
                SELECT :V$OBJ_ID, L10_9.PARENT_ID, L10_9.OBJ_ID, L10_9.OBJ_ID, L10_9.OBJ_TYPE_ID
                FROM LINKS L10
                JOIN LINKS L10_9 ON L10_9.OBJ_ID = L10.OBJ_ID AND L10_9.OBJ_TYPE_ID = 10 AND L10_9.PARENT_TYPE_ID IN (9, 187) AND L10_9.DATE_DEL IS NULL
                WHERE L10.PARENT_ID = :V$OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
                ORDER BY L10_9.PARENT_ID
                INTO :PARENT_ID, :V$I, :OBJ_ID, :TREE_OBJ_ID, :TYPE_ID
            DO
            BEGIN
                TREE_PARENT_ID = :V$OBJ_ID || '_' || :V$I;

                SELECT :V$SORT_ORDER || '  ' || CAPTION
                FROM OBJECT_CAPTION_GET(:V$I, 50, NULL, :I$USER_ID)
                INTO :SORT_ORDER;

                SELECT CAPTION, COLOR, :SORT_ORDER || '  ' || CAPTION
                FROM OBJECT_CAPTION_GET(:OBJ_ID, 50, NULL, :I$USER_ID)
                INTO :OBJ_CAPTION, :COLOR, :SORT_ORDER;

                SUSPEND;

                IF (:TREE_PARENT_ID <> :V$TREE_PARENT_ID) THEN
                BEGIN
                    V$TREE_PARENT_ID = :TREE_PARENT_ID;
                    OBJ_ID = :V$I;
                    TREE_OBJ_ID = :TREE_PARENT_ID;
                    TREE_PARENT_ID = :V$OBJ_ID;
                    TYPE_ID = 9;

                    SELECT CAPTION, COLOR, :V$SORT_ORDER || '  ' || CAPTION
                    FROM OBJECT_CAPTION_GET(:OBJ_ID, 50, NULL, :I$USER_ID)
                    INTO :OBJ_CAPTION, :COLOR, :SORT_ORDER;

                    SUSPEND;
                END
                ELSE
                BEGIN
                    V$TREE_PARENT_ID = :TREE_PARENT_ID;
                END
            END
            -- subgroups
            FOR
                SELECT L47.PARENT_ID,
                       L47.PARENT_ID,
                       L47.OBJ_ID,
                       L47.OBJ_ID,
                       L47.OBJ_TYPE_ID

                FROM LINKS L47

                WHERE L47.PARENT_ID = :V$OBJ_ID
                AND L47.OBJ_TYPE_ID IN (47,347)
                AND L47.DATE_DEL IS NULL

                INTO :PARENT_ID,
                     :TREE_PARENT_ID,
                     :OBJ_ID,
                     :TREE_OBJ_ID,
                     :TYPE_ID
            DO
            BEGIN
                V$I = :OBJ_ID;

                SELECT CAPTION,
                       COLOR,
                       :V$SORT_ORDER || '  ' || 'ЯЯЯ' || CAPTION
                FROM OBJECT_CAPTION_GET(:OBJ_ID, NULL, NULL, :I$USER_ID)
                INTO :OBJ_CAPTION,
                     :COLOR,
                     :SORT_ORDER;

                V$SORT_ORDER_47 = :SORT_ORDER;
                SUSPEND;

                FOR
                    SELECT PARENT_ID,
                           TREE_PARENT_ID,
                           OBJ_ID,
                           TREE_OBJ_ID,
                           TYPE_ID,
                           OBJ_CAPTION,
                           COLOR,
                           :V$SORT_ORDER_47 || '  ' || SORT_ORDER

                    FROM SUBGROUP_SCHOOLARS_LIST(:OBJ_ID, :I$USER_ID, 1)

                    INTO :PARENT_ID,
                         :TREE_PARENT_ID,
                         :OBJ_ID,
                         :TREE_OBJ_ID,
                         :TYPE_ID,
                         :OBJ_CAPTION,
                         :COLOR,
                         :SORT_ORDER
                DO
                BEGIN
                    SUSPEND;
                END

                FOR
                    SELECT L48.PARENT_ID,
                           L48.PARENT_ID,
                           L48.OBJ_ID,
                           L48.OBJ_ID,
                           L48.OBJ_TYPE_ID

                    FROM LINKS L48

                    WHERE L48.PARENT_ID = :V$I
                    AND L48.OBJ_TYPE_ID = 48
                    AND L48.DATE_DEL IS NULL

                    INTO :PARENT_ID,
                         :TREE_PARENT_ID,
                         :OBJ_ID,
                         :TREE_OBJ_ID,
                         :TYPE_ID
                DO
                BEGIN
                    SELECT CAPTION,
                           COLOR,
                           :V$SORT_ORDER_47 || '  ' || CAPTION

                    FROM OBJECT_CAPTION_GET(:OBJ_ID, NULL, NULL, :I$USER_ID)

                    INTO :OBJ_CAPTION,
                         :COLOR,
                         :SORT_ORDER;

                    V$SORT_ORDER_48 = :SORT_ORDER;
                    SUSPEND;

                    FOR
                        SELECT PARENT_ID,
                               TREE_PARENT_ID,
                               OBJ_ID,
                               TREE_OBJ_ID,
                               TYPE_ID,
                               OBJ_CAPTION,
                               COLOR,
                               :V$SORT_ORDER_48 || '  ' || SORT_ORDER

                        FROM SUBGROUP_SCHOOLARS_LIST(:OBJ_ID, :I$USER_ID, 1)

                        INTO :PARENT_ID,
                             :TREE_PARENT_ID,
                             :OBJ_ID,
                             :TREE_OBJ_ID,
                             :TYPE_ID,
                             :OBJ_CAPTION,
                             :COLOR,
                             :SORT_ORDER
                    DO
                    BEGIN
                        SUSPEND;
                    END
                END
            END
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GRID_CAPTION_GET (
    I$PARENT_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$TYPE_ID BIGINT,
    I$IS_SELECT SMALLINT)
RETURNS (
    CAPTION VARCHAR(1000),
    GRID_ORDER DOUBLE PRECISION,
    SORT_ORDER DOUBLE PRECISION)
AS
begin

  SELECT C.CAPTION, C.SORT_ORDER
  FROM OBJECT_CAPTION_GET(:I$OBJ_ID) C
  INTO :CAPTION, :SORT_ORDER;

  IF(I$IS_SELECT = 0) THEN
  BEGIN
    SELECT FIRST 1 V.SORT_ORDER
    FROM PARAMS P
    LEFT JOIN VAL_GET(:I$OBJ_ID, P.PARAM_ID, 0, 1) V ON 1 = 1
    WHERE P.TYPE_ID = :I$TYPE_ID AND P.IS_DEL = 0 AND P.IS_TREESORT = 1
    INTO :GRID_ORDER;
  END
  ELSE
  BEGIN
    SELECT FIRST 1 L.LINK_ID
    FROM LINKS L
    WHERE L.PARENT_ID = :I$PARENT_ID AND L.OBJ_ID = :I$OBJ_ID AND L.DATE_DEL IS NULL
    INTO :GRID_ORDER;
  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GRID_SELECT_ITEMS (
    I$OBJ_ID BIGINT,
    I$GRID_TYPE_ID BIGINT,
    I$LEVEL_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    RUN_SQL VARCHAR(1000))
AS
declare variable V$TYPE_ID bigint;
begin

  SELECT TYPE_ID
  FROM OBJECTS
  WHERE OBJ_ID = :I$OBJ_ID
  INTO :V$TYPE_ID;

  IF(V$TYPE_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Родительский объект не найден или бы удален';

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  SELECT P.RUN_SQL
  FROM PARENTS P
  JOIN LTYPES LT ON LT.LEVEL_ID = :I$LEVEL_ID AND LT.TYPE_ID = :I$GRID_TYPE_ID AND LT.IS_DEL = 0
  WHERE P.TYPE_ID = :V$TYPE_ID AND P.CHILD_ID = :I$GRID_TYPE_ID AND P.IS_DEL = 0
  INTO :RUN_SQL;

  IF(RUN_SQL IS NULL) THEN EXCEPTION DATA_ERROR 'Тип объектов недоступен для выбора';

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GROUP_ITEM_GET (
    I$OBJ_ID BIGINT,
    I$GROUP_ID BIGINT,
    I$USER_ID VARCHAR(100))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$ID BIGINT;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$OU_ID BIGINT;
DECLARE VARIABLE V$TYPE_ID BIGINT;
DECLARE VARIABLE V$STATE_ID BIGINT;
DECLARE VARIABLE V$STAGE_ID BIGINT;
DECLARE VARIABLE V$MASK_ID BIGINT;
DECLARE VARIABLE V$PLAN_ID BIGINT;
DECLARE VARIABLE V$CAPTION VARCHAR(1000);
DECLARE VARIABLE V$CLASS_CAPTION VARCHAR(400);
DECLARE VARIABLE V$GROUP_ID BIGINT;
DECLARE VARIABLE V$VD BIGINT;
DECLARE VARIABLE V INTEGER;
DECLARE VARIABLE VP BIGINT;
begin

  -- Наличие доступа к приложению ОП и УП ?
  -- !!!

  SELECT LP2.PARENT_ID, LP50.PARENT_ID, V2470.LISTVAL_ID, V381.LISTVAL_ID, LV.COST, V2545.LISTVAL_ID, LV.PARENT_ID
  FROM LINKS LP50
  JOIN VALL V381 ON V381.OBJ_ID = LP50.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V381.LISTVAL_ID
  JOIN VALL V2470 ON V2470.OBJ_ID = LP50.PARENT_ID AND V2470.PARAM_ID = IIF(LP50.PARENT_TYPE_ID = 400, 3013, 2470) AND V2470.IS_DEL = 0
  LEFT JOIN VALL V2545 ON V2545.OBJ_ID = LP50.PARENT_ID AND V2545.PARAM_ID = IIF(LP50.PARENT_TYPE_ID = 400, 3022, 2545) AND V2470.IS_DEL = 0
  JOIN LINKS LP57 ON LP57.OBJ_ID = LP50.PARENT_ID AND LP57.PARENT_TYPE_ID = 57 AND LP57.DATE_DEL IS NULL
  JOIN LINKS LP69 ON LP69.OBJ_ID = LP57.PARENT_ID AND LP69.PARENT_TYPE_ID = 69 AND LP69.DATE_DEL IS NULL
  JOIN LINKS LP2 ON LP2.OBJ_ID = LP69.PARENT_ID AND LP2.PARENT_TYPE_ID = 2 AND LP2.DATE_DEL IS NULL
  WHERE LP50.PARENT_TYPE_ID IN (50, 400) AND LP50.OBJ_ID = :I$OBJ_ID AND LP50.DATE_DEL IS NULL
  INTO :V$OU_ID, :V$ID, :V$STATE_ID, :V$STAGE_ID, :V, :V$VD, :VP;

  IF(V$ID IS NULL) THEN EXCEPTION DATA_ERROR 'Данные не найдены или были удалены';

  TAG_NAME = 'plan_id';
  VAL = V$ID;
  SUSPEND;

  TAG_NAME = 'stage_id';
  VAL = V$STAGE_ID;
  SUSPEND;

  TAG_NAME = 'stage_index';
  VAL = V;
  SUSPEND;

  TAG_NAME = 'state_id';
  VAL = V$STATE_ID;
  SUSPEND;

  TAG_NAME = 'is_vd';
  VAL = V$VD;
  SUSPEND;

  -- Справочник доступных этапов обучения в ОУ, из числа имеющихся в ОУ
  -- и всегда оставляем ту в которой сами находимся, даже если нет групп
  -- этапы дофильтровываем исходя из текущего вида ОП - для школьных ОП только школьные этапы, для СПО только СПО
  TAG_NAME = 'stage_index::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT LV.LISTVAL_ID, LV.COST, R.VAL
    FROM LINKS L7
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V49.LISTVAL_ID
    JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
    WHERE L7.PARENT_ID = :V$OU_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
      AND (LV.PARENT_ID = :VP OR LV.PARENT_ID IN (2141, 12941) AND :VP IN (2141, 12941))
    UNION
    SELECT LV.LISTVAL_ID, LV.COST, R.VAL
    FROM LISTVALS LV
    JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
    WHERE LV.LISTVAL_ID = :V$STAGE_ID
    ORDER BY 2
    INTO :V$OBJ_ID, :V, :V$CAPTION
  DO
  BEGIN
    TAG_NAME = 'stage_index:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'stage_index:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'stage_index:r:stage_index';
    VAL = V;
    SUSPEND;
    TAG_NAME = 'stage_index:r:value';
    VAL = V$CAPTION;
    SUSPEND;
    -- !!! Признак, что этап есть в данном УП, для раскраски
    TAG_NAME = 'stage_index:r:same_plan';
    VAL = '1';
    SUSPEND;
  END

  TAG_NAME = 'groups::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L256.OBJ_ID, L256.OBJ_TYPE_ID, COALESCE(V3062.VAL, 0), V2162.VAL
    FROM LINKS L256
    JOIN VALS V2162 ON V2162.OBJ_ID = L256.OBJ_ID AND V2162.PARAM_ID = 2162 AND V2162.IS_DEL = 0
    LEFT JOIN VALI V3062 ON V3062.OBJ_ID = L256.OBJ_ID AND V3062.PARAM_ID = 3062 AND V3062.IS_DEL = 0
    WHERE L256.PARENT_ID = :I$OBJ_ID AND L256.OBJ_TYPE_ID = 256 AND L256.DATE_DEL IS NULL AND (:I$GROUP_ID IS NULL OR L256.OBJ_ID = :I$GROUP_ID)
    INTO :V$ID, :V$TYPE_ID, :V$MASK_ID, :V$CAPTION
  DO
  BEGIN

    TAG_NAME = 'groups:r';
    VAL = NULL;
    SUSPEND;

    TAG_NAME = 'groups:r:id';
    VAL = V$ID;
    SUSPEND;

    TAG_NAME = 'groups:r:type_id';
    VAL = V$TYPE_ID;
    SUSPEND;

    TAG_NAME = 'groups:r:name';
    VAL = V$CAPTION;
    SUSPEND;

    TAG_NAME = 'groups:r:stage_mask';
    VAL = V$MASK_ID;
    SUSPEND;

    -- Список учащихся в группе
    TAG_NAME = 'groups:r:members::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT L10.OBJ_ID, L10.OBJ_TYPE_ID, C.NAME_FULL, CG.CAPTION, LV.COST, LPG.PARENT_ID, V49.LISTVAL_ID
      FROM LINKS L10
      JOIN LINKS LPG ON LPG.OBJ_ID = L10.OBJ_ID AND LPG.PARENT_TYPE_ID IN (9, 187) AND LPG.DATE_DEL IS NULL
      JOIN LINKS LPS ON LPS.OBJ_ID = LPG.PARENT_ID AND LPS.PARENT_TYPE_ID = 8 AND LPS.DATE_DEL IS NULL
      JOIN VALL V49 ON V49.OBJ_ID = LPS.PARENT_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
      JOIN LISTVALS LV ON LV.LISTVAL_ID = V49.LISTVAL_ID
      LEFT JOIN CJ2_PERSON_NAME(L10.OBJ_ID) C ON 1 = 1
      LEFT JOIN OBJECT_CAPTION_GET(LPG.PARENT_ID) CG ON 1 = 1
      WHERE L10.PARENT_ID = :V$ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      ORDER BY 4, 3, 2
      INTO :V$OBJ_ID, :V$TYPE_ID, :V$CAPTION, :V$CLASS_CAPTION, :V, :V$GROUP_ID, :V$STAGE_ID
    DO
    BEGIN
      TAG_NAME = 'groups:r:members:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'groups:r:members:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'groups:r:members:r:type_id';
      VAL = V$TYPE_ID;
      SUSPEND;
      TAG_NAME = 'groups:r:members:r:name';
      VAL = V$CAPTION;
      SUSPEND;
      TAG_NAME = 'groups:r:members:r:group_id';
      VAL = V$GROUP_ID;
      SUSPEND;
      TAG_NAME = 'groups:r:members:r:group_name';
      VAL = V$CLASS_CAPTION;
      SUSPEND;
      TAG_NAME = 'groups:r:members:r:stage_index';
      VAL = V$STAGE_ID;
      SUSPEND;
      -- Дата, с которой ученик зачислен в группу
      TAG_NAME = 'groups:r:members:r:date_from';
      VAL = NULL;
      SELECT FIRST 1 D.VAL
      FROM PERSON_MOVEMENTS M
      LEFT JOIN DATE2ISO(M.DATE_IN, 0) D ON 1 = 1
      WHERE M.DATE_DEL IS NULL AND M.GROUP_ID = :I$OBJ_ID AND M.PERSON_ID = :V$OBJ_ID AND M.DATE_OUT IS NULL
      INTO :VAL;
      SUSPEND;
    END

  END

  -- Список классов (административных групп)
  TAG_NAME = 'source_groups::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L9.OBJ_ID, L9.OBJ_TYPE_ID, C.CAPTION, LV.COST
    FROM LINKS L7
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V49.LISTVAL_ID
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 187) AND L9.DATE_DEL IS NULL
    LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C ON 1 = 1
    WHERE L7.PARENT_ID = :V$OU_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    ORDER BY LV.COST, C.CAPTION
    INTO :V$OBJ_ID, :V$TYPE_ID, :V$CAPTION, :V$STAGE_ID
  DO
  BEGIN
    TAG_NAME = 'source_groups:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'source_groups:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'source_groups:r:type_id';
    VAL = V$TYPE_ID;
    SUSPEND;
    TAG_NAME = 'source_groups:r:name';
    VAL = V$CAPTION;
    SUSPEND;
    TAG_NAME = 'source_groups:r:stage_index';
    VAL = V$STAGE_ID;
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GROUP_PLAN_ID (
    GRADE_ID BIGINT,
    GRADE_TYPE_ID BIGINT)
RETURNS (
    PLAN_ID BIGINT,
    IS_VD BIGINT,
    PLAN_TYPE BIGINT,
    PLAN_STAGE_ID BIGINT,
    PLAN_STAGE_LV BIGINT)
AS
begin
    IF(GRADE_TYPE_ID = 256) THEN
    BEGIN
        SELECT LP50.PARENT_ID, V2545.LISTVAL_ID, V2101.LISTVAL_ID, LP54.PARENT_ID, V381.LISTVAL_ID
        FROM LINKS LP54
        LEFT JOIN VALL V381 ON V381.OBJ_ID = LP54.PARENT_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
        JOIN LINKS LP50 ON LP50.OBJ_ID = LP54.PARENT_ID AND LP50.PARENT_TYPE_ID = 50 AND LP50.DATE_DEL IS NULL
        LEFT JOIN VALL V2545 ON V2545.OBJ_ID = LP50.PARENT_ID AND V2545.PARAM_ID = 2545 AND V2545.IS_DEL = 0
        LEFT JOIN VALL V2101 ON V2101.OBJ_ID = LP50.PARENT_ID AND V2101.PARAM_ID = 2101 AND V2101.IS_DEL = 0
        WHERE LP54.OBJ_ID = :GRADE_ID AND LP54.PARENT_TYPE_ID = 54 AND LP54.DATE_DEL IS NULL
        INTO :PLAN_ID, :IS_VD, :PLAN_TYPE, :PLAN_STAGE_ID, :PLAN_STAGE_LV;
    END
    ELSE IF(GRADE_TYPE_ID = 48) THEN
    BEGIN
        SELECT LP50.PARENT_ID, V2545.LISTVAL_ID, V2101.LISTVAL_ID, LP54.PARENT_ID, V381.LISTVAL_ID
        FROM LINKS LP47
        JOIN LINKS LP256 ON LP256.OBJ_ID = LP47.PARENT_ID AND LP256.PARENT_TYPE_ID = 256 AND LP256.DATE_DEL IS NULL
        JOIN LINKS LP54 ON LP54.OBJ_ID = LP256.PARENT_ID AND LP54.PARENT_TYPE_ID = 54 AND LP54.DATE_DEL IS NULL
        LEFT JOIN VALL V381 ON V381.OBJ_ID = LP54.PARENT_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
        JOIN LINKS LP50 ON LP50.OBJ_ID = LP54.PARENT_ID AND LP50.PARENT_TYPE_ID = 50 AND LP50.DATE_DEL IS NULL
        LEFT JOIN VALL V2545 ON V2545.OBJ_ID = LP50.PARENT_ID AND V2545.PARAM_ID = 2545 AND V2545.IS_DEL = 0
        LEFT JOIN VALL V2101 ON V2101.OBJ_ID = LP50.PARENT_ID AND V2101.PARAM_ID = 2101 AND V2101.IS_DEL = 0
        WHERE LP47.OBJ_ID = :GRADE_ID AND LP47.PARENT_TYPE_ID = 47 AND LP47.DATE_DEL IS NULL
        INTO :PLAN_ID, :IS_VD, :PLAN_TYPE, :PLAN_STAGE_ID, :PLAN_STAGE_LV;
    END
    ELSE IF(GRADE_TYPE_ID = 347) THEN
    BEGIN
        SELECT LP50.PARENT_ID, V2545.LISTVAL_ID, V2101.LISTVAL_ID, LP54.PARENT_ID, V381.LISTVAL_ID
        FROM LINKS LP346
        JOIN LINKS LP54 ON LP54.OBJ_ID = LP346.PARENT_ID AND LP54.PARENT_TYPE_ID = 54 AND LP54.DATE_DEL IS NULL
        LEFT JOIN VALL V381 ON V381.OBJ_ID = LP54.PARENT_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
        JOIN LINKS LP50 ON LP50.OBJ_ID = LP54.PARENT_ID AND LP50.PARENT_TYPE_ID = 50 AND LP50.DATE_DEL IS NULL
        LEFT JOIN VALL V2545 ON V2545.OBJ_ID = LP50.PARENT_ID AND V2545.PARAM_ID = 2545 AND V2545.IS_DEL = 0
        LEFT JOIN VALL V2101 ON V2101.OBJ_ID = LP50.PARENT_ID AND V2101.PARAM_ID = 2101 AND V2101.IS_DEL = 0
        WHERE LP346.OBJ_ID = :GRADE_ID AND LP346.PARENT_TYPE_ID = 346 AND LP346.DATE_DEL IS NULL
        INTO :PLAN_ID, :IS_VD, :PLAN_TYPE, :PLAN_STAGE_ID, :PLAN_STAGE_LV;
    END
    SUSPEND;
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GUP_SUBJ_PTP_CJ_STATUS (
    I$CURRICULUM_ID BIGINT,
    I$CHECK_CURRICULUM_ID BIGINT,
    I$COMPONENT_TYPE_ID BIGINT = null)
RETURNS (
    SUBJECT_ID BIGINT,
    STAGE_ID BIGINT,
    JOURNAL_ID BIGINT,
    JOURNAL_NAME VARCHAR(1000),
    PTP_ID BIGINT,
    CJ_LESSON_MISSED INTEGER,
    CJ_PTP_EQUALS FLOAT)
AS
declare variable V$N integer;
declare variable V$PTP_LESSON_COUNT integer;
declare variable V$COMPONENT_TYPE_ID bigint;
declare variable SORT_ORDER bigint;
BEGIN

    -- Федеральный и обязательный компоненты идентичны, региональный и компонент ОО также
    IF(I$COMPONENT_TYPE_ID IS NOT NULL) THEN BEGIN
      IF(I$COMPONENT_TYPE_ID = 780) THEN V$COMPONENT_TYPE_ID = 13303;
      ELSE IF(I$COMPONENT_TYPE_ID = 782) THEN V$COMPONENT_TYPE_ID = 13304;
    END

    FOR
      SELECT DISTINCT S.SUBJECT_ID, V381.LISTVAL_ID, LV381.SORT_ORDER
      FROM PLAN_SUBJECTS S
      JOIN PLAN_SUBJECTS PS ON PS.OBJ_ID = S.PARENT_ID
      JOIN PLAN_LOADS L ON L.DATE_DEL IS NULL AND L.SUBJECT_ID = S.OBJ_ID AND (L.LOAD_HOURS_S1 > 0 OR L.LOAD_HOURS_S2 > 0)
      JOIN VALL V381 ON V381.OBJ_ID = L.STAGE_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
      JOIN LISTVALS LV381 ON LV381.LISTVAL_ID = V381.LISTVAL_ID
      LEFT JOIN VALI V375 ON V375.OBJ_ID = S.SUBJECT_ID AND V375.PARAM_ID = 375 AND V375.IS_DEL = 0
      WHERE S.DATE_DEL IS NULL AND S.PLAN_ID = :I$CURRICULUM_ID AND S.ROW_TYPE = 10
        AND ((:I$COMPONENT_TYPE_ID IS NULL) OR (PS.FIELD_ID = :I$COMPONENT_TYPE_ID) OR (PS.FIELD_ID = :V$COMPONENT_TYPE_ID))
        AND S.SUBJECT_ID <> 34607
      ORDER BY V375.VAL, LV381.SORT_ORDER
      INTO :SUBJECT_ID, :STAGE_ID, :SORT_ORDER
    DO
    BEGIN

      FOR
        SELECT J.OBJ_ID, J.JOURNAL_NAME, P.OBJ_ID
        FROM CJ2_JOURNAL J
        JOIN CJ2_JOURNAL_PTP JP ON JP.DATE_DEL IS NULL AND JP.CJ_ID = J.OBJ_ID AND JP.APPROVAL_STATE = 2
        JOIN PTP P ON P.OBJ_ID = JP.PTP_ID
        WHERE J.DATE_DEL IS NULL AND J.REF_ID = :I$CURRICULUM_ID AND J.SUBJECT_ID = :SUBJECT_ID
            AND J.STAGE_INDEX = :STAGE_ID AND J.JOURNAL_TYPE = 0
        ORDER BY 2
        INTO :JOURNAL_ID, :JOURNAL_NAME, :PTP_ID
      DO
      BEGIN

          SELECT COUNT(*)
          FROM CJ2_JOURNAL_LESSONS CJL
          LEFT JOIN PTP_LESSONS PL ON PL.OBJ_ID = CJL.LESSON_PTP_ID AND PL.DATE_DEL IS NULL
          WHERE CJL.CJ_ID = :JOURNAL_ID AND CJL.IS_COMPLETED = 1 AND
          -- для уроков из ПТП проверяем по id - темы должны и так биться
          -- вторую проверку убираем - она по идее не должна быть актуальной (связи с ПТП нет, но тема урока бьтся с ПТП)
          PL.OBJ_ID IS NOT NULL
/*
          OR
          (CJL.PTP_LESSON_ID IS NULL AND EXISTS(
            SELECT FIRST 1 1
            FROM LINKS L88
            JOIN VALS V476 ON V476.OBJ_ID = L88.OBJ_ID AND V476.PARAM_ID = 476 AND V476.IS_DEL = 0 AND
                UPPER(REPLACE(REPLACE(REPLACE(CJL.LESSON_THEME, ASCII_CHAR(13), ''), ASCII_CHAR(10), ''), ' ', '')) =
                  UPPER(REPLACE(REPLACE(REPLACE(V476.VAL, ASCII_CHAR(13), ''), ASCII_CHAR(10), ''), ' ', ''))
          )))*/
          INTO :V$N;

          SELECT COUNT(*)
          FROM PTP_LESSONS PL
          WHERE PL.PTP_ID = :PTP_ID AND PL.DATE_DEL IS NULL
          INTO :V$PTP_LESSON_COUNT;

          CJ_LESSON_MISSED = V$PTP_LESSON_COUNT - V$N;

          -- Дополнительная проверка для КЖ ГУП, где все дети учатся в потоках другого УП
          -- Критерий: нет ни одного урока, и все дети числятся в потоках по этому предмету
/*          IF(NOT EXISTS(
              SELECT FIRST 1 1
              FROM CJ_LESSON CJL
              WHERE CJL.CJ_ID = :V$CJ_ID
          ) AND NOT EXISTS (
              SELECT FIRST 1 1
              FROM CJ_MAIN CJM
              JOIN LINKS L10 ON L10.PARENT_ID = :GUP_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
              JOIN LINKS LP347 ON LP347.OBJ_ID = L10.OBJ_ID AND LP347.PARENT_TYPE_ID = 347 AND LP347.DATE_DEL IS NULL AND LP347.PARENT_ID <> :GUP_ID
              JOIN LINKS LP346 ON LP346.OBJ_ID = LP347.PARENT_ID AND LP346.PARENT_TYPE_ID = 346 AND LP346.DATE_DEL IS NULL
              JOIN VALR V2705 ON V2705.OBJ_ID = LP346.PARENT_ID AND V2705.PARAM_ID = 2705 AND V2705.IS_DEL = 0 AND V2705.PARAM_ID = CJM.SUBJECT_ID
              WHERE CJM.CJ_ID = :V$CJ_ID
          ))
          THEN V$PTP_LESSON_COUNT = 0; */

          IF (V$PTP_LESSON_COUNT > 0) THEN
          BEGIN
              CJ_PTP_EQUALS = V$PTP_LESSON_COUNT - CJ_LESSON_MISSED;
              CJ_PTP_EQUALS = (CJ_PTP_EQUALS / V$PTP_LESSON_COUNT) * 100;
              SUSPEND;
          END
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GUP_SUBJ_PTP_EXECUTION_STATUS (
    I$CURRICULUM_ID BIGINT,
    I$CHECK_CURRICULUM_ID BIGINT,
    I$COMPONENT_TYPE_ID BIGINT = null)
RETURNS (
    SUBJECT_ID BIGINT,
    STAGE_ID BIGINT,
    JOURNAL_ID BIGINT,
    JOURNAL_NAME VARCHAR(1000),
    PTP_STATUS BIGINT,
    PTP_HOURS INTEGER,
    CURRICULUM_HOURS INTEGER,
    LESSONS_COUNT INTEGER,
    PTP_REALIZATION_PROCENT FLOAT,
    CURRICULUM_REALIZATION_PROCENT FLOAT,
    COMPARE_RESULT_ID BIGINT)
AS
declare variable V$COMPONENT_TYPE_ID bigint;
declare variable SORT_ORDER bigint;
BEGIN

    -- Федеральный и обязательный компоненты идентичны, региональный и компонент ОО также
    IF(I$COMPONENT_TYPE_ID IS NOT NULL) THEN BEGIN
      IF(I$COMPONENT_TYPE_ID = 780) THEN V$COMPONENT_TYPE_ID = 13303;
      ELSE IF(I$COMPONENT_TYPE_ID = 782) THEN V$COMPONENT_TYPE_ID = 13304;
    END

    FOR
      SELECT DISTINCT S.SUBJECT_ID, V381.LISTVAL_ID, LV381.SORT_ORDER
      FROM PLAN_SUBJECTS S
      JOIN PLAN_SUBJECTS PS ON PS.OBJ_ID = S.PARENT_ID
      JOIN PLAN_LOADS L ON L.DATE_DEL IS NULL AND L.SUBJECT_ID = S.OBJ_ID AND (L.LOAD_HOURS_S1 > 0 OR L.LOAD_HOURS_S2 > 0)
      JOIN VALL V381 ON V381.OBJ_ID = L.STAGE_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
      JOIN LISTVALS LV381 ON LV381.LISTVAL_ID = V381.LISTVAL_ID
      LEFT JOIN VALI V375 ON V375.OBJ_ID = S.SUBJECT_ID AND V375.PARAM_ID = 375 AND V375.IS_DEL = 0
      WHERE S.DATE_DEL IS NULL AND S.PLAN_ID = :I$CURRICULUM_ID AND S.ROW_TYPE = 10
        AND ((:I$COMPONENT_TYPE_ID IS NULL) OR (PS.FIELD_ID = :I$COMPONENT_TYPE_ID) OR (PS.FIELD_ID = :V$COMPONENT_TYPE_ID))
        AND S.SUBJECT_ID <> 34607
      ORDER BY V375.VAL, LV381.SORT_ORDER
      INTO :SUBJECT_ID, :STAGE_ID, :SORT_ORDER
    DO
    BEGIN

      FOR
        SELECT J.OBJ_ID, J.JOURNAL_NAME, J.HOURS
        FROM CJ2_JOURNAL J
        WHERE J.DATE_DEL IS NULL AND J.REF_ID = :I$CURRICULUM_ID AND J.SUBJECT_ID = :SUBJECT_ID
          AND J.STAGE_INDEX = :STAGE_ID AND J.JOURNAL_TYPE = 0
        ORDER BY 2
        INTO :JOURNAL_ID, :JOURNAL_NAME, :CURRICULUM_HOURS
      DO
      BEGIN
        PTP_HOURS = NULL;
        PTP_STATUS = NULL;

        SELECT FIRST 1 P.PTP_HOURS, JP.APPROVAL_STATE
        FROM CJ2_JOURNAL_PTP JP
        LEFT JOIN PTP P ON P.OBJ_ID = JP.PTP_ID
        WHERE JP.DATE_DEL IS NULL AND JP.CJ_ID = :JOURNAL_ID
        ORDER BY IIF(JP.APPROVAL_STATE = 3, -1, JP.APPROVAL_STATE) DESC
        INTO :PTP_HOURS, :PTP_STATUS;

        IF(PTP_STATUS IS NOT NULL) THEN
        BEGIN

          -- Преобразуем новый код статуса в старый LV
          IF(PTP_STATUS = 0) THEN PTP_STATUS = 11713;
          ELSE IF(PTP_STATUS = 1) THEN PTP_STATUS = 11712;
          ELSE IF(PTP_STATUS = 2) THEN PTP_STATUS = 11711;
          ELSE PTP_STATUS = 11714; -- не действующий

          SELECT COUNT(*)
          FROM CJ2_JOURNAL_LESSONS CJL
          WHERE CJL.CJ_ID = :JOURNAL_ID AND CJL.IS_COMPLETED = 1
          INTO :LESSONS_COUNT;

          IF (LESSONS_COUNT >= 0 AND CURRICULUM_HOURS > 0) THEN
          BEGIN
            IF (PTP_HOURS > 0) THEN
            BEGIN
              PTP_REALIZATION_PROCENT = LESSONS_COUNT;
              PTP_REALIZATION_PROCENT = (PTP_REALIZATION_PROCENT / PTP_HOURS) * 100;
            END
            ELSE
            BEGIN
              PTP_REALIZATION_PROCENT = 0;
            END

            IF (CURRICULUM_HOURS > 0) THEN
            BEGIN
              CURRICULUM_REALIZATION_PROCENT = LESSONS_COUNT;
              CURRICULUM_REALIZATION_PROCENT = (CURRICULUM_REALIZATION_PROCENT / CURRICULUM_HOURS) * 100;
            END
            ELSE
            BEGIN
              CURRICULUM_REALIZATION_PROCENT = 0;
            END

            IF (CURRICULUM_REALIZATION_PROCENT >= 100) THEN
            BEGIN
              COMPARE_RESULT_ID = 11722;
            END
            ELSE IF (PTP_REALIZATION_PROCENT >= 100) THEN
            BEGIN
              COMPARE_RESULT_ID = 11723;
            END
            ELSE
            BEGIN
              COMPARE_RESULT_ID = 11724;
            END

            SUSPEND;

          END

        END

      END

    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GZ_ADD_CHECK (
    I$PARENT_ID BIGINT,
    I$TYPE_ID BIGINT)
AS
declare variable V$GZ_ID bigint;
begin

  IF(I$TYPE_ID = 441) THEN
  BEGIN
    IF(EXISTS(SELECT 1 FROM VAL_GET(:I$PARENT_ID, 3210) WHERE I = 1)) THEN EXCEPTION DATA_ERROR 'Проекты ГЗ нельзя добавлять в архивную папку';
  END
  ELSE
  BEGIN
    IF(I$TYPE_ID = 442) THEN
      V$GZ_ID = I$PARENT_ID;
    ELSE
      SELECT FIRST 1 LP441.PARENT_ID
      FROM LINKS LP441
      WHERE LP441.OBJ_ID = :I$PARENT_ID AND LP441.PARENT_TYPE_ID = 441 AND LP441.DATE_DEL IS NULL
      INTO :V$GZ_ID;

    IF(NOT EXISTS(
      SELECT FIRST 1 1
      FROM VALL
      WHERE OBJ_ID = :V$GZ_ID AND PARAM_ID = 3214 AND IS_DEL = 0 AND LISTVAL_ID = 13502
    ))
    THEN EXCEPTION DATA_ERROR 'Изменять разделы Государственного Задания можно только в статусе проекта';
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GZ_ADD_QUALITY (
    I$SECTION_ID BIGINT,
    I$ITEM_ID BIGINT,
    I$UNITS VARCHAR(40),
    I$TEXT VARCHAR(1000))
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$UNIT_ID bigint;
declare variable V$U varchar(400);
declare variable T bigint;
begin

  -- Проверяем, добавлен ли уже такой показатель ?
  -- ...

  SELECT OBJ_ID FROM OBJECT_ADD(:I$SECTION_ID, 444) INTO :OBJ_ID;
  SELECT 1 FROM VAL_ADD(3250, :OBJ_ID, :I$TEXT) INTO :T;

  -- Подбираем единицы из справочника
  V$U = I$TEXT;
  T = POSITION('(' IN V$U);
  IF(T > 0) THEN
  BEGIN
    V$U = SUBSTRING(V$U FROM T + 1);
    T = POSITION(')' IN V$U);
    V$U = SUBSTRING(V$U FROM 1 FOR T - 1);
  END

  SELECT FIRST 1 LV.LISTVAL_ID
  FROM LISTVALS LV
  JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
  WHERE LV.LIST_ID = 340 AND LV.IS_DEL = 0 AND (LV.TAG = :I$UNITS OR R.VAL = :V$U)
  INTO :V$UNIT_ID;

  SELECT 1 FROM VAL_ADD(3251, :OBJ_ID, :V$UNIT_ID) INTO :T;

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GZ_ADD_SECTION (
    I$OBJ_ID BIGINT NOT NULL,
    I$REF_ID BIGINT NOT NULL,
    I$TYPE INTEGER NOT NULL,
    I$LEVEL SMALLINT NOT NULL,
    I$NAME VARCHAR(2000),
    I$REGNUM VARCHAR(100),
    I$TECHNUM VARCHAR(100),
    I$OKVED VARCHAR(200),
    I$OKPD VARCHAR(200),
    I$C1 VARCHAR(1000),
    I$C2 VARCHAR(1000),
    I$C3 VARCHAR(1000),
    I$T1 VARCHAR(1000),
    I$T2 VARCHAR(1000),
    I$CONS VARCHAR(1000),
    I$EXTRA VARCHAR(1000),
    I$C0 VARCHAR(2000),
    I$TR VARCHAR(1000),
    I$USER_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    CAPTION VARCHAR(1000))
AS
declare variable V$STATUS bigint;
declare variable V$NROWS integer;
begin

  -- I$LEVEL нигде не фиксируется

  -- Проверяем статус ГЗ
  SELECT FIRST 1 V3214.LISTVAL_ID
  FROM VALL V3214
  WHERE V3214.OBJ_ID = :I$OBJ_ID AND V3214.PARAM_ID = 3214 AND V3214.IS_DEL = 0
  INTO :V$STATUS;

  IF(V$STATUS IS NULL) THEN EXCEPTION DATA_ERROR 'Не указан статус ГЗ';
  IF(V$STATUS <> 13502) THEN EXCEPTION DATA_ERROR 'Недопустимый статус ГЗ, вносить изменения можно только в статусе проекта';

  -- Нет ли уже такого раздела ?
  IF(EXISTS(
    SELECT FIRST 1 1
    FROM LINKS L442
    JOIN VALI V3219 ON V3219.OBJ_ID = L442.OBJ_ID AND V3219.PARAM_ID = 3219 AND V3219.IS_DEL = 0 AND V3219.VAL = :I$REF_ID
    WHERE L442.PARENT_ID = :I$OBJ_ID AND L442.OBJ_TYPE_ID = 442 AND L442.DATE_DEL IS NULL
  ))
  THEN EXCEPTION DATA_ERROR 'Данный раздел уже присутствует в ГЗ';

  SELECT COUNT(*)
  FROM LINKS L442
  WHERE L442.PARENT_ID = :I$OBJ_ID AND L442.OBJ_TYPE_ID = 442 AND L442.DATE_DEL IS NULL
  INTO :V$NROWS;

  -- Добавляем строку
  SELECT OBJ_ID FROM OBJECT_ADD(:I$OBJ_ID, 442, NULL, NULL, :I$USER_ID) INTO :OBJ_ID;

  INSERT INTO VALI (OBJ_ID, PARAM_ID, VAL) VALUES (:OBJ_ID, 3219, :I$REF_ID); -- ссылка на справочник
  INSERT INTO VALI (OBJ_ID, PARAM_ID, VAL) VALUES (:OBJ_ID, 3218, :V$NROWS + 1); -- номер раздела по порядку
  SELECT 1 FROM VAL_ADD(3220, :OBJ_ID, :I$NAME) INTO :V$NROWS;
  SELECT 1 FROM VAL_ADD(3221, :OBJ_ID, :I$REGNUM) INTO :V$NROWS;
  SELECT 1 FROM VAL_ADD(3222, :OBJ_ID, :I$TECHNUM) INTO :V$NROWS;
  SELECT 1 FROM VAL_ADD(3235, :OBJ_ID, SUBSTRING(:I$REGNUM FROM 14 FOR 4)) INTO :V$NROWS;
  SELECT 1 FROM VAL_ADD(3223, :OBJ_ID, :I$OKVED) INTO :V$NROWS;
  SELECT 1 FROM VAL_ADD(3224, :OBJ_ID, :I$OKPD) INTO :V$NROWS;
  SELECT 1 FROM VAL_ADD(3225, :OBJ_ID, IIF(:I$TYPE = 0, 13508, 13509)) INTO :V$NROWS;
  SELECT 1 FROM VAL_ADD(3226, :OBJ_ID, :I$C1) INTO :V$NROWS;
  SELECT 1 FROM VAL_ADD(3227, :OBJ_ID, :I$C2) INTO :V$NROWS;
  SELECT 1 FROM VAL_ADD(3228, :OBJ_ID, :I$C3) INTO :V$NROWS;
  SELECT 1 FROM VAL_ADD(3229, :OBJ_ID, :I$T1) INTO :V$NROWS;
  SELECT 1 FROM VAL_ADD(3230, :OBJ_ID, :I$T2) INTO :V$NROWS;
  SELECT 1 FROM VAL_ADD(3231, :OBJ_ID, :I$CONS) INTO :V$NROWS;
  SELECT 1 FROM VAL_ADD(3232, :OBJ_ID, :I$EXTRA) INTO :V$NROWS;
  SELECT 1 FROM VAL_ADD(3233, :OBJ_ID, :I$C0) INTO :V$NROWS;
  SELECT 1 FROM VAL_ADD(3234, :OBJ_ID, :I$TR) INTO :V$NROWS;

  -- Остальные поля заполнятся по-умолчанию

  SELECT CAPTION FROM OBJECT_CAPTION_GET(:OBJ_ID) INTO :CAPTION;

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GZ_ADD_VOLUME (
    I$SECTION_ID BIGINT,
    I$ITEM_ID BIGINT,
    I$UNITS VARCHAR(40),
    I$TEXT VARCHAR(1000),
    I$PAY SMALLINT)
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$UNIT_ID bigint;
declare variable V$U varchar(400);
declare variable T bigint;
begin

  -- Проверяем, добавлены ли уже такие единицы ?
  -- ...

  SELECT OBJ_ID FROM OBJECT_ADD(:I$SECTION_ID, 443) INTO :OBJ_ID;
  SELECT 1 FROM VAL_ADD(3242, :OBJ_ID, :I$TEXT) INTO :T;
  SELECT 1 FROM VAL_ADD(3243, :OBJ_ID, IIF(:I$PAY = 0, 13510, 13511)) INTO :T;

  -- Подбираем единицы из справочника
  V$U = I$TEXT;
  T = POSITION('(' IN V$U);
  IF(T > 0) THEN
  BEGIN
    V$U = SUBSTRING(V$U FROM T + 1);
    T = POSITION(')' IN V$U);
    V$U = SUBSTRING(V$U FROM 1 FOR T - 1);
  END

  SELECT FIRST 1 LV.LISTVAL_ID
  FROM LISTVALS LV
  JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
  WHERE LV.LIST_ID = 340 AND LV.IS_DEL = 0 AND (LV.TAG = :I$UNITS OR R.VAL = :V$U)
  INTO :V$UNIT_ID;

  SELECT 1 FROM VAL_ADD(3244, :OBJ_ID, :V$UNIT_ID) INTO :T;

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GZ_CALC_RESULT (
    I$PARAM_ID BIGINT,
    I$USER_ID BIGINT,
    I$OU_ID BIGINT = null,
    I$PARAM_CODE VARCHAR(200) = null,
    I$YEAR INTEGER = null)
RETURNS (
    RESULT DOUBLE PRECISION)
AS
declare variable V$SECTION_ID bigint;
declare variable V$NAME varchar(1000);
declare variable V$YEAR integer;
declare variable V$DATE date;
declare variable V$UNITS bigint;
declare variable V$MEMBER_ID bigint;
declare variable V$MEMBER_TYPE bigint;
declare variable V$STAGE_ID bigint;
begin

  -- Передается либо PARAM_ID для расчета конкретного параметра
  -- либо PARAM_CODE и YEAR для скользящего отчета + OU_ID

  IF(I$PARAM_ID IS NOT NULL) THEN
  BEGIN
    -- Получаем год и название параметра, ID раздела
    -- Год = год утверждения задания, т.е. само задание на следующий год
    SELECT FIRST 1 LP442.PARENT_ID, V3211.VAL, UPPER(V3242.VAL), V3244.LISTVAL_ID
    FROM LINKS LP442
    JOIN VALS V3242 ON V3242.OBJ_ID = LP442.OBJ_ID AND V3242.PARAM_ID IN (3242, 3250) AND V3242.IS_DEL = 0
    JOIN VALL V3244 ON V3244.OBJ_ID = LP442.OBJ_ID AND V3244.PARAM_ID IN (3244, 3251) AND V3244.IS_DEL = 0
    JOIN LINKS LP441 ON LP441.OBJ_ID = LP442.PARENT_ID AND LP441.PARENT_TYPE_ID = 441 AND LP441.DATE_DEL IS NULL
    JOIN VALI V3211 ON V3211.OBJ_ID = LP441.PARENT_ID AND V3211.PARAM_ID = 3211 AND V3211.IS_DEL = 0
    JOIN LINKS LP432 ON LP432.OBJ_ID = LP441.PARENT_ID AND LP432.PARENT_TYPE_ID = 432 AND LP432.DATE_DEL IS NULL
    WHERE LP442.OBJ_ID = :I$PARAM_ID AND LP442.PARENT_TYPE_ID = 442 AND LP442.DATE_DEL IS NULL
    INTO :V$SECTION_ID, :V$YEAR, :V$NAME, :V$UNITS;

    V$DATE = '20.09.' || V$YEAR;
  END
  ELSE
  BEGIN
    -- Берем последнюю версию ГЗ для указанного года
    -- сам показатель нас не интересует
    SELECT FIRST 1 L442.OBJ_ID
    FROM LINKS L441
    JOIN VALI V3211 ON V3211.OBJ_ID = L441.OBJ_ID AND V3211.PARAM_ID = 3211 AND V3211.IS_DEL = 0 AND V3211.VAL = :I$YEAR
    JOIN VALL V3214 ON V3214.OBJ_ID = L441.OBJ_ID AND V3214.PARAM_ID = 3214 AND V3214.IS_DEL = 0
    JOIN LINKS L442 ON L442.PARENT_ID = L441.OBJ_ID AND L442.OBJ_TYPE_ID = 442 AND L442.DATE_DEL IS NULL
    JOIN VALS V3221 ON V3221.OBJ_ID = L442.OBJ_ID AND V3221.PARAM_ID = 3221 AND V3221.IS_DEL = 0 AND V3221.SVAL = :I$PARAM_CODE
    WHERE L441.PARENT_ID = :I$OU_ID AND L441.OBJ_TYPE_ID = 441 AND L441.DATE_DEL IS NULL
    ORDER BY V3214.LISTVAL_ID DESC
    INTO :V$SECTION_ID;

    V$NAME = 'КОЛИЧЕСТВО ОБУЧАЮЩИХСЯ';
    V$UNITS = 13847;

    V$DATE = '20.09.' || I$YEAR;
  END

  -- Число обучающихся (варианты: Численность обучающихся, число/численность детей, контингент)
  -- берем данные на 31.12 указанного года
  IF((POSITION('ЧИСЛ' IN V$NAME) > 0 AND (POSITION('ОБУЧАЮЩИХСЯ' IN V$NAME) > 0 OR POSITION('ДЕТЕЙ' IN V$NAME) > 0)) OR POSITION('КОНТИНГЕНТ' IN V$NAME) > 0) THEN
  BEGIN
    IF(V$UNITS = 13662) THEN
    BEGIN
      -- Единицы = штука
      SELECT COUNT(DISTINCT V3427.VAL)
      FROM LINKS L495
      JOIN VALR V3427 ON V3427.OBJ_ID = L495.OBJ_ID AND V3427.PARAM_ID = 3427 AND V3427.IS_DEL = 0
      JOIN OBJECTS OBJ ON OBJ.OBJ_ID = V3427.VAL AND OBJ.TYPE_ID = 400
      WHERE L495.PARENT_ID = :V$SECTION_ID AND L495.OBJ_TYPE_ID = 495 AND L495.DATE_DEL IS NULL
      INTO :RESULT;
    END
    ELSE
    BEGIN
      -- Все остальное по барабану, считаем человек (предполагается 13847)
      -- Изменено: теперь считаем не про прямой связи с УП, а через участников #495
      RESULT = 0;
      FOR
        SELECT DISTINCT V3427.VAL, OBJ.TYPE_ID
        FROM LINKS L495
        JOIN VALR V3427 ON V3427.OBJ_ID = L495.OBJ_ID AND V3427.PARAM_ID = 3427 AND V3427.IS_DEL = 0
        JOIN OBJECTS OBJ ON OBJ.OBJ_ID = V3427.VAL
        WHERE L495.PARENT_ID = :V$SECTION_ID AND L495.OBJ_TYPE_ID = 495 AND L495.DATE_DEL IS NULL
        INTO :V$MEMBER_ID, :V$MEMBER_TYPE
      DO
      BEGIN
        IF(V$MEMBER_TYPE = 10) THEN RESULT = RESULT + 1;
        ELSE IF(V$MEMBER_TYPE = 2) THEN
          RESULT = RESULT + (
            SELECT COUNT(DISTINCT M.PERSON_ID)
            FROM PERSON_MOVEMENTS M
            WHERE M.DATE_DEL IS NULL AND M.GROUP_TYPE_ID = 9 AND M.DATE_IN <= :V$DATE AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :V$DATE)
          );
        ELSE IF(V$MEMBER_TYPE = 7) THEN
        BEGIN
          SELECT FIRST 1 V43.LISTVAL_ID
          FROM VALL V43
          WHERE V43.OBJ_ID = :V$MEMBER_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0
          INTO :V$STAGE_ID;
          RESULT = RESULT + (
            SELECT COUNT(DISTINCT M.PERSON_ID)
            FROM PERSON_MOVEMENTS M
            WHERE M.DATE_DEL IS NULL AND M.STAGE_ID = :V$STAGE_ID AND M.GROUP_TYPE_ID = 9 AND M.LEVEL_ID = :V$STAGE_ID AND M.DATE_IN <= :V$DATE
              AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :V$DATE)
          );
        END
        ELSE IF(V$MEMBER_TYPE = 8) THEN
        BEGIN
          SELECT FIRST 1 V49.LISTVAL_ID
          FROM VALL V49
          WHERE V49.OBJ_ID = :V$MEMBER_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
          INTO :V$STAGE_ID;
          RESULT = RESULT + (
            SELECT COUNT(DISTINCT M.PERSON_ID)
            FROM PERSON_MOVEMENTS M
            WHERE M.DATE_DEL IS NULL AND M.STAGE_ID = :V$STAGE_ID AND M.GROUP_TYPE_ID = 9 AND M.STAGE_ID = :V$STAGE_ID AND M.DATE_IN <= :V$DATE
              AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :V$DATE)
          );
        END
        ELSE IF(V$MEMBER_TYPE = 9) THEN
          RESULT = RESULT + (
            SELECT COUNT(DISTINCT M.PERSON_ID)
            FROM PERSON_MOVEMENTS M
            WHERE M.DATE_DEL IS NULL AND M.GROUP_TYPE_ID = 9 AND M.GROUP_ID = :V$MEMBER_ID AND M.DATE_IN <= :V$DATE AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :V$DATE)
          );
        ELSE IF(V$MEMBER_TYPE = 400) THEN
          RESULT = RESULT + (
            SELECT COUNT(DISTINCT M.PERSON_ID)
            FROM LINKS L54
            JOIN LINKS L256 ON L256.PARENT_ID = L54.OBJ_ID AND L256.OBJ_TYPE_ID = 256 AND L256.DATE_DEL IS NULL
            JOIN PERSON_MOVEMENTS M ON M.DATE_DEL IS NULL AND M.GROUP_ID = L256.OBJ_ID AND M.DATE_IN <= :V$DATE AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :V$DATE)
            WHERE L54.PARENT_ID = :V$MEMBER_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
          );
      END
    END
  END
  ELSE IF(POSITION('ВЫПОЛНЕНИЕ' IN V$NAME) > 0 AND POSITION('ПРОГРАММ' IN V$NAME) > 0) THEN
  BEGIN
    IF(V$UNITS = 13662) THEN
      -- Единицы = штука
      SELECT COUNT(DISTINCT V3427.VAL)
      FROM LINKS L495
      JOIN VALR V3427 ON V3427.OBJ_ID = L495.OBJ_ID AND V3427.PARAM_ID = 3427 AND V3427.IS_DEL = 0
      JOIN OBJECTS OBJ ON OBJ.OBJ_ID = V3427.VAL AND OBJ.TYPE_ID = 400
      WHERE L495.PARENT_ID = :V$SECTION_ID AND L495.OBJ_TYPE_ID = 495 AND L495.DATE_DEL IS NULL
      INTO :RESULT;
    ELSE
      -- Проценты - пока игнорируем
      RESULT = NULL;
  END
  ELSE IF(POSITION('ОБЕСПЕЧЕННОСТ' IN V$NAME) > 0 AND POSITION('КАДР' IN V$NAME) > 0) THEN
  BEGIN
    IF(V$UNITS = 13847) THEN
      -- Единица = Человек, считаем количество педагогических сотрудников
      SELECT COUNT(DISTINCT L14.OBJ_ID)
      FROM LINKS L14
      JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
      JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
      JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0 AND V73.VAL <= :V$DATE
      LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
      LEFT JOIN DO_FUNC(LP13.PARENT_ID, 400) PD ON 1 = 1
      WHERE L14.PARENT_TYPE_ID IN (2, 84) AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL AND (V74.VAL IS NULL OR V74.VAL >= :V$DATE) AND PD.VAL = 'Да'
      INTO :RESULT;
    ELSE
      -- Проценты - пока игнорируем
      RESULT = NULL;
  END

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GZ_COPY (
    I$OBJ_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    CAPTION VARCHAR(1000))
AS
declare variable V$FOLDER_ID bigint;
declare variable V$OBJ_ID bigint;
declare variable V$OBJ_ID2 bigint;
declare variable V$NEW_SECTION_ID bigint;
declare variable V$TYPE_ID2 bigint;
declare variable T bigint;
begin

  -- Копировать можно задания даже из архивной папки, но помещаться они будут все равно в основную папку

  -- Свойства самого задания будут по-умолчанию
  SELECT FIRST 1 L432.OBJ_ID
  FROM LINKS L2
  JOIN LINKS L432 ON L432.PARENT_ID = L2.OBJ_ID AND L432.OBJ_TYPE_ID = 432 AND L432.DATE_DEL IS NULL
  JOIN VALI V3210 ON V3210.OBJ_ID = L432.OBJ_ID AND V3210.PARAM_ID = 3210 AND V3210.IS_DEL = 0 AND V3210.VAL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$FOLDER_ID;

  SELECT OBJ_ID FROM OBJECT_ADD(:V$FOLDER_ID, 441, NULL, NULL, :I$USER_ID) INTO :OBJ_ID;

  -- Ставим текущий год
  SELECT 1 FROM VAL_ADD(3211, :OBJ_ID, EXTRACT(YEAR FROM CURRENT_DATE) + 1) INTO :T;

  -- Копируем все вложенные объекты
  FOR
    SELECT L.OBJ_ID
    FROM LINKS L
    WHERE L.PARENT_ID = :I$OBJ_ID AND L.OBJ_TYPE_ID = 442 AND L.DATE_DEL IS NULL
    ORDER BY L.COST
    INTO :V$OBJ_ID
  DO
  BEGIN
    SELECT OBJ_ID FROM OBJECT_COPY(:OBJ_ID, :V$OBJ_ID) INTO :V$NEW_SECTION_ID;

    FOR
      SELECT L.OBJ_ID, L.OBJ_TYPE_ID
      FROM LINKS L
      WHERE L.PARENT_ID = :V$OBJ_ID AND L.DATE_DEL IS NULL
      ORDER BY L.COST
      INTO :V$OBJ_ID2, :V$TYPE_ID2
    DO
    BEGIN
      IF(V$TYPE_ID2 = 400) THEN
      BEGIN
        SELECT 1 FROM OBJECT_ADD_LINK(:V$NEW_SECTION_ID, :V$OBJ_ID2, :V$TYPE_ID2) INTO :T;
      END
      ELSE
      BEGIN
        SELECT 1 FROM OBJECT_COPY(:V$NEW_SECTION_ID, :V$OBJ_ID2) INTO :T;

        -- Показатели обьема надо сдвинуть на год !!!
        IF(V$TYPE_ID2 = 443) THEN
        BEGIN
        END
        IF(V$TYPE_ID2 = 444) THEN
        BEGIN
        END
      END
    END
  END

  SELECT CAPTION FROM OBJECT_CAPTION_GET(:OBJ_ID) INTO :CAPTION;

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GZ_DELETE_CHECK (
    I$OBJ_ID BIGINT,
    I$OBJ_TYPE_ID BIGINT)
AS
declare variable V$GZ_ID bigint;
begin

  -- DATE_DEL не сверяем, чтобы при рекурсивном удалении все не слетело

  IF(I$OBJ_TYPE_ID = 441) THEN V$GZ_ID = I$OBJ_ID;
  ELSE IF(I$OBJ_TYPE_ID = 442) THEN
    SELECT FIRST 1 LP441.PARENT_ID
    FROM LINKS LP441
    WHERE LP441.OBJ_ID = :I$OBJ_ID AND LP441.PARENT_TYPE_ID = 441
    INTO :V$GZ_ID;
  ELSE
    SELECT FIRST 1 LP441.PARENT_ID
    FROM LINKS LP442
    JOIN LINKS LP441 ON LP441.OBJ_ID = LP442.PARENT_ID AND LP441.PARENT_TYPE_ID = 441
    WHERE LP442.OBJ_ID = :I$OBJ_ID AND LP442.PARENT_TYPE_ID = 442
    INTO :V$GZ_ID;

  IF(NOT EXISTS(
    SELECT FIRST 1 1
    FROM VALL
    WHERE OBJ_ID = :V$GZ_ID AND PARAM_ID = 3214 AND IS_DEL = 0 AND LISTVAL_ID = 13502
  ))
  THEN EXCEPTION DATA_ERROR 'Удалять Государственное Задание или его элементы можно только в статусе проекта (' || I$OBJ_TYPE_ID || ')';

  -- Нельзя удалять задание, если у него есть дочерние задания
  IF(EXISTS(
    SELECT FIRST 1 1
    FROM VALS V
    JOIN LINKS LP432 ON LP432.OBJ_ID = V.OBJ_ID AND LP432.PARENT_TYPE_ID = 432 AND LP432.DATE_DEL IS NULL
    WHERE V.VAL = :V$GZ_ID AND V.PARAM_ID = 3241 AND V.IS_DEL = 0
  ))
  THEN EXCEPTION DATA_ERROR 'Нельзя удалять Задание, если есть унаследованные от него варианты';

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GZ_FUNC (
    I$OBJ_ID BIGINT,
    I$PARAM_ID BIGINT)
RETURNS (
    VAL VARCHAR(1000),
    I BIGINT)
AS
begin

  IF(I$PARAM_ID = 3215) THEN
  BEGIN
    -- Кол-во услуг
    SELECT COUNT(*)
    FROM LINKS L442
    JOIN VALL V3225 ON V3225.OBJ_ID = L442.OBJ_ID AND V3225.PARAM_ID = 3225 AND V3225.IS_DEL = 0 AND V3225.LISTVAL_ID = 13508
    WHERE L442.PARENT_ID = :I$OBJ_ID AND L442.OBJ_TYPE_ID = 442 AND L442.DATE_DEL IS NULL
    INTO :I;
    VAL = I;
  END
  ELSE IF(I$PARAM_ID = 3216) THEN
  BEGIN
    -- Кол-во работ
    SELECT COUNT(*)
    FROM LINKS L442
    JOIN VALL V3225 ON V3225.OBJ_ID = L442.OBJ_ID AND V3225.PARAM_ID = 3225 AND V3225.IS_DEL = 0 AND V3225.LISTVAL_ID = 13509
    WHERE L442.PARENT_ID = :I$OBJ_ID AND L442.OBJ_TYPE_ID = 442 AND L442.DATE_DEL IS NULL
    INTO :I;
    VAL = I;
  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GZ_MEMBERS_GET (
    I$OBJ_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
declare variable V$OBJ_ID bigint;
declare variable V$REF_ID bigint;
declare variable V$NAME varchar(1000);
declare variable V$OWNER_TYPE bigint;
declare variable V$TYPE_ID bigint;
declare variable V$YEAR integer;
begin

  SELECT TYPE_ID
  FROM OBJECTS
  WHERE OBJ_ID = :I$OBJ_ID
  INTO :V$OWNER_TYPE;

  TAG_NAME = 'items::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    -- Все участники ГЗ
    SELECT L495.OBJ_ID, V3427.VAL, OBJ.TYPE_ID, V3428.VAL, NULL
    FROM LINKS L495
    JOIN VALR V3427 ON V3427.OBJ_ID = L495.OBJ_ID AND V3427.PARAM_ID = 3427 AND V3427.IS_DEL = 0
    JOIN OBJECTS OBJ ON OBJ.OBJ_ID = V3427.VAL
    JOIN VALS V3428 ON V3428.OBJ_ID = L495.OBJ_ID AND V3428.PARAM_ID = 3428 AND V3428.IS_DEL = 0
    WHERE L495.PARENT_ID = :I$OBJ_ID AND L495.OBJ_TYPE_ID = 495 AND L495.DATE_DEL IS NULL AND :V$OWNER_TYPE = 442
    -- Сами ГЗ (обратная выборка)
    ORDER BY 3, 4
    INTO :V$OBJ_ID, :V$REF_ID, :V$TYPE_ID, :V$NAME, :V$YEAR
  DO
  BEGIN
    TAG_NAME = 'items:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'items:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'items:r:ref_id';
    VAL = V$REF_ID;
    SUSPEND;
    TAG_NAME = 'items:r:type_id';
    VAL = V$TYPE_ID;
    SUSPEND;
    TAG_NAME = 'items:r:name';
    VAL = V$NAME;
    SUSPEND;
    TAG_NAME = 'items:r:year';
    VAL = V$YEAR;
    SUSPEND;
  END

  -- Список возможных участников для выбора
  IF(V$OWNER_TYPE <> 442) THEN EXIT;

  TAG_NAME = 'selection::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L2.OBJ_ID, L2.OBJ_TYPE_ID, C.SORT_ORDER, C.CAPTION
    FROM LINKS L2
    LEFT JOIN OBJECT_CAPTION_GET(L2.OBJ_ID) C ON 1 = 1
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    UNION
    SELECT L7.OBJ_ID, L7.OBJ_TYPE_ID, C.SORT_ORDER, C.CAPTION
    FROM LINKS L2
    JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    LEFT JOIN OBJECT_CAPTION_GET(L7.OBJ_ID) C ON 1 = 1
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    UNION
    SELECT L8.OBJ_ID, L8.OBJ_TYPE_ID, C.SORT_ORDER, C.CAPTION
    FROM LINKS L2
    JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    LEFT JOIN OBJECT_CAPTION_GET(L8.OBJ_ID) C ON 1 = 1
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    UNION
    SELECT L9.OBJ_ID, L9.OBJ_TYPE_ID, C.SORT_ORDER, C.CAPTION
    FROM LINKS L2
    JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
    LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C ON 1 = 1
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    UNION
    SELECT L10.OBJ_ID, L10.OBJ_TYPE_ID, CX.SORT_ORDER, C.CAPTION
    FROM LINKS L2
    JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
    LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) CX ON 1 = 1
    JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    LEFT JOIN OBJECT_CAPTION_GET(L10.OBJ_ID) C ON 1 = 1
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    UNION
    SELECT L400.OBJ_ID, L400.OBJ_TYPE_ID, C.SORT_ORDER, C.CAPTION
    FROM LINKS L2
    JOIN LINKS L69 ON L69.PARENT_ID = L2.OBJ_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL
    JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
    JOIN LINKS L400 ON L400.PARENT_ID = L57.OBJ_ID AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL
    -- только действующие
    JOIN VALL V3013 ON V3013.OBJ_ID = L400.OBJ_ID AND V3013.PARAM_ID = 3013 AND V3013.IS_DEL = 0 AND V3013.LISTVAL_ID = 11715
    LEFT JOIN OBJECT_CAPTION_GET(L400.OBJ_ID) C ON 1 = 1
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    ORDER BY 2, 3, 4
    INTO :V$OBJ_ID, :V$TYPE_ID, :V$REF_ID, :V$NAME
  DO
  BEGIN
    TAG_NAME = 'selection:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'selection:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'selection:r:type_id';
    VAL = V$TYPE_ID;
    SUSPEND;
    TAG_NAME = 'selection:r:name';
    VAL = V$NAME;
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GZ_MEMBER_SET (
    I$GZ_ID BIGINT,
    I$MEMBER_ID BIGINT,
    I$DELETE SMALLINT,
    I$USER_ID BIGINT)
RETURNS (
    ID BIGINT,
    NAME VARCHAR(1000),
    TYPE_ID BIGINT,
    REF_ID BIGINT,
    "YEAR" INTEGER)
AS
declare variable T bigint;
begin

  -- Запрет редактирования архивных и действующих ГЗ
  SELECT FIRST 1 V3214.LISTVAL_ID
  FROM LINKS LP441
  JOIN VALL V3214 ON V3214.OBJ_ID = LP441.PARENT_ID AND V3214.PARAM_ID = 3214 AND V3214.IS_DEL = 0
  WHERE LP441.OBJ_ID = :I$GZ_ID AND LP441.PARENT_TYPE_ID = 441 AND LP441.DATE_DEL IS NULL
  INTO :T;

  IF(T IS NULL) THEN EXCEPTION DATA_ERROR 'ГЗ не найдено';
  IF(T <> 13502) THEN EXCEPTION DATA_ERROR 'Участников ГЗ можно менять только в статусе проекта';

  REF_ID = I$MEMBER_ID;

  SELECT FIRST 1 L.OBJ_TYPE_ID
  FROM LINKS L
  WHERE L.OBJ_ID = :I$MEMBER_ID AND (L.PARENT_ID IS NULL OR L.PARENT_TYPE_ID IN (2, 7, 8, 9, 57)) AND L.DATE_DEL IS NULL
  INTO :TYPE_ID;

  IF(I$DELETE = 1) THEN
  BEGIN

    SELECT FIRST 1 L495.OBJ_ID
    FROM LINKS L495
    JOIN VALR V3427 ON V3427.OBJ_ID = L495.OBJ_ID AND V3427.PARAM_ID = 3427 AND V3427.IS_DEL = 0 AND V3427.VAL = :I$MEMBER_ID
    WHERE L495.PARENT_ID = :I$GZ_ID AND L495.OBJ_TYPE_ID = 495 AND L495.DATE_DEL IS NULL
    INTO :ID;

    IF(ID IS NOT NULL) THEN
    UPDATE LINKS
    SET DATE_DEL = CURRENT_TIMESTAMP
    WHERE OBJ_ID = :ID;

  END
  ELSE BEGIN

    IF(TYPE_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Выбранный участник не найден и не может быть добавлен';

    SELECT FIRST 1 L495.OBJ_ID
    FROM LINKS L495
    JOIN VALR V3427 ON V3427.OBJ_ID = L495.OBJ_ID AND V3427.PARAM_ID = 3427 AND V3427.IS_DEL = 0 AND V3427.VAL = :I$MEMBER_ID
    WHERE L495.PARENT_ID = :I$GZ_ID AND L495.OBJ_TYPE_ID = 495 AND L495.DATE_DEL IS NULL
    INTO :ID;

    -- Только если уже не добавлен
    IF(ID IS NOT NULL) THEN EXCEPTION DATA_ERROR 'Этот участник уже добавлен';

    SELECT OBJ_ID FROM OBJECT_ADD(:I$GZ_ID, 495) INTO :ID;
    SELECT 1 FROM VAL_ADD(3427, :ID, :I$MEMBER_ID) INTO :T;

    NAME = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$MEMBER_ID, IIF(:TYPE_ID = 10, 23, NULL)));
    SELECT 1 FROM VAL_ADD(3428, :ID, :NAME) INTO :T;
  END

  IF(TYPE_ID = 400) THEN EXECUTE PROCEDURE PLAN_RECALC(:I$MEMBER_ID, NULL);

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GZ_NEXT (
    I$OBJ_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    CAPTION VARCHAR(1000))
AS
declare variable V$FOLDER_ID bigint;
declare variable V$OBJ_ID bigint;
declare variable V$OBJ_ID2 bigint;
declare variable V$NEW_SECTION_ID bigint;
declare variable V$STATE bigint;
declare variable T bigint;
declare variable PN bigint;
declare variable V double precision;
declare variable TMP integer;
declare variable V$TYPE bigint;
begin

  -- Задание можно изменять только в основной рабочей папке, и только в действующем статусе

  -- Свойства самого задания будут по-умолчанию
  SELECT FIRST 1 LP432.PARENT_ID, V3210.VAL, V3214.LISTVAL_ID
  FROM LINKS LP432
  JOIN VALI V3210 ON V3210.OBJ_ID = LP432.PARENT_ID AND V3210.PARAM_ID = 3210 AND V3210.IS_DEL = 0
  JOIN VALL V3214 ON V3214.OBJ_ID = LP432.OBJ_ID AND V3214.PARAM_ID = 3214 AND V3214.IS_DEL = 0
  WHERE LP432.OBJ_ID = :I$OBJ_ID AND LP432.PARENT_TYPE_ID = 432 AND LP432.DATE_DEL IS NULL
  INTO :V$FOLDER_ID, :T, :V$STATE;

  IF(T IS NULL OR T <> 0 OR V$STATE = 13502) THEN EXCEPTION DATA_ERROR 'Изменения можно вносить только для действующих Заданий актуального отчетного периода';

  -- Нет ли уже других копий задания
  IF(EXISTS(
    SELECT FIRST 1 1
    FROM VALR V3241
    JOIN LINKS LP432 ON LP432.OBJ_ID = V3241.OBJ_ID AND LP432.PARENT_TYPE_ID = 432 AND LP432.DATE_DEL IS NULL
    WHERE V3241.PARAM_ID = 3241 AND V3241.IS_DEL = 0 AND V3241.VAL = :I$OBJ_ID
  ))
  THEN EXCEPTION DATA_ERROR 'Можно создавать только одно изменение Задания';

  SELECT OBJ_ID FROM OBJECT_ADD(:V$FOLDER_ID, 441, NULL, NULL, :I$USER_ID) INTO :OBJ_ID;

  -- Ссылка на предыдущий вариант задания
  INSERT INTO VALR (OBJ_ID, PARAM_ID, VAL) VALUES (:OBJ_ID, 3241, :I$OBJ_ID);
  -- Год задания - копируем тот что был
  T = NULL;
  SELECT V3211.VAL
  FROM VALI V3211
  WHERE V3211.OBJ_ID = :I$OBJ_ID AND V3211.PARAM_ID = 3211 AND V3211.IS_DEL = 0
  INTO :T;
  IF(T IS NULL) THEN EXCEPTION DATA_ERROR 'Не указан год Задания';
  SELECT 1 FROM VAL_ADD(3211, :OBJ_ID, :T) INTO :T;

  -- Копируем все вложенные объекты
  FOR
    SELECT L.OBJ_ID
    FROM LINKS L
    WHERE L.PARENT_ID = :I$OBJ_ID AND L.OBJ_TYPE_ID = 442 AND L.DATE_DEL IS NULL
    ORDER BY L.COST
    INTO :V$OBJ_ID
  DO
  BEGIN
    SELECT OBJ_ID FROM OBJECT_COPY(:OBJ_ID, :V$OBJ_ID) INTO :V$NEW_SECTION_ID;

    FOR
      SELECT L.OBJ_ID, L.OBJ_TYPE_ID
      FROM LINKS L
      WHERE L.PARENT_ID = :V$OBJ_ID AND L.DATE_DEL IS NULL
      ORDER BY L.COST
      INTO :V$OBJ_ID2, :V$TYPE
    DO
    BEGIN
      -- Учебные планы не копируются, а только связываются
      IF(V$TYPE = 400) THEN
      SELECT 1 FROM OBJECT_ADD_LINK(:V$NEW_SECTION_ID, :V$OBJ_ID2, 400) INTO :T;
      -- Все остальное копируем, но затем делаем сдвиг показателей на 1 год
      ELSE
      SELECT 1 FROM OBJECT_COPY(:V$NEW_SECTION_ID, :V$OBJ_ID2) INTO :T;

      IF(V$TYPE = 443) THEN
      BEGIN
        PN = 3246;
        WHILE(PN <= 3249) DO
        BEGIN
          V = NULL;
          SELECT VAL FROM VALF WHERE OBJ_ID = :T AND PARAM_ID = :PN AND IS_DEL = 0 INTO :V;
          SELECT 1 FROM VAL_ADD(:PN - 1, :T, :V) INTO :TMP;
          PN = PN + 1;
        END
        -- Фактическое значение и причину - удаляем
        UPDATE VALF SET IS_DEL = 1 WHERE OBJ_ID = :T AND PARAM_ID = 3275 AND IS_DEL = 0;
        UPDATE VALS SET IS_DEL = 1 WHERE OBJ_ID = :T AND PARAM_ID = 3302 AND IS_DEL = 0;
      END

      IF(V$TYPE = 444) THEN
      BEGIN
        PN = 3253;
        WHILE(PN <= 3256) DO
        BEGIN
          V = NULL;
          SELECT VAL FROM VALF WHERE OBJ_ID = :T AND PARAM_ID = :PN AND IS_DEL = 0 INTO :V;
          SELECT 1 FROM VAL_ADD(:PN - 1, :T, :V) INTO :TMP;
          PN = PN + 1;
        END
        -- Фактическое значение и причину - удаляем
        UPDATE VALF SET IS_DEL = 1 WHERE OBJ_ID = :T AND PARAM_ID = 3276 AND IS_DEL = 0;
        UPDATE VALS SET IS_DEL = 1 WHERE OBJ_ID = :T AND PARAM_ID = 3301 AND IS_DEL = 0;
      END

      IF(V$TYPE = 447) THEN
      BEGIN
        PN = 3259;
        WHILE(PN <= 3262) DO
        BEGIN
          V = NULL;
          SELECT VAL FROM VALF WHERE OBJ_ID = :T AND PARAM_ID = :PN AND IS_DEL = 0 INTO :V;
          SELECT 1 FROM VAL_ADD(:PN - 1, :T, :V) INTO :TMP;
          PN = PN + 1;
        END
      END
    END
  END

  SELECT CAPTION FROM OBJECT_CAPTION_GET(:OBJ_ID) INTO :CAPTION;

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GZ_RENUMBER_SECTIONS (
    I$GZ_ID BIGINT)
AS
declare variable V$OBJ_ID bigint;
declare variable N integer;
begin

  -- Перенумеровывам разделы ГЗ
  N = 1;
  FOR
    SELECT L442.OBJ_ID
    FROM LINKS L442
    JOIN VALI V3218 ON V3218.OBJ_ID = L442.OBJ_ID AND V3218.PARAM_ID = 3218 AND V3218.IS_DEL = 0
    WHERE L442.PARENT_ID = :I$GZ_ID AND L442.OBJ_TYPE_ID = 442 AND L442.DATE_DEL IS NULL
    ORDER BY V3218.VAL
    INTO :V$OBJ_ID
  DO
  BEGIN
    UPDATE VALI V3218
    SET VAL = :N
    WHERE V3218.OBJ_ID = :V$OBJ_ID AND V3218.PARAM_ID = 3218 AND V3218.IS_DEL = 0 AND V3218.VAL <> :N;
    N = N + 1;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GZ_REPORT_AGG_VOL (
    I$OBJ_ID BIGINT,
    I$YEAR INTEGER = null)
RETURNS (
    VAL VARCHAR(4000))
AS
declare variable V$TYPE_ID bigint;
declare variable V$INNER smallint;
declare variable V$OBJ_ID bigint;
declare variable V$SECTION_CODE varchar(100);
declare variable V$YEAR integer;
declare variable V$VNAME varchar(400);
declare variable V$SECNAME varchar(400);
declare variable V$CODE1 varchar(100);
declare variable V$CODE2 varchar(100);
declare variable N integer;
declare variable NY integer;
declare variable Y integer;
declare variable V$V1 double precision;
declare variable V$V2 double precision;
declare variable V$V3 double precision;
declare variable V$V4 double precision;
declare variable S2 varchar(40);
begin

  V$INNER = 0;

  IF(I$OBJ_ID < 0) THEN
  BEGIN
    I$OBJ_ID = - I$OBJ_ID;
    V$INNER = 1;
  END

  SELECT TYPE_ID
  FROM OBJECTS
  WHERE OBJ_ID = :I$OBJ_ID
  INTO :V$TYPE_ID;

  -- Если год не заполнен - берем последний год из числа действующих
  IF(I$YEAR IS NULL) THEN
  SELECT FIRST 1 V3211.VAL
  FROM LINKS L2
  JOIN LINKS L432 ON L432.PARENT_ID = L2.OBJ_ID AND L432.OBJ_TYPE_ID = 432 AND L432.DATE_DEL IS NULL
  JOIN LINKS L441 ON L441.PARENT_ID = L432.OBJ_ID AND L441.OBJ_TYPE_ID = 441 AND L441.DATE_DEL IS NULL
  JOIN VALI V3211 ON V3211.OBJ_ID = L441.OBJ_ID AND V3211.PARAM_ID = 3211 AND V3211.IS_DEL = 0
  JOIN VALL V3214 ON V3214.OBJ_ID = L441.OBJ_ID AND V3214.PARAM_ID = 3214 AND V3214.IS_DEL = 0 AND V3214.LISTVAL_ID <> 13502
  WHERE L2.PARENT_ID = :I$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  ORDER BY 1 DESC
  INTO :I$YEAR;

  IF(I$YEAR IS NULL) THEN
  SELECT FIRST 1 V3211.VAL
  FROM LINKS L111
  JOIN LINKS L2 ON L2.PARENT_ID = L111.OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  JOIN LINKS L432 ON L432.PARENT_ID = L2.OBJ_ID AND L432.OBJ_TYPE_ID = 432 AND L432.DATE_DEL IS NULL
  JOIN LINKS L441 ON L441.PARENT_ID = L432.OBJ_ID AND L441.OBJ_TYPE_ID = 441 AND L441.DATE_DEL IS NULL
  JOIN VALI V3211 ON V3211.OBJ_ID = L441.OBJ_ID AND V3211.PARAM_ID = 3211 AND V3211.IS_DEL = 0
  JOIN VALL V3214 ON V3214.OBJ_ID = L441.OBJ_ID AND V3214.PARAM_ID = 3214 AND V3214.IS_DEL = 0 AND V3214.LISTVAL_ID <> 13502
  WHERE L111.PARENT_ID = :I$OBJ_ID AND L111.OBJ_TYPE_ID = 111 AND L111.DATE_DEL IS NULL
  ORDER BY 1 DESC
  INTO :I$YEAR;

  VAL = '';
  IF(V$INNER = 0) THEN
  BEGIN
  VAL = '<!DOCTYPE html>';
  VAL = VAL || '<html lang="ru">';
  VAL = VAL || '<head>';
  VAL = VAL || '<meta charset="utf-8" />';
  VAL = VAL || '<style>';
  VAL = VAL || 'html { font-family: Tahoma, Verdana, Arial;';
  VAL = VAL || 'font-size: 10pt; ';
  VAL = VAL || '} ';
  VAL = VAL || '.title1 { font-size: 150%;';
  VAL = VAL || 'padding: 8px;';
  VAL = VAL || 'margin-bottom: 4px;';
  VAL = VAL || 'font-weight: bold;';
  VAL = VAL || 'background-color: #D4E157;';
  VAL = VAL || '} ';
  VAL = VAL || '.title2 { ';
  VAL = VAL || 'padding: 4px;';
  VAL = VAL || 'font-weight: bold;';
  VAL = VAL || '} ';
  VAL = VAL || 'td { ';
  VAL = VAL || 'padding: 0.25em 0.5em; ';
  VAL = VAL || 'border-right: 1px solid #808080; ';
  VAL = VAL || 'border-bottom: 1px solid #808080; ';
  VAL = VAL || 'max-width: 20rem; ';
  VAL = VAL || '} ';
  VAL = VAL || 'tr:not(.sx) td:first-child { ';
  VAL = VAL || 'border-left: 1px solid #808080; ';
  VAL = VAL || '} ';
  VAL = VAL || 'tr:first-child td { ';
  VAL = VAL || 'border-top: 1px solid #808080; ';
  VAL = VAL || '} ';
  VAL = VAL || '.yb { ';
  VAL = VAL || 'background-color: #B3E5FC; ';
  VAL = VAL || 'font-family: Georgia; ';
  VAL = VAL || '} ';
  VAL = VAL || '.yc { ';
  VAL = VAL || 'background-color: #FFE082; ';
  VAL = VAL || 'font-weight: bold; ';
  VAL = VAL || 'font-family: Georgia; ';
  VAL = VAL || '} ';
  VAL = VAL || '.y1, .y2 { ';
  VAL = VAL || 'background-color: #ECEFF1; ';
  VAL = VAL || 'font-family: Georgia; ';
  VAL = VAL || '} ';
  VAL = VAL || '.cy { ';
  VAL = VAL || 'width: 4rem; ';
  VAL = VAL || 'font-family: Georgia; ';
  VAL = VAL || '} ';
  VAL = VAL || '</style>';

  VAL = VAL || '</head>';
  VAL = VAL || '<body>';
  SUSPEND;

  -- Заголовок отчета
  VAL = '<div class="title1">Отчет по агрегированным показателям услуг/работ</div>';
  END

  VAL = VAL || '<div class="title2">' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$OBJ_ID)) || '</div>';
  VAL = VAL || '<div class="title2">Отчетный период: ' || I$YEAR || ' год</div>';

  -- Заголовок таблицы
  VAL = VAL || '<table class="table" cellspacing="0" cellpadding="0">';

  VAL = VAL || '<tr class="thd fx">';
  VAL = VAL || '<td rowspan="2">№ п/п</td>';
  VAL = VAL || '<td rowspan="2">Наименование государственной услуги (работы)</td>';
  VAL = VAL || '<td rowspan="2">Реестровый номер базовой услуги или работы</td>';
  VAL = VAL || '<td rowspan="2">Показатель объема/качества</td>';
  VAL = VAL || '<td rowspan="2">Год</td>';
  VAL = VAL || '<td colspan="8">Показатели объема ГЗ по годам</td>';
  VAL = VAL || '</tr>';
  VAL = VAL || '<tr class="thd sx">';
  VAL = VAL || '<td class="cy">' || (I$YEAR - 4) || '</td>';
  VAL = VAL || '<td class="cy">' || (I$YEAR - 3) || '</td>';
  VAL = VAL || '<td class="cy">' || (I$YEAR - 2) || '</td>';
  VAL = VAL || '<td class="cy">' || (I$YEAR - 1) || '</td>';
  VAL = VAL || '<td class="cy">' || (I$YEAR + 0) || '</td>';
  VAL = VAL || '<td class="cy">' || (I$YEAR + 1) || '</td>';
  VAL = VAL || '<td class="cy">' || (I$YEAR + 2) || '</td>';
  VAL = VAL || '<td class="cy">' || (I$YEAR + 3) || '</td>';
  VAL = VAL || '</tr>';
  SUSPEND;

  N = 0;
  IF(V$TYPE_ID = 111) THEN
  FOR
    -- Выборка по району
    SELECT DISTINCT V3235.SVAL, V3242.SVAL
    FROM LINKS L2
    JOIN LINKS L432 ON L432.PARENT_ID = L2.OBJ_ID AND L432.OBJ_TYPE_ID = 432 AND L432.DATE_DEL IS NULL
    JOIN LINKS L441 ON L441.PARENT_ID = L432.OBJ_ID AND L441.OBJ_TYPE_ID = 441 AND L441.DATE_DEL IS NULL
    JOIN VALI V3211 ON V3211.OBJ_ID = L441.OBJ_ID AND V3211.PARAM_ID = 3211 AND V3211.IS_DEL = 0 AND V3211.VAL >= :I$YEAR - 3 AND V3211.VAL <= :I$YEAR + 1
    JOIN VALL V3214 ON V3214.OBJ_ID = L441.OBJ_ID AND V3214.PARAM_ID = 3214 AND V3214.IS_DEL = 0
    JOIN LINKS L442 ON L442.PARENT_ID = L441.OBJ_ID AND L442.OBJ_TYPE_ID = 442 AND L442.DATE_DEL IS NULL
    JOIN VALS V3235 ON V3235.OBJ_ID = L442.OBJ_ID AND V3235.PARAM_ID = 3235 AND V3235.IS_DEL = 0
    JOIN LINKS L443 ON L443.PARENT_ID = L442.OBJ_ID AND L443.OBJ_TYPE_ID = 443 AND L443.DATE_DEL IS NULL
    JOIN VALS V3242 ON V3242.OBJ_ID = L443.OBJ_ID AND V3242.PARAM_ID = 3242 AND V3242.IS_DEL = 0
    -- Только кумулятивные единицы измерения - штуки, человеки, часы
    JOIN VALL V3244 ON V3244.OBJ_ID = L443.OBJ_ID AND V3244.PARAM_ID = 3244 AND V3244.IS_DEL = 0 AND V3244.LISTVAL_ID IN (13826, 13847, 13662, 13627)
    WHERE L2.PARENT_ID = :I$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      AND (V3214.LISTVAL_ID <> 13502 OR V3211.VAL = :I$YEAR + 1)
    ORDER BY 1, 2
    INTO :V$SECTION_CODE, :V$VNAME
  DO
  BEGIN
    -- Берем первый попавшийся показатель из данной группы, чтобы получить название
    -- Если начинается с цифр, обрезаем до первого пробела !!!
    SELECT FIRST 1 V3220.VAL
    FROM LINKS L2
    JOIN LINKS L432 ON L432.PARENT_ID = L2.OBJ_ID AND L432.OBJ_TYPE_ID = 432 AND L432.DATE_DEL IS NULL
    JOIN LINKS L441 ON L441.PARENT_ID = L432.OBJ_ID AND L441.OBJ_TYPE_ID = 441 AND L441.DATE_DEL IS NULL
    JOIN VALI V3211 ON V3211.OBJ_ID = L441.OBJ_ID AND V3211.PARAM_ID = 3211 AND V3211.IS_DEL = 0 AND V3211.VAL >= :I$YEAR - 3 AND V3211.VAL <= :I$YEAR + 1
    JOIN VALL V3214 ON V3214.OBJ_ID = L441.OBJ_ID AND V3214.PARAM_ID = 3214 AND V3214.IS_DEL = 0
    JOIN VALL V3274 ON V3274.OBJ_ID = L441.OBJ_ID AND V3274.PARAM_ID = 3274 AND V3274.IS_DEL = 0
    JOIN LINKS L442 ON L442.PARENT_ID = L441.OBJ_ID AND L442.OBJ_TYPE_ID = 442 AND L442.DATE_DEL IS NULL
    JOIN VALS V3235 ON V3235.OBJ_ID = L442.OBJ_ID AND V3235.PARAM_ID = 3235 AND V3235.IS_DEL = 0 AND V3235.SVAL = :V$SECTION_CODE
    JOIN LINKS L443 ON L443.PARENT_ID = L442.OBJ_ID AND L443.OBJ_TYPE_ID = 443 AND L443.DATE_DEL IS NULL
    JOIN VALS V3242 ON V3242.OBJ_ID = L443.OBJ_ID AND V3242.PARAM_ID = 3242 AND V3242.IS_DEL = 0 AND V3242.SVAL = :V$VNAME
    -- Только кумулятивные единицы измерения - штуки, человеки, часы
    JOIN VALL V3244 ON V3244.OBJ_ID = L443.OBJ_ID AND V3244.PARAM_ID = 3244 AND V3244.IS_DEL = 0 AND V3244.LISTVAL_ID IN (13826, 13847, 13662, 13627)
    JOIN VALS V3220 ON V3220.OBJ_ID = L442.OBJ_ID AND V3220.PARAM_ID = 3220 AND V3220.IS_DEL = 0
    WHERE L2.PARENT_ID = :I$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      AND ((V3214.LISTVAL_ID <> 13502 AND V3274.LISTVAL_ID = 2) OR V3211.VAL = :I$YEAR + 1)
    INTO :V$SECNAME;

    -- Всегда делаем 5 строк

    VAL = '<tr class="v">';
    VAL = VAL || '<td rowspan="5">' || N || '</td>';
    VAL = VAL || '<td rowspan="5">' || V$SECNAME || '</td>';
    VAL = VAL || '<td rowspan="5">' || V$SECTION_CODE || '</td>';
    VAL = VAL || '<td rowspan="5">' || V$VNAME || '</td>';
    SUSPEND;

    NY = 1;
    WHILE (NY <= 5) DO
    BEGIN
      -- В первой строке блока продолжаем, в последующих начинаем новую строку
      IF(NY = 1) THEN VAL = ''; ELSE VAL = '<tr class="v nx">';

      V$V1 = NULL;
      V$V2 = NULL;
      V$V3 = NULL;
      V$V4 = NULL;
      V$YEAR = I$YEAR - 4 + NY;
      VAL = VAL || '<td>' || V$YEAR || '</td>';

      SELECT SUM(V3245.VAL), SUM(V3247.VAL), SUM(V3248.VAL), SUM(V3249.VAL)
      FROM LINKS L2
      JOIN LINKS L432 ON L432.PARENT_ID = L2.OBJ_ID AND L432.OBJ_TYPE_ID = 432 AND L432.DATE_DEL IS NULL
      JOIN LINKS L441 ON L441.PARENT_ID = L432.OBJ_ID AND L441.OBJ_TYPE_ID = 441 AND L441.DATE_DEL IS NULL
      JOIN VALI V3211 ON V3211.OBJ_ID = L441.OBJ_ID AND V3211.PARAM_ID = 3211 AND V3211.IS_DEL = 0 AND V3211.VAL = :V$YEAR
      JOIN VALL V3214 ON V3214.OBJ_ID = L441.OBJ_ID AND V3214.PARAM_ID = 3214 AND V3214.IS_DEL = 0
      JOIN VALL V3274 ON V3274.OBJ_ID = L441.OBJ_ID AND V3274.PARAM_ID = 3274 AND V3274.IS_DEL = 0
      JOIN LINKS L442 ON L442.PARENT_ID = L441.OBJ_ID AND L442.OBJ_TYPE_ID = 442 AND L442.DATE_DEL IS NULL
      JOIN VALS V3235 ON V3235.OBJ_ID = L442.OBJ_ID AND V3235.PARAM_ID = 3235 AND V3235.IS_DEL = 0 AND V3235.SVAL = :V$SECTION_CODE
      JOIN LINKS L443 ON L443.PARENT_ID = L442.OBJ_ID AND L443.OBJ_TYPE_ID = 443 AND L443.DATE_DEL IS NULL
      JOIN VALS V3242 ON V3242.OBJ_ID = L443.OBJ_ID AND V3242.PARAM_ID = 3242 AND V3242.IS_DEL = 0 AND V3242.SVAL = :V$VNAME
      -- Только кумулятивные единицы измерения - штуки, человеки, часы
      JOIN VALL V3244 ON V3244.OBJ_ID = L443.OBJ_ID AND V3244.PARAM_ID = 3244 AND V3244.IS_DEL = 0 AND V3244.LISTVAL_ID IN (13826, 13847, 13662, 13627)
      -- Показатели
      LEFT JOIN VALF V3245 ON V3245.OBJ_ID = L443.OBJ_ID AND V3245.PARAM_ID = 3245 AND V3245.IS_DEL = 0
      LEFT JOIN VALF V3247 ON V3247.OBJ_ID = L443.OBJ_ID AND V3247.PARAM_ID = 3247 AND V3247.IS_DEL = 0
      LEFT JOIN VALF V3248 ON V3248.OBJ_ID = L443.OBJ_ID AND V3248.PARAM_ID = 3248 AND V3248.IS_DEL = 0
      LEFT JOIN VALF V3249 ON V3249.OBJ_ID = L443.OBJ_ID AND V3249.PARAM_ID = 3249 AND V3249.IS_DEL = 0
      WHERE L2.PARENT_ID = :I$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
        AND ((V3214.LISTVAL_ID <> 13502 AND V3274.LISTVAL_ID = 2) OR V3211.VAL = :I$YEAR + 1)
      INTO :V$V1, :V$V2, :V$V3, :V$V4;

      -- Пустые ячейки до данных
      Y = I$YEAR - 3;
      WHILE(Y < V$YEAR) DO BEGIN Y = Y + 1; VAL = VAL || '<td></td>'; END

      -- Сами данные
      S2 = CAST(V$V1 AS NUMERIC(18, 0));
      VAL = VAL || '<td class="yb">' || COALESCE(S2, '-') || '</td>';
      S2 = CAST(V$V2 AS NUMERIC(18, 0));
      VAL = VAL || '<td class="yc">' || COALESCE(S2, '-') || '</td>';
      S2 = CAST(V$V3 AS NUMERIC(18, 0));
      VAL = VAL || '<td class="y1">' || COALESCE(S2, '-') || '</td>';
      S2 = CAST(V$V4 AS NUMERIC(18, 0));
      VAL = VAL || '<td class="y2">' || COALESCE(S2, '-') || '</td>';
      Y = Y + 3;

      -- Пустые ячейки после данных
      WHILE(Y <= I$YEAR + 3) DO BEGIN Y = Y + 1; VAL = VAL || '<td></td>'; END

      VAL = VAL || '</tr>';
      NY = NY + 1;
      SUSPEND;
    END

    N = N + 1;

  END
  ELSE
  BEGIN
    FOR
      SELECT L111.OBJ_ID
      FROM LINKS L111
      LEFT JOIN OBJECT_CAPTION_GET(L111.OBJ_ID) C ON 1 = 1
      WHERE L111.PARENT_ID = :I$OBJ_ID AND L111.OBJ_TYPE_ID = 111 AND L111.DATE_DEL IS NULL
      ORDER BY C.CAPTION
      INTO :V$OBJ_ID
    DO
    BEGIN
      FOR 
        SELECT V.VAL
        FROM GZ_REPORT_AGG_VOL(0 - :V$OBJ_ID, :I$YEAR) V
        INTO :VAL
      DO
      BEGIN
        SUSPEND;
      END
    END
  END

  IF(V$INNER = 0) THEN VAL = '</table></body></html>'; ELSE VAL = '</table>';
  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GZ_REPORT_DATA (
    I$GZ_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
declare variable V$SECTION_ID bigint;
declare variable V$OBJ_ID bigint;
declare variable V$UNITS bigint;
declare variable V$IDM bigint;
declare variable V$ID1 bigint;
declare variable V$ID2 bigint;
declare variable V$ID3 bigint;
declare variable V$PARAM varchar(400);
declare variable FS varchar(4000);
declare variable S varchar(1000);
declare variable S2 varchar(400);
declare variable S3 varchar(1000);
declare variable S4 varchar(400);
declare variable S5 varchar(400);
declare variable S6 varchar(400);
declare variable N integer;
declare variable NP integer;
declare variable V double precision;
declare variable VSRC double precision;
declare variable V$Y integer;
begin

  -- Все годы
  TAG_NAME = 'gz_year';
  SELECT V.VAL
  FROM VALI V
  WHERE V.OBJ_ID = :I$GZ_ID AND V.PARAM_ID = 3211 AND V.IS_DEL = 0
  INTO :V$Y;
  IF(V$Y IS NULL) THEN EXCEPTION DATA_ERROR 'Не найдено Задание или не указан год';
  VAL = V$Y;
  SUSPEND;

  TAG_NAME = 'gz_first_year';
  SELECT V.VAL
  FROM VALI V
  WHERE V.OBJ_ID = :I$GZ_ID AND V.PARAM_ID = 3212 AND V.IS_DEL = 0
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'gz_second_year';
  SELECT V.VAL
  FROM VALI V
  WHERE V.OBJ_ID = :I$GZ_ID AND V.PARAM_ID = 3213 AND V.IS_DEL = 0
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'state_id';
  SELECT V.LISTVAL_ID, C.VAL
  FROM VALL V
  LEFT JOIN LISTVAL_TEXT(V.LISTVAL_ID) C ON 1 = 1
  WHERE V.OBJ_ID = :I$GZ_ID AND V.PARAM_ID = 3214 AND V.IS_DEL = 0
  INTO :VAL, :S;
  SUSPEND;

  TAG_NAME = 'state_name';
  VAL = S;
  SUSPEND;

  TAG_NAME = 'approve_name';
  SELECT D.POST, SUBSTRING(D.I FROM 1 FOR 1) || '.' || SUBSTRING(D.O FROM 1 FOR 1) || '. ' || D.F, V5.VAL, A.VAL
  FROM LINKS LP432
  JOIN LINKS LP2 ON LP2.OBJ_ID = LP432.PARENT_ID AND LP2.PARENT_TYPE_ID = 2 AND LP2.DATE_DEL IS NULL
  LEFT JOIN R_SPB_POST_DIRECTOR(LP2.PARENT_ID, 1) D ON 1 = 1
  LEFT JOIN VALS V5 ON V5.PARAM_ID = LP2.PARENT_ID AND V5.PARAM_ID = 5 AND V5.IS_DEL = 0
  LEFT JOIN ADR_GET(27, LP2.PARENT_ID) A ON 1 = 1
  WHERE LP432.OBJ_ID = :I$GZ_ID AND LP432.PARENT_TYPE_ID = 432 AND LP432.DATE_DEL IS NULL
  INTO :S2, :VAL, :S, :S3;
  SUSPEND;

  TAG_NAME = 'approve_post';
  VAL = S2;
  SUSPEND;

  TAG_NAME = 'ou_name_full';
  VAL = S;
  SUSPEND;

  TAG_NAME = 'ou_address';
  VAL = S3;
  SUSPEND;

  -- Дата утверждения текущего задания
  TAG_NAME = 'approve_date_text';
  VAL = NULL;
  SELECT C.VAL
  FROM VALD V3300
  LEFT JOIN DATE2SCRIPT(V3300.VAL) C ON 1 = 1
  WHERE V3300.OBJ_ID = :I$GZ_ID AND V3300.PARAM_ID = 3300 AND V3300.IS_DEL = 0
  INTO :VAL;
  SUSPEND;

  S3 = NULL;
  S4 = NULL;
  S5 = NULL;
  TAG_NAME = 'approve_dates::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L441.OBJ_ID, V3214.LISTVAL_ID, C.VAL, DC.VAL
    FROM LINKS LP432
    JOIN LINKS L441 ON L441.PARENT_ID = LP432.PARENT_ID AND L441.OBJ_TYPE_ID = 441 AND L441.DATE_DEL IS NULL
    JOIN VALI V3211 ON V3211.OBJ_ID = L441.OBJ_ID AND V3211.PARAM_ID = 3211 AND V3211.IS_DEL = 0 AND V3211.VAL = :V$Y
    JOIN VALL V3214 ON V3214.OBJ_ID = L441.OBJ_ID AND V3214.PARAM_ID = 3214 AND V3214.IS_DEL = 0 AND V3214.LISTVAL_ID <> 13502
    LEFT JOIN VALD V3300 ON V3300.OBJ_ID = L441.OBJ_ID AND V3300.PARAM_ID = 3300 AND V3300.IS_DEL = 0
    LEFT JOIN LISTVAL_TEXT(V3214.LISTVAL_ID) C ON 1 = 1
    LEFT JOIN DATE2SCRIPT(V3300.VAL) DC ON 1 = 1
    WHERE LP432.OBJ_ID = :I$GZ_ID AND LP432.PARENT_TYPE_ID = 432 AND LP432.DATE_DEL IS NULL
    ORDER BY V3214.LISTVAL_ID
    INTO :V$OBJ_ID, :V$UNITS, :S, :S2
  DO
  BEGIN
    IF(V$UNITS = 13503) THEN
    BEGIN
      -- Основная дата в списке не выводится
      S3 = S2;
      V$IDM = V$OBJ_ID;
    END
    ELSE
    BEGIN
      IF(V$UNITS = 13504) THEN BEGIN S4 = S2; V$ID1 = V$OBJ_ID; END
      IF(V$UNITS = 13505) THEN BEGIN S5 = S2; V$ID2 = V$OBJ_ID; END
      IF(V$UNITS = 13506) THEN BEGIN S6 = S2; V$ID3 = V$OBJ_ID; END
      TAG_NAME = 'approve_dates:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'approve_dates:r:state';
      VAL = S;
      SUSPEND;
      TAG_NAME = 'approve_dates:r:date_text';
      VAL = S2;
      SUSPEND;
    END
  END
  -- Даты утверждения вариантов
  TAG_NAME = 'main_approve_date_text';
  VAL = S3;
  SUSPEND;
  TAG_NAME = 'c1_approve_date_text';
  VAL = S4;
  SUSPEND;
  TAG_NAME = 'c2_approve_date_text';
  VAL = S5;
  SUSPEND;
  TAG_NAME = 'c3_approve_date_text';
  VAL = S6;
  SUSPEND;

  -- По секциям
  TAG_NAME = 'sections::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L442.OBJ_ID, V3218.VAL
    FROM LINKS L442
    JOIN VALI V3218 ON V3218.OBJ_ID = L442.OBJ_ID AND V3218.PARAM_ID = 3218 AND V3218.IS_DEL = 0
    WHERE L442.PARENT_ID = :I$GZ_ID AND L442.OBJ_TYPE_ID = 442 AND L442.DATE_DEL IS NULL
    INTO :V$SECTION_ID, :N
  DO
  BEGIN
    TAG_NAME = 'sections:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'sections:r:id';
    VAL = V$SECTION_ID;
    SUSPEND;
    TAG_NAME = 'sections:r:index';
    VAL = N;
    SUSPEND;
    TAG_NAME = 'sections:r:name';
    VAL = NULL;
    SELECT V.VAL
    FROM VALS V
    WHERE V.OBJ_ID = :V$SECTION_ID AND V.PARAM_ID = 3220 AND V.IS_DEL = 0
    INTO :VAL;
    FS = VAL; -- формирование полного названия параметра
    SUSPEND;
    TAG_NAME = 'sections:r:reg_num';
    VAL = NULL;
    SELECT V.VAL
    FROM VALS V
    WHERE V.OBJ_ID = :V$SECTION_ID AND V.PARAM_ID = 3221 AND V.IS_DEL = 0
    INTO :VAL;
    FS = COALESCE(VAL || ' ', '') || FS; -- формирование полного названия параметра
    SUSPEND;
    TAG_NAME = 'sections:r:tech_num';
    VAL = NULL;
    SELECT V.VAL
    FROM VALS V
    WHERE V.OBJ_ID = :V$SECTION_ID AND V.PARAM_ID = 3222 AND V.IS_DEL = 0
    INTO :VAL;
    SUSPEND;
    TAG_NAME = 'sections:r:base_num';
    VAL = NULL;
    SELECT V.VAL
    FROM VALS V
    WHERE V.OBJ_ID = :V$SECTION_ID AND V.PARAM_ID = 3235 AND V.IS_DEL = 0
    INTO :VAL;
    SUSPEND;
    TAG_NAME = 'sections:r:okved';
    VAL = NULL;
    SELECT V.VAL
    FROM VALS V
    WHERE V.OBJ_ID = :V$SECTION_ID AND V.PARAM_ID = 3223 AND V.IS_DEL = 0
    INTO :VAL;
    SUSPEND;
    TAG_NAME = 'sections:r:okpd';
    VAL = NULL;
    SELECT V.VAL
    FROM VALS V
    WHERE V.OBJ_ID = :V$SECTION_ID AND V.PARAM_ID = 3224 AND V.IS_DEL = 0
    INTO :VAL;
    SUSPEND;
    TAG_NAME = 'sections:r:kind_id';
    VAL = NULL;
    S = NULL;
    SELECT V.LISTVAL_ID, C.VAL
    FROM VALL V
    LEFT JOIN LISTVAL_TEXT(V.LISTVAL_ID) C ON 1 = 1
    WHERE V.OBJ_ID = :V$SECTION_ID AND V.PARAM_ID = 3225 AND V.IS_DEL = 0
    INTO :VAL, :S;
    SUSPEND;
    TAG_NAME = 'sections:r:kind_name';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'sections:r:content1';
    VAL = NULL;
    SELECT V.VAL
    FROM VALS V
    WHERE V.OBJ_ID = :V$SECTION_ID AND V.PARAM_ID = 3226 AND V.IS_DEL = 0
    INTO :VAL;
    FS = FS || COALESCE('; ' || VAL, ''); -- формирование полного названия параметра
    SUSPEND;
    TAG_NAME = 'sections:r:content2';
    VAL = NULL;
    SELECT V.VAL
    FROM VALS V
    WHERE V.OBJ_ID = :V$SECTION_ID AND V.PARAM_ID = 3227 AND V.IS_DEL = 0
    INTO :VAL;
    FS = FS || COALESCE('; ' || VAL, ''); -- формирование полного названия параметра
    SUSPEND;
    TAG_NAME = 'sections:r:content3';
    VAL = NULL;
    SELECT V.VAL
    FROM VALS V
    WHERE V.OBJ_ID = :V$SECTION_ID AND V.PARAM_ID = 3228 AND V.IS_DEL = 0
    INTO :VAL;
    FS = FS || COALESCE('; ' || VAL, ''); -- формирование полного названия параметра
    SUSPEND;
    TAG_NAME = 'sections:r:term1';
    VAL = NULL;
    SELECT V.VAL
    FROM VALS V
    WHERE V.OBJ_ID = :V$SECTION_ID AND V.PARAM_ID = 3229 AND V.IS_DEL = 0
    INTO :VAL;
    FS = FS || COALESCE('; ' || VAL, ''); -- формирование полного названия параметра
    SUSPEND;
    TAG_NAME = 'sections:r:term2';
    VAL = NULL;
    SELECT V.VAL
    FROM VALS V
    WHERE V.OBJ_ID = :V$SECTION_ID AND V.PARAM_ID = 3230 AND V.IS_DEL = 0
    INTO :VAL;
    FS = FS || COALESCE('; ' || VAL, ''); -- формирование полного названия параметра
    SUSPEND;
    TAG_NAME = 'sections:r:cons_type';
    VAL = NULL;
    SELECT V.VAL
    FROM VALS V
    WHERE V.OBJ_ID = :V$SECTION_ID AND V.PARAM_ID = 3231 AND V.IS_DEL = 0
    INTO :VAL;
    FS = FS || COALESCE('; ' || VAL, ''); -- формирование полного названия параметра
    SUSPEND;
    TAG_NAME = 'sections:r:extra_info';
    VAL = NULL;
    SELECT V.VAL
    FROM VALS V
    WHERE V.OBJ_ID = :V$SECTION_ID AND V.PARAM_ID = 3232 AND V.IS_DEL = 0
    INTO :VAL;
    FS = FS || COALESCE('; ' || VAL, ''); -- формирование полного названия параметра
    SUSPEND;
    TAG_NAME = 'sections:r:content';
    VAL = NULL;
    SELECT V.VAL
    FROM VALS V
    WHERE V.OBJ_ID = :V$SECTION_ID AND V.PARAM_ID = 3233 AND V.IS_DEL = 0
    INTO :VAL;
    SUSPEND;
    TAG_NAME = 'sections:r:result_term';
    VAL = NULL;
    SELECT V.VAL
    FROM VALS V
    WHERE V.OBJ_ID = :V$SECTION_ID AND V.PARAM_ID = 3234 AND V.IS_DEL = 0
    INTO :VAL;
    SUSPEND;
    TAG_NAME = 'sections:r:stop_cond';
    VAL = NULL;
    SELECT V.VAL
    FROM VALS V
    WHERE V.OBJ_ID = :V$SECTION_ID AND V.PARAM_ID = 3236 AND V.IS_DEL = 0
    INTO :VAL;
    SUSPEND;
    TAG_NAME = 'sections:r:stop_term';
    VAL = NULL;
    SELECT V.VAL
    FROM VALS V
    WHERE V.OBJ_ID = :V$SECTION_ID AND V.PARAM_ID = 3237 AND V.IS_DEL = 0
    INTO :VAL;
    SUSPEND;
    TAG_NAME = 'sections:r:report_form';
    VAL = NULL;
    SELECT V.VAL
    FROM VALS V
    WHERE V.OBJ_ID = :V$SECTION_ID AND V.PARAM_ID = 3238 AND V.IS_DEL = 0
    INTO :VAL;
    SUSPEND;
    TAG_NAME = 'sections:r:report_pd';
    VAL = NULL;
    SELECT V.VAL
    FROM VALS V
    WHERE V.OBJ_ID = :V$SECTION_ID AND V.PARAM_ID = 3239 AND V.IS_DEL = 0
    INTO :VAL;
    SUSPEND;
    TAG_NAME = 'sections:r:other';
    VAL = NULL;
    SELECT V.VAL
    FROM VALS V
    WHERE V.OBJ_ID = :V$SECTION_ID AND V.PARAM_ID = 3240 AND V.IS_DEL = 0
    INTO :VAL;
    SUSPEND;

    -- Платность тянем из первого попавшегося показателя
    TAG_NAME = 'sections:r:form';
    VAL = NULL;
    SELECT FIRST 1 C.VAL
    FROM LINKS L443
    JOIN VALL V3243 ON V3243.OBJ_ID = L443.OBJ_ID AND V3243.PARAM_ID = 3243 AND V3243.IS_DEL = 0
    LEFT JOIN LISTVAL_TEXT(V3243.LISTVAL_ID) C ON 1 = 1
    WHERE L443.PARENT_ID = :V$SECTION_ID AND L443.OBJ_TYPE_ID = 443 AND L443.DATE_DEL IS NULL
    INTO :VAL;
    SUSPEND;

    NP = 1;
    TAG_NAME = 'sections:r:volume_params::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT L443.OBJ_ID
      FROM LINKS L443
      WHERE L443.PARENT_ID = :V$SECTION_ID AND L443.OBJ_TYPE_ID = 443 AND L443.DATE_DEL IS NULL
      ORDER BY 1
      INTO :V$OBJ_ID
    DO
    BEGIN
      TAG_NAME = 'sections:r:volume_params:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'sections:r:volume_params:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'sections:r:volume_params:r:index';
      VAL = NP;
      NP = NP + 1;
      SUSPEND;
      TAG_NAME = 'sections:r:volume_params:r:name';
      VAL = NULL;
      SELECT V.VAL
      FROM VALS V
      WHERE V.OBJ_ID = :V$OBJ_ID AND V.PARAM_ID = 3242 AND V.IS_DEL = 0
      INTO :VAL;
      V$PARAM = VAL;
      SUSPEND;
      TAG_NAME = 'sections:r:volume_params:r:fullname';
      VAL = FS;
      SUSPEND;
      TAG_NAME = 'sections:r:volume_params:r:form';
      VAL = NULL;
      SELECT C.VAL
      FROM VALL V
      LEFT JOIN LISTVAL_TEXT(V.LISTVAL_ID) C ON 1 = 1
      WHERE V.OBJ_ID = :V$OBJ_ID AND V.PARAM_ID = 3243 AND V.IS_DEL = 0
      INTO :VAL;
      SUSPEND;
      TAG_NAME = 'sections:r:volume_params:r:unit_name';
      V$UNITS = NULL;
      VAL = NULL;
      SELECT C.VAL, V.LISTVAL_ID
      FROM VALL V
      LEFT JOIN LISTVAL_TEXT(V.LISTVAL_ID) C ON 1 = 1
      WHERE V.OBJ_ID = :V$OBJ_ID AND V.PARAM_ID = 3244 AND V.IS_DEL = 0
      INTO :VAL, :V$UNITS;
      SUSPEND;
      TAG_NAME = 'sections:r:volume_params:r:v1';
      V = NULL;
      SELECT V.VAL
      FROM VALF V
      WHERE V.OBJ_ID = :V$OBJ_ID AND V.PARAM_ID = 3245 AND V.IS_DEL = 0
      INTO :V;
      IF(V$UNITS = 13837) THEN VAL = CAST(V AS NUMERIC(18, 2)); ELSE VAL = CAST(V AS INTEGER);
      SUSPEND;
      TAG_NAME = 'sections:r:volume_params:r:v2';
      V = NULL;
      SELECT V.VAL
      FROM VALF V
      WHERE V.OBJ_ID = :V$OBJ_ID AND V.PARAM_ID = 3246 AND V.IS_DEL = 0
      INTO :V;
      IF(V$UNITS = 13837) THEN VAL = CAST(V AS NUMERIC(18, 2)); ELSE VAL = CAST(V AS INTEGER);
      SUSPEND;
      TAG_NAME = 'sections:r:volume_params:r:v3';
      V = NULL;
      SELECT V.VAL
      FROM VALF V
      WHERE V.OBJ_ID = :V$OBJ_ID AND V.PARAM_ID = 3247 AND V.IS_DEL = 0
      INTO :V;
      VSRC = V;
      IF(V$UNITS = 13837) THEN VAL = CAST(V AS NUMERIC(18, 2)); ELSE VAL = CAST(V AS INTEGER);
      SUSPEND;
      TAG_NAME = 'sections:r:volume_params:r:v4';
      V = NULL;
      SELECT V.VAL
      FROM VALF V
      WHERE V.OBJ_ID = :V$OBJ_ID AND V.PARAM_ID = 3248 AND V.IS_DEL = 0
      INTO :V;
      IF(V$UNITS = 13837) THEN VAL = CAST(V AS NUMERIC(18, 2)); ELSE VAL = CAST(V AS INTEGER);
      SUSPEND;
      TAG_NAME = 'sections:r:volume_params:r:v5';
      V = NULL;
      SELECT V.VAL
      FROM VALF V
      WHERE V.OBJ_ID = :V$OBJ_ID AND V.PARAM_ID = 3249 AND V.IS_DEL = 0
      INTO :V;
      IF(V$UNITS = 13837) THEN VAL = CAST(V AS NUMERIC(18, 2)); ELSE VAL = CAST(V AS INTEGER);
      SUSPEND;

      -- Значения параметра по этапам коррекции
      TAG_NAME = 'sections:r:volume_params:r:vmain';
      V = NULL;
      SELECT FIRST 1 V.VAL
      FROM LINKS L442
      JOIN VALI V3218 ON V3218.OBJ_ID = L442.OBJ_ID AND V3218.PARAM_ID = 3218 AND V3218.IS_DEL = 0 AND V3218.VAL = :N -- тот же раздел !!!
      JOIN LINKS L443 ON L443.PARENT_ID = L442.OBJ_ID AND L443.OBJ_TYPE_ID = 443 AND L443.DATE_DEL IS NULL
      JOIN VALS VN ON VN.OBJ_ID = L443.OBJ_ID AND VN.PARAM_ID = 3242 AND VN.IS_DEL = 0 AND VN.SVAL = :V$PARAM
      JOIN VALF V ON V.OBJ_ID = L443.OBJ_ID AND V.PARAM_ID = 3247 AND V.IS_DEL = 0
      WHERE L442.PARENT_ID = :V$IDM AND L442.OBJ_TYPE_ID = 442 AND L442.DATE_DEL IS NULL
      INTO :V;
      IF(V$UNITS = 13837) THEN VAL = CAST(V AS NUMERIC(18, 2)); ELSE VAL = CAST(V AS INTEGER);
      SUSPEND;
      TAG_NAME = 'sections:r:volume_params:r:vc1';
      V = NULL;
      SELECT FIRST 1 V.VAL
      FROM LINKS L442
      JOIN VALI V3218 ON V3218.OBJ_ID = L442.OBJ_ID AND V3218.PARAM_ID = 3218 AND V3218.IS_DEL = 0 AND V3218.VAL = :N -- тот же раздел !!!
      JOIN LINKS L443 ON L443.PARENT_ID = L442.OBJ_ID AND L443.OBJ_TYPE_ID = 443 AND L443.DATE_DEL IS NULL
      JOIN VALS VN ON VN.OBJ_ID = L443.OBJ_ID AND VN.PARAM_ID = 3242 AND VN.IS_DEL = 0 AND VN.SVAL = :V$PARAM
      JOIN VALF V ON V.OBJ_ID = L443.OBJ_ID AND V.PARAM_ID = 3247 AND V.IS_DEL = 0
      WHERE L442.PARENT_ID = :V$ID1 AND L442.OBJ_TYPE_ID = 442 AND L442.DATE_DEL IS NULL
      INTO :V;
      IF(V$UNITS = 13837) THEN VAL = CAST(V AS NUMERIC(18, 2)); ELSE VAL = CAST(V AS INTEGER);
      SUSPEND;
      TAG_NAME = 'sections:r:volume_params:r:vc2';
      V = NULL;
      SELECT FIRST 1 V.VAL
      FROM LINKS L442
      JOIN VALI V3218 ON V3218.OBJ_ID = L442.OBJ_ID AND V3218.PARAM_ID = 3218 AND V3218.IS_DEL = 0 AND V3218.VAL = :N -- тот же раздел !!!
      JOIN LINKS L443 ON L443.PARENT_ID = L442.OBJ_ID AND L443.OBJ_TYPE_ID = 443 AND L443.DATE_DEL IS NULL
      JOIN VALS VN ON VN.OBJ_ID = L443.OBJ_ID AND VN.PARAM_ID = 3242 AND VN.IS_DEL = 0 AND VN.SVAL = :V$PARAM
      JOIN VALF V ON V.OBJ_ID = L443.OBJ_ID AND V.PARAM_ID = 3247 AND V.IS_DEL = 0
      WHERE L442.PARENT_ID = :V$ID2 AND L442.OBJ_TYPE_ID = 442 AND L442.DATE_DEL IS NULL
      INTO :V;
      IF(V$UNITS = 13837) THEN VAL = CAST(V AS NUMERIC(18, 2)); ELSE VAL = CAST(V AS INTEGER);
      SUSPEND;
      TAG_NAME = 'sections:r:volume_params:r:vc3';
      V = NULL;
      SELECT FIRST 1 V.VAL
      FROM LINKS L442
      JOIN VALI V3218 ON V3218.OBJ_ID = L442.OBJ_ID AND V3218.PARAM_ID = 3218 AND V3218.IS_DEL = 0 AND V3218.VAL = :N -- тот же раздел !!!
      JOIN LINKS L443 ON L443.PARENT_ID = L442.OBJ_ID AND L443.OBJ_TYPE_ID = 443 AND L443.DATE_DEL IS NULL
      JOIN VALS VN ON VN.OBJ_ID = L443.OBJ_ID AND VN.PARAM_ID = 3242 AND VN.IS_DEL = 0 AND VN.SVAL = :V$PARAM
      JOIN VALF V ON V.OBJ_ID = L443.OBJ_ID AND V.PARAM_ID = 3247 AND V.IS_DEL = 0
      WHERE L442.PARENT_ID = :V$ID3 AND L442.OBJ_TYPE_ID = 442 AND L442.DATE_DEL IS NULL
      INTO :V;
      IF(V$UNITS = 13837) THEN VAL = CAST(V AS NUMERIC(18, 2)); ELSE VAL = CAST(V AS INTEGER);
      SUSPEND;

      TAG_NAME = 'sections:r:volume_params:r:result';
      V = NULL;
      SELECT V.VAL
      FROM VALF V
      WHERE V.OBJ_ID = :V$OBJ_ID AND V.PARAM_ID = 3275 AND V.IS_DEL = 0
      INTO :V;
      IF(V$UNITS = 13837) THEN VAL = CAST(V AS NUMERIC(18, 2)); ELSE VAL = CAST(V AS INTEGER);
      SUSPEND;
      TAG_NAME = 'sections:r:volume_params:r:delta';
      VAL = NULL;
      IF(V$UNITS = 13837) THEN VAL = CAST((V - VSRC) AS NUMERIC(18, 2)); ELSE VAL = CAST((V - VSRC) AS INTEGER);
      SUSPEND;
      TAG_NAME = 'sections:r:volume_params:r:reason';
      VAL = NULL;
      SELECT V.VAL
      FROM VALS V
      WHERE V.OBJ_ID = :V$OBJ_ID AND V.PARAM_ID = 3301 AND V.IS_DEL = 0
      INTO :VAL;
      SUSPEND;
    END

    NP = 1;
    TAG_NAME = 'sections:r:qty_params::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT L444.OBJ_ID
      FROM LINKS L444
      WHERE L444.PARENT_ID = :V$SECTION_ID AND L444.OBJ_TYPE_ID = 444 AND L444.DATE_DEL IS NULL
      ORDER BY 1
      INTO :V$OBJ_ID
    DO
    BEGIN
      TAG_NAME = 'sections:r:qty_params:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'sections:r:qty_params:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'sections:r:qty_params:r:index';
      VAL = NP;
      NP = NP + 1;
      SUSPEND;
      TAG_NAME = 'sections:r:qty_params:r:name';
      VAL = NULL;
      SELECT V.VAL
      FROM VALS V
      WHERE V.OBJ_ID = :V$OBJ_ID AND V.PARAM_ID = 3250 AND V.IS_DEL = 0
      INTO :VAL;
      V$PARAM = VAL;
      SUSPEND;
      TAG_NAME = 'sections:r:qty_params:r:fullname';
      VAL = FS;
      SUSPEND;
      TAG_NAME = 'sections:r:qty_params:r:unit_name';
      V$UNITS = NULL;
      VAL = NULL;
      SELECT C.VAL, V.LISTVAL_ID
      FROM VALL V
      LEFT JOIN LISTVAL_TEXT(V.LISTVAL_ID) C ON 1 = 1
      WHERE V.OBJ_ID = :V$OBJ_ID AND V.PARAM_ID = 3251 AND V.IS_DEL = 0
      INTO :VAL, :V$UNITS;
      SUSPEND;
      TAG_NAME = 'sections:r:qty_params:r:v1';
      V = NULL;
      SELECT V.VAL
      FROM VALF V
      WHERE V.OBJ_ID = :V$OBJ_ID AND V.PARAM_ID = 3252 AND V.IS_DEL = 0
      INTO :V;
      IF(V$UNITS = 13837) THEN VAL = CAST(V AS NUMERIC(18, 2)); ELSE VAL = CAST(V AS INTEGER);
      SUSPEND;
      TAG_NAME = 'sections:r:qty_params:r:v2';
      V = NULL;
      SELECT V.VAL
      FROM VALF V
      WHERE V.OBJ_ID = :V$OBJ_ID AND V.PARAM_ID = 3253 AND V.IS_DEL = 0
      INTO :V;
      IF(V$UNITS = 13837) THEN VAL = CAST(V AS NUMERIC(18, 2)); ELSE VAL = CAST(V AS INTEGER);
      SUSPEND;
      TAG_NAME = 'sections:r:qty_params:r:v3';
      V = NULL;
      SELECT V.VAL
      FROM VALF V
      WHERE V.OBJ_ID = :V$OBJ_ID AND V.PARAM_ID = 3254 AND V.IS_DEL = 0
      INTO :V;
      VSRC = V;
      IF(V$UNITS = 13837) THEN VAL = CAST(V AS NUMERIC(18, 2)); ELSE VAL = CAST(V AS INTEGER);
      SUSPEND;
      TAG_NAME = 'sections:r:qty_params:r:v4';
      V = NULL;
      SELECT V.VAL
      FROM VALF V
      WHERE V.OBJ_ID = :V$OBJ_ID AND V.PARAM_ID = 3255 AND V.IS_DEL = 0
      INTO :V;
      IF(V$UNITS = 13837) THEN VAL = CAST(V AS NUMERIC(18, 2)); ELSE VAL = CAST(V AS INTEGER);
      SUSPEND;
      TAG_NAME = 'sections:r:qty_params:r:v5';
      V = NULL;
      SELECT V.VAL
      FROM VALF V
      WHERE V.OBJ_ID = :V$OBJ_ID AND V.PARAM_ID = 3256 AND V.IS_DEL = 0
      INTO :V;
      IF(V$UNITS = 13837) THEN VAL = CAST(V AS NUMERIC(18, 2)); ELSE VAL = CAST(V AS INTEGER);
      SUSPEND;

      -- Значения параметра по этапам коррекции
      TAG_NAME = 'sections:r:qty_params:r:vmain';
      V = NULL;
      SELECT FIRST 1 V.VAL
      FROM LINKS L442
      JOIN VALI V3218 ON V3218.OBJ_ID = L442.OBJ_ID AND V3218.PARAM_ID = 3218 AND V3218.IS_DEL = 0 AND V3218.VAL = :N -- тот же раздел !!!
      JOIN LINKS L444 ON L444.PARENT_ID = L442.OBJ_ID AND L444.OBJ_TYPE_ID = 444 AND L444.DATE_DEL IS NULL
      JOIN VALS VN ON VN.OBJ_ID = L444.OBJ_ID AND VN.PARAM_ID = 3250 AND VN.IS_DEL = 0 AND VN.SVAL = :V$PARAM
      JOIN VALF V ON V.OBJ_ID = L444.OBJ_ID AND V.PARAM_ID = 3254 AND V.IS_DEL = 0
      WHERE L442.PARENT_ID = :V$IDM AND L442.OBJ_TYPE_ID = 442 AND L442.DATE_DEL IS NULL
      INTO :V;
      IF(V$UNITS = 13837) THEN VAL = CAST(V AS NUMERIC(18, 2)); ELSE VAL = CAST(V AS INTEGER);
      SUSPEND;
      TAG_NAME = 'sections:r:qty_params:r:vc1';
      V = NULL;
      SELECT FIRST 1 V.VAL
      FROM LINKS L442
      JOIN VALI V3218 ON V3218.OBJ_ID = L442.OBJ_ID AND V3218.PARAM_ID = 3218 AND V3218.IS_DEL = 0 AND V3218.VAL = :N -- тот же раздел !!!
      JOIN LINKS L444 ON L444.PARENT_ID = L442.OBJ_ID AND L444.OBJ_TYPE_ID = 444 AND L444.DATE_DEL IS NULL
      JOIN VALS VN ON VN.OBJ_ID = L444.OBJ_ID AND VN.PARAM_ID = 3250 AND VN.IS_DEL = 0 AND VN.SVAL = :V$PARAM
      JOIN VALF V ON V.OBJ_ID = L444.OBJ_ID AND V.PARAM_ID = 3254 AND V.IS_DEL = 0
      WHERE L442.PARENT_ID = :V$ID1 AND L442.OBJ_TYPE_ID = 442 AND L442.DATE_DEL IS NULL
      INTO :V;
      IF(V$UNITS = 13837) THEN VAL = CAST(V AS NUMERIC(18, 2)); ELSE VAL = CAST(V AS INTEGER);
      SUSPEND;
      TAG_NAME = 'sections:r:qty_params:r:vc2';
      V = NULL;
      SELECT FIRST 1 V.VAL
      FROM LINKS L442
      JOIN VALI V3218 ON V3218.OBJ_ID = L442.OBJ_ID AND V3218.PARAM_ID = 3218 AND V3218.IS_DEL = 0 AND V3218.VAL = :N -- тот же раздел !!!
      JOIN LINKS L444 ON L444.PARENT_ID = L442.OBJ_ID AND L444.OBJ_TYPE_ID = 444 AND L444.DATE_DEL IS NULL
      JOIN VALS VN ON VN.OBJ_ID = L444.OBJ_ID AND VN.PARAM_ID = 3250 AND VN.IS_DEL = 0 AND VN.SVAL = :V$PARAM
      JOIN VALF V ON V.OBJ_ID = L444.OBJ_ID AND V.PARAM_ID = 3254 AND V.IS_DEL = 0
      WHERE L442.PARENT_ID = :V$ID2 AND L442.OBJ_TYPE_ID = 442 AND L442.DATE_DEL IS NULL
      INTO :V;
      IF(V$UNITS = 13837) THEN VAL = CAST(V AS NUMERIC(18, 2)); ELSE VAL = CAST(V AS INTEGER);
      SUSPEND;
      TAG_NAME = 'sections:r:qty_params:r:vc3';
      V = NULL;
      SELECT FIRST 1 V.VAL
      FROM LINKS L442
      JOIN VALI V3218 ON V3218.OBJ_ID = L442.OBJ_ID AND V3218.PARAM_ID = 3218 AND V3218.IS_DEL = 0 AND V3218.VAL = :N -- тот же раздел !!!
      JOIN LINKS L444 ON L444.PARENT_ID = L442.OBJ_ID AND L444.OBJ_TYPE_ID = 444 AND L444.DATE_DEL IS NULL
      JOIN VALS VN ON VN.OBJ_ID = L444.OBJ_ID AND VN.PARAM_ID = 3250 AND VN.IS_DEL = 0 AND VN.SVAL = :V$PARAM
      JOIN VALF V ON V.OBJ_ID = L444.OBJ_ID AND V.PARAM_ID = 3254 AND V.IS_DEL = 0
      WHERE L442.PARENT_ID = :V$ID3 AND L442.OBJ_TYPE_ID = 442 AND L442.DATE_DEL IS NULL
      INTO :V;
      IF(V$UNITS = 13837) THEN VAL = CAST(V AS NUMERIC(18, 2)); ELSE VAL = CAST(V AS INTEGER);
      SUSPEND;

      TAG_NAME = 'sections:r:qty_params:r:result';
      V = NULL;
      SELECT V.VAL
      FROM VALF V
      WHERE V.OBJ_ID = :V$OBJ_ID AND V.PARAM_ID = 3276 AND V.IS_DEL = 0
      INTO :V;
      IF(V$UNITS = 13837) THEN VAL = CAST(V AS NUMERIC(18, 2)); ELSE VAL = CAST(V AS INTEGER);
      SUSPEND;
      TAG_NAME = 'sections:r:qty_params:r:delta';
      VAL = NULL;
      IF(V$UNITS = 13837) THEN VAL = CAST((V - VSRC) AS NUMERIC(18, 2)); ELSE VAL = CAST((V - VSRC) AS INTEGER);
      SUSPEND;
      TAG_NAME = 'sections:r:qty_params:r:reason';
      VAL = NULL;
      SELECT V.VAL
      FROM VALS V
      WHERE V.OBJ_ID = :V$OBJ_ID AND V.PARAM_ID = 3302 AND V.IS_DEL = 0
      INTO :VAL;
      SUSPEND;
    END

    NP = 1;
    TAG_NAME = 'sections:r:price::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT L447.OBJ_ID
      FROM LINKS L447
      WHERE L447.PARENT_ID = :V$SECTION_ID AND L447.OBJ_TYPE_ID = 447 AND L447.DATE_DEL IS NULL
      ORDER BY 1
      INTO :V$OBJ_ID
    DO
    BEGIN
      TAG_NAME = 'sections:r:price:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'sections:r:price:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'sections:r:price:r:index';
      VAL = NP;
      NP = NP + 1;
      SUSPEND;
      TAG_NAME = 'sections:r:price:r:fullname';
      VAL = FS;
      SUSPEND;
      TAG_NAME = 'sections:r:price:r:unit_name';
      V$UNITS = NULL;
      VAL = NULL;
      SELECT C.VAL, V.LISTVAL_ID
      FROM VALL V
      LEFT JOIN LISTVAL_TEXT(V.LISTVAL_ID) C ON 1 = 1
      WHERE V.OBJ_ID = :V$OBJ_ID AND V.PARAM_ID = 3257 AND V.IS_DEL = 0
      INTO :VAL, :V$UNITS;
      SUSPEND;
      TAG_NAME = 'sections:r:price:r:v1';
      V = NULL;
      SELECT V.VAL
      FROM VALF V
      WHERE V.OBJ_ID = :V$OBJ_ID AND V.PARAM_ID = 3258 AND V.IS_DEL = 0
      INTO :V;
      VAL = CAST(V AS NUMERIC(18, 2));
      SUSPEND;
      TAG_NAME = 'sections:r:price:r:v2';
      V = NULL;
      SELECT V.VAL
      FROM VALF V
      WHERE V.OBJ_ID = :V$OBJ_ID AND V.PARAM_ID = 3259 AND V.IS_DEL = 0
      INTO :V;
      VAL = CAST(V AS NUMERIC(18, 2));
      SUSPEND;
      TAG_NAME = 'sections:r:price:r:v3';
      V = NULL;
      SELECT V.VAL
      FROM VALF V
      WHERE V.OBJ_ID = :V$OBJ_ID AND V.PARAM_ID = 3260 AND V.IS_DEL = 0
      INTO :V;
      VAL = CAST(V AS NUMERIC(18, 2));
      SUSPEND;
      TAG_NAME = 'sections:r:price:r:v4';
      V = NULL;
      SELECT V.VAL
      FROM VALF V
      WHERE V.OBJ_ID = :V$OBJ_ID AND V.PARAM_ID = 3261 AND V.IS_DEL = 0
      INTO :V;
      VAL = CAST(V AS NUMERIC(18, 2));
      SUSPEND;
      TAG_NAME = 'sections:r:price:r:v5';
      V = NULL;
      SELECT V.VAL
      FROM VALF V
      WHERE V.OBJ_ID = :V$OBJ_ID AND V.PARAM_ID = 3262 AND V.IS_DEL = 0
      INTO :V;
      VAL = CAST(V AS NUMERIC(18, 2));
      SUSPEND;
    END

    NP = 1;
    TAG_NAME = 'sections:r:control::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT L453.OBJ_ID
      FROM LINKS L453
      WHERE L453.PARENT_ID = :V$SECTION_ID AND L453.OBJ_TYPE_ID = 453 AND L453.DATE_DEL IS NULL
      ORDER BY 1
      INTO :V$OBJ_ID
    DO
    BEGIN
      TAG_NAME = 'sections:r:control:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'sections:r:control:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'sections:r:control:r:index';
      VAL = NP;
      NP = NP + 1;
      SUSPEND;
      TAG_NAME = 'sections:r:control:r:form';
      VAL = NULL;
      SELECT V.VAL
      FROM VALS V
      WHERE V.OBJ_ID = :V$OBJ_ID AND V.PARAM_ID = 3266 AND V.IS_DEL = 0
      INTO :VAL;
      SUSPEND;
      TAG_NAME = 'sections:r:control:r:procedure';
      VAL = NULL;
      SELECT V.VAL
      FROM VALS V
      WHERE V.OBJ_ID = :V$OBJ_ID AND V.PARAM_ID = 3267 AND V.IS_DEL = 0
      INTO :VAL;
      SUSPEND;
      TAG_NAME = 'sections:r:control:r:period';
      VAL = NULL;
      SELECT V.VAL
      FROM VALS V
      WHERE V.OBJ_ID = :V$OBJ_ID AND V.PARAM_ID = 3268 AND V.IS_DEL = 0
      INTO :VAL;
      SUSPEND;
    END
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GZ_REPORT_LIST_VOL (
    I$OBJ_ID BIGINT,
    I$YEAR INTEGER = null)
RETURNS (
    VAL VARCHAR(4000))
AS
declare variable V$SECTION_CODE bigint;
declare variable V$PAY smallint;
declare variable V$VNAME varchar(400);
declare variable V$SECNAME varchar(400);
declare variable V$CODE1 varchar(100);
declare variable V$CODE2 varchar(100);
declare variable V$PREVPAY smallint;
declare variable N integer;
declare variable V$U bigint;
declare variable V$V1 float;
declare variable V$V2 float;
declare variable V$V3 float;
declare variable V$V4 float;
declare variable S1 varchar(40);
declare variable S2 varchar(40);
begin

  -- Если год не заполнен - берем последний год из числа действующих
  IF(I$YEAR IS NULL) THEN
  SELECT FIRST 1 V3211.VAL
  FROM LINKS L432
  JOIN LINKS L441 ON L441.PARENT_ID = L432.OBJ_ID AND L441.OBJ_TYPE_ID = 441 AND L441.DATE_DEL IS NULL
  JOIN VALI V3211 ON V3211.OBJ_ID = L441.OBJ_ID AND V3211.PARAM_ID = 3211 AND V3211.IS_DEL = 0
  JOIN VALL V3214 ON V3214.OBJ_ID = L441.OBJ_ID AND V3214.PARAM_ID = 3214 AND V3214.IS_DEL = 0 AND V3214.LISTVAL_ID <> 13502
  WHERE L432.PARENT_ID = :I$OBJ_ID AND L432.OBJ_TYPE_ID = 432 AND L432.DATE_DEL IS NULL
  ORDER BY 1 DESC
  INTO :I$YEAR;

  VAL = '<!DOCTYPE html>';
  VAL = VAL || '<html lang="ru">';
  VAL = VAL || '<head>';
  VAL = VAL || '<meta charset="utf-8" />';
  VAL = VAL || '<style>';
  VAL = VAL || 'html { font-family: Tahoma, Verdana, Arial;';
  VAL = VAL || 'font-size: 10pt; ';
  VAL = VAL || '} ';
  VAL = VAL || '.title1 { font-size: 150%;';
  VAL = VAL || 'padding: 8px;';
  VAL = VAL || 'margin-bottom: 4px;';
  VAL = VAL || 'font-weight: bold;';
  VAL = VAL || 'background-color: #D4E157;';
  VAL = VAL || '} ';
  VAL = VAL || '.title2 { ';
  VAL = VAL || 'padding: 4px;';
  VAL = VAL || 'font-weight: bold;';
  VAL = VAL || '} ';
  VAL = VAL || 'td { ';
  VAL = VAL || 'padding: 0.25em 0.5em; ';
  VAL = VAL || 'border-right: 1px solid #808080; ';
  VAL = VAL || 'border-bottom: 1px solid #808080; ';
  VAL = VAL || 'max-width: 20rem; ';
  VAL = VAL || '} ';
  VAL = VAL || 'td:first-child { ';
  VAL = VAL || 'border-left: 1px solid #808080; ';
  VAL = VAL || '} ';
  VAL = VAL || 'tr:first-child td { ';
  VAL = VAL || 'border-top: 1px solid #808080; ';
  VAL = VAL || '} ';
  VAL = VAL || '.cy { ';
  VAL = VAL || 'width: 4rem; ';
  VAL = VAL || 'font-family: Georgia; ';
  VAL = VAL || '} ';
  VAL = VAL || '.yb { ';
  VAL = VAL || 'font-family: Georgia; ';
  VAL = VAL || '} ';
  VAL = VAL || '</style>';

  VAL = VAL || '</head>';
  VAL = VAL || '<body>';
  SUSPEND;

  -- Заголовок отчета
  VAL = '<div class="title1">Отчет ОО по перечню работ и услуг по годам</div>';

  VAL = VAL || '<div class="title2">' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$OBJ_ID)) || '</div>';
  VAL = VAL || '<div class="title2">Отчетный период: ' || I$YEAR || ' год</div>';

  -- Заголовок таблицы
  VAL = VAL || '<table class="table" cellspacing="0" cellpadding="0">';

  VAL = VAL || '<tr class="thd">';
  VAL = VAL || '<td>№ п/п</td>';
  VAL = VAL || '<td>Наименование государственной услуги (работы)</td>';
  VAL = VAL || '<td>Реестровый номер базовой услуги или работы</td>';
  VAL = VAL || '<td>Технический номер</td>';
  VAL = VAL || '<td class="cy">' || (I$YEAR - 2) || '</td>';
  VAL = VAL || '<td class="cy">' || (I$YEAR - 1) || '</td>';
  VAL = VAL || '<td class="cy">' || (I$YEAR + 0) || '</td>';
  VAL = VAL || '<td class="cy">' || (I$YEAR + 1) || '</td>';
  VAL = VAL || '</tr>';
  SUSPEND;

  V$PREVPAY = -1;
  N = 0;
  FOR
    -- Сначала бесплатные услуги, потом платные услуги, потом работы
    SELECT DISTINCT IIF(V3225.LISTVAL_ID = 13508, IIF(V3243.LISTVAL_ID = 13510, 0, 1), 100), V3219.VAL, V3242.SVAL
    FROM LINKS L432
    JOIN LINKS L441 ON L441.PARENT_ID = L432.OBJ_ID AND L441.OBJ_TYPE_ID = 441 AND L441.DATE_DEL IS NULL
    JOIN VALI V3211 ON V3211.OBJ_ID = L441.OBJ_ID AND V3211.PARAM_ID = 3211 AND V3211.IS_DEL = 0 AND V3211.VAL >= :I$YEAR - 2 AND V3211.VAL <= :I$YEAR + 1
    JOIN VALL V3274 ON V3274.OBJ_ID = L441.OBJ_ID AND V3274.PARAM_ID = 3274 AND V3274.IS_DEL = 0 AND V3274.LISTVAL_ID = 2 -- финальный вариант
    JOIN LINKS L442 ON L442.PARENT_ID = L441.OBJ_ID AND L442.OBJ_TYPE_ID = 442 AND L442.DATE_DEL IS NULL
    JOIN VALI V3219 ON V3219.OBJ_ID = L442.OBJ_ID AND V3219.PARAM_ID = 3219 AND V3219.IS_DEL = 0
    JOIN VALL V3225 ON V3225.OBJ_ID = L442.OBJ_ID AND V3225.PARAM_ID = 3225 AND V3225.IS_DEL = 0
    JOIN LINKS L443 ON L443.PARENT_ID = L442.OBJ_ID AND L443.OBJ_TYPE_ID = 443 AND L443.DATE_DEL IS NULL
    JOIN VALS V3242 ON V3242.OBJ_ID = L443.OBJ_ID AND V3242.PARAM_ID = 3242 AND V3242.IS_DEL = 0
    JOIN VALL V3243 ON V3243.OBJ_ID = L443.OBJ_ID AND V3243.PARAM_ID = 3243 AND V3243.IS_DEL = 0
    WHERE L432.PARENT_ID = :I$OBJ_ID AND L432.OBJ_TYPE_ID = 432 AND L432.DATE_DEL IS NULL
    ORDER BY 1, 2, 3
    INTO :V$PAY, :V$SECTION_CODE, :V$VNAME
  DO
  BEGIN
    IF(V$PAY <> V$PREVPAY) THEN
    BEGIN
      V$PREVPAY = V$PAY;
      VAL = '<tr class="vt"><td>';
      IF(V$PAY = 0) THEN VAL = VAL || '1';
      ELSE IF(V$PAY = 0) THEN VAL = VAL || '2';
      ELSE VAL = VAL || '3';
      VAL = VAL || '</td><td colspan="7">';
      IF(V$PAY = 0) THEN VAL = VAL || 'Услуги (безвоздмездные)';
      ELSE IF(V$PAY = 0) THEN VAL = VAL || 'Услуги (платные)';
      ELSE VAL = VAL || 'Работы';
      VAL = VAL || '</td></tr>';
      SUSPEND;
      N = 1;
    END
    ELSE N = N + 1;

    V$CODE1 = NULL;
    V$CODE2 = NULL;
    SELECT FIRST 1 V3220.VAL, V3221.VAL, V3222.VAL, V3244.LISTVAL_ID
    FROM LINKS L432
    JOIN LINKS L441 ON L441.PARENT_ID = L432.OBJ_ID AND L441.OBJ_TYPE_ID = 441 AND L441.DATE_DEL IS NULL
    JOIN VALI V3211 ON V3211.OBJ_ID = L441.OBJ_ID AND V3211.PARAM_ID = 3211 AND V3211.IS_DEL = 0 AND V3211.VAL >= :I$YEAR - 2 AND V3211.VAL <= :I$YEAR + 1
    JOIN VALL V3274 ON V3274.OBJ_ID = L441.OBJ_ID AND V3274.PARAM_ID = 3274 AND V3274.IS_DEL = 0 AND V3274.LISTVAL_ID = 2 -- финальный вариант
    JOIN LINKS L442 ON L442.PARENT_ID = L441.OBJ_ID AND L442.OBJ_TYPE_ID = 442 AND L442.DATE_DEL IS NULL
    JOIN VALI V3219 ON V3219.OBJ_ID = L442.OBJ_ID AND V3219.PARAM_ID = 3219 AND V3219.IS_DEL = 0 AND V3219.VAL = :V$SECTION_CODE
    JOIN LINKS L443 ON L443.PARENT_ID = L442.OBJ_ID AND L443.OBJ_TYPE_ID = 443 AND L443.DATE_DEL IS NULL
    JOIN VALS V3242 ON V3242.OBJ_ID = L443.OBJ_ID AND V3242.PARAM_ID = 3242 AND V3242.IS_DEL = 0 AND V3242.SVAL = :V$VNAME
    JOIN VALS V3220 ON V3220.OBJ_ID = L442.OBJ_ID AND V3220.PARAM_ID = 3220 AND V3220.IS_DEL = 0
    JOIN VALS V3221 ON V3221.OBJ_ID = L442.OBJ_ID AND V3221.PARAM_ID = 3221 AND V3221.IS_DEL = 0
    JOIN VALS V3222 ON V3222.OBJ_ID = L442.OBJ_ID AND V3222.PARAM_ID = 3222 AND V3222.IS_DEL = 0
    LEFT JOIN VALL V3244 ON V3244.OBJ_ID = L442.OBJ_ID AND V3244.PARAM_ID = 3244 AND V3244.IS_DEL = 0
    WHERE L432.PARENT_ID = :I$OBJ_ID AND L432.OBJ_TYPE_ID = 432 AND L432.DATE_DEL IS NULL
    INTO :V$SECNAME, :V$CODE1, :V$CODE2, :V$U;

    VAL = '<tr class="v">';
    VAL = VAL || '<td>';
    IF(V$PAY = 0) THEN VAL = VAL || '1';
    ELSE IF(V$PAY = 0) THEN VAL = VAL || '2';
    ELSE VAL = VAL || '3';
    VAL = VAL || '.' || N || '</td>';
    VAL = VAL || '<td>' || V$SECNAME || '<br/>' || V$VNAME || '</td>';
    VAL = VAL || '<td>' || V$CODE1 || '</td>';
    VAL = VAL || '<td>' || V$CODE2 || '</td>';

    -- Выбираем данные по годам
    V$V1 = NULL;
    V$V2 = NULL;
    V$V3 = NULL;
    V$V4 = NULL;

    SELECT FIRST 1 V3247.VAL
    FROM LINKS L432
    JOIN LINKS L441 ON L441.PARENT_ID = L432.OBJ_ID AND L441.OBJ_TYPE_ID = 441 AND L441.DATE_DEL IS NULL
    JOIN VALI V3211 ON V3211.OBJ_ID = L441.OBJ_ID AND V3211.PARAM_ID = 3211 AND V3211.IS_DEL = 0 AND V3211.VAL = :I$YEAR - 2
    JOIN VALL V3274 ON V3274.OBJ_ID = L441.OBJ_ID AND V3274.PARAM_ID = 3274 AND V3274.IS_DEL = 0 AND V3274.LISTVAL_ID = 2 -- финальный вариант
    JOIN LINKS L442 ON L442.PARENT_ID = L441.OBJ_ID AND L442.OBJ_TYPE_ID = 442 AND L442.DATE_DEL IS NULL
    JOIN VALI V3219 ON V3219.OBJ_ID = L442.OBJ_ID AND V3219.PARAM_ID = 3219 AND V3219.IS_DEL = 0 AND V3219.VAL = :V$SECTION_CODE
    JOIN LINKS L443 ON L443.PARENT_ID = L442.OBJ_ID AND L443.OBJ_TYPE_ID = 443 AND L443.DATE_DEL IS NULL
    JOIN VALS V3242 ON V3242.OBJ_ID = L443.OBJ_ID AND V3242.PARAM_ID = 3242 AND V3242.IS_DEL = 0 AND V3242.SVAL = :V$VNAME
    JOIN VALF V3247 ON V3247.OBJ_ID = L443.OBJ_ID AND V3247.PARAM_ID = 3247 AND V3247.IS_DEL = 0
    WHERE L432.PARENT_ID = :I$OBJ_ID AND L432.OBJ_TYPE_ID = 432 AND L432.DATE_DEL IS NULL
    INTO :V$V1;

    SELECT FIRST 1 V3247.VAL
    FROM LINKS L432
    JOIN LINKS L441 ON L441.PARENT_ID = L432.OBJ_ID AND L441.OBJ_TYPE_ID = 441 AND L441.DATE_DEL IS NULL
    JOIN VALI V3211 ON V3211.OBJ_ID = L441.OBJ_ID AND V3211.PARAM_ID = 3211 AND V3211.IS_DEL = 0 AND V3211.VAL = :I$YEAR - 1
    JOIN VALL V3274 ON V3274.OBJ_ID = L441.OBJ_ID AND V3274.PARAM_ID = 3274 AND V3274.IS_DEL = 0 AND V3274.LISTVAL_ID = 2 -- финальный вариант
    JOIN LINKS L442 ON L442.PARENT_ID = L441.OBJ_ID AND L442.OBJ_TYPE_ID = 442 AND L442.DATE_DEL IS NULL
    JOIN VALI V3219 ON V3219.OBJ_ID = L442.OBJ_ID AND V3219.PARAM_ID = 3219 AND V3219.IS_DEL = 0 AND V3219.VAL = :V$SECTION_CODE
    JOIN LINKS L443 ON L443.PARENT_ID = L442.OBJ_ID AND L443.OBJ_TYPE_ID = 443 AND L443.DATE_DEL IS NULL
    JOIN VALS V3242 ON V3242.OBJ_ID = L443.OBJ_ID AND V3242.PARAM_ID = 3242 AND V3242.IS_DEL = 0 AND V3242.SVAL = :V$VNAME
    JOIN VALF V3247 ON V3247.OBJ_ID = L443.OBJ_ID AND V3247.PARAM_ID = 3247 AND V3247.IS_DEL = 0
    WHERE L432.PARENT_ID = :I$OBJ_ID AND L432.OBJ_TYPE_ID = 432 AND L432.DATE_DEL IS NULL
    INTO :V$V2;

    SELECT FIRST 1 V3247.VAL
    FROM LINKS L432
    JOIN LINKS L441 ON L441.PARENT_ID = L432.OBJ_ID AND L441.OBJ_TYPE_ID = 441 AND L441.DATE_DEL IS NULL
    JOIN VALI V3211 ON V3211.OBJ_ID = L441.OBJ_ID AND V3211.PARAM_ID = 3211 AND V3211.IS_DEL = 0 AND V3211.VAL = :I$YEAR
    JOIN VALL V3274 ON V3274.OBJ_ID = L441.OBJ_ID AND V3274.PARAM_ID = 3274 AND V3274.IS_DEL = 0 AND V3274.LISTVAL_ID = 2 -- финальный вариант
    JOIN LINKS L442 ON L442.PARENT_ID = L441.OBJ_ID AND L442.OBJ_TYPE_ID = 442 AND L442.DATE_DEL IS NULL
    JOIN VALI V3219 ON V3219.OBJ_ID = L442.OBJ_ID AND V3219.PARAM_ID = 3219 AND V3219.IS_DEL = 0 AND V3219.VAL = :V$SECTION_CODE
    JOIN LINKS L443 ON L443.PARENT_ID = L442.OBJ_ID AND L443.OBJ_TYPE_ID = 443 AND L443.DATE_DEL IS NULL
    JOIN VALS V3242 ON V3242.OBJ_ID = L443.OBJ_ID AND V3242.PARAM_ID = 3242 AND V3242.IS_DEL = 0 AND V3242.SVAL = :V$VNAME
    JOIN VALF V3247 ON V3247.OBJ_ID = L443.OBJ_ID AND V3247.PARAM_ID = 3247 AND V3247.IS_DEL = 0
    WHERE L432.PARENT_ID = :I$OBJ_ID AND L432.OBJ_TYPE_ID = 432 AND L432.DATE_DEL IS NULL
    INTO :V$V3;

    SELECT FIRST 1 V3247.VAL
    FROM LINKS L432
    JOIN LINKS L441 ON L441.PARENT_ID = L432.OBJ_ID AND L441.OBJ_TYPE_ID = 441 AND L441.DATE_DEL IS NULL
    JOIN VALI V3211 ON V3211.OBJ_ID = L441.OBJ_ID AND V3211.PARAM_ID = 3211 AND V3211.IS_DEL = 0 AND V3211.VAL = :I$YEAR + 1
    JOIN VALL V3274 ON V3274.OBJ_ID = L441.OBJ_ID AND V3274.PARAM_ID = 3274 AND V3274.IS_DEL = 0 AND V3274.LISTVAL_ID = 2 -- финальный вариант
    JOIN LINKS L442 ON L442.PARENT_ID = L441.OBJ_ID AND L442.OBJ_TYPE_ID = 442 AND L442.DATE_DEL IS NULL
    JOIN VALI V3219 ON V3219.OBJ_ID = L442.OBJ_ID AND V3219.PARAM_ID = 3219 AND V3219.IS_DEL = 0 AND V3219.VAL = :V$SECTION_CODE
    JOIN LINKS L443 ON L443.PARENT_ID = L442.OBJ_ID AND L443.OBJ_TYPE_ID = 443 AND L443.DATE_DEL IS NULL
    JOIN VALS V3242 ON V3242.OBJ_ID = L443.OBJ_ID AND V3242.PARAM_ID = 3242 AND V3242.IS_DEL = 0 AND V3242.SVAL = :V$VNAME
    JOIN VALF V3247 ON V3247.OBJ_ID = L443.OBJ_ID AND V3247.PARAM_ID = 3247 AND V3247.IS_DEL = 0
    WHERE L432.PARENT_ID = :I$OBJ_ID AND L432.OBJ_TYPE_ID = 432 AND L432.DATE_DEL IS NULL
    INTO :V$V4;

    S1 = CAST(V$V1 AS NUMERIC(18, 1));
    S2 = CAST(V$V1 AS NUMERIC(18, 0));
    VAL = VAL || '<td class="yb">' || COALESCE(IIF(V$U = 13837, S1, S2), '-') || '</td>';
    S1 = CAST(V$V2 AS NUMERIC(18, 1));
    S2 = CAST(V$V2 AS NUMERIC(18, 0));
    VAL = VAL || '<td class="yb">' || COALESCE(IIF(V$U = 13837, S1, S2), '-') || '</td>';
    S1 = CAST(V$V3 AS NUMERIC(18, 1));
    S2 = CAST(V$V3 AS NUMERIC(18, 0));
    VAL = VAL || '<td class="yb">' || COALESCE(IIF(V$U = 13837, S1, S2), '-') || '</td>';
    S1 = CAST(V$V4 AS NUMERIC(18, 1));
    S2 = CAST(V$V4 AS NUMERIC(18, 0));
    VAL = VAL || '<td class="yb">' || COALESCE(IIF(V$U = 13837, S1, S2), '-') || '</td>';

    VAL = VAL || '</tr>';
    SUSPEND;

  END

  VAL = '</table></body></html>';
  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GZ_REPORT_MEMBERS_VOL (
    I$OBJ_ID BIGINT,
    I$YEAR INTEGER = null)
RETURNS (
    VAL VARCHAR(4000))
AS
declare variable V$TYPE_ID bigint;
declare variable V$SECTION_CODE bigint;
declare variable V$PAY smallint;
declare variable V$VNAME varchar(400);
declare variable V$SECNAME varchar(400);
declare variable V$CODE1 varchar(100);
declare variable V$CODE2 varchar(100);
declare variable V$PREVPAY smallint;
declare variable N integer;
declare variable V$V1 integer;
declare variable V$V2 integer;
declare variable V$V3 integer;
declare variable V$U bigint;
declare variable S1 varchar(100);
declare variable S2 varchar(100);
begin

  SELECT TYPE_ID
  FROM OBJECTS
  WHERE OBJ_ID = :I$OBJ_ID
  INTO :V$TYPE_ID;

  -- Если год не заполнен - берем последний год из числа действующих
  IF(I$YEAR IS NULL) THEN
  SELECT FIRST 1 V3211.VAL
  FROM LINKS L432
  JOIN LINKS L441 ON L441.PARENT_ID = L432.OBJ_ID AND L441.OBJ_TYPE_ID = 441 AND L441.DATE_DEL IS NULL
  JOIN VALI V3211 ON V3211.OBJ_ID = L441.OBJ_ID AND V3211.PARAM_ID = 3211 AND V3211.IS_DEL = 0
  JOIN VALL V3214 ON V3214.OBJ_ID = L441.OBJ_ID AND V3214.PARAM_ID = 3214 AND V3214.IS_DEL = 0 AND V3214.LISTVAL_ID <> 13502
  WHERE L432.PARENT_ID = :I$OBJ_ID AND L432.OBJ_TYPE_ID = 432 AND L432.DATE_DEL IS NULL
  ORDER BY 1 DESC
  INTO :I$YEAR;

  IF(I$YEAR IS NULL) THEN EXCEPTION DATA_ERROR 'Нет ни одного ГЗ в действующем статусе, отчет невозможно сформировать';

  VAL = '<!DOCTYPE html>';
  VAL = VAL || '<html lang="ru">';
  VAL = VAL || '<head>';
  VAL = VAL || '<meta charset="utf-8" />';
  VAL = VAL || '<style>';
  VAL = VAL || 'html { font-family: Tahoma, Verdana, Arial;';
  VAL = VAL || 'font-size: 10pt; ';
  VAL = VAL || '} ';
  VAL = VAL || '.title1 { font-size: 150%;';
  VAL = VAL || 'padding: 8px;';
  VAL = VAL || 'margin-bottom: 4px;';
  VAL = VAL || 'font-weight: bold;';
  VAL = VAL || 'background-color: #D4E157;';
  VAL = VAL || '} ';
  VAL = VAL || '.title2 { ';
  VAL = VAL || 'padding: 4px;';
  VAL = VAL || 'font-weight: bold;';
  VAL = VAL || '} ';
  VAL = VAL || 'td { ';
  VAL = VAL || 'padding: 0.25em 0.5em; ';
  VAL = VAL || 'border-right: 1px solid #808080; ';
  VAL = VAL || 'border-bottom: 1px solid #808080; ';
  VAL = VAL || 'max-width: 20rem; ';
  VAL = VAL || '} ';
  VAL = VAL || 'td:first-child { ';
  VAL = VAL || 'border-left: 1px solid #808080; ';
  VAL = VAL || '} ';
  VAL = VAL || 'tr:first-child td { ';
  VAL = VAL || 'border-top: 1px solid #808080; ';
  VAL = VAL || '} ';
  VAL = VAL || '.cy { ';
  VAL = VAL || 'width: 4rem; ';
  VAL = VAL || 'font-family: Georgia; ';
  VAL = VAL || '} ';
  VAL = VAL || '.yb { ';
  VAL = VAL || 'font-family: Georgia; ';
  VAL = VAL || '} ';
  VAL = VAL || '</style>';

  VAL = VAL || '</head>';
  VAL = VAL || '<body>';
  SUSPEND;

  -- Заголовок отчета
  VAL = '<div class="title1">Количество обучающихся по видам услуг/работ</div>';

  VAL = VAL || '<div class="title2">' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$OBJ_ID)) || '</div>';
  VAL = VAL || '<div class="title2">Отчетный период: ' || I$YEAR || ' год</div>';

  -- Заголовок таблицы
  VAL = VAL || '<table class="table" cellspacing="0" cellpadding="0">';

  VAL = VAL || '<tr class="thd">';
  VAL = VAL || '<td>№ п/п</td>';
  VAL = VAL || '<td>Наименование государственной услуги (работы)</td>';
  VAL = VAL || '<td>Реестровый номер базовой услуги или работы</td>';
  VAL = VAL || '<td>Технический номер</td>';
  VAL = VAL || '<td class="cy">' || (I$YEAR - 2) || '</td>';
  VAL = VAL || '<td class="cy">' || (I$YEAR - 1) || '</td>';
  VAL = VAL || '<td class="cy">' || (I$YEAR + 0) || '</td>';
  VAL = VAL || '</tr>';
  SUSPEND;

  V$PREVPAY = -1;
  N = 0;
  FOR
    -- Сначала бесплатные услуги, потом платные услуги, потом работы
    SELECT DISTINCT IIF(V3225.LISTVAL_ID = 13508, IIF(V3243.LISTVAL_ID = 13510, 0, 1), 100), V3219.VAL, V3242.SVAL
    FROM LINKS L432
    JOIN LINKS L441 ON L441.PARENT_ID = L432.OBJ_ID AND L441.OBJ_TYPE_ID = 441 AND L441.DATE_DEL IS NULL
    JOIN VALI V3211 ON V3211.OBJ_ID = L441.OBJ_ID AND V3211.PARAM_ID = 3211 AND V3211.IS_DEL = 0 AND V3211.VAL >= :I$YEAR - 2 AND V3211.VAL <= :I$YEAR + 1
    JOIN VALL V3274 ON V3274.OBJ_ID = L441.OBJ_ID AND V3274.PARAM_ID = 3274 AND V3274.IS_DEL = 0 AND V3274.LISTVAL_ID = 2 -- финальный вариант
    JOIN LINKS L442 ON L442.PARENT_ID = L441.OBJ_ID AND L442.OBJ_TYPE_ID = 442 AND L442.DATE_DEL IS NULL
    JOIN VALI V3219 ON V3219.OBJ_ID = L442.OBJ_ID AND V3219.PARAM_ID = 3219 AND V3219.IS_DEL = 0
    JOIN VALL V3225 ON V3225.OBJ_ID = L442.OBJ_ID AND V3225.PARAM_ID = 3225 AND V3225.IS_DEL = 0
    JOIN LINKS L443 ON L443.PARENT_ID = L442.OBJ_ID AND L443.OBJ_TYPE_ID = 443 AND L443.DATE_DEL IS NULL
    JOIN VALS V3242 ON V3242.OBJ_ID = L443.OBJ_ID AND V3242.PARAM_ID = 3242 AND V3242.IS_DEL = 0
    JOIN VALL V3243 ON V3243.OBJ_ID = L443.OBJ_ID AND V3243.PARAM_ID = 3243 AND V3243.IS_DEL = 0
    WHERE L432.PARENT_ID = :I$OBJ_ID AND L432.OBJ_TYPE_ID = 432 AND L432.DATE_DEL IS NULL
    ORDER BY 1, 2, 3
    INTO :V$PAY, :V$SECTION_CODE, :V$VNAME
  DO
  BEGIN
    IF(V$PAY <> V$PREVPAY) THEN
    BEGIN
      V$PREVPAY = V$PAY;
      VAL = '<tr class="vt"><td>';
      IF(V$PAY = 0) THEN VAL = VAL || '1';
      ELSE IF(V$PAY = 0) THEN VAL = VAL || '2';
      ELSE VAL = VAL || '3';
      VAL = VAL || '</td><td colspan="7">';
      IF(V$PAY = 0) THEN VAL = VAL || 'Услуги (безвоздмездные)';
      ELSE IF(V$PAY = 0) THEN VAL = VAL || 'Услуги (платные)';
      ELSE VAL = VAL || 'Работы';
      VAL = VAL || '</td></tr>';
      SUSPEND;
      N = 1;
    END
    ELSE N = N + 1;

    V$CODE1 = NULL;
    V$CODE2 = NULL;
    SELECT FIRST 1 V3220.VAL, V3221.VAL, V3222.VAL, V3244.LISTVAL_ID
    FROM LINKS L432
    JOIN LINKS L441 ON L441.PARENT_ID = L432.OBJ_ID AND L441.OBJ_TYPE_ID = 441 AND L441.DATE_DEL IS NULL
    JOIN VALI V3211 ON V3211.OBJ_ID = L441.OBJ_ID AND V3211.PARAM_ID = 3211 AND V3211.IS_DEL = 0 AND V3211.VAL >= :I$YEAR - 2 AND V3211.VAL <= :I$YEAR + 1
    JOIN VALL V3274 ON V3274.OBJ_ID = L441.OBJ_ID AND V3274.PARAM_ID = 3274 AND V3274.IS_DEL = 0 AND V3274.LISTVAL_ID = 2 -- финальный вариант
    JOIN LINKS L442 ON L442.PARENT_ID = L441.OBJ_ID AND L442.OBJ_TYPE_ID = 442 AND L442.DATE_DEL IS NULL
    JOIN VALI V3219 ON V3219.OBJ_ID = L442.OBJ_ID AND V3219.PARAM_ID = 3219 AND V3219.IS_DEL = 0 AND V3219.VAL = :V$SECTION_CODE
    JOIN LINKS L443 ON L443.PARENT_ID = L442.OBJ_ID AND L443.OBJ_TYPE_ID = 443 AND L443.DATE_DEL IS NULL
    JOIN VALS V3242 ON V3242.OBJ_ID = L443.OBJ_ID AND V3242.PARAM_ID = 3242 AND V3242.IS_DEL = 0 AND V3242.SVAL = :V$VNAME
    JOIN VALS V3220 ON V3220.OBJ_ID = L442.OBJ_ID AND V3220.PARAM_ID = 3220 AND V3220.IS_DEL = 0
    JOIN VALS V3221 ON V3221.OBJ_ID = L442.OBJ_ID AND V3221.PARAM_ID = 3221 AND V3221.IS_DEL = 0
    JOIN VALS V3222 ON V3222.OBJ_ID = L442.OBJ_ID AND V3222.PARAM_ID = 3222 AND V3222.IS_DEL = 0
    LEFT JOIN VALL V3244 ON V3244.OBJ_ID = L442.OBJ_ID AND V3244.PARAM_ID = 3244 AND V3244.IS_DEL = 0
    WHERE L432.PARENT_ID = :I$OBJ_ID AND L432.OBJ_TYPE_ID = 432 AND L432.DATE_DEL IS NULL
    INTO :V$SECNAME, :V$CODE1, :V$CODE2, :V$U;

    VAL = '<tr class="v">';
    VAL = VAL || '<td>';
    IF(V$PAY = 0) THEN VAL = VAL || '1';
    ELSE IF(V$PAY = 0) THEN VAL = VAL || '2';
    ELSE VAL = VAL || '3';
    VAL = VAL || '.' || N || '</td>';
    VAL = VAL || '<td>' || V$SECNAME || '<br/>' || V$VNAME || '</td>';
    VAL = VAL || '<td>' || V$CODE1 || '</td>';
    VAL = VAL || '<td>' || V$CODE2 || '</td>';

    V$V1 = (SELECT RESULT FROM GZ_CALC_RESULT(NULL, NULL, :I$OBJ_ID, :V$CODE1, :I$YEAR - 2));
    V$V2 = (SELECT RESULT FROM GZ_CALC_RESULT(NULL, NULL, :I$OBJ_ID, :V$CODE1, :I$YEAR - 1));
    V$V3 = (SELECT RESULT FROM GZ_CALC_RESULT(NULL, NULL, :I$OBJ_ID, :V$CODE1, :I$YEAR));

    S1 = CAST(V$V1 AS NUMERIC(18, 1));
    S2 = CAST(V$V1 AS NUMERIC(18, 0));
    VAL = VAL || '<td class="yb">' || COALESCE(IIF(V$U = 13837, S1, S2), '-') || '</td>';
    S1 = CAST(V$V2 AS NUMERIC(18, 1));
    S2 = CAST(V$V2 AS NUMERIC(18, 0));
    VAL = VAL || '<td class="yb">' || COALESCE(IIF(V$U = 13837, S1, S2), '-') || '</td>';
    S1 = CAST(V$V3 AS NUMERIC(18, 1));
    S2 = CAST(V$V3 AS NUMERIC(18, 0));
    VAL = VAL || '<td class="yb">' || COALESCE(IIF(V$U = 13837, S1, S2), '-') || '</td>';

    VAL = VAL || '</tr>';
    SUSPEND;

  END

  VAL = '</table></body></html>';
  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GZ_REPORT_OO_QTY (
    I$OBJ_ID BIGINT,
    I$YEAR INTEGER = null)
RETURNS (
    VAL VARCHAR(4000))
AS
declare variable V$GZ_ID bigint;
declare variable V$SECTION_ID bigint;
declare variable V$PARAM_ID bigint;
declare variable V$PREV_SCODE bigint;
declare variable V$PREV_VNAME varchar(400);
declare variable V$SECTION_CODE bigint;
declare variable V$YEAR integer;
declare variable V$STAGE bigint;
declare variable V$VNAME varchar(400);
declare variable V$SECNAME varchar(400);
declare variable V$CODE1 varchar(100);
declare variable V$CODE2 varchar(100);
declare variable N integer;
declare variable NY integer;
declare variable C integer;
declare variable Y integer;
declare variable V$U bigint;
declare variable V$V1 float;
declare variable V$V2 float;
declare variable V$V3 float;
declare variable V$V4 float;
declare variable S1 varchar(40);
declare variable S2 varchar(40);
begin

  -- Если год не заполнен - берем последний год из числа действующих
  IF(I$YEAR IS NULL) THEN
  SELECT FIRST 1 V3211.VAL
  FROM LINKS L432
  JOIN LINKS L441 ON L441.PARENT_ID = L432.OBJ_ID AND L441.OBJ_TYPE_ID = 441 AND L441.DATE_DEL IS NULL
  JOIN VALI V3211 ON V3211.OBJ_ID = L441.OBJ_ID AND V3211.PARAM_ID = 3211 AND V3211.IS_DEL = 0
  JOIN VALL V3214 ON V3214.OBJ_ID = L441.OBJ_ID AND V3214.PARAM_ID = 3214 AND V3214.IS_DEL = 0 AND V3214.LISTVAL_ID <> 13502
  WHERE L432.PARENT_ID = :I$OBJ_ID AND L432.OBJ_TYPE_ID = 432 AND L432.DATE_DEL IS NULL
  ORDER BY 1 DESC
  INTO :I$YEAR;

  VAL = '<!DOCTYPE html>';
  VAL = VAL || '<html lang="ru">';
  VAL = VAL || '<head>';
  VAL = VAL || '<meta charset="utf-8" />';
  VAL = VAL || '<style>';
  VAL = VAL || 'html { font-family: Tahoma, Verdana, Arial;';
  VAL = VAL || 'font-size: 10pt; ';
  VAL = VAL || '} ';
  VAL = VAL || '.title1 { font-size: 150%;';
  VAL = VAL || 'padding: 8px;';
  VAL = VAL || 'margin-bottom: 4px;';
  VAL = VAL || 'font-weight: bold;';
  VAL = VAL || 'background-color: #D4E157;';
  VAL = VAL || '} ';
  VAL = VAL || '.title2 { ';
  VAL = VAL || 'padding: 4px;';
  VAL = VAL || 'font-weight: bold;';
  VAL = VAL || '} ';
  VAL = VAL || 'td { ';
  VAL = VAL || 'padding: 0.25em 0.5em; ';
  VAL = VAL || 'border-right: 1px solid #808080; ';
  VAL = VAL || 'border-bottom: 1px solid #808080; ';
  VAL = VAL || 'max-width: 20rem; ';
  VAL = VAL || '} ';
  VAL = VAL || 'tr:not(.sx) td:first-child { ';
  VAL = VAL || 'border-left: 1px solid #808080; ';
  VAL = VAL || '} ';
  VAL = VAL || 'tr:first-child td { ';
  VAL = VAL || 'border-top: 1px solid #808080; ';
  VAL = VAL || '} ';
  VAL = VAL || '.yb { ';
  VAL = VAL || 'background-color: #B3E5FC; ';
  VAL = VAL || 'font-family: Georgia; ';
  VAL = VAL || '} ';
  VAL = VAL || '.yc { ';
  VAL = VAL || 'background-color: #FFE082; ';
  VAL = VAL || 'font-weight: bold; ';
  VAL = VAL || 'font-family: Georgia; ';
  VAL = VAL || '} ';
  VAL = VAL || '.y1, .y2 { ';
  VAL = VAL || 'background-color: #ECEFF1; ';
  VAL = VAL || 'font-family: Georgia; ';
  VAL = VAL || '} ';
  VAL = VAL || '.cy { ';
  VAL = VAL || 'width: 4rem; ';
  VAL = VAL || 'font-family: Georgia; ';
  VAL = VAL || '} ';
  VAL = VAL || '</style>';

  VAL = VAL || '</head>';
  VAL = VAL || '<body>';
  SUSPEND;

  -- Заголовок отчета
  VAL = '<div class="title1">Отчет ОО по показателям качества услуг/работ</div>';

  VAL = VAL || '<div class="title2">' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$OBJ_ID)) || '</div>';
  VAL = VAL || '<div class="title2">Отчетный период: ' || I$YEAR || ' год</div>';

  -- Заголовок таблицы
  VAL = VAL || '<table class="table" cellspacing="0" cellpadding="0">';

  VAL = VAL || '<tr class="thd fx">';
  VAL = VAL || '<td rowspan="2">№ п/п</td>';
  VAL = VAL || '<td rowspan="2">Наименование государственной услуги (работы)</td>';
  VAL = VAL || '<td rowspan="2">Реестровый номер базовой услуги или работы</td>';
  VAL = VAL || '<td rowspan="2">Технический номер</td>';
  VAL = VAL || '<td rowspan="2">Показатель объема</td>';
  VAL = VAL || '<td rowspan="2">Год</td>';
  VAL = VAL || '<td rowspan="2">Статус</td>';
  VAL = VAL || '<td colspan="8">Показатели объема ГЗ по годам</td>';
  VAL = VAL || '</tr>';
  VAL = VAL || '<tr class="thd sx">';
  VAL = VAL || '<td class="cy">' || (I$YEAR - 4) || '</td>';
  VAL = VAL || '<td class="cy">' || (I$YEAR - 3) || '</td>';
  VAL = VAL || '<td class="cy">' || (I$YEAR - 2) || '</td>';
  VAL = VAL || '<td class="cy">' || (I$YEAR - 1) || '</td>';
  VAL = VAL || '<td class="cy">' || (I$YEAR + 0) || '</td>';
  VAL = VAL || '<td class="cy">' || (I$YEAR + 1) || '</td>';
  VAL = VAL || '<td class="cy">' || (I$YEAR + 2) || '</td>';
  VAL = VAL || '<td class="cy">' || (I$YEAR + 3) || '</td>';
  VAL = VAL || '</tr>';
  SUSPEND;

  V$PREV_SCODE = -1;
  V$PREV_VNAME = '';
  N = 0;
  FOR
    SELECT L441.OBJ_ID, L442.OBJ_ID, L444.OBJ_ID, V3219.VAL, V3250.SVAL, V3211.VAL, V3214.LISTVAL_ID, V3251.LISTVAL_ID, V3252.VAL, V3254.VAL, V3255.VAL, V3256.VAL
    FROM LINKS L432
    JOIN LINKS L441 ON L441.PARENT_ID = L432.OBJ_ID AND L441.OBJ_TYPE_ID = 441 AND L441.DATE_DEL IS NULL
    JOIN VALI V3211 ON V3211.OBJ_ID = L441.OBJ_ID AND V3211.PARAM_ID = 3211 AND V3211.IS_DEL = 0 AND V3211.VAL >= :I$YEAR - 3 AND V3211.VAL <= :I$YEAR + 1
    JOIN VALL V3214 ON V3214.OBJ_ID = L441.OBJ_ID AND V3214.PARAM_ID = 3214 AND V3214.IS_DEL = 0
    JOIN LINKS L442 ON L442.PARENT_ID = L441.OBJ_ID AND L442.OBJ_TYPE_ID = 442 AND L442.DATE_DEL IS NULL
    JOIN VALI V3219 ON V3219.OBJ_ID = L442.OBJ_ID AND V3219.PARAM_ID = 3219 AND V3219.IS_DEL = 0
    JOIN LINKS L444 ON L444.PARENT_ID = L442.OBJ_ID AND L444.OBJ_TYPE_ID = 444 AND L444.DATE_DEL IS NULL
    JOIN VALS V3250 ON V3250.OBJ_ID = L444.OBJ_ID AND V3250.PARAM_ID = 3250 AND V3250.IS_DEL = 0
    LEFT JOIN VALL V3251 ON V3251.OBJ_ID = L444.OBJ_ID AND V3251.PARAM_ID = 3251 AND V3251.IS_DEL = 0
    LEFT JOIN VALF V3252 ON V3252.OBJ_ID = L444.OBJ_ID AND V3252.PARAM_ID = 3252 AND V3252.IS_DEL = 0
    LEFT JOIN VALF V3254 ON V3254.OBJ_ID = L444.OBJ_ID AND V3254.PARAM_ID = 3254 AND V3254.IS_DEL = 0
    LEFT JOIN VALF V3255 ON V3255.OBJ_ID = L444.OBJ_ID AND V3255.PARAM_ID = 3255 AND V3255.IS_DEL = 0
    LEFT JOIN VALF V3256 ON V3256.OBJ_ID = L444.OBJ_ID AND V3256.PARAM_ID = 3256 AND V3256.IS_DEL = 0
    WHERE L432.PARENT_ID = :I$OBJ_ID AND L432.OBJ_TYPE_ID = 432 AND L432.DATE_DEL IS NULL
      AND (V3214.LISTVAL_ID <> 13502 OR V3211.VAL = :I$YEAR + 1)
    ORDER BY 4, 5, 6, 7
    INTO :V$GZ_ID, :V$SECTION_ID, :V$PARAM_ID, :V$SECTION_CODE, :V$VNAME, :V$YEAR, :V$STAGE, :V$U, :V$V1, :V$V2, :V$V3, :V$V4
  DO
  BEGIN
    IF(V$PREV_SCODE <> V$SECTION_CODE OR V$PREV_VNAME <> V$VNAME) THEN
    BEGIN
      V$PREV_SCODE = V$SECTION_CODE;
      V$PREV_VNAME = V$VNAME;
      N = N + 1;
      NY = 1;

      SELECT V3220.VAL
      FROM VALS V3220
      WHERE V3220.OBJ_ID = :V$SECTION_ID AND V3220.PARAM_ID = 3220 AND V3220.IS_DEL = 0
      INTO :V$SECNAME;

      SELECT V3221.VAL
      FROM VALS V3221
      WHERE V3221.OBJ_ID = :V$SECTION_ID AND V3221.PARAM_ID = 3221 AND V3221.IS_DEL = 0
      INTO :V$CODE1;

      SELECT V3222.VAL
      FROM VALS V3222
      WHERE V3222.OBJ_ID = :V$SECTION_ID AND V3222.PARAM_ID = 3222 AND V3222.IS_DEL = 0
      INTO :V$CODE2;

      -- Сколько у нас будет строк в этом разделе ?
      SELECT COUNT(*)
      FROM LINKS L432
      JOIN LINKS L441 ON L441.PARENT_ID = L432.OBJ_ID AND L441.OBJ_TYPE_ID = 441 AND L441.DATE_DEL IS NULL
      JOIN VALI V3211 ON V3211.OBJ_ID = L441.OBJ_ID AND V3211.PARAM_ID = 3211 AND V3211.IS_DEL = 0 AND V3211.VAL >= :I$YEAR - 3 AND V3211.VAL <= :I$YEAR + 1
      JOIN VALL V3214 ON V3214.OBJ_ID = L441.OBJ_ID AND V3214.PARAM_ID = 3214 AND V3214.IS_DEL = 0
      JOIN LINKS L442 ON L442.PARENT_ID = L441.OBJ_ID AND L442.OBJ_TYPE_ID = 442 AND L442.DATE_DEL IS NULL
      JOIN VALI V3219 ON V3219.OBJ_ID = L442.OBJ_ID AND V3219.PARAM_ID = 3219 AND V3219.IS_DEL = 0 AND V3219.VAL = :V$SECTION_CODE
      JOIN LINKS L444 ON L444.PARENT_ID = L442.OBJ_ID AND L444.OBJ_TYPE_ID = 444 AND L444.DATE_DEL IS NULL
      JOIN VALS V3250 ON V3250.OBJ_ID = L444.OBJ_ID AND V3250.PARAM_ID = 3250 AND V3250.IS_DEL = 0 AND V3250.SVAL = :V$VNAME
      WHERE L432.PARENT_ID = :I$OBJ_ID AND L432.OBJ_TYPE_ID = 432 AND L432.DATE_DEL IS NULL
        AND (V3214.LISTVAL_ID <> 13502 OR V3211.VAL = :I$YEAR + 1)
      INTO :C;

      VAL = '<tr class="v">';
      VAL = VAL || '<td rowspan="' || C || '">' || N || '</td>';
      VAL = VAL || '<td rowspan="' || C || '">' || V$SECNAME || '</td>';
      VAL = VAL || '<td rowspan="' || C || '">' || V$CODE1 || '</td>';
      VAL = VAL || '<td rowspan="' || C || '">' || V$CODE2 || '</td>';
      VAL = VAL || '<td rowspan="' || C || '">' || V$VNAME || '</td>';
      SUSPEND;
    END

    IF(NY = 1) THEN VAL = ''; ELSE VAL = '<tr class="v nx">';
    VAL = VAL || '<td>' || V$YEAR || '</td>';
    S1 = COALESCE((SELECT VAL FROM LISTVAL_TEXT(:V$STAGE)), '?');
    IF(V$STAGE = 13503) THEN S1 = 'Действ.';
    S1 = REPLACE(S1, 'енение', '.');
    VAL = VAL || '<td>' || S1 || '</td>';

    -- Пустые ячейки до данных
    Y = I$YEAR - 3;
    WHILE(Y < V$YEAR) DO BEGIN Y = Y + 1; VAL = VAL || '<td></td>'; END

    -- Сами данные
    S1 = CAST(V$V1 AS NUMERIC(18, 1));
    S2 = CAST(V$V1 AS NUMERIC(18, 0));
    VAL = VAL || '<td class="yb">' || COALESCE(IIF(V$U = 13837, S1, S2), '-') || '</td>';
    S1 = CAST(V$V2 AS NUMERIC(18, 1));
    S2 = CAST(V$V2 AS NUMERIC(18, 0));
    VAL = VAL || '<td class="yc">' || COALESCE(IIF(V$U = 13837, S1, S2), '-') || '</td>';
    S1 = CAST(V$V3 AS NUMERIC(18, 1));
    S2 = CAST(V$V3 AS NUMERIC(18, 0));
    VAL = VAL || '<td class="y1">' || COALESCE(IIF(V$U = 13837, S1, S2), '-') || '</td>';
    S1 = CAST(V$V4 AS NUMERIC(18, 1));
    S2 = CAST(V$V4 AS NUMERIC(18, 0));
    VAL = VAL || '<td class="y2">' || COALESCE(IIF(V$U = 13837, S1, S2), '-') || '</td>';
    Y = Y + 3;

    -- Пустые ячейки после данных
    WHILE(Y <= I$YEAR + 3) DO BEGIN Y = Y + 1; VAL = VAL || '<td></td>'; END

    VAL = VAL || '</tr>';
    NY = NY + 1;
    SUSPEND;

  END

  VAL = '</table></body></html>';
  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GZ_REPORT_OO_VOL (
    I$OBJ_ID BIGINT,
    I$YEAR INTEGER = null)
RETURNS (
    VAL VARCHAR(4000))
AS
declare variable V$GZ_ID bigint;
declare variable V$SECTION_ID bigint;
declare variable V$PARAM_ID bigint;
declare variable V$PREV_SCODE bigint;
declare variable V$PREV_VNAME varchar(400);
declare variable V$SECTION_CODE bigint;
declare variable V$YEAR integer;
declare variable V$STAGE bigint;
declare variable V$VNAME varchar(400);
declare variable V$SECNAME varchar(400);
declare variable V$CODE1 varchar(100);
declare variable V$CODE2 varchar(100);
declare variable N integer;
declare variable NY integer;
declare variable C integer;
declare variable Y integer;
declare variable V$U bigint;
declare variable V$V1 float;
declare variable V$V2 float;
declare variable V$V3 float;
declare variable V$V4 float;
declare variable S1 varchar(40);
declare variable S2 varchar(40);
begin

  -- Если год не заполнен - берем последний год из числа действующих
  IF(I$YEAR IS NULL) THEN
  SELECT FIRST 1 V3211.VAL
  FROM LINKS L432
  JOIN LINKS L441 ON L441.PARENT_ID = L432.OBJ_ID AND L441.OBJ_TYPE_ID = 441 AND L441.DATE_DEL IS NULL
  JOIN VALI V3211 ON V3211.OBJ_ID = L441.OBJ_ID AND V3211.PARAM_ID = 3211 AND V3211.IS_DEL = 0
  JOIN VALL V3214 ON V3214.OBJ_ID = L441.OBJ_ID AND V3214.PARAM_ID = 3214 AND V3214.IS_DEL = 0 AND V3214.LISTVAL_ID <> 13502
  WHERE L432.PARENT_ID = :I$OBJ_ID AND L432.OBJ_TYPE_ID = 432 AND L432.DATE_DEL IS NULL
  ORDER BY 1 DESC
  INTO :I$YEAR;

  VAL = '<!DOCTYPE html>';
  VAL = VAL || '<html lang="ru">';
  VAL = VAL || '<head>';
  VAL = VAL || '<meta charset="utf-8" />';
  VAL = VAL || '<style>';
  VAL = VAL || 'html { font-family: Tahoma, Verdana, Arial;';
  VAL = VAL || 'font-size: 10pt; ';
  VAL = VAL || '} ';
  VAL = VAL || '.title1 { font-size: 150%;';
  VAL = VAL || 'padding: 8px;';
  VAL = VAL || 'margin-bottom: 4px;';
  VAL = VAL || 'font-weight: bold;';
  VAL = VAL || 'background-color: #D4E157;';
  VAL = VAL || '} ';
  VAL = VAL || '.title2 { ';
  VAL = VAL || 'padding: 4px;';
  VAL = VAL || 'font-weight: bold;';
  VAL = VAL || '} ';
  VAL = VAL || 'td { ';
  VAL = VAL || 'padding: 0.25em 0.5em; ';
  VAL = VAL || 'border-right: 1px solid #808080; ';
  VAL = VAL || 'border-bottom: 1px solid #808080; ';
  VAL = VAL || 'max-width: 20rem; ';
  VAL = VAL || '} ';
  VAL = VAL || 'tr:not(.sx) td:first-child { ';
  VAL = VAL || 'border-left: 1px solid #808080; ';
  VAL = VAL || '} ';
  VAL = VAL || 'tr:first-child td { ';
  VAL = VAL || 'border-top: 1px solid #808080; ';
  VAL = VAL || '} ';
  VAL = VAL || '.yb { ';
  VAL = VAL || 'background-color: #B3E5FC; ';
  VAL = VAL || 'font-family: Georgia; ';
  VAL = VAL || '} ';
  VAL = VAL || '.yc { ';
  VAL = VAL || 'background-color: #FFE082; ';
  VAL = VAL || 'font-weight: bold; ';
  VAL = VAL || 'font-family: Georgia; ';
  VAL = VAL || '} ';
  VAL = VAL || '.y1, .y2 { ';
  VAL = VAL || 'background-color: #ECEFF1; ';
  VAL = VAL || 'font-family: Georgia; ';
  VAL = VAL || '} ';
  VAL = VAL || '.cy { ';
  VAL = VAL || 'width: 4rem; ';
  VAL = VAL || 'font-family: Georgia; ';
  VAL = VAL || '} ';
  VAL = VAL || '</style>';

  VAL = VAL || '</head>';
  VAL = VAL || '<body>';
  SUSPEND;

  -- Заголовок отчета
  VAL = '<div class="title1">Отчет ОО по показателям объема услуг/работ</div>';

  VAL = VAL || '<div class="title2">' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$OBJ_ID)) || '</div>';
  VAL = VAL || '<div class="title2">Отчетный период: ' || I$YEAR || ' год</div>';

  -- Заголовок таблицы
  VAL = VAL || '<table class="table" cellspacing="0" cellpadding="0">';

  VAL = VAL || '<tr class="thd fx">';
  VAL = VAL || '<td rowspan="2">№ п/п</td>';
  VAL = VAL || '<td rowspan="2">Наименование государственной услуги (работы)</td>';
  VAL = VAL || '<td rowspan="2">Реестровый номер базовой услуги или работы</td>';
  VAL = VAL || '<td rowspan="2">Технический номер</td>';
  VAL = VAL || '<td rowspan="2">Показатель объема</td>';
  VAL = VAL || '<td rowspan="2">Год</td>';
  VAL = VAL || '<td rowspan="2">Статус</td>';
  VAL = VAL || '<td colspan="8">Показатели объема ГЗ по годам</td>';
  VAL = VAL || '</tr>';
  VAL = VAL || '<tr class="thd sx">';
  VAL = VAL || '<td class="cy">' || (I$YEAR - 4) || '</td>';
  VAL = VAL || '<td class="cy">' || (I$YEAR - 3) || '</td>';
  VAL = VAL || '<td class="cy">' || (I$YEAR - 2) || '</td>';
  VAL = VAL || '<td class="cy">' || (I$YEAR - 1) || '</td>';
  VAL = VAL || '<td class="cy">' || (I$YEAR + 0) || '</td>';
  VAL = VAL || '<td class="cy">' || (I$YEAR + 1) || '</td>';
  VAL = VAL || '<td class="cy">' || (I$YEAR + 2) || '</td>';
  VAL = VAL || '<td class="cy">' || (I$YEAR + 3) || '</td>';
  VAL = VAL || '</tr>';
  SUSPEND;

  V$PREV_SCODE = -1;
  V$PREV_VNAME = '';
  N = 0;
  FOR
    SELECT L441.OBJ_ID, L442.OBJ_ID, L443.OBJ_ID, V3219.VAL, V3242.SVAL, V3211.VAL, V3214.LISTVAL_ID, V3244.LISTVAL_ID, V3245.VAL, V3247.VAL, V3248.VAL, V3249.VAL
    FROM LINKS L432
    JOIN LINKS L441 ON L441.PARENT_ID = L432.OBJ_ID AND L441.OBJ_TYPE_ID = 441 AND L441.DATE_DEL IS NULL
    JOIN VALI V3211 ON V3211.OBJ_ID = L441.OBJ_ID AND V3211.PARAM_ID = 3211 AND V3211.IS_DEL = 0 AND V3211.VAL >= :I$YEAR - 3 AND V3211.VAL <= :I$YEAR + 1
    JOIN VALL V3214 ON V3214.OBJ_ID = L441.OBJ_ID AND V3214.PARAM_ID = 3214 AND V3214.IS_DEL = 0
    JOIN LINKS L442 ON L442.PARENT_ID = L441.OBJ_ID AND L442.OBJ_TYPE_ID = 442 AND L442.DATE_DEL IS NULL
    JOIN VALI V3219 ON V3219.OBJ_ID = L442.OBJ_ID AND V3219.PARAM_ID = 3219 AND V3219.IS_DEL = 0
    JOIN LINKS L443 ON L443.PARENT_ID = L442.OBJ_ID AND L443.OBJ_TYPE_ID = 443 AND L443.DATE_DEL IS NULL
    JOIN VALS V3242 ON V3242.OBJ_ID = L443.OBJ_ID AND V3242.PARAM_ID = 3242 AND V3242.IS_DEL = 0
    LEFT JOIN VALL V3244 ON V3244.OBJ_ID = L443.OBJ_ID AND V3244.PARAM_ID = 3244 AND V3244.IS_DEL = 0
    LEFT JOIN VALF V3245 ON V3245.OBJ_ID = L443.OBJ_ID AND V3245.PARAM_ID = 3245 AND V3245.IS_DEL = 0
    LEFT JOIN VALF V3247 ON V3247.OBJ_ID = L443.OBJ_ID AND V3247.PARAM_ID = 3247 AND V3247.IS_DEL = 0
    LEFT JOIN VALF V3248 ON V3248.OBJ_ID = L443.OBJ_ID AND V3248.PARAM_ID = 3248 AND V3248.IS_DEL = 0
    LEFT JOIN VALF V3249 ON V3249.OBJ_ID = L443.OBJ_ID AND V3249.PARAM_ID = 3249 AND V3249.IS_DEL = 0
    WHERE L432.PARENT_ID = :I$OBJ_ID AND L432.OBJ_TYPE_ID = 432 AND L432.DATE_DEL IS NULL
      AND (V3214.LISTVAL_ID <> 13502 OR V3211.VAL = :I$YEAR + 1)
    ORDER BY 4, 5, 6, 7
    INTO :V$GZ_ID, :V$SECTION_ID, :V$PARAM_ID, :V$SECTION_CODE, :V$VNAME, :V$YEAR, :V$STAGE, :V$U, :V$V1, :V$V2, :V$V3, :V$V4
  DO
  BEGIN
    IF(V$PREV_SCODE <> V$SECTION_CODE OR V$PREV_VNAME <> V$VNAME) THEN
    BEGIN
      V$PREV_SCODE = V$SECTION_CODE;
      V$PREV_VNAME = V$VNAME;
      N = N + 1;
      NY = 1;

      SELECT V3220.VAL
      FROM VALS V3220
      WHERE V3220.OBJ_ID = :V$SECTION_ID AND V3220.PARAM_ID = 3220 AND V3220.IS_DEL = 0
      INTO :V$SECNAME;

      SELECT V3221.VAL
      FROM VALS V3221
      WHERE V3221.OBJ_ID = :V$SECTION_ID AND V3221.PARAM_ID = 3221 AND V3221.IS_DEL = 0
      INTO :V$CODE1;

      SELECT V3222.VAL
      FROM VALS V3222
      WHERE V3222.OBJ_ID = :V$SECTION_ID AND V3222.PARAM_ID = 3222 AND V3222.IS_DEL = 0
      INTO :V$CODE2;

      -- Сколько у нас будет строк в этом разделе ?
      SELECT COUNT(*)
      FROM LINKS L432
      JOIN LINKS L441 ON L441.PARENT_ID = L432.OBJ_ID AND L441.OBJ_TYPE_ID = 441 AND L441.DATE_DEL IS NULL
      JOIN VALI V3211 ON V3211.OBJ_ID = L441.OBJ_ID AND V3211.PARAM_ID = 3211 AND V3211.IS_DEL = 0 AND V3211.VAL >= :I$YEAR - 3 AND V3211.VAL <= :I$YEAR + 1
      JOIN VALL V3214 ON V3214.OBJ_ID = L441.OBJ_ID AND V3214.PARAM_ID = 3214 AND V3214.IS_DEL = 0
      JOIN LINKS L442 ON L442.PARENT_ID = L441.OBJ_ID AND L442.OBJ_TYPE_ID = 442 AND L442.DATE_DEL IS NULL
      JOIN VALI V3219 ON V3219.OBJ_ID = L442.OBJ_ID AND V3219.PARAM_ID = 3219 AND V3219.IS_DEL = 0 AND V3219.VAL = :V$SECTION_CODE
      JOIN LINKS L443 ON L443.PARENT_ID = L442.OBJ_ID AND L443.OBJ_TYPE_ID = 443 AND L443.DATE_DEL IS NULL
      JOIN VALS V3242 ON V3242.OBJ_ID = L443.OBJ_ID AND V3242.PARAM_ID = 3242 AND V3242.IS_DEL = 0 AND V3242.SVAL = :V$VNAME
      WHERE L432.PARENT_ID = :I$OBJ_ID AND L432.OBJ_TYPE_ID = 432 AND L432.DATE_DEL IS NULL
        AND (V3214.LISTVAL_ID <> 13502 OR V3211.VAL = :I$YEAR + 1)
      INTO :C;

      VAL = '<tr class="v">';
      VAL = VAL || '<td rowspan="' || C || '">' || N || '</td>';
      VAL = VAL || '<td rowspan="' || C || '">' || V$SECNAME || '</td>';
      VAL = VAL || '<td rowspan="' || C || '">' || V$CODE1 || '</td>';
      VAL = VAL || '<td rowspan="' || C || '">' || V$CODE2 || '</td>';
      VAL = VAL || '<td rowspan="' || C || '">' || V$VNAME || '</td>';
      SUSPEND;
    END

    IF(NY = 1) THEN VAL = ''; ELSE VAL = '<tr class="v nx">';
    VAL = VAL || '<td>' || V$YEAR || '</td>';
    S1 = COALESCE((SELECT VAL FROM LISTVAL_TEXT(:V$STAGE)), '?');
    IF(V$STAGE = 13503) THEN S1 = 'Действ.';
    S1 = REPLACE(S1, 'енение', '.');
    VAL = VAL || '<td>' || S1 || '</td>';

    -- Пустые ячейки до данных
    Y = I$YEAR - 3;
    WHILE(Y < V$YEAR) DO BEGIN Y = Y + 1; VAL = VAL || '<td></td>'; END

    -- Сами данные
    S1 = CAST(V$V1 AS NUMERIC(18, 1));
    S2 = CAST(V$V1 AS NUMERIC(18, 0));
    VAL = VAL || '<td class="yb">' || COALESCE(IIF(V$U = 13837, S1, S2), '-') || '</td>';
    S1 = CAST(V$V2 AS NUMERIC(18, 1));
    S2 = CAST(V$V2 AS NUMERIC(18, 0));
    VAL = VAL || '<td class="yc">' || COALESCE(IIF(V$U = 13837, S1, S2), '-') || '</td>';
    S1 = CAST(V$V3 AS NUMERIC(18, 1));
    S2 = CAST(V$V3 AS NUMERIC(18, 0));
    VAL = VAL || '<td class="y1">' || COALESCE(IIF(V$U = 13837, S1, S2), '-') || '</td>';
    S1 = CAST(V$V4 AS NUMERIC(18, 1));
    S2 = CAST(V$V4 AS NUMERIC(18, 0));
    VAL = VAL || '<td class="y2">' || COALESCE(IIF(V$U = 13837, S1, S2), '-') || '</td>';
    Y = Y + 3;

    -- Пустые ячейки после данных
    WHILE(Y <= I$YEAR + 3) DO BEGIN Y = Y + 1; VAL = VAL || '<td></td>'; END

    VAL = VAL || '</tr>';
    NY = NY + 1;
    SUSPEND;

  END

  VAL = '</table></body></html>';
  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GZ_RESULTS (
    I$OBJ_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
declare variable V$SECTION_ID bigint;
declare variable V$I bigint;
declare variable V$OBJ_ID bigint;
declare variable V$UNITS bigint;
declare variable S varchar(1000);
declare variable S2 varchar(400);
declare variable V$V1 float;
declare variable V$V2 float;
declare variable V$V3 float;
declare variable V$V4 float;
declare variable V$V5 float;
declare variable V$RES float;
begin

  TAG_NAME = 'year';
  VAL = NULL;
  SELECT VAL
  FROM VALI
  WHERE OBJ_ID = :I$OBJ_ID AND PARAM_ID = 3211 AND IS_DEL = 0
  INTO :VAL;
  IF(VAL IS NULL) THEN EXCEPTION DATA_ERROR 'Государственное задание не найдено, либо не заполнен год';
  SUSPEND;

  TAG_NAME = 'sections::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L442.OBJ_ID, V3218.VAL, V3220.VAL
    FROM LINKS L442
    JOIN VALI V3218 ON V3218.OBJ_ID = L442.OBJ_ID AND V3218.PARAM_ID = 3218 AND V3218.IS_DEL = 0
    JOIN VALS V3220 ON V3220.OBJ_ID = L442.OBJ_ID AND V3220.PARAM_ID = 3220 AND V3220.IS_DEL = 0
    WHERE L442.PARENT_ID = :I$OBJ_ID AND L442.OBJ_TYPE_ID = 442 AND L442.DATE_DEL IS NULL
    ORDER BY 2
    INTO :V$SECTION_ID, :V$I, :S
  DO
  BEGIN
    TAG_NAME = 'sections:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'sections:r:id';
    VAL = V$SECTION_ID;
    SUSPEND;
    TAG_NAME = 'sections:r:index';
    VAL = V$I;
    SUSPEND;
    TAG_NAME = 'sections:r:name';
    VAL = S;
    SUSPEND;

    TAG_NAME = 'sections:r:params::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT L.OBJ_ID, L.OBJ_TYPE_ID, V1.VAL, V2.LISTVAL_ID, C.VAL, VV1.VAL, VV2.VAL, VV3.VAL, VV4.VAL, VV5.VAL, VRES.VAL
      FROM LINKS L
      JOIN VALS V1 ON V1.OBJ_ID = L.OBJ_ID AND V1.PARAM_ID IN (3242, 3250) AND V1.IS_DEL = 0
      JOIN VALL V2 ON V2.OBJ_ID = L.OBJ_ID AND V2.PARAM_ID IN (3244, 3251) AND V2.IS_DEL = 0
      LEFT JOIN LISTVAL_TEXT(V2.LISTVAL_ID) C ON 1 = 1
      LEFT JOIN VALF VV1 ON VV1.OBJ_ID = L.OBJ_ID AND VV1.PARAM_ID IN (3245, 3252) AND VV1.IS_DEL = 0
      LEFT JOIN VALF VV2 ON VV2.OBJ_ID = L.OBJ_ID AND VV2.PARAM_ID IN (3246, 3253) AND VV2.IS_DEL = 0
      LEFT JOIN VALF VV3 ON VV3.OBJ_ID = L.OBJ_ID AND VV3.PARAM_ID IN (3247, 3254) AND VV3.IS_DEL = 0
      LEFT JOIN VALF VV4 ON VV4.OBJ_ID = L.OBJ_ID AND VV4.PARAM_ID IN (3248, 3255) AND VV4.IS_DEL = 0
      LEFT JOIN VALF VV5 ON VV5.OBJ_ID = L.OBJ_ID AND VV5.PARAM_ID IN (3249, 3256) AND VV5.IS_DEL = 0
      LEFT JOIN VALF VRES ON VRES.OBJ_ID = L.OBJ_ID AND VRES.PARAM_ID IN (3275, 3276) AND VRES.IS_DEL = 0
      WHERE L.PARENT_ID = :V$SECTION_ID AND L.OBJ_TYPE_ID IN (443, 444) AND L.DATE_DEL IS NULL
      ORDER BY L.OBJ_TYPE_ID, L.LINK_ID, V1.VAL
      INTO :V$OBJ_ID, :V$I, :S, :V$UNITS, :S2, :V$V1, :V$V2, :V$V3, :V$V4, :V$V5, :V$RES
    DO
    BEGIN
      TAG_NAME = 'sections:r:params:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'sections:r:params:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'sections:r:params:r:type';
      VAL = V$I;
      SUSPEND;
      TAG_NAME = 'sections:r:params:r:name';
      VAL = S;
      SUSPEND;
      TAG_NAME = 'sections:r:params:r:units';
      VAL = S2;
      SUSPEND;
      TAG_NAME = 'sections:r:params:r:units_id';
      VAL = V$UNITS;
      SUSPEND;
      TAG_NAME = 'sections:r:params:r:v1';
      VAL = V$V1;
      SUSPEND;
      TAG_NAME = 'sections:r:params:r:v2';
      VAL = V$V2;
      SUSPEND;
      TAG_NAME = 'sections:r:params:r:v3';
      VAL = V$V3;
      SUSPEND;
      TAG_NAME = 'sections:r:params:r:v4';
      VAL = V$V4;
      SUSPEND;
      TAG_NAME = 'sections:r:params:r:v5';
      VAL = V$V5;
      SUSPEND;
      TAG_NAME = 'sections:r:params:r:result';
      VAL = V$RES;
      SUSPEND;
    END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GZ_SAVE_RESULT (
    I$PARAM_ID BIGINT,
    I$VAL FLOAT,
    I$USER_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$YEAR bigint;
declare variable V$STATUS bigint;
declare variable V$FIN bigint;
declare variable V$T bigint;
begin

  -- Проверяем параметр еще раз
  SELECT FIRST 1 LP442.OBJ_ID, LP442.OBJ_TYPE_ID, V3211.VAL, V3214.LISTVAL_ID, V3274.LISTVAL_ID
  FROM LINKS LP442
  JOIN LINKS LP441 ON LP441.OBJ_ID = LP442.PARENT_ID AND LP441.PARENT_TYPE_ID = 441 AND LP441.DATE_DEL IS NULL
  JOIN VALI V3211 ON V3211.OBJ_ID = LP441.PARENT_ID AND V3211.PARAM_ID = 3211 AND V3211.IS_DEL = 0
  JOIN VALL V3214 ON V3214.OBJ_ID = LP441.PARENT_ID AND V3214.PARAM_ID = 3214 AND V3214.IS_DEL = 0
  JOIN VALL V3274 ON V3274.OBJ_ID = LP441.PARENT_ID AND V3274.PARAM_ID = 3274 AND V3274.IS_DEL = 0
  JOIN LINKS LP432 ON LP432.OBJ_ID = LP441.PARENT_ID AND LP432.PARENT_TYPE_ID = 432 AND LP432.DATE_DEL IS NULL
  WHERE LP442.OBJ_ID = :I$PARAM_ID AND LP442.PARENT_TYPE_ID = 442 AND LP442.DATE_DEL IS NULL
  INTO :OBJ_ID, :V$T, :V$YEAR, :V$STATUS, :V$FIN;

  -- Нельзя вводить значения в неутвержденный ГЗ, а также в ГЗ со статусом ниже максимального за тот же год

  IF(OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Задание, раздел или параметр не найдены или были удалены';
  IF(V$STATUS = 13502) THEN EXCEPTION DATA_ERROR 'Нельзя вводить результаты в проект задания';
  IF(V$FIN <> 2) THEN EXCEPTION DATA_ERROR 'Результаты можно вводить только в финальный вариант Задания';

  -- Задание утверждается на будущий год, т.е. результы можно вводить для заданий прошлого и позапрошлого года, но пока разрешаем и за текущий
  IF(V$YEAR < EXTRACT(YEAR FROM CURRENT_DATE) - 2 OR V$YEAR > EXTRACT(YEAR FROM CURRENT_DATE)) THEN EXCEPTION DATA_ERROR 'Результаты можно вводить только за прошлый отчетный год';

  IF(I$VAL IS NULL) THEN
    UPDATE VALF
    SET IS_DEL = 1
    WHERE OBJ_ID = :I$PARAM_ID AND PARAM_ID = IIF(:V$T = 443, 3275, 3276) AND IS_DEL = 0;
  ELSE
    UPDATE OR INSERT INTO VALF
    (OBJ_ID, PARAM_ID, VAL,  IS_DEL)
    VALUES (:I$PARAM_ID, IIF(:V$T = 443, 3275, 3276), :I$VAL, 0);

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE GZ_VAL_AFTER (
    I$OBJ_ID BIGINT,
    I$PARAM_ID BIGINT,
    I$VAL VARCHAR(4000),
    I$IS_DEL SMALLINT)
AS
declare variable V$FOLDER_ID bigint;
declare variable V$OBJ_ID bigint;
declare variable V$GZ_ID bigint;
declare variable V$TYPE_ID bigint;
declare variable V$PARENT_ID bigint;
declare variable V$DATE date;
declare variable VM bigint;
declare variable V bigint;
declare variable I bigint;
declare variable XI bigint;
begin

  IF(I$IS_DEL <> 0) THEN EXCEPTION DATA_ERROR 'Нельзя удалить данный параметр';

  -- Если задание стоит в статусе утвержденного, менять нельзя все кроме самого статуса, а также результат выполнения
  IF(I$PARAM_ID <> 3214) THEN
  BEGIN

    V$GZ_ID = I$OBJ_ID;
    V$OBJ_ID = I$OBJ_ID;
    V$TYPE_ID = 0;
    WHILE(V$OBJ_ID IS NOT NULL AND V$TYPE_ID <> 441) DO
    BEGIN
      V$TYPE_ID = NULL;
      SELECT L.OBJ_TYPE_ID, L.PARENT_ID
      FROM LINKS L
      WHERE L.OBJ_ID = :V$OBJ_ID AND L.PARENT_TYPE_ID IN (432, 441, 442)
      INTO :V$TYPE_ID, :V$PARENT_ID;

      IF(V$TYPE_ID IS NULL) THEN EXCEPTION DATA_ERROR 'E001 ' || I$PARAM_ID;
      IF(V$TYPE_ID = 441) THEN V$GZ_ID = V$OBJ_ID;
      V$OBJ_ID = V$PARENT_ID;
    END

    IF(V$TYPE_ID <> 441) THEN EXCEPTION DATA_ERROR 'E002 ' || I$PARAM_ID;

    IF(I$PARAM_ID IN (3275, 3276, 3301, 3302)) THEN
    BEGIN
      -- !!! Можно менять только в финальном варианте, с ограничением по году ГЗ
    END
    ELSE
    BEGIN
      IF(NOT EXISTS(
        SELECT FIRST 1 1
        FROM VALL V3214
        WHERE V3214.OBJ_ID = :V$GZ_ID AND V3214.PARAM_ID = 3214 AND V3214.IS_DEL = 0 AND V3214.LISTVAL_ID = 13502
      ))
      THEN EXCEPTION DATA_ERROR 'Нельзя изменять данные в действующем задании';
    END

  END

  IF(I$PARAM_ID = 3211) THEN
  BEGIN
    -- Год ГЗ
    -- В цепочке заданий одного года год нельзя менять на другое значение
    SELECT FIRST 1 V3211.VAL
    FROM VALR V3241
    JOIN VALI V3211 ON V3211.OBJ_ID = V3241.VAL AND V3211.PARAM_ID = 3211 AND V3211.IS_DEL = 0
    WHERE V3241.OBJ_ID = :I$OBJ_ID AND V3241.PARAM_ID = 3241 AND V3241.IS_DEL = 0
    INTO :V;

    IF(V IS NOT NULL AND CAST(I$VAL AS INTEGER) <> V) THEN EXCEPTION DATA_ERROR 'Для измененного Задания год должен совпадать с первоначальным';
    IF(CAST(I$VAL AS INTEGER) > EXTRACT(YEAR FROM CURRENT_DATE) + 1) THEN EXCEPTION DATA_ERROR 'Нельзя указывать год задания позднее, чем следующий календарный год';
    IF(CAST(I$VAL AS INTEGER) < 2010) THEN EXCEPTION DATA_ERROR 'Нельзя указывать год задания ранее чем 2010';

    -- Год госзадания - переставляем в следующие периоды
    SELECT 1 FROM VAL_ADD(3212, :I$OBJ_ID, CAST(:I$VAL AS INTEGER) + 1, NULL, :I$IS_DEL) INTO :I;
    SELECT 1 FROM VAL_ADD(3213, :I$OBJ_ID, CAST(:I$VAL AS INTEGER) + 2, NULL, :I$IS_DEL) INTO :I;
  END
  ELSE IF(I$PARAM_ID = 3214) THEN
  BEGIN
    -- Статус
    -- Проверяем статус родительского задания. Если оно в статусе, отличном от действующего
    SELECT FIRST 1 V3211.VAL
    FROM VALR V3241
    JOIN VALI V3211 ON V3211.OBJ_ID = V3241.VAL AND V3211.PARAM_ID = 3211 AND V3211.IS_DEL = 0
    WHERE V3241.OBJ_ID = :I$OBJ_ID AND V3241.PARAM_ID = 3241 AND V3241.IS_DEL = 0
    INTO :VM;

    IF(VM <> 13502 AND I$VAL <> 13502 AND CAST(I$VAL AS INTEGER) <= VM) THEN
      EXCEPTION DATA_ERROR 'Измененное задание можно переводить только в статус "Изменение" не ниже предыдущего варианта задания';
    IF(VM IS NULL AND I$VAL <> 13502 AND I$VAL <> 13503) THEN
      EXCEPTION DATA_ERROR 'Новое задание можно фиксировать только в статусе "Действующий"';
    IF(VM = 13502 AND I$VAL <> 13502) THEN
      EXCEPTION DATA_ERROR 'Предыдущий вариант Задания находится в статусе "Проект", нельзя установить более высокий статус';

    -- Статус дочернего задания
    SELECT FIRST 1 V3214.LISTVAL_ID
    FROM VALR V3241
    JOIN LINKS LP432 ON LP432.OBJ_ID = V3241.OBJ_ID AND LP432.PARENT_ID = 432 AND LP432.DATE_DEL IS NULL
    JOIN VALL V3214 ON V3214.OBJ_ID = V3241.OBJ_ID AND V3214.PARAM_ID = 3214 AND V3214.IS_DEL = 0
    WHERE V3241.PARAM_ID = 3241 AND V3241.IS_DEL = 0 AND V3241.VAL = :I$OBJ_ID
    INTO :V;

    IF(V <> 13502) THEN EXCEPTION DATA_ERROR 'При наличии измененного задания, нельзя менять статус предыдущего варианта этого задания';

    IF(I$VAL = 13503) THEN
    BEGIN
      -- При первом утверждении Задания все старые задания переносим в архив
      SELECT FIRST 1 L432.OBJ_ID
      FROM LINKS L2
      JOIN LINKS L432 ON L432.PARENT_ID = L2.OBJ_ID AND L432.OBJ_TYPE_ID = 432 AND L432.DATE_DEL IS NULL
      JOIN VALI V3210 ON V3210.OBJ_ID = L432.OBJ_ID AND V3210.PARAM_ID = 3210 AND V3210.IS_DEL = 0 AND V3210.VAL = 1
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      INTO :V$FOLDER_ID;

      SELECT FIRST 1 V3211.VAL
      FROM VALI V3211
      WHERE V3211.OBJ_ID = :I$OBJ_ID AND V3211.PARAM_ID = 3211 AND V3211.IS_DEL = 0
      INTO :V;

      IF(V IS NULL OR V > EXTRACT(YEAR FROM CURRENT_DATE) + 1) THEN EXCEPTION DATA_ERROR 'Не указан год задания';

      -- Надо проверить, заполнены ли фактические результаты !!!

      FOR
        SELECT L442.OBJ_ID
        FROM LINKS LP441
        JOIN LINKS L442 ON L442.PARENT_ID = LP441.PARENT_ID AND L442.OBJ_TYPE_ID = 442 AND L442.DATE_DEL IS NULL
        JOIN VALI V3211 ON V3211.OBJ_ID = L442.OBJ_ID AND V3211.PARAM_ID = 3211 AND V3211.IS_DEL = 0 AND V3211.VAL < :V
        WHERE LP441.OBJ_ID = :I$OBJ_ID AND LP441.PARENT_TYPE_ID = 441 AND LP441.DATE_DEL IS NULL
        ORDER BY 1
        INTO :V$OBJ_ID
      DO
      BEGIN
        UPDATE LINKS L
        SET L.PARENT_ID = :V$FOLDER_ID
        WHERE L.OBJ_ID = :V$OBJ_ID;
      END
    END

    -- Год задания
    SELECT FIRST 1 V3211.VAL
    FROM VALI V3211
    WHERE V3211.OBJ_ID = :I$OBJ_ID AND V3211.PARAM_ID = 3211 AND V3211.IS_DEL = 0
    INTO :V;

    -- Дата утверждения
    SELECT FIRST 1 V3300.VAL
    FROM VALD V3300
    WHERE V3300.OBJ_ID = :I$OBJ_ID AND V3300.PARAM_ID = 3300 AND V3300.IS_DEL = 0
    INTO :V$DATE;

    IF(I$VAL = 13502) THEN
    BEGIN
      -- Откатываем задание в проект - снимаем статус действующего, и выставляем у последнего из действующих
      UPDATE VALL SET LISTVAL_ID = 3 WHERE OBJ_ID = :I$OBJ_ID AND PARAM_ID = 3274 AND IS_DEL = 0 AND LISTVAL_ID <> 3;

      -- Очищаем дату утверждения
      UPDATE VALD SET IS_DEL = 1 WHERE OBJ_ID = :I$OBJ_ID AND PARAM_ID = 3300 AND IS_DEL = 0;

      V$OBJ_ID = NULL;
      SELECT FIRST 1 L442.OBJ_ID
      FROM LINKS LP441
      JOIN LINKS L442 ON L442.PARENT_ID = LP441.PARENT_ID AND L442.OBJ_TYPE_ID = 442 AND L442.DATE_DEL IS NULL AND L442.OBJ_ID <> :I$OBJ_ID
      JOIN VALI V3211 ON V3211.OBJ_ID = L442.OBJ_ID AND V3211.PARAM_ID = 3211 AND V3211.IS_DEL = 0 AND V3211.VAL = :V
      JOIN VALL V3214 ON V3214.OBJ_ID = L442.OBJ_ID AND V3214.PARAM_ID = 3214 AND V3214.IS_DEL = 0 AND V3214.LISTVAL_ID <> 13502
      WHERE LP441.OBJ_ID = :I$OBJ_ID AND LP441.PARENT_TYPE_ID = 441 AND LP441.DATE_DEL IS NULL
      ORDER BY V3214.LISTVAL_ID DESC
      INTO :V$OBJ_ID;

      UPDATE VALL SET LISTVAL_ID = 2 WHERE OBJ_ID = :V$OBJ_ID AND PARAM_ID = 3274 AND IS_DEL = 0 AND LISTVAL_ID <> 2;
    END
    ELSE
    BEGIN
      -- При утверждении в статусе выше проекта

      -- Все ли показатели или единицы заданы ?
      V$OBJ_ID = NULL;
      SELECT FIRST 1 L442.OBJ_ID
      FROM LINKS L442
      JOIN LINKS L443 ON L443.PARENT_ID = L442.OBJ_ID AND L443.OBJ_TYPE_ID = 443 AND L443.DATE_DEL IS NULL
      LEFT JOIN VALL V3244 ON V3244.OBJ_ID = L443.OBJ_ID AND V3244.PARAM_ID = 3244 AND V3244.IS_DEL = 0
      LEFT JOIN VALF V3245 ON V3245.OBJ_ID = L443.OBJ_ID AND V3245.PARAM_ID = 3245 AND V3245.IS_DEL = 0
      LEFT JOIN VALF V3246 ON V3246.OBJ_ID = L443.OBJ_ID AND V3246.PARAM_ID = 3246 AND V3246.IS_DEL = 0
      LEFT JOIN VALF V3247 ON V3247.OBJ_ID = L443.OBJ_ID AND V3247.PARAM_ID = 3247 AND V3247.IS_DEL = 0
      LEFT JOIN VALF V3248 ON V3248.OBJ_ID = L443.OBJ_ID AND V3248.PARAM_ID = 3248 AND V3248.IS_DEL = 0
      LEFT JOIN VALF V3249 ON V3249.OBJ_ID = L443.OBJ_ID AND V3249.PARAM_ID = 3249 AND V3249.IS_DEL = 0
      WHERE L442.PARENT_ID = :I$OBJ_ID AND L442.OBJ_TYPE_ID = 442 AND L442.DATE_DEL IS NULL AND
        (V3244.LISTVAL_ID IS NULL OR V3245.VAL IS NULL OR V3246.VAL IS NULL OR V3247.VAL IS NULL OR V3248.VAL IS NULL OR V3249.VAL IS NULL)
      INTO :V$OBJ_ID;

      IF(V$OBJ_ID IS NOT NULL) THEN
        EXCEPTION DATA_ERROR 'Не все показатели количества заданы, проверьте единицы измерения и значения для ' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$OBJ_ID));
      IF(V$DATE IS NULL) THEN
        EXCEPTION DATA_ERROR 'Не указана дата утверждения';

      SELECT FIRST 1 L442.OBJ_ID
      FROM LINKS L442
      JOIN LINKS L444 ON L444.PARENT_ID = L442.OBJ_ID AND L444.OBJ_TYPE_ID = 444 AND L444.DATE_DEL IS NULL
      LEFT JOIN VALL V3251 ON V3251.OBJ_ID = L444.OBJ_ID AND V3251.PARAM_ID = 3251 AND V3251.IS_DEL = 0
      LEFT JOIN VALF V3252 ON V3252.OBJ_ID = L444.OBJ_ID AND V3252.PARAM_ID = 3252 AND V3252.IS_DEL = 0
      LEFT JOIN VALF V3253 ON V3253.OBJ_ID = L444.OBJ_ID AND V3253.PARAM_ID = 3253 AND V3253.IS_DEL = 0
      LEFT JOIN VALF V3254 ON V3254.OBJ_ID = L444.OBJ_ID AND V3254.PARAM_ID = 3254 AND V3254.IS_DEL = 0
      LEFT JOIN VALF V3255 ON V3255.OBJ_ID = L444.OBJ_ID AND V3255.PARAM_ID = 3255 AND V3255.IS_DEL = 0
      LEFT JOIN VALF V3256 ON V3256.OBJ_ID = L444.OBJ_ID AND V3256.PARAM_ID = 3256 AND V3256.IS_DEL = 0
      WHERE L442.PARENT_ID = :I$OBJ_ID AND L442.OBJ_TYPE_ID = 442 AND L442.DATE_DEL IS NULL AND
        (V3251.LISTVAL_ID IS NULL OR V3252.VAL IS NULL OR V3253.VAL IS NULL OR V3254.VAL IS NULL OR V3255.VAL IS NULL OR V3256.VAL IS NULL)
      INTO :V$OBJ_ID;

      IF(V$OBJ_ID IS NOT NULL) THEN
        EXCEPTION DATA_ERROR 'Не все показатели качества заданы, проверьте единицы измерения и значения для ' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$OBJ_ID));

      -- Выставляем статус актуального задания, и снимаем его у всех предыдущих этого года
      UPDATE VALL SET LISTVAL_ID = 2 WHERE OBJ_ID = :I$OBJ_ID AND PARAM_ID = 3274 AND IS_DEL = 0 AND LISTVAL_ID <> 2;

      FOR
        SELECT L442.OBJ_ID
        FROM LINKS LP441
        JOIN LINKS L442 ON L442.PARENT_ID = LP441.PARENT_ID AND L442.OBJ_TYPE_ID = 442 AND L442.DATE_DEL IS NULL AND L442.OBJ_ID <> :I$OBJ_ID
        JOIN VALI V3211 ON V3211.OBJ_ID = L442.OBJ_ID AND V3211.PARAM_ID = 3211 AND V3211.IS_DEL = 0 AND V3211.VAL = :V
        WHERE LP441.OBJ_ID = :I$OBJ_ID AND LP441.PARENT_TYPE_ID = 441 AND LP441.DATE_DEL IS NULL
        ORDER BY 1
        INTO :V$OBJ_ID
      DO
      BEGIN
        UPDATE VALL SET LISTVAL_ID = 3 WHERE OBJ_ID = :V$OBJ_ID AND PARAM_ID = 3274 AND IS_DEL = 0 AND LISTVAL_ID <> 3;
      END
    END

  END
  ELSE IF(I$PARAM_ID = 3218) THEN
  BEGIN
    -- Порядковый номер раздела
    -- Перенумеровывать надо вообще все пункты кроме текущего
    SELECT COUNT(*)
    FROM LINKS LP441
    JOIN LINKS L442 ON L442.PARENT_ID = LP441.PARENT_ID AND L442.OBJ_TYPE_ID = 442 AND L442.DATE_DEL IS NULL
    WHERE LP441.OBJ_ID = :I$OBJ_ID AND LP441.PARENT_TYPE_ID = 441 AND LP441.DATE_DEL IS NULL
    INTO :V;

    VM = CAST(I$VAL AS INTEGER);
    IF(VM <= 0 OR VM > V) THEN EXCEPTION DATA_ERROR 'Порядковый номер не может быть <= 0 или превышать количество разделов (' || V || ')';

    XI = 0;
    V = 1;
    FOR
      SELECT L442.OBJ_ID, V3218.VAL
      FROM LINKS LP441
      JOIN LINKS L442 ON L442.PARENT_ID = LP441.PARENT_ID AND L442.OBJ_TYPE_ID = 442 AND L442.DATE_DEL IS NULL AND L442.OBJ_ID <> :I$OBJ_ID
      JOIN VALI V3218 ON V3218.OBJ_ID = L442.OBJ_ID AND V3218.PARAM_ID = 3218 AND V3218.IS_DEL = 0
      WHERE LP441.OBJ_ID = :I$OBJ_ID AND LP441.PARENT_TYPE_ID = 441 AND LP441.DATE_DEL IS NULL
      ORDER BY V3218.VAL
      INTO :V$OBJ_ID, :I
    DO
    BEGIN
      -- В момент перехода индекса от "до" к "после" добавляем окно
      IF(XI < VM AND I >= VM) THEN V = V + 1;
      XI = I;
      UPDATE VALI V3218
      SET VAL = :V
      WHERE V3218.OBJ_ID = :V$OBJ_ID AND V3218.PARAM_ID = 3218 AND V3218.IS_DEL = 0 AND V3218.VAL <> :V;
      V = V + 1;
    END
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE HAS_FALSE_PUPIL_WITH_EDU_DOC (
    I$YEAR BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    RESULT SMALLINT)
AS
declare variable V$PUPIL_ID bigint;
declare variable V$STAGE_ID bigint;
begin
    RESULT = 0;
    FOR
        SELECT L7.OBJ_ID,
               L10.OBJ_ID
        FROM LINKS L2

        JOIN LINKS L7
        ON L7.PARENT_ID = L2.OBJ_ID
        AND L7.OBJ_TYPE_ID = 7
        AND L7.DATE_DEL IS NULL

        JOIN LINKS L8
        ON L8.PARENT_ID = L7.OBJ_ID
        AND L8.OBJ_TYPE_ID = 8
        AND L8.DATE_DEL IS NULL

        JOIN LINKS L125
        ON L125.PARENT_ID = L8.OBJ_ID
        AND L125.OBJ_TYPE_ID = 125
        AND L125.DATE_DEL IS NULL

        JOIN LINKS L10
        ON L10.PARENT_ID = L125.OBJ_ID
        AND L10.OBJ_TYPE_ID = 10
        AND L10.DATE_DEL IS NULL
        AND EXISTS(
            SELECT FIRST 1 1
            FROM LINKS L
            WHERE L.OBJ_ID = L10.OBJ_ID
            AND L.PARENT_TYPE_ID IN (81,82,83)
            AND L.DATE_DEL IS NULL
        )

        WHERE L2.PARENT_ID IS NULL
        AND L2.OBJ_TYPE_ID = 2
        AND L2.DATE_DEL IS NULL

        INTO :V$STAGE_ID,
             :V$PUPIL_ID
    DO
    BEGIN
        IF ((SELECT FIRST 1
                    FORM_ID
             FROM CERTIFICATE_PUPIL_INFO_GET (
                :I$YEAR,
                :V$STAGE_ID,
                :V$PUPIL_ID,
                :I$USER_ID
             )) IS NOT NULL) THEN
        BEGIN
            RESULT = 1;
        END
    END
    SUSPEND;
end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE HOUSE_GUID_WRITE_IN (
    MANUAL_REG SMALLINT = 0)
RETURNS (
    RESULT VARCHAR(1000),
    OBJ_CAPTION VARCHAR(255),
    PARAM_CAPTION VARCHAR(255),
    OLD_ADDR_VALUE VARCHAR(255),
    NEW_ADDR_VALUE VARCHAR(255),
    HOUSEGUID VARCHAR(36),
    POSTALCODE VARCHAR(15),
    OKATO VARCHAR(15))
AS
declare variable I integer;
declare variable DBPATH varchar(255);
declare variable OBJ_ID bigint;
declare variable OBJ_TYPE_ID bigint;
declare variable PARAM_ID bigint;
declare variable REGION varchar(255);
declare variable REGIONGUID varchar(36);
declare variable REGION_STN varchar(255);
declare variable REGION_TN varchar(255);
declare variable DISTRICT varchar(255);
declare variable DISTRICTGUID varchar(36);
declare variable DISTRICT_STN varchar(255);
declare variable DISTRICT_TN varchar(255);
declare variable TOWN varchar(255);
declare variable TOWNGUID varchar(36);
declare variable TOWN_STN varchar(255);
declare variable TOWN_TN varchar(255);
declare variable SETTLEMENT varchar(255);
declare variable SETTLEMENTGUID varchar(36);
declare variable SETTLEMENT_STN varchar(255);
declare variable SETTLEMENT_TN varchar(255);
declare variable STREET varchar(255);
declare variable STREETGUID varchar(36);
declare variable STREET_STN varchar(255);
declare variable STREET_TN varchar(255);
declare variable HOUSE varchar(255);
declare variable CORP varchar(255);
declare variable LIT varchar(255);
declare variable PARENTGUID varchar(36);
begin

  -- Функционал утрачен, формат хранения изменился с 01.2021

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE IAC3_FINDLEARNERSBYEDUDOC (
    I$NUMERAL VARCHAR(20),
    I$TYPECODE INTEGER = NULL,
    I$SERIES VARCHAR(20) = NULL,
    I$USER_ID BIGINT = 1)
RETURNS (
    PID BIGINT)
AS
BEGIN
    FOR
        SELECT V565.OBJ_ID FROM VALS V565
        JOIN LINKS LP9
        ON LP9.OBJ_ID = V565.OBJ_ID
        AND V565.PARAM_ID = 565
        AND LP9.PARENT_TYPE_ID = 10
        AND LP9.DATE_DEL IS NULL
        
        LEFT JOIN VALL V50
        ON V50.OBJ_ID = V565.OBJ_ID
        AND V50.PARAM_ID = 50
        AND V50.IS_DEL = 0
        
        LEFT JOIN VALS V564
        ON V564.OBJ_ID = V565.OBJ_ID
        AND V564.PARAM_ID = 564
        AND V564.IS_DEL = 0
        
        WHERE V565.SVAL = :I$NUMERAL
        AND V565.IS_DEL = 0
        AND ((:I$TYPECODE IS NULL) OR (V50.LISTVAL_ID LIKE :I$TYPECODE))
        AND ((:I$SERIES IS NULL) OR (V564.SVAL LIKE :I$SERIES))
        INTO :PID
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE IAC3_FINDLEARNERSBYIDENTDOC (
    I$NUMERAL VARCHAR(20),
    I$TYPECODE INTEGER = NULL,
    I$SERIES VARCHAR(20) = NULL,
    I$USER_ID BIGINT = 1)
RETURNS (
    PID BIGINT)
AS
BEGIN
    FOR
        SELECT V559.OBJ_ID FROM VALS V559
        JOIN LINKS LP9
        ON LP9.OBJ_ID = V559.OBJ_ID
        AND V559.PARAM_ID = 559
        AND LP9.PARENT_TYPE_ID = 10
        AND LP9.DATE_DEL IS NULL
        
        LEFT JOIN VALL V441
        ON V441.OBJ_ID = V559.OBJ_ID
        AND V441.PARAM_ID = 441
        AND V441.IS_DEL = 0
        
        LEFT JOIN VALS V442
        ON V442.OBJ_ID = V559.OBJ_ID
        AND V442.PARAM_ID = 442
        AND V442.IS_DEL = 0
        
        WHERE V559.SVAL = :I$NUMERAL
        AND V559.IS_DEL = 0
        AND ((:I$TYPECODE IS NULL) OR (V441.LISTVAL_ID LIKE :I$TYPECODE))
        AND ((:I$SERIES IS NULL) OR (V442.SVAL LIKE :I$SERIES))
        INTO :PID
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE IAC3_FINDLEARNERSBYPARAMS (
    I$FIRSTNAME VARCHAR(30),
    I$LASTNAME VARCHAR(30),
    I$SECONDNAME VARCHAR(30),
    I$BIRTHDATE DATE = NULL,
    I$SCHOOLPID VARCHAR(30) = NULL,
    I$USER_ID BIGINT = 1)
RETURNS (
    PID BIGINT)
AS
BEGIN

    IF (CHAR_LENGTH(I$FIRSTNAME) > 1) THEN
    BEGIN
        I$FIRSTNAME = UPPER(SUBSTRING(I$FIRSTNAME FROM 1 FOR 1))||LOWER(SUBSTRING(I$FIRSTNAME FROM 2));
    END
    ELSE
    BEGIN
        EXIT;
    END
    IF (CHAR_LENGTH(I$LASTNAME) > 1) THEN
    BEGIN
        I$LASTNAME = UPPER(SUBSTRING(I$LASTNAME FROM 1 FOR 1))||LOWER(SUBSTRING(I$LASTNAME FROM 2));
    END
    ELSE
    BEGIN
        EXIT;
    END
    IF (CHAR_LENGTH(I$SECONDNAME) > 1) THEN
    BEGIN
        I$SECONDNAME = UPPER(SUBSTRING(I$SECONDNAME FROM 1 FOR 1))||LOWER(SUBSTRING(I$SECONDNAME FROM 2));
    END

    FOR
        SELECT V55.OBJ_ID

        FROM VALS V55
        
        JOIN LINKS LP9
        ON LP9.OBJ_ID = V55.OBJ_ID
        AND LP9.PARENT_TYPE_ID = 9
        AND LP9.DATE_DEL IS NULL
        
        JOIN LINKS LP8
        ON LP8.OBJ_ID = LP9.PARENT_ID
        AND LP8.PARENT_TYPE_ID = 8
        AND LP8.DATE_DEL IS NULL
        
        JOIN LINKS LP7
        ON LP7.OBJ_ID = LP8.PARENT_ID
        AND LP7.PARENT_TYPE_ID = 7
        AND LP7.DATE_DEL IS NULL
        
        JOIN LINKS LP2
        ON LP2.OBJ_ID = LP7.PARENT_ID
        AND LP2.PARENT_TYPE_ID = 2
        AND LP2.DATE_DEL IS NULL
        
        LEFT JOIN VALS V9
        ON V9.OBJ_ID = LP2.PARENT_ID
        AND V9.PARAM_ID = 9
        AND V9.IS_DEL = 0
        
        LEFT JOIN VALS V56
        ON V56.OBJ_ID = V55.OBJ_ID
        AND V56.PARAM_ID = 56
        AND V56.IS_DEL = 0
        
        LEFT JOIN VALS V57
        ON V57.OBJ_ID = V55.OBJ_ID
        AND V57.PARAM_ID = 57
        AND V57.IS_DEL = 0
        
        LEFT JOIN VALD V89
        ON V89.OBJ_ID = V55.OBJ_ID
        AND V89.PARAM_ID = 89
        AND V89.IS_DEL = 0
        
        WHERE V55.SVAL = :I$FIRSTNAME
        AND V55.PARAM_ID = 55
        AND V55.IS_DEL = 0
        
        AND V56.SVAL = :I$LASTNAME
        
        AND ((:I$SECONDNAME IS NULL) OR (V57.SVAL LIKE :I$SECONDNAME))
        AND ((:I$SCHOOLPID IS NULL) OR (V9.SVAL LIKE :I$SCHOOLPID))
        AND ((:I$BIRTHDATE IS NULL) OR (V89.VAL LIKE :I$BIRTHDATE))
        INTO PID
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE IAC3_FINDLEARNERSBYSNILS (
    I$SNILS VARCHAR(30),
    I$USER_ID BIGINT = 1)
RETURNS (
    PID BIGINT)
AS
BEGIN
    FOR
--        SELECT DISTINCT L.OBJ_ID FROM LINKS L
--        LEFT JOIN VALS V
--        ON V.OBJ_ID = L.OBJ_ID
--        AND V.PARAM_ID = 1409
--        AND V.IS_DEL = 0
--        WHERE L.OBJ_TYPE_ID = 10
--        AND L.DATE_DEL IS NULL
--        AND V.VAL = :I$SNILS
        SELECT OBJ_ID FROM VALS V
        WHERE V.SVAL = :I$SNILS
        AND V.PARAM_ID = 1409
        AND V.IS_DEL = 0
        INTO :PID
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE IAC3_FINDSCHOOLBYPARAMS (
    I$SHORTNAME VARCHAR(50),
    I$ORGN VARCHAR(50),
    I$INN VARCHAR(50),
    I$HEADFIO VARCHAR(100),
    I$REGION VARCHAR(50),
    I$DISTRICT VARCHAR(50),
    I$TOWN VARCHAR(50),
    I$SETTLEMENT VARCHAR(50),
    I$STREET VARCHAR(50),
    I$HOUSE VARCHAR(50),
    I$LITER VARCHAR(50),
    I$CORP VARCHAR(50),
    I$FLAT VARCHAR(50),
    I$POSTINDEX VARCHAR(50),
    I$OKATO VARCHAR(50),
    I$EMAIL VARCHAR(50),
    I$SITE VARCHAR(50),
    I$PHONE VARCHAR(30),
    I$USER_ID BIGINT = 1)
RETURNS (
    PID BIGINT)
AS
declare variable V$REGION varchar(50);
declare variable V$DISTRICT varchar(50);
declare variable V$TOWN varchar(50);
declare variable V$SETTLEMENT varchar(50);
declare variable V$STREET varchar(50);
declare variable V$HOUSE varchar(50);
declare variable V$LITER varchar(50);
declare variable V$CORP varchar(50);
declare variable V$FLAT varchar(50);
declare variable V$POSTINDEX varchar(50);
declare variable V$OKATO varchar(50);
declare variable V$HEADFIO varchar(50);
BEGIN
    FOR
        SELECT L2.OBJ_ID
        
        FROM LINKS L2

        JOIN LINKS L111
        ON L111.OBJ_ID = L2.PARENT_ID
        AND L111.OBJ_TYPE_ID = 111
        AND L111.DATE_DEL IS NULL

        JOIN LINKS L112
        ON L112.OBJ_ID = L111.PARENT_ID
        AND L112.OBJ_TYPE_ID = 112
        AND L112.DATE_DEL IS NULL
        AND L112.PARENT_ID IS NULL

        JOIN VALS V2              --shortname
        ON V2.OBJ_ID = L2.OBJ_ID
        AND V2.PARAM_ID = 2
        AND V2.IS_DEL = 0
        AND ((:I$SHORTNAME IS NULL) OR (V2.SVAL LIKE :I$SHORTNAME))

        JOIN VALS V9              --orgn
        ON V9.OBJ_ID = L2.OBJ_ID
        AND V9.PARAM_ID = 9
        AND V9.IS_DEL = 0
        AND ((:I$ORGN IS NULL) OR (V9.SVAL LIKE :I$ORGN))

        JOIN VALS V33              --inn
        ON V33.OBJ_ID = L2.OBJ_ID
        AND V33.PARAM_ID = 33
        AND V33.IS_DEL = 0
        AND ((:I$INN IS NULL) OR (V33.SVAL LIKE :I$INN))

        JOIN VALS V35                --email
        ON V35.OBJ_ID = L2.OBJ_ID
        AND V35.PARAM_ID = 35
        AND V35.IS_DEL = 0
        AND ((:I$EMAIL IS NULL) OR (V35.SVAL LIKE :I$EMAIL))

        JOIN VALS V36                 --site
        ON V36.OBJ_ID = L2.OBJ_ID
        AND V36.PARAM_ID = 36
        AND V36.IS_DEL = 0
        AND ((:I$SITE IS NULL) OR (V36.SVAL LIKE :I$SITE))

        JOIN VALS V29                 -- phone
        ON V29.OBJ_ID = L2.OBJ_ID
        AND V29.PARAM_ID = 29
        AND V29.IS_DEL = 0
        AND ((:I$PHONE IS NULL) OR (V29.SVAL LIKE :I$PHONE))

        WHERE L2.OBJ_TYPE_ID = 2
        AND L2.DATE_DEL IS NULL

        INTO PID
    DO
    BEGIN
        SELECT F || ' ' || I || ' ' || O
        FROM R_SPB_POST_DIRECTOR(:PID, :I$USER_ID)
        INTO V$HEADFIO;

        SELECT REGION, DISTRICT, TOWN, SETTLEMENT, STREET, HOUSE, CORP, LITER, FLAT, POST_INDEX, OCATD FROM ADR_GET(27, :PID)
        INTO V$REGION, V$DISTRICT, V$TOWN, V$SETTLEMENT, V$STREET, V$HOUSE, V$CORP, V$LITER, V$FLAT, V$POSTINDEX, V$OKATO;

        IF (
        ((V$HEADFIO = I$HEADFIO) OR (I$HEADFIO IS NULL)) AND
        ((V$REGION = I$REGION) OR (I$REGION IS NULL)) AND
        ((V$DISTRICT = I$DISTRICT) OR (I$DISTRICT IS NULL)) AND
        ((V$TOWN = I$TOWN) OR (I$TOWN IS NULL)) AND
        ((V$SETTLEMENT = I$SETTLEMENT) OR (I$SETTLEMENT IS NULL)) AND
        ((V$STREET = I$STREET) OR (I$STREET IS NULL)) AND
        ((V$HOUSE = I$HOUSE) OR (I$HOUSE IS NULL)) AND
        ((V$CORP = I$CORP) OR (I$CORP IS NULL)) AND
        ((V$LITER = I$LITER) OR (I$LITER IS NULL)) AND
        ((V$FLAT = I$FLAT) OR (I$FLAT IS NULL)) AND
        ((V$POSTINDEX = I$POSTINDEX) OR (I$POSTINDEX IS NULL)) AND
        ((V$OKATO = I$OKATO) OR (I$OKATO IS NULL))
        )THEN
        BEGIN
            SUSPEND;
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE IAC3_GETEDUCATIONDOCUMENT (
    I$PID BIGINT,
    I$USER_ID BIGINT = 1)
RETURNS (
    PID BIGINT,
    TYPECODE INTEGER,
    SERIES VARCHAR(20),
    NUMERAL VARCHAR(30),
    REGNUMBER VARCHAR(30),
    ISSUEDATE DATE,
    ISSUER VARCHAR(200),
    LASTNAME VARCHAR(50),
    FIRSTNAME VARCHAR(50),
    SECONDNAME VARCHAR(50))
AS
DECLARE VARIABLE V$ID234 BIGINT;
DECLARE VARIABLE V$FIO234 VARCHAR(200);
DECLARE VARIABLE V$PUPIL_ID BIGINT;
BEGIN
    SELECT L.PARENT_ID FROM LINKS L
    WHERE L.OBJ_ID = :I$PID
    AND L.PARENT_TYPE_ID = 10
    AND L.DATE_DEL IS NULL
    INTO :V$PUPIL_ID;

    SELECT VR1877.OBJ_ID FROM LINKS L
    LEFT JOIN VALS V1881 ON V1881.OBJ_ID = L.OBJ_ID
    AND V1881.IS_DEL = 0
    AND V1881.PARAM_ID = 1881
    
    LEFT JOIN VALS V1848 ON V1848.OBJ_ID = L.OBJ_ID
    AND V1848.IS_DEL = 0
    AND V1848.PARAM_ID = 1848
    
    LEFT JOIN VALS V1849 ON V1849.OBJ_ID = L.OBJ_ID
    AND V1849.IS_DEL = 0
    AND V1849.PARAM_ID = 1849
    
    JOIN VAL_GET(:I$PID, 564, 0, :I$USER_ID) V564 ON V564.V = V1881.VAL
    JOIN VAL_GET(:I$PID, 565, 0, :I$USER_ID) V565 ON V565.V >= V1848.VAL AND V565.V<=V1849.VAL
    
    JOIN LINKS L236 ON  L236.PARENT_ID = L.OBJ_ID
       AND L236.DATE_DEL IS NULL
       AND L236.OBJ_TYPE_ID= 236
    
    JOIN VALR VR1877 ON VR1877.VAL = L236.OBJ_ID
        AND VR1877.PARAM_ID = 1877
        AND VR1877.IS_DEL = 0
    
    WHERE L.OBJ_TYPE_ID = 228
    AND L.DATE_DEL IS NULL
    INTO V$ID234;

    PID = I$PID;
    SELECT I FROM VAL_GET(:PID, 50, 0, :I$USER_ID)
    INTO TYPECODE;
    SELECT V FROM VAL_GET(:PID, 564, 0, :I$USER_ID)
    INTO SERIES;
    SELECT V FROM VAL_GET(:PID, 565, 0, :I$USER_ID)
    INTO NUMERAL;
    SELECT V FROM VAL_GET(:V$ID234, 1871, 0, :I$USER_ID)
    INTO REGNUMBER;
    SELECT D FROM VAL_GET(:PID, 566, 0, :I$USER_ID)
    INTO ISSUEDATE;
    SELECT V FROM VAL_GET(:PID, 568, 0, :I$USER_ID)
    INTO ISSUER;

    SELECT V1874.VAL||V1873.VAL||V1875.VAL FROM VALS V1874
    LEFT JOIN VALS V1873 ON 1=1
    AND V1873.OBJ_ID = :V$ID234
    AND V1873.PARAM_ID = 1873
    AND V1873.IS_DEL = 0
    LEFT JOIN VALS V1875 ON 1=1
    AND V1875.OBJ_ID = :V$ID234
    AND V1875.PARAM_ID = 1875
    AND V1875.IS_DEL = 0
    WHERE
    V1874.OBJ_ID = :V$ID234
    AND V1874.PARAM_ID = 1874
    AND V1874.IS_DEL = 0
    INTO :V$FIO234;

    IF ((TRIM(V$FIO234) IS NULL) OR (TRIM(V$FIO234) = ''))  THEN
    BEGIN
        SELECT V FROM VAL_GET(:V$PUPIL_ID, 56, 0, :I$USER_ID)
        INTO FIRSTNAME;
        SELECT V FROM VAL_GET(:V$PUPIL_ID, 55, 0, :I$USER_ID)
        INTO LASTNAME;
        SELECT V FROM VAL_GET(:V$PUPIL_ID, 57, 0, :I$USER_ID)
        INTO SECONDNAME;
    END
    ELSE
    BEGIN
        SELECT V FROM VAL_GET(:PID, 1873, 0, :I$USER_ID)
        INTO FIRSTNAME;
        SELECT V FROM VAL_GET(:PID, 1874, 0, :I$USER_ID)
        INTO LASTNAME;
        SELECT V FROM VAL_GET(:PID, 1875, 0, :I$USER_ID)
        INTO SECONDNAME;

    END

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE IAC3_GETIDENTITYDOCUMENTBYID (
    I$PID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    PID BIGINT,
    TYPECODE INTEGER,
    SERIES VARCHAR(20),
    NUMERAL VARCHAR(30),
    ISSUEDATE DATE,
    ISSUER VARCHAR(200),
    VALIDATYDATE DATE)
AS
BEGIN
    PID = I$PID;
    SELECT I FROM VAL_GET(:PID, 441, 0, :I$USER_ID)
    INTO TYPECODE;
    SELECT V FROM VAL_GET(:PID, 442, 0, :I$USER_ID)
    INTO SERIES;
    SELECT V FROM VAL_GET(:PID, 559, 0, :I$USER_ID)
    INTO NUMERAL;
    SELECT D FROM VAL_GET(:PID, 560, 0, :I$USER_ID)
    INTO ISSUEDATE;
    SELECT V FROM VAL_GET(:PID, 562, 0, :I$USER_ID)
    INTO ISSUER;
    SELECT D FROM VAL_GET(:PID, 561, 0, :I$USER_ID)
    INTO VALIDATYDATE;

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE IAC3_GETLEARNERBYPID (
    I$LEARNERID BIGINT,
    I$USER_ID BIGINT = 1)
RETURNS (
    PID BIGINT,
    FIRSTNAME VARCHAR(30),
    LASTNAME VARCHAR(30),
    SECONDNAME VARCHAR(30),
    BIRTHDATE DATE,
    BIRTHPLACE VARCHAR(60),
    SNILS VARCHAR(30),
    SCHOOLPID VARCHAR(30),
    TEAMNUMERAL VARCHAR(30),
    TEAMLETTER VARCHAR(30),
    ENROLLMENTDATE DATE,
    DEDUCTIONDATE DATE)
AS
declare variable V$CLASS_ID bigint;
BEGIN
    PID = I$LEARNERID;
    
    SELECT V FROM VAL_GET(:I$LEARNERID, 55, 0, :I$USER_ID)
    INTO FIRSTNAME;
    
    SELECT V FROM VAL_GET(:I$LEARNERID, 56, 0, :I$USER_ID)
    INTO LASTNAME;
    
    SELECT V FROM VAL_GET(:I$LEARNERID, 57, 0, :I$USER_ID)
    INTO SECONDNAME;
    
    SELECT D FROM VAL_GET(:I$LEARNERID, 89, 0, :I$USER_ID)
    INTO BIRTHDATE;
    
    SELECT V FROM VAL_GET(:I$LEARNERID, 1343, 0, :I$USER_ID)
    INTO BIRTHPLACE;
    
    SELECT V FROM VAL_GET(:I$LEARNERID, 1409, 0, :I$USER_ID)
    INTO SNILS;
    
    SELECT FIRST 1 OBJ_ID
    FROM OBJECT_PARENTS_GET(:I$LEARNERID, 2)
    INTO SCHOOLPID;

    SELECT FIRST 1 P9.PARENT_ID
    FROM LINKS P9
    WHERE P9.PARENT_TYPE_ID = 9
    AND P9.OBJ_ID = :I$LEARNERID
    AND P9.DATE_DEL IS NULL
    INTO V$CLASS_ID;

    SELECT V FROM VAL_GET(:V$CLASS_ID, 1767, 0, :I$USER_ID)
    INTO TEAMNUMERAL;

    SELECT V FROM VAL_GET(:V$CLASS_ID, 54, 0, :I$USER_ID)
    INTO :TEAMLETTER;

    SELECT FIRST 1 M.DATE_IN
    FROM PERSON_MOVEMENTS M
    JOIN OBJECTS O ON O.OBJ_ID = M.GROUP_ID AND O.TYPE_ID = 9
    JOIN LISTVALS LV ON LV.LISTVAL_ID = M.REASON_IN AND LV."FILTER" LIKE 'ACCEPTED%'
    WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :I$LEARNERID
    ORDER BY 1
    INTO :ENROLLMENTDATE;
    
    SELECT FIRST 1 M.DATE_OUT
    FROM PERSON_MOVEMENTS M
    JOIN OBJECTS O ON O.OBJ_ID = M.GROUP_ID AND O.TYPE_ID = 9
    JOIN LISTVALS LV ON LV.LISTVAL_ID = M.REASON_OUT AND LV."FILTER" LIKE 'LEAVED%'
    WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :I$LEARNERID
    ORDER BY 1 DESC
    INTO DEDUCTIONDATE;

    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE IAC3_GETLEARNERSEDUDOCS (
    I$LEARNERPID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    PID BIGINT)
AS
BEGIN
    FOR
        SELECT L.OBJ_ID FROM LINKS L
        WHERE L.PARENT_ID = :I$LEARNERPID
        AND L.OBJ_TYPE_ID = 11
        AND L.DATE_DEL IS NULL
        INTO PID
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE IAC3_GETLEARNERSIDENTDOCS (
    I$LEARNERPID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    PID BIGINT)
AS
BEGIN
    FOR
        SELECT L.OBJ_ID FROM LINKS L
        WHERE L.PARENT_ID = :I$LEARNERPID
        AND L.OBJ_TYPE_ID = 79
        AND L.DATE_DEL IS NULL
        INTO PID
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE IAC3_GETLEARNERSREGISTRATIONS (
    I$LEARNERID BIGINT,
    I$USER_ID BIGINT = 1)
RETURNS (
    "TYPE" VARCHAR(30),
    REGION VARCHAR(50),
    DISTRICT VARCHAR(50),
    TOWN VARCHAR(50),
    SETTLEMENT VARCHAR(50),
    STREET VARCHAR(50),
    HOUSE VARCHAR(50),
    LITER VARCHAR(50),
    CORP VARCHAR(50),
    FLAT VARCHAR(50),
    POSTINDEX VARCHAR(50),
    OKATO VARCHAR(50),
    EXPIRATIONDATE DATE)
AS
BEGIN

    SELECT V FROM VAL_GET(:I$LEARNERID, 108, 0, :I$USER_ID)
    INTO "TYPE";

    SELECT REGION, DISTRICT, TOWN, SETTLEMENT, STREET, HOUSE, CORP, LITER, FLAT, POST_INDEX, OCATD FROM ADR_GET(111, :I$LEARNERID)
    INTO REGION, DISTRICT, TOWN, SETTLEMENT, STREET, HOUSE, CORP, LITER, FLAT, POSTINDEX, OKATO;

    SELECT D FROM VAL_GET(:I$LEARNERID, 1347, 0, :I$USER_ID)
    INTO EXPIRATIONDATE;

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE IAC3_GETSCHOOLBYID (
    I$PID BIGINT,
    I$USER_ID BIGINT = 1)
RETURNS (
    PID BIGINT,
    FULLNAME VARCHAR(300),
    SHORTNAME VARCHAR(100),
    ORGN VARCHAR(50),
    INN VARCHAR(50),
    KPP VARCHAR(60),
    FORM VARCHAR(50),
    HEADPOSITION VARCHAR(50),
    HEADFIO VARCHAR(50),
    REGION VARCHAR(50),
    DISTRICT VARCHAR(50),
    TOWN VARCHAR(50),
    SETTLEMENT VARCHAR(50),
    STREET VARCHAR(50),
    HOUSE VARCHAR(50),
    LITER VARCHAR(50),
    CORP VARCHAR(50),
    FLAT VARCHAR(50),
    POSTINDEX VARCHAR(50),
    OKATO VARCHAR(50),
    EMAIL VARCHAR(50),
    SITE VARCHAR(60))
AS
declare variable V$CLASS_ID bigint;
BEGIN
    PID = I$PID;
    
    SELECT V FROM VAL_GET(:I$PID, 5, 0, :I$USER_ID)
    INTO FULLNAME;
    
    SELECT V FROM VAL_GET(:I$PID, 2, 0, :I$USER_ID)
    INTO SHORTNAME;

    SELECT V FROM VAL_GET(:I$PID, 9, 0, :I$USER_ID)
    INTO ORGN;
    
    SELECT V FROM VAL_GET(:I$PID, 33, 0, :I$USER_ID)
    INTO INN;
    
    SELECT V FROM VAL_GET(:I$PID, 34, 0, :I$USER_ID)
    INTO KPP;
    
    SELECT V FROM VAL_GET(:I$PID, 8, 0, :I$USER_ID)
    INTO FORM;

    SELECT V FROM VAL_GET(:I$PID, 1178, 0, :I$USER_ID)
    INTO HEADFIO;

    SELECT POST, F || ' ' || I || ' ' || O
    FROM R_SPB_POST_DIRECTOR(:I$PID, :I$USER_ID)
    INTO HEADPOSITION, HEADFIO;

    SELECT REGION, DISTRICT, TOWN, SETTLEMENT, STREET, HOUSE, CORP, LITER, FLAT, POST_INDEX, OCATD FROM ADR_GET(27, :I$PID)
    INTO REGION, DISTRICT, TOWN, SETTLEMENT, STREET, HOUSE, CORP, LITER, FLAT, POSTINDEX, OKATO;

    SELECT V FROM VAL_GET(:I$PID, 35, 0, :I$USER_ID)
    INTO EMAIL;
    
    SELECT V FROM VAL_GET(:I$PID, 36, 0, :I$USER_ID)
    INTO SITE;

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE IMPORT_CLEAR_LINKS (
    I$REG_NUMBER BIGINT,
    I$LEVEL INTEGER,
    I$FORCE_DELETE SMALLINT = 0)
RETURNS (
    R INTEGER)
AS
declare variable V$REG_NUMBER bigint;
declare variable M bigint;
BEGIN
    R = 0;

    -- Для уровня региона FORCE_DELETE = 1, для уровня районов FORCE_DELETE = 0

    IF (I$LEVEL = 1) THEN
    BEGIN
        -- Импорт файла из ОО - удаляем все объекты ОО
        SELECT R FROM IMPORT_CLEAR_REG_LINKS(:I$REG_NUMBER, :I$FORCE_DELETE) INTO :R;
    END
    ELSE IF (I$LEVEL = 2) THEN
    BEGIN
        -- Импорт районного файла
        SELECT FIRST 1 MULTIPLIER FROM GEN INTO :M;

        -- Удаляем данные всех ОО импортируемого района
        -- Сначала запоминаем во временной таблице список ID ОО, затем чистим все (включая записи самих ОО)
        INSERT INTO FILTER_SESSION_VALS(OBJ_ID, TYPE_ID)
        SELECT L2.OBJ_ID, L2.OBJ_TYPE_ID
        FROM LINKS L112
        JOIN LINKS L111 ON L111.PARENT_ID = L112.OBJ_ID AND L111.OBJ_TYPE_ID = 111 AND L111.DATE_DEL IS NULL AND L111.OBJ_ID / :M = :I$REG_NUMBER
        JOIN LINKS L2 ON L2.PARENT_ID = L111.OBJ_ID AND L2.OBJ_TYPE_ID IN (2, 124) AND L2.DATE_DEL IS NULL
        WHERE L112.PARENT_ID IS NULL AND L112.OBJ_TYPE_ID = 112 AND L112.DATE_DEL IS NULL;

        FOR
            SELECT OBJ_ID / :M
            FROM FILTER_SESSION_VALS
            INTO :V$REG_NUMBER
        DO
        BEGIN
            SELECT R + :R
            FROM IMPORT_CLEAR_REG_LINKS(:V$REG_NUMBER, :I$FORCE_DELETE)
            INTO :R;
        END

        -- Удаляем записи самого района
        SELECT R + :R
        FROM IMPORT_CLEAR_REG_LINKS(:I$REG_NUMBER, :I$FORCE_DELETE)
        INTO :R;
    END
    ELSE
    BEGIN
        SUSPEND;
        EXIT;
    END

    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE IMPORT_CLEAR_REG_LINKS (
    I$REG_NUMBER BIGINT,
    I$FORCE_DELETE SMALLINT = 0)
RETURNS (
    R INTEGER)
AS
DECLARE VARIABLE M BIGINT;
DECLARE VARIABLE M1 BIGINT;
DECLARE VARIABLE M2 BIGINT;
BEGIN
    R = 0;

    -- Для уровня региона FORCE_DELETE = 1, для уровня районов FORCE_DELETE = 0
    -- Если вдруг вылез номер ключа 100 - немедленно выходим, это тестовые костыли на региональной базе, и при попытке их удалить умрет все
    IF(I$REG_NUMBER = 100) THEN
    BEGIN
      SUSPEND;
      EXIT;
    END

    SELECT FIRST 1 MULTIPLIER FROM GEN INTO :M;

    -- Диапазон индексов, которые будут удаляться
    M1 = I$REG_NUMBER * M + 1;
    M2 = I$REG_NUMBER * M + M;

    -- Удаляем записи
    DELETE FROM PERSON_MOVEMENTS WHERE OBJ_ID >= :M1 AND OBJ_ID < :M2;
    DELETE FROM ORDER_DATA WHERE OBJ_ID >= :M1 AND OBJ_ID < :M2;
    DELETE FROM ORDERS WHERE OBJ_ID >= :M1 AND OBJ_ID < :M2;
    DELETE FROM CJ2_JOURNAL WHERE OBJ_ID >= :M1 AND OBJ_ID < :M2;

    IF (I$FORCE_DELETE = 1) THEN
    BEGIN
        -- При импорте из районов удаляем вообще все связи
        DELETE FROM LINKS WHERE LINK_ID >= :M1 AND LINK_ID < :M2;

        R = ROW_COUNT;

        DELETE FROM VALA WHERE OBJ_ID >= :M1 AND OBJ_ID < :M2;
        DELETE FROM VALD WHERE OBJ_ID >= :M1 AND OBJ_ID < :M2;
        DELETE FROM VALDT WHERE OBJ_ID >= :M1 AND OBJ_ID < :M2;
        DELETE FROM VALF WHERE OBJ_ID >= :M1 AND OBJ_ID < :M2;
        -- Оставляем только код ОООД+ГИА, код ППЭ, признаки ППЭ для 4-9-выпускных классов (атрибуты в объекте ОО)
        DELETE FROM VALI WHERE OBJ_ID >= :M1 AND OBJ_ID < :M2 AND PARAM_ID NOT IN (1364, 1365, 1366, 1367, 1368);
        DELETE FROM VALL WHERE OBJ_ID >= :M1 AND OBJ_ID < :M2;
        DELETE FROM VALR WHERE OBJ_ID >= :M1 AND OBJ_ID < :M2;
        DELETE FROM VALS WHERE OBJ_ID >= :M1 AND OBJ_ID < :M2;
        DELETE FROM VALT WHERE OBJ_ID >= :M1 AND OBJ_ID < :M2;
        DELETE FROM VALM WHERE MARK_ID >= :M1 AND MARK_ID < :M2;
        DELETE FROM VALN WHERE OBJ_ID >= :M1 AND OBJ_ID < :M2;

        -- Последним шагом удаляем объекты
        DELETE FROM OBJECTS
        WHERE OBJ_ID >= :M1 AND OBJ_ID < :M2
            AND OBJ_ID NOT IN (SELECT OBJ_ID FROM VALI WHERE OBJ_ID >= :M1 AND OBJ_ID < :M2)
            AND OBJ_ID NOT IN (SELECT OBJ_ID FROM LINKS WHERE LINK_ID >= :M1 AND LINK_ID < :M2)
            AND OBJ_ID NOT IN (SELECT PARENT_ID FROM LINKS WHERE LINK_ID >= :M1 AND LINK_ID < :M2);
    END
    ELSE
    BEGIN
        -- При импорте из ОО удаляем все, кроме самих ОО и записей района, а также оставляем название ОУ
        DELETE FROM LINKS
        WHERE LINK_ID >= :M1 AND LINK_ID < :M2 AND OBJ_TYPE_ID NOT IN (2, 111);

        R = ROW_COUNT;
    
        DELETE FROM VALA WHERE OBJ_ID >= :M1 AND OBJ_ID < :M2;
        DELETE FROM VALD WHERE OBJ_ID >= :M1 AND OBJ_ID < :M2;
        DELETE FROM VALDT WHERE OBJ_ID >= :M1 AND OBJ_ID < :M2;
        DELETE FROM VALF WHERE OBJ_ID >= :M1 AND OBJ_ID < :M2;
        -- Осталяем только код ОООД+ГИА, код ППЭ, признаки ППЭ для 4-9-выпускных классов
        DELETE FROM VALI WHERE OBJ_ID >= :M1 AND OBJ_ID < :M2 AND PARAM_ID NOT IN (1364, 1365, 1366, 1367, 1368);
        DELETE FROM VALL WHERE OBJ_ID >= :M1 AND OBJ_ID < :M2;
        DELETE FROM VALR WHERE OBJ_ID >= :M1 AND OBJ_ID < :M2;
        DELETE FROM VALS WHERE OBJ_ID >= :M1 AND OBJ_ID < :M2 AND PARAM_ID <> 2;
        DELETE FROM VALT WHERE OBJ_ID >= :M1 AND OBJ_ID < :M2;
        DELETE FROM VALM WHERE MARK_ID >= :M1 AND MARK_ID < :M2;
        DELETE FROM VALN WHERE OBJ_ID >= :M1 AND OBJ_ID < :M2;

        -- Последним шагом удаляем объекты
        DELETE FROM OBJECTS WHERE OBJ_ID >= :M1 AND OBJ_ID < :M2 AND TYPE_ID <> 2
            AND OBJ_ID NOT IN (SELECT OBJ_ID FROM VALI WHERE OBJ_ID >= :M1 AND OBJ_ID < :M2)
            AND OBJ_ID NOT IN (SELECT OBJ_ID FROM LINKS WHERE LINK_ID >= :M1 AND LINK_ID < :M2)
            AND OBJ_ID NOT IN (SELECT PARENT_ID FROM LINKS WHERE LINK_ID >= :M1 AND LINK_ID < :M2);
    END

    -- Удаляем метаданные
    DELETE FROM CS_METADATA WHERE OBJ_ID >= :M1 AND OBJ_ID < :M2;
    -- Удаляем все рейтинги и расчетные показатели
    DELETE FROM CJ2_STUDENT_RATING WHERE 1 = 1;

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE IMPORT_CREATE_INDEXES
AS
BEGIN
    EXECUTE STATEMENT 'ALTER TABLE "OBJECTS" ADD CONSTRAINT "PK_OBJECTS" PRIMARY KEY ("OBJ_ID");';
    EXECUTE STATEMENT 'ALTER TABLE "OBJECTS" ADD CONSTRAINT "OBJECTS_TYPE_ID" FOREIGN KEY ("TYPE_ID") REFERENCES "TYPES" ("TYPE_ID");';
    EXECUTE STATEMENT 'ALTER TABLE "LINKS" ADD PRIMARY KEY ("LINK_ID");';
    EXECUTE STATEMENT 'ALTER TABLE "LINKS" ADD CONSTRAINT "LINKS_EXT_OBJ_ID" FOREIGN KEY ("EXT_OBJ_ID") REFERENCES "OBJECTS" ("OBJ_ID");';
    EXECUTE STATEMENT 'ALTER TABLE "LINKS" ADD CONSTRAINT "LINKS_EXT_OBJ_TYPE_ID" FOREIGN KEY ("EXT_OBJ_TYPE_ID") REFERENCES "TYPES" ("TYPE_ID");';
    EXECUTE STATEMENT 'ALTER TABLE "LINKS" ADD CONSTRAINT "LINKS_OBJ_ID" FOREIGN KEY ("OBJ_ID") REFERENCES "OBJECTS" ("OBJ_ID") ON DELETE CASCADE;';
    EXECUTE STATEMENT 'ALTER TABLE "LINKS" ADD CONSTRAINT "LINKS_OBJ_TYPE_ID" FOREIGN KEY ("OBJ_TYPE_ID") REFERENCES "TYPES" ("TYPE_ID");';
    EXECUTE STATEMENT 'ALTER TABLE "LINKS" ADD CONSTRAINT "LINKS_PARENT_ID" FOREIGN KEY ("PARENT_ID") REFERENCES "OBJECTS" ("OBJ_ID") ON DELETE CASCADE;';
    EXECUTE STATEMENT 'ALTER TABLE "LINKS" ADD CONSTRAINT "LINKS_PARENT_TYPE_ID" FOREIGN KEY ("PARENT_TYPE_ID") REFERENCES "TYPES" ("TYPE_ID");';

    EXECUTE STATEMENT 'ALTER TABLE "VALA" ADD CONSTRAINT "PK_VALA" PRIMARY KEY ("PARAM_ID", "OBJ_ID");';
    EXECUTE STATEMENT 'ALTER TABLE "VALA" ADD CONSTRAINT "VALA_OBJ_ID" FOREIGN KEY ("OBJ_ID") REFERENCES "OBJECTS" ("OBJ_ID") ON DELETE CASCADE;';
    EXECUTE STATEMENT 'ALTER TABLE "VALA" ADD CONSTRAINT "VALA_PARAM_ID" FOREIGN KEY ("PARAM_ID") REFERENCES "PARAMS" ("PARAM_ID") ON DELETE CASCADE;';

    EXECUTE STATEMENT 'ALTER TABLE "VALB" ADD CONSTRAINT "PK_VALB" PRIMARY KEY ("PARAM_ID", "OBJ_ID");';
    EXECUTE STATEMENT 'ALTER TABLE "VALB" ADD CONSTRAINT "VALB_OBJ_ID" FOREIGN KEY ("OBJ_ID") REFERENCES "OBJECTS" ("OBJ_ID") ON DELETE CASCADE;';
    EXECUTE STATEMENT 'ALTER TABLE "VALB" ADD CONSTRAINT "VALB_PARAM_ID" FOREIGN KEY ("PARAM_ID") REFERENCES "PARAMS" ("PARAM_ID") ON DELETE CASCADE;';
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE IMPORT_DROP_INDEXES
AS
BEGIN
    EXECUTE STATEMENT 'ALTER TABLE "OBJECTS" DROP CONSTRAINT "PK_OBJECTS"';
    EXECUTE STATEMENT 'ALTER TABLE "OBJECTS" DROP CONSTRAINT "OBJECTS_TYPE_ID"';
    EXECUTE STATEMENT 'ALTER TABLE "LINKS" DROP PRIMARY KEY ("LINK_ID");';
    EXECUTE STATEMENT 'ALTER TABLE "LINKS" DROP CONSTRAINT "LINKS_EXT_OBJ_ID"';
    EXECUTE STATEMENT 'ALTER TABLE "LINKS" DROP CONSTRAINT "LINKS_EXT_OBJ_TYPE_ID"';
    EXECUTE STATEMENT 'ALTER TABLE "LINKS" DROP CONSTRAINT "LINKS_OBJ_ID"';
    EXECUTE STATEMENT 'ALTER TABLE "LINKS" DROP CONSTRAINT "LINKS_OBJ_TYPE_ID"';
    EXECUTE STATEMENT 'ALTER TABLE "LINKS" DROP CONSTRAINT "LINKS_PARENT_ID"';
    EXECUTE STATEMENT 'ALTER TABLE "LINKS" DROP CONSTRAINT "LINKS_PARENT_TYPE_ID"';

    EXECUTE STATEMENT 'ALTER TABLE "VALA" DROP CONSTRAINT "PK_VALA"';
    EXECUTE STATEMENT 'ALTER TABLE "VALA" DROP CONSTRAINT "VALA_OBJ_ID"';
    EXECUTE STATEMENT 'ALTER TABLE "VALA" DROP CONSTRAINT "VALA_PARAM_ID"';

    EXECUTE STATEMENT 'ALTER TABLE "VALB" DROP CONSTRAINT "PK_VALB"';
    EXECUTE STATEMENT 'ALTER TABLE "VALB" DROP CONSTRAINT "VALB_OBJ_ID"';
    EXECUTE STATEMENT 'ALTER TABLE "VALB" DROP CONSTRAINT "VALB_PARAM_ID"';
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE IMPORT_OLD_CARDS
AS
declare variable V$OBJ_ID bigint;
declare variable V$CARD_ID varchar(100);
declare variable V$TM timestamp;
declare variable V$TYPE_ID bigint;
declare variable V$OLD_ID varchar(100);
declare variable V$NOW timestamp;
declare variable V$REG_ID bigint;
declare variable V varchar(400);
begin

  -- Пытаемся вытащить данные по ранее выданным картам из базы BASE-CARDS.FDB
  SELECT MON$DATABASE_NAME
  FROM MON$DATABASE
  INTO :V;

  V = REPLACE(V, 'BASE.FDB', 'BASE-CARDS.FDB');

  EXECUTE STATEMENT 'ALTER TRIGGER VALS_BU2 INACTIVE';

  FOR
    -- Действующие обучающиеся
    SELECT L10.OBJ_ID, L10.OBJ_TYPE_ID, V2855.VAL, V2855.DATE_MODIFY
    FROM LINKS L2
    JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
    JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    JOIN VALS V2855 ON V2855.OBJ_ID = L10.OBJ_ID AND V2855.PARAM_ID = 2855 AND V2855.IS_DEL = 0
    LEFT JOIN LINKS L455 ON L455.PARENT_ID = L10.OBJ_ID AND L455.OBJ_TYPE_ID = 455 AND L455.DATE_DEL IS NULL
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND L455.OBJ_ID IS NULL
    -- Выбывшие обучающиеся
    UNION
    SELECT L10.OBJ_ID, L10.OBJ_TYPE_ID, V2855.VAL, V2855.DATE_MODIFY
    FROM LINKS L2
    JOIN LINKS L78 ON L78.PARENT_ID = L2.OBJ_ID AND L78.OBJ_TYPE_ID = 78 AND L78.DATE_DEL IS NULL
    JOIN LINKS L8X ON L8X.PARENT_ID = L78.OBJ_ID AND L8X.OBJ_TYPE_ID IN (81, 82, 83) AND L8X.DATE_DEL IS NULL
    JOIN LINKS L10 ON L10.PARENT_ID = L8X.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL AND L10.DATE_INS > '01.09.2020'
    JOIN VALS V2855 ON V2855.OBJ_ID = L10.OBJ_ID AND V2855.PARAM_ID = 2855 AND V2855.IS_DEL = 0
    LEFT JOIN LINKS L455 ON L455.PARENT_ID = L10.OBJ_ID AND L455.OBJ_TYPE_ID = 455 AND L455.DATE_DEL IS NULL
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND L455.OBJ_ID IS NULL
    -- Действующие Сотрудники
    UNION
    SELECT L14.OBJ_ID, L14.OBJ_TYPE_ID, V2857.VAL, V2857.DATE_MODIFY
    FROM LINKS L2
    JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
    JOIN VALS V2857 ON V2857.OBJ_ID = L14.OBJ_ID AND V2857.PARAM_ID = 2857 AND V2857.IS_DEL = 0
    LEFT JOIN LINKS L455 ON L455.PARENT_ID = L14.OBJ_ID AND L455.OBJ_TYPE_ID = 455 AND L455.DATE_DEL IS NULL
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND L455.OBJ_ID IS NULL
    -- Выбывшие Сотрудники
    UNION
    SELECT L14.OBJ_ID, L14.OBJ_TYPE_ID, V2857.VAL, V2857.DATE_MODIFY
    FROM LINKS L2
    JOIN LINKS L84 ON L84.PARENT_ID = L2.OBJ_ID AND L84.OBJ_TYPE_ID = 84 AND L84.DATE_DEL IS NULL
    JOIN LINKS L14 ON L14.PARENT_ID = L84.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL AND L14.DATE_INS > '01.09.2020'
    JOIN VALS V2857 ON V2857.OBJ_ID = L14.OBJ_ID AND V2857.PARAM_ID = 2857 AND V2857.IS_DEL = 0
    LEFT JOIN LINKS L455 ON L455.PARENT_ID = L14.OBJ_ID AND L455.OBJ_TYPE_ID = 455 AND L455.DATE_DEL IS NULL
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND L455.OBJ_ID IS NULL
    ORDER BY 1
    INTO :V$OBJ_ID, :V$TYPE_ID, :V$CARD_ID, :V$NOW
  DO
  BEGIN

    V$TM = NULL;
    V$OLD_ID = NULL;

    EXECUTE STATEMENT
      'SELECT DATE_MODIFY, VAL FROM VALS WHERE PARAM_ID IN (2855, 2857) AND OBJ_ID = ' || :V$OBJ_ID || ' AND IS_DEL = 0'
    ON EXTERNAL :V
    -- ROLE 'INISSOFT_ROLE'
    WITH COMMON TRANSACTION
    INTO :V$TM, :V$OLD_ID;

    -- Исправляем метку времени, регистрируем карту
    IF(V$TM IS NOT NULL AND V$TM > '01.01.1990' AND V$TM < V$NOW AND V$CARD_ID = V$OLD_ID) THEN
    BEGIN
      SELECT OBJ_ID FROM OBJECT_ADD(:V$OBJ_ID, 455) INTO :V$REG_ID;
      INSERT INTO VALDT (OBJ_ID, PARAM_ID, VAL) VALUES (:V$REG_ID, 3269, :V$TM);
      INSERT INTO VALL (OBJ_ID, PARAM_ID, LISTVAL_ID) VALUES (:V$REG_ID, 3270, 14073);
      INSERT INTO VALS (OBJ_ID, PARAM_ID, VAL) VALUES (:V$REG_ID, 3273, :V$CARD_ID);
    END

    -- В случае ошибки коннекта к старой базе ничего не делаем
    WHEN GDSCODE eds_connection DO V$TM = '01.01.1990';

  END

  EXECUTE STATEMENT 'ALTER TRIGGER VALS_BU2 ACTIVE';

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE INFOEQUIPMENT_ESTIMATION_DTL (
    I$OBJ_ID BIGINT,
    I$PARAM_NUMBER SMALLINT)
RETURNS (
    VAL1 VARCHAR(1000),
    VAL3 VARCHAR(1000),
    NAME VARCHAR(1000),
    CNT INTEGER)
AS
declare variable V$YEAR varchar(4);
declare variable V$YEAR1 varchar(4);
declare variable V$YEAR2 varchar(4);
declare variable V$YEAR3 varchar(4);
declare variable V$YEAR4 varchar(4);
declare variable V$YEAR5 varchar(4);
BEGIN
    IF (I$PARAM_NUMBER = 5) THEN
        FOR SELECT
                (SELECT CAPTION FROM OBJECT_CAPTION_GET(L9.OBJ_ID)),
                (SELECT CAPTION FROM OBJECT_CAPTION_GET(L10.OBJ_ID))
            FROM LINKS L7
            JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.DATE_DEL IS NULL AND L8.OBJ_TYPE_ID = 8
            JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.DATE_DEL IS NULL AND L9.OBJ_TYPE_ID = 9
            JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.DATE_DEL IS NULL AND L10.OBJ_TYPE_ID = 10
            WHERE L7.PARENT_ID = :I$OBJ_ID AND L7.DATE_DEL IS NULL AND L7.OBJ_TYPE_ID = 7
            ORDER BY 1, 2
            INTO :VAL3, :VAL1
        DO
        BEGIN
            SUSPEND;
        END
    ELSE IF (I$PARAM_NUMBER = 6) THEN
        FOR SELECT DISTINCT (SELECT CAPTION FROM OBJECT_CAPTION_GET(L14.OBJ_ID))
    
            FROM LINKS L14
    
            JOIN LINKS L15
            ON L15.PARENT_ID = L14.OBJ_ID
            AND L15.OBJ_TYPE_ID = 15
            AND L15.DATE_DEL IS NULL
    
            JOIN LINKS L13
            ON L13.OBJ_ID = L15.OBJ_ID
            AND L13.PARENT_TYPE_ID = 13
            AND L13.DATE_DEL IS NULL
    
            JOIN VALD V73
            ON V73.OBJ_ID = L15.OBJ_ID
            AND V73.PARAM_ID = 73
            AND V73.IS_DEL = 0
            AND V73.VAL <= CURRENT_DATE
    
            LEFT JOIN VALD V74
            ON V74.OBJ_ID = L15.OBJ_ID
            AND V74.PARAM_ID = 74
            AND V74.IS_DEL = 0
    
            WHERE L14.PARENT_ID IN (
                SELECT OBJ_ID
                FROM LINKS L
                WHERE L.PARENT_ID = :I$OBJ_ID
                AND L.DATE_DEL IS NULL
                AND L.OBJ_TYPE_ID = 211
    
                UNION ALL
    
                SELECT :I$OBJ_ID
                FROM RDB$DATABASE
            )
            AND L14.OBJ_TYPE_ID = 14
            AND L14.DATE_DEL IS NULL
            AND ((V74.VAL IS NULL) OR (V74.VAL >= CURRENT_DATE))
            AND (SELECT SORT_ORDER FROM DO_FUNC(L13.PARENT_ID, 400)) = 2
    
            INTO :VAL1
        DO
        BEGIN
            SUSPEND;
        END
    ELSE IF (I$PARAM_NUMBER IN (7,8,9,10,11)) THEN
        FOR SELECT (SELECT CAPTION FROM OBJECT_CAPTION_GET(L114.OBJ_ID)) FROM LINKS L23
            JOIN LINKS L95 ON L95.PARENT_ID = L23.OBJ_ID AND L95.OBJ_TYPE_ID = 95 AND L95.DATE_DEL IS NULL
            JOIN VALL VL ON VL.OBJ_ID = L95.OBJ_ID AND VL.PARAM_ID = 626 AND VL.IS_DEL = 0 AND VL.LISTVAL_ID = 1799
            JOIN LINKS L114 ON L114.PARENT_ID = L95.OBJ_ID AND L114.OBJ_TYPE_ID = 114 AND L114.DATE_DEL IS NULL
            JOIN VALL VL2 ON VL2.OBJ_ID = L95.OBJ_ID AND VL2.PARAM_ID = 604 AND VL2.IS_DEL = 0
            AND ((:I$PARAM_NUMBER = 7)
                OR ((:I$PARAM_NUMBER = 8) AND (VL2.LISTVAL_ID IN (1804,1805,1806)))
                OR ((:I$PARAM_NUMBER = 9) AND (VL2.LISTVAL_ID IN (1807,1808,1809)))
                OR ((:I$PARAM_NUMBER = 10) AND (VL2.LISTVAL_ID IN (1800,1801,1802)))
                OR ((:I$PARAM_NUMBER = 11) AND (VL2.LISTVAL_ID = 1803))
            )
            WHERE L23.PARENT_ID = :I$OBJ_ID AND L23.OBJ_TYPE_ID = 23 AND L23.DATE_DEL IS NULL
            INTO :NAME
        DO
        BEGIN
            SUSPEND;
        END
    ELSE IF (I$PARAM_NUMBER IN (12,13,14,15,16,17,18,19)) THEN
    BEGIN
        V$YEAR = EXTRACT(YEAR FROM CURRENT_TIMESTAMP);
        V$YEAR1 = EXTRACT(YEAR FROM CURRENT_TIMESTAMP) - 1;
        V$YEAR2 = EXTRACT(YEAR FROM CURRENT_TIMESTAMP) - 2;
        V$YEAR3 = EXTRACT(YEAR FROM CURRENT_TIMESTAMP) - 3;
        V$YEAR4 = EXTRACT(YEAR FROM CURRENT_TIMESTAMP) - 4;
        V$YEAR5 = EXTRACT(YEAR FROM CURRENT_TIMESTAMP) - 5;

        FOR SELECT (SELECT CAPTION FROM OBJECT_CAPTION_GET(L114.OBJ_ID)) FROM LINKS L23
            JOIN LINKS L95 ON L95.PARENT_ID = L23.OBJ_ID AND L95.OBJ_TYPE_ID = 95 AND L95.DATE_DEL IS NULL
            JOIN VALL VL ON VL.OBJ_ID = L95.OBJ_ID AND VL.PARAM_ID = 626 AND VL.IS_DEL = 0 AND VL.LISTVAL_ID = 1799
            JOIN LINKS L114 ON L114.PARENT_ID = L95.OBJ_ID AND L114.OBJ_TYPE_ID = 114 AND L114.DATE_DEL IS NULL
            JOIN VALS V ON V.OBJ_ID = L114.OBJ_ID AND V.PARAM_ID = 682 AND V.IS_DEL = 0
            AND (
                ((:I$PARAM_NUMBER = 12) AND (V.VAL LIKE :V$YEAR))
                OR ((:I$PARAM_NUMBER = 13) AND (V.VAL LIKE :V$YEAR1))
                OR ((:I$PARAM_NUMBER = 14) AND (V.VAL LIKE :V$YEAR2))
                OR ((:I$PARAM_NUMBER = 15) AND (V.VAL LIKE :V$YEAR3))
                OR ((:I$PARAM_NUMBER = 16) AND (V.VAL LIKE :V$YEAR4))
                OR ((:I$PARAM_NUMBER = 17) AND (V.VAL LIKE :V$YEAR5))
                OR ((:I$PARAM_NUMBER = 18) AND (V.VAL < :V$YEAR) AND (V.VAL > '1900'))
                OR ((:I$PARAM_NUMBER = 19) AND (V.VAL = '') AND (V.VAL IS NULL))
            )
            WHERE L23.PARENT_ID = :I$OBJ_ID AND L23.OBJ_TYPE_ID = 23 AND L23.DATE_DEL IS NULL
            INTO :NAME
        DO
        BEGIN
            SUSPEND;
        END
    END
    ELSE IF (I$PARAM_NUMBER IN (20,21)) THEN
        FOR SELECT (SELECT CAPTION FROM OBJECT_CAPTION_GET(L114.OBJ_ID)) FROM LINKS L23
            JOIN LINKS L95 ON L95.PARENT_ID = L23.OBJ_ID AND L95.OBJ_TYPE_ID = 95 AND L95.DATE_DEL IS NULL
            JOIN VALL VL ON VL.OBJ_ID = L95.OBJ_ID AND VL.PARAM_ID = 626 AND VL.IS_DEL = 0 AND VL.LISTVAL_ID = 1901
            JOIN VALL VL2 ON VL2.OBJ_ID = L95.OBJ_ID AND VL2.PARAM_ID = 604 AND VL2.IS_DEL = 0
            AND (
                ((:I$PARAM_NUMBER = 20) AND (VL2.LISTVAL_ID IN (1908,1909,1910)))
                OR ((:I$PARAM_NUMBER = 21) AND (VL2.LISTVAL_ID = 1908))
            )
            JOIN LINKS L114 ON L114.PARENT_ID = L95.OBJ_ID AND L114.OBJ_TYPE_ID = 114 AND L114.DATE_DEL IS NULL
            WHERE L23.PARENT_ID = :I$OBJ_ID  AND L23.OBJ_TYPE_ID = 23 AND L23.DATE_DEL IS NULL
            INTO :NAME
        DO
        BEGIN
            SUSPEND;
        END
    ELSE IF (I$PARAM_NUMBER IN (22,23,24,25,26,27,28,29)) THEN
    BEGIN
        V$YEAR = EXTRACT(YEAR FROM CURRENT_TIMESTAMP);
        V$YEAR1 = EXTRACT(YEAR FROM CURRENT_TIMESTAMP) - 1;
        V$YEAR2 = EXTRACT(YEAR FROM CURRENT_TIMESTAMP) - 2;
        V$YEAR3 = EXTRACT(YEAR FROM CURRENT_TIMESTAMP) - 3;
        V$YEAR4 = EXTRACT(YEAR FROM CURRENT_TIMESTAMP) - 4;
        V$YEAR5 = EXTRACT(YEAR FROM CURRENT_TIMESTAMP) - 5;

        FOR SELECT (SELECT CAPTION FROM OBJECT_CAPTION_GET(L114.OBJ_ID)) FROM LINKS L23
            JOIN LINKS L95 ON L95.PARENT_ID = L23.OBJ_ID AND L95.OBJ_TYPE_ID = 95 AND L95.DATE_DEL IS NULL
            JOIN VALL VL ON VL.OBJ_ID = L95.OBJ_ID AND VL.PARAM_ID = 626 AND VL.IS_DEL = 0 AND VL.LISTVAL_ID = 1901
            JOIN VALL VL2 ON VL2.OBJ_ID = L95.OBJ_ID AND VL2.PARAM_ID = 604 AND VL2.IS_DEL = 0 AND VL2.LISTVAL_ID IN (1908,1909,1910)
            JOIN LINKS L114 ON L114.PARENT_ID = L95.OBJ_ID AND L114.OBJ_TYPE_ID = 114 AND L114.DATE_DEL IS NULL
            JOIN VALS V ON V.OBJ_ID = L114.OBJ_ID AND V.PARAM_ID = 682 AND V.IS_DEL = 0
            AND (
                ((:I$PARAM_NUMBER = 22) AND (V.VAL LIKE :V$YEAR))
                OR ((:I$PARAM_NUMBER = 23) AND (V.VAL LIKE :V$YEAR1))
                OR ((:I$PARAM_NUMBER = 24) AND (V.VAL LIKE :V$YEAR2))
                OR ((:I$PARAM_NUMBER = 25) AND (V.VAL LIKE :V$YEAR3))
                OR ((:I$PARAM_NUMBER = 26) AND (V.VAL LIKE :V$YEAR4))
                OR ((:I$PARAM_NUMBER = 27) AND (V.VAL LIKE :V$YEAR5))
                OR ((:I$PARAM_NUMBER = 28) AND (V.VAL < :V$YEAR) AND (V.VAL > '1900'))
                OR ((:I$PARAM_NUMBER = 29) AND (V.VAL = '') AND (V.VAL IS NULL))
            )
            WHERE L23.PARENT_ID = :I$OBJ_ID AND L23.OBJ_TYPE_ID = 23 AND L23.DATE_DEL IS NULL
            INTO :NAME
        DO
        BEGIN
            SUSPEND;
        END
    END
    ELSE IF (I$PARAM_NUMBER IN (30,31,32)) THEN
        FOR SELECT (SELECT CAPTION FROM OBJECT_CAPTION_GET(L114.OBJ_ID)) FROM LINKS L23
            JOIN LINKS L95 ON L95.PARENT_ID = L23.OBJ_ID AND L95.OBJ_TYPE_ID = 95 AND L95.DATE_DEL IS NULL
            JOIN VALL VL ON VL.OBJ_ID = L95.OBJ_ID AND VL.PARAM_ID = 626 AND VL.IS_DEL = 0 AND VL.LISTVAL_ID = 1901
            JOIN VALL VL2 ON VL2.OBJ_ID = L95.OBJ_ID AND VL2.PARAM_ID = 604 AND VL2.IS_DEL = 0
            AND (
                ((:I$PARAM_NUMBER = 30) AND (VL2.LISTVAL_ID IN (1905,1906,1907)))
                OR ((:I$PARAM_NUMBER = 31) AND (VL2.LISTVAL_ID = 1905))
                OR ((:I$PARAM_NUMBER = 32) AND (VL2.LISTVAL_ID IN (1906,1907)))
            )
            JOIN LINKS L114 ON L114.PARENT_ID = L95.OBJ_ID AND L114.OBJ_TYPE_ID = 114 AND L114.DATE_DEL IS NULL
            WHERE L23.PARENT_ID = :I$OBJ_ID AND L23.OBJ_TYPE_ID = 23 AND L23.DATE_DEL IS NULL
            INTO :NAME
        DO
        BEGIN
            SUSPEND;
        END
    ELSE IF (I$PARAM_NUMBER IN (33,34,35,36,37,38,39,40)) THEN
    BEGIN
        V$YEAR = EXTRACT(YEAR FROM CURRENT_TIMESTAMP);
        V$YEAR1 = EXTRACT(YEAR FROM CURRENT_TIMESTAMP) - 1;
        V$YEAR2 = EXTRACT(YEAR FROM CURRENT_TIMESTAMP) - 2;
        V$YEAR3 = EXTRACT(YEAR FROM CURRENT_TIMESTAMP) - 3;
        V$YEAR4 = EXTRACT(YEAR FROM CURRENT_TIMESTAMP) - 4;
        V$YEAR5 = EXTRACT(YEAR FROM CURRENT_TIMESTAMP) - 5;

        FOR SELECT (SELECT CAPTION FROM OBJECT_CAPTION_GET(L114.OBJ_ID)) FROM LINKS L23
            JOIN LINKS L95 ON L95.PARENT_ID = L23.OBJ_ID AND L95.OBJ_TYPE_ID = 95 AND L95.DATE_DEL IS NULL
            JOIN VALL VL ON VL.OBJ_ID = L95.OBJ_ID AND VL.PARAM_ID = 626 AND VL.IS_DEL = 0 AND VL.LISTVAL_ID = 1901
            JOIN VALL VL2 ON VL2.OBJ_ID = L95.OBJ_ID AND VL2.PARAM_ID = 604 AND VL2.IS_DEL = 0 AND VL2.LISTVAL_ID IN (1905,1906,1907)
            JOIN LINKS L114 ON L114.PARENT_ID = L95.OBJ_ID AND L114.OBJ_TYPE_ID = 114 AND L114.DATE_DEL IS NULL
            JOIN VALS V ON V.OBJ_ID = L114.OBJ_ID AND V.PARAM_ID = 682 AND V.IS_DEL = 0
            AND (
                ((:I$PARAM_NUMBER = 33) AND (V.VAL LIKE :V$YEAR))
                OR ((:I$PARAM_NUMBER = 34) AND (V.VAL LIKE :V$YEAR1))
                OR ((:I$PARAM_NUMBER = 35) AND (V.VAL LIKE :V$YEAR2))
                OR ((:I$PARAM_NUMBER = 36) AND (V.VAL LIKE :V$YEAR3))
                OR ((:I$PARAM_NUMBER = 37) AND (V.VAL LIKE :V$YEAR4))
                OR ((:I$PARAM_NUMBER = 38) AND (V.VAL LIKE :V$YEAR5))
                OR ((:I$PARAM_NUMBER = 39) AND (V.VAL < :V$YEAR) AND (V.VAL > '1900'))
                OR ((:I$PARAM_NUMBER = 40) AND (V.VAL = '') AND (V.VAL IS NULL))
            )
            WHERE L23.PARENT_ID = :I$OBJ_ID AND L23.OBJ_TYPE_ID = 23 AND L23.DATE_DEL IS NULL
            INTO :NAME
        DO
        BEGIN
            SUSPEND;
        END
    END
    ELSE IF (I$PARAM_NUMBER = 41) THEN
        FOR SELECT (SELECT CAPTION FROM OBJECT_CAPTION_GET(L114.OBJ_ID)) FROM LINKS L23
            JOIN LINKS L95 ON L95.PARENT_ID = L23.OBJ_ID AND L95.OBJ_TYPE_ID = 95 AND L95.DATE_DEL IS NULL
            JOIN VALL VL ON VL.OBJ_ID = L95.OBJ_ID AND VL.PARAM_ID = 626 AND VL.IS_DEL = 0 AND VL.LISTVAL_ID = 1901
            JOIN VALL VL2 ON VL2.OBJ_ID = L95.OBJ_ID AND VL2.PARAM_ID = 604 AND VL2.IS_DEL = 0 AND VL2.LISTVAL_ID = 1912
            JOIN LINKS L114 ON L114.PARENT_ID = L95.OBJ_ID AND L114.OBJ_TYPE_ID = 114 AND L114.DATE_DEL IS NULL
            WHERE L23.PARENT_ID = :I$OBJ_ID AND L23.OBJ_TYPE_ID = 23 AND L23.DATE_DEL IS NULL
            INTO :NAME
        DO
        BEGIN
            SUSPEND;
        END
    ELSE IF (I$PARAM_NUMBER = 42) THEN
        FOR SELECT (SELECT CAPTION FROM OBJECT_CAPTION_GET(L114.OBJ_ID)) FROM LINKS L23
            JOIN LINKS L95 ON L95.PARENT_ID = L23.OBJ_ID AND L95.OBJ_TYPE_ID = 95 AND L95.DATE_DEL IS NULL
            JOIN VALL VL ON VL.OBJ_ID = L95.OBJ_ID AND VL.PARAM_ID = 626 AND VL.IS_DEL = 0 AND VL.LISTVAL_ID = 1901
            JOIN VALL VL2 ON VL2.OBJ_ID = L95.OBJ_ID AND VL2.PARAM_ID = 604 AND VL2.IS_DEL = 0 AND VL2.LISTVAL_ID = 1824
            JOIN LINKS L114 ON L114.PARENT_ID = L95.OBJ_ID AND L114.OBJ_TYPE_ID = 114 AND L114.DATE_DEL IS NULL
            WHERE L23.PARENT_ID = :I$OBJ_ID AND L23.OBJ_TYPE_ID = 23 AND L23.DATE_DEL IS NULL
            INTO :NAME
        DO
        BEGIN
            SUSPEND;
        END
    ELSE IF (I$PARAM_NUMBER = 43) THEN
        FOR SELECT (SELECT CAPTION FROM OBJECT_CAPTION_GET(L114.OBJ_ID)) FROM LINKS L23
            JOIN LINKS L95 ON L95.PARENT_ID = L23.OBJ_ID AND L95.OBJ_TYPE_ID = 95 AND L95.DATE_DEL IS NULL
            JOIN VALL VL ON VL.OBJ_ID = L95.OBJ_ID AND VL.PARAM_ID = 626 AND VL.IS_DEL = 0 AND VL.LISTVAL_ID = 1815
            JOIN VALL VL2 ON VL2.OBJ_ID = L95.OBJ_ID AND VL2.PARAM_ID = 604 AND VL2.IS_DEL = 0 AND VL2.LISTVAL_ID = 3237
            JOIN LINKS L114 ON L114.PARENT_ID = L95.OBJ_ID AND L114.OBJ_TYPE_ID = 114 AND L114.DATE_DEL IS NULL
            WHERE L23.PARENT_ID = :I$OBJ_ID AND L23.OBJ_TYPE_ID = 23 AND L23.DATE_DEL IS NULL
            INTO :NAME
        DO
        BEGIN
            SUSPEND;
        END
    ELSE IF (I$PARAM_NUMBER = 44) THEN
        FOR SELECT (SELECT CAPTION FROM OBJECT_CAPTION_GET(L114.OBJ_ID)) FROM LINKS L23
            JOIN LINKS L95 ON L95.PARENT_ID = L23.OBJ_ID AND L95.OBJ_TYPE_ID = 95 AND L95.DATE_DEL IS NULL
            JOIN VALL VL ON VL.OBJ_ID = L95.OBJ_ID AND VL.PARAM_ID = 626 AND VL.IS_DEL = 0 AND VL.LISTVAL_ID = 1815
            JOIN VALL VL2 ON VL2.OBJ_ID = L95.OBJ_ID AND VL2.PARAM_ID = 604 AND VL2.IS_DEL = 0 AND VL2.LISTVAL_ID = 1819
            JOIN LINKS L114 ON L114.PARENT_ID = L95.OBJ_ID AND L114.OBJ_TYPE_ID = 114 AND L114.DATE_DEL IS NULL
            WHERE L23.PARENT_ID = :I$OBJ_ID AND L23.OBJ_TYPE_ID = 23 AND L23.DATE_DEL IS NULL
            INTO :NAME
        DO
        BEGIN
            SUSPEND;
        END
    ELSE IF (I$PARAM_NUMBER = 45) THEN
        FOR SELECT (SELECT CAPTION FROM OBJECT_CAPTION_GET(L114.OBJ_ID)) FROM LINKS L23
            JOIN LINKS L95 ON L95.PARENT_ID = L23.OBJ_ID AND L95.OBJ_TYPE_ID = 95 AND L95.DATE_DEL IS NULL
            JOIN VALL VL ON VL.OBJ_ID = L95.OBJ_ID AND VL.PARAM_ID = 626 AND VL.IS_DEL = 0 AND VL.LISTVAL_ID = 1815
            JOIN VALL VL2 ON VL2.OBJ_ID = L95.OBJ_ID AND VL2.PARAM_ID = 604 AND VL2.IS_DEL = 0 AND VL2.LISTVAL_ID = 3252
            JOIN LINKS L114 ON L114.PARENT_ID = L95.OBJ_ID AND L114.OBJ_TYPE_ID = 114 AND L114.DATE_DEL IS NULL
            WHERE L23.PARENT_ID = :I$OBJ_ID AND L23.OBJ_TYPE_ID = 23 AND L23.DATE_DEL IS NULL
            INTO :NAME
        DO
        BEGIN
            SUSPEND;
        END
    ELSE IF (I$PARAM_NUMBER IN (46,47,48)) THEN
        FOR SELECT (SELECT CAPTION FROM OBJECT_CAPTION_GET(L128.OBJ_ID))
            FROM LINKS L23 JOIN LINKS L128 ON L128.PARENT_ID = L23.OBJ_ID AND L128.OBJ_TYPE_ID = 128 AND L128.DATE_DEL IS NULL
            JOIN VALL VL ON VL.OBJ_ID = L128.OBJ_ID AND VL.PARAM_ID = 876 AND VL.IS_DEL = 0
            AND (
                ((:I$PARAM_NUMBER = 46) AND (VL.LISTVAL_ID IN (2068,2067)))
                OR ((:I$PARAM_NUMBER = 47) AND (VL.LISTVAL_ID = 2067))
                OR ((:I$PARAM_NUMBER = 48) AND (VL.LISTVAL_ID = 2068))
            )
            WHERE L23.PARENT_ID = :I$OBJ_ID AND L23.OBJ_TYPE_ID = 23 AND L23.DATE_DEL IS NULL
            INTO :NAME
        DO
        BEGIN
            SUSPEND;
        END
    ELSE IF (I$PARAM_NUMBER IN (49,50,51)) THEN
        FOR SELECT (SELECT CAPTION FROM OBJECT_CAPTION_GET(L128.OBJ_ID)), COALESCE(SUM(V.VAL), 0) FROM LINKS L23
            JOIN LINKS L128 ON L128.PARENT_ID = L23.OBJ_ID AND L128.OBJ_TYPE_ID = 128 AND L128.DATE_DEL IS NULL
            JOIN VALL VL ON VL.OBJ_ID = L128.OBJ_ID AND VL.PARAM_ID = 876 AND VL.IS_DEL = 0
            AND (
                ((:I$PARAM_NUMBER = 49) AND (VL.LISTVAL_ID IN (2068,2067)))
                OR ((:I$PARAM_NUMBER = 50) AND (VL.LISTVAL_ID = 2067))
                OR ((:I$PARAM_NUMBER = 51) AND (VL.LISTVAL_ID = 2068))
            )
            JOIN VALI V ON V.OBJ_ID = L128.OBJ_ID AND V.PARAM_ID = 888 AND V.IS_DEL = 0
            WHERE L23.PARENT_ID = :I$OBJ_ID AND L23.OBJ_TYPE_ID = 23 AND L23.DATE_DEL IS NULL
            GROUP BY L128.OBJ_ID
            INTO :NAME, :CNT
        DO
        BEGIN
            SUSPEND;
        END
    ELSE IF (I$PARAM_NUMBER IN (52,53,54,55,56,57)) THEN
        FOR SELECT (SELECT CAPTION FROM OBJECT_CAPTION_GET(L128.OBJ_ID)) FROM LINKS L23
            JOIN LINKS L128 ON L128.PARENT_ID = L23.OBJ_ID AND L128.OBJ_TYPE_ID = 128 AND L128.DATE_DEL IS NULL
            JOIN VALL VL ON VL.OBJ_ID = L128.OBJ_ID AND VL.PARAM_ID = 876 AND VL.IS_DEL = 0
            AND (
                ((:I$PARAM_NUMBER = 52) AND (VL.LISTVAL_ID IN (2072,2071,2069,2070,2073)))
                OR ((:I$PARAM_NUMBER = 53) AND (VL.LISTVAL_ID = 2069))
                OR ((:I$PARAM_NUMBER = 54) AND (VL.LISTVAL_ID = 2072))
                OR ((:I$PARAM_NUMBER = 55) AND (VL.LISTVAL_ID = 2070))
                OR ((:I$PARAM_NUMBER = 56) AND (VL.LISTVAL_ID = 2071))
                OR ((:I$PARAM_NUMBER = 57) AND (VL.LISTVAL_ID = 2073))
            )
            WHERE L23.PARENT_ID = :I$OBJ_ID AND L23.OBJ_TYPE_ID = 23 AND L23.DATE_DEL IS NULL
            INTO :NAME
        DO
        BEGIN
            SUSPEND;
        END
    ELSE IF (I$PARAM_NUMBER IN (58,59,60,61,62,63)) THEN
        FOR SELECT (SELECT CAPTION FROM OBJECT_CAPTION_GET(L128.OBJ_ID)), COALESCE(SUM(V.VAL), 0) FROM LINKS L23
            JOIN LINKS L128 ON L128.PARENT_ID = L23.OBJ_ID AND L128.OBJ_TYPE_ID = 128 AND L128.DATE_DEL IS NULL
            JOIN VALL VL ON VL.OBJ_ID = L128.OBJ_ID AND VL.PARAM_ID = 876 AND VL.IS_DEL = 0
            AND (
                ((:I$PARAM_NUMBER = 58) AND (VL.LISTVAL_ID IN (2072,2071,2069,2070,2073)))
                OR ((:I$PARAM_NUMBER = 59) AND (VL.LISTVAL_ID = 2069))
                OR ((:I$PARAM_NUMBER = 60) AND (VL.LISTVAL_ID = 2072))
                OR ((:I$PARAM_NUMBER = 61) AND (VL.LISTVAL_ID = 2070))
                OR ((:I$PARAM_NUMBER = 62) AND (VL.LISTVAL_ID = 2071))
                OR ((:I$PARAM_NUMBER = 63) AND (VL.LISTVAL_ID = 2073))
            )
            JOIN VALI V ON V.OBJ_ID = L128.OBJ_ID AND V.PARAM_ID = 888 AND V.IS_DEL = 0
            WHERE L23.PARENT_ID = :I$OBJ_ID AND L23.OBJ_TYPE_ID = 23 AND L23.DATE_DEL IS NULL
            GROUP BY L128.OBJ_ID
            INTO :NAME, :CNT
        DO
        BEGIN
            SUSPEND;
        END
    ELSE IF (I$PARAM_NUMBER = 64) THEN
        FOR SELECT (SELECT CAPTION FROM OBJECT_CAPTION_GET(L128.OBJ_ID)) FROM LINKS L23
            JOIN LINKS L128 ON L128.PARENT_ID = L23.OBJ_ID AND L128.OBJ_TYPE_ID = 128 AND L128.DATE_DEL IS NULL
            JOIN VALL VL ON VL.OBJ_ID = L128.OBJ_ID AND VL.PARAM_ID = 876 AND VL.IS_DEL = 0 AND VL.LISTVAL_ID = 2074
            WHERE L23.PARENT_ID = :I$OBJ_ID AND L23.OBJ_TYPE_ID = 23 AND L23.DATE_DEL IS NULL
            INTO :NAME
        DO
        BEGIN
            SUSPEND;
        END
    ELSE IF (I$PARAM_NUMBER = 65) THEN
        FOR SELECT (SELECT CAPTION FROM OBJECT_CAPTION_GET(L128.OBJ_ID)) FROM LINKS L23
            JOIN LINKS L128 ON L128.PARENT_ID = L23.OBJ_ID AND L128.OBJ_TYPE_ID = 128 AND L128.DATE_DEL IS NULL
            JOIN VALL VL ON VL.OBJ_ID = L128.OBJ_ID AND VL.PARAM_ID = 876 AND VL.IS_DEL = 0 AND VL.LISTVAL_ID = 2075
            WHERE L23.PARENT_ID = :I$OBJ_ID AND L23.OBJ_TYPE_ID = 23 AND L23.DATE_DEL IS NULL
            INTO :NAME
        DO
        BEGIN
            SUSPEND;
        END
    ELSE IF (I$PARAM_NUMBER = 66) THEN
        FOR SELECT (SELECT CAPTION FROM OBJECT_CAPTION_GET(L128.OBJ_ID)) FROM LINKS L23
            JOIN LINKS L128 ON L128.PARENT_ID = L23.OBJ_ID AND L128.OBJ_TYPE_ID = 128 AND L128.DATE_DEL IS NULL
            JOIN VALL VL ON VL.OBJ_ID = L128.OBJ_ID AND VL.PARAM_ID = 876 AND VL.IS_DEL = 0 AND VL.LISTVAL_ID = 2079
            WHERE L23.PARENT_ID = :I$OBJ_ID AND L23.OBJ_TYPE_ID = 23 AND L23.DATE_DEL IS NULL
            INTO :NAME
        DO
        BEGIN
            SUSPEND;
        END
    ELSE IF (I$PARAM_NUMBER = 67) THEN
        FOR SELECT (SELECT CAPTION FROM OBJECT_CAPTION_GET(L128.OBJ_ID)) FROM LINKS L23
            JOIN LINKS L128 ON L128.PARENT_ID = L23.OBJ_ID AND L128.OBJ_TYPE_ID = 128 AND L128.DATE_DEL IS NULL
            JOIN VALL VL ON VL.OBJ_ID = L128.OBJ_ID AND VL.PARAM_ID = 876 AND VL.IS_DEL = 0 AND VL.LISTVAL_ID = 2076
            WHERE L23.PARENT_ID = :I$OBJ_ID AND L23.OBJ_TYPE_ID = 23 AND L23.DATE_DEL IS NULL
            INTO :NAME
        DO
        BEGIN
            SUSPEND;
        END
    ELSE IF (I$PARAM_NUMBER = 68) THEN
        FOR SELECT (SELECT CAPTION FROM OBJECT_CAPTION_GET(L116.OBJ_ID)) FROM LINKS L116
            WHERE L116.PARENT_ID = :I$OBJ_ID
            AND L116.OBJ_TYPE_ID = 116
            AND L116.DATE_DEL IS NULL
            INTO :NAME
        DO
        BEGIN
            SUSPEND;
        END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE INFOEQUIPMENT_ESTIMATION_GET (
    I$OBJ_ID BIGINT,
    I$PARAM_NUMBER SMALLINT,
    I$USER_ID BIGINT)
RETURNS (
    VAL VARCHAR(4000))
AS
declare variable V$YEAR varchar(4);
declare variable V$YEAR1 varchar(4);
declare variable V$YEAR2 varchar(4);
declare variable V$YEAR3 varchar(4);
declare variable V$YEAR4 varchar(4);
declare variable V$YEAR5 varchar(4);
declare variable V$I integer;
declare variable V$F float;
declare variable LANG_CODE varchar(2);
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :LANG_CODE;

    VAL = '';
    IF (I$PARAM_NUMBER = 1) THEN SELECT V FROM VAL_GET(:I$OBJ_ID, 2, 0, :I$USER_ID) INTO :VAL;
    ELSE IF (I$PARAM_NUMBER = 2) THEN SELECT V FROM VAL_GET(:I$OBJ_ID, 11, 0, :I$USER_ID) INTO :VAL;
    ELSE IF (I$PARAM_NUMBER = 3) THEN SELECT V FROM VAL_GET(:I$OBJ_ID, 10, 0, :I$USER_ID) INTO :VAL;
    ELSE IF (I$PARAM_NUMBER = 4) THEN
        SELECT R.VAL FROM LINKS LP111
        JOIN VALL VL ON VL.OBJ_ID = LP111.PARENT_ID AND VL.PARAM_ID = 665 AND VL.IS_DEL = 0
        JOIN LISTVALS LV ON LV.LISTVAL_ID = VL.LISTVAL_ID
        LEFT JOIN RES_GET(LV.RES_ID,  :LANG_CODE) R ON 1=1
        WHERE LP111.OBJ_ID = :I$OBJ_ID AND LP111.PARENT_TYPE_ID = 111 AND LP111.DATE_DEL IS NULL
        INTO :VAL;
    ELSE IF (I$PARAM_NUMBER = 5) THEN
        SELECT COUNT(*) FROM LINKS L7
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.DATE_DEL IS NULL AND L8.OBJ_TYPE_ID = 8
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.DATE_DEL IS NULL AND L9.OBJ_TYPE_ID = 9
        JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.DATE_DEL IS NULL AND L10.OBJ_TYPE_ID = 10
        WHERE L7.PARENT_ID = :I$OBJ_ID AND L7.DATE_DEL IS NULL AND L7.OBJ_TYPE_ID = 7
        INTO :VAL;
    ELSE IF (I$PARAM_NUMBER = 6) THEN
        SELECT X FROM PARAGRAF_TEACHERS_COUNT(:I$OBJ_ID)
        INTO :VAL;
    ELSE IF (I$PARAM_NUMBER IN (7,8,9,10,11)) THEN
        SELECT COUNT(L114.OBJ_ID) FROM LINKS L23
        JOIN LINKS L95 ON L95.PARENT_ID = L23.OBJ_ID AND L95.OBJ_TYPE_ID = 95 AND L95.DATE_DEL IS NULL
        JOIN VALL VL ON VL.OBJ_ID = L95.OBJ_ID AND VL.PARAM_ID = 626 AND VL.IS_DEL = 0 AND VL.LISTVAL_ID = 1799
        JOIN LINKS L114 ON L114.PARENT_ID = L95.OBJ_ID AND L114.OBJ_TYPE_ID = 114 AND L114.DATE_DEL IS NULL
        JOIN VALL VL2 ON VL2.OBJ_ID = L95.OBJ_ID AND VL2.PARAM_ID = 604 AND VL2.IS_DEL = 0
        AND ((:I$PARAM_NUMBER = 7)
            OR ((:I$PARAM_NUMBER = 8) AND (VL2.LISTVAL_ID IN (1804,1805,1806)))
            OR ((:I$PARAM_NUMBER = 9) AND (VL2.LISTVAL_ID IN (1807,1808,1809)))
            OR ((:I$PARAM_NUMBER = 10) AND (VL2.LISTVAL_ID IN (1800,1801,1802)))
            OR ((:I$PARAM_NUMBER = 11) AND (VL2.LISTVAL_ID = 1803))
        )
        WHERE L23.PARENT_ID = :I$OBJ_ID AND L23.OBJ_TYPE_ID = 23 AND L23.DATE_DEL IS NULL
        INTO :VAL;
    ELSE IF (I$PARAM_NUMBER IN (12,13,14,15,16,17,18,19)) THEN
    BEGIN
        V$YEAR = EXTRACT(YEAR FROM CURRENT_TIMESTAMP);
        V$YEAR1 = EXTRACT(YEAR FROM CURRENT_TIMESTAMP) - 1;
        V$YEAR2 = EXTRACT(YEAR FROM CURRENT_TIMESTAMP) - 2;
        V$YEAR3 = EXTRACT(YEAR FROM CURRENT_TIMESTAMP) - 3;
        V$YEAR4 = EXTRACT(YEAR FROM CURRENT_TIMESTAMP) - 4;
        V$YEAR5 = EXTRACT(YEAR FROM CURRENT_TIMESTAMP) - 5;

        SELECT COUNT(L114.OBJ_ID) FROM LINKS L23
        JOIN LINKS L95 ON L95.PARENT_ID = L23.OBJ_ID AND L95.OBJ_TYPE_ID = 95 AND L95.DATE_DEL IS NULL
        JOIN VALL VL ON VL.OBJ_ID = L95.OBJ_ID AND VL.PARAM_ID = 626 AND VL.IS_DEL = 0 AND VL.LISTVAL_ID = 1799
        JOIN LINKS L114 ON L114.PARENT_ID = L95.OBJ_ID AND L114.OBJ_TYPE_ID = 114 AND L114.DATE_DEL IS NULL
        JOIN VALS V ON V.OBJ_ID = L114.OBJ_ID AND V.PARAM_ID = 682 AND V.IS_DEL = 0
        AND (
            ((:I$PARAM_NUMBER = 12) AND (V.VAL LIKE :V$YEAR))
            OR ((:I$PARAM_NUMBER = 13) AND (V.VAL LIKE :V$YEAR1))
            OR ((:I$PARAM_NUMBER = 14) AND (V.VAL LIKE :V$YEAR2))
            OR ((:I$PARAM_NUMBER = 15) AND (V.VAL LIKE :V$YEAR3))
            OR ((:I$PARAM_NUMBER = 16) AND (V.VAL LIKE :V$YEAR4))
            OR ((:I$PARAM_NUMBER = 17) AND (V.VAL LIKE :V$YEAR5))
            OR ((:I$PARAM_NUMBER = 18) AND (V.VAL < :V$YEAR) AND (V.VAL > '1900'))
            OR ((:I$PARAM_NUMBER = 19) AND (V.VAL = '') AND (V.VAL IS NULL))
        )
        WHERE L23.PARENT_ID = :I$OBJ_ID AND L23.OBJ_TYPE_ID = 23 AND L23.DATE_DEL IS NULL
        INTO :VAL;
    END
    ELSE IF (I$PARAM_NUMBER IN (20,21)) THEN
        SELECT COUNT(L114.OBJ_ID) FROM LINKS L23
        JOIN LINKS L95 ON L95.PARENT_ID = L23.OBJ_ID AND L95.OBJ_TYPE_ID = 95 AND L95.DATE_DEL IS NULL
        JOIN VALL VL ON VL.OBJ_ID = L95.OBJ_ID AND VL.PARAM_ID = 626 AND VL.IS_DEL = 0 AND VL.LISTVAL_ID = 1901
        JOIN VALL VL2 ON VL2.OBJ_ID = L95.OBJ_ID AND VL2.PARAM_ID = 604 AND VL2.IS_DEL = 0
        AND (
            ((:I$PARAM_NUMBER = 20) AND (VL2.LISTVAL_ID IN (1908,1909,1910)))
            OR ((:I$PARAM_NUMBER = 21) AND (VL2.LISTVAL_ID = 1908))
        )
        JOIN LINKS L114 ON L114.PARENT_ID = L95.OBJ_ID AND L114.OBJ_TYPE_ID = 114 AND L114.DATE_DEL IS NULL
        WHERE L23.PARENT_ID = :I$OBJ_ID  AND L23.OBJ_TYPE_ID = 23 AND L23.DATE_DEL IS NULL
        INTO :VAL;
    ELSE IF (I$PARAM_NUMBER IN (22,23,24,25,26,27,28,29)) THEN
    BEGIN
        V$YEAR = EXTRACT(YEAR FROM CURRENT_TIMESTAMP);
        V$YEAR1 = EXTRACT(YEAR FROM CURRENT_TIMESTAMP) - 1;
        V$YEAR2 = EXTRACT(YEAR FROM CURRENT_TIMESTAMP) - 2;
        V$YEAR3 = EXTRACT(YEAR FROM CURRENT_TIMESTAMP) - 3;
        V$YEAR4 = EXTRACT(YEAR FROM CURRENT_TIMESTAMP) - 4;
        V$YEAR5 = EXTRACT(YEAR FROM CURRENT_TIMESTAMP) - 5;

        SELECT COUNT(L114.OBJ_ID) FROM LINKS L23
        JOIN LINKS L95 ON L95.PARENT_ID = L23.OBJ_ID AND L95.OBJ_TYPE_ID = 95 AND L95.DATE_DEL IS NULL
        JOIN VALL VL ON VL.OBJ_ID = L95.OBJ_ID AND VL.PARAM_ID = 626 AND VL.IS_DEL = 0 AND VL.LISTVAL_ID = 1901
        JOIN VALL VL2 ON VL2.OBJ_ID = L95.OBJ_ID AND VL2.PARAM_ID = 604 AND VL2.IS_DEL = 0 AND VL2.LISTVAL_ID IN (1908,1909,1910)
        JOIN LINKS L114 ON L114.PARENT_ID = L95.OBJ_ID AND L114.OBJ_TYPE_ID = 114 AND L114.DATE_DEL IS NULL
        JOIN VALS V ON V.OBJ_ID = L114.OBJ_ID AND V.PARAM_ID = 682 AND V.IS_DEL = 0
        AND (
            ((:I$PARAM_NUMBER = 22) AND (V.VAL LIKE :V$YEAR))
            OR ((:I$PARAM_NUMBER = 23) AND (V.VAL LIKE :V$YEAR1))
            OR ((:I$PARAM_NUMBER = 24) AND (V.VAL LIKE :V$YEAR2))
            OR ((:I$PARAM_NUMBER = 25) AND (V.VAL LIKE :V$YEAR3))
            OR ((:I$PARAM_NUMBER = 26) AND (V.VAL LIKE :V$YEAR4))
            OR ((:I$PARAM_NUMBER = 27) AND (V.VAL LIKE :V$YEAR5))
            OR ((:I$PARAM_NUMBER = 28) AND (V.VAL < :V$YEAR) AND (V.VAL > '1900'))
            OR ((:I$PARAM_NUMBER = 29) AND (V.VAL = '') AND (V.VAL IS NULL))
        )
        WHERE L23.PARENT_ID = :I$OBJ_ID AND L23.OBJ_TYPE_ID = 23 AND L23.DATE_DEL IS NULL
        INTO :VAL;
    END
    ELSE IF (I$PARAM_NUMBER IN (30,31,32)) THEN
        SELECT COUNT(L114.OBJ_ID) FROM LINKS L23
        JOIN LINKS L95 ON L95.PARENT_ID = L23.OBJ_ID AND L95.OBJ_TYPE_ID = 95 AND L95.DATE_DEL IS NULL
        JOIN VALL VL ON VL.OBJ_ID = L95.OBJ_ID AND VL.PARAM_ID = 626 AND VL.IS_DEL = 0 AND VL.LISTVAL_ID = 1901
        JOIN VALL VL2 ON VL2.OBJ_ID = L95.OBJ_ID AND VL2.PARAM_ID = 604 AND VL2.IS_DEL = 0
        AND (
            ((:I$PARAM_NUMBER = 30) AND (VL2.LISTVAL_ID IN (1905,1906,1907)))
            OR ((:I$PARAM_NUMBER = 31) AND (VL2.LISTVAL_ID = 1905))
            OR ((:I$PARAM_NUMBER = 32) AND (VL2.LISTVAL_ID IN (1906,1907)))
        )
        JOIN LINKS L114 ON L114.PARENT_ID = L95.OBJ_ID AND L114.OBJ_TYPE_ID = 114 AND L114.DATE_DEL IS NULL
        WHERE L23.PARENT_ID = :I$OBJ_ID AND L23.OBJ_TYPE_ID = 23 AND L23.DATE_DEL IS NULL
        INTO :VAL;
    ELSE IF (I$PARAM_NUMBER IN (33,34,35,36,37,38,39,40)) THEN
    BEGIN
        V$YEAR = EXTRACT(YEAR FROM CURRENT_TIMESTAMP);
        V$YEAR1 = EXTRACT(YEAR FROM CURRENT_TIMESTAMP) - 1;
        V$YEAR2 = EXTRACT(YEAR FROM CURRENT_TIMESTAMP) - 2;
        V$YEAR3 = EXTRACT(YEAR FROM CURRENT_TIMESTAMP) - 3;
        V$YEAR4 = EXTRACT(YEAR FROM CURRENT_TIMESTAMP) - 4;
        V$YEAR5 = EXTRACT(YEAR FROM CURRENT_TIMESTAMP) - 5;

        SELECT COUNT(L114.OBJ_ID) FROM LINKS L23
        JOIN LINKS L95 ON L95.PARENT_ID = L23.OBJ_ID AND L95.OBJ_TYPE_ID = 95 AND L95.DATE_DEL IS NULL
        JOIN VALL VL ON VL.OBJ_ID = L95.OBJ_ID AND VL.PARAM_ID = 626 AND VL.IS_DEL = 0 AND VL.LISTVAL_ID = 1901
        JOIN VALL VL2 ON VL2.OBJ_ID = L95.OBJ_ID AND VL2.PARAM_ID = 604 AND VL2.IS_DEL = 0 AND VL2.LISTVAL_ID IN (1905,1906,1907)
        JOIN LINKS L114 ON L114.PARENT_ID = L95.OBJ_ID AND L114.OBJ_TYPE_ID = 114 AND L114.DATE_DEL IS NULL
        JOIN VALS V ON V.OBJ_ID = L114.OBJ_ID AND V.PARAM_ID = 682 AND V.IS_DEL = 0
        AND (
            ((:I$PARAM_NUMBER = 33) AND (V.VAL LIKE :V$YEAR))
            OR ((:I$PARAM_NUMBER = 34) AND (V.VAL LIKE :V$YEAR1))
            OR ((:I$PARAM_NUMBER = 35) AND (V.VAL LIKE :V$YEAR2))
            OR ((:I$PARAM_NUMBER = 36) AND (V.VAL LIKE :V$YEAR3))
            OR ((:I$PARAM_NUMBER = 37) AND (V.VAL LIKE :V$YEAR4))
            OR ((:I$PARAM_NUMBER = 38) AND (V.VAL LIKE :V$YEAR5))
            OR ((:I$PARAM_NUMBER = 39) AND (V.VAL < :V$YEAR) AND (V.VAL > '1900'))
            OR ((:I$PARAM_NUMBER = 40) AND (V.VAL = '') AND (V.VAL IS NULL))
        )
        WHERE L23.PARENT_ID = :I$OBJ_ID AND L23.OBJ_TYPE_ID = 23 AND L23.DATE_DEL IS NULL
        INTO :VAL;
    END
    ELSE IF (I$PARAM_NUMBER = 41) THEN
        SELECT COUNT(L114.OBJ_ID) FROM LINKS L23
        JOIN LINKS L95 ON L95.PARENT_ID = L23.OBJ_ID AND L95.OBJ_TYPE_ID = 95 AND L95.DATE_DEL IS NULL
        JOIN VALL VL ON VL.OBJ_ID = L95.OBJ_ID AND VL.PARAM_ID = 626 AND VL.IS_DEL = 0 AND VL.LISTVAL_ID = 1901
        JOIN VALL VL2 ON VL2.OBJ_ID = L95.OBJ_ID AND VL2.PARAM_ID = 604 AND VL2.IS_DEL = 0 AND VL2.LISTVAL_ID = 1912
        JOIN LINKS L114 ON L114.PARENT_ID = L95.OBJ_ID AND L114.OBJ_TYPE_ID = 114 AND L114.DATE_DEL IS NULL
        WHERE L23.PARENT_ID = :I$OBJ_ID AND L23.OBJ_TYPE_ID = 23 AND L23.DATE_DEL IS NULL
        INTO :VAL;
    ELSE IF (I$PARAM_NUMBER = 42) THEN
        SELECT COUNT(L114.OBJ_ID) FROM LINKS L23
        JOIN LINKS L95 ON L95.PARENT_ID = L23.OBJ_ID AND L95.OBJ_TYPE_ID = 95 AND L95.DATE_DEL IS NULL
        JOIN VALL VL ON VL.OBJ_ID = L95.OBJ_ID AND VL.PARAM_ID = 626 AND VL.IS_DEL = 0 AND VL.LISTVAL_ID = 1901
        JOIN VALL VL2 ON VL2.OBJ_ID = L95.OBJ_ID AND VL2.PARAM_ID = 604 AND VL2.IS_DEL = 0 AND VL2.LISTVAL_ID = 1824
        JOIN LINKS L114 ON L114.PARENT_ID = L95.OBJ_ID AND L114.OBJ_TYPE_ID = 114 AND L114.DATE_DEL IS NULL
        WHERE L23.PARENT_ID = :I$OBJ_ID AND L23.OBJ_TYPE_ID = 23 AND L23.DATE_DEL IS NULL
        INTO :VAL;
    ELSE IF (I$PARAM_NUMBER = 43) THEN
        SELECT COUNT(L114.OBJ_ID) FROM LINKS L23
        JOIN LINKS L95 ON L95.PARENT_ID = L23.OBJ_ID AND L95.OBJ_TYPE_ID = 95 AND L95.DATE_DEL IS NULL
        JOIN VALL VL ON VL.OBJ_ID = L95.OBJ_ID AND VL.PARAM_ID = 626 AND VL.IS_DEL = 0 AND VL.LISTVAL_ID = 1815
        JOIN VALL VL2 ON VL2.OBJ_ID = L95.OBJ_ID AND VL2.PARAM_ID = 604 AND VL2.IS_DEL = 0 AND VL2.LISTVAL_ID = 3237
        JOIN LINKS L114 ON L114.PARENT_ID = L95.OBJ_ID AND L114.OBJ_TYPE_ID = 114 AND L114.DATE_DEL IS NULL
        WHERE L23.PARENT_ID = :I$OBJ_ID AND L23.OBJ_TYPE_ID = 23 AND L23.DATE_DEL IS NULL
        INTO :VAL;
    ELSE IF (I$PARAM_NUMBER = 44) THEN
        SELECT COUNT(L114.OBJ_ID) FROM LINKS L23
        JOIN LINKS L95 ON L95.PARENT_ID = L23.OBJ_ID AND L95.OBJ_TYPE_ID = 95 AND L95.DATE_DEL IS NULL
        JOIN VALL VL ON VL.OBJ_ID = L95.OBJ_ID AND VL.PARAM_ID = 626 AND VL.IS_DEL = 0 AND VL.LISTVAL_ID = 1815
        JOIN VALL VL2 ON VL2.OBJ_ID = L95.OBJ_ID AND VL2.PARAM_ID = 604 AND VL2.IS_DEL = 0 AND VL2.LISTVAL_ID = 1819
        JOIN LINKS L114 ON L114.PARENT_ID = L95.OBJ_ID AND L114.OBJ_TYPE_ID = 114 AND L114.DATE_DEL IS NULL
        WHERE L23.PARENT_ID = :I$OBJ_ID AND L23.OBJ_TYPE_ID = 23 AND L23.DATE_DEL IS NULL
        INTO :VAL;
    ELSE IF (I$PARAM_NUMBER = 45) THEN
        SELECT COUNT(L114.OBJ_ID) FROM LINKS L23
        JOIN LINKS L95 ON L95.PARENT_ID = L23.OBJ_ID AND L95.OBJ_TYPE_ID = 95 AND L95.DATE_DEL IS NULL
        JOIN VALL VL ON VL.OBJ_ID = L95.OBJ_ID AND VL.PARAM_ID = 626 AND VL.IS_DEL = 0 AND VL.LISTVAL_ID = 1815
        JOIN VALL VL2 ON VL2.OBJ_ID = L95.OBJ_ID AND VL2.PARAM_ID = 604 AND VL2.IS_DEL = 0 AND VL2.LISTVAL_ID = 3252
        JOIN LINKS L114 ON L114.PARENT_ID = L95.OBJ_ID AND L114.OBJ_TYPE_ID = 114 AND L114.DATE_DEL IS NULL
        WHERE L23.PARENT_ID = :I$OBJ_ID AND L23.OBJ_TYPE_ID = 23 AND L23.DATE_DEL IS NULL
        INTO :VAL;
    ELSE IF (I$PARAM_NUMBER IN (46,47,48)) THEN
        SELECT COUNT(L128.OBJ_ID)
        FROM LINKS L23 JOIN LINKS L128 ON L128.PARENT_ID = L23.OBJ_ID AND L128.OBJ_TYPE_ID = 128 AND L128.DATE_DEL IS NULL
        JOIN VALL VL ON VL.OBJ_ID = L128.OBJ_ID AND VL.PARAM_ID = 876 AND VL.IS_DEL = 0
        AND (
            ((:I$PARAM_NUMBER = 46) AND (VL.LISTVAL_ID IN (2068,2067)))
            OR ((:I$PARAM_NUMBER = 47) AND (VL.LISTVAL_ID = 2067))
            OR ((:I$PARAM_NUMBER = 48) AND (VL.LISTVAL_ID = 2068))
        )
        WHERE L23.PARENT_ID = :I$OBJ_ID AND L23.OBJ_TYPE_ID = 23 AND L23.DATE_DEL IS NULL
        INTO :VAL;
    ELSE IF (I$PARAM_NUMBER IN (49,50,51)) THEN
        SELECT COALESCE(SUM(V.VAL), 0) FROM LINKS L23
        JOIN LINKS L128 ON L128.PARENT_ID = L23.OBJ_ID AND L128.OBJ_TYPE_ID = 128 AND L128.DATE_DEL IS NULL
        JOIN VALL VL ON VL.OBJ_ID = L128.OBJ_ID AND VL.PARAM_ID = 876 AND VL.IS_DEL = 0
        AND (
            ((:I$PARAM_NUMBER = 49) AND (VL.LISTVAL_ID IN (2068,2067)))
            OR ((:I$PARAM_NUMBER = 50) AND (VL.LISTVAL_ID = 2067))
            OR ((:I$PARAM_NUMBER = 51) AND (VL.LISTVAL_ID = 2068))
        )
        JOIN VALI V ON V.OBJ_ID = L128.OBJ_ID AND V.PARAM_ID = 888 AND V.IS_DEL = 0
        WHERE L23.PARENT_ID = :I$OBJ_ID AND L23.OBJ_TYPE_ID = 23 AND L23.DATE_DEL IS NULL
        INTO :VAL;
    ELSE IF (I$PARAM_NUMBER IN (52,53,54,55,56,57)) THEN
        SELECT COUNT(L128.OBJ_ID) FROM LINKS L23
        JOIN LINKS L128 ON L128.PARENT_ID = L23.OBJ_ID AND L128.OBJ_TYPE_ID = 128 AND L128.DATE_DEL IS NULL
        JOIN VALL VL ON VL.OBJ_ID = L128.OBJ_ID AND VL.PARAM_ID = 876 AND VL.IS_DEL = 0
        AND (
            ((:I$PARAM_NUMBER = 52) AND (VL.LISTVAL_ID IN (2072,2071,2069,2070,2073)))
            OR ((:I$PARAM_NUMBER = 53) AND (VL.LISTVAL_ID = 2069))
            OR ((:I$PARAM_NUMBER = 54) AND (VL.LISTVAL_ID = 2072))
            OR ((:I$PARAM_NUMBER = 55) AND (VL.LISTVAL_ID = 2070))
            OR ((:I$PARAM_NUMBER = 56) AND (VL.LISTVAL_ID = 2071))
            OR ((:I$PARAM_NUMBER = 57) AND (VL.LISTVAL_ID = 2073))
        )
        WHERE L23.PARENT_ID = :I$OBJ_ID AND L23.OBJ_TYPE_ID = 23 AND L23.DATE_DEL IS NULL
        INTO :VAL;
    ELSE IF (I$PARAM_NUMBER IN (58,59,60,61,62,63)) THEN
        SELECT COALESCE(SUM(V.VAL), 0) FROM LINKS L23
        JOIN LINKS L128 ON L128.PARENT_ID = L23.OBJ_ID AND L128.OBJ_TYPE_ID = 128 AND L128.DATE_DEL IS NULL
        JOIN VALL VL ON VL.OBJ_ID = L128.OBJ_ID AND VL.PARAM_ID = 876 AND VL.IS_DEL = 0
        AND (
            ((:I$PARAM_NUMBER = 58) AND (VL.LISTVAL_ID IN (2072,2071,2069,2070,2073)))
            OR ((:I$PARAM_NUMBER = 59) AND (VL.LISTVAL_ID = 2069))
            OR ((:I$PARAM_NUMBER = 60) AND (VL.LISTVAL_ID = 2072))
            OR ((:I$PARAM_NUMBER = 61) AND (VL.LISTVAL_ID = 2070))
            OR ((:I$PARAM_NUMBER = 62) AND (VL.LISTVAL_ID = 2071))
            OR ((:I$PARAM_NUMBER = 63) AND (VL.LISTVAL_ID = 2073))
        )
        JOIN VALI V ON V.OBJ_ID = L128.OBJ_ID AND V.PARAM_ID = 888 AND V.IS_DEL = 0
        WHERE L23.PARENT_ID = :I$OBJ_ID AND L23.OBJ_TYPE_ID = 23 AND L23.DATE_DEL IS NULL
        INTO :VAL;
    ELSE IF (I$PARAM_NUMBER = 64) THEN
        SELECT COUNT(L128.OBJ_ID) FROM LINKS L23
        JOIN LINKS L128 ON L128.PARENT_ID = L23.OBJ_ID AND L128.OBJ_TYPE_ID = 128 AND L128.DATE_DEL IS NULL
        JOIN VALL VL ON VL.OBJ_ID = L128.OBJ_ID AND VL.PARAM_ID = 876 AND VL.IS_DEL = 0 AND VL.LISTVAL_ID = 2074
        WHERE L23.PARENT_ID = :I$OBJ_ID AND L23.OBJ_TYPE_ID = 23 AND L23.DATE_DEL IS NULL
        INTO :VAL;
    ELSE IF (I$PARAM_NUMBER = 65) THEN
        SELECT COUNT(L128.OBJ_ID) FROM LINKS L23
        JOIN LINKS L128 ON L128.PARENT_ID = L23.OBJ_ID AND L128.OBJ_TYPE_ID = 128 AND L128.DATE_DEL IS NULL
        JOIN VALL VL ON VL.OBJ_ID = L128.OBJ_ID AND VL.PARAM_ID = 876 AND VL.IS_DEL = 0 AND VL.LISTVAL_ID = 2075
        WHERE L23.PARENT_ID = :I$OBJ_ID AND L23.OBJ_TYPE_ID = 23 AND L23.DATE_DEL IS NULL
        INTO :VAL;
    ELSE IF (I$PARAM_NUMBER = 66) THEN
        SELECT COUNT(L128.OBJ_ID) FROM LINKS L23
        JOIN LINKS L128 ON L128.PARENT_ID = L23.OBJ_ID AND L128.OBJ_TYPE_ID = 128 AND L128.DATE_DEL IS NULL
        JOIN VALL VL ON VL.OBJ_ID = L128.OBJ_ID AND VL.PARAM_ID = 876 AND VL.IS_DEL = 0 AND VL.LISTVAL_ID = 2079
        WHERE L23.PARENT_ID = :I$OBJ_ID AND L23.OBJ_TYPE_ID = 23 AND L23.DATE_DEL IS NULL
        INTO :VAL;
    ELSE IF (I$PARAM_NUMBER = 67) THEN
        SELECT COUNT(L128.OBJ_ID) FROM LINKS L23
        JOIN LINKS L128 ON L128.PARENT_ID = L23.OBJ_ID AND L128.OBJ_TYPE_ID = 128 AND L128.DATE_DEL IS NULL
        JOIN VALL VL ON VL.OBJ_ID = L128.OBJ_ID AND VL.PARAM_ID = 876 AND VL.IS_DEL = 0 AND VL.LISTVAL_ID = 2076
        WHERE L23.PARENT_ID = :I$OBJ_ID AND L23.OBJ_TYPE_ID = 23 AND L23.DATE_DEL IS NULL
        INTO :VAL;
    ELSE IF (I$PARAM_NUMBER = 68) THEN
        SELECT COUNT(L116.OBJ_ID) FROM LINKS L116
        WHERE L116.PARENT_ID = :I$OBJ_ID
        AND L116.OBJ_TYPE_ID = 116
        AND L116.DATE_DEL IS NULL
        INTO :VAL;
    ELSE IF (I$PARAM_NUMBER = 69) THEN
    BEGIN
        SELECT MAX(V.VAL) FROM LINKS L116
        JOIN VALI V ON V.OBJ_ID = L116.OBJ_ID AND V.PARAM_ID = 701 AND V.IS_DEL = 0
        WHERE L116.PARENT_ID = :I$OBJ_ID AND L116.OBJ_TYPE_ID = 116 AND L116.DATE_DEL IS NULL
        INTO :VAL;
        IF (VAL <> '') THEN
        BEGIN
            VAL = VAL || ' кбит/с';
        END
    END
    ELSE IF (I$PARAM_NUMBER = 70) THEN
    BEGIN
        IF (EXISTS(
            SELECT FIRST 1 1
            FROM LINKS L116

            JOIN VALL V
            ON V.OBJ_ID = L116.OBJ_ID
            AND V.PARAM_ID = 698
            AND V.IS_DEL = 0
            AND V.LISTVAL_ID = 2

            WHERE L116.PARENT_ID = :I$OBJ_ID
            AND L116.OBJ_TYPE_ID = 116
            AND L116.DATE_DEL IS NULL
        )) THEN
        BEGIN
            VAL = 'Да';
        END
        ELSE
        BEGIN
            VAL = 'Нет';
        END     
    END
    ELSE IF (I$PARAM_NUMBER = 71) THEN
        SELECT V FROM VAL_GET(:I$OBJ_ID, 711, 0, :I$USER_ID) INTO :VAL;
    ELSE IF (I$PARAM_NUMBER = 72) THEN
        SELECT V FROM VAL_GET(:I$OBJ_ID, 712, 0, :I$USER_ID) INTO :VAL;
    ELSE IF (I$PARAM_NUMBER = 73) THEN
        SELECT CAST(F AS NUMERIC(5, 2)) FROM VAL_GET(:I$OBJ_ID, 735, 0, :I$USER_ID) INTO :VAL;
    ELSE IF (I$PARAM_NUMBER = 74) THEN
        SELECT V FROM VAL_GET(:I$OBJ_ID, 727, 0, :I$USER_ID) INTO :VAL;
    ELSE IF (I$PARAM_NUMBER = 75) THEN
        SELECT I FROM VAL_GET(:I$OBJ_ID, 728, 0, :I$USER_ID) INTO :VAL;
    ELSE IF (I$PARAM_NUMBER = 76) THEN
        SELECT I FROM VAL_GET(:I$OBJ_ID, 729, 0, :I$USER_ID) INTO :VAL;
    ELSE IF (I$PARAM_NUMBER = 77) THEN
        SELECT I FROM VAL_GET(:I$OBJ_ID, 730, 0, :I$USER_ID) INTO :VAL;
    ELSE IF (I$PARAM_NUMBER = 78) THEN
        SELECT I FROM VAL_GET(:I$OBJ_ID, 731, 0, :I$USER_ID) INTO :VAL;
    ELSE IF (I$PARAM_NUMBER = 79) THEN
    BEGIN
        SELECT V FROM VAL_GET(:I$OBJ_ID, 711) INTO :VAL;
        SELECT VAL FROM MONITORING_DO_FUNC(:I$OBJ_ID, 1433, :I$USER_ID) INTO :V$F;
        SELECT COUNT(L114.OBJ_ID) FROM LINKS L23
        JOIN LINKS L95 ON L95.PARENT_ID = L23.OBJ_ID AND L95.OBJ_TYPE_ID = 95 AND L95.DATE_DEL IS NULL
        JOIN VALL VL ON VL.OBJ_ID = L95.OBJ_ID AND VL.PARAM_ID = 626 AND VL.IS_DEL = 0 AND VL.LISTVAL_ID = 1799
        JOIN VALL VL2 ON VL2.OBJ_ID = L95.OBJ_ID AND VL2.PARAM_ID = 604 AND VL2.IS_DEL = 0 AND VL2.LISTVAL_ID IN (1805,1806)
        JOIN LINKS L114 ON L114.PARENT_ID = L95.OBJ_ID AND L114.OBJ_TYPE_ID = 114 AND L114.DATE_DEL IS NULL
        WHERE L23.PARENT_ID = :I$OBJ_ID AND L23.OBJ_TYPE_ID = 23 AND L23.DATE_DEL IS NULL
        INTO :V$I;

        IF (V$I > 0) THEN
        BEGIN
            VAL = CAST(V$F / V$I AS NUMERIC(5, 2));
        END
        ELSE
        BEGIN
            VAL = '';
        END
    END
    ELSE IF (I$PARAM_NUMBER = 80) THEN
    BEGIN
        SELECT X FROM PARAGRAF_TEACHERS_COUNT(:I$OBJ_ID) INTO :V$I;
        SELECT COUNT(L114.OBJ_ID) FROM LINKS L23
        JOIN LINKS L95 ON L95.PARENT_ID = L23.OBJ_ID AND L95.OBJ_TYPE_ID = 95 AND L95.DATE_DEL IS NULL
        JOIN VALL VL ON VL.OBJ_ID = L95.OBJ_ID AND VL.PARAM_ID = 626 AND VL.IS_DEL = 0 AND VL.LISTVAL_ID = 1799
        JOIN VALL VL2 ON VL2.OBJ_ID = L95.OBJ_ID AND VL2.PARAM_ID = 604 AND VL2.IS_DEL = 0 AND VL2.LISTVAL_ID IN (1808,1809)
        JOIN LINKS L114 ON L114.PARENT_ID = L95.OBJ_ID AND L114.OBJ_TYPE_ID = 114 AND L114.DATE_DEL IS NULL
        WHERE L23.PARENT_ID = :I$OBJ_ID AND L23.OBJ_TYPE_ID = 23 AND L23.DATE_DEL IS NULL
        INTO :V$F;
        IF (V$I > 0) THEN
        BEGIN
            VAL = CAST((V$F / V$I) * 100 AS NUMERIC(5, 2));
        END
        ELSE
        BEGIN
            VAL = '';
        END
    END
    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE INFOEQUIPMENT_ESTIMATION_OU_REP (
    I$SCHOOL_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    VAL VARCHAR(4000))
AS
BEGIN
    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 1, :I$USER_ID) INTO :VAL;
    SUSPEND;
    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 2, :I$USER_ID) INTO :VAL;
    SUSPEND;
    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 3, :I$USER_ID) INTO :VAL;
    SUSPEND;
    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 4, :I$USER_ID) INTO :VAL;
    SUSPEND;
    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 5, :I$USER_ID) INTO :VAL;
    SUSPEND;
    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 6, :I$USER_ID) INTO :VAL;
    SUSPEND;
    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 7, :I$USER_ID) INTO :VAL;
    SUSPEND;
    VAL = NULL;
    SUSPEND;
    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 8, :I$USER_ID) INTO :VAL;
    SUSPEND;
    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 9, :I$USER_ID) INTO :VAL;
    SUSPEND;
    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 10, :I$USER_ID) INTO :VAL;
    SUSPEND;
    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 11, :I$USER_ID) INTO :VAL;
    SUSPEND;
    --comp by made year
    VAL = NULL;
    SUSPEND;
    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 12, :I$USER_ID) INTO :VAL;
    SUSPEND;
    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 13, :I$USER_ID) INTO :VAL;
    SUSPEND;
    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 14, :I$USER_ID) INTO :VAL;
    SUSPEND;
    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 15, :I$USER_ID) INTO :VAL;
    SUSPEND;
    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 16, :I$USER_ID) INTO :VAL;
    SUSPEND;
    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 17, :I$USER_ID) INTO :VAL;
    SUSPEND;
    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 18, :I$USER_ID) INTO :VAL;
    SUSPEND;
    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 19, :I$USER_ID) INTO :VAL;
    SUSPEND;
    --multimedia
    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 20, :I$USER_ID) INTO :VAL;
    SUSPEND;
    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 21, :I$USER_ID) INTO :VAL;
    SUSPEND;
    --multimedia by made year
    VAL = NULL;
    SUSPEND;
    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 22, :I$USER_ID) INTO :VAL;
    SUSPEND;
    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 23, :I$USER_ID) INTO :VAL;
    SUSPEND;
    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 24, :I$USER_ID) INTO :VAL;
    SUSPEND;
    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 25, :I$USER_ID) INTO :VAL;
    SUSPEND;
    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 26, :I$USER_ID) INTO :VAL;
    SUSPEND;
    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 27, :I$USER_ID) INTO :VAL;
    SUSPEND;
    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 28, :I$USER_ID) INTO :VAL;
    SUSPEND;
    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 29, :I$USER_ID) INTO :VAL;
    SUSPEND;
    --inteactive board
    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 30, :I$USER_ID) INTO :VAL;
    SUSPEND;
    VAL = NULL;
    SUSPEND;
    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 31, :I$USER_ID) INTO :VAL;
    SUSPEND;
    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 32, :I$USER_ID) INTO :VAL;
    SUSPEND;
    --inteactive board by made year
    VAL = NULL;
    SUSPEND;
    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 33, :I$USER_ID) INTO :VAL;
    SUSPEND;
    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 34, :I$USER_ID) INTO :VAL;
    SUSPEND;
    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 35, :I$USER_ID) INTO :VAL;
    SUSPEND;
    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 36, :I$USER_ID) INTO :VAL;
    SUSPEND;
    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 37, :I$USER_ID) INTO :VAL;
    SUSPEND;
    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 38, :I$USER_ID) INTO :VAL;
    SUSPEND;
    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 39, :I$USER_ID) INTO :VAL;
    SUSPEND;
    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 40, :I$USER_ID) INTO :VAL;
    SUSPEND;
    --inf terminals
    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 41, :I$USER_ID) INTO :VAL;
    SUSPEND;
    --doc camera
    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 42, :I$USER_ID) INTO :VAL;
    SUSPEND;
    --digital sensors
    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 43, :I$USER_ID) INTO :VAL;
    SUSPEND;
    --microscopes
    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 44, :I$USER_ID) INTO :VAL;
    SUSPEND;
    --telescopes
    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 45, :I$USER_ID) INTO :VAL;
    SUSPEND;
    --comp classes
    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 46, :I$USER_ID) INTO :VAL;
    SUSPEND;
    VAL = NULL;
    SUSPEND;
    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 47, :I$USER_ID) INTO :VAL;
    SUSPEND;
    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 48, :I$USER_ID) INTO :VAL;
    SUSPEND;
    --comp classes, places
    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 49, :I$USER_ID) INTO :VAL;
    SUSPEND;
    VAL = NULL;
    SUSPEND;
    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 50, :I$USER_ID) INTO :VAL;
    SUSPEND;
    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 51, :I$USER_ID) INTO :VAL;
    SUSPEND;
    --digital labs
    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 52, :I$USER_ID) INTO :VAL;
    SUSPEND;
    VAL = NULL;
    SUSPEND;
    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 53, :I$USER_ID) INTO :VAL;
    SUSPEND;
    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 54, :I$USER_ID) INTO :VAL;
    SUSPEND;
    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 55, :I$USER_ID) INTO :VAL;
    SUSPEND;
    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 56, :I$USER_ID) INTO :VAL;
    SUSPEND;
    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 57, :I$USER_ID) INTO :VAL;
    SUSPEND;
    --digital labs, places
    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 58, :I$USER_ID) INTO :VAL;
    SUSPEND;
    VAL = NULL;
    SUSPEND;
    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 59, :I$USER_ID) INTO :VAL;
    SUSPEND;
    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 60, :I$USER_ID) INTO :VAL;
    SUSPEND;
    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 61, :I$USER_ID) INTO :VAL;
    SUSPEND;
    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 62, :I$USER_ID) INTO :VAL;
    SUSPEND;
    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 63, :I$USER_ID) INTO :VAL;
    SUSPEND;
    --robolabs
    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 64, :I$USER_ID) INTO :VAL;
    SUSPEND;
    --lingo
    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 65, :I$USER_ID) INTO :VAL;
    SUSPEND;
    --presentation complex
    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 66, :I$USER_ID) INTO :VAL;
    SUSPEND;
    --video conf
    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 67, :I$USER_ID) INTO :VAL;
    SUSPEND;
    --lans
    VAL = NULL;
    SUSPEND;
    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 68, :I$USER_ID) INTO :VAL;
    SUSPEND;
    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 69, :I$USER_ID) INTO :VAL;
    SUSPEND;
    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 70, :I$USER_ID) INTO :VAL;
    SUSPEND;
    --informatisation level
    VAL = NULL;
    SUSPEND;
    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 71, :I$USER_ID) INTO :VAL;
    SUSPEND;
    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 72, :I$USER_ID) INTO :VAL;
    SUSPEND;
    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 73, :I$USER_ID) INTO :VAL;
    SUSPEND;
    --informatisation control
    VAL = NULL;
    SUSPEND;
    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 74, :I$USER_ID) INTO :VAL;
    SUSPEND;
    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 75, :I$USER_ID) INTO :VAL;
    SUSPEND;
    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 76, :I$USER_ID) INTO :VAL;
    SUSPEND;
    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 77, :I$USER_ID) INTO :VAL;
    SUSPEND;
    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 78, :I$USER_ID) INTO :VAL;
    SUSPEND;
    VAL = NULL;
    SUSPEND;
    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 79, :I$USER_ID) INTO :VAL;
    SUSPEND;
    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 80, :I$USER_ID) INTO :VAL;
    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE INFOEQUIPMENT_ESTIMATION_REPORT (
    I$REGION_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    COL_NUM SMALLINT,
    VAL VARCHAR(4000),
    DATA VARCHAR(4000),
    ORIENTATION VARCHAR(20))
AS
declare variable V$SCHOOL_ID bigint;
BEGIN
    ORIENTATION = 'MIXED';
    DATA = NULL;
    FOR
        SELECT S.OBJ_ID,
               S.SCHOOL_NUMBER
        FROM MTR_DISTRICT_LIST(:I$REGION_ID) D
        JOIN MTR_SCHOOL_LIST(D.OBJ_ID) S ON 1=1

        UNION ALL

        SELECT OBJ_ID,
               SCHOOL_NUMBER
        FROM MTR_SCHOOL_LIST(:I$REGION_ID)

        ORDER BY 2
        INTO :V$SCHOOL_ID,
             :VAL
    DO
    BEGIN
        COL_NUM = 1;
        SUSPEND;

        SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:V$SCHOOL_ID, 1, :I$USER_ID) INTO :VAL;
        COL_NUM = 2;
        SUSPEND;
        SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:V$SCHOOL_ID, 2, :I$USER_ID) INTO :VAL;
        COL_NUM = 3;
        SUSPEND;
        SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:V$SCHOOL_ID, 3, :I$USER_ID) INTO :VAL;
        COL_NUM = 4;
        SUSPEND;
        SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:V$SCHOOL_ID, 4, :I$USER_ID) INTO :VAL;
        COL_NUM = 5;
        SUSPEND;
        SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:V$SCHOOL_ID, 5, :I$USER_ID) INTO :VAL;
        COL_NUM = 6;
        SUSPEND;
        SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:V$SCHOOL_ID, 6, :I$USER_ID) INTO :VAL;
        COL_NUM = 7;
        SUSPEND;
        SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:V$SCHOOL_ID, 7, :I$USER_ID) INTO :VAL;
        COL_NUM = 8;
        SUSPEND;
        VAL = NULL;
        COL_NUM = 9;
        SUSPEND;
        SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:V$SCHOOL_ID, 8, :I$USER_ID) INTO :VAL;
        COL_NUM = 10;
        SUSPEND;
        SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:V$SCHOOL_ID, 9, :I$USER_ID) INTO :VAL;
        COL_NUM = 11;
        SUSPEND;
        SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:V$SCHOOL_ID, 10, :I$USER_ID) INTO :VAL;
        COL_NUM = 12;
        SUSPEND;
        SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:V$SCHOOL_ID, 11, :I$USER_ID) INTO :VAL;
        COL_NUM = 13;
        SUSPEND;
        --comp by made year
        VAL = NULL;
        COL_NUM = 14;
        SUSPEND;
        SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:V$SCHOOL_ID, 12, :I$USER_ID) INTO :VAL;
        COL_NUM = 15;
        SUSPEND;
        SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:V$SCHOOL_ID, 13, :I$USER_ID) INTO :VAL;
        COL_NUM = 16;
        SUSPEND;
        SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:V$SCHOOL_ID, 14, :I$USER_ID) INTO :VAL;
        COL_NUM = 17;
        SUSPEND;
        SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:V$SCHOOL_ID, 15, :I$USER_ID) INTO :VAL;
        COL_NUM = 18;
        SUSPEND;
        SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:V$SCHOOL_ID, 16, :I$USER_ID) INTO :VAL;
        COL_NUM = 19;
        SUSPEND;
        SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:V$SCHOOL_ID, 17, :I$USER_ID) INTO :VAL;
        COL_NUM = 20;
        SUSPEND;
        SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:V$SCHOOL_ID, 18, :I$USER_ID) INTO :VAL;
        COL_NUM = 21;
        SUSPEND;
        SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:V$SCHOOL_ID, 19, :I$USER_ID) INTO :VAL;
        COL_NUM = 22;
        SUSPEND;
        --multimedia
        SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:V$SCHOOL_ID, 20, :I$USER_ID) INTO :VAL;
        COL_NUM = 23;
        SUSPEND;
        SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:V$SCHOOL_ID, 21, :I$USER_ID) INTO :VAL;
        COL_NUM = 24;
        SUSPEND;
        --multimedia by made year
        VAL = NULL;
        COL_NUM = 25;
        SUSPEND;
        SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:V$SCHOOL_ID, 22, :I$USER_ID) INTO :VAL;
        COL_NUM = 26;
        SUSPEND;
        SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:V$SCHOOL_ID, 23, :I$USER_ID) INTO :VAL;
        COL_NUM = 27;
        SUSPEND;
        SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:V$SCHOOL_ID, 24, :I$USER_ID) INTO :VAL;
        COL_NUM = 28;
        SUSPEND;
        SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:V$SCHOOL_ID, 25, :I$USER_ID) INTO :VAL;
        COL_NUM = 29;
        SUSPEND;
        SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:V$SCHOOL_ID, 26, :I$USER_ID) INTO :VAL;
        COL_NUM = 30;
        SUSPEND;
        SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:V$SCHOOL_ID, 27, :I$USER_ID) INTO :VAL;
        COL_NUM = 31;
        SUSPEND;
        SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:V$SCHOOL_ID, 28, :I$USER_ID) INTO :VAL;
        COL_NUM = 32;
        SUSPEND;
        SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:V$SCHOOL_ID, 29, :I$USER_ID) INTO :VAL;
        COL_NUM = 33;
        SUSPEND;
        --inteactive board
        SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:V$SCHOOL_ID, 30, :I$USER_ID) INTO :VAL;
        COL_NUM = 34;
        SUSPEND;
        VAL = NULL;
        COL_NUM = 35;
        SUSPEND;
        SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:V$SCHOOL_ID, 31, :I$USER_ID) INTO :VAL;
        COL_NUM = 36;
        SUSPEND;
        SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:V$SCHOOL_ID, 32, :I$USER_ID) INTO :VAL;
        COL_NUM = 37;
        SUSPEND;
        --inteactive board by made year
        VAL = NULL;
        COL_NUM = 38;
        SUSPEND;
        SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:V$SCHOOL_ID, 33, :I$USER_ID) INTO :VAL;
        COL_NUM = 39;
        SUSPEND;
        SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:V$SCHOOL_ID, 34, :I$USER_ID) INTO :VAL;
        COL_NUM = 40;
        SUSPEND;
        SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:V$SCHOOL_ID, 35, :I$USER_ID) INTO :VAL;
        COL_NUM = 41;
        SUSPEND;
        SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:V$SCHOOL_ID, 36, :I$USER_ID) INTO :VAL;
        COL_NUM = 42;
        SUSPEND;
        SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:V$SCHOOL_ID, 37, :I$USER_ID) INTO :VAL;
        COL_NUM = 43;
        SUSPEND;
        SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:V$SCHOOL_ID, 38, :I$USER_ID) INTO :VAL;
        COL_NUM = 44;
        SUSPEND;
        SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:V$SCHOOL_ID, 39, :I$USER_ID) INTO :VAL;
        COL_NUM = 45;
        SUSPEND;
        SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:V$SCHOOL_ID, 40, :I$USER_ID) INTO :VAL;
        COL_NUM = 46;
        SUSPEND;
        --inf terminals
        SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:V$SCHOOL_ID, 41, :I$USER_ID) INTO :VAL;
        COL_NUM = 47;
        SUSPEND;
        --doc camera
        SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:V$SCHOOL_ID, 42, :I$USER_ID) INTO :VAL;
        COL_NUM = 48;
        SUSPEND;
        --digital sensors
        SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:V$SCHOOL_ID, 43, :I$USER_ID) INTO :VAL;
        COL_NUM = 49;
        SUSPEND;
        --microscopes
        SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:V$SCHOOL_ID, 44, :I$USER_ID) INTO :VAL;
        COL_NUM = 50;
        SUSPEND;
        --telescopes
        SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:V$SCHOOL_ID, 45, :I$USER_ID) INTO :VAL;
        COL_NUM = 51;
        SUSPEND;
        --comp classes
        SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:V$SCHOOL_ID, 46, :I$USER_ID) INTO :VAL;
        COL_NUM = 52;
        SUSPEND;
        VAL = NULL;
        COL_NUM = 53;
        SUSPEND;
        SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:V$SCHOOL_ID, 47, :I$USER_ID) INTO :VAL;
        COL_NUM = 54;
        SUSPEND;
        SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:V$SCHOOL_ID, 48, :I$USER_ID) INTO :VAL;
        COL_NUM = 55;
        SUSPEND;
        --comp classes, places
        SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:V$SCHOOL_ID, 49, :I$USER_ID) INTO :VAL;
        COL_NUM = 56;
        SUSPEND;
        VAL = NULL;
        COL_NUM = 57;
        SUSPEND;
        SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:V$SCHOOL_ID, 50, :I$USER_ID) INTO :VAL;
        COL_NUM = 58;
        SUSPEND;
        SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:V$SCHOOL_ID, 51, :I$USER_ID) INTO :VAL;
        COL_NUM = 59;
        SUSPEND;
        --digital labs
        SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:V$SCHOOL_ID, 52, :I$USER_ID) INTO :VAL;
        COL_NUM = 60;
        SUSPEND;
        VAL = NULL;
        COL_NUM = 61;
        SUSPEND;
        SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:V$SCHOOL_ID, 53, :I$USER_ID) INTO :VAL;
        COL_NUM = 62;
        SUSPEND;
        SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:V$SCHOOL_ID, 54, :I$USER_ID) INTO :VAL;
        COL_NUM = 63;
        SUSPEND;
        SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:V$SCHOOL_ID, 55, :I$USER_ID) INTO :VAL;
        COL_NUM = 64;
        SUSPEND;
        SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:V$SCHOOL_ID, 56, :I$USER_ID) INTO :VAL;
        COL_NUM = 65;
        SUSPEND;
        SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:V$SCHOOL_ID, 57, :I$USER_ID) INTO :VAL;
        COL_NUM = 66;
        SUSPEND;
        --digital labs, places
        SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:V$SCHOOL_ID, 58, :I$USER_ID) INTO :VAL;
        COL_NUM = 67;
        SUSPEND;
        VAL = NULL;
        COL_NUM = 68;
        SUSPEND;
        SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:V$SCHOOL_ID, 59, :I$USER_ID) INTO :VAL;
        COL_NUM = 69;
        SUSPEND;
        SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:V$SCHOOL_ID, 60, :I$USER_ID) INTO :VAL;
        COL_NUM = 70;
        SUSPEND;
        SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:V$SCHOOL_ID, 61, :I$USER_ID) INTO :VAL;
        COL_NUM = 71;
        SUSPEND;
        SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:V$SCHOOL_ID, 62, :I$USER_ID) INTO :VAL;
        COL_NUM = 72;
        SUSPEND;
        SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:V$SCHOOL_ID, 63, :I$USER_ID) INTO :VAL;
        COL_NUM = 73;
        SUSPEND;
        --robolabs
        SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:V$SCHOOL_ID, 64, :I$USER_ID) INTO :VAL;
        COL_NUM = 74;
        SUSPEND;
        --lingo
        SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:V$SCHOOL_ID, 65, :I$USER_ID) INTO :VAL;
        COL_NUM = 75;
        SUSPEND;
        --presentation complex
        SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:V$SCHOOL_ID, 66, :I$USER_ID) INTO :VAL;
        COL_NUM = 76;
        SUSPEND;
        --video conf
        SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:V$SCHOOL_ID, 67, :I$USER_ID) INTO :VAL;
        COL_NUM = 77;
        SUSPEND;
        --lans
        VAL = NULL;
        COL_NUM = 78;
        SUSPEND;
        SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:V$SCHOOL_ID, 68, :I$USER_ID) INTO :VAL;
        COL_NUM = 79;
        SUSPEND;
        SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:V$SCHOOL_ID, 69, :I$USER_ID) INTO :VAL;
        COL_NUM = 80;
        SUSPEND;
        SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:V$SCHOOL_ID, 70, :I$USER_ID) INTO :VAL;
        COL_NUM = 81;
        SUSPEND;
        --informatisation level
        VAL = NULL;
        COL_NUM = 82;
        SUSPEND;
        SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:V$SCHOOL_ID, 71, :I$USER_ID) INTO :VAL;
        COL_NUM = 83;
        SUSPEND;
        SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:V$SCHOOL_ID, 72, :I$USER_ID) INTO :VAL;
        COL_NUM = 84;
        SUSPEND;
        SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:V$SCHOOL_ID, 73, :I$USER_ID) INTO :VAL;
        COL_NUM = 85;
        SUSPEND;
        --informatisation control
        VAL = NULL;
        COL_NUM = 86;
        SUSPEND;
        SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:V$SCHOOL_ID, 74, :I$USER_ID) INTO :VAL;
        COL_NUM = 87;
        SUSPEND;
        SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:V$SCHOOL_ID, 75, :I$USER_ID) INTO :VAL;
        COL_NUM = 88;
        SUSPEND;
        SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:V$SCHOOL_ID, 76, :I$USER_ID) INTO :VAL;
        COL_NUM = 89;
        SUSPEND;
        SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:V$SCHOOL_ID, 77, :I$USER_ID) INTO :VAL;
        COL_NUM = 90;
        SUSPEND;
        SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:V$SCHOOL_ID, 78, :I$USER_ID) INTO :VAL;
        COL_NUM = 91;
        SUSPEND;
        SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:V$SCHOOL_ID, 79, :I$USER_ID) INTO :VAL;
        COL_NUM = 92;
        SUSPEND;
        SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:V$SCHOOL_ID, 80, :I$USER_ID) INTO :VAL;
        COL_NUM = 93;
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE INFO_KEY_SET (
    INFO_CODE VARCHAR(100),
    INFO_NAME VARCHAR(100),
    INFO_VAL VARCHAR(4000))
RETURNS (
    INFO_ID BIGINT)
AS
BEGIN
    UPDATE OR INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
    VALUES (:INFO_CODE, :INFO_NAME, :INFO_VAL)
    MATCHING (INFO_CODE)
    RETURNING INFO_ID 
    INTO :INFO_ID;

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE INTOKC_SCHOLAR_GET RETURNS (
    SCHOLAR_ID BIGINT,
    F VARCHAR(1000),
    I VARCHAR(1000),
    O VARCHAR(1000),
    DT DATE,
    SEX CHAR(1))
AS
DECLARE VARIABLE SCHOOL_ID BIGINT;
DECLARE VARIABLE SEX_ID BIGINT;
BEGIN
    SELECT FIRST 1 L.OBJ_ID
    FROM LINKS L
    WHERE L.PARENT_ID IS NULL
      AND L.OBJ_TYPE_ID = 2
      AND L.DATE_DEL IS NULL
    INTO :SCHOOL_ID;

    FOR SELECT L10.OBJ_ID, D.VAL, F.VAL, I.VAL, O.VAL, S.LISTVAL_ID
        FROM LINKS L7
        INNER JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID
        INNER JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID
        INNER JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID
        INNER JOIN VALD D ON D.OBJ_ID = L10.OBJ_ID
        INNER JOIN VALS F ON F.OBJ_ID = L10.OBJ_ID
        INNER JOIN VALS I ON I.OBJ_ID = L10.OBJ_ID
        LEFT  JOIN VALS O ON O.OBJ_ID = L10.OBJ_ID AND O.PARAM_ID = 57 AND O.IS_DEL = 0
        LEFT  JOIN VALL S ON S.OBJ_ID = L10.OBJ_ID AND S.PARAM_ID = 88 AND S.IS_DEL = 0
        WHERE L7.PARENT_ID = :SCHOOL_ID
          AND L7.OBJ_TYPE_ID = 7
          AND L7.DATE_DEL IS NULL
          AND L8.OBJ_TYPE_ID = 8
          AND L8.DATE_DEL IS NULL
          AND L9.OBJ_TYPE_ID = 9
          AND L9.DATE_DEL IS NULL
          AND L10.OBJ_TYPE_ID = 10
          AND L10.DATE_DEL IS NULL
          AND D.PARAM_ID = 89
          AND D.IS_DEL = 0
          AND F.PARAM_ID = 55
          AND F.IS_DEL = 0
          AND I.PARAM_ID = 56
          AND I.IS_DEL = 0
        INTO :SCHOLAR_ID, :DT, :F, :I, :O, :SEX_ID
    DO
    BEGIN
        SEX = NULL;
        IF (SEX_ID = 183) THEN SEX = 'M';
        IF (SEX_ID = 182) THEN SEX = 'W';
        SUSPEND;
    END

END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE IS_CURRICULUM_HAS_NET (
    OBJ_ID BIGINT)
RETURNS (
    RETCODE INTEGER)
AS
declare variable V$CURRICULUM_ID bigint;
BEGIN
    SELECT FIRST 1 OBJ_ID
    FROM OBJECT_PARENTS_GET(:OBJ_ID, 57)
    INTO :V$CURRICULUM_ID;

    SELECT I
    FROM VAL_GET(:V$CURRICULUM_ID,1891)
    INTO :RETCODE;

    IF (RETCODE = 2) THEN
    BEGIN
        RETCODE = 1;
    END
    ELSE
    BEGIN
        RETCODE = 0;
    END
    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE IS_DOU RETURNS (
    STATUS SMALLINT)
AS
begin
    IF (EXISTS(
        SELECT 1
        FROM KEYS
        WHERE KEY_CODE = 'PROJECT_NAME' AND KEY_VAL = 'Параграф ДОУ'
    )) THEN
    BEGIN
        STATUS = 1;
    END
    ELSE
    BEGIN
        STATUS = 0;
    END
    SUSPEND;
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE IS_MANAGER (
    I$TEACHER_ID BIGINT)
RETURNS (
    X SMALLINT)
AS
BEGIN
    X = 0;

    SELECT FIRST 1 1

    FROM LINKS L15

    JOIN LINKS L13
    ON L13.OBJ_ID = L15.OBJ_ID
    AND L13.PARENT_TYPE_ID = 13
    AND L13.DATE_DEL IS NULL

    JOIN VALL V63
    ON V63.OBJ_ID = L13.PARENT_ID
    AND V63.PARAM_ID = 63
    AND V63.IS_DEL = 0
    AND V63.LISTVAL_ID = 55

    JOIN VALL V72
    ON V72.OBJ_ID = L15.OBJ_ID
    AND V72.PARAM_ID = 72
    AND V72.IS_DEL = 0
    AND V72.LISTVAL_ID = 934

    JOIN VALD V73
    ON V73.OBJ_ID = L15.OBJ_ID
    AND V73.PARAM_ID = 73
    AND V73.IS_DEL = 0
    AND V73.VAL <= CURRENT_DATE

    LEFT JOIN VALD V74
    ON V74.OBJ_ID = L15.OBJ_ID
    AND V74.PARAM_ID = 74
    AND V74.IS_DEL = 0

    WHERE L15.PARENT_ID = :I$TEACHER_ID
    AND L15.OBJ_TYPE_ID = 15
    AND L15.DATE_DEL IS NULL
    AND ((V74.VAL IS NULL) OR (V74.VAL >= CURRENT_DATE))

    INTO :X;

    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE IS_NATIVE_ID (
    I$ID BIGINT)
RETURNS (
    IS_NATIVE SMALLINT)
AS
BEGIN
    IS_NATIVE = 0;
    SELECT 1 FROM GEN
    WHERE :I$ID > GEN * MULTIPLIER AND :I$ID < (GEN + 1) * MULTIPLIER
    INTO :IS_NATIVE;
    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE IS_ON_THE_STAFF (
    I$TEACHER_ID BIGINT)
RETURNS (
    X SMALLINT)
AS
BEGIN
    X = 0;

    SELECT FIRST 1 1
    FROM LINKS L15
    JOIN VALL V587 ON V587.OBJ_ID = L15.OBJ_ID AND V587.PARAM_ID = 587 AND V587.IS_DEL = 0 AND V587.LISTVAL_ID = 207
    JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0 AND V73.VAL <= CURRENT_DATE
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
    WHERE L15.PARENT_ID = :I$TEACHER_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
      AND ((V74.VAL IS NULL) OR (V74.VAL >= CURRENT_DATE))
    INTO :X;

    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE IS_ROOT_OBJ_PARENT (
    I$PARENT_ID BIGINT,
    I$ROOT_OBJ_ID BIGINT,
    I$LEVEL_ID BIGINT)
RETURNS (
    STATUS SMALLINT)
AS
BEGIN
    STATUS = 0;
    IF (I$PARENT_ID = I$ROOT_OBJ_ID) THEN
    BEGIN
        STATUS = 1;
    END
    ELSE
    BEGIN
        FOR
            SELECT L.PARENT_ID
            FROM LINKS L
            WHERE L.OBJ_ID = :I$PARENT_ID
            AND L.DATE_DEL IS NULL

            INTO :I$PARENT_ID
        DO
        BEGIN
            FOR
                SELECT STATUS
                FROM IS_ROOT_OBJ_PARENT(
                    :I$PARENT_ID,
                    :I$ROOT_OBJ_ID,
                    :I$LEVEL_ID
                )
                INTO :STATUS
            DO
            BEGIN
                IF (STATUS = 1) THEN
                BEGIN
                    BREAK;
                END
            END
        END
    END
    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE IS_SECOND_YEAR (
    I$STUDENT_ID BIGINT,
    I$DATE DATE)
RETURNS (
    VAL SMALLINT)
AS
declare variable V$CHECK_DATE date;
declare variable V$LAST_MOVE_DATE date;
declare variable V$LAST_MOVE_TYPE bigint;
declare variable V$STAGE_ID bigint;
declare variable V$S varchar(255);
begin

  VAL = 0;

  -- Проверку выполняем с 01.08.XXXX в текущем учебном году
  IF(EXTRACT(MONTH FROM I$DATE) < 8) THEN V$CHECK_DATE = '01.08.' || (EXTRACT(YEAR FROM I$DATE) - 1); ELSE V$CHECK_DATE = '01.08.' || EXTRACT(YEAR FROM I$DATE);

  VAL = 0;

  -- Выбираем последнюю запись движения в параллели, и смотрим ее тип и параллель
  SELECT FIRST 1 M.DATE_IN, M.REASON_IN, LV."FILTER", M.STAGE_ID
  FROM PERSON_MOVEMENTS M
  JOIN OBJECTS O ON O.OBJ_ID = M.GROUP_ID AND O.TYPE_ID = 9
  JOIN LISTVALS LV ON LV.LISTVAL_ID = M.REASON_IN
  WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :I$STUDENT_ID AND M.DATE_IN >= :V$CHECK_DATE AND M.DATE_IN <= :I$DATE AND M.DATE_OUT IS NULL
  ORDER BY M.DATE_IN DESC
  INTO :V$LAST_MOVE_DATE, :V$LAST_MOVE_TYPE, :V$S, :V$STAGE_ID;

  -- Если записей движения не нашлось - считаем что ученик был принят в обычном порядке
  IF(V$LAST_MOVE_DATE IS NULL) THEN BEGIN END
  -- Если это - запись об оставлении на второй год, на этом заканчиваем
  ELSE IF(V$LAST_MOVE_TYPE = 810) THEN VAL = 1;
  -- Если это прием - считаем что это точно не второй год
  ELSE IF(POSITION('ACCEPTED' IN V$S) > 0) THEN VAL = 1;
  -- Во всех прочих случаях (перевод) смотрим, не было ли оставления на второй год в той же параллели до этого
  ELSE
  BEGIN
    SELECT FIRST 1 1
    FROM PERSON_MOVEMENTS M
    JOIN OBJECTS O ON O.OBJ_ID = M.GROUP_ID AND O.TYPE_ID = 9
    WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :I$STUDENT_ID AND M.DATE_IN >= :V$CHECK_DATE AND M.DATE_IN <= :I$DATE AND M.REASON_IN = 810
    INTO :VAL;
  END

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE IS_TEACHER (
    I$TEACHER_ID BIGINT)
RETURNS (
    X SMALLINT,
    VALID SMALLINT)
AS
declare variable V$X smallint;
BEGIN
    -- По-умолчанию для совместимости говорим, что не-педагог
    X = 0;
    -- Ответ не валиден
    VALID = 0;

    FOR
        SELECT T.SORT_ORDER
        -- Прием на должность
        FROM LINKS L15
        -- Должность
        JOIN LINKS L13 ON L13.OBJ_ID = L15.OBJ_ID AND L13.PARENT_TYPE_ID = 13 AND L13.DATE_DEL IS NULL
        -- Дата приема не в будущем
        JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0 AND V73.VAL <= CURRENT_DATE
        -- Человек не уволен, или уволен в будущем
        LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
        -- Должность = педагогическая
        LEFT JOIN DO_FUNC(L13.PARENT_ID, 400) T ON 1 = 1
        WHERE L15.PARENT_ID = :I$TEACHER_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
            AND ((V74.VAL IS NULL) OR (V74.VAL >= CURRENT_DATE))
        INTO :V$X
    DO
    BEGIN
        -- Есть хотя бы одна текущая должность
        VALID = 1;
        -- Если хотя бы одна педагогическая должность
        IF(V$X = 2) THEN BEGIN
            X = 1;
            SUSPEND;
            EXIT;
        END
    END

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE IS_VPL RETURNS (
    STATUS SMALLINT)
AS
begin
    STATUS = 0;
    IF (EXISTS(
        SELECT 1
        FROM KEYS
        WHERE KEY_CODE = 'COUNTRY'
        AND KEY_NAME LIKE 'ГИА Вирт ОУ'
    )) THEN
    BEGIN
        STATUS = 1;
    END
    SUSPEND;
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE IS_YOUNG_EMPLOYEE (
    I$PERSON_ID BIGINT,
    I$DATE_FROM DATE,
    I$DATE_TO DATE)
RETURNS (
    VAL SMALLINT)
AS
begin

  -- Выпускники этого года

  VAL = 0;

  SELECT FIRST 1 1
  FROM LINKS L33
  JOIN VALD V290 ON V290.OBJ_ID = L33.OBJ_ID AND V290.PARAM_ID = 290 AND V290.IS_DEL = 0 AND V290.VAL >= :I$DATE_FROM AND V290.VAL < :I$DATE_TO
  WHERE L33.PARENT_ID = :I$PERSON_ID AND L33.OBJ_TYPE_ID = 33 AND L33.DATE_DEL IS NULL
  INTO :VAL;

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE JOBLIST_DELETE (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
AS
DECLARE VARIABLE V$PARENT_ID BIGINT;
DECLARE VARIABLE V$ALLOW SMALLINT;
DECLARE VARIABLE V$MSG VARCHAR(1000);
DECLARE VARIABLE T INTEGER;
begin

  SELECT FIRST 1 LP.PARENT_ID
  FROM LINKS LP
  WHERE LP.OBJ_ID = :I$OBJ_ID AND LP.PARENT_TYPE_ID IN (2, 211) AND LP.DATE_DEL IS NULL
  INTO :V$PARENT_ID;

  SELECT CD.CAN_DELETE, COALESCE(CD.ERR_MSG, '')
  FROM PARAGRAF_CAN_DELETE_OBJECT(:I$OBJ_ID) CD
  INTO :V$ALLOW, :V$MSG;

  IF(V$ALLOW = 0) THEN
  BEGIN
    IF(V$MSG = '') THEN V$MSG = 'Объект не может быть удален';
    EXCEPTION DATA_ERROR V$MSG;
  END

  SELECT 1 FROM OBJECT_DEL(:V$PARENT_ID, :I$OBJ_ID) INTO :T;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE JOBLIST_DESCRIBE (
    I$USER_ID VARCHAR(40),
    I$APP VARCHAR(400),
    I$IP VARCHAR(400))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$USER_TYPE SMALLINT;
begin

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  TAG_NAME = 'user_type';
  VAL = NULL;
  SELECT FIRST 1 U.USER_TYPE
  FROM USERS U
  WHERE U.USER_ID = :I$USER_ID
  INTO :V$USER_TYPE;
  VAL = V$USER_TYPE;
  SUSPEND;

  TAG_NAME = 'is_admin';
  VAL = IIF(V$USER_TYPE = 1, 1, 0);
  SUSPEND;

  TAG_NAME = 'is_fin';
  VAL = 1;
  SUSPEND;

  TAG_NAME = 'level';
  VAL = (SELECT KEY_VAL FROM KEYS WHERE KEY_CODE = 'LEVEL');
  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE JOBLIST_GET (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$DIV_ID BIGINT;
DECLARE VARIABLE V$DIV_TYPE BIGINT;
DECLARE VARIABLE S VARCHAR(1000);
DECLARE VARIABLE S2 VARCHAR(1000);
DECLARE VARIABLE D1 DATE;
DECLARE VARIABLE D2 DATE;
DECLARE VARIABLE V$EMP_ID VARCHAR(40);
DECLARE VARIABLE V$RATE DOUBLE PRECISION;
DECLARE VARIABLE V$CAT_ID BIGINT;
DECLARE VARIABLE V$WEEK VARCHAR(400);
DECLARE VARIABLE V$TERMS_ID VARCHAR(400);
DECLARE VARIABLE V$ORDER_D1 DATE;
DECLARE VARIABLE V$ORDER_D2 DATE;
DECLARE VARIABLE V$CONTRACT_TO DATE;
DECLARE VARIABLE V$CONTRACT_D DATE;
DECLARE VARIABLE V$ORDER_N1 VARCHAR(400);
DECLARE VARIABLE V$ORDER_N2 VARCHAR(400);
DECLARE VARIABLE V$CONTRACT_N VARCHAR(400);
DECLARE VARIABLE V$OU_ID BIGINT;
DECLARE VARIABLE V$JOB_LV BIGINT;
DECLARE VARIABLE V$JOB_NAME VARCHAR(1000);
DECLARE VARIABLE V$LIST_ID BIGINT;
begin

  SELECT L13.OBJ_ID, L13.PARENT_ID, L13.PARENT_TYPE_ID
  FROM LINKS L13
  WHERE L13.OBJ_ID = :I$OBJ_ID AND L13.PARENT_TYPE_ID IN (2, 211) AND L13.DATE_DEL IS NULL
  INTO :V$OBJ_ID, :V$DIV_ID, :V$DIV_TYPE;

  IF(I$OBJ_ID IS NOT NULL AND V$OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Должность не найдена или была удалена';

  IF(V$DIV_TYPE = 2) THEN V$OU_ID = V$DIV_ID;
  ELSE
  SELECT FIRST 1 LP2.PARENT_ID
  FROM LINKS LP2
  WHERE LP2.OBJ_ID = :V$DIV_ID AND LP2.PARENT_TYPE_ID = 2 AND LP2.DATE_DEL IS NULL
  INTO :V$OU_ID;

  TAG_NAME = 'id';
  VAL = I$OBJ_ID;
  SUSPEND;

  TAG_NAME = 'div_id';
  VAL = V$DIV_ID;
  SUSPEND;

  TAG_NAME = 'div_name';
  IF(V$DIV_TYPE = 2) THEN VAL = 'Образовательная организация'; ELSE VAL = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$DIV_ID));
  SUSPEND;

  TAG_NAME = 'name';
  VAL = NULL;
  SELECT V.VAL
  FROM VALS V
  WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 66 AND V.IS_DEL = 0
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'cat_id';
  VAL = NULL;
  S = NULL;
  S2 = NULL;
  SELECT FIRST 1 V58.LISTVAL_ID, C.VAL, IIF(LV.LIST_ID = 369, LV.TAG, NULL), LV.LIST_ID
  FROM VALL V58
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V58.LISTVAL_ID
  LEFT JOIN LISTVAL_TEXT(LV.LISTVAL_ID) C ON 1 = 1
  WHERE V58.OBJ_ID = :I$OBJ_ID AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0
  INTO :V$JOB_LV, :S, :S2, :V$LIST_ID;
  VAL = V$JOB_LV;
  V$JOB_NAME = S;
  SUSPEND;

  -- Если есть код - добавляем его к названию должности, только ОКДП
  TAG_NAME = 'cat_name';
  VAL = S;
  IF(S2 = 'R1' OR S2 = 'R2' OR S2 = 'U') THEN S2 = NULL;
  IF(S2 IS NOT NULL AND V$LIST_ID = 369) THEN VAL = S2 || ' ' || VAL;
  SUSPEND;

  TAG_NAME = 'rate_val';
  VAL = NULL;
  SELECT V.VAL
  FROM VALF V
  WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 62 AND V.IS_DEL = 0
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'load_val';
  VAL = NULL;
  SELECT V.VAL
  FROM VALF V
  WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 65 AND V.IS_DEL = 0
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'comments';
  VAL = NULL;
  SELECT V.VAL
  FROM VALS V
  WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 67 AND V.IS_DEL = 0
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'file';
  VAL = NULL;
  SELECT V.VAL
  FROM VALB V
  WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 68 AND V.IS_DEL = 0
  INTO :VAL;
  SUSPEND;

  -- Текущая информация по данной должности
  -- Количество по штатному расписанию
  TAG_NAME = 'rate_joblist';
  VAL = NULL;
  SELECT FIRST 1 V3493.VAL
  FROM LINKS L508
  JOIN LINKS L505 ON L505.PARENT_ID = L508.OBJ_ID AND L505.OBJ_TYPE_ID = 505 AND L505.DATE_DEL IS NULL
  JOIN VALL V3490 ON V3490.OBJ_ID = L505.OBJ_ID AND V3490.PARAM_ID = 3490 AND V3490.IS_DEL = 0 AND V3490.LISTVAL_ID = 11715  -- действующее ШР
  JOIN LINKS L506 ON L506.PARENT_ID = L505.OBJ_ID AND L506.OBJ_TYPE_ID = 506 AND L506.DATE_DEL IS NULL
  JOIN VALF V3493 ON V3493.OBJ_ID = L506.OBJ_ID AND V3493.PARAM_ID = 3493 AND V3493.IS_DEL = 0 -- кол-во ставок
  LEFT JOIN VALL V3492 ON V3492.OBJ_ID = L506.OBJ_ID AND V3492.PARAM_ID = 3492 AND V3492.IS_DEL = 0 -- должность из списка
  LEFT JOIN VALS V3494 ON V3494.OBJ_ID = L506.OBJ_ID AND V3494.PARAM_ID = 3494 AND V3494.IS_DEL =  0 -- название должности
  WHERE L508.PARENT_ID = :V$OU_ID AND L508.OBJ_TYPE_ID = 508 AND L508.DATE_DEL IS NULL
    AND COALESCE(V3492.LISTVAL_ID, 0) = COALESCE(:V$JOB_LV, 0) AND UPPER(TRIM(V3494.VAL)) = UPPER(TRIM(:V$JOB_NAME))
  INTO :VAL;
  SUSPEND;

  -- Фактически количество занятых ставок
  TAG_NAME = 'rate_fact';
  VAL = NULL;
  SELECT V.VAL
  FROM VALF V
  WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 2850 AND V.IS_DEL = 0
  INTO :VAL;
  SUSPEND;

  -- Количество временно свободных
  TAG_NAME = 'rate_tempfree';
  VAL = NULL;
  SELECT V.VAL
  FROM VALF V
  WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 2851 AND V.IS_DEL = 0
  INTO :VAL;
  SUSPEND;

  -- Список сотрудников на должности все скопом, группируем на фронте
  TAG_NAME = 'items::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L15.OBJ_ID, C.C1, V73.VAL, V74.VAL, V3543.VAL, C72.VAL, V71.VAL, V1790.LISTVAL_ID, C3553.VAL, C587.VAL,
      V454.VAL, V455.SVAL, V456.VAL, V457.SVAL, V583.VAL, V1638.SVAL, V1639.VAL
    FROM LINKS L15
    JOIN LINKS LP14 ON LP14.OBJ_ID = L15.OBJ_ID AND LP14.PARENT_TYPE_ID = 14 AND LP14.DATE_DEL IS NULL
    LEFT JOIN BUILD_REP_FIO(LP14.PARENT_ID, 59, 60, 61, 1) C ON 1 = 1
    JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
    LEFT JOIN VALS V3543 ON V3543.OBJ_ID = L15.OBJ_ID AND V3543.PARAM_ID = 3543 AND V3543.IS_DEL = 0
    JOIN VALL V72 ON V72.OBJ_ID = L15.OBJ_ID AND V72.PARAM_ID = 72 AND V72.IS_DEL = 0
    LEFT JOIN LISTVAL_TEXT(V72.LISTVAL_ID) C72 ON 1 = 1
    JOIN VALF V71 ON V71.OBJ_ID = L15.OBJ_ID AND V71.PARAM_ID = 71 AND V71.IS_DEL = 0
    LEFT JOIN VALL V1790 ON V1790.OBJ_ID = L15.OBJ_ID AND V1790.PARAM_ID = 1790 AND V1790.IS_DEL = 0
    LEFT JOIN VALL V3553 ON V3553.OBJ_ID = L15.OBJ_ID AND V3553.PARAM_ID = 3553 AND V3553.IS_DEL = 0
    LEFT JOIN LISTVAL_TEXT(V3553.LISTVAL_ID) C3553 ON 1 = 1
    LEFT JOIN VALL V587 ON V587.OBJ_ID = L15.OBJ_ID AND V587.PARAM_ID = 587 AND V587.IS_DEL = 0
    LEFT JOIN LISTVAL_TEXT(V587.LISTVAL_ID) C587 ON 1 = 1
    LEFT JOIN VALD V454 ON V454.OBJ_ID = L15.OBJ_ID AND V454.PARAM_ID = 454 AND V454.IS_DEL = 0
    LEFT JOIN VALS V455 ON V455.OBJ_ID = L15.OBJ_ID AND V455.PARAM_ID = 455 AND V455.IS_DEL = 0
    LEFT JOIN VALD V456 ON V456.OBJ_ID = L15.OBJ_ID AND V456.PARAM_ID = 456 AND V456.IS_DEL = 0
    LEFT JOIN VALS V457 ON V457.OBJ_ID = L15.OBJ_ID AND V457.PARAM_ID = 457 AND V457.IS_DEL = 0
    LEFT JOIN VALD V583 ON V583.OBJ_ID = L15.OBJ_ID AND V583.PARAM_ID = 583 AND V583.IS_DEL = 0
    LEFT JOIN VALS V1638 ON V1638.OBJ_ID = L15.OBJ_ID AND V1638.PARAM_ID = 1638 AND V1638.IS_DEL = 0
    LEFT JOIN VALD V1639 ON V1639.OBJ_ID = L15.OBJ_ID AND V1639.PARAM_ID = 1639 AND V1639.IS_DEL = 0
    WHERE L15.PARENT_ID = :I$OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
    ORDER BY 3, 2
    INTO :V$OBJ_ID, :S, :D1, :D2, :S2, :V$EMP_ID, :V$RATE, :V$CAT_ID, :V$WEEK, :V$TERMS_ID,
      :V$ORDER_D1, :V$ORDER_N1, :V$ORDER_D2, :V$ORDER_N2, :V$CONTRACT_TO, :V$CONTRACT_N, :V$CONTRACT_D
  DO
  BEGIN
    TAG_NAME = 'items:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'items:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'items:r:name';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'items:r:book_name';
    VAL = S2;
    SUSPEND;
    TAG_NAME = 'items:r:date_from';
    VAL = (SELECT VAL FROM DATE2ISO(:D1, 0));
    SUSPEND;
    TAG_NAME = 'items:r:date_to';
    VAL = (SELECT VAL FROM DATE2ISO(:D2, 0));
    SUSPEND;
    TAG_NAME = 'items:r:emp_type';
    VAL = V$EMP_ID;
    SUSPEND;
    TAG_NAME = 'items:r:terms';
    VAL = V$TERMS_ID;
    SUSPEND;
    TAG_NAME = 'items:r:week';
    VAL = V$WEEK;
    SUSPEND;
    TAG_NAME = 'items:r:rate';
    VAL = V$RATE;
    SUSPEND;
    TAG_NAME = 'items:r:contract_date';
    VAL = (SELECT VAL FROM DATE2ISO(:V$CONTRACT_D, 0));
    SUSPEND;
    TAG_NAME = 'items:r:contract_num';
    VAL = V$CONTRACT_N;
    SUSPEND;
    TAG_NAME = 'items:r:contract_to_date';
    VAL = (SELECT VAL FROM DATE2ISO(:V$CONTRACT_TO, 0));
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE JOBLIST_MERGE (
    I$OBJ_ID BIGINT,
    I$DEST_ID BIGINT,
    I$USER_ID VARCHAR(40))
AS
DECLARE VARIABLE V$CNT SMALLINT;
DECLARE VARIABLE V$ID BIGINT;
DECLARE VARIABLE V$F FLOAT;
DECLARE VARIABLE V$S VARCHAR(1000);
DECLARE VARIABLE V$RATE FLOAT;
begin
  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  -- проверка, что должности одного типа и из одного подразделения
  SELECT COUNT(*)
  FROM
    (SELECT DISTINCT L13.PARENT_ID, V58.LISTVAL_ID
    FROM LINKS L13
    JOIN VALL V58 ON V58.OBJ_ID = L13.OBJ_ID AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0
    WHERE L13.OBJ_ID IN (:I$OBJ_ID, :I$DEST_ID) AND L13.DATE_DEL IS NULL AND L13.PARENT_TYPE_ID IN (2, 211))
  INTO :V$CNT;
  IF (V$CNT > 1) THEN
    EXCEPTION DATA_ERROR('Невозможно склеить должности. Должности должны совпадать по кодификатору и относится к одному подразделению');

  -- Перенос назначений на новую должность
  SELECT VAL
  FROM VALF
  WHERE OBJ_ID = :I$DEST_ID AND PARAM_ID = 62 AND IS_DEL = 0
  INTO :V$RATE;
  FOR
    SELECT L15.OBJ_ID, V66.VAL, V71.VAL
    FROM LINKS L15
    JOIN VALS V66 ON V66.OBJ_ID = L15.PARENT_ID AND V66.PARAM_ID = 66 AND V66.IS_DEL = 0
    JOIN VALF V71 ON V71.OBJ_ID = L15.OBJ_ID AND V71.PARAM_ID = 71 AND V71.IS_DEL = 0 AND V71.VAL > 0
    WHERE L15.OBJ_TYPE_ID = 15 AND L15.PARENT_ID = :I$OBJ_ID AND L15.DATE_DEL IS NULL
    ORDER BY 1
    INTO :V$ID, :V$S, :V$F
  DO
  BEGIN
    -- необходимо заполнить "название в трудовой у сотрудника, если его нет"
    IF (NOT EXISTS(SELECT VAL FROM VALS WHERE OBJ_ID = :V$ID AND PARAM_ID = 3543 AND IS_DEL = 0)) THEN
      SELECT 1 FROM VAL_ADD(3543, :V$ID, :V$S, :I$USER_ID) INTO :V$CNT;

    -- перенос назначения на новую должность
    UPDATE LINKS
    SET PARENT_ID = :I$DEST_ID
    WHERE OBJ_ID = :V$ID AND PARENT_ID = :I$OBJ_ID AND DATE_DEL IS NULL;

    V$RATE = COALESCE(V$RATE, 0) + V$F;
  END
  -- увеличим число ставок у новой должности
  IF (V$RATE <> V$F) THEN
    SELECT 1 FROM VAL_ADD(62, :I$DEST_ID, :V$RATE, :I$USER_ID) INTO :V$CNT;

  -- удаляем должность
  UPDATE LINKS
  SET DATE_DEL = CURRENT_TIMESTAMP
  WHERE DATE_DEL IS NULL AND OBJ_ID = :I$OBJ_ID AND PARENT_TYPE_ID IN (2, 211);

  -- логирование
  INSERT INTO HISTVALS
  (TABLE_NAME, OBJ_ID, USER_ID, PARAM_ID, OPT_ID, PARENT_ID, OLD_VAL, VAL)
  VALUES ('LINKS', :I$OBJ_ID, :I$USER_ID, 0, 0, :I$DEST_ID, 'JOBLIST_MERGE, склеивание должностей', '');

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE JOBLIST_MERGE_CND (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$ID BIGINT;
DECLARE VARIABLE V$CODE BIGINT;
DECLARE VARIABLE V$NAME VARCHAR(1000);
DECLARE VARIABLE V$PARENT_ID BIGINT;
begin
  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  -- найдем подразделение, к которому относится должность
  SELECT L13.PARENT_ID
  FROM LINKS L13
  WHERE L13.OBJ_ID = :I$OBJ_ID AND L13.PARENT_TYPE_ID IN (2, 211) AND L13.DATE_DEL IS NULL
  INTO :V$PARENT_ID;

  -- найдем код должности из справочника
  SELECT V.LISTVAL_ID
  FROM VALL V
  WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 58 AND V.IS_DEL = 0
  INTO :V$CODE;

  -- найдем аналогичные должности в подразделении, с которыми можно склеить эту должность
  FOR
    SELECT L13.OBJ_ID, V66.VAL
    FROM LINKS L13
    JOIN VALL V58 ON V58.OBJ_ID = L13.OBJ_ID AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0 AND V58.LISTVAL_ID = :V$CODE
    JOIN VALS V66 ON V66.OBJ_ID = L13.OBJ_ID AND V66.PARAM_ID = 66 AND V66.IS_DEL = 0
    WHERE L13.OBJ_TYPE_ID = 13 AND L13.DATE_DEL IS NULL AND L13.PARENT_ID = :V$PARENT_ID AND L13.OBJ_ID <> :I$OBJ_ID
    INTO :V$ID, :V$NAME
  DO
  BEGIN
    TAG_NAME = 'item';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'item:id';
    VAL = V$ID;
    SUSPEND;
    TAG_NAME = 'item:value';
    VAL = V$NAME;
    SUSPEND;
  END
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE JOBLIST_SET (
    I$OBJ_ID BIGINT,
    I$DIV_ID BIGINT,
    I$CATEGORY_ID BIGINT,
    I$NAME VARCHAR(1000) NOT NULL,
    I$RATE DOUBLE PRECISION,
    I$LOAD DOUBLE PRECISION,
    I$COMMENTS VARCHAR(4000),
    I$USER_ID VARCHAR(40))
RETURNS (
    OBJ_ID BIGINT)
AS
DECLARE VARIABLE T BIGINT;
begin
  I$NAME = TRIM(I$NAME);
  IF(CHAR_LENGTH(I$NAME) < 3) THEN EXCEPTION DATA_ERROR 'Название должности должно быть не менее 3 символов';
  IF(I$CATEGORY_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не задана должность из списка';
  IF(I$RATE < 0 OR I$RATE IS NULL) THEN EXCEPTION DATA_ERROR 'Количество ставок должно быть неотрицательным';
  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  SELECT FIRST 1 L13.OBJ_ID
  FROM LINKS L13
  WHERE L13.PARENT_ID = :I$DIV_ID AND L13.OBJ_ID = :I$OBJ_ID AND L13.OBJ_TYPE_ID = 13 AND L13.DATE_DEL IS NULL AND L13.PARENT_TYPE_ID IN (2, 211)
  INTO :OBJ_ID;

  IF(I$OBJ_ID IS NOT NULL AND OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Должность не найдена или была удалена';

  IF(I$OBJ_ID IS NULL) THEN
  BEGIN
    IF(NOT EXISTS(SELECT FIRST 1 1 FROM OBJECTS WHERE OBJ_ID = :I$DIV_ID AND TYPE_ID IN (2, 211))) THEN EXCEPTION DATA_ERROR 'Недопустимый родительский объект';
    SELECT OBJ_ID FROM OBJECT_ADD(:I$DIV_ID, 13, NULL, NULL, :I$USER_ID) INTO :OBJ_ID;
  END

  SELECT 1 FROM VAL_ADD(58, :OBJ_ID, :I$CATEGORY_ID, :I$USER_ID) INTO :T;
  SELECT 1 FROM VAL_ADD(66, :OBJ_ID, :I$NAME, :I$USER_ID) INTO :T;
  SELECT 1 FROM VAL_ADD(62, :OBJ_ID, :I$RATE, :I$USER_ID) INTO :T;
  SELECT 1 FROM VAL_ADD(65, :OBJ_ID, :I$LOAD, :I$USER_ID) INTO :T;
  SELECT 1 FROM VAL_ADD(67, :OBJ_ID, :I$COMMENTS, :I$USER_ID) INTO :T;

  -- Пересчет статуса должности
  EXECUTE PROCEDURE CALC_JOB_OCCUPIED(:OBJ_ID);

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE JOBLIST_TRANSFER (
    I$MODE VARCHAR(12))
RETURNS (
    VAL VARCHAR(4000))
AS
DECLARE VARIABLE V$ID BIGINT;
DECLARE VARIABLE V$JOB_ID BIGINT;
DECLARE VARIABLE V$OLD_JOB_ID BIGINT;
DECLARE VARIABLE V$JOB_NAME VARCHAR(1000);
DECLARE VARIABLE V$ORG BIGINT;
DECLARE VARIABLE V$JOB_EMP_ID BIGINT;
DECLARE VARIABLE V$F FLOAT;
DECLARE VARIABLE V$S VARCHAR(1000);
DECLARE VARIABLE V$CAT_ID BIGINT;
DECLARE VARIABLE V$NEW_CAT_ID BIGINT;
DECLARE VARIABLE DT TIMESTAMP;
begin
  -- ALL     - перенести все должности в название должности в трудовой. А также перенести должности по полному совпадению названий из старого кодификатора в новый
  -- RECORD  - пропишем текущее название должности в поле Наименование должности в трудовой книжке для всех работающих сотрудников
  -- TEACH   - заменим должность 'учитель такой-то' на 'учитель' из справочника. Полное название дожности переносим в название должности в трудовой.
  -- TUTOR   - Заменим должность 'воспитатель такой-то' на 'воспитатель' из справочника. Полное название дожности переносим в название должности в трудовой.
  -- LECT    - Заменим должность 'преподаватель такой-то' на 'преподаватель' из справочника. Полное название дожности переносим в название должности в трудовой.
  -- DEPUTY  - Заменим должность 'Заместитель директора по такой-то работе' на 'Заместитель директора' из справочника. Полное название дожности переносим в название должности в трудовой.

  DT = CURRENT_TIMESTAMP;
  I$MODE = UPPER(TRIM(I$MODE));
  IF (COALESCE(I$MODE, '') = '') THEN I$MODE = 'ALL';
  IF (I$MODE <> 'ALL' AND I$MODE <> 'RECORD' AND I$MODE <> 'TEACH' AND I$MODE <> 'TUTOR' AND I$MODE <> 'LECT' AND I$MODE <> 'DEPUTY') THEN
    EXCEPTION DATA_ERROR('Неверный параметр выполнения процедуры - ' || COALESCE(I$MODE, 'null'));

  -- ИО директора и ИО заведующего как должность прибить навсегда, вместе с назначением на нее
  FOR
    SELECT LP13.PARENT_ID, LP13.OBJ_ID
    FROM LINKS LP13
    JOIN VALL V58 ON V58.OBJ_ID = LP13.PARENT_ID AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0 AND V58.LISTVAL_ID IN (74, 3301)
    JOIN LINKS LPG ON LPG.OBJ_ID = LP13.PARENT_ID AND LPG.PARENT_TYPE_ID IN (2, 211) AND LPG.DATE_DEL IS NULL
    WHERE LP13.OBJ_TYPE_ID = 15 AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
    ORDER BY 2
    INTO :V$JOB_ID, :V$JOB_EMP_ID
  DO
  BEGIN
    -- Удаляем только связь 14 -> 15, 13 -> 15 оставляем
    UPDATE LINKS
    SET DATE_DEL = CURRENT_TIMESTAMP
    WHERE DATE_DEL IS NULL AND OBJ_ID = :V$JOB_EMP_ID AND PARENT_TYPE_ID = 14;
  END
  FOR
    SELECT DISTINCT LP13.PARENT_ID
    FROM LINKS LP13
    JOIN VALL V58 ON V58.OBJ_ID = LP13.PARENT_ID AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0 AND V58.LISTVAL_ID IN (74, 3301)
    JOIN LINKS LPG ON LPG.OBJ_ID = LP13.PARENT_ID AND LPG.PARENT_TYPE_ID IN (2, 211) AND LPG.DATE_DEL IS NULL
    WHERE LP13.OBJ_TYPE_ID = 15 AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
    ORDER BY 1
    INTO :V$JOB_ID
  DO
  BEGIN
    -- Удаляем саму #13
    UPDATE LINKS
    SET DATE_DEL = CURRENT_TIMESTAMP
    WHERE DATE_DEL IS NULL AND OBJ_ID = :V$JOB_ID AND PARENT_TYPE_ID IN (2, 211);
  END

  -- пропишем текущее название должности в поле Наименование должности в трудовой книжке для всех сотрудников
  IF (I$MODE = 'RECORD' OR I$MODE = 'ALL') THEN
  FOR
    SELECT L15.OBJ_ID, COALESCE(V66.VAL, JB.VAL)
    FROM LINKS L15
    JOIN VALL V58 ON V58.OBJ_ID = L15.PARENT_ID AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0
    LEFT JOIN LISTVAL_TEXT(V58.LISTVAL_ID) JB ON 1 = 1
    LEFT JOIN VALS V66 ON V66.OBJ_ID = L15.PARENT_ID AND V66.PARAM_ID = 66 AND V66.IS_DEL = 0
    LEFT JOIN VALS V3543 ON V3543.OBJ_ID = L15.OBJ_ID AND V3543.PARAM_ID = 3543 AND V3543.IS_DEL = 0
    WHERE L15.OBJ_TYPE_ID = 15 AND L15.PARENT_TYPE_ID = 13 AND L15.DATE_DEL IS NULL AND V3543.SVAL IS NULL
    ORDER BY 2, 1
    INTO :V$JOB_EMP_ID, :V$JOB_NAME
  DO
  BEGIN
    IF (NOT EXISTS(SELECT FIRST 1 1 FROM VALS V WHERE V.OBJ_ID = :V$JOB_EMP_ID AND V.PARAM_ID = 3543 AND V.IS_DEL = 0)) THEN
    BEGIN
      SELECT 1 FROM VAL_ADD(3543, :V$JOB_EMP_ID, :V$JOB_NAME) INTO :V$ID;
      VAL = 'Установка названия должности в трудовой '  || V$JOB_NAME || ', id = ' || V$JOB_EMP_ID;
      SUSPEND;
    END
  END

  -- Исправляем косяк когда все стали Старшими преподавателями
  FOR
    SELECT DISTINCT LP13.PARENT_ID, V3543.SVAL, LPG.PARENT_ID
    FROM LINKS LP13
    JOIN VALL V58 ON V58.OBJ_ID = LP13.PARENT_ID AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0 AND V58.LISTVAL_ID = 18558
    JOIN VALS V3543 ON V3543.OBJ_ID = LP13.OBJ_ID AND V3543.PARAM_ID = 3543 AND V3543.IS_DEL = 0
    JOIN LINKS LPG ON LPG.OBJ_ID = LP13.PARENT_ID AND LPG.PARENT_TYPE_ID IN (2, 211) AND LPG.DATE_DEL IS NULL
    WHERE LP13.OBJ_TYPE_ID = 15 AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL AND V3543.SVAL <> 'Старший преподаватель'
    ORDER BY 1, 2
    INTO :V$JOB_ID, :V$JOB_NAME, :V$ORG
  DO
  BEGIN
    V$CAT_ID = NULL;
    V$NEW_CAT_ID = NULL;

    SELECT MAX(LV369.LISTVAL_ID)
    FROM LISTVALS LV369
    JOIN RES R ON R.RES_ID = LV369.RES_ID AND R.LANG_CODE = 'RU' AND R.VAL = :V$JOB_NAME
    WHERE LV369.LIST_ID = 369 AND LV369.PARENT_ID IN (18528, 18543, 18552) AND LV369.IS_DEL = 0
    INTO :V$CAT_ID;

    SELECT MAX(LV369.LISTVAL_ID)
    FROM LISTVALS LV369
    JOIN RES R ON R.RES_ID = LV369.RES_ID AND R.LANG_CODE = 'RU' AND R.VAL = :V$JOB_NAME
    WHERE LV369.LIST_ID = 369 AND LV369.PARENT_ID NOT IN (18528, 18543, 18552) AND LV369.IS_DEL = 0
    INTO :V$NEW_CAT_ID;

    V$CAT_ID = COALESCE(V$CAT_ID, V$NEW_CAT_ID);

    IF(V$CAT_ID IS NULL) THEN
    BEGIN
      V$S = UPPER(V$JOB_NAME);
      IF(V$S LIKE '%ЗАМЕСТИТЕЛЬ ДИРЕКТОРА%') THEN V$CAT_ID = 18498;
      IF(V$S LIKE '%ЗАВЕДУЮЩИЙ%ПОДРАЗДЕЛЕНИ%' OR V$S LIKE '%РУКОВОДИТЕЛЬ%ПОДРАЗДЕЛЕНИ%' OR V$S LIKE '%ЗАВЕДУЮЩИЙ%БИБЛ%') THEN V$CAT_ID = 18499;
    END

    -- Если совсем не получается, ищем по всем
    IF(V$CAT_ID IS NULL) THEN
    SELECT MAX(LV21.LISTVAL_ID)
    FROM LISTVALS LV21
    JOIN RES R ON R.RES_ID = LV21.RES_ID AND R.LANG_CODE = 'RU' AND R.VAL = :V$JOB_NAME
    WHERE LV21.LIST_ID = 21 AND LV21.PARENT_ID IS NOT NULL AND LV21.IS_DEL = 0
    INTO :V$CAT_ID;

    -- И последняя надежда на старый справочник
    IF(V$CAT_ID IS NULL) THEN
    SELECT MAX(LV369.LISTVAL_ID)
    FROM LISTVALS LV369
    JOIN RES R ON R.RES_ID = LV369.RES_ID AND R.LANG_CODE = 'RU' AND R.VAL = :V$JOB_NAME
    WHERE LV369.LIST_ID = 369 AND LV369.PARENT_ID IS NOT NULL AND LV369.IS_DEL = 0
    INTO :V$CAT_ID;

    IF(V$CAT_ID IN (18498, 18499)) THEN
    BEGIN
      -- Убираем дубли
      V$OLD_JOB_ID = NULL;
      SELECT FIRST 1 L13.OBJ_ID
      FROM LINKS L13
      JOIN VALL V58 ON V58.OBJ_ID = L13.OBJ_ID AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0 AND V58.LISTVAL_ID = :V$CAT_ID
      WHERE L13.OBJ_TYPE_ID = 13 AND L13.PARENT_ID = :V$ORG AND L13.DATE_DEL IS NULL
      ORDER BY L13.DATE_MODIFY DESC
      INTO :V$OLD_JOB_ID;

      IF(V$OLD_JOB_ID <> V$JOB_ID) THEN
      BEGIN
        UPDATE LINKS SET PARENT_ID = :V$OLD_JOB_ID WHERE PARENT_ID = :V$JOB_ID AND DATE_DEL IS NULL;
        UPDATE LINKS SET DATE_DEL = CURRENT_TIMESTAMP WHERE OBJ_ID = :V$JOB_ID AND DATE_DEL IS NULL;
        VAL = 'Слияние должностей '  || V$JOB_NAME || ', id = ' || V$JOB_ID;
        SUSPEND;
        V$CAT_ID = NULL;
      END
    END
    IF(V$CAT_ID IS NOT NULL) THEN
    BEGIN
      VAL = 'Коррекция, должность ' || V$JOB_NAME || ', новый тип ' || V$CAT_ID;
      SUSPEND;
      SELECT 1 FROM VAL_ADD(58, :V$JOB_ID, :V$CAT_ID) INTO :V$ID;
      SELECT 1 FROM VAL_ADD(66, :V$JOB_ID, :V$JOB_NAME) INTO :V$ID;
    END
  END

  -- Переносим по полному соответствию названия должности с названием в новом кодификаторе. Таким образом, соблюдем уникальность уже имеющихся должностей - цчитель, воспитатель и т.д, но в новом кодификаторе
  IF (1 = 1) THEN
  BEGIN
    FOR
      -- Найдем должности, которые можно перенести по полному соответствию ее названия с названием в новом кодификаторе
      SELECT LP13.OBJ_ID, LP13.PARENT_ID, V66.VAL
      FROM LINKS LP13
      JOIN VALS V66 ON V66.OBJ_ID = LP13.PARENT_ID AND V66.PARAM_ID = 66 AND V66.IS_DEL = 0
      JOIN VALL V58 ON V58.OBJ_ID = LP13.PARENT_ID AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0
      JOIN LISTVALS LV58 ON LV58.LISTVAL_ID = V58.LISTVAL_ID AND LV58.IS_DEL = 0 AND LV58.LIST_ID = 21 -- старый кодификатор должностей
      WHERE LP13.OBJ_TYPE_ID = 15 AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
      ORDER BY 1
      INTO :V$JOB_EMP_ID, :V$JOB_ID, :V$JOB_NAME
    DO
    BEGIN
      V$CAT_ID = NULL;
      V$NEW_CAT_ID = NULL;

      SELECT MAX(LV369.LISTVAL_ID)
      FROM LISTVALS LV369
      JOIN RES R ON R.RES_ID = LV369.RES_ID AND R.LANG_CODE = 'RU' AND R.VAL = :V$JOB_NAME
      WHERE LV369.LIST_ID = 369 AND LV369.PARENT_ID IN (18528, 18543, 18552) AND LV369.IS_DEL = 0
      INTO :V$CAT_ID;

      SELECT MAX(LV369.LISTVAL_ID)
      FROM LISTVALS LV369
      JOIN RES R ON R.RES_ID = LV369.RES_ID AND R.LANG_CODE = 'RU' AND R.VAL = :V$JOB_NAME
      WHERE LV369.LIST_ID = 369 AND LV369.PARENT_ID NOT IN (18528, 18543, 18552) AND LV369.IS_DEL = 0
      INTO :V$NEW_CAT_ID;

      V$CAT_ID = COALESCE(V$CAT_ID, V$NEW_CAT_ID);

      IF(V$CAT_ID IS NOT NULL) THEN
      BEGIN
        VAL = 'Перенос по полному соответствию названия, должность '  || V$JOB_NAME;
        SUSPEND;
        SELECT 1 FROM VAL_ADD(58, :V$JOB_ID, :V$CAT_ID) INTO :V$ID;
        SELECT 1 FROM VAL_ADD(66, :V$JOB_ID, :V$JOB_NAME) INTO :V$ID;
        SELECT 1 FROM VAL_ADD(3543, :V$JOB_EMP_ID, :V$JOB_NAME) INTO :V$ID;
        VAL = 'Должность приведена в соответствие c новым кодификатором, id: '  || V$JOB_ID || ', тип ' || V$CAT_ID;
        SUSPEND;
      END
    END
  END

  -- Заменим должность 'учитель такой-то' на 'учитель' из справочника. Полное название дожности переносим в название должности в трудовой.
  -- Кроме: Учитель-логопед, учитель-дефектолог, у них свои особенные коды
  IF (I$MODE = 'TEACH' OR I$MODE = 'ALL') THEN
  BEGIN
    FOR
      SELECT L15.OBJ_ID, L15.PARENT_ID, V58.LISTVAL_ID, V66.VAL, LP2.PARENT_ID
      FROM LINKS L15
      JOIN LINKS LP2 ON LP2.OBJ_ID = L15.PARENT_ID AND LP2.PARENT_TYPE_ID IN (2, 211) AND LP2.DATE_DEL IS NULL
      JOIN VALL V58 ON V58.OBJ_ID = L15.PARENT_ID AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0
      JOIN VALS V66 ON V66.OBJ_ID = L15.PARENT_ID AND V66.PARAM_ID = 66 AND V66.IS_DEL = 0
      LEFT JOIN LISTVAL_TEXT(V58.LISTVAL_ID) JB ON 1 = 1
      WHERE L15.OBJ_TYPE_ID = 15 AND L15.PARENT_TYPE_ID = 13 AND L15.DATE_DEL IS NULL
        AND V58.LISTVAL_ID NOT IN (18501, 18505, 18551)
        AND (
          UPPER(TRIM(V66.VAL)) LIKE '%УЧИТЕЛЬ %' OR
          UPPER(JB.VAL) LIKE '%УЧИТЕЛЬ %' OR
          UPPER(TRIM(V66.VAL)) LIKE '%УЧИТЕЛЬ-%' OR
          UPPER(JB.VAL) LIKE '%УЧИТЕЛЬ-%'
        )
      ORDER BY 1
      INTO :V$JOB_EMP_ID, :V$OLD_JOB_ID, :V$CAT_ID, :V$JOB_NAME, :V$ORG
    DO
    BEGIN
      VAL = 'Перенос ' || V$JOB_NAME || ', id = ' || V$JOB_EMP_ID;
      SUSPEND;

      -- Найти должность Учитель, Учитель-Логопед, Учитель-дефектолог
      V$CAT_ID = CASE V$CAT_ID WHEN 119 THEN 18505 WHEN 120 THEN 18551 ELSE 18501 END;
      IF(UPPER(V$JOB_NAME) LIKE '%ЛОГОПЕД%') THEN V$CAT_ID = 18551;
      IF(UPPER(V$JOB_NAME) LIKE '%ДЕФЕКТОЛОГ%') THEN V$CAT_ID = 18505;

      -- Проверим по id, есть ли должность Учитель, Учитель-Логопед, Учитель-дефектолог
      V$JOB_ID = NULL;
      SELECT FIRST 1 L13.OBJ_ID
      FROM LINKS L13
      JOIN VALL V58 ON V58.OBJ_ID = L13.OBJ_ID AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0 AND V58.LISTVAL_ID = :V$CAT_ID
      WHERE L13.OBJ_TYPE_ID = 13 AND L13.PARENT_ID = :V$ORG AND L13.DATE_DEL IS NULL
      ORDER BY L13.DATE_MODIFY DESC
      INTO :V$JOB_ID;

      -- Если ее нет, надо создать заново; количество ставок посчитаем в самом конце
      IF (V$JOB_ID IS NULL) THEN
      BEGIN
        SELECT OBJ_ID FROM OBJECT_ADD(:V$ORG, 13) INTO :V$JOB_ID;
        SELECT 1 FROM VAL_ADD(58, :V$JOB_ID, :V$CAT_ID) INTO :V$ID;
        VAL = 'Создали должность учителя по новому кодификатору, id = '  || V$JOB_ID || ', тип ' || V$CAT_ID;
        SUSPEND;
      END
      SELECT VAL FROM LISTVAL_TEXT(:V$CAT_ID) INTO :V$S;
      SELECT 1 FROM VAL_ADD(66, :V$JOB_ID, :V$S) INTO :V$ID;

      -- Перекинем связь назначения на должность на новую должность
      UPDATE LINKS
      SET PARENT_ID = :V$JOB_ID
      WHERE PARENT_ID = :V$OLD_JOB_ID AND OBJ_ID = :V$JOB_EMP_ID AND DATE_DEL IS NULL;
      VAL = 'Перенос связи на новую должность id = ' || V$JOB_ID || ', ' || ROW_COUNT;
      SUSPEND;

      -- пропишем текущее название старой должности в поле Наименование должности в трудовой книжке, а также ссылку на должность (13)
      SELECT 1 FROM VAL_ADD(3543, :V$JOB_EMP_ID, :V$JOB_NAME) INTO :V$ID;
      SELECT 1 FROM VAL_ADD(69, :V$JOB_EMP_ID, :V$JOB_ID) INTO :V$ID;
    END

    -- Удалим старые должности, оставшиеся пустыми после конвертации
    FOR
      SELECT L13.OBJ_ID, L13.PARENT_ID, V66.VAL
      FROM LINKS L13
      JOIN VALL V58 ON V58.OBJ_ID = L13.OBJ_ID AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0
      JOIN VALS V66 ON V66.OBJ_ID = L13.OBJ_ID AND V66.PARAM_ID = 66 AND V66.IS_DEL = 0
      LEFT JOIN LISTVAL_TEXT(V58.LISTVAL_ID) JB ON 1 = 1
      WHERE L13.OBJ_TYPE_ID = 13 AND L13.PARENT_TYPE_ID IN (2, 211) AND L13.DATE_DEL IS NULL
        AND V58.LISTVAL_ID NOT IN (18501, 18505, 18551)
        AND (
          UPPER(TRIM(V66.VAL)) LIKE '%УЧИТЕЛЬ %' OR
          UPPER(JB.VAL) LIKE '%УЧИТЕЛЬ %' OR
          UPPER(TRIM(V66.VAL)) LIKE '%УЧИТЕЛЬ-%' OR
          UPPER(JB.VAL) LIKE '%УЧИТЕЛЬ-%'
        )
      ORDER BY 1
      INTO :V$JOB_EMP_ID, :V$ORG, :V$JOB_NAME
    DO
    BEGIN
      SELECT CAN_DELETE, ERR_MSG FROM PARAGRAF_CAN_DELETE_OBJECT(:V$JOB_EMP_ID) INTO :V$ID, :V$S;

      IF (V$ID = 1) THEN
      BEGIN
        SELECT DEL_COUNT FROM OBJECT_DEL(:V$ORG, :V$JOB_EMP_ID) INTO :V$ID;
        VAL = 'Старая должность удалена ' || V$JOB_NAME;
        SUSPEND;
      END
      ELSE
      BEGIN
        VAL = 'Невозможно удалить старую должность ' || V$JOB_NAME || ' - ' || V$S;
        SUSPEND;
      END
    END
  END

  -- Заменим должность 'воспитатель такой-то' на 'воспитатель' из справочника. Полное название дожности переносим в название должности в трудовой.
  IF (I$MODE = 'TUTOR' OR I$MODE = 'ALL') THEN
  BEGIN
    FOR
      SELECT L15.OBJ_ID, L15.PARENT_ID, V58.LISTVAL_ID, V66.VAL, LP2.PARENT_ID
      FROM LINKS L15
      JOIN LINKS LP2 ON LP2.OBJ_ID = L15.PARENT_ID AND LP2.PARENT_TYPE_ID IN (2, 211) AND LP2.DATE_DEL IS NULL
      JOIN VALL V58 ON V58.OBJ_ID = L15.PARENT_ID AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0
      LEFT JOIN LISTVAL_TEXT(V58.LISTVAL_ID) JB ON 1 = 1
      JOIN VALS V66 ON V66.OBJ_ID = L15.PARENT_ID AND V66.PARAM_ID = 66 AND V66.IS_DEL = 0
      WHERE L15.OBJ_TYPE_ID = 15 AND L15.PARENT_TYPE_ID = 13 AND L15.DATE_DEL IS NULL
        AND V58.LISTVAL_ID NOT IN (18507, 18546, 17284)
        AND ((UPPER(TRIM(V66.VAL)) LIKE '%ВОСПИТАТЕЛЬ%' AND NOT UPPER(V66.VAL) LIKE '%ЗАМЕСТИТЕЛЬ%') OR
          (UPPER(TRIM(JB.VAL)) LIKE '%ВОСПИТАТЕЛЬ%' AND NOT UPPER(JB.VAL) LIKE '%ЗАМЕСТИТЕЛЬ%'))
      ORDER BY 1
      INTO :V$JOB_EMP_ID, :V$OLD_JOB_ID, :V$CAT_ID, :V$JOB_NAME, :V$ORG
    DO
    BEGIN
      VAL = 'Перенос '  || V$JOB_NAME || ', id = ' || V$JOB_EMP_ID;
      SUSPEND;

      -- Найти должность воспитатель или старший воспитатель
      -- Отдельная история с младшим воспитателем, которая не является педагогической
      IF(UPPER(V$JOB_NAME) LIKE '%СТАРШИЙ%') THEN V$CAT_ID = 18546;
      IF(UPPER(V$JOB_NAME) LIKE '%МЛАДШИЙ%') THEN V$CAT_ID = 17284;
      ELSE V$CAT_ID = 18507; -- просто воспитатель

      V$JOB_ID = NULL;
      SELECT FIRST 1 L13.OBJ_ID
      FROM LINKS L13
      JOIN VALL V58 ON V58.OBJ_ID = L13.OBJ_ID AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0 AND V58.LISTVAL_ID = :V$CAT_ID
      WHERE L13.OBJ_TYPE_ID = 13 AND L13.PARENT_ID = :V$ORG AND L13.DATE_DEL IS NULL
      ORDER BY L13.DATE_MODIFY DESC
      INTO :V$JOB_ID;

      -- Если ее нет, надо создать
      IF (V$JOB_ID IS NULL) THEN
      BEGIN
        SELECT OBJ_ID FROM OBJECT_ADD(:V$ORG, 13) INTO :V$JOB_ID;
        SELECT 1 FROM VAL_ADD(58, :V$JOB_ID, :V$CAT_ID) INTO :V$ID;
        VAL = 'Создали должность воспитателя по новому кодификатору, id = '  || V$JOB_ID || ', тип ' || V$CAT_ID;
        SUSPEND;
      END
      SELECT VAL FROM LISTVAL_TEXT(:V$CAT_ID) INTO :V$S;
      SELECT 1 FROM VAL_ADD(66, :V$JOB_ID, :V$S) INTO :V$ID;

      -- перекинем связь назначения на новую должность
      UPDATE LINKS
      SET PARENT_ID = :V$JOB_ID
      WHERE PARENT_ID = :V$OLD_JOB_ID AND OBJ_ID = :V$JOB_EMP_ID AND DATE_DEL IS NULL;
      VAL = 'Перенос связи на новую должность id = ' || V$JOB_ID || ', ' || ROW_COUNT;
      SUSPEND;

      -- пропишем текущее название старой должности в поле Наименование должности в трудовой книжке, а также ссылку на должность (13)
      SELECT 1 FROM VAL_ADD(3543, :V$JOB_EMP_ID, :V$JOB_NAME) INTO :V$ID;
      SELECT 1 FROM VAL_ADD(69, :V$JOB_EMP_ID, :V$JOB_ID) INTO :V$ID;
    END

    -- Удалим старые должности, оставшиеся пустыми после конвертации
    FOR
      SELECT L13.OBJ_ID, L13.PARENT_ID, V66.VAL
      FROM LINKS L13
      JOIN VALL V58 ON V58.OBJ_ID = L13.OBJ_ID AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0
      LEFT JOIN LISTVAL_TEXT(V58.LISTVAL_ID) JB ON 1 = 1
      JOIN VALS V66 ON V66.OBJ_ID = L13.OBJ_ID AND V66.PARAM_ID = 66 AND V66.IS_DEL = 0
      WHERE L13.OBJ_TYPE_ID = 13 AND L13.PARENT_TYPE_ID IN (2, 211) AND L13.DATE_DEL IS NULL
        AND V58.LISTVAL_ID NOT IN (18507, 18546, 17284)
        AND ((UPPER(TRIM(V66.VAL)) LIKE '%ВОСПИТАТЕЛЬ%' AND NOT UPPER(V66.VAL) LIKE '%ЗАМЕСТИТЕЛЬ%') OR
          (UPPER(TRIM(JB.VAL)) LIKE '%ВОСПИТАТЕЛЬ%' AND NOT UPPER(JB.VAL) LIKE '%ЗАМЕСТИТЕЛЬ%'))
      ORDER BY 1
      INTO :V$JOB_EMP_ID, :V$ORG, :V$JOB_NAME
    DO
    BEGIN
      SELECT CAN_DELETE, ERR_MSG FROM PARAGRAF_CAN_DELETE_OBJECT(:V$JOB_EMP_ID) INTO :V$ID, :V$S;

      IF (V$ID = 1) THEN
      BEGIN
        SELECT DEL_COUNT FROM OBJECT_DEL(:V$ORG, :V$JOB_EMP_ID) INTO :V$ID;
        VAL = 'Старая должность удалена ' || V$JOB_NAME;
        SUSPEND;
      END
      ELSE
      BEGIN
        VAL = 'Невозможно удалить старую должность ' || V$JOB_NAME || ' - ' || V$S;
        SUSPEND;
      END
    END
  END

  -- Заменим должность 'преподаватель такой-то' на 'преподаватель' из справочника. Полное название дожности переносим в название должности в трудовой.
  IF (I$MODE = 'LECT' OR I$MODE = 'ALL') THEN
  BEGIN
    FOR
      SELECT L15.OBJ_ID, L15.PARENT_ID, V58.LISTVAL_ID, V66.VAL, LP2.PARENT_ID
      FROM LINKS L15
      JOIN LINKS LP2 ON LP2.OBJ_ID = L15.PARENT_ID AND LP2.PARENT_TYPE_ID IN (2, 211) AND LP2.DATE_DEL IS NULL
      JOIN VALL V58 ON V58.OBJ_ID = L15.PARENT_ID AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0
      LEFT JOIN LISTVAL_TEXT(V58.LISTVAL_ID) JB ON 1 = 1
      JOIN VALS V66 ON V66.OBJ_ID = L15.PARENT_ID AND V66.PARAM_ID = 66 AND V66.IS_DEL = 0
      WHERE L15.OBJ_TYPE_ID = 15 AND L15.PARENT_TYPE_ID = 13 AND L15.DATE_DEL IS NULL
        AND V58.LISTVAL_ID NOT IN (18502, 18519, 18550, 18520, 18557, 18558)
        AND (
          UPPER(TRIM(V66.VAL)) LIKE '%ПРЕПОДАВАТЕЛЬ %' OR
          UPPER(TRIM(V66.VAL)) LIKE '%ПРЕПОДАВАТЕЛЬ-%' OR
          UPPER(JB.VAL) LIKE '%ПРЕПОДАВАТЕЛЬ %' OR
          UPPER(JB.VAL) LIKE '%ПРЕПОДАВАТЕЛЬ-%'
        )
      ORDER BY 1
      INTO :V$JOB_EMP_ID, :V$OLD_JOB_ID, :V$CAT_ID, :V$JOB_NAME, :V$ORG
    DO
    BEGIN
      VAL = 'Перенос '  || V$JOB_NAME || ', id = ' || V$JOB_EMP_ID;
      SUSPEND;

      -- Найти должность "Преподаватель"
      IF(UPPER(V$JOB_NAME) LIKE '%БЕЗОПАС%') THEN V$CAT_ID = 18519;
      ELSE IF(UPPER(V$JOB_NAME) LIKE '%СТАРШИЙ%ТРЕНЕР%') THEN V$CAT_ID = 18550;
      ELSE IF(UPPER(V$JOB_NAME) LIKE '%ТРЕНЕР%') THEN V$CAT_ID = 18520;
      ELSE IF(UPPER(V$JOB_NAME) LIKE '%СТАРШИЙ%') THEN V$CAT_ID = 18558;
      -- выбор между школьным и СПО
      ELSE IF(EXISTS(
        SELECT FIRST 1 1
        FROM LINKS L7
        JOIN VALL V43 ON V43.OBJ_ID = L7.OBJ_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0 AND V43.LISTVAL_ID = 29  -- СПО
        WHERE L7.PARENT_TYPE_ID IN (2, 211) AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
      ))
      THEN V$CAT_ID = 18557;  -- из группы профессорско-преподавательский состав
      ELSE V$CAT_ID = 18502;  -- из группы педагогические работники

      V$JOB_ID = NULL;
      SELECT FIRST 1 L13.OBJ_ID
      FROM LINKS L13
      JOIN VALL V58 ON V58.OBJ_ID = L13.OBJ_ID AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0 AND V58.LISTVAL_ID = :V$CAT_ID
      WHERE L13.OBJ_TYPE_ID = 13 AND L13.PARENT_ID = :V$ORG AND L13.DATE_DEL IS NULL
      ORDER BY L13.DATE_MODIFY DESC
      INTO :V$JOB_ID;

      -- Если ее нет, надо создать
      IF (V$JOB_ID IS NULL) THEN
      BEGIN
        -- создадим должность
        SELECT OBJ_ID FROM OBJECT_ADD(:V$ORG, 13) INTO :V$JOB_ID;
        SELECT 1 FROM VAL_ADD(58, :V$JOB_ID, :V$CAT_ID) INTO :V$ID;
        VAL = 'Создали должность преподавателя по новому кодификатору, id = '  || V$JOB_ID || ', тип ' || V$CAT_ID;
        SUSPEND;
      END
      SELECT VAL FROM LISTVAL_TEXT(:V$CAT_ID) INTO :V$S;
      SELECT 1 FROM VAL_ADD(66, :V$JOB_ID, :V$S) INTO :V$ID;

      -- перекинем связь назначения на должность на новую должность
      UPDATE LINKS
      SET PARENT_ID = :V$JOB_ID
      WHERE PARENT_ID = :V$OLD_JOB_ID AND OBJ_ID = :V$JOB_EMP_ID AND DATE_DEL IS NULL;
      VAL = 'Перенос связи на новую должность id = ' || V$JOB_ID || ', ' || ROW_COUNT;
      SUSPEND;

      -- пропишем текущее название старой должности в поле Наименование должности в трудовой книжке, а также ссылку на должность (13)
      SELECT 1 FROM VAL_ADD(3543, :V$JOB_EMP_ID, :V$JOB_NAME) INTO :V$ID;
      SELECT 1 FROM VAL_ADD(69, :V$JOB_EMP_ID, :V$JOB_ID) INTO :V$ID;
    END

    -- удалим старые должности, оставшиеся пустыми после конвертации
    FOR
      SELECT L13.OBJ_ID, L13.PARENT_ID, COALESCE(V66.VAL, JB.VAL)
      FROM LINKS L13
      JOIN VALL V58 ON V58.OBJ_ID = L13.OBJ_ID AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0
      LEFT JOIN LISTVAL_TEXT(V58.LISTVAL_ID) JB ON 1 = 1
      JOIN VALS V66 ON V66.OBJ_ID = L13.OBJ_ID AND V66.PARAM_ID = 66 AND V66.IS_DEL = 0
      WHERE L13.OBJ_TYPE_ID = 13 AND L13.PARENT_TYPE_ID IN (2, 211) AND L13.DATE_DEL IS NULL
        AND V58.LISTVAL_ID NOT IN (18502, 18519, 18550, 18520, 18557, 18558)
        AND (
          UPPER(TRIM(V66.VAL)) LIKE '%ПРЕПОДАВАТЕЛЬ %' OR
          UPPER(TRIM(V66.VAL)) LIKE '%ПРЕПОДАВАТЕЛЬ-%' OR
          UPPER(JB.VAL) LIKE '%ПРЕПОДАВАТЕЛЬ %' OR
          UPPER(JB.VAL) LIKE '%ПРЕПОДАВАТЕЛЬ-%'
        )
      ORDER BY 1
      INTO :V$JOB_EMP_ID, :V$ORG, :V$JOB_NAME
    DO
    BEGIN
      SELECT CAN_DELETE, ERR_MSG FROM PARAGRAF_CAN_DELETE_OBJECT(:V$JOB_EMP_ID) INTO :V$ID, :V$S;

      IF (V$ID = 1) THEN
      BEGIN
        SELECT DEL_COUNT FROM OBJECT_DEL(:V$ORG, :V$JOB_EMP_ID) INTO :V$ID;
        VAL = 'Старая должность удалена ' || V$JOB_NAME;
        SUSPEND;
      END
      ELSE
      BEGIN
        VAL = 'Невозможно удалить старую должность ' || V$JOB_NAME || ' - ' || V$S;
        SUSPEND;
      END
    END
  END

  -- Заменим должность 'Заместитель директора по такой-то работе' на 'Заместитель директора' из справочника
  -- Полное название дожности переносим в название должности в трудовой.
  IF (I$MODE = 'DEPUTY' OR I$MODE = 'ALL') THEN
  BEGIN
    FOR
      SELECT L15.OBJ_ID, L15.PARENT_ID, V58.LISTVAL_ID, V66.VAL, LP2.PARENT_ID
      FROM LINKS L15
      JOIN LINKS LP2 ON LP2.OBJ_ID = L15.PARENT_ID AND LP2.PARENT_TYPE_ID = 2 AND LP2.DATE_DEL IS NULL
      JOIN VALL V64 ON V64.OBJ_ID = L15.PARENT_ID AND V64.PARAM_ID = 64 AND V64.IS_DEL = 0 AND V64.LISTVAL_ID = 113 -- руководитель 2-го уровня
      JOIN VALL V58 ON V58.OBJ_ID = L15.PARENT_ID AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0
      LEFT JOIN LISTVAL_TEXT(V58.LISTVAL_ID) JB ON 1 = 1
      JOIN VALS V66 ON V66.OBJ_ID = L15.PARENT_ID AND V66.PARAM_ID = 66 AND V66.IS_DEL = 0
      WHERE L15.OBJ_TYPE_ID = 15 AND L15.PARENT_TYPE_ID = 13 AND L15.DATE_DEL IS NULL
        AND V58.LISTVAL_ID NOT IN (18498, 18534) --'Заместитель руководителя ОУ'
        AND (
          UPPER(TRIM(V66.VAL)) LIKE '%ЗАМЕСТИТЕЛЬ ДИРЕКТОРА%' OR
          UPPER(TRIM(V66.VAL)) LIKE '%ЗАМЕСТИТЕЛЬ ЗАВЕДУЮЩЕГО%' OR
          UPPER(TRIM(V66.VAL)) LIKE '%ЗАМЕСТИТЕЛЬ РУКОВОДИТЕЛЯ%' OR
          UPPER(JB.VAL) LIKE '%ЗАМЕСТИТЕЛЬ ДИРЕКТОРА%' OR
          UPPER(JB.VAL) LIKE '%ЗАМЕСТИТЕЛЬ ЗАВЕДУЮЩЕГО%' OR
          UPPER(JB.VAL) LIKE '%ЗАМЕСТИТЕЛЬ РУКОВОДИТЕЛЯ%'
        )
      ORDER BY 1
      INTO :V$JOB_EMP_ID, :V$OLD_JOB_ID, :V$CAT_ID, :V$JOB_NAME, :V$ORG
    DO
    BEGIN
      VAL = 'Перенос '  || V$JOB_NAME || ', id = ' || V$JOB_EMP_ID;
      SUSPEND;

      -- найти должность "Заместитель" - либо замрука подразделения, либо директора
      IF(V$CAT_ID = 13136) THEN V$CAT_ID = 18534; ELSE V$CAT_ID = 18498;

      V$JOB_ID = NULL;
      SELECT FIRST 1 L13.OBJ_ID
      FROM LINKS L13
      JOIN VALL V58 ON V58.OBJ_ID = L13.OBJ_ID AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0 AND V58.LISTVAL_ID = :V$CAT_ID
      WHERE L13.OBJ_TYPE_ID = 13 AND L13.PARENT_ID = :V$ORG AND L13.DATE_DEL IS NULL
      ORDER BY L13.DATE_MODIFY DESC
      INTO :V$JOB_ID;

      -- Если ее нет, надо создать
      IF (V$JOB_ID IS NULL) THEN
      BEGIN
        -- создадим должность
        SELECT OBJ_ID FROM OBJECT_ADD(:V$ORG, 13) INTO :V$JOB_ID;
        SELECT 1 FROM VAL_ADD(58, :V$JOB_ID, :V$CAT_ID) INTO :V$ID;
        VAL = 'Создали должность руководителя 2-го уровня по новому кодификатору, id = '  || V$JOB_ID || ', тип ' || V$CAT_ID;
        SUSPEND;
      END
      SELECT VAL FROM LISTVAL_TEXT(:V$CAT_ID) INTO :V$S;
      SELECT 1 FROM VAL_ADD(66, :V$JOB_ID, :V$S) INTO :V$ID;

      -- перекинем связь назначения на должность на новую должность
      UPDATE LINKS
      SET PARENT_ID = :V$JOB_ID
      WHERE PARENT_ID = :V$OLD_JOB_ID AND OBJ_ID = :V$JOB_EMP_ID AND DATE_DEL IS NULL;
      VAL = 'Перенос связи на новую должность id = ' || V$JOB_ID || ', ' || ROW_COUNT;
      SUSPEND;

      -- пропишем текущее название старой должности в поле Наименование должности в трудовой книжке, а также ссылку на должность (13)
      SELECT 1 FROM VAL_ADD(3543, :V$JOB_EMP_ID, :V$JOB_NAME) INTO :V$ID;
      SELECT 1 FROM VAL_ADD(69, :V$JOB_EMP_ID, :V$JOB_ID) INTO :V$ID;
    END

    -- удалим старые должности, оставшиеся пустыми после конвертации
    FOR
      SELECT L13.OBJ_ID, L13.PARENT_ID, COALESCE(V66.VAL, JB.VAL)
      FROM LINKS L13
      JOIN VALL V64 ON V64.OBJ_ID = L13.OBJ_ID AND V64.PARAM_ID = 64 AND V64.IS_DEL = 0 AND V64.LISTVAL_ID = 113 -- руководитель 2-го уровня
      JOIN VALL V58 ON V58.OBJ_ID = L13.OBJ_ID AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0
      LEFT JOIN LISTVAL_TEXT(V58.LISTVAL_ID) JB ON 1 = 1
      JOIN VALS V66 ON V66.OBJ_ID = L13.OBJ_ID AND V66.PARAM_ID = 66 AND V66.IS_DEL = 0
      WHERE L13.OBJ_TYPE_ID = 13 AND L13.PARENT_TYPE_ID IN (2, 211) AND L13.DATE_DEL IS NULL
        AND V58.LISTVAL_ID NOT IN (18498, 18534)
        AND (
          UPPER(TRIM(V66.VAL)) LIKE '%ЗАМЕСТИТЕЛЬ ДИРЕКТОРА%' OR
          UPPER(TRIM(V66.VAL)) LIKE '%ЗАМЕСТИТЕЛЬ ЗАВЕДУЮЩЕГО%' OR
          UPPER(TRIM(V66.VAL)) LIKE '%ЗАМЕСТИТЕЛЬ РУКОВОДИТЕЛЯ%' OR
          UPPER(JB.VAL) LIKE '%ЗАМЕСТИТЕЛЬ ДИРЕКТОРА%' OR
          UPPER(JB.VAL) LIKE '%ЗАМЕСТИТЕЛЬ ЗАВЕДУЮЩЕГО%' OR
          UPPER(JB.VAL) LIKE '%ЗАМЕСТИТЕЛЬ РУКОВОДИТЕЛЯ%'
        )
      ORDER BY 1
      INTO :V$JOB_EMP_ID, :V$ORG, :V$JOB_NAME
    DO
    BEGIN
      SELECT CAN_DELETE, ERR_MSG FROM PARAGRAF_CAN_DELETE_OBJECT(:V$JOB_EMP_ID) INTO :V$ID, :V$S;

      IF (V$ID = 1) THEN
      BEGIN
        SELECT DEL_COUNT FROM OBJECT_DEL(:V$ORG, :V$JOB_EMP_ID) INTO :V$ID;
        VAL = 'Старая должность удалена ' || V$JOB_NAME;
        SUSPEND;
      END
      ELSE
      BEGIN
        VAL = 'Невозможно удалить старую должность ' || V$JOB_NAME || ' - ' || V$S;
        SUSPEND;
      END
    END
  END

  -- Пересчет ставок по факту (только те что поменялись). Пусть сами потом проверяют что там правильно
  FOR
    SELECT L13.PARENT_ID, L13.OBJ_ID, V58.LISTVAL_ID
    FROM LINKS L13
    JOIN VALL V58 ON V58.OBJ_ID = L13.OBJ_ID AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0
      AND V58.LISTVAL_ID IN (18501, 18505, 18551, 18507, 18546, 18502, 18519, 18550, 18520, 18557, 18558, 18498, 18534, 17284)
    WHERE L13.PARENT_TYPE_ID IN (2, 211) AND L13.OBJ_TYPE_ID = 13 AND L13.DATE_DEL IS NULL
      AND EXISTS(SELECT FIRST 1 1 FROM LINKS L15 WHERE L15.PARENT_ID = L13.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_MODIFY >= :DT)
    INTO :V$ORG, :V$JOB_ID, :V$CAT_ID
  DO
  BEGIN
    V$F = 0;
    SELECT COALESCE(SUM(V71.VAL), 0)
    FROM LINKS L15
    JOIN VALF V71 ON V71.OBJ_ID = L15.OBJ_ID AND V71.PARAM_ID = 71 AND V71.IS_DEL = 0 AND V71.VAL > 0
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
    WHERE L15.OBJ_TYPE_ID = 15 AND L15.PARENT_ID = :V$JOB_ID AND L15.DATE_DEL IS NULL AND V74.VAL IS NULL
    INTO :V$F;

    SELECT 1 FROM VAL_ADD(62, :V$JOB_ID, :V$F) INTO :V$ID;
    EXECUTE PROCEDURE CALC_JOB_OCCUPIED(:V$JOB_ID);
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE JOB_FUNCTION_TO_CODE (
    JF BIGINT,
    JNAME VARCHAR(400) = NULL)
RETURNS (
    CODE VARCHAR(20))
AS
begin

    -- Смотреть справочник JobPosition.xml
    -- Старые коды должностей заменены на новые справочник 369, учительские должности идут текстом
    JNAME = UPPER(JNAME);

    -- Начальники 1 уровня
    IF(JF = 64 OR JF = 18497) THEN CODE = '01.01';
    IF(JF = 65 OR JF = 18532) THEN CODE = '01.02';
    IF(JF = 3399 OR JF = 18531) THEN CODE = '01.03';
    IF(JF = 66 OR JF = 18530) THEN CODE = '01.04';
    IF(JF = 74) THEN CODE = '01.05';
    IF(JF = 3301) THEN CODE = '01.06';

    -- Начальники 2 уровня
    IF(JF = 80 OR JF = 18498) THEN CODE = '02.01';
    IF(JF = 142) THEN CODE = '02.02';
    IF(JF = 67) THEN CODE = '02.03';
    IF(JF = 141) THEN CODE = '02.04';
    IF(JF = 68) THEN CODE = '02.05';
    IF(JF = 69 OR JNAME LIKE '%ГЛАВНЫЙ%БУХГАЛТЕР%') THEN CODE = '02.06';
    IF(JF = 83) THEN CODE = '02.07';
    IF(JF = 84) THEN CODE = '02.08';
    IF(JF = 85) THEN CODE = '02.09';
    IF(JF = 86) THEN CODE = '02.10';
    IF(JF = 87) THEN CODE = '02.11';
    IF(JF = 88) THEN CODE = '02.12';
    IF(JF = 5387) THEN CODE = '02.13';
    IF(JF = 89) THEN CODE = '02.14';
    IF(JF = 5386) THEN CODE = '02.15';
    IF(JF = 95) THEN CODE = '02.16';
    IF(JF = 103) THEN CODE = '02.17';
    IF(JF = 123) THEN CODE = '02.18';
    IF(JF = 3300) THEN CODE = '02.19';
    IF(JF = 3299) THEN CODE = '02.20';
    IF(JF = 127) THEN CODE = '02.21';
    IF(JF = 11095) THEN CODE = '02.22';
    -- Советник директора по воспитанию -> Советник директора ?
    IF(JF = 14209 OR JNAME LIKE '%СОВЕТНИК%') THEN CODE = '02.23';

    -- Начальники третьего уровня
    IF(JF = 71) THEN CODE = '03.01';
    IF(JF = 72) THEN CODE = '03.02';
    IF(JF = 73 OR JF = 18499) THEN CODE = '03.03';
    IF(JF = 75) THEN CODE = '03.04';
    IF(JF = 76) THEN CODE = '03.05';
    IF(JF = 77) THEN CODE = '03.06';
    IF(JF = 124) THEN CODE = '03.07';
    IF(JF = 1312) THEN CODE = '03.08';
    IF(JF = 78) THEN CODE = '03.09';
    IF(JF = 79) THEN CODE = '03.10';
    IF(JF = 81) THEN CODE = '03.11';
    IF(JF = 1322) THEN CODE = '03.12';
    IF(JF = 82) THEN CODE = '03.13';
    IF(JF = 90) THEN CODE = '03.14';
    IF(JF = 91) THEN CODE = '03.15';
    IF(JF = 92) THEN CODE = '03.16';
    IF(JF = 93) THEN CODE = '03.17';
    IF(JF = 1271) THEN CODE = '03.18';
    IF(JF = 1253) THEN CODE = '03.19';
    IF(JF = 1254) THEN CODE = '03.20';
    IF(JF = 94) THEN CODE = '03.21';
    IF(JF = 96) THEN CODE = '03.22';
    IF(JF = 11096) THEN CODE = '03.23';

    -- Учителя
    IF(JF = 99 OR JNAME LIKE '%АНГЛИЙСКОГО%') THEN CODE = '04.01';
    IF(JF = 100 OR JNAME LIKE '%БИОЛОГИИ%') THEN CODE = '04.02';
    IF(JF = 101 OR JNAME LIKE '%ГЕОГРАФИИ%') THEN CODE = '04.03';
    IF(JF = 102 OR JNAME LIKE '%ИНФОРМАТИКИ%') THEN CODE = '04.04';
    IF(JF = 104 OR JNAME LIKE '%ИСТОРИИ%') THEN CODE = '04.05';
    IF(JF = 105 OR JNAME LIKE '%МАТЕМАТИКИ%') THEN CODE = '04.06';
    IF(JF = 106 OR JNAME LIKE '%МУЗЫКИ%') THEN CODE = '04.07';
    IF(JF = 107 OR JNAME LIKE '%ХУДОЖЕСТВЕННОЙ КУЛЬТУРЫ%') THEN CODE = '04.08';
    IF(JF = 108 OR JNAME LIKE '%НАЧАЛЬНЫХ%') THEN CODE = '04.09';
    IF(JF = 109 OR JNAME LIKE '%НЕМЕЦКОГО%') THEN CODE = '04.10';
    IF(JF = 110 OR JNAME LIKE '%%ОБЖ%' OR JNAME LIKE '%ОБЗР%' OR JNAME LIKE '%ЗАЩИТЫ%') THEN CODE = '04.11';
    IF(JF = 111 OR JNAME LIKE '%ИЗОБРАЗИТЕЛЬНОГО%') THEN CODE = '04.12';
    IF(JF = 112 OR JNAME LIKE '%РУССКОГО%') THEN CODE = '04.13';
    IF(JF = 114 OR JNAME LIKE '%ТРУДА%') THEN CODE = '04.14';
    IF(JF = 115 OR JNAME LIKE '%ФИЗИКИ%') THEN CODE = '04.15';
    IF(JF = 116 OR JNAME LIKE '%ФИЗИЧЕСКОЙ КУЛЬТУРЫ%') THEN CODE = '04.16';
    IF(JF = 117 OR JNAME LIKE '%ФРАНЦУЗСКОГО%') THEN CODE = '04.17';
    IF(JF = 118 OR JNAME LIKE '%ХИМИИ%') THEN CODE = '04.18';
    IF(JF = 119 OR JF = 18551) THEN CODE = '04.19';
    IF(JF = 120 OR JF = 18505) THEN CODE = '04.20';
    IF(JF = 122 OR JF = 18502) THEN CODE = '04.21';
    IF(JF = 1260 OR JNAME LIKE '%РУССКОГО%ЛИТЕРАТУРЫ%') THEN CODE = '04.22';
    IF(JF = 1264 OR JNAME LIKE '%ИНОСТРАННОГО%') THEN CODE = '04.23';
    IF(JF = 1268 OR JNAME LIKE '%ОБЩЕСТВОЗНАНИЯ%') THEN CODE = '04.24';
    IF(JF = 1273 OR JNAME LIKE '%ЭКОНОМИКИ%') THEN CODE = '04.25';
    IF(JF = 1278 OR JNAME LIKE '%ПРАВА%') THEN CODE = '04.26';
    IF(JF = 1282 OR JNAME LIKE '%САНКТ-ПЕТЕРБУРГА%') THEN CODE = '04.27';
    IF(JF = 1283 OR JNAME LIKE '%КРАЕВЕДЕНИЯ%') THEN CODE = '04.28';
    IF(JF = 1285 OR JNAME LIKE '%ЕСТЕСТВОЗНАНИЯ%') THEN CODE = '04.29';
    IF(JF = 1286 OR JNAME LIKE '%ТЕХНОЛОГИИ%') THEN CODE = '04.30';
    IF(JF = 1289 OR JNAME LIKE '%ПРИРОДОВЕДЕНИЯ%') THEN CODE = '04.31';
    IF(JF = 3148 OR JNAME LIKE '%ЧЕРЧЕНИЯ%') THEN CODE = '04.32';

    IF(JF = 128 OR JF = 18546) THEN CODE = '05.01';
    IF(JF = 126) THEN CODE = '05.02';
    IF(JF = 148) THEN CODE = '05.03';

    IF(JF = 130 OR JF = 18521) THEN CODE = '06.01';

    IF(JF = 121 OR JF = 18519) THEN CODE = '07.01';
    IF(JF = 151 OR JF = 18518) THEN CODE = '07.02';
    IF(JF = 150 OR JF = 18515) THEN CODE = '07.03';
    IF(JF = 152 OR JF = 18517) THEN CODE = '07.04';
    IF(JF = 132 OR JF = 18513) THEN CODE = '07.05';
    IF(JF = 133 OR JF = 18516) THEN CODE = '07.06';
    IF(JF = 140 OR JF = 18512) THEN CODE = '07.07';
    IF(JF = 143 OR JF = 18511) THEN CODE = '07.08';
    IF(JF = 144 OR JF = 18503) THEN CODE = '07.09';
    IF(JF = 145 OR JF = 18506) THEN CODE = '07.10';
    IF(JF = 146) THEN CODE = '07.11';
    IF(JF = 147) THEN CODE = '07.12'; -- руководитель кружка
    IF(JF = 149 OR JF = 18514) THEN CODE = '07.13';
    IF(JF = 1251 OR JF = 18504) THEN CODE = '07.14';
    IF(JF = 1252 OR JF = 18510) THEN CODE = '07.15';
    IF(JF = 1255 OR JF = 18548) THEN CODE = '07.16';
    IF(JF = 1256 OR JF = 18520) THEN CODE = '07.17';
    IF(JF = 1291 OR JF = 18508) THEN CODE = '07.18';
    IF(JF = 1293) THEN CODE = '07.19';
    IF(JF = 1295) THEN CODE = '07.20';
    IF(JF = 12832 OR JF = 18509) THEN CODE = '07.21';

    IF(JF = 1258 OR JNAME = 'АДМИНИСТРАТОР') THEN CODE = '08.01';
    IF(JF = 1259 OR JNAME = 'АККОМПАНИАТОР') THEN CODE = '08.02';
    IF(JF = 3242 OR JNAME = 'АНАЛИТИК') THEN CODE = '08.03';
    IF(JF = 1261 OR JNAME = 'БАЛЕТМЕЙСТЕР') THEN CODE = '08.04';
    IF(JF = 1262 OR JNAME LIKE '%БИБЛИОТЕКАРЬ%') THEN CODE = '08.05';
    IF(JF = 1263 OR JNAME = 'БИБЛИОГРАФ') THEN CODE = '08.06';
    IF(JF = 1265 OR JNAME = 'БУХГАЛТЕР') THEN CODE = '08.07';
    IF(JF = 1266 OR JNAME = 'ВИДЕОИНЖЕНЕР') THEN CODE = '08.08';
    IF(JF = 1267 OR JNAME = 'ВРАЧ') THEN CODE = '08.09';
    IF(JF = 1269 OR JNAME = 'ДЕФЕКТОЛОГ') THEN CODE = '08.10';
    IF(JF = 1270 OR JNAME = 'ДИРИЖЕР') THEN CODE = '08.11';
    IF(JF = 3145 OR JNAME = 'ДОКУМЕНТОВЕД') THEN CODE = '08.12';
    IF(JF = 1272 OR JNAME = 'ЗАВЕДУЩИЙ АРХИВОМ') THEN CODE = '08.13';
    IF(JF = 1274 OR JNAME = 'ЗВУКОРЕЖИССЕР') THEN CODE = '08.14';
    IF(JF = 1275 OR JNAME = 'ЗВУКООПЕРАТОР') THEN CODE = '08.15';
    IF(JF = 1276 OR JNAME = 'ИНСТРУКТОР') THEN CODE = '08.16';
    IF(JF = 1277 OR JNAME LIKE '%ИНЖЕНЕР%') THEN CODE = '08.17';
    IF(JF = 1279) THEN CODE = '08.18';
    IF(JF = 1280) THEN CODE = '08.19';
    IF(JF = 1281 OR JF = 18544) THEN CODE = '08.20';
    IF(JF = 1284 OR JNAME = 'МЕДИЦИНСКАЯ СЕСТРА') THEN CODE = '08.21';
    IF(JF = 1287 OR JNAME LIKE '%МЕХАНИК%') THEN CODE = '08.22';
    IF(JF = 1288) THEN CODE = '08.23';
    IF(JF = 1290) THEN CODE = '08.24';
    IF(JF = 1292 OR JNAME LIKE '%ПРОГРАММИСТ%') THEN CODE = '08.25';
    IF(JF = 1294 OR JNAME LIKE 'ПСИХОЛОГ%') THEN CODE = '08.26';
    IF(JF = 1296) THEN CODE = '08.27';
    IF(JF = 1297 OR JNAME LIKE '%КАДРАМ%') THEN CODE = '08.28';
    IF(JF = 1298) THEN CODE = '08.29';
    IF(JF = 1299 OR JNAME LIKE '%ТРЕНЕР%') THEN CODE = '08.30';
    IF(JF = 1309) THEN CODE = '08.31';
    IF(JF = 1300 OR JNAME = 'ХОРЕОГРАФ') THEN CODE = '08.32';
    IF(JF = 1301 OR JNAME = 'ХУДОЖНИК') THEN CODE = '08.33';
    IF(JF = 1302 OR JNAME = 'ХУДОЖЕСТВЕННЫЙ РУКОВОДИТЕЛЬ') THEN CODE = '08.34';
    IF(JF = 1303 OR JNAME = 'ЭКОНОМИСТ') THEN CODE = '08.35';
    IF(JF = 1304) THEN CODE = '08.36';
    IF(JF = 1305) THEN CODE = '08.37';
    IF(JF = 1306) THEN CODE = '08.38';
    IF(JF = 1307) THEN CODE = '08.39';
    IF(JF = 1308 OR JNAME LIKE '%ЮРИСТ%') THEN CODE = '08.40';
    IF(JF = 11097 OR JNAME LIKE 'СПЕЦИАЛИСТ ПО СОЦ%') THEN CODE = '08.41';
    IF(JF = 12773) THEN CODE = '08.42';
    IF(JF = 12886) THEN CODE = '08.43';

    IF(JF = 1314 OR JNAME = 'ДЕЛОПРОИЗВОДИТЕЛЬ') THEN CODE = '09.01';
    IF(JF = 1315) THEN CODE = '09.02';
    IF(JF = 1316) THEN CODE = '09.03';
    IF(JF = 1317 OR JNAME = 'ЗАВЕДУЮЩИЙ КАНЦЕЛЯРИЕЙ') THEN CODE = '09.04';
    IF(JF = 1318 OR JNAME = 'ЗАВЕДУЮЩИЙ ХОЗЯЙСТВОМ') THEN CODE = '09.05';
    IF(JF = 1319) THEN CODE = '09.06';
    IF(JF = 3302 OR JNAME LIKE 'СЕКРЕТАРЬ%') THEN CODE = '09.07';
    IF(JF = 1320) THEN CODE = '09.08';
    IF(JF = 1321) THEN CODE = '09.09';
    IF(JF = 1311) THEN CODE = '09.10';
    IF(JF = 1328) THEN CODE = '09.11';
    IF(JF = 1335) THEN CODE = '09.12';
    IF(JF = 3035) THEN CODE = '09.13';

    IF(JF = 1324 OR JNAME = 'ВАХТЕР') THEN CODE = '10.01';
    IF(JF = 1325 OR JNAME LIKE 'ВОДИТЕЛЬ%') THEN CODE = '10.02';
    IF(JF = 1326 OR JNAME = 'ГАРДЕРОБЩИК') THEN CODE = '10.03';
    IF(JF = 1327 OR JNAME = 'ДВОРНИК') THEN CODE = '10.04';
    IF(JF = 1330 OR JNAME = 'КАСТЕЛЯНША') THEN CODE = '10.05';
    IF(JF = 1329 OR JNAME = 'КЛАДОВЩИК') THEN CODE = '10.06';
    IF(JF = 11098 OR JNAME = 'КИНОМЕХАНИК') THEN CODE = '10.07';
    IF(JF = 1331) THEN CODE = '10.10';
    IF(JF = 1332) THEN CODE = '10.09';
    IF(JF = 1333) THEN CODE = '10.10';
    IF(JF = 11099) THEN CODE = '10.11';
    IF(JF = 1334 OR JNAME = 'ПОВАР') THEN CODE = '10.12';
    IF(JF = 1336) THEN CODE = '10.13';
    IF(JF = 1337) THEN CODE = '10.14';
    IF(JF = 1338 OR JNAME = 'СТОРОЖ') THEN CODE = '10.15';
    IF(JF = 1339) THEN CODE = '10.16';
    IF(JF = 1340) THEN CODE = '10.17';
    IF(JF = 1341) THEN CODE = '10.18';
    IF(JF = 3153 OR JNAME = 'РАБОЧИЙ') THEN CODE = '10.19';

    -- IF(CODE IS NULL) THEN EXCEPTION 'Неизвестная должность';

    SUSPEND;
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE JOB_LIST_ADD (
    I$OBJ_ID BIGINT,
    I$STATUS_ID BIGINT NOT NULL,
    I$SR_NUMBER VARCHAR(400),
    I$SR_DATE DATE,
    I$DATE_FROM DATE,
    I$DATE_TO DATE,
    I$ORDER_NUMBER VARCHAR(400),
    I$ORDER_DATE DATE,
    I$DIR_FIO VARCHAR(1000),
    I$GB_FIO VARCHAR(1000),
    I$USER_ID VARCHAR(40))
RETURNS (
    OBJ_ID BIGINT)
AS
DECLARE VARIABLE V$FOLDER_ID BIGINT;
DECLARE VARIABLE T INTEGER;
begin

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  SELECT FIRST 1 L508.OBJ_ID
  FROM LINKS L2
  JOIN LINKS L508 ON L508.PARENT_ID = L2.OBJ_ID AND L508.OBJ_TYPE_ID = 508 AND L508.DATE_DEL IS NULL
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$FOLDER_ID;

  IF(V$FOLDER_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не найден каталог штатных расписаний';

  IF(I$DATE_FROM > I$DATE_TO) THEN EXCEPTION DATA_ERROR 'Неверный порядок дат начала и конца';
  IF(I$SR_DATE > I$DATE_FROM) THEN EXCEPTION DATA_ERROR 'Дата создания не может быть позже даты начала действия';
  IF(I$SR_DATE > I$ORDER_DATE) THEN EXCEPTION DATA_ERROR 'Дата создания не может быть позже даты приказа';

  IF(I$OBJ_ID IS NULL) THEN
  BEGIN
    SELECT OBJ_ID FROM OBJECT_ADD(:V$FOLDER_ID, 505, NULL, NULL, :I$USER_ID) INTO :OBJ_ID;
  END
  ELSE
  BEGIN
    SELECT FIRST 1 L505.OBJ_ID
    FROM LINKS L505
    WHERE L505.PARENT_ID = :V$FOLDER_ID AND L505.OBJ_TYPE_ID = 505 AND L505.OBJ_ID = :I$OBJ_ID AND L505.DATE_DEL IS NULL
    INTO :OBJ_ID;

    IF(OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Расписание не найдено или было удалено';
  END

  -- Если статус не проект, а новый = проект, то сразу меняем
  -- SELECT 1 FROM VAL_ADD(3490, :OBJ_ID, :I$STATUS_ID) INTO :T;

  SELECT 1 FROM VAL_ADD(3506, :OBJ_ID, TRIM(:I$SR_NUMBER)) INTO :T;
  SELECT 1 FROM VAL_ADD(3507, :OBJ_ID, :I$SR_DATE) INTO :T;
  SELECT 1 FROM VAL_ADD(3487, :OBJ_ID, :I$DATE_FROM) INTO :T;
  SELECT 1 FROM VAL_ADD(3489, :OBJ_ID, :I$DATE_TO) INTO :T;
  SELECT 1 FROM VAL_ADD(3504, :OBJ_ID, TRIM(:I$ORDER_NUMBER)) INTO :T;
  SELECT 1 FROM VAL_ADD(3505, :OBJ_ID, :I$ORDER_DATE) INTO :T;
  SELECT 1 FROM VAL_ADD(3508, :OBJ_ID, TRIM(:I$DIR_FIO)) INTO :T;
  SELECT 1 FROM VAL_ADD(3509, :OBJ_ID, TRIM(:I$GB_FIO)) INTO :T;

  -- Статус корректируем в конце
  SELECT 1 FROM VAL_ADD(3490, :OBJ_ID, :I$STATUS_ID) INTO :T;

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE JOB_LIST_COPY (
    I$OBJ_ID BIGINT NOT NULL,
    I$USER_ID VARCHAR(100))
RETURNS (
    OBJ_ID BIGINT,
    OBJ_CAPTION VARCHAR(1000))
AS
DECLARE VARIABLE V$PARENT_ID BIGINT;
DECLARE VARIABLE V$I BIGINT;
DECLARE VARIABLE V$ID BIGINT;
begin
  --Redmine #1172
  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;
  --nnn проверка уровня доступа ?

  -- найдем ШР и родителя
  SELECT FIRST 1 L505.OBJ_ID, L505.PARENT_ID
  FROM LINKS L505
  WHERE L505.OBJ_ID = :I$OBJ_ID AND L505.PARENT_TYPE_ID = 508 AND L505.DATE_DEL IS NULL
  INTO :V$I, :V$PARENT_ID;

  IF (V$I IS NULL) THEN EXCEPTION DATA_ERROR 'Не найдено штатное расписание, которое необходимо скопировать, id = ' || I$OBJ_ID || ')';

  -- копируем ШР
  SELECT OBJ_ID, CAPTION FROM OBJECT_ADD(:V$PARENT_ID, 505, NULL, NULL, :I$USER_ID) INTO :OBJ_ID, :OBJ_CAPTION;
  SELECT 1 FROM VAL_ADD(3490, :OBJ_ID, 11716, :I$USER_ID) INTO :V$I; -- задаем статус ШР = проект

  -- копируем элементы ШР
  FOR
    SELECT L506.OBJ_ID
    FROM LINKS L506
    WHERE L506.OBJ_TYPE_ID = 506 AND L506.PARENT_ID = :I$OBJ_ID AND L506.DATE_DEL IS NULL
    ORDER BY L506.COST
    INTO :V$ID
    --nnn Тут нужно будет еще восстановить связи с должностями, чтобы фиксировать преемственность или создание новых - это на паузе
  DO
  BEGIN
    SELECT 1 FROM OBJECT_COPY(:OBJ_ID, :V$ID, NULL, NULL, NULL, :I$USER_ID) INTO :V$I;
  END

  SUSPEND;
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE JOB_LIST_CURRENT RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$UNIT_ID BIGINT;
DECLARE VARIABLE V$UNIT_NAME VARCHAR(1000);
DECLARE VARIABLE V$JOB_ID BIGINT;
DECLARE VARIABLE V$POS_ID BIGINT;
DECLARE VARIABLE V$POS_NAME VARCHAR(1000);
DECLARE VARIABLE V$FULL_NAME VARCHAR(1000);
DECLARE VARIABLE V$F FLOAT;
DECLARE VARIABLE V$T BIGINT;
DECLARE VARIABLE V$HAS2 SMALLINT;
DECLARE VARIABLE V$TEACHERS SMALLINT;
DECLARE VARIABLE V$POS_GROUP BIGINT;
begin

  -- Выдаем в порядке следования подразделений
  V$HAS2 = 0;
  TAG_NAME = 'items::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L2.OBJ_ID, L2.OBJ_TYPE_ID, C.VAL
    FROM LINKS L2
    JOIN VALS C ON C.OBJ_ID = L2.OBJ_ID AND C.PARAM_ID = 999 AND C.IS_DEL = 0
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    UNION
    SELECT L211.OBJ_ID, L211.OBJ_TYPE_ID, C.VAL
    FROM LINKS L2
    JOIN LINKS L211 ON L211.PARENT_ID = L2.OBJ_ID AND L211.OBJ_TYPE_ID = 211 AND L211.DATE_DEL IS NULL
    JOIN VALS C ON C.OBJ_ID = L211.OBJ_ID AND C.PARAM_ID = 1791 AND C.IS_DEL = 0
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    ORDER BY 2, 3
    INTO :V$UNIT_ID, :V$T, :V$UNIT_NAME
  DO
  BEGIN
    IF(V$T = 2) THEN V$HAS2 = 1;
    V$TEACHERS = 0;
    -- Старые школьные учительские должности выдаем одной суммарной строкой
    FOR
      SELECT L13.OBJ_ID, V58.LISTVAL_ID, C58.VAL, V66.VAL, V62.VAL, LV58.PARENT_ID
      FROM LINKS L13
      LEFT JOIN VALL V58 ON V58.OBJ_ID = L13.OBJ_ID AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0
      LEFT JOIN LISTVALS LV58 ON LV58.LISTVAL_ID = V58.LISTVAL_ID
      LEFT JOIN LISTVAL_TEXT(V58.LISTVAL_ID) C58 ON 1 = 1
      LEFT JOIN VALS V66 ON V66.OBJ_ID = L13.OBJ_ID AND V66.PARAM_ID = 66 AND V66.IS_DEL = 0
      JOIN VALF V62 ON V62.OBJ_ID = L13.OBJ_ID AND V62.PARAM_ID = 62 AND V62.IS_DEL = 0
      WHERE L13.PARENT_ID = :V$UNIT_ID AND L13.OBJ_TYPE_ID = 13 AND L13.DATE_DEL IS NULL AND V62.VAL > 0
      ORDER BY 4
      INTO :V$JOB_ID, :V$POS_ID, :V$POS_NAME, :V$FULL_NAME, :V$F, :V$POS_GROUP
    DO
    BEGIN
      IF((V$TEACHERS = 0 AND V$POS_GROUP = 98 AND V$POS_ID <> 122) OR COALESCE(V$POS_GROUP, 0) <> 98) THEN
      BEGIN
        IF(V$POS_GROUP = 98) THEN
        BEGIN
          V$POS_ID = 18501;
          V$POS_NAME = 'Учитель';
          V$FULL_NAME = 'Учитель';
          SELECT SUM(V62.VAL)
          FROM LINKS L13
          JOIN VALL V58 ON V58.OBJ_ID = L13.OBJ_ID AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0
          JOIN LISTVALS LV58 ON LV58.LISTVAL_ID = V58.LISTVAL_ID AND LV58.PARENT_ID = 98 AND LV58.LISTVAL_ID <> 122
          JOIN VALF V62 ON V62.OBJ_ID = L13.OBJ_ID AND V62.PARAM_ID = 62 AND V62.IS_DEL = 0
          WHERE L13.PARENT_ID = :V$UNIT_ID AND L13.OBJ_TYPE_ID = 13 AND L13.DATE_DEL IS NULL AND V62.VAL > 0
          INTO :V$F;
        END

        TAG_NAME = 'items:r';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'items:r:id';
        VAL = V$JOB_ID;
        SUSPEND;
        -- Подразделение
        TAG_NAME = 'items:r:unit_id';
        VAL = V$UNIT_ID;
        SUSPEND;
        TAG_NAME = 'items:r:unit_name';
        VAL = V$UNIT_NAME;
        SUSPEND;
        -- Группа должностей - пытаемся найти по текущему штатному расписанию
        TAG_NAME = 'items:r:group_id';
        VAL = NULL;
        SELECT FIRST 1 V3498.VAL
        FROM LINKS L2
        JOIN LINKS L508 ON L508.PARENT_ID = L2.OBJ_ID AND L508.OBJ_TYPE_ID = 508 AND L508.DATE_DEL IS NULL
        JOIN LINKS L505 ON L505.PARENT_ID = L508.OBJ_ID AND L505.OBJ_TYPE_ID = 505 AND L505.DATE_DEL IS NULL
        JOIN VALD V3507 ON V3507.OBJ_ID = L505.OBJ_ID AND V3507.PARAM_ID = 3507 AND V3507.IS_DEL = 0
        JOIN LINKS L506 ON L506.PARENT_ID = L505.OBJ_ID AND L506.OBJ_TYPE_ID = 506 AND L506.DATE_DEL IS NULL
        JOIN VALR V3491 ON V3491.OBJ_ID = L506.OBJ_ID AND V3491.PARAM_ID = 3491 AND V3491.IS_DEL = 0 AND V3491.VAL = :V$UNIT_ID
        JOIN VALS V3494 ON V3494.OBJ_ID = L506.OBJ_ID AND V3494.PARAM_ID = 3494 AND V3494.IS_DEL = 0 AND V3494.SVAL = :V$POS_NAME
        LEFT JOIN VALL V3492 ON V3492.OBJ_ID = L506.OBJ_ID AND V3492.PARAM_ID = 3492 AND V3492.IS_DEL = 0
        LEFT JOIN VALR V3498 ON V3498.OBJ_ID = L506.OBJ_ID AND V3498.PARAM_ID = 3498 AND V3498.IS_DEL = 0
        WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
          AND (V3492.LISTVAL_ID = :V$POS_ID OR (V3492.LISTVAL_ID IS NULL AND :V$POS_ID IS NULL))
        ORDER BY V3507.VAL DESC
        INTO :VAL;
        SUSPEND;
        TAG_NAME = 'items:r:group_name';
        IF(VAL IS NOT NULL) THEN VAL = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:VAL));
        SUSPEND;
        -- должности - по справочнику
        TAG_NAME = 'items:r:job_id';
        VAL = V$POS_ID;
        SUSPEND;
        TAG_NAME = 'items:r:job_title';
        VAL = V$POS_NAME;
        SUSPEND;
        -- введенное руками текстовое название, если есть
        TAG_NAME = 'items:r:job_title_full';
        VAL = V$FULL_NAME;
        SUSPEND;
        -- кол-во ставок, обрезаем до 3 знаков после запятой
        TAG_NAME = 'items:r:rate';
        VAL = CAST(V$F AS NUMERIC(15, 3));
        SUSPEND;
      END
      IF(V$POS_GROUP = 98 AND V$POS_ID <> 122) THEN V$TEACHERS = 1;
    END
  END

  IF(V$HAS2 = 0) THEN EXCEPTION DATA_ERROR 'Не внесено наименование организации по уставу';

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE JOB_LIST_GET (
    I$OBJ_ID BIGINT NOT NULL,
    I$USER_ID VARCHAR(100))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$USER_ID BIGINT;
DECLARE VARIABLE V$ID BIGINT;
DECLARE VARIABLE V$STATUS_ID BIGINT;
DECLARE VARIABLE V$S VARCHAR(1000);
DECLARE VARIABLE V$D DATE;
DECLARE VARIABLE V$D2 DATE;
DECLARE VARIABLE V$F DOUBLE PRECISION;
DECLARE VARIABLE V$B BIGINT;
DECLARE VARIABLE V$JOB_ID BIGINT;
DECLARE VARIABLE V$S2 VARCHAR(1000);
DECLARE VARIABLE V$S3 VARCHAR(1000);
DECLARE VARIABLE V$F2 DOUBLE PRECISION;
DECLARE VARIABLE V$F3 DOUBLE PRECISION;
DECLARE VARIABLE V$GROUP_ID BIGINT;
DECLARE VARIABLE V$S4 VARCHAR(1000);
DECLARE VARIABLE V$S5 VARCHAR(4000);
DECLARE VARIABLE V$EXT1 FLOAT;
DECLARE VARIABLE V$EXT2 FLOAT;
DECLARE VARIABLE V$EXT3 FLOAT;
DECLARE VARIABLE TN FLOAT;
BEGIN
  --Redmine #1172
  IF(I$USER_ID = 'Веб-администратор') THEN V$USER_ID = 1; ELSE V$USER_ID = I$USER_ID;
  --nnn проверка уровня доступа ?

  --выводим данные самого ШР
  SELECT L505.OBJ_ID, V3490.LISTVAL_ID, LV3490.VAL, V3487.VAL, V3489.VAL
  FROM LINKS L505
  LEFT JOIN VALL V3490 ON V3490.OBJ_ID = L505.OBJ_ID AND V3490.PARAM_ID = 3490 AND V3490.IS_DEL = 0
  LEFT JOIN LISTVAL_TEXT(V3490.LISTVAL_ID) LV3490 ON 1 = 1
  LEFT JOIN VALD V3487 ON V3487.OBJ_ID = L505.OBJ_ID AND V3487.PARAM_ID = 3487 AND V3487.IS_DEL = 0
  LEFT JOIN VALD V3489 ON V3489.OBJ_ID = L505.OBJ_ID AND V3489.PARAM_ID = 3489 AND V3489.IS_DEL = 0
  LEFT JOIN VALS V3506 ON V3506.OBJ_ID = L505.OBJ_ID AND V3506.PARAM_ID = 3506 AND V3506.IS_DEL = 0
  WHERE L505.OBJ_ID = :I$OBJ_ID AND L505.DATE_DEL IS NULL AND L505.PARENT_TYPE_ID = 508 -- группа ШР
  INTO :V$ID, :V$STATUS_ID, :V$S, :V$D, :V$D2;

  -- ШР не может быть выбрано, пока не передан id
  IF(V$ID IS NULL) THEN EXCEPTION DATA_ERROR 'Штатное расписание не найдено или было удалено';

  TAG_NAME = 'id';
  VAL = V$ID;
  SUSPEND;
  TAG_NAME = 'date_from';
  -- даты выводим в формате для печати, сами даты нам тут не нужны
  SELECT RESULT FROM DATE2STR(:V$D) INTO :VAL;
  SUSPEND;
  TAG_NAME = 'date_to';
  SELECT RESULT FROM DATE2STR(:V$D2) INTO :VAL;
  SUSPEND;
  TAG_NAME = 'status_id';
  VAL = V$STATUS_ID;
  SUSPEND;
  TAG_NAME = 'status';
  VAL = V$S;
  SUSPEND;

  TAG_NAME = 'ou_name';
  V$ID = NULL;
  SELECT FIRST 1 L2.OBJ_ID, V2.VAL
  FROM LINKS L2
  LEFT JOIN VALS V2 ON V2.OBJ_ID = L2.OBJ_ID AND V2.PARAM_ID = 2 AND V2.IS_DEL = 0
  WHERE L2.OBJ_TYPE_ID = 2 AND L2.PARENT_TYPE_ID IS NULL AND L2.DATE_DEL IS NULL
  INTO :V$ID, :VAL;
  SUSPEND;

  TAG_NAME = 'sr_number';
  VAL = NULL;
  SELECT FIRST 1 V.VAL
  FROM VALS V
  WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 3506 AND V.IS_DEL = 0
  INTO :VAL;
  SUSPEND;
  TAG_NAME = 'sr_date';
  VAL = NULL;
  SELECT FIRST 1 D.RESULT
  FROM VALD V
  LEFT JOIN DATE2STR(V.VAL) D ON 1 = 1
  WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 3507 AND V.IS_DEL = 0
  INTO :VAL;
  SUSPEND;
  TAG_NAME = 'order_number';
  VAL = NULL;
  SELECT FIRST 1 V.VAL
  FROM VALS V
  WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 3504 AND V.IS_DEL = 0
  INTO :VAL;
  SUSPEND;
  TAG_NAME = 'order_date';
  VAL = NULL;
  SELECT FIRST 1 D.RESULT
  FROM VALD V
  LEFT JOIN DATE2STR(V.VAL) D ON 1 = 1
  WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 3505 AND V.IS_DEL = 0
  INTO :VAL;
  SUSPEND;

  -- Список подразделений для выбора при добавлении
  -- при просмотре в районе-регионе тут будет пусто, и ладно
  TAG_NAME = 'units::json&colon;array';
  VAL = 1;
  SUSPEND;
  -- Сама ОУ
  IF(V$ID IS NOT NULL) THEN
  BEGIN
    TAG_NAME = 'units:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'units:r:id';
    VAL = V$ID;
    SUSPEND;
    TAG_NAME = 'units:r:value';
    VAL = NULL;
    SELECT VAL FROM VALS WHERE OBJ_ID = :V$ID AND PARAM_ID = 999 AND IS_DEL = 0 INTO :VAL;
    SUSPEND;
    TAG_NAME = 'units:r:groups::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT L509.OBJ_ID, V3497.SVAL
      FROM LINKS L509
      JOIN VALS V3497 ON V3497.OBJ_ID = L509.OBJ_ID AND V3497.PARAM_ID = 3497 AND V3497.IS_DEL = 0
      WHERE L509.PARENT_ID = :V$ID AND L509.OBJ_TYPE_ID = 509 AND L509.DATE_DEL IS NULL
      INTO :V$GROUP_ID, :V$S
    DO
    BEGIN
      TAG_NAME = 'units:r:groups:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'units:r:groups:r:id';
      VAL = V$GROUP_ID;
      SUSPEND;
      TAG_NAME = 'units:r:groups:r:value';
      VAL = V$S;
      SUSPEND;
    END
    -- Подразделения 1 уровня
    FOR
      SELECT L211.OBJ_ID, C.CAPTION
      FROM LINKS L211
      LEFT JOIN OBJECT_CAPTION_GET(L211.OBJ_ID) C ON 1 = 1
      WHERE L211.OBJ_TYPE_ID = 211 AND L211.PARENT_ID = :V$ID AND L211.DATE_DEL IS NULL
      ORDER BY 2
      INTO :V$B, :V$S
    DO
    BEGIN
      TAG_NAME = 'units:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'units:r:id';
      VAL = V$B;
      SUSPEND;
      TAG_NAME = 'units:r:value';
      VAL = V$S;
      SUSPEND;
      TAG_NAME = 'units:r:groups::json&colon;array';
      VAL = 1;
      SUSPEND;
      FOR
        SELECT L509.OBJ_ID, V3497.SVAL
        FROM LINKS L509
        JOIN VALS V3497 ON V3497.OBJ_ID = L509.OBJ_ID AND V3497.PARAM_ID = 3497 AND V3497.IS_DEL = 0
        WHERE L509.PARENT_ID = :V$B AND L509.OBJ_TYPE_ID = 509 AND L509.DATE_DEL IS NULL
        INTO :V$GROUP_ID, :V$S
      DO
      BEGIN
        TAG_NAME = 'units:r:groups:r';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'units:r:groups:r:id';
        VAL = V$GROUP_ID;
        SUSPEND;
        TAG_NAME = 'units:r:groups:r:value';
        VAL = V$S;
        SUSPEND;
      END
    END
  END

  -- Элементы ШР
  -- выдаем в порядке следования, но сам номер не выдаем
  TN = 0;
  TAG_NAME = 'items::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L506.OBJ_ID, V3491.VAL, C.VAL, V3492.LISTVAL_ID, JC.VAL, V3494.VAL, V3493.VAL, V3495.VAL, V3496.VAL, V3499.VAL, V3500.VAL, V3501.VAL, V3502.VAL,
      V3498.VAL, C2.CAPTION
    FROM LINKS L506
    LEFT JOIN VALR V3491 ON V3491.OBJ_ID = L506.OBJ_ID AND V3491.PARAM_ID = 3491 AND V3491.IS_DEL = 0 -- подразделение
    LEFT JOIN VALS C ON C.OBJ_ID = V3491.VAL AND C.PARAM_ID IN (999, 1791) AND C.IS_DEL = 0 AND V3491.VAL IS NOT NULL
    LEFT JOIN VALL V3492 ON V3492.OBJ_ID = L506.OBJ_ID AND V3492.PARAM_ID = 3492 AND V3492.IS_DEL = 0
    LEFT JOIN LISTVAL_TEXT(V3492.LISTVAL_ID) JC ON V3492.LISTVAL_ID IS NOT NULL
    LEFT JOIN VALS V3494 ON V3494.OBJ_ID = L506.OBJ_ID AND V3494.PARAM_ID = 3494 AND V3494.IS_DEL = 0
    LEFT JOIN VALF V3493 ON V3493.OBJ_ID = L506.OBJ_ID AND V3493.PARAM_ID = 3493 AND V3493.IS_DEL = 0
    LEFT JOIN VALF V3495 ON V3495.OBJ_ID = L506.OBJ_ID AND V3495.PARAM_ID = 3495 AND V3495.IS_DEL = 0
    LEFT JOIN VALF V3496 ON V3496.OBJ_ID = L506.OBJ_ID AND V3496.PARAM_ID = 3496 AND V3496.IS_DEL = 0
    LEFT JOIN VALS V3499 ON V3499.OBJ_ID = L506.OBJ_ID AND V3499.PARAM_ID = 3499 AND V3499.IS_DEL = 0
    LEFT JOIN VALF V3500 ON V3500.OBJ_ID = L506.OBJ_ID AND V3500.PARAM_ID = 3500 AND V3500.IS_DEL = 0
    LEFT JOIN VALF V3501 ON V3501.OBJ_ID = L506.OBJ_ID AND V3501.PARAM_ID = 3501 AND V3501.IS_DEL = 0
    LEFT JOIN VALF V3502 ON V3502.OBJ_ID = L506.OBJ_ID AND V3502.PARAM_ID = 3502 AND V3502.IS_DEL = 0
    LEFT JOIN VALR V3498 ON V3498.OBJ_ID = L506.OBJ_ID AND V3498.PARAM_ID = 3498 AND V3498.IS_DEL = 0
    LEFT JOIN OBJECT_CAPTION_GET(V3498.VAL) C2 ON V3498.VAL IS NOT NULL
    WHERE L506.OBJ_TYPE_ID = 506 AND L506.PARENT_ID = :I$OBJ_ID AND L506.DATE_DEL IS NULL
    ORDER BY L506.COST
    INTO :V$ID, :V$B, :V$S, :V$JOB_ID, :V$S2, :V$S3, :V$F, :V$F2, :V$F3, :V$S4, :V$EXT1, :V$EXT2, :V$EXT3,
      :V$GROUP_ID, :V$S5
  DO
  BEGIN
    TN = TN + V$F;

    TAG_NAME = 'items:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'items:r:id';
    VAL = V$ID;
    SUSPEND;
    TAG_NAME = 'items:r:comments';
    VAL = V$S4;
    SUSPEND;
    -- Подразделение
    TAG_NAME = 'items:r:unit_id';
    VAL = V$B;
    SUSPEND;
    TAG_NAME = 'items:r:unit_name';
    VAL = V$S;
    SUSPEND;

    -- Группа должностей
    TAG_NAME = 'items:r:group_id';
    VAL = V$GROUP_ID;
    SUSPEND;
    TAG_NAME = 'items:r:group_name';
    VAL = V$S5;
    SUSPEND;

    -- должности - по справочнику
    TAG_NAME = 'items:r:job_id';
    VAL = V$JOB_ID;
    SUSPEND;
    TAG_NAME = 'items:r:job_title';
    VAL = V$S2;
    SUSPEND;
    -- введенное руками текстовое название, если есть
    TAG_NAME = 'items:r:job_title_full';
    VAL = V$S3;
    SUSPEND;
    -- кол-во ставок, обрезаем до 3 знаков после запятой
    TAG_NAME = 'items:r:rate';
    VAL = CAST(V$F AS NUMERIC(15, 3));
    SUSPEND;
    -- оклад
    TAG_NAME = 'items:r:base_salary';
    VAL = CAST(V$F2 AS NUMERIC(15, 2));
    SUSPEND;
    TAG_NAME = 'items:r:full_salary';
    VAL = CAST(V$F3 AS NUMERIC(15, 2));
    SUSPEND;
    TAG_NAME = 'items:r:extra1';
    VAL = CAST(V$EXT1 AS NUMERIC(15, 2));
    SUSPEND;
    TAG_NAME = 'items:r:extra2';
    VAL = CAST(V$EXT2 AS NUMERIC(15, 2));
    SUSPEND;
    TAG_NAME = 'items:r:extra3';
    VAL = CAST(V$EXT3 AS NUMERIC(15, 2));
    SUSPEND;

    --nnn Если конкретное ШР является действующим, показываем количество занятых ставок на текущий момент. На паузе, вопрос связывания должностей ШР и реальных должностей еще не проработан
    -- TODO: разделяем ставки на постоянно занятые и временно занятые
    TAG_NAME = 'items:r:rate_used';
    VAL = NULL;
    IF(V$STATUS_ID = 11715) THEN
    BEGIN
    END
    SUSPEND;
  END

  TAG_NAME = 'total_rate';
  VAL = CAST(TN AS NUMERIC (18, 2));
  SUSPEND;

  -- Списки выбора для должностей
  TAG_NAME = 'lists::json&colon;array';
  VAL = 1;
  SUSPEND;
  TAG_NAME = 'lists:r';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'lists:r:id';
  VAL = 370;
  SUSPEND;
  TAG_NAME = 'lists:r:value';
  VAL = 'Должности педагогических работчиков ОУ';
  SUSPEND;
  TAG_NAME = 'lists:r';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'lists:r:id';
  VAL = 369;
  SUSPEND;
  TAG_NAME = 'lists:r:value';
  VAL = 'Классификатор ОКПДТР';
  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE JOB_LIST_HEADERS (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$ID BIGINT;
DECLARE VARIABLE V$STATUS_ID BIGINT;
DECLARE VARIABLE V$D DATE;
DECLARE VARIABLE V$D2 DATE;
DECLARE VARIABLE NEW_VAR INTEGER;
DECLARE VARIABLE V$SRD DATE;
DECLARE VARIABLE V$SRNUM VARCHAR(400);
DECLARE VARIABLE V$S VARCHAR(400);
DECLARE VARIABLE V$S2 VARCHAR(400);
DECLARE VARIABLE V$ONUM VARCHAR(400);
DECLARE VARIABLE V$ODATE DATE;
begin

  SELECT L505.OBJ_ID, V3490.LISTVAL_ID, V3487.VAL, V3489.VAL, V3506.SVAL, V3507.VAL, V3508.VAL, V3509.VAL, V3504.VAL, V3505.VAL
  FROM LINKS L505
  LEFT JOIN VALL V3490 ON V3490.OBJ_ID = L505.OBJ_ID AND V3490.PARAM_ID = 3490 AND V3490.IS_DEL = 0
  LEFT JOIN VALD V3487 ON V3487.OBJ_ID = L505.OBJ_ID AND V3487.PARAM_ID = 3487 AND V3487.IS_DEL = 0
  LEFT JOIN VALD V3489 ON V3489.OBJ_ID = L505.OBJ_ID AND V3489.PARAM_ID = 3489 AND V3489.IS_DEL = 0
  LEFT JOIN VALS V3506 ON V3506.OBJ_ID = L505.OBJ_ID AND V3506.PARAM_ID = 3506 AND V3506.IS_DEL = 0
  LEFT JOIN VALD V3507 ON V3507.OBJ_ID = L505.OBJ_ID AND V3507.PARAM_ID = 3507 AND V3507.IS_DEL = 0
  LEFT JOIN VALS V3508 ON V3508.OBJ_ID = L505.OBJ_ID AND V3508.PARAM_ID = 3508 AND V3508.IS_DEL = 0
  LEFT JOIN VALS V3509 ON V3509.OBJ_ID = L505.OBJ_ID AND V3509.PARAM_ID = 3509 AND V3509.IS_DEL = 0
  LEFT JOIN VALS V3504 ON V3504.OBJ_ID = L505.OBJ_ID AND V3504.PARAM_ID = 3504 AND V3504.IS_DEL = 0
  LEFT JOIN VALD V3505 ON V3505.OBJ_ID = L505.OBJ_ID AND V3505.PARAM_ID = 3505 AND V3505.IS_DEL = 0
  WHERE L505.OBJ_ID = :I$OBJ_ID AND L505.DATE_DEL IS NULL AND L505.PARENT_TYPE_ID = 508 -- группа ШР
  INTO :V$ID, :V$STATUS_ID, :V$D, :V$D2, :V$SRNUM, :V$SRD, :V$S, :V$S2, :V$ONUM, :V$ODATE;

  IF(I$OBJ_ID IS NOT NULL AND V$ID IS NULL) THEN EXCEPTION DATA_ERROR 'Штатное расписание не найдено или было удалено';

  IF(V$STATUS_ID IS NULL) THEN V$STATUS_ID = 11716;
  IF(V$SRD IS NULL) THEN V$SRD = CURRENT_DATE;

  IF(V$S IS NULL) THEN
  SELECT FIRST 1 F.C1
  FROM LINKS L2
  JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
  LEFT JOIN VALL V3343 ON V3343.OBJ_ID = L14.OBJ_ID AND V3343.PARAM_ID = 3343 AND V3343.IS_DEL = 0
  JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
  LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
  JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
  LEFT JOIN VALL V63 ON V63.OBJ_ID = LP13.PARENT_ID AND V63.PARAM_ID = 63 AND V63.IS_DEL = 0
  LEFT JOIN BUILD_REP_FIO(L14.OBJ_ID, 59, 60, 61) F ON 1 = 1
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND V74.VAL IS NULL
    AND (V63.LISTVAL_ID = 55 OR V3343.LISTVAL_ID = 2) -- рук 1 уровня
  ORDER BY IIF(V63.LISTVAL_ID = 55, 0, 1)
  INTO :V$S;

  IF(V$S2 IS NULL) THEN
  SELECT FIRST 1 F.C1
  FROM LINKS L2
  JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
  LEFT JOIN VALL V3343 ON V3343.OBJ_ID = L14.OBJ_ID AND V3343.PARAM_ID = 3343 AND V3343.IS_DEL = 0
  JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
  LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
  JOIN VALS V3543 ON V3543.OBJ_ID = L15.OBJ_ID AND V3543.PARAM_ID = 3543 AND V3543.IS_DEL = 0 AND UPPER(V3543.SVAL) LIKE '%ГЛАВНЫЙ БУХГАЛТЕР%'
  LEFT JOIN BUILD_REP_FIO(L14.OBJ_ID, 59, 60, 61) F ON 1 = 1
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND V74.VAL IS NULL
  INTO :V$S;

  TAG_NAME = 'id';
  VAL = V$ID;
  SUSPEND;
  TAG_NAME = 'date_from';
  SELECT VAL FROM DATE2ISO(:V$D, 0) INTO :VAL;
  SUSPEND;
  TAG_NAME = 'date_to';
  SELECT VAL FROM DATE2ISO(:V$D2, 0) INTO :VAL;
  SUSPEND;

  TAG_NAME = 'status_id:values:value';
  VAL = V$STATUS_ID;
  SUSPEND;
  TAG_NAME = 'status_id:selection::json&colon;array';
  VAL = V$STATUS_ID;
  SUSPEND;
    TAG_NAME = 'status_id:selection:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'status_id:selection:r:id';
    VAL = 11716;
    SUSPEND;
    TAG_NAME = 'status_id:selection:r:value';
    VAL = 'Проект';
    SUSPEND;
    TAG_NAME = 'status_id:selection:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'status_id:selection:r:id';
    VAL = 11715;
    SUSPEND;
    TAG_NAME = 'status_id:selection:r:value';
    VAL = 'Действующий';
    SUSPEND;
    TAG_NAME = 'status_id:selection:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'status_id:selection:r:id';
    VAL = 14261;
    SUSPEND;
    TAG_NAME = 'status_id:selection:r:value';
    VAL = 'Архивный';
    SUSPEND;

  TAG_NAME = 'sr_number';
  VAL = V$SRNUM;
  SUSPEND;
  TAG_NAME = 'sr_date';
  SELECT VAL FROM DATE2ISO(:V$SRD, 0) INTO :VAL;
  SUSPEND;

  TAG_NAME = 'order_number';
  VAL = V$ONUM;
  SUSPEND;
  TAG_NAME = 'order_date';
  SELECT VAL FROM DATE2ISO(:V$ODATE, 0) INTO :VAL;
  SUSPEND;

  TAG_NAME = 'dir_fio';
  VAL = V$S;
  SUSPEND;
  TAG_NAME = 'gb_fio';
  VAL = V$S2;
  SUSPEND;

  TAG_NAME = 'db_level';
  VAL = NULL;
  SELECT FIRST 1 K.KEY_VAL
  FROM KEYS K
  WHERE K.KEY_CODE = 'LEVEL'
  INTO :VAL;
  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE JOB_LIST_SYNC (
    I$OBJ_ID BIGINT NOT NULL)
AS
declare variable V$ROW_ID bigint;
declare variable V$LINK_ID bigint;
declare variable V$ID bigint;
declare variable V$I bigint;
declare variable V$SCH_JOB_ID bigint;
declare variable V$SCH_JOBNAME varchar(400);
declare variable V$JOBNAME varchar(400);
declare variable V$UNIT_ID bigint;
declare variable V$F double precision;
declare variable V$F_PREV double precision;
declare variable V$DT timestamp;
declare variable V$TMP bigint;
declare variable V$ID_STR varchar(4000);
declare variable V$S varchar(400);
begin
  -- https://jira.netrika.ru/browse/PARAGRAPH-299
  -- При переводе в статус действующего синхронизация списка должностей (13) только в пределах конкретного указанного подразделения

  -- Сбрасываем статус всех должностей REASON_ID - смотри CALC_JOB_OCCUPIED
  -- даже удаленных - мы можем что-то восстановить
  UPDATE LINKS
  SET REASON_ID = 1
  WHERE OBJ_TYPE_ID = 13 AND PARENT_TYPE_ID IN (2, 211) AND (REASON_ID IS NULL OR REASON_ID <> 1);

  FOR
    SELECT L506.OBJ_ID, V3493.VAL, V3492.LISTVAL_ID, V3494.VAL, V3491.VAL
    FROM LINKS L506
    JOIN VALR V3491 ON V3491.OBJ_ID = L506.OBJ_ID AND V3491.PARAM_ID = 3491 AND V3491.IS_DEL = 0      -- подразделение
    JOIN VALF V3493 ON V3493.OBJ_ID = L506.OBJ_ID AND V3493.PARAM_ID = 3493 AND V3493.IS_DEL = 0      -- кол-во ставок
    LEFT JOIN VALL V3492 ON V3492.OBJ_ID = L506.OBJ_ID AND V3492.PARAM_ID = 3492 AND V3492.IS_DEL = 0 -- должность из списка  (506)
    LEFT JOIN VALS V3494 ON V3494.OBJ_ID = L506.OBJ_ID AND V3494.PARAM_ID = 3494 AND V3494.IS_DEL = 0 -- название должности   (506)
    WHERE L506.OBJ_TYPE_ID = 506 AND L506.PARENT_ID = :I$OBJ_ID AND L506.DATE_DEL IS NULL
    INTO :V$ROW_ID, :V$F, :V$SCH_JOB_ID, :V$JOBNAME, :V$UNIT_ID
  DO
  BEGIN
    -- Проверка валидности пары id:name для должности уже сделана
    V$SCH_JOBNAME = UPPER(TRIM(V$JOBNAME));

    -- найдем должность среди объектов типа 13 по совпадению значений в списка и текстового наименования
    V$ID = NULL;
    V$DT = NULL;
    V$LINK_ID = NULL;
    SELECT FIRST 1 L13.LINK_ID, L13.OBJ_ID, L13.DATE_DEL
    FROM LINKS L13
    LEFT JOIN VALL V58 ON V58.OBJ_ID = L13.OBJ_ID AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0 -- должность из списка (13)
    LEFT JOIN VALS V66 ON V66.OBJ_ID = L13.OBJ_ID AND V66.PARAM_ID = 66 AND V66.IS_DEL = 0 -- название должности  (13)
    WHERE L13.OBJ_TYPE_ID = 13 AND L13.PARENT_ID = :V$UNIT_ID
      AND COALESCE(V58.LISTVAL_ID, 0) = COALESCE(:V$SCH_JOB_ID, 0) AND UPPER(TRIM(V66.VAL)) = :V$SCH_JOBNAME
    ORDER BY L13.DATE_DEL NULLS FIRST
    INTO :V$LINK_ID, :V$ID, :V$DT;

    -- Если должность есть среди объектов типа 13
    IF(V$DT IS NOT NULL) THEN
    BEGIN
      -- Восстанавливаем должность из удаленных, так как она есть в ШР
      UPDATE LINKS L13
      SET L13.DATE_DEL = NULL
      WHERE L13.LINK_ID = :V$LINK_ID;
    END
    ELSE IF (V$LINK_ID IS NULL) THEN
    BEGIN
      -- Надо создать новую запись должности в соответствии с настройками ШР
      -- Тут может быть кейс, когда подразделение уже не существует, но и черт с ним
      SELECT OBJ_ID FROM OBJECT_ADD(:V$UNIT_ID, 13, NULL, NULL, NULL) INTO :V$ID;
    END
    -- Запоминаем ID должности в числе валидных
    V$ID_STR = IIF(V$ID_STR IS NULL, V$ID, V$ID_STR || ',' || V$ID);

    -- зададим полученные параметры в должность типа 13
    -- кол-во ставок
    V$F_PREV = NULL;
    SELECT VAL FROM VALF WHERE OBJ_ID = :V$ID AND PARAM_ID = 62 AND IS_DEL = 0 INTO :V$F_PREV;
    IF(COALESCE(V$F_PREV, -1) <> V$F) THEN SELECT 1 FROM VAL_ADD(62, :V$ID, :V$F, NULL) INTO :V$TMP;

    -- название должности
    V$S = NULL;
    SELECT VAL FROM VALS WHERE OBJ_ID = :V$ID AND PARAM_ID = 66 AND IS_DEL = 0 INTO :V$S;
    IF (COALESCE(V$S, '') <> V$JOBNAME) THEN SELECT 1 FROM VAL_ADD(66, :V$ID, :V$JOBNAME, NULL) INTO :V$TMP;

    -- должность из списка
    V$TMP = NULL;
    SELECT LISTVAL_ID FROM VALL WHERE OBJ_ID = :V$ID AND PARAM_ID = 58 AND IS_DEL = 0 INTO :V$TMP;
    IF (COALESCE(V$SCH_JOB_ID, 0) <> COALESCE(V$TMP, 0)) THEN
    BEGIN
      SELECT 1 FROM VAL_ADD(58, :V$ID, :V$SCH_JOB_ID, NULL) INTO :V$TMP;
      -- если по списку значения должности нет, то выставляем значения по-умолчанию для подгруппы и группы
      IF(V$SCH_JOB_ID IS NULL) THEN
      BEGIN
        SELECT 1 FROM VAL_ADD(64, :V$ID, 1257, NULL) INTO :V$TMP;
        SELECT 1 FROM VAL_ADD(63, :V$ID, 97, NULL) INTO :V$TMP;
      END
    END

    -- Пересчитываем итоги и статусы по этой должности
    EXECUTE PROCEDURE CALC_JOB_OCCUPIED(:V$ID, :V$ROW_ID, :V$F);
  END

  -- Обнуляем ставки должностей, которые не вxодят в текущее ШР
  FOR
    SELECT L13.LINK_ID, L13.OBJ_ID
    FROM LINKS L2
    JOIN LINKS L13 ON L13.PARENT_ID = L2.OBJ_ID AND L13.OBJ_TYPE_ID = 13 AND L13.DATE_DEL IS NULL
    LEFT JOIN VALF V62 ON V62.OBJ_ID = L13.OBJ_ID AND V62.PARAM_ID = 62 AND V62.IS_DEL = 0
    LEFT JOIN STR_TO_ID_LIST(:V$ID_STR) L ON L.ID = L13.OBJ_ID
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND L.ID IS NULL AND (V62.VAL IS NULL OR V62.VAL <> 0)
    UNION
    SELECT L13.LINK_ID, L13.OBJ_ID
    FROM LINKS L2
    JOIN LINKS L211 ON L211.PARENT_ID = L2.OBJ_ID AND L211.OBJ_TYPE_ID = 211 AND L211.DATE_DEL IS NULL
    JOIN LINKS L13 ON L13.PARENT_ID = L211.OBJ_ID AND L13.OBJ_TYPE_ID = 13 AND L13.DATE_DEL IS NULL
    LEFT JOIN VALF V62 ON V62.OBJ_ID = L13.OBJ_ID AND V62.PARAM_ID = 62 AND V62.IS_DEL = 0
    LEFT JOIN STR_TO_ID_LIST(:V$ID_STR) L ON L.ID = L13.OBJ_ID
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND L.ID IS NULL AND (V62.VAL IS NULL OR V62.VAL <> 0)
    INTO :V$I, :V$ID
  DO
  BEGIN
    SELECT 1 FROM VAL_ADD(62, :V$ID, 0, NULL) INTO :V$TMP;  -- кол-во ставок
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE JOB_LIST_VERIFY (
    I$OBJ_ID BIGINT NOT NULL,
    I$USER_ID BIGINT,
    I$TYPE_ID BIGINT NOT NULL,
    I$PARAM_ID BIGINT NOT NULL,
    I$VAL VARCHAR(4000) NOT NULL)
AS
DECLARE VARIABLE V$D DATE;
DECLARE VARIABLE V$ID BIGINT;
DECLARE VARIABLE V$S VARCHAR(400);
DECLARE VARIABLE V$S2 VARCHAR(400);
DECLARE VARIABLE V$D1 DATE;
DECLARE VARIABLE V$D2 DATE;
DECLARE VARIABLE V$PREV_ID BIGINT;
begin
  -- Тут только 505
  -- IF (I$TYPE_ID <> 505) THEN EXIT;

  IF (I$PARAM_ID = 3490) THEN -- статус
  BEGIN
    IF (I$VAL = 11716) THEN -- в статус проект
    BEGIN
      -- Очищать дату начала действия ШР - пока не делаем
      -- UPDATE VALD SET IS_DEL = 1 WHERE OBJ_ID = :I$OBJ_ID AND PARAM_ID = 3487 AND IS_DEL = 0;

      -- Ищем последнее по хронологии расписание в статусе "архив"
      SELECT FIRST 1 L505.OBJ_ID
      FROM LINKS L505
      JOIN VALL V3490 ON V3490.OBJ_ID = L505.OBJ_ID AND V3490.PARAM_ID = 3490 AND V3490.IS_DEL = 0 AND V3490.LISTVAL_ID = 14261 -- статус = архив
      JOIN VALD V3487 ON V3487.OBJ_ID = L505.OBJ_ID AND V3487.PARAM_ID = 3487 AND V3487.IS_DEL = 0
      WHERE L505.PARENT_TYPE_ID = 508 AND L505.OBJ_TYPE_ID = 505 AND L505.DATE_DEL IS NULL
      ORDER BY V3487.VAL DESC
      INTO :V$ID;

      -- Если мы не самые последние - переводим предыдущее из архива в действующее мимо всех проверок
      IF(V$ID IS NOT NULL) THEN
      BEGIN
        UPDATE VALL SET LISTVAL_ID = 11715 WHERE OBJ_ID = :V$ID AND PARAM_ID = 3490; -- статус ШР
        -- Синхронизируем должности
        EXECUTE PROCEDURE JOB_LIST_SYNC(:V$ID);
      END
    END
    ELSE IF (I$VAL = 11715) THEN -- в статус действующего, только из проекта
    BEGIN
      -- nnn
      --IF(NOT EXISTS(
      --  SELECT FIRST 1 1
      --  FROM LUSERS LU
      --  WHERE LU.USER_ID = :I$USER_ID AND LU.LEVEL_ID IN (48) AND LU.READ_ONLY <> 1
      --)) THEN EXCEPTION DATA_ERROR 'У вас нет доступа к штатным расписаниям';

      -- Проверка вводимых парaметров ШР
      SELECT FIRST 1 V3507.VAL, V3487.VAL, V3504.VAL, V3505.VAL, V3529.VAL
      FROM LINKS L505
      LEFT JOIN VALD V3507 ON V3507.OBJ_ID = L505.OBJ_ID AND V3507.PARAM_ID = 3507 AND V3507.IS_DEL = 0 -- дата составления
      LEFT JOIN VALD V3487 ON V3487.OBJ_ID = L505.OBJ_ID AND V3487.PARAM_ID = 3487 AND V3487.IS_DEL = 0 -- дата начала действия
      LEFT JOIN VALS V3504 ON V3504.OBJ_ID = L505.OBJ_ID AND V3504.PARAM_ID = 3504 AND V3504.IS_DEL = 0 -- номер приказа утверждения
      LEFT JOIN VALD V3505 ON V3505.OBJ_ID = L505.OBJ_ID AND V3505.PARAM_ID = 3505 AND V3505.IS_DEL = 0 -- дата приказа утверждения
      LEFT JOIN VALR V3529 ON V3529.OBJ_ID = L505.OBJ_ID AND V3529.PARAM_ID = 3529 AND V3529.IS_DEL = 0 -- предыдущее ШР
      WHERE L505.PARENT_TYPE_ID = 508 AND L505.OBJ_ID = :I$OBJ_ID AND L505.DATE_DEL IS NULL
      INTO :V$D, :V$D1, :V$S, :V$D2, :V$PREV_ID;

      IF (V$D IS NULL) THEN EXCEPTION DATA_ERROR 'Не указана дата составления штатного расписания';
      IF (V$S IS NULL) THEN EXCEPTION DATA_ERROR 'Не указан номер приказа об утверждении штатного расписания';
      IF (V$D2 IS NULL) THEN EXCEPTION DATA_ERROR 'Не указана дата приказа об утверждении штатного расписания';
      IF (V$D1 IS NULL) THEN EXCEPTION DATA_ERROR 'Не задана дата начала действия штатного расписания';
      -- Проверка хронологии
      IF (V$D > V$D1) THEN EXCEPTION DATA_ERROR 'Дата составления должна быть не позже даты начала действия штатного расписания';
      IF (V$D2 > V$D1) THEN EXCEPTION DATA_ERROR 'Дата приказа об утверждении штатного расписания должна быть не позже даты начала действия штатного расписания';

      -- дата начала действия должна быть строго позднее самой поздней даты действия других активных расписаний
      V$D = NULL;
      SELECT FIRST 1 V3487.VAL
      FROM LINKS L505
      JOIN VALL V3490 ON V3490.OBJ_ID = L505.OBJ_ID AND V3490.PARAM_ID = 3490 AND V3490.IS_DEL = 0 AND V3490.LISTVAL_ID IN (11715, 14261) -- действующий или архив
      JOIN VALD V3487 ON V3487.OBJ_ID = L505.OBJ_ID AND V3487.PARAM_ID = 3487 AND V3487.IS_DEL = 0
      WHERE L505.PARENT_TYPE_ID = 508 AND L505.OBJ_ID = :I$OBJ_ID AND L505.DATE_DEL IS NULL AND L505.OBJ_ID <> :I$OBJ_ID
      ORDER BY 1 DESC
      INTO :V$D;

      IF(V$D >= V$D1) THEN EXCEPTION DATA_ERROR 'Уже есть расписание с более поздним сроком начала действия ' || V$D;

      -- Запрещать перевод, если в ШР нет хотя бы одного элемента, а также если есть элементы где не заполнено количество ставок, количество ставок <= 0, либо не заполнено одно из двух полей - ссылка на должность по справочнику или текстовое наименование
      IF (NOT EXISTS(
        SELECT FIRST 1 1
        FROM LINKS L506
        WHERE L506.PARENT_ID = :I$OBJ_ID AND L506.OBJ_TYPE_ID = 506 AND L506.DATE_DEL IS NULL
      ))
      THEN
        EXCEPTION DATA_ERROR 'Штатное расписание должно содержать хотя бы одну должность';

      IF (EXISTS(
        SELECT FIRST 1 1
        FROM LINKS L506
        LEFT JOIN VALL V3492 ON V3492.OBJ_ID = L506.OBJ_ID AND V3492.PARAM_ID = 3492 AND V3492.IS_DEL = 0 -- должность
        LEFT JOIN VALS V3494 ON V3494.OBJ_ID = L506.OBJ_ID AND V3494.PARAM_ID = 3494 AND V3494.IS_DEL = 0 -- полное наименование должности
        LEFT JOIN VALF V3493 ON V3493.OBJ_ID = L506.OBJ_ID AND V3493.PARAM_ID = 3493 AND V3493.IS_DEL = 0 -- ставки
        WHERE L506.OBJ_TYPE_ID = 506 AND L506.PARENT_ID = :I$OBJ_ID AND L506.DATE_DEL IS NULL
          AND ((V3492.LISTVAL_ID IS NULL AND V3494.VAL IS NULL) OR V3493.VAL IS NULL OR V3493.VAL <= 0)
      ))
      THEN
        EXCEPTION DATA_ERROR 'Штатное расписание не полностью заполнено, не заполнены должность или количество ставок';

      -- При первом утверждении запоминаем предыдущее действующее расписание
      -- сейчас будет два действующих расписания
      IF(V$PREV_ID IS NULL) THEN
      BEGIN
        SELECT FIRST 1 L505.OBJ_ID
        FROM LINKS L505
        JOIN VALL V3490 ON V3490.OBJ_ID = L505.OBJ_ID AND V3490.PARAM_ID = 3490 AND V3490.IS_DEL = 0 AND V3490.LISTVAL_ID = 11715
        WHERE L505.PARENT_TYPE_ID = 508 AND L505.OBJ_TYPE_ID = 505 AND L505.DATE_DEL IS NULL AND L505.OBJ_ID <> :I$OBJ_ID
        INTO :V$PREV_ID;
      END
      ELSE
      BEGIN
        -- Предыдущее и должно быть действующим
        -- !!! по идее тут надо проверить не удалили ли предыдущее, и попытаться восстановить цепочку
        IF(NOT EXISTS(
          SELECT FIRST 1 1
          FROM LINKS L505
          JOIN VALL V3490 ON V3490.OBJ_ID = L505.OBJ_ID AND V3490.PARAM_ID = 3490 AND V3490.IS_DEL = 0 AND V3490.LISTVAL_ID = 11715
          WHERE L505.PARENT_TYPE_ID = 508 AND L505.OBJ_TYPE_ID = 505 AND L505.DATE_DEL IS NULL AND L505.OBJ_ID = :V$PREV_ID
        ))
        THEN
          EXCEPTION DATA_ERROR 'Вы нарушили порядок утверждения штатных расписаний, либо повреждена база данных';
      END

      IF(V$PREV_ID IS NOT NULL) THEN
      BEGIN
        -- записываем предыдущее ШР
        UPDATE OR INSERT INTO VALR (OBJ_ID, PARAM_ID, VAL, IS_DEL) VALUES (:I$OBJ_ID, 3529, :V$PREV_ID, 0) MATCHING (OBJ_ID, PARAM_ID);
        -- Переводим предыдущее в архив
        UPDATE VALL SET LISTVAL_ID = 14261 WHERE OBJ_ID = :V$PREV_ID AND PARAM_ID = 3490; -- статус
        -- Время окончания действия = дата начала текущего
        UPDATE OR INSERT INTO VALD (OBJ_ID, PARAM_ID, VAL, IS_DEL) VALUES (:V$PREV_ID, 3489, :V$D1, 0) MATCHING (OBJ_ID, PARAM_ID); -- время окончания действия
      END

      -- Обновляем ФИО директора и бухгалтера
      SELECT FIRST 1 C1.FIO, C2.FIO
      FROM LINKS L2
      LEFT JOIN R_SPB_POST_DIRECTOR(L2.OBJ_ID, 1) C1 ON 1 = 1
      LEFT JOIN R_SPB_POST_BUHGALTER(L2.OBJ_ID, 1) C2 ON 1 = 1
      WHERE L2.OBJ_TYPE_ID = 2 AND L2.PARENT_ID IS NULL AND L2.DATE_DEL IS NULL
      INTO :V$S, :V$S2;

      IF(V$S IS NOT NULL) THEN
      UPDATE OR INSERT INTO VALS (OBJ_ID, PARAM_ID, VAL, IS_DEL) VALUES (:I$OBJ_ID, 3508, :V$S, 0) MATCHING (OBJ_ID, PARAM_ID);
      IF(V$S2 IS NOT NULL) THEN
      UPDATE OR INSERT INTO VALS (OBJ_ID, PARAM_ID, VAL, IS_DEL) VALUES (:I$OBJ_ID, 3509, :V$S2, 0) MATCHING (OBJ_ID, PARAM_ID);

      -- Синхронизируем должности и сразу там же их пересчитываем
      EXECUTE PROCEDURE JOB_LIST_SYNC(:I$OBJ_ID);
    END
    -- В статус архив - перевод руками (автоматический перевод идет мимо VAL_ADD)
    ELSE IF (I$VAL = 14261) THEN -- в статус архив
    BEGIN
      EXCEPTION DATA_ERROR 'Штатное расписание переводится в архив только автоматически, после утверждения нового штатного расписания';
    END
    ELSE IF (I$VAL = 11717) THEN -- в статус не действующий
    BEGIN
      EXCEPTION DATA_ERROR 'Статус "Не действующий" не должен использоваться. Удалите неактуальное штатное расписание';
    END
  END
  ELSE
  BEGIN
    -- Нельзя вносить изменения для действующих или архивных ШР
    IF (EXISTS(
      SELECT FIRST 1 1
      FROM VALL V3490
      WHERE V3490.OBJ_ID = :I$OBJ_ID AND V3490.PARAM_ID = 3490 AND V3490.IS_DEL = 0 AND V3490.LISTVAL_ID <> 11716
    ))
    THEN
      EXCEPTION DATA_ERROR 'Штатное расписание можно изменять только в статусе Проект';

    -- Дата начала действия не должна быть в будущем, иначе поломаем текущий ввод должностей
    IF (I$PARAM_ID = 3487 AND I$VAL > CURRENT_DATE) THEN
      EXCEPTION DATA_ERROR 'Дата начала действия должна быть не позднее текущей даты';

    -- Дата составления действия не должна быть в будущем
    IF (I$PARAM_ID = 3507 AND I$VAL > CURRENT_DATE) THEN
      EXCEPTION DATA_ERROR 'Дата составления должна быть не позднее текущей даты';
  END
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE JOB_POS_DELETE (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(100))
AS
DECLARE VARIABLE V$ID BIGINT;
DECLARE VARIABLE V$PARENT_ID BIGINT;
DECLARE VARIABLE V$COST FLOAT;
DECLARE VARIABLE V$STATE_ID BIGINT;
begin
   --Redmine #1172
  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;
  --nnn проверка уровня доступа ?

  SELECT FIRST 1 L506.OBJ_ID, L506.PARENT_ID, L506.COST, V3490.LISTVAL_ID
  FROM LINKS L506
  JOIN VALL V3490 ON V3490.OBJ_ID = L506.PARENT_ID AND V3490.PARAM_ID = 3490 AND V3490.IS_DEL = 0
  WHERE L506.OBJ_ID = :I$OBJ_ID AND L506.PARENT_TYPE_ID = 505 AND L506.DATE_DEL IS NULL
  INTO :V$ID, :V$PARENT_ID, :V$COST, :V$STATE_ID;

  IF (V$ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не найден элемент штатного расписания, id = ' || I$OBJ_ID;

  -- Статус ШР допускает редактирование ?
  -- ...
  IF(V$STATE_ID <> 11716) THEN EXCEPTION DATA_ERROR 'Удалять элементы штатного расписания можно только в статусе проекта';

  SELECT DEL_COUNT FROM OBJECT_DEL(:V$PARENT_ID, :V$ID) INTO :V$ID;

  -- Сдвигаем нумерацию элементов
  IF (V$COST > 0) THEN
  BEGIN
    UPDATE LINKS L506
    SET COST = COST - 1
    WHERE L506.OBJ_ID <> :I$OBJ_ID AND L506.PARENT_TYPE_ID = 505 AND L506.DATE_DEL IS NULL AND COST > :V$COST
    ORDER BY L506.COST;
  END
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE JOB_POS_DELETE_ALL (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
AS
DECLARE VARIABLE V$STATUS BIGINT;
begin

  SELECT V.LISTVAL_ID
  FROM VALL V
  WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 3490 AND V.IS_DEL = 0
  INTO :V$STATUS;

  IF(V$STATUS IS NULL) THEN EXCEPTION DATA_ERROR 'Штатное расписание не найдено или было удалено';
  IF(V$STATUS <> 11716) THEN EXCEPTION DATA_ERROR 'Штатное расписание можно удалить только в статусе Проект';

  UPDATE LINKS
  SET DATE_DEL = CURRENT_TIMESTAMP
  WHERE OBJ_ID = :I$OBJ_ID AND DATE_DEL IS NULL AND PARENT_TYPE_ID = 508;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE JOB_POS_MOVE (
    I$PARENT_ID BIGINT NOT NULL,
    I$OBJ_ID BIGINT,
    I$UNIT_ID BIGINT,
    I$GROUP_ID BIGINT,
    I$INDEX BIGINT NOT NULL,
    I$USER_ID VARCHAR(40))
AS
DECLARE VARIABLE V$UNIT_ID BIGINT;
DECLARE VARIABLE V$GROUP_ID BIGINT;
DECLARE VARIABLE V$SEQ BIGINT;
DECLARE VARIABLE V$STATUS BIGINT;
DECLARE VARIABLE D$UNIT_ID BIGINT;
DECLARE VARIABLE D$GROUP_ID BIGINT;
DECLARE VARIABLE V$LINK_ID BIGINT;
DECLARE VARIABLE V$N BIGINT;
DECLARE VARIABLE D$OBJ_ID BIGINT;
DECLARE VARIABLE V$SEQ2 BIGINT;
DECLARE VARIABLE V$RES_NUM BIGINT;
begin

  -- На входе задается либо OBJ_ID конкретного элемента, либо UNIT_ID+GROUP_ID для группы, либо только UNIT_ID для подразделения
  -- для default группы указывается GROUP_ID = 0 - эта комбинация все равно блокируется, default группа всегда идет в хвосте
  -- INDEX это OBJ_ID элемента после которого хотим встать

  -- Заодно получаем реквизиты элемента, за которым должны встать
  SELECT V3490.LISTVAL_ID, V3491.VAL, V3492.VAL
  FROM LINKS L505
  JOIN VALL V3490 ON V3490.OBJ_ID = L505.OBJ_ID AND V3490.PARAM_ID = 3490 AND V3490.IS_DEL = 0
  JOIN LINKS L506 ON L506.PARENT_ID = L505.OBJ_ID AND L506.OBJ_ID = :I$INDEX AND L506.DATE_DEL IS NULL -- сразу же удостоверяемся что он тоже в этом ШР
  JOIN VALR V3491 ON V3491.OBJ_ID = L506.OBJ_ID AND V3491.PARAM_ID = 3491 AND V3491.IS_DEL = 0
  LEFT JOIN VALR V3492 ON V3492.OBJ_ID = L506.OBJ_ID AND V3492.PARAM_ID = 3492 AND V3492.IS_DEL = 0
  WHERE L505.OBJ_ID = :I$PARENT_ID AND L505.PARENT_TYPE_ID = 508 AND L505.DATE_DEL IS NULL
  INTO :V$STATUS, :D$UNIT_ID, :D$GROUP_ID;

  IF(V$STATUS IS NULL) THEN EXCEPTION DATA_ERROR 'Системная ошибка, возможно один из элементов был удален. Переоткройте ШР';
  IF(V$STATUS <> 11716) THEN EXCEPTION DATA_ERROR 'Нельзя изменять ШР не в статусе проекта';

  -- Дополнительные проверки, на случай если что-то поменялось
  IF(I$OBJ_ID IS NOT NULL) THEN
  BEGIN
    -- Тащим один конкретный элемент
    SELECT L506.COST, V3491.VAL, V3492.VAL
    FROM LINKS L506
    JOIN VALR V3491 ON V3491.OBJ_ID = L506.OBJ_ID AND V3491.PARAM_ID = 3491 AND V3491.IS_DEL = 0
    LEFT JOIN VALR V3492 ON V3492.OBJ_ID = L506.OBJ_ID AND V3492.PARAM_ID = 3492 AND V3492.IS_DEL = 0
    WHERE L506.PARENT_ID = :I$PARENT_ID AND L506.OBJ_ID = :I$OBJ_ID AND L506.OBJ_TYPE_ID = 506 AND L506.DATE_DEL IS NULL
    INTO :V$SEQ, :V$UNIT_ID, :V$GROUP_ID;

    IF(V$SEQ IS NULL) THEN EXCEPTION DATA_ERROR 'Перемещаемый элемент не найден';

    -- Перемещать можно только в пределах той же группы того же подразделения
    IF(V$UNIT_ID <> D$UNIT_ID OR COALESCE(V$GROUP_ID, 0) <> COALESCE(D$GROUP_ID, 0)) THEN
      EXCEPTION DATA_ERROR 'Изменять порядок элементов можно только в пределах одного подразделения и одной группы должностей';
  END
  ELSE
  BEGIN
    IF(I$GROUP_ID IS NULL) THEN
    BEGIN
      -- Перемещаем подразделение
      -- Всегда встаем за последним элементом выбранного подразделения - корректируем индекс чтобы наверняка
      SELECT FIRST 1 L506.OBJ_ID
      FROM LINKS L506
      JOIN VALR V3491 ON V3491.OBJ_ID = L506.OBJ_ID AND V3491.PARAM_ID = 3491 AND V3491.IS_DEL = 0 AND V3491.VAL = :D$UNIT_ID
      LEFT JOIN VALR V3492 ON V3492.OBJ_ID = L506.OBJ_ID AND V3492.PARAM_ID = 3492 AND V3492.IS_DEL = 0
      WHERE L506.PARENT_ID = :I$PARENT_ID AND L506.OBJ_TYPE_ID = 506 AND L506.DATE_DEL IS NULL
      ORDER BY L506.COST DESC
      INTO :I$INDEX;
    END
    ELSE
    BEGIN
      -- Перемещаем конкретную группу в пределах подразделения
      -- Нельзя перемещать ни группу по-умолчанию, ни на группу по-умолчанию (она всегда последняя)
      IF(I$GROUP_ID = 0) THEN EXCEPTION DATA_ERROR 'Группу по-умолчанию нельзя перемещать, она всегда идет последней';
      IF(I$UNIT_ID = D$UNIT_ID AND D$GROUP_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Группа по-умолчанию может находиться только в конце списка';
      -- Корректируем индекс, чтобы встать после последнего элемента группы
      SELECT FIRST 1 L506.OBJ_ID
      FROM LINKS L506
      JOIN VALR V3491 ON V3491.OBJ_ID = L506.OBJ_ID AND V3491.PARAM_ID = 3491 AND V3491.IS_DEL = 0 AND V3491.VAL = :D$UNIT_ID
      LEFT JOIN VALR V3492 ON V3492.OBJ_ID = L506.OBJ_ID AND V3492.PARAM_ID = 3492 AND V3492.IS_DEL = 0
      WHERE L506.PARENT_ID = :I$PARENT_ID AND L506.OBJ_TYPE_ID = 506 AND L506.DATE_DEL IS NULL
        AND (V3492.VAL = :D$GROUP_ID OR (:D$UNIT_ID IS NULL AND V3492.VAL IS NULL))
      ORDER BY L506.COST DESC
      INTO :I$INDEX;
    END
  END

  -- Сколько адресов нам нужно зарезервировать в перемещаемом блоке ?
  SELECT COUNT(*)
  FROM LINKS L506
  LEFT JOIN VALR V3491 ON V3491.OBJ_ID = L506.OBJ_ID AND V3491.PARAM_ID = 3491 AND V3491.IS_DEL = 0
  LEFT JOIN VALR V3492 ON V3492.OBJ_ID = L506.OBJ_ID AND V3492.PARAM_ID = 3492 AND V3492.IS_DEL = 0
  WHERE L506.PARENT_ID = :I$PARENT_ID AND L506.OBJ_TYPE_ID = 506 AND L506.DATE_DEL IS NULL
    AND (L506.OBJ_ID = :I$OBJ_ID OR :I$OBJ_ID IS NULL) -- это конкретный элемент ?
    AND (COALESCE(V3492.VAL, 0) = :I$GROUP_ID OR :I$GROUP_ID IS NULL) -- это группа ?
    AND (V3491.VAL = :I$UNIT_ID OR :I$UNIT_ID IS NULL) -- подразделение
  INTO :V$RES_NUM;

  -- Общий цикл по не-перемещаемым элементам, перемещаем их и фиксируем место начало нумерации для перемещения
  V$SEQ2 = -1;
  V$N = 0;
  FOR
    SELECT L506.LINK_ID, L506.OBJ_ID, L506.COST
    FROM LINKS L506
    LEFT JOIN VALR V3491 ON V3491.OBJ_ID = L506.OBJ_ID AND V3491.PARAM_ID = 3491 AND V3491.IS_DEL = 0
    LEFT JOIN VALR V3492 ON V3492.OBJ_ID = L506.OBJ_ID AND V3492.PARAM_ID = 3492 AND V3492.IS_DEL = 0
    WHERE L506.PARENT_ID = :I$PARENT_ID AND L506.OBJ_TYPE_ID = 506 AND L506.DATE_DEL IS NULL
      AND (L506.OBJ_ID <> :I$OBJ_ID OR :I$OBJ_ID IS NULL) -- это конкретный элемент ?
      AND (COALESCE(V3492.VAL, 0) <> :I$GROUP_ID OR :I$GROUP_ID IS NULL) -- группа
      AND (V3491.VAL <> :I$UNIT_ID OR :I$UNIT_ID IS NULL) -- подразделение
    ORDER BY 3
    INTO :V$LINK_ID, :D$OBJ_ID, :V$SEQ
  DO
  BEGIN
    IF(V$SEQ <> V$N) THEN
    BEGIN
      UPDATE LINKS SET COST = :V$N WHERE LINK_ID = :V$LINK_ID;
    END
    V$N = V$N + 1;
    -- Когда дошли до элемента после которого надо вставить - резервируем место
    IF(D$OBJ_ID = I$INDEX) THEN
    BEGIN
      V$SEQ2 = V$N;
      V$N = V$N + V$RES_NUM;
    END
  END

  -- Встраиваем
  V$N = V$SEQ2;
  FOR
    SELECT L506.LINK_ID, L506.OBJ_ID, L506.COST
    FROM LINKS L506
    LEFT JOIN VALR V3491 ON V3491.OBJ_ID = L506.OBJ_ID AND V3491.PARAM_ID = 3491 AND V3491.IS_DEL = 0
    LEFT JOIN VALR V3492 ON V3492.OBJ_ID = L506.OBJ_ID AND V3492.PARAM_ID = 3492 AND V3492.IS_DEL = 0
    WHERE L506.PARENT_ID = :I$PARENT_ID AND L506.OBJ_TYPE_ID = 506 AND L506.DATE_DEL IS NULL
      AND (L506.OBJ_ID = :I$OBJ_ID OR :I$OBJ_ID IS NULL) -- это конкретный элемент ?
      AND (COALESCE(V3492.VAL, 0) = :I$GROUP_ID OR :I$GROUP_ID IS NULL) -- это группа ?
      AND (V3491.VAL = :I$UNIT_ID OR :I$UNIT_ID IS NULL) -- подразделение
    ORDER BY 3
    INTO :V$LINK_ID, :D$OBJ_ID, :V$SEQ
  DO
  BEGIN
    IF(V$SEQ <> V$N) THEN
    BEGIN
      UPDATE LINKS SET COST = :V$N WHERE LINK_ID = :V$LINK_ID;
    END
    V$N = V$N + 1;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE JOB_POS_SET (
    I$PARENT_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(100) NOT NULL,
    I$UNIT_ID BIGINT,
    I$GROUP_ID BIGINT,
    I$JOB_ID BIGINT,
    I$JOB_TITLE_FULL VARCHAR(1000),
    I$RATE FLOAT,
    I$SALARY_BASE FLOAT,
    I$SALARY_FULL FLOAT,
    I$EXTRA1 FLOAT,
    I$EXTRA2 FLOAT,
    I$EXTRA3 FLOAT,
    I$COMMENTS VARCHAR(4000),
    I$INDEX BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    PRE_ID BIGINT)
AS
DECLARE VARIABLE V$ID BIGINT;
DECLARE VARIABLE V$LINK_ID BIGINT;
DECLARE VARIABLE V$INDEX BIGINT;
DECLARE VARIABLE V$CI BIGINT;
DECLARE VARIABLE V$JOB_ID BIGINT;
DECLARE VARIABLE V$JOB_TITLE_FULL VARCHAR(1000);
DECLARE VARIABLE V$GROUP_ID BIGINT;
DECLARE VARIABLE V$RATE FLOAT;
DECLARE VARIABLE V$SALARY_BASE FLOAT;
DECLARE VARIABLE V$SALARY_FULL FLOAT;
DECLARE VARIABLE N INTEGER;
DECLARE VARIABLE V$EXTRA1 FLOAT;
DECLARE VARIABLE V$EXTRA2 FLOAT;
DECLARE VARIABLE V$EXTRA3 FLOAT;
DECLARE VARIABLE V$COMMENTS VARCHAR(4000);
DECLARE VARIABLE V$LAST_ID BIGINT;
DECLARE VARIABLE V$SEQ BIGINT;
DECLARE VARIABLE V$LAST_SEQ BIGINT;
DECLARE VARIABLE V$UNIT_OBJ_ID BIGINT;
DECLARE VARIABLE V$GROUP_ID_ND BIGINT;
DECLARE VARIABLE V$SEQ_ND BIGINT;
DECLARE VARIABLE V$GROUP_ID_D BIGINT;
DECLARE VARIABLE V$SEQ_D BIGINT;
begin
  --Redmine #1172
  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;
  --nnn проверка уровня доступа ?

  I$JOB_TITLE_FULL = TRIM(I$JOB_TITLE_FULL);

  -- OBJ_ID -1 - специальный случай для автоподбора должности по кодификаторам
  IF(I$OBJ_ID = -1 AND I$JOB_ID IS NULL) THEN
  BEGIN
    I$OBJ_ID = NULL;
    -- Пытаемся подобрать буквальное соответствие должности
    SELECT FIRST 1 LV.LISTVAL_ID
    FROM LISTVALS LV
    JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU' AND UPPER(R.VAL) = UPPER(:I$JOB_TITLE_FULL)
    LEFT JOIN LISTVALS LV2 ON LV2.PARENT_ID = LV.LISTVAL_ID AND LV2.LISTVAL_ID = LV.LIST_ID AND LV2.IS_DEL = 0
    WHERE LV.LIST_ID IN (369, 370) AND LV.IS_DEL = 0 AND LV2.LISTVAL_ID IS NULL
    ORDER BY LV.LIST_ID DESC
    INTO :I$JOB_ID;
    -- Должность 1:1 не нашлась, пробуем ключевые комбинации
    IF(POSITION('УЧИТЕЛЬ' IN UPPER(I$JOB_TITLE_FULL)) > 0) THEN
    BEGIN
      IF(POSITION('ЛОГОПЕД' IN UPPER(I$JOB_TITLE_FULL)) > 0) THEN I$JOB_ID = 18551;
      ELSE IF(POSITION('ДЕФЕКТОЛОГ' IN UPPER(I$JOB_TITLE_FULL)) > 0) THEN I$JOB_ID = 18505;
      ELSE I$JOB_ID = 18501;
    END
    ELSE IF(POSITION('ПРЕПОДАВАТЕЛЬ' IN UPPER(I$JOB_TITLE_FULL)) > 0) THEN
    BEGIN
      IF(POSITION('ТРЕНЕР' IN UPPER(I$JOB_TITLE_FULL)) > 0) THEN BEGIN
        IF(POSITION('СТАРШИЙ' IN UPPER(I$JOB_TITLE_FULL)) > 0) THEN I$JOB_ID = 18550;
        ELSE I$JOB_ID = 18520;
      END
      ELSE IF(POSITION('БЕЗОПАСНОСТИ' IN UPPER(I$JOB_TITLE_FULL)) > 0) THEN I$JOB_ID = 18519;
      ELSE IF(POSITION('СТАРШИЙ' IN UPPER(I$JOB_TITLE_FULL)) > 0) THEN I$JOB_ID = 18558;
      -- Есть еще повторная должность предподавателя профессорско-преподавательского состава - ее игнорируем
      ELSE I$JOB_ID = 18502;
    END
  END
  ELSE IF(I$OBJ_ID = -1) THEN
    I$OBJ_ID = NULL;

  SELECT FIRST 1 L506.OBJ_ID, L506.LINK_ID, L506.COST
  FROM LINKS L506
  WHERE L506.OBJ_ID = :I$OBJ_ID AND L506.DATE_DEL IS NULL AND L506.PARENT_TYPE_ID = 505 AND L506.PARENT_ID = :I$PARENT_ID
  INTO :OBJ_ID, :V$LINK_ID, :V$INDEX;

  IF(I$OBJ_ID IS NOT NULL AND OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Запись штатного расписания не найдена';
  IF(I$UNIT_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не указано подразделение';
  IF(I$RATE <= 0) THEN EXCEPTION DATA_ERROR 'Количество ставок должно быть положительным числом';
  IF(I$SALARY_BASE <= 0 OR I$SALARY_FULL <= 0) THEN EXCEPTION DATA_ERROR 'Оклад должен быть положительным числом';
  IF(I$EXTRA1 <= 0 OR I$EXTRA2 <= 0 OR I$EXTRA3 <= 0) THEN EXCEPTION DATA_ERROR 'Надбавки к окладу должны быть положительным числом';
  -- I$INDEX = NULL значит автоопределение положения в расписании
  -- в прочих случаях I$INDEX = ID элемента, за которым встаем; 0 если надо встать в самое начало
  -- обратно возвращаем PRE_ID - ID предыдущего элемента (NULL если мы самый первый элемент списка)
  IF(I$INDEX IS NOT NULL AND I$INDEX <> 0) THEN
  BEGIN
    IF(NOT EXISTS(
      SELECT FIRST 1 1
      FROM LINKS L506
      WHERE L506.PARENT_ID = :I$PARENT_ID AND L506.OBJ_TYPE_ID = 506 AND L506.DATE_DEL IS NULL AND L506.OBJ_ID = :I$INDEX
    ))
    THEN
      EXCEPTION DATA_ERROR 'Недопустимый индекс элемента расписания, нужная позиция в расписании не найдена или была удалена';
  END

  I$JOB_TITLE_FULL = REPLACE(TRIM(I$JOB_TITLE_FULL), '  ', ' ');

  -- Проверяем уникальность должности в расписании в пределах подразделения
  -- Также нельзя добавлять более одной пустой строки в ШР
  IF(I$JOB_ID IS NOT NULL OR I$JOB_TITLE_FULL IS NOT NULL) THEN N = 1; ELSE N = 0;
  IF((
    SELECT COUNT(*)
    FROM LINKS L506
    JOIN VALR V3491 ON V3491.OBJ_ID = L506.OBJ_ID AND V3491.PARAM_ID = 3491 AND V3491.IS_DEL = 0 AND V3491.VAL = :I$UNIT_ID
    LEFT JOIN VALL V3492 ON V3492.OBJ_ID = L506.OBJ_ID AND V3492.PARAM_ID = 3492 AND V3492.IS_DEL = 0
    LEFT JOIN VALS V3494 ON V3494.OBJ_ID = L506.OBJ_ID AND V3494.PARAM_ID = 3494 AND V3494.IS_DEL = 0
    WHERE L506.PARENT_ID = :I$PARENT_ID AND L506.OBJ_TYPE_ID = 506 AND L506.DATE_DEL IS NULL
      AND V3492.LISTVAL_ID IS NULL AND V3494.VAL IS NULL) > N
  )
  THEN
  BEGIN
    EXCEPTION DATA_ERROR 'Нельзя добавлять более одной пустой строки в одном подразделении';
  END

  IF(I$OBJ_ID IS NOT NULL) THEN
  BEGIN
    -- Достаем текущие значения полей
    SELECT VAL FROM VALR WHERE OBJ_ID = :OBJ_ID AND PARAM_ID = 3498 AND IS_DEL = 0 INTO :V$GROUP_ID;
    SELECT VAL FROM VALR WHERE OBJ_ID = :OBJ_ID AND PARAM_ID = 3492 AND IS_DEL = 0 INTO :V$JOB_ID;
    SELECT VAL FROM VALS WHERE OBJ_ID = :OBJ_ID AND PARAM_ID = 3494 AND IS_DEL = 0 INTO :V$JOB_TITLE_FULL;
    SELECT VAL FROM VALF WHERE OBJ_ID = :OBJ_ID AND PARAM_ID = 3493 AND IS_DEL = 0 INTO :V$RATE;
    SELECT VAL FROM VALF WHERE OBJ_ID = :OBJ_ID AND PARAM_ID = 3495 AND IS_DEL = 0 INTO :V$SALARY_BASE;
    SELECT VAL FROM VALF WHERE OBJ_ID = :OBJ_ID AND PARAM_ID = 3496 AND IS_DEL = 0 INTO :V$SALARY_FULL;
    SELECT VAL FROM VALS WHERE OBJ_ID = :OBJ_ID AND PARAM_ID = 3499 AND IS_DEL = 0 INTO :V$COMMENTS;
    SELECT VAL FROM VALF WHERE OBJ_ID = :OBJ_ID AND PARAM_ID = 3500 AND IS_DEL = 0 INTO :V$EXTRA1;
    SELECT VAL FROM VALF WHERE OBJ_ID = :OBJ_ID AND PARAM_ID = 3501 AND IS_DEL = 0 INTO :V$EXTRA2;
    SELECT VAL FROM VALF WHERE OBJ_ID = :OBJ_ID AND PARAM_ID = 3502 AND IS_DEL = 0 INTO :V$EXTRA3;
  END

  -- Добавление нового элемента, тут всегда автоопределение
  IF(I$OBJ_ID IS NULL) THEN
  BEGIN
    -- Получаем id последнего элемента расписания
    SELECT FIRST 1 L506.OBJ_ID, L506.COST
    FROM LINKS L506
    WHERE L506.PARENT_ID = :I$PARENT_ID AND L506.OBJ_TYPE_ID = 506 AND L506.DATE_DEL IS NULL
    ORDER BY L506.COST DESC
    INTO :V$LAST_ID, :V$LAST_SEQ;
    -- Есть у нас уже записи в этом подразделении ?
    SELECT FIRST 1 L506.OBJ_ID
    FROM LINKS L506
    JOIN VALR V3491 ON V3491.OBJ_ID = L506.OBJ_ID AND V3491.PARAM_ID = 3491 AND V3491.IS_DEL = 0 AND V3491.VAL = :I$UNIT_ID
    WHERE L506.PARENT_ID = :I$PARENT_ID AND L506.OBJ_TYPE_ID = 506 AND L506.DATE_DEL IS NULL
    ORDER BY L506.COST
    INTO :V$UNIT_OBJ_ID;

    IF(V$LAST_ID IS NULL) THEN
    BEGIN
      -- Вообще ничего нет - добавляем в конец = начало
      PRE_ID = 0;
      V$SEQ = 0;
    END
    ELSE IF(V$UNIT_OBJ_ID IS NULL) THEN
    BEGIN
      -- Такого подразделения еще нет - добавляем в самый конец
      PRE_ID = V$LAST_ID;
      V$SEQ = V$LAST_SEQ + 1;
    END
    ELSE
    BEGIN
      -- Подразделение уже есть, надо найти место для вклинивания
      -- Ищем последнюю позицию заданной группы
      SELECT FIRST 1 L506.OBJ_ID, L506.COST
      FROM LINKS L506
      JOIN VALR V3491 ON V3491.OBJ_ID = L506.OBJ_ID AND V3491.PARAM_ID = 3491 AND V3491.IS_DEL = 0 AND V3491.VAL = :I$UNIT_ID
      LEFT JOIN VALR V3498 ON V3498.OBJ_ID = L506.OBJ_ID AND V3498.PARAM_ID = 3498 AND V3498.IS_DEL = 0
      WHERE L506.PARENT_ID = :I$PARENT_ID AND L506.OBJ_TYPE_ID = 506 AND L506.DATE_DEL IS NULL AND (V3498.VAL = :I$GROUP_ID OR (:I$GROUP_ID IS NULL AND V3498.VAL IS NULL))
      ORDER BY L506.COST DESC
      INTO :PRE_ID, :V$SEQ;

      -- Ищем последнюю позицию не-default группы
      SELECT FIRST 1 L506.OBJ_ID, L506.COST
      FROM LINKS L506
      JOIN VALR V3491 ON V3491.OBJ_ID = L506.OBJ_ID AND V3491.PARAM_ID = 3491 AND V3491.IS_DEL = 0 AND V3491.VAL = :I$UNIT_ID
      LEFT JOIN VALR V3498 ON V3498.OBJ_ID = L506.OBJ_ID AND V3498.PARAM_ID = 3498 AND V3498.IS_DEL = 0
      WHERE L506.PARENT_ID = :I$PARENT_ID AND L506.OBJ_TYPE_ID = 506 AND L506.DATE_DEL IS NULL AND V3498.VAL IS NOT NULL
      ORDER BY L506.COST DESC
      INTO :V$GROUP_ID_ND, :V$SEQ_ND;

      -- Ищем последнюю позицию default группы
      SELECT FIRST 1 L506.OBJ_ID, L506.COST
      FROM LINKS L506
      JOIN VALR V3491 ON V3491.OBJ_ID = L506.OBJ_ID AND V3491.PARAM_ID = 3491 AND V3491.IS_DEL = 0 AND V3491.VAL = :I$UNIT_ID
      LEFT JOIN VALR V3498 ON V3498.OBJ_ID = L506.OBJ_ID AND V3498.PARAM_ID = 3498 AND V3498.IS_DEL = 0
      WHERE L506.PARENT_ID = :I$PARENT_ID AND L506.OBJ_TYPE_ID = 506 AND L506.DATE_DEL IS NULL AND V3498.VAL IS NULL
      ORDER BY L506.COST DESC
      INTO :V$GROUP_ID_D, :V$SEQ_D;

      IF(PRE_ID IS NOT NULL) THEN
      BEGIN
        -- Группа уже есть, встаем в конец группы
        V$SEQ = V$SEQ + 1;
      END
      ELSE IF(I$GROUP_ID IS NULL OR V$GROUP_ID_D IS NULL) THEN
      BEGIN
        -- Такой группы нет, и это default группа, либо default группы нет - встаем в конец подразделения
        PRE_ID = COALESCE(V$GROUP_ID_ND, V$GROUP_ID_ND);
        V$SEQ = COALESCE(V$SEQ_ND, V$SEQ_D) + 1;
      END
      ELSE IF(V$GROUP_ID_ND IS NOT NULL) THEN
      BEGIN
        -- Такой группы нет, и это не-default группа и есть default, и одновременно есть и не-default - встаем после последней не-default
        PRE_ID = V$GROUP_ID_ND;
        V$SEQ = V$SEQ_ND + 1;
      END
      ELSE
      BEGIN
        -- Такой группы нет, и это не-default группа и есть default, при этом нет ни одной не-default - встаем в самое начало подразделения
        -- индекс уже известен
        V$SEQ = V$SEQ_D;
        IF(V$SEQ = 0) THEN
        BEGIN
          -- Это первое подразделение в списке, встаем сами в самое начало
          PRE_ID = NULL;
        END
        ELSE
        BEGIN
          -- Есть подразделения перед этим - надо определить PRE_ID, ищем последнюю строку из предыдущих
          SELECT FIRST 1 L506.OBJ_ID
          FROM LINKS L506
          JOIN VALR V3491 ON V3491.OBJ_ID = L506.OBJ_ID AND V3491.PARAM_ID = 3491 AND V3491.IS_DEL = 0 AND V3491.VAL = :I$UNIT_ID
          WHERE L506.PARENT_ID = :I$PARENT_ID AND L506.OBJ_TYPE_ID = 506 AND L506.DATE_DEL IS NULL AND L506.COST < :V$SEQ
          ORDER BY L506.COST DESC
          INTO :PRE_ID;
        END
      END
    END
  END
  ELSE IF(COALESCE(I$GROUP_ID, 0) = COALESCE(V$GROUP_ID, 0)) THEN
  BEGIN
    -- Группа не изменяется, PRE_ID возвращаем 0
    -- тут надо отдельно проверять I$INDEX по части dragdrop
    V$SEQ = NULL;
    PRE_ID = 0;
  END
  ELSE
  BEGIN
    -- Группа изменяется, надо скорректировать расположение. Элемент всегда помещается в конец выбранной группы
    -- но подразделение всегда остается то же, и количество элементов в нем также не меняется
    IF(I$GROUP_ID IS NULL) THEN
    BEGIN
      -- Перемещаем в default группу - это всегда в конец
      -- мы сейчас не в ней, поэтому просто берем самый последний индекс в подразделении
      SELECT FIRST 1 L506.OBJ_ID, L506.COST
      FROM LINKS L506
      JOIN VALR V3491 ON V3491.OBJ_ID = L506.OBJ_ID AND V3491.PARAM_ID = 3491 AND V3491.IS_DEL = 0 AND V3491.VAL = :I$UNIT_ID
      WHERE L506.PARENT_ID = :I$PARENT_ID AND L506.OBJ_TYPE_ID = 506 AND L506.DATE_DEL IS NULL AND L506.OBJ_ID <> :I$OBJ_ID
      ORDER BY L506.COST DESC
      INTO :PRE_ID, :V$SEQ;
    END
    ELSE
    BEGIN
      -- Перемещаем в не-default группу в ее конец
      -- Если группа уже есть - можно к ней обращаться, смотрим последний элемент в ней
      SELECT FIRST 1 L506.OBJ_ID, L506.COST
      FROM LINKS L506
      JOIN VALR V3491 ON V3491.OBJ_ID = L506.OBJ_ID AND V3491.PARAM_ID = 3491 AND V3491.IS_DEL = 0 AND V3491.VAL = :I$UNIT_ID
      JOIN VALR V3498 ON V3498.OBJ_ID = L506.OBJ_ID AND V3498.PARAM_ID = 3498 AND V3498.IS_DEL = 0 AND V3498.VAL = :I$GROUP_ID
      WHERE L506.PARENT_ID = :I$PARENT_ID AND L506.OBJ_TYPE_ID = 506 AND L506.DATE_DEL IS NULL AND L506.OBJ_ID <> :I$OBJ_ID
      ORDER BY L506.COST DESC
      INTO :PRE_ID, :V$SEQ;

      IF(PRE_ID IS NOT NULL) THEN
      BEGIN
        -- Группа уже есть
      END
      ELSE
      BEGIN
        -- Группы нет - пытаемся найти место где она появится
        SELECT FIRST 1 L506.OBJ_ID, L506.COST
        FROM LINKS L506
        JOIN VALR V3491 ON V3491.OBJ_ID = L506.OBJ_ID AND V3491.PARAM_ID = 3491 AND V3491.IS_DEL = 0 AND V3491.VAL = :I$UNIT_ID
        JOIN VALR V3498 ON V3498.OBJ_ID = L506.OBJ_ID AND V3498.PARAM_ID = 3498 AND V3498.IS_DEL = 0 -- только не-default
        WHERE L506.PARENT_ID = :I$PARENT_ID AND L506.OBJ_TYPE_ID = 506 AND L506.DATE_DEL IS NULL AND L506.OBJ_ID <> :I$OBJ_ID
        ORDER BY L506.COST DESC
        INTO :PRE_ID, :V$SEQ;

        -- Если не-default групп вообще нет - встаем самыми первыми по списку
        IF(PRE_ID IS NULL) THEN
        BEGIN
          V$SEQ = 0;
        END
      END
      -- Если не самое начало, то мы добавляемся ПОСЛЕ этого элемента - увеличиваем индекс
      IF(PRE_ID IS NOT NULL) THEN V$SEQ = V$SEQ + 1;
      -- Если мы переезжаем из более ранней позиции списка - корректируем индекс на свою старую позицию
      IF(V$SEQ > V$INDEX) THEN V$SEQ = V$SEQ - 1;
    END
  END

  -- Перенумеровываем все заново, кроме нашего собственного пункта
  IF(V$SEQ IS NOT NULL) THEN
  BEGIN
    V$CI = 0;
    -- Если встаем в самое начало - оставляем нулевой индекс для себя
    IF(PRE_ID IS NULL) THEN V$CI = 1;
    FOR
      SELECT L506.LINK_ID, L506.COST, L506.OBJ_ID
      FROM LINKS L506
      WHERE L506.PARENT_ID = :I$PARENT_ID AND L506.OBJ_TYPE_ID = 506 AND L506.DATE_DEL IS NULL AND (L506.OBJ_ID <> :I$OBJ_ID OR :I$OBJ_ID IS NULL)
      ORDER BY 2
      INTO :V$ID, :V$SEQ_ND, :V$GROUP_ID_ND
    DO
    BEGIN
      IF(V$SEQ_ND <> V$CI) THEN
      BEGIN
        UPDATE LINKS SET COST = :V$CI WHERE LINK_ID = :V$ID;
      END
      V$CI = V$CI + 1;
      -- Когда достигли позиции, за которой будем становиться - резервируем место под себя
      IF(V$GROUP_ID_ND = PRE_ID) THEN V$CI = V$CI + 1;
      N = 1;
    END
  END

  IF(I$OBJ_ID IS NULL) THEN
  BEGIN
    -- Вообще все новое, добавляем с нужным значением COST
    SELECT OBJ_ID, LINK_ID
    FROM OBJECT_ADD(:I$PARENT_ID, 506, NULL, NULL, :I$USER_ID, :V$SEQ)
    INTO :OBJ_ID, :V$LINK_ID;

    -- UNIT_ID сохраняется только при добавлении, измениться не может
    SELECT 1 FROM VAL_ADD(3491, :OBJ_ID, :I$UNIT_ID, :I$USER_ID) INTO :V$ID;
  END
  ELSE IF(V$SEQ IS NOT NULL AND V$INDEX <> V$SEQ) THEN
  BEGIN
    -- Обновляем себя, если индекс поменялся
    UPDATE LINKS SET COST = :V$SEQ WHERE LINK_ID = :V$LINK_ID;
  END

  -- Сохраняем только изменившиеся поля
  IF(COALESCE(I$GROUP_ID, 0) <> COALESCE(V$GROUP_ID, 0)) THEN
    SELECT 1 FROM VAL_ADD(3498, :OBJ_ID, :I$GROUP_ID, :I$USER_ID) INTO :V$ID;
  IF(COALESCE(I$JOB_ID, 0) <> COALESCE(V$JOB_ID, 0)) THEN
    SELECT 1 FROM VAL_ADD(3492, :OBJ_ID, :I$JOB_ID, :I$USER_ID) INTO :V$ID;
  IF(COALESCE(I$JOB_TITLE_FULL, '') <> COALESCE(V$JOB_TITLE_FULL, '')) THEN
    SELECT 1 FROM VAL_ADD(3494, :OBJ_ID, :I$JOB_TITLE_FULL, :I$USER_ID) INTO :V$ID;
  IF(COALESCE(I$RATE, 0) <> COALESCE(V$RATE, 0)) THEN
    SELECT 1 FROM VAL_ADD(3493, :OBJ_ID, :I$RATE, :I$USER_ID) INTO :V$ID;
  IF(COALESCE(I$SALARY_BASE, 0) <> COALESCE(V$SALARY_BASE, 0)) THEN
    SELECT 1 FROM VAL_ADD(3495, :OBJ_ID, :I$SALARY_BASE, :I$USER_ID) INTO :V$ID;
  IF(COALESCE(I$SALARY_FULL, 0) <> COALESCE(V$SALARY_FULL, 0)) THEN
    SELECT 1 FROM VAL_ADD(3496, :OBJ_ID, :I$SALARY_FULL, :I$USER_ID) INTO :V$ID;
  IF(COALESCE(I$EXTRA1, 0) <> COALESCE(V$EXTRA1, 0)) THEN
    SELECT 1 FROM VAL_ADD(3500, :OBJ_ID, :I$EXTRA1, :I$USER_ID) INTO :V$ID;
  IF(COALESCE(I$EXTRA2, 0) <> COALESCE(V$EXTRA2, 0)) THEN
    SELECT 1 FROM VAL_ADD(3501, :OBJ_ID, :I$EXTRA2, :I$USER_ID) INTO :V$ID;
  IF(COALESCE(I$EXTRA3, 0) <> COALESCE(V$EXTRA3, 0)) THEN
    SELECT 1 FROM VAL_ADD(3502, :OBJ_ID, :I$EXTRA3, :I$USER_ID) INTO :V$ID;
  IF(COALESCE(I$COMMENTS, '') <> COALESCE(V$COMMENTS, '')) THEN
    SELECT 1 FROM VAL_ADD(3499, :OBJ_ID, :I$COMMENTS, :I$USER_ID) INTO :V$ID;

  SUSPEND;
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE JOB_POS_SINGLE_VAL (
    I$PARENT_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$FIELD INTEGER,
    I$VAL VARCHAR(1000),
    I$USER_ID VARCHAR(40))
RETURNS (
    OBJ_ID BIGINT)
AS
DECLARE VARIABLE V$STATUS BIGINT;
DECLARE VARIABLE S VARCHAR(1000);
DECLARE VARIABLE V DOUBLE PRECISION;
DECLARE VARIABLE VV DOUBLE PRECISION;
begin

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  SELECT FIRST 1 L506.OBJ_ID, V3490.LISTVAL_ID
  FROM LINKS L506
  JOIN VALL V3490 ON V3490.OBJ_ID = L506.PARENT_ID AND V3490.PARAM_ID = 3490 AND V3490.IS_DEL = 0
  WHERE L506.PARENT_ID = :I$PARENT_ID AND L506.OBJ_ID = :I$OBJ_ID AND L506.DATE_DEL IS NULL
  INTO :OBJ_ID, :V$STATUS;

  IF(V$STATUS IS NULL) THEN EXCEPTION DATA_ERROR 'Запись штатного расписания не найдена или была удалена';
  IF(V$STATUS <> 11716) THEN EXCEPTION DATA_ERROR 'Изменять штатное расписание можно только в статусе Проект';

  IF(I$FIELD = 1) THEN I$FIELD = 3494;
  ELSE IF(I$FIELD = 2) THEN I$FIELD = 3493;
  ELSE IF(I$FIELD = 3) THEN I$FIELD = 3495;
  ELSE IF(I$FIELD = 4) THEN I$FIELD = 3500;
  ELSE IF(I$FIELD = 5) THEN I$FIELD = 3501;
  ELSE IF(I$FIELD = 6) THEN I$FIELD = 3502;
  ELSE IF(I$FIELD = 8) THEN I$FIELD = 3499;
  ELSE EXCEPTION DATA_ERROR 'Недопустимое поле';

  IF(I$FIELD IN (3494, 3499)) THEN
  BEGIN
    SELECT V.VAL
    FROM VALS V
    WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = :I$FIELD AND V.IS_DEL = 0
    INTO :S;

    IF(COALESCE(S, '') <> COALESCE(:I$VAL, '')) THEN
    SELECT 1 FROM VAL_ADD(:I$FIELD, :I$OBJ_ID, :I$VAL, :I$USER_ID) INTO :V$STATUS;
  END
  ELSE
  BEGIN
    VV = REPLACE(I$VAL, ',', '.');

    SELECT V.VAL
    FROM VALF V
    WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = :I$FIELD AND V.IS_DEL = 0
    INTO :V;

    IF(COALESCE(V, -1) <> COALESCE(VV, -1)) THEN
    BEGIN
      SELECT 1 FROM VAL_ADD(:I$FIELD, :I$OBJ_ID, :VV, :I$USER_ID) INTO :V$STATUS;

      -- Обновляем общий итог
      VV = NULL;
      SELECT SUM(V.VAL)
      FROM VALF V
      WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID IN (3495, 3500, 3501, 3502) AND V.IS_DEL = 0
      INTO :VV;

      SELECT 1 FROM VAL_ADD(3496, :I$OBJ_ID, :VV, :I$USER_ID) INTO :V$STATUS;
    END
  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE KONTINGENT_DOC_ADD (
    I$PUPIL_ID BIGINT,
    I$TYPE_CODE SMALLINT,
    I$SERIES VARCHAR(50),
    I$NUMERAL VARCHAR(50),
    I$ACT_NUMBER VARCHAR(50),
    I$ISSUE_DATE DATE,
    I$ISSUER VARCHAR(1000),
    I$EXPIRED_DATE DATE,
    I$DELETED SMALLINT = 0)
RETURNS (
    CODE VARCHAR(3000))
AS
declare variable V$OBJ_ID bigint;
declare variable V$BLOB_ID bigint;
declare variable V$LANG_CODE varchar(2);
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = 1
    INTO :V$LANG_CODE;

    SELECT FIRST 1
           L79.OBJ_ID
    FROM LINKS L79

    JOIN VALL V441
    ON V441.OBJ_ID = L79.OBJ_ID
    AND V441.PARAM_ID = 441
    AND V441.IS_DEL = 0

    JOIN LISTVALS LV441
    ON LV441.LISTVAL_ID = V441.LISTVAL_ID
    AND LV441.TAG = :I$TYPE_CODE

    JOIN VALS V442
    ON V442.OBJ_ID = L79.OBJ_ID
    AND V442.PARAM_ID = 442
    AND V442.IS_DEL = 0
    AND V442.VAL LIKE :I$SERIES

    JOIN VALS V559
    ON V559.OBJ_ID = L79.OBJ_ID
    AND V559.PARAM_ID = 559
    AND V559.IS_DEL = 0
    AND V559.VAL LIKE :I$NUMERAL

    WHERE L79.PARENT_ID = :I$PUPIL_ID
    AND L79.OBJ_TYPE_ID = 79
    AND L79.DATE_DEL IS NULL

    INTO :V$OBJ_ID;

    IF ((V$OBJ_ID IS NULL) AND (I$DELETED = 0) AND EXISTS(SELECT L.LISTVAL_ID FROM LISTVALS L WHERE L.LIST_ID = 143 AND L.TAG = :I$TYPE_CODE)) THEN
    BEGIN
        SELECT OBJ_ID
        FROM OBJECT_ADD(:I$PUPIL_ID, 79)
        INTO :V$OBJ_ID;

        SELECT BLOB_ID
        FROM VAL_ADD(441, :V$OBJ_ID, (SELECT L.LISTVAL_ID FROM LISTVALS L WHERE L.LIST_ID = 143 AND L.TAG = :I$TYPE_CODE))
        INTO :V$BLOB_ID;

        IF (I$SERIES IS NOT NULL) THEN
        BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD(442, :V$OBJ_ID, :I$SERIES)
            INTO :V$BLOB_ID;
        END

        IF (I$NUMERAL IS NOT NULL) THEN
        BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD(559, :V$OBJ_ID, :I$NUMERAL)
            INTO :V$BLOB_ID;
        END

        IF (I$ISSUE_DATE IS NOT NULL) THEN
        BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD(560, :V$OBJ_ID, :I$ISSUE_DATE)
            INTO :V$BLOB_ID;
        END

        IF (I$ISSUER IS NOT NULL) THEN
        BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD(562, :V$OBJ_ID, :I$ISSUER)
            INTO :V$BLOB_ID;
        END

        IF (I$EXPIRED_DATE IS NOT NULL) THEN
        BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD(561, :V$OBJ_ID, :I$EXPIRED_DATE)
            INTO :V$BLOB_ID;
        END

        CODE = 'Добавлен документ "' || (SELECT R.VAL FROM LISTVALS L LEFT JOIN RES_GET(L.RES_ID, :V$LANG_CODE) R ON 1=1 WHERE L.LIST_ID = 143 AND L.TAG = :I$TYPE_CODE) || '" серия ' || :I$SERIES || ' номер ' || :I$NUMERAL || ' выдан ' || I$ISSUE_DATE || ' ' || I$ISSUER;
        SUSPEND;
    END
    ELSE IF ((V$OBJ_ID IS NOT NULL) AND (I$DELETED = 1)) THEN
    BEGIN
        UPDATE LINKS SET DATE_DEL = CURRENT_TIMESTAMP
        WHERE PARENT_ID = :I$PUPIL_ID
        AND OBJ_ID = :V$OBJ_ID;

        CODE = 'Удален документ "' || (SELECT R.VAL FROM LISTVALS L LEFT JOIN RES_GET(L.RES_ID, :V$LANG_CODE) R ON 1=1 WHERE L.LIST_ID = 143 AND L.TAG = :I$TYPE_CODE) || '" серия ' || :I$SERIES || ' номер ' || :I$NUMERAL || ' выдан ' || I$ISSUE_DATE || ' ' || I$ISSUER;
        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE KONTINGENT_EMPLOYEES_EXPORT (
    I$SCHOOL_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    TAG_NAME VARCHAR(255),
    VAL VARCHAR(4000))
AS
declare variable V$PUPIL_ID bigint;
BEGIN
    FOR
        SELECT L14.OBJ_ID
        FROM LINKS L2

        JOIN LINKS L14
        ON L14.PARENT_ID = L2.OBJ_ID
        AND L14.OBJ_TYPE_ID = 14
        AND L14.DATE_DEL IS NULL

        WHERE ((L2.PARENT_ID IS NULL) OR (L2.PARENT_TYPE_ID IN (111, 112)))
        AND L2.OBJ_TYPE_ID = 2
        AND L2.DATE_DEL IS NULL
        AND L2.OBJ_ID = :I$SCHOOL_ID

        INTO :V$PUPIL_ID
    DO
    BEGIN
        FOR
            SELECT TAG_NAME,
                   VAL
            FROM KONTINGENT_EMPLOYEE_EXPORT(:V$PUPIL_ID, :I$SCHOOL_ID, :I$USER_ID)
            INTO :TAG_NAME,
                 :VAL
        DO
        BEGIN
            SUSPEND;
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE KONTINGENT_EMPLOYEE_EXPORT (
    I$EMPLOYEE_ID BIGINT,
    I$SCHOOL_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    TAG_NAME VARCHAR(255),
    VAL VARCHAR(4000))
AS
declare variable V$OBJ_ID bigint;
declare variable V$OBJ_ID2 bigint;
declare variable V$RES_ID bigint;
declare variable V$LANG_CODE varchar(2);
declare variable V$STR varchar(1000);
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :V$LANG_CODE;

    TAG_NAME = 'employee:person:externalKey';
    VAL = I$EMPLOYEE_ID;
    SUSPEND;

    FOR
        SELECT L15.OBJ_ID
        FROM LINKS L15

        WHERE L15.PARENT_ID = :I$EMPLOYEE_ID
        AND L15.OBJ_TYPE_ID = 15
        AND L15.DATE_DEL IS NULL

        INTO :V$OBJ_ID
    DO
    BEGIN
        VAL = V$OBJ_ID;
        TAG_NAME = 'employee:job:externalKey';
        SUSPEND;

        VAL = I$SCHOOL_ID;
        TAG_NAME = 'employee:job:institution:externalKey';
        SUSPEND;

/*        SELECT IIF(V <> '', EXTRACT(YEAR FROM D) || '-' ||
               IIF(EXTRACT(MONTH FROM D) < 10,0,'') || EXTRACT(MONTH FROM D) || '-' ||
               IIF(EXTRACT(DAY FROM D) < 10,0,'') || EXTRACT(DAY FROM D), '')
        FROM VAL_GET(:V$OBJ_ID, 73)
        INTO :VAL;
        IF (VAL <> '') THEN
        BEGIN
            TAG_NAME = 'employee:job:employmentDate';
            SUSPEND;
        END

        SELECT IIF(V <> '', EXTRACT(YEAR FROM D) || '-' ||
               IIF(EXTRACT(MONTH FROM D) < 10,0,'') || EXTRACT(MONTH FROM D) || '-' ||
               IIF(EXTRACT(DAY FROM D) < 10,0,'') || EXTRACT(DAY FROM D), '')
        FROM VAL_GET(:V$OBJ_ID, 74)
        INTO :VAL;
        IF (VAL <> '') THEN
        BEGIN
            TAG_NAME = 'employee:job:dismissDate';
            SUSPEND;
        END

        SELECT V
        FROM VAL_GET(:V$OBJ_ID, 458)
        INTO :VAL;
        IF (VAL <> '') THEN
        BEGIN
            TAG_NAME = 'employee:job:dismissDocumentText';
            SUSPEND;
        END*/

        FOR
            SELECT V69.VAL

            FROM VALR V69

            WHERE V69.OBJ_ID = :V$OBJ_ID
            AND V69.PARAM_ID = 69
            AND V69.IS_DEL = 0

            INTO :V$OBJ_ID2
        DO
        BEGIN
            FOR
                SELECT CAST(LV58.COST AS INT), R.VAL
                FROM VALL V58
        
                JOIN LISTVALS LV58
                ON LV58.LISTVAL_ID = V58.LISTVAL_ID
                AND LV58.COST > 0
        
                LEFT JOIN RES_GET(LV58.RES_ID, :V$LANG_CODE) R ON 1=1
    
                WHERE V58.OBJ_ID = :V$OBJ_ID2
                AND V58.PARAM_ID = 58
                AND V58.IS_DEL = 0
        
                INTO :VAL, :V$STR
            DO
            BEGIN
                TAG_NAME = 'employee:job:employment:positionType:code';
                SUSPEND;
    
                TAG_NAME = 'employee:job:employment:positionType:name';
                VAL = V$STR;
                SUSPEND;
            END
        END

        SELECT IIF(V <> '', EXTRACT(YEAR FROM D) || '-' ||
               IIF(EXTRACT(MONTH FROM D) < 10,0,'') || EXTRACT(MONTH FROM D) || '-' ||
               IIF(EXTRACT(DAY FROM D) < 10,0,'') || EXTRACT(DAY FROM D), '')
        FROM VAL_GET(:V$OBJ_ID, 73)
        INTO :VAL;
        IF (VAL <> '') THEN
        BEGIN
            TAG_NAME = 'employee:job:employment:positionStartDate';
            SUSPEND;
        END

        SELECT IIF(V <> '', EXTRACT(YEAR FROM D) || '-' ||
               IIF(EXTRACT(MONTH FROM D) < 10,0,'') || EXTRACT(MONTH FROM D) || '-' ||
               IIF(EXTRACT(DAY FROM D) < 10,0,'') || EXTRACT(DAY FROM D), '')
        FROM VAL_GET(:V$OBJ_ID, 74)
        INTO :VAL;
        IF (VAL <> '') THEN
        BEGIN
            TAG_NAME = 'employee:job:employment:positionEndDate';
            SUSPEND;
        END
    END

    -- Квалификационная категория по основной должности (теперь берем из должности)
    FOR
        SELECT FIRST 1 LV.TAG, LV.RES_ID
        FROM LINKS L14_15
        JOIN LINKS L13_15 ON L13_15.OBJ_ID = L14_15.OBJ_ID AND L13_15.PARENT_TYPE_ID = 13 AND L13_15.DATE_DEL IS NULL
        -- только основная должность
        JOIN VALL V72 ON V72.OBJ_ID = L14_15.OBJ_ID AND V72.PARAM_ID = 72 AND V72.IS_DEL = 0 AND V72.LISTVAL_ID = 934
        -- числится на должности
        LEFT JOIN VALD V74 ON V74.OBJ_ID = L14_15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
        -- категория по должности
        JOIN VALL V1790 ON V1790.OBJ_ID = L14_15.OBJ_ID AND V1790.PARAM_ID = 1790 AND V1790.IS_DEL = 0
        -- перекодирование категории из LISTVALS
        JOIN LISTVALS LV ON LV.LISTVAL_ID = V1790.LISTVAL_ID AND LV.LIST_ID = 90 AND LV.IS_DEL = 0
        WHERE L14_15.PARENT_ID = :V$OBJ_ID AND L14_15.OBJ_TYPE_ID = 15 AND L14_15.DATE_DEL IS NULL AND (V74.VAL IS NULL OR V74.VAL > CURRENT_TIMESTAMP)
        INTO :VAL, :V$RES_ID
    DO
    BEGIN
        TAG_NAME = 'employee:job:employment:qualificationCategory:code';
        SUSPEND;

        TAG_NAME = 'employee:job:employment:qualificationCategory:name';
        SELECT VAL
        FROM RES_GET(:V$RES_ID, :V$LANG_CODE)
        INTO :VAL;
        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE KONTINGENT_EXPORT_PROP_SET (
    FTP_ADDRESS VARCHAR(100),
    FTP_PORT VARCHAR(100),
    FTP_LOGIN VARCHAR(100),
    FTP_PWD VARCHAR(100),
    FTP_MODE VARCHAR(100),
    EXPORT_INTERVAL VARCHAR(100))
AS
BEGIN
    UPDATE OR INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
    VALUES ('KONTINGENT_FTP_ADDRESS', 'KONTINGENT_FTP_ADDRESS', :FTP_ADDRESS)
    MATCHING (INFO_CODE);

    UPDATE OR INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
    VALUES ('KONTINGENT_FTP_PORT', 'KONTINGENT_FTP_PORT', :FTP_PORT)
    MATCHING (INFO_CODE);

    UPDATE OR INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
    VALUES ('KONTINGENT_FTP_LOGIN', 'KONTINGENT_FTP_LOGIN', :FTP_LOGIN)
    MATCHING (INFO_CODE);

    UPDATE OR INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
    VALUES ('KONTINGENT_FTP_PWD', 'KONTINGENT_FTP_PWD', :FTP_PWD)
    MATCHING (INFO_CODE);

    UPDATE OR INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
    VALUES ('KONTINGENT_FTP_MODE', 'KONTINGENT_FTP_MODE', :FTP_MODE)
    MATCHING (INFO_CODE);

    UPDATE OR INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
    VALUES ('KONTINGENT_EXPORT_INTERVAL', 'KONTINGENT_EXPORT_INTERVAL', :EXPORT_INTERVAL)
    MATCHING (INFO_CODE);
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE KONTINGENT_FILEUPDATE_GET (
    I$FILEUPDATE VARCHAR(1000))
RETURNS (
    VAL VARCHAR(20))
AS
BEGIN
    SELECT INFO_VAL
    FROM INFO
    WHERE INFO_CODE LIKE 'KONTINGENT_FILEUPDATE=' || :I$FILEUPDATE
    INTO : VAL;

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE KONTINGENT_FILEUPDATE_SET (
    I$FILEUPDATE VARCHAR(1000))
AS
declare variable V$PUPIL_ID bigint;
BEGIN
    UPDATE INFO SET INFO_VAL = CURRENT_TIMESTAMP
    WHERE INFO_CODE = 'KONTINGENT_FILEUPDATE=' || :I$FILEUPDATE;

   IF (ROW_COUNT = 0) THEN
   BEGIN
      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('KONTINGENT_FILEUPDATE=' || :I$FILEUPDATE, 'KONTINGENT_FILEUPDATE=' || :I$FILEUPDATE, CURRENT_TIMESTAMP);
   END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE KONTINGENT_LAST_EXPORT_DATE_SET (
    I$DT TIMESTAMP)
AS
BEGIN
    UPDATE OR INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
    VALUES ('KONTINGENT_LAST_EXPORT_DATE', 'KONTINGENT_LAST_EXPORT_DATE', :I$DT)
    MATCHING (INFO_CODE);
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE KONTINGENT_OOOD_EXPORT (
    I$SCHOOL_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    TAG_NAME VARCHAR(255),
    VAL VARCHAR(4000))
AS
DECLARE VARIABLE V$SCHOOL_ID BIGINT;
DECLARE VARIABLE V$FROM_ID BIGINT;
DECLARE VARIABLE V$TO_ID BIGINT;
DECLARE VARIABLE V$MONITORING_ID BIGINT;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$OBJ_ID2 BIGINT;
DECLARE VARIABLE V$TYPE_ID BIGINT;
DECLARE VARIABLE V$I BIGINT;
DECLARE VARIABLE V$I2 BIGINT;
DECLARE VARIABLE V$S VARCHAR(1000);
DECLARE VARIABLE V$LANG_CODE VARCHAR(2);
DECLARE VARIABLE V$STR VARCHAR(1000);
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :V$LANG_CODE;

    FOR
        SELECT L2.OBJ_ID,
               L162.OBJ_ID
        FROM LINKS L2

        JOIN LINKS L162
        ON L162.PARENT_ID = L2.OBJ_ID
        AND L162.OBJ_TYPE_ID = 162
        AND L162.DATE_DEL IS NULL

        WHERE ((L2.PARENT_ID IS NULL) OR (L2.PARENT_TYPE_ID IN (111, 112)))
        AND L2.OBJ_TYPE_ID = 2
        AND L2.DATE_DEL IS NULL
        AND L2.OBJ_ID = :I$SCHOOL_ID

        INTO :V$SCHOOL_ID,
             :V$MONITORING_ID
    DO
    BEGIN
        TAG_NAME = 'institution:externalKey';
        VAL = V$SCHOOL_ID;
        SUSPEND;

        SELECT V
        FROM VAL_GET(:V$SCHOOL_ID, 2)
        INTO :VAL;
        IF (VAL <> '') THEN
        BEGIN
            TAG_NAME = 'institution:name';
            SUSPEND;
        END

        SELECT V
        FROM VAL_GET(:V$SCHOOL_ID, 5)
        INTO :VAL;
        IF (VAL <> '') THEN
        BEGIN
            TAG_NAME = 'institution:fullName';
            SUSPEND;
        END

        SELECT V
        FROM VAL_GET(:V$SCHOOL_ID, 999)
        INTO :VAL;
        IF (VAL <> '') THEN
        BEGIN
            TAG_NAME = 'institution:additionalName';
            SUSPEND;
        END
    
        SELECT V
        FROM VAL_GET(:V$SCHOOL_ID, 27)
        INTO :VAL;
        IF (VAL <> '') THEN
        BEGIN
            TAG_NAME = 'institution:legalAddress:name';
            SUSPEND;
        END

        SELECT V
        FROM VAL_GET(:V$SCHOOL_ID, 9)
        INTO :VAL;
        IF (VAL <> '') THEN
        BEGIN
            TAG_NAME = 'institution:ogrn';
            SUSPEND;
        END

        SELECT V
        FROM VAL_GET(:V$SCHOOL_ID, 33)
        INTO :VAL;
        IF (VAL <> '') THEN
        BEGIN
            TAG_NAME = 'institution:inn';
            SUSPEND;
        END

        SELECT V
        FROM VAL_GET(:V$SCHOOL_ID, 34)
        INTO :VAL;
        IF (VAL <> '') THEN
        BEGIN
            TAG_NAME = 'institution:kpp';
            SUSPEND;
        END

        SELECT V
        FROM VAL_GET(:V$SCHOOL_ID, 18)
        INTO :VAL;
        IF (VAL <> '') THEN
        BEGIN
            TAG_NAME = 'institution:okato';
            SUSPEND;
        END

        SELECT V
        FROM VAL_GET(:V$SCHOOL_ID, 2440)
        INTO :VAL;
        IF (VAL <> '') THEN
        BEGIN
            TAG_NAME = 'institution:oktmo';
            SUSPEND;
        END

        SELECT V
        FROM VAL_GET(:V$SCHOOL_ID, 21)
        INTO :VAL;
        IF (VAL <> '') THEN
        BEGIN
            TAG_NAME = 'institution:okfs';
            SUSPEND;
        END

        SELECT V
        FROM VAL_GET(:V$SCHOOL_ID, 20)
        INTO :VAL;
        IF (VAL <> '') THEN
        BEGIN
            TAG_NAME = 'institution:okved';
            SUSPEND;
        END

        SELECT V
        FROM VAL_GET(:V$SCHOOL_ID, 22)
        INTO :VAL;
        IF (VAL <> '') THEN
        BEGIN
            TAG_NAME = 'institution:okopf';
            SUSPEND;
        END

        SELECT V
        FROM VAL_GET(:V$SCHOOL_ID, 19)
        INTO :VAL;
        IF (VAL <> '') THEN
        BEGIN
            TAG_NAME = 'institution:okogu';
            SUSPEND;
        END

        SELECT F || ' ' || I || ' ' || O
        FROM R_SPB_POST_DIRECTOR(:V$SCHOOL_ID, 1)
        INTO VAL;
        IF (VAL <> '') THEN
        BEGIN
            TAG_NAME = 'institution:head';
            SUSPEND;
        END

        SELECT V
        FROM VAL_GET(:V$SCHOOL_ID, 36)
        INTO :VAL;
        IF (VAL <> '') THEN
        BEGIN
            TAG_NAME = 'institution:siteUrl';
            SUSPEND;
        END

        SELECT V
        FROM VAL_GET(:V$SCHOOL_ID, 35)
        INTO :VAL;
        IF (VAL <> '') THEN
        BEGIN
            TAG_NAME = 'institution:email';
            SUSPEND;
        END

        SELECT V
        FROM VAL_GET(:V$SCHOOL_ID, 29)
        INTO :VAL;
        IF (VAL <> '') THEN
        BEGIN
            TAG_NAME = 'institution:phone';
            SUSPEND;
        END

        FOR
            SELECT LV2371.TAG, LV2371.RES_ID
            FROM VALL V2371
    
            JOIN LISTVALS LV2371
            ON LV2371.LISTVAL_ID = V2371.LISTVAL_ID
    
            WHERE V2371.OBJ_ID = :V$OBJ_ID
            AND V2371.PARAM_ID = 2371
            AND V2371.IS_DEL = 0
    
            INTO :VAL, :V$I
        DO
        BEGIN
            TAG_NAME = 'institution:status:code';
            SUSPEND;

            TAG_NAME = 'institution:status:name';
            SELECT VAL
            FROM RES_GET(:V$I, 'RU')
            INTO :VAL;
            SUSPEND;
        END

        SELECT CASE I
            WHEN 5424 THEN 1
            WHEN 5425 THEN 11
            WHEN 5426 THEN 12
            WHEN 5427 THEN 14
            WHEN 5428 THEN 15
            WHEN 5429 THEN 16
            WHEN 5430 THEN 17
            WHEN 5432 THEN 23
            WHEN 5435 THEN 21
            WHEN 5433 THEN 22
            WHEN 5434 THEN 22
            ELSE 0
        END
        FROM VAL_GET(:V$SCHOOL_ID, 1890)
        INTO :V$I;
        IF (V$I > 0) THEN
        BEGIN
            IF (V$I = 12) THEN
            BEGIN
                SELECT I
                FROM VAL_GET(:V$SCHOOL_ID, 11)
                INTO :V$I2;

                IF (V$I2 = 978) THEN
                BEGIN
                    V$I = 13;
                END
                ELSE
                BEGIN   
                    SELECT V
                    FROM VAL_GET(:V$SCHOOL_ID, 937)
                    INTO :V$S;

                    IF (V$S LIKE '%для глухих детей%') THEN
                    BEGIN
                        V$I = 1301;
                    END
                    ELSE IF (V$S LIKE '%для слабослышащих и позднооглохших детей%') THEN
                    BEGIN
                        V$I = 1302;
                    END
                    ELSE IF (V$S LIKE '%для слепых детей%') THEN
                    BEGIN
                        V$I = 1304;
                    END
                    ELSE IF (V$S LIKE '%для слабовидящих и поздноослепших детей%') THEN
                    BEGIN
                        V$I = 1305;
                    END
                    ELSE IF (V$S LIKE '%для детей с тяжелыми нарушениями речи%') THEN
                    BEGIN
                        V$I = 1306;
                    END
                    ELSE IF (V$S LIKE '%для детей с нарушением опорно-двигательного аппарата%') THEN
                    BEGIN
                        V$I = 1307;
                    END
                    ELSE IF (V$S LIKE '%для детей с задержкой психического развития%') THEN
                    BEGIN
                        V$I = 1308;
                    END
                    ELSE IF (V$S LIKE '%для умственно отсталых детей%') THEN
                    BEGIN
                        V$I = 1309;
                    END
                END
            END
            IF (V$I > 0) THEN
            BEGIN
                VAL = V$I;
                TAG_NAME = 'institution:type:code';
                SUSPEND;

                VAL = CASE V$I
                    WHEN 1 THEN 'Образовательные организации'
                    WHEN 11 THEN 'Дошкольная образовательная организация'
                    WHEN 12 THEN 'Общеобразовательная организация'
                    WHEN 13 THEN 'Общеобразовательная организация, осуществляющая образовательную деятельность по адаптированным основным общеобразовательным программам'
                    WHEN 1301 THEN 'Общеобразовательная организация, осуществляющая образовательную деятельность по адаптированным основным общеобразовательным программам для глухих'
                    WHEN 1302 THEN 'Общеобразовательная организация, осуществляющая образовательную деятельность по адаптированным основным общеобразовательным программам для слабослышащих'
                    WHEN 1303 THEN 'Общеобразовательная организация, осуществляющая образовательную деятельность по адаптированным основным общеобразовательным программам для позднооглохших'
                    WHEN 1304 THEN 'Общеобразовательная организация, осуществляющая образовательную деятельность по адаптированным основным общеобразовательным программам для слепых'
                    WHEN 1305 THEN 'Общеобразовательная организация, осуществляющая образовательную деятельность по адаптированным основным общеобразовательным программам для слабовидящих'
                    WHEN 1306 THEN 'Общеобразовательная организация, осуществляющая образовательную деятельность по адаптированным основным общеобразовательным программам с тяжелыми нарушениями речи'
                    WHEN 1307 THEN 'Общеобразовательная организация, осуществляющая образовательную деятельность по адаптированным основным общеобразовательным программам с нарушениями опорно-двигательного аппарата'
                    WHEN 1308 THEN 'Общеобразовательная организация, осуществляющая образовательную деятельность по адаптированным основным общеобразовательным программам с задержкой психического развития'
                    WHEN 1309 THEN 'Общеобразовательная организация, осуществляющая образовательную деятельность по адаптированным основным общеобразовательным программам с умственной отсталостью'
                    WHEN 1310 THEN 'Общеобразовательная организация, осуществляющая образовательную деятельность по адаптированным основным общеобразовательным программам с расстройствами аутистического спектра'
                    WHEN 1311 THEN 'Общеобразовательная организация, осуществляющая образовательную деятельность по адаптированным основным общеобразовательным программам со сложными дефектами'
                    WHEN 1312 THEN 'Общеобразовательная организация, осуществляющая образовательную деятельность по адаптированным основным общеобразовательным программам для других обучающихся с ограниченными возможностями здоровья'
                    WHEN 14 THEN 'Профессиональная образовательная организация'
                    WHEN 15 THEN 'Образовательная организация высшего образования'
                    WHEN 16 THEN 'Организация дополнительного образования'
                    WHEN 17 THEN 'Организация дополнительного профессионального образования'
                    WHEN 21 THEN 'Научная организация'
                    WHEN 22 THEN 'Центр психолого-педагогической, медицинской и социальной помощи'
                    WHEN 23 THEN 'Организация для детей-сирот и детей, оставшихся без попечения родителей'
                END;
                TAG_NAME = 'institution:type:name';
                SUSPEND;
            END
        END
        FOR
            SELECT FIRST 1
                   L17.OBJ_ID
            FROM LINKS L17

            JOIN VALL V471
            ON V471.OBJ_ID = L17.OBJ_ID
            AND V471.PARAM_ID = 471
            AND V471.IS_DEL = 0
            AND V471.LISTVAL_ID IN (1052, 18624)

            JOIN VALD V482
            ON V482.OBJ_ID = L17.OBJ_ID
            AND V482.PARAM_ID = 482
            AND V482.IS_DEL = 0

            LEFT JOIN VALD V483
            ON V483.OBJ_ID = L17.OBJ_ID
            AND V483.PARAM_ID = 483
            AND V483.IS_DEL = 0

            WHERE L17.PARENT_ID = :V$SCHOOL_ID
            AND L17.OBJ_TYPE_ID = 17
            AND L17.DATE_DEL IS NULL
            AND ((V483.VAL IS NULL) OR (V483.VAL > CURRENT_DATE))

            ORDER BY V482.VAL DESC
            INTO :V$OBJ_ID
        DO
        BEGIN
            SELECT V
            FROM VAL_GET(:V$OBJ_ID, 479)
            INTO :VAL;
            IF (VAL <> '') THEN
            BEGIN
                TAG_NAME = 'institution:license:series';
                SUSPEND;
            END

            SELECT V
            FROM VAL_GET(:V$OBJ_ID, 480)
            INTO :VAL;
            IF (VAL <> '') THEN
            BEGIN
                TAG_NAME = 'institution:license:number';
                SUSPEND;
            END

            SELECT EXTRACT(YEAR FROM D) || '-' ||
                   IIF(EXTRACT(MONTH FROM D) < 10,0,'') || EXTRACT(MONTH FROM D) || '-' ||
                   IIF(EXTRACT(DAY FROM D) < 10,0,'') || EXTRACT(DAY FROM D)
            FROM VAL_GET(:V$OBJ_ID, 482)
            INTO :VAL;
            IF (VAL <> '') THEN
            BEGIN
                TAG_NAME = 'institution:license:issueDate';
                SUSPEND;
            END

            SELECT V
            FROM VAL_GET(:V$OBJ_ID, 481)
            INTO :VAL;
            IF (VAL <> '') THEN
            BEGIN
                TAG_NAME = 'institution:license:issuedBy';
                SUSPEND;
            END

            SELECT V
            FROM VAL_GET(:V$OBJ_ID, 483)
            INTO :VAL;
            IF (VAL <> '') THEN
            BEGIN
                TAG_NAME = 'institution:license:expirationDate:date';
                SUSPEND;
            END
        END

        SELECT V
        FROM VAL_GET(:V$MONITORING_ID, 1433)
        INTO :VAL;
        IF (VAL <> '') THEN
        BEGIN
            TAG_NAME = 'institution:occupiedPlace';
            SUSPEND;
        END

        SELECT V
        FROM VAL_GET(:V$MONITORING_ID, 1432)
        INTO :VAL;
        IF (VAL <> '') THEN
        BEGIN
            TAG_NAME = 'institution:totalPlace';
            SUSPEND;
        END

        SELECT IIF(I = 5405,2,1)
        FROM VAL_GET(:V$SCHOOL_ID, 29)
        INTO :VAL;
        IF (VAL <> '') THEN
        BEGIN
            TAG_NAME = 'institution:legal';
            SUSPEND;
        END

        FOR
            SELECT L57.OBJ_ID

            FROM LINKS L69

            JOIN LINKS L57
            ON L57.PARENT_ID = L69.OBJ_ID
            AND L57.OBJ_TYPE_ID = 57
            AND L57.DATE_DEL IS NULL

            WHERE L69.PARENT_ID = :V$SCHOOL_ID
            AND L69.OBJ_TYPE_ID = 69
            AND L69.DATE_DEL IS NULL

            INTO :V$OBJ_ID
        DO
        BEGIN
            VAL = V$OBJ_ID;
            TAG_NAME = 'institution:programs:program:externalKey';
            SUSPEND;

            TAG_NAME = 'institution:programs:program:name';
            SELECT V
            FROM VAL_GET(:V$OBJ_ID, 386)
            INTO :VAL;
            SUSPEND;

            VAL = V$SCHOOL_ID;
            TAG_NAME = 'institution:programs:program:institution:externalKey';
            SUSPEND;

            FOR
                SELECT LV1832.TAG, R.VAL
                FROM VALL V1832
    
                JOIN LISTVALS LV1832
                ON LV1832.LISTVAL_ID = V1832.LISTVAL_ID
    
                LEFT JOIN RES_GET(LV1832.RES_ID, :V$LANG_CODE) R ON 1=1

                WHERE V1832.OBJ_ID = :V$OBJ_ID
                AND V1832.PARAM_ID = 1832
                AND V1832.IS_DEL = 0
    
                INTO :VAL, :V$STR
            DO
            BEGIN
                TAG_NAME = 'institution:programs:program:type:code';
                SUSPEND;

                VAL = V$STR;
                TAG_NAME = 'institution:programs:program:type:name';
                SUSPEND;
            END

            FOR
                SELECT LV1594.TAG, R.VAL
                FROM VALL V1594
    
                JOIN LISTVALS LV1594
                ON LV1594.LISTVAL_ID = V1594.LISTVAL_ID
    
                LEFT JOIN RES_GET(LV1594.RES_ID, :V$LANG_CODE) R ON 1=1

                WHERE V1594.OBJ_ID = :V$OBJ_ID
                AND V1594.PARAM_ID = 1594
                AND V1594.IS_DEL = 0
    
                INTO :VAL, :V$STR
            DO
            BEGIN
                TAG_NAME = 'institution:programs:program:studyLevel:code';
                SUSPEND;

                VAL = V$STR;
                TAG_NAME = 'institution:programs:program:studyLevel:name';
                SUSPEND;
            END

            FOR
                SELECT LV2379.TAG, R.VAL
                FROM VALL V2379
    
                JOIN LISTVALS LV2379
                ON LV2379.LISTVAL_ID = V2379.LISTVAL_ID
    
                LEFT JOIN RES_GET(LV2379.RES_ID, :V$LANG_CODE) R ON 1=1

                WHERE V2379.OBJ_ID = :V$OBJ_ID
                AND V2379.PARAM_ID = 2379
                AND V2379.IS_DEL = 0
    
                INTO :VAL, :V$STR
            DO
            BEGIN
                TAG_NAME = 'institution:programs:program:adaptability:code';
                SUSPEND;

                VAL = V$STR;
                TAG_NAME = 'institution:programs:program:adaptability:name';
                SUSPEND;
            END
        END

        FOR
            SELECT L9.OBJ_ID,
                   L9.OBJ_TYPE_ID,
                   L7.OBJ_ID

            FROM LINKS L7

            JOIN LINKS L8
            ON L8.PARENT_ID = L7.OBJ_ID
            AND L8.OBJ_TYPE_ID = 8
            AND L8.DATE_DEL IS NULL

            JOIN LINKS L9
            ON L9.PARENT_ID = L8.OBJ_ID
            AND L9.OBJ_TYPE_ID IN (9,187)
            AND L9.DATE_DEL IS NULL

            WHERE L7.PARENT_ID = :V$SCHOOL_ID
            AND L7.OBJ_TYPE_ID = 7
            AND L7.DATE_DEL IS NULL

            INTO :V$OBJ_ID,
                 :V$TYPE_ID,
                 :V$OBJ_ID2
        DO
        BEGIN
            VAL = V$OBJ_ID;
            TAG_NAME = 'institution:groups:group:externalKey';
            SUSPEND;

            FOR
                SELECT CAPTION
                FROM OBJECT_CAPTION_GET(:V$OBJ_ID)
                INTO :VAL
            DO
            BEGIN
                TAG_NAME = 'institution:groups:group:name';
                SUSPEND;
            END

            VAL = V$SCHOOL_ID;
            TAG_NAME = 'institution:groups:group:institution:externalKey';
            SUSPEND;

            FOR
                SELECT LV43.TAG, R.VAL
                FROM VALL V43
    
                JOIN LISTVALS LV43
                ON LV43.LISTVAL_ID = V43.LISTVAL_ID
    
                LEFT JOIN RES_GET(LV43.RES_ID, :V$LANG_CODE) R ON 1=1

                WHERE V43.OBJ_ID = :V$OBJ_ID2
                AND V43.PARAM_ID = 43
                AND V43.IS_DEL = 0
    
                INTO :VAL, :V$STR
            DO
            BEGIN
                TAG_NAME = 'institution:groups:group:studyLevel:code';
                SUSPEND;

                VAL = V$STR;
                TAG_NAME = 'institution:groups:group:studyLevel:name';
                SUSPEND;
            END
        END

        V$FROM_ID = V$SCHOOL_ID / 1000000000;
        V$TO_ID = (V$FROM_ID + 1) * 1000000000 - 1;
        V$FROM_ID = V$FROM_ID * 1000000000 + 1;

        FOR
            SELECT DISTINCT V.SUBJECT_ID

            FROM VALM V

            WHERE V.MARK_ID >= :V$FROM_ID
            AND V.MARK_ID <= :V$TO_ID


            INTO :V$OBJ_ID
        DO
        BEGIN
            VAL = V$OBJ_ID;
            TAG_NAME = 'institution:courses:course:externalKey';
            SUSPEND;

            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:V$OBJ_ID)
            INTO :VAL;
            TAG_NAME = 'institution:courses:course:name';
            SUSPEND;
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE KONTINGENT_PERSONS_EXPORT (
    I$SCHOOL_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    TAG_NAME VARCHAR(255),
    VAL VARCHAR(4000))
AS
declare variable V$PERSON_ID bigint;
BEGIN
    FOR
        SELECT L10.OBJ_ID
        FROM LINKS L2

        JOIN LINKS L7
        ON L7.PARENT_ID = L2.OBJ_ID
        AND L7.OBJ_TYPE_ID = 7
        AND L7.DATE_DEL IS NULL

        JOIN LINKS L8
        ON L8.PARENT_ID = L7.OBJ_ID
        AND L8.OBJ_TYPE_ID = 8
        AND L8.DATE_DEL IS NULL

        JOIN LINKS L9
        ON L9.PARENT_ID = L8.OBJ_ID
        AND L9.OBJ_TYPE_ID IN (187,9)
        AND L9.DATE_DEL IS NULL

        JOIN LINKS L10
        ON L10.PARENT_ID = L9.OBJ_ID
        AND L10.OBJ_TYPE_ID = 10
        AND L10.DATE_DEL IS NULL

        WHERE ((L2.PARENT_ID IS NULL) OR (L2.PARENT_TYPE_ID IN (111, 112)))
        AND L2.OBJ_TYPE_ID = 2
        AND L2.DATE_DEL IS NULL
        AND L2.OBJ_ID = :I$SCHOOL_ID

        UNION ALL

        SELECT L20.OBJ_ID
        FROM LINKS L2

        JOIN LINKS L7
        ON L7.PARENT_ID = L2.OBJ_ID
        AND L7.OBJ_TYPE_ID = 7
        AND L7.DATE_DEL IS NULL

        JOIN LINKS L8
        ON L8.PARENT_ID = L7.OBJ_ID
        AND L8.OBJ_TYPE_ID = 8
        AND L8.DATE_DEL IS NULL

        JOIN LINKS L9
        ON L9.PARENT_ID = L8.OBJ_ID
        AND L9.OBJ_TYPE_ID IN (187,9)
        AND L9.DATE_DEL IS NULL

        JOIN LINKS L10
        ON L10.PARENT_ID = L9.OBJ_ID
        AND L10.OBJ_TYPE_ID = 10
        AND L10.DATE_DEL IS NULL

        JOIN LINKS L20
        ON L20.PARENT_ID = L10.OBJ_ID
        AND L20.OBJ_TYPE_ID = 20
        AND L20.DATE_DEL IS NULL

        WHERE ((L2.PARENT_ID IS NULL) OR (L2.PARENT_TYPE_ID IN (111, 112)))
        AND L2.OBJ_TYPE_ID = 2
        AND L2.DATE_DEL IS NULL
        AND L2.OBJ_ID = :I$SCHOOL_ID

        UNION ALL

        SELECT L14.OBJ_ID
        FROM LINKS L2

        JOIN LINKS L14
        ON L14.PARENT_ID = L2.OBJ_ID
        AND L14.OBJ_TYPE_ID = 14
        AND L14.DATE_DEL IS NULL

        WHERE ((L2.PARENT_ID IS NULL) OR (L2.PARENT_TYPE_ID IN (111, 112)))
        AND L2.OBJ_TYPE_ID = 2
        AND L2.DATE_DEL IS NULL
        AND L2.OBJ_ID = :I$SCHOOL_ID

        INTO :V$PERSON_ID
    DO
    BEGIN
        FOR
            SELECT TAG_NAME,
                   VAL
            FROM KONTINGENT_PERSON_EXPORT(:V$PERSON_ID, :I$SCHOOL_ID, :I$USER_ID)
            INTO :TAG_NAME,
                 :VAL
        DO
        BEGIN
            SUSPEND;
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE KONTINGENT_PERSON_EXPORT (
    I$PERSON_ID BIGINT,
    I$SCHOOL_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    TAG_NAME VARCHAR(255),
    VAL VARCHAR(4000))
AS
declare variable V$OBJ_ID bigint;
declare variable V$TYPE_ID bigint;
declare variable V$EXT_OBJ_ID bigint;
declare variable V$OBJ_ID2 bigint;
declare variable Y smallint;
declare variable DT date;
declare variable YEAR_VAL varchar(20);
declare variable V$STR varchar(1000);
declare variable V$LANG_CODE varchar(2);
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :V$LANG_CODE;

    SELECT TYPE_ID
    FROM OBJECTS
    WHERE OBJ_ID = :I$PERSON_ID
    INTO :V$TYPE_ID;

    Y = EXTRACT(YEAR FROM CURRENT_DATE);
    DT = '1.09.' || Y;

    TAG_NAME = 'person:externalKey';
    VAL = I$PERSON_ID;
    SUSPEND;

    TAG_NAME = 'person:surname';
    SELECT V
    FROM VAL_GET(:I$PERSON_ID, CASE :V$TYPE_ID WHEN 10 THEN 55 WHEN 14 THEN 59 WHEN 20 THEN 128 END)
    INTO :VAL;
    SUSPEND;

    TAG_NAME = 'person:name';
    SELECT V
    FROM VAL_GET(:I$PERSON_ID, CASE :V$TYPE_ID WHEN 10 THEN 56 WHEN 14 THEN 60 WHEN 20 THEN 129 END)
    INTO :VAL;
    SUSPEND;

    SELECT V
    FROM VAL_GET(:I$PERSON_ID, CASE :V$TYPE_ID WHEN 10 THEN 57 WHEN 14 THEN 61 WHEN 20 THEN 130 END)
    INTO :VAL;
    IF (VAL <> '') THEN
    BEGIN
        TAG_NAME = 'person:patronymic';
        SUSPEND;
    END

    SELECT IIF(V <> '', EXTRACT(YEAR FROM D) || '-' ||
           IIF(EXTRACT(MONTH FROM D) < 10,0,'') || EXTRACT(MONTH FROM D) || '-' ||
           IIF(EXTRACT(DAY FROM D) < 10,0,'') || EXTRACT(DAY FROM D), '')
    FROM VAL_GET(:I$PERSON_ID, CASE :V$TYPE_ID WHEN 10 THEN 89 WHEN 14 THEN 241 WHEN 20 THEN 143 END)
    INTO :VAL;
    IF (VAL <> '') THEN
    BEGIN
        TAG_NAME = 'person:birthDate';
        SUSPEND;
    END

    SELECT V
    FROM VAL_GET(:I$PERSON_ID, CASE :V$TYPE_ID WHEN 10 THEN 1343 WHEN 14 THEN 244 WHEN 20 THEN 2543 END)
    INTO :VAL;
    IF (VAL <> '') THEN
    BEGIN
        TAG_NAME = 'person:birthPlace';
        SUSPEND;
    END

    SELECT IIF(I = 182,'f',IIF(I = 183,'m',''))
    FROM VAL_GET(:I$PERSON_ID, CASE :V$TYPE_ID WHEN 10 THEN 88 WHEN 14 THEN 239 WHEN 20 THEN 2544 END)
    INTO :VAL;
    IF (VAL <> '') THEN
    BEGIN
        TAG_NAME = 'person:sex';
        SUSPEND;
    END

    SELECT V
    FROM VAL_GET(:I$PERSON_ID, CASE :V$TYPE_ID WHEN 10 THEN 1409 WHEN 14 THEN 2455 WHEN 20 THEN 2365 END)
    INTO :VAL;
    IF (VAL <> '') THEN
    BEGIN
        TAG_NAME = 'person:snils';
        SUSPEND;
    END

    SELECT IIF(I = 1515,'1','2')
    FROM VAL_GET(:I$PERSON_ID, CASE :V$TYPE_ID WHEN 10 THEN 91 WHEN 14 THEN 243 WHEN 20 THEN 1559 END)
    INTO :VAL;
    IF (VAL <> '') THEN
    BEGIN
        TAG_NAME = 'person:nationality';
        SUSPEND;
    END

    FOR
        SELECT FIRST 1
               L79.OBJ_ID
        FROM LINKS L79

        JOIN VALL V441
        ON V441.OBJ_ID = L79.OBJ_ID
        AND V441.PARAM_ID = 441
        AND V441.IS_DEL = 0
        AND V441.LISTVAL_ID = 1370

        JOIN VALD V560
        ON V560.OBJ_ID = L79.OBJ_ID
        AND V560.PARAM_ID = 560
        AND V560.IS_DEL = 0

        WHERE L79.PARENT_ID = :I$PERSON_ID
        AND L79.OBJ_TYPE_ID = 79
        AND L79.DATE_DEL IS NULL

        ORDER BY V560.VAL DESC
        INTO :V$OBJ_ID
    DO
    BEGIN
        SELECT V
        FROM VAL_GET(:V$OBJ_ID, 442)
        INTO :VAL;
        IF (VAL <> '') THEN
        BEGIN
            TAG_NAME = 'person:identityDocument:series';
            SUSPEND;
        END

        SELECT V
        FROM VAL_GET(:V$OBJ_ID, 559)
        INTO :VAL;
        IF (VAL <> '') THEN
        BEGIN
            TAG_NAME = 'person:identityDocument:number';
            SUSPEND;
        END

        SELECT IIF(V <> '', EXTRACT(YEAR FROM D) || '-' ||
               IIF(EXTRACT(MONTH FROM D) < 10,0,'') || EXTRACT(MONTH FROM D) || '-' ||
               IIF(EXTRACT(DAY FROM D) < 10,0,'') || EXTRACT(DAY FROM D), '')
        FROM VAL_GET(:V$OBJ_ID, 560)
        INTO :VAL;
        IF (VAL <> '') THEN
        BEGIN
            TAG_NAME = 'person:identityDocument:issueDate';
            SUSPEND;
        END

        SELECT V
        FROM VAL_GET(:V$OBJ_ID, 562)
        INTO :VAL;
        IF (VAL <> '') THEN
        BEGIN
            TAG_NAME = 'person:identityDocument:issuedBy';
            SUSPEND;
        END

        TAG_NAME = 'person:identityDocument:type';
        VAL = 'Свидетельство о рождении';
        SUSPEND;
    END

    FOR
        SELECT L79.OBJ_ID
        FROM LINKS L79

        JOIN VALL V441
        ON V441.OBJ_ID = L79.OBJ_ID
        AND V441.PARAM_ID = 441
        AND V441.IS_DEL = 0
        AND V441.LISTVAL_ID <> 1370

        JOIN VALD V560
        ON V560.OBJ_ID = L79.OBJ_ID
        AND V560.PARAM_ID = 560
        AND V560.IS_DEL = 0

        WHERE L79.PARENT_ID = :I$PERSON_ID
        AND L79.OBJ_TYPE_ID = 79
        AND L79.DATE_DEL IS NULL

        INTO :V$OBJ_ID
    DO
    BEGIN
        VAL = :V$OBJ_ID;
        TAG_NAME = 'person:identityDocument:externalKey';
        SUSPEND;

        SELECT V
        FROM VAL_GET(:V$OBJ_ID, 442)
        INTO :VAL;
        IF (VAL <> '') THEN
        BEGIN
            TAG_NAME = 'person:identityDocument:series';
            SUSPEND;
        END

        SELECT V
        FROM VAL_GET(:V$OBJ_ID, 559)
        INTO :VAL;
        IF (VAL <> '') THEN
        BEGIN
            TAG_NAME = 'person:identityDocument:number';
            SUSPEND;
        END

        SELECT IIF(V <> '', EXTRACT(YEAR FROM D) || '-' ||
               IIF(EXTRACT(MONTH FROM D) < 10,0,'') || EXTRACT(MONTH FROM D) || '-' ||
                   IIF(EXTRACT(DAY FROM D) < 10,0,'') || EXTRACT(DAY FROM D), '')
        FROM VAL_GET(:V$OBJ_ID, 560)
        INTO :VAL;
        IF (VAL <> '') THEN
        BEGIN
            TAG_NAME = 'person:identityDocument:issueDate';
            SUSPEND;
        END

        SELECT V
        FROM VAL_GET(:V$OBJ_ID, 562)
        INTO :VAL;
        IF (VAL <> '') THEN
        BEGIN
            TAG_NAME = 'person:identityDocument:issuedBy';
            SUSPEND;
        END

        TAG_NAME = 'person:identityDocument:type';
        VAL = 'Паспорт';
        SUSPEND;
    END

    SELECT V
    FROM VAL_GET(:I$PERSON_ID, CASE :V$TYPE_ID WHEN 10 THEN 111 WHEN 14 THEN 262 WHEN 20 THEN 1561 END)
    INTO :VAL;
    IF (VAL <> '') THEN
    BEGIN
        TAG_NAME = 'person:addresses:registrationAddress:name';
        SUSPEND;
    END

    SELECT V
    FROM VAL_GET(:I$PERSON_ID, CASE :V$TYPE_ID WHEN 10 THEN 103 WHEN 14 THEN 255 WHEN 20 THEN 147 END)
    INTO :VAL;
    IF (VAL <> '') THEN
    BEGIN
        TAG_NAME = 'person:addresses:residanceAddress:name';
        SUSPEND;
    END

    IF (V$TYPE_ID = 10) THEN
    BEGIN
        SELECT V
        FROM VAL_GET(:I$PERSON_ID, 2357)
        INTO :VAL;
        IF (VAL <> '') THEN
        BEGIN
            TAG_NAME = 'person:addresses:stayAddress:name';
            SUSPEND;
        END
    END

    FOR
        SELECT L20.OBJ_ID,
               L20.EXT_OBJ_ID
        FROM LINKS L20

        WHERE L20.PARENT_ID = :I$PERSON_ID
        AND L20.OBJ_TYPE_ID = 20
        AND L20.DATE_DEL IS NULL

        INTO :V$OBJ_ID,
             :V$EXT_OBJ_ID
    DO
    BEGIN
        VAL = V$OBJ_ID;
        TAG_NAME = 'person:representative:externalKey';
        SUSPEND;

        VAL = V$OBJ_ID;
        TAG_NAME = 'person:representative:person:externalKey';
        SUSPEND;

        FOR
            SELECT LV1573.TAG, R.VAL
            FROM VALL V1573
    
            JOIN LISTVALS LV1573
            ON LV1573.LISTVAL_ID = V1573.LISTVAL_ID
    
            LEFT JOIN RES_GET(LV1573.RES_ID, :V$LANG_CODE) R ON 1=1

            WHERE V1573.OBJ_ID = :V$EXT_OBJ_ID
            AND V1573.PARAM_ID = 1573
            AND V1573.IS_DEL = 0
    
            INTO :VAL, :V$STR
        DO
        BEGIN
            TAG_NAME = 'person:representative:type:code';
            SUSPEND;

            TAG_NAME = 'person:representative:type:name';
            VAL = V$STR;
            SUSPEND;
        END
    END

    FOR
        SELECT LV2364.TAG, R.VAL
        FROM VALL V2364

        JOIN LISTVALS LV2364
        ON LV2364.LISTVAL_ID = V2364.LISTVAL_ID
    
        LEFT JOIN RES_GET(LV2364.RES_ID, :V$LANG_CODE) R ON 1=1

        WHERE V2364.OBJ_ID = :I$PERSON_ID
        AND V2364.PARAM_ID = 2364
        AND V2364.IS_DEL = 0

        INTO :VAL, :V$STR
    DO
    BEGIN
        TAG_NAME = 'person:hardSituation:code';
        SUSPEND;

        VAL = V$STR;
        TAG_NAME = 'person:hardSituation:name';
        SUSPEND;
    END

    FOR
        SELECT LV208.TAG, R.VAL
        FROM VALL V208

        JOIN LISTVALS LV208
        ON LV208.LISTVAL_ID = V208.LISTVAL_ID

        LEFT JOIN RES_GET(LV208.RES_ID, :V$LANG_CODE) R ON 1=1

        WHERE V208.OBJ_ID = :I$PERSON_ID
        AND V208.PARAM_ID = 208
        AND V208.IS_DEL = 0

        INTO :VAL, :V$STR
    DO
    BEGIN
        TAG_NAME = 'person:health:group:code';
        SUSPEND;

        TAG_NAME = 'person:health:group:name';
        VAL = V$STR;
        SUSPEND;
    END

    FOR
        SELECT LV176.TAG, R.VAL
        FROM VALL V176

        JOIN LISTVALS LV176
        ON LV176.LISTVAL_ID = V176.LISTVAL_ID

        LEFT JOIN RES_GET(LV176.RES_ID, :V$LANG_CODE) R ON 1=1

        WHERE V176.OBJ_ID = :I$PERSON_ID
        AND V176.PARAM_ID = 176
        AND V176.IS_DEL = 0

        INTO :VAL, :V$STR
    DO
    BEGIN
        TAG_NAME = 'person:health:sportgroup:code';
        SUSPEND;

        TAG_NAME = 'person:health:sportgroup:name';
        VAL = V$STR;
        SUSPEND;
    END

    FOR
        SELECT L295.OBJ_ID
        FROM LINKS L295

        WHERE L295.PARENT_ID = :I$PERSON_ID
        AND L295.OBJ_TYPE_ID = 295
        AND L295.DATE_DEL IS NULL

        INTO :V$OBJ_ID
    DO
    BEGIN
        FOR
            SELECT LV2373.TAG, R.VAL
            FROM VALL V2373
    
            JOIN LISTVALS LV2373
            ON LV2373.LISTVAL_ID = V2373.LISTVAL_ID
    
            LEFT JOIN RES_GET(LV2373.RES_ID, :V$LANG_CODE) R ON 1=1

            WHERE V2373.OBJ_ID = :V$OBJ_ID
            AND V2373.PARAM_ID = 2373
            AND V2373.IS_DEL = 0
    
            INTO :VAL, :V$STR
        DO
        BEGIN
            TAG_NAME = 'person:health:disability:group:code';
            SUSPEND;

            TAG_NAME = 'person:health:disability:group:name';
            VAL = V$STR;
            SUSPEND;
        END

        FOR
            SELECT LV2374.TAG, R.VAL
            FROM VALL V2374
    
            JOIN LISTVALS LV2374
            ON LV2374.LISTVAL_ID = V2374.LISTVAL_ID
    
            LEFT JOIN RES_GET(LV2374.RES_ID, :V$LANG_CODE) R ON 1=1

            WHERE V2374.OBJ_ID = :V$OBJ_ID
            AND V2374.PARAM_ID = 2374
            AND V2374.IS_DEL = 0
    
            INTO :VAL, :V$STR
        DO
        BEGIN
            TAG_NAME = 'person:health:disability:category:code';
            SUSPEND;

            TAG_NAME = 'person:health:disability:category:name';
            VAL = V$STR;
            SUSPEND;
        END

        SELECT IIF(V <> '', EXTRACT(YEAR FROM D) || '-' ||
               IIF(EXTRACT(MONTH FROM D) < 10,0,'') || EXTRACT(MONTH FROM D) || '-' ||
               IIF(EXTRACT(DAY FROM D) < 10,0,'') || EXTRACT(DAY FROM D), '')
        FROM VAL_GET(:V$OBJ_ID, 2375)
        INTO :VAL;
        IF (VAL <> '') THEN
        BEGIN
            TAG_NAME = 'person:health:disability:expirationDate';
            SUSPEND;
        END
    END

    FOR
        SELECT IIF(V2377.LISTVAL_ID = 2,1,0)
        FROM VALL V2377

        WHERE V2377.OBJ_ID = :I$PERSON_ID
        AND V2377.PARAM_ID = 2377
        AND V2377.IS_DEL = 0

        INTO :VAL
    DO
    BEGIN
        TAG_NAME = 'person:health:needAdapt';
        SUSPEND;
    END

    FOR
        SELECT IIF(V2378.LISTVAL_ID = 2,1,0)
        FROM VALL V2378

        WHERE V2378.OBJ_ID = :I$PERSON_ID
        AND V2378.PARAM_ID = 2378
        AND V2378.IS_DEL = 0

        INTO :VAL
    DO
    BEGIN
        TAG_NAME = 'person:health:needTreatment';
        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE KONTINGENT_PUPILS_EXPORT (
    I$SCHOOL_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    TAG_NAME VARCHAR(255),
    VAL VARCHAR(4000))
AS
declare variable V$PUPIL_ID bigint;
BEGIN
    FOR
        SELECT L10.OBJ_ID
        FROM LINKS L2

        JOIN LINKS L7
        ON L7.PARENT_ID = L2.OBJ_ID
        AND L7.OBJ_TYPE_ID = 7
        AND L7.DATE_DEL IS NULL

        JOIN LINKS L8
        ON L8.PARENT_ID = L7.OBJ_ID
        AND L8.OBJ_TYPE_ID = 8
        AND L8.DATE_DEL IS NULL

        JOIN LINKS L9
        ON L9.PARENT_ID = L8.OBJ_ID
        AND L9.OBJ_TYPE_ID IN (187,9)
        AND L9.DATE_DEL IS NULL

        JOIN LINKS L10

        ON L10.PARENT_ID = L9.OBJ_ID
        AND L10.OBJ_TYPE_ID = 10
        AND L10.DATE_DEL IS NULL

        WHERE ((L2.PARENT_ID IS NULL) OR (L2.PARENT_TYPE_ID IN (111, 112)))
        AND L2.OBJ_TYPE_ID = 2
        AND L2.DATE_DEL IS NULL
        AND L2.OBJ_ID = :I$SCHOOL_ID

        INTO :V$PUPIL_ID
    DO
    BEGIN
        FOR
            SELECT TAG_NAME,
                   VAL
            FROM KONTINGENT_PUPIL_EXPORT(:V$PUPIL_ID, :I$SCHOOL_ID, :I$USER_ID)
            INTO :TAG_NAME,
                 :VAL
        DO
        BEGIN
            SUSPEND;
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE KONTINGENT_PUPIL_EXPORT (
    I$PUPIL_ID BIGINT,
    I$SCHOOL_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    TAG_NAME VARCHAR(255),
    VAL VARCHAR(4000))
AS
declare variable V$OBJ_ID bigint;
declare variable V$EXT_OBJ_ID bigint;
declare variable V$OBJ_ID2 bigint;
declare variable Y smallint;
declare variable DT date;
declare variable YEAR_VAL varchar(20);
declare variable V$STR varchar(1000);
declare variable V$VAL varchar(1000);
declare variable V$LANG_CODE varchar(2);

declare variable V$MARKTYPE_ID bigint;
declare variable V$MARKVAL_ID bigint;
declare variable V$SUBJECT_ID bigint;
declare variable V$MARK_ID bigint;
declare variable V$IS_DEL smallint;
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :V$LANG_CODE;

    Y = EXTRACT(YEAR FROM CURRENT_DATE);
    DT = '1.09.' || Y;

    IF (CURRENT_DATE < DT) THEN
    BEGIN
        YEAR_VAL = (Y - 1);-- || '-' || Y;
    END
    ELSE
    BEGIN
        YEAR_VAL = Y;-- || '-' ||(Y + 1);
    END

    TAG_NAME = 'student:person:externalKey';
    VAL = I$PUPIL_ID;
    SUSPEND;

    FOR
        SELECT L22.OBJ_ID
        FROM LINKS L22

        WHERE L22.PARENT_ID = :I$PUPIL_ID
        AND L22.OBJ_TYPE_ID = 22
        AND L22.DATE_DEL IS NULL

        INTO :V$OBJ_ID
    DO
    BEGIN
        FOR
            SELECT V167.LISTVAL_ID, R.VAL
            FROM VALL V167
    
            JOIN LISTVALS LV167
            ON LV167.LISTVAL_ID = V167.LISTVAL_ID
    
            LEFT JOIN RES_GET(LV167.RES_ID, :V$LANG_CODE) R ON 1=1

            WHERE V167.OBJ_ID = :V$OBJ_ID
            AND V167.PARAM_ID = 167
            AND V167.IS_DEL = 0
    
            INTO :V$OBJ_ID2, :V$STR
        DO
        BEGIN
            SELECT V
            FROM VAL_GET(:V$OBJ_ID2, 167)
            INTO :VAL;
            IF (VAL <> '') THEN
            BEGIN
                TAG_NAME = 'student:portfolio:event:name';
                SUSPEND;
            END

            VAL = V$OBJ_ID2;
            TAG_NAME = 'student:portfolio:event:type:code';
            SUSPEND;

            VAL = V$STR;
            TAG_NAME = 'student:portfolio:event:type:name';
            SUSPEND;
        END

        SELECT IIF(V <> '', EXTRACT(YEAR FROM D) || '-' ||
               IIF(EXTRACT(MONTH FROM D) < 10,0,'') || EXTRACT(MONTH FROM D) || '-' ||
               IIF(EXTRACT(DAY FROM D) < 10,0,'') || EXTRACT(DAY FROM D), '')
        FROM VAL_GET(:V$OBJ_ID, 166)
        INTO :VAL;
        IF (VAL <> '') THEN
        BEGIN
            TAG_NAME = 'student:portfolio:involveDate';
            SUSPEND;
        END

        SELECT V
        FROM VAL_GET(:V$OBJ_ID, 237)
        INTO :VAL;
        IF (VAL <> '') THEN
        BEGIN
            TAG_NAME = 'student:portfolio:involveResult';
            SUSPEND;
        END
    END

    FOR
        SELECT L11.OBJ_ID
        FROM LINKS L11

        WHERE L11.PARENT_ID = :I$PUPIL_ID
        AND L11.OBJ_TYPE_ID = 11
        AND L11.DATE_DEL IS NULL

        INTO :V$OBJ_ID
    DO
    BEGIN
        FOR
            SELECT LV50.TAG, R.VAL
            FROM VALL V50
    
            JOIN LISTVALS LV50
            ON LV50.LISTVAL_ID = V50.LISTVAL_ID
    
            LEFT JOIN RES_GET(LV50.RES_ID, :V$LANG_CODE) R ON 1=1

            WHERE V50.OBJ_ID = :V$OBJ_ID
            AND V50.PARAM_ID = 50
            AND V50.IS_DEL = 0
    
            INTO :VAL, :V$STR
        DO
        BEGIN
            TAG_NAME = 'student:studyDocument:type:code';
            SUSPEND;

            V$STR = CASE VAL
                WHEN '11' THEN 'Аттестат о среднем общем образовании'
                WHEN '12' THEN 'Аттестат об основном общем образовании'
                WHEN '21' THEN 'Диплом о среднем профессиональном образовании'
                WHEN '22' THEN 'Диплом бакалавра'
                WHEN '23' THEN 'Диплом специалиста'
                WHEN '24' THEN 'Диплом магистра'
                WHEN '25' THEN 'Диплом об окончании аспирантуры (адъюнктуры)'
                WHEN '26' THEN 'Диплом об окончании ординатуры'
                WHEN '27' THEN 'Диплом об окончании  ассистентуры-стажировки'
                WHEN '31' THEN 'Удостоверение о повышении квалификации'
                WHEN '32' THEN 'Диплом о профессиональной переподготовке'
                WHEN '33' THEN 'Свидетельство о профессии рабочего, должности служащего'
                WHEN '41' THEN 'Свидетельство об обучении для лиц с ограниченными возможностями здоровья (с различными формами умственной отсталости)'
                WHEN '5' THEN 'Свидетельство об освоении предпрофессиональной программы в области искусств'
                WHEN '6' THEN 'Другой документ об образовании'
                WHEN '7' THEN 'Другой документ об обучении'
            END;

            TAG_NAME = 'student:studyDocument:type:name';
            VAL = V$STR;
            SUSPEND;
        END

        SELECT V
        FROM VAL_GET(:V$OBJ_ID, 564)
        INTO :VAL;
        IF (VAL <> '') THEN
        BEGIN
            TAG_NAME = 'student:studyDocument:document:series';
            SUSPEND;
        END

        SELECT V
        FROM VAL_GET(:V$OBJ_ID, 565)
        INTO :VAL;
        IF (VAL <> '') THEN
        BEGIN
            TAG_NAME = 'student:studyDocument:document:number';
            SUSPEND;
        END

        SELECT IIF(V <> '', EXTRACT(YEAR FROM D) || '-' ||
               IIF(EXTRACT(MONTH FROM D) < 10,0,'') || EXTRACT(MONTH FROM D) || '-' ||
               IIF(EXTRACT(DAY FROM D) < 10,0,'') || EXTRACT(DAY FROM D), '')
        FROM VAL_GET(:V$OBJ_ID, 566)
        INTO :VAL;
        IF (VAL <> '') THEN
        BEGIN
            TAG_NAME = 'student:studyDocument:document:issueDate';
            SUSPEND;
        END

        SELECT V
        FROM VAL_GET(:V$OBJ_ID, 568)
        INTO :VAL;
        IF (VAL <> '') THEN
        BEGIN
            TAG_NAME = 'student:studyDocument:document:issuedBy';
            SUSPEND;
        END
    END

    TAG_NAME = 'student:education:institution:externalKey';
    VAL = I$SCHOOL_ID;
    SUSPEND;

    FOR
        SELECT FIRST 1
               L76.OBJ_ID
        FROM LINKS L76

        JOIN VALL V432
        ON V432.OBJ_ID = L76.OBJ_ID
        AND V432.PARAM_ID = 432
        AND V432.IS_DEL = 0
--            AND V432.LISTVAL_ID IN (805,806)

        JOIN LISTVALS LV432
        ON LV432.LISTVAL_ID = V432.LISTVAL_ID
        AND LV432."FILTER" LIKE '%ACCEPTED%'

        JOIN VALD V433
        ON V433.OBJ_ID = L76.OBJ_ID
        AND V433.PARAM_ID = 433
        AND V433.IS_DEL = 0

        WHERE L76.PARENT_ID = :I$PUPIL_ID
        AND L76.OBJ_TYPE_ID = 76
        AND L76.DATE_DEL IS NULL

        ORDER BY V433.VAL DESC
        INTO :V$OBJ_ID
    DO
    BEGIN
        SELECT IIF(V <> '', EXTRACT(YEAR FROM D) || '-' ||
               IIF(EXTRACT(MONTH FROM D) < 10,0,'') || EXTRACT(MONTH FROM D) || '-' ||
               IIF(EXTRACT(DAY FROM D) < 10,0,'') || EXTRACT(DAY FROM D), '')
        FROM VAL_GET(:V$OBJ_ID, 433)
        INTO :VAL;
        IF (VAL <> '') THEN
        BEGIN
            TAG_NAME = 'student:education:enroll:date';
            SUSPEND;
        END

        SELECT EXTRACT(YEAR FROM D)
        FROM VAL_GET(:V$OBJ_ID, 433)
        INTO :VAL;
        IF (VAL <> '') THEN
        BEGIN
            TAG_NAME = 'student:education:enroll:year';
            SUSPEND;
        END

        SELECT I
        FROM VAL_GET(:V$OBJ_ID, 438)
        INTO :VAL;
        IF (VAL <> '') THEN
        BEGIN
            TAG_NAME = 'student:education:enroll:group:externalKey';
            SUSPEND;
        END

        SELECT V
        FROM VAL_GET(:V$OBJ_ID, 434)
        INTO :VAL;
        IF (VAL <> '') THEN
        BEGIN
            TAG_NAME = 'student:education:enroll:document:number';
            SUSPEND;
        END

        SELECT V
        FROM VAL_GET(:V$OBJ_ID, 435)
        INTO :VAL;
        IF (VAL <> '') THEN
        BEGIN
            TAG_NAME = 'student:education:enroll:document:issueDate';
            SUSPEND;
        END
    END

    FOR
        SELECT LP57.PARENT_ID

        FROM LINKS LP256

        JOIN LINKS LP54
        ON LP54.OBJ_ID = LP256.PARENT_ID
        AND LP54.PARENT_TYPE_ID = 54
        AND LP54.DATE_DEL IS NULL

        JOIN LINKS LP50
        ON LP50.OBJ_ID = LP54.PARENT_ID
        AND LP50.PARENT_TYPE_ID = 50
        AND LP50.DATE_DEL IS NULL

        JOIN LINKS LP57
        ON LP57.OBJ_ID = LP50.PARENT_ID
        AND LP57.PARENT_TYPE_ID = 57
        AND LP57.DATE_DEL IS NULL

        WHERE LP256.OBJ_ID = :I$PUPIL_ID
        AND LP256.PARENT_TYPE_ID = 256
        AND LP256.DATE_DEL IS NULL

        INTO :V$OBJ_ID
    DO
    BEGIN
        VAL = V$OBJ_ID;
        TAG_NAME = 'student:education:program:externalKey';
        SUSPEND;
    END

    FOR
        SELECT FIRST 1
               LP9.PARENT_ID
        FROM LINKS LP9

        WHERE LP9.OBJ_ID = :I$PUPIL_ID
        AND LP9.PARENT_TYPE_ID IN (9, 187, 243)
        AND LP9.DATE_DEL IS NULL

        INTO :V$OBJ_ID
    DO
    BEGIN
        TAG_NAME = 'student:education:study:year';
        VAL = YEAR_VAL;
        SUSPEND;

        TAG_NAME = 'student:education:study:group:externalKey';
        VAL = V$OBJ_ID;
        SUSPEND;
    END

    FOR
        SELECT V.MARKTYPE_ID,
               V.MARKVAL_ID,
               V.SUBJECT_ID,
               V.MARK_ID,
               V.IS_DEL,
               RY.VAL,
               RMV.VAL
        FROM VALM V

        JOIN LISTVALS LVY
        ON LVY.LISTVAL_ID = V.YEAR_ID

        LEFT JOIN RES_GET(LVY.RES_ID, 'RU') RY
        ON 1=1

        JOIN LISTVALS LVMV
        ON LVMV.LISTVAL_ID = V.MARKVAL_ID

        LEFT JOIN RES_GET(LVMV.RES_ID, 'RU') RMV
        ON 1=1

        WHERE PUPIL_ID = :I$PUPIL_ID
        AND V.MARKTYPE_ID IN (3011,3013)

        INTO :V$MARKTYPE_ID,
             :V$MARKVAL_ID,
             :V$SUBJECT_ID,
             :V$MARK_ID,
             :V$IS_DEL,
             :V$STR,
             :V$VAL
    DO
    BEGIN
        TAG_NAME = 'student:education:performance:course:externalKey';
        VAL = V$SUBJECT_ID;
        SUSPEND;

        TAG_NAME = 'student:education:performance:year';
        VAL = V$STR;
        SUSPEND;

        TAG_NAME = 'student:education:performance:estimate:externalKey';
        VAL = V$MARK_ID;
        SUSPEND;

        TAG_NAME = 'student:education:performance:estimate:score';
        VAL = V$VAL;
        SUSPEND;

        TAG_NAME = 'student:education:performance:estimate:type:code';
        VAL = CASE V$MARKTYPE_ID
            WHEN 3013 THEN 10
            WHEN 3011 THEN 2
        END;
        SUSPEND;

        TAG_NAME = 'student:education:performance:estimate:type:name';
        VAL = CASE V$MARKTYPE_ID
            WHEN 3013 THEN 'Итоговая'
            WHEN 3011 THEN 'Годовая'
        END;
        SUSPEND;


        IF (V$MARKVAL_ID IN (3014,3015,3016,3017,3018)) THEN
        BEGIN
            TAG_NAME = 'student:education:performance:estimate:system:code';
            VAL = '5';
            SUSPEND;

            TAG_NAME = 'student:education:performance:estimate:system:name';
            VAL = '5-балльная';
            SUSPEND;
        END
        ELSE
        BEGIN
            TAG_NAME = 'student:education:performance:estimate:system:code';
            VAL = '';
            SUSPEND;

            TAG_NAME = 'student:education:performance:estimate:system:name';
            VAL = 'безотметочная';
            SUSPEND;
        END
        IF (V$IS_DEL = 1) THEN
        BEGIN
            TAG_NAME = 'student:education:performance:estimate:deleted';
            VAL = 'true';
            SUSPEND;   
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE KONTINGENT_UDOD_EMPLOYEES_EXP (
    I$SCHOOL_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    TAG_NAME VARCHAR(255),
    VAL VARCHAR(4000))
AS
declare variable V$EMPLOYEE_ID bigint;
BEGIN
    FOR
        SELECT EMPLOYEE_ID
        FROM UDOD_EMPLOYEE_LIST(:I$SCHOOL_ID)

        INTO :V$EMPLOYEE_ID
    DO
    BEGIN
        FOR
            SELECT TAG_NAME,
                   VAL
            FROM KONTINGENT_EMPLOYEE_EXPORT(:V$EMPLOYEE_ID, :I$SCHOOL_ID, :I$USER_ID)
            INTO :TAG_NAME,
                 :VAL
        DO
        BEGIN
            SUSPEND;
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE KONTINGENT_UDOD_PERSONS_EXPORT (
    I$SCHOOL_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    TAG_NAME VARCHAR(255),
    VAL VARCHAR(4000))
AS
declare variable V$PERSON_ID bigint;
BEGIN
    FOR
        SELECT PERSON_ID
        FROM UDOD_PERSON_LIST(:I$SCHOOL_ID)

        INTO :V$PERSON_ID
    DO
    BEGIN
        FOR
            SELECT TAG_NAME,
                   VAL
            FROM KONTINGENT_PERSON_EXPORT(:V$PERSON_ID, :I$SCHOOL_ID, :I$USER_ID)
            INTO :TAG_NAME,
                 :VAL
        DO
        BEGIN
            SUSPEND;
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE KONTINGENT_UDOD_PUPILS_EXPORT (
    I$SCHOOL_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    TAG_NAME VARCHAR(255),
    VAL VARCHAR(4000))
AS
declare variable V$PUPIL_ID bigint;
BEGIN
    FOR
        SELECT PUPIL_ID
        FROM UDOD_PUPIL_LIST(:I$SCHOOL_ID)

        INTO :V$PUPIL_ID
    DO
    BEGIN
        FOR
            SELECT TAG_NAME,
                   VAL
            FROM KONTINGENT_PUPIL_EXPORT(:V$PUPIL_ID, :I$SCHOOL_ID, :I$USER_ID)
            INTO :TAG_NAME,
                 :VAL
        DO
        BEGIN
            SUSPEND;
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LAST_BACKUP_DATE_ADD
AS
BEGIN
   UPDATE INFO SET INFO_VAL = CURRENT_TIMESTAMP
   WHERE INFO_CODE = 'LAST_BACKUP';

   IF (ROW_COUNT = 0) THEN
      INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
      VALUES ('LAST_BACKUP', 'LAST_BACKUP', CURRENT_TIMESTAMP);
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LD_STUDENT_GET (
    I$OBJ_ID BIGINT NOT NULL,
    I$USER_ID VARCHAR(100) NOT NULL,
    I$PRINT SMALLINT,
    I$TO VARCHAR(100),
    I$IP VARCHAR(30))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(4000))
AS
DECLARE VARIABLE V$PARAM_ID BIGINT;
DECLARE VARIABLE V$ID BIGINT;
DECLARE VARIABLE V$S VARCHAR(100);
DECLARE VARIABLE V$USER_ID BIGINT;
DECLARE VARIABLE V$USER_NAME VARCHAR(100);
DECLARE VARIABLE V$VAL VARCHAR(4000);
DECLARE VARIABLE V$VAL_OLD VARCHAR(4000);
DECLARE VARIABLE V$DT TIMESTAMP;
DECLARE VARIABLE V$DT2 TIMESTAMP;
DECLARE VARIABLE V$LD_OPEN_DT TIMESTAMP;
DECLARE VARIABLE V$DISCHARGE_DT TIMESTAMP; /* дата последнего отчисления */
DECLARE VARIABLE V$ADMISSION_DT TIMESTAMP;
DECLARE VARIABLE V$DOC_ID BIGINT;
DECLARE VARIABLE V$REASON_IN VARCHAR(500);
DECLARE VARIABLE V$REASON_OUT VARCHAR(500);
DECLARE VARIABLE V$GRADE VARCHAR(1000);
DECLARE VARIABLE V$HOURS FLOAT;
DECLARE VARIABLE V$F FLOAT;
DECLARE VARIABLE V$SUM FLOAT;
DECLARE VARIABLE V$CTCOST FLOAT;
DECLARE VARIABLE V$YEAR BIGINT;
DECLARE VARIABLE V$D1 DATE;
DECLARE VARIABLE V$D2 DATE;
DECLARE VARIABLE V$CJ_ID BIGINT;
DECLARE VARIABLE V$YEAR_DT DATE;
DECLARE VARIABLE N INTEGER;
DECLARE VARIABLE V$TYPE_ID BIGINT;
DECLARE VARIABLE V$VAL_ID BIGINT;
DECLARE VARIABLE V$STAGE_ID BIGINT;
DECLARE VARIABLE V$PERIOD_ID BIGINT;
DECLARE VARIABLE V$PREV_PERIOD BIGINT;
DECLARE VARIABLE V$PREV_MT BIGINT;
BEGIN
  --Redmine #1165
  IF(I$USER_ID = 'Веб-администратор') THEN V$USER_ID = 1; ELSE V$USER_ID = I$USER_ID;

  FOR
    SELECT P.PARAM_ID, R.VAL
    FROM PARAMS P
    JOIN RES R ON R.RES_ID = P.RES_ID AND LANG_CODE = 'RU'
    WHERE P.IS_DEL = 0 AND P.TYPE_ID = 10 -- student
    INTO :V$PARAM_ID, :TAG_NAME
  DO
  BEGIN
    TAG_NAME = REPLACE(TAG_NAME, ' ', '_');
    TAG_NAME = REPLACE(TAG_NAME, '-', '_');
    TAG_NAME = REPLACE(TAG_NAME, '/', '_');
    TAG_NAME = REPLACE(TAG_NAME, '\', '_');
    TAG_NAME = REPLACE(TAG_NAME, '.', '_');
    TAG_NAME = REPLACE(TAG_NAME, ',', '_');
    TAG_NAME = REPLACE(TAG_NAME, '"', '_');
    TAG_NAME = REPLACE(TAG_NAME, '(', '_');
    TAG_NAME = REPLACE(TAG_NAME, ')', '_');
    TAG_NAME = REPLACE(TAG_NAME, '__', '_');

    IF (EXISTS(SELECT 1
      FROM LPARAMS LP
      JOIN LEVELS L ON L.LEVEL_ID = LP.LEVEL_ID AND L.IS_DEL = 0 AND LP.EDIT_TYPE >= 0
      JOIN TASKS T ON T.TASK_ID = L.TASK_ID AND T.IS_DEL = 0
      JOIN MODULES M ON M.MODULE_ID = T.MODULE_ID AND M.IS_DEL = 0 AND M.IS_ACTIVE = 1
      WHERE LP.PARAM_ID = :V$PARAM_ID))
    THEN
    BEGIN
      VAL = NULL;
      SELECT V FROM VAL_GET(:I$OBJ_ID, :V$PARAM_ID) WHERE IS_EXISTS = 1 INTO :VAL;
      IF (VAL IS NULL) THEN VAL = 'нет данных';

      -- Поле регионального идентификатора - обрезаем только кусок с guid (удалить символы фигурных скобок если есть, удалить хвост после двоеточия, lowercase)
      IF (V$PARAM_ID = 2912) THEN
      BEGIN
        VAL = REPLACE(VAL, '{', '');
        VAL = REPLACE(VAL, '}', '');
        WHILE (POSITION(':', VAL) > 0) DO
        BEGIN
          VAL = SUBSTRING(VAL FROM 1 FOR POSITION(':', VAL) - 1);
        END
        VAL = LOWER(VAL);
      END
      SUSPEND;
    END
  END

  -- поля распечатки и выдачи ЛД.
  -- проверяем текущее состояние объекта Запись распечатки личного дела (#504)
  V$DOC_ID = NULL;
  V$VAL = NULL;
  SELECT FIRST 1 L504.OBJ_ID, V3483.VAL, V3484.LISTVAL_ID, V3485.SVAL
  FROM LINKS L504
  JOIN VALD V3483 ON V3483.OBJ_ID = L504.OBJ_ID AND V3483.PARAM_ID = 3483 AND V3483.IS_DEL = 0
  LEFT JOIN VALL V3484 ON V3484.OBJ_ID = L504.OBJ_ID AND V3484.PARAM_ID = 3484 AND V3484.IS_DEL = 0
  LEFT JOIN VALS V3485 ON V3485.OBJ_ID = L504.OBJ_ID AND V3485.PARAM_ID = 3485 AND V3485.IS_DEL = 0
  WHERE L504.OBJ_TYPE_ID = 504 AND L504.PARENT_ID = :I$OBJ_ID AND L504.DATE_DEL IS NULL
  ORDER BY 2 DESC
  INTO :V$ID, :V$DT, :V$DOC_ID, :V$VAL;

  -- выдаем поля распечатки и выдачи ЛД, когда просто просмотр
  IF (I$PRINT IS NULL) THEN
  BEGIN
    TAG_NAME = 'Распечатано';
    VAL = IIF(V$DT IS NULL, 'Нет', 'Да');
    SUSPEND;
    TAG_NAME = 'Дата_распечатки';
    SELECT RESULT FROM DATE2STR(:V$DT) INTO :VAL;
    SUSPEND;
    TAG_NAME = 'Выдано_на_руки';
    VAL = IIF(V$DOC_ID = 2, 'Да', 'Нет');
    SUSPEND;
    TAG_NAME = 'Кому_выдано';
    VAL = V$VAL;
    SUSPEND;
  END
  ELSE
  BEGIN
    -- найдем имя пользователя + IP
    V$USER_NAME = NULL;
    IF(I$USER_ID = 'Веб-администратор') THEN
      V$USER_NAME = I$USER_ID;
    ELSE
    BEGIN
      SELECT FIRST 1 IIF(U.OBJ_ID IS NULL, NM.FULL_NAME, CAP.SCAPTION)
      FROM USERS U
      LEFT JOIN BUILD_FIO(U.LAST_NAME, U.FIRST_NAME, U.MIDDLE_NAME) NM ON 1 = 1
      LEFT JOIN OBJECT_CAPTION_GET(U.OBJ_ID) CAP ON 1 = 1
      WHERE U.USER_ID = :I$USER_ID
      INTO :V$USER_NAME;
    END
    V$USER_NAME = V$USER_NAME || ' (IP = ' || IIF(I$IP IS NULL, 'NULL', I$IP) || ')';

    -- регистрируем текущую дату в подчиненном объекте типа 504
    SELECT OBJ_ID FROM OBJECT_ADD(:I$OBJ_ID, 504) INTO :V$ID;
    SELECT 1 FROM VAL_ADD(3483, :V$ID, CURRENT_DATE, :V$USER_ID) INTO :V$DOC_ID; -- Дата распечатывания
    SELECT 1 FROM VAL_ADD(3486, :V$ID, :V$USER_NAME, :V$USER_ID) INTO :V$DOC_ID; -- Кто распечатал
    SELECT 1 FROM VAL_ADD(3484, :V$ID, IIF(:I$PRINT = 0, 3, 2), :V$USER_ID) INTO :V$DOC_ID; -- Выдано на руки  0/1
    IF (I$PRINT > 0) THEN SELECT 1 FROM VAL_ADD(3485, :V$ID, :I$TO, :V$USER_ID) INTO :V$DOC_ID; -- Кому выдано, только если выдано на руки

    TAG_NAME = 'Распечатано';
    VAL = 'Да';
    SUSPEND;
    TAG_NAME = 'Дата_распечатки';
    SELECT RESULT FROM DATE2STR(CURRENT_DATE) INTO :VAL;
    SUSPEND;
    TAG_NAME = 'Выдано_на_руки';
    VAL = IIF(I$PRINT <> 0, 'Да', 'Нет');
    SUSPEND;
    TAG_NAME = 'Кому_выдано';
    VAL = I$TO;
    SUSPEND;
  END

  -- данные о школе
  TAG_NAME = 'Наименование_ОО';
  VAL = NULL;
  SELECT FIRST 1 V5.VAL
  FROM LINKS L2
  LEFT JOIN VALS V5 ON V5.OBJ_ID = L2.OBJ_ID AND V5.PARAM_ID = 5 AND V5.IS_DEL = 0
  WHERE L2.OBJ_TYPE_ID = 2 AND L2.PARENT_TYPE_ID IS NULL AND L2.DATE_DEL IS NULL
  INTO :VAL;
  SUSPEND;
  TAG_NAME = 'Должность_руководителя';
  VAL = NULL; V$S = NULL;
  SELECT FIRST 1 C.POST, NM.FULL_NAME
  FROM LINKS L2
  LEFT JOIN R_SPB_POST_DIRECTOR(L2.OBJ_ID, 1) C ON 1 = 1
  LEFT JOIN BUILD_FIO(C.F, C.I, C.O) NM ON 1 = 1
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :VAL, :V$S;
  SUSPEND;
  TAG_NAME = 'ФИО_руководителя';
  VAL = V$S;
  SUSPEND;

  --изменения по ученику
  TAG_NAME = 'changes::json&colon;array';
  VAL = 1;
  SUSPEND;
  N = 1;
  FOR
    SELECT R.VAL, H.DATE_ADD, H.VAL, H.OLD_VAL, P.PARAM_TYPE, IIF(U.OBJ_ID IS NULL, NM.FULL_NAME, USR.SCAPTION), U.USER_ID
    FROM HISTVALS H
    LEFT JOIN USERS U ON U.USER_ID = H.USER_ID
    LEFT JOIN OBJECT_CAPTION_GET(U.OBJ_ID) USR ON 1 = 1
    LEFT JOIN BUILD_FIO(U.LAST_NAME, U.FIRST_NAME, U.MIDDLE_NAME) NM ON 1 = 1
    JOIN PARAMS P ON P.PARAM_ID = H.PARAM_ID
    JOIN RES R ON R.RES_ID = P.RES_ID AND R.LANG_CODE = 'RU'
    WHERE H.OBJ_ID = :I$OBJ_ID AND H.TABLE_NAME = 'VAL'
    INTO :V$S, :V$DT, :V$VAL, :V$VAL_OLD, :V$TYPE_ID, :V$USER_NAME, :V$VAL_ID
  DO
  BEGIN
    IF(V$VAL_ID = 1) THEN V$USER_NAME = 'Администратор';

    TAG_NAME = 'changes:item';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'changes:item:Индекс';
    VAL = N;
    N = N + 1;
    SUSPEND;
    TAG_NAME = 'changes:item:Параметр';
    VAL = V$S;
    SUSPEND;
    TAG_NAME = 'changes:item:Дата';
    SELECT RESULT FROM DATE2STR(:V$DT) INTO :VAL;
    SUSPEND;

    -- Для списковых параметров меняем id на текст
    IF(V$TYPE_ID = 6) THEN
    BEGIN
      IF(V$VAL_OLD IS NOT NULL AND V$VAL_OLD <> '') THEN
      BEGIN
        BEGIN
          V$VAL_ID = V$VAL_OLD;
          WHEN ANY DO V$VAL_ID = NULL;
        END
        SELECT FIRST 1 V.VAL
        FROM LISTVAL_TEXT(:V$VAL_ID) V
        INTO :V$VAL_OLD;
      END
      IF(V$VAL IS NOT NULL AND V$VAL <> '') THEN
      BEGIN
        BEGIN
          V$VAL_ID = V$VAL;
          WHEN ANY DO V$VAL_ID = NULL;
        END
        SELECT FIRST 1 V.VAL
        FROM LISTVAL_TEXT(:V$VAL_ID) V
        INTO :V$VAL;
      END
    END

    TAG_NAME = 'changes:item:Новое_значение';
    VAL = V$VAL;
    SUSPEND;
    TAG_NAME = 'changes:item:Старое_значение';
    VAL = V$VAL_OLD;
    SUSPEND;
    TAG_NAME = 'changes:item:Пользователь';
    VAL = V$USER_NAME;
    SUSPEND;
  END

  -- дата открытия и закрытия личного дела, название учебного коллектива куда принят и откуда выбыл в конце (person_movements)
  -- найдем дату последнего отчисления из ОУ
  V$DISCHARGE_DT = NULL; V$VAL_OLD = NULL;
  SELECT FIRST 1 PM.DATE_OUT, GR.SCAPTION
  FROM PERSON_MOVEMENTS PM
  LEFT JOIN LISTVALS LV ON LV.LISTVAL_ID = PM.REASON_OUT
  LEFT JOIN OBJECT_CAPTION_GET(PM.GROUP_ID) GR ON 1 = 1
  WHERE PM.DATE_DEL IS NULL AND PM.PERSON_ID = :I$OBJ_ID
    AND PM.GROUP_TYPE_ID IN (9, 187)   --класс, экстернат
    AND (PM.REASON_OUT IS NULL OR LV."FILTER" NOT LIKE '%TRANSFERED%')
  ORDER BY PM.DATE_OUT DESC
  INTO :V$DISCHARGE_DT, :V$VAL_OLD;

  -- дата открытия ЛД
  V$LD_OPEN_DT = NULL; V$S = NULL; V$ADMISSION_DT = NULL;  --дата подачи заявления о зачислении на ребенка. Заносим сюда дату добавления записи о движении
  SELECT FIRST 1 PM.DATE_IN, GR.SCAPTION, PM.DATE_ADD
  FROM PERSON_MOVEMENTS PM
  LEFT JOIN OBJECT_CAPTION_GET(PM.GROUP_ID) GR ON 1 = 1
  WHERE PM.DATE_DEL IS NULL AND PM.PERSON_ID = :I$OBJ_ID AND PM.GROUP_TYPE_ID IN (9, 187) AND (:V$DISCHARGE_DT IS NULL OR PM.DATE_IN >= :V$DISCHARGE_DT)
  ORDER BY PM.DATE_IN
  INTO :V$LD_OPEN_DT, :V$S, :V$ADMISSION_DT;

  -- Если V$LD_OPEN_DT пуста, значит студент в данный момент отчислен в первый раз. Надо найти дату зачисления и дату подачи заявления
  IF (V$LD_OPEN_DT IS NULL) THEN
  BEGIN
    V$ADMISSION_DT = NULL;
    SELECT FIRST 1 PM.DATE_IN, PM.DATE_ADD
    FROM PERSON_MOVEMENTS PM
    WHERE PM.DATE_DEL IS NULL AND PM.PERSON_ID = :I$OBJ_ID AND PM.GROUP_TYPE_ID IN (9, 187)
    ORDER BY PM.DATE_IN
    INTO :V$LD_OPEN_DT, V$ADMISSION_DT;
  END

  TAG_NAME = 'Дата_открытия_дела';
  SELECT RESULT FROM DATE2STR(:V$LD_OPEN_DT) INTO :VAL;
  SUSPEND;
  TAG_NAME = 'Класс_куда_зачислен';
  VAL = V$S;
  SUSPEND;

  IF (V$ADMISSION_DT > V$LD_OPEN_DT) THEN V$ADMISSION_DT = V$LD_OPEN_DT;

  -- дата закрытия ЛД
  IF (V$DISCHARGE_DT IS NULL OR V$LD_OPEN_DT > V$DISCHARGE_DT) THEN
  BEGIN 
    V$DT = NULL;
  END
  ELSE
  BEGIN
    V$DT = V$DISCHARGE_DT;
  END
  SELECT RESULT FROM DATE2STR(:V$DT) INTO :VAL;
  TAG_NAME = 'Дата_выбытия';
  SUSPEND;

  -- Класс, из которого выбыл, или текущий класс
  VAL = NULL;
  IF (V$DISCHARGE_DT IS NULL OR V$LD_OPEN_DT > V$DISCHARGE_DT) THEN
  BEGIN 
    --найдем текущий класс
    SELECT FIRST 1 GR.SCAPTION
    FROM PERSON_MOVEMENTS PM
    LEFT JOIN OBJECT_CAPTION_GET(PM.GROUP_ID) GR ON 1 = 1
    WHERE PM.DATE_DEL IS NULL AND PM.PERSON_ID = :I$OBJ_ID AND PM.GROUP_TYPE_ID IN (9, 187)   --класс, экстернат
    ORDER BY PM.DATE_IN DESC
    INTO :VAL;
  END
  ELSE
  BEGIN
    VAL = V$VAL_OLD;
  END
  TAG_NAME = 'Класс_откуда_выбыл';
  SUSPEND;

  -- Документы для описи. Документы, необходимые для зачисления ребенка в школу
  TAG_NAME = 'extra_docs::json&colon;array';
  VAL = 1;
  SUSPEND;
  N = 1;

  -- Скорректируем дату подачи заявления о зачислении на ребенка, если ребенок был принят через предварительный прием
  V$DT = NULL;
  SELECT FIRST 1 L.DATE_INS
  FROM LINKS L
  WHERE L.OBJ_ID = :I$OBJ_ID AND L.PARENT_TYPE_ID = 290
  INTO :V$DT;
  IF (V$DT IS NOT NULL AND V$DT < V$ADMISSION_DT) THEN V$ADMISSION_DT = V$DT;

  -- Документы, удостоверяющий личность обучающегося
  FOR
    SELECT L79.OBJ_ID, LV441.VAL, V576.VAL, V576.BLOB_ID, V563.VAL, V442.VAL, V562.VAL, V562.VAL
    FROM LINKS L79
    JOIN VALL V441 ON V441.OBJ_ID = L79.OBJ_ID AND V441.PARAM_ID = 441 AND V441.IS_DEL = 0
    LEFT JOIN LISTVAL_TEXT(V441.LISTVAL_ID) LV441 ON 1 = 1
    LEFT JOIN VALS V563 ON V563.OBJ_ID = L79.OBJ_ID AND V563.PARAM_ID = 563 AND V563.IS_DEL = 0
    LEFT JOIN VALS V442 ON V442.OBJ_ID = L79.OBJ_ID AND V442.PARAM_ID = 442 AND V442.IS_DEL = 0   -- серия
    LEFT JOIN VALS V559 ON V559.OBJ_ID = L79.OBJ_ID AND V559.PARAM_ID = 559 AND V559.IS_DEL = 0   -- номер
    LEFT JOIN VALS V562 ON V562.OBJ_ID = L79.OBJ_ID AND V562.PARAM_ID = 562 AND V562.IS_DEL = 0   -- кем выдан
    JOIN VALD V560 ON V560.OBJ_ID = L79.OBJ_ID AND V560.PARAM_ID = 560 AND V560.IS_DEL = 0 AND V560.VAL <= :V$ADMISSION_DT -- выданы до даты подачи заявления в школу о зачислении
    JOIN VALB V576 ON V576.OBJ_ID = L79.OBJ_ID AND V576.PARAM_ID = 576 AND V576.IS_DEL = 0
    JOIN VALL V614 ON V614.OBJ_ID = L79.OBJ_ID AND V614.PARAM_ID = 614 AND V614.IS_DEL = 0 AND V614.LISTVAL_ID = 1982 -- действующий
    WHERE L79.OBJ_TYPE_ID = 79 AND L79.PARENT_ID = :I$OBJ_ID AND L79.DATE_DEL IS NULL
    INTO :V$DOC_ID, :V$S, :V$VAL, :V$ID, :V$VAL_OLD, :V$REASON_IN, :V$REASON_OUT, :V$GRADE
  DO
  BEGIN
    TAG_NAME = 'extra_docs:item';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'extra_docs:item:id';
    VAL = V$DOC_ID;
    SUSPEND;
    TAG_NAME = 'extra_docs:item:Тип_документа';
    VAL = V$S || ' обучающегося';
    SUSPEND;
    TAG_NAME = 'extra_docs:item:Серия';
    VAL = V$REASON_IN;
    SUSPEND;
    TAG_NAME = 'extra_docs:item:Номер';
    VAL = V$REASON_OUT;
    SUSPEND;
    TAG_NAME = 'extra_docs:item:Кем_выдан';
    VAL = V$GRADE;
    SUSPEND;
    TAG_NAME = 'extra_docs:item:filename';
    VAL = V$VAL;
    SUSPEND;
    TAG_NAME = 'extra_docs:item:blob_id';
    VAL = V$ID;
    SUSPEND;
    TAG_NAME = 'extra_docs:item:Примечание';
    VAL = V$VAL_OLD;
    SUSPEND;
    TAG_NAME = 'extra_docs:item:Индекс';
    VAL = N;
    N = N + 1;
    SUSPEND;
  END

  -- Прочие документы обучающегося, тип 12
  FOR
    SELECT L12.OBJ_ID, LV51.VAL, V578.VAL, V578.BLOB_ID, V575.VAL
    FROM LINKS L12
    LEFT JOIN VALL V51 ON V51.OBJ_ID = L12.OBJ_ID AND V51.PARAM_ID = 51 AND V51.IS_DEL = 0
    LEFT JOIN LISTVAL_TEXT(V51.LISTVAL_ID) LV51 ON 1 = 1
    LEFT JOIN VALD V572 ON V572.OBJ_ID = L12.OBJ_ID AND V572.PARAM_ID = 572 AND V572.IS_DEL = 0
    LEFT JOIN VALB V578 ON V578.OBJ_ID = L12.OBJ_ID AND V578.PARAM_ID = 578 AND V578.IS_DEL = 0
    LEFT JOIN VALS V575 ON V575.OBJ_ID = L12.OBJ_ID AND V575.PARAM_ID = 575 AND V575.IS_DEL = 0
    WHERE L12.OBJ_TYPE_ID = 12 AND L12.PARENT_ID = :I$OBJ_ID AND L12.DATE_DEL IS NULL
      AND (V51.LISTVAL_ID IN (1384, 14303) OR V572.VAL <= :V$ADMISSION_DT)  --выдано ДО подачи заявления на зачисление
      AND (V51.LISTVAL_ID NOT IN (1384, 14303) OR DATEDIFF(DAY, :V$ADMISSION_DT, L12.DATE_INS) <= 10)
    INTO :V$DOC_ID, :V$S, :V$VAL, :V$ID, :V$VAL_OLD
  DO
  BEGIN
    TAG_NAME = 'extra_docs:item';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'extra_docs:item:id';
    VAL = V$DOC_ID;
    SUSPEND;
    TAG_NAME = 'extra_docs:item:Тип_документа';
    VAL = V$S || ' обучающегося';
    SUSPEND;
    TAG_NAME = 'extra_docs:item:filename';
    VAL = V$VAL;
    SUSPEND;
    TAG_NAME = 'extra_docs:item:blob_id';
    VAL = V$ID;
    SUSPEND;
    TAG_NAME = 'extra_docs:item:Примечание';
    VAL = V$VAL_OLD;
    SUSPEND;
    TAG_NAME = 'extra_docs:item:Индекс';
    VAL = N;
    N = N + 1;
    SUSPEND;
  END

  -- документы для описи, удостоверяющие личность родителя, который первый был добавлен в систему, найдем документы родителя, которые были выданы до даты подачи заявления в школу о зачислении
  FOR
    SELECT L79.OBJ_ID, LV441.VAL, V576.VAL, V576.BLOB_ID, V563.VAL
    FROM LINKS L79
    JOIN VALL V441 ON V441.OBJ_ID = L79.OBJ_ID AND V441.PARAM_ID = 441 AND V441.IS_DEL = 0
    LEFT JOIN LISTVAL_TEXT(V441.LISTVAL_ID) LV441 ON 1 = 1
    JOIN VALL V614 ON V614.OBJ_ID = L79.OBJ_ID AND V614.PARAM_ID = 614 AND V614.IS_DEL = 0 AND V614.LISTVAL_ID = 1982  -- действующий
    JOIN VALD V560 ON V560.OBJ_ID = L79.OBJ_ID AND V560.PARAM_ID = 560 AND V560.IS_DEL = 0 AND V560.VAL <= :V$ADMISSION_DT
    LEFT JOIN VALB V576 ON V576.OBJ_ID = L79.OBJ_ID AND V576.PARAM_ID = 576 AND V576.IS_DEL = 0
    LEFT JOIN VALS V563 ON V563.OBJ_ID = L79.OBJ_ID AND V563.PARAM_ID = 563 AND V563.IS_DEL = 0
    WHERE L79.OBJ_TYPE_ID = 79 AND L79.DATE_DEL IS NULL
      AND L79.PARENT_ID = (SELECT FIRST 1 L20.OBJ_ID FROM LINKS L20 WHERE L20.OBJ_TYPE_ID = 20 AND L20.PARENT_ID = :I$OBJ_ID AND L20.DATE_DEL IS NULL ORDER BY L20.DATE_INS) -- родитель, подавший заявление на зачисление
    INTO :V$DOC_ID, :V$S, :V$VAL, :V$ID, :V$VAL_OLD
  DO
  BEGIN
    TAG_NAME = 'extra_docs:item';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'extra_docs:item:id';
    VAL = V$DOC_ID;
    SUSPEND;
    TAG_NAME = 'extra_docs:item:Тип_документа';
    VAL = V$S || ' родителя/законного представителя';
    SUSPEND;
    TAG_NAME = 'extra_docs:item:filename';
    VAL = V$VAL;
    SUSPEND;
    TAG_NAME = 'extra_docs:item:blob_id';
    VAL = V$ID;
    SUSPEND;
    TAG_NAME = 'extra_docs:item:Примечание';
    VAL = V$VAL_OLD;
    SUSPEND;
    TAG_NAME = 'extra_docs:item:Индекс';
    VAL = N;
    N = N + 1;
    SUSPEND;
  END

  -- Документы для описи, удостоверяющий положение законного представителя по отношению к ребенку (#294), которые были выданы до даты подачи заявления в школу о зачислении
  FOR
    SELECT L294.OBJ_ID, V2366.VAL, V2370.VAL, V2370.BLOB_ID
    FROM LINKS L294
    JOIN VALD V2368 ON V2368.OBJ_ID = L294.OBJ_ID AND V2368.PARAM_ID = 2368 AND V2368.IS_DEL = 0 AND V2368.VAL <= :V$ADMISSION_DT -- выданы до даты подачи заявления в школу о зачислении
    JOIN VALS V2366 ON V2366.OBJ_ID = L294.OBJ_ID AND V2366.PARAM_ID = 2366 AND V2366.IS_DEL = 0
    LEFT JOIN VALB V2370 ON V2370.OBJ_ID = L294.OBJ_ID AND V2370.PARAM_ID = 2370 AND V2370.IS_DEL = 0
    LEFT JOIN VALR V3469 ON V3469.OBJ_ID = L294.OBJ_ID AND V3469.PARAM_ID = 3469 AND V3469.IS_DEL = 0 AND (V3469.VAL IS NULL OR V3469.VAL = :I$OBJ_ID)  -- документы тип 294 если не привязаны к ребенку или привязаны к данному конкретному ребенку)
    WHERE L294.OBJ_TYPE_ID = 294 AND L294.PARENT_ID = :V$ID AND DATE_DEL IS NULL
    INTO :V$DOC_ID, :V$S, :V$VAL, :V$ID
  DO
  BEGIN
    TAG_NAME = 'extra_docs:item';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'extra_docs:item:id';
    VAL = V$DOC_ID;
    SUSPEND;
    TAG_NAME = 'extra_docs:item:Тип_документа';
    VAL = V$S;
    SUSPEND;
    TAG_NAME = 'extra_docs:item:filename';
    VAL = V$VAL;
    SUSPEND;
    TAG_NAME = 'extra_docs:item:blob_id';
    VAL = V$ID;
    SUSPEND;
    TAG_NAME = 'extra_docs:item:Индекс';
    VAL = N;
    N = N + 1;
    SUSPEND;
  END

  -- документ об образовании, предъявленный при поступлении в школу
  FOR
    SELECT L11.OBJ_ID, CAP.VAL, V577.VAL, V577.BLOB_ID
    FROM LINKS L11
    JOIN VALD V566 ON V566.OBJ_ID = L11.OBJ_ID AND V566.PARAM_ID = 566 AND V566.IS_DEL = 0 AND V566.VAL <= :V$ADMISSION_DT -- выданы до даты подачи заявления в школу о зачислении
    JOIN VALL V50 ON V50.OBJ_ID = L11.OBJ_ID AND V50.PARAM_ID = 50 AND V50.IS_DEL = 0
    LEFT JOIN LISTVAL_TEXT(V50.LISTVAL_ID) CAP ON 1 = 1
    JOIN VALB V577 ON V577.OBJ_ID = L11.OBJ_ID AND V577.PARAM_ID = 577 AND V577.IS_DEL = 0
    WHERE L11.OBJ_TYPE_ID = 11 AND L11.PARENT_ID = :I$OBJ_ID AND L11.DATE_DEL IS NULL
    INTO :V$DOC_ID, :V$S, :V$VAL, :V$ID
  DO
  BEGIN
    TAG_NAME = 'extra_docs:item';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'extra_docs:item:id';
    VAL = V$DOC_ID;
    SUSPEND;
    TAG_NAME = 'extra_docs:item:Тип_документа';
    VAL = V$S;
    SUSPEND;
    TAG_NAME = 'extra_docs:item:filename';
    VAL = V$VAL;
    SUSPEND;
    TAG_NAME = 'extra_docs:item:blob_id';
    VAL = V$ID;
    SUSPEND;
    TAG_NAME = 'extra_docs:item:Индекс';
    VAL = N;
    N = N + 1;
    SUSPEND;
  END

  -- Документы, удостоверяющий личность обучающегося
  TAG_NAME = 'documents::json&colon;array';
  VAL = 1;
  SUSPEND;
  N = 1;
  FOR
    SELECT L79.OBJ_ID, LV441.VAL, V442.VAL, V559.VAL, V560.VAL, V561.VAL, V562.VAL, V563.VAL, V576.VAL, V576.BLOB_ID, LV614.VAL
    FROM LINKS L79
    JOIN VALL V441 ON V441.OBJ_ID = L79.OBJ_ID AND V441.PARAM_ID = 441 AND V441.IS_DEL = 0
    LEFT JOIN LISTVAL_TEXT(V441.LISTVAL_ID) LV441 ON 1 = 1
    JOIN VALS V442 ON V442.OBJ_ID = L79.OBJ_ID AND V442.PARAM_ID = 442 AND V442.IS_DEL = 0
    JOIN VALS V559 ON V559.OBJ_ID = L79.OBJ_ID AND V559.PARAM_ID = 559 AND V559.IS_DEL = 0
    LEFT JOIN VALD V560 ON V560.OBJ_ID = L79.OBJ_ID AND V560.PARAM_ID = 560 AND V560.IS_DEL = 0
    LEFT JOIN VALD V561 ON V561.OBJ_ID = L79.OBJ_ID AND V561.PARAM_ID = 561 AND V561.IS_DEL = 0
    LEFT JOIN VALS V562 ON V562.OBJ_ID = L79.OBJ_ID AND V562.PARAM_ID = 562 AND V562.IS_DEL = 0
    LEFT JOIN VALS V563 ON V563.OBJ_ID = L79.OBJ_ID AND V563.PARAM_ID = 563 AND V563.IS_DEL = 0
    LEFT JOIN VALB V576 ON V576.OBJ_ID = L79.OBJ_ID AND V576.PARAM_ID = 576 AND V576.IS_DEL = 0
    JOIN VALL V614 ON V614.OBJ_ID = L79.OBJ_ID AND V614.PARAM_ID = 614 AND V614.IS_DEL = 0 AND V614.LISTVAL_ID = 1982 -- действующий
    LEFT JOIN LISTVAL_TEXT(V614.LISTVAL_ID) LV614 ON 1 = 1
    WHERE L79.OBJ_TYPE_ID = 79 AND L79.PARENT_ID = :I$OBJ_ID AND L79.DATE_DEL IS NULL
    INTO :V$ID, :V$S, :V$VAL, :V$VAL_OLD, :V$DT, :V$DT2, :V$GRADE, :V$USER_NAME, :V$REASON_IN, :V$DOC_ID, :V$REASON_OUT
  DO
  BEGIN
    TAG_NAME = 'documents:item';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'documents:item:id';
    VAL = V$ID;
    SUSPEND;
    TAG_NAME = 'documents:item:Тип_документа';
    VAL = V$S;
    SUSPEND;
    TAG_NAME = 'documents:item:Серия';
    VAL = V$VAL;
    SUSPEND;
    TAG_NAME = 'documents:item:Номер';
    VAL = V$VAL_OLD;
    SUSPEND;
    TAG_NAME = 'documents:item:Дата_выдачи';
    SELECT RESULT FROM DATE2STR(:V$DT) INTO :VAL;
    SUSPEND;
    TAG_NAME = 'documents:item:Дата_окончания';
    SELECT RESULT FROM DATE2STR(:V$DT2) INTO :VAL;
    SUSPEND;
    TAG_NAME = 'documents:item:Кем_выдан';
    VAL = V$GRADE;
    SUSPEND;
    TAG_NAME = 'documents:item:Примечания';
    VAL = V$USER_NAME;
    SUSPEND;
    TAG_NAME = 'documents:item:scan_filename';
    VAL = V$REASON_IN;
    SUSPEND;
    TAG_NAME = 'documents:item:scan_blob';
    VAL = V$DOC_ID;
    SUSPEND;
    TAG_NAME = 'documents:item:Статус';
    VAL = V$REASON_OUT;
    SUSPEND;
    TAG_NAME = 'documents:item:Индекс';
    VAL = N;
    N = N + 1;
    SUSPEND;
  END

  -- данные по инвалидности
  TAG_NAME = 'disability::json&colon;array';
  VAL = 1;
  SUSPEND;
  N = 1;
  FOR
    SELECT LV2373.VAL, LV2374.VAL, V2375.VAL
    FROM LINKS L295
    LEFT JOIN VALL V2373 ON V2373.OBJ_ID = L295.OBJ_ID AND V2373.PARAM_ID = 2373 AND V2373.IS_DEL = 0
    LEFT JOIN LISTVAL_TEXT(V2373.LISTVAL_ID) LV2373 ON 1 = 1
    LEFT JOIN VALL V2374 ON V2374.OBJ_ID = L295.OBJ_ID AND V2374.PARAM_ID = 2374 AND V2374.IS_DEL = 0
    LEFT JOIN LISTVAL_TEXT(V2374.LISTVAL_ID) LV2374 ON 1 = 1
    LEFT JOIN VALD V2375 ON V2375.OBJ_ID = L295.OBJ_ID AND V2375.PARAM_ID = 2375 AND V2375.IS_DEL = 0
    WHERE L295.OBJ_TYPE_ID = 295 AND L295.PARENT_ID = :I$OBJ_ID AND L295.DATE_DEL IS NULL
    INTO :V$S, :V$VAL, :V$DT
  DO
  BEGIN
    TAG_NAME = 'disability:item';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'disability:item:Группа';
    VAL = V$S;
    SUSPEND;
    TAG_NAME = 'disability:item:Категория';
    VAL = V$VAL;
    SUSPEND;
    TAG_NAME = 'disability:item:Действует_до';
    SELECT RESULT FROM DATE2STR(:V$DT) INTO :VAL;
    SUSPEND;
    TAG_NAME = 'disability:item:Индекс';
    VAL = N;
    N = N + 1;
    SUSPEND;
  END

  -- Специальные условия и мероприятия
  TAG_NAME = 'specterms::json&colon;array';
  VAL = 1;
  SUSPEND;
  N = 1;
  FOR
    SELECT V3307.VAL, LV3306.VAL, V3308.VAL, V3309.VAL, LV3310.VAL
    FROM LINKS L461
    LEFT JOIN VALD V3307 ON V3307.OBJ_ID = L461.OBJ_ID AND V3307.PARAM_ID = 3307 AND V3307.IS_DEL = 0
    LEFT JOIN VALL V3306 ON V3306.OBJ_ID = L461.OBJ_ID AND V3306.PARAM_ID = 3306 AND V3306.IS_DEL = 0
    LEFT JOIN LISTVAL_TEXT(V3306.LISTVAL_ID) LV3306 ON 1 = 1
    LEFT JOIN VALD V3308 ON V3308.OBJ_ID = L461.OBJ_ID AND V3308.PARAM_ID = 3308 AND V3308.IS_DEL = 0
    LEFT JOIN VALS V3309 ON V3309.OBJ_ID = L461.OBJ_ID AND V3309.PARAM_ID = 3309 AND V3309.IS_DEL = 0
    LEFT JOIN VALL V3310 ON V3310.OBJ_ID = L461.OBJ_ID AND V3310.PARAM_ID = 3310 AND V3310.IS_DEL = 0
    LEFT JOIN LISTVAL_TEXT(V3310.LISTVAL_ID) LV3310 ON 1 = 1
    WHERE L461.OBJ_TYPE_ID = 461 AND L461.PARENT_ID = :I$OBJ_ID AND L461.DATE_DEL IS NULL
    INTO :V$DT, :V$VAL, :V$DT2, :V$VAL_OLD, :V$S
  DO
  BEGIN
    TAG_NAME = 'specterms:item';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'specterms:item:Дата';
    SELECT RESULT FROM DATE2STR(:V$DT) INTO :VAL;
    SUSPEND;
    TAG_NAME = 'specterms:item:Требования';
    VAL = V$VAL;
    SUSPEND;
    TAG_NAME = 'specterms:item:Действует_до';
    SELECT RESULT FROM DATE2STR(:V$DT2) INTO :VAL;
    SUSPEND;
    TAG_NAME = 'specterms:item:Содержание';
    VAL = V$VAL_OLD;
    SUSPEND;
    TAG_NAME = 'specterms:item:Выполнено';
    VAL = V$S;
    SUSPEND;
    TAG_NAME = 'specterms:item:Индекс';
    VAL = N;
    N = N + 1;
    SUSPEND;
  END

  -- данные по родителям
  TAG_NAME = 'parents::json&colon;array';
  VAL = 1;
  SUSPEND;
  N = 1;
  FOR
    SELECT L20.OBJ_ID, REL.VAL, ST.VAL
    FROM LINKS L20
    LEFT JOIN VALL V1562 ON V1562.OBJ_ID = L20.EXT_OBJ_ID AND V1562.PARAM_ID = 1562 AND V1562.IS_DEL = 0
    LEFT JOIN LISTVAL_TEXT(V1562.LISTVAL_ID) ST ON 1 = 1
    LEFT JOIN VALL V1573 ON V1573.OBJ_ID = L20.EXT_OBJ_ID AND V1573.PARAM_ID = 1573 AND V1573.IS_DEL = 0
    LEFT JOIN LISTVAL_TEXT(V1573.LISTVAL_ID) REL ON 1 = 1
    WHERE L20.OBJ_TYPE_ID = 20 AND L20.PARENT_ID = :I$OBJ_ID AND L20.DATE_DEL IS NULL
    INTO :V$ID, :V$VAL, :V$VAL_OLD
  DO
  BEGIN
    TAG_NAME = 'parents:item';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'parents:item:Индекс';
    VAL = N;
    N = N + 1;
    SUSPEND;
    TAG_NAME = 'parents:item:Степень_родства';
    VAL = V$VAL;
    SUSPEND;
    TAG_NAME = 'parents:item:Юридический_статус';
    VAL = V$VAL_OLD;
    SUSPEND;

    VAL = NULL;
    V$S = NULL;
    V$GRADE = NULL;
    V$REASON_IN = NULL;
    V$REASON_OUT = NULL;
    V$D1 = NULL;
    SELECT FIRST 1 LV441.VAL, V442.VAL, V559.VAL, V562.VAL, V560.VAL
    FROM LINKS L79
    JOIN VALL V441 ON V441.OBJ_ID = L79.OBJ_ID AND V441.PARAM_ID = 441 AND V441.IS_DEL = 0
    LEFT JOIN LISTVAL_TEXT(V441.LISTVAL_ID) LV441 ON 1 = 1
    JOIN VALS V442 ON V442.OBJ_ID = L79.OBJ_ID AND V442.PARAM_ID = 442 AND V442.IS_DEL = 0
    JOIN VALS V559 ON V559.OBJ_ID = L79.OBJ_ID AND V559.PARAM_ID = 559 AND V559.IS_DEL = 0
    JOIN VALL V614 ON V614.OBJ_ID = L79.OBJ_ID AND V614.PARAM_ID = 614 AND V614.IS_DEL = 0 AND V614.LISTVAL_ID = 1982  -- действующий
    JOIN VALD V560 ON V560.OBJ_ID = L79.OBJ_ID AND V560.PARAM_ID = 560 AND V560.IS_DEL = 0 --AND V560.VAL <= :V$ADMISSION_DT
    LEFT JOIN VALS V562 ON V562.OBJ_ID = L79.OBJ_ID AND V562.PARAM_ID = 562 AND V562.IS_DEL = 0
    LEFT JOIN VALS V563 ON V563.OBJ_ID = L79.OBJ_ID AND V563.PARAM_ID = 563 AND V563.IS_DEL = 0
    WHERE L79.OBJ_TYPE_ID = 79 AND L79.DATE_DEL IS NULL AND L79.PARENT_ID = :V$ID
    ORDER BY V560.VAL DESC
    INTO :V$REASON_OUT, :V$S, :V$GRADE, :V$REASON_IN, :V$D1;
    IF (V$REASON_OUT IS NOT NULL AND V$S IS NOT NULL AND V$GRADE IS NOT NULL) THEN
    BEGIN
      TAG_NAME = 'parents:item:Тип_документа';
      VAL = V$REASON_OUT;
      SUSPEND;
      TAG_NAME = 'parents:item:Данные_документа';
      SELECT RESULT FROM DATE2STR(:V$D1) INTO VAL;
      VAL = V$S || '№' ||V$GRADE || ' выдан ' || V$REASON_IN || ', дата выдачи' || COALESCE(VAL, 'нет данных');
      SUSPEND;
    END
    FOR
      SELECT P.PARAM_ID, R.VAL, IIF(V.IS_EXISTS = 1, V.V, NULL)
      FROM PARAMS P
      JOIN RES R ON R.RES_ID = P.RES_ID AND LANG_CODE = 'RU'
      LEFT JOIN VAL_GET(:V$ID, P.PARAM_ID) V ON 1 = 1
      WHERE P.IS_DEL = 0 AND P.TYPE_ID = 20 -- relatives
      INTO :V$PARAM_ID, :TAG_NAME, :VAL
    DO
    BEGIN
      TAG_NAME = REPLACE(TAG_NAME, ' ', '_');
      TAG_NAME = REPLACE(TAG_NAME, '-', '_');
      TAG_NAME = REPLACE(TAG_NAME, '/', '_');
      TAG_NAME = REPLACE(TAG_NAME, '\', '_');
      TAG_NAME = REPLACE(TAG_NAME, '.', '_');
      TAG_NAME = REPLACE(TAG_NAME, ',', '_');
      TAG_NAME = REPLACE(TAG_NAME, '"', '_');
      TAG_NAME = REPLACE(TAG_NAME, '(', '_');
      TAG_NAME = REPLACE(TAG_NAME, ')', '_');
      TAG_NAME = REPLACE(TAG_NAME, '__', '_');

      TAG_NAME = 'parents:item:' || TAG_NAME;
      IF (VAL IS NULL) THEN VAL = 'нет данных';
      SUSPEND;
    END
  END

  -- Массив movements (только по движению в обычных классах, семейное обучение и академический отпуск)
  TAG_NAME = 'movements::json&colon;array';
  VAL = 1;
  SUSPEND;
  N = 1;
  FOR
    SELECT PM.DATE_IN, PM.DATE_OUT, R_IN.VAL, R_OUT.VAL, GR.SCAPTION, LV_ST.VAL
    FROM PERSON_MOVEMENTS PM
    LEFT JOIN OBJECT_CAPTION_GET(PM.GROUP_ID) GR ON 1 = 1
    JOIN LISTVALS LV_IN ON LV_IN.LISTVAL_ID = PM.REASON_IN AND LV_IN.LIST_ID = 122 AND LV_IN.IS_DEL = 0
    JOIN RES R_IN ON R_IN.RES_ID = LV_IN.RES_ID AND R_IN.IS_DEL = 0 AND R_IN.LANG_CODE = 'RU'
    JOIN LISTVALS LV_OUT ON LV_OUT.LISTVAL_ID = PM.REASON_OUT AND LV_OUT.LIST_ID = 122 AND LV_OUT.IS_DEL = 0
    JOIN RES R_OUT ON R_OUT.RES_ID = LV_OUT.RES_ID AND R_OUT.IS_DEL = 0 AND R_OUT.LANG_CODE = 'RU'
    LEFT JOIN LISTVAL_TEXT(PM.STAGE_ID) LV_ST ON 1 = 1
    WHERE PM.DATE_DEL IS NULL AND PM.PERSON_ID = :I$OBJ_ID AND PM.GROUP_TYPE_ID IN (9, 187, 289)                        -- класс, экстернат
      AND (PM.REASON_OUT IS NULL OR LV_OUT."FILTER" NOT LIKE '%TRANSFERED%' OR LV_IN."FILTER" NOT LIKE '%TRANSFERED%')  -- исключаем переводы внутри параллели
    ORDER BY PM.DATE_IN, PM.DATE_ADD
    INTO :V$DT, :V$DT2, :V$REASON_IN, :V$REASON_OUT, :V$GRADE, :V$VAL_OLD
  DO
  BEGIN
    TAG_NAME = 'movements:item';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'movements:item:Дата_начала';
    VAL = NULL;
    SELECT RESULT FROM DATE2STR(:V$DT) INTO :VAL;
    SUSPEND;
    TAG_NAME = 'movements:item:Основание_начала';
    VAL = V$REASON_IN;
    SUSPEND;
    TAG_NAME = 'movements:item:Дата_окончания';
    VAL = NULL;
    SELECT RESULT FROM DATE2STR(:V$DT2) INTO :VAL;
    SUSPEND;
    TAG_NAME = 'movements:item:Основание_окончания';
    VAL = V$REASON_OUT;
    SUSPEND;
    TAG_NAME = 'movements:item:Этап_обучения';
    VAL = V$VAL_OLD;
    SUSPEND;
    TAG_NAME = 'movements:item:Учебный_коллектив';
    VAL = V$GRADE;
    SUSPEND;
    TAG_NAME = 'movements:item:Индекс';
    VAL = N;
    N = N + 1;
    SUSPEND;
  END

  -- оценки, итоговая успеваемость, если выставлена хоть одна годовая оценка
  -- пока не учитываем, что в одном году может быть аттестация за несколько этапов

  TAG_NAME = 'marks_final::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT DISTINCT MA.YEAR_ID, MA.STAGE_ID
    FROM VALM MA
    JOIN LISTVALS LV ON LV.LISTVAL_ID = MA.YEAR_ID -- порядок в списке учебных годов имеет косяки, надо сортировать по индексу
    WHERE MA.IS_DEL = 0 AND MA.PUPIL_ID = :I$OBJ_ID AND (MA.IS_NATIVE IS NULL OR MA.IS_NATIVE = 1)
      AND (LV.COST < 300 OR LV.COST > 400) -- не считаем тут модули
    ORDER BY LV.COST, 2
    INTO :V$DOC_ID, :V$STAGE_ID
  DO
  BEGIN
    TAG_NAME = 'marks_final:M';
    VAL = NULL;
    SUSPEND;

    TAG_NAME = 'marks_final:M:Год';
    SELECT VAL FROM LISTVAL_TEXT(:V$DOC_ID) INTO :VAL;
    SUSPEND;

    TAG_NAME = 'marks_final:M:Этап_обучения';
    IF(VAL IS NULL) THEN VAL = 'Не указан';
    ELSE SELECT VAL FROM LISTVAL_TEXT(:V$STAGE_ID) INTO :VAL;
    SUSPEND;

    TAG_NAME = 'marks_final:M:marks::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT DISTINCT MA.SUBJECT_ID, CAP.SCAPTION
      FROM VALM MA
      JOIN LISTVALS LV ON LV.LISTVAL_ID = MA.YEAR_ID
      LEFT JOIN OBJECT_CAPTION_GET(MA.SUBJECT_ID) CAP ON 1 = 1
      WHERE MA.IS_DEL = 0 AND MA.PUPIL_ID = :I$OBJ_ID AND MA.YEAR_ID = :V$DOC_ID AND (MA.IS_NATIVE IS NULL OR MA.IS_NATIVE = 1)
        AND (LV.COST < 300 OR LV.COST > 400) -- не считаем тут модули
        AND ((MA.STAGE_ID IS NULL AND :V$STAGE_ID IS NULL) OR MA.STAGE_ID = :V$STAGE_ID)
      ORDER BY CAP.SCAPTION  -- сортируем по алфавиту
      INTO :V$ID, :V$VAL
    DO
    BEGIN
      TAG_NAME = 'marks_final:M:marks:item';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'marks_final:M:marks:item:Предмет';
      VAL = V$VAL;
      SUSPEND;

      -- Оценка одного типа должна быть только одна, но могут быть наслоения из-за сбоя в базе
      -- поэтому собираем оценки в один проход, затем выдаем - в порядке от самой свежей даты
      V$VAL = '';
      FOR
        SELECT MA.MARKTYPE_ID, V.VAL
        FROM VALM MA
        JOIN LISTVALS LV ON LV.LISTVAL_ID = MA.YEAR_ID
        LEFT JOIN LISTVAL_TEXT(MA.MARKVAL_ID) V ON 1 = 1
        WHERE MA.IS_DEL = 0 AND MA.PUPIL_ID = :I$OBJ_ID AND MA.YEAR_ID = :V$DOC_ID AND MA.SUBJECT_ID = :V$ID AND (MA.IS_NATIVE IS NULL OR MA.IS_NATIVE = 1)
          AND (LV.COST < 300 OR LV.COST > 400) -- не считаем тут модули
          AND ((MA.STAGE_ID IS NULL AND :V$STAGE_ID IS NULL) OR MA.STAGE_ID = :V$STAGE_ID)
        ORDER BY MA.DATE_MODIFY DESC
        INTO :V$TYPE_ID, :VAL
      DO
      BEGIN
        -- Храним в формате: V3002=5|...
        -- более старые оценки того же типа пропускаем
        V$S = 'V' || V$TYPE_ID || '=';
        IF(POSITION(V$S IN V$VAL) <= 0) THEN V$VAL = V$VAL || V$S || VAL || '|';
      END

      TAG_NAME = 'marks_final:M:marks:item:Q1';
      N = POSITION('V3002=' IN V$VAL);
      IF(N > 0) THEN VAL = SUBSTRING(V$VAL FROM N + 6 FOR POSITION('|', V$VAL, N) - N - 6); ELSE VAL = NULL;
      SUSPEND;
      TAG_NAME = 'marks_final:M:marks:item:Q2';
      N = POSITION('V3003=' IN V$VAL);
      IF(N > 0) THEN VAL = SUBSTRING(V$VAL FROM N + 6 FOR POSITION('|', V$VAL, N) - N - 6); ELSE VAL = NULL;
      SUSPEND;
      TAG_NAME = 'marks_final:M:marks:item:Q3';
      N = POSITION('V3004=' IN V$VAL);
      IF(N > 0) THEN VAL = SUBSTRING(V$VAL FROM N + 6 FOR POSITION('|', V$VAL, N) - N - 6); ELSE VAL = NULL;
      SUSPEND;
      TAG_NAME = 'marks_final:M:marks:item:Q4';
      N = POSITION('V3005=' IN V$VAL);
      IF(N > 0) THEN VAL = SUBSTRING(V$VAL FROM N + 6 FOR POSITION('|', V$VAL, N) - N - 6); ELSE VAL = NULL;
      SUSPEND;
      TAG_NAME = 'marks_final:M:marks:item:T1';
      N = POSITION('V3006=' IN V$VAL);
      IF(N > 0) THEN VAL = SUBSTRING(V$VAL FROM N + 6 FOR POSITION('|', V$VAL, N) - N - 6); ELSE VAL = NULL;
      SUSPEND;
      TAG_NAME = 'marks_final:M:marks:item:T2';
      N = POSITION('V3007=' IN V$VAL);
      IF(N > 0) THEN VAL = SUBSTRING(V$VAL FROM N + 6 FOR POSITION('|', V$VAL, N) - N - 6); ELSE VAL = NULL;
      SUSPEND;
      TAG_NAME = 'marks_final:M:marks:item:T3';
      N = POSITION('V3008=' IN V$VAL);
      IF(N > 0) THEN VAL = SUBSTRING(V$VAL FROM N + 6 FOR POSITION('|', V$VAL, N) - N - 6); ELSE VAL = NULL;
      SUSPEND;
      TAG_NAME = 'marks_final:M:marks:item:H1';
      N = POSITION('V3009=' IN V$VAL);
      IF(N > 0) THEN VAL = SUBSTRING(V$VAL FROM N + 6 FOR POSITION('|', V$VAL, N) - N - 6); ELSE VAL = NULL;
      SUSPEND;
      TAG_NAME = 'marks_final:M:marks:item:H2';
      N = POSITION('V3010=' IN V$VAL);
      IF(N > 0) THEN VAL = SUBSTRING(V$VAL FROM N + 6 FOR POSITION('|', V$VAL, N) - N - 6); ELSE VAL = NULL;
      SUSPEND;
      TAG_NAME = 'marks_final:M:marks:item:S1';
      N = POSITION('V12973=' IN V$VAL);
      IF(N > 0) THEN VAL = SUBSTRING(V$VAL FROM N + 7 FOR POSITION('|', V$VAL, N) - N - 7); ELSE VAL = NULL;
      SUSPEND;
      TAG_NAME = 'marks_final:M:marks:item:S2';
      N = POSITION('V12974=' IN V$VAL);
      IF(N > 0) THEN VAL = SUBSTRING(V$VAL FROM N + 7 FOR POSITION('|', V$VAL, N) - N - 7); ELSE VAL = NULL;
      SUSPEND;
      TAG_NAME = 'marks_final:M:marks:item:Y';
      N = POSITION('V3011=' IN V$VAL);
      IF(N > 0) THEN VAL = SUBSTRING(V$VAL FROM N + 6 FOR POSITION('|', V$VAL, N) - N - 6); ELSE VAL = NULL;
      SUSPEND;
      TAG_NAME = 'marks_final:M:marks:item:Exam';
      N = POSITION('V3012=' IN V$VAL);
      IF(N > 0) THEN VAL = SUBSTRING(V$VAL FROM N + 6 FOR POSITION('|', V$VAL, N) - N - 6); ELSE VAL = NULL;
      SUSPEND;
      TAG_NAME = 'marks_final:M:marks:item:QExam';
      N = POSITION('V5544=' IN V$VAL);
      IF(N > 0) THEN VAL = SUBSTRING(V$VAL FROM N + 6 FOR POSITION('|', V$VAL, N) - N - 6); ELSE VAL = NULL;
      SUSPEND;
      TAG_NAME = 'marks_final:M:marks:item:Final';
      N = POSITION('V3013=' IN V$VAL);
      IF(N > 0) THEN VAL = SUBSTRING(V$VAL FROM N + 6 FOR POSITION('|', V$VAL, N) - N - 6); ELSE VAL = NULL;
      SUSPEND;

      -- Флаги наличия или отсутствия оценок по группам
      TAG_NAME = 'marks_final:M:marks:item:HAS_Q';
      IF(POSITION('V3002=' IN V$VAL) > 0 OR POSITION('V3003=' IN V$VAL) > 0 OR POSITION('V3004=' IN V$VAL) > 0 OR POSITION('V3005=' IN V$VAL) > 0) THEN VAL = '1'; ELSE VAL = '0';
      SUSPEND;
      TAG_NAME = 'marks_final:M:marks:item:HAS_T';
      IF(POSITION('V3006=' IN V$VAL) > 0 OR POSITION('V3007=' IN V$VAL) > 0 OR POSITION('V3008=' IN V$VAL) > 0) THEN VAL = '1'; ELSE VAL = '0';
      SUSPEND;
      TAG_NAME = 'marks_final:M:marks:item:HAS_H';
      IF(POSITION('V3009=' IN V$VAL) > 0 OR POSITION('V3010=' IN V$VAL) > 0) THEN VAL = '1'; ELSE VAL = '0';
      SUSPEND;
      TAG_NAME = 'marks_final:M:marks:item:HAS_S';
      IF(POSITION('V12973=' IN V$VAL) > 0 OR POSITION('V12974=' IN V$VAL) > 0) THEN VAL = '1'; ELSE VAL = '0';
      SUSPEND;
    END
  END

  -- Найдем текущий учебный год и дату его начала. Дату начала движения делаем с запасом в 10 дней для первоклашек
  -- если ученик пришел в середине года или уходил-приходил, смотрим последний интервал
  SELECT FIRST 1 V1236.LISTVAL_ID, CAST(LV.TAG AS DATE)
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE L2.OBJ_TYPE_ID = 2 AND L2.PARENT_TYPE_ID IS NULL AND L2.DATE_DEL IS NULL
  INTO :V$YEAR, :V$YEAR_DT;

  V$YEAR_DT = DATEADD(-10 DAY TO V$YEAR_DT);
  V$DT = MAXVALUE(V$YEAR_DT, CAST(V$LD_OPEN_DT AS DATE));

  -- Текущие оценки - выдаем только строки по предметам, по которым не была выставлена годовая оценка за текущий период обучения
  -- там где годовая оценка есть - будет только строка в таблице итоговых
  -- Имитируем выдачу строк по каждому периоду, иначе возникает куча логических проблем
  TAG_NAME = 'marks_current::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT DISTINCT J.SUBJECT_ID, CAP.SCAPTION
    FROM PERSON_MOVEMENTS M
    JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.JOURNAL_TYPE = 0 AND J.GRADE_ID = M.GROUP_ID AND J.YEAR_ID = :V$YEAR
    LEFT JOIN OBJECT_CAPTION_GET(J.SUBJECT_ID) CAP ON 1 = 1
    WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :I$OBJ_ID AND M.DATE_IN >= :V$DT AND NOT EXISTS(
      SELECT FIRST 1 1
      FROM VALM V
      WHERE V.IS_DEL = 0 AND V.PUPIL_ID = M.PERSON_ID AND V.SUBJECT_ID = J.SUBJECT_ID AND V.YEAR_ID = J.YEAR_ID AND V.MARKTYPE_ID = 3011
        AND (V.IS_NATIVE IS NULL OR V.IS_NATIVE = 1)
    )
    ORDER BY 2
    INTO :V$ID, :V$VAL -- предмет, название предмета по алфавиту
  DO
  BEGIN
    TAG_NAME = 'marks_current:item';
    VAL = NULL;
    SUSPEND;
    VAL = NULL;
    TAG_NAME = 'marks_current:item:Предмет';
    VAL = V$VAL;
    SUSPEND;

    -- найдем кол-во из нагрузки согласно УП (из журнала), и тут же последнюю сетку периодов
    V$PARAM_ID = NULL;
    V$PERIOD_ID = NULL;
    SELECT FIRST 1 J.HOURS, J.PERIOD_ID
    FROM PERSON_MOVEMENTS PM
    JOIN CJ2_JOURNAL J ON J.GRADE_ID = PM.GROUP_ID AND J.DATE_DEL IS NULL AND J.SUBJECT_ID = :V$ID AND J.YEAR_ID = :V$YEAR AND J.JOURNAL_TYPE = 0
    WHERE PM.DATE_DEL IS NULL AND PM.PERSON_ID = :I$OBJ_ID AND PM.DATE_IN >= :V$DT
    ORDER BY PM.DATE_IN DESC
    INTO :V$PARAM_ID, :V$PERIOD_ID; -- кол-во часов по УП
    TAG_NAME = 'marks_current:item:Часов_по_плану';
    VAL = V$PARAM_ID;
    SUSPEND;

    -- Проведено занятий (час.)
    -- суммируем по интервалам, где ученик присутствовал в конкретной группе
    V$HOURS = 0;
    FOR
      SELECT DISTINCT PM.OBJ_ID, PM.DATE_IN, PM.DATE_OUT
      FROM PERSON_MOVEMENTS PM
      JOIN CJ2_JOURNAL J ON J.GRADE_ID = PM.GROUP_ID AND J.DATE_DEL IS NULL AND J.SUBJECT_ID = :V$ID AND J.YEAR_ID = :V$YEAR AND J.JOURNAL_TYPE = 0
      WHERE PM.DATE_DEL IS NULL AND PM.PERSON_ID = :I$OBJ_ID AND PM.DATE_IN >= :V$YEAR_DT
      INTO :V$CJ_ID, :V$D1, :V$D2
    DO
    BEGIN
      SELECT COALESCE(SUM(L.LESSON_HOURS), 0)
      FROM CJ2_JOURNAL_LESSONS L
      WHERE L.DATE_DEL IS NULL AND L.IS_COMPLETED = 1 AND L.CJ_ID = :V$CJ_ID AND L.LESSON_DATE >= :V$D1 AND (:V$D2 IS NULL OR L.LESSON_DATE < :V$D2)
      INTO :V$F;
      V$HOURS = V$HOURS + V$F;
    END
    TAG_NAME = 'marks_current:item:Часов_проведено';
    VAL = CAST(V$HOURS AS NUMERIC(15, 0));
    SUSPEND;

    -- найдем число пропусков, предполагается что пропуски не должны стоять на дату, когда ученика не было
    V$F = NULL;
    SELECT COALESCE(SUM(COALESCE(L.LESSON_HOURS, 1)), 0)
    FROM CJ2_MARK MA
    JOIN CJ2_MARK_TYPE MT ON MT.MARK_TYPE_ID = MA.MARK_TYPE_ID
    JOIN CJ2_CONTROL C ON C.CONTROL_ID = MA.CONTROL_ID AND C.DATE_DEL IS NULL
    JOIN CJ2_JOURNAL_LESSONS L ON C.LESSON_ID = L.OBJ_ID AND L.DATE_DEL IS NULL AND L.IS_COMPLETED = 1 AND L.LESSON_DATE >= :V$YEAR_DT
    JOIN CJ2_JOURNAL J ON J.OBJ_ID = L.CJ_ID AND J.SUBJECT_ID = :V$ID AND J.YEAR_ID = :V$YEAR AND J.JOURNAL_TYPE = 0
    WHERE MA.STUDENT_ID = :I$OBJ_ID AND MA.DATE_DEL IS NULL AND MA.MARK_TYPE_ID IN (91, 92, 93, 94) -- пропуски
    INTO :V$F;
    TAG_NAME = 'marks_current:item:Пропущено';
    VAL = CAST(V$F AS NUMERIC(18, 0));
    SUSPEND;

    -- Присутствие на занятиях (часов)
    TAG_NAME = 'marks_current:item:Часов_присутствия';
    VAL = CAST(IIF(V$HOURS IS NULL, 0, V$HOURS) - IIF(V$F IS NULL, 0, V$F) AS NUMERIC(15, 0));
    SUSPEND;

    -- Идем последовательно по текущим оценкам, пересекаем их с периодами аттестации
    -- периоды берем обязательно по последнему журналу - если ученик переходил из параллели в параллель, сетку берем именно последнюю
    -- периоды выдаем не массивом, а имитируя выдачу строк основной таблицы (в последующих строках название предмета зачищаем)
    V$PREV_PERIOD = 0;
    V$PREV_MT = NULL;
    V$VAL = '';
    N = 0;
    V$SUM = 0;
    V$HOURS = 0;
    FOR
      SELECT IIF(MT.PARENT_ID IS NULL OR MT.PARENT_ID < 400, MT.MARK_NAME,
        IIF(MT.PARENT_ID = 450, MT.MARK_NAME ||'/12', IIF(MT.PARENT_ID = 499, MT.MARK_NAME ||'/20', IIF(MT.PARENT_ID = 599, MT.MARK_NAME ||'/100', MT.MARK_NAME)))),
        L.LESSON_DATE, MT.MARK_COST, CT.DEFAULT_COST
      FROM CJ2_MARK MA
      JOIN CJ2_MARK_TYPE MT ON MT.MARK_TYPE_ID = MA.MARK_TYPE_ID AND MT.IS_DEL = 0
      JOIN CJ2_CONTROL C ON C.CONTROL_ID = MA.CONTROL_ID AND C.DATE_DEL IS NULL AND C.CONTROL_TYPE_ID <> 0
      JOIN CJ2_CONTROL_TYPE CT ON CT.CONTROL_TYPE_ID = C.CONTROL_TYPE_ID
      JOIN CJ2_JOURNAL_LESSONS L ON L.OBJ_ID = C.LESSON_ID AND L.DATE_DEL IS NULL AND L.IS_COMPLETED = 1 AND L.LESSON_DATE >= :V$DT
      JOIN CJ2_JOURNAL J ON J.OBJ_ID = L.CJ_ID AND J.SUBJECT_ID = :V$ID AND J.YEAR_ID = :V$YEAR AND J.JOURNAL_TYPE = 0
      WHERE MA.STUDENT_ID = :I$OBJ_ID AND MA.DATE_DEL IS NULL
      ORDER BY L.LESSON_DATE, L.LESSON_NUM
      INTO :V$S, :V$D1, :V$F, :V$CTCOST
    DO
    BEGIN
      -- Поиск периода делаем только по начальной дате
      V$VAL_ID = 0;
      V$TYPE_ID = NULL;
      SELECT FIRST 1 V1170.LISTVAL_ID, V1171.LISTVAL_ID
      FROM LINKS L154
      JOIN VALL V1170 ON V1170.OBJ_ID = L154.OBJ_ID AND V1170.PARAM_ID = 1170 AND V1170.IS_DEL = 0
      JOIN VALD V1169 ON V1169.OBJ_ID = L154.OBJ_ID AND V1169.PARAM_ID = 1169 AND V1169.IS_DEL = 0 AND V1169.VAL <= :V$D1
      JOIN VALL V1171 ON V1171.OBJ_ID = L154.OBJ_ID AND V1171.PARAM_ID = 1171 AND V1171.IS_DEL = 0
      WHERE L154.PARENT_ID = :V$PERIOD_ID AND L154.OBJ_TYPE_ID = 154 AND L154.DATE_DEL IS NULL
      ORDER BY V1169.VAL DESC
      INTO :V$VAL_ID, :V$TYPE_ID;

      IF(V$PREV_PERIOD <> V$VAL_ID) THEN
      BEGIN
        IF(V$VAL <> '') THEN
        BEGIN
          -- Для второй и далее строк периодов - формируем новую строку с пустыми первыми столбцами
          IF(N > 0) THEN
          BEGIN
            TAG_NAME = 'marks_current:item';
            VAL = NULL;
            SUSPEND;
            TAG_NAME = 'marks_current:item:Предмет';
            VAL = NULL;
            SUSPEND;
            TAG_NAME = 'marks_current:item:Часов_по_плану';
            VAL = NULL;
            SUSPEND;
            TAG_NAME = 'marks_current:item:Часов_проведено';
            VAL = NULL;
            SUSPEND;
            TAG_NAME = 'marks_current:item:Пропущено';
            VAL = NULL;
            SUSPEND;
            TAG_NAME = 'marks_current:item:Часов_присутствия';
            VAL = NULL;
            SUSPEND;
          END
          TAG_NAME = 'marks_current:item:Период';
          IF(V$PREV_PERIOD = 0) THEN VAL = 'Неизвестный период';
          ELSE VAL = (SELECT VAL FROM LISTVAL_TEXT(:V$PREV_PERIOD));
          SUSPEND;
          TAG_NAME = 'marks_current:item:Оценки';
          VAL = V$VAL;
          SUSPEND;
          TAG_NAME = 'marks_current:item:Средний_балл';
          VAL = NULL;
          IF(V$HOURS >= 2) THEN VAL = CAST((V$SUM / V$HOURS) AS NUMERIC(18, 2));
          SUSPEND;
          TAG_NAME = 'marks_current:item:Итоговая_отметка';
          VAL = NULL;
          SELECT FIRST 1 C.VAL
          FROM VALM M
          LEFT JOIN LISTVAL_TEXT(M.MARKVAL_ID) C ON 1 = 1
          WHERE M.IS_DEL = 0 AND M.PUPIL_ID = :I$OBJ_ID AND M.SUBJECT_ID = :V$ID AND M.YEAR_ID = :V$YEAR AND M.MARKTYPE_ID = :V$PREV_MT
            AND (M.IS_NATIVE IS NULL OR M.IS_NATIVE = 1)
          INTO :VAL;
          SUSPEND;
          N = N + 1;
        END
        V$VAL = '';
        V$PREV_PERIOD = V$VAL_ID;
        V$PREV_MT = V$TYPE_ID;
        V$SUM = 0;
        V$HOURS = 0;
      END
      IF(V$VAL <> '') THEN V$VAL = V$VAL || ', ';
      V$VAL = V$VAL || V$S;
      V$SUM = V$SUM + V$F * V$CTCOST; -- числитель
      V$HOURS = V$HOURS + V$CTCOST; -- знаменатель
    END

    -- Закрываем последний период
    IF(V$VAL <> '') THEN
    BEGIN
      -- Для второй и далее строк периодов - формируем новую строку с пустыми первыми столбцами
      IF(N > 0) THEN
      BEGIN
        TAG_NAME = 'marks_current:item';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'marks_current:item:Предмет';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'marks_current:item:Часов_по_плану';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'marks_current:item:Часов_проведено';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'marks_current:item:Пропущено';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'marks_current:item:Часов_присутствия';
        VAL = NULL;
        SUSPEND;
      END
      TAG_NAME = 'marks_current:item:Период';
      IF(V$PREV_PERIOD = 0) THEN VAL = 'Неизвестный период';
      ELSE VAL = (SELECT VAL FROM LISTVAL_TEXT(:V$PREV_PERIOD));
      SUSPEND;
      TAG_NAME = 'marks_current:item:Оценки';
      VAL = V$VAL;
      SUSPEND;
      TAG_NAME = 'marks_current:item:Средний_балл';
      IF(V$HOURS >= 2) THEN VAL = CAST((V$SUM / V$HOURS) AS NUMERIC(18, 2));
      SUSPEND;
      TAG_NAME = 'marks_current:item:Итоговая_отметка';
      VAL = NULL;
      SELECT FIRST 1 C.VAL
      FROM VALM M
      LEFT JOIN LISTVAL_TEXT(M.MARKVAL_ID) C ON 1 = 1
      WHERE M.IS_DEL = 0 AND M.PUPIL_ID = :I$OBJ_ID AND M.SUBJECT_ID = :V$ID AND M.YEAR_ID = :V$YEAR AND M.MARKTYPE_ID = :V$PREV_MT
        AND (M.IS_NATIVE IS NULL OR M.IS_NATIVE = 1)
      INTO :VAL;
      SUSPEND;
      N = N + 1;
    END
  END

  -- данные по документам об образовании, выданного самой ОО.
  -- По полю 569 (Идентификатор документа в DOC.FDB) определяем, был ли аттестат выдан здесь и просто загружен при предъявлении
  TAG_NAME = 'study_docs::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L11.OBJ_ID
    FROM LINKS L11
    JOIN VALS V569 ON V569.OBJ_ID = L11.OBJ_ID AND V569.PARAM_ID = 569 AND V569.IS_DEL = 0 -- Идентификатор документа в DOC.FDB должен быть, значит выдан в этой школе
    WHERE L11.OBJ_TYPE_ID = 11 AND L11.PARENT_ID = :I$OBJ_ID AND L11.DATE_DEL IS NULL
    INTO :V$ID
  DO
  BEGIN
    TAG_NAME = 'study_docs:item';
    VAL = NULL;
    SUSPEND;
    FOR
      SELECT P.PARAM_ID, R.VAL, IIF(V.IS_EXISTS = 1, V.V, NULL)
      FROM PARAMS P
      JOIN RES R ON R.RES_ID = P.RES_ID AND LANG_CODE = 'RU'
      LEFT JOIN VAL_GET(:V$ID, P.PARAM_ID) V ON 1 = 1
      WHERE P.IS_DEL = 0 AND P.TYPE_ID = 11 -- edu docs
      INTO :V$PARAM_ID, :TAG_NAME, :VAL
    DO
    BEGIN
      TAG_NAME = REPLACE(TAG_NAME, ' ', '_');
      TAG_NAME = REPLACE(TAG_NAME, '-', '_');
      TAG_NAME = REPLACE(TAG_NAME, '/', '_');
      TAG_NAME = REPLACE(TAG_NAME, '\', '_');
      TAG_NAME = REPLACE(TAG_NAME, '.', '_');
      TAG_NAME = REPLACE(TAG_NAME, ',', '_');
      TAG_NAME = REPLACE(TAG_NAME, '"', '_');
      TAG_NAME = REPLACE(TAG_NAME, '(', '_');
      TAG_NAME = REPLACE(TAG_NAME, ')', '_');
      TAG_NAME = REPLACE(TAG_NAME, '__', '_');

      TAG_NAME = 'study_docs:item:' || TAG_NAME;
      IF (VAL IS NULL) THEN VAL = 'нет данных';
      SUSPEND;
    END
  END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LD_STUDENT_UPDATE (
    I$PERSON_ID BIGINT,
    I$RECORD_ID VARCHAR(400),
    I$VAL VARCHAR(1000),
    I$DT TIMESTAMP)
RETURNS (
    OBJ_ID BIGINT,
    MODIFIED SMALLINT)
AS
declare variable P integer;
declare variable S varchar(100);
declare variable V$PARAM_ID bigint;
declare variable V$SUBJECT_ID bigint;
declare variable V$YEAR_ID bigint;
declare variable V$STAGE_ID bigint;
declare variable V$DATE date;
declare variable V$MT bigint;
declare variable V$MV bigint;
declare variable V$OLD_MV bigint;
declare variable V varchar(1000);
begin

  MODIFIED = 0;

  -- Записи самого личного дела идут в формате OBJ_ID:PARAM_ID
  P = POSITION(':' IN I$RECORD_ID);
  S = SUBSTRING(I$RECORD_ID FROM 1 FOR P - 1);

  IF(S = 'mark') THEN
  BEGIN
    -- Итоговые отметки
    -- Формат значения: subject_id,year_id,stage_id,date,mark_type,mark_val

    P = POSITION(',' IN I$VAL);
    IF(P <= 0) THEN EXCEPTION DATA_ERROR 'Неверный формат записи итоговой отметки';
    V$SUBJECT_ID = SUBSTRING(I$VAL FROM 1 FOR P - 1);
    I$VAL = SUBSTRING(I$VAL FROM P + 1);
    P = POSITION(',' IN I$VAL);
    IF(P <= 0) THEN EXCEPTION DATA_ERROR 'Неверный формат записи итоговой отметки';
    V$YEAR_ID = SUBSTRING(I$VAL FROM 1 FOR P - 1);
    I$VAL = SUBSTRING(I$VAL FROM P + 1);
    P = POSITION(',' IN I$VAL);
    IF(P <= 0) THEN EXCEPTION DATA_ERROR 'Неверный формат записи итоговой отметки';
    IF(P > 1) THEN V$STAGE_ID = SUBSTRING(I$VAL FROM 1 FOR P - 1);
    I$VAL = SUBSTRING(I$VAL FROM P + 1);
    P = POSITION(',' IN I$VAL);
    IF(P <= 0) THEN EXCEPTION DATA_ERROR 'Неверный формат записи итоговой отметки';
    V$DATE = SUBSTRING(I$VAL FROM 1 FOR P - 1);
    I$VAL = SUBSTRING(I$VAL FROM P + 1);
    P = POSITION(',' IN I$VAL);
    IF(P <= 0) THEN EXCEPTION DATA_ERROR 'Неверный формат записи итоговой отметки';
    V$MT = SUBSTRING(I$VAL FROM 1 FOR P - 1);
    V$MV = SUBSTRING(I$VAL FROM P + 1);

    -- Если предмет из чужой сетки предметов - не вносим
    IF(EXISTS(
      SELECT FIRST 1 1
      FROM LINKS L51
      WHERE L51.OBJ_ID = :V$SUBJECT_ID AND L51.PARENT_TYPE_ID = 301 AND L51.DATE_DEL IS NULL
    )) THEN
    BEGIN
      SELECT FIRST 1 M.MARK_ID, M.MARKVAL_ID
      FROM VALM M
      WHERE M.IS_DEL = 0 AND M.IS_NATIVE = 0 AND M.PUPIL_ID = :I$PERSON_ID AND M.SUBJECT_ID = :V$SUBJECT_ID AND M.YEAR_ID = :V$YEAR_ID AND
        ((M.STAGE_ID IS NULL AND :V$STAGE_ID IS NULL) OR M.STAGE_ID = :V$STAGE_ID) AND M.MARKTYPE_ID = :V$MT
      INTO :OBJ_ID, :V$OLD_MV;

      IF(OBJ_ID IS NULL) THEN
      BEGIN
        INSERT INTO VALM
        (PUPIL_ID, IS_NATIVE, SUBJECT_ID, YEAR_ID, STAGE_ID, MARK_DATE, MARKTYPE_ID, MARKVAL_ID)
        VALUES (:I$PERSON_ID, 0, :V$SUBJECT_ID, :V$YEAR_ID, :V$STAGE_ID, :V$DATE, :V$MT, :V$MV)
        RETURNING MARK_ID INTO :OBJ_ID;

        MODIFIED = 1;
      END
      ELSE IF(V$MV <> V$OLD_MV) THEN
      BEGIN
        UPDATE VALM
        SET MARKVAL_ID = :V$MV, MARK_DATE = :V$DATE
        WHERE MARK_ID = :OBJ_ID;

        MODIFIED = 1;
      END
    END
  END
  ELSE
  BEGIN
    -- Обычные параметры - просто вносим значение
    V$PARAM_ID = SUBSTRING(I$RECORD_ID FROM P + 1);

    SELECT FIRST 1 SUBSTRING(V.VAL FROM 1 FOR 1000)
    FROM VALS V
    WHERE V.OBJ_ID = :I$PERSON_ID AND V.PARAM_ID = :V$PARAM_ID AND V.IS_DEL = 0
    UNION
    SELECT FIRST 1 V.LISTVAL_ID
    FROM VALL V
    WHERE V.OBJ_ID = :I$PERSON_ID AND V.PARAM_ID = :V$PARAM_ID AND V.IS_DEL = 0
    INTO :V;

    OBJ_ID = V$PARAM_ID;

    IF(COALESCE(V, '') <> :I$VAL) THEN
    BEGIN
      SELECT 1 FROM VAL_ADD(:V$PARAM_ID, :I$PERSON_ID, :I$VAL) INTO :P;
      MODIFIED = 1;
    END
  END

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LD_STUFF_UPDATE (
    I$PERSON_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$OBJ_TYPE BIGINT,
    I$STATE_ID SMALLINT,
    I$TYPE_ID BIGINT,
    I$SERIE VARCHAR(40),
    I$NUMBER VARCHAR(40),
    I$DATE DATE,
    I$STAGE_ID BIGINT,
    I$ISSUED_BY VARCHAR(1000),
    I$SPEC VARCHAR(1000),
    I$QUAL VARCHAR(1000),
    I$PROFILE_ID BIGINT,
    I$ISSUED_SHORT VARCHAR(1000),
    I$REG_NUM VARCHAR(1000))
RETURNS (
    OBJ_ID BIGINT,
    MODIFIED SMALLINT)
AS
declare variable T integer;
begin

  MODIFIED = 0;

  IF(I$OBJ_TYPE IN (34, 156)) THEN
  BEGIN
    -- Аттестацию вообще не добавляем - она делается в конкретной ОУ
  END
  ELSE
  BEGIN
    -- Сверяем по номеру и дате документа
    SELECT FIRST 1 L.OBJ_ID
    FROM LINKS L
    JOIN VALD VD ON VD.OBJ_ID = L.OBJ_ID AND VD.PARAM_ID IN (290, 300, 310) AND VD.IS_DEL = 0 AND VD.VAL = :I$DATE
    JOIN VALS VS ON VS.OBJ_ID = L.OBJ_ID AND VS.PARAM_ID IN (288, 299, 309) AND VD.IS_DEL = 0 AND VS.SVAL = :I$NUMBER
    WHERE L.PARENT_ID = :I$PERSON_ID AND L.OBJ_TYPE_ID = :I$OBJ_TYPE AND L.DATE_DEL IS NULL
    INTO :OBJ_ID;

    -- Только на добавление
    IF(OBJ_ID IS NULL) THEN
    BEGIN
      MODIFIED = 1;
      SELECT OBJ_ID FROM OBJECT_ADD(:I$PERSON_ID, :I$OBJ_TYPE) INTO :OBJ_ID;

      IF(I$OBJ_TYPE = 33) THEN
      BEGIN
        -- Образование
        SELECT 1 FROM VAL_ADD(286, :OBJ_ID, :I$TYPE_ID) INTO :T;
        SELECT 1 FROM VAL_ADD(284, :OBJ_ID, :I$STAGE_ID) INTO :T;
        SELECT 1 FROM VAL_ADD(287, :OBJ_ID, :I$SERIE) INTO :T;
        SELECT 1 FROM VAL_ADD(288, :OBJ_ID, :I$NUMBER) INTO :T;
        SELECT 1 FROM VAL_ADD(290, :OBJ_ID, :I$DATE) INTO :T;
        SELECT 1 FROM VAL_ADD(285, :OBJ_ID, :I$ISSUED_BY) INTO :T;
        SELECT 1 FROM VAL_ADD(291, :OBJ_ID, :I$SPEC) INTO :T;
        SELECT 1 FROM VAL_ADD(292, :OBJ_ID, :I$QUAL) INTO :T;
        SELECT 1 FROM VAL_ADD(293, :OBJ_ID, :I$PROFILE_ID) INTO :T;
      END
      ELSE IF(I$OBJ_TYPE = 35) THEN
      BEGIN
        -- Переподготовка
        SELECT 1 FROM VAL_ADD(297, :OBJ_ID, :I$TYPE_ID) INTO :T;
        SELECT 1 FROM VAL_ADD(298, :OBJ_ID, :I$SERIE) INTO :T;
        SELECT 1 FROM VAL_ADD(299, :OBJ_ID, :I$NUMBER) INTO :T;
        SELECT 1 FROM VAL_ADD(300, :OBJ_ID, :I$DATE) INTO :T;
        SELECT 1 FROM VAL_ADD(296, :OBJ_ID, :I$ISSUED_BY) INTO :T;
        SELECT 1 FROM VAL_ADD(301, :OBJ_ID, :I$SPEC) INTO :T;
        SELECT 1 FROM VAL_ADD(302, :OBJ_ID, :I$QUAL) INTO :T;
      END
      ELSE IF(I$OBJ_TYPE = 36) THEN
      BEGIN
        -- Повышение квалификации
        SELECT 1 FROM VAL_ADD(307, :OBJ_ID, :I$TYPE_ID) INTO :T;
        SELECT 1 FROM VAL_ADD(303, :OBJ_ID, :I$STAGE_ID) INTO :T;
        SELECT 1 FROM VAL_ADD(308, :OBJ_ID, :I$SERIE) INTO :T;
        SELECT 1 FROM VAL_ADD(309, :OBJ_ID, :I$NUMBER) INTO :T;
        SELECT 1 FROM VAL_ADD(310, :OBJ_ID, :I$DATE) INTO :T;
        SELECT 1 FROM VAL_ADD(304, :OBJ_ID, :I$ISSUED_BY) INTO :T;
        SELECT 1 FROM VAL_ADD(305, :OBJ_ID, :I$QUAL) INTO :T;
        SELECT 1 FROM VAL_ADD(306, :OBJ_ID, :I$SPEC) INTO :T; -- тут число в виде строки
        SELECT 1 FROM VAL_ADD(1024, :OBJ_ID, :I$PROFILE_ID) INTO :T;
      END
      ELSE
        EXCEPTION DATA_ERROR 'Недопустимый тип записи в личном деле';
    END
  END

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LEAVED_PUPIL_W_ATT_LIST (
    I$LAST_NAME VARCHAR(255),
    I$FIRST_NAME VARCHAR(255))
RETURNS (
    PUPIL_ID BIGINT,
    LAST_NAME VARCHAR(255),
    FIRST_NAME VARCHAR(255),
    MIDDLE_NAME VARCHAR(255),
    DOB DATE,
    CONTAINER_NAME VARCHAR(255))
AS
declare variable V$PARALLEL integer;
declare variable V$OBJ_ID bigint;
BEGIN
    FOR
        SELECT L10.OBJ_ID,
            (
                SELECT FIRST 1 M.STAGE_ID
                FROM PERSON_MOVEMENTS M
                JOIN OBJECTS O ON O.OBJ_ID = M.GROUP_ID AND O.TYPE_ID = 9
                WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = L10.OBJ_ID
                ORDER BY M.DATE_IN DESC
            ),
            V55.VAL,
            V56.VAL,
            V57.VAL,
            V89.VAL,
            L82_83.OBJ_ID
        FROM LINKS L2
        JOIN LINKS L78 ON L78.PARENT_ID = L2.OBJ_ID AND L78.OBJ_TYPE_ID = 78 AND L78.DATE_DEL IS NULL
        JOIN LINKS L82_83 ON L82_83.PARENT_ID = L78.OBJ_ID AND L82_83.OBJ_TYPE_ID IN (82, 83) AND L82_83.DATE_DEL IS NULL
        JOIN LINKS L10 ON L10.PARENT_ID = L82_83.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        LEFT JOIN VALS V55 ON V55.OBJ_ID = L10.OBJ_ID AND V55.PARAM_ID = 55 AND V55.IS_DEL = 0
        LEFT JOIN VALS V56 ON V56.OBJ_ID = L10.OBJ_ID AND V56.PARAM_ID = 56 AND V56.IS_DEL = 0
        LEFT JOIN VALS V57 ON V57.OBJ_ID = L10.OBJ_ID AND V57.PARAM_ID = 57 AND V57.IS_DEL = 0
        LEFT JOIN VALD V89 ON V89.OBJ_ID = L10.OBJ_ID AND V89.PARAM_ID = 89 AND V89.IS_DEL = 0
        WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
          AND ((:I$LAST_NAME IS NULL) OR (V55.VAL LIKE :I$LAST_NAME))
          AND ((:I$FIRST_NAME IS NULL) OR (V56.VAL LIKE :I$FIRST_NAME))

        INTO :PUPIL_ID,
             :V$PARALLEL,
             :LAST_NAME,
             :FIRST_NAME,
             :MIDDLE_NAME,
             :DOB, 
             :V$OBJ_ID
    DO
    BEGIN
        IF (((V$PARALLEL = 45) AND NOT EXISTS(
                SELECT FIRST 1 1
                FROM LINKS L11

                JOIN VALL V50
                ON V50.OBJ_ID = L11.OBJ_ID
                AND V50.PARAM_ID = 50
                AND V50.IS_DEL = 0
                AND V50.LISTVAL_ID IN (1375,3241)

                WHERE L11.PARENT_ID = :PUPIL_ID
                AND L11.OBJ_TYPE_ID = 11
                AND L11.DATE_DEL IS NULL
             )) OR
            ((V$PARALLEL IN (45,47,48)) AND NOT EXISTS(
                SELECT FIRST 1 1
                FROM LINKS L11

                JOIN VALL V50
                ON V50.OBJ_ID = L11.OBJ_ID
                AND V50.PARAM_ID = 50
                AND V50.IS_DEL = 0
                AND V50.LISTVAL_ID IN (1376,3240)

                WHERE L11.PARENT_ID = :PUPIL_ID
                AND L11.OBJ_TYPE_ID = 11
                AND L11.DATE_DEL IS NULL
             ))) THEN
        BEGIN
            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:V$OBJ_ID)
            INTO :CONTAINER_NAME;
            SUSPEND;
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LEAVE_TO_LIST (
    I$OBJ_ID BIGINT)
RETURNS (
    PARENT_ID BIGINT,
    LISTVAL_ID BIGINT,
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$STATUS VARCHAR(1);
DECLARE VARIABLE V$LEVEL_ID BIGINT;
DECLARE VARIABLE F VARCHAR(100);
begin

  V$STATUS = (SELECT STATUS FROM OU_LICENCE_TYPE);

  IF(V$STATUS = 'O') THEN F = '%GOU%';
  ELSE IF(V$STATUS = 'C') THEN F = '%COLLEGE%';
  ELSE IF(V$STATUS = 'D') THEN F = '%DOU%';
  ELSE IF(V$STATUS = 'U') THEN F = '%UDOD%';
  ELSE IF(V$STATUS = 'S') THEN
  BEGIN
    -- Смотрим данные по последней записи движения
    SELECT FIRST 1 M.LEVEL_ID
    FROM PERSON_MOVEMENTS M
    WHERE M.PERSON_ID = :I$OBJ_ID AND M.DATE_DEL IS NULL AND M.GROUP_TYPE_ID IN (9, 125, 187)
    ORDER BY M.DATE_IN DESC
    INTO :V$LEVEL_ID;

    IF(V$LEVEL_ID IN (21, 3263, 3264)) THEN F = '%DOU%';
    ELSE IF(V$LEVEL_ID IN (22, 26, 27)) THEN F = '%GOU%';
    ELSE IF(V$LEVEL_ID IN (28, 29, 13129, 13131)) THEN F = '%COLLEGE%';
    ELSE IF(V$LEVEL_ID IN (13128)) THEN F = '%UDOD%';
  END

  FOR
    SELECT PARENT_ID, LISTVAL_ID, VAL
    FROM LISTVALS_LIST(127)
    WHERE IS_DEL = 0 AND (:F IS NULL OR "FILTER" LIKE :F)
    INTO :PARENT_ID, :LISTVAL_ID, :VAL
  DO
  BEGIN
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LEVELS_LIST (
    I$TASK_ID BIGINT,
    I$LANG_CODE VARCHAR(2) = 'RU')
RETURNS (
    LEVEL_ID BIGINT,
    RES_ID BIGINT,
    TASK_ID BIGINT,
    IS_DEL SMALLINT,
    ROOT_TYPE_ID BIGINT,
    PARENT_TYPE_ID BIGINT,
    LEVEL_CAPTION VARCHAR(4000),
    ICON_ID BIGINT)
AS
BEGIN
    FOR
        SELECT LEVEL_ID,
               RES_ID,
               TASK_ID,
               IS_DEL,
               ROOT_TYPE_ID,
               PARENT_TYPE_ID,
               ICON_ID
        FROM LEVELS
        WHERE TASK_ID = :I$TASK_ID
        ORDER BY SORT_ORDER,
                 LEVEL_ID
        INTO   :LEVEL_ID,
               :RES_ID,
               :TASK_ID,
               :IS_DEL,
               :ROOT_TYPE_ID,
               :PARENT_TYPE_ID,
               :ICON_ID
    DO
    BEGIN
        SELECT VAL
        FROM RES_GET(:RES_ID, :I$LANG_CODE)
        INTO   :LEVEL_CAPTION;
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LEVEL_ADD (
    I$LEVEL_ID BIGINT,
    I$RES_ID BIGINT,
    I$TASK_ID BIGINT,
    I$LANG_CODE CHAR(2),
    I$LEVEL_CAPTION VARCHAR(4000),
    I$IS_DEL SMALLINT = 0,
    I$ROOT_TYPE_ID BIGINT = NULL,
    I$PARENT_TYPE_ID BIGINT = NULL,
    I$ICON_ID BIGINT = NULL)
RETURNS (
    LEVEL_ID BIGINT,
    RES_ID BIGINT)
AS
DECLARE VARIABLE SORT_ORDER SMALLINT;
BEGIN
    LEVEL_ID = I$LEVEL_ID;
    RES_ID = I$RES_ID;
    IF (I$LEVEL_ID IS NULL) THEN
    BEGIN
        SELECT MAX(SORT_ORDER) + 1 FROM LEVELS WHERE TASK_ID = :I$TASK_ID
        INTO :SORT_ORDER;
        IF (SORT_ORDER IS NULL) THEN SORT_ORDER = 1;

        INSERT INTO LEVELS (TASK_ID, SORT_ORDER, ROOT_TYPE_ID, PARENT_TYPE_ID, ICON_ID)
        VALUES (:I$TASK_ID, :SORT_ORDER, :I$ROOT_TYPE_ID, :I$PARENT_TYPE_ID, :I$ICON_ID)
        RETURNING LEVEL_ID, RES_ID INTO :LEVEL_ID, :RES_ID;
    END
    ELSE
    BEGIN
        UPDATE LEVELS SET
            IS_DEL = :I$IS_DEL,
            ROOT_TYPE_ID = :I$ROOT_TYPE_ID,
            PARENT_TYPE_ID = :I$PARENT_TYPE_ID,
            ICON_ID = :I$ICON_ID
        WHERE LEVEL_ID = :I$LEVEL_ID;
    END

    IF (RES_ID IS NOT NULL) THEN
        EXECUTE PROCEDURE RES_ADD (:RES_ID,:I$LANG_CODE,:I$LEVEL_CAPTION);

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LEVEL_BARS_LIST (
    I$LEVEL_ID BIGINT,
    I$LANG_CODE CHAR(2) = 'RU',
    I$USER_ID BIGINT = 1)
RETURNS (
    BAR_ID BIGINT,
    SORT_ORDER SMALLINT,
    BUTTON_CAPTION VARCHAR(4000),
    DO_FUNC VARCHAR(100),
    TAG VARCHAR(20),
    ICON_ID BIGINT)
AS
declare variable RES_ID bigint;
declare variable READ_ONLY bigint;
declare variable V$GEN bigint;
declare variable V$BUTTON bigint;
BEGIN
    READ_ONLY = 0;

    SELECT FIRST 1 L.READ_ONLY
    FROM LUSERS L
    WHERE L.LEVEL_ID = :I$LEVEL_ID AND L.USER_ID = :I$USER_ID
    INTO :READ_ONLY;

    -- Номер лицензии Параграф
    SELECT GEN
    FROM GEN
    INTO :V$GEN;

    --IF (READ_ONLY = 1) THEN EXIT;

    FOR
      SELECT DISTINCT B.BAR_ID
      FROM BARS B
      JOIN LTYPES L ON L.BAR_ID = B.BAR_ID
      WHERE L.LEVEL_ID = :I$LEVEL_ID AND L.IS_DEL = 0 AND B.IS_DEL = 0
      ORDER BY B.BAR_ID
      INTO :BAR_ID
    DO
    BEGIN
      FOR
        SELECT SORT_ORDER, RES_ID, DO_FUNC, ICON_ID, TAG, BUTTON_ID
        FROM BARBUTTONS
        WHERE BAR_ID = :BAR_ID AND IS_DEL = 0
        ORDER BY SORT_ORDER
        INTO :SORT_ORDER, :RES_ID, :DO_FUNC, :ICON_ID, :TAG, :V$BUTTON
      DO
      BEGIN
        SELECT VAL
        FROM RES_GET(:RES_ID, :I$LANG_CODE)
        INTO :BUTTON_CAPTION;
        -- Кнопку сброса пароля родителя показываем только в 369
        IF(V$GEN = 903 OR V$BUTTON <> 204) THEN SUSPEND;
      END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LEVEL_MOVE (
    I$LEVEL_ID BIGINT,
    I$MOVE SMALLINT)
RETURNS (
    SORT_ORDER SMALLINT)
AS
DECLARE VARIABLE TASK_ID BIGINT = NULL;
DECLARE VARIABLE LEVEL_ID BIGINT = NULL;
BEGIN
   SELECT TASK_ID, SORT_ORDER FROM LEVELS
   WHERE LEVEL_ID = :I$LEVEL_ID
   INTO :TASK_ID, :SORT_ORDER;

   SELECT LEVEL_ID FROM LEVELS
   WHERE TASK_ID = :TASK_ID AND SORT_ORDER = (:SORT_ORDER + :I$MOVE)
   INTO :LEVEL_ID;

   IF (LEVEL_ID IS NOT NULL) THEN
   BEGIN
      UPDATE LEVELS SET SORT_ORDER = :SORT_ORDER WHERE LEVEL_ID = :LEVEL_ID;
      UPDATE LEVELS SET SORT_ORDER = (:SORT_ORDER + :I$MOVE) WHERE LEVEL_ID = :I$LEVEL_ID;
   END
   SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LEVEL_TYPES_LIST (
    I$LEVEL_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    PARENT_TYPE_ID BIGINT,
    TYPE_ID BIGINT,
    TYPE_CAPTION VARCHAR(4000),
    EDIT_TYPE SMALLINT,
    IS_ADD SMALLINT,
    IS_INTERNAL_ADD SMALLINT,
    IS_COPY SMALLINT,
    IS_CUT SMALLINT,
    IS_LINK SMALLINT,
    IS_SELECT SMALLINT,
    IS_HIDDEN SMALLINT,
    DO_FUNC SMALLINT,
    IS_FROM_LIST SMALLINT,
    RUN_SQL VARCHAR(1000),
    IS_AUTO_CREATE SMALLINT,
    TAB_ID BIGINT,
    BAR_ID BIGINT,
    TAG VARCHAR(100),
    COLOR INTEGER)
AS
declare variable RES_ID bigint;
declare variable LANG_CODE varchar(2);
declare variable READ_ONLY smallint;
BEGIN
    SELECT LANG_CODE FROM USERS WHERE USER_ID = :I$USER_ID INTO :LANG_CODE;

    /* ROOT TYPE */
    PARENT_TYPE_ID = NULL;
    TYPE_ID = NULL;
    READ_ONLY = 0;

    SELECT FIRST 1 L.ROOT_TYPE_ID, T.RES_ID, LT.EDIT_TYPE, T.TAG, LT.BAR_ID, T.COLOR, LU.READ_ONLY
    FROM LEVELS L
    JOIN TYPES T ON T.TYPE_ID = L.ROOT_TYPE_ID
    JOIN LUSERS LU ON LU.LEVEL_ID = L.LEVEL_ID
    LEFT JOIN LTYPES LT ON LT.LEVEL_ID = L.LEVEL_ID AND LT.TYPE_ID = T.TYPE_ID
    WHERE L.LEVEL_ID = :I$LEVEL_ID AND L.IS_DEL = 0 AND LT.IS_DEL = 0 AND T.IS_DEL = 0 AND LU.USER_ID = :I$USER_ID AND T.IS_DEL = 0
    INTO :TYPE_ID, :RES_ID, :EDIT_TYPE, :TAG, :BAR_ID, :COLOR, :READ_ONLY;

    IF (TYPE_ID IS NOT NULL) THEN
    BEGIN

        SELECT IIF(CHAR_LENGTH(VAL) > 50 AND CHAR_LENGTH(VAL_LONG) BETWEEN 2 AND 49, VAL_LONG, VAL)
        FROM RES_GET(:RES_ID, :LANG_CODE)
        INTO :TYPE_CAPTION;

        IS_ADD = 1;
        IS_COPY = 0;
        IS_CUT = 0;
        IS_LINK = 0;
        DO_FUNC = 0;
        IS_FROM_LIST = 0;
        RUN_SQL = NULL;
        IS_AUTO_CREATE = 0;
        TAB_ID = NULL;

        IF (READ_ONLY = 1) THEN IS_ADD = 0;

        SUSPEND;

    END

    FOR
        SELECT P.TYPE_ID, P.CHILD_ID, P.IS_ADD, P.IS_INTERNAL_ADD, P.IS_COPY, P.IS_CUT, P.IS_LINK, P.IS_SELECT,
               P.DO_FUNC, P.IS_FROM_LIST, P.RUN_SQL, P.IS_AUTO_CREATE, P.TAB_ID, T.RES_ID, L.EDIT_TYPE, L.BAR_ID, T.TAG,
               T.IS_HIDDEN, T.COLOR
        FROM PARENTS P
        JOIN TYPES T ON T.TYPE_ID = P.CHILD_ID AND T.IS_DEL = 0
        JOIN LTYPES L ON L.TYPE_ID = P.CHILD_ID AND L.LEVEL_ID = :I$LEVEL_ID AND L.IS_DEL = 0
        JOIN LTYPES L2 ON L2.TYPE_ID = P.TYPE_ID AND L2.LEVEL_ID = :I$LEVEL_ID AND L2.IS_DEL = 0
        WHERE P.IS_DEL = 0 AND ((P.IS_ADD > 0) OR (P.IS_INTERNAL_ADD > 0) OR (P.IS_COPY > 0) OR (P.IS_CUT > 0) OR (P.IS_LINK > 0) OR (P.IS_SELECT > 0) OR (P.IS_FROM_LIST > 0))
        ORDER BY T.SORT_ORDER
        INTO :PARENT_TYPE_ID, :TYPE_ID, :IS_ADD, :IS_INTERNAL_ADD, :IS_COPY, :IS_CUT, :IS_LINK, :IS_SELECT, :DO_FUNC,
             :IS_FROM_LIST, :RUN_SQL, :IS_AUTO_CREATE, :TAB_ID, :RES_ID, :EDIT_TYPE, :BAR_ID, :TAG, :IS_HIDDEN, :COLOR
    DO
    BEGIN
        SELECT VAL
        FROM RES_GET(:RES_ID, :LANG_CODE)
        INTO :TYPE_CAPTION;

        IF (READ_ONLY = 1) THEN
        BEGIN
            IS_ADD = 0;
            IS_COPY = 0;
            IS_CUT = 0;
            IS_LINK = 0;
        END

        SUSPEND;
    END

END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIB2_ABN_GET (
    I$OBJ_ID BIGINT,
    I$ALL SMALLINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$PARENT_ID BIGINT;
DECLARE VARIABLE V$PARENT_TYPE_ID BIGINT;
DECLARE VARIABLE V$TYPE_ID BIGINT;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$BOOK_ID BIGINT;
DECLARE VARIABLE V$INSTANCE_ID BIGINT;
DECLARE VARIABLE V$ACTION_DATE DATE;
DECLARE VARIABLE V$QUANTITY INTEGER;
DECLARE VARIABLE V$PLAN_DATE DATE;
DECLARE VARIABLE V$RETURN_DATE DATE;
DECLARE VARIABLE V$LOSS_DATE DATE;
DECLARE VARIABLE V$BOOK_NAME VARCHAR(400);
DECLARE VARIABLE V$INV_CODE VARCHAR(100);
DECLARE VARIABLE V$PUB_YEAR INTEGER;
DECLARE VARIABLE V$AUTHOR VARCHAR(200);
DECLARE VARIABLE V$OBJ_TYPE BIGINT;
DECLARE VARIABLE V$PART_NUM SMALLINT;
DECLARE VARIABLE V$CT VARCHAR(100);
DECLARE VARIABLE V$LOAD_ID BIGINT;
begin

  -- Тут могут быть: сотрудники, ученики, классы
  SELECT FIRST 1 LP.PARENT_ID, LP.PARENT_TYPE_ID, LP.OBJ_TYPE_ID
  FROM LINKS LP
  WHERE LP.OBJ_ID = :I$OBJ_ID AND LP.PARENT_TYPE_ID IN (2, 211, 8, 9, 187, 81, 82, 83, 84) AND LP.DATE_DEL IS NULL
  -- ORDER BY ???
  INTO :V$PARENT_ID, :V$PARENT_TYPE_ID, :V$TYPE_ID;

  IF(V$PARENT_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Персона не найдена';

  TAG_NAME = 'id';
  VAL = I$OBJ_ID;
  SUSPEND;

  TAG_NAME = 'type_id';
  VAL = V$TYPE_ID;
  SUSPEND;

  TAG_NAME = 'parent_type_id';
  VAL = V$PARENT_TYPE_ID;
  SUSPEND;

  TAG_NAME = 'parent_id';
  VAL = V$PARENT_ID;
  SUSPEND;

  TAG_NAME = 'parent_name';
  IF(V$PARENT_TYPE_ID IN (2, 211)) THEN VAL = 'Сотрудники';
  -- название класса
  ELSE IF(V$PARENT_TYPE_ID = 8) THEN VAL = NULL;
  ELSE VAL = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$PARENT_ID));
  SUSPEND;

  -- Для класса название будет то же что и parent_id
  TAG_NAME = 'name';
  IF(V$PARENT_TYPE_ID = 8) THEN
    VAL = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$OBJ_ID));
  ELSE
    SELECT C1 FROM BUILD_REP_FIO(:I$OBJ_ID, IIF(:V$TYPE_ID = 10, 55, 59), IIF(:V$TYPE_ID = 10, 56, 60), IIF(:V$TYPE_ID = 10, 57, 61), 1) INTO :VAL;
  SUSPEND;

  TAG_NAME = 'ab_num';
  VAL = NULL;
  SUSPEND;

  TAG_NAME = 'ab_date';
  VAL = NULL;
  SUSPEND;

  TAG_NAME = 'books::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    -- Сначала список литературы на руках
    -- только если all = 0
    SELECT U.OBJ_ID, U.BOOK_ID, U.INSTANCE_ID, U.ACTION_DATE, U.QUANTITY, U.PLAN_DATE, U.RETURN_DATE, U.LOSS_DATE, B.BOOK_NAME, B.PUB_YEAR, B.PART_NUM, I.INV_CODE,
      COALESCE(A.VAL, B.AUTHORS), B.OBJ_TYPE, CT.VAL, U.LOAD_ID
    FROM LIB2_USAGE U
    JOIN LIB2_BOOKS B ON B.OBJ_ID = U.BOOK_ID
    LEFT JOIN LIB2_LISTVALS A ON A.LISTVAL_ID = B.AUTHOR_ID
    LEFT JOIN LIB2_INSTANCES I ON I.OBJ_ID = U.INSTANCE_ID
    LEFT JOIN LISTVAL_TEXT(B.OBJ_TYPE) CT ON 1 = 1
    WHERE U.DATE_DEL IS NULL AND U.REF_ID = :I$OBJ_ID AND U.RETURN_DATE IS NULL AND U.LOSS_DATE IS NULL AND :I$ALL = 0
    -- История - только если all = 1
    UNION
    SELECT U.OBJ_ID, U.BOOK_ID, U.INSTANCE_ID, U.ACTION_DATE, U.QUANTITY, U.PLAN_DATE, U.RETURN_DATE, U.LOSS_DATE, B.BOOK_NAME, B.PUB_YEAR, B.PART_NUM, I.INV_CODE,
      COALESCE(A.VAL, B.AUTHORS), B.OBJ_TYPE, CT.VAL, NULL
    FROM LIB2_USAGE U
    JOIN LIB2_BOOKS B ON B.OBJ_ID = U.BOOK_ID
    LEFT JOIN LIB2_LISTVALS A ON A.LISTVAL_ID = B.AUTHOR_ID
    LEFT JOIN LIB2_INSTANCES I ON I.OBJ_ID = U.INSTANCE_ID
    LEFT JOIN LISTVAL_TEXT(B.OBJ_TYPE) CT ON 1 = 1
    WHERE U.DATE_DEL IS NULL AND U.REF_ID = :I$OBJ_ID AND (U.RETURN_DATE IS NOT NULL OR U.LOSS_DATE IS NOT NULL) AND :I$ALL = 1
    ORDER BY 4
    INTO :V$OBJ_ID, :V$BOOK_ID, :V$INSTANCE_ID, :V$ACTION_DATE, :V$QUANTITY, :V$PLAN_DATE, :V$RETURN_DATE, :V$LOSS_DATE, :V$BOOK_NAME, :V$PUB_YEAR, :V$PART_NUM, :V$INV_CODE,
      :V$AUTHOR, :V$OBJ_TYPE, :V$CT, :V$LOAD_ID
  DO
  BEGIN
    TAG_NAME = 'books:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'books:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'books:r:book_id';
    VAL = V$BOOK_ID;
    SUSPEND;
    TAG_NAME = 'books:r:inst_id';
    VAL = V$INSTANCE_ID;
    SUSPEND;
    TAG_NAME = 'books:r:obj_type_id';
    VAL = V$OBJ_TYPE;
    SUSPEND;
    TAG_NAME = 'books:r:obj_type';
    VAL = V$CT;
    SUSPEND;
    TAG_NAME = 'books:r:part_num';
    VAL = V$PART_NUM;
    SUSPEND;
    TAG_NAME = 'books:r:plan_name';
    VAL = NULL;
    IF(V$LOAD_ID IS NOT NULL) THEN
    SELECT FIRST 1 C.CAPTION
    FROM PLAN_LOADS PL
    JOIN PLAN_SUBJECTS PS ON PS.OBJ_ID = PL.SUBJECT_ID
    LEFT JOIN OBJECT_CAPTION_GET(PS.PLAN_ID) C ON 1 = 1
    WHERE PL.OBJ_ID = :V$LOAD_ID AND PL.DATE_DEL IS NULL
    INTO :VAL;
    SUSPEND;
    TAG_NAME = 'books:r:action_date';
    VAL = (SELECT VAL FROM DATE2ISO(:V$ACTION_DATE, 0));
    SUSPEND;
    TAG_NAME = 'books:r:plan_date';
    VAL = (SELECT VAL FROM DATE2ISO(:V$PLAN_DATE, 0));
    SUSPEND;
    TAG_NAME = 'books:r:return_date';
    VAL = (SELECT VAL FROM DATE2ISO(:V$RETURN_DATE, 0));
    SUSPEND;
    TAG_NAME = 'books:r:loss_date';
    VAL = (SELECT VAL FROM DATE2ISO(:V$LOSS_DATE, 0));
    SUSPEND;
    TAG_NAME = 'books:r:name';
    VAL = V$BOOK_NAME;
    SUSPEND;
    TAG_NAME = 'books:r:author';
    VAL = V$AUTHOR;
    SUSPEND;
    TAG_NAME = 'books:r:pub_year';
    VAL = V$PUB_YEAR;
    SUSPEND;
    TAG_NAME = 'books:r:inv_code';
    VAL = V$INV_CODE;
    SUSPEND;
    TAG_NAME = 'books:r:quantity';
    VAL = V$QUANTITY;
    SUSPEND;
    -- Если это ведомость класса - надо посчитать еще баланс по ученикам
    -- на руки выдаются только поштучно !
    IF(V$PARENT_TYPE_ID = 8) THEN
    BEGIN
      -- Сколько у нас в группе обучающихся ?
      TAG_NAME = 'books:r:n_students';
      VAL = NULL; -- !!!
      SUSPEND;
      -- Сколько числится на руках
      TAG_NAME = 'books:r:quantity_onhands';
      SELECT COUNT(*)
      FROM LIB2_USAGE U
      WHERE U.DATE_DEL IS NULL AND U.REF_TYPE_ID = 10 AND U.CLASS_USAGE_ID = :V$OBJ_ID AND U.RETURN_DATE IS NULL AND U.LOSS_DATE IS NULL
      INTO :VAL;
      SUSPEND;
    END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIB2_ABN_INFO (
    I$USE_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$ACTION_DATE DATE;
DECLARE VARIABLE V$RETURN_DATE DATE;
DECLARE VARIABLE V$LOSS_DATE DATE;
DECLARE VARIABLE V$USER_ID BIGINT;
DECLARE VARIABLE V$RET_USER_ID BIGINT;
DECLARE VARIABLE V$BOOK_NAME VARCHAR(400);
DECLARE VARIABLE V$INV_CODE VARCHAR(40);
DECLARE VARIABLE V$PART_NUM SMALLINT;
DECLARE VARIABLE Q INTEGER;
DECLARE VARIABLE V$USERTYPE SMALLINT;
DECLARE VARIABLE V$PLAN_ID BIGINT;
begin

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  SELECT U.USER_TYPE
  FROM USERS U
  WHERE U.USER_ID = :I$USER_ID
  INTO :V$USERTYPE;

  SELECT U.ACTION_DATE, U.RETURN_DATE, U.LOSS_DATE, U.QUANTITY, U.USER_ID, U.RET_USER_ID, B.BOOK_NAME, B.PART_NUM, I.INV_CODE, PS.PLAN_ID
  FROM LIB2_USAGE U
  JOIN LIB2_BOOKS B ON B.OBJ_ID = U.BOOK_ID
  LEFT JOIN LIB2_INSTANCES I ON I.OBJ_ID = U.INSTANCE_ID
  LEFT JOIN PLAN_LOADS PL ON PL.OBJ_ID = U.LOAD_ID
  LEFT JOIN PLAN_SUBJECTS PS ON PS.OBJ_ID = PL.SUBJECT_ID
  WHERE U.DATE_DEL IS NULL AND U.OBJ_ID = :I$USE_ID
  INTO :V$ACTION_DATE, :V$RETURN_DATE, :V$LOSS_DATE, :Q, :V$USER_ID, :V$RET_USER_ID, :V$BOOK_NAME, :V$PART_NUM, :V$INV_CODE, :V$PLAN_ID;

  IF(V$ACTION_DATE IS NULL) THEN EXCEPTION DATA_ERROR 'Запись выдачи издания не найдена или была отменена';

  TAG_NAME = 'id';
  VAL = I$USE_ID;
  SUSPEND;

  TAG_NAME = 'book_name';
  VAL = V$BOOK_NAME;
  SUSPEND;

  TAG_NAME = 'part_num';
  VAL = V$PART_NUM;
  SUSPEND;

  TAG_NAME = 'quantity';
  VAL = Q;
  SUSPEND;

  TAG_NAME = 'inv_code';
  VAL = V$INV_CODE;
  SUSPEND;

  TAG_NAME = 'plan_id';
  VAL = V$PLAN_ID;
  SUSPEND;

  TAG_NAME = 'plan_name';
  IF(V$PLAN_ID IS NULL) THEN VAL = NULL; ELSE VAL = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$PLAN_ID));
  SUSPEND;

  TAG_NAME = 'action_date';
  VAL = (SELECT VAL FROM DATE2ISO(:V$ACTION_DATE));
  SUSPEND;

  TAG_NAME = 'return_date';
  VAL = (SELECT VAL FROM DATE2ISO(:V$RETURN_DATE));
  SUSPEND;

  TAG_NAME = 'loss_date';
  VAL = (SELECT VAL FROM DATE2ISO(:V$LOSS_DATE));
  SUSPEND;

  -- Отменять может только тот же самый пользователь, или администратор или руководитель
  TAG_NAME = 'can_undo_give';
  IF(V$RETURN_DATE IS NOT NULL OR V$LOSS_DATE IS NOT NULL) THEN VAL = 0;
  ELSE IF(V$USERTYPE IN (1, 5) OR I$USER_ID = V$USER_ID) THEN VAL = 1;
  ELSE VAL = 0;
  SUSPEND;

  TAG_NAME = 'can_undo_return';
  IF(V$RETURN_DATE IS NULL AND V$LOSS_DATE IS NULL) THEN VAL = 0;
  ELSE IF(V$USERTYPE IN (1, 5) OR I$USER_ID = V$RET_USER_ID) THEN VAL = 1;
  ELSE VAL = 0;
  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIB2_ABN_LIST (
    I$PLACE_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$GROUP_ID BIGINT;
DECLARE VARIABLE V$SI DOUBLE PRECISION;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$IS_BIBL SMALLINT;
DECLARE VARIABLE V$ROLE SMALLINT;
DECLARE VARIABLE V$PERSON_ID BIGINT;
DECLARE VARIABLE V$HEAD SMALLINT;
DECLARE VARIABLE S VARCHAR(1000);
DECLARE VARIABLE CARDNUM VARCHAR(200);
DECLARE VARIABLE T BIGINT;
begin

  -- Библиотекарь, админ, директор, завуч видят всех
  -- предметники и классруки видят свой класс
  -- и все видят только себя
  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;
  SELECT FIRST 1 U.USER_TYPE, U.OBJ_ID
  FROM USERS U
  WHERE U.USER_ID = :I$USER_ID AND U.DATE_DEL IS NULL
  INTO :V$ROLE, :V$PERSON_ID;

  V$IS_BIBL = 0;
  -- Роль = библиотекарь
  IF(V$ROLE = 11
  OR EXISTS(
    -- Должность = библиотекарь
    SELECT FIRST 1 1
    FROM USERS U
    JOIN LINKS L15 ON L15.PARENT_ID = U.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
    JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
    LEFT JOIN VALS V3543 ON V3543.OBJ_ID = L15.OBJ_ID AND V3543.PARAM_ID = 3543 AND V3543.IS_DEL = 0
    LEFT JOIN VALS V589 ON V589.OBJ_ID = L15.OBJ_ID AND V589.PARAM_ID = 589 AND V589.IS_DEL = 0
    WHERE U.USER_ID = :I$USER_ID AND U.DATE_DEL IS NULL AND V74.VAL IS NULL
      AND (UPPER(V3543.SVAL) LIKE '%БИБЛИОТ%' OR UPPER(V589.SVAL) LIKE '%БИБЛИОТ%')
  ))
  THEN
    V$IS_BIBL = 1;

  TAG_NAME = 'groups::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L2.OBJ_ID, -1, L2.OBJ_TYPE_ID, 'Сотрудники', 0
    FROM LINKS L2
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    UNION
    SELECT L9.OBJ_ID, C.SORT_ORDER, L9.OBJ_TYPE_ID, C.SCAPTION, IIF(V53.VAL = :V$PERSON_ID, 1, 0)
    FROM LINKS L2
    JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 187) AND L9.DATE_DEL IS NULL
    LEFT JOIN VALR V53 ON V53.OBJ_ID = L9.OBJ_ID AND V53.PARAM_ID = 53 AND V53.IS_DEL = 0
    LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C ON 1 = 1
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    AND (
      :V$IS_BIBL = 1
      OR :V$ROLE IN (1, 5, 6)
      OR V53.VAL = :V$PERSON_ID
      -- Добавить кураторов и воспитателей ДО
    )
    ORDER BY 2, 4
    INTO :V$GROUP_ID, :V$SI, :T, :S, :V$HEAD
  DO
  BEGIN
    TAG_NAME = 'groups:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'groups:r:id';
    VAL = V$GROUP_ID;
    SUSPEND;
    TAG_NAME = 'groups:r:name';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'groups:r:type_id';
    VAL = T;
    SUSPEND;
    TAG_NAME = 'groups:r:persons::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT LP.OBJ_ID, LP.OBJ_TYPE_ID, C.C1, V.SVAL
      FROM LINKS LP
      LEFT JOIN BUILD_REP_FIO(LP.OBJ_ID, IIF(LP.OBJ_TYPE_ID = 10, 55, 59), IIF(LP.OBJ_TYPE_ID = 10, 56, 60), IIF(LP.OBJ_TYPE_ID = 10, 57, 61), 1) C ON 1 = 1
      LEFT JOIN VALS V ON V.OBJ_ID = LP.OBJ_ID AND V.PARAM_ID IN (2855, 2857) AND V.IS_DEL = 0
      WHERE LP.PARENT_ID = :V$GROUP_ID AND LP.OBJ_TYPE_ID IN (10, 14) AND LP.DATE_DEL IS NULL
      AND (
        :V$IS_BIBL = 1
        OR :V$ROLE IN (1, 5, 6)
        OR :V$HEAD = 1
        OR LP.OBJ_ID = :V$PERSON_ID
      )
      ORDER BY 2, 3
      INTO :V$OBJ_ID, :T, :S, :CARDNUM
    DO
    BEGIN
      TAG_NAME = 'groups:r:persons:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'groups:r:persons:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'groups:r:persons:r:type_id';
      VAL = T;
      SUSPEND;
      TAG_NAME = 'groups:r:persons:r:name';
      VAL = S;
      SUSPEND;
      TAG_NAME = 'groups:r:persons:r:ab_num';
      VAL = NULL; -- TODO !!!
      SUSPEND;
      TAG_NAME = 'groups:r:persons:r:ab_date';
      VAL = NULL; -- TODO !!!
      SUSPEND;
      TAG_NAME = 'groups:r:persons:r:cardnum';
      VAL = CARDNUM;
      SUSPEND;
    END
  END

  -- Надо додумать что делать с выбывшими чтобы можно было посмотреть историю

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIB2_ABN_MASS_ASSN (
    I$GRADE_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(40),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$REF_ID BIGINT;
DECLARE VARIABLE V$PLAN_ID BIGINT;
DECLARE VARIABLE S VARCHAR(1000);
DECLARE VARIABLE S2 VARCHAR(1000);
DECLARE VARIABLE Q INTEGER;
DECLARE VARIABLE Y INTEGER;
begin

  TAG_NAME = 'name';
  VAL = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$GRADE_ID));
  SUSPEND;

  -- Список учащихся
  -- Связка с УП, чтобы можно было выдавать только те учебники, которые выделены под данный УП
  TAG_NAME = 'persons::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L10.OBJ_ID, F.C1
    FROM LINKS L10
    LEFT JOIN BUILD_REP_FIO(L10.OBJ_ID, 55, 56, 57, 1) F ON 1 = 1
    WHERE L10.PARENT_ID = :I$GRADE_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    ORDER BY 2
    INTO :V$OBJ_ID, :S
  DO
  BEGIN
    TAG_NAME = 'persons:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'persons:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'persons:r:name';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'persons:r:plan_id';
    VAL = NULL;
    S2 = NULL;
    SELECT FIRST 1 LP400.PARENT_ID, C.CAPTION
    FROM LINKS LP256
    JOIN LINKS LP54 ON LP54.OBJ_ID = LP256.PARENT_ID AND LP54.PARENT_TYPE_ID = 54 AND LP54.DATE_DEL IS NULL
    JOIN LINKS LP400 ON LP400.OBJ_ID = LP54.PARENT_ID AND LP400.PARENT_TYPE_ID = 400 AND LP400.DATE_DEL IS NULL
    LEFT JOIN OBJECT_CAPTION_GET(LP400.PARENT_ID) C ON 1 = 1
    WHERE LP256.OBJ_ID = :V$OBJ_ID AND LP256.PARENT_TYPE_ID = 256 AND LP256.DATE_DEL IS NULL
    INTO :VAL, :S2;
    SUSPEND;
    TAG_NAME = 'persons:r:plan_name';
    VAL = S2;
    SUSPEND;
  END

  -- Список партий учебников
  -- Партии привязываются к учебным планам через нагрузки, мешать нельзя
  TAG_NAME = 'books::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT U.OBJ_ID, B.BOOK_NAME, B.AUTHORS, B.PUB_YEAR, U.QUANTITY, PS.PLAN_ID
    FROM LIB2_USAGE U
    JOIN LIB2_BOOKS B ON B.OBJ_ID = U.BOOK_ID
    LEFT JOIN PLAN_LOADS PL ON PL.OBJ_ID = U.LOAD_ID
    LEFT JOIN PLAN_SUBJECTS PS ON PS.OBJ_ID = PL.SUBJECT_ID
    WHERE U.DATE_DEL IS NULL AND U.REF_ID = :I$GRADE_ID AND U.RETURN_DATE IS NULL AND U.LOSS_DATE IS NULL
    ORDER BY 2
    INTO :V$OBJ_ID, :S, :S2, :Y, :Q, :V$PLAN_ID
  DO
  BEGIN
    TAG_NAME = 'books:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'books:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'books:r:plan_id';
    VAL = V$PLAN_ID;
    SUSPEND;
    TAG_NAME = 'books:r:name';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'books:r:authors';
    VAL = S2;
    SUSPEND;
    TAG_NAME = 'books:r:pub_year';
    VAL = Y;
    SUSPEND;
    TAG_NAME = 'books:r:quantity';
    VAL = Q;
    SUSPEND;
  END

  -- Связывание учеников и учебников
  TAG_NAME = 'assignments::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L10.OBJ_ID, U.CLASS_USAGE_ID
    FROM LINKS L10
    JOIN LIB2_USAGE U ON U.DATE_DEL IS NULL AND U.REF_ID = L10.OBJ_ID AND U.RETURN_DATE IS NULL AND U.LOSS_DATE IS NULL AND U.CLASS_USAGE_ID IS NOT NULL
    WHERE L10.PARENT_ID = :I$GRADE_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    INTO :V$OBJ_ID, :V$REF_ID
  DO
  BEGIN
    TAG_NAME = 'assignments:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'assignments:r:person_id';
    VAL = V$OBJ_ID;
    SUSPEND;
    -- тут не именно book_id, а номер партии выданной на класс
    TAG_NAME = 'assignments:r:book_id';
    VAL = V$REF_ID;
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIB2_ABN_MASS_LIST (
    I$GRADE_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$SUBJECT_ID BIGINT;
DECLARE VARIABLE V$STAGE_ID INTEGER;
DECLARE VARIABLE N INTEGER;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$NAME VARCHAR(400);
DECLARE VARIABLE V$AUTHORS VARCHAR(400);
DECLARE VARIABLE V$PART SMALLINT;
DECLARE VARIABLE V$N_AVAIL INTEGER;
DECLARE VARIABLE V$N_FREE INTEGER;
DECLARE VARIABLE V$YEAR INTEGER;
DECLARE VARIABLE V$LOAD_ID BIGINT;
DECLARE VARIABLE V$PLAN_ID BIGINT;
DECLARE VARIABLE V$PLAN_NAME VARCHAR(400);
DECLARE VARIABLE S VARCHAR(4000);
begin

  -- Показываем все учебники, которые подходят по параллели и предмету данному классу
  S = '';
  TAG_NAME = 'subjects::json&colon;array';
  VAL = 1;
  SUSPEND;
  -- Первый цикл выборки - по учебным планам
  FOR
    SELECT DISTINCT PS.PLAN_ID, C.CAPTION
    FROM LINKS L10
    JOIN LINKS LP256 ON LP256.OBJ_ID = L10.OBJ_ID AND LP256.PARENT_TYPE_ID = 256 AND LP256.DATE_DEL IS NULL
    JOIN LINKS LP54 ON LP54.OBJ_ID = LP256.PARENT_ID AND LP54.PARENT_TYPE_ID = 54 AND LP54.DATE_DEL IS NULL
    JOIN VALL V381 ON V381.OBJ_ID = LP54.PARENT_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V381.LISTVAL_ID
    JOIN PLAN_LOADS PL ON PL.DATE_DEL IS NULL AND PL.STAGE_ID = LP54.PARENT_ID AND PL.LOAD_HOURS > 0
    JOIN PLAN_SUBJECTS PS ON PS.DATE_DEL IS NULL AND PS.OBJ_ID = PL.SUBJECT_ID AND PS.ROW_TYPE = 10
    LEFT JOIN OBJECT_CAPTION_GET(PS.PLAN_ID) C ON 1 = 1
    WHERE L10.PARENT_ID = :I$GRADE_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    ORDER BY 2
    INTO :V$PLAN_ID, :V$PLAN_NAME
  DO
  BEGIN
    S = '';
    FOR
      SELECT PL.OBJ_ID, COALESCE(PS.SRC_SUBJECT_ID, PS.SUBJECT_ID), LV.COST, V376.SVAL, COUNT(DISTINCT L10.OBJ_ID)
      FROM LINKS L10
      JOIN LINKS LP256 ON LP256.OBJ_ID = L10.OBJ_ID AND LP256.PARENT_TYPE_ID = 256 AND LP256.DATE_DEL IS NULL
      JOIN LINKS LP54 ON LP54.OBJ_ID = LP256.PARENT_ID AND LP54.PARENT_TYPE_ID = 54 AND LP54.DATE_DEL IS NULL
      JOIN VALL V381 ON V381.OBJ_ID = LP54.PARENT_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
      JOIN LISTVALS LV ON LV.LISTVAL_ID = V381.LISTVAL_ID
      JOIN PLAN_LOADS PL ON PL.DATE_DEL IS NULL AND PL.STAGE_ID = LP54.PARENT_ID AND PL.LOAD_HOURS > 0
      JOIN PLAN_SUBJECTS PS ON PS.DATE_DEL IS NULL AND PS.OBJ_ID = PL.SUBJECT_ID AND PS.ROW_TYPE = 10 AND PS.PLAN_ID = :V$PLAN_ID
      -- не показываем тут индивидуальный проект и элективный блок
      LEFT JOIN PLAN_SUBJECTS PSP ON PSP.OBJ_ID = PS.PARENT_ID
      JOIN VALS V376 ON V376.OBJ_ID = COALESCE(PS.SRC_SUBJECT_ID, PS.SUBJECT_ID) AND V376.PARAM_ID = 376 AND V376.IS_DEL = 0
      WHERE L10.PARENT_ID = :I$GRADE_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        AND (PSP.OBJ_ID IS NULL OR PSP.FIELD_ID IS NULL OR PSP.FIELD_ID <> 12928) AND PS.SUBJECT_ID <> 34651
      GROUP BY 1, 2, 3, 4
      ORDER BY 3, 4
      INTO :V$LOAD_ID, :V$SUBJECT_ID, :V$STAGE_ID, :V$NAME, :N
    DO
    BEGIN
      -- Не выдаем повторно строки предметов, которые уже появлялись в выдаче
      -- например когда предмет идет в обязательной и переменной частях УП
      IF(POSITION(V$SUBJECT_ID || ':' || V$STAGE_ID || ',' IN S) <= 0) THEN
      BEGIN
        -- Запоминаем, что уже выдали
        S = S || V$SUBJECT_ID || ':' || V$STAGE_ID || ',';
        TAG_NAME = 'subjects:r';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'subjects:r:id';
        VAL = V$SUBJECT_ID;
        SUSPEND;
        TAG_NAME = 'subjects:r:load_id';
        VAL = V$LOAD_ID;
        SUSPEND;
        TAG_NAME = 'subjects:r:plan_name';
        VAL = V$PLAN_NAME;
        SUSPEND;
        TAG_NAME = 'subjects:r:name';
        VAL = V$NAME;
        SUSPEND;
        TAG_NAME = 'subjects:r:stage_num';
        VAL = V$STAGE_ID;
        SUSPEND;
        TAG_NAME = 'subjects:r:n_students';
        VAL = N;
        SUSPEND;
        -- Показываем все ученики, подходящие по одному из предметов
        TAG_NAME = 'subjects:r:books::json&colon;array';
        VAL = 1;
        SUSPEND;
        FOR
          SELECT B.OBJ_ID, B.BOOK_NAME, COALESCE(A.VAL, B.AUTHORS), B.PART_NUM, B.PUB_YEAR, B.N_AVAIL, B.N_FREE
          FROM LIB2_BOOKS B
          LEFT JOIN LIB2_LISTVALS A ON A.LISTVAL_ID = B.AUTHOR_ID
          WHERE B.DATE_DEL IS NULL AND (B.SUBJECT_ID = :V$SUBJECT_ID OR B.SUBJECT_ID2 = :V$SUBJECT_ID OR B.SUBJECT_ID3 = :V$SUBJECT_ID)
            AND B.STAGE_FROM <= :V$STAGE_ID AND B.STAGE_TO >= :V$STAGE_ID AND B.N_AVAIL > 0
          ORDER BY 2
          INTO :V$OBJ_ID, :V$NAME, :V$AUTHORS, :V$PART, :V$YEAR, :V$N_AVAIL, :V$N_FREE
        DO
        BEGIN
          TAG_NAME = 'subjects:r:books:r';
          VAL = NULL;
          SUSPEND;
          TAG_NAME = 'subjects:r:books:r:id';
          VAL = V$OBJ_ID;
          SUSPEND;
          TAG_NAME = 'subjects:r:books:r:name';
          VAL = V$NAME;
          SUSPEND;
          TAG_NAME = 'subjects:r:books:r:author';
          VAL = V$AUTHORS;
          SUSPEND;
          TAG_NAME = 'subjects:r:books:r:part_num';
          VAL = V$PART;
          SUSPEND;
          TAG_NAME = 'subjects:r:books:r:pub_year';
          VAL = V$YEAR;
          SUSPEND;
          TAG_NAME = 'subjects:r:books:r:n_avail';
          VAL = V$N_AVAIL;
          SUSPEND;
          TAG_NAME = 'subjects:r:books:r:n_free';
          VAL = V$N_FREE;
          SUSPEND;
          -- Сколько выдано в данный класс
          -- Тут может быть коллизия, если поменяли УП, а выдача была привязана к другой строке нагрузки
          TAG_NAME = 'subjects:r:books:r:n_used';
          VAL = NULL;
          SELECT SUM(U.QUANTITY)
          FROM LIB2_USAGE U
          WHERE U.DATE_DEL IS NULL AND U.BOOK_ID = :V$OBJ_ID AND U.REF_ID = :I$GRADE_ID AND U.RETURN_DATE IS NULL AND U.LOSS_DATE IS NULL AND U.LOAD_ID = :V$LOAD_ID
          INTO :VAL;
          IF(VAL IS NULL) THEN VAL = 0;
          SUSPEND;
        END
      END
    END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIB2_BOOK_ADD_FPU (
    I$FPU_ID BIGINT,
    I$TYPE_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    OBJ_ID BIGINT,
    BOOK_NAME VARCHAR(1000))
AS
DECLARE VARIABLE V$AUTHORS VARCHAR(400);
DECLARE VARIABLE V$SUBJECT_ID BIGINT;
DECLARE VARIABLE V$GRADE_FROM INTEGER;
DECLARE VARIABLE V$GRADE_TO INTEGER;
DECLARE VARIABLE V$ATTRS INTEGER;
DECLARE VARIABLE V$GRADES VARCHAR(100);
DECLARE VARIABLE V$EDU_LEVEL_ID BIGINT;
DECLARE VARIABLE V$PUB_ID BIGINT;
DECLARE VARIABLE V$COMP_ID BIGINT;
DECLARE VARIABLE V$PNAME VARCHAR(200);
DECLARE VARIABLE V$CODE VARCHAR(40);
DECLARE VARIABLE V$DATE DATE;
DECLARE VARIABLE V$FPU_ID BIGINT;
DECLARE VARIABLE V$FPE_ID BIGINT;
begin
  IF (I$TYPE_ID = 18712) THEN
  BEGIN
    -- учебник
    IF (EXISTS(SELECT FIRST 1 1
      FROM LIB_FPU F
      WHERE F.OBJ_ID = :I$FPU_ID AND F.DATE_DEL IS NULL AND F.BOOKNAME LIKE '%част%'
    )) THEN
    BEGIN
      IF( EXISTS(
        SELECT FIRST 1 1
        FROM LIB2_BOOKS B
        WHERE B.DATE_DEL IS NULL AND B.FPU_ID = :I$FPU_ID AND B.PART_NUM IS NULL AND B.PUB_YEAR IS NULL
      ))
      THEN
        EXCEPTION DATA_ERROR 'Учебник с таким кодом уже есть в системе. Проверьте, правильно ли у него заполнены номер части и год публикации';
    END
    ELSE
    BEGIN
      IF(EXISTS(
        SELECT FIRST 1 1
        FROM LIB2_BOOKS B
        WHERE B.DATE_DEL IS NULL AND B.FPU_ID = :I$FPU_ID AND B.PUB_YEAR IS NULL
      ))
      THEN
        EXCEPTION DATA_ERROR 'Учебник с таким кодом уже есть в системе. Проверьте, правильно ли у него заполнен год публикации';
    END

    SELECT FIRST 1 SUBSTRING(F.BOOKNAME FROM 1 FOR 200), F.AUTHORS, F.SUBJECT_ID, F.GRADE_FROM, F.GRADE_TO, F.ATTRS, P.PUBLISHER_NAME
    FROM LIB_FPU F
    JOIN LIB_FP_PUBLISHER P ON P.PUBLISHER_ID = F.PUBLISHER_ID
    WHERE F.DATE_DEL IS NULL AND F.OBJ_ID = :I$FPU_ID
    INTO :BOOK_NAME, :V$AUTHORS, :V$SUBJECT_ID, :V$GRADE_FROM, :V$GRADE_TO, :V$ATTRS, :V$PNAME;

    V$FPU_ID = I$FPU_ID;
  END
  ELSE IF(I$TYPE_ID = 18716) THEN
  BEGIN
    -- электронное издание
    IF (EXISTS(
      SELECT FIRST 1 1
      FROM LIB2_BOOKS B
      WHERE B.DATE_DEL IS NULL AND B.FPE_ID = :I$FPU_ID
    )) THEN
      EXCEPTION DATA_ERROR 'Электронное издание с таким кодом уже есть в системе';

    -- Авторов тут нет, ставим издательство вместо автора
    SELECT FIRST 1 SUBSTRING(F.BOOKNAME FROM 1 FOR 200), P.PUBLISHER_NAME, F.SUBJECT_ID, F.GRADE_FROM, F.GRADE_TO, F.ATTRS, P.PUBLISHER_NAME, F.BOOK_CODE
    FROM LIB_FPE F
    JOIN LIB_FP_PUBLISHER P ON P.PUBLISHER_ID = F.PUBLISHER_ID
    WHERE F.DATE_DEL IS NULL AND F.OBJ_ID = :I$FPU_ID
    INTO :BOOK_NAME, :V$AUTHORS, :V$SUBJECT_ID, :V$GRADE_FROM, :V$GRADE_TO, :V$ATTRS, :V$PNAME, :V$CODE;

    V$FPE_ID = I$FPU_ID;
  END

  IF(BOOK_NAME IS NULL) THEN EXCEPTION DATA_ERROR 'Издание не найдено в федеральном справочнике';

  --IF(EXTRACT(MONTH FROM CURRENT_DATE) >= 9) THEN V$DATE = '01.09.' || EXTRACT(YEAR FROM CURRENT_DATE);
  --  ELSE V$DATE = '01.09.' || (EXTRACT(YEAR FROM CURRENT_DATE) - 1);
  V$DATE = CURRENT_DATE;

  -- Только для ФПУ, для ФПЭ код уже добыли
  IF(I$TYPE_ID = 18712) THEN
  SELECT FIRST 1 C.BOOKCODE
  FROM LIB_FPU_CODES C
  WHERE C.DATE_DEL IS NULL AND C.BOOK_ID = :I$FPU_ID AND C.DATE_ADD <= :V$DATE
  ORDER BY C.DATE_ADD DESC
  INTO :V$CODE;

  IF(V$CODE IS NULL) THEN EXCEPTION DATA_ERROR 'Системная ошибка. Код учебника не удалось восстановить. Свяжитесь с техподдержкой';

  -- Пытаемся отыскать издательство
  V$PNAME = UPPER(V$PNAME);
  SELECT FIRST 1 V.LISTVAL_ID
  FROM LIB2_LISTVALS V
  WHERE V.DATE_DEL IS NULL AND V.LIST_ID = 1 AND UPPER(V.VAL) = UPPER(:V$PNAME)
  INTO :V$PUB_ID;

  -- Ну хотя-бы чтобы слово встречалось
  IF(V$PUB_ID IS NULL) THEN
  SELECT FIRST 1 V.LISTVAL_ID
  FROM LIB2_LISTVALS V
  WHERE V.DATE_DEL IS NULL AND V.LIST_ID = 1 AND POSITION(UPPER(V.VAL) IN :V$PNAME) > 0
  ORDER BY V.LISTVAL_ID
  INTO :V$PUB_ID;

  IF(V$PUB_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не удалось идентифицировать издательство';

  V$GRADES = V$GRADE_FROM;
  IF(V$GRADE_TO <> V$GRADE_FROM) THEN V$GRADES = V$GRADES || '-' || V$GRADE_TO;

  -- Всегда обязательная часть по-умолчанию
  V$COMP_ID = 12752;

  -- Уровень образования
  IF(V$GRADE_FROM < 5) THEN V$EDU_LEVEL_ID = 22;
  ELSE IF(V$GRADE_FROM < 10) THEN V$EDU_LEVEL_ID = 26;
  ELSE V$EDU_LEVEL_ID = 27;

  -- Вытащить номер издания из текста XXX издание или XXX-е издание ?

  INSERT INTO LIB2_BOOKS
  (OBJ_TYPE, BOOK_NAME, AUTHORS, PUBLISHER_ID, STAGE_FROM, STAGE_TO, STAGE_NUM, FPU_ID, FPE_ID, FPU_CODE, COMPONENT_ID, SUBJECT_ID, EDU_LEVEL_ID, ADAPT_ID, DIFF_LEVEL_ID)
  VALUES (:I$TYPE_ID, :BOOK_NAME, :V$AUTHORS, :V$PUB_ID, :V$GRADE_FROM, :V$GRADE_TO, :V$GRADES, :V$FPU_ID, :V$FPE_ID, :V$CODE, :V$COMP_ID, :V$SUBJECT_ID, :V$EDU_LEVEL_ID, IIF(:V$ATTRS = 3, 1, 0), IIF(:V$ATTRS = 2, 1, 0))
  RETURNING OBJ_ID INTO :OBJ_ID;

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIB2_BOOK_DELETE (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
AS
DECLARE VARIABLE N INTEGER;
begin

  SELECT FIRST 1 B.N_AVAIL
  FROM LIB2_BOOKS B
  WHERE B.OBJ_ID = :I$OBJ_ID AND B.DATE_DEL IS NULL
  INTO :N;

  IF(N IS NULL) THEN EXCEPTION DATA_ERROR 'Запись не найдена или была удалена';
  IF(N > 0) THEN EXCEPTION DATA_ERROR 'Нельзя удалить запись издания, пока в системе числится ненулевое количество экземпляров';

  UPDATE LIB2_BOOKS
  SET DATE_DEL = CURRENT_TIMESTAMP
  WHERE OBJ_ID = :I$OBJ_ID;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIB2_BOOK_GET (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$N_AVAIL INTEGER;
DECLARE VARIABLE V$N_FREE INTEGER;
DECLARE VARIABLE V$OBJ_TYPE BIGINT;
DECLARE VARIABLE V$AUTHOR_ID BIGINT;
DECLARE VARIABLE V$PUBLISHER_ID BIGINT;
DECLARE VARIABLE V$CODE_ISBN VARCHAR(30);
DECLARE VARIABLE S VARCHAR(1000);
DECLARE VARIABLE V$PUB_YEAR INTEGER;
DECLARE VARIABLE V$AUTHORS VARCHAR(400);
DECLARE VARIABLE V$PART_NUM SMALLINT;
DECLARE VARIABLE V$PART_NAME VARCHAR(200);
DECLARE VARIABLE V$LANG_ID BIGINT;
DECLARE VARIABLE V$BOOK_SIZE VARCHAR(20);
DECLARE VARIABLE V$AGE_GROUP VARCHAR(20);
DECLARE VARIABLE V$SUBJECT_ID BIGINT;
DECLARE VARIABLE V$PUB_PLACE_ID BIGINT;
DECLARE VARIABLE V$AUTHOR_SIGN VARCHAR(10);
DECLARE VARIABLE V$UDK VARCHAR(100);
DECLARE VARIABLE V$EDITION_TEXT VARCHAR(200);
DECLARE VARIABLE V$PURPOSE_ID BIGINT;
DECLARE VARIABLE V$BBK VARCHAR(100);
DECLARE VARIABLE V$SUBJECT_ID2 BIGINT;
DECLARE VARIABLE V$SUBJECT_ID3 BIGINT;
DECLARE VARIABLE V$STAGE_FROM SMALLINT;
DECLARE VARIABLE V$STAGE_TO SMALLINT;
DECLARE VARIABLE V$EDU_LEVEL_ID BIGINT;
DECLARE VARIABLE V$FPU_ID BIGINT;
DECLARE VARIABLE V$FPE_ID BIGINT;
DECLARE VARIABLE V$ADAPT_ID BIGINT;
DECLARE VARIABLE V$COMPONENT_ID BIGINT;
DECLARE VARIABLE V$RELEASE_NUM VARCHAR(10);
DECLARE VARIABLE V$DIFF_LEVEL_ID SMALLINT;
DECLARE VARIABLE V$FPU_CODE VARCHAR(40);
DECLARE VARIABLE V$LIST_ID BIGINT;
begin

  SELECT FIRST 1 B.OBJ_ID, B.N_AVAIL, B.N_FREE, B.OBJ_TYPE, B.AUTHOR_ID, B.PUBLISHER_ID, B.CODE_ISBN, B.BOOK_NAME, B.PUB_YEAR, B.AUTHORS, B.PART_NUM, B.PART_NAME,
    B.LANG_ID, B.BOOK_SIZE, B.AGE_GROUP, B.SUBJECT_ID, B.PUB_PLACE_ID, B.AUTHOR_SIGN, B.UDK, B.EDITION_TEXT, B.PURPOSE_ID, B.BBK,
    B.SUBJECT_ID2, B.SUBJECT_ID3, B.STAGE_FROM, B.STAGE_TO, B.EDU_LEVEL_ID, B.FPU_ID, B.FPE_ID, B.ADAPT_ID, B.COMPONENT_ID, B.RELEASE_NUM,
    B.DIFF_LEVEL_ID, B.FPU_CODE
  FROM LIB2_BOOKS B
  WHERE B.OBJ_ID = :I$OBJ_ID AND B.DATE_DEL IS NULL
  INTO :V$OBJ_ID, :V$N_AVAIL, :V$N_FREE, :V$OBJ_TYPE, :V$AUTHOR_ID, :V$PUBLISHER_ID, :V$CODE_ISBN, :S, :V$PUB_YEAR, :V$AUTHORS, :V$PART_NUM, :V$PART_NAME,
    :V$LANG_ID, :V$BOOK_SIZE, :V$AGE_GROUP, :V$SUBJECT_ID, :V$PUB_PLACE_ID, :V$AUTHOR_SIGN, :V$UDK, :V$EDITION_TEXT, :V$PURPOSE_ID, :V$BBK,
    :V$SUBJECT_ID2, :V$SUBJECT_ID3, :V$STAGE_FROM, :V$STAGE_TO, :V$EDU_LEVEL_ID, :V$FPU_ID, :V$FPE_ID, :V$ADAPT_ID, :V$COMPONENT_ID, :V$RELEASE_NUM,
    :V$DIFF_LEVEL_ID, :V$FPU_CODE;

  IF(V$OBJ_ID IS NULL AND I$OBJ_ID IS NOT NULL) THEN EXCEPTION DATA_ERROR 'Запись не найдена или была удалена';

  TAG_NAME = 'id';
  VAL = V$OBJ_ID;
  SUSPEND;

  TAG_NAME = 'obj_type';
  VAL = V$OBJ_TYPE;
  SUSPEND;

  TAG_NAME = 'n_avail';
  VAL = V$N_AVAIL;
  SUSPEND;

  TAG_NAME = 'n_free';
  VAL = V$N_FREE;
  SUSPEND;

  TAG_NAME = 'author_id';
  VAL = V$AUTHOR_ID;
  SUSPEND;
  TAG_NAME = 'author_name';
  VAL = NULL;
  SELECT LV.VAL
  FROM LIB2_LISTVALS LV
  WHERE LV.LISTVAL_ID = :V$AUTHOR_ID
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'publisher_id';
  VAL = V$PUBLISHER_ID;
  SUSPEND;
  TAG_NAME = 'publisher_name';
  VAL = NULL;
  SELECT LV.VAL
  FROM LIB2_LISTVALS LV
  WHERE LV.LISTVAL_ID = :V$PUBLISHER_ID
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'code_isbn';
  VAL = V$CODE_ISBN;
  SUSPEND;

  TAG_NAME = 'book_name';
  VAL = S;
  SUSPEND;

  TAG_NAME = 'authors';
  VAL = V$AUTHORS;
  SUSPEND;

  TAG_NAME = 'part_num_id';
  VAL = V$PART_NUM;
  SUSPEND;

  TAG_NAME = 'part_name';
  VAL = V$PART_NAME;
  SUSPEND;

  TAG_NAME = 'book_size';
  VAL = V$BOOK_SIZE;
  SUSPEND;

  TAG_NAME = 'pub_year';
  VAL = V$PUB_YEAR;
  SUSPEND;

  TAG_NAME = 'age_group';
  VAL = V$AGE_GROUP;
  SUSPEND;

  TAG_NAME = 'lang_id:values:value';
  VAL = V$LANG_ID;
  SUSPEND;
  TAG_NAME = 'lang_id:selection::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT LISTVAL_ID, VAL
    FROM LISTVALS_LIST(49)
    WHERE IS_DEL = 0
    INTO :V$OBJ_ID, :S
  DO
  BEGIN
    TAG_NAME = 'lang_id:selection:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'lang_id:selection:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'lang_id:selection:r:value';
    VAL = S;
    SUSPEND;
  END

  -- Предметы только из федеральной сетки предметов - для учебников
  TAG_NAME = 'subject_id:values:value';
  VAL = V$SUBJECT_ID;
  SUSPEND;
  TAG_NAME = 'subject_id:selection::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L51.OBJ_ID, V376.SVAL
    FROM LINKS L51
    JOIN VALS V376 ON V376.OBJ_ID = L51.OBJ_ID AND V376.PARAM_ID = 376 AND V376.IS_DEL = 0
    WHERE L51.PARENT_ID = 32771 AND L51.OBJ_TYPE_ID = 51 AND L51.DATE_DEL IS NULL AND L51.OBJ_ID < 1000000000
      -- без олимпиадных предметов и элективов
      AND L51.OBJ_ID NOT IN (179, 34607, 38168, 38707, 38708, 38709, 38710, 38711, 38712, 38713, 38714, 38715, 38716, 38717, 38718, 38719)
    ORDER BY 2
    INTO :V$OBJ_ID, :S
  DO
  BEGIN
    TAG_NAME = 'subject_id:selection:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'subject_id:selection:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'subject_id:selection:r:value';
    VAL = S;
    SUSPEND;
  END
  -- Поле selection размножаем на клиентской стороне
  TAG_NAME = 'subject_id2:values:value';
  VAL = V$SUBJECT_ID2;
  SUSPEND;
  TAG_NAME = 'subject_id3:values:value';
  VAL = V$SUBJECT_ID3;
  SUSPEND;

  TAG_NAME = 'pub_place_id';
  VAL = V$PUB_PLACE_ID;
  SUSPEND;

  TAG_NAME = 'pub_place_name';
  VAL = NULL;
  SELECT LV.VAL
  FROM LIB2_LISTVALS LV
  WHERE LV.LISTVAL_ID = :V$PUB_PLACE_ID AND LV.DATE_DEL IS NULL
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'purpose_id:values:value';
  VAL = V$PURPOSE_ID;
  SUSPEND;
  TAG_NAME = 'purpose_id:selection::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT LV.LISTVAL_ID, LV.VAL
    FROM LIB2_LISTVALS LV
    WHERE LV.LIST_ID = 6 AND LV.DATE_DEL IS NULL
    ORDER BY 2
    INTO :V$OBJ_ID, :S
  DO
  BEGIN
    TAG_NAME = 'purpose_id:selection:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'purpose_id:selection:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'purpose_id:selection:r:value';
    VAL = S;
    SUSPEND;
  END

  TAG_NAME = 'author_sign';
  VAL = V$AUTHOR_SIGN;
  SUSPEND;

  TAG_NAME = 'udk';
  VAL = V$UDK;
  SUSPEND;

  TAG_NAME = 'bbk';
  VAL = V$BBK;
  SUSPEND;

  TAG_NAME = 'edition_text';
  VAL = V$EDITION_TEXT;
  SUSPEND;

  TAG_NAME = 'stage_from';
  VAL = V$STAGE_FROM;
  SUSPEND;

  TAG_NAME = 'stage_to';
  VAL = V$STAGE_TO;
  SUSPEND;

  TAG_NAME = 'stage_num';
  VAL = V$STAGE_FROM;
  IF(V$STAGE_TO <> V$STAGE_FROM) THEN VAL = VAL || '-' || V$STAGE_TO;
  SUSPEND;

  TAG_NAME = 'edu_level_id:values:value';
  VAL = V$EDU_LEVEL_ID;
  SUSPEND;
  TAG_NAME = 'edu_level_id:selection::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT LISTVAL_ID, VAL
    FROM LISTVALS_LIST(19)
    WHERE IS_DEL = 0 AND LISTVAL_ID IN (22, 26, 27) -- только ОО
    INTO :V$OBJ_ID, :S
  DO
  BEGIN
    TAG_NAME = 'edu_level_id:selection:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'edu_level_id:selection:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'edu_level_id:selection:r:value';
    VAL = S;
    SUSPEND;
  END

  TAG_NAME = 'fpu_id';
  VAL = V$FPU_ID;
  SUSPEND;
  TAG_NAME = 'fpe_id';
  VAL = V$FPU_ID;
  SUSPEND;
  TAG_NAME = 'fpu_code';
  VAL = V$FPU_CODE;
  SUSPEND;
  -- Это нам пока не надо, но можно выдать описание для ФПЭ
  TAG_NAME = 'fpu_name';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'fpu_from';
  VAL = NULL;
  IF(V$FPU_ID IS NOT NULL) THEN
  BEGIN
    SELECT FIRST 1 F.YEAR_ADD
    FROM LIB_FPU F
    WHERE F.OBJ_ID = :V$FPU_ID AND F.DATE_DEL IS NULL
    INTO :VAL;
  END
  -- FPE таких данных нет
  SUSPEND;
  TAG_NAME = 'fpu_to';
  VAL = NULL;
  IF(V$FPU_ID IS NOT NULL) THEN
  BEGIN
    SELECT FIRST 1 COALESCE(D.RESULT, F.YEAR_REMOVE)
    FROM LIB_FPU F
    LEFT JOIN DATE2STR(F.VALID_BY) D ON 1 = 1
    WHERE F.OBJ_ID = :V$FPU_ID AND F.DATE_DEL IS NULL
    INTO :VAL;
  END
  IF(V$FPE_ID IS NOT NULL) THEN
  BEGIN
    SELECT FIRST 1 D.RESULT
    FROM LIB_FPE F
    LEFT JOIN DATE2STR(F.VALID_BY) D ON 1 = 1
    WHERE F.OBJ_ID = :V$FPE_ID AND F.DATE_DEL IS NULL
    INTO :VAL;
  END
  SUSPEND;

  TAG_NAME = 'adapt_id:values:value';
  VAL = V$ADAPT_ID;
  SUSPEND;
  TAG_NAME = 'adapt_id:selection::json&colon;array';
  VAL = 1;
  SUSPEND;
    TAG_NAME = 'adapt_id:selection:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'adapt_id:selection:r:id';
    VAL = 0;
    SUSPEND;
    TAG_NAME = 'adapt_id:selection:r:value';
    VAL = 'Нет';
    SUSPEND;
    TAG_NAME = 'adapt_id:selection:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'adapt_id:selection:r:id';
    VAL = 1;
    SUSPEND;
    TAG_NAME = 'adapt_id:selection:r:value';
    VAL = 'Да';
    SUSPEND;

  TAG_NAME = 'component_id:values:value';
  VAL = V$COMPONENT_ID;
  SUSPEND;
  TAG_NAME = 'component_id:selection::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT LISTVAL_ID, VAL
    FROM LISTVALS_LIST(116)
    WHERE IS_DEL = 0 AND LISTVAL_ID IN (12752, 12753)
    INTO :V$OBJ_ID, :S
  DO
  BEGIN
    TAG_NAME = 'component_id:selection:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'component_id:selection:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'component_id:selection:r:value';
    VAL = S;
    SUSPEND;
  END

  TAG_NAME = 'release_num';
  VAL = V$RELEASE_NUM;
  SUSPEND;

  TAG_NAME = 'diff_level_id:values:value';
  VAL = V$DIFF_LEVEL_ID;
  SUSPEND;
  TAG_NAME = 'diff_level_id:selection::json&colon;array';
  VAL = 1;
  SUSPEND;
    TAG_NAME = 'diff_level_id:selection:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'diff_level_id:selection:r:id';
    VAL = 0;
    SUSPEND;
    TAG_NAME = 'diff_level_id:selection:r:value';
    VAL = 'Базовый';
    SUSPEND;
    TAG_NAME = 'diff_level_id:selection:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'diff_level_id:selection:r:id';
    VAL = 1;
    SUSPEND;
    TAG_NAME = 'diff_level_id:selection:r:value';
    VAL = 'Углубленный';
    SUSPEND;

  -- Кастомные атрибуты
  TAG_NAME = 'custom::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L.LIST_ID, L.LIST_NAME, L.MAX_LEVELS, BA.LISTVAL_ID
    FROM LIB2_LISTS L
    LEFT JOIN LIB2_BOOK_ATTRS BA ON BA.DATE_DEL IS NULL AND BA.BOOK_ID = :I$OBJ_ID AND BA.LIST_ID = L.LIST_ID
    WHERE L.DATE_DEL IS NULL AND L.LIST_ID > 1000000000
    ORDER BY 2
    INTO :V$LIST_ID, :S, V$LANG_ID, :V$OBJ_ID
  DO
  BEGIN
    TAG_NAME = 'custom:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'custom:r:id';
    VAL = V$LIST_ID;
    SUSPEND;
    TAG_NAME = 'custom:r:max_levels';
    VAL = V$LANG_ID;
    SUSPEND;
    TAG_NAME = 'custom:r:name';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'custom:r:value';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'custom:r:textvalue';
    VAL = NULL;
    IF(V$OBJ_ID IS NOT NULL) THEN
    SELECT LV.VAL
    FROM LIB2_LISTVALS LV
    WHERE LV.LISTVAL_ID = :V$OBJ_ID
    INTO :VAL;
    SUSPEND;
    -- Выбор значений только в линейном варианте списка или в древовидном в 1 уровень
    TAG_NAME = 'custom:r:values::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT LV.LISTVAL_ID, LV.VAL
      FROM LIB2_LISTVALS LV
      WHERE LV.DATE_DEL IS NULL AND LV.LIST_ID = :V$LIST_ID AND (:V$LANG_ID < 0 OR :V$LANG_ID = 1)
      ORDER BY 2
      INTO :V$SUBJECT_ID, :S
    DO
    BEGIN
      TAG_NAME = 'custom:r:values:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'custom:r:values:r:id';
      VAL = V$SUBJECT_ID;
      SUSPEND;
      TAG_NAME = 'custom:r:values:r:value';
      VAL = S;
      SUSPEND;
    END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIB2_BOOK_GIVE (
    I$PERSON_ID BIGINT,
    I$BOOK_ID BIGINT,
    I$INSTANCE_ID BIGINT,
    I$QTY INTEGER,
    I$DATE_TO DATE,
    I$IP VARCHAR(400),
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$PARENT_ID BIGINT;
DECLARE VARIABLE V$PARENT_TYPE_ID BIGINT;
DECLARE VARIABLE V$REF_TYPE_ID BIGINT;
DECLARE VARIABLE V$AVAIL INTEGER;
DECLARE VARIABLE V$FREE INTEGER;
DECLARE VARIABLE V$INST_FREE SMALLINT;
DECLARE VARIABLE V$USAGE_ID BIGINT;
DECLARE VARIABLE V$INV_CODE VARCHAR(100);
DECLARE VARIABLE V$BOOK_NAME VARCHAR(200);
DECLARE VARIABLE V$AUTHOR_ID BIGINT;
DECLARE VARIABLE V$PUB_YEAR INTEGER;
DECLARE VARIABLE V$OBJ_TYPE BIGINT;
DECLARE VARIABLE V$LOC_INDEX INTEGER;
DECLARE VARIABLE V$LOC INTEGER;
DECLARE VARIABLE N INTEGER;
DECLARE VARIABLE S VARCHAR(4000);
begin

  -- Формат ответа обязательно кореллировать в форматом LIB2_ABN_GET

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  IF(I$QTY IS NULL) THEN I$QTY = 1;
  IF(I$DATE_TO IS NULL) THEN I$DATE_TO = DATEADD(1 MONTH TO CURRENT_DATE);
  IF(I$QTY <= 0) THEN EXCEPTION DATA_ERROR 'Количество экземпляров должно быть положительным';
  IF(I$INSTANCE_ID IS NOT NULL AND I$QTY <> 1) THEN EXCEPTION DATA_ERROR 'Количество может быть только 1';
  IF(I$DATE_TO < CURRENT_DATE OR I$DATE_TO > DATEADD(1 YEAR TO CURRENT_DATE)) THEN EXCEPTION DATA_ERROR 'Плановая дата возврата не может быть в прошлом или более 1 года от текущей даты';

  -- В момент добавления - определяем площадку
  I$IP = REPLACE(TRIM(REPLACE(REPLACE(I$IP, '[', ''), ']', '')), ' ', '/');
  WHILE(POSITION('/' IN I$IP) > 0) DO I$IP = SUBSTRING(I$IP FROM POSITION('/' IN I$IP) + 1);
  I$IP = TRIM(I$IP);

  FOR
    SELECT V3600.VAL, V3599.VAL
    FROM LINKS L2
    JOIN LINKS L536 ON L536.PARENT_ID = L2.OBJ_ID AND L536.OBJ_TYPE_ID = 536 AND L536.DATE_DEL IS NULL
    JOIN VALI V3600 ON V3600.OBJ_ID = L536.OBJ_ID AND V3600.PARAM_ID = 3600 AND V3600.IS_DEL = 0
    JOIN VALS V3599 ON V3599.OBJ_ID = L536.OBJ_ID AND V3599.PARAM_ID = 3599 AND V3599.IS_DEL = 0
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    ORDER BY 1
    INTO :N, :S
  DO
  BEGIN
    S = S || ',';
    IF(POSITION((I$IP || ',') IN S) > 0) THEN V$LOC = N;
  END

  IF(V$LOC IS NULL) THEN EXCEPTION DATA_ERROR 'Невозможно определить площадку библиотеки по IP адресу';

  -- Нельзя выдавать не-действующей персоне или невалидному классу
  SELECT FIRST 1 LP.PARENT_ID, LP.PARENT_TYPE_ID, LP.OBJ_TYPE_ID
  FROM LINKS LP
  WHERE LP.OBJ_ID = :I$PERSON_ID AND LP.PARENT_TYPE_ID IN (2, 211, 9, 187, 8) AND LP.DATE_DEL IS NULL
  INTO :V$PARENT_ID, :V$PARENT_TYPE_ID, :V$REF_TYPE_ID;

  IF(V$PARENT_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Или персона не найдена / не является действующим сотрудником или обучающимся, или задан несуществующий класс.';

  -- Есть ли достаточное число экземпляров
  SELECT B.N_AVAIL, B.N_FREE, I.IS_FREE, I.INV_CODE, B.BOOK_NAME, B.PUB_YEAR, B.AUTHOR_ID, B.OBJ_TYPE, I.LOC_INDEX
  FROM LIB2_BOOKS B
  LEFT JOIN LIB2_INSTANCES I ON I.DATE_DEL IS NULL AND I.BOOK_ID = B.OBJ_ID AND I.OBJ_ID = :I$INSTANCE_ID
  WHERE B.DATE_DEL IS NULL AND B.OBJ_ID = :I$BOOK_ID
  INTO :V$AVAIL, :V$FREE, :V$INST_FREE, :V$INV_CODE, :V$BOOK_NAME, :V$PUB_YEAR, :V$AUTHOR_ID, :V$OBJ_TYPE, :V$LOC_INDEX;

  IF(V$AVAIL IS NULL) THEN EXCEPTION DATA_ERROR 'Издание не найдено или было удалено';
  IF(I$INSTANCE_ID IS NOT NULL AND V$INST_FREE IS NULL) THEN EXCEPTION DATA_ERROR 'Экземпляр издания не найден или был удален';
  IF(V$AVAIL < I$QTY OR V$FREE < I$QTY) THEN EXCEPTION DATA_ERROR 'Нет достаточного количества экземпляров издания, доступно ' || V$FREE;

  IF(V$LOC_INDEX IS NOT NULL AND V$LOC_INDEX <> V$LOC) THEN EXCEPTION DATA_ERROR 'Издание приписано к другой площадке, выдача невозможна';

  -- Для учебников надо проверить что количество есть на данной площадке
  -- !!!
  IF(V$LOC_INDEX IS NULL) THEN
  BEGIN
  END

  -- Нельзя выдавать ту же книгу той же персоне повторно
  IF(EXISTS(
    SELECT FIRST 1 1
    FROM LIB2_USAGE U
    WHERE U.DATE_DEL IS NULL AND U.REF_ID = :I$PERSON_ID AND U.BOOK_ID = :I$BOOK_ID AND U.RETURN_DATE IS NULL AND U.LOSS_DATE IS NULL
  ))
  THEN
    EXCEPTION DATA_ERROR 'Данное издание уже выдано данному человеку, повторно выдать нельзя';

  -- Выдан кому-то другому ?
  IF(I$INSTANCE_ID IS NOT NULL AND V$INST_FREE = 0) THEN EXCEPTION DATA_ERROR 'Экземпляр издания уже выдан на руки';

  -- Добавлять или изменять можно только библиотекарю или админу
  IF(I$USER_ID <> 1 AND NOT EXISTS(
    -- Роль = библиотекарь
    SELECT FIRST 1 1
    FROM USERS U
    WHERE U.USER_ID = :I$USER_ID AND U.DATE_DEL IS NULL AND U.USER_TYPE = 11
  )
  AND NOT EXISTS(
    -- Должность = библиотекарь
    SELECT FIRST 1 1
    FROM USERS U
    JOIN LINKS L15 ON L15.PARENT_ID = U.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
    JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
    LEFT JOIN VALS V3543 ON V3543.OBJ_ID = L15.OBJ_ID AND V3543.PARAM_ID = 3543 AND V3543.IS_DEL = 0
    LEFT JOIN VALS V589 ON V589.OBJ_ID = L15.OBJ_ID AND V589.PARAM_ID = 589 AND V589.IS_DEL = 0
    WHERE U.USER_ID = :I$USER_ID AND U.DATE_DEL IS NULL AND V74.VAL IS NULL
      AND (UPPER(V3543.SVAL) LIKE '%БИБЛИОТ%' OR UPPER(V589.SVAL) LIKE '%БИБЛИОТ%')
  ))
  THEN
    EXCEPTION DATA_ERROR 'Только библиотекарь может выдавать литературу';

  -- Регистрируем выдачу
  INSERT INTO LIB2_USAGE
  (REF_ID, REF_TYPE_ID, BOOK_ID, INSTANCE_ID, QUANTITY, ACTION_DATE, PLAN_DATE, LOC_INDEX, USER_ID)
  VALUES (:I$PERSON_ID, :V$REF_TYPE_ID, :I$BOOK_ID, :I$INSTANCE_ID, :I$QTY, CURRENT_DATE, :I$DATE_TO, :V$LOC, :I$USER_ID)
  RETURNING OBJ_ID INTO :V$USAGE_ID;

  -- Корректируем количество
  UPDATE LIB2_BOOKS
  SET N_FREE = N_FREE - :I$QTY
  WHERE OBJ_ID = :I$BOOK_ID;

  -- Фиксируем недоступность экземпляра
  IF(I$INSTANCE_ID IS NOT NULL) THEN
  UPDATE LIB2_INSTANCES
  SET IS_FREE = 0
  WHERE OBJ_ID = :I$INSTANCE_ID;

  TAG_NAME = 'id';
  VAL = V$USAGE_ID;
  SUSPEND;
  TAG_NAME = 'book_id';
  VAL = I$BOOK_ID;
  SUSPEND;
  TAG_NAME = 'inst_id';
  VAL = I$INSTANCE_ID;
  SUSPEND;
  TAG_NAME = 'obj_type_id';
  VAL = V$OBJ_TYPE;
  SUSPEND;
  TAG_NAME = 'obj_type';
  VAL = (SELECT VAL FROM LISTVAL_TEXT(:V$OBJ_TYPE));
  SUSPEND;
  TAG_NAME = 'quantity';
  VAL = I$QTY;
  SUSPEND;
  TAG_NAME = 'action_date';
  VAL = (SELECT VAL FROM DATE2ISO(CURRENT_DATE, 0));
  SUSPEND;
  TAG_NAME = 'plan_date';
  VAL = (SELECT VAL FROM DATE2ISO(:I$DATE_TO, 0));
  SUSPEND;
  TAG_NAME = 'return_date';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'loss_date';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'name';
  VAL = V$BOOK_NAME;
  SUSPEND;
  TAG_NAME = 'author';
  VAL = NULL;
  SELECT V.VAL
  FROM LIB2_LISTVALS V
  WHERE V.LISTVAL_ID = :V$AUTHOR_ID
  INTO :VAL;
  SUSPEND;
  TAG_NAME = 'pub_year';
  VAL = V$PUB_YEAR;
  SUSPEND;
  TAG_NAME = 'inv_code';
  VAL = V$INV_CODE;
  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIB2_BOOK_HISTORY (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$DIR SMALLINT;
DECLARE VARIABLE V$ACTION_DATE DATE;
DECLARE VARIABLE V$ACTION_NUM VARCHAR(100);
DECLARE VARIABLE V$DOCUMENT_DATE DATE;
DECLARE VARIABLE V$DOCUMENT_NUM VARCHAR(100);
DECLARE VARIABLE V$QTY INTEGER;
DECLARE VARIABLE V$REF_ID BIGINT;
DECLARE VARIABLE V$REF_TYPE BIGINT;
DECLARE VARIABLE V$PLAN_DATE DATE;
DECLARE VARIABLE S VARCHAR(1000);
DECLARE VARIABLE S2 VARCHAR(100);
DECLARE VARIABLE V$LOC SMALLINT;
DECLARE VARIABLE V$TYPE SMALLINT;
DECLARE VARIABLE V$DEST SMALLINT;
DECLARE VARIABLE V$STATE VARCHAR(100);
begin
  TAG_NAME = 'instances::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT I.INV_CODE, I.IS_FREE, LV.VAL, I.OBJ_ID, I.LOC_INDEX
    FROM LIB2_INSTANCES I
    LEFT JOIN LISTVAL_TEXT(I.STATE_ID) LV ON 1 = 1
    WHERE I.DATE_DEL IS NULL AND I.BOOK_ID = :I$OBJ_ID
    INTO :S, :V$DIR, :V$STATE, :V$OBJ_ID, :V$LOC
  DO
  BEGIN
    TAG_NAME = 'instances:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'instances:r:inv_code';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'instances:r:condition';
    VAL = V$STATE;
    SUSPEND;
    TAG_NAME = 'instances:r:is_free';
    VAL = V$DIR;
    SUSPEND;
    TAG_NAME = 'instances:r:location';
    VAL = V$LOC;
    SUSPEND;

    TAG_NAME = 'instances:r:place';
    IF (V$DIR = 1) THEN
    BEGIN
      VAL = 'В фонде';
    END
    ELSE
    BEGIN
      V$REF_ID = NULL;
      V$ACTION_DATE = NULL;
      SELECT FIRST 1 U.REF_ID, U.ACTION_DATE
      FROM LIB2_USAGE U
      WHERE U.DATE_DEL IS NULL AND U.INSTANCE_ID = :V$OBJ_ID AND U.RETURN_DATE IS NULL AND U.LOSS_DATE IS NULL
      INTO :V$REF_ID, :V$ACTION_DATE;

      IF(V$REF_ID IS NULL) THEN VAL = 'На руках ???';
      ELSE
      BEGIN
        SELECT RESULT FROM DATE2STR(:V$ACTION_DATE) INTO :VAL;
        SELECT SCAPTION FROM OBJECT_CAPTION_GET(:V$REF_ID) INTO :S;
        VAL = S || ', выдано ' || VAL;
      END
    END
    SUSPEND;
  END

  TAG_NAME = 'invoices::json&colon;array';
  VAL = 1;
  SUSPEND;
  -- Индивидуальные и пакетные списания никогда не пересекаются
  -- Поступления и списания, индивидуальные
  FOR
    SELECT V.OBJ_ID, 0, V.ACTION_DATE, V.LOC_INDEX, V.ACTION_NUM, V.DOCUMENT_DATE, V.DOCUMENT_NUM, C.VAL, V.DEST_INDEX, V.TYPE_ID, COUNT(*)
    FROM LIB2_INSTANCES I
    JOIN LIB2_INVOICES V ON V.OBJ_ID = I.INVOICE_IN_ID AND V.DATE_DEL IS NULL
    LEFT JOIN LIB2_LISTVALS C ON C.LISTVAL_ID = V.CONTRAGENT_ID
    WHERE I.DATE_DEL IS NULL AND I.BOOK_ID = :I$OBJ_ID AND (V.TYPE_ID <> 100 OR V.USER_ACCEPTED IS NOT NULL)
    GROUP BY 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
    UNION
    SELECT V.OBJ_ID, 1, V.ACTION_DATE, V.LOC_INDEX, V.ACTION_NUM, V.DOCUMENT_DATE, V.DOCUMENT_NUM, C.VAL, V.DEST_INDEX, V.TYPE_ID, COUNT(*)
    FROM LIB2_INSTANCES I
    JOIN LIB2_INVOICES V ON V.OBJ_ID = I.INVOICE_OUT_ID AND V.DATE_DEL IS NULL
    LEFT JOIN LIB2_LISTVALS C ON C.LISTVAL_ID = V.CONTRAGENT_ID
    WHERE I.DATE_DEL IS NULL AND I.BOOK_ID = :I$OBJ_ID AND (V.TYPE_ID <> 100 OR V.USER_ACCEPTED IS NOT NULL)
    GROUP BY 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
    ORDER BY 3, 2 DESC
    INTO :V$OBJ_ID, :V$DIR, :V$ACTION_DATE, :V$LOC, :V$ACTION_NUM, :V$DOCUMENT_DATE, :V$DOCUMENT_NUM, :S, :V$DEST, :V$TYPE, :V$QTY
  DO
  BEGIN
    TAG_NAME = 'invoices:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'invoices:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'invoices:r:location';
    VAL = V$LOC;
    SUSPEND;
    TAG_NAME = 'invoices:r:action_date';
    VAL = (SELECT VAL FROM DATE2ISO(:V$ACTION_DATE, 0));
    SUSPEND;
    TAG_NAME = 'invoices:r:action_num';
    VAL = V$ACTION_NUM;
    SUSPEND;
    TAG_NAME = 'invoices:r:document_date';
    VAL = (SELECT VAL FROM DATE2ISO(:V$DOCUMENT_DATE, 0));
    SUSPEND;
    TAG_NAME = 'invoices:r:document_num';
    VAL = V$DOCUMENT_NUM;
    SUSPEND;
    TAG_NAME = 'invoices:r:org_name';
    VAL = IIF(V$TYPE = 100, IIF(V$DIR = 0, 'Прием ', 'Выбытие ') || COALESCE(V$LOC, '') || '->' || COALESCE(V$DEST, ''), S);
    SUSPEND;
    TAG_NAME = 'invoices:r:quantity';
    IF(V$DIR = 0) THEN VAL = V$QTY; ELSE VAL = - V$QTY;
    SUSPEND;
  END
  -- Поступления и списания, пакетные
  FOR
    SELECT V.OBJ_ID, 0, V.ACTION_DATE, V.LOC_INDEX, V.ACTION_NUM, V.DOCUMENT_DATE, V.DOCUMENT_NUM, C.VAL, V.DEST_INDEX, V.TYPE_ID, B.QUANTITY
    FROM LIB2_BATCHES B
    JOIN LIB2_INVOICES V ON V.OBJ_ID = B.INVOICE_IN_ID AND V.DATE_DEL IS NULL
    LEFT JOIN LIB2_LISTVALS C ON C.LISTVAL_ID = V.CONTRAGENT_ID
    WHERE B.DATE_DEL IS NULL AND B.BOOK_ID = :I$OBJ_ID AND (V.TYPE_ID <> 100 OR V.USER_ACCEPTED IS NOT NULL)
    UNION
    SELECT V.OBJ_ID, 1, V.ACTION_DATE, V.LOC_INDEX, V.ACTION_NUM, V.DOCUMENT_DATE, V.DOCUMENT_NUM, C.VAL, V.DEST_INDEX, V.TYPE_ID, B.QUANTITY
    FROM LIB2_BATCHES B
    JOIN LIB2_INVOICES V ON V.OBJ_ID = B.INVOICE_OUT_ID AND V.DATE_DEL IS NULL
    LEFT JOIN LIB2_LISTVALS C ON C.LISTVAL_ID = V.CONTRAGENT_ID
    WHERE B.DATE_DEL IS NULL AND B.BOOK_ID = :I$OBJ_ID AND (V.TYPE_ID <> 100 OR V.USER_ACCEPTED IS NOT NULL)
    ORDER BY 3, 2 DESC
    INTO :V$OBJ_ID, :V$DIR, :V$ACTION_DATE, :V$LOC, :V$ACTION_NUM, :V$DOCUMENT_DATE, :V$DOCUMENT_NUM, :S, :V$DEST, :V$TYPE, :V$QTY
  DO
  BEGIN
    TAG_NAME = 'invoices:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'invoices:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'invoices:r:location';
    VAL = V$LOC;
    SUSPEND;
    TAG_NAME = 'invoices:r:action_date';
    VAL = (SELECT VAL FROM DATE2ISO(:V$ACTION_DATE, 0));
    SUSPEND;
    TAG_NAME = 'invoices:r:action_num';
    VAL = V$ACTION_NUM;
    SUSPEND;
    TAG_NAME = 'invoices:r:document_date';
    VAL = (SELECT VAL FROM DATE2ISO(:V$DOCUMENT_DATE, 0));
    SUSPEND;
    TAG_NAME = 'invoices:r:document_num';
    VAL = V$DOCUMENT_NUM;
    SUSPEND;
    TAG_NAME = 'invoices:r:org_name';
    VAL = IIF(V$TYPE = 100, IIF(V$DIR = 0, 'Прием ', 'Выбытие ') || COALESCE(V$LOC, '') || '->' || COALESCE(V$DEST, ''), S);
    SUSPEND;
    TAG_NAME = 'invoices:r:quantity';
    IF(V$DIR = 0) THEN VAL = V$QTY; ELSE VAL = - V$QTY;
    SUSPEND;
  END

  TAG_NAME = 'movements::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT U.OBJ_ID, U.ACTION_DATE, U.PLAN_DATE, IIF(U.LOSS_DATE IS NULL, 0, 1), COALESCE(U.RETURN_DATE, U.LOSS_DATE), C.C1, U.REF_TYPE_ID, U.REF_ID, U.QUANTITY, I.INV_CODE, U.LOC_INDEX
    FROM LIB2_USAGE U
    LEFT JOIN BUILD_REP_FIO(U.REF_ID, IIF(U.REF_TYPE_ID = 10, 55, 59), IIF(U.REF_TYPE_ID = 10, 56, 60), IIF(U.REF_TYPE_ID = 10, 57, 61), 1) C ON 1 = 1
    LEFT JOIN LIB2_INSTANCES I ON I.OBJ_ID = U.INSTANCE_ID AND I.DATE_DEL IS NULL AND U.INSTANCE_ID IS NOT NULL
    WHERE U.DATE_DEL IS NULL AND U.BOOK_ID = :I$OBJ_ID AND DATEDIFF(YEAR, U.ACTION_DATE, CURRENT_DATE) <= 2 --ограничиваем просмотр истории 2-мя годами
    ORDER BY 5 ASC, 2 DESC
    INTO :V$OBJ_ID, :V$ACTION_DATE, :V$PLAN_DATE, :V$DIR, :V$DOCUMENT_DATE, :S, :V$REF_TYPE, :V$REF_ID, :V$QTY, :S2, :V$LOC
  DO
  BEGIN
    TAG_NAME = 'movements:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'movements:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'movements:r:location';
    VAL = V$LOC;
    SUSPEND;
    TAG_NAME = 'movements:r:inv_code';
    VAL = S2;
    SUSPEND;
    TAG_NAME = 'movements:r:quantity';
    VAL = V$QTY;
    SUSPEND;
    TAG_NAME = 'movements:r:loss';
    VAL = V$DIR;
    SUSPEND;
    TAG_NAME = 'movements:r:action_date';
    VAL = (SELECT VAL FROM DATE2ISO(:V$ACTION_DATE, 0));
    SUSPEND;
    TAG_NAME = 'movements:r:plan_date';
    VAL = (SELECT VAL FROM DATE2ISO(:V$PLAN_DATE, 0));
    SUSPEND;
    TAG_NAME = 'movements:r:return_date';
    VAL = (SELECT VAL FROM DATE2ISO(:V$DOCUMENT_DATE, 0));
    SUSPEND;
    TAG_NAME = 'movements:r:name';
    IF(V$REF_TYPE = 9) THEN VAL = 'Пакетная выдача, #экз: ' || V$QTY;
    ELSE VAL = S;
    SUSPEND;
    TAG_NAME = 'movements:r:group_name';
    VAL = NULL;
    IF(V$REF_TYPE = 14) THEN
      VAL = 'Сотрудники';
    ELSE IF(V$REF_TYPE = 10) THEN
      -- Учащиеся
      SELECT FIRST 1 M.NAME_IN
      FROM PERSON_MOVEMENTS M
      WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :V$REF_ID AND M.GROUP_TYPE_ID IN (9, 187) AND M.DATE_DEL IS NULL AND M.DATE_IN <= :V$ACTION_DATE AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :V$ACTION_DATE)
      INTO :VAL;
    ELSE IF(V$REF_TYPE = 9) THEN
      -- Пакетная выдача на класс, но брать название надо на дату
      SELECT FIRST 1 M.NAME_IN
      FROM PERSON_MOVEMENTS M
      WHERE M.DATE_DEL IS NULL AND M.GROUP_ID = :V$REF_ID AND M.DATE_IN <= :V$ACTION_DATE AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :V$ACTION_DATE)
      ORDER BY M.DATE_IN DESC
      INTO :VAL;
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIB2_BOOK_RETURN (
    I$PERSON_ID BIGINT,
    I$USE_ID BIGINT,
    I$LOST SMALLINT NOT NULL,
    I$IP VARCHAR(400),
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$OBJ_TYPE BIGINT;
DECLARE VARIABLE V$BOOK_ID BIGINT;
DECLARE VARIABLE V$INSTANCE_ID BIGINT;
DECLARE VARIABLE V$ACTION_DATE DATE;
DECLARE VARIABLE V$FREE SMALLINT;
DECLARE VARIABLE V$PLAN_DATE DATE;
DECLARE VARIABLE V$RETURN_DATE DATE;
DECLARE VARIABLE V$LOSS_DATE DATE;
DECLARE VARIABLE V$QTY INTEGER;
DECLARE VARIABLE V$BOOK_NAME VARCHAR(400);
DECLARE VARIABLE V$AUTHOR_ID BIGINT;
DECLARE VARIABLE V$PUB_YEAR INTEGER;
DECLARE VARIABLE V$INV_CODE VARCHAR(100);
DECLARE VARIABLE V$CU BIGINT;
DECLARE VARIABLE V$REF_TYPE_ID BIGINT;
DECLARE VARIABLE N INTEGER;
DECLARE VARIABLE S VARCHAR(4000);
DECLARE VARIABLE V$LOC INTEGER;
DECLARE VARIABLE V$LOC_INDEX INTEGER;
begin

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  -- В момент добавления - определяем площадку
  I$IP = REPLACE(TRIM(REPLACE(REPLACE(I$IP, '[', ''), ']', '')), ' ', '/');
  WHILE(POSITION('/' IN I$IP) > 0) DO I$IP = SUBSTRING(I$IP FROM POSITION('/' IN I$IP) + 1);
  I$IP = TRIM(I$IP);

  FOR
    SELECT V3600.VAL, V3599.VAL
    FROM LINKS L2
    JOIN LINKS L536 ON L536.PARENT_ID = L2.OBJ_ID AND L536.OBJ_TYPE_ID = 536 AND L536.DATE_DEL IS NULL
    JOIN VALI V3600 ON V3600.OBJ_ID = L536.OBJ_ID AND V3600.PARAM_ID = 3600 AND V3600.IS_DEL = 0
    JOIN VALS V3599 ON V3599.OBJ_ID = L536.OBJ_ID AND V3599.PARAM_ID = 3599 AND V3599.IS_DEL = 0
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    ORDER BY 1
    INTO :N, :S
  DO
  BEGIN
    S = S || ',';
    IF(POSITION((I$IP || ',') IN S) > 0) THEN V$LOC = N;
  END

  IF(V$LOC IS NULL) THEN EXCEPTION DATA_ERROR 'Невозможно определить площадку библиотеки по IP адресу';

  -- Добавлять или изменять можно только библиотекарю или админу
  IF(I$USER_ID <> 1 AND NOT EXISTS(
    -- Роль = библиотекарь
    SELECT FIRST 1 1
    FROM USERS U
    WHERE U.USER_ID = :I$USER_ID AND U.DATE_DEL IS NULL AND U.USER_TYPE = 11
  )
  AND NOT EXISTS(
    -- Должность = библиотекарь
    SELECT FIRST 1 1
    FROM USERS U
    JOIN LINKS L15 ON L15.PARENT_ID = U.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
    JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
    LEFT JOIN VALS V3543 ON V3543.OBJ_ID = L15.OBJ_ID AND V3543.PARAM_ID = 3543 AND V3543.IS_DEL = 0
    LEFT JOIN VALS V589 ON V589.OBJ_ID = L15.OBJ_ID AND V589.PARAM_ID = 589 AND V589.IS_DEL = 0
    WHERE U.USER_ID = :I$USER_ID AND U.DATE_DEL IS NULL AND V74.VAL IS NULL
      AND (UPPER(V3543.SVAL) LIKE '%БИБЛИОТ%' OR UPPER(V589.SVAL) LIKE '%БИБЛИОТ%')
  ))
  THEN
    EXCEPTION DATA_ERROR 'Только библиотекарь может выдавать литературу';

  SELECT U.BOOK_ID, U.INSTANCE_ID, U.ACTION_DATE, U.PLAN_DATE, U.RETURN_DATE, U.LOSS_DATE, B.OBJ_TYPE, U.QUANTITY, B.BOOK_NAME, B.AUTHOR_ID, B.PUB_YEAR, U.CLASS_USAGE_ID, U.REF_TYPE_ID, U.LOC_INDEX
  FROM LIB2_USAGE U
  JOIN LIB2_BOOKS B ON B.OBJ_ID = U.BOOK_ID
  WHERE U.DATE_DEL IS NULL AND U.OBJ_ID = :I$USE_ID AND U.REF_ID = :I$PERSON_ID
  INTO :V$BOOK_ID, :V$INSTANCE_ID, :V$ACTION_DATE, :V$PLAN_DATE, :V$RETURN_DATE, :V$LOSS_DATE, :V$OBJ_TYPE, :V$QTY, :V$BOOK_NAME, :V$AUTHOR_ID, :V$PUB_YEAR, :V$CU, :V$REF_TYPE_ID, :V$LOC_INDEX;

  IF(V$BOOK_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Запись выдачи не найдена';
  IF(V$RETURN_DATE IS NOT NULL OR V$LOSS_DATE IS NOT NULL) THEN EXCEPTION DATA_ERROR 'Издание уже отмечено как возвращенное';
  IF(V$ACTION_DATE > CURRENT_DATE) THEN EXCEPTION DATA_ERROR 'Дата возврата не может быть раньше даты выдачи';
  IF(V$LOC_INDEX <> V$LOC) THEN EXCEPTION DATA_ERROR 'Издание должно возвращаться на ту же площадку, откуда выдавалось';

  IF(V$INSTANCE_ID IS NULL) THEN
  BEGIN
    -- Учебник
    -- Тут нет дополнительных проверок
  END
  ELSE
  BEGIN
    -- Книга
    IF(V$QTY <> 1) THEN EXCEPTION DATA_ERROR 'Количество для книг должно быть равно 1';

    SELECT I.INV_CODE, I.IS_FREE
    FROM LIB2_INSTANCES I
    WHERE I.OBJ_ID = :V$INSTANCE_ID
    INTO :V$INV_CODE, :V$FREE;

    IF(V$INV_CODE IS NULL) THEN EXCEPTION DATA_ERROR 'Инвентарный номер экземпляра не найден';
    IF(V$FREE <> 0) THEN EXCEPTION DATA_ERROR 'Экземпляр уже числится как возвращенный';

    -- Отмечаем экземпляр как свободный, если это не утрата
    IF(I$LOST = 0) THEN
    UPDATE LIB2_INSTANCES
    SET IS_FREE = 1
    WHERE OBJ_ID = :V$INSTANCE_ID;
  END

  -- Корректируем количество
  -- Но если это распределение пакета ученикам класса - количество не трогаем
  IF(V$CU IS NULL AND I$LOST = 0) THEN
  BEGIN
    UPDATE LIB2_BOOKS
    SET N_FREE = N_FREE + :V$QTY
    WHERE OBJ_ID = :V$BOOK_ID;
  END
  -- В случае утраты (неважно, пакетно или нет) - уменьшаем количество доступных
  IF(I$LOST = 1) THEN
  BEGIN
    UPDATE LIB2_BOOKS
    SET N_AVAIL = N_AVAIL - :V$QTY
    WHERE OBJ_ID = :V$BOOK_ID;
  END

  -- Закрываем запись
  IF(I$LOST = 0) THEN
    UPDATE LIB2_USAGE
    SET RETURN_DATE = CURRENT_DATE, RET_USER_ID = :I$USER_ID
    WHERE OBJ_ID = :I$USE_ID;
  ELSE
    UPDATE LIB2_USAGE
    SET LOSS_DATE = CURRENT_DATE, RET_USER_ID = :I$USER_ID
    WHERE OBJ_ID = :I$USE_ID;

  -- Закрываем открытое распределение ученикам
  -- потери тут быть не может
  IF(V$REF_TYPE_ID IN (9, 187)) THEN
  BEGIN
    UPDATE LIB2_USAGE
    SET RETURN_DATE = CURRENT_DATE, RET_USER_ID = :I$USER_ID
    WHERE DATE_DEL IS NULL AND CLASS_USAGE_ID = :I$USE_ID AND RETURN_DATE IS NULL AND LOSS_DATE IS NULL;
  END

  TAG_NAME = 'id';
  VAL = I$USE_ID;
  SUSPEND;
  TAG_NAME = 'book_id';
  VAL = V$BOOK_ID;
  SUSPEND;
  TAG_NAME = 'inst_id';
  VAL = V$INSTANCE_ID;
  SUSPEND;
  TAG_NAME = 'obj_type_id';
  VAL = V$OBJ_TYPE;
  SUSPEND;
  TAG_NAME = 'obj_type';
  VAL = (SELECT VAL FROM LISTVAL_TEXT(:V$OBJ_TYPE));
  SUSPEND;
  TAG_NAME = 'quantity';
  VAL = V$QTY;
  SUSPEND;
  TAG_NAME = 'action_date';
  VAL = (SELECT VAL FROM DATE2ISO(:V$ACTION_DATE, 0));
  SUSPEND;
  TAG_NAME = 'plan_date';
  VAL = (SELECT VAL FROM DATE2ISO(:V$PLAN_DATE, 0));
  SUSPEND;
  TAG_NAME = 'return_date';
  IF(I$LOST = 0) THEN VAL = (SELECT VAL FROM DATE2ISO(CURRENT_DATE, 0)); ELSE VAL = NULL;
  SUSPEND;
  TAG_NAME = 'loss_date';
  IF(I$LOST = 1) THEN VAL = (SELECT VAL FROM DATE2ISO(CURRENT_DATE, 0)); ELSE VAL = NULL;
  SUSPEND;
  TAG_NAME = 'name';
  VAL = V$BOOK_NAME;
  SUSPEND;
  TAG_NAME = 'author';
  VAL = NULL;
  SELECT V.VAL
  FROM LIB2_LISTVALS V
  WHERE V.LISTVAL_ID = :V$AUTHOR_ID
  INTO :VAL;
  SUSPEND;
  TAG_NAME = 'pub_year';
  VAL = V$PUB_YEAR;
  SUSPEND;
  TAG_NAME = 'inv_code';
  VAL = V$INV_CODE;
  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIB2_BOOK_RETURN_ALL (
    I$REF_ID BIGINT,
    I$IP VARCHAR(400),
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$USAGE_ID BIGINT;
DECLARE VARIABLE V$TYPE_ID BIGINT;
begin

  -- Тут есть два варианта вызова - для ученика/сотрудника и для учебного коллектива
  SELECT TYPE_ID
  FROM OBJECTS
  WHERE OBJ_ID = :I$REF_ID
  INTO :V$TYPE_ID;

  TAG_NAME = 'items::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT U.OBJ_ID
    FROM LIB2_USAGE U
    WHERE U.DATE_DEL IS NULL AND U.REF_ID = :I$REF_ID AND U.REF_TYPE_ID IN (10, 14, 9, 187) AND U.RETURN_DATE IS NULL AND U.LOSS_DATE IS NULL
    ORDER BY 1
    INTO :V$USAGE_ID
  DO
  BEGIN
    TAG_NAME = 'items:r';
    VAL = NULL;
    SUSPEND;
    FOR
      SELECT TAG_NAME, VAL
      FROM LIB2_BOOK_RETURN(:I$REF_ID, :V$USAGE_ID, 0, :I$IP, :I$USER_ID)
      INTO :TAG_NAME, :VAL
    DO
    BEGIN
      TAG_NAME = 'items:r:' || TAG_NAME;
      SUSPEND;
    END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIB2_BOOK_SET (
    I$OBJ_TYPE SMALLINT,
    I$OBJ_ID BIGINT,
    I$AUTHOR_ID BIGINT,
    I$PUBLISHER_ID BIGINT,
    I$CODE_ISBN VARCHAR(30),
    I$BOOK_NAME VARCHAR(400),
    I$PUB_YEAR INTEGER,
    I$AUTHORS VARCHAR(400),
    I$PART_NUM SMALLINT,
    I$PART_NAME VARCHAR(200),
    I$LANG_ID BIGINT,
    I$BOOK_SIZE VARCHAR(20),
    I$AGE_GROUP VARCHAR(20),
    I$SUBJECT_ID BIGINT,
    I$SUBJECT_ID2 BIGINT,
    I$SUBJECT_ID3 BIGINT,
    I$PUB_PLACE_ID BIGINT,
    I$AUTHOR_SIGN VARCHAR(10),
    I$UDK VARCHAR(100),
    I$EDITION_TEXT VARCHAR(200),
    I$PURPOSE_ID BIGINT,
    I$BBK VARCHAR(100),
    I$USER_ID VARCHAR(40))
RETURNS (
    OBJ_ID BIGINT)
AS
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$CODE VARCHAR(40);
DECLARE VARIABLE V$FPU_ID BIGINT;
begin

  IF(I$OBJ_TYPE IS NULL) THEN EXCEPTION DATA_ERROR 'Не указан системный тип издания';
  IF(I$AUTHOR_ID IS NULL AND I$AUTHORS IS NULL) THEN EXCEPTION DATA_ERROR 'Не указан автор или коллективный автор';
  IF(I$PUBLISHER_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не указано издательство';

  I$BOOK_NAME = TRIM(I$BOOK_NAME);
  IF(I$BOOK_NAME IS NULL OR CHAR_LENGTH(I$BOOK_NAME) < 1) THEN EXCEPTION DATA_ERROR 'Не указано название';

  SELECT FIRST 1 B.OBJ_ID, B.FPU_CODE, B.FPU_ID
  FROM LIB2_BOOKS B
  WHERE B.OBJ_ID = :I$OBJ_ID AND B.DATE_DEL IS NULL
  INTO :V$OBJ_ID, :V$CODE, :V$FPU_ID;

  IF(I$OBJ_ID IS NOT NULL AND V$OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Издание не найдено или было удалено';
  IF(I$PART_NUM <= 0) THEN EXCEPTION DATA_ERROR 'Номер части должен быть положительным числом';

  IF(I$OBJ_TYPE = 18712 AND EXISTS(
    SELECT FIRST 1 1
    FROM LIB2_BOOKS B
    WHERE B.DATE_DEL IS NULL AND B.OBJ_ID <> :I$OBJ_ID
      AND B.FPU_ID = (SELECT FIRST 1 BB.FPU_ID FROM LIB2_BOOKS BB WHERE BB.OBJ_ID = :I$OBJ_ID AND BB.DATE_DEL IS NULL)
      AND ((:I$PART_NUM IS NULL AND B.PART_NUM IS NULL) OR B.PART_NUM = :I$PART_NUM)
      AND ((:I$PUB_YEAR IS NULL AND B.PUB_YEAR IS NULL) OR B.PUB_YEAR = :I$PUB_YEAR)
  ))
  THEN
    EXCEPTION DATA_ERROR 'Учебник с таким кодом ФПУ, номером части и годом издания уже есть в системе';

  IF(I$OBJ_ID IS NULL) THEN
  BEGIN
    INSERT INTO LIB2_BOOKS
    (OBJ_TYPE, AUTHOR_ID, PUBLISHER_ID, CODE_ISBN, BOOK_NAME, PUB_YEAR, AUTHORS, PART_NUM, PART_NAME, LANG_ID, BOOK_SIZE, AGE_GROUP, SUBJECT_ID,
      SUBJECT_ID2, SUBJECT_ID3, PUB_PLACE_ID, AUTHOR_SIGN, UDK, EDITION_TEXT, PURPOSE_ID, BBK)
    VALUES (:I$OBJ_TYPE, :I$AUTHOR_ID, :I$PUBLISHER_ID, :I$CODE_ISBN, :I$BOOK_NAME, :I$PUB_YEAR, :I$AUTHORS, :I$PART_NUM, :I$PART_NAME, :I$LANG_ID, :I$BOOK_SIZE, :I$AGE_GROUP, :I$SUBJECT_ID,
      :I$SUBJECT_ID2, :I$SUBJECT_ID3, :I$PUB_PLACE_ID, :I$AUTHOR_SIGN, :I$UDK, :I$EDITION_TEXT, :I$PURPOSE_ID, :I$BBK)
    RETURNING OBJ_ID INTO :OBJ_ID;
  END
  ELSE
  BEGIN
    OBJ_ID = I$OBJ_ID;

    -- OBJ_TYPE не меняется никогда
    UPDATE LIB2_BOOKS
    SET
      AUTHOR_ID = :I$AUTHOR_ID,
      PUBLISHER_ID = :I$PUBLISHER_ID,
      CODE_ISBN = :I$CODE_ISBN,
      BOOK_NAME = :I$BOOK_NAME,
      PUB_YEAR = :I$PUB_YEAR,
      AUTHORS = :I$AUTHORS,
      PART_NUM = :I$PART_NUM,
      PART_NAME = :I$PART_NAME,
      LANG_ID = :I$LANG_ID,
      BOOK_SIZE = :I$BOOK_SIZE,
      AGE_GROUP = :I$AGE_GROUP,
      SUBJECT_ID = :I$SUBJECT_ID,
      SUBJECT_ID2 = :I$SUBJECT_ID2,
      SUBJECT_ID3 = :I$SUBJECT_ID3,
      PUB_PLACE_ID = :I$PUB_PLACE_ID,
      AUTHOR_SIGN = :I$AUTHOR_SIGN,
      UDK = :I$UDK,
      EDITION_TEXT = :I$EDITION_TEXT,
      PURPOSE_ID = :I$PURPOSE_ID,
      BBK = :I$BBK
    WHERE OBJ_ID = :I$OBJ_ID;

    -- Исправление потерянного кода
    IF(V$CODE IS NULL AND I$OBJ_TYPE = 18712) THEN
    BEGIN
      SELECT FIRST 1 F.BOOKCODE
      FROM LIB_FPU_CODES F
      WHERE F.DATE_DEL IS NULL AND F.BOOK_ID = :V$FPU_ID
      ORDER BY F.DATE_ADD DESC
      INTO :V$CODE;

      UPDATE LIB2_BOOKS
      SET FPU_CODE = :V$CODE
      WHERE OBJ_ID = :I$OBJ_ID;
    END
  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIB2_BOOK_SET_ATTR (
    I$BOOK_ID BIGINT,
    I$LIST_ID BIGINT,
    I$VALUE BIGINT)
AS
begin

  IF(I$VALUE IS NULL) THEN
  BEGIN
    UPDATE LIB2_BOOK_ATTRS
    SET DATE_DEL = CURRENT_TIMESTAMP
    WHERE BOOK_ID = :I$BOOK_ID AND LIST_ID = :I$LIST_ID AND DATE_DEL IS NULL;
  END
  ELSE
  BEGIN
    UPDATE OR INSERT INTO LIB2_BOOK_ATTRS
    (BOOK_ID, LIST_ID, DATE_DEL, LISTVAL_ID)
    VALUES (:I$BOOK_ID, :I$LIST_ID, NULL, :I$VALUE)
    MATCHING (BOOK_ID, LIST_ID);
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIB2_BOOK_UNDO (
    I$OBJ_ID BIGINT NOT NULL,
    I$USE_ID BIGINT NOT NULL,
    I$REASON SMALLINT NOT NULL,
    I$IP VARCHAR(400),
    I$USER_ID VARCHAR(40) NOT NULL)
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$REF_TYPE_ID BIGINT;
DECLARE VARIABLE V$ACTION_DATE DATE;
DECLARE VARIABLE V$RETURN_DATE DATE;
DECLARE VARIABLE V$LOSS_DATE DATE;
DECLARE VARIABLE V$BOOK_ID BIGINT;
DECLARE VARIABLE V$INSTANCE_ID BIGINT;
DECLARE VARIABLE Q INTEGER;
DECLARE VARIABLE V$CU BIGINT;
DECLARE VARIABLE N INTEGER;
DECLARE VARIABLE S VARCHAR(4000);
DECLARE VARIABLE V$LOC INTEGER;
DECLARE VARIABLE V$LOC_INDEX INTEGER;
DECLARE VARIABLE V$ROLE SMALLINT;
begin

  -- REASON: -1 = отмена выдачи, 0 = отмена возврата, 1 = отмена утраты

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;
  SELECT FIRST 1 U.USER_TYPE
  FROM USERS U
  WHERE U.USER_ID = :I$USER_ID
  INTO :V$ROLE;

  -- В момент добавления - определяем площадку
  I$IP = REPLACE(TRIM(REPLACE(REPLACE(I$IP, '[', ''), ']', '')), ' ', '/');
  WHILE(POSITION('/' IN I$IP) > 0) DO I$IP = SUBSTRING(I$IP FROM POSITION('/' IN I$IP) + 1);
  I$IP = TRIM(I$IP);

  FOR
    SELECT V3600.VAL, V3599.VAL
    FROM LINKS L2
    JOIN LINKS L536 ON L536.PARENT_ID = L2.OBJ_ID AND L536.OBJ_TYPE_ID = 536 AND L536.DATE_DEL IS NULL
    JOIN VALI V3600 ON V3600.OBJ_ID = L536.OBJ_ID AND V3600.PARAM_ID = 3600 AND V3600.IS_DEL = 0
    JOIN VALS V3599 ON V3599.OBJ_ID = L536.OBJ_ID AND V3599.PARAM_ID = 3599 AND V3599.IS_DEL = 0
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    ORDER BY 1
    INTO :N, :S
  DO
  BEGIN
    S = S || ',';
    IF(POSITION((I$IP || ',') IN S) > 0) THEN V$LOC = N;
  END

  SELECT FIRST 1 U.REF_TYPE_ID, U.ACTION_DATE, U.RETURN_DATE, U.LOSS_DATE, U.QUANTITY, U.BOOK_ID, U.INSTANCE_ID, U.CLASS_USAGE_ID, U.LOC_INDEX
  FROM LIB2_USAGE U
  WHERE U.OBJ_ID = :I$USE_ID AND U.REF_ID = :I$OBJ_ID AND U.DATE_DEL IS NULL
  INTO :V$REF_TYPE_ID, :V$ACTION_DATE, :V$RETURN_DATE, :V$LOSS_DATE, :Q, :V$BOOK_ID, :V$INSTANCE_ID, :V$CU, :V$LOC_INDEX;

  IF(V$REF_TYPE_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не найдена запись выдачи';
  IF(I$REASON < 0 AND (V$RETURN_DATE IS NOT NULL OR V$LOSS_DATE IS NOT NULL)) THEN EXCEPTION DATA_ERROR 'Нельзя отменить выдачу, если зафиксирован возврат или утрата';

  IF(V$ROLE NOT IN (1, 5, 6) AND (V$LOC IS NULL OR V$LOC <> V$LOC_INDEX)) THEN EXCEPTION DATA_ERROR 'Отменить операцию можно только на той же площадке, либо пользователю с административными правами';

  -- Пакетная выдача
  IF(V$REF_TYPE_ID IN (9, 187)) THEN
  BEGIN
    IF(EXISTS(
      SELECT FIRST 1 1
      FROM LIB2_USAGE U
      WHERE U.DATE_DEL IS NULL AND U.CLASS_USAGE_ID = :I$USE_ID
    ))
    THEN
      EXCEPTION DATA_ERROR 'Нельзя отменять операцию пакетной выдачи, если зафиксировано персональное движение литературы';
  END

  IF(I$REASON = 1) THEN
  BEGIN
    -- Отмена утраты - тут только персональная утрата
    IF(V$INSTANCE_ID IS NOT NULL) THEN
    UPDATE LIB2_INSTANCES
    SET IS_FREE = 0
    WHERE OBJ_ID = :V$INSTANCE_ID;

    UPDATE LIB2_USAGE
    SET LOSS_DATE = NULL
    WHERE OBJ_ID = :I$USE_ID;

    UPDATE LIB2_BOOKS
    SET N_AVAIL = N_AVAIL + :Q
    WHERE OBJ_ID = :V$BOOK_ID;

    -- Счетчик доступных менять не надо - в случае утраты оно уже учтено, и возврат все равно оставляет издание на руках
    -- а вот общий счетчик корректируем
    UPDATE LIB2_BOOKS
    SET N_AVAIL = N_AVAIL + :Q
    WHERE OBJ_ID = :V$BOOK_ID;
  END
  ELSE IF(I$REASON = 0) THEN
  BEGIN
    -- Отмена возврата
    IF(V$INSTANCE_ID IS NOT NULL) THEN
    UPDATE LIB2_INSTANCES
    SET IS_FREE = 0
    WHERE OBJ_ID = :V$INSTANCE_ID;

    UPDATE LIB2_USAGE
    SET RETURN_DATE = NULL
    WHERE OBJ_ID = :I$USE_ID;

    -- Счетчик при пакетной выдаче не меняем - он поменяется после пакетного возврата
    IF(V$CU IS NULL) THEN
    UPDATE LIB2_BOOKS
    SET N_FREE = N_FREE - :Q
    WHERE OBJ_ID = :V$BOOK_ID;
  END
  ELSE IF(I$REASON < 0) THEN
  BEGIN
    -- Отмена выдачи, выдачи внутри класса нет - это уже проверено
    UPDATE LIB2_USAGE
    SET DATE_DEL = CURRENT_TIMESTAMP
    WHERE OBJ_ID = :I$USE_ID;

    IF(V$INSTANCE_ID IS NOT NULL) THEN
    UPDATE LIB2_INSTANCES
    SET IS_FREE = 1
    WHERE OBJ_ID = :V$INSTANCE_ID;

    UPDATE LIB2_BOOKS
    SET N_FREE = N_FREE + :Q
    WHERE OBJ_ID = :V$BOOK_ID;
  END

  TAG_NAME = 'id';
  VAL = I$OBJ_ID;
  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIB2_DESCRIBE (
    I$USER_ID VARCHAR(40),
    I$APP VARCHAR(400),
    I$IP VARCHAR(400))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE N INTEGER;
DECLARE VARIABLE S VARCHAR(1000);
DECLARE VARIABLE V$LOC INTEGER;
DECLARE VARIABLE V$USER_TYPE SMALLINT;
begin

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  TAG_NAME = 'user_type';
  VAL = NULL;
  SELECT FIRST 1 U.USER_TYPE
  FROM USERS U
  WHERE U.USER_ID = :I$USER_ID
  INTO :V$USER_TYPE;
  VAL = V$USER_TYPE;
  SUSPEND;

  TAG_NAME = 'is_admin';
  VAL = IIF(V$USER_TYPE = 1, 1, 0);
  SUSPEND;

  TAG_NAME = 'is_bibl';
  IF(V$USER_TYPE = 11) THEN VAL = 1;
  ELSE
  BEGIN
    VAL = 0;
    IF(EXISTS(
      SELECT FIRST 1 1
      FROM USERS U
      JOIN LINKS L15 ON L15.PARENT_ID = U.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
      JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
      LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
      LEFT JOIN VALS V3543 ON V3543.OBJ_ID = L15.OBJ_ID AND V3543.PARAM_ID = 3543 AND V3543.IS_DEL = 0
      LEFT JOIN VALS V589 ON V589.OBJ_ID = L15.OBJ_ID AND V589.PARAM_ID = 589 AND V589.IS_DEL = 0
      WHERE U.USER_ID = :I$USER_ID AND U.DATE_DEL IS NULL AND V74.VAL IS NULL
        AND (UPPER(V3543.SVAL) LIKE '%БИБЛИОТ%' OR UPPER(V589.SVAL) LIKE '%БИБЛИОТ%')
    ))
    THEN VAL = 1;
  END
  SUSPEND;

  -- В момент добавления - определяем площадку
  I$IP = REPLACE(TRIM(REPLACE(REPLACE(I$IP, '[', ''), ']', '')), ' ', '/');
  WHILE(POSITION('/' IN I$IP) > 0) DO I$IP = SUBSTRING(I$IP FROM POSITION('/' IN I$IP) + 1);
  I$IP = TRIM(I$IP);

  TAG_NAME = 'loc_index';
  FOR
    SELECT V3600.VAL, V3599.VAL
    FROM LINKS L2
    JOIN LINKS L536 ON L536.PARENT_ID = L2.OBJ_ID AND L536.OBJ_TYPE_ID = 536 AND L536.DATE_DEL IS NULL
    JOIN VALI V3600 ON V3600.OBJ_ID = L536.OBJ_ID AND V3600.PARAM_ID = 3600 AND V3600.IS_DEL = 0
    JOIN VALS V3599 ON V3599.OBJ_ID = L536.OBJ_ID AND V3599.PARAM_ID = 3599 AND V3599.IS_DEL = 0
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    ORDER BY 1
    INTO :N, :S
  DO
  BEGIN
    S = S || ',';
    IF(POSITION((I$IP || ',') IN S) > 0) THEN V$LOC = N;
  END
  VAL = V$LOC;
  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIB2_LISTS_LIST (
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$LIST_NAME VARCHAR(1000);
DECLARE VARIABLE V$MAX_LEVELS SMALLINT;
DECLARE VARIABLE V$LOCAL_ACCESS SMALLINT;
DECLARE VARIABLE V$GEN BIGINT;
DECLARE VARIABLE V$MULT BIGINT;
BEGIN

  SELECT GEN, MULTIPLIER FROM GEN INTO :V$GEN, :V$MULT;

  TAG_NAME = 'is_rootdb';
  VAL = IIF(V$GEN = 0, '1', '0');
  SUSPEND;

  -- Может ли пользователь создавать справочники ?
  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  TAG_NAME = 'can_create';
  VAL = 0;
  IF(I$USER_ID = '1') THEN VAL = 1;
  SELECT FIRST 1 1
  FROM USERS U
  JOIN LUSERS LU ON LU.USER_ID = U.USER_ID AND LU.LEVEL_ID = 999 AND LU.READ_ONLY = 0 -- !!! прописать нужный level_id
  WHERE U.USER_ID = :I$USER_ID
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'items::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L.LIST_ID, L.LIST_NAME, L.MAX_LEVELS, L.LOCAL_ACCESS
    FROM LIB2_LISTS L
    WHERE L.DATE_DEL IS NULL
    ORDER BY 2
    INTO :V$OBJ_ID, :V$LIST_NAME, :V$MAX_LEVELS, :V$LOCAL_ACCESS
  DO
  BEGIN
    TAG_NAME = 'items:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'items:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'items:r:name';
    VAL = V$LIST_NAME;
    SUSPEND;
    TAG_NAME = 'items:r:max_levels';
    VAL = V$MAX_LEVELS;
    SUSPEND;
    TAG_NAME = 'items:r:local_access';
    VAL = V$LOCAL_ACCESS;
    SUSPEND;
    TAG_NAME = 'items:r:is_local';
    -- В эталонной базе всегда local
    VAL = IIF(V$OBJ_ID < V$MULT AND V$GEN > 0, 0, 1);
    SUSPEND;
  END

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIB2_LISTVAL_DELETE (
    I$LIST_ID BIGINT,
    I$LISTVAL_ID BIGINT,
    I$USER_ID VARCHAR(40))
AS
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$LA INTEGER;
DECLARE VARIABLE V$GEN BIGINT;
DECLARE VARIABLE V$MULTIPLIER BIGINT;
DECLARE VARIABLE T BIGINT;
begin

  SELECT FIRST 1 LV.LISTVAL_ID, L.LOCAL_ACCESS
  FROM LIB2_LISTVALS LV
  JOIN LIB2_LISTS L ON L.LIST_ID = LV.LIST_ID
  WHERE LV.DATE_DEL IS NULL AND LV.LIST_ID = :I$LIST_ID AND LV.LISTVAL_ID = :I$LISTVAL_ID
  INTO :V$OBJ_ID, :V$LA;

  IF(I$LISTVAL_ID IS NOT NULL AND V$OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Данные не найдены или были удалены';

  SELECT GEN, MULTIPLIER
  FROM GEN
  INTO :V$GEN, :V$MULTIPLIER;

  T = I$LISTVAL_ID / V$MULTIPLIER;
  IF(T <> V$GEN) THEN EXCEPTION DATA_ERROR 'Данные можно изменять только в базе организации, в которой они были созданы';

  IF(EXISTS(
    SELECT FIRST 1 1
    FROM LIB2_LISTVALS
    WHERE LIST_ID = :I$LIST_ID AND PARENT_ID = :I$LISTVAL_ID AND DATE_DEL IS NULL
  ))
  THEN
    EXCEPTION DATA_ERROR 'Нельзя удалять элементы дерева, если у них остались подчиненные элементы';

  UPDATE LIB2_LISTVALS
  SET DATE_DEL = CURRENT_TIMESTAMP
  WHERE LISTVAL_ID = :I$LISTVAL_ID;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIB2_LISTVAL_GET (
    I$LIST_ID BIGINT,
    I$LISTVAL_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$PARENT_ID BIGINT;
DECLARE VARIABLE S VARCHAR(1000);
DECLARE VARIABLE V$GEN BIGINT;
DECLARE VARIABLE V$MULTIPLIER BIGINT;
DECLARE VARIABLE V$LA SMALLINT;
DECLARE VARIABLE S2 VARCHAR(100);
begin

  SELECT LV.LISTVAL_ID, LV.VAL, LV.SVAL, LV.PARENT_ID
  FROM LIB2_LISTVALS LV
  WHERE LV.DATE_DEL IS NULL AND LV.LIST_ID = :I$LIST_ID AND LV.LISTVAL_ID = :I$LISTVAL_ID
  INTO :V$OBJ_ID, :S, :S2, :V$PARENT_ID;

  SELECT L.LOCAL_ACCESS
  FROM LIB2_LISTS L
  WHERE L.LIST_ID = :I$LIST_ID
  INTO :V$LA;

  SELECT GEN, MULTIPLIER
  FROM GEN
  INTO :V$GEN, :V$MULTIPLIER;

  IF(I$LISTVAL_ID IS NOT NULL AND V$OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Данные не найдены или были удалены';
  IF(I$LISTVAL_ID IS NULL AND V$LA <> 1 AND V$GEN <> 0) THEN EXCEPTION DATA_ERROR 'В данном справочнике нельзя добавлять элементы';

  TAG_NAME = 'id';
  VAL = V$OBJ_ID;
  SUSPEND;

  TAG_NAME = 'list_id';
  VAL = I$LIST_ID;
  SUSPEND;

  TAG_NAME = 'parent_id';
  VAL = V$PARENT_ID;
  SUSPEND;

  TAG_NAME = 'val';
  VAL = S;
  SUSPEND;

  TAG_NAME = 'code';
  VAL = S2;
  SUSPEND;

  V$OBJ_ID = I$LISTVAL_ID / V$MULTIPLIER;
  IF(V$OBJ_ID <> V$GEN OR (V$LA <> 1 AND V$GEN <> 0)) THEN
  BEGIN
    TAG_NAME = 'row_readonly';
    VAL = 1;
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIB2_LISTVAL_SET (
    I$LIST_ID BIGINT,
    I$PARENT_ID BIGINT,
    I$LISTVAL_ID BIGINT,
    I$VAL VARCHAR(1000),
    I$CODE VARCHAR(40),
    I$USER_ID VARCHAR(40))
RETURNS (
    OBJ_ID BIGINT)
AS
DECLARE VARIABLE V$PARENT_ID BIGINT;
DECLARE VARIABLE V$LA SMALLINT;
DECLARE VARIABLE V$MAX_LEVELS INTEGER;
DECLARE VARIABLE V$GEN BIGINT;
DECLARE VARIABLE V$MULTIPLIER BIGINT;
DECLARE VARIABLE T BIGINT;
DECLARE VARIABLE V$LEVEL INTEGER;
begin

  -- Проверяем доступ к справочнику

  SELECT FIRST 1 LV.LISTVAL_ID, LV.PARENT_ID
  FROM LIB2_LISTVALS LV
  WHERE LV.DATE_DEL IS NULL AND LV.LIST_ID = :I$LIST_ID AND LV.LISTVAL_ID = :I$LISTVAL_ID
  INTO :OBJ_ID, :V$PARENT_ID;

  IF(I$LISTVAL_ID IS NOT NULL AND OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Данные не найдены или были удалены';
  IF(I$LISTVAL_ID IS NOT NULL AND COALESCE(I$PARENT_ID, 0) <> COALESCE(V$PARENT_ID, 0)) THEN EXCEPTION DATA_ERROR 'Нельзя изменять местоположение узла в дереве';
  IF(I$VAL IS NULL OR CHAR_LENGTH(I$VAL) < 1) THEN EXCEPTION DATA_ERROR 'Название должно содержать хотя бы один символ';

  IF(I$LIST_ID = 4 AND I$CODE IS NOT NULL) THEN
  BEGIN
    IF(CHAR_LENGTH(I$CODE) NOT IN (10, 12)) THEN EXCEPTION DATA_ERROR 'ИНН может быть только 10 или 12 цифр';
    T = 1;
    WHILE(T <= CHAR_LENGTH(I$CODE)) DO
    BEGIN
      IF(POSITION(SUBSTRING(I$CODE FROM T FOR 1) IN '0123456789') <= 0) THEN EXCEPTION DATA_ERROR 'ИНН может содержать только цифры';
      T = T + 1;
    END
  END

  SELECT FIRST 1 1
  FROM LIB2_LISTVALS
  WHERE DATE_DEL IS NULL AND LIST_ID = :I$LIST_ID AND LISTVAL_ID = :I$PARENT_ID
  INTO :V$LEVEL;
  IF(I$PARENT_ID IS NOT NULL AND V$LEVEL IS NULL) THEN EXCEPTION DATA_ERROR 'Родительский узел дерева не найден';

  SELECT FIRST 1 L.LOCAL_ACCESS, L.MAX_LEVELS
  FROM LIB2_LISTS L
  WHERE L.LIST_ID = :I$LIST_ID AND L.DATE_DEL IS NULL
  INTO :V$LA, :V$MAX_LEVELS;

  -- Далее - закомментировано для отладочной базы
  SELECT GEN, MULTIPLIER
  FROM GEN
  INTO :V$GEN, :V$MULTIPLIER;

  T = I$LISTVAL_ID / V$MULTIPLIER;
  -- IF(V$LA IN (0, 2) AND V$GEN <> 0) THEN EXCEPTION DATA_ERROR 'Данный справочник можно заполнять только на региональном уровне';
  IF(T <> V$GEN) THEN EXCEPTION DATA_ERROR 'Данные можно изменять только в базе организации, в которой они были созданы';
  IF(V$LA = 1 AND V$GEN <> 0) THEN
  BEGIN
    -- Можно добавлять только на конечных уровнях
    -- в корне нельзя вообще никогда
    T = I$PARENT_ID / V$MULTIPLIER;
    -- IF(I$PARENT_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Нельзя создавать элементы в корне данного справочника';
    -- IF(T <> V$GEN AND EXISTS(SELECT FIRST 1 1 FROM LIB2_LISTVALS WHERE DATE_DEL IS NULL AND LIST_ID = :I$LIST_ID AND PARENT_ID = :I$PARENT_ID)) THEN EXCEPTION DATA_ERROR 'Элементы в данном справочнике можно добавлять только в конечных узлах';
  END
  IF(V$MAX_LEVELS < 0 AND I$PARENT_ID IS NOT NULL) THEN EXCEPTION DATA_ERROR 'В линейном справочнике нельзя добавлять вложенные элементы';
  IF(V$MAX_LEVELS > 0 AND COALESCE(V$LEVEL, 0) + 1 > V$MAX_LEVELS) THEN EXCEPTION DATA_ERROR 'Слишком большой уровень вложенности для данного справочника';

  -- Запрет рекурсии
  IF(I$PARENT_ID = I$LISTVAL_ID) THEN EXCEPTION DATA_ERROR 'Элемент не может быть родительским для самого себя';
  IF(I$PARENT_ID IS NOT NULL) THEN
  BEGIN
    -- !!!
  END

  IF(I$LISTVAL_ID IS NULL) THEN
  BEGIN
    INSERT INTO LIB2_LISTVALS
    (LIST_ID, PARENT_ID, VAL, SVAL)
    VALUES (:I$LIST_ID, :I$PARENT_ID, :I$VAL, :I$CODE)
    RETURNING LISTVAL_ID INTO :OBJ_ID;
  END
  ELSE
  BEGIN
    UPDATE LIB2_LISTVALS
    SET VAL = :I$VAL, SVAL = :I$CODE
    WHERE LISTVAL_ID = :I$LISTVAL_ID;
  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIB2_LIST_DELETE (
    I$LIST_ID BIGINT,
    I$USER_ID VARCHAR(40))
AS
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$LA INTEGER;
DECLARE VARIABLE V$GEN BIGINT;
DECLARE VARIABLE V$MULTIPLIER BIGINT;
DECLARE VARIABLE T BIGINT;
begin

  SELECT FIRST 1 L.LIST_ID, L.LOCAL_ACCESS
  FROM LIB2_LISTS L
  WHERE L.DATE_DEL IS NULL AND L.LIST_ID = :I$LIST_ID
  INTO :V$OBJ_ID, :V$LA;

  IF(I$LIST_ID IS NOT NULL AND V$OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Данные не найдены или были удалены';

  SELECT GEN, MULTIPLIER
  FROM GEN
  INTO :V$GEN, :V$MULTIPLIER;

  T = I$LIST_ID / V$MULTIPLIER;
  IF(T <> V$GEN) THEN EXCEPTION DATA_ERROR 'Данные можно изменять только в базе организации, в которой они были созданы';

  UPDATE LIB2_LISTS
  SET DATE_DEL = CURRENT_TIMESTAMP
  WHERE LIST_ID = :I$LIST_ID;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIB2_LIST_GET (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$MULT BIGINT;
DECLARE VARIABLE V$GEN BIGINT;
DECLARE VARIABLE V$LIST_NAME VARCHAR(1000);
DECLARE VARIABLE V$MAX_LEVELS SMALLINT;
DECLARE VARIABLE V$LOCAL_ACCESS SMALLINT;
DECLARE VARIABLE V$CAN_EDIT SMALLINT;
DECLARE VARIABLE N INTEGER;
begin

  SELECT GEN, MULTIPLIER FROM GEN INTO :V$GEN, :V$MULT;

  -- Может ли пользователь создавать справочники ?
  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  V$CAN_EDIT = 0;
  IF(I$USER_ID = '1') THEN V$CAN_EDIT = 1;
  SELECT FIRST 1 1
  FROM USERS U
  JOIN LUSERS LU ON LU.USER_ID = U.USER_ID AND LU.LEVEL_ID = 999 AND LU.READ_ONLY = 0 -- !!! прописать нужный level_id
  WHERE U.USER_ID = :I$USER_ID
  INTO :V$CAN_EDIT;

  IF(I$OBJ_ID IS NULL AND V$CAN_EDIT = 0) THEN EXCEPTION DATA_ERROR 'У вас нет прав для добавления справочников';

  SELECT L.LIST_ID, L.LIST_NAME, L.MAX_LEVELS, L.LOCAL_ACCESS
  FROM LIB2_LISTS L
  WHERE L.DATE_DEL IS NULL AND L.LIST_ID = :I$OBJ_ID
  INTO :V$OBJ_ID, :V$LIST_NAME, :V$MAX_LEVELS, :V$LOCAL_ACCESS;

  IF(I$OBJ_ID IS NOT NULL AND V$OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Справочник не найден или был удален';

  TAG_NAME = 'id';
  VAL = V$OBJ_ID;
  SUSPEND;

  TAG_NAME = 'name';
  VAL = V$LIST_NAME;
  SUSPEND;

  -- Возвращаем признак только чтение при совпадении условий
  -- Центральные справочники можно редактировать только в центральной базе
  IF((I$OBJ_ID < V$MULT AND V$GEN <> 0) OR V$CAN_EDIT = 0) THEN
  BEGIN
    TAG_NAME = 'row_readonly';
    VAL = 1;
    SUSPEND;
  END

  TAG_NAME = 'max_levels:selection::json&colon;array';
  VAL = 1;
  SUSPEND;
    TAG_NAME = 'max_levels:selection:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'max_levels:selection:r:id';
    VAL = '-1';
    SUSPEND;
    TAG_NAME = 'max_levels:selection:r:value';
    VAL = 'Линейный список';
    SUSPEND;
    --
    TAG_NAME = 'max_levels:selection:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'max_levels:selection:r:id';
    VAL = '0';
    SUSPEND;
    TAG_NAME = 'max_levels:selection:r:value';
    VAL = 'Дерево - без ограничения уровней';
    SUSPEND;
    --
    N = 1;
    WHILE(N <= 6) DO
    BEGIN
      TAG_NAME = 'max_levels:selection:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'max_levels:selection:r:id';
      VAL = N;
      SUSPEND;
      TAG_NAME = 'max_levels:selection:r:value';
      VAL = 'Дерево - ' || N;
      IF(N = 1) THEN VAL = VAL || ' уровень'; ELSE VAL = VAL || ' уровней';
      SUSPEND;
      N = N + 1;
    END
  TAG_NAME = 'max_levels:values:value';
  VAL = V$MAX_LEVELS;
  SUSPEND;

  TAG_NAME = 'local_access:selection::json&colon;array';
  VAL = 1;
  SUSPEND;
  -- Запрещать локальный доступ, а также прописывать онлайн-доступ можно только для центрального справочника
  IF(I$OBJ_ID < V$MULT OR V$GEN = 0) THEN
  BEGIN
    TAG_NAME = 'local_access:selection:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'local_access:selection:r:id';
    VAL = 0;
    SUSPEND;
    TAG_NAME = 'local_access:selection:r:value';
    VAL = 'Только централизованное внесение данных';
    SUSPEND;
    --
    TAG_NAME = 'local_access:selection:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'local_access:selection:r:id';
    VAL = 2;
    SUSPEND;
    TAG_NAME = 'local_access:selection:r:value';
    VAL = 'Онлайн-справочник';
    SUSPEND;
  END
  TAG_NAME = 'local_access:selection:r';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'local_access:selection:r:id';
  VAL = 1;
  SUSPEND;
  TAG_NAME = 'local_access:selection:r:value';
  VAL = 'Разрешить внесение данных в ОУ';
  SUSPEND;
  TAG_NAME = 'local_access:values:value';
  VAL = V$LOCAL_ACCESS;
  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIB2_LIST_SET (
    I$OBJ_ID BIGINT,
    I$NAME VARCHAR(1000),
    I$MAX_LEVEL INTEGER,
    I$LOCAL_ACCESS INTEGER,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$GEN BIGINT;
DECLARE VARIABLE V$PREV_LEVEL INTEGER;
DECLARE VARIABLE V$MULTIPLIER BIGINT;
BEGIN

  SELECT FIRST 1 L.LIST_ID, L.MAX_LEVELS
  FROM LIB2_LISTS L
  WHERE L.LIST_ID = :I$OBJ_ID AND L.DATE_DEL IS NULL
  INTO :V$OBJ_ID, :V$PREV_LEVEL;

  I$NAME = TRIM(I$NAME);
  IF(I$NAME IS NULL OR CHAR_LENGTH(I$NAME) < 3) THEN EXCEPTION DATA_ERROR 'Название должно быть не менее 3 символов';
  IF(I$MAX_LEVEL IS NULL OR I$MAX_LEVEL < -1) THEN EXCEPTION DATA_ERROR 'Тип справочника должен быть заполнен';
  IF(I$LOCAL_ACCESS IS NULL) THEN EXCEPTION DATA_ERROR 'Режим использования должен быть заполнен';
  IF(I$OBJ_ID IS NOT NULL AND V$OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Данные не найдены или были удалены';

  SELECT GEN, MULTIPLIER FROM GEN INTO :V$GEN, :V$MULTIPLIER;
  V$OBJ_ID = I$OBJ_ID / V$MULTIPLIER;
  IF(V$OBJ_ID < V$GEN) THEN EXCEPTION DATA_ERROR 'Справочник не может быть изменен';

  IF(I$MAX_LEVEL <> V$PREV_LEVEL) THEN BEGIN
    IF(I$MAX_LEVEL < 0 AND EXISTS(
      SELECT FIRST 1 1
      FROM LIB2_LISTVALS LV
      WHERE LV.DATE_DEL IS NULL AND LV.LIST_ID = :I$OBJ_ID AND LV.LEVEL_NUM > 0
    ))
    THEN
      EXCEPTION DATA_ERROR 'В справочнике уже внесены древовидные данные, требуется удалить все записи с уровнями выше первого';
    IF(I$MAX_LEVEL > 0 AND EXISTS(
      SELECT FIRST 1 1
      FROM LIB2_LISTVALS LV
      WHERE LV.DATE_DEL IS NULL AND LV.LIST_ID = :I$OBJ_ID AND LV.LEVEL_NUM > :I$MAX_LEVEL
    ))
    THEN
      EXCEPTION DATA_ERROR 'В справочнике уже внесены древовидные данные с количеством уровней больше указанного';
  END

  -- Уникальность имени
  IF(EXISTS(
    SELECT FIRST 1 1
    FROM LIB2_LISTS
    WHERE DATE_DEL IS NULL AND UPPER(LIST_NAME) = UPPER(:I$NAME)
  ))
  THEN
    EXCEPTION DATA_ERROR 'Название справочника должно быть уникальным';

  IF(I$OBJ_ID IS NULL) THEN
  BEGIN
    INSERT INTO LIB2_LISTS
    (LIST_NAME, MAX_LEVELS, LOCAL_ACCESS)
    VALUES (:I$NAME, :I$MAX_LEVEL, :I$LOCAL_ACCESS)
    RETURNING LIST_ID INTO :I$OBJ_ID;
  END
  ELSE
  BEGIN
    UPDATE LIB2_LISTS
    SET LIST_NAME = :I$NAME, MAX_LEVELS = :I$MAX_LEVEL, LOCAL_ACCESS = :I$LOCAL_ACCESS
    WHERE LIST_ID = :I$OBJ_ID;
  END

  TAG_NAME = 'id';
  VAL = I$OBJ_ID;
  SUSPEND;
  TAG_NAME = 'name';
  VAL = I$NAME;
  SUSPEND;
  TAG_NAME = 'max_levels';
  VAL = I$MAX_LEVEL;
  SUSPEND;
  TAG_NAME = 'local_access';
  VAL = I$LOCAL_ACCESS;
  SUSPEND;
  TAG_NAME = 'is_local';
  -- В эталонной базе всегда local
  VAL = IIF(I$OBJ_ID < V$MULTIPLIER AND V$GEN > 0, 0, 1);
  SUSPEND;

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIB2_LIST_TREE (
    I$LIST_ID BIGINT,
    I$PARENT_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$LISTVAL_ID BIGINT;
DECLARE VARIABLE S VARCHAR(1000);
DECLARE VARIABLE S2 VARCHAR(40);
DECLARE VARIABLE L INTEGER;
begin

  TAG_NAME = 'items::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT LV.LISTVAL_ID, LV.VAL, LV.SVAL, LV.LEVEL_NUM
    FROM LIB2_LISTVALS LV
    WHERE LV.DATE_DEL IS NULL AND LV.LIST_ID = :I$LIST_ID AND (LV.PARENT_ID = :I$PARENT_ID OR (LV.PARENT_ID IS NULL AND :I$PARENT_ID IS NULL))
    ORDER BY 2
    INTO :V$LISTVAL_ID, :S, :S2, :L
  DO
  BEGIN
    TAG_NAME = 'items:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'items:r:id';
    VAL = V$LISTVAL_ID;
    SUSPEND;
    TAG_NAME = 'items:r:value';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'items:r:code';
    VAL = S2;
    SUSPEND;
    TAG_NAME = 'items:r:level';
    VAL = L;
    SUSPEND;
    TAG_NAME = 'items:r:children';
    VAL = 0;
    SELECT FIRST 1 1
    FROM LIB2_LISTVALS LV
    WHERE LV.PARENT_ID = :V$LISTVAL_ID AND LV.DATE_DEL IS NULL AND LV.LIST_ID = :I$LIST_ID
    INTO :VAL;
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIB2_LOCATIONS_GET (
    I$IP VARCHAR(400),
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(4000))
AS
DECLARE VARIABLE N INTEGER;
DECLARE VARIABLE S VARCHAR(4000);
DECLARE VARIABLE V$LOC INTEGER;
begin

  I$IP = REPLACE(TRIM(REPLACE(REPLACE(I$IP, '[', ''), ']', '')), ' ', '/');
  WHILE(POSITION('/' IN I$IP) > 0) DO I$IP = SUBSTRING(I$IP FROM POSITION('/' IN I$IP) + 1);
  I$IP = TRIM(I$IP);

  FOR
    SELECT V3600.VAL, V3599.VAL
    FROM LINKS L2
    JOIN LINKS L536 ON L536.PARENT_ID = L2.OBJ_ID AND L536.OBJ_TYPE_ID = 536 AND L536.DATE_DEL IS NULL
    JOIN VALI V3600 ON V3600.OBJ_ID = L536.OBJ_ID AND V3600.PARAM_ID = 3600 AND V3600.IS_DEL = 0
    JOIN VALS V3599 ON V3599.OBJ_ID = L536.OBJ_ID AND V3599.PARAM_ID = 3599 AND V3599.IS_DEL = 0
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    ORDER BY 1
    INTO :N, :S
  DO
  BEGIN
    S = S || ',';
    IF(POSITION((I$IP || ',') IN S) > 0) THEN V$LOC = N;
  END

  TAG_NAME = 'loc_ip';
  VAL = I$IP;
  SUSPEND;

  TAG_NAME = 'loc_index';
  VAL = V$LOC;
  SUSPEND;

  TAG_NAME = 'invbase';
  VAL = NULL;
  SELECT FIRST 1 V3602.VAL
  FROM LINKS L2
  JOIN VALI V3602 ON V3602.OBJ_ID = L2.OBJ_ID AND V3602.PARAM_ID = 3602 AND V3602.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'locations::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT V3600.VAL, V3599.VAL
    FROM LINKS L2
    JOIN LINKS L536 ON L536.PARENT_ID = L2.OBJ_ID AND L536.OBJ_TYPE_ID = 536 AND L536.DATE_DEL IS NULL
    JOIN VALI V3600 ON V3600.OBJ_ID = L536.OBJ_ID AND V3600.PARAM_ID = 3600 AND V3600.IS_DEL = 0
    LEFT JOIN VALS V3599 ON V3599.OBJ_ID = L536.OBJ_ID AND V3599.PARAM_ID = 3599 AND V3599.IS_DEL = 0
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :N, :S
  DO
  BEGIN
    TAG_NAME = 'locations:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'locations:r:id';
    VAL = N;
    SUSPEND;
    TAG_NAME = 'locations:r:address';
    VAL = S;
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIB2_LOCATION_BASE (
    I$VAL INTEGER,
    I$USER_ID BIGINT)
AS
DECLARE VARIABLE V$OU_ID BIGINT;
DECLARE VARIABLE N INTEGER;
begin

  IF(I$VAL < 0) THEN EXCEPTION DATA_ERROR 'Допускаются только положительные значения';

  SELECT FIRST 1 L2.OBJ_ID
  FROM LINKS L2
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$OU_ID;

  SELECT 1 FROM VAL_ADD(3602, :V$OU_ID, :I$VAL, :I$USER_ID) INTO :N;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIB2_LOCATION_DEL (
    I$OBJ_ID BIGINT NOT NULL)
AS
DECLARE VARIABLE V$OU_ID BIGINT;
DECLARE VARIABLE V$INDEX INTEGER;
begin

  -- Нельзя удалять пункты в середине нумерации
  SELECT L536.OBJ_ID, V3600.VAL
  FROM LINKS L536
  JOIN VALI V3600 ON V3600.OBJ_ID = L536.OBJ_ID AND V3600.PARAM_ID = 3600 AND V3600.IS_DEL = 0
  WHERE L536.OBJ_ID = :I$OBJ_ID AND L536.OBJ_TYPE_ID = 536 AND L536.PARENT_TYPE_ID = 2 AND L536.DATE_DEL IS NULL
  INTO :V$OU_ID, :V$INDEX;

  IF(V$INDEX IS NULL) THEN EXIT;

  IF(EXISTS(
    SELECT FIRST 1 1
    FROM LINKS L536
    JOIN VALI V3600 ON V3600.OBJ_ID = L536.OBJ_ID AND V3600.PARAM_ID = 3600 AND V3600.IS_DEL = 0 AND V3600.VAL > :V$INDEX
    WHERE L536.PARENT_ID = :V$OU_ID AND L536.OBJ_TYPE_ID = 536 AND L536.DATE_DEL IS NULL
  ))
  THEN
    EXCEPTION DATA_ERROR 'Площадки можно удалять только с конца списка';

  UPDATE LINKS
  SET DATE_DEL = CURRENT_TIMESTAMP
  WHERE OBJ_ID = :I$OBJ_ID AND OBJ_TYPE_ID = 536 AND PARENT_TYPE_ID = 2 AND DATE_DEL IS NULL;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIB2_LOCATION_SET (
    I$INDEX INTEGER NOT NULL,
    I$ADDRESS VARCHAR(4000) NOT NULL)
RETURNS (
    OBJ_ID BIGINT)
AS
DECLARE VARIABLE V$OU_ID BIGINT;
DECLARE VARIABLE S VARCHAR(4000);
DECLARE VARIABLE T INTEGER;
DECLARE VARIABLE DT TIMESTAMP;
begin

  IF(I$INDEX <= 0 OR I$INDEX > 10) THEN EXCEPTION DATA_ERROR 'Допускается не более 10 записей площадок';

  SELECT FIRST 1 L2.OBJ_ID
  FROM LINKS L2
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$OU_ID;

  IF(V$OU_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не настроены данные ОУ';

  SELECT FIRST 1 L536.OBJ_ID, L536.DATE_DEL, V3599.VAL
  FROM LINKS L536
  JOIN VALI V3600 ON V3600.OBJ_ID = L536.OBJ_ID AND V3600.PARAM_ID = 3600 AND V3600.IS_DEL = 0 AND V3600.VAL = :I$INDEX
  LEFT JOIN VALS V3599 ON V3599.OBJ_ID = L536.OBJ_ID AND V3599.PARAM_ID = 3599 AND V3599.IS_DEL = 0
  WHERE L536.PARENT_ID = :V$OU_ID AND L536.OBJ_TYPE_ID = 536
  INTO :OBJ_ID, :DT, :S;

  IF(OBJ_ID IS NULL) THEN
  BEGIN
    SELECT OBJ_ID FROM OBJECT_ADD(:V$OU_ID, 536) INTO :OBJ_ID;
    SELECT 1 FROM VAL_ADD(3600, :OBJ_ID, :I$INDEX) INTO :T;
  END
  ELSE IF(DT IS NOT NULL) THEN
  BEGIN
    -- Отменяем удаление
    UPDATE LINKS
    SET DATE_DEL = NULL
    WHERE OBJ_ID = :OBJ_ID;
  END

  IF(COALESCE(I$ADDRESS, '') <> COALESCE(S, '')) THEN
  SELECT 1 FROM VAL_ADD(3599, :OBJ_ID, :I$ADDRESS) INTO :T;

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIB2_LOC_COUNT (
    I$BOOK_ID BIGINT,
    I$TYPE_ID BIGINT,
    I$LOCMASK INTEGER)
RETURNS (
    CNT_AVAIL1 INTEGER,
    CNT_FREE1 INTEGER,
    CNT_GIVEN1 INTEGER,
    CNT_AVAIL2 INTEGER,
    CNT_FREE2 INTEGER,
    CNT_GIVEN2 INTEGER,
    CNT_AVAIL3 INTEGER,
    CNT_FREE3 INTEGER,
    CNT_GIVEN3 INTEGER,
    CNT_AVAIL4 INTEGER,
    CNT_FREE4 INTEGER,
    CNT_GIVEN4 INTEGER,
    CNT_AVAIL5 INTEGER,
    CNT_FREE5 INTEGER,
    CNT_GIVEN5 INTEGER)
AS
DECLARE VARIABLE N1 INTEGER;
DECLARE VARIABLE N2 INTEGER;
DECLARE VARIABLE N3 INTEGER;
DECLARE VARIABLE N4 INTEGER;
DECLARE VARIABLE N5 INTEGER;
begin

  IF(I$TYPE_ID IN (18711, 18713, 18715)) THEN
  BEGIN
    IF(BIN_AND(I$LOCMASK, 2) <> 0) THEN
    SELECT COUNT(*), COALESCE(SUM(I.IS_FREE), 0)
    FROM LIB2_INSTANCES I
    WHERE I.DATE_DEL IS NULL AND I.BOOK_ID = :I$BOOK_ID AND I.LOC_INDEX = 1 AND I.INVOICE_OUT_ID IS NULL
    INTO :CNT_AVAIL1, :CNT_FREE1;
    IF(BIN_AND(I$LOCMASK, 4) <> 0) THEN
    SELECT COUNT(*), COALESCE(SUM(I.IS_FREE), 0)
    FROM LIB2_INSTANCES I
    WHERE I.DATE_DEL IS NULL AND I.BOOK_ID = :I$BOOK_ID AND I.LOC_INDEX = 2 AND I.INVOICE_OUT_ID IS NULL
    INTO :CNT_AVAIL2, :CNT_FREE2;
    IF(BIN_AND(I$LOCMASK, 8) <> 0) THEN
    SELECT COUNT(*), COALESCE(SUM(I.IS_FREE), 0)
    FROM LIB2_INSTANCES I
    WHERE I.DATE_DEL IS NULL AND I.BOOK_ID = :I$BOOK_ID AND I.LOC_INDEX = 3 AND I.INVOICE_OUT_ID IS NULL
    INTO :CNT_AVAIL3, :CNT_FREE3;
    IF(BIN_AND(I$LOCMASK, 16) <> 0) THEN
    SELECT COUNT(*), COALESCE(SUM(I.IS_FREE), 0)
    FROM LIB2_INSTANCES I
    WHERE I.DATE_DEL IS NULL AND I.BOOK_ID = :I$BOOK_ID AND I.LOC_INDEX = 4 AND I.INVOICE_OUT_ID IS NULL
    INTO :CNT_AVAIL4, :CNT_FREE4;
    IF(BIN_AND(I$LOCMASK, 32) <> 0) THEN
    SELECT COUNT(*), COALESCE(SUM(I.IS_FREE), 0)
    FROM LIB2_INSTANCES I
    WHERE I.DATE_DEL IS NULL AND I.BOOK_ID = :I$BOOK_ID AND I.LOC_INDEX = 5 AND I.INVOICE_OUT_ID IS NULL
    INTO :CNT_AVAIL5, :CNT_FREE5;

    CNT_GIVEN1 = CNT_AVAIL1 - CNT_FREE1;
    CNT_GIVEN2 = CNT_AVAIL2 - CNT_FREE2;
    CNT_GIVEN3 = CNT_AVAIL3 - CNT_FREE3;
    CNT_GIVEN4 = CNT_AVAIL5 - CNT_FREE4;
    CNT_GIVEN5 = CNT_AVAIL5 - CNT_FREE5;
  END
  ELSE
  BEGIN
    IF(BIN_AND(I$LOCMASK, 2) <> 0) THEN
    BEGIN
      SELECT COALESCE(SUM(B.QUANTITY), 0)
      FROM LIB2_BATCHES B
      WHERE B.DATE_DEL IS NULL AND B.BOOK_ID = :I$BOOK_ID AND B.LOC_INDEX = 1 AND B.INVOICE_IN_ID IS NOT NULL
      INTO :CNT_AVAIL1;
      SELECT COALESCE(SUM(B.QUANTITY), 0)
      FROM LIB2_BATCHES B
      WHERE B.DATE_DEL IS NULL AND B.BOOK_ID = :I$BOOK_ID AND B.LOC_INDEX = 1 AND B.INVOICE_OUT_ID IS NOT NULL
      INTO :N1;
      CNT_AVAIL1 = CNT_AVAIL1 - COALESCE(N1, 0);
      SELECT COALESCE(SUM(U.QUANTITY), 0)
      FROM LIB2_USAGE U
      WHERE U.DATE_DEL IS NULL AND U.BOOK_ID = :I$BOOK_ID AND U.LOC_INDEX = 1 AND U.RETURN_DATE IS NULL AND U.LOSS_DATE IS NULL AND U.CLASS_USAGE_ID IS NULL
      INTO :CNT_GIVEN1;
      CNT_FREE1 = CNT_AVAIL1 - CNT_GIVEN1;
    END

    IF(BIN_AND(I$LOCMASK, 4) <> 0) THEN
    BEGIN
      SELECT COALESCE(SUM(B.QUANTITY), 0)
      FROM LIB2_BATCHES B
      WHERE B.DATE_DEL IS NULL AND B.BOOK_ID = :I$BOOK_ID AND B.LOC_INDEX = 2 AND B.INVOICE_IN_ID IS NOT NULL
      INTO :CNT_AVAIL2;
      SELECT COALESCE(SUM(B.QUANTITY), 0)
      FROM LIB2_BATCHES B
      WHERE B.DATE_DEL IS NULL AND B.BOOK_ID = :I$BOOK_ID AND B.LOC_INDEX = 2 AND B.INVOICE_OUT_ID IS NOT NULL
      INTO :N2;
      CNT_AVAIL2 = CNT_AVAIL2 - COALESCE(N2, 0);
      SELECT COALESCE(SUM(U.QUANTITY), 0)
      FROM LIB2_USAGE U
      WHERE U.DATE_DEL IS NULL AND U.BOOK_ID = :I$BOOK_ID AND U.LOC_INDEX = 2 AND U.RETURN_DATE IS NULL AND U.LOSS_DATE IS NULL AND U.CLASS_USAGE_ID IS NULL
      INTO :CNT_GIVEN2;
      CNT_FREE2 = CNT_AVAIL2 - CNT_GIVEN2;
    END

    IF(BIN_AND(I$LOCMASK, 8) <> 0) THEN
    BEGIN
      SELECT COALESCE(SUM(B.QUANTITY), 0)
      FROM LIB2_BATCHES B
      WHERE B.DATE_DEL IS NULL AND B.BOOK_ID = :I$BOOK_ID AND B.LOC_INDEX = 3 AND B.INVOICE_IN_ID IS NOT NULL
      INTO :CNT_AVAIL3;
      SELECT COALESCE(SUM(B.QUANTITY), 0)
      FROM LIB2_BATCHES B
      WHERE B.DATE_DEL IS NULL AND B.BOOK_ID = :I$BOOK_ID AND B.LOC_INDEX = 3 AND B.INVOICE_OUT_ID IS NOT NULL
      INTO :N3;
      CNT_AVAIL3 = CNT_AVAIL3 - COALESCE(N3, 0);
      SELECT COALESCE(SUM(U.QUANTITY), 0)
      FROM LIB2_USAGE U
      WHERE U.DATE_DEL IS NULL AND U.BOOK_ID = :I$BOOK_ID AND U.LOC_INDEX = 3 AND U.RETURN_DATE IS NULL AND U.LOSS_DATE IS NULL AND U.CLASS_USAGE_ID IS NULL
      INTO :CNT_GIVEN3;
      CNT_FREE3 = CNT_AVAIL3 - CNT_GIVEN3;
    END

    IF(BIN_AND(I$LOCMASK, 16) <> 0) THEN
    BEGIN
      SELECT COALESCE(SUM(B.QUANTITY), 0)
      FROM LIB2_BATCHES B
      WHERE B.DATE_DEL IS NULL AND B.BOOK_ID = :I$BOOK_ID AND B.LOC_INDEX = 4 AND B.INVOICE_IN_ID IS NOT NULL
      INTO :CNT_AVAIL4;
      SELECT COALESCE(SUM(B.QUANTITY), 0)
      FROM LIB2_BATCHES B
      WHERE B.DATE_DEL IS NULL AND B.BOOK_ID = :I$BOOK_ID AND B.LOC_INDEX = 4 AND B.INVOICE_OUT_ID IS NOT NULL
      INTO :N4;
      CNT_AVAIL4 = CNT_AVAIL4 - COALESCE(N4, 0);
      SELECT COALESCE(SUM(U.QUANTITY), 0)
      FROM LIB2_USAGE U
      WHERE U.DATE_DEL IS NULL AND U.BOOK_ID = :I$BOOK_ID AND U.LOC_INDEX = 4 AND U.RETURN_DATE IS NULL AND U.LOSS_DATE IS NULL AND U.CLASS_USAGE_ID IS NULL
      INTO :CNT_GIVEN4;
      CNT_FREE4 = CNT_AVAIL4 - CNT_GIVEN4;
    END

    IF(BIN_AND(I$LOCMASK, 32) <> 0) THEN
    BEGIN
      SELECT COALESCE(SUM(B.QUANTITY), 0)
      FROM LIB2_BATCHES B
      WHERE B.DATE_DEL IS NULL AND B.BOOK_ID = :I$BOOK_ID AND B.LOC_INDEX = 5 AND B.INVOICE_IN_ID IS NOT NULL
      INTO :CNT_AVAIL5;
      SELECT COALESCE(SUM(B.QUANTITY), 0)
      FROM LIB2_BATCHES B
      WHERE B.DATE_DEL IS NULL AND B.BOOK_ID = :I$BOOK_ID AND B.LOC_INDEX = 5 AND B.INVOICE_OUT_ID IS NOT NULL
      INTO :N5;
      CNT_AVAIL5 = CNT_AVAIL5 - COALESCE(N5, 0);
      SELECT COALESCE(SUM(U.QUANTITY), 0)
      FROM LIB2_USAGE U
      WHERE U.DATE_DEL IS NULL AND U.BOOK_ID = :I$BOOK_ID AND U.LOC_INDEX = 5 AND U.RETURN_DATE IS NULL AND U.LOSS_DATE IS NULL AND U.CLASS_USAGE_ID IS NULL
      INTO :CNT_GIVEN5;
      CNT_FREE5 = CNT_AVAIL5 - CNT_GIVEN5;
    END

  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIB2_MASS_ASSN (
    I$GRADE_ID BIGINT,
    I$PERSON_ID BIGINT,
    I$BOOK_ID BIGINT,
    I$STATE INTEGER,
    I$IP VARCHAR(400),
    I$USER_ID VARCHAR(40))
RETURNS (
    OBJ_ID BIGINT)
AS
DECLARE VARIABLE V$DT TIMESTAMP;
DECLARE VARIABLE V$BOOK_ID BIGINT;
DECLARE VARIABLE V$REF_TYPE_ID BIGINT;
DECLARE VARIABLE V$DATE_TO DATE;
DECLARE VARIABLE V$FORCED_ID BIGINT;
DECLARE VARIABLE V$LOC INTEGER;
DECLARE VARIABLE V$LOC_INDEX INTEGER;
DECLARE VARIABLE N INTEGER;
DECLARE VARIABLE S VARCHAR(4000);
DECLARE VARIABLE V$ROLE SMALLINT;
begin

  -- При распределении записи выдачи сохраняются, но остатки не обновляются
  -- остатки уже учтены при выдаче на весь класс

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;
  SELECT FIRST 1 U.USER_TYPE
  FROM USERS U
  WHERE U.USER_ID = :I$USER_ID
  INTO :V$ROLE;

  -- В момент добавления - определяем площадку
  I$IP = REPLACE(TRIM(REPLACE(REPLACE(I$IP, '[', ''), ']', '')), ' ', '/');
  WHILE(POSITION('/' IN I$IP) > 0) DO I$IP = SUBSTRING(I$IP FROM POSITION('/' IN I$IP) + 1);
  I$IP = TRIM(I$IP);

  FOR
    SELECT V3600.VAL, V3599.VAL
    FROM LINKS L2
    JOIN LINKS L536 ON L536.PARENT_ID = L2.OBJ_ID AND L536.OBJ_TYPE_ID = 536 AND L536.DATE_DEL IS NULL
    JOIN VALI V3600 ON V3600.OBJ_ID = L536.OBJ_ID AND V3600.PARAM_ID = 3600 AND V3600.IS_DEL = 0
    JOIN VALS V3599 ON V3599.OBJ_ID = L536.OBJ_ID AND V3599.PARAM_ID = 3599 AND V3599.IS_DEL = 0
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    ORDER BY 1
    INTO :N, :S
  DO
  BEGIN
    S = S || ',';
    IF(POSITION((I$IP || ',') IN S) > 0) THEN V$LOC = N;
  END

  SELECT FIRST 1 L10.PARENT_TYPE_ID
  FROM LINKS L10
  WHERE L10.PARENT_ID = :I$GRADE_ID AND L10.OBJ_TYPE_ID = 10 AND L10.OBJ_ID = :I$PERSON_ID AND L10.DATE_DEL IS NULL
  INTO :V$REF_TYPE_ID;

  IF(V$REF_TYPE_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Ученик не числится в учебном коллективе';

  SELECT FIRST 1 U.BOOK_ID
  FROM LIB2_USAGE U
  WHERE U.DATE_DEL IS NULL AND U.OBJ_ID = :I$BOOK_ID AND U.REF_ID = :I$GRADE_ID
  INTO :V$BOOK_ID;

  IF(V$BOOK_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не найден учебник или запись пакетной выдачи';

  SELECT FIRST 1 U.OBJ_ID, U.DATE_DEL, U.LOC_INDEX
  FROM LIB2_USAGE U
  WHERE U.REF_ID = :I$PERSON_ID AND U.CLASS_USAGE_ID = :I$BOOK_ID AND U.RETURN_DATE IS NULL AND U.LOSS_DATE IS NULL
  ORDER BY 2 NULLS FIRST
  INTO :OBJ_ID, :V$DT, :V$LOC_INDEX;

  -- Нет выбора. Записи нет, или она удалена - ничего не надо делать
  IF((OBJ_ID IS NULL OR V$DT IS NOT NULL) AND I$STATE = 0) THEN EXIT;

  -- Удаляем выбор
  -- если учебник был выдан персонально - выбор не снимется
  IF(I$STATE = 0) THEN
  BEGIN
    UPDATE LIB2_USAGE
    SET DATE_DEL = CURRENT_TIMESTAMP, RET_USER_ID = :I$USER_ID
    WHERE OBJ_ID = :OBJ_ID;
    EXIT;
  END

  -- Выбор есть, запись есть - ничего не надо делать
  IF(OBJ_ID IS NOT NULL AND V$DT IS NULL) THEN EXIT;

  -- Проверяем что учебник не выдали персонально - без привязки к CLASS_USAGE
  -- если выдано - просто игнорируем команду
  -- Может быть ситуация, когда один учебник выдается по разным предметам - это костыль для обеспеченности
  SELECT FIRST 1 1
  FROM LIB2_USAGE U
  WHERE U.DATE_DEL IS NULL AND U.REF_ID = :I$PERSON_ID AND U.BOOK_ID = :V$BOOK_ID AND U.RETURN_DATE IS NULL AND U.LOSS_DATE IS NULL
    AND U.CLASS_USAGE_ID IS NULL
  INTO :V$FORCED_ID;

  IF(V$FORCED_ID IS NOT NULL) THEN EXIT;
  -- EXCEPTION DATA_ERROR 'Учебник уже выдан ученику в личном порядке (' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$PERSON_ID));

  -- Отменяем удаление старой
  IF(V$DT IS NOT NULL) THEN
  BEGIN
    UPDATE LIB2_USAGE
    SET DATE_DEL = NULL, USER_ID = :I$USER_ID
    WHERE OBJ_ID = :OBJ_ID;
  END

  -- Вносим новую запись
  IF(OBJ_ID IS NULL) THEN
  BEGIN
    IF(EXTRACT(MONTH FROM CURRENT_DATE) < 6) THEN V$DATE_TO = '31.05.' || EXTRACT(YEAR FROM CURRENT_DATE);
      ELSE V$DATE_TO = '31.05.' || (EXTRACT(YEAR FROM CURRENT_DATE) + 1);

    INSERT INTO LIB2_USAGE
    (REF_ID, REF_TYPE_ID, BOOK_ID, INSTANCE_ID, QUANTITY, ACTION_DATE, PLAN_DATE, USER_ID, CLASS_USAGE_ID, LOC_INDEX)
    VALUES (:I$PERSON_ID, 10, :V$BOOK_ID, NULL, 1, CURRENT_DATE, :V$DATE_TO, :I$USER_ID, :I$BOOK_ID, :V$LOC_INDEX)
    RETURNING OBJ_ID INTO :OBJ_ID;
  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIB2_MASS_GIVE (
    I$GRADE_ID BIGINT NOT NULL,
    I$BOOK_ID BIGINT NOT NULL,
    I$SUBJECT_ID BIGINT,
    I$LOAD_ID BIGINT,
    I$QUANTITY INTEGER NOT NULL,
    I$IP VARCHAR(400),
    I$USER_ID VARCHAR(40))
RETURNS (
    OBJ_ID BIGINT)
AS
DECLARE VARIABLE V$DT TIMESTAMP;
DECLARE VARIABLE Q INTEGER;
DECLARE VARIABLE F INTEGER;
DECLARE VARIABLE V$USED INTEGER;
DECLARE VARIABLE V$REF_TYPE_ID BIGINT;
DECLARE VARIABLE V$DATE_TO DATE;
DECLARE VARIABLE V$STUDENTS INTEGER;
DECLARE VARIABLE N INTEGER;
DECLARE VARIABLE S VARCHAR(4000);
DECLARE VARIABLE V$LOC INTEGER;
begin

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  -- Добавлять или изменять можно только библиотекарю или админу
  IF(I$USER_ID <> 1 AND NOT EXISTS(
    -- Роль = библиотекарь
    SELECT FIRST 1 1
    FROM USERS U
    WHERE U.USER_ID = :I$USER_ID AND U.DATE_DEL IS NULL AND U.USER_TYPE = 11
  )
  AND NOT EXISTS(
    -- Должность = библиотекарь
    SELECT FIRST 1 1
    FROM USERS U
    JOIN LINKS L15 ON L15.PARENT_ID = U.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
    JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
    LEFT JOIN VALS V3543 ON V3543.OBJ_ID = L15.OBJ_ID AND V3543.PARAM_ID = 3543 AND V3543.IS_DEL = 0
    LEFT JOIN VALS V589 ON V589.OBJ_ID = L15.OBJ_ID AND V589.PARAM_ID = 589 AND V589.IS_DEL = 0
    WHERE U.USER_ID = :I$USER_ID AND U.DATE_DEL IS NULL AND V74.VAL IS NULL
      AND (UPPER(V3543.SVAL) LIKE '%БИБЛИОТ%' OR UPPER(V589.SVAL) LIKE '%БИБЛИОТ%')
  ))
  THEN
    EXCEPTION DATA_ERROR 'Только библиотекарь может выдавать литературу';

  SELECT FIRST 1 LP.OBJ_TYPE_ID
  FROM LINKS LP
  WHERE LP.OBJ_ID = :I$GRADE_ID AND LP.PARENT_TYPE_ID = 8 AND LP.DATE_DEL IS NULL
  INTO :V$REF_TYPE_ID;

  IF(V$REF_TYPE_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Учебный коллектив не найден';

  -- В момент добавления - определяем площадку
  I$IP = REPLACE(TRIM(REPLACE(REPLACE(I$IP, '[', ''), ']', '')), ' ', '/');
  WHILE(POSITION('/' IN I$IP) > 0) DO I$IP = SUBSTRING(I$IP FROM POSITION('/' IN I$IP) + 1);
  I$IP = TRIM(I$IP);

  FOR
    SELECT V3600.VAL, V3599.VAL
    FROM LINKS L2
    JOIN LINKS L536 ON L536.PARENT_ID = L2.OBJ_ID AND L536.OBJ_TYPE_ID = 536 AND L536.DATE_DEL IS NULL
    JOIN VALI V3600 ON V3600.OBJ_ID = L536.OBJ_ID AND V3600.PARAM_ID = 3600 AND V3600.IS_DEL = 0
    JOIN VALS V3599 ON V3599.OBJ_ID = L536.OBJ_ID AND V3599.PARAM_ID = 3599 AND V3599.IS_DEL = 0
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    ORDER BY 1
    INTO :N, :S
  DO
  BEGIN
    S = S || ',';
    IF(POSITION((I$IP || ',') IN S) > 0) THEN V$LOC = N;
  END

  IF(V$LOC IS NULL) THEN EXCEPTION DATA_ERROR 'Невозможно определить площадку библиотеки по IP адресу';

  -- Проверяем запись выдачи по данному учебнику
  -- Всегда по конкретной площадке
  SELECT FIRST 1 U.OBJ_ID, U.DATE_DEL, U.QUANTITY
  FROM LIB2_USAGE U
  WHERE U.REF_ID = :I$GRADE_ID AND U.BOOK_ID = :I$BOOK_ID AND U.LOAD_ID = :I$LOAD_ID AND U.RETURN_DATE IS NULL AND U.LOSS_DATE IS NULL AND U.LOC_INDEX = :V$LOC
  ORDER BY 2 NULLS FIRST
  INTO :OBJ_ID, :V$DT, :Q;

  SELECT B.N_FREE
  FROM LIB2_BOOKS B
  WHERE B.OBJ_ID = :I$BOOK_ID AND B.DATE_DEL IS NULL
  INTO :F;

  IF(F IS NULL) THEN EXCEPTION DATA_ERROR 'Учебник не найден';

  -- Если количество нулевое, и выдачи нет - то и не надо
  IF(I$QUANTITY = 0 AND (OBJ_ID IS NULL OR V$DT IS NOT NULL)) THEN EXIT;

  -- Для удаленной записи зануляем количество
  IF(OBJ_ID IS NOT NULL AND V$DT IS NOT NULL) THEN Q = 0;

  -- Если запись уже есть и количество уменьшается, проверяем раздачу ученикам
  IF(OBJ_ID IS NOT NULL AND I$QUANTITY < Q) THEN
  BEGIN
    SELECT COUNT(*)
    FROM LIB2_USAGE U
    WHERE U.DATE_DEL IS NULL AND U.CLASS_USAGE_ID = :OBJ_ID
    INTO :V$USED;

    IF(V$USED > I$QUANTITY) THEN EXCEPTION DATA_ERROR 'Учебники уже распределены по ученикам, уменьшить количество нельзя';
  END

  IF(OBJ_ID IS NULL) THEN Q = 0;

  -- Сколько вообще учеников по данному предмету ?
  SELECT COUNT(DISTINCT L10.OBJ_ID)
  FROM LINKS L10
  JOIN LINKS LP256 ON LP256.OBJ_ID = L10.OBJ_ID AND LP256.PARENT_TYPE_ID = 256 AND LP256.DATE_DEL IS NULL
  JOIN LINKS LP54 ON LP54.OBJ_ID = LP256.PARENT_ID AND LP54.PARENT_TYPE_ID = 54 AND LP54.DATE_DEL IS NULL
  JOIN VALL V381 ON V381.OBJ_ID = LP54.PARENT_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V381.LISTVAL_ID
  JOIN PLAN_LOADS PL ON PL.DATE_DEL IS NULL AND PL.STAGE_ID = LP54.PARENT_ID AND PL.LOAD_HOURS > 0 AND PL.OBJ_ID = :I$LOAD_ID
  JOIN PLAN_SUBJECTS PS ON PS.DATE_DEL IS NULL AND PS.OBJ_ID = PL.SUBJECT_ID AND PS.ROW_TYPE = 10 AND (PS.SUBJECT_ID = :I$SUBJECT_ID OR PS.SRC_SUBJECT_ID = :I$SUBJECT_ID)
  WHERE L10.PARENT_ID = :I$GRADE_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
  INTO :V$STUDENTS;

  -- IF(I$QUANTITY > V$STUDENTS) THEN EXCEPTION DATA_ERROR 'Количество обучающихся в коллективе по данному предмету ' || V$STUDENTS;

  -- Есть ли у нас достаток по учебникам
  --IF(Q > I$QUANTITY) THEN
  --BEGIN
    IF(F < (I$QUANTITY - Q)) THEN EXCEPTION DATA_ERROR 'Количество учебников недостаточно, в наличии ' || F || ', а требуется ' || (I$QUANTITY - Q);
  --END

  IF(OBJ_ID IS NULL) THEN
  BEGIN
    IF(EXTRACT(MONTH FROM CURRENT_DATE) < 6) THEN V$DATE_TO = '31.05.' || EXTRACT(YEAR FROM CURRENT_DATE);
      ELSE V$DATE_TO = '31.05.' || (EXTRACT(YEAR FROM CURRENT_DATE) + 1);

    INSERT INTO LIB2_USAGE
    (REF_ID, REF_TYPE_ID, BOOK_ID, INSTANCE_ID, QUANTITY, ACTION_DATE, PLAN_DATE, LOC_INDEX, LOAD_ID, USER_ID)
    VALUES (:I$GRADE_ID, :V$REF_TYPE_ID, :I$BOOK_ID, NULL, :I$QUANTITY, CURRENT_DATE, :V$DATE_TO, :V$LOC, :I$LOAD_ID, :I$USER_ID)
    RETURNING OBJ_ID INTO :OBJ_ID;
  END
  ELSE IF(V$DT IS NOT NULL OR Q <> I$QUANTITY) THEN
  BEGIN
    UPDATE LIB2_USAGE
    SET DATE_DEL = NULL, QUANTITY = :I$QUANTITY
    WHERE OBJ_ID = :OBJ_ID;
  END

  -- Пересчитываем балансы по количеству
  IF(Q <> I$QUANTITY) THEN
  BEGIN
    UPDATE LIB2_BOOKS
    SET N_FREE = N_FREE - (:I$QUANTITY - :Q)
    WHERE OBJ_ID = :I$BOOK_ID;
  END

  IF(I$QUANTITY = 0 AND OBJ_ID IS NOT NULL AND V$DT IS NULL) THEN
  BEGIN
    UPDATE LIB2_USAGE
    SET DATE_DEL = CURRENT_TIMESTAMP, RET_USER_ID = :I$USER_ID
    WHERE OBJ_ID = :OBJ_ID;

    OBJ_ID = NULL;
  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIB2_MG_PFPE (
    I$BOOK_CODE VARCHAR(40) NOT NULL,
    I$NAME VARCHAR(1000) NOT NULL,
    I$DESC VARCHAR(4000),
    I$PUB_ID BIGINT NOT NULL,
    I$SUBJECT_ID VARCHAR(100),
    I$GRADES VARCHAR(40) NOT NULL,
    I$ORDER1 VARCHAR(40),
    I$ORDER2 VARCHAR(40),
    I$F1 VARCHAR(10),
    I$F2 VARCHAR(10),
    I$F3 VARCHAR(10),
    I$DATE_TO VARCHAR(40))
AS
DECLARE VARIABLE P INTEGER;
DECLARE VARIABLE G1 INTEGER;
DECLARE VARIABLE G2 INTEGER;
DECLARE VARIABLE L INTEGER;
DECLARE VARIABLE D DATE;
DECLARE VARIABLE OBJ_ID BIGINT;
DECLARE VARIABLE A INTEGER;
begin

  -- Обрезаем конечную точку
  I$BOOK_CODE = REPLACE(I$BOOK_CODE, ' ', '');
  IF(RIGHT(I$BOOK_CODE, 1) = '.') THEN I$BOOK_CODE = SUBSTRING(I$BOOK_CODE FROM 1 FOR CHAR_LENGTH(I$BOOK_CODE) - 1);

  I$NAME = REPLACE(TRIM(I$NAME), '  ', '');
  I$DESC = REPLACE(TRIM(I$DESC), '  ', '');
  IF(I$DESC = '') THEN I$DESC = NULL;

  I$ORDER1 = REPLACE(TRIM(I$ORDER1), '  ', '');
  I$ORDER2 = REPLACE(TRIM(I$ORDER2), '  ', '');
  IF(I$ORDER1 = '') THEN I$ORDER1 = NULL;
  IF(I$ORDER2 = '') THEN I$ORDER2 = NULL;

  -- Потом подставим
  I$SUBJECT_ID = LOWER(TRIM(I$SUBJECT_ID));
  IF(I$SUBJECT_ID = '') THEN I$SUBJECT_ID = NULL;

  -- Диапазон классов
  P = POSITION('-' IN I$GRADES);
  IF(P > 0) THEN
  BEGIN
    G1 = SUBSTRING(I$GRADES FROM 1 FOR P - 1);
    G2 = SUBSTRING(I$GRADES FROM P + 1);
  END
  ELSE
  BEGIN
    G1 = I$GRADES;
    G2 = I$GRADES;
  END
  IF(G1 < 1 OR G1 > 12 OR G2 < 1 OR G2 > 12) THEN EXCEPTION DATA_ERROR 'Фигня с параллелями';
  IF(G1 < 5) THEN L = 22;
  ELSE IF(G1 < 9) THEN L = 26;
  ELSE L = 27;

  -- Дата
  I$DATE_TO = REPLACE(TRIM(LOWER(I$DATE_TO)), ' ', '');
  I$DATE_TO = REPLACE(REPLACE(I$DATE_TO, 'год', ''), 'до', '');
  I$DATE_TO = REPLACE(I$DATE_TO, 'января', '01');
  I$DATE_TO = REPLACE(I$DATE_TO, 'февраля', '02');
  I$DATE_TO = REPLACE(I$DATE_TO, 'марта', '03');
  I$DATE_TO = REPLACE(I$DATE_TO, 'апреля', '04');
  I$DATE_TO = REPLACE(I$DATE_TO, 'мая', '05');
  I$DATE_TO = REPLACE(I$DATE_TO, 'июня', '06');
  I$DATE_TO = REPLACE(I$DATE_TO, 'нюня', '06');
  I$DATE_TO = REPLACE(I$DATE_TO, 'июля', '07');
  I$DATE_TO = REPLACE(I$DATE_TO, 'нюля', '07');
  I$DATE_TO = REPLACE(I$DATE_TO, 'августа', '08');
  I$DATE_TO = REPLACE(I$DATE_TO, 'сентября', '09');
  I$DATE_TO = REPLACE(I$DATE_TO, 'октября', '10');
  I$DATE_TO = REPLACE(I$DATE_TO, 'ноября', '11');
  I$DATE_TO = REPLACE(I$DATE_TO, 'декабря', '12');
  D = SUBSTRING(I$DATE_TO FROM 1 FOR 2) || '.' || SUBSTRING(I$DATE_TO FROM 3 FOR 2) || '.' || SUBSTRING(I$DATE_TO FROM 5 FOR 4);

  I$F1 = LOWER(TRIM(I$F1)); -- нафиг
  I$F2 = LOWER(TRIM(I$F2));
  I$F3 = LOWER(TRIM(I$F3));
  IF(I$F2 = 'есть' OR I$F2 = 'да') THEN A = 2;
  ELSE IF(I$F3 = 'есть' OR I$F3 = 'да') THEN A = 3;
  ELSE A = 1;

  SELECT FIRST 1 L.OBJ_ID
  FROM LIB_FPE L
  WHERE L.BOOK_CODE = :I$BOOK_CODE
  INTO :OBJ_ID;

  IF(OBJ_ID IS NOT NULL) THEN
  BEGIN
    EXIT;
  END

  INSERT INTO LIB_FPE
  (SUBJECT_ID, STAGE_ID, GRADE_FROM, GRADE_TO, PUBLISHER_ID, BOOKNAME, DESCRIPTION, ATTRS, ORDER_NUM1, ORDER_NUM2, VALID_BY, BOOK_CODE)
  VALUES (:I$SUBJECT_ID, :L, :G1, :G2, :I$PUB_ID, :I$NAME, :I$DESC, :A, :I$ORDER1, :I$ORDER2, :D, :I$BOOK_CODE)
  RETURNING OBJ_ID INTO :OBJ_ID;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIB2_MOVE_CLEANUP (
    I$MOVE_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$ACC_MODE SMALLINT,
    I$USER_ID VARCHAR(40))
AS
DECLARE VARIABLE V$TYPE_ID BIGINT;
DECLARE VARIABLE V$QTY INTEGER;
DECLARE VARIABLE V$BOOK_ID BIGINT;
DECLARE VARIABLE V$FREE INTEGER;
begin

  -- I$ACC_MODE: 0 = экземпляры, 1 = пакеты

  SELECT I.TYPE_ID
  FROM LIB2_INVOICES I
  WHERE I.OBJ_ID = :I$MOVE_ID
  INTO :V$TYPE_ID;

  IF(V$TYPE_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Накладная не найдена';

  IF(V$TYPE_ID = 0) THEN
  BEGIN
    -- Приемка книги - только конкретный экземпляр
    SELECT I.BOOK_ID
    FROM LIB2_INSTANCES I
    WHERE I.OBJ_ID = :I$OBJ_ID
    INTO :V$BOOK_ID;

    IF(V$BOOK_ID IS NULL) THEN EXCEPTION DATA_ERROR 'E0000';

    IF(EXISTS(
      SELECT FIRST 1 1
      FROM LIB2_USAGE U
      WHERE U.DATE_DEL IS NULL AND U.INSTANCE_ID = :I$OBJ_ID
    ))
    THEN
      EXCEPTION DATA_ERROR 'Данный экземляр книги выдавался на руки и не может быть удален';

    V$QTY = 1;
    UPDATE LIB2_BOOKS
    SET
      N_AVAIL = N_AVAIL - :V$QTY,
      N_FREE = N_FREE - :V$QTY
    WHERE
      OBJ_ID = :V$BOOK_ID;

    UPDATE LIB2_INSTANCES
    SET DATE_DEL = CURRENT_TIMESTAMP
    WHERE OBJ_ID = :I$OBJ_ID;
  END
  ELSE IF(V$TYPE_ID = 1 OR V$TYPE_ID = 2) THEN
  BEGIN
    -- Приемка учебников и пособий
    -- Обновляем счетчики
    SELECT B.QUANTITY, B.BOOK_ID
    FROM LIB2_BATCHES B
    WHERE B.OBJ_ID = :I$OBJ_ID
    INTO :V$QTY, :V$BOOK_ID;

    IF(V$QTY IS NULL) THEN EXCEPTION DATA_ERROR 'E0001';

    SELECT B.N_FREE
    FROM LIB2_BOOKS B
    WHERE B.OBJ_ID = :V$BOOK_ID
    INTO :V$FREE;

    IF(V$FREE < V$QTY) THEN EXCEPTION DATA_ERROR 'Нестыковка по количеству, отмена приемки приведет к нехватке учебников на балансе с учетом уже выданных';

    UPDATE LIB2_BOOKS
    SET
      N_AVAIL = N_AVAIL - :V$QTY,
      N_FREE = N_FREE - :V$QTY
    WHERE
      OBJ_ID = :V$BOOK_ID;

    -- Удаляем запись зачисления
    UPDATE LIB2_BATCHES
    SET DATE_DEL = CURRENT_TIMESTAMP
    WHERE OBJ_ID = :I$OBJ_ID;
  END
  ELSE IF(V$TYPE_ID = 10 OR (V$TYPE_ID = 100 AND I$ACC_MODE = 0)) THEN
  BEGIN
    -- Списание экземпляра книги - только конкретный экземпляр, id подкладывается сразу при выборе
    -- Обновляем счетчики
    SELECT I.BOOK_ID
    FROM LIB2_INSTANCES I
    WHERE I.OBJ_ID = :I$OBJ_ID AND I.DATE_DEL IS NULL
    INTO :V$BOOK_ID;

    IF(V$BOOK_ID IS NULL) THEN EXCEPTION DATA_ERROR 'E0000';

    V$QTY = 1;
    UPDATE LIB2_BOOKS
    SET
      N_AVAIL = N_AVAIL + :V$QTY,
      N_FREE = N_FREE + :V$QTY,
      DATE_DEL = NULL
    WHERE
      OBJ_ID = :V$BOOK_ID;

    -- Отменяем списание
    UPDATE LIB2_INSTANCES
    SET INVOICE_OUT_ID = NULL, INVOICE_OUT_IDX = NULL, IS_FREE = 1
    WHERE OBJ_ID = :I$OBJ_ID;
  END
  ELSE IF(V$TYPE_ID = 11 OR V$TYPE_ID = 12 OR (V$TYPE_ID = 100 AND I$ACC_MODE = 1)) THEN
  BEGIN
    -- Списание учебников
    -- Обновляем счетчики
    SELECT B.QUANTITY, B.BOOK_ID
    FROM LIB2_BATCHES B
    WHERE B.OBJ_ID = :I$OBJ_ID AND B.DATE_DEL IS NULL
    INTO :V$QTY, :V$BOOK_ID;

    IF(V$QTY IS NULL) THEN EXCEPTION DATA_ERROR 'E0001';

    UPDATE LIB2_BOOKS
    SET
      N_AVAIL = N_AVAIL + :V$QTY,
      N_FREE = N_FREE + :V$QTY,
      DATE_DEL = NULL
    WHERE
      OBJ_ID = :V$BOOK_ID;

    -- Удаляем запись списания
    UPDATE LIB2_BATCHES
    SET DATE_DEL = CURRENT_TIMESTAMP
    WHERE OBJ_ID = :I$OBJ_ID;
  END
  ELSE IF(V$TYPE_ID = 100) THEN
  BEGIN
    -- Перемещение
    -- Сюда не попадаем никогда
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIB2_MOVE_DELETE (
    I$OBJ_ID BIGINT,
    I$IP VARCHAR(400),
    I$USER_ID VARCHAR(40))
AS
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$INV_TYPE SMALLINT;
DECLARE VARIABLE V$BOOK_ID BIGINT;
DECLARE VARIABLE S VARCHAR(1000);
DECLARE VARIABLE N INTEGER;
DECLARE VARIABLE V$LOC INTEGER;
DECLARE VARIABLE V$INV_LOC INTEGER;
DECLARE VARIABLE U BIGINT;
begin

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  SELECT FIRST 1 I.OBJ_ID, I.TYPE_ID, I.LOC_INDEX, I.USER_ACCEPTED
  FROM LIB2_INVOICES I
  WHERE I.OBJ_ID = :I$OBJ_ID AND I.DATE_DEL IS NULL
  INTO :V$OBJ_ID, :V$INV_TYPE, :V$INV_LOC, :U;

  IF(V$OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Накладная не найдена или была удалена';
  IF(U IS NOT NULL) THEN EXCEPTION DATA_ERROR 'Накладные перемещения можно удалять только после отмены перемещения';

  -- Добавлять или изменять можно только библиотекарю или админу
  IF(I$USER_ID <> 1 AND NOT EXISTS(
    -- Роль = библиотекарь
    SELECT FIRST 1 1
    FROM USERS U
    WHERE U.USER_ID = :I$USER_ID AND U.DATE_DEL IS NULL AND U.USER_TYPE = 11
  )
  AND NOT EXISTS(
    -- Должность = библиотекарь
    SELECT FIRST 1 1
    FROM USERS U
    JOIN LINKS L15 ON L15.PARENT_ID = U.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
    JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
    LEFT JOIN VALS V3543 ON V3543.OBJ_ID = L15.OBJ_ID AND V3543.PARAM_ID = 3543 AND V3543.IS_DEL = 0
    LEFT JOIN VALS V589 ON V589.OBJ_ID = L15.OBJ_ID AND V589.PARAM_ID = 589 AND V589.IS_DEL = 0
    WHERE U.USER_ID = :I$USER_ID AND U.DATE_DEL IS NULL AND V74.VAL IS NULL
      AND (UPPER(V3543.SVAL) LIKE '%БИБЛИОТ%' OR UPPER(V589.SVAL) LIKE '%БИБЛИОТ%')
  ))
  THEN
    EXCEPTION DATA_ERROR 'Только библиотекарь может удалять накладные';

  -- В момент добавления - определяем площадку
  I$IP = REPLACE(TRIM(REPLACE(REPLACE(I$IP, '[', ''), ']', '')), ' ', '/');
  WHILE(POSITION('/' IN I$IP) > 0) DO I$IP = SUBSTRING(I$IP FROM POSITION('/' IN I$IP) + 1);
  I$IP = TRIM(I$IP);

  FOR
    SELECT V3600.VAL, V3599.VAL
    FROM LINKS L2
    JOIN LINKS L536 ON L536.PARENT_ID = L2.OBJ_ID AND L536.OBJ_TYPE_ID = 536 AND L536.DATE_DEL IS NULL
    JOIN VALI V3600 ON V3600.OBJ_ID = L536.OBJ_ID AND V3600.PARAM_ID = 3600 AND V3600.IS_DEL = 0
    JOIN VALS V3599 ON V3599.OBJ_ID = L536.OBJ_ID AND V3599.PARAM_ID = 3599 AND V3599.IS_DEL = 0
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    ORDER BY 1
    INTO :N, :S
  DO
  BEGIN
    S = S || ',';
    IF(POSITION((I$IP || ',') IN S) > 0) THEN V$LOC = N;
  END

  IF(V$LOC IS NULL) THEN EXCEPTION DATA_ERROR 'Невозможно определить площадку библиотеки по IP адресу';
  IF(V$LOC <> V$INV_LOC) THEN EXCEPTION DATA_ERROR 'Нельзя удалять накладную чужой площадки библиотеки';

  -- Проверяем что литература не находится на руках и не списана
  -- Поступление книг, а также учебников в случае персонифицированного учета
  -- Списание можно отменять всегда
  S = NULL;
  SELECT FIRST 1 B.OBJ_ID, B.BOOK_NAME
  FROM LIB2_INSTANCES BI
  JOIN LIB2_BOOKS B ON B.OBJ_ID = BI.BOOK_ID AND B.DATE_DEL IS NULL
  WHERE BI.DATE_DEL IS NULL AND BI.INVOICE_IN_ID = :I$OBJ_ID AND BI.IS_FREE <> 1 AND :V$INV_TYPE = 0
  UNION
  SELECT FIRST 1 B.OBJ_ID, B.BOOK_NAME
  FROM LIB2_BATCHES BT
  JOIN LIB2_BOOKS B ON B.OBJ_ID = BT.BOOK_ID AND B.DATE_DEL IS NULL AND B.N_FREE < BT.QUANTITY
  WHERE BT.DATE_DEL IS NULL AND BT.INVOICE_IN_ID = :I$OBJ_ID AND :V$INV_TYPE IN (1, 2)
  INTO :V$BOOK_ID, :S;

  IF(S IS NOT NULL) THEN EXCEPTION DATA_ERROR 'Как минимум одна из записей по данной накладной числится выданной или списанной, необходимо вернуть все экземпляры, либо отменить списание: ' || S;

  -- В случае отмены списания надо восстановить удаленные каталожные записи в LIB2_BOOKS
  -- !!!

  -- При удалении движения необходимо удалить все строки этого движения
  FOR
    -- удаляем строки поэкземплярного учета
    SELECT I.OBJ_ID, 0
    FROM LIB2_INSTANCES I
    WHERE (I.INVOICE_IN_ID = :I$OBJ_ID OR I.INVOICE_OUT_ID = :I$OBJ_ID) AND I.DATE_DEL IS NULL
    -- удаляем строки движения учебников
    UNION
    SELECT B.OBJ_ID, 1
    FROM LIB2_BATCHES B
    WHERE (B.INVOICE_IN_ID = :I$OBJ_ID OR B.INVOICE_OUT_ID = :I$OBJ_ID) AND B.DATE_DEL IS NULL
    INTO :V$OBJ_ID, :N
  DO
  BEGIN
    EXECUTE PROCEDURE LIB2_MOVE_CLEANUP(:I$OBJ_ID, :V$OBJ_ID, :N, :I$USER_ID);
  END

  -- удаляем саму запись движения
  UPDATE LIB2_INVOICES
  SET DATE_DEL = CURRENT_TIMESTAMP
  WHERE OBJ_ID = :I$OBJ_ID;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIB2_MOVE_GET (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$TYPE_ID BIGINT;
DECLARE VARIABLE V$ACTION_DATE DATE;
DECLARE VARIABLE V$ACTION_NUM VARCHAR(100);
DECLARE VARIABLE V$DOCUMENT_DATE DATE;
DECLARE VARIABLE V$DOCUMENT_NUM VARCHAR(100);
DECLARE VARIABLE S VARCHAR(1000);
DECLARE VARIABLE S2 VARCHAR(400);
DECLARE VARIABLE V$CONTRAGENT_ID BIGINT;
DECLARE VARIABLE V$USER_ID BIGINT;
DECLARE VARIABLE V$REASON_ID BIGINT;
DECLARE VARIABLE V$IDX INTEGER;
DECLARE VARIABLE V$BOOK_ID BIGINT;
DECLARE VARIABLE Q INTEGER;
DECLARE VARIABLE V$PRICE FLOAT;
DECLARE VARIABLE V$TOTAL_SUM FLOAT;
DECLARE VARIABLE V$CODE VARCHAR(40);
DECLARE VARIABLE V$LOC INTEGER;
DECLARE VARIABLE Y INTEGER;
DECLARE VARIABLE V$DEST_INDEX SMALLINT;
DECLARE VARIABLE V$USER_ACCEPTED BIGINT;
begin

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  SELECT I.OBJ_ID, I.TYPE_ID, I.ACTION_DATE, I.ACTION_NUM, I.DOCUMENT_DATE, I.DOCUMENT_NUM, I.COMMENTS, I.CONTRAGENT_ID, I.REASON_ID, I.LOC_INDEX, I.USER_ID,
    I.DEST_INDEX, I.USER_ACCEPTED
  FROM LIB2_INVOICES I
  WHERE I.DATE_DEL IS NULL AND I.OBJ_ID = :I$OBJ_ID
  INTO :V$OBJ_ID, :V$TYPE_ID, :V$ACTION_DATE, :V$ACTION_NUM, :V$DOCUMENT_DATE, :V$DOCUMENT_NUM, :S, :V$CONTRAGENT_ID, :V$REASON_ID, :V$LOC, :V$USER_ID,
    :V$DEST_INDEX, :V$USER_ACCEPTED;

  IF(I$OBJ_ID IS NOT NULL AND V$OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Накладная не найдена или была удалена';

  -- Добавлять или изменять можно только библиотекарю или админу
  IF(I$OBJ_ID IS NULL) THEN
  BEGIN
    IF(I$USER_ID <> 1 AND NOT EXISTS(
      -- Роль = библиотекарь
      SELECT FIRST 1 1
      FROM USERS U
      WHERE U.USER_ID = :I$USER_ID AND U.DATE_DEL IS NULL AND U.USER_TYPE = 11
    )
    AND NOT EXISTS(
      -- Должность = библиотекарь
      SELECT FIRST 1 1
      FROM USERS U
      JOIN LINKS L15 ON L15.PARENT_ID = U.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
      JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
      LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
      LEFT JOIN VALS V3543 ON V3543.OBJ_ID = L15.OBJ_ID AND V3543.PARAM_ID = 3543 AND V3543.IS_DEL = 0
      LEFT JOIN VALS V589 ON V589.OBJ_ID = L15.OBJ_ID AND V589.PARAM_ID = 589 AND V589.IS_DEL = 0
      WHERE U.USER_ID = :I$USER_ID AND U.DATE_DEL IS NULL AND V74.VAL IS NULL
        AND (UPPER(V3543.SVAL) LIKE '%БИБЛИОТ%' OR UPPER(V589.SVAL) LIKE '%БИБЛИОТ%')
    ))
    THEN
      EXCEPTION DATA_ERROR 'Только библиотекарь может вносить накладные';
  END

  TAG_NAME = 'id';
  VAL = I$OBJ_ID;
  SUSPEND;

  TAG_NAME = 'type_id';
  VAL = V$TYPE_ID;
  SUSPEND;

  TAG_NAME = 'action_date';
  IF(V$ACTION_DATE IS NULL) THEN V$ACTION_DATE = CURRENT_DATE;
  VAL = (SELECT VAL FROM DATE2ISO(:V$ACTION_DATE));
  SUSPEND;

  TAG_NAME = 'action_num';
  VAL = V$ACTION_NUM;
  SUSPEND;

  TAG_NAME = 'document_date';
  VAL = (SELECT VAL FROM DATE2ISO(:V$DOCUMENT_DATE));
  SUSPEND;

  TAG_NAME = 'document_num';
  VAL = V$DOCUMENT_NUM;
  SUSPEND;

  TAG_NAME = 'comments';
  VAL = S;
  SUSPEND;

  TAG_NAME = 'loc_index';
  VAL = V$LOC;
  SUSPEND;

  TAG_NAME = 'user_id';
  VAL = V$USER_ID;
  SUSPEND;

  TAG_NAME = 'user_name';
  VAL = NULL;
  SELECT FIRST 1 COALESCE(C.CAPTION, U.USER_NAME)
  FROM USERS U
  LEFT JOIN OBJECT_CAPTION_GET(U.OBJ_ID) C ON U.OBJ_ID IS NOT NULL
  WHERE U.USER_ID = :V$USER_ID
  INTO :VAL;
  SUSPEND;

  -- При списании пустую строку (списание в утиль) добавляем уже на фронте
  TAG_NAME = 'contragent_id:values:value';
  VAL = V$CONTRAGENT_ID;
  SUSPEND;
  TAG_NAME = 'contragent_id:selection::json&colon;array';
  VAL = 1;
  SUSPEND;
    TAG_NAME = 'contragent_id:selection:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'contragent_id:selection:r:id';
    VAL = '*';
    SUSPEND;
    TAG_NAME = 'contragent_id:selection:r:value';
    VAL = 'Не указан';
    SUSPEND;
  FOR
    SELECT LV.LISTVAL_ID, LV.VAL, LV.SVAL
    FROM LIB2_LISTVALS LV
    WHERE LV.DATE_DEL IS NULL AND LV.LIST_ID = 4
    INTO :V$OBJ_ID, :S, :S2
  DO
  BEGIN
    TAG_NAME = 'contragent_id:selection:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'contragent_id:selection:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'contragent_id:selection:r:value';
    IF(S2 IS NULL) THEN VAL = S;
    ELSE VAL = S2 || ' ' || S; -- Добавляем ИНН
    SUSPEND;
  END

  -- Это поле актуально только при списании
  TAG_NAME = 'reason_id:values:value';
  VAL = V$REASON_ID;
  SUSPEND;
  TAG_NAME = 'reason_id:selection::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT LISTVAL_ID, VAL
    FROM LISTVALS_LIST(384)
    WHERE IS_DEL = 0
    INTO :V$OBJ_ID, :S
  DO
  BEGIN
    TAG_NAME = 'reason_id:selection:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'reason_id:selection:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'reason_id:selection:r:value';
    VAL = S;
    SUSPEND;
  END

  TAG_NAME = 'dest_index';
  VAL = V$DEST_INDEX;
  SUSPEND;

  TAG_NAME = 'user_accepted';
  VAL = V$USER_ACCEPTED;
  SUSPEND;

  TAG_NAME = 'user_accepted_name';
  VAL = NULL;
  IF(V$USER_ACCEPTED IS NOT NULL) THEN
  SELECT FIRST 1 COALESCE(C.CAPTION, U.USER_NAME)
  FROM USERS U
  LEFT JOIN OBJECT_CAPTION_GET(U.OBJ_ID) C ON U.OBJ_ID IS NOT NULL
  WHERE U.DATE_DEL IS NULL AND U.USER_ID = :V$USER_ACCEPTED
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'items::json&colon;array';
  VAL = 1;
  SUSPEND;
  V$LOC = 0;
  V$TOTAL_SUM = 0;
  FOR
    SELECT I.OBJ_ID, I.INVOICE_IN_IDX, I.BOOK_ID, B.BOOK_NAME || COALESCE(' ' || B.PART_NUM || ' часть', ' ' || B.PART_NAME, ''),
      COALESCE(LV.VAL, B.AUTHORS), B.PUB_YEAR, 1, I.SRC_COST, I.INV_CODE
    FROM LIB2_INSTANCES I
    JOIN LIB2_BOOKS B ON B.OBJ_ID = I.BOOK_ID
    LEFT JOIN LIB2_LISTVALS LV ON LV.LISTVAL_ID = B.AUTHOR_ID
    WHERE I.DATE_DEL IS NULL AND I.INVOICE_IN_ID = :I$OBJ_ID AND :V$TYPE_ID = 0
    UNION
    SELECT I.OBJ_ID, I.INVOICE_OUT_IDX, I.BOOK_ID, B.BOOK_NAME || COALESCE(' ' || B.PART_NUM || ' часть', ' ' || B.PART_NAME, ''),
      COALESCE(LV.VAL, B.AUTHORS), B.PUB_YEAR, 1, I.CURRENT_COST, I.INV_CODE
    FROM LIB2_INSTANCES I
    JOIN LIB2_BOOKS B ON B.OBJ_ID = I.BOOK_ID
    LEFT JOIN LIB2_LISTVALS LV ON LV.LISTVAL_ID = B.AUTHOR_ID
    WHERE I.DATE_DEL IS NULL AND I.INVOICE_OUT_ID = :I$OBJ_ID AND :V$TYPE_ID = 10
    UNION
    SELECT BT.OBJ_ID, BT.INVOICE_IN_IDX, BT.BOOK_ID, B.BOOK_NAME || ' (' || B.STAGE_NUM || ' кл.)' || COALESCE(' ' || B.PART_NUM || ' часть', ' ' || B.PART_NAME, ''),
      COALESCE(LV.VAL, B.AUTHORS), B.PUB_YEAR, BT.QUANTITY, BT.CURRENT_PRICE, NULL
    FROM LIB2_BATCHES BT
    JOIN LIB2_BOOKS B ON B.OBJ_ID = BT.BOOK_ID
    LEFT JOIN LIB2_LISTVALS LV ON LV.LISTVAL_ID = B.AUTHOR_ID
    WHERE BT.DATE_DEL IS NULL AND BT.INVOICE_IN_ID = :I$OBJ_ID AND :V$TYPE_ID IN (1, 2)
    UNION
    SELECT BT.OBJ_ID, BT.INVOICE_OUT_IDX, BT.BOOK_ID, B.BOOK_NAME || ' (' || B.STAGE_NUM || ' кл.)' || COALESCE(' ' || B.PART_NUM || ' часть', ' ' || B.PART_NAME, ''),
      COALESCE(LV.VAL, B.AUTHORS), B.PUB_YEAR, BT.QUANTITY, BT.CURRENT_PRICE, NULL
    FROM LIB2_BATCHES BT
    JOIN LIB2_BOOKS B ON B.OBJ_ID = BT.BOOK_ID
    LEFT JOIN LIB2_LISTVALS LV ON LV.LISTVAL_ID = B.AUTHOR_ID
    WHERE BT.DATE_DEL IS NULL AND BT.INVOICE_OUT_ID = :I$OBJ_ID AND :V$TYPE_ID IN (11, 12, 100)
    ORDER BY 2
    INTO :V$OBJ_ID, :V$IDX, :V$BOOK_ID, :S, :S2,
      :Y, :Q, :V$PRICE, :V$CODE
  DO
  BEGIN
    TAG_NAME = 'items:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'items:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'items:r:book_id';
    VAL = V$BOOK_ID;
    SUSPEND;
    TAG_NAME = 'items:r:index';
    VAL = V$IDX;
    SUSPEND;
    TAG_NAME = 'items:r:quantity';
    VAL = Q;
    SUSPEND;
    TAG_NAME = 'items:r:price';
    VAL = CAST(V$PRICE AS NUMERIC(18, 2));
    SUSPEND;
    TAG_NAME = 'items:r:name';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'items:r:author';
    VAL = S2;
    SUSPEND;
    TAG_NAME = 'items:r:pub_year';
    VAL = Y;
    SUSPEND;
    TAG_NAME = 'items:r:inv_code';
    VAL = V$CODE;
    SUSPEND;
    V$LOC = V$LOC + 1;
    V$TOTAL_SUM = V$TOTAL_SUM + V$PRICE;
  END

  TAG_NAME = 'total_sum';
  VAL = V$TOTAL_SUM;
  SUSPEND;
  TAG_NAME = 'total_count';
  VAL = V$LOC;
  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIB2_MOVE_ITEM_IDS (
    I$OBJ_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT)
AS
DECLARE VARIABLE V$TYPE_ID BIGINT;
begin

  SELECT I.TYPE_ID
  FROM LIB2_INVOICES I
  WHERE I.OBJ_ID = :I$OBJ_ID
  INTO :V$TYPE_ID;

  FOR
    SELECT I.OBJ_ID
    FROM LIB2_INSTANCES I
    WHERE I.DATE_DEL IS NULL AND I.INVOICE_IN_ID = :I$OBJ_ID AND :V$TYPE_ID = 0
    UNION
    SELECT I.OBJ_ID
    FROM LIB2_INSTANCES I
    JOIN LIB2_BOOKS B ON B.OBJ_ID = I.BOOK_ID
    JOIN LIB2_LISTVALS LV ON LV.LISTVAL_ID = B.AUTHOR_ID
    WHERE I.DATE_DEL IS NULL AND I.INVOICE_OUT_ID = :I$OBJ_ID AND :V$TYPE_ID = 10
    UNION
    SELECT BT.OBJ_ID
    FROM LIB2_BATCHES BT
    WHERE BT.DATE_DEL IS NULL AND BT.INVOICE_IN_ID = :I$OBJ_ID AND :V$TYPE_ID = 1
    UNION
    SELECT BT.OBJ_ID
    FROM LIB2_BATCHES BT
    WHERE BT.DATE_DEL IS NULL AND BT.INVOICE_OUT_ID = :I$OBJ_ID AND :V$TYPE_ID = 11
    INTO :OBJ_ID
  DO
  BEGIN
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIB2_MOVE_ITEM_SET (
    I$MOVE_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$BOOK_ID BIGINT,
    I$QTY INTEGER,
    I$PRICE FLOAT,
    I$INDEX INTEGER,
    I$IP VARCHAR(400),
    I$USER_ID VARCHAR(40))
RETURNS (
    OBJ_ID BIGINT)
AS
DECLARE VARIABLE V$TYPE_ID BIGINT;
DECLARE VARIABLE N INTEGER;
DECLARE VARIABLE V$QTY INTEGER;
DECLARE VARIABLE V$FREE INTEGER;
DECLARE VARIABLE V$INVOICE_ID BIGINT;
DECLARE VARIABLE V$INDEX INTEGER;
DECLARE VARIABLE V$INV BIGINT;
DECLARE VARIABLE V$PRICE FLOAT;
DECLARE VARIABLE V$MOVE_LOC INTEGER;
DECLARE VARIABLE V$LOC INTEGER;
DECLARE VARIABLE V$LOC_INDEX INTEGER;
DECLARE VARIABLE V$ACTNUM VARCHAR(100);
DECLARE VARIABLE V$ACC_MODE SMALLINT;
DECLARE VARIABLE S VARCHAR(4000);
begin

  SELECT I.TYPE_ID, I.LOC_INDEX, I.ACTION_NUM
  FROM LIB2_INVOICES I
  WHERE I.OBJ_ID = :I$MOVE_ID
  INTO :V$TYPE_ID, :V$MOVE_LOC, :V$ACTNUM;

  IF(V$TYPE_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Накладная не найдена';
  IF(I$QTY IS NULL OR I$QTY <= 0) THEN EXCEPTION DATA_ERROR 'Недопустимое количество изданий';
  IF(I$PRICE < 0) THEN EXCEPTION DATA_ERROR 'Цена должна быть положительным числом';
  IF(I$PRICE IS NULL AND V$ACTNUM <> 'УЧЕБНИКИ') THEN EXCEPTION DATA_ERROR 'Должна быть указана цена (без цены можно внести только первичное приходование остатков учебников)';

  -- В момент добавления - определяем площадку
  I$IP = REPLACE(TRIM(REPLACE(REPLACE(I$IP, '[', ''), ']', '')), ' ', '/');
  WHILE(POSITION('/' IN I$IP) > 0) DO I$IP = SUBSTRING(I$IP FROM POSITION('/' IN I$IP) + 1);
  I$IP = TRIM(I$IP);

  FOR
    SELECT V3600.VAL, V3599.VAL
    FROM LINKS L2
    JOIN LINKS L536 ON L536.PARENT_ID = L2.OBJ_ID AND L536.OBJ_TYPE_ID = 536 AND L536.DATE_DEL IS NULL
    JOIN VALI V3600 ON V3600.OBJ_ID = L536.OBJ_ID AND V3600.PARAM_ID = 3600 AND V3600.IS_DEL = 0
    JOIN VALS V3599 ON V3599.OBJ_ID = L536.OBJ_ID AND V3599.PARAM_ID = 3599 AND V3599.IS_DEL = 0
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    ORDER BY 1
    INTO :N, :S
  DO
  BEGIN
    S = S || ',';
    IF(POSITION((I$IP || ',') IN S) > 0) THEN V$LOC = N;
  END

  IF(V$LOC IS NULL) THEN EXCEPTION DATA_ERROR 'Невозможно определить площадку библиотеки по IP адресу';
  IF(V$MOVE_LOC <> V$LOC) THEN EXCEPTION DATA_ERROR 'Накладная относится к другой площадке, нельзя внести изменения';

  -- Для накладной перемещения может быть микс типов, определяем по самому изданию
  -- Пакетно: учебники и пособия
  IF(V$TYPE_ID = 100) THEN
  BEGIN
    V$ACC_MODE = 0;
    SELECT FIRST 1 1
    FROM LIB2_BOOKS B
    WHERE B.OBJ_ID = :I$BOOK_ID AND B.OBJ_TYPE IN (18712, 18714)
    INTO :V$ACC_MODE;
  END

  IF(V$TYPE_ID = 0) THEN
  BEGIN
    -- Приемка книги
    -- Если книга уже есть - количество по ней менять нельзя, только цену
    IF(I$OBJ_ID IS NULL) THEN
    BEGIN
      -- Просто добавляем экземпляры книги в нужном количестве без дополнительных проверок
      IF(I$QTY > 100) THEN EXCEPTION DATA_ERROR 'Слишком большое количество изданий';

      SELECT MAX(I.INV_VALUE)
      FROM LIB2_INSTANCES I
      INTO :V$INV;
      -- Нумерацию начинаем с 10000
      IF(V$INV IS NULL) THEN V$INV = 10000; ELSE V$INV = V$INV + 1;

      N = 1;
      WHILE(N <= I$QTY) DO
      BEGIN
        -- Тут будет несколько OBJ_ID, наружу выдадим только последний - нам они все равно для подчистки не нужны
        INSERT INTO LIB2_INSTANCES
        (BOOK_ID, INVOICE_IN_ID, IS_FREE, INVOICE_IN_IDX, INV_VALUE, INV_CODE, SRC_COST, STATE_ID, LOC_INDEX)
        VALUES (:I$BOOK_ID, :I$MOVE_ID, 1, :I$INDEX, :V$INV, :V$INV, :I$PRICE, 18723, :V$LOC) -- состояие = новая
        RETURNING OBJ_ID INTO :OBJ_ID;

        N = N + 1;
        V$INV = V$INV + 1;
      END

      -- Обновляем общее количество, и если было удаление - отменяем его (появились новые экземпляры)
      UPDATE LIB2_BOOKS
      SET
        DATE_DEL = NULL,
        N_AVAIL = N_AVAIL + :I$QTY,
        N_FREE = N_FREE + :I$QTY
      WHERE
        OBJ_ID = :I$BOOK_ID;
    END
    ELSE
    BEGIN
      -- Корректируем только цену и номер строки, количество всегда 1 штука
      OBJ_ID = I$OBJ_ID;

      -- Это вообще книга из нашей накладной ?
      -- !!!

      UPDATE LIB2_INSTANCES
      SET SRC_COST = :I$PRICE, INVOICE_IN_IDX = :I$INDEX
      WHERE OBJ_ID = :OBJ_ID;
    END
  END
  ELSE IF(V$TYPE_ID = 1 OR V$TYPE_ID = 2) THEN
  BEGIN
    -- Приемка учебников, пособий
    IF(I$OBJ_ID IS NULL) THEN
    BEGIN
      INSERT INTO LIB2_BATCHES
      (BOOK_ID, INVOICE_IN_ID, QUANTITY, CURRENT_PRICE, INVOICE_IN_IDX, LOC_INDEX)
      VALUES (:I$BOOK_ID, :I$MOVE_ID, :I$QTY, :I$PRICE, :I$INDEX, :V$LOC)
      RETURNING OBJ_ID INTO :OBJ_ID;

      -- Обновляем общее количество, и если было удаление - отменяем его (появились новые экземпляры)
      UPDATE LIB2_BOOKS
      SET
        DATE_DEL = NULL,
        N_AVAIL = N_AVAIL + :I$QTY,
        N_FREE = N_FREE + :I$QTY
      WHERE
        OBJ_ID = :I$BOOK_ID;
    END        
    ELSE
    BEGIN
      OBJ_ID = I$OBJ_ID;
      SELECT B.QUANTITY, BB.N_FREE
      FROM LIB2_BATCHES B
      JOIN LIB2_BOOKS BB ON BB.OBJ_ID = B.BOOK_ID
      WHERE B.OBJ_ID = :I$OBJ_ID AND B.INVOICE_IN_ID = :I$MOVE_ID AND B.BOOK_ID = :I$BOOK_ID AND B.DATE_DEL IS NULL
      INTO :V$QTY, :V$FREE;
      IF(V$QTY IS NULL) THEN EXCEPTION DATA_ERROR 'Запись приемки не найдена';
      IF((V$FREE + I$QTY - V$QTY) < 0) THEN EXCEPTION DATA_ERROR 'Нестыковка по количеству, изменение количества приведет к нехватке учебников на балансе с учетом уже выданных';

      -- Корректируем количество и номер строки
      UPDATE LIB2_BATCHES
      SET QUANTITY = :I$QTY, INVOICE_IN_IDX = :I$INDEX, CURRENT_PRICE = :I$PRICE
      WHERE OBJ_ID = :I$OBJ_ID;

      -- Корректируем общее количество
      UPDATE LIB2_BOOKS
      SET
        N_AVAIL = N_AVAIL + :I$QTY - :V$QTY,
        N_FREE = N_FREE + :I$QTY - :V$QTY
      WHERE
        OBJ_ID = :I$BOOK_ID;
    END
  END
  ELSE IF(V$TYPE_ID = 10 OR (V$TYPE_ID = 100 AND V$ACC_MODE = 0)) THEN
  BEGIN
    -- Списание экземпляра книги - только конкретный экземпляр, id подкладывается сразу при выборе
    IF(I$OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не указан экземпляр издания';
    IF(I$QTY <> 1) THEN EXCEPTION DATA_ERROR 'Количество может быть только 1';
    OBJ_ID = I$OBJ_ID;

    SELECT FIRST 1 I.INVOICE_OUT_ID, I.INVOICE_OUT_IDX, I.IS_FREE, I.CURRENT_COST, I.LOC_INDEX
    FROM LIB2_INSTANCES I
    WHERE I.OBJ_ID = :I$OBJ_ID AND I.BOOK_ID = :I$BOOK_ID AND I.DATE_DEL IS NULL
    INTO :V$INVOICE_ID, :V$INDEX, :V$FREE, :V$PRICE, :V$LOC_INDEX;

    IF(V$FREE IS NULL) THEN EXCEPTION DATA_ERROR 'Экземпляр не найден';
    IF(V$INVOICE_ID <> I$MOVE_ID) THEN EXCEPTION DATA_ERROR 'Данный экземпляр уже списан по другой накладной';
    IF(V$LOC_INDEX <> V$LOC) THEN EXCEPTION DATA_ERROR 'Издание приписано к другой площадке, списание невозможно';
    IF(V$INVOICE_ID IS NULL) THEN
    BEGIN
      IF(V$FREE <> 1) THEN EXCEPTION DATA_ERROR 'Нельзя списать выданный на руки экземпляр';
      UPDATE LIB2_INSTANCES
      SET INVOICE_OUT_ID = :I$MOVE_ID, INVOICE_OUT_IDX = :I$INDEX, CURRENT_COST = :I$PRICE, IS_FREE = 0
      WHERE OBJ_ID = :OBJ_ID;

      -- Корректируем общее количество
      UPDATE LIB2_BOOKS
      SET
        N_AVAIL = N_AVAIL - :I$QTY,
        N_FREE = N_FREE - :I$QTY
      WHERE
        OBJ_ID = :I$BOOK_ID;
    END
    ELSE IF(V$INDEX <> I$INDEX OR COALESCE(:I$PRICE, -1) <> COALESCE(:V$PRICE, -1)) THEN
    BEGIN
      UPDATE LIB2_INSTANCES
      SET INVOICE_OUT_IDX = :I$INDEX, CURRENT_COST = :I$PRICE, IS_FREE = 0
      WHERE OBJ_ID = :OBJ_ID;
    END
  END
  ELSE IF(V$TYPE_ID = 11 OR V$TYPE_ID = 12 OR (V$TYPE_ID = 100 AND V$ACC_MODE = 1)) THEN
  BEGIN
    -- Списание учебников и пособий
    SELECT BB.N_FREE
    FROM LIB2_BOOKS BB
    WHERE BB.OBJ_ID = :I$BOOK_ID AND BB.DATE_DEL IS NULL
    INTO :V$FREE;

    -- Есть ли у нас достаточное количество на данной площадке ?
    -- !!!

    IF(I$OBJ_ID IS NULL) THEN
    BEGIN
      IF(V$FREE < V$QTY) THEN EXCEPTION DATA_ERROR 'Количество учебников меньше, чем запрошенное для списания количество';

      INSERT INTO LIB2_BATCHES
      (BOOK_ID, INVOICE_OUT_ID, QUANTITY, CURRENT_PRICE, INVOICE_OUT_IDX, LOC_INDEX)
      VALUES (:I$BOOK_ID, :I$MOVE_ID, :I$QTY, :I$PRICE, :I$INDEX, :V$LOC)
      RETURNING OBJ_ID INTO :OBJ_ID;

      -- Корректируем общее количество
      UPDATE LIB2_BOOKS
      SET
        N_AVAIL = N_AVAIL - :I$QTY,
        N_FREE = N_FREE - :I$QTY
      WHERE
        OBJ_ID = :I$BOOK_ID;
    END
    ELSE
    BEGIN
      SELECT B.QUANTITY
      FROM LIB2_BATCHES B
      WHERE B.OBJ_ID = :I$OBJ_ID AND B.INVOICE_OUT_ID = :I$MOVE_ID AND B.BOOK_ID = :I$BOOK_ID AND B.DATE_DEL IS NULL
      INTO :V$QTY;

      IF(V$QTY IS NULL) THEN EXCEPTION DATA_ERROR 'Запись списания не найдена';
      IF((V$FREE - (I$QTY - V$QTY)) < 0) THEN EXCEPTION DATA_ERROR 'Нестыковка по количеству, изменение количества приведет к нехватке учебников на балансе с учетом уже выданных';

      -- Корректируем количество и номер строки
      UPDATE LIB2_BATCHES
      SET QUANTITY = :I$QTY, INVOICE_OUT_IDX = :I$INDEX, CURRENT_PRICE = :I$PRICE
      WHERE OBJ_ID = :I$OBJ_ID;

      -- Корректируем общее количество
      UPDATE LIB2_BOOKS
      SET
        N_AVAIL = N_AVAIL - (:I$QTY - :V$QTY),
        N_FREE = N_FREE - (:I$QTY - :V$QTY)
      WHERE
        OBJ_ID = :I$BOOK_ID;
    END
  END
  ELSE IF(V$TYPE_ID = 100) THEN
  BEGIN
    -- Перемещение, тут могут быть и книги, и учебники
    -- Сюда не попадаем никогда, отрабатываем как списание
  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIB2_MOVE_SET (
    I$OBJ_ID BIGINT,
    I$TYPE_ID SMALLINT,
    I$ACTION_DATE DATE,
    I$ACTION_NUM VARCHAR(100),
    I$DOCUMENT_DATE DATE,
    I$DOCUMENT_NUM VARCHAR(100),
    I$REASON_ID BIGINT,
    I$CONTRAGENT_ID BIGINT,
    I$COMMENTS VARCHAR(1000),
    I$DEST_INDEX INTEGER,
    I$IP VARCHAR(400),
    I$USER_ID VARCHAR(40))
RETURNS (
    OBJ_ID BIGINT,
    TYPE_ID BIGINT)
AS
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$ACTION_DATE DATE;
DECLARE VARIABLE V$Y INTEGER;
DECLARE VARIABLE V$LOC SMALLINT;
DECLARE VARIABLE V$DI SMALLINT;
DECLARE VARIABLE V$UA BIGINT;
DECLARE VARIABLE N INTEGER;
DECLARE VARIABLE S VARCHAR(4000);
BEGIN

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  -- Добавлять или изменять можно только библиотекарю или админу
  IF(I$USER_ID <> 1 AND NOT EXISTS(
    -- Роль = библиотекарь
    SELECT FIRST 1 1
    FROM USERS U
    WHERE U.USER_ID = :I$USER_ID AND U.DATE_DEL IS NULL AND U.USER_TYPE = 11
  )
  AND NOT EXISTS(
    -- Должность = библиотекарь
    SELECT FIRST 1 1
    FROM USERS U
    JOIN LINKS L15 ON L15.PARENT_ID = U.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
    JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
    LEFT JOIN VALS V3543 ON V3543.OBJ_ID = L15.OBJ_ID AND V3543.PARAM_ID = 3543 AND V3543.IS_DEL = 0
    LEFT JOIN VALS V589 ON V589.OBJ_ID = L15.OBJ_ID AND V589.PARAM_ID = 589 AND V589.IS_DEL = 0
    WHERE U.USER_ID = :I$USER_ID AND U.DATE_DEL IS NULL AND V74.VAL IS NULL
      AND (UPPER(V3543.SVAL) LIKE '%БИБЛИОТ%' OR UPPER(V589.SVAL) LIKE '%БИБЛИОТ%')
  ))
  THEN
    EXCEPTION DATA_ERROR 'Только библиотекарь может вносить накладные';

  SELECT LV.COST
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$Y;

  IF(I$ACTION_DATE < CAST('01.09.' || V$Y AS DATE) OR (I$ACTION_DATE > CAST('31.08.' || (V$Y + 1) AS DATE))) THEN
    EXCEPTION DATA_ERROR 'Накладные можно вносить или изменять только в течение текущего учебного года';

  SELECT FIRST 1 I.OBJ_ID, I.ACTION_DATE, I.TYPE_ID, I.DEST_INDEX, I.LOC_INDEX, I.USER_ACCEPTED
  FROM LIB2_INVOICES I
  WHERE I.DATE_DEL IS NULL AND I.OBJ_ID = :I$OBJ_ID
  INTO :V$OBJ_ID, :V$ACTION_DATE, :TYPE_ID, :V$DI, :V$LOC, :V$UA;

  IF(I$OBJ_ID IS NOT NULL AND V$OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Данные не найдены или были удалены';
  IF(I$ACTION_DATE IS NULL) THEN EXCEPTION DATA_ERROR 'Не заполнена дата движения';
  IF(I$DOCUMENT_DATE > I$ACTION_DATE) THEN EXCEPTION DATA_ERROR 'Сопроводительный документ не может быть датирован позднее даты движения';
  IF(I$TYPE_ID NOT IN (0, 1, 2, 100) AND I$REASON_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Должна быть указана причина списания';
  IF(I$TYPE_ID IN (0, 1, 2) AND I$CONTRAGENT_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Должен быть указан поставщик';

  IF(I$OBJ_ID IS NULL) THEN
  BEGIN
    -- В момент добавления - определяем площадку
    I$IP = REPLACE(TRIM(REPLACE(REPLACE(I$IP, '[', ''), ']', '')), ' ', '/');
    WHILE(POSITION('/' IN I$IP) > 0) DO I$IP = SUBSTRING(I$IP FROM POSITION('/' IN I$IP) + 1);
    I$IP = TRIM(I$IP);

    FOR
      SELECT V3600.VAL, V3599.VAL
      FROM LINKS L2
      JOIN LINKS L536 ON L536.PARENT_ID = L2.OBJ_ID AND L536.OBJ_TYPE_ID = 536 AND L536.DATE_DEL IS NULL
      JOIN VALI V3600 ON V3600.OBJ_ID = L536.OBJ_ID AND V3600.PARAM_ID = 3600 AND V3600.IS_DEL = 0
      JOIN VALS V3599 ON V3599.OBJ_ID = L536.OBJ_ID AND V3599.PARAM_ID = 3599 AND V3599.IS_DEL = 0
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      ORDER BY 1
      INTO :N, :S
    DO
    BEGIN
      S = S || ',';
      IF(POSITION((I$IP || ',') IN S) > 0) THEN V$LOC = N;
    END

    IF(V$LOC IS NULL) THEN EXCEPTION DATA_ERROR 'Невозможно определить площадку библиотеки по IP адресу';
    IF(V$DI IS NOT NULL AND V$DI = V$LOC) THEN EXCEPTION DATA_ERROR 'Площадка назначения должна отличаться от текущей площадки';

    INSERT INTO LIB2_INVOICES
    (TYPE_ID, ACTION_DATE, ACTION_NUM, DOCUMENT_DATE, DOCUMENT_NUM, REASON_ID, CONTRAGENT_ID, COMMENTS, USER_ID, LOC_INDEX, DEST_INDEX)
    VALUES (:I$TYPE_ID, :I$ACTION_DATE, :I$ACTION_NUM, :I$DOCUMENT_DATE, :I$DOCUMENT_NUM, :I$REASON_ID, :I$CONTRAGENT_ID, :I$COMMENTS, :I$USER_ID, :V$LOC, :I$DEST_INDEX)
    RETURNING OBJ_ID INTO :OBJ_ID;

    TYPE_ID = I$TYPE_ID;
  END
  ELSE
  BEGIN
    OBJ_ID = I$OBJ_ID;
    IF(TYPE_ID <> I$TYPE_ID) THEN EXCEPTION DATA_ERROR 'Тип накладной не может измениться';
    IF(V$DI = V$LOC) THEN EXCEPTION DATA_ERROR 'Площадка назначения должна отличаться от текущей площадки';
    IF(V$UA IS NOT NULL) THEN EXCEPTION DATA_ERROR 'После приемки литературы накладную перемещения изменять нельзя';

    -- Тип накладной не может измениться
    -- Проверить хронологию
    IF(I$ACTION_DATE <> V$ACTION_DATE) THEN
    BEGIN
      IF(V$ACTION_DATE < CAST('01.09.' || V$Y AS DATE) OR (V$ACTION_DATE > CAST('31.08.' || (V$Y + 1) AS DATE))) THEN
        EXCEPTION DATA_ERROR 'Накладные нельзя переносить за пределы текущего учебного года';
    END

    UPDATE LIB2_INVOICES
    SET
      ACTION_DATE = :I$ACTION_DATE,
      ACTION_NUM = :I$ACTION_NUM,
      DOCUMENT_DATE = :I$DOCUMENT_DATE,
      DOCUMENT_NUM = :I$DOCUMENT_NUM,
      REASON_ID = :I$REASON_ID,
      CONTRAGENT_ID = :I$CONTRAGENT_ID,
      COMMENTS = :I$COMMENTS,
      DEST_INDEX = :I$DEST_INDEX
    WHERE
      OBJ_ID = :OBJ_ID;
  END

  SUSPEND;

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIB2_MOVE_TRANSFER (
    I$OBJ_ID BIGINT NOT NULL,
    I$IP VARCHAR(400),
    I$DEST_INDEX SMALLINT NOT NULL,
    I$ACTION VARCHAR(100) NOT NULL,
    I$USER_ID VARCHAR(40))
AS
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$TYPE_ID BIGINT;
DECLARE VARIABLE V$ACTION_DATE DATE;
DECLARE VARIABLE V$LOC SMALLINT;
DECLARE VARIABLE V$DEST_INDEX SMALLINT;
DECLARE VARIABLE V$USER_ACCEPTED BIGINT;
DECLARE VARIABLE V$Y INTEGER;
DECLARE VARIABLE IDX INTEGER;
DECLARE VARIABLE N INTEGER;
DECLARE VARIABLE S VARCHAR(1000);
DECLARE VARIABLE C INTEGER;
DECLARE VARIABLE V$CL SMALLINT;
DECLARE VARIABLE V$BOOK_ID BIGINT;
DECLARE VARIABLE V$STATE_ID BIGINT;
DECLARE VARIABLE V$INV_VALUE BIGINT;
DECLARE VARIABLE COST FLOAT;
begin

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  SELECT I.OBJ_ID, I.TYPE_ID, I.ACTION_DATE, I.LOC_INDEX, I.DEST_INDEX, I.USER_ACCEPTED
  FROM LIB2_INVOICES I
  WHERE I.DATE_DEL IS NULL AND I.OBJ_ID = :I$OBJ_ID
  INTO :V$OBJ_ID, :V$TYPE_ID, :V$ACTION_DATE, :V$LOC, :V$DEST_INDEX, :V$USER_ACCEPTED;

  SELECT LV.COST
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$Y;

  IF(V$ACTION_DATE < CAST('01.09.' || V$Y AS DATE) OR (V$ACTION_DATE > CAST('31.08.' || (V$Y + 1) AS DATE))) THEN
    EXCEPTION DATA_ERROR 'Накладные можно вносить или изменять только в течение текущего учебного года';

  IF(V$OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Накладная не найдена или была удалена';
  IF(V$TYPE_ID <> 100) THEN EXCEPTION DATA_ERROR 'Накладная не является накладной перемещения';
  IF(I$ACTION = 'accept' AND V$USER_ACCEPTED IS NOT NULL) THEN EXCEPTION DATA_ERROR 'Перемещение уже подтверждено';
  IF(I$ACTION = 'cancel' AND V$USER_ACCEPTED IS NULL) THEN EXCEPTION DATA_ERROR 'Перемещение не выполнялось или уже отменено';
  IF(I$ACTION = 'accept' AND (V$ACTION_DATE > CURRENT_DATE OR V$ACTION_DATE < DATEADD(-7 DAY TO CURRENT_DATE))) THEN
    EXCEPTION DATA_ERROR 'Перемещение должно быть подтверждено в течение 1 недели с указанной даты';

  IF(I$USER_ID <> 1 AND NOT EXISTS(
    -- Роль = библиотекарь
    SELECT FIRST 1 1
    FROM USERS U
    WHERE U.USER_ID = :I$USER_ID AND U.DATE_DEL IS NULL AND U.USER_TYPE = 11
  )
  AND NOT EXISTS(
    -- Должность = библиотекарь
    SELECT FIRST 1 1
    FROM USERS U
    JOIN LINKS L15 ON L15.PARENT_ID = U.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
    JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
    LEFT JOIN VALS V3543 ON V3543.OBJ_ID = L15.OBJ_ID AND V3543.PARAM_ID = 3543 AND V3543.IS_DEL = 0
    LEFT JOIN VALS V589 ON V589.OBJ_ID = L15.OBJ_ID AND V589.PARAM_ID = 589 AND V589.IS_DEL = 0
    WHERE U.USER_ID = :I$USER_ID AND U.DATE_DEL IS NULL AND V74.VAL IS NULL
      AND (UPPER(V3543.SVAL) LIKE '%БИБЛИОТ%' OR UPPER(V589.SVAL) LIKE '%БИБЛИОТ%')
  ))
  THEN
    EXCEPTION DATA_ERROR 'Только библиотекарь может выполнять перемещение';

  -- В момент добавления - определяем площадку
  I$IP = REPLACE(TRIM(REPLACE(REPLACE(I$IP, '[', ''), ']', '')), ' ', '/');
  WHILE(POSITION('/' IN I$IP) > 0) DO I$IP = SUBSTRING(I$IP FROM POSITION('/' IN I$IP) + 1);
  I$IP = TRIM(I$IP);

  FOR
    SELECT V3600.VAL, V3599.VAL
    FROM LINKS L2
    JOIN LINKS L536 ON L536.PARENT_ID = L2.OBJ_ID AND L536.OBJ_TYPE_ID = 536 AND L536.DATE_DEL IS NULL
    JOIN VALI V3600 ON V3600.OBJ_ID = L536.OBJ_ID AND V3600.PARAM_ID = 3600 AND V3600.IS_DEL = 0
    JOIN VALS V3599 ON V3599.OBJ_ID = L536.OBJ_ID AND V3599.PARAM_ID = 3599 AND V3599.IS_DEL = 0
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    ORDER BY 1
    INTO :N, :S
  DO
  BEGIN
    S = S || ',';
    IF(POSITION((I$IP || ',') IN S) > 0) THEN V$CL = N;
  END

  IF(V$CL IS NULL) THEN EXCEPTION DATA_ERROR 'Невозможно определить площадку библиотеки по IP адресу';
  IF(V$CL <> I$DEST_INDEX) THEN EXCEPTION DATA_ERROR 'Перемещение подтверждает или отменяет только библиотекарь, отвечающий за площадку получателя';

  IF(I$ACTION = 'accept') THEN
  BEGIN
    -- Проверять количества не нужно, экземпляры списаны уже при первоначальном сохранении
    -- Создаем только записи приемки, и возвращаем количество в доступные
    C = 1;

    FOR
      SELECT BI.BOOK_ID, BI.CURRENT_COST, BI.INV_CODE, BI.INV_VALUE, BI.STATE_ID, BI.INVOICE_OUT_IDX
      FROM LIB2_INSTANCES BI
      WHERE BI.DATE_DEL IS NULL AND BI.INVOICE_OUT_ID = :I$OBJ_ID
      INTO :V$BOOK_ID, :COST, :S, :V$INV_VALUE, :V$STATE_ID, :IDX
    DO
    BEGIN
      INSERT INTO LIB2_INSTANCES
      (BOOK_ID, SRC_COST, CURRENT_COST, INV_CODE, INV_VALUE, STATE_ID, INVOICE_IN_ID, INVOICE_IN_IDX, IS_FREE)
      VALUES (:V$BOOK_ID, :COST, :COST, :S, :V$INV_VALUE, :V$STATE_ID, :I$OBJ_ID, :IDX, 1);

      UPDATE LIB2_BOOKS
      SET N_AVAIL = N_AVAIL + 1, N_FREE = N_FREE + 1
      WHERE OBJ_ID = :V$BOOK_ID;

      C = C + 1;
    END

    FOR
      SELECT FIRST 1 BT.BOOK_ID, BT.QUANTITY, BT.CURRENT_PRICE, BT.STATE_ID, BT.INVOICE_OUT_IDX
      FROM LIB2_BATCHES BT
      WHERE BT.DATE_DEL IS NULL AND BT.INVOICE_OUT_ID = :I$OBJ_ID
      INTO :V$BOOK_ID, :N, :COST, :V$STATE_ID, :IDX
    DO
    BEGIN
      INSERT INTO LIB2_BATCHES
      (BOOK_ID, QUANTITY, CURRENT_PRICE, STATE_ID, INVOICE_IN_ID, INVOICE_IN_IDX)
      VALUES (:V$BOOK_ID, :N, :COST, :V$STATE_ID, :I$OBJ_ID, :IDX);

      UPDATE LIB2_BOOKS
      SET N_AVAIL = N_AVAIL + :N, N_FREE = N_FREE + :N
      WHERE OBJ_ID = :V$BOOK_ID;

      C = C + 1;
    END

    IF(C = 0) THEN EXCEPTION DATA_ERROR 'В накладной нет данных, нельзя подтвердить передачу изданий';

    UPDATE LIB2_INVOICES
    SET DEST_INDEX = :I$DEST_INDEX, USER_ACCEPTED = :I$USER_ID
    WHERE OBJ_ID = :I$OBJ_ID;
  END

  IF(I$ACTION = 'cancel') THEN
  BEGIN
    -- Все записи, которые передавались - должны быть свободны
    FOR
      SELECT BI.BOOK_ID, BI.OBJ_ID, BI.IS_FREE
      FROM LIB2_INSTANCES BI
      WHERE BI.DATE_DEL IS NULL AND BI.INVOICE_IN_ID = :I$OBJ_ID
      INTO :V$BOOK_ID, :V$OBJ_ID, :N
    DO
    BEGIN
      IF(N <> 1) THEN EXCEPTION DATA_ERROR 'Одно из изданий выдано на руки или утрачено, нельзя отменить: ' || (SELECT BOOK_NAME FROM LIB2_BOOKS WHERE OBJ_ID = :V$BOOK_ID);

      UPDATE LIB2_INSTANCES
      SET DATE_DEL = CURRENT_TIMESTAMP
      WHERE OBJ_ID = :V$OBJ_ID;

      UPDATE LIB2_BOOKS
      SET N_AVAIL = N_AVAIL - 1, N_FREE = N_FREE - 1
      WHERE OBJ_ID = :V$BOOK_ID;
    END

    FOR
      SELECT FIRST 1 BT.BOOK_ID, BT.QUANTITY, BT.OBJ_ID, B.N_FREE
      FROM LIB2_BATCHES BT
      JOIN LIB2_BOOKS B ON B.OBJ_ID = BT.BOOK_ID
      WHERE BT.DATE_DEL IS NULL AND BT.INVOICE_OUT_ID = :I$OBJ_ID
      INTO :V$BOOK_ID, :N, :V$OBJ_ID, :COST
    DO
    BEGIN
      IF(N > COST) THEN EXCEPTION DATA_ERROR 'Одно из изданий выдано на руки или утрачено, нельзя отменить: ' || (SELECT BOOK_NAME FROM LIB2_BOOKS WHERE OBJ_ID = :V$BOOK_ID);

      UPDATE LIB2_BATCHES
      SET DATE_DEL = CURRENT_TIMESTAMP
      WHERE OBJ_ID = :V$OBJ_ID;

      UPDATE LIB2_BOOKS
      SET N_AVAIL = N_AVAIL - :N, N_FREE = N_FREE - :N
      WHERE OBJ_ID = :V$BOOK_ID;
    END

    UPDATE LIB2_INVOICES
    SET USER_ACCEPTED = NULL
    WHERE OBJ_ID = :I$OBJ_ID;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIB2_REPORT_NX10 (
    I$USER_ID VARCHAR(40),
    I$DATE_FROM DATE,
    I$DATE_TO DATE,
    I$PARENT_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$OPTION_ID BIGINT,
    I$OPTIONS VARCHAR(1000),
    I$ZONE SMALLINT = 0)
RETURNS (
    VAL VARCHAR(4000))
AS
DECLARE VARIABLE V$CALLER_TYPE BIGINT;
DECLARE VARIABLE V$USER_TYPE SMALLINT;
DECLARE VARIABLE V$S1 VARCHAR(400);
DECLARE VARIABLE V$S2 VARCHAR(400);
DECLARE VARIABLE V$DATE DATE;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$OU_LICENCE_TYPE CHAR(1);
DECLARE VARIABLE V$ACCESS SMALLINT;
DECLARE VARIABLE N1 INTEGER;
DECLARE VARIABLE N2 INTEGER;
DECLARE VARIABLE T1 INTEGER;
DECLARE VARIABLE T2 INTEGER;
begin

  -- Школа, коллектив, персона
  SELECT TYPE_ID FROM OBJECTS WHERE OBJ_ID = :I$OBJ_ID INTO :V$CALLER_TYPE;
  SELECT STATUS FROM OU_LICENCE_TYPE INTO :V$OU_LICENCE_TYPE;

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;
  SELECT USER_TYPE FROM USERS WHERE USER_ID = :I$USER_ID INTO :V$USER_TYPE;

  VAL = '<!DOCTYPE html>';
  VAL = VAL || '<html lang="ru">';
  VAL = VAL || '<head>';
  VAL = VAL || '<meta charset="utf-8" />';
  VAL = VAL || '<style>';
  VAL = VAL || 'html { font-family: Tahoma, Verdana, Arial;';
  VAL = VAL || 'font-size: 10pt; ';
  VAL = VAL || '} ';
  VAL = VAL || '</style>';

  VAL = VAL || '</head>';
  VAL = VAL || '<body>';
  SUSPEND;

  -- Заголовок отчета
  VAL = '<div class="ui left aligned">Посещаемость</div>';
  V$S1 = (SELECT RESULT FROM DATE2STR(:I$DATE_FROM));
  V$S2 = (SELECT RESULT FROM DATE2STR(:I$DATE_TO));
  VAL = VAL || '<div class="ui left aligned">Период: ' || V$S1 || ' - ' || V$S2 || '</div>';

  T1 = 0;
  T2 = 0;
  -- Заголовок таблицы
  VAL = VAL || '<table class="ui celled striped table" cellspacing="100" cellpadding="25">';
  SUSPEND;
  VAL = '<tr class="ui center aligned">';
  VAL = VAL || '<thead>';
  VAL = VAL || '<th>Дата</th>';
  VAL = VAL || '<th>Обучающиеся</th>';
  VAL = VAL || '<th>Сотрудники</th>';
  VAL = VAL || '<th>ВСЕГО</th>';
  VAL = VAL || '</tr>';
  VAL = VAL || '</thead>';
  SUSPEND;

  FOR
    SELECT ACTION_DATE FROM
      (SELECT DISTINCT COALESCE(U.RETURN_DATE, U.ACTION_DATE) ACTION_DATE
      FROM LIB2_USAGE U
      JOIN LINKS L10 ON L10.OBJ_ID = U.REF_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL AND (:V$CALLER_TYPE <> 10 OR L10.OBJ_ID = :I$OBJ_ID) -- ученик
      JOIN LINKS L9 ON L9.OBJ_ID = L10.PARENT_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL AND (:V$CALLER_TYPE <> 9 OR L9.OBJ_ID = :I$OBJ_ID)   -- класс
      JOIN LINKS L8 ON L8.OBJ_ID = L9.PARENT_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL AND (:V$CALLER_TYPE <> 8 OR L8.OBJ_ID = :I$OBJ_ID)    -- этап
      JOIN LINKS L7 ON L7.OBJ_ID = L8.PARENT_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL AND (:V$CALLER_TYPE <> 7 OR L7.OBJ_ID = :I$OBJ_ID)    -- уровень
      WHERE U.REF_TYPE_ID = 10 AND U.ACTION_DATE >= :I$DATE_FROM AND U.ACTION_DATE <= :I$DATE_TO AND U.DATE_DEL IS NULL
      UNION
      SELECT DISTINCT COALESCE(U.RETURN_DATE, U.ACTION_DATE)
      FROM LIB2_USAGE U
      WHERE U.REF_TYPE_ID = 14 AND U.ACTION_DATE >= :I$DATE_FROM AND U.ACTION_DATE <= :I$DATE_TO
    ) ORDER BY ACTION_DATE
    INTO :V$DATE
  DO
  BEGIN
    N1 = 0;
    N2 = 0;
    SELECT COUNT(*)
    FROM LIB2_USAGE U
    WHERE U.REF_TYPE_ID = 10 AND U.ACTION_DATE = :V$DATE
    INTO :N1;
    T1 = T1 + N1;

    SELECT COUNT(*)
    FROM LIB2_USAGE U
    WHERE U.REF_TYPE_ID = 14 AND U.ACTION_DATE = :V$DATE
    INTO :N2;
    T2 = T2 + N2;

    VAL = '<tr class="ui center aligned">';
    VAL = VAL || '<td>' || (SELECT RESULT FROM DATE2STR(:V$DATE, 2)) || '</td>';
    SUSPEND;
    VAL = '<td> ' || N1 || '</td>';
    VAL = VAL ||  '<td>' || N2 || '</td>';
    N1 = N1 + N2;
    VAL = VAL ||  '<td>' || N1 || '</td>';
    VAL = VAL || '</tr>';
    SUSPEND;
  END

  VAL = '<tr class="ui center aligned">';
  VAL = VAL || '<td>ВСЕГО</td>';
  VAL = VAL || '<td>' || T1 || '</td>';
  VAL = VAL || '<td>' || T2 || '</td>';
  T1 = T1 + T2;
  VAL = VAL ||  '<td>' || T1 || '</td>';
  VAL = VAL || '</tr>';
  SUSPEND;

  VAL = '</table></body></html>';
  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIB2_REPORT_NX30 (
    I$USER_ID VARCHAR(40),
    I$DATE_FROM DATE,
    I$DATE_TO DATE,
    I$PARENT_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$OPTION_ID BIGINT,
    I$OPTIONS VARCHAR(1000),
    I$ZONE SMALLINT = 0)
RETURNS (
    VAL VARCHAR(4000))
AS
DECLARE VARIABLE V$CALLER_TYPE BIGINT;
DECLARE VARIABLE V$S1 VARCHAR(400);
DECLARE VARIABLE V$S2 VARCHAR(400);
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$USER_TYPE BIGINT;
DECLARE VARIABLE V$TYPE VARCHAR(100);
DECLARE VARIABLE V$NAME VARCHAR(400);
DECLARE VARIABLE D1 DATE;
DECLARE VARIABLE D2 DATE;
DECLARE VARIABLE V$AUTHOR VARCHAR(100);
DECLARE VARIABLE V$CLASS VARCHAR(100);
DECLARE VARIABLE V$BOOK VARCHAR(400);
DECLARE VARIABLE V$CODE VARCHAR(40);
begin
  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;
  SELECT TYPE_ID FROM OBJECTS WHERE OBJ_ID = :I$OBJ_ID INTO :V$CALLER_TYPE;
  SELECT USER_TYPE FROM USERS WHERE USER_ID = :I$USER_ID INTO :V$USER_TYPE;

  IF (I$DATE_TO IS NULL) THEN I$DATE_TO = CURRENT_DATE;

  VAL = '<!DOCTYPE html>';
  VAL = VAL || '<html lang="ru">';
  VAL = VAL || '<head>';
  VAL = VAL || '<meta charset="utf-8" />';
  VAL = VAL || '<style>';
  VAL = VAL || 'html { font-family: Tahoma, Verdana, Arial;';
  VAL = VAL || 'font-size: 10pt; ';
  VAL = VAL || '} ';
  VAL = VAL || '</style>';

  VAL = VAL || '</head>';
  VAL = VAL || '<body>';
  SUSPEND;

  -- Заголовок отчета
  VAL = '<div class="ui left aligned">Издания на руках</div>';
  V$S1 = (SELECT RESULT FROM DATE2STR(:I$DATE_FROM));
  V$S2 = (SELECT RESULT FROM DATE2STR(:I$DATE_TO));
  VAL = VAL || '<div class="ui left aligned">На дату: ' || V$S2 || '</div>';

  -- Заголовок таблицы
  VAL = VAL || '<table class="ui celled striped table" cellspacing="0" cellpadding="25">';
  SUSPEND;

  IF (V$CALLER_TYPE IN (2, 7, 8)) THEN
  BEGIN
    VAL = '<tr class="ui center aligned">';
    VAL = VAL || '<thead><th>Тип издания</th><th>Количество</th></thead>';
    VAL = VAL || '</tr>';
    SUSPEND;
    FOR
      SELECT TP.VAL, COUNT(*)
      FROM LIB2_USAGE U
      JOIN LIB2_BOOKS B ON B.OBJ_ID = U.BOOK_ID AND B.DATE_DEL IS NULL
      LEFT JOIN LISTVAL_TEXT(B.OBJ_TYPE) TP ON 1 = 1
      JOIN PERSON_MOVEMENTS M ON M.PERSON_ID = U.REF_ID AND M.DATE_DEL IS NULL AND M.GROUP_TYPE_ID IN (9, 187)
        AND (M.DATE_OUT IS NULL OR (M.DATE_OUT > :I$DATE_TO))
        AND M.OBJ_ID = (SELECT COALESCE(MAX(MM.OBJ_ID), 0) FROM PERSON_MOVEMENTS MM WHERE MM.PERSON_ID = M.PERSON_ID AND MM.DATE_DEL IS NULL
          AND MM.GROUP_TYPE_ID IN (9, 187) AND (MM.DATE_OUT IS NULL OR (MM.DATE_OUT > :I$DATE_TO)) )
      JOIN LINKS L8 ON L8.OBJ_ID = M.GROUP_ID AND L8.PARENT_TYPE_ID = 8 AND L8.DATE_DEL IS NULL AND (:V$CALLER_TYPE <> 8 OR L8.PARENT_ID = :I$OBJ_ID)    -- этап
      JOIN LINKS L7 ON L7.OBJ_ID = L8.PARENT_ID AND L7.PARENT_TYPE_ID = 7 AND L7.DATE_DEL IS NULL AND (:V$CALLER_TYPE <> 7 OR L7.PARENT_ID = :I$OBJ_ID)  -- уровень
      WHERE U.REF_TYPE_ID = 10 AND U.ACTION_DATE <= :I$DATE_TO AND U.DATE_DEL IS NULL
        AND U.RETURN_DATE IS NULL AND U.LOSS_DATE IS NULL
      GROUP BY TP.VAL
      INTO :V$S1, :V$OBJ_ID
    DO
    BEGIN
      VAL = '<tr class="ui center aligned">';
      VAL = VAL || '<td>' || V$S1 || '</td><td> ' || V$OBJ_ID || '</td></tr>';
      SUSPEND;
    END
  END
  ELSE IF (V$CALLER_TYPE IN (9, 10)) THEN
  BEGIN
    VAL = '<tr class="ui center aligned">';
    VAL = VAL || '<thead><th>Класс</th>';
    VAL = VAL || '<th>ФИО</th>';
    VAL = VAL || '<th>Тип издания</th>';
    VAL = VAL || '<th>Инвентарный номер</th>';
    VAL = VAL || '<th>Автор</th>';
    VAL = VAL || '<th>Название</th>';
    VAL = VAL || '<th>Дата выдачи</th>';
    VAL = VAL || '<th>Плановая дата возврата</th>';
    VAL = VAL || '</thead>';
    VAL = VAL || '</tr>';
    SUSPEND;

    FOR
      SELECT C.SCAPTION, FIO.NAME_FULL, TP.VAL, COALESCE(I.INV_CODE, '-'),
        COALESCE(A.VAL, '') || IIF(A.VAL IS NOT NULL AND B.AUTHORS IS NOT NULL, ',', '') || COALESCE(B.AUTHORS, ''),
        B.BOOK_NAME || COALESCE(', ' || B.PART_NUM || COALESCE(' ' || B.PART_NAME, ''), ''),
        U.ACTION_DATE, U.PLAN_DATE
      FROM LIB2_USAGE U
      JOIN LIB2_BOOKS B ON B.OBJ_ID = U.BOOK_ID AND B.DATE_DEL IS NULL
      JOIN PERSON_MOVEMENTS M ON M.PERSON_ID = U.REF_ID AND M.DATE_DEL IS NULL AND M.GROUP_TYPE_ID IN (9, 187)
        AND (M.DATE_OUT IS NULL OR (M.DATE_OUT > :I$DATE_TO))
        AND ((:V$CALLER_TYPE = 10 AND M.PERSON_ID = :I$OBJ_ID) OR (:V$CALLER_TYPE = 9 AND M.GROUP_ID = :I$OBJ_ID))
        AND M.OBJ_ID = (SELECT COALESCE(MAX(MM.OBJ_ID), 0) FROM PERSON_MOVEMENTS MM WHERE MM.PERSON_ID = M.PERSON_ID AND MM.DATE_DEL IS NULL
          AND MM.GROUP_TYPE_ID IN (9, 187) AND (MM.DATE_OUT IS NULL OR (MM.DATE_OUT > :I$DATE_TO)) )
      JOIN OBJECT_CAPTION_GET(M.GROUP_ID) C ON 1 = 1
      LEFT JOIN UT_PERSON_DESC(U.REF_ID, 0, 1) FIO ON 1 = 1
      LEFT JOIN LIB2_LISTVALS A ON A.LISTVAL_ID = B.AUTHOR_ID AND A.DATE_DEL IS NULL
      LEFT JOIN LISTVAL_TEXT(B.OBJ_TYPE) TP ON 1 = 1
      LEFT JOIN LIB2_INSTANCES I ON I.OBJ_ID = U.INSTANCE_ID AND I.DATE_DEL IS NULL
      WHERE U.REF_TYPE_ID = 10 AND U.ACTION_DATE <= :I$DATE_TO AND U.DATE_DEL IS NULL
        AND U.RETURN_DATE IS NULL AND U.LOSS_DATE IS NULL
      ORDER BY TP.VAL, FIO.NAME_FULL
      INTO :V$CLASS, :V$NAME, :V$TYPE, :V$CODE, :V$AUTHOR, V$BOOK, :D1, :D2
    DO
    BEGIN
      SELECT RESULT FROM DATE2STR(:D1) INTO :V$S1;
      SELECT RESULT FROM DATE2STR(:D2) INTO :V$S2;
      VAL = '<tr class="ui center aligned">';
      IF (D2 < CURRENT_TIMESTAMP) THEN
        VAL = '<tr class="ui error center aligned">';
      VAL = VAL || '<td>' || V$CLASS || '</td>';
      VAL = VAL || '<td>' || V$NAME || '</td>';
      VAL = VAL || '<td>' || V$TYPE || '</td>';
      VAL = VAL || '<td>' || V$CODE || '</td>';
      VAL = VAL || '<td>' || V$AUTHOR || '</td>';
      VAL = VAL || '<td>' || V$BOOK || '</td>';
      VAL = VAL || '<td>' || V$S1 || '</td>';
      VAL = VAL || '<td>' || V$S2 || '</td>';
      VAL = VAL || '</tr>';
      SUSPEND;
    END
  END
  ELSE IF (V$CALLER_TYPE = 14 OR I$OBJ_ID = 0) THEN
  BEGIN
    VAL = '<tr class="ui center aligned">';
    VAL = VAL || '<th>ФИО</th>';
    VAL = VAL || '<th>Тип издания</th>';
    VAL = VAL || '<th>Инвентарный номер</th>';
    VAL = VAL || '<th>Автор</th>';
    VAL = VAL || '<th>Название</th>';
    VAL = VAL || '<th>Дата выдачи</th>';
    VAL = VAL || '<th>Плановая дата возврата</th>';
    VAL = VAL || '</thead>';
    VAL = VAL || '</tr>';
    SUSPEND;

    FOR
      SELECT FIO.NAME_FULL, TP.VAL, COALESCE(I.INV_CODE, '-'),
        COALESCE(A.VAL, '') || IIF(A.VAL IS NOT NULL AND B.AUTHORS IS NOT NULL, ',', '') || COALESCE(B.AUTHORS, ''),
        B.BOOK_NAME || COALESCE(', ' || B.PART_NUM || COALESCE(' ' || B.PART_NAME, ''), ''),
        U.ACTION_DATE, U.PLAN_DATE
      FROM LIB2_USAGE U
      LEFT JOIN UT_PERSON_DESC(U.REF_ID, :I$ZONE, 1) FIO ON 1 = 1
      JOIN LIB2_BOOKS B ON B.OBJ_ID = U.BOOK_ID AND B.DATE_DEL IS NULL
      LEFT JOIN LIB2_LISTVALS A ON A.LISTVAL_ID = B.AUTHOR_ID AND A.DATE_DEL IS NULL
      LEFT JOIN LISTVAL_TEXT(B.OBJ_TYPE) TP ON 1 = 1
      LEFT JOIN LIB2_INSTANCES I ON I.OBJ_ID = U.INSTANCE_ID AND I.DATE_DEL IS NULL
      WHERE U.REF_TYPE_ID = 14 AND U.ACTION_DATE <= :I$DATE_TO AND U.DATE_DEL IS NULL
        AND U.RETURN_DATE IS NULL AND U.LOSS_DATE IS NULL
        AND (:I$OBJ_ID = 0 OR :I$OBJ_ID = U.REF_ID)
      ORDER BY TP.VAL, FIO.NAME_FULL
      INTO :V$NAME, :V$TYPE, :V$CODE, :V$AUTHOR, V$BOOK, :D1, :D2
    DO
    BEGIN
      SELECT RESULT FROM DATE2STR(:D1) INTO :V$S1;
      SELECT RESULT FROM DATE2STR(:D2) INTO :V$S2;
      VAL = '<tr class="ui center aligned">';
      IF (D2 < CURRENT_TIMESTAMP) THEN
        VAL = '<tr class="ui error center aligned">';
      VAL = VAL || '<td>' || V$NAME || '</td>';
      VAL = VAL || '<td>' || V$TYPE || '</td>';
      VAL = VAL || '<td>' || V$CODE || '</td>';
      VAL = VAL || '<td>' || V$AUTHOR || '</td>';
      VAL = VAL || '<td>' || V$BOOK || '</td>';
      VAL = VAL || '<td>' || V$S1 || '</td>';
      VAL = VAL || '<td>' || V$S2 || '</td>';
      VAL = VAL || '</tr>';
      SUSPEND;
    END
  END

  VAL = '</table></body></html>';
  SUSPEND;
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIB2_REPORT_NX50 (
    I$USER_ID VARCHAR(40),
    I$DATE_FROM DATE,
    I$DATE_TO DATE,
    I$PARENT_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$OPTION_ID BIGINT,
    I$OPTIONS VARCHAR(1000),
    I$ZONE SMALLINT = 0)
RETURNS (
    VAL VARCHAR(4000))
AS
DECLARE VARIABLE V$CALLER_TYPE BIGINT;
DECLARE VARIABLE V$S1 VARCHAR(400);
DECLARE VARIABLE V$S2 VARCHAR(400);
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$USER_TYPE BIGINT;
begin
  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;
  SELECT TYPE_ID FROM OBJECTS WHERE OBJ_ID = :I$OBJ_ID INTO :V$CALLER_TYPE;
  SELECT USER_TYPE FROM USERS WHERE USER_ID = :I$USER_ID INTO :V$USER_TYPE;

  VAL = '<!DOCTYPE html>';
  VAL = VAL || '<html lang="ru">';
  VAL = VAL || '<head>';
  VAL = VAL || '<meta charset="utf-8" />';
  VAL = VAL || '<style>';
  VAL = VAL || 'html { font-family: Tahoma, Verdana, Arial;';
  VAL = VAL || 'font-size: 10pt; ';
  VAL = VAL || '} ';
  VAL = VAL || '</style>';

  VAL = VAL || '</head>';
  VAL = VAL || '<body>';
  SUSPEND;

  -- Заголовок отчета
  VAL = '<div class="ui left aligned">Посещаемость</div>';
  V$S1 = (SELECT RESULT FROM DATE2STR(:I$DATE_FROM));
  V$S2 = (SELECT RESULT FROM DATE2STR(:I$DATE_TO));
  VAL = VAL || '<div class="ui left aligned">Период: ' || V$S1 || ' - ' || V$S2 || '</div>';

  -- Заголовок таблицы
  VAL = VAL || '<table class="ui celled striped table" cellspacing="0" cellpadding="25">';
  SUSPEND;

  VAL = '<tr class="ui center aligned">';
  VAL = VAL || '<thead>';
  VAL = VAL || '<th>ФИО</th>';
  VAL = VAL || '<th>Класс</th>';
  VAL = VAL || '<th>Количество посещений</th>';
  VAL = VAL || '</tr>';
  VAL = VAL || '</thead>';
  SUSPEND;
  FOR
    SELECT CLASS.SCAPTION, FIO.NAME_FULL, SUM(S.ACTIVITY)
    FROM (
      SELECT U.REF_ID, U.ACTION_DATE, M.GROUP_ID, 1 ACTIVITY
      FROM LIB2_USAGE U
      JOIN PERSON_MOVEMENTS M ON M.PERSON_ID = U.REF_ID AND M.GROUP_TYPE_ID IN (9, 187)
        AND (:V$CALLER_TYPE NOT IN (9, 10) OR (:V$CALLER_TYPE = 9 AND M.GROUP_ID = :I$OBJ_ID) OR (:V$CALLER_TYPE = 10 AND M.PERSON_ID = :I$OBJ_ID))    -- класс, персона
      JOIN LINKS L8 ON L8.OBJ_ID = M.GROUP_ID AND L8.PARENT_TYPE_ID = 8 AND L8.DATE_DEL IS NULL AND (:V$CALLER_TYPE <> 8 OR L8.PARENT_ID = :I$OBJ_ID)    -- этап
      JOIN LINKS L7 ON L7.OBJ_ID = L8.PARENT_ID AND L7.PARENT_TYPE_ID = 7 AND L7.DATE_DEL IS NULL AND (:V$CALLER_TYPE <> 7 OR L7.PARENT_ID = :I$OBJ_ID)  -- уровень
      WHERE U.REF_TYPE_ID = 10 AND U.ACTION_DATE >= :I$DATE_FROM AND U.ACTION_DATE <= :I$DATE_TO AND U.DATE_DEL IS NULL
        AND M.DATE_IN = (
          SELECT MAX(P.DATE_IN)
          FROM PERSON_MOVEMENTS P
          WHERE P.PERSON_ID = M.PERSON_ID AND P.GROUP_TYPE_ID IN (9, 187) AND P.DATE_IN <= :I$DATE_TO)
      GROUP BY U.REF_ID, U.ACTION_DATE, M.GROUP_ID
      ) S
    LEFT JOIN OBJECT_CAPTION_GET(S.GROUP_ID) CLASS ON 1 = 1
    LEFT JOIN UT_PERSON_DESC(S.REF_ID, :I$ZONE, 1) FIO ON 1 = 1
    GROUP BY S.REF_ID, FIO.NAME_FULL, CLASS.SCAPTION
    ORDER BY CLASS.SCAPTION, FIO.NAME_FULL
    INTO :V$S1, :V$S2, :V$OBJ_ID
  DO
  BEGIN
    VAL = '<tr class="ui center aligned">';
    VAL = VAL || '<td>' || V$S2 || '</td><td> ' || V$S1 || '</td><td>' || V$OBJ_ID || '</td></tr>';
    SUSPEND;
  END

  VAL = '</table></body></html>';
  SUSPEND;
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIB2_REPORT_NX60 (
    I$USER_ID VARCHAR(40),
    I$DATE_FROM DATE,
    I$DATE_TO DATE,
    I$PARENT_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$OPTION_ID BIGINT,
    I$OPTIONS VARCHAR(1000),
    I$ZONE SMALLINT = 0)
RETURNS (
    VAL VARCHAR(4000))
AS
DECLARE VARIABLE V$CALLER_TYPE BIGINT;
DECLARE VARIABLE V$S1 VARCHAR(400);
DECLARE VARIABLE V$S2 VARCHAR(400);
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$USER_TYPE BIGINT;
begin
  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;
  SELECT TYPE_ID FROM OBJECTS WHERE OBJ_ID = :I$OBJ_ID INTO :V$CALLER_TYPE;
  SELECT USER_TYPE FROM USERS WHERE USER_ID = :I$USER_ID INTO :V$USER_TYPE;

  VAL = '<!DOCTYPE html>';
  VAL = VAL || '<html lang="ru">';
  VAL = VAL || '<head>';
  VAL = VAL || '<meta charset="utf-8" />';
  VAL = VAL || '<style>';
  VAL = VAL || 'html { font-family: Tahoma, Verdana, Arial;';
  VAL = VAL || 'font-size: 10pt; ';
  VAL = VAL || '} ';
  VAL = VAL || '</style>';

  VAL = VAL || '</head>';
  VAL = VAL || '<body>';
  SUSPEND;

  -- Заголовок отчета
  VAL = '<div class="ui left aligned">Обучающиеся, не посещающие библиотеку</div>';
  V$S1 = (SELECT RESULT FROM DATE2STR(:I$DATE_FROM));
  V$S2 = (SELECT RESULT FROM DATE2STR(:I$DATE_TO));
  VAL = VAL || '<div class="ui left aligned">Период: ' || V$S1 || ' - ' || V$S2 || '</div>';

  -- Заголовок таблицы
  VAL = VAL || '<table class="ui celled striped table" cellspacing="0" cellpadding="25">';
  SUSPEND;

  VAL = '<tr class="ui center aligned">';
  VAL = VAL || '<thead><th>Класс</th><th>ФИО</th></thead>';
  VAL = VAL || '</tr>';
  SUSPEND;
  FOR
    SELECT DISTINCT CLASS.SCAPTION, FIO.NAME_FULL
    FROM LINKS L10
    LEFT JOIN UT_PERSON_DESC(L10.OBJ_ID, :I$ZONE, 1) FIO ON 1 = 1
    JOIN LINKS L9 ON L9.OBJ_ID = L10.PARENT_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL AND (:V$CALLER_TYPE <> 9 OR L9.OBJ_ID = :I$OBJ_ID)    -- класс
    LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) CLASS ON 1 = 1
    JOIN LINKS L8 ON L8.OBJ_ID = L9.PARENT_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL AND (:V$CALLER_TYPE <> 8 OR L8.OBJ_ID = :I$OBJ_ID)    -- этап
    JOIN LINKS L7 ON L7.OBJ_ID = L8.PARENT_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL AND (:V$CALLER_TYPE <> 7 OR L7.OBJ_ID = :I$OBJ_ID)    -- уровень
    WHERE L10.OBJ_TYPE_ID = 10 AND L10.PARENT_TYPE_ID IN (9, 187) AND L10.DATE_DEL IS NULL AND (:V$CALLER_TYPE <> 10 OR L10.OBJ_ID = :I$OBJ_ID)
      AND L10.OBJ_ID NOT IN
       (SELECT DISTINCT U.REF_ID
        FROM LIB2_USAGE U
        WHERE U.REF_TYPE_ID = 10 AND U.ACTION_DATE >= :I$DATE_FROM AND U.ACTION_DATE <= :I$DATE_TO AND U.DATE_DEL IS NULL)
    ORDER BY CLASS.SCAPTION, FIO.NAME_FULL
    INTO :V$S1, :V$S2
  DO
  BEGIN
    VAL = '<tr class="ui center aligned">';
    VAL = VAL || '<td>' || V$S1 || '</td><td> ' || V$S2 || '</td></tr>';
    SUSPEND;
  END

  VAL = '</table></body></html>';
  SUSPEND;
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIB2_REPORT_NX90 (
    I$USER_ID VARCHAR(40),
    I$DATE_FROM DATE,
    I$DATE_TO DATE,
    I$PARENT_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$OPTION_ID BIGINT,
    I$OPTIONS VARCHAR(1000),
    I$ZONE SMALLINT = 0)
RETURNS (
    VAL VARCHAR(4000))
AS
DECLARE VARIABLE V$CALLER_TYPE BIGINT;
DECLARE VARIABLE V$S1 VARCHAR(400);
DECLARE VARIABLE V$S2 VARCHAR(400);
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$USER_TYPE BIGINT;
DECLARE VARIABLE V$I INTEGER;
DECLARE VARIABLE N INTEGER;
DECLARE VARIABLE CNT INTEGER;
DECLARE VARIABLE V$BOOK_HANDOUT INTEGER;
DECLARE VARIABLE K NUMERIC(15,2);
begin
  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;
  SELECT TYPE_ID FROM OBJECTS WHERE OBJ_ID = :I$OBJ_ID INTO :V$CALLER_TYPE;
  SELECT USER_TYPE FROM USERS WHERE USER_ID = :I$USER_ID INTO :V$USER_TYPE;

  VAL = '<!DOCTYPE html>';
  VAL = VAL || '<html lang="ru">';
  VAL = VAL || '<head>';
  VAL = VAL || '<meta charset="utf-8" />';
  VAL = VAL || '<style>';
  VAL = VAL || 'html { font-family: Tahoma, Verdana, Arial;';
  VAL = VAL || 'font-size: 10pt; ';
  VAL = VAL || '} ';
  VAL = VAL || '</style>';

  VAL = VAL || '</head>';
  VAL = VAL || '<body>';
  SUSPEND;

  -- Заголовок отчета
  VAL = '<div class="ui left aligned">Уровень состояния фонда</div>';
  V$S1 = (SELECT RESULT FROM DATE2STR(:I$DATE_FROM));
  V$S2 = (SELECT RESULT FROM DATE2STR(:I$DATE_TO));
  VAL = VAL || '<div class="ui left aligned">Период: ' || V$S1 || ' - ' || V$S2 || '</div>';

  -- Заголовок таблицы
  VAL = VAL || '<table class="ui celled table" cellspacing="0" cellpadding="25">';
  SUSPEND;

  VAL = '<tr class="ui center aligned">';
  VAL = VAL || '<td></td>';
  VAL = VAL || '<td></td>';
  VAL = VAL || '<td></td>';
  VAL = VAL || '<td>Количество</td>';
  VAL = VAL || '</tr>';
  SUSPEND;

  SELECT COUNT(*)
  FROM LIB2_USAGE U
  WHERE U.ACTION_DATE >= :I$DATE_FROM AND U.ACTION_DATE <= :I$DATE_TO AND U.DATE_DEL IS NULL AND U.RETURN_DATE IS NULL AND U.LOSS_DATE IS NULL
  INTO :V$BOOK_HANDOUT;

  VAL = '<tr class="ui center aligned">';
  VAL = VAL || '<td>1</td>';
  VAL = VAL || '<td>Книговыдача</td>';
  VAL = VAL || '<td>Всего за год</td>';
  VAL = VAL || '<td>' || V$BOOK_HANDOUT || '</td>';
  VAL = VAL || '</tr>';
  SUSPEND;

  CNT = 0;
  SELECT COUNT(DISTINCT LV.LISTVAL_ID)
  FROM LIB2_LISTVALS LV
  WHERE LV.LIST_ID = 6
  INTO :CNT;

  VAL = '<tr class="ui center aligned">';
  VAL = VAL || '<td rowspan = "' || CNT || '">2</td>';
  VAL = VAL || '<td rowspan = "' || CNT || '">Книгообоспеченность основного фонда</td>';
  SUSPEND;
  -- значения из списка назначение издания
  N = 0;
  FOR
    SELECT DISTINCT LV.LISTVAL_ID, LV.VAL
    FROM LIB2_LISTVALS LV
    WHERE LV.LIST_ID = 6
    ORDER BY LV.LISTVAL_ID
    INTO :CNT, :V$S1
  DO
  BEGIN
    N = N + 1;
    -- сосчитаем кол-во книг по каждому назначению
    SELECT COALESCE(COUNT(*), 0)
    FROM LIB2_INSTANCES I
    JOIN LIB2_BOOKS B ON I.BOOK_ID = B.OBJ_ID AND B.DATE_DEL IS NULL AND B.OBJ_TYPE <> 18712 -- не учебник
    JOIN LIB2_LISTVALS LV ON LV.LISTVAL_ID = B.PURPOSE_ID AND LV.DATE_DEL IS NULL
    WHERE I.DATE_DEL IS NULL AND B.PURPOSE_ID = :CNT
    INTO :V$I;

    IF (N > 1) THEN
    BEGIN
      VAL = '<tr class="ui center aligned">';
    END
    VAL = '<td class="ui center aligned">' || V$S1 || '</td>';
    VAL = VAL || '<td class="ui center aligned">' || V$I || '</td>';
    VAL = VAL || '</tr>';
    SUSPEND;
  END

  -- учебники всего
  SELECT COALESCE(SUM(P.QUANTITY), 0)
  FROM LIB2_BATCHES P
  JOIN LIB2_BOOKS B ON P.BOOK_ID = B.OBJ_ID AND B.DATE_DEL IS NULL AND B.OBJ_TYPE = 18712 -- учебник
  WHERE P.DATE_DEL IS NULL AND P.QUANTITY > 0
  INTO :V$I;

  VAL = '<tr class="ui center aligned">';
  VAL = VAL || '<td rowspan = "4">3</td>';
  VAL = VAL || '<td rowspan = "4">Книгообоспеченность учебниками</td>';
  VAL = VAL || '<td>Всего</td>';
  VAL = VAL || '<td>' || V$I || '</td>';
  VAL = VAL || '</tr>';
  SUSPEND;

  -- учебники 1-4 класс
  SELECT COALESCE(SUM(P.QUANTITY), 0)
  FROM LIB2_BATCHES P
  JOIN LIB2_BOOKS B ON P.BOOK_ID = B.OBJ_ID AND B.DATE_DEL IS NULL AND B.OBJ_TYPE = 18712 -- учебник
  WHERE P.DATE_DEL IS NULL AND P.QUANTITY > 0 AND B.STAGE_FROM >= 1 AND B.STAGE_TO <= 4   -- класс
  INTO :V$I;

  VAL = '<tr class="ui center aligned">';
  VAL = VAL || '<td>1-4 классы</td>';
  VAL = VAL || '<td>' || V$I || '</td>';
  VAL = VAL || '</tr>';
  SUSPEND;

  -- учебники 5-9 класс
  SELECT COALESCE(SUM(P.QUANTITY), 0)
  FROM LIB2_BATCHES P
  JOIN LIB2_BOOKS B ON P.BOOK_ID = B.OBJ_ID AND B.DATE_DEL IS NULL AND B.OBJ_TYPE = 18712 -- учебник
  WHERE P.DATE_DEL IS NULL AND P.QUANTITY > 0 AND B.STAGE_FROM >= 5 AND B.STAGE_TO <= 9   --  класс
  INTO :V$I;

  VAL = '<tr class="ui center aligned">';
  VAL = VAL || '<td>5-9 классы</td>';
  VAL = VAL || '<td>' || V$I || '</td>';
  VAL = VAL || '</tr>';
  SUSPEND;

  -- учебники 10-11 класс
  SELECT COALESCE(SUM(P.QUANTITY), 0)
  FROM LIB2_BATCHES P
  JOIN LIB2_BOOKS B ON P.BOOK_ID = B.OBJ_ID AND B.DATE_DEL IS NULL AND B.OBJ_TYPE = 18712 -- учебник
  WHERE P.DATE_DEL IS NULL AND P.QUANTITY > 0 AND B.STAGE_FROM >= 10 AND B.STAGE_TO <= 11 -- класс
  INTO :V$I;

  VAL = '<tr class="ui center aligned">';
  VAL = VAL || '<td>10-11 классы</td>';
  VAL = VAL || '<td>' || V$I || '</td>';
  VAL = VAL || '</tr>';
  SUSPEND;

  -- вычислим объем фонда - все книги и учебники на балансе библиотеки
  V$I = 0;
  CNT = 0;
  SELECT COALESCE(SUM(P.QUANTITY), 0)
  FROM LIB2_BATCHES P
  JOIN LIB2_BOOKS B ON P.BOOK_ID = B.OBJ_ID AND B.DATE_DEL IS NULL AND B.OBJ_TYPE = 18712 -- учебник
  WHERE P.DATE_DEL IS NULL AND P.QUANTITY > 0
  INTO :V$I;

  SELECT COALESCE(COUNT(*), 0)
  FROM LIB2_INSTANCES I
  JOIN LIB2_BOOKS B ON I.BOOK_ID = B.OBJ_ID AND B.DATE_DEL IS NULL AND B.OBJ_TYPE <> 18712 -- не учебник
  WHERE I.DATE_DEL IS NULL
  INTO :CNT;

  -- вычислим обращаемость. О = В (за год) / Ф , где В - книговыдача, Ф - объем фонда
  VAL = '<tr class="ui center aligned">';
  VAL = VAL || '<td>4</td>';
  VAL = VAL || '<td>Обращаемость фонда</td>';
  VAL = VAL || '<td>Всего</td>';
  IF (V$I + CNT > 0) THEN
  BEGIN
    K = CAST(V$BOOK_HANDOUT AS NUMERIC(15, 2)) / (V$I + CNT);
    VAL = VAL || '<td>' || K || '</td>';
  END
  ELSE
  BEGIN
    VAL = VAL || '<td>-</td>';
  END
  VAL = VAL || '</tr>';
  SUSPEND;


  VAL = '</table></body></html>';
  SUSPEND;
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIB2_REPORT_NX98 (
    I$USER_ID VARCHAR(40),
    I$DATE_FROM DATE,
    I$DATE_TO DATE,
    I$PARENT_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$OPTION_ID BIGINT,
    I$OPTIONS VARCHAR(1000),
    I$ZONE SMALLINT = 0)
RETURNS (
    VAL VARCHAR(4000))
AS
DECLARE VARIABLE V$S1 VARCHAR(10);
DECLARE VARIABLE V$S2 VARCHAR(10);
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$TYPE BIGINT;
DECLARE VARIABLE V$USER_TYPE BIGINT;
DECLARE VARIABLE V$STAGE VARCHAR(400);
DECLARE VARIABLE V$SUBJECT VARCHAR(100);
DECLARE VARIABLE V$PUPIL_CNT INTEGER;
DECLARE VARIABLE V$IN_USE_CNT INTEGER;
DECLARE VARIABLE V$PERCENT NUMERIC(15,2);
DECLARE VARIABLE V$YEAR INTEGER;
DECLARE VARIABLE V$LVL BIGINT;
DECLARE VARIABLE V$ST BIGINT;
begin
  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;
  SELECT USER_TYPE FROM USERS WHERE USER_ID = :I$USER_ID INTO :V$USER_TYPE;

  -- найдем id ОУ
  SELECT OBJ_ID FROM LINKS WHERE OBJ_TYPE_ID = 2 AND PARENT_TYPE_ID IS NULL AND DATE_DEL IS NULL INTO :V$OBJ_ID;
  -- найдем текущий учебный год
  SELECT LV.COST
  FROM VALL V
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V.LISTVAL_ID AND LV.IS_DEL = 0
  WHERE V.OBJ_ID = :V$OBJ_ID AND V.PARAM_ID = 1236 AND V.IS_DEL = 0
  INTO :V$YEAR;

  VAL = '<!DOCTYPE html>';
  VAL = VAL || '<html lang="ru">';
  VAL = VAL || '<head>';
  VAL = VAL || '<meta charset="utf-8" />';
  VAL = VAL || '<style>';
  VAL = VAL || 'html { font-family: Tahoma, Verdana, Arial;';
  VAL = VAL || 'font-size: 10pt; ';
  VAL = VAL || '}';
  VAL = VAL || '</style>';
  VAL = VAL || '</head>';
  VAL = VAL || '<body>';
  SUSPEND;

  -- Заголовок отчета
  VAL = '<div class="ui left aligned">Отчет по обеспеченности учебниками - сводка</div>';
  V$S1 = (SELECT RESULT FROM DATE2STR(:I$DATE_FROM));
  V$S2 = (SELECT RESULT FROM DATE2STR(:I$DATE_TO));
  VAL = VAL || '<div class="ui left aligned">Период: ' || V$S1 || ' - ' || V$S2 || '</div>';
  SUSPEND;
  -- Заголовок таблицы
  VAL = '<table class="ui celled striped table" cellspacing="0" cellpadding="25">';
  SUSPEND;

  VAL = '<thead>';
  VAL = VAL || '<tr class="ui center aligned">';
  VAL = VAL || '<th>Параллель</th>';
  VAL = VAL || '<th>Предмет</th>';
  VAL = VAL || '<th>Кол-во обучающихся</th>';
  VAL = VAL || '<th>Кол-во выданных учебников из ФПУ</th>';
  VAL = VAL || '<th>Процент обеспеченности (%)</th>';
  VAL = VAL || '</tr>';
  VAL = VAL || '</thead>';
  SUSPEND;

  -- Определим тип вызывающего объекта
  SELECT L.OBJ_TYPE_ID
  FROM LINKS L
  WHERE L.OBJ_ID = :I$OBJ_ID AND L.PARENT_ID = :I$PARENT_ID AND L.DATE_DEL IS NULL
  INTO :V$TYPE;

  V$LVL = NULL;
  V$ST = NULL;
  IF (V$TYPE = 7) THEN
  BEGIN
    -- Определим уровень
    SELECT LV.TAG
    FROM VALL V
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V.LISTVAL_ID AND LV.IS_DEL = 0
    WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 43 AND V.IS_DEL = 0
    INTO :V$LVL;
  END ELSE IF (V$TYPE = 8) THEN
  BEGIN
    -- Определим этап
    SELECT V.LISTVAL_ID
    FROM VALL V
    WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 49 AND V.IS_DEL = 0
    INTO :V$ST;
  END ELSE IF (V$TYPE IN (9, 187)) THEN
  BEGIN
    -- Определим этап по родителю, так как сводку показывем для всей параллели
    SELECT V.LISTVAL_ID
    FROM VALL V
    WHERE V.OBJ_ID = :I$PARENT_ID AND V.PARAM_ID = 49 AND V.IS_DEL = 0
    INTO :V$ST;
  END ELSE IF (V$TYPE = 10) THEN
  BEGIN
    -- Если объект это ученик, то все равно показываем для всей параллели. Определим параллель
    SELECT V49.LISTVAL_ID
    FROM LINKS L9
    JOIN VALL V49 ON V49.OBJ_ID = L9.PARENT_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
    WHERE L9.OBJ_TYPE_ID IN (9, 187) AND L9.OBJ_ID = :I$PARENT_ID AND L9.DATE_DEL IS NULL
    INTO :V$ST;
  END

  FOR
    SELECT ST.VAL, SBJ.SCAPTION, COALESCE(SUF.PUPIL_CNT, 0), COALESCE(SUF.IN_USE_CNT, 0)
    FROM LIB2_WB_SUFFICIENCY_LIST(:V$LVL, :V$ST, NULL, 0) SUF   -- 0 - флаг-индикатор, чтобы получить только кол-во выданных книг
    LEFT JOIN LISTVAL_TEXT(SUF.STAGE_ID) ST ON 1 = 1 -- название этапа
    LEFT JOIN OBJECT_CAPTION_GET(SUF.SUBJECT_ID) SBJ ON 1 = 1  -- название предмета
    INTO :V$STAGE, :V$SUBJECT, :V$PUPIL_CNT, :V$IN_USE_CNT
  DO
  BEGIN
    -- ограничим обеспеченность 100 процентами. Она получается больше, если нескольк учебников/частей положены на один предмет
    IF (V$IN_USE_CNT > V$PUPIL_CNT) THEN V$IN_USE_CNT = V$PUPIL_CNT;
    V$PERCENT = IIF(V$PUPIL_CNT > 0, CAST(V$IN_USE_CNT AS NUMERIC(18, 2)) / V$PUPIL_CNT * 100, 0);

    VAL = '<tr class="ui center aligned">';
    VAL = VAL || '<td>' || V$STAGE || '</td>';
    VAL = VAL || '<td>' || V$SUBJECT || '</td>';
    VAL = VAL || '<td>' || V$PUPIL_CNT || '</td>';
    VAL = VAL || '<td>' || IIF(V$IN_USE_CNT = 0, '', V$IN_USE_CNT) || '</td>';
    VAL = VAL || '<td>' || V$PERCENT || '</td>';
    VAL = VAL || '</tr>';
    SUSPEND;
  END

  VAL = '</table></body></html>';
  SUSPEND;
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIB2_REPORT_NX99 (
    I$USER_ID VARCHAR(40),
    I$DATE_FROM DATE,
    I$DATE_TO DATE,
    I$PARENT_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$OPTION_ID BIGINT,
    I$OPTIONS VARCHAR(1000),
    I$ZONE SMALLINT = 0)
RETURNS (
    VAL VARCHAR(4000))
AS
DECLARE VARIABLE V$S1 VARCHAR(10);
DECLARE VARIABLE V$S2 VARCHAR(10);
DECLARE VARIABLE V$USER_TYPE BIGINT;
DECLARE VARIABLE V$STAGE VARCHAR(400);
DECLARE VARIABLE V$LVL_NAME VARCHAR(400);
DECLARE VARIABLE V$PLAN_NAME VARCHAR(400);
DECLARE VARIABLE V$SUBJECT_NAME VARCHAR(100);
DECLARE VARIABLE V$PUPIL_CNT INTEGER;
DECLARE VARIABLE V$BOOK_NAME VARCHAR(500);
DECLARE VARIABLE V$FPU_CODE VARCHAR(100);
DECLARE VARIABLE V$IN_USE_CNT INTEGER;
DECLARE VARIABLE V$TOTAL_CNT INTEGER;
DECLARE VARIABLE V$TYPE BIGINT;
DECLARE VARIABLE V$LVL BIGINT;
DECLARE VARIABLE V$ST BIGINT;
DECLARE VARIABLE V$GR BIGINT;
begin
  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;
  SELECT USER_TYPE FROM USERS WHERE USER_ID = :I$USER_ID INTO :V$USER_TYPE;

  VAL = '<!DOCTYPE html>';
  VAL = VAL || '<html lang="ru">';
  VAL = VAL || '<head>';
  VAL = VAL || '<meta charset="utf-8" />';
  VAL = VAL || '<style>';
  VAL = VAL || 'html { font-family: Tahoma, Verdana, Arial;';
  VAL = VAL || 'font-size: 10pt; ';
  VAL = VAL || '} ';
  VAL = VAL || '</style>';

  VAL = VAL || '</head>';
  VAL = VAL || '<body>';
  SUSPEND;

  -- Заголовок отчета
  VAL = '<div class="ui left aligned">Отчет по обеспеченности учебниками - детализация</div>';
  V$S1 = (SELECT RESULT FROM DATE2STR(:I$DATE_FROM));
  V$S2 = (SELECT RESULT FROM DATE2STR(:I$DATE_TO));
  VAL = VAL || '<div class="ui left aligned">Период: ' || V$S1 || ' - ' || V$S2 || '</div>';
  SUSPEND;
  -- Заголовок таблицы
  VAL = '<table class="ui celled striped table" cellspacing="0" cellpadding="25">';
  SUSPEND;

  VAL = '<thead>';
  VAL = VAL || '<tr class="ui center aligned">';
  VAL = VAL || '<th rowspan="2">Параллель</th>';
  VAL = VAL || '<th rowspan="2">Уровень образования</th>';
  VAL = VAL || '<th rowspan="2">Учебный план</th>';
  VAL = VAL || '<th rowspan="2">Предмет</th>';
  VAL = VAL || '<th rowspan="2">Кол-во обучающихся</th>';
  VAL = VAL || '<th colspan="4">Учебники из ФПУ</th>';
  VAL = VAL || '</tr><tr class="ui center aligned">';
  VAL = VAL || '<th>Выдано обучающимся</th>';
  VAL = VAL || '<th>Количество в библиотеке</th>';
  VAL = VAL || '<th>Номер ФПУ</th>';
  VAL = VAL || '<th>Название</th>';
  VAL = VAL || '</tr>';
  VAL = VAL || '</thead>';
  SUSPEND;

  -- Определим тип вызывающего объекта
  SELECT L.OBJ_TYPE_ID
  FROM LINKS L
  WHERE L.OBJ_ID = :I$OBJ_ID AND L.PARENT_ID = :I$PARENT_ID AND L.DATE_DEL IS NULL
  INTO :V$TYPE;

  V$LVL = NULL;
  V$ST = NULL;
  V$GR = NULL;
  IF (V$TYPE = 7) THEN
  BEGIN
    -- Определим уровень
    SELECT LV.TAG
    FROM VALL V
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V.LISTVAL_ID AND LV.IS_DEL = 0
    WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 43 AND V.IS_DEL = 0
    INTO :V$LVL;
  END ELSE IF (V$TYPE = 8) THEN
  BEGIN
    -- Определим этап
    SELECT V.LISTVAL_ID
    FROM VALL V
    WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 49 AND V.IS_DEL = 0
    INTO :V$ST;
  END ELSE IF (V$TYPE IN (9, 187)) THEN
  BEGIN
    V$GR = I$OBJ_ID;
  END ELSE IF (V$TYPE = 10) THEN
  BEGIN
     -- Если объект это ученик, то все равно показываем для всего класса. Определим класс
    V$GR = I$PARENT_ID;
  END

  FOR
    SELECT ST.VAL, IIF(LVL_ID = 5339, 'НОО', IIF(LVL_ID = 5341, 'ООО', IIF(LVL_ID = 5343, 'СОО', R.VAL))),
      V3012.VAL, SUB.SCAPTION, COALESCE(SUF.PUPIL_CNT, 0), BOOK_NAME, FPU_CODE, COALESCE(SUF.IN_USE_CNT, 0), COALESCE(SUF.BOOKS_LEFT_CNT, 0)
    FROM LIB2_WB_SUFFICIENCY_LIST(:V$LVL, :V$ST, :V$GR, 1) SUF  -- запрос расширенного объема данных о выданных книгах
    LEFT JOIN LISTVAL_TEXT(SUF.STAGE_ID) ST ON 1 = 1 -- название этапа
    JOIN VALS V3012 ON V3012.OBJ_ID = SUF.PLAN_ID AND V3012.PARAM_ID = 3012 AND V3012.IS_DEL = 0 -- название УП
    JOIN LISTVALS LV1594 ON LV1594.LISTVAL_ID = LVL_ID AND LV1594.IS_DEL = 0 AND (:V$LVL IS NULL OR LV1594.TAG = :V$LVL) -- уровень образования
    JOIN RES R ON R.RES_ID = LV1594.RES_ID AND R.LANG_CODE = 'RU' AND R.IS_DEL = 0
    LEFT JOIN OBJECT_CAPTION_GET(SUF.SUBJECT_ID) SUB ON 1 = 1  -- название предмета
    INTO :V$STAGE, :V$LVL_NAME, :V$PLAN_NAME, :V$SUBJECT_NAME, :V$PUPIL_CNT, :V$BOOK_NAME, :V$FPU_CODE, :V$IN_USE_CNT, :V$TOTAL_CNT
  DO
  BEGIN
    VAL = '<tr class="ui center aligned">';
    VAL = VAL || '<td>' || COALESCE(V$LVL_NAME, '') || '</td>';
    VAL = VAL || '<td>' || COALESCE(V$STAGE, '') || '</td>';
    VAL = VAL || '<td>' || COALESCE(V$PLAN_NAME, '') || '</td>';
    VAL = VAL || '<td>' || COALESCE(V$SUBJECT_NAME, '') || '</td>';
    VAL = VAL || '<td>' || V$PUPIL_CNT || '</td>';
    VAL = VAL || '<td>' || V$IN_USE_CNT || '</td>';
    VAL = VAL || '<td>' || V$TOTAL_CNT || '</td>';
    VAL = VAL || '<td>' || COALESCE(V$FPU_CODE, '') || '</td>';
    VAL = VAL || '<td>' || COALESCE(V$BOOK_NAME, '') || '</td>';
    VAL = VAL || '</tr>';
    SUSPEND;
  END

  VAL = '</table></body></html>';
  SUSPEND;
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIB2_SEARCH_DATA (
    USER_ID VARCHAR(100))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$ID BIGINT;
DECLARE VARIABLE V$VAL VARCHAR(1000);
begin
  --IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  -- тип издания
  TAG_NAME = 'type_id::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT LISTVAL_ID, VAL
    FROM LISTVALS_LIST(383)
    WHERE IS_DEL = 0    INTO :V$ID, :V$VAL
  DO
  BEGIN
    TAG_NAME = 'type_id:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'type_id:r:id';
    VAL = V$ID;
    SUSPEND;
    TAG_NAME = 'type_id:r:value';
    VAL = V$VAL;
    SUSPEND;
  END
  -- язык
  TAG_NAME = 'lang_id::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT LISTVAL_ID, VAL
    FROM LISTVALS_LIST(49)
    WHERE IS_DEL = 0    INTO :V$ID, :V$VAL
  DO
  BEGIN
    TAG_NAME = 'lang_id:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'lang_id:r:id';
    VAL = V$ID;
    SUSPEND;
    TAG_NAME = 'lang_id:r:value';
    VAL = V$VAL;
    SUSPEND;
  END

  -- Предметы
  TAG_NAME = 'subject_id::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L51.OBJ_ID, V376.SVAL
    FROM LINKS L51
    JOIN VALS V376 ON V376.OBJ_ID = L51.OBJ_ID AND V376.PARAM_ID = 376 AND V376.IS_DEL = 0
    WHERE L51.PARENT_ID = 32771 AND L51.OBJ_TYPE_ID = 51 AND L51.DATE_DEL IS NULL AND L51.OBJ_ID < 1000000000
      -- без олимпиадных предметов и элективов
      AND L51.OBJ_ID NOT IN (179, 34607, 38168, 38707, 38708, 38709, 38710, 38711, 38712, 38713, 38714, 38715, 38716, 38717, 38718, 38719)
    ORDER BY 2
    INTO :V$ID, :V$VAL
  DO
  BEGIN
    TAG_NAME = 'subject_id:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'subject_id:r:id';
    VAL = V$ID;
    SUSPEND;
    TAG_NAME = 'subject_id:r:value';
    VAL = V$VAL;
    SUSPEND;
  END

  -- Назначение
  TAG_NAME = 'purpose_id::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT LV.LISTVAL_ID, LV.VAL
    FROM LIB2_LISTVALS LV
    WHERE LV.LIST_ID = 6 AND LV.DATE_DEL IS NULL
    ORDER BY 2
    INTO :V$ID, :V$VAL
  DO
  BEGIN
    TAG_NAME = 'purpose_id:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'purpose_id:r:id';
    VAL = V$ID;
    SUSPEND;
    TAG_NAME = 'purpose_id:r:value';
    VAL = V$VAL;
    SUSPEND;
  END

  -- Уровень образования
  TAG_NAME = 'edu_level_id::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT LISTVAL_ID, VAL
    FROM LISTVALS_LIST(19)
    WHERE IS_DEL = 0 AND LISTVAL_ID IN (22, 26, 27) -- только ОО
    INTO :V$ID, :V$VAL
  DO
  BEGIN
    TAG_NAME = 'edu_level_id:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'edu_level_id:r:id';
    VAL = V$ID;
    SUSPEND;
    TAG_NAME = 'edu_level_id:r:value';
    VAL = V$VAL;
    SUSPEND;
  END

  -- Адаптированность
  TAG_NAME = 'adapt_id::json&colon;array';
  VAL = 1;
  SUSPEND;
  TAG_NAME = 'adapt_id:r';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'adapt_id:r:id';
  VAL = 0;
  SUSPEND;
  TAG_NAME = 'adapt_id:r:value';
  VAL = 'Нет';
  SUSPEND;
  TAG_NAME = 'adapt_id:r';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'adapt_id:r:id';
  VAL = 1;
  SUSPEND;
  TAG_NAME = 'adapt_id:r:value';
  VAL = 'Да';
  SUSPEND;

  -- компонент ОП
  TAG_NAME = 'component_id::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT LISTVAL_ID, VAL
    FROM LISTVALS_LIST(116)
    WHERE IS_DEL = 0 AND LISTVAL_ID IN (12752, 12753)
    INTO :V$ID, :V$VAL
  DO
  BEGIN
    TAG_NAME = 'component_id:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'component_id:r:id';
    VAL = V$ID;
    SUSPEND;
    TAG_NAME = 'component_id:r:value';
    VAL = V$VAL;
    SUSPEND;
  END

  -- уровень учебника
  TAG_NAME = 'diff_level_id::json&colon;array';
  VAL = 1;
  SUSPEND;
    TAG_NAME = 'diff_level_id:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'diff_level_id:r:id';
    VAL = 0;
    SUSPEND;
    TAG_NAME = 'diff_level_id:r:value';
    VAL = 'Базовый';
    SUSPEND;
    TAG_NAME = 'diff_level_id:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'diff_level_id:r:id';
    VAL = 1;
    SUSPEND;
    TAG_NAME = 'diff_level_id:r:value';
    VAL = 'Углубленный';
    SUSPEND;
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIB2_TRANSFER (
    I$MODE VARCHAR(100))
RETURNS (
    VAL VARCHAR(4000))
AS
DECLARE VARIABLE V$BOOK_ID BIGINT;
DECLARE VARIABLE V$PRICE FLOAT;
DECLARE VARIABLE V$AUTHOR VARCHAR(400);
DECLARE VARIABLE V$PUBL VARCHAR(400);
DECLARE VARIABLE V$AUTHOR_ID BIGINT;
DECLARE VARIABLE V$PUBL_ID BIGINT;
DECLARE VARIABLE V$DEST_ID BIGINT;
DECLARE VARIABLE V$AUTHORS VARCHAR(400);
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$TYPE BIGINT;
DECLARE VARIABLE V$DOCNO VARCHAR(100);
DECLARE VARIABLE V$DOCDATE DATE;
DECLARE VARIABLE V$DATE DATE;
DECLARE VARIABLE V$TDATE DATE;
DECLARE VARIABLE V$REC INTEGER;
DECLARE VARIABLE V$INST_ID BIGINT;
DECLARE VARIABLE V$INV_ID BIGINT;
DECLARE VARIABLE V$REASON BIGINT;
DECLARE VARIABLE V$INV_CODE BIGINT;
DECLARE VARIABLE C1 INTEGER;
DECLARE VARIABLE C2 INTEGER;
DECLARE VARIABLE V$BBK VARCHAR(100);
DECLARE VARIABLE V$UDK VARCHAR(100);
DECLARE VARIABLE V$SUBJECT_ID BIGINT;
DECLARE VARIABLE V$SUBJECT_ID2 BIGINT;
DECLARE VARIABLE V$FPU_ID BIGINT;
DECLARE VARIABLE S VARCHAR(400);
DECLARE VARIABLE ST BIGINT;
DECLARE VARIABLE G1 INTEGER;
DECLARE VARIABLE G2 INTEGER;
DECLARE VARIABLE AA INTEGER;
DECLARE VARIABLE V$DATE_TO DATE;
DECLARE VARIABLE V$LOAD_ID BIGINT;
DECLARE VARIABLE Y VARCHAR(40);
DECLARE VARIABLE SQ INTEGER;
DECLARE VARIABLE V$PLAN_ID BIGINT;
DECLARE VARIABLE V$PART_NUM SMALLINT;
begin

  -- !! Ни в коем случае не запускать на эталонной базе

  -- Возможные значения I$MODE
  -- ALL - полный перенос всего
  -- CLEAR - зачистка таблиц нового библиографа
  -- TEXTBOOKS - перенос книг с движениями и абонементами, а также карточек учебников в каталог (без движений)
  -- TBMOVE - пакетная выдача учебников
  -- TBALL - перенос только учебников и с движениями (ведомостями) и с пакетной выдачей.
  -- BOOKALL - перенос только книг с движениями (ведомостями) и абонементами.

  I$MODE = UPPER(TRIM(I$MODE));
  IF (I$MODE IS NOT NULL AND I$MODE <> 'ALL' AND I$MODE <> 'CLEAR' AND I$MODE <> 'TEXTBOOKS' AND I$MODE <> 'TBMOVE' AND I$MODE <> 'TBALL' AND I$MODE <> 'BOOKALL') THEN
    EXCEPTION DATA_ERROR('Нет такого режима выполнения процедуры - ' || COALESCE(I$MODE, 'null'));

  IF(I$MODE = 'CLEAR') THEN
  BEGIN
    DELETE FROM LIB2_USAGE WHERE 1 = 1;
    DELETE FROM LIB2_BATCHES WHERE 1 = 1;
    DELETE FROM LIB2_INVOICES WHERE 1 = 1;
    DELETE FROM LIB2_INSTANCES WHERE 1 = 1;
    DELETE FROM LIB2_BOOKS WHERE 1 = 1;
    EXIT;
  END

  -- Справочник авторов - дополняем
  FOR
    SELECT A.AUTHORNAME
    FROM LIB_AUTHOR A
    LEFT JOIN LIB2_LISTVALS LA ON LA.DATE_DEL IS NULL AND LA.LIST_ID = 2 AND UPPER(LA.VAL) = UPPER(A.AUTHORNAME)
    WHERE LA.LISTVAL_ID IS NULL
    ORDER BY 1
    INTO :VAL
  DO
  BEGIN
    INSERT INTO LIB2_LISTVALS
    (LIST_ID, VAL)
    VALUES (2, :VAL);

    VAL = 'Автор: ' || VAL;
    SUSPEND;
  END

  -- Справочник издательств, только те, к которым есть издания
  FOR
    SELECT A.PUBLISHERNAME
    FROM LIB_PUBLISHER A
    LEFT JOIN LIB2_LISTVALS LA ON LA.DATE_DEL IS NULL AND LA.LIST_ID = 1 AND UPPER(LA.VAL) = UPPER(A.PUBLISHERNAME)
    WHERE LA.LISTVAL_ID IS NULL AND EXISTS(SELECT FIRST 1 1 FROM LIB_BOOK B WHERE B.PUBLISHERID = A.PUBLISHERID)
    ORDER BY 1
    INTO :VAL
  DO
  BEGIN
    INSERT INTO LIB2_LISTVALS
    (LIST_ID, VAL)
    VALUES (1, :VAL);

    VAL = 'Издательство: ' || VAL;
    SUSPEND;
  END

  -- Справочник изданий - только те, по которым есть хотя бы один экземпляр
  FOR
    SELECT B.BOOKID, TRIM(B.NAME), A.AUTHORNAME, P.PUBLISHERNAME, COALESCE(B.COLLECTIVEAUTHOR, '') || COALESCE(B.OTHERAUTHORS, ''), B.BBKCODE, B.UDK, B.PARTNO, B.PARTNAME, B.PUBLICATIONDATE
    FROM LIB_BOOK B
    LEFT JOIN LIB_AUTHOR A ON A.AUTHORID = B.AUTHORID
    JOIN LIB_PUBLISHER P ON P.PUBLISHERID = B.PUBLISHERID
    WHERE (:I$MODE IS NULL OR :I$MODE = 'BOOKALL' OR :I$MODE = 'ALL' OR :I$MODE = 'TEXTBOOKS') AND B.BOOKTYPEID = 0 -- книги
    ORDER BY 2
    INTO :V$BOOK_ID, :VAL, :V$AUTHOR, :V$PUBL, :V$AUTHORS, :V$BBK, :V$UDK, :V$DOCNO, :Y, :C1
  DO
  BEGIN
    IF (NOT EXISTS(SELECT FIRST 1 1 FROM LIB_COPY C WHERE C.BOOKID = :V$BOOK_ID)) THEN
      CONTINUE;

    IF (V$AUTHOR IS NULL AND V$AUTHORS = '') THEN
    BEGIN
      VAL = 'Не заполнен автор для  ' || VAL || ', год: ' || COALESCE(C1, 'нет') || COALESCE(', часть: ' || Y, '');
      SUSPEND;
      CONTINUE;
    END

    V$DEST_ID = NULL;
    V$AUTHOR_ID = NULL;
    V$PUBL_ID = NULL;
    SELECT FIRST 1 L.LISTVAL_ID
    FROM LIB2_LISTVALS L
    WHERE L.LIST_ID = 1 AND L.DATE_DEL IS NULL AND UPPER(L.VAL) = UPPER(:V$PUBL)
    INTO :V$PUBL_ID;

    --Переносим только те книги, где издательство заполнено
    IF (V$PUBL_ID IS NULL) THEN
    BEGIN
      VAL = 'Не найдено или не заполнено издательство для ' || VAL || ', год: ' || COALESCE(C1, 'нет') || COALESCE(', часть: ' || Y, '');
      SUSPEND;
    END
    ELSE BEGIN

      SELECT FIRST 1 L.LISTVAL_ID
      FROM LIB2_LISTVALS L
      WHERE L.LIST_ID = 2 AND L.DATE_DEL IS NULL AND UPPER(L.VAL) = UPPER(:V$AUTHOR)
      INTO :V$AUTHOR_ID;

      -- перенесем номер части, если он внесен корректно
      BEGIN
        V$PART_NUM = V$DOCNO;
        WHEN ANY DO V$PART_NUM = NULL;
      END

      SELECT FIRST 1 B.OBJ_ID
      FROM LIB2_BOOKS B
      WHERE B.DATE_DEL IS NULL AND B.OBJ_TYPE = 18711 AND UPPER(B.BOOK_NAME) = UPPER(:VAL) AND B.PUBLISHER_ID = :V$PUBL_ID
        AND ((:V$AUTHOR_ID IS NOT NULL AND B.AUTHOR_ID = :V$AUTHOR_ID) OR (:V$AUTHOR_ID IS NULL AND B.AUTHORS = :V$AUTHORS))
        AND (COALESCE(:V$PART_NUM, 0) = COALESCE(B.PART_NUM, 0))
        AND (COALESCE(:C1, 0) = COALESCE(B.PUB_YEAR, 0))
      INTO :V$DEST_ID;

      -- Новое издание вносим с нулевыми количествами, пересчитаем в конце
      IF(V$DEST_ID IS NULL) THEN
      BEGIN
        INSERT INTO LIB2_BOOKS
        (OBJ_TYPE, BOOK_NAME, AUTHOR_ID, PUBLISHER_ID, AUTHORS, BBK, UDK, PART_NUM, PART_NAME, PUB_YEAR)
        VALUES (18711, :VAL, :V$AUTHOR_ID, :V$PUBL_ID, :V$AUTHORS, :V$BBK, :V$UDK, :V$PART_NUM, :Y, :C1)
        RETURNING OBJ_ID INTO :V$DEST_ID;
      END

      VAL = VAL || ', год: ' || COALESCE(C1, 'нет') || COALESCE(', часть: ' || Y, '') || ', ' || COALESCE(V$AUTHOR, V$AUTHORS, '');
      SUSPEND;
    END
  END

  -- Поступление и списание
  -- Справочник поставщиков
  FOR
    SELECT DISTINCT TRIM(S.INCOMESOURCENAME)
    FROM LIB_INCOMESOURCE S
    LEFT JOIN LIB2_LISTVALS L ON L.DATE_DEL IS NULL AND L.LIST_ID = 4 AND L.VAL = TRIM(S.INCOMESOURCENAME)
    WHERE L.LISTVAL_ID IS NULL AND S.INCOMESOURCENAME IS NOT NULL
    ORDER BY 1
    INTO :VAL
  DO
  BEGIN
    INSERT INTO LIB2_LISTVALS
    (LIST_ID, VAL)
    VALUES (4, :VAL);

    VAL = 'Контрагент: ' || VAL;
    SUSPEND;
  END

  -- Накладные - поступление
  FOR
    SELECT I.INCOMEID, I.INCOMETYPE, TRIM(S.INCOMESOURCENAME), I.RECNO, I.INCOMEDATE, I.DOCNO, I.DOCDATE
    FROM LIB_INCOME I
    LEFT JOIN LIB_INCOMESOURCE S ON S.INCOMESOURCEID = I.INCOMESOURCEID
    WHERE (:I$MODE IS NULL OR :I$MODE = 'BOOKALL' OR :I$MODE = 'ALL' OR :I$MODE = 'TEXTBOOKS') AND I.INCOMETYPE = 1 -- книги
    ORDER BY 5, 1
    INTO :V$OBJ_ID, :V$TYPE, :VAL, :V$REC, :V$DATE, :V$DOCNO, :V$DOCDATE
  DO
  BEGIN
    -- Контрагент обязательно найдется, если он был указан в старом библиографе
    V$PUBL_ID = NULL;
    SELECT FIRST 1 L.LISTVAL_ID
    FROM LIB2_LISTVALS L
    WHERE L.DATE_DEL IS NULL AND L.LIST_ID = 4 AND L.VAL = :VAL
    INTO :V$PUBL_ID;

    -- Поступление книг
    V$DEST_ID = NULL;
    SELECT FIRST 1 I.OBJ_ID
    FROM LIB2_INVOICES I
    WHERE I.DATE_DEL IS NULL AND (I.CONTRAGENT_ID = :V$PUBL_ID OR (:V$PUBL_ID IS NULL AND I.CONTRAGENT_ID IS NULL))
      AND COALESCE(I.ACTION_NUM, '') = COALESCE(:VAL, '') AND I.ACTION_DATE = :V$DATE AND I.TYPE_ID = 0
    INTO :V$DEST_ID;

    IF(V$DEST_ID IS NULL) THEN
    BEGIN
      INSERT INTO LIB2_INVOICES
      (TYPE_ID, LOC_INDEX, CONTRAGENT_ID, ACTION_DATE, ACTION_NUM, DOCUMENT_DATE, DOCUMENT_NUM)
      VALUES (0, 1, :V$PUBL_ID, :V$DATE, :VAL, :V$DOCDATE, :V$DOCNO)
      RETURNING OBJ_ID
      INTO :V$DEST_ID;
    END

    VAL = 'Накладная поступления: ' || COALESCE(VAL, '');
    SUSPEND;

    -- Конкретные строки
    FOR
      SELECT B.BOOKID, TRIM(C.INVNO), C.CURPRICE, TRIM(B.NAME), P.PUBLISHERNAME, A.AUTHORNAME, COALESCE(B.COLLECTIVEAUTHOR, '') || COALESCE(B.OTHERAUTHORS, ''),
        B.PARTNO, B.PUBLICATIONDATE
      FROM LIB_COPY C
      JOIN LIB_BOOK B ON B.BOOKID = C.BOOKID
      LEFT JOIN LIB_AUTHOR A ON A.AUTHORID = B.AUTHORID
      JOIN LIB_PUBLISHER P ON P.PUBLISHERID = B.PUBLISHERID
      WHERE C.INCOMEID = :V$OBJ_ID AND CHAR_LENGTH(C.INVNO) > 1 AND (B.AUTHORID IS NOT NULL OR B.COLLECTIVEAUTHOR IS NOT NULL OR B.OTHERAUTHORS IS NOT NULL)
      ORDER BY 1, 2
      INTO :V$OBJ_ID, :V$DOCNO, :V$PRICE, :VAL, :V$PUBL, :V$AUTHOR, :V$AUTHORS, :Y, :C1
    DO
    BEGIN
      -- Ищем ID автора и издательства
      V$PUBL_ID = NULL;
      SELECT FIRST 1 L.LISTVAL_ID
      FROM LIB2_LISTVALS L
      WHERE L.LIST_ID = 1 AND L.DATE_DEL IS NULL AND UPPER(L.VAL) = UPPER(:V$PUBL)
      INTO :V$PUBL_ID;

      -- ищем с номера части, если он внесен корректно
      BEGIN
        V$PART_NUM = Y;
        WHEN ANY DO V$PART_NUM = NULL;
      END

      IF(V$PUBL_ID IS NULL) THEN
      BEGIN
        VAL = 'Не найдено или не заполнено издательство для ' || VAL || ', год: ' || COALESCE(C1, 'нет') || COALESCE(', часть: ' || Y, '');
        SUSPEND;
      END
      ELSE BEGIN
        V$AUTHOR_ID = NULL;
        SELECT FIRST 1 L.LISTVAL_ID
        FROM LIB2_LISTVALS L
        WHERE L.LIST_ID = 2 AND L.DATE_DEL IS NULL AND UPPER(L.VAL) = UPPER(:V$AUTHOR)
        INTO :V$AUTHOR_ID;

        V$BOOK_ID = NULL;
        SELECT FIRST 1 B.OBJ_ID
        FROM LIB2_BOOKS B
        WHERE B.DATE_DEL IS NULL AND B.OBJ_TYPE = 18711 AND UPPER(B.BOOK_NAME) = UPPER(:VAL) AND B.PUBLISHER_ID = :V$PUBL_ID
          AND ((:V$AUTHOR_ID IS NOT NULL AND B.AUTHOR_ID = :V$AUTHOR_ID) OR (:V$AUTHOR_ID IS NULL AND UPPER(B.AUTHORS) = UPPER(:V$AUTHORS)))
          AND (COALESCE(:V$PART_NUM, 0) = COALESCE(B.PART_NUM, 0))
          AND (COALESCE(:C1, 0) = COALESCE(B.PUB_YEAR, 0))
        INTO :V$BOOK_ID;

        IF(V$BOOK_ID IS NOT NULL) THEN BEGIN
          V$INST_ID = NULL;
          SELECT FIRST 1 I.OBJ_ID
          FROM LIB2_INSTANCES I
          WHERE I.DATE_DEL IS NULL AND I.BOOK_ID = :V$BOOK_ID AND I.INV_CODE = :V$DOCNO
          INTO :V$INST_ID;

          IF(V$INST_ID IS NULL) THEN
          BEGIN
            -- !! Поскольку мы сбрасываем невалидный инв. код в -1, то при каждом следующем прогоне скрипта будет создаваться новый экземпляр.
            BEGIN
              V$INV_CODE = V$DOCNO;
              WHEN ANY DO V$INV_CODE = -1;
            END

            SELECT COALESCE(MAX(I2.INVOICE_IN_IDX), 0) + 1 FROM LIB2_INSTANCES I2 WHERE I2.DATE_DEL IS NULL AND I2.INVOICE_IN_ID = :V$DEST_ID INTO :C1;

            INSERT INTO LIB2_INSTANCES (BOOK_ID, INV_CODE, INV_VALUE, SRC_COST, CURRENT_COST, INVOICE_IN_ID, LOC_INDEX, INVOICE_IN_IDX)
            VALUES (:V$BOOK_ID, :V$DOCNO, :V$INV_CODE, :V$PRICE, :V$PRICE, :V$DEST_ID, 1, :C1)
            RETURNING OBJ_ID
            INTO :V$INST_ID;
          END
        END
        ELSE BEGIN
          VAL = 'Книга не найдена ' || VAL || ', год: ' || COALESCE(C1, 'нет') || COALESCE(', часть: ' || Y, '');
          SUSPEND;
        END
      END
    END

  END

  -- Накладные - списание
  FOR
    SELECT I.REMOVALID, I.REMOVALTYPE, NULL, I.RECNO, I.REMOVALDATE, I.DOCNO, I.DOCDATE, RR.REMOVALREASONNAME
    FROM LIB_REMOVAL I
    LEFT JOIN LIB_REMOVALREASON RR ON RR.REMOVALREASONID = I.REMOVALREASONID
    WHERE (:I$MODE IS NULL OR :I$MODE = 'BOOKALL' OR :I$MODE = 'ALL' OR :I$MODE = 'TEXTBOOKS') AND I.REMOVALTYPE = 1 -- книги
    ORDER BY 5, 1
    INTO :V$OBJ_ID, :V$TYPE, :VAL, :V$REC, :V$DATE, :V$DOCNO, :V$DOCDATE, :V$AUTHOR
  DO
  BEGIN
    -- Контрагент тут нужен
    V$PUBL_ID = NULL;
    V$REASON = NULL;

    SELECT FIRST 1 L.LISTVAL_ID
    FROM LISTVALS_LIST(384) L
    WHERE L.IS_DEL = 0 AND UPPER(L.VAL) = UPPER(:V$AUTHOR)
    INTO :V$REASON;

    -- Списание книг
    V$DEST_ID = NULL;
    SELECT FIRST 1 I.OBJ_ID
    FROM LIB2_INVOICES I
    WHERE I.DATE_DEL IS NULL AND (I.CONTRAGENT_ID = :V$PUBL_ID OR (:V$PUBL_ID IS NULL AND I.CONTRAGENT_ID IS NULL))
      AND COALESCE(I.ACTION_NUM, '') = COALESCE(:VAL, '') AND I.ACTION_DATE = :V$DATE AND I.TYPE_ID = 10
    INTO :V$DEST_ID;

    IF(V$DEST_ID IS NULL) THEN
    BEGIN
      INSERT INTO LIB2_INVOICES
      (TYPE_ID, LOC_INDEX, CONTRAGENT_ID, REASON_ID, ACTION_DATE, ACTION_NUM, DOCUMENT_DATE, DOCUMENT_NUM)
      VALUES (10, 1, :V$PUBL_ID, :V$REASON, :V$DATE, :VAL, :V$DOCDATE, :V$DOCNO)
      RETURNING OBJ_ID
      INTO :V$DEST_ID;
    END

    VAL = 'Накладная списания: ' || V$OBJ_ID;
    SUSPEND;

    -- Конкретные строки
    FOR
      SELECT C.INVNO, C.CURPRICE, TRIM(B.NAME), P.PUBLISHERNAME, A.AUTHORNAME, COALESCE(B.COLLECTIVEAUTHOR, '') || COALESCE(B.OTHERAUTHORS, ''), B.PARTNO, B.PUBLICATIONDATE
      FROM LIB_COPY C
      JOIN LIB_BOOK B ON B.BOOKID = C.BOOKID
      LEFT JOIN LIB_AUTHOR A ON A.AUTHORID = B.AUTHORID
      JOIN LIB_PUBLISHER P ON P.PUBLISHERID = B.PUBLISHERID
      WHERE C.REMOVALID = :V$OBJ_ID AND CHAR_LENGTH(C.INVNO) > 2
      ORDER BY B.BOOKID, 1
      INTO :V$DOCNO, :V$PRICE, :VAL, :V$PUBL, :V$AUTHOR, :V$AUTHORS, :Y, :C1
    DO
    BEGIN
      -- ищем с номера части, если он внесен корректно
      BEGIN
        V$PART_NUM = Y;
        WHEN ANY DO V$PART_NUM = NULL;
      END

      -- Ищем ID автора и издательства
      V$AUTHOR_ID = NULL;
      V$PUBL_ID = NULL;
      SELECT FIRST 1 L.LISTVAL_ID
      FROM LIB2_LISTVALS L
      WHERE L.LIST_ID = 1 AND L.DATE_DEL IS NULL AND UPPER(L.VAL) = UPPER(:V$PUBL)
      INTO :V$PUBL_ID;

      IF(V$PUBL_ID IS NULL) THEN
      BEGIN
        VAL = 'Не найдено или не заполнено издательство для ' || VAL || ', год: ' || COALESCE(C1, 'нет') || COALESCE(', часть: ' || Y, '');
        SUSPEND;
      END
      ELSE BEGIN
        SELECT FIRST 1 L.LISTVAL_ID
        FROM LIB2_LISTVALS L
        WHERE L.LIST_ID = 2 AND L.DATE_DEL IS NULL AND UPPER(L.VAL) = UPPER(:V$AUTHOR)
        INTO :V$AUTHOR_ID;

        V$BOOK_ID = NULL;
        SELECT FIRST 1 B.OBJ_ID
        FROM LIB2_BOOKS B
        WHERE B.DATE_DEL IS NULL AND B.OBJ_TYPE = 18711 AND UPPER(B.BOOK_NAME) = UPPER(:VAL) AND B.PUBLISHER_ID = :V$PUBL_ID
          AND ((:V$AUTHOR_ID IS NOT NULL AND B.AUTHOR_ID = :V$AUTHOR_ID) OR (:V$AUTHOR_ID IS NULL AND B.AUTHORS = :V$AUTHORS))
          AND (COALESCE(:V$PART_NUM, 0) = COALESCE(B.PART_NUM, 0))
          AND (COALESCE(:C1, 0) = COALESCE(B.PUB_YEAR, 0))
        INTO :V$BOOK_ID;

        IF(V$BOOK_ID IS NOT NULL) THEN
        BEGIN
          V$INST_ID = NULL;
          V$INV_ID = NULL;
          SELECT FIRST 1 I.OBJ_ID, I.INVOICE_OUT_ID
          FROM LIB2_INSTANCES I
          WHERE I.DATE_DEL IS NULL AND I.BOOK_ID = :V$BOOK_ID AND I.INV_CODE = :V$DOCNO
          INTO :V$INST_ID, :V$INV_ID;

          IF(V$INST_ID IS NOT NULL AND V$INV_ID IS NULL) THEN
          UPDATE LIB2_INSTANCES
          SET INVOICE_OUT_ID = :V$DEST_ID, INVOICE_OUT_IDX = COALESCE((SELECT MAX(I2.INVOICE_IN_IDX) + 1 FROM LIB2_INSTANCES I2 WHERE I2.DATE_DEL IS NULL AND I2.INVOICE_OUT_ID = :V$DEST_ID), 1)
          WHERE OBJ_ID = :V$INST_ID;
        END
        ELSE BEGIN
          VAL = 'Книга не найдена ' || VAL || ', год: ' || COALESCE(C1, 'нет') || COALESCE(', часть: ' || Y, '');
          SUSPEND;
        END
      END
    END
  END

  -- Выдача и возврат на руки
  IF (:I$MODE IS NULL OR :I$MODE = 'BOOKALL' OR :I$MODE = 'ALL' OR :I$MODE = 'TEXTBOOKS') THEN
  FOR
    SELECT COALESCE(AA.PERSONID, AA.SCBOYID), M.ISSUEDATE, M.RETURNDATE, M.TERMDATE, C.INVNO
    FROM LIB_MOVEMENT M
    JOIN LIB_COPY C ON C.COPYID = M.COPYID
    JOIN LIB_ABONEMENT AA ON AA.ABONEMENTID = M.ABONEMENTID
    ORDER BY 1, 2, 3
    INTO :V$AUTHOR_ID, :V$DATE, :V$DOCDATE, :V$TDATE, :S
  DO
  BEGIN
    -- найдем соотвествующий экземпляр по инвентаризационному номеру
    V$BOOK_ID = NULL;
    V$OBJ_ID = NULL;
    SELECT FIRST 1 I.OBJ_ID, I.BOOK_ID
    FROM LIB2_INSTANCES I
    WHERE I.DATE_DEL IS NULL AND UPPER(I.INV_CODE) = UPPER(:S)
    INTO :V$OBJ_ID, :V$BOOK_ID;

    IF (V$OBJ_ID IS NOT NULL AND NOT EXISTS(SELECT FIRST 1 1
      FROM LIB2_USAGE U
      WHERE U.DATE_DEL IS NULL AND U.INSTANCE_ID = :V$OBJ_ID AND U.BOOK_ID = :V$BOOK_ID AND U.REF_ID = :V$AUTHOR_ID AND U.ACTION_DATE = :V$DATE
    )) THEN
    BEGIN
      V$DEST_ID = NULL;
      SELECT TYPE_ID FROM OBJECTS WHERE OBJ_ID = :V$AUTHOR_ID INTO :V$DEST_ID;

      INSERT INTO LIB2_USAGE
      (BOOK_ID, INSTANCE_ID, REF_ID, REF_TYPE_ID, ACTION_DATE, PLAN_DATE, RETURN_DATE)
      VALUES (:V$BOOK_ID, :V$OBJ_ID, :V$AUTHOR_ID, :V$DEST_ID, :V$DATE, COALESCE(:V$TDATE, DATEADD(1 MONTH TO :V$DATE)), :V$DOCDATE);

      VAL = 'Выдача и возврат: ' || V$OBJ_ID;
      SUSPEND;
    END
  END

  -- Признаки доступности у экземпляров
  FOR
    SELECT I.OBJ_ID, I.INVOICE_OUT_ID
    FROM LIB2_BOOKS B
    JOIN LIB2_INSTANCES I ON I.DATE_DEL IS NULL AND I.BOOK_ID = B.OBJ_ID
    WHERE B.DATE_DEL IS NULL AND B.OBJ_TYPE = 18711  -- книги
    ORDER BY 1
    INTO :V$BOOK_ID, :V$OBJ_ID
  DO
  BEGIN
    IF(V$OBJ_ID IS NOT NULL) THEN C1 = 0;
    ELSE
    BEGIN
      C1 = 1;
      SELECT FIRST 1 0
      FROM LIB2_USAGE U
      WHERE U.DATE_DEL IS NULL AND U.INSTANCE_ID = :V$BOOK_ID AND U.RETURN_DATE IS NULL AND U.LOSS_DATE IS NULL
      INTO :C1;
    END

    UPDATE LIB2_INSTANCES
    SET IS_FREE = :C1
    WHERE OBJ_ID = :V$BOOK_ID;
  END

  -- Пересчет количества
  FOR
    SELECT B.OBJ_ID, B.BOOK_NAME, B.PART_NUM, B.PUB_YEAR
    FROM LIB2_BOOKS B
    WHERE B.DATE_DEL IS NULL AND B.OBJ_TYPE = 18711  -- книги
    ORDER BY 1
    INTO :V$BOOK_ID, :V$AUTHORS, :V$PART_NUM, :G1
  DO
  BEGIN
    C1 = 0;
    -- Всего экземпляров
    SELECT COALESCE(COUNT(*), 0)
    FROM LIB2_INSTANCES C
    WHERE C.DATE_DEL IS NULL AND C.BOOK_ID = :V$BOOK_ID AND C.INVOICE_OUT_ID IS NULL
    INTO :C1;

    -- Кол-во экземпляров в фонде
    C2 = 0;
    SELECT COALESCE(COUNT(*), 0)
    FROM LIB2_INSTANCES C
    WHERE C.DATE_DEL IS NULL AND C.BOOK_ID = :V$BOOK_ID AND C.INVOICE_OUT_ID IS NULL AND C.IS_FREE = 1
    INTO :C2;

    UPDATE LIB2_BOOKS
    SET N_AVAIL = :C1, N_FREE = :C2
    WHERE OBJ_ID = :V$BOOK_ID;
  END

  -- Если внесены учебники - создаем запись сводной накладной поступления
  IF((I$MODE IS NULL OR I$MODE = 'ALL' OR I$MODE = 'TBALL') AND EXISTS(
    SELECT FIRST 1 1
    FROM LINKS L2
    JOIN LINKS L105 ON L105.PARENT_ID = L2.OBJ_ID AND L105.OBJ_TYPE_ID = 105 AND L105.DATE_DEL IS NULL
    JOIN LINKS L107 ON L107.PARENT_ID = L105.OBJ_ID AND L107.OBJ_TYPE_ID = 107 AND L107.DATE_DEL IS NULL
    JOIN VALL V646 ON V646.OBJ_ID = L107.OBJ_ID AND V646.PARAM_ID = 646 AND V646.IS_DEL = 0 AND V646.LISTVAL_ID = 2057 -- учебник
    JOIN VALI V648 ON V648.OBJ_ID = L107.OBJ_ID AND V648.PARAM_ID = 648 AND V648.IS_DEL = 0 AND V648.VAL > 0 -- количество
    LEFT JOIN VALR V654 ON V654.OBJ_ID = L107.OBJ_ID AND V654.PARAM_ID = 654 AND V654.IS_DEL = 0 -- предмет
    JOIN VALS V2655 ON V2655.OBJ_ID = L107.OBJ_ID AND V2655.PARAM_ID = 2655 AND V2655.IS_DEL = 0 -- код
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  ))
  THEN
  BEGIN
    V$INV_ID = NULL;
    VAL = 'Пакетное приходование учебников из Параграф';
    SELECT FIRST 1 I.OBJ_ID
    FROM LIB2_INVOICES I
    WHERE I.DATE_DEL IS NULL AND I.TYPE_ID = 1 AND I.USER_ID IS NULL AND I.CONTRAGENT_ID IS NULL AND I.COMMENTS = :VAL
    INTO :V$INV_ID;

    IF(V$INV_ID IS NULL) THEN
    BEGIN
      INSERT INTO LIB2_INVOICES
      (TYPE_ID, LOC_INDEX, CONTRAGENT_ID, ACTION_DATE, ACTION_NUM, DOCUMENT_DATE, DOCUMENT_NUM, COMMENTS)
      VALUES (1, 1, NULL, CURRENT_DATE, 'УЧЕБНИКИ', NULL, NULL, :VAL)
      RETURNING OBJ_ID
      INTO :V$INV_ID;
    END
  END

  -- Учебники ФПУ из внесенных в МТР
  -- спаси бог от наличия нескольких записей с одним годом издания и одинаковыми количествами
  IF(EXTRACT(MONTH FROM CURRENT_DATE) < 6) THEN V$DATE_TO = '31.05.' || EXTRACT(YEAR FROM CURRENT_DATE);
    ELSE V$DATE_TO = '31.05.' || (EXTRACT(YEAR FROM CURRENT_DATE) + 1);

  FOR
    SELECT L107.OBJ_ID, V2655.SVAL, V650.SVAL, V654.VAL, V648.VAL
    FROM LINKS L2
    JOIN LINKS L105 ON L105.PARENT_ID = L2.OBJ_ID AND L105.OBJ_TYPE_ID = 105 AND L105.DATE_DEL IS NULL
    JOIN LINKS L107 ON L107.PARENT_ID = L105.OBJ_ID AND L107.OBJ_TYPE_ID = 107 AND L107.DATE_DEL IS NULL
    JOIN VALL V646 ON V646.OBJ_ID = L107.OBJ_ID AND V646.PARAM_ID = 646 AND V646.IS_DEL = 0 AND V646.LISTVAL_ID = 2057 -- учебник
    LEFT JOIN VALS V650 ON V650.OBJ_ID = L107.OBJ_ID AND V650.PARAM_ID = 650 AND V650.IS_DEL = 0 -- год издания, считаем 2024 если не задан
    JOIN VALI V648 ON V648.OBJ_ID = L107.OBJ_ID AND V648.PARAM_ID = 648 AND V648.IS_DEL = 0 AND V648.VAL > 0 -- количество
    LEFT JOIN VALR V654 ON V654.OBJ_ID = L107.OBJ_ID AND V654.PARAM_ID = 654 AND V654.IS_DEL = 0 -- предмет
    JOIN VALS V2655 ON V2655.OBJ_ID = L107.OBJ_ID AND V2655.PARAM_ID = 2655 AND V2655.IS_DEL = 0 -- код
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      AND (:I$MODE IS NULL OR :I$MODE = 'ALL' OR :I$MODE = 'TEXTBOOKS' OR :I$MODE = 'TBMOVE' OR :I$MODE = 'TBALL')
    ORDER BY 2, 1
    INTO :V$OBJ_ID, :VAL, :Y, :V$SUBJECT_ID2, :C2
  DO
  BEGIN
    -- Год издания - строка, может быть с косяками
    BEGIN
      C1 = COALESCE(Y, '');
      WHEN ANY DO C1 = 2024;
    END

    -- Восстанавливаем id ФПУ - ищем последний код, вопрос актуализации будет на школе
    V$FPU_ID = NULL;
    SELECT FIRST 1 F.OBJ_ID, F.BOOKNAME, F.AUTHORS, P.PUBLISHER_NAME, F.SUBJECT_ID, F.STAGE_ID, F.GRADE_FROM, F.GRADE_TO, F.ATTRS
    FROM LIB_FPU_CODES C
    LEFT JOIN LIB_FPU_CODES C2 ON C2.BOOK_ID = C.BOOK_ID AND C2.DATE_DEL IS NULL AND C2.DATE_ADD < C.DATE_ADD
    JOIN LIB_FPU F ON F.OBJ_ID = C.BOOK_ID AND F.DATE_DEL IS NULL AND (F.VALID_BY IS NULL OR F.VALID_BY > CURRENT_DATE)
    JOIN LIB_FP_PUBLISHER P ON P.PUBLISHER_ID = F.PUBLISHER_ID
    WHERE C.DATE_DEL IS NULL AND C.BOOKCODE = :VAL AND C2.BOOK_ID IS NULL
    INTO :V$FPU_ID, :S, :V$AUTHORS, :V$PUBL, :V$SUBJECT_ID, :ST, :G1, :G2, :AA;

    IF(V$FPU_ID IS NULL) THEN
    BEGIN
      VAL = VAL || ' код ФПУ не найден, пропускаем';
    END
    ELSE
    BEGIN
      V$BOOK_ID = NULL;
      SELECT FIRST 1 B.OBJ_ID
      FROM LIB2_BOOKS B
      WHERE B.DATE_DEL IS NULL AND B.OBJ_TYPE = 18712 AND B.FPU_ID = :V$FPU_ID AND B.PUB_YEAR = :C1
      INTO :V$BOOK_ID;

      -- Дополнительный предмет для иностранных языков по видам - ставим Иностранный язык
      IF(V$SUBJECT_ID2 = V$SUBJECT_ID OR V$SUBJECT_ID2 IS NULL) THEN
      BEGIN
        IF(V$SUBJECT_ID2 IN (188, 189, 2129, 3090, 3130, 3131, 3132, 3133, 3134, 3136, 3153, 3154, 3155, 5520, 5522, 34753)) THEN V$SUBJECT_ID2 = 178;
      END

      IF(V$BOOK_ID IS NULL) THEN
      BEGIN
        V$PUBL_ID = NULL;
        SELECT FIRST 1 L.LISTVAL_ID
        FROM LIB2_LISTVALS L
        WHERE L.LIST_ID = 1 AND L.DATE_DEL IS NULL AND UPPER(L.VAL) = UPPER(:V$PUBL)
        INTO :V$PUBL_ID;
        IF(V$PUBL_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не найдено или не заполнено издательство для ' || VAL;

        INSERT INTO LIB2_BOOKS
        (OBJ_TYPE, BOOK_NAME, AUTHOR_ID, PUBLISHER_ID, AUTHORS, SUBJECT_ID, SUBJECT_ID2, PUB_YEAR, STAGE_FROM, STAGE_TO, STAGE_NUM,
          EDU_LEVEL_ID, ADAPT_ID, DIFF_LEVEL_ID, FPU_ID, FPU_CODE)
        VALUES (18712, :S, NULL, :V$PUBL_ID, :V$AUTHORS, :V$SUBJECT_ID, IIF(:V$SUBJECT_ID2 <> :V$SUBJECT_ID, :V$SUBJECT_ID2, NULL), :C1, :G1, :G2, IIF(:G2 = :G1, :G1, :G1 || '-' || :G2),
          :ST, IIF(:AA = 3, 1, 0), IIF(:AA = 2, 1, 0), :V$FPU_ID,  :VAL)
        RETURNING OBJ_ID INTO :V$BOOK_ID;
      END

      -- Проверяем наличие записи в накладной
      IF(I$MODE IS NULL OR I$MODE = 'ALL' OR I$MODE = 'TBMOVE' OR I$MODE = 'TBALL') THEN
      BEGIN
        -- Накладную в режиме TBMOVE школа должна была внести
        IF(I$MODE IS NULL OR I$MODE = 'ALL' OR I$MODE = 'TBALL') THEN
        BEGIN
          -- найдем кол-во всех учебников в МТР с данным кодом ФПУ, чтобы добавить это кол-во в поступление
          -- учебник с одним кодом может быть внесен несколько раз, чтобы выдавать по разным предметам
          C2 = NULL;
          SELECT COALESCE(SUM(V648.VAL), 0)
          FROM LINKS L2
          JOIN LINKS L105 ON L105.PARENT_ID = L2.OBJ_ID AND L105.OBJ_TYPE_ID = 105 AND L105.DATE_DEL IS NULL
          JOIN LINKS L107 ON L107.PARENT_ID = L105.OBJ_ID AND L107.OBJ_TYPE_ID = 107 AND L107.DATE_DEL IS NULL
          JOIN VALL V646 ON V646.OBJ_ID = L107.OBJ_ID AND V646.PARAM_ID = 646 AND V646.IS_DEL = 0 AND V646.LISTVAL_ID = 2057 -- учебник
          JOIN VALS V650 ON V650.OBJ_ID = L107.OBJ_ID AND V650.PARAM_ID = 650 AND V650.IS_DEL = 0 AND V650.VAL = :Y -- год издания
          JOIN VALI V648 ON V648.OBJ_ID = L107.OBJ_ID AND V648.PARAM_ID = 648 AND V648.IS_DEL = 0 -- количество
          JOIN VALS V2655 ON V2655.OBJ_ID = L107.OBJ_ID AND V2655.PARAM_ID = 2655 AND V2655.IS_DEL = 0 AND V2655.VAL = :VAL -- код ФПУ
          WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
          INTO :C2;

          V$DEST_ID = NULL;
          SELECT FIRST 1 B.OBJ_ID
          FROM LIB2_BATCHES B
          WHERE B.DATE_DEL IS NULL AND B.BOOK_ID = :V$BOOK_ID AND B.QUANTITY = :C2 AND B.INVOICE_IN_ID = :V$INV_ID
          INTO :V$DEST_ID;

          IF(V$DEST_ID IS NULL) THEN
          BEGIN
            INSERT INTO LIB2_BATCHES
            (BOOK_ID, QUANTITY, INVOICE_IN_ID, LOC_INDEX, INVOICE_IN_IDX)
            VALUES (:V$BOOK_ID, :C2, :V$INV_ID, 1,
              COALESCE((SELECT MAX(I2.INVOICE_IN_IDX) + 1 FROM LIB2_BATCHES I2 WHERE I2.DATE_DEL IS NULL AND I2.INVOICE_IN_ID = :V$INV_ID), 1));
          END
        END

        VAL = VAL || ' добавлен или обновлен ' || V$BOOK_ID;

        -- Выдача по ГУП
        -- Внимание: тут могут быть повторы, вносить будем только по самому первому предмету по УП, по порядку предметов и сортируем
        -- не переносим учебники по индивидуальному проекту
        FOR
          SELECT DISTINCT PS.PLAN_ID, R.LOAD_ID, PS.GLOBAL_INDEX, L256.OBJ_ID
          FROM PLAN_RESOURCES R
          JOIN PLAN_LOADS PL ON PL.OBJ_ID = R.LOAD_ID AND PL.DATE_DEL IS NULL
          JOIN PLAN_SUBJECTS PS ON PS.OBJ_ID = PL.SUBJECT_ID AND PS.DATE_DEL IS NULL AND PS.SUBJECT_ID <> 34651
          -- только групповые
          JOIN VALL V3016 ON V3016.OBJ_ID = PS.PLAN_ID AND V3016.PARAM_ID = 3016 AND V3016.IS_DEL = 0 AND V3016.LISTVAL_ID = 5465
          -- ГУП должны быть только в действующих УП
          JOIN LINKS L256 ON L256.PARENT_ID = PL.STAGE_ID AND L256.OBJ_TYPE_ID = 256 AND L256.DATE_DEL IS NULL
          WHERE R.DATE_DEL IS NULL AND R.RES_ID = :V$OBJ_ID AND R.RES_TYPE_ID = 4
            -- только записи, где обеспеченность >= текущего числа обучающихся по УП
            -- тут могут оказаться пустые ГУП, они исключаться в подчиненной выборке
            AND R.QTY > 0 AND R.QTY >= (
              SELECT COUNT(*)
              FROM LINKS L256X
              JOIN LINKS L10X ON L10X.PARENT_ID = L256X.OBJ_ID AND L10X.OBJ_TYPE_ID = 10 AND L10X.DATE_DEL IS NULL
              WHERE L256X.PARENT_ID = PL.STAGE_ID AND L256.OBJ_TYPE_ID = 256 AND L256.DATE_DEL IS NULL
            )
          ORDER BY 1, 3
          INTO :V$PLAN_ID, :V$LOAD_ID, :SQ, :V$INST_ID
        DO
        BEGIN
          -- Группы надо переразбить по классам, убираем кривые ГУП без учеников
          -- количество за пределами текущего количества учеников будет потеряно
          FOR
            SELECT LP9.PARENT_ID, COUNT(*)
            FROM LINKS L10
            JOIN LINKS LP9 ON LP9.OBJ_ID = L10.OBJ_ID AND LP9.PARENT_TYPE_ID = 9 AND LP9.DATE_DEL IS NULL
            WHERE L10.PARENT_ID = :V$INST_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
            GROUP BY 1
            HAVING COUNT(*) > 0
            INTO :V$FPU_ID, :C1
          DO
          BEGIN
            -- Вносим выдачу только на класс - на учеников разбивку не делаем
            -- но один учебник в сечении класс-план может выдаваться только один раз
            -- с учетом повторной обеспеченности TODO
            IF(C1 > 0 AND NOT EXISTS(
              SELECT FIRST 1 1
              FROM LIB2_USAGE U
              JOIN PLAN_LOADS PL ON PL.OBJ_ID = U.LOAD_ID
              JOIN PLAN_SUBJECTS PS ON PS.OBJ_ID = PL.SUBJECT_ID AND PS.PLAN_ID = :V$PLAN_ID
              WHERE U.DATE_DEL IS NULL AND U.BOOK_ID = :V$BOOK_ID AND U.REF_TYPE_ID = 9 AND U.REF_ID = :V$FPU_ID AND U.LOAD_ID = :V$LOAD_ID
            ))
            THEN
            BEGIN
              V$DEST_ID = NULL;
              SELECT FIRST 1 U.OBJ_ID
              FROM LIB2_USAGE U
              WHERE U.DATE_DEL IS NULL AND U.BOOK_ID = :V$BOOK_ID AND U.REF_TYPE_ID = 9 AND U.REF_ID = :V$FPU_ID AND U.LOAD_ID = :V$LOAD_ID
              INTO :V$DEST_ID;

              IF(V$DEST_ID IS NULL) THEN
              BEGIN
                -- кол-во учебников, поступивших на площадку 1
                SELECT COALESCE(B.QUANTITY, 0)
                FROM LIB2_BATCHES B
                WHERE B.DATE_DEL IS NULL AND B.BOOK_ID = :V$BOOK_ID AND B.INVOICE_IN_ID IS NOT NULL AND B.LOC_INDEX = 1
                INTO :V$DEST_ID;

                IF (V$DEST_ID >= C1) THEN
                BEGIN
                  INSERT INTO LIB2_USAGE
                  (BOOK_ID, REF_TYPE_ID, REF_ID, QUANTITY, LOC_INDEX, LOAD_ID, ACTION_DATE, PLAN_DATE)
                  VALUES (:V$BOOK_ID, 9, :V$FPU_ID, :C1, 1, :V$LOAD_ID, CURRENT_DATE, :V$DATE_TO);
                  VAL = VAL || ', ' || V$FPU_ID || ' - ' || C1;
                END
                ELSE
                BEGIN
                  V$DEST_ID = C1 - COALESCE(V$DEST_ID, 0);
                  VAL = VAL || ', ' || V$FPU_ID || ' не достает для выдачи - ' || V$DEST_ID;
                END
              END
            END
          END
        END
      END
      ELSE
        VAL = VAL || ' добавлен или обновлен ' || V$BOOK_ID;
    END
    SUSPEND;
  END

  -- Пересчет количества учебников
  FOR
    SELECT B.OBJ_ID
    FROM LIB2_BOOKS B
    WHERE B.DATE_DEL IS NULL AND B.OBJ_TYPE = 18712 -- учебник
    ORDER BY 1
    INTO :V$BOOK_ID
  DO
  BEGIN
    -- Всего экземпляров
    -- пока считаем только приход, предполагается что списаний не было
    C1 = NULL;
    SELECT SUM(B.QUANTITY)
    FROM LIB2_BATCHES B
    WHERE B.DATE_DEL IS NULL AND B.BOOK_ID = :V$BOOK_ID
    INTO :C1;
    C1 = COALESCE(C1, 0);

    -- Кол-во экземпляров в фонде
    C2 = NULL;
    SELECT SUM(U.QUANTITY)
    FROM LIB2_USAGE U
    WHERE U.DATE_DEL IS NULL AND U.BOOK_ID = :V$BOOK_ID AND U.RETURN_DATE IS NULL AND (U.REF_TYPE_ID = 9 OR U.CLASS_USAGE_ID IS NULL)
    INTO :C2;
    C2 = C1 - COALESCE(C2, 0);
    IF(C2 < 0) THEN C2 = 0;

    UPDATE LIB2_BOOKS
    SET N_AVAIL = :C1, N_FREE = :C2
    WHERE OBJ_ID = :V$BOOK_ID;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIB2_USAGE_SUBJ_GUP (
    I$LOAD_ID BIGINT,
    I$CLASS_ID BIGINT,
    I$STAGE_ID BIGINT)
RETURNS (
    BOOK_NAME VARCHAR(400),
    FPU_CODE VARCHAR(40),
    COUNT_IN_USE INTEGER,
    BOOKS_LEFT INTEGER,
    YEAR_PUBLISHED INTEGER)
AS
begin
  -- для отчета по обеспеченности детализированного
  FOR
    SELECT BOOK_NAME, FPU_CODE, N_FREE, SUM(QUANTITY) QUANTITY, PUB_YEAR
    FROM
     (SELECT B.BOOK_NAME || IIF(B.PART_NUM IS NULL, '', ', часть ' || B.PART_NUM) BOOK_NAME,
        B.FPU_CODE, B.N_FREE, U.QUANTITY, B.PUB_YEAR
      FROM LIB2_USAGE U
      JOIN LIB2_BOOKS B ON B.OBJ_ID = U.BOOK_ID AND B.OBJ_TYPE = 18712 -- учебник
      JOIN LINKS LP9 ON LP9.OBJ_ID = U.REF_ID AND LP9.PARENT_TYPE_ID IN (9, 187) AND LP9.DATE_DEL IS NULL AND (:I$CLASS_ID IS NULL OR LP9.PARENT_ID = :I$CLASS_ID)
      JOIN LINKS L8 ON L8.OBJ_ID = LP9.PARENT_ID AND L8.PARENT_TYPE_ID = 8 AND L8.DATE_DEL IS NULL AND (:I$STAGE_ID IS NULL OR L8.PARENT_ID = :I$STAGE_ID)
      JOIN LIB2_LISTVALS LV ON LV.LISTVAL_ID = B.PUBLISHER_ID AND LV.DATE_DEL IS NULL
      JOIN LIB_FPU F ON F.OBJ_ID = B.FPU_ID AND F.DATE_DEL IS NULL
      WHERE U.DATE_DEL IS NULL AND (U.RETURN_DATE IS NULL AND U.LOSS_DATE IS NULL) AND U.REF_TYPE_ID = 10 -- выдано ученику
        AND (:I$LOAD_ID IS NULL OR U.LOAD_ID = :I$LOAD_ID) -- привязка к предмету через нагрузки

      UNION

      SELECT B.BOOK_NAME || IIF(B.PART_NUM IS NULL, '', ', часть ' || B.PART_NUM) BOOK_NAME,
        B.FPU_CODE, B.N_FREE, U.QUANTITY, B.PUB_YEAR
      FROM LIB2_USAGE U
      JOIN LINKS L8 ON L8.OBJ_ID = U.REF_ID AND L8.PARENT_TYPE_ID = 8 AND L8.DATE_DEL IS NULL AND (:I$STAGE_ID IS NULL OR L8.PARENT_ID = :I$STAGE_ID)
      JOIN LIB2_BOOKS B ON B.OBJ_ID = U.BOOK_ID AND B.OBJ_TYPE = 18712 -- учебник
      JOIN LIB2_LISTVALS LV ON LV.LISTVAL_ID = B.PUBLISHER_ID AND LV.DATE_DEL IS NULL
      JOIN LIB_FPU F ON F.OBJ_ID = B.FPU_ID AND F.DATE_DEL IS NULL
      WHERE U.DATE_DEL IS NULL AND (U.RETURN_DATE IS NULL AND U.LOSS_DATE IS NULL) AND U.REF_TYPE_ID = 9 AND U.CLASS_USAGE_ID IS NULL -- выдано на класс
        AND (:I$CLASS_ID IS NULL OR U.REF_ID = :I$CLASS_ID)
        AND (:I$LOAD_ID IS NULL OR U.LOAD_ID = :I$LOAD_ID) -- привязка к предмету через нагрузки
        )
    GROUP BY 1, 2, 3, 5
    INTO :BOOK_NAME, :FPU_CODE, :BOOKS_LEFT, :COUNT_IN_USE, :YEAR_PUBLISHED
  DO
  BEGIN
    SUSPEND;
  END
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIB2_WB_SUFFICIENCY_LIST (
    I$LVL BIGINT,
    I$ST BIGINT,
    I$GR BIGINT,
    I$DETAIL SMALLINT)
RETURNS (
    STAGE_ID BIGINT,
    LVL_ID BIGINT,
    PLAN_ID BIGINT,
    SUBJECT_ID BIGINT,
    PUPIL_CNT INTEGER,
    BOOKS_LEFT_CNT INTEGER,
    IN_USE_CNT INTEGER,
    BOOK_NAME VARCHAR(500),
    FPU_CODE VARCHAR(100),
    YEAR_PUBLISHED INTEGER)
AS
DECLARE VARIABLE V$YEAR INTEGER;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$STAGE_ID BIGINT;
DECLARE VARIABLE V$LOAD_ID BIGINT;
DECLARE VARIABLE V$PREV_STAGE_ID BIGINT;
DECLARE VARIABLE V$PREV_PLAN_ID BIGINT;
DECLARE VARIABLE V$REPLACE_SUBJ BIGINT;
DECLARE VARIABLE V$SUBJ_NAME VARCHAR(1000);
DECLARE VARIABLE V$HAS_TECH SMALLINT;
DECLARE VARIABLE V$HAS_FISCULT SMALLINT;
DECLARE VARIABLE V$LOAD_H SMALLINT;
begin
  -- найдем id ОУ
  SELECT OBJ_ID FROM LINKS WHERE OBJ_TYPE_ID = 2 AND PARENT_TYPE_ID IS NULL AND DATE_DEL IS NULL INTO :V$OBJ_ID;

  -- найдем текущий учебный год
  SELECT LV.COST
  FROM VALL V
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V.LISTVAL_ID AND LV.IS_DEL = 0
  WHERE V.OBJ_ID = :V$OBJ_ID AND V.PARAM_ID = 1236 AND V.IS_DEL = 0
  INTO :V$YEAR;

  BOOK_NAME = NULL;
  FPU_CODE = NULL;
  IN_USE_CNT = NULL;
  YEAR_PUBLISHED = NULL;
  BOOKS_LEFT_CNT = NULL;

  IF (I$DETAIL = 1) THEN
  BEGIN
    -- для детализированного отчета по обеспеченности
    FOR
      SELECT DISTINCT
        L54.OBJ_ID,
        V381.LISTVAL_ID,
        V1594.LISTVAL_ID,
        L400.OBJ_ID,
        PS.SUBJECT_ID,
        SUBJ.SCAPTION,
        PL.OBJ_ID,
        PS.SRC_SUBJECT_ID
      FROM LINKS L57
      JOIN VALL V2379 ON V2379.OBJ_ID = L57.OBJ_ID AND V2379.PARAM_ID = 2379 AND V2379.IS_DEL = 0 AND V2379.LISTVAL_ID = 11187 --адаптир-ть = нет
      JOIN VALI V3115 ON V3115.OBJ_ID = L57.OBJ_ID AND V3115.PARAM_ID = 3115 AND V3115.IS_DEL = 0 AND V3115.VAL = :V$YEAR -- год публик-ии текущий
      JOIN VALL V1594 ON V1594.OBJ_ID = L57.OBJ_ID AND V1594.PARAM_ID = 1594 AND V1594.IS_DEL = 0
      JOIN LISTVALS LV1594 ON LV1594.LISTVAL_ID = V1594.LISTVAL_ID AND LV1594.IS_DEL = 0 AND (:I$LVL IS NULL OR LV1594.TAG = :I$LVL)-- уровень образования
      JOIN LINKS L69 ON L69.OBJ_ID = L57.PARENT_ID AND L69.PARENT_TYPE_ID = 2 AND L69.DATE_DEL IS NULL
      JOIN VALL V2450 ON V2450.OBJ_ID = L69.OBJ_ID AND V2450.PARAM_ID = 2450 AND V2450.IS_DEL = 0 AND V2450.LISTVAL_ID IN (11385, 11387) -- общеобр или СПО
      JOIN LINKS L400 ON L400.PARENT_ID = L57.OBJ_ID AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL
      JOIN VALL V3016 ON V3016.OBJ_ID = L400.OBJ_ID AND V3016.PARAM_ID = 3016 AND V3016.IS_DEL = 0 AND V3016.LISTVAL_ID = 5465 -- УП = групповой УП
      JOIN VALL V3022 ON V3022.OBJ_ID = L400.OBJ_ID AND V3022.PARAM_ID = 3022 AND V3022.IS_DEL = 0 AND V3022.LISTVAL_ID = 3    -- УП = не ВД
      JOIN VALL V3013 ON V3013.OBJ_ID = L400.OBJ_ID AND V3013.PARAM_ID = 3013 AND V3013.IS_DEL = 0 AND V3013.LISTVAL_ID = 11715 -- статус действующий
      JOIN LINKS L54 ON L54.PARENT_ID = L400.OBJ_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL  -- этапы
      JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0 AND (:I$ST IS NULL OR :I$ST = V381.LISTVAL_ID) -- параллель
      JOIN PLAN_LOADS PL ON PL.DATE_DEL IS NULL AND PL.STAGE_ID = L54.OBJ_ID AND PL.LOAD_HOURS > 0
      JOIN PLAN_SUBJECTS PS ON PS.DATE_DEL IS NULL AND PS.OBJ_ID = PL.SUBJECT_ID AND PS.ROW_TYPE = 10 AND PS.PLAN_ID = L400.OBJ_ID AND PS.SUBJECT_ID <> 34651 -- индивидуальный проект
      JOIN PLAN_SUBJECTS SEC ON SEC.OBJ_ID = PS.PARENT_ID AND SEC.FIELD_ID = 13303 -- обязательная часть УП
      JOIN OBJECT_CAPTION_GET(PS.SUBJECT_ID) SUBJ ON 1 = 1
      WHERE L57.OBJ_TYPE_ID = 57 AND L57.PARENT_TYPE_ID = 69 AND L57.DATE_DEL IS NULL
      ORDER BY V381.LISTVAL_ID, PS.LEVEL_INDEX
      INTO :V$STAGE_ID, :STAGE_ID, :LVL_ID, :PLAN_ID, :SUBJECT_ID, :V$SUBJ_NAME, :V$LOAD_ID, :V$REPLACE_SUBJ
    DO
    BEGIN
      V$LOAD_H = 1;

      -- При переходе в следующий блок сбрасываем проверки по физкультуре и технологии
      IF(V$PREV_PLAN_ID IS NULL OR V$PREV_PLAN_ID <> PLAN_ID OR V$PREV_STAGE_ID <> V$STAGE_ID) THEN
      BEGIN
        V$HAS_FISCULT = 0;
        V$HAS_TECH = 0;
      END
      V$PREV_PLAN_ID = PLAN_ID;
      V$PREV_STAGE_ID = V$STAGE_ID;

      -- Если замена не прописана - анализируем текстовое название предмета
      IF(V$REPLACE_SUBJ IS NULL) THEN
      BEGIN
        IF(SUBSTRING(V$SUBJ_NAME FROM 1 FOR 19) = 'Физическая культура') THEN V$REPLACE_SUBJ = 205;
        ELSE IF(SUBSTRING(V$SUBJ_NAME FROM 1 FOR 10) = 'Технология') THEN V$REPLACE_SUBJ = 200;
      END

      IF(SUBJECT_ID = 205) THEN
      BEGIN
        -- Если предмет сама физкультура - оставим только ее (порядок сортировки обеспечит что она первая)
        V$HAS_FISCULT = 1;
      END
      ELSE IF(SUBJECT_ID = 200) THEN
      BEGIN
        -- Если предмет сама технология - оставим только ее (порядок сортировки обеспечит что она первая)
        V$HAS_TECH = 1;
      END
      ELSE IF(V$REPLACE_SUBJ IS NOT NULL) THEN
      BEGIN
        -- Если прописана физкультура/технология в качестве замены, разрешаем первый экземпляр, остальные пропускаем
        IF(V$REPLACE_SUBJ = 205) THEN
        BEGIN
          IF(V$HAS_FISCULT > 0) THEN V$LOAD_H = 0;
          V$HAS_FISCULT = 1;
        END
        ELSE IF(V$REPLACE_SUBJ = 200) THEN
        BEGIN
          IF(V$HAS_TECH > 0) THEN V$LOAD_H = 0;
          V$HAS_TECH = 1;
        END
      END

      -- найдем число учеников классов по параллели в данной УП, с учетом фильтра по классу.
      PUPIL_CNT = 0;
      SELECT COALESCE(COUNT(*), 0)
      FROM LINKS L256
      JOIN LINKS L10 ON L10.PARENT_ID = L256.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      JOIN LINKS L9 ON L9.OBJ_ID = L10.OBJ_ID AND L9.PARENT_TYPE_ID = 9 AND L9.DATE_DEL IS NULL AND (:I$GR IS NULL OR :I$GR = L9.PARENT_ID)
      WHERE L256.PARENT_ID = :V$STAGE_ID AND L256.OBJ_TYPE_ID IN (46, 256) AND L256.DATE_DEL IS NULL
      INTO :PUPIL_CNT;

      -- найдем какие учебники выданы на класс по предмету и в каком количестве
      FOR
        SELECT U.BOOK_NAME || IIF(U.YEAR_PUBLISHED IS NULL, '', ', год ' || U.YEAR_PUBLISHED), U.FPU_CODE, COALESCE(SUM(U.COUNT_IN_USE), 0), U.YEAR_PUBLISHED, MAX(COALESCE(U.BOOKS_LEFT, 0))
        FROM
          (SELECT DISTINCT L9.PARENT_ID
          FROM LINKS L256
          JOIN LINKS L10 ON L10.PARENT_ID = L256.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
          JOIN LINKS L9 ON L9.OBJ_ID = L10.OBJ_ID AND L9.PARENT_TYPE_ID IN (9, 187) AND L9.DATE_DEL IS NULL AND (:I$GR IS NULL OR :I$GR = L9.PARENT_ID) -- класс
          WHERE L256.PARENT_ID = :V$STAGE_ID AND L256.OBJ_TYPE_ID IN (46, 256) AND L256.DATE_DEL IS NULL
            AND :V$LOAD_H > 0) SEL
        LEFT JOIN LIB2_USAGE_SUBJ_GUP(:V$LOAD_ID, SEL.PARENT_ID, NULL) U ON 1 = 1
        GROUP BY 1, 2, 4
        INTO :BOOK_NAME, :FPU_CODE, :IN_USE_CNT, :YEAR_PUBLISHED, :BOOKS_LEFT_CNT
      DO
      BEGIN
        SUSPEND;
      END
    END
  END
  ELSE
  BEGIN
    -- для сводного отчета по обеспеченности
    FOR
      SELECT DISTINCT
        V381.LISTVAL_ID,
        V1594.LISTVAL_ID,
        PS.SUBJECT_ID
      FROM LINKS L57
      JOIN VALL V2379 ON V2379.OBJ_ID = L57.OBJ_ID AND V2379.PARAM_ID = 2379 AND V2379.IS_DEL = 0 AND V2379.LISTVAL_ID = 11187 --адаптир-ть = нет
      JOIN VALI V3115 ON V3115.OBJ_ID = L57.OBJ_ID AND V3115.PARAM_ID = 3115 AND V3115.IS_DEL = 0 AND V3115.VAL = :V$YEAR -- год публик-ии текущий
      JOIN VALL V1594 ON V1594.OBJ_ID = L57.OBJ_ID AND V1594.PARAM_ID = 1594 AND V1594.IS_DEL = 0
      JOIN LISTVALS LV1594 ON LV1594.LISTVAL_ID = V1594.LISTVAL_ID AND LV1594.IS_DEL = 0 AND (:I$LVL IS NULL OR LV1594.TAG = :I$LVL)-- уровень образования
      JOIN LINKS L69 ON L69.OBJ_ID = L57.PARENT_ID AND L69.PARENT_TYPE_ID = 2 AND L69.DATE_DEL IS NULL
      JOIN VALL V2450 ON V2450.OBJ_ID = L69.OBJ_ID AND V2450.PARAM_ID = 2450 AND V2450.IS_DEL = 0 AND V2450.LISTVAL_ID IN (11385, 11387) -- общеобр или СПО
      JOIN LINKS L400 ON L400.PARENT_ID = L57.OBJ_ID AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL
      JOIN VALL V3016 ON V3016.OBJ_ID = L400.OBJ_ID AND V3016.PARAM_ID = 3016 AND V3016.IS_DEL = 0 AND V3016.LISTVAL_ID = 5465 -- УП = групповой УП
      JOIN VALL V3022 ON V3022.OBJ_ID = L400.OBJ_ID AND V3022.PARAM_ID = 3022 AND V3022.IS_DEL = 0 AND V3022.LISTVAL_ID = 3    -- УП = не ВД
      JOIN VALL V3013 ON V3013.OBJ_ID = L400.OBJ_ID AND V3013.PARAM_ID = 3013 AND V3013.IS_DEL = 0 AND V3013.LISTVAL_ID = 11715 -- статус действующий
      JOIN LINKS L54 ON L54.PARENT_ID = L400.OBJ_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL  -- этапы
      JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0 AND (:I$ST IS NULL OR :I$ST = V381.LISTVAL_ID) -- параллель
      JOIN PLAN_LOADS PL ON PL.DATE_DEL IS NULL AND PL.STAGE_ID = L54.OBJ_ID AND PL.LOAD_HOURS > 0
      JOIN PLAN_SUBJECTS PS ON PS.DATE_DEL IS NULL AND PS.OBJ_ID = PL.SUBJECT_ID AND PS.ROW_TYPE = 10 AND PS.PLAN_ID = L400.OBJ_ID
      JOIN PLAN_SUBJECTS SEC ON SEC.OBJ_ID = PS.PARENT_ID AND SEC.FIELD_ID = 13303 -- обязательная часть УП
      WHERE L57.OBJ_TYPE_ID = 57 AND L57.PARENT_TYPE_ID = 69 AND L57.DATE_DEL IS NULL
      ORDER BY V381.LISTVAL_ID, PS.LEVEL_INDEX
      INTO :STAGE_ID, :LVL_ID, :SUBJECT_ID
    DO
    BEGIN
      -- найдем кол-во учеников в параллели
      IF (V$PREV_STAGE_ID IS NULL OR V$PREV_STAGE_ID <> STAGE_ID) THEN
      BEGIN
        PUPIL_CNT = 0;
        SELECT COALESCE(COUNT(*), 0)
        FROM LINKS L400
        JOIN VALL V3016 ON V3016.OBJ_ID = L400.OBJ_ID AND V3016.PARAM_ID = 3016 AND V3016.IS_DEL = 0 AND V3016.LISTVAL_ID = 5465 -- УП = групповой УП
        JOIN VALL V3022 ON V3022.OBJ_ID = L400.OBJ_ID AND V3022.PARAM_ID = 3022 AND V3022.IS_DEL = 0 AND V3022.LISTVAL_ID = 3    -- УП = не ВД
        JOIN VALL V3013 ON V3013.OBJ_ID = L400.OBJ_ID AND V3013.PARAM_ID = 3013 AND V3013.IS_DEL = 0 AND V3013.LISTVAL_ID = 11715 -- статус действующий
        JOIN LINKS L54 ON L54.PARENT_ID = L400.OBJ_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL  -- этапы
        JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0 AND (V381.LISTVAL_ID = :STAGE_ID) -- параллель
        JOIN LINKS L256 ON L256.PARENT_ID = L54.OBJ_ID AND L256.OBJ_TYPE_ID = 256 AND L256.DATE_DEL IS NULL
        JOIN LINKS L10 ON L10.PARENT_ID = L256.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        JOIN LINKS L57 ON L57.OBJ_ID = L400.PARENT_ID AND L57.OBJ_TYPE_ID = 57 AND L57.PARENT_TYPE_ID = 69 AND L57.DATE_DEL IS NULL
        JOIN VALL V2379 ON V2379.OBJ_ID = L57.OBJ_ID AND V2379.PARAM_ID = 2379 AND V2379.IS_DEL = 0 AND V2379.LISTVAL_ID = 11187 --адаптир-ть = нет
        JOIN VALI V3115 ON V3115.OBJ_ID = L57.OBJ_ID AND V3115.PARAM_ID = 3115 AND V3115.IS_DEL = 0 AND V3115.VAL = :V$YEAR -- год публик-ии текущий
        JOIN VALL V1594 ON V1594.OBJ_ID = L57.OBJ_ID AND V1594.PARAM_ID = 1594 AND V1594.IS_DEL = 0
        JOIN LINKS L69 ON L69.OBJ_ID = L57.PARENT_ID AND L69.PARENT_TYPE_ID = 2 AND L69.DATE_DEL IS NULL
        JOIN VALL V2450 ON V2450.OBJ_ID = L69.OBJ_ID AND V2450.PARAM_ID = 2450 AND V2450.IS_DEL = 0 AND V2450.LISTVAL_ID IN (11385, 11387) -- общеобр или СПО
        JOIN LISTVALS LV1594 ON LV1594.LISTVAL_ID = V1594.LISTVAL_ID AND LV1594.IS_DEL = 0 AND (:I$LVL IS NULL OR LV1594.TAG = :I$LVL)-- уровень образования
        WHERE L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL
        INTO :PUPIL_CNT;

        V$PREV_STAGE_ID = STAGE_ID;
      END

      -- найдем сколько учебников выдано по предмету. Учебник получен учеником или на класс и еще не распределен ученику.
      SELECT COALESCE(SUM(U.QUANTITY), 0)
      FROM LIB2_USAGE U
      JOIN LIB2_BOOKS B ON B.OBJ_ID = U.BOOK_ID AND B.OBJ_TYPE = 18712 -- учебник
      JOIN PLAN_LOADS PL ON PL.OBJ_ID = U.LOAD_ID AND PL.DATE_DEL IS NULL AND PL.LOAD_HOURS > 0
      JOIN LINKS L54 ON L54.OBJ_ID = PL.STAGE_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL  -- этапы
      JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0 AND (V381.LISTVAL_ID = :STAGE_ID) -- параллель
      JOIN LINKS L400 ON L400.OBJ_ID = L54.PARENT_ID AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL
      JOIN VALL V3016 ON V3016.OBJ_ID = L400.OBJ_ID AND V3016.PARAM_ID = 3016 AND V3016.IS_DEL = 0 AND V3016.LISTVAL_ID = 5465 -- УП = групповой УП
      JOIN VALL V3022 ON V3022.OBJ_ID = L400.OBJ_ID AND V3022.PARAM_ID = 3022 AND V3022.IS_DEL = 0 AND V3022.LISTVAL_ID = 3    -- УП = не ВД
      JOIN VALL V3013 ON V3013.OBJ_ID = L400.OBJ_ID AND V3013.PARAM_ID = 3013 AND V3013.IS_DEL = 0 AND V3013.LISTVAL_ID = 11715 -- статус действующий
      JOIN PLAN_SUBJECTS PS ON PS.OBJ_ID = PL.SUBJECT_ID AND PS.PLAN_ID = L400.OBJ_ID AND PS.DATE_DEL IS NULL AND COALESCE(PS.SUBJECT_ID, PS.SRC_SUBJECT_ID) = :SUBJECT_ID
      JOIN LINKS L57 ON L57.OBJ_ID = L400.PARENT_ID AND L57.OBJ_TYPE_ID = 57 AND L57.PARENT_TYPE_ID = 69 AND L57.DATE_DEL IS NULL
      JOIN VALL V2379 ON V2379.OBJ_ID = L57.OBJ_ID AND V2379.PARAM_ID = 2379 AND V2379.IS_DEL = 0 AND V2379.LISTVAL_ID = 11187 --адаптир-ть = нет
      JOIN VALI V3115 ON V3115.OBJ_ID = L57.OBJ_ID AND V3115.PARAM_ID = 3115 AND V3115.IS_DEL = 0 AND V3115.VAL = :V$YEAR -- год публик-ии текущий
      JOIN VALL V1594 ON V1594.OBJ_ID = L57.OBJ_ID AND V1594.PARAM_ID = 1594 AND V1594.IS_DEL = 0
      JOIN LISTVALS LV1594 ON LV1594.LISTVAL_ID = V1594.LISTVAL_ID AND LV1594.IS_DEL = 0 AND (:I$LVL IS NULL OR LV1594.TAG = :I$LVL)-- уровень образования
      WHERE U.DATE_DEL IS NULL AND (U.RETURN_DATE IS NULL AND U.LOSS_DATE IS NULL) -- экземпляр на руках
        AND U.CLASS_USAGE_ID IS NULL -- получено в библиотеке, а НЕ посредством распределения учебников от учителя ученикам (чтобы строки не задваивалсь с записью о получении учебника учителем)
      INTO :IN_USE_CNT;

      SUSPEND;
    END
  END
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIB_BOOK_ADD_FPU (
    I$OBJ_ID BIGINT,
    I$YEAR SMALLINT,
    I$BOOK_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable T bigint;
declare variable V$BOOKCODE varchar(100);
begin

  -- Получаем код ФПУ для выбранного учебника
  SELECT FIRST 1 C.BOOKCODE
  FROM LIB_FPU B
  LEFT JOIN FPU_CODE_GET(B.OBJ_ID, :I$YEAR) C ON 1 = 1
  WHERE B.OBJ_ID = :I$BOOK_ID AND B.DATE_DEL IS NULL
  INTO :V$BOOKCODE;

  IF(V$BOOKCODE IS NULL) THEN EXCEPTION DATA_ERROR 'Код ФПУ не найден';

  SELECT OBJ_ID FROM OBJECT_ADD(:I$OBJ_ID, 107) INTO :OBJ_ID;
  SELECT BLOB_ID FROM VAL_ADD(646, :OBJ_ID, 2057) INTO :T; -- учебник
  SELECT BLOB_ID FROM VAL_ADD(653, :OBJ_ID, 2099) INTO :T; -- выдаваемый на руки
  SELECT BLOB_ID FROM VAL_ADD(648, :OBJ_ID, 0) INTO :T;

  -- Год издания
  SELECT BLOB_ID FROM VAL_ADD(650, :OBJ_ID, :I$YEAR) INTO :T;
  -- Год самого кодификатора и кодификатор
  SELECT BLOB_ID FROM VAL_ADD(3123, :OBJ_ID, :I$YEAR) INTO :T;
  SELECT BLOB_ID FROM VAL_ADD(2655, :OBJ_ID, :V$BOOKCODE) INTO :T;

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIB_BOOK_UPDATE_PRG (
    I$OBJ_ID BIGINT NOT NULL,
    I$BOOK_CODE VARCHAR(4000),
    I$USER_ID BIGINT)
RETURNS (
    BOOK_NAME VARCHAR(500))
AS
declare variable V$AUTHORS varchar(600);
declare variable V$PUBLISHER_NAME varchar(300);
declare variable TMP$BLOB_ID bigint;
declare variable V$GRADE_FROM integer;
declare variable V$GRADE_TO integer;
declare variable V$SUBJ_ID bigint;
declare variable V$YEAR integer;
BEGIN

  IF ((I$BOOK_CODE IS NOT NULL) AND (I$BOOK_CODE <> '')) THEN
  BEGIN

    -- Должен быть указан год издания
    SELECT FIRST 1 V650.SVAL
    FROM VALS V650
    WHERE V650.OBJ_ID = :I$OBJ_ID AND V650.PARAM_ID = 650 AND V650.IS_DEL = 0
    INTO :V$YEAR;

    IF(V$YEAR IS NULL) THEN EXCEPTION DATA_ERROR 'Необходимо сначала указать год издания';

    SELECT FIRST 1 B.AUTHORS, B.BOOKNAME, P.PUBLISHER_NAME, B.GRADE_FROM, B.GRADE_TO, B.SUBJECT_ID
    FROM LIB_FPU_CODES C
    LEFT JOIN LIB_FPU_CODES C2 ON C2.DATE_DEL IS NULL AND C2.BOOKCODE = C.BOOKCODE AND C2.DATE_ADD > C.DATE_ADD AND C2.DATE_ADD <= '31.12.' || :V$YEAR -- сверка что такого кода нет впоследствии
    JOIN LIB_FPU B ON B.OBJ_ID = C.BOOK_ID AND B.DATE_DEL IS NULL
    JOIN LIB_FP_PUBLISHER P ON P.PUBLISHER_ID = B.PUBLISHER_ID
    WHERE C.BOOKCODE = :I$BOOK_CODE AND C.DATE_DEL IS NULL AND C.DATE_ADD <= '31.12.' || :V$YEAR AND C2.BOOK_ID IS NULL
    INTO :V$AUTHORS, :BOOK_NAME, :V$PUBLISHER_NAME, :V$GRADE_FROM, :V$GRADE_TO, :V$SUBJ_ID;

    -- Обновляем только если код нашелся. Если код не найден - ничего не делаем, в значениях будет показана ошибка
    IF (BOOK_NAME IS NOT NULL) THEN
    BEGIN

        SELECT BLOB_ID FROM VAL_ADD(647, :I$OBJ_ID, '"' || :BOOK_NAME || '"', :I$USER_ID) INTO :TMP$BLOB_ID;
        SELECT BLOB_ID FROM VAL_ADD(652, :I$OBJ_ID, :V$AUTHORS, :I$USER_ID) INTO :TMP$BLOB_ID;
        SELECT BLOB_ID FROM VAL_ADD(651, :I$OBJ_ID, :V$PUBLISHER_NAME, :I$USER_ID) INTO :TMP$BLOB_ID;
    
        -- Поля паралеллей от и до обновятся рекурсивно внутри VAL_ADD
        IF(V$GRADE_FROM = V$GRADE_TO) THEN
        BEGIN
            SELECT BLOB_ID FROM VAL_ADD(2658, :I$OBJ_ID, :V$GRADE_FROM, :I$USER_ID) INTO :TMP$BLOB_ID;
        END
        ELSE BEGIN
            SELECT BLOB_ID FROM VAL_ADD(2658, :I$OBJ_ID, CAST(:V$GRADE_FROM AS VARCHAR(100)) || '-' || CAST(:V$GRADE_TO AS VARCHAR(100)), :I$USER_ID) INTO :TMP$BLOB_ID;
        END

        -- Добавление 05.12.2016, автозаполнение предмета
        IF(V$SUBJ_ID IS NOT NULL) THEN
        BEGIN
            SELECT BLOB_ID FROM VAL_ADD(654, :I$OBJ_ID, :V$SUBJ_ID, :I$USER_ID) INTO :TMP$BLOB_ID;
        END

    END

  END

  SUSPEND;

END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIB_BOOK_VALIDATE_REFS (
    I$OBJ_ID BIGINT,
    I$YEAR VARCHAR(10))
AS
declare variable V$BOOK_CODE varchar(1000);
declare variable I integer;
BEGIN

        SELECT V2655.VAL
        FROM OBJECTS O
        LEFT JOIN VALS V2655 ON V2655.OBJ_ID = O.OBJ_ID AND V2655.PARAM_ID = 2655 AND V2655.IS_DEL = 0
        WHERE O.OBJ_ID = :I$OBJ_ID
        INTO :V$BOOK_CODE;
        -- Дубликаты в рамках ФПУ, если задан код
        IF(V$BOOK_CODE IS NOT NULL) THEN
        BEGIN
            I = 0;
            SELECT FIRST 1 1
            FROM LINKS L107
            JOIN VALS V2655 ON V2655.OBJ_ID = L107.OBJ_ID AND V2655.PARAM_ID = 2655 AND V2655.IS_DEL = 0 AND V2655.VAL = :V$BOOK_CODE
            JOIN VALS V650 ON V650.OBJ_ID = L107.OBJ_ID AND V650.PARAM_ID = 650 AND V650.IS_DEL = 0 AND V650.VAL = :I$YEAR
            WHERE L107.PARENT_TYPE_ID = 105 AND L107.OBJ_TYPE_ID = 107 AND L107.DATE_DEL IS NULL and L107.OBJ_ID <> :I$OBJ_ID
            INTO :I;
            IF(I > 0) THEN EXCEPTION DATA_ERROR 'Этот учебник с таким же годом издания уже внесен';
        END        

END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIB_FORMS_GET (
    I$FORMCODE BIGINT)
RETURNS (
    FORMCODE BIGINT,
    FORMLEADER BIGINT,
    FORMNAME VARCHAR(4000),
    FORMNUM INTEGER,
    FORMSTEP INTEGER,
    FORMPART INTEGER,
    FORMSTEP_NAME VARCHAR(1000),
    FORMLETTER VARCHAR(2),
    SORT_ORDER DOUBLE PRECISION)
AS
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$OBJ_ID2 BIGINT;
DECLARE VARIABLE V$I BIGINT;
BEGIN
    FOR
        SELECT L9.OBJ_ID,
               L8.OBJ_ID
        FROM LINKS L8
        INNER JOIN LINKS L9
        ON L9.PARENT_ID = L8.OBJ_ID
        AND L9.DATE_DEL IS NULL
        AND L9.OBJ_TYPE_ID = 9
        WHERE L8.DATE_DEL IS NULL
        AND L8.OBJ_TYPE_ID = 8
        AND L9.OBJ_ID = :I$FORMCODE
        INTO :FORMCODE,
             :V$OBJ_ID
    DO
    BEGIN
        FORMNUM = NULL;
        SELECT CAPTION,SORT_ORDER FROM OBJECT_CAPTION_GET(:FORMCODE) INTO :FORMNAME,:SORT_ORDER;
        SELECT LV.TAG
        FROM VAL_GET(:V$OBJ_ID, 49) V
        INNER JOIN LISTVALS LV
        ON LV.LISTVAL_ID = V.I
        INTO :FORMNUM;

        SELECT V FROM VAL_GET(:FORMCODE, 54) INTO :FORMLETTER;
        SELECT I FROM VAL_GET(:FORMCODE, 53) INTO :FORMLEADER;

        SELECT I
        FROM VAL_GET(:FORMCODE,706)
        INTO :FORMPART;

        FORMSTEP = NULL;
        FORMSTEP_NAME = NULL;

        FOR
            SELECT FIRST 1
                   OBJ_ID
            FROM OBJECT_PARENTS_GET(:FORMCODE, 7)
            INTO :V$OBJ_ID2
        DO
        BEGIN
            SELECT I,V
            FROM VAL_GET(:V$OBJ_ID2,43)
            INTO :FORMSTEP, :FORMSTEP_NAME;
        END
        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIB_FORMS_LIST RETURNS (
    FORMCODE BIGINT,
    FORMLEADER BIGINT,
    FORMNAME VARCHAR(4000),
    FORMNUM INTEGER,
    FORMSTEP INTEGER,
    FORMPART INTEGER,
    PUPILCOUNT INTEGER,
    FORMSTEP_NAME VARCHAR(1000),
    FORMPART_NAME VARCHAR(1000),
    FORMLANGUAGE_NAME VARCHAR(1000),
    FORMPROGRAMM_NAME VARCHAR(1000),
    FORMLEADER_NAME VARCHAR(1000),
    FORMLETTER VARCHAR(1000),
    SORT_ORDER DOUBLE PRECISION)
AS
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$OBJ_ID2 BIGINT;
DECLARE VARIABLE V$I BIGINT;
BEGIN
    FOR
        SELECT L9.OBJ_ID,
               L8.OBJ_ID
        FROM LINKS L8
        INNER JOIN LINKS L9
        ON L9.PARENT_ID = L8.OBJ_ID
        AND L9.DATE_DEL IS NULL
        AND L9.OBJ_TYPE_ID = 9
        WHERE L8.DATE_DEL IS NULL
        AND L8.OBJ_TYPE_ID = 8
        INTO :FORMCODE,
             :V$OBJ_ID
    DO
    BEGIN
        FORMNUM = NULL;
        SELECT CAPTION,
               SORT_ORDER
        FROM OBJECT_CAPTION_GET(:FORMCODE) INTO
               :FORMNAME,
               :SORT_ORDER;
        SELECT LV.TAG
        FROM VAL_GET(:V$OBJ_ID, 49) V
        INNER JOIN LISTVALS LV
        ON LV.LISTVAL_ID = V.I
        INTO :FORMNUM;

        SELECT COUNT(*)
        FROM LINKS L10
        WHERE L10.PARENT_ID = :FORMCODE
        AND L10.DATE_DEL IS NULL
        AND L10.OBJ_TYPE_ID = 10
        INTO :PUPILCOUNT;

        SELECT V FROM VAL_GET(:FORMCODE, 54) INTO :FORMLETTER;
        SELECT I FROM VAL_GET(:FORMCODE, 53) INTO :FORMLEADER;
        SELECT V FROM VAL_GET(:FORMCODE, 552) INTO :FORMLANGUAGE_NAME;

        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:FORMLEADER)
        INTO :FORMLEADER_NAME;

        FORMPROGRAMM_NAME = NULL;

        FOR
            SELECT FIRST 1
                   LP50.PARENT_ID
            FROM LINKS LP54
            INNER JOIN LINKS LP50
            ON LP50.OBJ_ID = LP54.PARENT_ID
            AND LP50.DATE_DEL IS NULL
            AND LP50.PARENT_TYPE_ID = 50
            WHERE LP54.PARENT_TYPE_ID = 54
            AND LP54.DATE_DEL IS NULL
            AND LP54.OBJ_ID = :FORMCODE
            INTO :V$I
        DO
        BEGIN
            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:V$I)
            INTO :FORMPROGRAMM_NAME;
        END

        FORMSTEP = NULL;
        FORMPART = NULL;
        FORMSTEP_NAME = NULL;

        FOR
            SELECT FIRST 1
                   OBJ_ID
            FROM OBJECT_PARENTS_GET(:FORMCODE, 7)
            INTO :V$OBJ_ID2
        DO
        BEGIN
            SELECT I,V
            FROM VAL_GET(:V$OBJ_ID2,43)
            INTO :FORMPART, :FORMPART_NAME;
        END
        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIB_FPU_ADD (
    I$CODE VARCHAR(1000),
    I$NAME VARCHAR(1000),
    I$AUTHORS VARCHAR(600),
    I$PUBLISHER VARCHAR(400),
    I$GRADES VARCHAR(40),
    I$DESC VARCHAR(100),
    I$DATE VARCHAR(100))
AS
declare variable V$ID bigint;
declare variable V$G1 integer;
declare variable V$G2 integer;
declare variable V$DATE date;
declare variable D integer;
declare variable M integer;
declare variable Y integer;
begin

  IF(I$PUBLISHER IS NULL OR I$PUBLISHER = '') THEN EXIT;

  IF(RIGHT(I$CODE, 1) = '.') THEN I$CODE = SUBSTRING(I$CODE FROM 1 FOR CHAR_LENGTH(I$CODE) - 1);
  I$CODE = REPLACE(I$CODE, '. ', ' '); -- для второго раздела

  I$GRADES = TRIM(I$GRADES);
  IF(I$GRADES = '') THEN
  BEGIN
    -- СПО
    V$G1 = 21;
    V$G2 = 26;
  END
  ELSE IF(POSITION('-' IN I$GRADES) <= 0) THEN
  BEGIN
    V$G1 = I$GRADES;
    V$G2 = I$GRADES;
  END
  ELSE
  BEGIN
    V$G1 = SUBSTRING(I$GRADES FROM 1 FOR POSITION('-' IN I$GRADES) - 1);
    V$G2 = SUBSTRING(I$GRADES FROM POSITION('-' IN I$GRADES) + 1);
  END

  IF(I$DATE = 'Бессрочно') THEN V$DATE = NULL;
  ELSE
  BEGIN
    I$DATE = TRIM(REPLACE(UPPER(I$DATE), 'ДО', ''));
    I$DATE = TRIM(REPLACE(UPPER(I$DATE), 'ГОДА', ''));

    -- Корректируем дату с 1 цифрой числа
    IF(SUBSTRING(I$DATE FROM 2 FOR 1) = ' ') THEN I$DATE = '0' || I$DATE;

    -- I$DATE = SUBSTRING(I$DATE FROM 4);
    D = TRIM(SUBSTRING(I$DATE FROM 1 FOR 2));
    Y = RIGHT(I$DATE, 4);
    I$DATE = TRIM(SUBSTRING(I$DATE FROM 3));

    I$DATE = LOWER(SUBSTRING(I$DATE FROM 1 FOR CHAR_LENGTH(I$DATE) - 5));
    IF(POSITION('январ' IN I$DATE) > 0) THEN M = 1;
    ELSE IF(POSITION('феврал' IN I$DATE) > 0) THEN M = 2;
    ELSE IF(POSITION('март' IN I$DATE) > 0) THEN M = 3;
    ELSE IF(POSITION('апрел' IN I$DATE) > 0) THEN M = 4;
    ELSE IF(POSITION('ма' IN I$DATE) > 0) THEN M = 5;
    ELSE IF(POSITION('июн' IN I$DATE) > 0) THEN M = 6;
    ELSE IF(POSITION('июл' IN I$DATE) > 0) THEN M = 7;
    ELSE IF(POSITION('авгус' IN I$DATE) > 0) THEN M = 8;
    ELSE IF(POSITION('сентябр' IN I$DATE) > 0) THEN M = 9;
    ELSE IF(POSITION('октябр' IN I$DATE) > 0) THEN M = 10;
    ELSE IF(POSITION('ноябр' IN I$DATE) > 0) THEN M = 11;
    ELSE IF(POSITION('декабр' IN I$DATE) > 0) THEN M = 12;
    ELSE EXCEPTION DATA_ERROR 'Неверная дата: ' || I$DATE;

    V$DATE = LPAD(D, 2, '0') || '.' || LPAD(M, 2, '0') || '.' || Y;
  END

  /*IF(EXISTS(
    SELECT FIRST 1 1
    FROM LIB_FPU_CODES C
    WHERE C.BOOKCODE = :I$CODE
  ))
  THEN
    EXCEPTION DATA_ERROR 'Дубликат ' || I$CODE;*/

  /*INSERT INTO LIB_FPU
  (YEAR_ADD, GRADE_FROM, GRADE_TO, BOOKNAME, AUTHORS, PUBLISHER_NAME, VALID_BY)
  VALUES (EXTRACT(YEAR FROM CURRENT_DATE), :V$G1, :V$G2, :I$NAME, :I$AUTHORS, :I$PUBLISHER, :V$DATE)
  RETURNING OBJ_ID INTO :V$ID;

  V$DATE = RIGHT(I$DESC, 10);

  INSERT INTO LIB_FPU_CODES
  (BOOK_ID, DATE_ADD, BOOKCODE, ORDER_INFO)
  VALUES (:V$ID, :V$DATE, :I$CODE, :I$DESC);*/

  SELECT FIRST 1 1
  FROM LIB_FPU_CODES C
  WHERE C.BOOKCODE = :I$CODE
  INTO :V$ID;

  UPDATE LIB_FPU
  SET VALID_BY = :V$DATE
  WHERE VALID_BY IS NULL AND OBJ_ID = :V$ID;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIB_FPU_DELETE (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    OBJ_ID BIGINT)
AS
begin

  IF(I$USER_ID <> 'Веб-администратор') THEN EXCEPTION DATA_ERROR 'Недостаточно прав доступа';

  IF(NOT EXISTS(
    SELECT 1
    FROM GEN G
    WHERE G.GEN = 0
  )) THEN EXCEPTION DATA_ERROR 'Справочник ФПУ можно менять только в эталонной базе';

  SELECT FIRST 1 L.OBJ_ID
  FROM LIB_FPU L
  WHERE L.OBJ_ID = :I$OBJ_ID AND L.DATE_DEL IS NULL
  INTO :OBJ_ID;

  IF(OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Запись не найдена или была удалена';

  UPDATE LIB_FPU
  SET DATE_DEL = CURRENT_TIMESTAMP
  WHERE OBJ_ID = :I$OBJ_ID;

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIB_FPU_GET (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
declare variable V$OBJ_ID bigint;
declare variable V$SUBJECT_ID bigint;
declare variable V$SA_ID bigint;
declare variable V$STAGE_ID bigint;
declare variable V$GRADE_FROM smallint;
declare variable V$GRADE_TO smallint;
declare variable V$YEAR_ADD smallint;
declare variable V$YEAR_REMOVE smallint;
declare variable V$PUBLISHER_ID bigint;
declare variable V$AUTHORS varchar(600);
declare variable V$ATTRS smallint;
declare variable V$DATE date;
declare variable V$VALID_BY date;
declare variable V$LANG bigint;
declare variable S varchar(1000);
declare variable S2 varchar(100);
begin

  SELECT FIRST 1 L.OBJ_ID, L.SUBJECT_ID, L.SA_ID, L.STAGE_ID, L.GRADE_FROM, L.GRADE_TO, L.YEAR_ADD, L.YEAR_REMOVE, L.PUBLISHER_ID, L.AUTHORS, L.BOOKNAME,
    L.ATTRS, L.VALID_BY, L.LANG_ID
  FROM LIB_FPU L
  WHERE L.OBJ_ID = :I$OBJ_ID AND L.DATE_DEL IS NULL
  INTO :V$OBJ_ID, :V$SUBJECT_ID, :V$SA_ID, :V$STAGE_ID, :V$GRADE_FROM, :V$GRADE_TO, :V$YEAR_ADD, :V$YEAR_REMOVE, :V$PUBLISHER_ID, :V$AUTHORS, :S,
    :V$ATTRS, :V$VALID_BY, :V$LANG;

  IF(I$OBJ_ID IS NOT NULL AND V$OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Запись не найдена или была удалена';

  TAG_NAME = 'id';
  VAL = I$OBJ_ID;
  SUSPEND;

  TAG_NAME = 'readonly';
  VAL = '1';
  IF(I$USER_ID = 'Веб-администратор' /* ... */) THEN VAL = '0';
  SUSPEND;

  TAG_NAME = 'grade_from';
  VAL = V$GRADE_FROM;
  SUSPEND;

  TAG_NAME = 'grade_to';
  VAL = V$GRADE_TO;
  SUSPEND;

  TAG_NAME = 'year_add';
  VAL = V$YEAR_ADD;
  SUSPEND;

  TAG_NAME = 'year_remove';
  VAL = V$YEAR_REMOVE;
  SUSPEND;

  TAG_NAME = 'authors';
  VAL = V$AUTHORS;
  SUSPEND;

  TAG_NAME = 'bookname';
  VAL = S;
  SUSPEND;

  TAG_NAME = 'attrs';
  VAL = V$ATTRS;
  SUSPEND;
  TAG_NAME = 'valid_by';
  VAL = (SELECT VAL FROM DATE2ISO(:V$VALID_BY));
  SUSPEND;

  TAG_NAME = 'bookcodes::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
    SELECT C.DATE_ADD, C.BOOKCODE, C.ORDER_INFO
    FROM LIB_FPU_CODES C
    WHERE C.DATE_DEL IS NULL AND C.BOOK_ID = :I$OBJ_ID
    ORDER BY C.DATE_ADD
    INTO :V$DATE, :S, :S2
  DO
  BEGIN
    TAG_NAME = 'bookcodes:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'bookcodes:r:date';
    VAL = (SELECT VAL FROM DATE2ISO(:V$DATE));
    SUSPEND;
    TAG_NAME = 'bookcodes:r:value';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'bookcodes:r:order';
    VAL = S2;
    SUSPEND;
  END

  TAG_NAME = 'stage_id';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'stage_id:selection';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'stage_id:selection::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
      SELECT LISTVAL_ID, VAL
      FROM LISTVALS_LIST(19)
      WHERE IS_DEL = 0 AND LISTVAL_ID IN (22, 26, 27)
      ORDER BY SORT_ORDER
      INTO :V$OBJ_ID, :S
  DO
  BEGIN
      TAG_NAME = 'stage_id:selection:option';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'stage_id:selection:option:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'stage_id:selection:option:value';
      VAL = S;
      SUSPEND;
  END
  TAG_NAME = 'stage_id:values:value';
  VAL = V$STAGE_ID;
  SUSPEND;

  TAG_NAME = 'sa_id';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'sa_id:selection';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'sa_id:selection::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
      SELECT LISTVAL_ID, VAL
      FROM LISTVALS_LIST(299)
      WHERE IS_DEL = 0
      ORDER BY SORT_ORDER
      INTO :V$OBJ_ID, :S
  DO
  BEGIN
      TAG_NAME = 'sa_id:selection:option';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'sa_id:selection:option:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'sa_id:selection:option:value';
      VAL = S;
      SUSPEND;
  END
  TAG_NAME = 'sa_id:values:value';
  VAL = V$SA_ID;
  SUSPEND;

  TAG_NAME = 'subject_id';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'subject_id:selection';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'subject_id:selection::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
      SELECT L51.OBJ_ID, C.CAPTION
      FROM LINKS L51
      LEFT JOIN OBJECT_CAPTION_GET(L51.OBJ_ID) C ON 1 = 1
      WHERE L51.PARENT_ID = 32771 AND L51.OBJ_TYPE_ID = 51 AND L51.DATE_DEL IS NULL AND L51.OBJ_ID < 1000000000
      ORDER BY 2
      INTO :V$OBJ_ID, :S
  DO
  BEGIN
      TAG_NAME = 'subject_id:selection:option';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'subject_id:selection:option:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'subject_id:selection:option:value';
      VAL = S;
      SUSPEND;
  END
  TAG_NAME = 'subject_id:values:value';
  VAL = V$SUBJECT_ID;
  SUSPEND;

  TAG_NAME = 'publisher_id';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'publisher_id:selection';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'publisher_id:selection::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
      SELECT P.PUBLISHER_ID, P.PUBLISHER_NAME
      FROM LIB_FP_PUBLISHER P
      WHERE P.DATE_DEL IS NULL
      ORDER BY 2
      INTO :V$OBJ_ID, :S
  DO
  BEGIN
      TAG_NAME = 'publisher_id:selection:option';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'publisher_id:selection:option:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'publisher_id:selection:option:value';
      VAL = S;
      SUSPEND;
  END
  TAG_NAME = 'publisher_id:values:value';
  VAL = V$PUBLISHER_ID;
  SUSPEND;

  TAG_NAME = 'lang_id';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'lang_id:selection';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'lang_id:selection::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
      SELECT LISTVAL_ID, VAL
      FROM LISTVALS_LIST(49)
      WHERE IS_DEL = 0
      ORDER BY SORT_ORDER
      INTO :V$OBJ_ID, :S
  DO
  BEGIN
      TAG_NAME = 'lang_id:selection:option';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'lang_id:selection:option:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'lang_id:selection:option:value';
      VAL = S;
      SUSPEND;
  END
  TAG_NAME = 'lang_id:values:value';
  VAL = V$LANG;
  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIB_FPU_SET (
    I$OBJ_ID BIGINT,
    I$SUBJECT_ID BIGINT,
    I$SA_ID BIGINT,
    I$AUTHORS VARCHAR(1000),
    I$BOOKNAME VARCHAR(1000),
    I$STAGE_ID BIGINT,
    I$GRADE_FROM SMALLINT NOT NULL,
    I$GRADE_TO SMALLINT NOT NULL,
    I$PUBLISHER_ID BIGINT,
    I$YEAR_REMOVE SMALLINT,
    I$ATTRS SMALLINT,
    I$VALID_BY DATE,
    I$CODEDATE DATE,
    I$BOOKCODE VARCHAR(40),
    I$ORDER VARCHAR(100),
    I$LANG_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$YEAR_ADD integer;
begin

  IF(I$USER_ID <> 'Веб-администратор') THEN EXCEPTION DATA_ERROR 'Недостаточно прав доступа';

  IF(NOT EXISTS(
    SELECT 1
    FROM GEN G
    WHERE G.GEN = 0
  )) THEN EXCEPTION DATA_ERROR 'Справочник ФПУ можно вносить только в эталонную базу';

  IF(I$GRADE_FROM <= 0 OR I$GRADE_FROM > 12 OR I$GRADE_TO <= 0 OR I$GRADE_TO > 12 OR I$GRADE_FROM > I$GRADE_TO) THEN EXCEPTION DATA_ERROR 'Неверно указаны номера параллелей';

  SELECT FIRST 1 L.OBJ_ID, L.YEAR_ADD
  FROM LIB_FPU L
  WHERE L.OBJ_ID = :I$OBJ_ID AND L.DATE_DEL IS NULL
  INTO :OBJ_ID, :V$YEAR_ADD;

  -- Если нет уровня образования - выбираем сами
  IF(I$STAGE_ID IS NULL) THEN
  BEGIN
    IF(I$GRADE_FROM <= 4) THEN I$STAGE_ID = 22;
    ELSE IF(I$GRADE_FROM <= 9) THEN I$STAGE_ID = 26;
    ELSE I$STAGE_ID = 27;
  END

  -- Если нет предметной области - формируем сами
  IF(I$SA_ID IS NULL) THEN
  BEGIN
    SELECT FIRST 1 V2462.LISTVAL_ID
    FROM LINKS L302
    JOIN VALL V2462 ON V2462.OBJ_ID = L302.OBJ_ID AND V2462.PARAM_ID = 2462 AND V2462.IS_DEL = 0
    WHERE L302.PARENT_ID = :I$SUBJECT_ID AND L302.OBJ_TYPE_ID = 302 AND L302.DATE_DEL IS NULL
    AND (
      ((:I$STAGE_ID = 22) AND (V2462.LISTVAL_ID IN (12740, 11680, 11682, 11685, 11686, 11689, 11693, 11694, 11695))) OR
      ((:I$STAGE_ID = 26) AND (V2462.LISTVAL_ID IN (11684, 11681, 11683, 11685, 11687, 11690, 11691, 11693, 11694, 11696))) OR
      ((:I$STAGE_ID = 27) AND (V2462.LISTVAL_ID IN (11684, 11681, 11683, 11685, 11688, 11690, 11692, 11693, 11694, 11696, 11697)))
    )
    INTO :I$SA_ID;
  END

  IF(I$OBJ_ID IS NULL) THEN
  BEGIN

    IF(I$CODEDATE IS NULL OR I$BOOKCODE IS NULL) THEN EXCEPTION DATA_ERROR 'При добавлении учебника должен быть указан код и дата приказа по ФПУ';
    IF(I$YEAR_REMOVE < EXTRACT(YEAR FROM :I$CODEDATE)) THEN EXCEPTION DATA_ERROR 'Дата исключения из ФПУ не может быть ранее даты включения';

    INSERT INTO LIB_FPU
    (SA_ID, SUBJECT_ID, STAGE_ID, GRADE_FROM, GRADE_TO, YEAR_ADD, YEAR_REMOVE,
      PUBLISHER_ID, AUTHORS, BOOKNAME, ATTRS, VALID_BY, LANG_ID)
    VALUES (:I$SA_ID, :I$SUBJECT_ID, :I$STAGE_ID, :I$GRADE_FROM, :I$GRADE_TO, EXTRACT(YEAR FROM :I$CODEDATE), :I$YEAR_REMOVE,
      :I$PUBLISHER_ID, TRIM(:I$AUTHORS), TRIM(:I$BOOKNAME), :I$ATTRS, :I$VALID_BY, :I$LANG_ID)
    RETURNING OBJ_ID INTO :OBJ_ID;

  END
  ELSE
  BEGIN

    IF(OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Запись не найдена или была удалена';
    IF(I$YEAR_REMOVE IS NOT NULL AND I$YEAR_REMOVE < V$YEAR_ADD) THEN EXCEPTION DATA_ERROR 'Дата исключения из ФПУ не может быть ранее даты включения';

    UPDATE LIB_FPU
    SET SA_ID = :I$SA_ID, SUBJECT_ID = :I$SUBJECT_ID, STAGE_ID = :I$STAGE_ID, GRADE_FROM = :I$GRADE_FROM, GRADE_TO = :I$GRADE_TO,
      YEAR_REMOVE = :I$YEAR_REMOVE, AUTHORS = TRIM(:I$AUTHORS), BOOKNAME = TRIM(:I$BOOKNAME), ATTRS = :I$ATTRS, PUBLISHER_ID = :I$PUBLISHER_ID,
      VALID_BY = :I$VALID_BY, LANG_ID = :I$LANG_ID
    WHERE OBJ_ID = :OBJ_ID;

  END

  IF(I$CODEDATE IS NOT NULL) THEN
  BEGIN
    IF(I$BOOKCODE IS NULL OR I$BOOKCODE = '*') THEN
    BEGIN
      UPDATE LIB_FPU_CODES
      SET DATE_DEL = CURRENT_TIMESTAMP
      WHERE BOOK_ID = :OBJ_ID AND DATE_ADD = :I$CODEDATE AND DATE_DEL IS NULL;
    END
    ELSE
    BEGIN
      UPDATE OR INSERT INTO LIB_FPU_CODES
      (BOOK_ID, DATE_ADD, BOOKCODE, ORDER_INFO, DATE_DEL)
      VALUES (:OBJ_ID, :I$CODEDATE, :I$BOOKCODE, :I$ORDER, NULL)
      MATCHING (BOOK_ID, DATE_ADD);
    END

    -- Корректируем дату добавления, если внесен более ранний код
    IF(V$YEAR_ADD IS NULL OR V$YEAR_ADD > EXTRACT(YEAR FROM :I$CODEDATE)) THEN
    BEGIN
      UPDATE LIB_FPU
      SET YEAR_ADD = EXTRACT(YEAR FROM :I$CODEDATE)
      WHERE OBJ_ID = :OBJ_ID;
    END
  END

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIB_FPU_UPDATE (
    I$BOOKCODE VARCHAR(40),
    I$ORDER_DATE DATE,
    I$ORDER_TEXT VARCHAR(100),
    I$VALID_BY DATE)
RETURNS (
    BOOK_ID BIGINT,
    BOOK_NAME VARCHAR(400),
    AUTHORS VARCHAR(400),
    SUBJECT_NAME VARCHAR(400),
    BOOKCODE VARCHAR(40),
    CODEDATE DATE,
    CODEORDER VARCHAR(100),
    IS_EXT SMALLINT,
    GRADE_FROM SMALLINT,
    GRADE_TO SMALLINT,
    YEAR_TO INTEGER,
    VALID_BY DATE)
AS
declare variable Y integer;
declare variable N integer;
begin

  Y = EXTRACT(YEAR FROM CURRENT_DATE);

  SELECT COUNT(*)
  FROM LIB_FPU_CODES C
  LEFT JOIN LIB_FPU_CODES C2 ON C2.BOOK_ID = C.BOOK_ID AND C2.DATE_DEL IS NULL AND C2.DATE_ADD > C.DATE_ADD
  JOIN LIB_FPU B ON B.OBJ_ID = C.BOOK_ID AND B.DATE_DEL IS NULL AND (B.YEAR_REMOVE IS NULL OR B.YEAR_REMOVE > :Y)
  WHERE C.DATE_DEL IS NULL AND C.BOOKCODE = :I$BOOKCODE AND C2.BOOKCODE IS NULL
  INTO :N;

  IF(N = 0) THEN EXCEPTION DATA_ERROR 'NO BOOK ' || I$BOOKCODE;
  IF(N > 1) THEN EXCEPTION DATA_ERROR 'MULTIPLE BOOK ' || I$BOOKCODE;

  SELECT FIRST 1 B.OBJ_ID, B.BOOKNAME, B.AUTHORS, CS.CAPTION, B.GRADE_FROM, B.GRADE_TO, B.YEAR_REMOVE, B.ATTRS, B.VALID_BY, C.BOOKCODE, C.DATE_ADD, C.ORDER_INFO
  FROM LIB_FPU_CODES C
  LEFT JOIN LIB_FPU_CODES C2 ON C2.BOOK_ID = C.BOOK_ID AND C2.DATE_DEL IS NULL AND C2.DATE_ADD > C.DATE_ADD
  JOIN LIB_FPU B ON B.OBJ_ID = C.BOOK_ID AND B.DATE_DEL IS NULL AND (B.YEAR_REMOVE IS NULL OR B.YEAR_REMOVE > :Y)
  LEFT JOIN OBJECT_CAPTION_GET(B.SUBJECT_ID) CS ON 1 = 1
  WHERE C.DATE_DEL IS NULL AND C.BOOKCODE = :I$BOOKCODE AND C2.BOOKCODE IS NULL
  INTO :BOOK_ID, :BOOK_NAME, :AUTHORS, :SUBJECT_NAME, :GRADE_FROM, :GRADE_TO, :YEAR_TO, :IS_EXT, :VALID_BY, :BOOKCODE, :CODEDATE, :CODEORDER;

  -- Если дата приказа не указана, то ничего не обновляем, только показываем что нашли
  -- Не внесено еще изменение ?
  IF(I$ORDER_DATE IS NOT NULL AND NOT EXISTS(
    SELECT FIRST 1 1
    FROM LIB_FPU_CODES C
    WHERE C.BOOK_ID = :BOOK_ID AND C.DATE_ADD = :I$ORDER_DATE
  ))
  THEN
  BEGIN
    INSERT INTO LIB_FPU_CODES
    (BOOK_ID, DATE_ADD, BOOKCODE, ORDER_INFO)
    VALUES (:BOOK_ID, :I$ORDER_DATE, :I$BOOKCODE, :I$ORDER_TEXT);
  END

  IF(I$ORDER_DATE IS NOT NULL AND COALESCE(VALID_BY, '01.01.1900') <> COALESCE(I$VALID_BY, '01.01.1900')) THEN
  BEGIN
     VALID_BY  = I$VALID_BY;
     UPDATE LIB_FPU SET VALID_BY = :I$VALID_BY WHERE OBJ_ID = :BOOK_ID;
  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIB_FPU_UPDATE_MASS (
    I$BOOKCODE VARCHAR(40),
    I$NUM SMALLINT,
    I$ORDER_DATE DATE,
    I$ORDER_TEXT VARCHAR(100),
    I$VALID_BY DATE)
RETURNS (
    BOOK_ID BIGINT,
    BOOK_NAME VARCHAR(400),
    AUTHORS VARCHAR(400),
    SUBJECT_NAME VARCHAR(400),
    BOOKCODE VARCHAR(40),
    CODEDATE DATE,
    CODEORDER VARCHAR(100),
    IS_EXT SMALLINT,
    GRADE_FROM SMALLINT,
    GRADE_TO SMALLINT,
    YEAR_TO INTEGER,
    VALID_BY DATE)
AS
declare variable N smallint;
declare variable P smallint;
begin

  -- Берем последний элемент кода, и повторяем его нужное число раз
  N = RIGHT(I$BOOKCODE, 1);
  P = 1;

  WHILE(I$NUM > 0) DO
  BEGIN
    FOR
      SELECT BOOK_ID, BOOK_NAME, AUTHORS, SUBJECT_NAME, BOOKCODE, CODEDATE, CODEORDER, IS_EXT, GRADE_FROM, GRADE_TO, YEAR_TO, VALID_BY
      FROM LIB_FPU_UPDATE(SUBSTRING(:I$BOOKCODE FROM 1 FOR CHAR_LENGTH(:I$BOOKCODE) - 1) || :N, :I$ORDER_DATE, :I$ORDER_TEXT, :I$VALID_BY)
      INTO :BOOK_ID, :BOOK_NAME, :AUTHORS, :SUBJECT_NAME, :BOOKCODE, :CODEDATE, :CODEORDER, :IS_EXT, :GRADE_FROM, :GRADE_TO, :YEAR_TO, :VALID_BY
    DO
    BEGIN
      SUSPEND;
    END
    N = N + 1;
    I$NUM = I$NUM - 1;
    I$VALID_BY = DATEADD(1 YEAR TO I$VALID_BY);
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIB_FP_ADD_PUBLISHER (
    PUBLISHER_NAME VARCHAR(300))
RETURNS (
    PUBLISHER_ID BIGINT)
AS
begin
  PUBLISHER_ID = GEN_ID(LIB_DICTGEN, 1);

  INSERT INTO LIB_FP_PUBLISHER (PUBLISHER_ID, PUBLISHER_NAME)
  VALUES (:PUBLISHER_ID, :PUBLISHER_NAME);

  SUSPEND;
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIB_FP_BOOK_INFO_GET (
    I$OBJ_ID BIGINT,
    I$PARAM_ID BIGINT)
RETURNS (
    VAL VARCHAR(4000))
AS
DECLARE VARIABLE V$YEAR INTEGER;
DECLARE VARIABLE V$BOOK_CODE VARCHAR(4000);
DECLARE VARIABLE V$YEAR_REMOVE INTEGER;
DECLARE VARIABLE V$LEVEL_NAME VARCHAR(100);
DECLARE VARIABLE V$SA_NAME VARCHAR(100);
DECLARE VARIABLE V$ADV_LEVEL SMALLINT;
DECLARE VARIABLE V$AUTHORS VARCHAR(600);
DECLARE VARIABLE V$BOOK_NAME VARCHAR(600);
DECLARE VARIABLE V$PUBLISHER_NAME VARCHAR(300);
DECLARE VARIABLE V$VALID_BY DATE;
BEGIN

  /* Получаем код учебника из параметров объекта */
  SELECT VAL FROM VALS WHERE OBJ_ID = :I$OBJ_ID AND PARAM_ID IN (2655, 2678) AND IS_DEL = 0
  INTO :V$BOOK_CODE;

  /*SELECT FIRST 1 V3123.VAL
  FROM VALI V3123
  WHERE V3123.OBJ_ID = :I$OBJ_ID AND V3123.PARAM_ID = 3123 AND V3123.IS_DEL = 0
  INTO :V$YEAR;

  IF(V$YEAR IS NULL) THEN
  BEGIN
    -- определим год утверждения учебника по порядковому номеру учебника
    SELECT FIRST 1 V3123.VAL
    FROM LINKS L107
    JOIN VALS V2655 ON V2655.OBJ_ID = L107.OBJ_ID AND V2655.PARAM_ID = 2655 AND V2655.IS_DEL = 0 AND V2655.VAL = :V$BOOK_CODE
    JOIN VALI V3123 ON V3123.OBJ_ID = L107.OBJ_ID AND V3123.PARAM_ID = 3123 AND V3123.IS_DEL = 0
    WHERE L107.OBJ_TYPE_ID = 107 AND L107.PARENT_TYPE_ID = 105 AND L107.DATE_DEL IS NULL
    INTO :V$YEAR;
  END

  IF(V$YEAR IS NULL) THEN V$YEAR = 2021;*/

  IF((V$BOOK_CODE IS NULL) OR (V$BOOK_CODE = '')) THEN
  BEGIN
    /* Признак ФПУ ДА-НЕТ */
    IF(I$PARAM_ID = 2663) THEN VAL = 'нет';
    ELSE VAL = '';
  END
  ELSE
  BEGIN

    /* Получаем информацию об учебнике по коду ФПУ. Достаем самый актуальный по дате. Если информация не нашлась - выдаем сообщение об ошибке */
    SELECT FIRST 1 B.YEAR_REMOVE, C.BOOKCODE, STT.VAL, SAT.VAL, B.ATTRS, B.BOOKNAME, B.AUTHORS, P.PUBLISHER_NAME, B.VALID_BY
    FROM LIB_FPU_CODES C
    LEFT JOIN LIB_FPU_CODES C2 ON C2.DATE_DEL IS NULL AND C2.BOOKCODE = C.BOOKCODE AND C2.DATE_ADD > C.DATE_ADD-- AND C2.DATE_ADD <= '31.12.' || :V$YEAR -- сверка что такого кода нет впоследствии
    JOIN LIB_FPU B ON B.OBJ_ID = C.BOOK_ID AND B.DATE_DEL IS NULL
    JOIN LIB_FP_PUBLISHER P ON P.PUBLISHER_ID = B.PUBLISHER_ID
    LEFT JOIN LISTVAL_TEXT(B.SA_ID) SAT ON 1 = 1
    LEFT JOIN LISTVAL_TEXT(B.STAGE_ID) STT ON 1 = 1
    WHERE C.BOOKCODE = :V$BOOK_CODE AND C.DATE_DEL IS NULL AND C2.BOOK_ID IS NULL --AND C.DATE_ADD <= '31.12.' || :V$YEAR
    INTO :V$YEAR_REMOVE, :V$BOOK_CODE, :V$LEVEL_NAME, :V$SA_NAME, :V$ADV_LEVEL, :V$BOOK_NAME, :V$AUTHORS, :V$PUBLISHER_NAME, :V$VALID_BY;

    IF(V$SA_NAME IS NULL AND V$LEVEL_NAME IS NULL) THEN VAL = 'Ошибка';
    ELSE
    BEGIN

        IF(I$PARAM_ID = 2656 OR I$PARAM_ID = 2682) THEN
        BEGIN
            /* Раньше был год исключения - теперь выдаем либо год исключения, либо дату окончания действия */
            IF(V$VALID_BY IS NOT NULL) THEN VAL = (SELECT RESULT FROM DATE2STR(:V$VALID_BY));
            ELSE IF(V$YEAR_REMOVE IS NOT NULL) THEN VAL = V$YEAR_REMOVE;
            ELSE VAL = '';
        END
        ELSE IF(I$PARAM_ID = 2657 OR I$PARAM_ID = 2677) THEN
        BEGIN
            /* Уровень образования */
            IF(V$LEVEL_NAME IS NULL) THEN VAL = ''; ELSE VAL = V$LEVEL_NAME;
        END
        ELSE IF(I$PARAM_ID = 2659) THEN
        BEGIN
            /* Предметная область */
            IF(V$SA_NAME IS NULL) THEN VAL = ''; ELSE VAL = V$SA_NAME;
        END
        ELSE IF(I$PARAM_ID = 2660) THEN
        BEGIN
            /* Уровень учебника */
            IF(V$ADV_LEVEL IS NULL) THEN VAL = '';
            ELSE BEGIN
                IF(V$ADV_LEVEL = 2) THEN VAL = 'Углубленный'; ELSE VAL = 'Базовый';
            END
        END
        ELSE IF(I$PARAM_ID = 2661) THEN
        BEGIN
            /* Адаптивность ОП */
            IF(V$ADV_LEVEL IS NULL) THEN VAL = '';
            ELSE BEGIN
                IF(V$ADV_LEVEL = 3) THEN VAL = 'да'; ELSE VAL = '';
            END
        END
        ELSE IF(I$PARAM_ID = 2662) THEN
        BEGIN
            /* Компонент ОП */
            VAL = '';
            /*
            ELSE BEGIN
                IF(V$COMPONENT_ID = 1) THEN VAL = 'Федеральный компонент';
                ELSE IF(V$COMPONENT_ID = 2) THEN VAL = 'Региональный и компонент ОООД';
                ELSE IF(V$COMPONENT_ID = 3) THEN VAL = 'Региональный и компонент ОООД (нац.)';
                ELSE VAL = 'Неизвестный компонент';
            END
            */
        END
        ELSE IF(I$PARAM_ID = 2663) THEN
        BEGIN
            /* Признак ФПУ ДА-НЕТ */
            VAL = 'да';
        END
        ELSE IF(I$PARAM_ID = 2679) THEN
        BEGIN
            /* Авторы */
            VAL = V$AUTHORS;
        END
        ELSE IF(I$PARAM_ID = 2680) THEN
        BEGIN
            /* Наименование учебника */
            VAL = V$BOOK_NAME;
        END
        ELSE IF(I$PARAM_ID = 2681) THEN
        BEGIN
            /* Издатели */
            VAL = V$PUBLISHER_NAME;
        END
        ELSE VAL = '';

    END

  END

  SUSPEND;

  WHEN ANY DO
  BEGIN
    VAL = 'Не указан год издания';
  END

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIB_PUPIL_GET (
    SCBOYCOD BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    SCBOYCODE BIGINT,
    FORMID BIGINT,
    FORMNAME VARCHAR(1000),
    FIRSTNAME VARCHAR(1000),
    NAME VARCHAR(1000),
    LASTNAME VARCHAR(1000),
    BIRTHDAY DATE,
    REGION VARCHAR(255),
    DISTRICT VARCHAR(255),
    TOWN VARCHAR(255),
    SETTLEMENT VARCHAR(255),
    STREET VARCHAR(255),
    HOUSE VARCHAR(10),
    CORP VARCHAR(10),
    LITER VARCHAR(10),
    FLAT VARCHAR(10),
    POST_INDEX VARCHAR(20),
    ADDRESS VARCHAR(2000),
    ABONEMENTID BIGINT,
    ABONEMENTNO INTEGER,
    PHONE VARCHAR(255),
    FULLNAME VARCHAR(255),
    ISOLDSCBOY SMALLINT)
AS
DECLARE VARIABLE LANG_CODE VARCHAR(2);
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :LANG_CODE;

    FOR
        SELECT DISTINCT S.OBJ_ID, F.OBJ_ID
        FROM LINKS S
        JOIN LINKS F ON S.PARENT_ID = F.OBJ_ID AND F.DATE_DEL IS NULL
        WHERE S.DATE_DEL IS NULL AND S.OBJ_ID = :SCBOYCOD AND S.OBJ_TYPE_ID = 10
        INTO :SCBOYCODE, :FORMID
    DO
    BEGIN
        BIRTHDAY = NULL;
        SELECT VAL
        FROM VALD
        WHERE OBJ_ID = :SCBOYCODE AND PARAM_ID = 89 AND IS_DEL = 0
        INTO :BIRTHDAY;

        ABONEMENTNO = NULL;
        ABONEMENTID = NULL;
        SELECT V FROM VAL_GET(:SCBOYCODE,55,0, :I$USER_ID) INTO :FIRSTNAME;
        SELECT V FROM VAL_GET(:SCBOYCODE,56,0, :I$USER_ID) INTO :NAME;
        SELECT V FROM VAL_GET(:SCBOYCODE,57,0, :I$USER_ID) INTO :LASTNAME;

        SELECT CAPTION FROM OBJECT_CAPTION_GET (:SCBOYCODE,NULL,NULL,:I$USER_ID) INTO :FULLNAME;

        SELECT CAPTION FROM OBJECT_CAPTION_GET (:FORMID,NULL,NULL,:I$USER_ID) INTO :FORMNAME;

        SELECT A.ABONEMENTID
        FROM LIB_ABONEMENT A
        WHERE A.SCBOYID = :SCBOYCODE
        INTO :ABONEMENTID;

        SELECT A.ABONEMENTNO
        FROM LIB_ABONEMENT A
        WHERE A.SCBOYID = :SCBOYCODE
        INTO :ABONEMENTNO;

        SELECT R.VAL
        FROM VAL_GET(:SCBOYCODE,103,0, :I$USER_ID) V
        JOIN LISTVALS L
        ON L.LISTVAL_ID = V.I
        LEFT JOIN RES_GET(L.RES_ID,  :LANG_CODE) R ON 1=1
        INTO :ADDRESS;

        SELECT V FROM VAL_GET(:SCBOYCODE,102,0, :I$USER_ID) INTO :PHONE;

        SELECT A.REGION,
               A.DISTRICT,
               A.TOWN,
               A.SETTLEMENT,
               A.STREET,
               A.HOUSE,
               A.CORP,
               A.LITER,
               A.FLAT,
               A.POST_INDEX,
               A.VAL
        FROM ADR_GET (103,:SCBOYCODE) A
        INTO :REGION,
             :DISTRICT,
             :TOWN,
             :SETTLEMENT,
             :STREET,
             :HOUSE,
             :CORP,
             :LITER,
             :FLAT,
             :POST_INDEX,
             :ADDRESS;

        ISOLDSCBOY = 0;
        SELECT FIRST 1
               1
        FROM OBJECT_PARENTS_GET(:SCBOYCODE,78)
        INTO :ISOLDSCBOY;

        IF (ISOLDSCBOY = 0) THEN
        BEGIN
            ISOLDSCBOY = 1;
            SELECT FIRST 1
                   0
            FROM OBJECT_PARENTS_GET(:SCBOYCODE,7)
            INTO :ISOLDSCBOY;
        END

        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIB_PUPIL_LIST (
    FORMCODE BIGINT = NULL)
RETURNS (
    SCBOYCODE BIGINT,
    FORMID BIGINT,
    FORMNUM INTEGER,
    BIRTHDAY DATE,
    FORMNAME VARCHAR(1000),
    FIRSTNAME VARCHAR(1000),
    NAME VARCHAR(1000),
    LASTNAME VARCHAR(1000),
    REGION VARCHAR(255),
    DISTRICT VARCHAR(255),
    TOWN VARCHAR(255),
    SETTLEMENT VARCHAR(255),
    STREET VARCHAR(255),
    HOUSE VARCHAR(10),
    CORP VARCHAR(10),
    LITER VARCHAR(10),
    FLAT VARCHAR(10),
    POST_INDEX VARCHAR(20),
    ADDRESS VARCHAR(2000),
    PHONE VARCHAR(100),
    ABONEMENTID BIGINT,
    ABONEMENTNO INTEGER,
    ISOLDSCBOY SMALLINT)
AS
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE SCHOOL_ID BIGINT;
BEGIN
    SELECT FIRST 1 L2.OBJ_ID
    FROM LINKS L2
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :SCHOOL_ID;

    FOR
        -- Действующие учащиемся
        SELECT L10.OBJ_ID, L9.OBJ_ID, L8.OBJ_ID, 0
        FROM LINKS L7
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL AND ((L9.OBJ_ID = :FORMCODE) OR (:FORMCODE IS NULL))
        JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        WHERE L7.DATE_DEL IS NULL AND L7.OBJ_TYPE_ID = 7 AND L7.PARENT_ID = :SCHOOL_ID
        UNION

        SELECT L10.OBJ_ID, NULL, NULL, 1
        FROM LINKS L78
        JOIN LINKS L81 ON L81.PARENT_ID = L78.OBJ_ID AND L81.OBJ_TYPE_ID = 81 AND L81.DATE_DEL IS NULL
        JOIN LINKS L10 ON L10.PARENT_ID = L81.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        WHERE :FORMCODE IS NULL AND L78.PARENT_ID = :SCHOOL_ID AND L78.OBJ_TYPE_ID = 78 AND L78.DATE_DEL IS NULL

        UNION
        SELECT L10.OBJ_ID, NULL, NULL, 1
        FROM LINKS L78
        JOIN LINKS L82 ON L82.PARENT_ID = L78.OBJ_ID AND L82.OBJ_TYPE_ID = 82 AND L82.DATE_DEL IS NULL
        JOIN LINKS L10 ON L10.PARENT_ID = L82.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        WHERE :FORMCODE IS NULL AND L78.PARENT_ID = :SCHOOL_ID AND L78.OBJ_TYPE_ID = 78 AND L78.DATE_DEL IS NULL

        UNION

        -- эта ветка вообще дохлая, в 83 нет классов
        SELECT L10.OBJ_ID, NULL, NULL, 1
        FROM LINKS L78
        JOIN LINKS L83 ON L83.PARENT_ID = L78.OBJ_ID AND L83.OBJ_TYPE_ID = 83 AND L83.DATE_DEL IS NULL
        JOIN LINKS L9 ON L9.PARENT_ID = L83.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
        JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        WHERE :FORMCODE IS NULL AND L78.PARENT_ID = :SCHOOL_ID AND L78.OBJ_TYPE_ID = 78 AND L78.DATE_DEL IS NULL

        INTO :SCBOYCODE, :FORMID, :V$OBJ_ID, :ISOLDSCBOY
    DO
    BEGIN
        FORMNAME = NULL;

        IF (FORMID IS NOT NULL) THEN
        BEGIN
            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:FORMID)
            INTO :FORMNAME;
        END

        ABONEMENTNO = NULL;
        ABONEMENTID = NULL;

        SELECT V
        FROM VAL_GET(:SCBOYCODE, 55, 0)
        INTO :FIRSTNAME;

        SELECT V
        FROM VAL_GET(:SCBOYCODE, 56, 0)
        INTO :NAME;

        SELECT V
        FROM VAL_GET(:SCBOYCODE, 57, 0)
        INTO :LASTNAME;

        SELECT A.ABONEMENTID
        FROM LIB_ABONEMENT A
        WHERE A.SCBOYID = :SCBOYCODE
        INTO :ABONEMENTID;

        SELECT A.ABONEMENTNO
        FROM LIB_ABONEMENT A
        WHERE A.SCBOYID = :SCBOYCODE
        INTO :ABONEMENTNO;

        BIRTHDAY = NULL;

        SELECT VAL
        FROM VALD
        WHERE OBJ_ID = :SCBOYCODE AND PARAM_ID = 89 AND IS_DEL = 0
        INTO :BIRTHDAY;

        SELECT A.REGION, A.DISTRICT, A.TOWN, A.SETTLEMENT, A.STREET, A.HOUSE, A.CORP, A.LITER, A.FLAT, A.POST_INDEX, A.VAL
        FROM ADR_GET(103, :SCBOYCODE) A
        INTO :REGION, :DISTRICT, :TOWN, :SETTLEMENT, :STREET, :HOUSE, :CORP, :LITER, :FLAT, :POST_INDEX, :ADDRESS;

        SELECT V
        FROM VAL_GET(:SCBOYCODE, 102)
        INTO :PHONE;

        FORMNUM = NULL;

        SELECT LV.TAG
        FROM VAL_GET(:V$OBJ_ID, 49) V
        JOIN LISTVALS LV ON LV.LISTVAL_ID = V.I
        INTO :FORMNUM;

        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIB_SCHOOL_INFO RETURNS (
    NAME VARCHAR(500),
    NUMBER VARCHAR(20),
    SUBJECTION VARCHAR(500),
    HIGHER_ECHELON VARCHAR(500),
    TYPE_OU VARCHAR(500),
    CLASS_OU VARCHAR(500))
AS
DECLARE VARIABLE V$OBJ_ID BIGINT;
BEGIN
    NAME = NULL;
    NUMBER = NULL;
    SUBJECTION = NULL;
    HIGHER_ECHELON = NULL;
    TYPE_OU = NULL;
    CLASS_OU = NULL;
    FOR
        SELECT FIRST 1
               OBJ_ID
        FROM LINKS L2
        WHERE L2.PARENT_ID IS NULL
        AND L2.DATE_DEL IS NULL
        AND L2.OBJ_TYPE_ID = 2
        INTO :V$OBJ_ID
    DO
    BEGIN
        SELECT V
        FROM VAL_GET(:V$OBJ_ID,2)
        INTO :NAME;

        SELECT V
        FROM VAL_GET(:V$OBJ_ID,17)
        INTO :NUMBER;

        SELECT V
        FROM VAL_GET(:V$OBJ_ID,6)
        INTO :SUBJECTION;

        SELECT V
        FROM VAL_GET(:V$OBJ_ID,7)
        INTO :HIGHER_ECHELON;

        SELECT V
        FROM VAL_GET(:V$OBJ_ID,11)
        INTO :TYPE_OU;

        SELECT V
        FROM VAL_GET(:V$OBJ_ID,10)
        INTO :CLASS_OU;
    END
    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIB_SUBJECT_LIST (
    I$PLAN_ONLY SMALLINT = 0)
RETURNS (
    SUBJECTCODE BIGINT,
    SUBJECTNAME VARCHAR(4000),
    SUBJECTSHORTNAME VARCHAR(4000),
    SUBJECTORDER DOUBLE PRECISION)
AS
BEGIN

    IF(I$PLAN_ONLY = 0) THEN
    BEGIN
        -- Весь список предметов (библиограф)
        FOR
            SELECT DISTINCT L51.OBJ_ID
            FROM LINKS L51
            WHERE L51.OBJ_TYPE_ID = 51 AND L51.DATE_DEL IS NULL
            INTO :SUBJECTCODE
        DO
        BEGIN
            SELECT CAPTION, SORT_ORDER FROM OBJECT_CAPTION_GET(:SUBJECTCODE) INTO :SUBJECTNAME, :SUBJECTORDER;
            SELECT V FROM VAL_GET(:SUBJECTCODE, 377) INTO :SUBJECTSHORTNAME;

            SUSPEND;
        END
    END
    ELSE
    BEGIN

        -- Только предметы, фигурирующие в нагрузках реальных УП, но не ВД
        FOR
            SELECT DISTINCT PS.SUBJECT_ID
            FROM LINKS L400
            JOIN VALL V3022 ON V3022.OBJ_ID = L400.OBJ_ID AND V3022.PARAM_ID = 3022 AND V3022.IS_DEL = 0 AND V3022.LISTVAL_ID = 3
            -- JOIN VALL V3013 ON V3013.OBJ_ID = L400.OBJ_ID AND V3013.PARAM_ID = 3013 AND V3013.IS_DEL = 0 AND V3013.LISTVAL_ID = 11715
            JOIN PLAN_SUBJECTS PS ON PS.DATE_DEL IS NULL AND PS.PLAN_ID = L400.OBJ_ID AND PS.ROW_TYPE = 10
            WHERE L400.PARENT_TYPE_ID = 57 AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL
            INTO :SUBJECTCODE
        DO
        BEGIN
            SELECT CAPTION, SORT_ORDER FROM OBJECT_CAPTION_GET(:SUBJECTCODE) INTO :SUBJECTNAME, :SUBJECTORDER;
            SELECT V FROM VAL_GET(:SUBJECTCODE, 377) INTO :SUBJECTSHORTNAME;

            SUSPEND;
        END

    END

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIB_TEACHER_GET (
    I$PERSONCODE BIGINT)
RETURNS (
    PERSONCODE BIGINT,
    FIRSTNAME VARCHAR(500),
    NAME VARCHAR(500),
    LASTNAME VARCHAR(500),
    BIRTHDAY DATE,
    EDUCATION VARCHAR(500),
    ABONEMENTID BIGINT,
    ABONEMENTNO INTEGER,
    REGION VARCHAR(255),
    DISTRICT VARCHAR(255),
    TOWN VARCHAR(255),
    SETTLEMENT VARCHAR(255),
    STREET VARCHAR(255),
    HOUSE VARCHAR(10),
    CORP VARCHAR(10),
    LITER VARCHAR(10),
    FLAT VARCHAR(10),
    POST_INDEX VARCHAR(20),
    ADDRESS VARCHAR(2000),
    PHONE VARCHAR(255),
    FULLNAME VARCHAR(255),
    "POSITION" VARCHAR(1000),
    POSITION_ID BIGINT,
    PASSPORT_NUMBER VARCHAR(50),
    PASSPORT_SER VARCHAR(50),
    PASSPORT_OVD VARCHAR(500),
    PASSPORT_DATE DATE)
AS
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$I BIGINT;
BEGIN
    FOR
        SELECT DISTINCT S.OBJ_ID
        FROM LINKS S
        WHERE S.DATE_DEL IS NULL
        AND S.OBJ_ID = :I$PERSONCODE
        AND S.OBJ_TYPE_ID = 14
        INTO :PERSONCODE
    DO
    BEGIN
        ABONEMENTNO = NULL;
        ABONEMENTID = NULL;

        SELECT V FROM VAL_GET(:PERSONCODE,59,0) INTO :FIRSTNAME;
        SELECT V FROM VAL_GET(:PERSONCODE,60,0) INTO :NAME;
        SELECT V FROM VAL_GET(:PERSONCODE,61,0) INTO :LASTNAME;

        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:PERSONCODE)
        INTO :FULLNAME;

        SELECT A.ABONEMENTID
        FROM LIB_ABONEMENT A
        WHERE A.PERSONID = :PERSONCODE
        INTO :ABONEMENTID;

        SELECT A.ABONEMENTNO
        FROM LIB_ABONEMENT A
        WHERE A.PERSONID = :PERSONCODE
        INTO :ABONEMENTNO;

        SELECT V
        FROM VAL_GET(:PERSONCODE,278)
        INTO :EDUCATION;

        SELECT V FROM VAL_GET(:PERSONCODE,254,0) INTO :PHONE;
        SELECT A.REGION,
               A.DISTRICT,
               A.TOWN,
               A.SETTLEMENT,
               A.STREET,
               A.HOUSE,
               A.CORP,
               A.LITER,
               A.FLAT,
               A.POST_INDEX,
               A.VAL
        FROM ADR_GET (255,:PERSONCODE) A
        INTO :REGION,
             :DISTRICT,
             :TOWN,
             :SETTLEMENT,
             :STREET,
             :HOUSE,
             :CORP,
             :LITER,
             :FLAT,
             :POST_INDEX,
             :ADDRESS;

        PASSPORT_NUMBER = NULL;
        PASSPORT_SER = NULL;
        PASSPORT_OVD = NULL;
        PASSPORT_DATE = NULL;

        FOR
            SELECT L79.OBJ_ID
            FROM LINKS L79
            WHERE L79.PARENT_ID = :PERSONCODE
            AND L79.DATE_DEL IS NULL
            AND L79.OBJ_TYPE_ID = 79
            INTO :V$OBJ_ID
        DO
        BEGIN
            SELECT I
            FROM VAL_GET(:V$OBJ_ID,614)
            INTO :V$I;
            IF (V$I = 1982) THEN
            BEGIN
                SELECT V
                FROM VAL_GET(:PERSONCODE,442)
                INTO :PASSPORT_SER;

                SELECT V
                FROM VAL_GET(:PERSONCODE,559)
                INTO :PASSPORT_NUMBER;

                SELECT V
                FROM VAL_GET(:PERSONCODE,562)
                INTO :PASSPORT_OVD;

                SELECT VAL
                FROM VALD
                WHERE OBJ_ID = :PERSONCODE
                AND PARAM_ID = 560
                AND IS_DEL = 0
                INTO :PASSPORT_DATE;

                BREAK;
            END
        END

        BIRTHDAY = NULL;
        SELECT VAL
        FROM VALD
        WHERE OBJ_ID = :PERSONCODE
        AND PARAM_ID = 241
        AND IS_DEL = 0
        INTO :BIRTHDAY;

        SELECT FIRST 1
               POSITION_ID,
               "POSITION"
        FROM LIB_TEACHER_POSITION_LIST(:PERSONCODE)
        INTO :POSITION_ID,
             :"POSITION";

        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIB_TEACHER_LIST RETURNS (
    PERSONCODE BIGINT,
    FIRSTNAME VARCHAR(1000),
    NAME VARCHAR(1000),
    LASTNAME VARCHAR(1000),
    BIRTHDAY DATE,
    REGION VARCHAR(255),
    DISTRICT VARCHAR(255),
    TOWN VARCHAR(255),
    SETTLEMENT VARCHAR(255),
    STREET VARCHAR(255),
    HOUSE VARCHAR(10),
    CORP VARCHAR(10),
    LITER VARCHAR(10),
    FLAT VARCHAR(10),
    POST_INDEX VARCHAR(20),
    ADDRESS VARCHAR(2000),
    PHONE VARCHAR(255),
    FULLNAME VARCHAR(255),
    "POSITION" VARCHAR(1000),
    POSITION_ID BIGINT,
    ABONEMENTID BIGINT,
    ABONEMENTNO INTEGER)
AS
BEGIN
    FOR
        SELECT DISTINCT S.OBJ_ID
        FROM LINKS S
        WHERE S.DATE_DEL IS NULL
        AND S.OBJ_TYPE_ID = 14
        INTO :PERSONCODE
    DO
    BEGIN
        ABONEMENTNO = NULL;
        ABONEMENTID = NULL;

        SELECT V FROM VAL_GET(:PERSONCODE,59,0) INTO :FIRSTNAME;
        SELECT V FROM VAL_GET(:PERSONCODE,60,0) INTO :NAME;
        SELECT V FROM VAL_GET(:PERSONCODE,61,0) INTO :LASTNAME;

        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:PERSONCODE)
        INTO :FULLNAME;

        SELECT A.ABONEMENTID
        FROM LIB_ABONEMENT A
        WHERE A.PERSONID = :PERSONCODE
        INTO :ABONEMENTID;

        SELECT A.ABONEMENTNO
        FROM LIB_ABONEMENT A
        WHERE A.PERSONID = :PERSONCODE
        INTO :ABONEMENTNO;

        BIRTHDAY = NULL;
        SELECT VAL
        FROM VALD
        WHERE OBJ_ID = :PERSONCODE
        AND PARAM_ID = 241
        AND IS_DEL = 0
        INTO :BIRTHDAY;

        SELECT V FROM VAL_GET(:PERSONCODE,254,0) INTO :PHONE;

        SELECT A.REGION,
               A.DISTRICT,
               A.TOWN,
               A.SETTLEMENT,
               A.STREET,
               A.HOUSE,
               A.CORP,
               A.LITER,
               A.FLAT,
               A.POST_INDEX,
               A.VAL
        FROM ADR_GET (255,:PERSONCODE) A
        INTO :REGION,
             :DISTRICT,
             :TOWN,
             :SETTLEMENT,
             :STREET,
             :HOUSE,
             :CORP,
             :LITER,
             :FLAT,
             :POST_INDEX,
             :ADDRESS;

        SELECT FIRST 1
               POSITION_ID,
               "POSITION"
        FROM LIB_TEACHER_POSITION_LIST(:PERSONCODE)
        INTO :POSITION_ID,
             :"POSITION";

        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIB_TEACHER_POSITION_LIST (
    I$PERSONCODE BIGINT)
RETURNS (
    "POSITION" VARCHAR(1000),
    POSITION_ID BIGINT)
AS
BEGIN
    FOR
        SELECT LP13.PARENT_ID
        FROM LINKS L15
        INNER JOIN LINKS LP13
        ON LP13.OBJ_ID = L15.OBJ_ID
        AND LP13.PARENT_TYPE_ID = 13
        WHERE L15.PARENT_ID = :I$PERSONCODE
        AND L15.OBJ_TYPE_ID = 15
        AND L15.DATE_DEL IS NULL
        INTO :POSITION_ID
    DO
    BEGIN
        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:POSITION_ID)
        INTO :"POSITION";

        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LICENCE_INFO_GET RETURNS (
    STR VARCHAR(5000))
AS
declare variable V$KEY_CODE varchar(100);
declare variable V$KEY_NAME varchar(100);
declare variable V$KEY_VAL varchar(4000);
declare variable V$VAL varchar(4000);
declare variable V$SCHOOL_ID bigint;
declare variable V$POSITION integer;
BEGIN
    SELECT FIRST 1
           OBJ_ID
    FROM LINKS
    WHERE OBJ_TYPE_ID = 2
    AND PARENT_ID IS NULL
    AND DATE_DEL IS NULL
    INTO :V$SCHOOL_ID;

    FOR
        SELECT KEY_CODE,
               KEY_NAME,
               KEY_VAL
        FROM KEYS
        WHERE KEY_CODE = 'ORGANIZATION_FULL_NAME'
        OR KEY_CODE = 'ORGANIZATION_SHORT_NAME'
        OR KEY_CODE = 'CUSTOMER'
        OR KEY_CODE = 'ADDRESS'
        OR KEY_CODE = 'USER_COUNT'
        OR KEY_CODE = 'REG_NUMBER'
        ORDER BY KEY_ID
        INTO :V$KEY_CODE,
             :V$KEY_NAME,
             :V$KEY_VAL
    DO
    BEGIN
        STR = V$KEY_NAME;
        IF (V$KEY_CODE = 'USER_COUNT') THEN
        BEGIN
            STR = STR || ' = ';
        END
        ELSE
        BEGIN
            STR = STR || ': ' || ASCII_CHAR(13)||ASCII_CHAR(10);
        END
        IF (V$SCHOOL_ID IS NOT NULL) THEN
        BEGIN
            V$VAL = '';
            IF (V$KEY_CODE = 'ORGANIZATION_FULL_NAME') THEN
            BEGIN
                SELECT V
                FROM VAL_GET(:V$SCHOOL_ID, 5)
                INTO :V$VAL;
            END
            ELSE IF (V$KEY_CODE = 'ORGANIZATION_SHORT_NAME') THEN
            BEGIN
                SELECT V
                FROM VAL_GET(:V$SCHOOL_ID, 2)
                INTO :V$VAL;
            END
            ELSE IF (V$KEY_CODE = 'CUSTOMER') THEN
            BEGIN
                SELECT V
                FROM VAL_GET(:V$SCHOOL_ID, 1178)
                INTO :V$VAL;
                V$POSITION = POSITION(':' IN V$VAL);
                IF (V$POSITION > 0) THEN
                BEGIN
                    V$VAL = TRIM(SUBSTRING(V$VAL FROM V$POSITION + 1));
                END
            END
            ELSE IF (V$KEY_CODE = 'ADDRESS') THEN
            BEGIN
                SELECT V
                FROM VAL_GET(:V$SCHOOL_ID, 27)
                INTO :V$VAL;
            END
            IF (V$VAL <> '') THEN
            BEGIN
                V$KEY_VAL = V$VAL;
            END
        END
        STR = STR || V$KEY_VAL;
        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIC_DATA_04_1 (
    I$SCHOOL BIGINT)
RETURNS (
    C1 INTEGER,
    C2 VARCHAR(1000),
    C3 INTEGER,
    C4 INTEGER,
    C5 FLOAT,
    C6 FLOAT)
AS
declare variable V$SCHOOLPROGID bigint;
declare variable V$PROGNAME varchar(1000);
declare variable V$PROGGOALNAME varchar(1000);
declare variable V$MARRES bigint;
declare variable V$TMP integer;
declare variable V$TMP1 integer;
BEGIN
  C1 = 0;
  FOR SELECT SCHOOLPROGID, PROGNAME, PROGGOALNAME
      FROM LIC_DATA_GET_PROGS(:I$SCHOOL)
      INTO :V$SCHOOLPROGID, :V$PROGNAME, :V$PROGGOALNAME
  DO
  BEGIN
    C1 = C1 + 1;
    C2 = V$PROGNAME;
    C3 = 0;
    C4 = 0;
    C5 = 0;
    C6 = 0;
    --  suspend;
    FOR SELECT DISTINCT(L107.OBJ_ID), L107.COST
        FROM LINKS L50
        JOIN LINKS L49 ON (L49.PARENT_ID = L50.OBJ_ID AND L49.DATE_DEL IS NULL AND L49.OBJ_TYPE_ID = 49)
        JOIN LINKS L56 ON (L56.PARENT_ID = L49.OBJ_ID AND L56.DATE_DEL IS NULL AND L56.OBJ_TYPE_ID = 56)
        JOIN LINKS L107 ON (L107.PARENT_ID = L56.OBJ_ID AND L107.DATE_DEL IS NULL AND L107.OBJ_TYPE_ID = 107)
        WHERE L50.OBJ_TYPE_ID = 50 AND
              L50.DATE_DEL IS NULL AND
              L50.PARENT_ID = :V$SCHOOLPROGID
        INTO V$MARRES, V$TMP1
    DO
    BEGIN
      C3 = :C3 + 1;
      SELECT
        CASE
          WHEN VL.LISTVAL_ID IN (2098, 2097) THEN
           (SELECT V FROM VAL_GET(VL.OBJ_ID, 648))
          WHEN VL.LISTVAL_ID = 2099 THEN :V$TMP1
        END AS C4
      FROM VALL VL
      WHERE VL.PARAM_ID = 653 AND
            VL.OBJ_ID = :V$MARRES
      INTO V$TMP;
      IF (:V$TMP IS NOT NULL) THEN
        C4 = :C4 + :V$TMP;
      SELECT
        CASE
          WHEN VL.LISTVAL_ID IN (2098, 2097) THEN (SELECT V
          FROM VAL_GET(VL.OBJ_ID, 648))
          WHEN VL.LISTVAL_ID = 2099 THEN :V$TMP1
        END AS C4
      FROM VALL VL
      JOIN VALS VS ON (VS.OBJ_ID = VL.OBJ_ID AND VS.PARAM_ID = 650 AND VS.IS_DEL = 0 AND VS.VAL > (EXTRACT(YEAR FROM CURRENT_DATE) - 10))
      WHERE VL.PARAM_ID = 653 AND
            VL.OBJ_ID = :V$MARRES
      INTO V$TMP;
      IF (:V$TMP IS NOT NULL) THEN
        C6 = :C6 + :V$TMP;
    END
    SELECT COALESCE(SUM(VI.VAL), 0)
    FROM LINKS L50
    JOIN LINKS L54 ON (L54.PARENT_ID = L50.OBJ_ID AND L54.DATE_DEL IS NULL AND L54.OBJ_TYPE_ID = 54)
    JOIN VALI VI ON (VI.OBJ_ID = L54.OBJ_ID AND VI.PARAM_ID = 1190 AND VI.IS_DEL = 0)
    WHERE L50.OBJ_TYPE_ID = 50 AND
          L50.DATE_DEL IS NULL AND
          L50.PARENT_ID = :V$SCHOOLPROGID
    INTO :C5;
    IF (C5 != 0) THEN
      C5 = C4 / C5;
    IF (C4 != 0) THEN
      C6 = 100 * C6 / C4;

    SUSPEND;
  END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIC_DATA_04_2 (
    SCHOOL BIGINT)
RETURNS (
    C1 INTEGER,
    C2 VARCHAR(250),
    C3 VARCHAR(250),
    C4 INTEGER,
    C5 INTEGER)
AS
declare variable V$SCHOOLPROGID bigint;
declare variable V$PROGNAME varchar(100);
declare variable V$TMP integer;
declare variable V$MARRES bigint;
BEGIN
  C1 = 0;
  FOR SELECT SCHOOLPROGID, PROGNAME --, PROGGOALNAME
      FROM LIC_DATA_GET_PROGS(:SCHOOL)
      WHERE ORDERID = 1
      INTO :V$SCHOOLPROGID, :V$PROGNAME --, :V$PROGGOALNAME
  DO
  BEGIN
    C1 = C1 + 1;
    C2 = V$PROGNAME;
    C3 = NULL;
    C4 = NULL;
    C5 = NULL;
    SUSPEND;
    FOR SELECT DISTINCT L107.OBJ_ID, L107.COST
        FROM LINKS L50
        JOIN LINKS L49 ON (L49.PARENT_ID = L50.OBJ_ID AND L49.DATE_DEL IS NULL AND L49.OBJ_TYPE_ID = 49)
        JOIN LINKS L56 ON (L56.PARENT_ID = L49.OBJ_ID AND L56.DATE_DEL IS NULL AND L56.OBJ_TYPE_ID = 56)
        JOIN LINKS L107 ON (L107.PARENT_ID = L56.OBJ_ID AND L107.DATE_DEL IS NULL AND L107.OBJ_TYPE_ID = 107)
        WHERE L50.OBJ_TYPE_ID = 50 AND
              L50.DATE_DEL IS NULL AND
              L50.PARENT_ID = :V$SCHOOLPROGID
        INTO V$MARRES, V$TMP
    DO
    BEGIN
      SELECT V1.V || ' ' || V2.V
      FROM VAL_GET(:V$MARRES, 654) v1
      join VAL_GET(:V$SCHOOLPROGID, 399) v2 ON 1 = 1
     INTO :C2;

      SELECT V1.V || ' «' || V2.V || '» ' || V3.V || ' ' || V4.V || ' ' || V5.V
      FROM VAL_GET(:V$MARRES, 646) V1
      INNER JOIN VAL_GET(:V$MARRES, 652) V2 ON 1 = 1
      INNER JOIN VAL_GET(:V$MARRES, 647) V3 ON 1 = 1
      INNER JOIN VAL_GET(:V$MARRES, 651) V4 ON 1 = 1
      INNER JOIN VAL_GET(:V$MARRES, 650) V5 ON 1 = 1
      INTO :C3;

      SELECT
        CASE
          WHEN VL.LISTVAL_ID IN (2098, 2097) THEN
            (SELECT V FROM VAL_GET(VL.OBJ_ID, 648))
             WHEN VL.LISTVAL_ID = 2099 THEN :V$TMP
        END AS C4
      FROM VALL VL
      WHERE VL.PARAM_ID = 653 AND
            VL.OBJ_ID = :V$MARRES
      INTO C4;

      SELECT COALESCE(SUM(VI.VAL), 0)
      FROM LINKS L50
      JOIN LINKS L54 ON (L54.PARENT_ID = L50.OBJ_ID AND L54.DATE_DEL IS NULL AND L54.OBJ_TYPE_ID = 54)
      JOIN VALI VI ON (VI.OBJ_ID = L54.OBJ_ID AND VI.PARAM_ID = 1190 AND VI.IS_DEL = 0)
      WHERE L50.OBJ_TYPE_ID = 50 AND
            L50.DATE_DEL IS NULL AND
            L50.PARENT_ID = :V$SCHOOLPROGID
      INTO :C5;
      SUSPEND;
    END
  END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIC_DATA_04_4 (
    SCHOOL BIGINT)
RETURNS (
    C1 INTEGER,
    C2 VARCHAR(4000),
    C3 VARCHAR(4000),
    C4 INTEGER)
AS
DECLARE VARIABLE V$SCHOOLPROGID bigint;
DECLARE VARIABLE V$PROGNAME VARCHAR(100);
DECLARE VARIABLE V$TMP BIGINT;
BEGIN
    C1 = 0;
    FOR SELECT SCHOOLPROGID, PROGNAME
        FROM LIC_DATA_GET_PROGS(:SCHOOL)
        WHERE ORDERID = 1
        INTO :V$SCHOOLPROGID, :V$PROGNAME
    DO
    BEGIN
        C1 = C1 + 1;
        C2 = V$PROGNAME;
        C3 = NULL;
        C4 = NULL;
        SUSPEND;

        FOR SELECT DISTINCT L106.OBJ_ID
            FROM LINKS L50
            JOIN LINKS L49 ON (L49.PARENT_ID = L50.OBJ_ID AND L49.DATE_DEL IS NULL AND L49.OBJ_TYPE_ID = 49)
            JOIN LINKS L56 ON (L56.PARENT_ID = L49.OBJ_ID AND L56.DATE_DEL IS NULL AND L56.OBJ_TYPE_ID = 56)
            JOIN LINKS L106 ON (L106.PARENT_ID = L56.OBJ_ID AND L106.DATE_DEL IS NULL AND L106.OBJ_TYPE_ID = 106)
            WHERE L50.OBJ_TYPE_ID = 50
              AND L50.DATE_DEL IS NULL
              AND L50.PARENT_ID = :V$SCHOOLPROGID
            INTO :V$TMP
        DO
        BEGIN
            SELECT V1.V || ' ' || V2.V
            FROM VAL_GET(:V$TMP, 644) V1
            INNER JOIN VAL_GET(:V$SCHOOLPROGID, 399) V2 ON 1 = 1
            INTO :C2;

            SELECT V1.V || ' «' || V2.V || '» ' || V3.V || ' ' || V4.V
            FROM VAL_GET(:V$TMP, 637) V1
            INNER JOIN VAL_GET(:V$TMP, 639) V2 ON 1 = 1
            INNER JOIN VAL_GET(:V$TMP, 641) V3 ON 1 = 1
            INNER JOIN VAL_GET(:V$TMP, 642) V4 ON 1 = 1
            INTO :C3;

            SELECT I
            FROM VAL_GET(:V$TMP, 640)
            INTO :C4;

            SUSPEND;
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIC_DATA_05 (
    I$OBJ_ID BIGINT,
    I$PROGTYPEID INTEGER)
RETURNS (
    PROGKINDID INTEGER,
    LICENSE VARCHAR(3),
    ORDERID INTEGER,
    ORDERID2 INTEGER,
    PROGNAME VARCHAR(500),
    PROGTYPENAME VARCHAR(500),
    PROGGOALNAME VARCHAR(500),
    PROGNORMTERM VARCHAR(20),
    PROGLEVELNAME VARCHAR(500),
    PROGKINDNAME VARCHAR(500),
    OVERALL FLOAT,
    OCHNO INTEGER,
    OCHNOZAOCHNO INTEGER,
    ZAOCHNO INTEGER,
    EXTERNAT INTEGER,
    SROKOSV VARCHAR(250))
AS
declare variable V$L57 bigint;
BEGIN
 /* SELECT V
  FROM VAL_GET(:I$OBJ_ID, 5)
  INTO PROGNAME;
  SUSPEND; */
  FOR SELECT (SELECT I FROM VAL_GET(L57.OBJ_ID, 389)) AS PROGKINDID,
             (SELECT V FROM VAL_GET(L57.OBJ_ID, 1184)) AS LICENSE,
             (SELECT CASE
                        WHEN I = 5336 THEN 1
                        WHEN I = 5345 THEN 2
                        WHEN I = 5364 THEN 3
                        WHEN I = 5357 THEN 4
                        --WHEN I = 3345 THEN 5
                        ELSE 10
                      END
               FROM VAL_GET(L57.OBJ_ID, 1832)) AS ORDERID,
              (SELECT V
               FROM VAL_GET(L57.OBJ_ID, 1832)) AS PROGTYPENAME , L57.OBJ_ID
      FROM LINKS L69
      JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
      JOIN VALL VL2 ON VL2.OBJ_ID = L57.OBJ_ID AND VL2.IS_DEL = 0 AND VL2.PARAM_ID = 1832 AND VL2.LISTVAL_ID = :I$PROGTYPEID
      WHERE L69.OBJ_TYPE_ID = 69 AND
            L69.DATE_DEL IS NULL AND
            L69.PARENT_ID = :I$OBJ_ID
      ORDER BY 2, 1, 3, 4
      INTO PROGKINDID, LICENSE, ORDERID, PROGTYPENAME, V$L57
  DO
  BEGIN
    SELECT CASE
             WHEN I = 22 THEN 1
             WHEN I = 26 THEN 2
             WHEN I = 27 THEN 3
             WHEN I = 791 THEN 4
             WHEN I = 792 THEN 5
             WHEN I = 29 THEN 6
             ELSE 10
             END
              FROM VAL_GET(:V$L57, 387) into ORDERID2;

    SELECT VS.VAL
               FROM VALS VS
               WHERE VS.OBJ_ID = :V$L57 AND
                     VS.PARAM_ID = 386 into PROGNAME;

    SELECT V FROM VAL_GET(:V$L57, 390) INTO PROGGOALNAME;
    SELECT V FROM VAL_GET(:V$L57, 399) INTO PROGNORMTERM;
    SELECT V FROM VAL_GET(:V$L57, 1594) INTO PROGLEVELNAME;
--DELETED!!!    SELECT V FROM VAL_GET(:V$L57, 389) INTO PROGKINDNAME;

    SELECT V FROM VAL_GET(:V$L57, 399) INTO SROKOSV;

    SELECT COALESCE(SUM(VL.VAL), 0)
    FROM LINKS L50
    JOIN LINKS L54 ON L54.PARENT_ID = L50.OBJ_ID AND L50.OBJ_TYPE_ID = 50 AND L50.DATE_DEL IS NULL
    JOIN VALF VL ON VL.OBJ_ID = L54.OBJ_ID AND VL.PARAM_ID = 1191 AND VL.IS_DEL = 0
    WHERE L50.OBJ_TYPE_ID = 50 AND
          L50.DATE_DEL IS NULL AND
          L50.PARENT_ID = :V$L57
    INTO OVERALL;

    SELECT COALESCE(SUM(VL.VAL), 0)
    FROM LINKS L50
    JOIN LINKS L54 ON L54.PARENT_ID = L50.OBJ_ID AND L50.OBJ_TYPE_ID = 50 AND L50.DATE_DEL IS NULL
    JOIN VALI VL ON VL.OBJ_ID = L54.OBJ_ID AND VL.PARAM_ID = 1187 AND VL.IS_DEL = 0
    WHERE L50.OBJ_TYPE_ID = 50 AND
          L50.DATE_DEL IS NULL AND
          L50.PARENT_ID = :V$L57
    INTO OCHNOZAOCHNO;

    SELECT COALESCE(SUM(VL.VAL), 0)
    FROM LINKS L50
    JOIN LINKS L54 ON L54.PARENT_ID = L50.OBJ_ID AND L50.OBJ_TYPE_ID = 50 AND L50.DATE_DEL IS NULL
    JOIN VALI VL ON VL.OBJ_ID = L54.OBJ_ID AND VL.PARAM_ID = 1188 AND VL.IS_DEL = 0
    WHERE L50.OBJ_TYPE_ID = 50 AND
          L50.DATE_DEL IS NULL AND
          L50.PARENT_ID = :V$L57
    INTO ZAOCHNO;

    SELECT COALESCE(SUM(VL.VAL), 0)
    FROM LINKS L50
    JOIN LINKS L54 ON L54.PARENT_ID = L50.OBJ_ID AND L50.OBJ_TYPE_ID = 50 AND L50.DATE_DEL IS NULL
    JOIN VALI VL ON VL.OBJ_ID = L54.OBJ_ID AND VL.PARAM_ID = 1189 AND VL.IS_DEL = 0
    WHERE L50.OBJ_TYPE_ID = 50 AND
          L50.DATE_DEL IS NULL AND
          L50.PARENT_ID = :V$L57
    INTO EXTERNAT;

    SELECT COALESCE(SUM(VL.VAL), 0)
    FROM LINKS L50
    JOIN LINKS L54 ON L54.PARENT_ID = L50.OBJ_ID AND L50.OBJ_TYPE_ID = 50 AND L50.DATE_DEL IS NULL
    JOIN VALI VL ON VL.OBJ_ID = L54.OBJ_ID AND VL.PARAM_ID = 1186 AND VL.IS_DEL = 0
    WHERE L50.OBJ_TYPE_ID = 50 AND
          L50.DATE_DEL IS NULL AND
          L50.PARENT_ID = :V$L57
    INTO OCHNO;
    SUSPEND;
  END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIC_DATA_05_1 (
    I$OBJ_ID BIGINT)
RETURNS (
    INN VARCHAR(200),
    KPP VARCHAR(200),
    GRN VARCHAR(200),
    GRN1 VARCHAR(200),
    LIC VARCHAR(200),
    R_OU VARCHAR(200),
    PHONE VARCHAR(200),
    FAX VARCHAR(200),
    ALL_PUPILCOUNT_OLD VARCHAR(200),
    ALL_FORMCOUNT VARCHAR(200),
    OCHNO_PUPILCOUNT VARCHAR(200),
    PRJ_PUPLCOUNT VARCHAR(200),
    COMPUTER_CLASS VARCHAR(200),
    COMPUTERS_COUNT VARCHAR(200),
    INNKPP VARCHAR(200),
    EMAIL VARCHAR(200))
AS
DECLARE VARIABLE V$SERIA VARCHAR(100);
DECLARE VARIABLE V$NUM VARCHAR(100);
DECLARE VARIABLE V$OBJ_ID BIGINT;
BEGIN
    SELECT FIRST 1
           L17.OBJ_ID

    FROM LINKS L17

    JOIN VALL VI
    ON VI.OBJ_ID = L17.OBJ_ID
    AND VI.PARAM_ID = 471
    AND VI.LISTVAL_ID = 1049

    WHERE L17.OBJ_TYPE_ID = 17
    AND L17.DATE_DEL IS NULL
    AND L17.PARENT_ID = :I$OBJ_ID
    INTO :V$OBJ_ID;

    SELECT V
    FROM VAL_GET(:I$OBJ_ID, 33)
    INTO :INN;
    SELECT V
    FROM VAL_GET(:I$OBJ_ID, 35)
    INTO :EMAIL;
    SELECT V
    FROM VAL_GET(:V$OBJ_ID, 479)
    INTO V$SERIA;
    SELECT V
    FROM VAL_GET(:V$OBJ_ID, 480)
    INTO V$NUM;

    INNKPP = :INN;
    INN = :INN || ', серия ' || :V$SERIA || ' №' || :V$NUM;
    SELECT V
    FROM VAL_GET(:I$OBJ_ID, 34)
    INTO KPP;
    KPP = :KPP || ', серия ' || :V$SERIA || ' №' || :V$NUM;
    SELECT V
    FROM VAL_GET(:I$OBJ_ID, 9)
    INTO GRN;
    --GRN = :GRN || ', серия ' || :v$SERIA || ' №' || :V$NUM;

    SELECT FIRST 1 'серия ' || (SELECT V
                                    FROM VAL_GET(L17.OBJ_ID, 479)) || ' №' ||(SELECT V
                                                                                FROM VAL_GET(L17.OBJ_ID, 480)) || ' от ' ||(SELECT V
                                                                                                                              FROM VAL_GET(L17.OBJ_ID, 482)) AS DT
    FROM LINKS L17
    JOIN VALL VI ON VI.OBJ_ID = L17.OBJ_ID AND VI.PARAM_ID = 471 AND VI.LISTVAL_ID = 1070
    WHERE L17.OBJ_TYPE_ID = 17
      AND L17.DATE_DEL IS NULL
      AND L17.PARENT_ID = :I$OBJ_ID
    INTO GRN1;

    IF (:GRN1 IS NULL) THEN


        SELECT FIRST 1 'серия ' ||(SELECT V
                                        FROM VAL_GET(L17.OBJ_ID, 479)) || ' №' ||(SELECT V
                                                                                    FROM VAL_GET(L17.OBJ_ID, 480)) || ' от ' ||(SELECT V
                                                                                                                                  FROM VAL_GET(L17.OBJ_ID, 482)) AS DT
        FROM LINKS L17
        JOIN VALL VI ON VI.OBJ_ID = L17.OBJ_ID AND VI.PARAM_ID = 471 AND VI.LISTVAL_ID = 1071
        JOIN VALD VD ON VD.OBJ_ID = L17.OBJ_ID AND VD.PARAM_ID = 482
        WHERE L17.OBJ_TYPE_ID = 17
          AND L17.DATE_DEL IS NULL
          AND L17.PARENT_ID = :I$OBJ_ID
        ORDER BY VD.VAL DESC
        INTO GRN1;/**/

    IF (:GRN1 IS NULL) THEN
        GRN1 = ' №';
    SELECT FIRST 1 'серия ' ||(SELECT V
                                    FROM VAL_GET(L17.OBJ_ID, 479)) || ' №' ||(SELECT V
                                                                                FROM VAL_GET(L17.OBJ_ID, 480)) || ' по ' ||(SELECT V
                                                                                                                              FROM VAL_GET(L17.OBJ_ID, 483)) AS DT
    FROM LINKS L17
    JOIN VALL VI ON VI.OBJ_ID = L17.OBJ_ID AND VI.PARAM_ID = 471 AND VI.LISTVAL_ID IN (1052, 18624)
    JOIN VALL V ON V.OBJ_ID = L17.OBJ_ID AND V.PARAM_ID = 613 AND V.LISTVAL_ID IN (1982, 1984) -- действующий
    WHERE L17.OBJ_TYPE_ID = 17
      AND L17.DATE_DEL IS NULL
      AND L17.PARENT_ID = :I$OBJ_ID
    INTO LIC;

    SELECT FIRST 1(SELECT V
                   FROM VAL_GET(L13.OBJ_ID, 58)) AS DOLJ
    FROM LINKS L13
    JOIN VALL VI ON VI.OBJ_ID = L13.OBJ_ID AND VI.PARAM_ID = 58 AND VI.LISTVAL_ID = 64
    WHERE L13.OBJ_TYPE_ID = 13 
      AND L13.DATE_DEL IS NULL 
      AND L13.PARENT_ID = :I$OBJ_ID
    INTO R_OU;

    SELECT V
    FROM VAL_GET(:I$OBJ_ID, 29)
    INTO PHONE;

    IF (:PHONE IS NULL) THEN
        PHONE = ' ';
    ELSE
        PHONE = 'тел.' || :PHONE;
    SELECT V
    FROM VAL_GET(:I$OBJ_ID, 30)
    INTO FAX;

    IF (:FAX IS NULL) THEN
        FAX = ' ';
    ELSE
        FAX = 'факс ' || :FAX;
    SELECT V
    FROM VAL_GET(:I$OBJ_ID, 12)
    INTO PRJ_PUPLCOUNT;

    SELECT COUNT(OBJ_ID)
    FROM OBJECT_CHILDREN_GET_DEEP(:I$OBJ_ID, 9, 3)
    INTO ALL_FORMCOUNT;

    SELECT COUNT(OBJ_ID)
    FROM OBJECT_CHILDREN_GET_DEEP(:I$OBJ_ID, 10, 4)
    INTO ALL_PUPILCOUNT_OLD;

    SELECT PPLCOUNTS
    FROM LIC_DATA_PPLCOUNTS(:I$OBJ_ID, 5336)
    INTO OCHNO_PUPILCOUNT;

    SELECT
           CASE
             WHEN COUNT(L128.OBJ_ID) > 0 THEN 'есть'
             ELSE 'нет'
           END AS C_CLASS
    FROM LINKS L23
    JOIN LINKS L128 ON L23.OBJ_ID = L128.PARENT_ID AND L128.OBJ_TYPE_ID = 128 AND L128.DATE_DEL IS NULL
    JOIN VALL VL ON VL.OBJ_ID = L128.OBJ_ID AND VL.PARAM_ID = 876 AND VL.LISTVAL_ID IN (2067, 2068)
    WHERE L23.OBJ_TYPE_ID = 23
      AND L23.DATE_DEL IS NULL
      AND L23.PARENT_ID = :I$OBJ_ID
    INTO COMPUTER_CLASS;

    SELECT COUNT(L114.OBJ_ID) AS C_COMP
    FROM LINKS L23
    JOIN LINKS L128 ON L23.OBJ_ID = L128.PARENT_ID AND L128.OBJ_TYPE_ID = 128 AND L128.DATE_DEL IS NULL
    JOIN VALL VL ON VL.OBJ_ID = L128.OBJ_ID AND VL.PARAM_ID = 876 AND VL.LISTVAL_ID IN (2067, 2068)
    JOIN LINKS L114 ON L128.OBJ_ID = L114.PARENT_ID AND L114.OBJ_TYPE_ID = 114 AND L114.DATE_DEL IS NULL
    WHERE L23.OBJ_TYPE_ID = 23
      AND L23.DATE_DEL IS NULL
      AND L23.PARENT_ID = :I$OBJ_ID
    INTO COMPUTERS_COUNT;

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIC_DATA_05_2 (
    I$OBJ_ID BIGINT,
    TYPE_DOLJ INTEGER)
RETURNS (
    F VARCHAR(100),
    I VARCHAR(100),
    O VARCHAR(100),
    TEL VARCHAR(50),
    ADDRESS VARCHAR(500),
    EDUC VARCHAR(500),
    TELEPHON_DIREKTORA VARCHAR(500),
    TELEFON_BUHGALTERA VARCHAR(500),
    OBJ_ID BIGINT,
    FIO VARCHAR(100))
AS
declare variable V$CHILD_OBJ_ID bigint;
declare variable V$TMP_OBJ_ID bigint;
declare variable V$TYPE_DOLJ bigint;
declare variable V$FIO varchar(500);
BEGIN
    FOR SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.PARENT_ID = :I$OBJ_ID
          AND L.OBJ_TYPE_ID = 13
          AND L.DATE_DEL IS NULL
        INTO V$CHILD_OBJ_ID
    DO
    BEGIN
        SELECT I
        FROM VAL_GET(:V$CHILD_OBJ_ID, 58)
        INTO V$TYPE_DOLJ;
        IF (:V$TYPE_DOLJ = TYPE_DOLJ) THEN
        BEGIN
            FOR SELECT L14.PARENT_ID
                FROM LINKS L15
                JOIN LINKS L14 ON L15.OBJ_ID = L14.OBJ_ID AND L14.PARENT_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
                WHERE L15.OBJ_TYPE_ID = 15
                  AND L15.DATE_DEL IS NULL
                  AND L15.PARENT_ID = :V$CHILD_OBJ_ID
                INTO V$TMP_OBJ_ID
            DO
            BEGIN
                OBJ_ID = :V$TMP_OBJ_ID;
                SELECT V
                FROM VAL_GET(:V$TMP_OBJ_ID, 60)
                INTO I;
                SELECT V
                FROM VAL_GET(:V$TMP_OBJ_ID, 59)
                INTO F;
                -- FIO = FIO || ' ' || V$FIO;
                SELECT V
                FROM VAL_GET(:V$TMP_OBJ_ID, 61)
                INTO O;
                --  FIO = FIO || ' ' || V$FIO;
                SELECT V
                FROM VAL_GET(:V$TMP_OBJ_ID, 253)
                INTO TEL;
                SELECT V
                FROM VAL_GET(:V$TMP_OBJ_ID, 278)
                INTO EDUC;
                SELECT VAL
                FROM ADR_GET(255, :V$TMP_OBJ_ID)
                INTO ADDRESS;
                SELECT V
                FROM VAL_GET(:I$OBJ_ID, 28)
                INTO TELEPHON_DIREKTORA;
                SELECT V
                FROM VAL_GET(:I$OBJ_ID, 31)
                INTO TELEFON_BUHGALTERA;
                FIO = :F || ' ' || SUBSTRING(I FROM 1 FOR 1) || '. ' || SUBSTRING(O FROM 1 FOR 1) || '. ';
                SUSPEND;
            END
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIC_DATA_05_3 (
    I$OBJ_ID BIGINT,
    I$PARAM_ID INTEGER,
    I$LISTVAL_ID INTEGER)
RETURNS (
    TEACHERS_COUNT INTEGER)
AS
declare variable V$Temp bigint;
declare variable V$TempCount integer;
begin
  TEACHERS_COUNT = 0;
  for select Teacher_Id from PARAGRAF_GRADE_TEACHERS_LIST(:I$OBJ_ID) into
  V$Temp do
  begin
    select
     count(l15.OBJ_ID)
    from LINKS l15
     join vall vl on vl.OBJ_ID = l15.OBJ_ID and vl.PARAM_ID = :I$PARAM_ID and
     vl.LISTVAL_ID = :I$LISTVAL_ID
    where l15.PARENT_ID = :V$Temp into V$TempCount;
    TEACHERS_COUNT = :TEACHERS_COUNT + :V$TempCount;
  end
  suspend;
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIC_DATA_05_4 (
    I$OBJ_ID BIGINT,
    I$PARAM_ID INTEGER)
RETURNS (
    TEACHERS_COUNT INTEGER)
AS
declare variable V$Temp bigint;
declare variable V$TempCount integer;
begin
  TEACHERS_COUNT = 0;
  for select Teacher_Id from PARAGRAF_GRADE_TEACHERS_LIST(:I$OBJ_ID) into
  V$Temp do
  begin
    select count(*) from vall vl where vl.PARAM_ID = 279 and vl.LISTVAL_ID = :I$PARAM_ID and
    vl.OBJ_ID = :V$Temp into V$TempCount;
    TEACHERS_COUNT = :TEACHERS_COUNT + :V$TempCount;
  end
  suspend;
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIC_DATA_05_5 (
    I$OBJ_ID BIGINT)
RETURNS (
    TEACHERS_COUNT INTEGER)
AS
declare variable V$Temp bigint;
declare variable V$TempCount integer;
begin
  TEACHERS_COUNT = 0;
  for select Teacher_Id from PARAGRAF_GRADE_TEACHERS_LIST(:I$OBJ_ID) into
  V$Temp do
  begin
  select count(*) from LINKS l10
   join VALL vl on vl.OBJ_ID = l10.OBJ_ID and vl.PARAM_ID = 279 and vl.LISTVAL_ID = 626
   join VALL vl1 on vl1.OBJ_ID = l10.OBJ_ID and vl1.PARAM_ID = 280 and vl1.LISTVAL_ID != 629
   where l10.OBJ_ID = :V$Temp into V$TempCount;
  TEACHERS_COUNT = :TEACHERS_COUNT + :V$TempCount;
  end
  suspend;
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIC_DATA_05_6 (
    I$OBJ_ID BIGINT)
RETURNS (
    TEACHERS_COUNT INTEGER)
AS
DECLARE VARIABLE V$TEMP bigint;
DECLARE VARIABLE V$TEMPCOUNT INTEGER;
BEGIN
  TEACHERS_COUNT = 0;
  FOR SELECT TEACHER_ID
      FROM PARAGRAF_GRADE_TEACHERS_LIST(:I$OBJ_ID)
      INTO V$TEMP
  DO
  BEGIN
    SELECT COUNT(*)
    FROM LINKS L33
    JOIN VALL VL ON VL.OBJ_ID = L33.OBJ_ID AND VL.PARAM_ID = 284 AND VL.LISTVAL_ID IN (622, 624)
    WHERE L33.PARENT_ID = :V$TEMP
    INTO V$TEMPCOUNT;

    IF (:V$TEMPCOUNT > 0) THEN
    BEGIN
      SELECT COUNT(L13.PARENT_ID)
      FROM LINKS L15
      JOIN LINKS L13 ON L15.OBJ_ID = L13.OBJ_ID AND L13.PARENT_TYPE_ID = 13 AND L13.DATE_DEL IS NULL
      JOIN VALL VL ON VL.OBJ_ID = L13.PARENT_ID AND VL.PARAM_ID = 58 AND VL.LISTVAL_ID = 130
      WHERE L15.OBJ_TYPE_ID = 15 AND
            L15.DATE_DEL IS NULL AND
            L15.PARENT_ID = :V$TEMP
      INTO V$TEMPCOUNT;
      TEACHERS_COUNT = :TEACHERS_COUNT + :V$TEMPCOUNT;
    END
  END
  SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIC_DATA_05_7 (
    I$OBJ_ID BIGINT)
RETURNS (
    TEACHERS_COUNT INTEGER)
AS
declare variable V$Temp bigint;
declare variable V$TempCount integer;
begin
  TEACHERS_COUNT = 0;
  for select Teacher_Id from PARAGRAF_GRADE_TEACHERS_LIST(:I$OBJ_ID) into
  V$Temp do
  begin
    select
     count(l15.OBJ_ID)
    from LINKS l15
     join vall vl on vl.OBJ_ID = l15.OBJ_ID and vl.PARAM_ID = 284 and
     vl.LISTVAL_ID in (621,623,625)
    where l15.PARENT_ID = :V$Temp into V$TempCount;
    TEACHERS_COUNT = :TEACHERS_COUNT + :V$TempCount;
  end
  suspend;
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIC_DATA_06_1 (
    I$OBJ_ID BIGINT)
RETURNS (
    VAL INTEGER,
    VAL1 INTEGER,
    VAL2 INTEGER)
AS
declare variable V$OBJ_ID bigint;
declare variable V$TEMP integer;
BEGIN
    VAL = 0;
    VAL1 = 0;
    VAL2 = 0;

    FOR
        SELECT TEACHER_ID
        FROM PARAGRAF_GRADE_TEACHERS_LIST(:I$OBJ_ID)
        INTO V$OBJ_ID
    DO
    BEGIN
        SELECT COUNT(*)
        FROM VALL VL
        WHERE VL.OBJ_ID = :V$OBJ_ID
        AND VL.PARAM_ID = 278
        INTO V$TEMP;

        IF (:V$TEMP = 0) THEN
        BEGIN
            VAL = :VAL + 1;
        END

        SELECT COUNT(*)
        FROM VALL VL
        WHERE VL.OBJ_ID = :V$OBJ_ID
        AND VL.PARAM_ID = 274
        INTO V$TEMP;

        IF (:V$TEMP = 0) THEN
        BEGIN
            VAL1 = :VAL1 + 1;
        END
    END
    FOR
        SELECT L13.OBJ_ID
        FROM LINKS L13

        LEFT JOIN VALL VL
        ON VL.OBJ_ID = L13.OBJ_ID
        AND VL.PARAM_ID = 58
        AND VL.IS_DEL = 0

        LEFT JOIN LISTVALS LV
        ON LV.LISTVAL_ID = VL.LISTVAL_ID

        WHERE L13.OBJ_TYPE_ID = 13
        AND L13.DATE_DEL IS NULL
        AND L13.PARENT_ID = :I$OBJ_ID
        AND ((VL.LISTVAL_ID IS NULL) OR (LV.TAG <> 'U'))
        INTO V$OBJ_ID
    DO
    BEGIN
        SELECT COUNT(VF.VAL)
        FROM VALF VF
        WHERE VF.PARAM_ID = 62
        AND VF.OBJ_ID = :V$OBJ_ID
        INTO V$TEMP;

        IF (:V$TEMP = 0) THEN
        BEGIN
            VAL2 = :VAL2 + 1;
        END
    END
    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIC_DATA_07 (
    I$PROPERTYID BIGINT,
    I$RIGHTDOC BIGINT,
    I$BUILDINGCODE BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    NAME VARCHAR(400),
    "COUNT" INTEGER,
    SPACE FLOAT,
    TAG INTEGER)
AS
BEGIN

    FOR SELECT "NAME", "COUNT", "SPACE", "TAG"
        FROM LIC_DATA_07_1(:I$PROPERTYID, :I$RIGHTDOC, :I$BUILDINGCODE, 10000)
        INTO "NAME", "COUNT", "SPACE", "TAG"
    DO
        SUSPEND;
    FOR SELECT "NAME", "COUNT", "SPACE", "TAG"
        FROM LIC_DATA_07_3(:I$PROPERTYID, :I$RIGHTDOC, :I$BUILDINGCODE, 10100, :I$USER_ID)
        INTO "NAME", "COUNT", "SPACE", "TAG"
    DO
        SUSPEND;
    FOR SELECT "NAME", "COUNT", "SPACE", TAG
        FROM LIC_DATA_07_3(:I$PROPERTYID, :I$RIGHTDOC, :I$BUILDINGCODE, 10200, :I$USER_ID)
        INTO "NAME", "COUNT", "SPACE", TAG
    DO
        SUSPEND;
    FOR SELECT "NAME", "COUNT", "SPACE", "TAG"
        FROM LIC_DATA_07_3(:I$PROPERTYID, :I$RIGHTDOC, :I$BUILDINGCODE, 10300, :I$USER_ID)
        INTO "NAME", "COUNT", "SPACE", "TAG"
    DO
        SUSPEND;
    FOR SELECT "NAME", "COUNT", "SPACE", "TAG"
        FROM LIC_DATA_07_3(:I$PROPERTYID, :I$RIGHTDOC, :I$BUILDINGCODE, 10400, :I$USER_ID)
        INTO "NAME", "COUNT", "SPACE", "TAG"
    DO
        SUSPEND;
    FOR SELECT "NAME", "COUNT", "SPACE", "TAG"
        FROM LIC_DATA_07_2(:I$PROPERTYID, :I$RIGHTDOC, :I$BUILDINGCODE, 11000, :I$USER_ID)
        INTO "NAME", "COUNT", "SPACE", "TAG"
    DO
        SUSPEND;
    SELECT CAST(NULL AS VARCHAR(400)) AS "NAME", CAST(NULL AS INTEGER) AS "COUNT", CAST(NULL AS FLOAT) AS "SPACE", CAST(0 AS INTEGER) AS "TAG"
    FROM RDB$DATABASE
    INTO "NAME", "COUNT", "SPACE", "TAG";
    SUSPEND;

    FOR SELECT "NAME", "COUNT", "SPACE", "TAG"
        FROM LIC_DATA_07_1(:I$PROPERTYID, :I$RIGHTDOC, :I$BUILDINGCODE, 20000)
        INTO "NAME", "COUNT", "SPACE", "TAG"
    DO
        SUSPEND;
    FOR SELECT "NAME", "COUNT", "SPACE", "TAG"
        FROM LIC_DATA_07_3(:I$PROPERTYID, :I$RIGHTDOC, :I$BUILDINGCODE, 20100, :I$USER_ID)
        INTO "NAME", "COUNT", "SPACE", "TAG"
    DO
        SUSPEND;
    FOR SELECT "NAME", "COUNT", "SPACE", "TAG"
        FROM LIC_DATA_07_3(:I$PROPERTYID, :I$RIGHTDOC, :I$BUILDINGCODE, 20200, :I$USER_ID)
        INTO "NAME", "COUNT", "SPACE", "TAG"
    DO
        SUSPEND;
    FOR SELECT "NAME", "COUNT", "SPACE", "TAG"
        FROM LIC_DATA_07_3(:I$PROPERTYID, :I$RIGHTDOC, :I$BUILDINGCODE, 20300, :I$USER_ID)
        INTO "NAME", "COUNT", "SPACE", "TAG"
    DO
        SUSPEND;
    FOR SELECT "NAME", "COUNT", "SPACE", "TAG"
        FROM LIC_DATA_07_3(:I$PROPERTYID, :I$RIGHTDOC, :I$BUILDINGCODE, 20400, :I$USER_ID)
        INTO "NAME", "COUNT", "SPACE", "TAG"
    DO
        SUSPEND;
    FOR SELECT "NAME", "COUNT", "SPACE", "TAG"
        FROM LIC_DATA_07_3(:I$PROPERTYID, :I$RIGHTDOC, :I$BUILDINGCODE, 20500, :I$USER_ID)
        INTO "NAME", "COUNT", "SPACE", "TAG"
    DO
        SUSPEND;
    SELECT CAST(NULL AS VARCHAR(400)) AS "NAME", CAST(NULL AS INTEGER) AS "COUNT", CAST(NULL AS FLOAT) AS "SPACE", CAST(0 AS INTEGER) AS "TAG"
    FROM RDB$DATABASE
    INTO "NAME", "COUNT", "SPACE", "TAG";
    SUSPEND;

    FOR SELECT "NAME", "COUNT", "SPACE", "TAG"
        FROM LIC_DATA_07_1(:I$PROPERTYID, :I$RIGHTDOC, :I$BUILDINGCODE, 30000)
        INTO "NAME", "COUNT", "SPACE", "TAG"
    DO
        SUSPEND;
    FOR SELECT "NAME", "COUNT", "SPACE", "TAG"
        FROM LIC_DATA_07_2(:I$PROPERTYID, :I$RIGHTDOC, :I$BUILDINGCODE, 31000, :I$USER_ID)
        INTO "NAME", "COUNT", "SPACE", "TAG"
    DO
        SUSPEND;
    SELECT CAST(NULL AS VARCHAR(400)) AS "NAME", CAST(NULL AS INTEGER) AS "COUNT", CAST(NULL AS FLOAT) AS "SPACE", CAST(0 AS INTEGER) AS "TAG"
    FROM RDB$DATABASE
    INTO "NAME", "COUNT", "SPACE", "TAG";
    SUSPEND;

    FOR SELECT "NAME", "COUNT", "SPACE", "TAG"
        FROM LIC_DATA_07_1(:I$PROPERTYID, :I$RIGHTDOC, :I$BUILDINGCODE, 40000)
        INTO "NAME", "COUNT", "SPACE", "TAG"
    DO
        SUSPEND;
    FOR SELECT "NAME", "COUNT", "SPACE", "TAG"
        FROM LIC_DATA_07_2(:I$PROPERTYID, :I$RIGHTDOC, :I$BUILDINGCODE, 41000, :I$USER_ID)
        INTO "NAME", "COUNT", "SPACE", "TAG"
    DO
        SUSPEND;
    SELECT CAST(NULL AS VARCHAR(400)) AS "NAME", CAST(NULL AS INTEGER) AS "COUNT", CAST(NULL AS FLOAT) AS "SPACE", CAST(0 AS INTEGER) AS "TAG"
    FROM RDB$DATABASE
    INTO "NAME", "COUNT", "SPACE", "TAG";
    SUSPEND;

    FOR SELECT "NAME", "COUNT", "SPACE", "TAG"
        FROM LIC_DATA_07_1(:I$PROPERTYID, :I$RIGHTDOC, :I$BUILDINGCODE, 50000)
        INTO "NAME", "COUNT", "SPACE", "TAG"
    DO
        SUSPEND;
    FOR SELECT "NAME", "COUNT", "SPACE", "TAG"
        FROM LIC_DATA_07_2(:I$PROPERTYID, :I$RIGHTDOC, :I$BUILDINGCODE, 51000, :I$USER_ID)
        INTO "NAME", "COUNT", "SPACE", "TAG"
    DO
        SUSPEND;
    SELECT CAST(NULL AS VARCHAR(400)) AS "NAME", CAST(NULL AS INTEGER) AS "COUNT", CAST(NULL AS FLOAT) AS "SPACE", CAST(0 AS INTEGER) AS "TAG"
    FROM RDB$DATABASE
    INTO "NAME", "COUNT", "SPACE", "TAG";
    SUSPEND;

    FOR SELECT "NAME", "COUNT", "SPACE", "TAG"
        FROM LIC_DATA_07_1(:I$PROPERTYID, :I$RIGHTDOC, :I$BUILDINGCODE, 60000)
        INTO "NAME", "COUNT", "SPACE", "TAG"
    DO
        SUSPEND;
    FOR SELECT "NAME", "COUNT", "SPACE", "TAG"
        FROM LIC_DATA_07_2(:I$PROPERTYID, :I$RIGHTDOC, :I$BUILDINGCODE, 61000, :I$USER_ID)
        INTO "NAME", "COUNT", "SPACE", "TAG"
    DO
        SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIC_DATA_07_1 (
    I$PROPERTYID BIGINT,
    I$RIGHTDOC BIGINT,
    I$BUILDINGCODE BIGINT,
    I$ID INTEGER)
RETURNS (
    NAME VARCHAR(400),
    "COUNT" INTEGER,
    SPACE FLOAT,
    TAG INTEGER)
AS
BEGIN
    SELECT CAST((SELECT UPPER(R.VAL)
                 FROM LISTVALS T

                 JOIN RES R
                 ON R.RES_ID = T.RES_ID
                 AND R.LANG_CODE = 'RU'

                 WHERE T.COST = :I$ID
                 AND T.LIST_ID = 20) AS VARCHAR(400)) AS "NAME", CAST((SELECT COUNT(L61.OBJ_ID)
                                                                         FROM LINKS L61
                                                                         JOIN VALL VL ON VL.OBJ_ID = L61.OBJ_ID AND VL.PARAM_ID = 527 AND VL.LISTVAL_ID = :I$PROPERTYID
                                                                         JOIN VALR VR ON VR.OBJ_ID = L61.OBJ_ID AND VR.PARAM_ID = 528 AND VR.VAL = :I$RIGHTDOC
                                                                         JOIN VALL VLL ON VLL.OBJ_ID = L61.OBJ_ID AND VLL.PARAM_ID = 526 AND VLL.LISTVAL_ID IN (SELECT LV.LISTVAL_ID
                                                                                                                                                                FROM LISTVALS LV
                                                                                                                                                                WHERE LV.COST BETWEEN :I$ID AND :I$ID + 10000)
                                                                         WHERE L61.OBJ_TYPE_ID = 61
                                                                           AND L61.DATE_DEL IS NULL
                                                                           AND L61.PARENT_ID = :I$BUILDINGCODE) AS INTEGER) AS "COUNT", CAST((SELECT SUM(VF.VAL)
                                                                                                                                              FROM LINKS L61
                                                                                                                                              JOIN VALL VL ON VL.OBJ_ID = L61.OBJ_ID AND VL.PARAM_ID = 527 AND VL.LISTVAL_ID = :I$PROPERTYID
                                                                                                                                              JOIN VALR VR ON VR.OBJ_ID = L61.OBJ_ID AND VR.PARAM_ID = 528 AND VR.VAL = :I$RIGHTDOC
                                                                                                                                              JOIN VALL VLL ON VLL.OBJ_ID = L61.OBJ_ID AND VLL.PARAM_ID = 526 AND VLL.LISTVAL_ID IN (SELECT LV.LISTVAL_ID
                                                                                                                                                                                                                                     FROM LISTVALS LV
                                                                                                                                                                                                                                     WHERE LV.COST BETWEEN :I$ID AND :I$ID + 10000)
                                                                                                                                              JOIN VALF VF ON VF.OBJ_ID = L61.OBJ_ID AND VF.PARAM_ID = 533
                                                                                                                                              WHERE L61.OBJ_TYPE_ID = 61
                                                                                                                                                AND L61.DATE_DEL IS NULL
                                                                                                                                                AND L61.PARENT_ID = :I$BUILDINGCODE) AS FLOAT) AS "SPACE",
           CAST(1 AS INTEGER) AS "TAG"
    FROM RDB$DATABASE
    INTO "NAME", "COUNT", "SPACE", "TAG";
    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIC_DATA_07_2 (
    I$PROPERTYID BIGINT,
    I$RIGHTDOC BIGINT,
    I$BUILDINGCODE BIGINT,
    I$ID INTEGER,
    I$USER_ID BIGINT)
RETURNS (
    NAME VARCHAR(400),
    "COUNT" INTEGER,
    SPACE FLOAT,
    TAG INTEGER)
AS
declare variable LANG_CODE varchar(2);
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :LANG_CODE;

    IF (I$ID < 30000) THEN
        FOR SELECT CAST(NULL AS VARCHAR(400)) AS "NAME", CAST(NULL AS INTEGER) AS "COUNT", CAST(NULL AS FLOAT) AS "SPACE", CAST(2 AS INTEGER) AS "TAG"
            FROM RDB$DATABASE
            UNION ALL
            SELECT CAST('          ' || R.VAL AS VARCHAR(400)) AS "NAME", CAST(COUNT(R.VAL) AS INTEGER) AS "COUNT", CAST(SUM(VF.VAL) AS FLOAT) AS "SPACE",
                   CAST(3 AS INTEGER) AS "TAG"
            FROM LINKS L61
            JOIN VALL VL ON VL.OBJ_ID = L61.OBJ_ID AND VL.PARAM_ID = 527 AND VL.LISTVAL_ID = :I$PROPERTYID
            JOIN VALR VR ON VR.OBJ_ID = L61.OBJ_ID AND VR.PARAM_ID = 528 AND VR.VAL = :I$RIGHTDOC
            JOIN VALL VLL ON VLL.OBJ_ID = L61.OBJ_ID AND VLL.PARAM_ID = 526 AND VLL.LISTVAL_ID IN (SELECT LV.LISTVAL_ID
                                                                                                   FROM LISTVALS LV
                                                                                                   WHERE LV.COST BETWEEN :I$ID AND :I$ID + 1000)
            JOIN LISTVALS LS ON LS.LISTVAL_ID = VLL.LISTVAL_ID
            LEFT JOIN RES_GET(LS.RES_ID,  :LANG_CODE) R ON 1=1
            JOIN VALF VF ON VF.OBJ_ID = L61.OBJ_ID AND VF.PARAM_ID = 533
            WHERE L61.OBJ_TYPE_ID = 61
              AND L61.DATE_DEL IS NULL
              AND L61.PARENT_ID = :I$BUILDINGCODE
            GROUP BY R.VAL
            INTO "NAME", "COUNT", "SPACE", "TAG"
        DO
            SUSPEND;
    ELSE
        FOR SELECT CAST('          ' || R.VAL AS VARCHAR(400)) AS "NAME", CAST(COUNT(R.VAL) AS INTEGER) AS "COUNT", CAST(SUM(VF.VAL) AS FLOAT) AS "SPACE",
                   CAST(4 AS INTEGER) AS "TAG"
            FROM LINKS L61
            JOIN VALL VL ON VL.OBJ_ID = L61.OBJ_ID AND VL.PARAM_ID = 527 AND VL.LISTVAL_ID = :I$PROPERTYID
            JOIN VALR VR ON VR.OBJ_ID = L61.OBJ_ID AND VR.PARAM_ID = 528 AND VR.VAL = :I$RIGHTDOC
            JOIN VALL VLL ON VLL.OBJ_ID = L61.OBJ_ID AND VLL.PARAM_ID = 526 AND VLL.LISTVAL_ID IN (SELECT LV.LISTVAL_ID
                                                                                                   FROM LISTVALS LV
                                                                                                   WHERE LV.COST BETWEEN :I$ID AND :I$ID + 1000)
            JOIN LISTVALS LS ON LS.LISTVAL_ID = VLL.LISTVAL_ID
            LEFT JOIN RES_GET(LS.RES_ID,  :LANG_CODE) R ON 1=1
            JOIN VALF VF ON VF.OBJ_ID = L61.OBJ_ID AND VF.PARAM_ID = 533
            WHERE L61.OBJ_TYPE_ID = 61
              AND L61.DATE_DEL IS NULL
              AND L61.PARENT_ID = :I$BUILDINGCODE
            GROUP BY R.VAL
            INTO "NAME", "COUNT", "SPACE", "TAG"
        DO
            SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIC_DATA_07_3 (
    I$PROPERTYID BIGINT,
    I$RIGHTDOC BIGINT,
    I$BUILDINGCODE BIGINT,
    I$ID INTEGER,
    I$USER_ID BIGINT)
RETURNS (
    NAME VARCHAR(400),
    "COUNT" INTEGER,
    SPACE FLOAT,
    TAG INTEGER)
AS
declare variable LANG_CODE varchar(2);
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :LANG_CODE;

    FOR SELECT CAST((SELECT R.VAL
                     FROM LISTVALS T

                     JOIN RES R
                     ON R.RES_ID = T.RES_ID
                     AND R.LANG_CODE = 'RU'

                     WHERE T.COST = :I$ID
                       AND T.LIST_ID = 20) AS VARCHAR(400)) AS "NAME", CAST(NULL AS INTEGER) AS "COUNT", CAST(NULL AS FLOAT) AS "SPACE", CAST(5 AS INTEGER) AS "TAG"
        FROM RDB$DATABASE
        UNION ALL
        SELECT CAST('          ' || R.VAL AS VARCHAR(50)) AS "NAME", CAST(COUNT(R.VAL) AS INTEGER) AS "COUNT", CAST(SUM(VF.VAL) AS FLOAT) AS "SPACE",
               CAST(6 AS INTEGER) AS "TAG"
        FROM LINKS L61
        JOIN VALL VL ON VL.OBJ_ID = L61.OBJ_ID AND VL.PARAM_ID = 527 AND VL.LISTVAL_ID = :I$PROPERTYID
        JOIN VALR VR ON VR.OBJ_ID = L61.OBJ_ID AND VR.PARAM_ID = 528 AND VR.VAL = :I$RIGHTDOC
        JOIN VALL VLL ON VLL.OBJ_ID = L61.OBJ_ID AND VLL.PARAM_ID = 526 AND VLL.LISTVAL_ID IN (SELECT LV.LISTVAL_ID
                                                                                               FROM LISTVALS LV
                                                                                               WHERE LV.COST BETWEEN :I$ID AND :I$ID + 100)
        JOIN LISTVALS LS ON LS.LISTVAL_ID = VLL.LISTVAL_ID
        LEFT JOIN RES_GET(LS.RES_ID,  :LANG_CODE) R ON 1=1
        JOIN VALF VF ON VF.OBJ_ID = L61.OBJ_ID AND VF.PARAM_ID = 533
        WHERE L61.OBJ_TYPE_ID = 61
          AND L61.DATE_DEL IS NULL
          AND L61.PARENT_ID = :I$BUILDINGCODE
        GROUP BY R.VAL
        INTO "NAME", "COUNT", "SPACE", "TAG"
    DO
        SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIC_DATA_07_4 (
    I$OBJ_ID BIGINT)
RETURNS (
    VAL INTEGER)
AS
declare variable V$OBJ_ID bigint;
declare variable V$TEMP integer;
begin
 VAL = 0;
 for select l61.OBJ_ID from LINKS l73
 join LINKS l16 on l16.PARENT_ID = l73.OBJ_ID and l16.OBJ_TYPE_ID = 16 and l16.DATE_DEL is null
 join LINKS l61 on l61.PARENT_ID = l16.OBJ_ID and l61.OBJ_TYPE_ID = 61 and l61.DATE_DEL is null
 where l73.obj_type_id = 73 and l73.date_del is null and l73.parent_id = :I$OBJ_ID
 into V$OBJ_ID do
  begin
   select count(*) from VALL vl where vl.OBJ_ID = :V$OBJ_ID and
   vl.PARAM_ID = 526 into V$TEMP;
   if (:V$TEMP = 0) then VAL = :VAL + 1;
   select count(*) from VALL vl where vl.OBJ_ID = :V$OBJ_ID and
   vl.PARAM_ID = 527 into V$TEMP;
   if (:V$TEMP = 0) then VAL = :VAL + 1;
   select count(*) from VALf vl where vl.OBJ_ID = :V$OBJ_ID and
   vl.PARAM_ID = 533 into V$TEMP;
   if (:V$TEMP = 0) then VAL = :VAL + 1;
   end
  suspend;
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIC_DATA_07_5 (
    I$SCHOOL BIGINT)
RETURNS (
    BUILDINGCODE BIGINT,
    PROPERTYNAME VARCHAR(1000),
    PROPERTYID BIGINT,
    S_RIGHT_DOC BIGINT,
    S_SOBSTVENNIK VARCHAR(1000),
    S_REKVIZIT__PRAVOMOCHN_K VARCHAR(1000),
    S_REKVIZIT__PRAVOMOCHN_DO VARCHAR(1000),
    S_REKVIZIT__DOKYUMENTOV_ VARCHAR(1000),
    S_REKVIZIT__GOSPOZHNADZR VARCHAR(1000))
AS
BEGIN
    FOR SELECT L16.OBJ_ID
        FROM LINKS L73
        JOIN LINKS L16 ON L16.PARENT_ID = L73.OBJ_ID
        WHERE L16.OBJ_TYPE_ID = 16
          AND L16.DATE_DEL IS NULL
          AND L73.OBJ_TYPE_ID = 73
          AND L73.DATE_DEL IS NULL
          AND L73.PARENT_ID = :I$SCHOOL
        INTO :BUILDINGCODE
    DO
    BEGIN
        SELECT V
        FROM VAL_GET(:BUILDINGCODE, 504)
        INTO :PROPERTYNAME;

        SELECT FIRST 1 VL.LISTVAL_ID
        FROM VALL VL
        WHERE VL.PARAM_ID = 504
          AND VL.OBJ_ID = :BUILDINGCODE
          AND VL.IS_DEL = 0
        INTO :PROPERTYID;

        SELECT FIRST 1 VR.VAL
        FROM VALR VR
        WHERE VR.OBJ_ID = :BUILDINGCODE
          AND VR.PARAM_ID = 505
          AND VR.IS_DEL = 0
        INTO :S_RIGHT_DOC;

        SELECT V
        FROM VAL_GET(:BUILDINGCODE, 542)
        INTO S_SOBSTVENNIK;

        SELECT V
        FROM VAL_GET(:BUILDINGCODE, 505)
        INTO S_REKVIZIT__PRAVOMOCHN_K;

        SELECT V
        FROM VAL_GET(:BUILDINGCODE, 483)
        INTO S_REKVIZIT__PRAVOMOCHN_DO;

        SELECT V
        FROM VAL_GET(:BUILDINGCODE, 506)
        INTO S_REKVIZIT__DOKYUMENTOV_;

        SELECT V
        FROM VAL_GET(:BUILDINGCODE, 507)
        INTO S_REKVIZIT__GOSPOZHNADZR;

        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIC_DATA_08 (
    I$SCHOOL BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    NAME VARCHAR(50),
    SPACE FLOAT,
    FORMA_VLADENIJA VARCHAR(250),
    S_REKVIZIT__PRAVOMOCHN_K VARCHAR(500),
    "ORDER" INTEGER,
    "GROUP" INTEGER)
AS
BEGIN
  FOR SELECT *
      FROM LIC_DATA_08_1(20100, :I$SCHOOL, 1057, :I$USER_ID)
      UNION ALL
      SELECT *
      FROM LIC_DATA_08_1(20200, :I$SCHOOL, 1059, :I$USER_ID)
      UNION ALL
      SELECT *
      FROM LIC_DATA_08_1(20300, :I$SCHOOL, 1, :I$USER_ID)
      UNION ALL
      SELECT *
      FROM LIC_DATA_08_1(20400, :I$SCHOOL, 1, :I$USER_ID)
      UNION ALL
      SELECT *
      FROM LIC_DATA_08_1(20500, :I$SCHOOL, 1, :I$USER_ID)
      UNION ALL
      SELECT *
      FROM LIC_DATA_08_1(10200, :I$SCHOOL, 1, :I$USER_ID)
      UNION ALL
      SELECT *
      FROM LIC_DATA_08_1(10300, :I$SCHOOL, 1, :I$USER_ID)
      ORDER BY 6, 5, 1
      INTO "NAME", "SPACE", "FORMA_VLADENIJA", "S_REKVIZIT__PRAVOMOCHN_K", "ORDER", "GROUP"
  DO
    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIC_DATA_08_1 (
    I$ID INTEGER,
    I$SCHOOL BIGINT,
    I$RIGHTDOC BIGINT = 1,
    I$USER_ID BIGINT = 1)
RETURNS (
    NAME VARCHAR(50),
    SPACE FLOAT,
    FORMA_VLADENIJA VARCHAR(250),
    S_REKVIZIT__PRAVOMOCHN_K VARCHAR(500),
    "ORDER" INTEGER,
    "GROUP" INTEGER)
AS
declare variable LANG_CODE varchar(2);
begin
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :LANG_CODE;

    FOR
        SELECT CAST ((SELECT UPPER(R.VAL)
                      FROM LISTVALS T
                      LEFT JOIN RES_GET(T.RES_ID,  :LANG_CODE) R ON 1=1
                      WHERE T.COST = :I$ID
                      AND T.LIST_ID = 20
               ) AS VARCHAR(50)) AS "NAME",
               CAST (NULL AS FLOAT) AS "SPACE", CAST (NULL AS VARCHAR(50)) AS "FORMA_VLADENIJA",
               CAST ((SELECT (SELECT CAPTION FROM OBJECT_CAPTION_GET(L17.OBJ_ID,NULL,NULL,:I$USER_ID))
                      FROM LINKS L17
                
                      JOIN VALL VL
                      ON VL.OBJ_ID = L17.OBJ_ID
                      AND VL.PARAM_ID = 471
                      AND VL.LISTVAL_ID = :I$RIGHTDOC
                
                      WHERE L17.OBJ_TYPE_ID = 17
                      AND L17.DATE_DEL IS NULL
                      AND L17.PARENT_ID = :I$SCHOOL) AS VARCHAR(250)
               ) AS "S_REKVIZIT__PRAVOMOCHN_K",
               CAST (0 AS INTEGER) AS "ORDER",
               CAST (:I$ID AS INTEGER) AS "GROUP"
        FROM RDB$DATABASE
        UNION ALL
        SELECT CAST ('          '|| LS.VAL AS VARCHAR(50)) AS "NAME",
               CAST ((VF.VAL) AS FLOAT) AS "SPACE",
               (R.VAL) AS "FORMA_VLADENIJA",
               (SELECT V FROM VAL_GET(VR.VAL, 471, 0, :I$USER_ID)) AS "S_REKVIZIT__PRAVOMOCHN_K",
               CAST (1 AS INTEGER) AS "ORDER", CAST (:I$ID AS INTEGER) AS "GROUP"
        FROM LINKS L73

        JOIN LINKS L16
        ON L16.PARENT_ID = L73.OBJ_ID
        AND L16.OBJ_TYPE_ID = 16
        AND L16.DATE_DEL IS NULL

        JOIN LINKS L61
        ON L61.PARENT_ID = L16.OBJ_ID
        AND L61.OBJ_TYPE_ID = 61
        AND L61.DATE_DEL IS NULL

        JOIN VALL VL
        ON VL.OBJ_ID = L61.OBJ_ID
        AND VL.PARAM_ID = 527

        JOIN LISTVALS LSS
        ON LSS.LISTVAL_ID = VL.LISTVAL_ID

        LEFT JOIN RES_GET(LSS.RES_ID,  :LANG_CODE) R ON 1=1

        JOIN VALR VR
        ON VR.OBJ_ID = L61.OBJ_ID
        AND VR.PARAM_ID = 528

        JOIN VALL VLL
        ON VLL.OBJ_ID = L61.OBJ_ID
        AND VLL.PARAM_ID = 526
        AND VLL.LISTVAL_ID IN (SELECT LV.LISTVAL_ID FROM LISTVALS LV WHERE LV.COST BETWEEN :I$ID AND :I$ID+100)

        JOIN VALS LS
        ON LS.OBJ_ID= L61.OBJ_ID
        AND LS.PARAM_ID = 408

        JOIN VALF VF
        ON VF.OBJ_ID = L61.OBJ_ID
        AND VF.PARAM_ID = 533 

        WHERE L73.OBJ_TYPE_ID = 73
        AND L73.DATE_DEL IS NULL
        AND L73.PARENT_ID = :I$SCHOOL

        INTO "NAME",
             "SPACE",
             "FORMA_VLADENIJA",
             "S_REKVIZIT__PRAVOMOCHN_K",
             "ORDER",
             "GROUP"
    DO
    BEGIN
        SUSPEND;
    END
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIC_DATA_10 (
    I$SCHOOL BIGINT)
RETURNS (
    SKIPNUM INTEGER,
    NAME VARCHAR(110),
    "TYPE" VARCHAR(50),
    "COUNT" INTEGER,
    TAG INTEGER,
    ID INTEGER)
AS
declare variable V$SUBJNAME varchar(200);
declare variable V$SubjID bigint;
begin
  for select  cast (1 as integer) as "SKIPNUM",
  cast ((select (select upper(Caption) from OBJECT_CAPTION_GET(l74.obj_ID)) from
  LINKS l74 where l74.OBJ_TYPE_ID = 74 and l74.date_del is null and
  l74.PARENT_ID = :I$SCHOOL)  as varchar(110)) as "NAME",
  cast (null as varchar(50)) as "TYPE",
  cast (null as integer) as "COUNT",
  cast (0 as integer) as "TAG",
  cast (21 as integer) as "ID"
from
  rdb$database
 union all
select
  cast (0 as integer) as "SKIPNUM",
  cast ('     '||vs.VAL as varchar(110)) as "NAME",
  cast (null as varchar(50)) as "TYPE",
  cast (VI.VAL as integer) as "COUNT",
  cast (1 as integer) as "TAG",
  cast (21 as integer) as "ID"
from
  LINKS l74
   join LINKS l94 on l94.PARENT_ID = l74.OBJ_ID and l94.OBJ_TYPE_ID = 94 and l94.DATE_DEL is null
  join vals vs on vs.OBJ_ID = l94.OBJ_ID and vs.PARAM_ID = 601
  join VALI VI on vI.OBJ_ID = l94.OBJ_ID and vi.PARAM_ID = 603
  where l74.OBJ_TYPE_ID = 74 and l74.date_del is null and
  l74.PARENT_ID = :I$School
  union all
  select  cast (1 as integer) as "SKIPNUM",
  cast ((select (select upper(Caption) from OBJECT_CAPTION_GET(l23.obj_ID)) from
  LINKS l23 where l23.OBJ_TYPE_ID = 23 and l23.date_del is null and
  l23.PARENT_ID = :I$SCHOOL)  as varchar(110)) as "NAME",
  cast (null as varchar(50)) as "TYPE",
  cast (null as integer) as "COUNT",
  cast (0 as integer) as "TAG",
  cast (22 as integer) as "ID"
from
  rdb$database
 union all
select
  cast (0 as integer) as "SKIPNUM",
  cast ('     '||vs.VAL as varchar(110)) as "NAME",
  cast (null as varchar(50)) as "TYPE",
  cast (VI.VAL as integer) as "COUNT",
  cast (1 as integer) as "TAG",
  cast (22 as integer) as "ID"
from
  LINKS l23
   join LINKS l95 on l95.PARENT_ID = l23.OBJ_ID and l95.OBJ_TYPE_ID = 95 and l95.DATE_DEL is null
  join vals vs on vs.OBJ_ID = l95.OBJ_ID and vs.PARAM_ID = 627
  join VALI VI on vI.OBJ_ID = l95.OBJ_ID and vi.PARAM_ID = 605
  where l23.OBJ_TYPE_ID = 23 and l23.date_del is null and
  l23.PARENT_ID = :I$School
  union all
select
  cast (1 as integer) as "SKIPNUM",
  cast ('МАТЕРИАЛЬНЫЕ РЕСУРСЫ ПО ПРЕДМЕТАМ' as varchar(110)) as "NAME",
  cast (null as varchar(50)) as "TYPE",
  cast (null as integer) as "COUNT",
  cast (4 as integer) as "TAG",
  cast (100000 as integer) as "ID"
from
  rdb$database
   order by 6,5,2  into "SKIPNUM", "NAME", "TYPE", "COUNT", "TAG", "ID"  do
      suspend;

   for select distinct vr.VAL as SUBJECTID, vs.VAL as SUBJECTNAME
    from LINKS l104
    join LINKS l106 on l106.PARENT_ID = l104.OBJ_ID and l106.OBJ_TYPE_ID = 106 and l106.DATE_DEL is null
    join VALR vr on vr.OBJ_ID = l106.OBJ_ID and vr.PARAM_ID = 644
    join VALS vs on vs.PARAM_ID = 376 and vs.OBJ_ID = vr.VAL
    where l104.obj_type_id = 104 and l104.date_del is null and l104.parent_id = :I$School
    union
    select distinct vr.VAL as SUBJECTID, vs.VAL as SUBJECTNAME
    from LINKS l105
    join LINKS l107 on l107.PARENT_ID = l105.OBJ_ID and l107.OBJ_TYPE_ID = 107 and l107.DATE_DEL is null
    join VALR vr on vr.OBJ_ID = l107.OBJ_ID and vr.PARAM_ID = 654
    join VALS vs on vs.PARAM_ID = 376 and vs.OBJ_ID = vr.VAL
    where l105.obj_type_id = 105 and l105.date_del is null and l105.parent_id =  :I$School
order by 2 into V$SUBJID, V$SUBJNAME do
   begin
     for select * from LIC_DATA_10_1(:I$SCHOOL, :V$SUBJID, :V$SUBJNAME, 100000 + :V$SUBJID)
     order by 6,5,2  into "SKIPNUM", "NAME", "TYPE", "COUNT", "TAG", "ID"  do
     suspend;
   end

  for select
   cast (1 as integer) as "SKIPNUM",
   cast ('ПРОЧИЕ РЕСУРСЫ (МЕТАПРЕДМЕТ)' as varchar(110)) as "NAME",
   cast (null as varchar(50)) as "TYPE",
   cast (null as integer) as "COUNT",
   cast (5 as integer) as "TAG",
   cast (999999 as integer) as "ID"
  from
   rdb$database
  union all
  select
   cast (0 as integer) as "SKIPNUM",
   cast ('     '||vs.VAL as varchar(110)) as "NAME",
   cast ((select V from VAL_GET(l108.OBJ_ID, 655)) as varchar(50)) as "TYPE",
   cast (VI.VAL as integer) as "COUNT",
   cast (6 as integer) as "TAG",
   cast (999999 as integer) as "ID"
  from
   LINKS l108
   join LINKS l109 on l109.PARENT_ID = l108.OBJ_ID and l109.OBJ_TYPE_ID = 109 and l109.DATE_DEL is null
   join vals vs on vs.OBJ_ID = l109.OBJ_ID and vs.PARAM_ID = 656
   join VALI VI on vI.OBJ_ID = l109.OBJ_ID and vi.PARAM_ID = 657
   where l108.OBJ_TYPE_ID = 108 and l108.date_del is null and
   l108.PARENT_ID = :I$SCHOOL
  order by 6,5,2  into "SKIPNUM", "NAME", "TYPE", "COUNT", "TAG", "ID"  do
      suspend;
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIC_DATA_10_1 (
    I$SCHOOL BIGINT,
    I$SUBJID BIGINT,
    I$SUBJNAME VARCHAR(200),
    I$ID INTEGER)
RETURNS (
    SKIPNUM INTEGER,
    NAME VARCHAR(110),
    "TYPE" VARCHAR(50),
    "COUNT" INTEGER,
    TAG INTEGER,
    ID INTEGER)
AS
begin
  for select
  cast (2 as integer) as "SKIPNUM",
  cast (:I$SUBJNAME as varchar(110)) as "NAME",
  cast (null as varchar(50)) as "TYPE",
  cast (null as integer) as "COUNT",
  cast (2 as integer) as "TAG",
  cast (:I$ID as integer) as "ID"
from
  rdb$database
union all
select
  cast (0 as integer) as "SKIPNUM",
  cast ('     '||vs.VAL as varchar(110)) as "NAME",
  cast ((select V from VAL_GET(l97.OBJ_ID, 645)) as varchar(50)) as "TYPE",
  cast (VI.VAL as integer) as "COUNT",
  cast (3 as integer) as "TAG",
  cast (:I$ID as integer) as "ID"
from
  LINKS l92
  join LINKS l97 on l97.PARENT_ID = l92.OBJ_ID and l97.OBJ_TYPE_ID = 97 and l97.DATE_DEL is null
  join vals vs on vs.OBJ_ID = l97.OBJ_ID and vs.PARAM_ID = 606
  join VALI VI on vI.OBJ_ID = l97.OBJ_ID and vI.PARAM_ID = 607
  join VALr Vr on vr.OBJ_ID = l97.OBJ_ID and vr.PARAM_ID = 643 and vr.VAL = :I$SUBJID
  where l92.OBJ_TYPE_ID = 92 and l92.date_del is null and
l92.PARENT_ID = :I$School
 union all
 select
  cast (0 as integer) as "SKIPNUM",
  cast ('     '||vs.VAL as varchar(110)) as "NAME",
  cast ((select V from VAL_GET(l106.OBJ_ID, 638)) as varchar(50)) as "TYPE",
  cast (VI.VAL as integer) as "COUNT",
  cast (3 as integer) as "TAG",
  cast (:I$ID as integer) as "ID"
from
  LINKS l104
  join LINKS l106 on l106.PARENT_ID = l104.OBJ_ID and l106.OBJ_TYPE_ID = 106 and l106.DATE_DEL is null
  join vals vs on vs.OBJ_ID = l106.OBJ_ID and vs.PARAM_ID = 639
  join VALI VI on vI.OBJ_ID = l106.OBJ_ID and vI.PARAM_ID = 640
  join VALr Vr on vr.OBJ_ID = l106.OBJ_ID and vr.PARAM_ID = 644 and vr.VAL = :I$SUBJID
  where l104.OBJ_TYPE_ID = 104 and l104.date_del is null and
l104.PARENT_ID = :I$School
 union all
 select
  cast (0 as integer) as "SKIPNUM",
  cast ('     '||vs.VAL as varchar(110)) as "NAME",
  cast ((select V from VAL_GET(l107.OBJ_ID, 646)) as varchar(50)) as "TYPE",
  cast (VI.VAL as integer) as "COUNT",
  cast (3 as integer) as "TAG",
  cast (:I$ID as integer) as "ID"
from
  LINKS l105
  join LINKS l107 on l107.PARENT_ID = l105.OBJ_ID and l107.OBJ_TYPE_ID = 107 and l107.DATE_DEL is null
  join vals vs on vs.OBJ_ID = l107.OBJ_ID and vs.PARAM_ID = 647
  join VALI VI on vI.OBJ_ID = l107.OBJ_ID and vI.PARAM_ID = 648
  join VALr Vr on vr.OBJ_ID = l107.OBJ_ID and vr.PARAM_ID = 654 and vr.VAL = :I$SUBJID
  where l105.OBJ_TYPE_ID = 105 and l105.date_del is null and
l105.PARENT_ID = :I$School
    into "SKIPNUM", "NAME", "TYPE", "COUNT", "TAG", "ID"  do
      suspend;
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIC_DATA_APP12 (
    SCHOOL BIGINT)
RETURNS (
    C1 INTEGER,
    PRI_ORDER INTEGER,
    S_DOLZHNOST_ VARCHAR(1000),
    S_DOLZHNOST VARCHAR(1000),
    WORKPLACE VARCHAR(1000),
    FIO VARCHAR(1000),
    EDUCATION VARCHAR(1000),
    SUBJECTNAME VARCHAR(1000),
    EDUC_PLACE VARCHAR(1000),
    CATEGORY VARCHAR(1000),
    STEPEN VARCHAR(1000),
    FULLSTAGE INTEGER,
    STATE VARCHAR(1000),
    PERSONCODE BIGINT)
AS
declare variable SCHOOLPROGID bigint;
declare variable PROGNAME varchar(1000);
BEGIN
    C1 = 0;
    FOR SELECT SCHOOLPROGID, PROGNAME
        FROM LIC_DATA_GET_PROGS(:SCHOOL)
        INTO :SCHOOLPROGID, :PROGNAME --, :PROGGOALNAME
    DO
    BEGIN
        C1 = C1 + 1;
        SUBJECTNAME = PROGNAME;
        PRI_ORDER = NULL;
        S_DOLZHNOST_ = NULL;
        S_DOLZHNOST = NULL;
        WORKPLACE = NULL;
        FIO = NULL;
        EDUCATION = NULL;
        WORKPLACE = NULL;
        EDUC_PLACE = NULL;
        CATEGORY = NULL;
        STEPEN = NULL;
        FULLSTAGE = NULL;
        STATE = NULL;
        PERSONCODE = NULL;
        SUSPEND;
        FOR SELECT DISTINCT CAST(1 AS INTEGER) AS "PRI_ORDER", LSL.SUBJECTNAME, L57.PARENT_ID
            FROM LIB_SUBJECT_LIST LSL
            JOIN LINKS L57 ON L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL AND L57.OBJ_ID = :SCHOOLPROGID
            JOIN LINKS L14 ON L14.OBJ_ID = LSL.SUBJECTCODE
            WHERE L14.PARENT_TYPE_ID = 14
              AND L14.DATE_DEL IS NULL
              AND L57.PARENT_ID = L14.PARENT_ID
            GROUP BY LSL.SUBJECTNAME, L57.PARENT_ID
            INTO :PRI_ORDER, :SUBJECTNAME, :PERSONCODE
        DO
        BEGIN
            SELECT C1
            FROM BUILD_REP_FIO(:PERSONCODE, 59, 60, 61, 0)
            INTO FIO;
            SELECT FIRST 1(SELECT V
                           FROM VAL_GET(L13.PARENT_ID, 58)) AS C1,
                           (SELECT V
                            FROM VAL_GET(L15.OBJ_ID, 587)) AS C2
            FROM LINKS L15
            JOIN LINKS L13 ON L15.OBJ_ID = L13.OBJ_ID AND L13.PARENT_TYPE_ID = 13 AND L13.DATE_DEL IS NULL
            WHERE L15.OBJ_TYPE_ID = 15
              AND L15.DATE_DEL IS NULL
              AND L15.PARENT_ID = :PERSONCODE
            INTO S_DOLZHNOST, :STATE;
            SELECT FIRST 1(SELECT V
                           FROM VAL_GET(L33.OBJ_ID, 285)) AS C1,
                           (SELECT V
                            FROM VAL_GET(L33.OBJ_ID, 284)) AS C2
            FROM LINKS L33
            WHERE L33.OBJ_TYPE_ID = 33
              AND L33.DATE_DEL IS NULL
              AND L33.PARENT_ID = :PERSONCODE
            INTO EDUC_PLACE, EDUCATION;
            SELECT V
            FROM VAL_GET(:PERSONCODE, 279)
            INTO :STEPEN;

            -- Квалификационная категория
            SELECT VAL FROM VACANCY_GET_CAT(:PERSONCODE) INTO :CATEGORY;

            SELECT SUM(DAYS360_COUNT) / 360
            FROM PARAGRAF_EMPLOYEE_SENIORITY_LST(:PERSONCODE)
            WHERE SENIORITY_TYPE = 942
            INTO FULLSTAGE;

            SELECT V
            FROM VAL_GET(:SCHOOL, 2)
            INTO :WORKPLACE;
            S_DOLZHNOST_ = :S_DOLZHNOST;
            SUSPEND;
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIC_DATA_APP33 (
    SCHOOL BIGINT)
RETURNS (
    C1 INTEGER,
    C2 VARCHAR(1000),
    C3 VARCHAR(4000),
    C5 VARCHAR(1000),
    BUILDINGADDRESS VARCHAR(1000),
    C6 VARCHAR(1000))
AS
declare variable SCHOOLPROGID bigint;
declare variable PROGNAME varchar(1000);
declare variable ROOMID bigint;
declare variable SUBJID integer;
declare variable PROOMID bigint;
declare variable T3 varchar(1000);
BEGIN
    C1 = 0;
    FOR SELECT SCHOOLPROGID, PROGNAME
        FROM LIC_DATA_GET_PROGS(:SCHOOL)
        WHERE ORDERID = 1
          AND ORDERID2 IN (2, 3)
        INTO :SCHOOLPROGID, :PROGNAME
    DO
    BEGIN
        C1 = C1 + 1;
        C2 = PROGNAME;
        C3 = NULL;
        BUILDINGADDRESS = NULL;
        C5 = NULL;
        C6 = NULL;
        PROOMID = 0;
        SUSPEND;
        FOR SELECT L57.PARENT_ID, L51.OBJ_ID, VS.VAL AS SUBJNAME, VS1.VAL || ' - ' || VS2.VAL AS C3,
                   (SELECT VAL
                    FROM ADR_GET(420, L61.PARENT_ID)) AS BUILDINGADDRESS
            FROM LINKS L57
            LEFT JOIN LINKS L51 ON (L57.PARENT_ID = L51.PARENT_ID AND L51.OBJ_TYPE_ID = 51 AND L51.DATE_DEL IS NULL)
            JOIN LINKS L61 ON (L61.OBJ_ID = L57.PARENT_ID AND L61.OBJ_TYPE_ID = 61 AND L61.DATE_DEL IS NULL)
            LEFT JOIN VALS VS ON (VS.OBJ_ID = L51.OBJ_ID AND VS.IS_DEL = 0 AND VS.PARAM_ID = 376)
            LEFT JOIN VALS VS1 ON (VS1.OBJ_ID = L57.PARENT_ID AND VS1.IS_DEL = 0 AND VS1.PARAM_ID = 408)
            LEFT JOIN VALS VS2 ON (VS2.OBJ_ID = L57.PARENT_ID AND VS2.IS_DEL = 0 AND VS2.PARAM_ID = 407)
            WHERE L57.PARENT_TYPE_ID = 61
              AND L57.DATE_DEL IS NULL
              AND L57.OBJ_ID = :SCHOOLPROGID
            INTO :ROOMID, :SUBJID, :C2, :C3, :BUILDINGADDRESS
        DO
        BEGIN
            IF (ROOMID != PROOMID) THEN
            BEGIN
                PROOMID = ROOMID;
                SELECT V
                FROM VAL_GET(:ROOMID, 527)
                INTO C5;
                SELECT V
                FROM VAL_GET(:ROOMID, 528)
                INTO C6;
                SUSPEND;
            END
            C3 = '';
            FOR SELECT (SELECT V
                        FROM VAL_GET(L97.OBJ_ID, 606)) || ' (' || CAST((SELECT V
                                                                        FROM VAL_GET(L97.OBJ_ID, 607)) AS VARCHAR(3)) || ' шт.) ' AS MC
                FROM LINKS L97
                JOIN VALR VR ON (L97.OBJ_ID = VR.OBJ_ID AND VR.IS_DEL = 0)
                WHERE L97.PARENT_TYPE_ID = 92
                  AND VAL = :SUBJID
                INTO :T3
            DO
            BEGIN
                C3 = :C3 || '' || :T3;
            END
            IF (:C3 <> '') THEN
            BEGIN
                C2 = NULL;
                BUILDINGADDRESS = NULL;
                C5 = NULL;
                C6 = NULL;
                SUSPEND;
            END
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIC_DATA_APP6 (
    SCHOOL BIGINT)
RETURNS (
    L1A INTEGER,
    L1B DOUBLE PRECISION,
    L11A INTEGER,
    L11B DOUBLE PRECISION,
    L21 INTEGER,
    L22 INTEGER,
    L23 INTEGER,
    L24 INTEGER,
    L25 INTEGER,
    L26 INTEGER,
    L27 INTEGER,
    L28 INTEGER,
    L29 INTEGER,
    L210 INTEGER,
    L211 INTEGER,
    L212 INTEGER,
    L13A INTEGER,
    L14A INTEGER,
    L13B DOUBLE PRECISION,
    L14B DOUBLE PRECISION)
AS
declare variable T double precision;
BEGIN
  SELECT COUNT(DISTINCT TEACHER_ID) AS VAL1
  FROM PARAGRAF_GRADE_TEACHERS_LIST(:SCHOOL)
  INTO :L1A;

  SELECT SUM(VF.VAL) AS VAL2
  FROM PARAGRAF_GRADE_TEACHERS_LIST(:SCHOOL)
  JOIN LINKS L15 ON L15.PARENT_ID = TEACHER_ID AND L15.DATE_DEL IS NULL AND L15.OBJ_TYPE_ID = 15
  JOIN VALF VF ON VF.PARAM_ID = 71 AND VF.OBJ_ID = L15.OBJ_ID AND VF.VAL > 0
  INTO :L1B;

  SELECT COUNT(DISTINCT TEACHER_ID) AS VAL2
  FROM PARAGRAF_GRADE_TEACHERS_LIST(:SCHOOL)
  JOIN LINKS L15 ON L15.PARENT_ID = TEACHER_ID AND L15.DATE_DEL IS NULL AND L15.OBJ_TYPE_ID = 15
  JOIN VALL VL ON VL.PARAM_ID = 587 AND VL.OBJ_ID = L15.OBJ_ID AND VL.LISTVAL_ID = 207
  INTO :L11A;

  SELECT SUM(VF.VAL) AS VAL2
  FROM PARAGRAF_GRADE_TEACHERS_LIST(:SCHOOL)
  JOIN LINKS L15 ON L15.PARENT_ID = TEACHER_ID AND L15.DATE_DEL IS NULL AND L15.OBJ_TYPE_ID = 15
  JOIN VALL VL ON VL.PARAM_ID = 587 AND VL.OBJ_ID = L15.OBJ_ID AND VL.LISTVAL_ID = 207
  JOIN VALF VF ON VF.PARAM_ID = 71 AND VF.OBJ_ID = L15.OBJ_ID AND VF.VAL > 0
  INTO :L11B;
  -------- fuckin shit skipped ! -----
  SELECT COUNT(DISTINCT TEACHER_ID) AS VAL3
  FROM PARAGRAF_GRADE_TEACHERS_LIST(:SCHOOL)
  JOIN LINKS L15 ON L15.PARENT_ID = TEACHER_ID AND L15.DATE_DEL IS NULL AND L15.OBJ_TYPE_ID = 15
  JOIN VALL VL ON VL.PARAM_ID = 587 AND VL.OBJ_ID = L15.OBJ_ID AND VL.LISTVAL_ID = 208
  INTO :L13A;

  SELECT SUM(VF.VAL) AS VAL2
  FROM PARAGRAF_GRADE_TEACHERS_LIST(:SCHOOL)
  JOIN LINKS L15 ON L15.PARENT_ID = TEACHER_ID AND L15.DATE_DEL IS NULL AND L15.OBJ_TYPE_ID = 15
  JOIN VALL VL ON VL.PARAM_ID = 587 AND VL.OBJ_ID = L15.OBJ_ID AND VL.LISTVAL_ID = 208
  JOIN VALF VF ON VF.PARAM_ID = 71 AND VF.OBJ_ID = L15.OBJ_ID AND VF.VAL > 0
  INTO :L13B;

  SELECT COUNT(DISTINCT TEACHER_ID) AS VAL3
  FROM PARAGRAF_GRADE_TEACHERS_LIST(:SCHOOL)
  JOIN LINKS L15 ON L15.PARENT_ID = TEACHER_ID AND L15.DATE_DEL IS NULL AND L15.OBJ_TYPE_ID = 15
  JOIN VALL VL ON VL.PARAM_ID = 587 AND VL.OBJ_ID = L15.OBJ_ID AND VL.LISTVAL_ID = 209
  INTO :L14A;

  SELECT SUM(VF.VAL) AS VAL2
  FROM PARAGRAF_GRADE_TEACHERS_LIST(:SCHOOL)
  JOIN LINKS L15 ON L15.PARENT_ID = TEACHER_ID AND L15.DATE_DEL IS NULL AND L15.OBJ_TYPE_ID = 15
  JOIN VALL VL ON VL.PARAM_ID = 587 AND VL.OBJ_ID = L15.OBJ_ID AND VL.LISTVAL_ID = 209
  JOIN VALF VF ON VF.PARAM_ID = 71 AND VF.OBJ_ID = L15.OBJ_ID AND VF.VAL > 0
  INTO :L14B;

  SELECT COUNT(DISTINCT TEACHER_ID) AS VAL3
  FROM PARAGRAF_GRADE_TEACHERS_LIST(:SCHOOL)
  JOIN LINKS L14 ON L14.OBJ_ID = TEACHER_ID AND L14.DATE_DEL IS NULL AND L14.OBJ_TYPE_ID = 14
  JOIN VALL VL ON VL.PARAM_ID = 279 AND VL.OBJ_ID = L14.OBJ_ID AND VL.LISTVAL_ID = 628
  INTO :L21;

  SELECT COUNT(DISTINCT TEACHER_ID) AS VAL3
  FROM PARAGRAF_GRADE_TEACHERS_LIST(:SCHOOL)
  JOIN LINKS L14 ON L14.OBJ_ID = TEACHER_ID AND L14.DATE_DEL IS NULL AND L14.OBJ_TYPE_ID = 14
  JOIN VALL VL ON VL.PARAM_ID = 279 AND VL.OBJ_ID = L14.OBJ_ID AND VL.LISTVAL_ID = 627
  INTO :L22;

  SELECT COUNT(DISTINCT TEACHER_ID) AS VAL3
  FROM PARAGRAF_GRADE_TEACHERS_LIST(:SCHOOL)
  JOIN LINKS L14 ON L14.OBJ_ID = TEACHER_ID AND L14.DATE_DEL IS NULL AND L14.OBJ_TYPE_ID = 14
  JOIN VALL VL ON VL.PARAM_ID = 279 AND VL.OBJ_ID = L14.OBJ_ID AND VL.LISTVAL_ID = 626
  JOIN VALL VL1 ON VL1.PARAM_ID = 280 AND VL1.OBJ_ID = L14.OBJ_ID AND VL1.LISTVAL_ID <> 629
  INTO :L23;

  SELECT COUNT(DISTINCT TEACHER_ID) AS VAL3
  FROM PARAGRAF_GRADE_TEACHERS_LIST(:SCHOOL)
  WHERE (SELECT SUM(DAYS360_COUNT)
         FROM PARAGRAF_EMPLOYEE_SENIORITY_LST(TEACHER_ID)
         WHERE SENIORITY_TYPE = 942) > 365
  INTO :L24;

  -- Учителя с высшей квалификационной категорией
  /*SELECT COUNT(DISTINCT TEACHER_ID) AS VAL3
  FROM PARAGRAF_GRADE_TEACHERS_LIST(:SCHOOL)
  JOIN LINKS L14 ON L14.OBJ_ID = TEACHER_ID AND L14.DATE_DEL IS NULL AND L14.OBJ_TYPE_ID = 14
  JOIN VALL VL ON VL.PARAM_ID = 281 AND VL.OBJ_ID = L14.OBJ_ID AND VL.LISTVAL_ID = 635
  INTO :L25;*/
  L25 = 0;

  -- Учителя с первой категорией
  /*SELECT COUNT(DISTINCT TEACHER_ID) AS VAL3
  FROM PARAGRAF_GRADE_TEACHERS_LIST(:SCHOOL)
  JOIN LINKS L14 ON L14.OBJ_ID = TEACHER_ID AND L14.DATE_DEL IS NULL AND L14.OBJ_TYPE_ID = 14
  JOIN VALL VL ON VL.PARAM_ID = 281 AND VL.OBJ_ID = L14.OBJ_ID AND VL.LISTVAL_ID = 634
  INTO :L26;*/
  L26 = 0;

  -- Учителя со второй категорией
  /*SELECT COUNT(DISTINCT TEACHER_ID) AS VAL3
  FROM PARAGRAF_GRADE_TEACHERS_LIST(:SCHOOL)
  JOIN LINKS L14 ON L14.OBJ_ID = TEACHER_ID AND L14.DATE_DEL IS NULL AND L14.OBJ_TYPE_ID = 14
  JOIN VALL VL ON VL.PARAM_ID = 281 AND VL.OBJ_ID = L14.OBJ_ID AND VL.LISTVAL_ID = 633
  INTO :L27;*/
  L27 = 0;

  SELECT COUNT(DISTINCT TEACHER_ID) AS VAL3
  FROM PARAGRAF_GRADE_TEACHERS_LIST(:SCHOOL)
  JOIN LINKS L14 ON L14.OBJ_ID = TEACHER_ID AND L14.DATE_DEL IS NULL AND L14.OBJ_TYPE_ID = 14
  JOIN VALL VL ON VL.PARAM_ID = 278 AND VL.OBJ_ID = L14.OBJ_ID AND VL.LISTVAL_ID = 620
  INTO :L28;

  SELECT COUNT(DISTINCT TEACHER_ID) AS VAL3
  FROM PARAGRAF_GRADE_TEACHERS_LIST(:SCHOOL)
  JOIN LINKS L14 ON L14.OBJ_ID = TEACHER_ID AND L14.DATE_DEL IS NULL AND L14.OBJ_TYPE_ID = 14
  JOIN VALL VL ON VL.PARAM_ID = 278 AND VL.OBJ_ID = L14.OBJ_ID AND VL.LISTVAL_ID IN (622, 621)
  INTO :L29;

  SELECT COUNT(DISTINCT TEACHER_ID) AS VAL3
  FROM PARAGRAF_GRADE_TEACHERS_LIST(:SCHOOL)
  JOIN LINKS L14 ON L14.OBJ_ID = TEACHER_ID AND L14.DATE_DEL IS NULL AND L14.OBJ_TYPE_ID = 14
  JOIN VALL VL ON VL.PARAM_ID = 278 AND VL.OBJ_ID = L14.OBJ_ID AND VL.LISTVAL_ID = 624
  INTO :L210;

  SELECT COUNT(DISTINCT TEACHER_ID) AS VAL3
  FROM PARAGRAF_GRADE_TEACHERS_LIST(:SCHOOL)
  JOIN LINKS L14 ON L14.OBJ_ID = TEACHER_ID AND L14.DATE_DEL IS NULL AND L14.OBJ_TYPE_ID = 14
  JOIN VALL VL ON VL.PARAM_ID = 278 AND VL.OBJ_ID = L14.OBJ_ID AND VL.LISTVAL_ID IN (622, 624)
  JOIN LINKS L15 ON L15.PARENT_ID = TEACHER_ID AND L15.DATE_DEL IS NULL AND L15.OBJ_TYPE_ID = 15
  JOIN VALR VR ON VR.PARAM_ID = 69 AND VR.OBJ_ID = L15.OBJ_ID
  JOIN VALL VL2 ON VL2.PARAM_ID = 58 AND VL2.OBJ_ID = VR.VAL AND VL2.LISTVAL_ID = 130
  INTO :L211;
  L29 = L29 - L211;
  L210 = L210 - L211;
  SELECT COUNT(DISTINCT TEACHER_ID) AS VAL3
  FROM PARAGRAF_GRADE_TEACHERS_LIST(:SCHOOL)
  JOIN LINKS L14 ON L14.OBJ_ID = TEACHER_ID AND L14.DATE_DEL IS NULL AND L14.OBJ_TYPE_ID = 14
  JOIN VALL VL ON VL.PARAM_ID = 278 AND VL.OBJ_ID = L14.OBJ_ID AND VL.LISTVAL_ID = 623
  INTO :L212;
  SUSPEND;/**/
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIC_DATA_APP7 (
    SCHOOL BIGINT)
RETURNS (
    NAME VARCHAR(100),
    "COUNT" INTEGER,
    SPACE FLOAT,
    PROPERTYNAME VARCHAR(250),
    S_SOBSTVENNIK VARCHAR(250),
    BUILDINGCODE INTEGER,
    S_REKVIZIT__PRAVOMOCHN_K VARCHAR(250),
    TAG VARCHAR(10))
AS
BEGIN
/*
    SELECT CAST('Помещения для работы медицинских работников' AS VARCHAR(100)) AS "NAME",
           CAST(NULL AS INTEGER) AS "COUNT", CAST(NULL AS FLOAT) AS "SPACE",
           CAST(NULL AS VARCHAR(250)) AS "PROPERTYNAME", CAST(NULL AS VARCHAR(250)) AS "S_SOBSTVENNIK",
           CAST(NULL AS INTEGER) AS "BUILDINGCODE", CAST(NULL AS VARCHAR(250)) AS "S_REKVIZIT__PRAVOMOCHN_K",
           CAST('1.' AS VARCHAR(10)) AS "TAG"
    FROM RDB$DATABASE
    INTO NAME, "COUNT", SPACE, PROPERTYNAME, S_SOBSTVENNIK, BUILDINGCODE, S_REKVIZIT__PRAVOMOCHN_K, TAG;

    SELECT LV.VAL || ' ' || VS.VAL || ' Выдано с ' ||(SELECT V
                                                             FROM VAL_GET(L17.OBJ_ID, 482)) || ' до ' ||(SELECT V
                                                                                                           FROM VAL_GET(L17.OBJ_ID, 483)) AS NAME
    FROM LINKS L17
    JOIN VALL VL ON (L17.OBJ_ID = VL.OBJ_ID AND VL.IS_DEL = 0 AND VL.PARAM_ID = 471 AND VL.LISTVAL_ID = 1057)
    JOIN LISTVALS LV ON (LV.LISTVAL_ID = VL.LISTVAL_ID)
    JOIN VALS VS ON (VS.OBJ_ID = L17.OBJ_ID AND VS.IS_DEL = 0 AND VS.PARAM_ID = 481)
    WHERE L17.OBJ_TYPE_ID = 17
      AND L17.DATE_DEL IS NULL
      AND L17.PARENT_ID = :SCHOOL
    INTO S_REKVIZIT__PRAVOMOCHN_K;

    SUSPEND;
    FOR SELECT CAST('          ' || VS.VAL AS VARCHAR(100)) AS "NAME", CAST(COUNT(L61.OBJ_ID) AS INTEGER) AS "COUNT",
               CAST(SUM(VF.VAL) AS FLOAT) AS "SPACE", CAST(LV.VAL AS VARCHAR(250)) AS "PROPERTYNAME", CAST((SELECT V
                                                                                                            FROM VAL_GET(L61.PARENT_ID, 542)) AS VARCHAR(250)) AS "S_SOBSTVENNIK",
               CAST(L61.PARENT_ID AS INTEGER) AS "BUILDINGCODE", CAST((SELECT V
                                                                       FROM VAL_GET(L61.PARENT_ID, 505)) AS VARCHAR(250)) AS "S_REKVIZIT__PRAVOMOCHN_K",
               CAST(NULL AS VARCHAR(10)) AS "TAG"
        FROM LINKS L73
        JOIN LINKS L16 ON (L73.OBJ_ID = L16.PARENT_ID AND L16.OBJ_TYPE_ID = 16 AND L16.DATE_DEL IS NULL)
        JOIN LINKS L61 ON L61.PARENT_ID = L16.OBJ_ID AND L61.OBJ_TYPE_ID = 61 AND L61.DATE_DEL IS NULL
        JOIN VALL VL ON (VL.OBJ_ID = L61.OBJ_ID AND VL.IS_DEL = 0 AND VL.PARAM_ID = 526 AND VL.LISTVAL_ID BETWEEN 1150 AND 1154)
        JOIN VALS VS ON (VS.OBJ_ID = L61.OBJ_ID AND VS.IS_DEL = 0 AND VS.PARAM_ID = 408)
        LEFT JOIN VALF VF ON (VF.OBJ_ID = L61.OBJ_ID AND VF.IS_DEL = 0 AND VF.PARAM_ID = 533)
        LEFT JOIN LISTVALS LV ON (LV.LISTVAL_ID = (SELECT LISTVAL_ID
                                                   FROM VALL
                                                   WHERE OBJ_ID = L61.OBJ_ID
                                                     AND IS_DEL = 0
                                                     AND PARAM_ID = 527))
        WHERE L73.OBJ_TYPE_ID = 73
          AND L73.DATE_DEL IS NULL
          AND L73.PARENT_ID = :SCHOOL
        GROUP BY VS.VAL, LV.VAL, L61.PARENT_ID, "S_SOBSTVENNIK"
        INTO NAME, "COUNT", SPACE, PROPERTYNAME, S_SOBSTVENNIK, BUILDINGCODE, S_REKVIZIT__PRAVOMOCHN_K, TAG
    DO
    BEGIN
        SUSPEND;
    END
    SELECT CAST('Помещения для питания обучающихся, воспитанников и работников' AS VARCHAR(100)) AS "NAME",
           CAST(NULL AS INTEGER) AS "COUNT", CAST(NULL AS FLOAT) AS "SPACE",
           CAST(NULL AS VARCHAR(250)) AS "PROPERTYNAME", CAST(NULL AS VARCHAR(250)) AS "S_SOBSTVENNIK",
           CAST(NULL AS INTEGER) AS "BUILDINGCODE", CAST(NULL AS VARCHAR(250)) AS "S_REKVIZIT__PRAVOMOCHN_K",
           CAST('2.' AS VARCHAR(10)) AS "TAG"
    FROM RDB$DATABASE
    INTO NAME, "COUNT", SPACE, PROPERTYNAME, S_SOBSTVENNIK, BUILDINGCODE, S_REKVIZIT__PRAVOMOCHN_K, TAG;

    SELECT LV.VAL || ' ' || VS.VAL || ' Выдано с ' ||(SELECT V
                                                             FROM VAL_GET(L17.OBJ_ID, 482)) || ' до ' ||(SELECT V
                                                                                                           FROM VAL_GET(L17.OBJ_ID, 483)) AS NAME
    FROM LINKS L17
    JOIN VALL VL ON (L17.OBJ_ID = VL.OBJ_ID AND VL.IS_DEL = 0 AND VL.PARAM_ID = 471 AND VL.LISTVAL_ID = 1057) --1059
    JOIN LISTVALS LV ON (LV.LISTVAL_ID = VL.LISTVAL_ID)
    JOIN VALS VS ON (VS.OBJ_ID = L17.OBJ_ID AND VS.IS_DEL = 0 AND VS.PARAM_ID = 481)
    WHERE L17.OBJ_TYPE_ID = 17
      AND L17.DATE_DEL IS NULL
      AND L17.PARENT_ID = :SCHOOL
    INTO S_REKVIZIT__PRAVOMOCHN_K;
    SUSPEND;
    FOR SELECT CAST('          ' || VS.VAL AS VARCHAR(100)) AS "NAME", CAST(COUNT(L61.OBJ_ID) AS INTEGER) AS "COUNT",
               CAST(SUM(VF.VAL) AS FLOAT) AS "SPACE", CAST(LV.VAL AS VARCHAR(250)) AS "PROPERTYNAME", CAST((SELECT V
                                                                                                            FROM VAL_GET(L61.PARENT_ID, 542)) AS VARCHAR(250)) AS "S_SOBSTVENNIK",
               CAST(L61.PARENT_ID AS INTEGER) AS "BUILDINGCODE", CAST((SELECT V
                                                                       FROM VAL_GET(L61.PARENT_ID, 505)) AS VARCHAR(250)) AS "S_REKVIZIT__PRAVOMOCHN_K",
               CAST(NULL AS VARCHAR(10)) AS "TAG"
        FROM LINKS L73
        JOIN LINKS L16 ON (L73.OBJ_ID = L16.PARENT_ID AND L16.OBJ_TYPE_ID = 16 AND L16.DATE_DEL IS NULL)
        JOIN LINKS L61 ON L61.PARENT_ID = L16.OBJ_ID AND L61.OBJ_TYPE_ID = 61 AND L61.DATE_DEL IS NULL
        JOIN VALL VL ON (VL.OBJ_ID = L61.OBJ_ID AND VL.IS_DEL = 0 AND VL.PARAM_ID = 526 AND VL.LISTVAL_ID BETWEEN 1154 AND 1159)
        JOIN VALS VS ON (VS.OBJ_ID = L61.OBJ_ID AND VS.IS_DEL = 0 AND VS.PARAM_ID = 408)
        LEFT JOIN VALF VF ON (VF.OBJ_ID = L61.OBJ_ID AND VF.IS_DEL = 0 AND VF.PARAM_ID = 533)
        LEFT JOIN LISTVALS LV ON (LV.LISTVAL_ID = (SELECT LISTVAL_ID
                                                   FROM VALL
                                                   WHERE OBJ_ID = L61.OBJ_ID
                                                     AND IS_DEL = 0
                                                     AND PARAM_ID = 527))
        WHERE L73.OBJ_TYPE_ID = 73
          AND L73.DATE_DEL IS NULL
          AND L73.PARENT_ID = :SCHOOL
        GROUP BY VS.VAL, LV.VAL, L61.PARENT_ID, "S_SOBSTVENNIK"
        INTO NAME, "COUNT", SPACE, PROPERTYNAME, S_SOBSTVENNIK, BUILDINGCODE, S_REKVIZIT__PRAVOMOCHN_K, TAG
    DO
    BEGIN
        SUSPEND;
    END
    SELECT CAST('Объекты хозяйственно-бытового и санитарно-гигиенического назначения' AS VARCHAR(100)) AS "NAME",
           CAST(NULL AS INTEGER) AS "COUNT", CAST(NULL AS FLOAT) AS "SPACE",
           CAST(NULL AS VARCHAR(250)) AS "PROPERTYNAME", CAST(NULL AS VARCHAR(250)) AS "S_SOBSTVENNIK",
           CAST(NULL AS INTEGER) AS "BUILDINGCODE", CAST(NULL AS VARCHAR(250)) AS "S_REKVIZIT__PRAVOMOCHN_K",
           CAST('3.' AS VARCHAR(10)) AS "TAG"
    FROM RDB$DATABASE
    INTO NAME, "COUNT", SPACE, PROPERTYNAME, S_SOBSTVENNIK, BUILDINGCODE, S_REKVIZIT__PRAVOMOCHN_K, TAG;
    SUSPEND;
    FOR SELECT CAST('          ' || VS.VAL AS VARCHAR(100)) AS "NAME", CAST(COUNT(L61.OBJ_ID) AS INTEGER) AS "COUNT",
               CAST(SUM(VF.VAL) AS FLOAT) AS "SPACE", CAST(LV.VAL AS VARCHAR(250)) AS "PROPERTYNAME", CAST((SELECT V
                                                                                                            FROM VAL_GET(L61.PARENT_ID, 542)) AS VARCHAR(250)) AS "S_SOBSTVENNIK",
               CAST(L61.PARENT_ID AS INTEGER) AS "BUILDINGCODE", CAST((SELECT V
                                                                       FROM VAL_GET(L61.PARENT_ID, 505)) AS VARCHAR(250)) AS "S_REKVIZIT__PRAVOMOCHN_K",
               CAST(NULL AS VARCHAR(10)) AS "TAG"
        FROM LINKS L73
        JOIN LINKS L16 ON (L73.OBJ_ID = L16.PARENT_ID AND L16.OBJ_TYPE_ID = 16 AND L16.DATE_DEL IS NULL)
        JOIN LINKS L61 ON L61.PARENT_ID = L16.OBJ_ID AND L61.OBJ_TYPE_ID = 61 AND L61.DATE_DEL IS NULL
        JOIN VALL VL ON (VL.OBJ_ID = L61.OBJ_ID AND VL.IS_DEL = 0 AND VL.PARAM_ID = 526 AND VL.LISTVAL_ID BETWEEN 1168 AND 1173)
        JOIN VALS VS ON (VS.OBJ_ID = L61.OBJ_ID AND VS.IS_DEL = 0 AND VS.PARAM_ID = 408)
        LEFT JOIN VALF VF ON (VF.OBJ_ID = L61.OBJ_ID AND VF.IS_DEL = 0 AND VF.PARAM_ID = 533)
        LEFT JOIN LISTVALS LV ON (LV.LISTVAL_ID = (SELECT LISTVAL_ID
                                                   FROM VALL
                                                   WHERE OBJ_ID = L61.OBJ_ID
                                                     AND IS_DEL = 0
                                                     AND PARAM_ID = 527))
        WHERE L73.OBJ_TYPE_ID = 73
          AND L73.DATE_DEL IS NULL
          AND L73.PARENT_ID = :SCHOOL
        GROUP BY VS.VAL, LV.VAL, L61.PARENT_ID, "S_SOBSTVENNIK"
        INTO NAME, "COUNT", SPACE, PROPERTYNAME, S_SOBSTVENNIK, BUILDINGCODE, S_REKVIZIT__PRAVOMOCHN_K, TAG
    DO
    BEGIN
        SUSPEND;
    END
    SELECT CAST('Помещения для круглосуточного пребывания, для сна и отдыха обучающихся, воспитанников, общежития' AS VARCHAR(100)) AS "NAME",
           CAST(NULL AS INTEGER) AS "COUNT", CAST(NULL AS FLOAT) AS "SPACE",
           CAST(NULL AS VARCHAR(250)) AS "PROPERTYNAME", CAST(NULL AS VARCHAR(250)) AS "S_SOBSTVENNIK",
           CAST(NULL AS INTEGER) AS "BUILDINGCODE", CAST(NULL AS VARCHAR(250)) AS "S_REKVIZIT__PRAVOMOCHN_K",
           CAST('4.' AS VARCHAR(10)) AS "TAG"
    FROM RDB$DATABASE
    INTO NAME, "COUNT", SPACE, PROPERTYNAME, S_SOBSTVENNIK, BUILDINGCODE, S_REKVIZIT__PRAVOMOCHN_K, TAG;
    SUSPEND;
    FOR SELECT CAST('          ' || VS.VAL AS VARCHAR(100)) AS "NAME", CAST(COUNT(L61.OBJ_ID) AS INTEGER) AS "COUNT",
               CAST(SUM(VF.VAL) AS FLOAT) AS "SPACE", CAST(LV.VAL AS VARCHAR(250)) AS "PROPERTYNAME", CAST((SELECT V
                                                                                                            FROM VAL_GET(L61.PARENT_ID, 542)) AS VARCHAR(250)) AS "S_SOBSTVENNIK",
               CAST(L61.PARENT_ID AS INTEGER) AS "BUILDINGCODE", CAST((SELECT V
                                                                       FROM VAL_GET(L61.PARENT_ID, 505)) AS VARCHAR(250)) AS "S_REKVIZIT__PRAVOMOCHN_K",
               CAST(NULL AS VARCHAR(10)) AS "TAG"
        FROM LINKS L73
        JOIN LINKS L16 ON (L73.OBJ_ID = L16.PARENT_ID AND L16.OBJ_TYPE_ID = 16 AND L16.DATE_DEL IS NULL)
        JOIN LINKS L61 ON L61.PARENT_ID = L16.OBJ_ID AND L61.OBJ_TYPE_ID = 61 AND L61.DATE_DEL IS NULL
        JOIN VALL VL ON (VL.OBJ_ID = L61.OBJ_ID AND VL.IS_DEL = 0 AND VL.PARAM_ID = 526 AND VL.LISTVAL_ID BETWEEN 1159 AND 1168)
        JOIN VALS VS ON (VS.OBJ_ID = L61.OBJ_ID AND VS.IS_DEL = 0 AND VS.PARAM_ID = 408)
        LEFT JOIN VALF VF ON (VF.OBJ_ID = L61.OBJ_ID AND VF.IS_DEL = 0 AND VF.PARAM_ID = 533)
        LEFT JOIN LISTVALS LV ON (LV.LISTVAL_ID = (SELECT LISTVAL_ID
                                                   FROM VALL
                                                   WHERE OBJ_ID = L61.OBJ_ID
                                                     AND IS_DEL = 0
                                                     AND PARAM_ID = 527))
        WHERE L73.OBJ_TYPE_ID = 73
          AND L73.DATE_DEL IS NULL
          AND L73.PARENT_ID = :SCHOOL
        GROUP BY VS.VAL, LV.VAL, L61.PARENT_ID, "S_SOBSTVENNIK"
        INTO NAME, "COUNT", SPACE, PROPERTYNAME, S_SOBSTVENNIK, BUILDINGCODE, S_REKVIZIT__PRAVOMOCHN_K, TAG
    DO
    BEGIN
        SUSPEND;
    END
    SELECT CAST('Объекты для проведения специальных коррекционных занятий' AS VARCHAR(100)) AS "NAME",
           CAST(NULL AS INTEGER) AS "COUNT", CAST(NULL AS FLOAT) AS "SPACE",
           CAST(NULL AS VARCHAR(250)) AS "PROPERTYNAME", CAST(NULL AS VARCHAR(250)) AS "S_SOBSTVENNIK",
           CAST(NULL AS INTEGER) AS "BUILDINGCODE", CAST(NULL AS VARCHAR(250)) AS "S_REKVIZIT__PRAVOMOCHN_K",
           CAST('5.' AS VARCHAR(10)) AS "TAG"
    FROM RDB$DATABASE
    INTO NAME, "COUNT", SPACE, PROPERTYNAME, S_SOBSTVENNIK, BUILDINGCODE, S_REKVIZIT__PRAVOMOCHN_K, TAG;
    SUSPEND;
    FOR SELECT CAST('          ' || VS.VAL AS VARCHAR(100)) AS "NAME", CAST(COUNT(L61.OBJ_ID) AS INTEGER) AS "COUNT",
               CAST(SUM(VF.VAL) AS FLOAT) AS "SPACE", CAST(LV.VAL AS VARCHAR(250)) AS "PROPERTYNAME", CAST((SELECT V
                                                                                                            FROM VAL_GET(L61.PARENT_ID, 542)) AS VARCHAR(250)) AS "S_SOBSTVENNIK",
               CAST(L61.PARENT_ID AS INTEGER) AS "BUILDINGCODE", CAST((SELECT V
                                                                       FROM VAL_GET(L61.PARENT_ID, 505)) AS VARCHAR(250)) AS "S_REKVIZIT__PRAVOMOCHN_K",
               CAST(NULL AS VARCHAR(10)) AS "TAG"
        FROM LINKS L73
        JOIN LINKS L16 ON (L73.OBJ_ID = L16.PARENT_ID AND L16.OBJ_TYPE_ID = 16 AND L16.DATE_DEL IS NULL)
        JOIN LINKS L61 ON L61.PARENT_ID = L16.OBJ_ID AND L61.OBJ_TYPE_ID = 61 AND L61.DATE_DEL IS NULL
        JOIN VALL VL ON (VL.OBJ_ID = L61.OBJ_ID AND VL.IS_DEL = 0 AND VL.PARAM_ID = 526 AND VL.LISTVAL_ID BETWEEN 1134 AND 1139)
        JOIN VALS VS ON (VS.OBJ_ID = L61.OBJ_ID AND VS.IS_DEL = 0 AND VS.PARAM_ID = 408)
        LEFT JOIN VALF VF ON (VF.OBJ_ID = L61.OBJ_ID AND VF.IS_DEL = 0 AND VF.PARAM_ID = 533)
        LEFT JOIN LISTVALS LV ON (LV.LISTVAL_ID = (SELECT LISTVAL_ID
                                                   FROM VALL
                                                   WHERE OBJ_ID = L61.OBJ_ID
                                                     AND IS_DEL = 0
                                                     AND PARAM_ID = 527))
        WHERE L73.OBJ_TYPE_ID = 73
          AND L73.DATE_DEL IS NULL
          AND L73.PARENT_ID = :SCHOOL
        GROUP BY VS.VAL, LV.VAL, L61.PARENT_ID, "S_SOBSTVENNIK"
        INTO NAME, "COUNT", SPACE, PROPERTYNAME, S_SOBSTVENNIK, BUILDINGCODE, S_REKVIZIT__PRAVOMOCHN_K, TAG
    DO
    BEGIN
        SUSPEND;
    END
    SELECT CAST('Объекты физической культуры и спорта' AS VARCHAR(100)) AS "NAME",
           CAST(NULL AS INTEGER) AS "COUNT", CAST(NULL AS FLOAT) AS "SPACE",
           CAST(NULL AS VARCHAR(250)) AS "PROPERTYNAME", CAST(NULL AS VARCHAR(250)) AS "S_SOBSTVENNIK",
           CAST(NULL AS INTEGER) AS "BUILDINGCODE", CAST(NULL AS VARCHAR(250)) AS "S_REKVIZIT__PRAVOMOCHN_K",
           CAST('6.' AS VARCHAR(10)) AS "TAG"
    FROM RDB$DATABASE
    INTO NAME, "COUNT", SPACE, PROPERTYNAME, S_SOBSTVENNIK, BUILDINGCODE, S_REKVIZIT__PRAVOMOCHN_K, TAG;
    SUSPEND;
    FOR SELECT CAST('          ' || VS.VAL AS VARCHAR(100)) AS "NAME", CAST(COUNT(L61.OBJ_ID) AS INTEGER) AS "COUNT",
               CAST(SUM(VF.VAL) AS FLOAT) AS "SPACE", CAST(LV.VAL AS VARCHAR(250)) AS "PROPERTYNAME", CAST((SELECT V
                                                                                                            FROM VAL_GET(L61.PARENT_ID, 542)) AS VARCHAR(250)) AS "S_SOBSTVENNIK",
               CAST(L61.PARENT_ID AS INTEGER) AS "BUILDINGCODE", CAST((SELECT V
                                                                       FROM VAL_GET(L61.PARENT_ID, 505)) AS VARCHAR(250)) AS "S_REKVIZIT__PRAVOMOCHN_K",
               CAST(NULL AS VARCHAR(10)) AS "TAG"
        FROM LINKS L73
        JOIN LINKS L16 ON (L73.OBJ_ID = L16.PARENT_ID AND L16.OBJ_TYPE_ID = 16 AND L16.DATE_DEL IS NULL)
        JOIN LINKS L61 ON L61.PARENT_ID = L16.OBJ_ID AND L61.OBJ_TYPE_ID = 61 AND L61.DATE_DEL IS NULL
        JOIN VALL VL ON (VL.OBJ_ID = L61.OBJ_ID AND VL.IS_DEL = 0 AND VL.PARAM_ID = 526 AND VL.LISTVAL_ID BETWEEN 1129 AND 1134)
        JOIN VALS VS ON (VS.OBJ_ID = L61.OBJ_ID AND VS.IS_DEL = 0 AND VS.PARAM_ID = 408)
        LEFT JOIN VALF VF ON (VF.OBJ_ID = L61.OBJ_ID AND VF.IS_DEL = 0 AND VF.PARAM_ID = 533)
        LEFT JOIN LISTVALS LV ON (LV.LISTVAL_ID = (SELECT LISTVAL_ID
                                                   FROM VALL
                                                   WHERE OBJ_ID = L61.OBJ_ID
                                                     AND IS_DEL = 0
                                                     AND PARAM_ID = 527))
        WHERE L73.OBJ_TYPE_ID = 73
          AND L73.DATE_DEL IS NULL
          AND L73.PARENT_ID = :SCHOOL
        GROUP BY VS.VAL, LV.VAL, L61.PARENT_ID, "S_SOBSTVENNIK"
        INTO NAME, "COUNT", SPACE, PROPERTYNAME, S_SOBSTVENNIK, BUILDINGCODE, S_REKVIZIT__PRAVOMOCHN_K, TAG
    DO
    BEGIN
        SUSPEND;
    END
    SELECT CAST('Иное (указать)' AS VARCHAR(100)) AS "NAME", CAST(NULL AS INTEGER) AS "COUNT",
           CAST(NULL AS FLOAT) AS "SPACE", CAST(NULL AS VARCHAR(250)) AS "PROPERTYNAME",
           CAST(NULL AS VARCHAR(250)) AS "S_SOBSTVENNIK", CAST(NULL AS INTEGER) AS "BUILDINGCODE",
           CAST(NULL AS VARCHAR(250)) AS "S_REKVIZIT__PRAVOMOCHN_K", CAST('7.' AS VARCHAR(10)) AS "TAG"
    FROM RDB$DATABASE
    INTO NAME, "COUNT", SPACE, PROPERTYNAME, S_SOBSTVENNIK, BUILDINGCODE, S_REKVIZIT__PRAVOMOCHN_K, TAG;
*/
    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIC_DATA_APP7_2 (
    I$SCHOOL BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    NAME VARCHAR(300),
    "COUNT" INTEGER,
    SPACE FLOAT,
    PROPERTYNAME VARCHAR(250),
    S_SOBSTVENNIK VARCHAR(250),
    BUILDINGCODE BIGINT,
    S_REKVIZIT__PRAVOMOCHN_K VARCHAR(500),
    TAG VARCHAR(10))
AS
declare variable LANG_CODE varchar(2);
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :LANG_CODE;

    SELECT CAST((SELECT RW.WORD
                 FROM REPORT_WORDS RW
                 WHERE RW.ID = 39) AS VARCHAR(100)) AS "NAME", CAST(NULL AS INTEGER) AS "COUNT", CAST(NULL AS FLOAT) AS "SPACE",
           CAST(NULL AS VARCHAR(250)) AS "PROPERTYNAME", CAST(NULL AS VARCHAR(250)) AS "S_SOBSTVENNIK", CAST(NULL AS INTEGER) AS "BUILDINGCODE",
           CAST(NULL AS VARCHAR(250)) AS "S_REKVIZIT__PRAVOMOCHN_K", CAST('1.' AS VARCHAR(10)) AS "TAG"
    FROM RDB$DATABASE
    INTO NAME, "COUNT", SPACE, PROPERTYNAME, S_SOBSTVENNIK, BUILDINGCODE, S_REKVIZIT__PRAVOMOCHN_K, TAG;

    SELECT FIRST 1 R.VAL || ' ' || VS.VAL || ' ' ||(SELECT RW.WORD
                                                     FROM REPORT_WORDS RW
                                                     WHERE RW.ID = 40) || '  ' ||(SELECT V
                                                                                  FROM VAL_GET(L17.OBJ_ID, 482)) || ' ' ||(SELECT RW.WORD
                                                                                                                           FROM REPORT_WORDS RW
                                                                                                                           WHERE RW.ID = 41) || '  ' ||(SELECT V
                                                                                                                                                        FROM VAL_GET(L17.OBJ_ID, 483)) AS NAME
    FROM LINKS L17
    JOIN VALL VL ON (L17.OBJ_ID = VL.OBJ_ID AND VL.IS_DEL = 0 AND VL.PARAM_ID = 471 AND VL.LISTVAL_ID = 1057)
    JOIN LISTVALS LV ON (LV.LISTVAL_ID = VL.LISTVAL_ID)
    LEFT JOIN RES_GET(LV.RES_ID,  :LANG_CODE) R ON 1=1
    JOIN VALS VS ON (VS.OBJ_ID = L17.OBJ_ID AND VS.IS_DEL = 0 AND VS.PARAM_ID = 481)
    WHERE L17.OBJ_TYPE_ID = 17
      AND L17.DATE_DEL IS NULL
      AND L17.PARENT_ID = :I$SCHOOL
    INTO S_REKVIZIT__PRAVOMOCHN_K;

    SUSPEND;

    FOR SELECT CAST('          ' || VS.VAL AS VARCHAR(100)) AS "NAME", CAST(COUNT(L61.OBJ_ID) AS INTEGER) AS "COUNT", CAST(SUM(VF.VAL) AS FLOAT) AS "SPACE",
               CAST(R.VAL AS VARCHAR(250)) AS "PROPERTYNAME", CAST((SELECT V
                                                                     FROM VAL_GET(L61.PARENT_ID, 542)) AS VARCHAR(250)) AS "S_SOBSTVENNIK",
               CAST(L61.PARENT_ID AS BIGINT) AS "BUILDINGCODE", CAST((SELECT V
                                                                      FROM VAL_GET(L61.PARENT_ID, 505)) AS VARCHAR(250)) AS "S_REKVIZIT__PRAVOMOCHN_K",
               CAST(NULL AS VARCHAR(10)) AS "TAG"
        FROM LINKS L73
        JOIN LINKS L16 ON (L73.OBJ_ID = L16.PARENT_ID AND L16.OBJ_TYPE_ID = 16 AND L16.DATE_DEL IS NULL)
        JOIN LINKS L61 ON L61.PARENT_ID = L16.OBJ_ID AND L61.OBJ_TYPE_ID = 61 AND L61.DATE_DEL IS NULL
        JOIN VALL VL ON (VL.OBJ_ID = L61.OBJ_ID AND VL.IS_DEL = 0 AND VL.PARAM_ID = 526 AND VL.LISTVAL_ID BETWEEN 1150 AND 1154)
        JOIN VALS VS ON (VS.OBJ_ID = L61.OBJ_ID AND VS.IS_DEL = 0 AND VS.PARAM_ID = 408)
        LEFT JOIN VALF VF ON (VF.OBJ_ID = L61.OBJ_ID AND VF.IS_DEL = 0 AND VF.PARAM_ID = 533)
        LEFT JOIN LISTVALS LV ON (LV.LISTVAL_ID = (SELECT LISTVAL_ID
                                                   FROM VALL
                                                   WHERE OBJ_ID = L61.OBJ_ID
                                                     AND IS_DEL = 0
                                                     AND PARAM_ID = 527))
        LEFT JOIN RES_GET(LV.RES_ID,  :LANG_CODE) R ON 1=1
        WHERE L73.OBJ_TYPE_ID = 73
          AND L73.DATE_DEL IS NULL
          AND L73.PARENT_ID = :I$SCHOOL
        GROUP BY VS.VAL, L61.PARENT_ID, R.VAL, "S_SOBSTVENNIK"
        INTO NAME, "COUNT", SPACE, PROPERTYNAME, S_SOBSTVENNIK, BUILDINGCODE, S_REKVIZIT__PRAVOMOCHN_K, TAG
    DO
    BEGIN
        SUSPEND;
    END

    SELECT CAST((SELECT RW.WORD
                 FROM REPORT_WORDS RW
                 WHERE RW.ID = 42) AS VARCHAR(100)) AS "NAME", CAST(NULL AS INTEGER) AS "COUNT", CAST(NULL AS FLOAT) AS "SPACE",
           CAST(NULL AS VARCHAR(250)) AS "PROPERTYNAME", CAST(NULL AS VARCHAR(250)) AS "S_SOBSTVENNIK", CAST(NULL AS INTEGER) AS "BUILDINGCODE",
           CAST(NULL AS VARCHAR(250)) AS "S_REKVIZIT__PRAVOMOCHN_K", CAST('2.' AS VARCHAR(10)) AS "TAG"
    FROM RDB$DATABASE
    INTO NAME, "COUNT", SPACE, PROPERTYNAME, S_SOBSTVENNIK, BUILDINGCODE, S_REKVIZIT__PRAVOMOCHN_K, TAG;

    SELECT FIRST 1 R.VAL || ' ' || VS.VAL || ' ' ||(SELECT RW.WORD
                                                     FROM REPORT_WORDS RW
                                                     WHERE RW.ID = 40) || '  ' ||(SELECT V
                                                                                  FROM VAL_GET(L17.OBJ_ID, 482)) || ' ' ||(SELECT RW.WORD
                                                                                                                           FROM REPORT_WORDS RW
                                                                                                                           WHERE RW.ID = 41) || '  ' ||(SELECT V
                                                                                                                                                        FROM VAL_GET(L17.OBJ_ID, 483)) AS NAME
    FROM LINKS L17
    JOIN VALL VL ON (L17.OBJ_ID = VL.OBJ_ID AND VL.IS_DEL = 0 AND VL.PARAM_ID = 471 AND VL.LISTVAL_ID = 1057) --1059
    JOIN LISTVALS LV ON (LV.LISTVAL_ID = VL.LISTVAL_ID)
    LEFT JOIN RES_GET(LV.RES_ID,  :LANG_CODE) R ON 1=1
    JOIN VALS VS ON (VS.OBJ_ID = L17.OBJ_ID AND VS.IS_DEL = 0 AND VS.PARAM_ID = 481)
    WHERE L17.OBJ_TYPE_ID = 17
      AND L17.DATE_DEL IS NULL
      AND L17.PARENT_ID = :I$SCHOOL
    INTO S_REKVIZIT__PRAVOMOCHN_K;

    SUSPEND;

    FOR SELECT CAST('          ' || VS.VAL AS VARCHAR(100)) AS "NAME", CAST(COUNT(L61.OBJ_ID) AS INTEGER) AS "COUNT", CAST(SUM(VF.VAL) AS FLOAT) AS "SPACE",
               CAST(R.VAL AS VARCHAR(250)) AS "PROPERTYNAME", CAST((SELECT V
                                                                     FROM VAL_GET(L61.PARENT_ID, 542)) AS VARCHAR(250)) AS "S_SOBSTVENNIK",
               CAST(L61.PARENT_ID AS BIGINT) AS "BUILDINGCODE", CAST((SELECT V
                                                                      FROM VAL_GET(L61.PARENT_ID, 505)) AS VARCHAR(250)) AS "S_REKVIZIT__PRAVOMOCHN_K",
               CAST(NULL AS VARCHAR(10)) AS "TAG"
        FROM LINKS L73
        JOIN LINKS L16 ON (L73.OBJ_ID = L16.PARENT_ID AND L16.OBJ_TYPE_ID = 16 AND L16.DATE_DEL IS NULL)
        JOIN LINKS L61 ON L61.PARENT_ID = L16.OBJ_ID AND L61.OBJ_TYPE_ID = 61 AND L61.DATE_DEL IS NULL
        JOIN VALL VL ON (VL.OBJ_ID = L61.OBJ_ID AND VL.IS_DEL = 0 AND VL.PARAM_ID = 526 AND VL.LISTVAL_ID BETWEEN 1154 AND 1159)
        JOIN VALS VS ON (VS.OBJ_ID = L61.OBJ_ID AND VS.IS_DEL = 0 AND VS.PARAM_ID = 408)
        LEFT JOIN VALF VF ON (VF.OBJ_ID = L61.OBJ_ID AND VF.IS_DEL = 0 AND VF.PARAM_ID = 533)
        LEFT JOIN LISTVALS LV ON (LV.LISTVAL_ID = (SELECT LISTVAL_ID
                                                   FROM VALL
                                                   WHERE OBJ_ID = L61.OBJ_ID
                                                     AND IS_DEL = 0
                                                     AND PARAM_ID = 527))
        LEFT JOIN RES_GET(LV.RES_ID,  :LANG_CODE) R ON 1=1
        WHERE L73.OBJ_TYPE_ID = 73
          AND L73.DATE_DEL IS NULL
          AND L73.PARENT_ID = :I$SCHOOL
        GROUP BY VS.VAL, L61.PARENT_ID, R.VAL, "S_SOBSTVENNIK"
        INTO NAME, "COUNT", SPACE, PROPERTYNAME, S_SOBSTVENNIK, BUILDINGCODE, S_REKVIZIT__PRAVOMOCHN_K, TAG
    DO
    BEGIN
        SUSPEND;
    END

    SELECT CAST((SELECT RW.WORD
                 FROM REPORT_WORDS RW
                 WHERE RW.ID = 43) AS VARCHAR(100)) AS "NAME", CAST(NULL AS INTEGER) AS "COUNT", CAST(NULL AS FLOAT) AS "SPACE",
           CAST(NULL AS VARCHAR(250)) AS "PROPERTYNAME", CAST(NULL AS VARCHAR(250)) AS "S_SOBSTVENNIK", CAST(NULL AS INTEGER) AS "BUILDINGCODE",
           CAST(NULL AS VARCHAR(250)) AS "S_REKVIZIT__PRAVOMOCHN_K", CAST('3.' AS VARCHAR(10)) AS "TAG"
    FROM RDB$DATABASE
    INTO NAME, "COUNT", SPACE, PROPERTYNAME, S_SOBSTVENNIK, BUILDINGCODE, S_REKVIZIT__PRAVOMOCHN_K, TAG;

    SUSPEND;

    FOR SELECT CAST('          ' || VS.VAL AS VARCHAR(100)) AS "NAME", CAST(COUNT(L61.OBJ_ID) AS INTEGER) AS "COUNT", CAST(SUM(VF.VAL) AS FLOAT) AS "SPACE",
               CAST(R.VAL AS VARCHAR(250)) AS "PROPERTYNAME", CAST((SELECT V
                                                                     FROM VAL_GET(L61.PARENT_ID, 542)) AS VARCHAR(250)) AS "S_SOBSTVENNIK",
               CAST(L61.PARENT_ID AS BIGINT) AS "BUILDINGCODE", CAST((SELECT V
                                                                      FROM VAL_GET(L61.PARENT_ID, 505)) AS VARCHAR(250)) AS "S_REKVIZIT__PRAVOMOCHN_K",
               CAST(NULL AS VARCHAR(10)) AS "TAG"
        FROM LINKS L73
        JOIN LINKS L16 ON (L73.OBJ_ID = L16.PARENT_ID AND L16.OBJ_TYPE_ID = 16 AND L16.DATE_DEL IS NULL)
        JOIN LINKS L61 ON L61.PARENT_ID = L16.OBJ_ID AND L61.OBJ_TYPE_ID = 61 AND L61.DATE_DEL IS NULL
        JOIN VALL VL ON (VL.OBJ_ID = L61.OBJ_ID AND VL.IS_DEL = 0 AND VL.PARAM_ID = 526 AND VL.LISTVAL_ID BETWEEN 1168 AND 1173)
        JOIN VALS VS ON (VS.OBJ_ID = L61.OBJ_ID AND VS.IS_DEL = 0 AND VS.PARAM_ID = 408)
        LEFT JOIN VALF VF ON (VF.OBJ_ID = L61.OBJ_ID AND VF.IS_DEL = 0 AND VF.PARAM_ID = 533)
        LEFT JOIN LISTVALS LV ON (LV.LISTVAL_ID = (SELECT LISTVAL_ID
                                                   FROM VALL
                                                   WHERE OBJ_ID = L61.OBJ_ID
                                                     AND IS_DEL = 0
                                                     AND PARAM_ID = 527))
        LEFT JOIN RES_GET(LV.RES_ID,  :LANG_CODE) R ON 1=1
        WHERE L73.OBJ_TYPE_ID = 73
          AND L73.DATE_DEL IS NULL
          AND L73.PARENT_ID = :I$SCHOOL
        GROUP BY VS.VAL, L61.PARENT_ID, R.VAL, "S_SOBSTVENNIK"
        INTO NAME, "COUNT", SPACE, PROPERTYNAME, S_SOBSTVENNIK, BUILDINGCODE, S_REKVIZIT__PRAVOMOCHN_K, TAG
    DO
    BEGIN
        SUSPEND;
    END

    SELECT CAST((SELECT RW.WORD
                 FROM REPORT_WORDS RW
                 WHERE RW.ID = 44) AS VARCHAR(300)) AS "NAME", CAST(NULL AS INTEGER) AS "COUNT", CAST(NULL AS FLOAT) AS "SPACE",
           CAST(NULL AS VARCHAR(250)) AS "PROPERTYNAME", CAST(NULL AS VARCHAR(250)) AS "S_SOBSTVENNIK", CAST(NULL AS INTEGER) AS "BUILDINGCODE",
           CAST(NULL AS VARCHAR(250)) AS "S_REKVIZIT__PRAVOMOCHN_K", CAST('4.' AS VARCHAR(10)) AS "TAG"
    FROM RDB$DATABASE
    INTO NAME, "COUNT", SPACE, PROPERTYNAME, S_SOBSTVENNIK, BUILDINGCODE, S_REKVIZIT__PRAVOMOCHN_K, TAG;

    SUSPEND;

    FOR SELECT CAST('          ' || VS.VAL AS VARCHAR(100)) AS "NAME", CAST(COUNT(L61.OBJ_ID) AS INTEGER) AS "COUNT", CAST(SUM(VF.VAL) AS FLOAT) AS "SPACE",
               CAST(R.VAL AS VARCHAR(250)) AS "PROPERTYNAME", CAST((SELECT V
                                                                     FROM VAL_GET(L61.PARENT_ID, 542)) AS VARCHAR(250)) AS "S_SOBSTVENNIK",
               CAST(L61.PARENT_ID AS BIGINT) AS "BUILDINGCODE", CAST((SELECT V
                                                                      FROM VAL_GET(L61.PARENT_ID, 505)) AS VARCHAR(250)) AS "S_REKVIZIT__PRAVOMOCHN_K",
               CAST(NULL AS VARCHAR(10)) AS "TAG"
        FROM LINKS L73
        JOIN LINKS L16 ON (L73.OBJ_ID = L16.PARENT_ID AND L16.OBJ_TYPE_ID = 16 AND L16.DATE_DEL IS NULL)
        JOIN LINKS L61 ON L61.PARENT_ID = L16.OBJ_ID AND L61.OBJ_TYPE_ID = 61 AND L61.DATE_DEL IS NULL
        JOIN VALL VL ON (VL.OBJ_ID = L61.OBJ_ID AND VL.IS_DEL = 0 AND VL.PARAM_ID = 526 AND VL.LISTVAL_ID BETWEEN 1159 AND 1168)
        JOIN VALS VS ON (VS.OBJ_ID = L61.OBJ_ID AND VS.IS_DEL = 0 AND VS.PARAM_ID = 408)
        LEFT JOIN VALF VF ON (VF.OBJ_ID = L61.OBJ_ID AND VF.IS_DEL = 0 AND VF.PARAM_ID = 533)
        LEFT JOIN LISTVALS LV ON (LV.LISTVAL_ID = (SELECT LISTVAL_ID
                                                   FROM VALL
                                                   WHERE OBJ_ID = L61.OBJ_ID
                                                     AND IS_DEL = 0
                                                     AND PARAM_ID = 527))
        LEFT JOIN RES_GET(LV.RES_ID,  :LANG_CODE) R ON 1=1
        WHERE L73.OBJ_TYPE_ID = 73
          AND L73.DATE_DEL IS NULL
          AND L73.PARENT_ID = :I$SCHOOL
        GROUP BY VS.VAL, L61.PARENT_ID, R.VAL, "S_SOBSTVENNIK"
        INTO NAME, "COUNT", SPACE, PROPERTYNAME, S_SOBSTVENNIK, BUILDINGCODE, S_REKVIZIT__PRAVOMOCHN_K, TAG
    DO
    BEGIN
        SUSPEND;
    END

    SELECT CAST((SELECT RW.WORD
                 FROM REPORT_WORDS RW
                 WHERE RW.ID = 45) AS VARCHAR(100)) AS "NAME", CAST(NULL AS INTEGER) AS "COUNT", CAST(NULL AS FLOAT) AS "SPACE",
           CAST(NULL AS VARCHAR(250)) AS "PROPERTYNAME", CAST(NULL AS VARCHAR(250)) AS "S_SOBSTVENNIK", CAST(NULL AS INTEGER) AS "BUILDINGCODE",
           CAST(NULL AS VARCHAR(250)) AS "S_REKVIZIT__PRAVOMOCHN_K", CAST('5.' AS VARCHAR(10)) AS "TAG"
    FROM RDB$DATABASE
    INTO NAME, "COUNT", SPACE, PROPERTYNAME, S_SOBSTVENNIK, BUILDINGCODE, S_REKVIZIT__PRAVOMOCHN_K, TAG;

    SUSPEND;

    FOR SELECT CAST('          ' || VS.VAL AS VARCHAR(100)) AS "NAME", CAST(COUNT(L61.OBJ_ID) AS INTEGER) AS "COUNT", CAST(SUM(VF.VAL) AS FLOAT) AS "SPACE",
               CAST(R.VAL AS VARCHAR(250)) AS "PROPERTYNAME", CAST((SELECT V
                                                                     FROM VAL_GET(L61.PARENT_ID, 542)) AS VARCHAR(250)) AS "S_SOBSTVENNIK",
               CAST(L61.PARENT_ID AS BIGINT) AS "BUILDINGCODE", CAST((SELECT V
                                                                      FROM VAL_GET(L61.PARENT_ID, 505)) AS VARCHAR(250)) AS "S_REKVIZIT__PRAVOMOCHN_K",
               CAST(NULL AS VARCHAR(10)) AS "TAG"
        FROM LINKS L73
        JOIN LINKS L16 ON (L73.OBJ_ID = L16.PARENT_ID AND L16.OBJ_TYPE_ID = 16 AND L16.DATE_DEL IS NULL)
        JOIN LINKS L61 ON L61.PARENT_ID = L16.OBJ_ID AND L61.OBJ_TYPE_ID = 61 AND L61.DATE_DEL IS NULL
        JOIN VALL VL ON (VL.OBJ_ID = L61.OBJ_ID AND VL.IS_DEL = 0 AND VL.PARAM_ID = 526 AND VL.LISTVAL_ID BETWEEN 1134 AND 1139)
        JOIN VALS VS ON (VS.OBJ_ID = L61.OBJ_ID AND VS.IS_DEL = 0 AND VS.PARAM_ID = 408)
        LEFT JOIN VALF VF ON (VF.OBJ_ID = L61.OBJ_ID AND VF.IS_DEL = 0 AND VF.PARAM_ID = 533)
        LEFT JOIN LISTVALS LV ON (LV.LISTVAL_ID = (SELECT LISTVAL_ID
                                                   FROM VALL
                                                   WHERE OBJ_ID = L61.OBJ_ID
                                                     AND IS_DEL = 0
                                                     AND PARAM_ID = 527))
        LEFT JOIN RES_GET(LV.RES_ID,  :LANG_CODE) R ON 1=1
        WHERE L73.OBJ_TYPE_ID = 73
          AND L73.DATE_DEL IS NULL
          AND L73.PARENT_ID = :I$SCHOOL
        GROUP BY VS.VAL, L61.PARENT_ID, R.VAL, "S_SOBSTVENNIK"
        INTO NAME, "COUNT", SPACE, PROPERTYNAME, S_SOBSTVENNIK, BUILDINGCODE, S_REKVIZIT__PRAVOMOCHN_K, TAG
    DO
    BEGIN
        SUSPEND;
    END

    SELECT CAST((SELECT RW.WORD
                 FROM REPORT_WORDS RW
                 WHERE RW.ID = 46) AS VARCHAR(100)) AS "NAME", CAST(NULL AS INTEGER) AS "COUNT", CAST(NULL AS FLOAT) AS "SPACE",
           CAST(NULL AS VARCHAR(250)) AS "PROPERTYNAME", CAST(NULL AS VARCHAR(250)) AS "S_SOBSTVENNIK", CAST(NULL AS INTEGER) AS "BUILDINGCODE",
           CAST(NULL AS VARCHAR(250)) AS "S_REKVIZIT__PRAVOMOCHN_K", CAST('6.' AS VARCHAR(10)) AS "TAG"
    FROM RDB$DATABASE
    INTO NAME, "COUNT", SPACE, PROPERTYNAME, S_SOBSTVENNIK, BUILDINGCODE, S_REKVIZIT__PRAVOMOCHN_K, TAG;

    SUSPEND;

    FOR SELECT CAST('          ' || VS.VAL AS VARCHAR(100)) AS "NAME", CAST(COUNT(L61.OBJ_ID) AS INTEGER) AS "COUNT", CAST(SUM(VF.VAL) AS FLOAT) AS "SPACE",
               CAST(R.VAL AS VARCHAR(250)) AS "PROPERTYNAME", CAST((SELECT V
                                                                     FROM VAL_GET(L61.PARENT_ID, 542)) AS VARCHAR(250)) AS "S_SOBSTVENNIK",
               CAST(L61.PARENT_ID AS BIGINT) AS "BUILDINGCODE", CAST((SELECT V
                                                                      FROM VAL_GET(L61.PARENT_ID, 505)) AS VARCHAR(250)) AS "S_REKVIZIT__PRAVOMOCHN_K",
               CAST(NULL AS VARCHAR(10)) AS "TAG"
        FROM LINKS L73
        JOIN LINKS L16 ON (L73.OBJ_ID = L16.PARENT_ID AND L16.OBJ_TYPE_ID = 16 AND L16.DATE_DEL IS NULL)
        JOIN LINKS L61 ON L61.PARENT_ID = L16.OBJ_ID AND L61.OBJ_TYPE_ID = 61 AND L61.DATE_DEL IS NULL
        JOIN VALL VL ON (VL.OBJ_ID = L61.OBJ_ID AND VL.IS_DEL = 0 AND VL.PARAM_ID = 526 AND VL.LISTVAL_ID BETWEEN 1129 AND 1134)
        JOIN VALS VS ON (VS.OBJ_ID = L61.OBJ_ID AND VS.IS_DEL = 0 AND VS.PARAM_ID = 408)
        LEFT JOIN VALF VF ON (VF.OBJ_ID = L61.OBJ_ID AND VF.IS_DEL = 0 AND VF.PARAM_ID = 533)
        LEFT JOIN LISTVALS LV ON (LV.LISTVAL_ID = (SELECT LISTVAL_ID
                                                   FROM VALL
                                                   WHERE OBJ_ID = L61.OBJ_ID
                                                     AND IS_DEL = 0
                                                     AND PARAM_ID = 527))
        LEFT JOIN RES_GET(LV.RES_ID,  :LANG_CODE) R ON 1=1
        WHERE L73.OBJ_TYPE_ID = 73
          AND L73.DATE_DEL IS NULL
          AND L73.PARENT_ID = :I$SCHOOL
        GROUP BY VS.VAL, L61.PARENT_ID, R.VAL, "S_SOBSTVENNIK"
        INTO NAME, "COUNT", SPACE, PROPERTYNAME, S_SOBSTVENNIK, BUILDINGCODE, S_REKVIZIT__PRAVOMOCHN_K, TAG
    DO
    BEGIN
        SUSPEND;
    END

    SELECT CAST((SELECT RW.WORD
                 FROM REPORT_WORDS RW
                 WHERE RW.ID = 47) AS VARCHAR(100)) AS "NAME", CAST(NULL AS INTEGER) AS "COUNT", CAST(NULL AS FLOAT) AS "SPACE",
           CAST(NULL AS VARCHAR(250)) AS "PROPERTYNAME", CAST(NULL AS VARCHAR(250)) AS "S_SOBSTVENNIK", CAST(NULL AS INTEGER) AS "BUILDINGCODE",
           CAST(NULL AS VARCHAR(250)) AS "S_REKVIZIT__PRAVOMOCHN_K", CAST('7.' AS VARCHAR(10)) AS "TAG"
    FROM RDB$DATABASE
    INTO NAME, "COUNT", SPACE, PROPERTYNAME, S_SOBSTVENNIK, BUILDINGCODE, S_REKVIZIT__PRAVOMOCHN_K, TAG;

    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIC_DATA_DOCOU (
    I$OBJ_ID BIGINT)
RETURNS (
    DOCSERIE VARCHAR(25),
    DOCNO VARCHAR(25),
    DOCDATE DATE,
    ORG VARCHAR(4000),
    GRN VARCHAR(25))
AS
DECLARE VARIABLE V$L17 bigint;
BEGIN
  FOR SELECT L17.OBJ_ID
      FROM LINKS L17
      JOIN VALL VL ON VL.OBJ_ID = L17.OBJ_ID AND VL.IS_DEL = 0 AND VL.PARAM_ID = 471 AND VL.LISTVAL_ID IN (1070, 1071)
      WHERE L17.OBJ_TYPE_ID = 17 AND
            L17.DATE_DEL IS NULL AND
            L17.PARENT_ID = :I$OBJ_ID
      ORDER BY VL.LISTVAL_ID DESC
      INTO :V$L17
  DO
  BEGIN
    SELECT V
    FROM VAL_GET(:V$L17, 479)
    INTO :DOCSERIE;
    SELECT V
    FROM VAL_GET(:V$L17, 480)
    INTO :DOCNO;
    SELECT D
    FROM VAL_GET(:V$L17, 482)
    INTO :DOCDATE;
    SELECT V
    FROM VAL_GET(:V$L17, 481)
    INTO :ORG;
    SELECT V
    FROM VAL_GET(:V$L17, 484)
    INTO :GRN;
    SUSPEND;
  END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIC_DATA_GET_PROGS (
    SCHOOL BIGINT)
RETURNS (
    PROGKINDID INTEGER,
    ORDERID INTEGER,
    ORDERID2 INTEGER,
    SCHOOLPROGID BIGINT,
    PROGNAME VARCHAR(1000),
    PROGGOALNAME VARCHAR(1000))
AS
BEGIN
    FOR
        SELECT (
            SELECT I
            FROM VAL_GET(L57.OBJ_ID, 389)) AS PROGKINDID,
               (
            SELECT
                CASE
                    WHEN I = 5336 THEN 1
                    WHEN I = 5345 THEN 2
                    WHEN I = 5364 THEN 3
                    WHEN I = 5357 THEN 4
                    --WHEN I = 3345 THEN 5
                    ELSE 10
                END
            FROM VAL_GET(L57.OBJ_ID, 1832)) AS ORDERID,
              (
            SELECT
                CASE
                    WHEN I = 22 THEN 1
                    WHEN I = 26 THEN 2
                    WHEN I = 27 THEN 3
                    WHEN I = 791 THEN 4
                    WHEN I = 792 THEN 5
                    WHEN I = 29 THEN 6
                    ELSE 10
                END
            FROM VAL_GET(L57.OBJ_ID, 387)) AS ORDERID2, L57.OBJ_ID AS SCHOOLPROGID,
              (
            SELECT VS.VAL
            FROM VALS VS
            WHERE VS.OBJ_ID = L57.OBJ_ID
            AND VS.PARAM_ID = 386) AS PROGNAME,
              (
            SELECT V
            FROM VAL_GET(L57.OBJ_ID, 390)) AS PROGGOALNAME
        FROM LINKS L69
        JOIN LINKS L57
        ON L57.PARENT_ID = L69.OBJ_ID
        AND L57.OBJ_TYPE_ID = 57
        AND L57.DATE_DEL IS NULL

        WHERE L69.OBJ_TYPE_ID = 69
        AND L69.DATE_DEL IS NULL
        AND L69.PARENT_ID = :SCHOOL
        ORDER BY 2, 1, 3, 6
        INTO :PROGKINDID, :ORDERID, :ORDERID2, :SCHOOLPROGID, :PROGNAME, :PROGGOALNAME
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIC_DATA_LISTOU RETURNS (
    CODE BIGINT,
    SHORTNAME VARCHAR(250),
    S_NAIMENOVANIE VARCHAR(500),
    SHORTNAME_ROD VARCHAR(250))
AS
DECLARE VARIABLE V$L112 bigint;
DECLARE VARIABLE V$L111 bigint;
BEGIN
    SELECT L112.OBJ_ID
    FROM LINKS L112
    WHERE L112.OBJ_TYPE_ID = 112
      AND L112.PARENT_ID IS NULL
      AND L112.DATE_DEL IS NULL
    INTO :V$L112;
    IF (NOT :V$L112 IS NULL) THEN
    BEGIN
        FOR SELECT L2.OBJ_ID AS CODE, VS.VAL, VS1.VAL, VS.VAL
            FROM LINKS L112
            JOIN LINKS L111 ON (L112.OBJ_ID = L111.PARENT_ID AND L111.OBJ_TYPE_ID = 111 AND L111.DATE_DEL IS NULL)
            JOIN LINKS L2 ON (L111.OBJ_ID = L2.PARENT_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL)
            LEFT JOIN VALS VS ON (VS.OBJ_ID = L2.OBJ_ID AND VS.PARAM_ID = 2)
            LEFT JOIN VALS VS1 ON (VS1.OBJ_ID = L2.OBJ_ID AND VS1.PARAM_ID = 5)
            WHERE L112.OBJ_TYPE_ID = 112
              AND L112.PARENT_ID IS NULL
              AND L112.DATE_DEL IS NULL
            INTO :CODE, :SHORTNAME, :S_NAIMENOVANIE, :SHORTNAME_ROD
        DO
        BEGIN
            SUSPEND;
        END
    END
    ELSE
    BEGIN
        SELECT L111.OBJ_ID
        FROM LINKS L111
        WHERE L111.OBJ_TYPE_ID = 111
          AND L111.PARENT_ID IS NULL
          AND L111.DATE_DEL IS NULL
        INTO :V$L111;
        IF (NOT :V$L111 IS NULL) THEN
        BEGIN
            FOR SELECT L2.OBJ_ID AS CODE, VS.VAL, VS1.VAL, VS.VAL
                FROM LINKS L2
                LEFT JOIN VALS VS ON (VS.OBJ_ID = L2.OBJ_ID AND VS.PARAM_ID = 2)
                LEFT JOIN VALS VS1 ON (VS1.OBJ_ID = L2.OBJ_ID AND VS1.PARAM_ID = 5)
                WHERE L2.PARENT_ID = :V$L111
                  AND L2.OBJ_TYPE_ID = 2
                  AND L2.DATE_DEL IS NULL
                INTO :CODE, :SHORTNAME, :S_NAIMENOVANIE, :SHORTNAME_ROD
            DO
            BEGIN
                SUSPEND;
            END
        END
        ELSE
        BEGIN
            FOR SELECT L2.OBJ_ID AS CODE, VS.VAL, VS1.VAL, VS.VAL
                FROM LINKS L2
                LEFT JOIN VALS VS ON (VS.OBJ_ID = L2.OBJ_ID AND VS.PARAM_ID = 2)
                LEFT JOIN VALS VS1 ON (VS1.OBJ_ID = L2.OBJ_ID AND VS1.PARAM_ID = 5)
                WHERE L2.OBJ_TYPE_ID = 2
                  AND L2.PARENT_ID IS NULL
                  AND L2.DATE_DEL IS NULL
                INTO :CODE, :SHORTNAME, :S_NAIMENOVANIE, :SHORTNAME_ROD
            DO
            BEGIN
                SUSPEND;
            END
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIC_DATA_PPLCOUNTS (
    I$OBJ_ID BIGINT,
    I$TYPEID INTEGER,
    I$EDUCFORMID INTEGER = -1000)
RETURNS (
    PPLCOUNTS INTEGER)
AS
declare variable V$L57 bigint;
declare variable V$TMP integer;
declare variable V$TMP1 integer;
BEGIN
    PPLCOUNTS = 0;
    FOR
        SELECT L57.OBJ_ID
        FROM LINKS L69
        JOIN LINKS L57
        ON L57.PARENT_ID = L69.OBJ_ID
        AND L57.OBJ_TYPE_ID = 57
        AND L57.DATE_DEL IS NULL

        JOIN VALL VL
        ON VL.OBJ_ID = L57.OBJ_ID
        AND VL.PARAM_ID = 1832

        WHERE L69.OBJ_TYPE_ID = 69
        AND L69.DATE_DEL IS NULL
        AND L69.PARENT_ID = :I$OBJ_ID
        AND VL.LISTVAL_ID = :I$TYPEID
        INTO V$L57
    DO
    BEGIN
        IF (:I$EDUCFORMID != -1000) THEN
        BEGIN
            SELECT COUNT(VL.OBJ_ID)

            FROM LINKS L50

            JOIN LINKS L54
            ON L54.PARENT_ID = L50.OBJ_ID
            AND L50.OBJ_TYPE_ID = 50
            AND L50.DATE_DEL IS NULL

            JOIN LINKS L9
            ON L9.PARENT_ID = L54.OBJ_ID
            AND L9.OBJ_TYPE_ID = 9
            AND L9.DATE_DEL IS NULL

            JOIN LINKS L10
            ON L10.PARENT_ID = L9.OBJ_ID
            AND L10.OBJ_TYPE_ID = 10
            AND L10.DATE_DEL IS NULL

            JOIN VALL VL
            ON VL.OBJ_ID = L10.OBJ_ID
            AND VL.PARAM_ID = 80
            AND VL.LISTVAL_ID = :I$EDUCFORMID

            WHERE L50.OBJ_TYPE_ID = 50
            AND L50.DATE_DEL IS NULL
            AND L50.PARENT_ID = :V$L57
            INTO V$TMP;

            SELECT COUNT(VL.OBJ_ID)
            FROM LINKS L50

            JOIN LINKS L54
            ON L54.PARENT_ID = L50.OBJ_ID
            AND L50.OBJ_TYPE_ID = 50
            AND L50.DATE_DEL IS NULL

            JOIN LINKS L46
            ON L46.PARENT_ID = L54.OBJ_ID
            AND L46.OBJ_TYPE_ID = 46
            AND L46.DATE_DEL IS NULL

            JOIN LINKS L10
            ON L10.PARENT_ID = L46.OBJ_ID
            AND L10.OBJ_TYPE_ID = 10
            AND L10.DATE_DEL IS NULL

            JOIN VALL VL
            ON VL.OBJ_ID = L10.OBJ_ID
            AND VL.PARAM_ID = 80
            AND VL.LISTVAL_ID = :I$EDUCFORMID

            WHERE L50.OBJ_TYPE_ID = 50
            AND L50.DATE_DEL IS NULL
            AND L50.PARENT_ID = :V$L57
            INTO V$TMP1;

            PPLCOUNTS = :PPLCOUNTS + :V$TMP + :V$TMP1;
        END
        ELSE
        BEGIN
            SELECT COUNT(L10.OBJ_ID)
            FROM LINKS L50

            JOIN LINKS L54
            ON L54.PARENT_ID = L50.OBJ_ID
            AND L50.OBJ_TYPE_ID = 50
            AND L50.DATE_DEL IS NULL

            JOIN LINKS L9
            ON L9.PARENT_ID = L54.OBJ_ID
            AND L9.OBJ_TYPE_ID = 9
            AND L9.DATE_DEL IS NULL

            JOIN LINKS L10
            ON L10.PARENT_ID = L9.OBJ_ID
            AND L10.OBJ_TYPE_ID = 10
            AND L10.DATE_DEL IS NULL

            WHERE L50.OBJ_TYPE_ID = 50
            AND L50.DATE_DEL IS NULL
            AND L50.PARENT_ID = :V$L57
            INTO V$TMP;

            SELECT COUNT(L10.OBJ_ID)
            FROM LINKS L50

            JOIN LINKS L54
            ON L54.PARENT_ID = L50.OBJ_ID
            AND L50.OBJ_TYPE_ID = 50
            AND L50.DATE_DEL IS NULL

            JOIN LINKS L46
            ON L46.PARENT_ID = L54.OBJ_ID
            AND L46.OBJ_TYPE_ID = 46
            AND L46.DATE_DEL IS NULL

            JOIN LINKS L10
            ON L10.PARENT_ID = L46.OBJ_ID
            AND L10.OBJ_TYPE_ID = 10
            AND L10.DATE_DEL IS NULL

            WHERE L50.OBJ_TYPE_ID = 50
            AND L50.DATE_DEL IS NULL
            AND L50.PARENT_ID = :V$L57
            INTO  V$TMP1;

            PPLCOUNTS = :PPLCOUNTS + :V$TMP + :V$TMP1;
        END
    END
    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIFECYCLE_DOC_GET (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$TYPE_ID BIGINT;
DECLARE VARIABLE S VARCHAR(1000);
DECLARE VARIABLE V$SERIE VARCHAR(100);
DECLARE VARIABLE V$NUM VARCHAR(100);
DECLARE VARIABLE V$DATE1 DATE;
DECLARE VARIABLE V$DATE2 DATE;
DECLARE VARIABLE V$ISSUER VARCHAR(1000);
DECLARE VARIABLE V$OKUD VARCHAR(100);
begin

  TAG_NAME = 'status_id:selection::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT LISTVAL_ID, VAL
    FROM LISTVALS_LIST(357)
    WHERE IS_DEL = 0
    INTO :V$OBJ_ID, :S
  DO
  BEGIN
    TAG_NAME = 'status_id:selection:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'status_id:selection:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'status_id:selection:r:value';
    VAL = S;
    SUSPEND;
  END
  TAG_NAME = 'status_id:values:value';
  VAL = NULL;
  SUSPEND;

  TAG_NAME = 'type_id:selection::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT LISTVAL_ID, VAL
    FROM LISTVALS_LIST(9)
    -- 11344 - акт готовности, для статусов включение в сеть и открытие
    WHERE IS_DEL = 0 AND LISTVAL_ID IN (14263, 14264, 14265, 14266, 14267, 14268, 1047, 1052, 1053, 11344)
    INTO :V$OBJ_ID, :S
  DO
  BEGIN
    TAG_NAME = 'type_id:selection:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'type_id:selection:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'type_id:selection:r:value';
    VAL = S;
    SUSPEND;
  END
  TAG_NAME = 'type_id:values:value';
  VAL = NULL;
  SUSPEND;

  -- Существующие документы, только еще не упомянутые в ЖЗЦ
  TAG_NAME = 'file_ref:selection::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L17.OBJ_ID, V471.LISTVAL_ID, V596.VAL, V479.VAL, V480.VAL, V482.VAL, V483.VAL, V481.VAL, V598.SVAL
    FROM LINKS L17
    JOIN VALL V471 ON V471.OBJ_ID = L17.OBJ_ID AND V471.PARAM_ID = 471 AND V471.IS_DEL = 0 AND V471.LISTVAL_ID IN (14263, 14264, 14265, 14266, 14267, 14268, 1047, 1052, 1053, 18624, 18625)
    JOIN VALS V596 ON V596.OBJ_ID = L17.OBJ_ID AND V596.PARAM_ID = 596 AND V596.IS_DEL = 0
    LEFT JOIN VALS V479 ON V479.OBJ_ID = L17.OBJ_ID AND V479.PARAM_ID = 479 AND V479.IS_DEL = 0
    LEFT JOIN VALS V480 ON V480.OBJ_ID = L17.OBJ_ID AND V480.PARAM_ID = 480 AND V480.IS_DEL = 0
    JOIN VALD V482 ON V482.OBJ_ID = L17.OBJ_ID AND V482.PARAM_ID = 482 AND V482.IS_DEL = 0
    LEFT JOIN VALD V483 ON V483.OBJ_ID = L17.OBJ_ID AND V483.PARAM_ID = 483 AND V483.IS_DEL = 0
    LEFT JOIN VALS V481 ON V481.OBJ_ID = L17.OBJ_ID AND V481.PARAM_ID = 481 AND V481.IS_DEL = 0
    LEFT JOIN VALS V598 ON V598.OBJ_ID = L17.OBJ_ID AND V598.PARAM_ID = 598 AND V598.IS_DEL = 0
    WHERE L17.PARENT_ID = :I$OBJ_ID AND L17.OBJ_TYPE_ID = 17 AND L17.DATE_DEL IS NULL
    INTO :V$OBJ_ID, :V$TYPE_ID, :S, :V$SERIE, :V$NUM, :V$DATE1, :V$DATE2, :V$ISSUER, :V$OKUD
  DO
  BEGIN
    TAG_NAME = 'file_ref:selection:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'file_ref:selection:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'file_ref:selection:r:value';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'file_ref:selection:r:subset_id';
    VAL = V$TYPE_ID || '|' || COALESCE(V$SERIE, '') || '|' || COALESCE(V$NUM, '') || '|' || COALESCE((SELECT VAL FROM DATE2ISO(:V$DATE1, 0)), '') || '|' ||
      COALESCE((SELECT VAL FROM DATE2ISO(:V$DATE2, 0)), '') || '|' || COALESCE(V$ISSUER, '') || '|' || COALESCE(V$OKUD, '');
    SUSPEND;
  END
  TAG_NAME = 'file_ref:values:value';
  VAL = NULL;
  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIFECYCLE_DOC_SET (
    I$OBJ_ID BIGINT,
    I$STATUS_ID BIGINT,
    I$TYPE_ID BIGINT,
    I$NAME VARCHAR(1000),
    I$ISSUER VARCHAR(1000),
    I$DATE_FROM DATE,
    I$DATE_TO DATE,
    I$DOC_DATE DATE,
    I$SERIE VARCHAR(100),
    I$NUMBER VARCHAR(100),
    I$OKUD VARCHAR(100),
    I$FILE_ID BIGINT,
    I$FILENAME1 VARCHAR(1000),
    I$FILENAME2 VARCHAR(1000))
RETURNS (
    LCD_ID BIGINT,
    DOC_ID BIGINT,
    BLOB_ID1 BIGINT,
    BLOB_ID2 BIGINT)
AS
DECLARE VARIABLE T INTEGER;
DECLARE VARIABLE V$DT DATE;
begin

  -- Если выбрали готовый документ - ничего не вносим, и подтягиваем данные из него
  IF(I$FILE_ID IS NOT NULL) THEN
  BEGIN

    SELECT FIRST 1 V.LISTVAL_ID
    FROM VALL V
    WHERE V.OBJ_ID = :I$FILE_ID AND V.PARAM_ID = 471 AND V.IS_DEL = 0
    INTO :I$TYPE_ID;

    IF(I$TYPE_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Указанный документ ОООД не найден';

    SELECT FIRST 1 V.VAL
    FROM VALD V
    WHERE V.OBJ_ID = :I$FILE_ID AND V.PARAM_ID = 482 AND V.IS_DEL = 0
    INTO :I$DOC_DATE;

    -- Не подшиты сканы ?
    -- !!!

    DOC_ID = I$FILE_ID;

  END

  -- Проверяем хронологию загрузки
  SELECT FIRST 1 V482.VAL
  FROM LINKS L497
  JOIN VALR V3433 ON V3433.OBJ_ID = L497.OBJ_ID AND V3433.PARAM_ID = 3433 AND V3433.IS_DEL = 0
  JOIN VALD V482 ON V482.OBJ_ID = V3433.VAL AND V482.PARAM_ID = 482 AND V482.IS_DEL = 0 AND V482.VAL > :I$DOC_DATE
  WHERE L497.PARENT_ID = :I$OBJ_ID AND L497.OBJ_TYPE_ID = 497 AND L497.DATE_DEL IS NULL
  INTO :V$DT;
  IF(V$DT IS NOT NULL) THEN
    EXCEPTION DATA_ERROR 'Документы жизненного цикла должны загружаться в строго хронологическом порядке, в системе есть документ от ' || V$DT;

  IF(I$DATE_FROM IS NULL) THEN EXCEPTION DATA_ERROR 'Не заполнена дата начала действия';
  IF(I$DATE_TO IS NOT NULL AND I$DATE_TO < I$DATE_FROM) THEN EXCEPTION DATA_ERROR 'Неверный порядок дат начала и окончания действия';
  IF(I$STATUS_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не заполнен статус';
  IF(I$TYPE_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не заполнен тип документа';
  IF(I$DOC_DATE IS NULL) THEN EXCEPTION DATA_ERROR 'Не заполнена дата документа';
  IF(I$NUMBER IS NULL) THEN EXCEPTION DATA_ERROR 'Не заполнен номер документа';
  IF(I$NAME IS NULL) THEN EXCEPTION DATA_ERROR 'Не заполнено название документа';

  -- Сверка по типам
  IF(
    (I$STATUS_ID = 14281 AND I$TYPE_ID NOT IN (14263, 14264)) OR
    (I$STATUS_ID = 14282 AND I$TYPE_ID NOT IN (14263, 14264)) OR
    (I$STATUS_ID = 14283 AND I$TYPE_ID NOT IN (14265)) OR
    (I$STATUS_ID = 14284 AND I$TYPE_ID NOT IN (14264)) OR
    (I$STATUS_ID = 14285 AND I$TYPE_ID NOT IN (1047)) OR
    (I$STATUS_ID = 14286 AND I$TYPE_ID NOT IN (14266)) OR
    (I$STATUS_ID = 14287 AND I$TYPE_ID NOT IN (14267)) OR
    (I$STATUS_ID = 14288 AND I$TYPE_ID NOT IN (1052, 18624)) OR
    (I$STATUS_ID = 14289 AND I$TYPE_ID NOT IN (1053, 18625)) OR
    (I$STATUS_ID = 14290 AND I$TYPE_ID NOT IN (14268)) OR
    -- Включение в сеть и открытие ОУ - можно взять любой тип
    (I$STATUS_ID = 14291 AND I$TYPE_ID IS NULL) OR
    (I$STATUS_ID = 14292 AND I$TYPE_ID IS NULL)
  )
  THEN
    EXCEPTION DATA_ERROR 'Неверно указан тип или статус документа';

  IF(I$FILE_ID IS NULL) THEN
  BEGIN
    SELECT OBJ_ID FROM OBJECT_ADD(:I$OBJ_ID, 17) INTO :DOC_ID;
    SELECT 1 FROM VAL_ADD(471, :DOC_ID, :I$TYPE_ID) INTO :T;
    SELECT 1 FROM VAL_ADD(596, :DOC_ID, :I$NAME) INTO :T;
    SELECT 1 FROM VAL_ADD(479, :DOC_ID, :I$SERIE) INTO :T;
    SELECT 1 FROM VAL_ADD(480, :DOC_ID, :I$NUMBER) INTO :T;
    SELECT 1 FROM VAL_ADD(481, :DOC_ID, :I$ISSUER) INTO :T;
    SELECT 1 FROM VAL_ADD(482, :DOC_ID, :I$DOC_DATE) INTO :T;
    -- 483 тут нет
    SELECT 1 FROM VAL_ADD(598, :DOC_ID, :I$OKUD) INTO :T;
  END

  SELECT OBJ_ID FROM OBJECT_ADD(:I$OBJ_ID, 497) INTO :LCD_ID;
  SELECT 1 FROM VAL_ADD(3430, :LCD_ID, :I$STATUS_ID) INTO :T;
  SELECT 1 FROM VAL_ADD(3433, :LCD_ID, :DOC_ID) INTO :T;
  SELECT 1 FROM VAL_ADD(3431, :LCD_ID, :I$DATE_FROM) INTO :T;
  SELECT 1 FROM VAL_ADD(3432, :LCD_ID, :I$DATE_TO) INTO :T;

  IF(I$FILE_ID IS NULL) THEN
  BEGIN
    SELECT BLOB_ID FROM VAL_ADD(478, :DOC_ID, :I$FILENAME1) INTO :BLOB_ID1;
    SELECT BLOB_ID FROM VAL_ADD(597, :DOC_ID, :I$FILENAME2) INTO :BLOB_ID2;
  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LINK_COLUMNS_LIST (
    I$OBJ_ID BIGINT,
    I$PARENT_ID BIGINT,
    I$TYPE_ID BIGINT,
    I$LEVEL_ID BIGINT,
    I$IS_SELECT SMALLINT,
    I$TYPE_IDS VARCHAR(4000),
    I$USER_ID BIGINT)
RETURNS (
    OWNER_OBJ_ID BIGINT,
    OBJ_ID BIGINT,
    TYPE_ID BIGINT,
    OBJ_CAPTION VARCHAR(4000))
AS
BEGIN
    FOR
        SELECT DISTINCT
               OBJ_ID
        FROM OBJECT_GRID_VALS(
            :I$PARENT_ID,
            :I$OBJ_ID,
            :I$TYPE_ID,
            :I$LEVEL_ID,
            :I$IS_SELECT,
            0,
            :I$USER_ID
        )
        INTO :OWNER_OBJ_ID
    DO
    BEGIN
        OBJ_ID = NULL;
        TYPE_ID = NULL;
        OBJ_CAPTION = NULL;

        SELECT FIRST 1
               O.OBJ_ID,
               O.TYPE_ID
        FROM LINKS L
        INNER JOIN OBJECTS O
        ON O.OBJ_ID = L.OBJ_ID
        WHERE L.PARENT_ID = :OWNER_OBJ_ID
        AND :I$TYPE_IDS CONTAINING '~' || O.TYPE_ID || '~'

        INTO :OBJ_ID,
             :TYPE_ID;

        IF (OBJ_ID IS NULL) THEN
        BEGIN
            SELECT FIRST 1
                   O.OBJ_ID,
                   O.TYPE_ID
            FROM LINKS L
            INNER JOIN OBJECTS O
            ON O.OBJ_ID = L.PARENT_ID
            WHERE L.OBJ_ID = :OWNER_OBJ_ID
            AND :I$TYPE_IDS CONTAINING '~' || O.TYPE_ID || '~'
        
            INTO :OBJ_ID,
                 :TYPE_ID;
        END

        IF (OBJ_ID IS NOT NULL) THEN
        BEGIN
            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:OBJ_ID,NULL,NULL,:I$USER_ID)
            INTO   :OBJ_CAPTION;
            SUSPEND;
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LISTS_LIST (
    I$LANG_CODE VARCHAR(2) = 'RU')
RETURNS (
    LIST_ID BIGINT,
    RES_ID BIGINT,
    FOR_REPL_UP SMALLINT,
    FOR_REPL_DOWN SMALLINT,
    IS_DEL SMALLINT,
    LANG_CODE CHAR(2),
    LIST_CAPTION VARCHAR(4000))
AS
BEGIN
    LANG_CODE = I$LANG_CODE;
    FOR
        SELECT LIST_ID,
               RES_ID,
               FOR_REPL_UP,
               FOR_REPL_DOWN,
               IS_DEL
        FROM LISTS
        ORDER BY LIST_ID
        INTO   :LIST_ID,
               :RES_ID,
               :FOR_REPL_UP,
               :FOR_REPL_DOWN,
               :IS_DEL
    DO
    BEGIN
       SELECT VAL
       FROM RES_GET(:RES_ID, :I$LANG_CODE)
       INTO   :LIST_CAPTION;
       SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LISTVALS_EDIT (
    I$LIST_ID BIGINT,
    I$LANG_CODE VARCHAR(2) = 'RU')
RETURNS (
    LISTVAL_ID BIGINT,
    LIST_ID BIGINT,
    LANG_CODE VARCHAR(2),
    PARENT_ID BIGINT,
    RES_ID BIGINT,
    VAL VARCHAR(4000),
    VAL_LONG VARCHAR(4000),
    TAG VARCHAR(100),
    SORT_ORDER SMALLINT,
    COST FLOAT,
    IS_DEL SMALLINT,
    IS_EDIT BIGINT)
AS
declare variable G bigint;
declare variable M bigint;
BEGIN
    SELECT GEN,  MULTIPLIER FROM GEN INTO :G, :M;

    FOR
        SELECT L.LISTVAL_ID,
               L.LIST_ID,
               :LANG_CODE,
               L.PARENT_ID,
               R.VAL,
               R.VAL_LONG,
               L.TAG,
               L.SORT_ORDER,
               L.COST,
               L.IS_DEL,
               L.RES_ID
        FROM LISTVALS L

        LEFT JOIN RES_GET(L.RES_ID,  :I$LANG_CODE) R ON 1=1

        WHERE L.LIST_ID = :I$LIST_ID

        ORDER BY L.SORT_ORDER
        INTO   :LISTVAL_ID,
               :LIST_ID,
               :LANG_CODE,
               :PARENT_ID,
               :VAL,
               :VAL_LONG,
               :TAG,
               :SORT_ORDER,
               :COST,
               :IS_DEL,
               :RES_ID
    DO
    BEGIN
        IF ((LISTVAL_ID / M) = G) THEN
        BEGIN
            IS_EDIT = 1;
        END
        ELSE
        BEGIN
            IS_EDIT = 0;
        END
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LISTVALS_LIST (
    I$LIST_ID BIGINT,
    I$LANG_CODE VARCHAR(2) = 'RU')
RETURNS (
    LISTVAL_ID BIGINT,
    LIST_ID BIGINT,
    RES_ID BIGINT,
    LANG_CODE VARCHAR(2),
    PARENT_ID BIGINT,
    VAL VARCHAR(4000),
    VAL_LONG VARCHAR(4000),
    TAG VARCHAR(100),
    "FILTER" VARCHAR(255),
    SORT_ORDER SMALLINT,
    COST FLOAT,
    IS_DEL SMALLINT)
AS
BEGIN
    FOR
        SELECT LV.LISTVAL_ID, LV.LIST_ID, :I$LANG_CODE, LV.PARENT_ID, LV.TAG, LV."FILTER", LV.SORT_ORDER, LV.COST, LV.IS_DEL, LV.RES_ID, R.VAL, R.VAL_LONG
        FROM LISTVALS LV
        LEFT JOIN RES_GET(LV.RES_ID, :I$LANG_CODE) R ON 1 = 1
        WHERE LV.LIST_ID = :I$LIST_ID
        ORDER BY LV.SORT_ORDER
        INTO :LISTVAL_ID, :LIST_ID, :LANG_CODE, :PARENT_ID, :TAG, :"FILTER", :SORT_ORDER, :COST, :IS_DEL, :RES_ID, :VAL, :VAL_LONG
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LISTVAL_ADD (
    I$LISTVAL_ID BIGINT,
    I$LIST_ID BIGINT,
    I$RES_ID BIGINT,
    I$LANG_CODE VARCHAR(2),
    I$PARENT_ID BIGINT,
    I$VAL VARCHAR(4000),
    I$VAL_LONG VARCHAR(4000),
    I$TAG VARCHAR(100),
    I$FILTER VARCHAR(255),
    I$COST FLOAT,
    I$IS_DEL SMALLINT,
    I$SORT_ORDER SMALLINT = null)
RETURNS (
    LISTVAL_ID BIGINT,
    SORT_ORDER SMALLINT)
AS
BEGIN
    LISTVAL_ID  = NULL;
    SORT_ORDER  = I$SORT_ORDER;
    IF (I$VAL_LONG IS NULL) THEN I$VAL_LONG = '';
    IF (I$COST IS NULL) THEN I$COST = 0;

    IF (I$LISTVAL_ID IS NULL) THEN
    BEGIN
        SELECT MAX(SORT_ORDER) + 1
        FROM LISTVALS
        WHERE LIST_ID = :I$LIST_ID
        INTO :SORT_ORDER;

        IF (SORT_ORDER IS NULL) THEN SORT_ORDER = 1;

        INSERT INTO LISTVALS
        (LIST_ID, PARENT_ID, TAG, "FILTER", SORT_ORDER, COST)
        VALUES (:I$LIST_ID, :I$PARENT_ID, :I$TAG, :I$FILTER, :SORT_ORDER, :I$COST)
        RETURNING LISTVAL_ID, RES_ID
        INTO :LISTVAL_ID, :I$RES_ID;
    END
    ELSE
    BEGIN
        IF (SORT_ORDER IS NULL) THEN
        BEGIN
            SELECT SORT_ORDER
            FROM LISTVALS
            WHERE LISTVAL_ID = :I$LISTVAL_ID
            INTO :SORT_ORDER;
        END
        UPDATE LISTVALS
        SET PARENT_ID = :I$PARENT_ID,
            TAG = :I$TAG,
            "FILTER" = :I$FILTER,
            COST = :I$COST,
            IS_DEL = :I$IS_DEL,
            SORT_ORDER = :SORT_ORDER
        WHERE LISTVAL_ID = :I$LISTVAL_ID;

        IF (ROW_COUNT = 1) THEN
        BEGIN
            LISTVAL_ID = I$LISTVAL_ID;
        END
    END
    IF (I$RES_ID IS NOT NULL) THEN
    BEGIN
        EXECUTE PROCEDURE RES_ADD (:I$RES_ID,:I$LANG_CODE,:I$VAL,:I$VAL_LONG);
    END
    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LISTVAL_DEL (
    I$LISTVAL_ID BIGINT,
    I$IS_DEL SMALLINT = 1)
AS
BEGIN
   UPDATE LISTVALS SET
      IS_DEL = :I$IS_DEL
    WHERE LISTVAL_ID = :I$LISTVAL_ID;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LISTVAL_LEVEL (
    I$LISTVAL_ID BIGINT)
RETURNS (
    "LEVEL" SMALLINT)
AS
BEGIN
    "LEVEL" = 1;
    I$LISTVAL_ID = (SELECT PARENT_ID FROM LISTVALS WHERE LISTVAL_ID = :I$LISTVAL_ID);
    WHILE(:I$LISTVAL_ID IS NOT NULL) DO
    BEGIN
        "LEVEL" = "LEVEL" + 1;
        I$LISTVAL_ID = (SELECT PARENT_ID FROM LISTVALS WHERE LISTVAL_ID = :I$LISTVAL_ID);
    END
    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LISTVAL_MOVE (
    I$LISTVAL_ID BIGINT,
    I$MOVE SMALLINT)
AS
declare variable LISTVAL_ID bigint;
declare variable LIST_ID bigint;
declare variable SORT_ORDER smallint;
BEGIN
    LIST_ID = NULL;

    SELECT LIST_ID, SORT_ORDER
    FROM LISTVALS
    WHERE LISTVAL_ID = :I$LISTVAL_ID
    INTO :LIST_ID, :SORT_ORDER;

    LISTVAL_ID = NULL;

    SELECT LISTVAL_ID
    FROM LISTVALS
    WHERE LIST_ID = :LIST_ID AND SORT_ORDER = (:SORT_ORDER + :I$MOVE)
    INTO :LISTVAL_ID;

    IF (LISTVAL_ID IS NOT NULL) THEN
    BEGIN
        UPDATE LISTVALS SET SORT_ORDER = :SORT_ORDER
        WHERE LISTVAL_ID = :LISTVAL_ID;

        UPDATE LISTVALS SET SORT_ORDER = (:SORT_ORDER + :I$MOVE)
        WHERE LISTVAL_ID = :I$LISTVAL_ID;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LISTVAL_MOVE_ABS (
    I$LISTVAL_ID BIGINT,
    I$LISTVAL_MASTER BIGINT)
AS
declare variable LIST_ID bigint;
declare variable SORT_ORDER integer;
declare variable LISTVAL_ID bigint;
declare variable V$SORT_ORDER integer;
begin

    -- Получаем номер списка и местоположение родителя
    SELECT LIST_ID, SORT_ORDER
    FROM LISTVALS
    WHERE LISTVAL_ID = :I$LISTVAL_MASTER
    INTO :LIST_ID, :SORT_ORDER;

    V$SORT_ORDER = SORT_ORDER;

    -- Сначала раздвигаем нумерацию списка элементов
    FOR
        SELECT LISTVAL_ID
        FROM LISTVALS
        WHERE LIST_ID = :LIST_ID AND SORT_ORDER >= :SORT_ORDER AND LISTVAL_ID <> :I$LISTVAL_ID
        ORDER BY SORT_ORDER
        INTO :LISTVAL_ID
    DO
    BEGIN

        V$SORT_ORDER = V$SORT_ORDER + 1;

        UPDATE LISTVALS
        SET SORT_ORDER = :V$SORT_ORDER
        WHERE LISTVAL_ID = :LISTVAL_ID;

    END

    -- Вставляем элемент на новое место
    UPDATE LISTVALS
    SET SORT_ORDER = :SORT_ORDER
    WHERE LISTVAL_ID = :I$LISTVAL_ID;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LISTVAL_TEXT (
    I$LISTVAL_ID BIGINT)
RETURNS (
    VAL VARCHAR(400),
    SORT_ORDER INTEGER)
AS
begin
  SELECT FIRST 1 SUBSTRING(R.VAL FROM 1 FOR 400), LV.SORT_ORDER
  FROM LISTVALS LV
  JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
  WHERE LV.LISTVAL_ID = :I$LISTVAL_ID
  INTO :VAL, :SORT_ORDER;

  SUSPEND;
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIST_ADD (
    I$LIST_ID BIGINT,
    I$RES_ID BIGINT,
    I$FOR_REPL_UP SMALLINT,
    I$FOR_REPL_DOWN SMALLINT,
    I$LANG_CODE CHAR(2),
    I$LIST_CAPTION VARCHAR(4000),
    I$IS_DEL SMALLINT = 1)
RETURNS (
    LIST_ID BIGINT,
    RES_ID BIGINT)
AS
BEGIN
   LIST_ID  = I$LIST_ID;
   RES_ID   = I$RES_ID;

   IF (I$LIST_ID IS NULL) THEN BEGIN
      INSERT INTO LISTS (FOR_REPL_UP, FOR_REPL_DOWN)
      VALUES (:I$FOR_REPL_UP, :I$FOR_REPL_DOWN)
      RETURNING LIST_ID, RES_ID INTO :LIST_ID, :RES_ID;
   END ELSE BEGIN
      UPDATE LISTS
      SET FOR_REPL_UP = :I$FOR_REPL_UP,
          FOR_REPL_DOWN = :I$FOR_REPL_DOWN,
          IS_DEL  = :I$IS_DEL
      WHERE LIST_ID = :I$LIST_ID;
   END

   IF (RES_ID IS NOT NULL) THEN
       EXECUTE PROCEDURE RES_ADD (:RES_ID,:I$LANG_CODE,:I$LIST_CAPTION);

   SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LIST_CLEAR (
    I$OBJ_ID BIGINT,
    I$LISTVAL_ID BIGINT)
RETURNS (
    X INTEGER)
AS
DECLARE VARIABLE ID BIGINT;
BEGIN
    X = 0;
    FOR SELECT O.OBJ_ID
        FROM OBJECT_CHILDREN_GET_DEEP(:I$OBJ_ID, 124, 5) O
        INNER JOIN VALL V ON V.OBJ_ID = O.OBJ_ID
        WHERE V.PARAM_ID = 912
          AND V.IS_DEL = 0
          AND V.LISTVAL_ID = :I$LISTVAL_ID
        INTO :ID
    DO
    BEGIN
        UPDATE LINKS L
        SET L.DATE_DEL = CURRENT_TIMESTAMP
        WHERE L.OBJ_ID = :ID;
        X = X + 1;
    END

    FOR SELECT O.OBJ_ID
        FROM OBJECT_CHILDREN_GET_DEEP(:I$OBJ_ID, 123, 3) O
        INNER JOIN VALL V ON V.OBJ_ID = O.OBJ_ID
        WHERE V.PARAM_ID = 755
          AND V.IS_DEL = 0
          AND V.LISTVAL_ID = :I$LISTVAL_ID
        INTO :ID
    DO
    BEGIN
        UPDATE LINKS L
        SET L.DATE_DEL = CURRENT_TIMESTAMP
        WHERE L.OBJ_ID = :ID;
        X = X + 1;
    END

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LLISTS_LIST (
    I$LEVEL_ID BIGINT,
    I$LANG_CODE VARCHAR(2) = 'RU')
RETURNS (
    LEVEL_ID BIGINT,
    LIST_ID BIGINT,
    LIST_CAPTION VARCHAR(4000),
    EDIT_TYPE SMALLINT)
AS
declare variable RES_ID bigint;
BEGIN
    LEVEL_ID = I$LEVEL_ID;

        FOR
            SELECT LS.LIST_ID,
                   LS.RES_ID,
                   COALESCE(LL.EDIT_TYPE,-1)
            FROM LISTS LS
            LEFT JOIN LLISTS LL
            ON LL.LEVEL_ID = :I$LEVEL_ID
            AND LL.LIST_ID = LS.LIST_ID
            INTO   :LIST_ID,
                   :RES_ID,
                   :EDIT_TYPE
        DO
        BEGIN
            SELECT VAL FROM RES_GET(:RES_ID, :I$LANG_CODE) INTO :LIST_CAPTION;
            SUSPEND;
        END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LLIST_ADD (
    I$LEVEL_ID BIGINT,
    I$LIST_ID BIGINT,
    I$EDIT_TYPE SMALLINT)
AS
DECLARE VARIABLE IS_DEL SMALLINT = 0;
BEGIN
    IF (I$EDIT_TYPE < 0) THEN IS_DEL = 1;

    UPDATE OR INSERT INTO LLISTS (LEVEL_ID, LIST_ID, EDIT_TYPE, IS_DEL)
    VALUES (:I$LEVEL_ID, :I$LIST_ID, :I$EDIT_TYPE, :IS_DEL);
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LOG_ADD (
    I$USER_ID BIGINT,
    I$LEVEL_ID BIGINT,
    I$PC_NAME VARCHAR(100))
RETURNS (
    LOG_ID BIGINT)
AS
BEGIN
    INSERT INTO LOG (USER_ID, LEVEL_ID, PC_NAME, DATE_START)
    VALUES (:I$USER_ID, :I$LEVEL_ID, :I$PC_NAME, CURRENT_TIMESTAMP)
    RETURNING LOG_ID INTO :LOG_ID;

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LOG_EXIT (
    I$LOG_ID BIGINT)
RETURNS (
    IS_EXIT INTEGER)
AS
DECLARE VARIABLE RES_ID BIGINT = NULL;
BEGIN
    UPDATE LOG SET DATE_EXIT = CURRENT_TIMESTAMP
    WHERE LOG_ID = :I$LOG_ID
      AND DATE_EXIT IS NULL;

    IS_EXIT = ROW_COUNT;

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LOG_GET (
    I$LOG_ID BIGINT)
RETURNS (
    USER_ID BIGINT,
    LEVEL_ID BIGINT,
    LANG_CODE CHAR(2),
    OBJ_ID BIGINT,
    USER_FIO VARCHAR(4000),
    TASK_ID BIGINT,
    MODULE_ID BIGINT,
    MODULE_CODE VARCHAR(100),
    MODULE_CAPTION VARCHAR(4000),
    TASK_CAPTION VARCHAR(4000),
    TASK_CAPTION_LONG VARCHAR(4000))
AS
declare variable RES_ID bigint = null;
declare variable TASK_RES_ID bigint;
BEGIN
    SELECT USER_ID, LEVEL_ID FROM LOG
    WHERE LOG_ID = :I$LOG_ID AND (DATE_ACTIVATE IS NULL OR (:I$LOG_ID < 0))
    INTO :USER_ID, :LEVEL_ID;

    IF (ROW_COUNT = 0) THEN
    BEGIN
--       SUSPEND;
       EXIT;
    END

    SELECT
       COALESCE(FIRST_NAME,'')||' '||COALESCE(MIDDLE_NAME,'')||' '||COALESCE(LAST_NAME,''),
       LANG_CODE,
       OBJ_ID
    FROM USERS
    WHERE USER_ID = :USER_ID
    INTO :USER_FIO, :LANG_CODE, :OBJ_ID;

    IF (OBJ_ID IS NOT NULL) THEN
       SELECT CAPTION FROM OBJECT_CAPTION_GET(:OBJ_ID) INTO :USER_FIO;

    SELECT M.MODULE_ID, M.MODULE_CODE, M.RES_ID, T.TASK_ID, T.RES_ID
    FROM MODULES M
    INNER JOIN TASKS T ON T.MODULE_ID = M.MODULE_ID
    INNER JOIN LEVELS L ON L.TASK_ID = T.TASK_ID
    WHERE L.LEVEL_ID = :LEVEL_ID
    INTO :MODULE_ID, :MODULE_CODE, :RES_ID, :TASK_ID, :TASK_RES_ID;

    IF (:RES_ID IS NOT NULL) THEN
      SELECT VAL FROM RES_GET(:RES_ID, :LANG_CODE) INTO :MODULE_CAPTION;

    IF (:TASK_RES_ID IS NOT NULL) THEN
      SELECT VAL, VAL_LONG FROM RES_GET(:TASK_RES_ID, :LANG_CODE) INTO :TASK_CAPTION, :TASK_CAPTION_LONG;

    UPDATE LOG SET DATE_ACTIVATE = CURRENT_TIMESTAMP
    WHERE LOG_ID = :I$LOG_ID;

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LOG_LIST (
    I$USER_ID BIGINT,
    I$LANG_CODE CHAR(2))
RETURNS (
    DATE_START TIMESTAMP,
    DATE_EXIT TIMESTAMP,
    PC_NAME VARCHAR(100),
    LEVEL_CAPTION VARCHAR(1000),
    TASK_CAPTION VARCHAR(1000),
    MODULE_CAPTION VARCHAR(1000))
AS
DECLARE VARIABLE LEVEL_RES_ID BIGINT;
DECLARE VARIABLE TASK_RES_ID BIGINT;
DECLARE VARIABLE MODULE_RES_ID BIGINT;
BEGIN
    FOR
        SELECT L.DATE_START,
               L.DATE_EXIT,
               L.PC_NAME,
               LV.RES_ID,
               T.RES_ID,
               M.RES_ID
        FROM LOG L
        INNER JOIN LEVELS LV
        ON LV.LEVEL_ID = L.LEVEL_ID
        INNER JOIN TASKS T
        ON T.TASK_ID = LV.TASK_ID
        INNER JOIN MODULES M
        ON M.MODULE_ID = T.MODULE_ID
        WHERE L.USER_ID = :I$USER_ID
        ORDER BY L.LOG_ID
        INTO   :DATE_START,
               :DATE_EXIT,
               :PC_NAME,
               :LEVEL_RES_ID,
               :TASK_RES_ID,
               :MODULE_RES_ID
    DO
    BEGIN
        SELECT VAL FROM RES_GET(:LEVEL_RES_ID, :I$LANG_CODE) INTO :LEVEL_CAPTION;
        SELECT VAL FROM RES_GET(:TASK_RES_ID, :I$LANG_CODE) INTO :TASK_CAPTION;
        SELECT VAL FROM RES_GET(:MODULE_RES_ID, :I$LANG_CODE) INTO :MODULE_CAPTION;
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LONGVACATION_ADD (
    OBJ_ID BIGINT)
AS
declare variable LINK_ID bigint;
declare variable STATUS_LV bigint;
declare variable DATE_IN date;
declare variable DATE_OUT date;
begin

    -- При добавлении новой записи длительного отпуска у предыдущей должны быть заполнены: статус, дата начала, дата окончания
    SELECT MAX(LINK_ID)
    FROM LINKS
    WHERE PARENT_ID = :OBJ_ID AND OBJ_TYPE_ID = 376 AND DATE_DEL IS NULL
    INTO :LINK_ID;

    -- Если записей нет, то и нечего проверять
    IF(LINK_ID IS NULL) THEN EXIT;

    SELECT V2859.LISTVAL_ID, V2860.VAL, V2861.VAL
    FROM LINKS L376
    LEFT JOIN VALL V2859 ON V2859.OBJ_ID = L376.OBJ_ID AND V2859.PARAM_ID = 2859 AND V2859.IS_DEL = 0
    LEFT JOIN VALD V2860 ON V2860.OBJ_ID = L376.OBJ_ID AND V2860.PARAM_ID = 2860 AND V2860.IS_DEL = 0
    LEFT JOIN VALD V2861 ON V2861.OBJ_ID = L376.OBJ_ID AND V2861.PARAM_ID = 2861 AND V2861.IS_DEL = 0
    WHERE L376.LINK_ID = :LINK_ID
    INTO :STATUS_LV, :DATE_IN, :DATE_OUT;

    IF(STATUS_LV IS NULL) THEN EXCEPTION DATA_ERROR 'У предыдущего отпуска не внесен статус';
    IF(DATE_IN IS NULL) THEN EXCEPTION DATA_ERROR 'У предыдущего отпуска не внесена дата начала отпуска';
    IF(DATE_OUT IS NULL) THEN EXCEPTION DATA_ERROR 'У предыдущего отпуска не внесена дата окончания отпуска';

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LONGVACATION_CHANGE (
    OBJ_ID BIGINT,
    PARAM_ID BIGINT,
    VAL VARCHAR(4000),
    IS_DEL SMALLINT)
AS
DECLARE VARIABLE N INTEGER;
DECLARE VARIABLE DATE_IN DATE;
DECLARE VARIABLE DATE_OUT DATE;
DECLARE VARIABLE DATE_ORDER_IN DATE;
DECLARE VARIABLE DATE_ORDER_OUT DATE;
DECLARE VARIABLE STATUS_LV BIGINT;
DECLARE VARIABLE PERSON_ID BIGINT;
DECLARE VARIABLE ASSN_ID BIGINT;
DECLARE VARIABLE VAC_ID BIGINT;
DECLARE VARIABLE VAC_RATE DOUBLE PRECISION;
DECLARE VARIABLE TEACHERS_RATE DOUBLE PRECISION;
DECLARE VARIABLE AVAIL_RATE DOUBLE PRECISION;
DECLARE VARIABLE USED_RATE DOUBLE PRECISION;
DECLARE VARIABLE VAC_NAME VARCHAR(1000);
begin

    -- В старых отпусках вообще ничего исправлять нельзя
    N = 0;
    SELECT FIRST 1 1
    FROM LINKS L376
    JOIN LINKS L376_NEXT ON L376_NEXT.PARENT_ID = L376.PARENT_ID AND L376_NEXT.OBJ_TYPE_ID = 376 AND L376_NEXT.DATE_DEL IS NULL AND L376_NEXT.LINK_ID > L376.LINK_ID
    WHERE L376.OBJ_ID = :OBJ_ID AND L376.PARENT_TYPE_ID = 14 AND L376.DATE_DEL IS NULL
    INTO :N;

    IF(N <> 0) THEN EXCEPTION DATA_ERROR 'Изменения можно вносить только в последнюю запись отпуска';

    IF(PARAM_ID = 2859 AND IS_DEL = 1) THEN EXCEPTION DATA_ERROR 'Нельзя удалять значение типа (статуса) отпуска';
    IF(PARAM_ID = 2860 AND IS_DEL = 1) THEN EXCEPTION DATA_ERROR 'Нельзя удалять дату ухода в отпуск';
    IF(PARAM_ID = 2859 AND VAL = 602) THEN EXCEPTION DATA_ERROR 'В качестве статуса нельзя указывать "работающий сотрудник"';

    -- Нельзя менять значения даты и реквизитов приказа ухода в отпуск, если заполнена дата выхода из отпуска
    IF(PARAM_ID IN (2860, 2863, 2863) AND IS_DEL = 0) THEN
    BEGIN
      SELECT VAL
      FROM VALD V2861
      WHERE V2861.OBJ_ID = :OBJ_ID AND V2861.PARAM_ID = 2861 AND V2861.IS_DEL = 0
      INTO :DATE_OUT;

      IF(DATE_OUT IS NOT NULL) THEN EXCEPTION DATA_ERROR 'Нельзя изменять параметры ухода в отпуск, когда уже заполнена дата возвращения из отпуска';
    END

    -- Дата выхода из отпуска должна быть не ранее даты выхода в отпуск, также для дат приказов
    IF(PARAM_ID IN (2861, 2862, 2864) AND IS_DEL = 0) THEN
    BEGIN
      SELECT V2860.VAL, V2861.VAL, V2862.VAL, V2864.VAL
      FROM OBJECTS OBJ
      LEFT JOIN VALD V2860 ON V2860.OBJ_ID = OBJ.OBJ_ID AND V2860.PARAM_ID = 2860 AND V2860.IS_DEL = 0
      LEFT JOIN VALD V2861 ON V2861.OBJ_ID = OBJ.OBJ_ID AND V2861.PARAM_ID = 2861 AND V2861.IS_DEL = 0
      LEFT JOIN VALD V2862 ON V2862.OBJ_ID = OBJ.OBJ_ID AND V2862.PARAM_ID = 2862 AND V2862.IS_DEL = 0
      LEFT JOIN VALD V2864 ON V2864.OBJ_ID = OBJ.OBJ_ID AND V2864.PARAM_ID = 2864 AND V2864.IS_DEL = 0
      WHERE OBJ.OBJ_ID = :OBJ_ID
      INTO :DATE_IN, :DATE_OUT, :DATE_ORDER_IN, :DATE_ORDER_OUT;

      IF(DATE_IN IS NULL) THEN EXCEPTION DATA_ERROR 'Не введена дата ухода в отпуск';

      IF(PARAM_ID = 2861 AND VAL <= DATE_IN) THEN EXCEPTION DATA_ERROR 'Дата выхода из отпуска должна быть позднее даты ухода в отпуск';
      IF(PARAM_ID = 2861 AND VAL > CURRENT_DATE) THEN EXCEPTION DATA_ERROR 'Нельзя возвращать сотрудника из отпуска ранее фактической даты выхода';
      IF(PARAM_ID = 2862 AND DATE_ORDER_OUT IS NOT NULL AND VAL >= DATE_ORDER_OUT) THEN EXCEPTION DATA_ERROR 'Дата приказа об отпуске должна быть не позднее даты приказа о возвращении из отпуска';
      IF(PARAM_ID = 2864 AND DATE_ORDER_IN IS NOT NULL AND VAL <= DATE_ORDER_IN) THEN EXCEPTION DATA_ERROR 'Дата приказа о возвращении из отпуска должна быть позднее даты приказа об уходе в отпуск';
    END

    -- Осталась маленькая лазейка - можно удалять даты и номера приказов в любых сочетаниях

    -- При изменении статуса или даты выхода из отпуска корректируем статус самого сотрудника
    IF(PARAM_ID = 2859 OR PARAM_ID = 2861) THEN
    BEGIN

        -- ID сотрудника
        SELECT LP14.PARENT_ID
        FROM LINKS LP14
        WHERE LP14.OBJ_ID = :OBJ_ID AND LP14.PARENT_TYPE_ID = 14 AND LP14.DATE_DEL IS NULL
        INTO :PERSON_ID;

        IF(PARAM_ID = 2861 AND IS_DEL = 0) THEN
        BEGIN
            -- Любые изменения делаем только если поле еще не было заполнено !
            N = 0;
            SELECT FIRST 1 1
            FROM VALD V2861
            WHERE V2861.OBJ_ID = :OBJ_ID AND V2861.PARAM_ID = 2861 AND V2861.IS_DEL = 0
            INTO :N;
            IF(N = 1) THEN EXIT;

            -- При вводе даты возвращения выставляем статус "работает"
            -- Проверяем, есть ли достаточное количество ставок на указанную дату по всем должностям
            -- Для обычных должностей
            FOR
                SELECT L15.OBJ_ID, LP13.PARENT_ID, V71.VAL, V62.VAL, C.CAPTION
                FROM LINKS L15
                JOIN VALF V71 ON V71.OBJ_ID = L15.OBJ_ID AND V71.PARAM_ID = 71 AND V71.IS_DEL = 0
                JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
                JOIN VALL V58 ON V58.OBJ_ID = LP13.PARENT_ID AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0
                JOIN VALF V62 ON V62.OBJ_ID = LP13.PARENT_ID AND V62.PARAM_ID = 62 AND V62.IS_DEL = 0
                LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
                LEFT JOIN LISTVALS LV ON LV.LISTVAL_ID = V58.LISTVAL_ID
                LEFT JOIN OBJECT_CAPTION_GET(LP13.PARENT_ID) C ON 1 = 1
                WHERE L15.PARENT_ID = :PERSON_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL AND (LV.TAG IS NULL OR LV.TAG <> 'U' OR LV.LISTVAL_ID = 121)
                    AND (V74.VAL IS NULL OR V74.VAL > CURRENT_DATE)
                INTO :ASSN_ID, :VAC_ID, :VAC_RATE, :AVAIL_RATE, :VAC_NAME
            DO
            BEGIN
                -- Сколько ставок занято сотрудниками, не находящимися в отпусках
                USED_RATE = (SELECT VAL FROM VACANCY_NUM_OCCUPIED(:VAC_ID));
                IF(VAC_RATE > (AVAIL_RATE - USED_RATE)) THEN
                BEGIN
                  -- Не ругаемся, иначе проблемы с импортом
                  -- Должно быть предупреждение на фронте !
                  -- EXCEPTION DATA_ERROR 'По должности "' || VAC_NAME || '" требуется ' || CAST(VAC_RATE AS NUMERIC(18, 2)) || ' ставок, доступно ' ||
                  --    CAST((AVAIL_RATE - USED_RATE) AS NUMERIC(18, 2));
                END
            END

            -- Для учительских должностей
            TEACHERS_RATE = 0;
            SELECT SUM(V71.VAL)
            FROM LINKS L15
            JOIN VALF V71 ON V71.OBJ_ID = L15.OBJ_ID AND V71.PARAM_ID = 71 AND V71.IS_DEL = 0
            JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
            JOIN VALL V58 ON V58.OBJ_ID = LP13.PARENT_ID AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0
            JOIN LISTVALS LV ON LV.LISTVAL_ID = V58.LISTVAL_ID AND LV.TAG = 'U' AND LV.LISTVAL_ID <> 121
            LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
            WHERE L15.PARENT_ID = :PERSON_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
                AND (V74.VAL IS NULL OR V74.VAL > CURRENT_DATE)
            INTO :TEACHERS_RATE;

            IF(TEACHERS_RATE > 0) THEN
            BEGIN
            END

            -- Все окей
            SELECT BLOB_ID FROM VAL_ADD(274, :PERSON_ID, 602) INTO :PERSON_ID;
        END
        ELSE
        BEGIN
            -- В прочих случаях выставляем указанный в отпуске статус
            IF(PARAM_ID = 2859) THEN STATUS_LV = CAST(VAL AS BIGINT);
            ELSE
            BEGIN
                SELECT LISTVAL_ID
                FROM VALL V2859
                WHERE V2859.OBJ_ID = :OBJ_ID AND V2859.PARAM_ID = 2859 AND V2859.IS_DEL = 0
                INTO :STATUS_LV;
                IF(STATUS_LV IS NULL) THEN EXCEPTION DATA_ERROR 'Не указан статус сотрудника';
            END
            SELECT BLOB_ID FROM VAL_ADD(274, :PERSON_ID, :STATUS_LV) INTO :PERSON_ID;
        END

    END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LONGVACATION_DELETE (
    OBJ_ID BIGINT)
AS
declare variable N integer;
declare variable TMP bigint;
declare variable PERSON_ID bigint;
begin

    -- Удалять можно только последнюю по хронологии запись
    N = 0;
    SELECT FIRST 1 1
    FROM LINKS L376
    JOIN LINKS L376_NEXT ON L376_NEXT.PARENT_ID = L376.PARENT_ID AND L376_NEXT.OBJ_TYPE_ID = 376 AND L376_NEXT.DATE_DEL IS NULL AND L376_NEXT.LINK_ID > L376.LINK_ID
    WHERE L376.OBJ_ID = :OBJ_ID AND L376.PARENT_TYPE_ID = 14 AND L376.DATE_DEL IS NULL
    INTO :N;

    IF(N > 0) THEN EXCEPTION DATA_ERROR 'Можно удалять только последнюю запись длительного отпуска';

    -- После удаления ставим статус 'работающий' у сотрудника, кроме случая когда сотрудник удален
    SELECT L376.PARENT_ID
    FROM LINKS L376
    WHERE L376.OBJ_ID = :OBJ_ID AND L376.PARENT_TYPE_ID = 14 AND L376.DATE_DEL IS NULL
    INTO :PERSON_ID;

    SELECT BLOB_ID FROM VAL_ADD(274, :PERSON_ID, 602) INTO :TMP;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LPARAMS_LIST (
    I$LEVEL_ID BIGINT,
    I$TYPE_ID BIGINT,
    I$LANG_CODE VARCHAR(2) = 'RU',
    I$USER_ID BIGINT = 1)
RETURNS (
    LEVEL_ID BIGINT,
    PARAM_ID BIGINT,
    TAB_ID BIGINT,
    PARAM_CAPTION VARCHAR(4000),
    EDIT_TYPE SMALLINT,
    PARAM_TYPE SMALLINT,
    BKG_COLOR INTEGER,
    IS_TREEVIEW SMALLINT)
AS
declare variable V$RES_ID bigint;
declare variable READ_ONLY bigint;
BEGIN
    LEVEL_ID = I$LEVEL_ID;
    READ_ONLY = 0;

    IF ((I$LEVEL_ID IS NOT NULL) AND (I$TYPE_ID IS NOT NULL)) THEN
    BEGIN
        SELECT FIRST 1 L.READ_ONLY
        FROM LUSERS L
        WHERE L.LEVEL_ID = :I$LEVEL_ID
          AND L.USER_ID = :I$USER_ID
        INTO :READ_ONLY;

        FOR SELECT P.PARAM_ID, P.RES_ID, P.TAB_ID, COALESCE(L.EDIT_TYPE, -1), PT.BKG_COLOR, P.PARAM_TYPE, P.IS_TREEVIEW
            FROM PARAMS P
            INNER JOIN PARAMTYPES PT ON PT.PARAM_TYPE = P.PARAM_TYPE
            LEFT JOIN TABS T ON T.TAB_ID = P.TAB_ID
            LEFT JOIN LPARAMS L ON L.LEVEL_ID = :I$LEVEL_ID AND L.PARAM_ID = P.PARAM_ID
            WHERE P.TYPE_ID = :I$TYPE_ID
              AND P.IS_DEL = 0
            ORDER BY T.TAB_NUM, P.GRID_ORDER
            INTO :PARAM_ID, :V$RES_ID, :TAB_ID, :EDIT_TYPE, :BKG_COLOR, :PARAM_TYPE, :IS_TREEVIEW
        DO
        BEGIN
            SELECT VAL
            FROM RES_GET(:V$RES_ID, :I$LANG_CODE)
            INTO :PARAM_CAPTION;

            IF ((READ_ONLY = 1) AND (EDIT_TYPE > 0)) THEN EDIT_TYPE = 0;

            SUSPEND;
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LPARAM_ADD (
    I$LEVEL_ID BIGINT,
    I$PARAM_ID BIGINT,
    I$EDIT_TYPE SMALLINT)
AS
DECLARE VARIABLE IS_DEL SMALLINT = 0;
BEGIN
    IF (I$EDIT_TYPE < 0) THEN IS_DEL = 1;

    UPDATE OR INSERT INTO LPARAMS (LEVEL_ID, PARAM_ID, EDIT_TYPE, IS_DEL)
    VALUES (:I$LEVEL_ID, :I$PARAM_ID, :I$EDIT_TYPE, :IS_DEL);
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LREPORTS_LIST (
    I$LEVEL_ID BIGINT,
    I$TYPE_ID BIGINT,
    I$LANG_CODE VARCHAR(2) = 'RU')
RETURNS (
    REPORT_ID BIGINT,
    REPORT_CAPTION VARCHAR(4000),
    IS_USED SMALLINT,
    GROUP_CAPTION VARCHAR(100))
AS
declare variable V$RES_ID bigint;
BEGIN
    FOR
        SELECT P.REPORT_ID,
               P.RES_ID,
               L.GROUP_NAME,
               L.IS_DEL
        FROM REPORTS P
        LEFT JOIN LREPORTS L
        ON L.LEVEL_ID = :I$LEVEL_ID
        AND L.REPORT_ID = P.REPORT_ID
        WHERE P.TYPE_ID = :I$TYPE_ID
        AND P.IS_DEL = 0
        INTO   :REPORT_ID,
               :V$RES_ID,
               :GROUP_CAPTION,
               :IS_USED
    DO
    BEGIN
        IF (IS_USED = 1 OR IS_USED IS NULL) THEN
        BEGIN
            IS_USED = 0;
        END
        ELSE
        BEGIN
            IS_USED = 1;
        END
        SELECT VAL FROM RES_GET(:V$RES_ID, :I$LANG_CODE) INTO :REPORT_CAPTION;
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LREPORT_ADD (
    I$LEVEL_ID BIGINT,
    I$REPORT_ID BIGINT,
    I$IS_USED SMALLINT,
    I$GROUP_NAME VARCHAR(100))
AS
BEGIN
    IF (I$IS_USED = 1) THEN
    BEGIN
        I$IS_USED = 0;
    END
    ELSE
    BEGIN
        I$IS_USED = 1;
    END
    UPDATE OR INSERT
    INTO LREPORTS (
                   LEVEL_ID,
                   REPORT_ID,
                   IS_DEL,
                   GROUP_NAME
                  )
           VALUES (
                   :I$LEVEL_ID,
                   :I$REPORT_ID,
                   :I$IS_USED,
                   :I$GROUP_NAME
                  );
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LTYPES_LIST (
    I$LEVEL_ID BIGINT,
    I$LANG_CODE VARCHAR(2) = 'RU')
RETURNS (
    LEVEL_ID BIGINT,
    TYPE_ID BIGINT,
    COLOR INTEGER,
    RES_ID BIGINT,
    TYPE_CAPTION VARCHAR(4000),
    EDIT_TYPE SMALLINT,
    SHOW_DEL SMALLINT,
    BAR_ID BIGINT)
AS
declare variable V$IS_HIDDEN smallint;
BEGIN
    LEVEL_ID = I$LEVEL_ID;
    IF (I$LEVEL_ID IS NOT NULL) THEN
    BEGIN
        FOR
            SELECT T.TYPE_ID,
                   T.COLOR,
                   T.RES_ID,
                   T.IS_HIDDEN,
                   COALESCE(L.EDIT_TYPE, -1),
                   COALESCE(L.SHOW_DEL, 0),
                   BAR_ID
            FROM TYPES T
            LEFT JOIN LTYPES L
            ON L.LEVEL_ID = :I$LEVEL_ID
            AND L.TYPE_ID = T.TYPE_ID
            AND T.IS_DEL  = 0
            ORDER BY T.SORT_ORDER
            INTO   :TYPE_ID,
                   :COLOR,
                   :RES_ID,
                   :V$IS_HIDDEN,
                   :EDIT_TYPE,
                   :SHOW_DEL,
                   :BAR_ID
        DO
        BEGIN
            SELECT VAL
            FROM RES_GET(:RES_ID, :I$LANG_CODE)
            INTO   :TYPE_CAPTION;
            if (V$IS_HIDDEN = 1) then
            begin
                TYPE_CAPTION = TYPE_CAPTION || ' [hidden]';
            end
            SUSPEND;
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LTYPE_ADD (
    I$LEVEL_ID BIGINT,
    I$TYPE_ID BIGINT,
    I$EDIT_TYPE SMALLINT,
    I$SHOW_DEL SMALLINT,
    I$BAR_ID BIGINT = NULL)
AS
DECLARE VARIABLE IS_DEL SMALLINT = 0;
BEGIN
    IF (I$EDIT_TYPE < 0) THEN IS_DEL = 1;

    UPDATE OR INSERT INTO LTYPES(LEVEL_ID, TYPE_ID, EDIT_TYPE, SHOW_DEL, BAR_ID, IS_DEL)
    VALUES (:I$LEVEL_ID, :I$TYPE_ID, :I$EDIT_TYPE, :I$SHOW_DEL, :I$BAR_ID, :IS_DEL);
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LUSERS_LIST (
    I$USER_ID BIGINT,
    I$LANG_CODE CHAR(2) = 'RU')
RETURNS (
    ID SMALLINT,
    PARENT_ID SMALLINT,
    IS_CHECKED SMALLINT,
    LEVEL_ID BIGINT,
    USER_ID BIGINT,
    ROOT_TYPE_ID BIGINT,
    PARENT_TYPE_ID BIGINT,
    ROOT_OBJ_ID BIGINT,
    ROOT_PARENT_ID BIGINT,
    CAPTION VARCHAR(4000),
    ROOT_OBJ_CAPTION VARCHAR(4000),
    ROOT_PARENT_CAPTION VARCHAR(4000),
    LEVEL_RULES VARCHAR(400))
AS
DECLARE VARIABLE MODULE_ID BIGINT;
DECLARE VARIABLE TASK_ID BIGINT;
DECLARE VARIABLE RES_ID BIGINT;
DECLARE VARIABLE I SMALLINT;
DECLARE VARIABLE J SMALLINT;
DECLARE VARIABLE K SMALLINT;
DECLARE VARIABLE C INTEGER;
BEGIN
    I = 0;
    FOR
        SELECT MODULE_ID,
               RES_ID
        FROM MODULES
        WHERE IS_ACTIVE = 1
        AND IS_DEL = 0
        ORDER BY SORT_ORDER
        INTO   :MODULE_ID,
               :RES_ID
    DO
    BEGIN
        I = I + 1;

        ID = I;
        PARENT_ID = NULL;
        IS_CHECKED = NULL;
        LEVEL_ID = NULL;
        USER_ID = NULL;
        ROOT_TYPE_ID = NULL;
        PARENT_TYPE_ID = NULL;
        ROOT_OBJ_ID = NULL;
        ROOT_PARENT_ID = NULL;
        ROOT_OBJ_CAPTION = NULL;
        ROOT_PARENT_CAPTION = NULL;

        SELECT VAL FROM RES_GET(:RES_ID, :I$LANG_CODE) INTO :CAPTION;

        C = 0;

        SELECT COUNT(T.TASK_ID)
        FROM TASKS T
        INNER JOIN LEVELS L
        ON L.TASK_ID = T.TASK_ID
        WHERE T.MODULE_ID = :MODULE_ID
        AND T.IS_DEL = 0
        AND L.IS_DEL = 0
        INTO :C;

        IF (C > 0) THEN
        BEGIN
            SUSPEND;

            /* TASK */
            K = I;

            FOR
                SELECT TASK_ID,
                       RES_ID
                FROM TASKS
                WHERE MODULE_ID = :MODULE_ID
                AND IS_DEL = 0
                ORDER BY SORT_ORDER
                INTO :TASK_ID, :RES_ID
            DO
            BEGIN
                K = K + 1;

                ID = K;
                PARENT_ID = I;
               /* IS_CHECKED = NULL;
                LEVEL_ID = NULL;
                USER_ID = NULL;
                ROOT_TYPE_ID = NULL;
                PARENT_TYPE_ID = NULL;
                ROOT_OBJ_ID = NULL;
                ROOT_PARENT_ID = NULL;
                ROOT_OBJ_CAPTION = NULL;
                ROOT_PARENT_CAPTION = NULL;      */

                SELECT VAL FROM RES_GET(:RES_ID, :I$LANG_CODE) INTO :CAPTION;

                C = 0;

                SELECT COUNT(*)
                FROM LEVELS
                WHERE TASK_ID = :TASK_ID
                AND IS_DEL = 0
                INTO :C;

                IF (C > 0) THEN
                BEGIN




                    /* LEVEL */

                    J = K;

                    FOR
                        SELECT LEVEL_ID,
                               RES_ID,
                               ROOT_TYPE_ID,
                               PARENT_TYPE_ID
                        FROM LEVELS
                        WHERE TASK_ID = :TASK_ID
                        AND IS_DEL = 0
                        ORDER BY SORT_ORDER
                        INTO   :LEVEL_ID,
                               :RES_ID,
                               :ROOT_TYPE_ID,
                               :PARENT_TYPE_ID

                    DO
                    BEGIN
                        J = J + 1;
                        ID = J;
                        --  PARENT_ID = K;
                        USER_ID = I$USER_ID;

                        IS_CHECKED = 0;

                        ROOT_OBJ_ID = NULL;
                        ROOT_PARENT_ID = NULL;
                        ROOT_OBJ_CAPTION = NULL;
                        ROOT_PARENT_CAPTION = NULL;

                        SELECT 1,
                               ROOT_OBJ_ID,
                               ROOT_PARENT_ID
                        FROM LUSERS
                        WHERE LEVEL_ID = :LEVEL_ID
                        AND USER_ID = :USER_ID
                        INTO   :IS_CHECKED,
                               :ROOT_OBJ_ID,
                               :ROOT_PARENT_ID;

                        IF (ROOT_OBJ_ID IS NOT NULL) THEN
                        BEGIN
                            SELECT CAPTION
                            FROM OBJECT_CAPTION_GET(:ROOT_OBJ_ID)
                            INTO   :ROOT_OBJ_CAPTION;
                        END
                        IF (ROOT_PARENT_ID IS NOT NULL) THEN
                        BEGIN
                            SELECT CAPTION
                            FROM OBJECT_CAPTION_GET(:ROOT_PARENT_ID)
                            INTO   :ROOT_PARENT_CAPTION;
                        END

                        SELECT VAL FROM RES_GET(:RES_ID, :I$LANG_CODE) INTO :LEVEL_RULES;
                        SUSPEND;

                    END
                    K = J;

                END

            END
            I = K;

        END

    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LUSERS_ROOT (
    I$TYPE_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    CAPTION VARCHAR(4000),
    SORT_ORDER DOUBLE PRECISION)
AS
BEGIN
    FOR SELECT DISTINCT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = :I$TYPE_ID
          AND L.DATE_DEL IS NULL
        INTO :OBJ_ID
    DO
    BEGIN
        SELECT CAPTION, SORT_ORDER
        FROM OBJECT_CAPTION_GET(:OBJ_ID)
        INTO :CAPTION, :SORT_ORDER;

        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE LUSER_ADD (
    I$LEVEL_ID BIGINT,
    I$USER_ID BIGINT,
    I$IS_CHECKED SMALLINT = 1,
    I$ROOT_OBJ_ID BIGINT = NULL,
    I$ROOT_PARENT_ID BIGINT = NULL)
AS
BEGIN
    IF (I$IS_CHECKED = 1) THEN BEGIN
        UPDATE OR INSERT INTO LUSERS (LEVEL_ID, USER_ID, ROOT_OBJ_ID, ROOT_PARENT_ID)
        VALUES (:I$LEVEL_ID, :I$USER_ID, :I$ROOT_OBJ_ID, :I$ROOT_PARENT_ID);
    END ELSE BEGIN
        DELETE FROM LUSERS
        WHERE LEVEL_ID = :I$LEVEL_ID AND USER_ID = :I$USER_ID;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE MASK_MATCH (
    I$MASK BIGINT,
    I$VALUE INTEGER)
RETURNS (
    RESULT SMALLINT)
AS
declare variable V$MASK bigint;
begin

  V$MASK = BIN_SHL(1, I$VALUE);
  V$MASK = BIN_AND(I$MASK, V$MASK);

  IF(V$MASK = 0) THEN RESULT = 0; ELSE RESULT = 1;
  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE MCAL_HANDLE_EDULOAD (
    I$OBJ_ID BIGINT,
    I$ZONE SMALLINT,
    I$USER_ID VARCHAR(40))
AS
DECLARE VARIABLE V$ROLE SMALLINT;
DECLARE VARIABLE V$PERSON_ID BIGINT;
DECLARE VARIABLE V$PERSON_TYPE BIGINT;
DECLARE VARIABLE V$OU_ID BIGINT;
DECLARE VARIABLE V$YEAR_ID BIGINT;
DECLARE VARIABLE V$OBJ_ID BIGINT;
begin

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  SELECT FIRST 1 U.USER_TYPE, U.OBJ_ID, O.TYPE_ID
  FROM USERS U
  LEFT JOIN OBJECTS O ON O.OBJ_ID = U.OBJ_ID
  WHERE U.USER_ID = :I$USER_ID AND U.DATE_DEL IS NULL AND U.IS_BLOCKED = 0 AND (U.EXP_DATE IS NULL OR U.EXP_DATE > CURRENT_DATE)
  INTO :V$ROLE, :V$PERSON_ID, :V$PERSON_TYPE;

  IF(V$ROLE IS NULL) THEN EXCEPTION DATA_ERROR 'Пользователь не найден';
  IF(V$PERSON_TYPE <> 14) THEN EXCEPTION DATA_ERROR 'Пользователь не является сотрудником';

  SELECT FIRST 1 L2.OBJ_ID, V1236.LISTVAL_ID
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$OU_ID, :V$YEAR_ID;

  SELECT FIRST 1 L531.OBJ_ID
  FROM LINKS L527
  JOIN LINKS L531 ON L531.PARENT_ID = L527.OBJ_ID AND L531.OBJ_TYPE_ID = 531 AND L531.DATE_DEL IS NULL AND L531.OBJ_ID = :I$OBJ_ID
  JOIN VALL V3568 ON V3568.OBJ_ID = L531.OBJ_ID AND V3568.PARAM_ID = 3568 AND V3568.IS_DEL = 0 AND V3568.LISTVAL_ID = 11715 -- действующий
  JOIN VALL V3567 ON V3567.OBJ_ID = L531.OBJ_ID AND V3567.PARAM_ID = 3567 AND V3567.IS_DEL = 0 AND V3567.LISTVAL_ID >= :V$YEAR_ID
  JOIN EDULOAD_DATA D ON D.PARENT_ID = L531.OBJ_ID AND D.PERSON_ID = :V$PERSON_ID AND D.VERIFIED = 0
  WHERE L527.PARENT_ID = :V$OU_ID AND L527.OBJ_TYPE_ID = 527 AND L527.DATE_DEL IS NULL
  INTO :V$OBJ_ID;

  IF(V$OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Все нагрузки уже согласованы';

  UPDATE EDULOAD_DATA
  SET VERIFIED = 1
  WHERE DATE_DEL IS NULL AND VERIFIED = 0 AND PARENT_ID = :I$OBJ_ID AND PERSON_ID = :V$PERSON_ID;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE MCAL_HANDLE_GIA (
    I$OBJ_ID BIGINT,
    I$ZONE SMALLINT,
    I$USER_ID VARCHAR(40))
AS
DECLARE VARIABLE V$PERSON_ID BIGINT;
DECLARE VARIABLE V$OU_ID BIGINT;
DECLARE VARIABLE V$YEAR_ID BIGINT;
DECLARE VARIABLE V$GRADE_ID BIGINT;
DECLARE VARIABLE V$GIA_TYPE BIGINT;
DECLARE VARIABLE V$GIA_STATE BIGINT;
DECLARE VARIABLE V$DATE DATE;
DECLARE VARIABLE V$EXAM_FOLDER BIGINT;
DECLARE VARIABLE V$SELECTION VARCHAR(2000);
DECLARE VARIABLE V$DST VARCHAR(2000);
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$SUBJECT_ID BIGINT;
begin

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  SELECT FIRST 1 U.OBJ_ID, LP9.PARENT_ID, V2388.LISTVAL_ID
  FROM USERS U
  JOIN LINKS LP9 ON LP9.OBJ_TYPE_ID = 10 AND LP9.OBJ_ID = U.OBJ_ID AND LP9.PARENT_TYPE_ID IN (9, 125, 187) AND LP9.DATE_DEL IS NULL
  JOIN VALL V2388 ON V2388.OBJ_ID = LP9.PARENT_ID AND V2388.PARAM_ID IN (2388, 2418, 2419) AND V2388.IS_DEL = 0
  WHERE U.USER_ID = :I$USER_ID AND U.DATE_DEL IS NULL
  INTO :V$PERSON_ID, :V$GRADE_ID, :V$GIA_TYPE;

  IF(V$PERSON_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Пользователь не найден или не является обучающимся';

  -- I$OBJ_ID > 0 - выбор конкретного экзамена
  -- < 0 - снятие выбора по данному предмету

  SELECT FIRST 1 V1236.LISTVAL_ID, CAST(LV.TAG AS DATE), V3598.LISTVAL_ID
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  LEFT JOIN VALL V3598 ON V3598.OBJ_ID = L2.OBJ_ID AND V3598.PARAM_ID = 3598 AND V3598.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$YEAR_ID, :V$DATE, :V$GIA_STATE;

  SELECT FIRST 1 L119.OBJ_ID
  FROM LINKS L119
  JOIN VALL V742 ON V742.OBJ_ID = L119.OBJ_ID AND V742.PARAM_ID = 742 AND V742.IS_DEL = 0 AND V742.LISTVAL_ID = :V$YEAR_ID
  WHERE L119.PARENT_ID = 3866 AND L119.OBJ_TYPE_ID = 119 AND L119.DATE_DEL IS NULL
  INTO :V$EXAM_FOLDER;

  IF(V$EXAM_FOLDER IS NULL) THEN EXCEPTION DATA_ERROR 'Расписание экзаменов еще не загружено';

  -- Выбор грузим только сделанный не ранее начала учебного года
  SELECT FIRST 1 V.VAL
  FROM VALS V
  WHERE V.OBJ_ID = :V$PERSON_ID AND V.PARAM_ID = 3596 AND V.IS_DEL = 0 AND V.DATE_MODIFY >= :V$DATE
  INTO :V$SELECTION;

  -- Скидываем старый выбор экзаменов
  IF(V$SELECTION IS NULL) THEN V$SELECTION = '';
  V$SELECTION = REPLACE(V$SELECTION, ';', ',');

  IF(V$GIA_TYPE = 11202) THEN V$GIA_TYPE = 3000; -- ГИА-9
  IF(V$GIA_TYPE = 11203) THEN V$GIA_TYPE = 3162; -- ГИА-11

  IF(V$GIA_STATE IS NULL OR V$GIA_STATE <> 18744) THEN EXCEPTION DATA_ERROR 'Статус записи на ГИА не позволяет вам вносить изменения';

  V$DST = '';
  IF(I$OBJ_ID >= 0) THEN
  BEGIN
    -- Новый выбор по предмету
    SELECT FIRST 1 V803.LISTVAL_ID
    FROM LINKS L120
    JOIN VALL V801 ON V801.OBJ_ID = L120.OBJ_ID AND V801.PARAM_ID = 801 AND V801.IS_DEL = 0 AND V801.LISTVAL_ID = :V$GIA_TYPE
    JOIN VALL V803 ON V803.OBJ_ID = L120.OBJ_ID AND V803.PARAM_ID = 803 AND V803.IS_DEL = 0
    WHERE L120.OBJ_ID = :I$OBJ_ID AND L120.OBJ_TYPE_ID = 120 AND L120.PARENT_ID = :V$EXAM_FOLDER AND L120.DATE_DEL IS NULL
    INTO :V$SUBJECT_ID;

    IF(V$SUBJECT_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Запись выбранного экзамена не найдена';

    -- Убираем ссылки на тот же предмет
    FOR
      SELECT S.ID
      FROM STR_TO_ID_LIST(:V$SELECTION) S
      JOIN LINKS L120 ON L120.OBJ_ID = S.ID AND L120.PARENT_ID = :V$EXAM_FOLDER AND L120.DATE_DEL IS NULL
      JOIN VALL V801 ON V801.OBJ_ID = L120.OBJ_ID AND V801.PARAM_ID = 801 AND V801.IS_DEL = 0 AND V801.LISTVAL_ID = :V$GIA_TYPE
      -- Исключаем из выбора указанный предмет
      JOIN VALL V803 ON V803.OBJ_ID = L120.OBJ_ID AND V803.PARAM_ID = 803 AND V803.IS_DEL = 0 AND V803.LISTVAL_ID <> :V$SUBJECT_ID
      INTO :V$OBJ_ID
    DO
    BEGIN
      IF(V$DST <> '') THEN V$DST = V$DST || ',';
      V$DST = V$DST || V$OBJ_ID;
    END

    IF(V$DST <> '') THEN V$DST = V$DST || ',';
    V$DST = V$DST || I$OBJ_ID;
  END
  ELSE
  BEGIN
    -- Снимаем выбор по предмету
    I$OBJ_ID = -I$OBJ_ID;
    FOR
      SELECT S.ID
      FROM STR_TO_ID_LIST(:V$SELECTION) S
      JOIN LINKS L120 ON L120.OBJ_ID = S.ID AND L120.PARENT_ID = :V$EXAM_FOLDER AND L120.DATE_DEL IS NULL
      JOIN VALL V801 ON V801.OBJ_ID = L120.OBJ_ID AND V801.PARAM_ID = 801 AND V801.IS_DEL = 0 AND V801.LISTVAL_ID = :V$GIA_TYPE
      -- Исключаем из выбора указанный предмет
      JOIN VALL V803 ON V803.OBJ_ID = L120.OBJ_ID AND V803.PARAM_ID = 803 AND V803.IS_DEL = 0 AND V803.LISTVAL_ID <> :I$OBJ_ID
      INTO :V$OBJ_ID
    DO
    BEGIN
      IF(V$DST <> '') THEN V$DST = V$DST || ',';
      V$DST = V$DST || V$OBJ_ID;
    END
  END

  IF(V$DST <> V$SELECTION) THEN
  BEGIN
    SELECT 1 FROM VAL_ADD(3596, :V$PERSON_ID, :V$DST) INTO :V$OBJ_ID;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE MCAL_LIST (
    I$DATE_FROM DATE,
    I$DATE_TO DATE,
    I$ZONE SMALLINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$OU_ID BIGINT;
DECLARE VARIABLE V$YEAR_ID BIGINT;
DECLARE VARIABLE V$YEAR_DATE DATE;
DECLARE VARIABLE V$PERSON_ID BIGINT;
DECLARE VARIABLE V$PERSON_TYPE BIGINT;
DECLARE VARIABLE V$ROLE SMALLINT;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$PERIOD_ID BIGINT;
DECLARE VARIABLE V$RANGE_ID BIGINT;
DECLARE VARIABLE V$DATE DATE;
DECLARE VARIABLE V$DATE2 DATE;
DECLARE VARIABLE V$PD DATE;
DECLARE VARIABLE V$N INTEGER;
DECLARE VARIABLE V$F INTEGER;
DECLARE VARIABLE S VARCHAR(1000);
DECLARE VARIABLE S2 VARCHAR(400);
begin

  SELECT FIRST 1 L2.OBJ_ID, V1236.LISTVAL_ID, CAST(LV.TAG AS DATE)
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$OU_ID, :V$YEAR_ID, :V$YEAR_DATE;

  -- IF(V$YEAR_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Нет данных по текущему учебного году, настройте текущий учебный год';

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  SELECT FIRST 1 U.USER_TYPE, U.OBJ_ID, O.TYPE_ID
  FROM USERS U
  LEFT JOIN OBJECTS O ON O.OBJ_ID = U.OBJ_ID
  WHERE U.USER_ID = :I$USER_ID AND U.DATE_DEL IS NULL AND U.IS_BLOCKED = 0 AND (U.EXP_DATE IS NULL OR U.EXP_DATE > CURRENT_DATE)
  INTO :V$ROLE, :V$PERSON_ID, :V$PERSON_TYPE;

  IF(V$ROLE IS NULL) THEN EXCEPTION DATA_ERROR 'Пользователь не найден';

  TAG_NAME = 'year_start';
  VAL = (SELECT VAL FROM DATE2ISO(:V$YEAR_DATE, 0));
  SUSPEND;

  IF(I$DATE_FROM IS NULL) THEN
  BEGIN
    I$DATE_FROM = '1.' || EXTRACT(MONTH FROM CURRENT_DATE) || '.' || EXTRACT(YEAR FROM CURRENT_DATE);
    I$DATE_FROM = DATEADD(-1 MONTH TO I$DATE_FROM);
  END
  -- Не даем запрашивать слишком старые данные и слишком новые данные
  IF(I$DATE_FROM < DATEADD(-1 MONTH TO V$YEAR_DATE)) THEN I$DATE_FROM = DATEADD(-1 MONTH TO V$YEAR_DATE);
  IF(I$DATE_FROM > DATEADD(13 MONTH TO V$YEAR_DATE)) THEN I$DATE_FROM = DATEADD(13 MONTH TO V$YEAR_DATE);
  IF(I$DATE_TO IS NULL) THEN I$DATE_TO = DATEADD(2 MONTH TO I$DATE_FROM);
  -- Не даем запрашивать слишком большой пул данных
  IF(I$DATE_TO > DATEADD(3 MONTH TO I$DATE_FROM)) THEN I$DATE_TO = DATEADD(3 MONTH TO I$DATE_FROM);
  -- Даты у нас включительно
  I$DATE_TO = DATEADD(-1 DAY TO I$DATE_TO);

  TAG_NAME = 'date_from';
  VAL = (SELECT VAL FROM DATE2ISO(:I$DATE_FROM, 0));
  SUSPEND;

  TAG_NAME = 'date_to';
  VAL = (SELECT VAL FROM DATE2ISO(:I$DATE_TO, 0));
  SUSPEND;

  -- Дни рождения. При доступе из черной зоны показываем алиасы
  -- Директор и завуч видит дни рождения всех учителей, учитель только дни рождения директора и завучей, ученик - дни рождения учителей
  -- А также дни рождения учеников своего класса и классов, где преподает
  TAG_NAME = 'birthdays::json&colon;array';
  VAL = 1;
  SUSPEND;
  -- Сотрудники
  FOR
    SELECT DISTINCT L14.OBJ_ID, V241.VAL
    FROM LINKS L14
    JOIN VALD V241 ON V241.OBJ_ID = L14.OBJ_ID AND V241.PARAM_ID = 241 AND V241.IS_DEL = 0
      AND EXTRACT(MONTH FROM V241.VAL) >= EXTRACT(MONTH FROM :I$DATE_FROM) AND EXTRACT(MONTH FROM V241.VAL) <= EXTRACT(MONTH FROM :I$DATE_TO)
    JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
    JOIN VALL V1399 ON V1399.OBJ_ID = L15.OBJ_ID AND V1399.PARAM_ID = 1399 AND V1399.IS_DEL = 0 -- подгруппа должностей
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
    WHERE L14.PARENT_ID = :V$OU_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL AND V74.VAL IS NULL
      AND (:V$ROLE IN (1, 5, 6) OR (:V$ROLE IN (7, 8, 9, 11, 16, 17, 18, 20) AND V1399.LISTVAL_ID IN (56, 113)))
      AND :V$PERSON_TYPE = 14
    ORDER BY V241.VAL
    INTO :V$OBJ_ID, :V$DATE
  DO
  BEGIN
    TAG_NAME = 'birthdays:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'birthdays:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'birthdays:r:date';
    VAL = SUBSTRING((SELECT VAL FROM DATE2ISO(:V$DATE, 0)) FROM 6);
    SUSPEND;
    TAG_NAME = 'birthdays:r:name';
    IF(I$ZONE = 1) THEN
    BEGIN
      VAL = NULL;
      SELECT FIRST 1 R.VAL
      FROM LINKS L15
      JOIN VALL V1394 ON V1394.OBJ_ID = L15.OBJ_ID AND V1394.PARAM_ID = 1394 AND V1394.IS_DEL = 0
      JOIN LISTVALS LV ON LV.LISTVAL_ID = V1394.LISTVAL_ID
      JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
      LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
      WHERE L15.PARENT_ID = :V$OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL AND V74.VAL IS NULL
      ORDER BY LV.SORT_ORDER
      INTO :VAL;
    END
    ELSE
    BEGIN
      VAL = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$OBJ_ID));
    END
    SUSPEND;
  END

  -- Ученики моих классов и групп, в том числе непосредственно классов где я = классный руководитель
  FOR
    SELECT DISTINCT L10.OBJ_ID, V89.VAL
    FROM LINKS L9
    JOIN VALR V53 ON V53.OBJ_ID = L9.OBJ_ID AND V53.PARAM_ID = 53 AND V53.IS_DEL = 0 AND V53.VAL = :V$PERSON_ID
    JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    JOIN VALD V89 ON V89.OBJ_ID = L10.OBJ_ID AND V89.PARAM_ID = 89 AND V89.IS_DEL = 0
      AND EXTRACT(MONTH FROM V89.VAL) >= EXTRACT(MONTH FROM :I$DATE_FROM) AND EXTRACT(MONTH FROM V89.VAL) <= EXTRACT(MONTH FROM :I$DATE_TO)
    WHERE L9.PARENT_TYPE_ID = 8 AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL AND :V$PERSON_TYPE = 14
    /*SELECT
    FROM CJ2_JOURNAL J
    WHERE J.DATE_DEL IS NULL AND J.TEACHER_ID = :V$PERSON_ID*/
    ORDER BY 2
    INTO :V$OBJ_ID, :V$DATE
  DO
  BEGIN
    TAG_NAME = 'birthdays:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'birthdays:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'birthdays:r:date';
    VAL = SUBSTRING((SELECT VAL FROM DATE2ISO(:V$DATE, 0)) FROM 6);
    SUSPEND;
    TAG_NAME = 'birthdays:r:name';
    IF(I$ZONE = 1) THEN
    BEGIN
      VAL = (SELECT V FROM VAL_GET(:V$OBJ_ID, 2991));
    END
    ELSE
    BEGIN
      VAL = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$OBJ_ID, 23));
    END
    SUSPEND;
  END

  -- Выходные и праздничные дни, тут же выдаем методические дни
  TAG_NAME = 'events::json&colon;array';
  VAL = 1;
  SUSPEND;

  -- Методические дни
  IF(V$PERSON_TYPE = 14) THEN
  BEGIN
    TAG_NAME = 'events:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'events:r:id';
    VAL = 'md';
    SUSPEND;
    TAG_NAME = 'events:r:type';
    VAL = 'md';
    SUSPEND;
    TAG_NAME = 'events:r:value';
    VAL = (SELECT V FROM VAL_GET(:V$PERSON_ID, 3065));
    SUSPEND;
  END

  -- Каникулы
  -- Пересекаем непересекающиеся комбинации дат
  FOR
    SELECT DISTINCT J.PERIOD_ID
    FROM CJ2_JOURNAL J
    WHERE J.DATE_DEL IS NULL AND J.YEAR_ID = :V$YEAR_ID AND J.PERIOD_ID IS NOT NULL AND J.TEACHER_ID = :V$PERSON_ID AND :V$PERSON_TYPE = 14
    UNION
    SELECT FIRST 1 J.PERIOD_ID
    FROM PERSON_MOVEMENTS M
    JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.GRADE_ID = M.GROUP_ID
    WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :V$PERSON_ID AND M.DATE_IN <= :I$DATE_TO AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :I$DATE_FROM) AND :V$PERSON_TYPE = 10
    INTO :V$PERIOD_ID
  DO
  BEGIN
    V$PD = NULL;
    FOR
      SELECT L4.OBJ_ID, V39.VAL, V40.VAL
      FROM LINKS L4
      JOIN VALD V39 ON V39.OBJ_ID = L4.OBJ_ID AND V39.PARAM_ID = 39 AND V39.IS_DEL = 0
      JOIN VALD V40 ON V40.OBJ_ID = L4.OBJ_ID AND V40.PARAM_ID = 40 AND V40.IS_DEL = 0 AND V40.VAL > V39.VAL
      WHERE L4.PARENT_ID = :V$OBJ_ID AND L4.OBJ_TYPE_ID = 4 AND L4.DATE_DEL IS NULL
      ORDER BY 2
      INTO :V$RANGE_ID, :V$DATE, :V$DATE2
    DO
    BEGIN
      IF(V$PD IS NOT NULL AND V$PD < V$DATE) THEN
      BEGIN
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'events:r:id';
        VAL = 'p' || V$RANGE_ID;
        SUSPEND;
        TAG_NAME = 'events:r:type';
        VAL = 'hd';
        SUSPEND;
        TAG_NAME = 'events:r:value';
        VAL = (SELECT VAL FROM DATE2ISO(:V$PD, 0)) || ',' || (SELECT VAL FROM DATE2ISO(:V$DATE, 0));
        SUSPEND;
      END
      V$PD = V$DATE2;
    END
  END

  -- Официальные выходные
  -- TODO: добавить праздники и замены из КУГ
  FOR
    SELECT D.DATETYPE, D.DATEVAL
    FROM SPECIAL_DATES D
    WHERE D.DATETYPE >= 0 AND D.DATEVAL >= :I$DATE_FROM AND D.DATEVAL <= :I$DATE_TO
    INTO :V$OBJ_ID, :V$DATE
  DO
  BEGIN
    TAG_NAME = 'events:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'events:r:id';
    VAL = 'off' || REPLACE((SELECT VAL FROM DATE2ISO(:V$DATE, 0)), '-', '');
    SUSPEND;
    TAG_NAME = 'events:r:type';
    VAL = 'off';
    SUSPEND;
    TAG_NAME = 'events:r:value';
    VAL = (SELECT VAL FROM DATE2ISO(:V$DATE, 0));
    IF(V$OBJ_ID = 1) THEN VAL = '/' || VAL;
    SUSPEND;
  END

  -- Отпуск плановый
  FOR
    SELECT L37.OBJ_ID, V237.VAL, V238.VAL
    FROM LINKS L37
    JOIN VALL V330 ON V330.OBJ_ID = L37.OBJ_ID AND V330.PARAM_ID = 330 AND V330.IS_DEL = 0 AND V330.LISTVAL_ID = 736 -- план
    JOIN VALL V326 ON V326.OBJ_ID = L37.OBJ_ID AND V326.PARAM_ID = 326 AND V326.IS_DEL = 0 AND V326.LISTVAL_ID = 730 -- текущий
    JOIN VALD V237 ON V237.OBJ_ID = L37.OBJ_ID AND V237.PARAM_ID = 237 AND V237.IS_DEL = 0
    JOIN VALD V238 ON V238.OBJ_ID = L37.OBJ_ID AND V238.PARAM_ID = 238 AND V238.IS_DEL = 0
    WHERE L37.PARENT_ID = :V$PERSON_ID AND L37.OBJ_TYPE_ID = 37 AND L37.DATE_DEL IS NULL
    ORDER BY 2
    INTO :V$RANGE_ID, :V$DATE, :V$DATE2
  DO
  BEGIN
    TAG_NAME = 'events:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'events:r:id';
    VAL = 'v' || V$RANGE_ID;
    SUSPEND;
    TAG_NAME = 'events:r:type';
    VAL = 'vc';
    SUSPEND;
    TAG_NAME = 'events:r:value';
    VAL = (SELECT VAL FROM DATE2ISO(:V$PD, 0)) || ',' || (SELECT VAL FROM DATE2ISO(:V$DATE, 0));
    SUSPEND;
  END

  -- Разовые мероприятия

  -- Возврат книг
  IF(V$PERSON_TYPE IN (10, 14)) THEN
  BEGIN
    V$PD = NULL;
    SELECT MIN(U.PLAN_DATE)
    FROM LIB2_USAGE U
    WHERE U.REF_ID = :V$PERSON_ID AND U.REF_TYPE_ID = :V$PERSON_TYPE AND U.RETURN_DATE IS NULL AND U.LOSS_DATE IS NULL
    INTO :V$PD;

    IF(V$PD IS NOT NULL) THEN
    BEGIN
      TAG_NAME = 'events:r:id';
      VAL = 'LIBRT';
      SUSPEND;
      TAG_NAME = 'events:r:type';
      VAL = 'cust';
      SUSPEND;
      TAG_NAME = 'events:r:value';
      VAL = (SELECT VAL FROM DATE2ISO(:V$PD, 0));
      SUSPEND;
      TAG_NAME = 'events:r:title';
      VAL = 'Возврат книг в библиотеку';
      SUSPEND;
    END
  END

  -- Расписание сессий для СПО
  IF(V$PERSON_TYPE = 10 AND EXISTS(
    SELECT FIRST 1 1
    FROM PERSON_MOVEMENTS M
    WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :V$PERSON_ID AND M.GROUP_TYPE_ID IN (9, 187, 289) AND M.LEVEL_ID = 29
  )) THEN
  BEGIN
    FOR
      SELECT L481.OBJ_ID, V3396.VAL, V3397.VAL, C.VAL, V3603.LISTVAL_ID
      FROM LINKS L481
      JOIN VALL V3389 ON V3389.OBJ_ID = L481.OBJ_ID AND V3389.PARAM_ID = 3389 AND V3389.LISTVAL_ID = :V$YEAR_ID
      JOIN VALL V3390 ON V3390.OBJ_ID = L481.OBJ_ID AND V3390.PARAM_ID = 3390 AND V3390.LISTVAL_ID = 11715
      JOIN LINKS L151 ON L151.PARENT_ID = L481.OBJ_ID AND L151.OBJ_TYPE_ID = 151 AND L151.DATE_DEL IS NULL
      JOIN LINKS L487 ON L487.PARENT_ID = L151.OBJ_ID AND L487.OBJ_TYPE_ID = 487 AND L487.DATE_DEL IS NULL
      JOIN VALD V3396 ON V3396.OBJ_ID = L487.OBJ_ID AND V3396.PARAM_ID = 3396 AND V3396.IS_DEL = 0
      JOIN VALD V3397 ON V3397.OBJ_ID = L487.OBJ_ID AND V3397.PARAM_ID = 3397 AND V3397.IS_DEL = 0
      LEFT JOIN VALL V3603 ON V3603.OBJ_ID = L487.OBJ_ID AND V3603.PARAM_ID = 3603 AND V3603.IS_DEL = 0
      LEFT JOIN LISTVAL_TEXT(V3603.LISTVAL_ID) C ON 1 = 1
      WHERE L481.PARENT_ID = :V$OU_ID AND L481.OBJ_TYPE_ID = 481 AND L481.DATE_DEL IS NULL
      ORDER BY 2
      INTO :V$RANGE_ID, :V$DATE, :V$DATE2, :S, :V$OBJ_ID
    DO
    BEGIN
      TAG_NAME = 'events:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'events:r:id';
      VAL = 'ssn' || V$RANGE_ID;
      SUSPEND;
      TAG_NAME = 'events:r:type';
      VAL = 'ssnpd';
      SUSPEND;
      TAG_NAME = 'events:r:value';
      VAL = (SELECT VAL FROM DATE2ISO(:V$DATE, 0)) || ',' || (SELECT VAL FROM DATE2ISO(:V$DATE2, 0));
      SUSPEND;
      TAG_NAME = 'events:r:subtype';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'events:r:title';
      VAL = S;
      SUSPEND;
    END
  END

  -- Тесты на уроках
  -- Расписание экзаменов для СПО
  IF(V$PERSON_TYPE = 10) THEN
  BEGIN
    FOR
      SELECT DISTINCT D.OBJ_ID, L.LESSON_DATE, D.OBJ_NAME
      FROM UT_EXAM_PERSON_ASSN PA
      JOIN UT_EXAM_DATES D ON D.DATE_DEL IS NULL AND D.OBJ_ID = PA.EXAM_ID AND D.EXAM_STATE = 600 AND D.PLAN_METHOD_ID = 4
      JOIN CJ2_CONTROL C ON C.DATE_DEL IS NULL AND C.TEST_ID = D.OBJ_ID
      JOIN CJ2_JOURNAL_LESSONS L ON L.OBJ_ID = C.LESSON_ID AND L.DATE_DEL IS NULL AND L.LESSON_DATE >= :V$YEAR_DATE
      JOIN CJ2_JOURNAL J ON J.OBJ_ID = L.CJ_ID
      WHERE PA.DATE_DEL IS NULL AND PA.PERSON_ID = :V$PERSON_ID
      ORDER BY 2, 3
      INTO :V$OBJ_ID, :V$PD, :S
    DO
    BEGIN
      TAG_NAME = 'events:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'events:r:id';
      VAL = 'test' || V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'events:r:type';
      VAL = 'cust+testing';
      SUSPEND;
      TAG_NAME = 'events:r:value';
      VAL = (SELECT VAL FROM DATE2ISO(:V$PD, 0));
      SUSPEND;
      TAG_NAME = 'events:r:title';
      IF(POSITION('ТЕСТ' IN UPPER(S)) <= 0) THEN S = 'Тест: ' || S;
      VAL = S;
      SUSPEND;
    END

    FOR
      SELECT R.OBJ_ID, R.ATT_DATE, V376.VAL, C.VAL
      FROM ATT_REGISTER_STDS S
      JOIN ATT_REGISTER R ON R.DATE_DEL IS NULL AND R.OBJ_ID = S.ATT_ID AND R.STATE_ID IN (1, 2) AND R.ATT_DATE >= :V$YEAR_DATE -- AND R.ATT_DATE <= :I$DATE_TO
      JOIN VALS V376 ON V376.OBJ_ID = R.SUBJECT_ID AND V376.PARAM_ID IN (376, 1751) AND V376.IS_DEL = 0
      LEFT JOIN LISTVAL_TEXT(R.CONTROL_TYPE_ID) C ON 1 = 1
      WHERE S.DATE_DEL IS NULL AND S.PERSON_ID = :V$PERSON_ID
      ORDER BY 2
      INTO :V$OBJ_ID, :V$PD, :S, :S2
    DO
    BEGIN
      TAG_NAME = 'events:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'events:r:id';
      VAL = 'att' || V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'events:r:type';
      VAL = 'cust+exam';
      SUSPEND;
      TAG_NAME = 'events:r:value';
      VAL = (SELECT VAL FROM DATE2ISO(:V$PD, 0));
      SUSPEND;
      TAG_NAME = 'events:r:title';
      VAL = S2 || ' - ' || S;
      SUSPEND;
    END
  END

  -- Замены, отмены, переносы для учителей
  TAG_NAME = 'subst::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT RP.OBJ_ID, RP.REPL_DATE, RP.LESSON_NUM, IIF(RP.PERSON_ID = :V$PERSON_ID, 0, 1), IIF(RP.PERSON_ID = :V$PERSON_ID, J1.JOURNAL_NAME || COALESCE(' - ' || C1.CAPTION, ''), J2.JOURNAL_NAME || COALESCE(' - ' || C2.CAPTION, ''))
    FROM CJ2_REPL_PROCESS RP
    JOIN CJ2_JOURNAL J1 ON J1.OBJ_ID = RP.CJ_ID
    LEFT JOIN CJ2_JOURNAL J2 ON J2.OBJ_ID = RP.REPL_CJ_ID
    LEFT JOIN OBJECT_CAPTION_GET(J1.SUBJECT_ID) C1 ON J1.SUBJECT_ID IS NOT NULL
    LEFT JOIN OBJECT_CAPTION_GET(J2.SUBJECT_ID) C2 ON J2.SUBJECT_ID IS NOT NULL
    WHERE RP.DATE_DEL IS NULL AND (RP.PERSON_ID = :V$PERSON_ID OR RP.REPL_PERSON_ID = :V$PERSON_ID) AND :V$PERSON_TYPE = 14
      AND RP.REPL_DATE >= :I$DATE_FROM AND RP.REPL_DATE <= :I$DATE_TO
    INTO :V$OBJ_ID, :V$DATE, :V$N, :V$F, :S
  DO
  BEGIN
    TAG_NAME = 'subst:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'subst:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'subst:r:date';
    VAL = (SELECT VAL FROM DATE2ISO(:V$DATE, 0)) || '/' || V$N;
    SUSPEND;
    TAG_NAME = 'subst:r:type';
    VAL = V$F;
    SUSPEND;
    TAG_NAME = 'subst:r:value';
    VAL = S;
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE MCAL_SCHEDULE_GET (
    I$DATE DATE NOT NULL,
    I$ZONE SMALLINT,
    I$FULL SMALLINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$OU_ID BIGINT;
DECLARE VARIABLE V$YEAR_ID BIGINT;
DECLARE VARIABLE V$PERSON_ID BIGINT;
DECLARE VARIABLE V$PERSON_TYPE BIGINT;
DECLARE VARIABLE V$ROLE SMALLINT;
DECLARE VARIABLE V$SCHEDULE_ID BIGINT;
DECLARE VARIABLE V$FLOW_ID BIGINT;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$OBJ_ID2 BIGINT;
DECLARE VARIABLE V$ROOM_ID BIGINT;
DECLARE VARIABLE V$DUR INTEGER;
DECLARE VARIABLE V$TEACHER_ID BIGINT;
DECLARE VARIABLE V$GRADE_ID BIGINT;
DECLARE VARIABLE V$SUBJECT_ID BIGINT;
DECLARE VARIABLE V$PERWEEK INTEGER;
DECLARE VARIABLE V$MG_ID BIGINT;
DECLARE VARIABLE N INTEGER;
DECLARE VARIABLE V$T1 TIME;
DECLARE VARIABLE V$T2 TIME;
DECLARE VARIABLE V$WEEKDAY_NUM INTEGER;
DECLARE VARIABLE V$LESSON_NUM INTEGER;
DECLARE VARIABLE V$DIFF BIGINT;
DECLARE VARIABLE V$PERDAY FLOAT;
DECLARE VARIABLE S VARCHAR(1000);
DECLARE VARIABLE S1 VARCHAR(1000);
DECLARE VARIABLE S2 VARCHAR(1000);
DECLARE VARIABLE V$D1 INTEGER;
DECLARE VARIABLE V$D2 INTEGER;
DECLARE VARIABLE V$PARENT_ID BIGINT;
DECLARE VARIABLE D DATE;
DECLARE VARIABLE V$CJ_ID BIGINT;
DECLARE VARIABLE V$DT VARCHAR(200);
DECLARE VARIABLE V$START_DATE DATE;
DECLARE VARIABLE V$YEAR INTEGER;
DECLARE VARIABLE D1 DATE;
DECLARE VARIABLE D2 DATE;
DECLARE VARIABLE V$GIA_STATE BIGINT;
begin

  -- Формат выдачи расписания похож на SCHEDULE_FLOW

  -- Сам учебный год мы проверяем, но дальше мы его выкинем и будем смотреть конкретную дату
  SELECT FIRST 1 L2.OBJ_ID, V1236.LISTVAL_ID, LV.COST
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$OU_ID, :V$YEAR_ID, :V$YEAR;

  IF(V$YEAR_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Нет данных по текущему учебного году, настройте текущий учебный год';

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  SELECT FIRST 1 U.USER_TYPE, U.OBJ_ID, O.TYPE_ID
  FROM USERS U
  LEFT JOIN OBJECTS O ON O.OBJ_ID = U.OBJ_ID
  WHERE U.USER_ID = :I$USER_ID AND U.DATE_DEL IS NULL AND U.IS_BLOCKED = 0 AND (U.EXP_DATE IS NULL OR U.EXP_DATE > CURRENT_DATE)
  INTO :V$ROLE, :V$PERSON_ID, :V$PERSON_TYPE;

  IF(V$ROLE IS NULL) THEN EXCEPTION DATA_ERROR 'Пользователь не найден';

  -- Находим подходящий по датам шаблон расписания - один единственный !
  -- Важно: до сентября смотрим прошлый учебный год, после сентября новый, несмотря на настройку текущего учебного года
  -- выбор учебного года делаем по концу недели, чтобы 1 сентября показывалось в правильном варианте
  SELECT FIRST 1 LV.LISTVAL_ID
  FROM LISTVALS LV
  JOIN LISTVALS LV2 ON LV2.LIST_ID = LV.LIST_ID AND LV2.IS_DEL = 0 AND LV2.COST = LV.COST + 1 AND CAST(LV2.TAG AS DATE) > DATEADD(7 DAY TO :I$DATE)
  WHERE LV.IS_DEL = 0 AND LV.LIST_ID = 29 AND CAST(LV.TAG AS DATE) <= DATEADD(7 DAY TO :I$DATE)
  INTO :V$YEAR_ID;

  -- Корректируем дату до начала недели (неделя начинается с понедельника), но по учебному году не отсекаем
  N = EXTRACT(WEEKDAY FROM I$DATE);
  IF(N = 0) THEN N = 6; ELSE N = N - 1;
  I$DATE = DATEADD(DAY, -N, I$DATE);

  TAG_NAME = 'date';
  VAL = (SELECT VAL FROM DATE2ISO(:I$DATE, 0));
  SUSPEND;

  TAG_NAME = 'person_type';
  VAL = V$PERSON_TYPE;
  SUSPEND;

  -- Список предметов - выбираем весь список
  TAG_NAME = 'subjects::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
    SELECT DISTINCT SUBJECT_ID, V3066.VAL, V3058.LISTVAL_ID, V3059.VAL, V377.VAL
    FROM CJ2_JOURNAL
    LEFT JOIN VALS V3066 ON V3066.OBJ_ID = SUBJECT_ID AND V3066.PARAM_ID IN (3066, 3067) AND V3066.IS_DEL = 0
    LEFT JOIN VALL V3058 ON V3058.OBJ_ID = SUBJECT_ID AND V3058.PARAM_ID IN (3058) AND V3058.IS_DEL = 0
    LEFT JOIN VALF V3059 ON V3059.OBJ_ID = SUBJECT_ID AND V3059.PARAM_ID IN (3059) AND V3059.IS_DEL = 0
    LEFT JOIN VALS V377 ON V377.OBJ_ID = SUBJECT_ID AND V377.PARAM_ID IN (377, 1752) AND V377.IS_DEL = 0
    WHERE SUBJECT_ID IS NOT NULL AND :I$FULL = 1
    INTO :V$OBJ_ID, :S, :V$DIFF, :V$PERDAY, :S1
  DO
  BEGIN
    TAG_NAME = 'subjects:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'subjects:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'subjects:r:name';
    VAL = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$OBJ_ID));
    SUSPEND;
    TAG_NAME = 'subjects:r:code';
    VAL = S1;
    SUSPEND;
    TAG_NAME = 'subjects:r:color';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'subjects:r:difficulty';
    VAL = V$DIFF;
    SUSPEND;
    TAG_NAME = 'subjects:r:perday';
    VAL = CAST(V$PERDAY AS NUMERIC(18, 1));
    SUSPEND;
  END

  -- Список помещений - в данной ОУ
  TAG_NAME = 'buildings::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
    SELECT L16.OBJ_ID, C.CAPTION
    FROM LINKS L73
    JOIN LINKS L16 ON L16.PARENT_ID = L73.OBJ_ID AND L16.OBJ_TYPE_ID = 16 AND L16.DATE_DEL IS NULL
    LEFT JOIN OBJECT_CAPTION_GET(L16.OBJ_ID) C ON 1 = 1
    WHERE L73.PARENT_ID = :V$OU_ID AND L73.OBJ_TYPE_ID = 73 AND L73.DATE_DEL IS NULL AND :I$FULL = 1
    INTO :V$OBJ_ID, :S
  DO
  BEGIN
    TAG_NAME = 'buildings:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'buildings:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'buildings:r:name';
    VAL = S;
    SUSPEND;

    -- Помещения выбираем только учебно-лабораторные и вспомогательные
    TAG_NAME = 'buildings:r:rooms::json&colon;array';
    VAL = '1';
    SUSPEND;
    FOR
      SELECT L61.OBJ_ID, C.CAPTION, V1344.VAL
      FROM LINKS L61
      JOIN VALL V525 ON V525.OBJ_ID = L61.OBJ_ID AND V525.PARAM_ID = 525 AND V525.IS_DEL = 0 AND V525.LISTVAL_ID IN (23, 12764)
      LEFT JOIN VALR V1344 ON V1344.OBJ_ID = L61.OBJ_ID AND V1344.PARAM_ID = 1344 AND V1344.IS_DEL = 0
      LEFT JOIN OBJECT_CAPTION_GET(L61.OBJ_ID) C ON 1 = 1
      WHERE L61.PARENT_ID = :V$OBJ_ID AND L61.OBJ_TYPE_ID = 61 AND L61.DATE_DEL IS NULL
      ORDER BY 2
      INTO :V$OBJ_ID2, :S, :V$TEACHER_ID
    DO
    BEGIN
      TAG_NAME = 'buildings:r:rooms:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'buildings:r:rooms:r:id';
      VAL = V$OBJ_ID2;
      SUSPEND;
      TAG_NAME = 'buildings:r:rooms:r:name';
      VAL = S;
      SUSPEND;
      TAG_NAME = 'buildings:r:rooms:r:teacher_id';
      VAL = V$TEACHER_ID;
      SUSPEND;
      -- Список предметов, закрепленных за помещением
      TAG_NAME = 'buildings:r:rooms:r:subjects::json&colon;array';
      VAL = 1;
      SUSPEND;
      FOR
        SELECT L51.OBJ_ID
        FROM LINKS L51
        WHERE L51.PARENT_ID = :V$OBJ_ID2 AND L51.OBJ_TYPE_ID IN (51, 197) AND L51.DATE_DEL IS NULL AND 0 = 1
        INTO :V$SUBJECT_ID
      DO
      BEGIN
        TAG_NAME = 'buildings:r:rooms:r:subjects:r';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'buildings:r:rooms:r:subjects:r:id';
        VAL = V$SUBJECT_ID;
        SUSPEND;
      END
    END
  END

  -- Добавляем виртуальный id для помещений на стороне, id помещения будет равно id ОУ чтобы сохранялась связность
  TAG_NAME = 'buildings:r';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'buildings:r:id';
  VAL = '';
  SUSPEND;
  TAG_NAME = 'buildings:r:name';
  VAL = 'Вне ОООД';
  SUSPEND;
  TAG_NAME = 'buildings:r:rooms::json&colon;array';
  VAL = '1';
  SUSPEND;
  TAG_NAME = 'buildings:r:rooms:r';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'buildings:r:rooms:r:id';
  VAL = V$OU_ID;
  SUSPEND;
  TAG_NAME = 'buildings:r:rooms:r:name';
  VAL = 'Вне ОООД';
  SUSPEND;
  TAG_NAME = 'buildings:r:rooms:r:teacher_id';
  VAL = '';
  SUSPEND;
  TAG_NAME = 'buildings:r:rooms:r:subjects::json&colon;array';
  VAL = 1;
  SUSPEND;

  -- Список всех журналов с названиями предметов, тут надо выдавать все - чтобы не сломались замены
  -- Для учеников выдаем только журналы, где они были
  TAG_NAME = 'journals::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
    SELECT J.OBJ_ID, J.JOURNAL_TYPE, J.TEACHER_ID, J.GRADE_ID, J.SUBJECT_ID, J.JOURNAL_NAME, C.CAPTION,
      IIF(J.WEEKS > 0, ROUND(J.HOURS / J.WEEKS), NULL), J.DURATION, LPG.EXT_OBJ_ID, J.STAGE_INDEX
    FROM CJ2_JOURNAL J
    LEFT JOIN LISTVALS LV ON LV.LISTVAL_ID = J.STAGE_INDEX
    LEFT JOIN OBJECT_CAPTION_GET(J.GRADE_ID) C ON 1 = 1
    LEFT JOIN LINKS LPG ON LPG.OBJ_ID = J.GRADE_ID AND LPG.PARENT_TYPE_ID = 2 AND LPG.DATE_DEL IS NULL
    WHERE J.DATE_DEL IS NULL AND J.YEAR_ID = :V$YEAR_ID AND :I$FULL = 1
    ORDER BY 10, 2, LV.COST, 6
    INTO :V$OBJ_ID, :N, :V$TEACHER_ID, :V$GRADE_ID, :V$SUBJECT_ID, :S, :S1, :V$PERWEEK, :V$DUR, :V$MG_ID, :V$DIFF
  DO
  BEGIN
    -- IF(V$PERSON_TYPE = 10) THEN

    TAG_NAME = 'journals:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'journals:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'journals:r:type';
    VAL = N;
    SUSPEND;
    TAG_NAME = 'journals:r:teacher_id';
    VAL = V$TEACHER_ID;
    SUSPEND;
    TAG_NAME = 'journals:r:mg_id'; -- ссылка на мастер-группу
    VAL = V$MG_ID;
    SUSPEND;
    TAG_NAME = 'journals:r:grade_id';
    VAL = V$GRADE_ID;
    SUSPEND;
    TAG_NAME = 'journals:r:grade_name';
    VAL = S1;
    SUSPEND;
    TAG_NAME = 'journals:r:stage_id';
    VAL = V$DIFF;
    SUSPEND;
    TAG_NAME = 'journals:r:subject_id';
    VAL = V$SUBJECT_ID;
    SUSPEND;
    TAG_NAME = 'journals:r:name';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'journals:r:perweek';
    VAL = V$PERWEEK;
    SUSPEND;
    TAG_NAME = 'journals:r:dur';
    IF(V$DUR IS NULL OR V$DUR = 0) THEN V$DUR = 45; -- по-умолчанию
    VAL = V$DUR;
    SUSPEND;
    -- Ресурсы
    TAG_NAME = 'journals:r:resources';
    VAL = NULL;
    SUSPEND;
  END

  TAG_NAME = 'flows::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
    SELECT L3.OBJ_ID, V3080.VAL, V3081.VAL
    FROM LINKS L68
    JOIN LINKS L3 ON L3.PARENT_ID = L68.OBJ_ID AND L3.OBJ_TYPE_ID = 3 AND L3.DATE_DEL IS NULL
    JOIN VALL V37 ON V37.OBJ_ID = L3.OBJ_ID AND V37.PARAM_ID = 37 AND V37.IS_DEL = 0 AND V37.LISTVAL_ID = :V$YEAR_ID
    LEFT JOIN VALT V3080 ON V3080.OBJ_ID = L3.OBJ_ID AND V3080.PARAM_ID = 3080 AND V3080.IS_DEL = 0
    LEFT JOIN VALT V3081 ON V3081.OBJ_ID = L3.OBJ_ID AND V3081.PARAM_ID = 3081 AND V3081.IS_DEL = 0
    WHERE L68.PARENT_ID = :V$OU_ID AND L68.OBJ_TYPE_ID = 68 AND L68.DATE_DEL IS NULL
    ORDER BY 1
    INTO :V$FLOW_ID, :V$T1, :V$T2
  DO
  BEGIN

    TAG_NAME = 'flows:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'flows:r:id';
    VAL = V$FLOW_ID;
    SUSPEND;

    -- Находим недельную выписку по датам
    SELECT FIRST 1 L59.OBJ_ID
    FROM LINKS L59
    JOIN VALL V1341 ON V1341.OBJ_ID = L59.OBJ_ID AND V1341.PARAM_ID = 1341 AND V1341.IS_DEL = 0 AND V1341.LISTVAL_ID = 2 -- выгружаемые на портал / активные
    LEFT JOIN VALD V3120 ON V3120.OBJ_ID = L59.OBJ_ID AND V3120.PARAM_ID = 3120 AND V3120.IS_DEL = 0
    LEFT JOIN VALD V3121 ON V3121.OBJ_ID = L59.OBJ_ID AND V3121.PARAM_ID = 3121 AND V3121.IS_DEL = 0
    WHERE L59.PARENT_ID = :V$FLOW_ID AND L59.OBJ_TYPE_ID = 59 AND L59.DATE_DEL IS NULL
      AND (V3120.VAL IS NULL OR V3120.VAL < DATEADD(7 DAY TO :I$DATE))
      AND (V3121.VAL IS NULL OR V3121.VAL >= :I$DATE)
    ORDER BY 1
    INTO :V$SCHEDULE_ID;

    TAG_NAME = 'flows:r:time_start';
    VAL = COALESCE(V$T1, '08:00:00');
    SUSPEND;

    TAG_NAME = 'flows:r:time_end';
    VAL = COALESCE(V$T2, '18:00:00');
    SUSPEND;

    -- Дни недели
    V$WEEKDAY_NUM = 0;
    TAG_NAME = 'flows:r:days::json&colon;array';
    VAL = '1';
    SUSPEND;
    WHILE(V$WEEKDAY_NUM < 7) DO
    BEGIN
      V$OBJ_ID = NULL;
      SELECT FIRST 1 V402.LISTVAL_ID - 798, R.VAL
      FROM LINKS L6
      JOIN VALL V402 ON V402.OBJ_ID = L6.OBJ_ID AND V402.PARAM_ID = 402 AND V402.IS_DEL = 0 AND V402.LISTVAL_ID = 798 + :V$WEEKDAY_NUM
      JOIN LISTVALS LV ON LV.LISTVAL_ID = V402.LISTVAL_ID
      JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
      LEFT JOIN VALD V42 ON V42.OBJ_ID = L6.OBJ_ID AND V42.PARAM_ID = 42 AND V42.IS_DEL = 0
      WHERE L6.PARENT_ID = :V$SCHEDULE_ID AND L6.OBJ_TYPE_ID = 6 AND L6.DATE_DEL IS NULL
      INTO :V$OBJ_ID, :S;

      IF(V$OBJ_ID IS NOT NULL) THEN
      BEGIN
        TAG_NAME = 'flows:r:days:r';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'flows:r:days:r:id';
        VAL = V$OBJ_ID;
        SUSPEND;
        TAG_NAME = 'flows:r:days:r:name';
        VAL = S;
        SUSPEND;
        TAG_NAME = 'flows:r:days:r:date';
        VAL = (SELECT RESULT FROM DATE2STR(DATEADD(:V$OBJ_ID DAY TO :I$DATE)));
        SUSPEND;
        TAG_NAME = 'flows:r:days:r:dateiso';
        VAL = (SELECT VAL FROM DATE2ISO(DATEADD(:V$OBJ_ID DAY TO :I$DATE), 0));
        SUSPEND;
      END
      V$WEEKDAY_NUM = V$WEEKDAY_NUM + 1;
    END

    -- Номера и время уроков - для фиксированной сетки
    V$LESSON_NUM = -1;
    TAG_NAME = 'flows:r:lessons::json&colon;array';
    VAL = '1';
    SUSPEND;
    FOR
      SELECT DISTINCT V404.VAL, V405.VAL, V406.VAL
      FROM LINKS L59
      JOIN LINKS L60 ON L60.PARENT_ID = L59.OBJ_ID AND L60.OBJ_TYPE_ID = 60 AND L60.DATE_DEL IS NULL
      JOIN VALI V404 ON V404.OBJ_ID = L60.OBJ_ID AND V404.PARAM_ID = 404 AND V404.IS_DEL = 0
      LEFT JOIN VALT V405 ON V405.OBJ_ID = L60.OBJ_ID AND V405.PARAM_ID = 405 AND V405.IS_DEL = 0
      LEFT JOIN VALT V406 ON V406.OBJ_ID = L60.OBJ_ID AND V406.PARAM_ID = 406 AND V406.IS_DEL = 0
      WHERE L59.PARENT_ID = :V$FLOW_ID AND L59.OBJ_ID = :V$SCHEDULE_ID AND L59.DATE_DEL IS NULL
      ORDER BY 1, 2
      INTO :N, :V$T1, :V$T2
    DO
    BEGIN
      IF(V$LESSON_NUM <> N) THEN
      BEGIN
        TAG_NAME = 'flows:r:lessons:r';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'flows:r:lessons:r:id';
        VAL = N;
        SUSPEND;
        TAG_NAME = 'flows:r:lessons:r:t_from';
        VAL = V$T1;
        SUSPEND;
        TAG_NAME = 'flows:r:lessons:r:t_to';
        VAL = V$T2;
        SUSPEND;
      END
      V$LESSON_NUM = N;
    END

    -- Список назначений - работает не так как в основном расписании, сшивка у нас не по дням недели, а по неделе целиком
    -- Внимание: выборка учителей идет не по журналу, а явно по teacher
    -- тут выдаем все записи шаблона, а дальше на клиенте дофильтровываются те, по которым сделано замещение
    TAG_NAME = 'flows:r:schedule::json&colon;array';
    VAL = '1';
    SUSPEND;
    FOR
      SELECT DISTINCT I.OBJ_ID, I.WEEKDAY_NUM, I.LESSON_NUM, I.CJ_ID, I.ROOM_ID, I.DURATION, I.EXT_INFO
      FROM LINKS L59
      JOIN SCHEDULE_ITEMS I ON I.DATE_DEL IS NULL AND I.SCHEDULE_ID = L59.OBJ_ID
      JOIN CJ2_JOURNAL J ON J.OBJ_ID = I.CJ_ID
      LEFT JOIN PERSON_MOVEMENTS M ON M.DATE_DEL IS NULL AND M.GROUP_ID = J.GRADE_ID AND M.PERSON_ID = :V$PERSON_ID AND M.DATE_IN < DATEADD(7 DAY TO :I$DATE) AND (M.DATE_OUT IS NULL OR M.DATE_OUT > :I$DATE)
      WHERE L59.PARENT_ID = :V$FLOW_ID AND L59.OBJ_ID = :V$SCHEDULE_ID AND L59.DATE_DEL IS NULL
        AND (J.TEACHER_ID = :V$PERSON_ID OR M.OBJ_ID IS NOT NULL)
      INTO :V$OBJ_ID, :V$WEEKDAY_NUM, :V$LESSON_NUM, :V$OBJ_ID2, :V$ROOM_ID, :V$DUR, :S
    DO
    BEGIN
      TAG_NAME = 'flows:r:schedule:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'flows:r:schedule:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'flows:r:schedule:r:day';
      VAL = V$WEEKDAY_NUM;
      SUSPEND;
      -- Нумерация lesson: 1..59 - номер урока по расписанию, >= 60 - метка времени в минутах с начала суток
      TAG_NAME = 'flows:r:schedule:r:lesson';
      VAL = V$LESSON_NUM;
      SUSPEND;
      TAG_NAME = 'flows:r:schedule:r:cj';
      VAL = V$OBJ_ID2;
      SUSPEND;
      TAG_NAME = 'flows:r:schedule:r:room';
      VAL = V$ROOM_ID;
      SUSPEND;
      TAG_NAME = 'flows:r:schedule:r:duration';
      VAL = V$DUR;
      SUSPEND;
      TAG_NAME = 'flows:r:schedule:r:parent';
      VAL = '';
      SUSPEND;
      TAG_NAME = 'flows:r:schedule:r:ext_info';
      VAL = S;
      SUSPEND;
    END

    -- Записи ленты расписания по датам, причем в качестве номера дня недели тут используется M * 100 + D
    V$D1 = EXTRACT(MONTH FROM I$DATE) * 100 + EXTRACT(DAY FROM I$DATE);
    V$D2 = EXTRACT(MONTH FROM DATEADD(7 DAY TO I$DATE)) * 100 + EXTRACT(DAY FROM DATEADD(7 DAY TO I$DATE));
    TAG_NAME = 'flows:r:fschedule::json&colon;array';
    VAL = '1';
    SUSPEND;
    FOR
      SELECT DISTINCT I.OBJ_ID, I.WEEKDAY_NUM, I.LESSON_NUM, I.CJ_ID, I.ROOM_ID, I.DURATION, J.TEACHER_ID, I.PARENT_ID, I.EXT_INFO
      FROM SCHEDULE_ITEMS I
      JOIN CJ2_JOURNAL J ON J.OBJ_ID = I.CJ_ID
      LEFT JOIN PERSON_MOVEMENTS M ON M.DATE_DEL IS NULL AND M.GROUP_ID = J.GRADE_ID AND M.PERSON_ID = :V$PERSON_ID AND M.DATE_IN < DATEADD(7 DAY TO :I$DATE) AND (M.DATE_OUT IS NULL OR M.DATE_OUT > :I$DATE)
      WHERE I.DATE_DEL IS NULL AND I.SCHEDULE_ID = :V$FLOW_ID AND I.WEEKDAY_NUM >= :V$D1 AND I.WEEKDAY_NUM < :V$D2
        AND (J.TEACHER_ID = :V$PERSON_ID OR M.OBJ_ID IS NOT NULL)
      INTO :V$OBJ_ID, :V$WEEKDAY_NUM, :V$LESSON_NUM, :V$OBJ_ID2, :V$ROOM_ID, :V$DUR, :V$TEACHER_ID, :V$PARENT_ID, :S
    DO
    BEGIN
      TAG_NAME = 'flows:r:fschedule:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'flows:r:fschedule:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'flows:r:fschedule:r:day';
      VAL = V$WEEKDAY_NUM - V$D1;
      SUSPEND;
      TAG_NAME = 'flows:r:fschedule:r:date';
      VAL = V$WEEKDAY_NUM;
      SUSPEND;
      TAG_NAME = 'flows:r:fschedule:r:lesson';
      VAL = V$LESSON_NUM;
      SUSPEND;
      TAG_NAME = 'flows:r:fschedule:r:cj';
      VAL = V$OBJ_ID2;
      SUSPEND;
      TAG_NAME = 'flows:r:fschedule:r:room';
      VAL = V$ROOM_ID;
      SUSPEND;
      TAG_NAME = 'flows:r:fschedule:r:duration';
      VAL = V$DUR;
      SUSPEND;
      TAG_NAME = 'flows:r:fschedule:r:teacher';
      VAL = V$TEACHER_ID;
      SUSPEND;
      TAG_NAME = 'flows:r:fschedule:r:parent';
      VAL = V$PARENT_ID;
      SUSPEND;
      TAG_NAME = 'flows:r:fschedule:r:ext_info';
      VAL = S;
      SUSPEND;
    END

    -- Тесты для прохождения - выдаем только ученикам
    FOR
      SELECT DISTINCT D.OBJ_ID, L.LESSON_DATE, L.LESSON_NUM, D.OBJ_NAME, J.OBJ_ID, COALESCE(L.TEACHER_ID, J.TEACHER_ID), J.DURATION
      FROM UT_EXAM_PERSON_ASSN PA
      JOIN UT_EXAM_DATES D ON D.DATE_DEL IS NULL AND D.OBJ_ID = PA.EXAM_ID AND D.EXAM_STATE = 600 AND D.PLAN_METHOD_ID = 4
      JOIN CJ2_CONTROL C ON C.DATE_DEL IS NULL AND C.TEST_ID = D.OBJ_ID
      JOIN CJ2_JOURNAL_LESSONS L ON L.OBJ_ID = C.LESSON_ID AND L.DATE_DEL IS NULL AND L.LESSON_DATE >= :I$DATE AND L.LESSON_DATE <= DATEADD(7 DAY TO :I$DATE)
      JOIN CJ2_JOURNAL J ON J.OBJ_ID = L.CJ_ID
      WHERE PA.DATE_DEL IS NULL AND PA.PERSON_ID = :V$PERSON_ID
      ORDER BY 2, 3
      INTO :V$OBJ_ID, :D, :V$LESSON_NUM, :S, :V$CJ_ID, :V$TEACHER_ID, :V$DUR
    DO
    BEGIN
      TAG_NAME = 'flows:r:fschedule:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'flows:r:fschedule:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'flows:r:fschedule:r:day';
      VAL = DATEDIFF(DAY FROM I$DATE TO D);
      SUSPEND;
      TAG_NAME = 'flows:r:fschedule:r:date';
      VAL = EXTRACT(MONTH FROM D) * 100 + EXTRACT(DAY FROM D); -- M * 100 + D
      SUSPEND;
      TAG_NAME = 'flows:r:fschedule:r:lesson';
      VAL = V$LESSON_NUM;
      SUSPEND;
      TAG_NAME = 'flows:r:fschedule:r:cj';
      VAL = V$CJ_ID;
      SUSPEND;
      TAG_NAME = 'flows:r:fschedule:r:room';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'flows:r:fschedule:r:duration';
      VAL = V$DUR;
      SUSPEND;
      TAG_NAME = 'flows:r:fschedule:r:teacher';
      VAL = V$TEACHER_ID;
      SUSPEND;
      TAG_NAME = 'flows:r:fschedule:r:parent';
      VAL = NULL; -- запись дополняет расписание
      SUSPEND;
      TAG_NAME = 'flows:r:fschedule:r:rc';
      VAL = 'test'; -- признак того что это тест
      SUSPEND;
      TAG_NAME = 'flows:r:fschedule:r:ext_info';
      VAL = S;
      SUSPEND;
    END

  END

  -- Записи замен, попадающие в актуальный диапазон по датам
  -- Сюда же попадают обычные замены уроков
  TAG_NAME = 'subst::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
    SELECT DISTINCT P.OBJ_ID, P.REPL_DATE, P.LESSON_NUM, P.REPL_CJ_ID, P.CJ_ID, P.ROOM_ID, COALESCE(J.DURATION, 45), P.REPL_PERSON_ID
    FROM CJ2_REPL_PROCESS P
    JOIN CJ2_JOURNAL J ON J.OBJ_ID = P.CJ_ID
    LEFT JOIN PERSON_MOVEMENTS M ON M.DATE_DEL IS NULL AND M.GROUP_ID = J.GRADE_ID AND M.PERSON_ID = :V$PERSON_ID AND M.DATE_IN < DATEADD(7 DAY TO :I$DATE) AND (M.DATE_OUT IS NULL OR M.DATE_OUT > :I$DATE)
    WHERE P.DATE_DEL IS NULL AND P.REPL_DATE >= :I$DATE AND P.REPL_DATE < DATEADD(7 DAY TO :I$DATE)
      AND (P.PERSON_ID = :V$PERSON_ID OR P.REPL_PERSON_ID = :V$PERSON_ID OR M.OBJ_ID IS NOT NULL)
    INTO :V$OBJ_ID, :D, :V$LESSON_NUM, :V$OBJ_ID2, :V$CJ_ID, :V$ROOM_ID, :V$DUR, :V$TEACHER_ID
  DO
  BEGIN
    V$WEEKDAY_NUM = EXTRACT(MONTH FROM D) * 100 + EXTRACT(DAY FROM D);
    TAG_NAME = 'subst:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'subst:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'subst:r:day';
    VAL = V$WEEKDAY_NUM - V$D1;
    SUSPEND;
    TAG_NAME = 'subst:r:date';
    VAL = V$WEEKDAY_NUM;
    SUSPEND;
    TAG_NAME = 'subst:r:lesson';
    VAL = V$LESSON_NUM;
    SUSPEND;
    TAG_NAME = 'subst:r:cj';
    VAL = COALESCE(V$OBJ_ID2, V$CJ_ID); -- NULL, если тот же журнал ?
    SUSPEND;
    TAG_NAME = 'subst:r:src_cj';
    VAL = V$CJ_ID;
    SUSPEND;
    TAG_NAME = 'subst:r:room';
    VAL = V$ROOM_ID;
    SUSPEND;
    TAG_NAME = 'subst:r:duration';
    VAL = V$DUR;
    SUSPEND;
    TAG_NAME = 'subst:r:teacher';
    VAL = V$TEACHER_ID;
    SUSPEND;
  END

  -- Напоминания
  -- Кликабельными являются только записи с type начинающимся с @
  TAG_NAME = 'alerts::json&colon;array';
  VAL = '1';
  SUSPEND;

  -- Выбор экзаменов ГИА
  IF(V$PERSON_TYPE = 10) THEN
  BEGIN
    SELECT V3598.LISTVAL_ID
    FROM VALL V3598
    WHERE V3598.OBJ_ID = :V$OU_ID AND V3598.PARAM_ID = 3598 AND V3598.IS_DEL = 0
    INTO :V$GIA_STATE;

    -- Кроме случая когда запись не начата
    IF(V$GIA_STATE <> 18743) THEN
    BEGIN
      TAG_NAME = 'alerts:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'alerts:r:level';  -- 0 = info, 1 = warning, 2 = alert
      VAL = IIF(V$GIA_STATE = 18744, 1, 0); -- желтый для записи, зеленый информационно
      SUSPEND;
      TAG_NAME = 'alerts:r:type';
      VAL = '@gia';
      SUSPEND;
      TAG_NAME = 'alerts:r:text';
      VAL = 'Выбрать экзамены';
      SUSPEND;
    END
  END

  -- Наличие замечаний по КЖ для меня
  -- Наличие замечаний по КЖ на проверку
  IF(V$PERSON_TYPE = 14) THEN
  BEGIN
    SELECT COUNT(*)
    FROM CJ2_AUDIT CA
    WHERE CA.DATE_DEL IS NULL AND CA.TEACHER_ID = :V$PERSON_ID AND CA.STATE_ID = 0
    INTO :N;

    IF(N > 0) THEN
    BEGIN
      TAG_NAME = 'alerts:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'alerts:r:level';
      VAL = 1;
      SUSPEND;
      TAG_NAME = 'alerts:r:type';
      VAL = 'cj_audit';
      SUSPEND;
      TAG_NAME = 'alerts:r:text';
      VAL = N || ' замечаний по журналам';
      SUSPEND;
    END

    SELECT COUNT(*)
    FROM CJ2_AUDIT CA
    WHERE CA.DATE_DEL IS NULL AND CA.OWNER_ID = :I$USER_ID AND CA.STATE_ID = 1
    INTO :N;

    IF(N > 0) THEN
    BEGIN
      TAG_NAME = 'alerts:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'alerts:r:level';
      VAL = 1;
      SUSPEND;
      TAG_NAME = 'alerts:r:type';
      VAL = 'cj_audit';
      SUSPEND;
      TAG_NAME = 'alerts:r:text';
      VAL = N || ' замечаний устранено';
      SUSPEND;
    END
  END

  -- + Повышение квалификации для конкретного учителя
  IF(V$PERSON_TYPE = 14) THEN
  BEGIN
    -- + Аттестация для конкретного учителя, на соответствие должности (только те кто без категории)
    FOR
      SELECT DISTINCT LV.TAG, V73.VAL
      FROM LINKS L15
      JOIN VALL V1790 ON V1790.OBJ_ID = L15.OBJ_ID AND V1790.PARAM_ID = 1790 AND V1790.IS_DEL = 0 AND V1790.LISTVAL_ID = 632 -- без категории
      JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0
      LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
      JOIN LINKS LP13 ON LP13.OBJ_ID  = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
      JOIN VALL V58 ON V58.OBJ_ID = LP13.PARENT_ID AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0
      JOIN LISTVALS LV ON LV.LISTVAL_ID = V58.LISTVAL_ID AND (LV.TAG = 'U' OR LV.TAG = 'V')
      WHERE L15.PARENT_ID = :V$PERSON_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL AND V74.VAL IS NULL
      INTO :V$DT, :V$START_DATE
    DO
    BEGIN
      S = NULL;
      V$DT = NULL;
      SELECT FIRST 1 '*', 0 -- есть свежие ?
      FROM LINKS L156
      JOIN VALD V1232 ON V1232.OBJ_ID = L156.OBJ_ID AND V1232.PARAM_ID = 1232 AND V1232.IS_DEL = 0 AND V1232.VAL >= DATEADD(-48 MONTH TO CURRENT_DATE)
      JOIN VALL V1233 ON V1233.OBJ_ID = L156.OBJ_ID AND V1233.PARAM_ID = 1233 AND V1233.IS_DEL = 0 AND V1233.LISTVAL_ID = 3033
      WHERE L156.PARENT_ID = :V$PERSON_ID AND L156.OBJ_TYPE_ID = 156 AND L156.DATE_DEL IS NULL
      INTO :S, :V$DT;
      IF(S IS NULL) THEN
      SELECT FIRST 1 D.RESULT, IIF(V1232.VAL >= DATEADD(-60 MONTH TO CURRENT_DATE), 1, 2)
      FROM LINKS L156
      JOIN VALD V1232 ON V1232.OBJ_ID = L156.OBJ_ID AND V1232.PARAM_ID = 1232 AND V1232.IS_DEL = 0 AND V1232.VAL < DATEADD(-48 MONTH TO CURRENT_DATE)
      JOIN VALL V1233 ON V1233.OBJ_ID = L156.OBJ_ID AND V1233.PARAM_ID = 1233 AND V1233.IS_DEL = 0 AND V1233.LISTVAL_ID = 3033
      LEFT JOIN DATE2STR(V1232.VAL) D ON 1 = 1
      WHERE L156.PARENT_ID = :V$PERSON_ID AND L156.OBJ_TYPE_ID = 156 AND L156.DATE_DEL IS NULL
      ORDER BY V1232.VAL DESC
      INTO :S, :V$DT;
      IF(V$DT IS NULL) THEN V$DT = 2;
      -- Обнуляем требование, если менее 2 лет на должности
      IF(CURRENT_DATE < DATEADD(2 YEAR TO V$START_DATE)) THEN V$DT = '0';
      IF(V$DT <> '0') THEN
      BEGIN
        TAG_NAME = 'alerts:r';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'alerts:r:level';
        VAL = V$DT;
        SUSPEND;
        TAG_NAME = 'alerts:r:type';
        VAL = 'job';
        SUSPEND;
        TAG_NAME = 'alerts:r:text';
        VAL = COALESCE('Последняя аттестация от ' || S, 'Нет данных по аттестации');
        SUSPEND;
      END
    END

    FOR
      SELECT DISTINCT LV.TAG, V73.VAL
      FROM LINKS L15
      JOIN VALL V1790 ON V1790.OBJ_ID = L15.OBJ_ID AND V1790.PARAM_ID = 1790 AND V1790.IS_DEL = 0 AND V1790.LISTVAL_ID <> 632 -- есть категория
      JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0
      LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
      JOIN LINKS LP13 ON LP13.OBJ_ID  = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
      JOIN VALL V58 ON V58.OBJ_ID = LP13.PARENT_ID AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0
      JOIN LISTVALS LV ON LV.LISTVAL_ID = V58.LISTVAL_ID AND (LV.TAG = 'U' OR LV.TAG = 'V')
      WHERE L15.PARENT_ID = :V$PERSON_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL AND V74.VAL IS NULL
      INTO :V$DT, :V$START_DATE
    DO
    BEGIN
      S = NULL;
      V$DT = NULL;
      SELECT FIRST 1 '*', 0 -- есть свежие ?
      FROM LINKS L34
      JOIN VALD V544 ON V544.OBJ_ID = L34.OBJ_ID AND V544.PARAM_ID = 544 AND V544.IS_DEL = 0 AND V544.VAL >= DATEADD(-48 MONTH TO CURRENT_DATE)
      JOIN VALL V545 ON V545.OBJ_ID = L34.OBJ_ID AND V545.PARAM_ID = 545 AND V545.IS_DEL = 0 AND V545.LISTVAL_ID IN (1208, 1209, 1210)
      WHERE L34.PARENT_ID = :V$PERSON_ID AND L34.OBJ_TYPE_ID = 34 AND L34.DATE_DEL IS NULL
      INTO :S, :V$DT;
      IF(S IS NULL) THEN
      SELECT FIRST 1 D.RESULT, IIF(V544.VAL >= DATEADD(-60 MONTH TO CURRENT_DATE), 1, 2)
      FROM LINKS L34
      JOIN VALD V544 ON V544.OBJ_ID = L34.OBJ_ID AND V544.PARAM_ID = 544 AND V544.IS_DEL = 0 AND V544.VAL < DATEADD(-48 MONTH TO CURRENT_DATE)
      JOIN VALL V545 ON V545.OBJ_ID = L34.OBJ_ID AND V545.PARAM_ID = 545 AND V545.IS_DEL = 0 AND V545.LISTVAL_ID IN (1208, 1209, 1210)
      LEFT JOIN DATE2STR(V544.VAL) D ON 1 = 1
      WHERE L34.PARENT_ID = :V$PERSON_ID AND L34.OBJ_TYPE_ID = 34 AND L34.DATE_DEL IS NULL
      ORDER BY V544.VAL DESC
      INTO :S, :V$DT;
      IF(V$DT IS NULL) THEN V$DT = 2;
      -- Обнуляем требование, если менее 2 лет на должности
      -- IF(CURRENT_DATE < DATEADD(2 YEAR TO V$START_DATE)) THEN V$DT = '0';
      IF(V$DT <> '0') THEN
      BEGIN
        TAG_NAME = 'alerts:r';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'alerts:r:level';
        VAL = V$DT;
        SUSPEND;
        TAG_NAME = 'alerts:r:type';
        VAL = 'job';
        SUSPEND;
        TAG_NAME = 'alerts:r:text';
        VAL = COALESCE('Последняя аттестация от ' || S, 'Нет данных по аттестации');
        SUSPEND;
      END
    END

    S = NULL;
    V$DT = NULL;
    SELECT FIRST 1 '*', 0 -- есть свежие повышения квалификации ?
    FROM LINKS L36
    JOIN VALD V310 ON V310.OBJ_ID = L36.OBJ_ID AND V310.PARAM_ID = 310 AND V310.IS_DEL = 0 AND V310.VAL >= DATEADD(-24 MONTH TO CURRENT_DATE)
    WHERE L36.PARENT_ID = :V$PERSON_ID AND L36.OBJ_TYPE_ID = 36 AND L36.DATE_DEL IS NULL
    INTO :S, :V$DT;
    IF(S IS NULL) THEN
    SELECT FIRST 1 D.RESULT, IIF(V310.VAL >= DATEADD(-36 MONTH TO CURRENT_DATE), 1, 2)
    FROM LINKS L36
    JOIN VALD V310 ON V310.OBJ_ID = L36.OBJ_ID AND V310.PARAM_ID = 310 AND V310.IS_DEL = 0 AND V310.VAL < DATEADD(-24 MONTH TO CURRENT_DATE)
    LEFT JOIN DATE2STR(V310.VAL) D ON 1 = 1
    WHERE L36.PARENT_ID = :V$PERSON_ID AND L36.OBJ_TYPE_ID = 36 AND L36.DATE_DEL IS NULL
    ORDER BY V310.VAL DESC
    INTO :S, :V$DT;
    IF(V$DT IS NULL) THEN V$DT = 2;
    IF(V$DT <> '0') THEN
    BEGIN
      TAG_NAME = 'alerts:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'alerts:r:level';
      VAL = V$DT;
      SUSPEND;
      TAG_NAME = 'alerts:r:type';
      VAL = 'qualification';
      SUSPEND;
      TAG_NAME = 'alerts:r:text';
      VAL = COALESCE('Последнее повышение квалификации от ' || S, 'Нет данных по повышению квалификации');
      SUSPEND;
    END
  END

  -- Распределение нагрузки на согласование - текущий и будущий год
  -- План отпусков
  IF(V$PERSON_TYPE = 14) THEN
  BEGIN
    V$OBJ_ID = NULL;
    SELECT FIRST 1 L531.OBJ_ID
    FROM LINKS L527
    JOIN LINKS L531 ON L531.PARENT_ID = L527.OBJ_ID AND L531.OBJ_TYPE_ID = 531 AND L531.DATE_DEL IS NULL
    JOIN VALL V3568 ON V3568.OBJ_ID = L531.OBJ_ID AND V3568.PARAM_ID = 3568 AND V3568.IS_DEL = 0 AND V3568.LISTVAL_ID = 11715 -- действующий
    JOIN VALL V3567 ON V3567.OBJ_ID = L531.OBJ_ID AND V3567.PARAM_ID = 3567 AND V3567.IS_DEL = 0 AND V3567.LISTVAL_ID >= :V$YEAR_ID
    JOIN EDULOAD_DATA D ON D.PARENT_ID = L531.OBJ_ID AND D.PERSON_ID = :V$PERSON_ID AND D.VERIFIED = 0
    WHERE L527.PARENT_ID = :V$OU_ID AND L527.OBJ_TYPE_ID = 527 AND L527.DATE_DEL IS NULL
    INTO :V$OBJ_ID;

    IF(V$OBJ_ID IS NOT NULL) THEN
    BEGIN
      TAG_NAME = 'alerts:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'alerts:r:level';
      VAL = 1; -- warning
      SUSPEND;
      TAG_NAME = 'alerts:r:type';
      VAL = '@eduload';
      SUSPEND;
      TAG_NAME = 'alerts:r:text';
      VAL = 'Распределение нагрузки|Ознакомление с распределением педагогической нагрузки';
      SUSPEND;
    END

    -- Наличие исправлений в графике контрольных мероприятий
    IF(EXISTS(
      SELECT FIRST 1 1
      FROM LINKS L535
      JOIN VALL V3590 ON V3590.OBJ_ID = L535.OBJ_ID AND V3590.PARAM_ID = 3590 AND V3590.IS_DEL = 0
      JOIN EDULOAD_DATA D ON D.DATE_DEL IS NULL AND D.PARENT_ID = L535.OBJ_ID AND D.LOAD_VAL = 1
      JOIN LINKS L10 ON L10.PARENT_ID = D.PERSON_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      JOIN LINKS LP179 ON LP179.OBJ_ID = L10.OBJ_ID AND LP179.PARENT_TYPE_ID = 179 AND LP179.DATE_DEL IS NULL
      JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.JOURNAL_TYPE = 0 AND J.GRADE_ID = LP179.PARENT_ID AND J.SUBJECT_ID = D.REF_ID AND J.TEACHER_ID = :V$PERSON_ID
      WHERE L535.PARENT_ID = :V$OU_ID AND L535.OBJ_TYPE_ID = 535 AND L535.DATE_DEL IS NULL
    ))
    THEN
    BEGIN
      TAG_NAME = 'alerts:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'alerts:r:level';
      VAL = 1; -- warning
      SUSPEND;
      TAG_NAME = 'alerts:r:type';
      VAL = '@cplan';
      SUSPEND;
      TAG_NAME = 'alerts:r:text';
      VAL = 'Контрольные мероприятия|Есть изменения в датах контрольных мероприятий';
      SUSPEND;
    END

    -- Есть ли у нас план отпусков в статусе проекта ?
    -- TODO: Менять цвет иконки если данные еще не внесены и если внесены
    TAG_NAME = 'alerts:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'alerts:r:level';
    VAL = 0; -- 0 = info, 1 = warning
    SELECT FIRST 1 1
    FROM LINKS L534
    JOIN VALI V3584 ON V3584.OBJ_ID = L534.OBJ_ID AND V3584.PARAM_ID = 3584 AND V3584.IS_DEL = 0 AND V3584.VAL = :V$YEAR
    JOIN VALL V3585 ON V3585.OBJ_ID = L534.OBJ_ID AND V3585.PARAM_ID = 3585 AND V3585.IS_DEL = 0 AND V3585.LISTVAL_ID = 11716
    WHERE L534.PARENT_ID = :V$OU_ID AND L534.OBJ_TYPE_ID = 534 AND L534.DATE_DEL IS NULL
    INTO :VAL;
    SUSPEND;
    TAG_NAME = 'alerts:r:type';
    VAL = '@vacation';
    SUSPEND;
    TAG_NAME = 'alerts:r:text';
    VAL = 'График отпусков|Планирование графика отпусков';
    SUSPEND;
  END

  -- Литература при подходе срока возврата
  IF(V$PERSON_TYPE IN (10, 14)) THEN
  BEGIN
    N = 0;
    D = NULL;
    SELECT COUNT(*), MIN(U.PLAN_DATE)
    FROM LIB2_USAGE U
    WHERE U.REF_ID = :V$PERSON_ID AND U.REF_TYPE_ID = :V$PERSON_TYPE AND U.RETURN_DATE IS NULL AND U.LOSS_DATE IS NULL
    INTO :N, :D;
    IF(N > 0) THEN
    BEGIN
      TAG_NAME = 'alerts:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'alerts:r:level';
      IF(D > DATEADD(3 DAY TO CURRENT_DATE)) THEN VAL = 10; -- 0 = info, 1 = warning, 2 = alert
      ELSE IF(D >= CURRENT_DATE) THEN VAL = 11;
      ELSE VAL = 12;
      SUSPEND;
      TAG_NAME = 'alerts:r:type';
      VAL = '@library';
      SUSPEND;
      TAG_NAME = 'alerts:r:text';
      VAL = 'Электронный абонемент|На руках ' || N || ' книг, ближайший срок возврата ' || (SELECT RESULT FROM DATE2STR(:D));
      SUSPEND;
      TAG_NAME = 'alerts:r:date';
      VAL = (SELECT VAL FROM DATE2ISO(:D));
      SUSPEND;
    END
  END

  -- Список чатов
  TAG_NAME = 'chats::json&colon;array';
  VAL = '1';
  SUSPEND;

  S = NULL;
  SELECT FIRST 1 V.VAL
  FROM VALS V
  WHERE V.OBJ_ID = :V$OU_ID AND V.PARAM_ID = 3357 AND V.IS_DEL = 0
  INTO :S;
  IF(S IS NOT NULL AND V$PERSON_TYPE = 14) THEN
  BEGIN
    TAG_NAME = 'chats:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'chats:r:name';
    VAL = 'Учительская';
    SUSPEND;
    TAG_NAME = 'chats:r:link';
    VAL = SUBSTRING(S FROM POSITION(',' IN S) + 1);
    SUSPEND;
  END

  -- Чаты классного руководителя
  IF(V$PERSON_TYPE = 14) THEN
  FOR
    SELECT C.CAPTION, CAST(V3336.VAL AS VARCHAR(1000)), CAST(V3359.VAL AS VARCHAR(1000))
    FROM VALR V53
    JOIN LINKS LP8 ON LP8.OBJ_ID = V53.OBJ_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
    LEFT JOIN OBJECT_CAPTION_GET(LP8.OBJ_ID) C ON 1 = 1
    LEFT JOIN VALS V3336 ON V3336.OBJ_ID = LP8.OBJ_ID AND V3336.PARAM_ID = 3336 AND V3336.IS_DEL = 0
    LEFT JOIN VALS V3359 ON V3359.OBJ_ID = LP8.OBJ_ID AND V3359.PARAM_ID = 3359 AND V3359.IS_DEL = 0
    WHERE V53.PARAM_ID = 53 AND V53.IS_DEL = 0 AND V53.VAL = :V$PERSON_ID AND (V3336.VAL IS NOT NULL OR V3359.VAL IS NOT NULL)
    ORDER BY C.SORT_ORDER, C.CAPTION
    INTO :S,  :S1, :S2
  DO
  BEGIN
    IF(S1 IS NOT NULL) THEN
    BEGIN
      TAG_NAME = 'chats:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'chats:r:name';
      VAL = S;
      SUSPEND;
      TAG_NAME = 'chats:r:link';
      VAL = SUBSTRING(S1 FROM POSITION(',' IN S1) + 1);
      SUSPEND;
    END
    IF(S2 IS NOT NULL) THEN
    BEGIN
      TAG_NAME = 'chats:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'chats:r:name';
      VAL = S || ' Родители';
      SUSPEND;
      TAG_NAME = 'chats:r:link';
      VAL = SUBSTRING(S1 FROM POSITION(',' IN S1) + 1);
      SUSPEND;
    END
  END
  IF(V$PERSON_TYPE = 14) THEN
  FOR
    SELECT J.JOURNAL_NAME || ' ' || C.CAPTION, J.CHAT_ID
    FROM CJ2_JOURNAL J
    LEFT JOIN OBJECT_CAPTION_GET(J.SUBJECT_ID) C ON 1 = 1
    WHERE J.DATE_DEL IS NULL AND J.TEACHER_ID = :V$PERSON_ID AND J.CHAT_ID IS NOT NULL
    ORDER BY 1
    INTO :S,  :S1
  DO
  BEGIN
    TAG_NAME = 'chats:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'chats:r:name';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'chats:r:link';
    VAL = SUBSTRING(S1 FROM POSITION(',' IN S1) + 1);
    SUSPEND;
  END

  S = NULL;
  S1= NULL;
  IF(V$PERSON_TYPE = 10) THEN
  FOR
    SELECT FIRST 1 0, C.CAPTION, V3336.VAL
    FROM LINKS LP9
    JOIN VALS V3336 ON V3336.OBJ_ID = LP9.PARENT_ID AND V3336.PARAM_ID = 3336 AND V3336.IS_DEL = 0
    LEFT JOIN OBJECT_CAPTION_GET(LP9.PARENT_ID) C ON 1 = 1
    WHERE LP9.OBJ_ID = :V$PERSON_ID AND LP9.PARENT_TYPE_ID = 9 AND LP9.DATE_DEL IS NULL
    UNION
    SELECT 1, J.JOURNAL_NAME || ' ' || C.CAPTION, J.CHAT_ID
    FROM PERSON_MOVEMENTS M
    JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.GRADE_ID = M.GROUP_ID AND J.CHAT_ID IS NOT NULL
    LEFT JOIN OBJECT_CAPTION_GET(J.SUBJECT_ID) C ON 1 = 1
    WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :V$PERSON_ID AND M.DATE_OUT IS NULL
    ORDER BY 1, 2
    INTO :V$CJ_ID, :S, S1
  DO
  BEGIN
    TAG_NAME = 'chats:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'chats:r:name';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'chats:r:link';
    VAL = SUBSTRING(S1 FROM POSITION(',' IN S1) + 1);
    SUSPEND;
  END

  -- Список экзаменов СПО в сессии
  -- Смотрим период 2 месяца до и 3 месяца после текущей даты
  IF(V$PERSON_TYPE = 10 AND EXISTS(
    SELECT FIRST 1 1
    FROM PERSON_MOVEMENTS M
    WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :V$PERSON_ID AND M.GROUP_TYPE_ID IN (9, 187, 289) AND M.LEVEL_ID = 29
  )) THEN
  BEGIN
    -- Расписание сессий
    -- с сентября по март показываем первый семестр, дальше - второй
    V$PARENT_ID = IIF(EXTRACT(MONTH FROM CURRENT_DATE) IN (9, 10, 11, 12, 1, 2, 3), 19, 20);

    TAG_NAME = 'ssn_periods::json&colon;array';
    VAL = '1';
    SUSPEND;
    FOR
      SELECT D1.RESULT, D2.RESULT, C.VAL
      FROM LINKS L481
      JOIN VALL V3389 ON V3389.OBJ_ID = L481.OBJ_ID AND V3389.PARAM_ID = 3389 AND V3389.LISTVAL_ID = :V$YEAR_ID
      JOIN VALL V3390 ON V3390.OBJ_ID = L481.OBJ_ID AND V3390.PARAM_ID = 3390 AND V3390.LISTVAL_ID = 11715
      JOIN LINKS L151 ON L151.PARENT_ID = L481.OBJ_ID AND L151.OBJ_TYPE_ID = 151 AND L151.DATE_DEL IS NULL
      JOIN LINKS L487 ON L487.PARENT_ID = L151.OBJ_ID AND L487.OBJ_TYPE_ID = 487 AND L487.DATE_DEL IS NULL
      JOIN VALD V3396 ON V3396.OBJ_ID = L487.OBJ_ID AND V3396.PARAM_ID = 3396 AND V3396.IS_DEL = 0
      LEFT JOIN DATE2STR(V3396.VAL) D1 ON 1 = 1
      JOIN VALD V3397 ON V3397.OBJ_ID = L487.OBJ_ID AND V3397.PARAM_ID = 3397 AND V3397.IS_DEL = 0
      LEFT JOIN DATE2STR(V3397.VAL) D2 ON 1 = 1
      JOIN VALL V3426 ON V3426.OBJ_ID = L487.OBJ_ID AND V3426.PARAM_ID = 3426 AND V3426.IS_DEL = 0 AND V3426.LISTVAL_ID = :V$PARENT_ID
      LEFT JOIN VALL V3603 ON V3603.OBJ_ID = L487.OBJ_ID AND V3603.PARAM_ID = 3603 AND V3603.IS_DEL = 0
      LEFT JOIN LISTVAL_TEXT(V3603.LISTVAL_ID) C ON 1 = 1
      WHERE L481.PARENT_ID = :V$OU_ID AND L481.OBJ_TYPE_ID = 481 AND L481.DATE_DEL IS NULL
      ORDER BY V3396.VAL
      INTO :S, :S1, :S2
    DO
    BEGIN
      TAG_NAME = 'ssn_periods:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'ssn_periods:r:date_from';
      VAL = S;
      SUSPEND;
      TAG_NAME = 'ssn_periods:r:date_to';
      VAL = S1;
      SUSPEND;
      TAG_NAME = 'ssn_periods:r:name';
      VAL = S2;
      SUSPEND;
    END

    TAG_NAME = 'sessions::json&colon;array';
    VAL = '1';
    SUSPEND;
    D1 = DATEADD(-2 MONTH TO CURRENT_DATE);
    D2 = DATEADD(3 MONTH TO CURRENT_DATE);
    FOR
      SELECT R.OBJ_ID, R.ATT_DATE, V376.VAL, R.CONTROL_TYPE_ID, C.VAL, V408.VAL, R.TIME_VAL
      FROM ATT_REGISTER_STDS S
      JOIN ATT_REGISTER R ON R.DATE_DEL IS NULL AND R.OBJ_ID = S.ATT_ID AND R.STATE_ID IN (1, 2) -- AND R.ATT_DATE >= :D1 AND R.ATT_DATE <= :D2
      JOIN VALS V376 ON V376.OBJ_ID = R.SUBJECT_ID AND V376.PARAM_ID IN (376, 1751) AND V376.IS_DEL = 0
      LEFT JOIN LISTVAL_TEXT(R.CONTROL_TYPE_ID) C ON 1 = 1
      LEFT JOIN VALS V408 ON V408.OBJ_ID = R.ROOM_ID AND V408.PARAM_ID = 408 AND V408.IS_DEL = 0
      WHERE S.DATE_DEL IS NULL AND S.PERSON_ID = :V$PERSON_ID
      ORDER BY 2
      INTO :V$OBJ_ID, :D, :S, :V$CJ_ID, :S2, :S1, :V$DT
    DO
    BEGIN
      TAG_NAME = 'sessions:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'sessions:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'sessions:r:date';
      VAL = (SELECT VAL FROM DATE2ISO(:D, 0));
      SUSPEND;
      TAG_NAME = 'sessions:r:type_id';
      VAL = V$CJ_ID;
      SUSPEND;
      TAG_NAME = 'sessions:r:type_name';
      VAL = S2;
      SUSPEND;
      TAG_NAME = 'sessions:r:subject_name';
      VAL = S;
      SUSPEND;
      TAG_NAME = 'sessions:r:room_name';
      VAL = S1;
      SUSPEND;
      TAG_NAME = 'sessions:r:time';
      VAL = V$DT;
      SUSPEND;
    END

    -- Расписание ГИА
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE MCAL_VIEW_CPLAN (
    I$OBJ_ID BIGINT,
    I$ZONE SMALLINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    VAL VARCHAR(4000))
AS
DECLARE VARIABLE V$ROLE SMALLINT;
DECLARE VARIABLE V$PERSON_ID BIGINT;
DECLARE VARIABLE V$PERSON_TYPE BIGINT;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$GRADE_NAME VARCHAR(200);
DECLARE VARIABLE V$SUBJECT_NAME VARCHAR(400);
DECLARE VARIABLE V$DESC VARCHAR(200);
DECLARE VARIABLE V$DATE DATE;
begin

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  SELECT FIRST 1 U.USER_TYPE, U.OBJ_ID, O.TYPE_ID
  FROM USERS U
  LEFT JOIN OBJECTS O ON O.OBJ_ID = U.OBJ_ID
  WHERE U.USER_ID = :I$USER_ID AND U.DATE_DEL IS NULL AND U.IS_BLOCKED = 0 AND (U.EXP_DATE IS NULL OR U.EXP_DATE > CURRENT_DATE)
  INTO :V$ROLE, :V$PERSON_ID, :V$PERSON_TYPE;

  IF(V$ROLE IS NULL) THEN EXCEPTION DATA_ERROR 'Пользователь не найден';
  IF(V$PERSON_TYPE <> 14) THEN EXCEPTION DATA_ERROR 'Пользователь не является сотрудником';

  VAL = '<table class="ui small striped celled table"><thead><tr>';
  VAL = VAL || '<th>Учебный коллектив</th>';
  VAL = VAL || '<th>Предмет</th>';
  VAL = VAL || '<th>Название мероприятия</th>';
  VAL = VAL || '<th>Дата мероприятия</th>';
  VAL = VAL || '</tr></thead><tbody>';
  SUSPEND;

  FOR
    SELECT D.OBJ_ID, C.CAPTION, V376.SVAL, CT.CONTROL_DESC, D.VAL_DATE
    FROM LINKS L535
    JOIN VALL V3590 ON V3590.OBJ_ID = L535.OBJ_ID AND V3590.PARAM_ID = 3590 AND V3590.IS_DEL = 0
    JOIN EDULOAD_DATA D ON D.DATE_DEL IS NULL AND D.PARENT_ID = L535.OBJ_ID AND D.LOAD_VAL = 1
    JOIN CJ2_CONTROL_TYPE CT ON CT.CONTROL_TYPE_ID = D.PLAN_ID
    LEFT JOIN OBJECT_CAPTION_GET(D.PERSON_ID) C ON 1 = 1
    JOIN VALS V376 ON V376.OBJ_ID = D.REF_ID AND V376.PARAM_ID = 376 AND V376.IS_DEL = 0
    WHERE L535.PARENT_TYPE_ID = 2 AND L535.OBJ_TYPE_ID = 535 AND L535.DATE_DEL IS NULL
    AND EXISTS(
      SELECT FIRST 1 1
      FROM LINKS L10
      JOIN LINKS LP179 ON LP179.OBJ_ID = L10.OBJ_ID AND LP179.PARENT_TYPE_ID = 179 AND LP179.DATE_DEL IS NULL
      JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.JOURNAL_TYPE = 0 AND J.GRADE_ID = LP179.PARENT_ID AND J.SUBJECT_ID = D.REF_ID AND J.TEACHER_ID = :V$PERSON_ID
      WHERE L10.PARENT_ID = D.PERSON_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    )
    ORDER BY D.VAL_DATE, D.VERIFIED
    INTO :V$OBJ_ID, :V$GRADE_NAME, :V$SUBJECT_NAME, :V$DESC, :V$DATE
  DO
  BEGIN
    VAL = '<tr>';
      VAL = VAL || '<td>' || (SELECT VAL FROM ESCAPE_STR(:V$GRADE_NAME)) || '</td>';
      VAL = VAL || '<td>' || (SELECT VAL FROM ESCAPE_STR(:V$SUBJECT_NAME)) || '</td>';
      VAL = VAL || '<td>' || (SELECT VAL FROM ESCAPE_STR(:V$DESC)) || '</td>';
      VAL = VAL || '<td>' || (SELECT RESULT FROM DATE2STR(:V$DATE)) || '</td>';
    VAL = VAL || '</tr>';
    SUSPEND;
  END

  VAL = '</tbody></table>';
  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE MCAL_VIEW_EDULOAD (
    I$OBJ_ID BIGINT,
    I$ZONE SMALLINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    VAL VARCHAR(4000))
AS
DECLARE VARIABLE V$ROLE SMALLINT;
DECLARE VARIABLE V$PERSON_ID BIGINT;
DECLARE VARIABLE V$PERSON_TYPE BIGINT;
DECLARE VARIABLE V$OU_ID BIGINT;
DECLARE VARIABLE V$YEAR_ID BIGINT;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$LOAD_YEAR VARCHAR(100);
DECLARE VARIABLE V$REF_TYPE BIGINT;
DECLARE VARIABLE V$GROUP_NAME VARCHAR(1000);
DECLARE VARIABLE V$GT BIGINT;
DECLARE VARIABLE F FLOAT;
DECLARE VARIABLE F0 BIGINT;
DECLARE VARIABLE F1 FLOAT;
DECLARE VARIABLE F2 FLOAT;
DECLARE VARIABLE F3 FLOAT;
begin

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  SELECT FIRST 1 U.USER_TYPE, U.OBJ_ID, O.TYPE_ID
  FROM USERS U
  LEFT JOIN OBJECTS O ON O.OBJ_ID = U.OBJ_ID
  WHERE U.USER_ID = :I$USER_ID AND U.DATE_DEL IS NULL AND U.IS_BLOCKED = 0 AND (U.EXP_DATE IS NULL OR U.EXP_DATE > CURRENT_DATE)
  INTO :V$ROLE, :V$PERSON_ID, :V$PERSON_TYPE;

  IF(V$ROLE IS NULL) THEN EXCEPTION DATA_ERROR 'Пользователь не найден';
  IF(V$PERSON_TYPE <> 14) THEN EXCEPTION DATA_ERROR 'Пользователь не является сотрудником';

  SELECT FIRST 1 L2.OBJ_ID, V1236.LISTVAL_ID
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$OU_ID, :V$YEAR_ID;

  SELECT FIRST 1 L531.OBJ_ID, C.VAL
  FROM LINKS L527
  JOIN LINKS L531 ON L531.PARENT_ID = L527.OBJ_ID AND L531.OBJ_TYPE_ID = 531 AND L531.DATE_DEL IS NULL
  JOIN VALL V3568 ON V3568.OBJ_ID = L531.OBJ_ID AND V3568.PARAM_ID = 3568 AND V3568.IS_DEL = 0 AND V3568.LISTVAL_ID = 11715 -- действующий
  JOIN VALL V3567 ON V3567.OBJ_ID = L531.OBJ_ID AND V3567.PARAM_ID = 3567 AND V3567.IS_DEL = 0 AND V3567.LISTVAL_ID >= :V$YEAR_ID
  JOIN EDULOAD_DATA D ON D.PARENT_ID = L531.OBJ_ID AND D.PERSON_ID = :V$PERSON_ID AND D.VERIFIED = 0
  LEFT JOIN LISTVAL_TEXT(V3567.LISTVAL_ID) C ON 1 = 1
  WHERE L527.PARENT_ID = :V$OU_ID AND L527.OBJ_TYPE_ID = 527 AND L527.DATE_DEL IS NULL
  INTO :V$OBJ_ID, :V$LOAD_YEAR;

  -- Если все уже согласовано, показываем просто форму на текущий и будущий год
  IF(V$OBJ_ID IS NULL) THEN
  BEGIN
    EXCEPTION DATA_ERROR 'Все нагрузки уже согласованы';
    EXIT;
  END

  VAL = '<input type="hidden" name="id" value="' || V$OBJ_ID || '">';
  SUSPEND;

  VAL = '<div class="ui small blue header">Учебная нагрузка на ' || V$LOAD_YEAR || ' учебный год</div>';
  VAL = VAL || '<table class="ui small striped celled table"><thead><tr>';
  VAL = VAL || '<th>Наименование нагрузки</th>';
  VAL = VAL || '<th>Нагрузка (часов в неделю)</th>';
  VAL = VAL || '</tr></thead><tbody>';
  SUSPEND;

  F0 = 0;
  F1 = 0;
  F2 = 0;
  F3 = 0;

  FOR
    SELECT D.REF_TYPE_ID, D.GROUP_TYPE_ID, COALESCE(C.CAPTION || ' - ', '') || D.GROUP_NAME, D.LOAD_VAL
    FROM EDULOAD_DATA D
    LEFT JOIN OBJECT_CAPTION_GET(D.REF_ID) C ON D.REF_TYPE_ID = 51
    WHERE D.PARENT_ID = :V$OBJ_ID AND D.PERSON_ID = :V$PERSON_ID AND D.REF_ID IS NOT NULL
    ORDER BY D.REF_TYPE_ID, D.GROUP_TYPE_ID, D.STAGE_ID, C.CAPTION
    INTO :V$REF_TYPE, :V$GT, :V$GROUP_NAME, :F
  DO
  BEGIN
    VAL = '<tr>';
    IF(V$REF_TYPE = 9) THEN V$GROUP_NAME = 'Классное руководство ' || V$GROUP_NAME;
    ELSE IF(V$REF_TYPE = 61) THEN V$GROUP_NAME = 'Заведование кабинетом ' || V$GROUP_NAME;
    -- ELSE IF(V$REF_TYPE = 51)

    VAL = VAL || '<td';
    IF(V$REF_TYPE = 51 AND V$GT = 1) THEN VAL = VAL || ' style="color: green"';
    IF(V$REF_TYPE = 51 AND V$GT = 3) THEN VAL = VAL || ' style="color: violet"';
    VAL = VAL || '>' || (SELECT VAL FROM ESCAPE_STR(:V$GROUP_NAME)) || '</td>';
    VAL = VAL || '<td>' || COALESCE(CAST(F AS NUMERIC(18, 2)), '') || '</td>';
    VAL = VAL || '</tr>';
    SUSPEND;

    -- Суммируем цифры по видам предметов
    IF(V$GT = 0) THEN F0 = F0 + F;
    IF(V$GT = 1) THEN F1 = F1 + F;
    IF(V$GT = 2) THEN F2 = F2 + F;
    IF(V$GT = 3) THEN F3 = F3 + F;
  END

  VAL = '</tbody></table><br/>';

  -- Сводная таблица по часам
  IF(F0 > 0) THEN VAL = VAL || '<div><div class="ui grey tag label" style="margin-bottom: 0.5rem">Часов уроков: ' || CAST(F0 AS NUMERIC(18, 2)) || '</div></div>';
  IF(F1 > 0) THEN VAL = VAL || '<div><div class="ui green tag label" style="margin-bottom: 0.5rem">Часов ВД: ' || CAST(F1 AS NUMERIC(18, 2)) || '</div></div>';
  IF(F3 > 0) THEN VAL = VAL || '<div><div class="ui violet tag label" style="margin-bottom: 0.5rem">Часов ДО: ' || CAST(F3 AS NUMERIC(18, 2)) || '</div></div>';
  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE MCAL_VIEW_GIA (
    I$OBJ_ID BIGINT,
    I$ZONE SMALLINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    VAL VARCHAR(4000))
AS
DECLARE VARIABLE V$YEAR_ID BIGINT;
DECLARE VARIABLE V$PERSON_ID BIGINT;
DECLARE VARIABLE V$GRADE_ID BIGINT;
DECLARE VARIABLE V$GIA_TYPE BIGINT;
DECLARE VARIABLE V$EXAM_FOLDER BIGINT;
DECLARE VARIABLE V$SELECTION VARCHAR(1000);
DECLARE VARIABLE V$DATE DATE;
DECLARE VARIABLE V$SUBJECT_ID BIGINT;
DECLARE VARIABLE N INTEGER;
DECLARE VARIABLE V$SUBJECT_NAME VARCHAR(200);
DECLARE VARIABLE V$DAYTYPE VARCHAR(100);
DECLARE VARIABLE V$GIA_STATE BIGINT;
DECLARE VARIABLE V$EDCLASS VARCHAR(100);
DECLARE VARIABLE V$OBJ_ID BIGINT;
begin

  SELECT FIRST 1 U.OBJ_ID, LP9.PARENT_ID, V2388.LISTVAL_ID
  FROM USERS U
  JOIN LINKS LP9 ON LP9.OBJ_ID = U.OBJ_ID AND LP9.PARENT_TYPE_ID IN (9, 125, 187) AND LP9.DATE_DEL IS NULL
  JOIN VALL V2388 ON V2388.OBJ_ID = LP9.PARENT_ID AND V2388.PARAM_ID IN (2388, 2418, 2419) AND V2388.IS_DEL = 0
  WHERE U.USER_ID = :I$USER_ID AND U.DATE_DEL IS NULL
  INTO :V$PERSON_ID, :V$GRADE_ID, :V$GIA_TYPE;

  IF(V$PERSON_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не найдена запись обучающегося для данного пользователя';
  IF(V$GIA_TYPE IS NULL OR V$GIA_TYPE = 11217) THEN EXCEPTION DATA_ERROR 'Запись на ГИА доступна только для классов, проходящих аттестацию';

  SELECT FIRST 1 V1236.LISTVAL_ID, CAST(LV.TAG AS DATE), V3598.LISTVAL_ID
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  LEFT JOIN VALL V3598 ON V3598.OBJ_ID = L2.OBJ_ID AND V3598.PARAM_ID = 3598 AND V3598.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$YEAR_ID, :V$DATE, :V$GIA_STATE;

  SELECT FIRST 1 L119.OBJ_ID
  FROM LINKS L119
  JOIN VALL V742 ON V742.OBJ_ID = L119.OBJ_ID AND V742.PARAM_ID = 742 AND V742.IS_DEL = 0 AND V742.LISTVAL_ID = :V$YEAR_ID
  WHERE L119.PARENT_ID = 3866 AND L119.OBJ_TYPE_ID = 119 AND L119.DATE_DEL IS NULL
  INTO :V$EXAM_FOLDER;

  IF(V$EXAM_FOLDER IS NULL) THEN EXCEPTION DATA_ERROR 'Расписание экзаменов еще не загружено';

  -- Выбор грузим только сделанный не ранее начала учебного года
  SELECT FIRST 1 V.VAL
  FROM VALS V
  WHERE V.OBJ_ID = :V$PERSON_ID AND V.PARAM_ID = 3596 AND V.IS_DEL = 0 AND V.DATE_MODIFY >= :V$DATE
  INTO :V$SELECTION;
  V$SELECTION = REPLACE(V$SELECTION, ';', ',');

  IF(V$GIA_TYPE = 11202) THEN V$GIA_TYPE = 3000; -- ГИА-9
  IF(V$GIA_TYPE = 11203) THEN V$GIA_TYPE = 3162; -- ГИА-11

  IF(V$GIA_STATE IS NULL OR V$GIA_STATE = 18743) THEN EXCEPTION DATA_ERROR 'Запись на ГИА еще не открыта';
  IF(V$GIA_STATE = 18744) THEN V$EDCLASS = 'subform gia_choose'; ELSE V$EDCLASS = '';

  -- Печать заявления
  VAL = '<div style="margin-bottom: 1rem;"><a class="action-link" target="_blank" href="/webservice/app.calendar/execute?action=export_pdf&id=' || V$PERSON_ID || '&year_id=' || V$YEAR_ID || '">Напечатать заявление</a></div>';

  VAL = VAL || '<table class="ui small compact celled striped table">';
  VAL = VAL || '<thead><tr><th>Предмет</th>';
  VAL = VAL || '<th>Предварительный выбор</th>';
  VAL = VAL || '<th>Официальное назначение</th></thead>';
  VAL = VAL || '<tbody>';
  SUSPEND;
  FOR
    SELECT DISTINCT LV.SORT_ORDER, V803.LISTVAL_ID, R.VAL
    FROM LINKS L120
    JOIN VALL V801 ON V801.OBJ_ID = L120.OBJ_ID AND V801.PARAM_ID = 801 AND V801.IS_DEL = 0 AND V801.LISTVAL_ID = :V$GIA_TYPE
    JOIN VALL V803 ON V803.OBJ_ID = L120.OBJ_ID AND V803.PARAM_ID = 803 AND V803.IS_DEL = 0
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V803.LISTVAL_ID
    JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
    WHERE L120.PARENT_ID = :V$EXAM_FOLDER AND L120.OBJ_TYPE_ID = 120 AND L120.DATE_DEL IS NULL
    ORDER BY 1
    INTO :N, :V$SUBJECT_ID, :V$SUBJECT_NAME
  DO
  BEGIN
    VAL = '<tr class="' || V$EDCLASS || '" data-value="' || V$SUBJECT_ID || '" data-list="';
    FOR
      SELECT L120.OBJ_ID, V804.VAL, DC.VAL
      FROM LINKS L120
      JOIN VALL V801 ON V801.OBJ_ID = L120.OBJ_ID AND V801.PARAM_ID = 801 AND V801.IS_DEL = 0 AND V801.LISTVAL_ID = :V$GIA_TYPE
      JOIN VALL V803 ON V803.OBJ_ID = L120.OBJ_ID AND V803.PARAM_ID = 803 AND V803.IS_DEL = 0 AND V803.LISTVAL_ID = :V$SUBJECT_ID
      JOIN VALD V804 ON V804.OBJ_ID = L120.OBJ_ID AND V804.PARAM_ID = 804 AND V804.IS_DEL = 0
      JOIN VALL V802 ON V802.OBJ_ID = L120.OBJ_ID AND V802.PARAM_ID = 802 AND V802.IS_DEL = 0
      LEFT JOIN LISTVAL_TEXT(V802.LISTVAL_ID) DC ON 1 = 1
      WHERE L120.PARENT_ID = :V$EXAM_FOLDER AND L120.OBJ_TYPE_ID = 120 AND L120.DATE_DEL IS NULL
      ORDER BY 2
      INTO :V$OBJ_ID, :V$DATE, :V$DAYTYPE
    DO
    BEGIN
      VAL = VAL || V$OBJ_ID || ',' || (SELECT RESULT FROM DATE2STR(:V$DATE)) || ',' || V$DAYTYPE || ';';
    END
    VAL = VAL || '"><td>' || (SELECT VAL FROM ESCAPE_STR(:V$SUBJECT_NAME)) || '</td>';
    SUSPEND;

    -- Хотелки ученика
    V$DATE = NULL;
    V$DAYTYPE = NULL;
    SELECT FIRST 1 V804.VAL, DC.VAL
    FROM STR_TO_ID_LIST(:V$SELECTION) S
    JOIN LINKS L120 ON L120.OBJ_ID = S.ID AND L120.PARENT_ID = :V$EXAM_FOLDER AND L120.DATE_DEL IS NULL
    JOIN VALL V801 ON V801.OBJ_ID = L120.OBJ_ID AND V801.PARAM_ID = 801 AND V801.IS_DEL = 0 AND V801.LISTVAL_ID = :V$GIA_TYPE
    JOIN VALL V803 ON V803.OBJ_ID = L120.OBJ_ID AND V803.PARAM_ID = 803 AND V803.IS_DEL = 0 AND V803.LISTVAL_ID = :V$SUBJECT_ID
    JOIN VALD V804 ON V804.OBJ_ID = L120.OBJ_ID AND V804.PARAM_ID = 804 AND V804.IS_DEL = 0
    JOIN VALL V802 ON V802.OBJ_ID = L120.OBJ_ID AND V802.PARAM_ID = 802 AND V802.IS_DEL = 0
    LEFT JOIN LISTVAL_TEXT(V802.LISTVAL_ID) DC ON 1 = 1
    INTO :V$DATE, :V$DAYTYPE;

    VAL = '<td>' || COALESCE((SELECT RESULT FROM DATE2STR(:V$DATE)), '') || COALESCE(' - ' || V$DAYTYPE, '') || '</td>';
    SUSPEND;

    -- Фактический выбор
    V$DATE = NULL;
    V$DAYTYPE = NULL;
    SELECT FIRST 1 V804.VAL, DC.VAL
    FROM LINKS L120
    JOIN LINKS LP119 ON LP119.OBJ_ID = L120.OBJ_ID AND LP119.PARENT_ID = :V$EXAM_FOLDER AND LP119.DATE_DEL IS NULL
    JOIN VALL V801 ON V801.OBJ_ID = L120.OBJ_ID AND V801.PARAM_ID = 801 AND V801.IS_DEL = 0 AND V801.LISTVAL_ID = :V$GIA_TYPE
    JOIN VALL V803 ON V803.OBJ_ID = L120.OBJ_ID AND V803.PARAM_ID = 803 AND V803.IS_DEL = 0 AND V803.LISTVAL_ID = :V$SUBJECT_ID
    JOIN VALD V804 ON V804.OBJ_ID = L120.OBJ_ID AND V804.PARAM_ID = 804 AND V804.IS_DEL = 0
    JOIN VALL V802 ON V802.OBJ_ID = L120.OBJ_ID AND V802.PARAM_ID = 802 AND V802.IS_DEL = 0
    LEFT JOIN LISTVAL_TEXT(V802.LISTVAL_ID) DC ON 1 = 1
    WHERE L120.PARENT_ID = :V$PERSON_ID AND L120.OBJ_TYPE_ID = 120 AND L120.DATE_DEL IS NULL
    INTO :V$DATE, :V$DAYTYPE;

    VAL = '<td>' || COALESCE((SELECT RESULT FROM DATE2STR(:V$DATE)), '') || COALESCE(' - ' || V$DAYTYPE, '') || '</td>';
    SUSPEND;
  END

  VAL = '</tbody></table>';
  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE MCAL_VIEW_LIBRARY (
    I$OBJ_ID BIGINT,
    I$ZONE SMALLINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$ROLE INTEGER;
DECLARE VARIABLE V$PERSON_ID BIGINT;
DECLARE VARIABLE V$PERSON_TYPE BIGINT;
DECLARE VARIABLE S VARCHAR(200);
DECLARE VARIABLE S2 VARCHAR(400);
DECLARE VARIABLE D1 DATE;
DECLARE VARIABLE D2 DATE;
begin

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  SELECT FIRST 1 U.USER_TYPE, U.OBJ_ID, O.TYPE_ID
  FROM USERS U
  LEFT JOIN OBJECTS O ON O.OBJ_ID = U.OBJ_ID
  WHERE U.USER_ID = :I$USER_ID AND U.DATE_DEL IS NULL AND U.IS_BLOCKED = 0 AND (U.EXP_DATE IS NULL OR U.EXP_DATE > CURRENT_DATE)
  INTO :V$ROLE, :V$PERSON_ID, :V$PERSON_TYPE;

  IF(V$ROLE IS NULL) THEN EXCEPTION DATA_ERROR 'Пользователь не найден';
  IF(V$PERSON_TYPE NOT IN (10, 14)) THEN EXCEPTION DATA_ERROR 'Пользователь не является сотрудником или обучающимся';

  VAL = '<div class="ui small blue header">Литература на руках</div>';
  VAL = VAL || '<table class="ui small striped celled table"><thead><tr>';
  VAL = VAL || '<th>Название</th>';
  VAL = VAL || '<th>Автор</th>';
  VAL = VAL || '<th>Дата выдачи</th>';
  VAL = VAL || '<th>Срок возврата</th>';
  VAL = VAL || '</tr></thead><tbody>';
  SUSPEND;
  FOR
    SELECT B.BOOK_NAME, COALESCE(A.VAL, B.AUTHORS), U.ACTION_DATE, U.PLAN_DATE
    FROM LIB2_USAGE U
    JOIN LIB2_BOOKS B ON B.OBJ_ID = U.BOOK_ID AND B.OBJ_TYPE <> 18712
    LEFT JOIN LIB2_LISTVALS A ON A.LISTVAL_ID = B.AUTHOR_ID
    WHERE U.DATE_DEL IS NULL AND U.REF_ID = :V$PERSON_ID AND U.REF_TYPE_ID = :V$PERSON_TYPE AND U.RETURN_DATE IS NULL AND U.LOSS_DATE IS NULL
    ORDER BY 3, 1
    INTO :S, :S2, :D1, :D2
  DO
  BEGIN
    VAL = '<tr>';
      VAL = VAL || '<td>' || (SELECT VAL FROM ESCAPE_STR(:S)) || '</td>';
      VAL = VAL || '<td>' || (SELECT VAL FROM ESCAPE_STR(:S2)) || '</td>';
      VAL = VAL || '<td>' || (SELECT RESULT FROM DATE2STR(:D1)) || '</td>';
      VAL = VAL || '<td>' || (SELECT RESULT FROM DATE2STR(:D2)) || '</td>';
    VAL = VAL || '</tr>';
    SUSPEND;
  END
  VAL = '</tbody></table>';
  SUSPEND;

  VAL = '<div class="ui small blue header">Учебники на руках</div>';
  VAL = VAL || '<table class="ui small striped celled table"><thead><tr>';
  VAL = VAL || '<th>Название</th>';
  VAL = VAL || '<th>Автор</th>';
  VAL = VAL || '<th>Дата выдачи</th>';
  VAL = VAL || '<th>Срок возврата</th>';
  VAL = VAL || '</tr></thead><tbody>';
  SUSPEND;
  FOR
    SELECT B.BOOK_NAME, COALESCE(A.VAL, B.AUTHORS), U.ACTION_DATE, U.PLAN_DATE
    FROM LIB2_USAGE U
    JOIN LIB2_BOOKS B ON B.OBJ_ID = U.BOOK_ID AND B.OBJ_TYPE = 18712
    LEFT JOIN LIB2_LISTVALS A ON A.LISTVAL_ID = B.AUTHOR_ID
    WHERE U.DATE_DEL IS NULL AND U.REF_ID = :V$PERSON_ID AND U.REF_TYPE_ID = :V$PERSON_TYPE AND U.RETURN_DATE IS NULL AND U.LOSS_DATE IS NULL
    ORDER BY 3, 1
    INTO :S, :S2, :D1, :D2
  DO
  BEGIN
    VAL = '<tr>';
      VAL = VAL || '<td>' || (SELECT VAL FROM ESCAPE_STR(:S)) || '</td>';
      VAL = VAL || '<td>' || (SELECT VAL FROM ESCAPE_STR(:S2)) || '</td>';
      VAL = VAL || '<td>' || (SELECT RESULT FROM DATE2STR(:D1)) || '</td>';
      VAL = VAL || '<td>' || (SELECT RESULT FROM DATE2STR(:D2)) || '</td>';
    VAL = VAL || '</tr>';
    SUSPEND;
  END
  VAL = '</tbody></table>';
  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE MCAL_VIEW_VACATION (
    I$OBJ_ID BIGINT,
    I$ZONE SMALLINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    VAL VARCHAR(4000))
AS
DECLARE VARIABLE V$YEAR INTEGER;
DECLARE VARIABLE V$PERSON_ID BIGINT;
DECLARE VARIABLE V$DATE1 DATE;
DECLARE VARIABLE V$DATE2 DATE;
DECLARE VARIABLE V$D1 DATE;
DECLARE VARIABLE V$D2 DATE;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE N INTEGER;
DECLARE VARIABLE V$YEAR_STATE BIGINT;
DECLARE VARIABLE V$EDCLASS VARCHAR(100);
begin

  SELECT FIRST 1 U.OBJ_ID
  FROM USERS U
  WHERE U.USER_ID = :I$USER_ID AND U.DATE_DEL IS NULL
  INTO :V$PERSON_ID;

  IF(V$PERSON_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не найдена запись сотрудника для данного пользователя';

  -- Данные формы редактирования периода или нового периода (0)
  IF(I$OBJ_ID IS NOT NULL) THEN
  BEGIN
    SELECT FIRST 1 L37.OBJ_ID, V327.VAL, V328.VAL, V329.VAL
    FROM LINKS L37
    JOIN VALR V3582 ON V3582.OBJ_ID = L37.OBJ_ID AND V3582.PARAM_ID = 3582 AND V3582.IS_DEL = 0
    JOIN VALL V330 ON V330.OBJ_ID = L37.OBJ_ID AND V330.PARAM_ID = 330 AND V330.IS_DEL = 0 AND V330.LISTVAL_ID = 18710 -- план
    JOIN VALL V326 ON V326.OBJ_ID = L37.OBJ_ID AND V326.PARAM_ID = 326 AND V326.IS_DEL = 0 AND V326.LISTVAL_ID = 730 -- текущий
    JOIN VALD V327 ON V327.OBJ_ID = L37.OBJ_ID AND V327.PARAM_ID = 327 AND V327.IS_DEL = 0 -- дата начала
    JOIN VALD V328 ON V328.OBJ_ID = L37.OBJ_ID AND V328.PARAM_ID = 328 AND V328.IS_DEL = 0 -- дата окончания
    JOIN VALI V329 ON V329.OBJ_ID = L37.OBJ_ID AND V329.PARAM_ID = 329 AND V329.IS_DEL = 0 -- дата начала
    WHERE L37.PARENT_ID = :V$PERSON_ID AND L37.OBJ_TYPE_ID = 37 AND L37.DATE_DEL IS NULL AND L37.OBJ_ID = :I$OBJ_ID
    INTO :V$OBJ_ID, :V$D1, :V$D2, :N;

    IF(V$OBJ_ID IS NULL AND I$OBJ_ID <> 0) THEN EXCEPTION DATA_ERROR 'Данные не найдены';

    VAL = '<div class="date calendar field"><label>Дата начала</label><input type="hidden" name="date_from" value="' || COALESCE((SELECT VAL FROM DATE2ISO(:V$D1)), '') || '"></div>';
    VAL = VAL || '<div class="date calendar field"><label>Дата окончания</label><input type="hidden" name="date_to" value="' || COALESCE((SELECT VAL FROM DATE2ISO(:V$D2)), '') || '"></div>';
    VAL = VAL || '<div class="field"><label>Количество дней</label><input type="text" name="days" value="' || COALESCE(N, '') || '"></div>';
    VAL = VAL || '<input type="hidden" name="id" value="' || V$PERSON_ID || '">';
    IF(I$OBJ_ID > 0) THEN VAL = VAL || '<input type="hidden" name="obj_id" value="' || I$OBJ_ID || '">';
    VAL = VAL || '<input type="hidden" name="plan_type" value="18710">';
    VAL = VAL || '<input type="hidden" name="type_id" value="730">';
    VAL = VAL || '<input type="hidden" name="target" value="/webservice/app.calendar/execute?action=vacation_add">';
    IF(I$OBJ_ID > 0) THEN VAL = VAL || '<input type="hidden" name="delete_target" value="/webservice/app.calendar/execute?action=vacation_delete&obj_id=' || I$OBJ_ID || '&parent_id=' || V$PERSON_ID || '">';
    SUSPEND;

    EXIT;
  END

  -- Текущий год
  V$YEAR = EXTRACT(YEAR FROM CURRENT_DATE);
  V$DATE1 = '01.01.' || V$YEAR;
  V$DATE2 = '31.12.' || V$YEAR;

  SELECT FIRST 1 V3585.LISTVAL_ID
  FROM LINKS L2
  JOIN LINKS L534 ON L534.PARENT_ID = L2.OBJ_ID AND L534.OBJ_TYPE_ID = 534 AND L534.DATE_DEL IS NULL
  JOIN VALI V3584 ON V3584.OBJ_ID = L534.OBJ_ID AND V3584.PARAM_ID = 3584 AND V3584.IS_DEL = 0 AND V3584.VAL = :V$YEAR
  JOIN VALL V3585 ON V3585.OBJ_ID = L534.OBJ_ID AND V3585.PARAM_ID = 3585 AND V3585.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$YEAR_STATE;

  IF(V$YEAR_STATE = 11716) THEN V$EDCLASS = 'subform vacation_edit'; ELSE V$EDCLASS = '';

  VAL = '<div class="ui small blue header">Текущий год (' || V$YEAR || ')</div>';

  VAL = VAL || '<table class="ui small compact celled striped table">';
  VAL = VAL || '<thead><tr><th>Дата начала</th>';
  VAL = VAL || '<th>Дата окончания</th>';
  VAL = VAL || '<th>Количество дней</th></thead>';
  VAL = VAL || '<thead><tr><th colspan="4">Пожелания сотрудника</th></thead><tbody>';
  SUSPEND;
  FOR
    SELECT L37.OBJ_ID, V327.VAL, V328.VAL, V329.VAL
    FROM LINKS L37
    JOIN VALR V3582 ON V3582.OBJ_ID = L37.OBJ_ID AND V3582.PARAM_ID = 3582 AND V3582.IS_DEL = 0
    JOIN VALL V330 ON V330.OBJ_ID = L37.OBJ_ID AND V330.PARAM_ID = 330 AND V330.IS_DEL = 0 AND V330.LISTVAL_ID = 18710 -- план
    JOIN VALL V326 ON V326.OBJ_ID = L37.OBJ_ID AND V326.PARAM_ID = 326 AND V326.IS_DEL = 0 AND V326.LISTVAL_ID = 730 -- текущий
    JOIN VALD V327 ON V327.OBJ_ID = L37.OBJ_ID AND V327.PARAM_ID = 327 AND V327.IS_DEL = 0 -- дата начала
      AND V327.VAL >= :V$DATE1 AND V327.VAL < :V$DATE2
    JOIN VALD V328 ON V328.OBJ_ID = L37.OBJ_ID AND V328.PARAM_ID = 328 AND V328.IS_DEL = 0 -- дата окончания
    JOIN VALI V329 ON V329.OBJ_ID = L37.OBJ_ID AND V329.PARAM_ID = 329 AND V329.IS_DEL = 0 -- дата начала
    WHERE L37.PARENT_ID = :V$PERSON_ID AND L37.OBJ_TYPE_ID = 37 AND L37.DATE_DEL IS NULL
    ORDER BY V327.VAL
    INTO :V$OBJ_ID, :V$D1, :V$D2, :N
  DO
  BEGIN
    VAL = '<tr class="' || V$EDCLASS || '" data-value="' || V$OBJ_ID || '"><td>' || (SELECT RESULT FROM DATE2STR(:V$D1)) || '</td>';
    VAL = VAL || '<td>' || (SELECT RESULT FROM DATE2STR(:V$D1)) || '</td>';
    VAL = VAL || '<td>' || N || '</td></tr>';
    SUSPEND;
  END

  IF(V$EDCLASS <> '') THEN
  BEGIN
    VAL = '<tr class="' || V$EDCLASS || '" data-person_id="' || V$PERSON_ID || '"><td colspan="4">Добавить новый период</td></tr>';
    SUSPEND;
  END

  VAL = '</tbody><thead><tr><th colspan="4">План отпусков</th></thead><tbody>';
  SUSPEND;
  FOR
    SELECT L37.OBJ_ID, V327.VAL, V328.VAL, V329.VAL
    FROM LINKS L37
    JOIN VALR V3582 ON V3582.OBJ_ID = L37.OBJ_ID AND V3582.PARAM_ID = 3582 AND V3582.IS_DEL = 0
    JOIN VALL V330 ON V330.OBJ_ID = L37.OBJ_ID AND V330.PARAM_ID = 330 AND V330.IS_DEL = 0 AND V330.LISTVAL_ID = 736 -- план
    JOIN VALL V326 ON V326.OBJ_ID = L37.OBJ_ID AND V326.PARAM_ID = 326 AND V326.IS_DEL = 0 AND V326.LISTVAL_ID = 730 -- текущий
    JOIN VALD V327 ON V327.OBJ_ID = L37.OBJ_ID AND V327.PARAM_ID = 327 AND V327.IS_DEL = 0 -- дата начала
      AND V327.VAL >= :V$DATE1 AND V327.VAL < :V$DATE2
    JOIN VALD V328 ON V328.OBJ_ID = L37.OBJ_ID AND V328.PARAM_ID = 328 AND V328.IS_DEL = 0 -- дата окончания
    JOIN VALI V329 ON V329.OBJ_ID = L37.OBJ_ID AND V329.PARAM_ID = 329 AND V329.IS_DEL = 0 -- дата начала
    WHERE L37.PARENT_ID = :V$PERSON_ID AND L37.OBJ_TYPE_ID = 37 AND L37.DATE_DEL IS NULL
    ORDER BY V327.VAL
    INTO :V$OBJ_ID, :V$D1, :V$D2, :N
  DO
  BEGIN
    VAL = '<tr data-value="' || V$OBJ_ID || '"><td>' || (SELECT RESULT FROM DATE2STR(:V$D1)) || '</td>';
    VAL = VAL || '<td>' || (SELECT RESULT FROM DATE2STR(:V$D1)) || '</td>';
    VAL = VAL || '<td>' || N || '</td></tr>';
    SUSPEND;
  END

  VAL = '</tbody><thead><tr><th colspan="4">Фактические отпуска</th></thead><tbody>';
  SUSPEND;
  FOR
    SELECT L37.OBJ_ID, V327.VAL, V328.VAL, V329.VAL
    FROM LINKS L37
    JOIN VALR V3582 ON V3582.OBJ_ID = L37.OBJ_ID AND V3582.PARAM_ID = 3582 AND V3582.IS_DEL = 0
    JOIN VALL V330 ON V330.OBJ_ID = L37.OBJ_ID AND V330.PARAM_ID = 330 AND V330.IS_DEL = 0 AND V330.LISTVAL_ID = 735 -- план
    JOIN VALL V326 ON V326.OBJ_ID = L37.OBJ_ID AND V326.PARAM_ID = 326 AND V326.IS_DEL = 0 AND V326.LISTVAL_ID = 730 -- текущий
    JOIN VALD V327 ON V327.OBJ_ID = L37.OBJ_ID AND V327.PARAM_ID = 327 AND V327.IS_DEL = 0 -- дата начала
      AND V327.VAL >= :V$DATE1 AND V327.VAL < :V$DATE2
    JOIN VALD V328 ON V328.OBJ_ID = L37.OBJ_ID AND V328.PARAM_ID = 328 AND V328.IS_DEL = 0 -- дата окончания
    JOIN VALI V329 ON V329.OBJ_ID = L37.OBJ_ID AND V329.PARAM_ID = 329 AND V329.IS_DEL = 0 -- дата начала
    WHERE L37.PARENT_ID = :V$PERSON_ID AND L37.OBJ_TYPE_ID = 37 AND L37.DATE_DEL IS NULL
    ORDER BY V327.VAL
    INTO :V$OBJ_ID, :V$D1, :V$D2, :N
  DO
  BEGIN
    VAL = '<tr data-value="' || V$OBJ_ID || '"><td>' || (SELECT RESULT FROM DATE2STR(:V$D1)) || '</td>';
    VAL = VAL || '<td>' || (SELECT RESULT FROM DATE2STR(:V$D1)) || '</td>';
    VAL = VAL || '<td>' || N || '</td></tr>';
    SUSPEND;
  END

  VAL = '</tbody></table>';
  SUSPEND;

  -- Планируемый год, если он есть
  V$YEAR = V$YEAR + 1;
  V$DATE1 = '01.01.' || V$YEAR;
  V$DATE2 = '31.12.' || V$YEAR;

  V$YEAR_STATE = NULL;
  SELECT FIRST 1 V3585.LISTVAL_ID
  FROM LINKS L2
  JOIN LINKS L534 ON L534.PARENT_ID = L2.OBJ_ID AND L534.OBJ_TYPE_ID = 534 AND L534.DATE_DEL IS NULL
  JOIN VALI V3584 ON V3584.OBJ_ID = L534.OBJ_ID AND V3584.PARAM_ID = 3584 AND V3584.IS_DEL = 0 AND V3584.VAL = :V$YEAR
  JOIN VALL V3585 ON V3585.OBJ_ID = L534.OBJ_ID AND V3585.PARAM_ID = 3585 AND V3585.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$YEAR_STATE;

  IF(V$YEAR_STATE IS NULL) THEN EXIT;
  IF(V$YEAR_STATE = 11716) THEN V$EDCLASS = 'subform vacation_edit'; ELSE V$EDCLASS = '';

  VAL = '<div class="ui small blue header">Будущий год (' || V$YEAR || ')</div>';

  VAL = VAL || '<table class="ui small compact celled striped table">';
  VAL = VAL || '<thead><tr><th>Дата начала</th>';
  VAL = VAL || '<th>Дата окончания</th>';
  VAL = VAL || '<th>Количество дней</th></thead>';
  VAL = VAL || '<thead><tr><th colspan="4">Пожелания сотрудника</th></thead><tbody>';
  SUSPEND;
  FOR
    SELECT L37.OBJ_ID, V327.VAL, V328.VAL, V329.VAL
    FROM LINKS L37
    JOIN VALR V3582 ON V3582.OBJ_ID = L37.OBJ_ID AND V3582.PARAM_ID = 3582 AND V3582.IS_DEL = 0
    JOIN VALL V330 ON V330.OBJ_ID = L37.OBJ_ID AND V330.PARAM_ID = 330 AND V330.IS_DEL = 0 AND V330.LISTVAL_ID = 18710 -- план
    JOIN VALL V326 ON V326.OBJ_ID = L37.OBJ_ID AND V326.PARAM_ID = 326 AND V326.IS_DEL = 0 AND V326.LISTVAL_ID = 730 -- текущий
    JOIN VALD V327 ON V327.OBJ_ID = L37.OBJ_ID AND V327.PARAM_ID = 327 AND V327.IS_DEL = 0 -- дата начала
      AND V327.VAL >= :V$DATE1 AND V327.VAL < :V$DATE2
    JOIN VALD V328 ON V328.OBJ_ID = L37.OBJ_ID AND V328.PARAM_ID = 328 AND V328.IS_DEL = 0 -- дата окончания
    JOIN VALI V329 ON V329.OBJ_ID = L37.OBJ_ID AND V329.PARAM_ID = 329 AND V329.IS_DEL = 0 -- дата начала
    WHERE L37.PARENT_ID = :V$PERSON_ID AND L37.OBJ_TYPE_ID = 37 AND L37.DATE_DEL IS NULL
    ORDER BY V327.VAL
    INTO :V$OBJ_ID, :V$D1, :V$D2, :N
  DO
  BEGIN
    VAL = '<tr class="' || V$EDCLASS || '" data-value="' || V$OBJ_ID || '"><td>' || (SELECT RESULT FROM DATE2STR(:V$D1)) || '</td>';
    VAL = VAL || '<td>' || (SELECT RESULT FROM DATE2STR(:V$D1)) || '</td>';
    VAL = VAL || '<td>' || N || '</td></tr>';
    SUSPEND;
  END

  IF(V$EDCLASS <> '') THEN
  BEGIN
    VAL = '<tr class="' || V$EDCLASS || '" data-person_id="' || V$PERSON_ID || '"><td colspan="4">Добавить новый период</td></tr>';
    SUSPEND;
  END

  IF(V$YEAR_STATE = 11715) THEN
  BEGIN
    VAL = '</tbody><thead><tr><th colspan="4">План отпусков</th></thead><tbody>';
    SUSPEND;
    FOR
      SELECT L37.OBJ_ID, V327.VAL, V328.VAL, V329.VAL
      FROM LINKS L37
      JOIN VALR V3582 ON V3582.OBJ_ID = L37.OBJ_ID AND V3582.PARAM_ID = 3582 AND V3582.IS_DEL = 0
      JOIN VALL V330 ON V330.OBJ_ID = L37.OBJ_ID AND V330.PARAM_ID = 330 AND V330.IS_DEL = 0 AND V330.LISTVAL_ID = 736 -- план
      JOIN VALL V326 ON V326.OBJ_ID = L37.OBJ_ID AND V326.PARAM_ID = 326 AND V326.IS_DEL = 0 AND V326.LISTVAL_ID = 730 -- текущий
      JOIN VALD V327 ON V327.OBJ_ID = L37.OBJ_ID AND V327.PARAM_ID = 327 AND V327.IS_DEL = 0 -- дата начала
        AND V327.VAL >= :V$DATE1 AND V327.VAL < :V$DATE2
      JOIN VALD V328 ON V328.OBJ_ID = L37.OBJ_ID AND V328.PARAM_ID = 328 AND V328.IS_DEL = 0 -- дата окончания
      JOIN VALI V329 ON V329.OBJ_ID = L37.OBJ_ID AND V329.PARAM_ID = 329 AND V329.IS_DEL = 0 -- дата начала
      WHERE L37.PARENT_ID = :V$PERSON_ID AND L37.OBJ_TYPE_ID = 37 AND L37.DATE_DEL IS NULL
      ORDER BY V327.VAL
      INTO :V$OBJ_ID, :V$D1, :V$D2, :N
    DO
    BEGIN
      VAL = '<tr data-value="' || V$OBJ_ID || '"><td>' || (SELECT RESULT FROM DATE2STR(:V$D1)) || '</td>';
      VAL = VAL || '<td>' || (SELECT RESULT FROM DATE2STR(:V$D1)) || '</td>';
      VAL = VAL || '<td>' || N || '</td></tr>';
      SUSPEND;
    END
  END

  VAL = '</tbody></table>';
  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE MIGRATE_INT128 RETURNS (
    INDEX_FIX VARCHAR(1000),
    SEQ SMALLINT)
AS
DECLARE VARIABLE S VARCHAR(100);
DECLARE VARIABLE T VARCHAR(100);
DECLARE VARIABLE V$NAME VARCHAR(100);
DECLARE VARIABLE N INTEGER;
DECLARE VARIABLE F VARCHAR(100);
DECLARE VARIABLE REF VARCHAR(100);
DECLARE VARIABLE URULE VARCHAR(40);
DECLARE VARIABLE DRULE VARCHAR(40);
begin
  -- Порядок
  -- 1. Снести FK и обычные индексы
  -- 2. Снести PK
  -- 3. Обновить поля
  -- 4. Восстановить PK
  -- 5. Восстановить FK и обычные индексы

  -- Обновить поля BIGINT, которые не ссылаются на определенный набор таблиц
  SEQ = 3;
  FOR
    SELECT TRIM(RF.RDB$FIELD_NAME), TRIM(RF.RDB$RELATION_NAME)
    FROM RDB$RELATION_FIELDS RF
    JOIN RDB$FIELDS F ON F.RDB$FIELD_NAME = RF.RDB$FIELD_SOURCE AND F.RDB$FIELD_TYPE = 16
    JOIN RDB$RELATIONS R ON R.RDB$RELATION_NAME = RF.RDB$RELATION_NAME AND R.RDB$VIEW_SOURCE IS NULL
    WHERE RF.RDB$SYSTEM_FLAG = 0 AND RF.RDB$RELATION_NAME <> 'FULLLOAD_REQUESTS' AND RF.RDB$FIELD_NAME NOT IN ('GEN', 'RES_ID', 'VAL_I')
      AND RF.RDB$RELATION_NAME NOT IN ('LISTVALS', 'TYPES', 'PARAMS', 'RES', 'CJ2_CONTROL_TYPE', 'CJ2_MARK_TYPE', 'MODULES', 'TASKS', 'LEVELS', 'REPORTS', 'QUERYS',
        'LISTS', 'BARS', 'BARBUTTONS')
    AND NOT EXISTS (
      SELECT FIRST 1 1
      FROM RDB$INDEX_SEGMENTS SI
      JOIN RDB$INDICES I ON I.RDB$INDEX_NAME = SI.RDB$INDEX_NAME AND I.RDB$RELATION_NAME = RF.RDB$RELATION_NAME
      JOIN RDB$RELATION_CONSTRAINTS RC ON RC.RDB$INDEX_NAME = I.RDB$INDEX_NAME AND RC.RDB$CONSTRAINT_TYPE = 'FOREIGN KEY'
      JOIN RDB$REF_CONSTRAINTS RR ON RR.RDB$CONSTRAINT_NAME = RC.RDB$CONSTRAINT_NAME -- имя PK, на который ссылается FK
      JOIN RDB$RELATION_CONSTRAINTS RC2 ON RC2.RDB$CONSTRAINT_NAME = RR.RDB$CONST_NAME_UQ
        AND RC2.RDB$RELATION_NAME IN ('LISTVALS', 'TYPES', 'PARAMS', 'RES', 'CJ2_CONTROL_TYPE', 'CJ2_MARK_TYPE', 'MODULES', 'TASKS', 'LEVELS', 'REPORTS', 'QUERYS',
          'LISTS', 'BARS', 'BARBUTTONS')
      WHERE SI.RDB$FIELD_NAME = RF.RDB$FIELD_NAME
    )
    INTO :S, :T
  DO
  BEGIN
    INDEX_FIX = 'ALTER TABLE ' || T || ' ALTER ' || S || ' TYPE INT128;';
    SUSPEND;
  END

  -- 1. INDEX
  -- Тут два разных кейса - UNIQUE индексы (UNIQUE CONSTRAINT) и просто индексы для сортировки
  FOR
    SELECT TRIM(C.RDB$CONSTRAINT_NAME), TRIM(I.RDB$INDEX_NAME), TRIM(I.RDB$RELATION_NAME)
    FROM RDB$INDICES I
    JOIN RDB$RELATION_CONSTRAINTS C ON C.RDB$INDEX_NAME = I.RDB$INDEX_NAME AND C.RDB$CONSTRAINT_TYPE = 'UNIQUE'
    WHERE I.RDB$SYSTEM_FLAG = 0
    ORDER BY 3, 2
    INTO :S, :V$NAME, :T
  DO
  BEGIN
    SEQ = 1;
    INDEX_FIX = 'ALTER TABLE ' || T || ' DROP CONSTRAINT ' || S || ';';
    SUSPEND;

    SEQ = 5;
    INDEX_FIX = 'ALTER TABLE ' || T || ' ADD CONSTRAINT ' || S || ' UNIQUE (';

    FOR
      SELECT TRIM(S.RDB$FIELD_NAME), S.RDB$FIELD_POSITION
      FROM RDB$INDEX_SEGMENTS S
      WHERE S.RDB$INDEX_NAME = :V$NAME
      ORDER BY 2
      INTO :S, :N
    DO
    BEGIN
      IF(N > 0) THEN INDEX_FIX = INDEX_FIX || ', ';
      INDEX_FIX = INDEX_FIX || S;
    END
    INDEX_FIX = INDEX_FIX || ');';

    SUSPEND;
  END
  FOR
    SELECT TRIM(I.RDB$INDEX_NAME), TRIM(I.RDB$RELATION_NAME)
    FROM RDB$INDICES I
    LEFT JOIN RDB$RELATION_CONSTRAINTS C ON C.RDB$INDEX_NAME = I.RDB$INDEX_NAME
    WHERE I.RDB$SYSTEM_FLAG = 0 AND I.RDB$UNIQUE_FLAG = 0 AND C.RDB$RELATION_NAME IS NULL
    ORDER BY 2, 1
    INTO :V$NAME, :T
  DO
  BEGIN
    SEQ = 1;
    INDEX_FIX = 'DROP INDEX ' || V$NAME || ';';
    SUSPEND;

    SEQ = 5;
    INDEX_FIX = 'CREATE INDEX ' || V$NAME || ' ON ' || T || ' (';

    FOR
      SELECT TRIM(S.RDB$FIELD_NAME), S.RDB$FIELD_POSITION
      FROM RDB$INDEX_SEGMENTS S
      WHERE S.RDB$INDEX_NAME = :V$NAME
      ORDER BY 2
      INTO :S, :N
    DO
    BEGIN
      IF(N > 0) THEN INDEX_FIX = INDEX_FIX || ', ';
      INDEX_FIX = INDEX_FIX || S;
    END
    INDEX_FIX = INDEX_FIX || ');';

    SUSPEND;
  END

  -- 2. FOREGN KEY
  FOR
    SELECT TRIM(C.RDB$CONSTRAINT_NAME), TRIM(I.RDB$INDEX_NAME), TRIM(I.RDB$RELATION_NAME), TRIM(S.RDB$FIELD_NAME), TRIM(R.RDB$CONST_NAME_UQ),
      TRIM(R.RDB$UPDATE_RULE), TRIM(R.RDB$DELETE_RULE)
    FROM RDB$RELATION_CONSTRAINTS C
    JOIN RDB$INDICES I ON I.RDB$INDEX_NAME = C.RDB$INDEX_NAME AND I.RDB$SYSTEM_FLAG = 0
    JOIN RDB$REF_CONSTRAINTS R ON R.RDB$CONSTRAINT_NAME = C.RDB$CONSTRAINT_NAME -- политика обновления
    JOIN RDB$INDEX_SEGMENTS S ON S.RDB$INDEX_NAME = I.RDB$INDEX_NAME -- поле откуда идет ссылка
    WHERE C.RDB$CONSTRAINT_TYPE = 'FOREIGN KEY'
    ORDER BY 2, 1
    INTO :V$NAME, :S, :T, :F, :REF, :URULE, :DRULE
  DO
  BEGIN
    IF(S <> V$NAME) THEN S = 'FK_' || T || '_' || F;
    SEQ = 1;
    INDEX_FIX = 'ALTER TABLE ' || T || ' DROP CONSTRAINT ' || V$NAME || ';';
    SUSPEND;

    SEQ = 5;
    INDEX_FIX = 'ALTER TABLE ' || T || ' ADD CONSTRAINT ' || S || ' FOREIGN KEY (' || F || ') REFERENCES ';

    -- Достаем описание PK из REF - имя таблицы и поля
    SELECT TRIM(I.RDB$RELATION_NAME) || ' (' || TRIM(S.RDB$FIELD_NAME) || ')'
    FROM RDB$INDICES I
    JOIN RDB$INDEX_SEGMENTS S ON S.RDB$INDEX_NAME = I.RDB$INDEX_NAME
    WHERE I.RDB$INDEX_NAME = :REF
    INTO :F;

    INDEX_FIX = INDEX_FIX || F;
    IF(DRULE <> 'RESTRICT') THEN INDEX_FIX = INDEX_FIX || ' ON DELETE ' || DRULE;
    IF(URULE <> 'RESTRICT') THEN INDEX_FIX = INDEX_FIX || ' ON UPDATE ' || URULE;
    INDEX_FIX = INDEX_FIX || ';';

    SUSPEND;
  END

  -- 3. PRIMARY KEY
  -- Выбираем не из RDB$INDICES, а из RDB$RELATION_CONSTRAINTS
  FOR
    SELECT TRIM(C.RDB$CONSTRAINT_NAME), TRIM(I.RDB$RELATION_NAME), TRIM(I.RDB$INDEX_NAME)
    FROM RDB$RELATION_CONSTRAINTS C
    JOIN RDB$INDICES I ON I.RDB$INDEX_NAME = C.RDB$INDEX_NAME AND I.RDB$SYSTEM_FLAG = 0
    WHERE C.RDB$CONSTRAINT_TYPE = 'PRIMARY KEY'
    ORDER BY 2, 1
    INTO :S, :T, :V$NAME
  DO
  BEGIN
    SEQ = 2;
    INDEX_FIX = 'ALTER TABLE ' || T || ' DROP CONSTRAINT ' || S || ';';
    SUSPEND;

    -- Заменяем первичный ключ на явно прописанное имя
    IF(POSITION('$' IN S) > 0 OR POSITION('INTEG_' IN S) > 0) THEN S = 'PK_' || T;
    SEQ = 4;
    INDEX_FIX = 'ALTER TABLE ' || T || ' ADD CONSTRAINT ' || S || ' PRIMARY KEY (';

    FOR
      SELECT TRIM(S.RDB$FIELD_NAME), S.RDB$FIELD_POSITION
      FROM RDB$INDEX_SEGMENTS S
      WHERE S.RDB$INDEX_NAME = :V$NAME
      ORDER BY 2
      INTO :S, :N
    DO
    BEGIN
      IF(N > 0) THEN INDEX_FIX = INDEX_FIX || ', ';
      INDEX_FIX = INDEX_FIX || S;
    END
    INDEX_FIX = INDEX_FIX || ');';

    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE MODULES_ACTIVE_LIST (
    I$LANG_CODE CHAR(2))
RETURNS (
    MODULE_ID BIGINT,
    MODULE_CODE VARCHAR(100),
    MODULE_CAPTION VARCHAR(4000))
AS
declare variable v$res_id bigint;
BEGIN
    FOR
        SELECT MODULE_ID,
               RES_ID,
               MODULE_CODE
        FROM MODULES
        WHERE IS_ACTIVE = 1
        AND IS_DEL = 0
        ORDER BY SORT_ORDER
        INTO   :MODULE_ID,
               :V$RES_ID,
               :MODULE_CODE
    DO
    BEGIN
        SELECT VAL FROM RES_GET(:V$RES_ID, :I$LANG_CODE) INTO :MODULE_CAPTION;
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE MODULES_LIST (
    I$LANG_CODE VARCHAR(2) = 'RU')
RETURNS (
    MODULE_ID BIGINT,
    MODULE_CODE VARCHAR(100),
    RES_ID BIGINT,
    IS_ACTIVE SMALLINT,
    IS_DEL SMALLINT,
    MODULE_CAPTION VARCHAR(4000))
AS
BEGIN
    FOR
        SELECT MODULE_ID,
               MODULE_CODE,
               RES_ID,
               IS_ACTIVE,
               IS_DEL
        FROM MODULES
        WHERE IS_ACTIVE = 1
        ORDER BY SORT_ORDER,
                 MODULE_ID
        INTO   :MODULE_ID,
               :MODULE_CODE,
               :RES_ID,
               :IS_ACTIVE,
               :IS_DEL
    DO BEGIN
       SELECT VAL FROM RES_GET(:RES_ID, :I$LANG_CODE) INTO :MODULE_CAPTION;
       SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE MODULE_ACTIVATE (
    I$MODULE_ID BIGINT,
    I$IS_ACTIVE SMALLINT)
AS
BEGIN
  UPDATE MODULES SET IS_ACTIVE = :I$IS_ACTIVE WHERE MODULE_ID = :I$MODULE_ID;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE MODULE_ADD (
    I$MODULE_ID BIGINT,
    I$RES_ID BIGINT,
    I$MODULE_CODE VARCHAR(100),
    I$LANG_CODE CHAR(2),
    I$MODULE_CAPTION VARCHAR(4000),
    I$IS_ACTIVE SMALLINT = 1,
    I$IS_DEL SMALLINT = 0)
RETURNS (
    MODULE_ID BIGINT,
    RES_ID BIGINT)
AS
DECLARE VARIABLE SORT_ORDER SMALLINT;
BEGIN
    RES_ID = I$RES_ID;
    MODULE_ID = I$MODULE_ID;

    IF (I$MODULE_ID IS NULL) THEN
    BEGIN
        SELECT MAX(SORT_ORDER) + 1 FROM MODULES INTO :SORT_ORDER;
        IF (SORT_ORDER IS NULL) THEN SORT_ORDER = 1;

        INSERT INTO MODULES (MODULE_CODE, IS_ACTIVE, SORT_ORDER)
        VALUES (:I$MODULE_CODE, :I$IS_ACTIVE, :SORT_ORDER)
        RETURNING MODULE_ID, RES_ID INTO :MODULE_ID, :RES_ID;
    END
    ELSE
    BEGIN
        UPDATE MODULES
        SET MODULE_CODE = :I$MODULE_CODE,
            IS_ACTIVE = :I$IS_ACTIVE,
            IS_DEL = :I$IS_DEL
        WHERE MODULE_ID = :I$MODULE_ID;
    END

    IF (RES_ID IS NOT NULL) THEN
        EXECUTE PROCEDURE RES_ADD (:RES_ID,:I$LANG_CODE,:I$MODULE_CAPTION);

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE MODULE_MOVE (
    I$MODULE_ID BIGINT,
    I$MOVE SMALLINT)
RETURNS (
    SORT_ORDER SMALLINT)
AS
DECLARE VARIABLE MODULE_ID BIGINT;
BEGIN
   MODULE_ID = NULL;

   SELECT SORT_ORDER FROM MODULES WHERE MODULE_ID = :I$MODULE_ID INTO :SORT_ORDER;

   SELECT MODULE_ID FROM MODULES WHERE SORT_ORDER = (:SORT_ORDER + :I$MOVE) INTO :MODULE_ID;

   IF (MODULE_ID IS NOT NULL) THEN
   BEGIN
      UPDATE MODULES SET SORT_ORDER = :SORT_ORDER WHERE MODULE_ID = :MODULE_ID;
      UPDATE MODULES SET SORT_ORDER = (:SORT_ORDER + :I$MOVE) WHERE MODULE_ID = :I$MODULE_ID;
   END
   SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE MONITORING_BOOKS_GET_STAT (
    I$MONITORING_ID BIGINT,
    I$PARALLEL_LV BIGINT,
    I$STAT INTEGER,
    I$LEVEL_PUPIL_CNT INTEGER)
RETURNS (
    VAL INTEGER)
AS
declare variable V$YEAR integer;
declare variable V$PLAN_ID bigint;
declare variable V$STUDENTS_COUNT integer;
declare variable V$MISS_COUNT integer;
declare variable V$VSUBJ_ID bigint;
declare variable V$VAL integer;
declare variable V$V1 integer;
declare variable V$V2 integer;
declare variable V$V3 integer;
declare variable V$V4 integer;
declare variable V$V5 integer;
declare variable V$PREV integer;
declare variable V$T_VAL integer;
BEGIN

    /* Функция более неактуальна */

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE MONITORING_BOOKS_SUBSTAT (
    I$MONITORING_ID BIGINT,
    I$PARALLEL_LV BIGINT,
    I$PLAN_ID BIGINT,
    I$YEAR INTEGER)
RETURNS (
    SUBJECT_ID BIGINT,
    STUDENTS_COUNT INTEGER,
    BOOKS_COUNT INTEGER,
    MISS_COUNT INTEGER)
AS
begin

  /* Функция более неактуальна */

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE MONITORING_BOOKS_SUMMARY (
    I$SCHOOL_ID BIGINT,
    I$PARALLEL_LV BIGINT,
    I$OLD_BOOKS SMALLINT = 1,
    I$LIB2 SMALLINT = 0)
RETURNS (
    SUBJECT_ID BIGINT,
    PLAN_ID BIGINT,
    STAGE_ID BIGINT,
    LOAD_ID BIGINT,
    STUDENTS_COUNT INTEGER,
    BOOKS_COUNT INTEGER,
    MISS_COUNT INTEGER)
AS
DECLARE VARIABLE V$YEAR INTEGER;
DECLARE VARIABLE V$ALT_SUBJECT_ID BIGINT;
DECLARE VARIABLE V$HAS_PH SMALLINT;
DECLARE VARIABLE V$HAS_TECH SMALLINT;
DECLARE VARIABLE V$PREV_STAGE BIGINT;
DECLARE VARIABLE V$EOD DATE;
begin

    /* Возвращает только данные по сечениям, где есть ученики, при этом количество учебников ограничено числом учеников */
    /* Внимание: все будет корректно работать только если ученики одновременно могут фигурировать только в одном коллективе по интересующему предмету */

    V$YEAR = EXTRACT(YEAR FROM CURRENT_DATE);
    IF(EXTRACT(MONTH FROM CURRENT_DATE) < 9) THEN V$EOD = '01.05.' || V$YEAR; ELSE V$EOD = '01.05.' || (V$YEAR + 1);

    -- Теперь учитываем только действующие учебники на текущую дату
    I$OLD_BOOKS = 0;

    -- Флаги для фиксации наличия разновидностей физкультуры и технологии
    V$PREV_STAGE = NULL;
    V$HAS_PH = 0;
    V$HAS_TECH = 0;

    FOR
        -- Школы
        SELECT MP.SUBJECT_ID, L400.OBJ_ID, L54.OBJ_ID, MP.LOAD_ID
        FROM LINKS L69
        /* Образовательная программа */
        JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
        /* Учебный план */
        JOIN LINKS L400 ON L400.PARENT_ID = L57.OBJ_ID AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL
        /* Убираем планы ВД */
        LEFT JOIN VALL VD ON VD.OBJ_ID = L400.OBJ_ID and VD.PARAM_ID = 3022 AND VD.IS_DEL = 0
        /* Убираем индивидуальные планы */
        LEFT JOIN VALL VI ON VI.OBJ_ID = L400.OBJ_ID and VI.PARAM_ID = 3016 AND VI.IS_DEL = 0
        /* Только неадаптированные программы */
        LEFT JOIN VALL V2379 ON V2379.OBJ_ID = L57.OBJ_ID AND V2379.PARAM_ID = 2379 AND V2379.IS_DEL = 0
        /* Этапы УП - фильтр по параллели */
        JOIN LINKS L54 ON L54.PARENT_ID = L400.OBJ_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
        JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID and V381.PARAM_ID = 381 AND V381.IS_DEL = 0 AND V381.LISTVAL_ID = :I$PARALLEL_LV
        /* Прямая выборка предметов с прописанными нагрузками - переносим во вложенную функцию */
        LEFT JOIN MONITORING_PLAN_SUBJECTS(L400.OBJ_ID, L54.OBJ_ID, V381.LISTVAL_ID) MP ON 1 = 1
        WHERE L69.PARENT_ID = :I$SCHOOL_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL
            AND (VD.LISTVAL_ID IS NULL OR VD.LISTVAL_ID = 3) AND (VI.LISTVAL_ID IS NULL OR VI.LISTVAL_ID = 5465)
            AND (V2379.LISTVAL_ID IS NULL OR V2379.LISTVAL_ID = 11187)
            AND (MP.COMPONENT_TYPE IS NULL OR MP.COMPONENT_TYPE = 13303) AND MP.IS_ELECTIVE = 0
        ORDER BY 2, 3, 4
        INTO :SUBJECT_ID, :PLAN_ID, :STAGE_ID, :LOAD_ID
    DO
    BEGIN

        IF(V$PREV_STAGE IS NOT NULL AND V$PREV_STAGE <> STAGE_ID) THEN
        BEGIN
          V$HAS_PH = 0;
          V$HAS_TECH = 0;
        END
        V$PREV_STAGE = STAGE_ID;

        -- Количество учеников - из ГУП, в параллели где есть такой предмет
        SELECT COUNT(DISTINCT L10.OBJ_ID)
        FROM LINKS L256
        JOIN PLAN_SUBJECTS PS ON PS.DATE_DEL IS NULL AND PS.SUBJECT_ID = :SUBJECT_ID AND PS.PLAN_ID = :PLAN_ID
        JOIN PLAN_LOADS PL ON PL.DATE_DEL IS NULL AND PL.SUBJECT_ID = PS.OBJ_ID AND PL.STAGE_ID = L256.PARENT_ID AND (PL.LOAD_HOURS_S1 > 0 OR PL.LOAD_HOURS_S2 > 0)
        JOIN LINKS L10 ON L10.PARENT_ID = L256.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        WHERE L256.PARENT_ID = :STAGE_ID AND L256.OBJ_TYPE_ID = 256 AND L256.DATE_DEL IS NULL
        INTO :STUDENTS_COUNT;

        -- Явно прописанный алиасинг предметов, за исключением реально разных предметов (например, математика)
        V$ALT_SUBJECT_ID = NULL;

        SELECT FIRST 1 PS.SRC_SUBJECT_ID
        FROM PLAN_SUBJECTS PS
        WHERE PS.DATE_DEL IS NULL AND PS.SUBJECT_ID = :SUBJECT_ID AND PS.PLAN_ID = :PLAN_ID AND PS.SRC_SUBJECT_ID IS NOT NULL
        INTO :V$ALT_SUBJECT_ID;

        IF(V$ALT_SUBJECT_ID = 190) THEN V$ALT_SUBJECT_ID = NULL;

        IF(V$ALT_SUBJECT_ID IS NOT NULL) THEN SUBJECT_ID = V$ALT_SUBJECT_ID;

        -- Специальные проверки для физкультуры и технологии - при наличии нескольких разновидностей, в зачет берем только первую
        -- Пропуск выполняем обнулением количества студентов
        IF((V$ALT_SUBJECT_ID = 205 AND V$HAS_PH <> 0) OR (V$ALT_SUBJECT_ID = 200 AND V$HAS_TECH <> 0)) THEN STUDENTS_COUNT = 0;

        IF(STUDENTS_COUNT IS NOT NULL AND STUDENTS_COUNT > 0) THEN
        BEGIN
          BOOKS_COUNT = NULL;

          -- Количество учебников
          -- старая схема через МТР
          IF(I$LIB2 = 0) THEN
            SELECT SUM(R.QTY)
            FROM PLAN_RESOURCES R
            -- Дополнительная проверка что учебник не был удален
            JOIN LINKS LP105 ON LP105.PARENT_TYPE_ID = 105 AND LP105.OBJ_ID = R.RES_ID AND LP105.DATE_DEL IS NULL
            JOIN VALS VC ON VC.OBJ_ID = R.RES_ID AND VC.PARAM_ID = 2655 AND VC.IS_DEL = 0
            JOIN VALS V650 ON V650.OBJ_ID = R.RES_ID AND V650.PARAM_ID = 650 AND V650.IS_DEL = 0
            JOIN LIB_FPU_CODES C ON C.DATE_DEL IS NULL AND C.BOOKCODE = VC.SVAL -- AND C.DATE_ADD <= '31.12.2021'
            LEFT JOIN LIB_FPU_CODES C2 ON C2.DATE_DEL IS NULL AND C2.BOOKCODE = C.BOOKCODE AND C2.DATE_ADD > C.DATE_ADD -- AND C2.DATE_ADD <= '31.12.2021'
            JOIN LIB_FPU B ON B.OBJ_ID = C.BOOK_ID AND B.DATE_DEL IS NULL
              AND (B.YEAR_REMOVE IS NULL OR B.YEAR_REMOVE > :V$YEAR) -- год исключения - старая схема учета
              AND (B.VALID_BY IS NULL OR B.VALID_BY >= :V$EOD) -- дата окончания аккредитации - новая схема учета
            WHERE R.DATE_DEL IS NULL AND R.LOAD_ID = :LOAD_ID AND C2.BOOK_ID IS NULL
            INTO :BOOKS_COUNT;
          ELSE
            -- новая схема через библиограф
            SELECT SUM(U.QUANTITY)
            FROM LIB2_USAGE U
            JOIN LIB2_BOOKS BB ON BB.OBJ_ID = U.BOOK_ID
            JOIN LIB_FPU B ON B.OBJ_ID = BB.FPU_ID AND B.DATE_DEL IS NULL
              AND (B.YEAR_REMOVE IS NULL OR B.YEAR_REMOVE > :V$YEAR) -- год исключения - старая схема учета
              AND (B.VALID_BY IS NULL OR B.VALID_BY >= :V$EOD) -- дата окончания аккредитации - новая схема учета
            WHERE U.DATE_DEL IS NULL AND U.LOAD_ID = :LOAD_ID AND U.RETURN_DATE IS NULL AND U.REF_TYPE_ID = 9
            INTO :BOOKS_COUNT;

          IF(BOOKS_COUNT IS NULL) THEN BOOKS_COUNT = 0;
          IF(BOOKS_COUNT > STUDENTS_COUNT) THEN BOOKS_COUNT = STUDENTS_COUNT;
          MISS_COUNT = STUDENTS_COUNT - BOOKS_COUNT;

          IF(BOOKS_COUNT > 0) THEN
          BEGIN
            IF(SUBJECT_ID = 200) THEN V$HAS_TECH = 1;
            IF(SUBJECT_ID = 205) THEN V$HAS_PH = 1;
          END

          SUSPEND;
        END

    END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE MONITORING_BOOK_ADD (
    I$MONITORING_ID BIGINT,
    I$PARALLEL_ID BIGINT,
    I$PLAN_ID BIGINT,
    I$SUBJECT_ID BIGINT,
    I$BOOK_CODE VARCHAR(50),
    I$STUDENTS_CNT INTEGER,
    I$BOOK_CNT INTEGER,
    I$BOOK_YEAR INTEGER)
RETURNS (
    OBJ_ID BIGINT)
AS
BEGIN

    /* Обновляем строчку по сечению отчетности - обеспеченность учебниками */

    SELECT FIRST 1 L.OBJ_ID
    FROM LINKS L
    JOIN VALL VL ON VL.OBJ_ID = L.OBJ_ID AND VL.PARAM_ID = 2672 AND VL.IS_DEL = 0 AND VL.LISTVAL_ID = :I$PARALLEL_ID
    JOIN VALR VP ON VP.OBJ_ID = L.OBJ_ID AND VP.PARAM_ID = 2673 AND VP.IS_DEL = 0 AND VP.VAL = :I$PLAN_ID
    JOIN VALR VS ON VS.OBJ_ID = L.OBJ_ID AND VS.PARAM_ID = 2675 AND VS.IS_DEL = 0 AND VS.VAL = :I$SUBJECT_ID
    JOIN VALS VB ON VB.OBJ_ID = L.OBJ_ID AND VB.PARAM_ID = 2678 AND VB.IS_DEL = 0 AND VB.VAL = :I$BOOK_CODE
    LEFT JOIN VALI VI ON VI.OBJ_ID = L.OBJ_ID AND VI.PARAM_ID = 2683 AND VI.IS_DEL = 0 AND VI.VAL = :I$BOOK_YEAR
    WHERE L.PARENT_ID = :I$MONITORING_ID AND L.OBJ_TYPE_ID = 344 AND L.DATE_DEL IS NULL
      AND (:I$BOOK_YEAR IS NULL OR VI.VAL = :I$BOOK_YEAR)
    INTO :OBJ_ID;

    IF(OBJ_ID IS NULL) THEN
    BEGIN
      SELECT OBJ_ID FROM OBJECT_ADD(:I$MONITORING_ID, 344) INTO :OBJ_ID;

      UPDATE OR INSERT INTO VALL (OBJ_ID, PARAM_ID, LISTVAL_ID, IS_DEL)
      VALUES (:OBJ_ID, 2672, :I$PARALLEL_ID, 0);

      UPDATE OR INSERT INTO VALR (OBJ_ID, PARAM_ID, VAL, IS_DEL)
      VALUES (:OBJ_ID, 2673, :I$PLAN_ID, 0);

      UPDATE OR INSERT INTO VALR (OBJ_ID, PARAM_ID, VAL, IS_DEL)
      VALUES (:OBJ_ID, 2675, :I$SUBJECT_ID, 0);

      UPDATE OR INSERT INTO VALS (OBJ_ID, PARAM_ID, VAL, IS_DEL)
      VALUES (:OBJ_ID, 2678, :I$BOOK_CODE, 0);
   END

   UPDATE OR INSERT INTO VALI (OBJ_ID, PARAM_ID, VAL, IS_DEL)
   VALUES (:OBJ_ID, 2674, :I$STUDENTS_CNT, 0);

   UPDATE OR INSERT INTO VALI (OBJ_ID, PARAM_ID, VAL, IS_DEL)
   VALUES (:OBJ_ID, 2676, :I$BOOK_CNT, 0);

   IF(I$BOOK_YEAR IS NOT NULL AND I$BOOK_YEAR > 0) THEN
   BEGIN
      UPDATE OR INSERT INTO VALI (OBJ_ID, PARAM_ID, VAL, IS_DEL)
      VALUES (:OBJ_ID, 2683, :I$BOOK_YEAR, 0);
   END

   SUSPEND;

  WHEN ANY DO
  BEGIN
    EXCEPTION DATA_ERROR 'Ошибка с кодом ФПУ ' || COALESCE(I$BOOK_CODE, 'N/A') || ' за ' || COALESCE(I$BOOK_YEAR, '?') || ' год';
  END

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE MONITORING_BUFFETS (
    I$SCHOOL_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    BUFFET_ID BIGINT,
    BUILDING_ID BIGINT,
    BUFFET_NAME VARCHAR(1000),
    BUFFET_PURPOSE VARCHAR(1000),
    BUILDING_NAME VARCHAR(1000),
    SEATS_PRO INTEGER,
    SEATS_FACT INTEGER,
    BUFFET_SQUARE FLOAT)
AS
declare variable LANG_CODE varchar(2);
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :LANG_CODE;

    FOR
        SELECT L16.OBJ_ID,
               L61.OBJ_ID,
               VF.VAL,
               VI2.VAL,
               VI3.VAL,
               R.VAL
        FROM LINKS L73

        JOIN LINKS L16
        ON L16.PARENT_ID = L73.OBJ_ID
        AND L16.DATE_DEL IS NULL
        AND L16.OBJ_TYPE_ID = 16

        JOIN LINKS L61
        ON L61.PARENT_ID = L16.OBJ_ID
        AND L61.DATE_DEL IS NULL
        AND L61.OBJ_TYPE_ID = 61

        JOIN VALL VL
        ON VL.OBJ_ID = L61.OBJ_ID
        AND VL.IS_DEL = 0
        AND VL.PARAM_ID = 526
        AND VL.LISTVAL_ID IN (1155,1156)

        LEFT JOIN LISTVALS LVL
        ON LVL.LISTVAL_ID = VL.LISTVAL_ID

        LEFT JOIN RES_GET(LVL.RES_ID,  :LANG_CODE) R ON 1=1

        JOIN VALF VF
        ON VF.OBJ_ID = L61.OBJ_ID
        AND VF.IS_DEL = 0
        AND VF.PARAM_ID = 533

        JOIN VALI VI2
        ON VI2.OBJ_ID = L61.OBJ_ID
        AND VI2.IS_DEL = 0
        AND VI2.PARAM_ID = 531

        JOIN VALI VI3
        ON VI3.OBJ_ID = L61.OBJ_ID
        AND VI3.IS_DEL = 0
        AND VI3.PARAM_ID = 532

        WHERE L73.PARENT_ID = :I$SCHOOL_ID
        AND L73.DATE_DEL IS NULL
        AND L73.OBJ_TYPE_ID = 73

        INTO :BUILDING_ID,
             :BUFFET_ID,
             :BUFFET_SQUARE,
             :SEATS_PRO,
             :SEATS_FACT,
             :BUFFET_PURPOSE
    DO
    BEGIN
        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:BUFFET_ID,NULL,NULL,:I$USER_ID)
        INTO :BUFFET_NAME;

        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:BUILDING_ID,NULL,NULL,:I$USER_ID)
        INTO :BUILDING_NAME;

        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE MONITORING_BUILDINGS (
    I$SCHOOL_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    BUILDING_ID BIGINT,
    NAME VARCHAR(1000),
    ADDRESS VARCHAR(2000),
    REGION VARCHAR(255),
    DISTRICT VARCHAR(255),
    TOWN VARCHAR(255),
    SETTLEMENT VARCHAR(255),
    STREET VARCHAR(255),
    HOUSE VARCHAR(10),
    LITER VARCHAR(10),
    CORP VARCHAR(10),
    FLAT VARCHAR(10),
    POST_INDEX VARCHAR(20),
    SPORTS_GROUND VARCHAR(10),
    STADIUM_ARTIFICAL VARCHAR(10),
    STADIUM_NATURAL VARCHAR(10),
    FENCE_ID BIGINT,
    FENCE VARCHAR(255),
    STUDY_ROOM_SQUARE FLOAT)
AS
declare variable LANG_CODE varchar(2);
declare variable STEAD_ID bigint;
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :LANG_CODE;

    FOR
        SELECT L16.OBJ_ID, VF.VAL, V3408.VAL
        FROM LINKS L73
        JOIN LINKS L16 ON L16.PARENT_ID = L73.OBJ_ID AND L16.DATE_DEL IS NULL AND L16.OBJ_TYPE_ID = 16
        LEFT JOIN VALF VF ON VF.OBJ_ID = L16.OBJ_ID AND VF.IS_DEL = 0 AND VF.PARAM_ID = 499
        LEFT JOIN VALR V3408 ON V3408.OBJ_ID = L16.OBJ_ID AND V3408.IS_DEL = 0 AND V3408.PARAM_ID = 3408
        --LEFT JOIN VALL VL ON VL.OBJ_ID = L16.OBJ_ID AND VL.IS_DEL = 0 AND VL.PARAM_ID = 1446 AND VL.LISTVAL_ID = 2
        --LEFT JOIN VALL VL2 ON VL2.OBJ_ID = L16.OBJ_ID AND VL2.IS_DEL = 0 AND VL2.PARAM_ID = 1443 AND VL2.LISTVAL_ID = 2
        --LEFT JOIN VALL VL3 ON VL3.OBJ_ID = L16.OBJ_ID AND VL3.IS_DEL = 0 AND VL3.PARAM_ID = 1441 AND VL3.LISTVAL_ID = 2
        WHERE L73.PARENT_ID = :I$SCHOOL_ID AND L73.DATE_DEL IS NULL AND L73.OBJ_TYPE_ID = 73
        INTO :BUILDING_ID, :STUDY_ROOM_SQUARE, :STEAD_ID
    DO
    BEGIN
        SELECT REGION, DISTRICT, TOWN, SETTLEMENT, STREET, HOUSE, CORP, LITER, FLAT, POST_INDEX, VAL
        FROM ADR_GET(420,:BUILDING_ID)
        INTO :REGION, :DISTRICT, :TOWN, :SETTLEMENT, :STREET, :HOUSE, :CORP, :LITER, :FLAT, :POST_INDEX, :ADDRESS;
        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:BUILDING_ID, NULL, NULL, :I$USER_ID)
        INTO :NAME;

        -- Наличие спортивных сооружений и ограждения
        SPORTS_GROUND = 'Нет';
        STADIUM_ARTIFICAL = 'Нет';
        STADIUM_NATURAL = 'Нет';
        FENCE_ID = NULL;
        FENCE = NULL;

        SELECT FIRST 1 VFENCE.LISTVAL_ID, R.VAL
        FROM VALL VFENCE
        JOIN LISTVALS LVL ON LVL.LISTVAL_ID = VFENCE.LISTVAL_ID
        LEFT JOIN RES_GET(LVL.RES_ID, :LANG_CODE) R ON 1 = 1
        WHERE VFENCE.OBJ_ID = :STEAD_ID AND VFENCE.IS_DEL = 0 AND VFENCE.PARAM_ID = 3404 -- 522
        INTO :FENCE_ID, :FENCE;

        IF(STEAD_ID IS NOT NULL AND EXISTS(
          SELECT FIRST 1 1
          FROM VALR V3407
          JOIN LINKS LP73 ON LP73.OBJ_ID = V3407.OBJ_ID AND LP73.PARENT_TYPE_ID = 73 AND LP73.DATE_DEL IS NULL -- живое сооружение
          JOIN VALL V3398 ON V3398.OBJ_ID = V3407.OBJ_ID AND V3398.PARAM_ID = 3398 AND V3398.IS_DEL = 0 AND V3398.LISTVAL_ID = 14242
          LEFT JOIN VALD V3411 ON V3411.OBJ_ID = V3407.OBJ_ID AND V3411.PARAM_ID = 3411 AND V3411.IS_DEL = 0
          WHERE V3407.PARAM_ID = 3407 AND V3407.IS_DEL = 0 AND V3407.VAL = :STEAD_ID AND V3411.VAL IS NULL
        ))
        THEN
          SPORTS_GROUND = 'Да';

        IF(STEAD_ID IS NOT NULL AND EXISTS(
          SELECT FIRST 1 1
          FROM VALR V3407
          JOIN LINKS LP73 ON LP73.OBJ_ID = V3407.OBJ_ID AND LP73.PARENT_TYPE_ID = 73 AND LP73.DATE_DEL IS NULL -- живое сооружение
          JOIN VALL V3398 ON V3398.OBJ_ID = V3407.OBJ_ID AND V3398.PARAM_ID = 3398 AND V3398.IS_DEL = 0 AND V3398.LISTVAL_ID = 14244
          LEFT JOIN VALD V3411 ON V3411.OBJ_ID = V3407.OBJ_ID AND V3411.PARAM_ID = 3411 AND V3411.IS_DEL = 0
          WHERE V3407.PARAM_ID = 3407 AND V3407.IS_DEL = 0 AND V3407.VAL = :STEAD_ID
        ))
        THEN
          STADIUM_ARTIFICAL = 'Да';

        IF(STEAD_ID IS NOT NULL AND EXISTS(
          SELECT FIRST 1 1
          FROM VALR V3407
          JOIN LINKS LP73 ON LP73.OBJ_ID = V3407.OBJ_ID AND LP73.PARENT_TYPE_ID = 73 AND LP73.DATE_DEL IS NULL -- живое сооружение
          JOIN VALL V3398 ON V3398.OBJ_ID = V3407.OBJ_ID AND V3398.PARAM_ID = 3398 AND V3398.IS_DEL = 0 AND V3398.LISTVAL_ID = 14243
          LEFT JOIN VALD V3411 ON V3411.OBJ_ID = V3407.OBJ_ID AND V3411.PARAM_ID = 3411 AND V3411.IS_DEL = 0
          WHERE V3407.PARAM_ID = 3407 AND V3407.IS_DEL = 0 AND V3407.VAL = :STEAD_ID
        ))
        THEN
          STADIUM_NATURAL = 'Да';

        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE MONITORING_CONTINGENT_ADD
AS
DECLARE VARIABLE V$MON_ID BIGINT;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$BLOB_ID BIGINT;
DECLARE VARIABLE V$LISTVAL_ID BIGINT;
BEGIN
    SELECT OBJ_ID FROM LINKS
    WHERE OBJ_TYPE_ID = 162 AND DATE_DEL IS NULL
    INTO :V$MON_ID;

    IF (V$MON_ID IS NULL) THEN EXIT;

    -- Маркируем как удаленные все записи что были в подразделах, затем нужное вернем
    UPDATE LINKS L
    SET L.DATE_DEL = CURRENT_TIMESTAMP
    WHERE L.PARENT_ID = :V$MON_ID AND L.OBJ_TYPE_ID IN (265, 368);

    -- Добавляем строки из списка + строку ИТОГО
    FOR
        SELECT LISTVAL_ID
        FROM FILTRED_LIST(22, 'DO')
        UNION
        SELECT 10974
        FROM RDB$DATABASE
        INTO :V$LISTVAL_ID
    DO
    BEGIN
            -- Общее ДО тип 265
            V$OBJ_ID = NULL;
            SELECT L.OBJ_ID
            FROM LINKS L
            JOIN VALL V2196 ON V2196.PARAM_ID = 2196 AND V2196.OBJ_ID = L.OBJ_ID AND V2196.IS_DEL = 0 AND V2196.LISTVAL_ID = :V$LISTVAL_ID
            WHERE L.OBJ_TYPE_ID = 265 INTO :V$OBJ_ID;
            IF (V$OBJ_ID IS NULL) THEN
            BEGIN
                -- Добавляем новый
                SELECT OBJ_ID FROM OBJECT_ADD(:V$MON_ID, 265) INTO :V$OBJ_ID;
                SELECT BLOB_ID FROM VAL_ADD(2196, :V$OBJ_ID, :V$LISTVAL_ID) INTO :V$BLOB_ID;
            END
            ELSE
            BEGIN
                -- Возвращаем старый
                UPDATE LINKS L
                SET L.DATE_DEL = NULL
                WHERE L.PARENT_ID = :V$MON_ID AND L.OBJ_ID = :V$OBJ_ID;
            END
            -- Кружки вне ОДОД тип 368
            V$OBJ_ID = NULL;
            SELECT L.OBJ_ID
            FROM LINKS L
            JOIN VALL V2826 ON V2826.PARAM_ID = 2826 AND V2826.OBJ_ID = L.OBJ_ID AND V2826.IS_DEL = 0 AND V2826.LISTVAL_ID = :V$LISTVAL_ID
            WHERE L.OBJ_TYPE_ID = 368 INTO :V$OBJ_ID;
            IF (V$OBJ_ID IS NULL) THEN
            BEGIN
                SELECT OBJ_ID FROM OBJECT_ADD(:V$MON_ID, 368) INTO :V$OBJ_ID;
                SELECT BLOB_ID FROM VAL_ADD(2826, :V$OBJ_ID, :V$LISTVAL_ID) INTO :V$BLOB_ID;
            END
            ELSE
            BEGIN
                -- Возвращаем старый
                UPDATE LINKS L
                SET L.DATE_DEL = NULL
                WHERE L.PARENT_ID = :V$MON_ID AND L.OBJ_ID = :V$OBJ_ID;
            END
    END

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE MONITORING_CONTINGENT_DO_ADD
AS
BEGIN
  -- Удалено 06.12.2016
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE MONITORING_CURRICULUMTABL10_SET (
    I$SCHOOL_ID BIGINT,
    I$STAGE_ID BIGINT,
    I$GUP_ID BIGINT,
    I$SUBJECT_ID BIGINT,
    I$VAL1 INTEGER,
    I$VAL2 INTEGER,
    I$VAL3 FLOAT)
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$MONITORING_ID bigint;
declare variable V$BLOB_ID bigint;
BEGIN

    SELECT FIRST 1 L162.OBJ_ID
    FROM LINKS L162
    WHERE L162.PARENT_ID = :I$SCHOOL_ID AND L162.OBJ_TYPE_ID = 162 AND L162.DATE_DEL IS NULL
    INTO :V$MONITORING_ID;

    OBJ_ID = NULL;
    SELECT FIRST 1 L319.OBJ_ID
    FROM LINKS L319
    JOIN VALL V2537 ON V2537.OBJ_ID = L319.OBJ_ID AND V2537.PARAM_ID = 2537 AND V2537.IS_DEL = 0 AND V2537.LISTVAL_ID = :I$STAGE_ID
    JOIN VALR V2538 ON V2538.OBJ_ID = L319.OBJ_ID AND V2538.PARAM_ID = 2538 AND V2538.IS_DEL = 0 AND V2538.VAL = :I$GUP_ID
    JOIN VALR V2539 ON V2539.OBJ_ID = L319.OBJ_ID AND V2539.PARAM_ID = 2539 AND V2539.IS_DEL = 0 AND V2539.VAL = :I$SUBJECT_ID
    WHERE L319.PARENT_ID = :V$MONITORING_ID AND L319.OBJ_TYPE_ID = 319
    INTO :OBJ_ID;

    IF (OBJ_ID IS NULL) THEN
    BEGIN
      SELECT OBJ_ID FROM OBJECT_ADD(:V$MONITORING_ID, 319) INTO :OBJ_ID;
    END
    ELSE
    BEGIN
      UPDATE LINKS
      SET DATE_DEL = NULL
      WHERE PARENT_ID = :V$MONITORING_ID AND OBJ_ID = :OBJ_ID AND DATE_DEL IS NOT NULL;
    END

    IF (OBJ_ID IS NOT NULL) THEN
    BEGIN
      SELECT BLOB_ID FROM VAL_ADD(2537, :OBJ_ID, :I$STAGE_ID) INTO :V$BLOB_ID;
      SELECT BLOB_ID FROM VAL_ADD(2538, :OBJ_ID, :I$GUP_ID) INTO :V$BLOB_ID;
      SELECT BLOB_ID FROM VAL_ADD(2539, :OBJ_ID, :I$SUBJECT_ID) INTO :V$BLOB_ID;
      SELECT BLOB_ID FROM VAL_ADD(2540, :OBJ_ID, :I$VAL1) INTO :V$BLOB_ID;
      SELECT BLOB_ID FROM VAL_ADD(2541, :OBJ_ID, :I$VAL2) INTO :V$BLOB_ID;
      SELECT BLOB_ID FROM VAL_ADD(2542, :OBJ_ID, :I$VAL3) INTO :V$BLOB_ID;
    END

    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE MONITORING_CURRICULUMTABL11_SET (
    I$SCHOOL_ID BIGINT,
    I$CURRICULUM_ID BIGINT,
    I$VAL1 BIGINT,
    I$VAL2 BIGINT,
    I$PROFILED_CNT BIGINT,
    I$VAL4 BIGINT,
    I$HOURS_ALL BIGINT,
    I$HOURS_INVAR BIGINT,
    I$HOURS_VAR BIGINT,
    I$VAL7 BIGINT,
    I$VAL8 BIGINT,
    I$STANDARD BIGINT,
    I$SUBJECTS BIGINT,
    I$VAL10 BIGINT)
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$MONITORING_ID bigint;
declare variable V$BLOB_ID bigint;
declare variable V$VAL bigint;
declare variable V$PROFILE_SUBJECTS varchar(1000);
declare variable V$CAPTION varchar(1000);
declare variable V$HOURS_FED double precision;
declare variable V$HOURS_REG double precision;
BEGIN
    SELECT FIRST 1 L162.OBJ_ID
    FROM LINKS L162
    WHERE L162.PARENT_ID = :I$SCHOOL_ID AND L162.OBJ_TYPE_ID = 162 AND L162.DATE_DEL IS NULL
    INTO :V$MONITORING_ID;

    OBJ_ID = NULL;
    SELECT FIRST 1 L357.OBJ_ID
    FROM LINKS L357
    JOIN VALR V2745 ON V2745.OBJ_ID = L357.OBJ_ID AND V2745.PARAM_ID = 2745 AND V2745.IS_DEL = 0 AND V2745.VAL = :I$CURRICULUM_ID
    WHERE L357.PARENT_ID = :V$MONITORING_ID AND L357.OBJ_TYPE_ID = 357
    INTO :OBJ_ID;

    IF (OBJ_ID IS NULL) THEN
    BEGIN
      SELECT OBJ_ID FROM OBJECT_ADD(:V$MONITORING_ID, 357) INTO :OBJ_ID;
    END
    ELSE
    BEGIN
      UPDATE LINKS
      SET DATE_DEL = NULL
      WHERE PARENT_ID = :V$MONITORING_ID AND OBJ_ID = :OBJ_ID AND DATE_DEL IS NOT NULL;
    END

    IF (OBJ_ID IS NOT NULL) THEN
    BEGIN
      -- Ссылка на проверяемый УП
      SELECT BLOB_ID FROM VAL_ADD(2745, :OBJ_ID, :I$CURRICULUM_ID) INTO :V$BLOB_ID;
      -- Номер образовательного стандарта
      SELECT BLOB_ID FROM VAL_ADD(2924, :OBJ_ID, :I$STANDARD) INTO :V$BLOB_ID;

      -- Записываем длительность учебной недели (она должна быть одинаковой для всех параллелей среднего образования)
      FOR
        SELECT FIRST 1 V2837.LISTVAL_ID
        FROM LINKS L54
        JOIN VALL V2837 ON V2837.OBJ_ID = L54.OBJ_ID AND V2837.PARAM_ID = 2837 AND V2837.IS_DEL = 0
        WHERE L54.OBJ_TYPE_ID = 54 AND L54.PARENT_ID = :I$CURRICULUM_ID AND L54.DATE_DEL IS NULL
        INTO :V$VAL
      DO
      BEGIN
        SELECT BLOB_ID FROM VAL_ADD(2746, :OBJ_ID, :V$VAL) INTO :V$BLOB_ID;
      END

      FOR
        SELECT V3112.LISTVAL_ID
        FROM VALL V3112
        WHERE V3112.OBJ_ID = :I$CURRICULUM_ID AND V3112.PARAM_ID = 3112 AND V3112.IS_DEL = 0
        INTO :V$VAL
      DO
      BEGIN
        SELECT BLOB_ID FROM VAL_ADD(2747, :OBJ_ID, :V$VAL) INTO :V$BLOB_ID;
      END

      -- Подсчет часов по компонентам
      /*V$HOURS_FED = (SELECT HOURS FROM CURRICULUM_HOURS_GET(:I$CURRICULUM_ID, 780));
      V$HOURS_REG = (SELECT HOURS FROM CURRICULUM_HOURS_GET(:I$CURRICULUM_ID, 782, null, null, 0)) +
        (SELECT HOURS FROM CURRICULUM_HOURS_GET(:I$CURRICULUM_ID, 782, 34607, null, 1));
        :V$HOURS_FED + :V$HOURS_REG */

      -- Всего часов в УП
      SELECT BLOB_ID FROM VAL_ADD(2748, :OBJ_ID, :I$HOURS_ALL) INTO :V$BLOB_ID;

      -- Если стандарт = ФГОС, часы по компонентам не показываем. Для ФБУП
      IF(I$STANDARD >= 11721) THEN
      BEGIN
        I$VAL2 = NULL;
        I$HOURS_INVAR = NULL;
        I$HOURS_VAR = NULL;
        V$HOURS_FED = NULL;
        V$HOURS_REG = NULL;
      END
      ELSE
      BEGIN
        -- 11720
        I$SUBJECTS = NULL;
        I$VAL10 = NULL;
      END

      --SELECT BLOB_ID FROM VAL_ADD(2749, :OBJ_ID, :V$HOURS_FED) INTO :V$BLOB_ID;
      --SELECT BLOB_ID FROM VAL_ADD(2750, :OBJ_ID, :V$HOURS_REG) INTO :V$BLOB_ID;

      V$PROFILE_SUBJECTS = '';
      FOR
        SELECT DISTINCT C.CAPTION
        FROM PLAN_SUBJECTS S
        JOIN PLAN_SUBJECTS S2 ON S2.OBJ_ID = S.PARENT_ID AND S2.FIELD_ID = 13303 -- только из базовой части
        LEFT JOIN OBJECT_CAPTION_GET(S.SUBJECT_ID) C ON 1=1
        WHERE S.DATE_DEL IS NULL AND S.PLAN_ID = :I$CURRICULUM_ID AND S.ROW_TYPE = 10 AND S.IS_ADV = 1
        INTO :V$CAPTION
      DO
      BEGIN
        IF (V$PROFILE_SUBJECTS <> '') THEN
        BEGIN
          V$PROFILE_SUBJECTS = V$PROFILE_SUBJECTS || '; ';
        END
        V$PROFILE_SUBJECTS = V$PROFILE_SUBJECTS || V$CAPTION;
      END

      SELECT BLOB_ID FROM VAL_ADD(2751, :OBJ_ID, :V$PROFILE_SUBJECTS) INTO :V$BLOB_ID; -- Список профильных предметов
      SELECT BLOB_ID FROM VAL_ADD(2752, :OBJ_ID, :I$VAL1) INTO :V$BLOB_ID;  -- 9  Предметы invar
      SELECT BLOB_ID FROM VAL_ADD(2753, :OBJ_ID, :I$VAL2) INTO :V$BLOB_ID;  -- 10 Предметы var
      SELECT BLOB_ID FROM VAL_ADD(2925, :OBJ_ID, :I$SUBJECTS) INTO :V$BLOB_ID;  -- 11 Контроль количества предметов
      SELECT BLOB_ID FROM VAL_ADD(2754, :OBJ_ID, :I$PROFILED_CNT) INTO :V$BLOB_ID;  -- 12 Наличие/отсутствие профильных
      SELECT BLOB_ID FROM VAL_ADD(2755, :OBJ_ID, :I$VAL4) INTO :V$BLOB_ID;  -- 13 Часы на базовые и профильные
      --SELECT BLOB_ID FROM VAL_ADD(2756, :OBJ_ID, :I$HOURS_INVAR) INTO :V$BLOB_ID;  -- 14 Общие часы invar
      --SELECT BLOB_ID FROM VAL_ADD(2757, :OBJ_ID, :I$HOURS_VAR) INTO :V$BLOB_ID;  -- 15 Общие часы var
      SELECT BLOB_ID FROM VAL_ADD(2926, :OBJ_ID, :I$VAL10) INTO :V$BLOB_ID; -- 16 Общее кол-во часов
      SELECT BLOB_ID FROM VAL_ADD(2758, :OBJ_ID, :I$VAL7) INTO :V$BLOB_ID;  -- 17 Предельная наполняемость УП по неделе

      SELECT BLOB_ID FROM VAL_ADD(2771, :OBJ_ID, :I$VAL8) INTO :V$BLOB_ID;  -- Контроль УП универсального профиля, утрачен

    END

    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE MONITORING_CURRICULUMTABL12_SET (
    I$SCHOOL_ID BIGINT,
    I$CURRICULUM_ID BIGINT,
    I$SUBJECTS_MISS VARCHAR(5000))
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$MONITORING_ID bigint;
declare variable V$BLOB_ID bigint;
BEGIN

    SELECT FIRST 1 L162.OBJ_ID
    FROM LINKS L162
    WHERE L162.PARENT_ID = :I$SCHOOL_ID AND L162.OBJ_TYPE_ID = 162 AND L162.DATE_DEL IS NULL
    INTO :V$MONITORING_ID;


    OBJ_ID = NULL;
    SELECT FIRST 1 L361.OBJ_ID
    FROM LINKS L361
    JOIN VALR V2769 ON V2769.OBJ_ID = L361.OBJ_ID AND V2769.PARAM_ID = 2769 AND V2769.IS_DEL = 0 AND V2769.VAL = :I$CURRICULUM_ID
    WHERE L361.PARENT_ID = :V$MONITORING_ID AND L361.OBJ_TYPE_ID = 361
    INTO :OBJ_ID;

    IF (OBJ_ID IS NULL) THEN
    BEGIN
      SELECT OBJ_ID FROM OBJECT_ADD(:V$MONITORING_ID, 361) INTO :OBJ_ID;
    END
    ELSE
    BEGIN
      UPDATE LINKS
      SET DATE_DEL = NULL
      WHERE PARENT_ID = :V$MONITORING_ID AND OBJ_ID = :OBJ_ID AND DATE_DEL IS NOT NULL;
    END

    IF (OBJ_ID IS NOT NULL) THEN
    BEGIN
      SELECT BLOB_ID FROM VAL_ADD(2769, :OBJ_ID, :I$CURRICULUM_ID) INTO :V$BLOB_ID;
      SELECT BLOB_ID FROM VAL_ADD(2770, :OBJ_ID, :I$SUBJECTS_MISS) INTO :V$BLOB_ID;
    END

    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE MONITORING_CURRICULUMTABL13_SET (
    I$SCHOOL_ID BIGINT,
    I$CURRICULUM_ID BIGINT,
    I$SUBJECTS_MISS VARCHAR(5000))
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$MONITORING_ID bigint;
declare variable V$BLOB_ID bigint;
BEGIN
  SELECT FIRST 1 L162.OBJ_ID
  FROM LINKS L162
  WHERE L162.PARENT_ID = :I$SCHOOL_ID AND L162.OBJ_TYPE_ID = 162 AND L162.DATE_DEL IS NULL
  INTO :V$MONITORING_ID;

  OBJ_ID = NULL;
  SELECT FIRST 1 L358.OBJ_ID
  FROM LINKS L358
  JOIN VALR V2759 ON V2759.OBJ_ID = L358.OBJ_ID AND V2759.PARAM_ID = 2759 AND V2759.IS_DEL = 0 AND V2759.VAL = :I$CURRICULUM_ID
  WHERE L358.PARENT_ID = :V$MONITORING_ID AND L358.OBJ_TYPE_ID = 358
  INTO :OBJ_ID;

  IF (OBJ_ID IS NULL) THEN
  BEGIN
    SELECT OBJ_ID FROM OBJECT_ADD(:V$MONITORING_ID, 358) INTO :OBJ_ID;
  END
  ELSE
  BEGIN
    UPDATE LINKS SET DATE_DEL = NULL WHERE PARENT_ID = :V$MONITORING_ID AND OBJ_ID = :OBJ_ID AND DATE_DEL IS NOT NULL;
  END

  IF (OBJ_ID IS NOT NULL) THEN
  BEGIN
    SELECT BLOB_ID FROM VAL_ADD(2759, :OBJ_ID, :I$CURRICULUM_ID) INTO :V$BLOB_ID;
    SELECT BLOB_ID FROM VAL_ADD(2760, :OBJ_ID, :I$SUBJECTS_MISS) INTO :V$BLOB_ID;
  END

  SUSPEND;

END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE MONITORING_CURRICULUMTABL14_SET (
    I$SCHOOL_ID BIGINT,
    I$CURRICULUM_ID BIGINT,
    I$SUBJECTS_MISS VARCHAR(5000))
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$MONITORING_ID bigint;
declare variable V$BLOB_ID bigint;
BEGIN

  SELECT FIRST 1 L162.OBJ_ID
  FROM LINKS L162
  WHERE L162.PARENT_ID = :I$SCHOOL_ID AND L162.OBJ_TYPE_ID = 162 AND L162.DATE_DEL IS NULL
  INTO :V$MONITORING_ID;

  OBJ_ID = NULL;
  SELECT FIRST 1 L359.OBJ_ID
  FROM LINKS L359
  JOIN VALR V2761 ON V2761.OBJ_ID = L359.OBJ_ID AND V2761.PARAM_ID = 2761 AND V2761.IS_DEL = 0 AND V2761.VAL = :I$CURRICULUM_ID
  WHERE L359.PARENT_ID = :V$MONITORING_ID AND L359.OBJ_TYPE_ID = 359
  INTO :OBJ_ID;

  IF (OBJ_ID IS NULL) THEN
  BEGIN
    SELECT OBJ_ID FROM OBJECT_ADD(:V$MONITORING_ID, 359) INTO :OBJ_ID;
  END
  ELSE
  BEGIN
    UPDATE LINKS
    SET DATE_DEL = NULL
    WHERE PARENT_ID = :V$MONITORING_ID AND OBJ_ID = :OBJ_ID AND DATE_DEL IS NOT NULL;
  END

  IF (OBJ_ID IS NOT NULL) THEN
  BEGIN
    SELECT BLOB_ID FROM VAL_ADD(2761, :OBJ_ID, :I$CURRICULUM_ID) INTO :V$BLOB_ID;
    SELECT BLOB_ID FROM VAL_ADD(2762, :OBJ_ID, :I$SUBJECTS_MISS) INTO :V$BLOB_ID;
  END

  SUSPEND;

END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE MONITORING_CURRICULUMTABL15_SET (
    I$SCHOOL_ID BIGINT,
    I$CURRICULUM_ID BIGINT,
    I$SUBJECT_ID BIGINT,
    I$STAGE_ID BIGINT,
    I$SUBJECT_LEARN_LEVEL_ID BIGINT,
    I$CURRICULUM_HOURS FLOAT,
    I$CHECK_CURRICULUM_HOURS FLOAT)
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$MONITORING_ID bigint;
declare variable V$BLOB_ID bigint;
BEGIN
    SELECT FIRST 1 L162.OBJ_ID
    FROM LINKS L162
    WHERE L162.PARENT_ID = :I$SCHOOL_ID AND L162.OBJ_TYPE_ID = 162 AND L162.DATE_DEL IS NULL
    INTO :V$MONITORING_ID;

    OBJ_ID = NULL;
    SELECT FIRST 1 L360.OBJ_ID
    FROM LINKS L360
    JOIN VALR V2763 ON V2763.OBJ_ID = L360.OBJ_ID AND V2763.PARAM_ID = 2763 AND V2763.IS_DEL = 0 AND V2763.VAL = :I$CURRICULUM_ID
    JOIN VALR V2764 ON V2764.OBJ_ID = L360.OBJ_ID AND V2764.PARAM_ID = 2764 AND V2764.IS_DEL = 0 AND V2764.VAL = :I$SUBJECT_ID
--    JOIN VALL V2765 ON V2765.OBJ_ID = L360.OBJ_ID AND V2765.PARAM_ID = 2765 AND V2765.IS_DEL = 0 AND V2765.LISTVAL_ID = :I$STAGE_ID
    WHERE L360.PARENT_ID = :V$MONITORING_ID AND L360.OBJ_TYPE_ID = 360
    INTO :OBJ_ID;

    IF (OBJ_ID IS NULL) THEN
    BEGIN
      SELECT OBJ_ID FROM OBJECT_ADD(:V$MONITORING_ID, 360) INTO :OBJ_ID;
    END
    ELSE
    BEGIN
      UPDATE LINKS
      SET DATE_DEL = NULL
      WHERE PARENT_ID = :V$MONITORING_ID AND OBJ_ID = :OBJ_ID AND DATE_DEL IS NOT NULL;
    END

    IF (OBJ_ID IS NOT NULL) THEN
    BEGIN

      SELECT BLOB_ID FROM VAL_ADD(2763, :OBJ_ID, :I$CURRICULUM_ID) INTO :V$BLOB_ID;
      SELECT BLOB_ID FROM VAL_ADD(2764, :OBJ_ID, :I$SUBJECT_ID) INTO :V$BLOB_ID;
--      SELECT BLOB_ID FROM VAL_ADD(2765, :OBJ_ID, :I$STAGE_ID) INTO :V$BLOB_ID;
      SELECT BLOB_ID FROM VAL_ADD(2766, :OBJ_ID, :I$SUBJECT_LEARN_LEVEL_ID) INTO :V$BLOB_ID;
      SELECT BLOB_ID FROM VAL_ADD(2767, :OBJ_ID, :I$CHECK_CURRICULUM_HOURS) INTO :V$BLOB_ID;
      SELECT BLOB_ID FROM VAL_ADD(2768, :OBJ_ID, :I$CURRICULUM_HOURS) INTO :V$BLOB_ID;

    END

    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE MONITORING_CURRICULUMTABLE1_SET (
    I$SCHOOL_ID BIGINT,
    I$CURRICULUM_ID BIGINT,
    I$STD_ID BIGINT,
    VAL1 BIGINT,
    VAL2 BIGINT,
    VAL3 INTEGER,
    VAL4 INTEGER,
    VAL5 INTEGER,
    VAL6 INTEGER,
    VAL7 INTEGER,
    VAL8 INTEGER)
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$MONITORING_ID bigint;
declare variable V$BLOB_ID bigint;
declare variable V$CAPTION varchar(1000);
declare variable V$PROFILE_SUBJECTS varchar(5000);
BEGIN
    SELECT FIRST 1 L162.OBJ_ID
    FROM LINKS L162
    WHERE L162.PARENT_ID = :I$SCHOOL_ID AND L162.OBJ_TYPE_ID = 162 AND L162.DATE_DEL IS NULL
    INTO :V$MONITORING_ID;

    OBJ_ID = NULL;
    SELECT FIRST 1 L305.OBJ_ID
    FROM LINKS L305
    JOIN VALR V2482 ON V2482.OBJ_ID = L305.OBJ_ID AND V2482.PARAM_ID = 2482 AND V2482.IS_DEL = 0 AND V2482.VAL = :I$CURRICULUM_ID
    WHERE L305.PARENT_ID = :V$MONITORING_ID AND L305.OBJ_TYPE_ID = 305
    INTO :OBJ_ID;

    V$PROFILE_SUBJECTS = '';
    FOR
      SELECT DISTINCT C.CAPTION
      FROM PLAN_SUBJECTS S
      LEFT JOIN OBJECT_CAPTION_GET(S.SUBJECT_ID) C ON 1=1
      WHERE S.DATE_DEL IS NULL AND S.PLAN_ID = :I$CURRICULUM_ID AND S.ROW_TYPE = 10 AND S.IS_ADV = 1
      INTO :V$CAPTION
    DO
    BEGIN
      IF (V$PROFILE_SUBJECTS <> '') THEN
      BEGIN
        V$PROFILE_SUBJECTS = V$PROFILE_SUBJECTS || '; ';
      END
      V$PROFILE_SUBJECTS = V$PROFILE_SUBJECTS || V$CAPTION;
    END

    IF (OBJ_ID IS NULL) THEN
    BEGIN
      SELECT OBJ_ID FROM OBJECT_ADD(:V$MONITORING_ID, 305) INTO :OBJ_ID;
    END
    ELSE
    BEGIN
      UPDATE LINKS
      SET DATE_DEL = NULL
      WHERE PARENT_ID = :V$MONITORING_ID AND OBJ_ID = :OBJ_ID AND DATE_DEL IS NOT NULL;
    END

    IF (OBJ_ID IS NOT NULL) THEN
    BEGIN
      SELECT BLOB_ID FROM VAL_ADD(2482, :OBJ_ID, :I$CURRICULUM_ID) INTO :V$BLOB_ID;
      SELECT BLOB_ID FROM VAL_ADD(3161, :OBJ_ID, :I$STD_ID) INTO :V$BLOB_ID;
      SELECT BLOB_ID FROM VAL_ADD(2483, :OBJ_ID, :VAL1) INTO :V$BLOB_ID;
      SELECT BLOB_ID FROM VAL_ADD(2484, :OBJ_ID, :VAL2) INTO :V$BLOB_ID;
      SELECT BLOB_ID FROM VAL_ADD(2485, :OBJ_ID, :VAL3) INTO :V$BLOB_ID;
      SELECT BLOB_ID FROM VAL_ADD(2486, :OBJ_ID, :VAL4) INTO :V$BLOB_ID;
      SELECT BLOB_ID FROM VAL_ADD(2487, :OBJ_ID, :VAL5) INTO :V$BLOB_ID;
      SELECT BLOB_ID FROM VAL_ADD(2488, :OBJ_ID, :VAL6) INTO :V$BLOB_ID;
      -- SELECT BLOB_ID FROM VAL_ADD(2489, :OBJ_ID, :VAL7) INTO :V$BLOB_ID;
      SELECT BLOB_ID FROM VAL_ADD(3157, :OBJ_ID, :VAL8) INTO :V$BLOB_ID;
      SELECT BLOB_ID FROM VAL_ADD(3160, :OBJ_ID, :V$PROFILE_SUBJECTS) INTO :V$BLOB_ID;
    END

    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE MONITORING_CURRICULUMTABLE2_SET (
    I$SCHOOL_ID BIGINT,
    I$CURRICULUM_ID BIGINT,
    I$SUBJECTS_MISS VARCHAR(5000),
    I$SUBJECTS_MORE VARCHAR(5000),
    I$SUBJECTS_REPLACEMENT VARCHAR(5000))
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$MONITORING_ID bigint;
declare variable V$BLOB_ID bigint;
BEGIN

    SELECT FIRST 1 L162.OBJ_ID
    FROM LINKS L162
    WHERE L162.PARENT_ID = :I$SCHOOL_ID AND L162.OBJ_TYPE_ID = 162 AND L162.DATE_DEL IS NULL
    INTO :V$MONITORING_ID;

    OBJ_ID = NULL;
    SELECT FIRST 1 L306.OBJ_ID
    FROM LINKS L306
    JOIN VALR V2490 ON V2490.OBJ_ID = L306.OBJ_ID AND V2490.PARAM_ID = 2490 AND V2490.IS_DEL = 0 AND V2490.VAL = :I$CURRICULUM_ID
    WHERE L306.PARENT_ID = :V$MONITORING_ID AND L306.OBJ_TYPE_ID = 306
    INTO :OBJ_ID;

    IF (OBJ_ID IS NULL) THEN
    BEGIN
      SELECT OBJ_ID FROM OBJECT_ADD(:V$MONITORING_ID, 306) INTO :OBJ_ID;
    END
    ELSE
    BEGIN
      UPDATE LINKS
      SET DATE_DEL = NULL
      WHERE PARENT_ID = :V$MONITORING_ID AND OBJ_ID = :OBJ_ID AND DATE_DEL IS NOT NULL;
    END

    IF (OBJ_ID IS NOT NULL) THEN
    BEGIN
      SELECT BLOB_ID FROM VAL_ADD(2490, :OBJ_ID, :I$CURRICULUM_ID) INTO :V$BLOB_ID;
      SELECT BLOB_ID FROM VAL_ADD(2491, :OBJ_ID, :I$SUBJECTS_MISS) INTO :V$BLOB_ID;
      SELECT BLOB_ID FROM VAL_ADD(2492, :OBJ_ID, :I$SUBJECTS_MORE) INTO :V$BLOB_ID;
      SELECT BLOB_ID FROM VAL_ADD(2721, :OBJ_ID, :I$SUBJECTS_REPLACEMENT) INTO :V$BLOB_ID;
    END

    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE MONITORING_CURRICULUMTABLE3_SET (
    I$SCHOOL_ID BIGINT,
    I$CURRICULUM_ID BIGINT,
    I$SUBJECT_ID BIGINT,
    I$STAGE_ID BIGINT,
    VAL1 INTEGER,
    VAL2 INTEGER)
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$MONITORING_ID bigint;
declare variable V$BLOB_ID bigint;
BEGIN

    SELECT FIRST 1 L162.OBJ_ID
    FROM LINKS L162
    WHERE L162.PARENT_ID = :I$SCHOOL_ID AND L162.OBJ_TYPE_ID = 162 AND L162.DATE_DEL IS NULL
    INTO :V$MONITORING_ID;

    OBJ_ID = NULL;
    SELECT FIRST 1 L307.OBJ_ID
    FROM LINKS L307
    JOIN VALR V2493 ON V2493.OBJ_ID = L307.OBJ_ID AND V2493.PARAM_ID = 2493 AND V2493.IS_DEL = 0 AND V2493.VAL = :I$CURRICULUM_ID
    JOIN VALR V2494 ON V2494.OBJ_ID = L307.OBJ_ID AND V2494.PARAM_ID = 2494 AND V2494.IS_DEL = 0 AND V2494.VAL = :I$SUBJECT_ID
    JOIN VALL V2495 ON V2495.OBJ_ID = L307.OBJ_ID AND V2495.PARAM_ID = 2495 AND V2495.IS_DEL = 0 AND V2495.LISTVAL_ID = :I$STAGE_ID
    WHERE L307.PARENT_ID = :V$MONITORING_ID AND L307.OBJ_TYPE_ID = 307
    INTO :OBJ_ID;

    IF (OBJ_ID IS NULL) THEN
    BEGIN
      SELECT OBJ_ID FROM OBJECT_ADD(:V$MONITORING_ID, 307) INTO :OBJ_ID;
    END
    ELSE
    BEGIN
      UPDATE LINKS
      SET DATE_DEL = NULL
      WHERE PARENT_ID = :V$MONITORING_ID AND OBJ_ID = :OBJ_ID AND DATE_DEL IS NOT NULL;
    END

    IF (OBJ_ID IS NOT NULL) THEN
    BEGIN
      SELECT BLOB_ID FROM VAL_ADD(2493, :OBJ_ID, :I$CURRICULUM_ID) INTO :V$BLOB_ID;
      SELECT BLOB_ID FROM VAL_ADD(2494, :OBJ_ID, :I$SUBJECT_ID) INTO :V$BLOB_ID;
      SELECT BLOB_ID FROM VAL_ADD(2495, :OBJ_ID, :I$STAGE_ID) INTO :V$BLOB_ID;
      SELECT BLOB_ID FROM VAL_ADD(2496, :OBJ_ID, :VAL1) INTO :V$BLOB_ID;
      SELECT BLOB_ID FROM VAL_ADD(2497, :OBJ_ID, :VAL2) INTO :V$BLOB_ID;
    END

    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE MONITORING_CURRICULUMTABLE4_SET (
    I$SCHOOL_ID BIGINT,
    I$CURRICULUM_ID BIGINT,
    I$STAGE_ID BIGINT,
    VAL1 BIGINT,
    VAL2 INTEGER)
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$MONITORING_ID bigint;
declare variable V$BLOB_ID bigint;
BEGIN
    SELECT FIRST 1 L162.OBJ_ID
    FROM LINKS L162
    WHERE L162.PARENT_ID = :I$SCHOOL_ID AND L162.OBJ_TYPE_ID = 162 AND L162.DATE_DEL IS NULL
    INTO :V$MONITORING_ID;

    OBJ_ID = NULL;
    SELECT FIRST 1 L309.OBJ_ID
    FROM LINKS L309
    JOIN VALR V2498 ON V2498.OBJ_ID = L309.OBJ_ID AND V2498.PARAM_ID = 2498 AND V2498.IS_DEL = 0 AND V2498.VAL = :I$CURRICULUM_ID
    JOIN VALL V2499 ON V2499.OBJ_ID = L309.OBJ_ID AND V2499.PARAM_ID = 2499 AND V2499.IS_DEL = 0 AND V2499.LISTVAL_ID = :I$STAGE_ID
    WHERE L309.PARENT_ID = :V$MONITORING_ID AND L309.OBJ_TYPE_ID = 309
    INTO :OBJ_ID;

    IF (OBJ_ID IS NULL) THEN
    BEGIN
      SELECT OBJ_ID FROM OBJECT_ADD(:V$MONITORING_ID, 309) INTO :OBJ_ID;
    END
    ELSE
    BEGIN
      UPDATE LINKS
      SET DATE_DEL = NULL
      WHERE PARENT_ID = :V$MONITORING_ID AND OBJ_ID = :OBJ_ID AND DATE_DEL IS NOT NULL;
    END

    IF (OBJ_ID IS NOT NULL) THEN
    BEGIN
      SELECT BLOB_ID FROM VAL_ADD(2498, :OBJ_ID, :I$CURRICULUM_ID) INTO :V$BLOB_ID;
      SELECT BLOB_ID FROM VAL_ADD(2499, :OBJ_ID, :I$STAGE_ID) INTO :V$BLOB_ID;
      SELECT BLOB_ID FROM VAL_ADD(2500, :OBJ_ID, :VAL1) INTO :V$BLOB_ID;
      SELECT BLOB_ID FROM VAL_ADD(2501, :OBJ_ID, :VAL2) INTO :V$BLOB_ID;
    END

    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE MONITORING_CURRICULUMTABLE5_SET (
    I$SCHOOL_ID BIGINT,
    I$CURRICULUM_ID BIGINT,
    I$VELEL_ID BIGINT,
    I$CHECK_CURRICULUM_ID BIGINT,
    I$VAL1 BIGINT,
    I$VAL2 BIGINT)
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$MONITORING_ID bigint;
declare variable V$BLOB_ID bigint;
BEGIN
    SELECT FIRST 1 L162.OBJ_ID
    FROM LINKS L162
    WHERE L162.PARENT_ID = :I$SCHOOL_ID AND L162.OBJ_TYPE_ID = 162 AND L162.DATE_DEL IS NULL
    INTO :V$MONITORING_ID;

    OBJ_ID = NULL;
    SELECT FIRST 1 L311.OBJ_ID
    FROM LINKS L311
    JOIN VALR V2506 ON V2506.OBJ_ID = L311.OBJ_ID AND V2506.PARAM_ID = 2506 AND V2506.IS_DEL = 0 AND V2506.VAL = :I$CURRICULUM_ID
    JOIN VALL V2507 ON V2507.OBJ_ID = L311.OBJ_ID AND V2507.PARAM_ID = 2507 AND V2507.IS_DEL = 0 AND V2507.LISTVAL_ID = :I$VELEL_ID
    JOIN VALR V2508 ON V2508.OBJ_ID = L311.OBJ_ID AND V2508.PARAM_ID = 2508 AND V2508.IS_DEL = 0 AND V2508.VAL = :I$CHECK_CURRICULUM_ID
    WHERE L311.PARENT_ID = :V$MONITORING_ID AND L311.OBJ_TYPE_ID = 311
    INTO :OBJ_ID;

    IF (OBJ_ID IS NULL) THEN
    BEGIN
      SELECT OBJ_ID FROM OBJECT_ADD(:V$MONITORING_ID, 311) INTO :OBJ_ID;
    END
    ELSE
    BEGIN
      UPDATE LINKS
      SET DATE_DEL = NULL
      WHERE PARENT_ID = :V$MONITORING_ID AND OBJ_ID = :OBJ_ID AND DATE_DEL IS NOT NULL;
    END

    IF (OBJ_ID IS NOT NULL) THEN
    BEGIN
      SELECT BLOB_ID FROM VAL_ADD(2506, :OBJ_ID, :I$CURRICULUM_ID) INTO :V$BLOB_ID;
      SELECT BLOB_ID FROM VAL_ADD(2507, :OBJ_ID, :I$VELEL_ID) INTO :V$BLOB_ID;
      SELECT BLOB_ID FROM VAL_ADD(2508, :OBJ_ID, :I$CHECK_CURRICULUM_ID) INTO :V$BLOB_ID;
      SELECT BLOB_ID FROM VAL_ADD(2509, :OBJ_ID, :I$VAL1) INTO :V$BLOB_ID;
      SELECT BLOB_ID FROM VAL_ADD(2510, :OBJ_ID, :I$VAL2) INTO :V$BLOB_ID;
    END

    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE MONITORING_CURRICULUMTABLE6_SET (
    I$SCHOOL_ID BIGINT,
    I$CURRICULUM_ID BIGINT,
    I$SUBJECT_ID BIGINT,
    I$STAGE_ID BIGINT,
    I$JOURNAL_NAME VARCHAR(1000))
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$MONITORING_ID bigint;
declare variable V$BLOB_ID bigint;
BEGIN
    SELECT FIRST 1 L162.OBJ_ID
    FROM LINKS L162
    WHERE L162.PARENT_ID = :I$SCHOOL_ID AND L162.OBJ_TYPE_ID = 162 AND L162.DATE_DEL IS NULL
    INTO :V$MONITORING_ID;

    OBJ_ID = NULL;
    SELECT FIRST 1 L313.OBJ_ID
    FROM LINKS L313
    JOIN VALR V2511 ON V2511.OBJ_ID = L313.OBJ_ID AND V2511.PARAM_ID = 2511 AND V2511.IS_DEL = 0 AND V2511.VAL = :I$CURRICULUM_ID
    JOIN VALR V2512 ON V2512.OBJ_ID = L313.OBJ_ID AND V2512.PARAM_ID = 2512 AND V2512.IS_DEL = 0 AND V2512.VAL = :I$SUBJECT_ID
    JOIN VALL V2513 ON V2513.OBJ_ID = L313.OBJ_ID AND V2513.PARAM_ID = 2513 AND V2513.IS_DEL = 0 AND V2513.LISTVAL_ID = :I$STAGE_ID
    JOIN VALS V2514 ON V2514.OBJ_ID = L313.OBJ_ID AND V2514.PARAM_ID = 2514 AND V2514.IS_DEL = 0 AND V2514.VAL = :I$JOURNAL_NAME
    WHERE L313.PARENT_ID = :V$MONITORING_ID AND L313.OBJ_TYPE_ID = 313
    INTO :OBJ_ID;

    IF (OBJ_ID IS NULL) THEN
    BEGIN
      SELECT OBJ_ID FROM OBJECT_ADD(:V$MONITORING_ID, 313) INTO :OBJ_ID;
    END
    ELSE
    BEGIN
      UPDATE LINKS
      SET DATE_DEL = NULL
      WHERE PARENT_ID = :V$MONITORING_ID AND OBJ_ID = :OBJ_ID AND DATE_DEL IS NOT NULL;
    END

    IF (OBJ_ID IS NOT NULL) THEN
    BEGIN
      SELECT BLOB_ID FROM VAL_ADD(2511, :OBJ_ID, :I$CURRICULUM_ID) INTO :V$BLOB_ID;
      SELECT BLOB_ID FROM VAL_ADD(2512, :OBJ_ID, :I$SUBJECT_ID) INTO :V$BLOB_ID;
      SELECT BLOB_ID FROM VAL_ADD(2513, :OBJ_ID, :I$STAGE_ID) INTO :V$BLOB_ID;
      SELECT BLOB_ID FROM VAL_ADD(2514, :OBJ_ID, :I$JOURNAL_NAME) INTO :V$BLOB_ID;
    END

    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE MONITORING_CURRICULUMTABLE7_SET (
    I$SCHOOL_ID BIGINT,
    I$CURRICULUM_ID BIGINT,
    I$SUBJECT_ID BIGINT,
    I$STAGE_ID BIGINT,
    I$JOURNAL_NAME VARCHAR(1000),
    I$VAL1 INTEGER,
    I$VAL2 INTEGER)
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$MONITORING_ID bigint;
declare variable V$BLOB_ID bigint;
BEGIN

    SELECT FIRST 1 L162.OBJ_ID
    FROM LINKS L162
    WHERE L162.PARENT_ID = :I$SCHOOL_ID AND L162.OBJ_TYPE_ID = 162 AND L162.DATE_DEL IS NULL
    INTO :V$MONITORING_ID;

    OBJ_ID = NULL;
    SELECT FIRST 1 L315.OBJ_ID
    FROM LINKS L315
    JOIN VALR V2515 ON V2515.OBJ_ID = L315.OBJ_ID AND V2515.PARAM_ID = 2515 AND V2515.IS_DEL = 0 AND V2515.VAL = :I$CURRICULUM_ID
    JOIN VALR V2516 ON V2516.OBJ_ID = L315.OBJ_ID AND V2516.PARAM_ID = 2516 AND V2516.IS_DEL = 0 AND V2516.VAL = :I$SUBJECT_ID
    JOIN VALL V2517 ON V2517.OBJ_ID = L315.OBJ_ID AND V2517.PARAM_ID = 2517 AND V2517.IS_DEL = 0 AND V2517.LISTVAL_ID = :I$STAGE_ID
    JOIN VALS V2518 ON V2518.OBJ_ID = L315.OBJ_ID AND V2518.PARAM_ID = 2518 AND V2518.IS_DEL = 0 AND V2518.VAL = :I$JOURNAL_NAME
    WHERE L315.PARENT_ID = :V$MONITORING_ID AND L315.OBJ_TYPE_ID = 315
    INTO :OBJ_ID;

    IF (OBJ_ID IS NULL) THEN
    BEGIN
      SELECT OBJ_ID FROM OBJECT_ADD(:V$MONITORING_ID, 315) INTO :OBJ_ID;
    END
    ELSE
    BEGIN
      UPDATE LINKS
      SET DATE_DEL = NULL
      WHERE PARENT_ID = :V$MONITORING_ID AND OBJ_ID = :OBJ_ID AND DATE_DEL IS NOT NULL;
    END

    IF (OBJ_ID IS NOT NULL) THEN
    BEGIN
      SELECT BLOB_ID FROM VAL_ADD(2515, :OBJ_ID, :I$CURRICULUM_ID) INTO :V$BLOB_ID;
      SELECT BLOB_ID FROM VAL_ADD(2516, :OBJ_ID, :I$SUBJECT_ID) INTO :V$BLOB_ID;
      SELECT BLOB_ID FROM VAL_ADD(2517, :OBJ_ID, :I$STAGE_ID) INTO :V$BLOB_ID;
      SELECT BLOB_ID FROM VAL_ADD(2518, :OBJ_ID, :I$JOURNAL_NAME) INTO :V$BLOB_ID;
      SELECT BLOB_ID FROM VAL_ADD(2519, :OBJ_ID, :I$VAL1) INTO :V$BLOB_ID;
      SELECT BLOB_ID FROM VAL_ADD(2520, :OBJ_ID, :I$VAL2) INTO :V$BLOB_ID;
    END

    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE MONITORING_CURRICULUMTABLE8_SET (
    I$SCHOOL_ID BIGINT,
    I$STAGE_ID BIGINT,
    I$JOURNAL_NAME VARCHAR(1000),
    I$SUBJECT_ID BIGINT,
    I$VAL1 BIGINT,
    I$VAL2 INTEGER,
    I$VAL3 INTEGER,
    I$VAL4 INTEGER,
    I$VAL5 FLOAT,
    I$VAL6 FLOAT,
    I$VAL7 BIGINT)
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$MONITORING_ID bigint;
declare variable V$BLOB_ID bigint;
BEGIN

    SELECT FIRST 1 L162.OBJ_ID
    FROM LINKS L162
    WHERE L162.PARENT_ID = :I$SCHOOL_ID AND L162.OBJ_TYPE_ID = 162 AND L162.DATE_DEL IS NULL
    INTO :V$MONITORING_ID;

    OBJ_ID = NULL;
    SELECT FIRST 1 L316.OBJ_ID
    FROM LINKS L316
    JOIN VALL V2522 ON V2522.OBJ_ID = L316.OBJ_ID AND V2522.PARAM_ID = 2522 AND V2522.IS_DEL = 0 AND V2522.LISTVAL_ID = :I$STAGE_ID
    JOIN VALS V2523 ON V2523.OBJ_ID = L316.OBJ_ID AND V2523.PARAM_ID = 2523 AND V2523.IS_DEL = 0 AND V2523.VAL = :I$JOURNAL_NAME
    JOIN VALR V2524 ON V2524.OBJ_ID = L316.OBJ_ID AND V2524.PARAM_ID = 2524 AND V2524.IS_DEL = 0 AND V2524.VAL = :I$SUBJECT_ID
    WHERE L316.PARENT_ID = :V$MONITORING_ID AND L316.OBJ_TYPE_ID = 316
    INTO :OBJ_ID;

    IF (OBJ_ID IS NULL) THEN
    BEGIN
      SELECT OBJ_ID FROM OBJECT_ADD(:V$MONITORING_ID, 316) INTO :OBJ_ID;
    END
    ELSE
    BEGIN
      UPDATE LINKS
      SET DATE_DEL = NULL
      WHERE PARENT_ID = :V$MONITORING_ID AND OBJ_ID = :OBJ_ID AND DATE_DEL IS NOT NULL;
    END

    IF (OBJ_ID IS NOT NULL) THEN
    BEGIN
      SELECT BLOB_ID FROM VAL_ADD(2522, :OBJ_ID, :I$STAGE_ID) INTO :V$BLOB_ID;
      SELECT BLOB_ID FROM VAL_ADD(2523, :OBJ_ID, :I$JOURNAL_NAME) INTO :V$BLOB_ID;
      SELECT BLOB_ID FROM VAL_ADD(2524, :OBJ_ID, :I$SUBJECT_ID) INTO :V$BLOB_ID;

      IF (I$VAL1 IS NOT NULL) THEN
      BEGIN
        SELECT BLOB_ID FROM VAL_ADD(2525, :OBJ_ID, :I$VAL1) INTO :V$BLOB_ID;
      END

      SELECT BLOB_ID FROM VAL_ADD(2526, :OBJ_ID, :I$VAL2) INTO :V$BLOB_ID;
      SELECT BLOB_ID FROM VAL_ADD(2527, :OBJ_ID, :I$VAL3) INTO :V$BLOB_ID;
      SELECT BLOB_ID FROM VAL_ADD(2528, :OBJ_ID, :I$VAL4) INTO :V$BLOB_ID;
      SELECT BLOB_ID FROM VAL_ADD(2529, :OBJ_ID, :I$VAL5) INTO :V$BLOB_ID;
      SELECT BLOB_ID FROM VAL_ADD(2530, :OBJ_ID, :I$VAL6) INTO :V$BLOB_ID;
      SELECT BLOB_ID FROM VAL_ADD(2531, :OBJ_ID, :I$VAL7) INTO :V$BLOB_ID;
    END

    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE MONITORING_CURRICULUMTABLE9_SET (
    I$SCHOOL_ID BIGINT,
    I$STAGE_ID BIGINT,
    I$JOURNAL_NAME VARCHAR(1000),
    I$SUBJECT_ID BIGINT,
    I$VAL1 INTEGER,
    I$VAL2 FLOAT)
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$MONITORING_ID bigint;
declare variable V$BLOB_ID bigint;
BEGIN

    SELECT FIRST 1 L162.OBJ_ID
    FROM LINKS L162
    WHERE L162.PARENT_ID = :I$SCHOOL_ID AND L162.OBJ_TYPE_ID = 162 AND L162.DATE_DEL IS NULL
    INTO :V$MONITORING_ID;

    OBJ_ID = NULL;
    SELECT FIRST 1 L317.OBJ_ID
    FROM LINKS L317
    JOIN VALL V2532 ON V2532.OBJ_ID = L317.OBJ_ID AND V2532.PARAM_ID = 2532 AND V2532.IS_DEL = 0 AND V2532.LISTVAL_ID = :I$STAGE_ID
    JOIN VALS V2533 ON V2533.OBJ_ID = L317.OBJ_ID AND V2533.PARAM_ID = 2533 AND V2533.IS_DEL = 0 AND V2533.VAL = :I$JOURNAL_NAME
    JOIN VALR V2534 ON V2534.OBJ_ID = L317.OBJ_ID AND V2534.PARAM_ID = 2534 AND V2534.IS_DEL = 0 AND V2534.VAL = :I$SUBJECT_ID
    WHERE L317.PARENT_ID = :V$MONITORING_ID AND L317.OBJ_TYPE_ID = 317
    INTO :OBJ_ID;

    IF (OBJ_ID IS NULL) THEN
    BEGIN
      SELECT OBJ_ID FROM OBJECT_ADD(:V$MONITORING_ID, 317) INTO :OBJ_ID;
    END
    ELSE
    BEGIN
      UPDATE LINKS
      SET DATE_DEL = NULL
      WHERE PARENT_ID = :V$MONITORING_ID AND OBJ_ID = :OBJ_ID AND DATE_DEL IS NOT NULL;
    END

    IF (OBJ_ID IS NOT NULL) THEN
    BEGIN
      SELECT BLOB_ID FROM VAL_ADD(2532, :OBJ_ID, :I$STAGE_ID) INTO :V$BLOB_ID;
      SELECT BLOB_ID FROM VAL_ADD(2533, :OBJ_ID, :I$JOURNAL_NAME) INTO :V$BLOB_ID;
      SELECT BLOB_ID FROM VAL_ADD(2534, :OBJ_ID, :I$SUBJECT_ID) INTO :V$BLOB_ID;
      SELECT BLOB_ID FROM VAL_ADD(2535, :OBJ_ID, :I$VAL1) INTO :V$BLOB_ID;
      SELECT BLOB_ID FROM VAL_ADD(2536, :OBJ_ID, :I$VAL2) INTO :V$BLOB_ID;
    END

    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE MONITORING_DATA_REPORT (
    I$OBJ_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    COL_NUM SMALLINT,
    VAL VARCHAR(4000),
    DATA VARCHAR(4000),
    ORIENTATION VARCHAR(20))
AS
declare variable V$MONITORING_ID bigint;
declare variable V$CURRENT_COL smallint;
BEGIN
    ORIENTATION = 'MIXED';
   FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1506, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 2081, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END


    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1510, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1896, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END


    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1503, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1897, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END


    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1504, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1898, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END


        FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1505, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1899, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END


        FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1507, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1900, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END


        FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        VAL = '';
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        VAL = '';
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END


        FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1418, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1902, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END


        FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1419, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1903, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END


        FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1420, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1904, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END


        FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1421, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1905, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END


        FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1422, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1906, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END


        FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1423, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1908, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END



        FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1424, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1910, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END


        FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1425, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1911, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END


        FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1426, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1912, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END


        FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1427, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1913, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END


        FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1428, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1914, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END


        FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1429, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1915, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END


        FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1430, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1916, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END


        FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1431, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1917, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END


        FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        VAL = '';
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        VAL = '';
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END


        FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1435, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1919, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END



            FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1495, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1909, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END

        FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1436, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1920, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END


        FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1437, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1921, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END

   ---------------------------------
      FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1496, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1955, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END



        FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1434, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1925, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END


        FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1477, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1926, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END


        FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1502, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1927, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END


        FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        VAL = '';
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        VAL = '';
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END
      ---------------------------------------------------
FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1439, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1929, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END


    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1440, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1930, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END


    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1447, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1931, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END


        FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1448, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1932, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END


        FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1450, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1933, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END


        FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        VAL = '';
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        VAL = '';
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END


        FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1452, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1935, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END


        FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1453, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1936, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END


        FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1455, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1941, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END


        FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1459, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1942, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END


        FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        VAL = '';
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        VAL = '';
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END

   --------------------------------
        FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1460, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1944, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END


        FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1464, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1945, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END


        FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1497, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1946, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END


        FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1468, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1947, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END


        FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1469, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1948, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END


        FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1470, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1949, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END


        FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1471, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1950, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END


        FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1472, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1951, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END


        FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1498, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1952, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END


        FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1473, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1953, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END


        FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1474, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1954, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END



        FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1499, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1922, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END


        FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1475, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1956, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END


        FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1476, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1957, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END


        FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1500, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1958, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END


        FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1501, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1959, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END


        FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1492, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1960, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END


        FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1493, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1961, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END


        FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1479, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1964, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END


    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1480, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1965, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END

        FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1482, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1966, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END


     FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1483, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1967, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END

            FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1484, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1968, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END

            FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1485, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1969, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END


END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE MONITORING_DATA_REPORT2 (
    I$OBJ_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    COL_NUM SMALLINT,
    VAL VARCHAR(4000),
    DATA VARCHAR(4000),
    ORIENTATION VARCHAR(20))
AS
declare variable V$MONITORING_ID bigint;
declare variable V$CURRENT_COL integer;
BEGIN
    ORIENTATION = 'MIXED';

            FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1486, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1970, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END

            FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1487, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1971, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END

            FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1488, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1972, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END

            FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1489, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1973, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END

            FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1490, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1974, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END

            FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1491, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1975, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END



END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE MONITORING_DO_FUNC (
    I$SCHOOL_ID BIGINT,
    I$PARAM_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    VAL VARCHAR(4000),
    SORT_ORDER DOUBLE PRECISION)
AS
declare variable V$PARAM_ID bigint;
declare variable V$LISTVAL_ID bigint;
declare variable V$Y1 smallint;
declare variable V$Y2 smallint;
declare variable V varchar(4000);
declare variable V$DT1 date;
declare variable V$DT2 date;
declare variable V$GEN bigint;
declare variable LANG_CODE varchar(2);
declare variable SCHOOL_TOTAL integer;
declare variable TOTAL integer;
declare variable GRADE_ID bigint;
declare variable STAGE_ID bigint;
declare variable CLASS_ID bigint;
declare variable DT_IN date;
declare variable DT_OUT date;
declare variable SCHOLAR_ID bigint;
declare variable DT date;
declare variable V$Y smallint;
declare variable V$DT date;
declare variable V$YEAR_VAL varchar(100);
declare variable V$YEAR_ID bigint;
declare variable N integer;
declare variable V$MONITORING_ID bigint;
declare variable F double precision;
begin
    V$Y = EXTRACT(YEAR FROM CURRENT_DATE);
    V$DT = '1.09.' || V$Y;
        
    IF (CURRENT_DATE < V$DT) THEN
    BEGIN
        V$YEAR_VAL = (V$Y - 1) || '-' || V$Y;
    END
    ELSE
    BEGIN
        V$YEAR_VAL = V$Y || '-' ||(V$Y + 1);
    END
        
    SELECT FIRST 1 LV.LISTVAL_ID
    FROM LISTVALS LV
    JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
    WHERE LV.LIST_ID = 29 AND R.VAL LIKE :V$YEAR_VAL
    INTO :V$YEAR_ID;

    SELECT LANG_CODE FROM USERS WHERE USER_ID = :I$USER_ID INTO :LANG_CODE;

    V$GEN = I$SCHOOL_ID / 1000000000;
    VAL = '';
    SORT_ORDER = 0;

    V$PARAM_ID = NULL;
    IF (I$PARAM_ID = 1418) THEN
    BEGIN
        V$PARAM_ID = 5;
    END
    ELSE IF (I$PARAM_ID = 1419) THEN
    BEGIN
        V$PARAM_ID = 2;
    END
    ELSE IF (I$PARAM_ID = 1420) THEN
    BEGIN
        V$PARAM_ID = 17;
    END
    ELSE IF (I$PARAM_ID = 1421) THEN
    BEGIN
        V$PARAM_ID = 11;
    END
    ELSE IF (I$PARAM_ID = 1422) THEN
    BEGIN
        V$PARAM_ID = 10;
    END
    ELSE IF (I$PARAM_ID = 1423) THEN
    BEGIN
        V$PARAM_ID = 8;
    END
    ELSE IF (I$PARAM_ID = 1424) THEN
    BEGIN
        V$PARAM_ID = 27;
    END
    ELSE IF (I$PARAM_ID = 1672) THEN
    BEGIN
        V$PARAM_ID = 7;
    END
    ELSE IF (I$PARAM_ID = 1425) THEN
    BEGIN
        SELECT POST
        FROM R_SPB_POST_DIRECTOR(:I$SCHOOL_ID, :I$USER_ID)
        INTO :VAL;
    END
    ELSE IF (I$PARAM_ID = 1426) THEN
    BEGIN
        SELECT F || ' ' || I || ' ' || O
        FROM R_SPB_POST_DIRECTOR(:I$SCHOOL_ID, :I$USER_ID)
        INTO :VAL;
    END
    ELSE IF (I$PARAM_ID = 1427) THEN
    BEGIN
        V$PARAM_ID = 28;
    END
    ELSE IF (I$PARAM_ID = 1428) THEN
    BEGIN
        V$PARAM_ID = 29;
    END
    ELSE IF (I$PARAM_ID = 1429) THEN
    BEGIN
        V$PARAM_ID = 30;
    END
    ELSE IF (I$PARAM_ID = 1430) THEN
    BEGIN
        V$PARAM_ID = 35;
    END
    ELSE IF (I$PARAM_ID = 1431) THEN
    BEGIN
        V$PARAM_ID = 36;
    END
    ELSE IF (I$PARAM_ID = 1432) THEN
    BEGIN
        V$PARAM_ID = 2168;
    END
    ELSE IF (I$PARAM_ID = 2193) THEN
    BEGIN
        V$PARAM_ID = 2167;
    END
    ELSE IF ((I$PARAM_ID = 2194) OR (I$PARAM_ID = 2195)) THEN
    BEGIN
        -- Наполняемость на 20 сентября / 1 января текущего уч. года
        IF (I$PARAM_ID = 2194) THEN
        BEGIN
            IF (CURRENT_DATE < '31.08.' || EXTRACT(YEAR FROM CURRENT_DATE)) THEN
            BEGIN
                DT = '20.09.' || (EXTRACT(YEAR FROM CURRENT_DATE) - 1);
            END
            ELSE
            BEGIN
                DT = '20.09.' || EXTRACT(YEAR FROM CURRENT_DATE);
            END
        END
        ELSE
        BEGIN
            IF (CURRENT_DATE < '31.08.' ||EXTRACT(YEAR FROM CURRENT_DATE)) THEN
            BEGIN
                DT =  '01.01.' || EXTRACT(YEAR FROM CURRENT_DATE);
            END
            ELSE
            BEGIN
                DT = '01.01.' || (EXTRACT(YEAR FROM CURRENT_DATE) + 1);
            END
        END

        IF (CURRENT_DATE < DT) THEN
        BEGIN
            VAL  = NULL;
        END
        ELSE
        BEGIN
            SCHOOL_TOTAL = 0;

            SELECT COUNT(DISTINCT OBJ_ID)
            FROM (
              SELECT L10.OBJ_ID
              FROM LINKS L7
              JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
              JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
              JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
              JOIN PERSON_MOVEMENTS M ON M.DATE_DEL IS NULL AND M.PERSON_ID = L10.OBJ_ID AND M.GROUP_ID = L9.OBJ_ID AND M.DATE_IN <= :DT AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :DT)
              WHERE L7.PARENT_ID = :I$SCHOOL_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
              UNION
              SELECT L10.OBJ_ID
              FROM LINKS L78
              JOIN LINKS L8X ON L8X.PARENT_ID = L78.OBJ_ID AND L8X.OBJ_TYPE_ID IN (81, 82, 83, 84) AND L8X.DATE_DEL IS NULL
              JOIN LINKS L10 ON L10.PARENT_ID = L8X.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
              JOIN PERSON_MOVEMENTS M ON M.DATE_DEL IS NULL AND M.PERSON_ID = L10.OBJ_ID AND M.DATE_IN <= :DT AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :DT)
              JOIN OBJECTS O ON O.OBJ_ID = M.GROUP_ID AND O.TYPE_ID = 9
              WHERE L78.PARENT_ID = :I$SCHOOL_ID AND L78.OBJ_TYPE_ID = 78 AND L78.DATE_DEL IS NULL
            )
            INTO :SCHOOL_TOTAL;

            VAL = SCHOOL_TOTAL;
        END
    END
    ELSE IF (I$PARAM_ID = 1433) THEN
    BEGIN
        SELECT COUNT(*)
        FROM LINKS L7

        JOIN LINKS L8
        ON L8.PARENT_ID = L7.OBJ_ID
        AND L8.DATE_DEL IS NULL
        AND L8.OBJ_TYPE_ID = 8

        JOIN LINKS L9
        ON L9.PARENT_ID = L8.OBJ_ID
        AND L9.DATE_DEL IS NULL
        AND L9.OBJ_TYPE_ID = 9

        JOIN LINKS L10
        ON L10.PARENT_ID = L9.OBJ_ID
        AND L10.DATE_DEL IS NULL
        AND L10.OBJ_TYPE_ID = 10

        WHERE L7.PARENT_ID = :I$SCHOOL_ID
        AND L7.DATE_DEL IS NULL
        AND L7.OBJ_TYPE_ID = 7
        INTO :VAL;

        SORT_ORDER = VAL;
    END
    ELSE IF (I$PARAM_ID = 1434) THEN
    BEGIN
        SELECT CAST(F AS NUMERIC(18,2)), SORT_ORDER
        FROM VAL_GET(:I$SCHOOL_ID, 14, 0, :I$USER_ID)
        INTO :VAL, :SORT_ORDER;
    END
    ELSE IF (I$PARAM_ID = 1435) THEN
    BEGIN
        SELECT COUNT(*)
        FROM LINKS L73
        JOIN LINKS L16 ON L16.PARENT_ID = L73.OBJ_ID AND L16.DATE_DEL IS NULL AND L16.OBJ_TYPE_ID = 16
        WHERE L73.PARENT_ID = :I$SCHOOL_ID AND L73.DATE_DEL IS NULL AND L73.OBJ_TYPE_ID = 73
        INTO :VAL;

        SORT_ORDER = VAL;
    END
    ELSE IF (I$PARAM_ID = 1436) THEN
    BEGIN
        SELECT CAST(COALESCE(SUM(VI.VAL),0) AS NUMERIC(18,2))
        FROM LINKS L73
        JOIN LINKS L16 ON L16.PARENT_ID = L73.OBJ_ID AND L16.DATE_DEL IS NULL AND L16.OBJ_TYPE_ID = 16
        JOIN VALF VI ON VI.OBJ_ID = L16.OBJ_ID AND VI.IS_DEL = 0 AND VI.PARAM_ID = 496
        WHERE L73.PARENT_ID = :I$SCHOOL_ID AND L73.DATE_DEL IS NULL AND L73.OBJ_TYPE_ID = 73
        INTO :VAL;

        SORT_ORDER = VAL;
    END
    ELSE IF (I$PARAM_ID = 1437) THEN
    BEGIN
        SELECT CAST(COALESCE(SUM(VI.VAL),0) AS NUMERIC(18,2))
        FROM LINKS L73
        JOIN LINKS L16 ON L16.PARENT_ID = L73.OBJ_ID AND L16.DATE_DEL IS NULL AND L16.OBJ_TYPE_ID = 16
        JOIN VALF VI ON VI.OBJ_ID = L16.OBJ_ID AND VI.IS_DEL = 0 AND VI.PARAM_ID = 499
        WHERE L73.PARENT_ID = :I$SCHOOL_ID AND L73.DATE_DEL IS NULL AND L73.OBJ_TYPE_ID = 73
        INTO :VAL;

        SORT_ORDER = VAL;
    END
    ELSE IF (I$PARAM_ID = 1452) THEN
    BEGIN
        SELECT COUNT(*)
        FROM LINKS L23

        JOIN LINKS L128
        ON L128.PARENT_ID = L23.OBJ_ID
        AND L128.DATE_DEL IS NULL
        AND L128.OBJ_TYPE_ID = 128

        JOIN VALL VL
        ON VL.OBJ_ID = L128.OBJ_ID
        AND VL.IS_DEL = 0
        AND VL.PARAM_ID = 876
        AND VL.LISTVAL_ID IN (2067,2068)

        WHERE L23.PARENT_ID = :I$SCHOOL_ID
        AND L23.DATE_DEL IS NULL
        AND L23.OBJ_TYPE_ID = 23

        INTO :VAL;

        SORT_ORDER = VAL;
    END
    ELSE IF (I$PARAM_ID = 1453) THEN
    BEGIN
        SELECT COALESCE(SUM(VI.VAL),0)
        FROM LINKS L23

        JOIN LINKS L128
        ON L128.PARENT_ID = L23.OBJ_ID
        AND L128.DATE_DEL IS NULL
        AND L128.OBJ_TYPE_ID = 128

        JOIN VALL VL
        ON VL.OBJ_ID = L128.OBJ_ID
        AND VL.IS_DEL = 0
        AND VL.PARAM_ID = 876
        AND VL.LISTVAL_ID IN (2067,2068)

        JOIN VALI VI
        ON VI.OBJ_ID = L128.OBJ_ID
        AND VI.IS_DEL = 0
        AND VI.PARAM_ID = 888

        WHERE L23.PARENT_ID = :I$SCHOOL_ID
        AND L23.DATE_DEL IS NULL
        AND L23.OBJ_TYPE_ID = 23

        INTO :VAL;

        SORT_ORDER = VAL;
    END
    ELSE IF (I$PARAM_ID = 1455) THEN
    BEGIN
        SELECT COALESCE(SUM(VI.VAL),0)
        FROM LINKS L23

        JOIN LINKS L95
        ON L95.PARENT_ID = L23.OBJ_ID
        AND L95.DATE_DEL IS NULL
        AND L95.OBJ_TYPE_ID = 95

        JOIN VALL VL
        ON VL.OBJ_ID = L95.OBJ_ID
        AND VL.IS_DEL = 0
        AND VL.PARAM_ID = 626
        AND VL.LISTVAL_ID = 1799

        JOIN VALI VI
        ON VI.OBJ_ID = L95.OBJ_ID
        AND VI.IS_DEL = 0
        AND VI.PARAM_ID = 605

        WHERE L23.PARENT_ID = :I$SCHOOL_ID
        AND L23.DATE_DEL IS NULL
        AND L23.OBJ_TYPE_ID = 23

        INTO :VAL;

        SORT_ORDER = VAL;
    END
    ELSE IF (I$PARAM_ID = 1459) THEN
    BEGIN
        SELECT COALESCE(SUM(VI.VAL),0)
        FROM LINKS L23

        JOIN LINKS L95
        ON L95.PARENT_ID = L23.OBJ_ID
        AND L95.DATE_DEL IS NULL
        AND L95.OBJ_TYPE_ID = 95

        JOIN VALL VL
        ON VL.OBJ_ID = L95.OBJ_ID
        AND VL.IS_DEL = 0
        AND VL.PARAM_ID = 604
        AND VL.LISTVAL_ID IN (1800,1801,1802)

        JOIN VALI VI
        ON VI.OBJ_ID = L95.OBJ_ID
        AND VI.IS_DEL = 0
        AND VI.PARAM_ID = 605

        WHERE L23.PARENT_ID = :I$SCHOOL_ID
        AND L23.DATE_DEL IS NULL
        AND L23.OBJ_TYPE_ID = 23

        INTO :VAL;

        SORT_ORDER = VAL;
    END
    ELSE IF (I$PARAM_ID = 1460) THEN
    BEGIN
        SELECT COUNT(*)
        FROM LINKS L73
        JOIN LINKS L16 ON L16.PARENT_ID = L73.OBJ_ID AND L16.DATE_DEL IS NULL AND L16.OBJ_TYPE_ID = 16
        JOIN LINKS L61 ON L61.PARENT_ID = L16.OBJ_ID AND L61.DATE_DEL IS NULL AND L61.OBJ_TYPE_ID = 61
        JOIN VALL VL ON VL.OBJ_ID = L61.OBJ_ID AND VL.IS_DEL = 0 AND VL.PARAM_ID = 526 AND VL.LISTVAL_ID = 1130
        WHERE L73.PARENT_ID = :I$SCHOOL_ID AND L73.DATE_DEL IS NULL AND L73.OBJ_TYPE_ID = 73
        INTO :VAL;

        SORT_ORDER = VAL;
    END
    ELSE IF (I$PARAM_ID = 1464) THEN
    BEGIN
        SELECT CAST(COALESCE(SUM(VI.VAL),0) AS NUMERIC(18,2))
        FROM LINKS L73
        JOIN LINKS L16 ON L16.PARENT_ID = L73.OBJ_ID AND L16.DATE_DEL IS NULL AND L16.OBJ_TYPE_ID = 16
        JOIN LINKS L61 ON L61.PARENT_ID = L16.OBJ_ID AND L61.DATE_DEL IS NULL AND L61.OBJ_TYPE_ID = 61
        JOIN VALL VL ON VL.OBJ_ID = L61.OBJ_ID AND VL.IS_DEL = 0 AND VL.PARAM_ID = 526 AND VL.LISTVAL_ID = 1130
        JOIN VALF VI ON VI.OBJ_ID = L61.OBJ_ID AND VI.IS_DEL = 0 AND VI.PARAM_ID = 533
        WHERE L73.PARENT_ID = :I$SCHOOL_ID AND L73.DATE_DEL IS NULL AND L73.OBJ_TYPE_ID = 73
        INTO :VAL;

        SORT_ORDER = VAL;
    END
    ELSE IF (I$PARAM_ID = 1468) THEN
    BEGIN
        -- Бассейн
        IF (EXISTS(
            SELECT FIRST 1 1
            FROM LINKS L73
            JOIN LINKS L16 ON L16.PARENT_ID = L73.OBJ_ID AND L16.DATE_DEL IS NULL AND L16.OBJ_TYPE_ID = 16
            JOIN LINKS L61 ON L61.PARENT_ID = L16.OBJ_ID AND L61.DATE_DEL IS NULL AND L61.OBJ_TYPE_ID = 61
            JOIN VALL VL ON VL.OBJ_ID = L61.OBJ_ID AND VL.IS_DEL = 0 AND VL.PARAM_ID = 526 AND VL.LISTVAL_ID = 1132
            WHERE L73.PARENT_ID = :I$SCHOOL_ID AND L73.DATE_DEL IS NULL AND L73.OBJ_TYPE_ID = 73
        )) THEN
        BEGIN
            VAL = 'Да';
            SORT_ORDER = 1;
        END
        ELSE
        BEGIN
            VAL = 'Нет';
            SORT_ORDER = 0;

            -- Обнуляем параметр со значением площади бассейн
            SELECT FIRST 1 L162.OBJ_ID, V2521.VAL
            FROM LINKS L162
            LEFT JOIN VALF V2521 ON V2521.OBJ_ID = L162.OBJ_ID AND V2521.PARAM_ID = 2521 AND V2521.IS_DEL = 0
            WHERE L162.PARENT_ID = :I$SCHOOL_ID AND L162.OBJ_TYPE_ID = 162 AND L162.DATE_DEL IS NULL
            INTO :V$MONITORING_ID, :F;
            IF(F IS NULL OR F <> 0) THEN
            BEGIN
                SELECT BLOB_ID FROM VAL_ADD(2521, :V$MONITORING_ID, 0) INTO :V$MONITORING_ID;
            END
        END
    END
    ELSE IF (I$PARAM_ID = 1469) THEN
    BEGIN
        IF (EXISTS(
            SELECT FIRST 1 1
            FROM LINKS L73
            JOIN LINKS L16 ON L16.PARENT_ID = L73.OBJ_ID AND L16.DATE_DEL IS NULL AND L16.OBJ_TYPE_ID = 16
            JOIN LINKS L61 ON L61.PARENT_ID = L16.OBJ_ID AND L61.DATE_DEL IS NULL AND L61.OBJ_TYPE_ID = 61
            JOIN VALL VL ON VL.OBJ_ID = L61.OBJ_ID AND VL.IS_DEL = 0 AND VL.PARAM_ID = 526 AND VL.LISTVAL_ID = 1733
            WHERE L73.PARENT_ID = :I$SCHOOL_ID AND L73.DATE_DEL IS NULL AND L73.OBJ_TYPE_ID = 73
        )) THEN
        BEGIN
            VAL = 'Да';
            SORT_ORDER = 1;
        END
        ELSE
        BEGIN
            VAL = 'Нет';
            SORT_ORDER = 0;
        END
    END
    ELSE IF (I$PARAM_ID = 1470) THEN
    BEGIN
        IF (EXISTS(
            SELECT FIRST 1 1
            FROM LINKS L73
    
            JOIN LINKS L16
            ON L16.PARENT_ID = L73.OBJ_ID
            AND L16.DATE_DEL IS NULL
            AND L16.OBJ_TYPE_ID = 16
    
            JOIN LINKS L61
            ON L61.PARENT_ID = L16.OBJ_ID
            AND L61.DATE_DEL IS NULL
            AND L61.OBJ_TYPE_ID = 61
    
            JOIN VALL VL
            ON VL.OBJ_ID = L61.OBJ_ID
            AND VL.IS_DEL = 0
            AND VL.PARAM_ID = 526
            AND VL.LISTVAL_ID = 1136
    
            WHERE L73.PARENT_ID = :I$SCHOOL_ID
            AND L73.DATE_DEL IS NULL
            AND L73.OBJ_TYPE_ID = 73
        )) THEN
        BEGIN
            VAL = 'Да';
            SORT_ORDER = 1;
        END
        ELSE
        BEGIN
            VAL = 'Нет';
            SORT_ORDER = 0;
        END
    END
    ELSE IF (I$PARAM_ID = 1471) THEN
    BEGIN
        SELECT SUM(
            COALESCE((
                SELECT FIRST 1 1
                FROM LINKS L61
        
                JOIN VALL VL
                ON VL.OBJ_ID = L61.OBJ_ID
                AND VL.IS_DEL = 0
                AND VL.PARAM_ID = 526
                AND VL.LISTVAL_ID IN (1155,1156)

                WHERE L61.PARENT_ID = L16.OBJ_ID
                AND L61.DATE_DEL IS NULL
                AND L61.OBJ_TYPE_ID = 61
            ),0)),
            COUNT(*)
        FROM LINKS L73

        JOIN LINKS L16
        ON L16.PARENT_ID = L73.OBJ_ID
        AND L16.DATE_DEL IS NULL
        AND L16.OBJ_TYPE_ID = 16

        WHERE L73.PARENT_ID = :I$SCHOOL_ID
        AND L73.DATE_DEL IS NULL
        AND L73.OBJ_TYPE_ID = 73

        INTO :V$Y1,
             :V$Y2;

        IF (V$Y1 = 0) THEN
        BEGIN
            VAL = 'Нет';
        END
        ELSE IF (V$Y1 <> V$Y2) THEN
        BEGIN
            VAL = 'Не везде';
        END
        ELSE
        BEGIN
            VAL = 'Да';
        END
    END
    ELSE IF (I$PARAM_ID = 1472) THEN
    BEGIN
        SELECT COALESCE(SUM(VI.VAL),0)
        FROM LINKS L73

        JOIN LINKS L16
        ON L16.PARENT_ID = L73.OBJ_ID
        AND L16.DATE_DEL IS NULL
        AND L16.OBJ_TYPE_ID = 16

        JOIN LINKS L61
        ON L61.PARENT_ID = L16.OBJ_ID
        AND L61.DATE_DEL IS NULL
        AND L61.OBJ_TYPE_ID = 61

        JOIN VALL VL
        ON VL.OBJ_ID = L61.OBJ_ID
        AND VL.IS_DEL = 0
        AND VL.PARAM_ID = 526
        AND VL.LISTVAL_ID IN (1155,1156)

        JOIN VALI VI
        ON VI.OBJ_ID = L61.OBJ_ID
        AND VI.IS_DEL = 0
        AND VI.PARAM_ID = 532

        WHERE L73.PARENT_ID = :I$SCHOOL_ID
        AND L73.DATE_DEL IS NULL
        AND L73.OBJ_TYPE_ID = 73

        INTO :VAL;

        SORT_ORDER = VAL;
    END
    ELSE IF (I$PARAM_ID = 1474) THEN
    BEGIN
        -- Спортплощадка
        IF (EXISTS(
            SELECT FIRST 1 1
            FROM LINKS L73
            JOIN LINKS L492 ON L492.PARENT_ID = L73.OBJ_ID AND L492.DATE_DEL IS NULL AND L492.OBJ_TYPE_ID = 492
            JOIN VALL V3398 ON V3398.OBJ_ID = L492.OBJ_ID AND V3398.IS_DEL = 0 AND V3398.PARAM_ID = 3398 AND V3398.LISTVAL_ID = 14242
            WHERE L73.PARENT_ID = :I$SCHOOL_ID AND L73.DATE_DEL IS NULL AND L73.OBJ_TYPE_ID = 73
        )) THEN
        BEGIN
            VAL = 'Да';
            SORT_ORDER = 1;
        END
        ELSE
        BEGIN
            VAL = 'Нет';
            SORT_ORDER = 0;
        END
    END
    ELSE IF (I$PARAM_ID = 1475) THEN
    BEGIN
        -- Стадион
        IF (EXISTS(
            SELECT FIRST 1 1
            FROM LINKS L73
            JOIN LINKS L492 ON L492.PARENT_ID = L73.OBJ_ID AND L492.DATE_DEL IS NULL AND L492.OBJ_TYPE_ID = 492
            JOIN VALL V3398 ON V3398.OBJ_ID = L492.OBJ_ID AND V3398.IS_DEL = 0 AND V3398.PARAM_ID = 3398 AND V3398.LISTVAL_ID IN (14243, 14244)
            WHERE L73.PARENT_ID = :I$SCHOOL_ID AND L73.DATE_DEL IS NULL AND L73.OBJ_TYPE_ID = 73
        )) THEN
        BEGIN
            VAL = 'Да';
            SORT_ORDER = 1;
        END
        ELSE
        BEGIN
            VAL = 'Нет';
            SORT_ORDER = 0;
        END
    END
    ELSE IF (I$PARAM_ID = 1476) THEN
    BEGIN
        -- Стадион с искусственным покрытием
        IF (EXISTS(
            SELECT FIRST 1 1
            FROM LINKS L73
            JOIN LINKS L492 ON L492.PARENT_ID = L73.OBJ_ID AND L492.DATE_DEL IS NULL AND L492.OBJ_TYPE_ID = 492
            JOIN VALL V3398 ON V3398.OBJ_ID = L492.OBJ_ID AND V3398.IS_DEL = 0 AND V3398.PARAM_ID = 3398 AND V3398.LISTVAL_ID = 14244
            WHERE L73.PARENT_ID = :I$SCHOOL_ID AND L73.DATE_DEL IS NULL AND L73.OBJ_TYPE_ID = 73
        )) THEN
        BEGIN
            VAL = 'Да';
            SORT_ORDER = 1;
        END
        ELSE
        BEGIN
            VAL = 'Нет';
            SORT_ORDER = 0;
        END
    END
    ELSE IF (I$PARAM_ID = 1477) THEN
    BEGIN
        SELECT SUM(
            COALESCE((
                SELECT FIRST 1 1
                FROM VALL VL
                WHERE VL.OBJ_ID = L16.OBJ_ID
                AND VL.IS_DEL = 0
                AND VL.PARAM_ID = 522
                AND VL.LISTVAL_ID IN (1122,1123,1124)
            ),0)),
            COUNT(*)
        FROM LINKS L73

        JOIN LINKS L16
        ON L16.PARENT_ID = L73.OBJ_ID
        AND L16.DATE_DEL IS NULL
        AND L16.OBJ_TYPE_ID = 16

        WHERE L73.PARENT_ID = :I$SCHOOL_ID
        AND L73.DATE_DEL IS NULL
        AND L73.OBJ_TYPE_ID = 73

        INTO :V$Y1,
             :V$Y2;

        IF (V$Y1 = 0) THEN
        BEGIN
            VAL = 'Нет';
        END
        ELSE IF (V$Y1 <> V$Y2) THEN
        BEGIN
            VAL = 'Не везде';
        END
        ELSE
        BEGIN
            VAL = 'Да';
        END
    END
    ELSE IF (I$PARAM_ID = 1486) THEN
    BEGIN
        SELECT COUNT(*)
        FROM LINKS L7

        JOIN LINKS L8
        ON L8.PARENT_ID = L7.OBJ_ID
        AND L8.DATE_DEL IS NULL
        AND L8.OBJ_TYPE_ID = 8

        JOIN LINKS L9
        ON L9.PARENT_ID = L8.OBJ_ID
        AND L9.DATE_DEL IS NULL
        AND L9.OBJ_TYPE_ID = 9

        JOIN LINKS L10
        ON L10.PARENT_ID = L9.OBJ_ID
        AND L10.DATE_DEL IS NULL
        AND L10.OBJ_TYPE_ID = 10

        JOIN VALL VL
        ON VL.OBJ_ID = L10.OBJ_ID
        AND VL.IS_DEL = 0
        AND VL.PARAM_ID = 2169
        AND VL.LISTVAL_ID = 2

        WHERE L7.PARENT_ID = :I$SCHOOL_ID
        AND L7.DATE_DEL IS NULL
        INTO :VAL;

        SORT_ORDER = VAL;
    END
    ELSE IF (I$PARAM_ID = 1495) THEN
    BEGIN
        V$Y1 = 1;
        VAL = '';
        FOR
            SELECT NAME || ': ' || ADDRESS
            FROM MONITORING_BUILDINGS(:I$SCHOOL_ID, :I$USER_ID)
            INTO :V
        DO
        BEGIN
            IF (VAL <> '') THEN
            BEGIN
                VAL = VAL || /*ASCII_CHAR(10) || */ASCII_CHAR(13);
            END
            -- Ограничиваем размер строки
            N = 3960 - CHAR_LENGTH(VAL);
            IF(CHAR_LENGTH(V) >= N) THEN V = SUBSTRING(V FROM 1 FOR N);
            VAL = VAL || V$Y1 || '. ' || V;
            V$Y1 = V$Y1 + 1;
        END
    END
    ELSE IF (I$PARAM_ID = 1496) THEN
    BEGIN
        V$Y1 = 1;
        VAL = '';
        FOR
            SELECT NAME || ': ' || COALESCE(CAST(STUDY_ROOM_SQUARE AS NUMERIC(18,2)),0) || ' м. кв.'
            FROM MONITORING_BUILDINGS(:I$SCHOOL_ID, :I$USER_ID)
            INTO :V
        DO
        BEGIN
            IF (VAL <> '') THEN
            BEGIN
                VAL = VAL || /*ASCII_CHAR(10) || */ASCII_CHAR(13);
            END
            -- Ограничиваем размер строки
            N = 3960 - CHAR_LENGTH(VAL);
            IF(CHAR_LENGTH(V) >= N) THEN V = SUBSTRING(V FROM 1 FOR N);
            VAL = VAL || V$Y1 || '. ' || V;
            V$Y1 = V$Y1 + 1;
        END
    END
    ELSE IF (I$PARAM_ID = 1497) THEN
    BEGIN
        V$Y1 = 1;
        VAL = '';
        FOR
            SELECT BUILDING_NAME || ', ' || GYM_NAME || ': ' || COALESCE(CAST(GYM_SQUARE AS NUMERIC(18,2)),0) || ' м. кв.'
            FROM MONITORING_GYMS(:I$SCHOOL_ID)
            INTO :V
        DO
        BEGIN
            IF (VAL <> '') THEN
            BEGIN
                VAL = VAL || /*ASCII_CHAR(10) || */ASCII_CHAR(13);
            END
            VAL = VAL || V$Y1 || '. ' || V;
            V$Y1 = V$Y1 + 1;
        END
    END
    ELSE IF (I$PARAM_ID = 1498) THEN
    BEGIN
        V$Y1 = 1;
        VAL = '';
        FOR
            SELECT BUILDING_NAME || ', ' || BUFFET_NAME || ' (' || BUFFET_PURPOSE || '): Количество посадочных мест (проектное) - ' || SEATS_PRO || ', Количество посадочных мест (фактическое) - ' || SEATS_FACT || ', площадь  (кв.м.) - ' || IIF(BUFFET_SQUARE IS NOT NULL, CAST(BUFFET_SQUARE AS NUMERIC(18,2)),0)
            FROM MONITORING_BUFFETS(:I$SCHOOL_ID, :I$USER_ID)
            INTO :V
        DO
        BEGIN
            IF (VAL <> '') THEN
            BEGIN
                VAL = VAL || /*ASCII_CHAR(10) || */ASCII_CHAR(13);
            END
            VAL = VAL || V$Y1 || '. ' || V;
            V$Y1 = V$Y1 + 1;
        END
    END
    ELSE IF (I$PARAM_ID = 1499) THEN
    BEGIN
        V$Y1 = 1;
        VAL = '';
        FOR
            SELECT NAME || ': есть спортплощадка - ' || SPORTS_GROUND
            FROM MONITORING_BUILDINGS(:I$SCHOOL_ID, :I$USER_ID)
            INTO :V
        DO
        BEGIN
            IF (VAL <> '') THEN
            BEGIN
                VAL = VAL || /*ASCII_CHAR(10) || */ASCII_CHAR(13);
            END
            VAL = VAL || V$Y1 || '. ' || V;
            V$Y1 = V$Y1 + 1;
        END
    END
    ELSE IF (I$PARAM_ID = 1500) THEN
    BEGIN
        V$Y1 = 1;
        VAL = '';
        FOR
            SELECT NAME
            FROM MONITORING_BUILDINGS(:I$SCHOOL_ID, :I$USER_ID)
            WHERE STADIUM_NATURAL = 'Да' AND NAME IS NOT NULL
            INTO :V
        DO
        BEGIN
            IF (VAL <> '') THEN
            BEGIN
                VAL = VAL || /*ASCII_CHAR(10) || */ASCII_CHAR(13);
            END
            VAL = VAL || V$Y1 || '. ' || V;
            V$Y1 = V$Y1 + 1;
        END
        IF (VAL = '') THEN
        BEGIN
            VAL = 'Нет';
        END
    END
    ELSE IF (I$PARAM_ID = 1501) THEN
    BEGIN
        V$Y1 = 1;
        VAL = '';
        FOR
            SELECT NAME
            FROM MONITORING_BUILDINGS(:I$SCHOOL_ID, :I$USER_ID)
            WHERE STADIUM_ARTIFICAL = 'Да' AND NAME IS NOT NULL
            INTO :V
        DO
        BEGIN
            IF (VAL <> '') THEN
            BEGIN
                VAL = VAL || /*ASCII_CHAR(10) || */ASCII_CHAR(13);
            END
            VAL = VAL || V$Y1 || '. ' || V;
            V$Y1 = V$Y1 + 1;
        END
        IF (VAL = '') THEN
        BEGIN
            VAL = 'Нет';
        END
    END
    ELSE IF (I$PARAM_ID = 1502) THEN
    BEGIN
        V$Y1 = 1;
        VAL = '';
        FOR
            SELECT NAME || ': ограждение - ' || FENCE
            FROM MONITORING_BUILDINGS(:I$SCHOOL_ID, :I$USER_ID)
            WHERE NAME IS NOT NULL AND FENCE IS NOT NULL
            INTO :V
        DO
        BEGIN
            IF (VAL <> '') THEN
            BEGIN
                VAL = VAL || /*ASCII_CHAR(10) || */ASCII_CHAR(13);
            END
            VAL = VAL || V$Y1 || '. ' || V;
            V$Y1 = V$Y1 + 1;
        END
    END
    ELSE IF (I$PARAM_ID = 1526) THEN
    BEGIN
        SELECT COUNT(L9.OBJ_ID)
        FROM LINKS L7

        JOIN LINKS L8
        ON L8.PARENT_ID = L7.OBJ_ID
        AND L8.DATE_DEL IS NULL
        AND L8.OBJ_TYPE_ID = 8

        JOIN LINKS L9
        ON L9.PARENT_ID = L8.OBJ_ID
        AND L9.DATE_DEL IS NULL
        AND L9.OBJ_TYPE_ID = 9

        WHERE L7.PARENT_ID = :I$SCHOOL_ID
        AND L7.DATE_DEL IS NULL
        AND L7.OBJ_TYPE_ID = 7

        INTO :VAL;
        SORT_ORDER = VAL;
    END
    ELSE IF (I$PARAM_ID IN (1528,1529,1530,1531,1532,1533,1534,1535,1536,1537,1538,1539,2908)) THEN
    BEGIN
        IF (I$PARAM_ID = 2908) THEN
        BEGIN
            V$LISTVAL_ID = 12765;
        END
        ELSE IF (I$PARAM_ID = 1528) THEN
        BEGIN
            V$LISTVAL_ID = 37;
        END
        ELSE IF (I$PARAM_ID = 1529) THEN
        BEGIN
            V$LISTVAL_ID = 38;
        END
        ELSE IF (I$PARAM_ID = 1530) THEN
        BEGIN
            V$LISTVAL_ID = 39;
        END
        ELSE IF (I$PARAM_ID = 1531) THEN
        BEGIN
            V$LISTVAL_ID = 40;
        END
        ELSE IF (I$PARAM_ID = 1532) THEN
        BEGIN
            V$LISTVAL_ID = 41;
        END
        ELSE IF (I$PARAM_ID = 1533) THEN
        BEGIN
            V$LISTVAL_ID = 42;
        END
        ELSE IF (I$PARAM_ID = 1534) THEN
        BEGIN
            V$LISTVAL_ID = 43;
        END
        ELSE IF (I$PARAM_ID = 1535) THEN
        BEGIN
            V$LISTVAL_ID = 44;
        END
        ELSE IF (I$PARAM_ID = 1536) THEN
        BEGIN
            V$LISTVAL_ID = 45;
        END
        ELSE IF (I$PARAM_ID = 1537) THEN
        BEGIN
            V$LISTVAL_ID = 46;
        END
        ELSE IF (I$PARAM_ID = 1538) THEN
        BEGIN
            V$LISTVAL_ID = 47;
        END
        ELSE IF (I$PARAM_ID = 1539) THEN
        BEGIN
            V$LISTVAL_ID = 48;
        END
        SELECT COUNT(L9.OBJ_ID)
        FROM LINKS L7

        JOIN LINKS L8
        ON L8.PARENT_ID = L7.OBJ_ID
        AND L8.DATE_DEL IS NULL
        AND L8.OBJ_TYPE_ID = 8

        JOIN VALL VL
        ON VL.OBJ_ID = L8.OBJ_ID
        AND VL.IS_DEL = 0
        AND VL.PARAM_ID = 49
        AND VL.LISTVAL_ID = :V$LISTVAL_ID

        JOIN LINKS L9
        ON L9.PARENT_ID = L8.OBJ_ID
        AND L9.DATE_DEL IS NULL
        AND L9.OBJ_TYPE_ID = 9

        WHERE L7.PARENT_ID = :I$SCHOOL_ID
        AND L7.DATE_DEL IS NULL
        AND L7.OBJ_TYPE_ID = 7

        INTO :VAL;
        SORT_ORDER = VAL;        
    END
    ELSE IF (I$PARAM_ID IN (1513,1514,1515,1516,1517,1518,1519,1520,1521,1522,1524,1525,2909)) THEN
    BEGIN
        IF (I$PARAM_ID = 2909) THEN
        BEGIN
            V$LISTVAL_ID = 12765;
        END
        ELSE IF (I$PARAM_ID = 1513) THEN
        BEGIN
            V$LISTVAL_ID = 37;
        END
        ELSE IF (I$PARAM_ID = 1514) THEN
        BEGIN
            V$LISTVAL_ID = 38;
        END
        ELSE IF (I$PARAM_ID = 1515) THEN
        BEGIN
            V$LISTVAL_ID = 39;
        END
        ELSE IF (I$PARAM_ID = 1516) THEN
        BEGIN
            V$LISTVAL_ID = 40;
        END
        ELSE IF (I$PARAM_ID = 1517) THEN
        BEGIN
            V$LISTVAL_ID = 41;
        END
        ELSE IF (I$PARAM_ID = 1518) THEN
        BEGIN
            V$LISTVAL_ID = 42;
        END
        ELSE IF (I$PARAM_ID = 1519) THEN
        BEGIN
            V$LISTVAL_ID = 43;
        END
        ELSE IF (I$PARAM_ID = 1520) THEN
        BEGIN
            V$LISTVAL_ID = 44;
        END
        ELSE IF (I$PARAM_ID = 1521) THEN
        BEGIN
            V$LISTVAL_ID = 45;
        END
        ELSE IF (I$PARAM_ID = 1522) THEN
        BEGIN
            V$LISTVAL_ID = 46;
        END
        ELSE IF (I$PARAM_ID = 1524) THEN
        BEGIN
            V$LISTVAL_ID = 47;
        END
        ELSE IF (I$PARAM_ID = 1525) THEN
        BEGIN
            V$LISTVAL_ID = 48;
        END
        SELECT COUNT(L10.OBJ_ID)
        FROM LINKS L7

        JOIN LINKS L8
        ON L8.PARENT_ID = L7.OBJ_ID
        AND L8.DATE_DEL IS NULL
        AND L8.OBJ_TYPE_ID = 8

        JOIN VALL VL
        ON VL.OBJ_ID = L8.OBJ_ID
        AND VL.IS_DEL = 0
        AND VL.PARAM_ID = 49
        AND VL.LISTVAL_ID = :V$LISTVAL_ID

        JOIN LINKS L9
        ON L9.PARENT_ID = L8.OBJ_ID
        AND L9.DATE_DEL IS NULL
        AND L9.OBJ_TYPE_ID = 9

        JOIN LINKS L10
        ON L10.PARENT_ID = L9.OBJ_ID
        AND L10.DATE_DEL IS NULL
        AND L10.OBJ_TYPE_ID = 10

        WHERE L7.PARENT_ID = :I$SCHOOL_ID
        AND L7.DATE_DEL IS NULL
        AND L7.OBJ_TYPE_ID = 7

        INTO :VAL;
        SORT_ORDER = VAL;
    END
    ELSE IF (I$PARAM_ID = 1541) THEN
    BEGIN
        SELECT COUNT(*)
        FROM LINKS L14

        JOIN LINKS L15
        ON L15.PARENT_ID = L14.OBJ_ID
        AND L15.DATE_DEL IS NULL
        AND L15.OBJ_TYPE_ID = 15

        JOIN VALL VL
        ON VL.OBJ_ID = L15.OBJ_ID
        AND VL.PARAM_ID = 72
        AND VL.IS_DEL = 0
        AND VL.LISTVAL_ID = 934

        JOIN VALD D_FROM
        ON D_FROM.OBJ_ID = L15.OBJ_ID
        AND D_FROM.PARAM_ID = 73
        AND D_FROM.IS_DEL = 0
        AND D_FROM.VAL <= CURRENT_DATE

        JOIN VALR VR
        ON VR.OBJ_ID = L15.OBJ_ID
        AND VR.PARAM_ID = 69
        AND VR.IS_DEL = 0

        JOIN VALL VAC
        ON VAC.OBJ_ID = VR.VAL
        AND VAC.PARAM_ID = 63
        AND VAC.IS_DEL = 0
        AND VAC.LISTVAL_ID IN (55,97)

        LEFT JOIN VALD D_TO
        ON D_TO.OBJ_ID = L15.OBJ_ID
        AND D_TO.PARAM_ID = 74
        AND D_TO.IS_DEL = 0

        WHERE L14.PARENT_ID = :I$SCHOOL_ID
        AND L14.DATE_DEL IS NULL
        AND L14.OBJ_TYPE_ID = 14
        AND ((D_TO.VAL > CURRENT_DATE) OR (D_TO.VAL IS NULL))

        INTO :VAL;
        SORT_ORDER = VAL;
    END
    ELSE IF (I$PARAM_ID = 1542) THEN
    BEGIN
        SELECT X FROM PARAGRAF_TEACHERS_COUNT(:I$SCHOOL_ID)
        INTO :VAL;
        SORT_ORDER = VAL;
    END
    ELSE IF (I$PARAM_ID = 1544) THEN
    BEGIN
        SELECT COUNT(*)
        FROM LINKS L14

        JOIN LINKS L15
        ON L15.PARENT_ID = L14.OBJ_ID
        AND L15.DATE_DEL IS NULL
        AND L15.OBJ_TYPE_ID = 15

        JOIN VALL VL
        ON VL.OBJ_ID = L15.OBJ_ID
        AND VL.PARAM_ID = 72
        AND VL.IS_DEL = 0
        AND VL.LISTVAL_ID = 934

        JOIN VALD D_FROM
        ON D_FROM.OBJ_ID = L15.OBJ_ID
        AND D_FROM.PARAM_ID = 73
        AND D_FROM.IS_DEL = 0
        AND D_FROM.VAL <= CURRENT_DATE

        JOIN VALR VR
        ON VR.OBJ_ID = L15.OBJ_ID
        AND VR.PARAM_ID = 69
        AND VR.IS_DEL = 0

        JOIN VALL VAC
        ON VAC.OBJ_ID = VR.VAL
        AND VAC.PARAM_ID = 63
        AND VAC.IS_DEL = 0
        AND VAC.LISTVAL_ID = 1323

        LEFT JOIN VALD D_TO
        ON D_TO.OBJ_ID = L15.OBJ_ID
        AND D_TO.PARAM_ID = 74
        AND D_TO.IS_DEL = 0

        WHERE L14.PARENT_ID = :I$SCHOOL_ID
        AND L14.DATE_DEL IS NULL
        AND L14.OBJ_TYPE_ID = 14
        AND ((D_TO.VAL > CURRENT_DATE) OR (D_TO.VAL IS NULL))

        INTO :VAL;
        SORT_ORDER = VAL;
    END
    ELSE IF (I$PARAM_ID = 1546) THEN
    BEGIN
        SELECT COUNT(*)
        FROM LINKS L14

        JOIN LINKS L15
        ON L15.PARENT_ID = L14.OBJ_ID
        AND L15.DATE_DEL IS NULL
        AND L15.OBJ_TYPE_ID = 15

        JOIN VALL VL
        ON VL.OBJ_ID = L15.OBJ_ID
        AND VL.PARAM_ID = 72
        AND VL.IS_DEL = 0
        AND VL.LISTVAL_ID = 934

        JOIN VALD D_FROM
        ON D_FROM.OBJ_ID = L15.OBJ_ID
        AND D_FROM.PARAM_ID = 73
        AND D_FROM.IS_DEL = 0
        AND D_FROM.VAL <= CURRENT_DATE

        JOIN VALR VR
        ON VR.OBJ_ID = L15.OBJ_ID
        AND VR.PARAM_ID = 69
        AND VR.IS_DEL = 0

        JOIN VALL VAC
        ON VAC.OBJ_ID = VR.VAL
        AND VAC.PARAM_ID = 58
        AND VAC.IS_DEL = 0

        JOIN LISTVALS LV
        ON LV.LISTVAL_ID = VAC.LISTVAL_ID

        LEFT JOIN VALD D_TO
        ON D_TO.OBJ_ID = L15.OBJ_ID
        AND D_TO.PARAM_ID = 74
        AND D_TO.IS_DEL = 0

        WHERE L14.PARENT_ID = :I$SCHOOL_ID
        AND L14.DATE_DEL IS NULL
        AND L14.OBJ_TYPE_ID = 14
        AND ((D_TO.VAL > CURRENT_DATE) OR (D_TO.VAL IS NULL))
        AND EXISTS (
            SELECT FIRST 1 1
            FROM RES_GET(LV.RES_ID,  :LANG_CODE) R
            WHERE R.VAL_LONG SIMILAR TO 'Учитель'
        )

        INTO :VAL;
        SORT_ORDER = VAL;
    END
    ELSE IF (I$PARAM_ID = 1726) THEN
    BEGIN
        SELECT COUNT(*)
        FROM LINKS L14

        JOIN LINKS L15
        ON L15.PARENT_ID = L14.OBJ_ID
        AND L15.DATE_DEL IS NULL
        AND L15.OBJ_TYPE_ID = 15

        JOIN VALL VL
        ON VL.OBJ_ID = L15.OBJ_ID
        AND VL.PARAM_ID = 72
        AND VL.IS_DEL = 0
        AND VL.LISTVAL_ID = 934

        JOIN VALD D_FROM
        ON D_FROM.OBJ_ID = L15.OBJ_ID
        AND D_FROM.PARAM_ID = 73
        AND D_FROM.IS_DEL = 0
        AND D_FROM.VAL <= CURRENT_DATE

        JOIN VALR VR
        ON VR.OBJ_ID = L15.OBJ_ID
        AND VR.PARAM_ID = 69
        AND VR.IS_DEL = 0

        JOIN VALL VAC
        ON VAC.OBJ_ID = VR.VAL
        AND VAC.PARAM_ID = 58
        AND VAC.IS_DEL = 0

        JOIN LISTVALS LV
        ON LV.LISTVAL_ID = VAC.LISTVAL_ID

        LEFT JOIN VALD D_TO
        ON D_TO.OBJ_ID = L15.OBJ_ID
        AND D_TO.PARAM_ID = 74
        AND D_TO.IS_DEL = 0

        WHERE L14.PARENT_ID = :I$SCHOOL_ID
        AND L14.DATE_DEL IS NULL
        AND L14.OBJ_TYPE_ID = 14
        AND ((D_TO.VAL > CURRENT_DATE) OR (D_TO.VAL IS NULL))
        AND EXISTS (
            SELECT FIRST 1 1
            FROM RES_GET(LV.RES_ID,  :LANG_CODE) R
            WHERE R.VAL_LONG SIMILAR TO 'Воспитатель'
        )

        INTO :VAL;
        SORT_ORDER = VAL;
    END
    ELSE IF (I$PARAM_ID = 1547) THEN
    BEGIN
        SELECT COUNT(*)
        FROM LINKS L14

        JOIN LINKS L15
        ON L15.PARENT_ID = L14.OBJ_ID
        AND L15.DATE_DEL IS NULL
        AND L15.OBJ_TYPE_ID = 15

        JOIN VALL VL
        ON VL.OBJ_ID = L15.OBJ_ID
        AND VL.PARAM_ID = 72
        AND VL.IS_DEL = 0
        AND VL.LISTVAL_ID = 934

        JOIN VALD D_FROM
        ON D_FROM.OBJ_ID = L15.OBJ_ID
        AND D_FROM.PARAM_ID = 73
        AND D_FROM.IS_DEL = 0
        AND D_FROM.VAL <= CURRENT_DATE

        JOIN VALR VR
        ON VR.OBJ_ID = L15.OBJ_ID
        AND VR.PARAM_ID = 69
        AND VR.IS_DEL = 0

        JOIN VALL VAC
        ON VAC.OBJ_ID = VR.VAL
        AND VAC.PARAM_ID = 63
        AND VAC.IS_DEL = 0
        AND VAC.LISTVAL_ID = 55

        LEFT JOIN VALD D_TO
        ON D_TO.OBJ_ID = L15.OBJ_ID
        AND D_TO.PARAM_ID = 74
        AND D_TO.IS_DEL = 0

        WHERE L14.PARENT_ID = :I$SCHOOL_ID
        AND L14.DATE_DEL IS NULL
        AND L14.OBJ_TYPE_ID = 14
        AND ((D_TO.VAL > CURRENT_DATE) OR (D_TO.VAL IS NULL))

        INTO :VAL;
        SORT_ORDER = VAL;
    END
    ELSE IF (I$PARAM_ID = 1596) THEN
    BEGIN
        -- Количество прибывших обучающихся в ОООД за учебный год
        V$Y1 = EXTRACT(YEAR FROM CURRENT_DATE);
        V$DT1 = V$Y1 || '-09-01';
        IF (CURRENT_DATE < V$DT1) THEN
        BEGIN
            V$DT1 = (V$Y1 - 1) || '-09-01';
            V$DT2 = V$Y1 || '-05-31';
        END
        ELSE
        BEGIN
            V$DT1 = V$Y1 || '-09-01';
            V$DT2 = (V$Y1 + 1) || '-05-31';
        END

        SELECT COUNT(DISTINCT M.PERSON_ID)
        FROM PERSON_MOVEMENTS M
        WHERE M.DATE_DEL IS NULL AND M.DATE_IN >= :V$DT1 AND M.DATE_IN <= :V$DT2 AND M.REASON_IN = 806 AND M.OBJ_ID / 1000000000 = :V$GEN
        INTO :VAL;
    END
    ELSE IF (I$PARAM_ID = 1597) THEN
    BEGIN
        -- Количество выбывших из ОООД за учебный год
        V$Y1 = EXTRACT(YEAR FROM CURRENT_DATE);
        V$DT1 = V$Y1 || '-09-01';
        IF (CURRENT_DATE < V$DT1) THEN
        BEGIN
            V$DT1 = (V$Y1 - 1) || '-09-01';
            V$DT2 = V$Y1 || '-05-31';
        END
        ELSE
        BEGIN
            V$DT1 = V$Y1 || '-09-01';
            V$DT2 = (V$Y1 + 1) || '-05-31';
        END

        SELECT COUNT(DISTINCT M.PERSON_ID)
        FROM PERSON_MOVEMENTS M
        WHERE M.DATE_DEL IS NULL AND M.DATE_OUT >= :V$DT1 AND M.DATE_OUT <= :V$DT2 AND M.REASON_IN = 811 AND M.OBJ_ID / 1000000000 = :V$GEN
        INTO :VAL;
    END
    ELSE IF (I$PARAM_ID = 1656) THEN
    BEGIN
        IF (EXISTS(
            SELECT FIRST 1 1
            FROM LINKS L73

            JOIN LINKS L16
            ON L16.PARENT_ID = L73.OBJ_ID
            AND L16.DATE_DEL IS NULL
            AND L16.OBJ_TYPE_ID = 16

            JOIN LINKS L61
            ON L61.PARENT_ID = L16.OBJ_ID
            AND L61.DATE_DEL IS NULL
            AND L61.OBJ_TYPE_ID = 61

            JOIN VALL VL
            ON VL.OBJ_ID = L61.OBJ_ID
            AND VL.IS_DEL = 0
            AND VL.PARAM_ID = 526
            AND VL.LISTVAL_ID IN (3287,3288)

            WHERE L73.PARENT_ID = :I$SCHOOL_ID
            AND L73.DATE_DEL IS NULL
            AND L73.OBJ_TYPE_ID = 73
        )) THEN
        BEGIN
            VAL = 'Да';
        END
        ELSE
        BEGIN
            VAL = 'Нет';
        END
    END
    ELSE IF (I$PARAM_ID IN (1685,1686,1687,1688,1689,1690,1691,1692,1693)) THEN
    BEGIN
        IF (I$PARAM_ID = 1685) THEN
        BEGIN
            V$LISTVAL_ID = 30;
        END
        ELSE IF (I$PARAM_ID = 1686) THEN
        BEGIN
            V$LISTVAL_ID = 31;
        END
        ELSE IF (I$PARAM_ID = 1687) THEN
        BEGIN
            V$LISTVAL_ID = 32;
        END
        ELSE IF (I$PARAM_ID = 1688) THEN
        BEGIN
            V$LISTVAL_ID = 33;
        END
        ELSE IF (I$PARAM_ID = 1689) THEN
        BEGIN
            V$LISTVAL_ID = 3261;
        END
        ELSE IF (I$PARAM_ID = 1690) THEN
        BEGIN
            V$LISTVAL_ID = 34;
        END
        ELSE IF (I$PARAM_ID = 1691) THEN
        BEGIN
            V$LISTVAL_ID = 35;
        END
        ELSE IF (I$PARAM_ID = 1692) THEN
        BEGIN
            V$LISTVAL_ID = 36;
        END
        ELSE IF (I$PARAM_ID = 1693) THEN
        BEGIN
            V$LISTVAL_ID = 3262;
        END

        SELECT COUNT(L10.OBJ_ID)
        FROM LINKS L7

        JOIN LINKS L8
        ON L8.PARENT_ID = L7.OBJ_ID
        AND L8.DATE_DEL IS NULL
        AND L8.OBJ_TYPE_ID = 8

        JOIN VALL VL
        ON VL.OBJ_ID = L8.OBJ_ID
        AND VL.IS_DEL = 0
        AND VL.PARAM_ID = 49
        AND VL.LISTVAL_ID = :V$LISTVAL_ID

        JOIN LINKS L9
        ON L9.PARENT_ID = L8.OBJ_ID
        AND L9.DATE_DEL IS NULL
        AND L9.OBJ_TYPE_ID = 9

        JOIN LINKS L10
        ON L10.PARENT_ID = L9.OBJ_ID
        AND L10.DATE_DEL IS NULL
        AND L10.OBJ_TYPE_ID = 10

        WHERE L7.PARENT_ID = :I$SCHOOL_ID
        AND L7.DATE_DEL IS NULL
        AND L7.OBJ_TYPE_ID = 7

        INTO :VAL;
        SORT_ORDER = VAL;
    END
    ELSE IF (I$PARAM_ID IN (1674,1675,1676,1677,1678,1680,1681,1682,1683)) THEN
    BEGIN
        IF (I$PARAM_ID = 1674) THEN
        BEGIN
            V$LISTVAL_ID = 30;
        END
        ELSE IF (I$PARAM_ID = 1675) THEN
        BEGIN
            V$LISTVAL_ID = 31;
        END
        ELSE IF (I$PARAM_ID = 1676) THEN
        BEGIN
            V$LISTVAL_ID = 32;
        END
        ELSE IF (I$PARAM_ID = 1677) THEN
        BEGIN
            V$LISTVAL_ID = 33;
        END
        ELSE IF (I$PARAM_ID = 1678) THEN
        BEGIN
            V$LISTVAL_ID = 3261;
        END
        ELSE IF (I$PARAM_ID = 1680) THEN
        BEGIN
            V$LISTVAL_ID = 34;
        END
        ELSE IF (I$PARAM_ID = 1681) THEN
        BEGIN
            V$LISTVAL_ID = 35;
        END
        ELSE IF (I$PARAM_ID = 1682) THEN
        BEGIN
            V$LISTVAL_ID = 36;
        END
        ELSE IF (I$PARAM_ID = 1683) THEN
        BEGIN
            V$LISTVAL_ID = 3262;
        END

        SELECT COUNT(L9.OBJ_ID)
        FROM LINKS L7

        JOIN LINKS L8
        ON L8.PARENT_ID = L7.OBJ_ID
        AND L8.DATE_DEL IS NULL
        AND L8.OBJ_TYPE_ID = 8

        JOIN VALL VL
        ON VL.OBJ_ID = L8.OBJ_ID
        AND VL.IS_DEL = 0
        AND VL.PARAM_ID = 49
        AND VL.LISTVAL_ID = :V$LISTVAL_ID

        JOIN LINKS L9
        ON L9.PARENT_ID = L8.OBJ_ID
        AND L9.DATE_DEL IS NULL
        AND L9.OBJ_TYPE_ID = 9

        WHERE L7.PARENT_ID = :I$SCHOOL_ID
        AND L7.DATE_DEL IS NULL
        AND L7.OBJ_TYPE_ID = 7

        INTO :VAL;
        SORT_ORDER = VAL;        
    END
    ELSE IF (I$PARAM_ID IN (1695,1696,1698,1699,1700,1701,1702,1703,1704)) THEN
    BEGIN
        IF (I$PARAM_ID = 1695) THEN
        BEGIN
            V$LISTVAL_ID = 30;
        END
        ELSE IF (I$PARAM_ID = 1696) THEN
        BEGIN
            V$LISTVAL_ID = 31;
        END
        ELSE IF (I$PARAM_ID = 1698) THEN
        BEGIN
            V$LISTVAL_ID = 32;
        END
        ELSE IF (I$PARAM_ID = 1699) THEN
        BEGIN
            V$LISTVAL_ID = 33;
        END
        ELSE IF (I$PARAM_ID = 1700) THEN
        BEGIN
            V$LISTVAL_ID = 3261;
        END
        ELSE IF (I$PARAM_ID = 1701) THEN
        BEGIN
            V$LISTVAL_ID = 34;
        END
        ELSE IF (I$PARAM_ID = 1702) THEN
        BEGIN
            V$LISTVAL_ID = 35;
        END
        ELSE IF (I$PARAM_ID = 1703) THEN
        BEGIN
            V$LISTVAL_ID = 36;
        END
        ELSE IF (I$PARAM_ID = 1704) THEN
        BEGIN
            V$LISTVAL_ID = 3262;
        END

        SELECT COUNT(L9.OBJ_ID)
        FROM LINKS L7

        JOIN LINKS L8
        ON L8.PARENT_ID = L7.OBJ_ID
        AND L8.DATE_DEL IS NULL
        AND L8.OBJ_TYPE_ID = 8

        JOIN VALL VL
        ON VL.OBJ_ID = L8.OBJ_ID
        AND VL.IS_DEL = 0
        AND VL.PARAM_ID = 49
        AND VL.LISTVAL_ID = :V$LISTVAL_ID

        JOIN LINKS L9
        ON L9.PARENT_ID = L8.OBJ_ID
        AND L9.DATE_DEL IS NULL
        AND L9.OBJ_TYPE_ID = 9

        JOIN VALL V1549
        ON V1549.OBJ_ID = L9.OBJ_ID
        AND V1549.PARAM_ID = 1549
        AND V1549.IS_DEL = 0
        AND V1549.LISTVAL_ID = 3266

        WHERE L7.PARENT_ID = :I$SCHOOL_ID
        AND L7.DATE_DEL IS NULL
        AND L7.OBJ_TYPE_ID = 7

        INTO :VAL;
        SORT_ORDER = VAL;        
    END
    ELSE IF (I$PARAM_ID IN (1706,1707,1708,1709,1710,1711,1712,1713,1714)) THEN
    BEGIN
        IF (I$PARAM_ID = 1706) THEN
        BEGIN
            V$LISTVAL_ID = 30;
        END
        ELSE IF (I$PARAM_ID = 1707) THEN
        BEGIN
            V$LISTVAL_ID = 31;
        END
        ELSE IF (I$PARAM_ID = 1708) THEN
        BEGIN
            V$LISTVAL_ID = 32;
        END
        ELSE IF (I$PARAM_ID = 1709) THEN
        BEGIN
            V$LISTVAL_ID = 33;
        END
        ELSE IF (I$PARAM_ID = 1710) THEN
        BEGIN
            V$LISTVAL_ID = 3261;
        END
        ELSE IF (I$PARAM_ID = 1711) THEN
        BEGIN
            V$LISTVAL_ID = 34;
        END
        ELSE IF (I$PARAM_ID = 1712) THEN
        BEGIN
            V$LISTVAL_ID = 35;
        END
        ELSE IF (I$PARAM_ID = 1713) THEN
        BEGIN
            V$LISTVAL_ID = 36;
        END
        ELSE IF (I$PARAM_ID = 1714) THEN
        BEGIN
            V$LISTVAL_ID = 3262;
        END

        SELECT COUNT(L9.OBJ_ID)
        FROM LINKS L7

        JOIN LINKS L8
        ON L8.PARENT_ID = L7.OBJ_ID
        AND L8.DATE_DEL IS NULL
        AND L8.OBJ_TYPE_ID = 8

        JOIN VALL VL
        ON VL.OBJ_ID = L8.OBJ_ID
        AND VL.IS_DEL = 0
        AND VL.PARAM_ID = 49
        AND VL.LISTVAL_ID = :V$LISTVAL_ID

        JOIN LINKS L9
        ON L9.PARENT_ID = L8.OBJ_ID
        AND L9.DATE_DEL IS NULL
        AND L9.OBJ_TYPE_ID = 9

        JOIN VALL V1549
        ON V1549.OBJ_ID = L9.OBJ_ID
        AND V1549.PARAM_ID = 1549
        AND V1549.IS_DEL = 0
        AND V1549.LISTVAL_ID = 3267

        WHERE L7.PARENT_ID = :I$SCHOOL_ID
        AND L7.DATE_DEL IS NULL
        AND L7.OBJ_TYPE_ID = 7

        INTO :VAL;
        SORT_ORDER = VAL;        
    END
    ELSE IF (I$PARAM_ID IN (1716,1717,1718,1719,1720,1721,1722,1723,1724)) THEN
    BEGIN
        IF (I$PARAM_ID = 1716) THEN
        BEGIN
            V$LISTVAL_ID = 30;
        END
        ELSE IF (I$PARAM_ID = 1717) THEN
        BEGIN
            V$LISTVAL_ID = 31;
        END
        ELSE IF (I$PARAM_ID = 1718) THEN
        BEGIN
            V$LISTVAL_ID = 32;
        END
        ELSE IF (I$PARAM_ID = 1719) THEN
        BEGIN
            V$LISTVAL_ID = 33;
        END
        ELSE IF (I$PARAM_ID = 1720) THEN
        BEGIN
            V$LISTVAL_ID = 3261;
        END
        ELSE IF (I$PARAM_ID = 1721) THEN
        BEGIN
            V$LISTVAL_ID = 34;
        END
        ELSE IF (I$PARAM_ID = 1722) THEN
        BEGIN
            V$LISTVAL_ID = 35;
        END
        ELSE IF (I$PARAM_ID = 1723) THEN
        BEGIN
            V$LISTVAL_ID = 36;
        END
        ELSE IF (I$PARAM_ID = 1724) THEN
        BEGIN
            V$LISTVAL_ID = 3262;
        END

        SELECT COUNT(L9.OBJ_ID)
        FROM LINKS L7

        JOIN LINKS L8
        ON L8.PARENT_ID = L7.OBJ_ID
        AND L8.DATE_DEL IS NULL
        AND L8.OBJ_TYPE_ID = 8

        JOIN VALL VL
        ON VL.OBJ_ID = L8.OBJ_ID
        AND VL.IS_DEL = 0
        AND VL.PARAM_ID = 49
        AND VL.LISTVAL_ID = :V$LISTVAL_ID

        JOIN LINKS L9
        ON L9.PARENT_ID = L8.OBJ_ID
        AND L9.DATE_DEL IS NULL
        AND L9.OBJ_TYPE_ID = 9

        JOIN VALL V1549
        ON V1549.OBJ_ID = L9.OBJ_ID
        AND V1549.PARAM_ID = 1549
        AND V1549.IS_DEL = 0
        AND V1549.LISTVAL_ID = 3268

        WHERE L7.PARENT_ID = :I$SCHOOL_ID
        AND L7.DATE_DEL IS NULL
        AND L7.OBJ_TYPE_ID = 7

        INTO :VAL;
        SORT_ORDER = VAL;        
    END
    ELSE IF (I$PARAM_ID = 1725) THEN
    BEGIN
        SELECT COUNT(L9.OBJ_ID)
        FROM LINKS L7

        JOIN LINKS L8
        ON L8.PARENT_ID = L7.OBJ_ID
        AND L8.DATE_DEL IS NULL
        AND L8.OBJ_TYPE_ID = 8

        JOIN LINKS L9
        ON L9.PARENT_ID = L8.OBJ_ID
        AND L9.DATE_DEL IS NULL
        AND L9.OBJ_TYPE_ID = 9

        JOIN VALL V1558
        ON V1558.OBJ_ID = L9.OBJ_ID
        AND V1558.PARAM_ID = 1558
        AND V1558.IS_DEL = 0
        AND V1558.LISTVAL_ID = 3296

        WHERE L7.PARENT_ID = :I$SCHOOL_ID
        AND L7.DATE_DEL IS NULL
        AND L7.OBJ_TYPE_ID = 7

        INTO :VAL;
        SORT_ORDER = VAL;        
    END
    IF (V$PARAM_ID IS NOT NULL) THEN
    BEGIN
        SELECT V, SORT_ORDER
        FROM VAL_GET(:I$SCHOOL_ID, :V$PARAM_ID, 0, :I$USER_ID)
        INTO :VAL, :SORT_ORDER;
    END
    SUSPEND;
end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE MONITORING_DO_FUNC2 (
    I$SCHOOL_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$PARAM_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    VAL VARCHAR(4000),
    SORT_ORDER DOUBLE PRECISION)
AS
declare variable V$Y smallint;
declare variable V$LISTVAL_ID bigint;
declare variable V$DT date;
declare variable V$YEAR_VAL varchar(100);
declare variable V$YEAR_ID bigint;
begin
    V$Y = EXTRACT(YEAR FROM CURRENT_DATE);
    V$DT = '1.09.' || V$Y;
        
    IF (CURRENT_DATE < V$DT) THEN
    BEGIN
        V$YEAR_VAL = (V$Y - 1) || '-' || V$Y;
    END
    ELSE
    BEGIN
        V$YEAR_VAL = V$Y || '-' ||(V$Y + 1);
    END
        
    SELECT FIRST 1
           LV.LISTVAL_ID
    FROM LISTVALS LV
        
    JOIN RES R
    ON R.RES_ID = LV.RES_ID
    AND R.LANG_CODE = 'RU'
        
    WHERE LV.LIST_ID = 29
    AND R.VAL LIKE :V$YEAR_VAL
    INTO :V$YEAR_ID;

    IF (I$PARAM_ID = 2399) THEN
    BEGIN
        SELECT COUNT(L10.OBJ_ID)
        FROM LINKS L7

        JOIN LINKS L8
        ON L8.PARENT_ID = L7.OBJ_ID
        AND L8.DATE_DEL IS NULL
        AND L8.OBJ_TYPE_ID = 8

        JOIN LINKS L9
        ON L9.PARENT_ID = L8.OBJ_ID
        AND L9.DATE_DEL IS NULL
        AND L9.OBJ_TYPE_ID = 9

        JOIN LINKS L10
        ON L10.PARENT_ID = L9.OBJ_ID
        AND L10.DATE_DEL IS NULL
        AND L10.OBJ_TYPE_ID = 10

        WHERE L7.PARENT_ID = :I$SCHOOL_ID
        AND L7.DATE_DEL IS NULL
        AND L7.OBJ_TYPE_ID = 7
        AND NOT EXISTS(
            SELECT FIRST 1 1
            FROM LINKS L297

            JOIN VALL V2394
            ON V2394.OBJ_ID = L297.OBJ_ID
            AND V2394.PARAM_ID = 2394
            AND V2394.IS_DEL = 0
    
            JOIN VALL V2391
            ON V2391.OBJ_ID = L297.OBJ_ID
            AND V2391.PARAM_ID = 2391
            AND V2391.IS_DEL = 0
    
            JOIN VALL V2392
            ON V2392.OBJ_ID = L297.OBJ_ID
            AND V2392.PARAM_ID = 2392
            AND V2392.IS_DEL = 0
    
            JOIN VALL V2393
            ON V2393.OBJ_ID = L297.OBJ_ID
            AND V2393.PARAM_ID = 2393
            AND V2393.IS_DEL = 0
    
            WHERE L297.PARENT_ID = L10.OBJ_ID
            AND L297.OBJ_TYPE_ID = 297
            AND L297.DATE_DEL IS NULL
            AND V2394.LISTVAL_ID = :V$YEAR_ID
        )
        INTO :VAL;
        SORT_ORDER = VAL;
    END
    ELSE IF (I$PARAM_ID = 2400) THEN
    BEGIN
        SELECT COUNT(L10.OBJ_ID)
        FROM LINKS L7

        JOIN VALL V43
        ON V43.OBJ_ID = L7.OBJ_ID
        AND V43.PARAM_ID = 43
        AND V43.IS_DEL = 0
        AND V43.LISTVAL_ID = 22

        JOIN LINKS L8
        ON L8.PARENT_ID = L7.OBJ_ID
        AND L8.DATE_DEL IS NULL
        AND L8.OBJ_TYPE_ID = 8

        JOIN LINKS L9
        ON L9.PARENT_ID = L8.OBJ_ID
        AND L9.DATE_DEL IS NULL
        AND L9.OBJ_TYPE_ID = 9

        JOIN LINKS L10
        ON L10.PARENT_ID = L9.OBJ_ID
        AND L10.DATE_DEL IS NULL
        AND L10.OBJ_TYPE_ID = 10

        WHERE L7.PARENT_ID = :I$SCHOOL_ID
        AND L7.DATE_DEL IS NULL
        AND L7.OBJ_TYPE_ID = 7
        AND NOT EXISTS(
            SELECT FIRST 1 1
            FROM LINKS L297

            JOIN VALL V2394
            ON V2394.OBJ_ID = L297.OBJ_ID
            AND V2394.PARAM_ID = 2394
            AND V2394.IS_DEL = 0
    
            JOIN VALL V2391
            ON V2391.OBJ_ID = L297.OBJ_ID
            AND V2391.PARAM_ID = 2391
            AND V2391.IS_DEL = 0
    
            JOIN VALL V2392
            ON V2392.OBJ_ID = L297.OBJ_ID
            AND V2392.PARAM_ID = 2392
            AND V2392.IS_DEL = 0
    
            JOIN VALL V2393
            ON V2393.OBJ_ID = L297.OBJ_ID
            AND V2393.PARAM_ID = 2393
            AND V2393.IS_DEL = 0
    
            WHERE L297.PARENT_ID = L10.OBJ_ID
            AND L297.OBJ_TYPE_ID = 297
            AND L297.DATE_DEL IS NULL
            AND V2394.LISTVAL_ID = :V$YEAR_ID
        )
        INTO :VAL;
        SORT_ORDER = VAL;   
    END
    ELSE IF (I$PARAM_ID = 2401) THEN
    BEGIN
        SELECT COUNT(L10.OBJ_ID)
        FROM LINKS L7

        JOIN VALL V43
        ON V43.OBJ_ID = L7.OBJ_ID
        AND V43.PARAM_ID = 43
        AND V43.IS_DEL = 0
        AND V43.LISTVAL_ID = 26

        JOIN LINKS L8
        ON L8.PARENT_ID = L7.OBJ_ID
        AND L8.DATE_DEL IS NULL
        AND L8.OBJ_TYPE_ID = 8

        JOIN LINKS L9
        ON L9.PARENT_ID = L8.OBJ_ID
        AND L9.DATE_DEL IS NULL
        AND L9.OBJ_TYPE_ID = 9

        JOIN LINKS L10
        ON L10.PARENT_ID = L9.OBJ_ID
        AND L10.DATE_DEL IS NULL
        AND L10.OBJ_TYPE_ID = 10

        WHERE L7.PARENT_ID = :I$SCHOOL_ID
        AND L7.DATE_DEL IS NULL
        AND L7.OBJ_TYPE_ID = 7
        AND NOT EXISTS(
            SELECT FIRST 1 1
            FROM LINKS L297

            JOIN VALL V2394
            ON V2394.OBJ_ID = L297.OBJ_ID
            AND V2394.PARAM_ID = 2394
            AND V2394.IS_DEL = 0
    
            JOIN VALL V2391
            ON V2391.OBJ_ID = L297.OBJ_ID
            AND V2391.PARAM_ID = 2391
            AND V2391.IS_DEL = 0
    
            JOIN VALL V2392
            ON V2392.OBJ_ID = L297.OBJ_ID
            AND V2392.PARAM_ID = 2392
            AND V2392.IS_DEL = 0
    
            JOIN VALL V2393
            ON V2393.OBJ_ID = L297.OBJ_ID
            AND V2393.PARAM_ID = 2393
            AND V2393.IS_DEL = 0
    
            WHERE L297.PARENT_ID = L10.OBJ_ID
            AND L297.OBJ_TYPE_ID = 297
            AND L297.DATE_DEL IS NULL
            AND V2394.LISTVAL_ID = :V$YEAR_ID
        )
        INTO :VAL;
        SORT_ORDER = VAL;   
    END
    ELSE IF (I$PARAM_ID = 2402) THEN
    BEGIN
        SELECT COUNT(L10.OBJ_ID)
        FROM LINKS L7

        JOIN VALL V43
        ON V43.OBJ_ID = L7.OBJ_ID
        AND V43.PARAM_ID = 43
        AND V43.IS_DEL = 0
        AND V43.LISTVAL_ID = 27

        JOIN LINKS L8
        ON L8.PARENT_ID = L7.OBJ_ID
        AND L8.DATE_DEL IS NULL
        AND L8.OBJ_TYPE_ID = 8

        JOIN LINKS L9
        ON L9.PARENT_ID = L8.OBJ_ID
        AND L9.DATE_DEL IS NULL
        AND L9.OBJ_TYPE_ID = 9

        JOIN LINKS L10
        ON L10.PARENT_ID = L9.OBJ_ID
        AND L10.DATE_DEL IS NULL
        AND L10.OBJ_TYPE_ID = 10

        WHERE L7.PARENT_ID = :I$SCHOOL_ID
        AND L7.DATE_DEL IS NULL
        AND L7.OBJ_TYPE_ID = 7
        AND NOT EXISTS(
            SELECT FIRST 1 1
            FROM LINKS L297

            JOIN VALL V2394
            ON V2394.OBJ_ID = L297.OBJ_ID
            AND V2394.PARAM_ID = 2394
            AND V2394.IS_DEL = 0
    
            JOIN VALL V2391
            ON V2391.OBJ_ID = L297.OBJ_ID
            AND V2391.PARAM_ID = 2391
            AND V2391.IS_DEL = 0
    
            JOIN VALL V2392
            ON V2392.OBJ_ID = L297.OBJ_ID
            AND V2392.PARAM_ID = 2392
            AND V2392.IS_DEL = 0
    
            JOIN VALL V2393
            ON V2393.OBJ_ID = L297.OBJ_ID
            AND V2393.PARAM_ID = 2393
            AND V2393.IS_DEL = 0
    
            WHERE L297.PARENT_ID = L10.OBJ_ID
            AND L297.OBJ_TYPE_ID = 297
            AND L297.DATE_DEL IS NULL
            AND V2394.LISTVAL_ID = :V$YEAR_ID
        )
        INTO :VAL;
        SORT_ORDER = VAL;   
    END
    ELSE IF (I$PARAM_ID = 2412) THEN
    BEGIN
        SELECT COUNT(L10.OBJ_ID)
        FROM LINKS L7

        JOIN VALL V43
        ON V43.OBJ_ID = L7.OBJ_ID
        AND V43.PARAM_ID = 43
        AND V43.IS_DEL = 0
        AND V43.LISTVAL_ID = 3263

        JOIN LINKS L8
        ON L8.PARENT_ID = L7.OBJ_ID
        AND L8.DATE_DEL IS NULL
        AND L8.OBJ_TYPE_ID = 8

        JOIN LINKS L9
        ON L9.PARENT_ID = L8.OBJ_ID
        AND L9.DATE_DEL IS NULL
        AND L9.OBJ_TYPE_ID = 9

        JOIN LINKS L10
        ON L10.PARENT_ID = L9.OBJ_ID
        AND L10.DATE_DEL IS NULL
        AND L10.OBJ_TYPE_ID = 10

        WHERE L7.PARENT_ID = :I$SCHOOL_ID
        AND L7.DATE_DEL IS NULL
        AND L7.OBJ_TYPE_ID = 7
        AND NOT EXISTS(
            SELECT FIRST 1 1
            FROM LINKS L297

            JOIN VALL V2394
            ON V2394.OBJ_ID = L297.OBJ_ID
            AND V2394.PARAM_ID = 2394
            AND V2394.IS_DEL = 0
    
            JOIN VALL V2391
            ON V2391.OBJ_ID = L297.OBJ_ID
            AND V2391.PARAM_ID = 2391
            AND V2391.IS_DEL = 0
    
            JOIN VALL V2392
            ON V2392.OBJ_ID = L297.OBJ_ID
            AND V2392.PARAM_ID = 2392
            AND V2392.IS_DEL = 0
    
            JOIN VALL V2393
            ON V2393.OBJ_ID = L297.OBJ_ID
            AND V2393.PARAM_ID = 2393
            AND V2393.IS_DEL = 0
    
            WHERE L297.PARENT_ID = L10.OBJ_ID
            AND L297.OBJ_TYPE_ID = 297
            AND L297.DATE_DEL IS NULL
            AND V2394.LISTVAL_ID = :V$YEAR_ID
        )
        INTO :VAL;
        SORT_ORDER = VAL;   
    END
    ELSE IF (I$PARAM_ID = 2414) THEN
    BEGIN
        SELECT COUNT(L10.OBJ_ID)
        FROM LINKS L7

        JOIN VALL V43
        ON V43.OBJ_ID = L7.OBJ_ID
        AND V43.PARAM_ID = 43
        AND V43.IS_DEL = 0
        AND V43.LISTVAL_ID = 3264

        JOIN LINKS L8
        ON L8.PARENT_ID = L7.OBJ_ID
        AND L8.DATE_DEL IS NULL
        AND L8.OBJ_TYPE_ID = 8

        JOIN LINKS L9
        ON L9.PARENT_ID = L8.OBJ_ID
        AND L9.DATE_DEL IS NULL
        AND L9.OBJ_TYPE_ID = 9

        JOIN LINKS L10
        ON L10.PARENT_ID = L9.OBJ_ID
        AND L10.DATE_DEL IS NULL
        AND L10.OBJ_TYPE_ID = 10

        WHERE L7.PARENT_ID = :I$SCHOOL_ID
        AND L7.DATE_DEL IS NULL
        AND L7.OBJ_TYPE_ID = 7
        AND NOT EXISTS(
            SELECT FIRST 1 1
            FROM LINKS L297

            JOIN VALL V2394
            ON V2394.OBJ_ID = L297.OBJ_ID
            AND V2394.PARAM_ID = 2394
            AND V2394.IS_DEL = 0
    
            JOIN VALL V2391
            ON V2391.OBJ_ID = L297.OBJ_ID
            AND V2391.PARAM_ID = 2391
            AND V2391.IS_DEL = 0
    
            JOIN VALL V2392
            ON V2392.OBJ_ID = L297.OBJ_ID
            AND V2392.PARAM_ID = 2392
            AND V2392.IS_DEL = 0
    
            JOIN VALL V2393
            ON V2393.OBJ_ID = L297.OBJ_ID
            AND V2393.PARAM_ID = 2393
            AND V2393.IS_DEL = 0
    
            WHERE L297.PARENT_ID = L10.OBJ_ID
            AND L297.OBJ_TYPE_ID = 297
            AND L297.DATE_DEL IS NULL
            AND V2394.LISTVAL_ID = :V$YEAR_ID
        )
        INTO :VAL;
        SORT_ORDER = VAL;   
    END
    ELSE IF (I$PARAM_ID = 2403) THEN
    BEGIN
        -- Участвующие в ДО на платной основе (всего)
        SELECT COUNT(L10.OBJ_ID)
        FROM LINKS L7
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.DATE_DEL IS NULL AND L8.OBJ_TYPE_ID = 8
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.DATE_DEL IS NULL AND L9.OBJ_TYPE_ID = 9
        JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.DATE_DEL IS NULL AND L10.OBJ_TYPE_ID = 10
        WHERE L7.PARENT_ID = :I$SCHOOL_ID AND L7.DATE_DEL IS NULL AND L7.OBJ_TYPE_ID = 7
        AND EXISTS(
            SELECT FIRST 1 1
            FROM LINKS L297
            JOIN VALL V2394 ON V2394.OBJ_ID = L297.OBJ_ID AND V2394.PARAM_ID = 2394 AND V2394.IS_DEL = 0
            JOIN VALL V2391 ON V2391.OBJ_ID = L297.OBJ_ID AND V2391.PARAM_ID = 2391 AND V2391.IS_DEL = 0
            JOIN VALL V2392 ON V2392.OBJ_ID = L297.OBJ_ID AND V2392.PARAM_ID = 2392 AND V2392.IS_DEL = 0
            JOIN VALL V2393 ON V2393.OBJ_ID = L297.OBJ_ID AND V2393.PARAM_ID = 2393 AND V2393.IS_DEL = 0 AND V2393.LISTVAL_ID = 11328 -- платно
            WHERE L297.PARENT_ID = L10.OBJ_ID AND L297.OBJ_TYPE_ID = 297 AND L297.DATE_DEL IS NULL AND V2394.LISTVAL_ID = :V$YEAR_ID
        )
        INTO :VAL;
        SORT_ORDER = VAL;
    END
    ELSE IF (I$PARAM_ID = 2404) THEN
    BEGIN
        -- Участвующие в ДО на платной основе (начальная школа)
        SELECT COUNT(L10.OBJ_ID)
        FROM LINKS L7
        JOIN VALL V43 ON V43.OBJ_ID = L7.OBJ_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0 AND V43.LISTVAL_ID = 22
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.DATE_DEL IS NULL AND L8.OBJ_TYPE_ID = 8
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.DATE_DEL IS NULL AND L9.OBJ_TYPE_ID = 9
        JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.DATE_DEL IS NULL AND L10.OBJ_TYPE_ID = 10
        WHERE L7.PARENT_ID = :I$SCHOOL_ID AND L7.DATE_DEL IS NULL AND L7.OBJ_TYPE_ID = 7
        AND EXISTS(
            SELECT FIRST 1 1
            FROM LINKS L297
            JOIN VALL V2394 ON V2394.OBJ_ID = L297.OBJ_ID AND V2394.PARAM_ID = 2394 AND V2394.IS_DEL = 0
            JOIN VALL V2391 ON V2391.OBJ_ID = L297.OBJ_ID AND V2391.PARAM_ID = 2391 AND V2391.IS_DEL = 0
            JOIN VALL V2392 ON V2392.OBJ_ID = L297.OBJ_ID AND V2392.PARAM_ID = 2392 AND V2392.IS_DEL = 0
            JOIN VALL V2393 ON V2393.OBJ_ID = L297.OBJ_ID AND V2393.PARAM_ID = 2393 AND V2393.IS_DEL = 0 AND V2393.LISTVAL_ID = 11328 -- платно
            WHERE L297.PARENT_ID = L10.OBJ_ID AND L297.OBJ_TYPE_ID = 297 AND L297.DATE_DEL IS NULL AND V2394.LISTVAL_ID = :V$YEAR_ID
        )
        INTO :VAL;
        SORT_ORDER = VAL;   
    END
    ELSE IF (I$PARAM_ID = 2405) THEN
    BEGIN
        -- Участвующие в ДО на платной основе (основная школа)
        SELECT COUNT(L10.OBJ_ID)
        FROM LINKS L7
        JOIN VALL V43 ON V43.OBJ_ID = L7.OBJ_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0 AND V43.LISTVAL_ID = 26
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.DATE_DEL IS NULL AND L8.OBJ_TYPE_ID = 8
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.DATE_DEL IS NULL AND L9.OBJ_TYPE_ID = 9
        JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.DATE_DEL IS NULL AND L10.OBJ_TYPE_ID = 10
        WHERE L7.PARENT_ID = :I$SCHOOL_ID AND L7.DATE_DEL IS NULL AND L7.OBJ_TYPE_ID = 7
        AND EXISTS(
            SELECT FIRST 1 1
            FROM LINKS L297
            JOIN VALL V2394 ON V2394.OBJ_ID = L297.OBJ_ID AND V2394.PARAM_ID = 2394 AND V2394.IS_DEL = 0
            JOIN VALL V2391 ON V2391.OBJ_ID = L297.OBJ_ID AND V2391.PARAM_ID = 2391 AND V2391.IS_DEL = 0
            JOIN VALL V2392 ON V2392.OBJ_ID = L297.OBJ_ID AND V2392.PARAM_ID = 2392 AND V2392.IS_DEL = 0
            JOIN VALL V2393 ON V2393.OBJ_ID = L297.OBJ_ID AND V2393.PARAM_ID = 2393 AND V2393.IS_DEL = 0 AND V2393.LISTVAL_ID = 11328 -- платно
            WHERE L297.PARENT_ID = L10.OBJ_ID AND L297.OBJ_TYPE_ID = 297 AND L297.DATE_DEL IS NULL AND V2394.LISTVAL_ID = :V$YEAR_ID
        )
        INTO :VAL;
        SORT_ORDER = VAL;   
    END
    ELSE IF (I$PARAM_ID = 2406) THEN
    BEGIN
        -- Участвующие в ДО на платной основе (средняя школа)
        SELECT COUNT(L10.OBJ_ID)
        FROM LINKS L7
        JOIN VALL V43 ON V43.OBJ_ID = L7.OBJ_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0 AND V43.LISTVAL_ID = 27
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.DATE_DEL IS NULL AND L8.OBJ_TYPE_ID = 8
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.DATE_DEL IS NULL AND L9.OBJ_TYPE_ID = 9
        JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.DATE_DEL IS NULL AND L10.OBJ_TYPE_ID = 10
        WHERE L7.PARENT_ID = :I$SCHOOL_ID AND L7.DATE_DEL IS NULL AND L7.OBJ_TYPE_ID = 7
        AND EXISTS(
            SELECT FIRST 1 1
            FROM LINKS L297
            JOIN VALL V2394 ON V2394.OBJ_ID = L297.OBJ_ID AND V2394.PARAM_ID = 2394 AND V2394.IS_DEL = 0
            JOIN VALL V2391 ON V2391.OBJ_ID = L297.OBJ_ID AND V2391.PARAM_ID = 2391 AND V2391.IS_DEL = 0
            JOIN VALL V2392 ON V2392.OBJ_ID = L297.OBJ_ID AND V2392.PARAM_ID = 2392 AND V2392.IS_DEL = 0
            JOIN VALL V2393 ON V2393.OBJ_ID = L297.OBJ_ID AND V2393.PARAM_ID = 2393 AND V2393.IS_DEL = 0 AND V2393.LISTVAL_ID = 11328 -- платно
            WHERE L297.PARENT_ID = L10.OBJ_ID AND L297.OBJ_TYPE_ID = 297 AND L297.DATE_DEL IS NULL AND V2394.LISTVAL_ID = :V$YEAR_ID
        )
        INTO :VAL;
        SORT_ORDER = VAL;   
    END
    ELSE IF (I$PARAM_ID = 2413) THEN
    BEGIN
        SELECT COUNT(L10.OBJ_ID)
        FROM LINKS L7

        JOIN VALL V43
        ON V43.OBJ_ID = L7.OBJ_ID
        AND V43.PARAM_ID = 43
        AND V43.IS_DEL = 0
        AND V43.LISTVAL_ID = 3263

        JOIN LINKS L8
        ON L8.PARENT_ID = L7.OBJ_ID
        AND L8.DATE_DEL IS NULL
        AND L8.OBJ_TYPE_ID = 8

        JOIN LINKS L9
        ON L9.PARENT_ID = L8.OBJ_ID
        AND L9.DATE_DEL IS NULL
        AND L9.OBJ_TYPE_ID = 9

        JOIN LINKS L10
        ON L10.PARENT_ID = L9.OBJ_ID
        AND L10.DATE_DEL IS NULL
        AND L10.OBJ_TYPE_ID = 10

        WHERE L7.PARENT_ID = :I$SCHOOL_ID
        AND L7.DATE_DEL IS NULL
        AND L7.OBJ_TYPE_ID = 7
        AND EXISTS(
            SELECT FIRST 1 1
            FROM LINKS L297

            JOIN VALL V2394
            ON V2394.OBJ_ID = L297.OBJ_ID
            AND V2394.PARAM_ID = 2394
            AND V2394.IS_DEL = 0
    
            JOIN VALL V2391
            ON V2391.OBJ_ID = L297.OBJ_ID
            AND V2391.PARAM_ID = 2391
            AND V2391.IS_DEL = 0
    
            JOIN VALL V2392
            ON V2392.OBJ_ID = L297.OBJ_ID
            AND V2392.PARAM_ID = 2392
            AND V2392.IS_DEL = 0
    
            JOIN VALL V2393
            ON V2393.OBJ_ID = L297.OBJ_ID
            AND V2393.PARAM_ID = 2393
            AND V2393.IS_DEL = 0
    
            WHERE L297.PARENT_ID = L10.OBJ_ID
            AND L297.OBJ_TYPE_ID = 297
            AND L297.DATE_DEL IS NULL
            AND V2394.LISTVAL_ID = :V$YEAR_ID
        )
        INTO :VAL;
        SORT_ORDER = VAL;   
    END
    ELSE IF (I$PARAM_ID = 2415) THEN
    BEGIN
        SELECT COUNT(L10.OBJ_ID)
        FROM LINKS L7

        JOIN VALL V43
        ON V43.OBJ_ID = L7.OBJ_ID
        AND V43.PARAM_ID = 43
        AND V43.IS_DEL = 0
        AND V43.LISTVAL_ID = 3264

        JOIN LINKS L8
        ON L8.PARENT_ID = L7.OBJ_ID
        AND L8.DATE_DEL IS NULL
        AND L8.OBJ_TYPE_ID = 8

        JOIN LINKS L9
        ON L9.PARENT_ID = L8.OBJ_ID
        AND L9.DATE_DEL IS NULL
        AND L9.OBJ_TYPE_ID = 9

        JOIN LINKS L10
        ON L10.PARENT_ID = L9.OBJ_ID
        AND L10.DATE_DEL IS NULL
        AND L10.OBJ_TYPE_ID = 10

        WHERE L7.PARENT_ID = :I$SCHOOL_ID
        AND L7.DATE_DEL IS NULL
        AND L7.OBJ_TYPE_ID = 7
        AND EXISTS(
            SELECT FIRST 1 1
            FROM LINKS L297

            JOIN VALL V2394
            ON V2394.OBJ_ID = L297.OBJ_ID
            AND V2394.PARAM_ID = 2394
            AND V2394.IS_DEL = 0
    
            JOIN VALL V2391
            ON V2391.OBJ_ID = L297.OBJ_ID
            AND V2391.PARAM_ID = 2391
            AND V2391.IS_DEL = 0
    
            JOIN VALL V2392
            ON V2392.OBJ_ID = L297.OBJ_ID
            AND V2392.PARAM_ID = 2392
            AND V2392.IS_DEL = 0
    
            JOIN VALL V2393
            ON V2393.OBJ_ID = L297.OBJ_ID
            AND V2393.PARAM_ID = 2393
            AND V2393.IS_DEL = 0
    
            WHERE L297.PARENT_ID = L10.OBJ_ID
            AND L297.OBJ_TYPE_ID = 297
            AND L297.DATE_DEL IS NULL
            AND V2394.LISTVAL_ID = :V$YEAR_ID
        )
        INTO :VAL;
        SORT_ORDER = VAL;   
    END
    ELSE IF (I$PARAM_ID = 2408) THEN
    BEGIN
        SELECT I
        FROM VAL_GET(:I$OBJ_ID, 2407)
        INTO :V$LISTVAL_ID;

        SELECT COUNT(L10.OBJ_ID)
        FROM LINKS L7

        JOIN VALL V43
        ON V43.OBJ_ID = L7.OBJ_ID
        AND V43.PARAM_ID = 43
        AND V43.IS_DEL = 0
        AND V43.LISTVAL_ID = 22

        JOIN LINKS L8
        ON L8.PARENT_ID = L7.OBJ_ID
        AND L8.DATE_DEL IS NULL
        AND L8.OBJ_TYPE_ID = 8

        JOIN LINKS L9
        ON L9.PARENT_ID = L8.OBJ_ID
        AND L9.DATE_DEL IS NULL
        AND L9.OBJ_TYPE_ID = 9

        JOIN LINKS L10
        ON L10.PARENT_ID = L9.OBJ_ID
        AND L10.DATE_DEL IS NULL
        AND L10.OBJ_TYPE_ID = 10

        WHERE L7.PARENT_ID = :I$SCHOOL_ID
        AND L7.DATE_DEL IS NULL
        AND L7.OBJ_TYPE_ID = 7
        AND EXISTS(
            SELECT FIRST 1 1
            FROM LINKS L297

            JOIN VALL V2394
            ON V2394.OBJ_ID = L297.OBJ_ID
            AND V2394.PARAM_ID = 2394
            AND V2394.IS_DEL = 0
    
            JOIN VALL V2391
            ON V2391.OBJ_ID = L297.OBJ_ID
            AND V2391.PARAM_ID = 2391
            AND V2391.IS_DEL = 0
    
            JOIN VALL V2392
            ON V2392.OBJ_ID = L297.OBJ_ID
            AND V2392.PARAM_ID = 2392
            AND V2392.IS_DEL = 0
    
            JOIN VALL V2393
            ON V2393.OBJ_ID = L297.OBJ_ID
            AND V2393.PARAM_ID = 2393
            AND V2393.IS_DEL = 0
    
            WHERE L297.PARENT_ID = L10.OBJ_ID
            AND L297.OBJ_TYPE_ID = 297
            AND L297.DATE_DEL IS NULL
            AND V2394.LISTVAL_ID = :V$YEAR_ID
            AND V2392.LISTVAL_ID = :V$LISTVAL_ID
        )
        INTO :VAL;
        SORT_ORDER = VAL;   
    END
    ELSE IF (I$PARAM_ID = 2409) THEN
    BEGIN
        SELECT I
        FROM VAL_GET(:I$OBJ_ID, 2407)
        INTO :V$LISTVAL_ID;

        SELECT COUNT(L10.OBJ_ID)
        FROM LINKS L7

        JOIN VALL V43
        ON V43.OBJ_ID = L7.OBJ_ID
        AND V43.PARAM_ID = 43
        AND V43.IS_DEL = 0
        AND V43.LISTVAL_ID = 26

        JOIN LINKS L8
        ON L8.PARENT_ID = L7.OBJ_ID
        AND L8.DATE_DEL IS NULL
        AND L8.OBJ_TYPE_ID = 8

        JOIN LINKS L9
        ON L9.PARENT_ID = L8.OBJ_ID
        AND L9.DATE_DEL IS NULL
        AND L9.OBJ_TYPE_ID = 9

        JOIN LINKS L10
        ON L10.PARENT_ID = L9.OBJ_ID
        AND L10.DATE_DEL IS NULL
        AND L10.OBJ_TYPE_ID = 10

        WHERE L7.PARENT_ID = :I$SCHOOL_ID
        AND L7.DATE_DEL IS NULL
        AND L7.OBJ_TYPE_ID = 7
        AND EXISTS(
            SELECT FIRST 1 1
            FROM LINKS L297

            JOIN VALL V2394
            ON V2394.OBJ_ID = L297.OBJ_ID
            AND V2394.PARAM_ID = 2394
            AND V2394.IS_DEL = 0
    
            JOIN VALL V2391
            ON V2391.OBJ_ID = L297.OBJ_ID
            AND V2391.PARAM_ID = 2391
            AND V2391.IS_DEL = 0
    
            JOIN VALL V2392
            ON V2392.OBJ_ID = L297.OBJ_ID
            AND V2392.PARAM_ID = 2392
            AND V2392.IS_DEL = 0
    
            JOIN VALL V2393
            ON V2393.OBJ_ID = L297.OBJ_ID
            AND V2393.PARAM_ID = 2393
            AND V2393.IS_DEL = 0
    
            WHERE L297.PARENT_ID = L10.OBJ_ID
            AND L297.OBJ_TYPE_ID = 297
            AND L297.DATE_DEL IS NULL
            AND V2394.LISTVAL_ID = :V$YEAR_ID
            AND V2392.LISTVAL_ID = :V$LISTVAL_ID
        )
        INTO :VAL;
        SORT_ORDER = VAL;   
    END
    ELSE IF (I$PARAM_ID = 2410) THEN
    BEGIN
        SELECT I
        FROM VAL_GET(:I$OBJ_ID, 2407)
        INTO :V$LISTVAL_ID;

        SELECT COUNT(L10.OBJ_ID)
        FROM LINKS L7

        JOIN VALL V43
        ON V43.OBJ_ID = L7.OBJ_ID
        AND V43.PARAM_ID = 43
        AND V43.IS_DEL = 0
        AND V43.LISTVAL_ID = 27

        JOIN LINKS L8
        ON L8.PARENT_ID = L7.OBJ_ID
        AND L8.DATE_DEL IS NULL
        AND L8.OBJ_TYPE_ID = 8

        JOIN LINKS L9
        ON L9.PARENT_ID = L8.OBJ_ID
        AND L9.DATE_DEL IS NULL
        AND L9.OBJ_TYPE_ID = 9

        JOIN LINKS L10
        ON L10.PARENT_ID = L9.OBJ_ID
        AND L10.DATE_DEL IS NULL
        AND L10.OBJ_TYPE_ID = 10

        WHERE L7.PARENT_ID = :I$SCHOOL_ID
        AND L7.DATE_DEL IS NULL
        AND L7.OBJ_TYPE_ID = 7
        AND EXISTS(
            SELECT FIRST 1 1
            FROM LINKS L297

            JOIN VALL V2394
            ON V2394.OBJ_ID = L297.OBJ_ID
            AND V2394.PARAM_ID = 2394
            AND V2394.IS_DEL = 0
    
            JOIN VALL V2391
            ON V2391.OBJ_ID = L297.OBJ_ID
            AND V2391.PARAM_ID = 2391
            AND V2391.IS_DEL = 0
    
            JOIN VALL V2392
            ON V2392.OBJ_ID = L297.OBJ_ID
            AND V2392.PARAM_ID = 2392
            AND V2392.IS_DEL = 0
    
            JOIN VALL V2393
            ON V2393.OBJ_ID = L297.OBJ_ID
            AND V2393.PARAM_ID = 2393
            AND V2393.IS_DEL = 0
    
            WHERE L297.PARENT_ID = L10.OBJ_ID
            AND L297.OBJ_TYPE_ID = 297
            AND L297.DATE_DEL IS NULL
            AND V2394.LISTVAL_ID = :V$YEAR_ID
            AND V2392.LISTVAL_ID = :V$LISTVAL_ID
        )
        INTO :VAL;
        SORT_ORDER = VAL;   
    END
    ELSE IF (I$PARAM_ID = 2416) THEN
    BEGIN
        SELECT I
        FROM VAL_GET(:I$OBJ_ID, 2407)
        INTO :V$LISTVAL_ID;

        SELECT COUNT(L10.OBJ_ID)
        FROM LINKS L7

        JOIN VALL V43
        ON V43.OBJ_ID = L7.OBJ_ID
        AND V43.PARAM_ID = 43
        AND V43.IS_DEL = 0
        AND V43.LISTVAL_ID = 3263

        JOIN LINKS L8
        ON L8.PARENT_ID = L7.OBJ_ID
        AND L8.DATE_DEL IS NULL
        AND L8.OBJ_TYPE_ID = 8

        JOIN LINKS L9
        ON L9.PARENT_ID = L8.OBJ_ID
        AND L9.DATE_DEL IS NULL
        AND L9.OBJ_TYPE_ID = 9

        JOIN LINKS L10
        ON L10.PARENT_ID = L9.OBJ_ID
        AND L10.DATE_DEL IS NULL
        AND L10.OBJ_TYPE_ID = 10

        WHERE L7.PARENT_ID = :I$SCHOOL_ID
        AND L7.DATE_DEL IS NULL
        AND L7.OBJ_TYPE_ID = 7
        AND EXISTS(
            SELECT FIRST 1 1
            FROM LINKS L297

            JOIN VALL V2394
            ON V2394.OBJ_ID = L297.OBJ_ID
            AND V2394.PARAM_ID = 2394
            AND V2394.IS_DEL = 0
    
            JOIN VALL V2391
            ON V2391.OBJ_ID = L297.OBJ_ID
            AND V2391.PARAM_ID = 2391
            AND V2391.IS_DEL = 0
    
            JOIN VALL V2392
            ON V2392.OBJ_ID = L297.OBJ_ID
            AND V2392.PARAM_ID = 2392
            AND V2392.IS_DEL = 0
    
            JOIN VALL V2393
            ON V2393.OBJ_ID = L297.OBJ_ID
            AND V2393.PARAM_ID = 2393
            AND V2393.IS_DEL = 0
    
            WHERE L297.PARENT_ID = L10.OBJ_ID
            AND L297.OBJ_TYPE_ID = 297
            AND L297.DATE_DEL IS NULL
            AND V2394.LISTVAL_ID = :V$YEAR_ID
            AND V2392.LISTVAL_ID = :V$LISTVAL_ID
        )
        INTO :VAL;
        SORT_ORDER = VAL;   
    END
    ELSE IF (I$PARAM_ID = 2417) THEN
    BEGIN
        SELECT I
        FROM VAL_GET(:I$OBJ_ID, 2407)
        INTO :V$LISTVAL_ID;

        SELECT COUNT(L10.OBJ_ID)
        FROM LINKS L7

        JOIN VALL V43
        ON V43.OBJ_ID = L7.OBJ_ID
        AND V43.PARAM_ID = 43
        AND V43.IS_DEL = 0
        AND V43.LISTVAL_ID = 3264

        JOIN LINKS L8
        ON L8.PARENT_ID = L7.OBJ_ID
        AND L8.DATE_DEL IS NULL
        AND L8.OBJ_TYPE_ID = 8

        JOIN LINKS L9
        ON L9.PARENT_ID = L8.OBJ_ID
        AND L9.DATE_DEL IS NULL
        AND L9.OBJ_TYPE_ID = 9

        JOIN LINKS L10
        ON L10.PARENT_ID = L9.OBJ_ID
        AND L10.DATE_DEL IS NULL
        AND L10.OBJ_TYPE_ID = 10

        WHERE L7.PARENT_ID = :I$SCHOOL_ID
        AND L7.DATE_DEL IS NULL
        AND L7.OBJ_TYPE_ID = 7
        AND EXISTS(
            SELECT FIRST 1 1
            FROM LINKS L297

            JOIN VALL V2394
            ON V2394.OBJ_ID = L297.OBJ_ID
            AND V2394.PARAM_ID = 2394
            AND V2394.IS_DEL = 0
    
            JOIN VALL V2391
            ON V2391.OBJ_ID = L297.OBJ_ID
            AND V2391.PARAM_ID = 2391
            AND V2391.IS_DEL = 0
    
            JOIN VALL V2392
            ON V2392.OBJ_ID = L297.OBJ_ID
            AND V2392.PARAM_ID = 2392
            AND V2392.IS_DEL = 0
    
            JOIN VALL V2393
            ON V2393.OBJ_ID = L297.OBJ_ID
            AND V2393.PARAM_ID = 2393
            AND V2393.IS_DEL = 0
    
            WHERE L297.PARENT_ID = L10.OBJ_ID
            AND L297.OBJ_TYPE_ID = 297
            AND L297.DATE_DEL IS NULL
            AND V2394.LISTVAL_ID = :V$YEAR_ID
            AND V2392.LISTVAL_ID = :V$LISTVAL_ID
        )
        INTO :VAL;
        SORT_ORDER = VAL;   
    END
    ELSE IF (I$PARAM_ID = 2411) THEN
    BEGIN
        SELECT I
        FROM VAL_GET(:I$OBJ_ID, 2407)
        INTO :V$LISTVAL_ID;

        SELECT COUNT(L10.OBJ_ID)
        FROM LINKS L7

        JOIN LINKS L8
        ON L8.PARENT_ID = L7.OBJ_ID
        AND L8.DATE_DEL IS NULL
        AND L8.OBJ_TYPE_ID = 8

        JOIN LINKS L9
        ON L9.PARENT_ID = L8.OBJ_ID
        AND L9.DATE_DEL IS NULL
        AND L9.OBJ_TYPE_ID = 9

        JOIN LINKS L10
        ON L10.PARENT_ID = L9.OBJ_ID
        AND L10.DATE_DEL IS NULL
        AND L10.OBJ_TYPE_ID = 10

        WHERE L7.PARENT_ID = :I$SCHOOL_ID
        AND L7.DATE_DEL IS NULL
        AND L7.OBJ_TYPE_ID = 7
        AND EXISTS(
            SELECT FIRST 1 1
            FROM LINKS L297

            JOIN VALL V2394
            ON V2394.OBJ_ID = L297.OBJ_ID
            AND V2394.PARAM_ID = 2394
            AND V2394.IS_DEL = 0
    
            JOIN VALL V2391
            ON V2391.OBJ_ID = L297.OBJ_ID
            AND V2391.PARAM_ID = 2391
            AND V2391.IS_DEL = 0
    
            JOIN VALL V2392
            ON V2392.OBJ_ID = L297.OBJ_ID
            AND V2392.PARAM_ID = 2392
            AND V2392.IS_DEL = 0
    
            JOIN VALL V2393
            ON V2393.OBJ_ID = L297.OBJ_ID
            AND V2393.PARAM_ID = 2393
            AND V2393.IS_DEL = 0
    
            WHERE L297.PARENT_ID = L10.OBJ_ID
            AND L297.OBJ_TYPE_ID = 297
            AND L297.DATE_DEL IS NULL
            AND V2394.LISTVAL_ID = :V$YEAR_ID
            AND V2392.LISTVAL_ID = :V$LISTVAL_ID
        )
        INTO :VAL;
        SORT_ORDER = VAL;   
    END

    SUSPEND;
end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE MONITORING_DO_FUNC3 (
    I$SCHOOL_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    VAL VARCHAR(4000),
    SORT_ORDER DOUBLE PRECISION)
AS
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$LINK_ID BIGINT;
DECLARE VARIABLE V$BLOB_ID BIGINT;
DECLARE VARIABLE V$SUBJECT_ID BIGINT;
DECLARE VARIABLE V$STAGE_ID BIGINT;
DECLARE VARIABLE V$MONITORING_ID BIGINT;
DECLARE VARIABLE V$PLAN_ID BIGINT;
DECLARE VARIABLE V$LEVEL_ID BIGINT;
DECLARE VARIABLE V$SUBJECT_LEARN_LEVEL_ID BIGINT;
DECLARE VARIABLE V$CHECKIN_CURRICULUM_ID BIGINT;
DECLARE VARIABLE V$SRC_PLAN_ID5 BIGINT;
DECLARE VARIABLE V$SRC_PLAN_ID6 BIGINT;
DECLARE VARIABLE V$SRC_PROFILE_ID BIGINT;
DECLARE VARIABLE V$CURRICULUM_HOURS INTEGER;
DECLARE VARIABLE V$HOURS INTEGER;
DECLARE VARIABLE V$CHECK_CURRICULUM_HOURS INTEGER;
DECLARE VARIABLE V$CURRICULUM_BASE_HOURS INTEGER;
DECLARE VARIABLE V$CHECK_CURR_BASE_HOURS INTEGER;
DECLARE VARIABLE V$CURRICULUM_EXTEND_HOURS INTEGER;
DECLARE VARIABLE V$CHECK_CURR_EXT_HOURS INTEGER;
DECLARE VARIABLE V$MISSED_SUBJECTS VARCHAR(5000);
DECLARE VARIABLE V$MORE_SUBJECTS VARCHAR(5000);
DECLARE VARIABLE V$SUBJECTS_REPLACEMENT VARCHAR(5000);
DECLARE VARIABLE V$JOURNAL_NAME VARCHAR(1000);
DECLARE VARIABLE V$DELTA_SUBJECTS INTEGER;
DECLARE VARIABLE V$PTP_STATUS BIGINT;
DECLARE VARIABLE V$LESSONS_COUNT INTEGER;
DECLARE VARIABLE V$PTP_REALIZATION_PROCENT FLOAT;
DECLARE VARIABLE V$CURR_REALIZATION_PROCENT FLOAT;
DECLARE VARIABLE V$COMPARE_RESULT_ID BIGINT;
DECLARE VARIABLE V$PTP_HOURS INTEGER;
DECLARE VARIABLE V$STADY_WEEK_ID BIGINT;
DECLARE VARIABLE V$STD_ID BIGINT;
DECLARE VARIABLE V$STADY_PROFILE_ID BIGINT;
DECLARE VARIABLE V$VAL1 BIGINT;
DECLARE VARIABLE V$VAL2 BIGINT;
DECLARE VARIABLE V$VAL3 BIGINT;
DECLARE VARIABLE V$VAL4 BIGINT;
DECLARE VARIABLE V$VAL5 BIGINT;
DECLARE VARIABLE V$VAL6 BIGINT;
DECLARE VARIABLE V$VAL7 BIGINT;
DECLARE VARIABLE V$VAL8 BIGINT;
DECLARE VARIABLE V$VAL9 BIGINT;
DECLARE VARIABLE V$VAL10 BIGINT;
DECLARE VARIABLE V$HOURS_INV INTEGER;
DECLARE VARIABLE V$HOURS_VAR INTEGER;
DECLARE VARIABLE V$CHECK_HOURS_INV INTEGER;
DECLARE VARIABLE V$CHECK_HOURS_VAR INTEGER;
DECLARE VARIABLE V$HOURS_LOCAL INTEGER;
DECLARE VARIABLE V$CURRICULUM_HOURS_S INTEGER;
DECLARE VARIABLE V$CHECK_CURRICULUM_HOURS_S INTEGER;
DECLARE VARIABLE V$MATCH_H_TOTAL SMALLINT;
DECLARE VARIABLE V$MATCH_H_INV SMALLINT;
DECLARE VARIABLE V$MATCH_H_VAR SMALLINT;
DECLARE VARIABLE V$LIMIT1 INTEGER;
DECLARE VARIABLE V$LIMIT2 INTEGER;
BEGIN
  IF(NOT EXISTS(SELECT FIRST 1 1 FROM KEYS K WHERE K.KEY_CODE = 'LEVEL' AND K.KEY_VAL = 1)) THEN
  BEGIN
    EXIT;
  END

  -- Изменено 04.2023: теперь тут пересчитываем только выполнение по ПТП и урокам
  -- сам пересчет УП вынесен в MONITORING_PLAN_UPD

  -- Выбираем первый и единственный объект СМИР
  SELECT FIRST 1 L162.OBJ_ID
  FROM LINKS L162
  WHERE L162.PARENT_ID = :I$SCHOOL_ID AND L162.OBJ_TYPE_ID = 162 AND L162.DATE_DEL IS NULL
  INTO :V$MONITORING_ID;
  IF(V$MONITORING_ID IS NULL) THEN EXIT;

  -- Маркируем все объекты СМИР в части нагрузок как удаленные - потом то что живое будет восстановлено
  UPDATE LINKS
  SET DATE_DEL = CURRENT_TIMESTAMP
  --WHERE PARENT_ID = :V$MONITORING_ID AND OBJ_TYPE_ID IN (54, 305, 306, 307, 309, 310, 311, 313, 315, 316, 317, 319, 357, 358, 359, 360, 361) AND DATE_DEL IS NULL;
  -- 319 значение утрачено
  WHERE PARENT_ID = :V$MONITORING_ID AND OBJ_TYPE_ID IN (311, 313, 315, 316, 317) AND DATE_DEL IS NULL;

  -- В начальном состоянии временная таблица CURRICULUM_HOURS пуста

  -- Цикл по учебным планам
  FOR
    SELECT L400.OBJ_ID, V1594.LISTVAL_ID, V3014.LISTVAL_ID, V3112.LISTVAL_ID
    FROM LINKS L69
    JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
    JOIN VALL V1594 ON V1594.OBJ_ID = L57.OBJ_ID AND V1594.PARAM_ID = 1594 AND V1594.IS_DEL = 0 AND V1594.LISTVAL_ID IN (5339, 5341, 5343)
    LEFT JOIN VALL V2379 ON V2379.OBJ_ID = L57.OBJ_ID AND V2379.PARAM_ID = 2379 AND V2379.IS_DEL = 0
    JOIN LINKS L400 ON L400.PARENT_ID = L57.OBJ_ID AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL
    -- Только действующие
    JOIN VALL V3013 ON V3013.OBJ_ID = L400.OBJ_ID AND V3013.PARAM_ID = 3013 AND V3013.IS_DEL = 0 AND V3013.LISTVAL_ID = 11715
    -- Не проверяем заочную и очно-заочную форму
    LEFT JOIN VALL V3015 ON V3015.OBJ_ID = L400.OBJ_ID AND V3015.PARAM_ID = 3015 AND V3015.IS_DEL = 0
    LEFT JOIN VALL V3014 ON V3014.OBJ_ID = L400.OBJ_ID AND V3014.PARAM_ID = 3014 AND V3014.IS_DEL = 0
    LEFT JOIN VALL V3016 ON V3016.OBJ_ID = L400.OBJ_ID AND V3016.PARAM_ID = 3016 AND V3016.IS_DEL = 0
    LEFT JOIN VALL V3022 ON V3022.OBJ_ID = L400.OBJ_ID AND V3022.PARAM_ID = 3022 AND V3022.IS_DEL = 0
    LEFT JOIN VALL V3112 ON V3112.OBJ_ID = L400.OBJ_ID AND V3112.PARAM_ID = 3112 AND V3112.IS_DEL = 0
    WHERE L69.PARENT_ID = :I$SCHOOL_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL AND
      (V3015.LISTVAL_ID IS NULL OR V3015.LISTVAL_ID = 153) AND
      (V3016.LISTVAL_ID IS NULL OR V3016.LISTVAL_ID = 5465) AND
      (V3022.LISTVAL_ID IS NULL OR V3022.LISTVAL_ID = 3) and
      (V2379.LISTVAL_ID IS NULL OR V2379.LISTVAL_ID = 11187)
    INTO :V$PLAN_ID, :V$LEVEL_ID, :V$STD_ID, :V$STADY_PROFILE_ID
  DO
  BEGIN

    --V$SRC_PLAN_ID5 = NULL;
    --V$SRC_PROFILE_ID = NULL;

    -- Ищем эталонный учебный план в шаблонах - он тут непременно должен быть (выборка идет по уровню образования и номеру стандарта)
    /*SELECT FIRST 1 L50.OBJ_ID
    FROM LINKS L50
    JOIN VALL V2503 ON V2503.OBJ_ID = L50.OBJ_ID AND V2503.PARAM_ID = 2503 AND V2503.IS_DEL = 0 AND V2503.LISTVAL_ID = :V$LEVEL_ID
    LEFT JOIN VALL V2478 ON V2478.OBJ_ID = L50.OBJ_ID AND V2478.PARAM_ID = 2478 AND V2478.IS_DEL = 0
    JOIN VALL V2466 ON V2466.OBJ_ID = L50.OBJ_ID AND V2466.PARAM_ID = 2466 AND V2466.IS_DEL = 0 AND V2466.LISTVAL_ID = 2
    JOIN VALL V2166 ON V2166.OBJ_ID = L50.OBJ_ID AND V2166.PARAM_ID = 2166 AND V2166.IS_DEL = 0 AND V2166.LISTVAL_ID = 10955
    LEFT JOIN VALL V3155 ON V3155.OBJ_ID = L50.OBJ_ID AND V3155.PARAM_ID = 3155 AND V3155.IS_DEL = 0
    WHERE L50.PARENT_ID = 258 AND L50.OBJ_TYPE_ID = 50 AND L50.DATE_DEL IS NULL AND
      ((:V$STD_ID IS NULL) OR (V2478.LISTVAL_ID = :V$STD_ID)) AND
      (:V$STD_ID <> 13452 OR V3155.LISTVAL_ID = 11718 OR V3155.LISTVAL_ID IS NULL)
    ORDER BY V3155.LISTVAL_ID NULLS FIRST
    SELECT FIRST 1 L400.OBJ_ID
    FROM LINKS L400
    JOIN VALL V3345 ON V3345.OBJ_ID = L400.OBJ_ID AND V3345.PARAM_ID = 3345 AND V3345.IS_DEL = 0 AND V3345.LISTVAL_ID = :V$LEVEL_ID
    LEFT JOIN VALL V3014 ON V3014.OBJ_ID = L400.OBJ_ID AND V3014.PARAM_ID = 3014 AND V3014.IS_DEL = 0
    JOIN VALL V3347 ON V3347.OBJ_ID = L400.OBJ_ID AND V3347.PARAM_ID = 3347 AND V3347.IS_DEL = 0 AND V3347.LISTVAL_ID = 2
    JOIN VALL V3112 ON V3112.OBJ_ID = L400.OBJ_ID AND V3112.PARAM_ID = 3112 AND V3112.IS_DEL = 0 AND V3112.LISTVAL_ID = 10955
    LEFT JOIN VALL V3346 ON V3346.OBJ_ID = L400.OBJ_ID AND V3346.PARAM_ID = 3346 AND V3346.IS_DEL = 0
    WHERE L400.PARENT_ID = 258 AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL AND
      (:V$STD_ID IS NULL OR V3014.LISTVAL_ID = :V$STD_ID) AND
      (:V$STD_ID NOT IN (13452, 14184) OR V3346.LISTVAL_ID = 11718 OR V3346.LISTVAL_ID IS NULL)
    ORDER BY V3346.LISTVAL_ID NULLS FIRST
    INTO :V$SRC_PLAN_ID5;*/

    /*SELECT FIRST 1 L50.OBJ_ID
    FROM LINKS L50
    JOIN VALL V2503 ON V2503.OBJ_ID = L50.OBJ_ID AND V2503.PARAM_ID = 2503 AND V2503.IS_DEL = 0 AND V2503.LISTVAL_ID = :V$LEVEL_ID
    LEFT JOIN VALL V2478 ON V2478.OBJ_ID = L50.OBJ_ID AND V2478.PARAM_ID = 2478 AND V2478.IS_DEL = 0
    JOIN VALL V2466 ON V2466.OBJ_ID = L50.OBJ_ID AND V2466.PARAM_ID = 2466 AND V2466.IS_DEL = 0 AND V2466.LISTVAL_ID = 2
    JOIN VALL V2166 ON V2166.OBJ_ID = L50.OBJ_ID AND V2166.PARAM_ID = 2166 AND V2166.IS_DEL = 0 AND V2166.LISTVAL_ID = 10955
    LEFT JOIN VALL V3155 ON V3155.OBJ_ID = L50.OBJ_ID AND V3155.PARAM_ID = 3155 AND V3155.IS_DEL = 0
    WHERE L50.PARENT_ID = 258 AND L50.OBJ_TYPE_ID = 50 AND L50.DATE_DEL IS NULL AND
      ((:V$STD_ID IS NULL) OR (V2478.LISTVAL_ID = :V$STD_ID)) AND
      (:V$STD_ID <> 13452 OR V3155.LISTVAL_ID = 11719 OR V3155.LISTVAL_ID IS NULL)
    ORDER BY V3155.LISTVAL_ID NULLS FIRST
    SELECT FIRST 1 L400.OBJ_ID
    FROM LINKS L400
    JOIN VALL V3345 ON V3345.OBJ_ID = L400.OBJ_ID AND V3345.PARAM_ID = 3345 AND V3345.IS_DEL = 0 AND V3345.LISTVAL_ID = :V$LEVEL_ID
    LEFT JOIN VALL V3014 ON V3014.OBJ_ID = L400.OBJ_ID AND V3014.PARAM_ID = 3014 AND V3014.IS_DEL = 0
    JOIN VALL V3347 ON V3347.OBJ_ID = L400.OBJ_ID AND V3347.PARAM_ID = 3347 AND V3347.IS_DEL = 0 AND V3347.LISTVAL_ID = 2
    JOIN VALL V3112 ON V3112.OBJ_ID = L400.OBJ_ID AND V3112.PARAM_ID = 3112 AND V3112.IS_DEL = 0 AND V3112.LISTVAL_ID = 10955
    LEFT JOIN VALL V3346 ON V3346.OBJ_ID = L400.OBJ_ID AND V3346.PARAM_ID = 3346 AND V3346.IS_DEL = 0
    WHERE L400.PARENT_ID = 258 AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL AND
      (:V$STD_ID IS NULL OR V3014.LISTVAL_ID = :V$STD_ID) AND
      (:V$STD_ID NOT IN (13452, 14184) OR V3346.LISTVAL_ID = 11719 OR V3346.LISTVAL_ID IS NULL)
    ORDER BY V3346.LISTVAL_ID NULLS FIRST
    INTO :V$SRC_PLAN_ID6; */

    -- Если не нашелся шаблон для ФГОС-2 - берем его же ФГОС-1
    IF(V$SRC_PLAN_ID5 IS NULL) THEN BEGIN
      IF(V$STD_ID = 11721) THEN V$STD_ID = 13452;

      /*SELECT FIRST 1 L50.OBJ_ID
      FROM LINKS L50
      JOIN VALL V2503 ON V2503.OBJ_ID = L50.OBJ_ID AND V2503.PARAM_ID = 2503 AND V2503.IS_DEL = 0 AND V2503.LISTVAL_ID = :V$LEVEL_ID
      LEFT JOIN VALL V2478 ON V2478.OBJ_ID = L50.OBJ_ID AND V2478.PARAM_ID = 2478 AND V2478.IS_DEL = 0
      JOIN VALL V2466 ON V2466.OBJ_ID = L50.OBJ_ID AND V2466.PARAM_ID = 2466 AND V2466.IS_DEL = 0 AND V2466.LISTVAL_ID = 2
      JOIN VALL V2166 ON V2166.OBJ_ID = L50.OBJ_ID AND V2166.PARAM_ID = 2166 AND V2166.IS_DEL = 0 AND V2166.LISTVAL_ID = 10955
      WHERE L50.PARENT_ID = 258 AND L50.OBJ_TYPE_ID = 50 AND L50.DATE_DEL IS NULL and
        ((:V$STD_ID IS NULL) or (V2478.LISTVAL_ID = :V$STD_ID))
      SELECT FIRST 1 L400.OBJ_ID
      FROM LINKS L400
      JOIN VALL V3345 ON V3345.OBJ_ID = L400.OBJ_ID AND V3345.PARAM_ID = 3345 AND V3345.IS_DEL = 0 AND V3345.LISTVAL_ID = :V$LEVEL_ID
      LEFT JOIN VALL V3014 ON V3014.OBJ_ID = L400.OBJ_ID AND V3014.PARAM_ID = 3014 AND V3014.IS_DEL = 0
      JOIN VALL V3347 ON V3347.OBJ_ID = L400.OBJ_ID AND V3347.PARAM_ID = 3347 AND V3347.IS_DEL = 0 AND V3347.LISTVAL_ID = 2
      JOIN VALL V3112 ON V3112.OBJ_ID = L400.OBJ_ID AND V3112.PARAM_ID = 3112 AND V3112.IS_DEL = 0 AND V3112.LISTVAL_ID = 10955
      WHERE L400.PARENT_ID = 258 AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL
        AND (:V$STD_ID IS NULL OR V3014.LISTVAL_ID = :V$STD_ID)
      INTO :V$SRC_PLAN_ID5;

      V$SRC_PLAN_ID6 = V$SRC_PLAN_ID5; */
    END

    -- Проверить, точно ли сюда не будут попадать другие виды ОУ
    /*IF(V$SRC_PLAN_ID5 IS NULL) THEN BEGIN
      EXCEPTION DATA_ERROR 'Не найден шаблон для учебного плана "' ||
        (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$PLAN_ID)) || '" ' ||
        'Проверьте, что правильно указан образовательный стандарт и заполнены все поля УП.';
    END

    -- На всякий случай чистим временную таблицу
    DELETE FROM CURRICULUM_HOURS WHERE 1 = 1;
    -- Формируем временную таблицу с часами по предметам по данному УП (таблица кумулятивно пополняется по мере движения по УП)
    EXECUTE PROCEDURE BUILD_CURPLAN_HOURS(:V$PLAN_ID, NULL);
    -- И то же самое для шаблонного УП
    EXECUTE PROCEDURE BUILD_CURPLAN_HOURS(:V$SRC_PLAN_ID5, NULL);
    EXECUTE PROCEDURE BUILD_CURPLAN_HOURS(:V$SRC_PLAN_ID6, NULL); */

    /*
    -- Находим объект (маркированный как удаленный), соответствующий этому УП и шаблону
    V$OBJ_ID = NULL;
    SELECT FIRST 1 L310.OBJ_ID, L310.LINK_ID
    FROM LINKS L310
    JOIN VALR V2504 ON V2504.OBJ_ID = L310.OBJ_ID AND V2504.PARAM_ID = 2504 AND V2504.IS_DEL = 0 AND V2504.VAL = :V$PLAN_ID
    JOIN VALR V2505 ON V2505.OBJ_ID = L310.OBJ_ID AND V2505.PARAM_ID = 2505 AND V2505.IS_DEL = 0 AND V2505.VAL = :V$SRC_PLAN_ID5
    WHERE L310.PARENT_ID = :V$MONITORING_ID AND L310.OBJ_TYPE_ID = 310
    INTO :V$OBJ_ID, :V$LINK_ID;

    IF(V$OBJ_ID IS NULL) THEN
    BEGIN
      -- Если такого нет - создаем его
      SELECT OBJ_ID FROM OBJECT_ADD(:V$MONITORING_ID, 310) INTO :V$OBJ_ID;
      SELECT BLOB_ID FROM VAL_ADD(2504, :V$OBJ_ID, :V$PLAN_ID) INTO :V$BLOB_ID;
      SELECT BLOB_ID FROM VAL_ADD(2505, :V$OBJ_ID, :V$SRC_PLAN_ID5) INTO :V$BLOB_ID;
    END
    ELSE
    BEGIN
      -- Если есть - восстанавливаем из удаленных
      UPDATE LINKS SET DATE_DEL = NULL WHERE LINK_ID = :V$LINK_ID;
    END
    */

    -- Среднее образование
    IF(V$LEVEL_ID = 5343) THEN
    BEGIN

      /*V$VAL1 = NULL;
      V$VAL2 = NULL;
      V$VAL3 = NULL;
      V$VAL4 = NULL;
      V$VAL5 = NULL;
      V$VAL6 = NULL;
      V$VAL7 = NULL;
      V$VAL8 = NULL;
      V$VAL9 = NULL;
      V$VAL10 = NULL;

      -- Ищем УП с типом "Профиль" (параметр 3112 не задан)
      SELECT FIRST 1 L400.OBJ_ID
      FROM LINKS L400
      JOIN VALL V3345 ON V3345.OBJ_ID = L400.OBJ_ID AND V3345.PARAM_ID = 3345 AND V3345.IS_DEL = 0 AND V3345.LISTVAL_ID = :V$LEVEL_ID
      LEFT JOIN VALL V3014 ON V3014.OBJ_ID = L400.OBJ_ID AND V3014.PARAM_ID = 3014 AND V3014.IS_DEL = 0
      JOIN VALL V3347 ON V3347.OBJ_ID = L400.OBJ_ID AND V3347.PARAM_ID = 3347 AND V3347.IS_DEL = 0 AND V3347.LISTVAL_ID = 2
      LEFT JOIN VALL V3112 ON V3112.OBJ_ID = L400.OBJ_ID AND V3112.PARAM_ID = 3112 AND V3112.IS_DEL = 0
      WHERE L400.PARENT_ID = 258 AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL and
        (:V$STD_ID IS NULL OR V3014.LISTVAL_ID = :V$STD_ID OR (:V$STD_ID = 13452 AND V3014.LISTVAL_ID = 11721)) AND V3112.LISTVAL_ID IS NULL
      ORDER BY V3014.LISTVAL_ID DESC
      INTO :V$SRC_PROFILE_ID;

      -- Обрабатываем профильный план сверки
      IF(V$SRC_PROFILE_ID IS NOT NULL) THEN EXECUTE PROCEDURE BUILD_CURPLAN_HOURS(:V$SRC_PROFILE_ID, :V$SRC_PROFILE_ID);

      -- Проверяем соответствие по федеральной / обязательной части (внутри выборка по типу 780 дополняется выборкой по типу 12752)
      -- базовый перечень предметов
      SELECT DELTA, SUBJECTS_MISS
      FROM CURRICULUM_DELTA_INV_SUBJ_GET(:V$PLAN_ID, 780, IIF(:V$STD_ID = 11720, 1, 2))
      INTO :V$DELTA_SUBJECTS, :V$MISSED_SUBJECTS;

      IF(V$DELTA_SUBJECTS = 0) THEN
      BEGIN
        V$VAL1 = 2;
      END
      ELSE
      BEGIN
        -- Если есть нехватка предметов - формируем по ним таблицу #358
        V$VAL1 = 3;
        SELECT OBJ_ID
        FROM MONITORING_CURRICULUMTABL13_SET(:I$SCHOOL_ID, :V$PLAN_ID, :V$MISSED_SUBJECTS)
        INTO :V$OBJ_ID;
      END*/

      -- Проверяем соответствие по федеральной / обязательной части (внутри выборка по типу 780 дополняется выборкой по типу 12752)
      -- вариативная часть предметов обязательной части, прописанная в шаблоне
      /*SELECT DELTA, SUBJECTS_MISS, SUBJECTS_MORE, SUBJECTS_REPLACEMENT
      FROM CURRICULUM_DELTA_SUBJECT_GET(:V$PLAN_ID, :V$SRC_PLAN_ID5, 780)
      INTO :V$DELTA_SUBJECTS, :V$MISSED_SUBJECTS, :V$MORE_SUBJECTS, :V$SUBJECTS_REPLACEMENT;

      IF(V$MORE_SUBJECTS = '') THEN
      BEGIN
        V$VAL2 = 2;
      END
      ELSE
      BEGIN
        -- Если есть несоответствия - формируем по ним таблицу
        V$VAL2 = 3;
        SELECT OBJ_ID
        FROM MONITORING_CURRICULUMTABL14_SET(:I$SCHOOL_ID, :V$PLAN_ID, :V$MORE_SUBJECTS)
        INTO :V$OBJ_ID;
      END*/

      /*
      -- Сверка часов по профильным предметам
      IF(V$STADY_PROFILE_ID = 10955) THEN
      BEGIN
        -- Универсальный профиль - по старому стандарту должно быть 0 профильных, по новому стандарту оставляем пустым
        IF(V$STD_ID = 11720) THEN
        BEGIN
          V$VAL3 = IIF(NOT EXISTS(SELECT FIRST 1 1 FROM PLAN_SUBJECTS S WHERE S.DATE_DEL IS NULL AND S.PLAN_ID = :V$PLAN_ID AND S.IS_ADV = 1), 2, 3);
        END
        ELSE V$VAL3 = NULL;
      END
      ELSE
      BEGIN
        -- Указан какой-то тематический профиль. Должно быть не менее N предметов углубленного изучения, с ненулевыми часами ?
        -- N = 2 по старому и 3 по новому стандарту
        SELECT COUNT(DISTINCT COALESCE(S.SRC_SUBJECT_ID, S.SUBJECT_ID))
        FROM PLAN_SUBJECTS S
        WHERE S.DATE_DEL IS NULL AND S.PLAN_ID = :V$PLAN_ID AND S.IS_ADV = 1
        INTO :V$VAL3;

        IF(V$STD_ID = 11720) THEN V$VAL3 = IIF(V$VAL3 >= 2, 2, 3); ELSE V$VAL3 = IIF(V$VAL3 >= 3, 2, 3);
      END*/

      -- Таблица #360 соответствия по часам базового и профильного уровней
      -- Корневой цикл по этапам обучения
      /*V$VAL4 = 2;
      FOR
        SELECT V381.LISTVAL_ID
        FROM LINKS L54
        JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
        WHERE L54.PARENT_ID = :V$PLAN_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
        INTO :V$STAGE_ID
      DO
      BEGIN

        -- Цикл по всем предметам всех этапов в рабочем УП, одновременно пересекаем со списком профильных предметов
        -- Профильность по всем заменам предметов должна обязательно совпадать
        FOR
          SELECT DISTINCT COALESCE(S.SRC_SUBJECT_ID, S.SUBJECT_ID)
          FROM PLAN_SUBJECTS S
          JOIN PLAN_SUBJECTS S2 ON S2.OBJ_ID = S.PARENT_ID AND S2.FIELD_ID = 13303
          WHERE S.DATE_DEL IS NULL AND S.PLAN_ID = :V$PLAN_ID AND S.ROW_TYPE = 10
          INTO :V$SUBJECT_ID
        DO
        BEGIN
          V$BLOB_ID = NULL;
          SELECT FIRST 1 S.IS_ADV
          FROM PLAN_SUBJECTS S
          JOIN PLAN_SUBJECTS S2 ON S2.OBJ_ID = S.PARENT_ID AND S2.FIELD_ID = 13303
          WHERE S.DATE_DEL IS NULL AND S.PLAN_ID = :V$PLAN_ID AND S.ROW_TYPE = 10 AND (S.SRC_SUBJECT_ID = :V$SUBJECT_ID OR S.SUBJECT_ID = :V$SUBJECT_ID)
          INTO :V$BLOB_ID;

          IF(V$BLOB_ID IS NULL OR V$BLOB_ID = 0) THEN
          BEGIN
            -- базовый уровень, сверяем с базовым шаблоном
            V$CHECKIN_CURRICULUM_ID = V$SRC_PLAN_ID5;
            V$SUBJECT_LEARN_LEVEL_ID = 12046;
          END
          ELSE
          BEGIN
            -- профильный уровень, сверяем с профильным шаблоном
            V$CHECKIN_CURRICULUM_ID = V$SRC_PROFILE_ID;
            V$SUBJECT_LEARN_LEVEL_ID = 12047;
          END

          -- Сколько часов по факту по всем вариантам данного предмета - только по инвариантному компоненту
          V$HOURS = 0;
          SELECT SUM(H.HOURS)
          FROM CURRICULUM_HOURS H
          WHERE H.CURRICULUM_ID = :V$PLAN_ID AND H.COMPONENT_TYPE_ID IN (13303) --AND H.STAGE_ID = :V$STAGE_ID
            AND (H.SUBJECT_ID = :V$SUBJECT_ID OR H.TEMPLATE_SUBJECT_ID = :V$SUBJECT_ID)
          INTO :V$HOURS;
          V$HOURS = COALESCE(V$HOURS, 0);

          -- Сколько часов по факту по региональному компоненту, только физика
          V$HOURS_LOCAL = 0;
          SELECT SUM(H.HOURS)
          FROM CURRICULUM_HOURS H
          WHERE H.CURRICULUM_ID = :V$PLAN_ID AND H.COMPONENT_TYPE_ID IN (13304) --AND H.STAGE_ID = :V$STAGE_ID
            AND (H.SUBJECT_ID = :V$SUBJECT_ID OR H.TEMPLATE_SUBJECT_ID = :V$SUBJECT_ID)
            AND (:V$SUBJECT_ID = 198) -- физика
          INTO :V$HOURS_LOCAL;
          V$HOURS_LOCAL = COALESCE(V$HOURS_LOCAL, 0);

          IF(V$HOURS > 0) THEN
          BEGIN
            -- Сколько часов по плану
            -- Суммировать надо отдельно по 5-дневке и 6-дневке !!!
            V$CHECK_CURR_BASE_HOURS = (SELECT HOURS FROM CURRICULUM_HOURS_GET(:V$CHECKIN_CURRICULUM_ID, 780, :V$SUBJECT_ID));

            -- Для индивидуального проекта сверяем не с шаблоном, а > 8 часов (исправлено на 0)
            IF(V$SUBJECT_ID = 34651) THEN
            BEGIN
                -- если часов норм, то сбрасываем в шаблонное чтобы сверка прошла как надо
                IF(V$HOURS > 0) THEN V$HOURS = V$CHECK_CURR_BASE_HOURS;
            END

            -- ФГОС-2021 профильные предметы проверяем часы не на полное совпадение, а на не меньше
            IF(V$STD_ID = 13452 AND V$BLOB_ID = 1 AND V$HOURS > V$CHECK_CURR_BASE_HOURS) THEN V$HOURS = V$CHECK_CURR_BASE_HOURS;

            -- Если план и факт по часам не совпали - вносим запись
            -- #1726 кроме Физики (только в непрофильном варианте и только по старому стандарту)
            IF ((V$HOURS <> V$CHECK_CURR_BASE_HOURS) AND ((V$SUBJECT_ID <> 198) OR (V$BLOB_ID IS NOT NULL) OR (V$STD_ID <> 11720))) THEN
            BEGIN
              V$VAL4 = 3;
              -- exception data_error 'subj ' || V$SUBJECT_ID || ' ' || V$HOURS || ' ' || V$CHECK_CURR_BASE_HOURS;
              -- Сводная таблица #360
              SELECT OBJ_ID
              FROM MONITORING_CURRICULUMTABL15_SET(:I$SCHOOL_ID, :V$PLAN_ID, :V$SUBJECT_ID, :V$STAGE_ID, :V$SUBJECT_LEARN_LEVEL_ID, :V$HOURS, :V$CHECK_CURR_BASE_HOURS)
              INTO :V$OBJ_ID;
            END
            -- #1726 отдельно для непрофильной Физики
            IF ((V$SUBJECT_ID = 198) AND (V$STD_ID = 11720) AND (V$BLOB_ID IS NULL) AND ((V$HOURS < 68) OR ((V$HOURS + V$HOURS_LOCAL) < 136))) THEN
            BEGIN
              V$VAL4 = 3;
              -- Сводная таблица #360
              SELECT OBJ_ID
              FROM MONITORING_CURRICULUMTABL15_SET(:I$SCHOOL_ID, :V$PLAN_ID, :V$SUBJECT_ID, :V$STAGE_ID, :V$SUBJECT_LEARN_LEVEL_ID, (:V$HOURS + :V$HOURS_LOCAL), :V$CHECK_CURR_BASE_HOURS)
              INTO :V$OBJ_ID;
            END
          END
        END
      END

      -- Общее количество учебных часов инвариантной части
      V$HOURS_INV = (SELECT HOURS FROM CURRICULUM_HOURS_GET(:V$PLAN_ID, 780));
      V$VAL5 = IIF(V$HOURS_INV <= 2108, 2, 3);

      --- !!! тут надо исправлять ???
      -- Общее количество часов переменной части
      -- Первая составляющая - сумма по не-элективным курсам, вторая - строка "Предметы по выбору"
      V$HOURS_VAR = (SELECT HOURS FROM CURRICULUM_HOURS_GET(:V$PLAN_ID, 782, NULL, NULL, 0)) +
        (SELECT HOURS FROM CURRICULUM_HOURS_GET(:V$PLAN_ID, 782, 34607, NULL, 1));
      V$VAL5 = IIF(V$HOURS_VAR >= 408, 2, 3);

      -- Сравниваем полное количество часов
      -- в случае со средней школой у нас обязательно должны совпадать недели 10 и 11 классов
      V$STADY_WEEK_ID = NULL;
      SELECT FIRST 1 V2837.LISTVAL_ID
      FROM LINKS L54
      JOIN VALL V2837 ON V2837.OBJ_ID = L54.OBJ_ID AND V2837.PARAM_ID = 2837 AND V2837.IS_DEL = 0
      WHERE L54.PARENT_ID = :V$PLAN_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
      INTO :V$STADY_WEEK_ID;*/

      -- Дополнительные предметы - только для универсального профиля (само поле нигде не отображается !)
      /*IF(V$STADY_PROFILE_ID = 10955) THEN
      BEGIN
        SELECT DELTA, SUBJECTS_MISS
        FROM CURRICULUM_DELTA_SUBJECT_GET2(:V$PLAN_ID, NULL)
        INTO :V$DELTA_SUBJECTS, :V$MISSED_SUBJECTS;

        IF(V$DELTA_SUBJECTS = 0) THEN
        BEGIN
          V$VAL8 = 2;
        END
        ELSE
        BEGIN
          V$VAL8 = 3;
          -- Сводная таблица #361
          SELECT OBJ_ID FROM MONITORING_CURRICULUMTABL12_SET(:I$SCHOOL_ID, :V$PLAN_ID, :V$MISSED_SUBJECTS) INTO :V$OBJ_ID;
        END
      END*/

      /*V$CURRICULUM_HOURS = V$HOURS_INV + V$HOURS_VAR;

      IF(V$STD_ID = 11720) THEN
      BEGIN
        -- ФБУП 2004
        V$VAL9 = NULL;
        V$VAL10 = NULL;

        -- наполняемость по часам
        IF(((V$STADY_WEEK_ID = 11718) AND (V$CURRICULUM_HOURS <= 2312)) OR ((V$STADY_WEEK_ID = 11719) AND (V$CURRICULUM_HOURS <= 2516))) THEN
        BEGIN
          V$VAL7 = 2;
        END
        ELSE
        BEGIN
          V$VAL7 = 3;
        END
      END
      ELSE IF(V$STD_ID = 11721 OR V$STD_ID = 13452) THEN
      BEGIN
        -- ФГОС
        -- Количество предметов где есть часы >=11, кроме индпроекта и элективов
        SELECT COUNT(DISTINCT SUBJECT_ID) FROM CURRICULUM_SUBJECT_LIST_HS(:V$PLAN_ID) INTO :V$VAL9;
        V$VAL9 = IIF(V$VAL9 >= 11, 2, 3);

        V$VAL10 = IIF(V$CURRICULUM_HOURS >= 2170 AND V$CURRICULUM_HOURS <= 2590, 2, 3);

        -- наполняемость ДА для 6-дневки 37 часов, для 5-дневки 34 часа
        -- x2 поскольку счет идет за два года
        IF(((V$STADY_WEEK_ID = 11718) AND (V$CURRICULUM_HOURS <= 2312)) OR ((V$STADY_WEEK_ID = 11719) AND (V$CURRICULUM_HOURS <= 2516))) THEN
        BEGIN
          V$VAL7 = 2;
        END
        ELSE
        BEGIN
          V$VAL7 = 3;
        END
      END*/

      -- Сводная таблица #357
      /*SELECT OBJ_ID
      FROM MONITORING_CURRICULUMTABL11_SET(:I$SCHOOL_ID, :V$PLAN_ID, :V$VAL1, :V$VAL2, :V$VAL3, :V$VAL4, :V$VAL5, :V$VAL6, :V$VAL7, :V$VAL8,
        :V$STD_ID, :V$VAL9, :V$VAL10)
      INTO :V$OBJ_ID;*/

      -- Конец обработки среднего образования

    END
    ELSE
    BEGIN

      -- Начальное и общее образование

      /*V$CHECK_CURRICULUM_HOURS = 0;
      V$CURRICULUM_HOURS = 0;

      V$CHECK_CURR_BASE_HOURS = 0;
      V$CURRICULUM_BASE_HOURS = 0;

      V$CHECK_CURR_EXT_HOURS = 0;
      V$CURRICULUM_EXTEND_HOURS = 0;

      V$MATCH_H_TOTAL = 1;
      V$MATCH_H_INV = 1;
      V$MATCH_H_VAR = 1;

      IF(V$STD_ID IS NULL) THEN BEGIN
        EXCEPTION DATA_ERROR 'Для учебного плана "' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$PLAN_ID)) ||
          '" не задан образовательный стандарт';
      END

      -- Цикл по этапам обучения (параллелям)
      V$VAL8 = NULL;
      FOR
        SELECT V381.LISTVAL_ID, V2837.LISTVAL_ID, V383.VAL, V1185.VAL
        FROM LINKS L54
        JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
        LEFT JOIN VALL V2837 ON V2837.OBJ_ID = L54.OBJ_ID AND V2837.PARAM_ID = 2837 AND V2837.IS_DEL = 0
        LEFT JOIN VALI V383 ON V383.OBJ_ID = L54.OBJ_ID AND V383.PARAM_ID = 383 AND V383.IS_DEL = 0
        LEFT JOIN VALI V1185 ON V1185.OBJ_ID = L54.OBJ_ID AND V1185.PARAM_ID = 1185 AND V1185.IS_DEL = 0
        WHERE L54.PARENT_ID = :V$PLAN_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
        INTO :V$STAGE_ID, :V$STADY_WEEK_ID, :V$LIMIT1, :V$LIMIT2
      DO
      BEGIN

        IF(V$STADY_WEEK_ID IS NULL) THEN BEGIN
          EXCEPTION DATA_ERROR 'Для учебного плана "' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$PLAN_ID)) ||
            '" для одного из этапов не задана длительность учебной недели';
        END

        IF(V$VAL8 IS NULL AND V$LIMIT2 IS NOT NULL) THEN V$VAL8 = 2;
        IF(V$LIMIT2 > V$LIMIT1) THEN V$VAL8 = 3;

        -- Общее количество часов нагрузки по этапу
        -- Вычисляем из трех частей: обязательная часть + переменная часть (обычные предметы) + суммарный план по выбору
        V$HOURS_INV = (SELECT HOURS FROM CURRICULUM_HOURS_GET(:V$PLAN_ID, 780, NULL, :V$STAGE_ID));
        V$HOURS_VAR = (SELECT HOURS FROM CURRICULUM_HOURS_GET(:V$PLAN_ID, 782, NULL, :V$STAGE_ID, 0)) +
          (SELECT HOURS FROM CURRICULUM_HOURS_GET(:V$PLAN_ID, 782, 34607, :V$STAGE_ID));
        V$HOURS = V$HOURS_INV + V$HOURS_VAR;

        IF(V$HOURS > 0) THEN
        BEGIN
          V$CURRICULUM_HOURS = V$CURRICULUM_HOURS + V$HOURS;

          -- Общее количество часов по этапе в шаблоне
          V$CHECK_HOURS_INV = (SELECT HOURS FROM CURRICULUM_HOURS_GET(IIF(:V$STADY_WEEK_ID = 11718, :V$SRC_PLAN_ID5, :V$SRC_PLAN_ID6), 780, NULL, :V$STAGE_ID));
          -- Переменную часть по шаблону берем только константами - ибо переменная часть всех шаблонов обнулена
          V$CHECK_HOURS_VAR = (SELECT HOURS FROM CURRICULUM_HOURS_GET_CONST(:V$LEVEL_ID, :V$STD_ID, :V$STAGE_ID, :V$STADY_WEEK_ID));
          V$HOURS = V$CHECK_HOURS_INV + V$CHECK_HOURS_VAR;
          V$CHECK_CURRICULUM_HOURS = V$CHECK_CURRICULUM_HOURS + V$HOURS;

          -- Количество часов по компонентам суммарно по этапу, по обязательной части
          V$CHECK_CURR_BASE_HOURS = V$CHECK_CURR_BASE_HOURS + V$CHECK_HOURS_INV;
          V$CURRICULUM_BASE_HOURS = V$CURRICULUM_BASE_HOURS + V$HOURS_INV;

          -- то же, по переменной части
          V$CHECK_CURR_EXT_HOURS = V$CHECK_CURR_EXT_HOURS + V$CHECK_HOURS_VAR; -- должно быть
          V$CURRICULUM_EXTEND_HOURS = V$CURRICULUM_EXTEND_HOURS + V$HOURS_VAR; -- есть фактически

          -- Флаги соответствия
          -- Инвариантную часть тут не смотрим - там будет сверка отдельно по конкретным предметам
          -- IF(V$CHECK_HOURS_INV <> V$HOURS_INV) THEN V$MATCH_H_INV = 0;
          IF(V$CHECK_HOURS_VAR <> V$HOURS_VAR) THEN V$MATCH_H_VAR = 0;
        END
      END

      IF(V$STD_ID = 13452) THEN -- ФГОС-2021
      BEGIN
        IF(V$LEVEL_ID = 5339 AND (V$CURRICULUM_HOURS < 2954 OR V$CURRICULUM_HOURS > 3190)) THEN V$MATCH_H_TOTAL = 0;
        IF(V$LEVEL_ID = 5341 AND (V$CURRICULUM_HOURS < 5058 OR V$CURRICULUM_HOURS > 5549)) THEN V$MATCH_H_TOTAL = 0;
      END
      ELSE IF(V$STD_ID = 11721) THEN -- ФГОС
      BEGIN
        IF(V$LEVEL_ID = 5339 AND (V$CURRICULUM_HOURS < 2904 OR V$CURRICULUM_HOURS > 3345)) THEN V$MATCH_H_TOTAL = 0;
        IF(V$LEVEL_ID = 5341 AND (V$CURRICULUM_HOURS < 5267 OR V$CURRICULUM_HOURS > 6020)) THEN V$MATCH_H_TOTAL = 0;
      END
      ELSE
      BEGIN
        IF(V$CHECK_CURRICULUM_HOURS <> V$CURRICULUM_HOURS) THEN V$MATCH_H_TOTAL = 0;
      END

      -- Сверяем шаблон с УП по части соответствия этапов, и обнуляем соответствие по часам если хотя бы один этап отсутствует
      FOR
        SELECT V381.LISTVAL_ID
        FROM LINKS L54
        JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0 AND V381.LISTVAL_ID <> 12765
        WHERE L54.PARENT_ID = :V$SRC_PLAN_ID5 AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
        INTO :V$STAGE_ID
      DO
      BEGIN
        V$COMPARE_RESULT_ID = 0;

        SELECT COUNT(*)
        FROM LINKS L54_CHK
        JOIN VALL V381_CHK ON V381_CHK.OBJ_ID = L54_CHK.OBJ_ID AND V381_CHK.PARAM_ID = 381 AND V381_CHK.IS_DEL = 0 AND V381_CHK.LISTVAL_ID = :V$STAGE_ID
        WHERE L54_CHK.PARENT_ID = :V$PLAN_ID AND L54_CHK.OBJ_TYPE_ID = 54 AND L54_CHK.DATE_DEL IS NULL
        INTO :V$COMPARE_RESULT_ID;

        IF(V$COMPARE_RESULT_ID = 0) THEN
        BEGIN
          V$MATCH_H_TOTAL = 0;
          V$MATCH_H_INV = 0;
          V$MATCH_H_VAR = 0;
        END
      END*/

      -- Получаем список несоответствующих предметов обязательной части
      /*
      SELECT DELTA, SUBJECTS_MISS, SUBJECTS_MORE, SUBJECTS_REPLACEMENT
      FROM CURRICULUM_DELTA_SUBJECT_GET(:V$PLAN_ID, :V$SRC_PLAN_ID5, 780)
      INTO :V$DELTA_SUBJECTS, :V$MISSED_SUBJECTS, :V$MORE_SUBJECTS, :V$SUBJECTS_REPLACEMENT;

      -- Записываем в #306 (недостающие, лишние предметы, замены наименований предметов)
      IF(V$DELTA_SUBJECTS <> 0 OR V$SUBJECTS_REPLACEMENT <> '') THEN
      BEGIN
        SELECT OBJ_ID
        FROM MONITORING_CURRICULUMTABLE2_SET(:I$SCHOOL_ID, :V$PLAN_ID, :V$MISSED_SUBJECTS, :V$MORE_SUBJECTS, :V$SUBJECTS_REPLACEMENT)
        INTO :V$OBJ_ID;
      END
      */

      -- Запись несоответствия часов (#307)
      /*
      FOR
        SELECT SUBJECT_ID, STAGE_ID, HOURS, CHECK_HOURS
        FROM CURRICULUM_SUBJECT_HOURS_NEQ(:V$PLAN_ID, :V$SRC_PLAN_ID5, 780)
        INTO :V$SUBJECT_ID, :V$STAGE_ID, :V$CURRICULUM_HOURS_S, :V$CHECK_CURRICULUM_HOURS_S
      DO
      BEGIN
        -- Сверяем часы по конкретным предметам
        V$MATCH_H_INV = 0;
        SELECT OBJ_ID
        FROM MONITORING_CURRICULUMTABLE3_SET(:I$SCHOOL_ID, :V$PLAN_ID, :V$SUBJECT_ID, :V$STAGE_ID, :V$CHECK_CURRICULUM_HOURS_S, :V$CURRICULUM_HOURS_S)
        INTO :V$OBJ_ID;
      END
      */

      -- Несоответствие часов необязательной части (#309)
      /*FOR
        SELECT STAGE_ID, SUM(HOURS), SUM(CHECK_HOURS)
        FROM CURRICULUM_SUBJECT_HOURS_NEQ(:V$PLAN_ID, :V$SRC_PLAN_ID5, 782)
        GROUP BY STAGE_ID
        INTO :V$STAGE_ID, :V$CURRICULUM_HOURS_S, :V$CHECK_CURRICULUM_HOURS_S
      DO
      BEGIN
        SELECT OBJ_ID
        FROM MONITORING_CURRICULUMTABLE4_SET(:I$SCHOOL_ID, :V$PLAN_ID, :V$STAGE_ID, :V$CHECK_CURRICULUM_HOURS_S, :V$CURRICULUM_HOURS_S)
        INTO :V$OBJ_ID;
      END*/

      -- Записываем в #305 (общее количество часов и флаги соответствия)
      /*
      SELECT OBJ_ID
      FROM MONITORING_CURRICULUMTABLE1_SET(:I$SCHOOL_ID, :V$PLAN_ID, :V$STD_ID, :V$LEVEL_ID,
        :V$SRC_PLAN_ID5, :V$CURRICULUM_HOURS,
        IIF((:V$MATCH_H_TOTAL = 0) OR (:V$CURRICULUM_HOURS = 0), 3, 2),
        IIF(:V$DELTA_SUBJECTS <> 0, 3, 2),
        IIF((:V$MATCH_H_INV = 0) OR (:V$CURRICULUM_HOURS = 0), 3, 2),
        IIF((:V$MATCH_H_VAR = 0) OR (:V$CURRICULUM_HOURS = 0), 3, 2),
        :V$VAL8
      )
      INTO :V$OBJ_ID;
      */

    END

    /*
    -- Все этапы образования
    -- Соответствие по предельной нагрузке
    FOR
      SELECT L54.OBJ_ID
      FROM LINKS L54
      JOIN VALI V383 ON V383.OBJ_ID = L54.OBJ_ID AND V383.PARAM_ID = 383 AND V383.IS_DEL = 0
      JOIN VALI V1185 ON V1185.OBJ_ID = L54.OBJ_ID AND V1185.PARAM_ID = 1185 AND V1185.IS_DEL = 0
      WHERE L54.PARENT_ID = :V$PLAN_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL AND V1185.VAL > V383.VAL
      INTO :V$OBJ_ID
    DO
    BEGIN
      V$LINK_ID = NULL;
      SELECT FIRST 1 L54.LINK_ID
      FROM LINKS L54
      WHERE L54.PARENT_ID = :V$MONITORING_ID AND L54.OBJ_ID = :V$OBJ_ID
      INTO :V$LINK_ID;

      IF(V$LINK_ID IS NULL) THEN
      BEGIN
        -- Если такого нет - создаем его
        SELECT 1 FROM OBJECT_ADD_LINK(:V$MONITORING_ID, :V$OBJ_ID, 54) INTO :V$BLOB_ID;
      END
      ELSE
      BEGIN
        -- Если есть - восстанавливаем из удаленных
        UPDATE LINKS SET DATE_DEL = NULL WHERE LINK_ID = :V$LINK_ID AND DATE_DEL IS NOT NULL;
      END
    END
    */

    -- Назначение ПТП
    FOR
      SELECT COALESCE(SUM(NO_PTP), 0), COALESCE(SUM(NO_EQUAL_HOURS), 0)
      FROM CURRICULUM_GUP_HAS_PTP(:V$PLAN_ID, NULL)
      INTO :V$CHECK_CURRICULUM_HOURS, :V$CURRICULUM_HOURS
    DO
    BEGIN
      -- Записываем в #311
      SELECT OBJ_ID
      FROM MONITORING_CURRICULUMTABLE5_SET(:I$SCHOOL_ID, :V$PLAN_ID, :V$LEVEL_ID, :V$SRC_PLAN_ID5,
        IIF(:V$CHECK_CURRICULUM_HOURS > 0, 3, 2), IIF(:V$CURRICULUM_HOURS > 0, 3, 2)
      )
      INTO :V$OBJ_ID;
    END

    -- Утверждение ПТП
    FOR
      SELECT SUBJECT_ID, STAGE_ID, JOURNAL_NAME
      FROM CURRICULUM_GUP_SUBJ_HAS_PTP(:V$PLAN_ID, NULL)
      INTO :V$SUBJECT_ID, :V$STAGE_ID, :V$JOURNAL_NAME
    DO
    BEGIN
      -- Записываем в #313
      SELECT OBJ_ID
      FROM MONITORING_CURRICULUMTABLE6_SET(:I$SCHOOL_ID, :V$PLAN_ID, :V$SUBJECT_ID, :V$STAGE_ID, :V$JOURNAL_NAME)
      INTO :V$OBJ_ID;
    end
    
    -- Соответствие УП и ПТП
    FOR
      SELECT SUBJECT_ID, STAGE_ID, JOURNAL_NAME, CURRICULUM_HOURS, PTP_HOURS
      FROM CURRICULUM_GUP_SUBJ_PTP_HOURS(:V$PLAN_ID, NULL)
      INTO :V$SUBJECT_ID, :V$STAGE_ID, :V$JOURNAL_NAME, :V$CHECK_CURRICULUM_HOURS, :V$CURRICULUM_HOURS
    DO
    BEGIN
      -- Записываем в #315
      SELECT OBJ_ID
      FROM MONITORING_CURRICULUMTABLE7_SET(:I$SCHOOL_ID, :V$PLAN_ID, :V$SUBJECT_ID, :V$STAGE_ID, :V$JOURNAL_NAME, :V$CHECK_CURRICULUM_HOURS, :V$CURRICULUM_HOURS)
      INTO :V$OBJ_ID;
    END
    
    -- Выполнение ПТП по часам
    FOR
      SELECT SUBJECT_ID, STAGE_ID, JOURNAL_NAME, PTP_STATUS, CURRICULUM_HOURS, PTP_HOURS, LESSONS_COUNT,
        PTP_REALIZATION_PROCENT, CURRICULUM_REALIZATION_PROCENT, COMPARE_RESULT_ID
      FROM GUP_SUBJ_PTP_EXECUTION_STATUS(:V$PLAN_ID, NULL)
      INTO :V$SUBJECT_ID, :V$STAGE_ID, :V$JOURNAL_NAME, :V$PTP_STATUS, :V$CURRICULUM_HOURS, :V$PTP_HOURS, :V$LESSONS_COUNT,
        :V$PTP_REALIZATION_PROCENT, :V$CURR_REALIZATION_PROCENT, :V$COMPARE_RESULT_ID
    DO
    BEGIN
      -- Записываем в #316
      SELECT OBJ_ID
      FROM MONITORING_CURRICULUMTABLE8_SET(:I$SCHOOL_ID, :V$STAGE_ID, :V$JOURNAL_NAME, :V$SUBJECT_ID, :V$PTP_STATUS, :V$PTP_HOURS, :V$CURRICULUM_HOURS, :V$LESSONS_COUNT,
        :V$PTP_REALIZATION_PROCENT, :V$CURR_REALIZATION_PROCENT, :V$COMPARE_RESULT_ID)
      INTO :V$OBJ_ID;
    END
    
    -- Выполнение ПТП по темам уроков
    FOR
      SELECT SUBJECT_ID, STAGE_ID, JOURNAL_NAME, CJ_LESSON_MISSED, CJ_PTP_EQUALS
      FROM GUP_SUBJ_PTP_CJ_STATUS(:V$PLAN_ID, NULL)
      INTO :V$SUBJECT_ID, :V$STAGE_ID, :V$JOURNAL_NAME, :V$LESSONS_COUNT, :V$PTP_REALIZATION_PROCENT
    DO
    BEGIN
      -- Записываем в #317
      SELECT OBJ_ID
      FROM MONITORING_CURRICULUMTABLE9_SET(:I$SCHOOL_ID, :V$STAGE_ID, :V$JOURNAL_NAME, :V$SUBJECT_ID, :V$LESSONS_COUNT, :V$PTP_REALIZATION_PROCENT)
      INTO :V$OBJ_ID;
    END
  END

  VAL = CURRENT_TIMESTAMP;
  SORT_ORDER = 0;
  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE MONITORING_DO_FUNC4 (
    I$MONITORING_ID BIGINT)
RETURNS (
    VAL VARCHAR(4000),
    SORT_ORDER DOUBLE PRECISION)
AS
declare variable V$ROOMDEMAND_ID bigint;
declare variable V$ROOM_ID bigint;
BEGIN
    IF (I$MONITORING_ID IS NULL) THEN
    BEGIN
        -- Восстанавливаем ID СМИР, если не был передан
        SELECT FIRST 1 OBJ_ID
        FROM LINKS
        WHERE OBJ_TYPE_ID = 162 AND DATE_DEL IS NULL
        INTO :I$MONITORING_ID;
    END

    EXECUTE PROCEDURE EINSPECTOR_ROOMDEMAND_CLEAR(:I$MONITORING_ID, 325);
    EXECUTE PROCEDURE EINSPECTOR_ROOMDEMAND_CLEAR(:I$MONITORING_ID, 326);
    EXECUTE PROCEDURE EINSPECTOR_ROOMDEMAND_CLEAR(:I$MONITORING_ID, 328);
    EXECUTE PROCEDURE EINSPECTOR_ROOMDEMAND_CLEAR(:I$MONITORING_ID, 329);

    -- Общие помещения
    FOR SELECT ROOMDEMAND_ID FROM EINSPECTOR_ROOMDEMAND_INIT(325) INTO :V$ROOMDEMAND_ID DO
    BEGIN
        FOR SELECT ROOM_ID FROM EINSPECTOR_ROOMDEMAND_COINCIDE(:V$ROOMDEMAND_ID, 325) INTO :V$ROOM_ID DO
        BEGIN
            EXECUTE PROCEDURE EINSPECTOR_ROOMDEMAND_ADD(325, :I$MONITORING_ID, :V$ROOM_ID, :V$ROOMDEMAND_ID);
        END
    END

    -- Начальное образование
    FOR SELECT ROOMDEMAND_ID FROM EINSPECTOR_ROOMDEMAND_INIT(326) INTO :V$ROOMDEMAND_ID DO
    BEGIN
        FOR SELECT ROOM_ID FROM EINSPECTOR_ROOMDEMAND_COINCIDE(:V$ROOMDEMAND_ID, 326) INTO :V$ROOM_ID DO
        BEGIN
            EXECUTE PROCEDURE EINSPECTOR_ROOMDEMAND_ADD(326, :I$MONITORING_ID, :V$ROOM_ID, :V$ROOMDEMAND_ID);
        END
    END

    -- Основное общее  образование
    FOR SELECT ROOMDEMAND_ID FROM EINSPECTOR_ROOMDEMAND_INIT(328) INTO :V$ROOMDEMAND_ID DO
    BEGIN
        FOR SELECT ROOM_ID FROM EINSPECTOR_ROOMDEMAND_COINCIDE(:V$ROOMDEMAND_ID, 328) INTO :V$ROOM_ID DO
        BEGIN
            EXECUTE PROCEDURE EINSPECTOR_ROOMDEMAND_ADD(328, :I$MONITORING_ID, :V$ROOM_ID, :V$ROOMDEMAND_ID);
        END
    END

    -- Среднее образование
    FOR SELECT ROOMDEMAND_ID FROM EINSPECTOR_ROOMDEMAND_INIT(329) INTO :V$ROOMDEMAND_ID DO
    BEGIN
        FOR SELECT ROOM_ID FROM EINSPECTOR_ROOMDEMAND_COINCIDE(:V$ROOMDEMAND_ID, 329) INTO :V$ROOM_ID DO
        BEGIN
            EXECUTE PROCEDURE EINSPECTOR_ROOMDEMAND_ADD(329, :I$MONITORING_ID, :V$ROOM_ID,:V$ROOMDEMAND_ID);
        END
    END

    VAL = CURRENT_TIMESTAMP;
    SORT_ORDER = 0;
    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE MONITORING_DO_FUNC5 (
    I$MONITORING_ID BIGINT)
RETURNS (
    VAL VARCHAR(4000),
    SORT_ORDER DOUBLE PRECISION)
AS
declare variable V$EQDEMAND_ID bigint;
declare variable V$EQ_ID bigint;
BEGIN
    IF ((SELECT STATUS FROM IS_VPL) = 1) THEN
    BEGIN
        EXIT;
    END

    IF (I$MONITORING_ID IS NULL) THEN
    BEGIN
        SELECT FIRST 1
               OBJ_ID
        FROM LINKS

        WHERE OBJ_TYPE_ID = 162
        AND DATE_DEL IS NULL

        INTO :I$MONITORING_ID;
    END

    IF (NOT EXISTS(
        SELECT FIRST 1 1
        FROM LINKS L

        WHERE L.PARENT_ID = :I$MONITORING_ID
        AND L.OBJ_TYPE_ID IN (332,333,335,337)
        AND L.DATE_DEL IS NULL
    )) THEN
    BEGIN
        FOR
            SELECT EQDEMAND_ID
            FROM EINSPECTOR_EQDEMAND_INIT(332)
            INTO :V$EQDEMAND_ID
        DO
        BEGIN
            FOR
                SELECT EQ_ID
                FROM EINSPECTOR_EQDEMAND_COINCIDE(:V$EQDEMAND_ID)
                INTO :V$EQ_ID
            DO
            BEGIN
                EXECUTE PROCEDURE EINSPECTOR_EQDEMAND_ADD (
                    332,
                    :I$MONITORING_ID,
                    :V$EQ_ID,
                    :V$EQDEMAND_ID
                );
            END
        END

        FOR
            SELECT EQDEMAND_ID
            FROM EINSPECTOR_EQDEMAND_INIT(333)
            INTO :V$EQDEMAND_ID
        DO
        BEGIN
            FOR
                SELECT EQ_ID
                FROM EINSPECTOR_EQDEMAND_COINCIDE(:V$EQDEMAND_ID)
                INTO :V$EQ_ID
            DO
            BEGIN
                EXECUTE PROCEDURE EINSPECTOR_EQDEMAND_ADD (
                    333,
                    :I$MONITORING_ID,
                    :V$EQ_ID,
                    :V$EQDEMAND_ID
                );
            END
        END

        FOR
            SELECT EQDEMAND_ID
            FROM EINSPECTOR_EQDEMAND_INIT(335)
            INTO :V$EQDEMAND_ID
        DO
        BEGIN
            FOR
                SELECT EQ_ID
                FROM EINSPECTOR_EQDEMAND_COINCIDE(:V$EQDEMAND_ID)
                INTO :V$EQ_ID
            DO
            BEGIN
                EXECUTE PROCEDURE EINSPECTOR_EQDEMAND_ADD (
                    335,
                    :I$MONITORING_ID,
                    :V$EQ_ID,
                    :V$EQDEMAND_ID
                );
            END
        END

        FOR
            SELECT EQDEMAND_ID
            FROM EINSPECTOR_EQDEMAND_INIT(337)
            INTO :V$EQDEMAND_ID
        DO
        BEGIN
            FOR
                SELECT EQ_ID
                FROM EINSPECTOR_EQDEMAND_COINCIDE(:V$EQDEMAND_ID)
                INTO :V$EQ_ID
            DO
            BEGIN
                EXECUTE PROCEDURE EINSPECTOR_EQDEMAND_ADD (
                    337,
                    :I$MONITORING_ID,
                    :V$EQ_ID,
                    :V$EQDEMAND_ID
                );
            END
        END

        VAL = CURRENT_TIMESTAMP;
    END
    ELSE
    BEGIN
        SELECT MAX(L.DATE_INS)
        FROM LINKS L

        WHERE L.PARENT_ID = :I$MONITORING_ID
        AND L.OBJ_TYPE_ID IN (332,333,335,337)
        AND L.DATE_DEL IS NULL

        INTO :VAL;
    END

    EXECUTE PROCEDURE MONITORING_DO_FUNC_BOOKS(:I$MONITORING_ID);

    -- Временная затычка
    VAL = CURRENT_TIMESTAMP;

    SORT_ORDER = 0;
    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE MONITORING_DO_FUNC6 (
    I$MONITORING_ID BIGINT)
RETURNS (
    VAL VARCHAR(4000),
    SORT_ORDER DOUBLE PRECISION)
AS
declare variable V$OBJ340_ID bigint;
declare variable V$REF_ID bigint;
declare variable V$SCHOOL_ID bigint;
declare variable V$EMPLOYEE_ID bigint;
declare variable V$COUNT_COL1 integer;
declare variable V$COUNT_COL2 integer;
declare variable V$COUNT_COL3 integer;
declare variable V$COUNT_COL4 integer;
declare variable V$COUNT_COL5 integer;
declare variable V$BLOB_ID bigint;
declare variable V$LISTVAL_ID bigint;
declare variable V$VAL_DATE date;
declare variable V$CAPTION varchar(1000);
declare variable V$JT_DATE date;
declare variable V$CAPTION2 varchar(1000);
declare variable V$IS_TEACHER smallint;
declare variable V$VACANCY_TYPE bigint;
declare variable V$IS_MAIN_PD smallint;
declare variable V$START_DATE date;
declare variable V$JT_ID bigint;
declare variable V$TMP_VAL_DATE date;
declare variable V$TMP_VAL_DATE_MAX date;
declare variable V$LINK_ID bigint;
declare variable V$OU_LICENCE_TYPE char(1);
declare variable V$PREV_ID bigint;
declare variable N integer;
BEGIN
  SELECT STATUS FROM OU_LICENCE_TYPE INTO :V$OU_LICENCE_TYPE;

  --340: Требования к квалификации педагогических кадров (свод)
  --341: Требования к образованию педагогических кадров (список)
  --365: Требования к повышению квалификации педагогических кадров (список)
  -- тут два разных способа доступа к должности через LP13 и V69

  V$COUNT_COL1 = 0;
  V$COUNT_COL2 = 0;
  V$COUNT_COL3 = 0;
  V$COUNT_COL4 = 0;
  V$COUNT_COL5 = 0;
  IF(I$MONITORING_ID IS NULL) THEN
  BEGIN
    SELECT FIRST 1 OBJ_ID
    FROM LINKS
    WHERE OBJ_TYPE_ID = 162 AND DATE_DEL IS NULL
    INTO :I$MONITORING_ID;
  END

  SELECT FIRST 1 PARENT_ID
  FROM LINKS
  WHERE OBJ_ID = :I$MONITORING_ID AND PARENT_TYPE_ID = 2 AND DATE_DEL IS NULL
  INTO :V$SCHOOL_ID;

  UPDATE LINKS
  SET DATE_DEL = CURRENT_TIMESTAMP
  WHERE PARENT_ID = :I$MONITORING_ID AND OBJ_TYPE_ID IN (341, 365, 387, 388, 389) AND DATE_DEL IS NULL;

  SELECT FIRST 1 OBJ_ID
  FROM LINKS
  WHERE PARENT_ID = :I$MONITORING_ID AND OBJ_TYPE_ID = 340 AND DATE_DEL IS NULL
  INTO :V$OBJ340_ID;

  IF(V$OBJ340_ID IS NULL) THEN
  BEGIN
    SELECT OBJ_ID FROM OBJECT_ADD(:I$MONITORING_ID, 340) INTO :V$OBJ340_ID;
  END
  ELSE
  BEGIN
    -- Подчистка
    SELECT COUNT(*)
    FROM LINKS
    WHERE PARENT_ID = :I$MONITORING_ID AND OBJ_TYPE_ID = 340 AND DATE_DEL IS NULL
    INTO :N;

    IF(N > 1) THEN
    BEGIN
      UPDATE LINKS
      SET DATE_DEL = CURRENT_TIMESTAMP
      WHERE PARENT_ID = :I$MONITORING_ID AND OBJ_TYPE_ID = 340 AND DATE_DEL IS NULL AND OBJ_ID <> :V$OBJ340_ID;
    END
  END

  IF(V$OBJ340_ID IS NOT NULL) THEN
  BEGIN
    FOR
        SELECT L14.OBJ_ID, min(V73.VAL), max(V73.VAL)
        FROM LINKS L14 -- Сотрудник
        -- работающий (см. список 85)
        JOIN VALL V274 ON V274.OBJ_ID = L14.OBJ_ID AND V274.PARAM_ID = 274 AND V274.IS_DEL = 0 AND V274.LISTVAL_ID = 602
        -- Приём сотрудника на должность
        JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
        -- дата вступления в должность
        JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0
        -- дата увольнения с должности (должна быть пустой)
        LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
        JOIN VALR V69 ON V69.OBJ_ID = L15.OBJ_ID AND V69.PARAM_ID = 69 AND V69.IS_DEL = 0
        -- Берем только преподавателей
        JOIN VALL V64 ON V64.OBJ_ID = V69.VAL AND V64.PARAM_ID = 64 AND V64.IS_DEL = 0 AND V64.LISTVAL_ID in (98, 125, 129, 131) -- см. список 21
        -- Дофильтровываем, чтобы убрать преподавателей-организаторов ОБЖ
        JOIN VALL V58 ON V58.OBJ_ID = V69.VAL AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0 AND V58.LISTVAL_ID <> 121
        WHERE L14.PARENT_ID = :V$SCHOOL_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL AND V74.VAL IS NULL
        GROUP BY 1
        INTO :V$EMPLOYEE_ID, :V$START_DATE, :V$JT_DATE -- сотрудник + дата приема + дата вступления в должность
    DO
    BEGIN
      --11.10.2017 #1816
      --Ранее проверялось, что сотрудник назначен на должность после 01.09.2013.
      --Теперь нужно изменить алгоритм и при определении даты приёма на должность проверять предыдущие записи с такой же должностью,
      --где уже есть дата увольнения и в качестве "Основания увольнения" указана
      --"ст.74 ТК РФ - Изменение определенных сторонами условий трудового договора по причинам, связанным с изменением организационных или технологических условий труда".
      --Вычислять дату приема на должность нужно из самой первой записи по этой должности.
      IF(V$JT_DATE >= '2013-09-01') THEN
      BEGIN
        -- определяем действующие пед. должности сотрудника
        FOR
          SELECT V69.VAL
          FROM LINKS L15
          -- должность
          JOIN VALR V69 ON V69.OBJ_ID = L15.OBJ_ID AND V69.PARAM_ID = 69 AND V69.IS_DEL = 0
          JOIN VALL V64 ON V64.OBJ_ID = V69.VAL AND V64.PARAM_ID = 64 AND V64.IS_DEL = 0 AND V64.LISTVAL_ID in (98, 125, 129, 131) -- см. список 21
          -- дата увольнения с должности (должна быть пустой)
          LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
          WHERE L15.PARENT_ID = :V$EMPLOYEE_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL AND V74.VAL IS NULL
          INTO :V$JT_ID
        DO
        BEGIN
          -- дата приема сотрудника по этой должности с учетом изменении количества ставок
          SELECT MIN(V73.VAL)
          FROM LINKS L15
          -- должность
          JOIN VALR V69 ON V69.OBJ_ID = L15.OBJ_ID AND V69.PARAM_ID = 69 AND V69.IS_DEL = 0 AND V69.VAL = :V$JT_ID
          -- дата вступления в должность
          JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0
          -- основание увольнение ст.74
          LEFT JOIN VALR V458 ON V458.OBJ_ID = L15.OBJ_ID AND V458.PARAM_ID = 458 AND V458.IS_DEL = 0
          WHERE L15.PARENT_ID = :V$EMPLOYEE_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL AND (V458.VAL IS NULL or V458.VAL = 12757)
          INTO :V$TMP_VAL_DATE;

          IF((V$TMP_VAL_DATE_MAX IS NULL) OR ((V$TMP_VAL_DATE IS NOT NULL) AND (V$TMP_VAL_DATE > V$TMP_VAL_DATE_MAX))) THEN V$TMP_VAL_DATE_MAX = V$TMP_VAL_DATE;
        END
      END
      IF(V$JT_DATE > V$TMP_VAL_DATE_MAX) THEN V$JT_DATE = V$TMP_VAL_DATE_MAX;

      -- Заполняем таблицу Требования к образованию педагогических кадров (список)
      IF(
        -- 1. поле Профиль образования = Непедагогическое и
        not exists(
            SELECT FIRST 1 1
            FROM LINKS L33
            JOIN VALL V293 ON V293.OBJ_ID = L33.OBJ_ID AND V293.PARAM_ID = 293 AND V293.IS_DEL = 0 AND V293.LISTVAL_ID = 647 -- Педагогическое
            WHERE L33.PARENT_ID = :V$EMPLOYEE_ID AND L33.OBJ_TYPE_ID = 33 AND L33.DATE_DEL IS NULL
        )
        --2. табличное поле «Прохождение аттестации с целью установления уровня квалификации» - не заполнено или дата ранее, чем 5 лет с текущей даты, и
        AND not exists(
           SELECT FIRST 1 1
           FROM LINKS L34
           JOIN VALD V544 ON V544.OBJ_ID = L34.OBJ_ID AND V544.PARAM_ID = 544 AND V544.IS_DEL = 0 AND V544.VAL >= DATEADD(-5 YEAR to CURRENT_TIMESTAMP)
           WHERE L34.PARENT_ID = :V$EMPLOYEE_ID AND L34.OBJ_TYPE_ID = 34 AND L34.DATE_DEL IS NULL
        )
        -- 3. табличное поле «Прохождение аттестации с целью подтверждения соответствия занимаемой должности» - не заполнено
        -- или дата ранее, чем 5 лет с текущей даты, и
        AND not exists(
           SELECT FIRST 1 1
           FROM LINKS L156
           JOIN VALD V1232 ON V1232.OBJ_ID = L156.OBJ_ID AND V1232.PARAM_ID = 1232 AND V1232.IS_DEL = 0 AND V1232.VAL >= DATEADD(-5 YEAR to CURRENT_TIMESTAMP)
           WHERE L156.PARENT_ID = :V$EMPLOYEE_ID AND L156.OBJ_TYPE_ID = 156 AND L156.DATE_DEL IS NULL
        )
        -- 4.  отсутствует документ в таблице Профессиональная переподготовка и
        AND not exists(
           SELECT FIRST 1 1
           FROM LINKS L35
           WHERE L35.PARENT_ID = :V$EMPLOYEE_ID AND L35.OBJ_TYPE_ID = 35 AND L35.DATE_DEL IS NULL
        )
        -- 5. поле Дата вступления в должность позже 01.09.2013.
        AND (V$JT_DATE >= '2013-09-01')
        -- 6. Убираем педагогов дополнительного образования, не имеющих других должностей из подгрупп: учителя/преподаватели; воспитатели;
        -- мастера производственного обучения; прочие педагогические работники
        -- и образование высшее или среднее профессиональное
        AND ((V$OU_LICENCE_TYPE <> 'O') OR (SELECT DO_HIDE FROM MONITORING_TEACHER_HIDE_DOPS(:V$EMPLOYEE_ID, 1)) = 0)
      )
      THEN
      BEGIN
        -- счетчик нарушителей 1
        V$COUNT_COL1 = V$COUNT_COL1 + 1;

        V$REF_ID = NULL;
        SELECT FIRST 1 L341.OBJ_ID, L341.LINK_ID
        FROM LINKS L341
        -- сотрудник
        JOIN VALR V2702 ON V2702.OBJ_ID = L341.OBJ_ID AND V2702.PARAM_ID = 2702 AND V2702.IS_DEL = 0 AND V2702.VAL = :V$EMPLOYEE_ID
        WHERE L341.PARENT_ID = :I$MONITORING_ID AND L341.OBJ_TYPE_ID = 341
        INTO :V$REF_ID, :V$LINK_ID;

        IF(V$REF_ID IS NULL) THEN
        BEGIN
          SELECT OBJ_ID FROM OBJECT_ADD(:I$MONITORING_ID, 341) INTO :V$REF_ID;
          SELECT BLOB_ID FROM VAL_ADD(2702, :V$REF_ID, :V$EMPLOYEE_ID) INTO :V$BLOB_ID;
        END
        ELSE
        BEGIN
          UPDATE LINKS SET DATE_DEL = NULL WHERE LINK_ID = :V$LINK_ID AND DATE_DEL IS NOT NULL;
        END

        IF(V$REF_ID IS NOT NULL) THEN
        BEGIN
          SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$EMPLOYEE_ID) INTO :V$CAPTION;
          SELECT BLOB_ID FROM VAL_ADD(2666, :V$REF_ID, :V$CAPTION) INTO :V$BLOB_ID; -- ФИО

          FOR
              SELECT FIRST 1 C.CAPTION
              FROM LINKS L15
              -- дата вступления в должность
              JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0
              -- дата увольнения с должности (должна быть пустой)
              LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
              JOIN VALR V69 ON V69.OBJ_ID = L15.OBJ_ID AND V69.PARAM_ID = 69 AND V69.IS_DEL = 0
              JOIN VALL V64 ON V64.OBJ_ID = V69.VAL AND V64.PARAM_ID = 64 AND V64.IS_DEL = 0 AND V64.LISTVAL_ID in (98, 125, 129, 131)
              LEFT JOIN OBJECT_CAPTION_GET(V69.VAL) C ON 1 = 1
              WHERE L15.PARENT_ID = :V$EMPLOYEE_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL AND V74.VAL IS NULL
              ORDER BY V73.VAL DESC  -- последняя по хронологии должность
              INTO :V$CAPTION
          DO
          BEGIN
            -- Должность
            SELECT BLOB_ID FROM VAL_ADD(2667, :V$REF_ID, :V$CAPTION) INTO :V$BLOB_ID;
          END

          FOR
              SELECT FIRST 1 V284.LISTVAL_ID, V291.VAL
              FROM LINKS L33
              JOIN VALL V284 ON V284.OBJ_ID = L33.OBJ_ID AND V284.PARAM_ID = 284 AND V284.IS_DEL = 0
              JOIN VALS V291 ON V291.OBJ_ID = L33.OBJ_ID AND V291.PARAM_ID = 291 AND V291.IS_DEL = 0
              JOIN VALD V290 ON V290.OBJ_ID = L33.OBJ_ID AND V290.PARAM_ID = 290 AND V290.IS_DEL = 0
              WHERE L33.PARENT_ID = :V$EMPLOYEE_ID AND L33.OBJ_TYPE_ID = 33 AND L33.DATE_DEL IS NULL
              ORDER BY V290.VAL desc
              INTO :V$LISTVAL_ID, :V$CAPTION
          DO
          BEGIN
            -- Вид образования
            SELECT BLOB_ID FROM VAL_ADD(2668, :V$REF_ID, :V$LISTVAL_ID) INTO :V$BLOB_ID;
            -- Специальность
            SELECT BLOB_ID FROM VAL_ADD(2669, :V$REF_ID, :V$CAPTION) INTO :V$BLOB_ID;
          END
        END
      END

      -- Требования к повышению квалификации педагогических кадров (список)
      IF(
        -- 1. В табличном поле «Полученное образование» поле «Дата окончания» имеет значение раньше, чем текущий год минус 3 года и
        not exists(
          SELECT FIRST 1 1
          FROM LINKS L33
          JOIN VALD V290 ON V290.OBJ_ID = L33.OBJ_ID AND V290.PARAM_ID = 290 AND V290.IS_DEL = 0 AND V290.VAL >= DATEADD(-3 YEAR to CURRENT_TIMESTAMP)
          WHERE L33.PARENT_ID = :V$EMPLOYEE_ID AND L33.OBJ_TYPE_ID = 33 AND L33.DATE_DEL IS NULL
        )
        -- 2. В табличном поле «Профессиональная переподготовка» пусто или поле «Дата выдачи» имеет значение раньше, чем текущий год минус 3 года и
        AND not exists(
          SELECT FIRST 1 1
          FROM LINKS L35
          JOIN VALD V300 ON V300.OBJ_ID = L35.OBJ_ID AND V300.PARAM_ID = 300 AND V300.IS_DEL = 0 AND V300.VAL >= DATEADD(-3 YEAR to CURRENT_TIMESTAMP)
          WHERE L35.PARENT_ID = :V$EMPLOYEE_ID AND L35.OBJ_TYPE_ID = 35 AND L35.DATE_DEL IS NULL
        )
        -- 3. В табличном поле «Повышение квалификации» пусто, или поле «Дата выдачи» имеет значение раньше, чем текущий год минус 3 года.
        AND not exists(
          SELECT FIRST 1 1
          FROM LINKS L36
          JOIN VALD V310 ON V310.OBJ_ID = L36.OBJ_ID AND V310.PARAM_ID = 310 AND V310.IS_DEL = 0 AND V310.VAL >= DATEADD(-3 YEAR to CURRENT_TIMESTAMP)
          WHERE L36.PARENT_ID = :V$EMPLOYEE_ID AND L36.OBJ_TYPE_ID = 36 AND L36.DATE_DEL IS NULL
        )
        -- 4. Добавление по #1642 - требуем повышение квалификации только по истечении 3 лет работы
        AND (V$START_DATE < DATEADD(-3 YEAR to CURRENT_TIMESTAMP))
        -- 5. Убираем педагогов дополнительного образования, у которых нет других должностей
        AND ((V$OU_LICENCE_TYPE <> 'O') OR ((SELECT DO_HIDE FROM MONITORING_TEACHER_HIDE_DOPS(:V$EMPLOYEE_ID, 2)) = 0))
        -- 6. #1805 - убираем вернувшихся из длительного отпуска (имеется запись о длительном отпуске и с даты возвращения из отпуска прошло менее 3 лет)
        AND not exists(
            SELECT FIRST 1 1
            FROM LINKS L376
            JOIN VALL v2859 ON v2859.param_id = 2859 AND v2859.obj_id = l376.obj_id AND v2859.is_del = 0 AND v2859.LISTVAL_ID = 603
            JOIN VALD v2861 ON v2861.param_id = 2861 AND v2861.obj_id = l376.obj_id AND v2861.is_del = 0 AND v2861.VAL IS NOT NULL AND v2861.VAL > DATEADD(-3 YEAR to CURRENT_TIMESTAMP)
            WHERE L376.OBJ_TYPE_ID = 376 AND L376.PARENT_ID = :V$EMPLOYEE_ID AND L376.DATE_DEL IS NULL
         )
      ) THEN
      BEGIN
        -- счетчик нарушителей 2
        V$COUNT_COL2 = V$COUNT_COL2 + 1;

        V$REF_ID = NULL;
        SELECT FIRST 1 L365.OBJ_ID, L365.LINK_ID
        FROM LINKS L365
        -- сотрудник
        JOIN VALR V2776 ON V2776.OBJ_ID = L365.OBJ_ID AND V2776.PARAM_ID = 2776 AND V2776.IS_DEL = 0 AND V2776.VAL = :V$EMPLOYEE_ID
        WHERE L365.PARENT_ID = :I$MONITORING_ID AND L365.OBJ_TYPE_ID = 365
        INTO :V$REF_ID, :V$LINK_ID;

        IF(V$REF_ID IS NULL) THEN
        BEGIN
          SELECT OBJ_ID FROM OBJECT_ADD(:I$MONITORING_ID, 365) INTO :V$REF_ID;
          SELECT BLOB_ID FROM VAL_ADD(2776, :V$REF_ID, :V$EMPLOYEE_ID) INTO :V$BLOB_ID;
        END
        ELSE
        BEGIN
          UPDATE LINKS SET DATE_DEL = NULL WHERE LINK_ID = :V$LINK_ID;
        END

        IF(V$REF_ID IS NOT NULL) THEN
        BEGIN
          SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$EMPLOYEE_ID) INTO :V$CAPTION;
          SELECT BLOB_ID FROM VAL_ADD(2773, :V$REF_ID, :V$CAPTION) INTO :V$BLOB_ID; --ФИО

          -- Проходим по всем должностям данного сотрудника
          V$CAPTION = '';
          V$IS_MAIN_PD = 0;

          FOR
              SELECT C.CAPTION, V72.LISTVAL_ID, PD.SORT_ORDER
              FROM LINKS L15
             -- дата вступления в должность
              JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0
             -- дата увольнения с должности (должна быть пустой)
              LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
              -- тип должности
              JOIN VALL V72 ON V72.OBJ_ID = L15.OBJ_ID AND V72.PARAM_ID = 72 AND V72.IS_DEL = 0
              -- связь с должностью
              JOIN VALR V69 ON V69.OBJ_ID = L15.OBJ_ID AND V69.PARAM_ID = 69 AND V69.IS_DEL = 0
              JOIN VALL V64 ON V64.OBJ_ID = V69.VAL AND V64.PARAM_ID = 64 AND V64.IS_DEL = 0 AND V64.LISTVAL_ID in (98, 125, 129, 131)
              LEFT JOIN OBJECT_CAPTION_GET(V69.VAL) C ON 1 = 1
              LEFT JOIN DO_FUNC(V69.VAL, 400) PD ON 1 = 1
              WHERE L15.PARENT_ID = :V$EMPLOYEE_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL AND V74.VAL IS NULL
              -- Сначала пойдут основные должности, потом дополнительные
              ORDER BY 2
              INTO :V$CAPTION2, :V$VACANCY_TYPE, :V$IS_TEACHER
          DO
          BEGIN
            IF(V$VACANCY_TYPE = 934 AND V$IS_TEACHER = 2) THEN
            BEGIN
                -- Основная педагогическая должность
                V$IS_MAIN_PD = 1;
                V$CAPTION = V$CAPTION2;
            END
            IF(V$IS_MAIN_PD = 0 AND V$VACANCY_TYPE = 935) THEN
            BEGIN
                -- Основная должность не-педагогическая - складываем все дополнительные должности
                IF(V$CAPTION <> '') THEN V$CAPTION = V$CAPTION || ', ';
                V$CAPTION = SUBSTRING(V$CAPTION || V$CAPTION2 FROM 1 FOR 1000);
            END
          END

          -- Сохраняем в поле "должность"
          SELECT BLOB_ID FROM VAL_ADD(2774, :V$REF_ID, :V$CAPTION) INTO :V$BLOB_ID;

          FOR
              SELECT FIRST 1 V310.VAL
              FROM LINKS L36
              JOIN VALD V310 ON V310.OBJ_ID = L36.OBJ_ID AND V310.PARAM_ID = 310 AND V310.IS_DEL = 0
              WHERE L36.PARENT_ID = :V$EMPLOYEE_ID AND L36.OBJ_TYPE_ID = 36 AND L36.DATE_DEL IS NULL
              ORDER BY V310.VAL DESC
              INTO :V$VAL_DATE
          DO
          BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD(2775, :V$REF_ID, :V$VAL_DATE) -- Дата последнего повышения квалификации
            INTO :V$BLOB_ID;
          END
        END
      END

      -- Наличие курсов первой медицинской помощи
      IF(NOT EXISTS(
          SELECT FIRST 1 1
          FROM LINKS L36
          JOIN VALL V1024 ON V1024.OBJ_ID = L36.OBJ_ID AND V1024.PARAM_ID IN (1024, 2978) AND V1024.IS_DEL = 0 AND V1024.LISTVAL_ID = 12903
          WHERE L36.PARENT_ID = :V$EMPLOYEE_ID AND L36.OBJ_TYPE_ID IN (36, 395) AND L36.DATE_DEL IS NULL
      ))
      THEN
      BEGIN

          V$COUNT_COL3 = V$COUNT_COL3 + 1;

          V$REF_ID = NULL;
          SELECT FIRST 1 L387.OBJ_ID, L387.LINK_ID
          FROM LINKS L387
          -- сотрудник
          JOIN VALR V2940 ON V2940.OBJ_ID = L387.OBJ_ID AND V2940.PARAM_ID = 2940 AND V2940.IS_DEL = 0 AND V2940.VAL = :V$EMPLOYEE_ID
          WHERE L387.PARENT_ID = :I$MONITORING_ID AND L387.OBJ_TYPE_ID = 387
          INTO :V$REF_ID, :V$LINK_ID;

          IF(V$REF_ID IS NULL) THEN
          BEGIN
            SELECT OBJ_ID FROM OBJECT_ADD(:I$MONITORING_ID, 387) INTO :V$REF_ID;
            SELECT BLOB_ID FROM VAL_ADD(2940, :V$REF_ID, :V$EMPLOYEE_ID) INTO :V$BLOB_ID;
          END
          ELSE
          BEGIN
            UPDATE LINKS SET DATE_DEL = NULL WHERE LINK_ID = :V$LINK_ID;
          END

          IF(V$REF_ID IS NOT NULL) THEN
          BEGIN
            SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$EMPLOYEE_ID) INTO :V$CAPTION;
            SELECT BLOB_ID FROM VAL_ADD(2938, :V$REF_ID, :V$CAPTION) INTO :V$BLOB_ID; -- ФИО

            SELECT FIRST 1 C.CAPTION
            FROM LINKS L15                                                           
            -- дата вступления в должность
            JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0
            -- дата увольнения с должности (должна быть пустой)
            LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
            JOIN VALR V69 ON V69.OBJ_ID = L15.OBJ_ID AND V69.PARAM_ID = 69 AND V69.IS_DEL = 0
            JOIN VALL V64 ON V64.OBJ_ID = V69.VAL AND V64.PARAM_ID = 64 AND V64.IS_DEL = 0 AND V64.LISTVAL_ID in (98, 125, 129, 131)
            LEFT JOIN OBJECT_CAPTION_GET(V69.VAL) C ON 1 = 1
            WHERE L15.PARENT_ID = :V$EMPLOYEE_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL AND V74.VAL IS NULL
            ORDER BY V73.VAL DESC  -- последняя по хронологии должность
            INTO :V$CAPTION;

            SELECT BLOB_ID FROM VAL_ADD(2939, :V$REF_ID, :V$CAPTION) INTO :V$BLOB_ID; -- должность
          END

      END

      -- Аттестация - более 2 лет работы, не в длительном отпуске конкретных видов и 2 года после выхода из него
      V$PREV_ID = NULL;
      IF(V$START_DATE >= DATEADD(-2 YEAR TO CURRENT_DATE)) THEN
      FOR
          SELECT DISTINCT LP13.PARENT_ID, COALESCE(V72.LISTVAL_ID, 934), C.CAPTION
          FROM LINKS L15
          JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0 AND V73.VAL <= DATEADD(-2 YEAR to CURRENT_TIMESTAMP)
          -- дата увольнения с должности (должна быть пустой)
          LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
          JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
          -- Берем только преподавателей
          JOIN VALL V64 ON V64.OBJ_ID = LP13.PARENT_ID AND V64.PARAM_ID = 64 AND V64.IS_DEL = 0 AND V64.LISTVAL_ID in (98, 125, 129, 131) -- см. список 21
          -- Дофильтровываем, чтобы убрать преподавателей-организаторов ОБЖ
          JOIN VALL V58 ON V58.OBJ_ID = LP13.PARENT_ID AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0 AND V58.LISTVAL_ID <> 121
          -- Квалификационная категория = отсутствует или не задана
          LEFT JOIN VALL V1790 ON V1790.OBJ_ID = L15.OBJ_ID AND V1790.PARAM_ID = 1790 AND V1790.IS_DEL = 0
          -- Основная или дополнительная ?
          LEFT JOIN VALL V72 ON V72.OBJ_ID = L15.OBJ_ID AND V72.PARAM_ID = 72 AND V72.IS_DEL = 0
          -- Название должности
          LEFT JOIN OBJECT_CAPTION_GET(LP13.PARENT_ID) C ON 1 = 1
          WHERE L15.PARENT_ID = :V$EMPLOYEE_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL AND V74.VAL IS NULL
              -- нет ни категории в самой должности, ни записи о ее присвоении
               AND (V1790.LISTVAL_ID IS NULL OR V1790.LISTVAL_ID = 632)
               -- не в длительном отпуске по беременности или уходу за ребенком
               AND NOT EXISTS (
                   SELECT FIRST 1 1
                   FROM LINKS L376
                   JOIN VALD V2860 ON V2860.OBJ_ID = L376.OBJ_ID AND V2860.PARAM_ID = 2860 AND V2860.IS_DEL = 0 AND V2860.VAL <= CURRENT_DATE
                   LEFT JOIN VALD V2861 ON V2861.OBJ_ID = L376.OBJ_ID AND V2861.PARAM_ID = 2861 AND V2861.IS_DEL = 0
                   JOIN VALL V2859 ON V2859.OBJ_ID = L376.OBJ_ID AND V2859.PARAM_ID = 2859 AND V2859.IS_DEL = 0 AND V2859.LISTVAL_ID IN (604, 605, 606, 607, 609)
                   WHERE L376.PARENT_ID = L15.PARENT_ID AND L376.OBJ_TYPE_ID = 376 AND L376.DATE_DEL IS NULL AND (V2861.VAL IS NULL OR V2861.VAL > CURRENT_DATE)
               )
               -- и нет повышения аттестации по этой должности
               AND NOT EXISTS (
                   SELECT FIRST 1 1
                   FROM LINKS L156
                   JOIN VALD V1232 ON V1232.OBJ_ID = L156.OBJ_ID AND V1232.PARAM_ID = 1232 AND V1232.IS_DEL = 0
                   JOIN VALL V1233 ON V1233.OBJ_ID = L156.OBJ_ID AND V1233.PARAM_ID = 1233 AND V1233.IS_DEL = 0 AND V1233.LISTVAL_ID = 3033
                   JOIN VALL V2348 ON V2348.OBJ_ID = L156.OBJ_ID AND V2348.PARAM_ID = 2348 AND V2348.IS_DEL = 0 AND V2348.LISTVAL_ID = 11126 -- временно !!!
                   WHERE L156.PARENT_ID = L15.PARENT_ID AND L156.OBJ_TYPE_ID = 156 AND L156.DATE_DEL IS NULL
               )
          INTO :V$JT_ID, :V$LISTVAL_ID, :V$CAPTION2
      DO
      BEGIN

          IF(V$PREV_ID IS NULL) THEN V$COUNT_COL4 = V$COUNT_COL4 + 1;
          V$PREV_ID = 1;

          V$REF_ID = NULL;
          SELECT FIRST 1 L388.OBJ_ID, L388.LINK_ID
          FROM LINKS L388
          JOIN VALR V2944 ON V2944.OBJ_ID = L388.OBJ_ID AND V2944.PARAM_ID = 2944 AND V2944.IS_DEL = 0 AND V2944.VAL = :V$EMPLOYEE_ID
          JOIN VALR V2950 ON V2950.OBJ_ID = L388.OBJ_ID AND V2950.PARAM_ID = 2950 AND V2950.IS_DEL = 0 AND V2950.VAL = :V$JT_ID
          JOIN VALL V2943 ON V2943.OBJ_ID = L388.OBJ_ID AND V2943.PARAM_ID = 2943 AND V2943.IS_DEL = 0 AND V2943.LISTVAL_ID = :V$LISTVAL_ID
          WHERE L388.PARENT_ID = :I$MONITORING_ID AND L388.OBJ_TYPE_ID = 388
          INTO :V$REF_ID, :V$LINK_ID;

          IF(V$REF_ID IS NULL) THEN
          BEGIN
            SELECT OBJ_ID FROM OBJECT_ADD(:I$MONITORING_ID, 388) INTO :V$REF_ID;
            SELECT BLOB_ID FROM VAL_ADD(2944, :V$REF_ID, :V$EMPLOYEE_ID) INTO :V$BLOB_ID;
            SELECT BLOB_ID FROM VAL_ADD(2950, :V$REF_ID, :V$JT_ID) INTO :V$BLOB_ID;
            SELECT BLOB_ID FROM VAL_ADD(2943, :V$REF_ID, :V$LISTVAL_ID) INTO :V$BLOB_ID;
          END
          ELSE
          BEGIN
            UPDATE LINKS SET DATE_DEL = NULL WHERE LINK_ID = :V$LINK_ID;
          END

          IF(V$REF_ID IS NOT NULL) THEN
          BEGIN
            SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$EMPLOYEE_ID) INTO :V$CAPTION;
            SELECT BLOB_ID FROM VAL_ADD(2941, :V$REF_ID, :V$CAPTION) INTO :V$BLOB_ID; -- ФИО
            SELECT BLOB_ID FROM VAL_ADD(2942, :V$REF_ID, :V$CAPTION2) INTO :V$BLOB_ID; -- должность
          END

      END

      -- Повышение квалификации по профилю должности - по каждой из должностей
      V$PREV_ID = NULL;
      FOR
          SELECT DISTINCT LP13.PARENT_ID
          FROM LINKS L15
          JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0
          -- дата увольнения с должности (должна быть пустой)
          LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
          JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
          -- Берем только преподавателей
          JOIN VALL V64 ON V64.OBJ_ID = LP13.PARENT_ID AND V64.PARAM_ID = 64 AND V64.IS_DEL = 0 AND V64.LISTVAL_ID in (98, 125, 129, 131) -- см. список 21
          -- Дофильтровываем, чтобы убрать преподавателей-организаторов ОБЖ
          JOIN VALL V58 ON V58.OBJ_ID = LP13.PARENT_ID AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0 AND V58.LISTVAL_ID <> 121
          WHERE L15.PARENT_ID = :V$EMPLOYEE_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL AND V74.VAL IS NULL
              -- связка по направлению для повышения квалификации: предметное, педагогика, +ИКТ для преподавателя ИКТ и психология для педагога-психолога
              AND NOT EXISTS (
                  SELECT FIRST 1 1
                  FROM LINKS L36
                  JOIN VALD V310 ON V310.OBJ_ID = L36.OBJ_ID AND V310.PARAM_ID = 310 AND V310.IS_DEL = 0
                  JOIN VALL V1024 ON V1024.OBJ_ID = L36.OBJ_ID AND V1024.PARAM_ID = 1024 AND V1024.IS_DEL = 0 AND
                      (V1024.LISTVAL_ID IN (2812, 2814) OR (V1024.LISTVAL_ID = 2810 AND V58.LISTVAL_ID = 102) OR (V1024.LISTVAL_ID = 2811 AND V58.LISTVAL_ID = 145))
                  WHERE L36.PARENT_ID = :V$EMPLOYEE_ID AND L36.OBJ_TYPE_ID = 36 AND L36.DATE_DEL IS NULL
              )
          INTO :V$JT_ID
      DO
      BEGIN

          IF(V$PREV_ID IS NULL) THEN V$COUNT_COL5 = V$COUNT_COL5 + 1;
          V$PREV_ID = 1;

          V$REF_ID = NULL;
          SELECT FIRST 1 L389.OBJ_ID, L389.LINK_ID
          FROM LINKS L389
          JOIN VALR V2947 ON V2947.OBJ_ID = L389.OBJ_ID AND V2947.PARAM_ID = 2947 AND V2947.IS_DEL = 0 AND V2947.VAL = :V$EMPLOYEE_ID
          JOIN VALR V2949 ON V2949.OBJ_ID = L389.OBJ_ID AND V2949.PARAM_ID = 2949 AND V2949.IS_DEL = 0 AND V2949.VAL = :V$JT_ID
          WHERE L389.PARENT_ID = :I$MONITORING_ID AND L389.OBJ_TYPE_ID = 389
          INTO :V$REF_ID, :V$LINK_ID;

          IF(V$REF_ID IS NULL) THEN
          BEGIN
            SELECT OBJ_ID FROM OBJECT_ADD(:I$MONITORING_ID, 389) INTO :V$REF_ID;
            SELECT BLOB_ID FROM VAL_ADD(2947, :V$REF_ID, :V$EMPLOYEE_ID) INTO :V$BLOB_ID;
            SELECT BLOB_ID FROM VAL_ADD(2949, :V$REF_ID, :V$JT_ID) INTO :V$BLOB_ID;
          END
          ELSE
          BEGIN
            UPDATE LINKS SET DATE_DEL = NULL WHERE LINK_ID = :V$LINK_ID;
          END

          IF(V$REF_ID IS NOT NULL) THEN
          BEGIN
            SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$EMPLOYEE_ID) INTO :V$CAPTION;
            SELECT BLOB_ID FROM VAL_ADD(2945, :V$REF_ID, :V$CAPTION) INTO :V$BLOB_ID; -- ФИО
            SELECT BLOB_ID FROM VAL_ADD(2946, :V$REF_ID, :V$CAPTION2) INTO :V$BLOB_ID; -- должность
          END

      END

    END

    SELECT BLOB_ID FROM VAL_ADD(2664, :V$OBJ340_ID, :V$COUNT_COL1) INTO :V$BLOB_ID; -- без переподготовки
    SELECT BLOB_ID FROM VAL_ADD(2665, :V$OBJ340_ID, :V$COUNT_COL2) INTO :V$BLOB_ID; -- без повышения квалификации за период
    SELECT BLOB_ID FROM VAL_ADD(2936, :V$OBJ340_ID, :V$COUNT_COL3) INTO :V$BLOB_ID; -- нет курсов по первой помощи
    SELECT BLOB_ID FROM VAL_ADD(2937, :V$OBJ340_ID, :V$COUNT_COL4) INTO :V$BLOB_ID; -- не аттестованные
    SELECT BLOB_ID FROM VAL_ADD(2948, :V$OBJ340_ID, :V$COUNT_COL5) INTO :V$BLOB_ID; -- нет профильного повышения квалификации
  END

  VAL = CURRENT_TIMESTAMP;
  SORT_ORDER = 0;
  SUSPEND;
end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE MONITORING_DO_FUNC7 (
    I$MONITORING_ID BIGINT)
RETURNS (
    VAL VARCHAR(4000),
    SORT_ORDER DOUBLE PRECISION)
AS
declare variable V$OBJ342_ID bigint;
declare variable V$LINK_ID bigint;
declare variable V$SCHOOL_ID bigint;
declare variable V$CLASS_ID bigint;
declare variable V$STAGE_ID bigint;
declare variable V$COUNT_COL1 integer;
declare variable V$COUNT_COL2 integer;
declare variable V$COL1 integer;
declare variable V$COL2 integer;
declare variable V$BLOB_ID bigint;
declare variable V$LISTVAL_ID bigint;
declare variable V$CAPTION varchar(1000);
declare variable Y smallint;
declare variable DT date;
declare variable YEAR_VAL varchar(100);
declare variable YEAR_VAL_1 varchar(100);
declare variable YEAR_VAL_2 varchar(100);
declare variable YEAR_VAL_3 varchar(100);
declare variable YEAR_VAL_4 varchar(100);
declare variable YEAR_ID bigint;
declare variable YEAR_ID_1 bigint;
declare variable YEAR_ID_2 bigint;
declare variable YEAR_ID_3 bigint;
declare variable YEAR_ID_4 bigint;
declare variable END_DATE date;
declare variable END_DATE_1 date;
declare variable END_DATE_2 date;
declare variable END_DATE_3 date;
declare variable END_DATE_4 date;
declare variable VN1 integer;
declare variable VN2 integer;
declare variable VN3 integer;
declare variable VN4 integer;
declare variable T bigint;
BEGIN

    IF (I$MONITORING_ID IS NULL) THEN
    BEGIN
        -- ID объекта мониторинга
        SELECT FIRST 1 OBJ_ID FROM LINKS WHERE OBJ_TYPE_ID = 162 AND DATE_DEL IS NULL INTO :I$MONITORING_ID;
    END

    -- ID ОУ
    SELECT FIRST 1 PARENT_ID FROM LINKS WHERE OBJ_ID = :I$MONITORING_ID AND PARENT_TYPE_ID = 2 AND DATE_DEL IS NULL INTO :V$SCHOOL_ID;

    /*
    Y = EXTRACT(YEAR FROM CURRENT_DATE);
    DT = '1.09.' || Y;

    IF (CURRENT_DATE < DT) THEN
    BEGIN
        YEAR_VAL = (Y - 1) || '-' || Y;
        YEAR_VAL_1 = (Y - 2) || '-' || (Y - 1);
        YEAR_VAL_2 = (Y - 3) || '-' || (Y - 2);
        YEAR_VAL_3 = (Y - 4) || '-' || (Y - 3);
        YEAR_VAL_4 = (Y - 5) || '-' || (Y - 4);

        END_DATE = Y || '-05-31';
        END_DATE_1 = (Y - 1) || '-05-31';
        END_DATE_2 = (Y - 2) || '-05-31';
        END_DATE_3 = (Y - 3) || '-05-31';
        END_DATE_4 = (Y - 4) || '-05-31';
    END
    ELSE
    BEGIN
        YEAR_VAL = Y || '-' ||(Y + 1);
        YEAR_VAL_1 = (Y - 1) || '-' || Y;
        YEAR_VAL_2 = (Y - 2) || '-' || (Y - 1);
        YEAR_VAL_3 = (Y - 3) || '-' || (Y - 2);
        YEAR_VAL_4 = (Y - 4) || '-' || (Y - 3);

        END_DATE = (Y + 1) || '-05-31';
        END_DATE_1 = Y || '-05-31';
        END_DATE_2 = (Y - 1) || '-05-31';
        END_DATE_3 = (Y - 2) || '-05-31';
        END_DATE_4 = (Y - 3) || '-05-31';
    END

    SELECT FIRST 1 LV.LISTVAL_ID
    FROM LISTVALS LV
    JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
    WHERE LV.LIST_ID = 29 AND R.VAL LIKE :YEAR_VAL
    INTO :YEAR_ID;

    SELECT FIRST 1 LV.LISTVAL_ID
    FROM LISTVALS LV
    JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
    WHERE LV.LIST_ID = 29 AND R.VAL LIKE :YEAR_VAL_1
    INTO :YEAR_ID_1;

    SELECT FIRST 1 LV.LISTVAL_ID
    FROM LISTVALS LV
    JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
    WHERE LV.LIST_ID = 29 AND R.VAL LIKE :YEAR_VAL_2
    INTO :YEAR_ID_2;

    SELECT FIRST 1 LV.LISTVAL_ID
    FROM LISTVALS LV
    JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
    WHERE LV.LIST_ID = 29 AND R.VAL LIKE :YEAR_VAL_3
    INTO :YEAR_ID_3;

    SELECT FIRST 1 LV.LISTVAL_ID
    FROM LISTVALS LV
    JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
    WHERE LV.LIST_ID = 29 AND R.VAL LIKE :YEAR_VAL_4
    INTO :YEAR_ID_4;

    FOR
        SELECT V49.LISTVAL_ID, L8.OBJ_ID
        FROM LINKS L7
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
        JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0 AND V49.LISTVAL_ID IN (38,39,40,41,42,43,44,45,46,47)
        WHERE L7.PARENT_ID = :V$SCHOOL_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
        INTO :V$LISTVAL_ID, :V$STAGE_ID
    DO
    BEGIN
        V$COUNT_COL1 = 0;
        V$COUNT_COL2 = 0;
        V$OBJ342_ID = NULL;

        SELECT FIRST 1 L342.OBJ_ID
        FROM LINKS L342
        JOIN VALL V2692 ON V2692.OBJ_ID = L342.OBJ_ID AND V2692.PARAM_ID = 2692 AND V2692.IS_DEL = 0 AND V2692.LISTVAL_ID = :V$LISTVAL_ID
        WHERE L342.PARENT_ID = :I$MONITORING_ID AND L342.OBJ_TYPE_ID = 342 AND L342.DATE_DEL IS NULL
        INTO :V$OBJ342_ID;
    
        IF (V$OBJ342_ID IS NULL) THEN
        BEGIN
            SELECT OBJ_ID FROM OBJECT_ADD(:I$MONITORING_ID, 342) INTO :V$OBJ342_ID;
            SELECT BLOB_ID FROM VAL_ADD(2692, :V$OBJ342_ID, :V$LISTVAL_ID) INTO :V$BLOB_ID;
        END
        IF (V$OBJ342_ID IS NOT NULL) THEN
        BEGIN
            FOR
                SELECT L9.OBJ_ID
                FROM LINKS L9
                WHERE L9.PARENT_ID = :V$STAGE_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
                INTO :V$CLASS_ID
            DO
            BEGIN
                FOR
                    SELECT COL1, COL2
                    FROM EINSPECTOR_PUPIL_FINAL_MISSED(:I$MONITORING_ID, :V$CLASS_ID, :YEAR_ID, :END_DATE)
                    INTO :V$COL1, :V$COL2
                DO
                BEGIN
                    V$COUNT_COL1 = V$COUNT_COL1 + V$COL1;
                    V$COUNT_COL2 = V$COUNT_COL2 + V$COL2;
                END
                IF (V$LISTVAL_ID IN (39,40,42,43,44,45,47)) THEN
                BEGIN
                    FOR
                        SELECT COL1, COL2
                        FROM EINSPECTOR_PUPIL_FINAL_MISSED(:I$MONITORING_ID, :V$CLASS_ID, :YEAR_ID_1, :END_DATE_1)
                        INTO :V$COL1, :V$COL2
                    DO
                    BEGIN
                        V$COUNT_COL1 = V$COUNT_COL1 + V$COL1;
                        V$COUNT_COL2 = V$COUNT_COL2 + V$COL2;
                    END
                END
                IF (V$LISTVAL_ID IN (40,43,44,45)) THEN
                BEGIN
                    FOR
                        SELECT COL1, COL2
                        FROM EINSPECTOR_PUPIL_FINAL_MISSED(:I$MONITORING_ID, :V$CLASS_ID, :YEAR_ID_2, :END_DATE_2)
                        INTO :V$COL1, :V$COL2
                    DO
                    BEGIN
                        V$COUNT_COL1 = V$COUNT_COL1 + V$COL1;
                        V$COUNT_COL2 = V$COUNT_COL2 + V$COL2;
                    END
                END
                IF (V$LISTVAL_ID IN (44,45)) THEN
                BEGIN
                    FOR
                        SELECT COL1, COL2
                        FROM EINSPECTOR_PUPIL_FINAL_MISSED(:I$MONITORING_ID, :V$CLASS_ID, :YEAR_ID_3, :END_DATE_3)
                        INTO :V$COL1, :V$COL2
                    DO
                    BEGIN
                        V$COUNT_COL1 = V$COUNT_COL1 + V$COL1;
                        V$COUNT_COL2 = V$COUNT_COL2 + V$COL2;
                    END
                END
                IF (V$LISTVAL_ID IN (45)) THEN
                BEGIN
                    FOR
                        SELECT COL1, COL2
                        FROM EINSPECTOR_PUPIL_FINAL_MISSED(:I$MONITORING_ID, :V$CLASS_ID, :YEAR_ID_4, :END_DATE_4)
                        INTO :V$COL1, :V$COL2
                    DO
                    BEGIN
                        V$COUNT_COL1 = V$COUNT_COL1 + V$COL1;
                        V$COUNT_COL2 = V$COUNT_COL2 + V$COL2;
                    END
                END
            END

            SELECT BLOB_ID FROM VAL_ADD(2693, :V$OBJ342_ID, :V$COUNT_COL1) INTO :V$BLOB_ID;
            SELECT BLOB_ID FROM VAL_ADD(2694, :V$OBJ342_ID, :V$COUNT_COL2) INTO :V$BLOB_ID;
        END
    END

    FOR
        SELECT L343.LINK_ID
        FROM LINKS L343
        JOIN VALR V2697 ON V2697.OBJ_ID = L343.OBJ_ID AND V2697.PARAM_ID = 2697 AND V2697.IS_DEL = 0
        JOIN VALR V2700 ON V2700.OBJ_ID = L343.OBJ_ID AND V2700.PARAM_ID = 2700 AND V2700.IS_DEL = 0
        JOIN VALL V2698 ON V2698.OBJ_ID = L343.OBJ_ID AND V2698.PARAM_ID = 2698 AND V2698.IS_DEL = 0
        JOIN VALL V2699 ON V2699.OBJ_ID = L343.OBJ_ID AND V2699.PARAM_ID = 2699 AND V2699.IS_DEL = 0
        JOIN VALM M ON M.PUPIL_ID = V2700.VAL AND M.SUBJECT_ID = V2697.VAL AND M.YEAR_ID = V2698.LISTVAL_ID AND M.MARKTYPE_ID = V2699.LISTVAL_ID
            AND M.MARKVAL_ID IN (3016,3017,3018,3019,3021,11040,11041)
        WHERE L343.PARENT_ID = :I$MONITORING_ID AND L343.OBJ_TYPE_ID = 343 AND L343.DATE_DEL IS NULL
        INTO :V$LINK_ID
    DO
    BEGIN
        UPDATE LINKS SET DATE_DEL = CURRENT_TIMESTAMP WHERE LINK_ID = :V$LINK_ID AND DATE_DEL IS NULL;
    END
    */

    -- Пересчет итоговых цифр, передаваемых в объекте СМИР
    VN1 = NULL;
    VN2 = NULL;
    VN3 = NULL;
    VN4 = NULL;

    SELECT SUM(IIF((M.PAPER_DATE > M.ORDER_DATE OR M.PAPER_DATE < WD1.RESULT OR M.PAPER_DATE IS NULL) AND V78.LISTVAL_ID IN (817, 3274), 1, 0)),
      SUM(IIF((M.PAPER_DATE > M.ORDER_DATE OR M.PAPER_DATE < WD2.RESULT) AND V78.LISTVAL_ID NOT IN (817, 3274), 1, 0))
    FROM SMIR_MOVE_ENTER(:V$SCHOOL_ID) M
    JOIN LISTVALS LV ON LV.LISTVAL_ID = M.STAGE_INDEX
    JOIN VALL V78 ON V78.OBJ_ID = M.STUDENT_ID AND V78.PARAM_ID = 78 AND V78.IS_DEL = 0
    LEFT JOIN WORK_DIFF(M.ORDER_DATE, -7) WD1 ON 1 = 1
    LEFT JOIN WORK_DIFF(M.ORDER_DATE, -3) WD2 ON 1 = 1
    INTO :VN1, :VN2;

    SELECT SUM(IIF(M.ORDER_DATE IS NULL AND M.PAPER_DATE < WD1.RESULT, 1, 0)),
      SUM(IIF(M.PAPER_DATE > M.ORDER_DATE OR M.PAPER_DATE < WD2.RESULT, 1, 0))
    FROM SMIR_MOVE_LEAVE(:V$SCHOOL_ID) M
    LEFT JOIN WORK_DIFF(CURRENT_DATE, -3) WD1 ON 1 = 1
    LEFT JOIN WORK_DIFF(M.ORDER_DATE, -3) WD2 ON 1 = 1
    INTO :VN3, :VN4;

    IF(VN1 IS NULL) THEN VN1 = 0;
    IF(VN2 IS NULL) THEN VN2 = 0;
    IF(VN3 IS NULL) THEN VN3 = 0;
    IF(VN4 IS NULL) THEN VN4 = 0;

    SELECT BLOB_ID FROM VAL_ADD(3002, :I$MONITORING_ID, :VN1) INTO :T;
    SELECT BLOB_ID FROM VAL_ADD(3003, :I$MONITORING_ID, :VN2) INTO :T;
    SELECT BLOB_ID FROM VAL_ADD(3004, :I$MONITORING_ID, :VN3) INTO :T;
    SELECT BLOB_ID FROM VAL_ADD(3005, :I$MONITORING_ID, :VN4) INTO :T;

    VAL = CURRENT_TIMESTAMP;
    SORT_ORDER = 0;
    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE MONITORING_DO_FUNC8 (
    I$MONITORING_ID BIGINT)
RETURNS (
    VAL VARCHAR(4000),
    SORT_ORDER DOUBLE PRECISION)
AS
declare variable V$SCHOOL_ID bigint;
declare variable V$CLASS_ID bigint;
declare variable V$STAGE_ID bigint;
declare variable V$COUNT_COL1 bigint;
declare variable V$COUNT_COL2 bigint;
declare variable V$LINK_ID bigint;
declare variable V$BLOB_ID bigint;
declare variable V$YEAR_ID bigint;
begin

    IF (I$MONITORING_ID IS NULL) THEN
    BEGIN
        -- ID объекта мониторинга
        SELECT FIRST 1 OBJ_ID FROM LINKS WHERE OBJ_TYPE_ID = 162 AND DATE_DEL IS NULL INTO :I$MONITORING_ID;
    END

    -- ID ОУ
    SELECT FIRST 1 LP2.PARENT_ID, V1236.LISTVAL_ID
    FROM LINKS LP2
    JOIN VALL V1236 ON V1236.OBJ_ID = LP2.PARENT_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
    WHERE LP2.OBJ_ID = :I$MONITORING_ID AND LP2.PARENT_TYPE_ID = 2 AND LP2.DATE_DEL IS NULL
    INTO :V$SCHOOL_ID, :V$YEAR_ID;

    UPDATE LINKS SET DATE_DEL = CURRENT_TIMESTAMP WHERE PARENT_ID = :I$MONITORING_ID AND OBJ_TYPE_ID = 421 AND DATE_DEL IS NULL;

    FOR
      SELECT L9.OBJ_ID, V49.LISTVAL_ID
      FROM LINKS L7
      JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
      JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
      WHERE L7.PARENT_ID = :V$SCHOOL_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
      INTO :V$CLASS_ID, :V$STAGE_ID
    DO
    BEGIN
      SELECT COUNT(*)
      FROM LINKS L10
      LEFT JOIN DO_FUNC(L10.OBJ_ID, NULL, 1) A ON 1 = 1
      WHERE L10.PARENT_ID = :V$CLASS_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL AND A.SORT_ORDER >= 5 AND A.SORT_ORDER <= 18
      INTO :V$COUNT_COL1;

      SELECT COUNT(*)
      FROM LINKS L10
      LEFT JOIN DO_FUNC(L10.OBJ_ID, NULL, 1) A ON 1 = 1
      WHERE L10.PARENT_ID = :V$CLASS_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL AND A.SORT_ORDER >= 5 AND A.SORT_ORDER <= 18
        AND EXISTS (
          -- Числится в группе ДО
          SELECT FIRST 1 1
          FROM LINKS LPG
          JOIN LINKS LPF ON LPF.OBJ_ID = LPG.PARENT_ID AND LPF.PARENT_TYPE_ID = 86 AND LPF.DATE_DEL IS NULL
          JOIN VALL V1579 ON V1579.OBJ_ID = LPF.PARENT_ID AND V1579.PARAM_ID = 1579 AND V1579.IS_DEL = 0 AND V1579.LISTVAL_ID IN (3315, 3316)
          WHERE LPG.OBJ_ID = L10.OBJ_ID AND LPG.PARENT_TYPE_ID = 46 AND LPG.DATE_DEL IS NULL
          -- Внесена запись о внешнем освоении
          UNION
          SELECT FIRST 1 1
          FROM LINKS L297
          JOIN VALL V2394 ON V2394.OBJ_ID = L297.OBJ_ID AND V2394.PARAM_ID = 2394 AND V2394.IS_DEL = 0 AND V2394.LISTVAL_ID = :V$YEAR_ID
          WHERE L297.PARENT_ID = L10.OBJ_ID AND L297.OBJ_TYPE_ID = 297 AND L297.DATE_DEL IS NULL
        )
      INTO :V$COUNT_COL2;

      V$LINK_ID = NULL;
      SELECT FIRST 1 L421.OBJ_ID
      FROM LINKS L421
      JOIN VALR V3100 ON V3100.OBJ_ID = L421.OBJ_ID AND V3100.PARAM_ID = 3100 AND V3100.IS_DEL = 0 AND V3100.VAL = :V$CLASS_ID
      WHERE L421.PARENT_ID = :I$MONITORING_ID AND L421.OBJ_TYPE_ID = 421
      INTO :V$LINK_ID;

      IF(V$LINK_ID IS NULL) THEN
      BEGIN
        SELECT OBJ_ID FROM OBJECT_ADD(:I$MONITORING_ID, 421) INTO :V$LINK_ID;
        SELECT BLOB_ID FROM VAL_ADD(3100, :V$LINK_ID, :V$CLASS_ID) INTO :V$BLOB_ID;
      END
      ELSE
      BEGIN
        UPDATE LINKS SET DATE_DEL = NULL WHERE OBJ_ID = :V$LINK_ID;
      END

      SELECT BLOB_ID FROM VAL_ADD(3104, :V$LINK_ID, :V$STAGE_ID) INTO :V$BLOB_ID;
      SELECT BLOB_ID FROM VAL_ADD(3101, :V$LINK_ID, :V$COUNT_COL1) INTO :V$BLOB_ID;
      SELECT BLOB_ID FROM VAL_ADD(3102, :V$LINK_ID, :V$COUNT_COL2) INTO :V$BLOB_ID;
    END

    VAL = CURRENT_TIMESTAMP;
    SORT_ORDER = 0;
    SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE MONITORING_DO_FUNC_BOOKS (
    I$MONITORING_ID BIGINT)
AS
DECLARE VARIABLE V$PARALLEL_LV BIGINT;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$PUPIL_CNT INTEGER;
DECLARE VARIABLE V$SCHOOL_ID BIGINT;
DECLARE VARIABLE V$PLAN_ID BIGINT;
DECLARE VARIABLE V$BOOK_CNT INTEGER;
DECLARE VARIABLE V$BOOK_CODE VARCHAR(50);
DECLARE VARIABLE V$BOOK_USAGE INTEGER;
DECLARE VARIABLE V$SUBJECT_ID BIGINT;
DECLARE VARIABLE V$STAGE_ID BIGINT;
DECLARE VARIABLE V$LOAD_H INTEGER;
DECLARE VARIABLE V$BOOK_ID BIGINT;
DECLARE VARIABLE V$HAS_BOOKS INTEGER;
DECLARE VARIABLE V$BOOK_SUBJ_ID BIGINT;
DECLARE VARIABLE V$BOOK_YEAR INTEGER;
DECLARE VARIABLE V$CMP_ID BIGINT;
DECLARE VARIABLE V$GPD_COUNT INTEGER;
DECLARE VARIABLE V$COMPONENT_ID BIGINT;
DECLARE VARIABLE V$COMPONENT_TYPE INTEGER;
DECLARE VARIABLE V$IS_COLLEGE SMALLINT;
DECLARE VARIABLE V$LOAD_ID BIGINT;
DECLARE VARIABLE V$IS_DUBL SMALLINT;
DECLARE VARIABLE V$REPLACE_SUBJ BIGINT;
DECLARE VARIABLE V$HAS_FISCULT SMALLINT;
DECLARE VARIABLE V$HAS_TECH SMALLINT;
DECLARE VARIABLE V$PREV_PLAN_ID BIGINT;
DECLARE VARIABLE V$PREV_PAR_LV BIGINT;
DECLARE VARIABLE V$SUBJ_NAME VARCHAR(1000);
DECLARE VARIABLE V$MISS_COUNT INTEGER;
DECLARE VARIABLE V$PREV INTEGER;
DECLARE VARIABLE V$VAL INTEGER;
DECLARE VARIABLE V$CNT INTEGER;
DECLARE VARIABLE V$V1 INTEGER;
DECLARE VARIABLE V$V2 INTEGER;
DECLARE VARIABLE V$V3 INTEGER;
DECLARE VARIABLE V$V4 INTEGER;
DECLARE VARIABLE V$V5 INTEGER;
DECLARE VARIABLE V$LIB2 SMALLINT;
BEGIN

    -- На входе - идентификатор родительского объекта данных мониторинга. Получаем ID ОООД
    SELECT L.PARENT_ID
    FROM LINKS L
    WHERE L.OBJ_ID = :I$MONITORING_ID AND L.PARENT_TYPE_ID = 2 AND L.DATE_DEL IS NULL
    INTO :V$SCHOOL_ID;

    -- Новый режим работы через библиограф.
    -- Обеспеченность через данные МТР отключена по указанию Невзоровой 16.04.2025. Всегда брать обеспеченность учебниками из библиографа
    V$LIB2 = 1;
    SELECT FIRST 1 1
    FROM LIB2_BOOKS B
    WHERE B.DATE_DEL IS NULL AND B.OBJ_TYPE = 18712
    INTO :V$LIB2;

    V$PREV_PLAN_ID = NULL;
    V$PREV_PAR_LV = NULL;

    /* 1. Полный отчет по учебникам - сюда пойдут только учебники из ФПУ */
    /* 1.1. Обновление и добавление новых пунктов */
    FOR
        -- LOAD_ID для школ null, для колледжей заполнено
        SELECT DISTINCT L400.OBJ_ID, V381.LISTVAL_ID, L54.OBJ_ID, PS.SUBJECT_ID, C.CAPTION, L.OBJ_ID, PS.SRC_SUBJECT_ID
        FROM LINKS L400
        -- Убираем планы ВД
        LEFT JOIN VALL VD ON VD.OBJ_ID = L400.OBJ_ID and VD.PARAM_ID = 3022 AND VD.IS_DEL = 0
        -- Убираем индивидуальные планы
        LEFT JOIN VALL VI ON VI.OBJ_ID = L400.OBJ_ID and VI.PARAM_ID = 3016 AND VI.IS_DEL = 0
        -- Только неадаптированные программы
        LEFT JOIN VALL V2379 ON V2379.OBJ_ID = L400.PARENT_ID AND V2379.PARAM_ID = 2379 AND V2379.IS_DEL = 0
        -- Вверх - Учебный план и программа
        JOIN LINKS L57_69 ON L57_69.OBJ_ID = L400.PARENT_ID AND L57_69.PARENT_TYPE_ID = 69 AND L57_69.DATE_DEL IS NULL
        JOIN LINKS L69_2 ON L69_2.OBJ_ID = L57_69.PARENT_ID AND L69_2.PARENT_ID = :V$SCHOOL_ID AND L69_2.DATE_DEL IS NULL
        -- Фильтр по ОП только общего образования
        LEFT JOIN VALL V2450 ON V2450.OBJ_ID = L69_2.OBJ_ID AND V2450.PARAM_ID = 2450 AND V2450.IS_DEL = 0
        -- Вниз - Этапы
        JOIN LINKS L54 ON L54.PARENT_ID = L400.OBJ_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
        JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
        -- Предметы и нагрузки
        JOIN PLAN_SUBJECTS PS ON PS.DATE_DEL IS NULL AND PS.PLAN_ID = L400.OBJ_ID AND PS.ROW_TYPE = 10
        JOIN PLAN_SUBJECTS PSP ON PSP.OBJ_ID = PS.PARENT_ID AND PSP.FIELD_ID IN (13303)
        -- L.LOAD_HOURS ! но он бывает пустой
        JOIN PLAN_LOADS L ON L.DATE_DEL IS NULL AND L.SUBJECT_ID = PS.OBJ_ID AND L.STAGE_ID = L54.OBJ_ID AND (L.LOAD_HOURS_S1 > 0 OR L.LOAD_HOURS_S2 > 0)
        LEFT JOIN VALL V2816 ON V2816.OBJ_ID = PS.SUBJECT_ID AND V2816.PARAM_ID = 2816 AND V2816.IS_DEL = 0
        LEFT JOIN OBJECT_CAPTION_GET(PS.SUBJECT_ID) C ON 1 = 1
        -- Основная выборка по УП
        WHERE L400.OBJ_TYPE_ID = 400 AND L400.PARENT_TYPE_ID = 57 AND L400.DATE_DEL IS NULL
            AND (VD.LISTVAL_ID IS NULL OR VD.LISTVAL_ID = 3) AND (VI.LISTVAL_ID IS NULL OR VI.LISTVAL_ID = 5465)
            AND (V2379.LISTVAL_ID IS NULL OR V2379.LISTVAL_ID = 11187) AND (V2450.LISTVAL_ID IS NULL OR V2450.LISTVAL_ID = 11385 OR V2450.LISTVAL_ID = 11387)
            AND (V2816.LISTVAL_ID = 3 OR V2816.LISTVAL_ID IS NULL)
        ORDER BY 2, 1, 3, 4
        INTO :V$PLAN_ID, :V$PARALLEL_LV, :V$STAGE_ID, :V$SUBJECT_ID, :V$SUBJ_NAME, :V$LOAD_ID, :V$REPLACE_SUBJ
    DO
    BEGIN

        V$LOAD_H = 1;

        -- При переходе в следующий блок сбрасываем проверки по физкультуре и технологии
        IF(V$PREV_PLAN_ID IS NULL OR V$PREV_PLAN_ID <> V$PLAN_ID OR V$PREV_PAR_LV <> V$PARALLEL_LV) THEN
        BEGIN
          V$HAS_FISCULT = 0;
          V$HAS_TECH = 0;
        END
        V$PREV_PLAN_ID = V$PLAN_ID;
        V$PREV_PAR_LV = V$PARALLEL_LV;

        -- Убираем ГПД ? зачем ?
        SELECT COUNT(*)
        FROM LINKS L54
        JOIN VALL G ON G.OBJ_ID = L54.OBJ_ID AND G.PARAM_ID = 369 AND G.IS_DEL = 0 AND G.LISTVAL_ID = 1246
        WHERE L54.PARENT_ID = :V$STAGE_ID AND L54.OBJ_TYPE_ID = 46 AND L54.DATE_DEL IS NULL
        INTO :V$GPD_COUNT;

        -- Количество учеников по данному УП в параллели - только через группы. Может быть нулевое !
        V$PUPIL_CNT = 0;

        SELECT COUNT(L10.OBJ_ID)
        FROM LINKS L256
        JOIN LINKS L10 ON L10.PARENT_ID = L256.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        WHERE L256.PARENT_ID = :V$STAGE_ID AND L256.OBJ_TYPE_ID IN (46, 256) AND L256.DATE_DEL IS NULL
        INTO :V$PUPIL_CNT;

        -- Если замена не прописана - анализируем текстовое название предмета
        IF(V$REPLACE_SUBJ IS NULL) THEN
        BEGIN
          IF(SUBSTRING(V$SUBJ_NAME FROM 1 FOR 19) = 'Физическая культура') THEN V$REPLACE_SUBJ = 205;
          ELSE IF(SUBSTRING(V$SUBJ_NAME FROM 1 FOR 10) = 'Технология') THEN V$REPLACE_SUBJ = 200;
        END

        IF(V$SUBJECT_ID = 205) THEN
        BEGIN
          -- Если предмет сама физкультура - оставим только ее (порядок сортировки обеспечит что она первая)
          V$HAS_FISCULT = 1;
        END
        ELSE IF(V$SUBJECT_ID = 200) THEN
        BEGIN
          -- Если предмет сама технология - оставим только ее (порядок сортировки обеспечит что она первая)
          V$HAS_TECH = 1;
        END
        ELSE IF(V$REPLACE_SUBJ IS NOT NULL) THEN
        BEGIN
          -- Если прописана физкультура/технология в качестве замены, разрешаем первый экземпляр, остальные пропускаем
          IF(V$REPLACE_SUBJ = 205) THEN
          BEGIN
            IF(V$HAS_FISCULT > 0) THEN V$LOAD_H = 0;
            V$HAS_FISCULT = 1;
          END
          ELSE IF(V$REPLACE_SUBJ = 200) THEN
          BEGIN
            IF(V$HAS_TECH > 0) THEN V$LOAD_H = 0;
            V$HAS_TECH = 1;
          END
        END

        -- Получаем список учебников по предмету
        V$HAS_BOOKS = 0;
        FOR
            SELECT VS.VAL, R.RES_ID, VC.VAL, VN.VAL, CAST(VY.VAL AS INTEGER), NULL, R.QTY
            FROM PLAN_RESOURCES R
            JOIN LINKS LP105 ON LP105.PARENT_TYPE_ID = 105 and LP105.OBJ_ID = R.RES_ID and LP105.DATE_DEL IS NULL
            JOIN VALS VC ON VC.OBJ_ID = R.RES_ID AND VC.PARAM_ID = 2655 AND VC.IS_DEL = 0
            JOIN VALI VN ON VN.OBJ_ID = R.RES_ID AND VN.PARAM_ID = 648 AND VN.IS_DEL = 0
            JOIN VALS VY ON VY.OBJ_ID = R.RES_ID AND VY.PARAM_ID = 650 AND VY.IS_DEL = 0
            -- Код предмета, заданный для учебника. Связку по удалению убрали, чтобы не портить ошибочно добавленные линки
            JOIN VALR VS ON VS.OBJ_ID = R.RES_ID AND VS.PARAM_ID = 654 AND VS.IS_DEL = 0
            JOIN LIB_FPU_CODES C ON C.DATE_DEL IS NULL AND C.BOOKCODE = VC.SVAL
            LEFT JOIN LIB_FPU_CODES C2 ON C2.DATE_DEL IS NULL AND C2.BOOKCODE = C.BOOKCODE AND C2.DATE_ADD > C.DATE_ADD
            WHERE :V$LIB2 = 0 AND R.DATE_DEL IS NULL AND R.LOAD_ID = :V$LOAD_ID AND :V$GPD_COUNT = 0 AND :V$LOAD_H > 0 AND C2.BOOK_ID IS NULL
            -- Новая схема через библиограф, выдача на классы
            -- код из FPU_CODES не нужен, он уже прокэширован в BOOKS
            UNION
            SELECT COALESCE(:V$SUBJECT_ID, :V$REPLACE_SUBJ), U.BOOK_ID, B.FPU_CODE, B.N_AVAIL, B.PUB_YEAR, NULL, SUM(U.QUANTITY)
            FROM LIB2_USAGE U
            JOIN LIB2_BOOKS B ON B.OBJ_ID = U.BOOK_ID
            WHERE :V$LIB2 = 1 AND U.DATE_DEL IS NULL AND U.RETURN_DATE IS NULL AND U.LOSS_DATE IS NULL AND U.REF_TYPE_ID = 9
              AND U.LOAD_ID = :V$LOAD_ID AND :V$GPD_COUNT = 0 AND :V$LOAD_H > 0

            GROUP BY 1, 2, 3, 4, 5, 6
            INTO :V$BOOK_SUBJ_ID, :V$BOOK_ID, :V$BOOK_CODE, :V$BOOK_CNT, :V$BOOK_YEAR, :V$COMPONENT_TYPE, :V$BOOK_USAGE
        DO
        BEGIN
          -- Если учебник был назначен по региональному компоненту, при этом есть такой же предмет по федеральному - игнорируем такой учебник
          -- Для колледжей не проверяется
          V$IS_DUBL = 0;
          IF(V$BOOK_SUBJ_ID = V$SUBJECT_ID AND V$PUPIL_CNT > 0 AND V$IS_DUBL = 0) THEN
          BEGIN
            V$HAS_BOOKS = 1;
            EXECUTE PROCEDURE MONITORING_BOOK_ADD(:I$MONITORING_ID, :V$PARALLEL_LV, :V$PLAN_ID, :V$SUBJECT_ID, :V$BOOK_CODE, :V$PUPIL_CNT, :V$BOOK_USAGE, :V$BOOK_YEAR)
              RETURNING_VALUES (:V$OBJ_ID);
            INSERT INTO FPU_BOOKS_TEMP VALUES (:V$OBJ_ID);
          END
        END

        /* Если учебников нет - добавляем пустую строку */
        IF(V$HAS_BOOKS = 0 AND V$PUPIL_CNT > 0 AND V$GPD_COUNT = 0 AND V$LOAD_H > 0) THEN
        BEGIN
          EXECUTE PROCEDURE MONITORING_BOOK_ADD(:I$MONITORING_ID, :V$PARALLEL_LV, :V$PLAN_ID, :V$SUBJECT_ID, '', :V$PUPIL_CNT, 0, NULL)
            RETURNING_VALUES (:V$OBJ_ID);
          INSERT INTO FPU_BOOKS_TEMP VALUES (:V$OBJ_ID);
        END

    END

    -- 1.2. Удаляем устаревшие объекты
    FOR
      SELECT L.OBJ_ID, T.OBJ_ID
      FROM LINKS L
      LEFT JOIN FPU_BOOKS_TEMP T ON T.OBJ_ID = L.OBJ_ID
      WHERE L.PARENT_ID = :I$MONITORING_ID AND L.OBJ_TYPE_ID = 344 AND L.DATE_DEL IS NULL
      INTO :V$OBJ_ID, :V$CMP_ID
    DO
    BEGIN
      IF(V$CMP_ID IS NULL) THEN EXECUTE PROCEDURE OBJECT_DEL(:I$MONITORING_ID, :V$OBJ_ID) RETURNING_VALUES (V$HAS_BOOKS);
    END

    /* Чистим буферную таблицу */
    DELETE FROM FPU_BOOKS_TEMP WHERE 1 = 1;

    /* 2. Сводный отчет по учебникам - только по актуальным этапам обучения */
    FOR
        SELECT DISTINCT V49.LISTVAL_ID
        FROM LINKS LP2
        JOIN LINKS L7 ON L7.PARENT_ID = LP2.PARENT_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
        JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
        WHERE LP2.OBJ_ID = :I$MONITORING_ID AND LP2.PARENT_TYPE_ID = 2 AND LP2.DATE_DEL IS NULL
        ORDER BY 1
        INTO :V$PARALLEL_LV
    DO
    BEGIN

        -- Если такой объект в статистике уже есть - пишем в него, если нет - добавляем
        V$OBJ_ID = NULL;

        SELECT FIRST 1 L.OBJ_ID
        FROM LINKS L
        JOIN VALL VL ON VL.OBJ_ID = L.OBJ_ID AND VL.PARAM_ID = 2684 AND VL.IS_DEL = 0 AND VL.LISTVAL_ID = :V$PARALLEL_LV
        WHERE L.PARENT_ID = :I$MONITORING_ID AND L.OBJ_TYPE_ID = 345 AND L.DATE_DEL IS NULL
        INTO :V$OBJ_ID;

        IF(V$OBJ_ID IS NULL) THEN
        BEGIN
            SELECT OBJ_ID FROM OBJECT_ADD(:I$MONITORING_ID, 345) INTO :V$OBJ_ID;

            UPDATE OR INSERT INTO VALL (OBJ_ID, PARAM_ID, LISTVAL_ID, IS_DEL)
            VALUES (:V$OBJ_ID, 2684, :V$PARALLEL_LV, 0);
        END

        /* Количество учащихся в параллели - суммой по всем УП */
        V$PUPIL_CNT = NULL;

        SELECT COUNT(DISTINCT L10.OBJ_ID)
        -- Основная выборка по образовательным программам
        FROM LINKS L69
        -- Образовательная программа
        JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
        -- Учебный план
        JOIN LINKS L400 ON L400.PARENT_ID = L57.OBJ_ID AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL
        -- Убираем планы ВД
        LEFT JOIN VALL VD ON VD.OBJ_ID = L400.OBJ_ID and VD.PARAM_ID = 3022 AND VD.IS_DEL = 0
        -- Убираем индивидуальные планы
        LEFT JOIN VALL VI ON VI.OBJ_ID = L400.OBJ_ID and VI.PARAM_ID = 3016 AND VI.IS_DEL = 0
        -- Только неадаптированные программы
        LEFT JOIN VALL V2379 ON V2379.OBJ_ID = L57.OBJ_ID AND V2379.PARAM_ID = 2379 AND V2379.IS_DEL = 0
        -- Этапы УП
        JOIN LINKS L54 ON L54.PARENT_ID = L400.OBJ_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
        -- Фильтр по параллели
        JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID and V381.PARAM_ID = 381 AND V381.IS_DEL = 0 AND V381.LISTVAL_ID = :V$PARALLEL_LV
        -- ГУП
        JOIN LINKS L256 ON L256.PARENT_ID = L54.OBJ_ID AND L256.OBJ_TYPE_ID = 256 AND L256.DATE_DEL IS NULL
        -- Ученики
        JOIN LINKS L10 ON L10.PARENT_ID = L256.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        WHERE L69.PARENT_ID = :V$SCHOOL_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL
          AND (VD.LISTVAL_ID IS NULL OR VD.LISTVAL_ID = 3) AND (VI.LISTVAL_ID IS NULL OR VI.LISTVAL_ID = 5465)
          AND (V2379.LISTVAL_ID IS NULL OR V2379.LISTVAL_ID = 11187)
        INTO :V$PUPIL_CNT;

        IF(V$PUPIL_CNT IS NULL) THEN V$PUPIL_CNT = 0;

        UPDATE OR INSERT INTO VALI (OBJ_ID, PARAM_ID, VAL, IS_DEL)
        VALUES (:V$OBJ_ID, 2685, :V$PUPIL_CNT, 0);

        -- Калькуляция обеспеченности учебниками V2 (15.01.2018) - сразу подсчитываем все уровни
        -- Предполагается что один ученик может быть только в одной группе по некоторому предмету
        -- Полностью обеспечены учебниками из ФПУ
        V$HAS_BOOKS = NULL;
        SELECT FIRST 1 SUBJECT_ID, SUM(STUDENTS_COUNT), SUM(BOOKS_COUNT)
        FROM MONITORING_BOOKS_SUMMARY(:V$SCHOOL_ID, :V$PARALLEL_LV, 0, :V$LIB2)
        GROUP BY 1
        ORDER BY 3, 2
        INTO :V$SUBJECT_ID, :V$CNT, :V$HAS_BOOKS;
        IF(V$HAS_BOOKS IS NOT NULL AND V$HAS_BOOKS > V$CNT) THEN V$HAS_BOOKS = V$CNT;
        IF(V$HAS_BOOKS IS NULL) THEN V$HAS_BOOKS = 0;
        UPDATE OR INSERT INTO VALI (OBJ_ID, PARAM_ID, VAL, IS_DEL) VALUES (:V$OBJ_ID, 2686, :V$HAS_BOOKS, 0);

        -- Полностью обеспечены учебниками из ФПУ и исключенными до 5 лет - утратило актуальность */
        /*V$BOOK_CNT = NULL;
        SELECT FIRST 1 SUBJECT_ID, SUM(STUDENTS_COUNT), SUM(BOOKS_COUNT)
        FROM MONITORING_BOOKS_SUMMARY(:V$SCHOOL_ID, :V$PARALLEL_LV, 1, :V$LIB2)
        GROUP BY 1
        ORDER BY 3, 2
        INTO :V$SUBJECT_ID, :V$CNT, :V$BOOK_CNT;
        IF(V$BOOK_CNT IS NOT NULL AND V$BOOK_CNT > V$CNT) THEN V$BOOK_CNT = V$CNT;
        IF(V$BOOK_CNT IS NULL) THEN V$BOOK_CNT = 0;
        UPDATE OR INSERT INTO VALI (OBJ_ID, PARAM_ID, VAL, IS_DEL) VALUES (:V$OBJ_ID, 2687, :V$BOOK_CNT - :V$HAS_BOOKS, 0);*/

        -- Нехватка по 1..5+ предметам - инкрементально. Двигаемся от самого большого количества необеспеченных
        V$MISS_COUNT = 0;
        V$PREV = NULL;
        V$V1 = NULL;
        V$V2 = NULL;
        V$V3 = NULL;
        V$V4 = NULL;
        V$V5 = NULL;

        FOR
            SELECT SUBJECT_ID, SUM(MISS_COUNT)
            FROM MONITORING_BOOKS_SUMMARY(:V$SCHOOL_ID, :V$PARALLEL_LV, 1, :V$LIB2)
            GROUP BY 1
            HAVING SUM(MISS_COUNT) > 0
            ORDER BY 2 DESC
            INTO :V$SUBJECT_ID, :V$HAS_BOOKS
        DO
        BEGIN
            -- Отсекаем необеспеченность большую кол-ва учеников. Иначе, это дает ошибку в алгоритме подсчета, как будто изменось кол-во необеспеченных учеников
            IF (V$HAS_BOOKS > V$PUPIL_CNT) THEN V$HAS_BOOKS = V$PUPIL_CNT;

            -- Раздел закончился, можно подвести итоги
            IF(V$HAS_BOOKS <> V$PREV AND V$PREV IS NOT NULL) THEN
            BEGIN
                IF(V$MISS_COUNT = 1) THEN V$V1 = V$PREV;
                ELSE IF(V$MISS_COUNT = 2) THEN V$V2 = V$PREV;
                ELSE IF(V$MISS_COUNT = 3) THEN V$V3 = V$PREV;
                ELSE IF(V$MISS_COUNT = 4) THEN V$V4 = V$PREV;
                ELSE IF(V$V5 IS NULL) THEN V$V5 = V$PREV;
            END
            V$MISS_COUNT = V$MISS_COUNT + 1;
            V$PREV = V$HAS_BOOKS;

        END

        -- Если разделы кончились раньше, чем набралось 5 строчек
        IF(V$PREV IS NOT NULL) THEN
        BEGIN
            IF(V$MISS_COUNT = 1) THEN V$V1 = V$PREV;
            ELSE IF(V$MISS_COUNT = 2) THEN V$V2 = V$PREV;
            ELSE IF(V$MISS_COUNT = 3) THEN V$V3 = V$PREV;
            ELSE IF(V$MISS_COUNT = 4) THEN V$V4 = V$PREV;
            ELSE IF(V$V5 IS NULL) THEN V$V5 = V$PREV;
        END

        IF(V$V1 IS NULL) THEN V$V1 = 0;
        ELSE
        BEGIN
          IF(V$V2 IS NOT NULL) THEN V$V1 = V$V1 - V$V2;
          ELSE IF(V$V3 IS NOT NULL) THEN V$V1 = V$V1 - V$V3;
          ELSE IF(V$V4 IS NOT NULL) THEN V$V1 = V$V1 - V$V4;
          ELSE IF(V$V5 IS NOT NULL) THEN V$V1 = V$V1 - V$V5;
        END

        IF(V$V2 IS NULL) THEN V$V2 = 0;
        ELSE
        BEGIN
          IF(V$V3 IS NOT NULL) THEN V$V2 = V$V2 - V$V3;
          ELSE IF(V$V4 IS NOT NULL) THEN V$V2 = V$V2 - V$V4;
          ELSE IF(V$V5 IS NOT NULL) THEN V$V2 = V$V2 - V$V5;
        END

        IF(V$V3 IS NULL) THEN V$V3 = 0;
        ELSE
        BEGIN
          IF(V$V4 IS NOT NULL) THEN V$V3 = V$V3 - V$V4;
          ELSE IF(V$V5 IS NOT NULL) THEN V$V3 = V$V3 - V$V5;
        END

        IF(V$V4 IS NULL) THEN V$V4 = 0;
        ELSE
        BEGIN
          IF(V$V5 IS NOT NULL) THEN V$V4 = V$V4 - V$V5;
        END

        IF(V$V5 IS NULL) THEN V$V5 = 0;

        UPDATE OR INSERT INTO VALI (OBJ_ID, PARAM_ID, VAL, IS_DEL) VALUES (:V$OBJ_ID, 2688, :V$V1, 0);
        UPDATE OR INSERT INTO VALI (OBJ_ID, PARAM_ID, VAL, IS_DEL) VALUES (:V$OBJ_ID, 2689, :V$V2, 0);
        UPDATE OR INSERT INTO VALI (OBJ_ID, PARAM_ID, VAL, IS_DEL) VALUES (:V$OBJ_ID, 2690, :V$V3, 0);
        UPDATE OR INSERT INTO VALI (OBJ_ID, PARAM_ID, VAL, IS_DEL) VALUES (:V$OBJ_ID, 2691, :V$V4, 0);
        UPDATE OR INSERT INTO VALI (OBJ_ID, PARAM_ID, VAL, IS_DEL) VALUES (:V$OBJ_ID, 2772, :V$V5, 0);

    END

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE MONITORING_EXPORT (
    I$SCHOOL_ID BIGINT = null,
    I$USER_ID BIGINT = null)
RETURNS (
    TAG_NAME VARCHAR(255),
    VAL VARCHAR(4000))
AS
declare variable V$OBJ_ID bigint;
declare variable V$MONITORING_ID bigint;
declare variable V$OU_LICENCE_TYPE varchar(1);
begin
    SELECT STATUS FROM OU_LICENCE_TYPE INTO :V$OU_LICENCE_TYPE;
    IF (I$SCHOOL_ID IS NULL) THEN
    BEGIN
        SELECT FIRST 1
               OBJ_ID
        FROM LINKS
        WHERE PARENT_ID IS NULL
        AND OBJ_TYPE_ID = 2
        AND DATE_DEL IS NULL

        INTO :I$SCHOOL_ID;
    END

    SELECT FIRST 1 OBJ_ID
    FROM lINKS
    WHERE PARENT_ID = :I$SCHOOL_ID
    AND OBJ_TYPE_ID = 162
    AND DATE_DEL IS NULL
    INTO :V$MONITORING_ID;

    IF (V$OU_LICENCE_TYPE = 'D') THEN
    BEGIN
        TAG_NAME = 'school::ou_type';
        VAL = 2;
        SUSPEND;
    END
    ELSE IF (V$OU_LICENCE_TYPE = 'O') THEN
    BEGIN
        TAG_NAME = 'school::ou_type';
        VAL = 1;
        SUSPEND;
    END
    ELSE IF (V$OU_LICENCE_TYPE = 'C') THEN
    BEGIN
        TAG_NAME = 'school::ou_type';
        VAL = 3;
        SUSPEND;
    END

    TAG_NAME = 'school::license_number';
    VAL = CAST(I$SCHOOL_ID / 1000000000 AS INT);
    SUSPEND;

    TAG_NAME = 'school:version_pg';
    SELECT V
    FROM VAL_GET(:V$MONITORING_ID, 1503, 0, :I$USER_ID)
    INTO :VAL;
    SUSPEND;

    TAG_NAME = 'school:version_pg_bd';
    SELECT V
    FROM VAL_GET(:V$MONITORING_ID, 1504, 0, :I$USER_ID)
    INTO :VAL;
    SUSPEND;

    TAG_NAME = 'school:version_pg_exp';
    SELECT V
    FROM VAL_GET(:V$MONITORING_ID, 1505, 0, :I$USER_ID)
    INTO :VAL;
    SUSPEND;

    TAG_NAME = 'school:sinh_exp_data';
    SELECT D
    FROM VAL_GET(:V$MONITORING_ID, 1506, 0, :I$USER_ID)
    INTO :VAL;
    SUSPEND;

    TAG_NAME = 'school:sinh_exp_time';
    SELECT T
    FROM VAL_GET(:V$MONITORING_ID, 1506, 0, :I$USER_ID)
    INTO :VAL;
    SUSPEND;

    TAG_NAME = 'school:School_number';
    SELECT VAL
    FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1420, :I$USER_ID)
    INTO :VAL;
    SUSPEND;

    IF (V$OU_LICENCE_TYPE IN ('O','C')) THEN
    BEGIN
        TAG_NAME = 'school:version_znak';
        SELECT V
        FROM VAL_GET(:V$MONITORING_ID, 1507, 0, :I$USER_ID)
        INTO :VAL;
        SUSPEND;
    END

    TAG_NAME = 'school:Short_name';
    SELECT VAL
    FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1419, :I$USER_ID)
    INTO :VAL;
    SUSPEND;

    TAG_NAME = 'school:Charter_full_name';
    SELECT VAL
    FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1418, :I$USER_ID)
    INTO :VAL;
    SUSPEND;

    TAG_NAME = 'school:Post_of_head';
    SELECT VAL
    FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1425, :I$USER_ID)
    INTO :VAL;
    SUSPEND;

    TAG_NAME = 'school:Head:ID';
    VAL = '';
    SELECT OBJ_ID
    FROM R_SPB_POST_DIRECTOR(:I$SCHOOL_ID, :I$USER_ID)
    INTO :VAL;
    SUSPEND;

    TAG_NAME = 'school:Head:Surname';
    VAL = '';
    SELECT F
    FROM R_SPB_POST_DIRECTOR(:I$SCHOOL_ID, :I$USER_ID)
    INTO :VAL;
    SUSPEND;

    TAG_NAME = 'school:Head:Name';
    VAL = '';
    SELECT I
    FROM R_SPB_POST_DIRECTOR(:I$SCHOOL_ID, :I$USER_ID)
    INTO :VAL;
    SUSPEND;

    TAG_NAME = 'school:Head:Patronymic';
    VAL = '';
    SELECT O
    FROM R_SPB_POST_DIRECTOR(:I$SCHOOL_ID, :I$USER_ID)
    INTO :VAL;
    SUSPEND;

    IF (V$OU_LICENCE_TYPE IN ('O','C')) THEN
    BEGIN
        TAG_NAME = 'school:EGE_responsible:ID';
        VAL = '';
        SELECT OBJ_ID
        FROM R_SPB_POST_EGE_RESPONSIBLE(:I$SCHOOL_ID, :I$USER_ID)
        INTO :VAL;
        SUSPEND;

        TAG_NAME = 'school:EGE_responsible:Surname';
        VAL = '';
        SELECT F
        FROM R_SPB_POST_EGE_RESPONSIBLE(:I$SCHOOL_ID, :I$USER_ID)
        INTO :VAL;
        SUSPEND;

        TAG_NAME = 'school:EGE_responsible:Name';
        VAL = '';
        SELECT I
        FROM R_SPB_POST_EGE_RESPONSIBLE(:I$SCHOOL_ID, :I$USER_ID)
        INTO :VAL;
        SUSPEND;

        TAG_NAME = 'school:EGE_responsible:Patronymic';
        VAL = '';
        SELECT O
        FROM R_SPB_POST_EGE_RESPONSIBLE(:I$SCHOOL_ID, :I$USER_ID)
        INTO :VAL;
        SUSPEND;
    END

    TAG_NAME = 'school:Phone_head';
    SELECT VAL
    FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1427, :I$USER_ID)
    INTO :VAL;
    SUSPEND;

    TAG_NAME = 'school:Phone_reception';
    SELECT VAL
    FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1428, :I$USER_ID)
    INTO :VAL;
    SUSPEND;

    TAG_NAME = 'school:Fax';
    SELECT VAL
    FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1429, :I$USER_ID)
    INTO :VAL;
    SUSPEND;

    TAG_NAME = 'school:mail';
    SELECT VAL
    FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1430, :I$USER_ID)
    INTO :VAL;
    SUSPEND;

    TAG_NAME = 'school:http_address';
    SELECT VAL
    FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1431, :I$USER_ID)
    INTO :VAL;
    SUSPEND;

    TAG_NAME = 'school:School_type';
    SELECT I
    FROM VAL_GET(:I$SCHOOL_ID, 11, 0, :I$USER_ID)
    INTO :VAL;
    SUSPEND;

    TAG_NAME = 'school:School_kind';
    SELECT I
    FROM VAL_GET(:I$SCHOOL_ID, 10, 0, :I$USER_ID)
    INTO :VAL;
    SUSPEND;

    TAG_NAME = 'school:School_subtype';
    SELECT V
    FROM VAL_GET(:I$SCHOOL_ID, 937, 0, :I$USER_ID)
    INTO :VAL;
    SUSPEND;

    TAG_NAME = 'school:OOOD_type';
    SELECT I
    FROM VAL_GET(:I$SCHOOL_ID, 1889, 0, :I$USER_ID)
    INTO :VAL;
    SUSPEND;

    TAG_NAME = 'school:OOOD_kind';
    SELECT I
    FROM VAL_GET(:I$SCHOOL_ID, 1890, 0, :I$USER_ID)
    INTO :VAL;
    SUSPEND;

    TAG_NAME = 'school:School_subordination';
    SELECT V
    FROM VAL_GET(:I$SCHOOL_ID, 7, 0, :I$USER_ID)
    INTO :VAL;
    SUSPEND;

    TAG_NAME = 'school:OPF';
    SELECT I
    FROM VAL_GET(:I$SCHOOL_ID, 8, 0, :I$USER_ID)
    INTO :VAL;
    SUSPEND;

    TAG_NAME = 'school:District';
    VAL = NULL;
    IF (EXISTS(
        SELECT FIRST 1 LP111.PARENT_ID
        FROM LINKS LP111
        WHERE LP111.PARENT_TYPE_ID = 111
        AND LP111.OBJ_ID = :I$SCHOOL_ID
        AND LP111.DATE_DEL IS NULL
    )) THEN
    BEGIN
        FOR
            SELECT FIRST 1 LP111.PARENT_ID
            FROM LINKS LP111
            WHERE LP111.PARENT_TYPE_ID = 111
            AND LP111.OBJ_ID = :I$SCHOOL_ID
            AND LP111.DATE_DEL IS NULL
            INTO :V$OBJ_ID
        DO
        BEGIN
            SELECT I
            FROM VAL_GET(:V$OBJ_ID, 665, 0, :I$USER_ID)
            INTO :VAL;
        END
    END
    ELSE
    BEGIN
        SELECT FIRST 1
               CAST(L.COST AS BIGINT)
        FROM VALS V7
        JOIN LISTVALS L
        ON L.LIST_ID = 168
        AND L.COST > 0

        JOIN RES R
        ON R.RES_ID = L.RES_ID
        AND R.LANG_CODE = 'RU'
        AND R.VAL LIKE V7.VAL

        WHERE V7.OBJ_ID = :I$SCHOOL_ID
        AND V7.PARAM_ID = 7
        AND V7.IS_DEL = 0
        INTO :VAL;
    END
    SUSPEND;

    TAG_NAME = 'school:OGRN';
    SELECT V
    FROM VAL_GET(:I$SCHOOL_ID, 9, 0, :I$USER_ID)
    INTO :VAL;
    SUSPEND;

    IF (V$OU_LICENCE_TYPE IN ('O', 'C')) THEN
    BEGIN
        FOR
            SELECT OBJ_ID
            FROM LINKS
            WHERE PARENT_ID = :I$SCHOOL_ID
            AND DATE_DEL IS NULL
            AND OBJ_TYPE_ID = 51
            INTO :V$OBJ_ID
        DO
        BEGIN
            TAG_NAME = 'school:deepSubjects:subject::id';
            VAL = V$OBJ_ID;
            SUSPEND;
    
            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:V$OBJ_ID, NULL, NULL, :I$USER_ID)
            INTO :VAL;
            TAG_NAME = 'school:deepSubjects:subject::name';
            SUSPEND;
        END
    END
end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE MONITORING_EXPORT_INFOEQUIPMENT (
    I$SCHOOL_ID BIGINT = null,
    I$USER_ID BIGINT = null)
RETURNS (
    TAG_NAME VARCHAR(255),
    VAL VARCHAR(4000))
AS
begin
    IF (I$SCHOOL_ID IS NULL) THEN
    BEGIN
        SELECT FIRST 1
               OBJ_ID
        FROM LINKS
        WHERE PARENT_ID IS NULL
        AND OBJ_TYPE_ID = 2
        AND DATE_DEL IS NULL

        INTO :I$SCHOOL_ID;
    END

    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 7, :I$USER_ID) INTO :VAL;
    TAG_NAME = 'school:info_equipments:computers::all';
    SUSPEND;

    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 8, :I$USER_ID) INTO :VAL;
    TAG_NAME = 'school:info_equipments:computers::pupil_computers';
    SUSPEND;

    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 9, :I$USER_ID) INTO :VAL;
    TAG_NAME = 'school:info_equipments:computers::teacher_computers';
    SUSPEND;

    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 10, :I$USER_ID) INTO :VAL;
    TAG_NAME = 'school:info_equipments:computers::administration_computers';
    SUSPEND;

    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 11, :I$USER_ID) INTO :VAL;
    TAG_NAME = 'school:info_equipments:computers::servers';
    SUSPEND;

    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 12, :I$USER_ID) INTO :VAL;
    TAG_NAME = 'school:info_equipments:computers_by_years::current_year';
    SUSPEND;

    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 13, :I$USER_ID) INTO :VAL;
    TAG_NAME = 'school:info_equipments:computers_by_years::current_year_1';
    SUSPEND;

    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 14, :I$USER_ID) INTO :VAL;
    TAG_NAME = 'school:info_equipments:computers_by_years::current_year_2';
    SUSPEND;

    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 15, :I$USER_ID) INTO :VAL;
    TAG_NAME = 'school:info_equipments:computers_by_years::current_year_3';
    SUSPEND;

    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 16, :I$USER_ID) INTO :VAL;
    TAG_NAME = 'school:info_equipments:computers_by_years::current_year_4';
    SUSPEND;

    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 17, :I$USER_ID) INTO :VAL;
    TAG_NAME = 'school:info_equipments:computers_by_years::current_year_5';
    SUSPEND;

    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 18, :I$USER_ID) INTO :VAL;
    TAG_NAME = 'school:info_equipments:computers_by_years::earliest_year';
    SUSPEND;

    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 19, :I$USER_ID) INTO :VAL;
    TAG_NAME = 'school:info_equipments:computers_by_years::unknown_year';
    SUSPEND;

    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 20, :I$USER_ID) INTO :VAL;
    TAG_NAME = 'school:info_equipments:multimedia::all';
    SUSPEND;

    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 21, :I$USER_ID) INTO :VAL;
    TAG_NAME = 'school:info_equipments:multimedia::interection';
    SUSPEND;

    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 22, :I$USER_ID) INTO :VAL;
    TAG_NAME = 'school:info_equipments:multimedia_by_years::current_year';
    SUSPEND;

    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 23, :I$USER_ID) INTO :VAL;
    TAG_NAME = 'school:info_equipments:multimedia_by_years::current_year_1';
    SUSPEND;

    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 24, :I$USER_ID) INTO :VAL;
    TAG_NAME = 'school:info_equipments:multimedia_by_years::current_year_2';
    SUSPEND;

    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 25, :I$USER_ID) INTO :VAL;
    TAG_NAME = 'school:info_equipments:multimedia_by_years::current_year_3';
    SUSPEND;

    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 26, :I$USER_ID) INTO :VAL;
    TAG_NAME = 'school:info_equipments:multimedia_by_years::current_year_4';
    SUSPEND;

    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 27, :I$USER_ID) INTO :VAL;
    TAG_NAME = 'school:info_equipments:multimedia_by_years::current_year_5';
    SUSPEND;

    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 28, :I$USER_ID) INTO :VAL;
    TAG_NAME = 'school:info_equipments:multimedia_by_years::earliest_year';
    SUSPEND;

    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 29, :I$USER_ID) INTO :VAL;
    TAG_NAME = 'school:info_equipments:multimedia_by_years::unknown_year';
    SUSPEND;

    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 30, :I$USER_ID) INTO :VAL;
    TAG_NAME = 'school:info_equipments:interection_devices::all';
    SUSPEND;

    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 31, :I$USER_ID) INTO :VAL;
    TAG_NAME = 'school:info_equipments:interection_devices::interection_boards';
    SUSPEND;

    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 32, :I$USER_ID) INTO :VAL;
    TAG_NAME = 'school:info_equipments:interection_devices::interection_stations';
    SUSPEND;

    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 33, :I$USER_ID) INTO :VAL;
    TAG_NAME = 'school:info_equipments:interection_devices_by_years::current_year';
    SUSPEND;

    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 34, :I$USER_ID) INTO :VAL;
    TAG_NAME = 'school:info_equipments:interection_devices_by_years::current_year_1';
    SUSPEND;

    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 35, :I$USER_ID) INTO :VAL;
    TAG_NAME = 'school:info_equipments:interection_devices_by_years::current_year_2';
    SUSPEND;

    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 36, :I$USER_ID) INTO :VAL;
    TAG_NAME = 'school:info_equipments:interection_devices_by_years::current_year_3';
    SUSPEND;

    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 37, :I$USER_ID) INTO :VAL;
    TAG_NAME = 'school:info_equipments:interection_devices_by_years::current_year_4';
    SUSPEND;

    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 38, :I$USER_ID) INTO :VAL;
    TAG_NAME = 'school:info_equipments:interection_devices_by_years::current_year_5';
    SUSPEND;

    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 39, :I$USER_ID) INTO :VAL;
    TAG_NAME = 'school:info_equipments:interection_devices_by_years::earliest_year';
    SUSPEND;

    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 40, :I$USER_ID) INTO :VAL;
    TAG_NAME = 'school:info_equipments:interection_devices_by_years::unknown_year';
    SUSPEND;

    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 41, :I$USER_ID) INTO :VAL;
    TAG_NAME = 'school:info_equipments:terminals::all';
    SUSPEND;

    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 42, :I$USER_ID) INTO :VAL;
    TAG_NAME = 'school:info_equipments:document_camera::all';
    SUSPEND;

    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 43, :I$USER_ID) INTO :VAL;
    TAG_NAME = 'school:info_equipments:sensor::all';
    SUSPEND;

    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 44, :I$USER_ID) INTO :VAL;
    TAG_NAME = 'school:info_equipments:microscopes::all';
    SUSPEND;

    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 45, :I$USER_ID) INTO :VAL;
    TAG_NAME = 'school:info_equipments:telescopes::all';
    SUSPEND;

    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 46, :I$USER_ID) INTO :VAL;
    TAG_NAME = 'school:info_equipments:computer_classes::all';
    SUSPEND;

    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 47, :I$USER_ID) INTO :VAL;
    TAG_NAME = 'school:info_equipments:computer_classes::stationary_classes';
    SUSPEND;

    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 48, :I$USER_ID) INTO :VAL;
    TAG_NAME = 'school:info_equipments:computer_classes::portable_classes';
    SUSPEND;


    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 49, :I$USER_ID) INTO :VAL;
    TAG_NAME = 'school:info_equipments:computer_classes::workplaces';
    SUSPEND;

    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 50, :I$USER_ID) INTO :VAL;
    TAG_NAME = 'school:info_equipments:computer_classes::stationary_workplaces';
    SUSPEND;

    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 51, :I$USER_ID) INTO :VAL;
    TAG_NAME = 'school:info_equipments:computer_classes::portable_workplaces';
    SUSPEND;

    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 52, :I$USER_ID) INTO :VAL;
    TAG_NAME = 'school:info_equipments:science_labs::all';
    SUSPEND;

    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 53, :I$USER_ID) INTO :VAL;
    TAG_NAME = 'school:info_equipments:science_labs::physics_labs';
    SUSPEND;

    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 54, :I$USER_ID) INTO :VAL;
    TAG_NAME = 'school:info_equipments:science_labs::biology_labs';
    SUSPEND;

    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 55, :I$USER_ID) INTO :VAL;
    TAG_NAME = 'school:info_equipments:science_labs::chemistry_labs';
    SUSPEND;

    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 56, :I$USER_ID) INTO :VAL;
    TAG_NAME = 'school:info_equipments:science_labs::natural_science_labs';
    SUSPEND;

    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 57, :I$USER_ID) INTO :VAL;
    TAG_NAME = 'school:info_equipments:science_labs::chemistry_biology_labs';
    SUSPEND;

    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 58, :I$USER_ID) INTO :VAL;
    TAG_NAME = 'school:info_equipments:science_labs_workplace::all';
    SUSPEND;

    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 59, :I$USER_ID) INTO :VAL;
    TAG_NAME = 'school:info_equipments:science_labs_workplace::physics_labs';
    SUSPEND;

    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 60, :I$USER_ID) INTO :VAL;
    TAG_NAME = 'school:info_equipments:science_labs_workplace::biology_labs';
    SUSPEND;

    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 61, :I$USER_ID) INTO :VAL;
    TAG_NAME = 'school:info_equipments:science_labs_workplace::chemistry_labs';
    SUSPEND;

    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 62, :I$USER_ID) INTO :VAL;
    TAG_NAME = 'school:info_equipments:science_labs_workplace::natural_science_labs';
    SUSPEND;

    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 63, :I$USER_ID) INTO :VAL;
    TAG_NAME = 'school:info_equipments:science_labs_workplace::chemistry_biology_labs';
    SUSPEND;

    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 64, :I$USER_ID) INTO :VAL;
    TAG_NAME = 'school:info_equipments:robotic_labs::all';
    SUSPEND;

    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 65, :I$USER_ID) INTO :VAL;
    TAG_NAME = 'school:info_equipments:lingaphone_labs::all';
    SUSPEND;

    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 66, :I$USER_ID) INTO :VAL;
    TAG_NAME = 'school:info_equipments:presentation_complex::all';
    SUSPEND;

    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 67, :I$USER_ID) INTO :VAL;
    TAG_NAME = 'school:info_equipments:vcs::all';
    SUSPEND;

    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 68, :I$USER_ID) INTO :VAL;
    TAG_NAME = 'school:info_equipments:lan::all';
    SUSPEND;

    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 69, :I$USER_ID) INTO :VAL;
    TAG_NAME = 'school:info_equipments:lan::internet_speed';
    SUSPEND;

    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 70, :I$USER_ID) INTO :VAL;
    TAG_NAME = 'school:info_equipments:lan::emts_connect';
    SUSPEND;

    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 71, :I$USER_ID) INTO :VAL;
    TAG_NAME = 'school:info_equipments:inform_value::web_distance';
    SUSPEND;

    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 72, :I$USER_ID) INTO :VAL;
    TAG_NAME = 'school:info_equipments:inform_value::web_diary';
    SUSPEND;

    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 73, :I$USER_ID) INTO :VAL;
    TAG_NAME = 'school:info_equipments:inform_value::percent_teachers';
    SUSPEND;

    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 74, :I$USER_ID) INTO :VAL;
    TAG_NAME = 'school:info_equipments:inform_control::department_spio';
    SUSPEND;

    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 75, :I$USER_ID) INTO :VAL;
    TAG_NAME = 'school:info_equipments:inform_control::spio';
    SUSPEND;

    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 76, :I$USER_ID) INTO :VAL;
    TAG_NAME = 'school:info_equipments:inform_control::director_ikt';
    SUSPEND;

    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 77, :I$USER_ID) INTO :VAL;
    TAG_NAME = 'school:info_equipments:inform_control::metodists';
    SUSPEND;

    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 78, :I$USER_ID) INTO :VAL;
    TAG_NAME = 'school:info_equipments:inform_control::ingener_ikt';
    SUSPEND;

    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 79, :I$USER_ID) INTO :VAL;
    TAG_NAME = 'school:info_equipments:inform_control::student_for_computer';
    SUSPEND;

    SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:I$SCHOOL_ID, 80, :I$USER_ID) INTO :VAL;
    TAG_NAME = 'school:info_equipments:inform_control::teacher_for_computer';
    SUSPEND;
end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE MONITORING_EXPORT_MONITORING (
    I$SCHOOL_ID BIGINT = null,
    I$USER_ID BIGINT = null)
RETURNS (
    TAG_NAME VARCHAR(255),
    VAL VARCHAR(4000))
AS
declare variable V$OBJ_ID bigint;
declare variable V$BUILDING_ID bigint;
declare variable V$MONITORING_ID bigint;
declare variable V$LISTVAL_ID bigint;
declare variable V$OU_LICENCE_TYPE varchar(1);
declare variable V$STEAD_ID bigint;
declare variable V$SPD_ID bigint;
begin
    SELECT STATUS FROM OU_LICENCE_TYPE INTO :V$OU_LICENCE_TYPE;
    IF (I$SCHOOL_ID IS NULL) THEN
    BEGIN
        SELECT FIRST 1 OBJ_ID
        FROM LINKS
        WHERE PARENT_ID IS NULL AND OBJ_TYPE_ID = 2 AND DATE_DEL IS NULL
        INTO :I$SCHOOL_ID;
    END

    SELECT FIRST 1 OBJ_ID
    FROM LINKS
    WHERE PARENT_ID = :I$SCHOOL_ID AND OBJ_TYPE_ID = 162 AND DATE_DEL IS NULL
    INTO :V$MONITORING_ID;

    TAG_NAME = 'school:KO_monitoring:legal_address:area';
    SELECT REGION FROM ADR_GET(27, :I$SCHOOL_ID) INTO :VAL;
    SUSPEND;

    TAG_NAME = 'school:KO_monitoring:legal_address:district';
    SELECT DISTRICT FROM ADR_GET(27, :I$SCHOOL_ID) INTO :VAL;
    SUSPEND;

    TAG_NAME = 'school:KO_monitoring:legal_address:city';
    SELECT TOWN FROM ADR_GET(27, :I$SCHOOL_ID) INTO :VAL;
    SUSPEND;

    TAG_NAME = 'school:KO_monitoring:legal_address:settlement';
    SELECT SETTLEMENT FROM ADR_GET(27, :I$SCHOOL_ID) INTO :VAL;
    SUSPEND;

    TAG_NAME = 'school:KO_monitoring:legal_address:street';
    SELECT STREET FROM ADR_GET(27, :I$SCHOOL_ID) INTO :VAL;
    SUSPEND;

    TAG_NAME = 'school:KO_monitoring:legal_address:house';
    SELECT HOUSE FROM ADR_GET(27, :I$SCHOOL_ID) INTO :VAL;
    SUSPEND;

    TAG_NAME = 'school:KO_monitoring:legal_address:liter';
    SELECT LITER FROM ADR_GET(27, :I$SCHOOL_ID) INTO :VAL;
    SUSPEND;

    TAG_NAME = 'school:KO_monitoring:legal_address:corpus';
    SELECT CORP FROM ADR_GET(27, :I$SCHOOL_ID) INTO :VAL;
    SUSPEND;

    TAG_NAME = 'school:KO_monitoring:legal_address:flat';
    SELECT FLAT FROM ADR_GET(27, :I$SCHOOL_ID) INTO :VAL;
    SUSPEND;

    TAG_NAME = 'school:KO_monitoring:legal_address:index';
    SELECT POST_INDEX FROM ADR_GET(27, :I$SCHOOL_ID) INTO :VAL;
    SUSPEND;

    TAG_NAME = 'school:KO_monitoring:buildings::count';
    SELECT VAL FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1435, :I$USER_ID) INTO :VAL;
    SUSPEND;

    TAG_NAME = 'school:KO_monitoring:buildings::total_bilding_area';
    SELECT VAL FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1436, :I$USER_ID) INTO :VAL;
    SUSPEND;

    TAG_NAME = 'school:KO_monitoring:buildings::total_study_area';
    SELECT VAL FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1437, :I$USER_ID) INTO :VAL;
    SUSPEND;

    FOR
        SELECT L16.OBJ_ID, V3408.VAL
        FROM LINKS L73
        JOIN LINKS L16 ON L16.PARENT_ID = L73.OBJ_ID AND L16.OBJ_TYPE_ID = 16 AND L16.DATE_DEL IS NULL
        LEFT JOIN VALR V3408 ON V3408.OBJ_ID = L16.OBJ_ID AND V3408.PARAM_ID = 3408 AND V3408.IS_DEL = 0
        WHERE L73.PARENT_ID = :I$SCHOOL_ID AND L73.OBJ_TYPE_ID = 73 AND L73.DATE_DEL IS NULL
        INTO :V$OBJ_ID, :V$STEAD_ID
    DO
    BEGIN
        TAG_NAME = 'school:KO_monitoring:buildings:building::name';
        SELECT V FROM VAL_GET(:V$OBJ_ID, 421) INTO :VAL;
        SUSPEND;

        TAG_NAME = 'school:KO_monitoring:buildings:building::id';
        VAL = V$OBJ_ID;
        SUSPEND;

        TAG_NAME = 'school:KO_monitoring:buildings:building:address:area';
        SELECT REGION FROM ADR_GET(420, :V$OBJ_ID) INTO :VAL;
        SUSPEND;

        TAG_NAME = 'school:KO_monitoring:buildings:building:address:district';
        SELECT DISTRICT FROM ADR_GET(420, :V$OBJ_ID) INTO :VAL;
        SUSPEND;

        TAG_NAME = 'school:KO_monitoring:buildings:building:address:city';
        SELECT TOWN FROM ADR_GET(420, :V$OBJ_ID) INTO :VAL;
        SUSPEND;

        TAG_NAME = 'school:KO_monitoring:buildings:building:address:settlement';
        SELECT SETTLEMENT FROM ADR_GET(420, :V$OBJ_ID) INTO :VAL;
        SUSPEND;

        TAG_NAME = 'school:KO_monitoring:buildings:building:address:street';
        SELECT STREET FROM ADR_GET(420, :V$OBJ_ID) INTO :VAL;
        SUSPEND;

        TAG_NAME = 'school:KO_monitoring:buildings:building:address:house';
        SELECT HOUSE FROM ADR_GET(420, :V$OBJ_ID) INTO :VAL;
        SUSPEND;

        TAG_NAME = 'school:KO_monitoring:buildings:building:address:liter';
        SELECT LITER FROM ADR_GET(420, :V$OBJ_ID) INTO :VAL;
        SUSPEND;

        TAG_NAME = 'school:KO_monitoring:buildings:building:address:corpus';
        SELECT CORP FROM ADR_GET(420, :V$OBJ_ID) INTO :VAL;
        SUSPEND;

        TAG_NAME = 'school:KO_monitoring:buildings:building:address:flat';
        SELECT FLAT FROM ADR_GET(420, :V$OBJ_ID) INTO :VAL;
        SUSPEND;

        TAG_NAME = 'school:KO_monitoring:buildings:building:address:index';
        SELECT POST_INDEX FROM ADR_GET(420, :V$OBJ_ID) INTO :VAL;
        SUSPEND;

        TAG_NAME = 'school:KO_monitoring:buildings:building:study_area';
        SELECT F FROM VAL_GET(:V$OBJ_ID, 499) INTO :VAL;
        SUSPEND;

        FOR
            SELECT L61.OBJ_ID, VL.LISTVAL_ID
            FROM LINKS L61
            JOIN VALL VL ON VL.OBJ_ID = L61.OBJ_ID AND VL.PARAM_ID = 526 AND VL.IS_DEL = 0 AND VL.LISTVAL_ID IN (1155, 1156, 1130)
            WHERE L61.PARENT_ID = :V$OBJ_ID AND L61.OBJ_TYPE_ID = 61 AND L61.DATE_DEL IS NULL
            INTO :V$BUILDING_ID, :V$LISTVAL_ID
        DO
        BEGIN
            IF (V$LISTVAL_ID = 1130) THEN
            BEGIN
                TAG_NAME = 'school:KO_monitoring:buildings:building:gymnasium::id';
                VAL = V$BUILDING_ID;
                SUSPEND;

                TAG_NAME = 'school:KO_monitoring:buildings:building:gymnasium::name';
                SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$BUILDING_ID) INTO :VAL;
                SUSPEND;

                TAG_NAME = 'school:KO_monitoring:buildings:building:gymnasium::square';
                SELECT F FROM VAL_GET(:V$BUILDING_ID, 533) INTO :VAL;
                SUSPEND;
            END
            ELSE
            BEGIN
                TAG_NAME = 'school:KO_monitoring:buildings:building:buffet::id';
                VAL = V$BUILDING_ID;
                SUSPEND;

                TAG_NAME = 'school:KO_monitoring:buildings:building:buffet::function';
                SELECT V FROM VAL_GET(:V$BUILDING_ID, 526) INTO :VAL;
                SUSPEND;

                TAG_NAME = 'school:KO_monitoring:buildings:building:buffet::name';
                SELECT V FROM VAL_GET(:V$BUILDING_ID, 408) INTO :VAL;
                SUSPEND;

                TAG_NAME = 'school:KO_monitoring:buildings:building:buffet::seats_pro';
                SELECT I FROM VAL_GET(:V$BUILDING_ID, 531) INTO :VAL;
                SUSPEND;

                TAG_NAME = 'school:KO_monitoring:buildings:building:buffet::seats_fact';
                SELECT I FROM VAL_GET(:V$BUILDING_ID, 532) INTO :VAL;
                SUSPEND;

                TAG_NAME = 'school:KO_monitoring:buildings:building:buffet::square';
                SELECT F FROM VAL_GET(:V$BUILDING_ID, 533) INTO :VAL;
                SUSPEND;
            END
        END

        TAG_NAME = 'school:KO_monitoring:buildings:building:sports_ground';
        VAL = 'Нет';
        IF(V$STEAD_ID IS NOT NULL AND EXISTS(
          SELECT FIRST 1 1
          FROM VALR V3407
          JOIN LINKS LP73 ON LP73.OBJ_ID = V3407.OBJ_ID AND LP73.PARENT_TYPE_ID = 73 AND LP73.DATE_DEL IS NULL -- живое сооружение
          JOIN VALL V3398 ON V3398.OBJ_ID = V3407.OBJ_ID AND V3398.PARAM_ID = 3398 AND V3398.IS_DEL = 0 AND V3398.LISTVAL_ID = 14242
          LEFT JOIN VALD V3411 ON V3411.OBJ_ID = V3407.OBJ_ID AND V3411.PARAM_ID = 3411 AND V3411.IS_DEL = 0
          WHERE V3407.PARAM_ID = 3407 AND V3407.IS_DEL = 0 AND V3407.VAL = :V$STEAD_ID AND V3411.VAL IS NULL
        ))
        THEN
          VAL = 'Да';
        SUSPEND;

        IF (V$OU_LICENCE_TYPE IN ('O', 'C')) THEN
        BEGIN
            V$SPD_ID = NULL;
            VAL = NULL;
            SELECT FIRST 1 V3407.OBJ_ID, V3412.VAL
            FROM VALR V3407
            JOIN LINKS LP73 ON LP73.OBJ_ID = V3407.OBJ_ID AND LP73.PARENT_TYPE_ID = 73 AND LP73.DATE_DEL IS NULL -- живое сооружение
            JOIN VALL V3398 ON V3398.OBJ_ID = V3407.OBJ_ID AND V3398.PARAM_ID = 3398 AND V3398.IS_DEL = 0 AND V3398.LISTVAL_ID = 14244
            JOIN VALI V3412 ON V3412.OBJ_ID = V3407.OBJ_ID AND V3412.PARAM_ID = 3412 AND V3412.IS_DEL = 0
            LEFT JOIN VALD V3411 ON V3411.OBJ_ID = V3407.OBJ_ID AND V3411.PARAM_ID = 3411 AND V3411.IS_DEL = 0
            WHERE V3407.PARAM_ID = 3407 AND V3407.IS_DEL = 0 AND V3407.VAL = :V$STEAD_ID AND V3411.VAL IS NULL
            INTO :V$SPD_ID, :VAL;

            TAG_NAME = 'school:KO_monitoring:buildings:building:stadium_artifical::initial_year';
            -- VAL уже тут
            SUSPEND;
            TAG_NAME = 'school:KO_monitoring:buildings:building:stadium_artifical';
            IF(V$SPD_ID IS NULL) THEN VAL = 'Нет'; ELSE VAL = 'Да';
            SUSPEND;
    
            V$SPD_ID = NULL;
            VAL = NULL;
            SELECT FIRST 1 V3407.OBJ_ID, V3412.VAL
            FROM VALR V3407
            JOIN LINKS LP73 ON LP73.OBJ_ID = V3407.OBJ_ID AND LP73.PARENT_TYPE_ID = 73 AND LP73.DATE_DEL IS NULL -- живое сооружение
            JOIN VALL V3398 ON V3398.OBJ_ID = V3407.OBJ_ID AND V3398.PARAM_ID = 3398 AND V3398.IS_DEL = 0 AND V3398.LISTVAL_ID = 14243
            JOIN VALI V3412 ON V3412.OBJ_ID = V3407.OBJ_ID AND V3412.PARAM_ID = 3412 AND V3412.IS_DEL = 0
            LEFT JOIN VALD V3411 ON V3411.OBJ_ID = V3407.OBJ_ID AND V3411.PARAM_ID = 3411 AND V3411.IS_DEL = 0
            WHERE V3407.PARAM_ID = 3407 AND V3407.IS_DEL = 0 AND V3407.VAL = :V$STEAD_ID AND V3411.VAL IS NULL
            INTO :V$SPD_ID, :VAL;

            TAG_NAME = 'school:KO_monitoring:buildings:building:stadium_natural::initial_year';
            -- VAL уже тут
            SUSPEND;
            TAG_NAME = 'school:KO_monitoring:buildings:building:stadium_natural';
            IF(V$SPD_ID IS NULL) THEN VAL = 'Нет'; ELSE VAL = 'Да';
            SUSPEND;
        END

        -- Ограждение
        TAG_NAME = 'school:KO_monitoring:buildings:building:fence';
        SELECT I FROM VAL_GET(:V$STEAD_ID, 3404) INTO :VAL;
        SUSPEND;
    END

    TAG_NAME = 'school:KO_monitoring:student_places';
    SELECT VAL FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1432, :I$USER_ID) INTO :VAL;
    SUSPEND;

    TAG_NAME = 'school:KO_monitoring:fact_occupancy';
    SELECT VAL FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1433, :I$USER_ID) INTO :VAL;
    SUSPEND;

    TAG_NAME = 'school:KO_monitoring:total_area';
    SELECT VAL FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1434, :I$USER_ID) INTO :VAL;
    SUSPEND;

    TAG_NAME = 'school:KO_monitoring:biblio_total';
    SELECT V FROM VAL_GET(:V$MONITORING_ID, 1439) INTO :VAL;
    SUSPEND;

    IF (V$OU_LICENCE_TYPE IN ('O', 'C')) THEN
    BEGIN
        TAG_NAME = 'school:KO_monitoring:textbooks';
        SELECT V FROM VAL_GET(:V$MONITORING_ID, 1440) INTO :VAL;
        SUSPEND;
    
        TAG_NAME = 'school:KO_monitoring:fictionbooks';
        SELECT V FROM VAL_GET(:V$MONITORING_ID, 1447) INTO :VAL;
        SUSPEND;
    
        TAG_NAME = 'school:KO_monitoring:provision_textbooks';
        SELECT V FROM VAL_GET(:V$MONITORING_ID, 1448) INTO :VAL;
        SUSPEND;
    
        TAG_NAME = 'school:KO_monitoring:provision_textbooks_FGOS';
        SELECT V FROM VAL_GET(:V$MONITORING_ID, 1450) INTO :VAL;
        SUSPEND;
    END

    TAG_NAME = 'school:KO_monitoring:gymnasium_count';
    SELECT VAL FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1460, :I$USER_ID) INTO :VAL;
    SUSPEND;

    TAG_NAME = 'school:KO_monitoring:pool';
    SELECT VAL FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1468, :I$USER_ID) INTO :VAL;
    SUSPEND;

    TAG_NAME = 'school:KO_monitoring:museum';
    SELECT VAL FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1469, :I$USER_ID) INTO :VAL;
    SUSPEND;

    TAG_NAME = 'school:KO_monitoring:logoped';
    SELECT VAL FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1470, :I$USER_ID) INTO :VAL;
    SUSPEND;

    TAG_NAME = 'school:KO_monitoring:buffet_presence';
    SELECT VAL FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1471, :I$USER_ID) INTO :VAL;
    SUSPEND;

    TAG_NAME = 'school:KO_monitoring:buffet_seats';
    SELECT VAL FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1472, :I$USER_ID) INTO :VAL;
    SUSPEND;

    TAG_NAME = 'school:KO_monitoring:workroom';
    SELECT V FROM VAL_GET(:V$MONITORING_ID, 1473) INTO :VAL;
    SUSPEND;

    TAG_NAME = 'school:KO_monitoring:sports_ground';
    SELECT VAL FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1474, :I$USER_ID) INTO :VAL;
    SUSPEND;

    IF (V$OU_LICENCE_TYPE = 'D') THEN
    BEGIN
        TAG_NAME = 'school:KO_monitoring:group_cell';
        SELECT V FROM VAL_GET(:V$MONITORING_ID, 1658) INTO :VAL;
        SUSPEND;

        TAG_NAME = 'school:KO_monitoring:music_room';
        SELECT VAL FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1656, :I$USER_ID) INTO :VAL;
        SUSPEND;

        TAG_NAME = 'school:KO_monitoring:logoped_room';
        SELECT V FROM VAL_GET(:V$MONITORING_ID, 1657) INTO :VAL;
        SUSPEND;

        TAG_NAME = 'school:KO_monitoring:computers::total';
        SELECT V FROM VAL_GET(:V$MONITORING_ID, 1727) INTO :VAL;
        SUSPEND;

        TAG_NAME = 'school:KO_monitoring:computers::adm';
        SELECT V FROM VAL_GET(:V$MONITORING_ID, 1728) INTO :VAL;
        SUSPEND;

        TAG_NAME = 'school:KO_monitoring:computers::pupil';
        SELECT V FROM VAL_GET(:V$MONITORING_ID, 1730) INTO :VAL;
        SUSPEND;

        TAG_NAME = 'school:KO_monitoring:computers::teacher';
        SELECT V FROM VAL_GET(:V$MONITORING_ID, 1731) INTO :VAL;
        SUSPEND;
    END
    ELSE
    BEGIN
        TAG_NAME = 'school:KO_monitoring:stadium';
        SELECT VAL FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1475, :I$USER_ID) INTO :VAL;
        SUSPEND;
    
        TAG_NAME = 'school:KO_monitoring:stadium_artifical';
        SELECT VAL FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1476, :I$USER_ID) INTO :VAL;
        SUSPEND;
    END

    TAG_NAME = 'school:KO_monitoring:fence';
    SELECT VAL
    FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1477, :I$USER_ID)
    INTO :VAL;
    SUSPEND;

    IF (V$OU_LICENCE_TYPE = 'D') THEN
    BEGIN
        TAG_NAME = 'school:KO_monitoring:invalid';
        SELECT I
        FROM VAL_GET(:V$MONITORING_ID, 1733)
        INTO :VAL;
        SUSPEND;
    
        TAG_NAME = 'school:KO_monitoring:OVZ_invalid';
        SELECT I
        FROM VAL_GET(:V$MONITORING_ID, 1732)
        INTO :VAL;
        SUSPEND;

        TAG_NAME = 'school:KO_monitoring:groups::total';
        SELECT VAL
        FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1526, :I$USER_ID)
        INTO :VAL;
        SUSPEND;

        TAG_NAME = 'school:KO_monitoring:groups::short';
        SELECT VAL
        FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1725, :I$USER_ID)
        INTO :VAL;
        SUSPEND;

        TAG_NAME = 'school:KO_monitoring:groups::g1';
        SELECT VAL
        FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1674, :I$USER_ID)
        INTO :VAL;
        SUSPEND;

        TAG_NAME = 'school:KO_monitoring:groups::g2';
        SELECT VAL
        FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1675, :I$USER_ID)
        INTO :VAL;
        SUSPEND;

        TAG_NAME = 'school:KO_monitoring:groups::g3';
        SELECT VAL
        FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1676, :I$USER_ID)
        INTO :VAL;
        SUSPEND;

        TAG_NAME = 'school:KO_monitoring:groups::g4';
        SELECT VAL
        FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1677, :I$USER_ID)
        INTO :VAL;
        SUSPEND;

        TAG_NAME = 'school:KO_monitoring:groups::g5';
        SELECT VAL
        FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1678, :I$USER_ID)
        INTO :VAL;
        SUSPEND;

        TAG_NAME = 'school:KO_monitoring:groups::g6';
        SELECT VAL
        FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1680, :I$USER_ID)
        INTO :VAL;
        SUSPEND;

        TAG_NAME = 'school:KO_monitoring:groups::g7';
        SELECT VAL
        FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1681, :I$USER_ID)
        INTO :VAL;
        SUSPEND;

        TAG_NAME = 'school:KO_monitoring:groups::g8';
        SELECT VAL
        FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1682, :I$USER_ID)
        INTO :VAL;
        SUSPEND;

        TAG_NAME = 'school:KO_monitoring:groups::g9';
        SELECT VAL
        FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1683, :I$USER_ID)
        INTO :VAL;
        SUSPEND;

        TAG_NAME = 'school:KO_monitoring:occupancy::g1';
        SELECT VAL
        FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1685, :I$USER_ID)
        INTO :VAL;
        SUSPEND;

        TAG_NAME = 'school:KO_monitoring:occupancy::g2';
        SELECT VAL
        FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1686, :I$USER_ID)
        INTO :VAL;
        SUSPEND;

        TAG_NAME = 'school:KO_monitoring:occupancy::g3';
        SELECT VAL
        FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1687, :I$USER_ID)
        INTO :VAL;
        SUSPEND;

        TAG_NAME = 'school:KO_monitoring:occupancy::g4';
        SELECT VAL
        FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1688, :I$USER_ID)
        INTO :VAL;
        SUSPEND;

        TAG_NAME = 'school:KO_monitoring:occupancy::g5';
        SELECT VAL
        FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1689, :I$USER_ID)
        INTO :VAL;
        SUSPEND;

        TAG_NAME = 'school:KO_monitoring:occupancy::g6';
        SELECT VAL
        FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1690, :I$USER_ID)
        INTO :VAL;
        SUSPEND;

        TAG_NAME = 'school:KO_monitoring:occupancy::g7';
        SELECT VAL
        FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1691, :I$USER_ID)
        INTO :VAL;
        SUSPEND;

        TAG_NAME = 'school:KO_monitoring:occupancy::g8';
        SELECT VAL
        FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1692, :I$USER_ID)
        INTO :VAL;
        SUSPEND;

        TAG_NAME = 'school:KO_monitoring:occupancy::g9';
        SELECT VAL
        FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1693, :I$USER_ID)
        INTO :VAL;
        SUSPEND;

        TAG_NAME = 'school:KO_monitoring:compensative::g1';
        SELECT VAL
        FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1695, :I$USER_ID)
        INTO :VAL;
        SUSPEND;

        TAG_NAME = 'school:KO_monitoring:compensative::g2';
        SELECT VAL
        FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1696, :I$USER_ID)
        INTO :VAL;
        SUSPEND;

        TAG_NAME = 'school:KO_monitoring:compensative::g3';
        SELECT VAL
        FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1698, :I$USER_ID)
        INTO :VAL;
        SUSPEND;

        TAG_NAME = 'school:KO_monitoring:compensative::g4';
        SELECT VAL
        FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1699, :I$USER_ID)
        INTO :VAL;
        SUSPEND;

        TAG_NAME = 'school:KO_monitoring:compensative::g5';
        SELECT VAL
        FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1700, :I$USER_ID)
        INTO :VAL;
        SUSPEND;

        TAG_NAME = 'school:KO_monitoring:compensative::g6';
        SELECT VAL
        FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1701, :I$USER_ID)
        INTO :VAL;
        SUSPEND;

        TAG_NAME = 'school:KO_monitoring:compensative::g7';
        SELECT VAL
        FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1702, :I$USER_ID)
        INTO :VAL;
        SUSPEND;

        TAG_NAME = 'school:KO_monitoring:compensative::g8';
        SELECT VAL
        FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1703, :I$USER_ID)
        INTO :VAL;
        SUSPEND;

        TAG_NAME = 'school:KO_monitoring:compensative::g9';
        SELECT VAL
        FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1704, :I$USER_ID)
        INTO :VAL;
        SUSPEND;

        TAG_NAME = 'school:KO_monitoring:sanitary::g1';
        SELECT VAL
        FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1706, :I$USER_ID)
        INTO :VAL;
        SUSPEND;

        TAG_NAME = 'school:KO_monitoring:sanitary::g2';
        SELECT VAL
        FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1707, :I$USER_ID)
        INTO :VAL;
        SUSPEND;

        TAG_NAME = 'school:KO_monitoring:sanitary::g3';
        SELECT VAL
        FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1708, :I$USER_ID)
        INTO :VAL;
        SUSPEND;

        TAG_NAME = 'school:KO_monitoring:sanitary::g4';
        SELECT VAL
        FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1709, :I$USER_ID)
        INTO :VAL;
        SUSPEND;

        TAG_NAME = 'school:KO_monitoring:sanitary::g5';
        SELECT VAL
        FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1710, :I$USER_ID)
        INTO :VAL;
        SUSPEND;

        TAG_NAME = 'school:KO_monitoring:sanitary::g6';
        SELECT VAL
        FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1711, :I$USER_ID)
        INTO :VAL;
        SUSPEND;

        TAG_NAME = 'school:KO_monitoring:sanitary::g7';
        SELECT VAL
        FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1712, :I$USER_ID)
        INTO :VAL;
        SUSPEND;

        TAG_NAME = 'school:KO_monitoring:sanitary::g8';
        SELECT VAL
        FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1713, :I$USER_ID)
        INTO :VAL;
        SUSPEND;

        TAG_NAME = 'school:KO_monitoring:sanitary::g9';
        SELECT VAL
        FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1714, :I$USER_ID)
        INTO :VAL;
        SUSPEND;

        TAG_NAME = 'school:KO_monitoring:combined::g1';
        SELECT VAL
        FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1716, :I$USER_ID)
        INTO :VAL;
        SUSPEND;

        TAG_NAME = 'school:KO_monitoring:combined::g2';
        SELECT VAL
        FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1717, :I$USER_ID)
        INTO :VAL;
        SUSPEND;

        TAG_NAME = 'school:KO_monitoring:combined::g3';
        SELECT VAL
        FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1718, :I$USER_ID)
        INTO :VAL;
        SUSPEND;

        TAG_NAME = 'school:KO_monitoring:combined::g4';
        SELECT VAL
        FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1719, :I$USER_ID)
        INTO :VAL;
        SUSPEND;

        TAG_NAME = 'school:KO_monitoring:combined::g5';
        SELECT VAL
        FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1720, :I$USER_ID)
        INTO :VAL;
        SUSPEND;

        TAG_NAME = 'school:KO_monitoring:combined::g6';
        SELECT VAL
        FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1721, :I$USER_ID)
        INTO :VAL;
        SUSPEND;

        TAG_NAME = 'school:KO_monitoring:combined::g7';
        SELECT VAL
        FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1722, :I$USER_ID)
        INTO :VAL;
        SUSPEND;

        TAG_NAME = 'school:KO_monitoring:combined::g8';
        SELECT VAL
        FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1723, :I$USER_ID)
        INTO :VAL;
        SUSPEND;

        TAG_NAME = 'school:KO_monitoring:combined::g9';
        SELECT VAL
        FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1724, :I$USER_ID)
        INTO :VAL;
        SUSPEND;

        TAG_NAME = 'school:KO_monitoring:free_places::g1';
        SELECT V
        FROM VAL_GET(:V$MONITORING_ID, 1660)
        INTO :VAL;
        SUSPEND;

        TAG_NAME = 'school:KO_monitoring:free_places::g2';
        SELECT V
        FROM VAL_GET(:V$MONITORING_ID, 1662)
        INTO :VAL;
        SUSPEND;

        TAG_NAME = 'school:KO_monitoring:free_places::g3';
        SELECT V
        FROM VAL_GET(:V$MONITORING_ID, 1664)
        INTO :VAL;
        SUSPEND;

        TAG_NAME = 'school:KO_monitoring:free_places::g4';
        SELECT V
        FROM VAL_GET(:V$MONITORING_ID, 1665)
        INTO :VAL;
        SUSPEND;

        TAG_NAME = 'school:KO_monitoring:free_places::g5';
        SELECT V
        FROM VAL_GET(:V$MONITORING_ID, 1666)
        INTO :VAL;
        SUSPEND;

        TAG_NAME = 'school:KO_monitoring:free_places::g6';
        SELECT V
        FROM VAL_GET(:V$MONITORING_ID, 1667)
        INTO :VAL;
        SUSPEND;

        TAG_NAME = 'school:KO_monitoring:free_places::g7';
        SELECT V
        FROM VAL_GET(:V$MONITORING_ID, 1669)
        INTO :VAL;
        SUSPEND;

        TAG_NAME = 'school:KO_monitoring:free_places::g8';
        SELECT V
        FROM VAL_GET(:V$MONITORING_ID, 1670)
        INTO :VAL;
        SUSPEND;

        TAG_NAME = 'school:KO_monitoring:free_places::g9';
        SELECT V
        FROM VAL_GET(:V$MONITORING_ID, 1671)
        INTO :VAL;
        SUSPEND;
    END
    ELSE
    BEGIN
        TAG_NAME = 'school:KO_monitoring:ODOD::student';
        SELECT V
        FROM VAL_GET(:V$MONITORING_ID, 1480)
        INTO :VAL;
        SUSPEND;
    
        TAG_NAME = 'school:KO_monitoring:ODOD';
        SELECT V
        FROM VAL_GET(:V$MONITORING_ID, 1479)
        INTO :VAL;
        SUSPEND;
    
        TAG_NAME = 'school:KO_monitoring:DOU::student';
        SELECT I
        FROM VAL_GET(:V$MONITORING_ID, 1483)
        INTO :VAL;
        SUSPEND;


        TAG_NAME = 'school:KO_monitoring:DOU';
        SELECT V
        FROM VAL_GET(:V$MONITORING_ID, 1482)
        INTO :VAL;
        SUSPEND;
    
        TAG_NAME = 'school:KO_monitoring:OVZ::invalid';
        SELECT I
        FROM VAL_GET(:V$MONITORING_ID, 1485)
        INTO :VAL;
        SUSPEND;
    
        TAG_NAME = 'school:KO_monitoring:OVZ';
        SELECT I
        FROM VAL_GET(:V$MONITORING_ID, 1484)
        INTO :VAL;
        SUSPEND;

        TAG_NAME = 'school:KO_monitoring:home_study::invalid';
        SELECT I
        FROM VAL_GET(:V$MONITORING_ID, 1487)
        INTO :VAL;
        SUSPEND;

        TAG_NAME = 'school:KO_monitoring:home_study';
        SELECT I
        FROM VAL_GET(:V$MONITORING_ID, 1486)
        INTO :VAL;
        SUSPEND;

        TAG_NAME = 'school:KO_monitoring:nutrition::p100';
        SELECT I
        FROM VAL_GET(:V$MONITORING_ID, 1489)
        INTO :VAL;
        SUSPEND;
    
        TAG_NAME = 'school:KO_monitoring:nutrition::p70';
        SELECT I
        FROM VAL_GET(:V$MONITORING_ID, 1490)
        INTO :VAL;
        SUSPEND;
    
        TAG_NAME = 'school:KO_monitoring:nutrition::compensation';
        SELECT I
        FROM VAL_GET(:V$MONITORING_ID, 1491)
        INTO :VAL;
        SUSPEND;

        TAG_NAME = 'school:KO_monitoring:nutrition';
        SELECT I
        FROM VAL_GET(:V$MONITORING_ID, 1488)
        INTO :VAL;
        SUSPEND;
    
        TAG_NAME = 'school:KO_monitoring:car_fleet';
        SELECT V
        FROM VAL_GET(:V$MONITORING_ID, 1492)
        INTO :VAL;
        SUSPEND;
    
        TAG_NAME = 'school:KO_monitoring:school_bus';
        SELECT V
        FROM VAL_GET(:V$MONITORING_ID, 1493)
        INTO :VAL;
        SUSPEND;

        TAG_NAME = 'school:KO_monitoring:contingent::g1';
        SELECT VAL
        FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1513, :I$USER_ID)
        INTO :VAL;
        SUSPEND;
    
        TAG_NAME = 'school:KO_monitoring:contingent::g2';
        SELECT VAL
        FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1514, :I$USER_ID)
        INTO :VAL;
        SUSPEND;
    
        TAG_NAME = 'school:KO_monitoring:contingent::g3';
        SELECT VAL
        FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1515, :I$USER_ID)
        INTO :VAL;
        SUSPEND;
    
        TAG_NAME = 'school:KO_monitoring:contingent::g4';
        SELECT VAL
        FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1516, :I$USER_ID)
        INTO :VAL;
        SUSPEND;
    
        TAG_NAME = 'school:KO_monitoring:contingent::g5';
        SELECT VAL
        FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1517, :I$USER_ID)
        INTO :VAL;
        SUSPEND;
    
        TAG_NAME = 'school:KO_monitoring:contingent::g6';
        SELECT VAL
        FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1518, :I$USER_ID)
        INTO :VAL;
        SUSPEND;
    
        TAG_NAME = 'school:KO_monitoring:contingent::g7';
        SELECT VAL
        FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1519, :I$USER_ID)
        INTO :VAL;
        SUSPEND;
    
        TAG_NAME = 'school:KO_monitoring:contingent::g8';
        SELECT VAL
        FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1520, :I$USER_ID)
        INTO :VAL;
        SUSPEND;
    
        TAG_NAME = 'school:KO_monitoring:contingent::g9';
        SELECT VAL
        FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1521, :I$USER_ID)
        INTO :VAL;
        SUSPEND;
    
        TAG_NAME = 'school:KO_monitoring:contingent::g10';
        SELECT VAL
        FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1522, :I$USER_ID)
        INTO :VAL;
        SUSPEND;
    
        TAG_NAME = 'school:KO_monitoring:contingent::g11';
        SELECT VAL
        FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1524, :I$USER_ID)
        INTO :VAL;
        SUSPEND;
    
        TAG_NAME = 'school:KO_monitoring:contingent::g12';
        SELECT VAL FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1525, :I$USER_ID) INTO :VAL;
        SUSPEND;

        TAG_NAME = 'school:KO_monitoring:classes::total';
        SELECT VAL FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1526, :I$USER_ID) INTO :VAL;
        SUSPEND;
    
        TAG_NAME = 'school:KO_monitoring:classes::g1';
        SELECT VAL FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1528, :I$USER_ID) INTO :VAL;
        SUSPEND;
    
        TAG_NAME = 'school:KO_monitoring:classes::g2';
        SELECT VAL FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1529, :I$USER_ID) INTO :VAL;
        SUSPEND;
    
        TAG_NAME = 'school:KO_monitoring:classes::g3';
        SELECT VAL FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1530, :I$USER_ID) INTO :VAL;
        SUSPEND;
    
        TAG_NAME = 'school:KO_monitoring:classes::g4';
        SELECT VAL FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1531, :I$USER_ID) INTO :VAL;
        SUSPEND;
    
        TAG_NAME = 'school:KO_monitoring:classes::g5';
        SELECT VAL FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1532, :I$USER_ID) INTO :VAL;
        SUSPEND;
    
        TAG_NAME = 'school:KO_monitoring:classes::g6';
        SELECT VAL FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1533, :I$USER_ID) INTO :VAL;
        SUSPEND;
    
        TAG_NAME = 'school:KO_monitoring:classes::g7';
        SELECT VAL FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1534, :I$USER_ID) INTO :VAL;
        SUSPEND;
    
        TAG_NAME = 'school:KO_monitoring:classes::g8';
        SELECT VAL FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1535, :I$USER_ID) INTO :VAL;
        SUSPEND;
    
        TAG_NAME = 'school:KO_monitoring:classes::g9';
        SELECT VAL FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1536, :I$USER_ID) INTO :VAL;
        SUSPEND;
    
        TAG_NAME = 'school:KO_monitoring:classes::g10';
        SELECT VAL FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1537, :I$USER_ID) INTO :VAL;
        SUSPEND;
    
        TAG_NAME = 'school:KO_monitoring:classes::g11';
        SELECT VAL FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1538, :I$USER_ID) INTO :VAL;
        SUSPEND;
    
        TAG_NAME = 'school:KO_monitoring:classes::g12';
        SELECT VAL FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1539, :I$USER_ID) INTO :VAL;
        SUSPEND;
    END

    TAG_NAME = 'school:KO_monitoring:workers::w1';
    SELECT VAL FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1541, :I$USER_ID) INTO :VAL;
    SUSPEND;

    TAG_NAME = 'school:KO_monitoring:workers::w2';
    SELECT VAL FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1542, :I$USER_ID) INTO :VAL;
    SUSPEND;

    TAG_NAME = 'school:KO_monitoring:workers::w3';
    SELECT VAL FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1544, :I$USER_ID) INTO :VAL;
    SUSPEND;

    IF (V$OU_LICENCE_TYPE = 'D') THEN
    BEGIN
        TAG_NAME = 'school:KO_monitoring:workers::w7';
        SELECT VAL FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1726, :I$USER_ID) INTO :VAL;
        SUSPEND;
    END
    ELSE
    BEGIN
        TAG_NAME = 'school:KO_monitoring:workers::w4';
        SELECT VAL FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1546, :I$USER_ID) INTO :VAL;
        SUSPEND;
    END

    TAG_NAME = 'school:KO_monitoring:workers::w5';
    SELECT VAL FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1547, :I$USER_ID) INTO :VAL;
    SUSPEND;

    IF (V$OU_LICENCE_TYPE IN ('O', 'C')) THEN
    BEGIN
        TAG_NAME = 'school:KO_monitoring:pupil_movement::in';
        SELECT VAL
        FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1596, :I$USER_ID)
        INTO :VAL;
        SUSPEND;
    
        TAG_NAME = 'school:KO_monitoring:pupil_movement::out';
        SELECT VAL
        FROM MONITORING_DO_FUNC(:I$SCHOOL_ID, 1597, :I$USER_ID)
        INTO :VAL;
        SUSPEND;
    END
end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE MONITORING_GYMS (
    I$SCHOOL_ID BIGINT)
RETURNS (
    GYM_ID BIGINT,
    BUILDING_ID BIGINT,
    GYM_NAME VARCHAR(1000),
    BUILDING_NAME VARCHAR(1000),
    GYM_SQUARE FLOAT)
AS
BEGIN
    FOR
        SELECT L16.OBJ_ID, L61.OBJ_ID, VI.VAL
        FROM LINKS L73
        JOIN LINKS L16 ON L16.PARENT_ID = L73.OBJ_ID AND L16.DATE_DEL IS NULL AND L16.OBJ_TYPE_ID = 16
        JOIN LINKS L61 ON L61.PARENT_ID = L16.OBJ_ID AND L61.DATE_DEL IS NULL AND L61.OBJ_TYPE_ID = 61
        JOIN VALL VL ON VL.OBJ_ID = L61.OBJ_ID AND VL.IS_DEL = 0 AND VL.PARAM_ID = 526 AND VL.LISTVAL_ID = 1130
        JOIN VALF VI ON VI.OBJ_ID = L61.OBJ_ID AND VI.IS_DEL = 0 AND VI.PARAM_ID = 533
        WHERE L73.PARENT_ID = :I$SCHOOL_ID AND L73.DATE_DEL IS NULL AND L73.OBJ_TYPE_ID = 73
        INTO :BUILDING_ID, :GYM_ID, :GYM_SQUARE
    DO
    BEGIN
        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:GYM_ID)
        INTO :GYM_NAME;

        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:BUILDING_ID)
        INTO :BUILDING_NAME;

        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE MONITORING_PLAN_SUBJECTS (
    I$PLAN_ID BIGINT,
    I$STAGE_ID BIGINT,
    I$STAGE_LV BIGINT)
RETURNS (
    COMPONENT_ID BIGINT,
    COMPONENT_TYPE BIGINT,
    SUBJECT_ID BIGINT,
    SUBJECT_NAME VARCHAR(4000),
    IS_ELECTIVE SMALLINT,
    LOAD_ID BIGINT,
    IS_COLLEGE SMALLINT)
AS
begin

  FOR
      -- Ветка для школ
      SELECT PSP.FIELD_ID, PS.SUBJECT_ID, V376.VAL, IIF(V2816.LISTVAL_ID = 2, 1, 0), L.OBJ_ID, 0
      FROM PLAN_SUBJECTS PS
      JOIN PLAN_SUBJECTS PSP ON PSP.OBJ_ID = PS.PARENT_ID
      JOIN PLAN_LOADS L ON L.DATE_DEL IS NULL AND L.SUBJECT_ID = PS.OBJ_ID AND (L.STAGE_ID = :I$STAGE_ID OR :I$STAGE_ID IS NULL)
        AND (L.LOAD_HOURS_S1 > 0 OR L.LOAD_HOURS_S2 > 0)
      JOIN VALS V376 ON V376.OBJ_ID = PS.SUBJECT_ID AND V376.PARAM_ID = 376 AND V376.IS_DEL = 0
      -- Элективный предмет ?
      LEFT JOIN VALL V2816 ON V2816.OBJ_ID = PS.SUBJECT_ID and V2816.PARAM_ID = 2816 AND V2816.IS_DEL = 0
      WHERE PS.DATE_DEL IS NULL AND PS.PLAN_ID = :I$PLAN_ID AND PS.ROW_TYPE = 10
      INTO :COMPONENT_TYPE, :SUBJECT_ID, :SUBJECT_NAME, :IS_ELECTIVE, :LOAD_ID, :IS_COLLEGE
  DO
  BEGIN
      -- Убираем предмет - индивидуальный проект
      IF(SUBJECT_ID <> 34651) THEN SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE MONITORING_PLAN_UPD (
    I$PLAN_ID BIGINT)
RETURNS (
    VAL VARCHAR(5100))
AS
DECLARE VARIABLE V$MON_ID BIGINT;
DECLARE VARIABLE V$LINK_ID BIGINT;
DECLARE VARIABLE V$OU_ID BIGINT;
DECLARE VARIABLE V$PLAN_ID BIGINT;
DECLARE VARIABLE V$LEVEL_ID BIGINT;
DECLARE VARIABLE V$STD_ID BIGINT;
DECLARE VARIABLE V$PROFILE_ID BIGINT;
DECLARE VARIABLE V$SRC_PLAN_ID5 BIGINT;
DECLARE VARIABLE V$SRC_PLAN_ID6 BIGINT;
DECLARE VARIABLE V$SRC_PLAN BIGINT;
DECLARE VARIABLE V$SRC_PROFILE_ID BIGINT;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$REF_ID BIGINT;
DECLARE VARIABLE V$STAGE_ID BIGINT;
DECLARE VARIABLE V$WEEK BIGINT;
DECLARE VARIABLE V$LIMIT1 INTEGER;
DECLARE VARIABLE V$LIMIT2 INTEGER;
DECLARE VARIABLE V$STAGE_ROW BIGINT;
DECLARE VARIABLE N INTEGER;
DECLARE VARIABLE V$MATCH_H_TOTAL SMALLINT;
DECLARE VARIABLE V$MATCH_H_INV SMALLINT;
DECLARE VARIABLE V$MATCH_H_VAR SMALLINT;
DECLARE VARIABLE V$HOURS_INV FLOAT;
DECLARE VARIABLE V$HOURS_VAR FLOAT;
DECLARE VARIABLE V$HOURS FLOAT;
DECLARE VARIABLE V$HOURS_SUM FLOAT;
DECLARE VARIABLE V$SRC_HOURS_VAR FLOAT;
DECLARE VARIABLE V$SRC_HOURS_INV FLOAT;
DECLARE VARIABLE V$SRC_HOURS_SUM FLOAT;
DECLARE VARIABLE V$SUBJECT_ID BIGINT;
DECLARE VARIABLE V$SUBJECT_ID2 BIGINT;
DECLARE VARIABLE V$LIMIT_MATCH SMALLINT;
DECLARE VARIABLE V$MATCH_FIXED SMALLINT;
DECLARE VARIABLE V$MATCH_VAR SMALLINT;
DECLARE VARIABLE V$MATCH_DIV SMALLINT;
DECLARE VARIABLE V$MATCH_PF BIGINT;
DECLARE VARIABLE V$MATCH_CNT BIGINT;
DECLARE VARIABLE V$MATCH_SUM_HOURS BIGINT;
DECLARE VARIABLE V$WEEK_ID BIGINT;
DECLARE VARIABLE V$ADV SMALLINT;
DECLARE VARIABLE S1 VARCHAR(5000);
DECLARE VARIABLE S2 VARCHAR(5000);
DECLARE VARIABLE S3 VARCHAR(5000);
DECLARE VARIABLE V$PY INTEGER;
DECLARE VARIABLE V$LANG2 SMALLINT;
begin

  -- Мониторинг УП теперь пересчитываем не на каждый чих, а только при изменении самого УП
  -- I$PLAN_ID - null пересчитать все планы
  -- не null - пересчитать конкретный план, даже если он не действующий
  -- удалить действующий учебный план нельзя, надо сначала снять флаг действующего

  SELECT FIRST 1 L2.OBJ_ID, L162.OBJ_ID
  FROM LINKS L2
  JOIN LINKS L162 ON L162.PARENT_ID = L2.OBJ_ID AND L162.OBJ_TYPE_ID = 162 AND L162.DATE_DEL IS NULL
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$OU_ID, :V$MON_ID;

  IF(V$MON_ID IS NULL) THEN EXIT;

  -- Шаблоны не проверяем
  SELECT FIRST 1 LP.PARENT_TYPE_ID
  FROM LINKS LP
  WHERE LP.OBJ_ID = :I$PLAN_ID AND LP.PARENT_TYPE_ID IN (55, 57) AND LP.DATE_DEL IS NULL
  INTO :V$LINK_ID;
  IF(V$LINK_ID = 55) THEN EXIT;

  V$LANG2 = 0;
  SELECT FIRST 1 1
  FROM PLAN_SUBJECTS S
  JOIN PLAN_SUBJECTS PS ON PS.OBJ_ID = S.PARENT_ID AND PS.FIELD_ID = 13303
  WHERE S.DATE_DEL IS NULL AND (S.SRC_SUBJECT_ID = 32810 AND S.SUBJECT_ID = 32810)
  INTO :V$LANG2;

  -- Затираем записи по данному учебному плану или всем учебным планам, а также этапы учебного плана
  FOR
    -- Ссылки на элементы контроля по УП
    SELECT L.LINK_ID
    FROM LINKS L
    JOIN VALR V ON V.OBJ_ID = L.OBJ_ID AND V.PARAM_ID IN (2482, 2490, 2493, 2498, 2504, 2506, 2511, 2515, /**/ 2745, 2759, 2761, 2763, 2769)
      AND V.IS_DEL = 0 AND (V.VAL = :I$PLAN_ID OR :I$PLAN_ID IS NULL)
    WHERE L.PARENT_ID = :V$MON_ID AND L.OBJ_TYPE_ID IN (305, 306, 307, 309, 310, 311, 313, 315, /**/ 357, 358, 359, 360, 361) AND L.DATE_DEL IS NULL
    -- Ссылки на этапы - включая удаленные из УП
    UNION
    SELECT L54.LINK_ID
    FROM LINKS L54
    JOIN LINKS LP ON LP.OBJ_ID = L54.OBJ_ID AND (LP.PARENT_ID = :I$PLAN_ID OR :I$PLAN_ID IS NULL)
    WHERE L54.PARENT_ID = :V$MON_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
    ORDER BY 1
    INTO :V$LINK_ID
  DO
  BEGIN
    UPDATE LINKS SET DATE_DEL = CURRENT_TIMESTAMP WHERE LINK_ID = :V$LINK_ID;
  END

  -- Пересчитываем - только для действующих УП
  FOR
    SELECT L400.OBJ_ID, V1594.LISTVAL_ID, V3014.LISTVAL_ID, V3112.LISTVAL_ID, COALESCE(V3115.VAL, 0)
    FROM LINKS L69
    JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
    -- Год публикации
    LEFT JOIN VALI V3115 ON V3115.OBJ_ID = L57.OBJ_ID AND V3115.PARAM_ID = 3115 AND V3115.IS_DEL = 0
    -- Только НОО, ООО, СОО
    JOIN VALL V1594 ON V1594.OBJ_ID = L57.OBJ_ID AND V1594.PARAM_ID = 1594 AND V1594.IS_DEL = 0 AND V1594.LISTVAL_ID IN (5339, 5341, 5343)
    -- Адаптированность
    LEFT JOIN VALL V2379 ON V2379.OBJ_ID = L57.OBJ_ID AND V2379.PARAM_ID = 2379 AND V2379.IS_DEL = 0
    JOIN LINKS L400 ON L400.PARENT_ID = L57.OBJ_ID AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL AND (L400.OBJ_ID = :I$PLAN_ID OR :I$PLAN_ID IS NULL)
    -- Только действующие
    JOIN VALL V3013 ON V3013.OBJ_ID = L400.OBJ_ID AND V3013.PARAM_ID = 3013 AND V3013.IS_DEL = 0 AND V3013.LISTVAL_ID = 11715
    -- Не проверяем заочную и очно-заочную форму
    LEFT JOIN VALL V3015 ON V3015.OBJ_ID = L400.OBJ_ID AND V3015.PARAM_ID = 3015 AND V3015.IS_DEL = 0
    LEFT JOIN VALL V3014 ON V3014.OBJ_ID = L400.OBJ_ID AND V3014.PARAM_ID = 3014 AND V3014.IS_DEL = 0
    LEFT JOIN VALL V3016 ON V3016.OBJ_ID = L400.OBJ_ID AND V3016.PARAM_ID = 3016 AND V3016.IS_DEL = 0
    LEFT JOIN VALL V3022 ON V3022.OBJ_ID = L400.OBJ_ID AND V3022.PARAM_ID = 3022 AND V3022.IS_DEL = 0
    LEFT JOIN VALL V3112 ON V3112.OBJ_ID = L400.OBJ_ID AND V3112.PARAM_ID = 3112 AND V3112.IS_DEL = 0
    WHERE L69.PARENT_ID = :V$OU_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL
      AND (V2379.LISTVAL_ID IS NULL OR V2379.LISTVAL_ID = 11187) -- не адаптированные
      AND (V3015.LISTVAL_ID IS NULL OR V3015.LISTVAL_ID = 153) -- очная форма
      AND (V3016.LISTVAL_ID IS NULL OR V3016.LISTVAL_ID = 5465) -- групповой
      AND (V3022.LISTVAL_ID IS NULL OR V3022.LISTVAL_ID = 3) -- не ВД
    ORDER BY 2, 1
    INTO :V$PLAN_ID, :V$LEVEL_ID, :V$STD_ID, :V$PROFILE_ID, :V$PY
  DO
  BEGIN

    VAL = '>> ' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$PLAN_ID));
    SUSPEND;

    V$SRC_PLAN_ID5 = NULL;
    V$SRC_PLAN_ID6 = NULL;
    V$SRC_PROFILE_ID = NULL;

    -- Ищем эталонный учебный план в шаблонах - он тут непременно должен быть (выборка идет по уровню образования и номеру стандарта)
    SELECT FIRST 1 L400.OBJ_ID
    FROM LINKS L400
    JOIN VALL V3345 ON V3345.OBJ_ID = L400.OBJ_ID AND V3345.PARAM_ID = 3345 AND V3345.IS_DEL = 0 AND V3345.LISTVAL_ID = :V$LEVEL_ID
    LEFT JOIN VALL V3014 ON V3014.OBJ_ID = L400.OBJ_ID AND V3014.PARAM_ID = 3014 AND V3014.IS_DEL = 0
    JOIN VALL V3347 ON V3347.OBJ_ID = L400.OBJ_ID AND V3347.PARAM_ID = 3347 AND V3347.IS_DEL = 0 AND V3347.LISTVAL_ID = 2
    JOIN VALL V3112 ON V3112.OBJ_ID = L400.OBJ_ID AND V3112.PARAM_ID = 3112 AND V3112.IS_DEL = 0 AND V3112.LISTVAL_ID = 10955
    LEFT JOIN VALL V3346 ON V3346.OBJ_ID = L400.OBJ_ID AND V3346.PARAM_ID = 3346 AND V3346.IS_DEL = 0
    WHERE L400.PARENT_ID = 258 AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL AND
      (:V$STD_ID IS NULL OR V3014.LISTVAL_ID = :V$STD_ID) AND
      (:V$STD_ID NOT IN (13452, 14184) OR V3346.LISTVAL_ID = 11718 OR V3346.LISTVAL_ID IS NULL) AND
      (L400.REASON_ID IS NULL OR L400.REASON_ID <= :V$PY)
    ORDER BY L400.REASON_ID DESC NULLS LAST, V3346.LISTVAL_ID NULLS FIRST
    INTO :V$SRC_PLAN_ID5;

    SELECT FIRST 1 L400.OBJ_ID
    FROM LINKS L400
    JOIN VALL V3345 ON V3345.OBJ_ID = L400.OBJ_ID AND V3345.PARAM_ID = 3345 AND V3345.IS_DEL = 0 AND V3345.LISTVAL_ID = :V$LEVEL_ID
    LEFT JOIN VALL V3014 ON V3014.OBJ_ID = L400.OBJ_ID AND V3014.PARAM_ID = 3014 AND V3014.IS_DEL = 0
    JOIN VALL V3347 ON V3347.OBJ_ID = L400.OBJ_ID AND V3347.PARAM_ID = 3347 AND V3347.IS_DEL = 0 AND V3347.LISTVAL_ID = 2
    JOIN VALL V3112 ON V3112.OBJ_ID = L400.OBJ_ID AND V3112.PARAM_ID = 3112 AND V3112.IS_DEL = 0 AND V3112.LISTVAL_ID = 10955
    LEFT JOIN VALL V3346 ON V3346.OBJ_ID = L400.OBJ_ID AND V3346.PARAM_ID = 3346 AND V3346.IS_DEL = 0
    WHERE L400.PARENT_ID = 258 AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL AND
      (:V$STD_ID IS NULL OR V3014.LISTVAL_ID = :V$STD_ID) AND
      (:V$STD_ID NOT IN (13452, 14184) OR V3346.LISTVAL_ID = 11719 OR V3346.LISTVAL_ID IS NULL) AND
      (L400.REASON_ID IS NULL OR L400.REASON_ID <= :V$PY)
    ORDER BY L400.REASON_ID DESC NULLS LAST, V3346.LISTVAL_ID NULLS FIRST
    INTO :V$SRC_PLAN_ID6;

    -- Если не нашелся шаблон для нужного сочетания - берем его же по ФОП
    IF(V$SRC_PLAN_ID5 IS NULL) THEN BEGIN
      IF(V$STD_ID = 11721) THEN V$STD_ID = 14184; -- 13452;

      SELECT FIRST 1 L400.OBJ_ID
      FROM LINKS L400
      JOIN VALL V3345 ON V3345.OBJ_ID = L400.OBJ_ID AND V3345.PARAM_ID = 3345 AND V3345.IS_DEL = 0 AND V3345.LISTVAL_ID = :V$LEVEL_ID
      LEFT JOIN VALL V3014 ON V3014.OBJ_ID = L400.OBJ_ID AND V3014.PARAM_ID = 3014 AND V3014.IS_DEL = 0
      JOIN VALL V3347 ON V3347.OBJ_ID = L400.OBJ_ID AND V3347.PARAM_ID = 3347 AND V3347.IS_DEL = 0 AND V3347.LISTVAL_ID = 2
      JOIN VALL V3112 ON V3112.OBJ_ID = L400.OBJ_ID AND V3112.PARAM_ID = 3112 AND V3112.IS_DEL = 0 AND V3112.LISTVAL_ID = 10955
      WHERE L400.PARENT_ID = 258 AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL
        AND (:V$STD_ID IS NULL OR V3014.LISTVAL_ID = :V$STD_ID)
      INTO :V$SRC_PLAN_ID5;

      V$SRC_PLAN_ID6 = V$SRC_PLAN_ID5;
    END

    -- Проверить, точно ли сюда не будут попадать другие виды ОУ
    IF(V$STD_ID IS NULL) THEN BEGIN
      EXCEPTION DATA_ERROR 'Для учебного плана "' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$PLAN_ID)) ||
        '" не задан образовательный стандарт';
    END

    IF(V$SRC_PLAN_ID5 IS NULL) THEN BEGIN
      EXCEPTION DATA_ERROR 'Не найден шаблон для учебного плана "' ||
        (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$PLAN_ID)) || '" ' ||
        'Проверьте, что правильно указан образовательный стандарт и заполнены все поля УП.';
    END

    -- Находим объект (маркированный как удаленный), соответствующий этому УП и шаблону
    V$OBJ_ID = NULL;
    V$REF_ID = NULL;
    SELECT FIRST 1 L310.LINK_ID, L310.OBJ_ID, V2505.VAL
    FROM LINKS L310
    JOIN VALR V2504 ON V2504.OBJ_ID = L310.OBJ_ID AND V2504.PARAM_ID = 2504 AND V2504.IS_DEL = 0 AND V2504.VAL = :V$PLAN_ID
    JOIN VALR V2505 ON V2505.OBJ_ID = L310.OBJ_ID AND V2505.PARAM_ID = 2505 AND V2505.IS_DEL = 0
    WHERE L310.PARENT_ID = :V$MON_ID AND L310.OBJ_TYPE_ID = 310
    INTO :V$LINK_ID, :V$OBJ_ID, :V$REF_ID;

    IF(V$OBJ_ID IS NULL) THEN
    BEGIN
      -- Если такого нет - создаем его
      SELECT OBJ_ID FROM OBJECT_ADD(:V$MON_ID, 310) INTO :V$OBJ_ID;
      SELECT 1 FROM VAL_ADD(2504, :V$OBJ_ID, :V$PLAN_ID) INTO :N;
    END
    ELSE
    BEGIN
      -- Если есть - восстанавливаем из удаленных
      UPDATE LINKS SET DATE_DEL = NULL WHERE LINK_ID = :V$LINK_ID;
    END
    -- Заполняем ссылку на контрольный план
    IF(COALESCE(V$REF_ID, 0) <> V$SRC_PLAN_ID5) THEN SELECT 1 FROM VAL_ADD(2505, :V$OBJ_ID, :V$SRC_PLAN_ID5) INTO :N;

    VAL = 'Эталонный план ' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$SRC_PLAN_ID5));
    SUSPEND;

    -- Все этапы образования
    -- Соответствие по предельной нагрузке
    V$LIMIT_MATCH = 1;
    FOR
      SELECT L54.OBJ_ID
      FROM LINKS L54
      JOIN VALI V383 ON V383.OBJ_ID = L54.OBJ_ID AND V383.PARAM_ID = 383 AND V383.IS_DEL = 0
      JOIN VALI V1185 ON V1185.OBJ_ID = L54.OBJ_ID AND V1185.PARAM_ID = 1185 AND V1185.IS_DEL = 0
      WHERE L54.PARENT_ID = :V$PLAN_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL AND V1185.VAL > V383.VAL
      INTO :V$OBJ_ID
    DO
    BEGIN
      V$LIMIT_MATCH = 0;
      V$LINK_ID = NULL;
      SELECT FIRST 1 L54.LINK_ID
      FROM LINKS L54
      WHERE L54.PARENT_ID = :V$MON_ID AND L54.OBJ_ID = :V$OBJ_ID
      INTO :V$LINK_ID;

      IF(V$LINK_ID IS NULL) THEN
      BEGIN
        -- Если такого нет - создаем его
        SELECT 1 FROM OBJECT_ADD_LINK(:V$MON_ID, :V$OBJ_ID, 54) INTO :N;
      END
      ELSE
      BEGIN
        -- Если есть - восстанавливаем из удаленных
        UPDATE LINKS SET DATE_DEL = NULL WHERE LINK_ID = :V$LINK_ID AND DATE_DEL IS NOT NULL;
      END
    END

    -- Среднее образование
    IF(V$LEVEL_ID = 5343) THEN
    BEGIN

      -- Ищем УП с типом "Профиль" (параметр 3112 не задан)
      SELECT FIRST 1 L400.OBJ_ID
      FROM LINKS L400
      JOIN VALL V3345 ON V3345.OBJ_ID = L400.OBJ_ID AND V3345.PARAM_ID = 3345 AND V3345.IS_DEL = 0 AND V3345.LISTVAL_ID = :V$LEVEL_ID
      LEFT JOIN VALL V3014 ON V3014.OBJ_ID = L400.OBJ_ID AND V3014.PARAM_ID = 3014 AND V3014.IS_DEL = 0
      JOIN VALL V3347 ON V3347.OBJ_ID = L400.OBJ_ID AND V3347.PARAM_ID = 3347 AND V3347.IS_DEL = 0 AND V3347.LISTVAL_ID = 2
      LEFT JOIN VALL V3112 ON V3112.OBJ_ID = L400.OBJ_ID AND V3112.PARAM_ID = 3112 AND V3112.IS_DEL = 0
      WHERE L400.PARENT_ID = 258 AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL and
        (:V$STD_ID IS NULL OR V3014.LISTVAL_ID = :V$STD_ID OR (:V$STD_ID = 13452 AND V3014.LISTVAL_ID = 11721)) AND V3112.LISTVAL_ID IS NULL
      ORDER BY V3014.LISTVAL_ID DESC
      INTO :V$SRC_PROFILE_ID;

      -- Проверяем соответствие по федеральной / обязательной части, с учетом раскрытия обществознания и естествознания
      -- Базовый перечень предметов #358
      SELECT D.N, D.SUBJECTS_MISS
      FROM PLAN_SOO_SUBJECTS_MISS(:V$PLAN_ID, :V$STD_ID) D
      INTO :N, :S1;

      IF(S1 = '') THEN
      BEGIN
        V$MATCH_FIXED = 1;
      END
      ELSE
      BEGIN
        -- Если есть нехватка предметов - формируем по ним таблицу #358
        V$MATCH_FIXED = 0;
        SELECT 1 FROM MONITORING_CURRICULUMTABL13_SET(:V$OU_ID, :V$PLAN_ID, :S1) INTO :N;
      END

      VAL = 'Недостающие предметы ' || S1;
      SUSPEND;

      -- Записываем в #359 (только лишние предметы, замены наименований предметов факультативно), обязательная часть
      SELECT D.N, D.SUBJECTS_MISS, D.SUBJECTS_MORE, D.SUBJECTS_REPLACEMENT
      FROM PLAN_DELTA_SUBJECT_GET(:V$PLAN_ID, :V$SRC_PLAN_ID5, :V$LEVEL_ID) D
      INTO :N, :S1, :S2, :S3;

      IF(S2 <> '') THEN
      SELECT 1 FROM MONITORING_CURRICULUMTABL14_SET(:V$OU_ID, :V$PLAN_ID, :S2) INTO :N;

      V$MATCH_VAR = IIF(S2 = '', 1, 0);

      VAL = 'Лишние предметы ' || S2;
      SUSPEND;

      VAL = 'Замены ' || S3;
      SUSPEND;

      -- Сверка по профильным предметам
      SELECT COUNT(DISTINCT COALESCE(V3159.VAL, S.SRC_SUBJECT_ID, S.SUBJECT_ID))
      FROM PLAN_SUBJECTS S
      LEFT JOIN VALR V3159 ON V3159.OBJ_ID = COALESCE(S.SRC_SUBJECT_ID, S.SUBJECT_ID) AND V3159.PARAM_ID = 3159 AND V3159.IS_DEL = 0
      WHERE S.DATE_DEL IS NULL AND S.PLAN_ID = :V$PLAN_ID AND S.IS_ADV = 1
      INTO :V$MATCH_PF;

      VAL = 'Углубленных предметов ' || V$MATCH_PF;
      SUSPEND;

      IF(V$PROFILE_ID = 10955) THEN
      BEGIN
        -- Универсальный профиль - по старому стандарту должно быть 0 профильных, по ФГОС оставляем пустым
        -- По ФОП требуем 2+ профильных
        IF(V$STD_ID = 11720) THEN
        BEGIN
          V$MATCH_PF = IIF(V$MATCH_PF = 0, 2, 3);
        END
        ELSE IF(V$STD_ID = 14184) THEN
        BEGIN
          V$MATCH_PF = IIF(V$MATCH_PF >= 2, 2, 3);
        END
        ELSE V$MATCH_PF = NULL;
      END
      ELSE
      BEGIN
        -- Указан какой-то тематический профиль. Должно быть не менее N предметов углубленного изучения, с ненулевыми часами ?
        -- N = 2 по старому или по ФОП, 3 по ФГОС
        IF(V$STD_ID IN (11720, 14184)) THEN V$MATCH_PF = IIF(V$MATCH_PF >= 2, 2, 3);
        ELSE V$MATCH_PF = IIF(V$MATCH_PF >= 3, 2, 3);
      END

      -- Проверка по предметам
      -- Для ФОП делаем поэтапно (кроме индпроекта), по остальным стандартам суммарно за все этапы СОО
      V$MATCH_DIV = 1;
      V$HOURS_SUM = 0;
      FOR
        SELECT DISTINCT COALESCE(S.SRC_SUBJECT_ID, S.SUBJECT_ID)
        FROM PLAN_SUBJECTS S
        JOIN PLAN_SUBJECTS S2 ON S2.OBJ_ID = S.PARENT_ID AND S2.FIELD_ID = 13303
        WHERE S.DATE_DEL IS NULL AND S.PLAN_ID = :V$PLAN_ID AND S.ROW_TYPE = 10
        INTO :V$SUBJECT_ID
      DO
      BEGIN
        V$ADV = 0;
        SELECT FIRST 1 S.IS_ADV
        FROM PLAN_SUBJECTS S
        JOIN PLAN_SUBJECTS S2 ON S2.OBJ_ID = S.PARENT_ID AND S2.FIELD_ID = 13303
        WHERE S.DATE_DEL IS NULL AND S.PLAN_ID = :V$PLAN_ID AND S.ROW_TYPE = 10 AND (S.SRC_SUBJECT_ID = :V$SUBJECT_ID OR S.SUBJECT_ID = :V$SUBJECT_ID)
        INTO :V$ADV;

        IF(V$ADV = 0) THEN V$SRC_PLAN = V$SRC_PLAN_ID5; ELSE V$SRC_PLAN = V$SRC_PROFILE_ID;

        FOR
          SELECT L54.OBJ_ID, V381.LISTVAL_ID
          FROM LINKS L54
          JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
          WHERE L54.PARENT_ID = :V$PLAN_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL AND :V$STD_ID = 14184
          UNION
          SELECT NULL, NULL
          FROM RDB$DATABASE
          WHERE :V$STD_ID <> 14184
          ORDER BY 2
          INTO :V$STAGE_ROW, :V$STAGE_ID
        DO
        BEGIN

          -- Сколько часов по факту по всем вариантам данного предмета - только по инвариантному компоненту
          -- только по этапу, иначе общие часы не сложатся
          V$HOURS_INV = 0;
          SELECT COALESCE(SUM(PL.LOAD_HOURS), 0)
          FROM PLAN_SUBJECTS S
          JOIN PLAN_SUBJECTS S2 ON S2.OBJ_ID = S.PARENT_ID AND (S2.FIELD_ID = 13303 OR S.SUBJECT_ID = 34651 OR S.SRC_SUBJECT_ID = 34651)
          JOIN PLAN_LOADS PL ON PL.DATE_DEL IS NULL AND PL.SUBJECT_ID = S.OBJ_ID AND PL.STAGE_ID IS NOT NULL
            AND (:V$STAGE_ROW IS NULL OR PL.STAGE_ID = :V$STAGE_ROW)
          WHERE S.DATE_DEL IS NULL AND S.PLAN_ID = :V$PLAN_ID AND S.ROW_TYPE = 10 AND (S.SRC_SUBJECT_ID = :V$SUBJECT_ID OR S.SUBJECT_ID = :V$SUBJECT_ID)
          INTO :V$HOURS_INV;

          V$HOURS_SUM = V$HOURS_SUM + V$HOURS_INV;
          VAL = '+ часы ' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$SUBJECT_ID)) || ' ' || V$SUBJECT_ID || ' ' || V$HOURS_INV;
          SUSPEND;

          -- Для индпроекта считаем общие часы
          IF(V$SUBJECT_ID = 34651) THEN
          SELECT COALESCE(SUM(PL.LOAD_HOURS), 0)
          FROM PLAN_SUBJECTS S
          JOIN PLAN_SUBJECTS S2 ON S2.OBJ_ID = S.PARENT_ID AND S2.FIELD_ID = 13303
          JOIN PLAN_LOADS PL ON PL.DATE_DEL IS NULL AND PL.SUBJECT_ID = S.OBJ_ID AND PL.STAGE_ID IS NOT NULL
          WHERE S.DATE_DEL IS NULL AND S.PLAN_ID = :V$PLAN_ID AND S.ROW_TYPE = 10 AND (S.SRC_SUBJECT_ID = :V$SUBJECT_ID OR S.SUBJECT_ID = :V$SUBJECT_ID)
          INTO :V$HOURS_INV;

          -- Конкретно для физики по старому стандарту подсчитываем часы в переменной части
          V$HOURS_VAR = 0;
          IF(V$SUBJECT_ID = 198 AND V$STD_ID = 11720) THEN
          SELECT COALESCE(SUM(PL.LOAD_HOURS), 0)
          FROM PLAN_SUBJECTS S
          JOIN PLAN_SUBJECTS S2 ON S2.OBJ_ID = S.PARENT_ID AND S2.FIELD_ID = 13304
          JOIN PLAN_LOADS PL ON PL.DATE_DEL IS NULL AND PL.SUBJECT_ID = S.OBJ_ID AND PL.STAGE_ID IS NOT NULL
          WHERE S.DATE_DEL IS NULL AND S.PLAN_ID = :V$PLAN_ID AND S.ROW_TYPE = 10 AND (S.SRC_SUBJECT_ID = :V$SUBJECT_ID OR S.SUBJECT_ID = :V$SUBJECT_ID)
          INTO :V$HOURS_VAR;

          -- Коррекция предмета для ФОП - ОБЖ на ЗР, технология на труд
          V$SUBJECT_ID2 = V$SUBJECT_ID;
          IF(V$PY <= 2023 AND V$STD_ID = 14184 AND V$SUBJECT_ID = 206) THEN V$SUBJECT_ID2 = 38700;
          IF(V$PY <= 2023 AND V$STD_ID = 14184 AND V$SUBJECT_ID = 200) THEN V$SUBJECT_ID2 = 38703;

          -- Сколько часов по плану
          SELECT COALESCE(SUM(PL.LOAD_HOURS), 0)
          FROM PLAN_SUBJECTS S
          JOIN PLAN_SUBJECTS S2 ON S2.OBJ_ID = S.PARENT_ID AND S2.FIELD_ID = 13303
          JOIN PLAN_LOADS PL ON PL.DATE_DEL IS NULL AND PL.SUBJECT_ID = S.OBJ_ID AND PL.STAGE_ID IS NOT NULL
          JOIN VALL V381 ON V381.OBJ_ID = PL.STAGE_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
            AND (V381.LISTVAL_ID = :V$STAGE_ID OR :V$STAGE_ID IS NULL OR S.SUBJECT_ID = 34651 OR S.SRC_SUBJECT_ID = 34651)
          WHERE S.DATE_DEL IS NULL AND S.PLAN_ID = :V$SRC_PLAN AND S.ROW_TYPE = 10 AND S.SUBJECT_ID = :V$SUBJECT_ID2
          INTO :V$SRC_HOURS_INV;

          -- Для индивидуального проекта сверяем не с шаблоном, а > 8 часов (исправлено на 0)
          IF(V$SUBJECT_ID = 34651 AND V$STD_ID < 14184) THEN
          BEGIN
            -- если часов норм, то сбрасываем в шаблонное чтобы сверка прошла как надо
            IF(V$HOURS_INV > 0) THEN V$HOURS_INV = V$SRC_HOURS_INV;
          END

          -- ФГОС-2021 профильные предметы проверяем часы не на полное совпадение, а на не меньше
          IF(V$STD_ID = 13452 AND V$ADV = 1 AND V$HOURS_INV > V$SRC_HOURS_INV) THEN V$HOURS_INV = V$SRC_HOURS_INV;
          -- ФОП Физкультура универсальный профиль часов больше чем по другим
          IF(V$STD_ID = 14184 AND V$SUBJECT_ID = 205 AND V$PROFILE_ID = 10955) THEN V$SRC_HOURS_INV = 102;
          -- ФОП проверяем на не меньше вообще все предметы - отказались от этого
          -- IF(V$STD_ID = 14184 AND V$HOURS_INV > V$SRC_HOURS_INV) THEN V$HOURS_INV = V$SRC_HOURS_INV;

          -- Если план и факт по часам не совпали - вносим запись
          -- Сводная таблица #360
          -- #1726 кроме Физики (только в непрофильном варианте и только по старому стандарту)
          IF((V$HOURS_INV <> V$SRC_HOURS_INV) AND (V$SUBJECT_ID <> 198 OR V$ADV = 1 OR V$STD_ID <> 11720)) THEN
          BEGIN
            V$MATCH_DIV = 0;
            SELECT 1
            FROM MONITORING_CURRICULUMTABL15_SET(:V$OU_ID, :V$PLAN_ID, :V$SUBJECT_ID, IIF(:V$SUBJECT_ID = 34651, NULL, :V$STAGE_ID), IIF(:V$ADV = 1, 12047, 12046), :V$HOURS_INV, :V$SRC_HOURS_INV)
            INTO :N;

            VAL = 'Несовпадение часов ' || V$SUBJECT_ID || ' СОО' || COALESCE(', этап ' || IIF(:V$SUBJECT_ID = 34651, NULL, :V$STAGE_ID), '') || ', имется ' || V$HOURS_INV || ', по шаблону ' || V$SRC_HOURS_INV;
            SUSPEND;
          END
          -- #1726 отдельно для непрофильной Физики
          ELSE IF(V$SUBJECT_ID = 198 AND V$STD_ID = 11720 AND V$ADV = 0 AND (V$HOURS_INV < 68 OR (V$HOURS_INV + V$HOURS_VAR) < 136)) THEN
          BEGIN
            V$MATCH_DIV = 0;
            SELECT 1
            FROM MONITORING_CURRICULUMTABL15_SET(:V$OU_ID, :V$PLAN_ID, :V$SUBJECT_ID, :V$STAGE_ID, IIF(:V$ADV = 1, 12047, 12046), :V$HOURS_INV + :V$HOURS_VAR, :V$SRC_HOURS_INV)
            INTO :N;

            VAL = 'Несовпадение часов ' || V$SUBJECT_ID || ' (физика), имется ' || V$HOURS_INV || ', по шаблону ' || V$SRC_HOURS_INV;
            SUSPEND;
          END

        END

      END

      -- Сравнение по V$HOURS_SUM (VAL5) потеряло актуальность

      /* -- Тут только ОБЖ
      IF(V$PROFILE_ID = 10955) THEN
      BEGIN
        SELECT DELTA, SUBJECTS_MISS
        FROM CURRICULUM_DELTA_SUBJECT_GET2(:V$PLAN_ID, NULL)
        INTO :V$DELTA_SUBJECTS, :V$MISSED_SUBJECTS;

        IF(V$DELTA_SUBJECTS = 0) THEN
        BEGIN
          --V$VAL8 = 2;
        END
        ELSE
        BEGIN
          --V$VAL8 = 3;
          -- Сводная таблица #361
          SELECT OBJ_ID FROM MONITORING_CURRICULUMTABL12_SET(:I$SCHOOL_ID, :V$PLAN_ID, :V$MISSED_SUBJECTS) INTO :V$OBJ_ID;
        END
      END */

      -- Предметы по выбору и вариативная часть, убираем индивидуальный проект - он уже посчитан
      SELECT COALESCE(SUM(PL.LOAD_HOURS), 0)
      FROM PLAN_SUBJECTS S
      JOIN PLAN_SUBJECTS S2 ON S2.OBJ_ID = S.PARENT_ID
      JOIN PLAN_LOADS PL ON PL.DATE_DEL IS NULL AND PL.SUBJECT_ID = S.OBJ_ID AND PL.STAGE_ID IS NOT NULL
      WHERE S.DATE_DEL IS NULL AND S.PLAN_ID = :V$PLAN_ID AND S.ROW_TYPE = 10 AND (S2.FIELD_ID = 13304 OR S.SUBJECT_ID = 34607 OR S.SRC_SUBJECT_ID = 34607)
        AND S.SUBJECT_ID <> 34651 AND COALESCE(S.SRC_SUBJECT_ID, 0) <> 34651
      INTO :V$HOURS_INV;

      V$HOURS_SUM = V$HOURS_SUM + V$HOURS_INV;

      -- Неделя в 10 и 11 классах должна быть одинаковая
      SELECT FIRST 1 V2837.LISTVAL_ID
      FROM LINKS L54
      JOIN VALL V2837 ON V2837.OBJ_ID = L54.OBJ_ID AND V2837.PARAM_ID = 2837 AND V2837.IS_DEL = 0
      WHERE L54.PARENT_ID = :V$PLAN_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
      INTO :V$WEEK_ID;

      IF(V$STD_ID = 11720) THEN
      BEGIN
        -- ФБУП 2004
        V$MATCH_CNT = NULL;
        V$MATCH_SUM_HOURS = NULL;

        -- наполняемость по часам
        IF((V$WEEK_ID = 11718 AND V$HOURS_SUM <= 2312) OR (V$WEEK_ID = 11719 AND V$HOURS_SUM <= 2516)) THEN
        BEGIN
          V$LIMIT_MATCH = 1;
        END
        ELSE
        BEGIN
          V$LIMIT_MATCH = 0;
        END
      END
      ELSE IF(V$STD_ID IN (11721, 13452, 14184)) THEN
      BEGIN
        -- ФГОС, ФОП
        -- Количество предметов где есть часы, >=11 (13 для ФОП), кроме индпроекта и элективов
        SELECT COUNT(DISTINCT COALESCE(V3159.VAL, S.SRC_SUBJECT_ID, S.SUBJECT_ID))
        FROM PLAN_SUBJECTS S
        JOIN PLAN_SUBJECTS S2 ON S2.OBJ_ID = S.PARENT_ID AND S2.FIELD_ID IN (13303, 13304)
        JOIN PLAN_LOADS PL ON PL.DATE_DEL IS NULL AND PL.SUBJECT_ID = S.OBJ_ID AND PL.LOAD_HOURS > 0 AND PL.STAGE_ID IS NOT NULL
        LEFT JOIN VALL V2816 ON V2816.OBJ_ID = COALESCE(S.SRC_SUBJECT_ID, S.SUBJECT_ID) AND V2816.PARAM_ID = 2816 AND V2816.IS_DEL = 0
        LEFT JOIN VALR V3159 ON V3159.OBJ_ID = COALESCE(S.SRC_SUBJECT_ID, S.SUBJECT_ID) AND V3159.PARAM_ID = 3159 AND V3159.IS_DEL = 0
        WHERE S.DATE_DEL IS NULL AND S.PLAN_ID = :V$PLAN_ID AND S.ROW_TYPE = 10 AND COALESCE(S.SRC_SUBJECT_ID, S.SUBJECT_ID) NOT IN (34607, 34651)
          AND (V2816.LISTVAL_ID IS NULL OR V2816.LISTVAL_ID = 3)
        INTO :V$MATCH_CNT;

        VAL = 'Количество предметов СОО ' || V$MATCH_CNT;
        SUSPEND;

        IF(V$STD_ID = 14184) THEN V$MATCH_CNT = IIF(V$MATCH_CNT >= 13, 2, 3);
        ELSE V$MATCH_CNT = IIF(V$MATCH_CNT >= 11, 2, 3);

        IF(V$STD_ID = 14184) THEN
        BEGIN
          IF(V$PY < 2025) THEN
            V$MATCH_SUM_HOURS = IIF(V$HOURS_SUM >= 2170 AND V$HOURS_SUM <= 2516, 2, 3);
          ELSE
            V$MATCH_SUM_HOURS = IIF(V$HOURS_SUM >= 2312 AND V$HOURS_SUM <= 2516, 2, 3);
        END
        ELSE
          V$MATCH_SUM_HOURS = IIF(V$HOURS_SUM >= 2170 AND V$HOURS_SUM <= 2590, 2, 3);

        -- наполняемость ДА для 6-дневки 37 часов, для 5-дневки 34 часа
        -- x2 поскольку счет идет за два года
        IF((V$WEEK_ID = 11718 AND V$HOURS_SUM <= 2312) OR (V$WEEK_ID = 11719 AND V$HOURS_SUM <= 2516)) THEN
        BEGIN
          V$LIMIT_MATCH = 1;
        END
        ELSE
        BEGIN
          V$LIMIT_MATCH = 0;
        END
      END

      -- Сводная таблица #357
      SELECT 1
      FROM MONITORING_CURRICULUMTABL11_SET(:V$OU_ID, :V$PLAN_ID,
        IIF(:V$MATCH_FIXED = 0, 3, 2),
        IIF(:V$MATCH_VAR = 0, 3, 2),
        :V$MATCH_PF,
        IIF(:V$MATCH_DIV = 0, 3, 2), -- Разделение базовых и профильных часов
        :V$HOURS_SUM,
        NULL,
        NULL,
        IIF(:V$LIMIT_MATCH = 0, 3, 2), -- Контроль по предельной наполняемости УП
        NULL,
        :V$STD_ID,
        :V$MATCH_CNT, -- Контроль по количеству предметов или NULL
        :V$MATCH_SUM_HOURS -- Общее количество часов или NULL
      )
      INTO :N;

      VAL = 'Обязательные предметы ' || IIF(:V$MATCH_FIXED = 0, '-', '+');
      SUSPEND;
      VAL = 'Лишние предметы ' || IIF(:V$MATCH_VAR = 0, '-', '+');
      SUSPEND;
      VAL = 'Количество профильных ' || IIF(:V$MATCH_PF IS NULL, 'NC', IIF(:V$MATCH_PF = 2, '+', '-'));
      SUSPEND;
      VAL = 'Всего часов по УП ' || V$HOURS_SUM;
      SUSPEND;
      VAL = 'Предельная наполняемость ' || IIF(:V$LIMIT_MATCH = 0, '-', '+');
      SUSPEND;
      VAL = 'Количество предметов ' || IIF(:V$MATCH_CNT = 2, '+', '-');
      SUSPEND;
      VAL = 'Общее количество часов ' || IIF(:V$MATCH_SUM_HOURS = 2, '+', '-');
      SUSPEND;

    END
    -- Начальное и общее образование
    ELSE
    BEGIN
      V$MATCH_H_TOTAL = 1;
      V$MATCH_H_INV = 1;
      V$MATCH_H_VAR = 1;
      V$HOURS_SUM = 0;
      V$SRC_HOURS_SUM = 0;

      FOR
        SELECT L54.OBJ_ID, V381.LISTVAL_ID, V2837.LISTVAL_ID, V383.VAL, V1185.VAL
        FROM LINKS L54
        JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
        LEFT JOIN VALL V2837 ON V2837.OBJ_ID = L54.OBJ_ID AND V2837.PARAM_ID = 2837 AND V2837.IS_DEL = 0
        LEFT JOIN VALI V383 ON V383.OBJ_ID = L54.OBJ_ID AND V383.PARAM_ID = 383 AND V383.IS_DEL = 0
        LEFT JOIN VALI V1185 ON V1185.OBJ_ID = L54.OBJ_ID AND V1185.PARAM_ID = 1185 AND V1185.IS_DEL = 0
        WHERE L54.PARENT_ID = :V$PLAN_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
        ORDER BY 2
        INTO :V$STAGE_ROW, :V$STAGE_ID, :V$WEEK, :V$LIMIT1, :V$LIMIT2
      DO
      BEGIN
        IF(V$WEEK IS NULL) THEN BEGIN
          EXCEPTION DATA_ERROR 'Для учебного плана "' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$PLAN_ID)) ||
            '" для одного из этапов не задана длительность учебной недели';
        END

        -- Сверяем часы суммарно
        -- Постоянная часть
        IF(V$WEEK = 11719) THEN V$SRC_PLAN = V$SRC_PLAN_ID6; ELSE V$SRC_PLAN = V$SRC_PLAN_ID5;

        SELECT COALESCE(SUM(PL.LOAD_HOURS), 0)
        FROM PLAN_SUBJECTS PS
        JOIN PLAN_SUBJECTS PS2 ON PS2.OBJ_ID = PS.PARENT_ID AND PS2.FIELD_ID IN (13303)
        JOIN PLAN_LOADS PL ON PL.DATE_DEL IS NULL AND PL.SUBJECT_ID = PS.OBJ_ID AND PL.STAGE_ID = :V$STAGE_ROW
        WHERE PS.DATE_DEL IS NULL AND PS.PLAN_ID = :V$PLAN_ID AND PS.ROW_TYPE = 10
        INTO :V$HOURS_INV;

        -- Переменная часть - элективы считаем по суммарной строке
        SELECT COALESCE(SUM(PL.LOAD_HOURS), 0)
        FROM PLAN_SUBJECTS PS
        JOIN PLAN_SUBJECTS PS2 ON PS2.OBJ_ID = PS.PARENT_ID AND PS2.FIELD_ID <> 13303
        LEFT JOIN VALL V2816 ON V2816.OBJ_ID = PS.SUBJECT_ID AND V2816.PARAM_ID = 2816 AND V2816.IS_DEL = 0
        JOIN PLAN_LOADS PL ON PL.DATE_DEL IS NULL AND PL.SUBJECT_ID = PS.OBJ_ID AND PL.STAGE_ID = :V$STAGE_ROW
        WHERE PS.DATE_DEL IS NULL AND PS.PLAN_ID = :V$PLAN_ID AND PS.ROW_TYPE = 10 AND (V2816.LISTVAL_ID IS NULL OR V2816.LISTVAL_ID = 3 OR PS.SUBJECT_ID = 34607)
        INTO :V$HOURS_VAR;

        V$HOURS = V$HOURS_INV + V$HOURS_VAR;
        V$HOURS_SUM = V$HOURS_SUM + V$HOURS;

        -- Что у нас в эталонном плане по часам
        SELECT COALESCE(SUM(PL.LOAD_HOURS), 0)
        FROM PLAN_SUBJECTS PS
        JOIN PLAN_SUBJECTS PS2 ON PS2.OBJ_ID = PS.PARENT_ID AND PS2.FIELD_ID IN (13303)
        JOIN PLAN_LOADS PL ON PL.DATE_DEL IS NULL AND PL.SUBJECT_ID = PS.OBJ_ID
        JOIN VALL V381 ON V381.OBJ_ID = PL.STAGE_ID AND V381.PARAM_ID = 381 AND V381.LISTVAL_ID = :V$STAGE_ID
        WHERE PS.DATE_DEL IS NULL AND PS.PLAN_ID = :V$SRC_PLAN AND PS.ROW_TYPE = 10
        INTO :V$SRC_HOURS_INV;

        -- Переменную часть берем константами
        SELECT HOURS
        FROM CURRICULUM_HOURS_GET_CONST(:V$LEVEL_ID, :V$STD_ID, :V$STAGE_ID, :V$WEEK, :V$PY, :V$LANG2)
        INTO :V$SRC_HOURS_VAR;

        IF(V$SRC_HOURS_VAR <> V$HOURS_VAR) THEN V$MATCH_H_VAR = 0;

        V$HOURS = V$SRC_HOURS_INV + V$SRC_HOURS_VAR;
        V$SRC_HOURS_SUM = V$SRC_HOURS_SUM + V$HOURS;

      END

      VAL = 'Всего часов ' || V$HOURS_SUM || ', по шаблону ' || V$SRC_HOURS_SUM;
      SUSPEND;

      IF(V$STD_ID = 14184) THEN -- ФОП
      BEGIN
        IF(V$PY < 2025) THEN
        BEGIN
          IF(V$LEVEL_ID = 5339 AND (V$HOURS_SUM < 2954 OR V$HOURS_SUM > 3039)) THEN V$MATCH_H_TOTAL = 0;
          IF(V$LEVEL_ID = 5341 AND (V$HOURS_SUM < 5058 OR V$HOURS_SUM > 5848)) THEN V$MATCH_H_TOTAL = 0;
        END
        ELSE
        BEGIN
          IF(V$LEVEL_ID = 5339 AND (V$HOURS_SUM < 2966 OR V$HOURS_SUM > 3345)) THEN V$MATCH_H_TOTAL = 0;
          IF(V$LEVEL_ID = 5341 AND (V$HOURS_SUM < 5338 OR V$HOURS_SUM > 5848)) THEN V$MATCH_H_TOTAL = 0;
        END
      END
      ELSE IF(V$STD_ID = 13452) THEN -- ФГОС-2021
      BEGIN
        IF(V$LEVEL_ID = 5339 AND (V$HOURS_SUM < 2954 OR V$HOURS_SUM > 3190)) THEN V$MATCH_H_TOTAL = 0;
        IF(V$LEVEL_ID = 5341 AND (V$HOURS_SUM < 5058 OR V$HOURS_SUM > 5549)) THEN V$MATCH_H_TOTAL = 0;
      END
      ELSE IF(V$STD_ID = 11721) THEN -- ФГОС
      BEGIN
        IF(V$LEVEL_ID = 5339 AND (V$HOURS_SUM < 2904 OR V$HOURS_SUM > 3345)) THEN V$MATCH_H_TOTAL = 0;
        IF(V$LEVEL_ID = 5341 AND (V$HOURS_SUM < 5267 OR V$HOURS_SUM > 6020)) THEN V$MATCH_H_TOTAL = 0;
      END
      ELSE
      BEGIN
        IF(V$SRC_HOURS_SUM <> V$HOURS_SUM) THEN V$MATCH_H_TOTAL = 0;
      END

      -- Все этапы шаблона должны быть в нашем УП, если нет - зануляем все три сверки по часам
      IF(EXISTS(
        SELECT FIRST 1 1
        FROM LINKS L54
        JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
        WHERE L54.PARENT_ID = :V$SRC_PLAN_ID5 AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
        AND NOT EXISTS (
          SELECT FIRST 1 1
          FROM LINKS L54X
          JOIN VALL V381X ON V381X.OBJ_ID = L54X.OBJ_ID AND V381X.PARAM_ID = 381 AND V381X.IS_DEL = 0 AND V381X.LISTVAL_ID = V381.LISTVAL_ID
          WHERE L54X.PARENT_ID = :V$PLAN_ID AND L54X.OBJ_TYPE_ID = 54 AND L54X.DATE_DEL IS NULL
        )
      )) THEN
      BEGIN
        VAL = 'Не все этапы внесены как в шаблоне';
        SUSPEND;
        V$MATCH_H_TOTAL = 0;
        V$MATCH_H_INV = 0;
        V$MATCH_H_VAR = 0;
      END

      -- Записываем в #306 (недостающие, лишние предметы, замены наименований предметов), только обязательная часть
      SELECT D.N, D.SUBJECTS_MISS, D.SUBJECTS_MORE, D.SUBJECTS_REPLACEMENT
      FROM PLAN_DELTA_SUBJECT_GET(:V$PLAN_ID, :V$SRC_PLAN_ID5, :V$LEVEL_ID) D
      INTO :N, :S1, :S2, :S3;

      VAL = 'Недостающие предметы ' || S1;
      SUSPEND;

      VAL = 'Лишние предметы ' || S2;
      SUSPEND;

      VAL = 'Замены ' || S3;
      SUSPEND;

      VAL = 'Число расхождений ' || N;
      SUSPEND;

      IF(N <> 0 OR S3 <> '') THEN
      SELECT 1 FROM MONITORING_CURRICULUMTABLE2_SET(:V$OU_ID, :V$PLAN_ID, :S1, :S2, :S3) INTO :V$OBJ_ID;

      -- Записываем в #307 - несоответствие по часам в конкретной пара этап-предмет
      -- Запись несоответствия часов (#307)
      FOR
        SELECT SUBJECT_ID, STAGE_ID, HOURS, CHECK_HOURS
        FROM PLAN_SUBJECT_HOURS_NEQ(:V$PLAN_ID, :V$SRC_PLAN_ID5, :V$SRC_PLAN_ID6, :V$STD_ID, :V$LEVEL_ID, :V$LANG2)
        INTO :V$SUBJECT_ID, :V$STAGE_ID, :V$HOURS_INV, :V$SRC_HOURS_INV
      DO
      BEGIN
        -- Сверяем часы по конкретным предметам
        V$MATCH_H_INV = 0;
        SELECT 1
        FROM MONITORING_CURRICULUMTABLE3_SET(:V$OU_ID, :V$PLAN_ID, :V$SUBJECT_ID, :V$STAGE_ID, :V$SRC_HOURS_INV, :V$HOURS_INV)
        INTO :V$OBJ_ID;

        VAL = 'Несовпадение часов ' || V$SUBJECT_ID || ' в этапе ' || V$STAGE_ID || ', имется ' || V$HOURS_INV || ', по шаблону ' || V$SRC_HOURS_INV;
        SUSPEND;
      END

      -- Записываем в #305 (общее количество часов и флаги соответствия)
      SELECT 1
      FROM MONITORING_CURRICULUMTABLE1_SET(:V$OU_ID, :V$PLAN_ID, :V$STD_ID, :V$LEVEL_ID, :V$SRC_PLAN_ID5, :V$HOURS_SUM,
        IIF(:V$MATCH_H_TOTAL = 0 OR :V$HOURS_SUM = 0, 3, 2),
        IIF(:N <> 0, 3, 2),
        IIF(:V$MATCH_H_INV = 0 OR :V$HOURS_SUM = 0, 3, 2),
        IIF(:V$MATCH_H_VAR = 0 OR :V$HOURS_SUM = 0, 3, 2), -- это поле удалено
        IIF(:V$LIMIT_MATCH = 0, 3, 2) -- Контроль по предельной наполняемости УП
      )
      INTO :V$OBJ_ID;

      VAL = 'Общее количество часов ' || IIF(:V$MATCH_H_TOTAL = 0 OR :V$HOURS_SUM = 0, '-', '+');
      SUSPEND;
      VAL = 'Предметы обязательной части ' || IIF(:N <> 0, '-', '+');
      SUSPEND;
      VAL = 'Часы на изучение предметов ' || IIF(:V$MATCH_H_INV = 0 OR :V$HOURS_SUM = 0, '-', '+');
      SUSPEND;
      VAL = 'Предельная наполняемость ' || IIF(:V$LIMIT_MATCH = 0, '-', '+');
      SUSPEND;

    END

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE MONITORING_PUPILS_REPORT (
    I$OBJ_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    COL_NUM SMALLINT,
    VAL VARCHAR(4000),
    DATA VARCHAR(4000),
    ORIENTATION VARCHAR(20))
AS
declare variable V$MONITORING_ID bigint;
declare variable V$CURRENT_COL integer;
BEGIN
    ORIENTATION = 'MIXED';
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1596, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1984, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END


    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1597, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1985, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END
    --------------

    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1432, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1987, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END


    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1433, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1988, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END


    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1526, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 2002, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END


    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        VAL = '';
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        VAL = '';
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END


    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1528, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 2055, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END


        FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1529, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 2056, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END


        FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1530, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 2057, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END


        FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1531, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 2058, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END


        FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1532, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 2059, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END


        FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1533, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 2060, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END


        FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1534, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 2061, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END


        FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1535, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 2062, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END


        FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1536, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 2063, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END


        FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1537, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 2064, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END


        FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1538, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 2065, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END


        FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1539, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 2066, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END


        FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1433, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1988, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END



    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        VAL = '';
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        VAL = '';
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END


        FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1513, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 2068, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END


        FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1514, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 2069, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END


        FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1515, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 2070, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END


        FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1516, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 2071, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END


        FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1517, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 2072, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END


        FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1518, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 2073, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END


        FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1519, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 2074, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END


        FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1520, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 2075, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END


        FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1521, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 2076, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END


        FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1522, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 2077, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END


        FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1524, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 2078, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END


        FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1525, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 2079, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE MONITORING_SCHOOL_LIST (
    I$REGION_ID BIGINT)
RETURNS (
    SCHOOL_ID BIGINT,
    SCHOOL_CAPTION VARCHAR(4000),
    SCHOOL_NUMBER INTEGER)
AS
BEGIN
    SELECT FIRST 1 OBJ_ID
    FROM OBJECT_PARENTS_GET(:I$REGION_ID, 112)
    INTO :I$REGION_ID;
    FOR
        SELECT L2.OBJ_ID
        FROM LINKS L111

        JOIN LINKS L2
        ON L2.PARENT_ID = L111.OBJ_ID
        AND L2.OBJ_TYPE_ID = 2
        AND L2.DATE_DEL IS NULL

        WHERE L111.PARENT_ID = :I$REGION_ID
        AND L111.OBJ_TYPE_ID = 111
        AND L111.DATE_DEL IS NULL
        INTO :SCHOOL_ID
    DO
    BEGIN
        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:SCHOOL_ID)
        INTO :SCHOOL_CAPTION;

        SELECT I
        FROM VAL_GET(:SCHOOL_ID, 17)
        INTO :SCHOOL_NUMBER;
        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE MONITORING_STAFF_REPORT (
    I$OBJ_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    COL_NUM SMALLINT,
    VAL VARCHAR(4000),
    DATA VARCHAR(4000),
    ORIENTATION VARCHAR(20))
AS
declare variable V$MONITORING_ID bigint;
declare variable V$CURRENT_COL integer;
BEGIN
    ORIENTATION = 'MIXED';

    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1541, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1541, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END

    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1542, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1542, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END

    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1544, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1544, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END

    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1546, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1546, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END

    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1547, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V FROM VAL_GET(:V$MONITORING_ID, 1547, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        SUSPEND;
    
        V$CURRENT_COL = V$CURRENT_COL + 1;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE MONITORING_TEACHER_HIDE_DOPS (
    EMPLOYEE_ID BIGINT,
    TABLE_NO SMALLINT)
RETURNS (
    DO_HIDE SMALLINT)
AS
declare variable IS_TEACHER_DOP smallint;
declare variable TEACHER_HAS_OTHER smallint;
begin
  DO_HIDE = 0;

  IS_TEACHER_DOP = 0;
  TEACHER_HAS_OTHER = 0;

  IF(TABLE_NO = 1) THEN
  BEGIN

    -- Таблица 1 - требования к образованию
    -- Изменено в соответствии с #1642

    -- Проверяем наличие должности из подгруппы "Прочие педагогические сотрудники"
    select first 1 1
    -- Сотрудник
    from LINKS L14
    -- работающий (см. список 85)
    join VALL V274 on V274.OBJ_ID = L14.OBJ_ID and V274.PARAM_ID = 274 and V274.IS_DEL = 0 and V274.LISTVAL_ID = 602
    -- Приём сотрудника на должность
    join LINKS L15 on L15.PARENT_ID = L14.OBJ_ID and L15.OBJ_TYPE_ID = 15 and L15.DATE_DEL is null
    -- дата вступления в должность
    join VALD V73 on V73.OBJ_ID = L15.OBJ_ID and V73.PARAM_ID = 73 and V73.IS_DEL = 0
     -- дата увольнения с должности (должна быть пустой)
    left join VALD V74 on V74.OBJ_ID = L15.OBJ_ID and V74.PARAM_ID = 74 and V74.IS_DEL = 0
    join VALR V69 on V69.OBJ_ID = L15.OBJ_ID and V69.PARAM_ID = 69 and V69.IS_DEL = 0
    join VALL V64 on V64.OBJ_ID = V69.VAL and V64.PARAM_ID = 64 and V64.IS_DEL = 0 and V64.LISTVAL_ID in (131) -- см. список 21
    where L14.PARENT_TYPE_ID = 2 and L14.OBJ_TYPE_ID = 14 and L14.OBJ_ID = :EMPLOYEE_ID and L14.DATE_DEL is null and V74.VAL is null
    into :IS_TEACHER_DOP;

    -- Проверяем наличие других должностей из учительской группы кроме указанной
    IF(IS_TEACHER_DOP = 1) THEN
    BEGIN

      select first 1 1
      -- Сотрудник
      from LINKS L14
      -- работающий (см. список 85)
      join VALL V274 on V274.OBJ_ID = L14.OBJ_ID and V274.PARAM_ID = 274 and V274.IS_DEL = 0 and V274.LISTVAL_ID = 602
      -- Приём сотрудника на должность
      join LINKS L15 on L15.PARENT_ID = L14.OBJ_ID and L15.OBJ_TYPE_ID = 15 and L15.DATE_DEL is null
      -- дата вступления в должность
      join VALD V73 on V73.OBJ_ID = L15.OBJ_ID and V73.PARAM_ID = 73 and V73.IS_DEL = 0
      -- дата увольнения с должности (должна быть пустой)
      left join VALD V74 on V74.OBJ_ID = L15.OBJ_ID and V74.PARAM_ID = 74 and V74.IS_DEL = 0
      join VALR V69 on V69.OBJ_ID = L15.OBJ_ID and V69.PARAM_ID = 69 and V69.IS_DEL = 0
      join VALL V64 on V64.OBJ_ID = V69.VAL and V64.PARAM_ID = 64 and V64.IS_DEL = 0 and V64.LISTVAL_ID in (98, 125, 129) -- см. список 21, без группы 131
      where L14.PARENT_TYPE_ID = 2 and L14.OBJ_TYPE_ID = 14 and L14.OBJ_ID = :EMPLOYEE_ID and L14.DATE_DEL is null and V74.VAL is null
      into :TEACHER_HAS_OTHER;

    END

    IF(IS_TEACHER_DOP = 1 AND TEACHER_HAS_OTHER = 0) THEN
    BEGIN
      /*
      -- Других педагогических должностей нет. Проверяем образование (высшее или среднее профессиональное)
      select first 1 1
      from VALL V278
      where V278.OBJ_ID = :EMPLOYEE_ID and V278.PARAM_ID = 278 and V278.IS_DEL = 0 and V278.LISTVAL_ID in (620, 622) -- см. список 87
      into :DO_HIDE;
      */
      DO_HIDE = 1;
    END

  END
  ELSE
  BEGIN

    -- Таблица 2 - требования к повышению квалификации

    -- Проверяем наличие должности "Педагог дополнительного образования"
    select first 1 1
    -- Сотрудник
    from LINKS L14
    -- работающий (см. список 85)
    join VALL V274 on V274.OBJ_ID = L14.OBJ_ID and V274.PARAM_ID = 274 and V274.IS_DEL = 0 and V274.LISTVAL_ID = 602
    -- Приём сотрудника на должность
    join LINKS L15 on L15.PARENT_ID = L14.OBJ_ID and L15.OBJ_TYPE_ID = 15 and L15.DATE_DEL is null
    -- дата вступления в должность
    join VALD V73 on V73.OBJ_ID = L15.OBJ_ID and V73.PARAM_ID = 73 and V73.IS_DEL = 0
    -- дата увольнения с должности (должна быть пустой)
    left join VALD V74 on V74.OBJ_ID = L15.OBJ_ID and V74.PARAM_ID = 74 and V74.IS_DEL = 0
    join VALR V69 on V69.OBJ_ID = L15.OBJ_ID and V69.PARAM_ID = 69 and V69.IS_DEL = 0
    join VALL V64 on V64.OBJ_ID = V69.VAL and V64.PARAM_ID = 64 and V64.IS_DEL = 0 and V64.LISTVAL_ID in (98, 125, 129, 131) -- см. список 21
    -- должность как трудовая функция = педагог дополнительного образования
    join VALL V58 on V58.OBJ_ID = V69.VAL and V58.PARAM_ID = 58 and V58.IS_DEL = 0 and V58.LISTVAL_ID = 143
    where L14.PARENT_TYPE_ID = 2 and L14.OBJ_TYPE_ID = 14 and L14.OBJ_ID = :EMPLOYEE_ID and L14.DATE_DEL is null and V74.VAL is null
    into :IS_TEACHER_DOP;

    -- Проверяем наличие других должностей из учительской группы кроме указанной
    IF(IS_TEACHER_DOP = 1) THEN
    BEGIN

      select first 1 1
      -- Сотрудник
      from LINKS L14
      -- работающий (см. список 85)
      join VALL V274 on V274.OBJ_ID = L14.OBJ_ID and V274.PARAM_ID = 274 and V274.IS_DEL = 0 and V274.LISTVAL_ID = 602
      -- Приём сотрудника на должность
      join LINKS L15 on L15.PARENT_ID = L14.OBJ_ID and L15.OBJ_TYPE_ID = 15 and L15.DATE_DEL is null
      -- дата вступления в должность
      join VALD V73 on V73.OBJ_ID = L15.OBJ_ID and V73.PARAM_ID = 73 and V73.IS_DEL = 0
      -- дата увольнения с должности (должна быть пустой)
      left join VALD V74 on V74.OBJ_ID = L15.OBJ_ID and V74.PARAM_ID = 74 and V74.IS_DEL = 0
      join VALR V69 on V69.OBJ_ID = L15.OBJ_ID and V69.PARAM_ID = 69 and V69.IS_DEL = 0
      join VALL V64 on V64.OBJ_ID = V69.VAL and V64.PARAM_ID = 64 and V64.IS_DEL = 0 and V64.LISTVAL_ID in (98, 125, 129, 131) -- см. список 21
      -- кроме "Педагог доп. образования"
      join VALL V58 on V58.OBJ_ID = V69.VAL and V58.PARAM_ID = 58 and V58.IS_DEL = 0 and V58.LISTVAL_ID <> 143
      where L14.PARENT_TYPE_ID = 2 and L14.OBJ_TYPE_ID = 14 and L14.OBJ_ID = :EMPLOYEE_ID and L14.DATE_DEL is null and V74.VAL is null
      into :TEACHER_HAS_OTHER;

    END

    -- Исключаем из проверки предподавателей подгруппы "Прочие..."
    IF(IS_TEACHER_DOP = 1 AND TEACHER_HAS_OTHER = 0) THEN
    BEGIN
      DO_HIDE = 1;
    END

  END

  SUSPEND;
end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE MONITORING_WORKLOAD_ADD
AS
declare variable V$MON_ID bigint;
declare variable V$OBJ_ID bigint;
declare variable V$BLOB_ID bigint;
BEGIN
    SELECT OBJ_ID FROM LINKS
    WHERE OBJ_TYPE_ID = 162
    AND DATE_DEL IS NULL
    INTO :V$MON_ID;

    IF ( V$MON_ID IS NOT NULL ) THEN
    BEGIN
        SELECT L.OBJ_ID
        FROM LINKS L
        
        JOIN VALS V2206
        ON V2206.PARAM_ID = 2206
        AND V2206.OBJ_ID= L.OBJ_ID
        AND V2206.IS_DEL = 0
        AND V2206.VAL LIKE 'Текущий учебный год'
        
        WHERE L.OBJ_TYPE_ID = 270
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :V$MON_ID
        INTO :V$OBJ_ID;

        IF (V$OBJ_ID IS NULL) THEN
        BEGIN
            SELECT OBJ_ID FROM OBJECT_ADD(:V$MON_ID, 270) INTO :V$OBJ_ID;
            SELECT BLOB_ID FROM VAL_ADD(2206, :V$OBJ_ID, 'Текущий учебный год') INTO :V$BLOB_ID;
        END


    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE MONITORING_YEAR_REPORT (
    I$OBJ_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    COL_NUM SMALLINT,
    VAL VARCHAR(4000),
    DATA VARCHAR(4000),
    ORIENTATION VARCHAR(20))
AS
declare variable V$MONITORING_ID bigint;
declare variable V$CURRENT_COL integer;
BEGIN
    ORIENTATION = 'HORIZONTAL';

    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 162
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        VAL = 'Текущий учебный год';
        COL_NUM = 1;
        SUSPEND;
    END

    V$CURRENT_COL = 2;
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 238
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :I$OBJ_ID
        INTO V$MONITORING_ID
    DO
    BEGIN
        SELECT V.V||' учебный год' FROM VAL_GET(:V$MONITORING_ID, 1895, 0, :I$USER_ID) V
        INTO VAL;
        COL_NUM = V$CURRENT_COL;
        V$CURRENT_COL = V$CURRENT_COL + 1;
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE MOVEMENT_VERIFY (
    I$OBJ_ID BIGINT,
    I$USER_ID BIGINT,
    FLGERR1 SMALLINT,
    FLGERR2 SMALLINT,
    FLGERR3 SMALLINT,
    FLGERR4 SMALLINT,
    FLGERR5 SMALLINT,
    FLGERR6 SMALLINT,
    FLGERR7 SMALLINT,
    FLGERR8 SMALLINT,
    FLGERR9 SMALLINT,
    FLGERR10 SMALLINT,
    FLGERR11 SMALLINT,
    FLGERR12 SMALLINT,
    FLGERR13 SMALLINT,
    FLGERR14 SMALLINT,
    FLGERR15 SMALLINT,
    FLGERR16 SMALLINT,
    FLGERR17 SMALLINT)
RETURNS (
    LINK_ID BIGINT,
    SCHOOLAR_ID BIGINT,
    LOCATION VARCHAR(1000),
    PUPIL VARCHAR(1000),
    ERROR_TEXT VARCHAR(1000))
AS
declare variable V$PRL_ID bigint;
declare variable V$TYPE_MOV smallint;
declare variable V$TEMP integer;
declare variable V$TMP integer;
declare variable V$CNT_OBJ_MOV integer;
declare variable V$DATEOLD date;
declare variable V$DATECUR date;
declare variable V$Y smallint;
declare variable V$PRL1 smallint;
declare variable V$PRL4 smallint;
declare variable V$PRL5 smallint;
declare variable V$PRL9 smallint;
declare variable V$PRL10 smallint;
declare variable V$VAL0 varchar(2);
declare variable V$VAL1 varchar(2);
declare variable LANG_CODE varchar(2);
begin
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :LANG_CODE;

  SELECT FIRST 1 CASE WHEN MAX(VLL1.LISTVAL_ID) = 40 THEN 1 ELSE 0 END
  FROM LINKS L7
  JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
  JOIN VALL VLL ON VLL.OBJ_ID = L7.OBJ_ID AND VLL.PARAM_ID = 43 AND VLL.IS_DEL = 0
  LEFT JOIN VALL VLL1 ON VLL1.OBJ_ID = L8.OBJ_ID AND VLL.LISTVAL_ID = 22 AND VLL1.PARAM_ID = 49 AND VLL1.IS_DEL = 0
  WHERE L7.PARENT_ID = :I$OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
  INTO :V$PRL4;

  SELECT FIRST 1 CASE WHEN MAX(VLL1.LISTVAL_ID) = 45 THEN 1 ELSE 0 END
  FROM LINKS L7
  JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
  JOIN VALL VLL ON VLL.OBJ_ID = L7.OBJ_ID AND VLL.PARAM_ID = 43 AND VLL.IS_DEL = 0 AND VLL.LISTVAL_ID = 26
  LEFT JOIN VALL VLL1 ON VLL1.OBJ_ID = L8.OBJ_ID AND VLL1.PARAM_ID = 49 AND VLL1.IS_DEL = 0
  WHERE L7.PARENT_ID = :I$OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
  INTO :V$PRL9;

  SELECT FIRST 1 CASE WHEN MIN(VLL1.LISTVAL_ID) = 37 THEN 1 ELSE 0 END
  FROM LINKS L7
  JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
  JOIN VALL VLL ON VLL.OBJ_ID = L7.OBJ_ID AND VLL.PARAM_ID = 43 AND VLL.IS_DEL = 0 AND VLL.LISTVAL_ID = 22
  LEFT JOIN VALL VLL1 ON VLL1.OBJ_ID = L8.OBJ_ID AND VLL1.PARAM_ID = 49 AND VLL1.IS_DEL = 0
  WHERE L7.PARENT_ID = :I$OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
  INTO :V$PRL1;

  SELECT FIRST 1 CASE WHEN MIN(VLL1.LISTVAL_ID) = 41 THEN 1 ELSE 0 END
  FROM LINKS L7
  JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
  JOIN VALL VLL ON VLL.OBJ_ID = L7.OBJ_ID AND VLL.PARAM_ID = 43 AND VLL.IS_DEL = 0 AND VLL.LISTVAL_ID = 26
  LEFT JOIN VALL VLL1 ON VLL1.OBJ_ID = L8.OBJ_ID AND VLL1.PARAM_ID = 49 AND VLL1.IS_DEL = 0
  WHERE L7.PARENT_ID = :I$OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
  INTO :V$PRL5;

  SELECT FIRST 1 CASE WHEN MIN(VLL1.LISTVAL_ID) = 46 THEN 1 ELSE 0 END
  FROM LINKS L7
  JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
  JOIN VALL VLL ON VLL.OBJ_ID = L7.OBJ_ID AND VLL.PARAM_ID = 43 AND VLL.IS_DEL = 0 AND VLL.LISTVAL_ID = 27
  LEFT JOIN VALL VLL1 ON VLL1.OBJ_ID = L8.OBJ_ID AND VLL1.PARAM_ID = 49 AND VLL1.IS_DEL = 0
  WHERE L7.PARENT_ID = :I$OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
  INTO :V$PRL10;

  V$Y = EXTRACT(YEAR FROM CURRENT_DATE);

  FOR
      SELECT 0, L9.OBJ_ID, L10.OBJ_ID, L10.LINK_ID
      FROM LINKS L7
      JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL 
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL 
      JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      WHERE L7.PARENT_ID = :I$OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
      UNION ALL
      SELECT 1, L82.OBJ_ID, L10.OBJ_ID, L10.LINK_ID
      FROM LINKS L78
      JOIN LINKS L82 ON L82.PARENT_ID = L78.OBJ_ID AND L82.OBJ_TYPE_ID = 82 AND L82.DATE_DEL IS NULL
      JOIN LINKS L10 ON L10.PARENT_ID = L82.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      WHERE L78.PARENT_ID = :I$OBJ_ID AND L78.OBJ_TYPE_ID = 78 AND L78.DATE_DEL IS NULL
      INTO :V$TYPE_MOV, :V$PRL_ID, :SCHOOLAR_ID, :LINK_ID
  DO
  BEGIN
    SELECT CAPTION FROM OBJECT_CAPTION_GET(:SCHOOLAR_ID) INTO :PUPIL;
    SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$PRL_ID) INTO :LOCATION;
    -- 1 --
    IF (FLGERR1 = 1) THEN
    BEGIN
      SELECT COUNT(VLL.LISTVAL_ID)
      FROM VALL VLL
      WHERE VLL.PARAM_ID = 78 AND VLL.OBJ_ID = :SCHOOLAR_ID AND VLL.IS_DEL = 0
      INTO :V$TEMP;
      IF ((V$TEMP = 0) AND (V$TYPE_MOV IN (0, 1))) THEN
      BEGIN
        ERROR_TEXT = 'Пустое поле «Принят(а) из»';
        SUSPEND;
      END
    END
    -- 2 --
    IF (FLGERR2 = 1) THEN
    BEGIN
      SELECT COUNT(VLL.LISTVAL_ID)
      FROM VALL VLL
      WHERE VLL.PARAM_ID = 105 AND VLL.OBJ_ID = :SCHOOLAR_ID AND VLL.IS_DEL = 0
      INTO :V$TEMP;
      IF (V$TEMP = 0 AND V$TYPE_MOV = 1) THEN
      BEGIN
        ERROR_TEXT = 'Пустое поле «Выбыл(а) в»';
        SUSPEND;
      END
    END
    -- 3 --
    IF (FLGERR3 = 1) THEN
    BEGIN
      -- такого быть уж не может
      IF (0 = 1 AND (V$TYPE_MOV IN (0, 1))) THEN
      BEGIN
        ERROR_TEXT = 'Не заполнено поле «Тип движения»';
        SUSPEND;
      END
    END
    -- 4 --
    IF (FLGERR4 = 1) THEN
    BEGIN
      -- такого быть уж не может
      IF (0 = 1 AND V$TYPE_MOV IN (0, 1)) THEN
      BEGIN
        ERROR_TEXT = 'Не заполнено поле «Дата приёма, перевода, выбытия»';
        SUSPEND;
      END
    END
    -- 5 --
    IF (FLGERR5 = 1) THEN
    BEGIN
      -- такого быть уж не может
      IF (0 = 1 AND V$TYPE_MOV IN (0, 1)) THEN
      BEGIN
        ERROR_TEXT = 'Не заполнено поле «Принят на этап обучения»';
        SUSPEND;
      END
    END
    -- 6 --
    IF (FLGERR6 = 1) THEN
    BEGIN
      -- такого быть уж не может
      IF (0 = 1 AND V$TYPE_MOV IN (0, 1)) THEN
      BEGIN
        ERROR_TEXT = 'Не заполнено поле «Принят в учебный коллектив следующего типа»';
        SUSPEND;
      END
    END
    -- 7 --
    IF (FLGERR7 = 1) THEN
    BEGIN
      -- такого быть уж не может
      IF (0 = 1 AND V$TYPE_MOV IN (0, 1)) THEN
      BEGIN
        ERROR_TEXT = 'Не заполнено поле «Наименование учебного коллектива на момент выполнения движения»';
        SUSPEND;
      END
    END
    -- 8 --
    IF (FLGERR8 = 1) THEN
    BEGIN
      -- такого быть уж не может
      IF (0 = 1 AND V$TYPE_MOV IN (0, 1)) THEN
      BEGIN
        ERROR_TEXT = 'Нет записи о прибытии';
        SUSPEND;
      END
    END
    -- 9 --
    IF (FLGERR9 = 1) THEN
    BEGIN
      -- такого быть уж не может
      IF (0 = 1 AND V$TYPE_MOV IN (0, 1)) THEN
      BEGIN
        ERROR_TEXT = 'Запись о прибытии не первая по дате';
        SUSPEND;
      END
    END
    -- 10 --
    IF (FLGERR10 = 1) THEN
    BEGIN
      -- такого быть уж не может
      IF (0 = 1 AND V$TYPE_MOV IN (1)) THEN
      BEGIN
        ERROR_TEXT = 'Нет записи о выбытии';
        SUSPEND;
      END
    END
    -- 11 --
    IF (FLGERR11 = 1) THEN
    BEGIN
      -- такого быть уж не может
      IF (0 = 1 AND V$TYPE_MOV IN (1)) THEN
      BEGIN
        ERROR_TEXT = 'Запись о выбытии не последняя по дате';
        SUSPEND;
      END
    END
    -- 12 --
    IF (FLGERR12 = 1) THEN
    BEGIN
      SELECT FIRST 1 COUNT(M.DATE_IN)
      FROM PERSON_MOVEMENTS M
      JOIN OBJECTS O ON O.OBJ_ID = M.GROUP_ID AND M.TYPE_IN IN (9, 125, 187)
      WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :SCHOOLAR_ID
      GROUP BY M.DATE_IN
      ORDER BY 1 DESC
      INTO :V$TEMP;

      IF (:V$TEMP > 1 AND :V$TYPE_MOV IN (0, 1)) THEN
      BEGIN
        ERROR_TEXT = 'Две записи движения оформлены одним числом';
        SUSPEND;
      END
    END
    -- 13 --
    IF (FLGERR13 = 1) THEN
    BEGIN
      SELECT COUNT(L.OBJ_ID)
      FROM LINKS L
      JOIN VALS VLS ON L.OBJ_ID = VLS.OBJ_ID AND VLS.PARAM_ID = 437 AND VLS.IS_DEL = 0 AND UPPER(VLS.SVAL) = UPPER(:LOCATION)
      JOIN VALD VD ON L.OBJ_ID = VD.OBJ_ID AND VD.PARAM_ID = 433 AND VD.IS_DEL = 0
        AND VD.VAL = (
          SELECT FIRST 1 MAX(M.DATE_IN)
          FROM PERSON_MOVEMENTS M
          JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
          WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :SCHOOLAR_ID
        )
      WHERE L.PARENT_ID = :SCHOOLAR_ID AND L.OBJ_TYPE_ID = 76 AND L.DATE_DEL IS NULL
      INTO :V$TEMP;
      IF (V$TEMP = 0 AND V$TYPE_MOV = 0) THEN
      BEGIN
        ERROR_TEXT = 'Учебный коллектив не соответствует текущему';
        SUSPEND;
      END
    END
    -- 14 --
    IF (FLGERR14 = 1) THEN
    BEGIN
      FOR
          SELECT M.DATE_IN
          FROM PERSON_MOVEMENTS M
          JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
          WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :SCHOOLAR_ID
          UNION
          SELECT M.DATE_OUT
          FROM PERSON_MOVEMENTS M
          JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
          WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :SCHOOLAR_ID AND M.DATE_OUT IS NOT NULL
          ORDER BY 1
          INTO :V$DATECUR
      DO
      BEGIN
        IF (V$DATEOLD IS NULL) THEN
        BEGIN
          V$DATEOLD = V$DATECUR;
        END
        ELSE
        BEGIN
          V$TEMP = V$DATECUR - V$DATEOLD;
          V$DATEOLD = V$DATECUR;
          IF (V$TEMP > 500 AND V$TYPE_MOV IN (0, 1)) THEN
          BEGIN
            ERROR_TEXT = 'ПРОПУЩЕНА ЗАПИСЬ';
            SUSPEND;
          END
        END
      END
      V$DATEOLD = NULL;
      V$DATECUR = NULL;
    END
    -- 15 --
    IF (FLGERR15 = 1) THEN
    BEGIN
      FOR
          -- А если 10-11-12 класс ?!
          SELECT SUBSTRING(M.NAME_IN FROM 1 FOR 1),
                 (SELECT SUBSTRING(R.VAL FROM 1 FOR 1)
                  FROM LISTVALS LV
                  LEFT JOIN RES_GET(LV.RES_ID, :LANG_CODE) R ON 1 = 1
                  WHERE LV.LISTVAL_ID = M.STAGE_ID)
          FROM PERSON_MOVEMENTS M
          JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
          WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :SCHOOLAR_ID
          INTO :V$VAL0, :V$VAL1
      DO
      BEGIN
        IF (V$TYPE_MOV = 0 AND V$VAL0 <> V$VAL1) THEN
        BEGIN
          ERROR_TEXT = 'Неправильный этап или класс';
          SUSPEND;
        END
      END
    END
    --16--
    IF (FLGERR16 = 1) THEN
    BEGIN
      IF (((V$PRL4 = 1) OR (V$PRL9 = 1)) AND (V$TYPE_MOV = 1)) THEN
      BEGIN
        SELECT FIRST 1 M.DATE_OUT, M.REASON_OUT, M.STAGE_ID
        FROM PERSON_MOVEMENTS M
        JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
        WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :SCHOOLAR_ID AND M.DATE_OUT >= '1.06.' || :V$Y AND M.DATE_OUT <= '31.08.' || :V$Y
          AND M.REASON_IN >= 805 AND M.REASON_IN <= 810
        ORDER BY M.DATE_OUT DESC
        INTO :V$DATECUR, :V$TMP, :V$TEMP;
        IF (((V$TEMP = 40) OR (V$TEMP = 45)) AND (V$TMP <> 812) AND (V$TYPE_MOV = 1)) THEN
        BEGIN
          ERROR_TEXT = 'Тип движения должен быть «Окончил(а)», а не «Выбыл(а)»';
          SUSPEND;
        END
      END
    END
    -- 17 --
    IF (FLGERR17 = 1) THEN
    BEGIN
      IF (((V$PRL1 = 1) OR (V$PRL5 = 1) OR (V$PRL10 = 1)) AND (V$TYPE_MOV = 0) AND (CURRENT_DATE > '1.09.' || V$Y)) THEN
      BEGIN
        SELECT FIRST 1 M.DATE_IN, M.REASON_IN, M.STAGE_ID
        FROM PERSON_MOVEMENTS M
        JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
        WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :SCHOOLAR_ID AND M.DATE_IN >= '1.06.' || :V$Y AND M.DATE_OUT <= '01.09.' || :V$Y
        ORDER BY M.DATE_IN DESC
        INTO :V$DATECUR, :V$TMP, :V$TEMP;
        IF (((V$TEMP = 37) OR (V$TEMP = 41) OR (V$TEMP = 46)) AND (V$TMP <> 805) AND (V$TYPE_MOV = 0)) THEN
        BEGIN
          ERROR_TEXT = 'Тип движения должен быть «Принят(а) для начала обучения», а не «Принят для продолжения обучения»';
          SUSPEND;
        END
      END
    END
  END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE MREPORT_512_AUTO (
    I$REPORT_ID BIGINT,
    I$ROW_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$USER_ID BIGINT;
DECLARE VARIABLE V$STATUS_ID BIGINT;
DECLARE VARIABLE V$PERIOD_ID BIGINT;
DECLARE VARIABLE V$Y INTEGER;
DECLARE VARIABLE V$ID BIGINT;
DECLARE VARIABLE V$VAL FLOAT;
DECLARE VARIABLE V$I INTEGER;
DECLARE VARIABLE V$PARENT_ID BIGINT;
DECLARE VARIABLE V$PARENT_TYPE_ID BIGINT;
DECLARE VARIABLE V$BASE_LEVEL INTEGER;
DECLARE VARIABLE V$DATE1 DATE;
DECLARE VARIABLE V$DATE2 DATE;
DECLARE VARIABLE V$YY INTEGER;
DECLARE VARIABLE V$YEAR_ID BIGINT;
DECLARE VARIABLE V$PARAM_ID BIGINT;
DECLARE VARIABLE V$USERTYPE SMALLINT;
DECLARE VARIABLE V1 DOUBLE PRECISION;
DECLARE VARIABLE V2 DOUBLE PRECISION;
begin

  IF(I$USER_ID = 'Веб-администратор') THEN V$USER_ID = 1; ELSE V$USER_ID = I$USER_ID;
  --nnn проверка уровня доступа ?

  SELECT L512.OBJ_ID, V3513.LISTVAL_ID, V3512.VAL, V3511.LISTVAL_ID, LPX.PARENT_TYPE_ID, LPX.PARENT_ID
  FROM LINKS L512
  JOIN LINKS LP511 ON LP511.OBJ_ID = L512.PARENT_ID AND LP511.PARENT_TYPE_ID = 511 AND LP511.DATE_DEL IS NULL -- папка отчетов
  JOIN LINKS LPX ON LPX.OBJ_ID = LP511.PARENT_ID AND LPX.PARENT_TYPE_ID IN (2, 111, 112) AND LPX.DATE_DEL IS NULL -- владелец отчета
  LEFT JOIN VALL V3513 ON V3513.OBJ_ID = L512.OBJ_ID AND V3513.PARAM_ID = 3513 AND V3513.IS_DEL = 0
  LEFT JOIN VALI V3512 ON V3512.OBJ_ID = L512.OBJ_ID AND V3512.PARAM_ID = 3512 AND V3512.IS_DEL = 0
  LEFT JOIN VALL V3511 ON V3511.OBJ_ID = L512.OBJ_ID AND V3511.PARAM_ID = 3511 AND V3511.IS_DEL = 0
  WHERE L512.OBJ_ID = :I$REPORT_ID AND L512.DATE_DEL IS NULL AND L512.PARENT_TYPE_ID = 511 -- папка отчетов мониторинга
  INTO :V$ID, :V$STATUS_ID, :V$Y, :V$PERIOD_ID, :V$PARENT_TYPE_ID, :V$PARENT_ID;

  IF(V$ID IS NULL) THEN EXCEPTION DATA_ERROR 'Отчет не найден или был удален';
  IF(V$STATUS_ID <> 11716) THEN EXCEPTION DATA_ERROR 'Отчет можно обновлять только в статусе проекта';

  IF(V$PERIOD_ID = 18579) THEN
  BEGIN
    V$DATE1 = V$Y || '-01-01';
    V$DATE2 = V$Y || '-06-30';
  END
  ELSE
  BEGIN
    V$DATE1 = V$Y || '-07-01';
    V$DATE2 = V$Y || '-12-31';
  END

  -- Отчет можно обновлять только для подходящего уровня пользователя

  SELECT COALESCE(CAST(K.KEY_VAL AS INTEGER), 1)
  FROM KEYS K
  WHERE K.KEY_CODE = 'LEVEL'
  INTO :V$BASE_LEVEL;

  -- Нельзя обновлять отчет школьного уровня на районной или региональной базе
  IF(V$BASE_LEVEL > 1) THEN
  BEGIN
    IF(V$PARENT_TYPE_ID = 2) THEN EXCEPTION DATA_ERROR 'Отчет уровня ОУ можно пересчитывать только в базе этой ОУ';
    -- Проверяем, что уровень пользователя соответствует уровню отчета
    SELECT FIRST 1 U.USER_TYPE
    FROM USERS U
    WHERE U.USER_ID = :V$USER_ID AND U.DATE_DEL IS NULL
    INTO :V$USERTYPE;
    -- !!! TODO
  END

  TAG_NAME = 'items::json&colon;array';
  VAL = 1;
  SUSPEND;

  IF(V$PARENT_TYPE_ID = 2) THEN
  BEGIN
    -- Уровень ОУ

    SELECT LV.LISTVAL_ID, LV.COST
    FROM VALL V1236
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
    WHERE V1236.OBJ_ID = :V$PARENT_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
    INTO :V$YEAR_ID, :V$YY;

    IF(I$ROW_ID IS NULL OR I$ROW_ID = 0) THEN
    BEGIN
      -- РАЗДЕЛ: Всероссийская олимпиада
      -- 0 Участники школьного этапа 9-11
      -- + Количество
      TAG_NAME = 'items:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'items:r:index';
      VAL = 0;
      SUSPEND;
      TAG_NAME = 'items:r:value';
      SELECT COUNT(DISTINCT M.PERSON_ID)
      FROM PERSON_MOVEMENTS M
      JOIN LINKS L22 ON L22.PARENT_ID = M.PERSON_ID AND L22.OBJ_TYPE_ID = 22 AND L22.DATE_DEL IS NULL
      JOIN VALS V167 ON V167.OBJ_ID = L22.OBJ_ID AND V167.PARAM_ID = 167 AND V167.IS_DEL = 0 AND V167.SVAL = 'олимпиада'
      JOIN VALL V1819 ON V1819.OBJ_ID = L22.OBJ_ID AND V1819.PARAM_ID = 1819 AND V1819.IS_DEL = 0 AND V1819.LISTVAL_ID = 5292 -- всерос
      JOIN VALL V3533 ON V3533.OBJ_ID = L22.OBJ_ID AND V3533.PARAM_ID = 3533 AND V3533.IS_DEL = 0 AND V3533.LISTVAL_ID = 18598 -- школьный тур
      JOIN VALD V166 ON V166.OBJ_ID = L22.OBJ_ID AND V166.PARAM_ID = 166 AND V166.IS_DEL = 0 AND V166.VAL >= :V$DATE1 AND V166.VAL <= :V$DATE2
      WHERE M.DATE_DEL IS NULL AND M.GROUP_TYPE_ID = 9 AND M.DATE_IN <= :V$DATE2 AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :V$DATE1)
        AND M.STAGE_ID IN (45, 46, 47)
      INTO :V1;
      VAL = CAST(V1 AS BIGINT);
      SUSPEND;
      EXECUTE PROCEDURE MREPORT_SET_VAL(:I$REPORT_ID, 0, NULL, NULL, :V1, 0, NULL);

      -- + Всего - берем на конец периода
      TAG_NAME = 'items:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'items:r:index';
      VAL = 1;
      SUSPEND;
      TAG_NAME = 'items:r:value';
      SELECT COUNT(DISTINCT M.PERSON_ID)
      FROM PERSON_MOVEMENTS M
      WHERE M.DATE_DEL IS NULL AND M.GROUP_TYPE_ID = 9 AND M.DATE_IN <= :V$DATE2 AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :V$DATE2) AND M.STAGE_ID IN (45, 46, 47)
      INTO :V2;
      VAL = CAST(V2 AS BIGINT);
      SUSPEND;
      EXECUTE PROCEDURE MREPORT_SET_VAL(:I$REPORT_ID, 1, NULL, NULL, :V1, 0, NULL);

      IF(V1 > 0 AND V2 > 0) THEN
      BEGIN
        EXECUTE PROCEDURE MREPORT_SET_VAL(:I$REPORT_ID, 50, NULL, NULL, 100.0 * (:V1 / :V2), 0, NULL);
      END
      ELSE
      BEGIN
        EXECUTE PROCEDURE MREPORT_SET_VAL(:I$REPORT_ID, 50, NULL, NULL, NULL, 0, NULL);
      END

      -- 1 Участники районного тура 4-11 классы
      -- + Количество
      TAG_NAME = 'items:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'items:r:index';
      VAL = 100;
      SUSPEND;
      TAG_NAME = 'items:r:value';
      SELECT COUNT(DISTINCT M.PERSON_ID)
      FROM PERSON_MOVEMENTS M
      JOIN LINKS L22 ON L22.PARENT_ID = M.PERSON_ID AND L22.OBJ_TYPE_ID = 22 AND L22.DATE_DEL IS NULL
      JOIN VALS V167 ON V167.OBJ_ID = L22.OBJ_ID AND V167.PARAM_ID = 167 AND V167.IS_DEL = 0 AND V167.SVAL = 'олимпиада'
      JOIN VALL V1819 ON V1819.OBJ_ID = L22.OBJ_ID AND V1819.PARAM_ID = 1819 AND V1819.IS_DEL = 0 AND V1819.LISTVAL_ID = 5292 -- всерос
      JOIN VALL V3533 ON V3533.OBJ_ID = L22.OBJ_ID AND V3533.PARAM_ID = 3533 AND V3533.IS_DEL = 0 AND V3533.LISTVAL_ID = 18599 -- районный тур
      JOIN VALD V166 ON V166.OBJ_ID = L22.OBJ_ID AND V166.PARAM_ID = 166 AND V166.IS_DEL = 0 AND V166.VAL >= :V$DATE1 AND V166.VAL <= :V$DATE2
      WHERE M.DATE_DEL IS NULL AND M.GROUP_TYPE_ID = 9 AND M.DATE_IN <= :V$DATE2 AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :V$DATE1)
        AND M.STAGE_ID IN (40, 41, 42, 43, 44, 45, 46, 47)
      INTO :V1;
      VAL = CAST(V1 AS BIGINT);
      SUSPEND;
      EXECUTE PROCEDURE MREPORT_SET_VAL(:I$REPORT_ID, 100, NULL, NULL, :V1, 0, NULL);
      -- + Всего - берем на конец периода
      TAG_NAME = 'items:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'items:r:index';
      VAL = 101;
      SUSPEND;
      TAG_NAME = 'items:r:value';
      SELECT COUNT(DISTINCT M.PERSON_ID)
      FROM PERSON_MOVEMENTS M
      WHERE M.DATE_DEL IS NULL AND M.GROUP_TYPE_ID = 9 AND M.DATE_IN <= :V$DATE2 AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :V$DATE2)
        AND M.STAGE_ID IN (40, 41, 42, 43, 44, 45, 46, 47)
      INTO :V1;
      VAL = CAST(V2 AS BIGINT);
      SUSPEND;
      EXECUTE PROCEDURE MREPORT_SET_VAL(:I$REPORT_ID, 101, NULL, NULL, :V2, 0, NULL);

      IF(V1 > 0 AND V2 > 0) THEN
      BEGIN
        EXECUTE PROCEDURE MREPORT_SET_VAL(:I$REPORT_ID, 150, NULL, NULL, 100.0 * (:V1 / :V2), 0, NULL);
      END
      ELSE
      BEGIN
        EXECUTE PROCEDURE MREPORT_SET_VAL(:I$REPORT_ID, 150, NULL, NULL, NULL, 0, NULL);
      END

      -- 2 Участники регионального тура 4-11 классы
      -- + Количество
      TAG_NAME = 'items:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'items:r:index';
      VAL = 200;
      SUSPEND;
      TAG_NAME = 'items:r:value';
      SELECT COUNT(DISTINCT M.PERSON_ID)
      FROM PERSON_MOVEMENTS M
      JOIN LINKS L22 ON L22.PARENT_ID = M.PERSON_ID AND L22.OBJ_TYPE_ID = 22 AND L22.DATE_DEL IS NULL
      JOIN VALS V167 ON V167.OBJ_ID = L22.OBJ_ID AND V167.PARAM_ID = 167 AND V167.IS_DEL = 0 AND V167.SVAL = 'олимпиада'
      JOIN VALL V1819 ON V1819.OBJ_ID = L22.OBJ_ID AND V1819.PARAM_ID = 1819 AND V1819.IS_DEL = 0 AND V1819.LISTVAL_ID = 5292 -- всерос
      JOIN VALL V3533 ON V3533.OBJ_ID = L22.OBJ_ID AND V3533.PARAM_ID = 3533 AND V3533.IS_DEL = 0 AND V3533.LISTVAL_ID = 18600 -- региональный тур
      JOIN VALD V166 ON V166.OBJ_ID = L22.OBJ_ID AND V166.PARAM_ID = 166 AND V166.IS_DEL = 0 AND V166.VAL >= :V$DATE1 AND V166.VAL <= :V$DATE2
      WHERE M.DATE_DEL IS NULL AND M.GROUP_TYPE_ID = 9 AND M.DATE_IN <= :V$DATE2 AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :V$DATE1)
        AND M.STAGE_ID IN (40, 41, 42, 43, 44, 45, 46, 47)
      INTO :V1;
      VAL = CAST(V1 AS BIGINT);
      SUSPEND;
      EXECUTE PROCEDURE MREPORT_SET_VAL(:I$REPORT_ID, 200, NULL, NULL, :V1, 0, NULL);

      -- 3 Участники заключительного тура 4-11 классы
      -- + Количество
      TAG_NAME = 'items:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'items:r:index';
      VAL = 300;
      SUSPEND;
      TAG_NAME = 'items:r:value';
      SELECT COUNT(DISTINCT M.PERSON_ID)
      FROM PERSON_MOVEMENTS M
      JOIN LINKS L22 ON L22.PARENT_ID = M.PERSON_ID AND L22.OBJ_TYPE_ID = 22 AND L22.DATE_DEL IS NULL
      JOIN VALS V167 ON V167.OBJ_ID = L22.OBJ_ID AND V167.PARAM_ID = 167 AND V167.IS_DEL = 0 AND V167.SVAL = 'олимпиада'
      JOIN VALL V1819 ON V1819.OBJ_ID = L22.OBJ_ID AND V1819.PARAM_ID = 1819 AND V1819.IS_DEL = 0 AND V1819.LISTVAL_ID = 5292 -- всерос
      JOIN VALL V3533 ON V3533.OBJ_ID = L22.OBJ_ID AND V3533.PARAM_ID = 3533 AND V3533.IS_DEL = 0 AND V3533.LISTVAL_ID = 18601 -- заключительный тур
      JOIN VALD V166 ON V166.OBJ_ID = L22.OBJ_ID AND V166.PARAM_ID = 166 AND V166.IS_DEL = 0 AND V166.VAL >= :V$DATE1 AND V166.VAL <= :V$DATE2
      WHERE M.DATE_DEL IS NULL AND M.GROUP_TYPE_ID = 9 AND M.DATE_IN <= :V$DATE2 AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :V$DATE1)
        AND M.STAGE_ID IN (40, 41, 42, 43, 44, 45, 46, 47)
      INTO :V1;
      VAL = CAST(V1 AS BIGINT);
      SUSPEND;
      EXECUTE PROCEDURE MREPORT_SET_VAL(:I$REPORT_ID, 300, NULL, NULL, :V1, 0, NULL);

      -- 4 Количество участников олимпиады профильных классов по профильным предметам
      -- + Количество
      TAG_NAME = 'items:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'items:r:index';
      VAL = 400;
      SUSPEND;
      TAG_NAME = 'items:r:value';
      SELECT COUNT(DISTINCT M.PERSON_ID)
      FROM PERSON_MOVEMENTS M
      JOIN LINKS L22 ON L22.PARENT_ID = M.PERSON_ID AND L22.OBJ_TYPE_ID = 22 AND L22.DATE_DEL IS NULL
      JOIN VALS V167 ON V167.OBJ_ID = L22.OBJ_ID AND V167.PARAM_ID = 167 AND V167.IS_DEL = 0 AND V167.SVAL = 'олимпиада'
      JOIN VALL V1819 ON V1819.OBJ_ID = L22.OBJ_ID AND V1819.PARAM_ID = 1819 AND V1819.IS_DEL = 0 AND V1819.LISTVAL_ID = 5292 -- всерос
      JOIN VALL V3533 ON V3533.OBJ_ID = L22.OBJ_ID AND V3533.PARAM_ID = 3533 AND V3533.IS_DEL = 0 AND V3533.LISTVAL_ID = 18598 -- школьный тур
      JOIN VALD V166 ON V166.OBJ_ID = L22.OBJ_ID AND V166.PARAM_ID = 166 AND V166.IS_DEL = 0 AND V166.VAL >= :V$DATE1 AND V166.VAL <= :V$DATE2
      -- предмет олимпиады - профильный ?
      JOIN VALR V3539 ON V3539.OBJ_ID = L22.OBJ_ID AND V3539.PARAM_ID = 3539 AND V3539.IS_DEL = 0
      LEFT JOIN OD_SUBJECT_EXT(M.PERSON_ID, V3539.VAL, IIF(:V$Y = :V$YY, 1, 0), :V$YEAR_ID, :V$DATE1, :V$DATE2) IE ON 1 = 1
      WHERE M.DATE_DEL IS NULL AND M.GROUP_TYPE_ID = 9 AND M.DATE_IN <= :V$DATE2 AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :V$DATE1)
        AND M.STAGE_ID IN (40, 41, 42, 43, 44, 45, 46, 47) AND IE.IS_EXT = 1
      INTO :V1;
      VAL = CAST(V1 AS BIGINT);
      SUSPEND;
      EXECUTE PROCEDURE MREPORT_SET_VAL(:I$REPORT_ID, 400, NULL, NULL, :V1, 0, NULL);

    END

    IF(I$ROW_ID IS NULL OR I$ROW_ID = 500) THEN
    BEGIN
      -- РАЗДЕЛ: Региональные олимпиады
      -- 5 Победители или призеры профильных классов олимпиады регионального уровня по профильным предметам
      -- + Количество
      TAG_NAME = 'items:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'items:r:index';
      VAL = 500;
      SUSPEND;
      TAG_NAME = 'items:r:value';
      SELECT COUNT(DISTINCT M.PERSON_ID)
      FROM PERSON_MOVEMENTS M
      JOIN LINKS L22 ON L22.PARENT_ID = M.PERSON_ID AND L22.OBJ_TYPE_ID = 22 AND L22.DATE_DEL IS NULL
      JOIN VALS V167 ON V167.OBJ_ID = L22.OBJ_ID AND V167.PARAM_ID = 167 AND V167.IS_DEL = 0 AND V167.SVAL = 'олимпиада'
      JOIN VALL V1819 ON V1819.OBJ_ID = L22.OBJ_ID AND V1819.PARAM_ID = 1819 AND V1819.IS_DEL = 0 AND V1819.LISTVAL_ID = 5292 -- всерос
      JOIN VALL V3533 ON V3533.OBJ_ID = L22.OBJ_ID AND V3533.PARAM_ID = 3533 AND V3533.IS_DEL = 0 AND V3533.LISTVAL_ID = 18600 -- региональный тур
      JOIN VALD V166 ON V166.OBJ_ID = L22.OBJ_ID AND V166.PARAM_ID = 166 AND V166.IS_DEL = 0 AND V166.VAL >= :V$DATE1 AND V166.VAL <= :V$DATE2
      JOIN VALL V237 ON V237.OBJ_ID = L22.OBJ_ID AND V237.PARAM_ID = 237 AND V237.IS_DEL = 0 AND V237.LISTVAL_ID IN (5282, 5283) -- победитель или призер
      -- предмет олимпиады - профильный ?
      JOIN VALR V3539 ON V3539.OBJ_ID = L22.OBJ_ID AND V3539.PARAM_ID = 3539 AND V3539.IS_DEL = 0
      LEFT JOIN OD_SUBJECT_EXT(M.PERSON_ID, V3539.VAL, IIF(:V$Y = :V$YY, 1, 0), :V$YEAR_ID, :V$DATE1, :V$DATE2) IE ON 1 = 1
      WHERE M.DATE_DEL IS NULL AND M.GROUP_TYPE_ID = 9 AND M.DATE_IN <= :V$DATE2 AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :V$DATE1)
        AND M.STAGE_ID IN (40, 41, 42, 43, 44, 45, 46, 47) AND IE.IS_EXT = 1
      INTO :V1;
      VAL = CAST(V1 AS BIGINT);
      SUSPEND;
      EXECUTE PROCEDURE MREPORT_SET_VAL(:I$REPORT_ID, 500, NULL, NULL, :V1, 0, NULL);

      -- 6 Участники региональных олимпиад СПб 4-11
      -- + Количество
      TAG_NAME = 'items:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'items:r:index';
      VAL = 600;
      SUSPEND;
      TAG_NAME = 'items:r:value';
      SELECT COUNT(DISTINCT M.PERSON_ID)
      FROM PERSON_MOVEMENTS M
      JOIN LINKS L22 ON L22.PARENT_ID = M.PERSON_ID AND L22.OBJ_TYPE_ID = 22 AND L22.DATE_DEL IS NULL
      JOIN VALS V167 ON V167.OBJ_ID = L22.OBJ_ID AND V167.PARAM_ID = 167 AND V167.IS_DEL = 0 AND V167.SVAL = 'олимпиада'
      JOIN VALL V1819 ON V1819.OBJ_ID = L22.OBJ_ID AND V1819.PARAM_ID = 1819 AND V1819.IS_DEL = 0 AND V1819.LISTVAL_ID = 5289 -- СПб
      JOIN VALL V3533 ON V3533.OBJ_ID = L22.OBJ_ID AND V3533.PARAM_ID = 3533 AND V3533.IS_DEL = 0 AND V3533.LISTVAL_ID = 754 -- СПб
      JOIN VALD V166 ON V166.OBJ_ID = L22.OBJ_ID AND V166.PARAM_ID = 166 AND V166.IS_DEL = 0 AND V166.VAL >= :V$DATE1 AND V166.VAL <= :V$DATE2
      WHERE M.DATE_DEL IS NULL AND M.GROUP_TYPE_ID = 9 AND M.DATE_IN <= :V$DATE2 AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :V$DATE2)
        AND M.STAGE_ID IN (40, 41, 42, 43, 44, 45, 46, 47)
      INTO :V1;
      VAL = CAST(V1 AS BIGINT);
      SUSPEND;
      EXECUTE PROCEDURE MREPORT_SET_VAL(:I$REPORT_ID, 600, NULL, NULL, :V1, 0, NULL);
      -- + Всего - берем на конец периода
      TAG_NAME = 'items:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'items:r:index';
      VAL = 601;
      SUSPEND;
      TAG_NAME = 'items:r:value';
      SELECT COUNT(DISTINCT M.PERSON_ID)
      FROM PERSON_MOVEMENTS M
      WHERE M.DATE_DEL IS NULL AND M.GROUP_TYPE_ID = 9 AND M.DATE_IN <= :V$DATE2 AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :V$DATE2)
        AND M.STAGE_ID IN (40, 41, 42, 43, 44, 45, 46, 47)
      INTO :V2;
      VAL = CAST(V2 AS BIGINT);
      SUSPEND;
      EXECUTE PROCEDURE MREPORT_SET_VAL(:I$REPORT_ID, 601, NULL, NULL, :V2, 0, NULL);

      IF(V1 > 0 AND V2 > 0) THEN
      BEGIN
        EXECUTE PROCEDURE MREPORT_SET_VAL(:I$REPORT_ID, 650, NULL, NULL, 100.0 * (:V1 / :V2), 0, NULL);
      END
      ELSE
      BEGIN
        EXECUTE PROCEDURE MREPORT_SET_VAL(:I$REPORT_ID, 650, NULL, NULL, NULL, 0, NULL);
      END
    END

    IF(I$ROW_ID IS NULL OR I$ROW_ID = 700) THEN
    BEGIN
      -- РАЗДЕЛ: Районные олимпиады
      -- 7 Победители или призеры профильных классов олимпиады районного уровня по профильным предметам
      -- + Количество
      TAG_NAME = 'items:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'items:r:index';
      VAL = 700;
      SUSPEND;
      TAG_NAME = 'items:r:value';
      SELECT COUNT(DISTINCT M.PERSON_ID)
      FROM PERSON_MOVEMENTS M
      JOIN LINKS L22 ON L22.PARENT_ID = M.PERSON_ID AND L22.OBJ_TYPE_ID = 22 AND L22.DATE_DEL IS NULL
      JOIN VALS V167 ON V167.OBJ_ID = L22.OBJ_ID AND V167.PARAM_ID = 167 AND V167.IS_DEL = 0 AND V167.SVAL = 'олимпиада'
      JOIN VALL V1819 ON V1819.OBJ_ID = L22.OBJ_ID AND V1819.PARAM_ID = 1819 AND V1819.IS_DEL = 0 AND V1819.LISTVAL_ID = 5292 -- всерос
      JOIN VALL V3533 ON V3533.OBJ_ID = L22.OBJ_ID AND V3533.PARAM_ID = 3533 AND V3533.IS_DEL = 0 AND V3533.LISTVAL_ID = 18599 -- районный тур
      JOIN VALD V166 ON V166.OBJ_ID = L22.OBJ_ID AND V166.PARAM_ID = 166 AND V166.IS_DEL = 0 AND V166.VAL >= :V$DATE1 AND V166.VAL <= :V$DATE2
      -- предмет олимпиады - профильный ?
      JOIN VALR V3539 ON V3539.OBJ_ID = L22.OBJ_ID AND V3539.PARAM_ID = 3539 AND V3539.IS_DEL = 0
      LEFT JOIN OD_SUBJECT_EXT(M.PERSON_ID, V3539.VAL, IIF(:V$Y = :V$YY, 1, 0), :V$YEAR_ID, :V$DATE1, :V$DATE2) IE ON 1 = 1
      WHERE M.DATE_DEL IS NULL AND M.GROUP_TYPE_ID = 9 AND M.DATE_IN <= :V$DATE2 AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :V$DATE1)
        AND M.STAGE_ID IN (40, 41, 42, 43, 44, 45, 46, 47) AND IE.IS_EXT = 1
      INTO :V1;
      VAL = CAST(V1 AS BIGINT);
      SUSPEND;
      EXECUTE PROCEDURE MREPORT_SET_VAL(:I$REPORT_ID, 700, NULL, NULL, :V1, 0, NULL);
    END

    IF(I$ROW_ID IS NULL OR I$ROW_ID = 800) THEN
    BEGIN
      -- РАЗДЕЛ: Дополнительно
      -- 11 Количество педагогов, прошедших повышение квалификации...
      -- + Количество
      TAG_NAME = 'items:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'items:r:index';
      VAL = 1100;
      SUSPEND;
      TAG_NAME = 'items:r:value';
      SELECT COUNT(DISTINCT OBJ_ID)
      FROM (
        -- основная ОУ, действующие
        SELECT L14.OBJ_ID
        FROM LINKS L14
        JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
        JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0 AND V73.VAL <= :V$DATE2
        LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
        JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
        JOIN LINKS L36 ON L36.PARENT_ID = L14.OBJ_ID AND L36.OBJ_TYPE_ID = 36 AND L36.DATE_DEL IS NULL
        JOIN VALD V310 ON V310.OBJ_ID = L36.OBJ_ID AND V310.PARAM_ID = 310 AND V310.IS_DEL = 0 AND V310.VAL >= :V$DATE1 AND V310.VAL <= :V$DATE2
        JOIN VALL V1024 ON V1024.OBJ_ID = L36.OBJ_ID AND V1024.PARAM_ID = 1024 AND V1024.IS_DEL = 0 AND V1024.LISTVAL_ID = 18597
        WHERE L14.PARENT_ID = :V$PARENT_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL AND (V74.VAL IS NULL OR V74.VAL >= :V$DATE1)
        -- подразделения, действующие
        UNION
        SELECT L14.OBJ_ID
        FROM LINKS L211
        JOIN LINKS L14 ON L14.PARENT_ID = L211.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
        JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
        JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0 AND V73.VAL <= :V$DATE2
        LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
        JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
        JOIN LINKS L36 ON L36.PARENT_ID = L14.OBJ_ID AND L36.OBJ_TYPE_ID = 36 AND L36.DATE_DEL IS NULL
        JOIN VALD V310 ON V310.OBJ_ID = L36.OBJ_ID AND V310.PARAM_ID = 310 AND V310.IS_DEL = 0 AND V310.VAL >= :V$DATE1 AND V310.VAL <= :V$DATE2
        JOIN VALL V1024 ON V1024.OBJ_ID = L36.OBJ_ID AND V1024.PARAM_ID = 1024 AND V1024.IS_DEL = 0 AND V1024.LISTVAL_ID = 18597
        WHERE L211.PARENT_ID = :V$PARENT_ID AND L211.OBJ_TYPE_ID = 211 AND L211.DATE_DEL IS NULL AND (V74.VAL IS NULL OR V74.VAL >= :V$DATE1)
        -- уволенные
        UNION
        SELECT L14.OBJ_ID
        FROM LINKS L84
        JOIN LINKS L14 ON L14.PARENT_ID = L84.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
        JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
        JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0 AND V73.VAL <= :V$DATE2
        LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
        JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
        JOIN LINKS L36 ON L36.PARENT_ID = L14.OBJ_ID AND L36.OBJ_TYPE_ID = 36 AND L36.DATE_DEL IS NULL
        JOIN VALD V310 ON V310.OBJ_ID = L36.OBJ_ID AND V310.PARAM_ID = 310 AND V310.IS_DEL = 0 AND V310.VAL >= :V$DATE1 AND V310.VAL <= :V$DATE2
        JOIN VALL V1024 ON V1024.OBJ_ID = L36.OBJ_ID AND V1024.PARAM_ID = 1024 AND V1024.IS_DEL = 0 AND V1024.LISTVAL_ID = 18597
        WHERE L84.PARENT_ID = :V$PARENT_ID AND L84.OBJ_TYPE_ID = 84 AND L84.DATE_DEL IS NULL AND (V74.VAL IS NULL OR V74.VAL >= :V$DATE1)
      )
      INTO :V1;
      VAL = CAST(V1 AS BIGINT);
      SUSPEND;
      EXECUTE PROCEDURE MREPORT_SET_VAL(:I$REPORT_ID, 1100, NULL, NULL, :V1, 0, NULL);
    END

  END
  ELSE
  BEGIN
    -- Уровень района или региона
    -- Тут может быть только глобальное безусловное обновление, идем по показателям
    FOR
      SELECT V.ID
      FROM STR_TO_ID_LIST('0,100,200,300,400,500,600,700,800,900,1000,1100') V
      INTO :V$PARAM_ID
    DO
    BEGIN
      -- Основное значение есть всегда
      V1 = NULL;
      V2 = NULL;
      SELECT SUM(D.RATE_VALUE)
      FROM LINKS L
      JOIN LINKS L511 ON L511.PARENT_ID = L.OBJ_ID AND L511.OBJ_TYPE_ID = 511 AND L511.DATE_DEL IS NULL
      JOIN LINKS L511X ON L511X.PARENT_ID = L511.OBJ_ID AND L511X.OBJ_TYPE_ID = 511 AND L511X.DATE_DEL IS NULL -- подпапка по типу отчета
      JOIN LINKS L512 ON L512.PARENT_ID = L511X.OBJ_ID AND L512.OBJ_TYPE_ID = 512 AND L512.DATE_DEL IS NULL -- отчет мониторинга
      JOIN VALL V3513 ON V3513.OBJ_ID = L512.OBJ_ID AND V3513.PARAM_ID = 3513 AND V3513.IS_DEL = 0 AND V3513.LISTVAL_ID = 11715
      JOIN VALI V3512 ON V3512.OBJ_ID = L512.OBJ_ID AND V3512.PARAM_ID = 3512 AND V3512.IS_DEL = 0 AND V3512.VAL = :V$Y
      JOIN VALL V3511 ON V3511.OBJ_ID = L512.OBJ_ID AND V3511.PARAM_ID = 3511 AND V3511.IS_DEL = 0 AND V3511.LISTVAL_ID = :V$PERIOD_ID
      JOIN MREPORT_DATA D ON D.REPORT_ID = L512.OBJ_ID AND D.FIELD_ID = :V$PARAM_ID AND D.DATE_DEL IS NULL
      WHERE L.PARENT_ID = :V$PARENT_ID AND L.OBJ_TYPE_ID IN (2, 111) AND L.DATE_DEL IS NULL
      INTO :V1;
      TAG_NAME = 'items:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'items:r:index';
      VAL = V$PARAM_ID;
      SUSPEND;
      TAG_NAME = 'items:r:value';
      VAL = CAST(V1 AS BIGINT);
      SUSPEND;
      EXECUTE PROCEDURE MREPORT_SET_VAL(:I$REPORT_ID, :V$PARAM_ID + 0, NULL, NULL, :V1, 0, NULL);

      -- Дальше только если строка с процентовками - убрали, теперь всегда
      -- IF(V$PARAM_ID IN (0, 600, 900, 1100)) THEN
      IF(1 = 1) THEN
      BEGIN
        SELECT SUM(D.RATE_VALUE)
        FROM LINKS L
        JOIN LINKS L511 ON L511.PARENT_ID = L.OBJ_ID AND L511.OBJ_TYPE_ID = 511 AND L511.DATE_DEL IS NULL
        JOIN LINKS L511X ON L511X.PARENT_ID = L511.OBJ_ID AND L511X.OBJ_TYPE_ID = 511 AND L511X.DATE_DEL IS NULL -- подпапка по типу отчета
        JOIN LINKS L512 ON L512.PARENT_ID = L511X.OBJ_ID AND L512.OBJ_TYPE_ID = 512 AND L512.DATE_DEL IS NULL -- отчет мониторинга
        JOIN VALL V3513 ON V3513.OBJ_ID = L512.OBJ_ID AND V3513.PARAM_ID = 3513 AND V3513.IS_DEL = 0 AND V3513.LISTVAL_ID = 11715
        JOIN VALI V3512 ON V3512.OBJ_ID = L512.OBJ_ID AND V3512.PARAM_ID = 3512 AND V3512.IS_DEL = 0 AND V3512.VAL = :V$Y
        JOIN VALL V3511 ON V3511.OBJ_ID = L512.OBJ_ID AND V3511.PARAM_ID = 3511 AND V3511.IS_DEL = 0 AND V3511.LISTVAL_ID = :V$PERIOD_ID
        JOIN MREPORT_DATA D ON D.REPORT_ID = L512.OBJ_ID AND D.FIELD_ID = :V$PARAM_ID + 1 AND D.DATE_DEL IS NULL
        WHERE L.PARENT_ID = :V$PARENT_ID AND L.OBJ_TYPE_ID IN (2, 111) AND L.DATE_DEL IS NULL
        INTO :V2;
        TAG_NAME = 'items:r';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'items:r:index';
        VAL = V$PARAM_ID + 1;
        SUSPEND;
        TAG_NAME = 'items:r:value';
        VAL = CAST(V2 AS BIGINT);
        SUSPEND;

        EXECUTE PROCEDURE MREPORT_SET_VAL(:I$REPORT_ID, :V$PARAM_ID + 1, NULL, NULL, :V2, 0, NULL);

        TAG_NAME = 'items:r';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'items:r:index';
        VAL = V$PARAM_ID + 50;
        SUSPEND;
        TAG_NAME = 'items:r:value';
        IF(V1 > 0 AND V2 > 0) THEN
        BEGIN
          EXECUTE PROCEDURE MREPORT_SET_VAL(:I$REPORT_ID, :V$PARAM_ID + 50, NULL, NULL, 100.0 * (:V1 / :V2), 0, NULL);
          VAL = CAST(100.0 * (:V1 / :V2) AS NUMERIC(18, 2));
        END
        ELSE
        BEGIN
          EXECUTE PROCEDURE MREPORT_SET_VAL(:I$REPORT_ID, :V$PARAM_ID + 50, NULL, NULL, NULL, 0, NULL);
          VAL = NULL;
        END
        SUSPEND;
      END
    END

    -- Отдельно - показатель достоверности, сохраняем в параметре 99
    -- нас интересует сколько именно объектов вообще есть в статусе готовности
    SELECT COUNT(*), SUM(IIF(EXISTS(
      SELECT FIRST 1 1
      FROM LINKS L511
      JOIN LINKS L511X ON L511X.PARENT_ID = L511.OBJ_ID AND L511X.OBJ_TYPE_ID = 511 AND L511X.DATE_DEL IS NULL -- подпапка по типу отчета
      JOIN LINKS L512 ON L512.PARENT_ID = L511X.OBJ_ID AND L512.OBJ_TYPE_ID = 512 AND L512.DATE_DEL IS NULL -- отчет мониторинга
      JOIN VALL V3513 ON V3513.OBJ_ID = L512.OBJ_ID AND V3513.PARAM_ID = 3513 AND V3513.IS_DEL = 0 AND V3513.LISTVAL_ID = 11715
      JOIN VALI V3512 ON V3512.OBJ_ID = L512.OBJ_ID AND V3512.PARAM_ID = 3512 AND V3512.IS_DEL = 0 AND V3512.VAL = :V$Y
      JOIN VALL V3511 ON V3511.OBJ_ID = L512.OBJ_ID AND V3511.PARAM_ID = 3511 AND V3511.IS_DEL = 0 AND V3511.LISTVAL_ID = :V$PERIOD_ID
      WHERE L511.PARENT_ID = L.OBJ_ID AND L511.OBJ_TYPE_ID = 511 AND L511.DATE_DEL IS NULL
    ), 1, 0))
    FROM LINKS L
    WHERE L.PARENT_ID = :V$PARENT_ID AND L.OBJ_TYPE_ID IN (2, 111) AND L.DATE_DEL IS NULL
    INTO :V2, :V1;

    TAG_NAME = 'items:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'items:r:index';
    VAL = 99;
    SUSPEND;
    TAG_NAME = 'items:r:value';
    IF(V1 > 0 AND V2 > 0) THEN
    BEGIN
      EXECUTE PROCEDURE MREPORT_SET_VAL(:I$REPORT_ID, 99, NULL, NULL, 100.0 * (:V1 / :V2), 0, NULL);
      VAL = CAST(100.0 * (:V1 / :V2) AS NUMERIC(18, 2));
    END
    ELSE
    BEGIN
      EXECUTE PROCEDURE MREPORT_SET_VAL(:I$REPORT_ID, 99, NULL, NULL, NULL, 0, NULL);
      VAL = 0;
    END
    SUSPEND;

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE MREPORT_512_DTL (
    I$REPORT_ID BIGINT,
    I$ROW_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$USER_ID BIGINT;
DECLARE VARIABLE V$STATUS_ID BIGINT;
DECLARE VARIABLE V$PERIOD_ID BIGINT;
DECLARE VARIABLE V$Y INTEGER;
DECLARE VARIABLE V$PARENT_TYPE_ID BIGINT;
DECLARE VARIABLE V$PARENT_ID BIGINT;
DECLARE VARIABLE V$ID BIGINT;
DECLARE VARIABLE V$REPORT_ID BIGINT;
DECLARE VARIABLE S VARCHAR(1000);
DECLARE VARIABLE I2 BIGINT;
DECLARE VARIABLE V$FIELD_ID BIGINT;
DECLARE VARIABLE F FLOAT;
DECLARE VARIABLE I INTEGER;
begin

  IF(I$USER_ID = 'Веб-администратор') THEN V$USER_ID = 1; ELSE V$USER_ID = I$USER_ID;
  --nnn проверка уровня доступа ?

  SELECT L512.OBJ_ID, V3513.LISTVAL_ID, V3512.VAL, V3511.LISTVAL_ID, LPX.PARENT_TYPE_ID, LPX.PARENT_ID
  FROM LINKS L512
  JOIN LINKS LP511 ON LP511.OBJ_ID = L512.PARENT_ID AND LP511.PARENT_TYPE_ID = 511 AND LP511.DATE_DEL IS NULL -- папка отчетов
  JOIN LINKS LPX ON LPX.OBJ_ID = LP511.PARENT_ID AND LPX.PARENT_TYPE_ID IN (2, 111, 112) AND LPX.DATE_DEL IS NULL -- владелец отчета
  LEFT JOIN VALL V3513 ON V3513.OBJ_ID = L512.OBJ_ID AND V3513.PARAM_ID = 3513 AND V3513.IS_DEL = 0
  LEFT JOIN VALI V3512 ON V3512.OBJ_ID = L512.OBJ_ID AND V3512.PARAM_ID = 3512 AND V3512.IS_DEL = 0
  LEFT JOIN VALL V3511 ON V3511.OBJ_ID = L512.OBJ_ID AND V3511.PARAM_ID = 3511 AND V3511.IS_DEL = 0
  WHERE L512.OBJ_ID = :I$REPORT_ID AND L512.DATE_DEL IS NULL AND L512.PARENT_TYPE_ID = 511 -- папка отчетов мониторинга
  INTO :V$ID, :V$STATUS_ID, :V$Y, :V$PERIOD_ID, :V$PARENT_TYPE_ID, :V$PARENT_ID;

  IF(V$ID IS NULL) THEN EXCEPTION DATA_ERROR 'Отчет не найден или был удален';

  I2 = I$ROW_ID + 100;

  TAG_NAME = 'items::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L.OBJ_ID, COALESCE(V2.VAL, C1.VAL), V2X.VAL, (
      SELECT FIRST 1 L512.OBJ_ID
      FROM LINKS L511
      JOIN LINKS L511X ON L511X.PARENT_ID = L511.OBJ_ID AND L511X.OBJ_TYPE_ID = 511 AND L511X.DATE_DEL IS NULL -- подпапка по типу отчета
      JOIN LINKS L512 ON L512.PARENT_ID = L511X.OBJ_ID AND L512.OBJ_TYPE_ID = 512 AND L512.DATE_DEL IS NULL -- отчет мониторинга
      JOIN VALL V3513 ON V3513.OBJ_ID = L512.OBJ_ID AND V3513.PARAM_ID = 3513 AND V3513.IS_DEL = 0 AND V3513.LISTVAL_ID = 11715
      JOIN VALI V3512 ON V3512.OBJ_ID = L512.OBJ_ID AND V3512.PARAM_ID = 3512 AND V3512.IS_DEL = 0 AND V3512.VAL = :V$Y
      JOIN VALL V3511 ON V3511.OBJ_ID = L512.OBJ_ID AND V3511.PARAM_ID = 3511 AND V3511.IS_DEL = 0 AND V3511.LISTVAL_ID = :V$PERIOD_ID
      WHERE L511.PARENT_ID = L.OBJ_ID AND L511.OBJ_TYPE_ID = 511 AND L511.DATE_DEL IS NULL
    ) RPT_ID
    FROM LINKS L
    LEFT JOIN VALL V1 ON V1.OBJ_ID = L.OBJ_ID AND V1.PARAM_ID = 665 AND V1.IS_DEL = 0 AND L.OBJ_TYPE_ID = 111
    LEFT JOIN LISTVAL_TEXT(V1.LISTVAL_ID) C1 ON V1.LISTVAL_ID IS NOT NULL
    LEFT JOIN VALS V2 ON V2.OBJ_ID = L.OBJ_ID AND V2.PARAM_ID = 999 AND V2.IS_DEL = 0 AND L.OBJ_TYPE_ID = 2
    LEFT JOIN VALI V2X ON V2X.OBJ_ID = L.OBJ_ID AND V2X.PARAM_ID = 17 AND V2X.IS_DEL = 0 AND L.OBJ_TYPE_ID = 2
    WHERE L.PARENT_ID = :V$PARENT_ID AND L.OBJ_TYPE_ID IN (2, 111) AND L.DATE_DEL IS NULL
    ORDER BY 3, 2
    INTO :V$ID, :S, :I, :V$REPORT_ID
  DO
  BEGIN
    TAG_NAME = 'items:r';
    VAL = 1;
    SUSPEND;
    TAG_NAME = 'items:r:id';
    VAL = V$ID;
    SUSPEND;
    TAG_NAME = 'items:r:name';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'items:r:report_id';
    VAL = V$REPORT_ID;
    SUSPEND;
    -- Значения
    TAG_NAME = 'items:r:values::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT D.FIELD_ID, D.RATE_VALUE, D.RATE_INDEX
      FROM MREPORT_DATA D
      WHERE D.DATE_DEL IS NULL AND D.REPORT_ID = :V$REPORT_ID AND D.FIELD_ID >= :I$ROW_ID AND D.FIELD_ID < :I2
        AND D.FIELD_ID <> 99 -- служебное поле для значения достоверности
      ORDER BY 1
      INTO :V$FIELD_ID, :F, :I
    DO
    BEGIN
      TAG_NAME = 'items:r:values:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'items:r:values:r:index';
      VAL = V$FIELD_ID;
      SUSPEND;
      TAG_NAME = 'items:r:values:r:value';
      IF(V$FIELD_ID < 50) THEN VAL = CAST(F AS BIGINT); ELSE VAL = CAST(F AS NUMERIC(18, 2));
      SUSPEND;
      TAG_NAME = 'items:r:values:r:status';
      VAL = I;
      SUSPEND;
    END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE MREPORT_512_GET (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$USER_ID BIGINT;
DECLARE VARIABLE V$STATUS_ID BIGINT;
DECLARE VARIABLE V$S VARCHAR(1000);
DECLARE VARIABLE V$PERIOD_ID BIGINT;
DECLARE VARIABLE V$Y INTEGER;
DECLARE VARIABLE V$ID BIGINT;
DECLARE VARIABLE V$VAL FLOAT;
DECLARE VARIABLE V$I INTEGER;
DECLARE VARIABLE V$PARENT_ID BIGINT;
DECLARE VARIABLE V$PARENT_TYPE_ID BIGINT;
DECLARE VARIABLE V$BASE_LEVEL SMALLINT;
DECLARE VARIABLE V$USERTYPE SMALLINT;
DECLARE VARIABLE V$AREA_ID BIGINT;
begin

  IF(I$USER_ID = 'Веб-администратор') THEN V$USER_ID = 1; ELSE V$USER_ID = I$USER_ID;
  --nnn проверка уровня доступа ?

  SELECT L512.OBJ_ID, V3513.LISTVAL_ID, LV3513.VAL, V3512.VAL, V3511.LISTVAL_ID, LPX.PARENT_TYPE_ID, LPX.PARENT_ID
  FROM LINKS L512
  JOIN LINKS LP511 ON LP511.OBJ_ID = L512.PARENT_ID AND LP511.PARENT_TYPE_ID = 511 AND LP511.DATE_DEL IS NULL -- папка отчетов
  JOIN LINKS LPX ON LPX.OBJ_ID = LP511.PARENT_ID AND LPX.PARENT_TYPE_ID IN (2, 111, 112) AND LPX.DATE_DEL IS NULL -- владелец отчета
  LEFT JOIN VALL V3513 ON V3513.OBJ_ID = L512.OBJ_ID AND V3513.PARAM_ID = 3513 AND V3513.IS_DEL = 0
  LEFT JOIN LISTVAL_TEXT(V3513.LISTVAL_ID) LV3513 ON 1 = 1
  LEFT JOIN VALI V3512 ON V3512.OBJ_ID = L512.OBJ_ID AND V3512.PARAM_ID = 3512 AND V3512.IS_DEL = 0
  LEFT JOIN VALL V3511 ON V3511.OBJ_ID = L512.OBJ_ID AND V3511.PARAM_ID = 3511 AND V3511.IS_DEL = 0
  WHERE L512.OBJ_ID = :I$OBJ_ID AND L512.DATE_DEL IS NULL AND L512.PARENT_TYPE_ID = 511 -- папка отчетов мониторинга
  INTO :V$ID, :V$STATUS_ID, :V$S, :V$Y, :V$PERIOD_ID, :V$PARENT_TYPE_ID, :V$PARENT_ID;

  IF(V$ID IS NULL) THEN EXCEPTION DATA_ERROR 'Отчет не найден или был удален';

  TAG_NAME = 'id';
  VAL = V$ID;
  SUSPEND;
  TAG_NAME = 'year';
  VAL = V$Y;
  SUSPEND;
  TAG_NAME = 'period_id';
  VAL = V$PERIOD_ID;
  SUSPEND;
  TAG_NAME = 'status_id';
  VAL = V$STATUS_ID;
  SUSPEND;
  TAG_NAME = 'status';
  VAL = V$S;
  SUSPEND;

  -- Уровень юзера. Если лицензия не прописана, трактуем как уровень ОУ
  TAG_NAME = 'user_level';
  SELECT COALESCE(CAST(K.KEY_VAL AS INTEGER), 1)
  FROM KEYS K
  WHERE K.KEY_CODE = 'LEVEL'
  INTO :V$BASE_LEVEL;
  -- Для ОУ всегда будет тоже ОУ
  IF(V$BASE_LEVEL = 1) THEN VAL = 1;
  -- Для района всегда будет район
  ELSE IF(V$BASE_LEVEL = 1) THEN VAL = 2;
  ELSE
  BEGIN
    VAL = NULL;
    SELECT FIRST 1 U.USER_TYPE
    FROM USERS U
    WHERE U.USER_ID = :V$USER_ID AND U.DATE_DEL IS NULL
    INTO :V$USERTYPE;
    -- Классный руководитель = специалист района
    IF(V$USERTYPE = 8) THEN
    BEGIN
      -- Проверить есть ли доступ имменно к этому району
      SELECT FIRST 1 L.ROOT_OBJ_ID
      FROM LUSERS L
      WHERE L.USER_ID = :I$USER_ID AND L.ROOT_OBJ_ID IS NOT NULL
      INTO :V$AREA_ID;
      IF(V$AREA_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Для специалиста района не указан район';
      IF(V$PARENT_TYPE_ID = 112) THEN EXCEPTION DATA_ERROR 'Отказано в доступе к отчету регионального уровня';
      IF(V$PARENT_TYPE_ID = 111 AND V$PARENT_ID <> V$AREA_ID) THEN EXCEPTION DATA_ERROR 'Отказано в доступе к отчету чужого района';
      IF(V$PARENT_TYPE_ID = 2) THEN
      BEGIN
        IF(NOT EXISTS(SELECT FIRST 1 1 FROM LINKS LP111 WHERE LP111.OBJ_ID = :V$PARENT_ID AND LP111.PARENT_ID = :V$AREA_ID AND LP111.DATE_DEL IS NULL)) THEN EXCEPTION DATA_ERROR 'Отказано в доступе к отчету ОУ чужого района';
      END
      VAL = 2;
    END
    -- Все прочие случаи = регион
    ELSE
    BEGIN
      VAL = 3;
    END
  END
  SUSPEND;

  -- Уровень отчета, 1 = ОУ, 2 = район, 3 = регион
  TAG_NAME = 'level';
  IF(V$PARENT_TYPE_ID = 2) THEN VAL = 1;
  ELSE IF(V$PARENT_TYPE_ID = 111) THEN VAL = 2;
  ELSE IF(V$PARENT_TYPE_ID = 112) THEN VAL = 3;
  ELSE EXCEPTION DATA_ERROR 'Недопустимое расположение отчета';
  SUSPEND;

  -- Элементы отчета
  -- Внутри одного показателя может быть несколько срезов - столбцов таблицы отчета, храним их со сдвигом в 100 про запас (FIELD_ID = INDEX * 100 + SUBINDEX)
  -- Значения с индексом до 50 всегда целые, выше 50 - 2 знака после запятой
  TAG_NAME = 'items::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT D.FIELD_ID, D.RATE_VALUE, D.RATE_INDEX
    FROM MREPORT_DATA D
    WHERE D.DATE_DEL IS NULL AND D.REPORT_ID = :I$OBJ_ID
    ORDER BY 1
    INTO :V$ID, :V$VAL, :V$I
  DO
  BEGIN
    TAG_NAME = 'items:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'items:r:index';
    VAL = V$ID;
    SUSPEND;
    TAG_NAME = 'items:r:value';
    V$Y = MOD(V$ID, 100);
    IF(V$Y < 50) THEN VAL = CAST(V$VAL AS INTEGER); ELSE VAL = CAST(V$VAL AS NUMERIC(18, 2));
    SUSPEND;
    -- 0 = автоматически, 1 = ручной ввод
    TAG_NAME = 'items:r:status';
    VAL = V$I;
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE MREPORT_SET_VAL (
    I$OBJ_ID BIGINT,
    I$FIELD_ID BIGINT,
    I$DETAIL_ID BIGINT,
    I$DATE DATE,
    I$VALUE FLOAT,
    I$INDEX SMALLINT,
    I$USER_ID VARCHAR(40))
AS
DECLARE VARIABLE V$USER_ID BIGINT;
DECLARE VARIABLE V$STATUS_ID BIGINT;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$DD TIMESTAMP;
DECLARE VARIABLE V$VAL FLOAT;
DECLARE VARIABLE V$INDEX SMALLINT;
BEGIN

  IF(I$USER_ID = 'Веб-администратор') THEN V$USER_ID = 1; ELSE V$USER_ID = I$USER_ID;
  --nnn проверка уровня доступа ?

  SELECT V3513.LISTVAL_ID
  FROM LINKS L512
  JOIN VALL V3513 ON V3513.OBJ_ID = L512.OBJ_ID AND V3513.PARAM_ID = 3513 AND V3513.IS_DEL = 0
  WHERE L512.OBJ_ID = :I$OBJ_ID AND L512.DATE_DEL IS NULL AND L512.PARENT_TYPE_ID = 511 -- папка отчетов мониторинга
  INTO :V$STATUS_ID;

  IF(V$STATUS_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Отчет не найден или был удален';
  IF(V$STATUS_ID <> 11716) THEN EXCEPTION DATA_ERROR 'Статус отчета не допускает изменения данных';

  SELECT FIRST 1 D.OBJ_ID, D.DATE_DEL, D.RATE_VALUE, D.RATE_INDEX
  FROM MREPORT_DATA D
  WHERE D.REPORT_ID = :I$OBJ_ID AND D.FIELD_ID = :I$FIELD_ID AND
    (D.DETAIL_ID = :I$DETAIL_ID OR (D.DETAIL_ID IS NULL AND :I$DETAIL_ID IS NULL)) AND
    (D.RATE_DATE = :I$DATE OR (D.RATE_DATE IS NULL AND :I$DATE IS NULL))
  INTO :V$OBJ_ID, :V$DD, :V$VAL, :V$INDEX;

  IF(V$OBJ_ID IS NULL) THEN
  BEGIN
    -- Вообще не надо добавлять ?
    IF(I$VALUE IS NULL) THEN EXIT;

    INSERT INTO MREPORT_DATA
    (REPORT_ID, FIELD_ID, DETAIL_ID, RATE_DATE, RATE_VALUE, RATE_INDEX)
    VALUES (:I$OBJ_ID, :I$FIELD_ID, :I$DETAIL_ID, :I$DATE, :I$VALUE, :I$INDEX);
  END
  ELSE IF(V$DD IS NULL AND I$VALUE IS NULL) THEN
  BEGIN
    -- Удаляем запись
    UPDATE MREPORT_DATA
    SET DATE_DEL = CURRENT_TIMESTAMP
    WHERE OBJ_ID = :V$OBJ_ID;
  END
  ELSE IF(COALESCE(I$VALUE, -1) <> COALESCE(V$VAL, -1) OR COALESCE(I$INDEX, -1) <> COALESCE(V$INDEX, -1) OR V$DD IS NOT NULL) THEN
  BEGIN
    -- Обновляем или восстанавливаем запись
    UPDATE MREPORT_DATA
    SET DATE_DEL = NULL, RATE_VALUE = :I$VALUE, RATE_INDEX = :I$INDEX
    WHERE OBJ_ID = :V$OBJ_ID;
  END

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE MTR_DISTRICT_LIST (
    I$REGION_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    OBJ_CAPTION VARCHAR(4000))
AS
BEGIN
    FOR
        SELECT L111.OBJ_ID

        FROM LINKS L111
        WHERE L111.PARENT_ID = :I$REGION_ID
        AND L111.OBJ_TYPE_ID = 111
        AND L111.DATE_DEL IS NULL

        INTO :OBJ_ID
    DO
    BEGIN
        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:OBJ_ID)
        INTO :OBJ_CAPTION;
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE MTR_FILLING_DATA_REGION (
    I$REGION_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    COL_NUM SMALLINT,
    VAL VARCHAR(4000),
    DATA VARCHAR(4000),
    ORIENTATION VARCHAR(20))
AS
declare variable V$SCHOOL_ID bigint;
declare variable V$COUNT bigint;
BEGIN
    ORIENTATION = 'MIXED';
    DATA = NULL;
    FOR
        SELECT S.OBJ_ID,
               S.SCHOOL_NUMBER
        FROM MTR_DISTRICT_LIST(:I$REGION_ID) D
        JOIN MTR_SCHOOL_LIST(D.OBJ_ID) S ON 1=1

        UNION ALL

        SELECT OBJ_ID,
               SCHOOL_NUMBER
        FROM MTR_SCHOOL_LIST(:I$REGION_ID)
        ORDER BY 2

        INTO :V$SCHOOL_ID,
             :VAL
    DO
    BEGIN
        COL_NUM = 1;
        SUSPEND;

        SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:V$SCHOOL_ID, 1, :I$USER_ID) INTO :VAL;
        COL_NUM = 2;
        SUSPEND;
        SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:V$SCHOOL_ID, 4, :I$USER_ID) INTO :VAL;
        COL_NUM = 3;
        SUSPEND;

        SELECT COUNT(L114.OBJ_ID)
        FROM LINKS L23

        JOIN LINKS L95
        ON L95.PARENT_ID = L23.OBJ_ID
        AND L95.DATE_DEL IS NULL
        AND L95.OBJ_TYPE_ID = 95

        JOIN LINKS L114
        ON L114.PARENT_ID = L95.OBJ_ID
        AND L114.DATE_DEL IS NULL
        AND L114.OBJ_TYPE_ID = 114

        WHERE L23.PARENT_ID = :V$SCHOOL_ID
        AND L23.DATE_DEL IS NULL
        AND L23.OBJ_TYPE_ID = 23
        INTO :VAL;
        COL_NUM = 4;
        SUSPEND;

        SELECT COUNT(L114.OBJ_ID)
        FROM LINKS L23

        JOIN LINKS L95
        ON L95.PARENT_ID = L23.OBJ_ID
        AND L95.DATE_DEL IS NULL
        AND L95.OBJ_TYPE_ID = 95

        JOIN VALL VL
        ON VL.OBJ_ID = L95.OBJ_ID
        AND VL.PARAM_ID = 626
        AND VL.IS_DEL = 0
        AND VL.LISTVAL_ID = 1799

        JOIN LINKS L114
        ON L114.PARENT_ID = L95.OBJ_ID
        AND L114.DATE_DEL IS NULL
        AND L114.OBJ_TYPE_ID = 114

        WHERE L23.PARENT_ID = :V$SCHOOL_ID
        AND L23.DATE_DEL IS NULL
        AND L23.OBJ_TYPE_ID = 23
        INTO :VAL;
        COL_NUM = 5;
        SUSPEND;

        SELECT COUNT(L114.OBJ_ID)
        FROM LINKS L23

        JOIN LINKS L95
        ON L95.PARENT_ID = L23.OBJ_ID
        AND L95.DATE_DEL IS NULL
        AND L95.OBJ_TYPE_ID = 95

        JOIN VALL VL
        ON VL.OBJ_ID = L95.OBJ_ID
        AND VL.PARAM_ID = 626
        AND VL.IS_DEL = 0
        AND VL.LISTVAL_ID = 1901

        JOIN LINKS L114
        ON L114.PARENT_ID = L95.OBJ_ID
        AND L114.DATE_DEL IS NULL
        AND L114.OBJ_TYPE_ID = 114

        WHERE L23.PARENT_ID = :V$SCHOOL_ID
        AND L23.DATE_DEL IS NULL
        AND L23.OBJ_TYPE_ID = 23
        INTO :VAL;
        COL_NUM = 6;
        SUSPEND;

        SELECT COUNT(L114.OBJ_ID)
        FROM LINKS L23

        JOIN LINKS L95
        ON L95.PARENT_ID = L23.OBJ_ID
        AND L95.DATE_DEL IS NULL
        AND L95.OBJ_TYPE_ID = 95

        JOIN VALL VL
        ON VL.OBJ_ID = L95.OBJ_ID
        AND VL.PARAM_ID = 626
        AND VL.IS_DEL = 0
        AND VL.LISTVAL_ID = 1815

        JOIN LINKS L114
        ON L114.PARENT_ID = L95.OBJ_ID
        AND L114.DATE_DEL IS NULL
        AND L114.OBJ_TYPE_ID = 114

        WHERE L23.PARENT_ID = :V$SCHOOL_ID
        AND L23.DATE_DEL IS NULL
        AND L23.OBJ_TYPE_ID = 23
        INTO :VAL;
        COL_NUM = 7;
        SUSPEND;

        SELECT COUNT(L128.OBJ_ID)
        FROM LINKS L23

        JOIN LINKS L128
        ON L128.PARENT_ID = L23.OBJ_ID
        AND L128.DATE_DEL IS NULL
        AND L128.OBJ_TYPE_ID = 128

        WHERE L23.PARENT_ID = :V$SCHOOL_ID
        AND L23.DATE_DEL IS NULL
        AND L23.OBJ_TYPE_ID = 23
        INTO :VAL;
        COL_NUM = 8;
        SUSPEND;

        SELECT COUNT(L116.OBJ_ID)
        FROM LINKS L116

        WHERE L116.PARENT_ID = :V$SCHOOL_ID
        AND L116.DATE_DEL IS NULL
        AND L116.OBJ_TYPE_ID = 116
        INTO :VAL;
        COL_NUM = 9;
        SUSPEND;

        V$COUNT = 0;
        SELECT COUNT(*) + :V$COUNT FROM VALS WHERE OBJ_ID = :V$SCHOOL_ID AND PARAM_ID IN (711,712) AND VAL <> '' INTO :V$COUNT;
        SELECT COUNT(*) + :V$COUNT FROM VALF WHERE OBJ_ID = :V$SCHOOL_ID AND PARAM_ID IN (735,736,728,729,730,731) INTO :V$COUNT;
        SELECT COUNT(*) + :V$COUNT FROM VALL WHERE OBJ_ID = :V$SCHOOL_ID AND PARAM_ID IN (727) AND LISTVAL_ID <> 0 INTO :V$COUNT;
        VAL = V$COUNT;
        COL_NUM = 10;
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE MTR_FILLING_DATA_REPORT (
    I$REGION_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    COL_NUM SMALLINT,
    VAL VARCHAR(4000),
    DATA VARCHAR(4000),
    ORIENTATION VARCHAR(20))
AS
declare variable V$SCHOOL_ID bigint;
declare variable V$COUNT bigint;
BEGIN
    ORIENTATION = 'MIXED';
    DATA = NULL;
    FOR
        SELECT S.OBJ_ID,
               S.SCHOOL_NUMBER
        FROM MTR_DISTRICT_LIST(:I$REGION_ID) D
        JOIN MTR_SCHOOL_LIST(D.OBJ_ID) S ON 1=1

        UNION ALL

        SELECT OBJ_ID,
               SCHOOL_NUMBER
        FROM MTR_SCHOOL_LIST(:I$REGION_ID)
        ORDER BY 2

        INTO :V$SCHOOL_ID,
             :VAL
    DO
    BEGIN
        COL_NUM = 1;
        SUSPEND;

        SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:V$SCHOOL_ID, 1, :I$USER_ID) INTO :VAL;
        COL_NUM = 2;
        SUSPEND;
        SELECT VAL FROM INFOEQUIPMENT_ESTIMATION_GET(:V$SCHOOL_ID, 4, :I$USER_ID) INTO :VAL;
        COL_NUM = 3;
        SUSPEND;

        SELECT COUNT(L114.OBJ_ID)
        FROM LINKS L23

        JOIN LINKS L95
        ON L95.PARENT_ID = L23.OBJ_ID
        AND L95.DATE_DEL IS NULL
        AND L95.OBJ_TYPE_ID = 95

        JOIN LINKS L114
        ON L114.PARENT_ID = L95.OBJ_ID
        AND L114.DATE_DEL IS NULL
        AND L114.OBJ_TYPE_ID = 114

        WHERE L23.PARENT_ID = :V$SCHOOL_ID
        AND L23.DATE_DEL IS NULL
        AND L23.OBJ_TYPE_ID = 23
        INTO :VAL;
        COL_NUM = 4;
        SUSPEND;

        SELECT COUNT(L114.OBJ_ID)
        FROM LINKS L23

        JOIN LINKS L95
        ON L95.PARENT_ID = L23.OBJ_ID
        AND L95.DATE_DEL IS NULL
        AND L95.OBJ_TYPE_ID = 95

        JOIN VALL VL
        ON VL.OBJ_ID = L95.OBJ_ID
        AND VL.PARAM_ID = 626
        AND VL.IS_DEL = 0
        AND VL.LISTVAL_ID = 1799

        JOIN LINKS L114
        ON L114.PARENT_ID = L95.OBJ_ID
        AND L114.DATE_DEL IS NULL
        AND L114.OBJ_TYPE_ID = 114

        WHERE L23.PARENT_ID = :V$SCHOOL_ID
        AND L23.DATE_DEL IS NULL
        AND L23.OBJ_TYPE_ID = 23
        INTO :VAL;
        COL_NUM = 5;
        SUSPEND;

        SELECT COUNT(L114.OBJ_ID)
        FROM LINKS L23

        JOIN LINKS L95
        ON L95.PARENT_ID = L23.OBJ_ID
        AND L95.DATE_DEL IS NULL
        AND L95.OBJ_TYPE_ID = 95

        JOIN VALL VL
        ON VL.OBJ_ID = L95.OBJ_ID
        AND VL.PARAM_ID = 626
        AND VL.IS_DEL = 0
        AND VL.LISTVAL_ID = 1901

        JOIN LINKS L114
        ON L114.PARENT_ID = L95.OBJ_ID
        AND L114.DATE_DEL IS NULL
        AND L114.OBJ_TYPE_ID = 114

        WHERE L23.PARENT_ID = :V$SCHOOL_ID
        AND L23.DATE_DEL IS NULL
        AND L23.OBJ_TYPE_ID = 23
        INTO :VAL;
        COL_NUM = 6;
        SUSPEND;

        SELECT COUNT(L114.OBJ_ID)
        FROM LINKS L23

        JOIN LINKS L95
        ON L95.PARENT_ID = L23.OBJ_ID
        AND L95.DATE_DEL IS NULL
        AND L95.OBJ_TYPE_ID = 95

        JOIN VALL VL
        ON VL.OBJ_ID = L95.OBJ_ID
        AND VL.PARAM_ID = 626
        AND VL.IS_DEL = 0
        AND VL.LISTVAL_ID = 1815

        JOIN LINKS L114
        ON L114.PARENT_ID = L95.OBJ_ID
        AND L114.DATE_DEL IS NULL
        AND L114.OBJ_TYPE_ID = 114

        WHERE L23.PARENT_ID = :V$SCHOOL_ID
        AND L23.DATE_DEL IS NULL
        AND L23.OBJ_TYPE_ID = 23
        INTO :VAL;
        COL_NUM = 7;
        SUSPEND;

        SELECT COUNT(L128.OBJ_ID)
        FROM LINKS L23

        JOIN LINKS L128
        ON L128.PARENT_ID = L23.OBJ_ID
        AND L128.DATE_DEL IS NULL
        AND L128.OBJ_TYPE_ID = 128

        WHERE L23.PARENT_ID = :V$SCHOOL_ID
        AND L23.DATE_DEL IS NULL
        AND L23.OBJ_TYPE_ID = 23
        INTO :VAL;
        COL_NUM = 8;
        SUSPEND;

        SELECT COUNT(L116.OBJ_ID)
        FROM LINKS L116

        WHERE L116.PARENT_ID = :V$SCHOOL_ID
        AND L116.DATE_DEL IS NULL
        AND L116.OBJ_TYPE_ID = 116
        INTO :VAL;
        COL_NUM = 9;
        SUSPEND;

        V$COUNT = 0;
        SELECT COUNT(*) + :V$COUNT FROM VALS WHERE OBJ_ID = :V$SCHOOL_ID AND PARAM_ID IN (711,712) AND VAL <> '' INTO :V$COUNT;
        SELECT COUNT(*) + :V$COUNT FROM VALF WHERE OBJ_ID = :V$SCHOOL_ID AND PARAM_ID IN (735,736,728,729,730,731) INTO :V$COUNT;
        SELECT COUNT(*) + :V$COUNT FROM VALL WHERE OBJ_ID = :V$SCHOOL_ID AND PARAM_ID IN (727) AND LISTVAL_ID <> 0 INTO :V$COUNT;
        VAL = V$COUNT;
        COL_NUM = 10;
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE MTR_REPORT_ROOMS (
    I$OU_ID BIGINT)
RETURNS (
    VAL VARCHAR(4000))
AS
declare variable V$SUBJECT_ID bigint;
declare variable V$ROOM_ID bigint;
declare variable V$S1 varchar(400);
declare variable V$S2 varchar(400);
declare variable V$S3 varchar(400);
declare variable V$SOP varchar(400);
declare variable V$OBJ_ID bigint;
declare variable NS integer;
begin

  VAL = '<!DOCTYPE html>';
  VAL = VAL || '<html lang="ru">';
  VAL = VAL || '<head>';
  VAL = VAL || '<meta charset="utf-8" />';
  VAL = VAL || '<style>';
  VAL = VAL || 'html { font-family: Tahoma, Verdana, Arial;';
  VAL = VAL || 'font-size: 10pt; ';
  VAL = VAL || '} ';
  VAL = VAL || '.title1 { font-size: 150%;';
  VAL = VAL || 'padding: 8px;';
  VAL = VAL || 'margin-bottom: 4px;';
  VAL = VAL || 'font-weight: bold;';
  VAL = VAL || 'background-color: #D4E157;';
  VAL = VAL || '} ';
  VAL = VAL || '.title2 { ';
  VAL = VAL || 'padding: 4px;';
  VAL = VAL || 'font-weight: bold;';
  VAL = VAL || '} ';
  VAL = VAL || 'td { padding: 0.5em 1em;';
  VAL = VAL || 'border: 1px solid #000; ';
  VAL = VAL || '} ';
  VAL = VAL || '</style>';

  VAL = VAL || '</head>';
  VAL = VAL || '<body>';
  SUSPEND;

  -- Заголовок отчета
  VAL = '<div class="title1">Отчет по специализированным кабинетам</div>';
  VAL = VAL || '<div class="title2">' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$OU_ID)) || '</div>';

  VAL = VAL || '<table class="table" cellspacing="0" cellpadding="0" style="width: 100%">';

  VAL = VAL || '<tr class="thd">';
  VAL = VAL || '<td style="width: 20%">Уровень образования</td>';
  VAL = VAL || '<td style="width: 20%">Предмет (обязательная часть)</td>';
  VAL = VAL || '<td style="width: 35%">Наименование кабинета</td>';
  VAL = VAL || '<td style="width: 25%">Назначение</td>';
  VAL = VAL || '</tr>';
  SUSPEND;

  FOR
    SELECT L51.OBJ_ID, C.CAPTION
    FROM LINKS L51
    LEFT JOIN OBJECT_CAPTION_GET(L51.OBJ_ID) C ON 1 = 1
    WHERE L51.PARENT_TYPE_ID = 301 AND L51.OBJ_TYPE_ID = 51 AND L51.DATE_DEL IS NULL
      AND L51.OBJ_ID IN (185, 187, 178, 190, 5518, 174, 194, 3139, 198, 199, 202, 203, 200, 205, 206, 5516, 32840)
    ORDER BY 2
    INTO :V$SUBJECT_ID, :V$S1
  DO
  BEGIN

    -- Список помещений
    NS = 1;
    FOR
      SELECT LP61.PARENT_ID, C.CAPTION, CT.VAL
      FROM LINKS LP61
      JOIN VALL V526 ON V526.OBJ_ID = LP61.PARENT_ID AND V526.PARAM_ID = 526 AND V526.IS_DEL = 0
      LEFT JOIN OBJECT_CAPTION_GET(LP61.PARENT_ID) C ON 1 = 1
      LEFT JOIN LISTVAL_TEXT(V526.LISTVAL_ID) CT ON 1 = 1
      WHERE LP61.OBJ_ID = :V$SUBJECT_ID AND LP61.PARENT_TYPE_ID = 61 AND LP61.DATE_DEL IS NULL
      ORDER BY 2
      INTO :V$ROOM_ID, :V$S2, :V$S3
    DO
    BEGIN

      V$SOP = '';
      FOR
        SELECT DISTINCT V1594.LISTVAL_ID
        FROM LINKS L57
        JOIN VALL V1594 ON V1594.OBJ_ID = L57.OBJ_ID AND V1594.PARAM_ID = 1594 AND V1594.IS_DEL = 0
        WHERE L57.PARENT_ID = :V$ROOM_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
        ORDER BY 1
        INTO :V$OBJ_ID
      DO
      BEGIN
        IF(V$OBJ_ID = 5341) THEN V$SOP = V$SOP || 'ООО, ';
        IF(V$OBJ_ID = 5343) THEN V$SOP = V$SOP || 'СОО, ';
      END
      IF(V$SOP <> '') THEN V$SOP = SUBSTRING(V$SOP FROM 1 FOR CHAR_LENGTH(V$SOP) - 2);

      VAL = '<tr>';
      VAL = VAL || '<td>' || V$SOP || '</td>';
      VAL = VAL || '<td>' || V$S1 || '</td>';
      VAL = VAL || '<td>' || V$S2 || '</td>';
      VAL = VAL || '<td>' || V$S3 || '</td>';
      VAL = VAL || '</tr>';
      SUSPEND;

      NS = NS + 1;
    END

  END


  VAL = '</table></body></html>';
  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE MTR_REPORT_ROOM_EQ (
    I$OU_ID BIGINT)
RETURNS (
    VAL VARCHAR(4000))
AS
declare variable V$BUILDING_ID bigint;
declare variable V$ROOM_ID bigint;
declare variable V$PREV_ID bigint;
declare variable V$OBJ_ID bigint;
declare variable V$SOP varchar(200);
declare variable V$S1 varchar(400);
declare variable V$S2 varchar(400);
declare variable V$S3 varchar(400);
declare variable V$S4 varchar(400);
declare variable V$S5 varchar(400);
declare variable NS integer;
begin

  VAL = '<!DOCTYPE html>';
  VAL = VAL || '<html lang="ru">';
  VAL = VAL || '<head>';
  VAL = VAL || '<meta charset="utf-8" />';
  VAL = VAL || '<style>';
  VAL = VAL || 'html { font-family: Tahoma, Verdana, Arial;';
  VAL = VAL || 'font-size: 10pt; ';
  VAL = VAL || '} ';
  VAL = VAL || '.title1 { font-size: 150%;';
  VAL = VAL || 'padding: 8px;';
  VAL = VAL || 'margin-bottom: 4px;';
  VAL = VAL || 'font-weight: bold;';
  VAL = VAL || 'background-color: #D4E157;';
  VAL = VAL || '} ';
  VAL = VAL || '.title2 { ';
  VAL = VAL || 'padding: 4px;';
  VAL = VAL || 'font-weight: bold;';
  VAL = VAL || '} ';
  VAL = VAL || 'td { padding: 0.5em 1em;';
  VAL = VAL || 'border: 1px solid #000; ';
  VAL = VAL || '} ';
  VAL = VAL || '</style>';

  VAL = VAL || '</head>';
  VAL = VAL || '<body>';
  SUSPEND;

  -- Заголовок отчета
  VAL = '<div class="title1">Отчет по оборудованию в специализированных кабинетах</div>';
  VAL = VAL || '<div class="title2">' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$OU_ID)) || '</div>';

  VAL = VAL || '<table class="table" cellspacing="0" cellpadding="0" style="width: 100%">';

  VAL = VAL || '<tr class="thd">';
  VAL = VAL || '<td style="width: 15%">Наименование кабинета</td>';
  VAL = VAL || '<td style="width: 15%">Назначение</td>';
  VAL = VAL || '<td style="width: 25%">Используется как специализированный кабинет по предмету</td>';
  VAL = VAL || '<td style="width: 30%">Учебное оборудование и технические средства обучения</td>';
  VAL = VAL || '<td style="width: 15%">Инв.№</td>';
  VAL = VAL || '</tr>';
  SUSPEND;

  V$PREV_ID = -1;
  FOR
    SELECT L16.OBJ_ID, L61.OBJ_ID, C.CAPTION, CT.VAL
    FROM LINKS L73
    JOIN LINKS L16 ON L16.PARENT_ID = L73.OBJ_ID AND L16.OBJ_TYPE_ID = 16 AND L16.DATE_DEL IS NULL
    JOIN LINKS L61 ON L61.PARENT_ID = L16.OBJ_ID AND L61.OBJ_TYPE_ID = 61 AND L61.DATE_DEL IS NULL
    JOIN VALL V526 ON V526.OBJ_ID = L61.OBJ_ID AND V526.PARAM_ID = 526 AND V526.IS_DEL = 0
    LEFT JOIN OBJECT_CAPTION_GET(L61.OBJ_ID) C ON 1 = 1
    LEFT JOIN LISTVAL_TEXT(V526.LISTVAL_ID) CT ON 1 = 1
    WHERE L73.PARENT_ID = :I$OU_ID AND L73.OBJ_TYPE_ID = 73 AND L73.DATE_DEL IS NULL
    ORDER BY 1, 3
    INTO :V$BUILDING_ID, :V$ROOM_ID, :V$S1, :V$S2
  DO
  BEGIN
    IF(V$PREV_ID <> V$BUILDING_ID) THEN
    BEGIN
      VAL = '<tr><td colspan="5"><b>' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$BUILDING_ID)) || '</b></td></tr>';
      SUSPEND;
    END
    V$PREV_ID = V$BUILDING_ID;

    V$SOP = '';
    FOR
      SELECT DISTINCT V1594.LISTVAL_ID
      FROM LINKS L57
      JOIN VALL V1594 ON V1594.OBJ_ID = L57.OBJ_ID AND V1594.PARAM_ID = 1594 AND V1594.IS_DEL = 0
      WHERE L57.PARENT_ID = :V$ROOM_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
      ORDER BY 1
      INTO :V$OBJ_ID
    DO
    BEGIN
      IF(V$OBJ_ID = 5341) THEN V$SOP = V$SOP || 'ООО, ';
      IF(V$OBJ_ID = 5343) THEN V$SOP = V$SOP || 'СОО, ';
    END
    IF(V$SOP <> '') THEN V$SOP = SUBSTRING(V$SOP FROM 1 FOR CHAR_LENGTH(V$SOP) - 2);

    -- Физика, биология, химия
    V$S3 = '';
    FOR
      SELECT DISTINCT C.CAPTION
      FROM LINKS L51
      LEFT JOIN OBJECT_CAPTION_GET(L51.OBJ_ID) C ON 1 = 1
      WHERE L51.PARENT_ID = :V$ROOM_ID AND L51.OBJ_TYPE_ID = 51 AND L51.DATE_DEL IS NULL
        AND L51.OBJ_ID IN (197, 198, 199)
      ORDER BY 1
      INTO :V$S4
    DO
    BEGIN
      V$S3 = V$S3 || V$S4 || ', ';
    END
    IF(V$S3 <> '') THEN V$S3 = SUBSTRING(V$S3 FROM 1 FOR CHAR_LENGTH(V$S3) - 2);

    NS = 0;
    FOR
      SELECT V674.SVAL, V673.SVAL
      FROM LINKS L92
      JOIN LINKS L97 ON L97.PARENT_ID = L92.OBJ_ID AND L97.OBJ_TYPE_ID = 97 AND L97.DATE_DEL IS NULL
      JOIN LINKS L114 ON L114.PARENT_ID = L97.OBJ_ID AND L114.OBJ_TYPE_ID = 114 AND L114.DATE_DEL IS NULL
      JOIN VALR V679 ON V679.OBJ_ID = L114.OBJ_ID AND V679.PARAM_ID = 679 AND V679.IS_DEL = 0 AND V679.VAL = :V$ROOM_ID
      JOIN VALS V674 ON V674.OBJ_ID = L114.OBJ_ID AND V674.PARAM_ID = 674 AND V674.IS_DEL = 0
      JOIN VALS V673 ON V673.OBJ_ID = L114.OBJ_ID AND V673.PARAM_ID = 673 AND V673.IS_DEL = 0
      WHERE L92.PARENT_ID = :I$OU_ID AND L92.OBJ_TYPE_ID = 92 AND L92.DATE_DEL IS NULL AND :V$SOP <> '' AND :V$S3 <> ''
      ORDER BY 1, 2
      INTO :V$S4, :V$S5
    DO
    BEGIN
      VAL = '<tr>';
      IF(NS = 0) THEN VAL = VAL || '<td>' || V$S1 || '</td><td>' || V$S2 || '</td><td>' || V$S3 || '</td>';
      ELSE VAL = VAL || '<td></td><td></td><td></td>';
      NS = NS + 1;

      VAL = VAL || '<td>' || V$S4 || '</td>';
      VAL = VAL || '<td>' || V$S5 || '</td>';
      VAL = VAL || '</tr>';
      SUSPEND;
    END

    IF(NS = 0 AND V$S3 <> '') THEN
    BEGIN
      VAL = '<tr style="background-color: rgba(255,64,64,0.2)">';
      VAL = VAL || '<td>' || V$S1 || '</td><td>' || V$S2 || '</td><td>' || V$S3 || '</td>';

      VAL = VAL || '<td colspan="2">Нет оснащения</td>';
      VAL = VAL || '</tr>';
      SUSPEND;
    END

  END

  VAL = '</table></body></html>';
  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE MTR_SCHOOL_LIST (
    I$DISTRICT_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    OBJ_CAPTION VARCHAR(4000),
    SCHOOL_NUMBER INTEGER)
AS
BEGIN
    FOR
        SELECT L2.OBJ_ID

        FROM LINKS L2
        WHERE L2.PARENT_ID = :I$DISTRICT_ID
        AND L2.OBJ_TYPE_ID = 2
        AND L2.DATE_DEL IS NULL

        INTO :OBJ_ID
    DO
    BEGIN
        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:OBJ_ID)
        INTO :OBJ_CAPTION;

        SELECT I
        FROM VAL_GET(:OBJ_ID, 17)
        INTO :SCHOOL_NUMBER;
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE NEW_SPO_CURRICULUM_ADD_LOADS (
    I$DISCIPLINE_ID INTEGER,
    I$PLAN_SUBJECT_ID BIGINT NOT NULL,
    I$SUBJECT_ID SMALLINT NOT NULL,
    I$CURRICULUM_ID BIGINT NOT NULL,
    I$CURR_TEMPLATE_ID BIGINT NOT NULL)
AS
DECLARE VARIABLE V$WEEKS BIGINT;
DECLARE VARIABLE V$LOAD_HOURS_S1 BIGINT;
DECLARE VARIABLE V$LOAD_HOURS_S2 BIGINT;
DECLARE VARIABLE V$CONTROL_Q1 BIGINT;
DECLARE VARIABLE V$CONTROL_Q2 BIGINT;
DECLARE VARIABLE V$HOURS_MAX BIGINT;
DECLARE VARIABLE V$STAGE_ID BIGINT;
DECLARE VARIABLE V$DST_STAGE_ID BIGINT;
DECLARE VARIABLE V$CURS_WORK BIGINT;
DECLARE VARIABLE V$LAB_WORK BIGINT;
DECLARE VARIABLE V$SUBJ_ID BIGINT;
DECLARE VARIABLE V$ID BIGINT;
DECLARE VARIABLE V$ROW_CODE VARCHAR(40);
begin
  SELECT FIRST 1 ROW_CODE FROM PLAN_SUBJECTS
  WHERE OBJ_ID = :I$PLAN_SUBJECT_ID
  INTO :V$ROW_CODE;

  --                          weeks      hours max  курсработы лабы+практика
  SELECT FIRST 1 L203.OBJ_ID, V1770.VAL, V1771.VAL, V1775.VAL, V1774.VAL
  FROM LINKS L203
  JOIN LINKS L201 ON L201.OBJ_ID = L203.PARENT_ID AND L201.DATE_DEL IS NULL AND L201.OBJ_TYPE_ID = 201
  LEFT JOIN VALR V1766 ON V1766.OBJ_ID = L201.OBJ_ID AND V1766.PARAM_ID = 1766 AND V1766.IS_DEL = 0
  LEFT JOIN VALS V1765 ON V1765.OBJ_ID = L201.OBJ_ID AND V1765.PARAM_ID = 1765 AND V1765.IS_DEL = 0
  LEFT JOIN VALI V1770 ON V1770.OBJ_ID = L203.OBJ_ID AND V1770.PARAM_ID = 1770 AND V1770.IS_DEL = 0
  LEFT JOIN VALI V1771 ON V1771.OBJ_ID = L203.OBJ_ID AND V1771.PARAM_ID = 1771 AND V1771.IS_DEL = 0
  LEFT JOIN VALI V1774 ON V1774.OBJ_ID = L203.OBJ_ID AND V1774.PARAM_ID = 1774 AND V1774.IS_DEL = 0
  LEFT JOIN VALI V1775 ON V1775.OBJ_ID = L203.OBJ_ID AND V1775.PARAM_ID = 1775 AND V1775.IS_DEL = 0
  WHERE L203.PARENT_ID = :I$DISCIPLINE_ID AND L203.OBJ_TYPE_ID = 203 AND L203.DATE_DEL IS NULL AND V1766.VAL = :I$SUBJECT_ID AND V1765.VAL = :V$ROW_CODE
  INTO :V$ID, :V$WEEKS, :V$HOURS_MAX, :V$CURS_WORK, :V$LAB_WORK;

  IF (V$ID IS NOT NULL) THEN
  BEGIN
    --добавляем часы лаб и курсовых работ, кол-во недель, св-ва объекта 203
    INSERT INTO PLAN_LOADS
    (SUBJECT_ID, STAGE_ID, WEEKS, HOURS_MAX, HOURS_CR1, HOURS_PR1)
    VALUES (:I$PLAN_SUBJECT_ID, NULL, :V$WEEKS, :V$HOURS_MAX, :V$CURS_WORK, :V$LAB_WORK);

    FOR
      SELECT
        V1776.LISTVAL_ID,
        V1777.VAL, -- sem1 hours
        V1778.LISTVAL_ID, -- sem 1 control
        V1779.VAL, -- sem2 hours
        V1780.LISTVAL_ID  -- sem 2 control
      FROM LINKS L205
      LEFT JOIN VALL V1776 ON V1776.OBJ_ID = L205.OBJ_ID AND V1776.PARAM_ID = 1776 AND V1776.IS_DEL = 0
      LEFT JOIN VALI V1777 ON V1777.OBJ_ID = L205.OBJ_ID AND V1777.PARAM_ID = 1777 AND V1777.IS_DEL = 0
      LEFT JOIN VALL V1778 ON V1778.OBJ_ID = L205.OBJ_ID AND V1778.PARAM_ID = 1778 AND V1778.IS_DEL = 0
      LEFT JOIN VALI V1779 ON V1779.OBJ_ID = L205.OBJ_ID AND V1779.PARAM_ID = 1779 AND V1779.IS_DEL = 0
      LEFT JOIN VALL V1780 ON V1780.OBJ_ID = L205.OBJ_ID AND V1780.PARAM_ID = 1780 AND V1780.IS_DEL = 0
      WHERE L205.PARENT_ID = :V$ID AND L205.DATE_DEL IS NULL
      INTO :V$STAGE_ID, :V$LOAD_HOURS_S1, :V$CONTROL_Q1, :V$LOAD_HOURS_S2, :V$CONTROL_Q2
    DO
    BEGIN
      -- нужно найти соответствующий этап обучения в новом УП
      V$DST_STAGE_ID = NULL;
      SELECT FIRST 1 L54.OBJ_ID
      FROM LINKS L54
      LEFT JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
      WHERE L54.PARENT_ID = :I$CURRICULUM_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL AND V381.LISTVAL_ID = :V$STAGE_ID
      INTO :V$DST_STAGE_ID;

      --добавляем часы и контроль для каждого этапа обучения, св-ва объектов 205
      IF (V$DST_STAGE_ID IS NOT NULL) THEN
      BEGIN
        INSERT INTO PLAN_LOADS
        (SUBJECT_ID, STAGE_ID, LOAD_HOURS,
          LOAD_HOURS_S1, LOAD_HOURS_S2, CONTROL_Q1, CONTROL_Q2)
        VALUES (:I$PLAN_SUBJECT_ID, :V$DST_STAGE_ID, IIF(:V$LOAD_HOURS_S1 IS NULL, 0, :V$LOAD_HOURS_S1) + IIF(:V$LOAD_HOURS_S2 IS NULL, 0, :V$LOAD_HOURS_S2),
          :V$LOAD_HOURS_S1, :V$LOAD_HOURS_S2, :V$CONTROL_Q1, :V$CONTROL_Q2);
      END
    END
  END
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE NEW_SPO_PLAN_SUBJECT (
    I$OBJ_ID BIGINT NOT NULL,
    I$TYPE_ID BIGINT NOT NULL,
    I$SUBJ_ID BIGINT,
    I$FIELD_ID BIGINT,
    I$INDEX BIGINT NOT NULL,
    I$PARENT_ID BIGINT,
    I$LEVEL BIGINT NOT NULL,
    I$PARENT0 BIGINT,
    I$PARENT1 BIGINT,
    I$PARENT2 BIGINT,
    I$ROW_CODE VARCHAR(40))
RETURNS (
    SUBJECT_OBJ_ID BIGINT,
    IND BIGINT,
    PARENT0 BIGINT,
    PARENT1 BIGINT,
    PARENT2 BIGINT)
AS
DECLARE VARIABLE V$ROW_TYPE SMALLINT;
begin
  IF (I$TYPE_ID = 185) THEN V$ROW_TYPE = 0; ELSE V$ROW_TYPE = 10;

  INSERT INTO PLAN_SUBJECTS
  (PLAN_ID, SUBJECT_ID, FIELD_ID, SORT_INDEX, PARENT_ID, LEVEL_INDEX, GLOBAL_INDEX, IS_ADV, ROW_TYPE, SRC_SUBJECT_ID, IS_STM, ROW_CODE)
  VALUES (:I$OBJ_ID, :I$SUBJ_ID, :I$FIELD_ID, :I$INDEX, :I$PARENT_ID, :I$LEVEL, :I$INDEX, 0, :V$ROW_TYPE, 0, 0, :I$ROW_CODE)
  RETURNING OBJ_ID
  INTO :SUBJECT_OBJ_ID;

  --сохраним родительсике узлы
  IF (I$LEVEL = 0) THEN
  BEGIN
    --родитель на 0-м уровне,
    I$PARENT0 = SUBJECT_OBJ_ID;
    I$PARENT1 = NULL;
    I$PARENT2 = NULL;
  END
  ELSE IF (I$LEVEL = 1) THEN
  BEGIN
    --родитель на 1-м уровня
    I$PARENT1 = SUBJECT_OBJ_ID;
    I$PARENT2 = NULL;
  END 
  ELSE
  BEGIN
    --родитель на 2-м уровня
    I$PARENT2 = SUBJECT_OBJ_ID;
  END 

  IND = I$INDEX + 1;
  PARENT0 = I$PARENT0;
  PARENT1 = I$PARENT1;
  PARENT2 = I$PARENT2;

  SUSPEND;
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OAIS_COLLECT_PARENTS RETURNS (
    SURNAME VARCHAR(1000),
    NAME VARCHAR(1000),
    SECONDNAME VARCHAR(1000),
    IDN VARCHAR(1000),
    OBJ_ID BIGINT,
    JUDGE_PARAM_ID BIGINT,
    DATE_PARAM_ID BIGINT,
    NUM_PARAM_ID BIGINT)
AS
BEGIN
    FOR
        SELECT DISTINCT
               L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 124
        AND L.DATE_DEL IS NULL
        INTO :OBJ_ID
    DO
    BEGIN
        JUDGE_PARAM_ID = 772; --IN FOR LKR'S MOTHER
        DATE_PARAM_ID = 773;
        NUM_PARAM_ID = 774;
        SELECT V
        FROM VAL_GET(:OBJ_ID,763)
        INTO :SURNAME;

        SELECT V
        FROM VAL_GET(:OBJ_ID,764)
        INTO :NAME;

        SELECT V
        FROM VAL_GET(:OBJ_ID,765)
        INTO :SECONDNAME;

        SELECT V
        FROM VAL_GET(:OBJ_ID,964)
        INTO :IDN;

        SUSPEND;

        JUDGE_PARAM_ID = 788; --IN FOR LKR'S FATHER
        DATE_PARAM_ID = 789;
        NUM_PARAM_ID = 790;
        SELECT V
        FROM VAL_GET(:OBJ_ID,779)
        INTO :SURNAME;

        SELECT V
        FROM VAL_GET(:OBJ_ID,780)
        INTO :NAME;

        SELECT V
        FROM VAL_GET(:OBJ_ID,781)
        INTO :SECONDNAME;

        SELECT V
        FROM VAL_GET(:OBJ_ID,967)
        INTO :IDN;

        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OAIS_COLLECT_PERSONS RETURNS (
    SURNAME VARCHAR(1000),
    NAME VARCHAR(1000),
    SECONDNAME VARCHAR(1000),
    OBJ_ID BIGINT,
    PARAM_ID BIGINT)
AS
declare variable V$TYPE_ID bigint;
BEGIN
    FOR
        SELECT DISTINCT
               L.OBJ_ID,
               L.OBJ_TYPE_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID IN (124,126,125)
        AND L.DATE_DEL IS NULL
        INTO :OBJ_ID,
             :V$TYPE_ID
    DO
    BEGIN
        IF (V$TYPE_ID = 125) THEN
        BEGIN
            PARAM_ID = 978; -- IN FOR BROTHER|SISTER
            SELECT V
            FROM VAL_GET(:OBJ_ID,819)
            INTO :SURNAME;

            SELECT V
            FROM VAL_GET(:OBJ_ID,820)
            INTO :NAME;

            SELECT V
            FROM VAL_GET(:OBJ_ID,821)
            INTO :SECONDNAME;

            SUSPEND;
        END
        ELSE IF (V$TYPE_ID = 126) THEN
        BEGIN
            PARAM_ID = 835; -- IN FOR TUTOR
            SELECT V
            FROM VAL_GET(:OBJ_ID,827)
            INTO :SURNAME;

            SELECT V
            FROM VAL_GET(:OBJ_ID,828)
            INTO :NAME;

            SELECT V
            FROM VAL_GET(:OBJ_ID,829)
            INTO :SECONDNAME;

            SUSPEND;
        END
        ELSE IF (V$TYPE_ID = 124) THEN
        BEGIN
            PARAM_ID = 924; --IN FOR LKR
            SELECT V
            FROM VAL_GET(:OBJ_ID,756)
            INTO :SURNAME;

            SELECT V
            FROM VAL_GET(:OBJ_ID,757)
            INTO :NAME;

            SELECT V
            FROM VAL_GET(:OBJ_ID,758)
            INTO :SECONDNAME;

            SUSPEND;

            PARAM_ID = 964; --IN FOR LKR'S MOTHER
            SELECT V
            FROM VAL_GET(:OBJ_ID,763)
            INTO :SURNAME;

            SELECT V
            FROM VAL_GET(:OBJ_ID,764)
            INTO :NAME;

            SELECT V
            FROM VAL_GET(:OBJ_ID,765)
            INTO :SECONDNAME;

            SUSPEND;

            PARAM_ID = 967; --IN FOR LKR'S FATHER
            SELECT V
            FROM VAL_GET(:OBJ_ID,779)
            INTO :SURNAME;

            SELECT V
            FROM VAL_GET(:OBJ_ID,780)
            INTO :NAME;

            SELECT V
            FROM VAL_GET(:OBJ_ID,781)
            INTO :SECONDNAME;

            SUSPEND;
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OBFUSCATE_ALL (
    HASH_METHOD SMALLINT = 0)
AS
DECLARE VARIABLE TABLE_SIZE INTEGER = 30;
DECLARE VARIABLE OBJ_ID BIGINT;
DECLARE VARIABLE TYPE_ID BIGINT;
DECLARE VARIABLE TYPE_NAME BIGINT;
DECLARE VARIABLE TYPE_LASTNAME BIGINT;
DECLARE VARIABLE TYPE_SURNAME BIGINT;
DECLARE VARIABLE SEX BIGINT;
DECLARE VARIABLE S VARCHAR(1000);
DECLARE VARIABLE H_NAME BIGINT;
DECLARE VARIABLE H_SURNAME BIGINT;
DECLARE VARIABLE H_LASTNAME BIGINT;
DECLARE VARIABLE N INTEGER;
DECLARE VARIABLE REALSEX BIGINT;
begin

    -- Метод преобразования: 0 - случайное, 1 - сохраняющее соответствие (хеш)

    N = 0;

    FOR
        SELECT O.OBJ_ID, O.TYPE_ID, COALESCE(VSEX.LISTVAL_ID, 183), VSEX.LISTVAL_ID
        FROM OBJECTS O
        LEFT JOIN VALL VSEX ON VSEX.OBJ_ID = O.OBJ_ID AND VSEX.IS_DEL = 0 AND VSEX.PARAM_ID IN (88, 239, 2544, 1022, 1076)
        WHERE O.TYPE_ID IN (10, 14, 20, 124, 126, 149)
        INTO :OBJ_ID, :TYPE_ID, :SEX, :REALSEX
    DO
    BEGIN

        IF(TYPE_ID = 10) THEN
        BEGIN
            TYPE_LASTNAME = 55;
            TYPE_NAME = 56;
            TYPE_SURNAME = 57;
        END
        ELSE IF(TYPE_ID = 14) THEN
        BEGIN
            TYPE_LASTNAME = 59;
            TYPE_NAME = 60;
            TYPE_SURNAME = 61;
        END
        ELSE IF(TYPE_ID = 20) THEN
        BEGIN
            TYPE_LASTNAME = 128;
            TYPE_NAME = 129;
            TYPE_SURNAME = 130;
            -- Пытаемся выбрать реальный пол по степени родства
            IF(REALSEX IS NULL) THEN
            BEGIN
                SELECT FIRST 1 V1573.LISTVAL_ID
                FROM LINKS LP10
                JOIN VALL V1573 ON V1573.OBJ_ID = LP10.EXT_OBJ_ID AND V1573.PARAM_ID = 1573 AND V1573.IS_DEL = 0
                WHERE LP10.OBJ_ID = :OBJ_ID AND LP10.PARENT_TYPE_ID = 10 AND LP10.DATE_DEL IS NULL
                INTO :REALSEX;

                IF(REALSEX IN (225, 1224, 1226, 1228, 1235, 1237, 1243)) THEN SEX = 182; ELSE SEX = 183;
            END
        END
        ELSE IF(TYPE_ID = 124) THEN
        BEGIN
            TYPE_LASTNAME = 756;
            TYPE_NAME = 757;
            TYPE_SURNAME = 758;
        END
        ELSE IF(TYPE_ID = 126) THEN
        BEGIN
            TYPE_LASTNAME = 827;
            TYPE_NAME = 828;
            TYPE_SURNAME = 829;
        END
        ELSE IF(TYPE_ID = 149) THEN
        BEGIN
            TYPE_LASTNAME = 1073;
            TYPE_NAME = 1074;
            TYPE_SURNAME = 1075;
        END

        H_NAME = NULL;
        H_SURNAME = NULL;
        H_LASTNAME = NULL;

        -- Индексы имен и фамилий в количестве 30 штук каждого
        IF(HASH_METHOD = 0) THEN
        BEGIN
            H_NAME = TRUNC(RAND() * TABLE_SIZE) + N;
            H_SURNAME = TRUNC(RAND() * TABLE_SIZE) + N;
            H_LASTNAME = TRUNC(RAND() * TABLE_SIZE) + N;
        END
        ELSE IF(HASH_METHOD = 1) THEN
        BEGIN
            H_NAME = (SELECT ABS(HASH(VAL)) FROM VALS WHERE OBJ_ID = :OBJ_ID AND PARAM_ID = :TYPE_NAME AND IS_DEL = 0);
            H_SURNAME = (SELECT ABS(HASH(VAL)) FROM VALS WHERE OBJ_ID = :OBJ_ID AND PARAM_ID = :TYPE_SURNAME AND IS_DEL = 0);
            H_LASTNAME = (SELECT ABS(HASH(VAL)) FROM VALS WHERE OBJ_ID = :OBJ_ID AND PARAM_ID = :TYPE_LASTNAME AND IS_DEL = 0);
        END

        IF(H_NAME >= TABLE_SIZE) THEN H_NAME = H_NAME - TRUNC(H_NAME / TABLE_SIZE) * TABLE_SIZE;
        IF(H_SURNAME >= TABLE_SIZE) THEN H_SURNAME = H_SURNAME - TRUNC(H_SURNAME / TABLE_SIZE) * TABLE_SIZE;
        IF(H_LASTNAME >= TABLE_SIZE) THEN H_LASTNAME = H_LASTNAME - TRUNC(H_LASTNAME / TABLE_SIZE) * TABLE_SIZE;

        IF(H_NAME IS NOT NULL) THEN
        BEGIN
            
            IF(SEX = 182) THEN
            BEGIN
                S = CASE H_NAME
                WHEN 0 THEN 'Анастасия'
                WHEN 1 THEN 'Анна'
                WHEN 2 THEN 'Марина'
                WHEN 3 THEN 'Мария'
                WHEN 4 THEN 'Ксения'
                WHEN 5 THEN 'Татьяна'
                WHEN 6 THEN 'Ольга'
                WHEN 7 THEN 'Маргарита'
                WHEN 8 THEN 'Камилла'
                WHEN 9 THEN 'Лилия'
                WHEN 10 THEN 'Любовь'
                WHEN 11 THEN 'Юлия'
                WHEN 12 THEN 'Наталия'
                WHEN 13 THEN 'Виктория'
                WHEN 14 THEN 'Олеся'
                WHEN 15 THEN 'Надежда'
                WHEN 16 THEN 'Александра'
                WHEN 17 THEN 'Ульяна'
                WHEN 18 THEN 'София'
                WHEN 19 THEN 'Вера'
                WHEN 20 THEN 'Ника'
                WHEN 21 THEN 'Елизавета'
                WHEN 22 THEN 'Лариса'
                WHEN 23 THEN 'Тамара'
                WHEN 24 THEN 'Влада'
                WHEN 25 THEN 'Ирина'
                WHEN 26 THEN 'Кира'
                WHEN 27 THEN 'Валентина'
                WHEN 28 THEN 'Людмила'
                WHEN 29 THEN 'Галина'
                ELSE '???'
                END;
            END
            ELSE
            BEGIN
                S = CASE H_NAME
                WHEN 0 THEN 'Александр'
                WHEN 1 THEN 'Алексей'
                WHEN 2 THEN 'Кирилл'
                WHEN 3 THEN 'Роман'
                WHEN 4 THEN 'Денис'
                WHEN 5 THEN 'Виктор'
                WHEN 6 THEN 'Семен'
                WHEN 7 THEN 'Иван'
                WHEN 8 THEN 'Анатолий'
                WHEN 9 THEN 'Петр'
                WHEN 10 THEN 'Константин'
                WHEN 11 THEN 'Сергей'
                WHEN 12 THEN 'Вячеслав'
                WHEN 13 THEN 'Георгий'
                WHEN 14 THEN 'Антон'
                WHEN 15 THEN 'Глеб'
                WHEN 16 THEN 'Игорь'
                WHEN 17 THEN 'Федор'
                WHEN 18 THEN 'Борис'
                WHEN 19 THEN 'Марк'
                WHEN 20 THEN 'Захар'
                WHEN 21 THEN 'Павел'
                WHEN 22 THEN 'Филипп'
                WHEN 23 THEN 'Лев'
                WHEN 24 THEN 'Макар'
                WHEN 25 THEN 'Юрий'
                WHEN 26 THEN 'Степан'
                WHEN 27 THEN 'Григорий'
                WHEN 28 THEN 'Никита'
                WHEN 29 THEN 'Михаил'
                ELSE '???'
                END;
            END

            S = TRIM(S);

            UPDATE VALS
            SET VAL = :S
            WHERE OBJ_ID = :OBJ_ID AND PARAM_ID = :TYPE_NAME AND IS_DEL = 0;
        END

        IF(H_SURNAME IS NOT NULL) THEN
        BEGIN

            IF(SEX = 182) THEN
            BEGIN
                S = CASE H_SURNAME
                WHEN 0 THEN 'Александровна'
                WHEN 1 THEN 'Алексеевна'
                WHEN 2 THEN 'Кирилловна'
                WHEN 3 THEN 'Романовна'
                WHEN 4 THEN 'Денисовна'
                WHEN 5 THEN 'Викторовна'
                WHEN 6 THEN 'Семеновна'
                WHEN 7 THEN 'Ивановна'
                WHEN 8 THEN 'Анатольевна'
                WHEN 9 THEN 'Петровна'
                WHEN 10 THEN 'Константиновна'
                WHEN 11 THEN 'Сергеевна'
                WHEN 12 THEN 'Вячеславовна'
                WHEN 13 THEN 'Георгиевна'
                WHEN 14 THEN 'Антононовна'
                WHEN 15 THEN 'Глебовна'
                WHEN 16 THEN 'Игоревна'
                WHEN 17 THEN 'Федоровна'
                WHEN 18 THEN 'Борисовна'
                WHEN 19 THEN 'Марковна'
                WHEN 20 THEN 'Захаровна'
                WHEN 21 THEN 'Павловна'
                WHEN 22 THEN 'Филипповна'
                WHEN 23 THEN 'Львовна'
                WHEN 24 THEN 'Макаровна'
                WHEN 25 THEN 'Юрьевна'
                WHEN 26 THEN 'Степановна'
                WHEN 27 THEN 'Григорьевна'
                WHEN 28 THEN 'Никитовна'
                WHEN 29 THEN 'Михайловна'
                ELSE '???'
                END;
            END
            ELSE
            BEGIN
                S = CASE H_SURNAME
                WHEN 0 THEN 'Александрович'
                WHEN 1 THEN 'Алексеевич'
                WHEN 2 THEN 'Кириллович'
                WHEN 3 THEN 'Романович'
                WHEN 4 THEN 'Денисович'
                WHEN 5 THEN 'Викторович'
                WHEN 6 THEN 'Семенович'
                WHEN 7 THEN 'Иванович'
                WHEN 8 THEN 'Анатольевич'
                WHEN 9 THEN 'Петрович'
                WHEN 10 THEN 'Константинович'
                WHEN 11 THEN 'Сергеевич'
                WHEN 12 THEN 'Вячеславович'
                WHEN 13 THEN 'Георгиевич'
                WHEN 14 THEN 'Антононович'
                WHEN 15 THEN 'Глебович'
                WHEN 16 THEN 'Игоревич'
                WHEN 17 THEN 'Федорович'
                WHEN 18 THEN 'Борисович'
                WHEN 19 THEN 'Маркович'
                WHEN 20 THEN 'Захарович'
                WHEN 21 THEN 'Павлович'
                WHEN 22 THEN 'Филиппович'
                WHEN 23 THEN 'Львович'
                WHEN 24 THEN 'Макарович'
                WHEN 25 THEN 'Юрьевич'
                WHEN 26 THEN 'Степанович'
                WHEN 27 THEN 'Григорьевич'
                WHEN 28 THEN 'Никитович'
                WHEN 29 THEN 'Михайлович'
                ELSE '???'
                END;
            END

            S = TRIM(S);

            UPDATE VALS
            SET VAL = :S
            WHERE OBJ_ID = :OBJ_ID AND PARAM_ID = :TYPE_SURNAME AND IS_DEL = 0;
        END

        IF(H_LASTNAME IS NOT NULL) THEN
        BEGIN

            IF(SEX = 182) THEN
            BEGIN
                S = CASE H_LASTNAME
                WHEN 0 THEN 'Лазарева'
                WHEN 1 THEN 'Макарова'
                WHEN 2 THEN 'Ковалева'
                WHEN 3 THEN 'Назарова'
                WHEN 4 THEN 'Гурьева'
                WHEN 5 THEN 'Куликова'
                WHEN 6 THEN 'Захарьева'
                WHEN 7 THEN 'Лапина'
                WHEN 8 THEN 'Прохорова'
                WHEN 9 THEN 'Маркова'
                WHEN 10 THEN 'Большакова'
                WHEN 11 THEN 'Веселова'
                WHEN 12 THEN 'Фролова'
                WHEN 13 THEN 'Жукова'
                WHEN 14 THEN 'Орехова'
                WHEN 15 THEN 'Костина'
                WHEN 16 THEN 'Сазонова'
                WHEN 17 THEN 'Якушева'
                WHEN 18 THEN 'Журавлева'
                WHEN 19 THEN 'Зайцева'
                WHEN 20 THEN 'Никитина'
                WHEN 21 THEN 'Осипова'
                WHEN 22 THEN 'Белоусова'
                WHEN 23 THEN 'Яковлева'
                WHEN 24 THEN 'Воронина'
                WHEN 25 THEN 'Фомина'
                WHEN 26 THEN 'Ермакова'
                WHEN 27 THEN 'Давыдова'
                WHEN 28 THEN 'Осокина'
                WHEN 29 THEN 'Субботина'
                ELSE '???'
                END;
            END
            ELSE
            BEGIN
                S = CASE H_LASTNAME
                WHEN 0 THEN 'Быков'
                WHEN 1 THEN 'Галкин'
                WHEN 2 THEN 'Гаврилов'
                WHEN 3 THEN 'Гордеев'
                WHEN 4 THEN 'Ермаков'
                WHEN 5 THEN 'Лыков'
                WHEN 6 THEN 'Петров'
                WHEN 7 THEN 'Иванов'
                WHEN 8 THEN 'Комаров'
                WHEN 9 THEN 'Котов'
                WHEN 10 THEN 'Кулаков'
                WHEN 11 THEN 'Игнатьев'
                WHEN 12 THEN 'Лихачев'
                WHEN 13 THEN 'Наумов'
                WHEN 14 THEN 'Носов'
                WHEN 15 THEN 'Рябов'
                WHEN 16 THEN 'Савельев'
                WHEN 17 THEN 'Щукин'
                WHEN 18 THEN 'Шилов'
                WHEN 19 THEN 'Шашкин'
                WHEN 20 THEN 'Чернов'
                WHEN 21 THEN 'Уваров'
                WHEN 22 THEN 'Титов'
                WHEN 23 THEN 'Суханов'
                WHEN 24 THEN 'Сорокин'
                WHEN 25 THEN 'Ситников'
                WHEN 26 THEN 'Соловьев'
                WHEN 27 THEN 'Трубачев'
                WHEN 28 THEN 'Овчинников'
                WHEN 29 THEN 'Молчанов'
                ELSE '???'
                END;
            END

            S = TRIM(S);

            UPDATE VALS
            SET VAL = :S
            WHERE OBJ_ID = :OBJ_ID AND PARAM_ID = :TYPE_LASTNAME AND IS_DEL = 0;

        END

        -- Удаляем значения, которые помечены как удаленные
        DELETE FROM VALS
        WHERE OBJ_ID = :OBJ_ID AND IS_DEL = 1 AND (PARAM_ID = :TYPE_NAME OR PARAM_ID = :TYPE_SURNAME OR PARAM_ID = :TYPE_LASTNAME);

        N = N + 1;

    END

    -- Удаляем все параметры, которые более неактуальны, а также ненужные данные по ВПЛ
    DELETE FROM VALS
    WHERE PARAM_ID IN (171, 172, 173, 909, 910, 911, 779, 780, 781, 765, 796, 797, 798, 1006, 1007, 1008, 1012, 1013, 1014, 1195, 1196, 1197, 1201, 1202, 1203,
      1213, 1214, 1215, 1219, 1220, 1221, 1874, 1875, 1876, /* алиасы */ 2991, /* vk */ 3354, 3355, 3356, 2913, 2921, 2916, 2922, 2919, 2923, 3060, 3061, 3141);

    DELETE FROM VALS
    WHERE PARAM_ID IN (2546, 3482, 3446, 3009, 90, 228, 159, 1380);

    -- Обновляем серии паспортов
    UPDATE VALS
    SET VAL = '4000'
    WHERE PARAM_ID IN (219, 442, 479, 564, 570);

    -- Номера паспортов
    UPDATE VALS
    SET VAL = '123456'
    WHERE PARAM_ID IN (407, 475, 480, 559, 565, 571, 1605, 2358, 2367);

    -- СНИЛС
    FOR
      SELECT OBJ_ID, PARAM_ID
      FROM VALS
      WHERE PARAM_ID IN (1409, 2365, 2455)
      ORDER BY 1, 2
      INTO :OBJ_ID, :TYPE_ID
    DO
    BEGIN
      S = '';
      WHILE(CHAR_LENGTH(S) < 11) DO
      BEGIN
        S = S || SUBSTRING('0123456789' FROM MINVALUE(1 + RAND() * 10, 10) FOR 1);
      END

      S = SUBSTRING(S FROM 1 FOR 3) || '-' || SUBSTRING(S FROM 4 FOR 3) || '-' || SUBSTRING(S FROM 7 FOR 3) || ' ' || SUBSTRING(S FROM 10);
      S = SUBSTRING(S FROM 1 FOR 13) || (SELECT SNILS_CHECKSUM FROM CHECK_SNILS(:S));

      UPDATE VALS
      SET VAL = :S
      WHERE OBJ_ID = :OBJ_ID AND PARAM_ID = :TYPE_ID;
    END

    -- ИНН
    UPDATE VALS
    SET VAL = '000000000000'
    WHERE PARAM_ID IN (250);

    -- Кем выдан документ
    UPDATE VALS
    SET VAL = 'никем'
    WHERE PARAM_ID IN (562, 568, 574, 2369);

    -- email
    UPDATE VALS
    SET VAL = 'null@null.com'
    WHERE PARAM_ID IN (144, 1180);

    -- Номера телефонов
    UPDATE VALS
    SET VAL = '7-812-123-45-67'
    WHERE PARAM_ID IN (26, 28, 29, 31, 102, 141, 145, 146, 253, 254, 538, 668, 761, 808, 831, 1010, 1016, 1080, 1199, 1205, 1217, 1223, 1427, 1428, 1913, 1914);

    -- Даты рождения
    UPDATE VALD
    SET VAL = VAL - 100 * RAND()
    WHERE PARAM_ID IN (89, 175, 143, 241, 776, 782, 822, 830, 1077, 1859);

    UPDATE VALD
    SET VAL = VAL - 100 * RAND()
    WHERE PARAM_ID IN (300, 310, 339, 343, 347, 482, 560, 566, 572, 1876, 1884, 2359, 2368);

    -- Адреса заполняем пустотой, улицу ставим одну и ту же
    UPDATE VALA
    SET FLAT = '1', HOUSE = '1', OCATD = NULL, FIAS_UID = NULL, STREET_UID = NULL, STREET = 'Невский пр', DISTRICT = NULL, TOWN = NULL,
      SETTLEMENT = NULL, POST_INDEX = '197000', REGION = 'Санкт-Петербург г'
    WHERE 1 = 1;

    -- Образование, повышение квалификации, аттесации, награды - название ОУ, номера и серии документов, даты выдачи
    -- поощрения-взыскания
    UPDATE VALS
    SET VAL = 'Кудыкиногорская академия'
    WHERE PARAM_ID IN (285, 296, 2334, 304, 2335, 324);

    UPDATE VALS
    SET VAL = '123456'
    WHERE PARAM_ID IN (287, 288, 298, 299, 308, 309, 338, 215, 219);

    UPDATE VALS
    SET VAL = 'Учитель'
    WHERE PARAM_ID IN (291, 292, 301, 302);

    UPDATE VALS
    SET VAL = 'Околачивание груш в образовании'
    WHERE PARAM_ID IN (305);

    UPDATE VALS
    SET VAL = 'Просто так'
    WHERE PARAM_ID IN (276, 277, 294);

    UPDATE VALD
    SET VAL = VAL - 1000 * RAND()
    WHERE PARAM_ID IN (290, 300, 310, 224, 347, 339, 544, 213);

    -- Регид заменяем случайно сгенерированными значениями
    FOR
      SELECT OBJ_ID, PARAM_ID
      FROM VALS
      WHERE PARAM_ID IN (2912, 2915, 2917)
      ORDER BY 1, 2
      INTO :OBJ_ID, :TYPE_ID
    DO
    BEGIN
      S = '';
      WHILE(CHAR_LENGTH(S) < 32) DO
      BEGIN
        S = S || SUBSTRING('0123456789abcdef' FROM MINVALUE(1 + RAND() * 15, 15) FOR 1);
      END

      S = SUBSTRING(S FROM 1 FOR 8) || '-' || SUBSTRING(S FROM 9 FOR 4) || '-' || SUBSTRING(S FROM 13 FOR 4) || '-' || SUBSTRING(S FROM 17 FOR 4) || '-' || SUBSTRING(S FROM 21);

      UPDATE VALS
      SET VAL = :S
      WHERE OBJ_ID = :OBJ_ID AND PARAM_ID = :TYPE_ID;
    END

    -- Номера карт заменяем случайными значениями
    FOR
      SELECT OBJ_ID, PARAM_ID
      FROM VALS
      WHERE PARAM_ID IN (2855, 2857, 2918, 3273)
      ORDER BY 1, 2
      INTO :OBJ_ID, :TYPE_ID
    DO
    BEGIN
      S = '';
      WHILE(CHAR_LENGTH(S) < 6) DO
      BEGIN
        S = S || SUBSTRING('0123456789' FROM MINVALUE(RAND() * 10, 15) FOR 1);
      END

      S = '0000000000' || S || '0000000000000000';

      UPDATE VALS
      SET VAL = :S
      WHERE OBJ_ID = :OBJ_ID AND PARAM_ID = :TYPE_ID;
    END

    -- История
    DELETE FROM HISTVALS WHERE 1 = 1;
    DELETE FROM PDA_LOG WHERE 1 = 1;
    UPDATE SYNC_LOG SET MSG = 'X' WHERE 1 = 1;

    -- Юзеры
    DELETE FROM USERS WHERE USER_TYPE IN (12, 22);

    FOR
      SELECT USER_ID
      FROM USERS
      WHERE USER_ID > 1
      INTO :OBJ_ID
    DO
    BEGIN
      UPDATE USERS
      SET USER_NAME = 'user' || :OBJ_ID, FIRST_NAME = 'Hidden', LAST_NAME = 'Hidden', MIDDLE_NAME = 'Hidden', PWD = '*'
      WHERE USER_ID = :OBJ_ID;
    END

    -- Меняем название ОУ, ставим название = номер ключа
    FOR
      SELECT DISTINCT L2.OBJ_ID
      FROM LINKS L2
      WHERE L2.PARENT_ID IS NULL OR L2.PARENT_TYPE_ID IN (111, 112)
      INTO :OBJ_ID
    DO
    BEGIN
      N = OBJ_ID / 1000000000;
      UPDATE VALS
      SET VAL = 'ГБОУ СОШ №' || :N
      WHERE OBJ_ID = :OBJ_ID;
    END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OBJECTS_EXPORT_LIST (
    I$ROOT_ID BIGINT = null,
    I$OBJ_INDEX BIGINT = 0,
    I$LEVEL_ID BIGINT = null)
RETURNS (
    OBJ_INDEX BIGINT,
    PARENT_INDEX BIGINT,
    OBJ_ID BIGINT,
    TYPE_ID BIGINT,
    PARENT_ID BIGINT,
    SORT_ORDER DOUBLE PRECISION,
    CAPTION VARCHAR(4000),
    COLOR INTEGER,
    TYPE_ORDER SMALLINT,
    LINK_ID BIGINT,
    CHECKED SMALLINT,
    DATE_DEL TIMESTAMP)
AS
declare variable V$LEVEL_ID bigint;
declare variable V$ROOT_TYPE_ID bigint;
BEGIN
    PARENT_INDEX = I$OBJ_INDEX;
    OBJ_INDEX = PARENT_INDEX;
    CHECKED = 0;
    FOR
        SELECT DISTINCT OL.OBJ_ID, OL.PARENT_ID, OL.TYPE_ID, OL.SORT_ORDER, OL.CAPTION, OL.COLOR, OL.TYPE_ORDER, OL.LINK_ID, LV.LEVEL_ID, LV.ROOT_TYPE_ID, OL.DATE_DEL
        FROM LEVELS LV
        LEFT JOIN OBJECTS_LIST(:I$ROOT_ID, LV.LEVEL_ID, NULL, 1) OL ON OL.OBJ_ID IS NOT NULL
        JOIN LTYPES LT ON LT.LEVEL_ID = LV.LEVEL_ID AND LT.TYPE_ID = OL.TYPE_ID AND LT.IS_DEL = 0
        WHERE LV.IS_DEL = 0 AND (:I$LEVEL_ID IS NULL OR :I$LEVEL_ID = LV.LEVEL_ID) AND LV.IS_PREDEFINED = 1
        INTO :OBJ_ID, :PARENT_ID, :TYPE_ID, :SORT_ORDER, :CAPTION, :COLOR, :TYPE_ORDER, :LINK_ID, :V$LEVEL_ID, :V$ROOT_TYPE_ID, :DATE_DEL
    DO
    BEGIN
        -- Для LEVEL_ID = 202 нужно к заявленному типу 193 добавить типы 418 и 419
        IF(
            EXISTS(SELECT FIRST 1 1 FROM IS_NATIVE_ID(:OBJ_ID) WHERE IS_NATIVE = 1) AND
            ((PARENT_ID IS NULL) OR (EXISTS(SELECT FIRST 1 1 FROM IS_NATIVE_ID(:PARENT_ID) WHERE IS_NATIVE = 1))) AND
            OBJ_ID IS NOT NULL AND ((PARENT_ID IS NULL AND (V$ROOT_TYPE_ID = TYPE_ID OR (V$LEVEL_ID = 202 AND TYPE_ID IN (418, 419)))) OR (PARENT_ID IS NOT NULL))
        ) THEN
        BEGIN
            PARENT_INDEX = I$OBJ_INDEX;
            OBJ_INDEX = OBJ_INDEX + 1;
            SUSPEND;
            FOR
                SELECT OBJ_INDEX, PARENT_INDEX, OBJ_ID, TYPE_ID, PARENT_ID, SORT_ORDER, CAPTION, COLOR, TYPE_ORDER, LINK_ID, CHECKED, DATE_DEL
                FROM OBJECTS_EXPORT_LIST(:OBJ_ID, :OBJ_INDEX, :V$LEVEL_ID)
                INTO :OBJ_INDEX, :PARENT_INDEX, :OBJ_ID, :TYPE_ID, :PARENT_ID, :SORT_ORDER, :CAPTION, :COLOR, :TYPE_ORDER, :LINK_ID, :CHECKED, :DATE_DEL
            DO
            BEGIN
                SUSPEND;
            END
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OBJECTS_LIST (
    I$ROOT_ID BIGINT,
    I$LEVEL_ID BIGINT,
    I$USER_ID BIGINT,
    I$EXPORT_VIEW SMALLINT = 0,
    I$OBJ_ID BIGINT = null,
    I$FROM_IP VARCHAR(200) = null)
RETURNS (
    OBJ_ID BIGINT,
    TYPE_ID BIGINT,
    PARENT_ID BIGINT,
    PARENT_TYPE_ID BIGINT,
    USER_ID BIGINT,
    DATE_INS TIMESTAMP,
    DATE_DEL TIMESTAMP,
    SORT_ORDER DOUBLE PRECISION,
    CAPTION VARCHAR(4000),
    HAS_CHILD INTEGER,
    COLOR INTEGER,
    TAB_ID BIGINT,
    TYPE_ORDER SMALLINT,
    LINK_ID BIGINT,
    TAG VARCHAR(100))
AS
declare variable V$ROOT_TYPE_ID bigint = null;
declare variable V$PARENT_TYPE_ID bigint = null;
declare variable V$ROOT_OBJ_ID bigint = null;
declare variable V$ROOT_OBJ_ID2 bigint;
declare variable V$ROOT_OBJ_ID3 bigint;
declare variable V$ROOT_PARENT_ID bigint = null;
declare variable V$ROOT_PARENT_ID2 bigint;
declare variable V$ROOT_PARENT_ID3 bigint;
declare variable V$TYPE_USER bigint = null;
declare variable V$PERSON_ID bigint;
declare variable V$HIDE smallint;
declare variable V$LEVEL smallint;
declare variable V$TYPE_ID bigint;
declare variable V$SECTION_ID bigint;
declare variable T bigint;
BEGIN

  -- Логгируем доступ к ПД ?
  -- !!!

  -- Обычный вывод списка в середине дерева - только он и работает
  IF (I$ROOT_ID IS NOT NULL) THEN
  BEGIN
    -- В приложении СКУД и питание в корне дополнительно выдаем виртуальный список Сотрудники
    IF(I$LEVEL_ID = 475) THEN
    BEGIN
      SELECT TYPE_ID FROM OBJECTS WHERE OBJ_ID = :I$ROOT_ID INTO :V$TYPE_ID;

      IF(V$TYPE_ID = 2) THEN
      BEGIN
        OBJ_ID = -1;
        TYPE_ID = -1;
        PARENT_ID = I$ROOT_ID;
        PARENT_TYPE_ID = V$TYPE_ID;
        SORT_ORDER = -1;
        TYPE_ORDER = -1;
        LINK_ID = -1;
        USER_ID = 1;
        CAPTION = 'Сотрудники';
        COLOR = 0;
        TAG = '';

        HAS_CHILD = 0;
        SELECT FIRST 1 1
        FROM LINKS L14
        WHERE L14.PARENT_ID = :PARENT_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
        INTO :HAS_CHILD;

        SUSPEND;
      END
    END

    FOR
      SELECT OBJ_ID, TYPE_ID, PARENT_ID, USER_ID, DATE_INS, DATE_DEL, SORT_ORDER, CAPTION, HAS_CHILD, COLOR, TYPE_ORDER, LINK_ID, TAG, TAB_ID, PARENT_TYPE_ID
      FROM OBJECTS_LIST_RET(:I$ROOT_ID, :V$ROOT_OBJ_ID, :I$LEVEL_ID, :I$EXPORT_VIEW)
        INTO :OBJ_ID, :TYPE_ID, :PARENT_ID, :USER_ID, :DATE_INS, :DATE_DEL, :SORT_ORDER, :CAPTION, :HAS_CHILD, :COLOR, :TYPE_ORDER, :LINK_ID, :TAG, :TAB_ID, :PARENT_TYPE_ID
    DO
    BEGIN
      V$HIDE = 0;
      -- Сотрудников прячем из прямой выдачи в приложении СКУД и питание
      IF(I$LEVEL_ID = 475 AND V$TYPE_ID = 2 AND TYPE_ID = 14) THEN V$HIDE = 1;
      -- Для УДОД скрываем прямое отображение сотрудников в приложении Учебные коллективы на всех уровнях
      IF(I$LEVEL_ID IN (243, 267, 286) AND (PARENT_TYPE_ID IN (2, 211) AND TYPE_ID = 14)) THEN V$HIDE = 1;
      IF(V$HIDE = 0) THEN SUSPEND;
    END
    EXIT;
  END

  -- Прием обучающихся для сдачи ГИА - сразу же в корне выводим уровни образования
  IF (I$ROOT_ID IS NULL AND I$LEVEL_ID = 126) THEN
  BEGIN
    FOR
      SELECT OBJ_ID, TYPE_ID, PARENT_ID, USER_ID, DATE_INS, DATE_DEL, SORT_ORDER, CAPTION, HAS_CHILD, COLOR, TYPE_ORDER, LINK_ID, TAG, TAB_ID, PARENT_TYPE_ID
      FROM OBJECTS_LIST_RET_GIA
      INTO :OBJ_ID, :TYPE_ID, :PARENT_ID, :USER_ID, :DATE_INS, :DATE_DEL, :SORT_ORDER, :CAPTION, :HAS_CHILD, :COLOR, :TYPE_ORDER, :LINK_ID, :TAG, :TAB_ID, :PARENT_TYPE_ID
    DO
    BEGIN
      SUSPEND;
    END
    EXIT;
  END

  -- Далее трюки для отображения корня дерева

  -- Для некоторых уровней отображения идет сужение области отображения (например классные руководители видят только свои классы)
  -- Изменение 02.2025: теперь права ограничиваем не по одному ROOT_OBJ_ID, а гибридно через USERS.SECTION_ID и множественно для классруков и воспитателей
  SELECT L.ROOT_TYPE_ID, L.PARENT_TYPE_ID, LU.ROOT_OBJ_ID, LU.ROOT_PARENT_ID
  FROM LEVELS L
  JOIN LUSERS LU ON LU.LEVEL_ID = L.LEVEL_ID
  WHERE L.LEVEL_ID = :I$LEVEL_ID AND LU.USER_ID = :I$USER_ID
  INTO :V$ROOT_TYPE_ID, :V$PARENT_TYPE_ID, :V$ROOT_OBJ_ID, :V$ROOT_PARENT_ID;

  SELECT U.USER_TYPE, U.OBJ_ID, U.SECTION_ID
  FROM USERS U
  WHERE U.USER_ID = :I$USER_ID
  INTO :V$TYPE_USER, :V$PERSON_ID, :V$SECTION_ID;

  -- Роль классный руководитель ОУ/колледжа/ДОУ переключается на свой коллектив
  -- Роль руководитель отдела ОДОД переключается на свой отдел
  -- Максимально 3 учебных коллектива
  IF(V$TYPE_USER = 8 AND I$LEVEL_ID IN (50, 174, 305, 440, 23, 49, 241, 245, 533)) THEN
  BEGIN
    SELECT FIRST 1 KEY_VAL FROM KEYS WHERE KEY_CODE = 'LEVEL' INTO :V$LEVEL;

    -- Классы/группы
    V$ROOT_OBJ_ID = NULL; -- старую схема через LUSERS прибиваем навсегда
    FOR
      SELECT L9.OBJ_ID
      FROM LINKS L9
      JOIN VALR V53 ON V53.OBJ_ID = L9.OBJ_ID AND V53.PARAM_ID = 53 AND V53.IS_DEL = 0 AND V53.VAL = :V$PERSON_ID
      WHERE L9.PARENT_TYPE_ID = 8 AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL AND :V$LEVEL = 1
      UNION
      -- УДОД - отделы. Для преподавателей групп вообще не положен доступ
      SELECT L211.OBJ_ID
      FROM LINKS L211
      JOIN VALR V1793 ON V1793.OBJ_ID = L211.OBJ_ID AND V1793.PARAM_ID = 1793 AND V1793.IS_DEL = 0 AND V1793.VAL = :V$PERSON_ID
      WHERE L211.PARENT_TYPE_ID = 2 AND L211.OBJ_TYPE_ID = 211 AND L211.DATE_DEL IS NULL AND :V$LEVEL = 1
      -- ДОУ - воспитатели, хотя тут тоже доступ не положен совсем
      UNION
      SELECT L9.OBJ_ID
      FROM LINKS L9
      JOIN LINKS L165 ON L165.PARENT_ID = L9.OBJ_ID AND L165.OBJ_TYPE_ID = 165 AND L165.DATE_DEL IS NULL
      JOIN VALR V1556 ON V1556.OBJ_ID = L165.OBJ_ID AND V1556.PARAM_ID = 1556 AND V1556.IS_DEL = 0 AND V1556.VAL = :V$PERSON_ID
      WHERE L9.PARENT_TYPE_ID = 8 AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL AND :V$LEVEL = 1
      -- Регион - прикрепление пользователя к району ?
      /*SELECT 1211.OBJ_ID
      FROM LINKS L111
      JOIN VALR V1793 ON V1793.OBJ_ID = L211.OBJ_ID AND V1793.PARAM_ID = 1793 AND V1793.IS_DEL = 0 AND V1793.VAL = :V$PERSON_ID
      WHERE L111.PARENT_TYPE_ID = 112 AND L111.OBJ_TYPE_ID = 111 AND L111.DATE_DEL IS NULL AND :V$LEVEL = 3 */
      INTO :T
    DO
    BEGIN
      IF(V$ROOT_OBJ_ID IS NULL) THEN V$ROOT_OBJ_ID = T;
      ELSE IF(V$ROOT_OBJ_ID2 IS NULL) THEN V$ROOT_OBJ_ID2 = T;
      ELSE IF(V$ROOT_OBJ_ID3 IS NULL) THEN V$ROOT_OBJ_ID3 = T;
    END

    -- Если не удалось найти сущность привязки - выдаем пустоту
    IF(V$ROOT_OBJ_ID IS NULL) THEN EXIT;
  END

  -- Роль Завуч ограничивается по уровням образования в SECTION_ID
  -- битовая маска ДОО, НОО, ООО, СОО, СПО, профобучение, ДО
  -- если не указано, то ВСЕ
  -- Доразобраться что делать с предварительным приемом
  IF(V$TYPE_USER = 6 AND I$LEVEL_ID IN (50, 23, 49, 533, 535) AND V$SECTION_ID IS NOT NULL) THEN
  BEGIN
    FOR
      SELECT L7.OBJ_ID
      FROM LINKS L7
      JOIN VALL V43 ON V43.OBJ_ID = L7.OBJ_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0 AND (
        (V43.LISTVAL_ID IN (3263, 3264) AND BIN_AND(:V$SECTION_ID, 1) <> 0) OR
        (V43.LISTVAL_ID = 22 AND BIN_AND(:V$SECTION_ID, 2) <> 0) OR
        (V43.LISTVAL_ID = 26 AND BIN_AND(:V$SECTION_ID, 4) <> 0) OR
        (V43.LISTVAL_ID = 27 AND BIN_AND(:V$SECTION_ID, 8) <> 0) OR
        (V43.LISTVAL_ID IN (28, 29) AND BIN_AND(:V$SECTION_ID, 16) <> 0) OR
        (V43.LISTVAL_ID = 13131 AND BIN_AND(:V$SECTION_ID, 32) <> 0) OR
        (V43.LISTVAL_ID = 13128 AND BIN_AND(:V$SECTION_ID, 64) <> 0)
      )
      WHERE L7.PARENT_TYPE_ID = 2 AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL AND :V$LEVEL = 1
      INTO :T
    DO
    BEGIN
      IF(V$ROOT_OBJ_ID IS NULL) THEN V$ROOT_OBJ_ID = T;
      ELSE IF(V$ROOT_OBJ_ID2 IS NULL) THEN V$ROOT_OBJ_ID2 = T;
      ELSE IF(V$ROOT_OBJ_ID3 IS NULL) THEN V$ROOT_OBJ_ID3 = T;
    END
  END

  -- Для отображения МОИ ДАННЫЕ надо переставить ROOT_ID в OBJ_ID, а в ROOT_ID поставить подходящего (причем школа в самом низком приоритете)
  IF(I$LEVEL_ID IN (48, 50) AND I$OBJ_ID IS NOT NULL) THEN
  BEGIN
    V$ROOT_OBJ_ID = I$OBJ_ID;
    /*SELECT FIRST 1 LPG.PARENT_ID
    FROM LINKS LPG
    WHERE LPG.OBJ_ID = :V$ROOT_OBJ_ID AND LPG.PARENT_TYPE_ID IN (2, 211, 9, 187) AND LPG.DATE_DEL IS NULL
    ORDER BY LPG.PARENT_TYPE_ID DESC
    INTO :I$ROOT_ID;*/
  END

  IF (V$ROOT_OBJ_ID IS NULL AND V$ROOT_PARENT_ID IS NOT NULL) THEN
  BEGIN
    -- Эта ветка вообще хоть где-то работает ?
    FOR
      SELECT OBJ_ID, TYPE_ID, PARENT_ID, USER_ID, DATE_INS, DATE_DEL, SORT_ORDER, CAPTION, HAS_CHILD, COLOR, TYPE_ORDER, LINK_ID, TAG, TAB_ID
      FROM OBJECTS_LIST_RET(:V$ROOT_PARENT_ID, :V$ROOT_OBJ_ID, :I$LEVEL_ID, :I$EXPORT_VIEW)
      INTO :OBJ_ID, :TYPE_ID, :PARENT_ID, :USER_ID, :DATE_INS, :DATE_DEL, :SORT_ORDER, :CAPTION, :HAS_CHILD, :COLOR, :TYPE_ORDER, :LINK_ID, :TAG, :TAB_ID
    DO
    BEGIN
      SUSPEND;
    END
    EXIT;
  END

  IF (V$ROOT_OBJ_ID IS NOT NULL AND V$ROOT_PARENT_ID IS NULL) THEN
  BEGIN
    -- Непонятно зачем для завучей занулять V$ROOT_OBJ_ID - это разве что ошибка ?
    -- Родитель у всех ROOT_OBJ_ID может оказаться разным, например НОО и ООО
    -- IF (I$LEVEL_ID IN (50, 174, 305, 440) AND V$TYPE_USER = 6) THEN V$ROOT_OBJ_ID = NULL;
    -- Ограничиваем выбор для ГПД и ДО, поскольку они попадают в тот же LEVEL_ID что и обычные классы
    SELECT FIRST 1 L.PARENT_ID
    FROM LINKS L
    JOIN TYPES T ON T.TYPE_ID = L.PARENT_TYPE_ID AND T.IS_DEL = 0
    JOIN LTYPES LT ON LT.TYPE_ID = L.PARENT_TYPE_ID AND LT.LEVEL_ID = :I$LEVEL_ID AND LT.IS_DEL = 0
    WHERE L.OBJ_ID = :V$ROOT_OBJ_ID AND (:I$EXPORT_VIEW = 1 OR L.DATE_DEL IS NULL) AND L.PARENT_TYPE_ID <> 46
    INTO :V$ROOT_PARENT_ID;

    IF(V$ROOT_OBJ_ID2 IS NOT NULL) THEN
    BEGIN
      SELECT FIRST 1 L.PARENT_ID
      FROM LINKS L
      JOIN TYPES T ON T.TYPE_ID = L.PARENT_TYPE_ID AND T.IS_DEL = 0
      JOIN LTYPES LT ON LT.TYPE_ID = L.PARENT_TYPE_ID AND LT.LEVEL_ID = :I$LEVEL_ID AND LT.IS_DEL = 0
      WHERE L.OBJ_ID = :V$ROOT_OBJ_ID2 AND (:I$EXPORT_VIEW = 1 OR L.DATE_DEL IS NULL) AND L.PARENT_TYPE_ID <> 46
      INTO :V$ROOT_PARENT_ID2;
    END

    IF(V$ROOT_OBJ_ID3 IS NOT NULL) THEN
    BEGIN
      SELECT FIRST 1 L.PARENT_ID
      FROM LINKS L
      JOIN TYPES T ON T.TYPE_ID = L.PARENT_TYPE_ID AND T.IS_DEL = 0
      JOIN LTYPES LT ON LT.TYPE_ID = L.PARENT_TYPE_ID AND LT.LEVEL_ID = :I$LEVEL_ID AND LT.IS_DEL = 0
      WHERE L.OBJ_ID = :V$ROOT_OBJ_ID3 AND (:I$EXPORT_VIEW = 1 OR L.DATE_DEL IS NULL) AND L.PARENT_TYPE_ID <> 46
      INTO :V$ROOT_PARENT_ID3;
    END
  END

  IF (V$ROOT_OBJ_ID IS NOT NULL AND V$ROOT_PARENT_ID IS NOT NULL) THEN
  BEGIN
    FOR
      SELECT OBJ_ID, TYPE_ID, PARENT_ID, USER_ID, DATE_INS, DATE_DEL, SORT_ORDER, CAPTION, HAS_CHILD, COLOR, TYPE_ORDER, LINK_ID, TAG, TAB_ID
      FROM OBJECTS_LIST_RET(:V$ROOT_PARENT_ID, :V$ROOT_OBJ_ID, :I$LEVEL_ID, :I$EXPORT_VIEW)
      INTO :OBJ_ID, :TYPE_ID, :PARENT_ID, :USER_ID, :DATE_INS, :DATE_DEL, :SORT_ORDER, :CAPTION, :HAS_CHILD, :COLOR, :TYPE_ORDER, :LINK_ID, :TAG, :TAB_ID
    DO
    BEGIN
      SUSPEND;
    END
    -- Второй и третий запасные варианты
    IF(V$ROOT_OBJ_ID2 IS NOT NULL) THEN
    BEGIN
      FOR
        SELECT OBJ_ID, TYPE_ID, PARENT_ID, USER_ID, DATE_INS, DATE_DEL, SORT_ORDER, CAPTION, HAS_CHILD, COLOR, TYPE_ORDER, LINK_ID, TAG, TAB_ID
        FROM OBJECTS_LIST_RET(:V$ROOT_PARENT_ID2, :V$ROOT_OBJ_ID2, :I$LEVEL_ID, :I$EXPORT_VIEW)
        INTO :OBJ_ID, :TYPE_ID, :PARENT_ID, :USER_ID, :DATE_INS, :DATE_DEL, :SORT_ORDER, :CAPTION, :HAS_CHILD, :COLOR, :TYPE_ORDER, :LINK_ID, :TAG, :TAB_ID
      DO
      BEGIN
        SUSPEND;
      END
    END
    IF(V$ROOT_OBJ_ID3 IS NOT NULL) THEN
    BEGIN
      FOR
        SELECT OBJ_ID, TYPE_ID, PARENT_ID, USER_ID, DATE_INS, DATE_DEL, SORT_ORDER, CAPTION, HAS_CHILD, COLOR, TYPE_ORDER, LINK_ID, TAG, TAB_ID
        FROM OBJECTS_LIST_RET(:V$ROOT_PARENT_ID3, :V$ROOT_OBJ_ID3, :I$LEVEL_ID, :I$EXPORT_VIEW)
        INTO :OBJ_ID, :TYPE_ID, :PARENT_ID, :USER_ID, :DATE_INS, :DATE_DEL, :SORT_ORDER, :CAPTION, :HAS_CHILD, :COLOR, :TYPE_ORDER, :LINK_ID, :TAG, :TAB_ID
      DO
      BEGIN
        SUSPEND;
      END
    END
    EXIT;
  END

  IF (V$ROOT_TYPE_ID IS NOT NULL AND V$PARENT_TYPE_ID IS NULL) THEN
  BEGIN
    FOR
      SELECT OBJ_ID, TYPE_ID, PARENT_ID, USER_ID, DATE_INS, DATE_DEL, SORT_ORDER, CAPTION, HAS_CHILD, COLOR, TYPE_ORDER, LINK_ID, TAG, TAB_ID
      FROM OBJECTS_LIST_RET(:I$ROOT_ID, :V$ROOT_OBJ_ID, :I$LEVEL_ID, :I$EXPORT_VIEW)
      WHERE TYPE_ID = :V$ROOT_TYPE_ID
        -- Добавляем объекты в приложение дисциплин для колледжей
        -- предметы в приложение ОП и УП для садов
        OR (:I$LEVEL_ID IN (202, 229, 463) AND TYPE_ID IN (:V$ROOT_OBJ_ID, 418, 419, 53))
      INTO :OBJ_ID, :TYPE_ID, :PARENT_ID, :USER_ID, :DATE_INS, :DATE_DEL, :SORT_ORDER, :CAPTION, :HAS_CHILD, :COLOR, :TYPE_ORDER, :LINK_ID, :TAG, :TAB_ID
    DO
    BEGIN
      SUSPEND;
    END
    EXIT;
  END

  IF (V$ROOT_TYPE_ID IS NOT NULL AND V$PARENT_TYPE_ID IS NOT NULL) THEN
  BEGIN
    IF (NOT EXISTS(
      SELECT FIRST 1 1
      FROM LINKS L
      WHERE L.PARENT_TYPE_ID = :V$PARENT_TYPE_ID AND L.OBJ_TYPE_ID = :V$ROOT_TYPE_ID AND (:I$EXPORT_VIEW = 1 OR L.DATE_DEL IS NULL)
    )
    AND EXISTS(
      SELECT FIRST 1 1
      FROM PARENTS P
      WHERE P.CHILD_ID = :V$ROOT_TYPE_ID AND P.TYPE_ID = :V$PARENT_TYPE_ID AND P.IS_AUTO_CREATE = 1
    )) THEN
    BEGIN
      FOR
        SELECT FIRST 1 OBJ_ID
        FROM LINKS
        WHERE PARENT_ID IS NULL AND OBJ_TYPE_ID = :V$PARENT_TYPE_ID AND (:I$EXPORT_VIEW = 1 OR DATE_DEL IS NULL)
        AND EXISTS(
          SELECT FIRST 1 1
          FROM IS_NATIVE_ID(OBJ_ID)
          WHERE IS_NATIVE = 1
        )
        INTO :PARENT_ID
      DO
      BEGIN
        EXECUTE STATEMENT('SELECT OBJ_ID FROM OBJECT_ADD(' || :PARENT_ID || ', ' || :V$ROOT_TYPE_ID || ')') WITH AUTONOMOUS TRANSACTION
        INTO :OBJ_ID;
      END
    END
    FOR
      SELECT L.PARENT_ID, L.OBJ_ID
      FROM LINKS L
      WHERE L.PARENT_TYPE_ID = :V$PARENT_TYPE_ID AND L.OBJ_TYPE_ID = :V$ROOT_TYPE_ID AND L.DATE_DEL IS NULL
      INTO :V$ROOT_PARENT_ID, :V$ROOT_OBJ_ID
    DO
    BEGIN
      FOR
        SELECT OBJ_ID, TYPE_ID, PARENT_ID, USER_ID, DATE_INS, DATE_DEL, SORT_ORDER, CAPTION, HAS_CHILD, COLOR, TYPE_ORDER, LINK_ID, TAG, TAB_ID
        FROM OBJECTS_LIST_RET(:V$ROOT_PARENT_ID, :V$ROOT_OBJ_ID, :I$LEVEL_ID, :I$EXPORT_VIEW)
        INTO :OBJ_ID, :TYPE_ID, :PARENT_ID, :USER_ID, :DATE_INS, :DATE_DEL, :SORT_ORDER, :CAPTION, :HAS_CHILD, :COLOR, :TYPE_ORDER, :LINK_ID, :TAG, :TAB_ID
      DO
      BEGIN
        SUSPEND;
      END
    END
    EXIT;
  END

  IF (V$ROOT_TYPE_ID IS NULL) THEN
  BEGIN
    FOR
      SELECT OBJ_ID, TYPE_ID, PARENT_ID, USER_ID, DATE_INS, DATE_DEL, SORT_ORDER, CAPTION, HAS_CHILD, COLOR, TYPE_ORDER, LINK_ID, TAG, TAB_ID
      FROM OBJECTS_LIST_RET(:I$ROOT_ID, :V$ROOT_OBJ_ID, :I$LEVEL_ID, :I$EXPORT_VIEW)
      INTO :OBJ_ID, :TYPE_ID, :PARENT_ID, :USER_ID, :DATE_INS, :DATE_DEL, :SORT_ORDER, :CAPTION, :HAS_CHILD, :COLOR, :TYPE_ORDER, :LINK_ID, :TAG, :TAB_ID
    DO
    BEGIN
      SUSPEND;
    END
    EXIT;
  END

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OBJECTS_LIST_RET (
    I$ROOT_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$LEVEL_ID BIGINT,
    I$EXPORT_VIEW SMALLINT = 0)
RETURNS (
    OBJ_ID BIGINT,
    TYPE_ID BIGINT,
    PARENT_ID BIGINT,
    PARENT_TYPE_ID BIGINT,
    USER_ID BIGINT,
    DATE_INS TIMESTAMP,
    DATE_DEL TIMESTAMP,
    SORT_ORDER DOUBLE PRECISION,
    CAPTION VARCHAR(4000),
    HAS_CHILD INTEGER,
    COLOR INTEGER,
    TAB_ID BIGINT,
    TYPE_ORDER SMALLINT,
    LINK_ID BIGINT,
    TAG VARCHAR(100))
AS
DECLARE VARIABLE V$FILTER_TYPE BIGINT;
DECLARE VARIABLE CHILD_TYPE_ID BIGINT;
DECLARE VARIABLE SHOW_DEL BIGINT;
DECLARE VARIABLE V$HIDE SMALLINT;
BEGIN
    USER_ID = NULL;

    -- Обманка для отображения сотрудников в папке "Сотрудники" в приложении СКУД/Питание
    IF(I$LEVEL_ID = 475 AND I$ROOT_ID = -1) THEN
    BEGIN
      V$FILTER_TYPE = 14;

      SELECT FIRST 1 OBJ_ID
      FROM LINKS
      WHERE PARENT_ID IS NULL AND OBJ_TYPE_ID = 2 AND DATE_DEL IS NULL
      INTO :I$ROOT_ID;
    END

    FOR
      SELECT L.PARENT_ID, L.OBJ_ID, L.DATE_INS, L.DATE_DEL, L.OBJ_TYPE_ID, T.SORT_ORDER, L.LINK_ID, T.TAG, P.TAB_ID, L.PARENT_TYPE_ID
      FROM LINKS L
      JOIN TYPES T ON T.TYPE_ID = L.OBJ_TYPE_ID AND T.IS_DEL = 0
      JOIN LTYPES LT ON LT.TYPE_ID = L.OBJ_TYPE_ID AND LT.LEVEL_ID = :I$LEVEL_ID AND LT.IS_DEL = 0 AND LT.EDIT_TYPE >= 0
      LEFT JOIN PARENTS P ON P.TYPE_ID = L.PARENT_TYPE_ID AND P.CHILD_ID = L.OBJ_TYPE_ID AND P.IS_DEL = 0
      WHERE (L.PARENT_ID = :I$ROOT_ID OR (:I$ROOT_ID IS NULL AND L.PARENT_ID IS NULL))
        AND (:I$OBJ_ID IS NULL OR L.OBJ_ID = :I$OBJ_ID)
        AND (:I$EXPORT_VIEW = 1 OR LT.SHOW_DEL = 1 OR L.DATE_DEL IS NULL)
        AND (:I$EXPORT_VIEW = 1 OR LT.EDIT_TYPE = 0 OR LT.EDIT_TYPE = 1)
        AND (:I$EXPORT_VIEW = 1 OR P.TAB_ID IS NULL)
        AND (:I$EXPORT_VIEW = 1 OR T.IS_HIDDEN = 0)
        AND (:V$FILTER_TYPE IS NULL OR L.OBJ_TYPE_ID = :V$FILTER_TYPE)
      INTO :PARENT_ID, :OBJ_ID, :DATE_INS, :DATE_DEL, :TYPE_ID, :TYPE_ORDER, :LINK_ID, :TAG, :TAB_ID, :PARENT_TYPE_ID
    DO
    BEGIN
      SELECT CAPTION, SORT_ORDER, COLOR
      FROM OBJECT_CAPTION_GET(:OBJ_ID, :I$LEVEL_ID, NULL)
      INTO :CAPTION, :SORT_ORDER, :COLOR;

      IF (TYPE_ID = 10 AND I$LEVEL_ID = 126) THEN
      BEGIN
        SELECT FIRST 1 LP82_83.DATE_INS
        FROM LINKS LP82_83
        WHERE LP82_83.PARENT_TYPE_ID IN (82, 83) AND LP82_83.PARENT_ID <> :PARENT_ID AND LP82_83.OBJ_ID = :OBJ_ID AND LP82_83.DATE_DEL IS NULL
        INTO :DATE_DEL;
      END

      HAS_CHILD = 0;

      FOR
        SELECT P.CHILD_ID, LT.SHOW_DEL
        FROM PARENTS P
        JOIN TYPES T ON T.TYPE_ID = P.CHILD_ID AND T.IS_DEL = 0
        JOIN LTYPES LT ON LT.TYPE_ID = P.CHILD_ID AND LT.LEVEL_ID = :I$LEVEL_ID AND LT.IS_DEL = 0 AND LT.EDIT_TYPE >= 0
        WHERE P.TYPE_ID = :TYPE_ID AND P.IS_DEL = 0
          AND ((:I$EXPORT_VIEW = 1) OR (P.TAB_ID IS NULL))
          AND ((:I$EXPORT_VIEW = 1) OR (LT.EDIT_TYPE = 0) OR (LT.EDIT_TYPE = 1))
          AND ((:I$EXPORT_VIEW = 1) OR (T.IS_HIDDEN = 0))
        INTO :CHILD_TYPE_ID, :SHOW_DEL
      DO
      BEGIN
        IF (HAS_CHILD = 0) THEN
        BEGIN
          -- Прячем кнопку раскрытия дерева для определенных случаем
          V$HIDE = 0;
          -- Сотрудников прячем из прямой выдачи в приложении СКУД и питание
          IF(I$LEVEL_ID = 475 AND ((TYPE_ID IS NULL OR TYPE_ID = 2) AND CHILD_TYPE_ID = 14)) THEN V$HIDE = 1;
          -- Для УДОД скрываем прямое отображение сотрудников в приложении Учебные коллективы на всех уровнях
          IF(I$LEVEL_ID IN (243, 267, 286) AND (TYPE_ID IN (2, 211) AND CHILD_TYPE_ID = 14)) THEN V$HIDE = 1;
          -- Группы переменного состава прячем из корня всегда
          IF((TYPE_ID IS NULL OR TYPE_ID = 2) AND CHILD_TYPE_ID = 179) THEN V$HIDE = 1;

          SELECT FIRST 1 1
          FROM LINKS L
          WHERE L.PARENT_ID = :OBJ_ID AND L.OBJ_TYPE_ID = :CHILD_TYPE_ID
            AND (:I$EXPORT_VIEW = 1 OR :SHOW_DEL = 1 OR L.DATE_DEL IS NULL)
            AND :V$HIDE = 0
          INTO :HAS_CHILD;
        END
      END

      -- Теперь прячем сами дочерние объекты
      V$HIDE = 0;
      IF((PARENT_TYPE_ID IS NULL OR PARENT_TYPE_ID = 2) AND TYPE_ID = 179) THEN V$HIDE = 1;

      -- Скрываем документы связи родитель-ученик для чужих учеников
      -- если родитель был удален для конкретного ученика, документ станет виден
      IF(TYPE_ID = 294) THEN
      BEGIN
        SELECT FIRST 1 1
        FROM LINKS LP10
        LEFT JOIN VALR V3469 ON V3469.OBJ_ID = :OBJ_ID AND V3469.PARAM_ID = 3469 AND V3469.IS_DEL = 0
        WHERE LP10.OBJ_ID = :PARENT_ID AND LP10.PARENT_TYPE_ID = 10 AND LP10.DATE_DEL IS NULL AND (V3469.VAL IS NULL OR V3469.VAL <> LP10.PARENT_ID)
        INTO :V$HIDE;
      END

      IF(V$HIDE = 0) THEN SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OBJECTS_LIST_RET_GIA RETURNS (
    OBJ_ID BIGINT,
    TYPE_ID BIGINT,
    PARENT_ID BIGINT,
    PARENT_TYPE_ID BIGINT,
    USER_ID BIGINT,
    DATE_INS TIMESTAMP,
    DATE_DEL TIMESTAMP,
    SORT_ORDER DOUBLE PRECISION,
    CAPTION VARCHAR(4000),
    HAS_CHILD INTEGER,
    COLOR INTEGER,
    TAB_ID BIGINT,
    TYPE_ORDER SMALLINT,
    LINK_ID BIGINT,
    TAG VARCHAR(100))
AS
DECLARE VARIABLE CHILD_TYPE_ID BIGINT;
DECLARE VARIABLE SHOW_DEL BIGINT;
DECLARE VARIABLE SCHOOL_ID BIGINT;
BEGIN
    USER_ID = NULL;

    SELECT FIRST 1 L.OBJ_ID
    FROM LINKS L
    WHERE L.PARENT_ID IS NULL
      AND L.OBJ_TYPE_ID = 2
      AND L.DATE_DEL IS NULL
    INTO :SCHOOL_ID;

    FOR SELECT L.PARENT_ID, L.OBJ_ID, L.DATE_INS, L.DATE_DEL, L.OBJ_TYPE_ID, T.SORT_ORDER, L.LINK_ID, T.TAG,
               P.TAB_ID, L.PARENT_TYPE_ID
        FROM LINKS L7
        JOIN LINKS L ON L.PARENT_ID = L7.OBJ_ID
        JOIN TYPES T ON T.TYPE_ID = L.OBJ_TYPE_ID
        JOIN LTYPES LT ON LT.TYPE_ID = L.OBJ_TYPE_ID
        JOIN VALL V ON V.OBJ_ID = L.OBJ_ID
        LEFT JOIN PARENTS P ON P.TYPE_ID = L.PARENT_TYPE_ID AND P.CHILD_ID = L.OBJ_TYPE_ID AND P.IS_DEL = 0
        WHERE L7.PARENT_ID = :SCHOOL_ID
          AND L7.OBJ_TYPE_ID = 7
          AND L7.DATE_DEL IS NULL
          AND LT.LEVEL_ID = 126
          AND LT.IS_DEL = 0
          AND ((LT.SHOW_DEL = 1) OR (L.DATE_DEL IS NULL))
          AND ((LT.EDIT_TYPE = 0) OR (LT.EDIT_TYPE = 1))
          AND P.TAB_ID IS NULL
          AND T.IS_HIDDEN = 0
          AND T.IS_DEL = 0
          AND V.PARAM_ID = 49
          AND V.IS_DEL = 0
          AND V.LISTVAL_ID IN (45,47,48)
        INTO :PARENT_ID, :OBJ_ID, :DATE_INS, :DATE_DEL, :TYPE_ID, :TYPE_ORDER, :LINK_ID, :TAG, :TAB_ID, :PARENT_TYPE_ID
    DO
    BEGIN
        SELECT CAPTION, SORT_ORDER, COLOR
        FROM OBJECT_CAPTION_GET(:OBJ_ID, 126, NULL)
        INTO :CAPTION, :SORT_ORDER, :COLOR;

        HAS_CHILD = 0;

        FOR SELECT P.CHILD_ID, LT.SHOW_DEL
            FROM PARENTS P
            JOIN TYPES T ON T.TYPE_ID = P.CHILD_ID
            JOIN LTYPES LT ON LT.TYPE_ID = P.CHILD_ID
            WHERE P.TYPE_ID = :TYPE_ID
              AND P.TAB_ID IS NULL
              AND P.IS_DEL = 0
              AND T.IS_DEL = 0
              AND LT.LEVEL_ID = 126
              AND LT.IS_DEL = 0
              AND ((LT.EDIT_TYPE = 0) OR (LT.EDIT_TYPE = 1))
              AND T.IS_HIDDEN = 0
            INTO :CHILD_TYPE_ID, :SHOW_DEL
        DO
        BEGIN
            IF (:HAS_CHILD = 0) THEN
            BEGIN
                SELECT FIRST 1 1
                FROM LINKS L
                WHERE L.PARENT_ID = :OBJ_ID
                  AND L.OBJ_TYPE_ID = :CHILD_TYPE_ID
                  AND ((:SHOW_DEL = 1) OR (L.DATE_DEL IS NULL))
                INTO :HAS_CHILD;
            END
        END

        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OBJECT_ADD (
    I$PARENT_ID BIGINT,
    I$TYPE_ID BIGINT,
    I$REASON_ID BIGINT = NULL,
    I$LISTVAL_ID BIGINT = NULL,
    I$USER_ID BIGINT = NULL,
    I$COST FLOAT = 0,
    I$LEVEL_ID BIGINT = NULL,
    I$DATE_INS TIMESTAMP = CURRENT_TIMESTAMP,
    I$EXT_TYPE_ID BIGINT = NULL)
RETURNS (
    OBJ_ID BIGINT,
    TYPE_ID BIGINT,
    PARENT_ID BIGINT,
    PARENT_TYPE_ID BIGINT,
    USER_ID BIGINT,
    DATE_INS TIMESTAMP,
    DATE_DEL TIMESTAMP,
    SORT_ORDER DOUBLE PRECISION,
    CAPTION VARCHAR(4000),
    HAS_CHILD INTEGER,
    COLOR INTEGER,
    TAB_ID BIGINT,
    TYPE_ORDER SMALLINT,
    LINK_ID BIGINT,
    EXT_OBJ_TYPE_ID BIGINT,
    EXT_OBJ_ID BIGINT)
AS
DECLARE VARIABLE IS_ADD SMALLINT;
DECLARE VARIABLE AUTO_VAL VARCHAR(4000);
DECLARE VARIABLE BLOB_ID BIGINT;
DECLARE VARIABLE TAG VARCHAR(100);
DECLARE VARIABLE X BIGINT;
DECLARE VARIABLE Y BIGINT;
DECLARE VARIABLE N INTEGER;
DECLARE VARIABLE V$OU_TYPE VARCHAR(2);
DECLARE VARIABLE V$LEVEL VARCHAR(10);
BEGIN
    IF (I$DATE_INS IS NULL) THEN I$DATE_INS = CURRENT_TIMESTAMP;

    EXT_OBJ_TYPE_ID = I$EXT_TYPE_ID;
    EXT_OBJ_ID = NULL;
    TYPE_ID = I$TYPE_ID;
    PARENT_ID = I$PARENT_ID;
    USER_ID = I$USER_ID;
    DATE_INS = I$DATE_INS;
    DATE_DEL = NULL;
    SORT_ORDER = 0;
    CAPTION = '<  ...  >';
    COLOR = 0;
    IS_ADD = 0;
    TAB_ID = NULL;

    V$OU_TYPE = (SELECT STATUS FROM OU_LICENCE_TYPE);

    IF(I$COST IS NULL) THEN I$COST = 0;

    -- Блокируем добавление объектов в корень дерева
    IF(I$PARENT_ID IS NULL AND I$TYPE_ID NOT IN (2, 111, 112, 53, 55, 118, 224, 248, 251, 193, 241, 377, 124, 418, 419)) THEN
    BEGIN
        EXCEPTION DATA_ERROR 'Недопустимый тип объекта в корне дерева (' || I$TYPE_ID || ')';
    END

    -- Не даем добавлять 2+ корневых записей
    IF(I$PARENT_ID IS NULL AND I$TYPE_ID IN (2, 111, 112, 124)) THEN
    BEGIN
      V$LEVEL = (SELECT KEY_VAL FROM KEYS WHERE KEY_CODE = 'LEVEL');
      IF(
        (I$TYPE_ID = 112 AND V$LEVEL = '3' AND EXISTS(SELECT FIRST 1 1 FROM LINKS WHERE PARENT_ID IS NULL AND OBJ_TYPE_ID = 112 AND DATE_DEL IS NULL)) OR
        (I$TYPE_ID = 111 AND V$LEVEL = '2' AND EXISTS(SELECT FIRST 1 1 FROM LINKS WHERE PARENT_ID IS NULL AND OBJ_TYPE_ID = 111 AND DATE_DEL IS NULL)) OR
        (I$TYPE_ID IN (2, 124) AND V$LEVEL = '1' AND EXISTS(SELECT FIRST 1 1 FROM LINKS WHERE PARENT_ID IS NULL AND OBJ_TYPE_ID IN (2, 124) AND DATE_DEL IS NULL))
      )
      THEN
        EXCEPTION DATA_ERROR 'Можно добавить только один корневой объект данного типа';
    END

    -- Длительный отпуск
    IF (TYPE_ID = 376) THEN EXECUTE PROCEDURE LONGVACATION_ADD(:I$PARENT_ID);

    -- Нельзя добавлять наставников у уволенных
    IF(TYPE_ID = 397) THEN
    BEGIN
        IF(NOT EXISTS(
            SELECT FIRST 1 1
            FROM LINKS LP
            WHERE LP.OBJ_ID = :I$PARENT_ID AND LP.PARENT_TYPE_ID IN (2, 211) AND LP.DATE_DEL IS NULL
        )) THEN EXCEPTION DATA_ERROR 'Наставниками могут быть только действующие сотрудники';
    END

    -- Государственное задание
    IF (TYPE_ID IN (441, 442, 443, 444, 447, 453)) THEN EXECUTE PROCEDURE GZ_ADD_CHECK(:I$PARENT_ID, :I$TYPE_ID);

    -- Каталоги ГПД и ГИА - должен быть уникальный раздел
    IF(TYPE_ID IN (500, 502)) THEN
    BEGIN
      IF(EXISTS(
        SELECT FIRST 1 1
        FROM LINKS L500
        WHERE L500.PARENT_ID = :I$PARENT_ID AND L500.OBJ_TYPE_ID = :TYPE_ID AND L500.DATE_DEL IS NULL
      )) THEN EXCEPTION DATA_ERROR 'Каталоги ГПД и ГИА должны быть единственными в системе, нельзя добавить повторно';
    END

    -- Нельзя добавлять класс для сдачи Гиа (125) в ветку 2-7-8 для мультапараграфа
    IF(TYPE_ID = 125 AND V$OU_TYPE = 'S') THEN
    BEGIN
      IF (NOT EXISTS(
        SELECT FIRST 1 L.PARENT_TYPE_ID
        FROM LINKS L
        WHERE L.OBJ_ID = :I$PARENT_ID AND L.DATE_DEL IS NULL AND L.PARENT_TYPE_ID = 502))  -- Регистрация для сдачи ГИА
      THEN
        EXCEPTION DATA_ERROR 'Класс для выпускников, принятых для сдачи ГИА, не может быть добавлен в выбранную ступень обучения';
    END

    SELECT P.IS_ADD + P.IS_INTERNAL_ADD, P.TAB_ID, O.TYPE_ID
    FROM OBJECTS O
    JOIN PARENTS P ON P.TYPE_ID = O.TYPE_ID AND P.CHILD_ID = :I$TYPE_ID AND P.IS_DEL = 0
    WHERE O.OBJ_ID = :I$PARENT_ID
    INTO :IS_ADD, :TAB_ID, :PARENT_TYPE_ID;

    IF ((I$PARENT_ID IS NOT NULL) AND (IS_ADD < 1)) THEN EXIT;

    SELECT COLOR, SORT_ORDER, TAG
    FROM TYPES
    WHERE TYPE_ID = :I$TYPE_ID
    INTO :COLOR, :TYPE_ORDER, :TAG;

    -- AND V$OU_TYPE <> 'C'
    IF (TYPE_ID = 50 AND PARENT_TYPE_ID = 57) THEN
    BEGIN
        EXCEPTION DATA_ERROR 'Учебные планы старого формата больше нельзя добавить, используйте учебные планы нового формата';
    END

    -- Блокируем добавление периодов по старой схеме
    IF (TYPE_ID = 151 AND PARENT_TYPE_ID = 150) THEN EXCEPTION DATA_ERROR 'Расписание периодов с 2024 года создается только через календарный учебный график';

    INSERT INTO OBJECTS (TYPE_ID)
    VALUES (:TYPE_ID)
    RETURNING OBJ_ID
    INTO :OBJ_ID;

    IF (TYPE_ID = 245) THEN
    BEGIN
        -- Для УП профессионального обучения добавляем неудаляемый этап
        SELECT NULL FROM OBJECT_ADD(:OBJ_ID, 247, NULL, NULL, :USER_ID, 0, :I$LEVEL_ID) INTO :BLOB_ID;
    END

    IF (TYPE_ID = 400) THEN
    BEGIN
        EXECUTE PROCEDURE OBJECT_ADD_400(:I$PARENT_ID, :OBJ_ID, :USER_ID, :V$OU_TYPE);
    END

    IF (TYPE_ID = 46) THEN
    BEGIN
        -- Для группы ДПО ставим скрытый тип Группа
        IF(V$OU_TYPE = 'P') THEN
        BEGIN
            SELECT BLOB_ID FROM VAL_ADD(369, :OBJ_ID, 1719) INTO :BLOB_ID;
        END
    END

    -- Этап учебного плана - в СПО руками добавлять нельзя
    IF (PARENT_TYPE_ID = 400 AND TYPE_ID = 54) THEN
    BEGIN
        EXECUTE PROCEDURE PLAN_STAGE_VERIFY(:I$PARENT_ID, :I$USER_ID);
    END

    -- Добавление штатного расписания, Проект ШР должен быть уникальным (RM №1172)
    IF (PARENT_TYPE_ID = 508 AND TYPE_ID = 505) THEN
    BEGIN
        IF (EXISTS(SELECT FIRST 1 1
            FROM LINKS L505
            JOIN VALL V3490 ON V3490.OBJ_ID = L505.OBJ_ID AND V3490.PARAM_ID = 3490 AND V3490.IS_DEL = 0 AND V3490.LISTVAL_ID IS NOT NULL AND V3490.LISTVAL_ID = 11716
            WHERE L505.OBJ_TYPE_ID = 505 AND L505.PARENT_ID = :I$PARENT_ID AND L505.DATE_DEL IS NULL
        ))
        THEN
            EXCEPTION DATA_ERROR 'Проект штатного расписания должен быть уникальным';
    END

    IF (I$EXT_TYPE_ID IS NOT NULL) THEN
    BEGIN
        INSERT INTO OBJECTS (TYPE_ID) VALUES (:EXT_OBJ_TYPE_ID) RETURNING OBJ_ID INTO :EXT_OBJ_ID;
        SELECT HAS_CHILD FROM OBJECT_CREATE_AUTO_PARAMS(:EXT_OBJ_ID, :EXT_OBJ_TYPE_ID, :PARENT_ID, :PARENT_TYPE_ID, :I$USER_ID, :I$DATE_INS) INTO :HAS_CHILD;
    END

    INSERT INTO LINKS (PARENT_ID, OBJ_ID, REASON_ID, LISTVAL_ID, COST, DATE_INS, DATE_DEL, EXT_OBJ_ID, USER_ID)
    VALUES (:PARENT_ID, :OBJ_ID, :I$REASON_ID, :I$LISTVAL_ID, :I$COST, :DATE_INS, :DATE_DEL, :EXT_OBJ_ID, :I$USER_ID)
    RETURNING LINK_ID
    INTO :LINK_ID;

    SELECT HAS_CHILD
    FROM OBJECT_CREATE_AUTO_PARAMS(:OBJ_ID, :TYPE_ID, :PARENT_ID, :PARENT_TYPE_ID, :I$USER_ID, :I$DATE_INS)
    INTO :HAS_CHILD;

    SELECT CAPTION, SORT_ORDER, COLOR
    FROM OBJECT_CAPTION_GET(:OBJ_ID, :I$LEVEL_ID)
    INTO :CAPTION, :SORT_ORDER, :COLOR;

    IF ((TAG = 'CLASS') OR (TAG = 'EXTERNAL_VIRTUAL_CLASS') OR (TAG = 'GIA_VIRTUAL_CLASS')) THEN
    BEGIN
        IF (PARENT_TYPE_ID = 8) THEN
        BEGIN
            SELECT I
            FROM VAL_GET(:PARENT_ID, 49)
            INTO :X;

            IF (X = 45) THEN
            BEGIN
                Y = 11202;
            END
            ELSE IF (X IN (47,48)) THEN
            BEGIN
                Y = 11203;
            END
            ELSE
            BEGIN
                Y = 11217;
            END

            SELECT BLOB_ID
            FROM VAL_ADD(CASE WHEN :TYPE_ID = 9 THEN 2388 WHEN :TYPE_ID = 187 THEN 2418 WHEN :TYPE_ID = 125 THEN 2419 END, :OBJ_ID, :Y)
            INTO :BLOB_ID;
        END
    END
    ELSE IF (TAG = 'OP') THEN
    BEGIN
        EXECUTE PROCEDURE OO_SPECIALITY_LINK_CREATE(:OBJ_ID);
    END
    ELSE IF (TAG = 'ROOM') THEN
    BEGIN
        SELECT I, IS_EXISTS
        FROM VAL_GET(:I$PARENT_ID, 504)
        INTO :AUTO_VAL, :X;
        IF (X = 1) THEN
            SELECT BLOB_ID
            FROM VAL_ADD(527, :OBJ_ID, :AUTO_VAL)
            INTO :BLOB_ID;

        SELECT I, IS_EXISTS
        FROM VAL_GET(:I$PARENT_ID, 505)
        INTO :AUTO_VAL, :X;
        IF (X = 1) THEN SELECT BLOB_ID FROM VAL_ADD(528, :OBJ_ID, :AUTO_VAL) INTO :BLOB_ID;
    END
    ELSE IF (TAG = 'INVENTAR') THEN
    BEGIN
        IF (PARENT_TYPE_ID = 94) THEN
        /*MEBEL*/
        BEGIN
            SELECT V, IS_EXISTS
            FROM VAL_GET(:I$PARENT_ID, 601)
            INTO :AUTO_VAL, :X;
            IF (X = 1) THEN SELECT BLOB_ID FROM VAL_ADD(674, :OBJ_ID, :AUTO_VAL) INTO :BLOB_ID;
            SELECT V, IS_EXISTS FROM VAL_GET(:I$PARENT_ID, 634) INTO :AUTO_VAL, :X;
            IF (X = 1) THEN SELECT BLOB_ID FROM VAL_ADD(682, :OBJ_ID, :AUTO_VAL) INTO :BLOB_ID;
        END
        IF (PARENT_TYPE_ID = 95) THEN
        /*TCO*/
        BEGIN
            SELECT V, IS_EXISTS FROM VAL_GET(:I$PARENT_ID, 627) INTO :AUTO_VAL, :X;
            IF (X = 1) THEN SELECT BLOB_ID FROM VAL_ADD(674, :OBJ_ID, :AUTO_VAL) INTO :BLOB_ID;
            SELECT V, IS_EXISTS FROM VAL_GET(:I$PARENT_ID, 630) INTO :AUTO_VAL, :X;
            IF (X = 1) THEN SELECT BLOB_ID FROM VAL_ADD(682, :OBJ_ID, :AUTO_VAL) INTO :BLOB_ID;
            -- Пересчитываем количество
            SELECT COUNT(*) FROM LINKS WHERE PARENT_ID = :I$PARENT_ID AND OBJ_TYPE_ID = 114 AND DATE_DEL IS NULL INTO :N;
            SELECT BLOB_ID FROM VAL_ADD(605, :I$PARENT_ID, :N) INTO :BLOB_ID;
        END
        IF (PARENT_TYPE_ID = 97) THEN
        /*UCH OBORUDOVANIE*/
        BEGIN
            SELECT V, IS_EXISTS FROM VAL_GET(:I$PARENT_ID, 606) INTO :AUTO_VAL, :X;
            IF (X = 1) THEN SELECT BLOB_ID FROM VAL_ADD(674, :OBJ_ID, :AUTO_VAL) INTO :BLOB_ID;
            SELECT V, IS_EXISTS FROM VAL_GET(:I$PARENT_ID, 636) INTO :AUTO_VAL, :X;
            IF (X = 1) THEN SELECT BLOB_ID FROM VAL_ADD(682, :OBJ_ID, :AUTO_VAL) INTO :BLOB_ID;
        END
        IF (PARENT_TYPE_ID = 109) THEN
        /*MED*/
        BEGIN
            SELECT V, IS_EXISTS FROM VAL_GET(:I$PARENT_ID, 656) INTO :AUTO_VAL, :X;
            IF (X = 1) THEN SELECT BLOB_ID FROM VAL_ADD(674, :OBJ_ID, :AUTO_VAL) INTO :BLOB_ID;
            SELECT V, IS_EXISTS FROM VAL_GET(:I$PARENT_ID, 659) INTO :AUTO_VAL, :X;
            IF (X = 1) THEN SELECT BLOB_ID FROM VAL_ADD(682, :OBJ_ID, :AUTO_VAL) INTO :BLOB_ID;
        END

    END
    IF ((PARENT_TYPE_ID IN (9, 125)) AND (TYPE_ID IN (10, 126))) THEN
    BEGIN
        EXECUTE PROCEDURE GIA_COPY_INFO_EXAM_PARAMS(OBJ_ID, PARENT_ID, I$USER_ID);
    END
    IF(PARENT_TYPE_ID = 125 AND TYPE_ID = 126) THEN
    BEGIN
        EXECUTE PROCEDURE GIA_ACCEPT_CHECK_INT(:PARENT_ID);
    END

    -- Длительный отпуск - вносим дату начала отпуска текущим числом, потом пользователь может исправить
    IF (TYPE_ID = 376) THEN
    BEGIN
        SELECT BLOB_ID FROM VAL_ADD(2860, :OBJ_ID, CURRENT_DATE) INTO :BLOB_ID;
    END

    -- При добавлении ученика в класс-экстернат, корректируем форму обучения
    IF(PARENT_TYPE_ID = 187 AND I$TYPE_ID = 10) THEN
    BEGIN
        SELECT BLOB_ID FROM VAL_ADD(80, :OBJ_ID, 5422) INTO :BLOB_ID;
    END

    -- Для ОУ - создаем папки ГЗ
    IF(I$TYPE_ID = 2) THEN EXECUTE PROCEDURE CREATE_GZ_FOLDERS;

    -- Для шаблона расписания занятий - заполняем поля по-умолчанию
    IF(I$TYPE_ID = 59) THEN EXECUTE PROCEDURE CREATE_SCHEDULE_DEF(:OBJ_ID);

    -- Создаем журнал воспитательной работы
    IF(I$TYPE_ID = 478) THEN EXECUTE PROCEDURE CREATE_CJ_VOSP(:OBJ_ID);

    -- Создаем календарный учебный график (КУГ)
    IF(I$TYPE_ID = 481) THEN EXECUTE PROCEDURE CREATE_CALENDAR_PLAN(:OBJ_ID);

    -- Прописываем тип ГПД при добавлении в папке ГПД
    IF(I$TYPE_ID = 46 AND PARENT_TYPE_ID = 500) THEN SELECT 1 FROM VAL_ADD(369, :OBJ_ID, 1246) INTO :BLOB_ID;

    -- Отчет мониторинга талантов
    IF(I$TYPE_ID = 512) THEN EXECUTE PROCEDURE CREATE_MTL_REPORT(:OBJ_ID, NULL, NULL, NULL);

    -- Распределение учебной нагрузки
    IF(I$TYPE_ID = 531) THEN EXECUTE PROCEDURE CREATE_EDU_LOAD(:OBJ_ID);

    -- Создаем график контрольных мероприятий
    IF(I$TYPE_ID = 535) THEN EXECUTE PROCEDURE CREATE_CHECK_PLAN(:OBJ_ID);

    -- Регистрируем в логе
    INSERT INTO HISTVALS
    (TABLE_NAME, USER_ID, OBJ_ID, PARAM_ID, OPT_ID, PARENT_ID, VAL)
    VALUES ('OBJECTS', :I$USER_ID, :OBJ_ID, 0, :TYPE_ID, :PARENT_ID, (SELECT CAPTION FROM OBJECT_CAPTION_GET(:OBJ_ID)));

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OBJECT_ADD_400 (
    I$PARENT_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$USER_ID BIGINT,
    I$OU_TYPE VARCHAR(10))
AS
DECLARE VARIABLE X BIGINT;
DECLARE VARIABLE BLOB_ID BIGINT;
DECLARE VARIABLE V$PARENT_ID BIGINT;
DECLARE VARIABLE V$OP_TYPE BIGINT;
begin

    -- Если УП добавляется в ОП - должен быть указан уровень ОП
    SELECT FIRST 1 LP69.PARENT_ID, V1832.LISTVAL_ID
    FROM LINKS LP69
    LEFT JOIN VALL V1832 ON V1832.OBJ_ID = LP69.OBJ_ID AND V1832.PARAM_ID = 1832 AND V1832.IS_DEL = 0
    WHERE LP69.OBJ_ID = :I$PARENT_ID AND LP69.PARENT_TYPE_ID = 69 AND LP69.DATE_DEL IS NULL
    INTO :V$PARENT_ID, :V$OP_TYPE;

    IF(V$PARENT_ID IS NOT NULL AND V$OP_TYPE IS NULL) THEN EXCEPTION DATA_ERROR 'В ОП не заполнено поле "Вид ОП"';

    -- Для УП ДПО добавляем этап по-умолчанию
    IF(I$OU_TYPE = 'P' OR V$OP_TYPE IN (5362, 5363)) THEN
    BEGIN
      SELECT OBJ_ID FROM OBJECT_ADD(:I$OBJ_ID, 54, NULL, NULL, :I$USER_ID) INTO :X;
      SELECT BLOB_ID FROM VAL_ADD(381, :X, 13145) INTO :BLOB_ID;
      SELECT BLOB_ID FROM VAL_ADD(382, :X, 1) INTO :BLOB_ID;
      SELECT BLOB_ID FROM VAL_ADD(2837, :X, 11719) INTO :BLOB_ID;
    END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OBJECT_ADD_BY_CAPTION (
    I$PARENT_ID BIGINT,
    I$TYPE_ID BIGINT,
    I$OBJ_CAPTION VARCHAR(500))
RETURNS (
    OBJ_ID BIGINT,
    NEW_OBJ_INFO VARCHAR(500))
AS
DECLARE VARIABLE V$PARAM_ID BIGINT;
DECLARE VARIABLE V$PARAM2_ID BIGINT;
DECLARE VARIABLE V$LISTVAL_ID BIGINT;
BEGIN
    SELECT FIRST 1 OBJ_ID
    FROM OBJECT_CHILDREN_GET_DEEP(:I$PARENT_ID, :I$TYPE_ID)
    WHERE (SELECT CAPTION FROM OBJECT_CAPTION_GET(OBJ_ID)) = :I$OBJ_CAPTION
    INTO :OBJ_ID;

    IF (:OBJ_ID IS NULL) THEN
    BEGIN
        SELECT OBJ_ID
        FROM OBJECT_ADD(:I$PARENT_ID, :I$TYPE_ID)
        INTO :OBJ_ID;

        IF (:OBJ_ID IS NOT NULL) THEN
        BEGIN
            SELECT FIRST 1 P.PARAM_ID
            FROM PARAMS P
            WHERE P.TYPE_ID = :I$TYPE_ID
              AND P.IS_TREEVIEW = 1
              AND P.IS_DEL = 0
            ORDER BY P.GRID_ORDER
            INTO :V$PARAM_ID;

            FOR SELECT FIRST 1
                    P.PARAM_ID,
                    F.LISTVAL_ID
                FROM PARAMS P
                LEFT JOIN OO_FILTRED_LIST(P.LIST_ID) F ON 1 = 1
                WHERE P.TYPE_ID = :I$TYPE_ID
                  AND P.PARAM_ID <> COALESCE(:V$PARAM_ID, 0)
                  AND P.PARAM_TYPE = 6
                  AND P.IS_DEL = 0
                  AND F.VAL = :I$OBJ_CAPTION
                ORDER BY IIF(RUN_SQL LIKE '%OO_FILTRED_LIST%', 0, 1)
                INTO :V$PARAM2_ID, :V$LISTVAL_ID
            DO
            BEGIN
                IF ((SELECT V FROM VAL_GET(:OBJ_ID, :V$PARAM2_ID)) = '') THEN
                BEGIN
                    SELECT :OBJ_ID
                    FROM VAL_ADD(:V$PARAM2_ID, :OBJ_ID, :V$LISTVAL_ID)
                    INTO :OBJ_ID;
                END
            END
    
            IF (:V$PARAM_ID IS NOT NULL AND (SELECT V FROM VAL_GET(:OBJ_ID, :V$PARAM_ID)) = '') THEN
            BEGIN
                SELECT :OBJ_ID
                FROM VAL_ADD(:V$PARAM_ID, :OBJ_ID, :I$OBJ_CAPTION)
                INTO :OBJ_ID;
            END

            SELECT TYPE_CAPTION
            FROM TYPE_CAPTION_GET(:I$TYPE_ID)
            INTO :NEW_OBJ_INFO;

            SELECT :NEW_OBJ_INFO || ' = ' || CAPTION
            FROM OBJECT_CAPTION_GET(:OBJ_ID)
            INTO :NEW_OBJ_INFO;
        END
    END

    IF (:OBJ_ID IS NOT NULL) THEN
    BEGIN
        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OBJECT_ADD_LINK (
    I$PARENT_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$TYPE_ID BIGINT,
    I$REASON_ID BIGINT = null,
    I$LISTVAL_ID BIGINT = null,
    I$USER_ID BIGINT = null,
    I$COST FLOAT = 0,
    I$LEVEL_ID BIGINT = null,
    I$EXT_TYPE_ID BIGINT = null)
RETURNS (
    OBJ_ID BIGINT,
    TYPE_ID BIGINT,
    PARENT_ID BIGINT,
    USER_ID BIGINT,
    DATE_INS TIMESTAMP,
    DATE_DEL TIMESTAMP,
    SORT_ORDER DOUBLE PRECISION,
    CAPTION VARCHAR(4000),
    HAS_CHILD INTEGER,
    COLOR INTEGER,
    TAB_ID BIGINT,
    TYPE_ORDER SMALLINT,
    LINK_ID BIGINT,
    EXT_OBJ_TYPE_ID BIGINT,
    EXT_OBJ_ID BIGINT)
AS
declare variable V$LINK_ID bigint;
declare variable V$PARENT_TYPE_ID bigint;
declare variable V$LISTVAL_ID bigint;
declare variable V$BLOB_ID bigint;
declare variable V$OU_LICENCE_TYPE varchar(1);
BEGIN
    V$LINK_ID = NULL;
    EXT_OBJ_TYPE_ID = I$EXT_TYPE_ID;
    EXT_OBJ_ID = NULL;

    -- Блокируем добавление объектов в корень дерева
    IF(I$PARENT_ID IS NULL AND I$TYPE_ID NOT IN (2, 53, 55, 111, 112, 118, 124, 224, 248, 251, 193, 241, 377)) THEN
    BEGIN
        EXCEPTION DATA_ERROR 'Недопустимый тип объекта в корне дерева';
    END

    SELECT TYPE_ID
    FROM OBJECTS
    WHERE OBJ_ID = :I$PARENT_ID
    INTO :V$PARENT_TYPE_ID;

    SELECT FIRST 1 LINK_ID, DATE_INS, DATE_DEL
    FROM LINKS
    WHERE (PARENT_ID = :I$PARENT_ID OR (:I$PARENT_ID IS NULL AND PARENT_ID IS NULL)) AND OBJ_ID = :I$OBJ_ID AND DATE_DEL IS NULL
    INTO :V$LINK_ID, :DATE_INS, :DATE_DEL;

    IF (V$LINK_ID IS NOT NULL) THEN
    BEGIN
        PARENT_ID = I$PARENT_ID;
        OBJ_ID    = I$OBJ_ID;
        TYPE_ID   = I$TYPE_ID;
        TAB_ID    = NULL;

        UPDATE LINKS
        SET COST = :I$COST
        WHERE LINK_ID = :V$LINK_ID;

        SELECT COUNT(*)
        FROM LINKS L
        JOIN TYPES T ON T.TYPE_ID  = L.OBJ_TYPE_ID AND T.IS_DEL = 0
        JOIN LTYPES LT ON LT.TYPE_ID = L.OBJ_TYPE_ID AND LT.LEVEL_ID = :I$LEVEL_ID AND LT.IS_DEL = 0 AND LT.EDIT_TYPE > -1
        JOIN PARENTS P ON P.CHILD_ID = L.OBJ_TYPE_ID AND P.IS_DEL = 0 AND P.TYPE_ID = :TYPE_ID AND P.TAB_ID IS NULL
        WHERE L.PARENT_ID = :OBJ_ID AND ((LT.SHOW_DEL = 1) OR (L.DATE_DEL IS NULL))
        INTO :HAS_CHILD;

        SUSPEND;

        EXIT;
    END

    PARENT_ID = I$PARENT_ID;
    OBJ_ID    = I$OBJ_ID;
    TYPE_ID   = I$TYPE_ID;
    USER_ID   = I$USER_ID;
    DATE_INS  = CURRENT_TIMESTAMP;
    DATE_DEL  = NULL;
    HAS_CHILD = 0;
    TAB_ID    = NULL;

    IF (:I$TYPE_ID = 201) THEN
    BEGIN
        SELECT OBJ_ID FROM DISCIPLINE_ADD(:I$OBJ_ID) INTO :OBJ_ID;
    END

    IF (I$EXT_TYPE_ID IS NOT NULL) THEN
    BEGIN
        INSERT INTO OBJECTS (TYPE_ID)
        VALUES (:EXT_OBJ_TYPE_ID)
        RETURNING OBJ_ID
        INTO :EXT_OBJ_ID;

        SELECT HAS_CHILD
        FROM OBJECT_CREATE_AUTO_PARAMS(:EXT_OBJ_ID, :EXT_OBJ_TYPE_ID, :PARENT_ID, :V$PARENT_TYPE_ID, :I$USER_ID, CURRENT_TIMESTAMP)
        INTO :HAS_CHILD;
    END

    INSERT INTO LINKS (PARENT_ID, OBJ_ID, REASON_ID, DATE_INS, DATE_DEL, EXT_OBJ_ID, COST)
    VALUES (:PARENT_ID, :OBJ_ID, :I$REASON_ID, :DATE_INS, :DATE_DEL, :EXT_OBJ_ID, :I$COST)
    RETURNING LINK_ID INTO :LINK_ID;

    IF (:I$USER_ID IS NOT NULL) THEN
    BEGIN

        SELECT COLOR, SORT_ORDER
        FROM TYPES
        WHERE TYPE_ID = :I$TYPE_ID
        INTO :COLOR, :TYPE_ORDER;

        SELECT CAPTION, SORT_ORDER, COLOR FROM OBJECT_CAPTION_GET(:OBJ_ID, :I$LEVEL_ID)
        INTO :CAPTION, :SORT_ORDER, :COLOR;

        SELECT COUNT(*)
        FROM LINKS L
        JOIN TYPES T ON T.TYPE_ID  = L.OBJ_TYPE_ID AND T.IS_DEL = 0
        JOIN LTYPES LT ON LT.TYPE_ID = L.OBJ_TYPE_ID AND LT.LEVEL_ID = :I$LEVEL_ID AND LT.IS_DEL = 0 AND LT.EDIT_TYPE > -1
        JOIN PARENTS P ON P.CHILD_ID = L.OBJ_TYPE_ID AND P.TAB_ID IS NULL AND P.IS_DEL = 0 AND P.TYPE_ID  = :TYPE_ID
        WHERE L.PARENT_ID = :OBJ_ID AND ((LT.SHOW_DEL = 1) OR (L.DATE_DEL IS NULL))
        INTO :HAS_CHILD;

    END

    IF ((I$TYPE_ID = 9) AND (V$PARENT_TYPE_ID = 54)) THEN
    BEGIN
        SELECT STATUS FROM OU_LICENCE_TYPE INTO :V$OU_LICENCE_TYPE;
        IF (V$OU_LICENCE_TYPE = 'C') THEN
        BEGIN
            FOR
                SELECT VAL1753.LISTVAL_ID
                FROM LINKS LP50
                JOIN LINKS LP57 ON LP57.OBJ_ID = LP50.PARENT_ID AND LP57.PARENT_TYPE_ID = 57 AND LP57.DATE_DEL IS NULL
                JOIN VALL VAL1753 ON VAL1753.OBJ_ID = LP57.PARENT_ID AND VAL1753.PARAM_ID = 1753 AND VAL1753.IS_DEL = 0
                WHERE LP50.OBJ_ID = :I$PARENT_ID AND LP50.PARENT_TYPE_ID = 50 AND LP50.DATE_DEL IS NULL
                INTO :V$LISTVAL_ID
            DO
            BEGIN
                SELECT BLOB_ID
                FROM VAL_ADD(2165, :I$OBJ_ID, :V$LISTVAL_ID, :I$USER_ID)
                INTO :V$BLOB_ID;
            END
        END
    END

    -- При добавлении предметов в компоненты УП обнуляем часы нагрузки,
    -- чтобы не было наслоений от ранее удаленных и затем возвращенных предметов
    IF ((I$TYPE_ID = 51) AND (V$PARENT_TYPE_ID = 49)) THEN
    BEGIN
       FOR
           -- связка 49->56, 51->56, 50->54->56
           SELECT L56.OBJ_ID
           FROM LINKS L56
           JOIN LINKS LP51 ON LP51.PARENT_ID = :I$OBJ_ID AND LP51.OBJ_ID = L56.OBJ_ID AND LP51.DATE_DEL IS NULL
           JOIN LINKS LP50 ON LP50.OBJ_ID = :I$PARENT_ID AND LP50.PARENT_TYPE_ID = 50 AND LP50.DATE_DEL IS NULL
           JOIN LINKS L50_54 ON L50_54.PARENT_ID = LP50.PARENT_ID AND L50_54.OBJ_TYPE_ID = 54 AND L50_54.DATE_DEL IS NULL
           JOIN LINKS L54_56 ON L54_56.PARENT_ID = L50_54.OBJ_ID AND L54_56.OBJ_ID = L56.OBJ_ID AND L54_56.DATE_DEL IS NULL
           WHERE L56.PARENT_ID = :I$PARENT_ID AND L56.OBJ_TYPE_ID = 56 AND L56.DATE_DEL IS NULL
           INTO :V$BLOB_ID
       DO
       BEGIN

           UPDATE VALI V385
           SET V385.VAL = 0
           WHERE V385.OBJ_ID = :V$BLOB_ID AND V385.PARAM_ID = 385 AND V385.IS_DEL = 0;

       END

    END


    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OBJECT_ADD_WITH_PARAM (
    I$PARENT_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$TYPE_ID BIGINT,
    I$PARAM_ID BIGINT,
    I$PARAM_VAL VARCHAR(4000))
RETURNS (
    PARENT_ID BIGINT,
    OBJ_ID BIGINT,
    COLOR INTEGER,
    NEW_OBJ_INFO VARCHAR(500))
AS
BEGIN
    PARENT_ID = I$PARENT_ID;
    OBJ_ID = I$OBJ_ID;
    IF (PARENT_ID IS NOT NULL AND I$TYPE_ID IS NOT NULL) THEN
    BEGIN
        IF (OBJ_ID IS NULL) THEN
        BEGIN
            SELECT OBJ_ID
            FROM OBJECT_ADD(:PARENT_ID, :I$TYPE_ID)
            INTO :OBJ_ID;

            IF (OBJ_ID IS NOT NULL) THEN
            BEGIN
                SELECT TYPE_CAPTION
                FROM TYPE_CAPTION_GET(:I$TYPE_ID)
                INTO :NEW_OBJ_INFO;
            END
        END
        ELSE
        BEGIN
            SELECT OBJ_ID
            FROM OBJECT_ADD_LINK(:PARENT_ID, :OBJ_ID, :I$TYPE_ID)
            INTO :OBJ_ID;
        END
    END
    IF (OBJ_ID IS NOT NULL) THEN
    BEGIN
        IF (I$PARAM_ID IS NOT NULL AND I$PARAM_VAL IS NOT NULL) THEN
        BEGIN
            SELECT :OBJ_ID
            FROM VAL_ADD(:I$PARAM_ID, :OBJ_ID, :I$PARAM_VAL)
            INTO :OBJ_ID;
        END
    
        IF (NEW_OBJ_INFO IS NOT NULL) THEN
        BEGIN
            SELECT :NEW_OBJ_INFO || ' = ' || CAPTION
            FROM OBJECT_CAPTION_GET(:OBJ_ID)
            INTO :NEW_OBJ_INFO;
        END
    
        SELECT COLOR
        FROM OBJECT_CAPTION_GET(:OBJ_ID)
        INTO :COLOR;

        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OBJECT_CAN_LINK (
    I$OBJ_ID BIGINT,
    I$PARENT_ID BIGINT)
RETURNS (
    STATUS SMALLINT,
    MSG VARCHAR(1000))
AS
DECLARE VARIABLE V$OBJ_TYPE_ID BIGINT;
DECLARE VARIABLE V$PARENT_TYPE_ID BIGINT;
DECLARE VARIABLE V$SUBJECT_ID BIGINT;
BEGIN
    STATUS = 1;

    SELECT TYPE_ID
    FROM OBJECTS
    WHERE OBJ_ID = :I$OBJ_ID
    INTO :V$OBJ_TYPE_ID;

    SELECT TYPE_ID
    FROM OBJECTS
    WHERE OBJ_ID = :I$PARENT_ID
    INTO :V$PARENT_TYPE_ID;

    IF ((V$OBJ_TYPE_ID = 87) AND (V$PARENT_TYPE_ID = 256)) THEN
    BEGIN
        SELECT FIRST 1
               LP51.PARENT_ID
        FROM LINKS LP51
        WHERE LP51.OBJ_ID = :I$OBJ_ID
        AND LP51.PARENT_TYPE_ID = 51
        AND LP51.DATE_DEL IS NULL
        INTO :V$SUBJECT_ID;

        IF (EXISTS(
            SELECT FIRST 1 1
            FROM LINKS L87

            JOIN LINKS LP51
            ON LP51.OBJ_ID = L87.OBJ_ID
            AND LP51.PARENT_TYPE_ID = 51
            AND LP51.PARENT_ID = :V$SUBJECT_ID
            AND LP51.DATE_DEL IS NULL

            WHERE L87.PARENT_ID = :I$PARENT_ID
            AND L87.OBJ_TYPE_ID = 87
            AND L87.OBJ_ID <> :I$OBJ_ID
            AND L87.DATE_DEL IS NULL
        )) THEN
        BEGIN
            STATUS = 0;
            MSG = 'Нельзя прикрепить к ГУП два поурочно-тематических плана для одного предмета.';
        END
    END

    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OBJECT_CAPTION_GET (
    I$OBJ_ID BIGINT,
    I$LEVEL_ID BIGINT = NULL,
    I$SEPARATOR VARCHAR(10) = NULL,
    I$USER_ID BIGINT = 1)
RETURNS (
    CAPTION VARCHAR(4000),
    SCAPTION VARCHAR(400),
    SORT_ORDER DOUBLE PRECISION,
    COLOR INTEGER)
AS
DECLARE VARIABLE V$SORT_INDEX BIGINT;
DECLARE VARIABLE V$OU_LICENCE_TYPE VARCHAR(1);
DECLARE VARIABLE V$PARAM_ID BIGINT;
DECLARE VARIABLE V$PARENT_ID BIGINT;
DECLARE VARIABLE V$TYPE_ID BIGINT;
DECLARE VARIABLE V$V VARCHAR(4000);
DECLARE VARIABLE V$V2 VARCHAR(1000);
DECLARE VARIABLE V$I BIGINT;
DECLARE VARIABLE V$TYPE_TAG VARCHAR(100);
DECLARE VARIABLE V$PARAM_TAG VARCHAR(100);
DECLARE VARIABLE V$CAPTION_SEPARATOR VARCHAR(10);
DECLARE VARIABLE V$SIZE_RES_ID BIGINT;
DECLARE VARIABLE V$LANG_CODE VARCHAR(2);
DECLARE VARIABLE V$CNT BIGINT;
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :V$LANG_CODE;

    CAPTION = '';
    SORT_ORDER=0;

    SELECT TYPE_ID
    FROM OBJECTS
    WHERE OBJ_ID = :I$OBJ_ID
    INTO :V$TYPE_ID;

    SELECT TAG, COLOR, CAPTION_SEPARATOR
    FROM TYPES
    WHERE TYPE_ID = :V$TYPE_ID
    INTO :V$TYPE_TAG, :COLOR, :V$CAPTION_SEPARATOR;

    IF (I$SEPARATOR IS NULL) THEN
    BEGIN
        I$SEPARATOR = V$CAPTION_SEPARATOR;
    END

    FOR
        SELECT P.PARAM_ID, P.TAG, P.SIZE_RES_ID
        FROM PARAMS P
        JOIN TYPES T ON T.TYPE_ID = P.TYPE_ID
        LEFT JOIN LPARAMS LP ON LP.LEVEL_ID = :I$LEVEL_ID AND LP.PARAM_ID = P.PARAM_ID
        WHERE P.TYPE_ID = :V$TYPE_ID AND P.IS_TREEVIEW = 1 AND P.IS_DEL = 0 AND ((:I$LEVEL_ID IS NULL) OR ((:I$LEVEL_ID = LP.LEVEL_ID) AND (LP.EDIT_TYPE > -1)))
        ORDER BY P.GRID_ORDER
        INTO :V$PARAM_ID, :V$PARAM_TAG, :V$SIZE_RES_ID
    DO
    BEGIN

        V$V = '';

        SELECT V
        FROM VAL_GET(:I$OBJ_ID, :V$PARAM_ID, 0, :I$USER_ID)
        INTO :V$V;

        IF (CAPTION <> '' AND V$V <> '') THEN
        BEGIN
            CAPTION = CAPTION || I$SEPARATOR;
        END

        IF (V$V <> '') THEN
        BEGIN
            -- Орграничиваем значение единичного параметра
            IF(CHAR_LENGTH(V$V) > 1000) THEN
            BEGIN
                IF(CHAR_LENGTH(CAPTION) > 2000) THEN
                BEGIN
                    CAPTION = SUBSTRING(CAPTION FROM 1 FOR 2000) || '...';
                    V$V = SUBSTRING(V$V FROM 1 FOR 1000);
                END
                ELSE
                BEGIN
                    V$V = SUBSTRING(V$V FROM 1 FOR 3000);
                END
            END

            CAPTION = CAPTION || V$V;
            V$V = '';

            SELECT VAL
            FROM RES
            WHERE RES_ID = :V$SIZE_RES_ID AND LANG_CODE = 'RU' AND IS_DEL = 0
            INTO :V$V;

            IF (V$V <> '') THEN
            BEGIN
                IF(SUBSTRING(V$V FROM 1 FOR 1) = '-') THEN CAPTION = CAPTION || SUBSTRING(V$V FROM 2);
                ELSE CAPTION = CAPTION || ' (' || V$V || ')';
            END
        END
    END

    V$SORT_INDEX = 1;
    FOR
        SELECT P.PARAM_ID
        FROM PARAMS P WHERE P.TYPE_ID = :V$TYPE_ID AND P.IS_TREESORT = 1 AND P.IS_DEL = 0
        ORDER BY P.GRID_ORDER DESC
        INTO :V$PARAM_ID
    DO
    BEGIN
        SELECT :SORT_ORDER + SORT_ORDER * :V$SORT_INDEX
        FROM VAL_GET(:I$OBJ_ID, :V$PARAM_ID, 0, :I$USER_ID)
        INTO :SORT_ORDER;

        V$SORT_INDEX = V$SORT_INDEX * 1000000;
    END

    IF (V$TYPE_TAG = 'POST') THEN/* TYPE_TAG */
    BEGIN
        IF ((CAPTION = '') OR (CAPTION IS NULL)) THEN CAPTION = '<  ...  >';
        FOR
            SELECT FIRST 1 PARENT_ID
            FROM LINKS
            WHERE PARENT_TYPE_ID = 211 AND DATE_DEL IS NULL AND OBJ_ID = :I$OBJ_ID
            INTO :V$PARENT_ID
        DO
        BEGIN
            SELECT CAPTION || ' / ' || :CAPTION
            FROM OBJECT_CAPTION_GET(:V$PARENT_ID, NULL, NULL, :I$USER_ID)
            INTO :CAPTION;
        END
    END
    ELSE IF (V$TYPE_TAG = 'GUP') THEN
    BEGIN
        SELECT CAPTION, SORT_ORDER
        FROM THE_CAPTION_GUP(:I$OBJ_ID, :CAPTION)
        INTO :CAPTION, :SORT_ORDER;
    END
    ELSE IF (V$TYPE_TAG IN ('CLASS', 'INCOMING_GRADE')) THEN
    BEGIN
        SELECT STATUS FROM OU_LICENCE_TYPE INTO :V$OU_LICENCE_TYPE;
        IF (V$OU_LICENCE_TYPE = 'O') THEN
        BEGIN
            SELECT CAPTION, SORT_ORDER
            FROM THE_CAPTION_CLASS(:I$OBJ_ID, :CAPTION)
            INTO :CAPTION, :SORT_ORDER;
        END
        ELSE IF (V$OU_LICENCE_TYPE = 'C') THEN
        BEGIN
            SELECT CAPTION, SORT_ORDER
            FROM THE_CAPTION_COLLEGE_GROUP(:I$OBJ_ID, :CAPTION)
            INTO :CAPTION, :SORT_ORDER;
        END
        ELSE IF (V$OU_LICENCE_TYPE = 'D') THEN
        BEGIN
            SELECT CAPTION, SORT_ORDER
            FROM THE_CAPTION_GROUP(:I$OBJ_ID, :CAPTION, :I$USER_ID)
            INTO :CAPTION, :SORT_ORDER;
        END
        ELSE IF (V$OU_LICENCE_TYPE = 'S') THEN
        BEGIN
            SELECT CAPTION, SORT_ORDER
            FROM THE_CAPTION_DYNAMIC(:I$OBJ_ID, :CAPTION, :I$USER_ID)
            INTO :CAPTION, :SORT_ORDER;
        END
    END
    ELSE IF (V$TYPE_TAG = 'GIA_VIRTUAL_CLASS') THEN
    BEGIN
        SELECT CAPTION, SORT_ORDER
        FROM THE_CAPTION_CLASS_GIA_VIRTUAL(:I$OBJ_ID, :CAPTION)
        INTO :CAPTION, :SORT_ORDER;
    END
    ELSE IF (V$TYPE_TAG = 'EXTERNAL_VIRTUAL_CLASS') THEN
    BEGIN
        SELECT CAPTION, SORT_ORDER
        FROM CAPTION_VIRTUAL_EXTERNAL_CLASS(:I$OBJ_ID, :CAPTION)
        INTO :CAPTION, :SORT_ORDER;
    END
    ELSE IF (V$TYPE_TAG = 'STREAM') THEN
    BEGIN
        SELECT CAPTION, SORT_ORDER
        FROM THE_CAPTION_STREAM(:I$OBJ_ID, :CAPTION)
        INTO :CAPTION, :SORT_ORDER;
    END
    ELSE IF (V$TYPE_TAG = 'FINISHED_PUPIL') THEN
    BEGIN
        SELECT CAPTION
        FROM THE_CAPTION_FINISHED(:I$OBJ_ID, :CAPTION, :I$USER_ID)
        INTO :CAPTION;
    END
    ELSE IF (V$TYPE_TAG = 'LEAVED_PUPIL') THEN
    BEGIN
        SELECT CAPTION
        FROM THE_CAPTION_LEAVED(:I$OBJ_ID, :CAPTION, :I$USER_ID)
        INTO :CAPTION;
    END
    ELSE IF (V$TYPE_TAG = 'DOCUMENT_OU') THEN
    BEGIN
        SELECT TRIM(R.VAL_LONG || ' ' || :CAPTION)
        FROM LISTVALS L
        JOIN VALL V ON L.LISTVAL_ID = V.LISTVAL_ID
        LEFT JOIN RES_GET(L.RES_ID,  :V$LANG_CODE) R ON 1=1
        WHERE V.PARAM_ID = 613 AND V.OBJ_ID = :I$OBJ_ID
        INTO :CAPTION;
    END
    ELSE IF (V$TYPE_TAG = 'OP') THEN
    BEGIN
        V$I = 0;
        SELECT V.LISTVAL_ID
        FROM VALL V
        WHERE V.PARAM_ID = 1832 AND V.OBJ_ID = :I$OBJ_ID AND V.IS_DEL = 0
        INTO :V$I;

        SORT_ORDER = V$I * 10 + :SORT_ORDER;
        IF (V$I = 5357) THEN
        BEGIN
            COLOR = 4227327;
        END
    END
    ELSE IF(V$TYPE_ID = 69) THEN
    BEGIN
        -- Программы дополнительного образования выделяем цветом, чтобы запрещать кнопки
        V$I = 0;
        SELECT V.LISTVAL_ID
        FROM VALL V
        WHERE V.PARAM_ID = 2450 AND V.OBJ_ID = :I$OBJ_ID AND V.IS_DEL = 0
        INTO :V$I;

        IF(V$I = 11386) THEN COLOR = 12615680; -- Сине-зеленый цвет вместо травяного зеленого
    END

    IF ((CAPTION = '') OR (CAPTION IS NULL)) THEN
    BEGIN
        CAPTION = '<  ...  >';
        SORT_ORDER = 1000000000;
    END

    /* TYPE_TAG */

    /* TYPE_ID */
    /* Ученики */
    IF(V$TYPE_ID = 10) THEN
    BEGIN
        -- При работе в приложении "Личные дела учащихся" в школах делаем раскраску исходя из наличия присвоенных идентификаторов РК
        -- Также в приложении "СКУД и питание"
        IF(I$LEVEL_ID IN (50, 475, 533)) THEN
        BEGIN
            V$I = 0;
            SELECT FIRST 1 1
            FROM VALS V2912
            WHERE V2912.OBJ_ID = :I$OBJ_ID AND V2912.PARAM_ID = 2912 AND V2912.IS_DEL = 0
            INTO :V$I;

            -- У кого есть карта - темно-синий, у кого нет - ярко-красный
            IF(V$I = 0) THEN COLOR = 255; ELSE COLOR = 8388608;
        END

        -- В личных делах и учебных коллективах дораскрашиваем надомников
        IF(I$LEVEL_ID = 49 OR (I$LEVEL_ID = 50 AND COLOR <> 255)) THEN
        BEGIN
            V$I = 0;
            SELECT FIRST 1 1
            FROM VALL V2169
            WHERE V2169.OBJ_ID = :I$OBJ_ID AND V2169.PARAM_ID = 2169 AND V2169.IS_DEL = 0 AND V2169.LISTVAL_ID = 2
            INTO :V$I;

            IF(V$I = 1) THEN COLOR = 16711808;
        END
    END
    ELSE IF(V$TYPE_ID = 13) THEN
    BEGIN
        IF(I$LEVEL_ID IN (548)) THEN
        BEGIN

          V$I = 0;

          SELECT FIRST 1 L.REASON_ID
          FROM LINKS L
          WHERE L.OBJ_ID = :I$OBJ_ID AND L.PARENT_TYPE_ID IN (2, 211) AND L.DATE_DEL IS NULL
          INTO :V$I;

          -- Для мультипараграфа раскрасим должность в соответствии с индикатором заполненности ставки согласно элементу штатного расписания (Reason_ID)
          IF(V$I = 0) THEN COLOR = 0x808080;        -- серый
          ELSE IF(V$I = 1) THEN COLOR = 0x008CFF;   -- оранжевый
          ELSE IF(V$I = 2) THEN COLOR = 0x008000;   -- зеленый
          ELSE IF(V$I = 3) THEN COLOR = 0xff0000;   -- красный
          ELSE COLOR = 0x000000;
        END
    END
    ELSE IF(V$TYPE_ID = 14) THEN
    BEGIN
        IF(I$LEVEL_ID IN (48, 475, 534)) THEN
        BEGIN

          V$I = 0;

          SELECT FIRST 1 1
          FROM VALS V2915
          WHERE V2915.OBJ_ID = :I$OBJ_ID AND V2915.PARAM_ID = 2915 AND V2915.IS_DEL = 0
          INTO :V$I;

          -- У кого нет карты, выделяем оранжевым
          IF(V$I = 0) THEN COLOR = 0x0057CD;

        END
    END
    ELSE IF(V$TYPE_ID = 20) THEN
    BEGIN
        -- Для родственников в приложении "СКУД и питание" и "Личные дела обучающихся" делаем три раскраски. Для постоянных сопровождающих цвет меняется от RegID
        -- для не-сопровождающих оставляем цвет по-умолчанию (рыжий)
        IF(I$LEVEL_ID IN (50, 475, 533)) THEN
        BEGIN

          V$I = 0;

          SELECT FIRST 1 1
          FROM VALL V2818
          WHERE V2818.OBJ_ID = :I$OBJ_ID AND V2818.PARAM_ID = 2818 AND V2818.IS_DEL = 0 AND V2818.LISTVAL_ID = 2
          INTO :V$I;

          IF(V$I = 1) THEN
          BEGIN

            V$I = 0;

            SELECT FIRST 1 1
            FROM VALS V2917
            WHERE V2917.OBJ_ID = :I$OBJ_ID AND V2917.PARAM_ID = 2917 AND V2917.IS_DEL = 0
            INTO :V$I;

            -- У кого есть РегИД - серо-голубой, у кого нет - оранжевый
            IF(V$I = 1) THEN COLOR = 0xB48246; ELSE COLOR = 0x0057CD;

          END

        END
    END
    /* Предметы. Стандартным цветом идут предметы и дисциплины ФГОС. Пользовательские предметы выделяем синим цветом */
    ELSE IF(V$TYPE_ID = 51 OR V$TYPE_ID = 197) THEN
    BEGIN
        IF(I$OBJ_ID >= 1000000000) THEN COLOR = 16711680;
    END
    /* Печатные издания - раскраска по дубликатам */
    ELSE IF(V$TYPE_ID = 107) THEN
    BEGIN
        -- Проверяем заполнение всех положенных полей
        V$V = NULL;
        V$I = NULL;
        V$TYPE_ID = NULL;
        V$CNT = NULL;
        V$TYPE_TAG = NULL;
        SELECT V2655.VAL, V646.LISTVAL_ID, V653.LISTVAL_ID, V648.VAL, V650.VAL
        FROM OBJECTS O
        LEFT JOIN VALL V646 ON V646.OBJ_ID = O.OBJ_ID AND V646.PARAM_ID = 646 AND V646.IS_DEL = 0
        LEFT JOIN VALL V653 ON V653.OBJ_ID = O.OBJ_ID AND V653.PARAM_ID = 653 AND V653.IS_DEL = 0
        LEFT JOIN VALI V648 ON V648.OBJ_ID = O.OBJ_ID AND V648.PARAM_ID = 648 AND V648.IS_DEL = 0
        LEFT JOIN VALS V650 ON V650.OBJ_ID = O.OBJ_ID AND V650.PARAM_ID = 650 AND V650.IS_DEL = 0
        LEFT JOIN VALS V2655 ON V2655.OBJ_ID = O.OBJ_ID AND V2655.PARAM_ID = 2655 AND V2655.IS_DEL = 0
        WHERE O.OBJ_ID = :I$OBJ_ID
        INTO :V$V, :V$I, :V$TYPE_ID, :V$CNT, :V$TYPE_TAG;
        IF(V$I IS NULL OR V$TYPE_ID IS NULL OR V$CNT IS NULL OR V$TYPE_TAG IS NULL OR (V$CNT <= 0)) THEN
        BEGIN
            -- Фиолетовый
            COLOR = 8388863;
        END
        -- Дубликаты в рамках ФПУ, если задан код
        ELSE IF(V$V IS NOT NULL) THEN
        BEGIN
            V$I = 0;
            SELECT FIRST 1 1
            FROM LINKS L107
            JOIN VALS V2655 ON V2655.OBJ_ID = L107.OBJ_ID AND V2655.PARAM_ID = 2655 AND V2655.IS_DEL = 0 AND V2655.VAL = :V$V
            JOIN VALS V650 ON V650.OBJ_ID = L107.OBJ_ID AND V650.PARAM_ID = 650 AND V650.IS_DEL = 0 AND V650.VAL = :V$TYPE_TAG
            WHERE L107.PARENT_TYPE_ID = 105 AND L107.OBJ_TYPE_ID = 107 AND L107.DATE_DEL IS NULL and L107.OBJ_ID <> :I$OBJ_ID
            INTO :V$I;
            -- Красный
            IF(V$I > 0) THEN COLOR = 255;
        END
    END

    SCAPTION = SUBSTRING(CAPTION FROM 1 FOR 400);
    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OBJECT_CHILDREN_GET_DEEP (
    I$OBJ_ID BIGINT,
    I$TYPE_ID BIGINT,
    I$DEEP SMALLINT = 2)
RETURNS (
    OBJ_ID BIGINT)
AS
DECLARE VARIABLE T BIGINT;
DECLARE VARIABLE X BIGINT;
BEGIN
    /* OBJ_ID - Root object ID */
    /* TYPE_ID - Type of children objects which you want to find */
    /* DEEP - How many levels down you want to find child objects */
    /* if DEEP = 2 then find:  ROOT -> LEVEL1 -> LEVEL2 */
    /* if DEEP > 3 then working time too long */

    SELECT TYPE_ID FROM OBJECTS  WHERE OBJ_ID = :I$OBJ_ID  INTO :T;

    IF (:T = :I$TYPE_ID) THEN
    BEGIN
        OBJ_ID = :I$OBJ_ID;
        SUSPEND;
    END

    IF (:I$DEEP < 1) THEN EXIT;

    FOR SELECT DISTINCT OBJ_ID
        FROM LINKS
        WHERE PARENT_ID = :I$OBJ_ID
        AND DATE_DEL IS NULL
        INTO   :X
    DO
    BEGIN
        FOR SELECT OBJ_ID
            FROM OBJECT_CHILDREN_GET_DEEP(:X, :I$TYPE_ID, :I$DEEP-1)
            INTO   :OBJ_ID
        DO
        BEGIN
            SUSPEND;
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OBJECT_CHILDREN_LIST (
    I$TYPE_ID BIGINT,
    I$LEVEL_ID BIGINT)
RETURNS (
    TYPE_ID BIGINT,
    IS_ADD SMALLINT,
    IS_COPY SMALLINT,
    IS_CUT SMALLINT,
    IS_LINK SMALLINT)
AS
BEGIN
    FOR SELECT P.CHILD_ID, P.IS_ADD, P.IS_COPY, P.IS_CUT, P.IS_LINK
        FROM PARENTS P
        INNER JOIN TYPES T ON T.TYPE_ID = P.CHILD_ID
        INNER JOIN LTYPES L ON L.TYPE_ID = P.CHILD_ID
        WHERE P.TYPE_ID = :I$TYPE_ID
          AND P.IS_DEL = 0
          AND L.LEVEL_ID = :I$LEVEL_ID
          AND L.IS_DEL = 0
          AND L.EDIT_TYPE = 1
          AND T.IS_DEL = 0
        INTO :TYPE_ID, :IS_ADD, :IS_COPY, :IS_CUT, :IS_LINK
    DO
        SUSPEND;

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OBJECT_COPY (
    I$PARENT_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$TYPE_ID BIGINT = null,
    I$REASON_ID BIGINT = null,
    I$LISTVAL_ID BIGINT = null,
    I$USER_ID BIGINT = null,
    I$COST FLOAT = 0,
    I$LEVEL_ID BIGINT = null)
RETURNS (
    OBJ_ID BIGINT,
    TYPE_ID BIGINT,
    PARENT_ID BIGINT,
    PARENT_TYPE_ID BIGINT,
    USER_ID BIGINT,
    DATE_INS TIMESTAMP,
    DATE_DEL TIMESTAMP,
    SORT_ORDER DOUBLE PRECISION,
    CAPTION VARCHAR(4000),
    HAS_CHILD INTEGER,
    COLOR INTEGER,
    TAB_ID BIGINT,
    TYPE_ORDER SMALLINT,
    LINK_ID BIGINT)
AS
declare variable PARAM_ID bigint;
declare variable I bigint;
declare variable F double precision;
declare variable DT timestamp;
declare variable D date;
declare variable T time;
declare variable V varchar(4000);
BEGIN
    I$TYPE_ID = COALESCE(:I$TYPE_ID, (SELECT TYPE_ID FROM OBJECTS WHERE OBJ_ID = :I$OBJ_ID));

    SELECT OBJ_ID, TYPE_ID, PARENT_ID, PARENT_TYPE_ID, USER_ID, DATE_INS, DATE_DEL, SORT_ORDER, CAPTION, HAS_CHILD, COLOR, TAB_ID,  TYPE_ORDER, LINK_ID
    FROM OBJECT_ADD(:I$PARENT_ID, :I$TYPE_ID, :I$REASON_ID, :I$LISTVAL_ID, :I$USER_ID, :I$COST)
    INTO :OBJ_ID, :TYPE_ID, :PARENT_ID, :PARENT_TYPE_ID, :USER_ID, :DATE_INS, :DATE_DEL, :SORT_ORDER, :CAPTION, :HAS_CHILD, :COLOR, :TAB_ID, :TYPE_ORDER, :LINK_ID;

    /* copy params */

    FOR SELECT PARAM_ID, VAL
        FROM VALR
        WHERE OBJ_ID = :I$OBJ_ID AND IS_DEL = 0
        INTO :PARAM_ID, :I
    DO BEGIN
        UPDATE OR INSERT INTO VALR (PARAM_ID, OBJ_ID, USER_ID, VAL)
        VALUES (:PARAM_ID, :OBJ_ID, :USER_ID, :I);
    END

    FOR SELECT PARAM_ID, VAL
        FROM VALI
        WHERE OBJ_ID = :I$OBJ_ID AND IS_DEL = 0
        INTO :PARAM_ID, :I
    DO BEGIN
        UPDATE OR INSERT INTO VALI (PARAM_ID, OBJ_ID, USER_ID, VAL)
        VALUES (:PARAM_ID, :OBJ_ID, :USER_ID, :I);
    END

    FOR SELECT PARAM_ID, VAL
        FROM VALF
        WHERE OBJ_ID = :I$OBJ_ID AND IS_DEL = 0
        INTO :PARAM_ID, :F
    DO BEGIN
        UPDATE OR INSERT INTO VALF (PARAM_ID, OBJ_ID, USER_ID, VAL)
        VALUES (:PARAM_ID, :OBJ_ID, :USER_ID, :F);
    END

    FOR SELECT PARAM_ID, VAL
        FROM VALDT
        WHERE OBJ_ID = :I$OBJ_ID AND IS_DEL = 0
        INTO :PARAM_ID, :DT
    DO BEGIN
        UPDATE OR INSERT INTO VALDT (PARAM_ID, OBJ_ID, USER_ID, VAL)
        VALUES (:PARAM_ID, :OBJ_ID, :USER_ID, :DT);
    END

    FOR SELECT PARAM_ID, VAL
        FROM VALD
        WHERE OBJ_ID = :I$OBJ_ID AND IS_DEL = 0
        INTO :PARAM_ID, :D
    DO BEGIN
        UPDATE OR INSERT INTO VALD (PARAM_ID, OBJ_ID, USER_ID, VAL)
        VALUES (:PARAM_ID, :OBJ_ID, :USER_ID, :D);
    END

    FOR SELECT PARAM_ID, VAL
        FROM VALT
        WHERE OBJ_ID = :I$OBJ_ID AND IS_DEL = 0
        INTO :PARAM_ID, :T
    DO BEGIN
        UPDATE OR INSERT INTO VALT (PARAM_ID, OBJ_ID, USER_ID, VAL)
        VALUES (:PARAM_ID, :OBJ_ID, :USER_ID, :T);
    END

    FOR SELECT PARAM_ID, VAL
        FROM VALS
        WHERE OBJ_ID = :I$OBJ_ID
        AND IS_DEL = 0
        AND PARAM_ID <> 673 /*Inventory cards copy without inventory number*/
        INTO :PARAM_ID, :V
    DO BEGIN
        UPDATE OR INSERT INTO VALS (PARAM_ID, OBJ_ID, USER_ID, VAL)
        VALUES (:PARAM_ID, :OBJ_ID, :USER_ID, :V);
    END

    FOR SELECT PARAM_ID, LISTVAL_ID
        FROM VALL
        WHERE OBJ_ID = :I$OBJ_ID AND IS_DEL = 0
        INTO :PARAM_ID, :I
    DO BEGIN
        UPDATE OR INSERT INTO VALL (PARAM_ID, OBJ_ID, USER_ID, LISTVAL_ID)
        VALUES (:PARAM_ID, :OBJ_ID, :USER_ID, :I);
    END

    SELECT CAPTION, SORT_ORDER, COLOR FROM OBJECT_CAPTION_GET(:OBJ_ID, :I$LEVEL_ID)
    INTO :CAPTION, :SORT_ORDER, :COLOR;

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OBJECT_CREATE_AUTO_PARAMS (
    I$OBJ_ID BIGINT,
    I$TYPE_ID BIGINT,
    I$PARENT_ID BIGINT,
    I$PARENT_TYPE_ID BIGINT,
    I$USER_ID BIGINT,
    I$DATE_INS TIMESTAMP)
RETURNS (
    HAS_CHILD INTEGER)
AS
DECLARE VARIABLE V$IS_ADD SMALLINT;
DECLARE VARIABLE V$PARAM_ID BIGINT;
DECLARE VARIABLE V$PARAM_TYPE SMALLINT;
DECLARE VARIABLE V$AUTO_RES_ID BIGINT;
DECLARE VARIABLE V$AUTO_LISTVAL_ID BIGINT;
DECLARE VARIABLE V$AUTO_VAL VARCHAR(4000);
DECLARE VARIABLE V$LANG_CODE CHAR(2) = 'RU';
DECLARE VARIABLE V$BLOB_ID BIGINT;
DECLARE VARIABLE V$CHILD_OBJ_ID BIGINT;
DECLARE VARIABLE V$CHILD_TYPE_ID BIGINT;
DECLARE VARIABLE V$TAG VARCHAR(100);
DECLARE VARIABLE V$X BIGINT;
DECLARE VARIABLE V$IS_AUTO_CREATE SMALLINT;
DECLARE VARIABLE V$IS_LINK_REFERENSE SMALLINT;
DECLARE VARIABLE V$LINK_REFERENSE_TYPE_ID BIGINT;
DECLARE VARIABLE V$V VARCHAR(4000);
DECLARE VARIABLE V$Y SMALLINT;
DECLARE VARIABLE V$DT DATE;
DECLARE VARIABLE V$YEAR_VAL VARCHAR(100);
DECLARE VARIABLE V$YEAR_ID BIGINT;
begin
    HAS_CHILD = 0;
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :V$LANG_CODE;

    /* AUTO CREATE PARAMS */
    FOR
        SELECT PARAM_ID, PARAM_TYPE, AUTO_RES_ID, AUTO_LISTVAL_ID, IS_AUTO_CREATE, IS_LINK_REFERENSE, LINK_REFERENSE_TYPE_ID
        FROM PARAMS
        WHERE TYPE_ID = :I$TYPE_ID AND (IS_AUTO_CREATE = 1 OR IS_LINK_REFERENSE = 1) AND IS_DEL = 0
        INTO :V$PARAM_ID, :V$PARAM_TYPE, :V$AUTO_RES_ID, :V$AUTO_LISTVAL_ID, :V$IS_AUTO_CREATE, :V$IS_LINK_REFERENSE, :V$LINK_REFERENSE_TYPE_ID
    DO
    BEGIN
        IF (V$IS_AUTO_CREATE = 1) THEN
        BEGIN
            IF (V$PARAM_TYPE = 6) THEN
            BEGIN
                V$AUTO_VAL = V$AUTO_LISTVAL_ID;
            END
            ELSE
            BEGIN
                SELECT VAL
                FROM RES_GET(:V$AUTO_RES_ID, :V$LANG_CODE)
                INTO :V$AUTO_VAL;
            END

            IF (V$AUTO_VAL = 'ORGANIZATION_SHORT_NAME') THEN
            BEGIN
                SELECT K.KEY_VAL
                FROM KEYS K
                WHERE K.KEY_CODE = 'ORGANIZATION_SHORT_NAME'
                INTO :V$AUTO_VAL;
            END

            IF (V$PARAM_TYPE = 4 AND V$AUTO_VAL = 'NOW()') THEN
            BEGIN
                V$AUTO_VAL = CURRENT_DATE;
            END

            IF (V$AUTO_VAL <> '') THEN
            BEGIN
                SELECT BLOB_ID
                FROM VAL_ADD(:V$PARAM_ID, :I$OBJ_ID, :V$AUTO_VAL, :I$USER_ID, 0)
                INTO :V$BLOB_ID;
            END
        END
        ELSE
        IF ((V$IS_LINK_REFERENSE = 1) AND ((V$LINK_REFERENSE_TYPE_ID IS NULL) OR (V$LINK_REFERENSE_TYPE_ID = I$TYPE_ID) OR (V$LINK_REFERENSE_TYPE_ID = I$PARENT_TYPE_ID))) THEN
        BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD(:V$PARAM_ID, :I$OBJ_ID, :I$PARENT_ID, :I$USER_ID, 0)
            INTO :V$BLOB_ID;
        END
    END

    FOR
        SELECT CHILD_ID
        FROM PARENTS
        WHERE TYPE_ID = :I$TYPE_ID AND IS_AUTO_CREATE = 1 AND IS_DEL = 0
        INTO :V$CHILD_TYPE_ID
    DO
    BEGIN
        INSERT INTO OBJECTS (TYPE_ID)
        VALUES (:V$CHILD_TYPE_ID)
        RETURNING OBJ_ID
        INTO :V$CHILD_OBJ_ID;

        INSERT INTO LINKS (PARENT_ID, OBJ_ID, DATE_INS)
        VALUES (:I$OBJ_ID, :V$CHILD_OBJ_ID, :I$DATE_INS);

        HAS_CHILD = HAS_CHILD + 1;

        SELECT HAS_CHILD
        FROM OBJECT_CREATE_AUTO_PARAMS(:V$CHILD_OBJ_ID, :V$CHILD_TYPE_ID, :I$OBJ_ID, :I$TYPE_ID, :I$USER_ID, :I$DATE_INS)
        INTO :HAS_CHILD;

        -- Создаем папки для отчетов
        IF(I$TYPE_ID = 511 AND I$PARENT_TYPE_ID IN (2, 111, 112)) THEN EXECUTE PROCEDURE CREATE_REPORT_FOLDERS(:V$CHILD_OBJ_ID);
    END

    IF (I$TYPE_ID = 297) THEN
    BEGIN
        V$Y = EXTRACT(YEAR FROM CURRENT_DATE);
        V$DT = '1.09.' || V$Y;
        
        IF (CURRENT_DATE < V$DT) THEN
        BEGIN
            V$YEAR_VAL = (V$Y - 1) || '-' || V$Y;
        END
        ELSE
        BEGIN
            V$YEAR_VAL = V$Y || '-' ||(V$Y + 1);
        END
        
        SELECT FIRST 1 LV.LISTVAL_ID
        FROM LISTVALS LV
        JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
        WHERE LV.LIST_ID = 29 AND R.VAL LIKE :V$YEAR_VAL
        INTO :V$YEAR_ID;

        SELECT BLOB_ID
        FROM VAL_ADD(2394, :I$OBJ_ID, :V$YEAR_ID, :I$USER_ID, 0)
        INTO :V$BLOB_ID;
    END

    IF (I$TYPE_ID = 461) THEN
    BEGIN
        SELECT BLOB_ID
        FROM VAL_ADD(3307, :I$OBJ_ID, CURRENT_DATE, :I$USER_ID, 0)
        INTO :V$BLOB_ID;
    END

    SUSPEND;
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OBJECT_DEL (
    I$PARENT_ID BIGINT,
    I$OBJ_ID BIGINT)
RETURNS (
    DEL_COUNT INTEGER)
AS
DECLARE VARIABLE V$PARENTS_COUNT BIGINT;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$PARENT_ID BIGINT;
DECLARE VARIABLE V$DEL_COUNT INTEGER;
DECLARE VARIABLE V$OBJ_TYPE_ID BIGINT;
DECLARE VARIABLE V$PARENT_TYPE_ID BIGINT;
DECLARE VARIABLE V$TAG VARCHAR(100);
DECLARE VARIABLE V$LISTVAL_ID BIGINT;
DECLARE VARIABLE V$BLOB_ID BIGINT;
DECLARE VARIABLE V$OU_LICENCE_TYPE VARCHAR(1);
DECLARE VARIABLE V$HOURS INTEGER;
DECLARE VARIABLE S VARCHAR(400);
DECLARE VARIABLE N INTEGER;
BEGIN
    SELECT O.TYPE_ID, T.TAG
    FROM OBJECTS O
    JOIN TYPES T ON T.TYPE_ID = O.TYPE_ID
    WHERE OBJ_ID = :I$OBJ_ID
    INTO :V$OBJ_TYPE_ID, :V$TAG;

    SELECT TYPE_ID FROM OBJECTS WHERE OBJ_ID = :I$PARENT_ID INTO :V$PARENT_TYPE_ID;

    IF (V$TAG = 'OP') THEN
    BEGIN
      EXECUTE PROCEDURE OO_SPECIALITY_LINK_DELETE(:I$OBJ_ID);
    END

    -- Эта ветка уже не работает
    IF (V$PARENT_TYPE_ID = 54 AND V$OBJ_TYPE_ID = 9) THEN
    BEGIN
        SELECT STATUS FROM OU_LICENCE_TYPE INTO :V$OU_LICENCE_TYPE;
        IF (V$OU_LICENCE_TYPE = 'C') THEN
        BEGIN
            FOR
                SELECT VAL1753.LISTVAL_ID
                FROM LINKS LP50
                JOIN LINKS LP57 ON LP57.OBJ_ID = LP50.PARENT_ID AND LP57.PARENT_TYPE_ID = 57 AND LP57.DATE_DEL IS NULL
                JOIN VALL VAL1753 ON VAL1753.OBJ_ID = LP57.PARENT_ID AND VAL1753.PARAM_ID = 1753 AND VAL1753.IS_DEL = 0
                WHERE LP50.OBJ_ID = :I$PARENT_ID AND LP50.PARENT_TYPE_ID = 50 AND LP50.DATE_DEL IS NULL
                INTO :V$LISTVAL_ID
            DO
            BEGIN
                SELECT BLOB_ID
                FROM VAL_ADD(2165, :I$OBJ_ID, :V$LISTVAL_ID, NULL, 1)
                INTO :V$BLOB_ID;
            END
        END
    END

    -- Нельзя удалять последний корневой объект дерева
    IF(I$PARENT_ID IS NULL AND V$OBJ_TYPE_ID IN (2, 111, 112, 124)) THEN
    BEGIN
      IF(NOT EXISTS(
        SELECT FIRST 1 1
        FROM LINKS L
        WHERE L.PARENT_ID IS NULL AND L.OBJ_TYPE_ID IN (2, 111, 112, 124) AND L.DATE_DEL IS NULL AND L.OBJ_ID <> :I$OBJ_ID
      ))
      THEN
        EXCEPTION DATA_ERROR 'Нельзя удалять последний корневой объект';
    END

    -- При удалении организации или района делаем физическую вычистку хвостов
    IF (V$OBJ_TYPE_ID IN (2, 124, 111)) THEN
    BEGIN
      SELECT R
      FROM IMPORT_CLEAR_LINKS(:I$OBJ_ID / 1000000000, IIF(:V$OBJ_TYPE_ID = 111, 2, 1))
      INTO :V$DEL_COUNT;
    END

    -- Удаление предметов из компонентов, требуем чтобы были обнулены нагрузки, а также нельзя удалять профильные предметы из обязательной части
    -- разрешаем удалять когда сам план уже удален
    IF (V$PARENT_TYPE_ID = 49 AND V$OBJ_TYPE_ID = 51) THEN
    BEGIN
        SELECT SUM(V385.VAL)
        FROM LINKS LP50
        -- Тройная связь 49, 51, 54 -> 56
        JOIN LINKS L51_56 ON L51_56.PARENT_ID = :I$OBJ_ID AND L51_56.OBJ_TYPE_ID = 56 AND L51_56.DATE_DEL IS NULL
        JOIN LINKS L49_56 ON L49_56.PARENT_ID = :I$PARENT_ID AND L49_56.OBJ_TYPE_ID = 56 AND L49_56.DATE_DEL IS NULL AND L49_56.OBJ_ID = L51_56.OBJ_ID
        JOIN LINKS L54 ON L54.PARENT_ID = LP50.PARENT_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
        JOIN LINKS L54_56 ON L54_56.PARENT_ID = L54.OBJ_ID AND L54_56.OBJ_TYPE_ID = 56 AND L54_56.DATE_DEL IS NULL AND L54_56.OBJ_ID = L51_56.OBJ_ID
        JOIN VALI V385 ON V385.OBJ_ID = L51_56.OBJ_ID AND V385.PARAM_ID = 385 AND V385.IS_DEL = 0
        WHERE LP50.OBJ_ID = :I$PARENT_ID AND LP50.PARENT_TYPE_ID = 50 AND LP50.DATE_DEL IS NULL
        INTO :V$HOURS;
        IF(V$HOURS IS NOT NULL AND V$HOURS > 0) THEN EXCEPTION DATA_ERROR 'Нельзя удалять предмет, пока у него задана нагрузка в учебном плане';

        -- Это предмет из обязательной части ?
        SELECT FIRST 1 V372.LISTVAL_ID
        FROM VALL V372
        WHERE V372.OBJ_ID = :I$PARENT_ID AND V372.PARAM_ID = 372 AND V372.IS_DEL = 0
        INTO :V$LISTVAL_ID;

        IF(V$LISTVAL_ID IN (780, 12752)) THEN
        BEGIN
          IF(EXISTS(
            SELECT FIRST 1 1
            FROM LINKS LP50
            JOIN LINKS L51 ON L51.PARENT_ID = LP50.PARENT_ID AND L51.OBJ_ID = :I$OBJ_ID AND L51.DATE_DEL IS NULL
            WHERE LP50.OBJ_ID = :I$PARENT_ID AND LP50.PARENT_TYPE_ID = 50 AND LP50.DATE_DEL IS NULL
          ))
          THEN
          BEGIN
            EXCEPTION DATA_ERROR 'Данный предмет указан в составе профильных для выбранного УП, удаление невоможно';
          END
        END

        -- Нет ли потоков по этому предмету ?
        N = 0;

        SELECT FIRST 1 1
        FROM LINKS LP50
        JOIN LINKS L54 ON L54.PARENT_ID = LP50.PARENT_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
        JOIN LINKS L346 ON L346.PARENT_ID = L54.OBJ_ID AND L346.OBJ_TYPE_ID = 346 AND L346.DATE_DEL IS NULL
        JOIN VALR V2705 ON V2705.OBJ_ID = L346.OBJ_ID AND V2705.PARAM_ID = 2705 AND V2705.IS_DEL = 0 AND V2705.VAL = :I$OBJ_ID
        WHERE LP50.OBJ_ID = :I$PARENT_ID AND LP50.PARENT_TYPE_ID = 50 AND LP50.DATE_DEL IS NULL
        INTO :N;

        IF(N > 0) THEN EXCEPTION DATA_ERROR 'Нельзя удалить предмет при созданном делении на потоки по этому предмету';

    END

    IF((V$PARENT_TYPE_ID = 193 AND V$OBJ_TYPE_ID = 197) OR (V$PARENT_TYPE_ID = 53 AND V$OBJ_TYPE_ID = 51)) THEN
    BEGIN
        V$BLOB_ID = NULL;
        SELECT FIRST 1 PS.PLAN_ID
        FROM PLAN_SUBJECTS PS
        JOIN LINKS LP57 ON LP57.OBJ_ID = PS.PLAN_ID AND LP57.PARENT_TYPE_ID = 57 AND LP57.DATE_DEL IS NULL
        WHERE PS.DATE_DEL IS NULL AND PS.SUBJECT_ID = :I$OBJ_ID
        INTO :V$BLOB_ID;

        IF(V$BLOB_ID IS NOT NULL) THEN
            EXCEPTION DATA_ERROR 'Нельзя удалять предмет/модуль/дисциплину, используемую в действующем УП ' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$BLOB_ID));

        S = NULL;
        SELECT FIRST 1 J.JOURNAL_NAME
        FROM CJ2_JOURNAL J
        WHERE J.DATE_DEL IS NULL AND J.SUBJECT_ID = :I$OBJ_ID
        INTO :S;

        IF(S IS NOT NULL) THEN
            EXCEPTION DATA_ERROR 'Нельзя удалять предмет/модуль/дисциплину, используемую в действующем журнале ' || S;
    END

    -- Нельзя удалять утвержденный УП
    IF(V$PARENT_TYPE_ID = 57 AND V$OBJ_TYPE_ID IN (50, 400)) THEN
    BEGIN
        IF(EXISTS(
            SELECT 1
            FROM VALL
            WHERE OBJ_ID = :I$OBJ_ID AND IS_DEL = 0 AND PARAM_ID IN (2470, 3013) AND LISTVAL_ID = 11715
        ))
        THEN EXCEPTION DATA_ERROR 'Нельзя удалять действующий учебный план';
    END

    -- Нельзя удалять этапы в УП при наличии утверждения или прописанных часах
    -- только если сам план еще не удален
    IF(V$PARENT_TYPE_ID = 400 AND V$OBJ_TYPE_ID = 54) THEN
    BEGIN
        IF(EXISTS(
            SELECT FIRST 1 1
            FROM LINKS LP
            WHERE LP.OBJ_ID = :I$PARENT_ID AND LP.PARENT_TYPE_ID IN (57, 55) AND LP.DATE_DEL IS NULL
        )) THEN
        BEGIN
            IF(EXISTS(
                SELECT 1
                FROM VALL
                WHERE OBJ_ID = :I$PARENT_ID AND IS_DEL = 0 AND PARAM_ID IN (2470, 3013) AND LISTVAL_ID = 11715
            ))
            THEN EXCEPTION DATA_ERROR 'Нельзя удалять этапы действующего учебного плана';
            IF(EXISTS(
                SELECT 1
                FROM PLAN_SUBJECTS PS
                JOIN PLAN_LOADS PL ON PL.DATE_DEL IS NULL AND PL.SUBJECT_ID = PS.OBJ_ID AND PL.STAGE_ID = :I$OBJ_ID AND (PL.LOAD_HOURS_S1 > 0 OR PL.LOAD_HOURS_S2 > 0)
                WHERE PS.PLAN_ID = :I$PARENT_ID AND PS.DATE_DEL IS NULL AND PS.ROW_TYPE = 10
            ))
            THEN EXCEPTION DATA_ERROR 'Нельзя удалять этапы учебного плана при наличии нагрузки';
        END
    END

    -- Нельзя удалять периоды, связанные с журналами
    IF(V$OBJ_TYPE_ID = 151) THEN
    BEGIN
        IF(EXISTS(
            SELECT FIRST 1 1
            FROM CJ2_JOURNAL
            WHERE DATE_DEL IS NULL AND PERIOD_ID = :I$OBJ_ID
        ))
        THEN EXCEPTION DATA_ERROR 'Нельзя удалять периоды, связаны с действующими журналами';
    END

    IF(V$OBJ_TYPE_ID = 478) THEN
    BEGIN
        EXECUTE PROCEDURE VOSP_PLAN_DELETE(:I$OBJ_ID);
    END

    -- Земельный участок
    IF(V$OBJ_TYPE_ID = 490) THEN
    BEGIN
        EXECUTE PROCEDURE STEAD_DELETE(:I$OBJ_ID);
    END

    -- Запрещаем удалять предустановленные предметные области для предметов
    -- Для предметов ФГОС и так будет действовать запрет
    IF (V$PARENT_TYPE_ID = 51 AND V$OBJ_TYPE_ID = 302) THEN
    BEGIN
        IF(I$OBJ_ID < 1000000000) THEN EXCEPTION DATA_ERROR 'Вы не можете изменять предустановленные предметные области';
    END

    -- При удалении ученика из ГУП удаляем его также из всех подгрупп этой ГУП
    IF (V$PARENT_TYPE_ID = 256 AND V$OBJ_TYPE_ID = 10) THEN
    BEGIN
        UPDATE LINKS LP48
        SET LP48.DATE_DEL = CURRENT_TIMESTAMP
        WHERE LP48.OBJ_ID = :I$OBJ_ID AND LP48.DATE_DEL IS NULL AND LP48.PARENT_ID IN (
            SELECT L48.OBJ_ID
            FROM LINKS L47
            JOIN LINKS L48 ON L48.PARENT_ID = L47.OBJ_ID AND L48.OBJ_TYPE_ID = 48 AND L48.DATE_DEL IS NULL
            WHERE L47.PARENT_ID = :I$PARENT_ID AND L47.OBJ_TYPE_ID = 47 AND L47.DATE_DEL IS NULL
        );
    END

    -- Длительный отпуск
    IF(V$OBJ_TYPE_ID = 376) THEN
    BEGIN
        EXECUTE PROCEDURE LONGVACATION_DELETE(:I$OBJ_ID);
    END

    -- Нельзя удалять наставников у уволенных
    IF(V$OBJ_TYPE_ID = 397) THEN
    BEGIN
        IF(NOT EXISTS(
            SELECT FIRST 1 1
            FROM LINKS LP
            WHERE LP.OBJ_ID = :I$PARENT_ID AND LP.PARENT_TYPE_ID IN (2, 211) AND LP.DATE_DEL IS NULL
        )) THEN EXCEPTION DATA_ERROR 'Нельзя удалять записи наставничества у недействующих сотрудников';
    END

    -- При удалении ученика из выбывших прибиваем записи движения в классах
    IF (V$PARENT_TYPE_ID IN (81, 82, 83) AND V$OBJ_TYPE_ID = 10) THEN
    BEGIN
        EXECUTE PROCEDURE DROP_STUDENT_MOVEMENTS(:I$OBJ_ID);
    END

    -- При удалении своего отставшего из класса для сдачи ГИА, при наличии аттестата - перемещаем в окончивших
    IF (V$PARENT_TYPE_ID = 125 AND V$OBJ_TYPE_ID = 10) THEN
    BEGIN
        -- !!!
    END

    IF(V$OBJ_TYPE_ID IN (441, 442, 443, 444, 447, 453)) THEN
    BEGIN
        EXECUTE PROCEDURE GZ_DELETE_CHECK(:I$OBJ_ID, :V$OBJ_TYPE_ID);
    END

    IF(V$OBJ_TYPE_ID = 11) THEN
    BEGIN
        IF(EXISTS(
            SELECT FIRST 1 1
            FROM VALS
            WHERE OBJ_ID = :I$OBJ_ID AND PARAM_ID = 569 AND IS_DEL = 0
        ))
        THEN EXCEPTION DATA_ERROR 'Нельзя удалить автоматически созданный документ об образовании';
    END

    IF(V$OBJ_TYPE_ID = 458) THEN
    BEGIN
        IF(EXISTS(
            SELECT FIRST 1 1
            FROM VALL V
            WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 3299 AND V.IS_DEL = 0 AND V.LISTVAL_ID = 2
        ) OR EXISTS(
            SELECT FIRST 1 1
            FROM LINKS L459
            JOIN VALS V ON V.OBJ_ID = L459.OBJ_ID AND V.PARAM_ID IN (3291, 3297) AND V.IS_DEL = 0
            WHERE L459.PARENT_ID = :I$OBJ_ID AND L459.OBJ_TYPE_ID = 459 AND L459.DATE_DEL IS NULL
        ))
        THEN EXCEPTION DATA_ERROR 'Нельзя удалить пакет документов, если весь пакет или хотя бы один документ уже были отправлены';
    END

    -- МТР
    IF(V$OBJ_TYPE_ID IN (95, 97, 106, 107) AND V$PARENT_TYPE_ID IN (23, 92, 104, 105)) THEN
    BEGIN
      V$BLOB_ID = NULL;

      SELECT FIRST 1 S.PLAN_ID
      FROM PLAN_RESOURCES R
      JOIN PLAN_LOADS L ON L.DATE_DEL IS NULL AND L.OBJ_ID = R.LOAD_ID
      JOIN PLAN_SUBJECTS S ON S.DATE_DEL IS NULL AND S.OBJ_ID = L.SUBJECT_ID
      WHERE R.DATE_DEL IS NULL AND R.RES_ID = :I$OBJ_ID
      INTO :V$BLOB_ID;

      IF(V$BLOB_ID IS NOT NULL) THEN EXCEPTION DATA_ERROR 'Ресурс используется в учебном плане (' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$BLOB_ID)) || '), нельзя удалить';
    END

    IF(V$OBJ_TYPE_ID = 459) THEN
    BEGIN
      IF(EXISTS(
        SELECT FIRST 1 1
        FROM VALS V
        WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID IN (3291, 3297) AND V.IS_DEL = 0
      ))
      THEN EXCEPTION DATA_ERROR 'Нельзя удалить критерий оценивания, если он уже был отправлен';
    END

    -- Удаление классов и будущих классов - проверяем ГУП и вообще возможность удаления
    IF(V$PARENT_TYPE_ID = 8 AND V$OBJ_TYPE_ID IN (9, 403)) THEN
    BEGIN
      EXECUTE PROCEDURE FUTURE_GUP_CHECK(:I$OBJ_ID);
    END

    IF(V$PARENT_TYPE_ID = 496 AND V$OBJ_TYPE_ID = 17) THEN
    BEGIN
      EXCEPTION DATA_ERROR 'Документы в архиве удалять нельзя';
    END

    IF(V$OBJ_TYPE_ID = 17) THEN
    BEGIN
      IF(EXISTS(
        SELECT FIRST 1 1
        FROM VALR V
        JOIN LINKS LP2 ON LP2.OBJ_ID = V.OBJ_ID AND LP2.PARENT_TYPE_ID = 2 AND LP2.DATE_DEL IS NULL
        WHERE V.PARAM_ID = 3433 AND V.IS_DEL = 0 AND V.VAL = :I$OBJ_ID
      ))
      THEN EXCEPTION DATA_ERROR 'Нельзя удалить документ, зарегистрированный как документ жизненного цикла ОООД';
    END

    -- Redmine #1110 Нельзя удалять документ СНИЛС
    IF (V$OBJ_TYPE_ID = 12 AND V$PARENT_TYPE_ID IN (10, 14) AND EXISTS(
      SELECT FIRST 1 1
      FROM VALL V51
      WHERE V51.OBJ_ID = :I$OBJ_ID AND V51.PARAM_ID = 51 AND V51.IS_DEL = 0 AND V51.LISTVAL_ID = 1384
    )) THEN
    BEGIN
      EXCEPTION DATA_ERROR 'Необходимо удалять номер СНИЛС в личном деле персоны';
    END

    -- Выполняем непосредственно процедуру маркировки удаления
    UPDATE LINKS
    SET DATE_DEL = CURRENT_TIMESTAMP
    WHERE PARENT_ID = :I$PARENT_ID AND OBJ_ID = :I$OBJ_ID AND DATE_DEL IS NULL;

    V$DEL_COUNT = ROW_COUNT;

    -- Пересчет площадей для помещений (учебно-лабораторные)
    -- Пересчет количества учебно-лабораторных помещений (фактического)
    IF(V$OBJ_TYPE_ID = 61) THEN
    BEGIN
      EXECUTE PROCEDURE AREA_SL_ROOMS_CALC(:I$OBJ_ID);
      EXECUTE PROCEDURE COUNT_SL_ROOMS_CALC(:I$OBJ_ID);
    END

    -- Назначение на должность
    IF(V$OBJ_TYPE_ID = 15) THEN
    BEGIN
      EXECUTE PROCEDURE VACANCY_UPDATE_CAT(:I$OBJ_ID);
    END

    /* 15 - PRIEM SOTRUDNIKA NA DOLJNOST,
       56 - NAGRUZKAUC,
       58 - ELEMENT RASPISANIYA,
       123 - GIA MARK
       ALWAYS FULL DELETE */
    IF (V$OBJ_TYPE_ID IN (15, 56, 58, 70, 123) OR ((V$OBJ_TYPE_ID = 114) AND (V$PARENT_TYPE_ID = 95))) THEN
    BEGIN
      UPDATE LINKS L
      SET L.DATE_DEL = CURRENT_TIMESTAMP
      WHERE L.OBJ_ID = :I$OBJ_ID AND L.DATE_DEL IS NULL;

      V$DEL_COUNT = V$DEL_COUNT + ROW_COUNT;
    END

    -- Количество ТСО
    IF(V$OBJ_TYPE_ID = 114) THEN
    BEGIN
      SELECT COUNT(*) FROM LINKS WHERE PARENT_ID = :I$PARENT_ID AND OBJ_TYPE_ID = 114 AND DATE_DEL IS NULL INTO :N;
      SELECT BLOB_ID FROM VAL_ADD(605, :I$PARENT_ID, :N) INTO :V$BLOB_ID;
    END

    IF(V$OBJ_TYPE_ID = 442) THEN
    BEGIN
      EXECUTE PROCEDURE GZ_RENUMBER_SECTIONS(:I$PARENT_ID);
    END

    -- Каскадно удаляем объекты, на которые более нет ссылок
    SELECT COUNT(*)
    FROM LINKS
    WHERE OBJ_ID = :I$OBJ_ID AND DATE_DEL IS NULL
    INTO :V$PARENTS_COUNT;

    -- Отдельный случай для удаления учеников после выдачи им аттестата
    -- Их не удаляем, а кладем в окончивших
    IF(V$PARENTS_COUNT = 0 AND V$OBJ_TYPE_ID = 126) THEN
    BEGIN
      EXECUTE PROCEDURE ADD_EXTERNAT_GRADUATE(:I$OBJ_ID, :I$PARENT_ID);
      V$PARENTS_COUNT = 1;
    END

    IF (V$PARENTS_COUNT = 0) THEN
    BEGIN
      FOR
        SELECT OBJ_ID, PARENT_ID
        FROM LINKS
        WHERE PARENT_ID = :I$OBJ_ID AND DATE_DEL IS NULL
        ORDER BY LINK_ID DESC
        INTO :V$OBJ_ID, :V$PARENT_ID
      DO
      BEGIN
        SELECT DEL_COUNT + :V$DEL_COUNT
        FROM OBJECT_DEL(:V$PARENT_ID, :V$OBJ_ID)
        INTO :V$DEL_COUNT;
      END
    END

    DEL_COUNT = V$DEL_COUNT;
    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OBJECT_FRAMES_LIST (
    I$TYPE_ID BIGINT,
    I$PARENT_TYPE_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$PARENT_ID BIGINT,
    I$LEVEL_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    PARENT_TYPE_ID BIGINT,
    TYPE_ID BIGINT,
    CAPTION VARCHAR(200),
    FRAME_CLASS VARCHAR(100),
    IS_DEL SMALLINT,
    TAB_ID INTEGER)
AS
declare variable ALLOWED smallint;
declare variable I bigint;
declare variable I2 bigint;
begin

  FOR
    SELECT OBJ_ID, PARENT_TYPE_ID, TYPE_ID, CAPTION, FRAME_CLASS, IS_DEL, TAB_ID
    FROM OBJECT_FRAMES
    WHERE ((LEVEL_ID = :I$LEVEL_ID) or (LEVEL_ID IS NULL)) AND TYPE_ID = :I$TYPE_ID AND (PARENT_TYPE_ID = :I$PARENT_TYPE_ID OR (:I$PARENT_TYPE_ID IS NULL AND PARENT_TYPE_ID IS NULL)) AND IS_DEL = 0
    ORDER BY OBJ_ID
    INTO :OBJ_ID, :PARENT_TYPE_ID, :TYPE_ID, :CAPTION, :FRAME_CLASS, :IS_DEL, :TAB_ID
  DO
  BEGIN
    ALLOWED = 1;

    -- Предметы по выбору - только для обычных УП, не-ВД и не индивидуальных
    IF(OBJ_ID = 100) THEN
    BEGIN

      SELECT V2101.LISTVAL_ID, V2545.LISTVAL_ID
      FROM LINKS LP50
      LEFT JOIN VALL V2101 ON V2101.OBJ_ID = LP50.PARENT_ID AND V2101.PARAM_ID = 2101 AND V2101.IS_DEL = 0
      LEFT JOIN VALL V2545 ON V2545.OBJ_ID = LP50.PARENT_ID AND V2545.PARAM_ID = 2545 AND V2545.IS_DEL = 0
      WHERE LP50.OBJ_ID = :I$OBJ_ID AND LP50.PARENT_TYPE_ID = 50 AND LP50.DATE_DEL is null
      INTO :I, :I2;

      IF(I is null OR I <> 5465) THEN ALLOWED = 0;
      IF(I2 is null OR I2 <> 3) THEN ALLOWED = 0;

    END

    IF(ALLOWED = 1) THEN SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OBJECT_GET_BY_PARAMS (
    I$PARENT_ID BIGINT,
    I$TYPE_ID BIGINT,
    I$PARAM_ID0 BIGINT,
    I$VAL0 VARCHAR(500) = '',
    I$PARAM_ID1 BIGINT = NULL,
    I$VAL1 VARCHAR(500) = '',
    I$PARAM_ID2 BIGINT = NULL,
    I$VAL2 VARCHAR(500) = '',
    I$PARAM_ID3 BIGINT = NULL,
    I$VAL3 VARCHAR(500) = '')
RETURNS (
    OBJ_ID BIGINT)
AS
BEGIN
    FOR
        SELECT DISTINCT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = :I$TYPE_ID
          AND (:I$PARENT_ID IS NULL OR L.PARENT_ID = :I$PARENT_ID)
          AND L.DATE_DEL IS NULL
          AND ((SELECT V FROM VAL_GET(L.OBJ_ID, :I$PARAM_ID0)) = :I$VAL0
            OR (SELECT CAST(I AS VARCHAR(500)) FROM VAL_GET(L.OBJ_ID, :I$PARAM_ID0)) = :I$VAL0)
        INTO :OBJ_ID
    DO
    BEGIN
        IF ((:I$PARAM_ID1 IS NULL OR (SELECT V FROM VAL_GET(:OBJ_ID, :I$PARAM_ID1)) = :I$VAL1
                 OR (SELECT CAST(I AS VARCHAR(500)) FROM VAL_GET(:OBJ_ID, :I$PARAM_ID1)) = :I$VAL1) AND
            (:I$PARAM_ID2 IS NULL OR (SELECT V FROM VAL_GET(:OBJ_ID, :I$PARAM_ID2)) = :I$VAL2
                 OR (SELECT CAST(I AS VARCHAR(500)) FROM VAL_GET(:OBJ_ID, :I$PARAM_ID2)) = :I$VAL2) AND
            (:I$PARAM_ID3 IS NULL OR (SELECT V FROM VAL_GET(:OBJ_ID, :I$PARAM_ID3)) = :I$VAL3
                 OR (SELECT CAST(I AS VARCHAR(500)) FROM VAL_GET(:OBJ_ID, :I$PARAM_ID3)) = :I$VAL3)) THEN
        BEGIN
            SUSPEND;
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OBJECT_GRIDS_LIST (
    I$USER_ID BIGINT,
    I$TYPE_ID BIGINT,
    I$LEVEL_ID BIGINT,
    I$TAB_ID BIGINT,
    I$OBJ_ID BIGINT = NULL,
    I$PARENT_ID BIGINT = NULL)
RETURNS (
    OBJ_ID BIGINT,
    TYPE_ID BIGINT,
    TYPE_CAPTION VARCHAR(4000),
    IS_ADD SMALLINT,
    IS_COPY SMALLINT,
    IS_CUT SMALLINT,
    IS_LINK SMALLINT,
    IS_FROM_LIST SMALLINT,
    RUN_SQL VARCHAR(1000),
    DO_FUNC SMALLINT,
    IS_AUTO_CREATE SMALLINT,
    EDIT_TYPE SMALLINT,
    IS_SELECT SMALLINT,
    SORT_ORDER SMALLINT,
    IS_TAB_VERTICAL_ALIGNMENT SMALLINT,
    SHOW_ALL_FIELDS SMALLINT,
    RUN_FUNCTION SMALLINT)
AS
DECLARE VARIABLE V$EXT_OBJ_TYPE_ID BIGINT;
DECLARE VARIABLE V$EXT_OBJ_ID BIGINT;
DECLARE VARIABLE V$TAB_ID BIGINT;
DECLARE VARIABLE V$LANG_CODE CHAR(2) = 'RU';
DECLARE VARIABLE V$RES_ID BIGINT;
DECLARE VARIABLE V$TAB_NAME VARCHAR(1000);
DECLARE VARIABLE V$TYPE_USER BIGINT = NULL;
DECLARE VARIABLE V$ROOT_C BIGINT = NULL;
DECLARE VARIABLE V$HAS_ROOT_PARENT SMALLINT;
DECLARE VARIABLE V$READ_ONLY BIGINT;
DECLARE VARIABLE V$PARENT_TYPE_ID BIGINT;
DECLARE VARIABLE V$SUSPEND_FL SMALLINT;
DECLARE VARIABLE V$TEMP BIGINT;
BEGIN
    SELECT FIRST 1 L.READ_ONLY, L.ROOT_OBJ_ID
    FROM LUSERS L
    WHERE L.LEVEL_ID = :I$LEVEL_ID AND L.USER_ID = :I$USER_ID
    INTO :V$READ_ONLY, :V$ROOT_C;

    SELECT U.USER_TYPE FROM USERS U WHERE U.USER_ID = :I$USER_ID INTO :V$TYPE_USER;

    SELECT STATUS FROM IS_ROOT_OBJ_PARENT(:I$PARENT_ID, :V$ROOT_C, :I$LEVEL_ID) INTO :V$HAS_ROOT_PARENT;

    SELECT FIRST 1 EXT_OBJ_TYPE_ID, EXT_OBJ_ID, PARENT_TYPE_ID
    FROM LINKS
    WHERE OBJ_ID = :I$OBJ_ID AND PARENT_ID = :I$PARENT_ID AND DATE_DEL IS NULL
    INTO :V$EXT_OBJ_TYPE_ID, :V$EXT_OBJ_ID, :V$PARENT_TYPE_ID;

    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :V$LANG_CODE;

    SELECT R.VAL
    FROM TABS T
    JOIN RES R ON R.RES_ID = T.RES_ID AND R.LANG_CODE = :V$LANG_CODE
    WHERE T.TAB_ID = :I$TAB_ID AND T.IS_DEL = 0 INTO :V$TAB_NAME;

    IF (I$TAB_ID < 0) THEN V$TAB_ID = I$TAB_ID;

    SELECT T.TAB_ID
    FROM TABS T
    JOIN RES R ON R.RES_ID = T.RES_ID AND R.LANG_CODE = :V$LANG_CODE
    WHERE T.TYPE_ID = :V$EXT_OBJ_TYPE_ID AND T.IS_DEL = 0 AND R.VAL LIKE :V$TAB_NAME INTO :V$TAB_ID;

    -- В приложении "Школьные карты" гриды для ГПД/ДО вообще не показываем
    --IF(I$LEVEL_ID = 475 AND ) THEN EXIT;

    FOR
        -- Нормальные дочерние объекты
        SELECT P.CHILD_ID, P.IS_ADD, P.IS_COPY, P.IS_CUT, P.IS_LINK, P.DO_FUNC, P.IS_FROM_LIST, P.RUN_SQL, P.IS_AUTO_CREATE, T.RES_ID,
            LT.EDIT_TYPE, P.IS_SELECT, T.SORT_ORDER, P.IS_TAB_VERTICAL_ALIGNMENT, :I$OBJ_ID, P.SHOW_ALL_FIELDS, P.RUN_FUNCTION
        FROM PARENTS P
        JOIN TYPES T ON T.TYPE_ID = P.CHILD_ID AND T.IS_HIDDEN = 0 AND T.IS_DEL = 0
        JOIN LTYPES LT ON T.TYPE_ID = LT.TYPE_ID AND LT.LEVEL_ID = :I$LEVEL_ID AND LT.IS_DEL = 0
        WHERE P.TYPE_ID = :I$TYPE_ID AND P.IS_DEL = 0
            AND (((:I$TAB_ID = -1 OR :I$TAB_ID IS NULL) AND P.TAB_ID IS NOT NULL) OR :I$TAB_ID = -2 OR P.TAB_ID = :I$TAB_ID)

        -- Боковая ветка
        UNION ALL
        SELECT P.CHILD_ID, P.IS_ADD, P.IS_COPY, P.IS_CUT, P.IS_LINK, P.DO_FUNC, P.IS_FROM_LIST, P.RUN_SQL, P.IS_AUTO_CREATE, T.RES_ID,
            LT.EDIT_TYPE, P.IS_SELECT, T.SORT_ORDER, P.IS_TAB_VERTICAL_ALIGNMENT, :V$EXT_OBJ_ID, P.SHOW_ALL_FIELDS, P.RUN_FUNCTION
        FROM PARENTS P
        JOIN TYPES T ON T.TYPE_ID = P.CHILD_ID AND T.IS_HIDDEN = 0 AND T.IS_DEL = 0
        JOIN LTYPES LT ON T.TYPE_ID = LT.TYPE_ID AND LT.LEVEL_ID = :I$LEVEL_ID AND LT.IS_DEL = 0
        WHERE P.TYPE_ID = :V$EXT_OBJ_TYPE_ID AND P.IS_DEL = 0
            AND (((:I$TAB_ID = -1 OR :I$TAB_ID IS NULL) AND P.TAB_ID IS NOT NULL) OR :I$TAB_ID = -2 OR P.TAB_ID = :V$TAB_ID)

        ORDER BY 13 -- SORT_ORDER
        INTO :TYPE_ID, :IS_ADD, :IS_COPY, :IS_CUT, :IS_LINK, :DO_FUNC, :IS_FROM_LIST, :RUN_SQL, :IS_AUTO_CREATE, :V$RES_ID,
            :EDIT_TYPE, :IS_SELECT, :SORT_ORDER, :IS_TAB_VERTICAL_ALIGNMENT, :OBJ_ID, :SHOW_ALL_FIELDS, :RUN_FUNCTION
    DO
    BEGIN
        V$SUSPEND_FL = 1;

        -- хак для скрытия неугодных объектов, с разной видимостью в рамках одной задачи
        IF (V$PARENT_TYPE_ID = 50 AND TYPE_ID = 9) THEN
        BEGIN
          V$SUSPEND_FL = 0;
          -- классы в УП показываем только если Тип образования = Дополнительное (иначе ГУП)
          SELECT FIRST 1 1
          FROM LINKS L57
          JOIN VALL V1593 ON V1593.OBJ_ID = L57.PARENT_ID AND V1593.PARAM_ID = 1593 AND V1593.LISTVAL_ID = 5357 AND V1593.IS_DEL = 0
          WHERE L57.OBJ_ID = :I$PARENT_ID AND L57.PARENT_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
          INTO :V$SUSPEND_FL;
        END
        ELSE IF (V$PARENT_TYPE_ID = 301 AND TYPE_ID = 302) THEN
        BEGIN
          V$SUSPEND_FL = 0;
          -- предметные области доступны только для предметов в разделе общее образование
          SELECT FIRST 1 1
          FROM VALL V2461
          WHERE V2461.OBJ_ID = :I$PARENT_ID AND V2461.PARAM_ID = 2461 AND V2461.IS_DEL = 0 AND V2461.LISTVAL_ID = 11709
          INTO :V$SUSPEND_FL;
          -- Запрещаем редактирование предметных областей для предметов ФГОС, пустое значение считаем как НЕТ
          -- разрешаем только для объектов этой же базы
          V$TEMP = 3;
          SELECT V2465.LISTVAL_ID
          FROM VALL V2465
          WHERE V2465.OBJ_ID = :I$OBJ_ID AND V2465.PARAM_ID = 2465 AND V2465.IS_DEL = 0
          INTO :V$TEMP;

          I$OBJ_ID = I$OBJ_ID / (SELECT MULTIPLIER FROM GEN);
          IF(V$TEMP = 2 AND EDIT_TYPE = 1) THEN EDIT_TYPE = 0;
          IF(EDIT_TYPE = 1 AND (SELECT GEN FROM GEN) <> I$OBJ_ID) THEN EDIT_TYPE = 0;
        END
        ELSE IF (I$TYPE_ID = 49 AND TYPE_ID = 349) THEN
        BEGIN
          -- Замены предметов показываем только в федеральных/обязательных компонентах УП
          SELECT LISTVAL_ID
          FROM VALL V372
          WHERE V372.OBJ_ID = :I$OBJ_ID AND V372.PARAM_ID = 372 AND V372.IS_DEL = 0
          INTO :V$TEMP;

          IF(V$TEMP IS NULL OR V$TEMP NOT IN (780, 12752)) THEN V$SUSPEND_FL = 0;
        END
        ELSE IF (I$TYPE_ID = 10 AND TYPE_ID = 427) THEN
        BEGIN
          -- В обычных классах и предварительном приеме прячем предметы для аттестации
          IF(EXISTS(
            SELECT FIRST 1 1
            FROM LINKS
            WHERE OBJ_ID = :I$OBJ_ID AND PARENT_TYPE_ID IN (9, 290) AND DATE_DEL IS NULL
          )) THEN V$SUSPEND_FL = 0;
          -- Если ученик не числится в экстернате прямо сейчас - делаем RO
          ELSE IF(NOT EXISTS(
            SELECT FIRST 1 1
            FROM LINKS
            WHERE OBJ_ID = :I$OBJ_ID AND PARENT_TYPE_ID = 187 AND DATE_DEL IS NULL
          )) THEN IS_ADD = 0;
        END

        IF (V$SUSPEND_FL = 1) THEN
        BEGIN
            IF(((I$PARENT_ID IS NOT NULL) AND (V$READ_ONLY = 1) AND (EDIT_TYPE > 0)) AND ((:I$LEVEL_ID <> 50) OR (:V$TYPE_USER <> 6) OR (V$HAS_ROOT_PARENT = 0))) THEN EDIT_TYPE = 0;

            SELECT VAL
            FROM RES_GET(:V$RES_ID, :V$LANG_CODE)
            INTO :TYPE_CAPTION;

            IF(I$LEVEL_ID IN (243, 267, 286) AND TYPE_ID = 14) THEN TYPE_CAPTION = 'Преподаватели объединения';
            IF(I$TYPE_ID = 162 AND TYPE_ID = 54) THEN TYPE_CAPTION = 'Несоответствие по предельной наполняемости УП';

            SUSPEND;
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OBJECT_GRID_PARAMS (
    I$USER_ID BIGINT,
    I$TYPE_ID BIGINT,
    I$LEVEL_ID BIGINT,
    I$IS_SELECT SMALLINT = 0,
    I$IS_WRITABLE SMALLINT = 0,
    I$PARENT_ID BIGINT = null,
    I$IS_IMPORT SMALLINT = 0)
RETURNS (
    PARAM_ID BIGINT,
    PARAM_TYPE SMALLINT,
    LIST_ID BIGINT,
    IS_SORT SMALLINT,
    IS_REQUIRED SMALLINT,
    IS_HISTORY SMALLINT,
    PARAM_CAPTION VARCHAR(4000),
    SIZE_CAPTION VARCHAR(1000),
    HINT_CAPTION VARCHAR(4000),
    DO_FUNC BIGINT,
    EDIT_MASK VARCHAR(200),
    RUN_SQL VARCHAR(1000),
    IS_AUTO_CREATE SMALLINT,
    TAG VARCHAR(100),
    EDIT_TYPE SMALLINT,
    BKG_COLOR INTEGER,
    COLOR INTEGER,
    LIST_EDIT_TYPE SMALLINT,
    DO_CHECK SMALLINT,
    DO_CHECK_EVENT SMALLINT,
    BEGIN_GROUP SMALLINT)
AS
declare variable V$RES_ID bigint;
declare variable V$SIZE_RES_ID bigint;
declare variable V$HINT_RES_ID bigint;
declare variable V$LANG_CODE char(2) = 'RU';
declare variable V$READ_ONLY bigint;
declare variable V$TYPE_USER bigint = null;
declare variable V$ROOT_C bigint = null;
declare variable V$HAS_ROOT_PARENT smallint;
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :V$LANG_CODE;

    V$READ_ONLY = 0;

    SELECT FIRST 1L.READ_ONLY, L.ROOT_OBJ_ID
    FROM LUSERS L
    WHERE L.LEVEL_ID = :I$LEVEL_ID AND L.USER_ID = :I$USER_ID
    INTO :V$READ_ONLY, :V$ROOT_C;

    SELECT U.USER_TYPE FROM USERS U WHERE U.USER_ID = :I$USER_ID INTO :V$TYPE_USER;

    SELECT STATUS FROM IS_ROOT_OBJ_PARENT(:I$PARENT_ID, :V$ROOT_C, :I$LEVEL_ID) INTO :V$HAS_ROOT_PARENT;

    IF (I$IS_SELECT = 0) THEN
    BEGIN
        FOR
            SELECT P.PARAM_ID, P.PARAM_TYPE, P.LIST_ID, P.IS_REQUIRED, P.IS_HISTORY, P.RES_ID, P.SIZE_RES_ID, P.HINT_RES_ID, P.DO_FUNC, P.EDIT_MASK,
                P.RUN_SQL, P.IS_AUTO_CREATE, P.TAG, L.EDIT_TYPE, PT.BKG_COLOR, PT.COLOR, P.IS_TREESORT, P.DO_CHECK, P.DO_CHECK_EVENT, P.BEGIN_GROUP
            FROM PARAMS P
            LEFT JOIN LPARAMS L ON P.PARAM_ID = L.PARAM_ID AND L.LEVEL_ID = :I$LEVEL_ID AND L.IS_DEL = 0
            JOIN PARAMTYPES PT ON PT.PARAM_TYPE = P.PARAM_TYPE
            WHERE P.TYPE_ID = :I$TYPE_ID AND P.IS_DEL = 0AND ((:I$IS_IMPORT = 1 AND :I$TYPE_ID = 85) OR L.LEVEL_ID IS NOT NULL)
            ORDER BY P.GRID_ORDER
            INTO :PARAM_ID, :PARAM_TYPE, :LIST_ID, :IS_REQUIRED, :IS_HISTORY, :V$RES_ID, :V$SIZE_RES_ID, :V$HINT_RES_ID, :DO_FUNC, :EDIT_MASK,
                :RUN_SQL, :IS_AUTO_CREATE, :TAG, :EDIT_TYPE, :BKG_COLOR, :COLOR, :IS_SORT, :DO_CHECK, :DO_CHECK_EVENT, :BEGIN_GROUP
        DO
        BEGIN
            IF (((I$PARENT_ID IS NOT NULL) AND (V$READ_ONLY = 1) AND (EDIT_TYPE > 0)) AND
                (((I$LEVEL_ID <> 50) AND /* AP */ (I$LEVEL_ID <> 305)) OR (V$TYPE_USER <> 6) OR (V$HAS_ROOT_PARENT = 0))
            ) THEN EDIT_TYPE = 0;

            LIST_EDIT_TYPE = -1;
            IF (PARAM_TYPE IN (6 /* LIST_VALUE */, 7 /* STRING_OR_LIST_VALUE */, 20 /*STRING_OR_LIST_VALUE_RO*/ )) THEN
            BEGIN
                SELECT L.EDIT_TYPE
                FROM LLISTS L
                WHERE L.LEVEL_ID = :I$LEVEL_ID AND L.LIST_ID = :LIST_ID AND L.IS_DEL = 0
                INTO :LIST_EDIT_TYPE;
            END
            SELECT VAL FROM RES_GET(:V$RES_ID, :V$LANG_CODE) INTO :PARAM_CAPTION;
            SELECT VAL FROM RES_GET(:V$SIZE_RES_ID, :V$LANG_CODE) INTO :SIZE_CAPTION;
            SELECT VAL FROM RES_GET(:V$HINT_RES_ID, :V$LANG_CODE) INTO :HINT_CAPTION;
            IF ((I$IS_IMPORT = 1 AND I$TYPE_ID = 85) OR I$IS_WRITABLE = 0 OR (I$IS_WRITABLE = 1 AND EDIT_TYPE = 1)) THEN SUSPEND;
        END
    END
    ELSE
    BEGIN
        PARAM_CAPTION = '';
        PARAM_TYPE = -1;
        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OBJECT_GRID_VALS (
    I$PARENT_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$TYPE_ID BIGINT,
    I$LEVEL_ID BIGINT,
    I$IS_SELECT SMALLINT = 0,
    I$IS_WRITABLE SMALLINT = 0,
    I$USER_ID BIGINT = null,
    I$IS_EXPORT SMALLINT = 0)
RETURNS (
    LINK_ID BIGINT,
    OBJ_ID BIGINT,
    PARAM_ID BIGINT,
    PARAM_TYPE SMALLINT,
    LIST_ID BIGINT,
    VAL VARCHAR(4000),
    VAL2 VARCHAR(4000),
    COST FLOAT,
    BLOB_ID BIGINT,
    REGION VARCHAR(255),
    DISTRICT VARCHAR(255),
    TOWN VARCHAR(255),
    SETTLEMENT VARCHAR(255),
    STREET VARCHAR(255),
    HOUSE VARCHAR(10),
    CORP VARCHAR(10),
    FLAT VARCHAR(10),
    POST_INDEX VARCHAR(20),
    OCATD VARCHAR(11),
    LISTVAL_ID BIGINT,
    IS_EXISTS SMALLINT,
    SORT_ORDER DOUBLE PRECISION,
    COLOR INTEGER)
AS
declare variable V$IS_OUTLESSON smallint;
declare variable V$EDIT_TYPE smallint;
declare variable V$FILTRED smallint;
declare variable V$DO_FUNC bigint;
declare variable V$OBJ_ID bigint;
declare variable V$PARENT_ID bigint;
declare variable V$PARENT_TYPE_ID bigint;
declare variable V$V varchar(1000);
declare variable V$V2 varchar(1000);
declare variable V$PLAN_ID bigint;
BEGIN
    COST = 0;
    IF (I$IS_SELECT = 0) THEN
    BEGIN
        FOR
            SELECT DISTINCT L.OBJ_ID, P.PARAM_ID, P.LIST_ID, P.PARAM_TYPE, V.SORT_ORDER, LP.EDIT_TYPE, P."DO_FUNC", L.PARENT_ID
            FROM LINKS L
            JOIN TYPES T ON T.TYPE_ID = L.OBJ_TYPE_ID AND T.IS_DEL = 0
            LEFT JOIN LTYPES LT ON LT.TYPE_ID = L.OBJ_TYPE_ID AND LT.LEVEL_ID = :I$LEVEL_ID AND LT.IS_DEL = 0
            JOIN PARAMS P ON P.TYPE_ID = T.TYPE_ID AND P.IS_DEL = 0
            LEFT JOIN PARAMS P2 ON P2.TYPE_ID = T.TYPE_ID AND P2.IS_TREESORT = 1
            LEFT JOIN VAL_GET(L.OBJ_ID, P2.PARAM_ID, 0, :I$USER_ID) V ON P2.IS_TREESORT = 1
            LEFT JOIN LPARAMS LP ON P.PARAM_ID = LP.PARAM_ID AND LP.IS_DEL = 0 AND LP.LEVEL_ID = :I$LEVEL_ID
            WHERE L.PARENT_ID = :I$OBJ_ID AND L.OBJ_TYPE_ID = :I$TYPE_ID AND L.DATE_DEL IS NULL
                AND ((:I$IS_EXPORT = 1 AND :I$TYPE_ID = 85) OR LT.LEVEL_ID IS NOT NULL)
                AND ((:I$IS_EXPORT = 1 AND :I$TYPE_ID = 85) OR LP.LEVEL_ID IS NOT NULL)
            ORDER BY V.SORT_ORDER, L.OBJ_ID, P.GRID_ORDER
            INTO :OBJ_ID, :PARAM_ID, :LIST_ID, :PARAM_TYPE, :SORT_ORDER, :V$EDIT_TYPE, :V$DO_FUNC, :V$PARENT_ID
        DO
        BEGIN
            V$FILTRED = 0;

            LISTVAL_ID = NULL;
            BLOB_ID = NULL;
            VAL = '';
            IF (PARAM_TYPE = 6 /* LIST_VALUE */ OR PARAM_TYPE = 13 /* REFERENCE */ ) THEN
            BEGIN
                SELECT V, I, IS_EXISTS, COST
                FROM VAL_GET(:OBJ_ID, :PARAM_ID, 0, :I$USER_ID)
                INTO :VAL, :LISTVAL_ID, :IS_EXISTS, :COST;
            END
            ELSE
            IF (PARAM_TYPE = 17 OR PARAM_TYPE = 19) THEN
            BEGIN
                SELECT VAL
                FROM DO_FUNC(:OBJ_ID, :PARAM_ID, :V$DO_FUNC, NULL, NULL, :V$PARENT_ID)
                INTO :VAL;
            END
            ELSE
            IF (PARAM_TYPE = 18) THEN
            /*ADDRESS*/
            BEGIN
                SELECT REGION, DISTRICT, TOWN, SETTLEMENT, STREET, HOUSE, CORP, FLAT, POST_INDEX, VAL, OCATD
                FROM ADR_GET(:PARAM_ID, :OBJ_ID, 0)
                INTO :REGION, :DISTRICT, :TOWN, :SETTLEMENT, :STREET, :HOUSE, :CORP, :FLAT, :POST_INDEX, :VAL, :OCATD;
            END
            ELSE
            BEGIN
                IF (PARAM_TYPE = 11 /* FILE */ OR PARAM_TYPE = 12 /* IMAGE */ ) THEN
                BEGIN
                    SELECT BLOB_ID, VAL
                    FROM VALB
                    WHERE PARAM_ID = :PARAM_ID AND OBJ_ID = :OBJ_ID AND IS_DEL = 0
                    INTO :BLOB_ID, :VAL;
                    IS_EXISTS = ROW_COUNT;
                END
                ELSE
                BEGIN
                    SELECT V, IS_EXISTS
                    FROM VAL_GET(:OBJ_ID, :PARAM_ID, 0, :I$USER_ID)
                    INTO :VAL, :IS_EXISTS;
                END
            END

            IF ((V$FILTRED = 0) AND ((I$IS_WRITABLE = 0) OR (I$IS_WRITABLE = 1 AND V$EDIT_TYPE = 1))) THEN
            BEGIN
                SUSPEND;
            END
        END
    END
    ELSE
    BEGIN
        PARAM_ID = -1;
        FOR
            SELECT L.OBJ_ID, L.LINK_ID, L.PARENT_TYPE_ID, L.COST
            FROM LINKS L
            JOIN TYPES T ON T.TYPE_ID = L.OBJ_TYPE_ID AND T.IS_DEL = 0
            JOIN LTYPES LT ON LT.TYPE_ID = L.OBJ_TYPE_ID AND LT.LEVEL_ID = :I$LEVEL_ID AND LT.IS_DEL = 0
            WHERE L.PARENT_ID = :I$OBJ_ID AND L.OBJ_TYPE_ID = :I$TYPE_ID AND L.DATE_DEL IS NULL
            INTO :OBJ_ID, :LINK_ID, :V$PARENT_TYPE_ID, :COST
        DO
        BEGIN
            SELECT CAPTION, IIF(:I$TYPE_ID = 51 AND :V$PARENT_TYPE_ID = 49 AND :COST > 0, :COST, SORT_ORDER), COLOR
            FROM OBJECT_CAPTION_GET(:OBJ_ID, :I$LEVEL_ID, NULL, :I$USER_ID)
            INTO :VAL, :SORT_ORDER, :COLOR;

            IF (I$TYPE_ID = 201) THEN
            BEGIN
                SELECT CAPTION
                FROM OBJECT_CAPTION_GET((SELECT I FROM VAL_GET(:OBJ_ID, 1766,0, :I$USER_ID)), :I$LEVEL_ID, NULL, :I$USER_ID)
                INTO :VAL2;
            END

            /* Потоки в приложении расписание занятий - добавляем к названию предмет и параллель */
            IF(I$TYPE_ID = 347 AND I$LEVEL_ID = 7) THEN
            BEGIN

                SELECT PR.VAL, V376.VAL
                FROM LINKS LP346
                -- Предмет
                JOIN VALR V2705 ON V2705.OBJ_ID = LP346.PARENT_ID AND V2705.PARAM_ID = 2705 AND V2705.IS_DEL = 0
                JOIN VALS V376 ON V376.OBJ_ID = V2705.VAL AND V376.PARAM_ID = 376 AND V376.IS_DEL = 0
                -- Параллель
                JOIN LINKS LP54 ON LP54.OBJ_ID = LP346.PARENT_ID AND LP54.PARENT_TYPE_ID = 54 AND LP54.DATE_DEL IS NULL
                JOIN VALL V381 ON V381.OBJ_ID = LP54.PARENT_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
                JOIN LISTVALS LV ON LV.LISTVAL_ID = V381.LISTVAL_ID
                JOIN RES PR ON PR.RES_ID = LV.RES_ID AND PR.LANG_CODE = 'RU'
                WHERE LP346.OBJ_ID = :OBJ_ID AND LP346.PARENT_TYPE_ID = 346 AND LP346.DATE_DEL IS NULL
                INTO :V$V, :V$V2;

                V$V = REPLACE(V$V, 'параллель', 'классы');
                IF(CHAR_LENGTH(V$V2) > 100) THEN V$V2 = SUBSTRING(V$V2 FROM 1 FOR 100) || '...';

                VAL = V$V || ' - ' || V$V2 || ' - ' || VAL;

            END

            SUSPEND;
        END
    END
    -- Маршрут по виртуальным объектам
    FOR
        SELECT DISTINCT L.OBJ_ID, P.PARAM_ID, P.LIST_ID, P.PARAM_TYPE, V.SORT_ORDER, V.V
        FROM OBJECT_VR_LINKS(:I$LEVEL_ID, :I$OBJ_ID, :I$TYPE_ID) L
        JOIN TYPES T ON T.TYPE_ID = L.OBJ_TYPE_ID AND T.IS_DEL = 0
        JOIN LTYPES LT ON LT.TYPE_ID = L.OBJ_TYPE_ID AND LT.LEVEL_ID = :I$LEVEL_ID AND LT.IS_DEL = 0
        JOIN PARAMS P ON P.TYPE_ID = T.TYPE_ID AND P.IS_DEL = 0
        LEFT JOIN VAL_GET(L.OBJ_ID, P.PARAM_ID, 0, :I$USER_ID) V ON 1 = 1
        ORDER BY V.SORT_ORDER, L.OBJ_ID, P.GRID_ORDER
        INTO :OBJ_ID, :PARAM_ID, :LIST_ID, :PARAM_TYPE, :SORT_ORDER, :VAL
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OBJECT_GROUP_DEL (
    I$OBJ_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT)
AS
DECLARE VARIABLE X BIGINT;
BEGIN
    UPDATE LINKS
    SET DATE_DEL = CURRENT_TIMESTAMP
    WHERE OBJ_ID = :I$OBJ_ID
      AND DATE_DEL IS NULL;

    OBJ_ID = I$OBJ_ID;

    SUSPEND;

    FOR SELECT DISTINCT OBJ_ID
        FROM LINKS
        WHERE PARENT_ID = :I$OBJ_ID
          AND DATE_DEL IS NULL
        INTO :X
    DO
    BEGIN
        FOR SELECT OBJ_ID
            FROM OBJECT_GROUP_DEL(:X)
            INTO :OBJ_ID
        DO
        BEGIN
            SUSPEND;
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OBJECT_IS_PARENT (
    I$PARENT_OBJ_ID BIGINT,
    I$CHILD_OBJ_ID BIGINT)
RETURNS (
    YES_NO SMALLINT)
AS
DECLARE VARIABLE T BIGINT;
BEGIN
    YES_NO = 0;

    SELECT TYPE_ID FROM OBJECTS
    WHERE OBJ_ID = :I$PARENT_OBJ_ID INTO :T;

    SELECT COUNT(*) FROM OBJECT_PARENTS_GET(:I$CHILD_OBJ_ID, :T)
    WHERE OBJ_ID = :I$PARENT_OBJ_ID INTO :YES_NO;

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OBJECT_LISTVALS_LIST (
    I$LIST_ID BIGINT,
    I$USER_ID BIGINT,
    I$PARAM_ID BIGINT = NULL,
    I$LANG_CODE VARCHAR(2) = NULL)
RETURNS (
    LISTVAL_ID BIGINT,
    PARENT_ID BIGINT,
    VAL VARCHAR(4000),
    VAL_LONG VARCHAR(4000),
    TAG VARCHAR(100),
    "FILTER" VARCHAR(255))
AS
DECLARE VARIABLE LANG_CODE VARCHAR(2);
DECLARE VARIABLE RES_ID BIGINT;
BEGIN
    LANG_CODE = :I$LANG_CODE;

    IF (LANG_CODE IS NULL) THEN
    BEGIN
        SELECT LANG_CODE
        FROM USERS
        WHERE USER_ID = :I$USER_ID
        INTO :LANG_CODE;
    END

    FOR
        SELECT LISTVAL_ID,
               PARENT_ID,
               TAG,
               RES_ID,
               "FILTER"
        FROM LISTVALS
        WHERE LIST_ID = :I$LIST_ID
        AND IS_DEL = 0
        AND (:I$PARAM_ID IS NULL OR :I$PARAM_ID NOT IN (1398, 1399)
        -- Группа должностей
         OR (:I$PARAM_ID = 1398 AND PARENT_ID IS NULL)
        -- Подгруппа должностей
         OR (:I$PARAM_ID = 1399 AND LISTVAL_ID IN
                (SELECT PARENT_ID FROM LISTVALS
                 WHERE LIST_ID = :I$LIST_ID
                 AND IS_DEL = 0)))
        ORDER BY SORT_ORDER
        INTO   :LISTVAL_ID,
               :PARENT_ID,
               :TAG,
               :RES_ID,
               :"FILTER"
    DO
    BEGIN
        SELECT VAL,
               VAL_LONG
        FROM RES_GET(:RES_ID, :LANG_CODE)
        INTO :VAL,
             :VAL_LONG;
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OBJECT_LISTVALS_LIST_ROOT (
    I$LIST_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    LISTVAL_ID BIGINT,
    PARENT_ID BIGINT,
    VAL VARCHAR(4000),
    VAL_LONG VARCHAR(4000),
    TAG VARCHAR(100))
AS
DECLARE VARIABLE LANG_CODE VARCHAR(2);
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :LANG_CODE;

    FOR
        SELECT LV.LISTVAL_ID, LV.PARENT_ID, R.VAL, R.VAL_LONG, LV.TAG
        FROM LISTVALS LV
        LEFT JOIN RES_GET(LV.RES_ID,  :LANG_CODE) R ON 1 = 1
        WHERE LV.LIST_ID = :I$LIST_ID AND LV.PARENT_ID IS NULL AND IS_DEL = 0
        ORDER BY SORT_ORDER
        INTO :LISTVAL_ID, :PARENT_ID, :VAL, :VAL_LONG, :TAG
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OBJECT_LISTVALS_LIST_ROOTS (
    I$LIST_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    LISTVAL_ID BIGINT,
    PARENT_ID BIGINT,
    VAL VARCHAR(4000),
    VAL_LONG VARCHAR(4000),
    TAG VARCHAR(100))
AS
DECLARE VARIABLE V$COUNT INTEGER;
DECLARE VARIABLE V$RES_ID BIGINT;
DECLARE VARIABLE V$LANG_CODE VARCHAR(2);
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :V$LANG_CODE;

    FOR
        SELECT LV.LISTVAL_ID, LV.PARENT_ID, LV.TAG, LV.RES_ID
        FROM LISTVALS LV
        WHERE LV.LIST_ID = :I$LIST_ID AND LV.PARENT_ID IS NULL AND LV.IS_DEL = 0
        ORDER BY SORT_ORDER
        INTO :LISTVAL_ID, :PARENT_ID, :TAG, :V$RES_ID
    DO
    BEGIN
        SELECT VAL, VAL_LONG
        FROM RES_GET(:V$RES_ID, :V$LANG_CODE)
        INTO :VAL, :VAL_LONG;

        SUSPEND;

        FOR
            SELECT LV.LISTVAL_ID, LV.PARENT_ID, LV.TAG, LV.RES_ID
            FROM LISTVALS LV
            WHERE LV.LIST_ID = :I$LIST_ID AND LV.PARENT_ID = :LISTVAL_ID AND LV.IS_DEL = 0
            ORDER BY SORT_ORDER
            INTO :LISTVAL_ID, :PARENT_ID, :TAG, :V$RES_ID
        DO
        BEGIN
            SELECT COUNT(*)
            FROM LISTVALS
            WHERE LIST_ID = :I$LIST_ID AND PARENT_ID = :LISTVAL_ID AND IS_DEL = 0
            INTO :V$COUNT;

            IF (V$COUNT > 0) THEN
            BEGIN
                SELECT VAL, VAL_LONG
                FROM RES_GET(:V$RES_ID, :V$LANG_CODE)
                INTO :VAL, :VAL_LONG;

                SUSPEND;
            END
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OBJECT_LISTVALS_UPPROFILE (
    I$LIST_ID BIGINT,
    I$USER_ID BIGINT,
    I$PARAM_ID BIGINT,
    I$OBJ_ID BIGINT)
RETURNS (
    LISTVAL_ID BIGINT,
    PARENT_ID BIGINT,
    VAL VARCHAR(4000),
    VAL_LONG VARCHAR(4000),
    TAG VARCHAR(100),
    "FILTER" VARCHAR(255))
AS
declare variable V$STANDARD bigint;
declare variable V$OK smallint;
begin

  -- Выбираем номер образовательного стандарта
  SELECT FIRST 1 LISTVAL_ID
  FROM VALL
  WHERE OBJ_ID = :I$OBJ_ID AND PARAM_ID IN (2478, 3014) AND IS_DEL = 0
  ORDER BY DATE_MODIFY DESC
  INTO :V$STANDARD;

  IF(V$STANDARD IS NULL) THEN EXCEPTION DATA_ERROR 'Необходимо сначала выбрать образовательный стандарт';

  FOR
      SELECT LISTVAL_ID, PARENT_ID, VAL, VAL_LONG, TAG, "FILTER"
      FROM OBJECT_LISTVALS_LIST(:I$LIST_ID, :I$USER_ID, :I$PARAM_ID)
      INTO :LISTVAL_ID, :PARENT_ID, :VAL, :VAL_LONG, :TAG, :"FILTER"
  DO
  BEGIN
      V$OK = 1;

      IF(V$STANDARD = 11721) THEN
      BEGIN
          -- Ограниченный список вариантов выбора для профиля в ФГОС
          IF(LISTVAL_ID NOT IN (10955, 10951, 10952, 10953, 10954)) THEN V$OK = 0;
      END
      ELSE IF(V$STANDARD IN (14184, 14186)) THEN
      BEGIN
          -- Ограниченный список вариантов выбора для профиля в ФОП
          IF(LISTVAL_ID NOT IN (10955, 14185, 10952, 10953, 10954)) THEN V$OK = 0;
      END

      IF(V$OK = 1) THEN SUSPEND;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OBJECT_MOVE (
    I$OLD_PARENT_ID BIGINT,
    I$PARENT_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$TYPE_ID BIGINT,
    I$REASON_ID BIGINT = NULL,
    I$LISTVAL_ID BIGINT = NULL,
    I$USER_ID BIGINT = NULL,
    I$COST FLOAT = 0,
    I$LEVEL_ID BIGINT = NULL)
RETURNS (
    OBJ_ID BIGINT,
    TYPE_ID BIGINT,
    PARENT_ID BIGINT,
    PARENT_TYPE_ID BIGINT,
    USER_ID BIGINT,
    DATE_INS TIMESTAMP,
    DATE_DEL TIMESTAMP,
    SORT_ORDER DOUBLE PRECISION,
    CAPTION VARCHAR(4000),
    HAS_CHILD INTEGER,
    COLOR INTEGER,
    TAB_ID BIGINT,
    TYPE_ORDER SMALLINT,
    LINK_ID BIGINT)
AS
DECLARE VARIABLE C INTEGER;
BEGIN
    SELECT COUNT(*) FROM LINKS
    WHERE PARENT_ID = :I$PARENT_ID
    AND OBJ_ID = :I$OBJ_ID
    AND DATE_DEL IS NULL
    INTO :C;

    IF (C > 0) THEN EXIT;

    PARENT_ID = I$PARENT_ID;
    OBJ_ID    = I$OBJ_ID;
    TYPE_ID   = I$TYPE_ID;
    USER_ID   = I$USER_ID;
    DATE_INS  = CURRENT_TIMESTAMP;
    DATE_DEL  = NULL;
    HAS_CHILD = NULL;
    TAB_ID    = NULL;

    SELECT COLOR, SORT_ORDER
    FROM TYPES
    WHERE TYPE_ID = :I$TYPE_ID
    INTO   :COLOR, :TYPE_ORDER;

    SELECT CAPTION, SORT_ORDER, COLOR FROM OBJECT_CAPTION_GET(:OBJ_ID, :I$LEVEL_ID)
    INTO :CAPTION, :SORT_ORDER, :COLOR;

    SELECT TYPE_ID
    FROM OBJECTS
    WHERE OBJ_ID = :I$PARENT_ID
    INTO :PARENT_TYPE_ID;

    UPDATE LINKS
    SET DATE_DEL = CURRENT_TIMESTAMP
    WHERE PARENT_ID = :I$OLD_PARENT_ID AND OBJ_ID = :OBJ_ID AND DATE_DEL IS NULL;

    INSERT INTO LINKS (PARENT_ID, OBJ_ID, REASON_ID, DATE_INS, DATE_DEL)
    VALUES (:PARENT_ID, :OBJ_ID, :I$REASON_ID, :DATE_INS, :DATE_DEL)
    RETURNING LINK_ID INTO :LINK_ID;

    HAS_CHILD = 0;

    SELECT COUNT(*)

    FROM LINKS L

    JOIN OBJECTS O
    ON O.OBJ_ID   = L.OBJ_ID

    JOIN TYPES   T
    ON T.TYPE_ID  = O.TYPE_ID

    JOIN LTYPES LT
    ON LT.TYPE_ID = O.TYPE_ID

    LEFT  JOIN OBJECTS J
    ON J.OBJ_ID   = L.PARENT_ID

    LEFT  JOIN PARENTS P
    ON P.TYPE_ID  = J.TYPE_ID
    AND P.CHILD_ID = O.TYPE_ID
    AND P.IS_DEL = 0

    WHERE L.PARENT_ID = :OBJ_ID

    AND LT.LEVEL_ID = :I$LEVEL_ID
    AND LT.IS_DEL = 0
    AND T.IS_DEL = 0
    AND ((LT.SHOW_DEL = 1) OR (L.DATE_DEL IS NULL))
    AND P.TAB_ID IS NULL
    INTO :HAS_CHILD;

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OBJECT_PARAMS (
    I$OBJ_ID BIGINT,
    I$USER_ID BIGINT = 1)
RETURNS (
    PARAM_ID BIGINT,
    PARAM_TYPE SMALLINT,
    PARAM_VAL VARCHAR(4000))
AS
DECLARE VARIABLE V$IS_EXISTS INTEGER;
BEGIN
    FOR
        SELECT P.PARAM_ID, P.PARAM_TYPE
        FROM OBJECTS O
        JOIN PARAMS P ON P.TYPE_ID = O.TYPE_ID AND P.IS_DEL = 0
        WHERE O.OBJ_ID = :I$OBJ_ID
        INTO :PARAM_ID, :PARAM_TYPE
    DO
    BEGIN
        SELECT
            IIF(:PARAM_TYPE IN (6, 12), I, V),
            IS_EXISTS
        FROM VAL_GET(:I$OBJ_ID, :PARAM_ID, 0, :I$USER_ID)
        INTO :PARAM_VAL, :V$IS_EXISTS;
       -- IF (:V$IS_EXISTS > 0 OR :PARAM_ID = 1885) THEN
        IF (:V$IS_EXISTS > 0) THEN
        BEGIN
            SUSPEND;
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OBJECT_PARAMS_LIST (
    I$USER_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$LEVEL_ID BIGINT,
    I$TAB_ID BIGINT = NULL,
    I$TYPE_ID BIGINT = NULL,
    I$EXPORT_MODE SMALLINT = 0,
    I$PARENT_ID BIGINT = NULL,
    I$FROM_IP VARCHAR(200) = NULL)
RETURNS (
    OBJ_ID BIGINT,
    PARAM_ID BIGINT,
    PARAM_TYPE SMALLINT,
    LIST_ID BIGINT,
    LISTVAL_ID BIGINT,
    AUTO_LISTVAL_ID BIGINT,
    BLOB_ID BIGINT,
    IS_REQUIRED SMALLINT,
    IS_HISTORY SMALLINT,
    IS_TREEVIEW SMALLINT,
    PARAM_CAPTION VARCHAR(4000),
    HINT_CAPTION VARCHAR(4000),
    DO_FUNC BIGINT,
    EDIT_MASK VARCHAR(200),
    RUN_SQL VARCHAR(1000),
    IS_AUTO_CREATE SMALLINT,
    TAG VARCHAR(100),
    EDIT_TYPE SMALLINT,
    VAL VARCHAR(4000),
    COST FLOAT,
    REGION VARCHAR(255),
    DISTRICT VARCHAR(255),
    TOWN VARCHAR(255),
    SETTLEMENT VARCHAR(255),
    STREET VARCHAR(255),
    HOUSE VARCHAR(10),
    LITER VARCHAR(10),
    CORP VARCHAR(10),
    FLAT VARCHAR(10),
    POST_INDEX VARCHAR(20),
    OCATD VARCHAR(11),
    HOUSEGUID VARCHAR(36),
    STREETGUID VARCHAR(36),
    BKG_COLOR INTEGER,
    COLOR INTEGER,
    IS_EXISTS SMALLINT,
    LIST_EDIT_TYPE SMALLINT,
    TAB_ID BIGINT,
    DO_CHECK SMALLINT,
    DO_CHECK_EVENT SMALLINT,
    BEGIN_GROUP SMALLINT)
AS
DECLARE VARIABLE V$EXT_OBJ_ID BIGINT;
DECLARE VARIABLE V$EXT_OBJ_TYPE_ID BIGINT;
DECLARE VARIABLE V$TAB_ID BIGINT;
DECLARE VARIABLE V$OU_LICENCE_TYPE VARCHAR(1);
DECLARE VARIABLE V$SIZE_CAPTION VARCHAR(1000);
DECLARE VARIABLE V$TYPE_ID BIGINT = NULL;
DECLARE VARIABLE V$TYPE_USER BIGINT = NULL;
DECLARE VARIABLE V$ROOT_C BIGINT = NULL;
DECLARE VARIABLE V$RES_ID BIGINT;
DECLARE VARIABLE V$SIZE_RES_ID BIGINT;
DECLARE VARIABLE V$HINT_RES_ID BIGINT;
DECLARE VARIABLE V$LANG_CODE CHAR(2) = 'RU';
DECLARE VARIABLE V$READ_ONLY BIGINT;
DECLARE VARIABLE V$FLAG_OU_POST SMALLINT;
DECLARE VARIABLE V$HIDE_FIELD SMALLINT;
DECLARE VARIABLE V$TAB_NAME VARCHAR(1000);
DECLARE VARIABLE V$HAS_ROOT_PARENT SMALLINT;
DECLARE VARIABLE V$FPU_BOOKCODE VARCHAR(40);
DECLARE VARIABLE V$I BIGINT;
BEGIN
    OBJ_ID = I$OBJ_ID;
    V$TAB_ID = NULL;
    V$EXT_OBJ_ID = NULL;

    SELECT STATUS FROM OU_LICENCE_TYPE INTO :V$OU_LICENCE_TYPE;

    IF (I$PARENT_ID IS NULL) THEN
    BEGIN
      SELECT FIRST 1 EXT_OBJ_ID, EXT_OBJ_TYPE_ID
      FROM LINKS
      WHERE OBJ_ID = :I$OBJ_ID AND PARENT_ID IS NULL AND DATE_DEL IS NULL
      INTO :V$EXT_OBJ_ID, :V$EXT_OBJ_TYPE_ID;
    END
    ELSE
    BEGIN
      SELECT FIRST 1 EXT_OBJ_ID, EXT_OBJ_TYPE_ID
      FROM LINKS
      WHERE OBJ_ID = :I$OBJ_ID AND PARENT_ID = :I$PARENT_ID AND DATE_DEL IS NULL
      INTO :V$EXT_OBJ_ID, :V$EXT_OBJ_TYPE_ID;
    END
    IF (I$TYPE_ID IS NULL) THEN
    BEGIN
      SELECT TYPE_ID
      FROM OBJECTS
      WHERE OBJ_ID = :I$OBJ_ID
      INTO :V$TYPE_ID;
    END
    ELSE
    BEGIN
      V$TYPE_ID = I$TYPE_ID;
    END

    SELECT TRIM(LANG_CODE) FROM USERS WHERE USER_ID = :I$USER_ID INTO :V$LANG_CODE;

    -- Логгируем доступ к ПД
    IF(V$TYPE_ID IN (10, 20, 14, 126)) THEN
    INSERT INTO PDA_LOG
    (USER_ID, OBJ_ID, LEVEL_ID, FROM_IP)
    VALUES (:I$USER_ID, :I$OBJ_ID, :I$LEVEL_ID, :I$FROM_IP);

    V$READ_ONLY = 0;
    V$FLAG_OU_POST = 0;
    V$HIDE_FIELD = 0;

    SELECT FIRST 1 L.READ_ONLY, L.ROOT_OBJ_ID
    FROM LUSERS L
    WHERE L.LEVEL_ID = :I$LEVEL_ID AND L.USER_ID = :I$USER_ID
    INTO :V$READ_ONLY, :V$ROOT_C;

    SELECT U.USER_TYPE FROM USERS U WHERE U.USER_ID = :I$USER_ID INTO :V$TYPE_USER;

    SELECT STATUS FROM IS_ROOT_OBJ_PARENT(:I$PARENT_ID, :V$ROOT_C, :I$LEVEL_ID) INTO :V$HAS_ROOT_PARENT;

    -- Для печатных ресурсов проверяем назначение кода учебника из ФПУ
    IF(V$TYPE_ID = 107) THEN
    BEGIN
        SELECT V FROM VAL_GET(:I$OBJ_ID, 2655) INTO :V$FPU_BOOKCODE;
    END

    FOR
        SELECT P.PARAM_ID,
               P.TYPE_ID,
               P.PARAM_TYPE,
               P.LIST_ID,
               P.AUTO_LISTVAL_ID,
               P.IS_REQUIRED,
               P.IS_HISTORY,
               P.IS_TREEVIEW,
               P.RES_ID,
               P.SIZE_RES_ID,
               P.HINT_RES_ID,
               P.DO_FUNC,
               P.EDIT_MASK,
               P.RUN_SQL,
               P.IS_AUTO_CREATE,
               P.TAG,
               L.EDIT_TYPE,
               PT.BKG_COLOR,
               PT.COLOR,
               P.TAB_ID,
               P.DO_CHECK,
               P.DO_CHECK_EVENT,
               P.BEGIN_GROUP
        FROM PARAMS P
        JOIN LPARAMS L ON P.PARAM_ID = L.PARAM_ID
        JOIN PARAMTYPES PT ON PT.PARAM_TYPE = P.PARAM_TYPE
        WHERE P.TYPE_ID = :V$TYPE_ID AND L.LEVEL_ID = :I$LEVEL_ID AND L.IS_DEL = 0 AND P.IS_DEL = 0 AND ((:I$TAB_ID IS NULL) OR (P.TAB_ID = :I$TAB_ID))
        ORDER BY P.GRID_ORDER
        INTO :PARAM_ID,
             :V$TYPE_ID,
             :PARAM_TYPE,
             :LIST_ID,
             :AUTO_LISTVAL_ID,
             :IS_REQUIRED,
             :IS_HISTORY,
             :IS_TREEVIEW,
             :V$RES_ID,
             :V$SIZE_RES_ID,
             :V$HINT_RES_ID,
             :DO_FUNC,
             :EDIT_MASK,
             :RUN_SQL,
             :IS_AUTO_CREATE,
             :TAG,
             :EDIT_TYPE,
             :BKG_COLOR,
             :COLOR,
             :TAB_ID,
             :DO_CHECK,
             :DO_CHECK_EVENT,
             :BEGIN_GROUP
    DO
    BEGIN
        IF (V$TAB_ID IS NULL) THEN V$TAB_ID = TAB_ID;

        LISTVAL_ID = NULL;
        LIST_EDIT_TYPE = -1;
        BLOB_ID = NULL;

        REGION = NULL;
        DISTRICT = NULL;
        TOWN = NULL;
        SETTLEMENT = NULL;
        STREET = NULL;
        HOUSE = NULL;
        CORP = NULL;
        LITER = NULL;
        FLAT = NULL;
        POST_INDEX = NULL;
        VAL = '';
        COST = 0;


        IF (((I$PARENT_ID IS NOT NULL) AND (V$READ_ONLY = 1) AND (EDIT_TYPE > 0)) AND
            (
                ((I$LEVEL_ID <> 50) AND /* AP */ (I$LEVEL_ID <> 305)) OR
                (V$TYPE_USER <> 6) OR
                (V$HAS_ROOT_PARENT = 0)
            )
        ) THEN
        BEGIN
            EDIT_TYPE = 0;
        END

        -- Поля направленности не показываем в разделе общего образования, а код ГИА показываем только там
        -- Поле направленности ДО вообще не показывается нигде ?
        IF (PARAM_ID IN (600, 2463, 2464)) THEN
        BEGIN
            V$I = 0;
            SELECT FIRST 1 LP301.PARENT_ID
            FROM LINKS LP301
            WHERE LP301.OBJ_ID = :I$OBJ_ID AND LP301.PARENT_TYPE_ID = 301 AND LP301.DATE_DEL IS NULL
            INTO :V$I;
            IF(V$I = 32771) THEN
            BEGIN
                -- 32771 -> общее образование
                IF(PARAM_ID IN (2463, 2464)) THEN V$HIDE_FIELD = 1;
            END
            ELSE
            BEGIN
                -- 32771 -> ВД и ДОУ
                IF(PARAM_ID IN (600, 2463)) THEN V$HIDE_FIELD = 1;
                -- Для ДОУ прячем и второй
                IF(V$I = 38699 AND PARAM_ID = 2463) THEN V$HIDE_FIELD = 1;
            END
        END

        IF (TAG = 'DOU_GROUP_DIRECTION' AND EDIT_TYPE = 1) THEN
        BEGIN
            IF ((SELECT LISTVAL_ID FROM VALL WHERE OBJ_ID = :I$OBJ_ID AND PARAM_ID = 1549 AND IS_DEL = 0) IN (3265,3268)) THEN
            BEGIN
                EDIT_TYPE = 0;
                V$HIDE_FIELD = 1;
            END
            ELSE IF ((SELECT LISTVAL_ID FROM VALL WHERE OBJ_ID = :I$OBJ_ID AND PARAM_ID = 1549 AND IS_DEL = 0) IN (3266,3267)) THEN
            BEGIN
                EDIT_TYPE = 1;
            END
        END

        IF (PARAM_ID = 2521 AND EDIT_TYPE = 1 AND (SELECT V FROM VAL_GET(:I$OBJ_ID, 1468)) <> 'Да') THEN
        BEGIN
            EDIT_TYPE = 0;
        END

        IF (PARAM_TYPE = 11 /* FILE */ OR PARAM_TYPE = 12 /* IMAGE */ ) THEN
        BEGIN
            SELECT BLOB_ID, VAL
            FROM VALB
            WHERE PARAM_ID = :PARAM_ID AND OBJ_ID = :I$OBJ_ID AND IS_DEL = 0
            INTO :BLOB_ID, :VAL;
        END
        ELSE
        IF (PARAM_TYPE IN (6 /* LIST_VALUE */, 7 /* STRING_OR_LIST_VALUE */, 20 /*STRING_OR_LIST_VALUE_RO*/ )) THEN
        BEGIN
            SELECT V, I, IS_EXISTS, COST
            FROM VAL_GET(:I$OBJ_ID, :PARAM_ID, 0, :I$USER_ID)
            INTO :VAL, :LISTVAL_ID, :IS_EXISTS, :COST;

            SELECT L.EDIT_TYPE
            FROM LLISTS L
            WHERE L.LEVEL_ID = :I$LEVEL_ID AND L.LIST_ID = :LIST_ID AND L.IS_DEL = 0
            INTO :LIST_EDIT_TYPE;

            IF (PARAM_ID = 58 AND V$OU_LICENCE_TYPE IN ('O', 'C')) THEN
            BEGIN
                /* for teacher the param "stavok" not visible */
                SELECT FIRST 1 1
                FROM LISTVALS LV
                WHERE LV.LISTVAL_ID = :LISTVAL_ID AND LV.TAG = 'U' AND LV.PARENT_ID = 98
                INTO :V$FLAG_OU_POST;
            END
        END
        ELSE
        IF (PARAM_TYPE = 17 OR PARAM_TYPE = 19) THEN
        BEGIN
            SELECT VAL
            FROM DO_FUNC(:I$OBJ_ID, :PARAM_ID, :DO_FUNC, :AUTO_LISTVAL_ID, :I$USER_ID, :I$PARENT_ID)
            INTO :VAL;
        END
        ELSE
        IF (PARAM_TYPE = 18 /* ADDRESS */ ) THEN
        BEGIN
            SELECT REGION, DISTRICT, TOWN, SETTLEMENT, STREET, HOUSE, LITER, CORP, FLAT, POST_INDEX, VAL, OCATD, HOUSEGUID, STREETGUID, RAW_TEXT
            FROM ADR_GET(:PARAM_ID, :I$OBJ_ID, 0)
            INTO :REGION, :DISTRICT, :TOWN, :SETTLEMENT, :STREET, :HOUSE, :LITER, :CORP, :FLAT, :POST_INDEX, :VAL, :OCATD, :HOUSEGUID, :STREETGUID, :V$TAB_NAME;

            -- Липовое значение для сохранения некодифицированных данных
            IF(REGION = '*') THEN VAL = V$TAB_NAME;
        END
        ELSE
        BEGIN
            SELECT V, I, IS_EXISTS
            FROM VAL_GET(:I$OBJ_ID, :PARAM_ID, 0, :I$USER_ID)
            INTO :VAL, :LISTVAL_ID, :IS_EXISTS;
        END

        SELECT VAL FROM RES_GET(:V$RES_ID, :V$LANG_CODE) INTO :PARAM_CAPTION;
        SELECT VAL FROM RES_GET(:V$SIZE_RES_ID, :V$LANG_CODE) INTO :V$SIZE_CAPTION;

        IF (V$SIZE_CAPTION > '') THEN
        BEGIN
            PARAM_CAPTION = PARAM_CAPTION || ' (' || V$SIZE_CAPTION || ')';
        END

        SELECT VAL FROM RES_GET(:V$HINT_RES_ID, :V$LANG_CODE) INTO :HINT_CAPTION;

        -- В колледжах меняем подпись
        IF (PARAM_ID = 1362 AND V$OU_LICENCE_TYPE = 'C') THEN PARAM_CAPTION = 'Наличие участников ГИА';
        IF (PARAM_ID = 1590 AND V$OU_LICENCE_TYPE = 'C') THEN PARAM_CAPTION = 'Группа';

        -- Для ЦОПП выключаем лишние поля в обычных группах
        IF (PARAM_ID = 3063 AND (LISTVAL_ID IS NULL OR LISTVAL_ID = 3)) THEN V$FLAG_OU_POST = 1;

        /* Для печатных изданий делает READONLY поля, если назначен код ФПУ */
        IF(V$TYPE_ID = 107) THEN
        BEGIN
            IF((V$FPU_BOOKCODE IS NOT NULL) AND (V$FPU_BOOKCODE <> '')) THEN
            BEGIN
                IF(PARAM_ID NOT IN (646, 648, 650, 653, 654, 2655, 2658)) THEN EDIT_TYPE = 0;
            END
        END
        /* Для Объединений-Групп показываем поля ОП и направленности согласно #1564, также показываем для ДПО */
        IF(V$TYPE_ID = 46 AND PARAM_ID IN (2823, 2824, 2825)) THEN
        BEGIN
            SELECT V1579.LISTVAL_ID
            FROM LINKS LP86
            JOIN VALL V1579 ON V1579.OBJ_ID = LP86.PARENT_ID AND V1579.PARAM_ID = 1579 AND V1579.IS_DEL = 0
            WHERE LP86.OBJ_ID = :I$OBJ_ID AND LP86.PARENT_TYPE_ID = 86 AND LP86.DATE_DEL IS NULL
            INTO :V$I;
            IF(V$I NOT IN (3315, 3316) AND V$OU_LICENCE_TYPE <> 'P') THEN V$HIDE_FIELD = 1;
        END
        /* Для предметов показываем признак элективного курса только для общего образования */
        IF(V$TYPE_ID = 51 AND PARAM_ID = 2816) THEN
        BEGIN
            V$I = 0;
            SELECT V2461.LISTVAL_ID
            FROM LINKS LP301
            JOIN VALL V2461 ON V2461.OBJ_ID = LP301.PARENT_ID AND V2461.PARAM_ID = 2461 AND V2461.IS_DEL = 0
            WHERE LP301.OBJ_ID = :I$OBJ_ID AND LP301.PARENT_TYPE_ID = 301 AND LP301.DATE_DEL IS NULL
            INTO :V$I;
            IF(V$I = 11710) THEN V$HIDE_FIELD = 1;
        END
        /* Для ОП дополнительного образования прячем лишние поля */
        IF(V$TYPE_ID = 57 AND PARAM_ID IN (1891, 2479, 2480, 2481)) THEN
        BEGIN
            V$I = 0;
            SELECT V2450.LISTVAL_ID
            FROM LINKS LP69
            JOIN VALL V2450 ON V2450.OBJ_ID = LP69.PARENT_ID AND V2450.PARAM_ID = 2450 AND V2450.IS_DEL = 0
            WHERE LP69.OBJ_ID = :I$OBJ_ID AND LP69.PARENT_TYPE_ID = 69 AND LP69.DATE_DEL IS NULL
            INTO :V$I;
            IF(V$I = 11386) THEN V$HIDE_FIELD = 1;
        END
        /* Запрет изменения вида ОП при наличии добавленных в нее этапов УП */
        IF ((V$TYPE_ID = 57) AND (PARAM_ID = 1832) AND EXISTS(
          SELECT FIRST 1 1
          FROM LINKS L50
          WHERE L50.OBJ_TYPE_ID IN (50, 400) AND L50.PARENT_ID = :I$OBJ_ID AND L50.DATE_DEL IS NULL))
        THEN
          EDIT_TYPE = 0;
        /* Запрет изменения вида типа образования в ОП(-ах) при наличии добавленных ОП */
        IF ((V$TYPE_ID = 69) AND (PARAM_ID = 2450) AND EXISTS(
          SELECT FIRST(1) 1
          FROM LINKS L57
          WHERE L57.OBJ_TYPE_ID = 57 AND L57.PARENT_ID = :I$OBJ_ID AND L57.DATE_DEL IS NULL))
        THEN
          EDIT_TYPE = 0;
        /* Запрет изменения связи с ОП при наличии учеников */
        IF ((V$TYPE_ID = 46) AND (PARAM_ID = 2832) AND EXISTS(
          SELECT FIRST 1 1
          FROM LINKS L10
          WHERE L10.OBJ_TYPE_ID = 10 AND L10.PARENT_ID = :I$OBJ_ID AND L10.DATE_DEL IS NULL))
        THEN
          EDIT_TYPE = 0;

        IF ((PARAM_ID = 2164) AND NOT EXISTS(
            SELECT FIRST 1 1
            FROM LINKS LP77
            WHERE LP77.OBJ_ID = :I$PARENT_ID AND LP77.PARENT_TYPE_ID = 77 AND LP77.DATE_DEL IS NULL
        )) THEN
        BEGIN
            EDIT_TYPE = 0;
        END

        IF ((V$OU_LICENCE_TYPE = 'C') AND (PARAM_ID IN (2726, 2727) AND EXISTS(
            SELECT FIRST 1 1
            FROM VALL V2725
            WHERE V2725.OBJ_ID = :I$OBJ_ID AND V2725.PARAM_ID = 2725 AND V2725.LISTVAL_ID = 3
        ))) THEN
        BEGIN
            EDIT_TYPE = 0;
        END

        IF ((V$OU_LICENCE_TYPE = 'C') AND (PARAM_ID IN (2723, 2724) AND EXISTS(
            SELECT FIRST 1 1
            FROM VALL V2722
            WHERE V2722.OBJ_ID = :I$OBJ_ID AND V2722.PARAM_ID = 2722 AND V2722.LISTVAL_ID = 3
        ))) THEN
        BEGIN
            EDIT_TYPE = 0;
        END

        IF(V$OU_LICENCE_TYPE = 'P') THEN
        BEGIN
            IF(PARAM_ID = 502) THEN PARAM_CAPTION = 'Количество мест слушателей (проектное)';
            ELSE IF(PARAM_ID = 503) THEN PARAM_CAPTION = 'Количество мест слушателей (нормативное)';
            ELSE IF(PARAM_ID = 399) THEN BEGIN PARAM_CAPTION = 'Срок освоения'; HINT_CAPTION = 'часов'; END
        END

        -- Заканчивает обучение - только для ДОУ и СПО
        -- для ДОУ меняем название на просто заканчиваем обучение
        IF (PARAM_ID = 3344) THEN
        BEGIN
            SELECT FIRST 1 V43.LISTVAL_ID
            FROM LINKS LP8
            JOIN LINKS LP7 ON LP7.OBJ_ID = LP8.PARENT_ID AND LP7.PARENT_TYPE_ID = 7 AND LP7.DATE_DEL IS NULL
            JOIN VALL V43 ON V43.OBJ_ID = LP7.PARENT_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0
            WHERE LP8.OBJ_ID = :I$OBJ_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
            INTO :V$I;

            IF(V$I NOT IN (3263, 3264, 29)) THEN V$HIDE_FIELD = 1;
            ELSE IF(V$I IN (3263, 3264)) THEN PARAM_CAPTION = 'Заканчивает обучение';
        END
        -- Прячем лишние поля в мультипараграфе
        IF(V$OU_LICENCE_TYPE = 'S') THEN
        BEGIN
          -- Для класса экстерната
          IF (V$TYPE_ID = 187 AND PARAM_ID IN (2388, 1363, /**/ 1612, 1613, 1614, 1615, 1617, /**/ 1742, 1743, 1744, 1745, 1746) AND V$I NOT IN (22, 26, 27, 29)) THEN
            V$HIDE_FIELD = 1;

          --Определяем поля класса для отображения по уровню образования
          V$I = NULL;
          SELECT FIRST 1 V43.LISTVAL_ID
          FROM LINKS LP8
          JOIN LINKS LP7 ON LP7.OBJ_ID = LP8.PARENT_ID AND LP7.PARENT_TYPE_ID = 7 AND LP7.DATE_DEL IS NULL
          JOIN VALL V43 ON V43.OBJ_ID = LP7.PARENT_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0
          WHERE LP8.OBJ_ID = :I$OBJ_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
          INTO :V$I;

          -- Для класса и будущего класса в мультипараграфе прячем лишние поля
          IF (V$TYPE_ID IN (9, 403)) THEN
            IF((V$I IN (3263,3264) AND PARAM_ID NOT IN (54,551,552,555,557,558,584,585,586,1549,1550,1558,1655,3026,3027,3053,3075)) OR
               (V$I IN (22,26,27) AND PARAM_ID NOT IN (53,54,551,552,553,554,555,556,557,558,584,585,586,591,592,706,1338,1363,1612,1613,1614,1615,1617,2388,2998,3024,3026,3027,3028,3052,3053,3114,3117,3118,3336,3359,3517)) OR
               (V$I = 29 AND PARAM_ID NOT IN (53,54,551,552,553,555,584,585,586,1363,1612,1613,1614,1615,1767,1768,1831,2165,2388,2821,2822,3026,3027,3028,3053,3063,3071,3072,3073,3075,3344,3353,3367,3381,3382,3383,3384,3477))
               )THEN
              V$HIDE_FIELD = 1;
        END
        IF (V$OU_LICENCE_TYPE = 'S' AND V$TYPE_ID = 10) THEN
        BEGIN
          SELECT FIRST 1 V43.LISTVAL_ID
          FROM LINKS LP9
          JOIN LINKS LP8 ON LP8.OBJ_ID = LP9.PARENT_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
          JOIN LINKS LP7 ON LP7.OBJ_ID = LP8.PARENT_ID AND LP7.PARENT_TYPE_ID = 7 AND LP7.DATE_DEL IS NULL
          JOIN VALL V43 ON V43.OBJ_ID = LP7.PARENT_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0
          WHERE LP9.OBJ_ID = :I$OBJ_ID AND LP9.PARENT_TYPE_ID IN (9, 187) AND LP9.DATE_DEL IS NULL
          INTO :V$I;

          -- Для обучающегося прячем лишние поля в мультипараграфе
          IF ((V$I IN (3263,3264) AND PARAM_ID IN (86,90,104,106,107,117,126,160,161,162,163,164,165,182,183,187,188,189,226,228,229,1340,1345,1374,1375,1377,1378,1620, 1622, 1624, 1625,1812,1830,2085,2139,2154,2155,2161,2164,
            2169,2340,2456,2546,2738,2842,2843,2456,2546,2738,2842,2843,2844,2845,2846,2854,2899,2991,3054,3060,3076,3109,3116,3140,3170,3171,3172,3173,3174,3175,3176,3304,3328,3337,3338,3339,3340,3341,3342,3354,3358,3360,3380,
            3424,3479,3593,3594)) OR
          (V$I = 22 AND PARAM_ID IN (100,229,1340,1374,1375,1377,1378,1554,1555,1581,1582,1642,1830,1812,2139,2158,2161,2164,2340,2738,3001,3023,3054,3140,3170,3171,3172,3173,3174,3175,3176,3328,3337,3338,3339,3340,3341,3342,
            3360,3380,3424)) OR
          (V$I = 26 AND PARAM_ID IN (100,229,1554,1555,1581,1582,1642,1830,1812,2139,2158,2161,2164,2340,2738,3001,3023,3054,3140,3170,3171,3172,3173,3174,3175,3176,3328,3337,3338,3339,3340,3341,3342,3360,3380,3424)) OR
          (V$I = 27 AND PARAM_ID IN (100,1554,1555,1581,1582,1642,1830,1812,2139,2158,2161,2164,2340,2738,3001,3023,3054,3140,3170,3171,3172,3173,3174,3175,3176,3328,3337,3338,3339,3340,3341,3342,3360,3380,3424)) OR
          (V$I = 29 AND PARAM_ID IN (86,126,159,162,163,164,165,182,187,189,206,207,222,223,229,232,1345,1346,1554,1555,1581,1582,1642,2085,2158,2169,2443,2456,2546,2842,2843,2844,2845,2846,2854,2899,3000,3001,3023,3109,
            3304,3354,3479,3593,3594))) THEN
            V$HIDE_FIELD = 1;
        END
        /* хак для скрытия неугодных полей, с разной видимостью в рамках одной задачи */
        IF ((V$OU_LICENCE_TYPE IN ('O', 'S') AND I$EXPORT_MODE = 0 AND PARAM_ID IN (2545, 3022)) AND
            NOT(EXISTS(
                SELECT FIRST 1 1
                FROM LINKS LP57
                JOIN LINKS LP69 ON LP69.OBJ_ID = LP57.PARENT_ID AND LP69.PARENT_TYPE_ID = 69 AND LP69.DATE_DEL IS NULL
                JOIN VALL VL ON VL.OBJ_ID = LP69.PARENT_ID AND VL.PARAM_ID = 2450 AND VL.IS_DEL = 0 AND VL.LISTVAL_ID = 11385
                WHERE LP57.OBJ_ID = :I$OBJ_ID AND LP57.PARENT_TYPE_ID = 57 AND LP57.DATE_DEL IS NULL
            ))) THEN
        BEGIN
            V$FLAG_OU_POST = 0;
        END
        ELSE IF (V$TYPE_ID = 10 AND PARAM_ID IN (105,106,107,188,161,1346,226) AND EXISTS(
            SELECT FIRST 1 1
            FROM LINKS LP77
            WHERE LP77.OBJ_ID = :I$PARENT_ID AND LP77.PARENT_TYPE_ID = 77 AND LP77.DATE_DEL IS NULL
        )) THEN
        BEGIN
            V$FLAG_OU_POST = 0;     
        END
        ELSE IF (V$OU_LICENCE_TYPE IN ('O', 'C', 'S') AND I$EXPORT_MODE = 0 AND V$TYPE_ID = 10 AND PARAM_ID = 2154 AND
            (EXISTS(
                SELECT FIRST 1 1
                FROM LINKS LP9
                JOIN LINKS LP8 ON LP8.OBJ_ID = LP9.PARENT_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
                JOIN VALL VL ON VL.OBJ_ID = LP8.PARENT_ID AND VL.PARAM_ID = 49 AND VL.IS_DEL = 0 AND VL.LISTVAL_ID IN (37,38,39,40,41,42,43,44,45,46)
                WHERE LP9.OBJ_ID = :I$OBJ_ID AND LP9.PARENT_TYPE_ID = 9 AND LP9.DATE_DEL IS NULL
            ))) THEN
        BEGIN
            V$FLAG_OU_POST = 0;
        END
        ELSE IF (V$OU_LICENCE_TYPE IN ('O', 'C', 'S') AND I$EXPORT_MODE = 0 AND V$TYPE_ID = 10 AND PARAM_ID = 2155 AND
            (EXISTS(
                SELECT FIRST 1 1
                FROM LINKS LP9
                JOIN LINKS LP8 ON LP8.OBJ_ID = LP9.PARENT_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
                JOIN VALL VL ON VL.OBJ_ID = LP8.PARENT_ID AND VL.PARAM_ID = 49 AND VL.IS_DEL = 0 AND VL.LISTVAL_ID IN (37,38,39,40,41,42,43,44,46)
                WHERE LP9.OBJ_ID = :I$OBJ_ID AND LP9.PARENT_TYPE_ID = 9 AND LP9.DATE_DEL IS NULL
            ))) THEN
        BEGIN
            V$FLAG_OU_POST = 0;
        END
        -- Настроечные параметры для ГИА
        -- Сбрасываем обратно флаг для ЦОПП
        ELSE IF (V$OU_LICENCE_TYPE IN ('O', 'C', 'S') AND I$EXPORT_MODE = 0 AND V$TYPE_ID IN (9, 187) AND PARAM_ID IN (1612, 1613, 1614, 1615, 1617, /**/ 1742, 1743, 1744, 1745, 1746) AND
            (EXISTS(
                SELECT FIRST 1 1
                FROM LINKS LP8
                JOIN VALL VL ON VL.OBJ_ID = LP8.PARENT_ID AND VL.PARAM_ID = 49 AND VL.IS_DEL = 0 AND VL.LISTVAL_ID IN (37,38,39,40,41,42,43,44)
                WHERE LP8.OBJ_ID = :I$OBJ_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
            ))) THEN
        BEGIN
            V$FLAG_OU_POST = 0;
        END
        ELSE IF (V$OU_LICENCE_TYPE IN ('O', 'C', 'S') AND I$EXPORT_MODE = 0 AND V$TYPE_ID = 10 AND PARAM_ID IN (1620, 1622, 1624, 1625) AND
            (EXISTS(
                SELECT FIRST 1 1
                FROM LINKS LP9
                JOIN LINKS LP8 ON LP8.OBJ_ID = LP9.PARENT_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
                JOIN VALL VL ON VL.OBJ_ID = LP8.PARENT_ID AND VL.PARAM_ID = 49 AND VL.IS_DEL = 0 AND VL.LISTVAL_ID IN (37,38,39,40,41,42,43,44)
                WHERE LP9.OBJ_ID = :I$OBJ_ID AND LP9.PARENT_TYPE_ID IN (9, 187) AND LP9.DATE_DEL IS NULL
            ))) THEN
        BEGIN
            V$FLAG_OU_POST = 0;
        END
        ELSE IF (V$OU_LICENCE_TYPE IN ('O', 'C', 'S') AND V$FLAG_OU_POST = 1 AND PARAM_ID = 62 AND I$EXPORT_MODE = 0) THEN
        BEGIN
            /* Скрываем поле количества ставок для учительских должностей, но флаг не сбрасываем ! */
        END
        ELSE IF(PARAM_ID IN (3071, 3072) AND V$FLAG_OU_POST = 1) THEN
        BEGIN
            -- Даты для групп ЦОПП только когда это именно ЦОПП
        END
        ELSE IF (PARAM_ID IN (2166, 3112) AND
            NOT EXISTS(
                SELECT FIRST 1 1
                FROM LINKS L50
                JOIN VALL V1832 ON V1832.OBJ_ID = L50.PARENT_ID AND V1832.PARAM_ID = 1832 AND V1832.IS_DEL = 0 AND V1832.LISTVAL_ID = 5344
                WHERE L50.OBJ_ID = :I$OBJ_ID AND L50.DATE_DEL IS NULL AND L50.PARENT_TYPE_ID = 57
            ) AND NOT EXISTS(
                SELECT FIRST 1 1
                FROM LINKS LP55
                WHERE LP55.OBJ_ID = :I$OBJ_ID AND LP55.PARENT_TYPE_ID = 55 AND LP55.DATE_DEL IS NULL
            )) THEN
        BEGIN
            /* поле "Профиль " для объекта учебный план должно отображаться только для планов, относящихся к образовательной программе,
               которая имеет вид = "основная образовательная программа среднего общего образования" */
        END
        /*ELSE IF (PARAM_ID = 2720 AND
            NOT EXISTS(
                SELECT FIRST 1 1
                FROM VALL V372
                WHERE V372.OBJ_ID = :I$OBJ_ID
                AND V372.PARAM_ID = 372
                AND V372.IS_DEL = 0
                AND V372.LISTVAL_ID = 780
            )) THEN
        BEGIN
            /* поле "Учтены изменения в названиях предметов" для объекта учебный компонент должно отображаться только для федерального учебного компонента */
            /*V$FLAG_OU_POST = 0;
        END*/
        -- Скрываем поля зачисления в новое ОУ для учащихся, которые ещё числятся в классах - выключили
        /*ELSE IF (PARAM_ID IN (2442, 2443) AND
            EXISTS(
                SELECT FIRST 1 1
                FROM LINKS
                WHERE OBJ_ID = :I$PARENT_ID AND DATE_DEL IS NULL AND PARENT_TYPE_ID IN (8)
            )) THEN
        BEGIN
        END*/
        -- Поле даты окончания регистрации показываем только если указана временная регистрация
        ELSE IF (PARAM_ID IN (1347, 2835) AND
            NOT EXISTS(
                SELECT FIRST 1 1
                FROM VALL
                WHERE OBJ_ID = :I$OBJ_ID AND IS_DEL = 0 AND PARAM_ID IN (108, 2836) AND LISTVAL_ID = 1218
            )) THEN
        BEGIN
        END
        -- Поле количества ставок в должности показываем только для не-педагогических должностей
        --ELSE IF(V$OU_LICENCE_TYPE IN ('O', 'C') AND PARAM_ID IN (2850, 2851) AND V$FLAG_OU_POST = 1) THEN
        --BEGIN
        --END
        -- Год обучения и состав - только в классах ОВЗ
        ELSE IF(PARAM_ID IN (554, 3024, 3114) AND NOT EXISTS(SELECT FIRST 1 1 FROM VALL V592 WHERE V592.OBJ_ID = :I$OBJ_ID AND V592.PARAM_ID IN (592, 3117) AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 13275)) THEN
        BEGIN
        END
        -- Коды специальностей СПО для коллективов показываем только в положенных каталогах
        ELSE IF (PARAM_ID IN (2165, 2821, 3381, 3382) AND EXISTS(
          SELECT FIRST 1 1
          FROM LINKS LP7
          JOIN VALL V43 ON V43.OBJ_ID = LP7.PARENT_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0 AND V43.LISTVAL_ID = 13131
          WHERE LP7.OBJ_ID = :I$PARENT_ID AND LP7.PARENT_TYPE_ID = 7 AND LP7.DATE_DEL IS NULL
        )) THEN
        BEGIN
        END
        -- Аналогично для кодов профессий по ОКПДТР
        ELSE IF (PARAM_ID IN (3367, 3383) AND EXISTS(
          SELECT FIRST 1 1
          FROM LINKS LP7
          JOIN VALL V43 ON V43.OBJ_ID = LP7.PARENT_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0 AND V43.LISTVAL_ID = 29
          WHERE LP7.OBJ_ID = :I$PARENT_ID AND LP7.PARENT_TYPE_ID = 7 AND LP7.DATE_DEL IS NULL
        )) THEN
        BEGIN
        END
        -- То же самое фильтр полей для ОП СПО
        ELSE IF (PARAM_ID IN (1753, 2460) AND EXISTS(
          SELECT FIRST 1 1
          FROM LINKS LP69
          JOIN VALL V2450 ON V2450.OBJ_ID = LP69.PARENT_ID AND V2450.PARAM_ID = 2450 AND V2450.IS_DEL = 0 AND V2450.LISTVAL_ID = 11388
          WHERE LP69.OBJ_ID = :I$PARENT_ID AND LP69.PARENT_TYPE_ID = 69 AND LP69.DATE_DEL IS NULL
        )) THEN
        BEGIN
        END
        ELSE IF (PARAM_ID IN (69) AND EXISTS(
          SELECT FIRST 1 1
          FROM LINKS LP69
          JOIN VALL V2450 ON V2450.OBJ_ID = LP69.PARENT_ID AND V2450.PARAM_ID = 2450 AND V2450.IS_DEL = 0 AND V2450.LISTVAL_ID = 11387
          WHERE LP69.OBJ_ID = :I$PARENT_ID AND LP69.PARENT_TYPE_ID = 69 AND LP69.DATE_DEL IS NULL
        )) THEN
        BEGIN
        END
        ELSE IF (V$HIDE_FIELD = 1) THEN
        BEGIN
            V$HIDE_FIELD = 0;
        END
        ELSE
        BEGIN
            SUSPEND;
        END
    END
    IF (V$EXT_OBJ_ID IS NOT NULL) THEN
    BEGIN
        SELECT R.VAL
        FROM TABS T
        LEFT JOIN RES_GET(T.RES_ID, :V$LANG_CODE) R ON 1=1
        WHERE T.TAB_ID = :I$TAB_ID AND T.IS_DEL = 0
        INTO :V$TAB_NAME;

        IF (I$TAB_ID < 0) THEN
        BEGIN
            V$TAB_ID = I$TAB_ID;
        END
        ELSE
        BEGIN
            V$TAB_ID = NULL;
        END

        SELECT T.TAB_ID
        FROM TABS T
        LEFT JOIN RES_GET(T.RES_ID, :V$LANG_CODE) R ON 1=1
        WHERE T.TYPE_ID = :V$EXT_OBJ_TYPE_ID AND T.IS_DEL = 0 AND R.VAL LIKE :V$TAB_NAME
        INTO :V$TAB_ID;

        IF ((V$TAB_ID IS NOT NULL) OR (I$TAB_ID IS NULL)) THEN
        BEGIN
            OBJ_ID = V$EXT_OBJ_ID;
            FOR
                SELECT PARAM_ID,
                       PARAM_TYPE,
                       LIST_ID,
                       LISTVAL_ID,
                       AUTO_LISTVAL_ID,
                       BLOB_ID,
                       IS_REQUIRED,
                       IS_HISTORY,
                       IS_TREEVIEW,
                       PARAM_CAPTION,
                       HINT_CAPTION,
                       DO_FUNC,
                       EDIT_MASK,
                       RUN_SQL,
                       IS_AUTO_CREATE,
                       TAG,
                       EDIT_TYPE,
                       VAL,
                       COST,
                       REGION,
                       DISTRICT,
                       TOWN,
                       SETTLEMENT,
                       STREET,
                       HOUSE,
                       LITER,
                       CORP,
                       FLAT,
                       POST_INDEX,
                       BKG_COLOR,
                       COLOR,
                       IS_EXISTS,
                       LIST_EDIT_TYPE,
                       :V$TAB_ID,
                       DO_CHECK,
                       DO_CHECK_EVENT
                FROM OBJECT_PARAMS_LIST(:I$USER_ID, :V$EXT_OBJ_ID, :I$LEVEL_ID, :V$TAB_ID)
                INTO :PARAM_ID,
                     :PARAM_TYPE,
                     :LIST_ID,
                     :LISTVAL_ID,
                     :AUTO_LISTVAL_ID,
                     :BLOB_ID,
                     :IS_REQUIRED,
                     :IS_HISTORY,
                     :IS_TREEVIEW,
                     :PARAM_CAPTION,
                     :HINT_CAPTION,
                     :DO_FUNC,
                     :EDIT_MASK,
                     :RUN_SQL,
                     :IS_AUTO_CREATE,
                     :TAG,
                     :EDIT_TYPE,
                     :VAL,
                     :COST,
                     :REGION,
                     :DISTRICT,
                     :TOWN,
                     :SETTLEMENT,
                     :STREET,
                     :HOUSE,
                     :LITER,
                     :CORP,
                     :FLAT,
                     :POST_INDEX,
                     :BKG_COLOR,
                     :COLOR,
                     :IS_EXISTS,
                     :LIST_EDIT_TYPE,
                     :TAB_ID,
                     :DO_CHECK,
                     :DO_CHECK_EVENT
            DO
            BEGIN
                IF (((I$PARENT_ID IS NOT NULL) AND (V$READ_ONLY = 1) AND (EDIT_TYPE > 0)) AND
                    (
                        ((I$LEVEL_ID <> 50) AND /* AP */ (I$LEVEL_ID <> 305)) OR
                        (V$TYPE_USER <> 6) OR
                        (V$HAS_ROOT_PARENT = 0)
                    )
                ) THEN
                BEGIN
                    EDIT_TYPE = 0;
                END

                SUSPEND;
            END
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OBJECT_PARAM_USER_GET (
    I$OBJ_ID BIGINT,
    I$PARAM_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    FIO VARCHAR(4000))
AS
BEGIN
    FIO = NULL;
    SELECT FIRST_NAME || ' ' || MIDDLE_NAME || ' ' || LAST_NAME
    FROM VAL_GET(:I$OBJ_ID, :I$PARAM_ID, 0, :I$USER_ID) V
    JOIN USERS U ON U.USER_ID = V.USER_ID
    INTO :FIO;
    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OBJECT_PARENTS_GET (
    I$OBJ_ID BIGINT,
    I$PARENT_TYPE_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable T bigint;
declare variable X bigint;
BEGIN
  SELECT TYPE_ID
  FROM OBJECTS
  WHERE OBJ_ID = :I$OBJ_ID
  INTO :T;

  IF (T = I$PARENT_TYPE_ID OR I$PARENT_TYPE_ID = -1) THEN
  BEGIN
    OBJ_ID = I$OBJ_ID;
    SUSPEND;
  END

  FOR
    SELECT PARENT_ID
    FROM LINKS
    WHERE OBJ_ID = :I$OBJ_ID AND DATE_DEL IS NULL
    INTO :X
  DO
  BEGIN
    FOR
      SELECT OBJ_ID
      FROM OBJECT_PARENTS_GET(:X, :I$PARENT_TYPE_ID)
      INTO :OBJ_ID
    DO
    BEGIN
      SUSPEND;
    END
  END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OBJECT_RESTORE_LAST_LINK (
    I$PARENT_ID BIGINT,
    I$OBJ_ID BIGINT)
RETURNS (
    LINK_ID BIGINT)
AS
BEGIN
    SELECT FIRST 1 L.LINK_ID
    FROM LINKS L
    WHERE L.PARENT_ID = :I$PARENT_ID
      AND L.OBJ_ID = :I$OBJ_ID
      AND L.DATE_DEL IS NOT NULL
    ORDER BY L.DATE_DEL DESC
    INTO :LINK_ID;

    UPDATE LINKS
    SET DATE_DEL = NULL
    WHERE LINK_ID = :LINK_ID;

    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OBJECT_ROOT_OBJECT (
    I$TYPE_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    CAPTION VARCHAR(4000))
AS
BEGIN
    SELECT FIRST 1 OBJ_ID
    FROM  LINKS
    WHERE PARENT_ID IS NULL
    AND   DATE_DEL  IS NULL
    AND   OBJ_TYPE_ID = :I$TYPE_ID
    INTO :OBJ_ID;

    SELECT CAPTION FROM OBJECT_CAPTION_GET(:OBJ_ID) INTO :CAPTION;

    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OBJECT_STATE_LIST (
    I$STATE_MASK VARCHAR(100) = NULL)
RETURNS (
    LISTVAL_ID BIGINT,
    LIST_ID BIGINT,
    PARENT_ID BIGINT,
    VAL VARCHAR(4000),
    VAL_LONG VARCHAR(4000),
    TAG VARCHAR(100),
    "FILTER" VARCHAR(255),
    SORT_ORDER SMALLINT,
    COST FLOAT)
AS
BEGIN
    -- Буквы в маске задают возможные допустимые значения
    -- по-умолчанию скрываем не-действующий статус
    IF(I$STATE_MASK IS NULL) THEN I$STATE_MASK = 'dah';

    FOR
        SELECT LV.LISTVAL_ID, LV.LIST_ID, LV.PARENT_ID, LV.TAG, LV."FILTER", LV.SORT_ORDER, LV.COST, LV.VAL, LV.VAL_LONG
        FROM LISTVALS_LIST(304) LV
        WHERE LV.IS_DEL = 0
        ORDER BY LV.SORT_ORDER
        INTO :LISTVAL_ID, :LIST_ID, :PARENT_ID, :TAG, :"FILTER", :SORT_ORDER, :COST, :VAL, :VAL_LONG
    DO
    BEGIN
        IF(
            (POSITION('d' IN I$STATE_MASK) > 0 AND LISTVAL_ID = 11716) OR -- черновик
            (POSITION('a' IN I$STATE_MASK) > 0 AND LISTVAL_ID = 11715) OR -- действующий
            (POSITION('n' IN I$STATE_MASK) > 0 AND LISTVAL_ID = 11717) OR -- не действующий
            (POSITION('h' IN I$STATE_MASK) > 0 AND LISTVAL_ID = 14261)    -- архивный
        )
        THEN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OBJECT_TABS_LIST (
    I$TYPE_ID BIGINT,
    I$LEVEL_ID BIGINT,
    I$USER_ID BIGINT,
    I$PARENT_TYPE_ID BIGINT = null)
RETURNS (
    TAB_ID BIGINT,
    TAB_NUM SMALLINT,
    TAB_CAPTION VARCHAR(4000))
AS
declare variable RES_ID bigint;
declare variable LANG_CODE varchar(2);
declare variable V$OU_LICENCE_TYPE char(1);
BEGIN
    SELECT LANG_CODE FROM USERS WHERE USER_ID = :I$USER_ID INTO :LANG_CODE;
    SELECT STATUS FROM OU_LICENCE_TYPE INTO :V$OU_LICENCE_TYPE;

    FOR
        SELECT DISTINCT TAB_ID, TAB_NUM, RES_ID
        FROM OBJECT_TABS_LIST_RET(:I$PARENT_TYPE_ID, :I$TYPE_ID, :I$LEVEL_ID, :I$USER_ID)
        ORDER BY TAB_NUM
        INTO :TAB_ID, :TAB_NUM, :RES_ID
    DO
    BEGIN
        SELECT VAL FROM RES_GET(:RES_ID, :LANG_CODE) INTO :TAB_CAPTION;

        IF(V$OU_LICENCE_TYPE = 'P' AND TAB_CAPTION = 'Итоги обучения и ГИА') THEN TAB_CAPTION = 'Итоги обучения';

        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OBJECT_TABS_LIST_RET (
    I$PARENT_TYPE_ID BIGINT,
    I$TYPE_ID BIGINT,
    I$LEVEL_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    TAB_ID BIGINT,
    TAB_NUM SMALLINT,
    RES_ID BIGINT)
AS
declare variable V$LANG_CODE varchar(2);
BEGIN
    SELECT LANG_CODE FROM USERS WHERE USER_ID = :I$USER_ID INTO :V$LANG_CODE;

    -- Непосредственно закладки для данного типа объекта, где есть хотя бы один параметр
    FOR
        SELECT T.TAB_ID, T.TAB_NUM, T.RES_ID
        FROM TABS T
        JOIN PARAMS P ON P.TAB_ID = T.TAB_ID AND P.IS_DEL = 0
        JOIN LPARAMS L ON L.PARAM_ID = P.PARAM_ID AND L.LEVEL_ID = :I$LEVEL_ID AND L.IS_DEL = 0
        WHERE T.TYPE_ID = :I$TYPE_ID AND T.IS_DEL = 0
        INTO :TAB_ID, :TAB_NUM, :RES_ID
    DO
    BEGIN
        SUSPEND;
    END

    -- Закладки, где есть дочерние объекты
    FOR
        SELECT T.TAB_ID, T.TAB_NUM, T.RES_ID
        FROM TABS T
        JOIN PARENTS P ON P.TAB_ID = T.TAB_ID AND P.TYPE_ID = T.TYPE_ID AND P.IS_DEL = 0
        JOIN LTYPES L ON L.TYPE_ID = P.CHILD_ID AND L.LEVEL_ID = :I$LEVEL_ID AND L.IS_DEL = 0
        WHERE T.TYPE_ID = :I$TYPE_ID AND T.IS_DEL = 0
        INTO :TAB_ID, :TAB_NUM, :RES_ID
    DO
    BEGIN
        SUSPEND;
    END

    -- Закладки для фреймов
    FOR
        SELECT T.TAB_ID, T.TAB_NUM, T.RES_ID
        FROM TABS T
        JOIN OBJECT_FRAMES F ON F.TYPE_ID = :I$TYPE_ID AND F.IS_DEL = 0 AND F.TAB_ID = T.TAB_ID
            and (F.PARENT_TYPE_ID = :I$PARENT_TYPE_ID OR (F.PARENT_TYPE_ID IS NULL AND :I$PARENT_TYPE_ID IS NULL))
        WHERE ((LEVEL_ID = :I$LEVEL_ID) or (LEVEL_ID IS NULL)) AND T.TYPE_ID = :I$TYPE_ID AND T.IS_DEL = 0
        INTO :TAB_ID, :TAB_NUM, :RES_ID
    DO
    BEGIN
        SUSPEND;
    END

    -- Закладки для ссылок вбок
    FOR
        SELECT T.TAB_ID, T.TAB_NUM, T.RES_ID
        FROM TABS T
        JOIN PARENTS PR ON PR.TYPE_ID = :I$PARENT_TYPE_ID AND PR.CHILD_ID = T.TYPE_ID
        JOIN TABS T2 ON T2.TYPE_ID = PR.EXT_TYPE_ID
        LEFT JOIN RES_GET(T.RES_ID, :V$LANG_CODE) R ON 1=1
        LEFT JOIN RES_GET(T2.RES_ID, :V$LANG_CODE) R2 ON 1=1
        JOIN PARAMS P ON P.TAB_ID = T2.TAB_ID AND P.IS_DEL = 0
        JOIN LPARAMS L ON L.PARAM_ID = P.PARAM_ID AND L.IS_DEL = 0 AND L.LEVEL_ID = :I$LEVEL_ID
        WHERE T.TYPE_ID = :I$TYPE_ID AND T.IS_DEL = 0 AND R.VAL LIKE R2.VAL
        INTO :TAB_ID, :TAB_NUM, :RES_ID
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OBJECT_TAB_GET (
    I$LINK_ID BIGINT)
RETURNS (
    LINK_ID BIGINT,
    PARENT_ID BIGINT,
    OBJ_ID BIGINT,
    TAB_ID BIGINT)
AS
BEGIN
    SELECT L.LINK_ID,
           L.PARENT_ID,
           L.OBJ_ID,
           P.TAB_ID

    FROM LINKS L

    JOIN PARENTS P
    ON L.PARENT_TYPE_ID = P.TYPE_ID
    AND L.OBJ_TYPE_ID = P.CHILD_ID

    WHERE L.LINK_ID = :I$LINK_ID
    INTO :LINK_ID,
         :PARENT_ID,
         :OBJ_ID,
         :TAB_ID;

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OBJECT_TREE (
    I$OBJ_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    TYPE_ID BIGINT,
    IS_DEL SMALLINT)
AS
BEGIN
    FOR SELECT L.OBJ_ID, L.OBJ_TYPE_ID,
            IIF (L.DATE_DEL IS NULL, 0, 1)
        FROM LINKS L
        WHERE L.PARENT_ID = :I$OBJ_ID
        INTO :OBJ_ID, :TYPE_ID, :IS_DEL
    DO
    BEGIN
        SUSPEND;
        FOR SELECT OBJ_ID, TYPE_ID, IS_DEL
            FROM OBJECT_TREE(:OBJ_ID)
            INTO :OBJ_ID, TYPE_ID, IS_DEL
        DO
        BEGIN
            SUSPEND;
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OBJECT_TREE_COPY (
    I$PARENT_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$TYPE_ID BIGINT,
    I$LEVEL SMALLINT = 1)
AS
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$PARENT_ID BIGINT;
DECLARE VARIABLE V$TYPE_ID BIGINT;
BEGIN
    SELECT OBJ_ID
    FROM OBJECT_COPY(:I$PARENT_ID, :I$OBJ_ID, :I$TYPE_ID)
    INTO :V$PARENT_ID;

    DELETE FROM TREE_TMP WHERE "LEVEL" = :I$LEVEL;

    INSERT INTO TREE_TMP(OBJ_ID, TYPE_ID, "LEVEL")
    SELECT OBJ_ID, OBJ_TYPE_ID, :I$LEVEL
    FROM LINKS
    WHERE PARENT_ID = :I$OBJ_ID AND DATE_DEL IS NULL;

    FOR
      SELECT OBJ_ID, TYPE_ID
      FROM TREE_TMP
      WHERE "LEVEL" = :I$LEVEL
      INTO :V$OBJ_ID, :V$TYPE_ID
    DO
    BEGIN
      EXECUTE PROCEDURE OBJECT_TREE_COPY(:V$PARENT_ID, :V$OBJ_ID, :V$TYPE_ID, :I$LEVEL + 1);
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OBJECT_TYPES_LIST (
    I$TYPE_ID BIGINT,
    I$LEVEL_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    TYPE_ID BIGINT,
    TYPE_CAPTION VARCHAR(4000),
    DO_FUNC SMALLINT,
    IS_FROM_LIST SMALLINT,
    RUN_SQL VARCHAR(1000))
AS
declare variable RES_ID bigint;
declare variable LANG_CODE varchar(2);
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :LANG_CODE;

    IF (I$TYPE_ID IS NULL) THEN BEGIN

        TYPE_ID = NULL;

        SELECT L.ROOT_TYPE_ID
        FROM LEVELS L

        JOIN TYPES T
        ON T.TYPE_ID = L.ROOT_TYPE_ID

        JOIN LTYPES LT
        ON LT.TYPE_ID = T.TYPE_ID
        AND LT.LEVEL_ID = L.LEVEL_ID

        JOIN LUSERS LU
        ON LU.LEVEL_ID = L.LEVEL_ID

        WHERE L.LEVEL_ID = :I$LEVEL_ID
        AND L.IS_DEL = 0
        AND LU.USER_ID = :I$USER_ID
        AND L.PARENT_TYPE_ID IS NULL
        AND LU.ROOT_OBJ_ID IS NULL
        AND LU.ROOT_PARENT_ID IS NULL
        AND T.IS_DEL = 0
        AND LT.EDIT_TYPE = 1
        INTO :TYPE_ID;

        IF (TYPE_ID IS NULL) THEN EXIT;

        SELECT RES_ID FROM TYPES WHERE TYPE_ID = :TYPE_ID INTO :RES_ID;
        SELECT VAL FROM RES_GET(:RES_ID, :LANG_CODE) INTO :TYPE_CAPTION;

        DO_FUNC = 0;
        IS_FROM_LIST = 0;
        RUN_SQL = NULL;

        SUSPEND;
        EXIT;

    END

    FOR
        SELECT
             P.CHILD_ID,
             P.DO_FUNC,
             P.IS_FROM_LIST,
             P.RUN_SQL,
             T.RES_ID
        FROM PARENTS P
        JOIN TYPES T ON T.TYPE_ID = P.CHILD_ID
        JOIN LTYPES L ON L.TYPE_ID = P.CHILD_ID
        WHERE P.TYPE_ID = :I$TYPE_ID
        AND P.IS_DEL = 0
        AND P.IS_ADD = 1
        AND L.IS_DEL = 0
        AND L.LEVEL_ID = :I$LEVEL_ID
        AND L.EDIT_TYPE = 1
        AND T.IS_DEL = 0
        ORDER BY T.SORT_ORDER
        INTO :TYPE_ID, :DO_FUNC, :IS_FROM_LIST, :RUN_SQL, :RES_ID
    DO
    BEGIN
        SELECT VAL FROM RES_GET(:RES_ID, :LANG_CODE) INTO :TYPE_CAPTION;
        SUSPEND;
    END

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OBJECT_VR_LINKS (
    I$LEVEL_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$TYPE_ID BIGINT)
RETURNS (
    LINK_ID BIGINT,
    OBJ_ID BIGINT,
    OBJ_TYPE_ID BIGINT,
    PARENT_ID BIGINT)
AS
begin

  -- Список движения на дистанционном обучении
  IF(I$TYPE_ID = 152) THEN
  BEGIN
    OBJ_TYPE_ID = 152;
    FOR
      SELECT M.OBJ_ID, M.OBJ_ID
      FROM PERSON_MOVEMENTS M
      JOIN OBJECTS OBJ ON OBJ.OBJ_ID = M.GROUP_ID AND OBJ.TYPE_ID = 338
      WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :I$OBJ_ID
      INTO :LINK_ID, :OBJ_ID
    DO
    BEGIN
      SUSPEND;
    END
  END
  -- Учебные коллективы в рамках УП, выбираем все действующие и будущие
  ELSE IF(I$TYPE_ID = 499) THEN
  BEGIN
    OBJ_TYPE_ID = 499;
    FOR
      SELECT LP8.OBJ_ID, LP8.OBJ_ID
      FROM VALR VR
      JOIN LINKS LP8 ON LP8.OBJ_ID = VR.OBJ_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
      WHERE VR.PARAM_ID IN (3477, 3075) AND VR.VAL = :I$OBJ_ID AND VR.IS_DEL = 0
      INTO :LINK_ID, :OBJ_ID
    DO
    BEGIN
      SUSPEND;
    END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OD_SUBJECTS_LIST (
    I$OBJ_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    OBJ_CAPTION VARCHAR(1000))
AS
begin

  -- Список предметов должен быть синхронен с DC_OD_MEETINGS
  FOR
    SELECT L51.OBJ_ID, C.CAPTION
    FROM LINKS L51
    LEFT JOIN OBJECT_CAPTION_GET(L51.OBJ_ID) C ON 1 = 1
    WHERE L51.PARENT_ID = 32771 AND L51.OBJ_TYPE_ID = 51 AND L51.DATE_DEL IS NULL
    AND L51.OBJ_ID IN (5516, 172, 188, 197, 3139, 34752, 173, 177, 202, 191, 34279, 3131, 174, 3151, 3155, 3132, 34753,
      195, 187, 190, 34754, 2129, 34755, 194, 206, 5532, 900, 3138, 32787, 929, 34756, 32840, 185, 34757, 200, 198, 205,
      3130, 189, 199, 3135, 3160, 32843, 3134)
    ORDER BY 2
    INTO :OBJ_ID, :OBJ_CAPTION
  DO
  BEGIN
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OD_SUBJECT_EXT (
    I$PERSON_ID BIGINT,
    I$SUBJECT_ID BIGINT,
    I$IS_CY SMALLINT,
    I$YEAR_ID BIGINT,
    I$DATE1 DATE,
    I$DATE2 DATE)
RETURNS (
    IS_EXT SMALLINT)
AS
DECLARE VARIABLE V$SID1 BIGINT;
DECLARE VARIABLE V$SID2 BIGINT;
DECLARE VARIABLE V$SID3 BIGINT;
begin

  IS_EXT = 0;

  -- Список альтернативных предметов для видов
  -- Алгебра, геометрия, математика
  IF(I$SUBJECT_ID IN (172, 173, 190)) THEN BEGIN V$SID1 = 172; V$SID2 = 173; V$SID3 = 190; END
  -- История, История России
  ELSE IF(I$SUBJECT_ID IN (174, 3151)) THEN BEGIN V$SID1 = 174; V$SID2 = 3151; END

  IF(I$IS_CY = 1) THEN
  BEGIN

    -- Текущий год, смотрим через ГУП и УП
    SELECT FIRST 1 1
    FROM PERSON_MOVEMENTS M
    JOIN LINKS LP54 ON LP54.OBJ_ID = M.GROUP_ID AND LP54.PARENT_TYPE_ID = 54 -- DEL тут неактуально
    JOIN LINKS LP400 ON LP400.OBJ_ID = M.GROUP_ID AND LP400.PARENT_TYPE_ID = 400 -- DEL тут неактуально
    JOIN PLAN_SUBJECTS PS ON PS.DATE_DEL IS NULL AND PS.PLAN_ID = LP400.PARENT_ID AND PS.IS_ADV = 1 AND (
      PS.SUBJECT_ID = :I$SUBJECT_ID OR PS.SUBJECT_ID = :V$SID1 OR PS.SUBJECT_ID = :V$SID2 OR PS.SUBJECT_ID = :V$SID3 OR
      PS.SRC_SUBJECT_ID = :I$SUBJECT_ID OR PS.SRC_SUBJECT_ID = :V$SID1 OR PS.SRC_SUBJECT_ID = :V$SID2 OR PS.SRC_SUBJECT_ID = :V$SID3
    )
    -- есть нагрузка для этого этапа обучения
    JOIN PLAN_LOADS PL ON PL.DATE_DEL IS NULL AND PL.SUBJECT_ID = PS.OBJ_ID AND PL.STAGE_ID = LP54.PARENT_ID AND PL.LOAD_HOURS_S1 > 0
    WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :I$PERSON_ID AND M.GROUP_TYPE_ID = 256 AND M.DATE_IN <= :I$DATE2 AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :I$DATE1)
    INTO :IS_EXT;

  END
  ELSE
  BEGIN

    -- Архивный год, смотрим через итоговые отметки
    SELECT FIRST 1 1
    FROM VALM M
    WHERE M.IS_DEL = 0 AND M.IS_EXT = 1 AND M.IS_NATIVE = 1 AND M.PUPIL_ID = :I$PERSON_ID AND M.YEAR_ID = :I$YEAR_ID AND (
      M.SUBJECT_ID = :I$SUBJECT_ID OR M.SUBJECT_ID = :V$SID1 OR M.SUBJECT_ID = :V$SID2 OR M.SUBJECT_ID = :V$SID3
    )
    INTO :IS_EXT;

  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OK009_FILTRED_LIST (
    I$OBJ_ID BIGINT,
    I$LIST_ID BIGINT,
    I$USER_ID BIGINT = NULL)
RETURNS (
    LISTVAL_ID BIGINT,
    PARENT_ID BIGINT,
    VAL VARCHAR(4000),
    VAL_LONG VARCHAR(4000),
    TAG VARCHAR(100))
AS
DECLARE VARIABLE RES_ID BIGINT;
DECLARE VARIABLE LANG_CODE VARCHAR(2);
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :LANG_CODE;

    FOR
        SELECT LISTVAL_ID, PARENT_ID, TAG, RES_ID
        FROM LISTVALS
        WHERE LIST_ID = :I$LIST_ID AND IS_DEL = 0
        ORDER BY SORT_ORDER
        INTO :LISTVAL_ID, :PARENT_ID, :TAG, :RES_ID
    DO
    BEGIN
        SELECT :TAG || '. ' || VAL || IIF(VAL_LONG <> '',' (' || VAL_LONG || ')',''), VAL_LONG
        FROM RES_GET(:RES_ID, :LANG_CODE)
        INTO :VAL, :VAL_LONG;
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OLYMP_EVENT_GET (
    I$ROOT_ID BIGINT)
RETURNS (
    EVENT_ID BIGINT,
    EVENT_CAPTION VARCHAR(100))
AS
BEGIN
  FOR
    SELECT L382.OBJ_ID, OC382.CAPTION
    FROM LINKS L382
    LEFT JOIN OBJECT_CAPTION_GET(L382.OBJ_ID) OC382 ON 1=1
    WHERE L382.OBJ_ID = :I$ROOT_ID AND L382.OBJ_TYPE_ID = 382 AND L382.DATE_DEL IS NULL
      AND L382.PARENT_TYPE_ID IN (380, 381)  
    UNION
    SELECT L382.OBJ_ID, OC382.CAPTION
    FROM LINKS L382
    LEFT JOIN OBJECT_CAPTION_GET(L382.OBJ_ID) OC382 ON 1=1
    WHERE L382.PARENT_ID = :I$ROOT_ID AND L382.OBJ_TYPE_ID = 382 AND L382.DATE_DEL IS NULL
      AND L382.PARENT_TYPE_ID IN (380, 381)
    UNION
    SELECT L382.OBJ_ID, OC382.CAPTION
    FROM LINKS L381
    JOIN LINKS L382 ON L382.PARENT_ID = L381.OBJ_ID AND L382.OBJ_TYPE_ID = 382 AND L382.DATE_DEL IS NULL
    LEFT JOIN OBJECT_CAPTION_GET(L382.OBJ_ID) OC382 ON 1=1
    WHERE L381.PARENT_ID = :I$ROOT_ID AND L381.OBJ_TYPE_ID = 381 AND L381.DATE_DEL IS NULL
    INTO :EVENT_ID, :EVENT_CAPTION
  DO
  BEGIN
    SUSPEND;
  END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OLYMP_EVENT_PUPIL_GET (
    EVENT_ID BIGINT,
    PUPIL_ID BIGINT)
RETURNS (
    VAL INTEGER)
AS
BEGIN
  FOR
    select 1
    from LINKS L10
    where L10.PARENT_ID = :EVENT_ID and
          L10.PARENT_TYPE_ID = 382 and
          L10.OBJ_ID = :PUPIL_ID and
          L10.DATE_DEL is null
    INTO :VAL
  DO
  BEGIN
    SUSPEND;
  END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OLYMP_PUPIL_GET (
    I$GRADE_ID BIGINT)
RETURNS (
    STAGE_ID BIGINT,
    STAGE_CAPTION VARCHAR(100),
    GRADE_ID BIGINT,
    GRADE_CAPTION VARCHAR(100),
    CLASS_CAPTION VARCHAR(5),
    NPP SMALLINT,
    PUPIL_ID BIGINT,
    PUPIL_CAPTION VARCHAR(100),
    SECOND_NAME VARCHAR(100),
    FIRST_NAME VARCHAR(100),
    PATRONYMIC VARCHAR(100),
    DOB DATE,
    LIMITATION_TYPE BIGINT,
    GENDER BIGINT,
    CITIZENSHIP BIGINT)
AS
declare variable V$OBJ_ID bigint;
begin
  
  if (I$GRADE_ID IS NOT NULL) then
  BEGIN
     SELECT I FROM VAL_GET(:I$GRADE_ID, 2872)
     INTO :I$GRADE_ID;
  END

  select first (1) L2.OBJ_ID
  from LINKS L2
  where L2.PARENT_ID is null and
        L2.OBJ_TYPE_ID = 2
  into V$OBJ_ID;

  for select
             VL.LISTVAL_ID,
             OC7.CAPTION,
             VL1.LISTVAL_ID,
             OC8.CAPTION,
             L9.OBJ_ID,
             cast((VL1.LISTVAL_ID - 36) as varchar(2)) || VS.VAL
      from LINKS L7
      join VALL VL on L7.OBJ_ID = VL.OBJ_ID and
            VL.PARAM_ID = 43
      left join OBJECT_CAPTION_GET(L7.OBJ_ID) OC7 on 1=1
      join LINKS L8 on L7.OBJ_ID = L8.PARENT_ID and
            L8.DATE_DEL is null
      join VALL VL1 on L8.OBJ_ID = VL1.OBJ_ID and
            VL1.PARAM_ID = 49
      left join OBJECT_CAPTION_GET(L8.OBJ_ID) OC8 on 1=1
      join LINKS L9 on L8.OBJ_ID = L9.PARENT_ID and
            L9.DATE_DEL is null
      join VALS VS on L9.OBJ_ID = VS.OBJ_ID and
            VS.PARAM_ID = 54
      where L7.OBJ_TYPE_ID = 7 and
            L7.DATE_DEL is null and
            L7.PARENT_ID = :V$OBJ_ID and
            VL1.LISTVAL_ID = COALESCE(:I$GRADE_ID, VL1.LISTVAL_ID)
      order by 3
      into STAGE_ID, STAGE_CAPTION, GRADE_ID, GRADE_CAPTION, V$OBJ_ID, CLASS_CAPTION
  do
  begin
    NPP = 0;
    FOR SELECT L10.OBJ_ID
    FROM LINKS L10
    WHERE L10.PARENT_ID = :V$OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    INTO :PUPIL_ID
    DO
    BEGIN
      NPP = NPP + 1;
      select V from VAL_GET(:PUPIL_ID, 55)
      into :SECOND_NAME;
      select V from VAL_GET(:PUPIL_ID, 56)
      into :FIRST_NAME;
      PUPIL_CAPTION = SECOND_NAME || ' ' || FIRST_NAME;
      select V from VAL_GET(:PUPIL_ID, 57)
      into :PATRONYMIC;
      select D from VAL_GET(:PUPIL_ID, 89)
      into :DOB;
      select I from VAL_GET(:PUPIL_ID, 2364)
      into :LIMITATION_TYPE;
      select I from VAL_GET(:PUPIL_ID, 88)
      into :GENDER;
      select I from VAL_GET(:PUPIL_ID, 91)
      into :CITIZENSHIP;
      suspend;
    END
  end
end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OLYMP_RESULT_SET (
    I$PUPIL_ID BIGINT NOT NULL,
    I$EVENT_EXT_ID VARCHAR(50),
    I$EVENT_TYPE BIGINT,
    I$DESCRIPTION VARCHAR(400),
    I$STATUS BIGINT,
    I$EVENT_DATE DATE,
    I$SUBJECT VARCHAR(400),
    I$EVENT_RESULT BIGINT,
    I$REMOVED SMALLINT = 0)
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$STR varchar(100);
declare variable V$BLOB_ID bigint;
begin
  select L22.OBJ_ID
  from LINKS L22
  join VALS V2879 on V2879.OBJ_ID = L22.OBJ_ID and
        V2879.PARAM_ID = 2879 and
        V2879.IS_DEL = 0 and
        V2879.VAL = :I$EVENT_EXT_ID
  where L22.PARENT_ID = :I$PUPIL_ID and
        L22.OBJ_TYPE_ID = 22 and
        L22.DATE_DEL is null
  into :OBJ_ID;
  
  if (OBJ_ID is null) then
  begin
    if (I$REMOVED <> 0) then
    begin
      SUSPEND;
      EXIT;
    end
    select OBJ_ID
    from OBJECT_ADD(:I$PUPIL_ID, 22)
    into :OBJ_ID;
  end
  else begin
    if (I$REMOVED <> 0) then
    begin
      select DEL_COUNT
      from OBJECT_DEL(:I$PUPIL_ID, :OBJ_ID)
      into :V$BLOB_ID;
      SUSPEND;
      EXIT;
    end
  end

  select VAL
  from LISTVALS_LIST(53)
  where LISTVAL_ID = :I$EVENT_TYPE
  into :V$STR;

  SELECT BLOB_ID FROM VAL_ADD(167, :OBJ_ID, :V$STR)
  into :V$BLOB_ID;

  SELECT BLOB_ID FROM VAL_ADD(1818, :OBJ_ID, :I$DESCRIPTION)
  into :V$BLOB_ID;

  SELECT BLOB_ID FROM VAL_ADD(1819, :OBJ_ID, :I$STATUS)
  into :V$BLOB_ID;

  SELECT BLOB_ID FROM VAL_ADD(166, :OBJ_ID, :I$EVENT_DATE)
  into :V$BLOB_ID;

  SELECT BLOB_ID FROM VAL_ADD(1820, :OBJ_ID, :I$SUBJECT)
  into :V$BLOB_ID;

  SELECT BLOB_ID FROM VAL_ADD(237, :OBJ_ID, :I$EVENT_RESULT)
  into :V$BLOB_ID;

  SELECT BLOB_ID FROM VAL_ADD(2879, :OBJ_ID, :I$EVENT_EXT_ID)
  into :V$BLOB_ID;

  suspend;
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OLYMP_SCHEDULE_SET (
    I$EVENT_EXT_ID VARCHAR(50),
    I$EVENT_TYPE_ID BIGINT,
    I$EVENT_DESCRIPTION VARCHAR(400),
    I$EVENT_REMOVED SMALLINT,
    I$PHASE_EXT_ID VARCHAR(50),
    I$PHASE_START_DATE TIMESTAMP,
    I$PHASE_END_DATE TIMESTAMP,
    I$PHASE_DESCRIPTION VARCHAR(400),
    I$PHASE_SUBJECT_GIA BIGINT,
    I$PHASE_SUBJECT VARCHAR(400),
    I$PHASE_STAGE BIGINT,
    I$PHASE_REMOVED SMALLINT)
RETURNS (
    EVENT_ID BIGINT,
    PHASE_ID BIGINT)
AS
declare variable V$BLOB_ID bigint;
declare variable Y1 smallint;
declare variable M smallint;
declare variable V$YEAR_ID bigint;
declare variable V$EVENTS bigint;
declare variable V$PHASE_PARENT_ID bigint;
begin
  --создаем или редактируем год

  --определяем год
  I$PHASE_START_DATE = COALESCE(I$PHASE_START_DATE, CURRENT_TIMESTAMP);
  Y1 = EXTRACT(YEAR FROM I$PHASE_START_DATE);
  M = EXTRACT(MONTH FROM I$PHASE_START_DATE);
  IF (M < 9) THEN Y1 = Y1 - 1;

  select L379.OBJ_ID
  from LINKS L379
  join VALL V2871 ON V2871.OBJ_ID = L379.OBJ_ID and V2871.PARAM_ID = 2871 and V2871.IS_DEL = 0
  join LISTVALS LV ON LV.LISTVAL_ID = V2871.LISTVAL_ID and LV.LIST_ID = 29 AND LV.COST = :Y1 AND LV.IS_DEL = 0
  into :V$YEAR_ID;
  
  --корневой объект мероприятия
  select first(1) OBJ_ID from LINKS L377 where L377.OBJ_TYPE_ID = 377 and L377.DATE_DEL IS NULL
  into :V$EVENTS;

  if (V$YEAR_ID is null) then
  begin
    if (I$EVENT_REMOVED <> 0) then
    begin
      SUSPEND;
      EXIT;
    end
    select OBJ_ID
    from OBJECT_ADD(:V$EVENTS, 379)
    into :V$YEAR_ID;
  end

  SELECT BLOB_ID
  FROM LISTVALS LV
    LEFT JOIN VAL_ADD(2871, :V$YEAR_ID, LV.LISTVAL_ID) VA ON 1=1
  WHERE
    LV.LIST_ID = 29 and LV.COST = :Y1
  into :V$BLOB_ID;

  --создаем или редактируем мероприятие
  select first(1) L380.OBJ_ID
  from LINKS L380
  join VALS V2870 on V2870.OBJ_ID = L380.OBJ_ID and
        V2870.PARAM_ID = 2870 and
        V2870.IS_DEL = 0 and
        V2870.VAL = :I$EVENT_EXT_ID
  where L380.PARENT_ID = :V$YEAR_ID and
        L380.OBJ_TYPE_ID = 380 and
        L380.DATE_DEL is null
  into :EVENT_ID;
  
  if (EVENT_ID is null) then
  begin
    if (I$EVENT_REMOVED <> 0) then
    begin
      SUSPEND;
      EXIT;
    end
    select OBJ_ID
    from OBJECT_ADD(:V$YEAR_ID, 380)
    into :EVENT_ID;
  end
  else begin
    if (I$EVENT_REMOVED <> 0) then
    begin
      select DEL_COUNT
      from OBJECT_DEL(:V$YEAR_ID, :EVENT_ID)
      into :V$BLOB_ID;
      SUSPEND;
      EXIT;
    end
  end

  SELECT BLOB_ID FROM VAL_ADD(2870, :EVENT_ID, :I$EVENT_EXT_ID)
  into :V$BLOB_ID;

  SELECT BLOB_ID FROM VAL_ADD(2868, :EVENT_ID, :I$EVENT_DESCRIPTION)
  into :V$BLOB_ID;

  SELECT BLOB_ID FROM VAL_ADD(2869, :EVENT_ID, :I$EVENT_TYPE_ID)
  into :V$BLOB_ID;

  --создаем или редактируем этап обучения
  --этапа обучения может и не быть (I$PHASE_STAGE is null)
  if (I$PHASE_STAGE is null) then
    V$PHASE_PARENT_ID = EVENT_ID;
  else begin
    select first(1) L381.OBJ_ID
    from LINKS L381
    join VALL V2872 on V2872.OBJ_ID = L381.OBJ_ID and
          V2872.PARAM_ID = 2872 and
          V2872.IS_DEL = 0 and
          V2872.LISTVAL_ID = :I$PHASE_STAGE
    where L381.PARENT_ID = :EVENT_ID and
          L381.OBJ_TYPE_ID = 381 and
          L381.DATE_DEL is null
    into :V$PHASE_PARENT_ID;
    
    if (V$PHASE_PARENT_ID is null) then
    begin
      if (I$PHASE_REMOVED <> 0) then
      begin
        SUSPEND;
        EXIT;
      end
      select OBJ_ID
      from OBJECT_ADD(:EVENT_ID, 381)
      into :V$PHASE_PARENT_ID;
    end
    else begin
      if (I$PHASE_REMOVED <> 0) then
      begin
--        select DEL_COUNT
--        from OBJECT_DEL(:EVENT_ID, :V$PHASE_PARENT_ID)
--        into :V$BLOB_ID;
        SUSPEND;
        EXIT;
      end
    end
  
    select BLOB_ID from VAL_ADD(2872, :V$PHASE_PARENT_ID, :I$PHASE_STAGE)
    into :V$BLOB_ID;
  end

  --создаем или редактируем фазу
  select first(1) L382.OBJ_ID
  from LINKS L382
  join VALS V2877 on V2877.OBJ_ID = L382.OBJ_ID and
        V2877.PARAM_ID = 2877 and
        V2877.IS_DEL = 0 and
        V2877.VAL = :I$PHASE_EXT_ID
  where L382.PARENT_ID = :V$PHASE_PARENT_ID and
        L382.OBJ_TYPE_ID = 382 and
        L382.DATE_DEL is null
  into :PHASE_ID;
  
  if (PHASE_ID is null) then
  begin
    if (I$PHASE_REMOVED <> 0) then
    begin
      SUSPEND;
      EXIT;
    end
    select OBJ_ID
    from OBJECT_ADD(:V$PHASE_PARENT_ID, 382)
    into :PHASE_ID;
  end
  else begin
    if (I$PHASE_REMOVED <> 0) then
    begin
      select DEL_COUNT
      from OBJECT_DEL(:V$PHASE_PARENT_ID, :PHASE_ID)
      into :V$BLOB_ID;
      SUSPEND;
      EXIT;
    end
  end

  SELECT BLOB_ID FROM VAL_ADD(2877, :PHASE_ID, :I$PHASE_EXT_ID)
  into :V$BLOB_ID;

  SELECT BLOB_ID FROM VAL_ADD(2875, :PHASE_ID, :I$PHASE_START_DATE)
  into :V$BLOB_ID;

  SELECT BLOB_ID FROM VAL_ADD(2876, :PHASE_ID, :I$PHASE_END_DATE)
  into :V$BLOB_ID;

  SELECT BLOB_ID FROM VAL_ADD(2874, :PHASE_ID, :I$PHASE_DESCRIPTION)
  into :V$BLOB_ID;

  SELECT BLOB_ID FROM VAL_ADD(2873, :PHASE_ID, :I$PHASE_SUBJECT_GIA)
  into :V$BLOB_ID;

  suspend;
end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OO_ACCEPT_FROM_LIST (
    OBJ_ID BIGINT,
    USER_ID BIGINT = 1)
RETURNS (
    LISTVAL_ID BIGINT,
    PARENT_ID BIGINT,
    VAL VARCHAR(4000),
    VAL_LONG VARCHAR(4000),
    TAG VARCHAR(100),
    "FILTER" VARCHAR(255))
AS
DECLARE VARIABLE V$LEVEL_ID BIGINT;
DECLARE VARIABLE V$STAGE_ID BIGINT;
DECLARE VARIABLE V$STAGE_FOLDER BIGINT;
DECLARE VARIABLE V$FILTER VARCHAR(40);
begin

  -- OBJ_ID сюда может передаваться из типа 10, обязательно будет класс/группа или предварительный прием
  -- а также в предварительном приеме в качестве OBJ_ID будет передан не сам ученик, а учебный коллектив
  -- достаем уровень обучения
  SELECT FIRST 1 V43.LISTVAL_ID, V49.LISTVAL_ID
  FROM LINKS LP8
  JOIN VALL V49 ON V49.OBJ_ID = LP8.PARENT_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
  JOIN LINKS LP7 ON LP7.OBJ_ID = LP8.PARENT_ID AND LP7.PARENT_TYPE_ID = 7 AND LP7.DATE_DEL IS NULL
  JOIN VALL V43 ON V43.OBJ_ID = LP7.PARENT_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0
  WHERE LP8.OBJ_ID = :OBJ_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
  INTO :V$LEVEL_ID, :V$STAGE_ID;

  -- Прием в класс ?
  IF(V$LEVEL_ID IS NULL) THEN
  BEGIN
    SELECT FIRST 1 V43.LISTVAL_ID, V49.LISTVAL_ID
    FROM LINKS LP7
    JOIN VALL V49 ON V49.OBJ_ID = LP7.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
    JOIN VALL V43 ON V43.OBJ_ID = LP7.PARENT_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0
    WHERE LP7.OBJ_ID = :OBJ_ID AND LP7.PARENT_TYPE_ID = 7 AND LP7.DATE_DEL IS NULL
    INTO :V$LEVEL_ID, :V$STAGE_ID;
  END

  -- Предварительный прием ?
  IF(V$LEVEL_ID IS NULL) THEN
  BEGIN
    -- Нужен не сам этап обучения, а раздел
    -- Когда выбран ученик
    SELECT FIRST 1 LV.PARENT_ID, LV.LISTVAL_ID
    FROM LINKS LP290
    JOIN VALL V2346 ON V2346.OBJ_ID = LP290.PARENT_ID AND V2346.PARAM_ID = 2346 AND V2346.IS_DEL = 0
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V2346.LISTVAL_ID
    WHERE LP290.OBJ_ID = :OBJ_ID AND LP290.PARENT_TYPE_ID = 290 AND LP290.DATE_DEL IS NULL
    -- Диалог приема
    UNION
    SELECT FIRST 1 LV.PARENT_ID, LV.LISTVAL_ID
    FROM LINKS LP77
    JOIN VALL V2346 ON V2346.OBJ_ID = LP77.OBJ_ID AND V2346.PARAM_ID = 2346 AND V2346.IS_DEL = 0
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V2346.LISTVAL_ID
    WHERE LP77.OBJ_ID = :OBJ_ID AND LP77.PARENT_TYPE_ID = 77 AND LP77.DATE_DEL IS NULL
    INTO :V$STAGE_FOLDER, :V$STAGE_ID;

    IF(V$STAGE_FOLDER = 2140) THEN V$LEVEL_ID = 21; -- ДО
    ELSE IF(V$STAGE_FOLDER IN (2141, 12941)) THEN V$LEVEL_ID = 26; -- всегда НОО
    ELSE IF(V$STAGE_FOLDER = 2142) THEN V$LEVEL_ID = 29; -- СПО
    ELSE IF(V$STAGE_FOLDER = 2143) THEN V$LEVEL_ID = 13128; -- кружки
  END

  -- И последний случай - редактирование поля в самом ученике, тут могут быть варианты
  -- в перспективе этот случай прибиваем
  IF(V$LEVEL_ID IS NULL) THEN
  BEGIN
    -- Класс ?
    SELECT FIRST 1 V43.LISTVAL_ID, V49.LISTVAL_ID
    FROM LINKS LP9
    JOIN LINKS LP8 ON LP8.OBJ_ID = LP9.PARENT_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
    JOIN VALL V49 ON V49.OBJ_ID = LP8.PARENT_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
    JOIN LINKS LP7 ON LP7.OBJ_ID = LP8.PARENT_ID AND LP7.PARENT_TYPE_ID IN (7, 502) AND LP7.DATE_DEL IS NULL
    JOIN VALL V43 ON V43.OBJ_ID = LP7.PARENT_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0
    WHERE LP9.OBJ_ID = :OBJ_ID AND LP9.PARENT_TYPE_ID IN (9, 125, 187) AND LP9.DATE_DEL IS NULL
    INTO :V$LEVEL_ID, :V$STAGE_ID;
    -- Академический отпуск ?
    -- !!!
  END

  IF(V$LEVEL_ID IN (21, 3263, 3264)) THEN
  BEGIN
    V$FILTER = '%DOU%';
  END
  ELSE IF(V$LEVEL_ID IN (22, 26, 27)) THEN
  BEGIN
    V$FILTER = '%GOU%';
  END
  ELSE IF(V$LEVEL_ID IN (29, 13131)) THEN
  BEGIN
    V$FILTER = '%COLLEGE%';
  END
  ELSE IF(V$LEVEL_ID = 13128) THEN
  BEGIN
    -- Кружки - просто принят, по идее этого случая вообще быть не должно
  END

  FOR
    SELECT L.LISTVAL_ID, L.PARENT_ID, L.VAL, L.VAL_LONG, L.TAG, L."FILTER"
    FROM LISTVALS_LIST(123) L
    WHERE L.IS_DEL = 0 AND L."FILTER" LIKE :V$FILTER
    INTO :LISTVAL_ID, :PARENT_ID, :VAL, :VAL_LONG, :TAG, :"FILTER"
  DO
  BEGIN
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OO_ACCEPT_REASON_LIST (
    OBJ_ID BIGINT,
    USER_ID BIGINT = 1)
RETURNS (
    LISTVAL_ID BIGINT,
    PARENT_ID BIGINT,
    VAL VARCHAR(4000),
    VAL_LONG VARCHAR(4000),
    TAG VARCHAR(100),
    "FILTER" VARCHAR(255))
AS
DECLARE VARIABLE V$LEVEL_ID BIGINT;
DECLARE VARIABLE V$STAGE_ID BIGINT;
DECLARE VARIABLE V$STAGE_FOLDER BIGINT;
begin

  -- OBJ_ID сюда никогда не передается из типа 76, обязательно будет класс/группа или предварительный прием
  -- а также в предварительном приеме в качестве OBJ_ID будет передан не сам ученик, а учебный коллектив
  -- достаем уровень обучения
  SELECT FIRST 1 V43.LISTVAL_ID, V49.LISTVAL_ID
  FROM LINKS LP8
  JOIN VALL V49 ON V49.OBJ_ID = LP8.PARENT_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
  JOIN LINKS LP7 ON LP7.OBJ_ID = LP8.PARENT_ID AND LP7.PARENT_TYPE_ID = 7 AND LP7.DATE_DEL IS NULL
  JOIN VALL V43 ON V43.OBJ_ID = LP7.PARENT_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0
  WHERE LP8.OBJ_ID = :OBJ_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
  INTO :V$LEVEL_ID, :V$STAGE_ID;

  -- Прием в класс ?
  IF(V$LEVEL_ID IS NULL) THEN
  BEGIN
    SELECT FIRST 1 V43.LISTVAL_ID, V49.LISTVAL_ID
    FROM LINKS LP7
    JOIN VALL V49 ON V49.OBJ_ID = LP7.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
    JOIN VALL V43 ON V43.OBJ_ID = LP7.PARENT_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0
    WHERE LP7.OBJ_ID = :OBJ_ID AND LP7.PARENT_TYPE_ID = 7 AND LP7.DATE_DEL IS NULL
    INTO :V$LEVEL_ID, :V$STAGE_ID;
  END

  -- Предварительный прием ?
  IF(V$LEVEL_ID IS NULL) THEN
  BEGIN
    -- Нужен не сам этап обучения, а раздел
    SELECT FIRST 1 LV.PARENT_ID, LV.LISTVAL_ID
    FROM LINKS LP290
    JOIN VALL V2346 ON V2346.OBJ_ID = LP290.PARENT_ID AND V2346.PARAM_ID = 2346 AND V2346.IS_DEL = 0
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V2346.LISTVAL_ID
    WHERE LP290.OBJ_ID = :OBJ_ID AND LP290.PARENT_TYPE_ID = 290 AND LP290.DATE_DEL IS NULL
    UNION
    SELECT FIRST 1 LV.PARENT_ID, LV.LISTVAL_ID
    FROM LINKS LP77
    JOIN VALL V2346 ON V2346.OBJ_ID = LP77.OBJ_ID AND V2346.PARAM_ID = 2346 AND V2346.IS_DEL = 0
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V2346.LISTVAL_ID
    WHERE LP77.OBJ_ID = :OBJ_ID AND LP77.PARENT_TYPE_ID = 77 AND LP77.DATE_DEL IS NULL
    INTO :V$STAGE_FOLDER, :V$STAGE_ID;

    IF(V$STAGE_FOLDER = 2140) THEN V$LEVEL_ID = 21; -- ДО
    ELSE IF(V$STAGE_FOLDER IN (2141, 12941)) THEN V$LEVEL_ID = 26; -- всегда НОО
    ELSE IF(V$STAGE_FOLDER = 2142) THEN V$LEVEL_ID = 29; -- СПО
    ELSE IF(V$STAGE_FOLDER = 2143) THEN V$LEVEL_ID = 13128; -- кружки
  END

  -- Чтобы фильтр в диалоге отрабатывал
  "FILTER" = 'ACCEPTED';

  -- Для первых классов разрешаем принимать для начала обучения
  IF(V$LEVEL_ID IN (21, 3263, 3264)) THEN
  BEGIN
    -- ДО - всегда просто принят
    LISTVAL_ID = 3276;
  END
  ELSE IF(V$LEVEL_ID IN (22, 26, 27)) THEN
  BEGIN
    -- Только для первых классов разрешаем "Принят для начала"
    IF(V$STAGE_ID IN (37, 12942, 12943)) THEN
    BEGIN
      LISTVAL_ID = 805;
      VAL = (SELECT VAL FROM LISTVAL_TEXT(:LISTVAL_ID));
      SUSPEND;
    END
    LISTVAL_ID = 806;
  END
  ELSE IF(V$LEVEL_ID IN (29, 13131)) THEN
  BEGIN
    -- СПО - просто принят, и еще добавляем потом в хвост
    LISTVAL_ID = 5322;
  END
  ELSE IF(V$LEVEL_ID = 13128) THEN
  BEGIN
    -- Кружки - просто принят
    LISTVAL_ID = 5546;
  END

  IF(LISTVAL_ID IS NOT NULL) THEN
  BEGIN
    VAL = (SELECT VAL FROM LISTVAL_TEXT(:LISTVAL_ID));
    SUSPEND;
  END

  -- Для СПО добавляем варианты в конец
  IF(V$LEVEL_ID = 29) THEN
  BEGIN
    -- Восстановление (не из академки)
    LISTVAL_ID = 5321;
    VAL = (SELECT VAL FROM LISTVAL_TEXT(:LISTVAL_ID));
    SUSPEND;
    -- Повторное
    LISTVAL_ID = 12788;
    VAL = (SELECT VAL FROM LISTVAL_TEXT(:LISTVAL_ID));
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OO_DOCUMENT_INFO (
    I$OBJ_ID BIGINT)
RETURNS (
    LIC_DATA VARCHAR(400),
    ACCR_DATA VARCHAR(400),
    PRG_VER VARCHAR(40),
    DG_VER VARCHAR(40),
    IO_DATE VARCHAR(40),
    ADDR_DATA VARCHAR(1000))
AS
DECLARE VARIABLE V$TYPE_ID BIGINT;
DECLARE VARIABLE V$DT DATE;
DECLARE VARIABLE V$S1 VARCHAR(400);
DECLARE VARIABLE V$S2 VARCHAR(100);
begin

  -- Адреса места осуществления образовательной деятельности
  ADDR_DATA = '';
  FOR
    SELECT A.VAL
    FROM LINKS L73
    JOIN LINKS L16 ON L16.PARENT_ID = L73.OBJ_ID AND L16.OBJ_TYPE_ID = 16 AND L16.DATE_DEL IS NULL
    JOIN VALL V485 ON V485.OBJ_ID = L16.OBJ_ID AND V485.PARAM_ID = 485 AND V485.IS_DEL = 0 AND V485.LISTVAL_ID = 1093
    LEFT JOIN ADR_GET(420, L16.OBJ_ID) A ON 1 = 1
    WHERE L73.PARENT_ID = :I$OBJ_ID AND L73.OBJ_TYPE_ID = 73 AND L73.DATE_DEL IS NULL
    INTO :V$S1
  DO
  BEGIN
    IF(CHAR_LENGTH(ADDR_DATA) + CHAR_LENGTH(V$S1) < 990) THEN
    BEGIN
      IF(ADDR_DATA <> '') THEN ADDR_DATA = ADDR_DATA || ', ';
      ADDR_DATA = ADDR_DATA || V$S1;
    END
  END

  LIC_DATA = '';
  ACCR_DATA = '';
  FOR
    SELECT V471.LISTVAL_ID, V483.VAL, V479.VAL, V480.VAL
    FROM LINKS L17
    JOIN VALL V471 ON V471.OBJ_ID = L17.OBJ_ID AND V471.PARAM_ID = 471 AND V471.IS_DEL = 0 AND V471.LISTVAL_ID IN (1052, 1053, 18624, 18625)
    JOIN VALD V482 ON V482.OBJ_ID = L17.OBJ_ID AND V482.PARAM_ID = 482 AND V482.IS_DEL = 0
    LEFT JOIN VALD V483 ON V483.OBJ_ID = L17.OBJ_ID AND V483.PARAM_ID = 483 AND V483.IS_DEL = 0
    JOIN VALL V613 ON V613.OBJ_ID = L17.OBJ_ID AND V613.PARAM_ID = 613 AND V613.IS_DEL = 0 AND V613.LISTVAL_ID IN (1982, 1984)
    JOIN VALS V479 ON V479.OBJ_ID = L17.OBJ_ID AND V479.PARAM_ID = 479 AND V479.IS_DEL = 0
    JOIN VALS V480 ON V480.OBJ_ID = L17.OBJ_ID AND V480.PARAM_ID = 480 AND V480.IS_DEL = 0
    WHERE L17.PARENT_ID = :I$OBJ_ID AND L17.OBJ_TYPE_ID = 17 AND L17.DATE_DEL IS NULL AND (V483.VAL IS NULL OR V483.VAL >= CURRENT_DATE)
    ORDER BY 2
    INTO :V$TYPE_ID, :V$DT, :V$S1, :V$S2
  DO
  BEGIN
    IF(V$TYPE_ID IN (1052, 18624)) THEN
    BEGIN
      IF(LIC_DATA <> '') THEN LIC_DATA = LIC_DATA || ', ';
      LIC_DATA = LIC_DATA || COALESCE(V$S1 || ' ', '') || '№' || V$S2 || ' от ' || (SELECT RESULT FROM DATE2STR(:V$DT));
    END
    IF(V$TYPE_ID IN (1053, 18625)) THEN
    BEGIN
      IF(ACCR_DATA <> '') THEN ACCR_DATA = ACCR_DATA || ', ';
      ACCR_DATA = ACCR_DATA || COALESCE(V$S1 || ' ', '') || '№' || V$S2 || ' от ' || (SELECT RESULT FROM DATE2STR(:V$DT));
    END
  END

  SELECT FIRST 1 V1506.VAL
  FROM LINKS L162
  LEFT JOIN VALDT V1506 ON V1506.OBJ_ID = L162.OBJ_ID AND V1506.PARAM_ID = 1506 AND V1506.IS_DEL = 0
  WHERE L162.PARENT_ID = :I$OBJ_ID AND L162.OBJ_TYPE_ID = 162 AND L162.DATE_DEL IS NULL
  INTO :IO_DATE;

  PRG_VER = '3.23.11.23';
  DG_VER = '1.23.11.23';

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OO_DOC_LIST (
    I$OBJ_ID BIGINT,
    I$PARENT_ID BIGINT)
RETURNS (
    LISTVAL_ID BIGINT,
    PARENT_ID BIGINT,
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$TYPE_ID BIGINT;
begin
  SELECT L529.OBJ_TYPE_ID
  FROM LINKS L529
  WHERE L529.PARENT_ID = :I$PARENT_ID AND L529.OBJ_ID = :I$OBJ_ID AND L529.DATE_DEL IS NULL
  INTO :V$TYPE_ID;

  -- вывести документы (положения) для органа управления ОО
  IF (V$TYPE_ID = 529) THEN
  BEGIN
    FOR
      SELECT L17.OBJ_ID, NULL, V596.VAL
      FROM LINKS L17
      JOIN VALS V596 ON V596.OBJ_ID = L17.OBJ_ID AND V596.PARAM_ID = 596 AND V596.IS_DEL = 0
      JOIN VALL V471 ON V471.OBJ_ID = L17.OBJ_ID AND V471.PARAM_ID = 471 AND V471.IS_DEL = 0 AND V471.LISTVAL_ID IN (1047, 18635) -- устав, положение
      WHERE L17.OBJ_TYPE_ID = 17 AND L17.PARENT_TYPE_ID = 2 AND L17.DATE_DEL IS NULL
      ORDER BY V471.LISTVAL_ID
      INTO :LISTVAL_ID, :PARENT_ID, :VAL
    DO
    BEGIN
      SUSPEND;
    END
    EXIT;
  END
  ELSE IF (V$TYPE_ID = 211) THEN
  BEGIN
    FOR
      SELECT L17.OBJ_ID, NULL, V596.VAL
      FROM LINKS L17
      JOIN VALS V596 ON V596.OBJ_ID = L17.OBJ_ID AND V596.PARAM_ID = 596 AND V596.IS_DEL = 0
      WHERE L17.OBJ_TYPE_ID = 17 AND L17.PARENT_TYPE_ID = 530 AND L17.DATE_DEL IS NULL    -- локальные
      ORDER BY V596.VAL
      INTO :LISTVAL_ID, :PARENT_ID, :VAL
    DO
    BEGIN
      SUSPEND;
    END
    EXIT;
  END

  SUSPEND;
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OO_DOC_TYPE_LIST (
    I$OBJ_ID BIGINT,
    I$PARENT_ID BIGINT)
RETURNS (
    LISTVAL_ID BIGINT,
    PARENT_ID BIGINT,
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$TYPE_ID BIGINT;
DECLARE VARIABLE V$PARENT_TYPE_ID BIGINT;
begin
  SELECT L529.OBJ_TYPE_ID, L529.PARENT_TYPE_ID
  FROM LINKS L529
  WHERE L529.PARENT_ID = :I$PARENT_ID AND L529.OBJ_ID = :I$OBJ_ID AND L529.DATE_DEL IS NULL
  INTO :V$TYPE_ID, :V$PARENT_TYPE_ID;

  FOR
    SELECT LV.LISTVAL_ID, LV.PARENT_ID, CAP.VAL
    FROM LISTVALS LV
    LEFT JOIN LISTVAL_TEXT(LV.LISTVAL_ID) CAP ON 1 = 1
    WHERE LV.LIST_ID = 9 AND LV.IS_DEL = 0
    AND (
      (:V$PARENT_TYPE_ID = 530 AND LV.LISTVAL_ID = 18627)  -- локальный акт ОООД
      OR (:V$PARENT_TYPE_ID = 2 AND LV.LISTVAL_ID <> 18627)  -- локальный акт ОООД
      OR :V$PARENT_TYPE_ID IS NULL -- для поиска
    )
    INTO :LISTVAL_ID, :PARENT_ID, :VAL
  DO
  BEGIN
    SUSPEND;
  END

  SUSPEND;
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OO_FILTRED_LIST (
    I$LIST_ID BIGINT,
    I$USER_ID BIGINT = null,
    I$MAX_LEVEL SMALLINT = 0)
RETURNS (
    LISTVAL_ID BIGINT,
    PARENT_ID BIGINT,
    VAL VARCHAR(4000),
    VAL_LONG VARCHAR(4000),
    TAG VARCHAR(100),
    "FILTER" VARCHAR(255),
    COST FLOAT,
    SORT_ORDER SMALLINT)
AS
declare variable V$OU_LICENCE_TYPE varchar(1);
declare variable V$OU_PROJECT_TYPE varchar(25);
declare variable RES_ID bigint;
declare variable LANG_CODE varchar(2);
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :LANG_CODE;

    SELECT STATUS FROM OU_LICENCE_TYPE INTO :V$OU_LICENCE_TYPE;
    SELECT STATUS FROM PROJECT_TYPE INTO :V$OU_PROJECT_TYPE;

    FOR
        SELECT LISTVAL_ID, PARENT_ID, TAG, RES_ID, "FILTER", COST, SORT_ORDER
        FROM LISTVALS
        WHERE (
            ((:V$OU_LICENCE_TYPE = 'D') AND ("FILTER" SIMILAR TO '%DOU%')) OR
            ((:V$OU_LICENCE_TYPE = 'O') AND ("FILTER" SIMILAR TO '%GOU%')) OR
            ((:V$OU_LICENCE_TYPE = 'C') AND ("FILTER" SIMILAR TO '%COLLEGE%')) OR
            ((:V$OU_LICENCE_TYPE = 'U') AND ("FILTER" SIMILAR TO '%UDOD%')) OR
            ((:V$OU_LICENCE_TYPE = 'P') AND ("FILTER" SIMILAR TO '%DPO%')) OR
            ((:V$OU_LICENCE_TYPE = 'S') AND ("FILTER" SIMILAR TO '%MULT%'))
        )
        AND (
            ((:V$OU_PROJECT_TYPE = 'Апостроф') AND ("FILTER" SIMILAR TO '%APF%')) OR
            ((:V$OU_PROJECT_TYPE = 'Параграф') AND ("FILTER" SIMILAR TO '%PRG3%'))
        )
        AND ((:I$MAX_LEVEL = 0) OR ((SELECT "LEVEL" FROM LISTVAL_LEVEL(LISTVAL_ID)) <= :I$MAX_LEVEL))
        AND LIST_ID = :I$LIST_ID AND IS_DEL = 0
        ORDER BY SORT_ORDER

        INTO :LISTVAL_ID, :PARENT_ID, :TAG, :RES_ID, :"FILTER", :COST, :SORT_ORDER
    DO
    BEGIN
        SELECT VAL, VAL_LONG
        FROM RES_GET(:RES_ID, :LANG_CODE)
        INTO :VAL, :VAL_LONG;
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OO_GRADES_LIST (
    OBJ_ID BIGINT,
    USER_ID BIGINT = 1)
RETURNS (
    LISTVAL_ID BIGINT,
    PARENT_ID BIGINT,
    VAL VARCHAR(4000),
    VAL_LONG VARCHAR(4000),
    TAG VARCHAR(100),
    "FILTER" VARCHAR(255))
AS
DECLARE VARIABLE V$OP_TYPE BIGINT;
DECLARE VARIABLE V$OP_TYPE2 BIGINT;
DECLARE VARIABLE V$PARENT_FILTER BIGINT;
DECLARE VARIABLE V$PARENT_FILTER2 BIGINT;
DECLARE VARIABLE V$OVZ BIGINT;
DECLARE VARIABLE V$VD BIGINT;
begin

    -- Для школьных этапов необходимо выставить дополнительный фильтр
    SELECT FIRST 1 V2450.LISTVAL_ID, V1832.LISTVAL_ID, V2379.LISTVAL_ID, V2545.LISTVAL_ID
    FROM LINKS LP50
    JOIN VALL V2545 ON V2545.OBJ_ID = LP50.PARENT_ID AND V2545.PARAM_ID IN (2545, 3022) AND V2545.IS_DEL = 0
    JOIN LINKS LP57 ON LP57.OBJ_ID = LP50.PARENT_ID AND LP57.PARENT_TYPE_ID = 57 AND LP57.DATE_DEL IS NULL
    JOIN VALL V2379 ON V2379.OBJ_ID = LP57.PARENT_ID AND V2379.PARAM_ID = 2379 AND V2379.IS_DEL = 0
    JOIN VALL V1832 ON V1832.OBJ_ID = LP57.PARENT_ID AND V1832.PARAM_ID = 1832 AND V1832.IS_DEL = 0
    JOIN LINKS LP69 ON LP69.OBJ_ID = LP57.PARENT_ID AND LP69.PARENT_TYPE_ID = 69 AND LP69.DATE_DEL IS NULL
    JOIN VALL V2450 ON V2450.OBJ_ID = LP69.PARENT_ID AND V2450.PARAM_ID = 2450 AND V2450.IS_DEL = 0
    WHERE LP50.OBJ_ID = :OBJ_ID AND LP50.PARENT_TYPE_ID IN (50, 400) AND LP50.DATE_DEL IS NULL
    INTO :V$OP_TYPE, :V$OP_TYPE2, :V$OVZ, :V$VD;

    IF(V$OP_TYPE IS NULL) THEN
    BEGIN
      SELECT FIRST 1 V3345.LISTVAL_ID, V2545.LISTVAL_ID
      FROM LINKS LP50
      JOIN VALL V2545 ON V2545.OBJ_ID = LP50.PARENT_ID AND V2545.PARAM_ID IN (2545, 3022) AND V2545.IS_DEL = 0
      JOIN VALL V3345 ON V3345.OBJ_ID = LP50.PARENT_ID AND V3345.PARAM_ID = 3345 AND V3345.IS_DEL = 0
      JOIN LINKS LP55 ON LP55.OBJ_ID = LP50.PARENT_ID AND LP55.PARENT_TYPE_ID = 55 AND LP55.DATE_DEL IS NULL
      WHERE LP50.OBJ_ID = :OBJ_ID AND LP50.PARENT_TYPE_ID IN (50, 400) AND LP50.DATE_DEL IS NULL
      INTO :V$OP_TYPE, :V$VD;
      -- V$OVZ ???
    END

    -- В кодах надо учитывать и вариант из 2450, и из 3345
    -- Общее образование - фильтр только из обычных предметов
    -- Тут школы и ДОУ
    IF(V$OP_TYPE IN (11385, 5337, 5338, 5339, 5341, 5343)) THEN
    BEGIN
      IF(V$OP_TYPE2 IN (5337, 5338)) THEN V$PARENT_FILTER = 2140; ELSE V$PARENT_FILTER = 2141;
    END
    -- АООП с аутизмом - все варианты
    ELSE IF(V$OP_TYPE = 13270) THEN
    BEGIN
      V$PARENT_FILTER = 2141;
      V$PARENT_FILTER2 = 12941;
    END
    -- СПО
    ELSE IF(V$OP_TYPE = 11387) THEN
    BEGIN
      V$PARENT_FILTER = 2142;
    END

    -- Для адаптированных ОП - также оба варианта выбора
    IF(V$OVZ <> 11187) THEN BEGIN
      V$PARENT_FILTER = 2141;
      V$PARENT_FILTER2 = 12941;
    END

    FOR
      SELECT LISTVAL_ID, PARENT_ID, VAL, VAL_LONG, TAG, "FILTER"
      -- FROM OO_FILTRED_LIST(25, :USER_ID)
      FROM OBJECT_LISTVALS_LIST(25, :USER_ID)
      WHERE LISTVAL_ID NOT IN (SELECT STAGE_TYPE_ID FROM CURRICULUM_STAGE_LIST(:OBJ_ID)) AND
        (:V$PARENT_FILTER IS NULL OR (PARENT_ID = :V$PARENT_FILTER OR LISTVAL_ID = :V$PARENT_FILTER OR PARENT_ID = :V$PARENT_FILTER2 OR LISTVAL_ID = :V$PARENT_FILTER2))
      INTO :LISTVAL_ID, :PARENT_ID, :VAL, :VAL_LONG, :TAG, :"FILTER"
    DO
    BEGIN
      SUSPEND;
    END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OO_LEVEL_LIST (
    I$OBJ_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    PARENT_ID BIGINT,
    LISTVAL_ID BIGINT,
    VAL VARCHAR(4000),
    VAL_LONG VARCHAR(4000),
    TAG VARCHAR(100),
    "FILTER" VARCHAR(255))
AS
DECLARE VARIABLE V$PARENT_TYPE_ID BIGINT;
DECLARE VARIABLE N INTEGER;
begin

  SELECT FIRST 1 LP.PARENT_TYPE_ID
  FROM LINKS LP
  WHERE LP.OBJ_ID = :I$OBJ_ID AND LP.PARENT_TYPE_ID IN (2, 211) AND LP.DATE_DEL IS NULL
  INTO :V$PARENT_TYPE_ID;

  -- Пересекаем с видами деятельности ОО в описательной части
  -- В подразделениях не даем выбирать ОО и СПО
  N = 0;
  FOR
    SELECT L.PARENT_ID, L.LISTVAL_ID, L.VAL, L.VAL_LONG, L.TAG, L."FILTER"
    FROM OO_FILTRED_LIST(19, :I$USER_ID) L
    WHERE EXISTS(
      SELECT FIRST 1 1
      FROM LINKS L2
      JOIN LINKS L472 ON L472.PARENT_ID = L2.OBJ_ID AND L472.OBJ_TYPE_ID = 472 AND L472.DATE_DEL IS NULL
      JOIN VALL V3327 ON V3327.OBJ_ID = L472.OBJ_ID AND V3327.PARAM_ID = 3327 AND V3327.IS_DEL = 0
      JOIN LISTVALS LV ON LV.LISTVAL_ID = V3327.LISTVAL_ID AND (LV.LISTVAL_ID = L.LISTVAL_ID OR LV.PARENT_ID = L.LISTVAL_ID)
      WHERE (L2.PARENT_ID IS NULL OR L2.PARENT_TYPE_ID IN (111, 112)) AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    )
    INTO :PARENT_ID, :LISTVAL_ID, :VAL, :VAL_LONG, :TAG, :"FILTER"
  DO
  BEGIN
    IF(V$PARENT_TYPE_ID IS NULL OR V$PARENT_TYPE_ID <> 211 OR LISTVAL_ID NOT IN (22, 26, 27, 29)) THEN
    BEGIN
      SUSPEND;
      N = N + 1;
    END
  END

  IF(N = 0) THEN EXCEPTION DATA_ERROR 'Нет доступных для выбора ступеней обучения. Проверьте, всесены ли виды образовательной деятельности в сведения об ОО';

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OO_ROOM_TYPE_LIST (
    I$USER_ID BIGINT)
RETURNS (
    LISTVAL_ID BIGINT,
    PARENT_ID BIGINT,
    VAL VARCHAR(4000),
    VAL_LONG VARCHAR(4000),
    TAG VARCHAR(100),
    "FILTER" VARCHAR(255),
    COST FLOAT,
    SORT_ORDER SMALLINT)
AS
DECLARE VARIABLE LANG_CODE VARCHAR(10);
DECLARE VARIABLE V$ID BIGINT;
DECLARE VARIABLE V$PARENT_ID BIGINT;
DECLARE VARIABLE V$IS_DOU SMALLINT;
DECLARE VARIABLE V$IS_GOU SMALLINT;
DECLARE VARIABLE V$IS_SPO SMALLINT;
DECLARE VARIABLE V$IS_UDOD SMALLINT;
DECLARE VARIABLE V$IS_DPO SMALLINT;
DECLARE VARIABLE RES_ID BIGINT;
begin
  SELECT LANG_CODE
  FROM USERS
  WHERE USER_ID = :I$USER_ID
  INTO :LANG_CODE;

  -- получим виды оказываемой деятельности, 472 тип
  FOR
    SELECT DISTINCT LV.PARENT_ID, LV.LISTVAL_ID
    FROM LINKS L472
    JOIN VALL V3327 ON V3327.OBJ_ID = L472.OBJ_ID AND V3327.PARAM_ID = 3327 AND V3327.IS_DEL = 0
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V3327.LISTVAL_ID AND LV.LIST_ID = 19 AND LV.IS_DEL = 0
    WHERE L472.PARENT_TYPE_ID = 2 AND L472.OBJ_TYPE_ID = 472 AND L472.DATE_DEL IS NULL
    INTO :V$PARENT_ID, :V$ID
  DO
  BEGIN
    IF (V$IS_DOU IS NULL AND V$PARENT_ID = 21) THEN V$IS_DOU = 1;
    IF (V$IS_GOU IS NULL AND V$ID IN (22, 26, 27)) THEN V$IS_GOU = 1;
    IF (V$IS_SPO IS NULL AND V$ID = 29) THEN V$IS_SPO = 1;
    IF (V$IS_UDOD IS NULL AND V$ID = 13128) THEN V$IS_UDOD = 1;
    IF (V$IS_DPO IS NULL AND V$PARENT_ID = 13130) THEN V$IS_DPO = 1;
  END

  IF(V$IS_DOU IS NULL AND V$IS_GOU IS NULL AND V$IS_SPO IS NULL AND V$IS_UDOD IS NULL AND V$IS_DPO IS NULL) THEN
    EXCEPTION DATA_ERROR 'Требуется сначала заполнить список видов выполняемой образовательной деятельности ОУ';

  FOR
    SELECT LV.LISTVAL_ID, LV.PARENT_ID, LV.TAG, LV.RES_ID, LV."FILTER", LV.COST, LV.SORT_ORDER
    FROM LISTVALS LV
    WHERE LV.LIST_ID = 20 AND LV.IS_DEL = 0 AND (
      ((:V$IS_DOU = 1) AND (LV."FILTER" SIMILAR TO '%DOU %')) OR
      ((:V$IS_GOU = 1) AND (LV."FILTER" SIMILAR TO '%GOU %')) OR
      ((:V$IS_SPO = 1) AND (LV."FILTER" SIMILAR TO '%COLLEGE %')) OR
      ((:V$IS_UDOD = 1) AND (LV."FILTER" SIMILAR TO '%UDOD %')) OR
      ((:V$IS_DPO = 1) AND (LV."FILTER" SIMILAR TO '%DPO %'))
    )
    ORDER BY SORT_ORDER
    INTO :LISTVAL_ID, :PARENT_ID, :TAG, :RES_ID, :"FILTER", :COST, :SORT_ORDER
  DO
  BEGIN
    SELECT VAL, IIF(VAL_LONG IS NULL OR VAL_LONG = '', VAL, VAL_LONG)
    FROM RES_GET(:RES_ID, :LANG_CODE)
    INTO :VAL, :VAL_LONG;
    SUSPEND;
  END
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OO_SPECIALITY_LINK_CREATE (
    I$OP_ID BIGINT)
AS
declare variable V$SCHOOL_ID bigint;
declare variable V$SPECIALITY_LINK_ID bigint;
declare variable V$BLOB_ID bigint;
declare variable V$SPECIALITY_ID bigint;
declare variable V$SPECIALITY_CODE varchar(255);
BEGIN
    FOR
        SELECT LP2.PARENT_ID
        FROM LINKS LP69

        JOIN LINKS LP2
        ON LP2.OBJ_ID = LP69.PARENT_ID
        AND LP2.PARENT_TYPE_ID = 2
        AND LP2.DATE_DEL IS NULL

        WHERE LP69.OBJ_ID = :I$OP_ID
        AND LP69.PARENT_TYPE_ID = 69
        AND LP69.DATE_DEL IS NULL
        INTO :V$SCHOOL_ID
    DO
    BEGIN
        SELECT L207.OBJ_ID
        FROM LINKS L207

        JOIN VALR V1784
        ON V1784.OBJ_ID = L207.OBJ_ID
        AND V1784.PARAM_ID = 1784
        AND V1784.IS_DEL = 0
        AND V1784.VAL = :I$OP_ID

        WHERE L207.PARENT_ID = :V$SCHOOL_ID
        AND L207.OBJ_TYPE_ID = 207
        AND L207.DATE_DEL IS NULL
        INTO :V$SPECIALITY_LINK_ID;

        IF (V$SPECIALITY_LINK_ID IS NULL) THEN
        BEGIN
            INSERT INTO OBJECTS(TYPE_ID) VALUES (207)
            RETURNING OBJ_ID INTO :V$SPECIALITY_LINK_ID;

            IF (V$SPECIALITY_LINK_ID IS NOT NULL) THEN
            BEGIN
                INSERT INTO LINKS(PARENT_ID,OBJ_ID,DATE_INS) VALUES(:V$SCHOOL_ID, :V$SPECIALITY_LINK_ID,CURRENT_TIMESTAMP);
            END
        END
        IF (V$SPECIALITY_LINK_ID IS NOT NULL) THEN
        BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD(1784, :V$SPECIALITY_LINK_ID, :I$OP_ID)
            INTO :V$BLOB_ID;

            SELECT LISTVAL_ID
            FROM VALL
            WHERE OBJ_ID = :I$OP_ID
            AND PARAM_ID = 1753
            AND IS_DEL = 0

            INTO :V$SPECIALITY_ID;

            IF (V$SPECIALITY_ID IS NOT NULL) THEN
            BEGIN
                SELECT BLOB_ID
                FROM VAL_ADD(1782, :V$SPECIALITY_LINK_ID, :V$SPECIALITY_ID)
                INTO :V$BLOB_ID;
            END
            ELSE
            BEGIN
                UPDATE VALL
                SET IS_DEL = 1
                WHERE OBJ_ID = :V$SPECIALITY_LINK_ID
                AND PARAM_ID = 1782;
            END

            SELECT VAL
            FROM VALS
            WHERE OBJ_ID = :I$OP_ID
            AND PARAM_ID = 1754
            AND IS_DEL = 0
    
            INTO :V$SPECIALITY_CODE;

            IF (V$SPECIALITY_CODE IS NOT NULL) THEN
            BEGIN
                SELECT BLOB_ID
                FROM VAL_ADD(1783, :V$SPECIALITY_LINK_ID, :V$SPECIALITY_CODE)
                INTO :V$BLOB_ID;
            END
            ELSE
            BEGIN
                UPDATE VALS
                SET IS_DEL = 1
                WHERE OBJ_ID = :V$SPECIALITY_LINK_ID
                AND PARAM_ID = 1783;
            END
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OO_SPECIALITY_LINK_DELETE (
    I$OP_ID BIGINT)
AS
DECLARE VARIABLE V$SCHOOL_ID BIGINT;
DECLARE VARIABLE V$SPECIALITY_LINK_ID BIGINT;
DECLARE VARIABLE V$DEL_COUNT BIGINT;
BEGIN
    FOR
        SELECT LP2.PARENT_ID
        FROM LINKS LP69

        JOIN LINKS LP2
        ON LP2.OBJ_ID = LP69.PARENT_ID
        AND LP2.PARENT_TYPE_ID = 2
        AND LP2.DATE_DEL IS NULL

        WHERE LP69.OBJ_ID = :I$OP_ID
        AND LP69.PARENT_TYPE_ID = 69
        AND LP69.DATE_DEL IS NULL
        INTO :V$SCHOOL_ID
    DO
    BEGIN
        SELECT L207.OBJ_ID
        FROM LINKS L207

        JOIN VALR V1784
        ON V1784.OBJ_ID = L207.OBJ_ID
        AND V1784.PARAM_ID = 1784
        AND V1784.IS_DEL = 0
        AND V1784.VAL = :I$OP_ID

        WHERE L207.PARENT_ID = :V$SCHOOL_ID
        AND L207.OBJ_TYPE_ID = 207
        AND L207.DATE_DEL IS NULL
        INTO :V$SPECIALITY_LINK_ID;

        IF (V$SPECIALITY_LINK_ID IS NOT NULL) THEN
        BEGIN
            SELECT DEL_COUNT FROM OBJECT_DEL(:V$SCHOOL_ID, :V$SPECIALITY_LINK_ID) INTO V$DEL_COUNT;
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OO_STAGE_BASE_LIST (
    I$LIST_ID BIGINT,
    I$USER_ID BIGINT = null)
RETURNS (
    LISTVAL_ID BIGINT,
    PARENT_ID BIGINT,
    VAL VARCHAR(4000),
    VAL_LONG VARCHAR(4000),
    TAG VARCHAR(100),
    "FILTER" VARCHAR(255))
AS
declare variable V$OU_LICENCE_TYPE varchar(1);
declare variable RES_ID bigint;
declare variable LANG_CODE varchar(2);
declare variable N integer;
BEGIN

    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :LANG_CODE;

    SELECT STATUS FROM OU_LICENCE_TYPE INTO :V$OU_LICENCE_TYPE;

    -- PARENT_ID не выдаем, чтобы не путать список
    -- список тут всегда 25 !

    N = 0;
    FOR
        SELECT L.LISTVAL_ID, L.TAG, L.RES_ID, L."FILTER"
        FROM LISTVALS L
        WHERE (
            (:V$OU_LICENCE_TYPE = 'D' AND L.PARENT_ID = 2140) OR
            (:V$OU_LICENCE_TYPE = 'O' AND L.PARENT_ID IN (2141, 12941)) OR
            (:V$OU_LICENCE_TYPE = 'C' AND L.PARENT_ID = 2142) OR
            (:V$OU_LICENCE_TYPE = 'U' AND L."FILTER" SIMILAR TO '%UDOD%' AND L.PARENT_ID IS NOT NULL) OR
            (:V$OU_LICENCE_TYPE = 'S')
        )
        AND L.LIST_ID = :I$LIST_ID AND L.IS_DEL = 0 AND L.PARENT_ID IS NOT NULL
        -- Отсекаем уровни образования, не предусмотренные для данной ОУ
        AND EXISTS(
          SELECT FIRST 1 1
          FROM LINKS L2
          JOIN LINKS L472 ON L472.PARENT_ID = L2.OBJ_ID AND L472.OBJ_TYPE_ID = 472 AND L472.DATE_DEL IS NULL
          JOIN VALL V3327 ON V3327.OBJ_ID = L472.OBJ_ID AND V3327.PARAM_ID = 3327 AND V3327.IS_DEL = 0 AND (
            (V3327.LISTVAL_ID IN (3263, 3264) AND L.PARENT_ID = 2140) OR
            (V3327.LISTVAL_ID IN (22, 26, 27) AND L.PARENT_ID IN (2141, 12941)) OR
            (V3327.LISTVAL_ID IN (29, 13131) AND L.PARENT_ID = 2142) -- OR пока без ОДОД
          )
          WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
        )
        ORDER BY L.PARENT_ID, L.SORT_ORDER
        INTO :LISTVAL_ID, :TAG, :RES_ID, :"FILTER"
    DO
    BEGIN
        SELECT VAL, VAL_LONG
        FROM RES_GET(:RES_ID, :LANG_CODE)
        INTO :VAL, :VAL_LONG;

        N = N + 1;
        SUSPEND;
    END

    IF(N = 0) THEN EXCEPTION DATA_ERROR 'Нет доступных для выбора этапов обучения. Проверьте, всесены ли виды образовательной деятельности в сведения об ОО';

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OO_STAGE_LIST (
    I$OBJ_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    PARENT_ID BIGINT,
    LISTVAL_ID BIGINT,
    VAL VARCHAR(4000),
    VAL_LONG VARCHAR(4000),
    TAG VARCHAR(100),
    "FILTER" VARCHAR(255),
    COST FLOAT)
AS
DECLARE VARIABLE V$PARENT_ID BIGINT;
DECLARE VARIABLE V$LEVEL_ID BIGINT;
DECLARE VARIABLE V$OU_LICENCE_TYPE VARCHAR(2);
DECLARE VARIABLE LANG_CODE VARCHAR(10);
DECLARE VARIABLE RES_ID BIGINT;
DECLARE VARIABLE V$P1 BIGINT;
DECLARE VARIABLE V$P2 BIGINT;
DECLARE VARIABLE V$P3 BIGINT;
DECLARE VARIABLE V$P4 BIGINT;
DECLARE VARIABLE V$PARENT_TYPE BIGINT;
DECLARE VARIABLE V$HAS_DOU SMALLINT;
DECLARE VARIABLE V$HAS_OU SMALLINT;
DECLARE VARIABLE V$HAS_SPO SMALLINT;
begin

  SELECT LANG_CODE
  FROM USERS
  WHERE USER_ID = :I$USER_ID
  INTO :LANG_CODE;

  SELECT STATUS FROM OU_LICENCE_TYPE INTO :V$OU_LICENCE_TYPE;

  -- Кейс для выборки #8
  SELECT FIRST 1 LP7.PARENT_ID, LP7.PARENT_TYPE_ID, V43.LISTVAL_ID
  FROM LINKS LP7
  LEFT JOIN VALL V43 ON V43.OBJ_ID = LP7.PARENT_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0
  WHERE LP7.OBJ_ID = :I$OBJ_ID AND LP7.PARENT_TYPE_ID IN (7, 502) AND LP7.DATE_DEL IS NULL
  INTO :V$PARENT_ID, :V$PARENT_TYPE, :V$LEVEL_ID;

  IF(V$PARENT_TYPE = 502) THEN V$LEVEL_ID = 27; -- конкретный id несущественен, дофильтровываем дальше для 9 и 11

  -- Если I$OBJ_ID пустой, это выборка для построителя отчетов
  IF(I$OBJ_ID IS NOT NULL AND V$LEVEL_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Сначала необходимо выбрать уровень образования';

  -- IN (2140, 2141, 12941, 2142, 2143, 2155)
  IF(V$LEVEL_ID IN (3263, 3264)) THEN
  BEGIN
    -- Ясли, сад
    V$P1 = 2140;
  END
  ELSE IF(V$LEVEL_ID IN (22, 26, 27)) THEN
  BEGIN
    -- Школа
    V$P1 = 2141;
    V$P2 = 12941;
  END
  ELSE IF(V$LEVEL_ID IN (29, 13131)) THEN
  BEGIN
    -- СПО и проф обучение
    V$P1 = 2142;
  END
  ELSE IF(V$LEVEL_ID IN (13128, 13129)) THEN
  BEGIN
    -- ОДОД ???
    -- V$P1 = 2143;
    -- V$P1 = 2155;
  END

  --
  IF(I$OBJ_ID IS NULL) THEN
  BEGIN
    IF(V$OU_LICENCE_TYPE = 'S') THEN
    BEGIN
      SELECT FIRST 1 1
      FROM LINKS L472
      JOIN VALL V3327 ON V3327.OBJ_ID = L472.OBJ_ID AND V3327.PARAM_ID = 3327 AND V3327.IS_DEL = 0 AND V3327.LISTVAL_ID IN (3263, 3264)
      WHERE L472.PARENT_TYPE_ID = 2 AND L472.OBJ_TYPE_ID = 472 AND L472.DATE_DEL IS NULL
      INTO :V$HAS_DOU;

      SELECT FIRST 1 1
      FROM LINKS L472
      JOIN VALL V3327 ON V3327.OBJ_ID = L472.OBJ_ID AND V3327.PARAM_ID = 3327 AND V3327.IS_DEL = 0 AND V3327.LISTVAL_ID IN (22, 26, 27)
      WHERE L472.PARENT_TYPE_ID = 2 AND L472.OBJ_TYPE_ID = 472 AND L472.DATE_DEL IS NULL
      INTO :V$HAS_OU;

      SELECT FIRST 1 1
      FROM LINKS L472
      JOIN VALL V3327 ON V3327.OBJ_ID = L472.OBJ_ID AND V3327.PARAM_ID = 3327 AND V3327.IS_DEL = 0 AND V3327.LISTVAL_ID IN (28, 29, 13131)
      WHERE L472.PARENT_TYPE_ID = 2 AND L472.OBJ_TYPE_ID = 472 AND L472.DATE_DEL IS NULL
      INTO :V$HAS_SPO;
    END

    IF(V$OU_LICENCE_TYPE = 'D' OR V$HAS_DOU = 1) THEN
    BEGIN
      V$P1 = 2140;
    END
    IF(V$OU_LICENCE_TYPE = 'O' OR V$HAS_OU = 1) THEN
    BEGIN
      -- Школа
      V$P2 = 2141;
      V$P3 = 12941;
    END
    IF(V$OU_LICENCE_TYPE = 'C' OR V$HAS_SPO = 1) THEN
    BEGIN
      -- СПО и проф обучение
      V$P4 = 2142;
    END
  END

  -- PARENT_ID не выдаем

  -- Не даем выбирать два раза один и тот же этап обучения в одном уровне
  FOR
    SELECT L.LISTVAL_ID, L.TAG, L.RES_ID, L."FILTER", L.COST
    FROM LISTVALS L
    WHERE L.LIST_ID = 25 AND L.IS_DEL = 0 AND (
      (:V$OU_LICENCE_TYPE = 'D' AND L.PARENT_ID = 2140) OR
      (:V$OU_LICENCE_TYPE = 'O' AND L.PARENT_ID IN (2141, 12941)) OR
      (:V$OU_LICENCE_TYPE = 'C' AND L.PARENT_ID = 2142) OR
      (:V$OU_LICENCE_TYPE = 'U' AND "FILTER" SIMILAR TO '%UDOD%' AND PARENT_ID IS NOT NULL) OR -- 2143, 2155
      -- для мультипараграфа ограничиваем в пределах положенного уровня образования
      -- выбираем только плоский список в пределах раздела
      (:V$OU_LICENCE_TYPE = 'S' AND (L.PARENT_ID = :V$P1 OR L.PARENT_ID = :V$P2 OR L.PARENT_ID = :V$P3 OR L.PARENT_ID = :V$P4))
    )
    -- прячем уже выбранные
    AND NOT EXISTS (
      SELECT FIRST 1 1
      FROM LINKS L8
      JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0 AND V49.LISTVAL_ID = L.LISTVAL_ID
      WHERE L8.PARENT_ID = :V$PARENT_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL AND L8.OBJ_ID <> :I$OBJ_ID
    )
    AND (:V$PARENT_TYPE IS NULL OR :V$PARENT_TYPE <> 502 OR L.LISTVAL_ID IN (45, 47))
    ORDER BY L.SORT_ORDER
    INTO :LISTVAL_ID, :TAG, :RES_ID, :"FILTER", :COST
  DO
  BEGIN
    SELECT VAL, VAL_LONG
    FROM RES_GET(:RES_ID, :LANG_CODE)
    INTO :VAL, :VAL_LONG;

    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OO_STUDY_ACPT_LIST (
    I$OBJ_ID BIGINT)
RETURNS (
    LISTVAL_ID BIGINT,
    PARENT_ID BIGINT,
    VAL VARCHAR(4000),
    VAL_LONG VARCHAR(4000),
    TAG VARCHAR(100),
    "FILTER" VARCHAR(255),
    COST FLOAT,
    SORT_ORDER SMALLINT)
AS
DECLARE VARIABLE V$TYPE_ID BIGINT;
DECLARE VARIABLE V$SUB_ID BIGINT;
DECLARE VARIABLE V$IS_DOU SMALLINT;
DECLARE VARIABLE V$IS_GOU SMALLINT;
DECLARE VARIABLE V$IS_SPO SMALLINT;
DECLARE VARIABLE V$IS_UDOD SMALLINT;
DECLARE VARIABLE V$IS_DPO SMALLINT;
begin
  SELECT TYPE_ID
  FROM OBJECTS
  WHERE OBJ_ID = :I$OBJ_ID
  INTO :V$TYPE_ID;

  -- Если это - учебный план, смотрим тип ОП
  IF(V$TYPE_ID = 400) THEN
  BEGIN
    SELECT FIRST 1 V1594.LISTVAL_ID
    FROM LINKS L400
    JOIN VALL V1594 ON V1594.OBJ_ID = L400.PARENT_ID AND V1594.PARAM_ID = 1594 AND V1594.IS_DEL = 0
    WHERE L400.OBJ_ID = :I$OBJ_ID AND L400.PARENT_TYPE_ID = 57 AND L400.DATE_DEL IS NULL
    INTO :V$SUB_ID;

    IF(V$SUB_ID = 5337) THEN V$IS_DOU = 1;
    IF(V$SUB_ID IN (5339, 5341, 5343)) THEN V$IS_GOU = 1;
    IF(V$SUB_ID = 5346) THEN V$IS_SPO = 1;
    IF(V$SUB_ID IN (5361, 5364)) THEN V$IS_DPO = 1;
    IF(V$SUB_ID = 5358) THEN V$IS_UDOD = 1;
  END

  FOR
    SELECT LV.LISTVAL_ID, LV.PARENT_ID, LV.TAG, LV."FILTER", LV.COST, LV.SORT_ORDER, R.VAL, R.VAL_LONG
    FROM LISTVALS LV
    JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
    WHERE LV.LIST_ID = 242 AND LV.IS_DEL = 0 AND (
      ((:V$IS_DOU = 1) AND (LV."FILTER" SIMILAR TO '%DOU %')) OR
      ((:V$IS_GOU = 1) AND (LV."FILTER" SIMILAR TO '%GOU %')) OR
      ((:V$IS_SPO = 1) AND (LV."FILTER" SIMILAR TO '%COLLEGE %')) OR
      ((:V$IS_UDOD = 1) AND (LV."FILTER" SIMILAR TO '%UDOD %')) OR
      ((:V$IS_DPO = 1) AND (LV."FILTER" SIMILAR TO '%DPO %'))
    )
    ORDER BY SORT_ORDER
    INTO :LISTVAL_ID, :PARENT_ID, :TAG, :"FILTER", :COST, :SORT_ORDER, :VAL, :VAL_LONG
  DO
  BEGIN
    SUSPEND;
  END
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OO_STUDY_FORM_LIST (
    I$OBJ_ID BIGINT)
RETURNS (
    LISTVAL_ID BIGINT,
    PARENT_ID BIGINT,
    VAL VARCHAR(4000),
    VAL_LONG VARCHAR(4000),
    TAG VARCHAR(100),
    "FILTER" VARCHAR(255),
    COST FLOAT,
    SORT_ORDER SMALLINT)
AS
DECLARE VARIABLE V$TYPE_ID BIGINT;
DECLARE VARIABLE V$SUB_ID BIGINT;
DECLARE VARIABLE V$IS_DOU SMALLINT;
DECLARE VARIABLE V$IS_GOU SMALLINT;
DECLARE VARIABLE V$IS_SPO SMALLINT;
DECLARE VARIABLE V$IS_UDOD SMALLINT;
DECLARE VARIABLE V$IS_DPO SMALLINT;
begin
  SELECT TYPE_ID
  FROM OBJECTS
  WHERE OBJ_ID = :I$OBJ_ID
  INTO :V$TYPE_ID;

  -- Если это - учебный план, смотрим тип ОП
  IF(V$TYPE_ID = 400) THEN
  BEGIN
    SELECT FIRST 1 V1594.LISTVAL_ID
    FROM LINKS L400
    JOIN VALL V1594 ON V1594.OBJ_ID = L400.PARENT_ID AND V1594.PARAM_ID = 1594 AND V1594.IS_DEL = 0
    WHERE L400.OBJ_ID = :I$OBJ_ID AND L400.PARENT_TYPE_ID = 57 AND L400.DATE_DEL IS NULL
    INTO :V$SUB_ID;

    IF(V$SUB_ID IN (5337)) THEN V$IS_DOU = 1;
    IF(V$SUB_ID IN (5339, 5341, 5343, 13272)) THEN V$IS_GOU = 1;
    IF(V$SUB_ID IN (5346)) THEN V$IS_SPO = 1;
    IF(V$SUB_ID IN (5358)) THEN V$IS_UDOD = 1;
    IF(V$SUB_ID IN (5361)) THEN V$IS_DPO = 1;
  END

  FOR
    SELECT LV.LISTVAL_ID, LV.PARENT_ID, LV.TAG, LV."FILTER", LV.COST, LV.SORT_ORDER, R.VAL, R.VAL_LONG
    FROM LISTVALS LV
    JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
    WHERE LV.LIST_ID = 24 AND LV.IS_DEL = 0 AND ((
      ((:V$IS_DOU = 1) AND (LV."FILTER" SIMILAR TO '%DOU %')) OR
      ((:V$IS_GOU = 1) AND (LV."FILTER" SIMILAR TO '%GOU %')) OR
      ((:V$IS_SPO = 1) AND (LV."FILTER" SIMILAR TO '%COLLEGE %')) OR
      ((:V$IS_UDOD = 1) AND (LV."FILTER" SIMILAR TO '%UDOD %')) OR
      ((:V$IS_DPO = 1) AND (LV."FILTER" SIMILAR TO '%DPO %'))
    ) OR :V$SUB_ID IS NULL)
    ORDER BY SORT_ORDER
    INTO :LISTVAL_ID, :PARENT_ID, :TAG, :"FILTER", :COST, :SORT_ORDER, :VAL, :VAL_LONG
  DO
  BEGIN
    SUSPEND;
  END
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OO_SUBJECT_TYPE_LIST (
    OBJ_ID BIGINT,
    PARAM_ID BIGINT,
    USER_ID BIGINT = 1)
RETURNS (
    LISTVAL_ID BIGINT,
    PARENT_ID BIGINT,
    VAL VARCHAR(4000),
    VAL_LONG VARCHAR(4000),
    TAG VARCHAR(100),
    "FILTER" VARCHAR(255))
AS
declare variable V$FILTER varchar(100);
begin

  IF(PARAM_ID = 3158) THEN V$FILTER = 'GOU';
  ELSE V$FILTER = 'COLLEGE';

  FOR
    SELECT L.LISTVAL_ID, L.PARENT_ID, L.VAL, L.VAL_LONG, L.TAG, L."FILTER"
    FROM LISTVALS_LIST(240, 'RU') L
    WHERE L.IS_DEL = 0 AND L."FILTER" CONTAINING :V$FILTER
    INTO :LISTVAL_ID, :PARENT_ID, :VAL, :VAL_LONG, :TAG, :"FILTER"
  DO
  BEGIN
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OPLIST_BUILD (
    I$OBJ_ID BIGINT)
AS
DECLARE VARIABLE V$TYPE_ID BIGINT;
DECLARE VARIABLE V$OP_ID BIGINT;
DECLARE VARIABLE V$AREA_ID BIGINT;
DECLARE VARIABLE V$PLAN_ID BIGINT;
DECLARE VARIABLE V$OU_NAME VARCHAR(200);
DECLARE VARIABLE V$FULL_NAME VARCHAR(400);
DECLARE VARIABLE V$OGRN VARCHAR(20);
DECLARE VARIABLE V$OP_NAME VARCHAR(200);
DECLARE VARIABLE V$PLAN_NAME VARCHAR(200);
DECLARE VARIABLE V$OP_LEVEL BIGINT;
DECLARE VARIABLE V$OP_ADAPT BIGINT;
DECLARE VARIABLE V$WEEKLEN SMALLINT;
DECLARE VARIABLE V$ADVSUBJ VARCHAR(1000);
DECLARE VARIABLE V$GZCODES VARCHAR(1000);
DECLARE VARIABLE V$GZNAMES VARCHAR(1000);
DECLARE VARIABLE V$AT_HOME BIGINT;
DECLARE VARIABLE V$IS_NET BIGINT;
DECLARE VARIABLE V$IS_DIST BIGINT;
DECLARE VARIABLE V$HAS_ADV BIGINT;
DECLARE VARIABLE V$PLAN_TYPE BIGINT;
DECLARE VARIABLE V$PF_NAME BIGINT;
DECLARE VARIABLE V$OP_FORM BIGINT;
DECLARE VARIABLE V$FGOS BIGINT;
DECLARE VARIABLE V$CNT_GZ INTEGER;
DECLARE VARIABLE V$CNT_20 INTEGER;
DECLARE VARIABLE V$CNT_ALL INTEGER;
DECLARE VARIABLE V$SUM_HOURS INTEGER;
DECLARE VARIABLE V$STAGE_LOADS VARCHAR(400);
DECLARE VARIABLE V$STAGE_COUNTS VARCHAR(400);
DECLARE VARIABLE V$SUBJECT_NAMES VARCHAR(4000);
DECLARE VARIABLE V$MUL BIGINT;
DECLARE VARIABLE V$ID1 BIGINT;
DECLARE VARIABLE V$ID2 BIGINT;
BEGIN

  -- Нельзя просто так проверять данные по id - он может пересечься с регномером по значению
  SELECT MULTIPLIER FROM GEN INTO :V$MUL;

  IF(I$OBJ_ID > V$MUL) THEN
  BEGIN
    SELECT FIRST 1 TYPE_ID
    FROM OBJECTS
    WHERE OBJ_ID = :I$OBJ_ID
    INTO :V$TYPE_ID;
  END
  -- А вот эта ветка для проверки по регномеру
  ELSE
  BEGIN
    V$ID1 = I$OBJ_ID * V$MUL;
    V$ID2 = (I$OBJ_ID + 1) * V$MUL;

    SELECT FIRST 1 OBJ_ID, TYPE_ID
    FROM OBJECTS
    WHERE TYPE_ID IN (2, 111) AND OBJ_ID >= :V$ID1 AND OBJ_ID < :V$ID2
    INTO :I$OBJ_ID, :V$TYPE_ID;
  END

  IF(V$TYPE_ID = 111) THEN
  BEGIN
    FOR
      SELECT L2.OBJ_ID
      FROM LINKS L2
      WHERE L2.PARENT_ID = :I$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      INTO :V$TYPE_ID
    DO
    BEGIN
      EXECUTE PROCEDURE OPLIST_BUILD(:V$TYPE_ID);
    END
    EXIT;
  END
  ELSE IF(V$TYPE_ID IS NULL OR V$TYPE_ID <> 2) THEN
    EXCEPTION DATA_ERROR 'Недопустимый тип объекта для обновления данных ОП-УП ' || COALESCE(V$TYPE_ID, '???');

  SELECT FIRST 1 V665.LISTVAL_ID, SUBSTRING(V2.SVAL FROM 1 FOR 200), SUBSTRING(V5.SVAL FROM 1 FOR 400), SUBSTRING(V9.SVAL FROM 1 FOR 20)
  FROM LINKS LP111
  JOIN VALL V665 ON V665.OBJ_ID = LP111.PARENT_ID AND V665.PARAM_ID = 665 AND V665.IS_DEL = 0
  LEFT JOIN VALS V2 ON V2.OBJ_ID = LP111.OBJ_ID AND V2.PARAM_ID = 2 AND V2.IS_DEL = 0
  LEFT JOIN VALS V5 ON V5.OBJ_ID = LP111.OBJ_ID AND V5.PARAM_ID = 5 AND V5.IS_DEL = 0
  LEFT JOIN VALS V9 ON V9.OBJ_ID = LP111.OBJ_ID AND V9.PARAM_ID = 9 AND V9.IS_DEL = 0
  WHERE LP111.OBJ_ID = :I$OBJ_ID AND LP111.PARENT_TYPE_ID = 111 AND LP111.DATE_DEL IS NULL
  INTO :V$AREA_ID, :V$OU_NAME, :V$FULL_NAME, :V$OGRN;

  FOR
    SELECT L57.OBJ_ID, L400.OBJ_ID, SUBSTRING(V386.SVAL FROM 1 FOR 200) OP_NAME, SUBSTRING(V3012.SVAL FROM 1 FOR 200) PLAN_NAME, V1594.LISTVAL_ID OP_LEVEL,
      V2379.LISTVAL_ID OP_ADAPT, V3438.VAL WEEKLEN, V3439.VAL ADVSUBJ,
      SUBSTRING(V3437.VAL FROM 1 FOR 1000) GZCODES, SUBSTRING(V3443.VAL FROM 1 FOR 1000) GZNAMES, V3435.LISTVAL_ID AT_HOME, V1891.LISTVAL_ID IS_NET, V2833.LISTVAL_ID IS_DIST,
      V3436.LISTVAL_ID HAS_ADV, V3016.LISTVAL_ID PLAN_TYPE, V3112.LISTVAL_ID PF_NAME, V3015.LISTVAL_ID OP_FORM, V3014.LISTVAL_ID FGOS, V3440.VAL CNT_GZ, V3441.VAL CNT_20,
      V3442.VAL CNT_ALL, V3445.VAL SUM_HOURS, D.STAGE_LOADS, D.STAGE_COUNTS, D.SUBJECT_NAMES
    FROM LINKS L69
    JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
    JOIN VALS V386 ON V386.OBJ_ID = L57.OBJ_ID AND V386.PARAM_ID = 386
    JOIN VALL V1594 ON V1594.OBJ_ID = L57.OBJ_ID AND V1594.PARAM_ID = 1594 AND V1594.IS_DEL = 0
    JOIN VALL V2379 ON V2379.OBJ_ID = L57.OBJ_ID AND V2379.PARAM_ID = 2379 AND V2379.IS_DEL = 0
    JOIN VALL V1891 ON V1891.OBJ_ID = L57.OBJ_ID AND V1891.PARAM_ID = 1891 AND V1891.IS_DEL = 0
    JOIN VALL V2833 ON V2833.OBJ_ID = L57.OBJ_ID AND V2833.PARAM_ID = 2833 AND V2833.IS_DEL = 0
    JOIN LINKS L400 ON L400.PARENT_ID = L57.OBJ_ID AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL
    JOIN VALL V3013 ON V3013.OBJ_ID = L400.OBJ_ID AND V3013.PARAM_ID = 3013 AND V3013.IS_DEL = 0 AND V3013.LISTVAL_ID = 11715
    JOIN VALS V3012 ON V3012.OBJ_ID = L400.OBJ_ID AND V3012.PARAM_ID = 3012 AND V3012.IS_DEL = 0
    LEFT JOIN VALL V3016 ON V3016.OBJ_ID = L400.OBJ_ID AND V3016.PARAM_ID = 3016 AND V3016.IS_DEL = 0
    LEFT JOIN VALS V3437 ON V3437.OBJ_ID = L400.OBJ_ID AND V3437.PARAM_ID = 3437 AND V3437.IS_DEL = 0
    LEFT JOIN VALS V3443 ON V3443.OBJ_ID = L400.OBJ_ID AND V3443.PARAM_ID = 3443 AND V3443.IS_DEL = 0
    LEFT JOIN VALI V3438 ON V3438.OBJ_ID = L400.OBJ_ID AND V3438.PARAM_ID = 3438 AND V3438.IS_DEL = 0
    LEFT JOIN VALS V3439 ON V3439.OBJ_ID = L400.OBJ_ID AND V3439.PARAM_ID = 3439 AND V3439.IS_DEL = 0
    LEFT JOIN VALL V3435 ON V3435.OBJ_ID = L400.OBJ_ID AND V3435.PARAM_ID = 3435 AND V3435.IS_DEL = 0
    LEFT JOIN VALL V3436 ON V3436.OBJ_ID = L400.OBJ_ID AND V3436.PARAM_ID = 3436 AND V3436.IS_DEL = 0
    LEFT JOIN VALL V3112 ON V3112.OBJ_ID = L400.OBJ_ID AND V3112.PARAM_ID = 3112 AND V3112.IS_DEL = 0
    LEFT JOIN LISTVAL_TEXT(V3112.LISTVAL_ID) R3112 ON V3112.LISTVAL_ID IS NOT NULL
    LEFT JOIN VALL V3014 ON V3014.OBJ_ID = L400.OBJ_ID AND V3014.PARAM_ID = 3014 AND V3014.IS_DEL = 0
    LEFT JOIN LISTVAL_TEXT(V3014.LISTVAL_ID) R3014 ON V3014.LISTVAL_ID IS NOT NULL
    LEFT JOIN VALL V3015 ON V3015.OBJ_ID = L400.OBJ_ID AND V3015.PARAM_ID = 3015 AND V3015.IS_DEL = 0
    LEFT JOIN LISTVAL_TEXT(V3015.LISTVAL_ID) R3015 ON V3015.LISTVAL_ID IS NOT NULL
    LEFT JOIN VALI V3440 ON V3440.OBJ_ID = L400.OBJ_ID AND V3440.PARAM_ID = 3440 AND V3440.IS_DEL = 0
    LEFT JOIN VALI V3441 ON V3441.OBJ_ID = L400.OBJ_ID AND V3441.PARAM_ID = 3441 AND V3441.IS_DEL = 0
    LEFT JOIN VALI V3442 ON V3442.OBJ_ID = L400.OBJ_ID AND V3442.PARAM_ID = 3442 AND V3442.IS_DEL = 0
    LEFT JOIN VALI V3445 ON V3445.OBJ_ID = L400.OBJ_ID AND V3445.PARAM_ID = 3445 AND V3445.IS_DEL = 0
    LEFT JOIN OPLIST_PLAN_DETAILS(L400.OBJ_ID) D ON 1 = 1
    WHERE L69.PARENT_ID = :I$OBJ_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL
    ORDER BY 2
    INTO :V$OP_ID, :V$PLAN_ID, :V$OP_NAME, :V$PLAN_NAME, :V$OP_LEVEL, :V$OP_ADAPT, :V$WEEKLEN, :V$ADVSUBJ,
      :V$GZCODES, :V$GZNAMES, :V$AT_HOME, :V$IS_NET, :V$IS_DIST, :V$HAS_ADV,
      :V$PLAN_TYPE, :V$PF_NAME, :V$OP_FORM, :V$FGOS, :V$CNT_GZ, :V$CNT_20,
      :V$CNT_ALL, :V$SUM_HOURS, :V$STAGE_LOADS, :V$STAGE_COUNTS, :V$SUBJECT_NAMES
  DO
  BEGIN
    -- Кроме внеурочки
    IF(NOT EXISTS(
      SELECT FIRST 1 1
      FROM VALL V3022
      WHERE V3022.OBJ_ID = :V$PLAN_ID AND V3022.PARAM_ID = 3022 AND V3022.IS_DEL = 0 AND V3022.LISTVAL_ID = 2
    ))
    THEN
    UPDATE OR INSERT INTO OPLIST_PLANS
    (OBJ_ID, OU_ID, OP_ID, OU_NAME, FULL_NAME, OGRN, AREA_ID, OP_NAME, PLAN_NAME, OP_LEVEL_ID, OP_ADAPT_ID, WEEKLEN, ADVSUBJ,
      GZNAMES, GZCODES, AT_HOME_ID, IS_NET_ID, IS_DIST_ID, HAS_ADV, PLAN_TYPE_ID, PROFILE_ID, OP_FORM_ID, FGOS_ID,
      CNT_GZ, CNT_20, CNT_ALL, SUM_HOURS, STAGE_LOADS, STAGE_COUNTS, SUBJECT_NAMES)
    VALUES (:V$PLAN_ID, :I$OBJ_ID, :V$OP_ID, :V$OU_NAME, :V$FULL_NAME, :V$OGRN, :V$AREA_ID, :V$OP_NAME, :V$PLAN_NAME, :V$OP_LEVEL, :V$OP_ADAPT, :V$WEEKLEN, :V$ADVSUBJ,
      :V$GZNAMES, :V$GZCODES, :V$AT_HOME, :V$IS_NET, :V$IS_DIST, :V$HAS_ADV, :V$PLAN_TYPE, :V$PF_NAME, :V$OP_FORM, :V$FGOS,
      :V$CNT_GZ, :V$CNT_20, :V$CNT_ALL, :V$SUM_HOURS, :V$STAGE_LOADS, :V$STAGE_COUNTS, :V$SUBJECT_NAMES);
  END

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OPLIST_PLAN_DETAILS (
    I$PLAN_ID BIGINT)
RETURNS (
    STAGE_LOADS VARCHAR(400),
    STAGE_COUNTS VARCHAR(400),
    SUBJECT_NAMES VARCHAR(4000))
AS
declare variable V$OBJ_ID bigint;
declare variable V$STAGE_NAME varchar(400);
declare variable V$WEEK bigint;
declare variable N integer;
begin

  STAGE_LOADS = '';
  STAGE_COUNTS = '';
  SUBJECT_NAMES = '';

  FOR
    SELECT L54.OBJ_ID, C.CAPTION, V2837.LISTVAL_ID, V3444.VAL
    FROM LINKS L54
    LEFT JOIN OBJECT_CAPTION_GET(L54.OBJ_ID) C ON 1 = 1
    LEFT JOIN VALI V3444 ON V3444.OBJ_ID = L54.OBJ_ID AND V3444.PARAM_ID = 3444 AND V3444.IS_DEL = 0
    LEFT JOIN VALL V2837 ON V2837.OBJ_ID = L54.OBJ_ID AND V2837.PARAM_ID = 2837 AND V2837.IS_DEL = 0
    WHERE L54.PARENT_ID = :I$PLAN_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
    ORDER BY C.SORT_ORDER
    INTO :V$OBJ_ID, :V$STAGE_NAME, :V$WEEK, :N
  DO
  BEGIN
    V$STAGE_NAME = TRIM(REPLACE(REPLACE(V$STAGE_NAME, ' (', ''), ')', ''));
    V$STAGE_NAME = TRIM(REPLACE(REPLACE(V$STAGE_NAME, 'первый год', '/1'), 'второй год', '/2'));
    V$STAGE_NAME = TRIM(REPLACE(REPLACE(V$STAGE_NAME, ' параллель', ''), ' курс', ''));

    IF(STAGE_COUNTS <> '') THEN STAGE_COUNTS = STAGE_COUNTS || ', ';
    STAGE_COUNTS = STAGE_COUNTS || V$STAGE_NAME || ' (' || COALESCE(N, 0) || ')';

    N = NULL;
    SELECT SUM(L.LOAD_HOURS)
    FROM PLAN_SUBJECTS PS
    JOIN PLAN_LOADS L ON L.DATE_DEL IS NULL AND L.SUBJECT_ID = PS.OBJ_ID AND L.STAGE_ID = :V$OBJ_ID
    WHERE PS.DATE_DEL IS NULL AND PS.ROW_TYPE = 0 AND PS.PLAN_ID = :I$PLAN_ID AND PS.PARENT_ID IS NULL
    INTO :N;

    IF(STAGE_LOADS <> '') THEN STAGE_LOADS = STAGE_LOADS || ', ';
    STAGE_LOADS = STAGE_LOADS || V$STAGE_NAME || ' (' || IIF(V$WEEK = 11719, '6', '5') || 'дн) ' || COALESCE(N, 0) || 'ч';
  END

  FOR
    SELECT C.CAPTION, SUM(L.LOAD_HOURS)
    FROM PLAN_SUBJECTS PS
    JOIN PLAN_SUBJECTS PP ON PP.OBJ_ID = PS.PARENT_ID
    JOIN PLAN_LOADS L ON L.DATE_DEL IS NULL AND L.SUBJECT_ID = PS.OBJ_ID AND L.STAGE_ID IS NULL
    LEFT JOIN OBJECT_CAPTION_GET(PS.SUBJECT_ID) C ON 1 = 1
    WHERE PS.DATE_DEL IS NULL AND PS.ROW_TYPE = 10 AND PS.PLAN_ID = :I$PLAN_ID AND PS.PARENT_ID IS NOT NULL
      AND (PP.FIELD_ID <> 12928 OR PS.SUBJECT_ID = 34607)
    GROUP BY 1
    ORDER BY 1
    INTO :V$STAGE_NAME, :N
  DO
  BEGIN
    IF(N > 0) THEN
    BEGIN
      V$STAGE_NAME = SUBSTRING(V$STAGE_NAME FROM 1 FOR 100);
      IF(CHAR_LENGTH(SUBJECT_NAMES) + CHAR_LENGTH(V$STAGE_NAME) < 3960) THEN
      BEGIN
        IF(SUBJECT_NAMES <> '') THEN SUBJECT_NAMES = SUBJECT_NAMES || ', ';
        SUBJECT_NAMES = SUBJECT_NAMES || V$STAGE_NAME || ' (' || N || ')';
      END
    END
  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OPTEXT_DELETE (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
AS
begin

  IF(EXISTS(
    SELECT FIRST 1 1
    FROM OP_CONTENT C
    WHERE C.DATE_DEL IS NULL AND C.PARENT_ID = :I$OBJ_ID
  ))
  THEN
    EXCEPTION DATA_ERROR 'Нельзя удалять раздел, если в нем имеются подразделы';

  UPDATE OP_CONTENT
  SET DATE_DEL = CURRENT_TIMESTAMP
  WHERE OBJ_ID = :I$OBJ_ID AND DATE_DEL IS NULL;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OPTEXT_GET (
    I$OP_ID BIGINT,
    I$PARENT_ID BIGINT,
    I$USER_ID VARCHAR(200))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE S VARCHAR(1000);
DECLARE VARIABLE N INTEGER;
DECLARE VARIABLE T BIGINT;
DECLARE VARIABLE I INTEGER;
begin

  -- Справочники выдаем только с запросом в корне дерева
  IF(I$PARENT_ID IS NULL) THEN
  BEGIN
    TAG_NAME = 'types::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT L.LISTVAL_ID, L.VAL
      FROM LISTVALS_LIST(386) L
      WHERE L.IS_DEL = 0
      INTO :V$OBJ_ID, :S
    DO
    BEGIN
      TAG_NAME = 'types:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'types:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'types:r:value';
      VAL = S;
      SUSPEND;
    END
  END

  -- При 0 и отрицательных значениях PARENT_ID возвращаем в виде XML дерева
  -- В I$USER_ID передаем дерево имен узлов
  IF(I$PARENT_ID <= 0) THEN
  BEGIN
    IF(I$PARENT_ID = 0) THEN
    BEGIN
      I$PARENT_ID = NULL;
      I$USER_ID = '';

      -- Добавляем заголовочную часть текста
      TAG_NAME = 'op_name';
      SELECT V386.VAL
      FROM VALS V386
      WHERE V386.OBJ_ID = :I$OP_ID AND V386.PARAM_ID = 386 AND V386.IS_DEL = 0
      INTO :VAL;
      SUSPEND;

      TAG_NAME = 'type_name';
      SELECT C.VAL
      FROM VALL V1832
      LEFT JOIN LISTVAL_TEXT(V1832.LISTVAL_ID) C ON 1 = 1
      WHERE V1832.OBJ_ID = :I$OP_ID AND V1832.PARAM_ID = 1832 AND V1832.IS_DEL = 0
      INTO :VAL;
      SUSPEND;

      TAG_NAME = 'year';
      SELECT V3115.VAL
      FROM VALI V3115
      WHERE V3115.OBJ_ID = :I$OP_ID AND V3115.PARAM_ID = 3115 AND V3115.IS_DEL = 0
      INTO :VAL;
      SUSPEND;

      TAG_NAME = 'stage_id';
      SELECT V1832.LISTVAL_ID
      FROM VALL V1832
      WHERE V1832.OBJ_ID = :I$OP_ID AND V1832.PARAM_ID = 1832 AND V1832.IS_DEL = 0
      INTO :VAL;
      SUSPEND;

      TAG_NAME = 'ou_name';
      VAL = NULL;
      SELECT V999.VAL
      FROM LINKS L2
      JOIN VALS V999 ON V999.OBJ_ID = L2.OBJ_ID AND V999.PARAM_ID = 999 AND V999.IS_DEL = 0
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      INTO :VAL;
      IF(VAL IS NULL) THEN
      SELECT V2.VAL
      FROM LINKS L2
      JOIN VALS V2 ON V2.OBJ_ID = L2.OBJ_ID AND V2.PARAM_ID = 2 AND V2.IS_DEL = 0
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      INTO :VAL;
      SUSPEND;

      TAG_NAME = 'dir_name';
      SELECT C.FIO, C.POST
      FROM LINKS L2
      LEFT JOIN R_SPB_POST_DIRECTOR(L2.OBJ_ID, 1) C ON 1 = 1
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      INTO :VAL, :S;
      SUSPEND;

      TAG_NAME = 'dir_post';
      VAL = S;
      SUSPEND;
    END
    ELSE
    BEGIN
      I$PARENT_ID = ABS(I$PARENT_ID);
    END
    IF(I$USER_ID <> '') THEN I$USER_ID = I$USER_ID || ':';

    FOR
      SELECT C.OBJ_ID, C.SEQ_INDEX, C.TEXT, C.TYPE_ID, C.SC_INDEX
      FROM OP_CONTENT C
      WHERE C.DATE_DEL IS NULL AND C.OP_ID = :I$OP_ID AND ((C.PARENT_ID IS NULL AND :I$PARENT_ID IS NULL) OR C.PARENT_ID = :I$PARENT_ID)
      ORDER BY C.SEQ_INDEX
      INTO :V$OBJ_ID, :N, :S, :T, :I
    DO
    BEGIN
      TAG_NAME = I$USER_ID || 'row';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = I$USER_ID || 'row:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = I$USER_ID || 'row:text';
      VAL = S;
      SUSPEND;
      TAG_NAME = I$USER_ID || 'row:type_id';
      VAL = T;
      SUSPEND;
      TAG_NAME = I$USER_ID || 'row:sc_index';
      VAL = I;
      SUSPEND;
      -- Вниз по дереву
      FOR
        SELECT TAG_NAME, VAL
        FROM OPTEXT_GET(:I$OP_ID, - :V$OBJ_ID, :I$USER_ID || 'row')
        INTO :TAG_NAME, :VAL
      DO
      BEGIN
        SUSPEND;
      END
    END
    EXIT;
  END

  TAG_NAME = 'parent_id';
  VAL = I$PARENT_ID;
  SUSPEND;

  TAG_NAME = 'items::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT C.OBJ_ID, C.SEQ_INDEX, C.TEXT, C.TYPE_ID, C.SC_INDEX
    FROM OP_CONTENT C
    WHERE C.DATE_DEL IS NULL AND C.OP_ID = :I$OP_ID AND ((C.PARENT_ID IS NULL AND :I$PARENT_ID IS NULL) OR C.PARENT_ID = :I$PARENT_ID)
    ORDER BY C.SEQ_INDEX
    INTO :V$OBJ_ID, :N, :S, :T, :I
  DO
  BEGIN
    TAG_NAME = 'items:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'items:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'items:r:text';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'items:r:type_id';
    VAL = T;
    SUSPEND;
    TAG_NAME = 'items:r:index';
    VAL = N;
    SUSPEND;
    TAG_NAME = 'items:r:sc_index';
    VAL = I;
    SUSPEND;
    TAG_NAME = 'items:r:children';
    VAL = 0;
    SELECT FIRST 1 1
    FROM OP_CONTENT C
    WHERE C.DATE_DEL IS NULL AND C.OP_ID = :I$OP_ID AND C.PARENT_ID = :V$OBJ_ID
    INTO :VAL;
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OPTEXT_INNER_GET (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(4000))
AS
DECLARE VARIABLE V$PLAN_ID BIGINT;
DECLARE VARIABLE S VARCHAR(1000);
DECLARE VARIABLE S2 VARCHAR(1000);
DECLARE VARIABLE V$SUBJECT_ID BIGINT;
DECLARE VARIABLE V$RT SMALLINT;
DECLARE VARIABLE V$ADV SMALLINT;
DECLARE VARIABLE V$CAL_ID BIGINT;
DECLARE VARIABLE D1 DATE;
DECLARE VARIABLE D2 DATE;
DECLARE VARIABLE F FLOAT;
DECLARE VARIABLE W FLOAT;
begin

  -- УП общеобразовательные
  TAG_NAME = 'plans';
  VAL = NULL;
  SUSPEND;
  FOR
    SELECT L400.OBJ_ID, V3012.VAL
    FROM LINKS L400
    JOIN VALS V3012 ON V3012.OBJ_ID = L400.OBJ_ID AND V3012.PARAM_ID = 3012 AND V3012.IS_DEL = 0
    -- только групповые
    JOIN VALL V3016 ON V3016.OBJ_ID = L400.OBJ_ID AND V3016.PARAM_ID = 3016 AND V3016.IS_DEL = 0 AND V3016.LISTVAL_ID = 5465
    -- не ВД
    JOIN VALL V3022 ON V3022.OBJ_ID = L400.OBJ_ID AND V3022.PARAM_ID = 3022 AND V3022.IS_DEL = 0 AND V3022.LISTVAL_ID = 3
    WHERE L400.PARENT_ID = :I$OBJ_ID AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL
    ORDER BY 2
    INTO :V$PLAN_ID, :S
  DO
  BEGIN
    TAG_NAME = 'plans:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'plans:r:id';
    VAL = V$PLAN_ID;
    SUSPEND;
    TAG_NAME = 'plans:r:name';
    VAL = S;
    SUSPEND;
    -- Заголовочные столбцы
    TAG_NAME = 'plans:r:cols';
    VAL = NULL;
    SUSPEND;
    FOR
      SELECT C.VAL, W.VAL, V382.VAL
      FROM LINKS L54
      JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
      LEFT JOIN LISTVAL_TEXT(V381.LISTVAL_ID) C ON 1 = 1
      LEFT JOIN VALL V2837 ON V2837.OBJ_ID = L54.OBJ_ID AND V2837.PARAM_ID = 2837 AND V2837.IS_DEL = 0
      LEFT JOIN LISTVAL_TEXT(V2837.LISTVAL_ID) W ON 1 = 1
      JOIN VALI V382 ON V382.OBJ_ID = L54.OBJ_ID AND V382.PARAM_ID = 382 AND V382.IS_DEL = 0
      WHERE L54.PARENT_ID = :V$PLAN_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
      ORDER BY V381.LISTVAL_ID
      INTO :S, :S2, :W
    DO
    BEGIN
      TAG_NAME = 'plans:r:cols:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'plans:r:cols:r:name';
      VAL = S;
      SUSPEND;
      TAG_NAME = 'plans:r:cols:r:weekdays';
      VAL = S2;
      SUSPEND;
      TAG_NAME = 'plans:r:cols:r:weeks';
      VAL = CAST(W AS INTEGER);
      SUSPEND;
    END
    -- Выдаем в два слоя - разделы и далее предметы
    TAG_NAME = 'plans:r:subjects';
    VAL = NULL;
    SUSPEND;
    FOR
      SELECT PS.OBJ_ID, PS.ROW_TYPE, PS.IS_ADV, COALESCE(C.CAPTION, FC.VAL), FC.VAL
      FROM PLAN_SUBJECTS PS
      LEFT JOIN LISTVAL_TEXT(PS.FIELD_ID) FC ON PS.FIELD_ID IS NOT NULL
      LEFT JOIN OBJECT_CAPTION_GET(PS.SUBJECT_ID) C ON PS.SUBJECT_ID IS NOT NULL
      WHERE PS.DATE_DEL IS NULL AND PS.PLAN_ID = :V$PLAN_ID
      ORDER BY PS.GLOBAL_INDEX
      INTO :V$SUBJECT_ID, :V$RT, :V$ADV, :S, :S2
    DO
    BEGIN
      TAG_NAME = 'plans:r:subjects:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'plans:r:subjects:r:row_type';
      VAL = V$RT;
      SUSPEND;
      TAG_NAME = 'plans:r:subjects:r:is_adv';
      VAL = V$ADV;
      SUSPEND;
      TAG_NAME = 'plans:r:subjects:r:name';
      VAL = S;
      SUSPEND;
      TAG_NAME = 'plans:r:subjects:r:field_name';
      VAL = S2;
      SUSPEND;
      -- Нагрузки
      TAG_NAME = 'plans:r:subjects:r:total_hours';
      VAL = NULL;
      SELECT CAST(PL.LOAD_HOURS AS INTEGER)
      FROM PLAN_LOADS PL
      WHERE PL.DATE_DEL IS NULL AND PL.SUBJECT_ID = :V$SUBJECT_ID AND PL.STAGE_ID IS NULL
      INTO :VAL;
      SUSPEND;
      -- Столбцы
      TAG_NAME = 'plans:r:subjects:r:cols';
      VAL = NULL;
      SUSPEND;
      FOR
        SELECT PL.LOAD_HOURS, PL.WEEKS
        FROM LINKS L54
        JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
        JOIN PLAN_LOADS PL ON PL.DATE_DEL IS NULL AND PL.SUBJECT_ID = :V$SUBJECT_ID AND PL.STAGE_ID = L54.OBJ_ID
        WHERE L54.PARENT_ID = :V$PLAN_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
        ORDER BY V381.LISTVAL_ID
        INTO :F, :W
      DO
      BEGIN
        TAG_NAME = 'plans:r:subjects:r:cols:r';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'plans:r:subjects:r:cols:r:hours';
        VAL = CAST(F AS INTEGER);
        SUSPEND;
        TAG_NAME = 'plans:r:subjects:r:cols:r:weeks';
        VAL = CAST(W AS INTEGER);
        SUSPEND;
        TAG_NAME = 'plans:r:subjects:r:cols:r:perweek';
        VAL = CAST(F / W AS NUMERIC(18, 2));
        SUSPEND;
      END
    END
    -- Общий итог - тоже посчитаем тут
    TAG_NAME = 'plans:r:final';
    VAL = NULL;
    SUSPEND;
      TAG_NAME = 'plans:r:final:total_hours';
      VAL = NULL;
      SELECT CAST(SUM(PL.LOAD_HOURS) AS INTEGER)
      FROM PLAN_SUBJECTS PS
      JOIN PLAN_LOADS PL ON PL.DATE_DEL IS NULL AND PL.SUBJECT_ID = PS.OBJ_ID AND PL.STAGE_ID IS NULL
      WHERE PS.DATE_DEL IS NULL AND PS.PLAN_ID = :V$PLAN_ID AND PS.ROW_TYPE = 0
      INTO :VAL;
      SUSPEND;
    TAG_NAME = 'plans:r:final:cols';
    VAL = NULL;
    SUSPEND;
    FOR
      SELECT V382.VAL, (
        SELECT CAST(SUM(PL.LOAD_HOURS) AS INTEGER)
        FROM PLAN_SUBJECTS PS
        JOIN PLAN_LOADS PL ON PL.DATE_DEL IS NULL AND PL.SUBJECT_ID = PS.OBJ_ID AND PL.STAGE_ID = L54.OBJ_ID
        WHERE PS.DATE_DEL IS NULL AND PS.PLAN_ID = L54.PARENT_ID AND PS.ROW_TYPE = 0
      )
      FROM LINKS L54
      JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
      JOIN VALI V382 ON V382.OBJ_ID = L54.OBJ_ID AND V382.PARAM_ID = 382 AND V382.IS_DEL = 0
      WHERE L54.PARENT_ID = :V$PLAN_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
      ORDER BY V381.LISTVAL_ID
      INTO :W, :F
    DO
    BEGIN
      TAG_NAME = 'plans:r:final:cols:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'plans:r:final:cols:r:hours';
      VAL = CAST(F AS INTEGER);
      SUSPEND;
      TAG_NAME = 'plans:r:final:cols:r:perweek';
      VAL = CAST(F / W AS NUMERIC(18, 2));
      SUSPEND;
    END
  END

  -- УП ВД
  TAG_NAME = 'vdplans';
  VAL = NULL;
  SUSPEND;
  FOR
    SELECT L400.OBJ_ID, V3012.VAL
    FROM LINKS L400
    JOIN VALS V3012 ON V3012.OBJ_ID = L400.OBJ_ID AND V3012.PARAM_ID = 3012 AND V3012.IS_DEL = 0
    -- только групповые
    JOIN VALL V3016 ON V3016.OBJ_ID = L400.OBJ_ID AND V3016.PARAM_ID = 3016 AND V3016.IS_DEL = 0 AND V3016.LISTVAL_ID = 5465
    -- ВД
    JOIN VALL V3022 ON V3022.OBJ_ID = L400.OBJ_ID AND V3022.PARAM_ID = 3022 AND V3022.IS_DEL = 0 AND V3022.LISTVAL_ID = 2
    WHERE L400.PARENT_ID = :I$OBJ_ID AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL
    ORDER BY 2
    INTO :V$PLAN_ID, :S
  DO
  BEGIN
    TAG_NAME = 'vdplans:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'vdplans:r:id';
    VAL = V$PLAN_ID;
    SUSPEND;
    TAG_NAME = 'vdplans:r:name';
    VAL = S;
    SUSPEND;
    -- Заголовочные столбцы
    TAG_NAME = 'vdplans:r:cols';
    VAL = NULL;
    SUSPEND;
    FOR
      SELECT C.VAL, W.VAL, V382.VAL
      FROM LINKS L54
      JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
      LEFT JOIN LISTVAL_TEXT(V381.LISTVAL_ID) C ON 1 = 1
      LEFT JOIN VALL V2837 ON V2837.OBJ_ID = L54.OBJ_ID AND V2837.PARAM_ID = 2837 AND V2837.IS_DEL = 0
      LEFT JOIN LISTVAL_TEXT(V2837.LISTVAL_ID) W ON 1 = 1
      JOIN VALI V382 ON V382.OBJ_ID = L54.OBJ_ID AND V382.PARAM_ID = 382 AND V382.IS_DEL = 0
      WHERE L54.PARENT_ID = :V$PLAN_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
      ORDER BY V381.LISTVAL_ID
      INTO :S, :S2, :W
    DO
    BEGIN
      TAG_NAME = 'vdplans:r:cols:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'vdplans:r:cols:r:name';
      VAL = S;
      SUSPEND;
      TAG_NAME = 'vdplans:r:cols:r:weekdays';
      VAL = S2;
      SUSPEND;
      TAG_NAME = 'vdplans:r:cols:r:weeks';
      VAL = CAST(W AS INTEGER);
      SUSPEND;
    END
    -- Выдаем в два слоя - разделы и далее предметы
    TAG_NAME = 'vdplans:r:subjects';
    VAL = NULL;
    SUSPEND;
    FOR
      SELECT PS.OBJ_ID, PS.ROW_TYPE, PS.IS_ADV, COALESCE(C.CAPTION, FC.VAL), FC.VAL
      FROM PLAN_SUBJECTS PS
      LEFT JOIN LISTVAL_TEXT(PS.FIELD_ID) FC ON PS.FIELD_ID IS NOT NULL
      LEFT JOIN OBJECT_CAPTION_GET(PS.SUBJECT_ID) C ON PS.SUBJECT_ID IS NOT NULL
      WHERE PS.DATE_DEL IS NULL AND PS.PLAN_ID = :V$PLAN_ID
      ORDER BY PS.GLOBAL_INDEX
      INTO :V$SUBJECT_ID, :V$RT, :V$ADV, :S, :S2
    DO
    BEGIN
      TAG_NAME = 'vdplans:r:subjects:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'vdplans:r:subjects:r:row_type';
      VAL = V$RT;
      SUSPEND;
      TAG_NAME = 'vdplans:r:subjects:r:is_adv';
      VAL = V$ADV;
      SUSPEND;
      TAG_NAME = 'vdplans:r:subjects:r:name';
      VAL = S;
      SUSPEND;
      TAG_NAME = 'vdplans:r:subjects:r:field_name';
      VAL = S2;
      SUSPEND;
      -- Нагрузки
      TAG_NAME = 'vdplans:r:subjects:r:total_hours';
      VAL = NULL;
      SELECT CAST(PL.LOAD_HOURS AS INTEGER)
      FROM PLAN_LOADS PL
      WHERE PL.DATE_DEL IS NULL AND PL.SUBJECT_ID = :V$SUBJECT_ID AND PL.STAGE_ID IS NULL
      INTO :VAL;
      SUSPEND;
      -- Столбцы
      TAG_NAME = 'vdplans:r:subjects:r:cols';
      VAL = NULL;
      SUSPEND;
      FOR
        SELECT PL.LOAD_HOURS, PL.WEEKS
        FROM LINKS L54
        JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
        JOIN PLAN_LOADS PL ON PL.DATE_DEL IS NULL AND PL.SUBJECT_ID = :V$SUBJECT_ID AND PL.STAGE_ID = L54.OBJ_ID
        WHERE L54.PARENT_ID = :V$PLAN_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
        ORDER BY V381.LISTVAL_ID
        INTO :F, :W
      DO
      BEGIN
        TAG_NAME = 'vdplans:r:subjects:r:cols:r';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'vdplans:r:subjects:r:cols:r:hours';
        VAL = CAST(F AS INTEGER);
        SUSPEND;
        TAG_NAME = 'vdplans:r:subjects:r:cols:r:weeks';
        VAL = CAST(W AS INTEGER);
        SUSPEND;
        TAG_NAME = 'vdplans:r:subjects:r:cols:r:perweek';
        VAL = CAST(F / W AS NUMERIC(18, 2));
        SUSPEND;
      END
    END
    -- Общий итог - тоже посчитаем тут
    TAG_NAME = 'vdplans:r:final';
    VAL = NULL;
    SUSPEND;
      TAG_NAME = 'vdplans:r:final:total_hours';
      VAL = NULL;
      SELECT CAST(SUM(PL.LOAD_HOURS) AS INTEGER)
      FROM PLAN_SUBJECTS PS
      JOIN PLAN_LOADS PL ON PL.DATE_DEL IS NULL AND PL.SUBJECT_ID = PS.OBJ_ID AND PL.STAGE_ID IS NULL
      WHERE PS.DATE_DEL IS NULL AND PS.PLAN_ID = :V$PLAN_ID AND PS.ROW_TYPE = 0
      INTO :VAL;
      SUSPEND;
    TAG_NAME = 'vdplans:r:final:cols';
    VAL = NULL;
    SUSPEND;
    FOR
      SELECT V382.VAL, (
        SELECT CAST(SUM(PL.LOAD_HOURS) AS INTEGER)
        FROM PLAN_SUBJECTS PS
        JOIN PLAN_LOADS PL ON PL.DATE_DEL IS NULL AND PL.SUBJECT_ID = PS.OBJ_ID AND PL.STAGE_ID = L54.OBJ_ID
        WHERE PS.DATE_DEL IS NULL AND PS.PLAN_ID = L54.PARENT_ID AND PS.ROW_TYPE = 0
      )
      FROM LINKS L54
      JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
      JOIN VALI V382 ON V382.OBJ_ID = L54.OBJ_ID AND V382.PARAM_ID = 382 AND V382.IS_DEL = 0
      WHERE L54.PARENT_ID = :V$PLAN_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
      ORDER BY V381.LISTVAL_ID
      INTO :W, :F
    DO
    BEGIN
      TAG_NAME = 'vdplans:r:final:cols:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'vdplans:r:final:cols:r:hours';
      VAL = CAST(F AS INTEGER);
      SUSPEND;
      TAG_NAME = 'vdplans:r:final:cols:r:perweek';
      VAL = CAST(F / W AS NUMERIC(18, 2));
      SUSPEND;
    END
  END

  -- Рабочие программы
  TAG_NAME = 'wprograms';
  VAL = NULL;
  SUSPEND;
  FOR
    SELECT DISTINCT P.OBJ_ID, P.OBJ_NAME, V376.VAL
    FROM LINKS L400
    JOIN VALS V3012 ON V3012.OBJ_ID = L400.OBJ_ID AND V3012.PARAM_ID = 3012 AND V3012.IS_DEL = 0
    -- только групповые
    JOIN VALL V3016 ON V3016.OBJ_ID = L400.OBJ_ID AND V3016.PARAM_ID = 3016 AND V3016.IS_DEL = 0 AND V3016.LISTVAL_ID = 5465
    -- не ВД
    JOIN VALL V3022 ON V3022.OBJ_ID = L400.OBJ_ID AND V3022.PARAM_ID = 3022 AND V3022.IS_DEL = 0 AND V3022.LISTVAL_ID = 3
    -- Сами программы
    JOIN VALS V3592 ON V3592.OBJ_ID = L400.OBJ_ID AND V3592.PARAM_ID = 3592 AND V3592.IS_DEL = 0
    LEFT JOIN STR_TO_ID_LIST(V3592.VAL) WP ON V3592.VAL IS NOT NULL
    LEFT JOIN PTP P ON P.OBJ_ID = WP.ID AND P.DATE_DEL IS NULL
    LEFT JOIN VALS V376 ON V376.OBJ_ID = P.SUBJECT_ID AND V376.PARAM_ID = 376 AND V376.IS_DEL = 0
    WHERE L400.PARENT_ID = :I$OBJ_ID AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL
    ORDER BY 2
    INTO :V$PLAN_ID, :S, :S2
  DO
  BEGIN
    TAG_NAME = 'wprograms:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'wprograms:r:id';
    VAL = V$PLAN_ID;
    SUSPEND;
    TAG_NAME = 'wprograms:r:name';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'wprograms:r:subject_name';
    VAL = S2;
    SUSPEND;
    -- Строки рабочей программы - выдаем снаружи, поскольку там blob
  END

  -- Календарный учебный график
  -- Берем текущий, но надо будет брать по году ОП
  SELECT FIRST 1 L481.OBJ_ID
  FROM LINKS L2
  JOIN LINKS L481 ON L481.PARENT_ID = L2.OBJ_ID AND L481.OBJ_TYPE_ID = 481 AND L481.DATE_DEL IS NULL
  JOIN VALL V3390 ON V3390.OBJ_ID = L481.OBJ_ID AND V3390.PARAM_ID = 3390 AND V3390.IS_DEL = 0 AND V3390.LISTVAL_ID = 11715
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$CAL_ID;

  -- Праздничные дни
  TAG_NAME = 'calendar:holidays';
  VAL = NULL;
  SUSPEND;
  FOR
    SELECT D.RESULT, V3395.VAL
    FROM LINKS L486
    JOIN VALL V3394 ON V3394.OBJ_ID = L486.OBJ_ID AND V3394.PARAM_ID = 3394 AND V3394.IS_DEL = 0 AND V3394.LISTVAL_ID = 14234
    JOIN VALD V3393 ON V3393.OBJ_ID = L486.OBJ_ID AND V3393.PARAM_ID = 3393 AND V3393.IS_DEL = 0
    LEFT JOIN VALS V3395 ON V3395.OBJ_ID = L486.OBJ_ID AND V3395.PARAM_ID = 3395 AND V3395.IS_DEL = 0
    LEFT JOIN DATE2STR(V3393.VAL) D ON 1 = 1
    WHERE L486.PARENT_ID = :V$CAL_ID AND L486.OBJ_TYPE_ID = 486 AND L486.DATE_DEL IS NULL
    ORDER BY V3393.VAL
    INTO :S, :S2
  DO
  BEGIN
    TAG_NAME = 'calendar:holidays:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'calendar:holidays:r:date';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'calendar:holidays:r:name';
    VAL = S2;
    SUSPEND;
  END

  -- Каникулы
  TAG_NAME = 'calendar:vacation';
  VAL = NULL;
  SUSPEND;
  FOR
    SELECT L151.OBJ_ID, V1147.VAL
    FROM LINKS L151
    JOIN VALS V1147 ON V1147.OBJ_ID = L151.OBJ_ID AND V1147.PARAM_ID = 1147 AND V1147.IS_DEL = 0
    WHERE L151.PARENT_ID = :V$CAL_ID AND L151.OBJ_TYPE_ID = 151 AND L151.DATE_DEL IS NULL
    ORDER BY 1
    INTO :V$PLAN_ID, :S
  DO
  BEGIN
    TAG_NAME = 'calendar:vacation:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'calendar:vacation:r:name';
    VAL = S;
    SUSPEND;
    FOR
      SELECT V3263.VAL, V3264.VAL, V3265.VAL
      FROM LINKS L154
      JOIN VALD V3263 ON V3263.OBJ_ID = L154.OBJ_ID AND V3263.PARAM_ID = 3263 AND V3263.IS_DEL = 0
      JOIN VALD V3264 ON V3264.OBJ_ID = L154.OBJ_ID AND V3264.PARAM_ID = 3264 AND V3264.IS_DEL = 0
      LEFT JOIN VALS V3265 ON V3265.OBJ_ID = L154.OBJ_ID AND V3265.PARAM_ID = 3265 AND V3265.IS_DEL = 0
      WHERE L154.PARENT_ID = :V$PLAN_ID AND L154.OBJ_TYPE_ID = 154 AND L154.DATE_DEL IS NULL
      ORDER BY 1
      INTO :D1, :D2, :S
    DO
    BEGIN
      TAG_NAME = 'calendar:vacation:r:periods';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'calendar:vacation:r:periods:name';
      VAL = S;
      SUSPEND;
      TAG_NAME = 'calendar:vacation:r:periods:date_from';
      VAL = (SELECT RESULT FROM DATE2STR(:D1));
      SUSPEND;
      TAG_NAME = 'calendar:vacation:r:periods:date_to';
      VAL = (SELECT RESULT FROM DATE2STR(:D2));
      SUSPEND;
    END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OPTEXT_MOVE (
    I$OBJ_ID BIGINT NOT NULL,
    I$DEST_ID BIGINT NOT NULL,
    I$AS_CHILD SMALLINT,
    I$USER_ID VARCHAR(40))
AS
DECLARE VARIABLE P BIGINT;
DECLARE VARIABLE PP BIGINT;
DECLARE VARIABLE V$OP_ID_DEST BIGINT;
DECLARE VARIABLE V$PARENT_DEST BIGINT;
DECLARE VARIABLE V$OP_ID BIGINT;
begin

  -- Нельзя перемещать объект внутрь самого себя
  P = I$DEST_ID;
  WHILE(P IS NOT NULL) DO
  BEGIN
    IF(P = I$OBJ_ID) THEN EXCEPTION DATA_ERROR 'Нельзя переносить раздел внутрь самого себя';

    PP = P;
    P = NULL;
    SELECT FIRST 1 C.PARENT_ID
    FROM OP_CONTENT C
    WHERE C.OBJ_ID = :PP
    INTO :P;
  END

  SELECT C.OP_ID
  FROM OP_CONTENT C
  WHERE C.OBJ_ID = :I$OBJ_ID AND C.DATE_DEL IS NULL
  INTO :V$OP_ID;

  IF(V$OP_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Запись перемещаемого раздела не найдена';

  SELECT C.PARENT_ID, C.OP_ID
  FROM OP_CONTENT C
  WHERE C.OBJ_ID = :I$DEST_ID AND C.DATE_DEL IS NULL
  INTO :V$PARENT_DEST, :V$OP_ID_DEST;

  IF(V$OP_ID_DEST IS NULL OR V$OP_ID_DEST <> V$OP_ID) THEN EXCEPTION DATA_ERROR 'Недопустимый раздел назначения';

  -- Запоминаем диапазон нумерации элементов в перемещаемом разделе

  IF(I$AS_CHILD = 1) THEN
  BEGIN
    -- Перемещаем последним дочерним элементом указанного узла
    UPDATE OP_CONTENT
    SET PARENT_ID = :I$DEST_ID
    WHERE OBJ_ID = :I$OBJ_ID;
  END
  ELSE
  BEGIN
    -- Перемещаем следом за указанным элементом в том же уровне
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OPTEXT_SET (
    I$OP_ID BIGINT,
    I$PARENT_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$TEXT VARCHAR(1000),
    I$TYPE_ID BIGINT NOT NULL,
    I$SC_INDEX SMALLINT,
    I$CONTENT_NULL SMALLINT NOT NULL,
    I$USER_ID VARCHAR(40))
RETURNS (
    OBJ_ID BIGINT)
AS
DECLARE VARIABLE V$TEXT VARCHAR(1000);
DECLARE VARIABLE V$TYPE_ID BIGINT;
DECLARE VARIABLE V$IS_NULL SMALLINT;
DECLARE VARIABLE V$PARENT_SEQ INTEGER;
DECLARE VARIABLE V$SC_INDEX SMALLINT;
DECLARE VARIABLE N INTEGER;
begin

  -- PARENT_ID поменяться не может

  SELECT FIRST 1 C.OBJ_ID, C.TEXT, C.TYPE_ID, C.SC_INDEX, IIF(C.BLOB_DATA IS NULL, 1, 0)
  FROM OP_CONTENT C
  WHERE C.DATE_DEL IS NULL AND C.OBJ_ID = :I$OBJ_ID AND C.OP_ID = :I$OP_ID
  INTO :OBJ_ID, :V$TEXT, :V$TYPE_ID, :V$SC_INDEX, :V$IS_NULL;

  IF(I$OBJ_ID IS NOT NULL AND OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Запись не найдена';

  SELECT FIRST 1 C.SEQ_INDEX
  FROM OP_CONTENT C
  WHERE C.DATE_DEL IS NULL AND C.OBJ_ID = :I$PARENT_ID AND C.OP_ID = :I$OP_ID
  INTO :V$PARENT_SEQ;

  IF(I$PARENT_ID IS NOT NULL AND V$PARENT_SEQ IS NULL) THEN EXCEPTION DATA_ERROR 'Родительская запись не найдена';

  IF(I$OBJ_ID IS NULL) THEN
  BEGIN
    IF(I$PARENT_ID IS NULL) THEN
    BEGIN
      -- Добавление в самый конец - нумерация остается как есть
      SELECT FIRST 1 C.SEQ_INDEX
      FROM OP_CONTENT C
      WHERE C.DATE_DEL IS NULL AND C.OP_ID = :I$OP_ID
      ORDER BY 1 DESC
      INTO :N;
      IF(N IS NULL) THEN N = 0; ELSE N = N + 1;
    END
    ELSE
    BEGIN
      -- Добавление в конец уровня - надо сдвинуть нумерацию
      SELECT FIRST 1 C.SEQ_INDEX
      FROM OP_CONTENT C
      WHERE C.DATE_DEL IS NULL AND C.OP_ID = :I$OP_ID AND C.PARENT_ID = :I$PARENT_ID
      ORDER BY 1 DESC
      INTO :N;
      -- Если сейчас дочерних элементов нет - встаем сразу за родителем
      IF(N IS NULL) THEN N = V$PARENT_SEQ + 1; ELSE N = N + 1;

      UPDATE OP_CONTENT
      SET SEQ_INDEX = SEQ_INDEX + 1
      WHERE DATE_DEL IS NULL AND OP_ID = :I$OP_ID AND SEQ_INDEX >= :N;
    END

    INSERT INTO OP_CONTENT
    (OP_ID, PARENT_ID, TYPE_ID, TEXT, SEQ_INDEX, SC_INDEX)
    VALUES (:I$OP_ID, :I$PARENT_ID, :I$TYPE_ID, :I$TEXT, :N, :I$SC_INDEX)
    RETURNING OBJ_ID INTO :OBJ_ID;
  END
  ELSE BEGIN
    -- Изменение строки порядок нумерации не меняет
    IF(I$TEXT <> V$TEXT OR I$TYPE_ID <> V$TYPE_ID OR COALESCE(I$SC_INDEX, -1) <> COALESCE(V$SC_INDEX, -1)) THEN
    UPDATE OP_CONTENT
    SET TYPE_ID = :I$TYPE_ID, TEXT = :I$TEXT, SC_INDEX = :I$SC_INDEX
    WHERE OBJ_ID = :I$OBJ_ID;

    IF(I$CONTENT_NULL <> V$IS_NULL AND I$CONTENT_NULL = 1) THEN
    UPDATE OP_CONTENT
    SET BLOB_DATA = NULL
    WHERE OBJ_ID = :I$OBJ_ID;
  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OP_ENSURE_UNQ (
    I$OBJ_ID BIGINT,
    I$OP_TYPE BIGINT)
AS
begin

  IF(EXISTS(
    SELECT FIRST 1 1
    FROM LINKS LP2
    JOIN LINKS L69 ON L69.PARENT_ID = LP2.PARENT_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL AND L69.OBJ_ID <> LP2.OBJ_ID
    JOIN VALL V2450 ON V2450.OBJ_ID = L69.OBJ_ID AND V2450.PARAM_ID = 2450 AND V2450.IS_DEL = 0 AND V2450.LISTVAL_ID = :I$OP_TYPE
    WHERE LP2.OBJ_ID = :I$OBJ_ID AND LP2.PARENT_TYPE_ID = 2 AND LP2.DATE_DEL IS NULL
  ))
  THEN
    EXCEPTION DATA_ERROR 'Каталог ОП не может повторяться для одного и того же вида образования';

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE ORDER_CHECK_PRINTED (
    I$ORDER_ID BIGINT,
    I$NEW_STATE BIGINT,
    I$USER_ID VARCHAR(40))
AS
declare variable V varchar(400);
declare variable V$PERSON_ID bigint;
declare variable V$DOC_ID bigint;
declare variable N integer;
declare variable RN integer;
declare variable V$ORDER_DATE date;
declare variable V$ACTION_DATE date;
declare variable V$ORDER_NUM varchar(100);
declare variable V$TYPE_ID bigint;
begin

  SELECT MON$DATABASE_NAME
  FROM MON$DATABASE
  INTO :V;

  V = REPLACE(V, 'BASE.FDB', 'DOC.FDB');
  N = 0;

  FOR
    SELECT D.REF_ID, DD.TYPE_ID
    FROM ORDER_DATA D
    JOIN ORDERS DD ON DD.OBJ_ID = D.ORDER_ID
    WHERE D.DATE_DEL IS NULL AND D.ORDER_ID = :I$ORDER_ID
    INTO :V$PERSON_ID, :V$TYPE_ID
  DO
  BEGIN
    N = N + 1;
    V$DOC_ID = NULL;
    IF(I$NEW_STATE = 11715) THEN
    BEGIN
      -- Действующий приказ. Должен быть распечатанный аттестат
      EXECUTE STATEMENT
        'SELECT FIRST 1 D.OBJ_ID
        FROM DOCUMENTS D
        WHERE D.DATE_DEL IS NULL AND D.ORDER_ID = ' || I$ORDER_ID || ' AND D.PERSON_ID = ' || V$PERSON_ID || ' AND D.STATE_ID = 1'
      ON EXTERNAL :V
      WITH COMMON TRANSACTION
      INTO :V$DOC_ID;

      IF(V$DOC_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Документ не распечатан по обучающемуся ' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$PERSON_ID));
    END
    ELSE IF(I$NEW_STATE = 11716) THEN
    BEGIN
      -- Проект приказа. Не должно быть запечатанных аттестатов
      EXECUTE STATEMENT
        'SELECT FIRST 1 D.OBJ_ID
        FROM DOCUMENTS D
        WHERE D.DATE_DEL IS NULL AND D.ORDER_ID = ' || I$ORDER_ID || ' AND D.PERSON_ID = ' || V$PERSON_ID || ' AND D.STATE_ID = 4'
      ON EXTERNAL :V
      WITH COMMON TRANSACTION
      INTO :V$DOC_ID;

      IF(V$DOC_ID IS NOT NULL) THEN EXCEPTION DATA_ERROR 'Документ распечатан и закрыт по обучающемуся ' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$PERSON_ID));
    END
    ELSE IF(I$NEW_STATE = 11717) THEN
    BEGIN
      -- Не действующий. Не должно быть проектов и действующих
      EXECUTE STATEMENT
        'SELECT FIRST 1 D.OBJ_ID
        FROM DOCUMENTS D
        WHERE D.DATE_DEL IS NULL AND D.ORDER_ID = ' || I$ORDER_ID || ' AND D.PERSON_ID = ' || V$PERSON_ID || ' AND D.STATE_ID <> 2'
      ON EXTERNAL :V
      WITH COMMON TRANSACTION
      INTO :V$DOC_ID;

      IF(V$DOC_ID IS NOT NULL) THEN EXCEPTION DATA_ERROR 'Есть проект документа или действующий документ по обучающемуся ' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$PERSON_ID));
    END
  END

  -- Проверяем количество проектов и уже распечатанных
  -- Изменение: испорченный бланк теперь тоже считается, если внесен в книгу выдачи, и нет нового документа на замену
  IF(I$NEW_STATE = 11715) THEN
  BEGIN
    EXECUTE STATEMENT
      'SELECT COUNT(*)
      FROM DOCUMENTS D
      JOIN BLANKS B ON B.OBJ_ID = D.BLANK_ID AND B.DATE_DEL IS NULL
      WHERE D.DATE_DEL IS NULL AND D.ORDER_ID = ' || I$ORDER_ID || ' AND D.STATE_ID IN (0, 1, 4) AND (B.STATE_ID = 1 OR (B.STATE_ID = 2 AND D.SEQ_NO IS NOT NULL
        AND NOT EXISTS(SELECT FIRST 1 1 FROM DOCUMENTS D2 WHERE D2.DATE_DEL IS NULL AND D2.ORDER_ID = D.ORDER_ID AND D2.PARENT_ID = D.OBJ_ID)))'
    ON EXTERNAL :V
    -- ROLE 'INISSOFT_ROLE'
    WITH COMMON TRANSACTION
    INTO :RN;

    -- Кроме справки для оригиналов, кто по справкам делает приказ
    IF(V$TYPE_ID <> 99999 AND RN <> N) THEN EXCEPTION DATA_ERROR 'Количество документов к выдаче не соответствует количеству учеников в приказе (должно быть ' || N || ', по факту ' || RN || ')';

    -- Обновляем сохраненные реквизиты приказа в документах
    SELECT D.ORDER_DATE, D.ACTION_DATE, D.ORDER_NUM
    FROM ORDERS D
    WHERE D.OBJ_ID = :I$ORDER_ID
    INTO :V$ORDER_DATE, :V$ACTION_DATE, :V$ORDER_NUM;

    EXECUTE STATEMENT
      'UPDATE DOCUMENTS
      SET ORDER_DATE = ''' || V$ORDER_DATE || ''', ACTION_DATE = ''' || V$ACTION_DATE || ''', ORDER_NUM = ''' || V$ORDER_NUM || '''
      WHERE ORDER_ID = ' || I$ORDER_ID
    ON EXTERNAL :V
    -- ROLE 'INISSOFT_ROLE'
    WITH COMMON TRANSACTION;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE ORDER_DELETE (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
AS
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$STATE_ID BIGINT;
DECLARE VARIABLE V$TYPE_ID BIGINT;
DECLARE VARIABLE CAN_DEL INTEGER;
DECLARE VARIABLE S VARCHAR(1000);
begin

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;
  IF(NOT EXISTS(
    SELECT 1
    FROM USERS U
    WHERE U.DATE_DEL IS NULL AND U.USER_ID = :I$USER_ID AND U.USER_TYPE IN (1, 5, 6)
  ))
  THEN EXCEPTION DATA_ERROR 'Удалять приказы может только руководитель';

  -- Удалять приказы может только руководитель
  -- Утвержденные приказы удалять нельзя, также нельзя удалять старые версии приказов
  SELECT FIRST 1 OBJ_ID, STATE_ID, TYPE_ID
  FROM ORDERS
  WHERE OBJ_ID = :I$OBJ_ID
  INTO :V$OBJ_ID, :V$STATE_ID, :V$TYPE_ID;

  IF(V$OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Запись не найдена';
  IF(V$STATE_ID IN (11715)) THEN EXCEPTION DATA_ERROR 'Нельзя удалить действующий приказ';

  -- Очищаем настройки по обучающимся в приказе
  FOR
    SELECT OD.REF_ID
    FROM ORDER_DATA OD
    WHERE OD.DATE_DEL IS NULL AND OD.ORDER_ID = :I$OBJ_ID
    INTO :V$OBJ_ID
  DO
  BEGIN
    UPDATE VALS
    SET IS_DEL = 1
    WHERE IS_DEL = 0 AND OBJ_ID = :V$OBJ_ID AND PARAM_ID IN (3025);
  END

  -- Если при удалении приказа о приеме на должность, у сотрудника нет ни одной активной должности, то надо сотрудника удалить совсем
  IF (V$TYPE_ID = 14256) THEN
  BEGIN
    FOR
      SELECT OD.REF_ID
      FROM ORDER_DATA OD
      WHERE OD.DATE_DEL IS NULL AND OD.ORDER_ID = :I$OBJ_ID
      INTO :V$OBJ_ID  -- сотрудник
    DO
    BEGIN
      IF (NOT EXISTS(SELECT FIRST 1 1
        FROM LINKS L15
        LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
        WHERE L15.OBJ_TYPE_ID = 15 AND L15.PARENT_TYPE_ID = 13 AND L15.DATE_DEL IS NULL AND V74.VAL IS NULL
      )) THEN
      BEGIN
        SELECT CAN_DELETE, ERR_MSG FROM PARAGRAF_CAN_DELETE_OBJECT(:V$OBJ_ID)
        INTO :CAN_DEL, :S;
        IF (CAN_DEL = 1) THEN
        BEGIN
          V$TYPE_ID = NULL;
          SELECT L.PARENT_ID
          FROM LINKS L
          WHERE L.OBJ_ID = :V$OBJ_ID AND L.PARENT_TYPE_ID IN (2, 211) AND L.DATE_DEL IS NULL
          INTO :V$TYPE_ID;

          SELECT DEL_COUNT FROM OBJECT_DEL(:V$TYPE_ID, :V$OBJ_ID) INTO CAN_DEL;
        END
        ELSE
          EXCEPTION DATA_ERROR(S);
      END
    END
  END

  UPDATE ORDERS
  SET DATE_DEL = CURRENT_TIMESTAMP
  WHERE OBJ_ID = :I$OBJ_ID;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE ORDER_GET (
    I$OBJ_ID BIGINT,
    I$TYPE_ID BIGINT,
    I$USER_ID VARCHAR(40),
    I$OWNER_ID BIGINT = NULL)
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$ORDER_NUM VARCHAR(1000);
DECLARE VARIABLE V$ORDER_DATE DATE;
DECLARE VARIABLE V$ACTION_DATE DATE;
DECLARE VARIABLE V$CANCEL_DATE DATE;
DECLARE VARIABLE V$PARENT_ID BIGINT;
DECLARE VARIABLE V$TYPE_ID BIGINT;
DECLARE VARIABLE V$SIGNED_BY BIGINT;
DECLARE VARIABLE V$STATE_ID BIGINT;
DECLARE VARIABLE V$DETAILS_TEXT VARCHAR(1000);
DECLARE VARIABLE V$OLD_NAME VARCHAR(400);
DECLARE VARIABLE V$NEW_NAME VARCHAR(400);
DECLARE VARIABLE V$COST INTEGER;
DECLARE VARIABLE V$COMMENTS VARCHAR(1000);
DECLARE VARIABLE S VARCHAR(200);
DECLARE VARIABLE P INTEGER;
DECLARE VARIABLE N INTEGER;
DECLARE VARIABLE V$GROUP_ID BIGINT;
DECLARE VARIABLE V$STAGE_ID BIGINT;
DECLARE VARIABLE V$REF_ID BIGINT;
DECLARE VARIABLE V$OU_LICENCE_TYPE CHAR(1);
DECLARE VARIABLE V$IP SMALLINT;
DECLARE VARIABLE V$SUBTYPE_ID BIGINT;
DECLARE VARIABLE V$LIST_ID BIGINT;
DECLARE VARIABLE V$LEVEL_ID BIGINT;
DECLARE VARIABLE V$PERSON_ID BIGINT;
DECLARE VARIABLE NROWS INTEGER;
DECLARE VARIABLE V VARCHAR(400);
DECLARE VARIABLE V$PREV_BD DATE;
DECLARE VARIABLE V$NEW_BD DATE;
DECLARE VARIABLE V$PREV_DATE DATE;
DECLARE VARIABLE V$SPO_FIN BIGINT;
DECLARE VARIABLE V$MASTER_ID BIGINT;
DECLARE VARIABLE V$JOB_ID BIGINT;
DECLARE VARIABLE V$RATE FLOAT;
DECLARE VARIABLE V$CND BIGINT;
DECLARE VARIABLE V$ACTION_ID BIGINT;
DECLARE VARIABLE V$SAVED_JOB_ID BIGINT;
DECLARE VARIABLE V$OWNER_ID BIGINT;
DECLARE VARIABLE V$JOB_ID2 BIGINT;
DECLARE VARIABLE V$SAVED_JOB_ID2 BIGINT;
DECLARE VARIABLE V$ORDER_REF_ID BIGINT;
DECLARE VARIABLE V$HAS_OO SMALLINT;
DECLARE VARIABLE V$HAS_SPO SMALLINT;
DECLARE VARIABLE V$OU_ID BIGINT;
DECLARE VARIABLE B BIGINT;
DECLARE VARIABLE B1 BIGINT;
DECLARE VARIABLE B2 BIGINT;
DECLARE VARIABLE V$CAT_ID BIGINT;
begin

  -- I$TYPE_ID -1 при печати приказа, для остальных случаев передается NULL или реальный тип (при созданиии нового)

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  SELECT D.OBJ_ID, D.ORDER_NUM, D.ORDER_DATE, D.ACTION_DATE, D.CANCEL_DATE, D.PARENT_ID, D.TYPE_ID, D.SIGNED_BY, D.STATE_ID, D.DETAILS_TEXT,
    D.PROJECT_NUM, D.COMMENTS, D.SUBTYPE_ID, D.OWNER_ID, D.REF_ID
  FROM ORDERS D
  WHERE D.OBJ_ID = :I$OBJ_ID AND D.DATE_DEL IS NULL
  INTO :V$OBJ_ID, :V$ORDER_NUM, :V$ORDER_DATE, :V$ACTION_DATE, :V$CANCEL_DATE, :V$PARENT_ID, :V$TYPE_ID, :V$SIGNED_BY, :V$STATE_ID, :V$DETAILS_TEXT,
    :S, :V$COMMENTS, :V$SUBTYPE_ID, :V$OWNER_ID, :V$ORDER_REF_ID;

  IF(I$OBJ_ID IS NOT NULL AND V$OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Запись не найдена';
  IF(I$OBJ_ID IS NULL) THEN
  BEGIN
    V$TYPE_ID = I$TYPE_ID;
    V$OWNER_ID = I$OWNER_ID;
  END
  IF(I$OBJ_ID IS NULL AND I$TYPE_ID = 12964) THEN EXCEPTION DATA_ERROR 'Приказы о создании учебных коллективов формируются только автоматически при переводе года';

  V$OU_LICENCE_TYPE = (SELECT STATUS FROM OU_LICENCE_TYPE);
  V$STATE_ID = COALESCE(V$STATE_ID, 11716);

  IF(V$OBJ_ID IS NULL) THEN
  BEGIN
    SELECT FIRST 1 L2.OBJ_ID
    FROM LINKS L2
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :V$OU_ID;
  END
  ELSE
  BEGIN
    B = V$OBJ_ID / (SELECT MULTIPLIER FROM GEN);
    B1 = B * (SELECT MULTIPLIER FROM GEN);
    B2 = (B + 1) * (SELECT MULTIPLIER FROM GEN);

    SELECT FIRST 1 L2.OBJ_ID
    FROM LINKS L2
    WHERE (L2.PARENT_ID IS NULL OR L2.PARENT_TYPE_ID IN (111, 112)) AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND L2.OBJ_ID >= :B1 AND L2.OBJ_ID < :B2
    INTO :V$OU_ID;
  END

  V$HAS_OO = 0;
  V$HAS_SPO = 0;
  SELECT FIRST 1 1
  FROM LINKS L472
  JOIN VALL V3327 ON V3327.OBJ_ID = L472.OBJ_ID AND V3327.PARAM_ID = 3327 AND V3327.IS_DEL = 0 AND V3327.LISTVAL_ID IN (22, 26, 27)
  WHERE L472.PARENT_ID = :V$OU_ID AND L472.OBJ_TYPE_ID = 472 AND L472.DATE_DEL IS NULL
  INTO :V$HAS_OO;

  SELECT FIRST 1 1
  FROM LINKS L472
  JOIN VALL V3327 ON V3327.OBJ_ID = L472.OBJ_ID AND V3327.PARAM_ID = 3327 AND V3327.IS_DEL = 0 AND V3327.LISTVAL_ID IN (28, 29, 13129)
  WHERE L472.PARENT_ID = :V$OU_ID AND L472.OBJ_TYPE_ID = 472 AND L472.DATE_DEL IS NULL
  INTO :V$HAS_SPO;

  TAG_NAME = 'lic_type';
  VAL = V$OU_LICENCE_TYPE;
  SUSPEND;

  TAG_NAME = 'id';
  VAL = V$OBJ_ID;
  SUSPEND;

  TAG_NAME = 'project_num';
  VAL = S;
  SUSPEND;

  TAG_NAME = 'order_num';
  VAL = COALESCE(V$ORDER_NUM, 'АВТО');
  SUSPEND;

  TAG_NAME = 'order_num_text';
  VAL = COALESCE(V$ORDER_NUM, '______________________');
  SUSPEND;

  TAG_NAME = 'order_date';
  VAL = (SELECT VAL FROM DATE2ISO(:V$ORDER_DATE));
  SUSPEND;

  -- Дата +10 дней от даты приказа
  TAG_NAME = 'complete_order_date';
  VAL = (SELECT RESULT FROM DATE2STR(DATEADD(10 DAY TO :V$ORDER_DATE)));
  SUSPEND;

  -- Дата в скриптовом виде
  TAG_NAME = 'order_date_text';
  VAL = (SELECT VAL FROM DATE2SCRIPT(:V$ORDER_DATE));
  SUSPEND;

  TAG_NAME = 'action_date';
  VAL = (SELECT VAL FROM DATE2ISO(:V$ACTION_DATE));
  SUSPEND;

  TAG_NAME = 'action_date_text';
  VAL = (SELECT VAL FROM DATE2SCRIPT(:V$ACTION_DATE));
  SUSPEND;

  TAG_NAME = 'cancel_date';
  VAL = (SELECT VAL FROM DATE2ISO(:V$CANCEL_DATE));
  SUSPEND;

  TAG_NAME = 'cancel_date_text';
  VAL = (SELECT VAL FROM DATE2SCRIPT(:V$CANCEL_DATE));
  SUSPEND;

  TAG_NAME = 'parent_id';
  VAL = V$PARENT_ID;
  SUSPEND;

  TAG_NAME = 'owner_id';
  VAL = V$OWNER_ID;
  SUSPEND;

  TAG_NAME = 'ref_id';
  VAL = V$ORDER_REF_ID;
  SUSPEND;

  -- Это что вообще за поле ?
  TAG_NAME = 'has_children';
  VAL = 0;
  SELECT FIRST 1 1
  FROM ORDERS
  WHERE OBJ_ID = :V$OBJ_ID AND DATE_DEL IS NULL
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'details_text';
  VAL = V$DETAILS_TEXT;
  SUSPEND;

  TAG_NAME = 'comments';
  VAL = V$COMMENTS;
  SUSPEND;

  -- Фрагменты для печати приказов
  TAG_NAME = 'person_prefix';
  IF(V$OU_LICENCE_TYPE = 'D') THEN VAL = 'воспитанников'; ELSE VAL = 'обучающихся';
  SUSPEND;

  TAG_NAME = 'base_prefix';
  IF(V$OU_LICENCE_TYPE IN ('S', 'D')) THEN VAL = ''; ELSE VAL = ' или заявление совершеннолетнего гражданина';
  SUSPEND;

  TAG_NAME = 'person_appeal';
  IF(V$OU_LICENCE_TYPE = 'D') THEN VAL = 'ребенка';
  ELSE IF(V$TYPE_ID = 12929) THEN VAL = 'зачисляемого';
  ELSE VAL = 'обучающегося';
  SUSPEND;

  TAG_NAME = 'grade_prefix1';
  VAL = '';
  IF(V$OU_LICENCE_TYPE = 'C') THEN VAL = 'группы ';
  SUSPEND;

  TAG_NAME = 'grade_suffix1';
  VAL = '';
  IF(V$OU_LICENCE_TYPE IN ('O', 'S')) THEN VAL = ' класса';
  SUSPEND;

  TAG_NAME = 'grade_prefix2';
  VAL = '';
  IF(V$OU_LICENCE_TYPE = 'C') THEN VAL = 'группу ';
  SUSPEND;

  TAG_NAME = 'grade_suffix2';
  VAL = '';
  IF(V$OU_LICENCE_TYPE IN ('O', 'S')) THEN VAL = ' класс';
  SUSPEND;

  TAG_NAME = 'leave_suffix';
  VAL = '';
  IF(V$OU_LICENCE_TYPE = 'O') THEN VAL = 'учащихся 11 классов';
  ELSE IF(V$OU_LICENCE_TYPE = 'D') THEN VAL = 'воспитанников';
  ELSE VAL = 'обучающихся';
  SUSPEND;

  TAG_NAME = 'move_title';
  VAL = 'на следующий этап обучения';
  IF(V$OU_LICENCE_TYPE = 'O') THEN VAL = 'в следующий класс';
  SUSPEND;

  TAG_NAME = 're_group';
  VAL = 'учебный коллектив';
  IF(V$OU_LICENCE_TYPE = 'O') THEN VAL = 'класс';
  SUSPEND;

  TAG_NAME = 're_prefix';
  VAL = '';
  IF(V$OU_LICENCE_TYPE = 'C') THEN VAL = 'группу ';
  SUSPEND;

  TAG_NAME = 're_suffix';
  VAL = '';
  IF(V$OU_LICENCE_TYPE = 'O') THEN VAL = ' класс';
  SUSPEND;

  TAG_NAME = 're_content';
  VAL = '';
  IF(V$OU_LICENCE_TYPE IN ('O', 'C', 'S')) THEN VAL = 'не устранивших в установленный срок академическую задолженность, ';
  SUSPEND;

  -- Раздел нумерации - смотрим id родительского раздела
  SELECT FIRST 1 LV2.LISTVAL_ID
  FROM LISTVALS LV
  JOIN LISTVALS LV2 ON LV2.IS_DEL = 0 AND LV2.LIST_ID = LV.LIST_ID AND LV2.PARENT_ID = LV.PARENT_ID AND LV2.COST < 0
  WHERE LV.IS_DEL = 0 AND LV.LIST_ID = 322 AND LV.LISTVAL_ID = :V$TYPE_ID
  INTO :V$MASTER_ID;

  TAG_NAME = 'type_id:values:value';
  VAL = V$TYPE_ID;
  SUSPEND;
  TAG_NAME = 'type_id:parent_id';
  VAL = V$MASTER_ID;
  SUSPEND;
  TAG_NAME = 'type_id:selection::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT LISTVAL_ID, VAL
    FROM LISTVALS_LIST(322)
    WHERE IS_DEL = 0
    INTO :V$OBJ_ID, :V$DETAILS_TEXT
  DO
  BEGIN
    TAG_NAME = 'type_id:selection:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'type_id:selection:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'type_id:selection:r:value';
    VAL = V$DETAILS_TEXT;
    SUSPEND;
  END

  -- Выбираем правила нумерации для данного типа приказов
  TAG_NAME = 'numbering_rule';
  VAL = NULL;
  SELECT FIRST 1 V3031.VAL
  FROM LINKS L2
  JOIN LINKS L406 ON L406.PARENT_ID = L2.OBJ_ID AND L406.OBJ_TYPE_ID = 406 AND L406.DATE_DEL IS NULL
  JOIN VALL V3029 ON V3029.OBJ_ID = L406.OBJ_ID AND V3029.PARAM_ID = 3029 AND V3029.IS_DEL = 0 AND (V3029.LISTVAL_ID = :V$TYPE_ID OR V3029.LISTVAL_ID = :V$MASTER_ID)
  JOIN VALS V3031 ON V3031.OBJ_ID = L406.OBJ_ID AND V3031.PARAM_ID = 3031 AND V3031.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :VAL;
  IF(VAL IS NULL) THEN EXCEPTION DATA_ERROR 'Для данного типа приказов не внесено правило нумерации. Внесите правило в приложении - Структура ОООД (Документы ОООД)';
  SUSPEND;

  TAG_NAME = 'state_id:values:value';
  VAL = V$STATE_ID;
  SUSPEND;
  TAG_NAME = 'state_id:selection::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT LISTVAL_ID, VAL
    FROM LISTVALS_LIST(304)
    WHERE IS_DEL = 0 AND LISTVAL_ID <> 14261 -- кроме архивного
    INTO :V$OBJ_ID, :V$DETAILS_TEXT
  DO
  BEGIN
    TAG_NAME = 'state_id:selection:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'state_id:selection:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'state_id:selection:r:value';
    VAL = V$DETAILS_TEXT;
    SUSPEND;
  END

  TAG_NAME = 'signed_by:values:value';
  VAL = V$SIGNED_BY;
  SUSPEND;
  TAG_NAME = 'signed_by:selection::json&colon;array';
  VAL = 1;
  SUSPEND;
  -- Выбираем действующих сотрудников, плюс сотрудника уже указанного как подписанта
  FOR
    SELECT DISTINCT LP.OBJ_ID, C.NAME_FULL
    FROM (
      SELECT L14.OBJ_ID
      FROM LINKS L2
      JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      UNION
      SELECT L14.OBJ_ID
      FROM LINKS L2
      JOIN LINKS L211 ON L211.PARENT_ID = L2.OBJ_ID AND L211.OBJ_TYPE_ID = 211 AND L211.DATE_DEL IS NULL
      JOIN LINKS L14 ON L14.PARENT_ID = L211.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      UNION
      SELECT :V$SIGNED_BY
      FROM RDB$DATABASE
    ) LP
    JOIN LINKS L15 ON L15.PARENT_ID = LP.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
    JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
    LEFT JOIN VALL V64 ON V64.OBJ_ID = LP13.PARENT_ID AND V64.PARAM_ID = 64 AND V64.IS_DEL = 0
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
    LEFT JOIN VALL V3343 ON V3343.OBJ_ID = LP.OBJ_ID AND V3343.PARAM_ID = 3343 AND V3343.IS_DEL = 0
    LEFT JOIN UT_PERSON_DESC(LP.OBJ_ID) C ON 1 = 1
    WHERE V74.OBJ_ID IS NULL AND (V64.LISTVAL_ID = 56 OR V3343.LISTVAL_ID = 2)
    ORDER BY 2
    INTO :V$OBJ_ID, :V$DETAILS_TEXT
  DO
  BEGIN
    TAG_NAME = 'signed_by:selection:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'signed_by:selection:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'signed_by:selection:r:value';
    VAL = V$DETAILS_TEXT;
    SUSPEND;
  END

  -- Действующие строки контента
  -- Пока считаем что это все записи движения
  TAG_NAME = 'actions::json&colon;array';
  VAL = 1;
  SUSPEND;
  NROWS = 0;
  FOR
    -- Учеников сортируем по разному в зависимости от типа приказа
    SELECT D.OBJ_ID, D.ACTION_TYPE, D.REF_ID, D.JOB_ID, C.NAME_FULL, COALESCE(D.GRADE_NAME, IIF(:V$STATE_ID = 11716, V3025.SVAL, M.NAME_IN)), M.GROUP_ID, M.STAGE_ID, D.IS_PRESENT,
      D.GRADE_NAME, D.DST_DATA, D.ACTION_ID, D.JOB_ID2
    FROM ORDER_DATA D
    LEFT JOIN PERSON_MOVEMENTS M ON M.OBJ_ID = D.ACTION_ID AND :V$STATE_ID = 11715
    LEFT JOIN UT_PERSON_DESC(D.REF_ID) C ON 1 = 1
    LEFT JOIN VALS V3025 ON V3025.OBJ_ID = D.REF_ID AND V3025.PARAM_ID = 3025 AND V3025.IS_DEL = 0
    WHERE D.DATE_DEL IS NULL AND D.ORDER_ID = :I$OBJ_ID
    ORDER BY 7, 5, 4
    INTO :V$OBJ_ID, :V$PARENT_ID, :V$REF_ID, :V$JOB_ID, :V$DETAILS_TEXT, :S, :V$GROUP_ID, :V$STAGE_ID, :V$IP,
      :V$OLD_NAME, :V$ORDER_NUM, :V$ACTION_ID, :V$JOB_ID2
  DO
  BEGIN
    NROWS = NROWS + 1;
    TAG_NAME = 'actions:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'actions:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'actions:r:type';
    VAL = V$PARENT_ID;
    SUSPEND;
    TAG_NAME = 'actions:r:ref_id';
    VAL = V$REF_ID;
    V$PERSON_ID = V$REF_ID; -- запоминаем персону, если она одна - для приказов по аттестатам
    SUSPEND;
    TAG_NAME = 'actions:r:job_id';
    VAL = V$JOB_ID;
    V$SAVED_JOB_ID = V$JOB_ID; -- запоминаем выбранную должность
    SUSPEND;
    TAG_NAME = 'actions:r:new_id';
    VAL = V$JOB_ID2;
    V$SAVED_JOB_ID2 = V$JOB_ID2; -- запоминаем новую должность
    SUSPEND;
    TAG_NAME = 'actions:r:action_id';
    VAL = V$ACTION_ID;
    SUSPEND;
    TAG_NAME = 'actions:r:is_present';
    VAL = V$IP;
    SUSPEND;
    -- В grade_name для приказов по персоналу содержатся названия и старой, и новой должностей
    -- тут берем название старой
    IF(POSITION('|' IN V$DETAILS_TEXT) > 0) THEN V$DETAILS_TEXT = SUBSTRING(V$DETAILS_TEXT FROM 1 FOR POSITION('|' IN V$DETAILS_TEXT) - 1);
    TAG_NAME = 'actions:r:name';
    VAL = V$DETAILS_TEXT;
    SUSPEND;
    TAG_NAME = 'actions:r:name_full';
    VAL = V$DETAILS_TEXT;
    SUSPEND;
    TAG_NAME = 'actions:r:grade_id';
    VAL = V$GROUP_ID;
    SUSPEND;
    -- Сюда кладем полный текст
    TAG_NAME = 'actions:r:grade_name';
    VAL = S;
    SUSPEND;
    -- Разбиваем на старое и новое название
    TAG_NAME = 'actions:r:grade_name_old';
    IF(POSITION('|' IN S) > 0) THEN VAL = SUBSTRING(S FROM 1 FOR POSITION('|' IN S) - 1); ELSE VAL = S;
    SUSPEND;
    -- Для печати аттестатов - отдаем class_name с тем же значением
    -- а также тип медали при ее наличии
    IF(V$TYPE_ID = 13326) THEN
    BEGIN
      TAG_NAME = 'actions:r:class_name';
      SUSPEND;
      TAG_NAME = 'actions:r:medal';
      VAL = NULL;
      SELECT FIRST 1 V3479.LISTVAL_ID
      FROM VALL V3479
      WHERE V3479.OBJ_ID = :V$REF_ID AND V3479.PARAM_ID = 3479 AND V3479.IS_DEL = 0
      INTO :VAL;
      SUSPEND;
    END
    TAG_NAME = 'actions:r:grade_name_new';
    IF(POSITION('|' IN S) > 0) THEN VAL = SUBSTRING(S FROM POSITION('|' IN S) + 1); ELSE VAL = S;
    SUSPEND;
    TAG_NAME = 'actions:r:stage_id';
    VAL = V$STAGE_ID;
    SUSPEND;
    TAG_NAME = 'actions:r:dst_data';
    VAL = V$ORDER_NUM;
    SUSPEND;
    TAG_NAME = 'actions:r:stage_name';
    VAL = NULL;
    SELECT R.VAL
    FROM LISTVALS LV
    JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
    WHERE LV.LISTVAL_ID = :V$STAGE_ID
    INTO :VAL;
    SUSPEND;

    IF(V$TYPE_ID = 12929 AND V$STATE_ID = 11716) THEN
    BEGIN
      TAG_NAME = 'actions:r:spcode';
      VAL = NULL;
      IF(V$OU_LICENCE_TYPE IN ('C', 'S')) THEN
      SELECT FIRST 1 V.VAL
      FROM VALS V
      WHERE V.OBJ_ID = :V$OBJ_ID AND V.PARAM_ID = 3380 AND V.IS_DEL = 0
      INTO :VAL;
      SUSPEND;
    END

    -- Для проекта приказа берем данные из #3025, для утвержденного и отменного из реестра движения (запись движения все равно сохранится)
    -- для приказов выбытия там будут данные зачисления
    TAG_NAME = 'actions:r:destination';
    -- Приказ о переводе по параллели на стадии проекта - нужно достать название будущего класса
    IF(V$TYPE_ID = 12932 AND V$STATE_ID = 11716) THEN
    BEGIN
      SELECT FIRST 1 COALESCE(V54.SVAL, ''), COALESCE(V3118.SVAL, ''), LV.COST
      FROM LINKS LP9
      JOIN LINKS LP8 ON LP8.OBJ_ID = LP9.PARENT_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
      JOIN VALL V49 ON V49.OBJ_ID = LP8.PARENT_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
      JOIN LISTVALS LV ON LV.LISTVAL_ID = V49.LISTVAL_ID
      LEFT JOIN VALS V54 ON V54.OBJ_ID = LP9.PARENT_ID AND V54.PARAM_ID = 54 AND V54.IS_DEL = 0
      LEFT JOIN VALS V3118 ON V3118.OBJ_ID = LP9.PARENT_ID AND V3118.PARAM_ID = 3118 AND V3118.IS_DEL = 0
      WHERE LP9.OBJ_ID = :V$REF_ID AND LP9.PARENT_TYPE_ID IN (9, 187) AND LP9.DATE_DEL IS NULL
      ORDER BY LP9.PARENT_TYPE_ID
      INTO :V$OLD_NAME, :V$NEW_NAME, :V$COST;

      P = POSITION(';' IN V$NEW_NAME);
      V$DETAILS_TEXT = '';
      IF(P > 0) THEN
      BEGIN
        V$DETAILS_TEXT = SUBSTRING(V$NEW_NAME FROM P + 1);
        V$NEW_NAME = SUBSTRING(V$NEW_NAME FROM 1 FOR P - 1);
      END

      IF(V$NEW_NAME = '*') THEN V$NEW_NAME = 'ОШИБКА, РАСФОРМИРУЕМЫЙ КЛАСС';
      IF(V$NEW_NAME = '') THEN V$NEW_NAME = V$OLD_NAME;
      IF(V$DETAILS_TEXT <> '@' AND V$DETAILS_TEXT <> 'X') THEN V$COST = V$COST + 1;

      S = REPLACE(V$COST || ' ' || V$NEW_NAME, '  ', '');

    END
    IF(V$TYPE_ID IN (12929, 12930, 12931, 12932, 12937, 12964)) THEN
    BEGIN
      IF(POSITION('|' IN S) > 0) THEN VAL = SUBSTRING(S FROM POSITION('|' IN S) + 1); ELSE VAL = S;
    END
    ELSE
      VAL = NULL;
    SUSPEND;

    -- Данные по должности (старой и новой), чтобы сразу их отобразить без подгрузки данных
    -- Кроме случая с приемом на должность - в этом случае все поля и так есть
    IF(V$TYPE_ID IN (14257, 14258, 14259, 14272)) THEN
    BEGIN
      V$PREV_DATE = NULL;
      V$LEVEL_ID = NULL;
      V$LIST_ID = NULL;
      V$RATE = NULL;
      V$CND = NULL;
      S = NULL;
      V = NULL;
      SELECT FIRST 1 V73.VAL, V72.LISTVAL_ID, V1790.LISTVAL_ID, V71.VAL, CT.VAL, V587.LISTVAL_ID, CN.VAL, V58.LISTVAL_ID
      FROM OBJECTS L15
      JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
      JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0
      JOIN VALL V72 ON V72.OBJ_ID = L15.OBJ_ID AND V72.PARAM_ID = 72 AND V72.IS_DEL = 0
      JOIN VALF V71 ON V71.OBJ_ID = L15.OBJ_ID AND V71.PARAM_ID = 71 AND V71.IS_DEL = 0
      LEFT JOIN VALL V58 ON V58.OBJ_ID = LP13.PARENT_ID AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0
      LEFT JOIN VALL V1790 ON V1790.OBJ_ID = L15.OBJ_ID AND V1790.PARAM_ID = 1790 AND V1790.IS_DEL = 0
      LEFT JOIN LISTVAL_TEXT(V1790.LISTVAL_ID) CT ON V1790.LISTVAL_ID IS NOT NULL
      LEFT JOIN VALL V587 ON V587.OBJ_ID = L15.OBJ_ID AND V587.PARAM_ID = 587 AND V587.IS_DEL = 0
      LEFT JOIN LISTVAL_TEXT(V587.LISTVAL_ID) CN ON V587.LISTVAL_ID IS NOT NULL
      WHERE L15.OBJ_ID = :V$JOB_ID AND L15.TYPE_ID = 15 AND :V$JOB_ID IS NOT NULL
      ORDER BY 3, 5
      INTO :V$PREV_DATE, :V$LEVEL_ID, :V$LIST_ID, :V$RATE, :V, :V$CND, :S, :V$CAT_ID;

      TAG_NAME = 'actions:r:job_date';
      VAL = (SELECT VAL FROM DATE2ISO(:V$PREV_DATE, 0));
      SUSPEND;
      TAG_NAME = 'actions:r:job_type_id';
      VAL = V$LEVEL_ID;
      SUSPEND;
      TAG_NAME = 'actions:r:job_cat_id';
      VAL = V$LIST_ID;
      SUSPEND;
      TAG_NAME = 'actions:r:job_cat_name';
      VAL = V;
      SUSPEND;
      TAG_NAME = 'actions:r:job_rate';
      VAL = CAST(V$RATE AS NUMERIC(18, 2));
      SUSPEND;
      TAG_NAME = 'actions:r:job_cnd_id';
      VAL = V$CND;
      SUSPEND;
      TAG_NAME = 'actions:r:job_cnd_name';
      VAL = S;
      SUSPEND;
      TAG_NAME = 'actions:r:cat_id';
      VAL = V$CAT_ID;
      SUSPEND;

      -- Данные новой должности - тут только название, все остальное из полей DST
      TAG_NAME = 'actions:r:job_name2';
      IF(V$JOB_ID2 IS NULL) THEN VAL = NULL; ELSE VAL = SUBSTRING(V$OLD_NAME FROM POSITION('|' IN V$OLD_NAME) + 1);
      SUSPEND;
    END
    -- Для приказа об учебной нагрузке при печати расшифровываем содержимое
    IF(I$TYPE_ID < 0 AND V$TYPE_ID = 14260) THEN
    BEGIN
      TAG_NAME = 'actions:r:load::json&colon;array';
      VAL = 1;
      SUSPEND;
      WHILE(CHAR_LENGTH(V$ORDER_NUM) > 0) DO
      BEGIN
        P = POSITION(',' IN V$ORDER_NUM);
        IF(P <= 0) THEN P = CHAR_LENGTH(V$ORDER_NUM) + 1;
        V$PARENT_ID = SUBSTRING(V$ORDER_NUM FROM 1 FOR P - 1);
        V$ORDER_NUM = SUBSTRING(V$ORDER_NUM FROM P + 1);
        P = POSITION(',' IN V$ORDER_NUM);
        IF(P <= 0) THEN P = CHAR_LENGTH(V$ORDER_NUM) + 1;
        V = SUBSTRING(V$ORDER_NUM FROM 1 FOR P - 1);
        V$ORDER_NUM = SUBSTRING(V$ORDER_NUM FROM P + 1);

        TAG_NAME = 'actions:r:load:r';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'actions:r:load:r:name';
        VAL = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$PARENT_ID));
        SUSPEND;
        TAG_NAME = 'actions:r:load:r:hours';
        VAL = V;
        SUSPEND;
      END
    END
    -- Для приказов по приему-выбытию персонала и отпуску
    IF(I$TYPE_ID < 0 AND V$TYPE_ID IN (14256, 14257, 14258, 14259, 14272)) THEN
    BEGIN
      N = 1;
      WHILE(CHAR_LENGTH(V$ORDER_NUM) > 0) DO
      BEGIN
        TAG_NAME = 'actions:r:d' || N;
        P = POSITION(',' IN V$ORDER_NUM);
        IF(P <= 0) THEN P = CHAR_LENGTH(V$ORDER_NUM) + 1;
        VAL = SUBSTRING(V$ORDER_NUM FROM 1 FOR P - 1);
        V$ORDER_NUM = SUBSTRING(V$ORDER_NUM FROM P + 1);
        -- Корректируем ID в название - кроме отпуска
        IF(VAL <> '' AND (
          (V$TYPE_ID IN (14256, 14257, 14258, 14272) AND N IN (1, 2, 3, 5, 6))
        )) THEN
        BEGIN
          VAL = (SELECT VAL FROM LISTVAL_TEXT(:VAL));
        END
        SUSPEND;
        N = N + 1;
      END
    END
  END

  -- Строки, которые можно выбрать в приказ, исходя из его типа
  -- только когда приказ еще не действующий
  IF(V$TYPE_ID IN (12929) AND V$STATE_ID = 11716) THEN
  BEGIN
    -- Прием на обучение - смотрим предварительный прием
    -- Сначала список самих детей
    TAG_NAME = 'selection::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT L10.OBJ_ID, C.CAPTION, V2346.LISTVAL_ID, V3025.VAL, R.VAL
      FROM LINKS L2
      JOIN LINKS L77 ON L77.PARENT_ID = L2.OBJ_ID AND L77.OBJ_TYPE_ID = 77 AND L77.DATE_DEL IS NULL
      JOIN LINKS L290 ON L290.PARENT_ID = L77.OBJ_ID AND L290.OBJ_TYPE_ID = 290 AND L290.DATE_DEL IS NULL
      JOIN VALL V2346 ON V2346.OBJ_ID = L290.OBJ_ID AND V2346.PARAM_ID = 2346 AND V2346.IS_DEL = 0
      JOIN LISTVALS LV ON LV.LISTVAL_ID = V2346.LISTVAL_ID
      JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
      JOIN LINKS L10 ON L10.PARENT_ID = L290.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      LEFT JOIN OBJECT_CAPTION_GET(L10.OBJ_ID, 23) C ON 1 = 1
      LEFT JOIN VALS V3025 ON V3025.OBJ_ID = L10.OBJ_ID AND V3025.PARAM_ID = 3025 AND V3025.IS_DEL = 0
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      ORDER BY LV.COST, 2
      INTO :V$OBJ_ID, :V$DETAILS_TEXT, :V$PARENT_ID, :V$ORDER_NUM, :S
    DO
    BEGIN
      TAG_NAME = 'selection:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'selection:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'selection:r:stage_id';
      VAL = V$PARENT_ID;
      SUSPEND;
      TAG_NAME = 'selection:r:stage_name';
      VAL = S;
      SUSPEND;
      TAG_NAME = 'selection:r:name';
      VAL = V$DETAILS_TEXT;
      SUSPEND;
      TAG_NAME = 'selection:r:default';
      VAL = V$ORDER_NUM;
      SUSPEND;
      IF(V$TYPE_ID = 12929 AND V$STATE_ID = 11716) THEN
      BEGIN
        TAG_NAME = 'selection:r:spcode';
        VAL = NULL;
        IF(V$OU_LICENCE_TYPE IN ('C', 'S')) THEN
        SELECT FIRST 1 V.VAL
        FROM VALS V
        WHERE V.OBJ_ID = :V$OBJ_ID AND V.PARAM_ID = 3380 AND V.IS_DEL = 0
        INTO :VAL;
        SUSPEND;
      END
      TAG_NAME = 'selection:r:order';
      VAL = NULL;
      SELECT FIRST 1 D.PROJECT_NUM
      FROM ORDER_DATA OD
      JOIN ORDERS D ON D.OBJ_ID = OD.ORDER_ID AND D.DATE_DEL IS NULL AND D.STATE_ID = 11716
      WHERE OD.DATE_DEL IS NULL AND OD.REF_ID = :V$OBJ_ID
      INTO :VAL;
      SUSPEND;
    END
    -- Список, куда их определять - в grades
  END

  -- Приказы по сотрудникам
  -- Только для проекта приказа. В остальных случах оно берется из текущей строки, и при смене статуса подгружается с нуля
  IF(V$TYPE_ID IN (14256, 14257, 14258, 14259, 14260, 14271, 14272) AND V$STATE_ID = 11716) THEN
  BEGIN
    -- Список сотрудников
    TAG_NAME = 'selection::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT L14.OBJ_ID, C.NAME_FULL, 0
      FROM LINKS L2
      JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
      LEFT JOIN UT_PERSON_DESC(L14.OBJ_ID) C ON 1 = 1
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      -- Сотрудники подразделений
      UNION
      SELECT L14.OBJ_ID, C.NAME_FULL, 0
      FROM LINKS L2
      JOIN LINKS L211 ON L211.PARENT_ID = L2.OBJ_ID AND L211.OBJ_TYPE_ID = 211 AND L211.DATE_DEL IS NULL
      JOIN LINKS L14 ON L14.PARENT_ID = L211.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
      LEFT JOIN UT_PERSON_DESC(L14.OBJ_ID) C ON 1 = 1
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      -- Только для приема на работу - выбывшие сотрудники
      UNION
      SELECT L14.OBJ_ID, C.NAME_FULL, 1
      FROM LINKS L2
      JOIN LINKS L84 ON L84.PARENT_ID = L2.OBJ_ID AND L84.OBJ_TYPE_ID = 84 AND L84.DATE_DEL IS NULL
      JOIN LINKS L14 ON L14.PARENT_ID = L84.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
      LEFT JOIN UT_PERSON_DESC(L14.OBJ_ID) C ON 1 = 1
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND :V$TYPE_ID = 14256
      ORDER BY 2
      INTO :V$OBJ_ID, :S, :V$COST
    DO
    BEGIN
      TAG_NAME = 'selection:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'selection:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'selection:r:name';
      VAL = S;
      SUSPEND;
      TAG_NAME = 'selection:r:state';
      VAL = V$COST;
      SUSPEND;
      IF(V$TYPE_ID = 14260 AND V$STATE_ID = 11716) THEN
      BEGIN
        FOR
          SELECT TAG_NAME, VAL
          FROM EMPLOYEE_LOAD_GET(:V$OBJ_ID, :V$ACTION_DATE)
          INTO :TAG_NAME, :VAL
        DO
        BEGIN
          TAG_NAME = 'selection:r:' || TAG_NAME;
          SUSPEND;
        END
      END
    END
    -- Если уже есть сотрудник - список его должностей на текущую дату (если сотрудника нет, будет подгружен после выбора)
    -- Поле job_selection
    IF(V$PERSON_ID IS NOT NULL AND V$TYPE_ID NOT IN (14256, 14260, 14271)) THEN
    FOR
      SELECT TAG_NAME, VAL
      FROM EMPLOYEE_LEAVE_JOB_GET(:V$PERSON_ID, NULL, :I$USER_ID, 1)
      INTO :TAG_NAME, :VAL
    DO
    BEGIN
      SUSPEND;
    END
    -- Выбор новой должности - поле new_jobs
    IF(V$TYPE_ID IN (14256, 14258)) THEN
    BEGIN
      TAG_NAME = 'new_jobs::json&colon;array';
      VAL = 1;
      SUSPEND;
      FOR
        SELECT L.OBJ_ID, L.OBJ_CAPTION, L.COLUMN1, L.COLUMN2, L.CAT_ID
        FROM PARAGRAF_VACANCY_LIST3(:I$OWNER_ID, :V$PERSON_ID, NULL, IIF(:V$TYPE_ID = 14256, NULL, :V$SAVED_JOB_ID)) L
        INTO :V$OBJ_ID, :V$COMMENTS, :V$RATE, :S, :V$CAT_ID
      DO
      BEGIN
        TAG_NAME = 'new_jobs:r';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'new_jobs:r:id';
        VAL = V$OBJ_ID;
        SUSPEND;
        TAG_NAME = 'new_jobs:r:cat_id';
        VAL = V$CAT_ID;
        SUSPEND;
        TAG_NAME = 'new_jobs:r:name';
        VAL = V$COMMENTS;
        SUSPEND;
        TAG_NAME = 'new_jobs:r:rate';
        VAL = CAST(V$RATE AS NUMERIC(18, 2));
        SUSPEND;
        TAG_NAME = 'new_jobs:r:terms';
        VAL = S;
        SUSPEND;
      END
    END
  END

  -- Приказы по сотрудникам - в любом случае
  IF(V$TYPE_ID IN (14256, 14257, 14258, 14259, 14272)) THEN
  BEGIN
    TAG_NAME = 'leave_cause::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT LISTVAL_ID, VAL
      FROM LISTVALS_LIST(130)
      WHERE IS_DEL = 0
      ORDER BY SORT_ORDER
      INTO :V$OBJ_ID, :V$DETAILS_TEXT
    DO
    BEGIN
      TAG_NAME = 'leave_cause:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'leave_cause:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'leave_cause:r:value';
      VAL = V$DETAILS_TEXT;
      SUSPEND;
    END
    TAG_NAME = 'leave_reason::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT LISTVAL_ID, VAL
      FROM LISTVALS_LIST(128)
      WHERE IS_DEL = 0
      ORDER BY SORT_ORDER
      INTO :V$OBJ_ID, :V$DETAILS_TEXT
    DO
    BEGIN
      TAG_NAME = 'leave_reason:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'leave_reason:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'leave_reason:r:value';
      VAL = V$DETAILS_TEXT;
      SUSPEND;
    END
  END

  -- Показываем текущие классы, они же используются для выборки данных для приказов помимо приема
  TAG_NAME = 'grades::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    -- Обычные классы
    SELECT L9.OBJ_ID, C.CAPTION, V49.LISTVAL_ID, L9.OBJ_TYPE_ID, V2388.LISTVAL_ID, COALESCE(V3344.LISTVAL_ID, 3), LV.COST, V43.LISTVAL_ID, V53.VAL
    FROM LINKS L2
    JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    JOIN VALL V43 ON V43.OBJ_ID = L7.OBJ_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V49.LISTVAL_ID
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 187) AND L9.DATE_DEL IS NULL
    LEFT JOIN VALL V2388 ON V2388.OBJ_ID = L9.OBJ_ID AND V2388.PARAM_ID IN (2388, 2418) AND V2388.IS_DEL = 0
    LEFT JOIN VALL V3344 ON V3344.OBJ_ID = L9.OBJ_ID AND V3344.PARAM_ID = 3344 AND V3344.IS_DEL = 0
    LEFT JOIN VALR V53 ON V53.OBJ_ID = L9.OBJ_ID AND V53.PARAM_ID = 53 AND V53.IS_DEL = 0
    LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C ON 1 = 1
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    -- Классы для приема ГИА - только в приказах по аттестации, 7 - старыый маршрут, 502 - новый маршрут
    UNION
    SELECT L125.OBJ_ID, C.CAPTION, V49.LISTVAL_ID, L125.OBJ_TYPE_ID, V2419.LISTVAL_ID, NULL, LV.COST, V43.LISTVAL_ID, NULL
    FROM LINKS L2
    JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID IN (7, 502) AND L7.DATE_DEL IS NULL
    LEFT JOIN VALL V43 ON V43.OBJ_ID = L7.OBJ_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V49.LISTVAL_ID
    JOIN LINKS L125 ON L125.PARENT_ID = L8.OBJ_ID AND L125.OBJ_TYPE_ID = 125 AND L125.DATE_DEL IS NULL
    LEFT JOIN VALL V2419 ON V2419.OBJ_ID = L125.OBJ_ID AND V2419.PARAM_ID = 2419 AND V2419.IS_DEL = 0
    LEFT JOIN OBJECT_CAPTION_GET(L125.OBJ_ID) C ON 1 = 1
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND :I$TYPE_ID = 13326
    ORDER BY 6, 7, 2
    INTO :V$OBJ_ID, :V$DETAILS_TEXT, :V$PARENT_ID, :V$GROUP_ID, :V$REF_ID, :V$SPO_FIN, :V$COST, :V$LEVEL_ID, :V$CND
  DO
  BEGIN
    TAG_NAME = 'grades:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'grades:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'grades:r:type';
    VAL = V$GROUP_ID;
    SUSPEND;
    TAG_NAME = 'grades:r:stage';
    VAL = V$PARENT_ID;
    SUSPEND;
    TAG_NAME = 'grades:r:resp_id';
    VAL = V$CND;
    SUSPEND;
    TAG_NAME = 'grades:r:level';
    -- Для классов ГИА смотрим по этапу обучения
    IF(V$LEVEL_ID IS NULL) THEN V$LEVEL_ID = IIF(V$PARENT_ID = 47, 27, 26);
    VAL = V$LEVEL_ID;
    SUSPEND;
    TAG_NAME = 'grades:r:value';
    VAL = V$DETAILS_TEXT;
    SUSPEND;
    -- Признаки выпускного класса по ГИА и выпуска СПО
    TAG_NAME = 'grades:r:is_final';
    VAL = V$REF_ID;
    SUSPEND;
    TAG_NAME = 'grades:r:is_grad';
    VAL = V$SPO_FIN;
    SUSPEND;
  END

  -- Список для выбора классов назначения для приказов приема и перевода, о повторном обучении
  -- Тут только будущие классы
  TAG_NAME = 'chgrades::json&colon;array';
  VAL = 1;
  SUSPEND;
  IF(V$TYPE_ID IN (12929, 12931, 12937)) THEN
  BEGIN
    FOR
      SELECT G.GRADE_ID, G.TYPE_ID, G.STAGE_ID_NEW, 'будущий ' || G.GRADE_NAME_NEW
      FROM YCHANGE_REVIEW_GRADES(:V$OU_LICENCE_TYPE) G
      WHERE G.GRADE_NAME_NEW IS NOT NULL AND (G.GRADE_SUFFIX_NEW IS NULL OR G.GRADE_SUFFIX_NEW <> '*')
      ORDER BY G.STAGE_COST_NEW, G.GRADE_NAME_NEW
      INTO :V$OBJ_ID, :V$GROUP_ID, :V$PARENT_ID, :V$DETAILS_TEXT
    DO
    BEGIN
      TAG_NAME = 'chgrades:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'chgrades:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'chgrades:r:type';
      VAL = V$GROUP_ID;
      SUSPEND;
      TAG_NAME = 'chgrades:r:stage';
      VAL = V$PARENT_ID;
      SUSPEND;
      TAG_NAME = 'chgrades:r:value';
      VAL = V$DETAILS_TEXT;
      SUSPEND;
      IF(V$TYPE_ID = 12929 AND V$STATE_ID = 11716) THEN
      BEGIN
        -- Для СПО - код специальности
        TAG_NAME = 'chgrades:r:spcode';
        VAL = NULL;
        IF(V$OU_LICENCE_TYPE IN ('C', 'S')) THEN
        SELECT FIRST 1 V.VAL
        FROM VALS V
        WHERE V.OBJ_ID = :V$OBJ_ID AND V.PARAM_ID IN (2822, 3384) AND V.IS_DEL = 0
        INTO :VAL;
        SUSPEND;
      END
    END
  END

  IF(V$TYPE_ID = 14260) THEN
  BEGIN
    TAG_NAME = 'subjects::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT L51.OBJ_ID, C.CAPTION
      FROM LINKS L51
      LEFT JOIN OBJECT_CAPTION_GET(L51.OBJ_ID) C ON 1 = 1
      WHERE ((L51.PARENT_ID = 32771 AND :V$HAS_OO = 1) OR (L51.PARENT_ID = 12313 AND :V$HAS_SPO = 1))
        AND L51.OBJ_TYPE_ID IN (51, 197) AND L51.DATE_DEL IS NULL -- DATE_DEL убрать ???
      ORDER BY 2
      INTO :V$OBJ_ID, :V$DETAILS_TEXT
    DO
    BEGIN
      TAG_NAME = 'subjects:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'subjects:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'subjects:r:name';
      VAL = V$DETAILS_TEXT;
      SUSPEND;
    END

    IF(I$TYPE_ID < 0) THEN
    BEGIN
      TAG_NAME = 'prefix_text';
      IF(V$ORDER_REF_ID IS NULL) THEN VAL = 'в соответствии с таблицей:';
      ELSE
      BEGIN
        S = '???';
        SELECT C.VAL
        FROM VALL V3567
        LEFT JOIN LISTVAL_TEXT(V3567.LISTVAL_ID) C ON 1 = 1
        WHERE V3567.OBJ_ID = :V$ORDER_REF_ID AND V3567.PARAM_ID = 3567 AND V3567.IS_DEL = 0
        INTO :S;
        VAL = 'на ' || S || ' учебный год в соответствии с Приложением 1.';
      END
      SUSPEND;

      TAG_NAME = 'suffix_text';
      IF(V$ORDER_REF_ID IS NULL) THEN VAL = '';
      ELSE VAL = 'Приложения: Приложение 1. Распределение педагогической нагрузки';
      SUSPEND;
    END
  END

  -- Поля для формы печати, для СПО берем наименование по уставу
  TAG_NAME = 'org_name_full';
  VAL = NULL;
  SELECT V5.VAL
  FROM LINKS L2
  JOIN VALS V5 ON V5.OBJ_ID = L2.OBJ_ID AND V5.PARAM_ID = 5 AND V5.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :VAL;
  SUSPEND;
  TAG_NAME = 'org_name_short';
  VAL = NULL;
  SELECT V2.VAL
  FROM LINKS L2
  JOIN VALS V2 ON V2.OBJ_ID = L2.OBJ_ID AND V2.PARAM_ID = IIF(:V$OU_LICENCE_TYPE = 'C', 999, 2) AND V2.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :VAL;
  SUSPEND;
  TAG_NAME = 'signed_by_name_short';
  SELECT V59.VAL || ' ' || SUBSTRING(V60.VAL FROM 1 FOR 1) || '.' || COALESCE(SUBSTRING(V61.VAL FROM 1 FOR 1) || '.', '')
  FROM VALS V59
  JOIN VALS V60 ON V60.OBJ_ID = V59.OBJ_ID AND V60.PARAM_ID = 60 AND V60.IS_DEL = 0
  LEFT JOIN VALS V61 ON V61.OBJ_ID = V59.OBJ_ID AND V61.PARAM_ID = 61 AND V61.IS_DEL = 0
  WHERE V59.OBJ_ID = :V$SIGNED_BY AND V59.PARAM_ID = 59 AND V59.IS_DEL = 0
  INTO :VAL;
  SUSPEND;
  TAG_NAME = 'signed_by_post';
  SELECT FIRST 1 V589.VAL
  FROM LINKS L15
  JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
  JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0 AND V73.VAL <= COALESCE(:V$ORDER_DATE, CURRENT_DATE)
  LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
  JOIN VALS V589 ON V589.OBJ_ID = LP13.PARENT_ID AND V589.PARAM_ID = 589 AND V589.IS_DEL = 0
  JOIN VALL V63 ON V63.OBJ_ID = LP13.PARENT_ID AND V63.PARAM_ID = 63 AND V63.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V63.LISTVAL_ID
  WHERE L15.PARENT_ID = :V$SIGNED_BY AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
    AND (V74.VAL IS NULL OR V74.VAL >= :V$ORDER_DATE)
  ORDER BY LV.SORT_ORDER
  INTO :VAL;
  SUSPEND;

  -- При выборке для печати (I$TYPE_ID = -1) для приказов по аттестации по дубликатам подменяем subtype_id на 0
  -- там должен быть ровно один ученик
  IF(I$TYPE_ID = -1 AND V$TYPE_ID = 13326 AND NROWS = 1) THEN
  BEGIN
    SELECT MON$DATABASE_NAME
    FROM MON$DATABASE
    INTO :V;

    V = REPLACE(V, 'BASE.FDB', 'DOC.FDB');

    EXECUTE STATEMENT
      'SELECT FIRST 1 D.PREV_FIO, D.PREV_BD, D.NEW_FIO, D.NEW_BD, D.GRAD_YEAR, D.PREV_DATE, D.PREV_NUM, D.BLANK_NUM
      FROM SDOCS_DUB_DATA(' || I$OBJ_ID || ', ' || V$PERSON_ID || ') D'
    ON EXTERNAL :V
    WITH COMMON TRANSACTION
    INTO :V$OLD_NAME, :V$PREV_BD, :V$NEW_NAME, :V$NEW_BD, :N, :V$PREV_DATE, :S, :V$COMMENTS;

    IF(N IS NOT NULL) THEN
    BEGIN
      -- Название типа документа
      TAG_NAME = 'subtype_name';
      VAL = (SELECT VAL FROM LISTVAL_TEXT(:V$SUBTYPE_ID));
      SUSPEND;
      TAG_NAME = 'subtype_name_r';
      VAL = REPLACE(VAL, 'тестат ', 'тестата ');
      VAL = REPLACE(VAL, 'иплом ', 'иплома ');
      VAL = REPLACE(VAL, 'тельство ', 'тельства ');
      SUSPEND;
      V$SUBTYPE_ID = 0;

      TAG_NAME = 'prev_fio';
      VAL = V$OLD_NAME;
      SUSPEND;
      TAG_NAME = 'prev_bd';
      VAL = (SELECT RESULT FROM DATE2STR(:V$PREV_BD));
      SUSPEND;
      TAG_NAME = 'new_fio';
      VAL = V$NEW_NAME;
      SUSPEND;
      TAG_NAME = 'new_bd';
      VAL = (SELECT RESULT FROM DATE2STR(:V$NEW_BD));
      SUSPEND;
      TAG_NAME = 'grad_year';
      VAL = N;
      SUSPEND;
      TAG_NAME = 'prev_date';
      VAL = (SELECT RESULT FROM DATE2STR(:V$PREV_DATE));
      SUSPEND;
      -- Новая дата выдачи = дата action_date
      TAG_NAME = 'prev_num';
      VAL = S;
      SUSPEND;
      TAG_NAME = 'new_num';
      VAL = V$COMMENTS;
      SUSPEND;
    END
  END

  TAG_NAME = 'subtype_id:values:value';
  VAL = V$SUBTYPE_ID;
  SUSPEND;
  TAG_NAME = 'subtype_id:selection::json&colon;array';
  VAL = 1;
  SUSPEND;
  IF(V$TYPE_ID = 13326) THEN V$LIST_ID = 256; -- для приказов по аттестации
  FOR
    SELECT LISTVAL_ID, VAL
    FROM LISTVALS_LIST(:V$LIST_ID)
    WHERE IS_DEL = 0
      AND (
        (:V$HAS_OO = 1 AND LISTVAL_ID IN (5377, 5378, 5379, 5380, 5385)) OR
        (:V$HAS_SPO = 1 AND LISTVAL_ID IN (5377, 5378, 5379, 5380, 5385, 12766, 12767))
      )
    INTO :V$OBJ_ID, :V$DETAILS_TEXT
  DO
  BEGIN
    TAG_NAME = 'subtype_id:selection:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'subtype_id:selection:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'subtype_id:selection:r:value';
    VAL = V$DETAILS_TEXT;
    SUSPEND;
  END

  -- Специальный кекс для печати приказа СОО с отличием - два уровня
  -- первый уровень - цвет аттестата (причем смотрим не сам цвет, а статус медали), второй сами ученики
  IF(I$TYPE_ID = -1 AND V$SUBTYPE_ID = 5380) THEN
  BEGIN
    TAG_NAME = 'a5380::json&colon;array';
    VAL = 1;
    SUSPEND;
    N = 1;
    -- Первый уровень - цвет аттестата, сначала I степень, потом II степень
    -- старые аттестаты где медали не вносили - считаем I степень
    FOR
      SELECT DISTINCT COALESCE(V3479.LISTVAL_ID, 15828)
      FROM ORDER_DATA D
      LEFT JOIN VALL V3479 ON V3479.OBJ_ID = D.REF_ID AND V3479.PARAM_ID = 3479 AND V3479.IS_DEL = 0
      WHERE D.DATE_DEL IS NULL AND D.ORDER_ID = :I$OBJ_ID
      ORDER BY 1
      INTO :V$OBJ_ID
    DO
    BEGIN
      TAG_NAME = 'a5380:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'a5380:r:n';
      VAL = N;
      N = N + 1;
      SUSPEND;
      TAG_NAME = 'a5380:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'a5380:r:name';
      IF(V$OBJ_ID = 15829) THEN VAL = 'II степени'; ELSE VAL = 'I степени';
      SUSPEND;
      TAG_NAME = 'a5380:r:color';
      IF(V$OBJ_ID = 15829) THEN VAL = 'синего'; ELSE VAL = 'красного';
      SUSPEND;
      TAG_NAME = 'a5380:r:persons::json&colon;array';
      VAL = 1;
      SUSPEND;
      FOR
        SELECT D.REF_ID, C.NAME_FULL, D.GRADE_NAME
        FROM ORDER_DATA D
        LEFT JOIN VALL V3479 ON V3479.OBJ_ID = D.REF_ID AND V3479.PARAM_ID = 3479 AND V3479.IS_DEL = 0
        LEFT JOIN UT_PERSON_DESC(D.REF_ID) C ON 1 = 1
        WHERE D.DATE_DEL IS NULL AND D.ORDER_ID = :I$OBJ_ID AND COALESCE(V3479.LISTVAL_ID, 15828) = :V$OBJ_ID
        ORDER BY 3, 2
        INTO :V$REF_ID, :V$DETAILS_TEXT, :S
      DO
      BEGIN
        TAG_NAME = 'a5380:r:persons:r';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'a5380:r:persons:r:ref_id';
        VAL = V$REF_ID;
        SUSPEND;
        TAG_NAME = 'a5380:r:persons:r:name_full';
        VAL = V$DETAILS_TEXT;
        SUSPEND;
        TAG_NAME = 'a5380:r:persons:r:class_name';
        IF(POSITION('|' IN S) > 0) THEN VAL = SUBSTRING(S FROM 1 FOR POSITION('|' IN S) - 1); ELSE VAL = S;
        SUSPEND;
      END
    END
    TAG_NAME = 'a5380_nlast';
    VAL = N;
    SUSPEND;
  END

  -- Список учительских должностей для выборе в трудовую
  TAG_NAME = 'teacher_jobs::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L.VAL
    FROM LISTVALS_LIST(370) L
    WHERE L.IS_DEL = 0
    INTO :S
  DO
  BEGIN
    TAG_NAME = 'teacher_jobs:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'teacher_jobs:r:value';
    VAL = S;
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE ORDER_GROUP_SORTS (
    I$PERSON_ID BIGINT)
RETURNS (
    STAGE_INDEX BIGINT,
    CLASS_NAME VARCHAR(100),
    PERSON_NAME VARCHAR(400))
AS
begin

  SELECT V55.VAL || ' ' || V56.VAL || COALESCE(' ' || V57.VAL, '')
  FROM VALS V55
  JOIN VALS V56 ON V56.OBJ_ID = V55.OBJ_ID AND V56.PARAM_ID IN (56, 828) AND V56.IS_DEL = 0
  LEFT JOIN VALS V57 ON V57.OBJ_ID = V55.OBJ_ID AND V57.PARAM_ID IN (57, 829) AND V57.IS_DEL = 0
  WHERE V55.OBJ_ID = :I$PERSON_ID AND V55.PARAM_ID IN (55, 827) AND V55.IS_DEL = 0
  INTO :PERSON_NAME;

  SELECT FIRST 1 LV.COST, C.CAPTION
  FROM LINKS LPG
  JOIN LINKS LP8 ON LP8.OBJ_ID = LPG.PARENT_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
  JOIN VALL V49 ON V49.OBJ_ID = LP8.PARENT_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V49.LISTVAL_ID
  LEFT JOIN OBJECT_CAPTION_GET(LPG.PARENT_ID) C ON 1 = 1
  WHERE LPG.OBJ_ID = :I$PERSON_ID AND LPG.PARENT_TYPE_ID IN (9, 125, 187) AND LPG.DATE_DEL IS NULL
  INTO :STAGE_INDEX, :CLASS_NAME;

  -- Выбывший - печать дубликата ? Все дубликаты в самое начало списка
  IF(STAGE_INDEX IS NULL) THEN
  BEGIN
    STAGE_INDEX = -1;
    CLASS_NAME = '';
  END

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE ORDER_MK_NUM (
    I$TYPE_ID BIGINT,
    I$VALIDATE_ONLY SMALLINT,
    I$NUMBER VARCHAR(100))
RETURNS (
    ORDER_NUM VARCHAR(100))
AS
DECLARE VARIABLE V$RULE_ID BIGINT;
DECLARE VARIABLE V$MASTER_ID BIGINT;
DECLARE VARIABLE V$RULE VARCHAR(100);
DECLARE VARIABLE V$N INTEGER;
DECLARE VARIABLE V$Y INTEGER;
DECLARE VARIABLE V$RESET BIGINT;
DECLARE VARIABLE TMP INTEGER;
begin

  ORDER_NUM = I$NUMBER;

  SELECT L406.OBJ_ID, V3031.VAL, V3032.VAL, V3107.VAL, V3030.LISTVAL_ID -- FIRST 1
  FROM LINKS L2
  JOIN LINKS L406 ON L406.PARENT_ID = L2.OBJ_ID AND L406.OBJ_TYPE_ID = 406 AND L406.DATE_DEL IS NULL
  JOIN VALL V3029 ON V3029.OBJ_ID = L406.OBJ_ID AND V3029.PARAM_ID = 3029 AND V3029.IS_DEL = 0 AND V3029.LISTVAL_ID = :I$TYPE_ID
  JOIN VALS V3031 ON V3031.OBJ_ID = L406.OBJ_ID AND V3031.PARAM_ID = 3031 AND V3031.IS_DEL = 0
  JOIN VALL V3030 ON V3030.OBJ_ID = L406.OBJ_ID AND V3030.PARAM_ID = 3030 AND V3030.IS_DEL = 0
  LEFT JOIN VALI V3032 ON V3032.OBJ_ID = L406.OBJ_ID AND V3032.PARAM_ID = 3032 AND V3032.IS_DEL = 0
  LEFT JOIN VALI V3107 ON V3107.OBJ_ID = L406.OBJ_ID AND V3107.PARAM_ID = 3107 AND V3107.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$RULE_ID, :V$RULE, :V$N, :V$Y, :V$RESET;

  -- Если нет правила для именно этого типа приказа, смотрим глобальное для этой группы приказов
  IF(V$RULE_ID IS NULL) THEN
  BEGIN
    SELECT FIRST 1 LV2.LISTVAL_ID
    FROM LISTVALS LV
    JOIN LISTVALS LV2 ON LV2.IS_DEL = 0 AND LV2.LIST_ID = LV.LIST_ID AND LV2.PARENT_ID = LV.PARENT_ID AND LV2.COST < 0
    WHERE LV.IS_DEL = 0 AND LV.LIST_ID = 322 AND LV.LISTVAL_ID = :I$TYPE_ID
    INTO :V$MASTER_ID;

    SELECT L406.OBJ_ID, V3031.VAL, V3032.VAL, V3107.VAL, V3030.LISTVAL_ID -- FIRST 1
    FROM LINKS L2
    JOIN LINKS L406 ON L406.PARENT_ID = L2.OBJ_ID AND L406.OBJ_TYPE_ID = 406 AND L406.DATE_DEL IS NULL
    JOIN VALL V3029 ON V3029.OBJ_ID = L406.OBJ_ID AND V3029.PARAM_ID = 3029 AND V3029.IS_DEL = 0 AND V3029.LISTVAL_ID = :V$MASTER_ID
    JOIN VALS V3031 ON V3031.OBJ_ID = L406.OBJ_ID AND V3031.PARAM_ID = 3031 AND V3031.IS_DEL = 0
    JOIN VALL V3030 ON V3030.OBJ_ID = L406.OBJ_ID AND V3030.PARAM_ID = 3030 AND V3030.IS_DEL = 0
    LEFT JOIN VALI V3032 ON V3032.OBJ_ID = L406.OBJ_ID AND V3032.PARAM_ID = 3032 AND V3032.IS_DEL = 0
    LEFT JOIN VALI V3107 ON V3107.OBJ_ID = L406.OBJ_ID AND V3107.PARAM_ID = 3107 AND V3107.IS_DEL = 0
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :V$RULE_ID, :V$RULE, :V$N, :V$Y, :V$RESET;
  END

  IF(V$RULE_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не найдено правило нумерации приказов для данного вида приказов, и нет глобального правила. Настройте правила нумерации в приложении - Структура ОООД (Документы ОООД)';
  IF(V$RULE = '*') THEN EXCEPTION DATA_ERROR 'Для данного вида приказов предусмотрена ручная нумерация, значение АВТО недопустимо';

  -- Если правило нумерации приказов содержит %g, то заменяем правило на глобальный нумератор
  IF(POSITION('%g' IN V$RULE) > 0) THEN
  BEGIN
    V$RULE_ID = NULL;
    SELECT L406.OBJ_ID, V3032.VAL, V3107.VAL, V3030.LISTVAL_ID -- FIRST 1
    FROM LINKS L2
    JOIN LINKS L406 ON L406.PARENT_ID = L2.OBJ_ID AND L406.OBJ_TYPE_ID = 406 AND L406.DATE_DEL IS NULL
    JOIN VALL V3029 ON V3029.OBJ_ID = L406.OBJ_ID AND V3029.PARAM_ID = 3029 AND V3029.IS_DEL = 0 AND V3029.LISTVAL_ID = 13266
    JOIN VALL V3030 ON V3030.OBJ_ID = L406.OBJ_ID AND V3030.PARAM_ID = 3030 AND V3030.IS_DEL = 0
    LEFT JOIN VALI V3032 ON V3032.OBJ_ID = L406.OBJ_ID AND V3032.PARAM_ID = 3032 AND V3032.IS_DEL = 0
    LEFT JOIN VALI V3107 ON V3107.OBJ_ID = L406.OBJ_ID AND V3107.PARAM_ID = 3107 AND V3107.IS_DEL = 0
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :V$RULE_ID, :V$N, :V$Y, :V$RESET;

    IF(V$RULE_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не найдено глобальное правило нумерации приказов';
  END

  IF(I$VALIDATE_ONLY = 0) THEN
  BEGIN
    IF(V$Y IS NULL) THEN
    BEGIN
      V$Y = EXTRACT(YEAR FROM CURRENT_DATE);
      SELECT 1 FROM VAL_ADD(3107, :V$RULE_ID, :V$Y) INTO :TMP;
    END

    IF(V$N IS NULL) THEN V$N = 1; ELSE V$N = V$N + 1;
    IF(V$RESET = 2 AND V$Y <> EXTRACT(YEAR FROM CURRENT_DATE)) THEN
    BEGIN
      V$Y = EXTRACT(YEAR FROM CURRENT_DATE);
      SELECT 1 FROM VAL_ADD(3107, :V$RULE_ID, :V$Y) INTO :TMP;
      V$N = 1;
    END

    SELECT 1 FROM VAL_ADD(3032, :V$RULE_ID, :V$N) INTO :TMP;

    -- Номер приказа
    V$RULE = REPLACE(V$RULE, '%s', V$N);
    V$RULE = REPLACE(V$RULE, '%n', V$N);
    -- Номер календарного года
    V$RULE = REPLACE(V$RULE, '%y', EXTRACT(YEAR FROM CURRENT_DATE));
    -- Номер учебного года
    V$RULE = REPLACE(V$RULE, '%sy', IIF(EXTRACT(MONTH FROM CURRENT_DATE) < 9, EXTRACT(YEAR FROM CURRENT_DATE) - 1, EXTRACT(YEAR FROM CURRENT_DATE)));

    ORDER_NUM = V$RULE;
  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE ORDER_SET (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40),
    I$PARENT_ID BIGINT,
    I$TYPE_ID BIGINT,
    I$STATE_ID BIGINT,
    I$ORDER_DATE DATE,
    I$ORDER_NUM VARCHAR(100),
    I$ACTION_DATE DATE,
    I$SIGNED_BY BIGINT,
    I$DETAILS_TEXT VARCHAR(1000),
    I$COMMENTS VARCHAR(1000),
    I$SUBTYPE_ID BIGINT = NULL,
    I$OWNER_ID BIGINT = NULL,
    I$VACANCY_ID BIGINT = NULL,
    I$EMPLOYEE_ID BIGINT = NULL)
RETURNS (
    OBJ_ID BIGINT,
    STATE_ID BIGINT)
AS
DECLARE VARIABLE V$RULE_ID BIGINT;
DECLARE VARIABLE V$RULE VARCHAR(100);
DECLARE VARIABLE V$N BIGINT;
DECLARE VARIABLE V$Y BIGINT;
DECLARE VARIABLE V$RESET BIGINT;
DECLARE VARIABLE V$MASTER_ID BIGINT;
DECLARE VARIABLE V$OWNER_ID BIGINT;
DECLARE VARIABLE TMP BIGINT;
begin

  IF(SUBSTRING(I$USER_ID FROM 1 FOR 1) = '@') THEN I$USER_ID = NULL;
  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  -- Перевод года - подготовка к проведению приказа, старые поля все переносим один в один
  IF(I$USER_ID IS NULL) THEN
  BEGIN
    SELECT D.SIGNED_BY, D.TYPE_ID, D.DETAILS_TEXT, D.COMMENTS, D.OWNER_ID
    FROM ORDERS D
    WHERE D.DATE_DEL IS NULL AND D.OBJ_ID = :I$OBJ_ID
    INTO :I$SIGNED_BY, :I$TYPE_ID, :I$DETAILS_TEXT, :I$COMMENTS, :V$OWNER_ID;
  END

  IF(I$TYPE_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не указан тип приказа';
  IF(I$STATE_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не указан статус приказа';
  IF(I$STATE_ID = 11715 AND (I$ORDER_DATE IS NULL OR I$ORDER_NUM IS NULL OR I$ACTION_DATE IS NULL)) THEN EXCEPTION DATA_ERROR 'Даты или номер приказа не заполнены';

  -- Нумерация утвержденных приказов
  -- Код VALIDATE передаем чтобы только проверить нумерацию
  IF(I$STATE_ID = 11715 AND (UPPER(I$ORDER_NUM) = 'АВТО' OR I$ORDER_NUM = 'VALIDATE')) THEN
  BEGIN
    SELECT ORDER_NUM
    FROM ORDER_MK_NUM(:I$TYPE_ID, IIF(:I$ORDER_NUM = 'VALIDATE', 1, 0), :I$ORDER_NUM)
    INTO :I$ORDER_NUM;
  END
  -- Очищаем неудавшуюся автонумерацию
  ELSE IF(UPPER(I$ORDER_NUM) = 'АВТО') THEN I$ORDER_NUM = NULL;

  IF(V$OWNER_ID IS NOT NULL) THEN I$OWNER_ID = V$OWNER_ID;
  IF(I$OWNER_ID IS NULL) THEN
  BEGIN
    SELECT FIRST 1 L2.OBJ_ID
    FROM LINKS L2
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :I$OWNER_ID;
  END

  IF(I$SIGNED_BY IS NULL) THEN
  BEGIN
    -- Подписант - всегда руководитель организации, а не подразделения
    SELECT FIRST 1 L14.OBJ_ID
    FROM LINKS L14
    JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
    JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
    LEFT JOIN VALL V64 ON V64.OBJ_ID = LP13.PARENT_ID AND V64.PARAM_ID = 64 AND V64.IS_DEL = 0
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
    LEFT JOIN VALL V3343 ON V3343.OBJ_ID = L14.OBJ_ID AND V3343.PARAM_ID = 3343 AND V3343.IS_DEL = 0
    WHERE L14.PARENT_ID = :I$OWNER_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
      AND V74.OBJ_ID IS NULL AND (V64.LISTVAL_ID = 56 OR V3343.LISTVAL_ID = 2)
    INTO :I$SIGNED_BY;

    -- если нет, запасным вариантом смотрим руководителя подразделения
    IF(I$SIGNED_BY IS NULL) THEN
    SELECT FIRST 1 V1794.VAL
    FROM VALR V1794
    WHERE V1794.OBJ_ID = :V$OWNER_ID AND V1794.PARAM_ID = 1794 AND V1794.IS_DEL = 0
    INTO :I$SIGNED_BY;

    -- если подписанта нет, проверяем вообще наличие сотрудников в ОУ
    -- если сотрудников нет, то проверяем что первым должен принят быть тот самый руководитель - его и ставим
    -- изменение: если сотрудников нет вовсе, то первый принятый становится ИО
    IF(I$SIGNED_BY IS NULL) THEN
    BEGIN
      -- -1 в качестве OWNER_ID ставим чтобы система не ругалась ???
      -- Первый сотрудник директор или ИО, он же становится и подписантом
      I$SIGNED_BY = I$EMPLOYEE_ID;
    END
    IF(I$SIGNED_BY IS NULL) THEN EXCEPTION DATA_ERROR 'Нет руководителя организации (подразделения) для внесения в качестве подписанта приказа';
  END

  IF(I$OBJ_ID IS NULL) THEN
  BEGIN

    -- Добавляем всегда в статусе проекта, статус изменим после сохранения строк приказа
    I$STATE_ID = 11716;
    STATE_ID = I$STATE_ID;

    INSERT INTO ORDERS
    (TYPE_ID, STATE_ID, OWNER_ID, PARENT_ID, ORDER_DATE, ORDER_NUM, ACTION_DATE, SIGNED_BY, DETAILS_TEXT, COMMENTS, SUBTYPE_ID)
    VALUES (:I$TYPE_ID, :I$STATE_ID, :I$OWNER_ID, :I$PARENT_ID, :I$ORDER_DATE, :I$ORDER_NUM, :I$ACTION_DATE, :I$SIGNED_BY, :I$DETAILS_TEXT, :I$COMMENTS, :I$SUBTYPE_ID)
    RETURNING OBJ_ID INTO :OBJ_ID;

  END
  ELSE
  BEGIN

    SELECT D.OBJ_ID, D.STATE_ID
    FROM ORDERS D
    WHERE D.DATE_DEL IS NULL AND D.OBJ_ID = :I$OBJ_ID
    INTO :OBJ_ID, :STATE_ID;

    IF(OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Запись не найдена';

    -- Изменения вносим только когда текущее состояние приказа = проект
    -- Сам статус обновится в ORDER_SET_STATE
    -- OWNER_ID не может меняться, кроме случая когда не был заполнен вовсе
    IF(STATE_ID = 11716) THEN
    BEGIN
      UPDATE ORDERS
      SET ORDER_DATE = :I$ORDER_DATE, ORDER_NUM = :I$ORDER_NUM, ACTION_DATE = :I$ACTION_DATE, SIGNED_BY = :I$SIGNED_BY, DETAILS_TEXT = :I$DETAILS_TEXT,
        COMMENTS = :I$COMMENTS, OWNER_ID = COALESCE(OWNER_ID, :I$OWNER_ID)
      WHERE OBJ_ID = :OBJ_ID;
    END

  END

  SUSPEND;
                                                       
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE ORDER_SET_ROW (
    I$ORDER_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40),
    I$DELETED SMALLINT,
    I$REF_ID BIGINT,
    I$DESTINATION VARCHAR(400),
    I$IS_PRESENT SMALLINT,
    I$DEST_ID BIGINT = NULL,
    I$ORDER_DATE DATE = NULL,
    I$DST_DATA VARCHAR(1000) = NULL,
    I$JOB_ID BIGINT = NULL,
    I$JOB_ID2 BIGINT = NULL)
RETURNS (
    OBJ_ID BIGINT,
    ORDER_ID BIGINT)
AS
DECLARE VARIABLE V$STATE_ID BIGINT;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$DATE_ADD TIMESTAMP;
DECLARE VARIABLE V$DEST_ID BIGINT;
DECLARE VARIABLE V$TMP BIGINT;
DECLARE VARIABLE V$TYPE_ID BIGINT;
DECLARE VARIABLE V$TYPE_GROUP INTEGER;
DECLARE VARIABLE V$DEST_TYPE_ID BIGINT;
DECLARE VARIABLE V$DEST_CAPTION VARCHAR(1000);
DECLARE VARIABLE V$OU_LICENCE_TYPE CHAR(1);
DECLARE VARIABLE V$SIGNED_BY BIGINT;
DECLARE VARIABLE P INTEGER;
DECLARE VARIABLE V$OLD_PRESENT SMALLINT;
DECLARE VARIABLE V$DST VARCHAR(1000);
DECLARE VARIABLE S VARCHAR(400);
DECLARE VARIABLE V VARCHAR(400);
DECLARE VARIABLE V$OLD_GN VARCHAR(400);
DECLARE VARIABLE V$GRADE_NAME VARCHAR(400);
DECLARE VARIABLE V$JOB_ID BIGINT;
DECLARE VARIABLE V$JOB_ID2 BIGINT;
DECLARE VARIABLE V$REF_ID BIGINT;
begin

  -- REF_ID - ID персоны
  -- DESTINATION - текстовое значение поля для выбора назначения (название класса)
  -- DEST_ID - специально для диалога зачисления, позволяет указать id класса или проекта класса, заменяет DESTINATION
  -- DELETED - входит или не входит в данный приказ

  -- ORDER_ID = 0 - создать новый проект приказа
  -- ORDER_ID = 1 - создать новый индивидуальный приказ и тут же его провести (прием сразу в класс)

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  IF(I$ORDER_ID IN (0, 1)) THEN
  BEGIN
    -- Для приема в ДО вообще не делаем приказов
    IF(EXISTS(
      SELECT 1 FROM LINKS LP46 WHERE LP46.OBJ_ID = :I$REF_ID AND LP46.PARENT_TYPE_ID = 46 AND LP46.DATE_DEL IS NULL
    ))
    THEN EXIT;

    -- Создаем новый приказ - либо в статусе проекта, либо сразу утвержденный
    V$DATE_ADD = CURRENT_TIMESTAMP;
    V$STATE_ID = IIF(I$ORDER_ID = 0, 11716, 11715);
    V$TYPE_ID = 12929;
    V$TYPE_GROUP = 0;

    -- Блокировка - в предварительном приеме только проект, в реальном классе только утвержденный
    IF(NOT EXISTS(
      SELECT 1 FROM LINKS LP290 WHERE LP290.OBJ_ID = :I$REF_ID AND LP290.PARENT_TYPE_ID = 290 AND LP290.DATE_DEL IS NULL AND :I$ORDER_ID = 0
      UNION
      SELECT 1 FROM LINKS LP9 WHERE LP9.OBJ_ID = :I$REF_ID AND LP9.PARENT_TYPE_ID IN (9, 187) AND LP9.DATE_DEL IS NULL AND :I$ORDER_ID = 1
    ))
    THEN EXCEPTION DATA_ERROR 'Недопустимый выбор типа приказа';

    -- Выбираем текущего руководителя - фактического или ИО
    SELECT FIRST 1 L14.OBJ_ID
    FROM LINKS L2
    JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
    JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
    JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0 AND V73.VAL <= CURRENT_DATE
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
    JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
    JOIN VALL V64 ON V64.OBJ_ID = LP13.PARENT_ID AND V64.PARAM_ID = 64 AND V64.IS_DEL = 0 AND V64.LISTVAL_ID = 56
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND (V74.VAL IS NULL OR V74.VAL >= CURRENT_DATE)
    INTO :V$SIGNED_BY;

    IF(V$SIGNED_BY IS NULL) THEN 
    SELECT FIRST 1 L14.OBJ_ID
    FROM LINKS L2
    JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
    JOIN VALL V3343 ON V3343.OBJ_ID = L14.OBJ_ID AND V3343.PARAM_ID = 3343 AND V3343.IS_DEL = 0 AND V3343.LISTVAL_ID = 2
    JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
    JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0 AND V73.VAL <= CURRENT_DATE
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
    JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND (V74.VAL IS NULL OR V74.VAL >= CURRENT_DATE)
    INTO :V$SIGNED_BY;

    IF(V$SIGNED_BY IS NULL) THEN EXCEPTION DATA_ERROR 'В организации отсутствует руководитель или ИО руководителя первого уровня';

    -- Проверить что дата попадает в учебный год !!!
    IF(I$ORDER_DATE IS NULL) THEN I$ORDER_DATE = CURRENT_DATE;

    -- Вместо I$DST_DATA передается номер приказа о зачислении, если пользователь хочет его поставить
    -- I$DST_DATA обязательно затем зануляем
    IF(I$DST_DATA IS NULL OR SUBSTRING(I$DST_DATA FROM 1 FOR 1) <> '@') THEN S = 'АВТО';
    ELSE
    BEGIN
      S = SUBSTRING(I$DST_DATA FROM 2);
      I$DST_DATA = NULL;
    END

    SELECT OBJ_ID
    FROM ORDER_SET(NULL, :I$USER_ID, NULL, :V$TYPE_ID, 11716, :I$ORDER_DATE, :S, :I$ORDER_DATE, :V$SIGNED_BY, NULL, NULL)
    INTO :I$ORDER_ID;

    -- Если требуется утверждение, принудительно обновляем статус - добавление идет всегда в статусе проекта
    IF(V$STATE_ID <> 11716) THEN
    BEGIN
      -- Нужно пересохранить, чтобы сформировался номер, но статус при этом не меняется
      SELECT OBJ_ID
      FROM ORDER_SET(:I$ORDER_ID, :I$USER_ID, NULL, :V$TYPE_ID, :V$STATE_ID, :I$ORDER_DATE, :S, :I$ORDER_DATE, :V$SIGNED_BY, NULL, NULL)
      INTO :I$ORDER_ID;

      UPDATE ORDERS SET STATE_ID = :V$STATE_ID WHERE OBJ_ID = :I$ORDER_ID;
    END
  END
  ELSE
  BEGIN
    SELECT D.STATE_ID, D.DATE_ADD, D.TYPE_ID, LV.COST
    FROM ORDERS D
    JOIN LISTVALS LV ON LV.LISTVAL_ID = D.TYPE_ID
    WHERE D.OBJ_ID = :I$ORDER_ID
    INTO :V$STATE_ID, :V$DATE_ADD, :V$TYPE_ID, :V$TYPE_GROUP;

    IF(V$STATE_ID <> 11716 AND I$OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Нельзя менять данные в приказе не в статусе проекта';
  END

  IF(V$STATE_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Приказ не найден';

  V$OU_LICENCE_TYPE = (SELECT STATUS FROM OU_LICENCE_TYPE);

  IF(I$OBJ_ID IS NOT NULL) THEN
  BEGIN
    SELECT D.OBJ_ID, D.IS_PRESENT, D.DST_DATA, D.GRADE_NAME, D.JOB_ID, D.JOB_ID2, D.REF_ID
    FROM ORDER_DATA D
    WHERE D.DATE_DEL IS NULL AND D.OBJ_ID = :I$OBJ_ID
    INTO :V$OBJ_ID, :V$OLD_PRESENT, :V$DST, :V$OLD_GN, :V$JOB_ID, :V$JOB_ID2, :V$REF_ID;

    IF(V$OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Одна из строк приказа не найдена или была удалена';
  END

  -- Обработка для приема обучающегося в предварительный прием с указанием будущего класса
  -- Заменяем id на название
  IF(I$DEST_ID IS NOT NULL) THEN
  BEGIN

    SELECT LX.OBJ_TYPE_ID, C.CAPTION
    FROM LINKS LX
    LEFT JOIN OBJECT_CAPTION_GET(LX.OBJ_ID) C ON 1 = 1
    WHERE LX.PARENT_TYPE_ID = 8 AND LX.OBJ_ID = ABS(:I$DEST_ID) AND LX.DATE_DEL IS NULL
    INTO :V$DEST_TYPE_ID, :V$DEST_CAPTION;

    -- Для типа 403 и так будет префикс будущий
    IF(I$DEST_ID < 0) THEN
    BEGIN
      P = POSITION(' ' IN V$DEST_CAPTION);
      IF(P > 0) THEN V$DEST_CAPTION = (CAST(SUBSTRING(V$DEST_CAPTION FROM 1 FOR P - 1) AS INTEGER) + 1) || ' ' || SUBSTRING(V$DEST_CAPTION FROM P + 1);
      ELSE V$DEST_CAPTION = CAST(V$DEST_CAPTION AS INTEGER) + 1;
      I$DESTINATION = 'будущий ' || V$DEST_CAPTION;
    END
    ELSE I$DESTINATION = V$DEST_CAPTION;

  END

  -- Ученик может быть за один раз только в одном приказе одной группы типов, группа берется из справочника типов
  -- В порядке исключения делаем исключение для печати аттестатов 2022 года
  S = NULL;
  SELECT FIRST 1 COALESCE('Приказ № ' || D.ORDER_NUM, 'Проект приказа № ' || D.PROJECT_NUM)
  FROM ORDER_DATA OD
  JOIN ORDERS D ON D.OBJ_ID = OD.ORDER_ID AND D.DATE_DEL IS NULL AND D.STATE_ID = 11716
  JOIN LISTVALS LV ON LV.LISTVAL_ID = D.TYPE_ID AND LV.COST = :V$TYPE_GROUP
  WHERE OD.DATE_DEL IS NULL AND OD.REF_ID = :I$REF_ID AND (:I$OBJ_ID IS NULL OR OD.OBJ_ID <> :I$OBJ_ID)
  INTO :S;

  IF(I$DELETED = 0 AND S IS NOT NULL AND (V$TYPE_ID <> 13326 OR CURRENT_DATE > '10.09.2023')) THEN
    EXCEPTION DATA_ERROR 'Один человек может быть включен только в один приказ данного типа. ' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$REF_ID)) || ' - ' || S;

  -- Обновляем статус назначения только в статусе проект (при утверждении приказа поле очистится)
  IF(V$STATE_ID = 11716) THEN
  BEGIN

      -- А есть ли класс с таким названием ?
      SELECT FIRST 1 L9.OBJ_ID
      FROM LINKS L9
      LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C ON 1 = 1
      WHERE L9.PARENT_TYPE_ID = 8 AND L9.OBJ_TYPE_ID IN (9, 187, 403) AND L9.DATE_DEL IS NULL AND UPPER(REPLACE(C.CAPTION, ' ', '')) = UPPER(REPLACE(:I$DESTINATION, ' ', ''))
      INTO :V$DEST_ID;

      -- Если у нас будущий класс, ищем среди классов со скорректированным названием
      IF(V$DEST_ID IS NULL) THEN
      BEGIN
        IF(SUBSTRING(I$DESTINATION FROM 1 FOR 8) = 'будущий ') THEN
        BEGIN
          V$DEST_CAPTION = SUBSTRING(I$DESTINATION FROM 9);

          SELECT FIRST 1 G.GRADE_ID
          FROM YCHANGE_REVIEW_GRADES(:V$OU_LICENCE_TYPE, NULL) G
          WHERE UPPER(REPLACE(G.GRADE_NAME_NEW, ' ', '')) = UPPER(REPLACE(:V$DEST_CAPTION, ' ', ''))
          INTO :V$DEST_ID;
        END
      END

      -- 12932 не требуется указывать учебный коллектив, он сохраняется существующий
      IF(I$DESTINATION IS NOT NULL AND V$DEST_ID IS NULL AND I$DELETED = 0
        AND V$TYPE_ID IN (12929, 12931, 12927)) THEN EXCEPTION DATA_ERROR 'Не задан учебный коллектив для ' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$REF_ID, 23)) || ', либо указанный ранее коллектив утрачен';

      SELECT BLOB_ID FROM VAL_ADD(3025, :I$REF_ID, :I$DESTINATION) INTO :V$TMP;

  END

  IF(I$IS_PRESENT IS NULL) THEN
  BEGIN
    IF(POSITION('будущий ' IN I$DESTINATION) > 0) THEN I$IS_PRESENT = 0; ELSE I$IS_PRESENT = 1;
  END

  -- Убираем ГУП, если приказ о зачислении и выбран будущий класс
  IF(V$TYPE_ID = 12929 AND I$DELETED = 0) THEN
  BEGIN
    IF(POSITION('будущий ' IN I$DESTINATION) > 0) THEN I$DST_DATA = NULL;
  END

  -- Для приказа о изменении ставок - принудительно ставим новую должность из старой
  IF(V$TYPE_ID = 14272 AND V$STATE_ID = 11716 AND I$DELETED = 0) THEN
  BEGIN
    SELECT FIRST 1 LP13.PARENT_ID
    FROM LINKS LP13
    WHERE LP13.OBJ_ID = :I$JOB_ID AND LP13.PARENT_TYPE_ID = 13
    ORDER BY LP13.DATE_DEL NULLS FIRST
    INTO :I$JOB_ID2;
  END

  -- Если идет изменение статуса - новое название выставится в SET_STATE
  -- кроме случая приема в класс - в этом случае то что сейчас сохраняем будет окончательным
  IF(I$DELETED = 0) THEN
  BEGIN
    -- Приказ о печати аттестатов - запоминаем наименование класса
    IF(V$TYPE_ID = 13326) THEN
    BEGIN
      SELECT C.CAPTION
      FROM LINKS LPG
      LEFT JOIN OBJECT_CAPTION_GET(LPG.PARENT_ID) C ON 1 = 1
      WHERE LPG.OBJ_ID = :I$REF_ID AND LPG.PARENT_TYPE_ID IN (9, 125, 187) AND LPG.DATE_DEL IS NULL
      INTO :V$GRADE_NAME;
    END
    -- Для приказов по персоналу в GRADE_NAME запоминаем название должности (по классным руководителям - название класса)
    -- и старой, и новой
    ELSE IF(V$TYPE_ID IN (14256, 14257, 14258, 14259, 14271, 14272)) THEN
    BEGIN
      IF(I$JOB_ID IS NULL) THEN
      BEGIN
        V$GRADE_NAME = 'Уволить со всех должностей';
      END
      ELSE
      BEGIN
        -- Если тут #13 и #9 (классруки) - будет нормальный текст, а если #15 будет фуфел
        SELECT C.CAPTION
        FROM OBJECTS OBJ
        LEFT JOIN OBJECT_CAPTION_GET(OBJ.OBJ_ID) C ON 1 = 1
        WHERE OBJ.OBJ_ID = :I$JOB_ID AND OBJ.TYPE_ID IN (9, 13)
        UNION
        SELECT FIRST 1 C.CAPTION
        FROM LINKS LP13
        LEFT JOIN OBJECT_CAPTION_GET(LP13.PARENT_ID) C ON 1 = 1
        WHERE LP13.OBJ_ID = :I$JOB_ID AND LP13.OBJ_TYPE_ID = 15 AND LP13.PARENT_TYPE_ID = 13
        INTO :V$GRADE_NAME;

        IF(I$JOB_ID2 IS NOT NULL) THEN
        SELECT :V$GRADE_NAME || '|' || C.CAPTION
        FROM OBJECT_CAPTION_GET(:I$JOB_ID2) C
        INTO :V$GRADE_NAME;
      END
    END
    -- Перевод в новый класс всех видов
    ELSE IF(V$TYPE_ID IN (12929, 12930, 12931, 12932, 12937)) THEN
    BEGIN
      -- Старый класс
      SELECT FIRST 1 C.CAPTION
      FROM LINKS LPG
      LEFT JOIN OBJECT_CAPTION_GET(LPG.PARENT_ID) C ON 1 = 1
      WHERE LPG.OBJ_ID = :I$REF_ID AND LPG.PARENT_TYPE_ID IN (9, 125, 187, 290) AND LPG.DATE_DEL IS NULL
      ORDER BY LPG.PARENT_TYPE_ID
      INTO :V$GRADE_NAME;
      -- Новый класс
      -- При простом переводе в тот же класс название может поменяться, особенно хитро при ОВЗ
      IF(V$TYPE_ID = 12932) THEN
      BEGIN
         -- !!! временно !!!
         V$GRADE_NAME = V$GRADE_NAME || '|' || V$GRADE_NAME;
      END
      ELSE
      BEGIN
        SELECT FIRST 1 :V$GRADE_NAME || '|' || V3025.SVAL -- REPLACE(V3025.SVAL, 'будущий ', '')
        FROM VALS V3025
        WHERE V3025.OBJ_ID = :I$REF_ID AND V3025.PARAM_ID = 3025 AND V3025.IS_DEL = 0
        INTO :V$GRADE_NAME;
      END
    END
    -- Окончание обучения - только старый класс
    ELSE IF(V$TYPE_ID IN (12933, 12934, 12935, 12936)) THEN
    BEGIN
      SELECT FIRST 1 C.CAPTION
      FROM LINKS LPG
      LEFT JOIN OBJECT_CAPTION_GET(LPG.PARENT_ID) C ON 1 = 1
      WHERE LPG.OBJ_ID = :I$REF_ID AND LPG.PARENT_TYPE_ID IN (9, 125, 187) AND LPG.DATE_DEL IS NULL
      ORDER BY LPG.PARENT_TYPE_ID
      INTO :V$GRADE_NAME;
    END
    ELSE
      V$GRADE_NAME = V$OLD_GN;
  END
  ELSE
    V$GRADE_NAME = V$OLD_GN;

  -- Запоминаем название учебного коллектива назначения (зачисление, перевод)
  -- важно: в индивидуальном приказе о зачислении данные о коллективе заполняются в PUPIL_ACCEPT_MOVEMENTS
  IF(I$DELETED = 0 AND V$STATE_ID = 11716 AND V$TYPE_ID IN (12929, 12931, 12932, 12937, 12964)) THEN
  BEGIN
    I$DST_DATA = I$DESTINATION;
  END

  -- Для приказов о приеме на должность копируем должность в выходную тоже
  IF(V$TYPE_ID = 14256) THEN I$JOB_ID2 = I$JOB_ID;

  IF(I$DELETED = 1) THEN
  BEGIN
    IF(V$TYPE_ID = 13326) THEN
    BEGIN
      SELECT MON$DATABASE_NAME
      FROM MON$DATABASE
      INTO :V;

      V = REPLACE(V, 'BASE.FDB', 'DOC.FDB');

      -- Испорченные бланки игнорируем и разрешаем удалить таких учеников
      -- 08.2024 синхронизация с проверкой при закрытии приказа: только если реестровый номер еще не присвоен
      EXECUTE STATEMENT
        'SELECT COUNT(*)
        FROM DOCUMENTS D
        LEFT JOIN BLANKS B ON B.OBJ_ID = D.BLANK_ID
        WHERE D.DATE_DEL IS NULL AND D.ORDER_ID = ' || I$ORDER_ID || ' AND D.STATE_ID IN (0, 1) AND (B.OBJ_ID IS NULL OR B.STATE_ID < 2 OR D.SEQ_NO IS NOT NULL) AND D.PERSON_ID = ' || I$REF_ID
      ON EXTERNAL :V
      -- ROLE 'INISSOFT_ROLE'
      WITH COMMON TRANSACTION
      INTO :P;

      IF(P > 0) THEN EXCEPTION DATA_ERROR 'Нельзя исключить ' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$REF_ID)) || ' из приказа, поскольку уже был создан документ об образовании или его проект. Сначала требуется аннулировать или удалить документ';
    END

    UPDATE ORDER_DATA
    SET DATE_DEL = CURRENT_TIMESTAMP
    WHERE OBJ_ID = :I$OBJ_ID;

    IF(V$TYPE_ID <> 13326) THEN
    BEGIN
      -- Определен для приема или выбытия - зачищаем если приказ по движению
      UPDATE VALS
      SET IS_DEL = 1
      WHERE IS_DEL = 0 AND OBJ_ID = :I$REF_ID AND PARAM_ID IN (3025);
    END
  END
  ELSE IF(I$OBJ_ID IS NULL) THEN
  BEGIN
    -- ACTION_ID тут всегда NULL, оно заполнится в PUPIL_ACCEPT_MOVEMENTS или при проведении приказа

    INSERT INTO ORDER_DATA
    (ORDER_ID, REF_ID, ACTION_TYPE, ACTION_ID, IS_PRESENT, DST_DATA, GRADE_NAME, JOB_ID, JOB_ID2)
    VALUES (:I$ORDER_ID, :I$REF_ID, 0, NULL, :I$IS_PRESENT, :I$DST_DATA, :V$GRADE_NAME, :I$JOB_ID, :I$JOB_ID2)
    RETURNING OBJ_ID INTO :OBJ_ID;
  END
  ELSE
  BEGIN
    -- REF_ID может меняться только в приказах по персоналу
    IF(V$OLD_PRESENT <> I$IS_PRESENT OR COALESCE(I$DST_DATA, '') <> COALESCE(V$DST, '') OR COALESCE(I$JOB_ID, 0) <> COALESCE(V$JOB_ID, 0)
      OR COALESCE(I$JOB_ID2, 0) <> COALESCE(V$JOB_ID2, 0) OR I$REF_ID <> V$REF_ID OR COALESCE(V$OLD_GN, '') <> COALESCE(V$GRADE_NAME, '')) THEN
    BEGIN
      UPDATE ORDER_DATA
      SET IS_PRESENT = :I$IS_PRESENT, DST_DATA = :I$DST_DATA, JOB_ID = :I$JOB_ID, JOB_ID2 = :I$JOB_ID2, GRADE_NAME = :V$GRADE_NAME,
        REF_ID = IIF(:V$TYPE_ID IN (14256, 14257, 14258, 14259, 14260, 14271, 14272), :I$REF_ID, REF_ID)
      WHERE OBJ_ID = :I$OBJ_ID;
    END

    OBJ_ID = I$OBJ_ID;
  END

  ORDER_ID = I$ORDER_ID;

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE ORDER_SET_STATE (
    I$OBJ_ID BIGINT,
    I$STATE_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$STATE_ID BIGINT;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$REF_ID BIGINT;
DECLARE VARIABLE V$ORDER_DATE DATE;
DECLARE VARIABLE V$ORDER_NUM VARCHAR(100);
DECLARE VARIABLE V$ACTION_DATE DATE;
DECLARE VARIABLE V$DEST VARCHAR(1000);
DECLARE VARIABLE V$DEST_ID BIGINT;
DECLARE VARIABLE V$DEST_TYPE_ID BIGINT;
DECLARE VARIABLE V$TYPE_ID BIGINT;
DECLARE VARIABLE V$YEAR INTEGER;
DECLARE VARIABLE V$DEST_TYPE BIGINT;
DECLARE VARIABLE V$MOVE_ID BIGINT;
DECLARE VARIABLE V$OLD_ID BIGINT;
DECLARE VARIABLE V$CONTAINER_OUT_ID BIGINT;
DECLARE VARIABLE V$OUT_FOLDER_ID BIGINT;
DECLARE VARIABLE V$MOVE_TYPE BIGINT;
DECLARE VARIABLE V$STAGE_ID BIGINT;
DECLARE VARIABLE V$YC SMALLINT;
DECLARE VARIABLE S VARCHAR(400);
DECLARE VARIABLE V$GROUPS VARCHAR(400);
DECLARE VARIABLE N1 INTEGER;
DECLARE VARIABLE N2 INTEGER;
DECLARE VARIABLE P INTEGER;
DECLARE VARIABLE V$LEAVE_TYPE BIGINT;
DECLARE VARIABLE V$LEAVE_FOR BIGINT;
DECLARE VARIABLE V$HAVE_DOC BIGINT;
DECLARE VARIABLE V$LEAVE_TO BIGINT;
DECLARE VARIABLE V$TO_TYPE BIGINT;
DECLARE VARIABLE V$DISTR BIGINT;
DECLARE VARIABLE V$CTYPE BIGINT;
DECLARE VARIABLE V$D DATE;
DECLARE VARIABLE V$N VARCHAR(100);
DECLARE VARIABLE V$MT BIGINT;
DECLARE VARIABLE V$TYPE_GROUP BIGINT;
DECLARE VARIABLE V$STATUS VARCHAR(2);
DECLARE VARIABLE D1 DATE;
DECLARE VARIABLE D2 DATE;
begin
  -- I$USER_ID с собакой в начале выставляется при переводе года

  V$YC = 0;
  IF(SUBSTRING(I$USER_ID FROM 1 FOR 1) = '@') THEN
  BEGIN
    I$USER_ID = SUBSTRING(I$USER_ID FROM 2);
    V$YC = 1;
  END

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  V$STATUS = (SELECT STATUS FROM OU_LICENCE_TYPE);

  SELECT D.STATE_ID, D.ORDER_DATE, D.ORDER_NUM, D.ACTION_DATE, D.TYPE_ID, D.PROJECT_NUM, LV.PARENT_ID
  FROM ORDERS D
  JOIN LISTVALS LV ON LV.LISTVAL_ID = D.TYPE_ID
  WHERE D.OBJ_ID = :I$OBJ_ID AND D.DATE_DEL IS NULL
  INTO :V$STATE_ID, :V$ORDER_DATE, :V$ORDER_NUM, :V$ACTION_DATE, :V$TYPE_ID, :S, :V$TYPE_GROUP;

  IF(V$STATE_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Запись не найдена';
  IF(V$STATE_ID = I$STATE_ID) THEN EXIT;

  -- Дальше только когда статус приказа изменился

  -- Нельзя выполнять вручную приказы о переводе в следующий класс и оставлении на второй год
  IF(V$TYPE_ID IN (12932, 12937) AND V$YC = 0) THEN
    EXCEPTION DATA_ERROR 'Приказы о переводе в следующий класс и оставлении на повторное обучение обрабатываются только автоматически при переводе года';

  -- Проверяем дату движения - она должна попадать в текущий учебный год + можно 31.08
  SELECT LV.COST
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$YEAR;

  -- При переводе года проверку даты по началу отключаем

  IF(V$ACTION_DATE IS NULL) THEN V$ACTION_DATE = V$ORDER_DATE;
  D1 = '01.09.' || V$YEAR;
  D2 = '01.09.' || (V$YEAR + 1);
  IF(V$TYPE_GROUP = 14270) THEN
  BEGIN
    D1 = DATEADD(-1 MONTH TO D1);
    D2 = DATEADD(1 MONTH TO D2);
  END

  IF((V$YC = 0 AND V$ACTION_DATE < D1) OR V$ACTION_DATE > D2) THEN
    EXCEPTION DATA_ERROR 'Дата движения ' || V$ACTION_DATE || ' должна находиться в текущем учебном году. Приказы вне пределов учебного года нельзя создавать, выполнять или отменять';

  -- Выполняем проводку документа при переводе в статус действующего приказа
  IF(I$STATE_ID = 11715) THEN
  BEGIN

    IF((SELECT COUNT(*) FROM ORDER_DATA OD WHERE OD.DATE_DEL IS NULL AND OD.ORDER_ID = :I$OBJ_ID) = 0) THEN
      EXCEPTION DATA_ERROR 'Нельзя утвердить приказ (номер проекта ' || S || ') без наполнения';

    -- Персона может находиться только в одном проекте приказа такого же типа
    V$GROUPS = NULL;
    V$REF_ID = NULL;
    SELECT FIRST 1 D2.PROJECT_NUM, OD.REF_ID
    FROM ORDER_DATA OD
    JOIN ORDER_DATA OD2 ON OD2.DATE_DEL IS NULL AND OD2.REF_ID = OD.REF_ID AND OD2.OBJ_ID <> OD.OBJ_ID AND OD2.ORDER_ID <> OD.ORDER_ID
    JOIN ORDERS D2 ON D2.DATE_DEL IS NULL AND D2.TYPE_ID = :V$TYPE_ID AND D2.STATE_ID = 11716 AND D2.OBJ_ID = OD2.ORDER_ID
    WHERE OD.DATE_DEL IS NULL AND OD.ORDER_ID = :I$OBJ_ID
    INTO :V$GROUPS, :V$REF_ID;

    IF(V$GROUPS IS NOT NULL AND (V$TYPE_ID <> 13326 OR CURRENT_DATE > '10.09.2023')) THEN
      EXCEPTION DATA_ERROR 'Персоны в приказе могут указываться только в одном приказе того же типа, проверьте проект приказа ' || V$GROUPS ||
        ', ' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$REF_ID));

    -- В одном приказе не должны пересекаться актуальные и будущие классы
    SELECT COUNT(*)
    FROM ORDER_DATA OD
    JOIN VALS V3025 ON V3025.OBJ_ID = OD.REF_ID AND V3025.PARAM_ID = 3025 AND V3025.IS_DEL = 0 AND POSITION('будущий ' IN V3025.SVAL) <= 0
    WHERE OD.DATE_DEL IS NULL AND OD.ORDER_ID = :I$OBJ_ID
    INTO :N1;

    SELECT COUNT(*)
    FROM ORDER_DATA OD
    JOIN VALS V3025 ON V3025.OBJ_ID = OD.REF_ID AND V3025.PARAM_ID = 3025 AND V3025.IS_DEL = 0 AND POSITION('будущий ' IN V3025.SVAL) > 0
    WHERE OD.DATE_DEL IS NULL AND OD.ORDER_ID = :I$OBJ_ID
    INTO :N2;

    IF(N1 > 0 AND N2 > 0) THEN EXCEPTION DATA_ERROR 'Нельзя в одном приказе смешивать будущие и текущие учебные коллективы';

    -- Ученики - обновляем название текущего и будущего учебного коллектива
    -- все виды перевода и выбытия (зачисление и зачисление для ГИА - отдельный кейс)
    FOR
      SELECT D.OBJ_ID, D.REF_ID, V3025.SVAL,
        (SELECT FIRST 1 LPG.PARENT_ID FROM LINKS LPG WHERE LPG.OBJ_ID = D.REF_ID AND LPG.PARENT_TYPE_ID IN (9, 125, 187, 290) AND LPG.DATE_DEL IS NULL)
      FROM ORDER_DATA D
      LEFT JOIN VALS V3025 ON V3025.OBJ_ID = D.REF_ID AND V3025.PARAM_ID = 3025 AND V3025.IS_DEL = 0
      WHERE D.DATE_DEL IS NULL AND D.ORDER_ID = :I$OBJ_ID AND :V$TYPE_ID IN (12931, 12932, 12933, 12934, 12935, 12936, 12937)
      ORDER BY 1
      INTO :V$OBJ_ID, :V$REF_ID, :V$GROUPS, :V$DEST_ID
    DO
    BEGIN
      -- Обновляем текущее наименование класса во всех строках этого приказа
      -- При переводе года нам нужно старое название коллектива, сохраненное во временной таблице
      S = NULL;
      SELECT T.GRADE_NAME_OLD
      FROM YCHANGE_GRADES_TMP T
      WHERE T.GRADE_ID = :V$DEST_ID
      INTO :S;

      -- В остальных случаях берем текущее название
      IF(S IS NULL) THEN S = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$DEST_ID));

      -- Для приказов по зачислению, приему для ГИА, переводу в другой класс, оставлению на второй год
      -- добавляем название нового учебного коллектива из #3025
      IF(V$TYPE_ID IN (12931, 12937)) THEN S = S || '|' || REPLACE(V$GROUPS, 'будущий ', '');

      -- Перевод на следующий этап обучения
      -- Только при переводе года, берем текущее название класса - оно уже поменялось
      IF(V$TYPE_ID = 12932) THEN
      BEGIN
        SELECT FIRST 1 :S || '|' || C.CAPTION
        FROM LINKS L
        LEFT JOIN OBJECT_CAPTION_GET(L.PARENT_ID) C ON 1 = 1
        WHERE L.OBJ_ID = :V$REF_ID AND L.PARENT_TYPE_ID IN (9, 187) AND L.DATE_DEL IS NULL
        INTO :S;
      END

      UPDATE ORDER_DATA
      SET GRADE_NAME = :S
      WHERE OBJ_ID = :V$OBJ_ID AND COALESCE(GRADE_NAME, '') <> COALESCE(:S, '');
    END

    -- Зачисление и зачисление для ГИА
    FOR
      SELECT D.OBJ_ID, D.REF_ID, V3025.VAL, D.DST_GROUPS
      FROM ORDER_DATA D
      LEFT JOIN VALS V3025 ON V3025.OBJ_ID = D.REF_ID AND V3025.PARAM_ID = 3025 AND V3025.IS_DEL = 0
      WHERE D.DATE_DEL IS NULL AND D.ORDER_ID = :I$OBJ_ID AND :V$TYPE_ID IN (12929, 12930)
      INTO :V$OBJ_ID, :V$REF_ID, :V$DEST, :V$GROUPS
    DO
    BEGIN

      -- При переводе года он уже не будущий
      IF(V$YC = 1) THEN V$DEST = REPLACE(V$DEST, 'будущий ', '');
      S = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$REF_ID, 23));

      -- Для ДОУ убираем кривые кавычки
      V$DEST = REPLACE(REPLACE(V$DEST, '«', ''), '»', '');

      --VAL = '@ ' || S || ' в ' || V$DEST;
      --SUSPEND;

      V$DEST_ID = NULL;

      SELECT COUNT(*)
      FROM LINKS L9
      LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C ON 1 = 1
      WHERE L9.PARENT_TYPE_ID = 8 AND L9.OBJ_TYPE_ID IN (9, 187) AND L9.DATE_DEL IS NULL AND REPLACE(REPLACE(C.CAPTION, '«', ''), '»', '') = :V$DEST
        AND (L9.LISTVAL_ID IS NULL OR L9.LISTVAL_ID <> 2)
      INTO :N1;

      IF(N1 > 1) THEN EXCEPTION DATA_ERROR 'У обучающегося ' || S || ' найдено более 1 варианта коллектива назначения - ' || COALESCE(V$DEST, '?');

      SELECT L9.OBJ_ID, L9.OBJ_TYPE_ID, V49.LISTVAL_ID
      FROM LINKS L9
      LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C ON 1 = 1
      JOIN VALL V49 ON V49.OBJ_ID = L9.PARENT_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
      WHERE L9.PARENT_TYPE_ID = 8 AND L9.OBJ_TYPE_ID IN (9, 187) AND L9.DATE_DEL IS NULL AND REPLACE(REPLACE(C.CAPTION, '«', ''), '»', '') = :V$DEST
        AND (L9.LISTVAL_ID IS NULL OR L9.LISTVAL_ID <> 2)
      INTO :V$DEST_ID, :V$DEST_TYPE, :V$STAGE_ID;

      IF(V$DEST_ID IS NULL) THEN
      BEGIN
        IF(POSITION('будущий' IN V$DEST) > 0) THEN
          EXCEPTION DATA_ERROR 'У обучающегося ' || S || ' указан будущий учебный коллектив - ' || V$DEST || '. Приказы по зачислению будущего года утверждаются только автоматически в момент перевода года';
        ELSE
          EXCEPTION DATA_ERROR 'У обучающегося ' || S || ' не указан учебный коллектив, указанный коллектив утрачен или еще не создан - ' || COALESCE(V$DEST, '?');
      END

      -- Фактическое движение выполняем только в случае, когда дата движения попадает в текущий учебный год
      -- !!! тут нужно корректировать логику
      --IF(V$ACTION_DATE <> '01.09.' || (V$YEAR + 1)) THEN
      --BEGIN
        -- В первый класс принят для начала обучения (только если из ранее не обучавшихся), в последующие для продолжения обучения. Дата приема в класс всегда 01.09
        -- Досмотреть для детсадов !!!

        -- Если зачисление при переводе года в школе - то выставляем 805, иначе 806
        V$MT = 806;
        IF(V$STAGE_ID = 37 AND V$YC = 1) THEN V$MT = 805;
        IF(V$STATUS = 'C' OR V$STATUS = 'P') THEN V$MT = 5322; -- принят СПО и ДПО
        IF(V$STATUS = 'D') THEN V$MT = 3276; -- принят ДОУ
        IF(V$STATUS = 'U') THEN V$MT = 5546; -- принят УДОД

        SELECT OBJ_ID
        FROM VARGRP_MOVE_PUPIL(:V$REF_ID, :V$DEST_ID, :V$ORDER_NUM, :V$ORDER_DATE, :V$ACTION_DATE, 0, IIF(:V$YC = 0, '', '@') || :I$USER_ID, :I$OBJ_ID, :V$MT, IIF(:V$YC = 0, 903, 901))
        INTO :V$MOVE_ID;

        UPDATE ORDER_DATA
        SET ACTION_ID = :V$MOVE_ID
        WHERE OBJ_ID = :V$OBJ_ID;
      --END

      -- Зачисляем в ГУП и ГПП - кроме перевода года (тут ГУП выбирается не из приказа, а из поля 3119)
      IF(V$YC = 0) THEN
      SELECT COUNT(*) FROM PUPIL_GROUP_ACCEPT(:V$REF_ID, :V$GROUPS, :I$OBJ_ID) INTO :N1;

      -- Фиксируем дату и номер приказа в полях ученика
      SELECT BLOB_ID FROM VAL_ADD(2442, :V$REF_ID, :V$ORDER_DATE) INTO :V$OLD_ID;
      SELECT BLOB_ID FROM VAL_ADD(2443, :V$REF_ID, :V$ORDER_NUM) INTO :V$OLD_ID;

      VAL = 'Зачислен ' || S || ' в ' || V$DEST;
      SUSPEND;

    END

    -- Перевод по параллели и оставление на второй год
    FOR
      SELECT D.OBJ_ID, D.REF_ID, V3025.VAL, D.DST_GROUPS
      FROM ORDER_DATA D
      LEFT JOIN VALS V3025 ON V3025.OBJ_ID = D.REF_ID AND V3025.PARAM_ID = 3025 AND V3025.IS_DEL = 0
      WHERE D.DATE_DEL IS NULL AND D.ORDER_ID = :I$OBJ_ID AND :V$TYPE_ID IN (12931, 12937)
      INTO :V$OBJ_ID, :V$REF_ID, :V$DEST, :V$GROUPS
    DO
    BEGIN

      IF(V$TYPE_ID = 12937) THEN V$MOVE_TYPE = 810; -- повторное обучение
      ELSE IF(POSITION('будущий ' IN V$DEST) > 0) THEN V$MOVE_TYPE = 808; -- если будущий, то следующий этап
      ELSE V$MOVE_TYPE = 807; -- просто перевод

      -- При переводе года он уже не будущий
      IF(V$YC = 1) THEN V$DEST = REPLACE(V$DEST, 'будущий ', '');

      -- Для ДОУ убираем кривые кавычки
      V$DEST = REPLACE(REPLACE(V$DEST, '«', ''), '»', '');

      V$DEST_ID = NULL;

      SELECT COUNT(*)
      FROM LINKS L9
      LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C ON 1 = 1
      WHERE L9.PARENT_TYPE_ID = 8 AND L9.OBJ_TYPE_ID IN (9, 187) AND L9.DATE_DEL IS NULL AND REPLACE(REPLACE(C.CAPTION, '«', ''), '»', '') = :V$DEST
        AND (L9.LISTVAL_ID IS NULL OR L9.LISTVAL_ID <> 2)
      INTO :N1;

      IF(N1 > 1) THEN EXCEPTION DATA_ERROR 'У обучающегося ' || S || ' найдено более 1 варианта коллектива назначения - ' || COALESCE(V$DEST, '?');

      SELECT L9.OBJ_ID, L9.OBJ_TYPE_ID
      FROM LINKS L9
      LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C ON 1 = 1
      WHERE L9.PARENT_TYPE_ID = 8 AND L9.OBJ_TYPE_ID IN (9, 187) AND L9.DATE_DEL IS NULL AND REPLACE(REPLACE(C.CAPTION, '«', ''), '»', '') = :V$DEST
        AND (L9.LISTVAL_ID IS NULL OR L9.LISTVAL_ID <> 2)
      INTO :V$DEST_ID, :V$DEST_TYPE;

      S = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$REF_ID, 23));
      IF(V$DEST_ID IS NULL) THEN
      BEGIN
        IF(POSITION('будущий' IN V$DEST) > 0) THEN
          EXCEPTION DATA_ERROR 'У обучающегося ' || S || ' указан будущий учебный коллектив - ' || V$DEST || '. Приказы по движению будущего года утверждаются только автоматически в момент перевода года';
        ELSE
          EXCEPTION DATA_ERROR 'У обучающегося ' || S || ' не указан учебный коллектив или указанный коллектив (' || COALESCE(V$DEST, '-') || ') утрачен';
      END

      V$OLD_ID = NULL;
      SELECT LPG.PARENT_ID
      FROM LINKS LPG
      WHERE LPG.OBJ_ID = :V$REF_ID AND LPG.PARENT_TYPE_ID IN (9, 187) AND LPG.DATE_DEL IS NULL
      INTO :V$OLD_ID;
      IF(V$OLD_ID IS NULL) THEN EXCEPTION DATA_ERROR 'У обучающегося ' || S || ' не найден текущий учебный коллектив';

      -- ORDER_ID указывается как выбытие у старой записи и зачисление у новой, но запоминается движение зачисления
      SELECT OBJ_ID
      FROM VARGRP_MOVE_PUPIL(:V$REF_ID, :V$OLD_ID, :V$ORDER_NUM, :V$ORDER_DATE, :V$ACTION_DATE, 1, IIF(:V$YC = 0, '', '@') || :I$USER_ID, :I$OBJ_ID, :V$MOVE_TYPE, 902)
      INTO :V$MOVE_ID;

      SELECT OBJ_ID
      FROM VARGRP_MOVE_PUPIL(:V$REF_ID, :V$DEST_ID, :V$ORDER_NUM, :V$ORDER_DATE, :V$ACTION_DATE, 0, IIF(:V$YC = 0, '', '@') || :I$USER_ID, :I$OBJ_ID, :V$MOVE_TYPE, IIF(:V$YC = 0, 903, 901))
      INTO :V$MOVE_ID;

      -- Зачисляем в ГУП и ГПП
      SELECT COUNT(*) FROM PUPIL_GROUP_ACCEPT(:V$REF_ID, :V$GROUPS, :I$OBJ_ID) INTO :N1;

      UPDATE ORDER_DATA
      SET ACTION_ID = :V$MOVE_ID
      WHERE OBJ_ID = :V$OBJ_ID;

      VAL = 'Переведен ' || S || ' в другой коллектив ' || V$DEST;
      SUSPEND;

    END

    -- Перевод в следующий класс - ученик и так уже на месте, нужно только реестр движения подкорректировать
    FOR
      SELECT D.OBJ_ID, D.REF_ID
      FROM ORDER_DATA D
      WHERE D.DATE_DEL IS NULL AND D.ORDER_ID = :I$OBJ_ID AND :V$TYPE_ID = 12932
      INTO :V$OBJ_ID, :V$REF_ID
    DO
    BEGIN
      V$DEST_ID = NULL;
      SELECT FIRST 1 L.PARENT_ID
      FROM LINKS L
      WHERE L.OBJ_ID = :V$REF_ID AND L.PARENT_TYPE_ID IN (9, 187) AND L.DATE_DEL IS NULL
      INTO :V$DEST_ID;

      S = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$REF_ID, 23));
      IF(V$DEST_ID IS NULL) THEN EXCEPTION DATA_ERROR 'У обучающегося ' || S || ' не найден действующий учебный коллектив';

      -- ORDER_ID указывается как выбытие у старой записи и зачисление у новой, но запоминается движение зачисления
      SELECT OBJ_ID
      FROM VARGRP_MOVE_PUPIL(:V$REF_ID, :V$DEST_ID, :V$ORDER_NUM, :V$ORDER_DATE, :V$ACTION_DATE, 1, IIF(:V$YC = 0, '', '@') || :I$USER_ID, :I$OBJ_ID, 808, 902)
      INTO :V$MOVE_ID;

      SELECT OBJ_ID
      FROM VARGRP_MOVE_PUPIL(:V$REF_ID, :V$DEST_ID, :V$ORDER_NUM, :V$ORDER_DATE, :V$ACTION_DATE, 0, IIF(:V$YC = 0, '', '@') || :I$USER_ID, :I$OBJ_ID, 808, 901)
      INTO :V$MOVE_ID;

      UPDATE ORDER_DATA
      SET ACTION_ID = :V$MOVE_ID
      WHERE OBJ_ID = :V$OBJ_ID;

      VAL = 'Переведен ' || S || ' на следующий этап';
      SUSPEND;

    END

    -- Проверяем наличие общей папки окончания-выбытия
    IF(V$TYPE_ID IN (12933, 12934, 12935, 12936)) THEN
    BEGIN
      SELECT FIRST 1 L78.OBJ_ID
      FROM LINKS L78
      WHERE L78.PARENT_TYPE_ID = 2 AND L78.OBJ_TYPE_ID = 78 AND L78.DATE_DEL IS NULL
      INTO :V$CONTAINER_OUT_ID;

      IF(V$CONTAINER_OUT_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не найден каталог выбывших';

      V$YEAR = EXTRACT(YEAR FROM V$ACTION_DATE);
      IF(EXTRACT(MONTH FROM V$ACTION_DATE) <= 8) THEN V$YEAR = V$YEAR - 1;

      -- Выходной каталог - в зависимости от типа выбытия
      SELECT FIRST 1 L.OBJ_ID
      FROM LINKS L
      JOIN VALI V448 ON V448.OBJ_ID = L.OBJ_ID AND V448.PARAM_ID = 448 AND V448.IS_DEL = 0 AND V448.VAL = :V$YEAR
      WHERE L.PARENT_ID = :V$CONTAINER_OUT_ID AND L.OBJ_TYPE_ID = 82 AND L.DATE_DEL IS NULL
      INTO :V$OUT_FOLDER_ID;
    END

    -- Все виды выбытия
    IF(V$STATUS IN ('O', 'D', 'C', 'S')) THEN
    FOR
      SELECT D.REF_ID, COALESCE(D.DST_DATA, '')
      FROM ORDER_DATA D
      WHERE D.DATE_DEL IS NULL AND D.ORDER_ID = :I$OBJ_ID AND :V$TYPE_ID = 12934   -- Об отчислении обучающегося по заявлению
      INTO :V$REF_ID, :V$DEST
    DO
    BEGIN
      -- тут должно быть 10 элементов, разделенных символом |
      -- смотри таблицу в комментариях frame_orders_mv
      -- обязательным является только поля 3 action_type и 5 leave_for, остальные в зависимости от обстоятельств
      -- 1, 2, 9 не обязательны никогда
      N1 = 0;
      N2 = 0;
      V$LEAVE_TYPE = NULL;
      WHILE(CHAR_LENGTH(V$DEST) > 0) DO
      BEGIN
        N1 = N1 + 1;
        P = POSITION('|' IN V$DEST);
        IF(P > 0) THEN
        BEGIN
          IF(N1 = 5 AND P > 1) THEN V$LEAVE_TYPE = SUBSTRING(V$DEST FROM 1 FOR P - 1); -- куда выбыл
          IF(P = 1 AND N1 = 3) THEN N2 = 1; -- ключевые показатели - безусловная ошибка
          IF(P = 1 AND N1 = 5 AND V$STATUS IN ('O', 'D', 'S')) THEN N2 = 1;
          IF(P = 1 AND V$LEAVE_TYPE IN (905, 3143) AND V$STATUS IN ('O', 'D', 'S') AND N1 = 6) THEN N2 = 1; -- параметры ОУ выбытия в другом районе или в другое ДОУ, нужен район
          -- !!! проверить следующую строку где O
          IF(P = 1 AND V$LEAVE_TYPE IN (904, 905, 3143, 3283, 3284, 3285, 3286, 11363) AND V$STATUS = 'O' AND N1 IN (7, 8)) THEN N2 = 1; -- параметры ОУ выбытия, только если в ОУ своего региона, только школа
          V$DEST = SUBSTRING(V$DEST FROM P + 1);
          -- Название ОУ должно быть указано
          -- Досмотреть СПО
          IF(N1 = 9 AND CHAR_LENGTH(V$DEST) = 0 AND V$STATUS IN ('O', 'D', 'S') AND V$LEAVE_TYPE IN (904, 905, 906, 907, 3143, 3283, /*3284, 3285, 3286,*/ 11363)) THEN N2 = 1;
        END
        ELSE
        BEGIN
          -- Это последний параметр, если он был непустой
          V$DEST = '';
        END
      END

      IF(N2 > 0 OR N1 < 9) THEN EXCEPTION DATA_ERROR 'Для обучающегося ' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$REF_ID)) || ' не заданы все обязательные реквизиты выбытия';
    END

    -- Выбытие по прочим причинам или окончание
    FOR
      SELECT D.OBJ_ID, D.REF_ID, D.DST_DATA
      FROM ORDER_DATA D
      WHERE D.DATE_DEL IS NULL AND D.ORDER_ID = :I$OBJ_ID AND :V$TYPE_ID IN (12933, 12934, 12935, 12936)
      INTO :V$OBJ_ID, :V$REF_ID, :V$DEST
    DO
    BEGIN

      V$DEST_ID = NULL;
      SELECT FIRST 1 LPG.PARENT_ID, LPG.PARENT_TYPE_ID
      FROM LINKS LPG
      WHERE LPG.OBJ_ID = :V$REF_ID AND LPG.PARENT_TYPE_ID IN (9, 187) AND LPG.DATE_DEL IS NULL
      INTO :V$DEST_ID, :V$DEST_TYPE_ID;

      S = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$REF_ID));

      IF(V$DEST_ID IS NULL) THEN EXCEPTION DATA_ERROR 'По обучающемуся ' || S || ' не найден текущий учебный коллектив, ошибка в реестре движения';

      -- В школах и ДОУ будет просто выбыл или окончил
      -- В СПО ставим причину по заявлению
      IF(V$STATUS = 'C') THEN
      BEGIN
        IF(V$TYPE_ID = 12933) THEN V$MOVE_TYPE = 812;
        ELSE IF(V$TYPE_ID = 12935) THEN V$MOVE_TYPE = 812; -- по инициативе ОУ
        -- ELSE IF(V$TYPE_ID = 12936) THEN V$MOVE_TYPE = ; -- по иным обстоятельствам
        -- ELSE IF(V$TYPE_ID = ) THEN V$MOVE_TYPE = 5319; -- в академку
        ELSE V$MOVE_TYPE = 5316; -- по личному заявлению
      END
      ELSE
      BEGIN
        IF(V$TYPE_ID = 12933) THEN V$MOVE_TYPE = 812; ELSE V$MOVE_TYPE = 811;
      END

      -- Для экстерната линк в выбывших создавать не нужно !

      -- Изменено: теперь все действия по созданию движения выполняет PARAGRAF_EDUCATION_LEAVE
      -- Но поскольку она ничего не возвращает, чтобы вытащить id нужно делать запрос
      SELECT FIRST 1 M.OBJ_ID
      FROM LINKS LPG
      JOIN PERSON_MOVEMENTS M ON M.DATE_DEL IS NULL AND M.PERSON_ID = LPG.OBJ_ID AND M.GROUP_ID = LPG.PARENT_ID AND M.DATE_OUT IS NULL
      WHERE LPG.OBJ_ID = :V$REF_ID AND LPG.PARENT_TYPE_ID IN (9, 125, 187, 243) AND LPG.DATE_DEL IS NULL
      INTO :V$MOVE_ID;

      -- Реквизиты ОУ выбытия
      V$LEAVE_FOR = NULL;
      V$HAVE_DOC = NULL;
      V$LEAVE_TO = NULL;
      V$TO_TYPE = NULL;
      V$GROUPS = NULL;
      V$DISTR = NULL;
      V$CTYPE = NULL;
      IF(V$TYPE_ID = 12934) THEN
      BEGIN
        N1 = 0;
        WHILE(CHAR_LENGTH(V$DEST) > 0) DO
        BEGIN
          N1 = N1 + 1;
          P = POSITION('|' IN V$DEST);
          IF(P > 0) THEN
          BEGIN
            S = SUBSTRING(V$DEST FROM 1 FOR P - 1);
            IF(P > 1) THEN
            BEGIN
              IF(N1 = 1) THEN V$D = S;
              ELSE IF(N1 = 2) THEN V$N = S;
              ELSE IF(N1 = 3) THEN S = S; -- тип выбытия может быть только то выбытие, которое указано в типе приказа
              ELSE IF(N1 = 4) THEN V$HAVE_DOC = S;
              ELSE IF(N1 = 5) THEN V$LEAVE_FOR = S;
              ELSE IF(N1 = 6) THEN V$DISTR = S;
              ELSE IF(N1 = 7) THEN V$LEAVE_TO = S;
              ELSE IF(N1 = 8) THEN V$TO_TYPE = S;
              ELSE IF(N1 = 9) THEN V$CTYPE = S;
              ELSE IF(N1 = 10) THEN V$GROUPS = S; -- про запас, по идее сюда не попадаем
            END
            V$DEST = SUBSTRING(V$DEST FROM P + 1);
          END
          ELSE
          BEGIN
            IF(N1 = 10) THEN V$GROUPS = V$DEST;
            V$DEST = '';
          END
        END
      END

      EXECUTE PROCEDURE PARAGRAF_EDUCATION_LEAVE(:V$REF_ID, :V$ACTION_DATE, :V$MOVE_TYPE, :V$ORDER_NUM, :V$ORDER_DATE, :V$LEAVE_FOR, :V$HAVE_DOC,
        :V$LEAVE_TO, :V$TO_TYPE, :V$GROUPS, :V$DISTR, :V$CTYPE, IIF(:V$YC = 0, '', '@') || :I$USER_ID, 902, NULL, :V$D, :V$N);

      UPDATE ORDER_DATA
      SET ACTION_ID = :V$MOVE_ID
      WHERE OBJ_ID = :V$OBJ_ID;

      VAL = 'Выбыл/окончил ' || S;
      SUSPEND;

    END

    -- Чистим старые хвосты - поле определен для выбытия в...
    FOR
      SELECT D.OBJ_ID, D.REF_ID
      FROM ORDER_DATA D
      WHERE D.DATE_DEL IS NULL AND D.ORDER_ID = :I$OBJ_ID
      INTO :V$OBJ_ID, :V$REF_ID
    DO
    BEGIN
      UPDATE VALS SET IS_DEL = 1 WHERE PARAM_ID = 3025 AND IS_DEL = 0 AND OBJ_ID = :V$REF_ID;
    END

    FOR
      -- Движение по сотрудникам, увольнение
      SELECT VAL
      FROM RDB$DATABASE
      LEFT JOIN ORDER_STATE_GO_EM_OUT(:I$OBJ_ID, :V$TYPE_ID) M ON 1 = 1
      WHERE :V$TYPE_ID IN (14257, 14258, 14272)  -- об увольнении/переводе/изменении кол-ва ставок
      -- Движение по сотрудникам, прием на должность
      UNION ALL
      SELECT VAL
      FROM RDB$DATABASE
      LEFT JOIN ORDER_STATE_GO_EM_IN(:I$OBJ_ID, :V$TYPE_ID) M ON 1 = 1
      WHERE :V$TYPE_ID IN (14256, 14258, 14272) -- о приеме/переводе/изменении кол-ва ставок
      -- Движение по сотрудникам, назначение классруков
      UNION ALL
      SELECT VAL
      FROM RDB$DATABASE
      LEFT JOIN ORDER_STATE_GO_EM_CMATE(:I$OBJ_ID, :V$TYPE_ID) M ON 1 = 1
      WHERE :V$TYPE_ID IN (14271)
      INTO :VAL
    DO
    BEGIN
      SUSPEND;
    END

  END
  -- Возврат из проведенного статуса в проект. Или в отмененные тоже ?
  ELSE IF(V$STATE_ID = 11715) THEN
  BEGIN

    -- Отмена проведенного приказа, возврат зачисленных в исходное положение
    -- только если по учащимся были вручную отменены все последующие движения, т.е. после зачисления все чисто
    -- для приказа где указывается назначение - возвращаем текст в поле персоны

    -- Ни в коем случае не позволяем возвращать в проект приказ, если хотя бы один ученик есть в другом открытом проекте
    FOR
      SELECT D.REF_ID, C.CAPTION
      FROM ORDER_DATA D
      LEFT JOIN OBJECT_CAPTION_GET(D.REF_ID) C ON 1 = 1
      WHERE D.DATE_DEL IS NULL AND D.ORDER_ID = :I$OBJ_ID
      INTO :V$REF_ID, :S
    DO
    BEGIN
      V$OBJ_ID = NULL;
      SELECT FIRST 1 D.OBJ_ID, COALESCE('№' || D.ORDER_NUM, 'Проект №' || D.PROJECT_NUM)
      FROM ORDERS D
      JOIN LISTVALS LV ON LV.LISTVAL_ID = D.TYPE_ID AND LV.COST = :V$TYPE_GROUP -- из той же группы типов приказов
      JOIN ORDER_DATA OD ON OD.DATE_DEL IS NULL AND OD.ORDER_ID = D.OBJ_ID AND OD.REF_ID = :V$REF_ID
      WHERE D.DATE_DEL IS NULL AND D.STATE_ID = 11716 AND D.OBJ_ID <> :I$OBJ_ID
      INTO :V$OBJ_ID, :V$GROUPS;

      IF(V$OBJ_ID IS NOT NULL) THEN EXCEPTION DATA_ERROR 'Персона ' || S || ' уже входит в проект приказа ' || V$GROUPS;
    END

    -- Зачисление
    FOR
      SELECT D.OBJ_ID, D.REF_ID, D.ACTION_ID, M.GROUP_ID, C.CAPTION
      FROM ORDER_DATA D
      JOIN PERSON_MOVEMENTS M ON M.OBJ_ID = D.ACTION_ID
      LEFT JOIN OBJECT_CAPTION_GET(M.GROUP_ID) C ON 1 = 1
      WHERE D.DATE_DEL IS NULL AND D.ORDER_ID = :I$OBJ_ID AND :V$TYPE_ID = 12929
      INTO :V$OBJ_ID, :V$REF_ID, :V$MOVE_ID, :V$DEST_ID, :S
    DO
    BEGIN

      IF(EXISTS(
        SELECT 1
        FROM PERSON_MOVEMENTS M
        JOIN OBJECTS O ON O.OBJ_ID = M.GROUP_ID AND O.TYPE_ID IN (9, 187, 243)
        WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :V$REF_ID AND M.OBJ_ID > :V$MOVE_ID
      ))
      THEN
        EXCEPTION DATA_ERROR 'По обучающемуся ' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$REF_ID)) || ' есть более поздние движения, нельзя отменить приказ';

      -- Отменяем движение, ученик уберется из класса куда зачислен
      SELECT OBJ_ID FROM VARGRP_MOVE_PUPIL(:V$REF_ID, :V$DEST_ID, NULL, NULL, NULL, 3, NULL, NULL) INTO :V$DEST_TYPE;

      -- Теперь надо вернуть в предварительный прием, где он был, либо в отчисленных
      V$DEST_ID = NULL;
      SELECT FIRST 1 L290.LINK_ID
      FROM LINKS L290
      WHERE L290.OBJ_ID = :V$REF_ID AND L290.PARENT_TYPE_ID IN (81, 82, 83, 290) AND L290.DATE_DEL IS NOT NULL
      ORDER BY L290.LINK_ID DESC
      INTO :V$DEST_ID;

      IF(V$DEST_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Папка предварительного приема или выбывших утрачена';

      UPDATE LINKS
      SET DATE_DEL = NULL
      WHERE LINK_ID = :V$DEST_ID;

      -- Возвращаем обратно выбор учебного коллектива назначения
      SELECT BLOB_ID FROM VAL_ADD(3025, :V$REF_ID, :S) INTO :V$DEST_ID;

    END

    -- Перевод по параллели и оставление на повторное
    FOR
      SELECT D.OBJ_ID, D.REF_ID, D.ACTION_ID, M.GROUP_ID, C.CAPTION
      FROM ORDER_DATA D
      JOIN PERSON_MOVEMENTS M ON M.OBJ_ID = D.ACTION_ID
      LEFT JOIN OBJECT_CAPTION_GET(M.GROUP_ID) C ON 1 = 1
      WHERE D.DATE_DEL IS NULL AND D.ORDER_ID = :I$OBJ_ID AND :V$TYPE_ID IN (12931, 12937)
      INTO :V$OBJ_ID, :V$REF_ID, :V$MOVE_ID, :V$DEST_ID, :S
    DO
    BEGIN
      IF(EXISTS(
        SELECT 1
        FROM PERSON_MOVEMENTS M
        JOIN OBJECTS O ON O.OBJ_ID = M.GROUP_ID AND O.TYPE_ID IN (9, 187, 243)
        WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :V$REF_ID AND M.OBJ_ID > :V$MOVE_ID
      ))
      THEN EXCEPTION DATA_ERROR 'По обучающемуся ' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$REF_ID)) || ' есть более поздние движения, нельзя отменить приказ';

      -- Отменяем зачисление в новый класс, ученик уберется из класса куда зачислен
      SELECT OBJ_ID FROM VARGRP_MOVE_PUPIL(:V$REF_ID, :V$DEST_ID, NULL, NULL, NULL, 3, NULL, NULL) INTO :V$DEST_TYPE;

      -- Отменяем отчисление из старого класса
      V$DEST_ID = NULL;
      SELECT M.GROUP_ID
      FROM PERSON_MOVEMENTS M
      JOIN OBJECTS O ON O.OBJ_ID = M.GROUP_ID AND O.TYPE_ID IN (9, 187, 243)
      WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :V$REF_ID AND M.ORDER_ID_OUT = :I$OBJ_ID
      INTO :V$DEST_ID;

      IF(V$DEST_ID IS NULL) THEN EXCEPTION DATA_ERROR 'По обучающемуся ' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$REF_ID)) || ' не найдена запись зачисления';

      SELECT OBJ_ID FROM VARGRP_MOVE_PUPIL(:V$REF_ID, :V$DEST_ID, NULL, NULL, NULL, 4, NULL, NULL) INTO :V$DEST_TYPE;

      -- Возвращаем обратно выбор учебного коллектива назначения
      SELECT BLOB_ID FROM VAL_ADD(3025, :V$REF_ID, :S) INTO :V$DEST_ID;
    END

    -- Все виды выбытия
    FOR
      SELECT D.OBJ_ID, D.REF_ID, D.ACTION_ID, M.GROUP_ID
      FROM ORDER_DATA D
      JOIN PERSON_MOVEMENTS M ON M.OBJ_ID = D.ACTION_ID
      WHERE D.DATE_DEL IS NULL AND D.ORDER_ID = :I$OBJ_ID AND :V$TYPE_ID IN (12933, 12934, 12935, 12936)
      INTO :V$OBJ_ID, :V$REF_ID, :V$MOVE_ID, :V$DEST_ID
    DO
    BEGIN

      -- Отменяем выбытие в последней записи движения
      IF(EXISTS(
        SELECT 1
        FROM PERSON_MOVEMENTS M
        JOIN OBJECTS O ON O.OBJ_ID = M.GROUP_ID AND O.TYPE_ID IN (9, 187, 243)
        WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :V$REF_ID AND M.OBJ_ID > :V$MOVE_ID
      ))
      THEN EXCEPTION DATA_ERROR 'По обучающемуся ' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$REF_ID)) || ' есть более поздние движения, нельзя отменить приказ';

      -- Восстанавливаем в папке учебного коллектива
      V$MOVE_ID = NULL;
      SELECT FIRST 1 LPG.PARENT_ID
      FROM LINKS LPG
      JOIN LINKS LPF ON LPF.OBJ_ID = LPG.PARENT_ID AND LPF.PARENT_TYPE_ID = 8 AND LPF.DATE_DEL IS NULL
      WHERE LPG.OBJ_ID = :V$REF_ID AND LPG.PARENT_ID = :V$DEST_ID
      ORDER BY LPG.DATE_DEL DESC
      INTO :V$MOVE_ID;

      IF(V$MOVE_ID IS NULL) THEN
        EXCEPTION DATA_ERROR 'По обучающемуся ' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$REF_ID)) || ' не найден или был утрачен старый учебный коллектив';

      SELECT OBJ_ID FROM VARGRP_MOVE_PUPIL(:V$REF_ID, :V$DEST_ID, NULL, NULL, NULL, 4, NULL, NULL) INTO :V$DEST_TYPE;

    END

    FOR
      -- Движение по сотрудникам, прием на должность
      SELECT VAL
      FROM RDB$DATABASE
      LEFT JOIN ORDER_STATE_RW_EM_IN(:I$OBJ_ID, :V$TYPE_ID) M ON 1 = 1
      WHERE :V$TYPE_ID IN (14256, 14258, 14272)
      -- Движение по сотрудникам, увольнение
      UNION ALL
      SELECT VAL
      FROM RDB$DATABASE
      LEFT JOIN ORDER_STATE_RW_EM_OUT(:I$OBJ_ID, :V$TYPE_ID) M ON 1 = 1
      WHERE :V$TYPE_ID IN (14257, 14258, 14272)
      -- Движение по сотрудникам, назначение классруков
      UNION ALL
      SELECT VAL
      FROM RDB$DATABASE
      LEFT JOIN ORDER_STATE_RW_EM_CMATE(:I$OBJ_ID, :V$TYPE_ID) M ON 1 = 1
      WHERE :V$TYPE_ID IN (14271)
      INTO :VAL
    DO
    BEGIN
      SUSPEND;
    END
  END

  UPDATE ORDERS
  SET STATE_ID = :I$STATE_ID
  WHERE OBJ_ID = :I$OBJ_ID;
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE ORDER_STATE_GO_EM_CMATE (
    I$ORDER_ID BIGINT,
    I$TYPE_ID BIGINT)
RETURNS (
    VAL VARCHAR(1000))
AS
declare variable V$OBJ_ID bigint;
declare variable V$REF_ID bigint;
declare variable V$JOB_ID bigint;
begin

  -- JOB_ID хранит ссылку на класс

  FOR
    SELECT OD.OBJ_ID, OD.REF_ID, OD.JOB_ID
    FROM ORDER_DATA OD
    JOIN ORDERS D ON D.OBJ_ID = OD.ORDER_ID
    -- только действующие классы
    JOIN LINKS LP8 ON LP8.OBJ_ID = OD.JOB_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
    WHERE OD.DATE_DEL IS NULL AND OD.ORDER_ID = :I$ORDER_ID
    INTO :V$OBJ_ID, :V$REF_ID, :V$JOB_ID
  DO
  BEGIN

    SELECT 1 FROM VAL_ADD(53, :V$JOB_ID, :V$REF_ID) INTO :V$JOB_ID;

    VAL = V$REF_ID || ' -> ' || V$JOB_ID;
    SUSPEND;

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE ORDER_STATE_GO_EM_IN (
    I$ORDER_ID BIGINT,
    I$TYPE_ID BIGINT)
RETURNS (
    VAL VARCHAR(400))
AS
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$REF_ID BIGINT;
DECLARE VARIABLE V$JOB_ID BIGINT;
DECLARE VARIABLE V$JOB_ID2 BIGINT;
DECLARE VARIABLE V$ORDER_DATE DATE;
DECLARE VARIABLE V$ORDER_NUM VARCHAR(100);
DECLARE VARIABLE V$ACTION_DATE DATE;
DECLARE VARIABLE V$DATA VARCHAR(1000);
DECLARE VARIABLE V$BOOKNAME VARCHAR(1000);
DECLARE VARIABLE N INTEGER;
DECLARE VARIABLE T INTEGER;
DECLARE VARIABLE S VARCHAR(400);
DECLARE VARIABLE V$RATE FLOAT;
DECLARE VARIABLE V$JTYPE BIGINT;
DECLARE VARIABLE V$TERMS BIGINT;
DECLARE VARIABLE V$CAT BIGINT;
DECLARE VARIABLE V$DNUM VARCHAR(400);
DECLARE VARIABLE V$DDATE DATE;
DECLARE VARIABLE V$DDATETO DATE;
DECLARE VARIABLE V$MOVEMENT_ID BIGINT;
DECLARE VARIABLE V$ACTION_ID BIGINT;
DECLARE VARIABLE V$LINK_ID BIGINT;
DECLARE VARIABLE V$DT TIMESTAMP;
DECLARE VARIABLE V$JOB_TEACHER VARCHAR(10);
begin

  FOR
    SELECT OD.OBJ_ID, OD.REF_ID, OD.JOB_ID, OD.JOB_ID2, OD.DST_DATA, D.ORDER_DATE, D.ORDER_NUM, D.ACTION_DATE, OD.ACTION_ID
    FROM ORDER_DATA OD
    JOIN ORDERS D ON D.OBJ_ID = OD.ORDER_ID
    WHERE OD.DATE_DEL IS NULL AND OD.ORDER_ID = :I$ORDER_ID
    INTO :V$OBJ_ID, :V$REF_ID, :V$JOB_ID, :V$JOB_ID2, :V$DATA, :V$ORDER_DATE, :V$ORDER_NUM, :V$ACTION_DATE, :V$ACTION_ID
  DO
  BEGIN
    IF(V$JOB_ID2 IS NULL) THEN EXCEPTION DATA_ERROR 'Не указана новая должность';

    -- Достаем параметры из data
    N = 1;
    V$JTYPE = NULL;
    V$RATE = 0;
    V$TERMS = NULL;
    V$CAT = NULL;
    V$DNUM = NULL;
    V$DDATE = NULL;
    V$DDATETO = NULL;
    WHILE(CHAR_LENGTH(V$DATA) > 0) DO
    BEGIN
      T = POSITION(',' IN V$DATA);
      IF(T <= 0) THEN T = CHAR_LENGTH(V$DATA) + 1;
      S = SUBSTRING(V$DATA FROM 1 FOR T - 1);
      V$DATA = SUBSTRING(V$DATA FROM T + 1);

      -- Параметры 1 и 2 касаются увольнения, пропускаем
      -- Параметр 4 есть всегда. Остальные могут отсутствовать при смене количества ставок - берем из старой должности
      IF(N = 4) THEN V$RATE = S;
      ELSE IF(N = 3 AND I$TYPE_ID IN (14256, 14258)) THEN V$JTYPE = S;
      ELSE IF(N = 5 AND I$TYPE_ID IN (14256, 14258)) THEN V$TERMS = S;
      ELSE IF(N = 6 AND I$TYPE_ID IN (14256, 14258)) THEN
      BEGIN
        -- Проверка, установлена ли квалификационная категория, если должность педагогическая
        SELECT VAL FROM DO_FUNC(:V$JOB_ID2, 400) INTO :V$JOB_TEACHER;
        IF (V$JOB_TEACHER = 'Нет' AND S = '') THEN S = 632; -- без категории
        IF (V$JOB_TEACHER = 'Да'  AND S = '') THEN EXCEPTION DATA_ERROR('Не задана категория для педагогической должности');
        V$CAT = S;
      END
      ELSE IF(N = 7) THEN V$DNUM = S;
      ELSE IF(N = 8 AND CHAR_LENGTH(S) > 0) THEN V$DDATE = S;
      ELSE IF(N = 9 AND CHAR_LENGTH(S) > 0) THEN V$DDATETO = S;
      -- Для приказов о приеме на работу - название по трудовой
      ELSE IF(N = 10 AND I$TYPE_ID IN (14256, 14258)) THEN V$BOOKNAME = S;

      N = N + 1;
    END

    -- При изменении ставок берем из старой записи
    IF(I$TYPE_ID = 14272) THEN
    BEGIN
      V$JTYPE = (SELECT V.LISTVAL_ID FROM VALL V WHERE V.OBJ_ID = :V$JOB_ID AND V.PARAM_ID = 72 AND V.IS_DEL = 0);
      V$TERMS = (SELECT V.LISTVAL_ID FROM VALL V WHERE V.OBJ_ID = :V$JOB_ID AND V.PARAM_ID = 587 AND V.IS_DEL = 0);
      V$CAT = (SELECT V.LISTVAL_ID FROM VALL V WHERE V.OBJ_ID = :V$JOB_ID AND V.PARAM_ID = 1790 AND V.IS_DEL = 0);
      V$BOOKNAME = (SELECT V.VAL FROM VALS V WHERE V.OBJ_ID = :V$JOB_ID AND V.PARAM_ID = 3543 AND V.IS_DEL = 0);
    END

    -- Если у нас повторная проводка уже существующего приказа - восстанавливаем удаленную запись
    IF(V$ACTION_ID IS NOT NULL) THEN
    BEGIN
      SELECT L15.LINK_ID, L15.DATE_DEL
      FROM LINKS L15
      WHERE L15.PARENT_ID = :V$REF_ID AND L15.OBJ_ID = :V$ACTION_ID
      INTO :V$LINK_ID, :V$DT;

      IF(V$DT IS NULL) THEN EXCEPTION DATA_ERROR 'Системная ошибка: запись приема на должность должна быть удаленной';

      UPDATE LINKS
      SET DATE_DEL = NULL
      WHERE LINK_ID = :V$LINK_ID;
    END

    -- Провести назначение на должность согласно приказу
    SELECT MOVEMENT_ID
    FROM PARAGRAF_EMPLOYEE_VACANCY_ADD(:V$ACTION_ID, NULL, :V$REF_ID, :V$JOB_ID2, :V$RATE, :V$JTYPE, :V$ACTION_DATE, :V$ORDER_DATE, :V$ORDER_NUM,
      :V$DDATETO, :V$TERMS, :V$DNUM, :V$DDATE, :V$CAT, :V$BOOKNAME)
    INTO :V$MOVEMENT_ID;

    -- Запоминаем ссылку на должность в ACTION_ID, если ее еще нет
    UPDATE ORDER_DATA
    SET ACTION_ID = COALESCE(ACTION_ID, :V$MOVEMENT_ID)
    WHERE OBJ_ID = :V$OBJ_ID;

    VAL = V$REF_ID || ' -> ' || COALESCE(V$JOB_ID2, 'V$JOB_ID2(?)') || ' -> ' || COALESCE(V$MOVEMENT_ID, 'V$MOVEMENT_ID(?)');
    SUSPEND;
  END
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE ORDER_STATE_GO_EM_OUT (
    I$ORDER_ID BIGINT,
    I$TYPE_ID BIGINT,
    I$JOB_ID BIGINT = NULL)
RETURNS (
    VAL VARCHAR(400))
AS
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$REF_ID BIGINT;
DECLARE VARIABLE V$JOB_ID BIGINT;
DECLARE VARIABLE V$JOB_ID2 BIGINT;
DECLARE VARIABLE V$DATA VARCHAR(400);
DECLARE VARIABLE V$ORDER_DATE DATE;
DECLARE VARIABLE V$ORDER_NUM VARCHAR(100);
DECLARE VARIABLE V$ACTION_DATE DATE;
DECLARE VARIABLE V$IN_DATE DATE;
DECLARE VARIABLE V$OUT_DATE DATE;
DECLARE VARIABLE V$FOLDER_ID BIGINT;
DECLARE VARIABLE V$FOLDER_TYPE BIGINT;
DECLARE VARIABLE T INTEGER;
DECLARE VARIABLE N INTEGER;
DECLARE VARIABLE S VARCHAR(1000);
DECLARE VARIABLE V$ID1 BIGINT;
DECLARE VARIABLE V$ID2 BIGINT;
DECLARE VARIABLE V$OUT_ID BIGINT;
DECLARE VARIABLE V$DT TIMESTAMP;
begin

  -- I$JOB_ID используется для перебора активных должностей при увольнении со всех

  FOR
    -- Нормальная ветка
    SELECT OD.OBJ_ID, OD.REF_ID, OD.JOB_ID, OD.JOB_ID2, OD.DST_DATA, V73.VAL, V74.VAL, D.ORDER_DATE, D.ORDER_NUM, D.ACTION_DATE
    FROM ORDER_DATA OD
    JOIN ORDERS D ON D.OBJ_ID = OD.ORDER_ID
    LEFT JOIN VALD V73 ON V73.OBJ_ID = OD.JOB_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0 AND V73.VAL <= D.ACTION_DATE
    LEFT JOIN VALD V74 ON V74.OBJ_ID = OD.JOB_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
    WHERE OD.DATE_DEL IS NULL AND OD.ORDER_ID = :I$ORDER_ID AND :I$JOB_ID IS NULL AND (V74.VAL IS NULL OR V74.VAL > D.ACTION_DATE)
    -- Увольнение с конкретной должности при увольнении со всех
    UNION
    SELECT NULL, OD.REF_ID, :I$JOB_ID, OD.JOB_ID2, OD.DST_DATA, V73.VAL, V74.VAL, D.ORDER_DATE, D.ORDER_NUM, D.ACTION_DATE
    FROM ORDER_DATA OD
    JOIN ORDERS D ON D.OBJ_ID = OD.ORDER_ID
    JOIN VALD V73 ON V73.OBJ_ID = :I$JOB_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0
    LEFT JOIN VALD V74 ON V74.OBJ_ID = :I$JOB_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
    WHERE OD.DATE_DEL IS NULL AND OD.ORDER_ID = :I$ORDER_ID AND :I$JOB_ID IS NOT NULL
    ORDER BY 1
    INTO :V$OBJ_ID, :V$REF_ID, :V$JOB_ID, :V$JOB_ID2, :V$DATA, :V$IN_DATE, :V$OUT_DATE, :V$ORDER_DATE, :V$ORDER_NUM, :V$ACTION_DATE
  DO
  BEGIN
    -- Если JOB_ID не заполнено - увольняем со всех должностей, и запоминаем список должностей в DST_GROUPS
    IF(V$JOB_ID IS NULL) THEN
    BEGIN
      S = '';
      FOR
        SELECT L15.OBJ_ID, V73.VAL
        FROM LINKS L15
        JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0
        LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
        WHERE L15.PARENT_ID = :V$REF_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL AND V74.VAL IS NULL
        INTO :V$JOB_ID, :V$IN_DATE
      DO
      BEGIN
        IF(V$IN_DATE >= V$ACTION_DATE) THEN EXCEPTION DATA_ERROR 'Дата увольнения должна быть позднее даты приема на должность';
        IF(S <> '') THEN S = S || ',';
        S = S || V$JOB_ID;

        FOR
          SELECT VAL
          FROM ORDER_STATE_GO_EM_OUT(:I$ORDER_ID, :I$TYPE_ID, :V$JOB_ID)
          INTO :VAL
        DO
        BEGIN
          SUSPEND;
        END
      END

      IF(S = '') THEN EXCEPTION DATA_ERROR 'У сотрудника нет активных должностей';

      UPDATE ORDER_DATA
      SET DST_GROUPS = :S
      WHERE OBJ_ID = :V$OBJ_ID;
      EXIT;
    END

    -- Сотрудник должен быть актуальным
    -- Собираем цепочку через должность, и она должна собраться на той же ОУ или подразделении
    IF(V$OUT_DATE IS NOT NULL) THEN EXCEPTION DATA_ERROR 'По данной должности сотрудник уже числится уволенным';
    IF(V$IN_DATE IS NULL) THEN EXCEPTION DATA_ERROR 'Не найдена должность или не заполнена дата приема на должность';
    IF(V$IN_DATE >= V$ACTION_DATE) THEN EXCEPTION DATA_ERROR 'Дата увольнения должна быть позднее даты приема на должность';

    V$FOLDER_ID = NULL;
    SELECT FIRST 1 LPX.PARENT_ID, LPX.PARENT_TYPE_ID
    FROM LINKS L15
    JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
    JOIN LINKS LPO ON LPO.OBJ_ID = LP13.PARENT_ID AND LPO.PARENT_TYPE_ID IN (2, 211) AND LPO.DATE_DEL IS NULL
    JOIN LINKS LPX ON LPX.OBJ_ID = L15.PARENT_ID AND LPX.PARENT_ID = LPO.PARENT_ID AND LPX.DATE_DEL IS NULL
    WHERE L15.PARENT_ID = :V$REF_ID AND L15.OBJ_TYPE_ID = 15 AND L15.OBJ_ID = :V$JOB_ID AND L15.DATE_DEL IS NULL
    INTO :V$FOLDER_ID, :V$FOLDER_TYPE;

    IF(V$FOLDER_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Сотрудник не найден или не числится на данной должности';

    N = 1;
    V$ID1 = NULL;
    V$ID2 = NULL;
    WHILE(CHAR_LENGTH(V$DATA) > 0) DO
    BEGIN
      T = POSITION(',' IN V$DATA);
      IF(T <= 0) THEN T = CHAR_LENGTH(V$DATA) + 1;
      S = SUBSTRING(V$DATA FROM 1 FOR T - 1);
      V$DATA = SUBSTRING(V$DATA FROM T + 1);

      IF(CHAR_LENGTH(S) > 0) THEN
      BEGIN
        IF(N = 1) THEN V$ID1 = S;       -- причина увольнения
        ELSE IF(N = 2) THEN V$ID2 = S; -- основание увольнения
      END
      N = N + 1;
    END

    IF(V$ID2 IS NULL) THEN EXCEPTION DATA_ERROR 'Не указано основание увольнения';

    EXECUTE PROCEDURE PARAGRAF_EMPLOYEE_VACANCY_LEAVE(:V$JOB_ID, :V$ACTION_DATE, :V$ORDER_NUM, :V$ORDER_DATE, :V$ID1, :V$ID2, 1, :V$JOB_ID2, 1);

    VAL = V$REF_ID || ' -> ' || V$JOB_ID;
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE ORDER_STATE_RW_EM_CMATE (
    I$ORDER_ID BIGINT,
    I$TYPE_ID BIGINT)
RETURNS (
    VAL VARCHAR(1000))
AS
declare variable V$OBJ_ID bigint;
declare variable V$REF_ID bigint;
declare variable V$JOB_ID bigint;
declare variable V$DATE date;
declare variable V$PREV_ID bigint;
begin

  FOR
    SELECT OD.OBJ_ID, OD.REF_ID, OD.JOB_ID, D.ACTION_DATE
    FROM ORDER_DATA OD
    JOIN ORDERS D ON D.OBJ_ID = OD.ORDER_ID
    -- только действующие классы
    JOIN LINKS LP8 ON LP8.OBJ_ID = OD.JOB_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
    WHERE OD.DATE_DEL IS NULL AND OD.ORDER_ID = :I$ORDER_ID
    INTO :V$OBJ_ID, :V$REF_ID, :V$JOB_ID, :V$DATE
  DO
  BEGIN

    V$DATE = '25.08.' || EXTRACT(YEAR FROM V$DATE);
    IF(EXTRACT(MONTH FROM V$DATE) < 9) THEN V$DATE = '25.08.' || (EXTRACT(YEAR FROM V$DATE) - 1);

    -- Смотрим, есть ли более ранние назначения в пределах учебного года для этого класса
    -- если ничего не нашлось, просто очищаем поле
    V$PREV_ID = NULL;
    SELECT FIRST 1 OD.REF_ID
    FROM ORDERS D
    JOIN ORDER_DATA OD ON OD.DATE_DEL IS NULL AND OD.ORDER_ID = D.OBJ_ID AND OD.JOB_ID = :V$JOB_ID
    WHERE D.DATE_DEL IS NULL AND D.TYPE_ID = 14271 AND D.STATE_ID = 11715 AND D.ACTION_DATE >= :V$DATE
    ORDER BY D.ACTION_DATE DESC
    INTO :V$PREV_ID;

    SELECT 1 FROM VAL_ADD(53, :V$JOB_ID, :V$PREV_ID) INTO :V$JOB_ID;

    VAL = V$REF_ID || ' -> ' || V$JOB_ID;
    SUSPEND;

  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE ORDER_STATE_RW_EM_IN (
    I$ORDER_ID BIGINT,
    I$TYPE_ID BIGINT,
    I$JOB_ID BIGINT = NULL)
RETURNS (
    VAL VARCHAR(400))
AS
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$REF_ID BIGINT;
DECLARE VARIABLE V$JOB_ID BIGINT;
DECLARE VARIABLE V$DATA VARCHAR(400);
DECLARE VARIABLE V$ACTION_ID BIGINT;
DECLARE VARIABLE V$ORDER_DATE DATE;
DECLARE VARIABLE V$ORDER_NUM VARCHAR(100);
DECLARE VARIABLE V$ACTION_DATE DATE;
DECLARE VARIABLE V$OUT_DATE DATE;
DECLARE VARIABLE V$LINK_ID BIGINT;
DECLARE VARIABLE V$DT TIMESTAMP;
DECLARE VARIABLE V$SCHOOL_ID BIGINT;
begin

  FOR
    SELECT OD.OBJ_ID, OD.REF_ID, OD.JOB_ID2, OD.ACTION_ID, OD.DST_DATA, D.ORDER_DATE, D.ORDER_NUM, D.ACTION_DATE
    FROM ORDER_DATA OD
    JOIN ORDERS D ON D.OBJ_ID = OD.ORDER_ID
    WHERE OD.DATE_DEL IS NULL AND OD.ORDER_ID = :I$ORDER_ID
    INTO :V$OBJ_ID, :V$REF_ID, :V$JOB_ID, :V$ACTION_ID, :V$DATA, :V$ORDER_DATE, :V$ORDER_NUM, :V$ACTION_DATE
  DO
  BEGIN

    -- Маркируем связь с должностью как удаленную, но ссылка на нее останется в ACTION_ID
    V$DT = NULL;
    SELECT FIRST 1 L15.LINK_ID, L15.DATE_DEL
    FROM LINKS L15
    WHERE L15.OBJ_ID = :V$ACTION_ID AND L15.PARENT_ID = :V$REF_ID
    INTO :V$LINK_ID, :V$DT;

    IF(V$LINK_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Запись о назначении на должность не найдена';
    IF(V$DT IS NOT NULL) THEN EXCEPTION DATA_ERROR 'Запись о назначении на должность числится как удаленная';

    UPDATE LINKS
    SET DATE_DEL = CURRENT_TIMESTAMP
    WHERE LINK_ID = :V$LINK_ID;

    -- Если должностей не осталось - отрабатываем как при увольнении
    -- само увольнение не сработает, поскольку нет действующих должностей
    -- Если у нас не прием на должность, а перевод - у нас точно будет отмена парного увольнения, и переносить в выбывших не требуется
    IF(I$TYPE_ID = 14256 AND NOT EXISTS(
      SELECT FIRST 1 1
      FROM LINKS L15
      LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
      WHERE L15.PARENT_ID = :V$REF_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL AND V74.VAL IS NULL
    )) THEN
    BEGIN

      V$LINK_ID = NULL;
      SELECT FIRST 1 OBJ_ID FROM OBJECT_PARENTS_GET(:V$JOB_ID, 2) INTO :V$LINK_ID;

      EXECUTE PROCEDURE PARAGRAF_EMPLOYEE_LEAVE(:V$LINK_ID, :V$REF_ID, :V$ACTION_DATE, NULL, NULL, NULL, NULL);

    END

    VAL = V$REF_ID || ' -> ' || V$JOB_ID || ' -> ' || V$ACTION_ID;
    SUSPEND;

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE ORDER_STATE_RW_EM_OUT (
    I$ORDER_ID BIGINT,
    I$TYPE_ID BIGINT,
    I$JOB_ID BIGINT = NULL)
RETURNS (
    VAL VARCHAR(400))
AS
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$REF_ID BIGINT;
DECLARE VARIABLE V$JOB_ID BIGINT;
DECLARE VARIABLE V$DATA VARCHAR(400);
DECLARE VARIABLE V$ACTION_ID BIGINT;
DECLARE VARIABLE V$ORDER_DATE DATE;
DECLARE VARIABLE V$ORDER_NUM VARCHAR(100);
DECLARE VARIABLE V$ACTION_DATE DATE;
DECLARE VARIABLE V$OUT_DATE DATE;
DECLARE VARIABLE V$LINK_ID BIGINT;
DECLARE VARIABLE V$DT TIMESTAMP;
DECLARE VARIABLE S VARCHAR(1000);
begin

  FOR
    -- Нормальная ветка
    SELECT OD.OBJ_ID, OD.REF_ID, OD.JOB_ID, OD.DST_DATA, OD.ACTION_ID, V74.VAL, D.ORDER_DATE, D.ORDER_NUM, D.ACTION_DATE, OD.DST_GROUPS
    FROM ORDER_DATA OD
    JOIN ORDERS D ON D.OBJ_ID = OD.ORDER_ID
    LEFT JOIN VALD V74 ON V74.OBJ_ID = OD.JOB_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
    WHERE OD.DATE_DEL IS NULL AND OD.ORDER_ID = :I$ORDER_ID AND :I$JOB_ID IS NULL
    -- Увольнение с конкретной должности при увольнении со всех
    UNION
    SELECT NULL, OD.REF_ID, :I$JOB_ID, OD.DST_DATA, NULL, V74.VAL, D.ORDER_DATE, D.ORDER_NUM, D.ACTION_DATE, NULL
    FROM ORDER_DATA OD
    JOIN ORDERS D ON D.OBJ_ID = OD.ORDER_ID
    LEFT JOIN VALD V74 ON V74.OBJ_ID = :I$JOB_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
    WHERE OD.DATE_DEL IS NULL AND OD.ORDER_ID = :I$ORDER_ID AND :I$JOB_ID IS NOT NULL
    ORDER BY 1
    INTO :V$OBJ_ID, :V$REF_ID, :V$JOB_ID, :V$DATA, :V$ACTION_ID, :V$OUT_DATE, :V$ORDER_DATE, :V$ORDER_NUM, :V$ACTION_DATE, :S
  DO
  BEGIN
    IF(V$JOB_ID IS NULL) THEN
    BEGIN
      IF(S IS NULL OR S = '') THEN EXCEPTION DATA_ERROR 'Нет данных по должностям уволенного';

      FOR
        SELECT A.VAL
        FROM STR_TO_ID_LIST(:S) L
        LEFT JOIN ORDER_STATE_RW_EM_OUT(:I$ORDER_ID, :I$TYPE_ID, L.ID) A ON 1 = 1
        INTO :VAL
      DO
      BEGIN
        SUSPEND;
      END

      EXIT;
    END

    -- Сотрудник должен быть актуальным
    -- Собираем цепочку через должность, и она должна собраться на той же ОУ или подразделении
    IF(V$OUT_DATE IS NULL) THEN EXCEPTION DATA_ERROR 'По данной должности сотрудник не числится уволенным';

    V$LINK_ID = NULL;
    V$DT = NULL;
    SELECT FIRST 1 LPX.LINK_ID, LPX.DATE_DEL
    FROM LINKS L15
    JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
    JOIN LINKS LPO ON LPO.OBJ_ID = LP13.PARENT_ID AND LPO.PARENT_TYPE_ID IN (2, 211) AND LPO.DATE_DEL IS NULL     -- должность все еще есть в подразделении/школе
    JOIN LINKS LPX ON LPX.OBJ_ID = L15.PARENT_ID AND LPX.PARENT_ID = LPO.PARENT_ID                                -- сотрудник все еще есть/был в подразделении/школе
    WHERE L15.PARENT_ID = :V$REF_ID AND L15.OBJ_TYPE_ID = 15 AND L15.OBJ_ID = :V$JOB_ID AND L15.DATE_DEL IS NULL
    ORDER BY LPX.DATE_DEL DESC NULLS FIRST
    INTO :V$LINK_ID, :V$DT;

    IF(V$LINK_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Системная ошибка: восстанавливаемая должность утрачена';

    EXECUTE PROCEDURE PARAGRAF_EMPLOYEE_CANCEL_LEAVE(:V$REF_ID, :V$JOB_ID);

    VAL = V$REF_ID || ' -> ' || V$JOB_ID;
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE ORD_NM_RULE_AUTO_CREATE (
    I$RULE_TYPE BIGINT)
AS
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$RULE_ID BIGINT;
DECLARE VARIABLE V$YR INTEGER;
DECLARE VARIABLE V$ID BIGINT;
DECLARE VARIABLE V$GR_ID BIGINT;
begin
  -- id школы
  SELECT L2.OBJ_ID
  FROM LINKS L2
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$OBJ_ID;

  -- определим группу приказов по типу приказа
  SELECT PARENT_ID FROM LISTVALS LV WHERE LV.LISTVAL_ID = :I$RULE_TYPE AND LV.IS_DEL = 0 INTO :V$GR_ID;

  -- есть ли вообще правила нумерации приказов?
  IF (NOT EXISTS(
    SELECT FIRST 1 1
    FROM LINKS L2
    JOIN LINKS L406 ON L406.PARENT_ID = L2.OBJ_ID AND L406.OBJ_TYPE_ID = 406 AND L406.DATE_DEL IS NULL
    JOIN VALL V3029 ON V3029.OBJ_ID = L406.OBJ_ID AND V3029.PARAM_ID = 3029 AND V3029.IS_DEL = 0
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V3029.LISTVAL_ID AND LV.IS_DEL = 0 AND LV.PARENT_ID = :V$GR_ID
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_ID = :V$OBJ_ID AND L2.DATE_DEL IS NULL
  )) THEN
  BEGIN
    -- если нет, то добавим общее правило
    SELECT OBJ_ID FROM OBJECT_ADD(:V$OBJ_ID, 406) INTO :V$RULE_ID;
    SELECT BLOB_ID FROM VAL_ADD(3029, :V$RULE_ID, :I$RULE_TYPE) INTO :V$YR;
    V$YR = EXTRACT(YEAR FROM CURRENT_DATE);
    SELECT BLOB_ID FROM VAL_ADD(3107, :V$RULE_ID, :V$YR) INTO :V$YR;
  END

  -- есть ли дубликаты в группе приказов? Если есть, то надо оставить только те правила, которые имеют больший текущий номер
  FOR
    SELECT L406.OBJ_ID
    FROM LINKS L2
    JOIN LINKS L406 ON L406.PARENT_ID = L2.OBJ_ID AND L406.OBJ_TYPE_ID = 406 AND L406.DATE_DEL IS NULL
    JOIN VALL V3029 ON V3029.OBJ_ID = L406.OBJ_ID AND V3029.PARAM_ID = 3029 AND V3029.IS_DEL = 0
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V3029.LISTVAL_ID AND LV.IS_DEL = 0 AND LV.PARENT_ID = :V$GR_ID
    JOIN VALI V3032 ON V3032.OBJ_ID = L406.OBJ_ID AND V3032.PARAM_ID = 3032 AND V3032.IS_DEL = 0
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_ID = :V$OBJ_ID AND L2.DATE_DEL IS NULL
      AND V3032.VAL < (
        SELECT MAX(VV3032.VAL)
        FROM LINKS L
        JOIN LINKS LL406 ON LL406.PARENT_ID = L.OBJ_ID AND LL406.OBJ_TYPE_ID = 406 AND LL406.DATE_DEL IS NULL
        JOIN VALL VV3029 ON VV3029.OBJ_ID = LL406.OBJ_ID AND VV3029.PARAM_ID = 3029 AND VV3029.IS_DEL = 0 AND VV3029.LISTVAL_ID = V3029.LISTVAL_ID -- тот же тип приказа
        JOIN VALI VV3032 ON VV3032.OBJ_ID = LL406.OBJ_ID AND VV3032.PARAM_ID = 3032 AND VV3032.IS_DEL = 0
        WHERE L.PARENT_ID IS NULL AND L.OBJ_ID = :V$OBJ_ID AND L.DATE_DEL IS NULL
      )
    INTO :V$ID
  DO
  BEGIN
    SELECT DEL_COUNT FROM OBJECT_DEL(:V$OBJ_ID, :V$ID) INTO :V$YR;
  END
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE ORGANIZATION_SHORT_NAME_GET RETURNS (
    STR VARCHAR(5000))
AS
DECLARE VARIABLE V$SCHOOL_ID BIGINT;
BEGIN
    SELECT FIRST 1
           OBJ_ID
    FROM LINKS
    WHERE OBJ_TYPE_ID = 2
    AND PARENT_ID IS NULL
    AND DATE_DEL IS NULL
    INTO :V$SCHOOL_ID;

    IF (V$SCHOOL_ID IS NULL) THEN
    BEGIN
        SELECT KEY_VAL
        FROM KEYS
        WHERE KEY_CODE = 'ORGANIZATION_SHORT_NAME'
        INTO :STR;
    END
    ELSE
    BEGIN
        SELECT V
        FROM VAL_GET(:V$SCHOOL_ID, 2)
        INTO :STR;
    END

    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OSH1_1001 (
    I$OBJ_ID BIGINT,
    I$ROOM_TYPE_ID INTEGER)
RETURNS (
    V VARCHAR(3))
AS
DECLARE VARIABLE X INTEGER;
BEGIN

    X = 0;

    SELECT COUNT(*)
    FROM LINKS L73
    INNER JOIN LINKS L16 ON L16.PARENT_ID = L73.OBJ_ID
    INNER JOIN LINKS L61 ON L61.PARENT_ID = L16.OBJ_ID
    INNER JOIN VALL V526 ON V526.OBJ_ID = L61.OBJ_ID
    WHERE L73.PARENT_ID = :I$OBJ_ID
      AND L73.OBJ_TYPE_ID = 73
      AND L73.DATE_DEL IS NULL
      AND L16.OBJ_TYPE_ID = 16
      AND L16.DATE_DEL IS NULL
      AND L61.OBJ_TYPE_ID = 61
      AND L61.DATE_DEL IS NULL
      AND V526.PARAM_ID = 526
      AND V526.IS_DEL = 0
      AND V526.LISTVAL_ID = :I$ROOM_TYPE_ID
    INTO :X;

    IF (X = 0) THEN
    BEGIN
        V = '0';
    END
    ELSE
    BEGIN
        V = '1';
    END

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OSH1_101 (
    I$OBJ_ID BIGINT,
    I$ROW_NUM SMALLINT = 0,
    I$DT DATE = CURRENT_DATE)
RETURNS (
    VAL3 INTEGER,
    VAL4 INTEGER,
    VAL5 INTEGER,
    VAL6 INTEGER,
    VAL7 INTEGER,
    VAL8 INTEGER,
    VAL9 INTEGER,
    VAL10 INTEGER)
AS
DECLARE VARIABLE STAGE_LISTVAL_ID BIGINT;
DECLARE VARIABLE VAL INTEGER;
BEGIN
    IF (:I$ROW_NUM < 2) THEN
    BEGIN
        EXECUTE PROCEDURE SCHOLAR_BY_DATE(:I$OBJ_ID, :I$DT);
    END

    IF (:I$ROW_NUM = 1) THEN
    BEGIN
        SELECT VAL3, VAL7, VAL8, VAL9, VAL10
        FROM OSH1_101(:I$OBJ_ID, 3)
        INTO :VAL3, :VAL7, :VAL8, :VAL9, :VAL10;

        SUSPEND;
        EXIT;
    END

    IF (:I$ROW_NUM = 2) THEN
    BEGIN
        SELECT VAL4, VAL5, VAL6
        FROM OSH1_101(:I$OBJ_ID, 3)
        INTO :VAL4, :VAL5, :VAL6;

        SUSPEND;
        EXIT;
    END

    VAL3 = 0;
    VAL4 = 0;
    VAL5 = 0;
    VAL6 = 0;
    VAL7 = 0;
    VAL8 = 0;
    VAL9 = 0;
    VAL10 = 0;

    FOR SELECT V49.LISTVAL_ID
        FROM LINKS L7
        INNER JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID
        INNER JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID
        WHERE L7.PARENT_ID = :I$OBJ_ID
          AND L7.OBJ_TYPE_ID = 7
          AND L7.DATE_DEL IS NULL
          AND L8.OBJ_TYPE_ID = 8
          AND L8.DATE_DEL IS NULL
          AND V49.PARAM_ID = 49
          AND V49.IS_DEL = 0
        INTO :STAGE_LISTVAL_ID
    DO
    BEGIN
        SELECT COUNT(1)
        FROM REPORT_OSH1 R
        JOIN VALL V592 ON V592.OBJ_ID = R.CLASS_ID
          AND V592.PARAM_ID = 592
          AND V592.IS_DEL = 0
          AND V592.LISTVAL_ID < 198
        WHERE R.STAGE_LISTVAL_ID = :STAGE_LISTVAL_ID
        INTO :VAL;

        IF (STAGE_LISTVAL_ID = 36) THEN VAL3 = VAL3 + VAL;
        IF (STAGE_LISTVAL_ID = 37) THEN VAL4 = VAL4 + VAL;
        IF (STAGE_LISTVAL_ID = 38) THEN VAL5 = VAL5 + VAL;
        IF (STAGE_LISTVAL_ID = 39) THEN VAL6 = VAL6 + VAL;
        IF (STAGE_LISTVAL_ID = 40) THEN VAL7 = VAL7 + VAL;
        IF (STAGE_LISTVAL_ID IN (41, 42, 43, 44, 45)) THEN VAL8 = VAL8 + VAL;
        IF (STAGE_LISTVAL_ID IN (46, 47, 48)) THEN VAL9 = VAL9 + VAL;
    END

    VAL10 = VAL3 + VAL4 + VAL5 + VAL6 + VAL7 + VAL8 + VAL9;

    SUSPEND;

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OSH1_101DTL (
    I$OBJ_ID BIGINT NOT NULL,
    STAGE_NUM SMALLINT NOT NULL)
RETURNS (
    VAL1 VARCHAR(250),
    VAL2 VARCHAR(250),
    VAL3 VARCHAR(250))
AS
BEGIN
    FOR
        SELECT
            (SELECT CAPTION FROM OBJECT_CAPTION_GET(R.SCHOLAR_ID)) VAL1,
            (SELECT D FROM VAL_GET(R.SCHOLAR_ID, 89)) VAL2,
            R.CLASS VAL3
        FROM REPORT_OSH1 R
        JOIN VALL V592 ON V592.OBJ_ID = R.CLASS_ID
          AND V592.PARAM_ID = 592
          AND V592.IS_DEL = 0
          AND V592.LISTVAL_ID < 198
        WHERE (:STAGE_NUM = 3 AND R.STAGE_LISTVAL_ID = 36)
           OR (:STAGE_NUM = 4 AND R.STAGE_LISTVAL_ID = 37)
           OR (:STAGE_NUM = 5 AND R.STAGE_LISTVAL_ID = 38)
           OR (:STAGE_NUM = 6 AND R.STAGE_LISTVAL_ID = 39)
           OR (:STAGE_NUM = 7 AND R.STAGE_LISTVAL_ID = 40)
           OR (:STAGE_NUM = 8 AND R.STAGE_LISTVAL_ID IN (41, 42, 43, 44, 45))
           OR (:STAGE_NUM = 9 AND R.STAGE_LISTVAL_ID IN (46, 47, 48))
           OR (:STAGE_NUM = 10 AND R.STAGE_LISTVAL_ID BETWEEN 36 AND 48)
        ORDER BY 1
        INTO :VAL1, :VAL2, :VAL3
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OSH1_1101 (
    I$OBJ_ID BIGINT)
RETURNS (
    V VARCHAR(3))
AS
DECLARE VARIABLE X INTEGER;
BEGIN
    X = 0;

    SELECT COUNT(*)
    FROM VALL VL
    WHERE VL.OBJ_ID = :I$OBJ_ID
      AND VL.PARAM_ID = 32
      AND VL.LISTVAL_ID = 4
    INTO :X;

    IF (X = 0) THEN
    BEGIN
        V = '0';
    END
    ELSE
    BEGIN
        V = '1';
    END

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OSH1_1201 (
    I$OBJ_ID BIGINT,
    I$N INTEGER)
RETURNS (
    VAL VARCHAR(10))
AS
DECLARE VARIABLE CLASS_ID BIGINT;
DECLARE VARIABLE V INTEGER;
DECLARE VARIABLE X INTEGER;
BEGIN
    VAL = '0';

    V = 0;

    FOR SELECT R.STREAM_ID
        FROM REPORT_OSH1 R
        INNER JOIN VALL V708 ON V708.OBJ_ID = R.STREAM_ID
        WHERE V708.PARAM_ID = 708
          AND V708.IS_DEL = 0
          AND V708.LISTVAL_ID = 2
        INTO :CLASS_ID
    DO
    BEGIN
        IF (I$N = 1) THEN
        BEGIN
            VAL = '1';
        END

        IF (I$N = 2) THEN
        BEGIN
            X = 0;

            SELECT COUNT(1)
            FROM REPORT_OSH1 R
            WHERE R.STREAM_ID = :CLASS_ID
            INTO :X;

            V = V + X;
        END
    END

    IF (I$N = 2) THEN
    BEGIN
        VAL = V;
    END

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OSH1_1201DTL (
    I$OBJ_ID BIGINT NOT NULL,
    STAGE_NUM SMALLINT)
RETURNS (
    VAL1 VARCHAR(250),
    VAL2 VARCHAR(250),
    VAL3 VARCHAR(250))
AS
BEGIN
    FOR
        SELECT
            (SELECT CAPTION FROM OBJECT_CAPTION_GET(SCHOLAR_ID)) VAL1,
            (SELECT D FROM VAL_GET(SCHOLAR_ID, 89)) VAL2,
            (SELECT CAPTION FROM OBJECT_CAPTION_GET
                ((SELECT PARENT_ID
                 FROM LINKS
                 WHERE LINK_ID =
                     (SELECT MAX(L.LINK_ID)
                      FROM LINKS L
                      WHERE L.OBJ_ID = SCHOLAR_ID
                        AND L.PARENT_TYPE_ID IN (9,10,81,82,83)
                        AND l.DATE_DEL IS NULL
                     )
                ))
            ) VAL3
        FROM (
            SELECT R.SCHOLAR_ID
            FROM REPORT_OSH1 R
            INNER JOIN VALL V708 ON V708.OBJ_ID = R.STREAM_ID
            WHERE V708.PARAM_ID = 708
              AND V708.IS_DEL = 0
              AND V708.LISTVAL_ID = 2
        ) ORDER BY VAL1
        INTO :VAL1, :VAL2, :VAL3
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OSH1_1301 (
    I$OBJ_ID BIGINT,
    I$N INTEGER)
RETURNS (
    V INTEGER)
AS
DECLARE VARIABLE BUILDING_ID BIGINT;
DECLARE VARIABLE X INTEGER;
BEGIN
    V = 0;

    FOR SELECT L16.OBJ_ID
        FROM LINKS L73
        INNER JOIN LINKS L16 ON L16.PARENT_ID = L73.OBJ_ID
        WHERE L73.PARENT_ID = :I$OBJ_ID
          AND L73.OBJ_TYPE_ID = 73
          AND L73.DATE_DEL IS NULL
          AND L16.OBJ_TYPE_ID = 16
          AND L16.DATE_DEL IS NULL
        INTO :BUILDING_ID
    DO
    BEGIN
        IF (I$N = 1) THEN
            V = V + 1;
        IF (I$N = 2) THEN
        BEGIN
            X = 0;

            SELECT VAL
            FROM VALF
            WHERE PARAM_ID = 496
              AND OBJ_ID = :BUILDING_ID
              AND IS_DEL = 0
            INTO :X;

            V = V + X;
        END
        IF (I$N = 3) THEN
        BEGIN
            X = 0;

            SELECT VAL
            FROM VALI
            WHERE PARAM_ID = 501
              AND OBJ_ID = :BUILDING_ID
              AND IS_DEL = 0
            INTO :X;

            V = V + X;
        END
        IF (I$N = 4) THEN
        BEGIN
            X = 0;

            SELECT VAL
            FROM VALF
            WHERE PARAM_ID = 499
              AND OBJ_ID = :BUILDING_ID
              AND IS_DEL = 0
            INTO :X;

            V = V + X;
        END
        IF (I$N = 5) THEN
        BEGIN
            X = 0;

            SELECT COUNT(*)
            FROM LINKS L61
            INNER JOIN VALL V526 ON V526.OBJ_ID = L61.OBJ_ID
            WHERE L61.PARENT_ID = :BUILDING_ID
              AND L61.OBJ_TYPE_ID = 61
              AND L61.DATE_DEL IS NULL
              AND V526.PARAM_ID = 526
              AND V526.IS_DEL = 0
              AND V526.LISTVAL_ID = 1147
            INTO :X;

            V = V + X;
        END
        IF (I$N = 6) THEN
        BEGIN
            X = 0;

            SELECT COALESCE(SUM(V532.VAL), 0)
            FROM LINKS L61
            INNER JOIN VALL V526 ON V526.OBJ_ID = L61.OBJ_ID
            INNER JOIN VALI V532 ON V532.OBJ_ID = L61.OBJ_ID
            WHERE L61.PARENT_ID = :BUILDING_ID
              AND L61.OBJ_TYPE_ID = 61
              AND L61.DATE_DEL IS NULL
              AND V526.PARAM_ID = 526
              AND V526.IS_DEL = 0
              AND V526.LISTVAL_ID = 1147
              AND V532.PARAM_ID = 532
              AND V532.IS_DEL = 0
            INTO :X;

            V = V + X;
        END
        IF (I$N = 16) THEN
        BEGIN
            X = 0;

            SELECT SUM(V532.VAL)
            FROM LINKS L61
            INNER JOIN VALL V526 ON V526.OBJ_ID = L61.OBJ_ID
            INNER JOIN VALI V532 ON V532.OBJ_ID = L61.OBJ_ID
            WHERE L61.PARENT_ID = :BUILDING_ID
              AND L61.OBJ_TYPE_ID = 61
              AND L61.DATE_DEL IS NULL
              AND V526.PARAM_ID = 526
              AND V526.IS_DEL = 0
              AND V526.LISTVAL_ID IN (1155, 1156, 1157, 1158)
              AND V532.PARAM_ID = 532
              AND V532.IS_DEL = 0
            INTO :X;

            V = V + X;
        END

    END

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OSH1_1301DTL (
    I$OBJ_ID BIGINT NOT NULL,
    STAGE_NUM SMALLINT NOT NULL,
    I$DT DATE = CURRENT_DATE)
RETURNS (
    VAL1 VARCHAR(250),
    VAL2 VARCHAR(250),
    VAL3 VARCHAR(250),
    NAME VARCHAR(250))
AS
BEGIN
    STAGE_NUM = :STAGE_NUM + 1;
    IF (:STAGE_NUM = 1) THEN
        FOR
            SELECT (SELECT CAPTION FROM OBJECT_CAPTION_GET(L16.OBJ_ID))
            FROM LINKS L73
            INNER JOIN LINKS L16 ON L16.PARENT_ID = L73.OBJ_ID
            WHERE L73.PARENT_ID = :I$OBJ_ID
              AND L73.OBJ_TYPE_ID = 73
              AND L73.DATE_DEL IS NULL
              AND L16.OBJ_TYPE_ID = 16
              AND L16.DATE_DEL IS NULL
            INTO :NAME
        DO
        BEGIN
            SUSPEND;
        END
    IF (:STAGE_NUM = 5) THEN
        FOR
            SELECT (SELECT CAPTION FROM OBJECT_CAPTION_GET(L61.OBJ_ID))
            FROM LINKS L61
            INNER JOIN VALL V526 ON V526.OBJ_ID = L61.OBJ_ID
            WHERE L61.OBJ_TYPE_ID = 61
              AND L61.DATE_DEL IS NULL
              AND V526.PARAM_ID = 526
              AND V526.IS_DEL = 0
              AND V526.LISTVAL_ID = 1147
              AND L61.PARENT_ID IN (
                SELECT L16.OBJ_ID
                FROM LINKS L73
                INNER JOIN LINKS L16 ON L16.PARENT_ID = L73.OBJ_ID
                WHERE L73.PARENT_ID = :I$OBJ_ID
                  AND L73.OBJ_TYPE_ID = 73
                  AND L73.DATE_DEL IS NULL
                  AND L16.OBJ_TYPE_ID = 16
                  AND L16.DATE_DEL IS NULL
                )
            INTO :NAME
        DO
        BEGIN
            SUSPEND;
        END
    IF (:STAGE_NUM IN (18, 19)) THEN
        FOR
            SELECT
                (SELECT CAPTION FROM OBJECT_CAPTION_GET(SCHOLAR_ID)) VAL1,
                (SELECT D FROM VAL_GET(SCHOLAR_ID, 89)) VAL2,
                (SELECT CAPTION FROM OBJECT_CAPTION_GET
                    ((SELECT PARENT_ID
                     FROM LINKS
                     WHERE LINK_ID =
                         (SELECT MAX(L.LINK_ID)
                          FROM LINKS L
                          WHERE L.OBJ_ID = SCHOLAR_ID
                            AND L.PARENT_TYPE_ID IN (9,10,81,82,83)
                            AND l.DATE_DEL IS NULL
                         )
                    ))
                ) VAL3
            FROM (
                SELECT L10.OBJ_ID SCHOLAR_ID
                FROM LINKS L7
                INNER JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID
                INNER JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID
                INNER JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID
                INNER JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID
                INNER JOIN VALL V187 ON V187.OBJ_ID = L10.OBJ_ID
                WHERE L7.PARENT_ID = :I$OBJ_ID
                  AND :I$DT = CURRENT_DATE
                  AND L7.OBJ_TYPE_ID = 7
                  AND L7.DATE_DEL IS NULL
                  AND L8.OBJ_TYPE_ID = 8
                  AND L8.DATE_DEL IS NULL
                  AND V49.PARAM_ID = 49
                  AND V49.IS_DEL = 0
                  AND V49.LISTVAL_ID >= 36
                  AND V49.LISTVAL_ID <= 48
                  AND L9.OBJ_TYPE_ID = 9
                  AND L9.DATE_DEL IS NULL
                  AND L10.OBJ_TYPE_ID = 10
                  AND L10.DATE_DEL IS NULL
                  AND V187.PARAM_ID = 187
                  AND V187.IS_DEL = 0
                  AND (V187.LISTVAL_ID IN (475, 1411)
                    OR (:STAGE_NUM = 18 AND V187.LISTVAL_ID = 474))

                UNION
                SELECT R.SCHOLAR_ID
                FROM REPORT_OSH1 R
                INNER JOIN VALL V187 ON V187.OBJ_ID = R.SCHOLAR_ID
                WHERE :I$DT <> CURRENT_DATE
                  AND R.STAGE_LISTVAL_ID >= 36
                  AND R.STAGE_LISTVAL_ID <= 48
                  AND V187.PARAM_ID = 187
                  AND V187.IS_DEL = 0
                  AND (V187.LISTVAL_ID IN (475, 1411)
                    OR (:STAGE_NUM = 18 AND V187.LISTVAL_ID = 474))
            ) ORDER BY VAL1
        INTO :VAL1, :VAL2, :VAL3
    DO
    BEGIN
        SUSPEND;
    END
    IF (:STAGE_NUM IN (23, 25)) THEN
        FOR
            SELECT (SELECT CAPTION FROM OBJECT_CAPTION_GET(L16.OBJ_ID))
            FROM LINKS L73
            INNER JOIN LINKS L16 ON L16.PARENT_ID = L73.OBJ_ID
            INNER JOIN VALL V488 ON V488.OBJ_ID = L16.OBJ_ID
            WHERE L73.PARENT_ID = :I$OBJ_ID
              AND L73.OBJ_TYPE_ID = 73
              AND L73.DATE_DEL IS NULL
              AND L16.OBJ_TYPE_ID = 16
              AND L16.DATE_DEL IS NULL
              AND V488.PARAM_ID = 488
              AND V488.IS_DEL = 0
              AND ((:STAGE_NUM = 23 AND V488.LISTVAL_ID = 1103)
                OR (:STAGE_NUM = 25 AND V488.LISTVAL_ID = 1104))
            INTO :NAME
        DO
        BEGIN
            SUSPEND;
        END
    IF (:STAGE_NUM = 34) THEN
        FOR
            SELECT DISTINCT (SELECT CAPTION FROM OBJECT_CAPTION_GET(L61.OBJ_ID))
            FROM LINKS L73
            INNER JOIN LINKS L16 ON L16.PARENT_ID = L73.OBJ_ID
            INNER JOIN LINKS L61 ON L61.PARENT_ID = L16.OBJ_ID
            INNER JOIN LINKS L51 ON L51.PARENT_ID = L61.OBJ_ID
            WHERE L73.PARENT_ID = :I$OBJ_ID
              AND L73.OBJ_TYPE_ID = 73
              AND L73.DATE_DEL IS NULL
              AND L16.OBJ_TYPE_ID = 16
              AND L16.DATE_DEL IS NULL
              AND L61.OBJ_TYPE_ID = 61
              AND L61.DATE_DEL IS NULL
              AND L51.OBJ_TYPE_ID = 51
              AND L51.DATE_DEL IS NULL
              AND L51.OBJ_ID IN (191, 5518, 5519)
            INTO :NAME
        DO
        BEGIN
            SUSPEND;
        END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OSH1_1308 (
    I$OBJ_ID BIGINT,
    I$ROOM_TYPE1 BIGINT,
    I$ROOM_TYPE2 BIGINT)
RETURNS (
    V VARCHAR(3))
AS
DECLARE VARIABLE X INTEGER;
BEGIN

    X = 0;

    SELECT COUNT(*)
    FROM LINKS L73
    INNER JOIN LINKS L16 ON L16.PARENT_ID = L73.OBJ_ID
    INNER JOIN LINKS L61 ON L61.PARENT_ID = L16.OBJ_ID
    INNER JOIN VALL V526 ON V526.OBJ_ID = L61.OBJ_ID
    WHERE L73.PARENT_ID = :I$OBJ_ID
      AND L73.OBJ_TYPE_ID = 73
      AND L73.DATE_DEL IS NULL
      AND L16.OBJ_TYPE_ID = 16
      AND L16.DATE_DEL IS NULL
      AND L61.OBJ_TYPE_ID = 61
      AND L61.DATE_DEL IS NULL
      AND V526.PARAM_ID = 526
      AND V526.IS_DEL = 0
      AND V526.LISTVAL_ID IN (:I$ROOM_TYPE1, :I$ROOM_TYPE2)
    INTO :X;

    IF (X = 0) THEN
    BEGIN
        V = '0';
    END
    ELSE
    BEGIN
        V = '1';
    END

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OSH1_1318 (
    I$OBJ_ID BIGINT,
    I$1 BIGINT,
    I$2 BIGINT,
    I$3 BIGINT,
    I$DT DATE = CURRENT_DATE)
RETURNS (
    V INTEGER)
AS
BEGIN
    IF (:I$DT >= CURRENT_DATE) THEN
    BEGIN
        SELECT COUNT(*)
        FROM LINKS L7
        INNER JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID
        INNER JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID
        INNER JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID
        INNER JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID
        INNER JOIN VALL V187 ON V187.OBJ_ID = L10.OBJ_ID
        WHERE L7.PARENT_ID = :I$OBJ_ID
          AND L7.OBJ_TYPE_ID = 7
          AND L7.DATE_DEL IS NULL
          AND L8.OBJ_TYPE_ID = 8
          AND L8.DATE_DEL IS NULL
          AND V49.PARAM_ID = 49
          AND V49.IS_DEL = 0
          AND V49.LISTVAL_ID >= 36
          AND V49.LISTVAL_ID <= 48
          AND L9.OBJ_TYPE_ID = 9
          AND L9.DATE_DEL IS NULL
          AND L10.OBJ_TYPE_ID = 10
          AND L10.DATE_DEL IS NULL
          AND V187.PARAM_ID = 187
          AND V187.IS_DEL = 0
          AND V187.LISTVAL_ID IN (:I$1, :I$2, :I$3)
        INTO :V;
    END
    ELSE
    BEGIN
        SELECT COUNT(1)
        FROM REPORT_OSH1 R
        INNER JOIN VALL V187 ON V187.OBJ_ID = R.SCHOLAR_ID
        WHERE R.STAGE_LISTVAL_ID >= 36
          AND R.STAGE_LISTVAL_ID <= 48
          AND V187.PARAM_ID = 187
          AND V187.IS_DEL = 0
          AND V187.LISTVAL_ID IN (:I$1, :I$2, :I$3)
        INTO :V;
    END

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OSH1_1320 (
    I$OBJ_ID BIGINT)
RETURNS (
    V INTEGER)
AS
BEGIN
    SELECT SUM(V648.VAL)
    FROM LINKS L105
    INNER JOIN LINKS L107 ON L107.PARENT_ID = L105.OBJ_ID
    INNER JOIN VALI V648 ON V648.OBJ_ID = L107.OBJ_ID
    WHERE L105.PARENT_ID = :I$OBJ_ID
      AND L105.OBJ_TYPE_ID = 105
      AND L105.DATE_DEL IS NULL
      AND L107.OBJ_TYPE_ID = 107
      AND L107.DATE_DEL IS NULL
      AND V648.PARAM_ID = 648
      AND V648.IS_DEL = 0
    INTO :V;

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OSH1_1321 (
    I$OBJ_ID BIGINT)
RETURNS (
    V INTEGER)
AS
BEGIN
    SELECT SUM(V648.VAL)
    FROM LINKS L105
    INNER JOIN LINKS L107 ON L107.PARENT_ID = L105.OBJ_ID
    INNER JOIN VALI V648 ON V648.OBJ_ID = L107.OBJ_ID
    INNER JOIN VALL V646 ON V646.OBJ_ID = L107.OBJ_ID
    WHERE L105.PARENT_ID = :I$OBJ_ID
      AND L105.OBJ_TYPE_ID = 105
      AND L105.DATE_DEL IS NULL
      AND L107.OBJ_TYPE_ID = 107
      AND L107.DATE_DEL IS NULL
      AND V648.PARAM_ID = 648
      AND V648.IS_DEL = 0
      AND V646.PARAM_ID = 646
      AND V646.IS_DEL = 0
      AND V646.LISTVAL_ID = 2057
    INTO :V;

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OSH1_1322 (
    I$OBJ_ID BIGINT,
    I$BUILDING_SOST BIGINT)
RETURNS (
    V VARCHAR(3),
    X INTEGER)
AS
BEGIN

    X = 0;

    SELECT COUNT(*)
    FROM LINKS L73
    INNER JOIN LINKS L16 ON L16.PARENT_ID = L73.OBJ_ID
    INNER JOIN VALL V488 ON V488.OBJ_ID = L16.OBJ_ID
    WHERE L73.PARENT_ID = :I$OBJ_ID
      AND L73.OBJ_TYPE_ID = 73
      AND L73.DATE_DEL IS NULL
      AND L16.OBJ_TYPE_ID = 16
      AND L16.DATE_DEL IS NULL
      AND V488.PARAM_ID = 488
      AND V488.IS_DEL = 0
      AND V488.LISTVAL_ID = :I$BUILDING_SOST
    INTO :X;

    IF (X = 0) THEN
    BEGIN
        V = '0';
    END
    ELSE
    BEGIN
        V = '1';
    END

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OSH1_1326 (
    I$OBJ_ID BIGINT)
RETURNS (
    V VARCHAR(3),
    X INTEGER)
AS
BEGIN

    X = 0;

    SELECT COUNT(*)
    FROM LINKS L73
    INNER JOIN LINKS L16 ON L16.PARENT_ID = L73.OBJ_ID
    INNER JOIN VALL V509 ON V509.OBJ_ID = L16.OBJ_ID
    INNER JOIN VALL V510 ON V510.OBJ_ID = L16.OBJ_ID
    INNER JOIN VALL V511 ON V511.OBJ_ID = L16.OBJ_ID
    WHERE L73.PARENT_ID = :I$OBJ_ID
      AND L73.OBJ_TYPE_ID = 73
      AND L73.DATE_DEL IS NULL
      AND L16.OBJ_TYPE_ID = 16
      AND L16.DATE_DEL IS NULL
      AND V509.PARAM_ID = 509
      AND V509.IS_DEL = 0
      AND V509.LISTVAL_ID IN (1118,1119,1120)
      AND V510.PARAM_ID = 510
      AND V510.IS_DEL = 0
      AND V510.LISTVAL_ID = 4
      AND V511.PARAM_ID = 511
      AND V511.IS_DEL = 0
      AND V511.LISTVAL_ID = 4
    INTO :X;

    IF (X = 0) THEN
    BEGIN
        V = '0';
    END
    ELSE
    BEGIN
        V = '1';
    END

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OSH1_1327 (
    I$OBJ_ID BIGINT)
RETURNS (
    V VARCHAR(3),
    X INTEGER)
AS
BEGIN

    X = 0;

    SELECT COUNT(*)
    FROM LINKS L73
    INNER JOIN LINKS L16 ON L16.PARENT_ID = L73.OBJ_ID
    INNER JOIN VALL V510 ON V510.OBJ_ID = L16.OBJ_ID
    WHERE L73.PARENT_ID = :I$OBJ_ID
      AND L73.OBJ_TYPE_ID = 73
      AND L73.DATE_DEL IS NULL
      AND L16.OBJ_TYPE_ID = 16
      AND L16.DATE_DEL IS NULL
      AND V510.PARAM_ID = 510
      AND V510.IS_DEL = 0
      AND V510.LISTVAL_ID = 4
    INTO :X;

    IF (X = 0) THEN
    BEGIN
        V = '0';
    END
    ELSE
    BEGIN
        V = '1';
    END

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OSH1_1328 (
    I$OBJ_ID BIGINT)
RETURNS (
    V VARCHAR(3),
    X INTEGER)
AS
BEGIN

    X = 0;

    SELECT COUNT(*)
    FROM LINKS L73
    INNER JOIN LINKS L16 ON L16.PARENT_ID = L73.OBJ_ID
    INNER JOIN VALL V509 ON V509.OBJ_ID = L16.OBJ_ID
    WHERE L73.PARENT_ID = :I$OBJ_ID
      AND L73.OBJ_TYPE_ID = 73
      AND L73.DATE_DEL IS NULL
      AND L16.OBJ_TYPE_ID = 16
      AND L16.DATE_DEL IS NULL
      AND V509.PARAM_ID = 509
      AND V509.IS_DEL = 0
      AND V509.LISTVAL_ID IN (1118,1119,1120)
    INTO :X;

    IF (X = 0) THEN
    BEGIN
        V = '0';
    END
    ELSE
    BEGIN
        V = '1';
    END

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OSH1_1329 (
    I$OBJ_ID BIGINT)
RETURNS (
    V VARCHAR(3),
    X INTEGER)
AS
BEGIN

    X = 0;

    SELECT COUNT(*)
    FROM LINKS L73
    INNER JOIN LINKS L16 ON L16.PARENT_ID = L73.OBJ_ID
    INNER JOIN VALL V511 ON V511.OBJ_ID = L16.OBJ_ID
    WHERE L73.PARENT_ID = :I$OBJ_ID
      AND L73.OBJ_TYPE_ID = 73
      AND L73.DATE_DEL IS NULL
      AND L16.OBJ_TYPE_ID = 16
      AND L16.DATE_DEL IS NULL
      AND V511.PARAM_ID = 511
      AND V511.IS_DEL = 0
      AND V511.LISTVAL_ID = 4
    INTO :X;

    IF (X = 0) THEN
    BEGIN
        V = '0';
    END
    ELSE
    BEGIN
        V = '1';
    END

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OSH1_1334 (
    I$OBJ_ID BIGINT,
    I$N INTEGER = NULL)
RETURNS (
    V INTEGER)
AS
BEGIN
    SELECT COUNT(1)
    FROM R_SPB_INF_OU_2(:I$OBJ_ID)
    INTO :V;
    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OSH1_1336 (
    I$OBJ_ID BIGINT,
    I$N SMALLINT = 36)
RETURNS (
    V INTEGER)
AS
DECLARE VARIABLE V$YEAR VARCHAR(4);
BEGIN
    V$YEAR = EXTRACT(YEAR FROM CURRENT_TIMESTAMP);

    SELECT COUNT(1)
    FROM LINKS L23
    JOIN LINKS L95 ON L95.PARENT_ID = L23.OBJ_ID
      AND L95.OBJ_TYPE_ID = 95
      AND L95.DATE_DEL IS NULL
    JOIN VALL V626 ON V626.OBJ_ID = L95.OBJ_ID
      AND V626.PARAM_ID = 626
      AND V626.IS_DEL = 0
      AND V626.LISTVAL_ID = 1799
    JOIN VALL V604 ON V604.OBJ_ID = L95.OBJ_ID
      AND V604.PARAM_ID = 604
      AND V604.IS_DEL = 0
      -- PC only
      AND V604.LISTVAL_ID < 1810
      AND V604.LISTVAL_ID <> 1803
    JOIN LINKS L114 ON L114.PARENT_ID = L95.OBJ_ID
      AND L114.OBJ_TYPE_ID = 114
      AND L114.DATE_DEL IS NULL
    LEFT JOIN VALS V682 ON V682.OBJ_ID = L114.OBJ_ID
      AND V682.PARAM_ID = 682
      AND V682.IS_DEL = 0
    WHERE L23.PARENT_ID = :I$OBJ_ID
      AND L23.OBJ_TYPE_ID = 23
      AND L23.DATE_DEL IS NULL
      AND ((:I$N = 36)
        OR (:I$N = 37 AND V682.VAL LIKE :V$YEAR)
        OR (:I$N = 38 AND V604.LISTVAL_ID > 1803)
        OR ((:I$N = 39 OR (:I$N = 40 AND V604.LISTVAL_ID > 1803)) AND COALESCE((
          -- в классе c ЛВС
          SELECT FIRST 1 IIF(V880.LISTVAL_ID = 2, 1, 0)
          FROM LINKS L128_114
          JOIN VALL V880 ON V880.OBJ_ID = L128_114.PARENT_ID
            AND V880.IS_DEL = 0
            AND V880.PARAM_ID = 880
          WHERE L128_114.OBJ_ID = L114.OBJ_ID
            AND L128_114.PARENT_TYPE_ID = 128
            AND L128_114.DATE_DEL IS NULL
            ), (
          -- наличие ЛВС
          SELECT FIRST 1 1
          FROM LINKS L116
          WHERE L116.PARENT_ID = :I$OBJ_ID
            AND L116.OBJ_TYPE_ID = 116
            AND L116.DATE_DEL IS NULL
          )) = 1)
        OR ((:I$N = 41 OR (:I$N = 42 AND V604.LISTVAL_ID > 1803)) AND V604.LISTVAL_ID NOT IN (1802, 1806, 1809))
        OR ((:I$N = 51 OR (:I$N = 52 AND V604.LISTVAL_ID > 1803)) AND COALESCE((
          -- в классе c Internet
          SELECT FIRST 1 IIF(V881.LISTVAL_ID = 2, 1, 0)
          FROM LINKS L128_114
          JOIN VALL V881 ON V881.OBJ_ID = L128_114.PARENT_ID
            AND V881.IS_DEL = 0
            AND V881.PARAM_ID = 881
          WHERE L128_114.OBJ_ID = L114.OBJ_ID
            AND L128_114.PARENT_TYPE_ID = 128
            AND L128_114.DATE_DEL IS NULL
            ), (
          -- наличие ЛВС c Internet
          SELECT FIRST 1 IIF(V697.LISTVAL_ID = 2, 1, 0)
          FROM LINKS L116
          JOIN VALL V697 ON V697.OBJ_ID = L116.OBJ_ID
            AND V697.IS_DEL = 0
            AND V697.PARAM_ID = 697
          WHERE L116.PARENT_ID = :I$OBJ_ID
            AND L116.OBJ_TYPE_ID = 116
            AND L116.DATE_DEL IS NULL
          )) = 1))
    INTO :V;

    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OSH1_1340 (
    I$OBJ_ID BIGINT,
    I$N INTEGER)
RETURNS (
    V VARCHAR(3))
AS
DECLARE VARIABLE NET_ID BIGINT = 0;
DECLARE VARIABLE NET_TYPE_ID BIGINT = 0;
DECLARE VARIABLE NET_SPEED INTEGER = 0;
BEGIN
    V = '0';

    FOR SELECT L116.OBJ_ID
        FROM LINKS L116
        INNER JOIN VALL V697 ON V697.OBJ_ID = L116.OBJ_ID
        WHERE L116.PARENT_ID = :I$OBJ_ID
          AND L116.OBJ_TYPE_ID = 116
          AND L116.DATE_DEL IS NULL
          AND V697.PARAM_ID = 697
          AND V697.IS_DEL = 0
          AND V697.LISTVAL_ID = 2
        INTO :NET_ID
    DO
    BEGIN
        SELECT FIRST 1 V700.LISTVAL_ID
        FROM VALL V700
        WHERE V700.OBJ_ID = :NET_ID
          AND V700.PARAM_ID = 700
          AND V700.IS_DEL = 0
        INTO :NET_TYPE_ID;

        SELECT FIRST 1 V701.VAL
        FROM VALI V701
        WHERE V701.OBJ_ID = :NET_ID
          AND V701.PARAM_ID = 701
          AND V701.IS_DEL = 0
        INTO :NET_SPEED;

        IF (I$N = 43) THEN
        BEGIN
            V = '1';
        END
        ELSE
        IF ((I$N = 44) AND (NET_TYPE_ID IN (2183, 2188, 2189, 2190))) THEN
        BEGIN
            V = '1';
        END
        IF ((I$N = 45) AND (NET_TYPE_ID IN (2184, 2185, 2186, 2187)))  THEN
        BEGIN
            V = '1';
        END
        IF ((I$N = 46) AND (NET_TYPE_ID = 2191))  THEN
        BEGIN
            V = '1';
        END

        NET_SPEED = COALESCE(:NET_SPEED, 0);

        IF ((I$N = 47 AND NET_SPEED < 256)
         OR (I$N = 48 AND NET_SPEED < 1024)
         OR (I$N = 49 AND NET_SPEED < 5*1024)
         OR (I$N = 50 AND NET_SPEED >= 5*1024)) THEN
        BEGIN
            V = '1';
        END
    END
    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OSH1_1346 (
    I$OBJ_ID BIGINT,
    I$N INTEGER)
RETURNS (
    V VARCHAR(3))
AS
BEGIN
    V = '0';


    IF (I$N = 53) THEN
    BEGIN
        SELECT FIRST 1 '1'
        FROM VALS
        WHERE OBJ_ID = :I$OBJ_ID
          AND PARAM_ID = 35
          AND IS_DEL = 0
          AND VAL > ''
        INTO :V;
    END

    IF (I$N = 54) THEN
    BEGIN
        SELECT FIRST 1 '1'
        FROM VALS
        WHERE OBJ_ID = :I$OBJ_ID
          AND PARAM_ID = 36
          AND IS_DEL = 0
          AND VAL > ''
        INTO :V;
    END

    IF (I$N = 55) THEN
    BEGIN
        SELECT FIRST 1 '1'
        FROM VALS
        WHERE OBJ_ID = :I$OBJ_ID
          AND PARAM_ID = 712
          AND IS_DEL = 0
          AND VAL > ''
        INTO :V;
    END

    IF (I$N = 56) THEN
    BEGIN
        SELECT FIRST 1 '1'
        FROM VALI
        WHERE OBJ_ID = :I$OBJ_ID
          AND PARAM_ID = 719
          AND IS_DEL = 0
          AND VAL > 0
        INTO :V;
    END

    IF (I$N = 57) THEN
    BEGIN
        V = NULL;
    END

    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OSH1_1401 (
    I$OBJ_ID BIGINT,
    I$SECTION_TYPE_ID BIGINT)
RETURNS (
    V3 INTEGER,
    V4 INTEGER,
    V5 INTEGER,
    V6 INTEGER)
AS
BEGIN
    SELECT
        COUNT(DISTINCT(R.STREAM_ID)),
        COUNT(DISTINCT(IIF(V708.LISTVAL_ID = 2, R.STREAM_ID, NULL))),
        SUM(1),
        SUM(IIF(V708.LISTVAL_ID = 2, 1, 0))
    FROM REPORT_OSH1 R
    INNER JOIN VALL V369 ON V369.OBJ_ID = R.STREAM_ID
    INNER JOIN VALL V594 ON V594.OBJ_ID = R.STREAM_ID
    LEFT JOIN VALL V708 ON V708.PARAM_ID = 708 AND V708.OBJ_ID = R.STREAM_ID AND V708.IS_DEL = 0
    WHERE V594.PARAM_ID = 594
      AND V594.IS_DEL = 0
      AND V594.LISTVAL_ID = :I$SECTION_TYPE_ID
      AND V369.PARAM_ID = 369
      AND V369.IS_DEL = 0
      AND V369.LISTVAL_ID IN (944, 1245, 1249)
    INTO :V3, :V4, :V5, :V6;

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OSH1_1401DTL (
    I$OBJ_ID BIGINT NOT NULL,
    STAGE_NUM SMALLINT NOT NULL,
    STAGE_NUM2 SMALLINT NOT NULL)
RETURNS (
    VAL1 VARCHAR(250),
    VAL2 VARCHAR(250),
    VAL3 VARCHAR(250),
    NAME VARCHAR(250))
AS
BEGIN
    STAGE_NUM2 = :STAGE_NUM2 + 1;
    IF (:STAGE_NUM < 6) THEN
        STAGE_NUM = :STAGE_NUM + 1346;
    ELSE
        STAGE_NUM = :STAGE_NUM + 1;
    IF (:STAGE_NUM2 < 5) THEN
        FOR
            SELECT (SELECT CAPTION FROM OBJECT_CAPTION_GET(R.STREAM_ID))
            FROM REPORT_OSH1 R
            INNER JOIN VALL V369 ON V369.OBJ_ID = R.STREAM_ID
            INNER JOIN VALL V594 ON V594.OBJ_ID = R.STREAM_ID
            WHERE V594.PARAM_ID = 594
              AND V594.IS_DEL = 0
              AND ((:STAGE_NUM = 7 AND V594.LISTVAL_ID BETWEEN 1346 AND 1351)
                  OR V594.LISTVAL_ID = :STAGE_NUM)
              AND V369.PARAM_ID = 369
              AND V369.IS_DEL = 0
              AND V369.LISTVAL_ID IN (944, 1245, 1249)
              AND (:STAGE_NUM2 = 3 OR R.STREAM_ID IN (
                SELECT V708.OBJ_ID
                FROM VALL V708
                WHERE V708.LISTVAL_ID = 2
                  AND V708.PARAM_ID = 708
                  AND V708.IS_DEL = 0))
            INTO :NAME
        DO
        BEGIN
            SUSPEND;
        END
    ELSE
        FOR
            SELECT
                (SELECT CAPTION FROM OBJECT_CAPTION_GET(SCHOLAR_ID)) VAL1,
                (SELECT D FROM VAL_GET(SCHOLAR_ID, 89)) VAL2,
                (SELECT CAPTION FROM OBJECT_CAPTION_GET
                    ((SELECT PARENT_ID
                     FROM LINKS
                     WHERE LINK_ID =
                         (SELECT MAX(L.LINK_ID)
                          FROM LINKS L
                          WHERE L.OBJ_ID = SCHOLAR_ID
                            AND L.PARENT_TYPE_ID IN (9,10,81,82,83)
                            AND l.DATE_DEL IS NULL
                         )
                    ))
                ) VAL3
            FROM (
                SELECT DISTINCT R.SCHOLAR_ID, COUNT(1) CNT
                    FROM REPORT_OSH1 R
                    INNER JOIN VALL V369 ON V369.OBJ_ID = R.STREAM_ID
                    INNER JOIN VALL V594 ON V594.OBJ_ID = R.STREAM_ID
                    WHERE V594.PARAM_ID = 594
                      AND V594.IS_DEL = 0
                      AND ((:STAGE_NUM = 7 AND V594.LISTVAL_ID BETWEEN 1346 AND 1351)
                          OR V594.LISTVAL_ID = :STAGE_NUM)
                      AND V369.PARAM_ID = 369
                      AND V369.IS_DEL = 0
                      AND V369.LISTVAL_ID IN (944, 1245, 1249)
                      AND (:STAGE_NUM2 = 5 OR R.STREAM_ID IN (
                        SELECT V708.OBJ_ID
                        FROM VALL V708
                        WHERE V708.LISTVAL_ID = 2
                          AND V708.PARAM_ID = 708
                          AND V708.IS_DEL = 0))
                GROUP BY 1
            )
            WHERE :STAGE_NUM < 8 OR CNT > 1
            ORDER BY VAL1
            INTO :VAL1, :VAL2, :VAL3
        DO
        BEGIN
            SUSPEND;
        END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OSH1_1407 (
    I$OBJ_ID BIGINT)
RETURNS (
    V3 INTEGER,
    V4 INTEGER,
    V5 INTEGER,
    V6 INTEGER)
AS
BEGIN
    SELECT
        COUNT(DISTINCT(R.STREAM_ID)),
        COUNT(DISTINCT(IIF(V708.LISTVAL_ID = 2, R.STREAM_ID, NULL))),
        SUM(1),
        SUM(IIF(V708.LISTVAL_ID = 2, 1, 0))
    FROM REPORT_OSH1 R
    INNER JOIN VALL V369 ON V369.OBJ_ID = R.STREAM_ID
    INNER JOIN VALL V594 ON V594.OBJ_ID = R.STREAM_ID
    LEFT JOIN VALL V708 ON V708.PARAM_ID = 708 AND V708.OBJ_ID = R.STREAM_ID AND V708.IS_DEL = 0
    WHERE V594.PARAM_ID = 594
      AND V594.IS_DEL = 0
      AND V594.LISTVAL_ID IN (1346,1347,1348,1349,1350,1351)
      AND V369.PARAM_ID = 369
      AND V369.IS_DEL = 0
      AND V369.LISTVAL_ID IN (944, 1245, 1249)
    INTO :V3, :V4, :V5, :V6;

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OSH1_1408 (
    I$OBJ_ID BIGINT)
RETURNS (
    V5 INTEGER,
    V6 INTEGER)
AS
DECLARE VARIABLE X INTEGER;
BEGIN
    V5 = 0;
    V6 = 0;

    FOR SELECT COUNT(*)
        FROM REPORT_OSH1 R
        INNER JOIN VALL V369 ON V369.OBJ_ID = R.STREAM_ID
        INNER JOIN VALL V594 ON V594.OBJ_ID = R.STREAM_ID
        WHERE V594.PARAM_ID = 594
          AND V594.IS_DEL = 0
          AND V594.LISTVAL_ID IN (1346, 1347, 1348, 1349, 1350, 1351)
          AND V369.PARAM_ID = 369
          AND V369.IS_DEL = 0
          AND V369.LISTVAL_ID IN (944, 1245, 1249)
        GROUP BY R.SCHOLAR_ID
        INTO :X
    DO
    BEGIN
        IF (X > 1) THEN  V5 = V5 + 1;
    END

    FOR SELECT COUNT(*)
        FROM REPORT_OSH1 R
        INNER JOIN VALL V369 ON V369.OBJ_ID = R.STREAM_ID
        INNER JOIN VALL V594 ON V594.OBJ_ID = R.STREAM_ID
        INNER JOIN VALL V708 ON V708.OBJ_ID = R.STREAM_ID
        WHERE V594.PARAM_ID = 594
          AND V594.IS_DEL = 0
          AND V594.LISTVAL_ID IN (1346, 1347, 1348, 1349, 1350, 1351)
          AND V369.PARAM_ID = 369
          AND V369.IS_DEL = 0
          AND V369.LISTVAL_ID IN (944, 1245, 1249)
          AND V708.PARAM_ID = 708
          AND V708.IS_DEL = 0
          AND V708.LISTVAL_ID = 2
        GROUP BY R.SCHOLAR_ID
        INTO :X
    DO
    BEGIN
        IF (X > 1) THEN  V6 = V6 + 1;
    END

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OSH1_1501DTL (
    I$OBJ_ID BIGINT NOT NULL,
    STAGE_NUM SMALLINT NOT NULL,
    STAGE_NUM2 SMALLINT = NULL,
    I$DT DATE = CURRENT_DATE)
RETURNS (
    VAL1 VARCHAR(250),
    VAL2 VARCHAR(250),
    VAL3 VARCHAR(250))
AS
DECLARE VARIABLE DT1 DATE;
DECLARE VARIABLE DT2 DATE;
DECLARE VARIABLE IS_CURR_MOVE SMALLINT = 1;
BEGIN
    STAGE_NUM = :STAGE_NUM + 1;
    IF (:STAGE_NUM2 IS NOT NULL) THEN
    BEGIN
        STAGE_NUM2 = :STAGE_NUM2 - 1;
    END
    IS_CURR_MOVE = EXTRACT(YEAR FROM :I$DT) - 1;
    DT1 = IS_CURR_MOVE || '-09-20';
    IS_CURR_MOVE = EXTRACT(YEAR FROM :I$DT);
    DT2 = IS_CURR_MOVE || '-09-19';
    FOR
        SELECT
            (SELECT CAPTION FROM OBJECT_CAPTION_GET(SCHOLAR_ID)) VAL1,
            (SELECT D FROM VAL_GET(SCHOLAR_ID, 89)) VAL2,
            (SELECT CAPTION FROM OBJECT_CAPTION_GET
                ((SELECT PARENT_ID
                 FROM LINKS
                 WHERE LINK_ID =
                     (SELECT MAX(L.LINK_ID)
                      FROM LINKS L
                      WHERE L.OBJ_ID = SCHOLAR_ID
                        AND L.PARENT_TYPE_ID IN (9,10,81,82,83)
                        AND l.DATE_DEL IS NULL
                     )
                ))
            ) VAL3
        FROM (
            SELECT SCHOLAR_ID, STAGE_ID, CLASS_TYPE
            FROM (
                SELECT DISTINCT(L76.PARENT_ID) SCHOLAR_ID,
                       MAX(V436.LISTVAL_ID) STAGE_ID,
                       MAX(V1350.LISTVAL_ID) CLASS_TYPE,
                       MAXDATE
                FROM LINKS L76
                INNER JOIN VALD V433 ON V433.OBJ_ID = L76.OBJ_ID
                INNER JOIN VALL V432 ON V432.OBJ_ID = L76.OBJ_ID
                INNER JOIN VALL V436 ON V436.OBJ_ID = L76.OBJ_ID
                INNER JOIN (
                    SELECT MAX(V433.VAL) MAXDATE, LL76.PARENT_ID SCHOLAR_ID
                    FROM LINKS LL76
                    INNER JOIN VALD V433 ON V433.OBJ_ID = LL76.OBJ_ID
                    INNER JOIN VALL V432 ON V432.OBJ_ID = LL76.OBJ_ID
                    WHERE LL76.OBJ_TYPE_ID = 76
                      AND LL76.DATE_DEL IS NULL
                      AND V433.PARAM_ID = 433
                      AND V433.IS_DEL = 0
                      AND V433.VAL BETWEEN :DT1 AND :DT2
                      AND V432.PARAM_ID = 432
                      AND V432.IS_DEL = 0
                      AND V432.LISTVAL_ID IN (811, 812)
                      AND LL76.PARENT_ID IN (
                        SELECT SCHOLAR_ID
                        FROM (
                            SELECT L10.OBJ_ID SCHOLAR_ID, V105.LISTVAL_ID KUDA_ID, V107.LISTVAL_ID OU_VID_ID
                            FROM LINKS L7
                            INNER JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID
                            INNER JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID
                            INNER JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID
                            INNER JOIN VALL V105 ON V105.OBJ_ID = L10.OBJ_ID
                            LEFT JOIN VALL V107 ON V107.OBJ_ID = L10.OBJ_ID AND V107.PARAM_ID = 107 AND V107.IS_DEL = 0
                            WHERE L7.PARENT_ID = :I$OBJ_ID
                              AND ((L7.OBJ_TYPE_ID = 7 AND L8.OBJ_TYPE_ID = 8)
                                OR (L7.OBJ_TYPE_ID = 78 AND L8.OBJ_TYPE_ID = 83))
                              AND L7.DATE_DEL IS NULL
                              AND L8.DATE_DEL IS NULL
                              AND L9.OBJ_TYPE_ID = 9
                              AND L9.DATE_DEL IS NULL
                              AND L10.OBJ_TYPE_ID = 10
                              AND L10.DATE_DEL IS NULL
                              AND V105.PARAM_ID = 105
                              AND V105.IS_DEL = 0
                            UNION
                            SELECT L10.OBJ_ID SCHOLAR_ID, V105.LISTVAL_ID KUDA_ID, V107.LISTVAL_ID OU_VID_ID
                            FROM LINKS L78
                            INNER JOIN LINKS L81 ON L81.PARENT_ID = L78.OBJ_ID
                            INNER JOIN LINKS L10 ON L10.PARENT_ID = L81.OBJ_ID
                            INNER JOIN VALL V105 ON V105.OBJ_ID = L10.OBJ_ID
                            LEFT JOIN VALL V107 ON V107.OBJ_ID = L10.OBJ_ID AND V107.PARAM_ID = 107 AND V107.IS_DEL = 0
                            WHERE L78.PARENT_ID = :I$OBJ_ID
                              AND L78.OBJ_TYPE_ID = 78
                              AND L78.DATE_DEL IS NULL
                              AND L81.OBJ_TYPE_ID IN (81, 82)
                              AND L81.DATE_DEL IS NULL
                              AND L10.OBJ_TYPE_ID = 10
                              AND L10.DATE_DEL IS NULL
                              AND V105.PARAM_ID = 105
                              AND V105.IS_DEL = 0
                            )
                        WHERE :STAGE_NUM = 1
                          OR (:STAGE_NUM = 2 AND KUDA_ID IN (904, 905, 906, 907, 3143) AND (OU_VID_ID IS NULL
                              OR OU_VID_ID NOT IN (965, 966, 967, 979, 980, 985, 986, 1010, 1011, 1014, 1016, 2216, 2219, 2220, 2222, 2223, 2224, 2225)))
                          OR (:STAGE_NUM = 3 AND KUDA_ID IN (904, 905, 906, 907, 3143) AND OU_VID_ID IN (2216, 979, 980, 985, 986))
                          OR (:STAGE_NUM = 4 AND KUDA_ID IN (904, 905, 906, 907, 3143) AND OU_VID_ID IN (965, 966, 967))
                          OR (:STAGE_NUM = 5 AND KUDA_ID IN (904, 905, 906, 907, 3143) AND OU_VID_ID IN (1014, 1016))
                          OR (:STAGE_NUM = 6 AND KUDA_ID IN (904, 905, 906, 907, 3143) AND OU_VID_ID IN (1010, 1011))
                          OR (:STAGE_NUM = 9 AND KUDA_ID IN (914, 915))
                          OR (:STAGE_NUM =10 AND KUDA_ID = 910)
                          OR (:STAGE_NUM =11 AND KUDA_ID BETWEEN 904 AND 907 AND OU_VID_ID IN (2219, 2220, 2222, 2223, 2224, 2225))
                          OR (:STAGE_NUM =12 AND KUDA_ID = 908)
                          OR (:STAGE_NUM =13 AND KUDA_ID = 909)
                          OR (:STAGE_NUM =14 AND KUDA_ID = 916)
                          OR (:STAGE_NUM =15 AND KUDA_ID = 911)
                          OR (:STAGE_NUM =16 AND KUDA_ID IN (912, 913, 11200, 917))
                          -- for OSH5_601DTL
                          OR (:STAGE_NUM=-16 AND KUDA_ID NOT IN (916, 911) AND NOT(KUDA_ID IN (904, 905, 906, 907, 3143)
                              AND OU_VID_ID IN (965, 966, 967, 1014, 1016, 1010, 1011) AND OU_VID_ID IS NOT NULL))
                        )
                    GROUP BY LL76.PARENT_ID
                    ) V ON V.SCHOLAR_ID = L76.PARENT_ID
                LEFT JOIN VALL V1350 ON V1350.PARAM_ID = 1350 AND V1350.OBJ_ID = L76.OBJ_ID AND V1350.IS_DEL = 0
                WHERE L76.OBJ_TYPE_ID = 76
                  AND L76.DATE_DEL IS NULL
                  AND V433.PARAM_ID = 433
                  AND V433.IS_DEL = 0
                  AND V433.VAL <= MAXDATE
                  AND V432.PARAM_ID = 432
                  AND V432.IS_DEL = 0
                  AND V432.LISTVAL_ID BETWEEN 805 and 810
                  AND V436.PARAM_ID = 436
                  AND V436.IS_DEL = 0
                  AND V1350.LISTVAL_ID < 198
                GROUP BY L76.PARENT_ID, MAXDATE
                )
            WHERE :STAGE_NUM2 IS NULL
               OR (:STAGE_NUM2 = 1 AND STAGE_ID BETWEEN 37 AND 40)
               OR (:STAGE_NUM2 = 2 AND STAGE_ID BETWEEN 41 AND 45)
               OR (:STAGE_NUM2 = 3 AND STAGE_ID BETWEEN 46 AND 48)
        ) ORDER BY VAL1
        INTO :VAL1, :VAL2, :VAL3
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OSH1_1601DTL (
    I$OBJ_ID BIGINT NOT NULL,
    STAGE_NUM SMALLINT,
    STAGE_NUM2 SMALLINT,
    I$DT DATE = current_date)
RETURNS (
    VAL1 VARCHAR(250),
    VAL2 VARCHAR(250),
    VAL3 VARCHAR(250))
AS
BEGIN
    STAGE_NUM = :STAGE_NUM + 1;
    STAGE_NUM2 = :STAGE_NUM2 + 1;
    STAGE_NUM =
        CASE :STAGE_NUM
            WHEN 1 THEN 5339
            WHEN 2 THEN 5341
            WHEN 3 THEN 5343
            ELSE 4
        END;
    IF (:STAGE_NUM2/2*2 <> :STAGE_NUM2) THEN
        STAGE_NUM = -STAGE_NUM;
    STAGE_NUM2 =
        CASE
            WHEN :STAGE_NUM2 < 5 THEN 188
            WHEN :STAGE_NUM2 < 7 THEN 189
            WHEN :STAGE_NUM2 < 9 THEN 2129
            WHEN :STAGE_NUM2 <11 THEN 3155
            WHEN :STAGE_NUM2 <13 THEN 3131
            WHEN :STAGE_NUM2 <15 THEN 3132
            WHEN :STAGE_NUM2 <17 THEN 3136
            ELSE 17
        END;
    /*IF (STAGE_NUM > 0) THEN
        FOR
            SELECT
                (SELECT CAPTION FROM OBJECT_CAPTION_GET(SCHOLAR_ID)) VAL1,
                (SELECT D FROM VAL_GET(SCHOLAR_ID, 89)) VAL2,
                (SELECT CAPTION FROM OBJECT_CAPTION_GET
                    ((SELECT PARENT_ID
                     FROM LINKS
                     WHERE LINK_ID =
                         (SELECT MAX(L.LINK_ID)
                          FROM LINKS L
                          WHERE L.OBJ_ID = SCHOLAR_ID
                            AND L.PARENT_TYPE_ID IN (9,10,81,82,83)
                            AND l.DATE_DEL IS NULL
                         )
                    ))
                ) VAL3
            FROM (
                SELECT DISTINCT PL.PUPIL_ID SCHOLAR_ID
                FROM LINKS L69
                JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID
                  AND L57.OBJ_TYPE_ID = 57
                  --AND L57.DATE_DEL IS NULL
                JOIN VALL V1594 ON V1594.OBJ_ID = L57.OBJ_ID
                  AND V1594.PARAM_ID = 1594
                  AND V1594.IS_DEL = 0
                  AND (V1594.LISTVAL_ID = :STAGE_NUM OR :STAGE_NUM = 4)
                JOIN LINKS L50 ON L50.PARENT_ID = L57.OBJ_ID
                  AND L50.OBJ_TYPE_ID = 50
                  --AND L50.DATE_DEL IS NULL
                JOIN LINKS L54 ON L54.PARENT_ID = L50.OBJ_ID
                  AND L54.OBJ_TYPE_ID = 54
                  --AND L54.DATE_DEL IS NULL
                JOIN LINKS L256 ON L256.PARENT_ID = L54.OBJ_ID
                  AND L256.OBJ_TYPE_ID = 256
                  --AND L256.DATE_DEL IS NULL
                JOIN LINKS L47 ON L47.PARENT_ID = L256.OBJ_ID
                  AND L47.OBJ_TYPE_ID = 47
                  --AND L47.DATE_DEL IS NULL
                JOIN LINKS L48 ON L48.PARENT_ID = L47.OBJ_ID
                  AND L48.OBJ_TYPE_ID = 48
                  --AND L48.DATE_DEL IS NULL
                JOIN VALR V428 ON V428.OBJ_ID = L47.OBJ_ID
                  AND V428.PARAM_ID = 428
                  AND V428.IS_DEL = 0
                  AND ((:STAGE_NUM2 <> 17 AND ((:STAGE_NUM2 = 188 AND V428.VAL IN (178, 188)) OR V428.VAL = :STAGE_NUM2))
                    OR (:STAGE_NUM2 = 17 AND V428.VAL IN (3090,3130,3133,3134,3135,3137,3153,3154,5520,5521,5522)))
                LEFT JOIN CJ_GUP_PUPIL_PERIOD_LIST(L48.OBJ_ID, NULL) PL ON 1=1
                WHERE L69.PARENT_ID = :I$OBJ_ID
                  AND L69.OBJ_TYPE_ID = 69
                  AND PL.PUPIL_ID IS NOT NULL
                  AND :I$DT BETWEEN COALESCE(PL.PERIOD_START, :I$DT) AND COALESCE(PL.PERIOD_STOP, :I$DT)
            ) ORDER BY VAL1
            INTO :VAL1, :VAL2, :VAL3
        DO
        BEGIN
            SUSPEND;
        END
    ELSE
        BEGIN
            STAGE_NUM = -:STAGE_NUM;
            FOR
                SELECT (SELECT CAPTION FROM OBJECT_CAPTION_GET(GROUP_ID)) VAL3
                FROM (
                    SELECT DISTINCT L256.OBJ_ID GROUP_ID
                    FROM LINKS L69
                    JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID
                      AND L57.OBJ_TYPE_ID = 57
                      --AND L57.DATE_DEL IS NULL
                    JOIN VALL V1594 ON V1594.OBJ_ID = L57.OBJ_ID
                      AND V1594.PARAM_ID = 1594
                      AND V1594.IS_DEL = 0
                      AND (V1594.LISTVAL_ID = :STAGE_NUM OR :STAGE_NUM = 4)
                    JOIN LINKS L50 ON L50.PARENT_ID = L57.OBJ_ID
                      AND L50.OBJ_TYPE_ID = 50
                      --AND L50.DATE_DEL IS NULL
                    JOIN LINKS L54 ON L54.PARENT_ID = L50.OBJ_ID
                      AND L54.OBJ_TYPE_ID = 54
                      --AND L54.DATE_DEL IS NULL
                    JOIN LINKS L256 ON L256.PARENT_ID = L54.OBJ_ID
                      AND L256.OBJ_TYPE_ID = 256
                      --AND L256.DATE_DEL IS NULL
                    JOIN LINKS L47 ON L47.PARENT_ID = L256.OBJ_ID
                      AND L47.OBJ_TYPE_ID = 47
                      --AND L47.DATE_DEL IS NULL
                    JOIN LINKS L48 ON L48.PARENT_ID = L47.OBJ_ID
                      AND L48.OBJ_TYPE_ID = 48
                      --AND L48.DATE_DEL IS NULL
                    JOIN VALR V428 ON V428.OBJ_ID = L47.OBJ_ID
                      AND V428.PARAM_ID = 428
                      AND V428.IS_DEL = 0
                      AND ((:STAGE_NUM2 <> 17 AND ((:STAGE_NUM2 = 188 AND V428.VAL IN (178, 188)) OR V428.VAL = :STAGE_NUM2))
                        OR (:STAGE_NUM2 = 17 AND V428.VAL IN (3090,3130,3133,3134,3135,3137,3153,3154,5520,5521,5522)))
                    LEFT JOIN CJ_GUP_PUPIL_PERIOD_LIST(L48.OBJ_ID, NULL) PL ON 1=1
                    WHERE L69.PARENT_ID = :I$OBJ_ID
                      AND L69.OBJ_TYPE_ID = 69
                      AND PL.PUPIL_ID IS NOT NULL
                      AND :I$DT BETWEEN COALESCE(PL.PERIOD_START, :I$DT) AND COALESCE(PL.PERIOD_STOP, :I$DT)
                )
                INTO :VAL3
            DO
            BEGIN
                SUSPEND;
            END
        END*/
    IF(0 = 1) THEN SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OSH1_1611 (
    I$OBJ_ID BIGINT,
    I$GRADE BIGINT,
    I$LANG BIGINT,
    I$DT DATE = current_date)
RETURNS (
    V1 INTEGER,
    V2 INTEGER)
AS
BEGIN
    I$GRADE = CASE :I$GRADE
        WHEN 22 THEN 5339
        WHEN 26 THEN 5341
        WHEN 27 THEN 5343
        ELSE :I$GRADE
    END;

    /*SELECT
        COUNT(DISTINCT L256.OBJ_ID),
        COUNT(DISTINCT PL.PUPIL_ID)
    FROM LINKS L69
    JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID
      AND L57.OBJ_TYPE_ID = 57
      --AND L57.DATE_DEL IS NULL
    JOIN VALL V1594 ON V1594.OBJ_ID = L57.OBJ_ID
      AND V1594.PARAM_ID = 1594
      AND V1594.IS_DEL = 0
      AND V1594.LISTVAL_ID = :I$GRADE
    JOIN LINKS L50 ON L50.PARENT_ID = L57.OBJ_ID
      AND L50.OBJ_TYPE_ID = 50
      --AND L50.DATE_DEL IS NULL
    JOIN LINKS L54 ON L54.PARENT_ID = L50.OBJ_ID
      AND L54.OBJ_TYPE_ID = 54
      --AND L54.DATE_DEL IS NULL
    JOIN LINKS L256 ON L256.PARENT_ID = L54.OBJ_ID
      AND L256.OBJ_TYPE_ID = 256
      --AND L256.DATE_DEL IS NULL
    JOIN LINKS L47 ON L47.PARENT_ID = L256.OBJ_ID
      AND L47.OBJ_TYPE_ID = 47
      --AND L47.DATE_DEL IS NULL
    JOIN LINKS L48 ON L48.PARENT_ID = L47.OBJ_ID
      AND L48.OBJ_TYPE_ID = 48
      --AND L48.DATE_DEL IS NULL
    JOIN VALR V428 ON V428.OBJ_ID = L47.OBJ_ID
      AND V428.PARAM_ID = 428
      AND V428.IS_DEL = 0
      AND ((:I$LANG = 188 AND V428.VAL IN (178, 188)) OR V428.VAL = :I$LANG)
    LEFT JOIN CJ_GUP_PUPIL_PERIOD_LIST(L48.OBJ_ID, NULL) PL ON 1=1
    WHERE L69.PARENT_ID = :I$OBJ_ID
      AND L69.OBJ_TYPE_ID = 69
      AND PL.PUPIL_ID IS NOT NULL
      AND :I$DT BETWEEN COALESCE(PL.PERIOD_START, :I$DT) AND COALESCE(PL.PERIOD_STOP, :I$DT)
    INTO :V1, :V2;*/

    V1 = 0;
    V2 = 0;

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OSH1_1614 (
    I$OBJ_ID BIGINT,
    I$GRADE BIGINT,
    I$DT DATE = current_date)
RETURNS (
    V1 INTEGER,
    V2 INTEGER)
AS
BEGIN
    I$GRADE = CASE :I$GRADE
        WHEN 22 THEN 5339
        WHEN 26 THEN 5341
        WHEN 27 THEN 5343
        ELSE :I$GRADE
    END;

    /*SELECT
        COUNT(DISTINCT L256.OBJ_ID),
        COUNT(DISTINCT PL.PUPIL_ID)
    FROM LINKS L69
    JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID
      AND L57.OBJ_TYPE_ID = 57
      --AND L57.DATE_DEL IS NULL
    JOIN VALL V1594 ON V1594.OBJ_ID = L57.OBJ_ID
      AND V1594.PARAM_ID = 1594
      AND V1594.IS_DEL = 0
      AND V1594.LISTVAL_ID = :I$GRADE
    JOIN LINKS L50 ON L50.PARENT_ID = L57.OBJ_ID
      AND L50.OBJ_TYPE_ID = 50
      --AND L50.DATE_DEL IS NULL
    JOIN LINKS L54 ON L54.PARENT_ID = L50.OBJ_ID
      AND L54.OBJ_TYPE_ID = 54
      --AND L54.DATE_DEL IS NULL
    JOIN LINKS L256 ON L256.PARENT_ID = L54.OBJ_ID
      AND L256.OBJ_TYPE_ID = 256
      --AND L256.DATE_DEL IS NULL
    JOIN LINKS L47 ON L47.PARENT_ID = L256.OBJ_ID
      AND L47.OBJ_TYPE_ID = 47
      --AND L47.DATE_DEL IS NULL
    JOIN LINKS L48 ON L48.PARENT_ID = L47.OBJ_ID
      AND L48.OBJ_TYPE_ID = 48
      --AND L48.DATE_DEL IS NULL
    JOIN VALR V428 ON V428.OBJ_ID = L47.OBJ_ID
      AND V428.PARAM_ID = 428
      AND V428.IS_DEL = 0
      AND V428.VAL IN (3090,3130,3133,3134,3135,3137,3153,3154,5520,5521,5522)
    LEFT JOIN CJ_GUP_PUPIL_PERIOD_LIST(L48.OBJ_ID, NULL) PL ON 1=1
    WHERE L69.PARENT_ID = :I$OBJ_ID
      AND L69.OBJ_TYPE_ID = 69
      AND PL.PUPIL_ID IS NOT NULL
      AND :I$DT BETWEEN COALESCE(PL.PERIOD_START, :I$DT) AND COALESCE(PL.PERIOD_STOP, :I$DT)
    INTO :V1, :V2;*/

    V1 = 0;
    V2 = 0;

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OSH1_1641 (
    I$OBJ_ID BIGINT,
    I$LANG BIGINT,
    I$DT DATE = current_date)
RETURNS (
    V1 INTEGER,
    V2 INTEGER)
AS
BEGIN
    /*SELECT
        COUNT(DISTINCT L256.OBJ_ID),
        COUNT(DISTINCT PL.PUPIL_ID)
    FROM LINKS L69
    JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID
      AND L57.OBJ_TYPE_ID = 57
      --AND L57.DATE_DEL IS NULL
    JOIN VALL V1594 ON V1594.OBJ_ID = L57.OBJ_ID
      AND V1594.PARAM_ID = 1594
      AND V1594.IS_DEL = 0
      AND V1594.LISTVAL_ID IN (5339, 5341, 5343)
    JOIN LINKS L50 ON L50.PARENT_ID = L57.OBJ_ID
      AND L50.OBJ_TYPE_ID = 50
      --AND L50.DATE_DEL IS NULL
    JOIN LINKS L54 ON L54.PARENT_ID = L50.OBJ_ID
      AND L54.OBJ_TYPE_ID = 54
      --AND L54.DATE_DEL IS NULL
    JOIN LINKS L256 ON L256.PARENT_ID = L54.OBJ_ID
      AND L256.OBJ_TYPE_ID = 256
      --AND L256.DATE_DEL IS NULL
    JOIN LINKS L47 ON L47.PARENT_ID = L256.OBJ_ID
      AND L47.OBJ_TYPE_ID = 47
      --AND L47.DATE_DEL IS NULL
    JOIN LINKS L48 ON L48.PARENT_ID = L47.OBJ_ID
      AND L48.OBJ_TYPE_ID = 48
      --AND L48.DATE_DEL IS NULL
    JOIN VALR V428 ON V428.OBJ_ID = L47.OBJ_ID
      AND V428.PARAM_ID = 428
      AND V428.IS_DEL = 0
      AND ((:I$LANG = 188 AND V428.VAL IN (178, 188)) OR V428.VAL = :I$LANG)
    LEFT JOIN CJ_GUP_PUPIL_PERIOD_LIST(L48.OBJ_ID, NULL) PL ON 1=1
    WHERE L69.PARENT_ID = :I$OBJ_ID
      AND L69.OBJ_TYPE_ID = 69
      AND PL.PUPIL_ID IS NOT NULL
      AND :I$DT BETWEEN COALESCE(PL.PERIOD_START, :I$DT) AND COALESCE(PL.PERIOD_STOP, :I$DT)
    INTO :V1, :V2;*/

    V1 = 0;
    V2 = 0;

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OSH1_1644 (
    I$OBJ_ID BIGINT,
    I$DT DATE = current_date)
RETURNS (
    V1 INTEGER,
    V2 INTEGER)
AS
BEGIN
    /*SELECT
        COUNT(DISTINCT L256.OBJ_ID),
        COUNT(DISTINCT PL.PUPIL_ID)
    FROM LINKS L69
    JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID
      AND L57.OBJ_TYPE_ID = 57
      --AND L57.DATE_DEL IS NULL
    JOIN VALL V1594 ON V1594.OBJ_ID = L57.OBJ_ID
      AND V1594.PARAM_ID = 1594
      AND V1594.IS_DEL = 0
      AND V1594.LISTVAL_ID IN (5339, 5341, 5343)
    JOIN LINKS L50 ON L50.PARENT_ID = L57.OBJ_ID
      AND L50.OBJ_TYPE_ID = 50
      --AND L50.DATE_DEL IS NULL
    JOIN LINKS L54 ON L54.PARENT_ID = L50.OBJ_ID
      AND L54.OBJ_TYPE_ID = 54
      --AND L54.DATE_DEL IS NULL
    JOIN LINKS L256 ON L256.PARENT_ID = L54.OBJ_ID
      AND L256.OBJ_TYPE_ID = 256
      --AND L256.DATE_DEL IS NULL
    JOIN LINKS L47 ON L47.PARENT_ID = L256.OBJ_ID
      AND L47.OBJ_TYPE_ID = 47
      --AND L47.DATE_DEL IS NULL
    JOIN LINKS L48 ON L48.PARENT_ID = L47.OBJ_ID
      AND L48.OBJ_TYPE_ID = 48
      --AND L48.DATE_DEL IS NULL
    JOIN VALR V428 ON V428.OBJ_ID = L47.OBJ_ID
      AND V428.PARAM_ID = 428
      AND V428.IS_DEL = 0
      AND V428.VAL IN (3090,3130,3133,3134,3135,3137,3153,3154,5520,5521,5522)
    LEFT JOIN CJ_GUP_PUPIL_PERIOD_LIST(L48.OBJ_ID, NULL) PL ON 1=1
    WHERE L69.PARENT_ID = :I$OBJ_ID
      AND L69.OBJ_TYPE_ID = 69
      AND PL.PUPIL_ID IS NOT NULL
      AND :I$DT BETWEEN COALESCE(PL.PERIOD_START, :I$DT) AND COALESCE(PL.PERIOD_STOP, :I$DT)
    INTO :V1, :V2;*/

    V1 = 0;
    V2 = 0;

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OSH1_1701 (
    I$OBJ_ID BIGINT,
    I$PROFIL BIGINT)
RETURNS (
    V3 INTEGER,
    V4 INTEGER,
    V5 INTEGER,
    V6 INTEGER,
    V7 INTEGER,
    V8 INTEGER,
    V9 INTEGER,
    V10 INTEGER)
AS
DECLARE VARIABLE CLASS_ID BIGINT;
DECLARE VARIABLE STAGE_LISTVAL_ID BIGINT;
DECLARE VARIABLE X INTEGER;
BEGIN
    V3 = 0;
    V4 = 0;
    V5 = 0;
    V6 = 0;
    V7 = 0;
    V8 = 0;
    V9 = 0;
    V10 = 0;

    IF (I$PROFIL = 61) THEN
    BEGIN
        FOR SELECT DISTINCT
                 R.STAGE_LISTVAL_ID,
                 R.CLASS_ID,
                 COUNT(1)
            FROM REPORT_OSH1 R
            INNER JOIN VALL V591 ON V591.OBJ_ID = R.CLASS_ID
            WHERE V591.PARAM_ID = 591
              AND V591.LISTVAL_ID IN (61,62,63,134,135,136)
              AND V591.IS_DEL = 0
            GROUP BY R.STAGE_LISTVAL_ID, R.CLASS_ID
            INTO :STAGE_LISTVAL_ID, :CLASS_ID, :X
        DO
        BEGIN
            IF (:STAGE_LISTVAL_ID BETWEEN 37 AND 40) THEN
            BEGIN
                V3 = V3 + 1;
                V7 = V7 + X;
            END
            IF (:STAGE_LISTVAL_ID BETWEEN 41 AND 45) THEN
            BEGIN
                V4 = V4 + 1;
                V8 = V8 + X;
            END
            IF (:STAGE_LISTVAL_ID BETWEEN 46 AND 48) THEN
            BEGIN
                V5 = V5 + 1;
                V9 = V9 + X;
            END
        END
    END
    ELSE
    BEGIN
        FOR SELECT DISTINCT
                 R.STAGE_LISTVAL_ID,
                 R.CLASS_ID,
                 COUNT(1)
            FROM REPORT_OSH1 R
            INNER JOIN VALL V591 ON V591.OBJ_ID = R.CLASS_ID
            WHERE V591.PARAM_ID = 591
              AND V591.LISTVAL_ID = :I$PROFIL
              AND V591.IS_DEL = 0
            GROUP BY R.STAGE_LISTVAL_ID, R.CLASS_ID
            INTO :STAGE_LISTVAL_ID, :CLASS_ID, :X
        DO
        BEGIN
            IF (:STAGE_LISTVAL_ID BETWEEN 37 AND 40) THEN
            BEGIN
                V3 = V3 + 1;
                V7 = V7 + X;
            END
            IF (:STAGE_LISTVAL_ID BETWEEN 41 AND 45) THEN
            BEGIN
                V4 = V4 + 1;
                V8 = V8 + X;
            END
            IF (:STAGE_LISTVAL_ID BETWEEN 46 AND 48) THEN
            BEGIN
                V5 = V5 + 1;
                V9 = V9 + X;
            END
        END
    END
    V6 = V3 + V4 + V5;
    V10 = V7 + V8 + V9;
    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OSH1_1701DTL (
    I$OBJ_ID BIGINT NOT NULL,
    STAGE_NUM SMALLINT,
    STAGE_NUM2 SMALLINT)
RETURNS (
    VAL1 VARCHAR(250),
    VAL2 VARCHAR(250),
    VAL3 VARCHAR(250))
AS
DECLARE VARIABLE STAGE_MIN INTEGER;
DECLARE VARIABLE STAGE_MAX INTEGER;
BEGIN
    STAGE_NUM = :STAGE_NUM + 1;
    STAGE_NUM2 = :STAGE_NUM2 + 1;
    STAGE_NUM =
        CASE :STAGE_NUM
            WHEN 1 THEN 61
            WHEN 2 THEN 62
            WHEN 3 THEN 63
            WHEN 4 THEN 134
            WHEN 5 THEN 135
            WHEN 6 THEN 136
            WHEN 7 THEN 137
            WHEN 8 THEN 138
            WHEN 9 THEN 139
            WHEN 10 THEN 1730
        END;
    IF (:STAGE_NUM2 < 7) THEN
        STAGE_NUM = -STAGE_NUM;
    STAGE_NUM2 =
        CASE
            WHEN :STAGE_NUM2 IN (3, 7) THEN 22
            WHEN :STAGE_NUM2 IN (4, 8) THEN 26
            WHEN :STAGE_NUM2 IN (5, 9) THEN 27
            ELSE 10
        END;
    STAGE_MIN =
        CASE :STAGE_NUM2
            WHEN 26 THEN 41
            WHEN 27 THEN 46
            ELSE 37
        END;
    STAGE_MAX =
        CASE :STAGE_NUM2
            WHEN 22 THEN 40
            WHEN 26 THEN 45
            ELSE 48
        END;
    IF (:STAGE_NUM > 0) THEN
        FOR
            SELECT
                (SELECT CAPTION FROM OBJECT_CAPTION_GET(SCHOLAR_ID)) VAL1,
                (SELECT D FROM VAL_GET(SCHOLAR_ID, 89)) VAL2,
                (SELECT CAPTION FROM OBJECT_CAPTION_GET
                    ((SELECT PARENT_ID
                     FROM LINKS
                     WHERE LINK_ID =
                         (SELECT MAX(L.LINK_ID)
                          FROM LINKS L
                          WHERE L.OBJ_ID = SCHOLAR_ID
                            AND L.PARENT_TYPE_ID IN (9,10,81,82,83)
                            AND l.DATE_DEL IS NULL
                         )
                    ))
                ) VAL3
            FROM (
                SELECT R.SCHOLAR_ID
                FROM REPORT_OSH1 R
                INNER JOIN VALL V591 ON V591.OBJ_ID = R.CLASS_ID
                WHERE V591.PARAM_ID = 591
                  AND ((:STAGE_NUM <> 61 AND V591.LISTVAL_ID = :STAGE_NUM)
                    OR (:STAGE_NUM = 61 AND V591.LISTVAL_ID IN (61,62,63,134,135,136)))
                  AND V591.LISTVAL_ID = :STAGE_NUM
                  AND V591.IS_DEL = 0
                  AND R.STAGE_LISTVAL_ID BETWEEN :STAGE_MIN AND :STAGE_MAX
            ) ORDER BY VAL1
            INTO :VAL1, :VAL2, :VAL3
        DO
        BEGIN
            SUSPEND;
        END
    ELSE
        BEGIN
            STAGE_NUM = -:STAGE_NUM;
            FOR
                SELECT (SELECT CAPTION FROM OBJECT_CAPTION_GET(CLASS_ID)) VAL3
                FROM (
                    SELECT DISTINCT R.CLASS_ID
                    FROM REPORT_OSH1 R
                    INNER JOIN VALL V591 ON V591.OBJ_ID = R.CLASS_ID
                    WHERE V591.PARAM_ID = 591
                      AND ((:STAGE_NUM <> 61 AND V591.LISTVAL_ID = :STAGE_NUM)
                        OR (:STAGE_NUM = 61 AND V591.LISTVAL_ID IN (61,62,63,134,135,136)))
                      AND V591.LISTVAL_ID = :STAGE_NUM
                      AND V591.IS_DEL = 0
                      AND R.STAGE_LISTVAL_ID BETWEEN :STAGE_MIN AND :STAGE_MAX
                )
                INTO :VAL3
            DO
            BEGIN
                SUSPEND;
            END
        END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OSH1_1801 (
    I$OBJ_ID BIGINT)
RETURNS (
    V3 INTEGER,
    V4 INTEGER)
AS
BEGIN
    SELECT COUNT(DISTINCT R.CLASS_ID), COUNT(1)
    FROM REPORT_OSH1 R
    INNER JOIN VALL V1338 ON V1338.OBJ_ID = R.CLASS_ID
    WHERE V1338.PARAM_ID = 1338
      AND V1338.IS_DEL = 0
      AND V1338.LISTVAL_ID <> 3123
    INTO :V3, :V4;

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OSH1_1801DTL (
    I$OBJ_ID BIGINT NOT NULL,
    STAGE_NUM SMALLINT,
    STAGE_NUM2 SMALLINT)
RETURNS (
    VAL1 VARCHAR(250),
    VAL2 VARCHAR(250),
    VAL3 VARCHAR(250))
AS
BEGIN
    STAGE_NUM = :STAGE_NUM + 1;
    IF (:STAGE_NUM > 2) THEN
        STAGE_NUM = :STAGE_NUM + 3121;
    STAGE_NUM2 = :STAGE_NUM2 + 1;
    IF (:STAGE_NUM2 = 4) THEN
        FOR
            SELECT
                (SELECT CAPTION FROM OBJECT_CAPTION_GET(SCHOLAR_ID)) VAL1,
                (SELECT D FROM VAL_GET(SCHOLAR_ID, 89)) VAL2,
                (SELECT CAPTION FROM OBJECT_CAPTION_GET
                    ((SELECT PARENT_ID
                     FROM LINKS
                     WHERE LINK_ID =
                         (SELECT MAX(L.LINK_ID)
                          FROM LINKS L
                          WHERE L.OBJ_ID = SCHOLAR_ID
                            AND L.PARENT_TYPE_ID IN (9,10,81,82,83)
                            AND l.DATE_DEL IS NULL
                         )
                    ))
                ) VAL3
            FROM (
                SELECT R.SCHOLAR_ID
                FROM REPORT_OSH1 R
                INNER JOIN VALL V1338 ON V1338.OBJ_ID = R.CLASS_ID
                WHERE V1338.PARAM_ID = 1338
                  AND V1338.IS_DEL = 0
                  AND ((:STAGE_NUM = 1 AND V1338.LISTVAL_ID <> 3123)
                    OR (:STAGE_NUM = 2 AND V1338.LISTVAL_ID BETWEEN 3124 AND 3127)
                    OR (:STAGE_NUM > 2 AND V1338.LISTVAL_ID = :STAGE_NUM))
            ) ORDER BY VAL1
            INTO :VAL1, :VAL2, :VAL3
        DO
        BEGIN
            SUSPEND;
        END
    ELSE
        BEGIN
            FOR
                SELECT (SELECT CAPTION FROM OBJECT_CAPTION_GET(CLASS_ID)) VAL3
                FROM (
                    SELECT DISTINCT R.CLASS_ID
                    FROM REPORT_OSH1 R
                    INNER JOIN VALL V1338 ON V1338.OBJ_ID = R.CLASS_ID
                    WHERE V1338.PARAM_ID = 1338
                      AND V1338.IS_DEL = 0
                      AND ((:STAGE_NUM = 1 AND V1338.LISTVAL_ID <> 3123)
                        OR (:STAGE_NUM = 2 AND V1338.LISTVAL_ID BETWEEN 3124 AND 3127)
                        OR (:STAGE_NUM > 2 AND V1338.LISTVAL_ID = :STAGE_NUM))
                )
                INTO :VAL3
            DO
            BEGIN
                SUSPEND;
            END
        END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OSH1_1802 (
    I$OBJ_ID BIGINT)
RETURNS (
    V3 INTEGER,
    V4 INTEGER)
AS
BEGIN
    SELECT COUNT(DISTINCT R.CLASS_ID), COUNT(1)
    FROM REPORT_OSH1 R
    INNER JOIN VALL V1338 ON V1338.OBJ_ID = R.CLASS_ID
    WHERE V1338.PARAM_ID = 1338
      AND V1338.IS_DEL = 0
          AND V1338.LISTVAL_ID IN (3124,3125,3126,3127)
    INTO :V3, :V4;

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OSH1_1803 (
    I$OBJ_ID BIGINT,
    I$PROFIL BIGINT)
RETURNS (
    V3 INTEGER,
    V4 INTEGER)
AS
BEGIN
    SELECT COUNT(DISTINCT R.CLASS_ID), COUNT(1)
    FROM REPORT_OSH1 R
    INNER JOIN VALL V1338 ON V1338.OBJ_ID = R.CLASS_ID
    WHERE V1338.PARAM_ID = 1338
      AND V1338.IS_DEL = 0
      AND V1338.LISTVAL_ID = :I$PROFIL
    INTO :V3, :V4;

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OSH1_201 (
    I$OBJ_ID BIGINT,
    I$STAGE_LISTVAL_ID BIGINT,
    I$DT DATE = CURRENT_DATE)
RETURNS (
    VAL INTEGER)
AS
DECLARE VARIABLE SCHOOLAR_ID BIGINT;
DECLARE VARIABLE X INTEGER;
DECLARE VARIABLE V$YEAR INTEGER;
BEGIN
    V$YEAR = COALESCE(:V$YEAR, (SELECT Y FROM OSH1_YEAR_GET(0, :I$DT)));
    VAL = 0;

    FOR SELECT L10.OBJ_ID
        FROM LINKS L7
        INNER JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID
        INNER JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID
        INNER JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID
        INNER JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID
        WHERE L7.PARENT_ID = :I$OBJ_ID
          AND :I$DT = CURRENT_DATE
          AND L7.OBJ_TYPE_ID = 7
          AND L7.DATE_DEL IS NULL
          AND L8.OBJ_TYPE_ID = 8
          AND L8.DATE_DEL IS NULL
          AND V49.PARAM_ID = 49
          AND V49.IS_DEL = 0
          AND V49.LISTVAL_ID = :I$STAGE_LISTVAL_ID
          AND L9.OBJ_TYPE_ID = 9
          AND L9.DATE_DEL IS NULL
          AND L10.OBJ_TYPE_ID = 10
          AND L10.DATE_DEL IS NULL

        UNION
        SELECT SCHOLAR_ID
        FROM REPORT_OSH1 R
        WHERE R.STAGE_LISTVAL_ID = :I$STAGE_LISTVAL_ID
          AND :I$DT <> CURRENT_DATE

        INTO :SCHOOLAR_ID
    DO
    BEGIN
        X = 0;

        SELECT FIRST 1 1
        FROM LINKS L76
        INNER JOIN VALL V432 ON V432.OBJ_ID = L76.OBJ_ID
        INNER JOIN VALL V436 ON V436.OBJ_ID = L76.OBJ_ID
        INNER JOIN VALD V433 ON V433.OBJ_ID = L76.OBJ_ID
        JOIN VALL V1350 ON V1350.PARAM_ID = 1350
          AND V1350.OBJ_ID = L76.OBJ_ID
          AND V1350.IS_DEL = 0
          AND V1350.LISTVAL_ID < 198
        WHERE L76.PARENT_ID = :SCHOOLAR_ID
          AND L76.OBJ_TYPE_ID = 76
          AND L76.DATE_DEL IS NULL
          AND V432.PARAM_ID = 432
          AND V432.IS_DEL = 0
          AND V432.LISTVAL_ID = 808
          AND V436.PARAM_ID = 436
          AND V436.IS_DEL = 0
          AND V436.LISTVAL_ID = :I$STAGE_LISTVAL_ID
          AND V433.PARAM_ID = 433
          AND V433.IS_DEL = 0
          AND EXTRACT(YEAR FROM V433.VAL) = :V$YEAR
        INTO :X;

        VAL = VAL + X;
    END

    FOR SELECT L10.OBJ_ID
        FROM LINKS L78
        INNER JOIN LINKS L82 ON L82.PARENT_ID = L78.OBJ_ID
        INNER JOIN VALI V449 ON V449.OBJ_ID = L82.OBJ_ID
        INNER JOIN LINKS L10 ON L10.PARENT_ID = L82.OBJ_ID
        WHERE L78.PARENT_ID = :I$OBJ_ID
          AND L78.OBJ_TYPE_ID = 78
          AND L78.DATE_DEL IS NULL
          AND L82.OBJ_TYPE_ID = 82
          AND L82.DATE_DEL IS NULL
          AND V449.PARAM_ID = 449
          AND V449.IS_DEL = 0
          AND V449.VAL = :V$YEAR
          AND L10.OBJ_TYPE_ID = 10
          AND L10.DATE_DEL IS NULL
        INTO :SCHOOLAR_ID
    DO
    BEGIN
        X = 0;

        SELECT FIRST 1 1
        FROM LINKS L76
        INNER JOIN VALL V432 ON V432.OBJ_ID = L76.OBJ_ID
        INNER JOIN VALL V436 ON V436.OBJ_ID = L76.OBJ_ID
        INNER JOIN VALD V433 ON V433.OBJ_ID = L76.OBJ_ID
        JOIN VALL V1350 ON V1350.PARAM_ID = 1350
          AND V1350.OBJ_ID = L76.OBJ_ID
          AND V1350.IS_DEL = 0
          AND V1350.LISTVAL_ID < 198
        WHERE L76.PARENT_ID = :SCHOOLAR_ID
          AND L76.OBJ_TYPE_ID = 76
          AND L76.DATE_DEL IS NULL
          AND V432.PARAM_ID = 432
          AND V432.IS_DEL = 0
          AND V432.LISTVAL_ID = 808
          AND V436.PARAM_ID = 436
          AND V436.IS_DEL = 0
          AND V436.LISTVAL_ID = :I$STAGE_LISTVAL_ID
          AND V433.PARAM_ID = 433
          AND V433.IS_DEL = 0
          AND EXTRACT(YEAR FROM V433.VAL) = :V$YEAR
        INTO :X;

        VAL = VAL + X;
    END

    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OSH1_201DTL (
    I$OBJ_ID BIGINT NOT NULL,
    STAGE_NUM SMALLINT NOT NULL,
    I$DT DATE = CURRENT_DATE)
RETURNS (
    VAL1 VARCHAR(250),
    VAL2 VARCHAR(250),
    VAL3 VARCHAR(250))
AS
DECLARE VARIABLE V$YEAR INTEGER;
BEGIN
    V$YEAR = COALESCE(:V$YEAR, (SELECT Y FROM OSH1_YEAR_GET(0, :I$DT)));

    IF (:STAGE_NUM <> 11) THEN
    BEGIN
        IF (:STAGE_NUM > 11) THEN
            STAGE_NUM = STAGE_NUM - 1;
        STAGE_NUM = :STAGE_NUM + 37;
    END
    FOR
        SELECT
            (SELECT CAPTION FROM OBJECT_CAPTION_GET(SCHOLAR_ID)) VAL1,
            (SELECT D FROM VAL_GET(SCHOLAR_ID, 89)) VAL2,
            (SELECT CAPTION FROM OBJECT_CAPTION_GET
                ((SELECT PARENT_ID
                 FROM LINKS
                 WHERE LINK_ID =
                     (SELECT MAX(L.LINK_ID)
                      FROM LINKS L
                      WHERE L.OBJ_ID = SCHOLAR_ID
                        AND L.PARENT_TYPE_ID IN (9,10,81,82,83)
                        AND l.DATE_DEL IS NULL
                     )
                ))
            ) VAL3
        FROM (
            SELECT DISTINCT L76.PARENT_ID SCHOLAR_ID
            FROM LINKS L76
            INNER JOIN VALL V432 ON V432.OBJ_ID = L76.OBJ_ID
            INNER JOIN VALL V436 ON V436.OBJ_ID = L76.OBJ_ID
            INNER JOIN VALD V433 ON V433.OBJ_ID = L76.OBJ_ID
            JOIN VALL V1350 ON V1350.PARAM_ID = 1350
              AND V1350.OBJ_ID = L76.OBJ_ID
              AND V1350.IS_DEL = 0
              AND V1350.LISTVAL_ID < 198
            WHERE :STAGE_NUM <> 11
              AND L76.OBJ_TYPE_ID = 76
              AND L76.DATE_DEL IS NULL
              AND V432.PARAM_ID = 432
              AND V432.IS_DEL = 0
              AND V432.LISTVAL_ID = 808
              AND V436.PARAM_ID = 436
              AND V436.IS_DEL = 0
              AND V436.LISTVAL_ID = :STAGE_NUM
              AND V433.PARAM_ID = 433
              AND V433.IS_DEL = 0
              AND EXTRACT(YEAR FROM V433.VAL) = :V$YEAR
              AND L76.PARENT_ID IN (
                SELECT L10.OBJ_ID
                FROM LINKS L7
                INNER JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID
                INNER JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID
                INNER JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID
                INNER JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID
                WHERE L7.PARENT_ID = :I$OBJ_ID
                  AND :I$DT = CURRENT_DATE
                  AND L7.OBJ_TYPE_ID = 7
                  AND L7.DATE_DEL IS NULL
                  AND L8.OBJ_TYPE_ID = 8
                  AND L8.DATE_DEL IS NULL
                  AND V49.PARAM_ID = 49
                  AND V49.IS_DEL = 0
                  AND V49.LISTVAL_ID = :STAGE_NUM
                  AND L9.OBJ_TYPE_ID = 9
                  AND L9.DATE_DEL IS NULL
                  AND L10.OBJ_TYPE_ID = 10
                  AND L10.DATE_DEL IS NULL
                UNION
                SELECT SCHOLAR_ID
                FROM REPORT_OSH1
                WHERE STAGE_LISTVAL_ID = :STAGE_NUM
                  AND :I$DT <> CURRENT_DATE

                UNION ALL
                SELECT L10.OBJ_ID
                FROM LINKS L78
                INNER JOIN LINKS L82 ON L82.PARENT_ID = L78.OBJ_ID
                INNER JOIN VALI V449 ON V449.OBJ_ID = L82.OBJ_ID
                INNER JOIN LINKS L10 ON L10.PARENT_ID = L82.OBJ_ID
                WHERE L78.PARENT_ID = :I$OBJ_ID
                  AND L78.OBJ_TYPE_ID = 78
                  AND L78.DATE_DEL IS NULL
                  AND L82.OBJ_TYPE_ID = 82
                  AND L82.DATE_DEL IS NULL
                  AND V449.PARAM_ID = 449
                  AND V449.IS_DEL = 0
                  AND V449.VAL = :V$YEAR
                  AND L10.OBJ_TYPE_ID = 10
                  AND L10.DATE_DEL IS NULL
                )
            UNION
            SELECT DISTINCT L76.PARENT_ID SCHOLAR_ID
            FROM LINKS L76
            INNER JOIN VALL V432 ON V432.OBJ_ID = L76.OBJ_ID
            INNER JOIN VALD V433 ON V433.OBJ_ID = L76.OBJ_ID
            JOIN VALL V1350 ON V1350.PARAM_ID = 1350
              AND V1350.OBJ_ID = L76.OBJ_ID
              AND V1350.IS_DEL = 0
              AND V1350.LISTVAL_ID < 198
            WHERE :STAGE_NUM = 11
              AND L76.OBJ_TYPE_ID = 76
              AND L76.DATE_DEL IS NULL
              AND V432.PARAM_ID = 432
              AND V432.IS_DEL = 0
              AND V432.LISTVAL_ID = 812
              AND V433.PARAM_ID = 433
              AND V433.IS_DEL = 0
              AND EXTRACT(YEAR FROM V433.VAL) = :V$YEAR
              AND L76.PARENT_ID IN (
                SELECT L11.PARENT_ID SCHOLAR_ID
                FROM LINKS L11
                INNER JOIN VALL V50  ON V50.OBJ_ID = L11.OBJ_ID
                INNER JOIN VALD V566 ON V566.OBJ_ID = L11.OBJ_ID
                WHERE L11.OBJ_TYPE_ID = 11
                  AND L11.DATE_DEL IS NULL
                  AND V50.PARAM_ID = 50
                  AND V50.IS_DEL = 0
                  AND V50.LISTVAL_ID IN (1376, 3240)
                  AND V566.PARAM_ID = 566
                  AND V566.IS_DEL = 0
                  AND EXTRACT(YEAR FROM V566.VAL) = :V$YEAR
                  AND L11.PARENT_ID IN (
                    SELECT L10.OBJ_ID
                    FROM LINKS L78
                    INNER JOIN LINKS L83 ON L83.PARENT_ID = L78.OBJ_ID
                    INNER JOIN VALI V451 ON V451.OBJ_ID = L83.OBJ_ID
                    INNER JOIN LINKS L10 ON L10.PARENT_ID = L83.OBJ_ID
                    WHERE L78.PARENT_ID = :I$OBJ_ID
                      AND L78.OBJ_TYPE_ID = 78
                      AND L78.DATE_DEL IS NULL
                      AND L83.OBJ_TYPE_ID = 83
                      AND L83.DATE_DEL IS NULL
                      AND V451.PARAM_ID = 451
                      AND V451.IS_DEL = 0
                      AND V451.VAL = :V$YEAR
                      AND L10.OBJ_TYPE_ID = 10
                      AND L10.DATE_DEL IS NULL
                    )
                )
        ) ORDER BY VAL1
        INTO :VAL1, :VAL2, :VAL3
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OSH1_213 (
    I$OBJ_ID BIGINT,
    I$STAGE_LISTVAL_ID BIGINT,
    I$DT DATE = CURRENT_DATE)
RETURNS (
    VAL INTEGER)
AS
DECLARE VARIABLE SCHOOLAR_ID BIGINT;
DECLARE VARIABLE X INTEGER;
DECLARE VARIABLE Y INTEGER;
DECLARE VARIABLE V$YEAR INTEGER;
BEGIN
    VAL = 0;
    V$YEAR = COALESCE(:V$YEAR, (SELECT Y FROM OSH1_YEAR_GET(0, :I$DT)));

    FOR SELECT L10.OBJ_ID
        FROM LINKS L78
        INNER JOIN LINKS L83 ON L83.PARENT_ID = L78.OBJ_ID
        INNER JOIN VALI V451 ON V451.OBJ_ID = L83.OBJ_ID
        INNER JOIN LINKS L10 ON L10.PARENT_ID = L83.OBJ_ID
        WHERE L78.PARENT_ID = :I$OBJ_ID
          AND L78.OBJ_TYPE_ID = 78
          AND L78.DATE_DEL IS NULL
          AND L83.OBJ_TYPE_ID = 83
          AND L83.DATE_DEL IS NULL
          AND V451.PARAM_ID = 451
          AND V451.IS_DEL = 0
          AND V451.VAL = :V$YEAR
          AND L10.OBJ_TYPE_ID = 10
          AND L10.DATE_DEL IS NULL
        INTO :SCHOOLAR_ID
    DO
    BEGIN
        X = 0;

        SELECT FIRST 1 1
        FROM LINKS L76
        INNER JOIN VALL V432 ON V432.OBJ_ID = L76.OBJ_ID
        INNER JOIN VALD V433 ON V433.OBJ_ID = L76.OBJ_ID
        JOIN VALL V1350 ON V1350.PARAM_ID = 1350
          AND V1350.OBJ_ID = L76.OBJ_ID
          AND V1350.IS_DEL = 0
          AND V1350.LISTVAL_ID < 198
        WHERE L76.PARENT_ID = :SCHOOLAR_ID
          AND L76.OBJ_TYPE_ID = 76
          AND L76.DATE_DEL IS NULL
          AND V432.PARAM_ID = 432
          AND V432.IS_DEL = 0
          AND V432.LISTVAL_ID = 812
          AND V433.PARAM_ID = 433
          AND V433.IS_DEL = 0
          AND EXTRACT(YEAR FROM V433.VAL) = :V$YEAR
        INTO :X;

        Y = 0;

        SELECT FIRST 1 1
        FROM LINKS L11
        INNER JOIN VALL V50  ON V50.OBJ_ID = L11.OBJ_ID
        INNER JOIN VALD V566 ON V566.OBJ_ID = L11.OBJ_ID
        WHERE L11.PARENT_ID = :SCHOOLAR_ID
          AND L11.OBJ_TYPE_ID = 11
          AND L11.DATE_DEL IS NULL
          AND V50.PARAM_ID = 50
          AND V50.IS_DEL = 0
          AND V50.LISTVAL_ID IN (1376, 3240)
          AND V566.PARAM_ID = 566
          AND V566.IS_DEL = 0
          AND EXTRACT(YEAR FROM V566.VAL) = :V$YEAR
        INTO :Y;


        VAL = VAL + X * Y;
    END

    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OSH1_301 (
    I$OBJ_ID BIGINT,
    I$N SMALLINT)
RETURNS (
    VAL3 INTEGER,
    VAL4 INTEGER)
AS
DECLARE VARIABLE GRADE_ID BIGINT;
DECLARE VARIABLE LISTVAL_ID BIGINT;
DECLARE VARIABLE X INTEGER;
DECLARE VARIABLE C INTEGER;
DECLARE VARIABLE CLASS_TYPE BIGINT;
BEGIN
    VAL3 = 0;
    VAL4 = 0;

    FOR SELECT L7.OBJ_ID, V43.LISTVAL_ID
        FROM LINKS L7
        INNER JOIN VALL V43 ON V43.OBJ_ID = L7.OBJ_ID
        WHERE L7.PARENT_ID = :I$OBJ_ID
          AND L7.OBJ_TYPE_ID = 7
          AND L7.DATE_DEL IS NULL
          AND V43.PARAM_ID = 43
          AND V43.IS_DEL = 0
        INTO :GRADE_ID, :LISTVAL_ID
    DO
    BEGIN
        IF ((I$N = 1) AND
            ((LISTVAL_ID = 21) OR (LISTVAL_ID = 22))) THEN
        BEGIN
            FOR SELECT
                    V592.LISTVAL_ID,
                    COUNT(DISTINCT R.CLASS_ID)
                FROM LINKS L8
                JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID
                  AND V49.PARAM_ID = 49
                  AND V49.IS_DEL = 0
                JOIN REPORT_OSH1 R ON V49.LISTVAL_ID = R.STAGE_LISTVAL_ID
                JOIN VALL V592 ON V592.OBJ_ID = R.CLASS_ID
                  AND V592.PARAM_ID = 592
                  AND V592.IS_DEL = 0
                WHERE L8.PARENT_ID = :GRADE_ID
                  AND L8.OBJ_TYPE_ID = 8
                  AND L8.DATE_DEL IS NULL
                GROUP BY V592.LISTVAL_ID
                INTO :CLASS_TYPE, :X
            DO
            BEGIN
                IF (:CLASS_TYPE < 198) THEN
                BEGIN
                    VAL3 = VAL3 + X;
                END
                ELSE
                BEGIN
                    VAL4 = VAL4 + X;
                END
            END
        END

        IF ((I$N = 2) AND
            (LISTVAL_ID = 26)) THEN
        BEGIN
            FOR SELECT
                    V592.LISTVAL_ID,
                    COUNT(DISTINCT R.CLASS_ID)
                FROM LINKS L8
                JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID
                  AND V49.PARAM_ID = 49
                  AND V49.IS_DEL = 0
                JOIN REPORT_OSH1 R ON V49.LISTVAL_ID = R.STAGE_LISTVAL_ID
                JOIN VALL V592 ON V592.OBJ_ID = R.CLASS_ID
                  AND V592.PARAM_ID = 592
                  AND V592.IS_DEL = 0
                WHERE L8.PARENT_ID = :GRADE_ID
                  AND L8.OBJ_TYPE_ID = 8
                  AND L8.DATE_DEL IS NULL
                GROUP BY V592.LISTVAL_ID
                INTO :CLASS_TYPE, :X
            DO
            BEGIN
                IF (:CLASS_TYPE < 198) THEN
                BEGIN
                    VAL3 = VAL3 + X;
                END
                ELSE
                BEGIN
                    VAL4 = VAL4 + X;
                END
            END
        END

        IF ((I$N = 3) AND
            (LISTVAL_ID = 27)) THEN
        BEGIN
            FOR SELECT
                    V592.LISTVAL_ID,
                    COUNT(DISTINCT R.CLASS_ID)
                FROM LINKS L8
                JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID
                  AND V49.PARAM_ID = 49
                  AND V49.IS_DEL = 0
                JOIN REPORT_OSH1 R ON V49.LISTVAL_ID = R.STAGE_LISTVAL_ID
                JOIN VALL V592 ON V592.OBJ_ID = R.CLASS_ID
                  AND V592.PARAM_ID = 592
                  AND V592.IS_DEL = 0
                WHERE L8.PARENT_ID = :GRADE_ID
                  AND L8.OBJ_TYPE_ID = 8
                  AND L8.DATE_DEL IS NULL
                GROUP BY V592.LISTVAL_ID
                INTO :CLASS_TYPE, :X
            DO
            BEGIN
                IF (:CLASS_TYPE < 198) THEN
                BEGIN
                    VAL3 = VAL3 + X;
                END
                ELSE
                BEGIN
                    VAL4 = VAL4 + X;
                END
            END
        END

        IF ((I$N = 4) AND
            ((LISTVAL_ID = 21) OR (LISTVAL_ID = 22) OR (LISTVAL_ID = 26) OR (LISTVAL_ID = 27))) THEN
        BEGIN
            FOR SELECT
                    V592.LISTVAL_ID,
                    COUNT(DISTINCT R.CLASS_ID)
                FROM LINKS L8
                JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID
                  AND V49.PARAM_ID = 49
                  AND V49.IS_DEL = 0
                JOIN REPORT_OSH1 R ON V49.LISTVAL_ID = R.STAGE_LISTVAL_ID
                JOIN VALL V592 ON V592.OBJ_ID = R.CLASS_ID
                  AND V592.PARAM_ID = 592
                  AND V592.IS_DEL = 0
                WHERE L8.PARENT_ID = :GRADE_ID
                  AND L8.OBJ_TYPE_ID = 8
                  AND L8.DATE_DEL IS NULL
                GROUP BY V592.LISTVAL_ID
                INTO :CLASS_TYPE, :X
            DO
            BEGIN
                IF (:CLASS_TYPE < 198) THEN
                BEGIN
                    VAL3 = VAL3 + X;
                END
                ELSE
                BEGIN
                    VAL4 = VAL4 + X;
                END
            END
        END

        IF ((I$N = 5) AND
            ((LISTVAL_ID = 21) OR (LISTVAL_ID = 22) OR (LISTVAL_ID = 26) OR (LISTVAL_ID = 27))) THEN
        BEGIN
            FOR SELECT
                    V592.LISTVAL_ID,
                    COUNT(R.SCHOLAR_ID)
                FROM LINKS L8
                JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID
                  AND V49.PARAM_ID = 49
                  AND V49.IS_DEL = 0
                JOIN REPORT_OSH1 R ON V49.LISTVAL_ID = R.STAGE_LISTVAL_ID
                JOIN VALL V592 ON V592.OBJ_ID = R.CLASS_ID
                  AND V592.PARAM_ID = 592
                  AND V592.IS_DEL = 0
                WHERE L8.PARENT_ID = :GRADE_ID
                  AND L8.OBJ_TYPE_ID = 8
                  AND L8.DATE_DEL IS NULL
                GROUP BY V592.LISTVAL_ID, CLASS_ID
                INTO :CLASS_TYPE, :C
            DO
            BEGIN
                IF (C < 15) THEN
                BEGIN
                    IF (:CLASS_TYPE < 198) THEN
                    BEGIN
                        VAL3 = VAL3 + X;
                    END
                    ELSE
                    BEGIN
                        VAL4 = VAL4 + X;
                    END
                END
            END
        END
    END

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OSH1_301DTL (
    I$OBJ_ID BIGINT NOT NULL,
    STAGE_NUM SMALLINT NOT NULL,
    STAGE_NUM2 SMALLINT)
RETURNS (
    VAL3 VARCHAR(250))
AS
BEGIN
    STAGE_NUM = :STAGE_NUM + 1;
    STAGE_NUM2 = :STAGE_NUM2 + 1;
    FOR
        SELECT DISTINCT CLASS
        FROM LINKS L8
        JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID
          AND V49.PARAM_ID = 49
          AND V49.IS_DEL = 0
        JOIN REPORT_OSH1 R ON V49.LISTVAL_ID = R.STAGE_LISTVAL_ID
        JOIN VALL V592 ON V592.OBJ_ID = R.CLASS_ID
          AND V592.PARAM_ID = 592
          AND V592.IS_DEL = 0
          AND ((:STAGE_NUM2 = 3 AND V592.LISTVAL_ID < 198)
            OR (:STAGE_NUM2 = 4 AND V592.LISTVAL_ID > 197))

        WHERE L8.OBJ_TYPE_ID = 8
          AND L8.DATE_DEL IS NULL
          AND L8.PARENT_ID IN (
            SELECT L7.OBJ_ID
            FROM LINKS L7
            INNER JOIN VALL V43 ON V43.OBJ_ID = L7.OBJ_ID
            WHERE L7.PARENT_ID = :I$OBJ_ID
              AND L7.OBJ_TYPE_ID = 7
              AND L7.DATE_DEL IS NULL
              AND V43.PARAM_ID = 43
              AND V43.IS_DEL = 0
              AND ((:STAGE_NUM IN (1,4,5) AND V43.LISTVAL_ID BETWEEN 21 and 22)
                OR (:STAGE_NUM IN (2,4,5) AND V43.LISTVAL_ID = 26)
                OR (:STAGE_NUM IN (3,4,5) AND V43.LISTVAL_ID = 27))
              AND (:STAGE_NUM <> 5 OR (
                SELECT COUNT(1) FROM REPORT_OSH1 R2
                JOIN VALL V592 ON V592.OBJ_ID = R2.CLASS_ID
                  AND V592.PARAM_ID = 592
                  AND V592.IS_DEL = 0
                  AND ((:STAGE_NUM2 = 3 AND V592.LISTVAL_ID < 198)
                    OR (:STAGE_NUM2 = 4 AND V592.LISTVAL_ID > 197))
                WHERE R2.CLASS_ID = R.CLASS_ID) < 15)
            )
        INTO :VAL3
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OSH1_40 (
    I$OBJ_ID BIGINT)
RETURNS (
    PRAV_FORMA VARCHAR(1))
AS
BEGIN
    PRAV_FORMA = 1;

    SELECT 2
    FROM VALL VL
    WHERE VL.OBJ_ID = :I$OBJ_ID
      AND VL.PARAM_ID = 8
      AND VL.IS_DEL = 0
      AND VL.LISTVAL_ID = 1735
    INTO :PRAV_FORMA;

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OSH1_401 (
    I$OBJ_ID BIGINT,
    I$STAGE_LISTVAL_ID BIGINT,
    I$DT DATE = CURRENT_DATE)
RETURNS (
    V03 INTEGER,
    V04 INTEGER,
    V05 INTEGER,
    V06 INTEGER,
    V07 INTEGER,
    V08 INTEGER,
    V09 INTEGER,
    V10 INTEGER,
    V11 INTEGER,
    V12 INTEGER,
    V13 INTEGER,
    V14 INTEGER,
    V15 INTEGER,
    V16 INTEGER,
    V17 INTEGER,
    V18 INTEGER,
    V19 INTEGER,
    V20 INTEGER,
    V21 INTEGER,
    V22 INTEGER,
    V23 INTEGER)
AS
DECLARE VARIABLE CLASS_ID BIGINT;
DECLARE VARIABLE CLASS_TYPE BIGINT;
DECLARE VARIABLE SCHOOLAR_ID BIGINT;
DECLARE VARIABLE SEX_ID BIGINT;
DECLARE VARIABLE X INTEGER;
DECLARE VARIABLE V$YEAR INTEGER;
BEGIN
    V03 = 0;
    V04 = 0; V14 = 0;
    V05 = 0; V15 = 0;
    V06 = 0; V16 = 0;
    V07 = 0; V17 = 0;
    V08 = 0; V18 = 0;
    V09 = 0; V19 = 0;
    V10 = 0; V20 = 0;
    V11 = 0; V21 = 0;
    V12 = 0; V22 = 0;
    V13 = 0; V23 = 0;
    V$YEAR = COALESCE(:V$YEAR, (SELECT Y FROM OSH1_YEAR_GET(0, :I$DT)));

    FOR SELECT DISTINCT R.CLASS_ID, V592.LISTVAL_ID
        FROM REPORT_OSH1 R
        LEFT JOIN VALL V592 ON V592.OBJ_ID = R.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0
        WHERE R.STAGE_LISTVAL_ID = :I$STAGE_LISTVAL_ID
        INTO :CLASS_ID, :CLASS_TYPE
    DO
    BEGIN
        V03 = V03 + 1;

        IF (CLASS_TYPE = 11399) THEN
            V08 = V08 + 1;
        IF (CLASS_TYPE = 11402) THEN
            V10 = V10 + 1;
        IF (CLASS_TYPE = 11400) THEN
            V12 = V12 + 1;
        IF (CLASS_TYPE = 11401) THEN
            V14 = V14 + 1;
        IF (CLASS_TYPE = 11398) THEN
            V16 = V16 + 1;
        IF (CLASS_TYPE = 1732) THEN
            V18 = V18 + 1;
        IF (CLASS_TYPE = 199) THEN
            V20 = V20 + 1;
        IF (CLASS_TYPE = 198) THEN
            V22 = V22 + 1;

        FOR SELECT R.SCHOLAR_ID, V88.LISTVAL_ID
            FROM REPORT_OSH1 R
            INNER JOIN VALL V88 ON V88.OBJ_ID = R.SCHOLAR_ID
            WHERE R.CLASS_ID = :CLASS_ID
              AND V88.PARAM_ID = 88
              AND V88.IS_DEL = 0
            INTO :SCHOOLAR_ID, :SEX_ID
        DO
        BEGIN
            V04 = V04 + 1;
            V05 = 0;

            X = 0;

            SELECT FIRST 1 1
            FROM LINKS L76
            INNER JOIN VALL V432 ON V432.OBJ_ID = L76.OBJ_ID
            INNER JOIN VALL V436 ON V436.OBJ_ID = L76.OBJ_ID
            INNER JOIN VALD V433 ON V433.OBJ_ID = L76.OBJ_ID
            WHERE L76.PARENT_ID = :SCHOOLAR_ID
              AND L76.OBJ_TYPE_ID = 76
              AND L76.DATE_DEL IS NULL
              AND V432.PARAM_ID = 432
              AND V432.IS_DEL = 0
              AND V432.LISTVAL_ID = 810
              AND V436.PARAM_ID = 436
              AND V436.IS_DEL = 0
              AND V436.LISTVAL_ID = :I$STAGE_LISTVAL_ID
              AND V433.PARAM_ID = 433
              AND V433.IS_DEL = 0
              AND EXTRACT(YEAR FROM V433.VAL) = :V$YEAR
            INTO :X;

            V06 = V06 + X;

            IF (SEX_ID = 182) THEN
                V07 = V07 + 1;

            IF (CLASS_TYPE = 11399) THEN
                V09 = V09 + 1;
            IF (CLASS_TYPE = 11402) THEN
                V11 = V11 + 1;
            IF (CLASS_TYPE = 11400) THEN
                V13 = V13 + 1;
            IF (CLASS_TYPE = 11401) THEN
                V15 = V15 + 1;
            IF (CLASS_TYPE = 11398) THEN
                V17 = V17 + 1;
            IF (CLASS_TYPE = 1732) THEN
                V19 = V19 + 1;
            IF (CLASS_TYPE = 199) THEN
                V21 = V21 + 1;
            IF (CLASS_TYPE = 198) THEN
                V23 = V23 + 1;

        END
    END

    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OSH1_401DTL (
    I$OBJ_ID BIGINT NOT NULL,
    STAGE_NUM SMALLINT NOT NULL,
    STAGE_NUM2 SMALLINT NOT NULL,
    I$DT DATE = CURRENT_DATE)
RETURNS (
    VAL1 VARCHAR(250),
    VAL2 VARCHAR(250),
    VAL3 VARCHAR(250))
AS
DECLARE VARIABLE V$YEAR INTEGER;
BEGIN
    V$YEAR = COALESCE(:V$YEAR, (SELECT Y FROM OSH1_YEAR_GET(0, :I$DT)));
    STAGE_NUM2 = :STAGE_NUM2 + 1;
    IF (:STAGE_NUM BETWEEN 2 AND 13) THEN
    BEGIN
        STAGE_NUM = :STAGE_NUM - 1;
    END
    IF (:STAGE_NUM > 13) THEN
    BEGIN
        STAGE_NUM = :STAGE_NUM + 1;
    END
    ELSE
    BEGIN
        STAGE_NUM = :STAGE_NUM + 36;
    END
    IF (:STAGE_NUM = 17) THEN
    BEGIN
        FOR
            SELECT (SELECT CAPTION FROM OBJECT_CAPTION_GET(R.SCHOLAR_ID))
            FROM REPORT_OSH1 R
            INNER JOIN VALL V118 ON V118.OBJ_ID = R.SCHOLAR_ID
            WHERE R.STAGE_LISTVAL_ID BETWEEN 36 AND 48
              AND V118.PARAM_ID = 118
              AND V118.IS_DEL = 0
              AND V118.LISTVAL_ID = 206
            INTO :VAL3
        DO
        BEGIN
            SUSPEND;
        END
    END
    ELSE IF (:STAGE_NUM2 IN (3, 8, 10, 12, 14, 16, 18, 20, 22)) THEN
    BEGIN
        FOR
            SELECT DISTINCT R.CLASS
            FROM REPORT_OSH1 R
            LEFT JOIN VALL V592 ON V592.OBJ_ID = R.CLASS_ID
              AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0
            WHERE (:STAGE_NUM = 15 OR R.STAGE_LISTVAL_ID = :STAGE_NUM)
              AND ((:STAGE_NUM2 = 3)
                OR (:STAGE_NUM2 = 8 AND V592.LISTVAL_ID = 11399)
                OR (:STAGE_NUM2 =10 AND V592.LISTVAL_ID = 11402)
                OR (:STAGE_NUM2 =12 AND V592.LISTVAL_ID = 11400)
                OR (:STAGE_NUM2 =14 AND V592.LISTVAL_ID = 11401)
                OR (:STAGE_NUM2 =16 AND V592.LISTVAL_ID = 11398)
                OR (:STAGE_NUM2 =18 AND V592.LISTVAL_ID = 1732)
                OR (:STAGE_NUM2 =20 AND V592.LISTVAL_ID = 199)
                OR (:STAGE_NUM2 =22 AND V592.LISTVAL_ID = 198))
            INTO :VAL3
        DO
        BEGIN
            SUSPEND;
        END
    END
    ELSE
    BEGIN
        FOR
            SELECT
                (SELECT CAPTION FROM OBJECT_CAPTION_GET(SCHOLAR_ID)) VAL1,
                (SELECT D FROM VAL_GET(SCHOLAR_ID, 89)) VAL2,
                CLASS VAL3
            FROM (
                SELECT R.SCHOLAR_ID, R.CLASS

                FROM REPORT_OSH1 R
                LEFT JOIN VALL V592 ON V592.OBJ_ID = R.CLASS_ID
                  AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0

                JOIN VALL V88
                ON V88.OBJ_ID = R.SCHOLAR_ID
                AND V88.PARAM_ID = 88
                AND V88.IS_DEL = 0

                WHERE (:STAGE_NUM = 15 OR R.STAGE_LISTVAL_ID = :STAGE_NUM)
                AND R.CLASS_ID IS NOT NULL
                AND (:STAGE_NUM2 <> 6 OR R.SCHOLAR_ID IN (
                    SELECT L76.PARENT_ID
                    FROM LINKS L76

                    JOIN VALL V432
                    ON V432.OBJ_ID = L76.OBJ_ID
                    AND V432.PARAM_ID = 432
                    AND V432.IS_DEL = 0
                    AND (V432.LISTVAL_ID = 810 OR (:STAGE_NUM2 = 7))

                    JOIN VALL V436
                    ON V436.OBJ_ID = L76.OBJ_ID
                    AND V436.PARAM_ID = 436
                    AND V436.IS_DEL = 0
                    AND (:STAGE_NUM = 15 OR V436.LISTVAL_ID = :STAGE_NUM)

                    JOIN VALD V433
                    ON V433.OBJ_ID = L76.OBJ_ID
                    AND V433.PARAM_ID = 433
                    AND V433.IS_DEL = 0
                    AND EXTRACT(YEAR FROM V433.VAL) = :V$YEAR

                    WHERE L76.OBJ_TYPE_ID = 76
                    AND L76.DATE_DEL IS NULL))

                AND (:STAGE_NUM2 NOT IN (7, 9, 11, 13, 15, 17, 19, 21, 23)
                    OR (:STAGE_NUM2 = 7 AND V88.LISTVAL_ID = 182)
                    OR (:STAGE_NUM2 = 9 AND V592.LISTVAL_ID = 11399)
                    OR (:STAGE_NUM2 =11 AND V592.LISTVAL_ID = 11402)
                    OR (:STAGE_NUM2 =13 AND V592.LISTVAL_ID = 11400)
                    OR (:STAGE_NUM2 =15 AND V592.LISTVAL_ID = 11401)
                    OR (:STAGE_NUM2 =17 AND V592.LISTVAL_ID = 11398)
                    OR (:STAGE_NUM2 =19 AND V592.LISTVAL_ID = 1732)
                    OR (:STAGE_NUM2 =21 AND V592.LISTVAL_ID = 199)
                    OR (:STAGE_NUM2 =23 AND V592.LISTVAL_ID = 198)
                      )
            ) ORDER BY VAL1
            INTO :VAL1, :VAL2, :VAL3
        DO
        BEGIN
            SUSPEND;
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OSH1_418 (
    I$OBJ_ID BIGINT,
    I$DT DATE = CURRENT_DATE)
RETURNS (
    V03 INTEGER,
    V04 INTEGER,
    V05 INTEGER,
    V06 INTEGER,
    V07 INTEGER,
    V08 INTEGER,
    V09 INTEGER,
    V10 INTEGER,
    V11 INTEGER,
    V12 INTEGER,
    V13 INTEGER,
    V14 INTEGER,
    V15 INTEGER,
    V16 INTEGER,
    V17 INTEGER,
    V18 INTEGER,
    V19 INTEGER,
    V20 INTEGER,
    V21 INTEGER,
    V22 INTEGER,
    V23 INTEGER)
AS
DECLARE VARIABLE CLASS_ID BIGINT;
DECLARE VARIABLE CLASS_TYPE BIGINT;
DECLARE VARIABLE SCHOOLAR_ID BIGINT;
DECLARE VARIABLE SEX_ID BIGINT;
DECLARE VARIABLE X INTEGER;
DECLARE VARIABLE V$YEAR INTEGER;
BEGIN
    V03 = 0;
    V04 = 0;
    V05 = 0;
    V06 = 0;
    V07 = 0;
    V08 = 0;
    V09 = 0;
    V10 = 0;
    V11 = 0;
    V12 = 0;
    V13 = 0;
    V$YEAR = COALESCE(:V$YEAR, (SELECT Y FROM OSH1_YEAR_GET(0, :I$DT)));

    FOR SELECT DISTINCT R.CLASS_ID, V592.LISTVAL_ID
        FROM REPORT_OSH1 R
        LEFT JOIN VALL V592 ON V592.OBJ_ID = R.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0
        WHERE R.STAGE_LISTVAL_ID >= 36
          AND R.STAGE_LISTVAL_ID <= 48
        INTO :CLASS_ID, :CLASS_TYPE
    DO
    BEGIN
        V03 = V03 + 1;

        IF (CLASS_TYPE = 11399) THEN
            V08 = V08 + 1;
        IF (CLASS_TYPE = 11402) THEN
            V10 = V10 + 1;
        IF (CLASS_TYPE = 11400) THEN
            V12 = V12 + 1;
        IF (CLASS_TYPE = 11401) THEN
            V14 = V14 + 1;
        IF (CLASS_TYPE = 11398) THEN
            V16 = V16 + 1;
        IF (CLASS_TYPE = 1732) THEN
            V18 = V18 + 1;
        IF (CLASS_TYPE = 199) THEN
            V20 = V20 + 1;
        IF (CLASS_TYPE = 198) THEN
            V22 = V22 + 1;

        FOR SELECT R.SCHOLAR_ID, V88.LISTVAL_ID
            FROM REPORT_OSH1 R
            INNER JOIN VALL V88 ON V88.OBJ_ID = R.SCHOLAR_ID
            WHERE R.CLASS_ID = :CLASS_ID
              AND V88.PARAM_ID = 88
              AND V88.IS_DEL = 0
            INTO :SCHOOLAR_ID, :SEX_ID
        DO
        BEGIN
            V04 = V04 + 1;
            V05 = 0;

            X = 0;

            SELECT FIRST 1 1
            FROM LINKS L76
            INNER JOIN VALL V432 ON V432.OBJ_ID = L76.OBJ_ID
            INNER JOIN VALL V436 ON V436.OBJ_ID = L76.OBJ_ID
            INNER JOIN VALD V433 ON V433.OBJ_ID = L76.OBJ_ID
            WHERE L76.PARENT_ID = :SCHOOLAR_ID
              AND L76.OBJ_TYPE_ID = 76
              AND L76.DATE_DEL IS NULL
              AND V432.PARAM_ID = 432
              AND V432.IS_DEL = 0
              AND V432.LISTVAL_ID = 810
              AND V436.PARAM_ID = 436
              AND V436.IS_DEL = 0
              AND V436.LISTVAL_ID >= 36
              AND V436.LISTVAL_ID <= 48
              AND V433.PARAM_ID = 433
              AND V433.IS_DEL = 0
              AND EXTRACT(YEAR FROM V433.VAL) = :V$YEAR
            INTO :X;

            V06 = V06 + X;

            IF (SEX_ID = 182) THEN
                V07 = V07 + 1;

            IF (CLASS_TYPE = 11399) THEN
                V09 = V09 + 1;
            IF (CLASS_TYPE = 11402) THEN
                V11 = V11 + 1;
            IF (CLASS_TYPE = 11400) THEN
                V13 = V13 + 1;
            IF (CLASS_TYPE = 11401) THEN
                V15 = V15 + 1;
            IF (CLASS_TYPE = 11398) THEN
                V17 = V17 + 1;
            IF (CLASS_TYPE = 1732) THEN
                V19 = V19 + 1;
            IF (CLASS_TYPE = 199) THEN
                V21 = V21 + 1;
            IF (CLASS_TYPE = 198) THEN
                V23 = V23 + 1;

        END
    END

    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OSH1_419 (
    I$OBJ_ID BIGINT)
RETURNS (
    V INTEGER)
AS
BEGIN
    SELECT COUNT(*)
    FROM REPORT_OSH1 R
    INNER JOIN VALL V118 ON V118.OBJ_ID = R.SCHOLAR_ID
    WHERE R.STAGE_LISTVAL_ID >= 36
      AND R.STAGE_LISTVAL_ID <= 48
      AND V118.PARAM_ID = 118
      AND V118.IS_DEL = 0
      AND V118.LISTVAL_ID = 206
    INTO :V;

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OSH1_501 (
    I$OBJ_ID BIGINT,
    I$YEARS_OLD SMALLINT,
    I$MONTH_DELTA SMALLINT = 0,
    I$INVALID_ONLY SMALLINT = 0,
    I$DT DATE = current_date)
RETURNS (
    V3 INTEGER,
    V4 INTEGER,
    V5 INTEGER,
    V6 INTEGER,
    V7 INTEGER,
    V8 INTEGER,
    V9 INTEGER)
AS
declare variable V$STAGE_ID bigint;
declare variable V$SEX_ID bigint;
declare variable VIPUSK_ID bigint;
declare variable Y integer;
BEGIN
    V3 = 0;
    V4 = 0;
    V5 = 0;
    V6 = 0;
    V7 = 0;
    V8 = 0;
    V9 = 0;

    SELECT Y FROM OSH1_YEAR_GET(:I$YEARS_OLD, :I$DT) INTO :Y;

    FOR
        SELECT V88.LISTVAL_ID,
               R.STAGE_LISTVAL_ID,
               V2388.LISTVAL_ID
        FROM (
            SELECT
                R.STAGE_LISTVAL_ID,
                R.CLASS_ID,
                R.SCHOLAR_ID
            FROM REPORT_OSH1 R
            JOIN VALL V592 ON V592.OBJ_ID = R.CLASS_ID
              AND V592.PARAM_ID = 592
              AND V592.IS_DEL = 0
              AND V592.LISTVAL_ID < 198
            WHERE :I$DT <> CURRENT_DATE
              AND R.CLASS_ID IS NOT NULL

            UNION
            SELECT
                V49.LISTVAL_ID,
                L9.OBJ_ID,
                L10.OBJ_ID
            FROM LINKS L7
    
            JOIN LINKS L8
            ON L8.PARENT_ID = L7.OBJ_ID
            AND L8.OBJ_TYPE_ID = 8
            AND L8.DATE_DEL IS NULL
    
            JOIN VALL V49
            ON V49.OBJ_ID = L8.OBJ_ID
            AND V49.PARAM_ID = 49
            AND V49.IS_DEL = 0
    
            JOIN LINKS L9
            ON L9.PARENT_ID = L8.OBJ_ID
            AND L9.OBJ_TYPE_ID = 9
            AND L9.DATE_DEL IS NULL
    
            JOIN VALL V592 ON V592.OBJ_ID = L9.OBJ_ID
              AND V592.PARAM_ID = 592
              AND V592.IS_DEL = 0
              AND V592.LISTVAL_ID < 198

            JOIN LINKS L10
            ON L10.PARENT_ID = L9.OBJ_ID
            AND L10.OBJ_TYPE_ID = 10
            AND L10.DATE_DEL IS NULL

            WHERE L7.PARENT_ID = :I$OBJ_ID
            AND :I$DT = CURRENT_DATE
            AND L7.OBJ_TYPE_ID = 7
            AND L7.DATE_DEL IS NULL
        ) R

        JOIN VALD V89
        ON V89.OBJ_ID = R.SCHOLAR_ID
        AND V89.PARAM_ID = 89
        AND V89.IS_DEL = 0
        AND EXTRACT(YEAR FROM DATEADD(-:I$MONTH_DELTA MONTH TO V89.VAL)) = :Y
--        AND DATEDIFF (YEAR FROM V89.VAL TO :V$CALC_DATE) = :I$YEARS_OLD

        JOIN VALL V88
        ON V88.OBJ_ID = R.SCHOLAR_ID
        AND V88.PARAM_ID = 88
        AND V88.IS_DEL = 0

        LEFT JOIN VALL V2388
        ON V2388.OBJ_ID = R.CLASS_ID
        AND V2388.PARAM_ID IN (2388,2418)
        AND V2388.IS_DEL = 0

        WHERE :I$INVALID_ONLY <> 1 OR EXISTS(
            SELECT FIRST 1 1
            FROM LINKS L12
            JOIN VALL V51 ON V51.OBJ_ID = L12.OBJ_ID
              AND V51.PARAM_ID = 51
              AND V51.IS_DEL = 0
              AND V51.LISTVAL_ID = 1385
            WHERE L12.PARENT_ID = R.SCHOLAR_ID
              AND L12.OBJ_TYPE_ID = 12
              AND L12.DATE_DEL IS NULL)

        INTO :V$SEX_ID,
             :V$STAGE_ID,
             :VIPUSK_ID
    DO
    BEGIN
        V3 = V3 + 1;
        IF (V$SEX_ID = 182) THEN
        BEGIN
            V4 = V4 + 1;
        END
        IF (V$STAGE_ID = 36) THEN
        BEGIN
            V5 = V5 + 1;
        END
        IF (V$STAGE_ID = 37) THEN
        BEGIN
            V6 = V6 + 1;
        END
        IF (V$STAGE_ID = 45) THEN
        BEGIN
            V7 = V7 + 1;
        END
        IF (V$STAGE_ID IN (46, 47, 48)) THEN
        BEGIN
            V8 = V8 + 1;
            IF (VIPUSK_ID <> 11217) THEN
            BEGIN
                V9 = V9 + 1;
            END
        END
    END

    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OSH1_501DTL (
    I$OBJ_ID BIGINT NOT NULL,
    STAGE_NUM SMALLINT NOT NULL,
    STAGE_NUM2 SMALLINT NOT NULL,
    I$DT DATE = current_date,
    I$MONTH_DELTA SMALLINT = 0,
    I$INVALID_ONLY SMALLINT = 0)
RETURNS (
    VAL1 VARCHAR(250),
    VAL2 VARCHAR(250),
    VAL3 VARCHAR(250))
AS
declare variable Y integer;
declare variable V$YEARS_OLD smallint;
BEGIN
    STAGE_NUM2 = :STAGE_NUM2 - 2;
    STAGE_NUM = :STAGE_NUM + 5;

    V$YEARS_OLD = IIF(STAGE_NUM > 23, 5, STAGE_NUM) ;
    SELECT Y FROM OSH1_YEAR_GET(:V$YEARS_OLD, :I$DT) INTO :Y;

--    Y = EXTRACT(YEAR FROM CURRENT_DATE) - IIF(:STAGE_NUM = 24, 5, :STAGE_NUM) - 1;
--    Y = IIF(:STAGE_NUM = 28, Y + 12, Y);
    FOR
        SELECT
            (SELECT CAPTION FROM OBJECT_CAPTION_GET(SCHOLAR_ID)) VAL1,
            (SELECT D FROM VAL_GET(SCHOLAR_ID, 89)) VAL2,
            (SELECT CAPTION FROM OBJECT_CAPTION_GET
                ((SELECT PARENT_ID
                 FROM LINKS
                 WHERE LINK_ID =
                     (SELECT MAX(L.LINK_ID)
                      FROM LINKS L
                      WHERE L.OBJ_ID = SCHOLAR_ID
                        AND L.PARENT_TYPE_ID IN (9,10,81,82,83)
                        AND l.DATE_DEL IS NULL
                     )
                ))
            ) VAL3
        FROM (
            SELECT R.SCHOLAR_ID
            FROM (
                SELECT
                    R.STAGE_LISTVAL_ID,
                    R.CLASS_ID,
                    R.SCHOLAR_ID
                FROM REPORT_OSH1 R
                JOIN VALL V592 ON V592.OBJ_ID = R.CLASS_ID
                  AND V592.PARAM_ID = 592
                  AND V592.IS_DEL = 0
                  AND V592.LISTVAL_ID < 198
                WHERE :I$DT <> CURRENT_DATE
                  AND R.CLASS_ID IS NOT NULL
    
                UNION
                SELECT
                    V49.LISTVAL_ID,
                    L9.OBJ_ID,
                    L10.OBJ_ID
                FROM LINKS L7
    
                JOIN LINKS L8
                ON L8.PARENT_ID = L7.OBJ_ID
                AND L8.OBJ_TYPE_ID = 8
                AND L8.DATE_DEL IS NULL
    
                JOIN VALL V49
                ON V49.OBJ_ID = L8.OBJ_ID
                AND V49.PARAM_ID = 49
                AND V49.IS_DEL = 0
    
                JOIN LINKS L9
                ON L9.PARENT_ID = L8.OBJ_ID
                AND L9.OBJ_TYPE_ID = 9
                AND L9.DATE_DEL IS NULL
    
                JOIN VALL V592 ON V592.OBJ_ID = L9.OBJ_ID
                  AND V592.PARAM_ID = 592
                  AND V592.IS_DEL = 0
                  AND V592.LISTVAL_ID < 198
    
                JOIN LINKS L10
                ON L10.PARENT_ID = L9.OBJ_ID
                AND L10.OBJ_TYPE_ID = 10
                AND L10.DATE_DEL IS NULL
    
                WHERE L7.PARENT_ID = :I$OBJ_ID
                AND :I$DT = CURRENT_DATE
                AND L7.OBJ_TYPE_ID = 7
                AND L7.DATE_DEL IS NULL
            ) R

            JOIN VALD V89
            ON V89.OBJ_ID = R.SCHOLAR_ID
            AND V89.PARAM_ID = 89
            AND V89.IS_DEL = 0
            AND (:STAGE_NUM < 0
             OR ((:STAGE_NUM < 23 AND EXTRACT(YEAR FROM DATEADD(-:I$MONTH_DELTA MONTH TO V89.VAL)) = :Y)
              OR (:STAGE_NUM > 22 AND EXTRACT(YEAR FROM V89.VAL) <= :Y)))
/*            AND ((:STAGE_NUM < 23 AND DATEDIFF (YEAR FROM V89.VAL TO :V$CALC_DATE) = :V$YEARS_OLD)
                OR (:STAGE_NUM > 22 AND DATEDIFF (YEAR FROM V89.VAL TO :V$CALC_DATE) >= :V$YEARS_OLD)
            )*/

            JOIN VALL V88
            ON V88.OBJ_ID = R.SCHOLAR_ID
            AND V88.PARAM_ID = 88
            AND V88.IS_DEL = 0

            LEFT JOIN VALL V2388
            ON V2388.OBJ_ID = R.CLASS_ID
            AND V2388.PARAM_ID IN (2388,2418)
            AND V2388.IS_DEL = 0

            WHERE (:I$INVALID_ONLY <> 1 OR EXISTS(
                SELECT FIRST 1 1
                FROM LINKS L12
                JOIN VALL V51 ON V51.OBJ_ID = L12.OBJ_ID
                  AND V51.PARAM_ID = 51
                  AND V51.IS_DEL = 0
                  AND V51.LISTVAL_ID = 1385
                WHERE L12.PARENT_ID = R.SCHOLAR_ID
                  AND L12.OBJ_TYPE_ID = 12
                  AND L12.DATE_DEL IS NULL))

            AND (:STAGE_NUM2 = 3
               OR (:STAGE_NUM2 = 4 AND V88.LISTVAL_ID = 182)
               OR (:STAGE_NUM2 = 5 AND R.STAGE_LISTVAL_ID = 36)
               OR (:STAGE_NUM2 = 6 AND R.STAGE_LISTVAL_ID = 37)
               OR (:STAGE_NUM2 = 7 AND R.STAGE_LISTVAL_ID = 45)
               OR (:STAGE_NUM2 = 8 AND R.STAGE_LISTVAL_ID BETWEEN 46 AND 48)
               OR (:STAGE_NUM2 = 9 AND R.STAGE_LISTVAL_ID BETWEEN 46 AND 48 AND V2388.LISTVAL_ID <> 11217)
            )
            AND :STAGE_NUM < 25

            UNION

            SELECT R.SCHOLAR_ID
            FROM (
                SELECT
                    CLASS_ID,
                    SCHOLAR_ID
                FROM REPORT_OSH1
                WHERE :I$DT <> CURRENT_DATE
                  AND CLASS_ID IS NOT NULL
                  AND :STAGE_NUM = 28
    
                UNION
                SELECT
                    L9.OBJ_ID,
                    L10.OBJ_ID
                FROM LINKS L7
    
                JOIN LINKS L8
                ON L8.PARENT_ID = L7.OBJ_ID
                AND L8.OBJ_TYPE_ID = 8
                AND L8.DATE_DEL IS NULL

                JOIN LINKS L9
                ON L9.PARENT_ID = L8.OBJ_ID
                AND L9.OBJ_TYPE_ID = 9
                AND L9.DATE_DEL IS NULL
    
                JOIN LINKS L10
                ON L10.PARENT_ID = L9.OBJ_ID
                AND L10.OBJ_TYPE_ID = 10
                AND L10.DATE_DEL IS NULL
    
                WHERE L7.PARENT_ID = :I$OBJ_ID
                AND :I$DT = CURRENT_DATE
                AND L7.OBJ_TYPE_ID = 7
                AND L7.DATE_DEL IS NULL
                AND :STAGE_NUM = 28
            ) R
            JOIN VALL V592
            ON V592.OBJ_ID = R.CLASS_ID
            AND V592.PARAM_ID = 592
            AND V592.IS_DEL = 0
            AND V592.LISTVAL_ID > 197

            JOIN VALD V89
            ON V89.OBJ_ID = R.SCHOLAR_ID
            AND V89.PARAM_ID = 89
            AND V89.IS_DEL = 0
            AND EXTRACT(YEAR FROM V89.VAL) <= :Y
--            AND DATEDIFF (YEAR FROM V89.VAL TO :V$CALC_DATE) >= :V$YEARS_OLD

            JOIN VALL V88
            ON V88.OBJ_ID = R.SCHOLAR_ID
            AND V88.PARAM_ID = 88
            AND V88.IS_DEL = 0

        ) ORDER BY VAL1
        INTO :VAL1, :VAL2, :VAL3
    DO
    BEGIN
        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OSH1_514 (
    I$OBJ_ID BIGINT,
    I$YEARS_OLD SMALLINT = 23,
    I$DT DATE = CURRENT_DATE)
RETURNS (
    V3 INTEGER,
    V4 INTEGER,
    V5 INTEGER,
    V6 INTEGER,
    V7 INTEGER,
    V8 INTEGER,
    V9 INTEGER)
AS
DECLARE VARIABLE Y INTEGER;
DECLARE VARIABLE STAGE_ID BIGINT;
DECLARE VARIABLE SEX_ID BIGINT;
DECLARE VARIABLE VIPUSK_ID BIGINT;
BEGIN
    V3 = 0;
    V4 = 0;
    V5 = 0;
    V6 = 0;
    V7 = 0;
    V8 = 0;
    V9 = 0;

--    Y = EXTRACT(YEAR FROM CURRENT_DATE) - 23 - 1;
    SELECT Y FROM OSH1_YEAR_GET(:I$YEARS_OLD, :I$DT) INTO :Y;

    FOR
        SELECT V88.LISTVAL_ID,
               R.STAGE_LISTVAL_ID,
               V2388.LISTVAL_ID
        FROM (
            SELECT
                R.STAGE_LISTVAL_ID,
                R.CLASS_ID,
                R.SCHOLAR_ID
            FROM REPORT_OSH1 R
            JOIN VALL V592 ON V592.OBJ_ID = R.CLASS_ID
              AND V592.PARAM_ID = 592
              AND V592.IS_DEL = 0
              AND V592.LISTVAL_ID < 198
            WHERE :I$DT <> CURRENT_DATE
              AND R.CLASS_ID IS NOT NULL

            UNION
            SELECT
                V49.LISTVAL_ID,
                L9.OBJ_ID,
                L10.OBJ_ID
            FROM LINKS L7
    
            JOIN LINKS L8
            ON L8.PARENT_ID = L7.OBJ_ID
            AND L8.OBJ_TYPE_ID IN (8, 242)
            AND L8.DATE_DEL IS NULL
    
            LEFT JOIN VALL V49
            ON V49.OBJ_ID = L8.OBJ_ID
            AND V49.PARAM_ID = 49
            AND V49.IS_DEL = 0
    
            JOIN LINKS L9
            ON L9.PARENT_ID = L8.OBJ_ID
            AND L9.OBJ_TYPE_ID IN (9, 243)
            AND L9.DATE_DEL IS NULL
    
            JOIN VALL V592 ON V592.OBJ_ID = L9.OBJ_ID
              AND V592.PARAM_ID = 592
              AND V592.IS_DEL = 0
              AND V592.LISTVAL_ID < 198

            JOIN LINKS L10
            ON L10.PARENT_ID = L9.OBJ_ID
            AND L10.OBJ_TYPE_ID = 10
            AND L10.DATE_DEL IS NULL
    
            WHERE L7.PARENT_ID = :I$OBJ_ID
            AND :I$DT = CURRENT_DATE
            AND L7.OBJ_TYPE_ID IN (7, 211)
            AND L7.DATE_DEL IS NULL
        ) R
        JOIN VALD V89
        ON V89.OBJ_ID = R.SCHOLAR_ID
        AND V89.PARAM_ID = 89
        AND V89.IS_DEL = 0
        AND EXTRACT(YEAR FROM V89.VAL) <= :Y
--        AND DATEDIFF (YEAR FROM V89.VAL TO :V$CALC_DATE) >= 23

        JOIN VALL V88
        ON V88.OBJ_ID = R.SCHOLAR_ID
        AND V88.PARAM_ID = 88
        AND V88.IS_DEL = 0

        LEFT JOIN VALL V2388
        ON V2388.OBJ_ID = R.CLASS_ID
        AND V2388.PARAM_ID IN (2388, 2418)
        AND V2388.IS_DEL = 0

        INTO :SEX_ID,
             :STAGE_ID,
             :VIPUSK_ID
    DO
    BEGIN
        V3 = V3 + 1;
        IF (SEX_ID = 182) THEN
        BEGIN
            V4 = V4 + 1;
        END
        IF (STAGE_ID = 36) THEN
        BEGIN
            V5 = V5 + 1;
        END
        IF (STAGE_ID = 37) THEN
        BEGIN
            V6 = V6 + 1;
        END
        IF (STAGE_ID = 45) THEN
        BEGIN
            V7 = V7 + 1;
        END
        IF (STAGE_ID IN (46, 47, 48)) THEN
        BEGIN
            V8 = V8 + 1;
            IF (VIPUSK_ID <> 11217) THEN
            BEGIN
                V9 = V9 + 1;
            END
        END
    END

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OSH1_515 (
    I$OBJ_ID BIGINT,
    I$DT DATE = CURRENT_DATE)
RETURNS (
    V3 INTEGER,
    V4 INTEGER,
    V5 INTEGER,
    V6 INTEGER,
    V7 INTEGER,
    V8 INTEGER,
    V9 INTEGER)
AS
DECLARE VARIABLE STAGE_ID BIGINT;
DECLARE VARIABLE SEX_ID BIGINT;
DECLARE VARIABLE VIPUSK_ID BIGINT;
DECLARE VARIABLE Y INTEGER;
BEGIN
    V3 = 0;
    V4 = 0;
    V5 = 0;
    V6 = 0;
    V7 = 0;
    V8 = 0;
    V9 = 0;

--    Y = EXTRACT(YEAR FROM CURRENT_DATE) - 5 - 1;
    SELECT Y FROM OSH1_YEAR_GET(5, :I$DT) INTO :Y;

    FOR
        SELECT V88.LISTVAL_ID,
               R.STAGE_LISTVAL_ID,
               V2388.LISTVAL_ID
        FROM (
            SELECT
                R.STAGE_LISTVAL_ID,
                R.CLASS_ID,
                R.SCHOLAR_ID
            FROM REPORT_OSH1 R
            JOIN VALL V592 ON V592.OBJ_ID = R.CLASS_ID
              AND V592.PARAM_ID = 592
              AND V592.IS_DEL = 0
              AND V592.LISTVAL_ID < 198
            WHERE :I$DT <> CURRENT_DATE
              AND R.CLASS_ID IS NOT NULL

            UNION
            SELECT
                V49.LISTVAL_ID,
                L9.OBJ_ID,
                L10.OBJ_ID
            FROM LINKS L7
    
            JOIN LINKS L8
            ON L8.PARENT_ID = L7.OBJ_ID
            AND L8.OBJ_TYPE_ID = 8
            AND L8.DATE_DEL IS NULL
    
            JOIN VALL V49
            ON V49.OBJ_ID = L8.OBJ_ID
            AND V49.PARAM_ID = 49
            AND V49.IS_DEL = 0
    
            JOIN LINKS L9
            ON L9.PARENT_ID = L8.OBJ_ID
            AND L9.OBJ_TYPE_ID = 9
            AND L9.DATE_DEL IS NULL
    
            JOIN VALL V592 ON V592.OBJ_ID = L9.OBJ_ID
              AND V592.PARAM_ID = 592
              AND V592.IS_DEL = 0
              AND V592.LISTVAL_ID < 198

            JOIN LINKS L10
            ON L10.PARENT_ID = L9.OBJ_ID
            AND L10.OBJ_TYPE_ID = 10
            AND L10.DATE_DEL IS NULL
    
            WHERE L7.PARENT_ID = :I$OBJ_ID
            AND :I$DT = CURRENT_DATE
            AND L7.OBJ_TYPE_ID = 7
            AND L7.DATE_DEL IS NULL
        ) R
        JOIN VALD V89
        ON V89.OBJ_ID = R.SCHOLAR_ID
        AND V89.PARAM_ID = 89
        AND V89.IS_DEL = 0
        AND EXTRACT(YEAR FROM V89.VAL) <= :Y
--        AND DATEDIFF (YEAR FROM V89.VAL TO :V$CALC_DATE) >= 5

        JOIN VALL V88
        ON V88.OBJ_ID = R.SCHOLAR_ID
        AND V88.PARAM_ID = 88
        AND V88.IS_DEL = 0

        LEFT JOIN VALL V2388
        ON V2388.OBJ_ID = R.CLASS_ID
        AND V2388.PARAM_ID IN (2388, 2418)
        AND V2388.IS_DEL = 0

        INTO :SEX_ID,
             :STAGE_ID,
             :VIPUSK_ID
    DO
    BEGIN
        V3 = V3 + 1;
        IF (SEX_ID = 182) THEN
            V4 = V4 + 1;
        IF (STAGE_ID = 36) THEN
            V5 = V5 + 1;
        IF (STAGE_ID = 37) THEN
            V6 = V6 + 1;
        IF (STAGE_ID = 45) THEN
            V7 = V7 + 1;
        IF (STAGE_ID IN (46, 47, 48)) THEN
        BEGIN
            V8 = V8 + 1;
            IF (VIPUSK_ID <> 11217) THEN
                V9 = V9 + 1;
        END
    END

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OSH1_516 (
    I$OBJ_ID BIGINT,
    I$DT DATE = CURRENT_DATE)
RETURNS (
    V INTEGER)
AS
DECLARE VARIABLE Y INTEGER;
BEGIN
    --Y = EXTRACT(YEAR FROM CURRENT_DATE) - 16 - 1;
    SELECT Y FROM OSH1_YEAR_GET(16, :I$DT) INTO :Y;

    SELECT COUNT(*)
    FROM REPORT_OSH1 R
    INNER JOIN VALL V592 ON V592.OBJ_ID = R.CLASS_ID
    INNER JOIN VALD V89 ON V89.OBJ_ID = R.SCHOLAR_ID
    INNER JOIN VALL V88 ON V88.OBJ_ID = R.SCHOLAR_ID
    WHERE V592.PARAM_ID = 592
      AND V592.IS_DEL = 0
      AND V592.LISTVAL_ID > 197
      AND V89.PARAM_ID = 89
      AND V89.IS_DEL = 0
      AND EXTRACT(YEAR FROM V89.VAL) <= :Y
      AND V88.PARAM_ID = 88
      AND V88.IS_DEL = 0
    INTO :V;

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OSH1_601 (
    I$OBJ_ID BIGINT,
    I$DT DATE = CURRENT_DATE)
RETURNS (
    V INTEGER)
AS
DECLARE VARIABLE TEACHER_ID BIGINT;
DECLARE VARIABLE X01 INTEGER;
DECLARE VARIABLE X02 INTEGER;
DECLARE VARIABLE X03 INTEGER;
DECLARE VARIABLE X04 INTEGER;
DECLARE VARIABLE X05 INTEGER;
DECLARE VARIABLE X06 INTEGER;
DECLARE VARIABLE X07 INTEGER;
DECLARE VARIABLE X08 INTEGER;
DECLARE VARIABLE X09 INTEGER;
DECLARE VARIABLE X10 INTEGER;
DECLARE VARIABLE CORRECT_CLASS_NUM SMALLINT;
BEGIN
    V = 0;
    X02 = 0;
    X03 = 0;
    X04 = 0;
    X05 = 0;
    X06 = 0;
    X07 = 0;
    X08 = 0;
    X09 = 0;
    X10 = 0;

    FOR SELECT L14.OBJ_ID
        FROM LINKS L14
        INNER JOIN VALL V274 ON V274.OBJ_ID = L14.OBJ_ID
        WHERE L14.PARENT_ID IN (
            SELECT :I$OBJ_ID
            FROM RDB$DATABASE
            UNION
            SELECT L84.OBJ_ID
            FROM LINKS L84
            WHERE L84.PARENT_ID = :I$OBJ_ID
              AND L84.OBJ_TYPE_ID = 84
              AND L84.DATE_DEL IS NULL)
          AND L14.OBJ_TYPE_ID = 14
          AND L14.DATE_DEL IS NULL
          AND V274.PARAM_ID = 274
          AND V274.IS_DEL = 0
          AND V274.LISTVAL_ID = 602
        INTO :TEACHER_ID
    DO
    BEGIN
        X01 = 0;

        SELECT FIRST 1 1
        FROM LINKS L15
        JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0
        LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
        LEFT JOIN VALR V69 ON V69.OBJ_ID = L15.OBJ_ID
        LEFT JOIN VALL V64 ON V64.OBJ_ID = V69.VAL
        WHERE L15.PARENT_ID = :TEACHER_ID
          AND L15.OBJ_TYPE_ID = 15
          AND L15.DATE_DEL IS NULL
          AND V73.VAL <= :I$DT
          AND (V74.VAL IS NULL OR V74.VAL > :I$DT)
          AND V69.PARAM_ID = 69
          AND V69.IS_DEL = 0
          AND V64.PARAM_ID = 64
          AND V64.IS_DEL = 0
          AND V64.LISTVAL_ID = 98
        INTO :X01;

        V = V + X01;

        IF (:X01 = 1) THEN
        BEGIN
            CORRECT_CLASS_NUM = 0;

            SELECT FIRST 1
                CASE V592.LISTVAL_ID
                    WHEN 11399 THEN 3
                    WHEN 11402 THEN 4
                    WHEN 11400 THEN 5
                    WHEN 11401 THEN 6
                    WHEN 11398 THEN 7
                    WHEN 1732 THEN 8
                    WHEN 199 THEN 9
                    WHEN 198 THEN 10
                END
            FROM LINKS L14_58
            JOIN LINKS L256_58 ON L256_58.OBJ_ID = L14_58.OBJ_ID
              AND L256_58.PARENT_TYPE_ID = 256
              AND L256_58.DATE_DEL IS NULL
            JOIN LINKS L256_10 ON L256_10.PARENT_ID = L256_58.PARENT_ID
              AND L256_10.OBJ_TYPE_ID = 10
              --AND L256_10.DATE_DEL IS NULL
            JOIN LINKS L9_10 ON L9_10.OBJ_ID = L256_10.OBJ_ID
              AND L9_10.PARENT_TYPE_ID IN (9, 187)
              --AND L9_10.DATE_DEL IS NULL
            JOIN VALL V592 ON V592.OBJ_ID = L9_10.PARENT_ID
              AND V592.PARAM_ID = 592
              AND V592.IS_DEL = 0
              AND V592.LISTVAL_ID > 197
            WHERE L14_58.PARENT_ID = :TEACHER_ID
              AND L14_58.OBJ_TYPE_ID = 58
              AND L14_58.DATE_DEL IS NULL
            ORDER BY 1
            INTO :CORRECT_CLASS_NUM;

            IF (:CORRECT_CLASS_NUM > 0) THEN X02 = :X02 + 1;
            IF (:CORRECT_CLASS_NUM = 3) THEN X03 = :X03 + 1;
            IF (:CORRECT_CLASS_NUM = 4) THEN X04 = :X04 + 1;
            IF (:CORRECT_CLASS_NUM = 5) THEN X05 = :X05 + 1;
            IF (:CORRECT_CLASS_NUM = 6) THEN X06 = :X06 + 1;
            IF (:CORRECT_CLASS_NUM = 7) THEN X07 = :X07 + 1;
            IF (:CORRECT_CLASS_NUM = 8) THEN X08 = :X08 + 1;
            IF (:CORRECT_CLASS_NUM = 9) THEN X09 = :X09 + 1;
            IF (:CORRECT_CLASS_NUM =10) THEN X10 = :X10 + 1;
        END
    END

    SUSPEND;

    V = :X02;
    SUSPEND;
    V = :X03;
    SUSPEND;
    V = :X04;
    SUSPEND;
    V = :X05;
    SUSPEND;
    V = :X06;
    SUSPEND;
    V = :X07;
    SUSPEND;
    V = :X08;
    SUSPEND;
    V = :X09;
    SUSPEND;
    V = :X10;
    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OSH1_601DTL (
    I$OBJ_ID BIGINT NOT NULL,
    STAGE_NUM SMALLINT NOT NULL,
    I$DT DATE = CURRENT_DATE)
RETURNS (
    VAL1 VARCHAR(250))
AS
BEGIN
    STAGE_NUM = :STAGE_NUM + 1;
    FOR
        SELECT DISTINCT (SELECT CAPTION FROM OBJECT_CAPTION_GET(L15.PARENT_ID)) VAL1
        FROM LINKS L15
        JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0
        LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
        LEFT JOIN VALR V69 ON V69.OBJ_ID = L15.OBJ_ID
        LEFT JOIN VALL V64V58 ON V64V58.OBJ_ID = V69.VAL
        WHERE L15.OBJ_TYPE_ID = 15
          AND L15.DATE_DEL IS NULL
          AND V73.VAL <= :I$DT
          AND (V74.VAL IS NULL OR V74.VAL > :I$DT)
          AND V69.PARAM_ID = 69
          AND V69.IS_DEL = 0
          AND V64V58.PARAM_ID = IIF(:STAGE_NUM < 11, 64, 58)
          AND V64V58.IS_DEL = 0
          AND V64V58.LISTVAL_ID = IIF(:STAGE_NUM = 11, 1267, IIF(:STAGE_NUM = 12, 1284, 98))
          AND L15.PARENT_ID IN (
            SELECT L14.OBJ_ID
            FROM LINKS L14
            INNER JOIN VALL V274 ON V274.OBJ_ID = L14.OBJ_ID
            WHERE L14.PARENT_ID IN (
                SELECT :I$OBJ_ID
                FROM RDB$DATABASE
                UNION
                SELECT L84.OBJ_ID
                FROM LINKS L84
                WHERE L84.PARENT_ID = :I$OBJ_ID
                  AND L84.OBJ_TYPE_ID = 84
                  AND L84.DATE_DEL IS NULL)
              AND L14.OBJ_TYPE_ID = 14
              AND L14.DATE_DEL IS NULL
              AND V274.PARAM_ID = 274
              AND V274.IS_DEL = 0
              AND V274.LISTVAL_ID = 602
              AND (:STAGE_NUM IN (1, 11, 12) OR :STAGE_NUM IN (
                    SELECT FIRST 1
                        IIF (:STAGE_NUM = 2, 2,
                        CASE V592.LISTVAL_ID
                            WHEN 11399 THEN 3
                            WHEN 11402 THEN 4
                            WHEN 11400 THEN 5
                            WHEN 11401 THEN 6
                            WHEN 11398 THEN 7
                            WHEN 1732 THEN 8
                            WHEN 199 THEN 9
                            WHEN 198 THEN 10
                        END)
                    FROM LINKS L14_58
                    JOIN LINKS L256_58 ON L256_58.OBJ_ID = L14_58.OBJ_ID
                      AND L256_58.PARENT_TYPE_ID = 256
                      AND L256_58.DATE_DEL IS NULL
                    JOIN LINKS L256_10 ON L256_10.PARENT_ID = L256_58.PARENT_ID
                      AND L256_10.OBJ_TYPE_ID = 10
                      --AND L256_10.DATE_DEL IS NULL
                    JOIN LINKS L9_10 ON L9_10.OBJ_ID = L256_10.OBJ_ID
                      AND L9_10.PARENT_TYPE_ID IN (9, 187)
                      --AND L9_10.DATE_DEL IS NULL
                    JOIN VALL V592 ON V592.OBJ_ID = L9_10.PARENT_ID
                      AND V592.PARAM_ID = 592
                      AND V592.IS_DEL = 0
                      AND V592.LISTVAL_ID > 197
                    WHERE L14_58.PARENT_ID = L14.OBJ_ID
                      AND L14_58.OBJ_TYPE_ID = 58
                      AND L14_58.DATE_DEL IS NULL
                    ORDER BY 1
              ))
            )
        INTO :VAL1
    DO
    BEGIN
        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OSH1_603 (
    I$OBJ_ID BIGINT)
RETURNS (
    V INTEGER)
AS
DECLARE VARIABLE OU_TYPE_ID BIGINT;
DECLARE VARIABLE TEACHER_ID BIGINT;
DECLARE VARIABLE X INTEGER;
BEGIN
    V = 0;
    OU_TYPE_ID = 0;

    SELECT V11.LISTVAL_ID
    FROM VALL V11
    WHERE V11.PARAM_ID = 11
      AND V11.OBJ_ID = :I$OBJ_ID
      AND V11.IS_DEL = 0
    INTO :OU_TYPE_ID;

    IF (OU_TYPE_ID != 969) THEN
    BEGIN
        SUSPEND;
        EXIT;
    END

    FOR SELECT L14.OBJ_ID
        FROM LINKS L14
        INNER JOIN VALL V274 ON V274.OBJ_ID = L14.OBJ_ID
        WHERE L14.PARENT_ID = :I$OBJ_ID
          AND L14.OBJ_TYPE_ID = 14
          AND L14.DATE_DEL IS NULL
          AND V274.PARAM_ID = 274
          AND V274.IS_DEL = 0
          AND V274.LISTVAL_ID = 602
        INTO :TEACHER_ID
    DO
    BEGIN
        X = 0;

        SELECT FIRST 1 1
        FROM LINKS L15
        LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
        LEFT JOIN VALR V69 ON V69.OBJ_ID = L15.OBJ_ID
        LEFT JOIN VALL V58 ON V58.OBJ_ID = V69.VAL
        WHERE L15.PARENT_ID = :TEACHER_ID
          AND L15.OBJ_TYPE_ID = 15
          AND L15.DATE_DEL IS NULL
          AND V74.VAL IS NULL
          AND V69.PARAM_ID = 69
          AND V69.IS_DEL = 0
          AND V58.PARAM_ID = 58
          AND V58.IS_DEL = 0
          AND V58.LISTVAL_ID IN (127, 128, 148)
        INTO :X;

        V = V + X;
    END

    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OSH1_604 (
    I$OBJ_ID BIGINT)
RETURNS (
    V INTEGER)
AS
DECLARE VARIABLE TEACHER_ID BIGINT;
DECLARE VARIABLE X INTEGER;
BEGIN
    V = 0;

    FOR SELECT L14.OBJ_ID
        FROM LINKS L14
        INNER JOIN VALL V274 ON V274.OBJ_ID = L14.OBJ_ID
        WHERE L14.PARENT_ID = :I$OBJ_ID
          AND L14.OBJ_TYPE_ID = 14
          AND L14.DATE_DEL IS NULL
          AND V274.PARAM_ID = 274
          AND V274.IS_DEL = 0
          AND V274.LISTVAL_ID = 602
        INTO :TEACHER_ID
    DO
    BEGIN
        X = 0;

        SELECT FIRST 1 1
        FROM LINKS L15
        LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
        LEFT JOIN VALR V69 ON V69.OBJ_ID = L15.OBJ_ID
        LEFT JOIN VALL V58 ON V58.OBJ_ID = V69.VAL
        WHERE L15.PARENT_ID = :TEACHER_ID
          AND L15.OBJ_TYPE_ID = 15
          AND L15.DATE_DEL IS NULL
          AND V74.VAL IS NULL
          AND V69.PARAM_ID = 69
          AND V69.IS_DEL = 0
          AND V58.PARAM_ID = 58
          AND V58.IS_DEL = 0
          AND V58.LISTVAL_ID = 126
        INTO :X;

        V = V + X;
    END

    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OSH1_605 (
    I$OBJ_ID BIGINT,
    I$DT DATE = CURRENT_DATE)
RETURNS (
    V INTEGER)
AS
DECLARE VARIABLE TEACHER_ID BIGINT;
DECLARE VARIABLE X INTEGER;
BEGIN
    V = 0;

    FOR SELECT L14.OBJ_ID
        FROM LINKS L14
        INNER JOIN VALL V274 ON V274.OBJ_ID = L14.OBJ_ID
        WHERE L14.PARENT_ID IN (
            SELECT :I$OBJ_ID
            FROM RDB$DATABASE
            UNION
            SELECT L84.OBJ_ID
            FROM LINKS L84
            WHERE L84.PARENT_ID = :I$OBJ_ID
              AND L84.OBJ_TYPE_ID = 84
              AND L84.DATE_DEL IS NULL)
          AND L14.OBJ_TYPE_ID = 14
          AND L14.DATE_DEL IS NULL
          AND V274.PARAM_ID = 274
          AND V274.IS_DEL = 0
          AND V274.LISTVAL_ID = 602
        INTO :TEACHER_ID
    DO
    BEGIN
        X = 0;

        SELECT FIRST 1 1
        FROM LINKS L15
        JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0
        LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
        LEFT JOIN VALR V69 ON V69.OBJ_ID = L15.OBJ_ID
        LEFT JOIN VALL V58 ON V58.OBJ_ID = V69.VAL
        WHERE L15.PARENT_ID = :TEACHER_ID
          AND L15.OBJ_TYPE_ID = 15
          AND L15.DATE_DEL IS NULL
          AND V73.VAL <= :I$DT
          AND (V74.VAL IS NULL OR V74.VAL > :I$DT)
          AND V69.PARAM_ID = 69
          AND V69.IS_DEL = 0
          AND V58.PARAM_ID = 58
          AND V58.IS_DEL = 0
          AND V58.LISTVAL_ID = 1267
        INTO :X;

        V = V + X;
    END

    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OSH1_606 (
    I$OBJ_ID BIGINT,
    I$DT DATE = CURRENT_DATE)
RETURNS (
    V INTEGER)
AS
DECLARE VARIABLE TEACHER_ID BIGINT;
DECLARE VARIABLE X INTEGER;
BEGIN
    V = 0;

    FOR SELECT L14.OBJ_ID
        FROM LINKS L14
        INNER JOIN VALL V274 ON V274.OBJ_ID = L14.OBJ_ID
        WHERE L14.PARENT_ID IN (
            SELECT :I$OBJ_ID
            FROM RDB$DATABASE
            UNION
            SELECT L84.OBJ_ID
            FROM LINKS L84
            WHERE L84.PARENT_ID = :I$OBJ_ID
              AND L84.OBJ_TYPE_ID = 84
              AND L84.DATE_DEL IS NULL)
          AND L14.OBJ_TYPE_ID = 14
          AND L14.DATE_DEL IS NULL
          AND V274.PARAM_ID = 274
          AND V274.IS_DEL = 0
          AND V274.LISTVAL_ID = 602
        INTO :TEACHER_ID
    DO
    BEGIN
        X = 0;

        SELECT FIRST 1 1
        FROM LINKS L15
        JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0
        LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
        LEFT JOIN VALR V69 ON V69.OBJ_ID = L15.OBJ_ID
        LEFT JOIN VALL V58 ON V58.OBJ_ID = V69.VAL
        WHERE L15.PARENT_ID = :TEACHER_ID
          AND L15.OBJ_TYPE_ID = 15
          AND L15.DATE_DEL IS NULL
          AND V73.VAL <= :I$DT
          AND (V74.VAL IS NULL OR V74.VAL > :I$DT)
          AND V69.PARAM_ID = 69
          AND V69.IS_DEL = 0
          AND V58.PARAM_ID = 58
          AND V58.IS_DEL = 0
          AND V58.LISTVAL_ID = 1284
        INTO :X;

        V = V + X;
    END

    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OSH1_701DTL (
    I$OBJ_ID BIGINT NOT NULL,
    STAGE_NUM SMALLINT NOT NULL)
RETURNS (
    VAL1 VARCHAR(250),
    VAL2 VARCHAR(250),
    VAL3 VARCHAR(250))
AS
BEGIN
    IF (:STAGE_NUM IN (2, 4)) THEN
        FOR
            SELECT DISTINCT (SELECT CAPTION FROM OBJECT_CAPTION_GET(R.CLASS_ID))
            FROM REPORT_OSH1 R
            INNER JOIN VALI V706 ON V706.OBJ_ID = R.CLASS_ID
            WHERE V706.PARAM_ID = 706
              AND V706.IS_DEL = 0
              AND V706.VAL = IIF(:STAGE_NUM = 4, 3, 2)
            INTO :VAL3
        DO
        BEGIN
            SUSPEND;
        END
    ELSE
        FOR
            SELECT
                (SELECT CAPTION FROM OBJECT_CAPTION_GET(SCHOLAR_ID)) VAL1,
                (SELECT D FROM VAL_GET(SCHOLAR_ID, 89)) VAL2,
                (SELECT CAPTION FROM OBJECT_CAPTION_GET
                    ((SELECT PARENT_ID
                     FROM LINKS
                     WHERE LINK_ID =
                         (SELECT MAX(L.LINK_ID)
                          FROM LINKS L
                          WHERE L.OBJ_ID = SCHOLAR_ID
                            AND L.PARENT_TYPE_ID IN (9,10,81,82,83)
                            AND l.DATE_DEL IS NULL
                         )
                    ))
                ) VAL3
            FROM (
                SELECT R.SCHOLAR_ID
                FROM REPORT_OSH1 R
                INNER JOIN VALI V706 ON V706.OBJ_ID = R.CLASS_ID
                  AND V706.PARAM_ID = 706
                  AND V706.IS_DEL = 0
                  AND V706.VAL = IIF(:STAGE_NUM = 5, 3, 2)
            ) ORDER BY VAL1
            INTO :VAL1, :VAL2, :VAL3
        DO
        BEGIN
            SUSPEND;
        END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OSH1_702 (
    I$OBJ_ID BIGINT,
    I$SMENA INTEGER)
RETURNS (
    V1 INTEGER,
    V2 INTEGER)
AS
DECLARE VARIABLE CLASS_ID BIGINT;
DECLARE VARIABLE X INTEGER;
BEGIN
    V1 = 0;
    V2 = 0;

    FOR SELECT DISTINCT R.CLASS_ID
        FROM REPORT_OSH1 R
        INNER JOIN VALI V706 ON V706.OBJ_ID = R.CLASS_ID
        WHERE V706.PARAM_ID = 706
          AND V706.IS_DEL = 0
          AND V706.VAL = :I$SMENA
        INTO :CLASS_ID
    DO
    BEGIN
        V1 = V1 + 1;

        X = 0;

        SELECT COUNT(*)
        FROM REPORT_OSH1 R
        WHERE R.CLASS_ID = :CLASS_ID
        INTO :X;

        V2 = V2 + X;
    END

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OSH1_801 (
    I$OBJ_ID BIGINT,
    I$N INTEGER)
RETURNS (
    V INTEGER)
AS
BEGIN
    V = 0;

    IF (:I$N = 1) THEN
    BEGIN
        SELECT COUNT(DISTINCT R.STREAM_ID)
        FROM REPORT_OSH1 R
        INNER JOIN VALL V369 ON V369.OBJ_ID = R.STREAM_ID
          AND V369.PARAM_ID = 369
          AND V369.IS_DEL = 0
          AND V369.LISTVAL_ID = 1246
        INTO :V;
    END

    IF (:I$N = 2) THEN
    BEGIN
        SELECT COUNT(DISTINCT R.STREAM_ID)
        FROM REPORT_OSH1 R
        INNER JOIN VALL V369 ON V369.OBJ_ID = R.STREAM_ID
          AND V369.PARAM_ID = 369
          AND V369.IS_DEL = 0
          AND V369.LISTVAL_ID = 1246
        WHERE R.STAGE_LISTVAL_ID < 5
        INTO :V;
    END

    IF (:I$N = 3) THEN
    BEGIN
        SELECT COUNT(DISTINCT R.SCHOLAR_ID)
        FROM REPORT_OSH1 R
        INNER JOIN VALL V369 ON V369.OBJ_ID = R.STREAM_ID
          AND V369.PARAM_ID = 369
          AND V369.IS_DEL = 0
          AND V369.LISTVAL_ID = 1246
        WHERE R.STREAM_ID IS NOT NULL
        INTO :V;
    END

    IF (:I$N = 4) THEN
    BEGIN
        SELECT COUNT(DISTINCT R.SCHOLAR_ID)
        FROM REPORT_OSH1 R
        INNER JOIN VALL V369 ON V369.OBJ_ID = R.STREAM_ID
          AND V369.PARAM_ID = 369
          AND V369.IS_DEL = 0
          AND V369.LISTVAL_ID = 1246
        WHERE R.STREAM_ID IS NOT NULL
          AND R.STAGE_LISTVAL_ID < 5
        INTO :V;
    END

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OSH1_801DTL (
    I$OBJ_ID BIGINT NOT NULL,
    STAGE_NUM SMALLINT NOT NULL)
RETURNS (
    VAL1 VARCHAR(250),
    VAL2 VARCHAR(250),
    VAL3 VARCHAR(250))
AS
BEGIN
    STAGE_NUM = :STAGE_NUM + 1;
    IF (:STAGE_NUM < 3) THEN
        FOR
            SELECT DISTINCT (SELECT CAPTION FROM OBJECT_CAPTION_GET(R.STREAM_ID))
            FROM REPORT_OSH1 R
            INNER JOIN VALL V369 ON V369.OBJ_ID = R.STREAM_ID
              AND V369.PARAM_ID = 369
              AND V369.IS_DEL = 0
              AND V369.LISTVAL_ID = 1246
            WHERE :STAGE_NUM = 1 OR R.STAGE_LISTVAL_ID < 5
            INTO :VAL3
        DO
        BEGIN
            SUSPEND;
        END
    ELSE
        FOR
            SELECT
                (SELECT CAPTION FROM OBJECT_CAPTION_GET(SCHOLAR_ID)) VAL1,
                (SELECT D FROM VAL_GET(SCHOLAR_ID, 89)) VAL2,
                (SELECT CAPTION FROM OBJECT_CAPTION_GET
                    ((SELECT PARENT_ID
                     FROM LINKS
                     WHERE LINK_ID =
                         (SELECT MAX(L.LINK_ID)
                          FROM LINKS L
                          WHERE L.OBJ_ID = SCHOLAR_ID
                            AND L.PARENT_TYPE_ID IN (9,10,81,82,83)
                            AND l.DATE_DEL IS NULL
                         )
                    ))
                ) VAL3
            FROM (
                SELECT DISTINCT R.SCHOLAR_ID
                FROM REPORT_OSH1 R
                INNER JOIN VALL V369 ON V369.OBJ_ID = R.STREAM_ID
                  AND V369.PARAM_ID = 369
                  AND V369.IS_DEL = 0
                  AND V369.LISTVAL_ID = 1246
                WHERE :STAGE_NUM = 3 OR R.STAGE_LISTVAL_ID < 5
            ) ORDER BY VAL1
            INTO :VAL1, :VAL2, :VAL3
        DO
        BEGIN
            SUSPEND;
        END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OSH1_PUPIL_COUNT (
    I$OBJ_ID BIGINT,
    I$SUBJECT INTEGER)
RETURNS (
    PUPIL_COUNT INTEGER)
AS
DECLARE VARIABLE V$OBJ_ID INTEGER;
DECLARE VARIABLE V$P_COUNT INTEGER;
BEGIN
  PUPIL_COUNT = 0;
  FOR SELECT L9.OBJ_ID
      FROM LINKS L9
      JOIN VALL VL ON VL.OBJ_ID = L9.OBJ_ID AND VL.PARAM_ID = 552 AND VL.LISTVAL_ID = :I$SUBJECT AND VL.IS_DEL = 0
      WHERE L9.DATE_DEL IS NULL AND
            L9.OBJ_TYPE_ID = 9 AND
            L9.PARENT_ID = :I$OBJ_ID
      INTO V$OBJ_ID
  DO
  BEGIN
    SELECT COUNT(*)
    FROM LINKS L10
    WHERE L10.DATE_DEL IS NULL AND
          L10.OBJ_TYPE_ID = 10 AND
          L10.PARENT_ID = :V$OBJ_ID
    INTO V$P_COUNT;
    PUPIL_COUNT = :PUPIL_COUNT + :V$P_COUNT;
  END
  SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OSH1_PUPIL_COUNT_ (
    I$OBJ_ID BIGINT)
RETURNS (
    PUPIL_COUNT INTEGER)
AS
DECLARE VARIABLE V$OBJ_ID INTEGER;
DECLARE VARIABLE V$P_COUNT INTEGER;
BEGIN
  PUPIL_COUNT = 0;
  FOR SELECT L9.OBJ_ID
      FROM LINKS L9
      --  JOIN VALL VL ON VL.OBJ_ID = L9.OBJ_ID AND VL.PARAM_ID = 552 AND VL.LISTVAL_ID = :I$SUBJECT AND VL.IS_DEL = 0
      WHERE L9.DATE_DEL IS NULL AND
            L9.OBJ_TYPE_ID = 9 AND
            L9.PARENT_ID = :I$OBJ_ID
      INTO V$OBJ_ID
  DO
  BEGIN
    SELECT COUNT(*)
    FROM LINKS L10
    INNER JOIN LINKS L76 ON L76.PARENT_ID = L10.OBJ_ID AND L76.DATE_DEL IS NULL AND L76.OBJ_TYPE_ID = 76
    INNER JOIN VALL VL ON VL.OBJ_ID = L76.OBJ_ID AND VL.PARAM_ID = 432 AND VL.LISTVAL_ID = 808 AND VL.IS_DEL = 0
    INNER JOIN VALD VD ON VD.OBJ_ID = L76.OBJ_ID AND VD.PARAM_ID = 433 AND EXTRACT(YEAR FROM VD.VAL) =
    (SELECT Y FROM CURRENT_YEAR_GET) AND VD.IS_DEL = 0
    WHERE L10.DATE_DEL IS NULL AND
          L10.OBJ_TYPE_ID = 10 AND
          L10.PARENT_ID = :V$OBJ_ID
    INTO V$P_COUNT;
    PUPIL_COUNT = :PUPIL_COUNT + :V$P_COUNT;
  END
  SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OSH1_T2_1 (
    I$OBJ_ID BIGINT)
RETURNS (
    ETAP_NUM FLOAT,
    PUPIL_COUNT INTEGER)
AS
DECLARE VARIABLE OBJ_ID BIGINT;
BEGIN
    FOR SELECT O8.OBJ_ID, LV.COST
        FROM LINKS   L7
        INNER JOIN OBJECTS  O7 ON O7.OBJ_ID = L7.OBJ_ID    AND O7.TYPE_ID = 7
        INNER JOIN LINKS    L8 ON L8.PARENT_ID = O7.OBJ_ID AND L8.DATE_DEL IS NULL
        INNER JOIN OBJECTS  O8 ON O8.OBJ_ID = L8.OBJ_ID    AND O8.TYPE_ID = 8
        INNER JOIN VALL      V ON PARAM_ID = 49            AND V.OBJ_ID = O8.OBJ_ID  AND V.IS_DEL = 0
        INNER JOIN LISTVALS LV ON LV.LISTVAL_ID = V.LISTVAL_ID
        WHERE L7.PARENT_ID =:I$OBJ_ID
        AND L7.DATE_DEL IS NULL
        ORDER BY LV.COST
        INTO :OBJ_ID, :ETAP_NUM
    DO BEGIN
        

        SELECT COUNT(*)
        FROM LINKS   L9
        INNER JOIN OBJECTS  O9 ON O9.OBJ_ID = L9.OBJ_ID     AND  O9.TYPE_ID = 9
        INNER JOIN LINKS   L10 ON L10.PARENT_ID = O9.OBJ_ID AND L10.DATE_DEL IS NULL
        INNER JOIN OBJECTS O10 ON O10.OBJ_ID = L10.OBJ_ID   AND O10.TYPE_ID = 10
        WHERE L9.PARENT_ID =:OBJ_ID
        AND L9.DATE_DEL IS NULL
        INTO :PUPIL_COUNT;

        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OSH1_YEAR_GET (
    I$DELTA SMALLINT,
    I$DT DATE = CURRENT_DATE)
RETURNS (
    Y SMALLINT)
AS
DECLARE VARIABLE V$CALC_DATE TIMESTAMP;
BEGIN
    IF (EXTRACT(MONTH FROM :I$DT) >= 9) THEN
    BEGIN
        V$CALC_DATE = (EXTRACT(YEAR FROM :I$DT) + 1) || '-01-01';
    END
    ELSE
    BEGIN
        V$CALC_DATE = EXTRACT(YEAR FROM :I$DT) || '-01-01';
    END
    Y = EXTRACT(YEAR FROM DATEADD(-I$DELTA YEAR TO :V$CALC_DATE)) - 1;
    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OSH5_101DTL (
    I$OBJ_ID BIGINT NOT NULL,
    I$N SMALLINT = NULL)
RETURNS (
    VAL1 VARCHAR(250),
    VAL2 VARCHAR(250))
AS
BEGIN
    FOR
        SELECT
            (SELECT CAPTION FROM OBJECT_CAPTION_GET(R.SCHOLAR_ID)) VAL1,
            (SELECT D FROM VAL_GET(R.SCHOLAR_ID, 89)) VAL2
        FROM REPORT_OSH1 R
        JOIN VALL V592 ON V592.OBJ_ID = R.CLASS_ID
          AND V592.PARAM_ID = 592
          AND V592.IS_DEL = 0
          AND V592.LISTVAL_ID < 198
        WHERE R.STAGE_LISTVAL_ID >= 37
        ORDER BY VAL1
        INTO :VAL1, :VAL2
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OSH5_301 (
    I$OBJ_ID BIGINT,
    I$N SMALLINT)
RETURNS (
    VAL3 INTEGER,
    VAL4 INTEGER,
    VAL5 INTEGER,
    VAL6 INTEGER,
    VAL7 INTEGER,
    VAL8 INTEGER,
    VAL9 INTEGER,
    VAL10 INTEGER)
AS
BEGIN
    SELECT
        COUNT(DISTINCT VAL3) VAL3,
        SUM(VAL4) VAL4,
        COUNT(DISTINCT VAL5) VAL5,
        SUM(VAL6) VAL6,
        SUM(VAL7) VAL7,
        SUM(VAL8) VAL8,
        SUM(VAL9) VAL9,
        SUM(VAL10) VAL10
    FROM (
        SELECT
            IIF(SUM(IIF(SCHOLAR_FORM_ID IN (153, 154), 1, 0))/
                CAST(COUNT(1) AS FLOAT) > 0.5, CLASS_ID, NULL) VAL3,
            SUM(IIF(SCHOLAR_FORM_ID IN (153, 154), 1, 0)) VAL4,
            IIF(SUM(IIF(SCHOLAR_FORM_ID NOT IN (153, 154), 1, 0))/
                CAST(COUNT(1) AS FLOAT) > 0.5, CLASS_ID, NULL) VAL5,
            SUM(IIF(SCHOLAR_FORM_ID = 155, 1, 0)) VAL6,
            SUM(IIF(SCHOLAR_FORM_ID = 156, 1, 0)) VAL7,
            COUNT(1) VAL8,
            SUM(IIF(SCHOLAR_FORM_ID = 1222, 1, 0)) VAL9,
            SUM(YEAR2_FL) VAL10
        FROM (
            SELECT
                R.CLASS_ID,
                COALESCE((SELECT VL.LISTVAL_ID
                          FROM VALL VL
                          WHERE VL.OBJ_ID = R.SCHOLAR_ID
                            AND VL.PARAM_ID = 80
                            AND VL.IS_DEL = 0), 153) SCHOLAR_FORM_ID,
                IIF(COALESCE((SELECT VL.LISTVAL_ID
                          FROM VALL VL
                          WHERE VL.OBJ_ID = R.SCHOLAR_ID
                            AND VL.PARAM_ID = 82
                            AND VL.IS_DEL = 0), 157) <> 157, 1, 0) YEAR2_FL
            FROM REPORT_OSH1 R
            WHERE (:I$N = 1 AND R.STAGE_LISTVAL_ID BETWEEN 37 AND 40)
               OR (:I$N = 2 AND R.STAGE_LISTVAL_ID BETWEEN 41 AND 44)
               OR (:I$N = 3 AND R.STAGE_LISTVAL_ID = 45)
               OR (:I$N = 4 AND R.STAGE_LISTVAL_ID = 46)
               OR (:I$N = 5 AND R.STAGE_LISTVAL_ID IN (47, 48))
               OR (:I$N = 6 AND R.STAGE_LISTVAL_ID > 48)
               OR (:I$N = 7 AND R.STAGE_LISTVAL_ID >= 37))
        GROUP BY CLASS_ID)
    INTO :VAL3, :VAL4, :VAL5, :VAL6, :VAL7, :VAL8, :VAL9, :VAL10;
    VAL3 = IIF(:VAL3 = 0, NULL, :VAL3);
    VAL4 = IIF(:VAL4 = 0, NULL, :VAL4);
    VAL5 = IIF(:VAL5 = 0, NULL, :VAL5);
    VAL6 = IIF(:VAL6 = 0, NULL, :VAL6);
    VAL7 = IIF(:VAL7 = 0, NULL, :VAL7);
    VAL8 = IIF(:VAL8 = 0, NULL, :VAL8);
    VAL9 = IIF(:VAL9 = 0, NULL, :VAL9);
    VAL10 = IIF(:VAL10 = 0, NULL, :VAL10);
    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OSH5_301DTL (
    I$OBJ_ID BIGINT NOT NULL,
    I$N SMALLINT NOT NULL,
    I$N2 SMALLINT = NULL)
RETURNS (
    VAL1 VARCHAR(250),
    VAL2 VARCHAR(250))
AS
BEGIN
    IF (:I$N2 IN (3, 5)) THEN
    FOR
        SELECT
            (SELECT CAPTION FROM OBJECT_CAPTION_GET(CLASS_ID)) VAL1
        FROM (
            SELECT DISTINCT R.CLASS_ID
            FROM REPORT_OSH1 R
            WHERE ((:I$N = 1 AND R.STAGE_LISTVAL_ID BETWEEN 37 AND 40)
               OR (:I$N = 2 AND R.STAGE_LISTVAL_ID BETWEEN 41 AND 44)
               OR (:I$N = 3 AND R.STAGE_LISTVAL_ID = 45)
               OR (:I$N = 4 AND R.STAGE_LISTVAL_ID = 46)
               OR (:I$N = 5 AND R.STAGE_LISTVAL_ID IN (47, 48))
               OR (:I$N = 6 AND R.STAGE_LISTVAL_ID > 48)
               OR (:I$N = 7 AND R.STAGE_LISTVAL_ID >= 37))
              AND (SELECT SUM(IIF((:I$N2 = 3 AND SCHOLAR_FORM_ID IN (153, 154))
                               OR (:I$N2 = 5 AND SCHOLAR_FORM_ID NOT IN (153, 154)), 1, 0))/
                          CAST(COUNT(1) AS FLOAT)
                   FROM (
                       SELECT
                           R2.SCHOLAR_ID,
                           COALESCE((SELECT VL.LISTVAL_ID
                                     FROM VALL VL
                                     WHERE VL.OBJ_ID = R2.SCHOLAR_ID
                                       AND VL.PARAM_ID = 80
                                       AND VL.IS_DEL = 0), 153) SCHOLAR_FORM_ID
                       FROM REPORT_OSH1 R2
                       WHERE R2.CLASS_ID = R.CLASS_ID)) > 0.5
        ) ORDER BY VAL1
        INTO :VAL1
    DO
    BEGIN
        SUSPEND;
    END
    -------------------------------
    ELSE
    FOR
        SELECT
            (SELECT CAPTION FROM OBJECT_CAPTION_GET(SCHOLAR_ID)) VAL1,
            (SELECT D FROM VAL_GET(SCHOLAR_ID, 89)) VAL2
        FROM (
            SELECT
                R.SCHOLAR_ID,
                COALESCE((SELECT VL.LISTVAL_ID
                          FROM VALL VL
                          WHERE VL.OBJ_ID = R.SCHOLAR_ID
                            AND VL.PARAM_ID = 80
                            AND VL.IS_DEL = 0), 153) SCHOLAR_FORM_ID,
                IIF(COALESCE((SELECT VL.LISTVAL_ID
                          FROM VALL VL
                          WHERE VL.OBJ_ID = R.SCHOLAR_ID
                            AND VL.PARAM_ID = 82
                            AND VL.IS_DEL = 0), 157) <> 157, 1, 0) YEAR2_FL
            FROM REPORT_OSH1 R
            WHERE (:I$N = 1 AND R.STAGE_LISTVAL_ID BETWEEN 37 AND 40)
               OR (:I$N = 2 AND R.STAGE_LISTVAL_ID BETWEEN 41 AND 44)
               OR (:I$N = 3 AND R.STAGE_LISTVAL_ID = 45)
               OR (:I$N = 4 AND R.STAGE_LISTVAL_ID = 46)
               OR (:I$N = 5 AND R.STAGE_LISTVAL_ID IN (47, 48))
               OR (:I$N = 6 AND R.STAGE_LISTVAL_ID > 48)
               OR (:I$N = 7 AND R.STAGE_LISTVAL_ID >= 37))
        WHERE (:I$N2 = 4 AND SCHOLAR_FORM_ID IN (153, 154))
           OR (:I$N2 = 6 AND SCHOLAR_FORM_ID = 155)
           OR (:I$N2 = 7 AND SCHOLAR_FORM_ID = 156)
           OR  :I$N2 = 8
           OR (:I$N2 = 9 AND SCHOLAR_FORM_ID = 1222)
           OR (:I$N2 = 10 AND YEAR2_FL = 1)
        ORDER BY VAL1
        INTO :VAL1, :VAL2
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OSH5_401 (
    I$OBJ_ID BIGINT NOT NULL,
    I$DT DATE = CURRENT_DATE)
RETURNS (
    VAL3 INTEGER,
    VAL4 INTEGER,
    VAL5 INTEGER,
    VAL6 INTEGER,
    VAL7 INTEGER,
    VAL8 INTEGER,
    VAL9 INTEGER)
AS
BEGIN
    VAL3 = (SELECT VAL FROM OSH1_201(:I$OBJ_ID,41, :I$DT)) +
           (SELECT VAL FROM OSH1_201(:I$OBJ_ID,42, :I$DT));
    VAL4 = (SELECT VAL FROM OSH1_201(:I$OBJ_ID,43, :I$DT));
    VAL5 = (SELECT VAL FROM OSH1_201(:I$OBJ_ID,44, :I$DT));
    VAL6 = (SELECT VAL FROM OSH1_201(:I$OBJ_ID,45, :I$DT));
    VAL7 = (SELECT VAL FROM OSH1_201(:I$OBJ_ID,46, :I$DT));
    VAL8 = (SELECT VAL FROM OSH1_201(:I$OBJ_ID,47, :I$DT));
    VAL9 = (SELECT VAL FROM OSH1_213(:I$OBJ_ID,48, :I$DT)) +
           (SELECT VAL FROM OSH1_201(:I$OBJ_ID,48, :I$DT));
    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OSH5_401DTL (
    I$OBJ_ID BIGINT NOT NULL,
    I$N SMALLINT NOT NULL,
    I$N2 SMALLINT = NULL,
    I$DT DATE = CURRENT_DATE)
RETURNS (
    VAL1 VARCHAR(250),
    VAL2 VARCHAR(250))
AS
BEGIN
    IF (:I$N = 1 AND :I$N2 = 3) THEN
    FOR
        SELECT VAL1, VAL2 FROM OSH1_201DTL(:I$OBJ_ID, 4, :I$DT)
        INTO :VAL1, :VAL2
    DO
    BEGIN
        SUSPEND;
    END
    ------------------
    IF (:I$N = 1) THEN
    FOR
        SELECT VAL1, VAL2 FROM OSH1_201DTL(:I$OBJ_ID, :I$N2 + 2, :I$DT)
        INTO :VAL1, :VAL2
    DO
    BEGIN
        SUSPEND;
    END
    ------------------
    IF (:I$N = 1 AND :I$N2 = 9) THEN
    FOR
        SELECT VAL1, VAL2 FROM OSH1_201DTL(:I$OBJ_ID, 12, :I$DT)
        INTO :VAL1, :VAL2
    DO
    BEGIN
        SUSPEND;
    END
    ------------------
    IF (:I$N IN (2, 4)) THEN
    FOR
        SELECT VAL1, VAL2 FROM OSH1_201DTL(:I$OBJ_ID, :I$N + 7, :I$DT)
        INTO :VAL1, :VAL2
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OSH5_501 (
    I$OBJ_ID BIGINT NOT NULL,
    I$N SMALLINT NOT NULL,
    I$DT DATE = CURRENT_DATE)
RETURNS (
    V3 INTEGER,
    V4 INTEGER,
    V5 INTEGER,
    V6 INTEGER,
    V7 INTEGER)
AS
DECLARE VARIABLE Y4 INTEGER;
DECLARE VARIABLE Y5 INTEGER;
DECLARE VARIABLE Y6 INTEGER;
BEGIN
    SELECT Y FROM OSH1_YEAR_GET(15, :I$DT) INTO :Y4;
    SELECT Y FROM OSH1_YEAR_GET(17, :I$DT) INTO :Y5;
    SELECT Y FROM OSH1_YEAR_GET(29, :I$DT) INTO :Y6;

    SELECT
        COUNT(1) V3,
        IIF(:I$N < 4, SUM(IIF(EXTRACT(YEAR FROM V89.VAL) >= :Y4, 1, 0)), NULL) V4,
        IIF(:I$N < 4, SUM(IIF(EXTRACT(YEAR FROM V89.VAL) BETWEEN :Y5 AND :Y4 - 1, 1, 0)), NULL) V5,
        IIF(:I$N < 4, SUM(IIF(EXTRACT(YEAR FROM V89.VAL) BETWEEN :Y6 AND :Y5 - 1, 1, 0)), NULL) V6,
        IIF(:I$N < 4, SUM(IIF(EXTRACT(YEAR FROM V89.VAL) <  :Y6, 1, 0)), NULL) VAL7
    FROM REPORT_OSH1 R
    JOIN VALD V89 ON V89.OBJ_ID = R.SCHOLAR_ID
    JOIN VALL V88 ON V88.OBJ_ID = R.SCHOLAR_ID
      AND V89.PARAM_ID = 89
      AND V89.IS_DEL = 0
      AND V88.PARAM_ID = 88
      AND V88.IS_DEL = 0
      AND R.CLASS_ID IS NOT NULL
      AND (:I$N = 1
       OR (:I$N = 2 AND R.STAGE_LISTVAL_ID IN (46, 47, 48))
       OR (:I$N = 4 AND V88.LISTVAL_ID = 182))
    INTO :V3, :V4, :V5, :V6, :V7;

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OSH5_501DTL (
    I$OBJ_ID BIGINT NOT NULL,
    I$N SMALLINT NOT NULL,
    I$N2 SMALLINT NOT NULL,
    I$DT DATE = CURRENT_DATE)
RETURNS (
    VAL1 VARCHAR(250),
    VAL2 VARCHAR(250))
AS
DECLARE VARIABLE Y_FROM INTEGER;
DECLARE VARIABLE Y_TO INTEGER;
BEGIN
    Y_FROM = CASE :I$N2
        WHEN 4 THEN (SELECT Y FROM OSH1_YEAR_GET(15, :I$DT))
        WHEN 5 THEN (SELECT Y FROM OSH1_YEAR_GET(17, :I$DT))
        WHEN 6 THEN (SELECT Y FROM OSH1_YEAR_GET(29, :I$DT))
        WHEN 7 THEN 0
    END;
    Y_TO = CASE :I$N2
        WHEN 4 THEN 5000
        WHEN 5 THEN (SELECT Y-1 FROM OSH1_YEAR_GET(15, :I$DT))
        WHEN 6 THEN (SELECT Y-1 FROM OSH1_YEAR_GET(17, :I$DT))
        WHEN 7 THEN (SELECT Y-1 FROM OSH1_YEAR_GET(29, :I$DT))
    END;
    FOR
        SELECT
            (SELECT CAPTION FROM OBJECT_CAPTION_GET(SCHOLAR_ID)) VAL1,
            (SELECT D FROM VAL_GET(SCHOLAR_ID, 89)) VAL2
        FROM (
            SELECT R.SCHOLAR_ID
            FROM REPORT_OSH1 R
            JOIN VALD V89 ON V89.OBJ_ID = R.SCHOLAR_ID
            JOIN VALL V88 ON V88.OBJ_ID = R.SCHOLAR_ID
            WHERE V89.PARAM_ID = 89
              AND V89.IS_DEL = 0
              AND V88.PARAM_ID = 88
              AND V88.IS_DEL = 0
              AND R.CLASS_ID IS NOT NULL
              AND (:I$N = 1
               OR (:I$N = 2 AND R.STAGE_LISTVAL_ID IN (46, 47, 48))
               OR (:I$N = 4 AND V88.LISTVAL_ID = 182))
              AND (:I$N2 = 3 OR EXTRACT(YEAR FROM V89.VAL) BETWEEN :Y_FROM AND :Y_TO)
        ) ORDER BY VAL1
        INTO :VAL1, :VAL2
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OSH5_601 (
    I$OBJ_ID BIGINT NOT NULL,
    I$DT DATE = CURRENT_DATE)
RETURNS (
    VAL3 VARCHAR(10))
AS
DECLARE VARIABLE VAL9 INTEGER;
BEGIN
    -- 01
    SELECT VS FROM D_12(:I$OBJ_ID, 1, :I$DT) INTO :VAL3;
    VAL9 = CAST('0'||:VAL3 AS INT);
    SUSPEND;
    -- 02
    SELECT VS FROM D_12(:I$OBJ_ID, 4, :I$DT) INTO :VAL3;
    VAL9 = :VAL9 - CAST('0'||:VAL3 AS INT);
    SUSPEND;
    -- 03
    SELECT VS FROM D_12(:I$OBJ_ID, 5, :I$DT) INTO :VAL3;
    VAL9 = :VAL9 - CAST('0'||:VAL3 AS INT);
    SUSPEND;
    -- 04
    SELECT VS FROM D_12(:I$OBJ_ID, 6, :I$DT) INTO :VAL3;
    VAL9 = :VAL9 - CAST('0'||:VAL3 AS INT);
    SUSPEND;
    -- 05
    VAL3 = NULL;
    SUSPEND;
    -- 06
    VAL3 = NULL;
    SUSPEND;
    -- 07
    SELECT VS FROM D_12(:I$OBJ_ID, 14, :I$DT) INTO :VAL3;
    VAL9 = :VAL9 - CAST('0'||:VAL3 AS INT);
    SUSPEND;
    -- 08
    SELECT VS FROM D_12(:I$OBJ_ID, 15, :I$DT) INTO :VAL3;
    VAL9 = :VAL9 - CAST('0'||:VAL3 AS INT);
    SUSPEND;
    -- 09
    VAL3 = IIF(:VAL9 = 0, NULL, :VAL9);
    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OSH5_601DTL (
    I$OBJ_ID BIGINT NOT NULL,
    I$N SMALLINT NOT NULL,
    I$N2 SMALLINT = NULL,
    I$DT DATE = CURRENT_DATE)
RETURNS (
    VAL1 VARCHAR(250),
    VAL2 VARCHAR(250),
    VAL3 VARCHAR(250))
AS
BEGIN
    IF (:I$N = 1) THEN
    FOR
        SELECT VAL1, VAL2, VAL3 FROM OSH1_1501DTL(:I$OBJ_ID, 0, NULL, :I$DT)
        INTO :VAL1, :VAL2, :VAL3
    DO
    BEGIN
        SUSPEND;
    END
    ------------------
    ------------------
    IF (:I$N = 2) THEN
    FOR
        SELECT VAL1, VAL2, VAL3 FROM OSH1_1501DTL(:I$OBJ_ID, 3, NULL, :I$DT)
        INTO :VAL1, :VAL2, :VAL3
    DO
    BEGIN
        SUSPEND;
    END
    ------------------
    IF (:I$N = 3) THEN
    FOR
        SELECT VAL1, VAL2, VAL3 FROM OSH1_1501DTL(:I$OBJ_ID, 4, NULL, :I$DT)
        INTO :VAL1, :VAL2, :VAL3
    DO
    BEGIN
        SUSPEND;
    END
    ------------------
    IF (:I$N = 4) THEN
    FOR
        SELECT VAL1, VAL2, VAL3 FROM OSH1_1501DTL(:I$OBJ_ID, 5, NULL, :I$DT)
        INTO :VAL1, :VAL2, :VAL3
    DO
    BEGIN
        SUSPEND;
    END
    ------------------
    IF (:I$N = 7) THEN
    FOR
        SELECT VAL1, VAL2, VAL3 FROM OSH1_1501DTL(:I$OBJ_ID, 13, NULL, :I$DT)
        INTO :VAL1, :VAL2, :VAL3
    DO
    BEGIN
        SUSPEND;
    END
    ------------------
    IF (:I$N = 8) THEN
    FOR
        SELECT VAL1, VAL2, VAL3 FROM OSH1_1501DTL(:I$OBJ_ID, 14, NULL, :I$DT)
        INTO :VAL1, :VAL2, :VAL3
    DO
    BEGIN
        SUSPEND;
    END
    ------------------
    IF (:I$N = 9) THEN
    FOR
        SELECT VAL1, VAL2, VAL3 FROM OSH1_1501DTL(:I$OBJ_ID, -17, NULL, :I$DT)
        INTO :VAL1, :VAL2, :VAL3
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OSH5_701DTL (
    I$OBJ_ID BIGINT NOT NULL,
    I$N SMALLINT NOT NULL,
    I$N2 SMALLINT = NULL,
    I$DT DATE = CURRENT_DATE)
RETURNS (
    VAL1 VARCHAR(250),
    VAL2 VARCHAR(250),
    VAL3 VARCHAR(250),
    NAME VARCHAR(250))
AS
BEGIN
    FOR
        SELECT VAL1, VAL2, VAL3, NAME FROM OSH1_1301DTL(:I$OBJ_ID, :I$N - 1, :I$DT)
        INTO :VAL1, :VAL2, :VAL3, :NAME
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OSH5_801 (
    I$OBJ_ID BIGINT NOT NULL)
RETURNS (
    VAL3 INTEGER,
    VAL4 INTEGER)
AS
DECLARE VARIABLE N_OSH5 INTEGER; /* Row # in OSH5 */
DECLARE VARIABLE N_801 INTEGER; /* Row # in Query */
DECLARE VARIABLE VV03 INTEGER;
DECLARE VARIABLE VV04 INTEGER;
BEGIN
    N_OSH5 = 0;
    FOR
        SELECT
            DISTINCT(N) N,
            SUM(VAL3) VAL3,
            SUM(VAL4) VAL4
        FROM (
            SELECT
                CASE V504.LISTVAL_ID
                    WHEN 1114 THEN 2
                    WHEN 1115 THEN 3
                    ELSE 1
                END N,
                V501.VAL VAL3,
                V499.VAL VAL4
            FROM LINKS L73
            INNER JOIN LINKS L16 ON L16.PARENT_ID = L73.OBJ_ID
            INNER JOIN VALI V501 ON V501.OBJ_ID = L16.OBJ_ID
            INNER JOIN VALL V504 ON V504.OBJ_ID = L16.OBJ_ID
            INNER JOIN VALF V499 ON V499.OBJ_ID = L16.OBJ_ID
            WHERE L73.PARENT_ID = :I$OBJ_ID
              AND L73.OBJ_TYPE_ID = 73
              AND L73.DATE_DEL IS NULL
              AND L16.OBJ_TYPE_ID = 16
              AND L16.DATE_DEL IS NULL
              AND V501.PARAM_ID = 501
              AND V501.IS_DEL = 0
              AND V504.PARAM_ID = 504
              AND V504.IS_DEL = 0
              AND V499.PARAM_ID = 499
              AND V499.IS_DEL = 0)
        GROUP BY N
        INTO :N_801, :VV03, :VV04
    DO
    BEGIN
        N_OSH5 = :N_OSH5 + 1;
        WHILE (:N_OSH5 < :N_801) DO
        BEGIN
            N_OSH5 = :N_OSH5 + 1;
            VAL3 = NULL; VAL4 = NULL;
            SUSPEND;
        END
        VAL3 = :VV03; VAL4 = :VV04;
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OSH5_901 (
    I$OBJ_ID BIGINT NOT NULL,
    I$DT DATE = CURRENT_DATE)
RETURNS (
    V03 INTEGER,
    V04 NUMERIC(11,2),
    V05 INTEGER,
    V06 INTEGER,
    V07 INTEGER,
    V08 INTEGER,
    V09 INTEGER,
    V10 INTEGER,
    V11 INTEGER,
    V12 INTEGER,
    V13 INTEGER,
    V14 INTEGER,
    V15 INTEGER,
    V16 INTEGER,
    V17 INTEGER,
    V18 INTEGER,
    V19 INTEGER,
    V20 INTEGER,
    V21 INTEGER,
    V22 INTEGER,
    V23 INTEGER,
    V24 INTEGER,
    V25 INTEGER,
    V26 INTEGER,
    V27 INTEGER,
    V28 INTEGER,
    V29 INTEGER,
    V30 INTEGER)
AS
DECLARE VARIABLE N_RIK83 SMALLINT; /* Row # in RIK83 */
DECLARE VARIABLE N_OSH5 SMALLINT; /* Row # in OSH5 */
DECLARE VARIABLE VV03 INTEGER;
DECLARE VARIABLE VV04 NUMERIC(11,2);
DECLARE VARIABLE VV05 INTEGER;
DECLARE VARIABLE VV06 INTEGER;
DECLARE VARIABLE VV07 INTEGER;
DECLARE VARIABLE VV08 INTEGER;
DECLARE VARIABLE VV09 INTEGER;
DECLARE VARIABLE VV10 INTEGER;
DECLARE VARIABLE VV11 INTEGER;
DECLARE VARIABLE VV12 INTEGER;
DECLARE VARIABLE VV13 INTEGER;
DECLARE VARIABLE VV14 INTEGER;
DECLARE VARIABLE VV15 INTEGER;
DECLARE VARIABLE VV16 INTEGER;
DECLARE VARIABLE VV17 INTEGER;
DECLARE VARIABLE VV18 INTEGER;
DECLARE VARIABLE VV19 INTEGER;
DECLARE VARIABLE VV20 INTEGER;
DECLARE VARIABLE VV21 INTEGER;
DECLARE VARIABLE VV22 INTEGER;
DECLARE VARIABLE VV23 INTEGER;
DECLARE VARIABLE VV24 INTEGER;
DECLARE VARIABLE VV25 INTEGER;
DECLARE VARIABLE VV26 INTEGER;
DECLARE VARIABLE VV27 INTEGER;
DECLARE VARIABLE VV28 INTEGER;
DECLARE VARIABLE VV29 INTEGER;
DECLARE VARIABLE VV30 INTEGER;
DECLARE VARIABLE VV31 INTEGER;
DECLARE VARIABLE VV32 INTEGER;
DECLARE VARIABLE VV33 INTEGER;
DECLARE VARIABLE VV34 INTEGER;
DECLARE VARIABLE VV35 INTEGER;
DECLARE VARIABLE VV36 INTEGER;
DECLARE VARIABLE VV37 INTEGER;
DECLARE VARIABLE VV38 INTEGER;
BEGIN
    N_OSH5 = 0;
    FOR
        SELECT
            CASE
                WHEN N > 39 THEN N-2
                WHEN N > 9 THEN N-1
                ELSE N
            END N,
            V03, V04, V05, V06, V07, V08, V09,
            V10, V11, V12, V13, V14, V15, V16,
            V17, V18, V19, V20, V21, V22, V23,
            V24, V25, V26, V27, V28, V29, V30
        FROM RIK83_ALL(:I$OBJ_ID, NULL, NULL, 1, 0, NULL, NULL, :I$DT)
        WHERE N NOT IN (9, 39)
        INTO :N_RIK83,
            :VV03, :VV04, :VV05, :VV06, :VV07, :VV08, :VV09,
            :VV10, :VV11, :VV12, :VV13, :VV14, :VV15, :VV16,
            :VV17, :VV18, :VV19, :VV20, :VV21, :VV22, :VV23,
            :VV24, :VV25, :VV26, :VV27, :VV28, :VV29, :VV30
    DO
    BEGIN
        N_OSH5 = :N_OSH5 + 1;
        WHILE (:N_OSH5 < :N_RIK83) DO
        BEGIN
            N_OSH5 = :N_OSH5 + 1;
            V03 = NULL; V04 = NULL; V05 = NULL; V06 = NULL; V07 = NULL; V08 = NULL; V09 = NULL;
            V10 = NULL; V11 = NULL; V12 = NULL; V13 = NULL; V14 = NULL; V15 = NULL; V16 = NULL;
            V17 = NULL; V18 = NULL; V19 = NULL; V20 = NULL; V21 = NULL; V22 = NULL; V23 = NULL;
            V24 = NULL; V25 = NULL; V26 = NULL; V27 = NULL; V28 = NULL; V29 = NULL; V30 = NULL;
            SUSPEND;
        END
        V03 = :VV03; V04 = :VV04; V05 = :VV05; V06 = :VV06; V07 = :VV07; V08 = :VV08; V09 = :VV09;
        V10 = :VV10; V11 = :VV11; V12 = :VV12; V13 = :VV13; V14 = :VV14; V15 = :VV15; V16 = :VV16;
        V17 = :VV17; V18 = :VV18; V19 = :VV19; V20 = :VV20; V21 = :VV21; V22 = :VV22; V23 = :VV23;
        V24 = :VV24; V25 = :VV25; V26 = :VV26; V27 = :VV27; V28 = :VV28; V29 = :VV29; V30 = :VV30;
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OSH5_901DTL (
    I$OBJ_ID BIGINT NOT NULL,
    I$N SMALLINT NOT NULL,
    I$N2 SMALLINT = NULL)
RETURNS (
    NAME VARCHAR(250),
    CNT DOUBLE PRECISION,
    VAL1 VARCHAR(250))
AS
BEGIN
    FOR
        SELECT NAME, CNT, VAL1 FROM RIK83_DTL(1,
            CASE
                WHEN :I$N > 37 THEN :I$N+2
                WHEN :I$N > 8 THEN :I$N+1
                ELSE :I$N
            END,
            :I$N2)
        INTO :NAME, :CNT, :VAL1
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OU_ACTION_TYPES RETURNS (
    VAL VARCHAR(400))
AS
begin
  SELECT LIST(CAST(V3327.LISTVAL_ID AS VARCHAR(40)), ',')
  FROM LINKS L2
  JOIN LINKS L472 ON L472.PARENT_ID = L2.OBJ_ID AND L472.OBJ_TYPE_ID = 472 AND L472.DATE_DEL IS NULL
  JOIN VALL V3327 ON V3327.OBJ_ID = L472.OBJ_ID AND V3327.PARAM_ID = 3327 AND V3327.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :VAL;

  SUSPEND;
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OU_CLASS_REPORT (
    I$OBJ_ID BIGINT,
    I$DT DATE = CURRENT_DATE)
RETURNS (
    COLOR CHAR(7),
    NAME VARCHAR(250),
    CLASS_NUM INTEGER,
    CLASS_CNT INTEGER,
    SCHOLAR_CNT INTEGER,
    CLASS_PUB_CNT INTEGER,
    SCHOLAR_PUB_CNT INTEGER,
    CLASS_INC_CNT INTEGER,
    CLASS_ZPR_CNT INTEGER,
    SCHOLAR_ZPR_CNT INTEGER,
    SCHOLAR_HOUSE_CNT INTEGER,
    CLASS_AVG NUMERIC(7,1),
    CLASS_NOT_ZPR_AVG NUMERIC(7,1))
AS
DECLARE VARIABLE V$CLASS_CNT INTEGER;
DECLARE VARIABLE V$CLASS_PUB_CNT INTEGER;
DECLARE VARIABLE V$CLASS_ZPR_CNT INTEGER;
BEGIN
    FOR
        SELECT
            CASE
                WHEN CLASS_NUM BETWEEN -89 AND -1 THEN '$FFCCCC'
                WHEN CLASS_NUM=-90 THEN '$FFCC99'
                WHEN CLASS_NUM IN (-100,-200) THEN '$CCFFCC'
                WHEN CLASS_NUM<-200 THEN '$99FFFF'
            END COLOR,
            CASE
                WHEN CLASS_NUM>=0 THEN CLASS_NUM||' параллель'
                WHEN CLASS_NUM=-90 THEN 'Всего по школе'
                WHEN CLASS_NUM=-100 THEN 'Кол-во групп ГПД'
                WHEN CLASS_NUM=-200 THEN 'Кол-во уч-ся ГПД'
                WHEN CLASS_NUM=-201 THEN 'ОДОД'
                WHEN CLASS_NUM=-202 THEN 'кол-во групп'
                WHEN CLASS_NUM=-203 THEN 'фактич. кол-во уч-ся'
                WHEN CLASS_NUM=-204 THEN 'списочное кол-во уч-ся'
                ELSE 'Итого '||TRIM(IIF(CLASS_NUM=-4,'I',IIF(CLASS_NUM=-9,'II','III')))||' ступень'
            END NAME, CLASS_NUM,
            CLASS_CNT, SCHOLAR_CNT,
            CLASS_PUB_CNT, SCHOLAR_PUB_CNT, CLASS_INC_CNT, CLASS_ZPR_CNT,
            IIF(CLASS_NUM < -200, NULL, SCHOLAR_ZPR_CNT) SCHOLAR_ZPR_CNT,
            SCHOLAR_HOUSE_CNT
        FROM (
            SELECT
                CLASS_NUM,
                SUM(CLASS_CNT) CLASS_CNT,
                SUM(SCHOLAR_CNT) SCHOLAR_CNT,
                SUM(SCHOLAR_HOUSE_CNT) SCHOLAR_HOUSE_CNT,
                SUM(IIF(COALESCE(CLASS_TYPE, 197) = 197, CLASS_CNT, 0)) CLASS_PUB_CNT,
                SUM(NIS_OVZ) SCHOLAR_PUB_CNT,
                SUM(IIF(CLASS_TYPE = 13274, CLASS_CNT, 0)) CLASS_INC_CNT,
                SUM(IIF(CLASS_TYPE = 13275, CLASS_CNT, 0)) CLASS_ZPR_CNT,
                SUM(IS_OVZ) SCHOLAR_ZPR_CNT
            FROM (
                -- параллель
                SELECT
                    CLASS_NUM,
                    COUNT(DISTINCT CLASS_ID) CLASS_CNT,
                    CLASS_TYPE,
                    COUNT(1) SCHOLAR_CNT,
                    SUM(SCHOLAR_HOUSE_FL) SCHOLAR_HOUSE_CNT,
                    SUM(1 - IS_OVZ) NIS_OVZ,
                    SUM(IS_OVZ) IS_OVZ
                FROM OU_CLASS_REPORT_DTL(:I$OBJ_ID, :I$DT)
                GROUP BY CLASS_TYPE, CLASS_NUM
                UNION ALL
                -- ступень
                SELECT
                    IIF(CLASS_NUM<5,-4,IIF(CLASS_NUM<10,-9,-20)) CLASS_NUM,
                    COUNT(DISTINCT CLASS_ID) CLASS_CNT,
                    CLASS_TYPE,
                    COUNT(1) SCHOLAR_CNT,
                    SUM(SCHOLAR_HOUSE_FL) SCHOLAR_HOUSE_CNT,
                    SUM(1 - IS_OVZ) NIS_OVZ,
                    SUM(IS_OVZ) IS_OVZ
                FROM OU_CLASS_REPORT_DTL(:I$OBJ_ID, :I$DT)
                GROUP BY CLASS_TYPE, CLASS_NUM
                UNION ALL
                -- школа
                SELECT
                    -90 CLASS_NUM,
                    COUNT(DISTINCT CLASS_ID) CLASS_CNT,
                    CLASS_TYPE,
                    COUNT(1) SCHOLAR_CNT,
                    SUM(SCHOLAR_HOUSE_FL) SCHOLAR_HOUSE_CNT,
                    SUM(1 - IS_OVZ) NIS_OVZ,
                    SUM(IS_OVZ) IS_OVZ
                FROM OU_CLASS_REPORT_DTL(:I$OBJ_ID, :I$DT)
                GROUP BY CLASS_TYPE
                UNION ALL
                -- Кол-во групп ГПД
                SELECT -100 CLASS_NUM,
                    IIF(L.GPD_ID IS NULL,0,1) CLASS_CNT,
                    (
                      SELECT FIRST 1 V592.LISTVAL_ID
                      FROM LINKS L9
                      JOIN VALL V592 ON V592.OBJ_ID = L9.OBJ_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0
                      WHERE L9.PARENT_ID = L.GPD_ID AND L9.OBJ_TYPE_ID = 9 AND (:I$DT < CURRENT_DATE OR L9.DATE_DEL IS NULL)
                    ) CLASS_TYPE,
                    NULL SCHOLAR_CNT,
                    NULL SCHOLAR_HOUSE_CNT,
                    NULL NIS_OVZ,
                    NULL IS_OVZ
                FROM RDB$DATABASE
                LEFT JOIN (
                    SELECT DISTINCT(GPD_ID)
                    FROM OU_CLASS_REPORT_GPD(:I$OBJ_ID, :I$DT)) L ON 1=1
                UNION ALL
                -- Кол-во уч-ся ГПД
                SELECT -200 CLASS_NUM, NULL CLASS_CNT, L.CLASS_TYPE, COUNT(DISTINCT L.SCHOLAR_ID) SCHOLAR_CNT, NULL SCHOLAR_HOUSE_CNT, NULL NIS_OVZ, NULL IS_OVZ
                FROM RDB$DATABASE
                LEFT JOIN OU_CLASS_REPORT_GPD(:I$OBJ_ID, :I$DT) L ON 1 = 1
                GROUP BY L.CLASS_TYPE
                UNION ALL
                SELECT -201, NULL, NULL, NULL, NULL, NULL, NULL FROM RDB$DATABASE
                UNION ALL
                SELECT -202, NULL, NULL, NULL, NULL, NULL, NULL FROM RDB$DATABASE
                UNION ALL
                SELECT -203, NULL, NULL, NULL, NULL, NULL, NULL FROM RDB$DATABASE
                UNION ALL
                SELECT -204, NULL, NULL, NULL, NULL, NULL, NULL FROM RDB$DATABASE
                )
            GROUP BY CLASS_NUM
            )
        ORDER BY ABS(CLASS_NUM), CLASS_CNT
        INTO :COLOR, :NAME, :CLASS_NUM, :CLASS_CNT, :SCHOLAR_CNT, :CLASS_PUB_CNT, :SCHOLAR_PUB_CNT,
             :CLASS_INC_CNT, :CLASS_ZPR_CNT, :SCHOLAR_ZPR_CNT, :SCHOLAR_HOUSE_CNT
    DO
    BEGIN
        IF (CLASS_NUM = -100) THEN
        BEGIN
            V$CLASS_CNT = CLASS_CNT;
            V$CLASS_PUB_CNT = CLASS_PUB_CNT;
            V$CLASS_ZPR_CNT = CLASS_ZPR_CNT;
        END
        IF (CLASS_NUM = -200) THEN
        BEGIN
            CLASS_CNT = V$CLASS_CNT;
            CLASS_PUB_CNT = V$CLASS_PUB_CNT;
            CLASS_ZPR_CNT = V$CLASS_ZPR_CNT;
        END
        CLASS_AVG = CAST(CAST(SCHOLAR_CNT AS FLOAT)/IIF(CLASS_CNT = 0, 1, CLASS_CNT) AS NUMERIC(7,1));
        CLASS_NOT_ZPR_AVG = CAST(CAST(SCHOLAR_CNT-SCHOLAR_ZPR_CNT AS FLOAT)/IIF(CLASS_CNT-CLASS_ZPR_CNT = 0, 1, CLASS_CNT-CLASS_ZPR_CNT) AS NUMERIC(7,1));
        IF (CLASS_NUM = -200) THEN
        BEGIN
            CLASS_CNT = NULL;
            CLASS_PUB_CNT = NULL;
            CLASS_ZPR_CNT = NULL;
        END
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OU_CLASS_REPORT2 (
    I$OBJ_ID BIGINT,
    CLASS_NUM INTEGER = -90,
    SCHOLAR_HOUSE_FL SMALLINT = 0,
    SCHOLAR_ZPR_FL SMALLINT = null,
    I$DT DATE = current_date)
RETURNS (
    VAL1 VARCHAR(250),
    VAL2 VARCHAR(250),
    VAL3 VARCHAR(250))
AS
BEGIN
    FOR
        SELECT
            (SELECT CAPTION FROM OBJECT_CAPTION_GET(SCHOLAR_ID)) VAL1,
            (SELECT D FROM VAL_GET(SCHOLAR_ID, 89)) VAL2,
            (SELECT CAPTION FROM OBJECT_CAPTION_GET
                ((SELECT PARENT_ID
                 FROM LINKS
                 WHERE LINK_ID =
                     (SELECT MAX(L.LINK_ID)
                      FROM LINKS L
                      WHERE L.OBJ_ID = SCHOLAR_ID AND L.PARENT_TYPE_ID IN (9,10,81,82,83) AND L.DATE_DEL IS NULL
                     )
                ))
            ) VAL3
        FROM (
            SELECT DISTINCT SCHOLAR_ID
            FROM OU_CLASS_REPORT_DTL(:I$OBJ_ID, :I$DT)
            WHERE (COALESCE(:CLASS_NUM,-90) = -90
                OR (:CLASS_NUM = -4 AND CLASS_NUM < 5)
                OR (:CLASS_NUM = -9 AND CLASS_NUM BETWEEN 5 AND 9)
                OR (:CLASS_NUM =-20 AND CLASS_NUM > 9)
                OR (:CLASS_NUM >= 0 AND CLASS_NUM = :CLASS_NUM))
              AND (:SCHOLAR_ZPR_FL IS NULL
                OR (:SCHOLAR_ZPR_FL = 0 AND COALESCE(CLASS_TYPE, 197) = 197)
                OR (:SCHOLAR_ZPR_FL = 1 AND CLASS_TYPE = 13275)
                OR (:SCHOLAR_ZPR_FL = 2 AND CLASS_TYPE = 13274)
                OR (:SCHOLAR_ZPR_FL = 10 AND IS_OVZ = 0)
                OR (:SCHOLAR_ZPR_FL = 11 AND IS_OVZ = 1)
              )
              AND (COALESCE(:SCHOLAR_HOUSE_FL, 0) = 0 OR SCHOLAR_HOUSE_FL = 1)
            UNION ALL
            SELECT SCHOLAR_ID
            FROM OU_CLASS_REPORT_GPD(:I$OBJ_ID, :I$DT)
            WHERE (:SCHOLAR_ZPR_FL IS NULL
              OR (:SCHOLAR_ZPR_FL = 0 AND COALESCE(CLASS_TYPE, 197) = 197)
              OR (:SCHOLAR_ZPR_FL = 1 AND CLASS_TYPE = 13275)
              OR (:SCHOLAR_ZPR_FL = 2 AND CLASS_TYPE = 13274)
              OR (:SCHOLAR_ZPR_FL = 10 AND IS_OVZ = 0)
              OR (:SCHOLAR_ZPR_FL = 11 AND IS_OVZ = 1)
            )
            AND :CLASS_NUM = -200
        ) ORDER BY VAL1
        INTO :VAL1, :VAL2, :VAL3
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OU_CLASS_REPORT_DTL (
    I$OBJ_ID BIGINT,
    I$DT DATE = CURRENT_DATE)
RETURNS (
    CLASS_NUM INTEGER,
    CLASS_TYPE INTEGER,
    CLASS_ID BIGINT,
    SCHOLAR_ID BIGINT,
    SCHOLAR_HOUSE_FL SMALLINT,
    IS_OVZ SMALLINT)
AS
DECLARE VARIABLE V$M1 BIGINT;
DECLARE VARIABLE V$M2 BIGINT;
BEGIN

  IF(I$DT IS NULL) THEN I$DT = CURRENT_DATE;
  I$OBJ_ID = I$OBJ_ID / 1000000000;
  V$M1 = I$OBJ_ID * 1000000000;
  V$M2 = (I$OBJ_ID + 1) * 1000000000;

  -- Первый цикл по всем детям, кроме надомников, когда-либо бывших в реальных коллективах, но покинувшие их не ранее даты на которую требуется отчет
  FOR
    SELECT DISTINCT M.PERSON_ID, IIF(V2169.OBJ_ID IS NULL OR V2169.LISTVAL_ID = 3, 0, 1)
    FROM PERSON_MOVEMENTS M
    LEFT JOIN VALL V2169 ON V2169.OBJ_ID = M.PERSON_ID AND V2169.PARAM_ID = 2169 AND V2169.IS_DEL = 0
    WHERE M.DATE_DEL IS NULL AND M.OBJ_ID >= :V$M1 AND M.OBJ_ID < :V$M2 AND M.DATE_IN <= :I$DT AND (M.DATE_OUT IS NULL OR M.DATE_OUT > :I$DT)
      AND M.GROUP_TYPE_ID = 9
    INTO :SCHOLAR_ID, :SCHOLAR_HOUSE_FL
  DO
  BEGIN
    SELECT FIRST 1 M.GROUP_ID, M.TYPE_IN, LV.COST
    FROM PERSON_MOVEMENTS M
    JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
    JOIN LISTVALS LV ON LV.LISTVAL_ID = M.STAGE_ID
    WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :SCHOLAR_ID AND M.DATE_IN <= :I$DT AND (M.DATE_OUT IS NULL OR M.DATE_OUT > :I$DT)
    ORDER BY M.DATE_IN DESC
    INTO :CLASS_ID, :CLASS_TYPE, :CLASS_NUM;

    -- 5 (Нет) - из-за некорректной конвертации, сейчас все уже только 13289
    IS_OVZ = 0;
    SELECT FIRST 1 1
    FROM VALL V207
    WHERE V207.OBJ_ID = :SCHOLAR_ID AND V207.PARAM_ID = 207 AND V207.IS_DEL = 0 AND V207.LISTVAL_ID <> 13289 AND V207.LISTVAL_ID <> 5
    INTO :IS_OVZ;

    SUSPEND;
  END

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OU_CLASS_REPORT_GPD (
    I$OBJ_ID BIGINT,
    I$DT DATE = current_date,
    I$GPD_ONLY SMALLINT = 1)
RETURNS (
    CLASS_NUM INTEGER,
    CLASS_TYPE INTEGER,
    GPD_ID BIGINT,
    SCHOLAR_ID BIGINT,
    IS_OVZ SMALLINT)
AS
declare variable V$M1 bigint;
declare variable V$M2 bigint;
BEGIN

  IF(I$DT IS NULL) THEN I$DT = CURRENT_DATE;
  I$OBJ_ID = I$OBJ_ID / 1000000000;
  V$M1 = I$OBJ_ID * 1000000000;
  V$M2 = (I$OBJ_ID + 1) * 1000000000;

  -- Первый цикл по всем детям, кроме надомников, когда-либо бывших в реальных коллективах, но покинувшие их не ранее даты на которую требуется отчет
  FOR
    SELECT DISTINCT M.PERSON_ID, M.TYPE_IN, LV.COST, M2.GROUP_ID
    FROM PERSON_MOVEMENTS M
    JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
    JOIN LISTVALS LV ON LV.LISTVAL_ID = M.STAGE_ID
    JOIN PERSON_MOVEMENTS M2 ON M2.DATE_DEL IS NULL AND M2.PERSON_ID = M.PERSON_ID AND M2.DATE_IN <= :I$DT AND (M2.DATE_OUT IS NULL OR M2.DATE_OUT >= :I$DT)
    JOIN OBJECTS G2 ON G2.OBJ_ID = M2.GROUP_ID AND G2.TYPE_ID = 46
    JOIN VALL V369 ON V369.OBJ_ID = G2.OBJ_ID AND V369.PARAM_ID = 369 AND V369.IS_DEL = 0 AND V369.LISTVAL_ID = 1246
    WHERE M.DATE_DEL IS NULL AND M.OBJ_ID >= :V$M1 AND M.OBJ_ID < :V$M2 AND M.DATE_IN <= :I$DT AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :I$DT)
    INTO :SCHOLAR_ID, :CLASS_TYPE, :CLASS_NUM, :GPD_ID
  DO
  BEGIN
    -- Непонятно откуда вылезшее значение 5 (Нет)
    IS_OVZ = 0;
    SELECT FIRST 1 1
    FROM VALL V207
    WHERE V207.OBJ_ID = :SCHOLAR_ID AND V207.PARAM_ID = 207 AND V207.IS_DEL = 0 AND V207.LISTVAL_ID <> 13289 AND V207.LISTVAL_ID <> 5
    INTO :IS_OVZ;

    SUSPEND;
  END

END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OU_EDU_DO_COMMIT (
    I$OU_ID BIGINT,
    I$ILL_STUDENTS INTEGER,
    I$ILL_EMPLOYEES INTEGER,
    I$USER_ID VARCHAR(40))
RETURNS (
    OBJ_ID BIGINT)
AS
DECLARE VARIABLE S VARCHAR(8000);
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$CAPTION VARCHAR(400);
DECLARE VARIABLE V$GRADE BIGINT;
DECLARE VARIABLE V$DO SMALLINT;
DECLARE VARIABLE V$AGE SMALLINT;
DECLARE VARIABLE D1 DATE;
DECLARE VARIABLE D2 DATE;
DECLARE VARIABLE V$OU_LICENCE_TYPE CHAR(1);
DECLARE VARIABLE N1 INTEGER;
DECLARE VARIABLE N2 INTEGER;
DECLARE VARIABLE N3 INTEGER;
begin

  -- Сохраняем данные в CS_REPORTS с текущей датой, в строковом формате
  SELECT FIRST 1 R.OBJ_ID
  FROM CS_REPORTS R
  WHERE R.DATE_DEL IS NULL AND R.OU_ID = :I$OU_ID AND R.APPROVE_DATE = CURRENT_DATE
  INTO :OBJ_ID;

  V$OU_LICENCE_TYPE = (SELECT STATUS FROM OU_LICENCE_TYPE);

  -- Формируем структуру xml
  -- Количество заболевших персон
  S = 'ill;' || I$ILL_STUDENTS || ';' || I$ILL_EMPLOYEES || ASCII_CHAR(10);

  -- Разбивка по параллелям и классам
  FOR
    SELECT L9.OBJ_ID, C.SCAPTION, LV49.LISTVAL_ID, COALESCE(V3053.LISTVAL_ID, 3)
    FROM LINKS L7
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
    JOIN LISTVALS LV49 ON LV49.LISTVAL_ID = V49.LISTVAL_ID
    JOIN RES R ON R.RES_ID = LV49.RES_ID AND R.LANG_CODE = 'RU'
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
    LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C ON 1 = 1
    LEFT JOIN VALL V3053 ON V3053.OBJ_ID = L9.OBJ_ID AND V3053.PARAM_ID = 3053 AND V3053.IS_DEL = 0
    WHERE L7.PARENT_ID = :I$OU_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    ORDER BY LV49.COST, 2
    INTO :V$OBJ_ID, :V$CAPTION, :V$GRADE, :V$DO
  DO
  BEGIN
    V$CAPTION = REPLACE(V$CAPTION, ';', ',');
    S = S || 'g;' || V$GRADE || ';' || V$CAPTION || ';' || IIF(V$DO = 2, '1', '0') || ';';

    N1 = (SELECT COUNT(*) FROM LINKS L10 WHERE L10.PARENT_ID = :V$OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL);
    IF(V$DO = 2) THEN N2 = N1; ELSE N2 = 0;
    N3 = (
      SELECT COUNT(*)
      FROM LINKS L10
      JOIN PERSON_MOVEMENTS M ON M.DATE_DEL IS NULL AND M.PERSON_ID = L10.OBJ_ID AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= CURRENT_DATE)
      JOIN OBJECTS OBJ ON OBJ.OBJ_ID = M.GROUP_ID AND OBJ.TYPE_ID = 338
      WHERE L10.PARENT_ID = :V$OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    );
    IF(V$OU_LICENCE_TYPE = 'D') THEN N3 = 0;

    N2 = N2 - N3;
    IF(N2 < 0) THEN N2 = 0;

    S = S || N1 || ';';
    -- Новый показатель количества - учащиеся в классе на ДО
    S = S || N2 || ';';
    -- Изменено - учащиеся индивидуальном ДО
    S = S || N3;

    S = S || ASCII_CHAR(10);
  END

  -- Разбивка по возрастам
  V$AGE = 1;
  WHILE(V$AGE <= 20) DO
  BEGIN
    D1 = DATEADD(- V$AGE YEAR TO CURRENT_DATE);
    D2 = DATEADD(1 YEAR TO D1);
    IF(V$AGE = 1) THEN D2 = CURRENT_DATE;  -- < 1Y
    IF(V$AGE = 20) THEN D1 = '01.01.1980'; -- 20Y+
    S = S || 'a;' || V$AGE || ';';
      S = S || (
        SELECT COUNT(*)
        FROM LINKS L10
        JOIN VALD V89 ON V89.OBJ_ID = L10.OBJ_ID AND V89.PARAM_ID = 89 AND V89.IS_DEL = 0 AND V89.VAL >= :D1 AND V89.VAL < :D2
        JOIN LINKS LP8 ON LP8.OBJ_ID = L10.PARENT_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
        WHERE L10.PARENT_TYPE_ID = 9 AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      ) || ';';
      IF(V$OU_LICENCE_TYPE = 'D') THEN
      BEGIN
        S = S || (
          SELECT COUNT(*)
          FROM LINKS L10
          JOIN VALD V89 ON V89.OBJ_ID = L10.OBJ_ID AND V89.PARAM_ID = 89 AND V89.IS_DEL = 0 AND V89.VAL >= :D1 AND V89.VAL < :D2
          JOIN LINKS LP8 ON LP8.OBJ_ID = L10.PARENT_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
          JOIN VALL V3053 ON V3053.OBJ_ID = L10.PARENT_ID AND V3053.PARAM_ID = 3053 AND V3053.IS_DEL = 0 AND V3053.LISTVAL_ID = 2
          WHERE L10.PARENT_TYPE_ID = 9 AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        ) || ';';
      END
      ELSE
      BEGIN
        S = S || (
          SELECT COUNT(*)
          FROM LINKS L10
          JOIN VALD V89 ON V89.OBJ_ID = L10.OBJ_ID AND V89.PARAM_ID = 89 AND V89.IS_DEL = 0 AND V89.VAL >= :D1 AND V89.VAL < :D2
          JOIN PERSON_MOVEMENTS M ON M.DATE_DEL IS NULL AND M.PERSON_ID = L10.OBJ_ID AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= CURRENT_DATE)
          JOIN OBJECTS OBJ ON OBJ.OBJ_ID = M.GROUP_ID AND OBJ.TYPE_ID = 338
          JOIN LINKS LP8 ON LP8.OBJ_ID = L10.PARENT_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
          WHERE L10.PARENT_TYPE_ID = 9 AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        ) || ';';
      END
    S = S || ASCII_CHAR(10);
    V$AGE = V$AGE + 1;
  END

  IF(OBJ_ID IS NULL) THEN
  BEGIN
    INSERT INTO CS_REPORTS
    (OU_ID, APPROVE_DATE, STATE_ID, VAL)
    VALUES (:I$OU_ID, CURRENT_DATE, 0, :S)
    RETURNING OBJ_ID INTO :OBJ_ID;
  END
  ELSE
  BEGIN
    UPDATE CS_REPORTS
    SET VAL = :S, STATE_ID = 0
    WHERE OBJ_ID = :OBJ_ID;
  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OU_EDU_DO_DATA (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(1000))
AS
declare variable V$CLASS_ID bigint;
declare variable S varchar(1000);
declare variable V$DIST smallint;
declare variable S2 varchar(200);
declare variable V$OU_LICENCE_TYPE char(1);
declare variable N1 integer;
declare variable N2 integer;
declare variable N3 integer;
begin

  -- Показываем текущую общую статистику в разрезе классов (групп)
  V$OU_LICENCE_TYPE = (SELECT STATUS FROM OU_LICENCE_TYPE);
  TAG_NAME = 'type';
  VAL = V$OU_LICENCE_TYPE;
  SUSPEND;

  TAG_NAME = 'groups::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L9.OBJ_ID, C.CAPTION, R.VAL, COALESCE(V3053.LISTVAL_ID, 3)
    FROM LINKS L7
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
    JOIN LISTVALS LV49 ON LV49.LISTVAL_ID = V49.LISTVAL_ID
    JOIN RES R ON R.RES_ID = LV49.RES_ID AND R.LANG_CODE = 'RU'
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
    LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C ON 1 = 1
    LEFT JOIN VALL V3053 ON V3053.OBJ_ID = L9.OBJ_ID AND V3053.PARAM_ID = 3053 AND V3053.IS_DEL = 0
    WHERE L7.PARENT_ID = :I$OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    ORDER BY LV49.COST, 2
    INTO :V$CLASS_ID, :S, :S2, :V$DIST
  DO
  BEGIN
    N1 = (SELECT COUNT(*) FROM LINKS L10 WHERE L10.PARENT_ID = :V$CLASS_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL);
    IF(V$DIST = 2) THEN N2 = N1; ELSE N2 = 0;
    N3 = (
      SELECT COUNT(*)
      FROM LINKS L10
      JOIN PERSON_MOVEMENTS M ON M.DATE_DEL IS NULL AND M.PERSON_ID = L10.OBJ_ID AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= CURRENT_DATE)
      JOIN OBJECTS OBJ ON OBJ.OBJ_ID = M.GROUP_ID AND OBJ.TYPE_ID = 338
      WHERE L10.PARENT_ID = :V$CLASS_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    );
    IF(V$OU_LICENCE_TYPE = 'D') THEN N3 = 0;

    TAG_NAME = 'groups:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'groups:r:id';
    VAL = V$CLASS_ID;
    SUSPEND;
    TAG_NAME = 'groups:r:name';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'groups:r:grade_name';
    VAL = S2;
    SUSPEND;
    TAG_NAME = 'groups:r:class_dist';
    VAL = IIF(V$DIST = 2, 1, 0);
    SUSPEND;
    TAG_NAME = 'groups:r:n_students';
    VAL = N1;
    SUSPEND;
    TAG_NAME = 'groups:r:n_students_dist';
    N2 = N2 - N3;
    IF(N2 < 0) THEN N2 = 0;
    VAL = N2;
    SUSPEND;
    TAG_NAME = 'groups:r:n_students_ind';
    VAL = N3;
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OU_EDU_DO_OUTDATA (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(8000))
AS
declare variable V$DATE date;
declare variable V varchar(8000);
declare variable S varchar(1000);
declare variable P integer;
declare variable V$AGE smallint;
declare variable V$N1 integer;
declare variable V$N2 integer;
declare variable V$MD date;
declare variable V$GRADE_ID bigint;
declare variable V$SUBJECT_ID bigint;
declare variable V$CHECKDATE date;
declare variable V$OBJ_ID bigint;
declare variable V$MODATE date;
declare variable V$CID bigint;
declare variable V$NP integer;
declare variable V$NPC integer;
declare variable V$NM1 integer;
declare variable V$NM2 integer;
declare variable V$NM3 integer;
declare variable V$NM4 integer;
declare variable V$NM5 integer;
declare variable V$NM6 integer;
declare variable V$NM7 integer;
begin

  SELECT FIRST 1 R.APPROVE_DATE, R.VAL
  FROM CS_REPORTS R
  WHERE R.DATE_DEL IS NULL AND R.OU_ID = :I$OBJ_ID
  ORDER BY R.APPROVE_DATE DESC
  INTO :V$DATE, :V;

  TAG_NAME = 'org_id';
  VAL = I$OBJ_ID;
  SUSPEND;

  TAG_NAME = 'approve_date';
  VAL = (SELECT VAL FROM DATE2ISO(:V$DATE, 0));
  SUSPEND;

  IF(V$DATE IS NULL) THEN EXIT;

  -- Контрольная дата для подчета количества вернувшихся
  V$CHECKDATE = '11.01.2021';
  IF(V$CHECKDATE > '29.03.2021') THEN V$CHECKDATE = '29.03.2021';

  -- Если отправка после 15:00, то смотрим текущий день. Если раньше, то предыдущий
  V$MD = CURRENT_DATE;
  IF(EXTRACT(HOUR FROM CURRENT_TIMESTAMP) < 15) THEN V$MD = DATEADD(-1 DAY TO V$MD);
  IF(EXTRACT(WEEKDAY FROM V$MD) = 0) THEN V$MD = DATEADD(-1 DAY TO V$MD);
  IF(EXTRACT(WEEKDAY FROM V$MD) = 6) THEN
  BEGIN
    -- Суббота - учебная ? Проверяем, есть ли учебный план с шестидневкой
    IF(NOT EXISTS(
      SELECT FIRST 1 1
      FROM LINKS L50
      JOIN LINKS L54 ON L54.PARENT_ID = L50.OBJ_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
      JOIN VALL V2837 ON V2837.OBJ_ID = L54.OBJ_ID AND V2837.PARAM_ID = 2837 AND V2837.IS_DEL = 0 AND V2837.LISTVAL_ID = 11719
      WHERE L50.PARENT_TYPE_ID = 57 AND L50.OBJ_TYPE_ID = 50 AND L50.DATE_DEL IS NULL
    ))
    THEN V$MD = DATEADD(-1 DAY TO V$MD);
  END
  TAG_NAME = 'control_date';
  VAL = (SELECT VAL FROM DATE2ISO(:V$MD, 0));
  SUSPEND;

  -- Первая строка должна быть ill в новом формате
  IF(SUBSTRING(V FROM 1 FOR 4) = 'ill;') THEN
  BEGIN
    P = POSITION(ASCII_CHAR(10) IN V);
    IF(P <= 0) THEN P = CHAR_LENGTH(V) + 1;
    S = SUBSTRING(V FROM 1 FOR P - 1);
    V = SUBSTRING(V FROM P + 1);
    S = SUBSTRING(S FROM 5);
    P = POSITION(';' IN S);
    V$N1 = SUBSTRING(S FROM 1 FOR P - 1);
    V$N2 = SUBSTRING(S FROM P + 1);
  END
  ELSE
  BEGIN
    V$N1 = 0;
    V$N2 = 0;
  END
  TAG_NAME = 'ill:students';
  VAL = V$N1;
  SUSPEND;
  TAG_NAME = 'ill:employees';
  VAL = V$N2;
  SUSPEND;

  V$AGE = 0;

  -- Разом выдаем данные и по группам, и по возрастам
  TAG_NAME = 'groups::json&colon;array';
  VAL = 1;
  SUSPEND;
  WHILE(CHAR_LENGTH(V) > 0) DO
  BEGIN
    P = POSITION(ASCII_CHAR(10) IN V);
    IF(P <= 0) THEN P = CHAR_LENGTH(V) + 1;
    S = SUBSTRING(V FROM 1 FOR P - 1);
    V = SUBSTRING(V FROM P + 1);

    IF(SUBSTRING(S FROM 1 FOR 1) = 'g') THEN
    BEGIN
      S = SUBSTRING(S FROM 3);
      TAG_NAME = 'groups:g';
      VAL = NULL;
      SUSPEND;
      P = POSITION(';' IN S);
      TAG_NAME = 'groups:g:grade';
      VAL = SUBSTRING(S FROM 1 FOR P - 1);
      SUSPEND;
      S = SUBSTRING(S FROM P + 1);
      P = POSITION(';' IN S);
      TAG_NAME = 'groups:g:name';
      VAL = SUBSTRING(S FROM 1 FOR P - 1);
      SUSPEND;

      -- По названию выбираем id
      SELECT FIRST 1 L9.OBJ_ID
      FROM LINKS L9
      LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C ON 1 = 1
      WHERE L9.PARENT_TYPE_ID = 8 AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL AND C.CAPTION = :VAL
      INTO :V$GRADE_ID;

      S = SUBSTRING(S FROM P + 1);
      P = POSITION(';' IN S);
      TAG_NAME = 'groups:g:is_do';
      VAL = SUBSTRING(S FROM 1 FOR P - 1);
      SUSPEND;
      S = SUBSTRING(S FROM P + 1);
      P = POSITION(';' IN S);
      TAG_NAME = 'groups:g:n_students';
      VAL = SUBSTRING(S FROM 1 FOR P - 1);
      SUSPEND;
      S = SUBSTRING(S FROM P + 1);
      -- Если тут есть точка с запятой, значит имеем новый формат с двумя количествами
      P = POSITION(';' IN S);
      IF(P > 0) THEN
      BEGIN
        TAG_NAME = 'groups:g:n_students_do';
        VAL = SUBSTRING(S FROM 1 FOR P - 1);
        S = SUBSTRING(S FROM P + 1);
        SUSPEND;
      END
      TAG_NAME = 'groups:g:n_students_ind';
      VAL = REPLACE(S, ';', '');
      SUSPEND;

      -- Дополнения по выборкам от 15.12.2020 и 11.01.2021, статистика за указанную дату
      -- Возврат со смешанного на очное
      TAG_NAME = 'groups:g:n_returned';
      VAL = NULL;
      SELECT COUNT(DISTINCT L10.OBJ_ID)
      FROM LINKS L10
      JOIN PERSON_MOVEMENTS M ON M.DATE_DEL IS NULL AND M.PERSON_ID = L10.OBJ_ID AND M.DATE_OUT IS NOT NULL AND M.DATE_OUT < CURRENT_DATE AND M.DATE_OUT >= :V$CHECKDATE
      -- нет записи возврата авансом
      LEFT JOIN PERSON_MOVEMENTS M2 ON M2.DATE_DEL IS NULL AND M2.PERSON_ID = L10.OBJ_ID AND (M2.DATE_OUT IS NULL OR M2.DATE_OUT >= CURRENT_DATE)
      JOIN OBJECTS OBJ ON OBJ.OBJ_ID = M.GROUP_ID AND OBJ.TYPE_ID = 338
      WHERE L10.PARENT_ID = :V$GRADE_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL AND M2.OBJ_ID IS NULL
      INTO :VAL;
      SUSPEND;

      -- Максимальное количество уроков у учеников класса
      TAG_NAME = 'groups:g:lessons';
      VAL = NULL;
      SELECT COALESCE(MAX(D.CNT), 0)
      FROM (
        SELECT L10.OBJ_ID, COUNT(*) CNT
        FROM LINKS L10
        JOIN LINKS LPG ON LPG.OBJ_ID = L10.OBJ_ID AND LPG.PARENT_TYPE_ID = 179 AND LPG.DATE_DEL IS NULL
        JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.GRADE_ID = LPG.PARENT_ID AND J.JOURNAL_TYPE = 0
        JOIN CJ2_JOURNAL_LESSONS CJL ON CJL.DATE_DEL IS NULL AND CJL.CJ_ID = J.OBJ_ID AND CJL.LESSON_DATE = :V$MD
        WHERE L10.PARENT_ID = :V$GRADE_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        GROUP BY 1
      ) D
      INTO :VAL;
      SUSPEND;

      -- Количество проставленных отметок по значениям
      TAG_NAME = 'groups:g:marks2';
      SELECT COUNT(*)
      FROM LINKS L10
      JOIN CJ2_MARK M ON M.DATE_DEL IS NULL AND M.STUDENT_ID = L10.OBJ_ID AND M.MARK_TYPE_ID = 402 AND M.MARK_DATE = :V$MD
      JOIN CJ2_CONTROL C ON C.CONTROL_ID = M.CONTROL_ID AND C.DATE_DEL IS NULL
      JOIN CJ2_JOURNAL_LESSONS L ON L.OBJ_ID = C.LESSON_ID AND L.DATE_DEL IS NULL
      JOIN CJ2_JOURNAL J ON J.OBJ_ID = L.CJ_ID AND J.DATE_DEL IS NULL AND J.JOURNAL_TYPE = 0
      WHERE L10.PARENT_ID = :V$GRADE_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      INTO :VAL;
      SUSPEND;

      TAG_NAME = 'groups:g:marks3';
      SELECT COUNT(*)
      FROM LINKS L10
      JOIN CJ2_MARK M ON M.DATE_DEL IS NULL AND M.STUDENT_ID = L10.OBJ_ID AND M.MARK_TYPE_ID = 403 AND M.MARK_DATE = :V$MD
      JOIN CJ2_CONTROL C ON C.CONTROL_ID = M.CONTROL_ID AND C.DATE_DEL IS NULL
      JOIN CJ2_JOURNAL_LESSONS L ON L.OBJ_ID = C.LESSON_ID AND L.DATE_DEL IS NULL
      JOIN CJ2_JOURNAL J ON J.OBJ_ID = L.CJ_ID AND J.DATE_DEL IS NULL AND J.JOURNAL_TYPE = 0
      WHERE L10.PARENT_ID = :V$GRADE_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      INTO :VAL;
      SUSPEND;

      TAG_NAME = 'groups:g:marks4';
      SELECT COUNT(*)
      FROM LINKS L10
      JOIN CJ2_MARK M ON M.DATE_DEL IS NULL AND M.STUDENT_ID = L10.OBJ_ID AND M.MARK_TYPE_ID = 404 AND M.MARK_DATE = :V$MD
      JOIN CJ2_CONTROL C ON C.CONTROL_ID = M.CONTROL_ID AND C.DATE_DEL IS NULL
      JOIN CJ2_JOURNAL_LESSONS L ON L.OBJ_ID = C.LESSON_ID AND L.DATE_DEL IS NULL
      JOIN CJ2_JOURNAL J ON J.OBJ_ID = L.CJ_ID AND J.DATE_DEL IS NULL AND J.JOURNAL_TYPE = 0
      WHERE L10.PARENT_ID = :V$GRADE_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      INTO :VAL;
      SUSPEND;

      TAG_NAME = 'groups:g:marks5';
      SELECT COUNT(*)
      FROM LINKS L10
      JOIN CJ2_MARK M ON M.DATE_DEL IS NULL AND M.STUDENT_ID = L10.OBJ_ID AND M.MARK_TYPE_ID = 405 AND M.MARK_DATE = :V$MD
      JOIN CJ2_CONTROL C ON C.CONTROL_ID = M.CONTROL_ID AND C.DATE_DEL IS NULL
      JOIN CJ2_JOURNAL_LESSONS L ON L.OBJ_ID = C.LESSON_ID AND L.DATE_DEL IS NULL
      JOIN CJ2_JOURNAL J ON J.OBJ_ID = L.CJ_ID AND J.DATE_DEL IS NULL AND J.JOURNAL_TYPE = 0
      WHERE L10.PARENT_ID = :V$GRADE_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      INTO :VAL;
      SUSPEND;

      -- Сколько всего пропусков уроков
      TAG_NAME = 'groups:g:t_miss';
      VAL = NULL;
      SELECT COUNT(*)
      FROM LINKS L10
      JOIN CJ2_MARK M ON M.DATE_DEL IS NULL AND M.STUDENT_ID = L10.OBJ_ID AND M.MARK_TYPE_ID IN (91, 92, 93, 94)
      JOIN CJ2_CONTROL C ON C.CONTROL_ID = M.CONTROL_ID AND C.DATE_DEL IS NULL
      JOIN CJ2_JOURNAL_LESSONS L ON L.OBJ_ID = C.LESSON_ID AND L.DATE_DEL IS NULL AND L.LESSON_DATE = :V$MD
      JOIN CJ2_JOURNAL J ON J.OBJ_ID = L.CJ_ID AND J.DATE_DEL IS NULL AND J.JOURNAL_TYPE = 0
      WHERE L10.PARENT_ID = :V$GRADE_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      INTO :VAL;
      SUSPEND;

      -- Сколько учеников отсутствовали более чем на 2 уроках
      TAG_NAME = 'groups:g:n_miss';
      VAL = NULL;
      SELECT COUNT(*)
      FROM (
        SELECT L10.OBJ_ID, COUNT(*) CNT
        FROM LINKS L10
        JOIN CJ2_MARK M ON M.DATE_DEL IS NULL AND M.STUDENT_ID = L10.OBJ_ID AND M.MARK_TYPE_ID IN (91, 92, 93, 94)
        JOIN CJ2_CONTROL C ON C.CONTROL_ID = M.CONTROL_ID AND C.DATE_DEL IS NULL
        JOIN CJ2_JOURNAL_LESSONS L ON L.OBJ_ID = C.LESSON_ID AND L.DATE_DEL IS NULL AND L.LESSON_DATE = :V$MD
        JOIN CJ2_JOURNAL J ON J.OBJ_ID = L.CJ_ID AND J.DATE_DEL IS NULL AND J.JOURNAL_TYPE = 0
        WHERE L10.PARENT_ID = :V$GRADE_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        GROUP BY 1
      ) D
      WHERE D.CNT > 2
      INTO :VAL;
      SUSPEND;

      -- По скольки ученикам нет отметок более чем 1 месяц по какому-нибудь предмету
      TAG_NAME = 'groups:g:n_nomark';
      VAL = NULL;
      SELECT COUNT(DISTINCT OBJ_ID)
      FROM (
        SELECT L10.OBJ_ID, CJM.SUBJECT_ID, COUNT(M.MARK_ID) CNT
        FROM LINKS L10
        JOIN LINKS LPG ON LPG.OBJ_ID = L10.OBJ_ID AND LPG.PARENT_TYPE_ID = 179 AND LPG.DATE_DEL IS NULL
        JOIN CJ2_JOURNAL CJM ON CJM.DATE_DEL IS NULL AND CJM.GRADE_ID = LPG.PARENT_ID AND CJM.JOURNAL_TYPE = 0
        LEFT JOIN CJ2_JOURNAL_LESSONS L ON L.DATE_DEL IS NULL AND L.CJ_ID = CJM.OBJ_ID AND L.LESSON_DATE BETWEEN DATEADD(-1 MONTH TO :V$MD) AND :V$MD
        LEFT JOIN CJ2_CONTROL C ON C.DATE_DEL IS NULL AND C.LESSON_ID = L.OBJ_ID AND C.CONTROL_TYPE_ID > 0
        LEFT JOIN CJ2_MARK M ON C.DATE_DEL IS NULL AND C.CONTROL_ID = M.CONTROL_ID AND M.STUDENT_ID = L10.OBJ_ID
        WHERE L10.PARENT_ID = :V$GRADE_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        GROUP BY 1, 2
      )
      WHERE CNT = 0
      INTO :VAL;
      SUSPEND;

      -- По каким предметам нет отметок более чем 1 месяц
      TAG_NAME = 'groups:g:s_nomark';
      VAL = '';
      FOR
        SELECT DISTINCT SUBJECT_ID
        FROM (
          SELECT L10.OBJ_ID, CJM.SUBJECT_ID, COUNT(M.MARK_ID) CNT
          FROM LINKS L10
          JOIN LINKS LPG ON LPG.OBJ_ID = L10.OBJ_ID AND LPG.PARENT_TYPE_ID = 179 AND LPG.DATE_DEL IS NULL
          JOIN CJ2_JOURNAL CJM ON CJM.DATE_DEL IS NULL AND CJM.GRADE_ID = LPG.PARENT_ID AND CJM.JOURNAL_TYPE = 0
          LEFT JOIN CJ2_JOURNAL_LESSONS L ON L.DATE_DEL IS NULL AND L.CJ_ID = CJM.OBJ_ID AND L.LESSON_DATE BETWEEN DATEADD(-1 MONTH TO :V$MD) AND :V$MD
          LEFT JOIN CJ2_CONTROL C ON C.DATE_DEL IS NULL AND C.LESSON_ID = L.OBJ_ID AND C.CONTROL_TYPE_ID > 0
          LEFT JOIN CJ2_MARK M ON C.DATE_DEL IS NULL AND C.CONTROL_ID = M.CONTROL_ID AND M.STUDENT_ID = L10.OBJ_ID
          WHERE L10.PARENT_ID = :V$GRADE_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
          GROUP BY 1, 2
        )
        WHERE CNT = 0
        ORDER BY 1
        INTO :V$SUBJECT_ID
      DO
      BEGIN
        S = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$SUBJECT_ID));
        IF(CHAR_LENGTH(S) + CHAR_LENGTH(VAL) < 3990) THEN
        BEGIN
          IF(CHAR_LENGTH(VAL) > 0) THEN VAL = VAL || '; ';
          VAL = VAL || S;
        END
      END
      IF(CHAR_LENGTH(VAL) > 0) THEN SUSPEND;

    END
    ELSE IF(SUBSTRING(S FROM 1 FOR 1) = 'a') THEN
    BEGIN
      S = SUBSTRING(S FROM 3);
      -- Начинаем новый раздел после групп
      IF(V$AGE = 0) THEN
      BEGIN
        TAG_NAME = 'ages::json&colon;array';
        VAL = 1;
        SUSPEND;
        V$AGE = 1;
      END
      TAG_NAME = 'ages:g';
      VAL = NULL;
      SUSPEND;
      P = POSITION(';' IN S);
      TAG_NAME = 'ages:g:age';
      VAL = SUBSTRING(S FROM 1 FOR P - 1);
      SUSPEND;
      S = SUBSTRING(S FROM P + 1);
      P = POSITION(';' IN S);
      TAG_NAME = 'ages:g:n_students';
      VAL = SUBSTRING(S FROM 1 FOR P - 1);
      SUSPEND;
      S = SUBSTRING(S FROM P + 1);
      TAG_NAME = 'ages:g:n_students_do';
      VAL = REPLACE(S, ';', '');
      SUSPEND;
    END
  END

  -- Разбивку по этапам обучения и подсчет итогов сделает сервер на своей стороне

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OU_EDU_STAT_OUTDATA (
    I$DATE DATE = current_date,
    I$FORCE SMALLINT = 0)
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
declare variable N integer;
declare variable V$SRCDATE date;
declare variable V$MDATE date;
declare variable V$SSN bigint;
declare variable V$OU_ID bigint;
declare variable V$YEAR_ID bigint;
declare variable V$YEAR integer;
declare variable V$LESSON_ID bigint;
declare variable V$TEACHER_ID bigint;
declare variable V$ALT_ID bigint;
declare variable V$RS smallint;
declare variable V$GROUP_ID bigint;
declare variable V$SUBJECT_ID bigint;
declare variable V$LV varchar(40);
declare variable V$LESSON_DATE date;
declare variable V$IS_COMPLETED smallint;
declare variable V$PERSON_ID bigint;
declare variable V$LINK_ID bigint;
declare variable V$TITLE varchar(1000);
declare variable V$HW varchar(1000);
declare variable V$D1 date;
declare variable V$D2 date;
declare variable V float;
begin

  -- Выгрузка всегда маркируется 00:00 понедельника
  V$SRCDATE = I$DATE;
  N = EXTRACT(DAY FROM I$DATE) - 1;
  V$MDATE = DATEADD(- N DAY TO I$DATE);
  N = EXTRACT(WEEKDAY FROM I$DATE);
  IF(N = 0) THEN N = 6; ELSE N = N - 1;
  I$DATE = DATEADD(- N DAY TO I$DATE);
  V$SSN = EXTRACT(DAY FROM I$DATE) * 10000 + EXTRACT(MONTH FROM I$DATE) * 100 +
    CAST(SUBSTRING(EXTRACT(YEAR FROM I$DATE) FROM 2) AS BIGINT);

  TAG_NAME = 'date';
  VAL = (SELECT VAL FROM DATE2ISO(:I$DATE, 0));
  SUSPEND;

  -- Если на понедельник нет статистики - пересчитываем
  IF(NOT EXISTS(
    SELECT FIRST 1 1
    FROM CJ2_STUDENT_RATING R
    WHERE R.DATE_DEL IS NULL AND R.RATE_DATE = :I$DATE
  ) OR I$FORCE <> 0)
  THEN
    EXECUTE PROCEDURE CJ2_UPDATE_RATING(:I$DATE);

  -- id организации
  TAG_NAME = 'SchoolID';
  SELECT FIRST 1 L2.OBJ_ID, V1236.LISTVAL_ID, LV.COST
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$OU_ID, :V$YEAR_ID, :V$YEAR;
  VAL = V$OU_ID;
  SUSPEND;

  TAG_NAME = 'DirectorFio';
  VAL = NULL;
  SELECT FIRST 1 R.F || ' ' || R.I || COALESCE(' ' || R.O, '')
  FROM R_SPB_POST_DIRECTOR(:V$OU_ID, 1) R
  INTO :VAL;
  SUSPEND;

  -- Количество классов
  TAG_NAME = 'GroupCount';
  VAL = NULL;
  SELECT FIRST 1 R.RATE_VALUE
  FROM CJ2_STUDENT_RATING R
  WHERE R.DATE_DEL IS NULL AND R.STUDENT_ID = :V$OU_ID AND R.RATE_DATE = :I$DATE AND R.SUBJECT_ID = 0
  INTO :VAL;
  SUSPEND;

  -- Своевременность выдачи ДЗ
  TAG_NAME = 'TimelyDz';
  VAL = NULL;
  SELECT FIRST 1 R.RATE_VALUE
  FROM CJ2_STUDENT_RATING R
  WHERE R.DATE_DEL IS NULL AND R.STUDENT_ID = :V$OU_ID AND R.RATE_DATE = :I$DATE AND R.SUBJECT_ID = 12
  INTO :VAL;
  SUSPEND;

  -- Средний балл
  TAG_NAME = 'AverageMark';
  VAL = NULL;
  SELECT FIRST 1 R.RATE_VALUE
  FROM CJ2_STUDENT_RATING R
  WHERE R.DATE_DEL IS NULL AND R.STUDENT_ID = :V$OU_ID AND R.RATE_DATE = :I$DATE AND R.SUBJECT_ID = 1
  INTO :VAL;
  SUSPEND;

  -- Качество знаний
  TAG_NAME = 'KnowledgeQuality';
  VAL = NULL;
  SELECT FIRST 1 R.RATE_VALUE
  FROM CJ2_STUDENT_RATING R
  WHERE R.DATE_DEL IS NULL AND R.STUDENT_ID = :V$OU_ID AND R.RATE_DATE = :I$DATE AND R.SUBJECT_ID = 2
  INTO :VAL;
  SUSPEND;

  -- Обученность
  TAG_NAME = 'TrainingGrade';
  VAL = NULL;
  SELECT FIRST 1 R.RATE_VALUE
  FROM CJ2_STUDENT_RATING R
  WHERE R.DATE_DEL IS NULL AND R.STUDENT_ID = :V$OU_ID AND R.RATE_DATE = :I$DATE AND R.SUBJECT_ID = 3
  INTO :VAL;
  SUSPEND;

  -- Системная неуспеваемость
  TAG_NAME = 'PoorGrades';
  VAL = NULL;
  SELECT FIRST 1 R.RATE_VALUE
  FROM CJ2_STUDENT_RATING R
  WHERE R.DATE_DEL IS NULL AND R.STUDENT_ID = :V$OU_ID AND R.RATE_DATE = :I$DATE AND R.SUBJECT_ID = 4
  INTO :VAL;
  SUSPEND;

  -- Академическая успеваемость
  TAG_NAME = 'AcademicPerformance';
  VAL = NULL;
  SELECT FIRST 1 R.RATE_VALUE
  FROM CJ2_STUDENT_RATING R
  WHERE R.DATE_DEL IS NULL AND R.STUDENT_ID = :V$OU_ID AND R.RATE_DATE = :I$DATE AND R.SUBJECT_ID = 5
  INTO :VAL;
  SUSPEND;

  -- Количество учеников 5 классов
  TAG_NAME = 'StudentsFifthParallel';
  VAL = NULL;
  SELECT FIRST 1 R.RATE_VALUE
  FROM CJ2_STUDENT_RATING R
  WHERE R.DATE_DEL IS NULL AND R.STUDENT_ID = :V$OU_ID AND R.RATE_DATE = :I$DATE AND R.SUBJECT_ID = 6
  INTO :VAL;
  SUSPEND;

  -- Адаптировавшиеся ученики 5 классов
  TAG_NAME = 'AdaptedStudents';
  VAL = NULL;
  SELECT FIRST 1 R.RATE_VALUE
  FROM CJ2_STUDENT_RATING R
  WHERE R.DATE_DEL IS NULL AND R.STUDENT_ID = :V$OU_ID AND R.RATE_DATE = :I$DATE AND R.SUBJECT_ID = 7
  INTO :VAL;
  SUSPEND;

  --
  TAG_NAME = 'StudentsForObjectivity';
  VAL = NULL;
  SELECT FIRST 1 R.RATE_VALUE
  FROM CJ2_STUDENT_RATING R
  WHERE R.DATE_DEL IS NULL AND R.STUDENT_ID = :V$OU_ID AND R.RATE_DATE = :I$DATE AND R.SUBJECT_ID = 8
  INTO :VAL;
  SUSPEND;

  --
  TAG_NAME = 'StudentsWithObjectiveMarks';
  VAL = NULL;
  SELECT FIRST 1 R.RATE_VALUE
  FROM CJ2_STUDENT_RATING R
  WHERE R.DATE_DEL IS NULL AND R.STUDENT_ID = :V$OU_ID AND R.RATE_DATE = :I$DATE AND R.SUBJECT_ID = 9
  INTO :VAL;
  SUSPEND;

  --
  TAG_NAME = 'Students2to12parallel';
  VAL = NULL;
  SELECT FIRST 1 R.RATE_VALUE
  FROM CJ2_STUDENT_RATING R
  WHERE R.DATE_DEL IS NULL AND R.STUDENT_ID = :V$OU_ID AND R.RATE_DATE = :I$DATE AND R.SUBJECT_ID = 10
  INTO :VAL;
  SUSPEND;

  --
  TAG_NAME = 'StudentsMarksAccumulation';
  VAL = NULL;
  SELECT FIRST 1 R.RATE_VALUE
  FROM CJ2_STUDENT_RATING R
  WHERE R.DATE_DEL IS NULL AND R.STUDENT_ID = :V$OU_ID AND R.RATE_DATE = :I$DATE AND R.SUBJECT_ID = 11
  INTO :VAL;
  SUSPEND;

  -- Уроки за неделю
  TAG_NAME = 'lessons::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L.OBJ_ID, J.TEACHER_ID, L.TEACHER_ID, J.GRADE_ID, J.SUBJECT_ID, LV.TAG, L.LESSON_DATE, L.IS_COMPLETED, L.LESSON_THEME, L.LESSON_HOMEWORK, L.REPL_QUALITY
    FROM CJ2_JOURNAL J
    JOIN CJ2_JOURNAL_LESSONS L ON L.DATE_DEL IS NULL AND L.CJ_ID = J.OBJ_ID AND L.LESSON_DATE >= DATEADD(-1 WEEK TO :I$DATE) AND L.LESSON_DATE < :I$DATE
    JOIN LISTVALS LV ON LV.LISTVAL_ID = J.STAGE_INDEX
    WHERE J.DATE_DEL IS NULL AND J.JOURNAL_TYPE = 0
    ORDER BY 1
    INTO :V$LESSON_ID, :V$TEACHER_ID, :V$ALT_ID, :V$GROUP_ID, :V$SUBJECT_ID, :V$LV, :V$LESSON_DATE, :V$IS_COMPLETED, :V$TITLE, :V$HW, :V$RS
  DO
  BEGIN
    -- Качество замены урока
    IF(V$RS IS NULL AND COALESCE(V$ALT_ID, 0) <> COALESCE(V$TEACHER_ID, 0)) THEN
    BEGIN
      -- Смотрим предметные области, где он является штатным учителем
      V$RS = 1;
      SELECT FIRST 1 2
      FROM CJ2_JOURNAL J
      JOIN LINKS L301 ON L301.PARENT_ID = J.SUBJECT_ID AND L301.OBJ_TYPE_ID = 301 AND L301.DATE_DEL IS NULL
      JOIN VALL V2462 ON V2462.OBJ_ID = L301.OBJ_ID AND V2462.PARAM_ID = 2462 AND V2462.IS_DEL = 0
      JOIN VALL V2462S ON V2462S.OBJ_ID = :V$SUBJECT_ID AND V2462S.PARAM_ID = 2462 AND V2462S.IS_DEL = 0 AND V2462S.LISTVAL_ID = V2462.LISTVAL_ID
      WHERE J.DATE_DEL IS NULL AND J.YEAR_ID = :V$YEAR_ID AND J.TEACHER_ID = :V$ALT_ID AND J.JOURNAL_TYPE = 0
      INTO :V$RS;

      -- На всякий случай проверяем по данному конкретному предмету
      IF(V$RS = 1) THEN
      SELECT FIRST 1 2
      FROM CJ2_JOURNAL J
      WHERE J.DATE_DEL IS NULL AND J.YEAR_ID = :V$YEAR_ID AND J.TEACHER_ID = :V$ALT_ID AND J.JOURNAL_TYPE = 0 AND J.SUBJECT_ID = :V$SUBJECT_ID
      INTO :V$RS;

      UPDATE CJ2_JOURNAL_LESSONS
      SET REPL_QUALITY = :V$RS
      WHERE OBJ_ID = :V$LESSON_ID;
    END

    TAG_NAME = 'lessons:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'lessons:r:SessionID';
    VAL = V$OU_ID + V$SSN;
    SUSPEND;
    TAG_NAME = 'lessons:r:LessonId';
    VAL = V$LESSON_ID;
    SUSPEND;
    TAG_NAME = 'lessons:r:PersonId';
    VAL = V$TEACHER_ID;
    SUSPEND;
    TAG_NAME = 'lessons:r:ReplacementPersonId';
    VAL = V$ALT_ID;
    SUSPEND;
    TAG_NAME = 'lessons:r:ReplacementStatus';
    VAL = IIF(COALESCE(V$ALT_ID, 0) = COALESCE(V$TEACHER_ID, 0), 0, :V$RS);
    SUSPEND;
    TAG_NAME = 'lessons:r:SchoolID';
    VAL = V$OU_ID;
    SUSPEND;
    TAG_NAME = 'lessons:r:StdGroupId';
    VAL = V$GROUP_ID;
    SUSPEND;
    TAG_NAME = 'lessons:r:GroupId';
    VAL = NULL;
    SELECT FIRST 1 M2.GROUP_ID
    FROM PERSON_MOVEMENTS M
    JOIN PERSON_MOVEMENTS M2 ON M2.DATE_DEL IS NULL AND M2.PERSON_ID = M.PERSON_ID AND M2.DATE_OUT IS NULL
    JOIN OBJECTS G ON G.OBJ_ID = M2.GROUP_ID AND G.TYPE_ID = 9
    WHERE M.DATE_DEL IS NULL AND M.GROUP_ID = :V$GROUP_ID
    ORDER BY M.DATE_OUT DESC NULLS FIRST
    INTO :VAL;
    SUSPEND;
    TAG_NAME = 'lessons:r:GroupName';
    VAL = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$GROUP_ID));
    SUSPEND;
    TAG_NAME = 'lessons:r:GroupParallel';
    VAL = V$LV;
    SUSPEND;
    TAG_NAME = 'lessons:r:SubjectId';
    VAL = V$SUBJECT_ID;
    SUSPEND;
    TAG_NAME = 'lessons:r:SubjectName';
    VAL = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$SUBJECT_ID));
    SUSPEND;
    TAG_NAME = 'lessons:r:LessonPlanDate';
    VAL = (SELECT VAL FROM DATE2ISO(:V$LESSON_DATE, 0));
    SUSPEND;
    TAG_NAME = 'lessons:r:LessonResultDate';
    VAL = (SELECT VAL FROM DATE2ISO(:V$LESSON_DATE, 0));
    SUSPEND;
    TAG_NAME = 'lessons:r:IsCanceled';
    VAL = '0';
    SUSPEND;
    TAG_NAME = 'lessons:r:lessonHeld';
    VAL = V$IS_COMPLETED;
    SUSPEND;
    TAG_NAME = 'lessons:r:Title';
    VAL = V$TITLE;
    SUSPEND;
    TAG_NAME = 'lessons:r:DzCount';
    V$HW = UPPER(TRIM(V$HW));
    IF(V$HW IS NULL OR V$HW = '' OR POSITION('НЕ ЗАДАН' IN V$HW) > 0 OR POSITION('НЕ ПРЕДУСМ' IN V$HW) > 0) THEN VAL = '0'; ELSE VAL = '1';
    SUSPEND;
    TAG_NAME = 'lessons:r:SpecialMarksCount';
    SELECT COUNT(*)
    FROM CJ2_CONTROL C
    JOIN CJ2_MARK M ON M.CONTROL_ID = C.CONTROL_ID AND M.DATE_DEL IS NULL
    WHERE C.LESSON_ID = :V$LESSON_ID AND C.DATE_DEL IS NULL AND C.CONTROL_TYPE_ID IN (1058, 11082)
    INTO :VAL;
    SUSPEND;
    TAG_NAME = 'lessons:r:SpecialMarksInDateCount';
    V$LV = (SELECT VAL FROM DATE2ISO(DATEADD(1 DAY TO :V$LESSON_DATE), 0));
    SELECT COUNT(*)
    FROM CJ2_CONTROL C
    JOIN CJ2_MARK M ON M.CONTROL_ID = C.CONTROL_ID AND M.DATE_DEL IS NULL
    WHERE C.LESSON_ID = :V$LESSON_ID AND C.DATE_DEL IS NULL AND C.CONTROL_TYPE_ID IN (1058, 11082) AND C.DATE_ADD < :V$LV || ' 13:00'
    INTO :VAL;
    SUSPEND;
    TAG_NAME = 'lessons:r:TotalMarksCount';
    SELECT COUNT(*)
    FROM CJ2_CONTROL C
    JOIN CJ2_MARK M ON M.CONTROL_ID = C.CONTROL_ID AND M.DATE_DEL IS NULL
    WHERE C.LESSON_ID = :V$LESSON_ID AND C.DATE_DEL IS NULL
    INTO :VAL;
    SUSPEND;
    TAG_NAME = 'lessons:r:MembersCount';
    SELECT COUNT(*)
    FROM PERSON_MOVEMENTS M
    WHERE M.DATE_DEL IS NULL AND M.GROUP_ID = :V$GROUP_ID AND M.DATE_IN <= :V$LESSON_DATE AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :V$LESSON_DATE)
    INTO :VAL;
    SUSPEND;
    TAG_NAME = 'lessons:r:AbsenceCount';
    SELECT COUNT(*)
    FROM CJ2_CONTROL C
    JOIN CJ2_MARK M ON M.CONTROL_ID = C.CONTROL_ID AND M.DATE_DEL IS NULL AND M.MARK_TYPE_ID IN (91, 92, 93, 94)
    WHERE C.LESSON_ID = :V$LESSON_ID AND C.DATE_DEL IS NULL AND C.CONTROL_TYPE_ID = 0
    INTO :VAL;
    SUSPEND;
    TAG_NAME = 'lessons:r:DisregardAbsenceCount';
    SELECT COUNT(*)
    FROM CJ2_CONTROL C
    JOIN CJ2_MARK M ON M.CONTROL_ID = C.CONTROL_ID AND M.DATE_DEL IS NULL AND M.MARK_TYPE_ID = 94
    WHERE C.LESSON_ID = :V$LESSON_ID AND C.DATE_DEL IS NULL AND C.CONTROL_TYPE_ID = 0
    INTO :VAL;
    SUSPEND;
  END

  -- Движение
  TAG_NAME = 'ms::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT M.OBJ_ID, M.PERSON_ID, NULL, 1, M.DATE_IN, M.DATE_OUT, LV.TAG
    FROM PERSON_MOVEMENTS M
    JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
    JOIN LISTVALS LV ON LV.LISTVAL_ID = M.STAGE_ID
    WHERE M.DATE_DEL IS NULL AND M.DATE_IN <= :I$DATE AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :I$DATE)
    UNION
    SELECT DISTINCT L20.LINK_ID, L20.OBJ_ID, L20.PARENT_ID, 2, '01.09.' || :V$YEAR, NULL, NULL
    FROM PERSON_MOVEMENTS M
    JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
    JOIN LISTVALS LV ON LV.LISTVAL_ID = M.STAGE_ID
    JOIN LINKS L20 ON L20.DATE_DEL IS NULL AND L20.PARENT_ID = M.PERSON_ID AND L20.OBJ_TYPE_ID = 20
    WHERE M.DATE_DEL IS NULL AND M.DATE_IN <= :I$DATE AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :I$DATE)
    UNION
    SELECT L15.OBJ_ID, L14.OBJ_ID, NULL, 0, V73.VAL, V74.VAL, NULL
    FROM LINKS L14
    JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
    JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0 AND V73.VAL <= :I$DATE
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
    WHERE L14.OBJ_TYPE_ID = 14 AND L14.PARENT_TYPE_ID = 2 AND L14.DATE_DEL IS NULL AND (V74.VAL IS NULL OR V74.VAL >= :I$DATE)
    INTO :V$LESSON_ID, :V$PERSON_ID, :V$LINK_ID, :V$RS, :V$D1, :V$D2, :V$LV
  DO
  BEGIN
    TAG_NAME = 'ms:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'ms:r:SessionId';
    VAL = V$OU_ID + V$SSN;
    SUSPEND;
    TAG_NAME = 'ms:r:MembershipId';
    VAL = V$LESSON_ID;
    SUSPEND;
    TAG_NAME = 'ms:r:LinkId';
    VAL = V$LINK_ID;
    SUSPEND;
    TAG_NAME = 'ms:r:SchoolID';
    VAL = V$OU_ID;
    SUSPEND;
    TAG_NAME = 'ms:r:PersonId';
    VAL = V$PERSON_ID;
    SUSPEND;
    TAG_NAME = 'ms:r:Membershiprole';
    VAL = V$RS;
    SUSPEND;
    TAG_NAME = 'ms:r:DateStart';
    VAL = (SELECT VAL FROM DATE2ISO(:V$D1, 0));
    SUSPEND;
    TAG_NAME = 'ms:r:DateFinish';
    VAL = (SELECT VAL FROM DATE2ISO(:V$D2, 0));
    SUSPEND;

    -- Для родителя нужно исправить параллель
    IF(V$LV IS NULL AND V$LINK_ID IS NOT NULL) THEN
    SELECT FIRST 1 LV.TAG
    FROM PERSON_MOVEMENTS M
    JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
    JOIN LISTVALS LV ON LV.LISTVAL_ID = M.STAGE_ID
    WHERE M.DATE_DEL IS NULL AND M.DATE_IN <= :I$DATE AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :I$DATE) AND M.PERSON_ID = :V$LINK_ID
    INTO :V$LV;
    TAG_NAME = 'ms:r:GroupParallel';
    VAL = V$LV;
    SUSPEND;
  END

  -- Персоны
  TAG_NAME = 'persons::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT DISTINCT M.PERSON_ID
    FROM PERSON_MOVEMENTS M
    JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
    WHERE M.DATE_DEL IS NULL AND M.DATE_IN <= :I$DATE AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :I$DATE)
    UNION
    SELECT DISTINCT L20.OBJ_ID
    FROM PERSON_MOVEMENTS M
    JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
    JOIN LISTVALS LV ON LV.LISTVAL_ID = M.STAGE_ID
    JOIN LINKS L20 ON L20.DATE_DEL IS NULL AND L20.PARENT_ID = M.PERSON_ID AND L20.OBJ_TYPE_ID = 20
    WHERE M.DATE_DEL IS NULL AND M.DATE_IN <= :I$DATE AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :I$DATE)
    UNION
    SELECT DISTINCT L14.OBJ_ID
    FROM LINKS L14
    JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
    JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0 AND V73.VAL <= :I$DATE
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
    WHERE L14.OBJ_TYPE_ID = 14 AND L14.PARENT_TYPE_ID = 2 AND L14.DATE_DEL IS NULL AND (V74.VAL IS NULL OR V74.VAL >= :I$DATE)
    INTO :V$PERSON_ID
  DO
  BEGIN
    TAG_NAME = 'persons:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'persons:r:SessionId';
    VAL = V$OU_ID + V$SSN;
    SUSPEND;
    TAG_NAME = 'persons:r:PersonId';
    VAL = V$PERSON_ID;
    SUSPEND;
    TAG_NAME = 'persons:r:BirthDate';
    VAL = NULL;
    SELECT FIRST 1 V.VAL
    FROM VALD V
    WHERE V.OBJ_ID = :V$PERSON_ID AND V.PARAM_ID IN (89, 241, 143) AND V.IS_DEL = 0
    INTO :VAL;
    SUSPEND;
    TAG_NAME = 'persons:r:Gender';
    VAL = NULL;
    SELECT FIRST 1 IIF(V.LISTVAL_ID = 183, 'М', 'Ж')
    FROM VALL V
    WHERE V.OBJ_ID = :V$PERSON_ID AND V.PARAM_ID IN (88, 239, 2544) AND V.IS_DEL = 0
    INTO :VAL;
    SUSPEND;
    -- Первая или высшая
    TAG_NAME = 'persons:r:Qualification';
    VAL = NULL;
    SELECT FIRST 1 IIF(V.LISTVAL_ID IN (634, 635), '1', '0')
    FROM VALL V
    WHERE V.OBJ_ID = :V$PERSON_ID AND V.PARAM_ID = 281 AND V.IS_DEL = 0
    INTO :VAL;
    SUSPEND;
  END

  -- Добавляем выборку полей
  TAG_NAME = 'values::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT F.ID, R.STUDENT_ID, R.SUBJECT_ID, R.RATE_DATE, R.RATE_VALUE
    FROM STAT_QUERIES Q
    JOIN STAT_FIELDS F ON F.DATE_DEL IS NULL AND F.QUERY_ID = Q.ID
    JOIN CJ2_STUDENT_RATING R ON R.DATE_DEL IS NULL AND R.FIELD_ID = F.ID
      AND ((Q.UPDATE_PERIOD = 0 AND R.RATE_DATE = :I$DATE) OR (Q.UPDATE_PERIOD = 1 AND R.RATE_DATE = :V$SRCDATE) OR (Q.UPDATE_PERIOD = 2 AND R.RATE_DATE = :V$MDATE))
    WHERE Q.DATE_DEL IS NULL
    INTO :V$LINK_ID, :V$GROUP_ID, :V$SUBJECT_ID, :V$LESSON_DATE, :V
  DO
  BEGIN
    TAG_NAME = 'values:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'values:r:field_id';
    VAL = V$LINK_ID;
    SUSPEND;
    TAG_NAME = 'values:r:ref_id';
    VAL = V$GROUP_ID;
    SUSPEND;
    TAG_NAME = 'values:r:detail_id';
    VAL = V$SUBJECT_ID;
    SUSPEND;
    TAG_NAME = 'values:r:date';
    VAL = V$LESSON_DATE;
    SUSPEND;
    TAG_NAME = 'values:r:val';
    VAL = V;
    SUSPEND;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OU_FULLNAME_GENITIVE (
    OU_NAME VARCHAR(2000))
RETURNS (
    RESULT VARCHAR(2000))
AS
declare variable TAIL varchar(2000);
declare variable HEAD varchar(2000);
declare variable P integer;
BEGIN

  P = POSITION(' учреждение ' IN OU_NAME);

  IF(P <= 0) THEN RESULT = OU_NAME;
  ELSE
  BEGIN
    HEAD = LEFT(OU_NAME, P);
    TAIL = SUBSTRING(OU_NAME FROM POSITION(' учреждение ' IN OU_NAME) + 11);

    SELECT REPLACE(:HEAD, 'ное ', 'ного ')
    FROM RDB$DATABASE
    INTO :HEAD;

    RESULT = HEAD || 'учреждения' || TAIL;
  END

  SUSPEND;

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OU_LICENCE_TYPE RETURNS (
    STATUS VARCHAR(1))
AS
begin
    STATUS = 'O';
    IF (EXISTS(
        SELECT 1
        FROM KEYS
        WHERE KEY_CODE = 'PROJECT_NAME'
        AND ((KEY_VAL LIKE 'Параграф%Мульти') OR (KEY_VAL LIKE 'Апостроф%Мульти'))
    )) THEN
    BEGIN
        STATUS = 'S';
    END
    ELSE IF (EXISTS(
        SELECT 1
        FROM KEYS
        WHERE KEY_CODE = 'PROJECT_NAME'
        AND ((KEY_VAL LIKE 'Параграф%ДОУ') OR (KEY_VAL LIKE 'Апостроф%ДОУ'))
    )) THEN
    BEGIN
        STATUS = 'D';
    END
    ELSE IF (EXISTS(
        SELECT 1
        FROM KEYS
        WHERE KEY_CODE = 'PROJECT_NAME'
        AND ((KEY_VAL LIKE 'Параграф%Колледж') OR (KEY_VAL LIKE 'Апостроф%Колледж'))
    )) THEN
    BEGIN
        STATUS = 'C';
    END
    ELSE IF (EXISTS(
        SELECT 1
        FROM KEYS
        WHERE KEY_CODE = 'PROJECT_NAME'
        AND ((KEY_VAL LIKE 'Параграф%УДОД') OR (KEY_VAL LIKE 'Апостроф%УДОД'))
    )) THEN
    BEGIN
        STATUS = 'U';
    END
    ELSE IF (EXISTS(
        SELECT 1
        FROM KEYS
        WHERE KEY_CODE = 'PROJECT_NAME'
        AND ((KEY_VAL LIKE 'Параграф%ДПО') OR (KEY_VAL LIKE 'Апостроф%ДПО'))
    )) THEN
    BEGIN
        STATUS = 'P';
    END
    --STATUS = 'U';
    SUSPEND;
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OU_LIST (
    I$USER_ID BIGINT,
    I$TYPE SMALLINT = 1)
RETURNS (
    SCHOOLNO VARCHAR(100),
    SHORTNAME VARCHAR(500),
    FULLNAME VARCHAR(1000),
    NEWTYPEID BIGINT,
    PROPERTYFORMID INTEGER,
    DISTRICTID INTEGER,
    EMAIL VARCHAR(100),
    ADDRESS VARCHAR(500),
    CHIEF VARCHAR(100),
    WWW VARCHAR(100),
    PHONE VARCHAR(100),
    FAX VARCHAR(100),
    CHIEFPHONE VARCHAR(100),
    OGRN VARCHAR(100),
    OU_TYPE SMALLINT,
    LEGALNAME VARCHAR(500))
AS
declare variable F varchar(30);
declare variable I varchar(30);
declare variable O varchar(30);
declare variable S_INDEX varchar(6);
declare variable S_REGION varchar(51);
declare variable S_CITY varchar(51);
declare variable S_PLACE varchar(51);
declare variable S_STREET varchar(51);
declare variable S_HOUSE varchar(10);
declare variable S_BUILDING varchar(10);
declare variable DISTR_ID bigint;
declare variable SCHOOL_ID bigint;
declare variable DIRECTOR_ID bigint;
declare variable C double precision;
BEGIN
    OU_TYPE = I$TYPE;

    -- for Paragraf 2

    /*  FOR SELECT D.S_NOMER, D.SHORTNAME, D.S_NAIMENOVANIE, D.S_VID, 6, 19929, D.S_ELEKTRONNAJA_POCHTA, D.S_INDEX, D.S_REGION, D.S_CITY, D.S_PLACE, D.S_STREET, D.S_HOUSE,
               D.S_BUILDING, P.FIRSTNAME, P.NAME, P.LASTNAME, D.S_WWWADRES, D.S_TELEPHON_PRIEMNOJ, D.S_PHAKS, D.S_TELEPHON_DIREKTORA, S4.S_ZNACHENIE
        FROM SCHOOLDICT D
        LEFT JOIN PERSDICT P ON D.S_DIREKTOR = P.PERSONCODE
        LEFT JOIN SCHOOLDICT_S4 S4 ON S4.CODE = D.CODE AND S4.S_NAZVANIE = 'ОГРН'
        INTO :SCHOOLNO, :SHORTNAME, :FULLNAME, :NEWTYPEID, :PROPERTYFORMID, :DISTRICTID, :EMAIL, :S_INDEX, :S_REGION, :S_CITY, :S_PLACE, :S_STREET, :S_HOUSE, :S_BUILDING,
             :F, :I, :O, :WWW, :PHONE, :FAX, :CHIEFPHONE, :OGRN
    DO
    BEGIN

        CHIEF = F;
        IF (I > '') THEN CHIEF = CHIEF || ' ' || SUBSTR(I, 1, 1) || '.';
        IF (O > '') THEN CHIEF = CHIEF || ' ' || SUBSTR(O, 1, 1) || '.';

        ADDRESS = S_INDEX || ', ' || S_REGION;

        IF (S_CITY > '') THEN ADDRESS = ADDRESS || ', ' || S_CITY;
        IF (S_PLACE > '') THEN ADDRESS = ADDRESS || ', ' || S_PLACE;
        IF (S_STREET > '') THEN ADDRESS = ADDRESS || ', ' || S_STREET;
        IF (S_HOUSE > '') THEN ADDRESS = ADDRESS || ', д.' || S_HOUSE;
        IF (S_BUILDING > '') THEN ADDRESS = ADDRESS || ' ' || S_BUILDING;

        SUSPEND;
    END   */

    -- for Paragraf 3

    FOR
        SELECT L111.OBJ_ID, LV.LISTVAL_ID, LV.COST
        FROM LINKS L111
        JOIN VALL V665 ON V665.OBJ_ID = L111.OBJ_ID AND V665.PARAM_ID = 665 AND V665.IS_DEL = 0
        JOIN LISTVALS LV ON LV.LISTVAL_ID = V665.LISTVAL_ID
        WHERE L111.PARENT_TYPE_ID = 112 AND L111.OBJ_TYPE_ID = 111 AND L111.DATE_DEL IS NULL
        UNION
        SELECT L112.OBJ_ID, NULL, 0
        FROM LINKS L112
        WHERE L112.PARENT_ID IS NULL AND L112.OBJ_TYPE_ID = 112 AND L112.DATE_DEL IS NULL AND :I$TYPE = 2
        ORDER BY 3
        INTO :DISTR_ID, :DISTRICTID, :C
    DO
    BEGIN
        FOR
            SELECT L2.OBJ_ID
            FROM LINKS L2
            WHERE L2.PARENT_ID = :DISTR_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
            INTO :SCHOOL_ID
        DO
        BEGIN
            SELECT V FROM VAL_GET(:SCHOOL_ID, 17, 0, :I$USER_ID) INTO :SCHOOLNO;
            SELECT V FROM VAL_GET(:SCHOOL_ID,  2, 0, :I$USER_ID) INTO :SHORTNAME;
            SELECT V FROM VAL_GET(:SCHOOL_ID,  5, 0, :I$USER_ID) INTO :FULLNAME;
            SELECT V FROM VAL_GET(:SCHOOL_ID, 35, 0, :I$USER_ID) INTO :EMAIL;
            SELECT V FROM VAL_GET(:SCHOOL_ID, 36, 0, :I$USER_ID) INTO :WWW;
            SELECT V FROM VAL_GET(:SCHOOL_ID, 29, 0, :I$USER_ID) INTO :PHONE;
            SELECT V FROM VAL_GET(:SCHOOL_ID, 30, 0, :I$USER_ID) INTO :FAX;
            SELECT V FROM VAL_GET(:SCHOOL_ID, 28, 0, :I$USER_ID) INTO :CHIEFPHONE;
            SELECT V FROM VAL_GET(:SCHOOL_ID,  9, 0, :I$USER_ID) INTO :OGRN;

            SELECT I FROM VAL_GET(:SCHOOL_ID, 10, 0, :I$USER_ID) INTO :NEWTYPEID;
            SELECT I FROM VAL_GET(:SCHOOL_ID,  8, 0, :I$USER_ID) INTO :PROPERTYFORMID;

            DIRECTOR_ID = NULL;
            SELECT OBJ_ID FROM R_SPB_POST_DIRECTOR(:SCHOOL_ID,:I$USER_ID) INTO :DIRECTOR_ID;
            SELECT CAPTION FROM THE_CAPTION_TEACHER(:DIRECTOR_ID) INTO :CHIEF;

            SELECT VAL FROM ADR_GET(27, :SCHOOL_ID) INTO :ADDRESS;

            SELECT V FROM VAL_GET(:SCHOOL_ID,  999, 0, :I$USER_ID) INTO :LEGALNAME;

            SUSPEND;
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OU_LIST_BY_ROOT (
    I$OBJ_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    OWNER_ID BIGINT,
    OWNER_CAPTION VARCHAR(4000))
AS
DECLARE VARIABLE V$TYPE_ID BIGINT;
BEGIN
    SELECT TYPE_ID
    FROM OBJECTS
    WHERE OBJ_ID = :I$OBJ_ID
    INTO :V$TYPE_ID;

    IF (:V$TYPE_ID = 2) THEN
    BEGIN
        OBJ_ID = :I$OBJ_ID;

        SELECT IIF(V665.LISTVAL_ID = 3387, 0, NULL)
        FROM LINKS L2
        JOIN VALL V665 ON V665.OBJ_ID = L2.PARENT_ID
          AND V665.PARAM_ID = 665
          AND V665.IS_DEL = 0
        WHERE L2.DATE_DEL IS NULL
          AND L2.PARENT_TYPE_ID+0 = 111
          AND L2.OBJ_ID = :I$OBJ_ID
        INTO :OWNER_ID;

        SELECT COALESCE(:OWNER_ID, L168.LISTVAL_ID), V7.VAL
        FROM VALS V7
        JOIN LISTVALS L168 ON L168.LIST_ID = 168
          AND L168.IS_DEL = 0
        JOIN RES R ON R.RES_ID = L168.RES_ID
          AND R.LANG_CODE = 'RU'
          AND V7.VAL = R.VAL
        WHERE V7.IS_DEL = 0
          AND V7.PARAM_ID = 7
          AND V7.OBJ_ID = :OBJ_ID
        INTO :OWNER_ID, :OWNER_CAPTION;

        SUSPEND;
    END
    ELSE
    IF (:V$TYPE_ID = 111) THEN
    BEGIN
        FOR SELECT L2.OBJ_ID, IIF(V665.LISTVAL_ID = 3387, 0, NULL), NULL
            FROM LINKS L2
            JOIN VALL V665 ON V665.OBJ_ID = L2.PARENT_ID
              AND V665.PARAM_ID = 665
              AND V665.IS_DEL = 0
            WHERE L2.DATE_DEL IS NULL
              AND L2.OBJ_TYPE_ID+0 = 2
              AND L2.PARENT_ID = :I$OBJ_ID
            INTO :OBJ_ID, :OWNER_ID, :OWNER_CAPTION
        DO
        BEGIN
            SELECT COALESCE(:OWNER_ID, L168.LISTVAL_ID), V7.VAL
            FROM VALS V7
            JOIN LISTVALS L168 ON L168.LIST_ID = 168
              AND L168.IS_DEL = 0
            JOIN RES R ON R.RES_ID = L168.RES_ID
              AND R.LANG_CODE = 'RU'
              AND V7.VAL = R.VAL
            WHERE V7.IS_DEL = 0
              AND V7.PARAM_ID = 7
              AND V7.OBJ_ID = :OBJ_ID
            INTO :OWNER_ID, :OWNER_CAPTION;

            SUSPEND;
        END
    END
    IF (:V$TYPE_ID = 112) THEN
    BEGIN
        FOR SELECT L2.OBJ_ID, IIF(V665.LISTVAL_ID = 3387, 0, NULL), NULL
            FROM LINKS L111
            JOIN VALL V665 ON V665.OBJ_ID = L111.OBJ_ID
              AND V665.PARAM_ID = 665
              AND V665.IS_DEL = 0
            JOIN LINKS L2 ON L2.PARENT_ID = L111.OBJ_ID
              AND L2.DATE_DEL IS NULL
              AND L2.OBJ_TYPE_ID+0 = 2
            WHERE L111.DATE_DEL IS NULL
              AND L111.OBJ_TYPE_ID+0 = 111
              AND L111.PARENT_ID = :I$OBJ_ID
            INTO :OBJ_ID, :OWNER_ID, :OWNER_CAPTION
        DO
        BEGIN
            SELECT COALESCE(:OWNER_ID, L168.LISTVAL_ID), V7.VAL
            FROM VALS V7
            JOIN LISTVALS L168 ON L168.LIST_ID = 168
              AND L168.IS_DEL = 0
            JOIN RES R ON R.RES_ID = L168.RES_ID
              AND R.LANG_CODE = 'RU'
              AND V7.VAL = R.VAL
            WHERE V7.IS_DEL = 0
              AND V7.PARAM_ID = 7
              AND V7.OBJ_ID = :OBJ_ID
            INTO :OWNER_ID, :OWNER_CAPTION;

            SUSPEND;
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE OU_NET_REPORT (
    I$USER_ID BIGINT = 1)
RETURNS (
    F1 VARCHAR(500),
    F2 INTEGER,
    F3 INTEGER,
    F3_NUM VARCHAR(500),
    F4 INTEGER,
    F4_NUM VARCHAR(500),
    F5 INTEGER,
    F5_NUM VARCHAR(500),
    F6 INTEGER,
    F6_NUM VARCHAR(500),
    F7 INTEGER,
    F7_NUM VARCHAR(500),
    F8 INTEGER,
    F8_NUM VARCHAR(500),
    F9 INTEGER,
    F9_NUM VARCHAR(500),
    F10 INTEGER,
    F10_NUM VARCHAR(500),
    F11 INTEGER,
    F11_NUM VARCHAR(500),
    F12 INTEGER,
    F12_NUM VARCHAR(500),
    F13 INTEGER,
    F13_NUM VARCHAR(500),
    F14 INTEGER,
    F14_NUM VARCHAR(500),
    F15 INTEGER,
    F15_NUM VARCHAR(500),
    F16 INTEGER,
    F16_NUM VARCHAR(500),
    F17 INTEGER,
    F17_NUM VARCHAR(500),
    F18 INTEGER,
    F18_NUM VARCHAR(500),
    F19 INTEGER,
    F19_NUM VARCHAR(500),
    F20 INTEGER,
    F20_NUM VARCHAR(500),
    F21 INTEGER,
    F21_NUM VARCHAR(500),
    F22 INTEGER,
    F22_NUM VARCHAR(500),
    F23 INTEGER,
    F23_NUM VARCHAR(500),
    F24 INTEGER,
    F24_NUM VARCHAR(500),
    F25 INTEGER)
AS
declare variable LANG_CODE varchar(2);
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :LANG_CODE;

    FOR
        SELECT
            DISTINCT (SELECT V FROM VAL_GET(DISTRICT_ID, 665)) F1,
            SUM(F3+F4+F5+F6+F7+F8+F9+F10+F19) + SUM(F16+F20+F21+F22) F2,
            IIF(SUM(F3) = 0, NULL, SUM(F3)) F3, LIST(IIF(F3 = 1, SCHOOL_NUM, NULL), ', ') F3_NUM,
            IIF(SUM(F4) = 0, NULL, SUM(F4)) F4, LIST(IIF(F4 = 1, SCHOOL_NUM, NULL), ', ') F4_NUM,
            IIF(SUM(F5) = 0, NULL, SUM(F5)) F5, LIST(IIF(F5 = 1, SCHOOL_NUM, NULL), ', ') F5_NUM,
            IIF(SUM(F6) = 0, NULL, SUM(F6)) F6, LIST(IIF(F6 = 1, SCHOOL_NUM, NULL), ', ') F6_NUM,
            IIF(SUM(F7) = 0, NULL, SUM(F7)) F7, LIST(IIF(F7 = 1, SCHOOL_NUM, NULL), ', ') F7_NUM,
            IIF(SUM(F8) = 0, NULL, SUM(F8)) F8, LIST(IIF(F8 = 1, SCHOOL_NUM, NULL), ', ') F8_NUM,
            IIF(SUM(F9) = 0, NULL, SUM(F9)) F9, LIST(IIF(F9 = 1, SCHOOL_NUM, NULL), ', ') F9_NUM,
            IIF(SUM(F10) = 0, NULL, SUM(F10)) F10, LIST(IIF(F10 = 1, SCHOOL_NUM, NULL), ', ') F10_NUM,
            IIF(SUM(F11) = 0, NULL, SUM(F11)) F11, LIST(IIF(F11 = 1, SCHOOL_NUM, NULL), ', ') F11_NUM,
            IIF(SUM(F12) = 0, NULL, SUM(F12)) F12, LIST(IIF(F12 = 1, SCHOOL_NUM, NULL), ', ') F12_NUM,
            IIF(SUM(F13) = 0, NULL, SUM(F13)) F13, LIST(IIF(F13 = 1, SCHOOL_NUM, NULL), ', ') F13_NUM,
            IIF(SUM(F14) = 0, NULL, SUM(F14)) F14, LIST(IIF(F14 = 1, SCHOOL_NUM, NULL), ', ') F14_NUM,
            IIF(SUM(F15) = 0, NULL, SUM(F15)) F15, LIST(IIF(F15 = 1, SCHOOL_NUM, NULL), ', ') F15_NUM,
            IIF(SUM(F16) = 0, NULL, SUM(F16)) F16, LIST(IIF(F16 = 1, SCHOOL_NUM, NULL), ', ') F16_NUM,
            IIF(SUM(F17) = 0, NULL, SUM(F17)) F17, LIST(IIF(F17 = 1, SCHOOL_NUM, NULL), ', ') F17_NUM,
            IIF(SUM(F18) = 0, NULL, SUM(F18)) F18, LIST(IIF(F18 = 1, SCHOOL_NUM, NULL), ', ') F18_NUM,
            IIF(SUM(F19) = 0, NULL, SUM(F19)) F19, LIST(IIF(F19 = 1, SCHOOL_NUM, NULL), ', ') F19_NUM,
            IIF(SUM(F20) = 0, NULL, SUM(F20)) F20, LIST(IIF(F20 = 1, SCHOOL_NUM, NULL), ', ') F20_NUM,
            IIF(SUM(F21) = 0, NULL, SUM(F21)) F21, LIST(IIF(F21 = 1, SCHOOL_NUM, NULL), ', ') F21_NUM,
            IIF(SUM(F22) = 0, NULL, SUM(F22)) F22, LIST(IIF(F22 = 1, SCHOOL_NUM, NULL), ', ') F22_NUM,
            IIF(SUM(F23) = 0, NULL, SUM(F23)) F23, LIST(IIF(F23 = 1, SCHOOL_NUM, NULL), ', ') F23_NUM,
            IIF(SUM(F24) = 0, NULL, SUM(F24)) F24, LIST(IIF(F24 = 1, SCHOOL_NUM, NULL), ', ') F24_NUM,
            SUM(F3+F4+F5+F6+F7+F8+F9+F10+F19) + SUM(F16+F20+F22) + SUM(F21+F23+F24) F25
        FROM (
            SELECT
                DISTRICT_ID, SCHOOL_NUM,
                IIF(SCHOOL_OPF IN ('7','10') AND IS_SUB = 1 AND SCHOOL_TYPE = '01' AND IS_PUB = 0, 1, 0) F3,
                IIF(SCHOOL_OPF IN ('7','10') AND IS_SUB = 1 AND (SCHOOL_VID = '0201' OR (SCHOOL_VID = '0105' AND IS_PUB = 1)), 1, 0) F4,
                IIF(SCHOOL_OPF IN ('7','10') AND IS_SUB = 1 AND SCHOOL_VID IN ('0106', '0202', '0502'), 1, 0) F5,
                IIF(SCHOOL_OPF IN ('7','10') AND IS_SUB = 1 AND SCHOOL_VID IN ('0101', '0203', '0503'), 1, 0) F6,
                IIF(SCHOOL_OPF IN ('7','10') AND IS_SUB = 1 AND SCHOOL_VID IN ('0102', '0204'), 1, 0) F7,
                IIF(SCHOOL_OPF IN ('7','10') AND IS_SUB = 1 AND SCHOOL_VID IN ('0103', '0205'), 1, 0) F8,
                IIF(SCHOOL_OPF IN ('7','10') AND IS_SUB = 1 AND SCHOOL_VID IN ('0104', '0206') AND IS_SUB = 1, 1, 0) F9,
                IIF(SCHOOL_OPF IN ('7','10') AND IS_SUB = 1 AND SCHOOL_TYPE = '03' AND IS_KADET = 1, 1, 0) F10,
                IIF(SCHOOL_OPF IN ('7','10') AND IS_SUB = 1 AND SCHOOL_VID = '0202', 1, 0) F11,
                IIF(SCHOOL_OPF IN ('7','10') AND IS_SUB = 1 AND SCHOOL_VID = '0203', 1, 0) F12,
                IIF(SCHOOL_OPF IN ('7','10') AND IS_SUB = 1 AND SCHOOL_VID = '0204', 1, 0) F13,
                IIF(SCHOOL_OPF IN ('7','10') AND IS_SUB = 1 AND SCHOOL_VID = '0205', 1, 0) F14,
                IIF(SCHOOL_OPF IN ('7','10') AND IS_SUB = 1 AND SCHOOL_VID IN ('0502', '0503'), 1, 0) F15,
                IIF(SCHOOL_OPF IN ('7','10') AND IS_SUB = 1 AND (SCHOOL_TYPE = '06' OR SCHOOL_VID IN ('0504', '0505')), 1, 0) F16,
                IIF(SCHOOL_OPF IN ('7','10') AND IS_SUB = 1 AND SCHOOL_VID IN ('0603', '0505'), 1, 0) F17,
                IIF(SCHOOL_OPF IN ('7','10') AND IS_SUB = 1 AND SCHOOL_VID IN ('0504', '0505'), 1, 0) F18,
                IIF(SCHOOL_OPF IN ('7','10') AND IS_SUB = 1 AND SCHOOL_TYPE = '07', 1, 0) F19,
                IIF(SCHOOL_OPF IN ('7','10') AND IS_SUB = 1 AND SCHOOL_TYPE = '09', 1, 0) F20,
                IIF(V_TYPE = 2221, 1, 0) F21,
                IIF(SCHOOL_OPF IN ('7','10') AND IS_SUB = 1 AND SCHOOL_TYPE = '10', 1, 0) F22,
                IIF(SCHOOL_OPF = '4', 1, 0) F23,
                IIF(SCHOOL_OPF <> '4' AND (SCHOOL_OPF NOT IN ('7','10') OR IS_SUB = 0 OR (SCHOOL_TYPE = '03' AND IS_KADET = 0)) AND V_TYPE <> 2221, 1, 0) F24
            FROM (
                SELECT
                    L2.OBJ_ID SCHOOL_ID,
                    L111.OBJ_ID DISTRICT_ID,
                    IIF(LOWER(R_VID.VAL) LIKE 'кадетская школа%', 1, 0) IS_KADET,
                    L_VID.TAG SCHOOL_VID, L_OPF.TAG SCHOOL_OPF,
                    SUBSTRING(L_VID.TAG FROM 1 FOR 2) SCHOOL_TYPE,
                    IIF(LOWER(V_SUB.VAL) LIKE 'комитет по %образованию%'
                           OR LOWER(V_SUB.VAL) LIKE 'администрация%района%', 1, 0) IS_SUB,
                    IIF(LOWER(R_TYPE.VAL) LIKE 'общеобразовательные%', 1, 0) IS_PUB,
                    COALESCE(V_NUM.VAL, (SELECT V FROM VAL_GET(L2.OBJ_ID, 2))) SCHOOL_NUM,
                    V_TYPE.LISTVAL_ID V_TYPE
                FROM LINKS L111
                JOIN LINKS L2 ON L2.PARENT_ID = L111.OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
                JOIN VALL V_VID ON V_VID.PARAM_ID = 10 AND V_VID.IS_DEL = 0 AND V_VID.OBJ_ID = L2.OBJ_ID
                JOIN LISTVALS L_VID ON L_VID.LISTVAL_ID = V_VID.LISTVAL_ID AND L_VID.LIST_ID = 6 AND L_VID.IS_DEL = 0
                JOIN VALL V_OPF ON V_OPF.OBJ_ID = L2.OBJ_ID AND V_OPF.PARAM_ID = 8 AND V_OPF.IS_DEL = 0
                JOIN LISTVALS L_OPF ON L_OPF.LISTVAL_ID = V_OPF.LISTVAL_ID AND L_OPF.LIST_ID IN (4, 258) AND L_OPF.IS_DEL = 0
                JOIN VALL V_TYPE ON V_TYPE.OBJ_ID = L2.OBJ_ID AND V_TYPE.PARAM_ID = 11 AND V_TYPE.IS_DEL = 0
                JOIN LISTVALS L_TYPE ON L_TYPE.LISTVAL_ID = V_TYPE.LISTVAL_ID AND L_TYPE.LIST_ID = 6 AND L_TYPE.IS_DEL = 0
                LEFT JOIN VALS V_SUB ON V_SUB.OBJ_ID = L2.OBJ_ID AND V_SUB.PARAM_ID = 6 AND V_SUB.IS_DEL = 0
                LEFT JOIN VALI V_NUM ON V_NUM.OBJ_ID = L2.OBJ_ID AND V_NUM.PARAM_ID = 17 AND V_NUM.IS_DEL = 0
                LEFT JOIN RES_GET(L_VID.RES_ID, :LANG_CODE) R_VID ON 1 = 1
                LEFT JOIN RES_GET(L_TYPE.RES_ID, :LANG_CODE) R_TYPE ON 1 = 1
                WHERE L111.OBJ_TYPE_ID = 111 AND L111.DATE_DEL IS NULL
            )
        )
        GROUP BY DISTRICT_ID
        INTO :F1, :F2, :F3, :F3_NUM, :F4, :F4_NUM, :F5, :F5_NUM, :F6, :F6_NUM, :F7, :F7_NUM,
             :F8, :F8_NUM, :F9, :F9_NUM, :F10, :F10_NUM, :F11, :F11_NUM, :F12, F12_NUM,
             :F13, :F13_NUM, :F14, :F14_NUM, :F15, :F15_NUM, :F16, :F16_NUM,
             :F17, :F17_NUM, :F18, :F18_NUM, :F19, :F19_NUM, :F20, :F20_NUM,
             :F21, :F21_NUM, :F22, :F22_NUM, :F23, :F23_NUM, :F24, :F24_NUM, :F25
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_CAN_CHANGE_VAL (
    I$OBJ_ID BIGINT,
    I$PARAM_ID BIGINT,
    I$VAL VARCHAR(4000),
    I$IS_DEL SMALLINT,
    I$USER_ID BIGINT = 1)
RETURNS (
    CAN_CHANGE SMALLINT,
    ERR_MSG VARCHAR(4000))
AS
declare variable V$TAG varchar(100);
declare variable V$Y smallint;
declare variable V$DT date;
declare variable V$STADY_DATE_START date;
declare variable V$STADY_DATE_END date;
declare variable V$PUPIL_ID bigint;
declare variable V$PREV_MOVEMENT_DATE date;
declare variable V$TYPE_ID bigint;
declare variable V$YEAR_VAL varchar(100);
declare variable V$YEAR_ID bigint;
declare variable V$LANG_CODE varchar(2);
BEGIN
    CAN_CHANGE = 1;
    ERR_MSG = '';

    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :V$LANG_CODE;

    FOR
        SELECT TYPE_ID
        FROM OBJECTS
        WHERE OBJ_ID = :I$OBJ_ID
        INTO :V$TYPE_ID
    DO
    BEGIN
        IF ((V$TYPE_ID = 243) AND (I$PARAM_ID = 2114)) THEN
        BEGIN
            IF (EXISTS(
                SELECT FIRST 1 1
                FROM LINKS LP242
                JOIN LINKS L243 ON L243.PARENT_ID = LP242.PARENT_ID AND L243.OBJ_TYPE_ID = 243 AND L243.OBJ_ID <> :I$OBJ_ID AND L243.DATE_DEL IS NULL
                JOIN VALL V2114 ON V2114.OBJ_ID = L243.OBJ_ID AND V2114.PARAM_ID = 2114 AND V2114.IS_DEL = 0 AND V2114.LISTVAL_ID = :I$VAL
                WHERE LP242.OBJ_ID = :I$OBJ_ID AND LP242.PARENT_TYPE_ID = 242 AND LP242.DATE_DEL IS NULL
            )) THEN
            BEGIN
                CAN_CHANGE = 0;
                ERR_MSG = 'Уже существует этап обучения с названием "' || (SELECT R.VAL FROM LISTVALS LV LEFT JOIN RES_GET(LV.RES_ID, 'RU') R ON 1=1 WHERE LV.LISTVAL_ID = :I$VAL) || '"!';
            END     
        END
        ELSE IF ((V$TYPE_ID = 51) AND (I$PARAM_ID = 376)) THEN
        BEGIN
            IF (EXISTS(
                SELECT FIRST 1 1
                FROM LINKS LP301
                JOIN LINKS L51 ON L51.PARENT_ID = LP301.PARENT_ID AND L51.OBJ_TYPE_ID = 51 AND L51.OBJ_ID <> :I$OBJ_ID AND L51.DATE_DEL IS NULL
                JOIN VALS V376 ON V376.OBJ_ID = L51.OBJ_ID AND V376.PARAM_ID = 376 AND V376.IS_DEL = 0 AND V376.VAL = :I$VAL
                WHERE LP301.OBJ_ID = :I$OBJ_ID AND LP301.PARENT_TYPE_ID = 301 AND LP301.DATE_DEL IS NULL
            )) THEN
            BEGIN
                CAN_CHANGE = 0;
                ERR_MSG = 'Уже существует предмет с названием "' || I$VAL || '"!';
            END     
        END
        ELSE IF ((V$TYPE_ID = 49) AND (I$PARAM_ID = 372)) THEN
        BEGIN
            IF ((I$VAL = '780') AND EXISTS(
                SELECT FIRST 1 1
                FROM LINKS LP50

                JOIN VALL V2545
                ON V2545.OBJ_ID = LP50.PARENT_ID
                AND V2545.PARAM_ID = 2545
                AND V2545.IS_DEL = 0
                AND V2545.LISTVAL_ID = 2

                WHERE LP50.OBJ_ID = :I$OBJ_ID
                AND LP50.PARENT_TYPE_ID = 50
                AND LP50.DATE_DEL IS NULL
            )) THEN
            BEGIN
                CAN_CHANGE = 0;
                ERR_MSG = 'План внеурочной деятельности не может содержать федеральный компонент!';
            END
            ELSE IF (EXISTS(
                SELECT FIRST 1 1
                FROM LINKS LP50
                
                JOIN LINKS L49
                ON L49.PARENT_ID = LP50.PARENT_ID
                AND L49.OBJ_TYPE_ID = 49
                AND L49.OBJ_ID <> :I$OBJ_ID
                AND L49.DATE_DEL IS NULL

                JOIN VALL V372
                ON V372.OBJ_ID = L49.OBJ_ID
                AND V372.PARAM_ID = 372
                AND V372.IS_DEL = 0
                AND V372.LISTVAL_ID = :I$VAL

                WHERE LP50.OBJ_ID = :I$OBJ_ID
                AND LP50.PARENT_TYPE_ID = 50
                AND LP50.DATE_DEL IS NULL
            )) THEN
            BEGIN
                CAN_CHANGE = 0;
                ERR_MSG = 'Учебный план уже содержит ' || (SELECT R.VAL FROM LISTVALS LV LEFT JOIN RES_GET(LV.RES_ID, 'RU') R ON 1=1 WHERE LV.LISTVAL_ID = :I$VAL) || '!';
            END
        END
        ELSE IF ((V$TYPE_ID = 79) AND (I$PARAM_ID = 2457)) THEN
        BEGIN
            IF (I$IS_DEL = 1) THEN
            BEGIN
                CAN_CHANGE = 0;
                ERR_MSG = 'Это поле обязательно должно быть заполнено!';
            END
            ELSE
            BEGIN
                IF ((I$VAL = 3) AND NOT EXISTS(
                    SELECT FIRST 1 1
                    FROM LINKS LP10

                    JOIN LINKS L79
                    ON L79.PARENT_ID = LP10.PARENT_ID
                    AND L79.OBJ_TYPE_ID = 79
                    AND L79.DATE_DEL IS NULL
                    AND L79.OBJ_ID <> :I$OBJ_ID

                    JOIN VALL V2457
                    ON V2457.OBJ_ID = L79.OBJ_ID
                    AND V2457.PARAM_ID = 2457
                    AND V2457.IS_DEL = 0
                    AND V2457.LISTVAL_ID = 2
        
                    WHERE LP10.OBJ_ID = :I$OBJ_ID
                    AND LP10.PARENT_TYPE_ID = 10
                    AND LP10.DATE_DEL IS NULL
                )) THEN
                BEGIN
                    CAN_CHANGE = 0;
                    ERR_MSG = 'Один из документов должен иметь признак выгрузки "Да". Если вы хотите сменить документ для выгрузки, выберите в нужном документе признак "Да".';
                END
            END
        END
        IF ((V$TYPE_ID = 69) AND (I$PARAM_ID = 2450) AND (I$VAL <> '')) THEN
        BEGIN
            IF (EXISTS(
                SELECT FIRST 1 1
                FROM LINKS LP2
    
                JOIN LINKS L69
                ON L69.PARENT_ID = LP2.PARENT_ID
                AND L69.OBJ_TYPE_ID = 69
                AND L69.OBJ_ID <> :I$OBJ_ID
                AND L69.DATE_DEL IS NULL
    
                JOIN VALL V2450
                ON V2450.OBJ_ID = L69.OBJ_ID
                AND V2450.PARAM_ID = 2450
                AND V2450.IS_DEL = 0
                AND V2450.LISTVAL_ID = :I$VAL
    
                WHERE LP2.OBJ_ID = :I$OBJ_ID
                AND LP2.PARENT_TYPE_ID = 2
                AND LP2.DATE_DEL IS NULL
            )) THEN
            BEGIN
                CAN_CHANGE = 0;
                ERR_MSG = 'В ОООД уже создан раздел "' || (SELECT VAL FROM RES_GET((SELECT RES_ID FROM LISTVALS WHERE LISTVAL_ID = :I$VAL), :V$LANG_CODE)) || '"';
            END
        END
        ELSE IF (V$TYPE_ID IN (9,187,125)) THEN
        BEGIN
            IF (I$PARAM_ID IN (2388, 2418, 2419)) THEN
            BEGIN
                -- Смену года для ГИА берем с 01 июля
                V$Y = EXTRACT(YEAR FROM CURRENT_DATE);
                V$DT = '1.07.' || V$Y;
            
                IF (CURRENT_DATE < V$DT) THEN
                BEGIN
                    V$YEAR_VAL = (V$Y - 1) || '-' || V$Y;
                END
                ELSE
                BEGIN
                    V$YEAR_VAL = V$Y || '-' ||(V$Y + 1);
                END
            
                SELECT FIRST 1 LV.LISTVAL_ID
                FROM LISTVALS LV
                JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
                WHERE LV.LIST_ID = 29 AND R.VAL LIKE :V$YEAR_VAL
                INTO :V$YEAR_ID;

                IF (EXISTS(
                    SELECT FIRST 1 1
                    FROM LINKS L119
                    JOIN VALL V742 ON V742.OBJ_ID = L119.OBJ_ID AND V742.PARAM_ID = 742 AND V742.IS_DEL = 0 AND V742.LISTVAL_ID = :V$YEAR_ID
                    LEFT JOIN GIA_APPOINT_LIST (:I$OBJ_ID, L119.OBJ_ID) L ON 1=1
                    WHERE L119.DATE_DEL IS NULL AND L119.OBJ_TYPE_ID = 119 AND L.EXAM_ID IS NOT NULL
                )) THEN
                BEGIN
                    CAN_CHANGE = 0;
                    ERR_MSG = 'В учебном коллективе есть обучающийся назначенный на экзамен(ы). Снимите назначение прежде чем изменять значение поля "Выпускной класс".';
                END
            END
        END
        ELSE IF (V$TYPE_ID = 297) THEN
        BEGIN
            V$Y = EXTRACT(YEAR FROM CURRENT_DATE);
            V$DT = '1.09.' || V$Y;
        
            IF (CURRENT_DATE < V$DT) THEN
            BEGIN
                V$YEAR_VAL = (V$Y - 1) || '-' || V$Y;
            END
            ELSE
            BEGIN
                V$YEAR_VAL = V$Y || '-' ||(V$Y + 1);
            END
        
            SELECT FIRST 1
                   LV.LISTVAL_ID
            FROM LISTVALS LV
        
            JOIN RES R
            ON R.RES_ID = LV.RES_ID
            AND R.LANG_CODE = 'RU'
        
            WHERE LV.LIST_ID = 29
            AND R.VAL LIKE :V$YEAR_VAL
            INTO :V$YEAR_ID;

            IF (NOT EXISTS(
                SELECT FIRST 1 1
                FROM VALL V2394

                WHERE V2394.OBJ_ID = :I$OBJ_ID
                AND V2394.PARAM_ID = 2394
                AND V2394.IS_DEL = 0
                AND V2394.LISTVAL_ID = :V$YEAR_ID
            )) THEN
            BEGIN
                CAN_CHANGE = 0;
                ERR_MSG = 'Возможно редактирование только записей текущего учебного года';
            END
        END
        ELSE IF (V$TYPE_ID = 10 AND I$PARAM_ID = 2442 AND :I$VAL < (
            SELECT FIRST 1 M.DATE_IN
            FROM PERSON_MOVEMENTS M
            JOIN OBJECTS O ON O.OBJ_ID = M.GROUP_ID AND O.TYPE_ID IN (9, 125, 187)
            WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :I$OBJ_ID
            ORDER BY M.DATE_IN DESC, M.OBJ_ID DESC)) THEN
        BEGIN
            CAN_CHANGE = 0;
            ERR_MSG = 'Дата зачисления не может быть меньше даты выбытия';
        END
    END
    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_CAN_DELETE_OBJECT (
    I$OBJ_ID BIGINT)
RETURNS (
    CAN_DELETE SMALLINT,
    ERR_MSG VARCHAR(4000))
AS
declare variable V$TYPE_ID bigint;
declare variable V$CNT bigint;
declare variable V$OBJ_ID bigint;
declare variable V$CAPTION varchar(1000);
declare variable V$NAME varchar(1000);
declare variable SCHOOL_ID bigint;
declare variable V$Y smallint;
declare variable V$DT date;
declare variable V$YEAR_VAL varchar(100);
declare variable V$YEAR_ID bigint;
BEGIN
    CAN_DELETE = 1;
    ERR_MSG = '';

    FOR
        SELECT TYPE_ID
        FROM OBJECTS
        WHERE OBJ_ID = :I$OBJ_ID
        INTO :V$TYPE_ID
    DO
    BEGIN
        IF (V$TYPE_ID = 297) THEN
        BEGIN
            V$Y = EXTRACT(YEAR FROM CURRENT_DATE);
            V$DT = '1.09.' || V$Y;
        
            IF (CURRENT_DATE < V$DT) THEN
            BEGIN
                V$YEAR_VAL = (V$Y - 1) || '-' || V$Y;
            END
            ELSE
            BEGIN
                V$YEAR_VAL = V$Y || '-' ||(V$Y + 1);
            END
        
            SELECT FIRST 1
                   LV.LISTVAL_ID
            FROM LISTVALS LV
        
            JOIN RES R
            ON R.RES_ID = LV.RES_ID
            AND R.LANG_CODE = 'RU'
        
            WHERE LV.LIST_ID = 29
            AND R.VAL LIKE :V$YEAR_VAL
            INTO :V$YEAR_ID;

            IF (NOT EXISTS(
                SELECT FIRST 1 1
                FROM VALL V2394
                WHERE V2394.OBJ_ID = :I$OBJ_ID AND V2394.PARAM_ID = 2394 AND V2394.IS_DEL = 0 AND V2394.LISTVAL_ID = :V$YEAR_ID
            )) THEN
            BEGIN
                CAN_DELETE = 0;
                ERR_MSG = 'Возможно удаление только записей текущего учебного года';
            END
        END
        ELSE IF (V$TYPE_ID = 51) THEN --vacancy
        BEGIN
            SELECT COUNT(CJL.OBJ_ID) + COUNT(CJF.OBJ_ID)
            FROM CJ2_JOURNAL CJM
            LEFT JOIN CJ2_JOURNAL_LESSONS CJL ON CJL.CJ_ID = CJM.OBJ_ID
            LEFT JOIN CJ2_JOURNAL_FINALS CJF ON CJF.CJ_ID = CJM.OBJ_ID
            WHERE CJM.SUBJECT_ID = :I$OBJ_ID
            INTO :V$CNT;

            IF (V$CNT > 0) THEN
            BEGIN
                CAN_DELETE = 0;
        
                SELECT CAPTION
                FROM OBJECT_CAPTION_GET(:I$OBJ_ID)
                INTO :V$CAPTION;
        
                ERR_MSG = 'Невозможно удалить предмет "' || V$CAPTION || '", так как существуют классные журналы с уроками, которые назначены этому предмету: ';
                V$CNT = 0;
                FOR
                    SELECT CJM.GRADE_ID
                    FROM CJ2_JOURNAL CJM
                    LEFT JOIN CJ2_JOURNAL_LESSONS CJL ON CJL.CJ_ID = CJM.OBJ_ID
                    LEFT JOIN CJ2_JOURNAL_FINALS CJF ON CJF.CJ_ID = CJM.OBJ_ID
                    WHERE CJM.SUBJECT_ID = :I$OBJ_ID
                    GROUP BY 1
                    HAVING COUNT(CJL.OBJ_ID) + COUNT(CJF.OBJ_ID) > 0
                    INTO :V$OBJ_ID
                DO
                BEGIN
                    SELECT CAPTION
                    FROM OBJECT_CAPTION_GET(:V$OBJ_ID)
                    INTO :V$NAME;
                    IF (V$CNT > 0) THEN
                    BEGIN
                        ERR_MSG = ERR_MSG || '; ';
                    END
                    ELSE
                    BEGIN
                        V$CNT = 1;
                    END
                    ERR_MSG = ERR_MSG || V$NAME || '. ' || V$CAPTION;
                END
                ERR_MSG = ERR_MSG || '';
            END
            ELSE IF (EXISTS(
                SELECT FIRST 1 1
                FROM PLAN_SUBJECTS S
                JOIN LINKS L400 ON L400.OBJ_ID = S.PLAN_ID AND L400.PARENT_TYPE_ID = 57 AND L400.DATE_DEL IS NULL
                WHERE S.SUBJECT_ID = :I$OBJ_ID AND S.DATE_DEL IS NULL
            )) THEN
            BEGIN
                SELECT FIRST 1 C.CAPTION
                FROM PLAN_SUBJECTS S
                JOIN LINKS L400 ON L400.OBJ_ID = S.PLAN_ID AND L400.PARENT_TYPE_ID = 57 AND L400.DATE_DEL IS NULL
                LEFT JOIN OBJECT_CAPTION_GET(S.PLAN_ID) C ON 1 = 1
                WHERE S.SUBJECT_ID = :I$OBJ_ID AND S.DATE_DEL IS NULL
                INTO :V$CAPTION;

                CAN_DELETE = 0;
                ERR_MSG = 'Невозможно удалить "Предмет" прикрепленный к учебному плану "' || V$CAPTION || '"';
            END
        END --51 vacancy
        ELSE IF (V$TYPE_ID = 13) THEN  -- vacancy
        BEGIN
            SELECT STATUS FROM OU_LICENCE_TYPE INTO :V$YEAR_VAL;
            IF (V$YEAR_VAL = 'S') THEN
            BEGIN
                IF (EXISTS(SELECT FIRST 1 1
                    FROM LINKS L13
                    LEFT JOIN VALL V58 ON V58.OBJ_ID = L13.OBJ_ID AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0                                       -- должность из списка (13)
                    LEFT JOIN VALS V66 ON V66.OBJ_ID = L13.OBJ_ID AND V66.PARAM_ID = 66 AND V66.IS_DEL = 0                                       -- название должности  (13)
                    JOIN LINKS L506 ON L506.OBJ_TYPE_ID = 506 AND L506.DATE_DEL IS NULL
                    JOIN VALL V3490 ON V3490.OBJ_ID = L506.PARENT_ID AND V3490.PARAM_ID = 3490 AND V3490.IS_DEL = 0 AND V3490.LISTVAL_ID = 11715 -- действующее ШР
                    LEFT JOIN VALL V3492 ON V3492.OBJ_ID = L506.OBJ_ID AND V3492.PARAM_ID = 3492 AND V3492.IS_DEL = 0                            -- должность из списка (506)
                    LEFT JOIN VALS V3494 ON V3494.OBJ_ID = L506.OBJ_ID AND V3494.PARAM_ID = 3494 AND V3494.IS_DEL = 0                            -- название должности  (506)
                    WHERE L13.OBJ_ID = :I$OBJ_ID AND L13.DATE_DEL IS NULL AND L13.PARENT_TYPE_ID IN (2, 211)
                      AND COALESCE(V58.LISTVAL_ID, 0) = COALESCE(V3492.LISTVAL_ID, 0) AND UPPER(TRIM(V66.VAL)) = UPPER(TRIM(V3494.VAL))
                )) THEN
                BEGIN
                  CAN_DELETE = 0;
                  ERR_MSG = 'Невозможно удалить должность, так как она задействована в действующем штатном расписании';
                END
            END

            SELECT L.OBJ_ID
            FROM LINKS L
            WHERE L.OBJ_TYPE_ID = 2
            AND L.PARENT_ID IS NULL
            INTO :SCHOOL_ID;

            SELECT COUNT(R69.VAL)
            FROM LINKS L14
            JOIN LINKS L15
            ON L15.OBJ_TYPE_ID = 15 AND L15.PARENT_ID = L14.OBJ_ID AND L15.DATE_DEL IS NULL
            JOIN VALR R69 ON R69.PARAM_ID = 69 AND R69.OBJ_ID = L15.OBJ_ID AND R69.IS_DEL = 0
            WHERE L14.OBJ_TYPE_ID = 14 AND L14.PARENT_ID = :SCHOOL_ID AND L14.DATE_DEL IS NULL AND R69.VAL = :I$OBJ_ID
            INTO :V$CNT;

            SELECT COUNT(R69.VAL) + :V$CNT
            FROM LINKS L84
            JOIN LINKS L14 ON L14.OBJ_TYPE_ID = 14 AND L14.PARENT_ID = L84.OBJ_ID AND L14.DATE_DEL IS NULL
            JOIN LINKS L15 ON L15.OBJ_TYPE_ID = 15 AND L15.PARENT_ID = L14.OBJ_ID AND L15.DATE_DEL IS NULL
            JOIN VALR R69 ON R69.PARAM_ID = 69 AND R69.OBJ_ID = L15.OBJ_ID AND R69.IS_DEL = 0
            WHERE L84.OBJ_TYPE_ID = 84 AND L84.PARENT_ID = :SCHOOL_ID AND L84.DATE_DEL IS NULL AND R69.VAL = :I$OBJ_ID
            INTO :V$CNT;

            IF (V$CNT > 0) THEN
            BEGIN
                CAN_DELETE = 0;
                ERR_MSG = 'Невозможно удалить должность на которую назначались сотрудники (есть записи о приеме сотрудника(ов) на эту должность)';
            END
        END --13 vacancy
        ELSE IF (V$TYPE_ID = 57) THEN
        BEGIN
            IF (EXISTS(
                SELECT FIRST 1 1
                FROM LINKS
                WHERE PARENT_ID = :I$OBJ_ID AND DATE_DEL IS NULL AND OBJ_TYPE_ID IN (50, 400)
            )) THEN
            BEGIN
                CAN_DELETE = 0;
                ERR_MSG = 'Невозможно удалить "Образовательную программу" содержащую учебные планы';
            END
        END
        ELSE IF (V$TYPE_ID = 69) THEN
        BEGIN
            IF (EXISTS(
                SELECT FIRST 1 1
                FROM LINKS
                WHERE PARENT_ID = :I$OBJ_ID AND DATE_DEL IS NULL
            )) THEN
            BEGIN
                SELECT CAPTION
                FROM OBJECT_CAPTION_GET(:I$OBJ_ID)
                INTO :V$NAME;

                CAN_DELETE = 0;
                ERR_MSG = 'Невозможно удалить "' || V$NAME || '" содержащую образовательную программу';
            END
        END
        ELSE IF (V$TYPE_ID IN (50, 400)) THEN
        BEGIN
            IF (EXISTS(
                SELECT FIRST 1 1
                FROM LINKS L54
                JOIN LINKS L9 ON L9.PARENT_ID = L54.OBJ_ID AND L9.DATE_DEL IS NULL AND L9.OBJ_TYPE_ID IN (9, 256)
                WHERE L54.PARENT_ID = :I$OBJ_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
            )) THEN
            BEGIN
                CAN_DELETE = 0;
                ERR_MSG = 'Невозможно удалить "Учебный план" к которому прикреплены учебные коллективы или ГУП';
            END
        END
        ELSE IF (V$TYPE_ID = 49) THEN
        BEGIN
            IF (EXISTS(
                SELECT FIRST 1 1
                FROM LINKS L51
                WHERE L51.PARENT_ID = :I$OBJ_ID AND L51.DATE_DEL IS NULL AND L51.OBJ_TYPE_ID = 51
            )) THEN
            BEGIN
                CAN_DELETE = 0;
                ERR_MSG = 'Невозможно удалить "Учебный компонент" принадлежащий учебному плану к которому прикреплены учебные предметы';
            END
        END
        ELSE IF (V$TYPE_ID = 54) THEN
        BEGIN
            IF (EXISTS(
                SELECT FIRST 1 1
                FROM LINKS L9
                WHERE L9.PARENT_ID = :I$OBJ_ID AND L9.DATE_DEL IS NULL AND L9.OBJ_TYPE_ID IN (9, 256)
            )) THEN
            BEGIN
                CAN_DELETE = 0;
                ERR_MSG = 'Невозможно удалить "Этап учебного плана" к которому прикреплены учебные коллективы или ГУП';
            END
        END
        ELSE IF (V$TYPE_ID = 48) THEN
        BEGIN
            -- Подгрупп у нас уже нет
        END
        ELSE IF (V$TYPE_ID = 47) THEN
        BEGIN
            -- Подгрупп у нас уже нет
        END
        ELSE IF (V$TYPE_ID = 86) THEN
        BEGIN
            IF (EXISTS(
                SELECT FIRST 1 1
                FROM LINKS L46
                JOIN LINKS L10 ON L10.PARENT_ID = L46.OBJ_ID AND L10.DATE_DEL IS NULL AND L10.OBJ_TYPE_ID = 10
                WHERE L46.PARENT_ID = :I$OBJ_ID AND L46.DATE_DEL IS NULL AND L46.OBJ_TYPE_ID = 46
            )) THEN
            BEGIN
                CAN_DELETE = 0;
                ERR_MSG = 'Невозможно удалить "Раздел", к группам которого прикреплены воспитанники';
            END
        END
        ELSE IF (V$TYPE_ID = 46) THEN
        BEGIN
            IF (EXISTS(
                SELECT FIRST 1 1
                FROM LINKS L10
                WHERE L10.PARENT_ID = :I$OBJ_ID AND L10.DATE_DEL IS NULL AND L10.OBJ_TYPE_ID = 10
            )) THEN
            BEGIN
                CAN_DELETE = 0;
                ERR_MSG = 'Невозможно удалить "Группу", к которой прикреплены воспитанники';
            END
        END
        ELSE IF (V$TYPE_ID = 211) THEN
        BEGIN
            IF (EXISTS(
                SELECT FIRST 1 1
                FROM LINKS L242
                JOIN LINKS L243 ON L243.PARENT_ID = L242.OBJ_ID AND L243.DATE_DEL IS NULL AND L243.OBJ_TYPE_ID = 243
                JOIN LINKS L10 ON L10.PARENT_ID = L243.OBJ_ID AND L10.DATE_DEL IS NULL AND L10.OBJ_TYPE_ID = 10
                WHERE L242.PARENT_ID = :I$OBJ_ID AND L242.DATE_DEL IS NULL AND L242.OBJ_TYPE_ID = 242
            )) THEN
            BEGIN
                CAN_DELETE = 0;
                ERR_MSG = 'Невозможно удалить "' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$OBJ_ID)) ||
                          '", к детским коллективам которого прикреплены воспитанники';
            END
            ELSE
            IF (EXISTS(
                SELECT FIRST 1 1
                FROM LINKS L14
                WHERE L14.PARENT_ID = :I$OBJ_ID AND L14.DATE_DEL IS NULL AND L14.OBJ_TYPE_ID = 14
            )) THEN
            BEGIN
                CAN_DELETE = 0;
                ERR_MSG = 'Невозможно удалить "' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$OBJ_ID)) ||
                          '", к которому прикреплены сотрудники';
            END
            ELSE
            IF (EXISTS(
                SELECT FIRST 1 1
                FROM LINKS L252
                WHERE L252.PARENT_ID = :I$OBJ_ID AND L252.DATE_DEL IS NULL AND L252.OBJ_TYPE_ID = 252
            )) THEN
            BEGIN
                CAN_DELETE = 0;
                ERR_MSG = 'Невозможно удалить "' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$OBJ_ID)) ||
                          '", к которому прикреплены образовательные программы';
            END
        END
        ELSE IF (V$TYPE_ID = 242) THEN
        BEGIN
            IF (EXISTS(
                SELECT FIRST 1 1
                FROM LINKS L243
                
                JOIN LINKS L10
                ON L10.PARENT_ID = L243.OBJ_ID
                AND L10.DATE_DEL IS NULL
                AND L10.OBJ_TYPE_ID = 10
                
                WHERE L243.PARENT_ID = :I$OBJ_ID
                AND L243.DATE_DEL IS NULL
                AND L243.OBJ_TYPE_ID = 243
            )) THEN
            BEGIN
                CAN_DELETE = 0;
                ERR_MSG = 'Невозможно удалить "Объединение", к которому прикреплены воспитанники';
            END
        END
        ELSE IF (V$TYPE_ID = 243) THEN
        BEGIN
            IF (EXISTS(
                SELECT FIRST 1 1
                FROM LINKS L10

                WHERE L10.PARENT_ID = :I$OBJ_ID
                AND L10.DATE_DEL IS NULL
                AND L10.OBJ_TYPE_ID = 10
            )) THEN
            BEGIN
                CAN_DELETE = 0;
                ERR_MSG = 'Невозможно удалить "Этап обучения", к которому прикреплены воспитанники';
            END
        END
        ELSE IF (V$TYPE_ID = 7) THEN
        BEGIN
            IF(EXISTS(
                SELECT FIRST 1 1
                FROM LINKS L8
                WHERE L8.PARENT_ID = :I$OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
            )) THEN
            BEGIN
                CAN_DELETE = 0;
                ERR_MSG = 'Невозможно удалить "Уровень обучения", в котором есть этапы';
            END
        END
        ELSE IF (V$TYPE_ID = 8) THEN
        BEGIN
            IF(EXISTS(
                SELECT FIRST 1 1
                FROM LINKS L9
                WHERE L9.PARENT_ID = :I$OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 125, 187) AND L9.DATE_DEL IS NULL
            )) THEN
            BEGIN
                CAN_DELETE = 0;
                ERR_MSG = 'Невозможно удалить "Этап обучения", в котором есть учебные коллективы';
            END
        END
        ELSE IF (V$TYPE_ID IN (9, 187)) THEN
        BEGIN
            IF (EXISTS(
                SELECT FIRST 1 1
                FROM LINKS L10
                WHERE L10.PARENT_ID = :I$OBJ_ID AND L10.DATE_DEL IS NULL AND L10.OBJ_TYPE_ID = 10
            )) THEN
            BEGIN
                CAN_DELETE = 0;
                ERR_MSG = 'Невозможно удалить "Учебный коллектив", к которому прикреплены обучающиеся';
            END
        END
        ELSE IF (V$TYPE_ID IN (500, 502)) THEN
        BEGIN
            IF (EXISTS(
                SELECT FIRST 1 1
                FROM LINKS L
                WHERE L.PARENT_ID = :I$OBJ_ID AND L.DATE_DEL IS NULL AND L.OBJ_TYPE_ID IN (8, 46) -- тут может быть ГПД или этап обучения
            )) THEN
            BEGIN
                CAN_DELETE = 0;
                ERR_MSG = 'Невозможно удалить "Раздел", к которому прикреплены учебные коллективы';
            END
        END
        ELSE IF (V$TYPE_ID = 10) THEN
        BEGIN
            IF(EXISTS(
                SELECT FIRST 1 1
                FROM ORDER_DATA OD
                JOIN ORDERS D ON D.OBJ_ID = OD.ORDER_ID AND D.DATE_DEL IS NULL AND D.STATE_ID = 11716
                WHERE OD.DATE_DEL IS NULL AND OD.REF_ID = :I$OBJ_ID
            )) THEN
            BEGIN
                CAN_DELETE = 0;
                ERR_MSG = 'Невозможно удалить обучающегося, который включен в проекты приказов';
            END
        END
        ELSE IF (V$TYPE_ID = 505) THEN
        BEGIN
            SELECT V.LISTVAL_ID
            FROM VALL V
            WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 3490 AND V.IS_DEL = 0
            INTO V$CNT;

            IF (V$CNT <> 11716) THEN
            BEGIN
                CAN_DELETE = 0;
                ERR_MSG = 'Невозможно удалить штатное расписание в любом статусе, кроме проекта';
            END
        END
    END
    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_CLASS_LIST (
    I$OBJ_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    OBJ_CAPTION VARCHAR(4000),
    SORT_ORDER DOUBLE PRECISION)
AS
declare variable SCHOOL_ID bigint;
BEGIN
    SELECT FIRST 1 OBJ_ID
    FROM OBJECT_PARENTS_GET(:I$OBJ_ID, 2)
    INTO :SCHOOL_ID;

    FOR
        SELECT L9.OBJ_ID
        FROM LINKS L7
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
        WHERE L7.PARENT_ID = :SCHOOL_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
        INTO :OBJ_ID
    DO
    BEGIN
        SELECT CAPTION, SORT_ORDER
        FROM OBJECT_CAPTION_GET(:OBJ_ID)
        INTO :OBJ_CAPTION, :SORT_ORDER;
        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_COLLEGE_SUBJECTS_LIST2 (
    I$CURRICULUM_ID BIGINT,
    I$USER_ID BIGINT,
    I$LEVEL_ID INTEGER = 0)
RETURNS (
    SUBJECT_ID BIGINT,
    SUBJECT_CAPTION VARCHAR(4000))
AS
BEGIN
    FOR
        SELECT DISTINCT L197.OBJ_ID, C.V
        FROM DISCIPLINE_TREE(:I$CURRICULUM_ID, NULL, :I$USER_ID) DT201
        JOIN VALR V1766 ON V1766.OBJ_ID = DT201.OBJ_ID AND V1766.PARAM_ID = 1766 AND V1766.IS_DEL = 0
        JOIN LINKS L197 ON L197.OBJ_ID = V1766.VAL AND L197.OBJ_TYPE_ID = 197 AND L197.PARENT_TYPE_ID = 193 AND L197.DATE_DEL IS NULL
        JOIN VALL V1750 ON V1750.OBJ_ID = L197.OBJ_ID AND V1750.PARAM_ID = 1750 AND V1750.IS_DEL = 0
          AND V1750.LISTVAL_ID IN (SELECT OBJ_ID FROM CJ_STAGE_LIST(:I$USER_ID, :I$LEVEL_ID))
        LEFT JOIN VAL_GET(L197.OBJ_ID, 1751, 0, :I$USER_ID) C ON 1 = 1
        WHERE DT201.IS_LAST = 0 AND DT201.TYPE_ID = 201
        INTO :SUBJECT_ID, :SUBJECT_CAPTION
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_CURRICULUM_COPY (
    I$OBJ_ID BIGINT,
    I$CURRICULUM_ID BIGINT,
    I$COPY_MODE SMALLINT = 0)
RETURNS (
    OBJ_ID BIGINT)
AS
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$SRC_STAGE_ID BIGINT;
DECLARE VARIABLE V$SRC_STAGE_TYPE_ID BIGINT;
DECLARE VARIABLE V$STAGE_ID BIGINT;
DECLARE VARIABLE V$DST_STAGE_ID BIGINT;
DECLARE VARIABLE V$LOADING_ID BIGINT;
DECLARE VARIABLE V$SRC_LOADING_ID BIGINT;
DECLARE VARIABLE V$COMPONENT_ID BIGINT;
DECLARE VARIABLE V$SRC_COMPONENT_ID BIGINT;
DECLARE VARIABLE V$SUBJECT_ID BIGINT;
DECLARE VARIABLE V$STR VARCHAR(4000);
DECLARE VARIABLE V$PARAM_ID BIGINT;
DECLARE VARIABLE V$SUBJECT_COST FLOAT;
DECLARE VARIABLE V$TYPE_ID BIGINT;
DECLARE VARIABLE V$SRC_SUBJECT_ID BIGINT;
DECLARE VARIABLE V$FIELD_ID BIGINT;
DECLARE VARIABLE V$SORT_INDEX INTEGER;
DECLARE VARIABLE V$PARENT_ID BIGINT;
DECLARE VARIABLE V$LEVEL_INDEX INTEGER;
DECLARE VARIABLE V$GLOBAL_INDEX INTEGER;
DECLARE VARIABLE V$IS_ADV INTEGER;
DECLARE VARIABLE V$ROW_TYPE INTEGER;
DECLARE VARIABLE V$IS_STM INTEGER;
DECLARE VARIABLE V$DST_PARENT_ID BIGINT;
DECLARE VARIABLE V$ID BIGINT;
DECLARE VARIABLE V$DST_ID BIGINT;
DECLARE VARIABLE V$DST_ID2 BIGINT;
DECLARE VARIABLE V$WEEKS INTEGER;
DECLARE VARIABLE V$LOAD_HOURS FLOAT;
DECLARE VARIABLE V$LOAD_HOURS_S1 FLOAT;
DECLARE VARIABLE V$LOAD_HOURS_S2 FLOAT;
DECLARE VARIABLE V$CONTROL_Q1 BIGINT;
DECLARE VARIABLE V$CONTROL_Q2 BIGINT;
DECLARE VARIABLE V$VD BIGINT;
DECLARE VARIABLE V$WD BIGINT;
DECLARE VARIABLE LNX INTEGER;
DECLARE VARIABLE N INTEGER;
DECLARE VARIABLE V$HOURS_THEORY1 FLOAT;
DECLARE VARIABLE V$HOURS_PR1 FLOAT;
DECLARE VARIABLE V$HOURS_DX1 FLOAT;
DECLARE VARIABLE V$HOURS_IND1 FLOAT;
DECLARE VARIABLE V$HOURS_MAX FLOAT;
DECLARE VARIABLE V$HOURS_CR1 FLOAT;
DECLARE VARIABLE V$HOURS_ATT1 FLOAT;
DECLARE VARIABLE V$HOURS_GIA FLOAT;
DECLARE VARIABLE V$HOURS_REST FLOAT;
DECLARE VARIABLE V$CJ_ID BIGINT;
DECLARE VARIABLE V$DEST_ID BIGINT;
DECLARE VARIABLE V$DATE DATE;
DECLARE VARIABLE S2 VARCHAR(1000);
DECLARE VARIABLE V$CJ_YEAR INTEGER;
DECLARE VARIABLE V$CJ_YEAR2 INTEGER;
DECLARE VARIABLE V$SPO SMALLINT;
DECLARE VARIABLE V$_ID BIGINT;
DECLARE VARIABLE V$_FIELD BIGINT;
DECLARE VARIABLE V$_SUBJ BIGINT;
DECLARE VARIABLE V$_TYPE BIGINT;
DECLARE VARIABLE V$SUBJ_ID BIGINT;
DECLARE VARIABLE V$PARENT0 BIGINT;
DECLARE VARIABLE V$PARENT1 BIGINT;
DECLARE VARIABLE V$PARENT2 BIGINT;
DECLARE VARIABLE V$_PARENT BIGINT;
DECLARE VARIABLE V$LEVEL BIGINT;
DECLARE VARIABLE V$SUBJ_CODE VARCHAR(40);
DECLARE VARIABLE V$TIME_FRAME INTEGER;
DECLARE VARIABLE V$OP_YEAR INTEGER;
DECLARE VARIABLE V$STD_ID BIGINT;
DECLARE VARIABLE V$IS_FOP SMALLINT;
BEGIN

  SELECT TYPE_ID
  FROM OBJECTS
  WHERE OBJ_ID = :I$CURRICULUM_ID
  INTO :V$TYPE_ID;

  IF(V$TYPE_ID = 478) THEN
  BEGIN

    -- Планы воспитательной работы
    -- Из атрибутов - название и год
    SELECT OBJ_ID
    FROM OBJECT_ADD(:I$OBJ_ID, 478)
    INTO :OBJ_ID;

    SELECT V.VAL
    FROM VALS V
    WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 3374 AND V.IS_DEL = 0
    INTO :V$STR;

    SELECT 1 FROM VAL_ADD(3374, :OBJ_ID, :V$STR || ' (копия)') INTO :N;

    SELECT J.OBJ_ID, LV.COST
    FROM CJ2_JOURNAL J
    JOIN LISTVALS LV ON LV.LISTVAL_ID = J.YEAR_ID
    WHERE J.DATE_DEL IS NULL AND J.REF_ID = :I$CURRICULUM_ID
    INTO :V$CJ_ID, :V$CJ_YEAR;

    SELECT J.OBJ_ID, LV.COST
    FROM CJ2_JOURNAL J
    JOIN LISTVALS LV ON LV.LISTVAL_ID = J.YEAR_ID
    WHERE J.DATE_DEL IS NULL AND J.REF_ID = :OBJ_ID
    INTO :V$DEST_ID, :V$CJ_YEAR2;

    -- Содержимое плана 1:1
    FOR
      SELECT L.OBJ_ID, L.LESSON_DATE, L.LESSON_NUM, L.LESSON_THEME, L.LESSON_HOMEWORK
      FROM CJ2_JOURNAL_LESSONS L
      WHERE L.DATE_DEL IS NULL AND L.CJ_ID = :V$CJ_ID
      ORDER BY ABS(L.LESSON_NUM)
      INTO :V$OBJ_ID, :V$DATE, :V$PARAM_ID, :V$STR, :S2
    DO
    BEGIN
      -- Корректируем дату по текущему году
      IF(EXTRACT(YEAR FROM V$DATE) > 2000) THEN V$DATE = SUBSTRING((SELECT RESULT FROM DATE2STR(:V$DATE)) FROM 1 FOR 6) ||
        (EXTRACT(YEAR FROM V$DATE) - V$CJ_YEAR + V$CJ_YEAR2);

      INSERT INTO CJ2_JOURNAL_LESSONS
      (CJ_ID, LESSON_DATE, LESSON_NUM, LESSON_THEME, LESSON_HOMEWORK)
      VALUES (:V$DEST_ID, :V$DATE, :V$PARAM_ID, :V$STR, :S2)
      RETURNING OBJ_ID INTO :V$DST_ID;

      -- Атрибуты
      FOR
        SELECT A.ATTR_NAME, A.ATTR_VALUE, A.REF_ID, A.LISTVAL_ID
        FROM CJ2_LESSON_ATTRS A
        WHERE A.DATE_DEL IS NULL AND A.LESSON_ID = :V$OBJ_ID
        INTO :V$STR, :S2, :V$ID, :V$SUBJECT_ID
      DO
      BEGIN
        -- Дата окончания - корректируем дату по текущему году
        -- дата 29.02 будет коллапсом, заменяем всегда на 28.02
        IF(V$STR = 'date_to' AND S2 <> '') THEN
        BEGIN
          IF(SUBSTRING(S2 FROM 5 FOR 6) = '-02-29') THEN S2 = SUBSTRING(S2 FROM 1 FOR 4) || '-02-28';
          N = SUBSTRING(S2 FROM 1 FOR 4);
          S2 = (N - V$CJ_YEAR + V$CJ_YEAR2) || SUBSTRING(S2 FROM 5);
        END

        INSERT INTO CJ2_LESSON_ATTRS
        (LESSON_ID, ATTR_NAME, ATTR_VALUE, REF_ID, LISTVAL_ID)
        VALUES (:V$DST_ID, :V$STR, :S2, :V$ID, :V$SUBJECT_ID);
      END
    END

  END
  ELSE
  BEGIN

    -- Не даем копировать, если не заполнен тип ОП
    SELECT FIRST 1 1
    FROM VALL V1832
    WHERE V1832.OBJ_ID = :I$OBJ_ID AND V1832.PARAM_ID = 1832 AND V1832.IS_DEL = 0
    INTO :V$OBJ_ID;

    IF(I$OBJ_ID <> 258 AND V$OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Необходимо заполнить вид ОП';

    IF(I$COPY_MODE < 100) THEN
    BEGIN

      -- Старый формат копирования (типы 50, 245)

      SELECT OBJ_ID
      FROM OBJECT_COPY(:I$OBJ_ID, :I$CURRICULUM_ID)
      INTO :OBJ_ID;

      IF (I$COPY_MODE = 1) THEN
      BEGIN
        IF(V$TYPE_ID = 245) THEN V$PARAM_ID = 2127; ELSE V$PARAM_ID = 374;

        FOR
          SELECT V || ' (копия)'
          FROM VAL_GET(:I$CURRICULUM_ID, :V$PARAM_ID)
          INTO :V$STR
        DO
        BEGIN
          SELECT BLOB_ID
          FROM VAL_ADD(:V$PARAM_ID, :OBJ_ID, :V$STR)
          INTO :V$OBJ_ID;
        END
        -- Переводим УП в статус "проект"
        SELECT BLOB_ID FROM VAL_ADD(2470, :OBJ_ID, 11716) INTO :V$OBJ_ID;
        -- Удаляем поля номера и даты приказа об утверждении
        SELECT V FROM VAL_GET(:OBJ_ID, 2472) INTO :V$STR;
        SELECT BLOB_ID FROM VAL_ADD(2472, :OBJ_ID, :V$STR, null, 1) INTO :V$OBJ_ID;
        SELECT V FROM VAL_GET(:OBJ_ID, 2473) INTO :V$STR;
        SELECT BLOB_ID FROM VAL_ADD(2473, :OBJ_ID, :V$STR, null, 1) INTO :V$OBJ_ID;
      END

      -- Копируем компоненты УП
      FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 49 AND L.PARENT_ID = :I$CURRICULUM_ID AND L.DATE_DEL IS NULL
        INTO :V$SRC_COMPONENT_ID
      DO
      BEGIN
        SELECT OBJ_ID
        FROM OBJECT_COPY(:OBJ_ID, :V$SRC_COMPONENT_ID, 49)
        INTO :V$COMPONENT_ID;

        SELECT BLOB_ID
        FROM VAL_ADD(427, :V$COMPONENT_ID, CAST(:V$SRC_COMPONENT_ID AS VARCHAR(4000)))
        INTO :V$OBJ_ID;

        -- Копируем предметы, сохраняя порядок отображения
        FOR
          SELECT L.OBJ_ID, L.COST
          FROM LINKS L
          WHERE L.OBJ_TYPE_ID = 51 AND L.PARENT_ID = :V$SRC_COMPONENT_ID AND L.DATE_DEL IS NULL
          ORDER BY 2
          INTO :V$OBJ_ID, :V$SUBJECT_COST
        DO
        BEGIN
          SELECT OBJ_ID
          FROM OBJECT_ADD_LINK(:V$COMPONENT_ID, :V$OBJ_ID, 51, null, null, null, :V$SUBJECT_COST)
          INTO :V$OBJ_ID;
        END

      END

      -- Копируем этапы УП TYPE_ID IN (54, 247)
      FOR
        SELECT L.OBJ_ID, L.OBJ_TYPE_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID IN (54, 247) AND L.PARENT_ID = :I$CURRICULUM_ID AND L.DATE_DEL IS NULL
        INTO :V$SRC_STAGE_ID, :V$SRC_STAGE_TYPE_ID
      DO
      BEGIN
        IF (V$SRC_STAGE_TYPE_ID = 247) THEN
        BEGIN
          FOR
            SELECT OBJ_ID
            FROM LINKS L
            WHERE L.OBJ_TYPE_ID = 247 AND L.PARENT_ID = :OBJ_ID AND L.DATE_DEL IS NULL
            INTO :V$STAGE_ID
          DO
          BEGIN
            SELECT NULL
            FROM OBJECT_DEL(:OBJ_ID, :V$STAGE_ID)
            INTO :V$OBJ_ID;
          END
        END

        SELECT OBJ_ID
        FROM OBJECT_COPY(:OBJ_ID, :V$SRC_STAGE_ID, :V$SRC_STAGE_TYPE_ID)
        INTO :V$STAGE_ID;

        -- SEARCHING FOR COLLEGE TYPE_ID=209
        FOR
          SELECT L.OBJ_ID
          FROM LINKS L
          WHERE L.OBJ_TYPE_ID = 209 AND L.PARENT_ID = :V$SRC_STAGE_ID AND L.DATE_DEL IS NULL
          INTO :V$SRC_LOADING_ID
        DO
        BEGIN
          SELECT OBJ_ID
          FROM OBJECT_COPY(:V$STAGE_ID, :V$SRC_LOADING_ID, 209)
          INTO :V$LOADING_ID;
        END

        -- SEARCHING FOR LOADING LEVEL TYPE_ID=56
        FOR
          SELECT L.OBJ_ID
          FROM LINKS L
          WHERE L.OBJ_TYPE_ID = 56 AND L.PARENT_ID = :V$SRC_STAGE_ID AND L.DATE_DEL IS NULL
          INTO :V$SRC_LOADING_ID
        DO
        BEGIN
          SELECT OBJ_ID
          FROM OBJECT_COPY(:V$STAGE_ID, :V$SRC_LOADING_ID, 56)
          INTO :V$LOADING_ID;

          V$COMPONENT_ID = NULL;

          FOR
            SELECT L.PARENT_ID
            FROM LINKS L
            WHERE L.PARENT_TYPE_ID = 49 AND L.OBJ_ID = :V$SRC_LOADING_ID AND L.DATE_DEL IS NULL
            INTO :V$SRC_COMPONENT_ID
          DO
          BEGIN
            FOR
              SELECT L.OBJ_ID
              FROM LINKS L
              WHERE L.OBJ_TYPE_ID = 49 AND L.PARENT_ID = :OBJ_ID AND L.DATE_DEL IS NULL
              INTO :V$COMPONENT_ID
            DO
            BEGIN
              V$OBJ_ID = NULL;

              SELECT I
              FROM VAL_GET(:V$COMPONENT_ID, 427)
              INTO :V$OBJ_ID;

              IF (V$OBJ_ID <> V$SRC_COMPONENT_ID) THEN BEGIN
                V$COMPONENT_ID = NULL;
              END
              ELSE BEGIN
                BREAK;
              END
            END
          END

          IF (V$COMPONENT_ID IS NOT NULL) THEN BEGIN
            SELECT OBJ_ID
            FROM OBJECT_ADD_LINK(:V$COMPONENT_ID, :V$LOADING_ID, 56)
            INTO :V$OBJ_ID;
          END

          -- SEARCHING FOR SUBJECT ID
          V$SUBJECT_ID = NULL;

          SELECT FIRST 1 L.PARENT_ID
          FROM LINKS L
          WHERE L.PARENT_TYPE_ID = 51 AND L.OBJ_ID = :V$SRC_LOADING_ID AND L.DATE_DEL IS NULL
          INTO :V$SUBJECT_ID;

          IF (V$SUBJECT_ID IS NOT NULL) THEN BEGIN
            SELECT OBJ_ID
            FROM OBJECT_ADD_LINK(:V$SUBJECT_ID, :V$LOADING_ID, 56)
            INTO :V$OBJ_ID;
          END
        END
      END

      -- SEARCHING FOR COLLEGE TYPE_ID=208
      FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 208 AND L.PARENT_ID = :I$CURRICULUM_ID AND L.DATE_DEL IS NULL
        INTO :V$SRC_LOADING_ID
      DO
      BEGIN
        SELECT OBJ_ID
        FROM OBJECT_COPY(:OBJ_ID, :V$SRC_LOADING_ID, 208)
        INTO :V$LOADING_ID;
      END

      -- coping the college discipline tree
      FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = 185 AND L.PARENT_ID = :I$CURRICULUM_ID AND L.DATE_DEL IS NULL
        INTO :V$SRC_STAGE_ID
      DO
      BEGIN
        EXECUTE PROCEDURE OBJECT_TREE_COPY(:OBJ_ID, :V$SRC_STAGE_ID, 185);
      END

    END
    ELSE
    BEGIN

      -- Копирование в новый формат учебных планов, тип 400

      IF(V$TYPE_ID = 400) THEN
      BEGIN
        -- Новый учебный план - копируем бинарно
        -- Скидываем в проект, заменяем название со словом копия
        SELECT OBJ_ID
        FROM OBJECT_COPY(:I$OBJ_ID, :I$CURRICULUM_ID)
        INTO :OBJ_ID;

        SELECT BLOB_ID FROM VAL_ADD(3013, :OBJ_ID, 11716) INTO :V$OBJ_ID;
        SELECT BLOB_ID FROM VAL_ADD(3018, :OBJ_ID, '') INTO :V$OBJ_ID;
        SELECT BLOB_ID FROM VAL_ADD(3019, :OBJ_ID, '') INTO :V$OBJ_ID;

        V$STR = NULL;
        SELECT VAL FROM VALS V3012 WHERE V3012.OBJ_ID = :OBJ_ID AND V3012.PARAM_ID = 3012 AND V3012.IS_DEL = 0 INTO :V$STR;
        V$STR = COALESCE(V$STR, '') || ' (копия)';
        SELECT BLOB_ID FROM VAL_ADD(3012, :OBJ_ID, :V$STR) INTO :V$OBJ_ID;

        -- Выставляем признак внеурочности по названию
        IF(POSITION('ВНЕУРОЧ' IN UPPER(V$STR)) > 0) THEN
        SELECT BLOB_ID FROM VAL_ADD(3022, :OBJ_ID, 2) INTO :V$OBJ_ID;

        SELECT FIRST 1 V.LISTVAL_ID
        FROM VALL V
        WHERE V.OBJ_ID = :I$CURRICULUM_ID AND V.PARAM_ID = 3346 AND V.IS_DEL = 0
        INTO :V$WD;

        -- Копируем этапы обучения 1:1
        FOR
          SELECT OBJ_ID
          FROM LINKS L54
          WHERE L54.PARENT_ID = :I$CURRICULUM_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
          INTO :V$OBJ_ID
        DO
        BEGIN
          SELECT OBJ_ID FROM OBJECT_COPY(:OBJ_ID, :V$OBJ_ID) INTO :V$DST_ID;

          -- Если у нас было указано количество часов в шаблоне - их же копируем в этап
          IF(V$WD IS NOT NULL) THEN SELECT 1 FROM VAL_ADD(2837, :V$DST_ID, :V$WD) INTO :V$DST_ID;
        END

        -- Год публикации и стандарт ?
        SELECT FIRST 1 V3115.VAL, V3014.LISTVAL_ID
        FROM LINKS LP57
        JOIN VALL V3014 ON V3014.OBJ_ID = LP57.OBJ_ID AND V3014.PARAM_ID = 3014 AND V3014.IS_DEL = 0
        JOIN VALI V3115 ON V3115.OBJ_ID = LP57.PARENT_ID AND V3115.PARAM_ID = 3115 AND V3115.IS_DEL = 0
        WHERE LP57.OBJ_ID = :I$OBJ_ID AND LP57.PARENT_TYPE_ID = 57 AND LP57.DATE_DEL IS NULL
        INTO :V$OP_YEAR, :V$STD_ID;

        -- Выбираем предметную область
        V$IS_FOP = 0;
        IF(V$STD_ID IN (14184, 14186)) THEN V$IS_FOP = 1;

        FOR
          SELECT S.OBJ_ID, S.SUBJECT_ID, S.FIELD_ID, S.SORT_INDEX, SP.GLOBAL_INDEX, S.LEVEL_INDEX, S.GLOBAL_INDEX, S.IS_ADV, S.ROW_TYPE, S.SRC_SUBJECT_ID, S.IS_STM
          FROM PLAN_SUBJECTS S
          LEFT JOIN PLAN_SUBJECTS SP ON SP.OBJ_ID = S.PARENT_ID
          WHERE S.DATE_DEL IS NULL AND S.PLAN_ID = :I$CURRICULUM_ID
          ORDER BY S.GLOBAL_INDEX
          INTO :V$ID, :V$SUBJECT_ID, :V$FIELD_ID, :V$SORT_INDEX, :V$PARENT_ID, :V$LEVEL_INDEX, :V$GLOBAL_INDEX, :V$IS_ADV, :V$ROW_TYPE, :V$SRC_SUBJECT_ID, :V$IS_STM
        DO
        BEGIN

          -- Находим нового родителя по старому
          V$DST_PARENT_ID = NULL;
          SELECT FIRST 1 S.OBJ_ID
          FROM PLAN_SUBJECTS S
          WHERE S.PLAN_ID = :OBJ_ID AND S.DATE_DEL IS NULL AND S.GLOBAL_INDEX = :V$PARENT_ID
          INTO :V$DST_PARENT_ID;

          -- Заменяем предметную область для физкультуры и ОБЖ в >= 2024 для ФОП и ФАОП
          IF(V$OP_YEAR >= 2024 AND V$STD_ID IN (14184, 14186)) THEN
          BEGIN
            IF(V$SUBJECT_ID = 205 OR V$SRC_SUBJECT_ID = 205) THEN V$FIELD_ID = 14553; -- физкультура
            IF(V$SUBJECT_ID = 206 OR V$SRC_SUBJECT_ID = 206) THEN
            BEGIN
              V$FIELD_ID = 14552; -- ОБЖ заменяем на Защиту Родины
              IF(V$SUBJECT_ID = 206) THEN V$SUBJECT_ID = 38700;
              IF(V$SRC_SUBJECT_ID = 206) THEN V$SRC_SUBJECT_ID = 38700;
            END
          END

          INSERT INTO PLAN_SUBJECTS
          (PLAN_ID, SUBJECT_ID, FIELD_ID, SORT_INDEX, PARENT_ID, LEVEL_INDEX, GLOBAL_INDEX, IS_ADV, ROW_TYPE, SRC_SUBJECT_ID, IS_STM)
          VALUES (:OBJ_ID, :V$SUBJECT_ID, :V$FIELD_ID, :V$SORT_INDEX, :V$DST_PARENT_ID, :V$LEVEL_INDEX, :V$GLOBAL_INDEX, :V$IS_ADV, :V$ROW_TYPE, :V$SRC_SUBJECT_ID, :V$IS_STM)
          RETURNING OBJ_ID INTO :V$DST_ID;

          FOR
            SELECT V381.LISTVAL_ID, L.WEEKS, L.LOAD_HOURS, L.LOAD_HOURS_S1, L.LOAD_HOURS_S2, L.CONTROL_Q1, L.CONTROL_Q2,
              L.HOURS_THEORY1, L.HOURS_PR1, L.HOURS_DX1, L.HOURS_IND1, L.HOURS_MAX, L.HOURS_CR1, L.HOURS_ATT1, L.HOURS_GIA, L.HOURS_REST
            FROM PLAN_LOADS L
            JOIN VALL V381 ON V381.OBJ_ID = L.STAGE_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
            WHERE L.SUBJECT_ID = :V$ID AND L.DATE_DEL IS NULL
            INTO :V$STAGE_ID, :V$WEEKS, :V$LOAD_HOURS, :V$LOAD_HOURS_S1, :V$LOAD_HOURS_S2, :V$CONTROL_Q1, :V$CONTROL_Q2,
            :V$HOURS_THEORY1, :V$HOURS_PR1, :V$HOURS_DX1, :V$HOURS_IND1, :V$HOURS_MAX, :V$HOURS_CR1, :V$HOURS_ATT1, :V$HOURS_GIA, :V$HOURS_REST
          DO
          BEGIN
            -- STAGE_ID нужно поменять на новый - он точно есть
            V$DST_STAGE_ID = NULL;
            SELECT FIRST 1 L54.OBJ_ID
            FROM LINKS L54
            JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0 AND V381.LISTVAL_ID = :V$STAGE_ID
            WHERE L54.PARENT_ID = :OBJ_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
            INTO :V$DST_STAGE_ID;

            INSERT INTO PLAN_LOADS
            (SUBJECT_ID, STAGE_ID, WEEKS, LOAD_HOURS, LOAD_HOURS_S1, LOAD_HOURS_S2, CONTROL_Q1, CONTROL_Q2,
              HOURS_THEORY1, HOURS_PR1, HOURS_DX1, HOURS_IND1, HOURS_MAX, HOURS_CR1, HOURS_ATT1, HOURS_GIA, HOURS_REST)
            VALUES (:V$DST_ID, :V$DST_STAGE_ID, :V$WEEKS, :V$LOAD_HOURS, :V$LOAD_HOURS_S1, :V$LOAD_HOURS_S2, :V$CONTROL_Q1, :V$CONTROL_Q2,
              :V$HOURS_THEORY1, :V$HOURS_PR1, :V$HOURS_DX1, :V$HOURS_IND1, :V$HOURS_MAX, :V$HOURS_CR1, :V$HOURS_ATT1, :V$HOURS_GIA, :V$HOURS_REST);
          END

        END

      END
      ELSE IF(V$TYPE_ID = 50) THEN
      BEGIN
        -- Старый учебный план - копируем по полям, слово копия не добавляем

        -- Какой у нас уровень обучения ?
        SELECT FIRST 1 V1594.LISTVAL_ID
        FROM VALL V1594
        WHERE V1594.OBJ_ID = :I$OBJ_ID AND V1594.PARAM_ID = 1594 AND V1594.IS_DEL = 0
        INTO :V$SRC_STAGE_TYPE_ID;

        SELECT OBJ_ID FROM OBJECT_ADD(:I$OBJ_ID, 400) INTO :OBJ_ID;

        V$STR = NULL;
        SELECT V FROM VAL_GET(:I$CURRICULUM_ID, 374) WHERE IS_EXISTS = 1 INTO :V$STR;
        -- V$STR = V$STR || ' (копия)';
        SELECT BLOB_ID FROM VAL_ADD(3012, :OBJ_ID, :V$STR) INTO :V$OBJ_ID;

        V$STR = NULL;
        SELECT I FROM VAL_GET(:I$CURRICULUM_ID, 2478) WHERE IS_EXISTS = 1 INTO :V$STR;
        SELECT BLOB_ID FROM VAL_ADD(3014, :OBJ_ID, :V$STR) INTO :V$OBJ_ID;

        V$STR = NULL;
        SELECT I FROM VAL_GET(:I$CURRICULUM_ID, 2166) WHERE IS_EXISTS = 1 INTO :V$STR;
        SELECT BLOB_ID FROM VAL_ADD(3112, :OBJ_ID, :V$STR) INTO :V$OBJ_ID;

        V$STR = NULL;
        SELECT I FROM VAL_GET(:I$CURRICULUM_ID, 1759) WHERE IS_EXISTS = 1 INTO :V$STR;
        SELECT BLOB_ID FROM VAL_ADD(3015, :OBJ_ID, :V$STR) INTO :V$OBJ_ID;

        V$STR = NULL;
        SELECT I FROM VAL_GET(:I$CURRICULUM_ID, 2101) WHERE IS_EXISTS = 1 INTO :V$STR;
        SELECT BLOB_ID FROM VAL_ADD(3016, :OBJ_ID, :V$STR) INTO :V$OBJ_ID;

        V$VD = NULL;
        SELECT I FROM VAL_GET(:I$CURRICULUM_ID, 2545) WHERE IS_EXISTS = 1 INTO :V$VD;
        IF(V$VD IS NULL) THEN
        BEGIN
          -- Если у нас шаблон - выставляем "не ВД"; если существующий и не заполнено - ругаемся
          IF(EXISTS(SELECT FIRST 1 1
            FROM LINKS
            WHERE OBJ_ID = :I$CURRICULUM_ID AND PARENT_TYPE_ID = 57 AND DATE_DEL IS NULL
          )) THEN
            EXCEPTION DATA_ERROR 'Не указан принадлежность к ВД копируемого учебного плана';
          V$VD = 3;
        END
        SELECT BLOB_ID FROM VAL_ADD(3022, :OBJ_ID, :V$VD) INTO :V$OBJ_ID;

        -- Это СПО или школа ?
        V$SPO = 0;
        SELECT FIRST 1 1
        FROM LINKS L185
        WHERE L185.PARENT_ID = :I$CURRICULUM_ID AND L185.OBJ_TYPE_ID = 185 AND L185.DATE_DEL IS NULL
        INTO :V$SPO;

        -- Копируем этапы обучения для школ и максимальную учебную нагрузку в неделю 1:1 (для школ и колледжей)
        FOR
          SELECT OBJ_ID, OBJ_TYPE_ID
          FROM LINKS L
          WHERE L.PARENT_ID = :I$CURRICULUM_ID AND L.OBJ_TYPE_ID IN (54, 208) AND L.DATE_DEL IS NULL
          INTO :V$OBJ_ID, :V$_TYPE
        DO
        BEGIN
          IF (V$_TYPE = 208 OR V$SPO = 0) THEN SELECT OBJ_ID FROM OBJECT_COPY(:OBJ_ID, :V$OBJ_ID) INTO :V$DST_ID;
          -- Для началки сразу ставим 5-дневку
          IF(V$SRC_STAGE_TYPE_ID = 5339) THEN SELECT 1 FROM VAL_ADD(2837, :V$DST_ID, 11718) INTO :V$SORT_INDEX;
        END

        -- Для внеурочки копируем все в один раздел, для общеобра по разделам
        N = 0;
        LNX = 0;

        IF(V$VD = 2) THEN
        BEGIN

          -- Внеурочка

          INSERT INTO PLAN_SUBJECTS
          (PLAN_ID, SUBJECT_ID, FIELD_ID, SORT_INDEX, PARENT_ID, LEVEL_INDEX, GLOBAL_INDEX, IS_ADV, ROW_TYPE, SRC_SUBJECT_ID, IS_STM)
          VALUES (:OBJ_ID, NULL, 12927, 0, NULL, 0, :N, 0, 0, NULL, 0)
          RETURNING OBJ_ID INTO :V$DST_ID;
          N = N + 1;

          FOR
            SELECT L49.OBJ_ID, L51.OBJ_ID
            FROM LINKS L49
            JOIN LINKS L51 ON L51.PARENT_ID = L49.OBJ_ID AND L51.OBJ_TYPE_ID = 51 AND L51.DATE_DEL IS NULL
            WHERE L49.PARENT_ID = :I$CURRICULUM_ID AND L49.OBJ_TYPE_ID = 49 AND L49.DATE_DEL IS NULL
            ORDER BY L51.COST
            INTO :V$COMPONENT_ID, :V$SUBJECT_ID
          DO
          BEGIN
            UPDATE OR INSERT INTO PLAN_SUBJECTS
            (PLAN_ID, SUBJECT_ID, FIELD_ID, SORT_INDEX, PARENT_ID, LEVEL_INDEX, GLOBAL_INDEX, IS_ADV, ROW_TYPE, SRC_SUBJECT_ID, IS_STM)
            VALUES (:OBJ_ID, :V$SUBJECT_ID, NULL, :LNX, :V$DST_ID, 1, :N, 0, 10, NULL, 1)
            MATCHING (PLAN_ID, SUBJECT_ID, FIELD_ID)
            RETURNING OBJ_ID INTO :V$OBJ_ID;
            LNX = LNX + 1;
            N = N + 1;

            FOR
              SELECT V381.LISTVAL_ID, V2547.VAL, V385.VAL
              FROM LINKS L56
              JOIN LINKS LP51 ON LP51.OBJ_ID = L56.OBJ_ID AND LP51.PARENT_ID = :V$SUBJECT_ID AND LP51.DATE_DEL IS NULL
              JOIN LINKS LP54 ON LP54.OBJ_ID = L56.OBJ_ID AND LP54.PARENT_TYPE_ID = 54 AND LP54.DATE_DEL IS NULL
              JOIN LINKS LPP ON LPP.OBJ_ID = LP54.PARENT_ID AND LPP.PARENT_ID = :I$CURRICULUM_ID AND LPP.DATE_DEL IS NULL
              JOIN VALL V381 ON V381.OBJ_ID = LP54.PARENT_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
              JOIN VALI V2547 ON V2547.OBJ_ID = L56.OBJ_ID AND V2547.PARAM_ID = 2547 AND V2547.IS_DEL = 0
              JOIN VALI V385 ON V385.OBJ_ID = L56.OBJ_ID AND V385.PARAM_ID = 385 AND V385.IS_DEL = 0
              WHERE L56.PARENT_ID = :V$COMPONENT_ID AND L56.OBJ_TYPE_ID = 56 AND L56.DATE_DEL IS NULL
              INTO :V$STAGE_ID, :V$WEEKS, :V$LOAD_HOURS
            DO
            BEGIN
              -- STAGE_ID нужно поменять на новый
              V$DST_STAGE_ID = NULL;
              SELECT FIRST 1 L54.OBJ_ID
              FROM LINKS L54
              JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0 AND V381.LISTVAL_ID = :V$STAGE_ID
              WHERE L54.PARENT_ID = :OBJ_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
              INTO :V$DST_STAGE_ID;

              UPDATE OR INSERT INTO PLAN_LOADS
              (SUBJECT_ID, STAGE_ID, WEEKS, LOAD_HOURS, LOAD_HOURS_S1, LOAD_HOURS_S2, CONTROL_Q1, CONTROL_Q2)
              VALUES (:V$OBJ_ID, :V$DST_STAGE_ID, :V$WEEKS, :V$LOAD_HOURS, :V$LOAD_HOURS, 0, 5254, NULL)
              MATCHING (SUBJECT_ID, STAGE_ID);
            END
          END

        END
        ELSE IF(V$SPO = 1) THEN
        BEGIN  --Для СПО, Redmine #1064,  tree oblect types: 50-185-185
                 --                                                |
                 --                                               201 -(?)- 201
          --Копируем Нормативный срок освоения (курсов) + автоматом создаем этапы обучения для СПО, Redmine #1064 п.1
          V$ID = NULL;
          SELECT I FROM VAL_GET(:I$CURRICULUM_ID, 1760) WHERE IS_EXISTS = 1 INTO :V$ID;
          IF (V$ID > 0) THEN SELECT BLOB_ID FROM VAL_ADD(3371, :OBJ_ID, :V$ID) INTO :V$OBJ_ID;

          V$TIME_FRAME = NULL;
          --Заполним Кол-во учебных периодов (семестров) для каждого этапа
          FOR
            SELECT V381.LISTVAL_ID, V1762.VAL
            FROM LINKS L54
            JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
            LEFT JOIN VALI V1762 ON V1762.OBJ_ID = L54.OBJ_ID AND V1762.PARAM_ID = 1762 AND V1762.IS_DEL = 0
            WHERE L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL AND L54.PARENT_ID = :I$CURRICULUM_ID
            INTO :V$STAGE_ID, :V$TIME_FRAME
          DO
          BEGIN
            V$DST_ID = NULL;
            -- найдем соответсвующий этап
            SELECT L.OBJ_ID FROM LINKS L
            JOIN VALL V381 ON V381.OBJ_ID = L.OBJ_ID AND V381.PARAM_ID = 381 AND IS_DEL = 0
            WHERE OBJ_TYPE_ID = 54 AND PARENT_TYPE_ID = 400 AND DATE_DEL IS NULL AND PARENT_ID = :OBJ_ID AND V381.LISTVAL_ID = :V$STAGE_ID
            INTO :V$DST_ID;

            IF (V$DST_ID IS NOT NULL AND V$TIME_FRAME IS NOT NULL) THEN
            BEGIN
              UPDATE OR INSERT INTO VALI (OBJ_ID, PARAM_ID, VAL)
              VALUES (:V$DST_ID ,1762, :V$TIME_FRAME);
            END
          END 

          --Копируем Нормативный срок освоения (месяцев) УП, Redmine #1064 п.1
          V$ID = NULL;
          SELECT I FROM VAL_GET(:I$CURRICULUM_ID, 1761) WHERE IS_EXISTS = 1 INTO :V$ID;
          SELECT BLOB_ID FROM VAL_ADD(3352, :OBJ_ID, :V$ID) INTO :V$OBJ_ID;

          -- В СПО еще одна подчиненная сущность в этапах - Продолжительность (недель) (#209) - копируем, Redmine #1064 п.1
          FOR
            SELECT L209.OBJ_ID, V381.LISTVAL_ID
            FROM LINKS L209
            JOIN LINKS L54 ON L54.OBJ_ID = L209.PARENT_ID AND L54.DATE_DEL IS NULL AND L54.OBJ_TYPE_ID = 54
            JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND IS_DEL = 0
            WHERE L209.OBJ_TYPE_ID = 209 AND L209.DATE_DEL IS NULL AND L54.PARENT_ID = :I$CURRICULUM_ID
            INTO :V$SUBJECT_ID, :V$STAGE_ID
          DO
          BEGIN
            V$DST_ID = NULL;
            -- найдем соответсвующий этап
            SELECT L.OBJ_ID
            FROM LINKS L
            JOIN VALL V381 ON V381.OBJ_ID = L.OBJ_ID AND V381.PARAM_ID = 381 AND IS_DEL = 0
            WHERE L.OBJ_TYPE_ID = 54 AND L.PARENT_TYPE_ID = 400 AND L.DATE_DEL IS NULL AND L.PARENT_ID = :OBJ_ID AND V381.LISTVAL_ID = :V$STAGE_ID
            INTO :V$DST_ID;
            -- копируем продолжительность (недель) (#209)
            IF (V$DST_ID IS NOT NULL) THEN
            BEGIN
              SELECT 1 FROM OBJECT_COPY(:V$DST_ID, :V$SUBJECT_ID) INTO :V$SORT_INDEX;
            END
          END

          --МКД учебного плана
          FOR
            SELECT TR.LEVEL_NUM, TR.OBJ_ID, TR.TYPE_ID, L_V1608.LISTVAL_ID, V1766.VAL, V1765.VAL
            FROM DISCIPLINE_TREE(:I$CURRICULUM_ID) TR
            LEFT JOIN VALS V1765 ON V1765.OBJ_ID = TR.OBJ_ID AND V1765.PARAM_ID = 1765 AND V1765.IS_DEL IS NOT NULL AND TR.TYPE_ID = 201
            LEFT JOIN VALR V1766 ON V1766.OBJ_ID = TR.OBJ_ID AND V1766.PARAM_ID = 1766 AND V1766.IS_DEL IS NOT NULL AND TR.TYPE_ID = 201
            LEFT JOIN VALL L_V1608 ON L_V1608.OBJ_ID = TR.OBJ_ID AND L_V1608.IS_DEL = 0 AND TR.TYPE_ID = 185
            WHERE LEVEL_NUM <= 3
            INTO :V$LEVEL, :V$_ID, :V$_TYPE, :V$_FIELD, :V$_SUBJ, :V$SUBJ_CODE
          DO
          BEGIN
            IF(V$LEVEL = 0) THEN V$_PARENT = NULL;
            ELSE IF(V$LEVEL = 1) THEN V$_PARENT = V$PARENT0;
            ELSE IF(V$LEVEL = 2) THEN V$_PARENT = V$PARENT1;
            ELSE V$_PARENT = V$PARENT2;

            SELECT SUBJECT_OBJ_ID, IND, PARENT0, PARENT1
            FROM NEW_SPO_PLAN_SUBJECT(:OBJ_ID, :V$_TYPE, :V$_SUBJ, :V$_FIELD, :N, :V$_PARENT, :V$LEVEL, :V$PARENT0, :V$PARENT1, :V$PARENT2, :V$SUBJ_CODE)
            INTO :V$SUBJ_ID, :N, :V$PARENT0, :V$PARENT1;

            IF (V$_TYPE = 201) THEN
            BEGIN
              EXECUTE PROCEDURE NEW_SPO_CURRICULUM_ADD_LOADS(:V$_ID, :V$SUBJ_ID, :V$_SUBJ, :OBJ_ID, :I$CURRICULUM_ID);
            END
          END
        END
        ELSE
        BEGIN
          -- Общеобразовательные УП

          -- Элективные предметы должны по списку следовать после обычных
          V$SRC_COMPONENT_ID = -1;

          FOR
            SELECT L49.OBJ_ID, V372.LISTVAL_ID, L51.OBJ_ID
            FROM LINKS L49
            JOIN VALL V372 ON V372.OBJ_ID = L49.OBJ_ID AND V372.PARAM_ID = 372 AND V372.IS_DEL = 0
            JOIN LINKS L51 ON L51.PARENT_ID = L49.OBJ_ID AND L51.OBJ_TYPE_ID = 51 AND L51.DATE_DEL IS NULL
            LEFT JOIN VALL V2816 ON V2816.OBJ_ID = L51.OBJ_ID AND V2816.PARAM_ID = 2816 AND V2816.IS_DEL = 0
            WHERE L49.PARENT_ID = :I$CURRICULUM_ID AND L49.OBJ_TYPE_ID = 49 AND L49.DATE_DEL IS NULL
            ORDER BY 2, IIF(V2816.LISTVAL_ID = 2, L51.COST + 1E15, L51.COST)
            INTO :V$COMPONENT_ID, :V$PARAM_ID, :V$SUBJECT_ID
          DO
          BEGIN

            -- Отдельная история для элективных курсов - под них предусмотрен отдельный раздел
            IF(V$COMPONENT_ID <> V$SRC_COMPONENT_ID OR V$SUBJECT_ID = 34607) THEN
            BEGIN
              INSERT INTO PLAN_SUBJECTS
              (PLAN_ID, SUBJECT_ID, FIELD_ID, SORT_INDEX, PARENT_ID, LEVEL_INDEX, GLOBAL_INDEX, IS_ADV, ROW_TYPE, SRC_SUBJECT_ID, IS_STM)
              VALUES (:OBJ_ID, NULL, IIF(:V$PARAM_ID IN (780, 12752), 13303, IIF(:V$SUBJECT_ID = 34607, 12928, 13304)), 0, NULL, 0, :N, 0, 0, NULL, 0)
              RETURNING OBJ_ID INTO :V$DST_ID;
              N = N + 1;
              LNX = 0;
              V$SRC_COMPONENT_ID = V$COMPONENT_ID;
            END

            -- Замена на эталонный предмет ?
            V$SRC_SUBJECT_ID = NULL;
            IF (V$PARAM_ID IN (780, 12752)) THEN
            BEGIN
              SELECT FIRST 1 V2718.VAL
              FROM LINKS L349
              JOIN VALR V2719 ON V2719.OBJ_ID = L349.OBJ_ID AND V2719.PARAM_ID = 2719 AND V2719.IS_DEL = 0 AND V2719.VAL = :V$SUBJECT_ID
              JOIN VALR V2718 ON V2718.OBJ_ID = L349.OBJ_ID AND V2718.PARAM_ID = 2718 AND V2718.IS_DEL = 0
              WHERE L349.PARENT_ID = :V$COMPONENT_ID AND L349.OBJ_TYPE_ID = 349 AND L349.DATE_DEL IS NULL
              INTO :V$SRC_SUBJECT_ID;
            END

            V$FIELD_ID = NULL;
            SELECT FIRST 1 V2462.LISTVAL_ID
            FROM LINKS L302
            JOIN VALL V2462 ON V2462.OBJ_ID = L302.OBJ_ID AND V2462.PARAM_ID = 2462 AND V2462.IS_DEL = 0
            WHERE L302.PARENT_ID = :V$SUBJECT_ID AND L302.OBJ_TYPE_ID = 302 AND L302.DATE_DEL IS NULL
            AND (
              ((:V$SRC_STAGE_TYPE_ID = 5339) AND (V2462.LISTVAL_ID IN (12740, 11680, 11682, 11685, 11686, 11689, 11693, 11694, 11695))) OR
              ((:V$SRC_STAGE_TYPE_ID = 5341) AND (V2462.LISTVAL_ID IN (11684, 11681, 11683, 11685, 11687, 11690, 11691, 11693, 11694, 11696))) OR
              ((:V$SRC_STAGE_TYPE_ID = 5343) AND (:V$IS_FOP = 0) AND (V2462.LISTVAL_ID IN (11684, 11681, 11683, 11685, 11688, 11690, 11692, 11693, 11694, 11696, 11697))) OR
              ((:V$SRC_STAGE_TYPE_ID = 5343) AND (:V$IS_FOP = 1) AND (V2462.LISTVAL_ID IN (11684, 11681, 11683, 11685, 11687, 11690, 11691, 11693, 11694, 11696, 11697)))
            )
            INTO :V$FIELD_ID;

            UPDATE OR INSERT INTO PLAN_SUBJECTS
            (PLAN_ID, SUBJECT_ID, FIELD_ID, SORT_INDEX, PARENT_ID, LEVEL_INDEX, GLOBAL_INDEX, IS_ADV, ROW_TYPE, SRC_SUBJECT_ID, IS_STM)
            VALUES (:OBJ_ID, :V$SUBJECT_ID, :V$FIELD_ID, :LNX, :V$DST_ID, 1, :N, 0, 10, :V$SRC_SUBJECT_ID, 0)
            MATCHING (PLAN_ID, SUBJECT_ID, FIELD_ID, PARENT_ID)
            RETURNING OBJ_ID INTO :V$OBJ_ID;
            LNX = LNX + 1;
            N = N + 1;

            FOR
              SELECT V381.LISTVAL_ID, V2547.VAL, V385.VAL
              FROM LINKS L56
              JOIN LINKS LP51 ON LP51.OBJ_ID = L56.OBJ_ID AND LP51.PARENT_ID = :V$SUBJECT_ID AND LP51.DATE_DEL IS NULL
              JOIN LINKS LP54 ON LP54.OBJ_ID = L56.OBJ_ID AND LP54.PARENT_TYPE_ID = 54 AND LP54.DATE_DEL IS NULL
              JOIN LINKS LPP ON LPP.OBJ_ID = LP54.PARENT_ID AND LPP.PARENT_ID = :I$CURRICULUM_ID AND LPP.DATE_DEL IS NULL
              JOIN VALL V381 ON V381.OBJ_ID = LP54.PARENT_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
              JOIN VALI V2547 ON V2547.OBJ_ID = L56.OBJ_ID AND V2547.PARAM_ID = 2547 AND V2547.IS_DEL = 0
              JOIN VALI V385 ON V385.OBJ_ID = L56.OBJ_ID AND V385.PARAM_ID = 385 AND V385.IS_DEL = 0
              WHERE L56.PARENT_ID = :V$COMPONENT_ID AND L56.OBJ_TYPE_ID = 56 AND L56.DATE_DEL IS NULL
              INTO :V$STAGE_ID, :V$WEEKS, :V$LOAD_HOURS
            DO
            BEGIN
              -- STAGE_ID нужно поменять на новый
              V$DST_STAGE_ID = NULL;
              SELECT FIRST 1 L54.OBJ_ID
              FROM LINKS L54
              JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0 AND V381.LISTVAL_ID = :V$STAGE_ID
              WHERE L54.PARENT_ID = :OBJ_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
              INTO :V$DST_STAGE_ID;

              UPDATE OR INSERT INTO PLAN_LOADS
              (SUBJECT_ID, STAGE_ID, WEEKS, LOAD_HOURS, LOAD_HOURS_S1, LOAD_HOURS_S2, CONTROL_Q1, CONTROL_Q2)
              VALUES (:V$OBJ_ID, :V$DST_STAGE_ID, :V$WEEKS, :V$LOAD_HOURS, :V$LOAD_HOURS, 0, 5254, NULL)
              MATCHING (SUBJECT_ID, STAGE_ID);
            END

          END

        END

      END

    END

  END

  SUSPEND;

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_CURRICULUM_LIST (
    COPY_MODE SMALLINT = 0,
    I$PARENT_TYPE_ID BIGINT = 57,
    I$PARENT_ID BIGINT = NULL)
RETURNS (
    OBJ_ID BIGINT,
    OBJ_CAPTION VARCHAR(4000),
    LEVEL_ID BIGINT)
AS
DECLARE VARIABLE V$OU_LICENCE_TYPE VARCHAR(1);
DECLARE VARIABLE V$FOLDER_ID BIGINT;
DECLARE VARIABLE V$LEVEL_ID BIGINT;
DECLARE VARIABLE V$ALLOWED SMALLINT;
DECLARE VARIABLE V$LEVEL_ID_FLT BIGINT;
DECLARE VARIABLE V$ADAPT BIGINT;
DECLARE VARIABLE V$PLAN_ADAPT BIGINT;
BEGIN

    -- Получаем ID уровня образования
    IF(I$PARENT_ID IS NOT NULL) THEN
    BEGIN
      SELECT V1594.LISTVAL_ID, COALESCE(V2379.LISTVAL_ID, 11187)
      FROM OBJECTS P
      LEFT JOIN VALL V1594 ON V1594.OBJ_ID = P.OBJ_ID AND V1594.IS_DEL = 0 AND V1594.PARAM_ID IN (1594, 2132, 2146)
      LEFT JOIN VALL V2379 ON V2379.OBJ_ID = P.OBJ_ID AND V2379.IS_DEL = 0 AND V2379.PARAM_ID = 2379
      WHERE P.OBJ_ID = :I$PARENT_ID
      INTO :V$LEVEL_ID, :V$ADAPT;
    END

    IF (COPY_MODE IN (1, 101)) THEN
    BEGIN
        -- Это список имеющихся УП для копирования
        -- с типом 101 добавляем в выбор учебные планы нового образца
        FOR
          SELECT L50.OBJ_ID, V1594.LISTVAL_ID
          FROM LINKS L2
          JOIN LINKS L69 ON L69.PARENT_ID = L2.OBJ_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL
          JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = :I$PARENT_TYPE_ID AND L57.DATE_DEL IS NULL
          JOIN LINKS L50 ON L50.PARENT_ID = L57.OBJ_ID AND (L50.OBJ_TYPE_ID IN (50, 245) OR (:COPY_MODE = 101 AND L50.OBJ_TYPE_ID = 400)) AND L50.DATE_DEL IS NULL
          LEFT JOIN VALL V1594 ON V1594.OBJ_ID = L57.OBJ_ID AND V1594.IS_DEL = 0 AND V1594.PARAM_ID IN (1594, 2132, 2146)
          WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
          UNION ALL
          SELECT L50.OBJ_ID, V2146.LISTVAL_ID
          FROM LINKS L2
          JOIN LINKS L211 ON L211.PARENT_ID = L2.OBJ_ID AND L211.OBJ_TYPE_ID = 211 AND L211.DATE_DEL IS NULL
          JOIN LINKS L252 ON L252.PARENT_ID = L211.OBJ_ID AND L252.OBJ_TYPE_ID = :I$PARENT_TYPE_ID AND L252.DATE_DEL IS NULL
          JOIN LINKS L50 ON L50.PARENT_ID = L252.OBJ_ID AND (L50.OBJ_TYPE_ID IN (50, 245) OR (:COPY_MODE = 101 AND L50.OBJ_TYPE_ID = 400)) AND L50.DATE_DEL IS NULL
          LEFT JOIN VALL V2146 ON V2146.OBJ_ID = L252.OBJ_ID AND V2146.IS_DEL = 0 AND V2146.PARAM_ID = 2146
          WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
          INTO :OBJ_ID, :LEVEL_ID
        DO
        BEGIN
          V$ALLOWED = 1;

          IF(V$LEVEL_ID IS NOT NULL AND LEVEL_ID IS NOT NULL) THEN
          BEGIN
            IF(LEVEL_ID <> V$LEVEL_ID) THEN V$ALLOWED = 0;
          END

          IF(V$ALLOWED = 1) THEN
          BEGIN
            SELECT CAPTION FROM OBJECT_CAPTION_GET(:OBJ_ID, NULL) INTO :OBJ_CAPTION;
            SUSPEND;
          END
        END
    END
    ELSE
    BEGIN
        SELECT STATUS FROM OU_LICENCE_TYPE INTO :V$OU_LICENCE_TYPE;
        IF (V$OU_LICENCE_TYPE = 'O') THEN V$FOLDER_ID = 258;
        ELSE IF (V$OU_LICENCE_TYPE = 'C') THEN V$FOLDER_ID = 14298;
        ELSE IF (V$OU_LICENCE_TYPE = 'U') THEN V$FOLDER_ID = 20629;
        ELSE IF (V$OU_LICENCE_TYPE = 'S') THEN
        BEGIN
          -- Выбираем по типу ОП, дофильтровываем по конкретному уровню
          IF(V$LEVEL_ID IN (5337, 5339, 5341, 5343, 13272)) THEN BEGIN V$FOLDER_ID = 258; V$LEVEL_ID_FLT = V$LEVEL_ID; END -- ОО
          ELSE IF(V$LEVEL_ID IN (5346)) THEN V$FOLDER_ID = 14298; -- СПО
          ELSE IF(V$LEVEL_ID IN (5357)) THEN V$FOLDER_ID = 14298; -- ДО
        END

        -- Это список шаблонных УП
        -- Убираем шаблоны ФГОС для началки
        FOR
          SELECT L.OBJ_ID, V3345.LISTVAL_ID, C.CAPTION, V3014.LISTVAL_ID
          FROM LINKS L
          LEFT JOIN VALL V3345 ON V3345.OBJ_ID = L.OBJ_ID AND V3345.PARAM_ID = 3345 AND V3345.IS_DEL = 0
          LEFT JOIN VALL V3014 ON V3014.OBJ_ID = L.OBJ_ID AND V3014.PARAM_ID = 3014 AND V3014.IS_DEL = 0
          LEFT JOIN OBJECT_CAPTION_GET(L.OBJ_ID) C ON 1 = 1
          WHERE L.PARENT_ID = :V$FOLDER_ID AND L.OBJ_TYPE_ID = IIF(:I$PARENT_TYPE_ID = 244, 245, 400)
            AND L.DATE_DEL IS NULL AND L.OBJ_ID NOT IN (34238, 34325, 34641, 34642, 3178, 38171, 38214, 34111, 38653, 38654)
            -- фильтр по адаптированности
            AND (
              -- для АООП может быть только стандарт АООП
              (:V$LEVEL_ID = 13272 AND V3014.LISTVAL_ID = 13273) OR
              -- для АОП можно любой из стандартав АОП
              (COALESCE(:V$ADAPT, 0) <> 11187 AND :V$LEVEL_ID <> 13272 AND V3014.LISTVAL_ID IN (13288, 14186)) OR
              -- неадаптированная, стандарт только из неадаптированных
              (:V$ADAPT = 11187 AND COALESCE(V3014.LISTVAL_ID, 0) NOT IN (13273, 13288, 14186))
            )
          ORDER BY 2, 3
          INTO :OBJ_ID, :LEVEL_ID, :OBJ_CAPTION, :V$PLAN_ADAPT
        DO
        BEGIN
          V$ALLOWED = 1;

          IF(V$LEVEL_ID IS NOT NULL AND LEVEL_ID IS NOT NULL) THEN
          BEGIN
            IF(LEVEL_ID <> V$LEVEL_ID) THEN V$ALLOWED = 0;
          END

          IF(V$LEVEL_ID_FLT IS NOT NULL AND LEVEL_ID IS NOT NULL) THEN
          BEGIN
            IF(V$LEVEL_ID_FLT <> LEVEL_ID) THEN V$ALLOWED = 0;
          END

          IF(OBJ_ID IN (38629, 169, 38634, 38635, 38646)) THEN V$ALLOWED = 0;

          IF(V$ALLOWED = 1) THEN SUSPEND;
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_EDUCATION_FLEVELS_LIST (
    I$PUPIL_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    COLOR INTEGER,
    OBJ_CAPTION VARCHAR(4000))
AS
declare variable V$SORT_ORDER double precision;
declare variable V$EDUCATION_LEVEL_ID bigint;
declare variable V$EDUCATION_LEVEL_ID2 bigint;
declare variable V$LEVEL bigint;
declare variable V$LEVEL2 bigint;
declare variable V$IS_LAST smallint;
declare variable V$IS_FIRST smallint;
declare variable V$EDUCATION_LINE_ID bigint;
declare variable V$EDUCATION_LINE_ID2 bigint;
declare variable V$LEVEL_LINE bigint;
declare variable V$LEVEL_LINE2 bigint;
declare variable V$IS_FIRST_LINE smallint;
declare variable V$IS_LAST_LINE smallint;
BEGIN
    V$EDUCATION_LEVEL_ID = 0;
    FOR
        SELECT FIRST 1
               OBJ_ID
        FROM OBJECT_PARENTS_GET(:I$PUPIL_ID,7)
        INTO   :V$EDUCATION_LEVEL_ID
    DO
    BEGIN
        SELECT I,SORT_ORDER
        FROM VAL_GET(:V$EDUCATION_LEVEL_ID, 43, 0, :I$USER_ID)
        INTO   :V$LEVEL,:V$SORT_ORDER;

        SELECT FIRST 1
               EDUCATION_LEVEL_ID,
               LEVEL_ID
        FROM PARAGRAF_EDUCATION_LEVELS_LIST(:I$PUPIL_ID, :I$USER_ID)
        ORDER BY SORT_ORDER
        INTO   :V$EDUCATION_LEVEL_ID2,
               :V$LEVEL2;
        V$IS_FIRST = 0;
        IF ((V$EDUCATION_LEVEL_ID2 = V$EDUCATION_LEVEL_ID) AND (V$LEVEL2 = V$LEVEL)) THEN
        BEGIN
            V$IS_FIRST = 1;
        END

        SELECT FIRST 1
               EDUCATION_LEVEL_ID,
               LEVEL_ID
        FROM PARAGRAF_EDUCATION_LEVELS_LIST(:I$PUPIL_ID, :I$USER_ID)
        ORDER BY SORT_ORDER DESC
        INTO   :V$EDUCATION_LEVEL_ID2,
               :V$LEVEL2;
        V$IS_LAST = 0;
        IF ((V$EDUCATION_LEVEL_ID2 = V$EDUCATION_LEVEL_ID) AND (V$LEVEL2 = V$LEVEL)) THEN
        BEGIN
            V$IS_LAST = 1;
        END

        V$EDUCATION_LINE_ID = 0;
        FOR
            SELECT FIRST 1
                   OBJ_ID
            FROM OBJECT_PARENTS_GET(:I$PUPIL_ID,8)
            INTO   :V$EDUCATION_LINE_ID
        DO
        BEGIN
            SELECT I
            FROM VAL_GET(:V$EDUCATION_LINE_ID, 49, 0, :I$USER_ID)
            INTO   :V$LEVEL_LINE;
            SELECT FIRST 1
                   EDUCATION_LINE_ID,
                   LINE_ID
            FROM PARAGRAF_EDUCATION_LINES_LIST(:V$EDUCATION_LEVEL_ID, :I$USER_ID)
            ORDER BY SORT_ORDER
            INTO   :V$EDUCATION_LINE_ID2,
                   :V$LEVEL_LINE2;
            V$IS_FIRST_LINE = 0;
            IF ((V$EDUCATION_LINE_ID2 = V$EDUCATION_LINE_ID) AND (V$LEVEL_LINE2 = V$LEVEL_LINE)) THEN
            BEGIN
                V$IS_FIRST_LINE = 1;
            END
            SELECT FIRST 1
                   EDUCATION_LINE_ID,
                   LINE_ID
            FROM PARAGRAF_EDUCATION_LINES_LIST(:V$EDUCATION_LEVEL_ID, :I$USER_ID)
            ORDER BY SORT_ORDER DESC
            INTO   :V$EDUCATION_LINE_ID2,
                   :V$LEVEL_LINE2;
            V$IS_LAST_LINE = 0;
            IF ((V$EDUCATION_LINE_ID2 = V$EDUCATION_LINE_ID) AND (V$LEVEL_LINE2 = V$LEVEL_LINE)) THEN
            BEGIN
                V$IS_LAST_LINE = 1;
            END
            IF (V$IS_FIRST = 0 AND V$IS_FIRST_LINE = 1) THEN
            BEGIN
                FOR
                    SELECT FIRST 1
                           L.EDUCATION_LEVEL_ID,
                           T.COLOR
                    FROM PARAGRAF_EDUCATION_LEVELS_LIST(:I$PUPIL_ID, :I$USER_ID) L
                    JOIN OBJECTS O
                    ON O.OBJ_ID = L.EDUCATION_LEVEL_ID
                    JOIN TYPES T
                    ON T.TYPE_ID = O.TYPE_ID
                    WHERE L.SORT_ORDER < :V$SORT_ORDER
                    ORDER BY L.SORT_ORDER DESC
                    INTO :OBJ_ID,
                         :COLOR
                DO
                BEGIN
                    SELECT CAPTION
                    FROM OBJECT_CAPTION_GET(:OBJ_ID)
                    INTO :OBJ_CAPTION;
                    SUSPEND;
                END
            END
            ELSE IF (V$IS_LAST = 0 AND V$IS_LAST_LINE = 1) THEN
            BEGIN
                OBJ_ID = V$EDUCATION_LEVEL_ID;
                SELECT L.CAPTION,
                       T.COLOR
                FROM OBJECT_CAPTION_GET(:OBJ_ID) L
                JOIN OBJECTS O
                ON O.OBJ_ID = :OBJ_ID
                JOIN TYPES T
                ON T.TYPE_ID = O.TYPE_ID
                INTO :OBJ_CAPTION,
                     :COLOR;
                SUSPEND;
            END
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_EDUCATION_LEAVE (
    I$PUPIL_ID BIGINT,
    I$ACTION_DATE DATE,
    I$ACTION_TYPE BIGINT,
    I$ORDER_NUMBER VARCHAR(100),
    I$ORDER_DATE DATE,
    I$LEAVE_FOR BIGINT,
    I$HAVE_DOC BIGINT,
    I$LEAVE_TO BIGINT,
    I$LEAVE_TO_OU_TYPE BIGINT,
    I$LEAVE_TO_OU_NAME VARCHAR(4000),
    I$LEAVE_TO_DISTR BIGINT,
    I$LEAVE_TO_CLASS BIGINT,
    I$USER_ID VARCHAR(40),
    I$MOVEMENT_SOURCE_ID BIGINT = 902,
    I$CLASS_ID BIGINT = NULL,
    I$ACCEPT_DATE DATE = NULL,
    I$ACCEPT_ORDER VARCHAR(100) = NULL)
AS
DECLARE VARIABLE V$OU_LICENCE_TYPE VARCHAR(1);
DECLARE VARIABLE V$YC SMALLINT;
DECLARE VARIABLE V$BLOB_ID BIGINT;
DECLARE VARIABLE V$G_TYPE BIGINT;
DECLARE VARIABLE V$G_ID BIGINT;
DECLARE VARIABLE V$DATE DATE;
DECLARE VARIABLE V$LEAVE_TO_OU_TYPE BIGINT;
DECLARE VARIABLE V$PREV_LEVEL BIGINT;
DECLARE VARIABLE T INTEGER;
BEGIN

    -- Тут три варианта выбытия: либо чистое выбытие или окончание
    -- либо в СПО академический отпуск или отчисление из академического отпуска совсем

    -- Если это не выбытие/окончание - вообще ничего не делаем
    IF(NOT EXISTS(
      SELECT FIRST 1 1
      FROM LISTVALS
      WHERE LISTVAL_ID = :I$ACTION_TYPE AND (("FILTER" LIKE '%LEAVED%') OR ("FILTER" LIKE '%FINISHED%'))
    )) THEN
    BEGIN
      EXIT;
    END

    V$YC = 0;
    IF(SUBSTRING(I$USER_ID FROM 1 FOR 1) = '@') THEN
    BEGIN
      I$USER_ID = SUBSTRING(I$USER_ID FROM 2);
      V$YC = 1;
    END
    IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

    SELECT STATUS FROM OU_LICENCE_TYPE INTO :V$OU_LICENCE_TYPE;

    -- УДОД - если не указана группа, выбываем изо всех
    IF (V$OU_LICENCE_TYPE = 'U' AND I$CLASS_ID IS NULL) THEN
    BEGIN
      FOR
        SELECT PARENT_ID
        FROM LINKS
        WHERE OBJ_ID = :I$PUPIL_ID AND PARENT_TYPE_ID = 243 AND DATE_DEL IS NULL
        ORDER BY LINK_ID
        INTO :I$CLASS_ID
      DO
      BEGIN
        EXECUTE PROCEDURE PARAGRAF_EDUCATION_LEAVE(:I$PUPIL_ID, :I$ACTION_DATE,
          :I$ACTION_TYPE, :I$ORDER_NUMBER, :I$ORDER_DATE, :I$LEAVE_FOR, :I$HAVE_DOC,
          :I$LEAVE_TO, :I$LEAVE_TO_OU_TYPE, :I$LEAVE_TO_OU_NAME, :I$LEAVE_TO_DISTR,
          :I$LEAVE_TO_CLASS, IIF(:V$YC = 0, '', '@') || :I$USER_ID, :I$MOVEMENT_SOURCE_ID, :I$CLASS_ID,
          :I$ACCEPT_DATE, :I$ACCEPT_ORDER);
      END
      EXIT;
    END

    -- Запрещаем выбытие если есть регид и не устранены замечания
    IF(EXISTS(
      SELECT FIRST 1 1
      FROM VALS V
      JOIN SYNC_LOG L ON L.PERSON_ID = V.OBJ_ID AND L.MSG IS NOT NULL AND L.MSG <> '' AND L.MSG <> 'null'
      WHERE V.OBJ_ID = :I$PUPIL_ID AND V.PARAM_ID = 2912 AND V.IS_DEL = 0
    ))
    THEN
      EXCEPTION DATA_ERROR 'По обучающемуся зафиксированы ошибки или конфликт по персональным данным, смотри отчет по синхронизации РК. ' ||
        'Ошибки должны быть устранены до отчисления';

    IF(EXISTS(
      SELECT FIRST 1 1
      FROM LIB2_USAGE U
      WHERE U.DATE_DEL IS NULL AND U.REF_TYPE_ID = 10 AND U.RETURN_DATE IS NULL AND U.LOSS_DATE IS NULL AND U.REF_ID = :I$PUPIL_ID
    ))
    THEN
      EXCEPTION DATA_ERROR 'За обучающимся числится не возвращенная литература';

    -- Выставляем дату окончания ДО и снимаем флаг ДО. Тут фиксируем только дату выбытия без прочих реквизитов
    SELECT BLOB_ID FROM VAL_ADD(2992, :I$PUPIL_ID, 3) INTO :V$BLOB_ID;

    V$BLOB_ID = NULL;
    SELECT FIRST 1 M.OBJ_ID, M.DATE_IN
    FROM PERSON_MOVEMENTS M
    JOIN OBJECTS OBJ ON OBJ.OBJ_ID = M.GROUP_ID AND OBJ.TYPE_ID = 338
    WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :I$PUPIL_ID AND M.DATE_OUT IS NULL
    INTO :V$BLOB_ID, :V$DATE;

    IF(V$BLOB_ID IS NOT NULL) THEN
    BEGIN
      IF(V$DATE > I$ACTION_DATE) THEN EXCEPTION DATA_ERROR 'Дата начала дистанционного обучения позднее даты выбытия';
      UPDATE PERSON_MOVEMENTS
      SET DATE_OUT = :I$ACTION_DATE, USER_OUT = :I$USER_ID
      WHERE OBJ_ID = :V$BLOB_ID;
    END

    -- Фиксируем выбытие ученика из классов (конкретного класса) и академического отпуска
    -- только для СПО
    SELECT FIRST 1 LP7.PARENT_ID
    FROM LINKS LP9
    JOIN LINKS LP8 ON LP8.OBJ_ID = LP9.PARENT_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
    JOIN LINKS LP7 ON LP7.OBJ_ID = LP8.PARENT_ID AND LP7.PARENT_TYPE_ID = 7 AND LP7.DATE_DEL IS NULL
    WHERE LP9.OBJ_ID = :I$PUPIL_ID AND LP9.PARENT_TYPE_ID = 9 AND LP9.DATE_DEL IS NULL AND ((:I$CLASS_ID IS NULL) OR (LP9.PARENT_ID = :I$CLASS_ID))
    INTO :V$PREV_LEVEL;

    FOR
      SELECT LPG.PARENT_TYPE_ID, LPG.PARENT_ID
      FROM LINKS LPG
      WHERE LPG.OBJ_ID = :I$PUPIL_ID AND LPG.PARENT_TYPE_ID IN (9, 187, 289, 243) AND LPG.DATE_DEL IS NULL AND ((:I$CLASS_ID IS NULL) OR (LPG.PARENT_ID = :I$CLASS_ID))
      INTO :V$G_TYPE, :V$G_ID
    DO
    BEGIN
      SELECT OBJ_ID FROM VARGRP_MOVE_PUPIL(:I$PUPIL_ID, :V$G_ID, :I$ORDER_NUMBER, :I$ORDER_DATE, :I$ACTION_DATE, 1, IIF(:V$YC = 0, '', '@') || :I$USER_ID, NULL,
        :I$ACTION_TYPE, :I$MOVEMENT_SOURCE_ID) INTO :V$BLOB_ID;
    END

    -- Если выбытие в академический отпуск - фиксируем как зачисление, причем с номером курса и уровнем обучения тем который был последним
    IF(I$ACTION_TYPE = 5319) THEN
    BEGIN
      -- Ищем папку академического отпуска в том же уровне, где была группа где он ранее учился
      IF(V$PREV_LEVEL IS NULL) THEN EXCEPTION DATA_ERROR 'Не удалось определить раздел Академического отпуска';

      V$G_ID = NULL;
      SELECT FIRST 1 L289.OBJ_ID
      FROM LINKS L289
      WHERE L289.PARENT_ID = :V$PREV_LEVEL AND L289.OBJ_TYPE_ID = 289 AND L289.DATE_DEL IS NULL
      INTO :V$G_ID;

      IF(V$G_ID IS NULL) THEN
      BEGIN
        SELECT OBJ_ID FROM OBJECT_ADD(:V$PREV_LEVEL, 289) INTO :V$G_ID;
        SELECT 1 FROM VAL_ADD(2342, :V$G_ID, (SELECT VAL FROM RES_GET((SELECT RES_ID FROM TYPES WHERE TYPE_ID = 289), 'BY'))) INTO :T;
      END

      SELECT OBJ_ID FROM VARGRP_MOVE_PUPIL(:I$PUPIL_ID, :V$G_ID, :I$ORDER_NUMBER, :I$ORDER_DATE, :I$ACTION_DATE, 0, IIF(:V$YC = 0, '', '@') || :I$USER_ID, NULL,
        :I$ACTION_TYPE, :I$MOVEMENT_SOURCE_ID) INTO :V$BLOB_ID;
    END

    IF (I$LEAVE_FOR IS NOT NULL) THEN
    BEGIN
      SELECT BLOB_ID FROM VAL_ADD(105, :I$PUPIL_ID, :I$LEAVE_FOR, :I$USER_ID) INTO :V$BLOB_ID;
    END

    IF (I$HAVE_DOC IS NOT NULL) THEN
    BEGIN
      SELECT BLOB_ID FROM VAL_ADD(106, :I$PUPIL_ID, :I$HAVE_DOC, :I$USER_ID) INTO :V$BLOB_ID;
    END

    IF (I$LEAVE_TO IS NOT NULL) THEN
    BEGIN
      SELECT BLOB_ID FROM VAL_ADD(107, :I$PUPIL_ID, :I$LEAVE_TO, :I$USER_ID) INTO :V$BLOB_ID;
    END

    IF (I$LEAVE_TO_OU_TYPE IS NOT NULL) THEN
    BEGIN
      -- Перекодируем справочник 258 в справочник 4
      SELECT FIRST 1 LV4.LISTVAL_ID
      FROM LISTVALS LV258
      JOIN LISTVALS LV4 ON LV4.LIST_ID = 4 AND LV4.TAG = LV258.TAG
      WHERE LV258.LIST_ID = 258 AND LV258.LISTVAL_ID = :I$LEAVE_TO_OU_TYPE
      INTO :V$LEAVE_TO_OU_TYPE;

      IF(V$LEAVE_TO_OU_TYPE IS NOT NULL) THEN I$LEAVE_TO_OU_TYPE = V$LEAVE_TO_OU_TYPE;

      SELECT BLOB_ID FROM VAL_ADD(188, :I$PUPIL_ID, :I$LEAVE_TO_OU_TYPE, :I$USER_ID) INTO :V$BLOB_ID;
    END

    IF (I$LEAVE_TO_OU_NAME IS NOT NULL) THEN
    BEGIN
      IF (V$OU_LICENCE_TYPE = 'D') THEN
      BEGIN
        SELECT BLOB_ID FROM VAL_ADD(1555, :I$PUPIL_ID, :I$LEAVE_TO_OU_NAME, :I$USER_ID) INTO :V$BLOB_ID;
      END
      ELSE
      BEGIN
        SELECT BLOB_ID FROM VAL_ADD(161, :I$PUPIL_ID, :I$LEAVE_TO_OU_NAME, :I$USER_ID) INTO :V$BLOB_ID;
      END
    END

    IF (I$ACCEPT_DATE IS NOT NULL) THEN
    BEGIN
      SELECT BLOB_ID FROM VAL_ADD(2442, :I$PUPIL_ID, :I$ACCEPT_DATE, :I$USER_ID) INTO :V$BLOB_ID;
    END

    IF (I$ACCEPT_ORDER IS NOT NULL) THEN
    BEGIN
      SELECT BLOB_ID FROM VAL_ADD(2443, :I$PUPIL_ID, :I$ACCEPT_ORDER, :I$USER_ID) INTO :V$BLOB_ID;
    END

    IF (I$LEAVE_TO_DISTR IS NOT NULL) THEN
    BEGIN
      SELECT BLOB_ID FROM VAL_ADD(1346, :I$PUPIL_ID, :I$LEAVE_TO_DISTR, :I$USER_ID) INTO :V$BLOB_ID;
    END

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_EDUCATION_LEAVE_CHECK (
    I$MOVEMENT_ID BIGINT,
    I$MOVEMENT_DATE DATE,
    I$USER_ID BIGINT)
RETURNS (
    X INTEGER)
AS
DECLARE VARIABLE V$CONTAINER_PUPIL_OUT_ID BIGINT;
DECLARE VARIABLE V$START_YEAR INTEGER;
DECLARE VARIABLE V$END_YEAR INTEGER;
DECLARE VARIABLE V$PUPIL_ID BIGINT;
DECLARE VARIABLE V$PUPIL_OUT_ID BIGINT;
DECLARE VARIABLE V$PUPIL_OUT_FOUND BIGINT;
DECLARE VARIABLE V$BLOB_ID BIGINT;
DECLARE VARIABLE V$LINK_ID BIGINT;
BEGIN
    X = 1;
    V$PUPIL_ID = NULL;
    V$PUPIL_OUT_ID = NULL;
    V$PUPIL_OUT_FOUND = NULL;
    V$CONTAINER_PUPIL_OUT_ID = NULL;

    SELECT V432.LISTVAL_ID
    FROM VALL V432
    WHERE V432.PARAM_ID = 432
      AND V432.OBJ_ID = :I$MOVEMENT_ID
      AND V432.IS_DEL = 0
    INTO :V$BLOB_ID;

    IF (V$BLOB_ID <> 811) THEN
    BEGIN
        SUSPEND;
        EXIT;
    END

    IF (EXTRACT(MONTH FROM I$MOVEMENT_DATE) > 8) THEN
    BEGIN
        V$START_YEAR = EXTRACT(YEAR FROM I$MOVEMENT_DATE);
        V$END_YEAR = V$START_YEAR + 1;
    END
    ELSE
    BEGIN
        V$END_YEAR = EXTRACT(YEAR FROM I$MOVEMENT_DATE);
        V$START_YEAR = V$END_YEAR - 1;
    END

    SELECT FIRST 1 L.PARENT_ID
    FROM LINKS L
    WHERE L.PARENT_TYPE_ID = 10
      AND L.OBJ_ID = :I$MOVEMENT_ID
      AND L.DATE_DEL IS NULL
    INTO :V$PUPIL_ID;

    IF (V$PUPIL_ID IS NULL) THEN
    BEGIN
        SUSPEND;
        EXIT;
    END

    SELECT FIRST 1 L.PARENT_ID, L.LINK_ID
    FROM LINKS L
    WHERE L.PARENT_TYPE_ID = 82
      AND L.OBJ_ID = :V$PUPIL_ID
      AND L.DATE_DEL IS NULL
    INTO :V$PUPIL_OUT_ID, :V$LINK_ID;

    IF (V$PUPIL_OUT_ID IS NULL) THEN
    BEGIN
        SUSPEND;
        EXIT;
    END

    SELECT FIRST 1 L.PARENT_ID
    FROM LINKS L
    WHERE L.PARENT_TYPE_ID = 78
      AND L.OBJ_ID = :V$PUPIL_OUT_ID
      AND L.DATE_DEL IS NULL
    INTO :V$CONTAINER_PUPIL_OUT_ID;

    IF (V$CONTAINER_PUPIL_OUT_ID IS NULL) THEN
    BEGIN
        SUSPEND;
        EXIT;
    END

    SELECT COUNT(*)
    FROM VALI V448
    WHERE V448.PARAM_ID = 448
      AND V448.OBJ_ID = :V$PUPIL_OUT_ID
      AND V448.IS_DEL = 0
      AND V448.VAL = :V$START_YEAR
    INTO :X;

    IF (X = 1) THEN
    BEGIN
        SUSPEND;
        EXIT;
    END

    SELECT FIRST 1 L.OBJ_ID
    FROM LINKS L
    INNER JOIN VALI V448 ON V448.OBJ_ID = L.OBJ_ID
    WHERE L.PARENT_ID = :V$CONTAINER_PUPIL_OUT_ID
      AND L.OBJ_TYPE_ID = 82
      AND L.DATE_DEL IS NULL
      AND V448.PARAM_ID = 448
      AND V448.IS_DEL = 0
      AND V448.VAL = :V$START_YEAR
    INTO :V$PUPIL_OUT_FOUND;

    IF (V$PUPIL_OUT_FOUND IS NULL) THEN
    BEGIN
        SELECT OBJ_ID
        FROM OBJECT_ADD(:V$CONTAINER_PUPIL_OUT_ID, 82)
        INTO :V$PUPIL_OUT_FOUND;

        IF (V$PUPIL_OUT_FOUND IS NOT NULL) THEN
        BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD(448, :V$PUPIL_OUT_FOUND, CAST(:V$START_YEAR AS VARCHAR(4000)), :I$USER_ID)
            INTO :V$BLOB_ID;

            SELECT BLOB_ID
            FROM VAL_ADD(449, :V$PUPIL_OUT_FOUND, CAST(:V$END_YEAR AS VARCHAR(4000)), :I$USER_ID)
            INTO :V$BLOB_ID;
        END
    END

    IF (V$PUPIL_OUT_FOUND IS NOT NULL) THEN
    BEGIN
        UPDATE LINKS
        SET PARENT_ID = :V$PUPIL_OUT_FOUND
        WHERE (LINK_ID = :V$LINK_ID);

        X = 2;
    END

    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_EDUCATION_LEAVE_TYPES (
    I$OBJ_ID BIGINT,
    I$LIST_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    LISTVAL_ID BIGINT,
    PARENT_ID BIGINT,
    VAL VARCHAR(4000),
    VAL_LONG VARCHAR(4000),
    TAG VARCHAR(100),
    "FILTER" VARCHAR(255))
AS
declare variable C smallint;
BEGIN

    -- Выпускной класс ?
    C = 0;
    SELECT FIRST 1 1
    FROM LINKS L9
    JOIN LINKS L8 ON L8.OBJ_ID = L9.PARENT_ID AND L8.PARENT_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN VALL V ON V.OBJ_ID = L8.PARENT_ID AND V.PARAM_ID = 49 AND V.IS_DEL = 0 AND V.LISTVAL_ID IN (40,45,47,48) /* 4,9,11,12 классы */
    WHERE L9.OBJ_ID = :I$OBJ_ID AND L9.PARENT_TYPE_ID IN (9, 187) AND L9.DATE_DEL IS NULL
    INTO :C;

    FOR
        SELECT LISTVAL_ID, PARENT_ID, VAL, VAL_LONG, TAG, "FILTER"
        FROM OO_FILTRED_LIST(:I$LIST_ID, :I$USER_ID)
        WHERE ("FILTER" LIKE '%LEAVED%') OR ((:C > 0) AND ("FILTER" LIKE '%FINISHED%'))
        INTO :LISTVAL_ID, :PARENT_ID, :VAL, :VAL_LONG, :TAG, :"FILTER"
    DO
    BEGIN
        IF (LISTVAL_ID <> 5319 OR
        -- академический отпуск
        NOT EXISTS(
            SELECT FIRST 1 1
            FROM LINKS L10
            WHERE L10.OBJ_ID = :I$OBJ_ID AND L10.PARENT_TYPE_ID = 289 AND L10.DATE_DEL IS NULL)
        ) THEN
        BEGIN
            SUSPEND;
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_EDUCATION_LEVELS_LIST (
    I$OBJ_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    EDUCATION_LEVEL_ID BIGINT,
    LEVEL_ID BIGINT,
    SORT_ORDER DOUBLE PRECISION)
AS
declare variable V$SCHOOL_ID bigint;
BEGIN
    FOR
        SELECT FIRST 1
               OBJ_ID
        FROM OBJECT_PARENTS_GET(:I$OBJ_ID,2)
        INTO   :V$SCHOOL_ID
    DO
    BEGIN
        FOR
            SELECT O.OBJ_ID
            FROM LINKS L
            INNER JOIN OBJECTS O
            ON O.OBJ_ID = L.OBJ_ID
            AND O.TYPE_ID = 7
            WHERE L.PARENT_ID = :V$SCHOOL_ID
            AND L.DATE_DEL IS NULL
            INTO   :EDUCATION_LEVEL_ID
        DO
        BEGIN
            SELECT I,SORT_ORDER
            FROM VAL_GET(:EDUCATION_LEVEL_ID, 43, 0, :I$USER_ID)
            INTO   :LEVEL_ID,:SORT_ORDER;
            SUSPEND;
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_EDUCATION_LINES_LIST (
    I$EDUCATION_LEVEL_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    EDUCATION_LINE_ID BIGINT,
    LINE_ID BIGINT,
    SORT_ORDER DOUBLE PRECISION)
AS
BEGIN
    FOR
        SELECT O.OBJ_ID
        FROM LINKS L
        INNER JOIN OBJECTS O
        ON O.OBJ_ID = L.OBJ_ID
        AND O.TYPE_ID = 8
        WHERE L.PARENT_ID = :I$EDUCATION_LEVEL_ID
        AND L.DATE_DEL IS NULL
        INTO   :EDUCATION_LINE_ID
    DO
    BEGIN
        SELECT I,SORT_ORDER
        FROM VAL_GET(:EDUCATION_LINE_ID, 49, 0, :I$USER_ID)
        INTO   :LINE_ID,:SORT_ORDER;
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_EDUCATION_TRANSFER (
    I$PUPIL_ID BIGINT,
    I$CLASS_ID BIGINT,
    I$ACTION_DATE DATE,
    I$ACTION_TYPE BIGINT,
    I$ORDER_NUMBER VARCHAR(4000),
    I$ORDER_DATE DATE,
    I$USER_ID BIGINT,
    I$GUP_ID BIGINT = NULL)
RETURNS (
    OBJ_ID BIGINT,
    TYPE_ID BIGINT,
    PARENT_ID BIGINT,
    USER_ID BIGINT,
    DATE_INS TIMESTAMP,
    DATE_DEL TIMESTAMP,
    SORT_ORDER DOUBLE PRECISION,
    CAPTION VARCHAR(4000),
    HAS_CHILD INTEGER,
    COLOR INTEGER,
    TAB_ID BIGINT,
    TYPE_ORDER SMALLINT,
    LINK_ID BIGINT)
AS
DECLARE VARIABLE V$BLOB_ID BIGINT;
DECLARE VARIABLE V$STAGE_ID BIGINT;
DECLARE VARIABLE V$CLASS_TYPE_ID BIGINT;
DECLARE VARIABLE V$PARENT_TYPE_ID BIGINT;
DECLARE VARIABLE V$NEW_PARENT_TYPE_ID BIGINT;
DECLARE VARIABLE V$OU_LICENCE_TYPE VARCHAR(1);
DECLARE VARIABLE V$GIA_TYPE_OLD BIGINT;
DECLARE VARIABLE V$GIA_TYPE_NEW BIGINT;
DECLARE VARIABLE V$YEAR_ID BIGINT;
DECLARE VARIABLE V$Y INTEGER;
DECLARE VARIABLE V$DT DATE;
DECLARE VARIABLE V$OLD_CLASS_ID BIGINT;
DECLARE VARIABLE V$OLD_CLASS_TYPE BIGINT;
DECLARE VARIABLE V$YEAR_VAL VARCHAR(100);
DECLARE VARIABLE V$PREV290 BIGINT;
DECLARE VARIABLE V$LASTDATE DATE;
DECLARE VARIABLE S VARCHAR(100);
BEGIN
    SELECT STATUS FROM OU_LICENCE_TYPE INTO :V$OU_LICENCE_TYPE;

    SELECT O.TYPE_ID
    FROM OBJECTS O
    WHERE O.OBJ_ID = :I$PUPIL_ID
    INTO :TYPE_ID;

    IF (TYPE_ID IS NULL OR TYPE_ID <> 10) THEN EXCEPTION DATA_ERROR 'Недопустимый тип персоны для перевода';

    SELECT O.TYPE_ID
    FROM OBJECTS O
    WHERE O.OBJ_ID = :I$CLASS_ID
    INTO :V$PARENT_TYPE_ID;

    -- Дополнительная верификация, перенесенная с фронта
    IF(V$PARENT_TYPE_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не найден учебный коллектив назначения';
    ELSE IF(V$PARENT_TYPE_ID <> 290) THEN
    BEGIN
      IF(I$ACTION_DATE IS NULL) THEN EXCEPTION DATA_ERROR 'Не указана дата движения';
      IF(I$ACTION_TYPE IS NULL) THEN EXCEPTION DATA_ERROR 'Не указан тип движения';
    END

    -- Нельзя зачислять, если уже числится в экстернате
    -- разрешаем только в предварительный прием
    IF(EXISTS(
      SELECT FIRST 1 1
      FROM LINKS L
      WHERE L.OBJ_ID = :I$PUPIL_ID AND L.PARENT_ID = :I$CLASS_ID AND L.DATE_DEL IS NULL
    ))
    THEN
    BEGIN
      IF(V$CLASS_TYPE_ID = 290) THEN S = 'этом этапе предварительного приема';
      ELSE IF(V$CLASS_TYPE_ID = 289) THEN S = 'академическом отпуске';
      ELSE S = 'этом учебном коллективе';
      EXCEPTION DATA_ERROR 'Обучающийся уже числится в ' || S;
    END

    -- Проверяем, что запись зачисления позднее, чем последняя запись выбытия (если она есть)
    SELECT FIRST 1 M.DATE_OUT
    FROM PERSON_MOVEMENTS M
    WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :I$PUPIL_ID AND M.DATE_OUT IS NOT NULL AND M.GROUP_TYPE_ID IN (9, 125, 187, 289)
    ORDER BY 1 DESC
    INTO :V$LASTDATE;

    IF(V$LASTDATE > I$ACTION_DATE) THEN EXCEPTION DATA_ERROR 'Нельзя зачислить в новый учебный коллектив с датой раньше, чем дата последнего выбытия - ' || (SELECT RESULT FROM DATE2STR(:V$LASTDATE));

    SELECT V.LISTVAL_ID
    FROM LINKS L
    JOIN VALL V ON V.OBJ_ID = L.PARENT_ID AND V.PARAM_ID = 49 AND V.IS_DEL = 0
    WHERE L.PARENT_TYPE_ID = 8 AND L.OBJ_ID = :I$CLASS_ID AND L.DATE_DEL IS NULL
    UNION ALL
    SELECT V2114.LISTVAL_ID
    FROM VALL V2114
    WHERE V2114.OBJ_ID = :I$CLASS_ID AND V2114.PARAM_ID = 2114 AND V2114.IS_DEL = 0
    INTO :V$STAGE_ID;

    -- IF (V$STAGE_ID IS NULL) THEN EXIT;

    -- Запрещаем принимать "для начала обучения" в классы отличные от первого
    IF(I$ACTION_TYPE = 805 AND V$STAGE_ID NOT IN (37, 12942, 12943, 49)) THEN
      EXCEPTION DATA_ERROR 'Прием для начала обучения может быть только в 1 класс или на 1 курс';

    -- Запрещаем делать перевод руками, если ученик внесен в проект приказа
    IF(EXISTS(
      SELECT FIRST 1 1
      FROM ORDER_DATA OD
      JOIN ORDERS D ON D.DATE_DEL IS NULL AND D.OBJ_ID = OD.ORDER_ID AND D.TYPE_ID IN (12929, 12931, 12932, 12933, 12934, 12935, 12936, 12937, 12964)
        AND D.STATE_ID = 11716
      WHERE OD.DATE_DEL IS NULL AND OD.REF_ID = :I$PUPIL_ID
    ))
    THEN EXCEPTION DATA_ERROR 'Обучающийся уже внесен в проект приказа о движении. Нельзя использовать одновременно механизм и ручное движение';

    -- Получаем статус ГИА для текущего класса (обычный/экстернат/ВПЛ, но для ВПЛ сюда не попадем)
    SELECT V2388.LISTVAL_ID
    FROM LINKS LP9
    JOIN VALL V2388 ON V2388.OBJ_ID = LP9.PARENT_ID AND V2388.PARAM_ID IN (2388, 2418, 2419)
    WHERE LP9.OBJ_ID = :I$PUPIL_ID AND LP9.PARENT_TYPE_ID IN (9, 125, 187) AND LP9.DATE_DEL IS NULL
    INTO :V$GIA_TYPE_OLD;

    -- Получаем статус ГИА для нового класса
    SELECT V2388.LISTVAL_ID
    FROM LINKS L9
    JOIN VALL V2388 ON V2388.OBJ_ID = L9.OBJ_ID AND V2388.PARAM_ID IN (2388, 2418, 2419)
    WHERE L9.PARENT_TYPE_ID = 8 AND L9.OBJ_TYPE_ID IN (9, 125, 187) AND L9.DATE_DEL IS NULL AND L9.OBJ_ID = :I$CLASS_ID
    INTO :V$GIA_TYPE_NEW;

    -- Если ученик находился в выпускном классе
    IF(V$GIA_TYPE_OLD IS NOT NULL AND V$GIA_TYPE_OLD <> 11217) THEN
    BEGIN
        -- Требуем, чтобы у ученика отсутствовали назначения на экзамены в текущем учебном году вплоть до 01 мая текущего года
        IF(V$GIA_TYPE_NEW <> V$GIA_TYPE_OLD) THEN
        BEGIN
            V$Y = EXTRACT(YEAR FROM CURRENT_DATE);
            IF(CURRENT_DATE < ('1.05.' || V$Y) OR CURRENT_DATE >= ('1.09.' || V$Y)) THEN
            BEGIN
                -- Получаем LISTVAL_ID текущего года
                V$DT = '1.09.' || V$Y;
                IF (CURRENT_DATE < V$DT) THEN
                BEGIN
                  V$YEAR_VAL = (V$Y - 1) || '-' || V$Y;
                END
                ELSE
                BEGIN
                  V$YEAR_VAL = V$Y || '-' ||(V$Y + 1);
                END
                SELECT FIRST 1 LV.LISTVAL_ID
                FROM LISTVALS LV
                JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
                WHERE LV.LIST_ID = 29 AND R.VAL LIKE :V$YEAR_VAL INTO :V$YEAR_ID;
                -- Проверяем назначения на экзамены этого года
                V$BLOB_ID = 0;
                SELECT FIRST 1 1
                FROM LINKS L120
                JOIN VALL V742 ON V742.OBJ_ID = L120.PARENT_ID AND V742.PARAM_ID = 742 AND V742.IS_DEL = 0 AND V742.LISTVAL_ID = :V$YEAR_ID
                JOIN LINKS L10_120 ON L10_120.PARENT_ID = :I$PUPIL_ID AND L10_120.OBJ_ID = L120.OBJ_ID AND L10_120.DATE_DEL IS NULL
                WHERE L120.PARENT_TYPE_ID = 119 AND L120.OBJ_TYPE_ID = 120 AND L120.DATE_DEL IS NULL
                INTO :V$BLOB_ID;
                IF(V$BLOB_ID > 0) THEN EXCEPTION DATA_ERROR 'Обучающийся переводится из выпускного класса в не-выпускной или выпускной другого типа. Необходимо удалить все назначения экзаменов для этого обучающегося';
            END
        END
    END

    -- Перевод в экстернат заменяем выбытием в семью
    -- В обычных классах просто выбытие
    -- При переводе в предварительный прием просто создаем ссылку, старую прибиваем
    -- !!! ORDER_ID !!!
    IF (V$PARENT_TYPE_ID = 290) THEN
    BEGIN
      SELECT FIRST 1 LP290.PARENT_ID
      FROM LINKS LP290
      WHERE LP290.OBJ_ID = :I$PUPIL_ID AND LP290.PARENT_TYPE_ID = 290 AND LP290.DATE_DEL IS NULL
      INTO :V$PREV290;

      IF(V$PREV290 = I$CLASS_ID) THEN EXCEPTION DATA_ERROR 'Обучающийся уже числится на этом этапе предварительного приема';
      IF(V$PREV290 IS NOT NULL) THEN
      BEGIN
        UPDATE LINKS
        SET DATE_DEL = CURRENT_TIMESTAMP
        WHERE PARENT_ID = :V$PREV290 AND OBJ_ID = :I$PUPIL_ID AND DATE_DEL IS NULL;

        -- Регистрируем в логе
        INSERT INTO HISTVALS
        (TABLE_NAME, OBJ_ID, PARAM_ID, USER_ID, OLD_VAL, VAL)
        VALUES ('LINKS_DEL', :I$PUPIL_ID, NULL, :I$USER_ID, (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$PREV290)),
          (SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$CLASS_ID)));
      END

      SELECT 1 FROM OBJECT_ADD_LINK(:I$CLASS_ID, :I$PUPIL_ID, 10) INTO :V$BLOB_ID;
    END
    ELSE IF (V$PARENT_TYPE_ID = 187) THEN
    BEGIN
      -- При зачислении в экстернат меняем тип движения на просто прибыл
      I$ACTION_TYPE = 12905;
      EXECUTE PROCEDURE PARAGRAF_EDUCATION_LEAVE(:I$PUPIL_ID, :I$ACTION_DATE, 811, :I$ORDER_NUMBER, :I$ORDER_DATE, 11200, NULL, NULL, NULL, NULL, NULL, NULL, :I$USER_ID, 903);
    END
    ELSE
    BEGIN
      SELECT FIRST 1 LPG.PARENT_ID, LPG.PARENT_TYPE_ID
      FROM LINKS LPG
      WHERE LPG.OBJ_ID = :I$PUPIL_ID AND LPG.PARENT_TYPE_ID IN (9, 187) AND LPG.DATE_DEL IS NULL
      INTO :V$OLD_CLASS_ID, :V$OLD_CLASS_TYPE;

      -- При приеме из выбывших класса не будет
      IF(V$OLD_CLASS_ID IS NOT NULL) THEN
      BEGIN
        -- Если был класс-экстернат, то только выбытие (если только это не перевод в другой экстернат)
        IF(V$OLD_CLASS_TYPE = 187 AND V$PARENT_TYPE_ID <> 187) THEN I$ACTION_TYPE = 811;
        SELECT OBJ_ID FROM VARGRP_MOVE_PUPIL(:I$PUPIL_ID, :V$OLD_CLASS_ID, :I$ORDER_NUMBER, :I$ORDER_DATE, :I$ACTION_DATE, 1, :I$USER_ID, NULL, :I$ACTION_TYPE) INTO :V$BLOB_ID;
        -- В новый класс:
        -- Если был класс-экстернат, то в новый класс = продолжение обучения (если только это не перевод в другой экстернат)
        IF(V$OLD_CLASS_TYPE = 187 AND V$PARENT_TYPE_ID <> 187) THEN I$ACTION_TYPE = 806;
      END
    END

    -- Теперь зачисляем в новый коллектив
    IF(V$PARENT_TYPE_ID <> 290) THEN
    SELECT OBJ_ID FROM VARGRP_MOVE_PUPIL(:I$PUPIL_ID, :I$CLASS_ID, :I$ORDER_NUMBER, :I$ORDER_DATE, :I$ACTION_DATE, 0, :I$USER_ID, NULL, :I$ACTION_TYPE) INTO :V$BLOB_ID;

    -- Зачисляем в ГУП
    IF(I$GUP_ID IS NOT NULL) THEN
    BEGIN
      SELECT OBJ_ID FROM VARGRP_MOVE_PUPIL(:I$PUPIL_ID, :I$GUP_ID, :I$ORDER_NUMBER, :I$ORDER_DATE, :I$ACTION_DATE, 0, :I$USER_ID, NULL, :I$ACTION_TYPE) INTO :V$BLOB_ID;
    END

    SELECT FIRST 1 LPG.LINK_ID, C.CAPTION, C.SORT_ORDER
    FROM LINKS LPG
    LEFT JOIN OBJECT_CAPTION_GET(LPG.PARENT_ID) C ON 1 = 1
    WHERE LPG.OBJ_ID = :I$PUPIL_ID AND LPG.PARENT_ID = :I$CLASS_ID AND LPG.DATE_DEL IS NULL
    INTO :LINK_ID, :CAPTION, :SORT_ORDER;

    SELECT COLOR, SORT_ORDER
    FROM TYPES
    WHERE TYPE_ID = 10
    INTO :COLOR, :TYPE_ORDER;

    PARENT_ID = I$CLASS_ID;
    OBJ_ID = I$PUPIL_ID;
    TYPE_ID = 10;
    USER_ID = I$USER_ID;
    DATE_INS = I$ACTION_DATE;
    DATE_DEL = NULL;
    HAS_CHILD = 0;
    TAB_ID = NULL;

    IF(V$PARENT_TYPE_ID <> 290 AND V$PARENT_TYPE_ID <> 289) THEN
    EXECUTE PROCEDURE GIA_COPY_INFO_EXAM_PARAMS(:I$PUPIL_ID, :I$CLASS_ID, :I$USER_ID);

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_EMPLOYEE_ACCEPT (
    I$SCHOOL_ID BIGINT,
    I$LASTNAME VARCHAR(100),
    I$NAME VARCHAR(100),
    I$MIDDLENAME VARCHAR(100),
    I$DOB DATE,
    I$SEX BIGINT,
    I$VACANCY_ID BIGINT,
    I$RATECOUNT DOUBLE PRECISION,
    I$VACANCY_TYPE BIGINT,
    I$ACCEPTEDDATE DATE,
    I$ORDERDATE DATE,
    I$ORDERNUMBER VARCHAR(100),
    I$CONTRACTTO DATE,
    I$ACCEPTCONDITION BIGINT,
    I$FACT_REGION VARCHAR(255),
    I$FACT_DISTRICT VARCHAR(255),
    I$FACT_TOWN VARCHAR(255),
    I$FACT_SETTLEMENT VARCHAR(255),
    I$FACT_STREET VARCHAR(255),
    I$FACT_HOUSE VARCHAR(10),
    I$FACT_LITER VARCHAR(10),
    I$FACT_CORP VARCHAR(10),
    I$FACT_FLAT VARCHAR(10),
    I$FACT_POST_INDEX VARCHAR(20),
    I$FACT_OCATD VARCHAR(11),
    I$FACT_HOUSEGUID VARCHAR(40),
    I$FACT_STREETGUID VARCHAR(40),
    I$REG_REGION VARCHAR(255),
    I$REG_DISTRICT VARCHAR(255),
    I$REG_TOWN VARCHAR(255),
    I$REG_SETTLEMENT VARCHAR(255),
    I$REG_STREET VARCHAR(255),
    I$REG_HOUSE VARCHAR(10),
    I$REG_LITER VARCHAR(10),
    I$REG_CORP VARCHAR(10),
    I$REG_FLAT VARCHAR(10),
    I$REG_POST_INDEX VARCHAR(20),
    I$REG_OCATD VARCHAR(11),
    I$REG_HOUSEGUID VARCHAR(40),
    I$REG_STREETGUID VARCHAR(40),
    I$CONTRACT_NUMBER VARCHAR(255),
    I$CONTRACT_DATE DATE,
    I$CATEGORY BIGINT,
    I$USER_ID VARCHAR(40) = NULL,
    I$BOOK_NAME VARCHAR(1000) = NULL)
RETURNS (
    EMPLOYEE_ID BIGINT,
    OWNER_ID BIGINT)
AS
DECLARE VARIABLE V$MOVEMENT_ID BIGINT;
DECLARE VARIABLE V$BLOB_ID BIGINT;
DECLARE VARIABLE V$ORDER_ID BIGINT;
DECLARE VARIABLE V$SIGNED_BY BIGINT;
DECLARE VARIABLE V$OWNER_ID BIGINT;
DECLARE VARIABLE S VARCHAR(400);
BEGIN
  IF(I$CATEGORY IS NULL OR I$CATEGORY <= 0) THEN
  BEGIN
    SELECT VAL FROM DO_FUNC(:I$VACANCY_ID, 400) INTO :S;
    IF (S = 'Да') THEN EXCEPTION DATA_ERROR 'Не указана квалификационная категория';
    ELSE I$CATEGORY = 632;   -- Без категории
    S = NULL;
  END

  IF(I$ACCEPTEDDATE IS NULL) THEN EXCEPTION DATA_ERROR 'Не указана дата приема';

  -- Название должности является обязательным в S-Параграфе
  -- но если не ввели вовсе - ставим название идентично должности, пусть сами разбираются
  I$BOOK_NAME = TRIM(I$BOOK_NAME);
  IF(I$BOOK_NAME IS NULL OR I$BOOK_NAME = '') THEN
    SELECT FIRST 1 V66.VAL
    FROM VALS V66
    WHERE V66.OBJ_ID = :I$VACANCY_ID AND V66.PARAM_ID = 66 AND V66.IS_DEL = 0
    INTO :I$BOOK_NAME;

  EXECUTE PROCEDURE PARAGRAF_VACANCY_VERIFY(:I$SCHOOL_ID, NULL, :I$VACANCY_ID, NULL, :I$RATECOUNT, I$ACCEPTCONDITION);

  -- Создаем приказ о зачислении, статус сразу будет Проект, но присвоится номер
  SELECT FIRST 1 LP.PARENT_ID
  FROM LINKS LP
  WHERE LP.OBJ_ID = :I$VACANCY_ID AND LP.PARENT_TYPE_ID IN (2, 211) AND LP.DATE_DEL IS NULL
  INTO :V$OWNER_ID;

  -- Добавляем нового сотрудника
  SELECT OBJ_ID FROM OBJECT_ADD(:V$OWNER_ID, 14) INTO :EMPLOYEE_ID;

  IF(I$FACT_FLAT IS NOT NULL) THEN
  SELECT BLOB_ID
  FROM ADR_ADD(255, :EMPLOYEE_ID, :I$FACT_REGION, :I$FACT_DISTRICT, :I$FACT_TOWN, :I$FACT_SETTLEMENT, :I$FACT_STREET,
               :I$FACT_HOUSE, :I$FACT_LITER, :I$FACT_CORP, :I$FACT_FLAT, :I$FACT_POST_INDEX, :I$FACT_OCATD, :I$FACT_HOUSEGUID, :I$FACT_STREETGUID)
  INTO :V$BLOB_ID;

  IF(I$REG_FLAT IS NOT NULL) THEN
  SELECT BLOB_ID
  FROM ADR_ADD(262, :EMPLOYEE_ID, :I$REG_REGION, :I$REG_DISTRICT, :I$REG_TOWN, :I$REG_SETTLEMENT, :I$REG_STREET,
               :I$REG_HOUSE, :I$REG_LITER, :I$REG_CORP, :I$REG_FLAT, :I$REG_POST_INDEX, :I$REG_OCATD, :I$REG_HOUSEGUID, :I$REG_STREETGUID)
  INTO :V$BLOB_ID;

  SELECT BLOB_ID FROM VAL_ADD(59, :EMPLOYEE_ID, :I$LASTNAME) INTO :V$BLOB_ID;
  SELECT BLOB_ID FROM VAL_ADD(60, :EMPLOYEE_ID, :I$NAME) INTO :V$BLOB_ID;

  IF (I$MIDDLENAME IS NOT NULL) THEN
  SELECT BLOB_ID FROM VAL_ADD(61, :EMPLOYEE_ID, :I$MIDDLENAME) INTO :V$BLOB_ID;

  SELECT BLOB_ID FROM VAL_ADD(239, :EMPLOYEE_ID, :I$SEX) INTO :V$BLOB_ID;

  UPDATE OR INSERT INTO VALD (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
  VALUES (241, :EMPLOYEE_ID, NULL, 0, :I$DOB);

  -- Заменяем фейковый id настоящим, когда сам себя принимает
  IF(V$SIGNED_BY < 0) THEN V$SIGNED_BY = EMPLOYEE_ID;

  SELECT C.CAPTION
  FROM OBJECT_CAPTION_GET(:I$VACANCY_ID) C
  INTO :S;

  -- Создаем приказ на прием нового сотрудника в статусе Проект.
  SELECT D.OBJ_ID
  FROM ORDER_SET(NULL, :I$USER_ID, NULL, 14256, 11716, :I$ORDERDATE, :I$ORDERNUMBER, :I$ACCEPTEDDATE, :V$SIGNED_BY, NULL,
    'Прием ' || :S || ' - ' || :I$LASTNAME || ' ' || :I$NAME || COALESCE(' ' || :I$MIDDLENAME, ''), NULL, :V$OWNER_ID, :I$VACANCY_ID, :EMPLOYEE_ID) D
  INTO :V$ORDER_ID;

  -- Регистрируем строку приказа и фиксируем запись должности в ней
  SELECT 1 FROM ORDER_SET_ROW(:V$ORDER_ID, NULL, :I$USER_ID, 0, :EMPLOYEE_ID, NULL, 1, NULL, NULL,
    ',' || ',' || :I$VACANCY_TYPE || ',' || CAST(:I$RATECOUNT AS NUMERIC(18, 2)) || ',' || :I$ACCEPTCONDITION || ',' || COALESCE(:I$CATEGORY, 632) || ',' ||
    COALESCE(:I$CONTRACT_NUMBER, '') || ',' || COALESCE((SELECT RESULT FROM DATE2STR(:I$CONTRACT_DATE)), '') || ',' || COALESCE((SELECT RESULT FROM DATE2STR(:I$CONTRACTTO)), '') ||
    ',' || COALESCE(:I$BOOK_NAME, ''), :I$VACANCY_ID, :I$VACANCY_ID) INTO :V$SIGNED_BY;

  -- Перевод приказа в статус действующего. Внутри будет произведено назначение на должность
  SELECT VAL FROM ORDER_SET_STATE(:V$ORDER_ID, 11715, :I$USER_ID) INTO :S;

  -- Вызваем пересчет свободных ставок
  EXECUTE PROCEDURE CALC_JOB_OCCUPIED(:I$VACANCY_ID);

  SUSPEND;

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_EMPLOYEE_CANBE_FIRED (
    I$EMPLOYEE_ID BIGINT NOT NULL,
    I$RAISE SMALLINT = 1)
RETURNS (
    OBJ_ID BIGINT,
    LOAD_TYPE_ID SMALLINT,
    LOAD_MSG VARCHAR(2000))
AS
begin
--Redmine #1063
--добавить выдачу массива teacher_loads, элементы с полями
--type: 0 = классное руководство, 1 = учебная нагрузка (классный журнал с данным учителем), должны идти первыми по порядку
--name: название сущности, для type 0 - название класса из object_caption_get, для type 1 - название журнала, собирается из cj2_journal поле journal_name (название группы) и если есть subject_id - дописываем название предмета (object_caption_get) через дефис после названия группы

  -- Redmine #1063 .4 Не должен быть классным руководителем
  FOR
    SELECT V.OBJ_ID, C.CAPTION, 0  
    FROM VALR V
    JOIN LINKS LP ON LP.OBJ_ID = V.OBJ_ID AND LP.PARENT_TYPE_ID = 8 AND LP.DATE_DEL IS NULL
    LEFT JOIN OBJECT_CAPTION_GET(LP.OBJ_ID) C ON 1 = 1
    WHERE V.VAL = :I$EMPLOYEE_ID AND V.PARAM_ID = 53 AND V.IS_DEL = 0
    INTO :OBJ_ID, :LOAD_MSG, :LOAD_TYPE_ID
  DO
  BEGIN
    IF (OBJ_ID IS NOT NULL AND I$RAISE > 0) THEN
      EXCEPTION DATA_ERROR 'Сотрудник не должен оставаться классным руководителем (руководителем, куратором группы), смотри ' || LOAD_MSG;
    SUSPEND;
  END

  -- Не должен быть учителем в действующих журналах
  FOR
    SELECT J.OBJ_ID, J.JOURNAL_NAME || COALESCE(' - ' || C.CAPTION, ''), 1
    FROM CJ2_JOURNAL J
    LEFT JOIN OBJECT_CAPTION_GET(J.SUBJECT_ID) C ON J.SUBJECT_ID IS NOT NULL
    WHERE J.DATE_DEL IS NULL AND J.TEACHER_ID = :I$EMPLOYEE_ID
    INTO :OBJ_ID, :LOAD_MSG, :LOAD_TYPE_ID
  DO
  BEGIN
    IF (OBJ_ID IS NOT NULL AND I$RAISE > 0) THEN
      EXCEPTION DATA_ERROR 'Сотрудник не должен быть назначен действующим преподавателем в журналах, смотри ' || LOAD_MSG;
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_EMPLOYEE_CANCEL_LEAVE (
    I$EMPLOYEE_ID BIGINT,
    I$MOVEMENT_ID BIGINT)
AS
DECLARE VARIABLE V$SCHOOL_ID BIGINT;
DECLARE VARIABLE V$LEAVED_EMPLOYEE_ID BIGINT;
DECLARE VARIABLE V$BLOB_ID BIGINT;
DECLARE VARIABLE V$VAL VARCHAR(4000);
DECLARE VARIABLE V$MOVEMENT_ID BIGINT;
DECLARE VARIABLE V$STATUS BIGINT;
BEGIN
    SELECT FIRST 1 OBJ_ID
    FROM OBJECT_PARENTS_GET(:I$EMPLOYEE_ID, 2)
    INTO :V$SCHOOL_ID;

    IF(V$SCHOOL_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не удалось определить организацию';

    V$LEAVED_EMPLOYEE_ID = NULL;

    -- Находим каталог "Уволенные"
    SELECT FIRST 1 OBJ_ID
    FROM OBJECT_PARENTS_GET(:I$EMPLOYEE_ID, 84)
    INTO :V$LEAVED_EMPLOYEE_ID;

    -- Если была дата увольнения - обнуляем ее (странно, не быть ее тут не должно !)
    SELECT V FROM VAL_GET(:I$MOVEMENT_ID, 74) INTO :V$VAL;
    IF (V$VAL <> '') THEN
    BEGIN
        SELECT BLOB_ID FROM VAL_ADD(74, :I$MOVEMENT_ID, :V$VAL, NULL, 1) INTO :V$BLOB_ID;
    END

    -- Обнуляем поле дата приказа об увольнении
    SELECT V FROM VAL_GET(:I$MOVEMENT_ID, 456) INTO :V$VAL;
    IF (V$VAL <> '') THEN
    BEGIN
        SELECT BLOB_ID FROM VAL_ADD(456, :I$MOVEMENT_ID, :V$VAL, NULL, 1) INTO :V$BLOB_ID;
    END

    -- Обнуляем номер приказа об увольнении
    SELECT V FROM VAL_GET(:I$MOVEMENT_ID, 457) INTO :V$VAL;
    IF (V$VAL <> '') THEN
    BEGIN
        SELECT BLOB_ID FROM VAL_ADD(457, :I$MOVEMENT_ID, :V$VAL, NULL, 1) INTO :V$BLOB_ID;
    END

    -- Обнуляем поле "куда выбыл". Более не используется
    --SELECT V FROM VAL_GET(:I$MOVEMENT_ID, 459) INTO :V$VAL;
    --IF (V$VAL <> '') THEN
    --BEGIN
    --    SELECT BLOB_ID FROM VAL_ADD(459, :I$MOVEMENT_ID, :V$VAL, NULL, 1) INTO :V$BLOB_ID;
    --END

    -- Обнуляем основание увольнения
    SELECT I FROM VAL_GET(:I$MOVEMENT_ID, 458) INTO :V$BLOB_ID;
    IF (V$BLOB_ID <> 0) THEN
    BEGIN
        SELECT BLOB_ID FROM VAL_ADD(458, :I$MOVEMENT_ID, :V$BLOB_ID, NULL, 1) INTO :V$BLOB_ID;
    END

    -- Обнуляем причину увольнения
    SELECT I FROM VAL_GET(:I$MOVEMENT_ID, 461) INTO :V$BLOB_ID;
    IF (V$BLOB_ID <> 0) THEN BEGIN
        SELECT BLOB_ID FROM VAL_ADD(461, :I$MOVEMENT_ID, :V$BLOB_ID, NULL, 1) INTO :V$BLOB_ID;
    END

    -- Тип должности - основная или дополнительная ?
    SELECT I FROM VAL_GET(:I$MOVEMENT_ID, 72) INTO :V$BLOB_ID;
    IF (V$BLOB_ID = 934) THEN
    BEGIN
        -- Если была основная, и есть другие должности, то меняем на дополнительную
        FOR
            SELECT O.OBJ_ID
            FROM LINKS L
            JOIN OBJECTS O ON O.OBJ_ID = L.OBJ_ID AND O.TYPE_ID = 15 AND O.OBJ_ID <> :I$MOVEMENT_ID
            WHERE L.PARENT_ID = :I$EMPLOYEE_ID AND L.DATE_DEL IS NULL
            INTO :V$MOVEMENT_ID
        DO
        BEGIN
            SELECT BLOB_ID FROM VAL_ADD(72, :V$MOVEMENT_ID, 935) INTO :V$BLOB_ID;
        END
    END

    -- Если это была единственная ставка сотрудника, и он висит в уволенных
    IF (V$LEAVED_EMPLOYEE_ID IS NOT NULL) THEN
    BEGIN
      V$BLOB_ID = NULL;
      -- Пытаемся найти отдел
      SELECT OBJ_ID FROM OBJECT_PARENTS_GET((SELECT I FROM VAL_GET(:I$MOVEMENT_ID, 69)), 211) INTO :V$BLOB_ID;

      -- Восстанавливаем запись сотрудника в непосредственно в организации или в отделе, где он числился
      SELECT OBJ_ID
      FROM OBJECT_MOVE(:V$LEAVED_EMPLOYEE_ID, COALESCE(:V$BLOB_ID, :V$SCHOOL_ID), :I$EMPLOYEE_ID, 14)
      INTO :V$BLOB_ID;
    END

    -- Восстанавливаем поле статуса. Если почему-то ничего нет, выставляем статус РАБОТАЮЩИЙ
    SELECT FIRST 1 V2859.LISTVAL_ID
    FROM LINKS L376
    JOIN VALD V2860 ON V2860.OBJ_ID = L376.OBJ_ID AND V2860.PARAM_ID = 2860 AND V2860.IS_DEL = 0
    -- Выбираем только незакрытые отпуска
    LEFT JOIN VALD V2864 ON V2864.OBJ_ID = L376.OBJ_ID AND V2864.PARAM_ID = 2864 AND V2864.IS_DEL = 0
    JOIN VALL V2859 ON V2859.OBJ_ID = L376.OBJ_ID AND V2859.PARAM_ID = 2859 AND V2859.IS_DEL = 0
    WHERE L376.PARENT_ID = :I$EMPLOYEE_ID AND L376.OBJ_TYPE_ID = 376 AND L376.DATE_DEL IS NULL AND V2864.VAL IS NULL
    ORDER BY V2860.VAL DESC
    INTO :V$STATUS;

    IF(V$STATUS IS NULL) THEN V$STATUS = 602;
    SELECT BLOB_ID FROM VAL_ADD(274, :I$EMPLOYEE_ID, :V$STATUS) INTO :V$BLOB_ID;

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_EMPLOYEE_HASBASEVAC (
    I$EMPLOYEE_ID BIGINT)
RETURNS (
    HASBASEVACANCY SMALLINT)
AS
DECLARE VARIABLE V$MOVEMENT_ID BIGINT;
DECLARE VARIABLE V$LEAVEDATE DATE;
DECLARE VARIABLE V$ISBASE_ID BIGINT;
BEGIN
    HASBASEVACANCY = 0;
    FOR
        SELECT O.OBJ_ID
        FROM LINKS L
        INNER JOIN OBJECTS O
        ON O.OBJ_ID = L.OBJ_ID
        AND O.TYPE_ID = 15
        WHERE L.PARENT_ID = :I$EMPLOYEE_ID
        AND L.DATE_DEL IS NULL
        INTO :V$MOVEMENT_ID
    DO
    BEGIN
        FOR
            SELECT D
            FROM VAL_GET(:V$MOVEMENT_ID, 74)
            INTO :V$LEAVEDATE
        DO
        BEGIN
            IF (V$LEAVEDATE IS NULL) THEN
            BEGIN
                FOR
                    SELECT I
                    FROM VAL_GET(:V$MOVEMENT_ID, 72)
                    INTO :V$ISBASE_ID
                DO
                BEGIN
                    IF (V$ISBASE_ID = 934) THEN
                    BEGIN
                        HASBASEVACANCY = 1;
                    END
                END
            END
        END
    END

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_EMPLOYEE_JOB_GET (
    L15_PARENT_OBJ_ID BIGINT,
    L15_OBJ_ID BIGINT,
    JOB_DATE_START DATE,
    JOB_LISTVAL_ID BIGINT)
RETURNS (
    L15_OBJ_ID_START BIGINT)
AS
DECLARE VARIABLE V$L15_OBJ_ID BIGINT;
DECLARE VARIABLE V$JOB_DATE_END DATE;
DECLARE VARIABLE V$JOB_LISTVAL_ID BIGINT;
BEGIN
  -- Процедура испльзуется вроде только в отчетах, и судя по всему работает не очень адекватно
  -- Исключено из отчета Справка сотруднику, заменено на REPORT_EMP_FORM

  L15_OBJ_ID_START = NULL;
  FOR
    SELECT FIRST 1 L15.OBJ_ID, V73.VAL DOLGN_IN, V58.LISTVAL_ID
    FROM LINKS L15
    JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0  -- ДАТА ВСТУПЛЕНИЯ В ДОЛЖНОСТЬ
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0  -- ДАТА УВОЛЬНЕНИЯ С ДОЛЖНОСТИ
    JOIN VALL V72 ON V72.OBJ_ID = L15.OBJ_ID AND V72.PARAM_ID = 72 AND V72.IS_DEL = 0 AND V72.LISTVAL_ID = 934 -- ДОЛЖНОСТЬ ОСНОВНАЯ ИЛИ ДОПОЛНИТЕЛЬНАЯ LIST_VALUE  129
    LEFT JOIN VALR V69 ON V69.OBJ_ID = L15.OBJ_ID AND V69.PARAM_ID = 69 AND V69.IS_DEL = 0  --  ID ДОЛЖНОСТИ (TYPE_ID = 13)
    LEFT JOIN VALL V58 ON V58.OBJ_ID = V69.VAL AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0  --  ДОЛЖНОСТЬ
    WHERE L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL AND L15.PARENT_TYPE_ID = 14 AND L15.PARENT_ID = :L15_PARENT_OBJ_ID
      AND (L15.OBJ_ID < :L15_OBJ_ID OR :L15_OBJ_ID IS NULL)
      AND (V58.LISTVAL_ID = :JOB_LISTVAL_ID OR :JOB_LISTVAL_ID IS NULL)
      AND (V74.VAL = :JOB_DATE_START OR :JOB_DATE_START IS NULL)
      ORDER BY V73.VAL DESC, L15.OBJ_ID DESC
    INTO :V$L15_OBJ_ID, :V$JOB_DATE_END, :V$JOB_LISTVAL_ID
  DO
  BEGIN
    L15_OBJ_ID_START = V$L15_OBJ_ID;
    IF (L15_OBJ_ID_START IS NOT NULL) THEN
    BEGIN
      V$L15_OBJ_ID = NULL;
      SELECT L15_OBJ_ID_START
      FROM PARAGRAF_EMPLOYEE_JOB_GET(:L15_PARENT_OBJ_ID, :L15_OBJ_ID_START, :V$JOB_DATE_END, :V$JOB_LISTVAL_ID)
      INTO :V$L15_OBJ_ID;
      IF (V$L15_OBJ_ID IS NOT NULL) THEN L15_OBJ_ID_START = V$L15_OBJ_ID;
    END
    SUSPEND;
  END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_EMPLOYEE_LEAVE (
    I$PARENT_ID BIGINT,
    I$EMPLOYEE_ID BIGINT,
    I$LEAVEDATE DATE,
    I$LEAVEORDERNUMBER VARCHAR(4000),
    I$LEAVEORDERDATE DATE,
    I$LEAVEREASON BIGINT,
    I$LEAVEBASEMENT BIGINT,
    I$USER_ID BIGINT = NULL,
    I$RELEASE SMALLINT = 0)
AS
DECLARE VARIABLE V$LONG_VAC INTEGER;
DECLARE VARIABLE V$SCHOOL_ID BIGINT;
DECLARE VARIABLE V$LEAVED_EMPLOYEE_ID BIGINT;
DECLARE VARIABLE V$LINK_ID BIGINT;
DECLARE VARIABLE V$MOVEMENT_ID BIGINT;
DECLARE VARIABLE V$BLOB_ID BIGINT;
DECLARE VARIABLE V$LEAVEDATE DATE;
BEGIN
  IF (I$RELEASE IS NULL OR I$RELEASE < 0) THEN I$RELEASE = 0;
  IF (I$LEAVEDATE IS NULL) THEN EXCEPTION DATA_ERROR 'Не указана дата увольнения';

  V$LEAVED_EMPLOYEE_ID = NULL;

  V$SCHOOL_ID = NULL;
  SELECT FIRST 1 OBJ_ID FROM OBJECT_PARENTS_GET(:I$PARENT_ID, 2) INTO :V$SCHOOL_ID; -- найдем школу, если увольнение из отделения
  IF (V$SCHOOL_ID IS NULL) THEN V$SCHOOL_ID = I$PARENT_ID; --увольнение из школы
    
  SELECT FIRST 1 L84.OBJ_ID
  FROM LINKS L84
  WHERE L84.PARENT_ID = :V$SCHOOL_ID AND L84.OBJ_TYPE_ID = 84 AND L84.DATE_DEL IS NULL
  INTO :V$LEAVED_EMPLOYEE_ID;          -- найдем объект "уволенные"

  IF (V$LEAVED_EMPLOYEE_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не найден каталог уволенных';

  -- Нельзя увольнять сотрудника, находящегося в длительном отпуске (проверяем без реестра отпусков !)
  V$LONG_VAC = 0;
  SELECT FIRST 1 1
  FROM VALL V274
  WHERE V274.OBJ_ID = :I$EMPLOYEE_ID AND V274.PARAM_ID = 274 AND V274.IS_DEL = 0 AND V274.LISTVAL_ID <> 602
  INTO :V$LONG_VAC;

  IF(V$LONG_VAC <> 0) THEN
    EXCEPTION DATA_ERROR 'Нельзя увольнять сотрудника, находящегося в длительном отпуске';

  IF(EXISTS(
    SELECT FIRST 1 1
    FROM LIB2_USAGE U
    WHERE U.DATE_DEL IS NULL AND U.REF_TYPE_ID = 14 AND U.RETURN_DATE IS NULL AND U.LOSS_DATE IS NULL AND U.REF_ID = :I$EMPLOYEE_ID
  ))
  THEN
    EXCEPTION DATA_ERROR 'За сотрудником числятся не возвращенная литература';

  IF (I$RELEASE = 1) THEN
  BEGIN
    -- Снимаем классное руководства и нагрузки
    EXECUTE PROCEDURE DROP_CLASS_LEADERSHIP(:I$EMPLOYEE_ID, NULL, :I$USER_ID);
    EXECUTE PROCEDURE DROP_TEACHING_LOADS(:I$EMPLOYEE_ID, NULL);
  END
  ELSE
  BEGIN
    -- Проверки перед увольнением на классное руководство и педагогическую нагрузку
    SELECT COUNT(*) FROM PARAGRAF_EMPLOYEE_CANBE_FIRED(:I$EMPLOYEE_ID, 1) INTO :V$LINK_ID;
  END

  -- Тут удалится все, включая преподавателей объединений УДОД
  UPDATE LINKS
  SET DATE_DEL = :I$LEAVEDATE
  WHERE OBJ_ID = :I$EMPLOYEE_ID AND DATE_DEL IS NULL;

  -- Очищаем статус сотрудника
  UPDATE VALL
  SET IS_DEL = 1, DATE_MODIFY = CURRENT_TIMESTAMP
  WHERE OBJ_ID = :I$EMPLOYEE_ID AND PARAM_ID = 274 AND IS_DEL = 0;

  -- Отменяем наставничество в обе стороны
  FOR
    SELECT L397.OBJ_ID
    FROM LINKS L397
    LEFT JOIN VALD V2989 ON V2989.OBJ_ID = L397.OBJ_ID AND V2989.PARAM_ID = 2989 AND V2989.IS_DEL = 0
    WHERE L397.PARENT_ID = :I$EMPLOYEE_ID AND L397.OBJ_TYPE_ID = 397 AND L397.DATE_DEL IS NULL AND (V2989.VAL IS NULL OR V2989.VAL > :I$LEAVEDATE)
    INTO :V$LINK_ID
  DO
  BEGIN
    SELECT BLOB_ID FROM VAL_ADD(2989, :V$LINK_ID, :I$LEAVEDATE) INTO :V$BLOB_ID;
  END

  FOR
    SELECT V2985.OBJ_ID
    FROM VALR V2985
    JOIN LINKS LP14 ON LP14.OBJ_ID = V2985.OBJ_ID AND LP14.PARENT_TYPE_ID = 14 AND LP14.DATE_DEL IS NULL
    LEFT JOIN VALD V2989 ON V2989.OBJ_ID = V2985.OBJ_ID AND V2989.PARAM_ID = 2989 AND V2989.IS_DEL = 0
    WHERE V2985.PARAM_ID = 2985 AND V2985.VAL = :I$EMPLOYEE_ID AND V2985.IS_DEL = 0 AND (V2989.VAL IS NULL OR V2989.VAL > :I$LEAVEDATE)
    INTO :V$LINK_ID
  DO
  BEGIN
    SELECT BLOB_ID FROM VAL_ADD(2989, :V$LINK_ID, :I$LEAVEDATE) INTO :V$BLOB_ID;
  END

  -- Создаем линк в уволенных
  FOR
    SELECT LINK_ID
    FROM OBJECT_ADD_LINK(:V$LEAVED_EMPLOYEE_ID, :I$EMPLOYEE_ID, 14)
    INTO :V$LINK_ID
  DO
  BEGIN
    UPDATE LINKS
    SET DATE_INS = :I$LEAVEDATE
    WHERE LINK_ID = :V$LINK_ID;
    
    IF ((SELECT I FROM VAL_GET(:V$SCHOOL_ID, 1369)) = :I$EMPLOYEE_ID) THEN
      SELECT BLOB_ID FROM VAL_ADD(1369, :V$SCHOOL_ID, :I$EMPLOYEE_ID, NULL, 1) INTO :V$BLOB_ID;
  END

  --Увольняем со вcех должностей
  FOR
    SELECT L15.OBJ_ID
    FROM LINKS L15
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
    WHERE L15.PARENT_ID = :I$EMPLOYEE_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL AND (V74.VAL IS NULL OR V74.VAL > CURRENT_DATE)
    INTO :V$MOVEMENT_ID
  DO
  BEGIN
    SELECT BLOB_ID FROM VAL_ADD(74, :V$MOVEMENT_ID, :I$LEAVEDATE) INTO :V$BLOB_ID;
    SELECT BLOB_ID FROM VAL_ADD(456, :V$MOVEMENT_ID, :I$LEAVEORDERDATE) INTO :V$BLOB_ID;
    SELECT BLOB_ID FROM VAL_ADD(457, :V$MOVEMENT_ID, :I$LEAVEORDERNUMBER) INTO :V$BLOB_ID;

    -- удалено
    -- SELECT BLOB_ID FROM VAL_ADD(459, :V$MOVEMENT_ID, :I$LEAVETARGET) INTO :V$BLOB_ID;

    SELECT BLOB_ID FROM VAL_ADD(458, :V$MOVEMENT_ID, CAST(:I$LEAVEBASEMENT AS VARCHAR(4000))) INTO :V$BLOB_ID;

    IF (I$LEAVEREASON IS NOT NULL) THEN
      SELECT BLOB_ID FROM VAL_ADD(461, :V$MOVEMENT_ID, CAST(:I$LEAVEREASON AS VARCHAR(4000))) INTO :V$BLOB_ID;

    --найдем должность, связанную с увольнением, чтобы вызвать пересчет свободных ставок
    V$BLOB_ID = NULL;
    SELECT FIRST 1 L15.PARENT_ID
    FROM LINKS L15
    WHERE L15.OBJ_ID = :V$MOVEMENT_ID AND L15.PARENT_TYPE_ID = 13 AND L15.DATE_DEL IS NULL
    INTO :V$BLOB_ID;
    IF (V$BLOB_ID IS NOT NULL) THEN
    BEGIN
      EXECUTE PROCEDURE CALC_JOB_OCCUPIED(:V$BLOB_ID, :I$USER_ID, COALESCE(:I$PARENT_ID, :V$SCHOOL_ID));
    END
  END

  -- Закрытие стажа = :I$LEAVEDATE
  FOR
    SELECT L85.OBJ_ID
    FROM LINKS L85
    LEFT JOIN VALD VD ON VD.PARAM_ID = 467 AND VD.OBJ_ID = L85.OBJ_ID AND VD.IS_DEL = 0
    WHERE L85.PARENT_ID = :I$EMPLOYEE_ID AND L85.DATE_DEL IS NULL AND L85.OBJ_TYPE_ID = 85 AND VD.VAL IS NULL
    INTO :V$BLOB_ID
  DO
  BEGIN
    -- пускай пока остается прямая запись
    UPDATE OR INSERT INTO VALD (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
    VALUES (467, :V$BLOB_ID, NULL, 0, :I$LEAVEDATE);
  END

  -- Вносим изменения в пользователей
  UPDATE USERS
  SET DATE_DEL = CURRENT_TIMESTAMP
  WHERE OBJ_ID = :I$EMPLOYEE_ID AND DATE_DEL IS NULL;

  -- Удаляем доступ к журналам
  FOR
    SELECT U.USER_ID
    FROM USERS U
    WHERE U.OBJ_ID = :I$EMPLOYEE_ID
    INTO :V$BLOB_ID
  DO
  BEGIN
    UPDATE CJ2_JOURNAL_USERS U
    SET DATE_DEL = CURRENT_TIMESTAMP
    WHERE U.DATE_DEL IS NULL AND U.USER_ID = :V$BLOB_ID;
    UPDATE CJ2_JOURNAL_AUTOUSERS U
    SET DATE_DEL = CURRENT_TIMESTAMP
    WHERE U.DATE_DEL IS NULL AND U.USER_ID = :V$BLOB_ID;
  END

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_EMPLOYEE_LEAVE_CHANGES
AS
DECLARE VARIABLE V$IDLEAVE BIGINT;
DECLARE VARIABLE V$LEAVEDATE DATE;
DECLARE VARIABLE V$MOVEMENT_ID BIGINT;
BEGIN
    FOR SELECT L14.OBJ_ID
        FROM LINKS L2
        JOIN LINKS L84 ON L2.OBJ_ID = L84.PARENT_ID
        JOIN LINKS L14 ON L84.OBJ_ID = L14.PARENT_ID
        WHERE L2.PARENT_ID IS NULL
          AND L2.OBJ_TYPE_ID = 2
          AND L84.OBJ_TYPE_ID = 84
          AND L84.DATE_DEL IS NULL
          AND L14.OBJ_TYPE_ID = 14
          AND L14.DATE_DEL IS NULL
        INTO :V$IDLEAVE
    DO
    BEGIN
        SELECT MAX(V74.VAL)
        FROM LINKS L15
        INNER JOIN VALD V74 ON L15.OBJ_ID = V74.OBJ_ID
        WHERE L15.OBJ_TYPE_ID = 15
          AND L15.DATE_DEL IS NULL
          AND L15.PARENT_ID = :V$IDLEAVE
          AND V74.PARAM_ID = 74
          AND V74.IS_DEL = 0
        INTO :V$LEAVEDATE;

        IF (V$LEAVEDATE IS NOT NULL) THEN
        BEGIN
            FOR SELECT L85.OBJ_ID
                FROM LINKS L85
                INNER JOIN VALD V466 ON V466.OBJ_ID = L85.OBJ_ID
                LEFT JOIN VALD V467 ON V467.PARAM_ID = 467 AND V467.OBJ_ID = L85.OBJ_ID AND V467.IS_DEL = 0
                WHERE L85.PARENT_ID = :V$IDLEAVE
                  AND L85.DATE_DEL IS NULL
                  AND L85.OBJ_TYPE_ID = 85
                  AND V466.PARAM_ID = 466
                  AND V466.IS_DEL = 0
                  AND V466.VAL < :V$LEAVEDATE
                  AND V467.VAL IS NULL
                INTO :V$MOVEMENT_ID
            DO
            BEGIN
                UPDATE OR INSERT INTO VALD (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
                VALUES (467, :V$MOVEMENT_ID, NULL, 0, :V$LEAVEDATE);
            END
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_EMPLOYEE_LIST (
    I$HAS_VACANCY SMALLINT = 1,
    I$USER_ID BIGINT = null)
RETURNS (
    OBJ_ID BIGINT,
    OBJ_CAPTION VARCHAR(4000))
AS
BEGIN
    FOR
        SELECT L14.OBJ_ID
        FROM LINKS L14
        WHERE L14.DATE_DEL IS NULL AND L14.OBJ_TYPE_ID = 14
        INTO :OBJ_ID
    DO
    BEGIN
        IF ((I$HAS_VACANCY <> 1) OR
            EXISTS(
                SELECT FIRST 1 1
                FROM LINKS L15
                LEFT JOIN VAL_GET(L15.OBJ_ID, 73, 0, :I$USER_ID) VD_IN ON 1=1
                LEFT JOIN VAL_GET(L15.OBJ_ID, 74, 0, :I$USER_ID) VD_OUT ON 1=1
                WHERE L15.PARENT_ID = :OBJ_ID AND L15.DATE_DEL IS NULL AND L15.OBJ_TYPE_ID = 15
                   AND (VD_IN.D IS NOT NULL AND (CURRENT_TIMESTAMP >= VD_IN.D))
                   AND (VD_OUT.D IS NULL OR (CURRENT_TIMESTAMP < VD_OUT.D))
            )
        ) THEN
        BEGIN
            SELECT CAPTION FROM OBJECT_CAPTION_GET(:OBJ_ID) INTO :OBJ_CAPTION;
            SUSPEND;
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_EMPLOYEE_SENIORITY_ADD (
    I$CAPTION VARCHAR(4000),
    I$LANG_CODE CHAR(2))
RETURNS (
    LISTVAL_ID BIGINT,
    PARAM_ID BIGINT)
AS
BEGIN
    LISTVAL_ID = NULL;
    PARAM_ID = NULL;
    FOR
        SELECT LISTVAL_ID
        FROM LISTVAL_ADD(NULL,131,NULL,:I$LANG_CODE,NULL,:I$CAPTION,'','','',0,0)
        INTO :LISTVAL_ID
    DO
    BEGIN
        FOR
            SELECT PARAM_ID
            FROM PARAM_ADD(NULL,14,19,131,:LISTVAL_ID,16,0,0,0,0,NULL,NULL,NULL,NULL,'2','','',0,0,0,'',:I$LANG_CODE,:I$CAPTION,'','','',0,0)
            INTO :PARAM_ID
        DO
        BEGIN
            INSERT INTO LPARAMS(LEVEL_ID, PARAM_ID, EDIT_TYPE, IS_DEL)
            SELECT LEVEL_ID, :PARAM_ID, EDIT_TYPE, 0
            FROM LPARAMS WHERE PARAM_ID=462;
        END
    END
    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_EMPLOYEE_SENIORITY_DEL (
    SENIORITY_TYPE BIGINT)
AS
BEGIN
    UPDATE PARAMS P
    SET P.IS_DEL=1
    WHERE P.TYPE_ID = 14
    AND P.IS_DEL=0
    AND P.PARAM_TYPE = 19
    AND P.LIST_ID = 131
    AND P.AUTO_LISTVAL_ID = :SENIORITY_TYPE;

    UPDATE LISTVALS L SET L.IS_DEL=1 WHERE L.LISTVAL_ID = :SENIORITY_TYPE;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_EMPLOYEE_SENIORITY_LST (
    I$EMPLOYEE_ID BIGINT,
    I$CURRENT_DATE DATE = null,
    I$USER_ID BIGINT = null)
RETURNS (
    SENIORITY_ID BIGINT,
    SENIORITY_TYPE BIGINT,
    SENIORITY_TYPE_CAPTION VARCHAR(4000),
    SENIORITY_FROM DATE,
    SENIORITY_TO DATE,
    DAYS360_COUNT INTEGER)
AS
declare variable V$SENIORITY_TO date;
declare variable LANG_CODE varchar(2);
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :LANG_CODE;

    FOR
        SELECT L85.OBJ_ID,
               V465.LISTVAL_ID

        FROM LINKS L85

        LEFT JOIN VALL V465
        ON V465.OBJ_ID = L85.OBJ_ID
        AND V465.PARAM_ID = 465
        AND V465.IS_DEL = 0

        WHERE L85.PARENT_ID = :I$EMPLOYEE_ID
        AND L85.OBJ_TYPE_ID = 85
        AND L85.DATE_DEL IS NULL

        INTO :SENIORITY_ID, :SENIORITY_TYPE
    DO
    BEGIN
        IF (SENIORITY_TYPE > 0) THEN
        BEGIN
            SELECT R.VAL
            FROM LISTVALS LV

            LEFT JOIN RES_GET(LV.RES_ID,  :LANG_CODE) R ON 1=1

            WHERE LV.LISTVAL_ID = :SENIORITY_TYPE
            INTO :SENIORITY_TYPE_CAPTION;
        END

        SELECT D
        FROM VAL_GET(:SENIORITY_ID, 466, 0, :I$USER_ID)
        INTO :SENIORITY_FROM;

        IF (SENIORITY_FROM < '01.01.1900') THEN
        BEGIN
            SENIORITY_FROM = NULL;
        END

        SELECT D
        FROM VAL_GET(:SENIORITY_ID, 467, 0, :I$USER_ID)
        INTO :SENIORITY_TO;

        IF (SENIORITY_TO < '01.01.1900') THEN
        BEGIN
            SENIORITY_TO = NULL;
        END

        IF (SENIORITY_TO IS NULL) THEN
        BEGIN
            V$SENIORITY_TO = I$CURRENT_DATE;
        END
        ELSE
        BEGIN
            V$SENIORITY_TO = SENIORITY_TO;
        END

        SELECT DAYS360_COUNT
        FROM GET_DAYS360_COUNT(:SENIORITY_FROM, :V$SENIORITY_TO)
        INTO :DAYS360_COUNT;

        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_EMPLOYEE_VACANCY_ADD (
    I$MOVEMENT_ID BIGINT,
    I$SCHOOL_ID BIGINT,
    I$EMPLOYEE_ID BIGINT,
    I$VACANCY_ID BIGINT,
    I$RATECOUNT DOUBLE PRECISION,
    I$VACANCY_TYPE BIGINT,
    I$ACCEPTEDDATE DATE,
    I$ORDERDATE DATE,
    I$ORDERNUMBER VARCHAR(100),
    I$CONTRACTTO DATE,
    I$ACCEPTCONDITION BIGINT,
    I$CONTRACT_NUMBER VARCHAR(255),
    I$CONTRACT_DATE DATE,
    I$CATEGORY BIGINT,
    I$BOOK_NAME VARCHAR(1000) = NULL,
    I$USER_ID VARCHAR(40) = NULL)
RETURNS (
    NEED_REFRESH_TREE SMALLINT,
    MOVEMENT_ID BIGINT)
AS
DECLARE VARIABLE V$DEL_COUNT INTEGER;
DECLARE VARIABLE V$TYPE_ID BIGINT;
DECLARE VARIABLE V$BLOB_ID BIGINT;
DECLARE VARIABLE V$MOVEMENT_ID BIGINT;
DECLARE VARIABLE V$LEAVEDATE DATE;
DECLARE VARIABLE V$OLD_D1 DATE;
DECLARE VARIABLE V$OLD_D2 DATE;
DECLARE VARIABLE V$OLD_VR DOUBLE PRECISION;
DECLARE VARIABLE V$OLD_TERMS BIGINT;
DECLARE VARIABLE V$STATUS BIGINT;
DECLARE VARIABLE V$LEAVED_FOLDER BIGINT;
DECLARE VARIABLE V$ID BIGINT;
DECLARE VARIABLE S VARCHAR(500);
BEGIN

  NEED_REFRESH_TREE = 0;

  IF(I$RATECOUNT IS NULL OR I$RATECOUNT <= 0) THEN EXCEPTION DATA_ERROR 'Количество ставок должно быть положительным';
  IF(I$CATEGORY IS NULL OR I$CATEGORY <= 0) THEN
  BEGIN
    SELECT VAL FROM DO_FUNC(:I$VACANCY_ID, 400) INTO :S;
    IF (S = 'Да') THEN EXCEPTION DATA_ERROR 'Не указана квалификационная категория';
    ELSE I$CATEGORY = 632; -- Без категории
    S = NULL;
  END

  -- Название должности является обязательным в S-Параграфе
  -- но если не ввели вовсе - ставим название идентично должности, пусть сами разбираются
  I$BOOK_NAME = TRIM(I$BOOK_NAME);
  IF(I$BOOK_NAME IS NULL OR I$BOOK_NAME = '') THEN
    SELECT FIRST 1 V66.VAL
    FROM VALS V66
    WHERE V66.OBJ_ID = :I$VACANCY_ID AND V66.PARAM_ID = 66 AND V66.IS_DEL = 0
    INTO :I$BOOK_NAME;

  -- Если ОУ не передали - берем из должности
  IF(I$SCHOOL_ID IS NULL) THEN
  BEGIN
    SELECT FIRST 1 LP.PARENT_ID
    FROM LINKS LP
    WHERE LP.OBJ_ID = :I$VACANCY_ID AND LP.PARENT_TYPE_ID IN (2, 211) AND LP.DATE_DEL IS NULL
    INTO :I$SCHOOL_ID;
  END

  SELECT FIRST 1 TYPE_ID
  FROM OBJECTS
  WHERE OBJ_ID = :I$SCHOOL_ID
  INTO :V$TYPE_ID;

  IF(V$TYPE_ID = 84) THEN
  BEGIN
    V$BLOB_ID = I$SCHOOL_ID;
    SELECT FIRST 1 OBJ_ID
    FROM OBJECT_PARENTS_GET(:V$BLOB_ID, 2)
    INTO :I$SCHOOL_ID;
  END

  -- Сотрудник в папке уволенных ?
  SELECT FIRST 1 LP84.PARENT_ID
  FROM LINKS LP84
  WHERE LP84.OBJ_ID = :I$EMPLOYEE_ID AND LP84.PARENT_TYPE_ID = 84 AND LP84.DATE_DEL IS NULL
  INTO :V$LEAVED_FOLDER;

  -- Если операция - редактирование существующей вакансии, выполняем проверку количества ставок только при ключевых изменениях
  IF(I$MOVEMENT_ID IS NOT NULL) THEN
  BEGIN
    -- Дата приема, дата увольнения, кол-во ставок, условия приема
    SELECT V73.VAL, V74.VAL, V71.VAL, V587.LISTVAL_ID
    FROM LINKS L14_15
    JOIN VALD V73 ON V73.OBJ_ID = L14_15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L14_15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
    JOIN VALF V71 ON V71.OBJ_ID = L14_15.OBJ_ID AND V71.PARAM_ID = 71 AND V71.IS_DEL = 0
    JOIN VALL V587 ON V587.OBJ_ID = L14_15.OBJ_ID AND V587.PARAM_ID = 587 AND V587.IS_DEL = 0
    WHERE L14_15.PARENT_ID = :I$EMPLOYEE_ID AND L14_15.OBJ_ID = :I$MOVEMENT_ID AND L14_15.DATE_DEL IS NULL
    INTO :V$OLD_D1, :V$OLD_D2, :V$OLD_VR, :V$OLD_TERMS;

    -- Если что-то поменялось, перепроверяем
    IF(V$OLD_D1 <> I$ACCEPTEDDATE OR V$OLD_D2 IS NOT NULL OR V$OLD_VR <> I$RATECOUNT OR V$OLD_TERMS <> I$ACCEPTCONDITION) THEN
    BEGIN
      EXECUTE PROCEDURE PARAGRAF_VACANCY_VERIFY(:I$SCHOOL_ID, :I$EMPLOYEE_ID, :I$VACANCY_ID, :I$MOVEMENT_ID, :I$RATECOUNT, I$ACCEPTCONDITION);
    END

    -- При редактировании назначения на должность необходимо внести изменения в соотвествующий приказ
    -- найдем этот приказ (по сотруднику и должности), его тип и id строки приказа
    V$TYPE_ID = NULL;
    V$BLOB_ID = NULL;
    SELECT FIRST 1 D.OBJ_ID, D.TYPE_ID, OD.OBJ_ID
    FROM ORDER_DATA OD
    JOIN ORDERS D ON D.OBJ_ID = OD.ORDER_ID
    WHERE OD.DATE_DEL IS NULL AND OD.REF_ID = :I$EMPLOYEE_ID AND OD.JOB_ID = :I$VACANCY_ID
    ORDER BY D.DATE_ADD DESC
    INTO :V$BLOB_ID, :V$TYPE_ID, :V$ID;

    -- запишем изменения по должности в приказ - для старых приказа может не быть
    IF (V$BLOB_ID IS NOT NULL) THEN
    SELECT 1 FROM ORDER_SET_ROW(:V$BLOB_ID, :V$ID, :I$USER_ID, 0, :I$EMPLOYEE_ID, NULL, 1, NULL, NULL,
      ',' || ',' || :I$VACANCY_TYPE || ',' || CAST(:I$RATECOUNT AS NUMERIC(18, 2)) || ',' || :I$ACCEPTCONDITION || ',' || COALESCE(:I$CATEGORY, 632) || ',' ||
      COALESCE(:I$CONTRACT_NUMBER, '') || ',' || COALESCE((SELECT RESULT FROM DATE2STR(:I$CONTRACT_DATE)), '') || ',' || COALESCE((SELECT RESULT FROM DATE2STR(:I$CONTRACTTO)), '') ||
      ',' || COALESCE(:I$BOOK_NAME, ''), :I$VACANCY_ID, :I$VACANCY_ID)
    INTO :V$BLOB_ID;
  END
  ELSE
  BEGIN
    EXECUTE PROCEDURE PARAGRAF_VACANCY_VERIFY(:I$SCHOOL_ID, :I$EMPLOYEE_ID, :I$VACANCY_ID, :I$MOVEMENT_ID, :I$RATECOUNT, I$ACCEPTCONDITION);
  END

  IF (I$MOVEMENT_ID IS NULL) THEN
  BEGIN
    SELECT OBJ_ID
    FROM OBJECT_ADD(:I$EMPLOYEE_ID, 15)
    INTO :I$MOVEMENT_ID;
  END

  -- Если сотрудник принимается из уволенных, убираем его из уволенных и помещаем в основной список
  -- а также восстанавливаем статус длительного отпуска (если нет отпусков, ставим РАБОТАЮЩИЙ)
  IF(V$LEAVED_FOLDER IS NOT NULL) THEN
  BEGIN
    SELECT OBJ_ID
    FROM OBJECT_ADD_LINK(:I$SCHOOL_ID, :I$EMPLOYEE_ID, 14)
    INTO :I$EMPLOYEE_ID;

    SELECT DEL_COUNT
    FROM OBJECT_DEL(:V$LEAVED_FOLDER, :I$EMPLOYEE_ID)
    INTO :V$DEL_COUNT;

    SELECT FIRST 1 V2859.LISTVAL_ID
    FROM LINKS L376
    JOIN VALD V2860 ON V2860.OBJ_ID = L376.OBJ_ID AND V2860.PARAM_ID = 2860 AND V2860.IS_DEL = 0
    -- Выбираем только незакрытые отпуска
    LEFT JOIN VALD V2864 ON V2864.OBJ_ID = L376.OBJ_ID AND V2864.PARAM_ID = 2864 AND V2864.IS_DEL = 0
    JOIN VALL V2859 ON V2859.OBJ_ID = L376.OBJ_ID AND V2859.PARAM_ID = 2859 AND V2859.IS_DEL = 0
    WHERE L376.PARENT_ID = :I$EMPLOYEE_ID AND L376.OBJ_TYPE_ID = 376 AND L376.DATE_DEL IS NULL AND V2864.VAL IS NULL
    ORDER BY V2860.VAL DESC
    INTO :V$STATUS;

    IF(V$STATUS IS NULL) THEN V$STATUS = 602;
    SELECT BLOB_ID FROM VAL_ADD(274, :I$EMPLOYEE_ID, :V$STATUS) INTO :V$BLOB_ID;

    NEED_REFRESH_TREE = 1;
  END

  SELECT D
  FROM VAL_GET(:I$MOVEMENT_ID, 74)
  INTO :V$LEAVEDATE;

  IF (I$VACANCY_TYPE = 934 AND V$LEAVEDATE IS NULL) THEN
  BEGIN
    -- если сотрудник принимается на основную должность, то все остальные действующие должности переводим в дополнительные
    FOR
      SELECT O.OBJ_ID
      FROM LINKS L
      LEFT JOIN VALD V74 ON V74.OBJ_ID = L.OBJ_ID AND V74.PARAM_ID = 74
      JOIN OBJECTS O ON O.OBJ_ID = L.OBJ_ID AND O.TYPE_ID = 15 AND O.OBJ_ID <> :I$MOVEMENT_ID
      WHERE L.PARENT_ID = :I$EMPLOYEE_ID AND L.DATE_DEL IS NULL AND (V74.IS_DEL = 0 AND V74.VAL IS NULL)
      INTO :V$MOVEMENT_ID
    DO
    BEGIN
      SELECT BLOB_ID
      FROM VAL_ADD(72, :V$MOVEMENT_ID, 935)
      INTO :V$BLOB_ID;
    END
  END

  SELECT BLOB_ID
  FROM VAL_ADD(587, :I$MOVEMENT_ID, :I$ACCEPTCONDITION)
  INTO :V$BLOB_ID;

  SELECT BLOB_ID
  FROM VAL_ADD(453, :I$MOVEMENT_ID, :I$SCHOOL_ID)
  INTO :V$BLOB_ID;

  SELECT BLOB_ID
  FROM VAL_ADD(69, :I$MOVEMENT_ID, :I$VACANCY_ID)
  INTO :V$BLOB_ID;

  SELECT BLOB_ID
  FROM VAL_ADD(3543, :I$MOVEMENT_ID, :I$BOOK_NAME)
  INTO :V$BLOB_ID;

  SELECT BLOB_ID
  FROM VAL_ADD(71, :I$MOVEMENT_ID, :I$RATECOUNT)
  INTO :V$BLOB_ID;

  SELECT BLOB_ID
  FROM VAL_ADD(72, :I$MOVEMENT_ID, :I$VACANCY_TYPE)
  INTO :V$BLOB_ID;

  SELECT BLOB_ID
  FROM VAL_ADD(1790, :I$MOVEMENT_ID, :I$CATEGORY)
  INTO :V$BLOB_ID;

  UPDATE OR INSERT INTO VALD (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
  VALUES (73, :I$MOVEMENT_ID, NULL, 0, :I$ACCEPTEDDATE);

  UPDATE OR INSERT INTO VALD (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
  VALUES (454, :I$MOVEMENT_ID, NULL, 0, :I$ORDERDATE);

  IF (I$CONTRACTTO IS NOT NULL) THEN
  BEGIN
    UPDATE OR INSERT INTO VALD (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
    VALUES (583, :I$MOVEMENT_ID, NULL, 0, :I$CONTRACTTO);
  END
  ELSE
  BEGIN
    UPDATE VALD
    SET IS_DEL = 1
    WHERE PARAM_ID = 583 AND OBJ_ID = :I$MOVEMENT_ID;
  END

  SELECT BLOB_ID
  FROM VAL_ADD(455, :I$MOVEMENT_ID, :I$ORDERNUMBER)
  INTO :V$BLOB_ID;

  IF (I$CONTRACT_DATE IS NOT NULL) THEN
  BEGIN
    UPDATE OR INSERT INTO VALD (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
    VALUES (1639, :I$MOVEMENT_ID, NULL, 0, :I$CONTRACT_DATE);
  END
  ELSE
  BEGIN
    UPDATE VALD
    SET IS_DEL = 1
    WHERE PARAM_ID = 1639 AND OBJ_ID = :I$MOVEMENT_ID;
  END

  SELECT BLOB_ID
  FROM VAL_ADD(1638, :I$MOVEMENT_ID, :I$CONTRACT_NUMBER)
  INTO :V$BLOB_ID;

  -- Сотрудник является педагогом (988)
  V$ID = 0;
  SELECT X FROM IS_TEACHER(:I$EMPLOYEE_ID) INTO :V$ID;
  UPDATE OR INSERT INTO VALL(PARAM_ID, OBJ_ID, USER_ID, IS_DEL, LISTVAL_ID)
  VALUES (988, :I$EMPLOYEE_ID, NULL, 0, IIF(:V$ID = 1, 2, 3));

  -- Должность является педагогической (2444)
  S = '';
  SELECT VAL FROM DO_FUNC(:I$MOVEMENT_ID, 2444) INTO :S;
  UPDATE OR INSERT INTO VALL(PARAM_ID, OBJ_ID, USER_ID, IS_DEL, LISTVAL_ID)
  VALUES (2444, :I$MOVEMENT_ID, NULL, 0, IIF(:S = 'Да', 2, 3));

  -- Пересчет категории по сотруднику
  EXECUTE PROCEDURE VACANCY_UPDATE_CAT(:I$EMPLOYEE_ID);

  -- Вызваем пересчет свободных ставок
  EXECUTE PROCEDURE CALC_JOB_OCCUPIED(:I$VACANCY_ID);

  MOVEMENT_ID = I$MOVEMENT_ID;
  SUSPEND;

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_EMPLOYEE_VACANCY_GET (
    I$MOVEMENT_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    VACANCY_ID BIGINT,
    VACANCY_CAPTION VARCHAR(4000),
    RATECOUNT DOUBLE PRECISION,
    FREERATECOUNT DOUBLE PRECISION,
    FREERATE_CHECK INTEGER,
    VACANCY_TYPE BIGINT,
    VACANCY_TYPE_CAPTION VARCHAR(4000),
    ACCEPTEDDATE DATE,
    ORDERDATE DATE,
    ORDERNUMBER VARCHAR(100),
    CONTRACTTO DATE,
    ACCEPTCONDITION BIGINT,
    ACCEPTCONDITION_CAPTION VARCHAR(4000),
    CATEGORY BIGINT,
    CATEGORY_CAPTION VARCHAR(1000),
    CONTRACTNUMBER VARCHAR(100),
    CONTRACTDATE DATE)
AS
declare variable V$MOVEMENT_ID bigint;
declare variable V$LEAVEDATE date;
declare variable V$RC double precision;
BEGIN
    FREERATECOUNT = 0;
    FOR
        SELECT I
        FROM VAL_GET(:I$MOVEMENT_ID, 69, 0, :I$USER_ID)
        INTO :VACANCY_ID
    DO
    BEGIN
        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:VACANCY_ID)
        INTO :VACANCY_CAPTION;

        SELECT F, IS_EXISTS
        FROM VAL_GET(:VACANCY_ID, 62, 0, :I$USER_ID)
        INTO :FREERATECOUNT, :FREERATE_CHECK;

        IF (:FREERATE_CHECK = 1) THEN
        BEGIN
            /* for teacher the param "stavok" not visible*/
            SELECT COALESCE((
                SELECT FIRST 1 0
                FROM LISTVALS LV
                WHERE LV.LISTVAL_ID = VG.I AND LV.TAG = 'U' AND LV.LISTVAL_ID <> 121), 1)
            FROM VAL_GET(:VACANCY_ID, 58) VG
            INTO :FREERATE_CHECK;
        END

        FOR
            SELECT L.OBJ_ID
            FROM LINKS L
            JOIN OBJECTS O ON O.OBJ_ID = L.OBJ_ID AND O.TYPE_ID = 15
            WHERE L.PARENT_ID = :VACANCY_ID AND L.DATE_DEL IS NULL
            INTO :V$MOVEMENT_ID
        DO
        BEGIN
            FOR
                SELECT D
                FROM VAL_GET(:V$MOVEMENT_ID, 74, 0, :I$USER_ID)
                INTO :V$LEAVEDATE
            DO
            BEGIN
                IF (V$LEAVEDATE IS NULL) THEN
                BEGIN
                    FOR
                        SELECT F
                        FROM VAL_GET(:V$MOVEMENT_ID, 71, 0, :I$USER_ID)
                        INTO :V$RC
                    DO
                    BEGIN
                        FREERATECOUNT = FREERATECOUNT - V$RC;
                    END
                END
            END
        END
    END

    SELECT F
    FROM VAL_GET(:I$MOVEMENT_ID, 71, 0, :I$USER_ID)
    INTO :RATECOUNT;

    SELECT I,V
    FROM VAL_GET(:I$MOVEMENT_ID, 72, 0, :I$USER_ID)
    INTO :VACANCY_TYPE,VACANCY_TYPE_CAPTION;

    SELECT I,V
    FROM VAL_GET(:I$MOVEMENT_ID, 587, 0, :I$USER_ID)
    INTO :ACCEPTCONDITION,ACCEPTCONDITION_CAPTION;

    SELECT D
    FROM VAL_GET(:I$MOVEMENT_ID, 73, 0, :I$USER_ID)
    INTO :ACCEPTEDDATE;

    SELECT D
    FROM VAL_GET(:I$MOVEMENT_ID, 454, 0, :I$USER_ID)
    INTO :ORDERDATE;

    SELECT V
    FROM VAL_GET(:I$MOVEMENT_ID, 455, 0, :I$USER_ID)
    INTO :ORDERNUMBER;

    SELECT D
    FROM VAL_GET(:I$MOVEMENT_ID, 583, 0, :I$USER_ID)
    INTO :CONTRACTTO;

    SELECT I,V
    FROM VAL_GET(:I$MOVEMENT_ID, 1790, 0, :I$USER_ID)
    INTO :CATEGORY,:CATEGORY_CAPTION;

    SELECT D
    FROM VAL_GET(:I$MOVEMENT_ID, 1639, 0, :I$USER_ID)
    INTO :CONTRACTDATE;

    SELECT V
    FROM VAL_GET(:I$MOVEMENT_ID, 1638, 0, :I$USER_ID)
    INTO :CONTRACTNUMBER;

    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_EMPLOYEE_VACANCY_LEAVE (
    I$MOVEMENT_ID BIGINT NOT NULL,
    I$LEAVEDATE DATE,
    I$LEAVEORDERNUMBER VARCHAR(4000) NOT NULL,
    I$LEAVEORDERDATE DATE NOT NULL,
    I$LEAVEREASON BIGINT,
    I$LEAVEBASEMENT BIGINT,
    I$USER_ID BIGINT = NULL,
    I$NEW_JOB_ID BIGINT = NULL,
    I$RELEASE SMALLINT = 0)
AS
DECLARE VARIABLE V$BLOB_ID BIGINT;
DECLARE VARIABLE V$UNION_ID BIGINT;
DECLARE VARIABLE V$EMPLOYEE_ID BIGINT;
DECLARE VARIABLE V$TEACHING_IS_LEFT SMALLINT;
DECLARE VARIABLE V$POST_IS_LEFT SMALLINT;
DECLARE VARIABLE V$DIVISION_POST_IS_LEFT INTEGER;
BEGIN
  IF (I$RELEASE IS NULL OR I$RELEASE < 0) THEN I$RELEASE = 0;
  IF (I$NEW_JOB_ID IS NULL) then I$NEW_JOB_ID = 0;
  IF (I$LEAVEDATE IS NULL) THEN EXCEPTION DATA_ERROR 'Не указана дата увольнения';

  SELECT FIRST 1 LP14.PARENT_ID, LPP.PARENT_ID
  FROM LINKS LP14
  JOIN LINKS LP13 ON LP13.OBJ_ID = LP14.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
  JOIN LINKS LPP ON LPP.OBJ_ID = LP13.PARENT_ID AND LPP.PARENT_TYPE_ID IN (2, 211) AND LPP.DATE_DEL IS NULL
  WHERE LP14.OBJ_ID = :I$MOVEMENT_ID AND LP14.PARENT_TYPE_ID = 14 AND LP14.DATE_DEL IS NULL
  INTO :V$EMPLOYEE_ID, :V$UNION_ID;            -- сотрудник и подразделение

  IF(V$EMPLOYEE_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Сотрудник или должность не найдены';

  -- проверяем увольняется ли с последней должности в школе, в подразделении, и остается ли педагогическая должность вообще (c учетом перевода)
  SELECT TEACHING_IS_LEFT, POST_IS_LEFT, DIVISION_POST_IS_LEFT
  FROM CHECK_EMPLOYEE_TEACHING_IS_LEFT(:I$MOVEMENT_ID, :V$EMPLOYEE_ID, :V$UNION_ID, :I$NEW_JOB_ID)
  INTO :V$TEACHING_IS_LEFT, :V$POST_IS_LEFT, :V$DIVISION_POST_IS_LEFT;

  IF (V$POST_IS_LEFT = 0) THEN
  -- Если это последняя и не перевод на другую должность - отрабатываем как полное увольнение
  BEGIN
    EXECUTE PROCEDURE PARAGRAF_EMPLOYEE_LEAVE(:V$UNION_ID, :V$EMPLOYEE_ID, :I$LEAVEDATE, :I$LEAVEORDERNUMBER, :I$LEAVEORDERDATE, :I$LEAVEREASON, :I$LEAVEBASEMENT, :I$USER_ID, :I$RELEASE);
    EXIT;
  END

  IF (I$RELEASE = 1) THEN
  BEGIN  -- снимаем классное руководства и нагрузки при явном указании --Redmine #1063
    EXECUTE PROCEDURE DROP_CLASS_LEADERSHIP(:V$EMPLOYEE_ID, NULL, :I$USER_ID);
    EXECUTE PROCEDURE DROP_TEACHING_LOADS(:V$EMPLOYEE_ID, NULL);
  END
  ELSE IF (V$TEACHING_IS_LEFT = 0) THEN
  BEGIN
    SELECT COUNT(*)
    FROM PARAGRAF_EMPLOYEE_CANBE_FIRED(:V$EMPLOYEE_ID, 1)
    INTO :V$BLOB_ID;
  END

  -- заполняем дату увольнения, дату и номер приказа на увольнение
  SELECT BLOB_ID FROM VAL_ADD(74, :I$MOVEMENT_ID, :I$LEAVEDATE) INTO :V$BLOB_ID;
  SELECT BLOB_ID FROM VAL_ADD(456, :I$MOVEMENT_ID, :I$LEAVEORDERDATE) INTO :V$BLOB_ID;
  SELECT BLOB_ID FROM VAL_ADD(457, :I$MOVEMENT_ID, :I$LEAVEORDERNUMBER) INTO :V$BLOB_ID;
  IF (I$LEAVEBASEMENT IS NOT NULL) THEN  -- заполняем основание для увольнения
    SELECT BLOB_ID FROM VAL_ADD(458, :I$MOVEMENT_ID, :I$LEAVEBASEMENT) INTO :V$BLOB_ID;
  IF (I$LEAVEREASON IS NOT NULL) THEN   -- заполняем причину увольнения
    SELECT BLOB_ID FROM VAL_ADD(461, :I$MOVEMENT_ID, :I$LEAVEREASON) INTO :V$BLOB_ID;

  IF (V$DIVISION_POST_IS_LEFT = 0) THEN
  -- удалим сотрудника из подразделения
  BEGIN
    UPDATE LINKS
    SET DATE_DEL = :I$LEAVEDATE
    WHERE OBJ_ID = :V$EMPLOYEE_ID AND PARENT_ID = :V$UNION_ID AND PARENT_TYPE_ID IN (2, 211) AND DATE_DEL IS NULL;
  END

  -- найдем должность, связанную с увольнением, чтобы вызвать пересчет свободных ставок
  V$BLOB_ID = NULL;
  SELECT FIRST 1 LP13.PARENT_ID
  FROM LINKS LP13
  WHERE LP13.OBJ_ID = :I$MOVEMENT_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
  INTO :V$BLOB_ID;
  IF (V$BLOB_ID IS NOT NULL) THEN
  BEGIN
    EXECUTE PROCEDURE CALC_JOB_OCCUPIED(:V$BLOB_ID);
  END

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_EMPLOYEE_VACANCY_LIST (
    I$EMPLOYEE_ID BIGINT,
    I$LIST_TYPE SMALLINT = 1,
    I$USER_ID BIGINT = 1)
RETURNS (
    OBJ_ID BIGINT,
    PARENT_ID BIGINT,
    OBJ_CAPTION VARCHAR(4000),
    COLUMN1 NUMERIC(15,2),
    COLUMN2 VARCHAR(4000))
AS
DECLARE VARIABLE V$LEAVEDATE DATE;
DECLARE VARIABLE V$VACANCY_ID BIGINT;
BEGIN
    PARENT_ID = NULL;
    FOR
        SELECT O.OBJ_ID

        FROM LINKS L

        JOIN OBJECTS O
        ON O.OBJ_ID = L.OBJ_ID
        AND O.TYPE_ID = 15

        WHERE L.PARENT_ID = :I$EMPLOYEE_ID
        AND L.DATE_DEL IS NULL

        INTO :OBJ_ID
    DO
    BEGIN
        FOR
            SELECT D
            FROM VAL_GET(:OBJ_ID, 74, 0, :I$USER_ID)
            INTO :V$LEAVEDATE
        DO
        BEGIN
            IF (((I$LIST_TYPE = 1) AND (V$LEAVEDATE IS NULL)) OR
                ((I$LIST_TYPE = 2) AND (V$LEAVEDATE IS NOT NULL))) THEN
            BEGIN
                FOR
                    SELECT I
                    FROM VAL_GET(:OBJ_ID, 69, 0, :I$USER_ID)
                    INTO :V$VACANCY_ID
                DO
                BEGIN
                    SELECT CAPTION
                    FROM OBJECT_CAPTION_GET(:V$VACANCY_ID, NULL, NULL, :I$USER_ID)
                    INTO :OBJ_CAPTION;

                    SELECT F
                    FROM VAL_GET(:OBJ_ID, 71, 0, :I$USER_ID)
                    INTO :COLUMN1;

                    SELECT V
                    FROM VAL_GET(:OBJ_ID, 72, 0, :I$USER_ID)
                    INTO :COLUMN2;

                    SUSPEND;
                END
            END
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_ENTERING_CLASS_LIST (
    I$PUPIL_ID BIGINT,
    I$USER_ID BIGINT = 1)
RETURNS (
    OBJ_ID BIGINT,
    OBJ_CAPTION VARCHAR(4000),
    SORT_ORDER DOUBLE PRECISION)
AS
declare variable ENTERING_ID bigint;
declare variable CURR_CLASS_ID bigint;
BEGIN
    ENTERING_ID = NULL;

    SELECT FIRST 1 L.PARENT_ID
    FROM LINKS L
    WHERE L.OBJ_ID = :I$PUPIL_ID
      AND L.PARENT_TYPE_ID = 9
      AND L.DATE_DEL IS NULL
    INTO :CURR_CLASS_ID;

    SELECT FIRST 1 L.PARENT_ID
    FROM LINKS L
    WHERE L.OBJ_ID = :CURR_CLASS_ID
      AND L.PARENT_TYPE_ID = 77
      AND L.DATE_DEL IS NULL
    INTO :ENTERING_ID;

    FOR SELECT L9.OBJ_ID
        FROM LINKS L9
        WHERE L9.PARENT_ID = :ENTERING_ID
          AND L9.OBJ_ID <> :CURR_CLASS_ID
          AND L9.OBJ_TYPE_ID = 9
          AND L9.DATE_DEL IS NULL
        INTO :OBJ_ID
    DO
    BEGIN
        SELECT CAPTION, SORT_ORDER
        FROM OBJECT_CAPTION_GET(:OBJ_ID, NULL, NULL, :I$USER_ID)
        INTO :OBJ_CAPTION, :SORT_ORDER;
        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_ENTERING_TRANSFER (
    I$PUPIL_ID BIGINT,
    I$CLASS_ID BIGINT,
    I$USER_ID BIGINT,
    I$OLDLINK_DEL_FL SMALLINT = 1)
RETURNS (
    OBJ_ID BIGINT,
    TYPE_ID BIGINT,
    PARENT_ID BIGINT,
    USER_ID BIGINT,
    DATE_INS TIMESTAMP,
    DATE_DEL TIMESTAMP,
    SORT_ORDER DOUBLE PRECISION,
    CAPTION VARCHAR(4000),
    HAS_CHILD INTEGER,
    COLOR INTEGER,
    TAB_ID BIGINT,
    TYPE_ORDER SMALLINT,
    LINK_ID BIGINT)
AS
declare variable V$TYPE bigint;
declare variable V$BLOB_ID bigint;
declare variable V$STAGE_ID bigint;
declare variable V$MOVE_ID bigint;
BEGIN
    SELECT O.TYPE_ID
    FROM OBJECTS O
    WHERE O.OBJ_ID = :I$PUPIL_ID
    INTO :TYPE_ID;

    IF (TYPE_ID <> 10) THEN EXIT;

    IF (I$OLDLINK_DEL_FL = 1) THEN
    BEGIN
        -- Удаляем старую ссылку если ученик принят из предварительного приема
        UPDATE LINKS
        SET DATE_DEL = CURRENT_TIMESTAMP
        WHERE OBJ_ID = :I$PUPIL_ID AND DATE_DEL IS NULL;
    END

    SELECT OBJ_ID FROM VARGRP_MOVE_PUPIL(:I$PUPIL_ID, :I$CLASS_ID, NULL, NULL, CURRENT_DATE, 0, :I$USER_ID, NULL, 12905) INTO :V$BLOB_ID;

    SELECT L.LINK_ID, C.CAPTION, C.SORT_ORDER
    FROM LINKS L
    LEFT JOIN OBJECT_CAPTION_GET(L.PARENT_ID) C ON 1 = 1
    WHERE L.OBJ_ID = :I$PUPIL_ID AND L.PARENT_ID = :I$CLASS_ID AND L.DATE_DEL IS NULL
    INTO :LINK_ID,  :CAPTION, SORT_ORDER;

    PARENT_ID = I$CLASS_ID;
    OBJ_ID = I$PUPIL_ID;
    TYPE_ID = 10;
    USER_ID = I$USER_ID;
    DATE_INS = CURRENT_TIMESTAMP;
    DATE_DEL = NULL;
    HAS_CHILD = 0;
    TAB_ID = NULL;

    SELECT COLOR, SORT_ORDER
    FROM TYPES
    WHERE TYPE_ID = 10
    INTO :COLOR, :TYPE_ORDER;

    EXECUTE PROCEDURE GIA_COPY_INFO_EXAM_PARAMS(:I$PUPIL_ID, :I$CLASS_ID, :I$USER_ID);

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_EXTMOVEMENT_MAXDATE (
    I$PUPIL_ID BIGINT)
RETURNS (
    ACTION_DATE DATE)
AS
BEGIN
    SELECT MAX(M.DATE_IN)
    FROM PERSON_MOVEMENTS M
    JOIN OBJECTS O ON O.OBJ_ID = M.GROUP_ID AND O.TYPE_ID = 187
    WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :I$PUPIL_ID
    INTO :ACTION_DATE;

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_GRADE_CURRICULUM_LIST (
    I$GRADE_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    CURRICULUM_ID BIGINT,
    CURRICULUM_CAPTION VARCHAR(4000),
    GRADE_ID BIGINT)
AS
BEGIN
    FOR SELECT LP50.PARENT_ID, LP54.OBJ_ID
        FROM LINKS LP54
        JOIN LINKS LP50 ON LP50.OBJ_ID = LP54.PARENT_ID AND LP50.PARENT_TYPE_ID = 50 AND LP50.DATE_DEL IS NULL
        WHERE LP54.PARENT_TYPE_ID = 54 AND LP54.DATE_DEL IS NULL AND LP54.OBJ_ID IN (
            -- ГУП или Потоки
            SELECT :I$GRADE_ID FROM RDB$DATABASE
            -- Подгруппы 47-48
            UNION
            SELECT L256_10.PARENT_ID
            FROM LINKS L10
            JOIN LINKS L256_10 ON L256_10.OBJ_ID = L10.OBJ_ID AND L256_10.PARENT_TYPE_ID = 256 AND L256_10.DATE_DEL IS NULL
            WHERE L10.PARENT_ID = :I$GRADE_ID AND L10.PARENT_TYPE_ID = 9 AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
            -- Конкретный поток
            UNION
            SELECT LP346.PARENT_ID
            FROM LINKS LP346
            WHERE LP346.OBJ_ID = :I$GRADE_ID AND LP346.PARENT_TYPE_ID = 346 AND LP346.DATE_DEL IS NULL
            -- потоки
            UNION
            SELECT L347.PARENT_ID
            FROM LINKS L10
            JOIN LINKS L347_10 ON L347_10.OBJ_ID = L10.OBJ_ID AND L347_10.PARENT_TYPE_ID = 347 AND L347_10.DATE_DEL IS NULL
            JOIN LINKS L347 ON L347.OBJ_ID = L347_10.PARENT_ID AND L347.PARENT_TYPE_ID = 346 AND L347.DATE_DEL IS NULL
            WHERE L10.PARENT_ID = :I$GRADE_ID AND L10.PARENT_TYPE_ID = 9 AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
          )
        INTO :CURRICULUM_ID, :GRADE_ID
    DO
    BEGIN
        SELECT CAPTION FROM OBJECT_CAPTION_GET(:CURRICULUM_ID, NULL, NULL, :I$USER_ID) INTO :CURRICULUM_CAPTION;
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_GRADE_GROUPS_LIST (
    I$GRADE_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    GROUP_ID BIGINT,
    GROUP_SUBJECT_ID BIGINT,
    GROUP_CAPTION VARCHAR(4000),
    SUBJECT_ID BIGINT,
    SUBJECT_CAPTION VARCHAR(4000),
    SUBGROUP_ID BIGINT,
    SUBGROUP_CAPTION VARCHAR(4000))
AS
declare variable V$COUNT_ID integer;
declare variable V$GROUP_TYPE_ID bigint;
BEGIN
    GROUP_ID = I$GRADE_ID;
    SUBGROUP_ID = I$GRADE_ID;

    SELECT CAPTION
    FROM OBJECT_CAPTION_GET(:GROUP_ID, NULL, NULL, :I$USER_ID)
    INTO :GROUP_CAPTION;

    SUBGROUP_CAPTION = GROUP_CAPTION;
    SUBJECT_ID = NULL;
    SUSPEND;

    FOR
        SELECT L47.OBJ_ID,
               L48.OBJ_ID,
               48
        FROM LINKS L47

        LEFT OUTER JOIN LINKS L48
        ON L48.PARENT_ID = L47.OBJ_ID
        AND L48.OBJ_TYPE_ID = 48
        AND L48.DATE_DEL IS NULL

        WHERE L47.PARENT_ID = :I$GRADE_ID
        AND L47.OBJ_TYPE_ID = 47
        AND L47.DATE_DEL IS NULL

        UNION

        SELECT L347.PARENT_ID,
               L347.OBJ_ID,
               347
        FROM LINKS L347

        WHERE L347.PARENT_ID = :I$GRADE_ID
        AND L347.OBJ_TYPE_ID = 347
        AND L347.DATE_DEL IS NULL

        INTO :GROUP_ID,
             :SUBGROUP_ID,
             :V$GROUP_TYPE_ID
    DO
    BEGIN
        SELECT I
        FROM VAL_GET(:GROUP_ID,IIF(:V$GROUP_TYPE_ID = 48,428,2705),0,:I$USER_ID)
        INTO :GROUP_SUBJECT_ID;

        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:GROUP_ID, NULL, NULL, :I$USER_ID)
        INTO :GROUP_CAPTION;

        IF (SUBGROUP_ID IS NOT NULL) THEN
        BEGIN
            SELECT CAPTION  
            FROM OBJECT_CAPTION_GET(:SUBGROUP_ID, NULL, NULL, :I$USER_ID)
            INTO   :SUBGROUP_CAPTION;

            V$COUNT_ID = 0;
            FOR
                SELECT L51.OBJ_ID
                FROM LINKS L51
                WHERE L51.PARENT_ID = :SUBGROUP_ID
                AND L51.OBJ_TYPE_ID = 51
                AND L51.DATE_DEL IS NULL
                INTO :SUBJECT_ID
            DO
            BEGIN
                V$COUNT_ID = V$COUNT_ID + 1;
                SELECT CAPTION
                FROM OBJECT_CAPTION_GET(:SUBJECT_ID, NULL, NULL, :I$USER_ID)
                INTO   :SUBJECT_CAPTION;
                SUSPEND;
            END
            IF (V$COUNT_ID = 0) THEN
            BEGIN
                SUBJECT_ID = GROUP_SUBJECT_ID;
                SELECT CAPTION
                FROM OBJECT_CAPTION_GET(:SUBJECT_ID, NULL, NULL, :I$USER_ID)
                INTO   :SUBJECT_CAPTION;
                SUSPEND;
            END
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_GRADE_LOADING_LIST (
    I$GRADE_ID BIGINT,
    I$CURRICULUM_ID BIGINT)
RETURNS (
    LOADING_ID BIGINT,
    STAGE_LOADING_ID BIGINT,
    SUBJECT_ID BIGINT,
    CURRICULUM_SUBJECT_ID BIGINT,
    SUBGROUP_ID BIGINT,
    TEACHER_ID BIGINT,
    TEACHER_CAPTION VARCHAR(4000),
    OO_PARTNER_ID BIGINT,
    OO_PARTNER_CAPTION VARCHAR(4000),
    OOOD_PARTNER INTEGER)
AS
DECLARE VARIABLE V$GRADE_TYPE_ID BIGINT;
BEGIN
    -- I$GRADE_ID - ID коллектива или деления на коллективы (подгруппы, потоки)
    -- Сначала нужно выяснить тип коллектива, чтобы идти по нужной ветви дерева
    SELECT TYPE_ID FROM OBJECTS WHERE OBJ_ID = :I$GRADE_ID INTO :V$GRADE_TYPE_ID;

    /*
    FOR
        SELECT DISTINCT SUBJECT_ID, SUBJECT_ID, LOADING_ID, SUBGROUP_ID, STAGE_LOADING_ID, TEACHER_ID, LP237.PARENT_ID
        FROM GRADE_LOADING_LIST_INT(:I$GRADE_ID, :I$CURRICULUM_ID, NULL, :V$GRADE_TYPE_ID) LI
        -- ОООД-партнер
        LEFT JOIN LINKS LP237 ON LP237.OBJ_ID = LI.LOADING_ID AND LP237.PARENT_TYPE_ID = 237 AND LP237.DATE_DEL IS NULL
        INTO :SUBJECT_ID, :CURRICULUM_SUBJECT_ID, :LOADING_ID, :SUBGROUP_ID, :STAGE_LOADING_ID, :TEACHER_ID, :OO_PARTNER_ID
    */
    FOR
        SELECT L51.OBJ_ID, LP51.PARENT_ID, L58.OBJ_ID, :I$GRADE_ID, LP56.PARENT_ID, LP14.PARENT_ID, LP237.PARENT_ID
        FROM LINKS L49
        JOIN LINKS L51 ON L51.PARENT_ID = L49.OBJ_ID AND L51.OBJ_TYPE_ID = 51 AND L51.DATE_DEL IS NULL
        JOIN LINKS L58 ON L58.PARENT_ID = L51.OBJ_ID AND L58.OBJ_TYPE_ID = 58 AND L58.DATE_DEL IS NULL
        JOIN LINKS L9_58 ON L9_58.PARENT_ID = :I$GRADE_ID AND L9_58.OBJ_ID = L58.OBJ_ID AND L9_58.DATE_DEL IS NULL
        JOIN LINKS LP56 ON LP56.OBJ_ID = L58.OBJ_ID AND LP56.PARENT_TYPE_ID = 56 AND LP56.DATE_DEL IS NULL
        JOIN LINKS LP51 ON LP51.OBJ_ID = L58.OBJ_ID AND LP51.PARENT_TYPE_ID = 51 AND LP51.DATE_DEL IS NULL
        LEFT JOIN LINKS LP14 ON LP14.OBJ_ID = L58.OBJ_ID AND LP14.PARENT_TYPE_ID = 14 AND LP14.DATE_DEL IS NULL
        LEFT JOIN LINKS LP237 ON LP237.OBJ_ID = L58.OBJ_ID AND LP237.PARENT_TYPE_ID = 237 AND LP237.DATE_DEL IS NULL
        WHERE L49.PARENT_ID = :I$CURRICULUM_ID AND L49.OBJ_TYPE_ID = 49 AND L49.DATE_DEL IS NULL

        UNION

        SELECT LP51.PARENT_ID, L56_51.PARENT_ID, L58.OBJ_ID, L48.OBJ_ID, LP56.PARENT_ID, LP14.PARENT_ID, LP237.PARENT_ID
        FROM LINKS L49
        JOIN LINKS L47 ON L47.PARENT_ID = :I$GRADE_ID AND L47.OBJ_TYPE_ID = 47 AND L47.DATE_DEL IS NULL
        JOIN LINKS L48 ON L48.PARENT_ID = L47.OBJ_ID AND L48.OBJ_TYPE_ID = 48 AND L48.DATE_DEL IS NULL
        JOIN LINKS L58 ON L58.PARENT_ID = L48.OBJ_ID AND L58.OBJ_TYPE_ID = 58 AND L58.DATE_DEL IS NULL
        JOIN LINKS L51 ON L51.PARENT_ID = L49.OBJ_ID AND L51.OBJ_TYPE_ID = 51 AND L51.DATE_DEL IS NULL
        JOIN LINKS LP56 ON LP56.OBJ_ID = L58.OBJ_ID AND LP56.PARENT_TYPE_ID = 56 AND LP56.DATE_DEL IS NULL
        JOIN LINKS LP51 ON LP51.OBJ_ID = L58.OBJ_ID AND LP51.PARENT_TYPE_ID = 51 AND LP51.DATE_DEL IS NULL
        JOIN LINKS L56_51 ON L56_51.OBJ_ID = LP56.PARENT_ID AND L56_51.PARENT_TYPE_ID = 51 AND L56_51.DATE_DEL IS NULL
        LEFT JOIN LINKS LP14 ON LP14.OBJ_ID = L58.OBJ_ID AND LP14.PARENT_TYPE_ID = 14 AND LP14.DATE_DEL IS NULL
        LEFT JOIN LINKS LP237 ON LP237.OBJ_ID = L58.OBJ_ID AND LP237.PARENT_TYPE_ID = 237 AND LP237.DATE_DEL IS NULL
        WHERE L49.PARENT_ID = :I$CURRICULUM_ID AND L49.OBJ_TYPE_ID = 49 AND L49.DATE_DEL IS NULL

        UNION

        SELECT LP51.PARENT_ID, L56_51.PARENT_ID, L58.OBJ_ID, L347.OBJ_ID, LP56.PARENT_ID, LP14.PARENT_ID, LP237.PARENT_ID
        FROM LINKS L49
        JOIN LINKS L347 ON L347.PARENT_ID = :I$GRADE_ID AND L347.OBJ_TYPE_ID = 347 AND L347.DATE_DEL IS NULL
        JOIN LINKS L58 ON L58.PARENT_ID = L347.OBJ_ID AND L58.OBJ_TYPE_ID = 58 AND L58.DATE_DEL IS NULL
        JOIN LINKS L51 ON L51.PARENT_ID = L49.OBJ_ID AND L51.OBJ_TYPE_ID = 51 AND L51.DATE_DEL IS NULL
        JOIN LINKS LP56 ON LP56.OBJ_ID = L58.OBJ_ID AND LP56.PARENT_TYPE_ID = 56 AND LP56.DATE_DEL IS NULL
        JOIN LINKS LP51 ON LP51.OBJ_ID = L58.OBJ_ID AND LP51.PARENT_TYPE_ID = 51 AND LP51.DATE_DEL IS NULL
        JOIN LINKS L56_51 ON L56_51.OBJ_ID = LP56.PARENT_ID AND L56_51.PARENT_TYPE_ID = 51 AND L56_51.DATE_DEL IS NULL
        LEFT JOIN LINKS LP14 ON LP14.OBJ_ID = L58.OBJ_ID AND LP14.PARENT_TYPE_ID = 14 AND LP14.DATE_DEL IS NULL
        LEFT JOIN LINKS LP237 ON LP237.OBJ_ID = L58.OBJ_ID AND LP237.PARENT_TYPE_ID = 237 AND LP237.DATE_DEL IS NULL
        WHERE L49.PARENT_ID = :I$CURRICULUM_ID AND L49.OBJ_TYPE_ID = 49 AND L49.DATE_DEL IS NULL

        INTO :SUBJECT_ID, :CURRICULUM_SUBJECT_ID, :LOADING_ID, :SUBGROUP_ID, :STAGE_LOADING_ID, :TEACHER_ID, :OO_PARTNER_ID
    DO
    BEGIN

        OOOD_PARTNER = 0;
        SELECT I FROM VAL_GET(:STAGE_LOADING_ID, 1893) INTO :OOOD_PARTNER;

        IF (OOOD_PARTNER = 2) THEN OOOD_PARTNER = 1; ELSE OOOD_PARTNER = 0;

        TEACHER_CAPTION = NULL;
        IF (TEACHER_ID IS NOT NULL) THEN
        BEGIN
            SELECT CAPTION FROM OBJECT_CAPTION_GET(:TEACHER_ID, NULL) INTO :TEACHER_CAPTION;
        END

        OO_PARTNER_CAPTION = NULL;
        IF (OO_PARTNER_ID IS NOT NULL) THEN
        BEGIN
            SELECT CAPTION FROM OBJECT_CAPTION_GET(:OO_PARTNER_ID, NULL) INTO :OO_PARTNER_CAPTION;
        END

        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_GRADE_OO_PARTNERS_LIST (
    I$GRADE_ID BIGINT)
RETURNS (
    OO_PARTNER_ID BIGINT,
    OO_PARTNER_CAPTION VARCHAR(4000))
AS
declare variable V$PLAN_ID bigint;
BEGIN
    FOR
        SELECT L237.OBJ_ID

        FROM LINKS LP54

        JOIN LINKS LP50
        ON LP50.OBJ_ID = LP54.PARENT_ID
        AND LP50.PARENT_TYPE_ID = 50
        AND LP50.DATE_DEL IS NULL

        JOIN LINKS LP57
        ON LP57.OBJ_ID = LP50.PARENT_ID
        AND LP57.PARENT_TYPE_ID = 57
        AND LP57.DATE_DEL IS NULL

        JOIN LINKS L237
        ON L237.PARENT_ID = LP57.PARENT_ID
        AND L237.OBJ_TYPE_ID = 237
        AND L237.DATE_DEL IS NULL

        WHERE LP54.OBJ_ID = :I$GRADE_ID
        AND LP54.PARENT_TYPE_ID = 54
        AND LP54.DATE_DEL IS NULL

        INTO :OO_PARTNER_ID
    DO
    BEGIN
        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:OO_PARTNER_ID, NULL)
        INTO :OO_PARTNER_CAPTION;
        SUSPEND;
    END

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_GRADE_SUBJECTS_LIST (
    I$GRADE_ID BIGINT,
    I$CURRICULUM_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    STAGE_ID BIGINT,
    STAGE_LOADING_ID BIGINT,
    SUBJECT_ID BIGINT,
    SUBJECT_CAPTION VARCHAR(4000),
    STAGE_LOADING_PERIOD INTEGER,
    STAGE_LOADING_LIMIT INTEGER,
    VAL INTEGER)
AS
BEGIN
    STAGE_LOADING_ID = NULL;
    FOR SELECT LP54.PARENT_ID
        FROM LINKS LP54
        INNER JOIN LINKS L50_54 ON L50_54.OBJ_ID = LP54.PARENT_ID
        WHERE LP54.OBJ_ID = :I$GRADE_ID
          AND LP54.PARENT_TYPE_ID = 54
          AND LP54.DATE_DEL IS NULL
          AND L50_54.PARENT_ID = :I$CURRICULUM_ID
          AND L50_54.DATE_DEL IS NULL
        INTO :STAGE_ID
    DO
    BEGIN
        SELECT I
        FROM VAL_GET(:STAGE_ID, 382, 0, :I$USER_ID)
        INTO :STAGE_LOADING_PERIOD;
        SELECT I
        FROM VAL_GET(:STAGE_ID, 383, 0, :I$USER_ID)
        INTO :STAGE_LOADING_LIMIT;

        FOR SELECT L51.OBJ_ID, L56.OBJ_ID, SUM(VI.VAL)
            FROM LINKS L49
            INNER JOIN LINKS L51 ON L51.PARENT_ID = L49.OBJ_ID AND L51.OBJ_TYPE_ID = 51 AND L51.DATE_DEL IS NULL
            INNER JOIN LINKS L56 ON L56.PARENT_ID = :STAGE_ID AND L56.OBJ_TYPE_ID = 56 AND L56.DATE_DEL IS NULL
            INNER JOIN LINKS L51_56 ON L51_56.OBJ_ID = L56.OBJ_ID AND L51_56.PARENT_ID = L51.OBJ_ID AND L51_56.DATE_DEL IS NULL
            INNER JOIN LINKS L49_56 ON L49_56.OBJ_ID = L56.OBJ_ID AND L49_56.PARENT_ID = L49.OBJ_ID AND L49_56.DATE_DEL IS NULL
            INNER JOIN VALI VI ON VI.PARAM_ID = 385 AND VI.OBJ_ID = L56.OBJ_ID AND VI.IS_DEL = 0 AND VI.VAL > 0
            WHERE L49.PARENT_ID = :I$CURRICULUM_ID
              AND L49.OBJ_TYPE_ID = 49
              AND L49.DATE_DEL IS NULL
            GROUP BY L51.OBJ_ID, L56.OBJ_ID
            INTO :SUBJECT_ID, :STAGE_LOADING_ID, :VAL
        DO
        BEGIN
            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:SUBJECT_ID, NULL, NULL, :I$USER_ID)
            INTO :SUBJECT_CAPTION;
            SUSPEND;
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_GRADE_TEACHERS_LIST (
    I$GRADE_ID BIGINT,
    I$NOT_ONLY_PEDAGOGS SMALLINT = 0)
RETURNS (
    TEACHER_ID BIGINT,
    TEACHER_CAPTION VARCHAR(4000))
AS
declare variable V$SCHOOL_ID bigint;
BEGIN
    -- I$NOT_ONLY_PEDAGOGS:
    -- 0 = только педагогические должности
    -- 1 = все должности
    -- 2 = расширенные педагогические должности (+ все руководители) - включается принудительно для коллективов ВД

    -- Разрешаем всех руководителей выбирать помимо педагогов
    IF(I$NOT_ONLY_PEDAGOGS = 0) THEN I$NOT_ONLY_PEDAGOGS = 2;

    -- Если NULL, берем по всей ОО
    IF (I$GRADE_ID IS NULL) THEN
    BEGIN
        SELECT FIRST 1 OBJ_ID
        FROM LINKS L
        WHERE L.PARENT_ID IS NULL AND L.OBJ_TYPE_ID = 2 AND L.DATE_DEL IS NULL
        INTO :V$SCHOOL_ID;
    END
    ELSE
    BEGIN
        SELECT FIRST 1 OBJ_ID
        FROM OBJECT_PARENTS_GET(:I$GRADE_ID, 2)
        INTO :V$SCHOOL_ID;

        -- Если выбрана группа в учебном плане ВД, то переключаем в расширенный режим
        -- Потоков тут больше нет
        IF(EXISTS(
            SELECT FIRST 1 1
            FROM LINKS LP54
            JOIN LINKS LP400 ON LP400.OBJ_ID = LP54.PARENT_ID AND LP400.PARENT_TYPE_ID = 400 AND LP400.DATE_DEL IS NULL
            JOIN VALL V3022 ON V3022.OBJ_ID = LP400.PARENT_ID AND V3022.PARAM_ID = 3022 AND V3022.IS_DEL = 0 AND V3022.LISTVAL_ID = 2
            WHERE LP54.OBJ_ID = :I$GRADE_ID AND LP54.PARENT_TYPE_ID = 54 AND LP54.DATE_DEL IS NULL
        ))
        THEN
            I$NOT_ONLY_PEDAGOGS = 2;
    END

    FOR
        -- Сотрудники самого ОО
        SELECT DISTINCT L14.OBJ_ID
        FROM LINKS L14
        JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
        JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
        JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0 AND V73.VAL <= CURRENT_DATE
        LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
        LEFT JOIN DO_FUNC(LP13.PARENT_ID, 400) DF ON 1 = 1
        WHERE L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL AND L14.PARENT_ID = :V$SCHOOL_ID
            -- Должность действующая
            AND ((V74.VAL IS NULL) OR (V74.VAL >= CURRENT_DATE))
            -- Фильтр по педагогическим должностям (для ВД разрешаем расширенный список)
            AND ((:I$NOT_ONLY_PEDAGOGS = 1) OR (DF.SORT_ORDER = 2) OR (:I$NOT_ONLY_PEDAGOGS = 2 AND DF.I = 1))
        -- Сотрудники подразделений
        UNION
        SELECT DISTINCT L14.OBJ_ID
        FROM LINKS L211
        JOIN LINKS L14 ON L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL AND L14.PARENT_ID = L211.OBJ_ID
        JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
        JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
        JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0 AND V73.VAL <= CURRENT_DATE
        LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
        LEFT JOIN DO_FUNC(LP13.PARENT_ID, 400) DF ON 1 = 1
        WHERE L211.PARENT_ID = :V$SCHOOL_ID AND L211.OBJ_TYPE_ID = 211 AND L211.DATE_DEL IS NULL
            -- Должность действующая
            AND ((V74.VAL IS NULL) OR (V74.VAL >= CURRENT_DATE))
            -- Фильтр по педагогическим должностям (для ВД разрешаем расширенный список)
            AND ((:I$NOT_ONLY_PEDAGOGS = 1) OR (DF.SORT_ORDER = 2) OR (:I$NOT_ONLY_PEDAGOGS = 2 AND DF.I = 1))
        INTO :TEACHER_ID
    DO
    BEGIN
        SELECT CAPTION FROM OBJECT_CAPTION_GET(:TEACHER_ID, NULL) INTO :TEACHER_CAPTION;
        SUSPEND;
    END

END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_GRADE_TEACHER_L_LIST (
    I$TEACHER_ID BIGINT,
    I$GRADE_ID BIGINT = null,
    I$FILTER_VD SMALLINT = 1)
RETURNS (
    PLAN_ID BIGINT,
    CJ_ID BIGINT,
    SUBJECT_ID BIGINT,
    SUBJECT_CAPTION VARCHAR(4000),
    GROUP_CAPTION VARCHAR(4000),
    STAGE_ID BIGINT,
    HOURS DOUBLE PRECISION,
    WEEKS DOUBLE PRECISION,
    SUBJECT_LOADING DOUBLE PRECISION,
    PLAN_TYPE VARCHAR(40))
AS
declare variable ID bigint;
declare variable IS_VD smallint;
declare variable V$PLAN_TYPE bigint;
BEGIN

    -- Если параметр GRADE_ID не передан, считаем что это общеобразовательный план
    IS_VD = 0;

    IF(I$GRADE_ID IS NOT NULL) THEN
    BEGIN
        SELECT FIRST 1 1
        FROM LINKS LP54
        JOIN LINKS LP400 ON LP400.OBJ_ID = LP54.PARENT_ID AND LP400.PARENT_TYPE_ID = 400 AND LP400.DATE_DEL IS NULL
        JOIN VALL V3022 ON V3022.OBJ_ID = LP400.PARENT_ID AND V3022.PARAM_ID = 3022 AND V3022.IS_DEL = 0 AND V3022.LISTVAL_ID = 2
        WHERE LP54.OBJ_ID = :I$GRADE_ID AND LP54.PARENT_TYPE_ID = 54 AND LP54.DATE_DEL IS NULL
        INTO :IS_VD;
    END

    FOR
        SELECT J.OBJ_ID, J.SUBJECT_ID, J.STAGE_INDEX, V376.VAL, J.REF_ID, J.JOURNAL_TYPE, J.JOURNAL_NAME, J.HOURS, J.WEEKS
        FROM CJ2_JOURNAL J
        JOIN VALS V376 ON V376.OBJ_ID = J.SUBJECT_ID AND V376.PARAM_ID = 376 AND V376.IS_DEL = 0
        JOIN VALS N376 ON N376.OBJ_ID = J.SUBJECT_ID AND N376.PARAM_ID = 376 AND N376.IS_DEL = 0
        WHERE J.DATE_DEL IS NULL AND J.TEACHER_ID = :I$TEACHER_ID AND (:I$FILTER_VD = 0 OR (:IS_VD = 0 AND J.JOURNAL_TYPE = 0) OR (:IS_VD <> 0 AND J.JOURNAL_TYPE = 1))
        ORDER BY J.STAGE_INDEX, J.JOURNAL_NAME, V376.VAL
        INTO :CJ_ID, :SUBJECT_ID, :STAGE_ID, :SUBJECT_CAPTION, :PLAN_ID, :V$PLAN_TYPE, :GROUP_CAPTION, :HOURS, :WEEKS
    DO
    BEGIN
        IF(V$PLAN_TYPE = 1) THEN PLAN_TYPE = 'Внеурочная деятельность'; ELSE PLAN_TYPE = 'Общеобразовательная';
        SUBJECT_LOADING = 0;
        IF (WEEKS <> 0) THEN SUBJECT_LOADING = HOURS / WEEKS;
        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_GROUP_SUBJECTS_LIST (
    I$OBJ_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    OBJ_CAPTION VARCHAR(4000),
    SORT_ORDER DOUBLE PRECISION)
AS
declare variable V$OBJ_ID bigint;
declare variable V$SUBJECT_ID bigint;
BEGIN
    V$SUBJECT_ID = NULL;

    SELECT FIRST 1 OBJ_ID
    FROM OBJECT_PARENTS_GET(:I$OBJ_ID, 47)
    INTO :V$OBJ_ID;

    SELECT I
    FROM VAL_GET(:V$OBJ_ID, 428, 0, :I$USER_ID)
    INTO   :V$SUBJECT_ID;

    FOR SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.PARENT_ID = :V$SUBJECT_ID
          AND L.OBJ_TYPE_ID = 51
          AND L.DATE_DEL IS NULL
        INTO :OBJ_ID
    DO
    BEGIN
        SELECT CAPTION, SORT_ORDER
        FROM OBJECT_CAPTION_GET(:OBJ_ID, NULL, NULL, :I$USER_ID)
        INTO :OBJ_CAPTION, :SORT_ORDER;

        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_GROUP_SUBJECTS_LISTOLD (
    I$OBJ_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    OBJ_CAPTION VARCHAR(4000),
    SORT_ORDER DOUBLE PRECISION)
AS
declare variable V$OBJ_ID bigint;
declare variable V$SUBJECT_ID bigint;
BEGIN
    V$SUBJECT_ID = NULL;
    FOR
        SELECT FIRST 1 OBJ_ID
        FROM OBJECT_PARENTS_GET(:I$OBJ_ID, 47)
        INTO :V$OBJ_ID
    DO
    BEGIN
        SELECT I
        FROM VAL_GET(:V$OBJ_ID, 428, 0, :I$USER_ID)
        INTO   :V$SUBJECT_ID;
    END
    FOR
        SELECT OBJ_ID,
               OBJ_CAPTION,
               SORT_ORDER
        FROM PARAGRAF_TYPE_NOT_LINKED_LIST(2, 51, :I$OBJ_ID, :I$USER_ID, 47, 208)
        WHERE OBJ_ID <> :V$SUBJECT_ID
        ORDER BY OBJ_CAPTION
        INTO   :OBJ_ID,
               :OBJ_CAPTION,
               :SORT_ORDER
    DO
    BEGIN
        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_INPUT_STAGE_LIST (
    I$PUPIL_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    COLOR INTEGER,
    OBJ_CAPTION VARCHAR(4000),
    SORT_ORDER DOUBLE PRECISION)
AS
declare variable V$SCHOOL_ID bigint;
BEGIN
    V$SCHOOL_ID = NULL;

    SELECT FIRST 1 OBJ_ID
    FROM OBJECT_PARENTS_GET(:I$PUPIL_ID, 2)
    INTO :V$SCHOOL_ID;

    FOR
        SELECT L290.OBJ_ID,
               T290.COLOR

        FROM LINKS L77

        JOIN LINKS L290
        ON L290.PARENT_ID = L77.OBJ_ID
        AND L290.OBJ_TYPE_ID = 290
        AND L290.DATE_DEL IS NULL

        JOIN TYPES T290
        ON T290.TYPE_ID = L290.OBJ_TYPE_ID

        WHERE L77.PARENT_ID = :V$SCHOOL_ID
        AND L77.OBJ_TYPE_ID = 77
        AND L77.DATE_DEL IS NULL

        AND NOT EXISTS(
            SELECT FIRST 1 1
            FROM LINKS L
            WHERE L.OBJ_ID = :I$PUPIL_ID
            AND L.PARENT_ID = L290.OBJ_ID
            AND L.DATE_DEL IS NULL
        )

        INTO :OBJ_ID,
             :COLOR
    DO
    BEGIN
        SELECT CAPTION, SORT_ORDER
        FROM OBJECT_CAPTION_GET(:OBJ_ID, NULL, NULL, :I$USER_ID)
        INTO :OBJ_CAPTION, :SORT_ORDER;

        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_INVENTORY_CARD_LIST (
    I$PARENT_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    OBJ_CAPTION VARCHAR(4000),
    INVENTORY_NUMBER VARCHAR(4000))
AS
BEGIN
    FOR
        SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.PARENT_ID = :I$PARENT_ID
        AND OBJ_TYPE_ID = 114
        AND DATE_DEL IS NULL
        INTO :OBJ_ID
    DO
    BEGIN
        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:OBJ_ID, NULL, NULL, :I$USER_ID)
        INTO :OBJ_CAPTION;
        SELECT V
        FROM VAL_GET(:OBJ_ID, 673, 0, :I$USER_ID)
        INTO :INVENTORY_NUMBER;
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_KINSFOLK_LIST (
    I$OBJ_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    OBJ_CAPTION VARCHAR(4000))
AS
BEGIN
    FOR SELECT DISTINCT OBJ_ID
        FROM OBJECT_CHILDREN_GET_DEEP(:I$OBJ_ID, 20)
        INTO :OBJ_ID
    DO
    BEGIN
        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:OBJ_ID, NULL)
        INTO :OBJ_CAPTION;
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_LIST_STAGE_PUPILS (
    STAGE_ID BIGINT)
RETURNS (
    CLASS_NAME VARCHAR(1000),
    PUPIL_NAME VARCHAR(1000),
    PUPIL_ID BIGINT,
    SEL_SUBJECTS VARCHAR(1000),
    SEL_GROUPS VARCHAR(1000))
AS
declare variable ID bigint;
begin

  FOR
    SELECT DISTINCT C256.CAPTION, C10.CAPTION, L10.OBJ_ID, V2838.VAL
    FROM LINKS L256
    LEFT JOIN OBJECT_CAPTION_GET(L256.OBJ_ID) C256 on 1 = 1
    JOIN LINKS L10 on L10.PARENT_ID = L256.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL is null
    LEFT JOIN OBJECT_CAPTION_GET(L10.OBJ_ID) C10 on 1 = 1
    -- Список предметов по выбору
    LEFT JOIN VALS V2838 ON V2838.OBJ_ID = L10.OBJ_ID AND V2838.PARAM_ID = 2838 AND V2838.IS_DEL = 0
    WHERE L256.PARENT_ID = :STAGE_ID AND L256.OBJ_TYPE_ID = 256 AND L256.DATE_DEL is null
    -- Сортируем в порядке, как оно задано пользователем
    ORDER BY 1, 2
    INTO :CLASS_NAME, :PUPIL_NAME, :PUPIL_ID, :SEL_SUBJECTS
  DO
  BEGIN
    -- Формируем список всех ID потоков, в которых ученик числится
    SEL_GROUPS = '';
    FOR
      SELECT LP347.PARENT_ID
      FROM LINKS LP347
      WHERE LP347.OBJ_ID = :PUPIL_ID AND LP347.PARENT_TYPE_ID = 347 AND LP347.DATE_DEL is null
      INTO :ID
    DO
    BEGIN
      IF(CHAR_LENGTH(SEL_GROUPS) > 0) THEN SEL_GROUPS = SEL_GROUPS || ',';
      SEL_GROUPS = SEL_GROUPS || ID;
    END

    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_LIST_STAGE_SUBJECTS_SE (
    STAGE_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    CAPTION VARCHAR(1000),
    HAS_GROUPS SMALLINT)
AS
declare variable PLAN_ID bigint;
declare variable HOURS double precision;
begin

  FOR
    SELECT DISTINCT L51.OBJ_ID, C.CAPTION, LP50.PARENT_ID
    FROM LINKS LP50
    JOIN LINKS L49 ON L49.PARENT_ID = LP50.PARENT_ID AND L49.OBJ_TYPE_ID = 49 AND L49.DATE_DEL is null
    -- Исключаем служебный предмет из списка
    JOIN LINKS L51 ON L51.PARENT_ID = L49.OBJ_ID AND L51.OBJ_TYPE_ID = 51 AND L51.DATE_DEL is null AND L51.OBJ_ID <> 34607
    -- Фильтруем по предметам с признаком "электив"
    JOIN VALL V2816 ON V2816.OBJ_ID = L51.OBJ_ID AND V2816.PARAM_ID = 2816 AND V2816.IS_DEL = 0 AND V2816.LISTVAL_ID = 2
    -- Название предмета
    LEFT JOIN OBJECT_CAPTION_GET(L51.OBJ_ID) C on 1 = 1
    WHERE LP50.PARENT_TYPE_ID = 50 AND LP50.OBJ_ID = :STAGE_ID AND LP50.DATE_DEL is null
    -- Сортируем в порядке, как оно задано пользователем
    ORDER BY L51.COST
    INTO :OBJ_ID, :CAPTION, :PLAN_ID
  DO
  BEGIN
    -- Наличие часов нагрузки (смотрим все компоненты)
    HOURS = 0;

    SELECT SUM(V385.VAL)
    FROM LINKS LP50
    JOIN LINKS L56 ON L56.PARENT_ID = LP50.OBJ_ID AND L56.OBJ_TYPE_ID = 56 AND L56.DATE_DEL IS NULL
    JOIN LINKS LP51 ON LP51.OBJ_ID = L56.OBJ_ID AND LP51.PARENT_ID = :OBJ_ID AND LP51.DATE_DEL IS NULL
    JOIN VALI V385 ON V385.OBJ_ID = L56.OBJ_ID AND V385.PARAM_ID = 385 AND V385.IS_DEL = 0
    WHERE LP50.PARENT_ID = :PLAN_ID AND LP50.OBJ_ID = :STAGE_ID AND LP50.DATE_DEL is null
    INTO :HOURS;

    IF(HOURS > 0) THEN
    BEGIN

      -- Проверяем, есть ли по данному предмету деление на потоки - проверку делаем по всем этапам, а не только по текущему
      -- Проверку наличия групп делаем только по данной параллели
      HAS_GROUPS = 0;
      SELECT COUNT(*)
      FROM LINKS L54
      JOIN LINKS L346 ON L346.PARENT_ID = L54.OBJ_ID AND L346.OBJ_TYPE_ID = 346 AND L346.DATE_DEL is null
      JOIN VALR V2705 ON V2705.OBJ_ID = L346.OBJ_ID AND V2705.PARAM_ID = 2705 AND V2705.IS_DEL = 0 and V2705.VAL = :OBJ_ID
      WHERE L54.PARENT_ID = :PLAN_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL is null AND L54.OBJ_ID = :STAGE_ID
      INTO :HAS_GROUPS;

      SUSPEND;
    END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_LIST_STREAMS (
    STAGE_ID BIGINT,
    SUBJECT_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    CAPTION VARCHAR(1000))
AS
begin

  FOR
    -- Выбираем потоки по данному этапу УП
    SELECT L347.OBJ_ID, C.CAPTION
    FROM LINKS L346
    JOIN VALR V2705 ON V2705.OBJ_ID = L346.OBJ_ID AND V2705.PARAM_ID = 2705 AND V2705.IS_DEL = 0 AND V2705.VAL = :SUBJECT_ID
    -- Все потоки в данном делении
    JOIN LINKS L347 ON L347.PARENT_ID = L346.OBJ_ID AND L347.OBJ_TYPE_ID = 347 AND L347.DATE_DEL is null
    LEFT JOIN OBJECT_CAPTION_GET(L347.OBJ_ID) C on 1 = 1
    WHERE L346.PARENT_ID = :STAGE_ID AND L346.OBJ_TYPE_ID = 346 AND L346.DATE_DEL is null
    ORDER BY 2
    INTO :OBJ_ID, :CAPTION
  DO
  BEGIN
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_LOADING_CLASS_LIST (
    I$STAGE_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    OBJ_CAPTION VARCHAR(4000),
    SORT_ORDER DOUBLE PRECISION)
AS
DECLARE VARIABLE V$OBJ_ID BIGINT;
BEGIN
    SELECT FIRST 1
           OBJ_ID
    FROM OBJECT_PARENTS_GET(:I$STAGE_ID, 2)
    INTO :V$OBJ_ID;

    FOR
        SELECT L9.OBJ_ID
        FROM LINKS L7

        INNER JOIN LINKS L8
        ON L8.PARENT_ID = L7.OBJ_ID
        AND L8.OBJ_TYPE_ID = 8
        AND L8.DATE_DEL IS NULL

        INNER JOIN LINKS L9
        ON L9.PARENT_ID = L8.OBJ_ID
        AND L9.OBJ_TYPE_ID = 9
        AND L9.DATE_DEL IS NULL

        LEFT OUTER JOIN LINKS L
        ON L.PARENT_ID = :I$STAGE_ID
        AND L.OBJ_ID = L9.OBJ_ID
        AND L.DATE_DEL IS NULL

        WHERE L7.PARENT_ID = :V$OBJ_ID
        AND L7.OBJ_TYPE_ID = 7
        AND L7.DATE_DEL IS NULL
        AND L.LINK_ID IS NULL
        INTO :OBJ_ID
/*

        SELECT DISTINCT O.OBJ_ID
        FROM OBJECT_CHILDREN_GET(:V$OBJ_ID, 9) O
        INNER JOIN LINKS LNK   ON LNK.OBJ_ID = O.OBJ_ID       AND LNK.DATE_DEL IS NULL
        INNER JOIN OBJECTS OBJ ON OBJ.OBJ_ID = LNK.PARENT_ID  AND OBJ.TYPE_ID = 8
        LEFT OUTER JOIN LINKS L    ON L.PARENT_ID = :I$STAGE_ID   AND L.OBJ_ID = O.OBJ_ID  AND L.DATE_DEL IS NULL
        WHERE L.LINK_ID IS NULL
        INTO   :OBJ_ID*/
    DO
    BEGIN
            SELECT CAPTION,
                   SORT_ORDER
            FROM OBJECT_CAPTION_GET(:OBJ_ID, NULL, NULL, :I$USER_ID)
            INTO   :OBJ_CAPTION,
                   :SORT_ORDER;

            SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_LOADING_COLUMNS (
    I$OBJ_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    OBJ_CAPTION VARCHAR(4000),
    SORT_ORDER DOUBLE PRECISION,
    LOADING_IN_WEEK INTEGER,
    LOADING_WEEK_COUNT INTEGER,
    WEEKS BIGINT,
    STAGE_TYPE BIGINT)
AS
BEGIN
    FOR
        SELECT L54.OBJ_ID, V2837.LISTVAL_ID, V381.LISTVAL_ID
        FROM LINKS L54
        LEFT JOIN VALL V2837 ON V2837.OBJ_ID = L54.OBJ_ID AND V2837.PARAM_ID = 2837 AND V2837.IS_DEL = 0
        JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
        WHERE L54.PARENT_ID = :I$OBJ_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
        INTO :OBJ_ID, :WEEKS, :STAGE_TYPE
    DO
    BEGIN
        SELECT CAPTION, SORT_ORDER
        FROM OBJECT_CAPTION_GET(:OBJ_ID, NULL, NULL, :I$USER_ID)
        INTO :OBJ_CAPTION, :SORT_ORDER;

        SELECT I FROM VAL_GET(:OBJ_ID, 382, 0, :I$USER_ID) INTO :LOADING_WEEK_COUNT;
        SELECT I FROM VAL_GET(:OBJ_ID, 383, 0, :I$USER_ID) INTO :LOADING_IN_WEEK;

        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_LOADING_COMPONENTS (
    I$OBJ_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    OBJ_CAPTION VARCHAR(4000),
    COMPONENT_ID BIGINT,
    STANDARD_ID BIGINT,
    LEVEL_ID BIGINT,
    PROFILE_ID BIGINT)
AS
declare variable HAS_ELECTIVES integer;
declare variable TMP bigint;
BEGIN

    -- Если это шаблон, то уровень будет находиться в самом УП
    SELECT COALESCE(V2503.LISTVAL_ID, V1594.LISTVAL_ID)
    FROM OBJECTS P
    -- Выборка уровня для шаблонов
    LEFT JOIN VALL V2503 ON V2503.OBJ_ID = P.OBJ_ID AND V2503.PARAM_ID = 2503 AND V2503.IS_DEL = 0
    -- Выборка уровня для обычных УП
    LEFT JOIN LINKS LP57 ON LP57.OBJ_ID = P.OBJ_ID AND LP57.DATE_DEL is null AND LP57.PARENT_TYPE_ID IN (57, 244, 252)
    LEFT JOIN VALL V1594 ON V1594.OBJ_ID = LP57.PARENT_ID AND V1594.IS_DEL = 0 AND V1594.PARAM_ID IN (1594, 2132, 2146)
    WHERE P.OBJ_ID = :I$OBJ_ID
    INTO :LEVEL_ID;

    FOR
        SELECT L49.OBJ_ID, V372.LISTVAL_ID, V2478.LISTVAL_ID, V2166.LISTVAL_ID
        FROM LINKS L49
        LEFT JOIN VALL V372 ON V372.OBJ_ID = L49.OBJ_ID AND V372.PARAM_ID = 372 AND V372.IS_DEL = 0
        LEFT JOIN VALL V2478 ON V2478.OBJ_ID = L49.PARENT_ID AND V2478.PARAM_ID = 2478 AND V2478.IS_DEL = 0
        LEFT JOIN VALL V2166 ON V2166.OBJ_ID = L49.PARENT_ID AND V2166.PARAM_ID = 2166 AND V2166.IS_DEL = 0
        WHERE L49.PARENT_ID = :I$OBJ_ID AND L49.OBJ_TYPE_ID = 49 AND L49.DATE_DEL IS NULL
        INTO :OBJ_ID, :COMPONENT_ID, :STANDARD_ID, :PROFILE_ID
    DO
    BEGIN

        -- Наименование компонента
        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:OBJ_ID, NULL)
        INTO :OBJ_CAPTION;

        -- Для вариативных компонентов проверяем наличие элективных предметов
        IF(COMPONENT_ID IN (782, 12753)) THEN
        BEGIN
          HAS_ELECTIVES = 0;

          SELECT FIRST 1 1
          FROM LINKS L51
          JOIN VALL V2816 ON V2816.OBJ_ID = L51.OBJ_ID AND V2816.PARAM_ID = 2816 AND V2816.IS_DEL = 0 AND V2816.LISTVAL_ID = 2
          WHERE L51.PARENT_ID = :OBJ_ID AND L51.OBJ_TYPE_ID = 51 AND L51.DATE_DEL is null AND L51.OBJ_ID <> 34607
          INTO :HAS_ELECTIVES;

          IF(HAS_ELECTIVES > 0) THEN
          BEGIN

            -- Проверяем наличие строки предмета 34607 (Предметы по выбору)
            HAS_ELECTIVES = 0;

            SELECT FIRST 1 1
            FROM LINKS L51
            WHERE L51.PARENT_ID = :OBJ_ID AND L51.DATE_DEL is null AND L51.OBJ_ID = 34607
            INTO :HAS_ELECTIVES;

            IF(HAS_ELECTIVES = 0) THEN
            BEGIN
              -- Если такой строки нет - добавляем ее
              SELECT OBJ_ID FROM OBJECT_ADD_LINK(:OBJ_ID, 34607, 51) INTO :TMP;
            END

          END

        END

        SUSPEND;
    END
    -- Итоги
    OBJ_ID = NULL;
    OBJ_CAPTION = '';
    COMPONENT_ID = NULL;
    -- STANDARD_ID остается уже заполненным
    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_LOADING_EXTERNAL_LIST (
    I$STAGE_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    OBJ_CAPTION VARCHAR(4000),
    SORT_ORDER DOUBLE PRECISION)
AS
declare variable V$OBJ_ID bigint;
declare variable V$PLAN_STAGE_INDEX bigint;
BEGIN
    SELECT FIRST 1 OBJ_ID FROM OBJECT_PARENTS_GET(:I$STAGE_ID, 2) INTO :V$OBJ_ID;

    SELECT I FROM VAL_GET(:I$STAGE_ID, 381, 0, :I$USER_ID) INTO :V$PLAN_STAGE_INDEX;

    FOR SELECT DISTINCT L187.OBJ_ID
        FROM LINKS L7
        INNER JOIN LINKS L8  ON L8.PARENT_ID = L7.OBJ_ID
        INNER JOIN LINKS L187  ON L187.PARENT_ID = L8.OBJ_ID
        INNER JOIN VALL  V49 ON V49.OBJ_ID = L8.OBJ_ID
        LEFT  JOIN LINKS L   ON L.PARENT_TYPE_ID = 54 AND L.OBJ_ID = L187.OBJ_ID AND L.DATE_DEL IS NULL
        WHERE L7.PARENT_ID = :V$OBJ_ID
          AND L7.OBJ_TYPE_ID = 7
          AND L7.DATE_DEL IS NULL
          AND L8.OBJ_TYPE_ID = 8
          AND L8.DATE_DEL IS NULL
          AND L187.OBJ_TYPE_ID = 187
          AND L187.DATE_DEL IS NULL
          AND V49.PARAM_ID = 49
          AND V49.IS_DEL = 0
          AND V49.LISTVAL_ID = :V$PLAN_STAGE_INDEX
          AND L.LINK_ID IS NULL
         INTO :OBJ_ID
    DO
    BEGIN
        SELECT CAPTION, SORT_ORDER
        FROM OBJECT_CAPTION_GET(:OBJ_ID, NULL, NULL, :I$USER_ID)
        INTO :OBJ_CAPTION, :SORT_ORDER;
        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_LOADING_PUPIL_LIST (
    I$STAGE_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    OBJ_ID2 BIGINT,
    OBJ_CAPTION VARCHAR(4000),
    OBJ_CAPTION2 VARCHAR(4000),
    TYPE_ID BIGINT,
    TYPE_ID2 BIGINT,
    SORT_ORDER DOUBLE PRECISION)
AS
declare variable V$OBJ_ID bigint;
BEGIN
    TYPE_ID = 10;
    TYPE_ID2 = 9;
    SELECT FIRST 1
           OBJ_ID
    FROM OBJECT_PARENTS_GET(:I$STAGE_ID, 2)
    INTO :V$OBJ_ID;

    FOR
        SELECT DISTINCT
               O10.OBJ_ID,
               O9.OBJ_ID
        FROM LINKS L7
        INNER JOIN OBJECTS O7
        ON O7.OBJ_ID = L7.OBJ_ID
        AND O7.TYPE_ID = 7

        INNER JOIN LINKS L8
        ON L8.PARENT_ID = O7.OBJ_ID
        AND L8.DATE_DEL IS NULL
        INNER JOIN OBJECTS O8
        ON O8.OBJ_ID = L8.OBJ_ID
        AND O8.TYPE_ID = 8

        INNER JOIN LINKS L9
        ON L9.PARENT_ID = O8.OBJ_ID
        AND L9.DATE_DEL IS NULL
        INNER JOIN OBJECTS O9
        ON O9.OBJ_ID = L9.OBJ_ID
        AND O9.TYPE_ID = 9

        INNER JOIN LINKS LS
        ON LS.PARENT_ID = :I$STAGE_ID
        AND LS.OBJ_ID  = O9.OBJ_ID
        AND LS.DATE_DEL IS NULL

        INNER JOIN LINKS L10
        ON L10.PARENT_ID = O9.OBJ_ID
        AND L10.DATE_DEL IS NULL
        INNER JOIN OBJECTS O10
        ON O10.OBJ_ID = L10.OBJ_ID
        AND O10.TYPE_ID = 10

        LEFT OUTER JOIN LINKS LS2
        ON LS2.PARENT_ID = :I$STAGE_ID
        AND LS2.OBJ_ID = O10.OBJ_ID
        AND LS2.DATE_DEL IS NULL

        WHERE L7.PARENT_ID = :V$OBJ_ID
        AND L7.DATE_DEL IS NULL
        AND LS2.LINK_ID IS NULL

        INTO   :OBJ_ID, :OBJ_ID2
    DO
    BEGIN
        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:OBJ_ID, 49, NULL, :I$USER_ID)
        INTO   :OBJ_CAPTION;

        SELECT CAPTION,
               SORT_ORDER
        FROM OBJECT_CAPTION_GET(:OBJ_ID2, 49, NULL, :I$USER_ID)
        INTO   :OBJ_CAPTION2,
               :SORT_ORDER;


        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_LOADING_ST_CLASS_LIST (
    I$STAGE_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    OBJ_CAPTION VARCHAR(4000),
    SORT_ORDER DOUBLE PRECISION)
AS
declare variable V$OBJ_ID bigint;
declare variable V$PLAN_STAGE_INDEX bigint;
BEGIN
    SELECT FIRST 1 OBJ_ID FROM OBJECT_PARENTS_GET(:I$STAGE_ID, 2) INTO :V$OBJ_ID;

    SELECT I FROM VAL_GET(:I$STAGE_ID,381,0,:I$USER_ID) INTO :V$PLAN_STAGE_INDEX;

    FOR SELECT DISTINCT L9.OBJ_ID
        FROM LINKS L7
        INNER JOIN LINKS L8  ON L8.PARENT_ID = L7.OBJ_ID
        INNER JOIN LINKS L9  ON L9.PARENT_ID = L8.OBJ_ID
        INNER JOIN VALL  V49 ON V49.OBJ_ID = L8.OBJ_ID
        LEFT  JOIN LINKS L   ON L.PARENT_TYPE_ID = 54 AND L.OBJ_ID = L9.OBJ_ID AND L.DATE_DEL IS NULL
        WHERE L7.PARENT_ID = :V$OBJ_ID
          AND L7.OBJ_TYPE_ID = 7
          AND L7.DATE_DEL IS NULL
          AND L8.OBJ_TYPE_ID = 8
          AND L8.DATE_DEL IS NULL
          AND L9.OBJ_TYPE_ID = 9
          AND L9.DATE_DEL IS NULL
          AND V49.PARAM_ID = 49
          AND V49.IS_DEL = 0
          AND V49.LISTVAL_ID = :V$PLAN_STAGE_INDEX
          AND L.LINK_ID IS NULL
         INTO :OBJ_ID
    DO
    BEGIN
        SELECT CAPTION, SORT_ORDER
        FROM OBJECT_CAPTION_GET(:OBJ_ID, NULL, NULL, :I$USER_ID)
        INTO :OBJ_CAPTION, :SORT_ORDER;
        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_LOADING_ST_STREAM_LIST (
    I$STAGE_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    OBJ_CAPTION VARCHAR(4000),
    SORT_ORDER DOUBLE PRECISION)
AS
declare variable V$OBJ_ID bigint;
BEGIN
    SELECT FIRST 1 OBJ_ID
    FROM OBJECT_PARENTS_GET(:I$STAGE_ID, 2)
    INTO :V$OBJ_ID;

    FOR SELECT DISTINCT O.OBJ_ID
        FROM OBJECT_CHILDREN_GET_DEEP(:V$OBJ_ID, 46, 2) O
        LEFT OUTER JOIN LINKS L ON L.PARENT_ID = :I$STAGE_ID AND L.OBJ_ID = O.OBJ_ID AND L.DATE_DEL IS NULL
        WHERE L.LINK_ID IS NULL
        INTO :OBJ_ID
    DO
    BEGIN
        SELECT CAPTION, SORT_ORDER
        FROM OBJECT_CAPTION_GET(:OBJ_ID, NULL, NULL, :I$USER_ID)
        INTO :OBJ_CAPTION, :SORT_ORDER;

        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_LOADING_ST_UNION_LIST (
    I$STAGE_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    OBJ_CAPTION VARCHAR(4000),
    SORT_ORDER DOUBLE PRECISION)
AS
declare variable V$OBJ_ID bigint;
BEGIN
    SELECT FIRST 1 OBJ_ID
    FROM OBJECT_PARENTS_GET(:I$STAGE_ID, 252)
    INTO :V$OBJ_ID;

    FOR
        SELECT DISTINCT
               L243.OBJ_ID

        FROM VALR V2151

        JOIN LINKS L243
        ON L243.PARENT_ID = V2151.VAL
        AND L243.OBJ_TYPE_ID = 243
        AND L243.DATE_DEL IS NULL

        LEFT JOIN LINKS L

        ON L.PARENT_ID = :I$STAGE_ID
        AND L.OBJ_ID = L243.OBJ_ID
        AND L.DATE_DEL IS NULL

        WHERE V2151.OBJ_ID = :V$OBJ_ID
        AND V2151.PARAM_ID = 2151
        AND V2151.IS_DEL = 0

        AND L.LINK_ID IS NULL
        INTO :OBJ_ID
    DO
    BEGIN
        SELECT CAPTION, SORT_ORDER
        FROM OBJECT_CAPTION_GET(:OBJ_ID, NULL, NULL, :I$USER_ID)
        INTO :OBJ_CAPTION, :SORT_ORDER;

        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_LOADING_SUBJECTS (
    I$COMPONENT_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    OBJ_CAPTION VARCHAR(4000),
    SORT_ORDER DOUBLE PRECISION,
    OBJ302_CAPTION VARCHAR(1000),
    IS_SELECTABLE SMALLINT,
    REPLACE_ID BIGINT,
    IS_PROFILE SMALLINT)
AS
declare variable V$LISTVAL_ID bigint;
declare variable V$OBJ_ID bigint;
BEGIN
    -- Получаем уровень образования
    -- для шаблонов он в параметре 2503 самого УП, для реальных УП он в вышестоящем уровне
    SELECT COALESCE(V2503.LISTVAL_ID, V1594.LISTVAL_ID)
    FROM LINKS LP50
    -- Выборка уровня для шаблонов
    LEFT JOIN VALL V2503 ON V2503.OBJ_ID = LP50.PARENT_ID AND V2503.PARAM_ID = 2503 AND V2503.IS_DEL = 0 AND V2503.LISTVAL_ID IN (5339,5341,5343)
    -- Выборка уровня для обычных УП
    LEFT JOIN LINKS LP57 ON LP57.OBJ_ID = LP50.PARENT_ID AND LP57.DATE_DEL is null AND LP57.PARENT_TYPE_ID IN (57, 244, 252)
    LEFT JOIN VALL V1594 ON V1594.OBJ_ID = LP57.PARENT_ID AND V1594.IS_DEL = 0 AND V1594.PARAM_ID IN (1594, 2132, 2146)
    WHERE LP50.OBJ_ID = :I$COMPONENT_ID AND LP50.PARENT_TYPE_ID = 50 AND LP50.DATE_DEL IS NULL
    INTO :V$LISTVAL_ID;

    -- Коррекцию предметной области не делаем, это для толстого клиента

    FOR
        SELECT L51.OBJ_ID, L51.COST, IIF(V2816.LISTVAL_ID = 2, 1, 0)
        FROM LINKS L51
        LEFT JOIN VALL V2816 ON V2816.OBJ_ID = L51.OBJ_ID AND V2816.PARAM_ID = 2816 AND V2816.IS_DEL = 0
        WHERE L51.PARENT_ID = :I$COMPONENT_ID AND L51.OBJ_TYPE_ID = 51 AND L51.DATE_DEL IS NULL
        INTO :OBJ_ID, :SORT_ORDER, :IS_SELECTABLE
    DO
    BEGIN
        SELECT CAPTION, IIF(:SORT_ORDER > 0, :SORT_ORDER, SORT_ORDER)
        FROM OBJECT_CAPTION_GET(:OBJ_ID, NULL)
        INTO :OBJ_CAPTION, :SORT_ORDER;

        -- Не позволяем при сортировке переходить границу 1E15, чтобы обычные предметы не залезли в элективные
        IF(SORT_ORDER >= 1E15 - 1) THEN SORT_ORDER = 1E15 - 1;

        OBJ302_CAPTION = NULL;
        V$OBJ_ID = 999999;

        -- Выбираем замену предмета
        REPLACE_ID = OBJ_ID;
        SELECT V2718.VAL
        FROM LINKS L349
        JOIN VALR V2719 ON V2719.OBJ_ID = L349.OBJ_ID AND V2719.PARAM_ID = 2719 AND V2719.IS_DEL = 0 AND V2719.VAL = :OBJ_ID
        JOIN VALR V2718 ON V2718.OBJ_ID = L349.OBJ_ID AND V2718.PARAM_ID = 2718 AND V2718.IS_DEL = 0
        WHERE L349.PARENT_ID = :I$COMPONENT_ID AND L349.OBJ_TYPE_ID = 349 AND L349.DATE_DEL IS NULL
        INTO :REPLACE_ID;

        -- Проверяем, является ли предмет профильным
        IS_PROFILE = 0;

        SELECT FIRST 1 1
        FROM LINKS LP50
        JOIN LINKS L51 ON L51.PARENT_ID = LP50.PARENT_ID AND L51.OBJ_TYPE_ID = 51 AND L51.DATE_DEL IS NULL AND L51.OBJ_ID = :OBJ_ID
        WHERE LP50.OBJ_ID = :I$COMPONENT_ID AND LP50.PARENT_TYPE_ID = 50 AND LP50.DATE_DEL IS NULL
        INTO :IS_PROFILE;

        -- Для иностранных языков для начального образования исключаем область 11684 (Иностранные языки), для прочих 12740 (Иностранный язык)
        -- Остальное по таблице
        -- 2339 начальное, 5341 общее, 5343 среднее

        SELECT FIRST 1 (SELECT V FROM VAL_GET(L302.OBJ_ID, 2462)), L302.OBJ_ID
        FROM LINKS L302
        JOIN VALL V2462 ON V2462.OBJ_ID = L302.OBJ_ID AND V2462.PARAM_ID = 2462 AND V2462.IS_DEL = 0
        WHERE L302.PARENT_ID = :OBJ_ID AND L302.OBJ_TYPE_ID = 302 AND L302.DATE_DEL IS NULL
          AND (
             ((:V$LISTVAL_ID = 5339) AND (V2462.LISTVAL_ID IN (12740, 11680, 11682, 11685, 11686, 11689, 11693, 11694, 11695))) OR
             ((:V$LISTVAL_ID = 5341) AND (V2462.LISTVAL_ID IN (11684, 11681, 11683, 11685, 11687, 11690, 11691, 11693, 11694, 11696))) OR
             ((:V$LISTVAL_ID = 5343) AND (V2462.LISTVAL_ID IN (11684, 11681, 11683, 11685, 11688, 11690, 11692, 11693, 11694, 11696, 11697)))
          )
        INTO :OBJ302_CAPTION, :V$OBJ_ID;

        -- Порядок сортировки делаем ровно такой, как настроен пользователем
        -- Элективные курсы всегда помещаем в конце списка, и только после своего корневого заголовка
        IF(OBJ_ID = 34607) THEN SORT_ORDER = 1E15;
        ELSE IF(IS_SELECTABLE = 1) THEN SORT_ORDER = SORT_ORDER + 1E15 + 1;

        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_LOADING_VALS_ADD (
    I$OBJ_ID BIGINT,
    I$STAGE_ID BIGINT,
    I$SUBJECT_ID BIGINT,
    I$COMPONENT_ID BIGINT,
    I$VAL INTEGER,
    I$WEEKS INTEGER,
    I$OOOD_PARTNER INTEGER,
    I$LESSON_METHOD_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable BLOB_ID bigint;
declare variable V$REFS integer;
BEGIN
    IF (I$OBJ_ID IS NULL) THEN
    BEGIN
        SELECT FIRST 1 L56.OBJ_ID
        FROM LINKS L56
        JOIN LINKS L51_56 ON L51_56.PARENT_ID = :I$SUBJECT_ID AND L51_56.OBJ_ID = L56.OBJ_ID AND L51_56.DATE_DEL IS NULL
        JOIN LINKS L54_56 ON L54_56.PARENT_ID = :I$STAGE_ID AND L54_56.OBJ_ID = L56.OBJ_ID AND L54_56.DATE_DEL IS NULL
        WHERE L56.PARENT_ID = :I$COMPONENT_ID AND L56.OBJ_TYPE_ID = 56 AND L56.DATE_DEL IS NULL
        INTO :I$OBJ_ID;
    END

    IF (I$OBJ_ID IS NULL) THEN
    BEGIN
        SELECT OBJ_ID FROM OBJECT_ADD(:I$STAGE_ID,56) INTO :OBJ_ID;
        SELECT OBJ_ID FROM OBJECT_ADD_LINK(:I$SUBJECT_ID, :OBJ_ID, 56) INTO :OBJ_ID;
        SELECT OBJ_ID FROM OBJECT_ADD_LINK(:I$COMPONENT_ID,:OBJ_ID,56) INTO :OBJ_ID;
    END
    ELSE
    BEGIN
        OBJ_ID = I$OBJ_ID;
    END

    -- При обнулении часов нагрузки должен быть сначала убран преподаватель
    IF(I$VAL IS NULL OR I$VAL = 0) THEN
    BEGIN
        SELECT COUNT(*)
        FROM LINKS L58
        JOIN LINKS LP14 ON LP14.OBJ_ID = L58.OBJ_ID AND LP14.PARENT_TYPE_ID = 14 AND LP14.DATE_DEL IS NULL
        WHERE L58.PARENT_ID = :I$OBJ_ID AND L58.OBJ_TYPE_ID = 58 AND L58.DATE_DEL IS NULL
        INTO :V$REFS;

        IF(V$REFS > 0) THEN EXCEPTION DATA_ERROR 'По данному предмету есть назначенные преподаватели, удаление нагрузки невозможно';
    END

    SELECT BLOB_ID FROM VAL_ADD(385, :OBJ_ID, :I$VAL) INTO :BLOB_ID;
    SELECT BLOB_ID FROM VAL_ADD(2547, :OBJ_ID, :I$WEEKS) INTO :BLOB_ID;

    IF (I$OOOD_PARTNER = 1) THEN
    BEGIN
        I$OOOD_PARTNER = 2;
    END
    ELSE
    BEGIN
        I$OOOD_PARTNER = 3;
    END

    SELECT BLOB_ID
    FROM VAL_ADD(1893,:OBJ_ID,:I$OOOD_PARTNER)
    INTO :BLOB_ID;

    IF (I$LESSON_METHOD_ID > 0) THEN
    BEGIN
        SELECT BLOB_ID
        FROM VAL_ADD(2125,:OBJ_ID,:I$LESSON_METHOD_ID)
        INTO :BLOB_ID;
    END
    ELSE
    BEGIN
        UPDATE VALL
        SET IS_DEL = 1
        WHERE OBJ_ID = :OBJ_ID AND PARAM_ID = 2125 AND IS_DEL = 0;
    END

    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_LOADING_VALS_LIST (
    I$OBJ_ID BIGINT,
    I$COMPONENT_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    STAGE_ID BIGINT,
    SUBJECT_ID BIGINT,
    COMPONENT_ID BIGINT,
    OBJ_ID BIGINT,
    STAGE_LOADING_PERIOD INTEGER,
    STAGE_LOADING_LIMIT INTEGER,
    VAL INTEGER,
    WEEKS INTEGER,
    UMK1 INTEGER,
    UMK2 INTEGER,
    UMK3 INTEGER,
    UMK4 INTEGER,
    UMK5 INTEGER,
    OOOD_PARTNER INTEGER,
    LESSON_METHOD_ID BIGINT,
    LESSON_METHOD VARCHAR(255))
AS
declare variable V$OBJ_ID bigint;
declare variable V$COST float;
declare variable V$LISTVAL_ID bigint;
BEGIN
    COMPONENT_ID = I$COMPONENT_ID;
    FOR
        SELECT L54.OBJ_ID
        FROM LINKS L54
        WHERE L54.PARENT_ID = :I$OBJ_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
        INTO :STAGE_ID
    DO
    BEGIN
        SELECT I FROM VAL_GET(:STAGE_ID,382,0,:I$USER_ID) INTO :STAGE_LOADING_PERIOD;
        SELECT I FROM VAL_GET(:STAGE_ID,383,0,:I$USER_ID) INTO :STAGE_LOADING_LIMIT;
        FOR
            SELECT L51.OBJ_ID
            FROM LINKS L51
            WHERE L51.PARENT_ID = :I$COMPONENT_ID AND L51.OBJ_TYPE_ID = 51 AND L51.DATE_DEL IS NULL
            INTO :SUBJECT_ID
        DO
        BEGIN
            VAL = NULL;
            OBJ_ID = NULL;
            WEEKS = STAGE_LOADING_PERIOD;
            UMK1 = 0;
            UMK2 = 0;
            UMK3 = 0;
            UMK4 = 0;
            UMK5 = 0;
            OOOD_PARTNER = 0;
            LESSON_METHOD_ID = 0;
            LESSON_METHOD = NULL;
            FOR
                SELECT FIRST 1 L56.OBJ_ID
                FROM LINKS L56
                JOIN LINKS L51_56 ON L51_56.PARENT_ID = :SUBJECT_ID AND L51_56.OBJ_ID = L56.OBJ_ID AND L51_56.DATE_DEL IS NULL
                JOIN LINKS L49_56 ON L49_56.PARENT_ID = :I$COMPONENT_ID AND L49_56.OBJ_ID = L56.OBJ_ID AND L49_56.DATE_DEL IS NULL
                JOIN VALI V385 ON V385.OBJ_ID = L56.OBJ_ID AND V385.PARAM_ID = 385 AND V385.IS_DEL = 0 AND V385.VAL > 0
                WHERE L56.PARENT_ID = :STAGE_ID AND L56.OBJ_TYPE_ID = 56 AND L56.DATE_DEL IS NULL
                INTO :OBJ_ID
            DO
            BEGIN
                SELECT COUNT(*)
                FROM LINKS
                WHERE PARENT_ID = :OBJ_ID AND OBJ_TYPE_ID = 52 AND DATE_DEL IS NULL
                INTO :UMK1;

                SELECT COUNT(*)
                FROM LINKS
                WHERE PARENT_ID = :OBJ_ID AND OBJ_TYPE_ID = 106 AND DATE_DEL IS NULL
                INTO :UMK5;

                FOR
                    SELECT L107.OBJ_ID, COALESCE(L107.COST, 0)
                    FROM LINKS L107
                    /* Отслеживаем чтобы не попали удаленные учебники */
                    JOIN LINKS L105 ON L105.PARENT_TYPE_ID = 105 AND L105.OBJ_ID = L107.OBJ_ID AND L105.DATE_DEL IS NULL
                    WHERE L107.PARENT_ID = :OBJ_ID AND L107.OBJ_TYPE_ID = 107 AND L107.DATE_DEL IS NULL
                    INTO :V$OBJ_ID, :V$COST
                DO
                BEGIN
                    SELECT I FROM VAL_GET(:V$OBJ_ID, 653, 0, :I$USER_ID) INTO :V$LISTVAL_ID;
                    IF (V$LISTVAL_ID = 2097) THEN UMK2 = UMK2 + 1;
                    ELSE IF (V$LISTVAL_ID = 2098) THEN UMK3 = UMK3 + 1;
                    ELSE IF (V$LISTVAL_ID = 2099) THEN UMK4 = UMK4 + V$COST;
                END

                SELECT I FROM VAL_GET(:OBJ_ID, 385, 0, :I$USER_ID) INTO :VAL;
                IF (VAL = 0) THEN VAL = NULL;
                SELECT I FROM VAL_GET(:OBJ_ID, 2547, 0, :I$USER_ID) INTO :WEEKS;
                IF (WEEKS = 0) THEN WEEKS = NULL;

                SELECT I, V FROM VAL_GET(:OBJ_ID,2125,0,:I$USER_ID) INTO :LESSON_METHOD_ID, :LESSON_METHOD;

                IF (VAL IS NOT NULL) THEN
                BEGIN
                    SELECT I FROM VAL_GET(:OBJ_ID, 1893, 0, :I$USER_ID) INTO :OOOD_PARTNER;
                    IF(OOOD_PARTNER = 2) THEN OOOD_PARTNER = 1; ELSE OOOD_PARTNER = 0;
                END
                ELSE OOOD_PARTNER = 0;
            END

            SUSPEND;
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_MAKER_LIST RETURNS (
    LISTVAL_ID BIGINT,
    PARENT_ID BIGINT,
    VAL VARCHAR(1000),
    VAL_LONG VARCHAR(1000))
AS
BEGIN
    LISTVAL_ID = 0;
    PARENT_ID = 0;
    VAL_LONG = NULL;
    FOR
        SELECT DISTINCT
               VS.VAL
        FROM VALS VS
        WHERE VS.PARAM_ID=677
        AND VS.IS_DEL = 0
        AND EXISTS(SELECT FIRST 1 1 FROM LINKS L WHERE L.OBJ_ID = VS.OBJ_ID AND L.DATE_DEL IS NULL)
        ORDER BY VS.VAL
        INTO :VAL
    DO
    BEGIN
        LISTVAL_ID = LISTVAL_ID + 1;
        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_MOVEMENT_IS_OUT_IN (
    I$PUPIL_ID BIGINT)
RETURNS (
    IS_OUT_IN SMALLINT)
AS
BEGIN
    IS_OUT_IN = 1;

    SELECT FIRST 1 0
    FROM LINKS L
    JOIN VALL V1363 ON V1363.OBJ_ID = L.PARENT_ID AND V1363.PARAM_ID IN (2388, 2418) AND V1363.IS_DEL = 0 AND V1363.LISTVAL_ID <> 11217
    WHERE L.OBJ_ID = :I$PUPIL_ID AND L.PARENT_TYPE_ID IN (9, 187) AND L.DATE_DEL IS NULL
    INTO :IS_OUT_IN;

    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_MOVEMENT_MAXDATE (
    I$PUPIL_ID BIGINT)
RETURNS (
    ACTION_DATE DATE)
AS
BEGIN
    SELECT MAX(DT)
    FROM (
        SELECT M.DATE_IN DT
        FROM PERSON_MOVEMENTS M
        JOIN OBJECTS O ON O.OBJ_ID = M.GROUP_ID AND O.TYPE_ID IN (9, 125, 187)
        WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :I$PUPIL_ID AND M.REASON_IN <> 5548
        UNION
        SELECT M.DATE_OUT DT
        FROM PERSON_MOVEMENTS M
        JOIN OBJECTS O ON O.OBJ_ID = M.GROUP_ID AND O.TYPE_ID IN (9, 125, 187)
        WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :I$PUPIL_ID AND M.REASON_OUT <> 5548 AND M.DATE_OUT IS NOT NULL
    )
    INTO :ACTION_DATE;

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_NOT_LINKED_LIST_KK (
    I$OBJ_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    OBJ_CAPTION VARCHAR(4000),
    SORT_ORDER DOUBLE PRECISION)
AS
declare variable V$OBJ_ID bigint;
BEGIN
    V$OBJ_ID = NULL;

    SELECT FIRST 1 OBJ_ID FROM OBJECT_PARENTS_GET(:I$OBJ_ID, 23) INTO :V$OBJ_ID;

    IF (V$OBJ_ID IS NULL) THEN EXIT;

    FOR SELECT DISTINCT L114.OBJ_ID
        FROM LINKS L95
        INNER JOIN LINKS L114  ON L114.PARENT_ID = L95.OBJ_ID
        LEFT  JOIN LINKS L000  ON L000.OBJ_ID = L114.OBJ_ID
                              AND L000.PARENT_TYPE_ID = 128
                              AND L000.OBJ_TYPE_ID = 114
                              AND L000.DATE_DEL IS NULL
        WHERE L95.PARENT_ID = :V$OBJ_ID
        AND  L95.OBJ_TYPE_ID = 95
        AND  L95.DATE_DEL IS NULL
        AND L114.OBJ_TYPE_ID = 114
        AND L114.DATE_DEL IS NULL
        AND L000.LINK_ID  IS NULL
        INTO   :OBJ_ID
    DO
    BEGIN
        SELECT CAPTION, SORT_ORDER
        FROM OBJECT_CAPTION_GET(:OBJ_ID, NULL, NULL, :I$USER_ID)
        INTO :OBJ_CAPTION, :SORT_ORDER;
        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_PERIODS_ST_CLASS_LIST (
    I$PERIOD_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    OBJ_CAPTION VARCHAR(4000),
    SORT_ORDER DOUBLE PRECISION)
AS
declare variable V$OBJ_ID bigint;
BEGIN
    SELECT FIRST 1 OBJ_ID FROM OBJECT_PARENTS_GET(:I$PERIOD_ID, 2) INTO :V$OBJ_ID;

    FOR SELECT DISTINCT L9.OBJ_ID
        FROM LINKS L7
        INNER JOIN LINKS L8  ON L8.PARENT_ID = L7.OBJ_ID
        INNER JOIN LINKS L9  ON L9.PARENT_ID = L8.OBJ_ID
        LEFT  JOIN LINKS L151 ON L151.PARENT_TYPE_ID = 151 AND L151.OBJ_ID = L9.OBJ_ID AND L151.DATE_DEL IS NULL
        WHERE L7.PARENT_ID = :V$OBJ_ID
          AND L7.OBJ_TYPE_ID = 7
          AND L7.DATE_DEL IS NULL
          AND L8.OBJ_TYPE_ID = 8
          AND L8.DATE_DEL IS NULL
          AND L9.OBJ_TYPE_ID = 9
          AND L9.DATE_DEL IS NULL
          AND L151.LINK_ID IS NULL
         INTO :OBJ_ID
    DO
    BEGIN
        SELECT CAPTION, SORT_ORDER
        FROM OBJECT_CAPTION_GET(:OBJ_ID, NULL, NULL, :I$USER_ID)
        INTO :OBJ_CAPTION, :SORT_ORDER;
        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_PERIODS_ST_GUP_LIST (
    I$PERIOD_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    OBJ_CAPTION VARCHAR(4000),
    SORT_ORDER DOUBLE PRECISION)
AS
declare variable V$OBJ_ID bigint;
BEGIN
    SELECT FIRST 1 OBJ_ID FROM OBJECT_PARENTS_GET(:I$PERIOD_ID, 2) INTO :V$OBJ_ID;

    FOR
        SELECT DISTINCT
               L256.OBJ_ID
        FROM LINKS L69

        JOIN LINKS L57
        ON L57.PARENT_ID = L69.OBJ_ID
        AND L57.OBJ_TYPE_ID = 57
        AND L57.DATE_DEL IS NULL

        JOIN LINKS L50
        ON L50.PARENT_ID = L57.OBJ_ID
        AND L50.OBJ_TYPE_ID = 50
        AND L50.DATE_DEL IS NULL

        JOIN LINKS L54
        ON L54.PARENT_ID = L50.OBJ_ID
        AND L54.OBJ_TYPE_ID = 54
        AND L54.DATE_DEL IS NULL

        JOIN LINKS L256
        ON L256.PARENT_ID = L54.OBJ_ID
        AND L256.OBJ_TYPE_ID = 256
        AND L256.DATE_DEL IS NULL

        LEFT JOIN LINKS LP151
        ON LP151.PARENT_TYPE_ID = 151
        AND LP151.OBJ_ID = L256.OBJ_ID
        AND LP151.DATE_DEL IS NULL

        WHERE L69.PARENT_ID = :V$OBJ_ID
        AND L69.OBJ_TYPE_ID = 69
        AND L69.DATE_DEL IS NULL


        AND LP151.LINK_ID IS NULL
        INTO :OBJ_ID
    DO
    BEGIN
        SELECT CAPTION, SORT_ORDER
        FROM OBJECT_CAPTION_GET(:OBJ_ID, NULL, NULL, :I$USER_ID)
        INTO :OBJ_CAPTION, :SORT_ORDER;
        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_PERIODS_ST_STM_LIST (
    I$PERIOD_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    OBJ_CAPTION VARCHAR(4000),
    SORT_ORDER DOUBLE PRECISION)
AS
declare variable V$OBJ_ID bigint;
declare variable PAR_NAME varchar(200);
declare variable SUBJECT_NAME varchar(1000);
declare variable GROUP_NAME varchar(1000);
BEGIN
    SELECT FIRST 1 OBJ_ID FROM OBJECT_PARENTS_GET(:I$PERIOD_ID, 2) INTO :V$OBJ_ID;

    FOR
        SELECT DISTINCT L347.OBJ_ID, LV.SORT_ORDER, CAST(PR.VAL AS VARCHAR(100)), CAST(V376.VAL AS VARCHAR(1000)), CAST(V2706.VAL AS VARCHAR(1000))
        FROM LINKS L69
        JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
        JOIN LINKS L50 ON L50.PARENT_ID = L57.OBJ_ID AND L50.OBJ_TYPE_ID = 50 AND L50.DATE_DEL IS NULL
        JOIN LINKS L54 ON L54.PARENT_ID = L50.OBJ_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
        JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
        -- Название параллели
        JOIN LISTVALS LV ON LV.LISTVAL_ID = V381.LISTVAL_ID
        JOIN RES PR ON PR.RES_ID = LV.RES_ID AND PR.LANG_CODE = 'RU'
        JOIN LINKS L346 ON L346.PARENT_ID = L54.OBJ_ID AND L346.OBJ_TYPE_ID = 346 AND L346.DATE_DEL IS NULL
        -- Предмет
        JOIN VALR V2705 ON V2705.OBJ_ID = L346.OBJ_ID AND V2705.PARAM_ID = 2705 AND V2705.IS_DEL = 0
        JOIN VALS V376 ON V376.OBJ_ID = V2705.VAL AND V376.PARAM_ID = 376 AND V376.IS_DEL = 0
        -- Название потока
        JOIN LINKS L347 ON L347.PARENT_ID = L346.OBJ_ID AND L347.OBJ_TYPE_ID = 347 AND L347.DATE_DEL IS NULL
        JOIN VALS V2706 ON V2706.OBJ_ID = L347.OBJ_ID AND V2706.PARAM_ID = 2706 AND V2706.IS_DEL = 0
        LEFT JOIN LINKS LP151 ON LP151.PARENT_TYPE_ID = 151 AND LP151.OBJ_ID = L347.OBJ_ID AND LP151.DATE_DEL IS NULL
        WHERE L69.PARENT_ID = :V$OBJ_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL AND LP151.LINK_ID IS NULL
        INTO :OBJ_ID, :SORT_ORDER, :PAR_NAME, :SUBJECT_NAME, :GROUP_NAME
    DO
    BEGIN
        PAR_NAME = REPLACE(PAR_NAME, 'параллель', 'классы');
        IF(CHAR_LENGTH(SUBJECT_NAME) > 100) THEN SUBJECT_NAME = SUBSTRING(SUBJECT_NAME FROM 1 FOR 100) || '...';

        OBJ_CAPTION = PAR_NAME || ' - ' || SUBJECT_NAME || ' - ' || GROUP_NAME;
        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_PERIODS_ST_VGRP_LIST (
    I$PERIOD_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    OBJ_CAPTION VARCHAR(4000),
    SORT_ORDER DOUBLE PRECISION)
AS
declare variable V$OBJ_ID bigint;
declare variable V$YEAR_ID bigint;
BEGIN
    SELECT FIRST 1 P.OBJ_ID, V1236.LISTVAL_ID
    FROM OBJECT_PARENTS_GET(:I$PERIOD_ID, 2) P
    JOIN VALL V1236 ON V1236.OBJ_ID = P.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
    INTO :V$OBJ_ID, :V$YEAR_ID;

    FOR
        SELECT DISTINCT J.GRADE_ID
        FROM CJ2_JOURNAL J
        JOIN LINKS L179 ON L179.OBJ_ID = J.GRADE_ID AND L179.OBJ_TYPE_ID = 179 AND L179.PARENT_TYPE_ID = 2 AND L179.DATE_DEL IS NULL
        LEFT JOIN LINKS LP151 ON LP151.PARENT_TYPE_ID = 151 AND LP151.OBJ_ID = L179.OBJ_ID AND LP151.DATE_DEL IS NULL
        WHERE J.JOURNAL_TYPE IN (0, 1) AND J.DATE_DEL IS NULL AND LP151.LINK_ID IS NULL
        INTO :OBJ_ID
    DO
    BEGIN
        SELECT CAPTION, SORT_ORDER
        FROM OBJECT_CAPTION_GET(:OBJ_ID, NULL, NULL, :I$USER_ID)
        INTO :OBJ_CAPTION, :SORT_ORDER;
        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_PTP_LINK_LIST (
    I$OBJ_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    PARENT_ID BIGINT,
    OBJ_CAPTION VARCHAR(4000),
    SORT_ORDER DOUBLE PRECISION)
AS
declare variable V$SUBJECT_ID bigint;
declare variable V$STAGE_ID bigint;
BEGIN
    -- Похоронено
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_PUPIL_NOT_LINKED_LIST (
    I$GROUP_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    PARENT_ID BIGINT,
    OBJ_CAPTION VARCHAR(4000),
    SORT_ORDER DOUBLE PRECISION)
AS
declare variable V$UNION_ID bigint;
declare variable V$SEPARATOR_ID bigint;
BEGIN
    PARENT_ID = NULL;
    FOR
        SELECT FIRST 1
               LP.PARENT_ID,
               LP47.PARENT_ID
        FROM LINKS LP47

        JOIN LINKS LP
        ON LP.OBJ_ID = LP47.PARENT_ID
        AND LP.PARENT_TYPE_ID IN (9, 243, 46)
        AND LP.DATE_DEL IS NULL

        WHERE LP47.OBJ_ID = :I$GROUP_ID
        AND LP47.PARENT_TYPE_ID = 47
        AND LP47.DATE_DEL IS NULL

        INTO :V$UNION_ID,
             :V$SEPARATOR_ID
    DO
    BEGIN
        FOR
            SELECT L10.OBJ_ID
    
            FROM LINKS L10
    
            WHERE L10.PARENT_ID = :V$UNION_ID
            AND L10.OBJ_TYPE_ID = 10
            AND L10.DATE_DEL IS NULL

            AND NOT EXISTS (
                SELECT FIRST 1 1

                FROM LINKS LP48

                JOIN LINKS LP47
                ON LP47.OBJ_ID = LP48.PARENT_ID
                AND LP47.PARENT_TYPE_ID = 47
                AND LP47.DATE_DEL IS NULL
                AND LP47.PARENT_ID = :V$SEPARATOR_ID

                WHERE LP48.OBJ_ID = L10.OBJ_ID
                AND LP48.PARENT_TYPE_ID = 48
                AND LP48.DATE_DEL IS NULL
            )

            INTO :OBJ_ID
        DO
        BEGIN
            SELECT CAPTION, SORT_ORDER
            FROM OBJECT_CAPTION_GET(:OBJ_ID, NULL, NULL, :I$USER_ID)
            INTO :OBJ_CAPTION, :SORT_ORDER;
    
            SUSPEND;
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_PUPIL_REVERT (
    I$PUPIL_ID BIGINT,
    I$MOVEMENT_ID BIGINT)
RETURNS (
    X SMALLINT,
    OBJ_ID BIGINT,
    OBJ_CAPTION VARCHAR(4000))
AS
declare variable V$BLOB_ID bigint;
declare variable V$DATE_OUT date;
declare variable V$FOLDER_ID bigint;
declare variable V$GROUP_ID bigint;
declare variable V$LINK_ID bigint;
declare variable V$DT timestamp;
declare variable V$STAGE bigint;
BEGIN

    -- Возвращаемое значение в X:
    -- 0 = невозможно выполнить отмену из-за нехватки данных
    -- 1 = возвращен в ...
    -- 2 = удален из ...
    -- 101 = невозможно отменить из-за расформирования последнего класса

    SELECT M.DATE_OUT, M.GROUP_ID, M.DATE_MODIFY, M.STAGE_ID
    FROM PERSON_MOVEMENTS M
    WHERE M.OBJ_ID = :I$MOVEMENT_ID AND M.DATE_DEL IS NULL
    INTO :V$DATE_OUT, :OBJ_ID, :V$DT, :V$STAGE;

    IF(V$DATE_OUT IS NULL) THEN
    BEGIN
      -- Отменяем зачисление
      SELECT OBJ_ID FROM VARGRP_MOVE_PUPIL(:I$PUPIL_ID, :OBJ_ID, NULL, NULL, NULL, 3, NULL) INTO :V$BLOB_ID;

      -- Смотрим что у нас с последним выбытием - его нужно тоже отменить, если оно было сделано синхронно (не раньше 1 минуты до основного выбытия)
      -- группы + академический отпуск
      SELECT FIRST 1 M.GROUP_ID
      FROM PERSON_MOVEMENTS M
      JOIN OBJECTS O ON O.OBJ_ID = M.GROUP_ID AND O.TYPE_ID IN (9, 187, 289)
      WHERE M.OBJ_ID < :I$MOVEMENT_ID AND M.DATE_DEL IS NULL AND M.PERSON_ID = :I$PUPIL_ID AND M.DATE_MODIFY >= DATEADD(-1 MINUTE TO :V$DT)
      ORDER BY M.OBJ_ID DESC
      INTO :V$GROUP_ID;

      IF(V$GROUP_ID IS NOT NULL) THEN
      BEGIN
        -- Группа существует ли ?
        IF(NOT EXISTS(
          SELECT FIRST 1 1
          FROM LINKS LPG
          WHERE LPG.OBJ_ID = :V$GROUP_ID AND LPG.PARENT_TYPE_ID IN (8, 242) AND LPG.DATE_DEL IS NULL
        ))
        THEN
          EXCEPTION DATA_ERROR 'Учебный коллектив расформирован или утрачен, восстановить невозможно';

        SELECT OBJ_ID FROM VARGRP_MOVE_PUPIL(:I$PUPIL_ID, :V$GROUP_ID, NULL, NULL, NULL, 4, NULL) INTO :V$BLOB_ID;
      END
      ELSE
      BEGIN
        -- Не числился нигде в группах - возвращаем или в предварительный прием, или в отчисленных
        SELECT FIRST 1 LP.LINK_ID
        FROM LINKS LP
        WHERE LP.OBJ_ID = :I$PUPIL_ID AND LP.PARENT_TYPE_ID IN (290, 81, 82, 83)
        ORDER BY LP.DATE_DEL DESC NULLS FIRST
        INTO :V$GROUP_ID;

        IF(V$GROUP_ID IS NULL) THEN
        BEGIN
          -- Ученика не было ни в отчисленных, ни в предварительном приеме
          -- Восстанавливаем предварительный прием
          SELECT FIRST 1 L77.OBJ_ID
          FROM LINKS L77
          WHERE L77.PARENT_TYPE_ID = 2 AND L77.OBJ_TYPE_ID = 77 AND L77.DATE_DEL IS NULL
          INTO :V$FOLDER_ID;

          IF(V$FOLDER_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не найден каталог предварительного приема';

          SELECT FIRST 1 L290.LINK_ID, L290.OBJ_ID
          FROM LINKS L290
          JOIN VALL V2346 ON V2346.OBJ_ID = L290.OBJ_ID AND V2346.PARAM_ID = 2346 AND V2346.IS_DEL = 0 AND V2346.LISTVAL_ID = :V$STAGE
          WHERE L290.PARENT_ID = :V$FOLDER_ID AND L290.OBJ_TYPE_ID = 290
          ORDER BY L290.DATE_DEL DESC NULLS FIRST
          INTO :V$LINK_ID, :V$GROUP_ID;

          IF(V$GROUP_ID IS NULL) THEN
          BEGIN
            SELECT OBJ_ID FROM OBJECT_ADD_WITH_PARAM(:V$FOLDER_ID, NULL, 290, 2346, :V$STAGE) INTO :V$GROUP_ID;
          END
          ELSE
          BEGIN
            UPDATE LINKS SET DATE_DEL = NULL WHERE LINK_ID = :V$LINK_ID AND DATE_DEL IS NOT NULL;
          END

          SELECT LINK_ID FROM OBJECT_ADD_LINK(:V$GROUP_ID, :I$PUPIL_ID, 10) INTO :V$BLOB_ID;

        END
        ELSE
        BEGIN
          -- Группа/этап зачисления существует ли ?
          IF(NOT EXISTS(
            SELECT FIRST 1 1
            FROM LINKS L
            JOIN LINKS LPG ON LPG.OBJ_ID = L.PARENT_ID AND LPG.PARENT_TYPE_ID IN (78, 77) AND LPG.DATE_DEL IS NULL
            WHERE L.LINK_ID = :V$GROUP_ID
          ))
          THEN
            EXCEPTION DATA_ERROR 'Папка назначения утрачена, восстановить невозможно';

          UPDATE LINKS SET DATE_DEL = NULL WHERE LINK_ID = :V$GROUP_ID AND DATE_DEL IS NOT NULL;
        END
      END
    END
    ELSE
    BEGIN
      --- Отменяем выбытие
      SELECT OBJ_ID FROM VARGRP_MOVE_PUPIL(:I$PUPIL_ID, :OBJ_ID, NULL, NULL, NULL, 4, NULL) INTO :V$BLOB_ID;
    END

    X = 0;
    OBJ_ID = NULL;
    SELECT FIRST 1 IIF(LPG.PARENT_TYPE_ID IN (81, 82, 83, 290), 2, 1), LPG.PARENT_ID
    FROM LINKS LPG
    WHERE LPG.OBJ_ID = :I$PUPIL_ID AND LPG.PARENT_TYPE_ID IN (9, 125, 187, 243, 290, 81, 82, 83) AND LPG.DATE_DEL IS NULL
    ORDER BY LPG.PARENT_TYPE_ID -- выбывшие имеют приоритет над действующими
    INTO :X, :OBJ_ID;

    SELECT CAPTION FROM OBJECT_CAPTION_GET(:OBJ_ID) INTO :OBJ_CAPTION;

    IF (X = 1) THEN
    BEGIN
      -- Очищаем данные о выбытии
      UPDATE VALL V
      SET V.IS_DEL = 1
      WHERE V.PARAM_ID IN (105, 106, 107, 188, 1346) AND V.OBJ_ID = :I$PUPIL_ID AND V.IS_DEL = 0;
    
      UPDATE VALS V
      SET V.IS_DEL = 1
      WHERE V.PARAM_ID IN (161, 2443) AND V.OBJ_ID = :I$PUPIL_ID AND V.IS_DEL = 0;
    
      UPDATE VALD V
      SET V.IS_DEL = 1
      WHERE V.PARAM_ID = 2442 AND V.OBJ_ID = :I$PUPIL_ID AND V.IS_DEL = 0;
    END

    SUSPEND;

END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_RECALC_EMPLOYEES (
    I$OBJ_ID BIGINT,
    I$OPTION INTEGER = 0)
AS
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$L211_OBJ_ID BIGINT;
DECLARE VARIABLE V$TYPE_ID BIGINT;
DECLARE VARIABLE V$BLOB_ID BIGINT;
DECLARE VARIABLE V$COUNT INTEGER;
DECLARE VARIABLE V$COUNT182 INTEGER;
DECLARE VARIABLE V$COUNT183 INTEGER;
DECLARE VARIABLE V$OBJ_TYPE_ID BIGINT;
BEGIN
  -- I$OPTION описание значений:
  -- 0 - пересчитываем все, 
  -- 1 - только количество сотрудников, 
  -- 2 - только количество педагогов

/* ОПРЕДЕЛЯЕМ ТИП ОБЪЕКТА - 211, 2, 111, 14 */
  V$OBJ_TYPE_ID = 0;

  SELECT TYPE_ID FROM OBJECTS
  WHERE OBJ_ID = :I$OBJ_ID
  INTO :V$OBJ_TYPE_ID;

  IF (V$OBJ_TYPE_ID IN (14, 211, 2)) THEN
  BEGIN
    -- ВЫБИРАЕМ ID ОООД
    FOR
      SELECT OBJ_ID
      FROM LINKS
      WHERE  OBJ_TYPE_ID = 2 AND PARENT_TYPE_ID IS NULL AND DATE_DEL IS NULL
      INTO :V$OBJ_ID
    DO
    BEGIN

      IF (I$OPTION <> 2) THEN   --  ПЕРЕСЧИТЫВАЕМ  КОЛИЧЕСТВО СОТРУДНИКОВ
      BEGIN
        -- 182 ЖЕНЩИН  --183 МУЖЧИН
        SELECT COUNT(A.OBJ_ID), SUM(CASE V239.LISTVAL_ID WHEN 182 THEN 1 ELSE 0 END) AS CNTW, SUM(CASE V239.LISTVAL_ID WHEN 183 THEN 1 ELSE 0 END) AS CNTM
        FROM (
            SELECT DISTINCT L14.OBJ_ID
            FROM LINKS L14
            WHERE L14.DATE_DEL IS NULL AND L14.OBJ_TYPE_ID = 14 AND L14.PARENT_ID = :V$OBJ_ID
            UNION
            SELECT DISTINCT L14.OBJ_ID
            FROM LINKS L211
            JOIN LINKS L14 ON L14.DATE_DEL IS NULL AND L14.OBJ_TYPE_ID = 14 AND L14.PARENT_ID = L211.OBJ_ID
            WHERE L211.DATE_DEL IS NULL AND L211.OBJ_TYPE_ID = 211 AND L211.PARENT_ID = :V$OBJ_ID
          ) A
          JOIN VALL V239 ON V239.OBJ_ID = A.OBJ_ID AND V239.PARAM_ID = 239 AND V239.IS_DEL = 0
        INTO :V$COUNT, :V$COUNT182, :V$COUNT183;

       -- ОООД
          -- 1354-- ОБЩЕЕ КОЛИЧЕСТВО СОТРУДНИКОВ
          SELECT BLOB_ID FROM VAL_ADD(1354, :V$OBJ_ID, :V$COUNT) INTO :V$BLOB_ID;

          -- 1355 -- ОБЩЕЕ КОЛИЧЕСТВО СОТРУДНИКОВ МУЖЧИН
          SELECT BLOB_ID FROM VAL_ADD(1355, :V$OBJ_ID, :V$COUNT183) INTO :V$BLOB_ID;

          -- 1356 -- ОБЩЕЕ КОЛИЧЕСТВО СОТРУДНИКОВ ЖЕНЩИН
          SELECT BLOB_ID FROM VAL_ADD(1356, :V$OBJ_ID, :V$COUNT182) INTO :V$BLOB_ID;

        FOR SELECT L211.OBJ_ID FROM LINKS L211  WHERE L211.DATE_DEL IS NULL AND L211.OBJ_TYPE_ID = 211 AND L211.PARENT_ID = :V$OBJ_ID
        INTO  :V$L211_OBJ_ID
        DO
        BEGIN
          SELECT COUNT(A.OBJ_ID), SUM(CASE V239.LISTVAL_ID WHEN 182 THEN 1 ELSE 0 END) AS CNTW, SUM(CASE V239.LISTVAL_ID WHEN 183 THEN 1 ELSE 0 END) AS CNTM
          FROM (
              SELECT DISTINCT L14.OBJ_ID
              FROM LINKS L14 WHERE L14.DATE_DEL IS NULL AND L14.OBJ_TYPE_ID = 14 AND L14.PARENT_ID = :V$L211_OBJ_ID
            ) A
          JOIN VALL V239 ON V239.OBJ_ID = A.OBJ_ID AND V239.PARAM_ID = 239 AND V239.IS_DEL = 0
          INTO :V$COUNT, :V$COUNT182, :V$COUNT183 ;

       -- ПОДРАЗДЕЛЕНИЕ ПЕРВОГО УРОВНЯ
          -- 2107 -- ОБЩЕЕ КОЛИЧЕСТВО СОТРУДНИКОВ
          SELECT BLOB_ID FROM VAL_ADD(2107, :V$L211_OBJ_ID, :V$COUNT) INTO :V$BLOB_ID;

          -- 2108 -- ОБЩЕЕ КОЛИЧЕСТВО СОТРУДНИКОВ МУЖЧИН
          SELECT BLOB_ID FROM VAL_ADD(2108, :V$L211_OBJ_ID, :V$COUNT183) INTO :V$BLOB_ID;

          -- 2109 -- ОБЩЕЕ КОЛИЧЕСТВО СОТРУДНИКОВ ЖЕНЩИН
          SELECT BLOB_ID FROM VAL_ADD(2109, :V$L211_OBJ_ID, :V$COUNT182) INTO :V$BLOB_ID;
        END
      END

      IF (I$OPTION <> 1) THEN
      BEGIN
        -- 2110 -- подразделение первого уровня -- ОБЩЕЕ КОЛИЧЕСТВО ПЕДАГОГОВ
        FOR SELECT L211.OBJ_ID FROM LINKS L211  WHERE L211.DATE_DEL IS NULL AND L211.OBJ_TYPE_ID = 211 AND L211.PARENT_ID = :V$OBJ_ID
        INTO  :V$L211_OBJ_ID
        DO
        BEGIN
          SELECT X FROM PARAGRAF_TEACHERS_COUNT(:V$L211_OBJ_ID)
          INTO :V$COUNT;
          SELECT BLOB_ID FROM VAL_ADD(2110, :V$L211_OBJ_ID, :V$COUNT) INTO :V$BLOB_ID;
        END


          -- 1357 -- ОООД -- ОБЩЕЕ КОЛИЧЕСТВО ПЕДАГОГОВ
        BEGIN 
          SELECT X FROM PARAGRAF_TEACHERS_COUNT(:V$OBJ_ID)
          INTO :V$COUNT;
          SELECT BLOB_ID FROM VAL_ADD(1357, :V$OBJ_ID, :V$COUNT) INTO :V$BLOB_ID;
        END

      END

    END
  END

  IF (V$OBJ_TYPE_ID in (111, 112)) THEN
  BEGIN

    V$OBJ_ID = NULL;
    -- ВЫБИРАЕМ ID РАЙОНА
    FOR
      SELECT OBJ_ID
      FROM LINKS WHERE OBJ_TYPE_ID = 111 AND ((PARENT_TYPE_ID = 112) or (PARENT_TYPE_ID IS NULL)) AND DATE_DEL IS NULL
      INTO :V$OBJ_ID
    DO

    --  ПЕРЕСЧИТЫВАЕМ  КОЛИЧЕСТВО СОТРУДНИКОВ
    BEGIN
      SELECT COUNT(A.OBJ_ID), SUM(CASE V239.LISTVAL_ID WHEN 182 THEN 1 ELSE 0 END) AS CNTW, SUM(CASE V239.LISTVAL_ID WHEN 183 THEN 1 ELSE 0 END) AS CNTM
            FROM (
                SELECT L14.OBJ_ID
                FROM LINKS L2
                JOIN LINKS L14 ON L14.DATE_DEL IS NULL AND L14.OBJ_TYPE_ID = 14 AND L14.PARENT_ID = L2.OBJ_ID
                WHERE L2.PARENT_ID = :V$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
                UNION
                SELECT L14.OBJ_ID
                FROM LINKS L2
                JOIN LINKS L211 ON L211.DATE_DEL IS NULL AND L211.OBJ_TYPE_ID = 211 AND L211.PARENT_ID = L2.OBJ_ID
                JOIN LINKS L14 ON L14.DATE_DEL IS NULL AND L14.OBJ_TYPE_ID = 14 AND L14.PARENT_ID = L211.OBJ_ID
                WHERE L2.PARENT_ID = :V$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
            ) A
            JOIN VALL V239 ON V239.OBJ_ID = A.OBJ_ID AND V239.PARAM_ID = 239 AND V239.IS_DEL = 0
            INTO :V$COUNT, :V$COUNT182, :V$COUNT183;
  -- РАЙОН

        -- 1358-- ОБЩЕЕ КОЛИЧЕСТВО СОТРУДНИКОВ
        SELECT BLOB_ID FROM VAL_ADD(1358, :V$OBJ_ID, :V$COUNT) INTO :V$BLOB_ID;

        -- 1359 -- ОБЩЕЕ КОЛИЧЕСТВО СОТРУДНИКОВ МУЖЧИН
        SELECT BLOB_ID FROM VAL_ADD(1359, :V$OBJ_ID, :V$COUNT183) INTO :V$BLOB_ID;

        -- 1360 -- ОБЩЕЕ КОЛИЧЕСТВО СОТРУДНИКОВ ЖЕНЩИН
        SELECT BLOB_ID FROM VAL_ADD(1360, :V$OBJ_ID, :V$COUNT182) INTO :V$BLOB_ID;


        IF (I$OPTION <> 1) THEN
        BEGIN
          V$COUNT = 0;
          SELECT X FROM PARAGRAF_TEACHERS_COUNT_DISTR(:V$OBJ_ID)
          INTO :V$COUNT;

          -- 1361 -- ОБЩЕЕ КОЛИЧЕСТВО ПЕДАГОГОВ
          SELECT BLOB_ID FROM VAL_ADD(1361, :V$OBJ_ID, :V$COUNT) INTO :V$BLOB_ID;
        END
    END
  END


END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_REF_SUBJECTS RETURNS (
    OBJ_ID BIGINT,
    PARENT_ID BIGINT,
    OBJ_CAPTION VARCHAR(4000),
    SORT_ORDER DOUBLE PRECISION)
AS
declare variable V$STATUS char(1);
begin

  V$STATUS = (SELECT STATUS FROM OU_LICENCE_TYPE);

  IF(V$STATUS = 'O') THEN
  BEGIN

    -- Список предметов, в один уровень
    FOR
      SELECT OBJ_ID, OBJ_CAPTION, SORT_ORDER
      FROM PARAGRAF_TYPE_REFERENSE_LIST(51)
      INTO :OBJ_ID, :OBJ_CAPTION, :SORT_ORDER
    DO
    BEGIN
      SUSPEND;
    END

  END
  ELSE IF(V$STATUS = 'C') THEN
  BEGIN

    -- Список дисциплин, с разбивкой по видам деятельности
    FOR
      SELECT L.LISTVAL_ID, L.VAL, -1
      FROM LISTVALS_LIST(240) L
      WHERE L.IS_DEL = 0 AND (SELECT COUNT(*) FROM LISTVALS L2 WHERE L2.LIST_ID = L.LIST_ID AND L2.IS_DEL = 0 AND L2.PARENT_ID = L.LISTVAL_ID) = 0
      ORDER BY L.SORT_ORDER
      INTO :OBJ_ID, :OBJ_CAPTION, :SORT_ORDER
    DO
    BEGIN
      PARENT_ID = NULL;
      SUSPEND;
      PARENT_ID = OBJ_ID;

      FOR
        SELECT L197.OBJ_ID, V1751.VAL, L197.COST
        FROM LINKS L197
        JOIN VALS V1751 ON V1751.OBJ_ID  = L197.OBJ_ID AND V1751.PARAM_ID = 1751 AND V1751.IS_DEL = 0
        JOIN VALL V1750 ON V1750.OBJ_ID = L197.OBJ_ID AND V1750.PARAM_ID = 1750 AND V1750.IS_DEL = 0 AND V1750.LISTVAL_ID = :PARENT_ID
        WHERE L197.PARENT_TYPE_ID = 193 AND L197.OBJ_TYPE_ID = 197 AND L197.DATE_DEL IS NULL
        INTO :OBJ_ID, :OBJ_CAPTION, :SORT_ORDER
      DO
      BEGIN
        SUSPEND;
      END
    END

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_REPORT_335 (
    I$SCHOOLLEVEL INTEGER)
RETURNS (
    AREA_VALUE VARCHAR(400),
    REGION_VALUE VARCHAR(400),
    CNT_SCOOL_994 INTEGER,
    CNT_WORKER_994 INTEGER,
    CNT_TEACHER_994 INTEGER,
    CNT_SCOOL_1003 INTEGER,
    CNT_WORKER_1003 INTEGER,
    CNT_TEACHER_1003 INTEGER,
    CNT_SCOOL_1021 INTEGER,
    CNT_WORKER_1021 INTEGER,
    CNT_TEACHER_1021 INTEGER,
    TYPE_OOOD VARCHAR(10))
AS
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$TEST INTEGER;
BEGIN
  if (I$SCHOOLLEVEL = 3) then
  FOR
    SELECT
        cast(coalesce(V672.val, '<Текущий регион>') as varchar(400)) AREA_VALUE
        , cast(coalesce(R665.val, '<Текущий район>') as varchar(400)) REGION_VALUE
        , L111.obj_id OBJ_ID
    FROM
    --Район
    LINKS L111
    LEFT JOIN VALL V665 ON V665.OBJ_ID = L111.OBJ_ID AND V665.PARAM_ID = 665 AND V665.IS_DEL = 0
    LEFT JOIN LISTVALS LV665 ON LV665.LISTVAL_ID = V665.LISTVAL_ID AND LV665.IS_DEL = 0
    LEFT JOIN RES R665 ON R665.RES_ID = LV665.RES_ID AND R665.LANG_CODE ='RU' AND R665.IS_DEL = 0

    --Регион
    LEFT JOIN LINKS L112 ON L112.OBJ_ID = L111.PARENT_ID AND L112.DATE_DEL IS NULL AND L112.OBJ_TYPE_ID = 112
    LEFT JOIN VALS V672 ON V672.OBJ_ID = L112.OBJ_ID AND V672.PARAM_ID = 672 AND V672.IS_DEL = 0

    WHERE L111.DATE_DEL IS NULL AND L111.OBJ_TYPE_ID = 111
  INTO
    :AREA_VALUE
    , :REGION_VALUE
    , :V$OBJ_ID
  DO
  BEGIN
    -- 994: Образовательные учреждения дополнительного образования детей
    -- Количество школ
    SELECT
        count(*) CNT
    FROM
    LINKS L2
    JOIN VALL V11 ON V11.OBJ_ID = L2.OBJ_ID AND V11.PARAM_ID = 11 AND V11.IS_DEL = 0 AND V11.LISTVAL_ID = 994

    WHERE L2.PARENT_ID = :V$OBJ_ID AND L2.DATE_DEL IS NULL AND L2.OBJ_TYPE_ID = 2
    INTO :CNT_SCOOL_994;

    CNT_SCOOL_994 = coalesce(CNT_SCOOL_994,  0);

    -- Количество сотрудников
    SELECT COUNT(*) FROM (
        SELECT DISTINCT L14.OBJ_ID
        FROM LINKS L2
        JOIN VALL V11 ON V11.OBJ_ID = L2.OBJ_ID AND V11.PARAM_ID = 11 AND V11.IS_DEL = 0 AND V11.LISTVAL_ID = 994
        JOIN LINKS L14 ON L14.DATE_DEL IS NULL AND L14.OBJ_TYPE_ID = 14 AND L14.PARENT_ID = L2.OBJ_ID
        WHERE L2.PARENT_ID = :V$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
        UNION
        SELECT DISTINCT L14.OBJ_ID
        FROM LINKS L2
        JOIN VALL V11 ON V11.OBJ_ID = L2.OBJ_ID AND V11.PARAM_ID = 11 AND V11.IS_DEL = 0 AND V11.LISTVAL_ID = 994
        JOIN LINKS L211 ON L211.DATE_DEL IS NULL AND L211.OBJ_TYPE_ID = 211 AND L211.PARENT_ID = L2.OBJ_ID
        JOIN LINKS L14 ON L14.DATE_DEL IS NULL AND L14.OBJ_TYPE_ID = 14 AND L14.PARENT_ID = L211.OBJ_ID
        WHERE L2.PARENT_ID = :V$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    )
    INTO :CNT_WORKER_994;

    CNT_WORKER_994 = coalesce(CNT_WORKER_994,  0);

    -- Количество педагогов
    SELECT COUNT(*) FROM (
        SELECT DISTINCT L14.OBJ_ID
        FROM LINKS L2
        JOIN VALL V11 ON V11.OBJ_ID = L2.OBJ_ID AND V11.PARAM_ID = 11 AND V11.IS_DEL = 0 AND V11.LISTVAL_ID = 994
        JOIN LINKS L14 ON L14.DATE_DEL IS NULL AND L14.OBJ_TYPE_ID = 14 AND L14.PARENT_ID = L2.OBJ_ID
        JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.DATE_DEL IS NULL AND L15.OBJ_TYPE_ID = 15
        JOIN LINKS L13 ON L13.OBJ_ID = L15.OBJ_ID AND L13.DATE_DEL IS NULL AND L13.PARENT_TYPE_ID = 13
        JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0 AND V73.VAL <= CURRENT_DATE
        LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
        LEFT JOIN DO_FUNC(L13.PARENT_ID, 400) DF ON 1=1
        WHERE L2.PARENT_ID = :V$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND DF.SORT_ORDER = 2 AND ((V74.VAL IS NULL) or (V74.VAL >= CURRENT_DATE))

        UNION

        SELECT DISTINCT L14.OBJ_ID
        FROM LINKS L2
        JOIN VALL V11 ON V11.OBJ_ID = L2.OBJ_ID AND V11.PARAM_ID = 11 AND V11.IS_DEL = 0 AND V11.LISTVAL_ID = 994
        JOIN LINKS L211 ON L211.DATE_DEL IS NULL AND L211.OBJ_TYPE_ID = 211 AND L211.PARENT_ID = L2.OBJ_ID
        JOIN LINKS L14 ON L14.DATE_DEL IS NULL AND L14.OBJ_TYPE_ID = 14 AND L14.PARENT_ID = L211.OBJ_ID
        JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.DATE_DEL IS NULL AND L15.OBJ_TYPE_ID = 15
        JOIN LINKS L13 ON L13.OBJ_ID = L15.OBJ_ID AND L13.DATE_DEL IS NULL AND L13.PARENT_TYPE_ID = 13
        JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0 AND V73.VAL <= CURRENT_DATE
        LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
        LEFT JOIN DO_FUNC(L13.PARENT_ID, 400) DF ON 1=1
        WHERE L2.PARENT_ID = :V$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND DF.SORT_ORDER = 2 AND ((V74.VAL IS NULL) or (V74.VAL >= CURRENT_DATE))
    )
    INTO :CNT_TEACHER_994;

    CNT_TEACHER_994 = coalesce(CNT_TEACHER_994,  0);

    -- 1003: Образовательные учреждения для детей, нуждающихся в психолого-педагогической и медико-социальной помощи
    -- Количество школ
    SELECT
        count(*) CNT
    FROM
    LINKS L2
    JOIN VALL V11 ON V11.OBJ_ID = L2.OBJ_ID AND V11.PARAM_ID = 11 AND V11.IS_DEL = 0 AND V11.LISTVAL_ID = 1003

    WHERE L2.PARENT_ID = :V$OBJ_ID AND L2.DATE_DEL IS NULL AND L2.OBJ_TYPE_ID = 2
    INTO :CNT_SCOOL_1003;

    CNT_SCOOL_1003 = coalesce(CNT_SCOOL_1003,  0);

    -- Количество сотрудников
    SELECT COUNT(*) FROM (
        SELECT DISTINCT L14.OBJ_ID
        FROM LINKS L2
        JOIN VALL V11 ON V11.OBJ_ID = L2.OBJ_ID AND V11.PARAM_ID = 11 AND V11.IS_DEL = 0 AND V11.LISTVAL_ID = 1003
        JOIN LINKS L14 ON L14.DATE_DEL IS NULL AND L14.OBJ_TYPE_ID = 14 AND L14.PARENT_ID = L2.OBJ_ID
        WHERE L2.PARENT_ID = :V$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
        UNION
        SELECT DISTINCT L14.OBJ_ID
        FROM LINKS L2
        JOIN VALL V11 ON V11.OBJ_ID = L2.OBJ_ID AND V11.PARAM_ID = 11 AND V11.IS_DEL = 0 AND V11.LISTVAL_ID = 1003
        JOIN LINKS L211 ON L211.DATE_DEL IS NULL AND L211.OBJ_TYPE_ID = 211 AND L211.PARENT_ID = L2.OBJ_ID
        JOIN LINKS L14 ON L14.DATE_DEL IS NULL AND L14.OBJ_TYPE_ID = 14 AND L14.PARENT_ID = L211.OBJ_ID
        WHERE L2.PARENT_ID = :V$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    )
    INTO :CNT_WORKER_1003;

    CNT_WORKER_1003 = coalesce(CNT_WORKER_1003,  0);

    -- Количество педагогов
    SELECT COUNT(*) FROM (
        SELECT DISTINCT L14.OBJ_ID
        FROM LINKS L2
        JOIN VALL V11 ON V11.OBJ_ID = L2.OBJ_ID AND V11.PARAM_ID = 11 AND V11.IS_DEL = 0 AND V11.LISTVAL_ID = 1003
        JOIN LINKS L14 ON L14.DATE_DEL IS NULL AND L14.OBJ_TYPE_ID = 14 AND L14.PARENT_ID = L2.OBJ_ID
        JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.DATE_DEL IS NULL AND L15.OBJ_TYPE_ID = 15
        JOIN LINKS L13 ON L13.OBJ_ID = L15.OBJ_ID AND L13.DATE_DEL IS NULL AND L13.PARENT_TYPE_ID = 13
        JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0 AND V73.VAL <= CURRENT_DATE
        LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
        LEFT JOIN DO_FUNC(L13.PARENT_ID, 400) DF ON 1=1
        WHERE L2.PARENT_ID = :V$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND DF.SORT_ORDER = 2 AND ((V74.VAL IS NULL) or (V74.VAL >= CURRENT_DATE))

        UNION

        SELECT DISTINCT L14.OBJ_ID
        FROM LINKS L2
        JOIN VALL V11 ON V11.OBJ_ID = L2.OBJ_ID AND V11.PARAM_ID = 11 AND V11.IS_DEL = 0 AND V11.LISTVAL_ID = 1003
        JOIN LINKS L211 ON L211.DATE_DEL IS NULL AND L211.OBJ_TYPE_ID = 211 AND L211.PARENT_ID = L2.OBJ_ID
        JOIN LINKS L14 ON L14.DATE_DEL IS NULL AND L14.OBJ_TYPE_ID = 14 AND L14.PARENT_ID = L211.OBJ_ID
        JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.DATE_DEL IS NULL AND L15.OBJ_TYPE_ID = 15
        JOIN LINKS L13 ON L13.OBJ_ID = L15.OBJ_ID AND L13.DATE_DEL IS NULL AND L13.PARENT_TYPE_ID = 13
        JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0 AND V73.VAL <= CURRENT_DATE
        LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
        LEFT JOIN DO_FUNC(L13.PARENT_ID, 400) DF ON 1=1
        WHERE L2.PARENT_ID = :V$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND DF.SORT_ORDER = 2 AND ((V74.VAL IS NULL) or (V74.VAL >= CURRENT_DATE))
    )
    INTO :CNT_TEACHER_1003;

    CNT_TEACHER_1003 = coalesce(CNT_TEACHER_1003,  0);

    -- 1021: Образовательные учреждения дополнительного профессионального образования
    -- Количество школ
    SELECT
        count(*) CNT
    FROM
    LINKS L2
    JOIN VALL V11 ON V11.OBJ_ID = L2.OBJ_ID AND V11.PARAM_ID = 11 AND V11.IS_DEL = 0 AND V11.LISTVAL_ID = 1021

    WHERE L2.PARENT_ID = :V$OBJ_ID AND L2.DATE_DEL IS NULL AND L2.OBJ_TYPE_ID = 2
    INTO :CNT_SCOOL_1021;

    CNT_SCOOL_1021 = coalesce(CNT_SCOOL_1021,  0);

    -- Количество сотрудников
    SELECT COUNT(*) FROM (
        SELECT DISTINCT L14.OBJ_ID
        FROM LINKS L2
        JOIN VALL V11 ON V11.OBJ_ID = L2.OBJ_ID AND V11.PARAM_ID = 11 AND V11.IS_DEL = 0 AND V11.LISTVAL_ID = 1021
        JOIN LINKS L14 ON L14.DATE_DEL IS NULL AND L14.OBJ_TYPE_ID = 14 AND L14.PARENT_ID = L2.OBJ_ID
        WHERE L2.PARENT_ID = :V$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
        UNION
        SELECT DISTINCT L14.OBJ_ID
        FROM LINKS L2
        JOIN VALL V11 ON V11.OBJ_ID = L2.OBJ_ID AND V11.PARAM_ID = 11 AND V11.IS_DEL = 0 AND V11.LISTVAL_ID = 1021
        JOIN LINKS L211 ON L211.DATE_DEL IS NULL AND L211.OBJ_TYPE_ID = 211 AND L211.PARENT_ID = L2.OBJ_ID
        JOIN LINKS L14 ON L14.DATE_DEL IS NULL AND L14.OBJ_TYPE_ID = 14 AND L14.PARENT_ID = L211.OBJ_ID
        WHERE L2.PARENT_ID = :V$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    )
    INTO :CNT_WORKER_1021;

    CNT_WORKER_1021 = coalesce(CNT_WORKER_1021,  0);

    -- Количество педагогов
    SELECT COUNT(*) FROM (
        SELECT DISTINCT L14.OBJ_ID
        FROM LINKS L2
        JOIN VALL V11 ON V11.OBJ_ID = L2.OBJ_ID AND V11.PARAM_ID = 11 AND V11.IS_DEL = 0 AND V11.LISTVAL_ID = 1021
        JOIN LINKS L14 ON L14.DATE_DEL IS NULL AND L14.OBJ_TYPE_ID = 14 AND L14.PARENT_ID = L2.OBJ_ID
        JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.DATE_DEL IS NULL AND L15.OBJ_TYPE_ID = 15
        JOIN LINKS L13 ON L13.OBJ_ID = L15.OBJ_ID AND L13.DATE_DEL IS NULL AND L13.PARENT_TYPE_ID = 13
        JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0 AND V73.VAL <= CURRENT_DATE
        LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
        LEFT JOIN DO_FUNC(L13.PARENT_ID, 400) DF ON 1=1
        WHERE L2.PARENT_ID = :V$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND DF.SORT_ORDER = 2 AND ((V74.VAL IS NULL) or (V74.VAL >= CURRENT_DATE))

        UNION

        SELECT DISTINCT L14.OBJ_ID
        FROM LINKS L2
        JOIN VALL V11 ON V11.OBJ_ID = L2.OBJ_ID AND V11.PARAM_ID = 11 AND V11.IS_DEL = 0 AND V11.LISTVAL_ID = 1021
        JOIN LINKS L211 ON L211.DATE_DEL IS NULL AND L211.OBJ_TYPE_ID = 211 AND L211.PARENT_ID = L2.OBJ_ID
        JOIN LINKS L14 ON L14.DATE_DEL IS NULL AND L14.OBJ_TYPE_ID = 14 AND L14.PARENT_ID = L211.OBJ_ID
        JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.DATE_DEL IS NULL AND L15.OBJ_TYPE_ID = 15
        JOIN LINKS L13 ON L13.OBJ_ID = L15.OBJ_ID AND L13.DATE_DEL IS NULL AND L13.PARENT_TYPE_ID = 13
        JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0 AND V73.VAL <= CURRENT_DATE
        LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
        LEFT JOIN DO_FUNC(L13.PARENT_ID, 400) DF ON 1=1
        WHERE L2.PARENT_ID = :V$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND DF.SORT_ORDER = 2 AND ((V74.VAL IS NULL) or (V74.VAL >= CURRENT_DATE))
    )
    INTO :CNT_TEACHER_1021;

    CNT_TEACHER_1021 = coalesce(CNT_TEACHER_1021,  0);

    SUSPEND;
  END

  ELSE     --Район
  BEGIN
  V$TEST = 0;

  FOR
    SELECT
        cast(coalesce(R665.val, '<Текущий район>') as varchar(400)) REGION_VALUE,
        cast(coalesce(V2.val, '<Текущий ОООД>') as varchar(400)) OOOD_VALUE,
        L2.obj_id OBJ_ID,
        (case V11.LISTVAL_ID
        when 994 then 'УДОД'     -- 994: Образовательные учреждения дополнительного образования детей
        when 1003 then 'ЦППМСП'  -- 1003: Образовательные учреждения для детей, нуждающихся в психолого-педагогической и медико-социальной помощи
        when 1021 then 'ДПО'     -- 1021: Образовательные учреждения дополнительного профессионального образования
        else '???' end)
    FROM
    LINKS L2
    LEFT JOIN LINKS L111 ON L2.PARENT_ID = L111.OBJ_ID AND L111.OBJ_TYPE_ID = 111 AND L111.DATE_DEL IS NULL
    LEFT JOIN VALL V665 ON V665.OBJ_ID = L111.OBJ_ID AND V665.PARAM_ID = 665 AND V665.IS_DEL = 0
    LEFT JOIN LISTVALS LV665 ON LV665.LISTVAL_ID = V665.LISTVAL_ID AND LV665.IS_DEL = 0
    LEFT JOIN RES R665 ON R665.RES_ID = LV665.RES_ID AND R665.LANG_CODE ='RU' AND R665.IS_DEL = 0
    LEFT JOIN VALS V2 ON V2.OBJ_ID = L2.OBJ_ID AND V2.PARAM_ID = 2 AND V2.IS_DEL = 0
    LEFT JOIN VALL V11 ON V11.OBJ_ID = L2.OBJ_ID AND V11.PARAM_ID = 11 AND V11.IS_DEL = 0

    WHERE L2.DATE_DEL IS NULL AND L2.OBJ_TYPE_ID = 2
    ORDER BY V11.LISTVAL_ID
  INTO
    :AREA_VALUE, :REGION_VALUE, :V$OBJ_ID, :TYPE_OOOD
  DO
  BEGIN
    CNT_SCOOL_994 = coalesce(CNT_SCOOL_994,  0);

    -- Количество сотрудников
    SELECT COUNT(*) FROM (
        SELECT DISTINCT L14.OBJ_ID
        FROM LINKS L2
        JOIN LINKS L14 ON L14.DATE_DEL IS NULL AND L14.OBJ_TYPE_ID = 14 AND L14.PARENT_ID = L2.OBJ_ID
        WHERE L2.OBJ_ID = :V$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
        UNION
        SELECT DISTINCT L14.OBJ_ID
        FROM LINKS L2
        JOIN LINKS L211 ON L211.DATE_DEL IS NULL AND L211.OBJ_TYPE_ID = 211 AND L211.PARENT_ID = L2.OBJ_ID
        JOIN LINKS L14 ON L14.DATE_DEL IS NULL AND L14.OBJ_TYPE_ID = 14 AND L14.PARENT_ID = L211.OBJ_ID
        WHERE L2.OBJ_ID = :V$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    )
    INTO :CNT_WORKER_994;

    CNT_WORKER_994 = coalesce(CNT_WORKER_994,  0);

    -- Количество педагогов
    SELECT COUNT(*) FROM (
        SELECT DISTINCT L14.OBJ_ID
        FROM LINKS L2
        JOIN LINKS L14 ON L14.DATE_DEL IS NULL AND L14.OBJ_TYPE_ID = 14 AND L14.PARENT_ID = L2.OBJ_ID
        JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.DATE_DEL IS NULL AND L15.OBJ_TYPE_ID = 15
        JOIN LINKS L13 ON L13.OBJ_ID = L15.OBJ_ID AND L13.DATE_DEL IS NULL AND L13.PARENT_TYPE_ID = 13
        JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0 AND V73.VAL <= CURRENT_DATE
        LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
        LEFT JOIN DO_FUNC(L13.PARENT_ID, 400) DF ON 1=1
        WHERE L2.OBJ_ID = :V$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND DF.SORT_ORDER = 2 AND ((V74.VAL IS NULL) or (V74.VAL >= CURRENT_DATE))

        UNION

        SELECT DISTINCT L14.OBJ_ID
        FROM LINKS L2
        JOIN LINKS L211 ON L211.DATE_DEL IS NULL AND L211.OBJ_TYPE_ID = 211 AND L211.PARENT_ID = L2.OBJ_ID
        JOIN LINKS L14 ON L14.DATE_DEL IS NULL AND L14.OBJ_TYPE_ID = 14 AND L14.PARENT_ID = L211.OBJ_ID
        JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.DATE_DEL IS NULL AND L15.OBJ_TYPE_ID = 15
        JOIN LINKS L13 ON L13.OBJ_ID = L15.OBJ_ID AND L13.DATE_DEL IS NULL AND L13.PARENT_TYPE_ID = 13
        JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0 AND V73.VAL <= CURRENT_DATE
        LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
        LEFT JOIN DO_FUNC(L13.PARENT_ID, 400) DF ON 1=1
        WHERE L2.OBJ_ID = :V$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND DF.SORT_ORDER = 2 AND ((V74.VAL IS NULL) or (V74.VAL >= CURRENT_DATE))
    )
    INTO :CNT_TEACHER_994;

    CNT_TEACHER_994 = coalesce(CNT_TEACHER_994,  0);

    CNT_SCOOL_1003 = 0;
    CNT_WORKER_1003 = 0;
    CNT_TEACHER_1003 = 0;
    CNT_SCOOL_1021 = 0;
    CNT_WORKER_1021 = 0;
    CNT_TEACHER_1021 = 0;
    /*
    V$TEST = V$TEST + 1;
    if (V$TEST = 2) then
      TYPE_OOOD = 'ДПО'; */
    SUSPEND;
    END
  END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_REPORT_336 (
    I$SCHOOLLEVEL INTEGER)
RETURNS (
    AREA_VALUE VARCHAR(400),
    REGION_VALUE VARCHAR(400),
    CNT_SCOOL INTEGER,
    CNT_DISTRICT INTEGER,
    CNT_PUPIL_IN_DISTRICT INTEGER,
    CNT_PUPIL INTEGER)
AS
declare variable V$OBJ_ID bigint;
BEGIN
  if (I$SCHOOLLEVEL = 3) then
  FOR
    SELECT
        cast(coalesce(V672.val, '<Текущий регион>') as varchar(400)) AREA_VALUE
        , cast(coalesce(R665.val, R1406.val, '<Текущий район>') as varchar(400)) REGION_VALUE
        , L111.obj_id OBJ_ID
    FROM
    --Район
    LINKS L111
    --для Параграфа
    LEFT JOIN VALL V665 ON V665.OBJ_ID = L111.OBJ_ID AND V665.PARAM_ID = 665 AND V665.IS_DEL = 0
    LEFT JOIN LISTVALS LV665 ON LV665.LISTVAL_ID = V665.LISTVAL_ID AND LV665.IS_DEL = 0
    LEFT JOIN RES R665 ON R665.RES_ID = LV665.RES_ID AND R665.LANG_CODE ='RU' AND R665.IS_DEL = 0
    --для Апострофа
    LEFT JOIN VALL V1406 ON V1406.OBJ_ID = L111.OBJ_ID AND V1406.PARAM_ID = 1406 AND V1406.IS_DEL = 0
    LEFT JOIN LISTVALS LV1406 ON LV1406.LISTVAL_ID = V1406.LISTVAL_ID AND LV1406.IS_DEL = 0
    LEFT JOIN RES R1406 ON R1406.RES_ID = LV1406.RES_ID AND R1406.LANG_CODE ='RU' AND R1406.IS_DEL = 0

    --Регион
    LEFT JOIN LINKS L112 ON L112.OBJ_ID = L111.PARENT_ID AND L112.DATE_DEL IS NULL AND L112.OBJ_TYPE_ID = 112
    LEFT JOIN VALS V672 ON V672.OBJ_ID = L112.OBJ_ID AND V672.PARAM_ID = 672 AND V672.IS_DEL = 0

    WHERE L111.DATE_DEL IS NULL AND L111.OBJ_TYPE_ID = 111
  INTO
    :AREA_VALUE
    , :REGION_VALUE
    , :V$OBJ_ID
  DO
  BEGIN
    -- количество одод и воспитанников всего
    SELECT count(*) CNT_ODOD
    FROM
    --Количество ОООД
    --Подсчет по фильтру - Тип ОУ (по закону РФ "Об образовании" от 10.07.1992  №3216-1) - Образовательные учреждения  дополнительного образования детей
    LINKS L2
    JOIN VALL V11 ON V11.OBJ_ID = L2.OBJ_ID AND V11.PARAM_ID = 11 AND V11.IS_DEL = 0 AND V11.LISTVAL_ID = 994
    WHERE L2.PARENT_ID = :V$OBJ_ID AND L2.DATE_DEL IS NULL AND L2.OBJ_TYPE_ID = 2
    INTO :CNT_SCOOL;

    SELECT count (DISTINCT L10.OBJ_ID)
    --Количество ОООД
    --Подсчет по фильтру - Тип ОУ (по закону РФ "Об образовании" от 10.07.1992  №3216-1) - Образовательные учреждения  дополнительного образования детей
    FROM
    LINKS L2
    JOIN VALL V11 ON V11.OBJ_ID = L2.OBJ_ID AND V11.PARAM_ID = 11 AND V11.IS_DEL = 0 AND V11.LISTVAL_ID = 994

    LEFT JOIN LINKS L211 ON L211.PARENT_ID = L2.OBJ_ID AND L211.OBJ_TYPE_ID = 211 AND L211.DATE_DEL IS NULL
    JOIN LINKS L242 ON (L242.PARENT_ID = L211.OBJ_ID OR L242.PARENT_ID = L2.OBJ_ID) AND L242.OBJ_TYPE_ID = 242 AND L242.DATE_DEL IS NULL

    JOIN LINKS L243 ON  (L243.PARENT_ID = L242.OBJ_ID) AND L243.OBJ_TYPE_ID = 243 AND L243.DATE_DEL IS NULL  -- Этап обучения
    JOIN LINKS L10 ON  (L10.PARENT_ID = L243.OBJ_ID) AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL   -- Обучающийся, воспитанник
    WHERE L2.PARENT_ID = :V$OBJ_ID AND L2.DATE_DEL IS NULL AND L2.OBJ_TYPE_ID = 2
    INTO :CNT_PUPIL;

    CNT_SCOOL = coalesce(CNT_SCOOL,  0);
    CNT_PUPIL = coalesce(CNT_PUPIL,  0);

    -- количество объединений
    SELECT
        count(*) CNT_DISTRICT,
        SUM(CAST(P.VAL AS INTEGER)) CNT_PUPIL
    FROM
    (
    SELECT DISTINCT L242.OBJ_ID
    --Количество ОООД
    --Подсчет по фильтру - Тип ОУ (по закону РФ "Об образовании" от 10.07.1992  №3216-1) - Образовательные учреждения  дополнительного образования детей
    FROM
    LINKS L2
    JOIN VALL V11 ON V11.OBJ_ID = L2.OBJ_ID AND V11.PARAM_ID = 11 AND V11.IS_DEL = 0 AND V11.LISTVAL_ID = 994

    LEFT JOIN LINKS L211 ON L211.PARENT_ID = L2.OBJ_ID AND L211.OBJ_TYPE_ID = 211 AND L211.DATE_DEL IS NULL
    JOIN LINKS L242 ON (L242.PARENT_ID = L211.OBJ_ID OR L242.PARENT_ID = L2.OBJ_ID) AND L242.OBJ_TYPE_ID = 242 AND L242.DATE_DEL IS NULL

    WHERE L2.PARENT_ID = :V$OBJ_ID AND L2.DATE_DEL IS NULL AND L2.OBJ_TYPE_ID = 2
    ) a
    LEFT JOIN DO_FUNC(OBJ_ID, NULL, 9) P ON 1=1
    INTO :CNT_DISTRICT, :CNT_PUPIL_IN_DISTRICT;

    CNT_DISTRICT = coalesce(CNT_DISTRICT, 0);
    CNT_PUPIL_IN_DISTRICT = coalesce(CNT_PUPIL_IN_DISTRICT, 0);

    SUSPEND;
  END

  ELSE

  FOR
    SELECT
        cast(coalesce(R665.val, R1406.val, '<Текущий район>') as varchar(400)) REGION_VALUE,
        cast(coalesce(V2.val, '<Текущий ОООД>') as varchar(400)) OOOD_VALUE,
        L2.obj_id OBJ_ID
    FROM
    LINKS L2
    JOIN VALL V11 ON V11.OBJ_ID = L2.OBJ_ID AND V11.PARAM_ID = 11 AND V11.IS_DEL = 0 AND V11.LISTVAL_ID = 994
    LEFT JOIN LINKS L111 ON L2.PARENT_ID = L111.OBJ_ID AND L111.OBJ_TYPE_ID = 111 AND L111.DATE_DEL IS NULL
    --для Параграфа
    LEFT JOIN VALL V665 ON V665.OBJ_ID = L111.OBJ_ID AND V665.PARAM_ID = 665 AND V665.IS_DEL = 0
    LEFT JOIN LISTVALS LV665 ON LV665.LISTVAL_ID = V665.LISTVAL_ID AND LV665.IS_DEL = 0
    LEFT JOIN RES R665 ON R665.RES_ID = LV665.RES_ID AND R665.LANG_CODE ='RU' AND R665.IS_DEL = 0
    LEFT JOIN VALS V2 ON V2.OBJ_ID = L2.OBJ_ID AND V2.PARAM_ID = 2 AND V2.IS_DEL = 0
    --для Апострофа
    LEFT JOIN VALL V1406 ON V1406.OBJ_ID = L111.OBJ_ID AND V1406.PARAM_ID = 1406 AND V1406.IS_DEL = 0
    LEFT JOIN LISTVALS LV1406 ON LV1406.LISTVAL_ID = V1406.LISTVAL_ID AND LV1406.IS_DEL = 0
    LEFT JOIN RES R1406 ON R1406.RES_ID = LV1406.RES_ID AND R1406.LANG_CODE ='RU' AND R1406.IS_DEL = 0
    WHERE L2.DATE_DEL IS NULL AND L2.OBJ_TYPE_ID = 2
  INTO
    :AREA_VALUE, :REGION_VALUE, :V$OBJ_ID

  DO
  BEGIN
    -- количество одод и воспитанников всего
    CNT_SCOOL = 1;

    SELECT count (DISTINCT L10.OBJ_ID)
    --Количество ОООД
    --Подсчет по фильтру - Тип ОУ (по закону РФ "Об образовании" от 10.07.1992  №3216-1) - Образовательные учреждения  дополнительного образования детей
    FROM
    OBJECTS L2

    LEFT JOIN LINKS L211 ON L211.PARENT_ID = L2.OBJ_ID AND L211.OBJ_TYPE_ID = 211 AND L211.DATE_DEL IS NULL
    JOIN LINKS L242 ON (L242.PARENT_ID = L211.OBJ_ID OR L242.PARENT_ID = L2.OBJ_ID) AND L242.OBJ_TYPE_ID = 242 AND L242.DATE_DEL IS NULL

    JOIN LINKS L243 ON  (L243.PARENT_ID = L242.OBJ_ID) AND L243.OBJ_TYPE_ID = 243 AND L243.DATE_DEL IS NULL  -- Этап обучения
    JOIN LINKS L10 ON  (L10.PARENT_ID = L243.OBJ_ID) AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL   -- Обучающийся, воспитанник
    WHERE L2.OBJ_ID = :V$OBJ_ID
    INTO :CNT_PUPIL;

    CNT_SCOOL = coalesce(CNT_SCOOL,  0);
    CNT_PUPIL = coalesce(CNT_PUPIL,  0);

    -- количество объединений
    SELECT
        count(*) CNT_DISTRICT,
        SUM(CAST(P.VAL AS INTEGER)) CNT_PUPIL
    FROM
    (
    SELECT DISTINCT L242.OBJ_ID
    --Количество ОООД
    --Подсчет по фильтру - Тип ОУ (по закону РФ "Об образовании" от 10.07.1992  №3216-1) - Образовательные учреждения  дополнительного образования детей
    FROM
    OBJECTS L2

    LEFT JOIN LINKS L211 ON L211.PARENT_ID = L2.OBJ_ID AND L211.OBJ_TYPE_ID = 211 AND L211.DATE_DEL IS NULL
    JOIN LINKS L242 ON (L242.PARENT_ID = L211.OBJ_ID OR L242.PARENT_ID = L2.OBJ_ID) AND L242.OBJ_TYPE_ID = 242 AND L242.DATE_DEL IS NULL

    WHERE L2.OBJ_ID = :V$OBJ_ID
    ) a
    LEFT JOIN DO_FUNC(OBJ_ID, NULL, 9) P ON 1=1
    INTO :CNT_DISTRICT, :CNT_PUPIL_IN_DISTRICT;

    CNT_DISTRICT = coalesce(CNT_DISTRICT, 0);
    CNT_PUPIL_IN_DISTRICT = coalesce(CNT_PUPIL_IN_DISTRICT, 0);

    SUSPEND;
  END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_REPORT_VCN (
    I$OOOD_ID BIGINT)
RETURNS (
    OOOD_ID BIGINT,
    OOOD_NAME VARCHAR(100),
    VAK_TAG VARCHAR(20),
    VAC_ID BIGINT,
    VAC_CAPTION VARCHAR(100),
    FIO_OUT_ID BIGINT,
    FIO_OUT VARCHAR(100),
    DATE_EVENTS_OUT DATE,
    STAVOK_OUT DOUBLE PRECISION,
    FIO_IN_ID BIGINT,
    FIO_IN VARCHAR(100),
    DATE_EVENTS_IN DATE,
    STAVOK_IN DOUBLE PRECISION,
    COMMENT VARCHAR(500))
AS
declare variable V$OOOD_ID bigint;
declare variable V$VAK_TAG varchar(20);
declare variable V$VAC_ID bigint;
declare variable V$DATE_EVENTS date;
declare variable V$PERSON_ID bigint;
declare variable V$LISTVAL_ID bigint;
declare variable V$STAVOK double precision;
declare variable V$VAC_POS_ID integer;
declare variable V$PRED_OOOD_ID bigint;
declare variable V$PRED_VAK_TAG varchar(20);
declare variable V$PRED_VAC_ID bigint;
declare variable V$SUM_STAVOK_OUT double precision;
declare variable V$SUM_STAVOK_IN double precision;
declare variable V$FIRST_RECORD integer;
declare variable V$STAVOK_IN double precision;
declare variable V$STAVOK_OUT double precision;
declare variable V$DATE_EVENTS_OUT date;
declare variable V$DATE_EVENTS_IN date;
declare variable V$FIO_OUT_ID bigint;
declare variable V$FIO_IN_ID bigint;
BEGIN

  DELETE FROM PARAGRAF_REPORT_VCN_TEMP WHERE 1 = 1;
  
  V$PRED_OOOD_ID = 0;
  V$PRED_VAK_TAG = '';
  V$PRED_VAC_ID = 0;
  V$VAC_POS_ID = 0;

  -- Выборка по временно свободным ставкам
  FOR
    SELECT LPP.PARENT_ID, LV.TAG, LP13.PARENT_ID, V2860.VAL, L376.PARENT_ID, V587.LISTVAL_ID, V71.VAL
    -- Сотрудник -> Отпуск
    FROM LINKS L376
    -- Дата ухода в отпуск и выхода из отпуска
    JOIN VALD V2860 ON V2860.OBJ_ID = L376.OBJ_ID AND V2860.IS_DEL = 0 AND V2860.PARAM_ID = 2860 AND V2860.VAL <= CURRENT_DATE
    LEFT JOIN VALD V2861 ON V2861.OBJ_ID = L376.OBJ_ID AND V2861.PARAM_ID = 2861 AND V2861.IS_DEL = 0
    -- Назначение на должность
    JOIN LINKS L15 ON L15.PARENT_ID = L376.PARENT_ID AND L15.OBJ_TYPE_ID = 15 AND L15.PARENT_TYPE_ID = 14 AND L15.DATE_DEL IS NULL
    -- Сама должность
    JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
    -- Дата приема на должность
    JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.IS_DEL = 0  AND V73.PARAM_ID = 73 AND V73.VAL <= CURRENT_DATE
    -- Количество ставок
    JOIN VALF V71 ON V71.OBJ_ID = L15.OBJ_ID AND V71.IS_DEL = 0 AND V71.PARAM_ID = 71 AND V71.VAL > 0
    -- Дата увольнения
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.IS_DEL = 0 AND V74.PARAM_ID = 74
    -- Должность как трудовая функция
    JOIN VALL V58 ON V58.OBJ_ID = LP13.PARENT_ID AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V58.LISTVAL_ID
    -- Только штатные сотрудники или совместители
    JOIN VALL V587 ON V587.OBJ_ID = L15.OBJ_ID AND V587.IS_DEL = 0 AND V587.PARAM_ID = 587 AND V587.LISTVAL_ID IN (207, 208)
    JOIN LINKS LPP ON LPP.OBJ_ID = LP13.PARENT_ID AND LPP.PARENT_TYPE_ID IN (2, 211) AND LPP.DATE_DEL IS NULL
    WHERE L376.PARENT_TYPE_ID = 14 AND L376.OBJ_TYPE_ID = 376 AND L376.DATE_DEL IS NULL
      -- Все еще в отпуске, и действующий сотрудник
      AND (V2861.VAL IS NULL OR V2861.VAL > CURRENT_DATE) AND (V74.VAL IS NULL OR V74.VAL > CURRENT_DATE) AND
      (
        LPP.PARENT_ID = :I$OOOD_ID OR
        (LPP.PARENT_ID IN (SELECT L211.OBJ_ID FROM LINKS L211 WHERE L211.DATE_DEL IS NULL AND L211.OBJ_TYPE_ID = 211 AND L211.PARENT_ID = :I$OOOD_ID))
      )
      -- И нет других более ранних отпусков у того же сотрудника
      AND NOT EXISTS (
        SELECT FIRST 1 1
        FROM LINKS LX376
        JOIN VALD VX2860 ON VX2860.OBJ_ID = LX376.OBJ_ID AND VX2860.IS_DEL = 0 AND VX2860.PARAM_ID = 2860 AND VX2860.VAL > V2860.VAL
        WHERE LX376.PARENT_ID = L376.PARENT_ID AND LX376.OBJ_TYPE_ID = 376 AND LX376.DATE_DEL IS NULL AND LX376.OBJ_ID <> L376.OBJ_ID
      )
    ORDER BY 1, 2, 3, 4, 5
    INTO :V$OOOD_ID, :V$VAK_TAG, :V$VAC_ID, :V$DATE_EVENTS, :V$PERSON_ID, :V$LISTVAL_ID, :V$STAVOK
  DO
  BEGIN

      IF ((V$PRED_OOOD_ID <> V$OOOD_ID) OR (V$PRED_VAK_TAG <> V$VAK_TAG) OR (V$PRED_VAC_ID <> V$VAC_ID)) THEN
      BEGIN
        V$PRED_OOOD_ID = V$OOOD_ID;
        V$PRED_VAK_TAG = V$VAK_TAG;
        V$PRED_VAC_ID = V$VAC_ID;
        V$VAC_POS_ID = 1;
      END
      ELSE
        V$VAC_POS_ID = V$VAC_POS_ID + 1;
    
      INSERT INTO PARAGRAF_REPORT_VCN_TEMP (OOOD_ID, VAK_TAG, VAC_ID, DATE_EVENTS, FIO_ID, LISTVAL_ID, STAVOK, TYPE_RECORD, VAC_POS_ID)
      VALUES (:V$OOOD_ID, :V$VAK_TAG, :V$VAC_ID, :V$DATE_EVENTS, :V$PERSON_ID, :V$LISTVAL_ID, :V$STAVOK, 0, :V$VAC_POS_ID);

  END
  
  V$PRED_OOOD_ID = 0;
  V$PRED_VAK_TAG = '';
  V$PRED_VAC_ID = 0;
  V$VAC_POS_ID = 0;

  -- Сотрудники, принятые на временно свободные должности
  FOR
    SELECT LPP.PARENT_ID, LV.TAG, LP13.PARENT_ID, V73.VAL, L15.PARENT_ID, V587.LISTVAL_ID, V71.VAL
    -- Сотрудник -> Должность
    FROM LINKS L15
    JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
    JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.IS_DEL = 0 AND V73.PARAM_ID = 73 AND V73.VAL <= CURRENT_DATE
    JOIN VALF V71 ON V71.OBJ_ID = L15.OBJ_ID AND V71.IS_DEL = 0 AND V71.PARAM_ID = 71 AND V71.VAL > 0
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID  AND V74.IS_DEL = 0  AND V74.PARAM_ID = 74
    JOIN VALL V587 ON V587.OBJ_ID = L15.OBJ_ID  AND V587.IS_DEL = 0  AND V587.PARAM_ID = 587 AND V587.LISTVAL_ID IN (1720, 12824)
    JOIN LINKS LPP on LPP.OBJ_ID = LP13.PARENT_ID AND LPP.PARENT_TYPE_ID IN (2, 211) AND LPP.DATE_DEL IS NULL
    -- Должность как трудовая функция
    JOIN VALL V58 ON V58.OBJ_ID = LP13.PARENT_ID AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V58.LISTVAL_ID
    WHERE L15.OBJ_TYPE_ID = 15 AND L15.PARENT_TYPE_ID = 14 AND L15.DATE_DEL IS NULL AND
      -- Заместитель сам не в длительном отпуске и не уволен
      (V74.VAL > CURRENT_DATE OR V74.VAL IS NULL) AND
      NOT EXISTS (
        SELECT FIRST 1 1
        FROM LINKS L376
        JOIN VALD V2860 ON V2860.OBJ_ID = L376.OBJ_ID AND V2860.IS_DEL = 0 AND V2860.PARAM_ID = 2860 AND V2860.VAL <= CURRENT_DATE
        LEFT JOIN VALD V2861 ON V2861.OBJ_ID = L376.OBJ_ID AND V2861.IS_DEL = 0 AND V2861.PARAM_ID = 2861
        WHERE L376.PARENT_ID = L15.PARENT_ID AND L376.OBJ_TYPE_ID = 376 AND L376.DATE_DEL IS NULL AND
          (V2861.VAL IS NULL OR V2861.VAL > CURRENT_DATE)
      ) AND
      (
        LPP.PARENT_ID = :I$OOOD_ID OR
        (LPP.PARENT_ID IN (SELECT L211.OBJ_ID FROM LINKS L211 WHERE L211.DATE_DEL IS NULL AND L211.OBJ_TYPE_ID = 211 AND L211.PARENT_ID = :I$OOOD_ID))
      )
    ORDER BY 1, 2, 3, 4, 5
    INTO :V$OOOD_ID, :V$VAK_TAG, :V$VAC_ID, :V$DATE_EVENTS, :V$PERSON_ID, :V$LISTVAL_ID, :V$STAVOK
  DO
  BEGIN
    IF ((V$PRED_OOOD_ID <> V$OOOD_ID) OR (V$PRED_VAK_TAG <> V$VAK_TAG) OR (V$PRED_VAC_ID <> V$VAC_ID)) THEN
    BEGIN
      V$PRED_OOOD_ID = V$OOOD_ID;
      V$PRED_VAK_TAG = V$VAK_TAG;
      V$PRED_VAC_ID = V$VAC_ID;
      V$VAC_POS_ID = 1;
    END
    ELSE
      V$VAC_POS_ID = V$VAC_POS_ID + 1;
    
    INSERT INTO PARAGRAF_REPORT_VCN_TEMP (OOOD_ID, VAK_TAG, VAC_ID, DATE_EVENTS, FIO_ID, LISTVAL_ID, STAVOK, TYPE_RECORD, VAC_POS_ID)
    VALUES (:V$OOOD_ID, :V$VAK_TAG, :V$VAC_ID, :V$DATE_EVENTS, :V$PERSON_ID, :V$LISTVAL_ID, :V$STAVOK, 1, :V$VAC_POS_ID);
  END
  
  V$SUM_STAVOK_OUT = 0;
  V$SUM_STAVOK_IN = 0;
  V$PRED_OOOD_ID = 0;
  V$PRED_VAK_TAG = '';
  V$PRED_VAC_ID = 0;
  V$FIRST_RECORD = 0;
  
  FOR
    SELECT COALESCE(B.OOOD_ID, D.OOOD_ID), COALESCE(B.VAK_TAG, D.VAK_TAG), COALESCE(B.VAC_ID, D.VAC_ID), B.FIO_ID, B.DATE_EVENTS, B.STAVOK, D.FIO_ID, D.DATE_EVENTS, D.STAVOK
    FROM (
          SELECT A.OOOD_ID, A.VAK_TAG, A.VAC_ID, C.FIO_ID, C.LISTVAL_ID, C.DATE_EVENTS, C.STAVOK, C.VAC_POS_ID
          FROM (SELECT DISTINCT OOOD_ID, VAK_TAG, VAC_ID FROM PARAGRAF_REPORT_VCN_TEMP) A
          LEFT JOIN PARAGRAF_REPORT_VCN_TEMP C ON C.VAC_ID = A.VAC_ID AND C.OOOD_ID = A.OOOD_ID AND C.TYPE_RECORD = 0
          ) B
    FULL JOIN
         (
          SELECT A.OOOD_ID, A.VAK_TAG, A.VAC_ID, C.FIO_ID, C.LISTVAL_ID, C.DATE_EVENTS, C.STAVOK, C.VAC_POS_ID
          FROM (SELECT DISTINCT OOOD_ID,VAK_TAG, VAC_ID FROM PARAGRAF_REPORT_VCN_TEMP) A
          LEFT JOIN PARAGRAF_REPORT_VCN_TEMP C ON C.VAC_ID = A.VAC_ID AND C.OOOD_ID = A.OOOD_ID AND C.TYPE_RECORD = 1
         ) D ON B.OOOD_ID = D.OOOD_ID  AND B.VAK_TAG = D.VAK_TAG AND B.VAC_ID = D.VAC_ID AND B.VAC_POS_ID = D.VAC_POS_ID
    WHERE COALESCE(B.VAC_POS_ID, D.VAC_POS_ID) IS NOT NULL
    ORDER BY 1, 2, 3, COALESCE(B.VAC_POS_ID, D.VAC_POS_ID)
  INTO :V$OOOD_ID, :V$VAK_TAG, :V$VAC_ID, :V$FIO_OUT_ID, :V$DATE_EVENTS_OUT, :V$STAVOK_OUT, :V$FIO_IN_ID, :V$DATE_EVENTS_IN, :V$STAVOK_IN
  DO
  BEGIN
    VAC_CAPTION = '';
    FIO_OUT = '';
    FIO_IN = '';

    -- если меняется :OOOD_ID выводим строку с суммами итого  :STAVOK_OUT, :STAVOK_IN
    -- если меняется :VAC_ID и  :VAK_TAG <> 'U' выводим строку с суммами итого  :STAVOK_OUT, :STAVOK_IN
    -- если меняется :VAK_TAG и предыдущее VAK_TAG = 'U' выводим строку с суммами итого  :STAVOK_OUT, :STAVOK_IN
    IF ((V$PRED_OOOD_ID <> :V$OOOD_ID) OR (V$PRED_VAK_TAG <> :V$VAK_TAG) OR ((V$PRED_VAC_ID <> :V$VAC_ID) AND (:V$VAK_TAG <> 'U') ) ) THEN
    BEGIN

      IF (V$FIRST_RECORD <> 0) THEN
      BEGIN
        VAK_TAG = V$PRED_VAK_TAG;
        VAC_ID = V$PRED_VAC_ID;
        OOOD_ID = V$PRED_OOOD_ID;
        VAC_CAPTION = 'ИТОГО:';
        FIO_OUT = '';
        FIO_IN = '';
        COMMENT = '';
        OOOD_NAME = '';
        FIO_OUT_ID = NULL;
        FIO_IN_ID = NULL;
        STAVOK_OUT = V$SUM_STAVOK_OUT;
        STAVOK_IN = V$SUM_STAVOK_IN;
        DATE_EVENTS_OUT = NULL;
        DATE_EVENTS_IN = NULL;
        IF (STAVOK_IN > STAVOK_OUT) THEN COMMENT = 'ВНИМАНИЕ!!! Количество занятых ставок больше временно свободных по должности!';
        SUSPEND;
      END

      if ((V$PRED_OOOD_ID = V$OOOD_ID)) then V$FIRST_RECORD = 2; ELSE V$FIRST_RECORD = 1;
      V$PRED_OOOD_ID = V$OOOD_ID;
      V$PRED_VAK_TAG = V$VAK_TAG;
      V$PRED_VAC_ID = V$VAC_ID;

      V$SUM_STAVOK_OUT = COALESCE(V$STAVOK_OUT,0);
      V$SUM_STAVOK_IN = COALESCE(V$STAVOK_IN,0);

    END
    ELSE
    BEGIN
      V$SUM_STAVOK_OUT = V$SUM_STAVOK_OUT + COALESCE(V$STAVOK_OUT, 0);
      V$SUM_STAVOK_IN = V$SUM_STAVOK_IN + COALESCE(V$STAVOK_IN, 0);
      V$FIRST_RECORD = 2;
    END
    
    FIO_OUT_ID = V$FIO_OUT_ID;
    FIO_IN_ID = V$FIO_IN_ID;
    VAK_TAG = V$VAK_TAG;
    VAC_ID = V$VAC_ID;
    STAVOK_OUT = V$STAVOK_OUT;
    STAVOK_IN = V$STAVOK_IN;
    DATE_EVENTS_OUT = V$DATE_EVENTS_OUT;
    DATE_EVENTS_IN = V$DATE_EVENTS_IN;
    VAC_CAPTION = '';
    FIO_OUT = '';
    FIO_IN = '';
    COMMENT = '';
    
    SELECT CAST(VS59.VAL || ' ' || VS60.VAL || ' ' || COALESCE(VS61.VAL, '') AS VARCHAR(100))
    FROM VALS VS59
    LEFT JOIN VALS VS60 ON VS60.OBJ_ID = VS59.OBJ_ID  AND VS60.PARAM_ID = 60 AND VS60.IS_DEL = 0
    LEFT JOIN VALS VS61 ON VS61.OBJ_ID = VS59.OBJ_ID  AND VS61.PARAM_ID = 61 AND VS61.IS_DEL = 0
    WHERE VS59.OBJ_ID = :FIO_OUT_ID AND VS59.PARAM_ID = 59 AND VS59.IS_DEL=0
    INTO :FIO_OUT;
    
    SELECT CAST(VS59.VAL || ' ' || VS60.VAL || ' ' || COALESCE(VS61.VAL, '') AS VARCHAR(100))
    FROM VALS VS59
    LEFT JOIN VALS VS60 ON VS60.OBJ_ID = VS59.OBJ_ID  AND VS60.PARAM_ID = 60 AND VS60.IS_DEL = 0
    LEFT JOIN VALS VS61 ON VS61.OBJ_ID = VS59.OBJ_ID  AND VS61.PARAM_ID = 61 AND VS61.IS_DEL = 0
    WHERE VS59.OBJ_ID = :FIO_IN_ID  AND VS59.PARAM_ID = 59 AND VS59.IS_DEL=0
    INTO :FIO_IN;

    SELECT CAST( VS66.VAL AS VARCHAR(100))
    FROM VALS VS66
    WHERE VS66.OBJ_ID = :VAC_ID AND VS66.PARAM_ID = 66 AND VS66.IS_DEL=0
    INTO :VAC_CAPTION; 
    OOOD_NAME = '';

    IF (V$FIRST_RECORD <> 2) THEN
      SELECT CAST(VS2_1792.VAL AS VARCHAR(100))
      FROM VALS VS2_1792
      WHERE VS2_1792.OBJ_ID = :V$OOOD_ID AND ((VS2_1792.PARAM_ID = 2) OR (VS2_1792.PARAM_ID = 1792)) AND VS2_1792.IS_DEL = 0
      INTO :OOOD_NAME;
    ELSE
      OOOD_NAME = '';

    OOOD_ID = V$OOOD_ID;
    SUSPEND;
  END
  
  IF (V$FIRST_RECORD <> 0) THEN
  BEGIN
    VAC_CAPTION = 'ИТОГО:';
    FIO_OUT = '';
    FIO_IN = '';
    COMMENT = '';
    OOOD_NAME = '';
    FIO_OUT_ID= NULL;
    FIO_IN_ID= NULL;
    STAVOK_OUT = V$SUM_STAVOK_OUT;
    STAVOK_IN = V$SUM_STAVOK_IN;
    IF (STAVOK_IN > STAVOK_OUT) THEN COMMENT = 'ВНИМАНИЕ!!! Количество занятых ставок больше временно свободных по должности!';
    DATE_EVENTS_OUT = NULL;
    DATE_EVENTS_IN = NULL;
    SUSPEND;
  END

END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_ROOMS_LIST (
    I$OBJ_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    ROOM_ID BIGINT,
    ROOM_CAPTION VARCHAR(4000),
    ROOM_NUMBER VARCHAR(100),
    IS_SERVICE_ROOM SMALLINT)
AS
declare variable V$OBJ_ID bigint;
BEGIN
    IF (I$OBJ_ID IS NULL) THEN
    BEGIN
        SELECT FIRST 1 OBJ_ID
        FROM LINKS L
        WHERE L.PARENT_ID IS NULL AND L.OBJ_TYPE_ID = 2 AND L.DATE_DEL IS NULL
        INTO :V$OBJ_ID;
    END
    ELSE
    BEGIN
        SELECT FIRST 1 OBJ_ID
        FROM OBJECT_PARENTS_GET(:I$OBJ_ID, 2)
        INTO :V$OBJ_ID;
    END

    FOR SELECT L61.OBJ_ID
        FROM LINKS L73
        JOIN LINKS L16 ON L16.PARENT_ID = L73.OBJ_ID AND L16.OBJ_TYPE_ID = 16 AND L16.DATE_DEL IS NULL
        JOIN LINKS L61 ON L61.PARENT_ID = L16.OBJ_ID AND L61.OBJ_TYPE_ID = 61 AND L61.DATE_DEL IS NULL
        WHERE L73.PARENT_ID = :V$OBJ_ID AND L73.DATE_DEL IS NULL AND L73.OBJ_TYPE_ID = 73
        INTO :ROOM_ID
    DO
    BEGIN
        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:ROOM_ID, NULL, NULL, :I$USER_ID)
        INTO :ROOM_CAPTION;

        SELECT V
        FROM VAL_GET(:ROOM_ID, 407, 0, :I$USER_ID)
        INTO :ROOM_NUMBER;

        SELECT I
        FROM VAL_GET(:ROOM_ID, 525, 0, :I$USER_ID)
        INTO :IS_SERVICE_ROOM;

        IF (IS_SERVICE_ROOM = 23) THEN
        BEGIN
            IS_SERVICE_ROOM = 0;
        END
        ELSE
        BEGIN
            IS_SERVICE_ROOM = 1;
        END

        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_ROOMS_TREE_LIST (
    I$OBJ_ID BIGINT,
    I$NOT_SERVICE SMALLINT = 0,
    I$USER_ID BIGINT = null)
RETURNS (
    OBJ_ID BIGINT,
    PARENT_ID BIGINT,
    OBJ_CAPTION VARCHAR(4000))
AS
declare variable V$OBJ_ID bigint;
declare variable V$PARENT_ID bigint;
declare variable V$COUNT bigint;
declare variable V$IS_SERVICE_ROOM smallint;
BEGIN

    -- Вызывается из: закрепленный кабинет для классов, инвентаризационная карточка, кабинет с локальной сетью (NOT_SERVICE = 1)

    IF (I$OBJ_ID IS NULL) THEN
    BEGIN
        SELECT FIRST 1 OBJ_ID
        FROM LINKS L
        WHERE L.PARENT_ID IS NULL AND L.OBJ_TYPE_ID = 2 AND L.DATE_DEL IS NULL
        INTO :V$OBJ_ID;
    END
    ELSE
    BEGIN
        SELECT FIRST 1 OBJ_ID
        FROM OBJECT_PARENTS_GET(:I$OBJ_ID, 2)
        INTO :V$OBJ_ID;
    END

    FOR
        SELECT L16.OBJ_ID
        FROM LINKS L73
        JOIN LINKS L16 ON L16.PARENT_ID = L73.OBJ_ID AND L16.OBJ_TYPE_ID = 16 AND L16.DATE_DEL IS NULL
        WHERE L73.PARENT_ID = :V$OBJ_ID AND L73.DATE_DEL IS NULL AND L73.OBJ_TYPE_ID = 73
        INTO :V$PARENT_ID
    DO
    BEGIN
        V$COUNT = 0;
        PARENT_ID = V$PARENT_ID;
        FOR
            SELECT L61.OBJ_ID
            FROM LINKS L61
            WHERE L61.PARENT_ID = :V$PARENT_ID AND L61.OBJ_TYPE_ID = 61 AND L61.DATE_DEL IS NULL
            INTO :OBJ_ID
        DO
        BEGIN
            V$IS_SERVICE_ROOM = 0;
            IF (I$NOT_SERVICE = 1) THEN
            BEGIN
                SELECT I
                FROM VAL_GET(:OBJ_ID, 525, 0, :I$USER_ID)
                INTO :V$IS_SERVICE_ROOM;

                IF (V$IS_SERVICE_ROOM IN (23, 1182, 12764)) THEN
                BEGIN
                    V$IS_SERVICE_ROOM = 0;
                END
                ELSE
                BEGIN
                    V$IS_SERVICE_ROOM = 1;
                END
            END

            IF (V$IS_SERVICE_ROOM = 0) THEN
            BEGIN
                V$COUNT = V$COUNT + 1;
                SELECT CAPTION
                FROM OBJECT_CAPTION_GET(:OBJ_ID, NULL, NULL, :I$USER_ID)
                INTO :OBJ_CAPTION;
                SUSPEND;
            END
        END

        IF (V$COUNT > 0) THEN
        BEGIN
            PARENT_ID = NULL;
            OBJ_ID = V$PARENT_ID;
            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:OBJ_ID, NULL, NULL, :I$USER_ID)
            INTO :OBJ_CAPTION;
            SUSPEND;
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_SUBGROUP_COPY (
    I$OLD_GROUP_ID BIGINT,
    I$SUBJECT_ID BIGINT,
    I$USER_ID BIGINT,
    I$MOVE_DATE DATE = null)
RETURNS (
    NEW_GROUP_ID BIGINT,
    NEW_GROUP_CAPTION VARCHAR(4000),
    NEW_GROUP_COLOR INTEGER)
AS
declare variable GROUP_TYPE_ID bigint;
declare variable SUBGROUP_TYPE_ID bigint;
declare variable CLASS_ID bigint;
declare variable SUBJ_PARAM_ID bigint;
declare variable NAME_PARAM_ID bigint;
declare variable OLD_SUBGROUP_ID bigint;
declare variable NEW_SUBGROUP_ID bigint;
declare variable SUBGROUP_NAME varchar(4000);
declare variable BLOB_ID bigint;
declare variable SCHOOLAR_ID bigint;
BEGIN

  -- Функционал утрачен

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_SUBGROUP_SUBJECT_LIST (
    I$OBJ_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    PARENT_ID BIGINT,
    OBJ_CAPTION VARCHAR(4000),
    SORT_ORDER DOUBLE PRECISION)
AS
declare variable SUBJECT_FOLDER_ID bigint;
BEGIN
    PARENT_ID = NULL;
    SUBJECT_FOLDER_ID = NULL;

    SELECT FIRST 1 O.OBJ_ID
    FROM OBJECTS O
    WHERE O.TYPE_ID = 53
    INTO :SUBJECT_FOLDER_ID;

    IF (SUBJECT_FOLDER_ID IS NULL) THEN
    BEGIN
        EXIT;
    END

    FOR SELECT OBJ_ID
        FROM OBJECT_CHILDREN_GET_DEEP(:SUBJECT_FOLDER_ID, 51, 2)
        INTO :OBJ_ID
    DO
    BEGIN
        SELECT CAPTION,
               SORT_ORDER
        FROM OBJECT_CAPTION_GET(:OBJ_ID, NULL)
        INTO   :OBJ_CAPTION,
               :SORT_ORDER;
        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_SUBJECTS_LIST (
    I$OBJ_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    OBJ_CAPTION VARCHAR(1000),
    SORT_ORDER DOUBLE PRECISION)
AS
BEGIN
    FOR
        SELECT DISTINCT C.OBJ_ID
        FROM OBJECT_CHILDREN_GET_DEEP(208, 51, 2) C
        WHERE :I$OBJ_ID IS NULL
        UNION ALL
        SELECT DISTINCT C.OBJ_ID
        FROM OBJECTS O
        LEFT JOIN OBJECT_CHILDREN_GET_DEEP(208, 51, 2) C ON 1=1
        WHERE O.OBJ_ID = :I$OBJ_ID AND O.TYPE_ID <> 256
        UNION ALL
        SELECT DISTINCT O.OBJ_ID
        FROM LINKS LP54
        JOIN LINKS LP400 ON LP400.OBJ_ID = LP54.PARENT_ID AND LP400.PARENT_TYPE_ID = 400 AND LP400.DATE_DEL IS NULL
        JOIN VALL V3022 ON V3022.OBJ_ID = LP400.PARENT_ID AND V3022.PARAM_ID = 3022 AND V3022.IS_DEL = 0
        LEFT JOIN OBJECT_CHILDREN_GET_DEEP(IIF(V3022.LISTVAL_ID = 2, 32772, 32771), 51, 2) O ON 1=1
        WHERE LP54.OBJ_ID = :I$OBJ_ID AND LP54.PARENT_TYPE_ID = 54 AND LP54.DATE_DEL IS NULL
        INTO :OBJ_ID
    DO
    BEGIN
        SELECT CAPTION, SORT_ORDER
        FROM OBJECT_CAPTION_GET(:OBJ_ID)
        INTO :OBJ_CAPTION, :SORT_ORDER;

        IF (OBJ_CAPTION <> '<  ...  >') THEN SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_SUBJECT_LINK_LIST (
    I$OBJ_ID BIGINT,
    I$USER_ID BIGINT,
    I$ROOT_ID BIGINT = NULL)
RETURNS (
    OBJ_ID BIGINT,
    PARENT_ID BIGINT,
    OBJ_CAPTION VARCHAR(4000),
    SORT_ORDER DOUBLE PRECISION)
AS
DECLARE VARIABLE V$OO_TYPE VARCHAR(1);
BEGIN
    PARENT_ID = I$ROOT_ID;
    IF (I$ROOT_ID IS NULL) THEN
    BEGIN
        SELECT STATUS FROM OU_LICENCE_TYPE INTO :V$OO_TYPE;
        IF (V$OO_TYPE = 'U') THEN
        BEGIN
            I$ROOT_ID = 20630;
        END
        ELSE
        BEGIN
            I$ROOT_ID = 208;
        END
    END

    FOR
        SELECT L51.OBJ_ID
        FROM LINKS L51

        WHERE L51.PARENT_ID IN (
            SELECT :I$ROOT_ID
            FROM RDB$DATABASE
            UNION

            SELECT L301.OBJ_ID
            FROM LINKS L301
            WHERE L301.PARENT_ID = :I$ROOT_ID
              AND L301.OBJ_TYPE_ID = 301
              AND L301.DATE_DEL IS NULL)
        AND L51.OBJ_TYPE_ID = 51
        AND L51.DATE_DEL IS NULL

        INTO :OBJ_ID
    DO
    BEGIN
        IF (NOT EXISTS(
            SELECT FIRST 1 1
            FROM LINKS
            WHERE PARENT_ID = :I$OBJ_ID
            AND OBJ_ID = :OBJ_ID
            AND DATE_DEL IS NULL
        )) THEN
        BEGIN
            SELECT CAPTION, SORT_ORDER
            FROM OBJECT_CAPTION_GET(:OBJ_ID, NULL, NULL, :I$USER_ID)
            INTO :OBJ_CAPTION, :SORT_ORDER;

            SUSPEND;
        END

        FOR
            SELECT OBJ_ID,
                   PARENT_ID,
                   OBJ_CAPTION,
                   SORT_ORDER
            FROM PARAGRAF_SUBJECT_LINK_LIST(:I$OBJ_ID, :I$USER_ID, :OBJ_ID)
            INTO :OBJ_ID,
                 :PARENT_ID,
                 :OBJ_CAPTION,
                 :SORT_ORDER
        DO
        BEGIN
            SUSPEND;
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_TEACHERS_COUNT (
    I$SCHOOL_ID BIGINT)
RETURNS (
    X INTEGER)
AS
BEGIN

    SELECT COUNT(*) FROM (
        SELECT DISTINCT L14.OBJ_ID
        FROM LINKS L14
        JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.DATE_DEL IS NULL AND L15.OBJ_TYPE_ID = 15
        JOIN LINKS L13 ON L13.OBJ_ID = L15.OBJ_ID AND L13.DATE_DEL IS NULL AND L13.PARENT_TYPE_ID = 13
        JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0 AND V73.VAL <= CURRENT_DATE
        LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
        LEFT JOIN DO_FUNC(L13.PARENT_ID, 400) DF ON 1=1
        WHERE L14.DATE_DEL IS NULL AND L14.OBJ_TYPE_ID = 14 AND L14.PARENT_ID = :I$SCHOOL_ID AND DF.SORT_ORDER = 2 AND ((V74.VAL IS NULL) or (V74.VAL >= CURRENT_DATE))

        UNION

        SELECT DISTINCT L14.OBJ_ID
        FROM LINKS L211
        JOIN LINKS L14 ON L14.DATE_DEL IS NULL AND L14.OBJ_TYPE_ID = 14 AND L14.PARENT_ID = L211.OBJ_ID
        JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.DATE_DEL IS NULL AND L15.OBJ_TYPE_ID = 15
        JOIN LINKS L13 ON L13.OBJ_ID = L15.OBJ_ID AND L13.DATE_DEL IS NULL AND L13.PARENT_TYPE_ID = 13
        JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0 AND V73.VAL <= CURRENT_DATE
        LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
        LEFT JOIN DO_FUNC(L13.PARENT_ID, 400) DF ON 1=1
        WHERE L211.DATE_DEL IS NULL AND L211.OBJ_TYPE_ID = 211 AND L211.PARENT_ID = :I$SCHOOL_ID AND DF.SORT_ORDER = 2 AND ((V74.VAL IS NULL) or (V74.VAL >= CURRENT_DATE))
    )
    INTO :X;

    SUSPEND;

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_TEACHERS_COUNT_DISTR (
    I$OBJ_ID BIGINT)
RETURNS (
    X INTEGER)
AS
BEGIN

    SELECT COUNT(*) FROM (
        SELECT DISTINCT L14.OBJ_ID
        FROM LINKS L2
        JOIN LINKS L14 ON L14.DATE_DEL IS NULL AND L14.OBJ_TYPE_ID = 14 AND L14.PARENT_ID = L2.OBJ_ID
        JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.DATE_DEL IS NULL AND L15.OBJ_TYPE_ID = 15
        JOIN LINKS L13 ON L13.OBJ_ID = L15.OBJ_ID AND L13.DATE_DEL IS NULL AND L13.PARENT_TYPE_ID = 13
        JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0 AND V73.VAL <= CURRENT_DATE
        LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
        LEFT JOIN DO_FUNC(L13.PARENT_ID, 400) DF ON 1=1
        WHERE L2.PARENT_ID = :I$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND DF.SORT_ORDER = 2 AND ((V74.VAL IS NULL) or (V74.VAL >= CURRENT_DATE))

        UNION

        SELECT DISTINCT L14.OBJ_ID
        FROM LINKS L2
        JOIN LINKS L211 ON L211.DATE_DEL IS NULL AND L211.OBJ_TYPE_ID = 211 AND L211.PARENT_ID = L2.OBJ_ID
        JOIN LINKS L14 ON L14.DATE_DEL IS NULL AND L14.OBJ_TYPE_ID = 14 AND L14.PARENT_ID = L211.OBJ_ID
        JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.DATE_DEL IS NULL AND L15.OBJ_TYPE_ID = 15
        JOIN LINKS L13 ON L13.OBJ_ID = L15.OBJ_ID AND L13.DATE_DEL IS NULL AND L13.PARENT_TYPE_ID = 13
        JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0 AND V73.VAL <= CURRENT_DATE
        LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
        LEFT JOIN DO_FUNC(L13.PARENT_ID, 400) DF ON 1=1
        WHERE L2.PARENT_ID = :I$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND DF.SORT_ORDER = 2 AND ((V74.VAL IS NULL) or (V74.VAL >= CURRENT_DATE))
    )
    INTO :X;

    SUSPEND;

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_TRANSFER_STAGE_LIST (
    I$PUPIL_ID BIGINT,
    I$CLASS_ID BIGINT,
    I$USER_ID BIGINT,
    I$EXTERNAT_ONLY SMALLINT = 0)
RETURNS (
    OBJ_ID BIGINT,
    COLOR INTEGER,
    OBJ_CAPTION VARCHAR(4000),
    SORT_ORDER DOUBLE PRECISION)
AS
declare variable V$SCHOOL_ID bigint;
BEGIN
    V$SCHOOL_ID = NULL;
 --   V$OBJ_ID = NULL;

    SELECT FIRST 1 OBJ_ID
    FROM OBJECT_PARENTS_GET(:I$PUPIL_ID, 2)
    INTO :V$SCHOOL_ID;
 /*
    SELECT FIRST 1 OBJ_ID
    FROM OBJECT_PARENTS_GET(:I$PUPIL_ID, 9)
    INTO :V$OBJ_ID;

    IF (V$OBJ_ID IS NULL) THEN
    BEGIN
        SELECT FIRST 1 OBJ_ID
        FROM OBJECT_PARENTS_GET(:I$PUPIL_ID, 46)
        INTO :V$OBJ_ID;
    END
  */
    FOR
        SELECT L9.OBJ_ID,
               T9.COLOR
        FROM LINKS L7

        JOIN LINKS L8
        ON L8.PARENT_ID = L7.OBJ_ID
        AND L8.OBJ_TYPE_ID = 8
        AND L8.DATE_DEL IS NULL

        JOIN LINKS L9
        ON L9.PARENT_ID = L8.OBJ_ID
        AND L9.OBJ_TYPE_ID = 9
        AND L9.DATE_DEL IS NULL
        AND ((:I$CLASS_ID IS NULL) OR (L9.OBJ_ID <> :I$CLASS_ID))

        JOIN TYPES T9
        ON T9.TYPE_ID = L9.OBJ_TYPE_ID

        WHERE :I$EXTERNAT_ONLY = 0
        AND L7.PARENT_ID = :V$SCHOOL_ID
        AND L7.OBJ_TYPE_ID = 7
        AND L7.DATE_DEL IS NULL

        UNION ALL

        SELECT L187.OBJ_ID,
               T187.COLOR
        FROM LINKS L7

        JOIN LINKS L8
        ON L8.PARENT_ID = L7.OBJ_ID
        AND L8.OBJ_TYPE_ID = 8
        AND L8.DATE_DEL IS NULL

        JOIN LINKS L187
        ON L187.PARENT_ID = L8.OBJ_ID
        AND L187.OBJ_TYPE_ID = 187
        AND L187.DATE_DEL IS NULL

        JOIN TYPES T187
        ON T187.TYPE_ID = L187.OBJ_TYPE_ID

          -- восстанавливать в класс-экстернат нельзя

        AND NOT EXISTS (
            SELECT FIRST 1 1
            FROM LINKS L
            WHERE L.OBJ_ID = :I$PUPIL_ID
            AND L.DATE_DEL IS NULL
            AND L.PARENT_TYPE_ID = 187
        )
        AND ((:I$CLASS_ID IS NULL) OR (L187.OBJ_ID <> :I$CLASS_ID))

        WHERE L7.PARENT_ID = :V$SCHOOL_ID
        AND L7.OBJ_TYPE_ID = 7
        AND L7.DATE_DEL IS NULL


        INTO :OBJ_ID, :COLOR
    DO
    BEGIN
        SELECT CAPTION, SORT_ORDER
        FROM OBJECT_CAPTION_GET(:OBJ_ID, NULL, NULL, :I$USER_ID)
        INTO :OBJ_CAPTION, :SORT_ORDER;
        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_TYPE_LEVEL (
    I$PARENT_ID BIGINT,
    I$LINKED_TYPE_ID BIGINT,
    I$LEVEL SMALLINT = 1)
RETURNS (
    OBJ_ID BIGINT,
    PARENT_ID BIGINT,
    OBJ_CAPTION VARCHAR(4000),
    SORT_ORDER DOUBLE PRECISION)
AS
BEGIN
    PARENT_ID = NULL;
    IF (I$LEVEL > 0) THEN
    BEGIN
        FOR
            SELECT DISTINCT O.OBJ_ID
            FROM LINKS L
            JOIN OBJECTS O ON O.OBJ_ID = L.OBJ_ID AND (O.TYPE_ID = :I$LINKED_TYPE_ID OR :I$LEVEL > 1)
            WHERE L.PARENT_ID = :I$PARENT_ID AND L.DATE_DEL IS NULL
            INTO   :OBJ_ID
        DO
        BEGIN
            IF (I$LEVEL = 1) THEN
            BEGIN
                SELECT CAPTION, SORT_ORDER
                FROM OBJECT_CAPTION_GET(:OBJ_ID, NULL)
                INTO :OBJ_CAPTION, :SORT_ORDER;
                SUSPEND;
            END
            ELSE
            BEGIN
                FOR
                    SELECT OBJ_ID, OBJ_CAPTION, SORT_ORDER
                    FROM PARAGRAF_TYPE_LEVEL(:OBJ_ID, :I$LINKED_TYPE_ID, :I$LEVEL - 1)
                    INTO :OBJ_ID, :OBJ_CAPTION, :SORT_ORDER
                DO
                BEGIN
                    SUSPEND;
                END
            END
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_TYPE_NOT_LINKED_LIST (
    I$PARENT_TYPE_ID BIGINT,
    I$LINKED_TYPE_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$USER_ID BIGINT,
    I$CHECK_PARENT_TYPE_ID BIGINT = null,
    I$ROOT_PARENT_ID BIGINT = null,
    I$ROOT_TYPE_ID BIGINT = null)
RETURNS (
    OBJ_ID BIGINT,
    PARENT_ID BIGINT,
    OBJ_CAPTION VARCHAR(4000),
    SORT_ORDER DOUBLE PRECISION)
AS
declare variable V$OBJ_ID bigint;
declare variable V$OBJ_ID2 bigint;
declare variable V$OBJ_ID3 bigint;
declare variable V$GROUP_OBJ_ID bigint;
declare variable T bigint;
BEGIN
    PARENT_ID = NULL;
    V$OBJ_ID = NULL;
    V$GROUP_OBJ_ID = NULL;
    IF (I$ROOT_PARENT_ID IS NOT NULL) THEN
    BEGIN
      V$OBJ_ID = I$ROOT_PARENT_ID;
    END
    ELSE
    IF (I$ROOT_TYPE_ID IS NOT NULL) THEN
    BEGIN
      -- Изменение для ОП: может быть несколько разделов ОП, надо учесть все
      -- учитываем максимально 3 экземпляра
      FOR
        SELECT DISTINCT OBJ_ID
        FROM LINKS
        WHERE OBJ_TYPE_ID = :I$ROOT_TYPE_ID AND DATE_DEL IS NULL
        INTO :T
      DO
      BEGIN
        IF(V$OBJ_ID IS NULL) THEN V$OBJ_ID = T;
        ELSE IF(V$OBJ_ID2 IS NULL) THEN V$OBJ_ID2 = T;
        ELSE IF(V$OBJ_ID3 IS NULL) THEN V$OBJ_ID3 = T;
      END
    END
    ELSE
    BEGIN
      SELECT FIRST 1 OBJ_ID
      FROM OBJECT_PARENTS_GET(:I$OBJ_ID, :I$PARENT_TYPE_ID)
      INTO :V$OBJ_ID;
    END
    IF (V$OBJ_ID IS NOT NULL) THEN
    BEGIN
      IF (I$CHECK_PARENT_TYPE_ID IS NOT NULL) THEN
      BEGIN
        SELECT FIRST 1 OBJ_ID
        FROM OBJECT_PARENTS_GET(:I$OBJ_ID, :I$CHECK_PARENT_TYPE_ID)
        INTO :V$GROUP_OBJ_ID;
      END

      IF (V$GROUP_OBJ_ID IS NULL) THEN
      BEGIN
        FOR
          SELECT DISTINCT O.OBJ_ID
          FROM OBJECT_CHILDREN_GET_DEEP(:V$OBJ_ID, :I$LINKED_TYPE_ID, 2) O
          LEFT JOIN LINKS L ON L.PARENT_ID = :I$OBJ_ID AND L.OBJ_ID = O.OBJ_ID AND L.OBJ_TYPE_ID = :I$LINKED_TYPE_ID AND L.DATE_DEL IS NULL
          WHERE L.OBJ_ID IS NULL
          UNION
          SELECT DISTINCT O.OBJ_ID
          FROM OBJECT_CHILDREN_GET_DEEP(:V$OBJ_ID2, :I$LINKED_TYPE_ID, 2) O
          LEFT JOIN LINKS L ON L.PARENT_ID = :I$OBJ_ID AND L.OBJ_ID = O.OBJ_ID AND L.OBJ_TYPE_ID = :I$LINKED_TYPE_ID AND L.DATE_DEL IS NULL
          WHERE :V$OBJ_ID2 IS NOT NULL AND L.OBJ_ID IS NULL
          UNION
          SELECT DISTINCT O.OBJ_ID
          FROM OBJECT_CHILDREN_GET_DEEP(:V$OBJ_ID3, :I$LINKED_TYPE_ID, 2) O
          LEFT JOIN LINKS L ON L.PARENT_ID = :I$OBJ_ID AND L.OBJ_ID = O.OBJ_ID AND L.OBJ_TYPE_ID = :I$LINKED_TYPE_ID AND L.DATE_DEL IS NULL
          WHERE :V$OBJ_ID3 IS NOT NULL AND L.OBJ_ID IS NULL
          INTO :OBJ_ID
        DO
        BEGIN
          SELECT CAPTION, SORT_ORDER
          FROM OBJECT_CAPTION_GET(:OBJ_ID, NULL, NULL, :I$USER_ID)
          INTO :OBJ_CAPTION, :SORT_ORDER;
          SUSPEND;
        END
      END
      ELSE
      BEGIN
        FOR
          SELECT DISTINCT O.OBJ_ID
          FROM OBJECT_CHILDREN_GET_DEEP(:V$OBJ_ID, :I$LINKED_TYPE_ID, 2) O
          -- На нулевом уровне может оказаться что DATE_DEL для V$OBJ_ID не будет проверен
          JOIN LINKS L ON L.OBJ_ID = O.OBJ_ID AND L.DATE_DEL IS NULL
          WHERE O.OBJ_ID NOT IN (
            SELECT OBJ_ID
            FROM OBJECT_CHILDREN_GET_DEEP(:V$GROUP_OBJ_ID, :I$LINKED_TYPE_ID, 2)
          )
          UNION
          SELECT DISTINCT O.OBJ_ID
          FROM OBJECT_CHILDREN_GET_DEEP(:V$OBJ_ID2, :I$LINKED_TYPE_ID, 2) O
          JOIN LINKS L ON L.OBJ_ID = O.OBJ_ID AND L.DATE_DEL IS NULL
          WHERE :V$OBJ_ID2 IS NOT NULL AND O.OBJ_ID NOT IN (
            SELECT OBJ_ID
            FROM OBJECT_CHILDREN_GET_DEEP(:V$GROUP_OBJ_ID, :I$LINKED_TYPE_ID, 2)
          )
          UNION
          SELECT DISTINCT O.OBJ_ID
          FROM OBJECT_CHILDREN_GET_DEEP(:V$OBJ_ID3, :I$LINKED_TYPE_ID, 2) O
          JOIN LINKS L ON L.OBJ_ID = O.OBJ_ID AND L.DATE_DEL IS NULL
          WHERE :V$OBJ_ID3 IS NOT NULL AND O.OBJ_ID NOT IN (
            SELECT OBJ_ID
            FROM OBJECT_CHILDREN_GET_DEEP(:V$GROUP_OBJ_ID, :I$LINKED_TYPE_ID, 2)
          )
          INTO :OBJ_ID
        DO
        BEGIN
          SELECT CAPTION, SORT_ORDER
          FROM OBJECT_CAPTION_GET(:OBJ_ID, NULL, NULL, :I$USER_ID)
          INTO :OBJ_CAPTION, :SORT_ORDER;
          SUSPEND;
        END
      END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_TYPE_REFERENSE_LIST (
    I$TYPE_ID BIGINT,
    I$PARAM_ID BIGINT = null)
RETURNS (
    OBJ_ID BIGINT,
    OBJ_CAPTION VARCHAR(4000),
    SORT_ORDER DOUBLE PRECISION,
    PARAM_CAPTION VARCHAR(1000))
AS
BEGIN
    FOR
        SELECT DISTINCT L.OBJ_ID
        FROM LINKS L
        WHERE L.OBJ_TYPE_ID = :I$TYPE_ID AND L.DATE_DEL IS NULL
        INTO :OBJ_ID
    DO
    BEGIN
        SELECT CAPTION, SORT_ORDER
        FROM OBJECT_CAPTION_GET(:OBJ_ID, NULL)
        INTO :OBJ_CAPTION, :SORT_ORDER;

        PARAM_CAPTION = NULL;
        IF(I$PARAM_ID IS NOT NULL) THEN
        SELECT FIRST 1 V.VAL
        FROM VALS V
        WHERE V.OBJ_ID = :OBJ_ID AND V.PARAM_ID = :I$PARAM_ID AND V.IS_DEL = 0
        INTO :PARAM_CAPTION;

        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_UDOD_PUPIL_REVERT (
    I$PUPIL_ID BIGINT,
    I$MOVEMENT_ID BIGINT)
RETURNS (
    X SMALLINT,
    OBJ_ID BIGINT,
    OBJ_CAPTION VARCHAR(4000))
AS
declare variable V$DATE_OUT date;
declare variable V$BLOB_ID bigint;
BEGIN

    -- X принимает значение 1 или 2, 2 если ученик больше не числится в данной группе

    SELECT M.DATE_OUT, M.GROUP_ID
    FROM PERSON_MOVEMENTS M
    WHERE M.OBJ_ID = :I$MOVEMENT_ID
    INTO :V$DATE_OUT, :OBJ_ID;

    -- Отменяем зачисление или отчисление
    SELECT OBJ_ID FROM VARGRP_MOVE_PUPIL(:I$PUPIL_ID, :OBJ_ID, NULL, NULL, NULL, IIF(:V$DATE_OUT IS NULL, 3, 4), NULL) INTO :V$BLOB_ID;

    IF(EXISTS(SELECT 1 FROM LINKS L WHERE L.OBJ_ID = :I$PUPIL_ID AND L.PARENT_ID = :OBJ_ID AND L.DATE_DEL IS NULL)) THEN
    BEGIN
        X = 1;

        SELECT C1.CAPTION || ' - ' || C2.CAPTION
        FROM LINKS L
        LEFT JOIN OBJECT_CAPTION_GET(L.OBJ_ID) C2 ON 1 = 1
        LEFT JOIN OBJECT_CAPTION_GET(L.PARENT_ID) C1 ON 1 = 1
        WHERE L.OBJ_ID = :OBJ_CAPTION AND L.PARENT_TYPE_ID = 242 AND L.DATE_DEL IS NULL
        INTO :OBJ_CAPTION;
    END
    ELSE
    BEGIN
        X = 2;
        OBJ_ID = NULL;
    END

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_UMK1_LIST (
    I$OBJ_ID BIGINT,
    I$SUBJECT_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    TYPE_ID BIGINT,
    CAPTION VARCHAR(1000),
    AUTHOR VARCHAR(1000),
    HAS_LINK SMALLINT)
AS
declare variable V$OBJ_ID bigint;
BEGIN
    TYPE_ID = 52;

    FOR SELECT DISTINCT L52.OBJ_ID, L.LINK_ID
        FROM OBJECT_CHILDREN_GET_DEEP(:I$SUBJECT_ID, 52) L52
        LEFT OUTER JOIN LINKS L ON L.PARENT_ID = :I$OBJ_ID AND L.OBJ_ID = L52.OBJ_ID AND L.DATE_DEL IS NULL
        WHERE L52.OBJ_ID IS NOT NULL
        INTO :OBJ_ID, :V$OBJ_ID
    DO
    BEGIN
        IF (V$OBJ_ID IS NULL) THEN
        BEGIN
            HAS_LINK = 0;
        END
        ELSE
        BEGIN
            HAS_LINK = 1;
        END

        SELECT V
        FROM VAL_GET(:OBJ_ID, 378, 0, :I$USER_ID)
        INTO :CAPTION;

        SELECT V
        FROM VAL_GET(:OBJ_ID, 379, 0, :I$USER_ID)
        INTO :AUTHOR;

        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_UMK2_LIST (
    I$OBJ_ID BIGINT,
    I$RES_TYPE SMALLINT = 1,
    I$USER_ID BIGINT = null)
RETURNS (
    OBJ_ID BIGINT,
    TYPE_ID BIGINT,
    SUBJECT VARCHAR(1000),
    GROUP_NAME VARCHAR(1000),
    CAPTION VARCHAR(1000),
    TOTAL VARCHAR(50),
    PUBLISHER VARCHAR(1000),
    AUTHOR VARCHAR(1000),
    PUBLIESHED_YEAR VARCHAR(20),
    HAS_LINK SMALLINT,
    IS_FPU VARCHAR(20),
    YEAR_REMOVE VARCHAR(10),
    SUBJECT_AREA VARCHAR(200),
    STUDENTS_NUM INTEGER)
AS
declare variable V$OBJ_ID bigint;
declare variable V$LISTVAL_ID bigint;
declare variable V$SCHOOL_ID bigint;
declare variable V$RES_TYPE bigint;
declare variable V$SUBJECT_ID bigint;
declare variable V$BOOK_SUBJ_ID bigint;
declare variable V$PARALLEL bigint;
declare variable GRADE_FROM smallint;
declare variable GRADE_TO smallint;
declare variable SAVED_SUBJECT bigint;
declare variable V$MATCH_SUBJ integer;
declare variable V$USED_QTY integer;
declare variable V$S varchar(100);
declare variable V$LIC char(1);
declare variable V$GRADE_ID bigint;
declare variable V$GRADE_FOLDER_ID bigint;
declare variable V$TYPE_ID bigint;
BEGIN
    V$RES_TYPE = 0;
    IF (I$RES_TYPE = 1) THEN V$RES_TYPE = 2097;
    ELSE IF (I$RES_TYPE = 2) THEN V$RES_TYPE = 2098;
    ELSE IF (I$RES_TYPE = 3) THEN V$RES_TYPE = 2099;

    SELECT STATUS
    FROM OU_LICENCE_TYPE
    INTO :V$LIC;

    -- Получаем код предмета или дисциплины. Сначала вариант для школ, затем пробуем вариант колледжей
    SELECT LP51.PARENT_ID
    FROM LINKS LP51
    WHERE LP51.PARENT_TYPE_ID = 51 AND LP51.OBJ_ID = :I$OBJ_ID AND LP51.DATE_DEL IS NULL
    INTO :V$SUBJECT_ID;

    IF(V$SUBJECT_ID IS NULL) THEN
    BEGIN
        SELECT V1766.VAL
        FROM LINKS LP203
        JOIN LINKS LP201 ON LP201.OBJ_ID = LP203.PARENT_ID AND LP201.PARENT_TYPE_ID = 201 AND LP201.DATE_DEL IS NULL
        JOIN VALR V1766 ON V1766.OBJ_ID = LP201.PARENT_ID AND V1766.PARAM_ID = 1766 AND V1766.IS_DEL = 0
        WHERE LP203.PARENT_TYPE_ID = 203 AND LP203.OBJ_ID = :I$OBJ_ID AND LP203.DATE_DEL IS NULL
        INTO :V$SUBJECT_ID;
    END

    -- Получаем номер параллели, и приводим ее к виду 0..12
    -- Для колледжей тут будет NULL, и проверки параллелей срабатывать не будут
    SELECT VL.LISTVAL_ID
    FROM LINKS LP54
    JOIN VALL VL ON VL.OBJ_ID = LP54.PARENT_ID AND VL.PARAM_ID = 381 and VL.IS_DEL = 0
    WHERE LP54.PARENT_TYPE_ID = 54 AND LP54.OBJ_ID = :I$OBJ_ID AND LP54.DATE_DEL IS NULL
    INTO :V$PARALLEL;

    IF(V$PARALLEL IS NOT NULL) then
    BEGIN
        IF(V$PARALLEL = 12765) THEN V$PARALLEL = 0; ELSE IF((V$PARALLEL >= 37) AND (V$PARALLEL <= 48)) THEN V$PARALLEL = V$PARALLEL - 36;
    END

    -- Получаем ID контейнера уровня обучения для колледжей
    IF(V$LIC = 'C') THEN
    BEGIN
        -- Код уровня
        SELECT V1776.LISTVAL_ID
        FROM VALL V1776
        WHERE V1776.OBJ_ID = :I$OBJ_ID AND V1776.PARAM_ID = 1776 AND V1776.IS_DEL = 0
        INTO :V$GRADE_ID;

        -- Поднимаемся по дереву, пока не дойдем до учебного плана
        V$GRADE_FOLDER_ID = I$OBJ_ID;
        V$TYPE_ID = 205;
        WHILE(V$TYPE_ID IS NOT NULL AND V$TYPE_ID <> 50) DO
        BEGIN
            V$TYPE_ID = NULL;
            SELECT LP.PARENT_TYPE_ID, LP.PARENT_ID
            FROM LINKS LP
            WHERE LP.OBJ_ID = :V$GRADE_FOLDER_ID AND LP.PARENT_TYPE_ID IN (203, 201, 185, 50) AND LP.DATE_DEL IS NULL
            INTO :V$TYPE_ID, :V$GRADE_FOLDER_ID;
        END

        V$TYPE_ID = NULL;
        SELECT FIRST 1 L54.OBJ_TYPE_ID, L54.OBJ_ID
        FROM LINKS L54
        JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0 AND V381.LISTVAL_ID = :V$GRADE_ID
        WHERE L54.PARENT_ID = :V$GRADE_FOLDER_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
        INTO :V$TYPE_ID, :V$GRADE_FOLDER_ID;
        IF(V$TYPE_ID IS NULL) THEN V$GRADE_FOLDER_ID = NULL;
    END
    ELSE
    BEGIN
        -- Школы
        SELECT LP54.PARENT_ID
        FROM LINKS LP54
        WHERE LP54.OBJ_ID = :I$OBJ_ID AND LP54.PARENT_TYPE_ID = 54 AND LP54.DATE_DEL IS NULL
        INTO :V$GRADE_FOLDER_ID;
    END

    TYPE_ID = 107;
    FOR
        SELECT FIRST 1 OBJ_ID
        FROM OBJECT_PARENTS_GET(:I$OBJ_ID, 2)
        INTO :V$SCHOOL_ID
    DO
    BEGIN
        FOR
            SELECT DISTINCT L107.OBJ_ID, L.LINK_ID, COALESCE(L.COST, 0)
            FROM LINKS L105
            JOIN LINKS L107 ON L107.PARENT_ID = L105.OBJ_ID AND L107.OBJ_TYPE_ID = 107 AND L107.DATE_DEL IS NULL
            LEFT JOIN LINKS L ON L.PARENT_ID = :I$OBJ_ID AND L.OBJ_ID = L107.OBJ_ID AND L.DATE_DEL IS NULL
            WHERE L105.PARENT_ID = :V$SCHOOL_ID AND L105.OBJ_TYPE_ID = 105 AND L105.DATE_DEL IS NULL
            INTO :OBJ_ID, :V$OBJ_ID, :HAS_LINK
        DO
        BEGIN
            SELECT I
            FROM VAL_GET(:OBJ_ID, 653, 0, :I$USER_ID)
            INTO :V$LISTVAL_ID;

            IF (V$LISTVAL_ID = V$RES_TYPE) THEN
            BEGIN
                IF(I$RES_TYPE < 3) THEN
                BEGIN
                    IF(V$OBJ_ID IS NULL) THEN HAS_LINK = 0; ELSE HAS_LINK = 1;
                END

                SELECT V FROM VAL_GET(:OBJ_ID, 654, 0, :I$USER_ID) INTO :SUBJECT;
                SELECT V FROM VAL_GET(:OBJ_ID, 646, 0, :I$USER_ID) INTO :GROUP_NAME;
                SELECT V FROM VAL_GET(:OBJ_ID, 647, 0, :I$USER_ID) INTO :CAPTION;
                SELECT V FROM VAL_GET(:OBJ_ID, 648, 0, :I$USER_ID) INTO :TOTAL;
                SELECT V FROM VAL_GET(:OBJ_ID, 651, 0, :I$USER_ID) INTO :PUBLISHER;
                SELECT V FROM VAL_GET(:OBJ_ID, 652, 0, :I$USER_ID) INTO :AUTHOR;
                SELECT V FROM VAL_GET(:OBJ_ID, 650, 0, :I$USER_ID) INTO :PUBLIESHED_YEAR;

                SELECT V FROM VAL_GET(:OBJ_ID, 2819, 0, :I$USER_ID) INTO :V$S;
                IF(V$S IS NULL OR V$S = '') THEN GRADE_FROM = 0; ELSE GRADE_FROM = CAST(V$S AS INTEGER);

                SELECT V FROM VAL_GET(:OBJ_ID, 2820, 0, :I$USER_ID) INTO :V$S;
                IF(V$S IS NULL OR V$S = '') THEN GRADE_TO = 0; ELSE GRADE_TO = CAST(V$S AS INTEGER);

                /* Выборки в части ФПУ */
                SELECT V FROM VAL_GET(:OBJ_ID, 2663, 0, :I$USER_ID) INTO :IS_FPU;
                SELECT V FROM VAL_GET(:OBJ_ID, 2656, 0, :I$USER_ID) INTO :YEAR_REMOVE;
                SELECT V FROM VAL_GET(:OBJ_ID, 2659, 0, :I$USER_ID) INTO :SUBJECT_AREA;
                IF(IS_FPU = '') THEN
                BEGIN
                    IF(SUBJECT_AREA IS NULL) THEN IS_FPU = 'нет'; ELSE IS_FPU = 'да';
                END

                -- Проверяем на номер параллели - только для ФПУ
                SAVED_SUBJECT = V$SUBJECT_ID;

                IF((GRADE_FROM IS NOT NULL) AND (GRADE_TO IS NOT NULL)) THEN
                BEGIN
                    -- Портим код предмета, чтобы не выводить неправильные параллели - будет работать только в школах
                    IF((V$PARALLEL < GRADE_FROM) OR (V$PARALLEL > GRADE_TO)) THEN SAVED_SUBJECT = 999999;
                END

                -- Проверяем, соответствует ли выбранный учебник предмету
                SELECT I FROM VAL_GET(:OBJ_ID, 654, 0, :I$USER_ID) INTO :V$BOOK_SUBJ_ID;

                /* Разрешаем соответствие, если учебники относятся к одной предметной области (Параграф) */
                /* Сверку предметных областей разрешаем только для иностранных языков и математики */
                V$MATCH_SUBJ = 0;

                /*SELECT COUNT(*)
                FROM LINKS L302A
                JOIN VALL V2462A ON V2462A.OBJ_ID = L302A.OBJ_ID AND V2462A.PARAM_ID = 2462 AND V2462A.IS_DEL = 0
                    AND V2462A.LISTVAL_ID IN (11684, 11685)
                JOIN LINKS L302B ON L302B.PARENT_ID = :V$BOOK_SUBJ_ID AND L302B.OBJ_TYPE_ID = 302 AND L302B.DATE_DEL IS NULL
                JOIN VALL V2462B ON V2462B.OBJ_ID = L302B.OBJ_ID AND V2462B.PARAM_ID = 2462 AND V2462B.IS_DEL = 0
                    AND V2462B.LISTVAL_ID = V2462A.LISTVAL_ID
                WHERE L302A.PARENT_ID = :SAVED_SUBJECT AND L302A.OBJ_TYPE_ID = 302 AND L302A.DATE_DEL IS NULL
                INTO V$MATCH_SUBJ;*/

                IF(SAVED_SUBJECT = V$BOOK_SUBJ_ID) THEN V$MATCH_SUBJ = V$MATCH_SUBJ + 1;

                IF(V$MATCH_SUBJ > 0) THEN BEGIN

                    /* Количество учащихся в параллели по данному УП */
                    /* Связка учеников с ГУП: -> этап (54) -> группа (46 / 256) -> ученик (10) */
                    /* Связка учеников с ГУП: -> этап (54) -> потоки (346) -> поток (347) -> ученик (10) */
                    SELECT COUNT(DISTINCT OBJ_ID) FROM
                    (
                    SELECT L10.OBJ_ID
                    FROM LINKS LG
                    JOIN LINKS L10 ON L10.PARENT_ID = LG.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
                    WHERE LG.PARENT_ID = :V$GRADE_FOLDER_ID AND LG.OBJ_TYPE_ID IN (46, 256) AND LG.DATE_DEL IS NULL
                      AND NOT EXISTS(  -- не учитываем предметы вынесенные в потоки
                        SELECT FIRST 1 1
                        FROM LINKS L346
                        JOIN VALR V2705 ON V2705.OBJ_ID = L346.OBJ_ID AND V2705.PARAM_ID = 2705 AND V2705.IS_DEL = 0 AND V2705.VAL = :V$SUBJECT_ID -- Предмет
                        WHERE L346.PARENT_ID = :V$GRADE_FOLDER_ID AND L346.OBJ_TYPE_ID = 346 AND L346.DATE_DEL IS NULL)

                    UNION

                    SELECT L10.OBJ_ID
                    FROM LINKS L346
                    JOIN LINKS L347 ON L347.PARENT_ID = L346.OBJ_ID AND L347.OBJ_TYPE_ID = 347 AND L347.DATE_DEL IS NULL
                    JOIN VALR V2705 ON V2705.OBJ_ID = L346.OBJ_ID AND V2705.PARAM_ID = 2705 AND V2705.IS_DEL = 0 AND V2705.VAL = :V$SUBJECT_ID -- Предмет
                    JOIN LINKS L10 ON L10.PARENT_ID = L347.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
                    WHERE L346.PARENT_ID = :V$GRADE_FOLDER_ID AND L346.OBJ_TYPE_ID = 346 AND L346.DATE_DEL IS NULL
                    )
                    INTO :STUDENTS_NUM;


                    /* Корректируем количество учебников с учетом других УП и параллелей */
                    IF(V$LIC = 'C') THEN
                    BEGIN
                    END
                    ELSE
                    BEGIN
                        SELECT SUM(COALESCE(L107.COST, 0))
                        FROM LINKS L107
                        /* Исключаем удаленные учебники */
                        JOIN LINKS L105 ON L105.PARENT_TYPE_ID = 105 AND L105.OBJ_ID = L107.OBJ_ID AND L105.DATE_DEL IS NULL
                        /* Исключаем обнуленные часы по УП */
                        JOIN VALI V385 ON V385.OBJ_ID = L107.PARENT_ID AND V385.PARAM_ID = 385 AND V385.IS_DEL = 0 AND V385.VAL > 0
                        /* Исключаем криво удаленные предметы из УП с назначенными часами */
                        JOIN LINKS L51 ON L51.OBJ_ID = L107.PARENT_ID AND L51.PARENT_TYPE_ID = 51 AND L51.DATE_DEL IS NULL
                        JOIN LINKS L49 ON L49.OBJ_ID = L51.OBJ_ID AND L49.PARENT_TYPE_ID = 49 AND L49.DATE_DEL IS NULL
                        JOIN LINKS L54 ON L54.OBJ_ID = L51.OBJ_ID AND L54.PARENT_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
                        WHERE L107.OBJ_ID = :OBJ_ID AND L107.PARENT_TYPE_ID IN (56, 205) AND L107.PARENT_ID <> :I$OBJ_ID AND L107.DATE_DEL IS NULL
                        INTO :V$USED_QTY;
                    END

                    IF(V$USED_QTY IS NULL) THEN V$USED_QTY = 0;
                    TOTAL = IIF(TOTAL <> '', CAST(TOTAL AS INTEGER), 0) - V$USED_QTY;

                    SUSPEND;

                END

            END
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_UMK3_LIST (
    I$OBJ_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    TYPE_ID BIGINT,
    SUBJECT VARCHAR(1000),
    GROUP_NAME VARCHAR(1000),
    CAPTION VARCHAR(1000),
    TOTAL VARCHAR(50),
    SUBGROUP_NAME VARCHAR(1000),
    AUTHOR VARCHAR(1000),
    PUBLIESHED_YEAR VARCHAR(20),
    HAS_LINK SMALLINT)
AS
declare variable V$OBJ_ID bigint;
declare variable V$SCHOOL_ID bigint;
BEGIN
    TYPE_ID = 106;
    FOR
        SELECT FIRST 1
               OBJ_ID
        FROM OBJECT_PARENTS_GET(:I$OBJ_ID,2)
        INTO :V$SCHOOL_ID
    DO
    BEGIN
        FOR
            SELECT DISTINCT
                   L106.OBJ_ID,
                   L.LINK_ID
            FROM LINKS L104
            INNER JOIN LINKS L106
            ON L106.PARENT_ID = L104.OBJ_ID
            AND L106.OBJ_TYPE_ID = 106
            AND L106.DATE_DEL IS NULL
            LEFT OUTER JOIN LINKS L
            ON L.PARENT_ID = :I$OBJ_ID
            AND L.OBJ_ID = L106.OBJ_ID
            AND L.DATE_DEL IS NULL
            WHERE L104.PARENT_ID = :V$SCHOOL_ID
            AND L104.OBJ_TYPE_ID = 104
            AND L104.DATE_DEL IS NULL
            INTO :OBJ_ID,
                 :V$OBJ_ID
        DO
        BEGIN
            IF (V$OBJ_ID IS NULL) THEN
            BEGIN
                HAS_LINK = 0;
            END
            ELSE
            BEGIN
                HAS_LINK = 1;
            END

            SELECT V
            FROM VAL_GET(:OBJ_ID,644,0,:I$USER_ID)
            INTO :SUBJECT;

            SELECT V
            FROM VAL_GET(:OBJ_ID,637,0,:I$USER_ID)
            INTO :GROUP_NAME;

            SELECT V
            FROM VAL_GET(:OBJ_ID,639,0,:I$USER_ID)
            INTO :CAPTION;

            SELECT V
            FROM VAL_GET(:OBJ_ID,640,0,:I$USER_ID)
            INTO :TOTAL;

            SELECT V
            FROM VAL_GET(:OBJ_ID,641,0,:I$USER_ID)
            INTO :AUTHOR;

            SELECT V
            FROM VAL_GET(:OBJ_ID,638,0,:I$USER_ID)
            INTO :SUBGROUP_NAME;

            SELECT V
            FROM VAL_GET(:OBJ_ID,642,0,:I$USER_ID)
            INTO :PUBLIESHED_YEAR;

            SUSPEND;
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_VACANCY_LIST (
    I$USER_ID BIGINT = 1)
RETURNS (
    OBJ_ID BIGINT,
    OBJ_CAPTION VARCHAR(4000))
AS
declare variable V$SCHOOL_ID bigint;
BEGIN
    SELECT FIRST 1
           L.OBJ_ID

    FROM LINKS L

    WHERE L.PARENT_ID IS NULL
    AND L.OBJ_TYPE_ID = 2
    AND L.DATE_DEL IS NULL

    INTO :V$SCHOOL_ID;

    FOR
        SELECT L.OBJ_ID,
               PC.CAPTION

        FROM LINKS L

        LEFT JOIN OBJECT_CAPTION_GET(L.OBJ_ID,NULL,NULL,:I$USER_ID) PC
        ON 1=1

        WHERE L.PARENT_ID IN (
            SELECT OBJ_ID
            FROM LINKS L
            WHERE L.PARENT_ID = :V$SCHOOL_ID
            AND L.DATE_DEL IS NULL
            AND L.OBJ_TYPE_ID = 211

            UNION ALL

            SELECT :V$SCHOOL_ID
            FROM RDB$DATABASE
        )
        AND L.OBJ_TYPE_ID = 13
        AND L.DATE_DEL IS NULL

        INTO :OBJ_ID,
             :OBJ_CAPTION
    DO
    BEGIN
        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_VACANCY_LIST2 (
    I$SCHOOL_ID BIGINT,
    I$EMPLOYEE_ID BIGINT = NULL,
    I$USER_ID BIGINT = NULL)
RETURNS (
    ID BIGINT,
    PARENT_ID BIGINT,
    OBJ_ID BIGINT,
    OBJ_CAPTION VARCHAR(4000),
    COLUMN1 NUMERIC(18,5),
    COLUMN2 VARCHAR(100),
    T DOUBLE PRECISION,
    TFREE DOUBLE PRECISION)
AS
DECLARE VARIABLE V$RATE_COUNT FLOAT;
DECLARE VARIABLE V$RC FLOAT;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$LEAVEDATE DATE;
DECLARE VARIABLE V$EMPLOYEE_ID BIGINT;
DECLARE VARIABLE V$EMPLOYEE_STATUS BIGINT;
DECLARE VARIABLE V$STAVKA_STATUS BIGINT;
DECLARE VARIABLE V$TYPE_ID BIGINT;
DECLARE VARIABLE V$OU_LICENCE_TYPE VARCHAR(1);
DECLARE VARIABLE V$RATE_FREE_MAIN FLOAT;
DECLARE VARIABLE V$RATE_FREE_TEMP FLOAT;
DECLARE VARIABLE V$RATE_USED_MAIN FLOAT;
DECLARE VARIABLE V$RATE_USED_TEMP FLOAT;
BEGIN
    SELECT STATUS FROM OU_LICENCE_TYPE INTO :V$OU_LICENCE_TYPE;

    PARENT_ID = NULL;

    FOR
      SELECT TYPE_ID
      FROM OBJECTS
      WHERE OBJ_ID = :I$SCHOOL_ID
      INTO :V$TYPE_ID
    DO
    BEGIN
      IF (V$TYPE_ID <> 2) THEN
      BEGIN
        SELECT FIRST 1 OBJ_ID
        FROM OBJECT_PARENTS_GET(:I$SCHOOL_ID, 2)
        INTO :I$SCHOOL_ID;
      END
    END

    ID = 1;

    FOR
        -- Цикл по всем должностям школы (+район)
        SELECT L.OBJ_ID, F.VAL, CASE WHEN PC.CAPTION IS NULL THEN V.VAL ELSE PC.CAPTION || ' / ' || V.VAL END
        FROM LINKS L
        JOIN VALF F ON F.OBJ_ID = L.OBJ_ID AND F.PARAM_ID = 62 AND F.IS_DEL = 0 AND F.VAL > 0
        JOIN VALS V ON V.OBJ_ID = L.OBJ_ID AND V.PARAM_ID = 66 AND V.IS_DEL = 0
        JOIN VALL S ON S.OBJ_ID = L.OBJ_ID AND S.PARAM_ID = 58 AND S.IS_DEL = 0
        JOIN LISTVALS LV ON LV.LISTVAL_ID = S.LISTVAL_ID AND ((:V$OU_LICENCE_TYPE IN ('D','U')) OR (LV.TAG <> 'U') OR (LV.LISTVAL_ID <> 121))
        LEFT JOIN OBJECT_CAPTION_GET(L.PARENT_ID, NULL, NULL, :I$USER_ID) PC ON :V$OU_LICENCE_TYPE='U' AND L.PARENT_ID != :I$SCHOOL_ID
        WHERE L.PARENT_ID IN (
            SELECT OBJ_ID
            FROM LINKS L
            WHERE L.PARENT_ID = :I$SCHOOL_ID AND L.DATE_DEL IS NULL AND L.OBJ_TYPE_ID = 211
            UNION ALL
            SELECT :I$SCHOOL_ID FROM RDB$DATABASE
        )
        AND L.OBJ_TYPE_ID = 13 AND L.DATE_DEL IS NULL
        ORDER BY LV.SORT_ORDER
        INTO :OBJ_ID, :V$RATE_COUNT, :OBJ_CAPTION /* Должность, кол-во ставок, наименование должности */
    DO
    BEGIN
        -- 19.06.2017
        V$RATE_USED_MAIN = 0;
        V$RATE_USED_TEMP = 0;
        V$RATE_FREE_MAIN = 0;
        V$RATE_FREE_TEMP = 0;

        FOR
            SELECT L15.OBJ_ID, LP14.PARENT_ID
            FROM LINKS L15 /* Прием на должность */
            JOIN LINKS LP14 ON LP14.OBJ_ID = L15.OBJ_ID AND LP14.PARENT_TYPE_ID = 14 AND LP14.DATE_DEL IS NULL
            WHERE L15.PARENT_ID = :OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
            INTO :V$OBJ_ID, :V$EMPLOYEE_ID /* Прием на должность, сотрудник */
        DO
        BEGIN
            SELECT D FROM VAL_GET(:V$OBJ_ID, 74, 0, :I$USER_ID) INTO :V$LEAVEDATE; /* Дата увольнения */

            IF (V$LEAVEDATE IS NULL OR V$LEAVEDATE > CURRENT_DATE) THEN
            BEGIN
                SELECT I FROM VAL_GET(:V$EMPLOYEE_ID, 274, 0, :I$USER_ID) INTO V$EMPLOYEE_STATUS;/* Статус сотрудника */
                SELECT F FROM VAL_GET(:V$OBJ_ID, 71, 0, :I$USER_ID) INTO :V$RC; /* Кол-во занятых ставок */
                SELECT I FROM VAL_GET(:V$OBJ_ID, 587, 0, :I$USER_ID) INTO :V$STAVKA_STATUS;/* Статус ставки */

                /* Подсчитываем только по действующим сотрудникам */
                IF (V$EMPLOYEE_STATUS = 602) THEN
                BEGIN
                    /* Сотрудник работает в настоящее время */
                    IF (V$STAVKA_STATUS IN (1720, 12824)) THEN
                    BEGIN
                        /* Ставка на время отсутствия штатного сотрудника */
                        V$RATE_USED_TEMP = V$RATE_USED_TEMP + V$RC;
                    END
                    ELSE
                    BEGIN
                        /* Штатник, совместитель или почасовая оплата */
                        V$RATE_USED_MAIN = V$RATE_USED_MAIN + V$RC;
                    END
                END
                ELSE
                BEGIN
                    /* Сотрудник числится, но временно отсутствует */
                    -- 19.06.2017 - подсчитываем свободные вакансии раздельно по основным и временным
                    IF (V$STAVKA_STATUS IN (1720, 12824)) THEN V$RATE_FREE_TEMP = V$RATE_FREE_TEMP + V$RC;
                    ELSE V$RATE_FREE_MAIN = V$RATE_FREE_MAIN + V$RC;
                END
            END
        END

        -- Исправлено 19.06.2017 - количество свободных вакансий
        -- Работащие сотрудники на основных ставках - уменьшают свободные ставки
        -- Работающие заместители - уменьшают свободные ставки
        -- Неработающие сотрудники на основных ставках - не меняют свободные ставки
        -- Неработающие заместители - не меняют свободные ставки
        COLUMN1 = V$RATE_COUNT - V$RATE_USED_MAIN - V$RATE_FREE_MAIN;
        IF (COLUMN1 > 0) THEN
        BEGIN
            COLUMN2 = 'свободная';
            SUSPEND;
            ID = ID + 1;
        END

        -- Количество временно свободных вакансий
        COLUMN1 = V$RATE_FREE_MAIN - V$RATE_USED_TEMP;
        IF (COLUMN1 > 0) THEN
        BEGIN
            COLUMN2 = 'временно св.';
            SUSPEND;
            ID = ID + 1;
        END

    END

    /* Учительские должности */

    IF (V$OU_LICENCE_TYPE IN ('O', 'C')) THEN
    BEGIN
        V$RATE_COUNT = 0;

        -- Общее количество учительских ставок
        SELECT F
        FROM VAL_GET(:I$SCHOOL_ID, 1342, 0, :I$USER_ID)
        INTO :V$RATE_COUNT;

        V$RATE_USED_MAIN = 0;
        V$RATE_USED_TEMP = 0;
        V$RATE_FREE_MAIN = 0;
        V$RATE_FREE_TEMP = 0;
    
        FOR
            -- Цикл по всем учительским должностям
            SELECT L.OBJ_ID
            FROM LINKS L
            JOIN VALL S ON S.OBJ_ID = L.OBJ_ID AND S.PARAM_ID = 58 AND S.IS_DEL = 0
            JOIN LISTVALS LV ON LV.LISTVAL_ID = S.LISTVAL_ID AND LV.TAG = 'U' AND LV.LISTVAL_ID <> 121
            WHERE L.PARENT_ID = :I$SCHOOL_ID AND L.OBJ_TYPE_ID = 13 AND L.DATE_DEL IS NULL
            INTO :OBJ_ID
        DO
        BEGIN
            FOR
                -- Цикл по сотрудникам, принятым на данную должность
                SELECT L.OBJ_ID, L2.PARENT_ID
                FROM LINKS L
                JOIN LINKS L2 ON L2.OBJ_ID = L.OBJ_ID AND L2.PARENT_TYPE_ID = 14 AND L2.DATE_DEL IS NULL
                WHERE L.PARENT_ID = :OBJ_ID AND L.OBJ_TYPE_ID = 15 AND L.DATE_DEL IS NULL
                INTO :V$OBJ_ID, :V$EMPLOYEE_ID
            DO
            BEGIN
                SELECT D FROM VAL_GET(:V$OBJ_ID, 74, 0, :I$USER_ID) INTO :V$LEAVEDATE; /* DATA UVOLNENIYA */
    
                IF (V$LEAVEDATE IS NULL OR V$LEAVEDATE > CURRENT_DATE) THEN
                BEGIN
                    SELECT I FROM VAL_GET(:V$EMPLOYEE_ID, 274, 0, :I$USER_ID) INTO V$EMPLOYEE_STATUS; /* Статус сотрудника */
                    SELECT F FROM VAL_GET(:V$OBJ_ID, 71, 0, :I$USER_ID) INTO :V$RC; /* Количество занятых ставок */
                    SELECT I FROM VAL_GET(:V$OBJ_ID, 587, 0, :I$USER_ID) INTO :V$STAVKA_STATUS; /* Статус ставки */
    
                    IF (V$EMPLOYEE_STATUS = 602) THEN
                    BEGIN
                        /* Сотрудник работает в настоящее время */
                        IF (V$STAVKA_STATUS IN (1720, 12824)) THEN
                        BEGIN
                            /* Ставка на время отсутствия штатного сотрудника */
                            V$RATE_USED_TEMP = V$RATE_USED_TEMP + V$RC;
                        END
                        ELSE
                        BEGIN
                            /* Штатник, совместитель или почасовая оплата */
                            V$RATE_USED_MAIN = V$RATE_USED_MAIN + V$RC;
                        END
                    END
                    ELSE
                    BEGIN
                        /* Сотрудник числится, но временно отсутствует */
                        -- 19.06.2017 - подсчитываем свободные вакансии раздельно по основным и временным
                        IF (V$STAVKA_STATUS IN (1720, 12824)) THEN V$RATE_FREE_TEMP = V$RATE_FREE_TEMP + V$RC;
                        ELSE V$RATE_FREE_MAIN = V$RATE_FREE_MAIN + V$RC;
                    END
                END
            END
        END

        IF (V$OU_LICENCE_TYPE IN ('U', 'C')) THEN -- УДОД и Колледж
            OBJ_CAPTION = 'Преподаватель';
        ELSE
            OBJ_CAPTION = 'Учитель';

        COLUMN1 = V$RATE_COUNT - V$RATE_USED_MAIN - V$RATE_FREE_MAIN;
        IF (COLUMN1 > 0) THEN
        BEGIN
            COLUMN2 = 'свободная';
            SUSPEND;
            ID = ID + 1;
        END
    
        COLUMN1 = V$RATE_FREE_MAIN - V$RATE_USED_TEMP;
        IF (COLUMN1 > 0) THEN
        BEGIN
            COLUMN2 = 'временно св.';
            SUSPEND;
            ID = ID + 1;
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_VACANCY_LIST3 (
    I$SCHOOL_ID BIGINT,
    I$EMPLOYEE_ID BIGINT = NULL,
    I$USER_ID BIGINT = NULL,
    I$MOVEMENT_ID BIGINT = NULL)
RETURNS (
    ID BIGINT,
    PARENT_ID BIGINT,
    OBJ_ID BIGINT,
    OBJ_CAPTION VARCHAR(4000),
    COLUMN1 NUMERIC(15,2),
    COLUMN2 VARCHAR(100),
    CAT_ID BIGINT)
AS
DECLARE VARIABLE V$RATE_COUNT FLOAT;
DECLARE VARIABLE V$RC FLOAT;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$PARENT_ID BIGINT;
DECLARE VARIABLE V$LEAVEDATE DATE;
DECLARE VARIABLE V$EMPLOYEE_ID BIGINT;
DECLARE VARIABLE V$EMPLOYEE_STATUS BIGINT;
DECLARE VARIABLE V$STAVKA_STATUS BIGINT;
DECLARE VARIABLE V$TYPE_ID BIGINT;
DECLARE VARIABLE V$SELF_DOLJNOST SMALLINT;
DECLARE VARIABLE V$OU_LICENCE_TYPE VARCHAR(1);
DECLARE VARIABLE V$TYPE_DOLJNOST1 BIGINT;
DECLARE VARIABLE V$TYPE_DOLJNOST2 BIGINT;
DECLARE VARIABLE V$RATE_FREE_MAIN FLOAT;
DECLARE VARIABLE V$RATE_FREE_TEMP FLOAT;
DECLARE VARIABLE V$RATE_USED_MAIN FLOAT;
DECLARE VARIABLE V$RATE_USED_TEMP FLOAT;
DECLARE VARIABLE V$CURRENT_MATCH SMALLINT;
BEGIN

    -- Возможные комбинации передаваемых параметров:
    -- EMPLOYEE_ID = NULL, MOVEMENT_ID = NULL - прием на должность нового сотрудника
    -- EMPLOYEE_ID = *, MOVEMENT_ID = NULL - прием на новую должность действующего сотрудника
    -- EMPLOYEE_ID = *, MOVEMENT_ID = * - редактирование действующего назначения

    SELECT STATUS FROM OU_LICENCE_TYPE INTO :V$OU_LICENCE_TYPE;
    PARENT_ID = NULL;

    -- Вероятно тут может быть передано что-то еще кроме ID школы, в режиме отладки
    -- Восстанавливаем ID школы
    SELECT TYPE_ID
    FROM OBJECTS
    WHERE OBJ_ID = :I$SCHOOL_ID
    INTO :V$TYPE_ID;

    IF (V$TYPE_ID <> 2) THEN
    BEGIN
        SELECT FIRST 1 OBJ_ID FROM OBJECT_PARENTS_GET(:I$SCHOOL_ID, 2) INTO :I$SCHOOL_ID;
    END

    ID = 1;

    -- Список должностей
    -- Для Мультипараграфа выдаем все должности первым списком
    FOR
        -- Получаем также ID родителя (подразделение или ОООД), хотя нигде не применяется
        SELECT L13.OBJ_ID, L13.PARENT_ID, F.VAL, IIF(PC.CAPTION IS NULL, V.VAL, PC.CAPTION || ' / ' || V.VAL), S.LISTVAL_ID
        FROM LINKS L13
        JOIN VALF F ON F.OBJ_ID = L13.OBJ_ID AND F.PARAM_ID = 62 AND F.IS_DEL = 0 AND F.VAL > 0
        JOIN VALS V ON V.OBJ_ID = L13.OBJ_ID AND V.PARAM_ID = 66 AND V.IS_DEL = 0
        JOIN VALL S ON S.OBJ_ID = L13.OBJ_ID AND S.PARAM_ID = 58 AND S.IS_DEL = 0
        -- Все не-учительские должности для школы
        JOIN LISTVALS LV ON LV.LISTVAL_ID = S.LISTVAL_ID AND ((:V$OU_LICENCE_TYPE IN ('D', 'U', 'S')) OR LV.TAG <> 'U' OR LV.LISTVAL_ID = 121)
        -- Наименование подразделения
        LEFT JOIN OBJECT_CAPTION_GET(L13.PARENT_ID, NULL, NULL, :I$USER_ID) PC ON L13.PARENT_ID <> :I$SCHOOL_ID
        WHERE L13.OBJ_TYPE_ID = 13 AND L13.DATE_DEL IS NULL AND L13.PARENT_ID IN (
            -- Сама ОУ, а также подразделения первого уровня
            SELECT OBJ_ID
            FROM LINKS L
            WHERE L.PARENT_ID = :I$SCHOOL_ID AND L.DATE_DEL IS NULL AND L.OBJ_TYPE_ID = 211
            UNION ALL
            SELECT :I$SCHOOL_ID
            FROM RDB$DATABASE
        )
        ORDER BY LV.SORT_ORDER
        INTO :OBJ_ID, :V$PARENT_ID, :V$RATE_COUNT, :OBJ_CAPTION, :CAT_ID /* ID должности, ID родителя, кол-во ставок, наименование должности */
    DO
    BEGIN

        V$CURRENT_MATCH = 0;

        -- 19.06.2017
        V$RATE_USED_MAIN = 0;
        V$RATE_USED_TEMP = 0;
        V$RATE_FREE_MAIN = 0;
        V$RATE_FREE_TEMP = 0;

        FOR
            SELECT L15.OBJ_ID, LP14.PARENT_ID
            FROM LINKS L15 /* Прием на должность */
            JOIN LINKS LP14 ON LP14.OBJ_ID = L15.OBJ_ID AND LP14.PARENT_TYPE_ID = 14 AND LP14.DATE_DEL IS NULL
            WHERE L15.PARENT_ID = :OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
            INTO :V$OBJ_ID, :V$EMPLOYEE_ID /* Прием на должность, сотрудник */
        DO
        BEGIN
            SELECT D FROM VAL_GET(:V$OBJ_ID, 74, 0, :I$USER_ID) INTO :V$LEAVEDATE; /* Дата увольнения */

            IF(V$LEAVEDATE IS NULL AND V$OBJ_ID = I$MOVEMENT_ID) THEN V$CURRENT_MATCH = 1;

            -- Пропускаем из подсчета текущую ставку, если она указана (редактирование), чтобы она вообще показывалась в списке
            IF (V$LEAVEDATE IS NULL AND (V$OBJ_ID <> I$MOVEMENT_ID OR I$MOVEMENT_ID IS NULL)) THEN
            BEGIN
                SELECT I FROM VAL_GET(:V$EMPLOYEE_ID, 274, 0, :I$USER_ID) INTO V$EMPLOYEE_STATUS; /* Статус сотрудника */
                SELECT F FROM VAL_GET(:V$OBJ_ID, 71, 0, :I$USER_ID) INTO :V$RC; /* Кол-во занятых ставок */
                SELECT I FROM VAL_GET(:V$OBJ_ID, 587, 0, :I$USER_ID) INTO :V$STAVKA_STATUS; /* Статус ставки */

                /* Подсчитываем только по действующим сотрудникам */
                IF (V$EMPLOYEE_STATUS = 602) THEN
                BEGIN
                    /* Сотрудник работает в настоящее время */
                    IF (V$STAVKA_STATUS IN (1720, 12824)) THEN
                    BEGIN
                        /* Ставка на время отсутствия штатного сотрудника */
                        V$RATE_USED_TEMP = V$RATE_USED_TEMP + V$RC;
                    END
                    ELSE
                    BEGIN
                        /* Штатник, совместитель или почасовая оплата */
                        V$RATE_USED_MAIN = V$RATE_USED_MAIN + V$RC;
                    END
                END
                ELSE
                BEGIN
                    /* Сотрудник числится, но временно отсутствует */
                    -- 19.06.2017 - подсчитываем свободные вакансии раздельно по основным и временным
                    IF (V$STAVKA_STATUS IN (1720, 12824)) THEN V$RATE_FREE_TEMP = V$RATE_FREE_TEMP + V$RC;
                    ELSE V$RATE_FREE_MAIN = V$RATE_FREE_MAIN + V$RC;
                END
            END
        END

        -- Исправлено 19.06.2017 - количество свободных вакансий
        -- Работащие сотрудники на основных ставках - уменьшают свободные ставки
        -- Работающие заместители - уменьшают свободные ставки
        -- Неработающие сотрудники на основных ставках - не меняют свободные ставки
        -- Неработающие заместители - не меняют свободные ставки
        COLUMN1 = V$RATE_COUNT - V$RATE_USED_MAIN - V$RATE_FREE_MAIN;
        IF (COLUMN1 > 0) THEN
        BEGIN
            COLUMN2 = 'свободная';
            IF(V$CURRENT_MATCH = 1) THEN COLUMN2 = COLUMN2 || '*';
            SUSPEND;
            ID = ID + 1;
        END

        -- Количество временно свободных вакансий
        COLUMN1 = V$RATE_FREE_MAIN - V$RATE_USED_TEMP;
        IF (COLUMN1 > 0) THEN
        BEGIN
            COLUMN2 = 'временно св.';
            IF(V$CURRENT_MATCH = 1) THEN COLUMN2 = COLUMN2 || '*';
            SUSPEND;
            ID = ID + 1;
        END

    END

    -- Учительские должности - только непосредственно в ОУ
    -- Мультипараграф эту выборку уже не использует
    IF (V$OU_LICENCE_TYPE IN ('O', 'C', 'P')) THEN
    BEGIN
        CAT_ID = NULL;
        V$RATE_COUNT = 0;
        V$CURRENT_MATCH = 0;

        -- Общее количество учительских ставок
        SELECT F FROM VAL_GET(:I$SCHOOL_ID, 1342, 0, :I$USER_ID) INTO :V$RATE_COUNT;

        V$RATE_USED_MAIN = 0;
        V$RATE_USED_TEMP = 0;
        V$RATE_FREE_MAIN = 0;
        V$RATE_FREE_TEMP = 0;
    
        FOR
            -- Цикл по всем учительским должностям
            SELECT L.OBJ_ID
            FROM LINKS L
            JOIN VALL S ON S.OBJ_ID = L.OBJ_ID AND S.PARAM_ID = 58 AND S.IS_DEL = 0
            JOIN LISTVALS LV ON LV.LISTVAL_ID = S.LISTVAL_ID AND LV.TAG = 'U' AND LV.LISTVAL_ID <> 121
            WHERE L.PARENT_ID = :I$SCHOOL_ID AND L.OBJ_TYPE_ID = 13 AND L.DATE_DEL IS NULL
            INTO :OBJ_ID
        DO
        BEGIN
            FOR
                -- Цикл по сотрудникам, принятым на данную должность
                SELECT L.OBJ_ID, L2.PARENT_ID
                FROM LINKS L
                JOIN LINKS L2 ON L2.OBJ_ID = L.OBJ_ID  AND L2.PARENT_TYPE_ID = 14 AND L2.DATE_DEL IS NULL
                WHERE L.PARENT_ID = :OBJ_ID AND L.OBJ_TYPE_ID = 15 AND L.DATE_DEL IS NULL
                INTO :V$OBJ_ID, :V$EMPLOYEE_ID
            DO
            BEGIN
                SELECT D FROM VAL_GET(:V$OBJ_ID, 74, 0, :I$USER_ID) INTO :V$LEAVEDATE; /* Дата увольнения */

                IF(V$LEAVEDATE IS NULL AND V$OBJ_ID = I$MOVEMENT_ID) THEN V$CURRENT_MATCH = 1;
    
                IF (V$LEAVEDATE IS NULL AND (V$OBJ_ID <> I$MOVEMENT_ID OR I$MOVEMENT_ID IS NULL)) THEN
                BEGIN
                    SELECT I FROM VAL_GET(:V$EMPLOYEE_ID, 274, 0, :I$USER_ID) INTO V$EMPLOYEE_STATUS; /* Статус сотрудника */
                    SELECT F FROM VAL_GET(:V$OBJ_ID, 71, 0, :I$USER_ID) INTO :V$RC; /* Количество занятых ставок */
                    SELECT I FROM VAL_GET(:V$OBJ_ID, 587, 0, :I$USER_ID) INTO :V$STAVKA_STATUS; /* Статус ставки */

                    IF (V$EMPLOYEE_STATUS = 602) THEN
                    BEGIN
                        /* Сотрудник работает в настоящее время */
                        IF (V$STAVKA_STATUS IN (1720, 12824)) THEN
                        BEGIN
                            /* Ставка на время отсутствия штатного сотрудника */
                            V$RATE_USED_TEMP = V$RATE_USED_TEMP + V$RC;
                        END
                        ELSE
                        BEGIN
                            /* Штатник, совместитель или почасовая оплата */
                            V$RATE_USED_MAIN = V$RATE_USED_MAIN + V$RC;
                        END
                    END
                    ELSE
                    BEGIN
                        /* Сотрудник числится, но временно отсутствует */
                        -- 19.06.2017 - подсчитываем свободные вакансии раздельно по основным и временным
                        IF (V$STAVKA_STATUS IN (1720, 12824)) THEN V$RATE_FREE_TEMP = V$RATE_FREE_TEMP + V$RC;
                        ELSE V$RATE_FREE_MAIN = V$RATE_FREE_MAIN + V$RC;
                    END
                END
            END
        END
    
        -- Также исключаем ставки, занятые сотрудником
    
        FOR
            SELECT L.OBJ_ID, V.VAL
            FROM LINKS L
            JOIN VALS V ON V.OBJ_ID = L.OBJ_ID AND V.PARAM_ID = 66 AND V.IS_DEL = 0
            JOIN VALL S ON S.OBJ_ID = L.OBJ_ID AND S.PARAM_ID = 58 AND S.IS_DEL = 0
            JOIN LISTVALS LV ON LV.LISTVAL_ID = S.LISTVAL_ID AND LV.TAG = 'U' AND LV.LISTVAL_ID <> 121
            WHERE L.PARENT_ID = :I$SCHOOL_ID AND L.OBJ_TYPE_ID = 13 AND L.DATE_DEL IS NULL
            ORDER BY LV.SORT_ORDER
            INTO :OBJ_ID, :OBJ_CAPTION
        DO
        BEGIN
            V$SELF_DOLJNOST = 0;
            /* IF (I$EMPLOYEE_ID IS NOT NULL) THEN
            BEGIN
                V$TYPE_DOLJNOST1 = NULL;
                V$TYPE_DOLJNOST2 = NULL;
                FOR
                    SELECT L.OBJ_ID
                    FROM LINKS L
                    JOIN LINKS L2 ON L2.OBJ_ID = L.OBJ_ID AND L2.PARENT_ID = :OBJ_ID AND L2.OBJ_TYPE_ID = 15 AND L2.DATE_DEL IS NULL
                    WHERE L.PARENT_ID = :I$EMPLOYEE_ID AND L.OBJ_TYPE_ID = 15 AND L.DATE_DEL IS NULL
                    INTO :V$OBJ_ID
                DO
                BEGIN
                    SELECT D FROM VAL_GET(:V$OBJ_ID, 74, 0, :I$USER_ID) INTO :V$LEAVEDATE; -- Дата увольнения
    
                    IF (V$LEAVEDATE IS NULL) THEN
                    BEGIN
                        SELECT I FROM VAL_GET(:V$OBJ_ID, 72, 0, :I$USER_ID) INTO :V$TYPE_DOLJNOST1;
    
                        IF (:V$TYPE_DOLJNOST1 <> :V$TYPE_DOLJNOST2 AND :V$TYPE_DOLJNOST1 IS NOT NULL AND :V$TYPE_DOLJNOST2 IS NOT NULL) THEN
                        BEGIN
                            V$SELF_DOLJNOST = 1;
                        END
                        ELSE
                        BEGIN
                            V$TYPE_DOLJNOST2 = COALESCE(:V$TYPE_DOLJNOST1, :V$TYPE_DOLJNOST2);
                        END
                    END
                END
            END */
    
            IF (V$SELF_DOLJNOST = 0) THEN
            BEGIN
                COLUMN1 = V$RATE_COUNT - V$RATE_USED_MAIN - V$RATE_FREE_MAIN;
                IF (COLUMN1 > 0) THEN
                BEGIN
                    COLUMN2 = 'свободная';
                    IF(V$CURRENT_MATCH = 1) THEN COLUMN2 = COLUMN2 || '*';
                    SUSPEND;
                    ID = ID + 1;
                END
    
                COLUMN1 = V$RATE_FREE_MAIN - V$RATE_USED_TEMP;
                IF (COLUMN1 > 0) THEN
                BEGIN
                    COLUMN2 = 'временно св.';
                    IF(V$CURRENT_MATCH = 1) THEN COLUMN2 = COLUMN2 || '*';
                    SUSPEND;
                    ID = ID + 1;
                END
            END
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAGRAF_VACANCY_VERIFY (
    I$SCHOOL_ID BIGINT,
    I$EMPLOYEE_ID BIGINT,
    I$VACANCY_ID BIGINT,
    I$MOVEMENT_ID BIGINT,
    I$RATECOUNT DOUBLE PRECISION,
    I$ACCEPTCONDITION BIGINT)
AS
DECLARE VARIABLE V$TOTAL_VC FLOAT;
DECLARE VARIABLE V$USED_VC FLOAT;
DECLARE VARIABLE S VARCHAR(1000);
begin

  -- Если в должности задано количество ставок - сравниваем с ним
  IF(I$ACCEPTCONDITION IN (1720, 12824)) THEN
  BEGIN
    -- Хотим принять на временную занятость, общее количество ставок берем только из числа временно свободных, но не более общего !
    -- Количество сотрудников в отпусках
    SELECT SUM(V71.VAL)
    FROM LINKS L13_15
    JOIN LINKS L14_15 ON L14_15.PARENT_TYPE_ID = 14 AND L14_15.OBJ_ID = L13_15.OBJ_ID AND L14_15.DATE_DEL IS NULL AND (:I$MOVEMENT_ID IS NOT NULL OR :I$EMPLOYEE_ID IS NULL OR :I$EMPLOYEE_ID <> L14_15.PARENT_ID)
    JOIN VALF V71 ON V71.OBJ_ID = L13_15.OBJ_ID AND V71.PARAM_ID = 71 AND V71.IS_DEL = 0
    JOIN VALD V73 ON V73.OBJ_ID = L13_15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0 AND V73.VAL <= CURRENT_DATE
    JOIN VALL V274 ON V274.OBJ_ID = L14_15.PARENT_ID AND V274.PARAM_ID = 274 AND V274.IS_DEL = 0 AND V274.LISTVAL_ID <> 602 -- в разных видах отпусков
    JOIN VALL V587 ON V587.OBJ_ID = L13_15.OBJ_ID AND V587.PARAM_ID = 587 AND V587.IS_DEL = 0 AND V587.LISTVAL_ID NOT IN (1720, 12824) -- основная занятость
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L13_15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
    WHERE L13_15.PARENT_ID = :I$VACANCY_ID AND L13_15.OBJ_TYPE_ID = 15 AND L13_15.DATE_DEL IS NULL AND (:I$MOVEMENT_ID IS NULL OR L13_15.OBJ_ID <> :I$MOVEMENT_ID) AND (V74.VAL IS NULL OR V74.VAL > CURRENT_DATE)
    INTO :V$TOTAL_VC;
    IF(V$TOTAL_VC IS NULL) THEN V$TOTAL_VC = 0; -- всего в отпусках
    -- Занятые считаем по работающим сотрудникам на временной основе
    SELECT SUM(V71.VAL)
    FROM LINKS L13_15
    JOIN LINKS L14_15 ON L14_15.PARENT_TYPE_ID = 14 AND L14_15.OBJ_ID = L13_15.OBJ_ID AND L14_15.DATE_DEL IS NULL AND (:I$MOVEMENT_ID IS NOT NULL OR :I$EMPLOYEE_ID IS NULL OR :I$EMPLOYEE_ID <> L14_15.PARENT_ID)
    JOIN VALF V71 ON V71.OBJ_ID = L13_15.OBJ_ID AND V71.PARAM_ID = 71 AND V71.IS_DEL = 0
    JOIN VALD V73 ON V73.OBJ_ID = L13_15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0 AND V73.VAL <= CURRENT_DATE
    JOIN VALL V274 ON V274.OBJ_ID = L14_15.PARENT_ID AND V274.PARAM_ID = 274 AND V274.IS_DEL = 0 AND V274.LISTVAL_ID = 602 -- работает
    JOIN VALL V587 ON V587.OBJ_ID = L13_15.OBJ_ID AND V587.PARAM_ID = 587 AND V587.IS_DEL = 0 AND V587.LISTVAL_ID IN (1720, 12824) -- временная занятость
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L13_15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
    WHERE L13_15.PARENT_ID = :I$VACANCY_ID AND L13_15.OBJ_TYPE_ID = 15 AND L13_15.DATE_DEL IS NULL AND (:I$MOVEMENT_ID IS NULL OR L13_15.OBJ_ID <> :I$MOVEMENT_ID) AND (V74.VAL IS NULL OR V74.VAL > CURRENT_DATE)
    INTO :V$USED_VC;
  END
  ELSE
  BEGIN
    -- Хотим принять на постоянную занятость, в зачет берем только основные ставки вне зависимости от того, работает по ним сотрудник или нет
    -- Количество ставок
    SELECT SUM(V62.VAL)
    FROM VALF V62
    WHERE V62.OBJ_ID = :I$VACANCY_ID AND V62.PARAM_ID = 62 AND V62.IS_DEL = 0
    INTO :V$TOTAL_VC;
    SELECT SUM(V71.VAL)
    FROM LINKS L13_15
    JOIN LINKS L14_15 ON L14_15.PARENT_TYPE_ID = 14 AND L14_15.OBJ_ID = L13_15.OBJ_ID AND L14_15.DATE_DEL IS NULL AND (:I$MOVEMENT_ID IS NOT NULL OR :I$EMPLOYEE_ID IS NULL OR :I$EMPLOYEE_ID <> L14_15.PARENT_ID)
    JOIN VALF V71 ON V71.OBJ_ID = L13_15.OBJ_ID AND V71.PARAM_ID = 71 AND V71.IS_DEL = 0
    JOIN VALD V73 ON V73.OBJ_ID = L13_15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0 AND V73.VAL <= CURRENT_DATE
    JOIN VALL V587 ON V587.OBJ_ID = L13_15.OBJ_ID AND V587.PARAM_ID = 587 AND V587.IS_DEL = 0 AND V587.LISTVAL_ID NOT IN (1720, 12824) -- основная занятость
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L13_15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
    WHERE L13_15.PARENT_ID = :I$VACANCY_ID AND L13_15.OBJ_TYPE_ID = 15 AND L13_15.DATE_DEL IS NULL AND (:I$MOVEMENT_ID IS NULL OR L13_15.OBJ_ID <> :I$MOVEMENT_ID) AND (V74.VAL IS NULL OR V74.VAL > CURRENT_DATE)
    INTO :V$USED_VC;
  END
  IF(V$USED_VC IS NULL) THEN V$USED_VC = 0;

  IF(V$TOTAL_VC IS NOT NULL) THEN
  BEGIN
    -- Если в должности задано количество ставок - сравниваем с ним
    IF(V$USED_VC IS NULL) THEN V$USED_VC = 0;
    S = CAST(V$TOTAL_VC - V$USED_VC AS NUMERIC(18, 3));
    IF(V$USED_VC + I$RATECOUNT > V$TOTAL_VC + 0.01) THEN EXCEPTION DATA_ERROR 'Превышено количество ставок по должности (доступно ' || S || ')';
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAMS_LIST (
    I$TYPE_ID BIGINT,
    I$LANG_CODE VARCHAR(2) = 'RU')
RETURNS (
    PARAM_ID BIGINT,
    LANG_CODE VARCHAR(2),
    PARAM_CAPTION VARCHAR(4000),
    SIZE_CAPTION VARCHAR(1000),
    TYPE_ID BIGINT,
    PARAM_TYPE SMALLINT,
    VAL_TYPE VARCHAR(100),
    BKG_COLOR INTEGER,
    LIST_ID BIGINT,
    TAB_ID BIGINT,
    GRID_ORDER SMALLINT,
    IS_TREESORT SMALLINT,
    IS_TREEVIEW SMALLINT,
    IS_REQUIRED SMALLINT,
    IS_HISTORY SMALLINT,
    RES_ID BIGINT,
    SIZE_RES_ID BIGINT,
    HINT_RES_ID BIGINT,
    HINT_CAPTION VARCHAR(4000),
    DO_FUNC VARCHAR(100),
    EDIT_MASK VARCHAR(200),
    RUN_SQL VARCHAR(1000),
    IS_AUTO_CREATE SMALLINT,
    AUTO_RES_ID BIGINT,
    AUTO_CAPTION VARCHAR(4000),
    AUTO_LISTVAL_ID BIGINT,
    FOR_REPL_UP SMALLINT,
    FOR_REPL_DOWN SMALLINT,
    TAG VARCHAR(100),
    IS_DEL SMALLINT,
    IS_LINK_REFERENSE SMALLINT,
    LINK_REFERENSE_TYPE_ID BIGINT,
    DO_CHECK SMALLINT,
    DO_CHECK_EVENT SMALLINT,
    BEGIN_GROUP SMALLINT)
AS
BEGIN
    LANG_CODE = I$LANG_CODE;
    FOR
        SELECT P.PARAM_ID, P.TYPE_ID, P.PARAM_TYPE, P.LIST_ID, P.TAB_ID, P.GRID_ORDER, P.IS_TREESORT, P.IS_TREEVIEW, P.IS_REQUIRED, P.IS_HISTORY, P.RES_ID, P.SIZE_RES_ID,
               P.HINT_RES_ID, P.DO_FUNC, P.EDIT_MASK, P.RUN_SQL, P.IS_AUTO_CREATE, P.AUTO_RES_ID, P.AUTO_LISTVAL_ID, P.FOR_REPL_UP, P.FOR_REPL_DOWN, P.TAG, P.IS_DEL,
               P.IS_LINK_REFERENSE, P.LINK_REFERENSE_TYPE_ID, T.VAL_TYPE, T.BKG_COLOR, P.DO_CHECK, P.DO_CHECK_EVENT, P.BEGIN_GROUP
        FROM PARAMS P
        JOIN PARAMTYPES T ON T.PARAM_TYPE = P.PARAM_TYPE
        WHERE P.TYPE_ID = :I$TYPE_ID
        ORDER BY P.GRID_ORDER
        INTO :PARAM_ID, :TYPE_ID, :PARAM_TYPE, :LIST_ID, :TAB_ID, :GRID_ORDER, :IS_TREESORT, :IS_TREEVIEW, :IS_REQUIRED, :IS_HISTORY, :RES_ID, :SIZE_RES_ID, :HINT_RES_ID,
             :DO_FUNC, :EDIT_MASK, :RUN_SQL, :IS_AUTO_CREATE, :AUTO_RES_ID, :AUTO_LISTVAL_ID, :FOR_REPL_UP, :FOR_REPL_DOWN, :TAG, :IS_DEL, :IS_LINK_REFERENSE,
             :LINK_REFERENSE_TYPE_ID, :VAL_TYPE, :BKG_COLOR, :DO_CHECK, :DO_CHECK_EVENT, :BEGIN_GROUP
    DO
    BEGIN
        SELECT VAL
        FROM RES_GET(:RES_ID, :I$LANG_CODE)
        INTO :PARAM_CAPTION;

        SELECT VAL
        FROM RES_GET(:SIZE_RES_ID, :I$LANG_CODE)
        INTO :SIZE_CAPTION;

        SELECT VAL
        FROM RES_GET(:AUTO_RES_ID, :I$LANG_CODE)
        INTO :AUTO_CAPTION;

        SELECT VAL
        FROM RES_GET(:HINT_RES_ID, :I$LANG_CODE)
        INTO :HINT_CAPTION;

        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAMTYPES_LIST RETURNS (
    PARAM_TYPE SMALLINT,
    VAL_TYPE VARCHAR(100))
AS
BEGIN
   FOR SELECT PARAM_TYPE, VAL_TYPE
       FROM PARAMTYPES
       ORDER BY PARAM_TYPE
       INTO :PARAM_TYPE, :VAL_TYPE
   DO SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAM_ADD (
    I$PARAM_ID BIGINT,
    I$TYPE_ID BIGINT,
    I$PARAM_TYPE SMALLINT,
    I$LIST_ID BIGINT,
    I$AUTO_LISTVAL_ID BIGINT,
    I$TAB_ID BIGINT,
    I$IS_TREESORT SMALLINT,
    I$IS_TREEVIEW SMALLINT,
    I$IS_REQUIRED SMALLINT,
    I$IS_HISTORY SMALLINT,
    I$RES_ID BIGINT,
    I$HINT_RES_ID BIGINT,
    I$SIZE_RES_ID BIGINT,
    I$AUTO_RES_ID BIGINT,
    I$DO_FUNC VARCHAR(100),
    I$EDIT_MASK VARCHAR(200),
    I$RUN_SQL VARCHAR(1000),
    I$IS_AUTO_CREATE SMALLINT,
    I$FOR_REPL_UP SMALLINT,
    I$FOR_REPL_DOWN SMALLINT,
    I$TAG VARCHAR(100),
    I$LANG_CODE CHAR(2),
    I$PARAM_CAPTION VARCHAR(4000),
    I$HINT_CAPTION VARCHAR(4000),
    I$SIZE_CAPTION VARCHAR(1000),
    I$AUTO_CAPTION VARCHAR(4000),
    I$IS_DEL SMALLINT = 0,
    I$IS_LINK_REFERENSE SMALLINT = 0,
    I$LINK_REFERENSE_TYPE_ID BIGINT = null,
    I$DO_CHECK SMALLINT = 0,
    I$DO_CHECK_EVENT SMALLINT = 0,
    I$BEGIN_GROUP SMALLINT = 0)
RETURNS (
    PARAM_ID BIGINT,
    RES_ID BIGINT,
    HINT_RES_ID BIGINT,
    SIZE_RES_ID BIGINT,
    AUTO_RES_ID BIGINT)
AS
declare variable GRID_ORDER smallint;
BEGIN

    PARAM_ID = I$PARAM_ID;
    RES_ID = I$RES_ID;
    HINT_RES_ID = I$HINT_RES_ID;
    SIZE_RES_ID = I$SIZE_RES_ID;
    AUTO_RES_ID = I$AUTO_RES_ID;

    IF (I$PARAM_ID IS NULL) THEN
    BEGIN
        SELECT MAX(GRID_ORDER) + 1
        FROM PARAMS
        WHERE TYPE_ID = :I$TYPE_ID
        INTO :GRID_ORDER;

        IF (GRID_ORDER IS NULL) THEN GRID_ORDER = 1;

        INSERT INTO PARAMS
        (TYPE_ID, PARAM_TYPE, LIST_ID, AUTO_LISTVAL_ID, TAB_ID, GRID_ORDER, IS_TREESORT, IS_TREEVIEW, IS_REQUIRED, IS_HISTORY,
          DO_FUNC, EDIT_MASK, RUN_SQL, IS_AUTO_CREATE, FOR_REPL_UP, FOR_REPL_DOWN, TAG, IS_LINK_REFERENSE, LINK_REFERENSE_TYPE_ID,
          DO_CHECK, DO_CHECK_EVENT, BEGIN_GROUP)
        VALUES (:I$TYPE_ID, :I$PARAM_TYPE, :I$LIST_ID, :I$AUTO_LISTVAL_ID, :I$TAB_ID, :GRID_ORDER, :I$IS_TREESORT, :I$IS_TREEVIEW, :I$IS_REQUIRED, :I$IS_HISTORY,
          :I$DO_FUNC, :I$EDIT_MASK, :I$RUN_SQL, :I$IS_AUTO_CREATE, :I$FOR_REPL_UP, :I$FOR_REPL_DOWN, :I$TAG, :I$IS_LINK_REFERENSE, :I$LINK_REFERENSE_TYPE_ID,
          :I$DO_CHECK, :I$DO_CHECK_EVENT, :I$BEGIN_GROUP)
        RETURNING PARAM_ID, RES_ID, HINT_RES_ID, SIZE_RES_ID, AUTO_RES_ID
        INTO :PARAM_ID, :RES_ID, :HINT_RES_ID, :SIZE_RES_ID, :AUTO_RES_ID;
    END
    ELSE
    BEGIN
        IF(RES_ID IS NULL) THEN
        SELECT RES_ID, HINT_RES_ID, SIZE_RES_ID, AUTO_RES_ID
        FROM PARAMS
        WHERE PARAM_ID = :I$PARAM_ID
        INTO :RES_ID, :HINT_RES_ID, :SIZE_RES_ID, :AUTO_RES_ID;

        UPDATE PARAMS
        SET TYPE_ID = :I$TYPE_ID,
            PARAM_TYPE = :I$PARAM_TYPE,
            LIST_ID = :I$LIST_ID,
            AUTO_LISTVAL_ID = :I$AUTO_LISTVAL_ID,
            TAB_ID = :I$TAB_ID,
            IS_TREESORT = :I$IS_TREESORT,
            IS_TREEVIEW = :I$IS_TREEVIEW,
            IS_REQUIRED = :I$IS_REQUIRED,
            IS_HISTORY = :I$IS_HISTORY,
            DO_FUNC = :I$DO_FUNC,
            EDIT_MASK = :I$EDIT_MASK,
            RUN_SQL = :I$RUN_SQL,
            IS_AUTO_CREATE = :I$IS_AUTO_CREATE,
            FOR_REPL_UP = :I$FOR_REPL_UP,
            FOR_REPL_DOWN = :I$FOR_REPL_DOWN,
            TAG = :I$TAG,
            IS_DEL = :I$IS_DEL,
            IS_LINK_REFERENSE = :I$IS_LINK_REFERENSE,
            LINK_REFERENSE_TYPE_ID = :I$LINK_REFERENSE_TYPE_ID,
            DO_CHECK = :I$DO_CHECK,
            DO_CHECK_EVENT = :I$DO_CHECK_EVENT,
            BEGIN_GROUP = :I$BEGIN_GROUP
        WHERE
            PARAM_ID = :I$PARAM_ID;
    END

    /* IF (I$IS_TREESORT = 1) THEN
    BEGIN
        UPDATE PARAMS
        SET IS_TREESORT = 0
        WHERE TYPE_ID = :I$TYPE_ID AND PARAM_ID <> :I$PARAM_ID;
    END*/

    IF (RES_ID IS NOT NULL) THEN
    BEGIN
        EXECUTE PROCEDURE RES_ADD(:RES_ID, :I$LANG_CODE, :I$PARAM_CAPTION);
    END

    IF (HINT_RES_ID IS NOT NULL) THEN
    BEGIN
        EXECUTE PROCEDURE RES_ADD(:HINT_RES_ID, :I$LANG_CODE, :I$HINT_CAPTION);
    END

    IF (SIZE_RES_ID IS NOT NULL) THEN
    BEGIN
        EXECUTE PROCEDURE RES_ADD(:SIZE_RES_ID, :I$LANG_CODE, :I$SIZE_CAPTION);
    END

    IF (AUTO_RES_ID IS NOT NULL) THEN
    BEGIN
        EXECUTE PROCEDURE RES_ADD(:AUTO_RES_ID, :I$LANG_CODE, :I$AUTO_CAPTION);
    END

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAM_CAPTION_GET (
    I$OBJ_ID BIGINT,
    I$PARAM_ID BIGINT,
    I$LEVEL_ID BIGINT,
    I$LANG_CODE VARCHAR(2),
    I$ADD_PARAM_SIZE SMALLINT = 0)
RETURNS (
    CAPTION VARCHAR(4000))
AS
DECLARE VARIABLE V$RES_ID BIGINT;
DECLARE VARIABLE V$SIZE_RES_ID BIGINT;
DECLARE VARIABLE V$TAB_ID BIGINT;
DECLARE VARIABLE V$GRID_ORDER SMALLINT;
DECLARE VARIABLE V$PARAM_SIZE VARCHAR(4000);
BEGIN
    FOR SELECT P.RES_ID, P.SIZE_RES_ID, P.TAB_ID, P.GRID_ORDER
        FROM PARAMS P
        WHERE P.PARAM_ID = :I$PARAM_ID
        INTO :V$RES_ID, :V$SIZE_RES_ID, :V$TAB_ID, :V$GRID_ORDER
    DO
    BEGIN
        SELECT VAL
        FROM RES_GET(:V$RES_ID, :I$LANG_CODE)
        INTO :CAPTION;
    END

    V$RES_ID = NULL;

    SELECT FIRST 1 P.RES_ID
    FROM OBJECTS O
    INNER JOIN PARAMS P ON P.TYPE_ID = O.TYPE_ID AND P.PARAM_TYPE IN (14, 15) AND P.TAB_ID = :V$TAB_ID AND P.GRID_ORDER < :V$GRID_ORDER AND P.IS_DEL = 0
    INNER JOIN LPARAMS LP ON LP.PARAM_ID = P.PARAM_ID AND LP.LEVEL_ID = :I$LEVEL_ID AND LP.IS_DEL = 0 AND LP.EDIT_TYPE > -1
    WHERE O.OBJ_ID = :I$OBJ_ID
    ORDER BY P.GRID_ORDER DESC
    INTO :V$RES_ID;

    IF (V$RES_ID IS NOT NULL) THEN
    BEGIN
        SELECT VAL || ' - ' || :CAPTION
        FROM RES_GET(:V$RES_ID, :I$LANG_CODE)
        INTO :CAPTION;
    END
    IF (I$ADD_PARAM_SIZE = 1 AND V$SIZE_RES_ID IS NOT NULL) THEN
    BEGIN
        SELECT VAL
        FROM RES_GET(:V$SIZE_RES_ID, :I$LANG_CODE)
        INTO :V$PARAM_SIZE;

        IF (V$PARAM_SIZE <> '') THEN
        BEGIN
            CAPTION = CAPTION || ' (' || V$PARAM_SIZE || ')';
        END
    END
    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAM_GET (
    I$PARAM_ID BIGINT,
    I$LANG_CODE VARCHAR(2) = 'RU')
RETURNS (
    PARAM_ID BIGINT,
    LANG_CODE VARCHAR(2),
    PARAM_CAPTION VARCHAR(4000),
    SIZE_CAPTION VARCHAR(1000),
    TYPE_ID BIGINT,
    PARAM_TYPE SMALLINT,
    VAL_TYPE VARCHAR(100),
    BKG_COLOR INTEGER,
    LIST_ID BIGINT,
    TAB_ID BIGINT,
    GRID_ORDER SMALLINT,
    IS_TREESORT SMALLINT,
    IS_TREEVIEW SMALLINT,
    IS_REQUIRED SMALLINT,
    IS_HISTORY SMALLINT,
    RES_ID BIGINT,
    SIZE_RES_ID BIGINT,
    HINT_RES_ID BIGINT,
    HINT_CAPTION VARCHAR(4000),
    DO_FUNC VARCHAR(100),
    EDIT_MASK VARCHAR(200),
    RUN_SQL VARCHAR(1000),
    IS_AUTO_CREATE SMALLINT,
    AUTO_RES_ID BIGINT,
    AUTO_CAPTION VARCHAR(4000),
    AUTO_LISTVAL_ID BIGINT,
    FOR_REPL_UP SMALLINT,
    FOR_REPL_DOWN SMALLINT,
    TAG VARCHAR(100),
    IS_DEL SMALLINT,
    IS_LINK_REFERENSE SMALLINT,
    LINK_REFERENSE_TYPE_ID BIGINT,
    BEGIN_GROUP SMALLINT)
AS
BEGIN
    LANG_CODE = I$LANG_CODE;
    FOR
        SELECT P.PARAM_ID,
               P.TYPE_ID,
               P.PARAM_TYPE,
               P.LIST_ID,
               P.TAB_ID,
               P.GRID_ORDER,
               P.IS_TREESORT,
               P.IS_TREEVIEW,
               P.IS_REQUIRED,
               P.IS_HISTORY,
               P.RES_ID,
               P.SIZE_RES_ID,
               P.HINT_RES_ID,
               P.DO_FUNC,
               P.EDIT_MASK,
               P.RUN_SQL,
               P.IS_AUTO_CREATE,
               P.AUTO_RES_ID,
               P.AUTO_LISTVAL_ID,
               P.FOR_REPL_UP,
               P.FOR_REPL_DOWN,
               P.TAG,
               P.IS_DEL,
               P.IS_LINK_REFERENSE,
               P.LINK_REFERENSE_TYPE_ID,
               T.VAL_TYPE,
               T.BKG_COLOR,
               P.BEGIN_GROUP
        FROM PARAMS P
        INNER JOIN PARAMTYPES T
        ON T.PARAM_TYPE = P.PARAM_TYPE
        WHERE P.PARAM_ID = :I$PARAM_ID
        ORDER BY P.GRID_ORDER
        INTO   :PARAM_ID,
               :TYPE_ID,
               :PARAM_TYPE,
               :LIST_ID,
               :TAB_ID,
               :GRID_ORDER,
               :IS_TREESORT,
               :IS_TREEVIEW,
               :IS_REQUIRED,
               :IS_HISTORY,
               :RES_ID,
               :SIZE_RES_ID,
               :HINT_RES_ID,
               :DO_FUNC,
               :EDIT_MASK,
               :RUN_SQL,
               :IS_AUTO_CREATE,
               :AUTO_RES_ID,
               :AUTO_LISTVAL_ID,
               :FOR_REPL_UP,
               :FOR_REPL_DOWN,
               :TAG,
               :IS_DEL,
               :IS_LINK_REFERENSE,
               :LINK_REFERENSE_TYPE_ID,
               :VAL_TYPE,
               :BKG_COLOR,
               :BEGIN_GROUP
    DO
    BEGIN
        SELECT VAL FROM RES_GET(:RES_ID,      :I$LANG_CODE) INTO :PARAM_CAPTION;
        SELECT VAL FROM RES_GET(:SIZE_RES_ID, :I$LANG_CODE) INTO :SIZE_CAPTION;
        SELECT VAL FROM RES_GET(:AUTO_RES_ID, :I$LANG_CODE) INTO :AUTO_CAPTION;
        SELECT VAL FROM RES_GET(:HINT_RES_ID, :I$LANG_CODE) INTO :HINT_CAPTION;
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAM_GET_BY_CAPTION (
    I$TYPE_ID BIGINT,
    I$PARAM_CAPTION VARCHAR(1000),
    I$LANG_CODE VARCHAR(2) = 'RU')
RETURNS (
    TYPE_ID BIGINT,
    PARAM_ID BIGINT,
    PARAM_TYPE SMALLINT,
    LIST_ID BIGINT,
    LINK_REFERENSE_TYPE_ID BIGINT)
AS
BEGIN
    FOR
        SELECT FIRST 1
               P.TYPE_ID,
               P.PARAM_ID,
               P.PARAM_TYPE,
               P.LIST_ID,
               P.LINK_REFERENSE_TYPE_ID
        FROM PARAMS P
        JOIN TYPES T ON T.TYPE_ID = P.TYPE_ID
        JOIN RES RP ON RP.RES_ID = P.RES_ID
        JOIN RES RT ON RT.RES_ID = T.RES_ID
        WHERE P.TYPE_ID IN (
            SELECT :I$TYPE_ID FROM RDB$DATABASE
            UNION
            SELECT CHILD_ID FROM PARENTS
            WHERE TYPE_ID = :I$TYPE_ID
              AND IS_ADD + IS_INTERNAL_ADD > 0
              AND IS_DEL = 0)
          AND P.IS_DEL = 0
          AND (RP.VAL = :I$PARAM_CAPTION OR RT.VAL ||'|'|| RP.VAL = :I$PARAM_CAPTION)
        ORDER BY
            IIF(RT.VAL ||'|'|| RP.VAL = :I$PARAM_CAPTION, 0, 1),
            IIF(:I$TYPE_ID = P.TYPE_ID, 0, 1),
            IIF(:I$LANG_CODE = RP.LANG_CODE, 0, 1)
        INTO   :TYPE_ID,
               :PARAM_ID,
               :PARAM_TYPE,
               :LIST_ID,
               :LINK_REFERENSE_TYPE_ID
    DO
    BEGIN
        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAM_GET_DO_OP_DIRECTION (
    OBJ_ID BIGINT)
RETURNS (
    VAL VARCHAR(4000))
AS
declare variable V$OP_ID bigint;
BEGIN

    -- Получаем ID образовательной программы (ОО или ОДОД)
    SELECT VAL
    FROM VALR
    WHERE OBJ_ID = :OBJ_ID AND PARAM_ID IN (2441, 2823) AND IS_DEL = 0
    INTO :V$OP_ID;

    IF(V$OP_ID IS NOT NULL) THEN
    BEGIN
        SELECT V FROM VAL_GET(:V$OP_ID, 390) WHERE IS_EXISTS = 1 INTO :VAL;

        -- ОДОД
        IF(VAL IS NULL) THEN SELECT V FROM VAL_GET(:V$OP_ID, 2148) WHERE IS_EXISTS = 1 INTO :VAL;
    END

    SUSPEND;

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAM_GET_DO_OP_LIST (
    OBJ_ID BIGINT)
RETURNS (
    OP_ID BIGINT,
    OP_CAPTION VARCHAR(4000))
AS
declare variable V$SCHOOL_ID bigint;
declare variable V$OU_LICENCE_TYPE char(1);
BEGIN

  -- Для ДПО возвращаем не ОП, а утвержденные УП. Для всех остальных возвращаем ОП
  SELECT STATUS FROM OU_LICENCE_TYPE INTO :V$OU_LICENCE_TYPE;

  SELECT LP2.PARENT_ID
  FROM LINKS LP86
  JOIN LINKS LP2 ON LP2.OBJ_ID = LP86.PARENT_ID AND LP2.PARENT_TYPE_ID = 2 AND LP2.DATE_DEL IS NULL
  WHERE LP86.OBJ_ID = :OBJ_ID AND LP86.PARENT_TYPE_ID = 86 AND LP86.DATE_DEL IS NULL
  INTO :V$SCHOOL_ID;

  IF(V$OU_LICENCE_TYPE = 'P') THEN
  BEGIN
      FOR
          SELECT L400.OBJ_ID, C.CAPTION
          FROM LINKS L69
          JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
          JOIN LINKS L400 ON L400.PARENT_ID = L57.OBJ_ID AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL
          JOIN VALL V3013 ON V3013.OBJ_ID = L400.OBJ_ID AND V3013.PARAM_ID = 3013 AND V3013.IS_DEL = 0 AND V3013.LISTVAL_ID = 11715
          LEFT JOIN OBJECT_CAPTION_GET(L400.OBJ_ID) C ON 1 = 1
          WHERE L69.PARENT_ID = :V$SCHOOL_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL
          ORDER BY 2
          INTO :OP_ID, :OP_CAPTION
      DO
      BEGIN
          SUSPEND;
      END
  END
  ELSE
  BEGIN
      FOR
          SELECT L57.OBJ_ID, V386.VAL
          FROM LINKS L69
          JOIN VALL V2450 ON V2450.OBJ_ID = L69.OBJ_ID AND V2450.PARAM_ID = 2450 AND V2450.IS_DEL = 0 AND V2450.LISTVAL_ID = 11386
          JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
          JOIN VALS V386 ON V386.OBJ_ID = L57.OBJ_ID AND V386.PARAM_ID = 386 AND V386.IS_DEL = 0
          WHERE L69.PARENT_ID = :V$SCHOOL_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL
          INTO :OP_ID, :OP_CAPTION
      DO
      BEGIN
          SUSPEND;
      END
  END

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARAM_MOVE (
    I$PARAM_ID BIGINT,
    I$MOVE SMALLINT)
RETURNS (
    GRID_ORDER SMALLINT)
AS
DECLARE VARIABLE PARAM_ID BIGINT = NULL;
DECLARE VARIABLE TYPE_ID BIGINT = NULL;
BEGIN
   SELECT TYPE_ID, GRID_ORDER FROM PARAMS
   WHERE PARAM_ID = :I$PARAM_ID
   INTO :TYPE_ID, :GRID_ORDER;

   SELECT PARAM_ID FROM PARAMS
   WHERE TYPE_ID = :TYPE_ID AND GRID_ORDER = (:GRID_ORDER + :I$MOVE)
   INTO :PARAM_ID;

   IF (PARAM_ID IS NOT NULL) THEN BEGIN
      UPDATE PARAMS SET GRID_ORDER = :GRID_ORDER WHERE PARAM_ID = :PARAM_ID;
      UPDATE PARAMS SET GRID_ORDER = (:GRID_ORDER + :I$MOVE) WHERE PARAM_ID = :I$PARAM_ID;
   END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARENTS_ADD (
    I$TYPE_ID BIGINT,
    I$CHILD_ID BIGINT,
    I$IS_ADD SMALLINT,
    I$IS_INTERNAL_ADD SMALLINT,
    I$IS_COPY SMALLINT,
    I$IS_CUT SMALLINT,
    I$IS_LINK SMALLINT,
    I$DO_FUNC SMALLINT,
    I$IS_FROM_LIST SMALLINT,
    I$RUN_SQL VARCHAR(1000),
    I$IS_AUTO_CREATE SMALLINT,
    I$TAB_ID BIGINT,
    I$IS_REPL SMALLINT,
    I$IS_DEL SMALLINT,
    I$IS_DELETE_OTHER_LINKS SMALLINT,
    I$IS_SELECT SMALLINT,
    I$IS_TAB_VERTICAL_ALIGNMENT SMALLINT,
    I$EXT_TYPE_ID BIGINT,
    I$SHOW_ALL_FIELDS SMALLINT = null,
    I$RUN_FUNCTION SMALLINT = null)
AS
BEGIN
    IF (I$IS_SELECT = 1) THEN I$IS_ADD = 0;

    -- Когда последние два поля по-умолчанию - подтягиваем уже имеющиеся значения
    IF(I$SHOW_ALL_FIELDS IS NULL) THEN
    SELECT P.SHOW_ALL_FIELDS, P.RUN_FUNCTION
    FROM PARENTS P
    WHERE P.TYPE_ID = :I$TYPE_ID AND P.CHILD_ID = :I$CHILD_ID
    INTO :I$SHOW_ALL_FIELDS, :I$RUN_FUNCTION;

    I$SHOW_ALL_FIELDS = COALESCE(I$SHOW_ALL_FIELDS, 0);
    I$RUN_FUNCTION = COALESCE(I$RUN_FUNCTION, 0);

    UPDATE OR INSERT INTO PARENTS
    (TYPE_ID, CHILD_ID, IS_ADD, IS_INTERNAL_ADD, IS_COPY, IS_CUT, IS_LINK, DO_FUNC, IS_FROM_LIST, RUN_SQL, IS_AUTO_CREATE, TAB_ID, IS_DEL,
      IS_DELETE_OTHER_LINKS, IS_SELECT, IS_TAB_VERTICAL_ALIGNMENT, EXT_TYPE_ID, SHOW_ALL_FIELDS, RUN_FUNCTION)
    VALUES (:I$TYPE_ID, :I$CHILD_ID, :I$IS_ADD, :I$IS_INTERNAL_ADD, :I$IS_COPY, :I$IS_CUT, :I$IS_LINK, :I$DO_FUNC, :I$IS_FROM_LIST, :I$RUN_SQL, :I$IS_AUTO_CREATE, :I$TAB_ID, :I$IS_DEL,
      :I$IS_DELETE_OTHER_LINKS, :I$IS_SELECT, :I$IS_TAB_VERTICAL_ALIGNMENT, :I$EXT_TYPE_ID, :I$SHOW_ALL_FIELDS, :I$RUN_FUNCTION);

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARENTS_LIST (
    I$TYPE_ID BIGINT,
    I$LANG_CODE CHAR(2) = 'RU')
RETURNS (
    TYPE_ID BIGINT,
    RES_ID BIGINT,
    CHILD_ID BIGINT,
    IS_ADD SMALLINT,
    IS_INTERNAL_ADD SMALLINT,
    IS_COPY SMALLINT,
    IS_CUT SMALLINT,
    IS_LINK SMALLINT,
    DO_FUNC SMALLINT,
    IS_FROM_LIST SMALLINT,
    RUN_SQL VARCHAR(1000),
    IS_AUTO_CREATE SMALLINT,
    TAB_ID BIGINT,
    IS_REPL SMALLINT,
    IS_DEL SMALLINT,
    TYPE_CAPTION VARCHAR(4000),
    IS_DELETE_OTHER_LINKS SMALLINT,
    IS_SELECT SMALLINT,
    IS_TAB_VERTICAL_ALIGNMENT SMALLINT,
    EXT_TYPE_ID BIGINT)
AS
BEGIN
    IS_REPL = 0;
    TYPE_ID = I$TYPE_ID;
    FOR
        SELECT TP.TYPE_ID,
               TP.RES_ID,
               COALESCE(PR.IS_ADD, 0),
               COALESCE(PR.IS_INTERNAL_ADD, 0),
               COALESCE(PR.IS_COPY, 0),
               COALESCE(PR.IS_CUT, 0),
               COALESCE(PR.IS_LINK, 0),
               COALESCE(PR.DO_FUNC, 0),
               COALESCE(PR.IS_FROM_LIST, 0),
               PR.RUN_SQL,
               COALESCE(PR.IS_AUTO_CREATE, 0),
               PR.TAB_ID,
               COALESCE(PR.IS_DEL, 0),
               COALESCE(PR.IS_DELETE_OTHER_LINKS, 0),
               COALESCE(PR.IS_SELECT, 0),
               COALESCE(PR.IS_TAB_VERTICAL_ALIGNMENT, 0),
               PR.EXT_TYPE_ID
        FROM TYPES TP
        LEFT OUTER JOIN PARENTS PR
        ON PR.TYPE_ID = :I$TYPE_ID
        AND PR.CHILD_ID = TP.TYPE_ID
        WHERE TP.IS_DEL = 0
    /*    WHERE TP.TYPE_ID != :I$TYPE_ID   */
        ORDER BY TP.SORT_ORDER
        INTO   :CHILD_ID,
               :RES_ID,
               :IS_ADD,
               :IS_INTERNAL_ADD,
               :IS_COPY,
               :IS_CUT,
               :IS_LINK,
               :DO_FUNC,
               :IS_FROM_LIST,
               :RUN_SQL,
               :IS_AUTO_CREATE,
               :TAB_ID,
               :IS_DEL,
               :IS_DELETE_OTHER_LINKS,
               :IS_SELECT,
               :IS_TAB_VERTICAL_ALIGNMENT,
               :EXT_TYPE_ID
    DO
    BEGIN
        SELECT VAL FROM RES_GET(:RES_ID, :I$LANG_CODE) INTO :TYPE_CAPTION;
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARENT_ACCOUNT_INFO (
    I$OBJ_ID BIGINT)
RETURNS (
    USER_NAME VARCHAR(100),
    USER_ID BIGINT,
    IS_BLOCKED SMALLINT,
    VALID_TO DATE)
AS
begin

  SELECT U.USER_ID, U.USER_NAME, U.IS_BLOCKED, U.EXP_DATE
  FROM USERS U
  WHERE U.DATE_DEL IS NULL AND U.OBJ_ID = :I$OBJ_ID
  INTO :USER_ID, :USER_NAME, :IS_BLOCKED, :VALID_TO;

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARENT_CHILDREN_LIST (
    I$PARENT_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    OBJ_CAPTION VARCHAR(1000))
AS
begin

  -- Разрешаем выбирать только однократно, в дальнейшем менять нельзя - показываем только уже выбранного
  -- в дальнейшем новые документы добавляем только через кнопку
  SELECT FIRST 1 V2369.VAL
  FROM VALR V2369
  WHERE V2369.OBJ_ID = :I$PARENT_ID AND V2369.PARAM_ID = 2369 AND V2369.IS_DEL = 0
  INTO :OBJ_ID;

  IF(OBJ_ID IS NOT NULL) THEN
  BEGIN
    -- По идее такого быть не может - мы в принципе не увидим этот документ, если ученик утрачен
    IF(NOT EXISTS(
      SELECT FIRST 1 1
      FROM LINKS LP10
      WHERE LP10.OBJ_ID = :I$PARENT_ID AND LP10.PARENT_TYPE_ID = 10 AND LP10.DATE_DEL IS NULL AND LP10.PARENT_ID = :OBJ_ID
    ))
    THEN
      EXCEPTION DATA_ERROR 'Данный родитель (законный представитель) не имеет связи с указанным в документе обучающимся';

    OBJ_CAPTION = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:OBJ_ID, 23));
    SUSPEND;
    EXIT;
  END

  FOR
    SELECT LP10.PARENT_ID, C.CAPTION
    FROM LINKS LP20
    JOIN LINKS LP10 ON LP10.OBJ_ID = LP20.PARENT_ID AND LP10.PARENT_TYPE_ID = 10 AND LP10.DATE_DEL IS NULL
    LEFT JOIN OBJECT_CAPTION_GET(LP10.PARENT_ID, 23) C ON 1 = 1
    WHERE LP20.OBJ_ID = :I$PARENT_ID AND LP20.PARENT_TYPE_ID = 20 AND LP20.DATE_DEL IS NULL
    ORDER BY 2
    INTO :OBJ_ID, :OBJ_CAPTION
  DO
  BEGIN
    SUSPEND;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARENT_REF_DOU (
    I$STUDENT_ID BIGINT,
    I$PARENT_ID BIGINT)
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE S VARCHAR(1000);
DECLARE VARIABLE V$ID BIGINT;
DECLARE VARIABLE V$SCHOOL BIGINT;
begin
  TAG_NAME = 'licence_type';
  SELECT STATUS FROM OU_LICENCE_TYPE INTO :VAL;
  SUSPEND;

  SELECT L2.OBJ_ID
  FROM LINKS L2
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$SCHOOL;

  TAG_NAME = 'upper_name';
  VAL = NULL;
  SELECT V FROM VAL_GET(:V$SCHOOL, 7) WHERE IS_EXISTS = 1 INTO :VAL;
  SUSPEND;

  TAG_NAME = 'ou_name';
  VAL = NULL;
  SELECT V FROM VAL_GET(:V$SCHOOL, 5) WHERE IS_EXISTS = 1 INTO :VAL;
  SUSPEND;

  TAG_NAME = 'inn';
  VAL = NULL;
  SELECT V FROM VAL_GET(:V$SCHOOL, 33) WHERE IS_EXISTS = 1 INTO :VAL;
  SUSPEND;

  TAG_NAME = 'ogrn';
  VAL = NULL;
  SELECT V FROM VAL_GET(:V$SCHOOL, 9) WHERE IS_EXISTS = 1 INTO :VAL;
  SUSPEND;

  TAG_NAME = 'kpp';
  VAL = NULL;
  SELECT V FROM VAL_GET(:V$SCHOOL, 34) WHERE IS_EXISTS = 1 INTO :VAL;
  SUSPEND;

  TAG_NAME = 'okpo';
  VAL = NULL;
  SELECT V FROM VAL_GET(:V$SCHOOL, 16) WHERE IS_EXISTS = 1 INTO :VAL;
  SUSPEND;

  TAG_NAME = 'address';
  VAL = NULL;
  SELECT V FROM VAL_GET(:V$SCHOOL, 27) WHERE IS_EXISTS = 1 INTO :VAL;
  SUSPEND;

  TAG_NAME = 'district';
  VAL = NULL;
  SELECT V FROM VAL_GET(:V$SCHOOL, 2163) WHERE IS_EXISTS = 1 INTO :VAL;
  SUSPEND;

  TAG_NAME = 'phone';
  VAL = NULL;
  SELECT V FROM VAL_GET(:V$SCHOOL, 29) WHERE IS_EXISTS = 1 INTO :VAL;
  SUSPEND;

  TAG_NAME = 'fax';
  VAL = NULL;
  SELECT V FROM VAL_GET(:V$SCHOOL, 30) WHERE IS_EXISTS = 1 INTO :VAL;
  SUSPEND;

  TAG_NAME = 'email';
  VAL = NULL;
  SELECT V FROM VAL_GET(:V$SCHOOL, 35) WHERE IS_EXISTS = 1 INTO :VAL;
  SUSPEND;

  TAG_NAME = 'student_name';
  VAL = NULL;
  S = NULL;
  SELECT FIRST 1 BF.F || ' ' || BF.I || ' ' || BF.O, DC.F || ' ' || DC.I || ' ' || DC.O
  FROM RDB$DATABASE
  LEFT JOIN BUILD_REP_FIO(:I$STUDENT_ID, 55, 56, 57) BF ON 1 = 1
  LEFT JOIN DATIVECASE(BF.F, BF.I, BF.O) DC ON 1 = 1
  INTO :VAL, :S;
  SUSPEND;

  TAG_NAME = 'student_name_r';
  VAL = S;
  SUSPEND;

  TAG_NAME = 'student_gender';
  IF(EXISTS(
    SELECT FIRST 1 1
    FROM VALL V88
    WHERE V88.OBJ_ID = :I$STUDENT_ID AND V88.PARAM_ID = 88 AND V88.IS_DEL = 0 AND V88.LISTVAL_ID = 182
  ))
  THEN
    VAL = 'дочь';
  ELSE
    VAL = 'сын';
  SUSPEND;

  -- Определим группу
  V$ID = NULL;
  SELECT P.GROUP_ID
  FROM PERSON_MOVEMENTS P
  WHERE P.PERSON_ID = :I$STUDENT_ID AND P.DATE_DEL IS NULL AND P.DATE_OUT IS NULL AND P.GROUP_TYPE_ID IN (9, 187)
  INTO :V$ID;

  -- Определим этап обучения
  TAG_NAME = 'stage';
  VAL = NULL;
  SELECT FIRST 1 LV.PARENT_ID
  FROM LINKS L9
  JOIN VALL V49 ON V49.OBJ_ID = L9.PARENT_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V49.LISTVAL_ID AND LV.IS_DEL = 0
  WHERE L9.OBJ_ID = :V$ID AND L9.PARENT_TYPE_ID = 8 AND L9.DATE_DEL IS NULL
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'parent_name';
  VAL = NULL;
  S = NULL;
  SELECT FIRST 1 BF.F || ' ' || BF.I || ' ' || BF.O, DC.F || ' ' || DC.I || ' ' || DC.O
  FROM RDB$DATABASE
  LEFT JOIN BUILD_REP_FIO(:I$PARENT_ID, 128, 129, 130) BF ON 1 = 1
  LEFT JOIN DATIVECASE(BF.F, BF.I, BF.O) DC ON 1 = 1
  INTO :VAL, :S;
  SUSPEND;

  TAG_NAME = 'parent_name_r';
  VAL = S;
  SUSPEND;

  TAG_NAME = 'parent_gender';
  IF(EXISTS(
    SELECT FIRST 1 1
    FROM VALL V2544
    WHERE V2544.OBJ_ID = :I$PARENT_ID AND V2544.PARAM_ID = 2544 AND V2544.IS_DEL = 0 AND V2544.LISTVAL_ID = 182
  ))
  THEN
    VAL = 'его';
  ELSE
    VAL = 'ее';
  SUSPEND;

  TAG_NAME = 'birth_date';
  VAL = NULL;
  SELECT FIRST 1 D.RESULT
  FROM VALD V
  LEFT JOIN DATE2STR(V.VAL) D ON 1 = 1
  WHERE V.OBJ_ID = :I$STUDENT_ID AND V.PARAM_ID = 89 AND V.IS_DEL = 0
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'head_post';
  VAL = NULL;
  S = NULL;
  SELECT C.POST, SUBSTRING(TRIM(C.I) FROM 1 FOR 1) || '.' || SUBSTRING(TRIM(C.O) FROM 1 FOR 1) || '.'|| C.F
  FROM R_SPB_POST_DIRECTOR(:V$SCHOOL, 1) C
  INTO :VAL, :S;
  SUSPEND;

  TAG_NAME = 'head_name';
  VAL = S;
  SUSPEND;

  TAG_NAME = 'date_in';
  VAL = NULL;
  SELECT FIRST 1 D.RESULT
  FROM PERSON_MOVEMENTS M
  -- если были выбытия, то считаем от последнего
  LEFT JOIN PERSON_MOVEMENTS M2 ON M2.DATE_DEL IS NULL AND M2.PERSON_ID = M.PERSON_ID AND M2.GROUP_TYPE_ID = 9 AND M2.DATE_IN > M.DATE_IN AND M2.REASON_OUT IN (5548, 5549, 811, 812)
  LEFT JOIN DATE2STR(M.DATE_IN) D ON 1 = 1
  WHERE M.PERSON_ID = :I$STUDENT_ID AND M.GROUP_TYPE_ID = 9 AND M.DATE_DEL IS NULL AND M2.OBJ_ID IS NULL
  ORDER BY M.DATE_IN
  INTO :VAL;
  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PARSING_STRING_GET (
    I$STRING VARCHAR(4000),
    I$SEPARATOR VARCHAR(10))
RETURNS (
    TAKEN VARCHAR(4000))
AS
declare variable V$I integer;
declare variable V$S integer;
declare variable V$SEPR integer;
declare variable V$STR integer;
declare variable V$POS INTEGER;
declare variable V$Y integer;
declare variable V$TAKEN_TMP VarChar(100);
begin
  V$I = 0;
  V$S = 1;
  V$TAKEN_TMP = '';
  TAKEN = '';
  V$SEPR = char_length(:I$SEPARATOR);
  V$STR = char_length(:I$STRING);
  V$POS = 0;
  V$Y = 0;

  while (:V$I < V$STR) do
  begin
    V$I = :V$I + 1;
    V$TAKEN_TMP = substring(:I$STRING from :V$I for V$SEPR);
    if (upper(:V$TAKEN_TMP) = upper(:I$SEPARATOR)) then
    begin
      TAKEN = substring(:I$STRING from :V$S for :V$POS);
      suspend;
      V$S = :V$I + :V$SEPR;
      V$I = :V$Y + :V$pos + :V$SEPR;
      V$Y = :V$I;
      V$pos = 0;
    end else
    V$POS = V$POS + 1;
  end
  TAKEN = substring(:I$STRING from :V$S for :V$POS);
  suspend;
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PAUTH_APPLY (
    I$GRADE_ID BIGINT,
    I$PARENT_ID BIGINT,
    I$PWD VARCHAR(40),
    I$USER_ID VARCHAR(40))
AS
declare variable V$EMAIL varchar(200);
declare variable V$ID bigint;
declare variable V$NAME_LAST varchar(100);
declare variable V$NAME_FIRST varchar(100);
declare variable V$NAME_MID varchar(100);
declare variable V$TYPE bigint;
begin

  SELECT FIRST 1 V128.VAL, V129.VAL, V130.VAL
  FROM LINKS L10
  JOIN LINKS L20 ON L20.PARENT_ID = L10.OBJ_ID AND L20.OBJ_TYPE_ID = 20 AND L20.DATE_DEL IS NULL AND L20.OBJ_ID = :I$PARENT_ID
  JOIN VALS V128 ON V128.OBJ_ID = L20.OBJ_ID AND V128.PARAM_ID = 128 AND V128.IS_DEL = 0
  JOIN VALS V129 ON V129.OBJ_ID = L20.OBJ_ID AND V129.PARAM_ID = 129 AND V129.IS_DEL = 0
  LEFT JOIN VALS V130 ON V130.OBJ_ID = L20.OBJ_ID AND V130.PARAM_ID = 130 AND V130.IS_DEL = 0
  WHERE L10.PARENT_ID = :I$GRADE_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
  INTO :V$NAME_LAST, :V$NAME_FIRST, :V$NAME_MID;

  IF(V$NAME_LAST IS NULL) THEN EXCEPTION DATA_ERROR 'В выбранном классе нет такого родителя (' || I$PARENT_ID || ')';
  IF(V$NAME_MID IS NULL) THEN V$NAME_MID = '';

  SELECT FIRST 1 V144.VAL
  FROM VALS V144
  WHERE V144.OBJ_ID = :I$PARENT_ID AND V144.PARAM_ID = 144 AND V144.IS_DEL = 0
  INTO :V$EMAIL;

  IF(V$EMAIL IS NULL OR CHAR_LENGTH(V$EMAIL) < 4 OR POSITION('@' IN V$EMAIL) <= 1) THEN
    EXCEPTION DATA_ERROR 'В профиле пользователя ' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$PARENT_ID)) || ' указан неверный email';

  IF(EXISTS(
    SELECT FIRST 1 1
    FROM USERS U
    WHERE U.DATE_DEL IS NULL AND (U.OBJ_ID <> :I$PARENT_ID OR U.OBJ_ID IS NULL) AND UPPER(REPLACE(U.USER_NAME, ' ', '')) = UPPER(REPLACE(:V$EMAIL, ' ', ''))
  ))
  THEN EXCEPTION DATA_ERROR 'Пользователь с таким email уже есть в системе';

  SELECT FIRST 1 U.USER_ID, U.USER_TYPE
  FROM USERS U
  WHERE U.DATE_DEL IS NULL AND U.OBJ_ID = :I$PARENT_ID
  INTO :V$ID, :V$TYPE;

  IF(V$ID IS NULL) THEN
  BEGIN
    INSERT INTO USERS
    (USER_NAME, OBJ_ID, PWD, USER_TYPE, LAST_NAME, FIRST_NAME, MIDDLE_NAME)
    VALUES (:V$EMAIL, :I$PARENT_ID, :I$PWD, 22, :V$NAME_LAST, :V$NAME_FIRST, :V$NAME_MID);
  END
  ELSE
  BEGIN
    IF(V$TYPE <> 22) THEN EXCEPTION DATA_ERROR 'Пользователь имеет роль, отличную от роли родителя (' || V$TYPE || ')';

    UPDATE USERS
    SET PWD = :I$PWD, IS_BLOCKED = 0, LAST_NAME = :V$NAME_LAST, FIRST_NAME = :V$NAME_FIRST, MIDDLE_NAME = :V$NAME_MID, USER_NAME = :V$EMAIL
    WHERE USER_ID = :V$ID;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PAUTH_CONTENT (
    I$GRADE_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    CAPTION VARCHAR(400),
    PARENT_ID BIGINT,
    PARENT_CAPTION VARCHAR(400),
    PARENT_EMAIL VARCHAR(200),
    PARENT_CFM SMALLINT)
AS
begin

  FOR
    SELECT L10.OBJ_ID, C1.CAPTION, L20.OBJ_ID, C2.CAPTION, V144.VAL
    FROM LINKS L10      
    LEFT JOIN OBJECT_CAPTION_GET(L10.OBJ_ID, 23) C1 ON 1 = 1
    LEFT JOIN LINKS L20 ON L20.PARENT_ID = L10.OBJ_ID AND L20.OBJ_TYPE_ID = 20 AND L20.DATE_DEL IS NULL
    LEFT JOIN OBJECT_CAPTION_GET(L20.OBJ_ID) C2 ON 1 = 1
    LEFT JOIN VALS V144 ON V144.OBJ_ID = L20.OBJ_ID AND V144.PARAM_ID = 144 AND V144.IS_DEL = 0
    WHERE L10.PARENT_ID = :I$GRADE_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    ORDER BY 2, 4
    INTO :OBJ_ID, :CAPTION, :PARENT_ID, :PARENT_CAPTION, :PARENT_EMAIL
  DO
  BEGIN

    PARENT_CAPTION = REPLACE(PARENT_CAPTION, '  ', ' ');

    PARENT_CFM = 0;
    IF(PARENT_EMAIL IS NOT NULL) THEN
    BEGIN
      SELECT FIRST 1 1
      FROM USERS U
      WHERE U.DATE_DEL IS NULL AND U.OBJ_ID = :PARENT_ID AND U.USER_NAME = :PARENT_EMAIL
      INTO :PARENT_CFM;
    END

    SUSPEND;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PAUTH_REPORT (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    CHILD_ID BIGINT,
    OBJ_ID BIGINT,
    CHILD_NAME VARCHAR(400),
    CAPTION VARCHAR(400),
    USER_EMAIL VARCHAR(100),
    REG_DATE VARCHAR(40),
    LAST_DATE VARCHAR(40),
    AVG_RATE FLOAT,
    IS_BLOCKED INTEGER)
AS
declare variable DT timestamp;
begin

  FOR
    SELECT L10.OBJ_ID, C.CAPTION, U.DATE_MODIFY, U.IS_BLOCKED, V3076.SVAL
    FROM LINKS L10
    LEFT JOIN OBJECT_CAPTION_GET(L10.OBJ_ID, 23) C ON 1 = 1
    LEFT JOIN USERS U ON U.OBJ_ID = L10.OBJ_ID AND U.DATE_DEL IS NULL
    LEFT JOIN VALS V3076 ON V3076.OBJ_ID = L10.OBJ_ID AND V3076.PARAM_ID = 3076 AND V3076.IS_DEL = 0
    WHERE L10.PARENT_ID = :I$OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    INTO :CHILD_ID, :CHILD_NAME, :DT, :IS_BLOCKED, :USER_EMAIL
  DO
  BEGIN
    OBJ_ID = NULL;
    CAPTION = NULL;
    IF(EXTRACT(YEAR FROM DT) < 1900) THEN DT = NULL;
    REG_DATE = (SELECT VAL FROM DATE2ISO(:DT));
    SUSPEND;

    FOR
      SELECT L20.OBJ_ID, C.CAPTION, U.DATE_MODIFY, U.IS_BLOCKED, V144.SVAL
      FROM LINKS L20
      LEFT JOIN OBJECT_CAPTION_GET(L20.OBJ_ID) C ON 1 = 1
      LEFT JOIN USERS U ON U.OBJ_ID = L20.OBJ_ID AND U.DATE_DEL IS NULL
      LEFT JOIN VALS V144 ON V144.OBJ_ID = L20.OBJ_ID AND V144.PARAM_ID = 144 AND V144.IS_DEL = 0
      WHERE L20.PARENT_ID = :CHILD_ID AND L20.OBJ_TYPE_ID = 20 AND L20.DATE_DEL IS NULL
      INTO :OBJ_ID, :CAPTION, :DT, :IS_BLOCKED, :USER_EMAIL
    DO
    BEGIN
      IF(EXTRACT(YEAR FROM DT) < 1900) THEN DT = NULL;
      REG_DATE = (SELECT VAL FROM DATE2ISO(:DT));
      SUSPEND;
    END

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PAUTH_RESET (
    I$PARENT_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$PWD VARCHAR(40),
    I$USER_ID VARCHAR(40))
RETURNS (
    EMAIL VARCHAR(400),
    OBJ_ID BIGINT,
    USERNAME VARCHAR(400),
    OU_NAME VARCHAR(1000))
AS
begin

  -- Пароль может сбросить только руководство или классный руководитель

  SELECT FIRST 1 L20.OBJ_ID, V144.VAL, U.USER_NAME
  FROM LINKS L20
  JOIN LINKS LP9 ON LP9.OBJ_ID = L20.PARENT_ID AND LP9.PARENT_TYPE_ID IN (9, 187) AND LP9.DATE_DEL IS NULL
  LEFT JOIN VALS V144 ON V144.OBJ_ID = L20.OBJ_ID AND V144.PARAM_ID = 144 AND V144.IS_DEL = 0
  LEFT JOIN USERS U ON U.OBJ_ID = L20.OBJ_ID AND U.DATE_DEL IS NULL
  WHERE L20.PARENT_ID = :I$PARENT_ID AND L20.OBJ_ID = :I$OBJ_ID AND L20.DATE_DEL IS NULL
  INTO :OBJ_ID, :EMAIL, :USERNAME;

  IF(OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Запись родителя не найдена';
  IF(EMAIL IS NULL) THEN EXCEPTION DATA_ERROR 'У родителя не указан email';
  IF(USERNAME IS NULL) THEN EXCEPTION DATA_ERROR 'Родитель не зарегистрирован как пользователь';

  IF(EMAIL <> USERNAME) THEN EXCEPTION DATA_ERROR 'Учетная запись пользователя и указанный email не соответствуют друг другу';

  SELECT FIRST 1 C.CAPTION
  FROM LINKS L2
  LEFT JOIN OBJECT_CAPTION_GET(L2.OBJ_ID) C ON 1 = 1
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :OU_NAME;

  UPDATE USERS
  SET PWD = :I$PWD
  WHERE OBJ_ID = :I$OBJ_ID;

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PBDOO_SERIALIZE (
    I$VERSION VARCHAR(100))
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(4000))
AS
declare variable V$LIC_TYPE varchar(10);
declare variable V$OBJ_ID bigint;
declare variable V$PARENT_ID bigint;
declare variable D date;
declare variable S varchar(1000);
declare variable S1 varchar(250);
declare variable S2 varchar(250);
declare variable S3 varchar(250);
declare variable REGION varchar(255);
declare variable DISTRICT varchar(255);
declare variable TOWN varchar(255);
declare variable SETTLEMENT varchar(255);
declare variable STREET varchar(255);
declare variable HOUSE varchar(10);
declare variable LITER varchar(10);
declare variable CORP varchar(10);
declare variable FLAT varchar(10);
declare variable POST_INDEX varchar(20);
declare variable V$V bigint;
begin

  -- Вместо старой хрени в PORTAL_OU_DATA_GET
  SELECT STATUS FROM OU_LICENCE_TYPE INTO :V$LIC_TYPE;

  TAG_NAME = 'package::version';
  VAL = I$VERSION;
  SUSPEND;

  TAG_NAME = 'package::date';
  VAL = (SELECT RESULT FROM DATE2STR(CURRENT_DATE));
  SUSPEND;

  TAG_NAME = 'package:classType';
  VAL = NULL;
  SUSPEND;
  FOR
    SELECT LISTVAL_ID, PARENT_ID, VAL
    FROM LISTVALS_LIST(6)
    WHERE IS_DEL = 0
    ORDER BY SORT_ORDER
    INTO :V$OBJ_ID, :V$PARENT_ID, :S
  DO
  BEGIN
    IF(V$PARENT_ID IS NULL) THEN
    BEGIN
      TAG_NAME = 'package:classType:listKind';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'package:classType:listKind::parentID';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'package:classType:listKind::nameType';
      VAL = S;
      SUSPEND;
    END
    ELSE
    BEGIN
      TAG_NAME = 'package:classType:listKind:itemKind';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'package:classType:listKind:itemKind::id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'package:classType:listKind:itemKind::nameKind';
      VAL = S;
      SUSPEND;
    END
  END

  TAG_NAME = 'package:stopReason';
  VAL = NULL;
  SUSPEND;
  FOR
    SELECT LISTVAL_ID, PARENT_ID, VAL
    FROM LISTVALS_LIST(331)
    WHERE IS_DEL = 0
    ORDER BY SORT_ORDER
    INTO :V$OBJ_ID, :V$PARENT_ID, :S
  DO
  BEGIN
    TAG_NAME = 'package:stopReason:itemKind';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'package:stopReason:itemKind::id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'package:stopReason:itemKind::nameKind';
    VAL = S;
    SUSPEND;
  END

  TAG_NAME = 'package:institutions';
  VAL = NULL;
  SUSPEND;
  FOR
    SELECT DISTINCT L2.OBJ_ID
    FROM LINKS L2
    WHERE (L2.PARENT_TYPE_ID IN (111, 112) OR L2.PARENT_ID IS NULL) AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :V$OBJ_ID
  DO
  BEGIN
    TAG_NAME = 'package:institutions:institution';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'package:institutions:institution::uid';
    VAL = (SELECT V FROM VAL_GET(:V$OBJ_ID, 9) WHERE IS_EXISTS = 1);
    SUSPEND;

    TAG_NAME = 'package:institutions:institution:required';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'package:institutions:institution:required:fullname:string';
    VAL = (SELECT V FROM VAL_GET(:V$OBJ_ID, 5) WHERE IS_EXISTS = 1);
    SUSPEND;
    TAG_NAME = 'package:institutions:institution:required:shortname:string';
    IF(V$LIC_TYPE = 'C') THEN
    BEGIN
      VAL = (SELECT V FROM VAL_GET(:V$OBJ_ID, 999) WHERE IS_EXISTS = 1);
      IF(VAl IS NULL) THEN VAL = (SELECT V FROM VAL_GET(:V$OBJ_ID, 2) WHERE IS_EXISTS = 1);
    END
    ELSE
    BEGIN
      VAL = (SELECT V FROM VAL_GET(:V$OBJ_ID, 2) WHERE IS_EXISTS = 1);
    END
    SUSPEND;
    TAG_NAME = 'package:institutions:institution:required:ouType:int';
    VAL = (SELECT I FROM VAL_GET(:V$OBJ_ID, 11) WHERE IS_EXISTS = 1);
    SUSPEND;
    TAG_NAME = 'package:institutions:institution:required:ouKind:int';
    VAL = (SELECT I FROM VAL_GET(:V$OBJ_ID, 10) WHERE IS_EXISTS = 1);
    SUSPEND;

    TAG_NAME = 'package:institutions:institution:additional';
    VAL = NULL;
    SUSPEND;

    TAG_NAME = 'package:institutions:institution:additional:field';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'package:institutions:institution:additional:field::name';
    VAL = 'Номер ОУ';
    SUSPEND;
    TAG_NAME = 'package:institutions:institution:additional:field:int';
    VAL = (SELECT V FROM VAL_GET(:V$OBJ_ID, 17) WHERE IS_EXISTS = 1);
    SUSPEND;

    TAG_NAME = 'package:institutions:institution:additional:field';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'package:institutions:institution:additional:field::name';
    VAL = 'Адрес электронной почты';
    SUSPEND;
    TAG_NAME = 'package:institutions:institution:additional:field:string';
    VAL = (SELECT V FROM VAL_GET(:V$OBJ_ID, 35) WHERE IS_EXISTS = 1);
    SUSPEND;

    TAG_NAME = 'package:institutions:institution:additional:field';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'package:institutions:institution:additional:field::name';
    VAL = 'Адрес сайта';
    SUSPEND;
    TAG_NAME = 'package:institutions:institution:additional:field:string';
    VAL = (SELECT V FROM VAL_GET(:V$OBJ_ID, 36) WHERE IS_EXISTS = 1);
    SUSPEND;

    TAG_NAME = 'package:institutions:institution:additional:field';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'package:institutions:institution:additional:field::name';
    VAL = 'ОКТМО';
    SUSPEND;
    TAG_NAME = 'package:institutions:institution:additional:field:string';
    VAL = (SELECT V FROM VAL_GET(:V$OBJ_ID, 2440) WHERE IS_EXISTS = 1);
    SUSPEND;

    TAG_NAME = 'package:institutions:institution:additional:field';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'package:institutions:institution:additional:field::name';
    VAL = 'Должность руководителя';
    SUSPEND;
    TAG_NAME = 'package:institutions:institution:additional:field:string';
    SELECT F, I, O, POST
    FROM R_SPB_POST_DIRECTOR(:V$OBJ_ID, 1)
    INTO :S1, :S2, :S3, :VAL;
    SUSPEND;

    TAG_NAME = 'package:institutions:institution:additional:field';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'package:institutions:institution:additional:field::name';
    VAL = 'ФИО руководителя';
    SUSPEND;
    TAG_NAME = 'package:institutions:institution:additional:field:list';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'package:institutions:institution:additional:field:list:item';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'package:institutions:institution:additional:field:list:item::name';
    VAL = 'Фамилия';
    SUSPEND;
    TAG_NAME = 'package:institutions:institution:additional:field:list:item:string';
    VAL = S1;
    SUSPEND;
    TAG_NAME = 'package:institutions:institution:additional:field:list:item';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'package:institutions:institution:additional:field:list:item::name';
    VAL = 'Имя';
    SUSPEND;
    TAG_NAME = 'package:institutions:institution:additional:field:list:item:string';
    VAL = S2;
    SUSPEND;
    IF(S3 IS NOT NULL) THEN
    BEGIN
      TAG_NAME = 'package:institutions:institution:additional:field:list:item';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'package:institutions:institution:additional:field:list:item::name';
      VAL = 'Отчество';
      SUSPEND;
      TAG_NAME = 'package:institutions:institution:additional:field:list:item:string';
      VAL = S3;
      SUSPEND;
    END

    TAG_NAME = 'package:institutions:institution:additional:field';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'package:institutions:institution:additional:field::name';
    VAL = 'Телефон';
    SUSPEND;
    TAG_NAME = 'package:institutions:institution:additional:field:string';
    VAL = (SELECT V FROM VAL_GET(:V$OBJ_ID, 29) WHERE IS_EXISTS = 1);
    SUSPEND;

    TAG_NAME = 'package:institutions:institution:additional:field';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'package:institutions:institution:additional:field::name';
    VAL = 'ИНН';
    SUSPEND;
    TAG_NAME = 'package:institutions:institution:additional:field:string';
    VAL = (SELECT V FROM VAL_GET(:V$OBJ_ID, 33) WHERE IS_EXISTS = 1);
    SUSPEND;

    TAG_NAME = 'package:institutions:institution:additional:field';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'package:institutions:institution:additional:field::name';
    VAL = 'ОГРН';
    SUSPEND;
    TAG_NAME = 'package:institutions:institution:additional:field:string';
    VAL = (SELECT V FROM VAL_GET(:V$OBJ_ID, 9) WHERE IS_EXISTS = 1);
    SUSPEND;

    TAG_NAME = 'package:institutions:institution:additional:field';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'package:institutions:institution:additional:field::name';
    VAL = 'КПП';
    SUSPEND;
    TAG_NAME = 'package:institutions:institution:additional:field:string';
    VAL = (SELECT V FROM VAL_GET(:V$OBJ_ID, 34) WHERE IS_EXISTS = 1);
    SUSPEND;

    TAG_NAME = 'package:institutions:institution:additional:field';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'package:institutions:institution:additional:field::name';
    VAL = 'ОКПО';
    SUSPEND;
    TAG_NAME = 'package:institutions:institution:additional:field:string';
    VAL = (SELECT V FROM VAL_GET(:V$OBJ_ID, 16) WHERE IS_EXISTS = 1);
    SUSPEND;

    TAG_NAME = 'package:institutions:institution:additional:field';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'package:institutions:institution:additional:field::name';
    VAL = 'ОКОПФ';
    SUSPEND;
    TAG_NAME = 'package:institutions:institution:additional:field:string';
    VAL = (SELECT V FROM VAL_GET(:V$OBJ_ID, 22) WHERE IS_EXISTS = 1);
    SUSPEND;

    TAG_NAME = 'package:institutions:institution:additional:field';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'package:institutions:institution:additional:field::name';
    VAL = 'ОКФС';
    SUSPEND;
    TAG_NAME = 'package:institutions:institution:additional:field:string';
    VAL = (SELECT V FROM VAL_GET(:V$OBJ_ID, 21) WHERE IS_EXISTS = 1);
    SUSPEND;

    TAG_NAME = 'package:institutions:institution:additional:field';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'package:institutions:institution:additional:field::name';
    VAL = 'ОКОГУ';
    SUSPEND;
    TAG_NAME = 'package:institutions:institution:additional:field:string';
    VAL = (SELECT V FROM VAL_GET(:V$OBJ_ID, 19) WHERE IS_EXISTS = 1);
    SUSPEND;

    TAG_NAME = 'package:institutions:institution:additional:field';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'package:institutions:institution:additional:field::name';
    VAL = 'ОКАТО';
    SUSPEND;
    TAG_NAME = 'package:institutions:institution:additional:field:string';
    VAL = (SELECT V FROM VAL_GET(:V$OBJ_ID, 18) WHERE IS_EXISTS = 1);
    SUSPEND;

    TAG_NAME = 'package:institutions:institution:additional:field';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'package:institutions:institution:additional:field::name';
    VAL = 'rosobr_id';
    SUSPEND;
    TAG_NAME = 'package:institutions:institution:additional:field:string';
    VAL = (SELECT V FROM VAL_GET(:V$OBJ_ID, 3350) WHERE IS_EXISTS = 1);
    SUSPEND;

    S = NULL;
    IF(V$LIC_TYPE = 'C') THEN S = (SELECT V FROM VAL_GET(:V$OBJ_ID, 6) WHERE IS_EXISTS = 1);
    ELSE
    BEGIN
      -- Тут берем не подчинение, а вышестоящий орган
      -- Район обрезаем
      -- Изменение от 01.2023 - возвращаем как было
      /*S = (SELECT V FROM VAL_GET(:V$OBJ_ID, 7) WHERE IS_EXISTS = 1);
      IF(POSITION('Администрация ' IN S) > 0) THEN
      BEGIN
        S = REPLACE(S, 'Администрация', '');
        S = REPLACE(S, 'района', '');
        S = REPLACE(S, 'Санкт-Петербурга', '');
        S = REPLACE(S, 'ого', 'ий');
        S = TRIM(S);
      END*/
      SELECT FIRST 1 R.VAL, LV.LISTVAL_ID
      FROM LINKS LP111
      JOIN VALL VL ON VL.OBJ_ID = LP111.PARENT_ID AND VL.PARAM_ID = 665 AND VL.IS_DEL = 0
      JOIN LISTVALS LV ON LV.LISTVAL_ID = VL.LISTVAL_ID
      JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
      WHERE LP111.OBJ_ID = :V$OBJ_ID AND LP111.PARENT_TYPE_ID = 111 AND LP111.DATE_DEL IS NULL
      INTO :S, :V$V;

      IF(V$V = 3387) THEN S = 'Комитет по образованию Санкт-Петербурга';
    END

    IF(S IS NOT NULL) THEN
    BEGIN
      TAG_NAME = 'package:institutions:institution:additional:field';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'package:institutions:institution:additional:field::name';
      VAL = 'Подведомственность ОУО';
      SUSPEND;
      TAG_NAME = 'package:institutions:institution:additional:field:string';
      VAL = S;
      SUSPEND;
    END

    -- Район города
    S = (SELECT V FROM VAL_GET(:V$OBJ_ID, 2163) WHERE IS_EXISTS = 1);

    IF(S IS NOT NULL) THEN
    BEGIN
      TAG_NAME = 'package:institutions:institution:additional:field';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'package:institutions:institution:additional:field::name';
      VAL = 'Район';
      SUSPEND;
      TAG_NAME = 'package:institutions:institution:additional:field:string';
      VAL = S;
      SUSPEND;
    END

    TAG_NAME = 'package:institutions:institution:additional:field';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'package:institutions:institution:additional:field::name';
    VAL = 'Адрес ОУ';
    SUSPEND;
    TAG_NAME = 'package:institutions:institution:additional:field:address';
    VAL = NULL;
    SUSPEND;
    REGION = '';
    DISTRICT = '';
    TOWN = '';
    SETTLEMENT = '';
    STREET = '';
    HOUSE = '';
    LITER = '';
    CORP = '';
    FLAT = '';
    POST_INDEX = '';
    SELECT REGION, DISTRICT, TOWN, SETTLEMENT, STREET, HOUSE, LITER, CORP, FLAT, POST_INDEX
    FROM VALA
    WHERE PARAM_ID = 27 AND OBJ_ID = :V$OBJ_ID AND IS_DEL = 0
    INTO :REGION, :DISTRICT, :TOWN, :SETTLEMENT, :STREET, :HOUSE, :LITER, :CORP, :FLAT, :POST_INDEX;
    TAG_NAME = 'package:institutions:institution:additional:field:address:area';
    VAL = REGION;
    IF(VAL <> '') THEN SUSPEND;
    TAG_NAME = 'package:institutions:institution:additional:field:address:district';
    VAL = DISTRICT;
    IF(VAL <> '') THEN SUSPEND;
    TAG_NAME = 'package:institutions:institution:additional:field:address:city';
    VAL = TOWN;
    IF(VAL <> '') THEN SUSPEND;
    TAG_NAME = 'package:institutions:institution:additional:field:address:settlement';
    VAL = SETTLEMENT;
    IF(VAL <> '') THEN SUSPEND;
    TAG_NAME = 'package:institutions:institution:additional:field:address:street';
    VAL = STREET;
    IF(VAL <> '') THEN SUSPEND;
    TAG_NAME = 'package:institutions:institution:additional:field:address:house';
    VAL = HOUSE;
    IF(VAL <> '') THEN SUSPEND;
    TAG_NAME = 'package:institutions:institution:additional:field:address:liter';
    VAL = LITER;
    IF(VAL <> '') THEN SUSPEND;
    TAG_NAME = 'package:institutions:institution:additional:field:address:corpus';
    VAL = CORP;
    IF(VAL <> '') THEN SUSPEND;
    TAG_NAME = 'package:institutions:institution:additional:field:address:flat';
    VAL = FLAT;
    IF(VAL <> '') THEN SUSPEND;
    TAG_NAME = 'package:institutions:institution:additional:field:address:index';
    VAL = POST_INDEX;
    IF(VAL <> '') THEN SUSPEND;

    TAG_NAME = 'package:institutions:institution:buildings';
    VAL = NULL;
    SUSPEND;
    FOR
      SELECT L16.OBJ_ID
      FROM LINKS L73
      JOIN LINKS L16 ON L16.PARENT_ID = L73.OBJ_ID AND L16.OBJ_TYPE_ID = 16 AND L16.DATE_DEL IS NULL
      WHERE L73.PARENT_ID = :V$OBJ_ID AND L73.OBJ_TYPE_ID = 73 AND L73.DATE_DEL IS NULL
      INTO :V$PARENT_ID
    DO
    BEGIN
      TAG_NAME = 'package:institutions:institution:buildings:building';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'package:institutions:institution:buildings:building::uid';
      VAL = V$PARENT_ID;
      SUSPEND;

      S = (SELECT V FROM VAL_GET(:V$PARENT_ID, 3167) WHERE IS_EXISTS = 1);
      IF(S <> '') THEN
      BEGIN
        TAG_NAME = 'package:institutions:institution:buildings:building:field';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'package:institutions:institution:buildings:building:field::name';
        VAL = 'Кадастровый номер здания';
        SUSPEND;
        TAG_NAME = 'package:institutions:institution:buildings:building:field:string';
        VAL = S;
        SUSPEND;
      END

      S = '';
      SELECT FIRST 1 LV.TAG
      FROM VALL V3168
      JOIN LISTVALS LV ON LV.LISTVAL_ID = V3168.LISTVAL_ID
      WHERE V3168.OBJ_ID = :V$PARENT_ID AND V3168.PARAM_ID = 3168 AND V3168.IS_DEL = 0
      INTO :S;
      IF(S <> '') THEN
      BEGIN
        TAG_NAME = 'package:institutions:institution:buildings:building:field';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'package:institutions:institution:buildings:building:field::name';
        VAL = 'Отрасль';
        SUSPEND;
        TAG_NAME = 'package:institutions:institution:buildings:building:field:int';
        VAL = S;
        SUSPEND;
      END

      D = (SELECT D FROM VAL_GET(:V$PARENT_ID, 493) WHERE IS_EXISTS = 1);
      IF(D IS NOT NULL) THEN
      BEGIN
        TAG_NAME = 'package:institutions:institution:buildings:building:field';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'package:institutions:institution:buildings:building:field::name';
        VAL = 'Год постройки';
        SUSPEND;
        TAG_NAME = 'package:institutions:institution:buildings:building:field:int';
        VAL = EXTRACT(YEAR FROM :D);
        SUSPEND;
      END

      S = '';
      SELECT REGION, DISTRICT, TOWN, SETTLEMENT, STREET, HOUSE, LITER, CORP, FLAT, POST_INDEX, FIAS_UID
      FROM VALA A
      WHERE A.PARAM_ID = 420 AND A.OBJ_ID = :V$PARENT_ID AND A.IS_DEL = 0
      INTO :REGION, :DISTRICT, :TOWN, :SETTLEMENT, :STREET, :HOUSE, :LITER, :CORP, :FLAT, :POST_INDEX, :S;
      IF(S <> '') THEN
      BEGIN
        TAG_NAME = 'package:institutions:institution:buildings:building:field';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'package:institutions:institution:buildings:building:field::name';
        VAL = 'Идентификатор ФИАС';
        SUSPEND;
        TAG_NAME = 'package:institutions:institution:buildings:building:field:string';
        VAL = S;
        SUSPEND;

        TAG_NAME = 'package:institutions:institution:buildings:building:field';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'package:institutions:institution:buildings:building:field::name';
        VAL = 'Адрес';
        SUSPEND;
        TAG_NAME = 'package:institutions:institution:buildings:building:field:address';
        VAL = NULL;
        SUSPEND;

        TAG_NAME = 'package:institutions:institution:buildings:building:field:address:area';
        VAL = REGION;
        IF(VAL <> '') THEN SUSPEND;
        TAG_NAME = 'package:institutions:institution:buildings:building:field:address:district';
        VAL = DISTRICT;
        IF(VAL <> '') THEN SUSPEND;
        TAG_NAME = 'package:institutions:institution:buildings:building:field:address:city';
        VAL = TOWN;
        IF(VAL <> '') THEN SUSPEND;
        TAG_NAME = 'package:institutions:institution:buildings:building:field:address:settlement';
        VAL = SETTLEMENT;
        IF(VAL <> '') THEN SUSPEND;
        TAG_NAME = 'package:institutions:institution:buildings:building:field:address:street';
        VAL = STREET;
        IF(VAL <> '') THEN SUSPEND;
        TAG_NAME = 'package:institutions:institution:buildings:building:field:address:house';
        VAL = HOUSE;
        IF(VAL <> '') THEN SUSPEND;
        TAG_NAME = 'package:institutions:institution:buildings:building:field:address:liter';
        VAL = LITER;
        IF(VAL <> '') THEN SUSPEND;
        TAG_NAME = 'package:institutions:institution:buildings:building:field:address:corpus';
        VAL = CORP;
        IF(VAL <> '') THEN SUSPEND;
        TAG_NAME = 'package:institutions:institution:buildings:building:field:address:flat';
        VAL = FLAT;
        IF(VAL <> '') THEN SUSPEND;
        TAG_NAME = 'package:institutions:institution:buildings:building:field:address:index';
        VAL = POST_INDEX;
        IF(VAL <> '') THEN SUSPEND;
      END

      S = (SELECT V FROM VAL_GET(:V$PARENT_ID, 508) WHERE IS_EXISTS = 1);
      IF(S <> '') THEN
      BEGIN
        TAG_NAME = 'package:institutions:institution:buildings:building:field';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'package:institutions:institution:buildings:building:field::name';
        VAL = 'Этажность';
        SUSPEND;
        TAG_NAME = 'package:institutions:institution:buildings:building:field:int';
        VAL = S;
        SUSPEND;
      END

      D = (SELECT V FROM VAL_GET(:V$PARENT_ID, 3163) WHERE IS_EXISTS = 1);
      IF(D IS NOT NULL) THEN
      BEGIN
        TAG_NAME = 'package:institutions:institution:buildings:building:field';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'package:institutions:institution:buildings:building:field::name';
        VAL = 'Дата начала эксплуатации здания';
        SUSPEND;
        TAG_NAME = 'package:institutions:institution:buildings:building:field:date';
        VAL = (SELECT RESULT FROM DATE2STR(:D));
        SUSPEND;
      END

      D = (SELECT V FROM VAL_GET(:V$PARENT_ID, 3164) WHERE IS_EXISTS = 1);
      IF(D IS NOT NULL) THEN
      BEGIN
        TAG_NAME = 'package:institutions:institution:buildings:building:field';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'package:institutions:institution:buildings:building:field::name';
        VAL = 'Дата завершения эксплуатации здания';
        SUSPEND;
        TAG_NAME = 'package:institutions:institution:buildings:building:field:date';
        VAL = (SELECT RESULT FROM DATE2STR(:D));
        SUSPEND;
      END

      S = (SELECT I FROM VAL_GET(:V$PARENT_ID, 3165) WHERE IS_EXISTS = 1);
      IF(S IS NOT NULL) THEN
      BEGIN
        TAG_NAME = 'package:institutions:institution:buildings:building:field';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'package:institutions:institution:buildings:building:field::name';
        VAL = 'Причина завершения эксплуатации здания';
        SUSPEND;
        TAG_NAME = 'package:institutions:institution:buildings:building:field:int';
        VAL = S;
        SUSPEND;
      END

      S = (SELECT V FROM VAL_GET(:V$PARENT_ID, 496) WHERE IS_EXISTS = 1);
      IF(S IS NOT NULL) THEN
      BEGIN
        TAG_NAME = 'package:institutions:institution:buildings:building:field';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'package:institutions:institution:buildings:building:field::name';
        VAL = 'Площадь общая';
        SUSPEND;
        TAG_NAME = 'package:institutions:institution:buildings:building:field:float';
        VAL = S;
        SUSPEND;
      END

      S = (SELECT V FROM VAL_GET(:V$PARENT_ID, 498) WHERE IS_EXISTS = 1);
      IF(S IS NOT NULL) THEN
      BEGIN
        TAG_NAME = 'package:institutions:institution:buildings:building:field';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'package:institutions:institution:buildings:building:field::name';
        VAL = 'Площадь полезная';
        SUSPEND;
        TAG_NAME = 'package:institutions:institution:buildings:building:field:float';
        VAL = S;
        SUSPEND;
      END

      S = (SELECT V FROM VAL_GET(:V$PARENT_ID, 3166) WHERE IS_EXISTS = 1);
      IF(S IS NOT NULL) THEN
      BEGIN
        TAG_NAME = 'package:institutions:institution:buildings:building:field';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'package:institutions:institution:buildings:building:field::name';
        VAL = 'Площадь застройки';
        SUSPEND;
        TAG_NAME = 'package:institutions:institution:buildings:building:field:float';
        VAL = S;
        SUSPEND;
      END

      S = (SELECT V FROM VAL_GET(:V$PARENT_ID, 497) WHERE IS_EXISTS = 1);
      IF(S IS NOT NULL) THEN
      BEGIN
        TAG_NAME = 'package:institutions:institution:buildings:building:field';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'package:institutions:institution:buildings:building:field::name';
        VAL = 'Объем строительный';
        SUSPEND;
        TAG_NAME = 'package:institutions:institution:buildings:building:field:float';
        VAL = S;
        SUSPEND;
      END

      S = (SELECT V FROM VAL_GET(:V$PARENT_ID, 495) WHERE IS_EXISTS = 1);
      IF(S IS NOT NULL) THEN
      BEGIN
        TAG_NAME = 'package:institutions:institution:buildings:building:field';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'package:institutions:institution:buildings:building:field::name';
        VAL = 'Расчетный срок службы';
        SUSPEND;
        TAG_NAME = 'package:institutions:institution:buildings:building:field:int';
        VAL = S;
        SUSPEND;
      END

      S = (SELECT V FROM VAL_GET(:V$PARENT_ID, 502) WHERE IS_EXISTS = 1);
      IF(S IS NOT NULL) THEN
      BEGIN
        TAG_NAME = 'package:institutions:institution:buildings:building:field';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'package:institutions:institution:buildings:building:field::name';
        VAL = 'Количество мест';
        SUSPEND;
        TAG_NAME = 'package:institutions:institution:buildings:building:field:int';
        VAL = S;
        SUSPEND;
      END
    END
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PD_CONTENT_GET (
    I$PERSON_ID BIGINT,
    I$ZONE SMALLINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(40),
    VAL VARCHAR(2000))
AS
DECLARE VARIABLE V$PERSON_ID BIGINT;
DECLARE VARIABLE V$ROLE SMALLINT;
DECLARE VARIABLE V$PERSON_TYPE BIGINT;
DECLARE VARIABLE V$OU_ID BIGINT;
DECLARE VARIABLE V$YEAR_ID BIGINT;
DECLARE VARIABLE V$YEAR_DATE DATE;
DECLARE VARIABLE V$YEAR_NAME VARCHAR(40);
DECLARE VARIABLE V$GROUP_ID BIGINT;
DECLARE VARIABLE S1 VARCHAR(200);
DECLARE VARIABLE S2 VARCHAR(200);
DECLARE VARIABLE S3 VARCHAR(200);
DECLARE VARIABLE S4 VARCHAR(40);
DECLARE VARIABLE S5 VARCHAR(1000);
begin

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  SELECT FIRST 1 U.OBJ_ID, U.USER_TYPE, O.TYPE_ID
  FROM USERS U
  LEFT JOIN OBJECTS O ON O.OBJ_ID = U.OBJ_ID
  WHERE U.DATE_DEL IS NULL AND U.USER_ID = :I$USER_ID AND U.IS_BLOCKED = 0 AND (U.EXP_DATE IS NULL OR U.EXP_DATE >= CURRENT_DATE)
  INTO :V$PERSON_ID, :V$ROLE, :V$PERSON_TYPE;

  IF(V$ROLE IS NULL) THEN EXCEPTION DATA_ERROR 'Пользователь не идентифицирован как сотрудник или обучающийся';

  I$PERSON_ID = V$PERSON_ID;

  -- Текущий учебный год
  SELECT FIRST 1 L2.OBJ_ID, V1236.LISTVAL_ID, CAST(LV.TAG AS DATE), R.VAL
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$OU_ID, :V$YEAR_ID, :V$YEAR_DATE, :V$YEAR_NAME;

  TAG_NAME = 'name_last';
  VAL = NULL;
  SELECT FIRST 1 V.VAL
  FROM VALS V
  WHERE V.IS_DEL = 0 AND V.OBJ_ID = :I$PERSON_ID AND V.PARAM_ID = 55
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'name_first';
  VAL = NULL;
  SELECT FIRST 1 V.VAL
  FROM VALS V
  WHERE V.IS_DEL = 0 AND V.OBJ_ID = :I$PERSON_ID AND V.PARAM_ID = 56
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'name_mid';
  VAL = NULL;
  SELECT FIRST 1 V.VAL
  FROM VALS V
  WHERE V.IS_DEL = 0 AND V.OBJ_ID = :I$PERSON_ID AND V.PARAM_ID = 57
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'birthdate';
  VAL = NULL;
  SELECT FIRST 1 D.RESULT
  FROM VALD V
  LEFT JOIN DATE2STR(V.VAL) D ON 1 = 1
  WHERE V.IS_DEL = 0 AND V.OBJ_ID = :I$PERSON_ID AND V.PARAM_ID = 89
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'sex';
  VAL = NULL;
  SELECT FIRST 1 V.LISTVAL_ID
  FROM VALL V
  WHERE V.IS_DEL = 0 AND V.OBJ_ID = :I$PERSON_ID AND V.PARAM_ID = 88
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'snils';
  VAL = NULL;
  SELECT FIRST 1 V.VAL
  FROM VALS V
  WHERE V.IS_DEL = 0 AND V.OBJ_ID = :I$PERSON_ID AND V.PARAM_ID = 1409
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'citizenship';
  VAL = NULL;
  SELECT FIRST 1 C.VAL
  FROM VALL V
  LEFT JOIN LISTVAL_TEXT(V.LISTVAL_ID) C ON 1 = 1
  WHERE V.IS_DEL = 0 AND V.OBJ_ID = :I$PERSON_ID AND V.PARAM_ID = 91
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'lang';
  VAL = NULL;
  SELECT FIRST 1 C.VAL
  FROM VALL V
  LEFT JOIN LISTVAL_TEXT(V.LISTVAL_ID) C ON 1 = 1
  WHERE V.IS_DEL = 0 AND V.OBJ_ID = :I$PERSON_ID AND V.PARAM_ID = 127
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'adr_reg';
  VAL = NULL;
  SELECT FIRST 1 V.VAL
  FROM ADR_GET(111, :I$PERSON_ID) V
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'adr_fact';
  VAL = NULL;
  SELECT FIRST 1 V.VAL
  FROM ADR_GET(103, :I$PERSON_ID) V
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'adr_temp';
  VAL = NULL;
  SELECT FIRST 1 V.VAL
  FROM ADR_GET(2357, :I$PERSON_ID) V
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'phone';
  VAL = NULL;
  SELECT FIRST 1 V.VAL
  FROM VALS V
  WHERE V.IS_DEL = 0 AND V.OBJ_ID = :I$PERSON_ID AND V.PARAM_ID = 102
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'email';
  VAL = NULL;
  SELECT FIRST 1 V.VAL
  FROM VALS V
  WHERE V.IS_DEL = 0 AND V.OBJ_ID = :I$PERSON_ID AND V.PARAM_ID = 3076
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'vk_id';
  VAL = NULL;
  SELECT FIRST 1 V.VAL
  FROM VALS V
  WHERE V.IS_DEL = 0 AND V.OBJ_ID = :I$PERSON_ID AND V.PARAM_ID = 3354
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'std_financing';
  VAL = NULL;
  SELECT FIRST 1 C.VAL
  FROM VALL V
  LEFT JOIN LISTVAL_TEXT(V.LISTVAL_ID) C ON 1 = 1
  WHERE V.IS_DEL = 0 AND V.OBJ_ID = :I$PERSON_ID AND V.PARAM_ID = 1812
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'std_form';
  VAL = NULL;
  SELECT FIRST 1 C.VAL
  FROM VALL V
  LEFT JOIN LISTVAL_TEXT(V.LISTVAL_ID) C ON 1 = 1
  WHERE V.IS_DEL = 0 AND V.OBJ_ID = :I$PERSON_ID AND V.PARAM_ID = 80
  INTO :VAL;
  SUSPEND;

  VAL = NULL;
  SELECT FIRST 1 LP9.PARENT_ID, C.CAPTION, CP.SCAPTION
  FROM LINKS LP9
  LEFT JOIN OBJECT_CAPTION_GET(LP9.PARENT_ID) C ON 1 = 1
  LEFT JOIN VALR V53 ON V53.OBJ_ID = LP9.PARENT_ID AND V53.PARAM_ID = 53 AND V53.IS_DEL = 0
  LEFT JOIN OBJECT_CAPTION_GET(V53.VAL) CP ON V53.VAL IS NOT NULL
  WHERE LP9.OBJ_ID = :I$PERSON_ID AND LP9.PARENT_TYPE_ID = 9 AND LP9.DATE_DEL IS NULL
  INTO :V$GROUP_ID, :VAL, :S5;

  TAG_NAME = 'group_name';
  SUSPEND;

  TAG_NAME = 'group_head';
  VAL = S5;
  SUSPEND;

  VAL = NULL;
  S5 = NULL;
  SELECT FIRST 1 VV.VAL, VC.SVAL
  FROM VALL V
  LEFT JOIN LISTVAL_TEXT(V.LISTVAL_ID) VV ON 1 = 1
  JOIN VALS VC ON VC.OBJ_ID = V.OBJ_ID AND VC.PARAM_ID = 2822 AND VC.IS_DEL = 0
  WHERE V.OBJ_ID = :V$GROUP_ID AND V.PARAM_ID IN (2165, 2821, 3367) AND V.IS_DEL = 0
  INTO :VAL, :S5;
  IF(VAL IS NULL) THEN
  SELECT FIRST 1 VVV.VAL, VC.SVAL
  FROM VALR V
  JOIN VALL VV ON VV.OBJ_ID = V.VAL AND VV.PARAM_ID IN (3473, 3474, 3475) AND VV.IS_DEL = 0
  LEFT JOIN LISTVAL_TEXT(VV.LISTVAL_ID) VVV ON 1 = 1
  JOIN VALS VC ON VC.OBJ_ID = V.VAL AND VC.PARAM_ID = 3476 AND VC.IS_DEL = 0
  WHERE V.OBJ_ID = :V$GROUP_ID AND V.PARAM_ID = 3075 AND V.IS_DEL = 0
  INTO :VAL, :S5;

  TAG_NAME = 'spc_name';
  SUSPEND;

  TAG_NAME = 'spc_code';
  VAL = S5;
  SUSPEND;

  TAG_NAME = 'target_org_name';
  VAL = NULL;
  SELECT FIRST 1 V.VAL
  FROM VALS V
  WHERE V.IS_DEL = 0 AND V.OBJ_ID = :I$PERSON_ID AND V.PARAM_ID = 3172
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'documents::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT C.VAL, V442.SVAL, V559.SVAL, D.RESULT, V562.SVAL
    FROM LINKS L79
    JOIN VALL V441 ON V441.OBJ_ID = L79.OBJ_ID AND V441.PARAM_ID = 441 AND V441.IS_DEL = 0
    LEFT JOIN LISTVAL_TEXT(V441.LISTVAL_ID) C ON 1 = 1
    LEFT JOIN VALS V442 ON V442.OBJ_ID = L79.OBJ_ID AND V442.PARAM_ID = 442 AND V442.IS_DEL = 0
    LEFT JOIN VALS V559 ON V559.OBJ_ID = L79.OBJ_ID AND V559.PARAM_ID = 559 AND V559.IS_DEL = 0
    JOIN VALD V560 ON V560.OBJ_ID = L79.OBJ_ID AND V560.PARAM_ID = 560 AND V560.IS_DEL = 0
    LEFT JOIN DATE2STR(V560.VAL) D ON 1 = 1
    LEFT JOIN VALS V562 ON V562.OBJ_ID = L79.OBJ_ID AND V562.PARAM_ID = 562 AND V562.IS_DEL = 0
    JOIN VALL V614 ON V614.OBJ_ID = L79.OBJ_ID AND V614.PARAM_ID = 614 AND V614.IS_DEL = 0 AND V614.LISTVAL_ID IN (1982, 1984)
    WHERE L79.PARENT_ID = :I$PERSON_ID AND L79.OBJ_TYPE_ID = 79 AND L79.DATE_DEL IS NULL
    ORDER BY V560.VAL
    INTO :S1, :S2, :S3, :S4, :S5
  DO
  BEGIN
    TAG_NAME = 'documents:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'documents:r:name';
    VAL = S1;
    SUSPEND;
    TAG_NAME = 'documents:r:serie';
    VAL = S2;
    SUSPEND;
    TAG_NAME = 'documents:r:number';
    VAL = S3;
    SUSPEND;
    TAG_NAME = 'documents:r:date';
    VAL = S4;
    SUSPEND;
    TAG_NAME = 'documents:r:issuer';
    VAL = S5;
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PERIOD_VERIFY (
    I$OBJ_ID BIGINT,
    I$VAL BIGINT)
AS
declare variable V$V1 bigint;
declare variable V$V2 bigint;
declare variable V$V3 bigint;
declare variable V$V4 bigint;
begin

  IF(EXISTS(
    SELECT FIRST 1 1
    FROM LINKS LP151
    JOIN LINKS L154 ON L154.PARENT_ID = LP151.PARENT_ID AND L154.OBJ_TYPE_ID = 154 AND L154.DATE_DEL IS NULL AND L154.OBJ_ID <> LP151.OBJ_ID
    JOIN VALL V1170 ON V1170.OBJ_ID = L154.OBJ_ID AND V1170.PARAM_ID = 1170 AND V1170.IS_DEL = 0 AND V1170.LISTVAL_ID = :I$VAL
    WHERE LP151.OBJ_ID = :I$OBJ_ID AND LP151.PARENT_TYPE_ID = 151 AND LP151.DATE_DEL IS NULL
  ))
  THEN EXCEPTION DATA_ERROR 'Учебный период не должен повторяться в списке';

  IF(I$VAL IN (12, 13, 14, 15)) THEN
  BEGIN
    V$V1 = 12;
    V$V2 = 13;
    V$V3 = 14;
    V$V4 = 15;
  END
  ELSE IF(I$VAL IN (10, 11)) THEN
  BEGIN
    V$V1 = 10;
    V$V2 = 11;
  END
  ELSE IF(I$VAL IN (16, 17, 18)) THEN
  BEGIN
    V$V1 = 16;
    V$V2 = 17;
    V$V3 = 18;
  END
  ELSE IF(I$VAL IN (19, 20)) THEN
  BEGIN
    V$V1 = 19;
    V$V2 = 20;
  END

  IF(EXISTS(
    SELECT FIRST 1 1
    FROM LINKS LP151
    JOIN LINKS L154 ON L154.PARENT_ID = LP151.PARENT_ID AND L154.OBJ_TYPE_ID = 154 AND L154.DATE_DEL IS NULL AND L154.OBJ_ID <> LP151.OBJ_ID
    JOIN VALL V1170 ON V1170.OBJ_ID = L154.OBJ_ID AND V1170.PARAM_ID = 1170 AND V1170.IS_DEL = 0
      AND V1170.LISTVAL_ID <> :V$V1 AND V1170.LISTVAL_ID <> :V$V2
      AND (V1170.LISTVAL_ID <> :V$V3 OR :V$V3 IS NULL)
      AND (V1170.LISTVAL_ID <> :V$V4 OR :V$V4 IS NULL)
    WHERE LP151.OBJ_ID = :I$OBJ_ID AND LP151.PARENT_TYPE_ID = 151 AND LP151.DATE_DEL IS NULL
  ))
  THEN EXCEPTION DATA_ERROR 'Не допускается использование разнородных периодов в одной сетке. Создайте раздельные расписания периодов для четверей, полугодий и т.д.';

  -- Обновляем поле с типом отметки
  IF(I$VAL = 12) THEN I$VAL = 3002;
  ELSE IF(I$VAL = 13) THEN I$VAL = 3003;
  ELSE IF(I$VAL = 14) THEN I$VAL = 3004;
  ELSE IF(I$VAL = 15) THEN I$VAL = 3005;
  ELSE IF(I$VAL = 10) THEN I$VAL = 3009;
  ELSE IF(I$VAL = 11) THEN I$VAL = 3010;
  ELSE IF(I$VAL = 16) THEN I$VAL = 3006;
  ELSE IF(I$VAL = 17) THEN I$VAL = 3007;
  ELSE IF(I$VAL = 18) THEN I$VAL = 3008;
  ELSE IF(I$VAL = 19) THEN I$VAL = 12973;
  ELSE IF(I$VAL = 20) THEN I$VAL = 12974;
  ELSE I$VAL = NULL;

  SELECT 1 FROM VAL_ADD(1171, :I$OBJ_ID, :I$VAL) INTO :V$V1;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PERSON_FMARKS (
    I$UUID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
declare variable V$STUDENT_ID bigint;
declare variable V$SUBJECT_ID bigint;
declare variable V$YEAR integer;
declare variable V$SC varchar(1000);
declare variable V$MARKTYPE_ID bigint;
declare variable V$MARKTYPE varchar(100);
declare variable V$MARKVAL_ID bigint;
declare variable V$MARKVAL varchar(100);
declare variable V$STAGE_ID bigint;
declare variable V$STAGE varchar(100);
declare variable V$DATE timestamp;
declare variable V$EXT smallint;
begin

  I$UUID = UPPER(I$UUID);
  IF(SUBSTRING(I$UUID FROM 1 FOR 1) <> '{') THEN I$UUID = '{' || I$UUID || '}';

  TAG_NAME = 'marks::json&colon;array';
  VAL = 1;
  SUSPEND;

  FOR
    SELECT LPX.OBJ_ID, M.SUBJECT_ID, LY.COST, SC.CAPTION, M.MARKTYPE_ID, RT.VAL, M.MARKVAL_ID, RV.VAL, M.STAGE_ID, RS.VAL, M.DATE_MODIFY, M.IS_EXT
    FROM VALS V2912
    JOIN LINKS LPX ON LPX.OBJ_ID = V2912.OBJ_ID AND LPX.PARENT_TYPE_ID IN (9, 187, 81, 82, 83, 84) AND LPX.DATE_DEL IS NULL
    JOIN VALM M ON M.IS_DEL = 0 AND M.PUPIL_ID = LPX.OBJ_ID
    LEFT JOIN OBJECT_CAPTION_GET(M.SUBJECT_ID) SC ON 1 = 1
    JOIN LISTVALS LY ON LY.LISTVAL_ID = M.YEAR_ID
    JOIN RES RY ON RY.RES_ID = LY.RES_ID AND RY.LANG_CODE = 'RU'
    JOIN LISTVALS LT ON LT.LISTVAL_ID = M.MARKTYPE_ID
    JOIN RES RT ON RT.RES_ID = LT.RES_ID AND RT.LANG_CODE = 'RU'
    JOIN LISTVALS LV ON LV.LISTVAL_ID = M.MARKVAL_ID
    JOIN RES RV ON RV.RES_ID = LV.RES_ID AND RV.LANG_CODE = 'RU'
    LEFT JOIN LISTVALS LS ON LV.LISTVAL_ID = M.STAGE_ID
    LEFT JOIN RES RS ON RS.RES_ID = LS.RES_ID AND RV.LANG_CODE = 'RU'
    WHERE V2912.IS_DEL = 0 AND V2912.PARAM_ID = 2912 AND V2912.VAL = :I$UUID
    INTO :V$STUDENT_ID, :V$SUBJECT_ID, :V$YEAR, :V$SC, :V$MARKTYPE_ID, :V$MARKTYPE, :V$MARKVAL_ID, :V$MARKVAL, :V$STAGE_ID, :V$STAGE, :V$DATE, :V$EXT
  DO
  BEGIN
    TAG_NAME = 'marks:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'marks:r:student_id';
    VAL = V$STUDENT_ID;
    SUSPEND;
    TAG_NAME = 'marks:r:subject_id';
    VAL = V$SUBJECT_ID;
    SUSPEND;
    TAG_NAME = 'marks:r:year';
    VAL = V$YEAR;
    SUSPEND;
    TAG_NAME = 'marks:r:subject_name';
    VAL = V$SC;
    SUSPEND;
    TAG_NAME = 'marks:r:marktype_id';
    VAL = V$MARKTYPE_ID;
    SUSPEND;
    TAG_NAME = 'marks:r:marktype_name';
    VAL = V$MARKTYPE;
    SUSPEND;
    TAG_NAME = 'marks:r:markval_id';
    VAL = V$MARKVAL_ID;
    SUSPEND;
    TAG_NAME = 'marks:r:markval_name';
    VAL = V$MARKVAL;
    SUSPEND;
    TAG_NAME = 'marks:r:stage_id';
    VAL = V$STAGE_ID;
    SUSPEND;
    TAG_NAME = 'marks:r:stage_name';
    VAL = V$STAGE;
    SUSPEND;
    TAG_NAME = 'marks:r:tm';
    VAL = (SELECT VAL FROM DATE2ISO(:V$DATE));
    SUSPEND;
    TAG_NAME = 'marks:r:is_adv';
    VAL = V$EXT;
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PERSON_JOB_DETAILS (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$OU_ID BIGINT;
DECLARE VARIABLE V$PERSON_ID BIGINT;
DECLARE VARIABLE V$DOC_ID BIGINT;
DECLARE VARIABLE S VARCHAR(400);
begin

  SELECT FIRST 1 L2.OBJ_ID
  FROM LINKS L2
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$OU_ID;

  TAG_NAME = 'Полное_наименование_ОУ';
  VAL = NULL;
  SELECT FIRST 1 V5.VAL
  FROM VALS V5
  WHERE V5.OBJ_ID = :V$OU_ID AND V5.PARAM_ID = 5 AND V5.IS_DEL = 0
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'Адрес_ОУ';
  VAL = NULL;
  SELECT FIRST 1 V.VAL
  FROM ADR_GET(27, :V$OU_ID) V
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'ИНН_ОУ';
  VAL = NULL;
  SELECT FIRST 1 V33.VAL
  FROM VALS V33
  WHERE V33.OBJ_ID = :V$OU_ID AND V33.PARAM_ID = 33 AND V33.IS_DEL = 0
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'Телефон_ОУ';
  VAL = NULL;
  SELECT FIRST 1 V29.VAL
  FROM VALS V29
  WHERE V29.OBJ_ID = :V$OU_ID AND V29.PARAM_ID = 29 AND V29.IS_DEL = 0
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'Факс_ОУ';
  VAL = NULL;
  SELECT FIRST 1 V30.VAL
  FROM VALS V30
  WHERE V30.OBJ_ID = :V$OU_ID AND V30.PARAM_ID = 30 AND V30.IS_DEL = 0
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'Должность_руководителя';
  S = NULL;
  VAL = NULL;
  SELECT FIRST 1 C.POST, C.FIO
  FROM R_SPB_POST_DIRECTOR(:V$OU_ID, 1) C
  INTO :VAL, :S;
  SUSPEND;

  TAG_NAME = 'ФИО_руководителя';
  VAL = S;
  SUSPEND;

  -- Данные по сотруднику
  SELECT FIRST 1 LP14.PARENT_ID
  FROM LINKS LP14
  WHERE LP14.OBJ_ID = :I$OBJ_ID AND LP14.PARENT_TYPE_ID = 14 AND LP14.DATE_DEL IS NULL
  INTO :V$PERSON_ID;

  TAG_NAME = 'ФИО_Сотрудника';
  VAL = NULL;
  SELECT FIRST 1 C.C1
  FROM BUILD_REP_FIO(:V$PERSON_ID, 59, 60, 61, 1) C
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'ФИО_Сотрудника_Сокр';
  VAL = NULL;
  SELECT FIRST 1 C.C1
  FROM BUILD_REP_FIO(:V$PERSON_ID, 59, 60, 61, 0) C
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'Адрес_Сотрудника';
  VAL = NULL;
  SELECT FIRST 1 V.VAL
  FROM ADR_GET(262, :V$PERSON_ID) V
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'Телефон_Сотрудника';
  VAL = NULL;
  SELECT FIRST 1 V253.VAL
  FROM VALS V253
  WHERE V253.OBJ_ID = :V$PERSON_ID AND V253.PARAM_ID IN (253, 254) AND V253.IS_DEL = 0
  ORDER BY V253.PARAM_ID
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'Тип_документа';
  VAL = NULL;
  SELECT FIRST 1 L79.OBJ_ID, C.VAL
  FROM LINKS L79
  JOIN VALL V614 ON V614.OBJ_ID = L79.OBJ_ID AND V614.PARAM_ID = 614 AND V614.IS_DEL = 0 AND V614.LISTVAL_ID = 1982
  JOIN VALL V441 ON V441.OBJ_ID = L79.OBJ_ID AND V441.PARAM_ID = 441 AND V441.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V441.LISTVAL_ID
  LEFT JOIN LISTVAL_TEXT(V441.LISTVAL_ID) C ON 1 = 1
  WHERE L79.PARENT_ID = :V$PERSON_ID AND L79.OBJ_TYPE_ID = 79 AND L79.DATE_DEL IS NULL
  ORDER BY LV.COST
  INTO :V$DOC_ID, :VAL;
  SUSPEND;

  TAG_NAME = 'Серия_документа';
  VAL = NULL;
  SELECT FIRST 1 V442.VAL
  FROM VALS V442
  WHERE V442.OBJ_ID = :V$DOC_ID AND V442.PARAM_ID = 442 AND V442.IS_DEL = 0
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'Номер_документа';
  VAL = NULL;
  SELECT FIRST 1 V559.VAL
  FROM VALS V559
  WHERE V559.OBJ_ID = :V$DOC_ID AND V559.PARAM_ID = 559 AND V559.IS_DEL = 0
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'Дата_документа';
  VAL = NULL;
  SELECT FIRST 1 D.RESULT
  FROM VALD V560
  LEFT JOIN DATE2STR(V560.VAL) D ON 1 = 1
  WHERE V560.OBJ_ID = :V$DOC_ID AND V560.PARAM_ID = 560 AND V560.IS_DEL = 0
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'Документ_кем_выдан';
  VAL = NULL;
  SELECT FIRST 1 V562.VAL
  FROM VALS V562
  WHERE V562.OBJ_ID = :V$DOC_ID AND V562.PARAM_ID = 562 AND V562.IS_DEL = 0
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'Дата_договора';
  VAL = NULL;
  SELECT FIRST 1 D.RESULT
  FROM VALD V1639
  LEFT JOIN DATE2STR(V1639.VAL) D ON 1 = 1
  WHERE V1639.OBJ_ID = :I$OBJ_ID AND V1639.PARAM_ID = 1639 AND V1639.IS_DEL = 0
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'Номер_договора';
  VAL = NULL;
  SELECT FIRST 1 V1638.VAL
  FROM VALS V1638
  WHERE V1638.OBJ_ID = :I$OBJ_ID AND V1638.PARAM_ID = 1638 AND V1638.IS_DEL = 0
  INTO :VAL;
  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PERSON_MOVEMENTS_GET (
    I$PARENT_ID FLOAT,
    I$OBJ_ID BIGINT,
    I$LEVEL_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
declare variable V$OU_LICENCE_TYPE char(10);
declare variable V$OBJ_ID bigint;
declare variable V$GROUP_ID bigint;
declare variable V$GROUP_TYPE bigint;
declare variable V$REASON_IN bigint;
declare variable V$STAGE_ID bigint;
declare variable V$DATE_IN date;
declare variable V$ORDER_DATE_IN date;
declare variable V$ORDER_NUM_IN varchar(100);
declare variable V$REASON_OUT bigint;
declare variable V$DATE_OUT date;
declare variable V$ORDER_DATE_OUT date;
declare variable V$ORDER_NUM_OUT varchar(100);
declare variable V$NAME varchar(1000);
declare variable V$TAG varchar(400);
declare variable V$SOURCE_IN bigint;
declare variable V$SOURCE_OUT bigint;
declare variable V$VD smallint;
declare variable V$TYPE_IN bigint;
begin

  V$OU_LICENCE_TYPE = (SELECT STATUS FROM OU_LICENCE_TYPE);

  TAG_NAME = 'ou_type';
  VAL = V$OU_LICENCE_TYPE;
  SUSPEND;

  TAG_NAME = 'reasons::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
    -- Основные
    SELECT LISTVAL_ID, VAL, TAG FROM LISTVALS_LIST(122) WHERE IS_DEL = 0
    -- ГПД
    UNION
    SELECT LISTVAL_ID, VAL, TAG FROM LISTVALS_LIST(230) WHERE IS_DEL = 0
    -- ГУП
    UNION
    SELECT LISTVAL_ID, VAL, TAG FROM LISTVALS_LIST(274) WHERE IS_DEL = 0
    -- Потоки
    UNION
    SELECT LISTVAL_ID, VAL, TAG FROM LISTVALS_LIST(309) WHERE IS_DEL = 0
    -- Семейка
    UNION
    SELECT LISTVAL_ID, VAL, TAG FROM LISTVALS_LIST(319) WHERE IS_DEL = 0
    INTO :V$OBJ_ID, :V$NAME, :V$TAG
  DO
  BEGIN
    TAG_NAME = 'reasons:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'reasons:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'reasons:r:value';
    VAL = V$NAME;
    SUSPEND;
    TAG_NAME = 'reasons:r:tag';
    VAL = V$TAG;
    SUSPEND;
  END

  TAG_NAME = 'stages::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
    SELECT LISTVAL_ID, VAL
    FROM LISTVALS_LIST(25)
    WHERE IS_DEL = 0
    INTO :V$OBJ_ID, :V$NAME
  DO
  BEGIN
    TAG_NAME = 'stages:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'stages:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'stages:r:value';
    VAL = V$NAME;
    SUSPEND;
  END

  TAG_NAME = 'types::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
    SELECT LISTVAL_ID, VAL
    FROM LISTVALS_LIST(32)
    WHERE IS_DEL = 0
    INTO :V$OBJ_ID, :V$NAME
  DO
  BEGIN
    TAG_NAME = 'types:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'types:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'types:r:value';
    VAL = V$NAME;
    SUSPEND;
  END

  TAG_NAME = 'items::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
    SELECT M.OBJ_ID, M.GROUP_ID, O.TYPE_ID, M.STAGE_ID, M.REASON_IN, M.DATE_IN, M.ORDER_DATE_IN, M.ORDER_NUM_IN,
      M.REASON_OUT, M.DATE_OUT, M.ORDER_DATE_OUT, M.ORDER_NUM_OUT, M.NAME_IN, M.SOURCE_IN, M.SOURCE_OUT, M.IS_VD, M.TYPE_IN
    FROM PERSON_MOVEMENTS M
    LEFT JOIN OBJECTS O ON O.OBJ_ID = M.GROUP_ID
    WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :I$OBJ_ID AND O.TYPE_ID <> 338 -- кроме выбытия на дистант
    ORDER BY M.OBJ_ID
    INTO :V$OBJ_ID, :V$GROUP_ID, V$GROUP_TYPE, :V$STAGE_ID, :V$REASON_IN, :V$DATE_IN, :V$ORDER_DATE_IN, :V$ORDER_NUM_IN,
      :V$REASON_OUT, :V$DATE_OUT, :V$ORDER_DATE_OUT, :V$ORDER_NUM_OUT, :V$NAME, :V$SOURCE_IN, :V$SOURCE_IN, :V$VD, :V$TYPE_IN
  DO
  BEGIN
    TAG_NAME = 'items:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'items:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'items:r:stage_id';
    VAL = V$STAGE_ID;
    SUSPEND;
    TAG_NAME = 'items:r:grade_id';
    VAL = V$GROUP_ID;
    SUSPEND;
    TAG_NAME = 'items:r:grade_type_id';
    VAL = V$GROUP_TYPE;
    SUSPEND;
    -- Для группы по предмету добавляем название предмета
    TAG_NAME = 'items:r:name';
    IF(V$GROUP_TYPE = 179) THEN
    BEGIN
      V$TAG = NULL;
      SELECT FIRST 1 C.CAPTION
      FROM CJ2_JOURNAL J
      LEFT JOIN OBJECT_CAPTION_GET(J.SUBJECT_ID) C ON 1 = 1
      WHERE J.GRADE_ID = :V$GROUP_ID AND J.DATE_DEL IS NULL AND J.SUBJECT_ID IS NOT NULL
      INTO :V$TAG;
      IF(V$TAG IS NOT NULL) THEN V$NAME = V$NAME || ' (' || V$TAG || ')';
    END
    VAL = V$NAME;
    SUSPEND;
    TAG_NAME = 'items:r:reason_in';
    VAL = V$REASON_IN;
    SUSPEND;
    TAG_NAME = 'items:r:date_in';
    VAL = (SELECT VAL FROM DATE2ISO(:V$DATE_IN));
    SUSPEND;
    TAG_NAME = 'items:r:order_date_in';
    VAL = (SELECT VAL FROM DATE2ISO(:V$ORDER_DATE_IN));
    SUSPEND;
    TAG_NAME = 'items:r:order_num_in';
    VAL = V$ORDER_NUM_IN;
    SUSPEND;
    TAG_NAME = 'items:r:reason_out';
    VAL = V$REASON_OUT;
    SUSPEND;
    TAG_NAME = 'items:r:date_out';
    VAL = (SELECT VAL FROM DATE2ISO(:V$DATE_OUT));
    SUSPEND;
    TAG_NAME = 'items:r:order_date_out';
    VAL = (SELECT VAL FROM DATE2ISO(:V$ORDER_DATE_OUT));
    SUSPEND;
    TAG_NAME = 'items:r:order_num_out';
    VAL = V$ORDER_NUM_OUT;
    SUSPEND;
    TAG_NAME = 'items:r:vd';
    VAL = V$VD;
    SUSPEND;
    TAG_NAME = 'items:r:type';
    VAL = V$TYPE_IN;
    SUSPEND;
    TAG_NAME = 'items:r:source_in';
    VAL = V$SOURCE_IN;
    SUSPEND;
    TAG_NAME = 'items:r:source_out';
    VAL = V$SOURCE_OUT;
    SUSPEND;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PERSON_PATH_GET (
    REG_ID VARCHAR(40))
RETURNS (
    OBJ_ID BIGINT,
    TYPE_ID BIGINT)
AS
declare variable TMP bigint;
begin

  SELECT FIRST 1 O.OBJ_ID, O.TYPE_ID
  FROM VALS VR
  JOIN OBJECTS O ON O.OBJ_ID = VR.OBJ_ID
  WHERE VR.IS_DEL = 0 AND VR.PARAM_ID IN (2912, 2915, 2917) AND (VR.VAL = :REG_ID OR VR.VAL = '{' || :REG_ID || '}')
  INTO :OBJ_ID, :TYPE_ID;

  SUSPEND;

    -- Для сотрудников надо выдать фейковый уровень
  IF(TYPE_ID = 14) THEN
  BEGIN
    TMP = OBJ_ID;
    OBJ_ID = -1;
    TYPE_ID = -1;
    SUSPEND;
    OBJ_ID = TMP;
  END

  WHILE(OBJ_ID IS NOT NULL) DO
  BEGIN

    TMP = OBJ_ID;
    OBJ_ID = NULL;

    SELECT FIRST 1 LP.PARENT_ID, LP.PARENT_TYPE_ID
    FROM LINKS LP
    WHERE LP.OBJ_ID = :TMP AND LP.DATE_DEL IS NULL AND LP.PARENT_TYPE_ID IN (2, 211, 10, 9, 8, 7, 125, 187, 243, 242, 1, 81, 82, 83, 84, 78, 46)
    ORDER BY LP.PARENT_TYPE_ID -- сортировка, чтобы кружки оказались после классов
    INTO :OBJ_ID, :TYPE_ID;

    IF(OBJ_ID IS NOT NULL) THEN SUSPEND;

  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PF_BUILDINGS (
    I$OBJ_ID BIGINT,
    I$BLOCK_NAME VARCHAR(40),
    I$BLOCK_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(1000))
AS
declare variable V$TYPE_ID bigint;
begin

  SELECT TYPE_ID
  FROM OBJECTS
  WHERE OBJ_ID = :I$OBJ_ID
  INTO :V$TYPE_ID;

  IF(V$TYPE_ID = 2) THEN
  BEGIN
    FOR
      SELECT D.TAG_NAME, D.VAL
      FROM PF_BUILDINGS_OU(:I$OBJ_ID, :I$BLOCK_NAME, :I$BLOCK_ID, :I$USER_ID) D
      INTO :TAG_NAME, :VAL
    DO
    BEGIN
      SUSPEND;
    END
  END
  ELSE IF(V$TYPE_ID = 111) THEN
  BEGIN
    FOR
      SELECT D.TAG_NAME, D.VAL
      FROM PF_BUILDINGS_DIST(:I$OBJ_ID, :I$BLOCK_NAME, :I$BLOCK_ID, :I$USER_ID) D
      INTO :TAG_NAME, :VAL
    DO
    BEGIN
      SUSPEND;
    END
  END
  ELSE IF(V$TYPE_ID = 112) THEN
  BEGIN
    FOR
      SELECT D.TAG_NAME, D.VAL
      FROM PF_BUILDINGS_RGN(:I$OBJ_ID, :I$BLOCK_NAME, :I$BLOCK_ID, :I$USER_ID) D
      INTO :TAG_NAME, :VAL
    DO
    BEGIN
      SUSPEND;
    END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PF_BUILDINGS_DIST (
    I$OBJ_ID BIGINT,
    I$BLOCK_NAME VARCHAR(40),
    I$BLOCK_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(1000))
AS
declare variable V$VAL bigint;
declare variable V$VAL2 bigint;
declare variable V$VAL3 bigint;
declare variable V$VAL4 bigint;
declare variable V$VAL5 double precision;
declare variable V$VAL6 bigint;
declare variable V$VAL7 bigint;
declare variable S varchar(1000);
declare variable V$TYPE_ID1 bigint;
declare variable V$TYPE_ID2 bigint;
declare variable V$MID_TYPE bigint;
declare variable V$OBJ_ID bigint;
declare variable V$PARAM_ID bigint;
declare variable V$TYPE bigint;
declare variable V$T bigint;
declare variable V$MASTER_ID bigint;
begin

  IF(I$BLOCK_NAME IS NULL) THEN
  BEGIN
    -- Оглавление
    TAG_NAME = 'dashboard::json&colon;array';
    VAL = 1;
    SUSPEND;

    -- Количество и площадь зданий, площадь территории, количество учебных мест
    V$VAL = NULL;
    SELECT COUNT(*), SUM(IIF(V485.LISTVAL_ID = 1093, 1, 0)), SUM(V496.VAL), SUM(IIF(V485.LISTVAL_ID = 1093, V496.VAL, 0)), SUM(V520.VAL), SUM(V502.VAL), SUM(V503.VAL)
    FROM LINKS L2
    JOIN LINKS L73 ON L73.PARENT_ID = L2.OBJ_ID AND L73.OBJ_TYPE_ID = 73 AND L73.DATE_DEL IS NULL
    JOIN LINKS L16 ON L16.PARENT_ID = L73.OBJ_ID AND L16.OBJ_TYPE_ID = 16 AND L16.DATE_DEL IS NULL
    JOIN VALL V485 ON V485.OBJ_ID = L16.OBJ_ID AND V485.PARAM_ID = 485 AND V485.IS_DEL = 0
    JOIN VALF V496 ON V496.OBJ_ID = L16.OBJ_ID AND V496.PARAM_ID = 496 AND V496.IS_DEL = 0
    LEFT JOIN VALF V520 ON V520.OBJ_ID = L16.OBJ_ID AND V520.PARAM_ID = 520 AND V520.IS_DEL = 0
    LEFT JOIN VALI V502 ON V502.OBJ_ID = L16.OBJ_ID AND V502.PARAM_ID = 502 AND V502.IS_DEL = 0
    LEFT JOIN VALI V503 ON V503.OBJ_ID = L16.OBJ_ID AND V503.PARAM_ID = 503 AND V503.IS_DEL = 0
    LEFT JOIN VALD V3164 ON V3164.OBJ_ID = L16.OBJ_ID AND V3164.PARAM_ID = 3164 AND V3164.IS_DEL = 0 -- дата завершения эксплуатации
    WHERE L2.PARENT_ID = :I$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND V3164.VAL IS NULL
    INTO :V$VAL, :V$VAL2, :V$VAL3, :V$VAL4, :V$VAL5, :V$VAL6, :V$VAL7;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'buildings';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '16';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'building';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#410093';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Количество зданий';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'buildings';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '16+485';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'university';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#410093';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Количество учебных зданий';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL2;
    SUSPEND;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'buildings';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '16+496';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'chart area';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#1877F2';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Общая площадь зданий';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL3;
    SUSPEND;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'buildings';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '16+496';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'chart area';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#1877F2';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Общая площадь учебных зданий';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL4;
    SUSPEND;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'buildings';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '16+520';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'globe';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#25D366';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Площадь территории';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = CAST(V$VAL5 AS NUMERIC(18, 2));
    SUSPEND;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'buildings';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '16+502';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'child';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#FF6600';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Количество учебных мест (проектное)';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL6;
    SUSPEND;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'buildings';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '16+503';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'child';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#FF6600';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Количество учебных мест (нормативное)';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL7;
    SUSPEND;

    -- Количество подразделений
    SELECT COUNT(*)
    FROM LINKS L2
    JOIN LINKS L211 ON L211.PARENT_ID = L2.OBJ_ID AND L211.OBJ_TYPE_ID = 211 AND L211.DATE_DEL IS NULL
    WHERE L2.PARENT_ID = :I$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'sections';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '211';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'boxes';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#34465D';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Количество подразделений 1 уровня';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

  END
  ELSE
  BEGIN

    TAG_NAME = 'title';
    VAL = 'Здания, помещения и подразделения';
    SUSPEND;

    TAG_NAME = 'has_caption';
    VAL = 1;
    SUSPEND;

    TAG_NAME = 'columns::json&colon;array';
    VAL = 1;
    SUSPEND;

    TAG_NAME = 'columns:r'; VAL = NULL; SUSPEND;
    TAG_NAME = 'columns:r:type_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:param_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:type'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:name'; VAL = 'Количество зданий'; SUSPEND;

    TAG_NAME = 'columns:r'; VAL = NULL; SUSPEND;
    TAG_NAME = 'columns:r:type_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:param_id'; VAL = '2'; SUSPEND;
    TAG_NAME = 'columns:r:type'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:name'; VAL = 'Количество учебных зданий'; SUSPEND;

    TAG_NAME = 'columns:r'; VAL = NULL; SUSPEND;
    TAG_NAME = 'columns:r:type_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:param_id'; VAL = '3'; SUSPEND;
    TAG_NAME = 'columns:r:type'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:name'; VAL = 'Общая площадь зданий'; SUSPEND;

    TAG_NAME = 'columns:r'; VAL = NULL; SUSPEND;
    TAG_NAME = 'columns:r:type_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:param_id'; VAL = '4'; SUSPEND;
    TAG_NAME = 'columns:r:type'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:name'; VAL = 'Общая площадь учебных зданий'; SUSPEND;

    TAG_NAME = 'columns:r'; VAL = NULL; SUSPEND;
    TAG_NAME = 'columns:r:type_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:param_id'; VAL = '5'; SUSPEND;
    TAG_NAME = 'columns:r:type'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:name'; VAL = 'Площадь территории'; SUSPEND;

    TAG_NAME = 'columns:r'; VAL = NULL; SUSPEND;
    TAG_NAME = 'columns:r:type_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:param_id'; VAL = '6'; SUSPEND;
    TAG_NAME = 'columns:r:type'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:name'; VAL = 'Количество учебных место (проектная)'; SUSPEND;

    TAG_NAME = 'columns:r'; VAL = NULL; SUSPEND;
    TAG_NAME = 'columns:r:type_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:param_id'; VAL = '7'; SUSPEND;
    TAG_NAME = 'columns:r:type'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:name'; VAL = 'Количество учебных мест (нормативное)'; SUSPEND;

    TAG_NAME = 'columns:r'; VAL = NULL; SUSPEND;
    TAG_NAME = 'columns:r:type_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:param_id'; VAL = '8'; SUSPEND;
    TAG_NAME = 'columns:r:type'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:name'; VAL = 'Количество подразделений 1 уровня'; SUSPEND;

    -- Развертка по районам
    TAG_NAME = 'rows::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT L2.OBJ_ID, L2.OBJ_TYPE_ID, C.CAPTION
      FROM LINKS L2
      LEFT JOIN OBJECT_CAPTION_GET(L2.OBJ_ID) C ON 1 = 1
      WHERE L2.PARENT_ID = :I$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      ORDER BY 3
      INTO :V$OBJ_ID, :V$TYPE, :S
    DO
    BEGIN
      TAG_NAME = 'rows:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'rows:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'rows:r:type_id';
      VAL = '1';
      SUSPEND;
      TAG_NAME = 'rows:r:caption';
      VAL = S;
      SUSPEND;

      -- Счетчики
      V$VAL = NULL;
      SELECT COUNT(*), SUM(IIF(V485.LISTVAL_ID = 1093, 1, 0)), SUM(V496.VAL), SUM(IIF(V485.LISTVAL_ID = 1093, V496.VAL, 0)), SUM(V520.VAL), SUM(V502.VAL), SUM(V503.VAL)
      FROM LINKS L73
      JOIN LINKS L16 ON L16.PARENT_ID = L73.OBJ_ID AND L16.OBJ_TYPE_ID = 16 AND L16.DATE_DEL IS NULL
      JOIN VALL V485 ON V485.OBJ_ID = L16.OBJ_ID AND V485.PARAM_ID = 485 AND V485.IS_DEL = 0
      JOIN VALF V496 ON V496.OBJ_ID = L16.OBJ_ID AND V496.PARAM_ID = 496 AND V496.IS_DEL = 0
      LEFT JOIN VALF V520 ON V520.OBJ_ID = L16.OBJ_ID AND V520.PARAM_ID = 520 AND V520.IS_DEL = 0
      LEFT JOIN VALI V502 ON V502.OBJ_ID = L16.OBJ_ID AND V502.PARAM_ID = 502 AND V502.IS_DEL = 0
      LEFT JOIN VALI V503 ON V503.OBJ_ID = L16.OBJ_ID AND V503.PARAM_ID = 503 AND V503.IS_DEL = 0
      LEFT JOIN VALD V3164 ON V3164.OBJ_ID = L16.OBJ_ID AND V3164.PARAM_ID = 3164 AND V3164.IS_DEL = 0 -- дата завершения эксплуатации
      WHERE L73.PARENT_ID = :V$OBJ_ID AND L73.OBJ_TYPE_ID = 73 AND L73.DATE_DEL IS NULL AND V3164.VAL IS NULL
      INTO :V$VAL, :V$VAL2, :V$VAL3, :V$VAL4, :V$VAL5, :V$VAL6, :V$VAL7;

      TAG_NAME = 'rows:r:p1';
      VAL = V$VAL;
      SUSPEND;
      TAG_NAME = 'rows:r:p2';
      VAL = V$VAL2;
      SUSPEND;
      TAG_NAME = 'rows:r:p3';
      VAL = V$VAL3;
      SUSPEND;
      TAG_NAME = 'rows:r:p4';
      VAL = V$VAL4;
      SUSPEND;
      TAG_NAME = 'rows:r:p5';
      VAL = V$VAL5;
      SUSPEND;
      TAG_NAME = 'rows:r:p6';
      VAL = V$VAL6;
      SUSPEND;

      -- Количество подразделений
      SELECT COUNT(*)
      FROM LINKS L211
      WHERE L211.PARENT_ID = :V$OBJ_ID AND L211.OBJ_TYPE_ID = 211 AND L211.DATE_DEL IS NULL
      INTO :V$VAL;
      TAG_NAME = 'rows:r:p7';
      VAL = V$VAL;
      SUSPEND;

    END

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PF_BUILDINGS_OU (
    I$OBJ_ID BIGINT,
    I$BLOCK_NAME VARCHAR(40),
    I$BLOCK_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(1000))
AS
declare variable V$VAL bigint;
declare variable V$VAL2 bigint;
declare variable V$VAL3 bigint;
declare variable V$VAL4 bigint;
declare variable V$VAL5 float;
declare variable V$VAL6 bigint;
declare variable V$VAL7 bigint;
declare variable S varchar(1000);
declare variable V$TYPE_ID1 bigint;
declare variable V$TYPE_ID2 bigint;
declare variable V$MID_TYPE bigint;
declare variable V$OBJ_ID bigint;
declare variable V$PARAM_ID bigint;
declare variable V$TYPE bigint;
declare variable V$T bigint;
declare variable V$MASTER_ID bigint;
begin

  IF(I$BLOCK_NAME IS NULL) THEN
  BEGIN
    -- Оглавление
    TAG_NAME = 'dashboard::json&colon;array';
    VAL = 1;
    SUSPEND;

    -- Количество и площадь зданий, площадь территории, количество учебных мест
    V$VAL = NULL;
    SELECT COUNT(*), SUM(IIF(V485.LISTVAL_ID = 1093, 1, 0)), SUM(V496.VAL), SUM(IIF(V485.LISTVAL_ID = 1093, V496.VAL, 0)), SUM(V520.VAL), SUM(V502.VAL), SUM(V503.VAL)
    FROM LINKS L73
    JOIN LINKS L16 ON L16.PARENT_ID = L73.OBJ_ID AND L16.OBJ_TYPE_ID = 16 AND L16.DATE_DEL IS NULL
    JOIN VALL V485 ON V485.OBJ_ID = L16.OBJ_ID AND V485.PARAM_ID = 485 AND V485.IS_DEL = 0
    JOIN VALF V496 ON V496.OBJ_ID = L16.OBJ_ID AND V496.PARAM_ID = 496 AND V496.IS_DEL = 0
    LEFT JOIN VALF V520 ON V520.OBJ_ID = L16.OBJ_ID AND V520.PARAM_ID = 520 AND V520.IS_DEL = 0
    LEFT JOIN VALI V502 ON V502.OBJ_ID = L16.OBJ_ID AND V502.PARAM_ID = 502 AND V502.IS_DEL = 0
    LEFT JOIN VALI V503 ON V503.OBJ_ID = L16.OBJ_ID AND V503.PARAM_ID = 503 AND V503.IS_DEL = 0
    LEFT JOIN VALD V3164 ON V3164.OBJ_ID = L16.OBJ_ID AND V3164.PARAM_ID = 3164 AND V3164.IS_DEL = 0 -- дата завершения эксплуатации
    WHERE L73.PARENT_ID = :I$OBJ_ID AND L73.OBJ_TYPE_ID = 73 AND L73.DATE_DEL IS NULL AND V3164.VAL IS NULL
    INTO :V$VAL, :V$VAL2, :V$VAL3, :V$VAL4, :V$VAL5, :V$VAL6, :V$VAL7;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'buildings';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '16';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'building';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#410093';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Количество зданий';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'buildings';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '16+485';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'university';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#410093';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Количество учебных зданий';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL2;
    SUSPEND;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'buildings';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '16+496';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'chart area';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#1877F2';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Общая площадь зданий';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL3;
    SUSPEND;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'buildings';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '16+496';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'chart area';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#1877F2';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Общая площадь учебных зданий';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL4;
    SUSPEND;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'buildings';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '16+520';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'globe';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#25D366';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Площадь территории';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = CAST(V$VAL5 AS NUMERIC(18, 2));
    SUSPEND;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'buildings';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '16+502';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'child';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#FF6600';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Количество учебных мест (проектное)';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL6;
    SUSPEND;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'buildings';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '16+503';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'child';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#FF6600';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Количество учебных мест (нормативное)';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL7;
    SUSPEND;

    -- Количество подразделений
    SELECT COUNT(*)
    FROM LINKS L211
    WHERE L211.PARENT_ID = :I$OBJ_ID AND L211.OBJ_TYPE_ID = 211 AND L211.DATE_DEL IS NULL
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'sections';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '211';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'boxes';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#34465D';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Количество подразделений 1 уровня';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

  END
  ELSE
  BEGIN

    TAG_NAME = 'title';
    IF(I$BLOCK_NAME = 'buildings') THEN
    BEGIN
      VAL = 'Здания и помещения';
      V$TYPE_ID1 = 16;
      V$MID_TYPE = 73;
    END
    ELSE IF(I$BLOCK_NAME = 'sections') THEN
    BEGIN
      VAL = 'Подразделения';
      V$TYPE_ID1 = 211;
    END
    ELSE VAL = '???';
    SUSPEND;

    TAG_NAME = 'has_caption';
    VAL = IIF(V$MID_TYPE IS NULL, 0, 1);
    SUSPEND;

    -- Описание полей
    TAG_NAME = 'columns::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT P.TYPE_ID, P.PARAM_ID, P.PARAM_TYPE, R.VAL
      FROM PARAMS P
      JOIN RES R ON R.RES_ID = P.RES_ID AND R.LANG_CODE = 'RU'
      WHERE P.IS_DEL = 0 AND (P.TYPE_ID = :V$TYPE_ID1 OR P.TYPE_ID = :V$TYPE_ID2)
        AND P.PARAM_ID IN (421, 420, 485, 508, 520, 500, 501, 502, 503, 496, 497, 498, 493, 494, 1791, 1792, 2102, 2182)
      ORDER BY 1, 2
      INTO :V$TYPE, :V$PARAM_ID, :V$T, :S
    DO
    BEGIN
      TAG_NAME = 'columns:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'columns:r:type_id';
      VAL = V$TYPE;
      SUSPEND;
      TAG_NAME = 'columns:r:param_id';
      VAL = V$PARAM_ID;
      SUSPEND;
      TAG_NAME = 'columns:r:type';
      VAL = V$T;
      SUSPEND;
      TAG_NAME = 'columns:r:name';
      VAL = S;
      SUSPEND;
    END

    -- Данные
    TAG_NAME = 'rows::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT NULL, LD.OBJ_ID, LD.OBJ_TYPE_ID
      FROM LINKS LD
      WHERE LD.PARENT_ID = :I$OBJ_ID AND LD.DATE_DEL IS NULL AND (LD.OBJ_TYPE_ID = :V$TYPE_ID1 OR LD.OBJ_TYPE_ID = :V$TYPE_ID2)
      UNION
      SELECT LM.OBJ_ID, LD.OBJ_ID, LD.OBJ_TYPE_ID
      FROM LINKS LM
      JOIN LINKS LD ON LD.PARENT_ID = LM.OBJ_ID AND LD.DATE_DEL IS NULL AND (LD.OBJ_TYPE_ID = :V$TYPE_ID1 OR LD.OBJ_TYPE_ID = :V$TYPE_ID2)
      WHERE LM.PARENT_ID = :I$OBJ_ID AND LM.DATE_DEL IS NULL AND LM.OBJ_TYPE_ID = :V$MID_TYPE
      ORDER BY 1, 3, 2
      INTO :V$MASTER_ID, :V$OBJ_ID, :V$TYPE
    DO
    BEGIN
      TAG_NAME = 'rows:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'rows:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'rows:r:type_id';
      VAL = V$TYPE;
      SUSPEND;
      IF(V$MID_TYPE IS NOT NULL) THEN
      BEGIN
        TAG_NAME = 'rows:r:caption';
        VAL = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$MASTER_ID));
        SUSPEND;
      END
      FOR
        SELECT P.PARAM_ID, IIF(V.IS_EXISTS = 1, V.V, NULL)
        FROM PARAMS P
        LEFT JOIN VAL_GET(:V$OBJ_ID, P.PARAM_ID) V ON 1 = 1
        WHERE P.TYPE_ID = :V$TYPE AND P.IS_DEL = 0
        ORDER BY P.GRID_ORDER
        INTO :V$PARAM_ID, :S
      DO
      BEGIN
        TAG_NAME = 'rows:r:p' || V$PARAM_ID;
        VAL = S;
        SUSPEND;
      END
    END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PF_BUILDINGS_RGN (
    I$OBJ_ID BIGINT,
    I$BLOCK_NAME VARCHAR(40),
    I$BLOCK_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(1000))
AS
declare variable V bigint;
declare variable V$VAL bigint;
declare variable V$VAL2 bigint;
declare variable V$VAL3 bigint;
declare variable V$VAL4 bigint;
declare variable V$VAL5 double precision;
declare variable V$VAL6 bigint;
declare variable V$VAL7 bigint;
declare variable S varchar(1000);
declare variable V$TYPE_ID1 bigint;
declare variable V$TYPE_ID2 bigint;
declare variable V$MID_TYPE bigint;
declare variable V$OBJ_ID bigint;
declare variable V$PARAM_ID bigint;
declare variable V$TYPE bigint;
declare variable V$T bigint;
declare variable V$MASTER_ID bigint;
begin

  IF(I$BLOCK_NAME IS NULL) THEN
  BEGIN
    -- Оглавление
    TAG_NAME = 'dashboard::json&colon;array';
    VAL = 1;
    SUSPEND;

    -- Количество и площадь зданий, площадь территории, количество учебных мест
    V$VAL = NULL;
    SELECT COUNT(*), SUM(IIF(V485.LISTVAL_ID = 1093, 1, 0)), SUM(V496.VAL), SUM(IIF(V485.LISTVAL_ID = 1093, V496.VAL, 0)), SUM(V520.VAL), SUM(V502.VAL), SUM(V503.VAL)
    FROM LINKS L111
    JOIN LINKS L2 ON L2.PARENT_ID = L111.OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    JOIN LINKS L73 ON L73.PARENT_ID = L2.OBJ_ID AND L73.OBJ_TYPE_ID = 73 AND L73.DATE_DEL IS NULL
    JOIN LINKS L16 ON L16.PARENT_ID = L73.OBJ_ID AND L16.OBJ_TYPE_ID = 16 AND L16.DATE_DEL IS NULL
    JOIN VALL V485 ON V485.OBJ_ID = L16.OBJ_ID AND V485.PARAM_ID = 485 AND V485.IS_DEL = 0
    JOIN VALF V496 ON V496.OBJ_ID = L16.OBJ_ID AND V496.PARAM_ID = 496 AND V496.IS_DEL = 0
    LEFT JOIN VALF V520 ON V520.OBJ_ID = L16.OBJ_ID AND V520.PARAM_ID = 520 AND V520.IS_DEL = 0
    LEFT JOIN VALI V502 ON V502.OBJ_ID = L16.OBJ_ID AND V502.PARAM_ID = 502 AND V502.IS_DEL = 0
    LEFT JOIN VALI V503 ON V503.OBJ_ID = L16.OBJ_ID AND V503.PARAM_ID = 503 AND V503.IS_DEL = 0
    LEFT JOIN VALD V3164 ON V3164.OBJ_ID = L16.OBJ_ID AND V3164.PARAM_ID = 3164 AND V3164.IS_DEL = 0 -- дата завершения эксплуатации
    WHERE L111.PARENT_ID = :I$OBJ_ID AND L111.OBJ_TYPE_ID = 111 AND L111.DATE_DEL IS NULL AND V3164.VAL IS NULL
    INTO :V$VAL, :V$VAL2, :V$VAL3, :V$VAL4, :V$VAL5, :V$VAL6, :V$VAL7;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'buildings';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '16';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'building';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#410093';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Количество зданий';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'buildings';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '16+485';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'university';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#410093';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Количество учебных зданий';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL2;
    SUSPEND;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'buildings';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '16+496';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'chart area';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#1877F2';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Общая площадь зданий';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL3;
    SUSPEND;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'buildings';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '16+496';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'chart area';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#1877F2';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Общая площадь учебных зданий';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL4;
    SUSPEND;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'buildings';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '16+520';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'globe';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#25D366';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Площадь территории';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = CAST(V$VAL5 AS NUMERIC(18, 2));
    SUSPEND;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'buildings';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '16+502';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'child';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#FF6600';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Количество учебных мест (проектное)';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL6;
    SUSPEND;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'buildings';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '16+503';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'child';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#FF6600';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Количество учебных мест (нормативное)';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL7;
    SUSPEND;

    -- Количество подразделений
    SELECT COUNT(*)
    FROM LINKS L111
    JOIN LINKS L2 ON L2.PARENT_ID = L111.OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    JOIN LINKS L211 ON L211.PARENT_ID = L2.OBJ_ID AND L211.OBJ_TYPE_ID = 211 AND L211.DATE_DEL IS NULL
    WHERE L111.PARENT_ID = :I$OBJ_ID AND L111.OBJ_TYPE_ID = 111 AND L111.DATE_DEL IS NULL
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'sections';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '211';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'boxes';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#34465D';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Количество подразделений 1 уровня';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

  END
  ELSE
  BEGIN

    TAG_NAME = 'title';
    VAL = 'Здания, помещения и подразделения';
    SUSPEND;

    TAG_NAME = 'has_caption';
    VAL = 1;
    SUSPEND;

    TAG_NAME = 'columns::json&colon;array';
    VAL = 1;
    SUSPEND;

    TAG_NAME = 'columns:r'; VAL = NULL; SUSPEND;
    TAG_NAME = 'columns:r:type_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:param_id'; VAL = '0'; SUSPEND;
    TAG_NAME = 'columns:r:type'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:name'; VAL = 'Количество ОУ'; SUSPEND;

    TAG_NAME = 'columns:r'; VAL = NULL; SUSPEND;
    TAG_NAME = 'columns:r:type_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:param_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:type'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:name'; VAL = 'Количество зданий'; SUSPEND;

    TAG_NAME = 'columns:r'; VAL = NULL; SUSPEND;
    TAG_NAME = 'columns:r:type_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:param_id'; VAL = '2'; SUSPEND;
    TAG_NAME = 'columns:r:type'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:name'; VAL = 'Количество учебных зданий'; SUSPEND;

    TAG_NAME = 'columns:r'; VAL = NULL; SUSPEND;
    TAG_NAME = 'columns:r:type_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:param_id'; VAL = '3'; SUSPEND;
    TAG_NAME = 'columns:r:type'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:name'; VAL = 'Общая площадь зданий'; SUSPEND;

    TAG_NAME = 'columns:r'; VAL = NULL; SUSPEND;
    TAG_NAME = 'columns:r:type_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:param_id'; VAL = '4'; SUSPEND;
    TAG_NAME = 'columns:r:type'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:name'; VAL = 'Общая площадь учебных зданий'; SUSPEND;

    TAG_NAME = 'columns:r'; VAL = NULL; SUSPEND;
    TAG_NAME = 'columns:r:type_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:param_id'; VAL = '5'; SUSPEND;
    TAG_NAME = 'columns:r:type'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:name'; VAL = 'Площадь территории'; SUSPEND;

    TAG_NAME = 'columns:r'; VAL = NULL; SUSPEND;
    TAG_NAME = 'columns:r:type_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:param_id'; VAL = '6'; SUSPEND;
    TAG_NAME = 'columns:r:type'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:name'; VAL = 'Количество учебных место (проектная)'; SUSPEND;

    TAG_NAME = 'columns:r'; VAL = NULL; SUSPEND;
    TAG_NAME = 'columns:r:type_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:param_id'; VAL = '7'; SUSPEND;
    TAG_NAME = 'columns:r:type'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:name'; VAL = 'Количество учебных мест (нормативное)'; SUSPEND;

    TAG_NAME = 'columns:r'; VAL = NULL; SUSPEND;
    TAG_NAME = 'columns:r:type_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:param_id'; VAL = '8'; SUSPEND;
    TAG_NAME = 'columns:r:type'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:name'; VAL = 'Количество подразделений 1 уровня'; SUSPEND;

    -- Развертка по районам
    TAG_NAME = 'rows::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT L111.OBJ_ID, L111.OBJ_TYPE_ID, C.CAPTION
      FROM LINKS L111
      LEFT JOIN OBJECT_CAPTION_GET(L111.OBJ_ID) C ON 1 = 1
      WHERE L111.PARENT_ID = :I$OBJ_ID AND L111.OBJ_TYPE_ID = 111 AND L111.DATE_DEL IS NULL
      ORDER BY 3
      INTO :V$OBJ_ID, :V$TYPE, :S
    DO
    BEGIN
      TAG_NAME = 'rows:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'rows:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'rows:r:type_id';
      VAL = '1';
      SUSPEND;
      TAG_NAME = 'rows:r:caption';
      VAL = S;
      SUSPEND;

      -- Счетчики
      V$VAL = NULL;
      SELECT COUNT(DISTINCT L2.OBJ_ID), COUNT(*), SUM(IIF(V485.LISTVAL_ID = 1093, 1, 0)), SUM(V496.VAL), SUM(IIF(V485.LISTVAL_ID = 1093, V496.VAL, 0)), SUM(V520.VAL), SUM(V502.VAL), SUM(V503.VAL)
      FROM LINKS L2
      JOIN LINKS L73 ON L73.PARENT_ID = L2.OBJ_ID AND L73.OBJ_TYPE_ID = 73 AND L73.DATE_DEL IS NULL
      JOIN LINKS L16 ON L16.PARENT_ID = L73.OBJ_ID AND L16.OBJ_TYPE_ID = 16 AND L16.DATE_DEL IS NULL
      JOIN VALL V485 ON V485.OBJ_ID = L16.OBJ_ID AND V485.PARAM_ID = 485 AND V485.IS_DEL = 0
      JOIN VALF V496 ON V496.OBJ_ID = L16.OBJ_ID AND V496.PARAM_ID = 496 AND V496.IS_DEL = 0
      LEFT JOIN VALF V520 ON V520.OBJ_ID = L16.OBJ_ID AND V520.PARAM_ID = 520 AND V520.IS_DEL = 0
      LEFT JOIN VALI V502 ON V502.OBJ_ID = L16.OBJ_ID AND V502.PARAM_ID = 502 AND V502.IS_DEL = 0
      LEFT JOIN VALI V503 ON V503.OBJ_ID = L16.OBJ_ID AND V503.PARAM_ID = 503 AND V503.IS_DEL = 0
      LEFT JOIN VALD V3164 ON V3164.OBJ_ID = L16.OBJ_ID AND V3164.PARAM_ID = 3164 AND V3164.IS_DEL = 0 -- дата завершения эксплуатации
      WHERE L2.PARENT_ID = :V$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND V3164.VAL IS NULL
      INTO :V, :V$VAL, :V$VAL2, :V$VAL3, :V$VAL4, :V$VAL5, :V$VAL6, :V$VAL7;

      TAG_NAME = 'rows:r:p0';
      VAL = V;
      SUSPEND;
      TAG_NAME = 'rows:r:p1';
      VAL = V$VAL;
      SUSPEND;
      TAG_NAME = 'rows:r:p2';
      VAL = V$VAL2;
      SUSPEND;
      TAG_NAME = 'rows:r:p3';
      VAL = V$VAL3;
      SUSPEND;
      TAG_NAME = 'rows:r:p4';
      VAL = V$VAL4;
      SUSPEND;
      TAG_NAME = 'rows:r:p5';
      VAL = V$VAL5;
      SUSPEND;
      TAG_NAME = 'rows:r:p6';
      VAL = V$VAL6;
      SUSPEND;

      -- Количество подразделений
      SELECT COUNT(*)
      FROM LINKS L2
      JOIN LINKS L211 ON L211.PARENT_ID = L2.OBJ_ID AND L211.OBJ_TYPE_ID = 211 AND L211.DATE_DEL IS NULL
      WHERE L2.PARENT_ID = :V$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      INTO :V$VAL;
      TAG_NAME = 'rows:r:p7';
      VAL = V$VAL;
      SUSPEND;

    END

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PF_CONTENT_GET (
    I$PERSON_ID BIGINT,
    I$ZONE INTEGER,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$PERSON_ID BIGINT;
DECLARE VARIABLE V$PERSON_TYPE BIGINT;
DECLARE VARIABLE V$OU_ID BIGINT;
DECLARE VARIABLE V$YEAR_ID BIGINT;
DECLARE VARIABLE V$YEAR_DATE DATE;
DECLARE VARIABLE V$YEAR_NAME VARCHAR(100);
DECLARE VARIABLE V$SUBJECT_ID BIGINT;
DECLARE VARIABLE V$JT INTEGER;
DECLARE VARIABLE C VARCHAR(1000);
DECLARE VARIABLE S VARCHAR(1000);
DECLARE VARIABLE V$L DOUBLE PRECISION;
DECLARE VARIABLE V$H DOUBLE PRECISION;
DECLARE VARIABLE V$ROLE SMALLINT;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$Y BIGINT;
DECLARE VARIABLE V$GIA_SEL INTEGER;
DECLARE VARIABLE V$SUBJ1 BIGINT;
DECLARE VARIABLE V$SUBJ2 BIGINT;
DECLARE VARIABLE V$EXAM_ID BIGINT;
DECLARE VARIABLE D VARCHAR(400);
DECLARE VARIABLE T VARCHAR(1000);
DECLARE VARIABLE V$DATE DATE;
DECLARE VARIABLE V$DATE2 DATE;
DECLARE VARIABLE V$CJ_ID BIGINT;
DECLARE VARIABLE V$DE VARCHAR(400);
DECLARE VARIABLE V$CEC_ID BIGINT;
DECLARE VARIABLE V$USA_ID BIGINT;
DECLARE VARIABLE V$LEVEL_ID BIGINT;
DECLARE VARIABLE P INTEGER;
DECLARE VARIABLE V FLOAT;
DECLARE VARIABLE CT VARCHAR(100);
DECLARE VARIABLE TC VARCHAR(200);
DECLARE VARIABLE V$LAST_STAGE BIGINT;
DECLARE VARIABLE V$LAST_SUBSTAGE BIGINT;
DECLARE VARIABLE V$GROUP_ID BIGINT;
begin

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  SELECT FIRST 1 U.OBJ_ID, U.USER_TYPE, O.TYPE_ID
  FROM USERS U
  LEFT JOIN OBJECTS O ON O.OBJ_ID = U.OBJ_ID
  WHERE U.DATE_DEL IS NULL AND U.USER_ID = :I$USER_ID AND U.IS_BLOCKED = 0 AND (U.EXP_DATE IS NULL OR U.EXP_DATE >= CURRENT_DATE)
  INTO :V$PERSON_ID, :V$ROLE, :V$PERSON_TYPE;

  IF(V$ROLE IS NULL) THEN EXCEPTION DATA_ERROR 'Пользователь не идентифицирован как сотрудник или обучающийся';

  -- Если PERSON_ID не указан, значит берем самого себя
  IF(I$PERSON_ID IS NULL) THEN
  BEGIN
    IF(V$PERSON_TYPE IS NULL OR V$PERSON_TYPE <> 10) THEN EXCEPTION DATA_ERROR 'Портфолио доступно только для обучающихся';
    I$PERSON_ID = V$PERSON_ID;
  END
  ELSE
  BEGIN
    -- !!! проверить права доступа к данной персоне !!!
  END

  -- Текущий учебный год
  SELECT FIRST 1 L2.OBJ_ID, V1236.LISTVAL_ID, CAST(LV.TAG AS DATE), R.VAL
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$OU_ID, :V$YEAR_ID, :V$YEAR_DATE, :V$YEAR_NAME;

  -- На каком уровне сейчас обучается ?
  V$LEVEL_ID = 0;
  SELECT FIRST 1 M.LEVEL_ID, M.GROUP_ID
  FROM PERSON_MOVEMENTS M
  WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :V$PERSON_ID AND M.GROUP_TYPE_ID IN (9, 187, 289)
  ORDER BY M.GROUP_TYPE_ID, M.DATE_IN DESC
  INTO :V$LEVEL_ID, :V$GROUP_ID;

  -- Средние баллы для таблицы и круговой диаграммы
  TAG_NAME = 'avgmarks::json&colon;array';
  VAL = 1;
  SUSPEND;
  -- Первая выборка - для школы
  FOR
    SELECT DISTINCT J.SUBJECT_ID, J.JOURNAL_TYPE, C.CAPTION
    FROM PERSON_MOVEMENTS M
    JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.GRADE_ID = M.GROUP_ID AND J.JOURNAL_TYPE IN (0, 1) AND J.YEAR_ID = :V$YEAR_ID
    LEFT JOIN OBJECT_CAPTION_GET(J.SUBJECT_ID) C ON 1 = 1
    WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :I$PERSON_ID AND M.DATE_IN <= CURRENT_DATE AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :V$YEAR_DATE) AND :V$LEVEL_ID <> 29
    ORDER BY 3
    INTO :V$SUBJECT_ID, :V$JT, :S
  DO
  BEGIN
    TAG_NAME = 'avgmarks:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'avgmarks:r:subject_id';
    VAL = V$SUBJECT_ID;
    SUSPEND;
    TAG_NAME = 'avgmarks:r:jt';
    VAL = V$JT;
    SUSPEND;
    TAG_NAME = 'avgmarks:r:subject_name';
    VAL = S;
    SUSPEND;

    -- Средняя по итоговым
    TAG_NAME = 'avgmarks:r:by_final';
    V$L = NULL;
    SELECT SUM(MT.MARK_SCALE), SUM(MT.MARK_SCALE * MT.MARK_COST)
    FROM CJ2_MARK M
    JOIN CJ2_JOURNAL_FINALS F ON F.OBJ_ID = M.FINAL_ID AND F.DATE_DEL IS NULL
    JOIN LISTVALS LV ON LV.LISTVAL_ID = F.FINAL_TYPE AND LV.PARENT_ID = 3001 -- за период
    JOIN CJ2_JOURNAL J ON J.OBJ_ID = F.CJ_ID AND J.DATE_DEL IS NULL AND J.SUBJECT_ID = :V$SUBJECT_ID AND J.JOURNAL_TYPE = :V$JT AND J.YEAR_ID = :V$YEAR_ID
    JOIN CJ2_MARK_TYPE MT ON MT.MARK_TYPE_ID = M.MARK_TYPE_ID
    WHERE M.DATE_DEL IS NULL AND M.FINAL_ID IS NOT NULL AND M.STUDENT_ID = :I$PERSON_ID
    INTO :V$L, :V$H;
    IF(V$L IS NULL OR V$L <= 0) THEN VAL = NULL; ELSE VAL = CAST(V$H / V$L AS NUMERIC(18, 2));
    SUSPEND;

    -- Средняя по всем текущим
    TAG_NAME = 'avgmarks:r:by_all';
    V$L = NULL;
    SELECT SUM(MT.MARK_SCALE * CT.DEFAULT_COST), SUM(MT.MARK_SCALE * MT.MARK_COST * CT.DEFAULT_COST)
    FROM CJ2_MARK M
    JOIN CJ2_CONTROL C ON C.CONTROL_ID = M.CONTROL_ID AND C.DATE_DEL IS NULL AND C.CONTROL_ID <> 0 AND C.CONTROL_ID <> 30000
    JOIN CJ2_CONTROL_TYPE CT ON CT.CONTROL_TYPE_ID = C.CONTROL_TYPE_ID
    JOIN CJ2_JOURNAL_LESSONS L ON L.OBJ_ID = C.LESSON_ID AND L.DATE_DEL IS NULL
    JOIN CJ2_JOURNAL J ON J.OBJ_ID = L.CJ_ID AND J.DATE_DEL IS NULL AND J.SUBJECT_ID = :V$SUBJECT_ID AND J.JOURNAL_TYPE = :V$JT AND J.YEAR_ID = :V$YEAR_ID
    JOIN CJ2_MARK_TYPE MT ON MT.MARK_TYPE_ID = M.MARK_TYPE_ID
    WHERE M.DATE_DEL IS NULL AND M.CONTROL_ID IS NOT NULL AND M.STUDENT_ID = :I$PERSON_ID
    INTO :V$L, :V$H;
    IF(V$L IS NULL OR V$L <= 0) THEN VAL = NULL; ELSE VAL = CAST(V$H / V$L AS NUMERIC(18, 2));
    SUSPEND;
  END
  -- Вторая выборка СПО - показываем не среднюю, а итоговую оценку за последнюю сессию
  -- Выбираем данные последней сессии
  SELECT FIRST 1 M.STAGE_ID, M.MARKTYPE_ID
  FROM VALM M
  WHERE M.IS_DEL = 0 AND M.PUPIL_ID = :I$PERSON_ID AND M.MARKTYPE_ID IN (12973, 12974)
  ORDER BY 1 DESC, 2 DESC
  INTO :V$LAST_STAGE, :V$LAST_SUBSTAGE;

  FOR
    SELECT M.SUBJECT_ID, C.CAPTION, M.MARKVAL_ID, MC.VAL
    FROM VALM M
    LEFT JOIN OBJECT_CAPTION_GET(M.SUBJECT_ID) C ON 1 = 1
    LEFT JOIN LISTVAL_TEXT(M.MARKVAL_ID) MC ON 1 = 1
    WHERE M.IS_DEL = 0 AND M.PUPIL_ID = :I$PERSON_ID AND M.STAGE_ID = :V$LAST_STAGE AND M.MARKTYPE_ID = :V$LAST_SUBSTAGE AND :V$LEVEL_ID = 29
    ORDER BY 2
    INTO :V$SUBJECT_ID, :S, :V$OBJ_ID, :C
  DO
  BEGIN
    TAG_NAME = 'avgmarks:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'avgmarks:r:subject_id';
    VAL = V$SUBJECT_ID;
    SUSPEND;
    TAG_NAME = 'avgmarks:r:jt';
    VAL = 0;
    SUSPEND;
    TAG_NAME = 'avgmarks:r:subject_name';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'avgmarks:r:by_final';
    -- 5 баллов
    IF(V$OBJ_ID IN (3014, 3015, 3016, 3017, 3018)) THEN VAL = V$OBJ_ID - 3014 + 1;
    -- зачет-незачет
    ELSE IF(V$OBJ_ID = 3019) THEN VAL = 5;
    ELSE IF(V$OBJ_ID = 3020) THEN VAL = 2;
    -- 100 баллов
    ELSE IF(V$OBJ_ID >= 13020 AND V$OBJ_ID <= 13119) THEN VAL = 0.05 * (V$OBJ_ID - 13020 + 1);
    -- 12 баллов
    ELSE IF(V$OBJ_ID >= 13309 AND V$OBJ_ID <= 13318) THEN VAL = 0.5 * (V$OBJ_ID - 13309 + 1);
    ELSE IF(V$OBJ_ID IN (13319, 13320)) THEN VAL = 5;
    ELSE VAL = NULL;
    SUSPEND;
    TAG_NAME = 'avgmarks:r:by_all';
    SUSPEND;
  END

  -- Предметы с углубленным изучением, сразу выбираем итоговую отметку и результаты ГИА
  -- Отдельно добавляем предметы из УП текущего года, если по ним еще не было итоговых
  TAG_NAME = 'advsubjects::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT DISTINCT M.SUBJECT_ID, M.YEAR_ID, LV.COST, R.VAL, C.CAPTION
    FROM VALM M
    JOIN LISTVALS LV ON LV.LISTVAL_ID = M.YEAR_ID
    JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
    LEFT JOIN OBJECT_CAPTION_GET(M.SUBJECT_ID) C ON 1 = 1
    WHERE M.PUPIL_ID = :I$PERSON_ID AND M.IS_DEL = 0 AND M.IS_EXT = 1
    ORDER BY 4, 2
    INTO :V$SUBJECT_ID, :V$Y, :V$L, :C, :S
  DO
  BEGIN
    TAG_NAME = 'advsubjects:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'advsubjects:r:subject_id';
    VAL = V$SUBJECT_ID;
    SUSPEND;
    TAG_NAME = 'advsubjects:r:year';
    VAL = C;
    SUSPEND;
    TAG_NAME = 'advsubjects:r:subject_name';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'advsubjects:r:year_mark';
    VAL = NULL;
    SELECT FIRST 1 C.VAL
    FROM VALM M
    LEFT JOIN LISTVAL_TEXT(M.MARKVAL_ID) C ON 1 = 1
    WHERE M.PUPIL_ID = :I$PERSON_ID AND M.SUBJECT_ID = :V$SUBJECT_ID AND M.YEAR_ID = :V$Y AND M.MARKTYPE_ID = 3011 AND M.IS_DEL = 0 AND M.IS_EXT = 1
    INTO :VAL;
    SUSPEND;

    -- Проверяем отметку ГИА в том году, когда у ученика была итоговая отметка
    V$EXAM_ID = NULL;
    V$SUBJ1 = NULL;
    V$SUBJ2 = NULL;
    S = NULL;
    C = NULL;

    IF(V$SUBJECT_ID IN (185)) THEN BEGIN V$SUBJ1 = 2922; V$SUBJ2 = 10875; END -- русский
    IF(V$SUBJECT_ID IN (190, 172, 3149, 173, 38150, 32819, 38151)) THEN BEGIN V$SUBJ1 = 2923; V$SUBJ2 = 10879; END -- математика профильная
    IF(V$SUBJECT_ID IN (198)) THEN BEGIN V$SUBJ1 = 2924; V$SUBJ2 = 11205; END -- физика
    IF(V$SUBJECT_ID IN (199)) THEN BEGIN V$SUBJ1 = 2925; V$SUBJ2 = 11206; END -- химия
    IF(V$SUBJECT_ID IN (191, 5518, 32905)) THEN BEGIN V$SUBJ1 = 2926; V$SUBJ2 = 11207; END -- информатика
    IF(V$SUBJECT_ID IN (197)) THEN BEGIN V$SUBJ1 = 2927; V$SUBJ2 = 11208; END -- биология
    IF(V$SUBJECT_ID IN (174, 3151, 38154)) THEN BEGIN V$SUBJ1 = 2928; V$SUBJ2 = 11209; END -- история
    IF(V$SUBJECT_ID IN (3139)) THEN BEGIN V$SUBJ1 = 2929; V$SUBJ2 = 11210; END -- география
    IF(V$SUBJECT_ID IN (188)) THEN BEGIN V$SUBJ1 = 2930; V$SUBJ2 = 11211; END -- английский

    TAG_NAME = 'advsubjects:r:gia_sel';
    VAL = 0;
    SELECT FIRST 1 1, L120.OBJ_ID
    FROM LINKS L120
    JOIN VALL V803 ON V803.OBJ_ID = L120.OBJ_ID AND V803.PARAM_ID = 803 AND V803.IS_DEL = 0 AND (V803.LISTVAL_ID = :V$SUBJ1 OR V803.LISTVAL_ID = :V$SUBJ2)
    JOIN LINKS LP119 ON LP119.OBJ_ID = L120.OBJ_ID AND LP119.PARENT_TYPE_ID = 119 AND LP119.DATE_DEL IS NULL
    JOIN VALL V742 ON V742.OBJ_ID = LP119.PARENT_ID AND V742.PARAM_ID = 742 AND V742.IS_DEL = 0 AND V742.LISTVAL_ID = :V$Y
    WHERE L120.PARENT_ID = :I$PERSON_ID AND L120.OBJ_TYPE_ID = 120 AND L120.DATE_DEL IS NULL
    INTO :VAL, :V$EXAM_ID;
    SUSPEND;

    -- Максимальный балл брать неоткуда
    SELECT FIRST 1 V816.VAL, NULL
    FROM LINKS L123
    JOIN LINKS LP120 ON LP120.OBJ_ID = L123.OBJ_ID AND LP120.PARENT_ID = :V$EXAM_ID AND LP120.DATE_DEL IS NULL
    JOIN VALI V816 ON V816.OBJ_ID = L123.OBJ_ID AND V816.PARAM_ID = 816 AND V816.IS_DEL = 0
    WHERE L123.PARENT_ID = :I$PERSON_ID AND L123.OBJ_TYPE_ID = 123 AND L123.DATE_DEL IS NULL
    INTO :S, :C;

    -- Отметки и баллы выбираем даже если не выбрано
    TAG_NAME = 'advsubjects:r:gia_mark';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'advsubjects:r:gia_max';
    VAL = C;
    SUSPEND;
  END
  -- + текущий год
  FOR
    SELECT DISTINCT PS.SUBJECT_ID, C.CAPTION
    FROM LINKS LP256
    JOIN LINKS LP54 ON LP54.OBJ_ID = LP256.PARENT_ID AND LP54.PARENT_TYPE_ID = 54 AND LP54.DATE_DEL IS NULL
    JOIN LINKS LP400 ON LP400.OBJ_ID = LP54.PARENT_ID AND LP400.PARENT_TYPE_ID = 400 AND LP400.DATE_DEL IS NULL
    JOIN PLAN_SUBJECTS PS ON PS.DATE_DEL IS NULL AND PS.PLAN_ID = LP400.PARENT_ID AND PS.ROW_TYPE = 10 AND PS.IS_ADV = 1
    JOIN PLAN_LOADS PL ON PL.DATE_DEL IS NULL AND PL.SUBJECT_ID = PS.OBJ_ID AND PL.STAGE_ID = LP54.PARENT_ID
      AND (PL.LOAD_HOURS_S1 > 0 OR PL.LOAD_HOURS_S2 > 0)
    LEFT JOIN OBJECT_CAPTION_GET(PS.SUBJECT_ID) C ON 1 = 1
    LEFT JOIN VALM M ON M.PUPIL_ID = LP256.OBJ_ID AND M.SUBJECT_ID = PS.SUBJECT_ID AND M.YEAR_ID = :V$YEAR_ID AND M.IS_DEL = 0
    WHERE LP256.OBJ_ID = :I$PERSON_ID AND LP256.PARENT_TYPE_ID = 256 AND LP256.DATE_DEL IS NULL AND M.MARK_ID IS NULL
    ORDER BY 2
    INTO :V$SUBJECT_ID, :S
  DO
  BEGIN
    TAG_NAME = 'advsubjects:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'advsubjects:r:subject_id';
    VAL = V$SUBJECT_ID;
    SUSPEND;
    TAG_NAME = 'advsubjects:r:year';
    VAL = V$YEAR_NAME;
    SUSPEND;
    TAG_NAME = 'advsubjects:r:subject_name';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'advsubjects:r:year_mark';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'advsubjects:r:gia_sel';
    VAL = 0;
    SUSPEND;
    TAG_NAME = 'advsubjects:r:gia_mark';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'advsubjects:r:gia_max';
    VAL = NULL;
    SUSPEND;
  END

  -- Предметы и модули по выбору
  -- Аналогично, добавляем предметы текущего УП, если по ним еще нет итоговых
  TAG_NAME = 'optsubjects::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT DISTINCT M.SUBJECT_ID, M.YEAR_ID, LV.COST, R.VAL, C.CAPTION
    FROM VALM M
    JOIN LISTVALS LV ON LV.LISTVAL_ID = M.YEAR_ID
    JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
    LEFT JOIN OBJECT_CAPTION_GET(M.SUBJECT_ID) C ON 1 = 1
    LEFT JOIN VALL V2816 ON V2816.OBJ_ID = M.SUBJECT_ID AND V2816.PARAM_ID = 2816 AND V2816.IS_DEL = 0
    LEFT JOIN VALL V3158 ON V3158.OBJ_ID = M.SUBJECT_ID AND V3158.PARAM_ID = 3158 AND V3158.IS_DEL = 0
    WHERE M.PUPIL_ID = :I$PERSON_ID AND M.IS_DEL = 0 AND (V2816.LISTVAL_ID = 2 OR V3158.LISTVAL_ID IN (13455, 13456, 13457))
    ORDER BY 4, 2
    INTO :V$SUBJECT_ID, :V$Y, :V$L, :C, :S
  DO
  BEGIN
    TAG_NAME = 'optsubjects:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'optsubjects:r:subject_id';
    VAL = V$SUBJECT_ID;
    SUSPEND;
    TAG_NAME = 'optsubjects:r:year';
    VAL = C;
    SUSPEND;
    TAG_NAME = 'optsubjects:r:subject_name';
    VAL = S;
    SUSPEND;
  END
  FOR
    SELECT DISTINCT PS.SUBJECT_ID, C.CAPTION
    FROM LINKS LP256
    JOIN LINKS LP54 ON LP54.OBJ_ID = LP256.PARENT_ID AND LP54.PARENT_TYPE_ID = 54 AND LP54.DATE_DEL IS NULL
    JOIN LINKS LP400 ON LP400.OBJ_ID = LP54.PARENT_ID AND LP400.PARENT_TYPE_ID = 400 AND LP400.DATE_DEL IS NULL
    JOIN PLAN_SUBJECTS PS ON PS.DATE_DEL IS NULL AND PS.PLAN_ID = LP400.PARENT_ID AND PS.ROW_TYPE = 10
    JOIN PLAN_LOADS PL ON PL.DATE_DEL IS NULL AND PL.SUBJECT_ID = PS.OBJ_ID AND PL.STAGE_ID = LP54.PARENT_ID
      AND (PL.LOAD_HOURS_S1 > 0 OR PL.LOAD_HOURS_S2 > 0)
    LEFT JOIN VALL V2816 ON V2816.OBJ_ID = PS.SUBJECT_ID AND V2816.PARAM_ID = 2816 AND V2816.IS_DEL = 0
    LEFT JOIN VALL V3158 ON V3158.OBJ_ID = PS.SUBJECT_ID AND V3158.PARAM_ID = 3158 AND V3158.IS_DEL = 0
    LEFT JOIN OBJECT_CAPTION_GET(PS.SUBJECT_ID) C ON 1 = 1
    LEFT JOIN VALM M ON M.PUPIL_ID = LP256.OBJ_ID AND M.SUBJECT_ID = PS.SUBJECT_ID AND M.YEAR_ID = :V$YEAR_ID AND M.IS_DEL = 0
    WHERE LP256.OBJ_ID = :I$PERSON_ID AND LP256.PARENT_TYPE_ID = 256 AND LP256.DATE_DEL IS NULL
      AND (V2816.LISTVAL_ID = 2 OR V3158.LISTVAL_ID IN (13455, 13456, 13457))
      AND M.MARK_ID IS NULL
    ORDER BY 2
    INTO :V$SUBJECT_ID, :S
  DO
  BEGIN
    TAG_NAME = 'optsubjects:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'optsubjects:r:subject_id';
    VAL = V$SUBJECT_ID;
    SUSPEND;
    TAG_NAME = 'optsubjects:r:year';
    VAL = V$YEAR_NAME;
    SUSPEND;
    TAG_NAME = 'optsubjects:r:subject_name';
    VAL = S;
    SUSPEND;
  END

  -- Предметы ВД
  TAG_NAME = 'vdsubjects::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT DISTINCT M.SUBJECT_ID, M.YEAR_ID, LV.COST, R.VAL, C.CAPTION, CD.VAL
    FROM VALM M
    JOIN LISTVALS LV ON LV.LISTVAL_ID = M.YEAR_ID
    JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
    JOIN LINKS LP301 ON LP301.OBJ_ID = M.SUBJECT_ID AND LP301.PARENT_ID = 32772
    LEFT JOIN OBJECT_CAPTION_GET(M.SUBJECT_ID) C ON 1 = 1
    LEFT JOIN VALL V2464 ON V2464.OBJ_ID = M.SUBJECT_ID AND V2464.PARAM_ID = 2464 AND V2464.IS_DEL = 0
    LEFT JOIN LISTVAL_TEXT(V2464.LISTVAL_ID) CD ON 1 = 1
    WHERE M.PUPIL_ID = :I$PERSON_ID AND M.IS_DEL = 0
    ORDER BY 4, 2
    INTO :V$SUBJECT_ID, :V$Y, :V$L, :C, :S, :D
  DO
  BEGIN
    TAG_NAME = 'vdsubjects:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'vdsubjects:r:subject_id';
    VAL = V$SUBJECT_ID;
    SUSPEND;
    TAG_NAME = 'vdsubjects:r:year';
    VAL = C;
    SUSPEND;
    TAG_NAME = 'vdsubjects:r:subject_name';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'vdsubjects:r:dir_name';
    VAL = D;
    SUSPEND;
  END
  FOR
    SELECT DISTINCT J.SUBJECT_ID, C.CAPTION, CD.VAL
    FROM LINKS LPG
    JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.GRADE_ID = LPG.PARENT_ID AND J.JOURNAL_TYPE = 1
    LEFT JOIN VALL V2464 ON V2464.OBJ_ID = J.SUBJECT_ID AND V2464.PARAM_ID = 2464 AND V2464.IS_DEL = 0
    LEFT JOIN LISTVAL_TEXT(V2464.LISTVAL_ID) CD ON 1 = 1
    LEFT JOIN OBJECT_CAPTION_GET(J.SUBJECT_ID) C ON 1 = 1
    LEFT JOIN VALM M ON M.PUPIL_ID = LPG.OBJ_ID AND M.SUBJECT_ID = J.SUBJECT_ID AND M.YEAR_ID = :V$YEAR_ID AND M.IS_DEL = 0
    WHERE LPG.OBJ_ID = :I$PERSON_ID AND LPG.PARENT_TYPE_ID IN (9, 187, 256, 179) AND LPG.DATE_DEL IS NULL AND M.MARK_ID IS NULL
    ORDER BY 2
    INTO :V$SUBJECT_ID, :S, :D
  DO
  BEGIN
    TAG_NAME = 'vdsubjects:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'vdsubjects:r:subject_id';
    VAL = V$SUBJECT_ID;
    SUSPEND;
    TAG_NAME = 'vdsubjects:r:year';
    VAL = V$YEAR_NAME;
    SUSPEND;
    TAG_NAME = 'vdsubjects:r:subject_name';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'vdsubjects:r:dir_name';
    VAL = D;
    SUSPEND;
  END

  -- Отметки по ключевым контролям за последние 3 месяца
  TAG_NAME = 'keymarks::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT M.MARK_ID, CS.CAPTION, L.LESSON_DATE, CT.CONTROL_TYPE_ID, CT.CONTROL_NAME, MT.MARK_SHORTNAME, CAST(MT.MARK_COST AS NUMERIC(18, 1))
    FROM CJ2_MARK M
    JOIN CJ2_CONTROL C ON C.CONTROL_ID = M.CONTROL_ID AND C.DATE_DEL IS NULL AND C.CONTROL_TYPE_ID NOT IN (0, 30000) AND C.CONTROL_COST > 1
    JOIN CJ2_CONTROL_TYPE CT ON CT.CONTROL_TYPE_ID = C.CONTROL_TYPE_ID
    JOIN CJ2_JOURNAL_LESSONS L ON L.OBJ_ID = C.LESSON_ID AND L.DATE_DEL IS NULL AND L.LESSON_DATE >= DATEADD(-3 MONTH TO CURRENT_DATE) AND M.CONTROL_ID IS NOT NULL
    JOIN CJ2_JOURNAL J ON J.OBJ_ID = L.CJ_ID AND J.JOURNAL_TYPE = 0
    JOIN CJ2_MARK_TYPE MT ON MT.MARK_TYPE_ID = M.MARK_TYPE_ID
    LEFT JOIN OBJECT_CAPTION_GET(J.SUBJECT_ID) CS ON 1 = 1
    WHERE M.DATE_DEL IS NULL AND M.STUDENT_ID = :I$PERSON_ID
    ORDER BY 2, 3
    INTO :V$OBJ_ID, :C, :V$DATE, :V$EXAM_ID, :S,  :D, :V$DE
  DO
  BEGIN
    TAG_NAME = 'keymarks:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'keymarks:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'keymarks:r:subject';
    VAL = C;
    SUSPEND;
    TAG_NAME = 'keymarks:r:date';
    VAL = (SELECT VAL FROM DATE2ISO(:V$DATE));
    SUSPEND;
    TAG_NAME = 'keymarks:r:ct_id';
    VAL = V$EXAM_ID;
    SUSPEND;
    TAG_NAME = 'keymarks:r:ct_name';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'keymarks:r:cost';
    VAL = V$DE;
    SUSPEND;
    TAG_NAME = 'keymarks:r:value';
    VAL = D;
    SUSPEND;
  END

  -- Напоминания по домашней и классной работе
  TAG_NAME = 'hints::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT M.MARK_ID, CS.CAPTION, L.LESSON_DATE, CT.CONTROL_TYPE_ID, CT.CONTROL_NAME, MT.MARK_SHORTNAME, J.OBJ_ID, L.LESSON_THEME, COALESCE(L.DE_ID, '')
    FROM CJ2_MARK M
    JOIN CJ2_CONTROL C ON C.CONTROL_ID = M.CONTROL_ID AND C.DATE_DEL IS NULL AND C.CONTROL_TYPE_ID IN (1058, 1063)
    JOIN CJ2_CONTROL_TYPE CT ON CT.CONTROL_TYPE_ID = C.CONTROL_TYPE_ID
    JOIN CJ2_JOURNAL_LESSONS L ON L.OBJ_ID = C.LESSON_ID AND L.DATE_DEL IS NULL AND L.LESSON_DATE >= DATEADD(-1 MONTH TO CURRENT_DATE) AND M.CONTROL_ID IS NOT NULL
    JOIN CJ2_JOURNAL J ON J.OBJ_ID = L.CJ_ID AND J.JOURNAL_TYPE = 0
    JOIN CJ2_MARK_TYPE MT ON MT.MARK_TYPE_ID = M.MARK_TYPE_ID AND (MT.MARK_COST < 3 OR (:V$LEVEL_ID = 29 AND MT.MARK_COST <= 3)) -- !!! проверить
    LEFT JOIN OBJECT_CAPTION_GET(J.SUBJECT_ID) CS ON 1 = 1
    WHERE M.DATE_DEL IS NULL AND M.STUDENT_ID = :I$PERSON_ID
    -- Сюда же выводим плохие оценки по сессии
    UNION
    SELECT M2.MARK_ID, CS.CAPTION, M2.MARK_DATE, M2.MARKTYPE_ID, MC.VAL, VC.VAL, NULL, MC.VAL, ''
    FROM VALM M2
    LEFT JOIN OBJECT_CAPTION_GET(M2.SUBJECT_ID) CS ON 1 = 1
    LEFT JOIN LISTVAL_TEXT(M2.MARKTYPE_ID) MC ON 1 = 1
    LEFT JOIN LISTVAL_TEXT(M2.MARKVAL_ID) VC ON 1 = 1
    WHERE M2.IS_DEL = 0 AND M2.PUPIL_ID = :I$PERSON_ID AND M2.MARKVAL_ID IN (3014, 3015, 3016, 3020, 3022, 3023) AND M2.MARK_DATE >= DATEADD(-4 MONTH TO CURRENT_DATE)
    ORDER BY 2, 3
    INTO :V$OBJ_ID, :C, :V$DATE, :V$EXAM_ID, :S,  :D, :V$CJ_ID, :T, :V$DE
  DO
  BEGIN
    TAG_NAME = 'hints:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'hints:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'hints:r:subject';
    VAL = C;
    SUSPEND;
    TAG_NAME = 'hints:r:date';
    VAL = (SELECT VAL FROM DATE2ISO(:V$DATE));
    SUSPEND;
    TAG_NAME = 'hints:r:ct_id';
    VAL = V$EXAM_ID;
    SUSPEND;
    TAG_NAME = 'hints:r:ct_name';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'hints:r:value';
    VAL = D;
    SUSPEND;
    TAG_NAME = 'hints:r:theme';
    VAL = T;
    SUSPEND;
    TAG_NAME = 'hints:r:ext';
    VAL = NULL;
    SUSPEND;
    IF(V$EXAM_ID = 1063) THEN
    BEGIN
      TAG_NAME = 'hints:r:hw';
      VAL = NULL;
      SELECT FIRST 1 L.LESSON_HOMEWORK
      FROM CJ2_JOURNAL_LESSONS L
      WHERE L.DATE_DEL IS NULL AND L.CJ_ID = :V$CJ_ID AND L.LESSON_DATE < :V$DATE AND L.LESSON_HOMEWORK IS NOT NULL AND CHAR_LENGTH(L.LESSON_HOMEWORK) > 0
      ORDER BY L.LESSON_DATE DESC, L.LESSON_NUM DESC
      INTO :VAL;
      SUSPEND;
    END
    IF(V$DE <> '') THEN
    BEGIN
      TAG_NAME = 'hints:r:de';
      VAL = '';
      WHILE(CHAR_LENGTH(V$DE) > 0) DO
      BEGIN
        P = POSITION(',' IN V$DE);
        IF(P <= 0) THEN P = CHAR_LENGTH(V$DE) + 1;
        V$EXAM_ID = SUBSTRING(V$DE FROM 1 FOR P - 1);
        V$DE = SUBSTRING(V$DE FROM P + 1);

        SELECT CI.CAPTION
        FROM CEC_ITEMS CI
        WHERE CI.DATE_DEL IS NULL AND CI.OBJ_ID = :V$EXAM_ID
        INTO :S;

        IF(CHAR_LENGTH(VAL) + CHAR_LENGTH(S) < 990) THEN
        BEGIN
          IF(VAL <> '') THEN VAL = VAL || '; ';
          VAL = VAL || S;
        END
      END
      SUSPEND;
    END
  END

  -- Дефициты выбираются по ПЭС и УУД
  TAG_NAME = 'deficites::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT V.USA_ID, V.CEC_ID, COALESCE(C.SUBJECT_ID, CI.SUBJECT_ID), CS.CAPTION, COALESCE(CI.CAPTION, CA.VAL), 20 * (V.VTOTAL / V.NTOTAL)
    FROM VALX V
    LEFT JOIN CEC_ITEMS CI ON CI.OBJ_ID = V.CEC_ID
    LEFT JOIN CEC C ON C.OBJ_ID = CI.CEC_ID
    LEFT JOIN OBJECT_CAPTION_GET(COALESCE(C.SUBJECT_ID, CI.SUBJECT_ID)) CS ON C.SUBJECT_ID IS NOT NULL OR CI.SUBJECT_ID IS NOT NULL
    LEFT JOIN LISTVAL_TEXT(V.USA_ID) CA ON V.USA_ID <> 0
    WHERE V.PUPIL_ID = :I$PERSON_ID AND V.YEAR_ID = :V$YEAR_ID AND (V.VTOTAL / V.NTOTAL) < 3.0
    ORDER BY 3 NULLS LAST
    INTO :V$CEC_ID, :V$USA_ID, :V$SUBJECT_ID, :S, :C, :V
  DO
  BEGIN
    TAG_NAME = 'deficites:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'deficites:r:subject_id';
    VAL = V$SUBJECT_ID;
    SUSPEND;
    TAG_NAME = 'deficites:r:subject_name';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'deficites:r:usa_id';
    VAL = V$USA_ID;
    SUSPEND;
    TAG_NAME = 'deficites:r:cec_id';
    VAL = V$CEC_ID;
    SUSPEND;
    TAG_NAME = 'deficites:r:name';
    VAL = C;
    SUSPEND;
    TAG_NAME = 'deficites:r:value';
    VAL = V;
    SUSPEND;
  END

  -- Тут грузим только раздел олимпиады
  TAG_NAME = 'portfolio::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L22.OBJ_ID, V167.VAL, V1818.VAL, C1819.VAL, V166.VAL, V1820.VAL, V237.LISTVAL_ID, IIF(V3182.LISTVAL_ID = 2, 1, 0)
    FROM LINKS L22
    LEFT JOIN VALS V167 ON V167.OBJ_ID = L22.OBJ_ID AND V167.PARAM_ID = 167 AND V167.IS_DEL = 0 -- вид мероприятия
    LEFT JOIN VALS V1818 ON V1818.OBJ_ID = L22.OBJ_ID AND V1818.PARAM_ID = 1818 AND V1818.IS_DEL = 0 -- наименование
    LEFT JOIN VALL V1819 ON V1819.OBJ_ID = L22.OBJ_ID AND V1819.PARAM_ID = 1819 AND V1819.IS_DEL = 0 -- статус
    LEFT JOIN LISTVAL_TEXT(V1819.LISTVAL_ID) C1819 ON 1 = 1
    LEFT JOIN VALD V166 ON V166.OBJ_ID = L22.OBJ_ID AND V166.PARAM_ID = 166 AND V166.IS_DEL = 0 -- дата
    LEFT JOIN VALS V1820 ON V1820.OBJ_ID = L22.OBJ_ID AND V1820.PARAM_ID = 1820 AND V1820.IS_DEL = 0 -- тематика
    LEFT JOIN VALL V237 ON V237.OBJ_ID = L22.OBJ_ID AND V237.PARAM_ID = 237 AND V237.IS_DEL = 0 -- результат
    LEFT JOIN VALL V3182 ON V3182.OBJ_ID = L22.OBJ_ID AND V3182.PARAM_ID = 3182 AND V3182.IS_DEL = 0 -- верифицирован
    WHERE L22.PARENT_ID = :I$PERSON_ID AND L22.OBJ_TYPE_ID = 22 AND L22.DATE_DEL IS NULL
    ORDER BY L22.DATE_INS
    INTO :V$OBJ_ID, :S, :C, :V$DE, :V$DATE, :D, :V$Y, :V$GIA_SEL
  DO
  BEGIN
    TAG_NAME = 'portfolio:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'portfolio:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'portfolio:r:part';
    VAL = 22;
    SUSPEND;
    TAG_NAME = 'portfolio:r:type';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'portfolio:r:level';
    VAL = V$DE;
    SUSPEND;
    TAG_NAME = 'portfolio:r:name';
    VAL = C;
    SUSPEND;
    TAG_NAME = 'portfolio:r:theme';
    VAL = D;
    SUSPEND;
    TAG_NAME = 'portfolio:r:date';
    VAL = (SELECT VAL FROM DATE2ISO(:V$DATE, 0));
    SUSPEND;
    TAG_NAME = 'portfolio:r:result';
    VAL = V$Y;
    SUSPEND;
    TAG_NAME = 'portfolio:r:ver';
    VAL = V$GIA_SEL;
    SUSPEND;
  END
  FOR
    SELECT L24.OBJ_ID, C178.VAL, V177.VAL, C1826.VAL, C236.VAL, IIF(V3193.LISTVAL_ID = 2, 1, 0)
    FROM LINKS L24
    LEFT JOIN VALL V178 ON V178.OBJ_ID = L24.OBJ_ID AND V178.PARAM_ID = 178 AND V178.IS_DEL = 0
    LEFT JOIN LISTVAL_TEXT(V178.LISTVAL_ID) C178 ON 1 = 1
    LEFT JOIN VALD V177 ON V177.OBJ_ID = L24.OBJ_ID AND V177.PARAM_ID = 177 AND V177.IS_DEL = 0
    LEFT JOIN VALL V1826 ON V1826.OBJ_ID = L24.OBJ_ID AND V1826.PARAM_ID = 1826 AND V1826.IS_DEL = 0
    LEFT JOIN LISTVAL_TEXT(V1826.LISTVAL_ID) C1826 ON 1 = 1
    LEFT JOIN VALL V236 ON V236.OBJ_ID = L24.OBJ_ID AND V236.PARAM_ID = 236 AND V236.IS_DEL = 0
    LEFT JOIN LISTVAL_TEXT(V236.LISTVAL_ID) C236 ON 1 = 1
    LEFT JOIN VALL V3193 ON V3193.OBJ_ID = L24.OBJ_ID AND V3193.PARAM_ID = 3193 AND V3193.IS_DEL = 0 -- верифицирован
    WHERE L24.PARENT_ID = :I$PERSON_ID AND L24.OBJ_TYPE_ID = 24 AND L24.DATE_DEL IS NULL
    ORDER BY L24.DATE_INS
    INTO :V$OBJ_ID, :S, :V$DATE, :C, :D, :V$GIA_SEL
  DO
  BEGIN
    TAG_NAME = 'portfolio:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'portfolio:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'portfolio:r:part';
    VAL = 24;
    SUSPEND;
    TAG_NAME = 'portfolio:r:date';
    VAL = (SELECT VAL FROM DATE2ISO(:V$DATE, 0));
    SUSPEND;
    TAG_NAME = 'portfolio:r:sport';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'portfolio:r:level';
    VAL = C;
    SUSPEND;
    TAG_NAME = 'portfolio:r:result';
    VAL = D;
    SUSPEND;
    TAG_NAME = 'portfolio:r:ver';
    VAL = V$GIA_SEL;
    SUSPEND;
  END
  FOR
    SELECT L25.OBJ_ID, C181.VAL, V1827.VAL, C180.VAL, V1828.SVAL, IIF(V3192.LISTVAL_ID = 2, 1, 0)
    FROM LINKS L25
    LEFT JOIN VALL V181 ON V181.OBJ_ID = L25.OBJ_ID AND V181.PARAM_ID = 181 AND V181.IS_DEL = 0
    LEFT JOIN LISTVAL_TEXT(V181.LISTVAL_ID) C181 ON 1 = 1
    LEFT JOIN VALD V1827 ON V1827.OBJ_ID = L25.OBJ_ID AND V1827.PARAM_ID = 1827 AND V1827.IS_DEL = 0
    LEFT JOIN VALL V180 ON V180.OBJ_ID = L25.OBJ_ID AND V180.PARAM_ID = 180 AND V180.IS_DEL = 0
    LEFT JOIN LISTVAL_TEXT(V180.LISTVAL_ID) C180 ON 1 = 1
    LEFT JOIN VALS V1828 ON V1828.OBJ_ID = L25.OBJ_ID AND V1828.PARAM_ID = 1828 AND V1828.IS_DEL = 0
    LEFT JOIN VALL V3192 ON V3192.OBJ_ID = L25.OBJ_ID AND V3192.PARAM_ID = 3192 AND V3192.IS_DEL = 0 -- верифицирован
    WHERE L25.PARENT_ID = :I$PERSON_ID AND L25.OBJ_TYPE_ID = 25 AND L25.DATE_DEL IS NULL
    ORDER BY L25.DATE_INS
    INTO :V$OBJ_ID, :S, :V$DATE, :C, :D, :V$GIA_SEL
  DO
  BEGIN
    TAG_NAME = 'portfolio:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'portfolio:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'portfolio:r:date';
    VAL = (SELECT VAL FROM DATE2ISO(:V$DATE, 0));
    SUSPEND;
    TAG_NAME = 'portfolio:r:part';
    VAL = 25;
    SUSPEND;
    TAG_NAME = 'portfolio:r:sport';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'portfolio:r:level';
    VAL = C;
    SUSPEND;
    TAG_NAME = 'portfolio:r:org_name';
    VAL = D;
    SUSPEND;
    TAG_NAME = 'portfolio:r:ver';
    VAL = V$GIA_SEL;
    SUSPEND;
  END

  -- Данные по ДО
  TAG_NAME = 'do::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L297.OBJ_ID, CY.VAL, V3187.VAL, V3189.VAL, V3185.VAL, V3186.VAL, V2392.LISTVAL_ID, V3183.VAL, V3184.VAL
    FROM LINKS L297
    JOIN VALL V2394 ON V2394.OBJ_ID = L297.OBJ_ID AND V2394.PARAM_ID = 2394 AND V2394.IS_DEL = 0
    LEFT JOIN VALS V3187 ON V3187.OBJ_ID = L297.OBJ_ID AND V3187.PARAM_ID = 3187 AND V3187.IS_DEL = 0
    LEFT JOIN VALS V3189 ON V3189.OBJ_ID = L297.OBJ_ID AND V3189.PARAM_ID = 3189 AND V3189.IS_DEL = 0
    LEFT JOIN VALI V3185 ON V3185.OBJ_ID = L297.OBJ_ID AND V3185.PARAM_ID = 3185 AND V3185.IS_DEL = 0
    LEFT JOIN VALI V3186 ON V3186.OBJ_ID = L297.OBJ_ID AND V3186.PARAM_ID = 3186 AND V3186.IS_DEL = 0
    LEFT JOIN VALL V2392 ON V2392.OBJ_ID = L297.OBJ_ID AND V2392.PARAM_ID = 2392 AND V2392.IS_DEL = 0
    LEFT JOIN VALD V3183 ON V3183.OBJ_ID = L297.OBJ_ID AND V3183.PARAM_ID = 3183 AND V3183.IS_DEL = 0
    LEFT JOIN VALD V3184 ON V3184.OBJ_ID = L297.OBJ_ID AND V3184.PARAM_ID = 3184 AND V3184.IS_DEL = 0
    LEFT JOIN LISTVAL_TEXT(V2394.LISTVAL_ID) CY ON 1 = 1
    WHERE L297.PARENT_ID = :I$PERSON_ID AND L297.OBJ_TYPE_ID = 297 AND L297.DATE_DEL IS NULL
    ORDER BY V2394.LISTVAL_ID, L297.OBJ_ID
    INTO :V$OBJ_ID, :D, :C, :S, :V$Y, :V$GIA_SEL, :V$EXAM_ID, :V$DATE, :V$DATE2
  DO
  BEGIN
    TAG_NAME = 'do:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'do:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'do:r:year';
    VAL = V$Y;
    SUSPEND;
    TAG_NAME = 'do:r:ou_name';
    VAL = C;
    SUSPEND;
    TAG_NAME = 'do:r:grade_name';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'do:r:direction';
    VAL = V$EXAM_ID;
    SUSPEND;
    TAG_NAME = 'do:r:stage';
    VAL = COALESCE(V$Y, '-') || COALESCE(' / ' || V$GIA_SEL, '');
    SUSPEND;
    TAG_NAME = 'do:r:date_from';
    VAL = (SELECT VAL FROM DATE2ISO(:V$DATE, 0));
    SUSPEND;
    TAG_NAME = 'do:r:date_to';
    VAL = (SELECT VAL FROM DATE2ISO(:V$DATE2, 0));
    SUSPEND;
  END

  -- Данные зачетной книжки СПО
  TAG_NAME = 'sessions::json&colon;array';
  VAL = 1;
  SUSPEND;
  IF(V$LEVEL_ID IN (29, 13131)) THEN
  FOR
    SELECT R.OBJ_ID, R.ATT_DATE, R.STATE_ID, S.STATE_ID, SC.SCAPTION, LY.COST, TC.VAL, R.STAGE_ID, R.SUBSTAGE_ID, MC.VAL, R.TIME_VAL, RC.SCAPTION, CC.VAL, MTC.SCAPTION
    FROM ATT_REGISTER_STDS S
    JOIN ATT_REGISTER R ON R.DATE_DEL IS NULL AND R.OBJ_ID = S.ATT_ID
    JOIN LISTVALS LY ON LY.LISTVAL_ID = R.YEAR_ID
    LEFT JOIN OBJECT_CAPTION_GET(R.SUBJECT_ID) SC ON 1 = 1
    LEFT JOIN OBJECT_CAPTION_GET(R.ROOM_ID) RC ON R.ROOM_ID IS NOT NULL
    LEFT JOIN LISTVAL_TEXT(R.CONTROL_TYPE_ID) CC ON 1 = 1
    LEFT JOIN LISTVAL_TEXT(R.STAGE_ID) TC ON 1 = 1
    LEFT JOIN VALM M ON M.MARK_ID = S.MARK_ID
    LEFT JOIN LISTVAL_TEXT(M.MARKVAL_ID) MC ON M.MARK_ID IS NOT NULL
    LEFT JOIN OBJECT_CAPTION_GET(M.MARK_TEACHER_ID) MTC ON M.MARK_TEACHER_ID IS NOT NULL
    WHERE S.DATE_DEL IS NULL AND S.PERSON_ID = :I$PERSON_ID
    -- сюда же выводим старые оценки вне ведомостей
    ORDER BY 8, 9, 5, 2
    INTO :V$OBJ_ID, :V$DATE, :V$SUBJ1, :V$SUBJ2, :S, :V$Y, :V$DE, V$CEC_ID, :P, :C, :D, :T, :CT, :TC
  DO
  BEGIN
    TAG_NAME = 'sessions:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'sessions:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'sessions:r:date';
    VAL = (SELECT VAL FROM DATE2ISO(:V$DATE, 0));
    SUSPEND;
    TAG_NAME = 'sessions:r:time';
    VAL = D;
    SUSPEND;
    TAG_NAME = 'sessions:r:room';
    VAL = T;
    SUSPEND;
    TAG_NAME = 'sessions:r:state_id';
    VAL = V$SUBJ1;
    SUSPEND;
    TAG_NAME = 'sessions:r:res_state';
    VAL = V$SUBJ2;
    SUSPEND;
    TAG_NAME = 'sessions:r:subject_name';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'sessions:r:control_type';
    VAL = CT;
    SUSPEND;
    TAG_NAME = 'sessions:r:period';
    VAL = V$Y || '-' || (V$Y + 1);
    SUSPEND;
    TAG_NAME = 'sessions:r:stage_name';
    VAL = V$DE;
    SUSPEND;
    TAG_NAME = 'sessions:r:substage_id';
    VAL = P;
    SUSPEND;
    TAG_NAME = 'sessions:r:markval';
    VAL = C;
    SUSPEND;
    TAG_NAME = 'sessions:r:teacher_name';
    VAL = TC;
    SUSPEND;
  END

  -- Расписание сессий в текущем учебном году
  -- с датой окончания не позднее 1 месяца в прошлое
  TAG_NAME = 'addsessions::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT V3396.VAL, V3397.VAL
    FROM LINKS L481
    JOIN VALL V3389 ON V3389.OBJ_ID = L481.OBJ_ID AND V3389.PARAM_ID = 3389 AND V3389.LISTVAL_ID = :V$YEAR_ID
    JOIN VALL V3390 ON V3390.OBJ_ID = L481.OBJ_ID AND V3390.PARAM_ID = 3390 AND V3390.LISTVAL_ID = 11715
    JOIN LINKS L151 ON L151.PARENT_ID = L481.OBJ_ID AND L151.OBJ_TYPE_ID = 151 AND L151.DATE_DEL IS NULL
    JOIN LINKS L487 ON L487.PARENT_ID = L481.OBJ_ID AND L487.OBJ_TYPE_ID = 487 AND L487.DATE_DEL IS NULL
    JOIN VALL V3603 ON V3603.OBJ_ID = L481.OBJ_ID AND V3603.PARAM_ID = 3603 AND V3603.LISTVAL_ID = 23830 -- Дополнительная
    JOIN VALD V3396 ON V3396.OBJ_ID = L481.OBJ_ID AND V3396.PARAM_ID = 3396 AND V3396.IS_DEL = 0
    JOIN VALD V3397 ON V3397.OBJ_ID = L481.OBJ_ID AND V3397.PARAM_ID = 3397 AND V3397.IS_DEL = 0 AND V3397.VAL >= DATEADD(-1 MONTH TO CURRENT_DATE)
    WHERE L481.PARENT_ID = :V$OU_ID AND L481.OBJ_TYPE_ID = 481 AND L481.DATE_DEL IS NULL
    ORDER BY 1
    INTO :V$DATE,  :V$DATE2
  DO
  BEGIN
    TAG_NAME = 'addsessions:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'addsessions:r:date_from';
    VAL = (SELECT VAL FROM DATE2ISO(:V$DATE, 0));
    SUSPEND;
    TAG_NAME = 'addsessions:r:date_to';
    VAL = (SELECT VAL FROM DATE2ISO(:V$DATE2, 0));
    SUSPEND;
  END

  -- Практика для СПО
  -- Объединяем данные из #9 и #10 по предмету
  TAG_NAME = 'practice::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    -- Практики по #9, не имеющие пары в #10
    SELECT TC.VAL, V3420.VAL, PC.VAL, SC.SCAPTION, V3604.VAL, V3605.VAL, NULL
    FROM LINKS L474
    JOIN VALL V3419 ON V3419.OBJ_ID = L474.OBJ_ID AND V3419.PARAM_ID = 3419 AND V3419.IS_DEL = 0
    LEFT JOIN LISTVAL_TEXT(V3419.LISTVAL_ID) TC ON 1 = 1
    JOIN VALI V3420 ON V3420.OBJ_ID = L474.OBJ_ID AND V3420.PARAM_ID = 3420 AND V3420.IS_DEL = 0
    JOIN VALL V3334 ON V3334.OBJ_ID = L474.OBJ_ID AND V3334.PARAM_ID = 3334 AND V3334.IS_DEL = 0
    LEFT JOIN LISTVAL_TEXT(V3334.LISTVAL_ID) PC ON 1 = 1
    LEFT JOIN VALD V3604 ON V3604.OBJ_ID = L474.OBJ_ID AND V3604.PARAM_ID = 3604 AND V3604.IS_DEL = 0
    LEFT JOIN VALD V3605 ON V3605.OBJ_ID = L474.OBJ_ID AND V3605.PARAM_ID = 3605 AND V3605.IS_DEL = 0
    JOIN VALR V3425 ON V3425.OBJ_ID = L474.OBJ_ID AND V3425.PARAM_ID = 3425 AND V3425.IS_DEL = 0
    LEFT JOIN OBJECT_CAPTION_GET(V3425.VAL) SC ON 1 = 1
    WHERE L474.PARENT_ID = :V$GROUP_ID AND L474.OBJ_TYPE_ID = 474 AND L474.DATE_DEL IS NULL
    /* AND NOT EXISTS(
      SELECT FIRST 1 1
      FROM LINKS L474X
      JOIN VALR V3425 ON V3425.OBJ_ID = L474.OBJ_ID AND V3425.PARAM_ID = 3425 AND V3425.IS_DEL = 0
      JOIN VALR V3425X ON V3425X.OBJ_ID = L474X.OBJ_ID AND V3425X.PARAM_ID = 3425 AND V3425X.IS_DEL = 0 AND V3425X.VAL = V3425.VAL
      WHERE L474X.PARENT_ID = :I$PERSON_ID AND L474X.OBJ_TYPE_ID = 474 AND L474X.DATE_DEL IS NULL
    )
    UNION
    -- Практики по самой персоне - с оценкой
    SELECT TC.VAL, V3420.VAL, PC.VAL, SC.SCAPTION, V3604.VAL, V3605.VAL, V3415.SVAL
    FROM LINKS L474
    JOIN VALL V3419 ON V3419.OBJ_ID = L474.OBJ_ID AND V3419.PARAM_ID = 3419 AND V3419.IS_DEL = 0
    LEFT JOIN LISTVAL_TEXT(V3419.LISTVAL_ID) TC ON 1 = 1
    JOIN VALI V3420 ON V3420.OBJ_ID = L474.OBJ_ID AND V3420.PARAM_ID = 3420 AND V3420.IS_DEL = 0
    JOIN VALL V3334 ON V3334.OBJ_ID = L474.OBJ_ID AND V3334.PARAM_ID = 3334 AND V3334.IS_DEL = 0
    LEFT JOIN LISTVAL_TEXT(V3334.LISTVAL_ID) PC ON 1 = 1
    LEFT JOIN VALD V3604 ON V3604.OBJ_ID = L474.OBJ_ID AND V3604.PARAM_ID = 3604 AND V3604.IS_DEL = 0
    LEFT JOIN VALD V3605 ON V3605.OBJ_ID = L474.OBJ_ID AND V3605.PARAM_ID = 3605 AND V3605.IS_DEL = 0
    JOIN VALR V3425 ON V3425.OBJ_ID = L474.OBJ_ID AND V3425.PARAM_ID = 3425 AND V3425.IS_DEL = 0
    LEFT JOIN OBJECT_CAPTION_GET(V3425.VAL) SC ON 1 = 1
    LEFT JOIN VALS V3415 ON V3415.OBJ_ID = L474.OBJ_ID AND V3415.PARAM_ID = 3415 AND V3415.IS_DEL = 0
    WHERE L474.PARENT_ID = :I$PERSON_ID AND L474.OBJ_TYPE_ID = 474 AND L474.DATE_DEL IS NULL
    */
    ORDER BY 1, 2
    INTO :D, :P, :C, :S, :V$DATE, :V$DATE2, :T
  DO
  BEGIN
    TAG_NAME = 'practice:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'practice:r:stage_name';
    VAL = D;
    SUSPEND;
    TAG_NAME = 'practice:r:substage_id';
    VAL = P;
    SUSPEND;
    TAG_NAME = 'practice:r:type_name';
    VAL = C;
    SUSPEND;
    TAG_NAME = 'practice:r:subject_name';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'practice:r:date_from';
    VAL = (SELECT VAL FROM DATE2ISO(:V$DATE, 0));
    SUSPEND;
    TAG_NAME = 'practice:r:date_to';
    VAL = (SELECT VAL FROM DATE2ISO(:V$DATE2, 0));
    SUSPEND;
    TAG_NAME = 'practice:r:result';
    VAL = T;
    SUSPEND;
  END

  -- Госэкзамены для СПО
  TAG_NAME = 'gosexams::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L493.OBJ_ID, V3423.VAL, MC.VAL, SC.SCAPTION
    FROM LINKS L493
    JOIN VALR V3421 ON V3421.OBJ_ID = L493.OBJ_ID AND V3421.PARAM_ID = 3421 AND V3421.IS_DEL = 0
    LEFT JOIN OBJECT_CAPTION_GET(V3421.VAL) SC ON 1 = 1
    LEFT JOIN VALL V3422 ON V3422.OBJ_ID = L493.OBJ_ID AND V3422.PARAM_ID = 3422 AND V3422.IS_DEL = 0
    LEFT JOIN LISTVAL_TEXT(V3422.LISTVAL_ID) MC ON V3422.LISTVAL_ID IS NOT NULL
    LEFT JOIN VALD V3423 ON V3423.OBJ_ID = L493.OBJ_ID AND V3423.PARAM_ID = 3423 AND V3423.IS_DEL = 0
    WHERE L493.PARENT_ID = :I$PERSON_ID AND L493.OBJ_TYPE_ID = 493 AND L493.DATE_DEL IS NULL
    ORDER BY 2, 4
    INTO :V$OBJ_ID, :V$DATE, :C, :S
  DO
  BEGIN
    TAG_NAME = 'gosexams:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'gosexams:r:date';
    VAL = (SELECT VAL FROM DATE2ISO(:V$DATE, 0));
    SUSPEND;
    TAG_NAME = 'gosexams:r:subject_name';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'gosexams:r:result';
    VAL = C;
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PF_EDU (
    I$OBJ_ID BIGINT,
    I$BLOCK_NAME VARCHAR(40),
    I$BLOCK_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(1000))
AS
declare variable V$TYPE_ID bigint;
begin

  SELECT TYPE_ID
  FROM OBJECTS
  WHERE OBJ_ID = :I$OBJ_ID
  INTO :V$TYPE_ID;

  IF(V$TYPE_ID = 2) THEN
  BEGIN
    FOR
      SELECT D.TAG_NAME, D.VAL
      FROM PF_EDU_OU(:I$OBJ_ID, :I$BLOCK_NAME, :I$BLOCK_ID, :I$USER_ID) D
      INTO :TAG_NAME, :VAL
    DO
    BEGIN
      SUSPEND;
    END
  END
  ELSE IF(V$TYPE_ID = 111) THEN
  BEGIN
    FOR
      SELECT D.TAG_NAME, D.VAL
      FROM PF_EDU_DIST(:I$OBJ_ID, :I$BLOCK_NAME, :I$BLOCK_ID, :I$USER_ID) D
      INTO :TAG_NAME, :VAL
    DO
    BEGIN
      SUSPEND;
    END
  END
  ELSE IF(V$TYPE_ID = 112) THEN
  BEGIN
    FOR
      SELECT D.TAG_NAME, D.VAL
      FROM PF_EDU_RGN(:I$OBJ_ID, :I$BLOCK_NAME, :I$BLOCK_ID, :I$USER_ID) D
      INTO :TAG_NAME, :VAL
    DO
    BEGIN
      SUSPEND;
    END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PF_EDU_DIST (
    I$OBJ_ID BIGINT,
    I$BLOCK_NAME VARCHAR(40),
    I$BLOCK_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(1000))
AS
declare variable V$VAL bigint;
declare variable V$VAL2 bigint;
declare variable S varchar(1000);
declare variable V$TYPE_ID1 bigint;
declare variable V$TYPE_ID2 bigint;
declare variable V$MID_TYPE bigint;
declare variable V$OBJ_ID bigint;
declare variable V$PARAM_ID bigint;
declare variable V$TYPE bigint;
declare variable V$T bigint;
declare variable V$MASTER_ID bigint;
begin

  IF(I$BLOCK_NAME IS NULL) THEN
  BEGIN
    -- Оглавление
    TAG_NAME = 'dashboard::json&colon;array';
    VAL = 1;
    SUSPEND;

    SELECT COUNT(DISTINCT L57.OBJ_ID)
    FROM LINKS L2
    JOIN LINKS L69 ON L69.PARENT_ID = L2.OBJ_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL
    JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
    JOIN LINKS L400 ON L400.PARENT_ID = L57.OBJ_ID AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL
    JOIN VALL V3013 ON V3013.OBJ_ID = L400.OBJ_ID AND V3013.PARAM_ID = 3013 AND V3013.IS_DEL = 0 AND V3013.LISTVAL_ID = 11715
    JOIN VALL V3022 ON V3022.OBJ_ID = L400.OBJ_ID AND V3022.PARAM_ID = 3022 AND V3022.IS_DEL = 0
    JOIN VALL V3016 ON V3016.OBJ_ID = L400.OBJ_ID AND V3016.PARAM_ID = 3016 AND V3016.IS_DEL = 0
    WHERE L2.PARENT_ID = :I$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'edu';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '400';
    SUSPEND;
    TAG_NAME = 'dashboard:r:subtype_id';
    VAL = '';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'graduation cap';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#410093';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Количество образовательных программ';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

    SELECT COUNT(DISTINCT V3112.LISTVAL_ID)
    FROM LINKS L2
    JOIN LINKS L69 ON L69.PARENT_ID = L2.OBJ_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL
    JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
    JOIN LINKS L400 ON L400.PARENT_ID = L57.OBJ_ID AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL
    JOIN VALL V3013 ON V3013.OBJ_ID = L400.OBJ_ID AND V3013.PARAM_ID = 3013 AND V3013.IS_DEL = 0 AND V3013.LISTVAL_ID = 11715
    JOIN VALL V3022 ON V3022.OBJ_ID = L400.OBJ_ID AND V3022.PARAM_ID = 3022 AND V3022.IS_DEL = 0
    JOIN VALL V3016 ON V3016.OBJ_ID = L400.OBJ_ID AND V3016.PARAM_ID = 3016 AND V3016.IS_DEL = 0
    JOIN VALL V3112 ON V3112.OBJ_ID = L400.OBJ_ID AND V3112.PARAM_ID = 3112 AND V3112.IS_DEL = 0
    WHERE L2.PARENT_ID = :I$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'byprofile';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '400';
    SUSPEND;
    TAG_NAME = 'dashboard:r:subtype_id';
    VAL = '';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'tag';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#410093';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Количество профилей обучения';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

    SELECT COUNT(DISTINCT L400.OBJ_ID)
    FROM LINKS L2
    JOIN LINKS L69 ON L69.PARENT_ID = L2.OBJ_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL
    JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
    JOIN LINKS L400 ON L400.PARENT_ID = L57.OBJ_ID AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL
    JOIN VALL V3013 ON V3013.OBJ_ID = L400.OBJ_ID AND V3013.PARAM_ID = 3013 AND V3013.IS_DEL = 0 AND V3013.LISTVAL_ID = 11715
    JOIN VALL V3022 ON V3022.OBJ_ID = L400.OBJ_ID AND V3022.PARAM_ID = 3022 AND V3022.IS_DEL = 0
    JOIN VALL V3016 ON V3016.OBJ_ID = L400.OBJ_ID AND V3016.PARAM_ID = 3016 AND V3016.IS_DEL = 0
    JOIN VALL V2379 ON V2379.OBJ_ID = L400.OBJ_ID AND V2379.PARAM_ID = 2379 AND V2379.IS_DEL = 0 AND V2379.LISTVAL_ID <> 287
    WHERE L2.PARENT_ID = :I$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'byadapt';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '400';
    SUSPEND;
    TAG_NAME = 'dashboard:r:subtype_id';
    VAL = '';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'wheelchair';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#410093';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Количество адаптированных УП';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

    SELECT COUNT(DISTINCT L400.OBJ_ID)
    FROM LINKS L2
    JOIN LINKS L69 ON L69.PARENT_ID = L2.OBJ_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL
    JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
    JOIN LINKS L400 ON L400.PARENT_ID = L57.OBJ_ID AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL
    JOIN VALL V3013 ON V3013.OBJ_ID = L400.OBJ_ID AND V3013.PARAM_ID = 3013 AND V3013.IS_DEL = 0 AND V3013.LISTVAL_ID = 11715
    JOIN VALL V3022 ON V3022.OBJ_ID = L400.OBJ_ID AND V3022.PARAM_ID = 3022 AND V3022.IS_DEL = 0
    JOIN VALL V3016 ON V3016.OBJ_ID = L400.OBJ_ID AND V3016.PARAM_ID = 3016 AND V3016.IS_DEL = 0
    LEFT JOIN VALL V1891 ON V1891.OBJ_ID = L57.OBJ_ID AND V1891.PARAM_ID = 1891 AND V1891.IS_DEL = 0
    LEFT JOIN VALL V2833 ON V2833.OBJ_ID = L57.OBJ_ID AND V2833.PARAM_ID = 2833 AND V2833.IS_DEL = 0
    WHERE L2.PARENT_ID = :I$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'byextern';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '400';
    SUSPEND;
    TAG_NAME = 'dashboard:r:subtype_id';
    VAL = '';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'rss';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#410093';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Количество сетевых или дистанционных УП';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

    SELECT COUNT(DISTINCT L400.OBJ_ID)
    FROM LINKS L2
    JOIN LINKS L69 ON L69.PARENT_ID = L2.OBJ_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL
    JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
    JOIN LINKS L400 ON L400.PARENT_ID = L57.OBJ_ID AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL
    JOIN VALL V3013 ON V3013.OBJ_ID = L400.OBJ_ID AND V3013.PARAM_ID = 3013 AND V3013.IS_DEL = 0 AND V3013.LISTVAL_ID = 11715
    JOIN VALL V3022 ON V3022.OBJ_ID = L400.OBJ_ID AND V3022.PARAM_ID = 3022 AND V3022.IS_DEL = 0
    JOIN VALL V3016 ON V3016.OBJ_ID = L400.OBJ_ID AND V3016.PARAM_ID = 3016 AND V3016.IS_DEL = 0 AND V3016.LISTVAL_ID <> 5465
    WHERE L2.PARENT_ID = :I$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'byind';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '400';
    SUSPEND;
    TAG_NAME = 'dashboard:r:subtype_id';
    VAL = '80';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'sun';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#410093';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Количество индивидуальных УП';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

  END
  ELSE
  BEGIN

    TAG_NAME = 'title';
    VAL = 'Образовательные программы и учебные планы';
    SUSPEND;

    TAG_NAME = 'has_caption';
    VAL = 1;
    SUSPEND;

    TAG_NAME = 'columns::json&colon;array';
    VAL = 1;
    SUSPEND;

    TAG_NAME = 'columns:r'; VAL = NULL; SUSPEND;
    TAG_NAME = 'columns:r:type_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:param_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:type'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:name'; VAL = 'Количество образовательных программ'; SUSPEND;

    TAG_NAME = 'columns:r'; VAL = NULL; SUSPEND;
    TAG_NAME = 'columns:r:type_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:param_id'; VAL = '2'; SUSPEND;
    TAG_NAME = 'columns:r:type'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:name'; VAL = 'Количество профилей обучения'; SUSPEND;

    TAG_NAME = 'columns:r'; VAL = NULL; SUSPEND;
    TAG_NAME = 'columns:r:type_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:param_id'; VAL = '3'; SUSPEND;
    TAG_NAME = 'columns:r:type'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:name'; VAL = 'Количество адаптированных УП'; SUSPEND;

    TAG_NAME = 'columns:r'; VAL = NULL; SUSPEND;
    TAG_NAME = 'columns:r:type_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:param_id'; VAL = '4'; SUSPEND;
    TAG_NAME = 'columns:r:type'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:name'; VAL = 'Количество сетевых или дистанционных УП'; SUSPEND;

    TAG_NAME = 'columns:r'; VAL = NULL; SUSPEND;
    TAG_NAME = 'columns:r:type_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:param_id'; VAL = '5'; SUSPEND;
    TAG_NAME = 'columns:r:type'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:name'; VAL = 'Количество индивидуальных УП'; SUSPEND;

    -- Развертка по районам
    TAG_NAME = 'rows::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT L2.OBJ_ID, L2.OBJ_TYPE_ID, C.CAPTION
      FROM LINKS L2
      LEFT JOIN OBJECT_CAPTION_GET(L2.OBJ_ID) C ON 1 = 1
      WHERE L2.PARENT_ID = :I$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      ORDER BY 3
      INTO :V$OBJ_ID, :V$TYPE, :S
    DO
    BEGIN
      TAG_NAME = 'rows:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'rows:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'rows:r:type_id';
      VAL = '1';
      SUSPEND;
      TAG_NAME = 'rows:r:caption';
      VAL = S;
      SUSPEND;

      SELECT COUNT(DISTINCT L57.OBJ_ID)
      FROM LINKS L69
      JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
      JOIN LINKS L400 ON L400.PARENT_ID = L57.OBJ_ID AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL
      JOIN VALL V3013 ON V3013.OBJ_ID = L400.OBJ_ID AND V3013.PARAM_ID = 3013 AND V3013.IS_DEL = 0 AND V3013.LISTVAL_ID = 11715
      JOIN VALL V3022 ON V3022.OBJ_ID = L400.OBJ_ID AND V3022.PARAM_ID = 3022 AND V3022.IS_DEL = 0
      JOIN VALL V3016 ON V3016.OBJ_ID = L400.OBJ_ID AND V3016.PARAM_ID = 3016 AND V3016.IS_DEL = 0
      WHERE L69.PARENT_ID = :V$OBJ_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL
      INTO :V$VAL;

      TAG_NAME = 'rows:r:p1';
      VAL = V$VAL;
      SUSPEND;

      SELECT COUNT(DISTINCT V3112.LISTVAL_ID)
      FROM LINKS L69
      JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
      JOIN LINKS L400 ON L400.PARENT_ID = L57.OBJ_ID AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL
      JOIN VALL V3013 ON V3013.OBJ_ID = L400.OBJ_ID AND V3013.PARAM_ID = 3013 AND V3013.IS_DEL = 0 AND V3013.LISTVAL_ID = 11715
      JOIN VALL V3022 ON V3022.OBJ_ID = L400.OBJ_ID AND V3022.PARAM_ID = 3022 AND V3022.IS_DEL = 0
      JOIN VALL V3016 ON V3016.OBJ_ID = L400.OBJ_ID AND V3016.PARAM_ID = 3016 AND V3016.IS_DEL = 0
      JOIN VALL V3112 ON V3112.OBJ_ID = L400.OBJ_ID AND V3112.PARAM_ID = 3112 AND V3112.IS_DEL = 0
      WHERE L69.PARENT_ID = :V$OBJ_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL
      INTO :V$VAL;

      TAG_NAME = 'rows:r:p2';
      VAL = V$VAL;
      SUSPEND;

      SELECT COUNT(DISTINCT L400.OBJ_ID)
      FROM LINKS L69
      JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
      JOIN LINKS L400 ON L400.PARENT_ID = L57.OBJ_ID AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL
      JOIN VALL V3013 ON V3013.OBJ_ID = L400.OBJ_ID AND V3013.PARAM_ID = 3013 AND V3013.IS_DEL = 0 AND V3013.LISTVAL_ID = 11715
      JOIN VALL V3022 ON V3022.OBJ_ID = L400.OBJ_ID AND V3022.PARAM_ID = 3022 AND V3022.IS_DEL = 0
      JOIN VALL V3016 ON V3016.OBJ_ID = L400.OBJ_ID AND V3016.PARAM_ID = 3016 AND V3016.IS_DEL = 0
      JOIN VALL V2379 ON V2379.OBJ_ID = L400.OBJ_ID AND V2379.PARAM_ID = 2379 AND V2379.IS_DEL = 0 AND V2379.LISTVAL_ID <> 287
      WHERE L69.PARENT_ID = :V$OBJ_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL
      INTO :V$VAL;

      TAG_NAME = 'rows:r:p3';
      VAL = V$VAL;
      SUSPEND;

      SELECT COUNT(DISTINCT L400.OBJ_ID)
      FROM LINKS L69
      JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
      JOIN LINKS L400 ON L400.PARENT_ID = L57.OBJ_ID AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL
      JOIN VALL V3013 ON V3013.OBJ_ID = L400.OBJ_ID AND V3013.PARAM_ID = 3013 AND V3013.IS_DEL = 0 AND V3013.LISTVAL_ID = 11715
      JOIN VALL V3022 ON V3022.OBJ_ID = L400.OBJ_ID AND V3022.PARAM_ID = 3022 AND V3022.IS_DEL = 0
      JOIN VALL V3016 ON V3016.OBJ_ID = L400.OBJ_ID AND V3016.PARAM_ID = 3016 AND V3016.IS_DEL = 0
      LEFT JOIN VALL V1891 ON V1891.OBJ_ID = L57.OBJ_ID AND V1891.PARAM_ID = 1891 AND V1891.IS_DEL = 0
      LEFT JOIN VALL V2833 ON V2833.OBJ_ID = L57.OBJ_ID AND V2833.PARAM_ID = 2833 AND V2833.IS_DEL = 0
      WHERE L69.PARENT_ID = :V$OBJ_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL
      INTO :V$VAL;

      TAG_NAME = 'rows:r:p4';
      VAL = V$VAL;
      SUSPEND;

      SELECT COUNT(DISTINCT L400.OBJ_ID)
      FROM LINKS L69
      JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
      JOIN LINKS L400 ON L400.PARENT_ID = L57.OBJ_ID AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL
      JOIN VALL V3013 ON V3013.OBJ_ID = L400.OBJ_ID AND V3013.PARAM_ID = 3013 AND V3013.IS_DEL = 0 AND V3013.LISTVAL_ID = 11715
      JOIN VALL V3022 ON V3022.OBJ_ID = L400.OBJ_ID AND V3022.PARAM_ID = 3022 AND V3022.IS_DEL = 0
      JOIN VALL V3016 ON V3016.OBJ_ID = L400.OBJ_ID AND V3016.PARAM_ID = 3016 AND V3016.IS_DEL = 0 AND V3016.LISTVAL_ID <> 5465
      WHERE L69.PARENT_ID = :V$OBJ_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL
      INTO :V$VAL;

      TAG_NAME = 'rows:r:p5';
      VAL = V$VAL;
      SUSPEND;

    END

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PF_EDU_OU (
    I$OBJ_ID BIGINT,
    I$BLOCK_NAME VARCHAR(40),
    I$BLOCK_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(1000))
AS
declare variable V$VAL bigint;
declare variable V$VAL2 bigint;
declare variable F float;
declare variable S varchar(1000);
declare variable S2 varchar(1000);
declare variable V$P1 bigint;
declare variable V$P2 bigint;
declare variable V$P3 bigint;
declare variable V$P4 bigint;
declare variable V$P5 bigint;
declare variable V$TYPE_ID1 bigint;
declare variable V$TYPE_ID2 bigint;
declare variable V$MID_TYPE bigint;
declare variable V$OBJ_ID bigint;
declare variable V$PARAM_ID bigint;
declare variable V$TYPE bigint;
declare variable V$T bigint;
declare variable V$MASTER_ID bigint;
begin

  IF(I$BLOCK_NAME IS NULL) THEN
  BEGIN
    -- Оглавление
    TAG_NAME = 'dashboard::json&colon;array';
    VAL = 1;
    SUSPEND;

    SELECT COUNT(DISTINCT L57.OBJ_ID)
    FROM LINKS L69
    JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
    JOIN LINKS L400 ON L400.PARENT_ID = L57.OBJ_ID AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL
    JOIN VALL V3013 ON V3013.OBJ_ID = L400.OBJ_ID AND V3013.PARAM_ID = 3013 AND V3013.IS_DEL = 0 AND V3013.LISTVAL_ID = 11715
    JOIN VALL V3022 ON V3022.OBJ_ID = L400.OBJ_ID AND V3022.PARAM_ID = 3022 AND V3022.IS_DEL = 0
    JOIN VALL V3016 ON V3016.OBJ_ID = L400.OBJ_ID AND V3016.PARAM_ID = 3016 AND V3016.IS_DEL = 0
    WHERE L69.PARENT_ID = :I$OBJ_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'edu';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '400';
    SUSPEND;
    TAG_NAME = 'dashboard:r:subtype_id';
    VAL = '';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'graduation cap';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#410093';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Количество образовательных программ';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

    SELECT COUNT(DISTINCT V3112.LISTVAL_ID)
    FROM LINKS L69
    JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
    JOIN LINKS L400 ON L400.PARENT_ID = L57.OBJ_ID AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL
    JOIN VALL V3013 ON V3013.OBJ_ID = L400.OBJ_ID AND V3013.PARAM_ID = 3013 AND V3013.IS_DEL = 0 AND V3013.LISTVAL_ID = 11715
    JOIN VALL V3022 ON V3022.OBJ_ID = L400.OBJ_ID AND V3022.PARAM_ID = 3022 AND V3022.IS_DEL = 0
    JOIN VALL V3016 ON V3016.OBJ_ID = L400.OBJ_ID AND V3016.PARAM_ID = 3016 AND V3016.IS_DEL = 0
    JOIN VALL V3112 ON V3112.OBJ_ID = L400.OBJ_ID AND V3112.PARAM_ID = 3112 AND V3112.IS_DEL = 0
    WHERE L69.PARENT_ID = :I$OBJ_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'byprofile';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '400';
    SUSPEND;
    TAG_NAME = 'dashboard:r:subtype_id';
    VAL = '';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'tag';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#410093';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Количество профилей обучения';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

    SELECT COUNT(DISTINCT L400.OBJ_ID)
    FROM LINKS L69
    JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
    JOIN LINKS L400 ON L400.PARENT_ID = L57.OBJ_ID AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL
    JOIN VALL V3013 ON V3013.OBJ_ID = L400.OBJ_ID AND V3013.PARAM_ID = 3013 AND V3013.IS_DEL = 0 AND V3013.LISTVAL_ID = 11715
    JOIN VALL V3022 ON V3022.OBJ_ID = L400.OBJ_ID AND V3022.PARAM_ID = 3022 AND V3022.IS_DEL = 0
    JOIN VALL V3016 ON V3016.OBJ_ID = L400.OBJ_ID AND V3016.PARAM_ID = 3016 AND V3016.IS_DEL = 0
    JOIN VALL V2379 ON V2379.OBJ_ID = L400.OBJ_ID AND V2379.PARAM_ID = 2379 AND V2379.IS_DEL = 0 AND V2379.LISTVAL_ID <> 11187
    WHERE L69.PARENT_ID = :I$OBJ_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'byadapt';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '400';
    SUSPEND;
    TAG_NAME = 'dashboard:r:subtype_id';
    VAL = '';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'wheelchair';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#410093';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Количество адаптированных УП';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

    SELECT COUNT(DISTINCT L400.OBJ_ID)
    FROM LINKS L69
    JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
    JOIN LINKS L400 ON L400.PARENT_ID = L57.OBJ_ID AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL
    JOIN VALL V3013 ON V3013.OBJ_ID = L400.OBJ_ID AND V3013.PARAM_ID = 3013 AND V3013.IS_DEL = 0 AND V3013.LISTVAL_ID = 11715
    JOIN VALL V3022 ON V3022.OBJ_ID = L400.OBJ_ID AND V3022.PARAM_ID = 3022 AND V3022.IS_DEL = 0
    JOIN VALL V3016 ON V3016.OBJ_ID = L400.OBJ_ID AND V3016.PARAM_ID = 3016 AND V3016.IS_DEL = 0
    LEFT JOIN VALL V1891 ON V1891.OBJ_ID = L57.OBJ_ID AND V1891.PARAM_ID = 1891 AND V1891.IS_DEL = 0
    LEFT JOIN VALL V2833 ON V2833.OBJ_ID = L57.OBJ_ID AND V2833.PARAM_ID = 2833 AND V2833.IS_DEL = 0
    WHERE L69.PARENT_ID = :I$OBJ_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL AND (V1891.LISTVAL_ID = 2 OR V2833.LISTVAL_ID = 2)
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'byextern';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '400';
    SUSPEND;
    TAG_NAME = 'dashboard:r:subtype_id';
    VAL = '';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'rss';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#410093';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Количество сетевых или дистанционных УП';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

    SELECT COUNT(DISTINCT L400.OBJ_ID)
    FROM LINKS L69
    JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
    JOIN LINKS L400 ON L400.PARENT_ID = L57.OBJ_ID AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL
    JOIN VALL V3013 ON V3013.OBJ_ID = L400.OBJ_ID AND V3013.PARAM_ID = 3013 AND V3013.IS_DEL = 0 AND V3013.LISTVAL_ID = 11715
    JOIN VALL V3022 ON V3022.OBJ_ID = L400.OBJ_ID AND V3022.PARAM_ID = 3022 AND V3022.IS_DEL = 0
    JOIN VALL V3016 ON V3016.OBJ_ID = L400.OBJ_ID AND V3016.PARAM_ID = 3016 AND V3016.IS_DEL = 0 AND V3016.LISTVAL_ID <> 5465
    WHERE L69.PARENT_ID = :I$OBJ_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'byind';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '400';
    SUSPEND;
    TAG_NAME = 'dashboard:r:subtype_id';
    VAL = '80';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'sun';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#410093';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Количество индивидуальных УП';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

  END
  ELSE
  BEGIN

    V$TYPE = 400;
    TAG_NAME = 'has_caption';
    VAL = 0;
    SUSPEND;

    TAG_NAME = 'title';
    VAL = 'Образовательные программы и учебные планы';
    --IF(I$BLOCK_NAME = 'students') THEN VAL = 'Распределение обучающихся';
    --ELSE IF(I$BLOCK_NAME = 'byovz') THEN VAL = 'Обучающиеся по ОВЗ';
    --ELSE IF(I$BLOCK_NAME = 'byform') THEN VAL = 'Обучающиеся по форме обучения';
    --ELSE IF(I$BLOCK_NAME = 'bylevel') THEN VAL = 'Обучающиеся по ступеням обучения';
    --ELSE IF(I$BLOCK_NAME = 'classes') THEN VAL = 'Распределение по классам';
    --ELSE IF(I$BLOCK_NAME = 'accepted') THEN VAL = 'Распределение зачисленных';
    --ELSE IF(I$BLOCK_NAME = 'leaved') THEN VAL = 'Распределение выбывших';
    --ELSE VAL = '???';
    SUSPEND;

    TAG_NAME = 'columns::json&colon;array';
    VAL = 1;
    SUSPEND;
      TAG_NAME = 'columns:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'columns:r:type_id';
      VAL = 400;
      SUSPEND;
      TAG_NAME = 'columns:r:param_id';
      VAL = 0;
      SUSPEND;
      TAG_NAME = 'columns:r:type';
      VAL = 8;
      SUSPEND;
      TAG_NAME = 'columns:r:name';
      VAL = 'Образовательная программа';
      SUSPEND;

      TAG_NAME = 'columns:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'columns:r:type_id';
      VAL = 400;
      SUSPEND;
      TAG_NAME = 'columns:r:param_id';
      VAL = 1;
      SUSPEND;
      TAG_NAME = 'columns:r:type';
      VAL = 8;
      SUSPEND;
      TAG_NAME = 'columns:r:name';
      VAL = 'Учебный план';
      SUSPEND;

      TAG_NAME = 'columns:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'columns:r:type_id';
      VAL = 400;
      SUSPEND;
      TAG_NAME = 'columns:r:param_id';
      VAL = 2;
      SUSPEND;
      TAG_NAME = 'columns:r:type';
      VAL = 8;
      SUSPEND;
      TAG_NAME = 'columns:r:name';
      VAL = 'Адаптированность';
      SUSPEND;

      TAG_NAME = 'columns:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'columns:r:type_id';
      VAL = 400;
      SUSPEND;
      TAG_NAME = 'columns:r:param_id';
      VAL = 3;
      SUSPEND;
      TAG_NAME = 'columns:r:type';
      VAL = 8;
      SUSPEND;
      TAG_NAME = 'columns:r:name';
      VAL = 'Тип';
      SUSPEND;

      TAG_NAME = 'columns:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'columns:r:type_id';
      VAL = 400;
      SUSPEND;
      TAG_NAME = 'columns:r:param_id';
      VAL = 4;
      SUSPEND;
      TAG_NAME = 'columns:r:type';
      VAL = 8;
      SUSPEND;
      TAG_NAME = 'columns:r:name';
      VAL = 'Профиль';
      SUSPEND;

      TAG_NAME = 'columns:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'columns:r:type_id';
      VAL = 400;
      SUSPEND;
      TAG_NAME = 'columns:r:param_id';
      VAL = 5;
      SUSPEND;
      TAG_NAME = 'columns:r:type';
      VAL = 8;
      SUSPEND;
      TAG_NAME = 'columns:r:name';
      VAL = 'Сетевой';
      SUSPEND;

      TAG_NAME = 'columns:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'columns:r:type_id';
      VAL = 400;
      SUSPEND;
      TAG_NAME = 'columns:r:param_id';
      VAL = 6;
      SUSPEND;
      TAG_NAME = 'columns:r:type';
      VAL = 8;
      SUSPEND;
      TAG_NAME = 'columns:r:name';
      VAL = 'Дистанционный';
      SUSPEND;

      TAG_NAME = 'columns:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'columns:r:type_id';
      VAL = 400;
      SUSPEND;
      TAG_NAME = 'columns:r:param_id';
      VAL = 7;
      SUSPEND;
      TAG_NAME = 'columns:r:type';
      VAL = 8;
      SUSPEND;
      TAG_NAME = 'columns:r:name';
      VAL = 'Предметы с углубленным изучением';
      SUSPEND;

      TAG_NAME = 'columns:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'columns:r:type_id';
      VAL = 400;
      SUSPEND;
      TAG_NAME = 'columns:r:param_id';
      VAL = 100;
      SUSPEND;
      TAG_NAME = 'columns:r:type';
      VAL = 1;
      SUSPEND;
      TAG_NAME = 'columns:r:name';
      VAL = 'Количество обучающихся';
      SUSPEND;

    TAG_NAME = 'rows::json&colon;array';
    VAL = 1;
    SUSPEND;

    IF(I$BLOCK_NAME IS NOT NULL) THEN
      -- По параллелям
      FOR
        SELECT L400.OBJ_ID, COP.CAPTION, CP.CAPTION, V2379.LISTVAL_ID, V3013.LISTVAL_ID, V3112.LISTVAL_ID, V1891.LISTVAL_ID, V2833.LISTVAL_ID
        FROM LINKS L69
        JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
        JOIN LINKS L400 ON L400.PARENT_ID = L57.OBJ_ID AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL
        JOIN VALL V3013 ON V3013.OBJ_ID = L400.OBJ_ID AND V3013.PARAM_ID = 3013 AND V3013.IS_DEL = 0 AND V3013.LISTVAL_ID = 11715
        JOIN VALL V3022 ON V3022.OBJ_ID = L400.OBJ_ID AND V3022.PARAM_ID = 3022 AND V3022.IS_DEL = 0 AND V3022.LISTVAL_ID = 3 -- не ВД
        JOIN VALL V3016 ON V3016.OBJ_ID = L400.OBJ_ID AND V3016.PARAM_ID = 3016 AND V3016.IS_DEL = 0
        JOIN VALL V3112 ON V3112.OBJ_ID = L400.OBJ_ID AND V3112.PARAM_ID = 3112 AND V3112.IS_DEL = 0
        JOIN VALL V2379 ON V2379.OBJ_ID = L57.OBJ_ID AND V2379.PARAM_ID = 2379 AND V2379.IS_DEL = 0
        JOIN VALL V1891 ON V1891.OBJ_ID = L57.OBJ_ID AND V1891.PARAM_ID = 1891 AND V1891.IS_DEL = 0
        JOIN VALL V2833 ON V2833.OBJ_ID = L57.OBJ_ID AND V2833.PARAM_ID = 2833 AND V2833.IS_DEL = 0
        LEFT JOIN OBJECT_CAPTION_GET(L57.OBJ_ID) COP ON 1 = 1
        LEFT JOIN OBJECT_CAPTION_GET(L400.OBJ_ID) CP ON 1 = 1
        WHERE L69.PARENT_ID = :I$OBJ_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL
        ORDER BY 2, 3
        INTO :V$OBJ_ID, :S, :S2, :V$P1, :V$P2, :V$P3, :V$P4, :V$P5
      DO
      BEGIN
        TAG_NAME = 'rows:r';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'rows:r:id';
        VAL = V$OBJ_ID;
        SUSPEND;
        TAG_NAME = 'rows:r:type_id';
        VAL = V$TYPE;
        SUSPEND;
        TAG_NAME = 'rows:r:p0';
        VAL = S;
        SUSPEND;
        TAG_NAME = 'rows:r:p1';
        VAL = S2;
        SUSPEND;
        TAG_NAME = 'rows:r:p2';
        VAL = (SELECT VAL FROM LISTVAL_TEXT(:V$P1));
        SUSPEND;
        TAG_NAME = 'rows:r:p3';
        VAL = (SELECT VAL FROM LISTVAL_TEXT(:V$P2));
        SUSPEND;
        TAG_NAME = 'rows:r:p4';
        VAL = (SELECT VAL FROM LISTVAL_TEXT(:V$P3));
        SUSPEND;
        TAG_NAME = 'rows:r:p5';
        VAL = (SELECT VAL FROM LISTVAL_TEXT(:V$P4));
        SUSPEND;
        TAG_NAME = 'rows:r:p6';
        VAL = (SELECT VAL FROM LISTVAL_TEXT(:V$P5));
        SUSPEND;
        TAG_NAME = 'rows:r:p7';
        VAL = '';
        FOR
          SELECT DISTINCT C.CAPTION
          FROM PLAN_SUBJECTS PS
          LEFT JOIN OBJECT_CAPTION_GET(PS.SUBJECT_ID) C ON 1 = 1
          WHERE PS.PLAN_ID = :V$OBJ_ID AND PS.DATE_DEL IS NULL AND PS.IS_ADV = 1
          INTO :S
        DO
        BEGIN
          IF(VAL <> '') THEN VAL = VAL || ', ';
          VAL = VAL || S;
        END
        SUSPEND;

        TAG_NAME = 'rows:r:p100';
        SELECT COUNT(*)
        FROM LINKS L54
        JOIN LINKS L256 ON L256.PARENT_ID = L54.OBJ_ID AND L256.OBJ_TYPE_ID = 256 AND L256.DATE_DEL IS NULL
        JOIN LINKS L10 ON L10.PARENT_ID = L256.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        WHERE L54.PARENT_ID = :V$OBJ_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
        INTO :V$VAL;
        VAL = V$VAL;
        SUSPEND;
      END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PF_EDU_RGN (
    I$OBJ_ID BIGINT,
    I$BLOCK_NAME VARCHAR(40),
    I$BLOCK_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(1000))
AS
declare variable V bigint;
declare variable V$VAL bigint;
declare variable V$VAL2 bigint;
declare variable S varchar(1000);
declare variable V$TYPE_ID1 bigint;
declare variable V$TYPE_ID2 bigint;
declare variable V$MID_TYPE bigint;
declare variable V$OBJ_ID bigint;
declare variable V$PARAM_ID bigint;
declare variable V$TYPE bigint;
declare variable V$T bigint;
declare variable V$MASTER_ID bigint;
begin

  IF(I$BLOCK_NAME IS NULL) THEN
  BEGIN
    -- Оглавление
    TAG_NAME = 'dashboard::json&colon;array';
    VAL = 1;
    SUSPEND;

    SELECT COUNT(DISTINCT L57.OBJ_ID)
    FROM LINKS L111
    JOIN LINKS L2 ON L2.PARENT_ID = L111.OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    JOIN LINKS L69 ON L69.PARENT_ID = L2.OBJ_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL
    JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
    JOIN LINKS L400 ON L400.PARENT_ID = L57.OBJ_ID AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL
    JOIN VALL V3013 ON V3013.OBJ_ID = L400.OBJ_ID AND V3013.PARAM_ID = 3013 AND V3013.IS_DEL = 0 AND V3013.LISTVAL_ID = 11715
    JOIN VALL V3022 ON V3022.OBJ_ID = L400.OBJ_ID AND V3022.PARAM_ID = 3022 AND V3022.IS_DEL = 0
    JOIN VALL V3016 ON V3016.OBJ_ID = L400.OBJ_ID AND V3016.PARAM_ID = 3016 AND V3016.IS_DEL = 0
    WHERE L111.PARENT_ID = :I$OBJ_ID AND L111.OBJ_TYPE_ID = 111 AND L111.DATE_DEL IS NULL
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'edu';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '400';
    SUSPEND;
    TAG_NAME = 'dashboard:r:subtype_id';
    VAL = '';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'graduation cap';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#410093';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Количество образовательных программ';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

    SELECT COUNT(DISTINCT V3112.LISTVAL_ID)
    FROM LINKS L111
    JOIN LINKS L2 ON L2.PARENT_ID = L111.OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    JOIN LINKS L69 ON L69.PARENT_ID = L2.OBJ_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL
    JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
    JOIN LINKS L400 ON L400.PARENT_ID = L57.OBJ_ID AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL
    JOIN VALL V3013 ON V3013.OBJ_ID = L400.OBJ_ID AND V3013.PARAM_ID = 3013 AND V3013.IS_DEL = 0 AND V3013.LISTVAL_ID = 11715
    JOIN VALL V3022 ON V3022.OBJ_ID = L400.OBJ_ID AND V3022.PARAM_ID = 3022 AND V3022.IS_DEL = 0
    JOIN VALL V3016 ON V3016.OBJ_ID = L400.OBJ_ID AND V3016.PARAM_ID = 3016 AND V3016.IS_DEL = 0
    JOIN VALL V3112 ON V3112.OBJ_ID = L400.OBJ_ID AND V3112.PARAM_ID = 3112 AND V3112.IS_DEL = 0
    WHERE L111.PARENT_ID = :I$OBJ_ID AND L111.OBJ_TYPE_ID = 111 AND L111.DATE_DEL IS NULL
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'byprofile';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '400';
    SUSPEND;
    TAG_NAME = 'dashboard:r:subtype_id';
    VAL = '';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'tag';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#410093';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Количество профилей обучения';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

    SELECT COUNT(DISTINCT L400.OBJ_ID)
    FROM LINKS L111
    JOIN LINKS L2 ON L2.PARENT_ID = L111.OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    JOIN LINKS L69 ON L69.PARENT_ID = L2.OBJ_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL
    JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
    JOIN LINKS L400 ON L400.PARENT_ID = L57.OBJ_ID AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL
    JOIN VALL V3013 ON V3013.OBJ_ID = L400.OBJ_ID AND V3013.PARAM_ID = 3013 AND V3013.IS_DEL = 0 AND V3013.LISTVAL_ID = 11715
    JOIN VALL V3022 ON V3022.OBJ_ID = L400.OBJ_ID AND V3022.PARAM_ID = 3022 AND V3022.IS_DEL = 0
    JOIN VALL V3016 ON V3016.OBJ_ID = L400.OBJ_ID AND V3016.PARAM_ID = 3016 AND V3016.IS_DEL = 0
    JOIN VALL V2379 ON V2379.OBJ_ID = L400.OBJ_ID AND V2379.PARAM_ID = 2379 AND V2379.IS_DEL = 0 AND V2379.LISTVAL_ID <> 11187
    WHERE L111.PARENT_ID = :I$OBJ_ID AND L111.OBJ_TYPE_ID = 111 AND L111.DATE_DEL IS NULL
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'byadapt';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '400';
    SUSPEND;
    TAG_NAME = 'dashboard:r:subtype_id';
    VAL = '';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'wheelchair';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#410093';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Количество адаптированных УП';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

    SELECT COUNT(DISTINCT L400.OBJ_ID)
    FROM LINKS L111
    JOIN LINKS L2 ON L2.PARENT_ID = L111.OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    JOIN LINKS L69 ON L69.PARENT_ID = L2.OBJ_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL
    JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
    JOIN LINKS L400 ON L400.PARENT_ID = L57.OBJ_ID AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL
    JOIN VALL V3013 ON V3013.OBJ_ID = L400.OBJ_ID AND V3013.PARAM_ID = 3013 AND V3013.IS_DEL = 0 AND V3013.LISTVAL_ID = 11715
    JOIN VALL V3022 ON V3022.OBJ_ID = L400.OBJ_ID AND V3022.PARAM_ID = 3022 AND V3022.IS_DEL = 0
    JOIN VALL V3016 ON V3016.OBJ_ID = L400.OBJ_ID AND V3016.PARAM_ID = 3016 AND V3016.IS_DEL = 0
    LEFT JOIN VALL V1891 ON V1891.OBJ_ID = L57.OBJ_ID AND V1891.PARAM_ID = 1891 AND V1891.IS_DEL = 0
    LEFT JOIN VALL V2833 ON V2833.OBJ_ID = L57.OBJ_ID AND V2833.PARAM_ID = 2833 AND V2833.IS_DEL = 0
    WHERE L111.PARENT_ID = :I$OBJ_ID AND L111.OBJ_TYPE_ID = 111 AND L111.DATE_DEL IS NULL
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'byextern';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '400';
    SUSPEND;
    TAG_NAME = 'dashboard:r:subtype_id';
    VAL = '';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'rss';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#410093';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Количество сетевых или дистанционных УП';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

    SELECT COUNT(DISTINCT L400.OBJ_ID)
    FROM LINKS L111
    JOIN LINKS L2 ON L2.PARENT_ID = L111.OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    JOIN LINKS L69 ON L69.PARENT_ID = L2.OBJ_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL
    JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
    JOIN LINKS L400 ON L400.PARENT_ID = L57.OBJ_ID AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL
    JOIN VALL V3013 ON V3013.OBJ_ID = L400.OBJ_ID AND V3013.PARAM_ID = 3013 AND V3013.IS_DEL = 0 AND V3013.LISTVAL_ID = 11715
    JOIN VALL V3022 ON V3022.OBJ_ID = L400.OBJ_ID AND V3022.PARAM_ID = 3022 AND V3022.IS_DEL = 0
    JOIN VALL V3016 ON V3016.OBJ_ID = L400.OBJ_ID AND V3016.PARAM_ID = 3016 AND V3016.IS_DEL = 0 AND V3016.LISTVAL_ID <> 5465
    WHERE L111.PARENT_ID = :I$OBJ_ID AND L111.OBJ_TYPE_ID = 111 AND L111.DATE_DEL IS NULL
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'byind';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '400';
    SUSPEND;
    TAG_NAME = 'dashboard:r:subtype_id';
    VAL = '80';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'sun';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#410093';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Количество индивидуальных УП';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

  END
  ELSE
  BEGIN

    TAG_NAME = 'title';
    VAL = 'Образовательные программы и учебные планы';
    SUSPEND;

    TAG_NAME = 'has_caption';
    VAL = 1;
    SUSPEND;

    TAG_NAME = 'columns::json&colon;array';
    VAL = 1;
    SUSPEND;

    TAG_NAME = 'columns:r'; VAL = NULL; SUSPEND;
    TAG_NAME = 'columns:r:type_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:param_id'; VAL = '0'; SUSPEND;
    TAG_NAME = 'columns:r:type'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:name'; VAL = 'Количество ОУ'; SUSPEND;

    TAG_NAME = 'columns:r'; VAL = NULL; SUSPEND;
    TAG_NAME = 'columns:r:type_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:param_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:type'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:name'; VAL = 'Количество образовательных программ'; SUSPEND;

    TAG_NAME = 'columns:r'; VAL = NULL; SUSPEND;
    TAG_NAME = 'columns:r:type_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:param_id'; VAL = '2'; SUSPEND;
    TAG_NAME = 'columns:r:type'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:name'; VAL = 'Количество профилей обучения'; SUSPEND;

    TAG_NAME = 'columns:r'; VAL = NULL; SUSPEND;
    TAG_NAME = 'columns:r:type_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:param_id'; VAL = '3'; SUSPEND;
    TAG_NAME = 'columns:r:type'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:name'; VAL = 'Количество адаптированных УП'; SUSPEND;

    TAG_NAME = 'columns:r'; VAL = NULL; SUSPEND;
    TAG_NAME = 'columns:r:type_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:param_id'; VAL = '4'; SUSPEND;
    TAG_NAME = 'columns:r:type'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:name'; VAL = 'Количество сетевых или дистанционных УП'; SUSPEND;

    TAG_NAME = 'columns:r'; VAL = NULL; SUSPEND;
    TAG_NAME = 'columns:r:type_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:param_id'; VAL = '5'; SUSPEND;
    TAG_NAME = 'columns:r:type'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:name'; VAL = 'Количество индивидуальных УП'; SUSPEND;

    -- Развертка по районам
    TAG_NAME = 'rows::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT L111.OBJ_ID, L111.OBJ_TYPE_ID, C.CAPTION
      FROM LINKS L111
      LEFT JOIN OBJECT_CAPTION_GET(L111.OBJ_ID) C ON 1 = 1
      WHERE L111.PARENT_ID = :I$OBJ_ID AND L111.OBJ_TYPE_ID = 111 AND L111.DATE_DEL IS NULL
      ORDER BY 3
      INTO :V$OBJ_ID, :V$TYPE, :S
    DO
    BEGIN
      TAG_NAME = 'rows:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'rows:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'rows:r:type_id';
      VAL = '1';
      SUSPEND;
      TAG_NAME = 'rows:r:caption';
      VAL = S;
      SUSPEND;

      SELECT COUNT(DISTINCT L57.OBJ_ID), COUNT(DISTINCT L2.OBJ_ID)
      FROM LINKS L2
      JOIN LINKS L69 ON L69.PARENT_ID = L2.OBJ_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL
      JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
      JOIN LINKS L400 ON L400.PARENT_ID = L57.OBJ_ID AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL
      JOIN VALL V3013 ON V3013.OBJ_ID = L400.OBJ_ID AND V3013.PARAM_ID = 3013 AND V3013.IS_DEL = 0 AND V3013.LISTVAL_ID = 11715
      JOIN VALL V3022 ON V3022.OBJ_ID = L400.OBJ_ID AND V3022.PARAM_ID = 3022 AND V3022.IS_DEL = 0
      JOIN VALL V3016 ON V3016.OBJ_ID = L400.OBJ_ID AND V3016.PARAM_ID = 3016 AND V3016.IS_DEL = 0
      WHERE L2.PARENT_ID = :V$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      INTO :V$VAL, :V;

      TAG_NAME = 'rows:r:p0';
      VAL = V;
      SUSPEND;

      TAG_NAME = 'rows:r:p1';
      VAL = V$VAL;
      SUSPEND;

      SELECT COUNT(DISTINCT V3112.LISTVAL_ID)
      FROM LINKS L2
      JOIN LINKS L69 ON L69.PARENT_ID = L2.OBJ_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL
      JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
      JOIN LINKS L400 ON L400.PARENT_ID = L57.OBJ_ID AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL
      JOIN VALL V3013 ON V3013.OBJ_ID = L400.OBJ_ID AND V3013.PARAM_ID = 3013 AND V3013.IS_DEL = 0 AND V3013.LISTVAL_ID = 11715
      JOIN VALL V3022 ON V3022.OBJ_ID = L400.OBJ_ID AND V3022.PARAM_ID = 3022 AND V3022.IS_DEL = 0
      JOIN VALL V3016 ON V3016.OBJ_ID = L400.OBJ_ID AND V3016.PARAM_ID = 3016 AND V3016.IS_DEL = 0
      JOIN VALL V3112 ON V3112.OBJ_ID = L400.OBJ_ID AND V3112.PARAM_ID = 3112 AND V3112.IS_DEL = 0
      WHERE L2.PARENT_ID = :V$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      INTO :V$VAL;

      TAG_NAME = 'rows:r:p2';
      VAL = V$VAL;
      SUSPEND;

      SELECT COUNT(DISTINCT L400.OBJ_ID)
      FROM LINKS L2
      JOIN LINKS L69 ON L69.PARENT_ID = L2.OBJ_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL
      JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
      JOIN LINKS L400 ON L400.PARENT_ID = L57.OBJ_ID AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL
      JOIN VALL V3013 ON V3013.OBJ_ID = L400.OBJ_ID AND V3013.PARAM_ID = 3013 AND V3013.IS_DEL = 0 AND V3013.LISTVAL_ID = 11715
      JOIN VALL V3022 ON V3022.OBJ_ID = L400.OBJ_ID AND V3022.PARAM_ID = 3022 AND V3022.IS_DEL = 0
      JOIN VALL V3016 ON V3016.OBJ_ID = L400.OBJ_ID AND V3016.PARAM_ID = 3016 AND V3016.IS_DEL = 0
      JOIN VALL V2379 ON V2379.OBJ_ID = L400.OBJ_ID AND V2379.PARAM_ID = 2379 AND V2379.IS_DEL = 0 AND V2379.LISTVAL_ID <> 287
      WHERE L2.PARENT_ID = :V$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      INTO :V$VAL;

      TAG_NAME = 'rows:r:p3';
      VAL = V$VAL;
      SUSPEND;

      SELECT COUNT(DISTINCT L400.OBJ_ID)
      FROM LINKS L2
      JOIN LINKS L69 ON L69.PARENT_ID = L2.OBJ_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL
      JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
      JOIN LINKS L400 ON L400.PARENT_ID = L57.OBJ_ID AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL
      JOIN VALL V3013 ON V3013.OBJ_ID = L400.OBJ_ID AND V3013.PARAM_ID = 3013 AND V3013.IS_DEL = 0 AND V3013.LISTVAL_ID = 11715
      JOIN VALL V3022 ON V3022.OBJ_ID = L400.OBJ_ID AND V3022.PARAM_ID = 3022 AND V3022.IS_DEL = 0
      JOIN VALL V3016 ON V3016.OBJ_ID = L400.OBJ_ID AND V3016.PARAM_ID = 3016 AND V3016.IS_DEL = 0
      LEFT JOIN VALL V1891 ON V1891.OBJ_ID = L57.OBJ_ID AND V1891.PARAM_ID = 1891 AND V1891.IS_DEL = 0
      LEFT JOIN VALL V2833 ON V2833.OBJ_ID = L57.OBJ_ID AND V2833.PARAM_ID = 2833 AND V2833.IS_DEL = 0
      WHERE L2.PARENT_ID = :V$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      INTO :V$VAL;

      TAG_NAME = 'rows:r:p4';
      VAL = V$VAL;
      SUSPEND;

      SELECT COUNT(DISTINCT L400.OBJ_ID)
      FROM LINKS L2
      JOIN LINKS L69 ON L69.PARENT_ID = L2.OBJ_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL
      JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
      JOIN LINKS L400 ON L400.PARENT_ID = L57.OBJ_ID AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL
      JOIN VALL V3013 ON V3013.OBJ_ID = L400.OBJ_ID AND V3013.PARAM_ID = 3013 AND V3013.IS_DEL = 0 AND V3013.LISTVAL_ID = 11715
      JOIN VALL V3022 ON V3022.OBJ_ID = L400.OBJ_ID AND V3022.PARAM_ID = 3022 AND V3022.IS_DEL = 0
      JOIN VALL V3016 ON V3016.OBJ_ID = L400.OBJ_ID AND V3016.PARAM_ID = 3016 AND V3016.IS_DEL = 0 AND V3016.LISTVAL_ID <> 5465
      WHERE L2.PARENT_ID = :V$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      INTO :V$VAL;

      TAG_NAME = 'rows:r:p5';
      VAL = V$VAL;
      SUSPEND;

    END

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PF_EQUIPMENT (
    I$OBJ_ID BIGINT,
    I$BLOCK_NAME VARCHAR(40),
    I$BLOCK_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(1000))
AS
declare variable V$TYPE_ID bigint;
begin

  SELECT TYPE_ID
  FROM OBJECTS
  WHERE OBJ_ID = :I$OBJ_ID
  INTO :V$TYPE_ID;

  IF(V$TYPE_ID = 2) THEN
  BEGIN
    FOR
      SELECT D.TAG_NAME, D.VAL
      FROM PF_EQUIPMENT_OU(:I$OBJ_ID, :I$BLOCK_NAME, :I$BLOCK_ID, :I$USER_ID) D
      INTO :TAG_NAME, :VAL
    DO
    BEGIN
      SUSPEND;
    END
  END
  ELSE IF(V$TYPE_ID = 111) THEN
  BEGIN
    FOR
      SELECT D.TAG_NAME, D.VAL
      FROM PF_EQUIPMENT_DIST(:I$OBJ_ID, :I$BLOCK_NAME, :I$BLOCK_ID, :I$USER_ID) D
      INTO :TAG_NAME, :VAL
    DO
    BEGIN
      SUSPEND;
    END
  END
  ELSE IF(V$TYPE_ID = 112) THEN
  BEGIN
    FOR
      SELECT D.TAG_NAME, D.VAL
      FROM PF_EQUIPMENT_RGN(:I$OBJ_ID, :I$BLOCK_NAME, :I$BLOCK_ID, :I$USER_ID) D
      INTO :TAG_NAME, :VAL
    DO
    BEGIN
      SUSPEND;
    END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PF_EQUIPMENT_DIST (
    I$OBJ_ID BIGINT,
    I$BLOCK_NAME VARCHAR(40),
    I$BLOCK_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(1000))
AS
declare variable V$VAL bigint;
declare variable V$VAL2 bigint;
declare variable F float;
declare variable S varchar(1000);
declare variable V$TYPE_ID1 bigint;
declare variable V$TYPE_ID2 bigint;
declare variable V$MID_TYPE bigint;
declare variable V$OBJ_ID bigint;
declare variable V$PARAM_ID bigint;
declare variable V$TYPE bigint;
declare variable V$T bigint;
declare variable V$MASTER_ID bigint;
begin

  IF(I$BLOCK_NAME IS NULL) THEN
  BEGIN
    -- Оглавление
    TAG_NAME = 'dashboard::json&colon;array';
    VAL = 1;
    SUSPEND;

    SELECT SUM(V2685.VAL), SUM(V2686.VAL)
    FROM LINKS L2
    JOIN LINKS L162 ON L162.PARENT_ID = L2.OBJ_ID AND L162.OBJ_TYPE_ID = 162 AND L162.DATE_DEL IS NULL
    JOIN LINKS L345 ON L345.PARENT_ID = L162.OBJ_ID AND L345.OBJ_TYPE_ID = 345 AND L345.DATE_DEL IS NULL
    JOIN VALI V2685 ON V2685.OBJ_ID = L345.OBJ_ID AND V2685.PARAM_ID = 2685 AND V2685.IS_DEL = 0
    JOIN VALI V2686 ON V2686.OBJ_ID = L345.OBJ_ID AND V2686.PARAM_ID = 2686 AND V2686.IS_DEL = 0
    WHERE L2.PARENT_ID = :I$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :V$VAL, :V$VAL2;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'books';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '345';
    SUSPEND;
    TAG_NAME = 'dashboard:r:subtype_id';
    VAL = '';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'book';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#410093';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Доля полностью обеспеченных учебниками';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    IF(V$VAL = 0) THEN F = NULL; ELSE F = 100 * CAST(V$VAL2 AS FLOAT) / CAST(V$VAL AS FLOAT);
    VAL = CAST(F AS NUMERIC(18, 1));
    SUSPEND;

    SELECT COUNT(*)
    FROM LINKS L2
    JOIN LINKS L23 ON L23.PARENT_ID = L2.OBJ_ID AND L23.OBJ_TYPE_ID = 23 AND L23.DATE_DEL IS NULL
    JOIN LINKS L128 ON L128.PARENT_ID = L23.OBJ_ID AND L128.OBJ_TYPE_ID = 128 AND L128.DATE_DEL IS NULL
    JOIN VALL V876 ON V876.OBJ_ID = L128.OBJ_ID AND V876.PARAM_ID = 876 AND V876.IS_DEL = 0 AND V876.LISTVAL_ID IN (2069, 2070, 2071, 2072, 2073, 2074)
    WHERE L2.PARENT_ID = :I$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'labs';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '128';
    SUSPEND;
    TAG_NAME = 'dashboard:r:subtype_id';
    VAL = '';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'cog';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#410093';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Единиц лабораторных комплексов';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

    SELECT COUNT(*)
    FROM LINKS L2
    JOIN LINKS L23 ON L23.PARENT_ID = L2.OBJ_ID AND L23.OBJ_TYPE_ID = 23 AND L23.DATE_DEL IS NULL
    JOIN LINKS L128 ON L128.PARENT_ID = L23.OBJ_ID AND L128.OBJ_TYPE_ID = 128 AND L128.DATE_DEL IS NULL
    JOIN VALL V876 ON V876.OBJ_ID = L128.OBJ_ID AND V876.PARAM_ID = 876 AND V876.IS_DEL = 0 AND V876.LISTVAL_ID IN (2067, 2068)
    WHERE L2.PARENT_ID = :I$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'computers';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '128';
    SUSPEND;
    TAG_NAME = 'dashboard:r:subtype_id';
    VAL = '';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'desktop';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#410093';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Количество компьютерных классов';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

    SELECT COUNT(*)
    FROM LINKS L2
    JOIN LINKS L116 ON L116.PARENT_ID = L2.OBJ_ID AND L116.OBJ_TYPE_ID = 116 AND L116.DATE_DEL IS NULL
    JOIN VALL V695 ON V695.OBJ_ID = L116.OBJ_ID AND V695.PARAM_ID = 695 AND V695.IS_DEL = 0 AND V695.LISTVAL_ID IN (2180, 2181)
    WHERE L2.PARENT_ID = :I$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'networks';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '116';
    SUSPEND;
    TAG_NAME = 'dashboard:r:subtype_id';
    VAL = '2180';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'cloud';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#410093';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Количество локальных сетей';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

    SELECT COUNT(*)
    FROM LINKS L2
    JOIN LINKS L116 ON L116.PARENT_ID = L2.OBJ_ID AND L116.OBJ_TYPE_ID = 116 AND L116.DATE_DEL IS NULL
    JOIN VALL V695 ON V695.OBJ_ID = L116.OBJ_ID AND V695.PARAM_ID = 695 AND V695.IS_DEL = 0 AND V695.LISTVAL_ID IN (2182)
    WHERE L2.PARENT_ID = :I$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'networkjs';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '116';
    SUSPEND;
    TAG_NAME = 'dashboard:r:subtype_id';
    VAL = '2182';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'rss';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#410093';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Количество зон WiFi';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

    SELECT COUNT(*)
    FROM LINKS L2
    JOIN LINKS L116 ON L116.PARENT_ID = L2.OBJ_ID AND L116.OBJ_TYPE_ID = 116 AND L116.DATE_DEL IS NULL
    JOIN VALL V697 ON V697.OBJ_ID = L116.OBJ_ID AND V697.PARAM_ID = 697 AND V697.IS_DEL = 0 AND V697.LISTVAL_ID = 2
    WHERE L2.PARENT_ID = :I$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'networks';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '116';
    SUSPEND;
    TAG_NAME = 'dashboard:r:subtype_id';
    VAL = '697';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'cloud';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#410093';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Количество сетей с доступом к Интернет';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;
  END
  ELSE
  BEGIN

    TAG_NAME = 'title';
    VAL = 'Сотрудники';
    SUSPEND;

    TAG_NAME = 'has_caption';
    VAL = 1;
    SUSPEND;

    TAG_NAME = 'columns::json&colon;array';
    VAL = 1;
    SUSPEND;

    TAG_NAME = 'columns:r'; VAL = NULL; SUSPEND;
    TAG_NAME = 'columns:r:type_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:param_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:type'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:name'; VAL = 'Доля полностью обеспеченных учебниками'; SUSPEND;

    TAG_NAME = 'columns:r'; VAL = NULL; SUSPEND;
    TAG_NAME = 'columns:r:type_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:param_id'; VAL = '2'; SUSPEND;
    TAG_NAME = 'columns:r:type'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:name'; VAL = 'Единиц лабораторных комплексов'; SUSPEND;

    TAG_NAME = 'columns:r'; VAL = NULL; SUSPEND;
    TAG_NAME = 'columns:r:type_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:param_id'; VAL = '3'; SUSPEND;
    TAG_NAME = 'columns:r:type'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:name'; VAL = 'Количество компьютерных классов'; SUSPEND;

    -- Развертка по районам
    TAG_NAME = 'rows::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT L2.OBJ_ID, L2.OBJ_TYPE_ID, C.CAPTION
      FROM LINKS L2
      LEFT JOIN OBJECT_CAPTION_GET(L2.OBJ_ID) C ON 1 = 1
      WHERE L2.PARENT_ID = :I$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      ORDER BY 3
      INTO :V$OBJ_ID, :V$TYPE, :S
    DO
    BEGIN
      TAG_NAME = 'rows:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'rows:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'rows:r:type_id';
      VAL = '1';
      SUSPEND;
      TAG_NAME = 'rows:r:caption';
      VAL = S;
      SUSPEND;

      SELECT SUM(V2685.VAL), SUM(V2686.VAL)
      FROM LINKS L162
      JOIN LINKS L345 ON L345.PARENT_ID = L162.OBJ_ID AND L345.OBJ_TYPE_ID = 345 AND L345.DATE_DEL IS NULL
      JOIN VALI V2685 ON V2685.OBJ_ID = L345.OBJ_ID AND V2685.PARAM_ID = 2685 AND V2685.IS_DEL = 0
      JOIN VALI V2686 ON V2686.OBJ_ID = L345.OBJ_ID AND V2686.PARAM_ID = 2686 AND V2686.IS_DEL = 0
      WHERE L162.PARENT_ID = :V$OBJ_ID AND L162.OBJ_TYPE_ID = 162 AND L162.DATE_DEL IS NULL
      INTO :V$VAL, :V$VAL2;

      TAG_NAME = 'rows:r:p1';
      IF(V$VAL = 0) THEN F = NULL; ELSE F = 100 * CAST(V$VAL2 AS FLOAT) / CAST(V$VAL AS FLOAT);
      VAL = CAST(F AS NUMERIC(18, 1));
      SUSPEND;

      SELECT COUNT(*)
      FROM LINKS L23
      JOIN LINKS L128 ON L128.PARENT_ID = L23.OBJ_ID AND L128.OBJ_TYPE_ID = 128 AND L128.DATE_DEL IS NULL
      JOIN VALL V876 ON V876.OBJ_ID = L128.OBJ_ID AND V876.PARAM_ID = 876 AND V876.IS_DEL = 0 AND V876.LISTVAL_ID IN (2069, 2070, 2071, 2072, 2073, 2074)
      WHERE L23.PARENT_ID = :V$OBJ_ID AND L23.OBJ_TYPE_ID = 23 AND L23.DATE_DEL IS NULL
      INTO :V$VAL;

      TAG_NAME = 'rows:r:p2';
      VAL = V$VAL;
      SUSPEND;

      SELECT COUNT(*)
      FROM LINKS L23
      JOIN LINKS L128 ON L128.PARENT_ID = L23.OBJ_ID AND L128.OBJ_TYPE_ID = 128 AND L128.DATE_DEL IS NULL
      JOIN VALL V876 ON V876.OBJ_ID = L128.OBJ_ID AND V876.PARAM_ID = 876 AND V876.IS_DEL = 0 AND V876.LISTVAL_ID IN (2067, 2068)
      WHERE L23.PARENT_ID = :V$OBJ_ID AND L23.OBJ_TYPE_ID = 23 AND L23.DATE_DEL IS NULL
      INTO :V$VAL;

      TAG_NAME = 'rows:r:p3';
      VAL = V$VAL;
      SUSPEND;

    END

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PF_EQUIPMENT_OU (
    I$OBJ_ID BIGINT,
    I$BLOCK_NAME VARCHAR(40),
    I$BLOCK_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(1000))
AS
declare variable V$VAL bigint;
declare variable V$VAL2 bigint;
declare variable F float;
declare variable S varchar(1000);
declare variable S2 varchar(1000);
declare variable V$P1 bigint;
declare variable V$P2 bigint;
declare variable V$P3 bigint;
declare variable V$P4 bigint;
declare variable V$P5 bigint;
declare variable V$TYPE_ID1 bigint;
declare variable V$TYPE_ID2 bigint;
declare variable V$MID_TYPE bigint;
declare variable V$OBJ_ID bigint;
declare variable V$PARAM_ID bigint;
declare variable V$TYPE bigint;
declare variable V$T bigint;
declare variable V$MASTER_ID bigint;
declare variable V$YEAR_START date;
begin

  IF(EXTRACT(MONTH FROM CURRENT_DATE) < 8) THEN V$YEAR_START = '01.09.' || (EXTRACT(YEAR FROM CURRENT_DATE) - 1);
  ELSE V$YEAR_START = '01.09.' || EXTRACT(YEAR FROM CURRENT_DATE);

  IF(I$BLOCK_NAME IS NULL) THEN
  BEGIN
    -- Оглавление
    TAG_NAME = 'dashboard::json&colon;array';
    VAL = 1;
    SUSPEND;

    -- Сведения по ЛВС, wifi
    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'general';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = '';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#FAFAFA';
    SUSPEND;

    TAG_NAME = 'dashboard:r:title::json&colon;array';
    VAL = 1;
    SUSPEND;
    V$TYPE = 0;
    FOR
      SELECT V697.LISTVAL_ID, C700.VAL, V701.VAL, V695.LISTVAL_ID, COALESCE(V699.VAL, V694.VAL)
      FROM LINKS L116
      LEFT JOIN VALL V697 ON V697.OBJ_ID = L116.OBJ_ID AND V697.PARAM_ID = 697 AND V697.IS_DEL = 0
      LEFT JOIN VALI V701 ON V701.OBJ_ID = L116.OBJ_ID AND V701.PARAM_ID = 701 AND V701.IS_DEL = 0
      LEFT JOIN VALL V700 ON V700.OBJ_ID = L116.OBJ_ID AND V700.PARAM_ID = 700 AND V700.IS_DEL = 0
      LEFT JOIN LISTVAL_TEXT(V700.LISTVAL_ID) C700 ON 1 = 1
      LEFT JOIN VALL V695 ON V695.OBJ_ID = L116.OBJ_ID AND V695.PARAM_ID = 695 AND V695.IS_DEL = 0
      LEFT JOIN VALS V699 ON V699.OBJ_ID = L116.OBJ_ID AND V699.PARAM_ID = 699 AND V699.IS_DEL = 0
      LEFT JOIN VALS V694 ON V694.OBJ_ID = L116.OBJ_ID AND V694.PARAM_ID = 694 AND V694.IS_DEL = 0
      WHERE L116.PARENT_ID = :I$OBJ_ID AND L116.OBJ_TYPE_ID = 116 AND L116.DATE_DEL IS NULL
      INTO :V$T, :S, :V$VAL, :V$VAL2, :S2
    DO
    BEGIN
      TAG_NAME = 'dashboard:r:title:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'dashboard:r:title:r:title';
      IF(V$VAL2 = 2182) THEN VAL = 'Зона WiFi';
      ELSE IF(V$VAL2 = 2180) THEN VAL = 'Проводная сеть';
      ELSE IF(V$VAL2 = 2181) THEN VAL = 'Оптоволоконная сеть';
      ELSE VAL = 'Локальная сеть';
      SUSPEND;
      TAG_NAME = 'dashboard:r:title:r:value';
      IF(V$T IS NULL) THEN VAL = S2;
      ELSE IF(V$T = 3) THEN VAL = 'Без подключения к интернет';
      ELSE VAL = 'Подключение к интернет ' || COALESCE(S, '?') || ', ' || COALESCE(S2, '') || ', скорость ' || COALESCE(V$VAL || ' МБит/с', '-');
      SUSPEND;
      V$TYPE = V$TYPE + 1;
    END
    IF(V$TYPE = 0) THEN
    BEGIN
      TAG_NAME = 'dashboard:r:title:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'dashboard:r:title:r:title';
      VAL = 'Локальная сеть и интернет';
      SUSPEND;
      TAG_NAME = 'dashboard:r:title:r:value';
      VAL = 'Нет данных';
      SUSPEND;
    END

    -- Остальные плашки

    SELECT SUM(V2685.VAL), SUM(V2686.VAL)
    FROM LINKS L162
    JOIN LINKS L345 ON L345.PARENT_ID = L162.OBJ_ID AND L345.OBJ_TYPE_ID = 345 AND L345.DATE_DEL IS NULL
    JOIN VALI V2685 ON V2685.OBJ_ID = L345.OBJ_ID AND V2685.PARAM_ID = 2685 AND V2685.IS_DEL = 0
    JOIN VALI V2686 ON V2686.OBJ_ID = L345.OBJ_ID AND V2686.PARAM_ID = 2686 AND V2686.IS_DEL = 0
    WHERE L162.PARENT_ID = :I$OBJ_ID AND L162.OBJ_TYPE_ID = 162 AND L162.DATE_DEL IS NULL
    INTO :V$VAL, :V$VAL2;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'books';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '345';
    SUSPEND;
    TAG_NAME = 'dashboard:r:subtype_id';
    VAL = '';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'book';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#410093';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Доля полностью обеспеченных учебниками';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    IF(V$VAL = 0) THEN F = NULL; ELSE F = 100 * CAST(V$VAL2 AS FLOAT) / CAST(V$VAL AS FLOAT);
    VAL = CAST(F AS NUMERIC(18, 1));
    SUSPEND;

    SELECT COUNT(*)
    FROM LINKS L23
    JOIN LINKS L128 ON L128.PARENT_ID = L23.OBJ_ID AND L128.OBJ_TYPE_ID = 128 AND L128.DATE_DEL IS NULL
    JOIN VALL V876 ON V876.OBJ_ID = L128.OBJ_ID AND V876.PARAM_ID = 876 AND V876.IS_DEL = 0 AND V876.LISTVAL_ID IN (2069, 2070, 2071, 2072, 2073, 2074)
    WHERE L23.PARENT_ID = :I$OBJ_ID AND L23.OBJ_TYPE_ID = 23 AND L23.DATE_DEL IS NULL
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'labs';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '128';
    SUSPEND;
    TAG_NAME = 'dashboard:r:subtype_id';
    VAL = '';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'cog';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#410093';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Единиц лабораторных комплексов';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

    SELECT COUNT(*)
    FROM LINKS L23
    JOIN LINKS L128 ON L128.PARENT_ID = L23.OBJ_ID AND L128.OBJ_TYPE_ID = 128 AND L128.DATE_DEL IS NULL
    JOIN VALL V876 ON V876.OBJ_ID = L128.OBJ_ID AND V876.PARAM_ID = 876 AND V876.IS_DEL = 0 AND V876.LISTVAL_ID IN (2067, 2068)
    WHERE L23.PARENT_ID = :I$OBJ_ID AND L23.OBJ_TYPE_ID = 23 AND L23.DATE_DEL IS NULL
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'computers';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '128';
    SUSPEND;
    TAG_NAME = 'dashboard:r:subtype_id';
    VAL = '';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'desktop';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#410093';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Количество компьютерных классов';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

  END
  ELSE
  BEGIN

    TAG_NAME = 'has_caption';
    VAL = 0;
    SUSPEND;

    TAG_NAME = 'title';
    VAL = 'Образовательные программы и учебные планы';
    IF(I$BLOCK_NAME = 'books') THEN VAL = 'Обеспеченность учебниками';
    ELSE IF(I$BLOCK_NAME = 'labs') THEN VAL = 'Оснащение лабораторными комплексами';
    ELSE IF(I$BLOCK_NAME = 'computers') THEN VAL = 'Компьютерные классы';
    ELSE VAL = '???';
    SUSPEND;

    TAG_NAME = 'columns::json&colon;array';
    VAL = 1;
    SUSPEND;
    IF(I$BLOCK_NAME = 'books') THEN
    BEGIN
      V$TYPE_ID1 = 345;
      V$TYPE = 345;
      FOR
        SELECT P.TYPE_ID, P.PARAM_ID, P.PARAM_TYPE, R.VAL
        FROM PARAMS P
        JOIN RES R ON R.RES_ID = P.RES_ID AND R.LANG_CODE = 'RU'
        WHERE P.IS_DEL = 0 AND (P.TYPE_ID = :V$TYPE_ID1 OR P.TYPE_ID = :V$TYPE_ID2)
        ORDER BY 1, 2
        INTO :V$TYPE, :V$PARAM_ID, :V$T, :S
      DO
      BEGIN
        TAG_NAME = 'columns:r';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'columns:r:type_id';
        VAL = V$TYPE;
        SUSPEND;
        TAG_NAME = 'columns:r:param_id';
        VAL = V$PARAM_ID;
        SUSPEND;
        TAG_NAME = 'columns:r:type';
        VAL = V$T;
        SUSPEND;
        TAG_NAME = 'columns:r:name';
        VAL = S;
        SUSPEND;
      END
    END
    ELSE
    BEGIN
      V$TYPE_ID1 = 128;
      V$TYPE = 128;
      TAG_NAME = 'columns:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'columns:r:type_id';
      VAL = V$TYPE_ID1;
      SUSPEND;
      TAG_NAME = 'columns:r:param_id';
      VAL = 0;
      SUSPEND;
      TAG_NAME = 'columns:r:type';
      VAL = 8;
      SUSPEND;
      TAG_NAME = 'columns:r:name';
      VAL = 'Наименование';
      SUSPEND;
      TAG_NAME = 'columns:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'columns:r:type_id';
      VAL = V$TYPE_ID1;
      SUSPEND;
      TAG_NAME = 'columns:r:param_id';
      VAL = 1;
      SUSPEND;
      TAG_NAME = 'columns:r:type';
      VAL = 1;
      SUSPEND;
      TAG_NAME = 'columns:r:name';
      VAL = 'Год выпуска';
      SUSPEND;
      TAG_NAME = 'columns:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'columns:r:type_id';
      VAL = V$TYPE_ID1;
      SUSPEND;
      TAG_NAME = 'columns:r:param_id';
      VAL = 2;
      SUSPEND;
      TAG_NAME = 'columns:r:type';
      VAL = 1;
      SUSPEND;
      TAG_NAME = 'columns:r:name';
      VAL = 'Количество рабочих мест';
      SUSPEND;
    END

    TAG_NAME = 'rows::json&colon;array';
    VAL = 1;
    SUSPEND;

    IF(I$BLOCK_NAME = 'books') THEN
      -- По параллелям
      FOR
        SELECT L345.OBJ_ID
        FROM LINKS L162
        JOIN LINKS L345 ON L345.PARENT_ID = L162.OBJ_ID AND L345.OBJ_TYPE_ID = 345 AND L345.DATE_DEL IS NULL
        JOIN VALL V2684 ON V2684.OBJ_ID = L345.OBJ_ID AND V2684.PARAM_ID = 2684 AND V2684.IS_DEL = 0
        JOIN LISTVALS LV ON LV.LISTVAL_ID = V2684.LISTVAL_ID
        WHERE L162.PARENT_ID = :I$OBJ_ID AND L162.OBJ_TYPE_ID = 162 AND L162.DATE_DEL IS NULL
        ORDER BY LV.SORT_ORDER
        INTO :V$OBJ_ID
      DO
      BEGIN
        TAG_NAME = 'rows:r';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'rows:r:id';
        VAL = V$OBJ_ID;
        SUSPEND;
        TAG_NAME = 'rows:r:type_id';
        VAL = V$TYPE;
        SUSPEND;
        FOR
          SELECT P.PARAM_ID, IIF(V.IS_EXISTS = 1, V.V, NULL)
          FROM PARAMS P
          LEFT JOIN VAL_GET(:V$OBJ_ID, P.PARAM_ID) V ON 1 = 1
          WHERE P.TYPE_ID = :V$TYPE AND P.IS_DEL = 0
          ORDER BY P.GRID_ORDER
          INTO :V$PARAM_ID, :S
        DO
        BEGIN
          TAG_NAME = 'rows:r:p' || V$PARAM_ID;
          VAL = S;
          SUSPEND;
        END
      END
    ELSE
      FOR
        SELECT L128.OBJ_ID, L128.OBJ_TYPE_ID, C.CAPTION, V888.VAL, V878.VAL
        FROM LINKS L23
        JOIN LINKS L128 ON L128.PARENT_ID = L23.OBJ_ID AND L128.OBJ_TYPE_ID = 128 AND L128.DATE_DEL IS NULL
        JOIN VALL V876 ON V876.OBJ_ID = L128.OBJ_ID AND V876.PARAM_ID = 876 AND V876.IS_DEL = 0
          AND ((:I$BLOCK_NAME = 'labs' AND V876.LISTVAL_ID IN (2069, 2070, 2071, 2072, 2073, 2074)) OR (:I$BLOCK_NAME = 'computers' AND V876.LISTVAL_ID IN (2067, 2068)))
        LEFT JOIN VALI V888 ON V888.OBJ_ID = L128.OBJ_ID AND V888.PARAM_ID = 888 AND V888.IS_DEL = 0
        LEFT JOIN VALS V878 ON V878.OBJ_ID = L128.OBJ_ID AND V878.PARAM_ID = 878 AND V878.IS_DEL = 0
        LEFT JOIN OBJECT_CAPTION_GET(L128.OBJ_ID) C ON 1 = 1
        WHERE L23.PARENT_ID = :I$OBJ_ID AND L23.OBJ_TYPE_ID = 23 AND L23.DATE_DEL IS NULL
        ORDER BY 3
        INTO :V$OBJ_ID, :V$TYPE, :S, :V$VAL, :S2
      DO
      BEGIN
        TAG_NAME = 'rows:r';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'rows:r:id';
        VAL = V$OBJ_ID;
        SUSPEND;
        TAG_NAME = 'rows:r:type_id';
        VAL = V$TYPE;
        SUSPEND;
        TAG_NAME = 'rows:r:p0';
        VAL = S;
        SUSPEND;
        TAG_NAME = 'rows:r:p1';
        VAL = S2;
        SUSPEND;
        TAG_NAME = 'rows:r:p2';
        VAL = V$VAL;
        SUSPEND;
      END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PF_EQUIPMENT_RGN (
    I$OBJ_ID BIGINT,
    I$BLOCK_NAME VARCHAR(40),
    I$BLOCK_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(1000))
AS
declare variable V bigint;
declare variable V$VAL bigint;
declare variable V$VAL2 bigint;
declare variable F float;
declare variable S varchar(1000);
declare variable V$TYPE_ID1 bigint;
declare variable V$TYPE_ID2 bigint;
declare variable V$MID_TYPE bigint;
declare variable V$OBJ_ID bigint;
declare variable V$PARAM_ID bigint;
declare variable V$TYPE bigint;
declare variable V$T bigint;
declare variable V$MASTER_ID bigint;
begin

  IF(I$BLOCK_NAME IS NULL) THEN
  BEGIN
    -- Оглавление
    TAG_NAME = 'dashboard::json&colon;array';
    VAL = 1;
    SUSPEND;

    SELECT SUM(V2685.VAL), SUM(V2686.VAL)
    FROM LINKS L111
    JOIN LINKS L2 ON L2.PARENT_ID = L111.OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    JOIN LINKS L162 ON L162.PARENT_ID = L2.OBJ_ID AND L162.OBJ_TYPE_ID = 162 AND L162.DATE_DEL IS NULL
    JOIN LINKS L345 ON L345.PARENT_ID = L162.OBJ_ID AND L345.OBJ_TYPE_ID = 345 AND L345.DATE_DEL IS NULL
    JOIN VALI V2685 ON V2685.OBJ_ID = L345.OBJ_ID AND V2685.PARAM_ID = 2685 AND V2685.IS_DEL = 0
    JOIN VALI V2686 ON V2686.OBJ_ID = L345.OBJ_ID AND V2686.PARAM_ID = 2686 AND V2686.IS_DEL = 0
    WHERE L111.PARENT_ID = :I$OBJ_ID AND L111.OBJ_TYPE_ID = 111 AND L111.DATE_DEL IS NULL
    INTO :V$VAL, :V$VAL2;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'books';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '345';
    SUSPEND;
    TAG_NAME = 'dashboard:r:subtype_id';
    VAL = '';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'book';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#410093';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Доля полностью обеспеченных учебниками';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    IF(V$VAL = 0) THEN F = NULL; ELSE F = 100 * CAST(V$VAL2 AS FLOAT) / CAST(V$VAL AS FLOAT);
    VAL = CAST(F AS NUMERIC(18, 1));
    SUSPEND;

    SELECT COUNT(*)
    FROM LINKS L111
    JOIN LINKS L2 ON L2.PARENT_ID = L111.OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    JOIN LINKS L23 ON L23.PARENT_ID = L2.OBJ_ID AND L23.OBJ_TYPE_ID = 23 AND L23.DATE_DEL IS NULL
    JOIN LINKS L128 ON L128.PARENT_ID = L23.OBJ_ID AND L128.OBJ_TYPE_ID = 128 AND L128.DATE_DEL IS NULL
    JOIN VALL V876 ON V876.OBJ_ID = L128.OBJ_ID AND V876.PARAM_ID = 876 AND V876.IS_DEL = 0 AND V876.LISTVAL_ID IN (2069, 2070, 2071, 2072, 2073, 2074)
    WHERE L111.PARENT_ID = :I$OBJ_ID AND L111.OBJ_TYPE_ID = 111 AND L111.DATE_DEL IS NULL
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'labs';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '128';
    SUSPEND;
    TAG_NAME = 'dashboard:r:subtype_id';
    VAL = '';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'cog';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#410093';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Единиц лабораторных комплексов';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

    SELECT COUNT(*)
    FROM LINKS L111
    JOIN LINKS L2 ON L2.PARENT_ID = L111.OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    JOIN LINKS L23 ON L23.PARENT_ID = L2.OBJ_ID AND L23.OBJ_TYPE_ID = 23 AND L23.DATE_DEL IS NULL
    JOIN LINKS L128 ON L128.PARENT_ID = L23.OBJ_ID AND L128.OBJ_TYPE_ID = 128 AND L128.DATE_DEL IS NULL
    JOIN VALL V876 ON V876.OBJ_ID = L128.OBJ_ID AND V876.PARAM_ID = 876 AND V876.IS_DEL = 0 AND V876.LISTVAL_ID IN (2067, 2068)
    WHERE L111.PARENT_ID = :I$OBJ_ID AND L111.OBJ_TYPE_ID = 111 AND L111.DATE_DEL IS NULL
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'computers';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '128';
    SUSPEND;
    TAG_NAME = 'dashboard:r:subtype_id';
    VAL = '';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'desktop';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#410093';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Количество компьютерных классов';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

    SELECT COUNT(*)
    FROM LINKS L111
    JOIN LINKS L2 ON L2.PARENT_ID = L111.OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    JOIN LINKS L116 ON L116.PARENT_ID = L2.OBJ_ID AND L116.OBJ_TYPE_ID = 116 AND L116.DATE_DEL IS NULL
    JOIN VALL V695 ON V695.OBJ_ID = L116.OBJ_ID AND V695.PARAM_ID = 695 AND V695.IS_DEL = 0 AND V695.LISTVAL_ID IN (2180, 2181)
    WHERE L111.PARENT_ID = :I$OBJ_ID AND L111.OBJ_TYPE_ID = 111 AND L111.DATE_DEL IS NULL
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'networks';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '116';
    SUSPEND;
    TAG_NAME = 'dashboard:r:subtype_id';
    VAL = '2180';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'cloud';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#410093';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Количество локальных сетей';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

    SELECT COUNT(*)
    FROM LINKS L111
    JOIN LINKS L2 ON L2.PARENT_ID = L111.OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    JOIN LINKS L116 ON L116.PARENT_ID = L2.OBJ_ID AND L116.OBJ_TYPE_ID = 116 AND L116.DATE_DEL IS NULL
    JOIN VALL V695 ON V695.OBJ_ID = L116.OBJ_ID AND V695.PARAM_ID = 695 AND V695.IS_DEL = 0 AND V695.LISTVAL_ID IN (2182)
    WHERE L111.PARENT_ID = :I$OBJ_ID AND L111.OBJ_TYPE_ID = 111 AND L111.DATE_DEL IS NULL
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'networkjs';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '116';
    SUSPEND;
    TAG_NAME = 'dashboard:r:subtype_id';
    VAL = '2182';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'rss';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#410093';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Количество зон WiFi';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

    SELECT COUNT(*)
    FROM LINKS L111
    JOIN LINKS L2 ON L2.PARENT_ID = L111.OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    JOIN LINKS L116 ON L116.PARENT_ID = L2.OBJ_ID AND L116.OBJ_TYPE_ID = 116 AND L116.DATE_DEL IS NULL
    JOIN VALL V697 ON V697.OBJ_ID = L116.OBJ_ID AND V697.PARAM_ID = 697 AND V697.IS_DEL = 0 AND V697.LISTVAL_ID = 2
    WHERE L111.PARENT_ID = :I$OBJ_ID AND L111.OBJ_TYPE_ID = 111 AND L111.DATE_DEL IS NULL
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'networks';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '116';
    SUSPEND;
    TAG_NAME = 'dashboard:r:subtype_id';
    VAL = '697';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'cloud';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#410093';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Количество сетей с доступом к Интернет';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;
  END
  ELSE
  BEGIN

    TAG_NAME = 'title';
    VAL = 'Сотрудники';
    SUSPEND;

    TAG_NAME = 'has_caption';
    VAL = 1;
    SUSPEND;

    TAG_NAME = 'columns::json&colon;array';
    VAL = 1;
    SUSPEND;

    TAG_NAME = 'columns:r'; VAL = NULL; SUSPEND;
    TAG_NAME = 'columns:r:type_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:param_id'; VAL = '0'; SUSPEND;
    TAG_NAME = 'columns:r:type'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:name'; VAL = 'Количество ОУ'; SUSPEND;

    TAG_NAME = 'columns:r'; VAL = NULL; SUSPEND;
    TAG_NAME = 'columns:r:type_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:param_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:type'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:name'; VAL = 'Доля полностью обеспеченных учебниками'; SUSPEND;

    TAG_NAME = 'columns:r'; VAL = NULL; SUSPEND;
    TAG_NAME = 'columns:r:type_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:param_id'; VAL = '2'; SUSPEND;
    TAG_NAME = 'columns:r:type'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:name'; VAL = 'Единиц лабораторных комплексов'; SUSPEND;

    TAG_NAME = 'columns:r'; VAL = NULL; SUSPEND;
    TAG_NAME = 'columns:r:type_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:param_id'; VAL = '3'; SUSPEND;
    TAG_NAME = 'columns:r:type'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:name'; VAL = 'Количество компьютерных классов'; SUSPEND;

    -- Развертка по районам
    TAG_NAME = 'rows::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT L111.OBJ_ID, L111.OBJ_TYPE_ID, C.CAPTION
      FROM LINKS L111
      LEFT JOIN OBJECT_CAPTION_GET(L111.OBJ_ID) C ON 1 = 1
      WHERE L111.PARENT_ID = :I$OBJ_ID AND L111.OBJ_TYPE_ID = 111 AND L111.DATE_DEL IS NULL
      ORDER BY 3
      INTO :V$OBJ_ID, :V$TYPE, :S
    DO
    BEGIN
      TAG_NAME = 'rows:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'rows:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'rows:r:type_id';
      VAL = '1';
      SUSPEND;
      TAG_NAME = 'rows:r:caption';
      VAL = S;
      SUSPEND;

      SELECT COUNT(*)
      FROM LINKS L2
      WHERE L2.PARENT_ID = :V$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      INTO :V$VAL;

      TAG_NAME = 'rows:r:p0';
      VAL = V$VAL;
      SUSPEND;

      SELECT SUM(V2685.VAL), SUM(V2686.VAL)
      FROM LINKS L2
      JOIN LINKS L162 ON L162.PARENT_ID = L2.OBJ_ID AND L162.OBJ_TYPE_ID = 162 AND L162.DATE_DEL IS NULL
      JOIN LINKS L345 ON L345.PARENT_ID = L162.OBJ_ID AND L345.OBJ_TYPE_ID = 345 AND L345.DATE_DEL IS NULL
      JOIN VALI V2685 ON V2685.OBJ_ID = L345.OBJ_ID AND V2685.PARAM_ID = 2685 AND V2685.IS_DEL = 0
      JOIN VALI V2686 ON V2686.OBJ_ID = L345.OBJ_ID AND V2686.PARAM_ID = 2686 AND V2686.IS_DEL = 0
      WHERE L2.PARENT_ID = :V$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      INTO :V$VAL, :V$VAL2;

      TAG_NAME = 'rows:r:p1';
      IF(V$VAL = 0) THEN F = NULL; ELSE F = 100 * CAST(V$VAL2 AS FLOAT) / CAST(V$VAL AS FLOAT);
      VAL = CAST(F AS NUMERIC(18, 1));
      SUSPEND;

      SELECT COUNT(*)
      FROM LINKS L2
      JOIN LINKS L23 ON L23.PARENT_ID = L2.OBJ_ID AND L23.OBJ_TYPE_ID = 23 AND L23.DATE_DEL IS NULL
      JOIN LINKS L128 ON L128.PARENT_ID = L23.OBJ_ID AND L128.OBJ_TYPE_ID = 128 AND L128.DATE_DEL IS NULL
      JOIN VALL V876 ON V876.OBJ_ID = L128.OBJ_ID AND V876.PARAM_ID = 876 AND V876.IS_DEL = 0 AND V876.LISTVAL_ID IN (2069, 2070, 2071, 2072, 2073, 2074)
      WHERE L2.PARENT_ID = :V$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      INTO :V$VAL;

      TAG_NAME = 'rows:r:p2';
      VAL = V$VAL;
      SUSPEND;

      SELECT COUNT(*)
      FROM LINKS L2
      JOIN LINKS L23 ON L23.PARENT_ID = L2.OBJ_ID AND L23.OBJ_TYPE_ID = 23 AND L23.DATE_DEL IS NULL
      JOIN LINKS L128 ON L128.PARENT_ID = L23.OBJ_ID AND L128.OBJ_TYPE_ID = 128 AND L128.DATE_DEL IS NULL
      JOIN VALL V876 ON V876.OBJ_ID = L128.OBJ_ID AND V876.PARAM_ID = 876 AND V876.IS_DEL = 0 AND V876.LISTVAL_ID IN (2067, 2068)
      WHERE L2.PARENT_ID = :V$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      INTO :V$VAL;

      TAG_NAME = 'rows:r:p3';
      VAL = V$VAL;
      SUSPEND;

    END

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PF_ITEM_DELETE (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
AS
declare variable V$YEAR_DATE date;
declare variable V$YEAR_ID bigint;
declare variable V$STUDENT_ID bigint;
declare variable V$PERSON_ID bigint;
declare variable V$ROLE smallint;
declare variable V$PERSON_TYPE bigint;
declare variable V$APPROVED bigint;
begin

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  SELECT FIRST 1 CAST(LV.TAG AS DATE), LV.LISTVAL_ID
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$YEAR_DATE, :V$YEAR_ID;

  SELECT L.PARENT_ID
  FROM LINKS L
  WHERE L.OBJ_ID = :I$OBJ_ID AND L.PARENT_TYPE_ID = 10 AND L.DATE_DEL IS NULL AND L.OBJ_TYPE_ID IN (297, 22, 24, 25)
  INTO :V$STUDENT_ID;

  IF(V$STUDENT_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Запись не найдена или была удалена';

  IF(EXISTS(
    SELECT FIRST 1 1
    FROM VALS V
    WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID IN (2879, 3188) AND V.IS_DEL = 0
  ))
  THEN EXCEPTION DATA_ERROR 'Данная запись получена автоматически, ее нельзя изменить или удалить вручную';

  -- Оставляем возможность править данные вплоть до мая предыдущего учебного года
  IF(EXISTS(
    SELECT FIRST 1 1
    FROM VALD V
    WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID IN (166, 3183, 177, 1827) AND V.IS_DEL = 0 AND V.VAL < DATEADD(-4 MONTH TO :V$YEAR_DATE)
  ))
  THEN EXCEPTION DATA_ERROR 'Изменять можно только данные текущего учебного года';

  SELECT FIRST 1 U.OBJ_ID, U.USER_TYPE, O.TYPE_ID
  FROM USERS U
  LEFT JOIN OBJECTS O ON O.OBJ_ID = U.OBJ_ID
  WHERE U.DATE_DEL IS NULL AND U.USER_ID = :I$USER_ID AND U.IS_BLOCKED = 0 AND (U.EXP_DATE IS NULL OR U.EXP_DATE >= CURRENT_DATE)
  INTO :V$PERSON_ID, :V$ROLE, :V$PERSON_TYPE;

  IF(V$ROLE IS NULL) THEN EXCEPTION DATA_ERROR 'Пользователь не идентифицирован как сотрудник';

  -- Ученик не может изменять подтвержденную запись
  IF(I$OBJ_ID IS NOT NULL AND V$PERSON_TYPE = 10) THEN
  BEGIN
    SELECT FIRST 1 V.LISTVAL_ID
    FROM VALL V
    WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 3194 AND V.IS_DEL = 0
    INTO :V$APPROVED;
    IF(V$APPROVED = 2 OR V$APPROVED IS NULL) THEN EXCEPTION DATA_ERROR 'Запись отмечена как подтвержденная, вы не можете ее изменять';
  END

  UPDATE LINKS
  SET DATE_DEL = CURRENT_TIMESTAMP
  WHERE OBJ_ID = :I$OBJ_ID;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PF_ITEM_DO_GET (
    I$PERSON_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$ZONE SMALLINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
declare variable V$PERSON_ID bigint;
declare variable V$ROLE smallint;
declare variable V$PERSON_TYPE bigint;
declare variable V$PARENT_ID bigint;
declare variable V$OBJ_ID bigint;
declare variable S varchar(1000);
begin

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  IF(I$OBJ_ID IS NOT NULL) THEN
  BEGIN
    I$PERSON_ID = NULL;
    SELECT L297.PARENT_ID
    FROM LINKS L297
    WHERE L297.OBJ_ID = :I$OBJ_ID AND L297.PARENT_TYPE_ID = 10 AND L297.DATE_DEL IS NULL AND L297.OBJ_TYPE_ID = 297
    INTO :I$PERSON_ID;

    IF(I$PERSON_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Запись не найдена или была удалена';
  END

  SELECT FIRST 1 U.OBJ_ID, U.USER_TYPE, O.TYPE_ID
  FROM USERS U
  LEFT JOIN OBJECTS O ON O.OBJ_ID = U.OBJ_ID
  WHERE U.DATE_DEL IS NULL AND U.USER_ID = :I$USER_ID AND U.IS_BLOCKED = 0 AND (U.EXP_DATE IS NULL OR U.EXP_DATE >= CURRENT_DATE)
  INTO :V$PERSON_ID, :V$ROLE, :V$PERSON_TYPE;

  IF(V$ROLE IS NULL) THEN EXCEPTION DATA_ERROR 'Пользователь не идентифицирован как сотрудник';

  -- Если PERSON_ID не указан (создание новой строки), значит берем самого себя
  IF(I$PERSON_ID IS NULL) THEN
  BEGIN
    IF(V$PERSON_TYPE IS NULL OR V$PERSON_TYPE <> 10) THEN EXCEPTION DATA_ERROR 'Записи портфолио доступны только для обучащихся';
    I$PERSON_ID = V$PERSON_ID;
  END
  ELSE
  BEGIN
    -- !!! проверить права доступа к данной персоне !!!
  END

  TAG_NAME = 'id';
  VAL = I$OBJ_ID;
  SUSPEND;
  TAG_NAME = 'person_id';
  VAL = I$PERSON_ID;
  SUSPEND;
  TAG_NAME = 'oo_ved_id:selection::json&colon;array';
  VAL = 1;
  SUSPEND;
  -- Ведомственная принадлежность - тут 2-уровневый список, выдаем только нижний уровень
  FOR
    SELECT LV.PARENT_ID, LV.LISTVAL_ID, LV.VAL
    FROM LISTVALS_LIST(291) LV
    WHERE LV.IS_DEL = 0 AND LV.PARENT_ID IS NOT NULL
    ORDER BY LV.SORT_ORDER
    INTO :V$PARENT_ID, :V$OBJ_ID, :S
  DO
  BEGIN
    TAG_NAME = 'oo_ved_id:selection:option';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'oo_ved_id:selection:option:parent_id';
    VAL = V$PARENT_ID;
    SUSPEND;
    TAG_NAME = 'oo_ved_id:selection:option:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'oo_ved_id:selection:option:value';
    VAL = S;
    SUSPEND;
  END
  TAG_NAME = 'oo_ved_id:values:value';
  VAL = NULL;
  SELECT FIRST 1 V.LISTVAL_ID FROM VALL V WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 2391 AND V.IS_DEL = 0 INTO :VAL;
  SUSPEND;
  TAG_NAME = 'direction:selection::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT LV.LISTVAL_ID, LV.VAL
    FROM FILTRED_LIST(22, 'DO') LV
    ORDER BY 2
    INTO :V$OBJ_ID, :S
  DO
  BEGIN
    TAG_NAME = 'direction:selection:option';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'direction:selection:option:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'direction:selection:option:value';
    VAL = S;
    SUSPEND;
  END
  TAG_NAME = 'direction:values:value';
  VAL = NULL;
  SELECT FIRST 1 V.LISTVAL_ID FROM VALL V WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 2392 AND V.IS_DEL = 0 INTO :VAL;
  SUSPEND;
  TAG_NAME = 'fin_id:selection::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT LV.LISTVAL_ID, LV.VAL
    FROM LISTVALS_LIST(293) LV
    WHERE LV.IS_DEL = 0
    ORDER BY LV.SORT_ORDER
    INTO :V$OBJ_ID, :S
  DO
  BEGIN
    TAG_NAME = 'fin_id:selection:option';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'fin_id:selection:option:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'fin_id:selection:option:value';
    VAL = S;
    SUSPEND;
  END
  TAG_NAME = 'fin_id:values:value';
  VAL = NULL;
  SELECT FIRST 1 V.LISTVAL_ID FROM VALL V WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 2393 AND V.IS_DEL = 0 INTO :VAL;
  SUSPEND;
  TAG_NAME = 'oo_name';
  VAL = NULL;
  SELECT FIRST 1 V.VAL FROM VALS V WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 3187 AND V.IS_DEL = 0 INTO :VAL;
  SUSPEND;
  TAG_NAME = 'grade_name';
  VAL = NULL;
  SELECT FIRST 1 V.VAL FROM VALS V WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 3189 AND V.IS_DEL = 0 INTO :VAL;
  SUSPEND;
  TAG_NAME = 'dur';
  VAL = NULL;
  SELECT FIRST 1 V.VAL FROM VALI V WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 3185 AND V.IS_DEL = 0 INTO :VAL;
  SUSPEND;
  TAG_NAME = 'stage';
  VAL = NULL;
  SELECT FIRST 1 V.VAL FROM VALI V WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 3186 AND V.IS_DEL = 0 INTO :VAL;
  SUSPEND;
  TAG_NAME = 'date_in';
  VAL = NULL;
  SELECT FIRST 1 D.VAL FROM VALD V LEFT JOIN DATE2ISO(V.VAL, 0) D ON 1 = 1 WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 3183 AND V.IS_DEL = 0 INTO :VAL;
  SUSPEND;
  TAG_NAME = 'date_out';
  VAL = NULL;
  SELECT FIRST 1 D.VAL FROM VALD V LEFT JOIN DATE2ISO(V.VAL, 0) D ON 1 = 1 WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 3184 AND V.IS_DEL = 0 INTO :VAL;
  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PF_ITEM_DO_SET (
    I$PERSON_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$OO_VED_ID BIGINT,
    I$DIRECTION BIGINT,
    I$FIN_ID BIGINT,
    I$OO_NAME VARCHAR(1000),
    I$GRADE_NAME VARCHAR(1000),
    I$DUR INTEGER,
    I$STAGE INTEGER,
    I$DATE_IN DATE,
    I$DATE_OUT DATE,
    I$VER SMALLINT NOT NULL,
    I$USER_ID VARCHAR(40))
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$PERSON_ID bigint;
declare variable V$ROLE smallint;
declare variable V$PERSON_TYPE bigint;
declare variable V$APPROVED bigint;
declare variable V$YEAR_DATE date;
declare variable V$YEAR_ID bigint;
declare variable T bigint;
begin

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  SELECT FIRST 1 CAST(LV.TAG AS DATE), LV.LISTVAL_ID
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$YEAR_DATE, :V$YEAR_ID;

  IF(I$OBJ_ID IS NOT NULL) THEN
  BEGIN
    I$PERSON_ID = NULL;
    SELECT L.PARENT_ID
    FROM LINKS L
    WHERE L.OBJ_ID = :I$OBJ_ID AND L.PARENT_TYPE_ID = 10 AND L.DATE_DEL IS NULL AND L.OBJ_TYPE_ID = 297
    INTO :I$PERSON_ID;

    IF(I$PERSON_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Запись не найдена или была удалена';

    IF(EXISTS(
      SELECT FIRST 1 1
      FROM VALS V
      WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 3188 AND V.IS_DEL = 0
    ))
    THEN EXCEPTION DATA_ERROR 'Данная запись получена автоматически через портал ДО, ее нельзя редактировать вручную';

    -- Оставляем возможность править данные вплоть до мая предыдущего учебного года
    IF(EXISTS(
      SELECT FIRST 1 1
      FROM VALD V
      WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 3183 AND V.IS_DEL = 0 AND V.VAL < DATEADD(-4 MONTH TO :V$YEAR_DATE)
    ))
    THEN EXCEPTION DATA_ERROR 'Изменять можно только данные текущего учебного года';
  END

  SELECT FIRST 1 U.OBJ_ID, U.USER_TYPE, O.TYPE_ID
  FROM USERS U
  LEFT JOIN OBJECTS O ON O.OBJ_ID = U.OBJ_ID
  WHERE U.DATE_DEL IS NULL AND U.USER_ID = :I$USER_ID AND U.IS_BLOCKED = 0 AND (U.EXP_DATE IS NULL OR U.EXP_DATE >= CURRENT_DATE)
  INTO :V$PERSON_ID, :V$ROLE, :V$PERSON_TYPE;

  IF(V$ROLE IS NULL) THEN EXCEPTION DATA_ERROR 'Пользователь не идентифицирован как сотрудник';

  -- Ученик не может изменять подтвержденную запись
  IF(I$OBJ_ID IS NOT NULL AND V$PERSON_TYPE = 10) THEN
  BEGIN
    SELECT FIRST 1 V.LISTVAL_ID
    FROM VALL V
    WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 3194 AND V.IS_DEL = 0
    INTO :V$APPROVED;
    IF(V$APPROVED = 2 OR V$APPROVED IS NULL) THEN EXCEPTION DATA_ERROR 'Запись отмечена как подтвержденная, вы не можете ее изменять';
  END
  -- При добавлении учеников ставим всегда отсутствие верификации
  IF(V$PERSON_TYPE = 10) THEN I$VER = 0;
  -- При добавлении учеником не даем спамить - не более 3 записей в неподтвержденном статусе
  IF(I$OBJ_ID IS NULL AND V$PERSON_TYPE = 10) THEN
  BEGIN
    IF((
      SELECT COUNT(*)
      FROM LINKS L
      JOIN VALL V ON V.OBJ_ID = L.OBJ_ID AND V.PARAM_ID = 3194 AND V.IS_DEL = 0 AND V.LISTVAL_ID = 3
      WHERE L.PARENT_ID = :I$PERSON_ID AND L.OBJ_TYPE_ID = 297 AND L.DATE_DEL IS NULL
    ) >= 3)
    THEN EXCEPTION DATA_ERROR 'Обучающийся не может добавлять более 3 записей подряд. Попросите сотрудника образовательной организации верифицировать уже внесенные данные';
  END

  -- Если PERSON_ID не указан (создание новой строки), значит берем самого себя
  IF(I$PERSON_ID IS NULL) THEN
  BEGIN
    IF(V$PERSON_TYPE IS NULL OR V$PERSON_TYPE <> 10) THEN EXCEPTION DATA_ERROR 'Записи портфолио доступны только для обучащихся';
    I$PERSON_ID = V$PERSON_ID;
  END
  ELSE
  BEGIN
    IF(NOT EXISTS(
      SELECT FIRST 1 1
      FROM LINKS L10
      WHERE L10.DATE_DEL IS NULL AND L10.OBJ_ID = :I$PERSON_ID AND L10.OBJ_TYPE_ID = 10 AND L10.PARENT_TYPE_ID IN (9, 187, 290)
    )) THEN EXCEPTION DATA_ERROR 'Персона не найдена или не является действующим обучающимся';
    -- !!! проверить права доступа к данной персоне !!!
  END

  IF(I$OBJ_ID IS NULL) THEN
    SELECT OBJ_ID FROM OBJECT_ADD(:I$PERSON_ID, 297, NULL, :I$USER_ID) INTO :OBJ_ID;
  ELSE
    OBJ_ID = I$OBJ_ID;

  IF(I$DATE_IN IS NULL) THEN EXCEPTION DATA_ERROR 'Дата начала занятий является обязательным полем';
  IF(I$DATE_IN < DATEADD(-4 MONTH TO V$YEAR_DATE) OR I$DATE_IN > DATEADD(12 MONTH TO V$YEAR_DATE)) THEN EXCEPTION DATA_ERROR 'Можно вносить даты только диапазоне от мая текущего учебного года до августа следующего года';

  IF(I$VER = 1 AND (I$OO_VED_ID IS NULL OR I$DIRECTION IS NULL OR I$FIN_ID IS NULL OR I$OO_NAME IS NULL
    OR I$GRADE_NAME IS NULL)) THEN EXCEPTION DATA_ERROR 'Для верификации требуется, чтобы были заполнены обязательные поля';

  -- поле 2390 заполняется автоматически
  SELECT BLOB_ID FROM VAL_ADD(2391, :OBJ_ID, :I$OO_VED_ID) INTO :T;
  SELECT BLOB_ID FROM VAL_ADD(2392, :OBJ_ID, :I$DIRECTION) INTO :T;
  SELECT BLOB_ID FROM VAL_ADD(2393, :OBJ_ID, :I$FIN_ID) INTO :T;
  -- учебный год не редактируется, только заполняется
  IF(I$OBJ_ID IS NULL) THEN SELECT BLOB_ID FROM VAL_ADD(2394, :OBJ_ID, :V$YEAR_ID) INTO :T;
  SELECT BLOB_ID FROM VAL_ADD(3187, :OBJ_ID, :I$OO_NAME) INTO :T;
  SELECT BLOB_ID FROM VAL_ADD(3189, :OBJ_ID, :I$GRADE_NAME) INTO :T;
  SELECT BLOB_ID FROM VAL_ADD(3185, :OBJ_ID, :I$DUR) INTO :T;
  SELECT BLOB_ID FROM VAL_ADD(3186, :OBJ_ID, :I$STAGE) INTO :T;
  SELECT BLOB_ID FROM VAL_ADD(3183, :OBJ_ID, :I$DATE_IN) INTO :T;
  SELECT BLOB_ID FROM VAL_ADD(3184, :OBJ_ID, :I$DATE_OUT) INTO :T;

  SELECT BLOB_ID FROM VAL_ADD(3194, :OBJ_ID, IIF(:I$VER = 0, 3, 2)) INTO :T;

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PF_ITEM_PF_GET (
    I$PERSON_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$PART BIGINT NOT NULL,
    I$ZONE SMALLINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
declare variable V$PERSON_ID bigint;
declare variable V$ROLE smallint;
declare variable V$PERSON_TYPE bigint;
declare variable V$PARENT_ID bigint;
declare variable V$OBJ_ID bigint;
declare variable S varchar(1000);
begin

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  IF(I$PART NOT IN (22, 24, 25)) THEN EXCEPTION DATA_ERROR 'Недопустимый тип записи';

  IF(I$OBJ_ID IS NOT NULL) THEN
  BEGIN
    I$PERSON_ID = NULL;
    SELECT L.PARENT_ID
    FROM LINKS L
    WHERE L.OBJ_ID = :I$OBJ_ID AND L.PARENT_TYPE_ID = 10 AND L.DATE_DEL IS NULL AND L.OBJ_TYPE_ID = :I$PART
    INTO :I$PERSON_ID;

    IF(I$PERSON_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Запись не найдена или была удалена';
  END

  SELECT FIRST 1 U.OBJ_ID, U.USER_TYPE, O.TYPE_ID
  FROM USERS U
  LEFT JOIN OBJECTS O ON O.OBJ_ID = U.OBJ_ID
  WHERE U.DATE_DEL IS NULL AND U.USER_ID = :I$USER_ID AND U.IS_BLOCKED = 0 AND (U.EXP_DATE IS NULL OR U.EXP_DATE >= CURRENT_DATE)
  INTO :V$PERSON_ID, :V$ROLE, :V$PERSON_TYPE;

  IF(V$ROLE IS NULL) THEN EXCEPTION DATA_ERROR 'Пользователь не идентифицирован как сотрудник';

  -- Если PERSON_ID не указан (создание новой строки), значит берем самого себя
  IF(I$PERSON_ID IS NULL) THEN
  BEGIN
    IF(V$PERSON_TYPE IS NULL OR V$PERSON_TYPE <> 10) THEN EXCEPTION DATA_ERROR 'Записи портфолио доступны только для обучащихся';
    I$PERSON_ID = V$PERSON_ID;
  END
  ELSE
  BEGIN
    IF(NOT EXISTS(
      SELECT FIRST 1 1
      FROM LINKS L10
      WHERE L10.DATE_DEL IS NULL AND L10.OBJ_ID = :I$PERSON_ID AND L10.OBJ_TYPE_ID = 10 AND L10.PARENT_TYPE_ID IN (9, 187, 290)
    )) THEN EXCEPTION DATA_ERROR 'Персона не найдена или не является действующим обучающимся';
    -- !!! проверить права доступа к данной персоне !!!
  END

  TAG_NAME = 'id';
  VAL = I$OBJ_ID;
  SUSPEND;
  TAG_NAME = 'person_id';
  VAL = I$PERSON_ID;
  SUSPEND;
  TAG_NAME = 'part';
  VAL = I$PART;
  SUSPEND;

  IF(I$PART = 22) THEN
  BEGIN
    TAG_NAME = 'type:selection::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT LV.LISTVAL_ID, LV.VAL
      FROM LISTVALS_LIST(53) LV
      WHERE LV.IS_DEL = 0
      ORDER BY LV.SORT_ORDER
      INTO :V$OBJ_ID, :S
    DO
    BEGIN
      TAG_NAME = 'type:selection:option';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'type:selection:option:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'type:selection:option:value';
      VAL = S;
      SUSPEND;
    END
    TAG_NAME = 'type:values:value';
    VAL = NULL;
    SELECT LV.LISTVAL_ID
    FROM VALS V
    JOIN LISTVALS LV ON LV.LIST_ID = 53 AND LV.IS_DEL = 0
    JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU' AND R.VAL = V.VAL
    WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 167 AND V.IS_DEL = 0
    INTO :VAL;
    SUSPEND;

    TAG_NAME = 'level:selection::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT LV.LISTVAL_ID, LV.VAL
      FROM LISTVALS_LIST(251) LV
      WHERE LV.IS_DEL = 0
      ORDER BY LV.SORT_ORDER
      INTO :V$OBJ_ID, :S
    DO
    BEGIN
      TAG_NAME = 'level:selection:option';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'level:selection:option:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'level:selection:option:value';
      VAL = S;
      SUSPEND;
    END
    TAG_NAME = 'level:values:value';
    VAL = NULL;
    SELECT V.LISTVAL_ID
    FROM VALL V
    WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 1819 AND V.IS_DEL = 0
    INTO :VAL;

    SUSPEND;
    TAG_NAME = 'name';
    VAL = NULL;
    SELECT V.VAL
    FROM VALS V
    WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 1818 AND V.IS_DEL = 0
    INTO :VAL;
    SUSPEND;
    TAG_NAME = 'theme';
    VAL = NULL;
    SELECT V.VAL
    FROM VALS V
    WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 1820 AND V.IS_DEL = 0
    INTO :VAL;
    SUSPEND;
    TAG_NAME = 'date';
    VAL = NULL;
    SELECT D.VAL
    FROM VALD V
    LEFT JOIN DATE2ISO(V.VAL, 0) D ON 1 = 1
    WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 166 AND V.IS_DEL = 0
    INTO :VAL;
    SUSPEND;

    TAG_NAME = 'result:selection::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT LV.LISTVAL_ID, LV.VAL
      FROM LISTVALS_LIST(250) LV
      WHERE LV.IS_DEL = 0
      ORDER BY LV.SORT_ORDER
      INTO :V$OBJ_ID, :S
    DO
    BEGIN
      TAG_NAME = 'result:selection:option';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'result:selection:option:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'result:selection:option:value';
      VAL = S;
      SUSPEND;
    END
    TAG_NAME = 'result:values:value';
    VAL = NULL;
    SELECT V.LISTVAL_ID
    FROM VALL V
    WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 237 AND V.IS_DEL = 0
    INTO :VAL;
    SUSPEND;

    TAG_NAME = 'ver';
    VAL = NULL;
    SELECT IIF(V.LISTVAL_ID = 2, 1, 0)
    FROM VALL V
    WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 3182 AND V.IS_DEL = 0
    INTO :VAL;
    SUSPEND;
  END

  IF(I$PART = 24) THEN
  BEGIN
    TAG_NAME = 'sport:selection::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT LV.LISTVAL_ID, LV.VAL
      FROM LISTVALS_LIST(58) LV
      WHERE LV.IS_DEL = 0
      ORDER BY LV.SORT_ORDER
      INTO :V$OBJ_ID, :S
    DO
    BEGIN
      TAG_NAME = 'sport:selection:option';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'sport:selection:option:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'sport:selection:option:value';
      VAL = S;
      SUSPEND;
    END
    TAG_NAME = 'sport:values:value';
    VAL = NULL;
    SELECT V.LISTVAL_ID
    FROM VALL V
    WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 178 AND V.IS_DEL = 0
    INTO :VAL;
    SUSPEND;

    TAG_NAME = 'level:selection::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT LV.LISTVAL_ID, LV.VAL
      FROM LISTVALS_LIST(251) LV
      WHERE LV.IS_DEL = 0
      ORDER BY LV.SORT_ORDER
      INTO :V$OBJ_ID, :S
    DO
    BEGIN
      TAG_NAME = 'level:selection:option';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'level:selection:option:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'level:selection:option:value';
      VAL = S;
      SUSPEND;
    END
    TAG_NAME = 'level:values:value';
    VAL = NULL;
    SELECT V.LISTVAL_ID
    FROM VALL V
    WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 1826 AND V.IS_DEL = 0
    INTO :VAL;
    SUSPEND;

    TAG_NAME = 'result:selection::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT LV.LISTVAL_ID, LV.VAL
      FROM LISTVALS_LIST(250) LV
      WHERE LV.IS_DEL = 0
      ORDER BY LV.SORT_ORDER
      INTO :V$OBJ_ID, :S
    DO
    BEGIN
      TAG_NAME = 'result:selection:option';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'result:selection:option:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'result:selection:option:value';
      VAL = S;
      SUSPEND;
    END
    TAG_NAME = 'result:values:value';
    VAL = NULL;
    SELECT V.LISTVAL_ID
    FROM VALL V
    WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 236 AND V.IS_DEL = 0
    INTO :VAL;
    SUSPEND;

    TAG_NAME = 'date';
    VAL = NULL;
    SELECT D.VAL
    FROM VALD V
    LEFT JOIN DATE2ISO(V.VAL, 0) D ON 1 = 1
    WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 177 AND V.IS_DEL = 0
    INTO :VAL;
    SUSPEND;

    TAG_NAME = 'ver';
    VAL = NULL;
    SELECT IIF(V.LISTVAL_ID = 2, 1, 0)
    FROM VALL V
    WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 3193 AND V.IS_DEL = 0
    INTO :VAL;
    SUSPEND;
  END

  IF(I$PART = 25) THEN
  BEGIN
    TAG_NAME = 'sport:selection::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT LV.LISTVAL_ID, LV.VAL
      FROM LISTVALS_LIST(58) LV
      WHERE LV.IS_DEL = 0
      ORDER BY LV.SORT_ORDER
      INTO :V$OBJ_ID, :S
    DO
    BEGIN
      TAG_NAME = 'sport:selection:option';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'sport:selection:option:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'sport:selection:option:value';
      VAL = S;
      SUSPEND;
    END
    TAG_NAME = 'sport:values:value';
    VAL = NULL;
    SELECT V.LISTVAL_ID
    FROM VALL V
    WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 181 AND V.IS_DEL = 0
    INTO :VAL;
    SUSPEND;

    TAG_NAME = 'level:selection::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT LV.LISTVAL_ID, LV.VAL
      FROM LISTVALS_LIST(59) LV
      WHERE LV.IS_DEL = 0
      ORDER BY LV.SORT_ORDER
      INTO :V$OBJ_ID, :S
    DO
    BEGIN
      TAG_NAME = 'level:selection:option';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'level:selection:option:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'level:selection:option:value';
      VAL = S;
      SUSPEND;
    END
    TAG_NAME = 'level:values:value';
    VAL = NULL;
    SELECT V.LISTVAL_ID
    FROM VALL V
    WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 180 AND V.IS_DEL = 0
    INTO :VAL;
    SUSPEND;

    TAG_NAME = 'org_name';
    VAL = NULL;
    SELECT V.VAL
    FROM VALS V
    WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 1828 AND V.IS_DEL = 0
    INTO :VAL;
    SUSPEND;

    TAG_NAME = 'date';
    VAL = NULL;
    SELECT D.VAL
    FROM VALD V
    LEFT JOIN DATE2ISO(V.VAL, 0) D ON 1 = 1
    WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 1827 AND V.IS_DEL = 0
    INTO :VAL;
    SUSPEND;

    TAG_NAME = 'ver';
    VAL = NULL;
    SELECT IIF(V.LISTVAL_ID = 2, 1, 0)
    FROM VALL V
    WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 3192 AND V.IS_DEL = 0
    INTO :VAL;
    SUSPEND;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PF_ITEM_PF_SET (
    I$PERSON_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$PART BIGINT,
    I$DATE DATE,
    I$LEVEL BIGINT,
    I$RESULT BIGINT,
    I$SPORT BIGINT,
    I$NAME VARCHAR(1000),
    I$THEME VARCHAR(1000),
    I$VER SMALLINT NOT NULL,
    I$USER_ID VARCHAR(40))
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$PERSON_ID bigint;
declare variable V$ROLE smallint;
declare variable V$PERSON_TYPE bigint;
declare variable V$APPROVED bigint;
declare variable V$YEAR_DATE date;
declare variable T bigint;
declare variable S varchar(400);
begin

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  IF(I$PART NOT IN (22, 24, 25)) THEN EXCEPTION DATA_ERROR 'Недопустимый тип записи';

  SELECT FIRST 1 CAST(LV.TAG AS DATE)
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$YEAR_DATE;

  IF(I$OBJ_ID IS NOT NULL) THEN
  BEGIN
    I$PERSON_ID = NULL;
    SELECT L.PARENT_ID
    FROM LINKS L
    WHERE L.OBJ_ID = :I$OBJ_ID AND L.PARENT_TYPE_ID = 10 AND L.DATE_DEL IS NULL AND L.OBJ_TYPE_ID = :I$PART
    INTO :I$PERSON_ID;

    IF(I$PERSON_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Запись не найдена или была удалена';

    -- Это только для основных записей портфолио, по спорту их нет
    IF(EXISTS(
      SELECT FIRST 1 1
      FROM VALS V
      WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 2879 AND V.IS_DEL = 0
    ))
    THEN EXCEPTION DATA_ERROR 'Данная запись получена автоматически через портал ДО, ее нельзя редактировать вручную';

    -- Оставляем возможность править данные вплоть до мая предыдущего учебного года
    IF(EXISTS(
      SELECT FIRST 1 1
      FROM VALD V
      WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 2879 AND V.IS_DEL = 0 AND V.VAL < DATEADD(-4 MONTH TO :V$YEAR_DATE)
    ))
    THEN EXCEPTION DATA_ERROR 'Изменять можно только данные текущего учебного года';
  END

  SELECT FIRST 1 U.OBJ_ID, U.USER_TYPE, O.TYPE_ID
  FROM USERS U
  LEFT JOIN OBJECTS O ON O.OBJ_ID = U.OBJ_ID
  WHERE U.DATE_DEL IS NULL AND U.USER_ID = :I$USER_ID AND U.IS_BLOCKED = 0 AND (U.EXP_DATE IS NULL OR U.EXP_DATE >= CURRENT_DATE)
  INTO :V$PERSON_ID, :V$ROLE, :V$PERSON_TYPE;

  IF(V$ROLE IS NULL) THEN EXCEPTION DATA_ERROR 'Пользователь не идентифицирован как сотрудник';

  -- Ученик не может изменять подтвержденную запись
  IF(I$OBJ_ID IS NOT NULL AND V$PERSON_TYPE = 10) THEN
  BEGIN
    SELECT FIRST 1 V.LISTVAL_ID
    FROM VALL V
    WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID IN (3182, 3192, 3193) AND V.IS_DEL = 0
    INTO :V$APPROVED;
    IF(V$APPROVED = 2 OR V$APPROVED IS NULL) THEN EXCEPTION DATA_ERROR 'Запись отмечена как подтвержденная, вы не можете ее изменять';
  END
  -- При добавлении учеников ставим всегда отсутствие верификации
  IF(V$PERSON_TYPE = 10) THEN I$VER = 0;
  -- При добавлении учеником не даем спамить - не более 3 записей в неподтвержденном статусе
  IF(I$OBJ_ID IS NULL AND V$PERSON_TYPE = 10) THEN
  BEGIN
    IF((
      SELECT COUNT(*)
      FROM LINKS L
      JOIN VALL V ON V.OBJ_ID = L.OBJ_ID AND V.PARAM_ID IN (3182, 3192, 3193) AND V.IS_DEL = 0 AND V.LISTVAL_ID = 3
      WHERE L.PARENT_ID = :I$PERSON_ID AND L.OBJ_TYPE_ID IN (22, 24, 25) AND L.DATE_DEL IS NULL
    ) >= 3)
    THEN EXCEPTION DATA_ERROR 'Обучающийся не может добавлять более 3 записей подряд. Попросите сотрудника образовательной организации верифицировать уже внесенные данные';
  END

  -- Если PERSON_ID не указан (создание новой строки), значит берем самого себя
  IF(I$PERSON_ID IS NULL) THEN
  BEGIN
    IF(V$PERSON_TYPE IS NULL OR V$PERSON_TYPE <> 10) THEN EXCEPTION DATA_ERROR 'Записи портфолио доступны только для обучащихся';
    I$PERSON_ID = V$PERSON_ID;
  END
  ELSE
  BEGIN
    IF(NOT EXISTS(
      SELECT FIRST 1 1
      FROM LINKS L10
      WHERE L10.DATE_DEL IS NULL AND L10.OBJ_ID = :I$PERSON_ID AND L10.OBJ_TYPE_ID = 10 AND L10.PARENT_TYPE_ID IN (9, 187, 290)
    )) THEN EXCEPTION DATA_ERROR 'Персона не найдена или не является действующим обучающимся';
    -- !!! проверить права доступа к данной персоне !!!
  END

  IF(I$OBJ_ID IS NULL) THEN
    SELECT OBJ_ID FROM OBJECT_ADD(:I$PERSON_ID, :I$PART, NULL, :I$USER_ID) INTO :OBJ_ID;
  ELSE
    OBJ_ID = I$OBJ_ID;

  IF(I$DATE IS NULL) THEN EXCEPTION DATA_ERROR 'Дата мероприятия является обязательным полем';
  IF(I$DATE < DATEADD(-4 MONTH TO V$YEAR_DATE) OR I$DATE > DATEADD(12 MONTH TO V$YEAR_DATE)) THEN EXCEPTION DATA_ERROR 'Можно вносить даты только диапазоне от мая текущего учебного года до августа следующего года';

  IF(I$VER = 1 AND (I$LEVEL IS NULL OR I$SPORT IS NULL OR (I$RESULT IS NULL AND I$PART <> 25))) THEN EXCEPTION DATA_ERROR 'Для верификации требуется, чтобы были заполнены обязательные поля';

  IF(I$PART = 22) THEN
  BEGIN
    SELECT BLOB_ID FROM VAL_ADD(166, :OBJ_ID, :I$DATE) INTO :T;
    SELECT BLOB_ID FROM VAL_ADD(1819, :OBJ_ID, :I$LEVEL) INTO :T;
    SELECT BLOB_ID FROM VAL_ADD(237, :OBJ_ID, :I$RESULT) INTO :T;
    SELECT BLOB_ID FROM VAL_ADD(1818, :OBJ_ID, :I$NAME) INTO :T;
    SELECT BLOB_ID FROM VAL_ADD(1820, :OBJ_ID, :I$THEME) INTO :T;

    -- Тип надо перевести обратно в строку из ID
    SELECT C.VAL FROM LISTVAL_TEXT(:I$SPORT) C INTO :S;
    SELECT BLOB_ID FROM VAL_ADD(167, :OBJ_ID, :S) INTO :T;

    SELECT BLOB_ID FROM VAL_ADD(3182, :OBJ_ID, IIF(:I$VER = 0, 3, 2)) INTO :T;
  END
  IF(I$PART = 24) THEN
  BEGIN
    SELECT BLOB_ID FROM VAL_ADD(177, :OBJ_ID, :I$DATE) INTO :T;
    SELECT BLOB_ID FROM VAL_ADD(1826, :OBJ_ID, :I$LEVEL) INTO :T;
    SELECT BLOB_ID FROM VAL_ADD(236, :OBJ_ID, :I$RESULT) INTO :T;
    SELECT BLOB_ID FROM VAL_ADD(178, :OBJ_ID, :I$SPORT) INTO :T;
    SELECT BLOB_ID FROM VAL_ADD(3193, :OBJ_ID, IIF(:I$VER = 0, 3, 2)) INTO :T;
  END
  IF(I$PART = 25) THEN
  BEGIN
    SELECT BLOB_ID FROM VAL_ADD(1827, :OBJ_ID, :I$DATE) INTO :T;
    SELECT BLOB_ID FROM VAL_ADD(180, :OBJ_ID, :I$LEVEL) INTO :T;
    SELECT BLOB_ID FROM VAL_ADD(178, :OBJ_ID, :I$SPORT) INTO :T;
    SELECT BLOB_ID FROM VAL_ADD(1828, :OBJ_ID, :I$NAME) INTO :T;
    SELECT BLOB_ID FROM VAL_ADD(3192, :OBJ_ID, IIF(:I$VER = 0, 3, 2)) INTO :T;
  END

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PF_KPI (
    I$OBJ_ID BIGINT,
    I$BLOCK_NAME VARCHAR(40),
    I$BLOCK_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(1000))
AS
declare variable V$TYPE_ID bigint;
begin

  SELECT TYPE_ID
  FROM OBJECTS
  WHERE OBJ_ID = :I$OBJ_ID
  INTO :V$TYPE_ID;

  IF(V$TYPE_ID = 2) THEN
  BEGIN
    FOR
      SELECT D.TAG_NAME, D.VAL
      FROM PF_KPI_OU(:I$OBJ_ID, :I$BLOCK_NAME, :I$BLOCK_ID, :I$USER_ID) D
      INTO :TAG_NAME, :VAL
    DO
    BEGIN
      SUSPEND;
    END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PF_KPI_OU (
    I$OBJ_ID BIGINT,
    I$BLOCK_NAME VARCHAR(40),
    I$BLOCK_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(1000))
AS
declare variable V$YEAR_START date;
declare variable V$FIELD_ID bigint;
declare variable V$DETAILS smallint;
declare variable V$FUNC integer;
declare variable V$QT integer;
declare variable V$DATE date;
declare variable V$IS_REGMON smallint;
declare variable V$FIELD_DIR smallint;
declare variable V$LIMIT_W float;
declare variable V$LIMIT_A float;
declare variable V double precision;
declare variable S varchar(1000);
begin

  IF(EXTRACT(MONTH FROM CURRENT_DATE) < 8) THEN V$YEAR_START = '01.09.' || (EXTRACT(YEAR FROM CURRENT_DATE) - 1);
  ELSE V$YEAR_START = '01.09.' || EXTRACT(YEAR FROM CURRENT_DATE);

  SELECT MAX(R.RATE_DATE)
  FROM CJ2_STUDENT_RATING R
  WHERE R.DATE_DEL IS NULL AND R.FIELD_ID IS NOT NULL AND R.STUDENT_ID = :I$OBJ_ID AND R.RATE_DATE <= CURRENT_DATE
  INTO :V$DATE;

  IF(I$BLOCK_NAME IS NULL) THEN
  BEGIN
    -- Оглавление
    TAG_NAME = 'dashboard::json&colon;array';
    VAL = 1;
    SUSPEND;

    -- Динамические показатели
    FOR
      SELECT F.ID, IIF(Q.QUERY_DETAILS IS NULL, 0, 1), F.FIELD_TITLE, F.FUNC_ID, Q.QUERY_TYPE, F.IS_REGMON, F.FIELD_DIR, F.LIMIT_W, F.LIMIT_W
      FROM STAT_QUERIES Q
      -- FUNC_ID: 5 = вспомогательный параметр, пропускаем
      JOIN STAT_FIELDS F ON F.DATE_DEL IS NULL AND F.QUERY_ID = Q.ID AND F.FUNC_ID <> 5
      WHERE Q.DATE_DEL IS NULL
      ORDER BY 3
      INTO :V$FIELD_ID, :V$DETAILS, :S, :V$FUNC, :V$QT, :V$IS_REGMON, :V$FIELD_DIR, :V$LIMIT_W, :V$LIMIT_W
    DO
    BEGIN
      TAG_NAME = 'dashboard:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'dashboard:r:id';
      VAL = 'cv';
      SUSPEND;
      TAG_NAME = 'dashboard:r:details';
      VAL = 'none';
      SUSPEND;
      TAG_NAME = 'dashboard:r:type_id';
      VAL = '';
      SUSPEND;
      TAG_NAME = 'dashboard:r:subtype_id';
      VAL = V$FIELD_ID;
      SUSPEND;
      TAG_NAME = 'dashboard:r:icon';
      IF(V$IS_REGMON = 1) THEN VAL = 'eye'; ELSE VAL = 'cube';
      SUSPEND;
      TAG_NAME = 'dashboard:r:title';
      VAL = COALESCE(S, 'Параметр '|| V$FIELD_ID);
      SUSPEND;

      -- Для агрегатных показателей выбираем итоговое значение
      V = NULL;
      IF(V$DETAILS = 0) THEN
      BEGIN
        SELECT FIRST 1 R.RATE_VALUE
        FROM CJ2_STUDENT_RATING R
        WHERE R.DATE_DEL IS NULL AND R.FIELD_ID = :V$FIELD_ID AND R.STUDENT_ID = :I$OBJ_ID AND R.RATE_DATE = :V$DATE
        INTO :V;
      END
      ELSE
      BEGIN
        IF(V$FUNC IN (0, 1)) THEN
          SELECT SUM(R.RATE_VALUE)
          FROM CJ2_STUDENT_RATING R
          WHERE R.DATE_DEL IS NULL AND R.FIELD_ID = :V$FIELD_ID AND R.STUDENT_ID = :I$OBJ_ID AND R.RATE_DATE = :V$DATE
          INTO :V;
        ELSE IF(V$FUNC = 2) THEN
          SELECT AVG(R.RATE_VALUE)
          FROM CJ2_STUDENT_RATING R
          WHERE R.DATE_DEL IS NULL AND R.FIELD_ID = :V$FIELD_ID AND R.STUDENT_ID = :I$OBJ_ID AND R.RATE_DATE = :V$DATE
          INTO :V;
      END

      TAG_NAME = 'dashboard:r:color';
      IF(V$FIELD_DIR IS NOT NULL AND (V$LIMIT_A IS NOT NULL OR V$LIMIT_W IS NOT NULL)) THEN
      BEGIN
        IF(V$FIELD_DIR = 0) THEN
        BEGIN
          -- Больше = лучше
          IF(V < V$LIMIT_A) THEN VAL = '#DF2029';
          ELSE IF(V < V$LIMIT_W) THEN VAL = '#FFEA00';
          ELSE VAL = '#25D366';
        END
        ELSE
        BEGIN
          -- Меньше = лучше
          IF(V > V$LIMIT_A) THEN VAL = '#DF2029';
          ELSE IF(V > V$LIMIT_W) THEN VAL = '#FFEA00';
          ELSE VAL = '#25D366';
        END
      END
      ELSE
      BEGIN
        VAL = '#34465D';
      END
      SUSPEND;

      TAG_NAME = 'dashboard:r:value';
      IF(V$FUNC IN (0, 1)) THEN
        -- COUNT или SUM
        VAL = CAST(V AS INTEGER);
      ELSE
        -- AVG, MIN, MAX
        VAL = CAST(V AS NUMERIC(18, 2));
      SUSPEND;
    END

    -- Жестко прописанные показатели, идут с заданным SUBJECT_ID и FIELD_ID = NULL
    -- пока они не могут входить в контролиремые
    V$FIELD_ID = 0;
    WHILE(V$FIELD_ID <= 12) DO
    BEGIN
      TAG_NAME = 'dashboard:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'dashboard:r:id';
      VAL = 'cv';
      SUSPEND;
      TAG_NAME = 'dashboard:r:details';
      VAL = 'none';
      SUSPEND;
      TAG_NAME = 'dashboard:r:type_id';
      VAL = '';
      SUSPEND;
      TAG_NAME = 'dashboard:r:subtype_id';
      VAL = -100 - V$FIELD_ID;
      SUSPEND;
      TAG_NAME = 'dashboard:r:icon';
      --IF(V$IS_REGMON = 1) THEN VAL = 'eye'; ELSE VAL = 'cube';
      VAL = 'key';
      SUSPEND;
      TAG_NAME = 'dashboard:r:title';
      IF(V$FIELD_ID = 0) THEN VAL = 'Количество учебных коллективов';
      ELSE IF(V$FIELD_ID = 1) THEN VAL = 'Средняя отметка';
      ELSE IF(V$FIELD_ID = 2) THEN VAL = 'Качество знаний';
      ELSE IF(V$FIELD_ID = 3) THEN VAL = 'Обученность';
      ELSE IF(V$FIELD_ID = 4) THEN VAL = 'Системная неуспеваемость';
      ELSE IF(V$FIELD_ID = 5) THEN VAL = 'Академическая успеваемость';
      ELSE IF(V$FIELD_ID = 6) THEN VAL = 'Количество учеников 5 классов';
      ELSE IF(V$FIELD_ID = 7) THEN VAL = 'Адаптировавшиеся ученики 5 классов';
      ELSE IF(V$FIELD_ID = 8) THEN VAL = 'StudentsForObjectivity';
      ELSE IF(V$FIELD_ID = 9) THEN VAL = 'StudentsWithObjectiveMarks';
      ELSE IF(V$FIELD_ID = 10) THEN VAL = 'Students2to12parallel';
      ELSE IF(V$FIELD_ID = 11) THEN VAL = 'StudentsMarksAccumulation';
      ELSE IF(V$FIELD_ID = 12) THEN VAL = 'Своевременность выдачи ДЗ';
      SUSPEND;

      V = NULL;
      SELECT FIRST 1 R.RATE_VALUE
      FROM CJ2_STUDENT_RATING R
      WHERE R.DATE_DEL IS NULL AND R.SUBJECT_ID = :V$FIELD_ID AND R.STUDENT_ID = :I$OBJ_ID AND R.FIELD_ID IS NULL AND R.RATE_DATE = :V$DATE
      INTO :V;

      TAG_NAME = 'dashboard:r:color';
      VAL = '#34465D';
      SUSPEND;

      TAG_NAME = 'dashboard:r:value';
      IF(V$FIELD_ID IN (1, 2, 3, 4, 5, 12)) THEN
        VAL = CAST(V AS NUMERIC(18, 2));
      ELSE
        VAL = CAST(V AS INTEGER);
      SUSPEND;

      V$FIELD_ID = V$FIELD_ID + 1;
    END
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PF_PERSONS_LIST (
    I$ZONE INTEGER,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$PERSON_ID BIGINT;
DECLARE VARIABLE V$PERSON_TYPE BIGINT;
DECLARE VARIABLE V$GRADE_ID BIGINT;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$ROLE SMALLINT;
DECLARE VARIABLE V$RATE_DATE DATE;
DECLARE VARIABLE V$RV FLOAT;
DECLARE VARIABLE V$RI INTEGER;
DECLARE VARIABLE S VARCHAR(1000);
begin

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  SELECT FIRST 1 U.OBJ_ID, O.TYPE_ID, U.USER_TYPE
  FROM USERS U
  JOIN OBJECTS O ON O.OBJ_ID = U.OBJ_ID
  WHERE U.DATE_DEL IS NULL AND U.USER_ID = :I$USER_ID AND U.IS_BLOCKED = 0 AND (U.EXP_DATE IS NULL OR U.EXP_DATE >= CURRENT_DATE)
  INTO :V$PERSON_ID, :V$PERSON_TYPE, V$ROLE;

  IF(V$PERSON_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Пользователь не идентифицирован как сотрудник или ученик';

  TAG_NAME = 'type_id';
  VAL = V$PERSON_TYPE;
  SUSPEND;

  TAG_NAME = 'role';
  VAL = V$ROLE;
  SUSPEND;

  -- Для обучающихся выдаем текущий уровень обучения (нужен для кабинета СПО)
  TAG_NAME = 'edu_level';
  VAL = NULL;
  IF(V$PERSON_TYPE = 10) THEN
  SELECT FIRST 1 M.LEVEL_ID
  FROM PERSON_MOVEMENTS M
  WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :V$PERSON_ID AND M.GROUP_TYPE_ID IN (9, 187, 289)
  ORDER BY M.DATE_IN DESC
  INTO :VAL;
  SUSPEND;

  IF(V$PERSON_TYPE = 14) THEN
  BEGIN

    -- На какую дату у нас есть рейтинги ?
    SELECT MAX(R.RATE_DATE)
    FROM CJ2_STUDENT_RATING R
    WHERE R.DATE_DEL IS NULL AND R.RATE_DATE <= CURRENT_DATE AND R.FIELD_ID IS NULL AND R.SUBJECT_ID IS NULL
    INTO :V$RATE_DATE;

    TAG_NAME = 'groups::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT L9.OBJ_ID, C.CAPTION
      FROM LINKS L9
      JOIN VALL V49 ON V49.OBJ_ID = L9.PARENT_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
      JOIN LISTVALS LV ON LV.LISTVAL_ID = V49.LISTVAL_ID
      LEFT JOIN VALR V53 ON V53.OBJ_ID = L9.OBJ_ID AND V53.PARAM_ID = 53 AND V53.IS_DEL = 0
      LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C ON 1 = 1
      WHERE L9.PARENT_TYPE_ID = 8 AND L9.OBJ_TYPE_ID IN (9, 187) AND L9.DATE_DEL IS NULL AND (V53.VAL = :V$PERSON_ID OR :V$ROLE IN (1, 5, 6, 7, 16, 20))
      ORDER BY LV.COST, 2
      INTO :V$GRADE_ID, :S
    DO
    BEGIN
      TAG_NAME = 'groups:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'groups:r:id';
      VAL = V$GRADE_ID;
      SUSPEND;
      TAG_NAME = 'groups:r:name';
      VAL = S;
      SUSPEND;

      TAG_NAME = 'groups:r:members::json&colon;array';
      VAL = 1;
      SUSPEND;
      FOR
        SELECT L10.OBJ_ID, C.CAPTION, R.RATE_VALUE, R.RATE_INDEX
        FROM LINKS L10
        LEFT JOIN OBJECT_CAPTION_GET(L10.OBJ_ID, 23) C ON 1 = 1
        LEFT JOIN CJ2_STUDENT_RATING R ON R.DATE_DEL IS NULL AND R.STUDENT_ID = L10.OBJ_ID AND R.FIELD_ID IS NULL AND R.SUBJECT_ID IS NULL AND R.RATE_DATE = :V$RATE_DATE
        WHERE L10.PARENT_ID = :V$GRADE_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        ORDER BY 2
        INTO :V$OBJ_ID, :S, :V$RV, :V$RI
      DO
      BEGIN
        TAG_NAME = 'groups:r:members:r';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'groups:r:members:r:id';
        VAL = V$OBJ_ID;
        SUSPEND;
        TAG_NAME = 'groups:r:members:r:name';
        VAL = S;
        SUSPEND;
        TAG_NAME = 'groups:r:members:r:rv';
        VAL = CAST(V$RV AS NUMERIC(18, 2));
        SUSPEND;
        TAG_NAME = 'groups:r:members:r:ri';
        VAL = V$RI;
        SUSPEND;
      END
    END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PF_PORTFOLIO (
    I$OBJ_ID BIGINT,
    I$BLOCK_NAME VARCHAR(40),
    I$BLOCK_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(1000))
AS
declare variable V$TYPE_ID bigint;
begin

  SELECT TYPE_ID
  FROM OBJECTS
  WHERE OBJ_ID = :I$OBJ_ID
  INTO :V$TYPE_ID;

  IF(V$TYPE_ID = 2) THEN
  BEGIN
    FOR
      SELECT D.TAG_NAME, D.VAL
      FROM PF_PORTFOLIO_OU(:I$OBJ_ID, :I$BLOCK_NAME, :I$BLOCK_ID, :I$USER_ID) D
      INTO :TAG_NAME, :VAL
    DO
    BEGIN
      SUSPEND;
    END
  END
  ELSE IF(V$TYPE_ID = 111) THEN
  BEGIN
    FOR
      SELECT D.TAG_NAME, D.VAL
      FROM PF_PORTFOLIO_DIST(:I$OBJ_ID, :I$BLOCK_NAME, :I$BLOCK_ID, :I$USER_ID) D
      INTO :TAG_NAME, :VAL
    DO
    BEGIN
      SUSPEND;
    END
  END
  ELSE IF(V$TYPE_ID = 112) THEN
  BEGIN
    FOR
      SELECT D.TAG_NAME, D.VAL
      FROM PF_PORTFOLIO_RGN(:I$OBJ_ID, :I$BLOCK_NAME, :I$BLOCK_ID, :I$USER_ID) D
      INTO :TAG_NAME, :VAL
    DO
    BEGIN
      SUSPEND;
    END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PF_PORTFOLIO_DIST (
    I$OBJ_ID BIGINT,
    I$BLOCK_NAME VARCHAR(40),
    I$BLOCK_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(1000))
AS
declare variable V$VAL bigint;
declare variable V$VAL2 bigint;
declare variable S varchar(1000);
declare variable V$TYPE_ID1 bigint;
declare variable V$TYPE_ID2 bigint;
declare variable V$MID_TYPE bigint;
declare variable V$OBJ_ID bigint;
declare variable V$PARAM_ID bigint;
declare variable V$TYPE bigint;
declare variable V$T bigint;
declare variable V$MASTER_ID bigint;
begin

  IF(I$BLOCK_NAME IS NULL) THEN
  BEGIN
    -- Оглавление
    TAG_NAME = 'dashboard::json&colon;array';
    VAL = 1;
    SUSPEND;

    -- Инновационные площадки
    SELECT COUNT(*)
    FROM LINKS L2
    JOIN LINKS L463 ON L463.PARENT_ID = L2.OBJ_ID AND L463.OBJ_TYPE_ID = 463 AND L463.DATE_DEL IS NULL
    JOIN VALL V3313 ON V3313.OBJ_ID = L463.OBJ_ID AND V3313.PARAM_ID = 3313 AND V3313.IS_DEL = 0 AND V3313.LISTVAL_ID = 14142
    LEFT JOIN VALD V3315 ON V3315.OBJ_ID = L463.OBJ_ID AND V3315.PARAM_ID = 3315 AND V3315.IS_DEL = 0
    WHERE L2.PARENT_ID = :I$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND V3315.VAL IS NULL
    INTO :V$VAL;
    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'innoplace';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '463';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'chess queen';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#25D366';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Инновационная площадка регионального уровня';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

    SELECT COUNT(*)
    FROM LINKS L2
    JOIN LINKS L463 ON L463.PARENT_ID = L2.OBJ_ID AND L463.OBJ_TYPE_ID = 463 AND L463.DATE_DEL IS NULL
    JOIN VALL V3313 ON V3313.OBJ_ID = L463.OBJ_ID AND V3313.PARAM_ID = 3313 AND V3313.IS_DEL = 0 AND V3313.LISTVAL_ID = 14143
    LEFT JOIN VALD V3315 ON V3315.OBJ_ID = L463.OBJ_ID AND V3315.PARAM_ID = 3315 AND V3315.IS_DEL = 0
    WHERE L2.PARENT_ID = :I$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND V3315.VAL IS NULL
    INTO :V$VAL;
    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'innoplace';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '463';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'chess queen';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#FF5700';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Инновационная площадка федерального уровня';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

    SELECT COUNT(*)
    FROM LINKS L2
    JOIN LINKS L464 ON L464.PARENT_ID = L2.OBJ_ID AND L464.OBJ_TYPE_ID = 464 AND L464.DATE_DEL IS NULL
    JOIN VALL V3318 ON V3318.OBJ_ID = L464.OBJ_ID AND V3318.PARAM_ID = 3318 AND V3318.IS_DEL = 0 AND V3318.LISTVAL_ID = 757
    JOIN VALI V3316 ON V3316.OBJ_ID = L464.OBJ_ID AND V3316.PARAM_ID = 3316 AND V3316.IS_DEL = 0 AND V3316.VAL >= EXTRACT(YEAR FROM CURRENT_DATE) - 3
    WHERE L2.PARENT_ID = :I$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'contest';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '464';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'thumbs up';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#25D366';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Лауреатов конкурсов ОУ';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

    SELECT COUNT(*)
    FROM LINKS L2
    JOIN LINKS L464 ON L464.PARENT_ID = L2.OBJ_ID AND L464.OBJ_TYPE_ID = 464 AND L464.DATE_DEL IS NULL
    JOIN VALL V3318 ON V3318.OBJ_ID = L464.OBJ_ID AND V3318.PARAM_ID = 3318 AND V3318.IS_DEL = 0 AND V3318.LISTVAL_ID = 756
    JOIN VALI V3316 ON V3316.OBJ_ID = L464.OBJ_ID AND V3316.PARAM_ID = 3316 AND V3316.IS_DEL = 0 AND V3316.VAL >= EXTRACT(YEAR FROM CURRENT_DATE) - 3
    WHERE L2.PARENT_ID = :I$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'contest';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '464';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'thumbs up';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#FF5700';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Победителей конкурсов ОУ';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

    SELECT COUNT(*)
    FROM LINKS L2
    JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
    JOIN LINKS L39 ON L39.PARENT_ID = L14.OBJ_ID AND L39.OBJ_TYPE_ID IN (39, 40) AND L39.DATE_DEL IS NULL
    WHERE L2.PARENT_ID = :I$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'reward';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '39,40';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'trophy';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#1877F2';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Награды сотрудников';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

    -- Достижения сотрудников
    SELECT COUNT(*)
    FROM LINKS L2
    JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
    JOIN LINKS L41 ON L41.PARENT_ID = L14.OBJ_ID AND L41.OBJ_TYPE_ID IN (41, 42) AND L41.DATE_DEL IS NULL
    WHERE L2.PARENT_ID = :I$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'acv';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '41,42';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'star';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#34465D';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Достижения сотрудников';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

  END
  ELSE
  BEGIN

    TAG_NAME = 'title';
    IF(I$BLOCK_NAME = 'innoplace') THEN VAL = 'Инновационная площадки';
    ELSE IF(I$BLOCK_NAME = 'contest') THEN VAL = 'Участники конкурса ОУ';
    ELSE IF(I$BLOCK_NAME = 'reward') THEN VAL = 'Награды сотрудников';
    ELSE IF(I$BLOCK_NAME = 'acv') THEN VAL = 'Достижения сотрудников';
    SUSPEND;

    TAG_NAME = 'has_caption';
    VAL = 1;
    SUSPEND;

    TAG_NAME = 'columns::json&colon;array';
    VAL = 1;
    SUSPEND;
    -- Первый параметр всегда есть
    TAG_NAME = 'columns:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'columns:r:type_id';
    VAL = '1';
    SUSPEND;
    TAG_NAME = 'columns:r:param_id';
    VAL = '0';
    SUSPEND;
    TAG_NAME = 'columns:r:type';
    VAL = '0';
    SUSPEND;
    TAG_NAME = 'columns:r:name';
    SUSPEND;
    IF(I$BLOCK_NAME = 'innoplace') THEN VAL = 'Инновационная площадка регионального уровня';
    ELSE IF(I$BLOCK_NAME = 'contest') THEN VAL = 'Лауреатов конкурса ОУ';
    ELSE IF(I$BLOCK_NAME = 'reward') THEN VAL = 'Наград сотрудников';
    ELSE IF(I$BLOCK_NAME = 'acv') THEN VAL = 'Достижений сотрудников';
    SUSPEND;

    -- Второй парметр частично
    IF(I$BLOCK_NAME = 'innoplace' OR I$BLOCK_NAME = 'contest') THEN
    BEGIN
    TAG_NAME = 'columns:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'columns:r:type_id';
    VAL = '1';
    SUSPEND;
    TAG_NAME = 'columns:r:param_id';
    VAL = '1';
    SUSPEND;
    TAG_NAME = 'columns:r:type';
    VAL = '0';
    SUSPEND;
    TAG_NAME = 'columns:r:name';
    SUSPEND;
    IF(I$BLOCK_NAME = 'innoplace') THEN VAL = 'Инновационная площадка федерального уровня';
    ELSE IF(I$BLOCK_NAME = 'contest') THEN VAL = 'Победителей конкурса ОУ';
    SUSPEND;
    END

    -- Развертка по ОУ
    TAG_NAME = 'rows::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT L2.OBJ_ID, L2.OBJ_TYPE_ID, C.CAPTION
      FROM LINKS L2
      LEFT JOIN OBJECT_CAPTION_GET(L2.OBJ_ID) C ON 1 = 1
      WHERE L2.PARENT_ID = :I$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      ORDER BY 3
      INTO :V$OBJ_ID, :V$TYPE, :S
    DO
    BEGIN
      TAG_NAME = 'rows:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'rows:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'rows:r:type_id';
      VAL = '1';
      SUSPEND;
      TAG_NAME = 'rows:r:caption';
      VAL = S;
      SUSPEND;

      IF(I$BLOCK_NAME = 'innoplace') THEN 
      BEGIN
        SELECT SUM(IIF(V3313.LISTVAL_ID = 14142, 1, 0)), SUM(IIF(V3313.LISTVAL_ID = 14143, 1, 0))
        FROM LINKS L463
        JOIN VALL V3313 ON V3313.OBJ_ID = L463.OBJ_ID AND V3313.PARAM_ID = 3313 AND V3313.IS_DEL = 0 AND V3313.LISTVAL_ID = 14142
        LEFT JOIN VALD V3315 ON V3315.OBJ_ID = L463.OBJ_ID AND V3315.PARAM_ID = 3315 AND V3315.IS_DEL = 0
        WHERE L463.PARENT_ID = :V$OBJ_ID AND L463.OBJ_TYPE_ID = 463 AND L463.DATE_DEL IS NULL
        INTO :V$VAL, :V$VAL2;
      END
      ELSE IF(I$BLOCK_NAME = 'contest') THEN
      BEGIN
        SELECT SUM(IIF(V3318.LISTVAL_ID = 757, 1, 0)), SUM(IIF(V3318.LISTVAL_ID = 756, 1, 0))
        FROM LINKS L464
        JOIN VALL V3318 ON V3318.OBJ_ID = L464.OBJ_ID AND V3318.PARAM_ID = 3318 AND V3318.IS_DEL = 0
        JOIN VALI V3316 ON V3316.OBJ_ID = L464.OBJ_ID AND V3316.PARAM_ID = 3316 AND V3316.IS_DEL = 0 AND V3316.VAL >= EXTRACT(YEAR FROM CURRENT_DATE) - 3
        WHERE L464.PARENT_ID = :V$OBJ_ID AND L464.OBJ_TYPE_ID = 464 AND L464.DATE_DEL IS NULL
        INTO :V$VAL, :V$VAL2;
      END
      ELSE IF(I$BLOCK_NAME = 'reward') THEN
      BEGIN
        SELECT COUNT(*)
        FROM LINKS L14
        JOIN LINKS L39 ON L39.PARENT_ID = L14.OBJ_ID AND L39.OBJ_TYPE_ID IN (39, 40) AND L39.DATE_DEL IS NULL
        WHERE L14.PARENT_ID = :V$OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
        INTO :V$VAL;
      END
      ELSE IF(I$BLOCK_NAME = 'acv') THEN
      BEGIN
        SELECT COUNT(*)
        FROM LINKS L14
        JOIN LINKS L41 ON L41.PARENT_ID = L14.OBJ_ID AND L41.OBJ_TYPE_ID IN (41, 42) AND L41.DATE_DEL IS NULL
        WHERE L14.PARENT_ID = :V$OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
        INTO :V$VAL;
      END

      TAG_NAME = 'rows:r:p0';
      VAL = V$VAL;
      SUSPEND;
      TAG_NAME = 'rows:r:p1';
      VAL = V$VAL2;
      SUSPEND;
    END

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PF_PORTFOLIO_OU (
    I$OBJ_ID BIGINT,
    I$BLOCK_NAME VARCHAR(40),
    I$BLOCK_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$VAL BIGINT;
DECLARE VARIABLE S VARCHAR(1000);
DECLARE VARIABLE V$TYPE_ID1 BIGINT;
DECLARE VARIABLE V$TYPE_ID2 BIGINT;
DECLARE VARIABLE V$MID_TYPE BIGINT;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$PARAM_ID BIGINT;
DECLARE VARIABLE V$TYPE BIGINT;
DECLARE VARIABLE V$T BIGINT;
DECLARE VARIABLE V$MASTER_ID BIGINT;
DECLARE VARIABLE V$OK SMALLINT;
begin

  IF(I$BLOCK_NAME IS NULL) THEN
  BEGIN
    -- Оглавление
    TAG_NAME = 'dashboard::json&colon;array';
    VAL = 1;
    SUSPEND;

    -- Общие сведения об организации
    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'general';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = '';
    SUSPEND;
    TAG_NAME = 'dashboard:r:details';
    VAL = 'none';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#FAFAFA';
    SUSPEND;

    TAG_NAME = 'dashboard:r:title::json&colon;array';
    VAL = 1;
    SUSPEND;
    -- Краткое наименование
    TAG_NAME = 'dashboard:r:title:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:title:r:title';
    VAL = 'Краткое наименование организации';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title:r:value';
    VAL = NULL;
    SELECT V.VAL
    FROM VALS V
    WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 2 AND V.IS_DEL = 0
    INTO :VAL;
    SUSPEND;
    -- Полное наименование
    TAG_NAME = 'dashboard:r:title:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:title:r:title';
    VAL = 'Полное наименование организации';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title:r:value';
    VAL = NULL;
    SELECT V.VAL
    FROM VALS V
    WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 5 AND V.IS_DEL = 0
    INTO :VAL;
    SUSPEND;
    -- Адрес сайта
    TAG_NAME = 'dashboard:r:title:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:title:r:title';
    VAL = 'Адрес сайта';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title:r:value';
    VAL = NULL;
    SELECT V.VAL
    FROM VALS V
    WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 36 AND V.IS_DEL = 0
    INTO :VAL;
    SUSPEND;
    -- Учредители - собираем сводную строку
    TAG_NAME = 'dashboard:r:title:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:title:r:title';
    VAL = 'Учредители';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title:r:value';
    VAL = '';
    FOR
      SELECT V.VAL
      FROM LINKS L5
      JOIN VALS V ON V.OBJ_ID = L5.OBJ_ID AND V.PARAM_ID = 24 AND V.IS_DEL = 0
      WHERE L5.PARENT_ID = :I$OBJ_ID AND L5.OBJ_TYPE_ID = 5 AND L5.DATE_DEL IS NULL
      INTO :S
    DO
    BEGIN
      IF(VAL <> '') THEN VAL = VAL || '; ';
      VAL = VAL || S;
    END
    SUSPEND;
    -- Лицензия
    TAG_NAME = 'dashboard:r:title:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:title:r:title';
    VAL = 'Сведения о лицензии';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title:r:value';
    VAL = '';
    FOR
      SELECT V596.VAL || COALESCE(' ' || V478.VAL, '') || COALESCE(' №' || V479.VAL, '') || COALESCE(' от ' || VD.RESULT, '')
      FROM LINKS L17
      JOIN VALL V471 ON V471.OBJ_ID = L17.OBJ_ID AND V471.PARAM_ID = 471 AND V471.IS_DEL = 0 AND V471.LISTVAL_ID IN (1052, 18624)
      JOIN VALL V613 ON V613.OBJ_ID = L17.OBJ_ID AND V613.PARAM_ID = 613 AND V613.IS_DEL = 0 AND V613.LISTVAL_ID = 1982
      LEFT JOIN VALD V483 ON V483.OBJ_ID = L17.OBJ_ID AND V483.PARAM_ID = 483 AND V483.IS_DEL = 0
      -- Название, серия, номер, дата
      LEFT JOIN VALS V596 ON V596.OBJ_ID = L17.OBJ_ID AND V596.PARAM_ID = 596 AND V596.IS_DEL = 0
      LEFT JOIN VALS V478 ON V478.OBJ_ID = L17.OBJ_ID AND V478.PARAM_ID = 478 AND V478.IS_DEL = 0
      LEFT JOIN VALS V479 ON V479.OBJ_ID = L17.OBJ_ID AND V479.PARAM_ID = 479 AND V479.IS_DEL = 0
      LEFT JOIN VALD V482 ON V482.OBJ_ID = L17.OBJ_ID AND V482.PARAM_ID = 482 AND V482.IS_DEL = 0
      LEFT JOIN DATE2STR(V482.VAL) VD ON 1 = 1
      WHERE L17.PARENT_ID = :I$OBJ_ID AND L17.OBJ_TYPE_ID = 17 AND L17.DATE_DEL IS NULL AND (V483.VAL IS NULL OR V483.VAL > CURRENT_DATE)
      INTO :S
    DO
    BEGIN
      IF(VAL <> '') THEN VAL = VAL || '; ';
      VAL = VAL || S;
    END
    SUSPEND;
    -- Аккредитация
    TAG_NAME = 'dashboard:r:title:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:title:r:title';
    VAL = 'Сведения о государственной акредитации';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title:r:value';
    VAL = '';
    FOR
      SELECT V596.VAL || COALESCE(' ' || V478.VAL, '') || COALESCE(' №' || V479.VAL, '') || COALESCE(' от ' || VD.RESULT, '')
      FROM LINKS L17
      JOIN VALL V471 ON V471.OBJ_ID = L17.OBJ_ID AND V471.PARAM_ID = 471 AND V471.IS_DEL = 0 AND V471.LISTVAL_ID IN (1053, 18625)
      JOIN VALL V613 ON V613.OBJ_ID = L17.OBJ_ID AND V613.PARAM_ID = 613 AND V613.IS_DEL = 0 AND V613.LISTVAL_ID = 1982
      LEFT JOIN VALD V483 ON V483.OBJ_ID = L17.OBJ_ID AND V483.PARAM_ID = 483 AND V483.IS_DEL = 0
      -- Название, серия, номер, дата
      LEFT JOIN VALS V596 ON V596.OBJ_ID = L17.OBJ_ID AND V596.PARAM_ID = 596 AND V596.IS_DEL = 0
      LEFT JOIN VALS V478 ON V478.OBJ_ID = L17.OBJ_ID AND V478.PARAM_ID = 478 AND V478.IS_DEL = 0
      LEFT JOIN VALS V479 ON V479.OBJ_ID = L17.OBJ_ID AND V479.PARAM_ID = 479 AND V479.IS_DEL = 0
      LEFT JOIN VALD V482 ON V482.OBJ_ID = L17.OBJ_ID AND V482.PARAM_ID = 482 AND V482.IS_DEL = 0
      LEFT JOIN DATE2STR(V482.VAL) VD ON 1 = 1
      WHERE L17.PARENT_ID = :I$OBJ_ID AND L17.OBJ_TYPE_ID = 17 AND L17.DATE_DEL IS NULL AND (V483.VAL IS NULL OR V483.VAL > CURRENT_DATE)
      INTO :S
    DO
    BEGIN
      IF(VAL <> '') THEN VAL = VAL || '; ';
      VAL = VAL || S;
    END
    SUSPEND;
    -- Данные по госзаданию за текущий календарный год
    V$T = EXTRACT(YEAR FROM CURRENT_DATE);
    FOR
      SELECT V3220.VAL
      FROM LINKS L432
      JOIN LINKS L441 ON L441.PARENT_ID = L432.OBJ_ID AND L441.OBJ_TYPE_ID = 441 AND L441.DATE_DEL IS NULL
      JOIN VALI V3211 ON V3211.OBJ_ID = L441.OBJ_ID AND V3211.PARAM_ID = 3211 AND V3211.IS_DEL = 0 AND V3211.VAL = :V$T
      JOIN VALL V3274 ON V3274.OBJ_ID = L441.OBJ_ID AND V3274.PARAM_ID = 3274 AND V3274.IS_DEL = 0 AND V3274.LISTVAL_ID = 2
      JOIN LINKS L442 ON L442.PARENT_ID = L441.OBJ_ID AND L442.OBJ_TYPE_ID = 442 AND L442.DATE_DEL IS NULL
      JOIN VALI V3218 ON V3218.OBJ_ID = L442.OBJ_ID AND V3218.PARAM_ID = 3218 AND V3218.IS_DEL = 0
      JOIN VALS V3220 ON V3220.OBJ_ID = L442.OBJ_ID AND V3220.PARAM_ID = 3220 AND V3220.IS_DEL = 0
      WHERE L432.PARENT_ID = :I$OBJ_ID AND L432.OBJ_TYPE_ID = 432 AND L432.DATE_DEL IS NULL
      ORDER BY V3218.VAL
      INTO :S
    DO
    BEGIN
      TAG_NAME = 'dashboard:r:title:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'dashboard:r:title:r:title';
      VAL = 'Работа/услуга ГЗ';
      SUSPEND;
      TAG_NAME = 'dashboard:r:title:r:value';
      VAL = S;
      SUSPEND;
    END

    -- Статус инновационной площадки, если есть
    V$VAL = NULL;
    SELECT FIRST 1 V3313.LISTVAL_ID
    FROM LINKS L463
    JOIN VALL V3313 ON V3313.OBJ_ID = L463.OBJ_ID AND V3313.PARAM_ID = 3313 AND V3313.IS_DEL = 0
    LEFT JOIN VALD V3315 ON V3315.OBJ_ID = L463.OBJ_ID AND V3315.PARAM_ID = 3315 AND V3315.IS_DEL = 0
    WHERE L463.PARENT_ID = :I$OBJ_ID AND L463.OBJ_TYPE_ID = 463 AND L463.DATE_DEL IS NULL AND V3315.VAL IS NULL
    INTO :V$VAL;
    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'innoplace';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '463';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'chess queen';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    IF(V$VAL IS NULL) THEN VAL = '#4C75A3'; ELSE IF(V$VAL = 14142) THEN VAL = '#25D366'; ELSE VAL = '#FF5700';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    IF(V$VAL IS NULL) THEN VAL = 'Нет статуса инновационной площадки';
    ELSE IF(V$VAL = 14142) THEN VAL = 'Инновационная площадка регионального уровня';
    ELSE VAL = 'Инновационная площадка федерального уровня';
    SUSPEND;

    -- Участие в региональных конкурсах не старше 3 лет
    V$VAL = NULL;
    S = NULL;
    SELECT FIRST 1 V3318.LISTVAL_ID, V3317.VAL || ' (' || V3316.VAL || ') ' || C.VAL
    FROM LINKS L464
    JOIN VALL V3318 ON V3318.OBJ_ID = L464.OBJ_ID AND V3318.PARAM_ID = 3318 AND V3318.IS_DEL = 0
    JOIN VALI V3316 ON V3316.OBJ_ID = L464.OBJ_ID AND V3316.PARAM_ID = 3316 AND V3316.IS_DEL = 0 AND V3316.VAL >= EXTRACT(YEAR FROM CURRENT_DATE) - 3
    JOIN VALS V3317 ON V3317.OBJ_ID = L464.OBJ_ID AND V3317.PARAM_ID = 3317 AND V3317.IS_DEL = 0
    LEFT JOIN LISTVAL_TEXT(V3318.LISTVAL_ID) C ON 1 = 1
    WHERE L464.PARENT_ID = :I$OBJ_ID AND L464.OBJ_TYPE_ID = 464 AND L464.DATE_DEL IS NULL
    ORDER BY V3316.VAL DESC
    INTO :V$VAL, :S;
    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'contest';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '464';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'thumbs up';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    IF(V$VAL IS NULL) THEN VAL = '#4C75A3'; ELSE IF(V$VAL = 757) THEN VAL = '#25D366'; ELSE VAL = '#FF5700';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    IF(V$VAL IS NULL) THEN VAL = 'Нет данных по участию в конкурсе организаций'; ELSE VAL = S;
    SUSPEND;

    -- Награды сотрудников
    SELECT COUNT(*)
    FROM LINKS L14
    JOIN LINKS L39 ON L39.PARENT_ID = L14.OBJ_ID AND L39.OBJ_TYPE_ID IN (39, 40) AND L39.DATE_DEL IS NULL
    WHERE L14.PARENT_ID = :I$OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
    INTO :V$VAL;
    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'reward';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '39,40';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'trophy';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#1877F2';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Награды сотрудников';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

    -- Награды учителей
    SELECT COUNT(DISTINCT L39.OBJ_ID)
    FROM LINKS L14
    JOIN LINKS L39 ON L39.PARENT_ID = L14.OBJ_ID AND L39.OBJ_TYPE_ID IN (39, 40) AND L39.DATE_DEL IS NULL
    JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L14.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
    JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
    JOIN VALL V64 ON V64.OBJ_ID = LP13.PARENT_ID AND V64.PARAM_ID = 64 AND V64.IS_DEL = 0 AND V64.LISTVAL_ID = 98
    WHERE L14.PARENT_ID = :I$OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL AND V74.VAL IS NULL
    INTO :V$VAL;
    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'reward';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '39,40';
    SUSPEND;
    TAG_NAME = 'dashboard:r:subtype_id';
    VAL = '1';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'trophy';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#1877F2';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Награды учителей';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

    -- Награды руководителей
    SELECT COUNT(DISTINCT L39.OBJ_ID)
    FROM LINKS L14
    JOIN LINKS L39 ON L39.PARENT_ID = L14.OBJ_ID AND L39.OBJ_TYPE_ID IN (39, 40) AND L39.DATE_DEL IS NULL
    JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L14.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
    JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
    JOIN VALL V64 ON V64.OBJ_ID = LP13.PARENT_ID AND V64.PARAM_ID = 64 AND V64.IS_DEL = 0 AND V64.LISTVAL_ID = 56
    WHERE L14.PARENT_ID = :I$OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL AND V74.VAL IS NULL
    INTO :V$VAL;
    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'reward';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '39,40';
    SUSPEND;
    TAG_NAME = 'dashboard:r:subtype_id';
    VAL = '2';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'trophy';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#1877F2';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Награды руководителей';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

    -- Достижения сотрудников
    SELECT COUNT(*)
    FROM LINKS L14
    JOIN LINKS L41 ON L41.PARENT_ID = L14.OBJ_ID AND L41.OBJ_TYPE_ID IN (41, 42) AND L41.DATE_DEL IS NULL
    WHERE L14.PARENT_ID = :I$OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
    INTO :V$VAL;
    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'acv';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '41,42';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'star';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#34465D';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Достижения сотрудников';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

    -- Достижения учителей
    SELECT COUNT(DISTINCT L41.OBJ_ID)
    FROM LINKS L14
    JOIN LINKS L41 ON L41.PARENT_ID = L14.OBJ_ID AND L41.OBJ_TYPE_ID IN (41, 42) AND L41.DATE_DEL IS NULL
    JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L14.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
    JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
    JOIN VALL V64 ON V64.OBJ_ID = LP13.PARENT_ID AND V64.PARAM_ID = 64 AND V64.IS_DEL = 0 AND V64.LISTVAL_ID = 98
    WHERE L14.PARENT_ID = :I$OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL AND V74.VAL IS NULL
    INTO :V$VAL;
    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'acv';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '41,42';
    SUSPEND;
    TAG_NAME = 'dashboard:r:subtype_id';
    VAL = '1';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'star';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#34465D';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Достижения учителей';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

    -- Достижения руководителей
    SELECT COUNT(DISTINCT L41.OBJ_ID)
    FROM LINKS L14
    JOIN LINKS L41 ON L41.PARENT_ID = L14.OBJ_ID AND L41.OBJ_TYPE_ID IN (41, 42) AND L41.DATE_DEL IS NULL
    JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L14.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
    JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
    JOIN VALL V64 ON V64.OBJ_ID = LP13.PARENT_ID AND V64.PARAM_ID = 64 AND V64.IS_DEL = 0 AND V64.LISTVAL_ID = 56
    WHERE L14.PARENT_ID = :I$OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL AND V74.VAL IS NULL
    INTO :V$VAL;
    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'acv';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '41,42';
    SUSPEND;
    TAG_NAME = 'dashboard:r:subtype_id';
    VAL = '2';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'star';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#34465D';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Достижения руководителей';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;
  END
  ELSE
  BEGIN

    TAG_NAME = 'title';
    IF(I$BLOCK_NAME = 'innoplace') THEN
    BEGIN
      VAL = 'Статус инновационной площадки';
      V$TYPE_ID1 = 463;
    END
    ELSE IF(I$BLOCK_NAME = 'contest') THEN
    BEGIN
      VAL = 'Статус ОУ в региональных конкурсах';
      V$TYPE_ID1 = 464;
    END
    ELSE IF(I$BLOCK_NAME = 'reward') THEN
    BEGIN
      VAL = 'Награды сотрудников';
      V$TYPE_ID1 = 39;
      V$TYPE_ID2 = 40;
      V$MID_TYPE = 14;
    END
    ELSE IF(I$BLOCK_NAME = 'acv') THEN
    BEGIN
      VAL = 'Достижения сотрудников';
      V$TYPE_ID1 = 41;
      V$TYPE_ID2 = 42;
      V$MID_TYPE = 14;
    END
    ELSE VAL = '???';
    SUSPEND;

    TAG_NAME = 'has_caption';
    VAL = IIF(V$MID_TYPE IS NULL, 0, 1);
    SUSPEND;

    -- Описание полей
    TAG_NAME = 'columns::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT P.TYPE_ID, P.PARAM_ID, P.PARAM_TYPE, R.VAL
      FROM PARAMS P
      JOIN RES R ON R.RES_ID = P.RES_ID AND R.LANG_CODE = 'RU'
      WHERE P.IS_DEL = 0 AND (P.TYPE_ID = :V$TYPE_ID1 OR P.TYPE_ID = :V$TYPE_ID2)
      ORDER BY 1, 2
      INTO :V$TYPE, :V$PARAM_ID, :V$T, :S
    DO
    BEGIN
      TAG_NAME = 'columns:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'columns:r:type_id';
      VAL = V$TYPE;
      SUSPEND;
      TAG_NAME = 'columns:r:param_id';
      VAL = V$PARAM_ID;
      SUSPEND;
      TAG_NAME = 'columns:r:type';
      VAL = V$T;
      SUSPEND;
      TAG_NAME = 'columns:r:name';
      VAL = S;
      SUSPEND;
    END

    -- Данные
    TAG_NAME = 'rows::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT NULL, LD.OBJ_ID, LD.OBJ_TYPE_ID
      FROM LINKS LD
      WHERE LD.PARENT_ID = :I$OBJ_ID AND LD.DATE_DEL IS NULL AND (LD.OBJ_TYPE_ID = :V$TYPE_ID1 OR LD.OBJ_TYPE_ID = :V$TYPE_ID2)
      UNION
      SELECT LM.OBJ_ID, LD.OBJ_ID, LD.OBJ_TYPE_ID
      FROM LINKS LM
      JOIN LINKS LD ON LD.PARENT_ID = LM.OBJ_ID AND LD.DATE_DEL IS NULL AND (LD.OBJ_TYPE_ID = :V$TYPE_ID1 OR LD.OBJ_TYPE_ID = :V$TYPE_ID2)
      WHERE LM.PARENT_ID = :I$OBJ_ID AND LM.DATE_DEL IS NULL AND LM.OBJ_TYPE_ID = :V$MID_TYPE
      ORDER BY 1, 3, 2
      INTO :V$MASTER_ID, :V$OBJ_ID, :V$TYPE
    DO
    BEGIN
      -- Фильтрация по наградам и достижениям
      V$OK = 1;
      IF(I$BLOCK_NAME = 'reward' OR I$BLOCK_NAME = 'acv') THEN
      BEGIN
        IF(I$BLOCK_ID = 1) THEN
        BEGIN
          -- Учителя
          V$OK = 0;
          SELECT FIRST 1 1
          FROM LINKS L15
          LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.PARENT_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
          JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
          JOIN VALL V64 ON V64.OBJ_ID = LP13.PARENT_ID AND V64.PARAM_ID = 64 AND V64.IS_DEL = 0 AND V64.LISTVAL_ID = 98
          WHERE L15.PARENT_ID = :V$MASTER_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL AND V74.VAL IS NULL
          INTO :V$OK;
        END
        ELSE IF(I$BLOCK_ID = 2) THEN
        BEGIN
          -- Руководители
          V$OK = 0;
          SELECT FIRST 1 1
          FROM LINKS L15
          LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.PARENT_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
          JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
          JOIN VALL V64 ON V64.OBJ_ID = LP13.PARENT_ID AND V64.PARAM_ID = 64 AND V64.IS_DEL = 0 AND V64.LISTVAL_ID = 56
          WHERE L15.PARENT_ID = :V$MASTER_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL AND V74.VAL IS NULL
          INTO :V$OK;
        END
      END

      IF(V$OK = 1) THEN
      BEGIN
        TAG_NAME = 'rows:r';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'rows:r:id';
        VAL = V$OBJ_ID;
        SUSPEND;
        TAG_NAME = 'rows:r:type_id';
        VAL = V$TYPE;
        SUSPEND;
        IF(V$MID_TYPE IS NOT NULL) THEN
        BEGIN
          TAG_NAME = 'rows:r:caption';
          VAL = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$MASTER_ID));
          SUSPEND;
        END
        FOR
          SELECT P.PARAM_ID, IIF(V.IS_EXISTS = 1, V.V, NULL)
          FROM PARAMS P
          LEFT JOIN VAL_GET(:V$OBJ_ID, P.PARAM_ID) V ON 1 = 1
          WHERE P.TYPE_ID = :V$TYPE AND P.IS_DEL = 0
          ORDER BY P.GRID_ORDER
          INTO :V$PARAM_ID, :S
        DO
        BEGIN
          TAG_NAME = 'rows:r:p' || V$PARAM_ID;
          VAL = S;
          SUSPEND;
        END
      END
    END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PF_PORTFOLIO_RGN (
    I$OBJ_ID BIGINT,
    I$BLOCK_NAME VARCHAR(40),
    I$BLOCK_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(1000))
AS
declare variable V$VAL bigint;
declare variable V$VAL2 integer;
declare variable S varchar(1000);
declare variable V$TYPE_ID1 bigint;
declare variable V$TYPE_ID2 bigint;
declare variable V$MID_TYPE bigint;
declare variable V$OBJ_ID bigint;
declare variable V$PARAM_ID bigint;
declare variable V$TYPE bigint;
declare variable V$T bigint;
declare variable V$MASTER_ID bigint;
begin

  IF(I$BLOCK_NAME IS NULL) THEN
  BEGIN
    -- Оглавление
    TAG_NAME = 'dashboard::json&colon;array';
    VAL = 1;
    SUSPEND;

    -- Инновационные площадки
    SELECT COUNT(*)
    FROM LINKS L111
    JOIN LINKS L2 ON L2.PARENT_ID = L111.OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    JOIN LINKS L463 ON L463.PARENT_ID = L2.OBJ_ID AND L463.OBJ_TYPE_ID = 463 AND L463.DATE_DEL IS NULL
    JOIN VALL V3313 ON V3313.OBJ_ID = L463.OBJ_ID AND V3313.PARAM_ID = 3313 AND V3313.IS_DEL = 0 AND V3313.LISTVAL_ID = 14142
    LEFT JOIN VALD V3315 ON V3315.OBJ_ID = L463.OBJ_ID AND V3315.PARAM_ID = 3315 AND V3315.IS_DEL = 0
    WHERE L111.PARENT_ID = :I$OBJ_ID AND L111.OBJ_TYPE_ID = 111 AND L111.DATE_DEL IS NULL AND V3315.VAL IS NULL
    INTO :V$VAL;
    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'innoplace';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '463';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'chess queen';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#25D366';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Инновационная площадка регионального уровня';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

    SELECT COUNT(*)
    FROM LINKS L111
    JOIN LINKS L2 ON L2.PARENT_ID = L111.OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    JOIN LINKS L463 ON L463.PARENT_ID = L2.OBJ_ID AND L463.OBJ_TYPE_ID = 463 AND L463.DATE_DEL IS NULL
    JOIN VALL V3313 ON V3313.OBJ_ID = L463.OBJ_ID AND V3313.PARAM_ID = 3313 AND V3313.IS_DEL = 0 AND V3313.LISTVAL_ID = 14143
    LEFT JOIN VALD V3315 ON V3315.OBJ_ID = L463.OBJ_ID AND V3315.PARAM_ID = 3315 AND V3315.IS_DEL = 0
    WHERE L111.PARENT_ID = :I$OBJ_ID AND L111.OBJ_TYPE_ID = 111 AND L111.DATE_DEL IS NULL AND V3315.VAL IS NULL
    INTO :V$VAL;
    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'innoplace';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '463';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'chess queen';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#FF5700';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Инновационная площадка федерального уровня';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

    SELECT COUNT(*)
    FROM LINKS L111
    JOIN LINKS L2 ON L2.PARENT_ID = L111.OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    JOIN LINKS L464 ON L464.PARENT_ID = L2.OBJ_ID AND L464.OBJ_TYPE_ID = 464 AND L464.DATE_DEL IS NULL
    JOIN VALL V3318 ON V3318.OBJ_ID = L464.OBJ_ID AND V3318.PARAM_ID = 3318 AND V3318.IS_DEL = 0 AND V3318.LISTVAL_ID = 757
    JOIN VALI V3316 ON V3316.OBJ_ID = L464.OBJ_ID AND V3316.PARAM_ID = 3316 AND V3316.IS_DEL = 0 AND V3316.VAL >= EXTRACT(YEAR FROM CURRENT_DATE) - 3
    WHERE L111.PARENT_ID = :I$OBJ_ID AND L111.OBJ_TYPE_ID = 111 AND L111.DATE_DEL IS NULL
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'contest';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '464';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'thumbs up';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#25D366';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Лауреатов конкурсов ОУ';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

    SELECT COUNT(*)
    FROM LINKS L111
    JOIN LINKS L2 ON L2.PARENT_ID = L111.OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    JOIN LINKS L464 ON L464.PARENT_ID = L2.OBJ_ID AND L464.OBJ_TYPE_ID = 464 AND L464.DATE_DEL IS NULL
    JOIN VALL V3318 ON V3318.OBJ_ID = L464.OBJ_ID AND V3318.PARAM_ID = 3318 AND V3318.IS_DEL = 0 AND V3318.LISTVAL_ID = 756
    JOIN VALI V3316 ON V3316.OBJ_ID = L464.OBJ_ID AND V3316.PARAM_ID = 3316 AND V3316.IS_DEL = 0 AND V3316.VAL >= EXTRACT(YEAR FROM CURRENT_DATE) - 3
    WHERE L111.PARENT_ID = :I$OBJ_ID AND L111.OBJ_TYPE_ID = 111 AND L111.DATE_DEL IS NULL
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'contest';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '464';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'thumbs up';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#FF5700';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Победителей конкурсов ОУ';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

    SELECT COUNT(*)
    FROM LINKS L111
    JOIN LINKS L2 ON L2.PARENT_ID = L111.OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
    JOIN LINKS L39 ON L39.PARENT_ID = L14.OBJ_ID AND L39.OBJ_TYPE_ID IN (39, 40) AND L39.DATE_DEL IS NULL
    WHERE L111.PARENT_ID = :I$OBJ_ID AND L111.OBJ_TYPE_ID = 111 AND L111.DATE_DEL IS NULL
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'reward';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '39,40';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'trophy';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#1877F2';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Награды сотрудников';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

    -- Достижения сотрудников
    SELECT COUNT(*)
    FROM LINKS L111
    JOIN LINKS L2 ON L2.PARENT_ID = L111.OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
    JOIN LINKS L41 ON L41.PARENT_ID = L14.OBJ_ID AND L41.OBJ_TYPE_ID IN (41, 42) AND L41.DATE_DEL IS NULL
    WHERE L111.PARENT_ID = :I$OBJ_ID AND L111.OBJ_TYPE_ID = 111 AND L111.DATE_DEL IS NULL
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'acv';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '41,42';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'star';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#34465D';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Достижения сотрудников';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

  END
  ELSE
  BEGIN

    TAG_NAME = 'title';
    IF(I$BLOCK_NAME = 'innoplace') THEN VAL = 'Инновационная площадки';
    ELSE IF(I$BLOCK_NAME = 'contest') THEN VAL = 'Участники конкурса ОУ';
    ELSE IF(I$BLOCK_NAME = 'reward') THEN VAL = 'Награды сотрудников';
    ELSE IF(I$BLOCK_NAME = 'acv') THEN VAL = 'Достижения сотрудников';
    SUSPEND;

    TAG_NAME = 'has_caption';
    VAL = 1;
    SUSPEND;

    TAG_NAME = 'columns::json&colon;array';
    VAL = 1;
    SUSPEND;
    -- Первый параметр всегда есть
    TAG_NAME = 'columns:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'columns:r:type_id';
    VAL = '1';
    SUSPEND;
    TAG_NAME = 'columns:r:param_id';
    VAL = '0';
    SUSPEND;
    TAG_NAME = 'columns:r:type';
    VAL = '0';
    SUSPEND;
    TAG_NAME = 'columns:r:name';
    IF(I$BLOCK_NAME = 'innoplace') THEN VAL = 'Инновационная площадка регионального уровня';
    ELSE IF(I$BLOCK_NAME = 'contest') THEN VAL = 'Лауреатов конкурса ОУ';
    ELSE IF(I$BLOCK_NAME = 'reward') THEN VAL = 'Наград сотрудников';
    ELSE IF(I$BLOCK_NAME = 'acv') THEN VAL = 'Достижений сотрудников';
    SUSPEND;

    -- Второй парметр частично
    IF(I$BLOCK_NAME = 'innoplace' OR I$BLOCK_NAME = 'contest') THEN
    BEGIN
    TAG_NAME = 'columns:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'columns:r:type_id';
    VAL = '1';
    SUSPEND;
    TAG_NAME = 'columns:r:param_id';
    VAL = '1';
    SUSPEND;
    TAG_NAME = 'columns:r:type';
    VAL = '0';
    SUSPEND;
    TAG_NAME = 'columns:r:name';
    SUSPEND;
    IF(I$BLOCK_NAME = 'innoplace') THEN VAL = 'Инновационная площадка федерального уровня';
    ELSE IF(I$BLOCK_NAME = 'contest') THEN VAL = 'Победителей конкурса ОУ';
    SUSPEND;
    END

    -- Развертка по районам
    TAG_NAME = 'rows::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT L111.OBJ_ID, L111.OBJ_TYPE_ID, C.CAPTION
      FROM LINKS L111
      LEFT JOIN OBJECT_CAPTION_GET(L111.OBJ_ID) C ON 1 = 1
      WHERE L111.PARENT_ID = :I$OBJ_ID AND L111.OBJ_TYPE_ID = 111 AND L111.DATE_DEL IS NULL
      ORDER BY 3
      INTO :V$OBJ_ID, :V$TYPE, :S
    DO
    BEGIN
      TAG_NAME = 'rows:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'rows:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'rows:r:type_id';
      VAL = '1';
      SUSPEND;
      TAG_NAME = 'rows:r:caption';
      VAL = S;
      SUSPEND;

      IF(I$BLOCK_NAME = 'innoplace') THEN 
      BEGIN
        SELECT SUM(IIF(V3313.LISTVAL_ID = 14142, 1, 0)), SUM(IIF(V3313.LISTVAL_ID = 14143, 1, 0))
        FROM LINKS L2
        JOIN LINKS L463 ON L463.PARENT_ID = L2.OBJ_ID AND L463.OBJ_TYPE_ID = 463 AND L463.DATE_DEL IS NULL
        JOIN VALL V3313 ON V3313.OBJ_ID = L463.OBJ_ID AND V3313.PARAM_ID = 3313 AND V3313.IS_DEL = 0 AND V3313.LISTVAL_ID = 14142
        LEFT JOIN VALD V3315 ON V3315.OBJ_ID = L463.OBJ_ID AND V3315.PARAM_ID = 3315 AND V3315.IS_DEL = 0
        WHERE L2.PARENT_ID = :V$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND V3315.VAL IS NULL
        INTO :V$VAL, :V$VAL2;
      END
      ELSE IF(I$BLOCK_NAME = 'contest') THEN
      BEGIN
        SELECT SUM(IIF(V3318.LISTVAL_ID = 757, 1, 0)), SUM(IIF(V3318.LISTVAL_ID = 756, 1, 0))
        FROM LINKS L2
        JOIN LINKS L464 ON L464.PARENT_ID = L2.OBJ_ID AND L464.OBJ_TYPE_ID = 464 AND L464.DATE_DEL IS NULL
        JOIN VALL V3318 ON V3318.OBJ_ID = L464.OBJ_ID AND V3318.PARAM_ID = 3318 AND V3318.IS_DEL = 0
        JOIN VALI V3316 ON V3316.OBJ_ID = L464.OBJ_ID AND V3316.PARAM_ID = 3316 AND V3316.IS_DEL = 0 AND V3316.VAL >= EXTRACT(YEAR FROM CURRENT_DATE) - 3
        WHERE L2.PARENT_ID = :V$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
        INTO :V$VAL, :V$VAL2;
      END
      ELSE IF(I$BLOCK_NAME = 'reward') THEN
      BEGIN
        SELECT COUNT(*)
        FROM LINKS L2
        JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
        JOIN LINKS L39 ON L39.PARENT_ID = L14.OBJ_ID AND L39.OBJ_TYPE_ID IN (39, 40) AND L39.DATE_DEL IS NULL
        WHERE L2.PARENT_ID = :V$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
        INTO :V$VAL;
      END
      ELSE IF(I$BLOCK_NAME = 'acv') THEN
      BEGIN
        SELECT COUNT(*)
        FROM LINKS L2
        JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
        JOIN LINKS L41 ON L41.PARENT_ID = L14.OBJ_ID AND L41.OBJ_TYPE_ID IN (41, 42) AND L41.DATE_DEL IS NULL
        WHERE L2.PARENT_ID = :V$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
        INTO :V$VAL;
      END

      TAG_NAME = 'rows:r:p0';
      VAL = V$VAL;
      SUSPEND;
      TAG_NAME = 'rows:r:p1';
      VAL = V$VAL2;
      SUSPEND;
    END

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PF_STUDENTS (
    I$OBJ_ID BIGINT,
    I$BLOCK_NAME VARCHAR(40),
    I$BLOCK_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(1000))
AS
declare variable V$TYPE_ID bigint;
begin

  SELECT TYPE_ID
  FROM OBJECTS
  WHERE OBJ_ID = :I$OBJ_ID
  INTO :V$TYPE_ID;

  IF(V$TYPE_ID = 2) THEN
  BEGIN
    FOR
      SELECT D.TAG_NAME, D.VAL
      FROM PF_STUDENTS_OU(:I$OBJ_ID, :I$BLOCK_NAME, :I$BLOCK_ID, :I$USER_ID) D
      INTO :TAG_NAME, :VAL
    DO
    BEGIN
      SUSPEND;
    END
  END
  ELSE IF(V$TYPE_ID = 111) THEN
  BEGIN
    FOR
      SELECT D.TAG_NAME, D.VAL
      FROM PF_STUDENTS_DIST(:I$OBJ_ID, :I$BLOCK_NAME, :I$BLOCK_ID, :I$USER_ID) D
      INTO :TAG_NAME, :VAL
    DO
    BEGIN
      SUSPEND;
    END
  END
  ELSE IF(V$TYPE_ID = 112) THEN
  BEGIN
    FOR
      SELECT D.TAG_NAME, D.VAL
      FROM PF_STUDENTS_RGN(:I$OBJ_ID, :I$BLOCK_NAME, :I$BLOCK_ID, :I$USER_ID) D
      INTO :TAG_NAME, :VAL
    DO
    BEGIN
      SUSPEND;
    END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PF_STUDENTS_DIST (
    I$OBJ_ID BIGINT,
    I$BLOCK_NAME VARCHAR(40),
    I$BLOCK_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(1000))
AS
declare variable V$VAL bigint;
declare variable V$VAL2 bigint;
declare variable V$TEACHERS bigint;
declare variable F float;
declare variable S varchar(1000);
declare variable V$TYPE_ID1 bigint;
declare variable V$TYPE_ID2 bigint;
declare variable V$MID_TYPE bigint;
declare variable V$OBJ_ID bigint;
declare variable V$PARAM_ID bigint;
declare variable V$TYPE bigint;
declare variable V$T bigint;
declare variable V$MASTER_ID bigint;
declare variable V$YEAR_START date;
begin

  IF(EXTRACT(MONTH FROM CURRENT_DATE) < 8) THEN V$YEAR_START = '01.09.' || (EXTRACT(YEAR FROM CURRENT_DATE) - 1);
  ELSE V$YEAR_START = '01.09.' || EXTRACT(YEAR FROM CURRENT_DATE);

  IF(I$BLOCK_NAME IS NULL) THEN
  BEGIN
    -- Оглавление
    TAG_NAME = 'dashboard::json&colon;array';
    VAL = 1;
    SUSPEND;

    -- Сколько всего учителей ?
    SELECT COUNT(DISTINCT L14.OBJ_ID)
    FROM LINKS L2
    JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
    JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L14.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
    JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
    JOIN VALL V64 ON V64.OBJ_ID = LP13.PARENT_ID AND V64.PARAM_ID = 64 AND V64.IS_DEL = 0 AND V64.LISTVAL_ID = 98
    WHERE L2.PARENT_ID = :I$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND V74.VAL IS NULL
    INTO :V$TEACHERS;

    SELECT COUNT(DISTINCT M.PERSON_ID)
    FROM PERSON_MOVEMENTS M
    JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
    WHERE M.DATE_DEL IS NULL AND M.DATE_IN <= CURRENT_DATE AND M.DATE_OUT IS NULL -- AND M.GROUP_TYPE_ID = 9
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'students';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '10';
    SUSPEND;
    TAG_NAME = 'dashboard:r:subtype_id';
    VAL = '';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'user';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#410093';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Количество обучающихся';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

    -- Сколько классов в городе ?
    SELECT COUNT(DISTINCT M.GROUP_ID)
    FROM PERSON_MOVEMENTS M
    JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
    JOIN VALL V80 ON V80.OBJ_ID = M.PERSON_ID AND V80.PARAM_ID = 80 AND V80.IS_DEL = 0 AND V80.LISTVAL_ID = 5418
    WHERE M.DATE_DEL IS NULL AND M.DATE_IN <= CURRENT_DATE AND M.DATE_OUT IS NULL -- AND M.GROUP_TYPE_ID = 9
    INTO :V$VAL2;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'classfill';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '10';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'clone outline';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#410093';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Средняя наполняемость классов';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    IF(V$TEACHERS = 0) THEN F = NULL; ELSE F = CAST(V$VAL AS FLOAT) / CAST(V$VAL2 AS FLOAT);
    VAL = CAST(F AS NUMERIC (18, 2));
    SUSPEND;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'students';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '10';
    SUSPEND;
    TAG_NAME = 'dashboard:r:subtype_id';
    VAL = '';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'percent';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#25D366';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Обучающихся на одного учителя';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    IF(V$TEACHERS = 0) THEN F = NULL; ELSE F = CAST(V$VAL AS FLOAT) / CAST(V$TEACHERS AS FLOAT);
    VAL = CAST(F AS NUMERIC (18, 1));
    SUSPEND;

    SELECT COUNT(DISTINCT M.PERSON_ID)
    FROM LINKS L2
    JOIN PERSON_MOVEMENTS M ON M.DATE_DEL IS NULL AND M.OU_ID = L2.OBJ_ID AND M.DATE_IN <= CURRENT_DATE AND M.DATE_OUT IS NULL -- AND M.GROUP_TYPE_ID = 9
    JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
    JOIN VALL V207 ON V207.OBJ_ID = M.PERSON_ID AND V207.PARAM_ID = 207 AND V207.IS_DEL = 0 AND V207.LISTVAL_ID <> 13289
    WHERE L2.PARENT_ID = :I$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'byovz';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '10';
    SUSPEND;
    TAG_NAME = 'dashboard:r:subtype_id';
    VAL = '207';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'wheelchair';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#410093';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Количество обучающихся с ОВЗ';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

    SELECT COUNT(DISTINCT M.PERSON_ID)
    FROM LINKS L2
    JOIN PERSON_MOVEMENTS M ON M.DATE_DEL IS NULL AND M.OU_ID = L2.OBJ_ID AND M.DATE_IN <= CURRENT_DATE AND M.DATE_OUT IS NULL -- AND M.GROUP_TYPE_ID = 9
    JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
    JOIN VALL V80 ON V80.OBJ_ID = M.PERSON_ID AND V80.PARAM_ID = 80 AND V80.IS_DEL = 0 AND V80.LISTVAL_ID = 5418
    WHERE L2.PARENT_ID = :I$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'byform';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '10';
    SUSPEND;
    TAG_NAME = 'dashboard:r:subtype_id';
    VAL = '80';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'sun';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#410093';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Количество обучающихся очной формы';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

    SELECT COUNT(DISTINCT M.PERSON_ID)
    FROM LINKS L2
    JOIN PERSON_MOVEMENTS M ON M.DATE_DEL IS NULL AND M.OU_ID = L2.OBJ_ID AND M.DATE_IN <= CURRENT_DATE AND M.DATE_OUT IS NULL -- AND M.LEVEL_ID = 22 AND M.GROUP_TYPE_ID = 9
    JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
    -- !!!
    JOIN LINKS LP8 ON LP8.OBJ_ID = M.GROUP_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
    JOIN LINKS LP7 ON LP7.OBJ_ID = LP8.PARENT_ID AND LP7.PARENT_TYPE_ID = 7 AND LP7.DATE_DEL IS NULL
    JOIN VALL V43 ON V43.OBJ_ID = LP7.PARENT_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0 AND V43.LISTVAL_ID = 22
    WHERE L2.PARENT_ID = :I$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'bylevel';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '10';
    SUSPEND;
    TAG_NAME = 'dashboard:r:subtype_id';
    VAL = '43';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'user';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#410093';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Количество обучающихся НОО';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

    SELECT COUNT(DISTINCT M.PERSON_ID)
    FROM LINKS L2
    JOIN PERSON_MOVEMENTS M ON M.DATE_DEL IS NULL AND M.OU_ID = L2.OBJ_ID AND M.DATE_IN <= CURRENT_DATE AND M.DATE_OUT IS NULL -- AND M.LEVEL_ID = 26 AND M.GROUP_TYPE_ID = 9
    JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
    -- !!!
    JOIN LINKS LP8 ON LP8.OBJ_ID = M.GROUP_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
    JOIN LINKS LP7 ON LP7.OBJ_ID = LP8.PARENT_ID AND LP7.PARENT_TYPE_ID = 7 AND LP7.DATE_DEL IS NULL
    JOIN VALL V43 ON V43.OBJ_ID = LP7.PARENT_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0 AND V43.LISTVAL_ID = 26
    WHERE L2.PARENT_ID = :I$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'bylevel';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '10';
    SUSPEND;
    TAG_NAME = 'dashboard:r:subtype_id';
    VAL = '43';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'user';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#410093';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Количество обучающихся ООО';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

    SELECT COUNT(DISTINCT M.PERSON_ID)
    FROM LINKS L2
    JOIN PERSON_MOVEMENTS M ON M.DATE_DEL IS NULL AND M.OU_ID = L2.OBJ_ID AND M.DATE_IN <= CURRENT_DATE AND M.DATE_OUT IS NULL -- AND M.LEVEL_ID = 27 AND M.GROUP_TYPE_ID = 9
    JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
    -- !!!
    JOIN LINKS LP8 ON LP8.OBJ_ID = M.GROUP_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
    JOIN LINKS LP7 ON LP7.OBJ_ID = LP8.PARENT_ID AND LP7.PARENT_TYPE_ID = 7 AND LP7.DATE_DEL IS NULL
    JOIN VALL V43 ON V43.OBJ_ID = LP7.PARENT_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0 AND V43.LISTVAL_ID = 27
    WHERE L2.PARENT_ID = :I$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'bylevel';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '10';
    SUSPEND;
    TAG_NAME = 'dashboard:r:subtype_id';
    VAL = '43';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'user';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#410093';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Количество обучающихся СОО';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

    SELECT COUNT(*)
    FROM LINKS L2
    JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
    WHERE L2.PARENT_ID = :I$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'classes';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '9';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'sort numeric down';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#34465D';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Количество классов';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

    SELECT COUNT(DISTINCT M.PERSON_ID)
    FROM LINKS L2
    JOIN PERSON_MOVEMENTS M ON M.DATE_DEL IS NULL AND M.OU_ID = L2.OBJ_ID AND M.DATE_IN >= :V$YEAR_START -- AND M.GROUP_TYPE_ID = 9
    JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
    WHERE L2.PARENT_ID = :I$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'accepted';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '10';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'arrow circle down';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#DF2029';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Принято с начала года';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

    SELECT COUNT(DISTINCT M.PERSON_ID)
    FROM LINKS L2
    JOIN PERSON_MOVEMENTS M ON M.DATE_DEL IS NULL AND M.OU_ID = L2.OBJ_ID AND M.DATE_OUT >= :V$YEAR_START -- !!! учитывать перешедших AND M.GROUP_TYPE_ID = 9
    JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
    WHERE L2.PARENT_ID = :I$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'leaved';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '10';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'arrow circle up';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#DF2029';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Выбыло с начала года';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

  END
  ELSE
  BEGIN

    -- Чиним ID организации
    EXECUTE PROCEDURE FIX_MOVEMENTS_OU;

    TAG_NAME = 'title';
    VAL = 'Контингент';
    SUSPEND;

    TAG_NAME = 'has_caption';
    VAL = 1;
    SUSPEND;

    TAG_NAME = 'columns::json&colon;array';
    VAL = 1;
    SUSPEND;

    TAG_NAME = 'columns:r'; VAL = NULL; SUSPEND;
    TAG_NAME = 'columns:r:type_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:param_id'; VAL = '0'; SUSPEND;
    TAG_NAME = 'columns:r:type'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:name'; VAL = 'Количество ОУ'; SUSPEND;

    TAG_NAME = 'columns:r'; VAL = NULL; SUSPEND;
    TAG_NAME = 'columns:r:type_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:param_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:type'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:name'; VAL = 'Количество обучающихся'; SUSPEND;

    TAG_NAME = 'columns:r'; VAL = NULL; SUSPEND;
    TAG_NAME = 'columns:r:type_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:param_id'; VAL = '2'; SUSPEND;
    TAG_NAME = 'columns:r:type'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:name'; VAL = 'Обучающихся на 1 учителя'; SUSPEND;

    TAG_NAME = 'columns:r'; VAL = NULL; SUSPEND;
    TAG_NAME = 'columns:r:type_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:param_id'; VAL = '3'; SUSPEND;
    TAG_NAME = 'columns:r:type'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:name'; VAL = 'Количество обучающихся с ОВЗ'; SUSPEND;

    TAG_NAME = 'columns:r'; VAL = NULL; SUSPEND;
    TAG_NAME = 'columns:r:type_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:param_id'; VAL = '4'; SUSPEND;
    TAG_NAME = 'columns:r:type'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:name'; VAL = 'Количество обучающихся очной формы'; SUSPEND;

    TAG_NAME = 'columns:r'; VAL = NULL; SUSPEND;
    TAG_NAME = 'columns:r:type_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:param_id'; VAL = '5'; SUSPEND;
    TAG_NAME = 'columns:r:type'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:name'; VAL = 'Количество обучающихся НОО'; SUSPEND;

    TAG_NAME = 'columns:r'; VAL = NULL; SUSPEND;
    TAG_NAME = 'columns:r:type_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:param_id'; VAL = '6'; SUSPEND;
    TAG_NAME = 'columns:r:type'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:name'; VAL = 'Количество обучающихся ООО'; SUSPEND;

    TAG_NAME = 'columns:r'; VAL = NULL; SUSPEND;
    TAG_NAME = 'columns:r:type_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:param_id'; VAL = '7'; SUSPEND;
    TAG_NAME = 'columns:r:type'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:name'; VAL = 'Количество обучающихся СОО'; SUSPEND;

    TAG_NAME = 'columns:r'; VAL = NULL; SUSPEND;
    TAG_NAME = 'columns:r:type_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:param_id'; VAL = '8'; SUSPEND;
    TAG_NAME = 'columns:r:type'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:name'; VAL = 'Количество классов'; SUSPEND;

    TAG_NAME = 'columns:r'; VAL = NULL; SUSPEND;
    TAG_NAME = 'columns:r:type_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:param_id'; VAL = '9'; SUSPEND;
    TAG_NAME = 'columns:r:type'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:name'; VAL = 'Принято с начала года'; SUSPEND;

    TAG_NAME = 'columns:r'; VAL = NULL; SUSPEND;
    TAG_NAME = 'columns:r:type_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:param_id'; VAL = '9'; SUSPEND;
    TAG_NAME = 'columns:r:type'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:name'; VAL = 'Выбыло с начала года'; SUSPEND;

    -- Развертка по районам
    TAG_NAME = 'rows::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT L2.OBJ_ID, L2.OBJ_TYPE_ID, C.CAPTION
      FROM LINKS L2
      LEFT JOIN OBJECT_CAPTION_GET(L2.OBJ_ID) C ON 1 = 1
      WHERE L2.PARENT_ID = :I$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      ORDER BY 3
      INTO :V$OBJ_ID, :V$TYPE, :S
    DO
    BEGIN
      TAG_NAME = 'rows:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'rows:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'rows:r:type_id';
      VAL = '1';
      SUSPEND;
      TAG_NAME = 'rows:r:caption';
      VAL = S;
      SUSPEND;

      -- Сколько всего учителей ?
      SELECT COUNT(DISTINCT L14.OBJ_ID)
      FROM LINKS L2
      JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
      JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
      LEFT JOIN VALD V74 ON V74.OBJ_ID = L14.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
      JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
      JOIN VALL V64 ON V64.OBJ_ID = LP13.PARENT_ID AND V64.PARAM_ID = 64 AND V64.IS_DEL = 0 AND V64.LISTVAL_ID = 98
      WHERE L2.PARENT_ID = :V$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND V74.VAL IS NULL
      INTO :V$TEACHERS;

      SELECT COUNT(*)
      FROM LINKS L2
      WHERE L2.PARENT_ID = :V$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      INTO :V$VAL;

      TAG_NAME = 'rows:r:p0';
      VAL = V$VAL;
      SUSPEND;

      SELECT COUNT(DISTINCT M.PERSON_ID)
      FROM PERSON_MOVEMENTS M
      JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
      WHERE M.DATE_DEL IS NULL AND M.OU_ID = :V$OBJ_ID AND M.DATE_IN <= CURRENT_DATE AND M.DATE_OUT IS NULL -- AND M.GROUP_TYPE_ID = 9
      INTO :V$VAL;

      TAG_NAME = 'rows:r:p1';
      VAL = V$VAL;
      SUSPEND;

      TAG_NAME = 'rows:r:p2';
      IF(V$TEACHERS = 0) THEN F = NULL; ELSE F = CAST(V$VAL AS FLOAT) / CAST(V$TEACHERS AS FLOAT);
      VAL = CAST(F AS NUMERIC (18, 1));
      SUSPEND;

      SELECT COUNT(DISTINCT M.PERSON_ID)
      FROM PERSON_MOVEMENTS M
      JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
      JOIN VALL V207 ON V207.OBJ_ID = M.PERSON_ID AND V207.PARAM_ID = 207 AND V207.IS_DEL = 0 AND V207.LISTVAL_ID <> 13289
      WHERE M.DATE_DEL IS NULL AND M.OBJ_ID = :V$OBJ_ID AND M.DATE_IN <= CURRENT_DATE AND M.DATE_OUT IS NULL -- AND M.GROUP_TYPE_ID = 9
      INTO :V$VAL;

      TAG_NAME = 'rows:r:p3';
      VAL = V$VAL;
      SUSPEND;

      SELECT COUNT(DISTINCT M.PERSON_ID)
      FROM PERSON_MOVEMENTS M
      JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
      JOIN VALL V80 ON V80.OBJ_ID = M.PERSON_ID AND V80.PARAM_ID = 80 AND V80.IS_DEL = 0 AND V80.LISTVAL_ID = 5418
      WHERE M.DATE_DEL IS NULL AND M.OBJ_ID = :V$OBJ_ID  AND M.DATE_IN <= CURRENT_DATE AND M.DATE_OUT IS NULL -- AND M.GROUP_TYPE_ID = 9
      INTO :V$VAL;

      TAG_NAME = 'rows:r:p4';
      VAL = V$VAL;
      SUSPEND;

      SELECT COUNT(DISTINCT M.PERSON_ID)
      FROM PERSON_MOVEMENTS M
      JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
      -- !!!
      JOIN LINKS LP8 ON LP8.OBJ_ID = M.GROUP_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
      JOIN LINKS LP7 ON LP7.OBJ_ID = LP8.PARENT_ID AND LP7.PARENT_TYPE_ID = 7 AND LP7.DATE_DEL IS NULL
      JOIN VALL V43 ON V43.OBJ_ID = LP7.PARENT_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0 AND V43.LISTVAL_ID = 22
      WHERE M.DATE_DEL IS NULL AND M.OU_ID = :V$OBJ_ID AND M.DATE_IN <= CURRENT_DATE AND M.DATE_OUT IS NULL -- AND M.LEVEL_ID = 22 AND M.GROUP_TYPE_ID = 9
      INTO :V$VAL;

      TAG_NAME = 'rows:r:p5';
      VAL = V$VAL;
      SUSPEND;

      SELECT COUNT(DISTINCT M.PERSON_ID)
      FROM PERSON_MOVEMENTS M
      JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
      -- !!!
      JOIN LINKS LP8 ON LP8.OBJ_ID = M.GROUP_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
      JOIN LINKS LP7 ON LP7.OBJ_ID = LP8.PARENT_ID AND LP7.PARENT_TYPE_ID = 7 AND LP7.DATE_DEL IS NULL
      JOIN VALL V43 ON V43.OBJ_ID = LP7.PARENT_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0 AND V43.LISTVAL_ID = 26
      WHERE M.DATE_DEL IS NULL AND M.OU_ID = :V$OBJ_ID AND M.DATE_IN <= CURRENT_DATE AND M.DATE_OUT IS NULL -- AND M.LEVEL_ID = 26 AND M.GROUP_TYPE_ID = 9
      INTO :V$VAL;

      TAG_NAME = 'rows:r:p6';
      VAL = V$VAL;
      SUSPEND;

      SELECT COUNT(DISTINCT M.PERSON_ID)
      FROM PERSON_MOVEMENTS M
      JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
      -- !!!
      JOIN LINKS LP8 ON LP8.OBJ_ID = M.GROUP_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
      JOIN LINKS LP7 ON LP7.OBJ_ID = LP8.PARENT_ID AND LP7.PARENT_TYPE_ID = 7 AND LP7.DATE_DEL IS NULL
      JOIN VALL V43 ON V43.OBJ_ID = LP7.PARENT_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0 AND V43.LISTVAL_ID = 27
      WHERE M.DATE_DEL IS NULL AND M.OU_ID = :V$OBJ_ID AND M.DATE_IN <= CURRENT_DATE AND M.DATE_OUT IS NULL -- AND M.LEVEL_ID = 27 AND M.GROUP_TYPE_ID = 9
      INTO :V$VAL;

      TAG_NAME = 'rows:r:p7';
      VAL = V$VAL;
      SUSPEND;

      SELECT COUNT(*)
      FROM LINKS L7
      JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
      WHERE L7.PARENT_ID = :V$OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
      INTO :V$VAL;

      TAG_NAME = 'rows:r:p8';
      VAL = V$VAL;
      SUSPEND;

      SELECT COUNT(DISTINCT M.PERSON_ID)
      FROM PERSON_MOVEMENTS M
      JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
      WHERE M.DATE_DEL IS NULL AND M.OU_ID = :V$OBJ_ID AND M.DATE_IN >= :V$YEAR_START -- AND M.GROUP_TYPE_ID = 9
      INTO :V$VAL;

      TAG_NAME = 'rows:r:p9';
      VAL = V$VAL;
      SUSPEND;

      SELECT COUNT(DISTINCT M.PERSON_ID)
      FROM PERSON_MOVEMENTS M
      JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
      WHERE M.DATE_DEL IS NULL AND M.OU_ID = :V$OBJ_ID AND M.DATE_OUT >= :V$YEAR_START -- !!! учитывать перешедших AND M.GROUP_TYPE_ID = 9
      INTO :V$VAL;

      TAG_NAME = 'rows:r:p10';
      VAL = V$VAL;
      SUSPEND;

    END

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PF_STUDENTS_OU (
    I$OBJ_ID BIGINT,
    I$BLOCK_NAME VARCHAR(40),
    I$BLOCK_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(1000))
AS
declare variable V$VAL bigint;
declare variable V$VAL2 bigint;
declare variable V$TEACHERS bigint;
declare variable F float;
declare variable S varchar(1000);
declare variable V$TYPE_ID1 bigint;
declare variable V$TYPE_ID2 bigint;
declare variable V$MID_TYPE bigint;
declare variable V$OBJ_ID bigint;
declare variable V$PARAM_ID bigint;
declare variable V$TYPE bigint;
declare variable V$T bigint;
declare variable V$MASTER_ID bigint;
declare variable V$YEAR_START date;
begin

  -- Сколько всего учителей ?
  SELECT COUNT(DISTINCT L14.OBJ_ID)
  FROM LINKS L14
  JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
  LEFT JOIN VALD V74 ON V74.OBJ_ID = L14.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
  JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
  JOIN VALL V64 ON V64.OBJ_ID = LP13.PARENT_ID AND V64.PARAM_ID = 64 AND V64.IS_DEL = 0 AND V64.LISTVAL_ID = 98
  WHERE L14.PARENT_ID = :I$OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL AND V74.VAL IS NULL
  INTO :V$TEACHERS;

  IF(EXTRACT(MONTH FROM CURRENT_DATE) < 8) THEN V$YEAR_START = '01.09.' || (EXTRACT(YEAR FROM CURRENT_DATE) - 1);
  ELSE V$YEAR_START = '01.09.' || EXTRACT(YEAR FROM CURRENT_DATE);

  EXECUTE PROCEDURE FIX_MOVEMENTS_OU;

  IF(I$BLOCK_NAME IS NULL) THEN
  BEGIN
    -- Оглавление
    TAG_NAME = 'dashboard::json&colon;array';
    VAL = 1;
    SUSPEND;

    SELECT COUNT(DISTINCT M.PERSON_ID)
    FROM PERSON_MOVEMENTS M
    JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
    WHERE M.DATE_DEL IS NULL AND M.DATE_IN <= CURRENT_DATE AND M.DATE_OUT IS NULL -- AND M.GROUP_TYPE_ID = 9
      AND M.OU_ID = :I$OBJ_ID
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'students';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '10';
    SUSPEND;
    TAG_NAME = 'dashboard:r:subtype_id';
    VAL = '';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'user';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#410093';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Количество обучающихся';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'students';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '10';
    SUSPEND;
    TAG_NAME = 'dashboard:r:subtype_id';
    VAL = '';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'percent';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#25D366';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Обучающихся на 1 учителя';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    IF(V$TEACHERS = 0) THEN F = NULL; ELSE F = CAST(V$VAL AS FLOAT) / CAST(V$TEACHERS AS FLOAT);
    VAL = CAST(F AS NUMERIC (18, 1));
    SUSPEND;

    SELECT COUNT(DISTINCT M.PERSON_ID)
    FROM PERSON_MOVEMENTS M
    JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
    JOIN VALL V207 ON V207.OBJ_ID = M.PERSON_ID AND V207.PARAM_ID = 207 AND V207.IS_DEL = 0 AND V207.LISTVAL_ID <> 13289
    WHERE M.DATE_DEL IS NULL AND M.DATE_IN <= CURRENT_DATE AND M.DATE_OUT IS NULL -- AND M.GROUP_TYPE_ID = 9
      AND M.OU_ID = :I$OBJ_ID
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'byovz';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '10';
    SUSPEND;
    TAG_NAME = 'dashboard:r:subtype_id';
    VAL = '207';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'wheelchair';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#410093';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Количество обучающихся с ОВЗ';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

    SELECT COUNT(DISTINCT M.PERSON_ID)
    FROM PERSON_MOVEMENTS M
    JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 256
    JOIN LINKS LP54 ON LP54.OBJ_ID = M.GROUP_ID AND LP54.PARENT_TYPE_ID = 54 AND LP54.DATE_DEL IS NULL
    JOIN LINKS LP400 ON LP400.OBJ_ID = LP54.PARENT_ID AND LP400.PARENT_TYPE_ID = 400 AND LP400.DATE_DEL IS NULL
    JOIN LINKS LP57 ON LP57.OBJ_ID = LP400.PARENT_ID AND LP57.PARENT_TYPE_ID = 57 AND LP57.DATE_DEL IS NULL
    JOIN VALL V2379 ON V2379.OBJ_ID = LP57.PARENT_ID AND V2379.PARAM_ID = 2379 AND V2379.IS_DEL = 0 AND V2379.LISTVAL_ID <> 11187
    WHERE M.DATE_DEL IS NULL AND M.DATE_IN <= CURRENT_DATE AND M.DATE_OUT IS NULL -- AND M.GROUP_TYPE_ID = 256
      AND M.OU_ID = :I$OBJ_ID
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'byadapt';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '10';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'wheelchair';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#410093';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Количество обучающихся на адаптированных ОП';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

    SELECT COUNT(DISTINCT M.PERSON_ID)
    FROM PERSON_MOVEMENTS M
    JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
    JOIN VALL V80 ON V80.OBJ_ID = M.PERSON_ID AND V80.PARAM_ID = 80 AND V80.IS_DEL = 0 AND V80.LISTVAL_ID = 5418
    WHERE M.DATE_DEL IS NULL AND M.DATE_IN <= CURRENT_DATE AND M.DATE_OUT IS NULL -- AND M.GROUP_TYPE_ID = 9
      AND M.OU_ID = :I$OBJ_ID
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'byform';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '10';
    SUSPEND;
    TAG_NAME = 'dashboard:r:subtype_id';
    VAL = '80';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'sun';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#410093';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Количество обучающихся очной формы';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

    SELECT COUNT(DISTINCT M.PERSON_ID)
    FROM PERSON_MOVEMENTS M
    JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
    -- !!!
    JOIN LINKS LP8 ON LP8.OBJ_ID = M.GROUP_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
    JOIN LINKS LP7 ON LP7.OBJ_ID = LP8.PARENT_ID AND LP7.PARENT_TYPE_ID = 7 AND LP7.DATE_DEL IS NULL
    JOIN VALL V43 ON V43.OBJ_ID = LP7.PARENT_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0 AND V43.LISTVAL_ID = 22
    WHERE M.DATE_DEL IS NULL AND M.DATE_IN <= CURRENT_DATE AND M.DATE_OUT IS NULL -- AND M.LEVEL_ID = 22 AND M.GROUP_TYPE_ID = 9
      AND M.OU_ID = :I$OBJ_ID
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'bylevel';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '10';
    SUSPEND;
    TAG_NAME = 'dashboard:r:subtype_id';
    VAL = '43';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'user';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#410093';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Количество обучающихся НОО';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

    SELECT COUNT(DISTINCT M.PERSON_ID)
    FROM PERSON_MOVEMENTS M
    JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
    -- !!!
    JOIN LINKS LP8 ON LP8.OBJ_ID = M.GROUP_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
    JOIN LINKS LP7 ON LP7.OBJ_ID = LP8.PARENT_ID AND LP7.PARENT_TYPE_ID = 7 AND LP7.DATE_DEL IS NULL
    JOIN VALL V43 ON V43.OBJ_ID = LP7.PARENT_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0 AND V43.LISTVAL_ID = 26
    WHERE M.DATE_DEL IS NULL AND M.DATE_IN <= CURRENT_DATE AND M.DATE_OUT IS NULL -- AND M.LEVEL_ID = 26 AND M.GROUP_TYPE_ID = 9
      AND M.OU_ID = :I$OBJ_ID
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'bylevel';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '10';
    SUSPEND;
    TAG_NAME = 'dashboard:r:subtype_id';
    VAL = '43';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'user';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#410093';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Количество обучающихся ООО';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

    SELECT COUNT(DISTINCT M.PERSON_ID)
    FROM PERSON_MOVEMENTS M
    JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
    -- !!!
    JOIN LINKS LP8 ON LP8.OBJ_ID = M.GROUP_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
    JOIN LINKS LP7 ON LP7.OBJ_ID = LP8.PARENT_ID AND LP7.PARENT_TYPE_ID = 7 AND LP7.DATE_DEL IS NULL
    JOIN VALL V43 ON V43.OBJ_ID = LP7.PARENT_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0 AND V43.LISTVAL_ID = 27
    WHERE M.DATE_DEL IS NULL AND M.DATE_IN <= CURRENT_DATE AND M.DATE_OUT IS NULL -- AND M.LEVEL_ID = 27 AND M.GROUP_TYPE_ID = 9
      AND M.OU_ID = :I$OBJ_ID
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'bylevel';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '10';
    SUSPEND;
    TAG_NAME = 'dashboard:r:subtype_id';
    VAL = '43';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'user';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#410093';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Количество обучающихся СОО';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

    SELECT COUNT(*)
    FROM LINKS L7
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
    WHERE L7.PARENT_ID = :I$OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'classes';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '9';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'sort numeric down';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#34465D';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Количество классов';
    SUSPEND;
    TAG_NAME = 'dashboard:r:hint';
    VAL = 'Рапределение обучающихся по классам';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

    SELECT COUNT(DISTINCT M.PERSON_ID)
    FROM PERSON_MOVEMENTS M
    JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
    WHERE M.DATE_DEL IS NULL AND M.DATE_IN >= :V$YEAR_START -- AND M.GROUP_TYPE_ID = 9
      AND M.OU_ID = :I$OBJ_ID
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'accepted';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '10';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'arrow circle down';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#DF2029';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Принято с начала года';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

    SELECT COUNT(DISTINCT M.PERSON_ID)
    FROM PERSON_MOVEMENTS M
    JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
    WHERE M.DATE_DEL IS NULL AND M.DATE_OUT >= :V$YEAR_START -- !!! учитывать перешедших AND M.GROUP_TYPE_ID = 9
      AND M.OU_ID = :I$OBJ_ID
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'leaved';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '10';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'arrow circle up';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#DF2029';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Выбыло с начала года';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

  END
  ELSE
  BEGIN

    V$TYPE_ID1 = 10;
    V$TYPE = 10;
    TAG_NAME = 'has_caption';
    VAL = 0;
    SUSPEND;

    TAG_NAME = 'title';
    IF(I$BLOCK_NAME = 'students') THEN VAL = 'Распределение обучающихся';
    ELSE IF(I$BLOCK_NAME = 'byovz') THEN VAL = 'Обучающиеся по ОВЗ';
    ELSE IF(I$BLOCK_NAME = 'byadapt') THEN VAL = 'Обучающиеся по адаптированным ОП';
    ELSE IF(I$BLOCK_NAME = 'byform') THEN VAL = 'Обучающиеся по форме обучения';
    ELSE IF(I$BLOCK_NAME = 'bylevel') THEN VAL = 'Обучающиеся по ступеням обучения';
    ELSE IF(I$BLOCK_NAME = 'classes') THEN VAL = 'Распределение по классам';
    ELSE IF(I$BLOCK_NAME = 'accepted') THEN VAL = 'Распределение зачисленных';
    ELSE IF(I$BLOCK_NAME = 'leaved') THEN VAL = 'Распределение выбывших';
    ELSE VAL = '???';
    SUSPEND;

    TAG_NAME = 'columns::json&colon;array';
    VAL = 1;
    SUSPEND;
      TAG_NAME = 'columns:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'columns:r:type_id';
      VAL = 10;
      SUSPEND;
      TAG_NAME = 'columns:r:param_id';
      VAL = 0;
      SUSPEND;
      TAG_NAME = 'columns:r:type';
      VAL = 8;
      SUSPEND;
      TAG_NAME = 'columns:r:name';
      IF(I$BLOCK_NAME = 'students') THEN VAL = 'Этап обучения';
      ELSE IF(I$BLOCK_NAME = 'byovz') THEN VAL = 'Вид ОВЗ';
      ELSE IF(I$BLOCK_NAME = 'byadapt') THEN VAL = 'Адаптированность';
      ELSE IF(I$BLOCK_NAME = 'byform') THEN VAL = 'Форма обучения';
      ELSE IF(I$BLOCK_NAME = 'bylevel') THEN VAL = 'Ступень обучения';
      ELSE IF(I$BLOCK_NAME = 'classes') THEN VAL = 'Класс';
      ELSE IF(I$BLOCK_NAME = 'accepted') THEN VAL = 'Класс';
      ELSE IF(I$BLOCK_NAME = 'leaved') THEN VAL = 'Класс';
      ELSE VAL = '???';
      SUSPEND;
      TAG_NAME = 'columns:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'columns:r:type_id';
      VAL = 10;
      SUSPEND;
      TAG_NAME = 'columns:r:param_id';
      VAL = 1;
      SUSPEND;
      TAG_NAME = 'columns:r:type';
      VAL = 1;
      SUSPEND;
      TAG_NAME = 'columns:r:name';
      VAL = 'Количество обучающихся';
      SUSPEND;

    TAG_NAME = 'rows::json&colon;array';
    VAL = 1;
    SUSPEND;

    IF(I$BLOCK_NAME = 'students') THEN
      -- По параллелям
      FOR
        SELECT LV.SORT_ORDER, R.VAL, COUNT(DISTINCT M.PERSON_ID)
        FROM PERSON_MOVEMENTS M
        JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
        JOIN LINKS LP8 ON LP8.OBJ_ID = M.GROUP_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
        JOIN VALL V49 ON V49.OBJ_ID = LP8.PARENT_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
        JOIN LINKS LP7 ON LP7.OBJ_ID = LP8.PARENT_ID AND LP7.PARENT_TYPE_ID = 7 AND LP7.DATE_DEL IS NULL
        JOIN VALL V43 ON V43.OBJ_ID = LP7.PARENT_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0
        JOIN LISTVALS LV ON LV.LISTVAL_ID = V49.LISTVAL_ID
        JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
        WHERE M.DATE_DEL IS NULL AND M.DATE_IN <= CURRENT_DATE AND M.DATE_OUT IS NULL -- AND M.GROUP_TYPE_ID = 9
          AND M.OU_ID = :I$OBJ_ID
        GROUP BY 1, 2
        ORDER BY 1
        INTO :V$OBJ_ID, :S, :V$VAL
      DO
      BEGIN
        TAG_NAME = 'rows:r';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'rows:r:id';
        VAL = V$OBJ_ID;
        SUSPEND;
        TAG_NAME = 'rows:r:type_id';
        VAL = V$TYPE;
        SUSPEND;
        TAG_NAME = 'rows:r:p0';
        VAL = S;
        SUSPEND;
        TAG_NAME = 'rows:r:p1';
        VAL = V$VAL;
        SUSPEND;
      END
    ELSE IF(I$BLOCK_NAME = 'byovz') THEN
      FOR
        SELECT LV.SORT_ORDER, R.VAL, COUNT(DISTINCT M.PERSON_ID)
        FROM PERSON_MOVEMENTS M
        JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
        JOIN LINKS LP8 ON LP8.OBJ_ID = M.GROUP_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
        JOIN VALL V49 ON V49.OBJ_ID = LP8.PARENT_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
        JOIN LINKS LP7 ON LP7.OBJ_ID = LP8.PARENT_ID AND LP7.PARENT_TYPE_ID = 7 AND LP7.DATE_DEL IS NULL
        JOIN VALL V43 ON V43.OBJ_ID = LP7.PARENT_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0
        JOIN VALL V207 ON V207.OBJ_ID = M.PERSON_ID AND V207.PARAM_ID = 207 AND V207.IS_DEL = 0
        JOIN LISTVALS LV ON LV.LISTVAL_ID = V207.LISTVAL_ID
        JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
        WHERE M.DATE_DEL IS NULL AND M.DATE_IN <= CURRENT_DATE AND M.DATE_OUT IS NULL -- AND M.GROUP_TYPE_ID = 9
          AND M.OU_ID = :I$OBJ_ID
        GROUP BY 1, 2
        ORDER BY 1
        INTO :V$OBJ_ID, :S, :V$VAL
      DO
      BEGIN
        TAG_NAME = 'rows:r';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'rows:r:id';
        VAL = V$OBJ_ID;
        SUSPEND;
        TAG_NAME = 'rows:r:type_id';
        VAL = V$TYPE;
        SUSPEND;
        TAG_NAME = 'rows:r:p0';
        VAL = S;
        SUSPEND;
        TAG_NAME = 'rows:r:p1';
        VAL = V$VAL;
        SUSPEND;
      END
    ELSE IF(I$BLOCK_NAME = 'byovz') THEN
      begin
      end
    ELSE IF(I$BLOCK_NAME = 'byform') THEN
      FOR
        SELECT LV.SORT_ORDER, R.VAL, COUNT(DISTINCT M.PERSON_ID)
        FROM PERSON_MOVEMENTS M
        JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
        JOIN LINKS LP8 ON LP8.OBJ_ID = M.GROUP_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
        JOIN VALL V49 ON V49.OBJ_ID = LP8.PARENT_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
        JOIN LINKS LP7 ON LP7.OBJ_ID = LP8.PARENT_ID AND LP7.PARENT_TYPE_ID = 7 AND LP7.DATE_DEL IS NULL
        JOIN VALL V43 ON V43.OBJ_ID = LP7.PARENT_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0
        JOIN VALL V80 ON V80.OBJ_ID = M.PERSON_ID AND V80.PARAM_ID = 80 AND V80.IS_DEL = 0
        JOIN LISTVALS LV ON LV.LISTVAL_ID = V80.LISTVAL_ID
        JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
        WHERE M.DATE_DEL IS NULL AND M.DATE_IN <= CURRENT_DATE AND M.DATE_OUT IS NULL -- AND M.GROUP_TYPE_ID = 9
          AND M.OU_ID = :I$OBJ_ID
        GROUP BY 1, 2
        ORDER BY 1
        INTO :V$OBJ_ID, :S, :V$VAL
      DO
      BEGIN
        TAG_NAME = 'rows:r';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'rows:r:id';
        VAL = V$OBJ_ID;
        SUSPEND;
        TAG_NAME = 'rows:r:type_id';
        VAL = V$TYPE;
        SUSPEND;
        TAG_NAME = 'rows:r:p0';
        VAL = S;
        SUSPEND;
        TAG_NAME = 'rows:r:p1';
        VAL = V$VAL;
        SUSPEND;
      END
    ELSE IF(I$BLOCK_NAME = 'bylevel') THEN
      FOR
        SELECT LV.SORT_ORDER, R.VAL, COUNT(DISTINCT M.PERSON_ID)
        FROM PERSON_MOVEMENTS M
        JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
        JOIN LINKS LP8 ON LP8.OBJ_ID = M.GROUP_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
        JOIN VALL V49 ON V49.OBJ_ID = LP8.PARENT_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
        JOIN LINKS LP7 ON LP7.OBJ_ID = LP8.PARENT_ID AND LP7.PARENT_TYPE_ID = 7 AND LP7.DATE_DEL IS NULL
        JOIN VALL V43 ON V43.OBJ_ID = LP7.PARENT_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0
        JOIN LISTVALS LV ON LV.LISTVAL_ID = V43.LISTVAL_ID
        JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
        WHERE M.DATE_DEL IS NULL AND M.DATE_IN <= CURRENT_DATE AND M.DATE_OUT IS NULL -- AND M.GROUP_TYPE_ID = 9
          AND M.OU_ID = :I$OBJ_ID
        GROUP BY 1, 2
        ORDER BY 1
        INTO :V$OBJ_ID, :S, :V$VAL
      DO
      BEGIN
        TAG_NAME = 'rows:r';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'rows:r:id';
        VAL = V$OBJ_ID;
        SUSPEND;
        TAG_NAME = 'rows:r:type_id';
        VAL = V$TYPE;
        SUSPEND;
        TAG_NAME = 'rows:r:p0';
        VAL = S;
        SUSPEND;
        TAG_NAME = 'rows:r:p1';
        VAL = V$VAL;
        SUSPEND;
      END
    ELSE IF(I$BLOCK_NAME = 'classes') THEN
      FOR
        SELECT LV.SORT_ORDER, C.CAPTION, COUNT(DISTINCT M.PERSON_ID)
        FROM PERSON_MOVEMENTS M
        JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
        JOIN LINKS LP8 ON LP8.OBJ_ID = M.GROUP_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
        JOIN VALL V49 ON V49.OBJ_ID = LP8.PARENT_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
        JOIN LINKS LP7 ON LP7.OBJ_ID = LP8.PARENT_ID AND LP7.PARENT_TYPE_ID = 7 AND LP7.DATE_DEL IS NULL
        JOIN VALL V43 ON V43.OBJ_ID = LP7.PARENT_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0
        JOIN LISTVALS LV ON LV.LISTVAL_ID = V49.LISTVAL_ID
        LEFT JOIN OBJECT_CAPTION_GET(M.GROUP_ID) C ON 1 = 1
        WHERE M.DATE_DEL IS NULL AND M.DATE_IN <= CURRENT_DATE AND M.DATE_OUT IS NULL -- AND M.GROUP_TYPE_ID = 9
          AND M.OU_ID = :I$OBJ_ID
        GROUP BY 1, 2
        ORDER BY 1, 2
        INTO :V$OBJ_ID, :S, :V$VAL
      DO
      BEGIN
        TAG_NAME = 'rows:r';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'rows:r:id';
        VAL = V$OBJ_ID;
        SUSPEND;
        TAG_NAME = 'rows:r:type_id';
        VAL = V$TYPE;
        SUSPEND;
        TAG_NAME = 'rows:r:p0';
        VAL = S;
        SUSPEND;
        TAG_NAME = 'rows:r:p1';
        VAL = V$VAL;
        SUSPEND;
      END
    ELSE IF(I$BLOCK_NAME = 'accepted') THEN
      -- Распределение по параллелям
      FOR
        SELECT M.STAGE_ID, COUNT(DISTINCT M.PERSON_ID)
        FROM PERSON_MOVEMENTS M
        JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
        WHERE M.DATE_DEL IS NULL AND M.DATE_IN >= :V$YEAR_START -- AND M.GROUP_TYPE_ID = 9
          AND M.OU_ID = :I$OBJ_ID
        GROUP BY 1
        ORDER BY 1
        INTO :V$OBJ_ID, :V$VAL
      DO
      BEGIN
        TAG_NAME = 'rows:r';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'rows:r:id';
        VAL = V$OBJ_ID;
        SUSPEND;
        TAG_NAME = 'rows:r:type_id';
        VAL = V$TYPE;
        SUSPEND;
        TAG_NAME = 'rows:r:p0';
        VAL = (SELECT VAL FROM LISTVAL_TEXT(:V$OBJ_ID));
        SUSPEND;
        TAG_NAME = 'rows:r:p1';
        VAL = V$VAL;
        SUSPEND;
      END
    ELSE IF(I$BLOCK_NAME = 'leaved') THEN
      -- Распределение по параллелям
      FOR
        SELECT M.STAGE_ID, COUNT(DISTINCT M.PERSON_ID)
        FROM PERSON_MOVEMENTS M
        JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
        WHERE M.DATE_DEL IS NULL AND M.DATE_OUT >= :V$YEAR_START -- !!! учитывать перешедших AND M.GROUP_TYPE_ID = 9
          AND M.OU_ID = :I$OBJ_ID
        GROUP BY 1
        ORDER BY 1
        INTO :V$OBJ_ID, :V$VAL
      DO
      BEGIN
        TAG_NAME = 'rows:r';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'rows:r:id';
        VAL = V$OBJ_ID;
        SUSPEND;
        TAG_NAME = 'rows:r:type_id';
        VAL = V$TYPE;
        SUSPEND;
        TAG_NAME = 'rows:r:p0';
        VAL = (SELECT VAL FROM LISTVAL_TEXT(:V$OBJ_ID));
        SUSPEND;
        TAG_NAME = 'rows:r:p1';
        VAL = V$VAL;
        SUSPEND;
      END

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PF_STUDENTS_RGN (
    I$OBJ_ID BIGINT,
    I$BLOCK_NAME VARCHAR(40),
    I$BLOCK_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(1000))
AS
declare variable V$VAL bigint;
declare variable V$VAL2 bigint;
declare variable V$TEACHERS bigint;
declare variable F float;
declare variable S varchar(1000);
declare variable V$TYPE_ID1 bigint;
declare variable V$TYPE_ID2 bigint;
declare variable V$MID_TYPE bigint;
declare variable V$OBJ_ID bigint;
declare variable V$PARAM_ID bigint;
declare variable V$TYPE bigint;
declare variable V$T bigint;
declare variable V$MASTER_ID bigint;
declare variable V$YEAR_START date;
begin

  IF(EXTRACT(MONTH FROM CURRENT_DATE) < 8) THEN V$YEAR_START = '01.09.' || (EXTRACT(YEAR FROM CURRENT_DATE) - 1);
  ELSE V$YEAR_START = '01.09.' || EXTRACT(YEAR FROM CURRENT_DATE);

  IF(I$BLOCK_NAME IS NULL) THEN
  BEGIN
    -- Оглавление
    TAG_NAME = 'dashboard::json&colon;array';
    VAL = 1;
    SUSPEND;

    -- Сколько всего учителей ?
    SELECT COUNT(DISTINCT L14.OBJ_ID)
    FROM LINKS L111
    JOIN LINKS L2 ON L2.PARENT_ID = L111.OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
    JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L14.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
    JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
    JOIN VALL V64 ON V64.OBJ_ID = LP13.PARENT_ID AND V64.PARAM_ID = 64 AND V64.IS_DEL = 0 AND V64.LISTVAL_ID = 98
    WHERE L111.PARENT_ID = :I$OBJ_ID AND L111.OBJ_TYPE_ID = 111 AND L111.DATE_DEL IS NULL AND V74.VAL IS NULL
    INTO :V$TEACHERS;

    SELECT COUNT(DISTINCT M.PERSON_ID)
    FROM PERSON_MOVEMENTS M
    JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
    WHERE M.DATE_DEL IS NULL AND M.DATE_IN <= CURRENT_DATE AND M.DATE_OUT IS NULL -- AND M.GROUP_TYPE_ID = 9
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'students';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '10';
    SUSPEND;
    TAG_NAME = 'dashboard:r:subtype_id';
    VAL = '';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'user';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#410093';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Количество обучающихся';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

    -- Сколько классов в городе ?
    SELECT COUNT(DISTINCT M.GROUP_ID)
    FROM PERSON_MOVEMENTS M
    JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
    JOIN VALL V80 ON V80.OBJ_ID = M.PERSON_ID AND V80.PARAM_ID = 80 AND V80.IS_DEL = 0 AND V80.LISTVAL_ID = 5418
    WHERE M.DATE_DEL IS NULL AND M.DATE_IN <= CURRENT_DATE AND M.DATE_OUT IS NULL -- AND M.GROUP_TYPE_ID = 9
    INTO :V$VAL2;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'classfill';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '10';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'clone outline';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#410093';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Средняя наполняемость классов';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    IF(V$TEACHERS = 0) THEN F = NULL; ELSE F = CAST(V$VAL AS FLOAT) / CAST(V$VAL2 AS FLOAT);
    VAL = CAST(F AS NUMERIC (18, 2));
    SUSPEND;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'students';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '10';
    SUSPEND;
    TAG_NAME = 'dashboard:r:subtype_id';
    VAL = '';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'percent';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#25D366';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Обучающихся на одного учителя';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    IF(V$TEACHERS = 0) THEN F = NULL; ELSE F = CAST(V$VAL AS FLOAT) / CAST(V$TEACHERS AS FLOAT);
    VAL = CAST(F AS NUMERIC (18, 1));
    SUSPEND;

    SELECT COUNT(DISTINCT M.PERSON_ID)
    FROM PERSON_MOVEMENTS M
    JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
    JOIN VALL V207 ON V207.OBJ_ID = M.PERSON_ID AND V207.PARAM_ID = 207 AND V207.IS_DEL = 0 AND V207.LISTVAL_ID <> 13289
    WHERE M.DATE_DEL IS NULL AND M.DATE_IN <= CURRENT_DATE AND M.DATE_OUT IS NULL -- AND M.GROUP_TYPE_ID = 9
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'byovz';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '10';
    SUSPEND;
    TAG_NAME = 'dashboard:r:subtype_id';
    VAL = '207';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'wheelchair';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#410093';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Количество обучающихся с ОВЗ';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

    SELECT COUNT(DISTINCT M.PERSON_ID)
    FROM PERSON_MOVEMENTS M
    JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
    JOIN VALL V80 ON V80.OBJ_ID = M.PERSON_ID AND V80.PARAM_ID = 80 AND V80.IS_DEL = 0 AND V80.LISTVAL_ID = 5418
    WHERE M.DATE_DEL IS NULL AND M.DATE_IN <= CURRENT_DATE AND M.DATE_OUT IS NULL -- AND M.GROUP_TYPE_ID = 9
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'byform';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '10';
    SUSPEND;
    TAG_NAME = 'dashboard:r:subtype_id';
    VAL = '80';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'sun';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#410093';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Количество обучающихся очной формы';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

    SELECT COUNT(DISTINCT M.PERSON_ID)
    FROM PERSON_MOVEMENTS M
    JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
    -- !!!
    JOIN LINKS LP8 ON LP8.OBJ_ID = M.GROUP_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
    JOIN LINKS LP7 ON LP7.OBJ_ID = LP8.PARENT_ID AND LP7.PARENT_TYPE_ID = 7 AND LP7.DATE_DEL IS NULL
    JOIN VALL V43 ON V43.OBJ_ID = LP7.PARENT_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0 AND V43.LISTVAL_ID = 22
    WHERE M.DATE_DEL IS NULL AND M.DATE_IN <= CURRENT_DATE AND M.DATE_OUT IS NULL -- AND M.LEVEL_ID = 22 AND M.GROUP_TYPE_ID = 9
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'bylevel';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '10';
    SUSPEND;
    TAG_NAME = 'dashboard:r:subtype_id';
    VAL = '43';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'user';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#410093';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Количество обучающихся НОО';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

    SELECT COUNT(DISTINCT M.PERSON_ID)
    FROM PERSON_MOVEMENTS M
    JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
    -- !!!
    JOIN LINKS LP8 ON LP8.OBJ_ID = M.GROUP_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
    JOIN LINKS LP7 ON LP7.OBJ_ID = LP8.PARENT_ID AND LP7.PARENT_TYPE_ID = 7 AND LP7.DATE_DEL IS NULL
    JOIN VALL V43 ON V43.OBJ_ID = LP7.PARENT_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0 AND V43.LISTVAL_ID = 26
    WHERE M.DATE_DEL IS NULL AND M.DATE_IN <= CURRENT_DATE AND M.DATE_OUT IS NULL -- AND M.LEVEL_ID = 26 AND M.GROUP_TYPE_ID = 9
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'bylevel';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '10';
    SUSPEND;
    TAG_NAME = 'dashboard:r:subtype_id';
    VAL = '43';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'user';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#410093';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Количество обучающихся ООО';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

    SELECT COUNT(DISTINCT M.PERSON_ID)
    FROM PERSON_MOVEMENTS M
    JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
    -- !!!
    JOIN LINKS LP8 ON LP8.OBJ_ID = M.GROUP_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
    JOIN LINKS LP7 ON LP7.OBJ_ID = LP8.PARENT_ID AND LP7.PARENT_TYPE_ID = 7 AND LP7.DATE_DEL IS NULL
    JOIN VALL V43 ON V43.OBJ_ID = LP7.PARENT_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0 AND V43.LISTVAL_ID = 27
    WHERE M.DATE_DEL IS NULL AND M.DATE_IN <= CURRENT_DATE AND M.DATE_OUT IS NULL -- AND M.LEVEL_ID = 27 AND M.GROUP_TYPE_ID = 9
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'bylevel';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '10';
    SUSPEND;
    TAG_NAME = 'dashboard:r:subtype_id';
    VAL = '43';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'user';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#410093';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Количество обучающихся СОО';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

    SELECT COUNT(*)
    FROM LINKS L111
    JOIN LINKS L2 ON L2.PARENT_ID = L111.OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
    WHERE L111.PARENT_ID = :I$OBJ_ID AND L111.OBJ_TYPE_ID = 111 AND L111.DATE_DEL IS NULL
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'classes';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '9';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'sort numeric down';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#34465D';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Количество классов';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

    SELECT COUNT(DISTINCT M.PERSON_ID)
    FROM PERSON_MOVEMENTS M
    JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
    WHERE M.DATE_DEL IS NULL AND M.DATE_IN >= :V$YEAR_START -- AND M.GROUP_TYPE_ID = 9
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'accepted';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '10';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'arrow circle down';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#DF2029';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Принято с начала года';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

    SELECT COUNT(DISTINCT M.PERSON_ID)
    FROM PERSON_MOVEMENTS M
    JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
    WHERE M.DATE_DEL IS NULL AND M.DATE_OUT >= :V$YEAR_START -- !!! учитывать перешедших AND M.GROUP_TYPE_ID = 9
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'leaved';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '10';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'arrow circle up';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#DF2029';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Выбыло с начала года';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

  END
  ELSE
  BEGIN

    -- Чиним ID организации
    EXECUTE PROCEDURE FIX_MOVEMENTS_OU;

    TAG_NAME = 'title';
    VAL = 'Контингент';
    SUSPEND;

    TAG_NAME = 'has_caption';
    VAL = 1;
    SUSPEND;

    TAG_NAME = 'columns::json&colon;array';
    VAL = 1;
    SUSPEND;

    TAG_NAME = 'columns:r'; VAL = NULL; SUSPEND;
    TAG_NAME = 'columns:r:type_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:param_id'; VAL = '0'; SUSPEND;
    TAG_NAME = 'columns:r:type'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:name'; VAL = 'Количество ОУ'; SUSPEND;

    TAG_NAME = 'columns:r'; VAL = NULL; SUSPEND;
    TAG_NAME = 'columns:r:type_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:param_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:type'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:name'; VAL = 'Количество обучающихся'; SUSPEND;

    TAG_NAME = 'columns:r'; VAL = NULL; SUSPEND;
    TAG_NAME = 'columns:r:type_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:param_id'; VAL = '2'; SUSPEND;
    TAG_NAME = 'columns:r:type'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:name'; VAL = 'Обучающихся на 1 учителя'; SUSPEND;

    TAG_NAME = 'columns:r'; VAL = NULL; SUSPEND;
    TAG_NAME = 'columns:r:type_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:param_id'; VAL = '3'; SUSPEND;
    TAG_NAME = 'columns:r:type'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:name'; VAL = 'Количество обучающихся с ОВЗ'; SUSPEND;

    TAG_NAME = 'columns:r'; VAL = NULL; SUSPEND;
    TAG_NAME = 'columns:r:type_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:param_id'; VAL = '4'; SUSPEND;
    TAG_NAME = 'columns:r:type'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:name'; VAL = 'Количество обучающихся очной формы'; SUSPEND;

    TAG_NAME = 'columns:r'; VAL = NULL; SUSPEND;
    TAG_NAME = 'columns:r:type_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:param_id'; VAL = '5'; SUSPEND;
    TAG_NAME = 'columns:r:type'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:name'; VAL = 'Количество обучающихся НОО'; SUSPEND;

    TAG_NAME = 'columns:r'; VAL = NULL; SUSPEND;
    TAG_NAME = 'columns:r:type_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:param_id'; VAL = '6'; SUSPEND;
    TAG_NAME = 'columns:r:type'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:name'; VAL = 'Количество обучающихся ООО'; SUSPEND;

    TAG_NAME = 'columns:r'; VAL = NULL; SUSPEND;
    TAG_NAME = 'columns:r:type_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:param_id'; VAL = '7'; SUSPEND;
    TAG_NAME = 'columns:r:type'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:name'; VAL = 'Количество обучающихся СОО'; SUSPEND;

    TAG_NAME = 'columns:r'; VAL = NULL; SUSPEND;
    TAG_NAME = 'columns:r:type_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:param_id'; VAL = '8'; SUSPEND;
    TAG_NAME = 'columns:r:type'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:name'; VAL = 'Количество классов'; SUSPEND;

    TAG_NAME = 'columns:r'; VAL = NULL; SUSPEND;
    TAG_NAME = 'columns:r:type_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:param_id'; VAL = '9'; SUSPEND;
    TAG_NAME = 'columns:r:type'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:name'; VAL = 'Принято с начала года'; SUSPEND;

    TAG_NAME = 'columns:r'; VAL = NULL; SUSPEND;
    TAG_NAME = 'columns:r:type_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:param_id'; VAL = '9'; SUSPEND;
    TAG_NAME = 'columns:r:type'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:name'; VAL = 'Выбыло с начала года'; SUSPEND;

    -- Развертка по районам
    TAG_NAME = 'rows::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT L111.OBJ_ID, L111.OBJ_TYPE_ID, C.CAPTION
      FROM LINKS L111
      LEFT JOIN OBJECT_CAPTION_GET(L111.OBJ_ID) C ON 1 = 1
      WHERE L111.PARENT_ID = :I$OBJ_ID AND L111.OBJ_TYPE_ID = 111 AND L111.DATE_DEL IS NULL
      ORDER BY 3
      INTO :V$OBJ_ID, :V$TYPE, :S
    DO
    BEGIN
      TAG_NAME = 'rows:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'rows:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'rows:r:type_id';
      VAL = '1';
      SUSPEND;
      TAG_NAME = 'rows:r:caption';
      VAL = S;
      SUSPEND;

      -- Сколько всего учителей ?
      SELECT COUNT(DISTINCT L14.OBJ_ID)
      FROM LINKS L2
      JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
      JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
      LEFT JOIN VALD V74 ON V74.OBJ_ID = L14.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
      JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
      JOIN VALL V64 ON V64.OBJ_ID = LP13.PARENT_ID AND V64.PARAM_ID = 64 AND V64.IS_DEL = 0 AND V64.LISTVAL_ID = 98
      WHERE L2.PARENT_ID = :V$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND V74.VAL IS NULL
      INTO :V$TEACHERS;

      SELECT COUNT(*)
      FROM LINKS L2
      WHERE L2.PARENT_ID = :V$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      INTO :V$VAL;

      TAG_NAME = 'rows:r:p0';
      VAL = V$VAL;
      SUSPEND;

      SELECT COUNT(DISTINCT M.PERSON_ID)
      FROM LINKS L2
      JOIN PERSON_MOVEMENTS M ON M.DATE_DEL IS NULL AND M.OU_ID = L2.OBJ_ID AND M.DATE_IN <= CURRENT_DATE AND M.DATE_OUT IS NULL -- AND M.GROUP_TYPE_ID = 9
      JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
      WHERE L2.PARENT_ID = :V$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      INTO :V$VAL;

      TAG_NAME = 'rows:r:p1';
      VAL = V$VAL;
      SUSPEND;

      TAG_NAME = 'rows:r:p2';
      IF(V$TEACHERS = 0) THEN F = NULL; ELSE F = CAST(V$VAL AS FLOAT) / CAST(V$TEACHERS AS FLOAT);
      VAL = CAST(F AS NUMERIC (18, 1));
      SUSPEND;

      SELECT COUNT(DISTINCT M.PERSON_ID)
      FROM LINKS L2
      JOIN PERSON_MOVEMENTS M ON M.DATE_DEL IS NULL AND M.OU_ID = L2.OBJ_ID AND M.DATE_IN <= CURRENT_DATE AND M.DATE_OUT IS NULL -- AND M.GROUP_TYPE_ID = 9
      JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
      JOIN VALL V207 ON V207.OBJ_ID = M.PERSON_ID AND V207.PARAM_ID = 207 AND V207.IS_DEL = 0 AND V207.LISTVAL_ID <> 13289
      WHERE L2.PARENT_ID = :V$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      INTO :V$VAL;

      TAG_NAME = 'rows:r:p3';
      VAL = V$VAL;
      SUSPEND;

      SELECT COUNT(DISTINCT M.PERSON_ID)
      FROM LINKS L2
      JOIN PERSON_MOVEMENTS M ON M.DATE_DEL IS NULL AND M.OU_ID = L2.OBJ_ID AND M.DATE_IN <= CURRENT_DATE AND M.DATE_OUT IS NULL -- AND M.GROUP_TYPE_ID = 9
      JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
      JOIN VALL V80 ON V80.OBJ_ID = M.PERSON_ID AND V80.PARAM_ID = 80 AND V80.IS_DEL = 0 AND V80.LISTVAL_ID = 5418
      WHERE L2.PARENT_ID = :V$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      INTO :V$VAL;

      TAG_NAME = 'rows:r:p4';
      VAL = V$VAL;
      SUSPEND;

      SELECT COUNT(DISTINCT M.PERSON_ID)
      FROM LINKS L2
      JOIN PERSON_MOVEMENTS M ON M.DATE_DEL IS NULL AND M.OU_ID = L2.OBJ_ID AND M.DATE_IN <= CURRENT_DATE AND M.DATE_OUT IS NULL -- AND M.LEVEL_ID = 22 AND M.GROUP_TYPE_ID = 9
      JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
      -- !!!
      JOIN LINKS LP8 ON LP8.OBJ_ID = M.GROUP_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
      JOIN LINKS LP7 ON LP7.OBJ_ID = LP8.PARENT_ID AND LP7.PARENT_TYPE_ID = 7 AND LP7.DATE_DEL IS NULL
      JOIN VALL V43 ON V43.OBJ_ID = LP7.PARENT_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0 AND V43.LISTVAL_ID = 22
      WHERE L2.PARENT_ID = :V$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      INTO :V$VAL;

      TAG_NAME = 'rows:r:p5';
      VAL = V$VAL;
      SUSPEND;

      SELECT COUNT(DISTINCT M.PERSON_ID)
      FROM LINKS L2
      JOIN PERSON_MOVEMENTS M ON M.DATE_DEL IS NULL AND M.OU_ID = L2.OBJ_ID AND M.DATE_IN <= CURRENT_DATE AND M.DATE_OUT IS NULL -- AND M.LEVEL_ID = 26 AND M.GROUP_TYPE_ID = 9
      JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
      -- !!!
      JOIN LINKS LP8 ON LP8.OBJ_ID = M.GROUP_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
      JOIN LINKS LP7 ON LP7.OBJ_ID = LP8.PARENT_ID AND LP7.PARENT_TYPE_ID = 7 AND LP7.DATE_DEL IS NULL
      JOIN VALL V43 ON V43.OBJ_ID = LP7.PARENT_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0 AND V43.LISTVAL_ID = 26
      WHERE L2.PARENT_ID = :V$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      INTO :V$VAL;

      TAG_NAME = 'rows:r:p6';
      VAL = V$VAL;
      SUSPEND;

      SELECT COUNT(DISTINCT M.PERSON_ID)
      FROM LINKS L2
      JOIN PERSON_MOVEMENTS M ON M.DATE_DEL IS NULL AND M.OU_ID = L2.OBJ_ID AND M.DATE_IN <= CURRENT_DATE AND M.DATE_OUT IS NULL -- AND M.LEVEL_ID = 27 AND M.GROUP_TYPE_ID = 9
      JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
      -- !!!
      JOIN LINKS LP8 ON LP8.OBJ_ID = M.GROUP_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
      JOIN LINKS LP7 ON LP7.OBJ_ID = LP8.PARENT_ID AND LP7.PARENT_TYPE_ID = 7 AND LP7.DATE_DEL IS NULL
      JOIN VALL V43 ON V43.OBJ_ID = LP7.PARENT_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0 AND V43.LISTVAL_ID = 27
      WHERE L2.PARENT_ID = :V$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      INTO :V$VAL;

      TAG_NAME = 'rows:r:p7';
      VAL = V$VAL;
      SUSPEND;

      SELECT COUNT(*)
      FROM LINKS L2
      JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
      JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
      WHERE L2.PARENT_ID = :V$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      INTO :V$VAL;

      TAG_NAME = 'rows:r:p8';
      VAL = V$VAL;
      SUSPEND;

      SELECT COUNT(DISTINCT M.PERSON_ID)
      FROM LINKS L2
      JOIN PERSON_MOVEMENTS M ON M.DATE_DEL IS NULL AND M.OU_ID = L2.OBJ_ID AND M.DATE_IN >= :V$YEAR_START -- AND M.GROUP_TYPE_ID = 9
      JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
      WHERE L2.PARENT_ID = :V$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      INTO :V$VAL;

      TAG_NAME = 'rows:r:p9';
      VAL = V$VAL;
      SUSPEND;

      SELECT COUNT(DISTINCT M.PERSON_ID)
      FROM LINKS L2
      JOIN PERSON_MOVEMENTS M ON M.DATE_DEL IS NULL AND M.OU_ID = L2.OBJ_ID AND M.DATE_OUT >= :V$YEAR_START -- !!! учитывать перешедших AND M.GROUP_TYPE_ID = 9
      JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
      WHERE L2.PARENT_ID = :V$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      INTO :V$VAL;

      TAG_NAME = 'rows:r:p10';
      VAL = V$VAL;
      SUSPEND;

    END

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PF_STUFF (
    I$OBJ_ID BIGINT,
    I$BLOCK_NAME VARCHAR(40),
    I$BLOCK_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(1000))
AS
declare variable V$TYPE_ID bigint;
begin

  SELECT TYPE_ID
  FROM OBJECTS
  WHERE OBJ_ID = :I$OBJ_ID
  INTO :V$TYPE_ID;

  IF(V$TYPE_ID = 2) THEN
  BEGIN
    FOR
      SELECT D.TAG_NAME, D.VAL
      FROM PF_STUFF_OU(:I$OBJ_ID, :I$BLOCK_NAME, :I$BLOCK_ID, :I$USER_ID) D
      INTO :TAG_NAME, :VAL
    DO
    BEGIN
      SUSPEND;
    END
  END
  ELSE IF(V$TYPE_ID = 111) THEN
  BEGIN
    FOR
      SELECT D.TAG_NAME, D.VAL
      FROM PF_STUFF_DIST(:I$OBJ_ID, :I$BLOCK_NAME, :I$BLOCK_ID, :I$USER_ID) D
      INTO :TAG_NAME, :VAL
    DO
    BEGIN
      SUSPEND;
    END
  END
  ELSE IF(V$TYPE_ID = 112) THEN
  BEGIN
    FOR
      SELECT D.TAG_NAME, D.VAL
      FROM PF_STUFF_RGN(:I$OBJ_ID, :I$BLOCK_NAME, :I$BLOCK_ID, :I$USER_ID) D
      INTO :TAG_NAME, :VAL
    DO
    BEGIN
      SUSPEND;
    END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PF_STUFF_DIST (
    I$OBJ_ID BIGINT,
    I$BLOCK_NAME VARCHAR(40),
    I$BLOCK_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(1000))
AS
declare variable V$STUDENTS bigint;
declare variable V$YEAR_START date;
declare variable V$VAL bigint;
declare variable V$VAL2 bigint;
declare variable F double precision;
declare variable S varchar(1000);
declare variable V$TYPE_ID1 bigint;
declare variable V$TYPE_ID2 bigint;
declare variable V$MID_TYPE bigint;
declare variable V$OBJ_ID bigint;
declare variable V$PARAM_ID bigint;
declare variable V$TYPE bigint;
declare variable V$T bigint;
declare variable V$MASTER_ID bigint;
begin

  IF(EXTRACT(MONTH FROM CURRENT_DATE) < 8) THEN V$YEAR_START = '01.09.' || (EXTRACT(YEAR FROM CURRENT_DATE) - 1);
  ELSE V$YEAR_START = '01.09.' || EXTRACT(YEAR FROM CURRENT_DATE);

  IF(I$BLOCK_NAME IS NULL) THEN
  BEGIN
    -- Оглавление
    TAG_NAME = 'dashboard::json&colon;array';
    VAL = 1;
    SUSPEND;

    -- Сколько всего учеников ?
    SELECT COUNT(*)
    FROM LINKS L2
    JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
    JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    WHERE L2.PARENT_ID = :I$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :V$STUDENTS;

    SELECT COUNT(DISTINCT L14.OBJ_ID)
    FROM LINKS L2
    JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
    JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L14.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
    JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
    WHERE L2.PARENT_ID = :I$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND V74.VAL IS NULL
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'stuff';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '14';
    SUSPEND;
    TAG_NAME = 'dashboard:r:subtype_id';
    VAL = '';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'user';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#410093';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Количество сотрудников';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

    SELECT COUNT(DISTINCT L14.OBJ_ID)
    FROM LINKS L2
    JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
    JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L14.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
    JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
    JOIN VALL V64 ON V64.OBJ_ID = LP13.PARENT_ID AND V64.PARAM_ID = 64 AND V64.IS_DEL = 0 AND V64.LISTVAL_ID = 56
    WHERE L2.PARENT_ID = :I$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND V74.VAL IS NULL
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'stuff';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '14';
    SUSPEND;
    TAG_NAME = 'dashboard:r:subtype_id';
    VAL = '56';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'user';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#410093';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Количество руководителей';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

    SELECT COUNT(DISTINCT L14.OBJ_ID)
    FROM LINKS L2
    JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
    JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L14.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
    JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
    JOIN VALL V64 ON V64.OBJ_ID = LP13.PARENT_ID AND V64.PARAM_ID = 64 AND V64.IS_DEL = 0 AND V64.LISTVAL_ID = 113
    WHERE L2.PARENT_ID = :I$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND V74.VAL IS NULL
    INTO :V$VAL2;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'stuff';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '14';
    SUSPEND;
    TAG_NAME = 'dashboard:r:subtype_id';
    VAL = '113';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'user';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#410093';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Количество заместителей, руководителей 2 уровня';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL2;
    SUSPEND;

    -- На одного обучающегося
    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'stuff';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '14';
    SUSPEND;
    TAG_NAME = 'dashboard:r:subtype_id';
    VAL = '988';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'percent';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#25D366';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Руководителей на одного обучающегося';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    IF(V$STUDENTS = 0) THEN F = NULL; ELSE F = CAST((V$VAL + V$VAL2) AS FLOAT) / CAST(V$STUDENTS AS FLOAT);
    VAL = CAST(F AS NUMERIC (18, 3));
    SUSPEND;

    SELECT COUNT(DISTINCT L14.OBJ_ID)
    FROM LINKS L2
    JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
    JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L14.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
    JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
    LEFT JOIN VAL_GET(L14.OBJ_ID, 988) P ON 1 = 1
    WHERE L2.PARENT_ID = :I$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND V74.VAL IS NULL AND P.V = 'Да'
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'stuff';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '14';
    SUSPEND;
    TAG_NAME = 'dashboard:r:subtype_id';
    VAL = '988';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'graduation cap';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#410093';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Количество педагогических работников';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

    -- На одного обучающегося
    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'stuff';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '14';
    SUSPEND;
    TAG_NAME = 'dashboard:r:subtype_id';
    VAL = '988';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'percent';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#25D366';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Педагогических работников на одного обучающегося';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    IF(V$STUDENTS = 0) THEN F = NULL; ELSE F = CAST(V$VAL AS FLOAT) / CAST(V$STUDENTS AS FLOAT);
    VAL = CAST(F AS NUMERIC (18, 3));
    SUSPEND;

    SELECT COUNT(DISTINCT L14.OBJ_ID)
    FROM LINKS L2
    JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
    JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L14.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
    JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
    JOIN VALL V64 ON V64.OBJ_ID = LP13.PARENT_ID AND V64.PARAM_ID = 64 AND V64.IS_DEL = 0 AND V64.LISTVAL_ID = 98
    WHERE L2.PARENT_ID = :I$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND V74.VAL IS NULL
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'stuff';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '14';
    SUSPEND;
    TAG_NAME = 'dashboard:r:subtype_id';
    VAL = '98';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'graduation cap';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#410093';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Количество учителей';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

    -- По возрасту
    SELECT COUNT(DISTINCT L14.OBJ_ID)
    FROM LINKS L2
    JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
    JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L14.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
    JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
    JOIN VALD V241 ON V241.OBJ_ID = L14.OBJ_ID AND V241.PARAM_ID = 241 AND V241.IS_DEL = 0 AND V241.VAL >= DATEADD(-35 YEAR TO CURRENT_DATE)
    WHERE L2.PARENT_ID = :I$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND V74.VAL IS NULL
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'byage';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '14';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'sort amount down';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#34465D';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Сотрудников < 35 лет';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

    -- По образованию
    SELECT COUNT(DISTINCT L14.OBJ_ID)
    FROM LINKS L2
    JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
    JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L14.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
    JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
    JOIN VALL V278 ON V278.OBJ_ID = L14.OBJ_ID AND V278.PARAM_ID = 278 AND V278.IS_DEL = 0 AND V278.LISTVAL_ID IN (620, 3031, 3032)
    WHERE L2.PARENT_ID = :I$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND V74.VAL IS NULL
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'byedu';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '14';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'university';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#34465D';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Сотрудников с высшим образованием';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

    -- По стажу
    SELECT COUNT(DISTINCT L14.OBJ_ID)
    FROM LINKS L2
    JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
    JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L14.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
    JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
    JOIN VALL V64 ON V64.OBJ_ID = LP13.PARENT_ID AND V64.PARAM_ID = 64 AND V64.IS_DEL = 0 AND V64.LISTVAL_ID = 98
    LEFT JOIN VAL_GET(L14.OBJ_ID, 463) V ON 1 = 1
    WHERE L2.PARENT_ID = :I$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND V74.VAL IS NULL AND CAST(V.V AS INTEGER) > 3600
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'bystage';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '14';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'university';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#34465D';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Учителей со стажем > 10 лет';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

    SELECT COUNT(DISTINCT L14.OBJ_ID)
    FROM LINKS L2
    JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
    JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L14.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
    JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
    JOIN VALD V63 ON V63.OBJ_ID = L14.OBJ_ID AND V63.PARAM_ID = 63 AND V63.IS_DEL = 0 AND V63.VAL >= :V$YEAR_START
    WHERE L2.PARENT_ID = :I$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'stuff';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '14';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'arrow circle down';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#DF2029';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Принято с начала года';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

    -- !! Совсем выбывшие ?
    SELECT COUNT(DISTINCT L14.OBJ_ID)
    FROM LINKS L2
    JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
    JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L14.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
    JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
    JOIN VALD V64 ON V64.OBJ_ID = L14.OBJ_ID AND V64.PARAM_ID = 64 AND V64.IS_DEL = 0 AND V64.VAL >= :V$YEAR_START
    WHERE L2.PARENT_ID = :I$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'stuff';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '14';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'arrow circle up';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#DF2029';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Уволено с начала года';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

  END
  ELSE
  BEGIN

    TAG_NAME = 'title';
    VAL = 'Сотрудники';
    SUSPEND;

    TAG_NAME = 'has_caption';
    VAL = 1;
    SUSPEND;

    TAG_NAME = 'columns::json&colon;array';
    VAL = 1;
    SUSPEND;

    TAG_NAME = 'columns:r'; VAL = NULL; SUSPEND;
    TAG_NAME = 'columns:r:type_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:param_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:type'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:name'; VAL = 'Количество сотрудников'; SUSPEND;

    TAG_NAME = 'columns:r'; VAL = NULL; SUSPEND;
    TAG_NAME = 'columns:r:type_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:param_id'; VAL = '2'; SUSPEND;
    TAG_NAME = 'columns:r:type'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:name'; VAL = 'Количество руководителей'; SUSPEND;

    TAG_NAME = 'columns:r'; VAL = NULL; SUSPEND;
    TAG_NAME = 'columns:r:type_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:param_id'; VAL = '3'; SUSPEND;
    TAG_NAME = 'columns:r:type'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:name'; VAL = 'Количество заместителей, руководителей 2 уровня'; SUSPEND;

    TAG_NAME = 'columns:r'; VAL = NULL; SUSPEND;
    TAG_NAME = 'columns:r:type_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:param_id'; VAL = '4'; SUSPEND;
    TAG_NAME = 'columns:r:type'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:name'; VAL = 'Руководителей на одного обучающегося'; SUSPEND;

    TAG_NAME = 'columns:r'; VAL = NULL; SUSPEND;
    TAG_NAME = 'columns:r:type_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:param_id'; VAL = '5'; SUSPEND;
    TAG_NAME = 'columns:r:type'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:name'; VAL = 'Количество педагогических работников'; SUSPEND;

    TAG_NAME = 'columns:r'; VAL = NULL; SUSPEND;
    TAG_NAME = 'columns:r:type_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:param_id'; VAL = '6'; SUSPEND;
    TAG_NAME = 'columns:r:type'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:name'; VAL = 'Педагогических работников на одного обучающегося'; SUSPEND;

    TAG_NAME = 'columns:r'; VAL = NULL; SUSPEND;
    TAG_NAME = 'columns:r:type_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:param_id'; VAL = '7'; SUSPEND;
    TAG_NAME = 'columns:r:type'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:name'; VAL = 'Количество учителей'; SUSPEND;

    TAG_NAME = 'columns:r'; VAL = NULL; SUSPEND;
    TAG_NAME = 'columns:r:type_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:param_id'; VAL = '8'; SUSPEND;
    TAG_NAME = 'columns:r:type'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:name'; VAL = 'Сотрудников < 35 лет'; SUSPEND;

    TAG_NAME = 'columns:r'; VAL = NULL; SUSPEND;
    TAG_NAME = 'columns:r:type_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:param_id'; VAL = '9'; SUSPEND;
    TAG_NAME = 'columns:r:type'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:name'; VAL = 'Сотрудников с высшим образованием'; SUSPEND;

    TAG_NAME = 'columns:r'; VAL = NULL; SUSPEND;
    TAG_NAME = 'columns:r:type_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:param_id'; VAL = '10'; SUSPEND;
    TAG_NAME = 'columns:r:type'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:name'; VAL = 'Учителей со стажем > 10 лет'; SUSPEND;

    TAG_NAME = 'columns:r'; VAL = NULL; SUSPEND;
    TAG_NAME = 'columns:r:type_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:param_id'; VAL = '11'; SUSPEND;
    TAG_NAME = 'columns:r:type'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:name'; VAL = 'Принято с начала года'; SUSPEND;

    TAG_NAME = 'columns:r'; VAL = NULL; SUSPEND;
    TAG_NAME = 'columns:r:type_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:param_id'; VAL = '12'; SUSPEND;
    TAG_NAME = 'columns:r:type'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:name'; VAL = 'Уволено с начала года'; SUSPEND;

    -- Развертка по ОУ
    TAG_NAME = 'rows::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT L2.OBJ_ID, L2.OBJ_TYPE_ID, C.CAPTION
      FROM LINKS L2
      LEFT JOIN OBJECT_CAPTION_GET(L2.OBJ_ID) C ON 1 = 1
      WHERE L2.PARENT_ID = :I$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      ORDER BY 3
      INTO :V$OBJ_ID, :V$TYPE, :S
    DO
    BEGIN
      TAG_NAME = 'rows:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'rows:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'rows:r:type_id';
      VAL = '1';
      SUSPEND;
      TAG_NAME = 'rows:r:caption';
      VAL = S;
      SUSPEND;

      -- Сколько всего учеников ?
      SELECT COUNT(*)
      FROM LINKS L7
      JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
      JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      WHERE L7.PARENT_ID = :V$OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
      INTO :V$STUDENTS;

      SELECT COUNT(DISTINCT L14.OBJ_ID)
      FROM LINKS L14
      JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
      LEFT JOIN VALD V74 ON V74.OBJ_ID = L14.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
      JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
      WHERE L14.PARENT_ID = :V$OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL AND V74.VAL IS NULL
      INTO :V$VAL;

      TAG_NAME = 'rows:r:p1';
      VAL = V$VAL;
      SUSPEND;

      SELECT COUNT(DISTINCT L14.OBJ_ID)
      FROM LINKS L14
      JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
      LEFT JOIN VALD V74 ON V74.OBJ_ID = L14.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
      JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
      JOIN VALL V64 ON V64.OBJ_ID = LP13.PARENT_ID AND V64.PARAM_ID = 64 AND V64.IS_DEL = 0 AND V64.LISTVAL_ID = 56
      WHERE L14.PARENT_ID = :V$OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL AND V74.VAL IS NULL
      INTO :V$VAL;

      TAG_NAME = 'rows:r:p2';
      VAL = V$VAL;
      SUSPEND;

      SELECT COUNT(DISTINCT L14.OBJ_ID)
      FROM LINKS L14
      JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
      LEFT JOIN VALD V74 ON V74.OBJ_ID = L14.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
      JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
      JOIN VALL V64 ON V64.OBJ_ID = LP13.PARENT_ID AND V64.PARAM_ID = 64 AND V64.IS_DEL = 0 AND V64.LISTVAL_ID = 113
      WHERE L14.PARENT_ID = :V$OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL AND V74.VAL IS NULL
      INTO :V$VAL2;

      TAG_NAME = 'rows:r:p3';
      VAL = V$VAL2;
      SUSPEND;

      TAG_NAME = 'rows:r:p4';
      IF(V$STUDENTS = 0) THEN F = NULL; ELSE F = CAST((V$VAL + V$VAL2) AS FLOAT) / CAST(V$STUDENTS AS FLOAT);
      VAL = CAST(F AS NUMERIC (18, 3));
      SUSPEND;

      SELECT COUNT(DISTINCT L14.OBJ_ID)
      FROM LINKS L14
      JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
      LEFT JOIN VALD V74 ON V74.OBJ_ID = L14.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
      JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
      LEFT JOIN VAL_GET(L14.OBJ_ID, 988) P ON 1 = 1
      WHERE L14.PARENT_ID = :V$OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL AND V74.VAL IS NULL AND P.V = 'Да'
      INTO :V$VAL;

      TAG_NAME = 'rows:r:p5';
      VAL = V$VAL;
      SUSPEND;

      TAG_NAME = 'rows:r:p6';
      IF(V$STUDENTS = 0) THEN F = NULL; ELSE F = CAST(V$VAL AS FLOAT) / CAST(V$STUDENTS AS FLOAT);
      VAL = CAST(F AS NUMERIC (18, 3));
      SUSPEND;

      SELECT COUNT(DISTINCT L14.OBJ_ID)
      FROM LINKS L14
      JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
      LEFT JOIN VALD V74 ON V74.OBJ_ID = L14.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
      JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
      JOIN VALL V64 ON V64.OBJ_ID = LP13.PARENT_ID AND V64.PARAM_ID = 64 AND V64.IS_DEL = 0 AND V64.LISTVAL_ID = 98
      WHERE L14.PARENT_ID = :V$OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL AND V74.VAL IS NULL
      INTO :V$VAL;

      TAG_NAME = 'rows:r:p7';
      VAL = V$VAL;
      SUSPEND;

      SELECT COUNT(DISTINCT L14.OBJ_ID)
      FROM LINKS L14
      JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
      LEFT JOIN VALD V74 ON V74.OBJ_ID = L14.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
      JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
      JOIN VALD V241 ON V241.OBJ_ID = L14.OBJ_ID AND V241.PARAM_ID = 241 AND V241.IS_DEL = 0 AND V241.VAL >= DATEADD(-35 YEAR TO CURRENT_DATE)
      WHERE L14.PARENT_ID = :V$OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL AND V74.VAL IS NULL
      INTO :V$VAL;

      TAG_NAME = 'rows:r:p8';
      VAL = V$VAL;
      SUSPEND;

      SELECT COUNT(DISTINCT L14.OBJ_ID)
      FROM LINKS L14
      JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
      LEFT JOIN VALD V74 ON V74.OBJ_ID = L14.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
      JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
      JOIN VALL V278 ON V278.OBJ_ID = L14.OBJ_ID AND V278.PARAM_ID = 278 AND V278.IS_DEL = 0 AND V278.LISTVAL_ID IN (620, 3031, 3032)
      WHERE L14.PARENT_ID = :V$OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL AND V74.VAL IS NULL
      INTO :V$VAL;

      TAG_NAME = 'rows:r:p9';
      VAL = V$VAL;
      SUSPEND;

      SELECT COUNT(DISTINCT L14.OBJ_ID)
      FROM LINKS L14
      JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
      LEFT JOIN VALD V74 ON V74.OBJ_ID = L14.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
      JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
      JOIN VALL V64 ON V64.OBJ_ID = LP13.PARENT_ID AND V64.PARAM_ID = 64 AND V64.IS_DEL = 0 AND V64.LISTVAL_ID = 98
      LEFT JOIN VAL_GET(L14.OBJ_ID, 463) V ON 1 = 1
      WHERE L14.PARENT_ID = :V$OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL AND V74.VAL IS NULL AND CAST(V.V AS INTEGER) > 3600
      INTO :V$VAL;

      TAG_NAME = 'rows:r:p10';
      VAL = V$VAL;
      SUSPEND;

      SELECT COUNT(DISTINCT L14.OBJ_ID)
      FROM LINKS L14
      JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
      JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
      JOIN VALD V73 ON V73.OBJ_ID = L14.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0 AND V73.VAL >= :V$YEAR_START
      WHERE L14.PARENT_ID = :V$OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
      INTO :V$VAL;

      TAG_NAME = 'rows:r:p11';
      VAL = V$VAL;
      SUSPEND;

      -- !! Совсем выбывшие ?
      SELECT COUNT(DISTINCT L14.OBJ_ID)
      FROM LINKS L14
      JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
      JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
      JOIN VALD V74 ON V74.OBJ_ID = L14.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0 AND V74.VAL >= :V$YEAR_START
      WHERE L14.PARENT_ID = :V$OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
      INTO :V$VAL;

      TAG_NAME = 'rows:r:p12';
      VAL = V$VAL;
      SUSPEND;

    END

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PF_STUFF_OU (
    I$OBJ_ID BIGINT,
    I$BLOCK_NAME VARCHAR(40),
    I$BLOCK_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$VAL BIGINT;
DECLARE VARIABLE V$VAL2 BIGINT;
DECLARE VARIABLE V$STUDENTS BIGINT;
DECLARE VARIABLE F FLOAT;
DECLARE VARIABLE S VARCHAR(1000);
DECLARE VARIABLE V$TYPE_ID1 BIGINT;
DECLARE VARIABLE V$TYPE_ID2 BIGINT;
DECLARE VARIABLE V$MID_TYPE BIGINT;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$PARAM_ID BIGINT;
DECLARE VARIABLE V$TYPE BIGINT;
DECLARE VARIABLE V$T BIGINT;
DECLARE VARIABLE V$MASTER_ID BIGINT;
DECLARE VARIABLE V$YEAR_START DATE;
begin

  -- Сколько всего учеников ?
  SELECT COUNT(*)
  FROM LINKS L7
  JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
  JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
  JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
  WHERE L7.PARENT_ID = :I$OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
  INTO :V$STUDENTS;

  IF(EXTRACT(MONTH FROM CURRENT_DATE) < 8) THEN V$YEAR_START = '01.09.' || (EXTRACT(YEAR FROM CURRENT_DATE) - 1);
  ELSE V$YEAR_START = '01.09.' || EXTRACT(YEAR FROM CURRENT_DATE);

  IF(I$BLOCK_NAME IS NULL) THEN
  BEGIN
    -- Оглавление
    TAG_NAME = 'dashboard::json&colon;array';
    VAL = 1;
    SUSPEND;

    SELECT COUNT(DISTINCT L14.OBJ_ID)
    FROM LINKS L14
    JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74
    JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
    WHERE L14.PARENT_ID = :I$OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL AND (V74.IS_DEL = 1 OR V74.VAL IS NULL)
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'stuff';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '14';
    SUSPEND;
    TAG_NAME = 'dashboard:r:subtype_id';
    VAL = '';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'user';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#410093';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Количество сотрудников';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

    SELECT COUNT(DISTINCT L14.OBJ_ID)
    FROM LINKS L14
    JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74
    JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
    JOIN VALL V64 ON V64.OBJ_ID = LP13.PARENT_ID AND V64.PARAM_ID = 64 AND V64.IS_DEL = 0 AND V64.LISTVAL_ID = 56
    WHERE L14.PARENT_ID = :I$OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL AND (V74.IS_DEL = 1 OR V74.VAL IS NULL)
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'stuff';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '14';
    SUSPEND;
    TAG_NAME = 'dashboard:r:subtype_id';
    VAL = '56';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'user';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#410093';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Количество руководителей';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

    SELECT COUNT(DISTINCT L14.OBJ_ID)
    FROM LINKS L14
    JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74
    JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
    JOIN VALL V64 ON V64.OBJ_ID = LP13.PARENT_ID AND V64.PARAM_ID = 64 AND V64.IS_DEL = 0 AND V64.LISTVAL_ID = 113
    WHERE L14.PARENT_ID = :I$OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL AND (V74.IS_DEL = 1 OR V74.VAL IS NULL)
    INTO :V$VAL2;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'stuff';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '14';
    SUSPEND;
    TAG_NAME = 'dashboard:r:subtype_id';
    VAL = '113';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'user';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#410093';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Количество заместителей, руководителей 2 уровня';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL2;
    SUSPEND;

    -- На одного обучающегося
    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'stuff';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '14';
    SUSPEND;
    TAG_NAME = 'dashboard:r:subtype_id';
    VAL = '988';
    SUSPEND;
    TAG_NAME = 'dashboard:r:details';
    VAL = 'none';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'percent';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#25D366';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Руководителей на одного обучающегося';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    IF(V$STUDENTS = 0) THEN F = NULL; ELSE F = CAST((V$VAL + V$VAL2) AS FLOAT) / CAST(V$STUDENTS AS FLOAT);
    VAL = CAST(F AS NUMERIC (18, 3));
    SUSPEND;

    SELECT COUNT(DISTINCT L14.OBJ_ID)
    FROM LINKS L14
    JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74
    JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
    LEFT JOIN VAL_GET(L14.OBJ_ID, 988) P ON 1 = 1 AND P.V = 'Да'
    WHERE L14.PARENT_ID = :I$OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL AND (V74.IS_DEL = 1 OR V74.VAL IS NULL)
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'stuff';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '14';
    SUSPEND;
    TAG_NAME = 'dashboard:r:subtype_id';
    VAL = '988';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'graduation cap';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#410093';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Количество педагогических работников';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

    -- На одного обучающегося
    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'stuff';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '14';
    SUSPEND;
    TAG_NAME = 'dashboard:r:subtype_id';
    VAL = '988';
    SUSPEND;
    TAG_NAME = 'dashboard:r:details';
    VAL = 'none';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'percent';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#25D366';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Педагогических работников на одного обучающегося';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    IF(V$STUDENTS = 0) THEN F = NULL; ELSE F = CAST(V$VAL AS FLOAT) / CAST(V$STUDENTS AS FLOAT);
    VAL = CAST(F AS NUMERIC (18, 3));
    SUSPEND;

    SELECT COUNT(DISTINCT L14.OBJ_ID)
    FROM LINKS L14
    JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74
    JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
    JOIN VALL V64 ON V64.OBJ_ID = LP13.PARENT_ID AND V64.PARAM_ID = 64 AND V64.IS_DEL = 0 AND V64.LISTVAL_ID = 98
    WHERE L14.PARENT_ID = :I$OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL AND (V74.IS_DEL = 1 OR V74.VAL IS NULL)
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'stuff';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '14';
    SUSPEND;
    TAG_NAME = 'dashboard:r:subtype_id';
    VAL = '98';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'graduation cap';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#410093';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Количество учителей';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

    -- По возрасту
    SELECT COUNT(DISTINCT L14.OBJ_ID)
    FROM LINKS L14
    JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74
    JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
    JOIN VALD V241 ON V241.OBJ_ID = L14.OBJ_ID AND V241.PARAM_ID = 241 AND V241.IS_DEL = 0 AND V241.VAL >= DATEADD(-35 YEAR TO CURRENT_DATE)
    WHERE L14.PARENT_ID = :I$OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL AND (V74.IS_DEL = 1 OR V74.VAL IS NULL)
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'byage';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '14';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'sort amount down';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#34465D';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Сотрудников < 35 лет';
    SUSPEND;
    TAG_NAME = 'dashboard:r:hint';
    VAL = 'Распределение по возрастам';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

    -- По образованию
    SELECT COUNT(DISTINCT L14.OBJ_ID)
    FROM LINKS L14
    JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74
    JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
    JOIN VALL V278 ON V278.OBJ_ID = L14.OBJ_ID AND V278.PARAM_ID = 278 AND V278.IS_DEL = 0 AND V278.LISTVAL_ID IN (620, 3031, 3032)
    WHERE L14.PARENT_ID = :I$OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL AND (V74.IS_DEL = 1 OR V74.VAL IS NULL)
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'byedu';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '14';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'university';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#34465D';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Сотрудников с высшим образованием';
    SUSPEND;
    TAG_NAME = 'dashboard:r:hint';
    VAL = 'Распределение по образованию';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

    -- По стажу
    SELECT COUNT(DISTINCT L14.OBJ_ID)
    FROM LINKS L14
    JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74
    JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
    JOIN VALL V64 ON V64.OBJ_ID = LP13.PARENT_ID AND V64.PARAM_ID = 64 AND V64.IS_DEL = 0 AND V64.LISTVAL_ID = 98
    LEFT JOIN VAL_GET(L14.OBJ_ID, 463) V ON CAST(V.V AS INTEGER) > 3600
    WHERE L14.PARENT_ID = :I$OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL AND (V74.IS_DEL = 1 OR V74.VAL IS NULL)
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'bystage';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '14';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'university';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#34465D';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Учителей со стажем > 10 лет';
    SUSPEND;
    TAG_NAME = 'dashboard:r:hint';
    VAL = 'Распределение по стажу';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

    -- По категории
    SELECT COUNT(DISTINCT L14.OBJ_ID)
    FROM LINKS L14
    JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74
    JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
    JOIN VALL V281 ON V281.OBJ_ID = L14.OBJ_ID AND V281.PARAM_ID = 281 AND V281.IS_DEL = 0 AND V281.LISTVAL_ID = 635
    WHERE L14.PARENT_ID = :I$OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL AND (V74.IS_DEL = 1 OR V74.VAL IS NULL)
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'bycategory';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '14';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'thumbs up';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#34465D';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Сотрудников с высшей категорией';
    SUSPEND;
    TAG_NAME = 'dashboard:r:hint';
    VAL = 'Распределение по уровню квалификации';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

    SELECT COUNT(DISTINCT L14.OBJ_ID)
    FROM LINKS L14
    JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
    JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
    JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0 AND V73.VAL >= :V$YEAR_START
    WHERE L14.PARENT_ID = :I$OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'stuff';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '14';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'arrow circle down';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#DF2029';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Принято с начала года';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

    -- !! Совсем выбывшие ?
    SELECT COUNT(DISTINCT L14.OBJ_ID)
    FROM LINKS L14
    JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
    JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74
    WHERE L14.PARENT_ID = :I$OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
      AND V74.IS_DEL = 0 AND V74.VAL IS NOT NULL AND V74.VAL >= :V$YEAR_START
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'stuff';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '14';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'arrow circle up';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#DF2029';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Уволено с начала года';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

  END
  ELSE
  BEGIN

    V$TYPE_ID1 = 14;
    V$TYPE = 14;
    TAG_NAME = 'has_caption';
    IF(I$BLOCK_NAME = 'stuff') THEN VAL = 1; ELSE VAL = 0;
    SUSPEND;

    TAG_NAME = 'title';
    IF(I$BLOCK_NAME = 'stuff') THEN
    BEGIN
      VAL = 'Сотрудники';
      SUSPEND;

      -- Описание полей
      TAG_NAME = 'columns::json&colon;array';
      VAL = 1;
      SUSPEND;
      FOR
        SELECT P.TYPE_ID, P.PARAM_ID, P.PARAM_TYPE, R.VAL
        FROM PARAMS P
        JOIN RES R ON R.RES_ID = P.RES_ID AND R.LANG_CODE = 'RU'
        WHERE P.IS_DEL = 0 AND (P.TYPE_ID = :V$TYPE_ID1 OR P.TYPE_ID = :V$TYPE_ID2)
          AND P.PARAM_ID IN (268, 281, 988, 431, 462, 463, 464, 465, 274, 278, 2984)
        ORDER BY 1, 2
        INTO :V$TYPE, :V$PARAM_ID, :V$T, :S
      DO
      BEGIN
        TAG_NAME = 'columns:r';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'columns:r:type_id';
        VAL = V$TYPE;
        SUSPEND;
        TAG_NAME = 'columns:r:param_id';
        VAL = V$PARAM_ID;
        SUSPEND;
        TAG_NAME = 'columns:r:type';
        VAL = V$T;
        SUSPEND;
        TAG_NAME = 'columns:r:name';
        VAL = S;
        SUSPEND;
      END

      -- Данные
      TAG_NAME = 'rows::json&colon;array';
      VAL = 1;
      SUSPEND;
      FOR
        SELECT DISTINCT L14.OBJ_ID
        FROM LINKS L14
        JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
        LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74
        JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
        -- Фильтр по подгруппе должностей
        JOIN VALL V64 ON V64.OBJ_ID = LP13.PARENT_ID AND V64.PARAM_ID = 64 AND V64.IS_DEL = 0
          AND (:I$BLOCK_ID IS NULL OR :I$BLOCK_ID = 988 OR V64.LISTVAL_ID = :I$BLOCK_ID)
        -- Фильтр по педагогичности
        LEFT JOIN VAL_GET(L14.OBJ_ID, 988) P ON 1 = 1
        WHERE L14.PARENT_ID = :I$OBJ_ID AND L14.DATE_DEL IS NULL AND L14.OBJ_TYPE_ID = 14 AND (V74.IS_DEL = 1 OR V74.VAL IS NULL)
          AND (:I$BLOCK_ID IS NULL OR :I$BLOCK_ID <> 988 OR (:I$BLOCK_ID = 988 AND P.V = 'Да'))
        ORDER BY 1
        INTO :V$OBJ_ID
      DO
      BEGIN
        TAG_NAME = 'rows:r';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'rows:r:id';
        VAL = V$OBJ_ID;
        SUSPEND;
        TAG_NAME = 'rows:r:type_id';
        VAL = V$TYPE;
        SUSPEND;
        TAG_NAME = 'rows:r:caption';
        VAL = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$OBJ_ID));
        SUSPEND;
        FOR
          SELECT P.PARAM_ID, IIF(V.IS_EXISTS = 1, V.V, NULL)
          FROM PARAMS P
          LEFT JOIN VAL_GET(:V$OBJ_ID, P.PARAM_ID) V ON 1 = 1
          WHERE P.TYPE_ID = :V$TYPE AND P.IS_DEL = 0
            AND P.PARAM_ID IN (268, 281, 988, 431, 462, 463, 464, 465, 274, 278, 2984)
          ORDER BY P.GRID_ORDER
          INTO :V$PARAM_ID, :S
        DO
        BEGIN
          TAG_NAME = 'rows:r:p' || V$PARAM_ID;
          IF(V$PARAM_ID IN (462, 463, 464) AND S <> '') THEN S = CAST(CAST(S AS FLOAT) / 360 AS NUMERIC(18, 1));
          VAL = S;
          SUSPEND;
        END
      END
    END
    ELSE IF(I$BLOCK_NAME = 'byage') THEN
    BEGIN
      VAL = 'Распределение сотрудников по возрастам';
      SUSPEND;
      TAG_NAME = 'rows::json&colon;array';
      VAL = 1;
      SUSPEND;
      -- Разбивка по возрастам, <20 лет, блоки по 5 лет, >65 лет
      FOR
        SELECT CAST(CAST(V.V AS INTEGER) / 5 AS INTEGER) * 5, COUNT(DISTINCT L14.OBJ_ID)
        FROM LINKS L14
        JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
        LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74
        JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
        -- Фильтр по подгруппе должностей
        -- JOIN VALL V64 ON V64.OBJ_ID = LP13.PARENT_ID AND V64.PARAM_ID = 64 AND V64.IS_DEL = 0
        LEFT JOIN VAL_GET(L14.OBJ_ID, 431) V ON 1 = 1
        WHERE L14.PARENT_ID = :I$OBJ_ID AND L14.DATE_DEL IS NULL AND L14.OBJ_TYPE_ID = 14 AND (V74.IS_DEL = 1 OR V74.VAL IS NULL)
        GROUP BY 1
        ORDER BY 1
        INTO :V$OBJ_ID, :V$VAL
      DO
      BEGIN
        TAG_NAME = 'rows:r';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'rows:r:id';
        VAL = V$OBJ_ID;
        SUSPEND;
        TAG_NAME = 'rows:r:type_id';
        VAL = V$TYPE;
        SUSPEND;
        TAG_NAME = 'rows:r:p0';
        VAL = V$OBJ_ID || '...' || (V$OBJ_ID + 5) || ' лет';
        SUSPEND;
        TAG_NAME = 'rows:r:p1';
        VAL = V$VAL;
        SUSPEND;
      END
    END
    ELSE IF(I$BLOCK_NAME = 'byedu') THEN
    BEGIN
      VAL = 'Распределение сотрудников по образованию';
      SUSPEND;
      TAG_NAME = 'rows::json&colon;array';
      VAL = 1;
      SUSPEND;
      FOR
        SELECT V278.LISTVAL_ID, COUNT(DISTINCT L14.OBJ_ID)
        FROM LINKS L14
        JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
        LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74
        JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
        -- Фильтр по подгруппе должностей
        -- JOIN VALL V64 ON V64.OBJ_ID = LP13.PARENT_ID AND V64.PARAM_ID = 64 AND V64.IS_DEL = 0
        JOIN VALL V278 ON V278.OBJ_ID = L14.OBJ_ID AND V278.PARAM_ID = 278 AND V278.IS_DEL = 0
        WHERE L14.PARENT_ID = :I$OBJ_ID AND L14.DATE_DEL IS NULL AND L14.OBJ_TYPE_ID = 14 AND (V74.IS_DEL = 1 OR V74.VAL IS NULL)
        GROUP BY 1
        ORDER BY 1
        INTO :V$OBJ_ID, :V$VAL
      DO
      BEGIN
        TAG_NAME = 'rows:r';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'rows:r:id';
        VAL = V$OBJ_ID;
        SUSPEND;
        TAG_NAME = 'rows:r:type_id';
        VAL = V$TYPE;
        SUSPEND;
        TAG_NAME = 'rows:r:p0';
        VAL = (SELECT VAL FROM LISTVAL_TEXT(:V$OBJ_ID));
        SUSPEND;
        TAG_NAME = 'rows:r:p1';
        VAL = V$VAL;
        SUSPEND;
      END
    END
    ELSE IF(I$BLOCK_NAME = 'bystage') THEN
    BEGIN
      -- Группы стажа по числу лет, блоками по 5 лет
      VAL = 'Распределение сотрудников по стажу';
      SUSPEND;
      TAG_NAME = 'rows::json&colon;array';
      VAL = 1;
      SUSPEND;
      FOR
        SELECT CAST(CAST(V.V AS INTEGER) / 1800 AS INTEGER) * 5, COUNT(DISTINCT L14.OBJ_ID)
        FROM LINKS L14
        JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
        LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74
        JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
        -- Фильтр по подгруппе должностей
        -- JOIN VALL V64 ON V64.OBJ_ID = LP13.PARENT_ID AND V64.PARAM_ID = 64 AND V64.IS_DEL = 0
        LEFT JOIN VAL_GET(L14.OBJ_ID, 463) V ON 1 = 1
        WHERE L14.PARENT_ID = :I$OBJ_ID AND L14.DATE_DEL IS NULL AND L14.OBJ_TYPE_ID = 14 AND (V74.IS_DEL = 1 OR V74.VAL IS NULL)
        GROUP BY 1
        ORDER BY 1
        INTO :V$OBJ_ID, :V$VAL
      DO
      BEGIN
        TAG_NAME = 'rows:r';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'rows:r:id';
        VAL = V$OBJ_ID;
        SUSPEND;
        TAG_NAME = 'rows:r:type_id';
        VAL = V$TYPE;
        SUSPEND;
        TAG_NAME = 'rows:r:p0';
        VAL = V$OBJ_ID || '...' || (V$OBJ_ID + 5) || ' лет';
        SUSPEND;
        TAG_NAME = 'rows:r:p1';
        VAL = V$VAL;
        SUSPEND;
      END
    END
    ELSE IF(I$BLOCK_NAME = 'bycategory') THEN
    BEGIN
      VAL = 'Распределение сотрудников по квалификационной категории';
      SUSPEND;
      TAG_NAME = 'rows::json&colon;array';
      VAL = 1;
      SUSPEND;
      FOR
        SELECT V281.LISTVAL_ID, COUNT(DISTINCT L14.OBJ_ID)
        FROM LINKS L14
        JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
        LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74
        JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
        -- Фильтр по подгруппе должностей
        -- JOIN VALL V64 ON V64.OBJ_ID = LP13.PARENT_ID AND V64.PARAM_ID = 64 AND V64.IS_DEL = 0
        JOIN VALL V281 ON V281.OBJ_ID = L14.OBJ_ID AND V281.PARAM_ID = 281 AND V281.IS_DEL = 0
        WHERE L14.PARENT_ID = :I$OBJ_ID AND L14.DATE_DEL IS NULL AND L14.OBJ_TYPE_ID = 14 AND (V74.IS_DEL = 1 OR V74.VAL IS NULL)
        GROUP BY 1
        ORDER BY 1
        INTO :V$OBJ_ID, :V$VAL
      DO
      BEGIN
        TAG_NAME = 'rows:r';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'rows:r:id';
        VAL = V$OBJ_ID;
        SUSPEND;
        TAG_NAME = 'rows:r:type_id';
        VAL = V$TYPE;
        SUSPEND;
        TAG_NAME = 'rows:r:p0';
        VAL = (SELECT VAL FROM LISTVAL_TEXT(:V$OBJ_ID));
        SUSPEND;
        TAG_NAME = 'rows:r:p1';
        VAL = V$VAL;
        SUSPEND;
      END
    END
    ELSE
    BEGIN
      VAL = '???';
      SUSPEND;
    END

    -- Описание столбцов для детализации
    IF(I$BLOCK_NAME <> 'stuff') THEN
    BEGIN
      TAG_NAME = 'columns::json&colon;array';
      VAL = 1;
      SUSPEND;
        TAG_NAME = 'columns:r';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'columns:r:type_id';
        VAL = 14;
        SUSPEND;
        TAG_NAME = 'columns:r:param_id';
        VAL = 0;
        SUSPEND;
        TAG_NAME = 'columns:r:type';
        VAL = 8;
        SUSPEND;
        TAG_NAME = 'columns:r:name';
        IF(I$BLOCK_NAME = 'byage') THEN VAL = 'Возраст';
        IF(I$BLOCK_NAME = 'byedu') THEN VAL = 'Образование';
        IF(I$BLOCK_NAME = 'bystage') THEN VAL = 'Стаж';
        IF(I$BLOCK_NAME = 'bycategory') THEN VAL = 'Квалификационная категория по основной должности';
        SUSPEND;
        TAG_NAME = 'columns:r';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'columns:r:type_id';
        VAL = 14;
        SUSPEND;
        TAG_NAME = 'columns:r:param_id';
        VAL = 1;
        SUSPEND;
        TAG_NAME = 'columns:r:type';
        VAL = 1;
        SUSPEND;
        TAG_NAME = 'columns:r:name';
        VAL = 'Количество сотрудников';
        SUSPEND;
    END

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PF_STUFF_RGN (
    I$OBJ_ID BIGINT,
    I$BLOCK_NAME VARCHAR(40),
    I$BLOCK_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(1000))
AS
declare variable V$STUDENTS bigint;
declare variable V$YEAR_START date;
declare variable V bigint;
declare variable V$VAL bigint;
declare variable V$VAL2 bigint;
declare variable F double precision;
declare variable S varchar(1000);
declare variable V$TYPE_ID1 bigint;
declare variable V$TYPE_ID2 bigint;
declare variable V$MID_TYPE bigint;
declare variable V$OBJ_ID bigint;
declare variable V$PARAM_ID bigint;
declare variable V$TYPE bigint;
declare variable V$T bigint;
declare variable V$MASTER_ID bigint;
begin

  IF(EXTRACT(MONTH FROM CURRENT_DATE) < 8) THEN V$YEAR_START = '01.09.' || (EXTRACT(YEAR FROM CURRENT_DATE) - 1);
  ELSE V$YEAR_START = '01.09.' || EXTRACT(YEAR FROM CURRENT_DATE);

  IF(I$BLOCK_NAME IS NULL) THEN
  BEGIN
    -- Оглавление
    TAG_NAME = 'dashboard::json&colon;array';
    VAL = 1;
    SUSPEND;

    -- Сколько всего учеников ?
    SELECT COUNT(*)
    FROM LINKS L111
    JOIN LINKS L2 ON L2.PARENT_ID = L111.OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
    JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    WHERE L111.PARENT_ID = :I$OBJ_ID AND L111.OBJ_TYPE_ID = 111 AND L111.DATE_DEL IS NULL
    INTO :V$STUDENTS;

    SELECT COUNT(DISTINCT L14.OBJ_ID)
    FROM LINKS L111
    JOIN LINKS L2 ON L2.PARENT_ID = L111.OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
    JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L14.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
    JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
    WHERE L111.PARENT_ID = :I$OBJ_ID AND L111.OBJ_TYPE_ID = 111 AND L111.DATE_DEL IS NULL AND V74.VAL IS NULL
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'stuff';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '14';
    SUSPEND;
    TAG_NAME = 'dashboard:r:subtype_id';
    VAL = '';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'user';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#410093';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Количество сотрудников';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

    SELECT COUNT(DISTINCT L14.OBJ_ID)
    FROM LINKS L111
    JOIN LINKS L2 ON L2.PARENT_ID = L111.OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
    JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L14.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
    JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
    JOIN VALL V64 ON V64.OBJ_ID = LP13.PARENT_ID AND V64.PARAM_ID = 64 AND V64.IS_DEL = 0 AND V64.LISTVAL_ID = 56
    WHERE L111.PARENT_ID = :I$OBJ_ID AND L111.OBJ_TYPE_ID = 111 AND L111.DATE_DEL IS NULL AND V74.VAL IS NULL
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'stuff';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '14';
    SUSPEND;
    TAG_NAME = 'dashboard:r:subtype_id';
    VAL = '56';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'user';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#410093';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Количество руководителей';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

    SELECT COUNT(DISTINCT L14.OBJ_ID)
    FROM LINKS L111
    JOIN LINKS L2 ON L2.PARENT_ID = L111.OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
    JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L14.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
    JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
    JOIN VALL V64 ON V64.OBJ_ID = LP13.PARENT_ID AND V64.PARAM_ID = 64 AND V64.IS_DEL = 0 AND V64.LISTVAL_ID = 113
    WHERE L111.PARENT_ID = :I$OBJ_ID AND L111.OBJ_TYPE_ID = 111 AND L111.DATE_DEL IS NULL AND V74.VAL IS NULL
    INTO :V$VAL2;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'stuff';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '14';
    SUSPEND;
    TAG_NAME = 'dashboard:r:subtype_id';
    VAL = '113';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'user';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#410093';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Количество заместителей, руководителей 2 уровня';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL2;
    SUSPEND;

    -- На одного обучающегося
    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'stuff';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '14';
    SUSPEND;
    TAG_NAME = 'dashboard:r:subtype_id';
    VAL = '988';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'percent';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#25D366';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Руководителей на одного обучающегося';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    IF(V$STUDENTS = 0) THEN F = NULL; ELSE F = CAST((V$VAL + V$VAL2) AS FLOAT) / CAST(V$STUDENTS AS FLOAT);
    VAL = CAST(F AS NUMERIC (18, 3));
    SUSPEND;

    SELECT COUNT(DISTINCT L14.OBJ_ID)
    FROM LINKS L111
    JOIN LINKS L2 ON L2.PARENT_ID = L111.OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
    JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L14.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
    JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
    LEFT JOIN VAL_GET(L14.OBJ_ID, 988) P ON 1 = 1
    WHERE L111.PARENT_ID = :I$OBJ_ID AND L111.OBJ_TYPE_ID = 111 AND L111.DATE_DEL IS NULL AND V74.VAL IS NULL AND P.V = 'Да'
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'stuff';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '14';
    SUSPEND;
    TAG_NAME = 'dashboard:r:subtype_id';
    VAL = '988';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'graduation cap';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#410093';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Количество педагогических работников';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

    -- На одного обучающегося
    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'stuff';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '14';
    SUSPEND;
    TAG_NAME = 'dashboard:r:subtype_id';
    VAL = '988';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'percent';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#25D366';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Педагогических работников на одного обучающегося';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    IF(V$STUDENTS = 0) THEN F = NULL; ELSE F = CAST(V$VAL AS FLOAT) / CAST(V$STUDENTS AS FLOAT);
    VAL = CAST(F AS NUMERIC (18, 3));
    SUSPEND;

    SELECT COUNT(DISTINCT L14.OBJ_ID)
    FROM LINKS L111
    JOIN LINKS L2 ON L2.PARENT_ID = L111.OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
    JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L14.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
    JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
    JOIN VALL V64 ON V64.OBJ_ID = LP13.PARENT_ID AND V64.PARAM_ID = 64 AND V64.IS_DEL = 0 AND V64.LISTVAL_ID = 98
    WHERE L111.PARENT_ID = :I$OBJ_ID AND L111.OBJ_TYPE_ID = 111 AND L111.DATE_DEL IS NULL AND V74.VAL IS NULL
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'stuff';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '14';
    SUSPEND;
    TAG_NAME = 'dashboard:r:subtype_id';
    VAL = '98';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'graduation cap';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#410093';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Количество учителей';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

    -- По возрасту
    SELECT COUNT(DISTINCT L14.OBJ_ID)
    FROM LINKS L111
    JOIN LINKS L2 ON L2.PARENT_ID = L111.OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
    JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L14.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
    JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
    JOIN VALD V241 ON V241.OBJ_ID = L14.OBJ_ID AND V241.PARAM_ID = 241 AND V241.IS_DEL = 0 AND V241.VAL >= DATEADD(-35 YEAR TO CURRENT_DATE)
    WHERE L111.PARENT_ID = :I$OBJ_ID AND L111.OBJ_TYPE_ID = 111 AND L111.DATE_DEL IS NULL AND V74.VAL IS NULL
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'byage';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '14';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'sort amount down';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#34465D';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Сотрудников < 35 лет';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

    -- По образованию
    SELECT COUNT(DISTINCT L14.OBJ_ID)
    FROM LINKS L111
    JOIN LINKS L2 ON L2.PARENT_ID = L111.OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
    JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L14.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
    JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
    JOIN VALL V278 ON V278.OBJ_ID = L14.OBJ_ID AND V278.PARAM_ID = 278 AND V278.IS_DEL = 0 AND V278.LISTVAL_ID IN (620, 3031, 3032)
    WHERE L111.PARENT_ID = :I$OBJ_ID AND L111.OBJ_TYPE_ID = 111 AND L111.DATE_DEL IS NULL AND V74.VAL IS NULL
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'byedu';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '14';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'university';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#34465D';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Сотрудников с высшим образованием';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

    -- По стажу
    SELECT COUNT(DISTINCT L14.OBJ_ID)
    FROM LINKS L111
    JOIN LINKS L2 ON L2.PARENT_ID = L111.OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
    JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L14.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
    JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
    JOIN VALL V64 ON V64.OBJ_ID = LP13.PARENT_ID AND V64.PARAM_ID = 64 AND V64.IS_DEL = 0 AND V64.LISTVAL_ID = 98
    LEFT JOIN VAL_GET(L14.OBJ_ID, 463) V ON 1 = 1
    WHERE L111.PARENT_ID = :I$OBJ_ID AND L111.OBJ_TYPE_ID = 111 AND L111.DATE_DEL IS NULL AND V74.VAL IS NULL AND CAST(V.V AS INTEGER) > 3600
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'bystage';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '14';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'university';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#34465D';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Учителей со стажем > 10 лет';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

    SELECT COUNT(DISTINCT L14.OBJ_ID)
    FROM LINKS L111
    JOIN LINKS L2 ON L2.PARENT_ID = L111.OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
    JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L14.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
    JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
    JOIN VALD V63 ON V63.OBJ_ID = L14.OBJ_ID AND V63.PARAM_ID = 63 AND V63.IS_DEL = 0 AND V63.VAL >= :V$YEAR_START
    WHERE L111.PARENT_ID = :I$OBJ_ID AND L111.OBJ_TYPE_ID = 111 AND L111.DATE_DEL IS NULL
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'stuff';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '14';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'arrow circle down';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#DF2029';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Принято с начала года';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

    -- !! Совсем выбывшие ?
    SELECT COUNT(DISTINCT L14.OBJ_ID)
    FROM LINKS L111
    JOIN LINKS L2 ON L2.PARENT_ID = L111.OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
    JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L14.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
    JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
    JOIN VALD V64 ON V64.OBJ_ID = L14.OBJ_ID AND V64.PARAM_ID = 64 AND V64.IS_DEL = 0 AND V64.VAL >= :V$YEAR_START
    WHERE L111.PARENT_ID = :I$OBJ_ID AND L111.OBJ_TYPE_ID = 111 AND L111.DATE_DEL IS NULL
    INTO :V$VAL;

    TAG_NAME = 'dashboard:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'dashboard:r:id';
    VAL = 'stuff';
    SUSPEND;
    TAG_NAME = 'dashboard:r:type_id';
    VAL = '14';
    SUSPEND;
    TAG_NAME = 'dashboard:r:icon';
    VAL = 'arrow circle up';
    SUSPEND;
    TAG_NAME = 'dashboard:r:color';
    VAL = '#DF2029';
    SUSPEND;
    TAG_NAME = 'dashboard:r:title';
    VAL = 'Уволено с начала года';
    SUSPEND;
    TAG_NAME = 'dashboard:r:value';
    VAL = V$VAL;
    SUSPEND;

  END
  ELSE
  BEGIN

    TAG_NAME = 'title';
    VAL = 'Сотрудники';
    SUSPEND;

    TAG_NAME = 'has_caption';
    VAL = 1;
    SUSPEND;

    TAG_NAME = 'columns::json&colon;array';
    VAL = 1;
    SUSPEND;

    TAG_NAME = 'columns:r'; VAL = NULL; SUSPEND;
    TAG_NAME = 'columns:r:type_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:param_id'; VAL = '0'; SUSPEND;
    TAG_NAME = 'columns:r:type'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:name'; VAL = 'Количество ОУ'; SUSPEND;

    TAG_NAME = 'columns:r'; VAL = NULL; SUSPEND;
    TAG_NAME = 'columns:r:type_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:param_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:type'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:name'; VAL = 'Количество сотрудников'; SUSPEND;

    TAG_NAME = 'columns:r'; VAL = NULL; SUSPEND;
    TAG_NAME = 'columns:r:type_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:param_id'; VAL = '2'; SUSPEND;
    TAG_NAME = 'columns:r:type'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:name'; VAL = 'Количество руководителей'; SUSPEND;

    TAG_NAME = 'columns:r'; VAL = NULL; SUSPEND;
    TAG_NAME = 'columns:r:type_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:param_id'; VAL = '3'; SUSPEND;
    TAG_NAME = 'columns:r:type'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:name'; VAL = 'Количество заместителей, руководителей 2 уровня'; SUSPEND;

    TAG_NAME = 'columns:r'; VAL = NULL; SUSPEND;
    TAG_NAME = 'columns:r:type_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:param_id'; VAL = '4'; SUSPEND;
    TAG_NAME = 'columns:r:type'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:name'; VAL = 'Руководителей на одного обучающегося'; SUSPEND;

    TAG_NAME = 'columns:r'; VAL = NULL; SUSPEND;
    TAG_NAME = 'columns:r:type_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:param_id'; VAL = '5'; SUSPEND;
    TAG_NAME = 'columns:r:type'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:name'; VAL = 'Количество педагогических работников'; SUSPEND;

    TAG_NAME = 'columns:r'; VAL = NULL; SUSPEND;
    TAG_NAME = 'columns:r:type_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:param_id'; VAL = '6'; SUSPEND;
    TAG_NAME = 'columns:r:type'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:name'; VAL = 'Педагогических работников на одного обучающегося'; SUSPEND;

    TAG_NAME = 'columns:r'; VAL = NULL; SUSPEND;
    TAG_NAME = 'columns:r:type_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:param_id'; VAL = '7'; SUSPEND;
    TAG_NAME = 'columns:r:type'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:name'; VAL = 'Количество учителей'; SUSPEND;

    TAG_NAME = 'columns:r'; VAL = NULL; SUSPEND;
    TAG_NAME = 'columns:r:type_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:param_id'; VAL = '8'; SUSPEND;
    TAG_NAME = 'columns:r:type'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:name'; VAL = 'Сотрудников < 35 лет'; SUSPEND;

    TAG_NAME = 'columns:r'; VAL = NULL; SUSPEND;
    TAG_NAME = 'columns:r:type_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:param_id'; VAL = '9'; SUSPEND;
    TAG_NAME = 'columns:r:type'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:name'; VAL = 'Сотрудников с высшим образованием'; SUSPEND;

    TAG_NAME = 'columns:r'; VAL = NULL; SUSPEND;
    TAG_NAME = 'columns:r:type_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:param_id'; VAL = '10'; SUSPEND;
    TAG_NAME = 'columns:r:type'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:name'; VAL = 'Учителей со стажем > 10 лет'; SUSPEND;

    TAG_NAME = 'columns:r'; VAL = NULL; SUSPEND;
    TAG_NAME = 'columns:r:type_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:param_id'; VAL = '11'; SUSPEND;
    TAG_NAME = 'columns:r:type'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:name'; VAL = 'Принято с начала года'; SUSPEND;

    TAG_NAME = 'columns:r'; VAL = NULL; SUSPEND;
    TAG_NAME = 'columns:r:type_id'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:param_id'; VAL = '12'; SUSPEND;
    TAG_NAME = 'columns:r:type'; VAL = '1'; SUSPEND;
    TAG_NAME = 'columns:r:name'; VAL = 'Уволено с начала года'; SUSPEND;

    -- Развертка по районам
    TAG_NAME = 'rows::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT L111.OBJ_ID, L111.OBJ_TYPE_ID, C.CAPTION
      FROM LINKS L111
      LEFT JOIN OBJECT_CAPTION_GET(L111.OBJ_ID) C ON 1 = 1
      WHERE L111.PARENT_ID = :I$OBJ_ID AND L111.OBJ_TYPE_ID = 111 AND L111.DATE_DEL IS NULL
      ORDER BY 3
      INTO :V$OBJ_ID, :V$TYPE, :S
    DO
    BEGIN
      TAG_NAME = 'rows:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'rows:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'rows:r:type_id';
      VAL = '1';
      SUSPEND;
      TAG_NAME = 'rows:r:caption';
      VAL = S;
      SUSPEND;

      -- Сколько всего учеников ?
      SELECT COUNT(*), COUNT(DISTINCT L2.OBJ_ID)
      FROM LINKS L2
      JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
      JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
      JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      WHERE L2.PARENT_ID = :V$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      INTO :V$STUDENTS, :V;

      TAG_NAME = 'rows:r:p0';
      VAL = V;
      SUSPEND;

      SELECT COUNT(DISTINCT L14.OBJ_ID)
      FROM LINKS L2
      JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
      JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
      LEFT JOIN VALD V74 ON V74.OBJ_ID = L14.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
      JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
      WHERE L2.PARENT_ID = :V$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND V74.VAL IS NULL
      INTO :V$VAL;

      TAG_NAME = 'rows:r:p1';
      VAL = V$VAL;
      SUSPEND;

      SELECT COUNT(DISTINCT L14.OBJ_ID)
      FROM LINKS L2
      JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
      JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
      LEFT JOIN VALD V74 ON V74.OBJ_ID = L14.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
      JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
      JOIN VALL V64 ON V64.OBJ_ID = LP13.PARENT_ID AND V64.PARAM_ID = 64 AND V64.IS_DEL = 0 AND V64.LISTVAL_ID = 56
      WHERE L2.PARENT_ID = :V$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND V74.VAL IS NULL
      INTO :V$VAL;

      TAG_NAME = 'rows:r:p2';
      VAL = V$VAL;
      SUSPEND;

      SELECT COUNT(DISTINCT L14.OBJ_ID)
      FROM LINKS L2
      JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
      JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
      LEFT JOIN VALD V74 ON V74.OBJ_ID = L14.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
      JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
      JOIN VALL V64 ON V64.OBJ_ID = LP13.PARENT_ID AND V64.PARAM_ID = 64 AND V64.IS_DEL = 0 AND V64.LISTVAL_ID = 113
      WHERE L2.PARENT_ID = :V$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND V74.VAL IS NULL
      INTO :V$VAL2;

      TAG_NAME = 'rows:r:p3';
      VAL = V$VAL2;
      SUSPEND;

      TAG_NAME = 'rows:r:p4';
      IF(V$STUDENTS = 0) THEN F = NULL; ELSE F = CAST((V$VAL + V$VAL2) AS FLOAT) / CAST(V$STUDENTS AS FLOAT);
      VAL = CAST(F AS NUMERIC (18, 3));
      SUSPEND;

      SELECT COUNT(DISTINCT L14.OBJ_ID)
      FROM LINKS L2
      JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
      JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
      LEFT JOIN VALD V74 ON V74.OBJ_ID = L14.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
      JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
      LEFT JOIN VAL_GET(L14.OBJ_ID, 988) P ON 1 = 1
      WHERE L2.PARENT_ID = :V$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND V74.VAL IS NULL AND P.V = 'Да'
      INTO :V$VAL;

      TAG_NAME = 'rows:r:p5';
      VAL = V$VAL;
      SUSPEND;

      TAG_NAME = 'rows:r:p6';
      IF(V$STUDENTS = 0) THEN F = NULL; ELSE F = CAST(V$VAL AS FLOAT) / CAST(V$STUDENTS AS FLOAT);
      VAL = CAST(F AS NUMERIC (18, 3));
      SUSPEND;

      SELECT COUNT(DISTINCT L14.OBJ_ID)
      FROM LINKS L2
      JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
      JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
      LEFT JOIN VALD V74 ON V74.OBJ_ID = L14.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
      JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
      JOIN VALL V64 ON V64.OBJ_ID = LP13.PARENT_ID AND V64.PARAM_ID = 64 AND V64.IS_DEL = 0 AND V64.LISTVAL_ID = 98
      WHERE L2.PARENT_ID = :V$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND V74.VAL IS NULL
      INTO :V$VAL;

      TAG_NAME = 'rows:r:p7';
      VAL = V$VAL;
      SUSPEND;

      SELECT COUNT(DISTINCT L14.OBJ_ID)
      FROM LINKS L2
      JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
      JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
      LEFT JOIN VALD V74 ON V74.OBJ_ID = L14.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
      JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
      JOIN VALD V241 ON V241.OBJ_ID = L14.OBJ_ID AND V241.PARAM_ID = 241 AND V241.IS_DEL = 0 AND V241.VAL >= DATEADD(-35 YEAR TO CURRENT_DATE)
      WHERE L2.PARENT_ID = :V$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND V74.VAL IS NULL
      INTO :V$VAL;

      TAG_NAME = 'rows:r:p8';
      VAL = V$VAL;
      SUSPEND;

      SELECT COUNT(DISTINCT L14.OBJ_ID)
      FROM LINKS L2
      JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
      JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
      LEFT JOIN VALD V74 ON V74.OBJ_ID = L14.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
      JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
      JOIN VALL V278 ON V278.OBJ_ID = L14.OBJ_ID AND V278.PARAM_ID = 278 AND V278.IS_DEL = 0 AND V278.LISTVAL_ID IN (620, 3031, 3032)
      WHERE L2.PARENT_ID = :V$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND V74.VAL IS NULL
      INTO :V$VAL;

      TAG_NAME = 'rows:r:p9';
      VAL = V$VAL;
      SUSPEND;

      SELECT COUNT(DISTINCT L14.OBJ_ID)
      FROM LINKS L2
      JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
      JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
      LEFT JOIN VALD V74 ON V74.OBJ_ID = L14.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
      JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
      JOIN VALL V64 ON V64.OBJ_ID = LP13.PARENT_ID AND V64.PARAM_ID = 64 AND V64.IS_DEL = 0 AND V64.LISTVAL_ID = 98
      LEFT JOIN VAL_GET(L14.OBJ_ID, 463) V ON 1 = 1
      WHERE L2.PARENT_ID = :V$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND V74.VAL IS NULL AND CAST(V.V AS INTEGER) > 3600
      INTO :V$VAL;

      TAG_NAME = 'rows:r:p10';
      VAL = V$VAL;
      SUSPEND;

      SELECT COUNT(DISTINCT L14.OBJ_ID)
      FROM LINKS L2
      JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
      JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
      JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
      JOIN VALD V73 ON V73.OBJ_ID = L14.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0 AND V73.VAL >= :V$YEAR_START
      WHERE L2.PARENT_ID = :V$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      INTO :V$VAL;

      TAG_NAME = 'rows:r:p11';
      VAL = V$VAL;
      SUSPEND;

      -- !! Совсем выбывшие ?
      SELECT COUNT(DISTINCT L14.OBJ_ID)
      FROM LINKS L2
      JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
      JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
      JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
      JOIN VALD V74 ON V74.OBJ_ID = L14.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0 AND V74.VAL >= :V$YEAR_START
      WHERE L2.PARENT_ID = :V$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      INTO :V$VAL;

      TAG_NAME = 'rows:r:p12';
      VAL = V$VAL;
      SUSPEND;

    END

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PLANTMPL_OP_LIST (
    I$OBJ_ID BIGINT,
    I$USER_ID BIGINT = NULL)
RETURNS (
    LISTVAL_ID BIGINT,
    PARENT_ID BIGINT,
    VAL VARCHAR(4000),
    VAL_LONG VARCHAR(4000),
    TAG VARCHAR(100),
    "FILTER" VARCHAR(255))
AS
DECLARE VARIABLE V$STATUS VARCHAR(2);
DECLARE VARIABLE V$GEN BIGINT;
BEGIN

  -- Список всегда 254, PARENT_ID всегда пустой
  V$STATUS = (SELECT STATUS FROM OU_LICENCE_TYPE);

  SELECT GEN
  FROM GEN
  INTO :V$GEN;

  IF(V$STATUS = 'S' OR V$GEN = 0) THEN
  BEGIN
    -- Пока без фильтрации по настройкам ОУ
    FOR
      SELECT LISTVAL_ID, VAL, VAL_LONG, TAG, L."FILTER"
      FROM LISTVALS_LIST(254, :I$USER_ID) L
      WHERE L.IS_DEL = 0 AND (L.PARENT_ID = 5336 OR L.LISTVAL_ID = 5346)
      AND (:V$GEN = 0 OR 1 = 1)
      INTO :LISTVAL_ID, :VAL, :VAL_LONG, :TAG, :"FILTER"
    DO
    BEGIN
      SUSPEND;
    END
  END
  ELSE
  BEGIN
    -- Старый формат - только НОО, ООО, СОО
    FOR
      SELECT LISTVAL_ID, VAL, VAL_LONG, TAG, L."FILTER"
      FROM OO_FILTRED_LIST(254, :I$USER_ID) L
      WHERE LISTVAL_ID IN (5339, 5341, 5343)
      INTO :LISTVAL_ID, :VAL, :VAL_LONG, :TAG, :"FILTER"
    DO
    BEGIN
      SUSPEND;
    END
  END

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PLAN_CHECK_SAVE (
    I$PLAN_ID BIGINT,
    I$TIMEMARK VARCHAR(40),
    I$USER_ID VARCHAR(40))
RETURNS (
    TIMEMARK VARCHAR(100))
AS
declare variable V$GEN bigint;
declare variable V$MULTIPLIER bigint;
begin

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  SELECT FIRST 1 DI.VAL
  FROM LINKS L
  LEFT JOIN DATE2ISO(L.DATE_MODIFY, 1) DI ON 1 = 1
  WHERE L.OBJ_ID = :I$PLAN_ID
  INTO :TIMEMARK;

  IF(TIMEMARK IS NULL) THEN EXCEPTION DATA_ERROR 'Учебный план не найден';
  IF(TIMEMARK <> I$TIMEMARK) THEN EXCEPTION DATA_ERROR 'Учебный план был изменен другим пользователем, сохранение невозможно';

  -- Проверка прав доступа к приложению и утвержденного статуса
  SELECT FIRST 1 GEN, MULTIPLIER
  FROM GEN
  INTO :V$GEN, :V$MULTIPLIER;

  IF(I$PLAN_ID / V$MULTIPLIER <> V$GEN) THEN EXCEPTION DATA_ERROR 'Нельзя изменять данный учебный план';

  UPDATE LINKS
  SET DATE_MODIFY = CURRENT_TIMESTAMP
  WHERE OBJ_ID = :I$PLAN_ID;

  SELECT FIRST 1 DI.VAL
  FROM LINKS L
  LEFT JOIN DATE2ISO(L.DATE_MODIFY, 1) DI ON 1 = 1
  WHERE L.OBJ_ID = :I$PLAN_ID
  INTO :TIMEMARK;

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PLAN_CLEANUP
AS
DECLARE VARIABLE V$OU_ID BIGINT;
DECLARE VARIABLE V$YEAR INTEGER;
DECLARE VARIABLE V$OP_ID BIGINT;
DECLARE VARIABLE V$PLAN_ID BIGINT;
begin

  -- Удаляем только учебные планы, к которым не прикреплены ученики

  SELECT FIRST 1 L2.OBJ_ID, LV.COST
  FROM LINKS L2
  LEFT JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  LEFT JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$OU_ID, :V$YEAR;

  IF(V$OU_ID IS NULL) THEN EXIT;

  FOR
    SELECT L57.OBJ_ID
    FROM LINKS L69
    -- Только общеобразовательные и АООП
    -- Костыль для завершения старых ОП с годом публикации меньше текущего - если нет детей, то сами виноваты
    JOIN VALL V2450 ON V2450.OBJ_ID = L69.OBJ_ID AND V2450.PARAM_ID = 2450 AND V2450.IS_DEL = 0 AND V2450.LISTVAL_ID IN (11385, 13270)
    JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
    JOIN VALI V3115 ON V3115.OBJ_ID = L57.OBJ_ID AND V3115.PARAM_ID = 3115 AND V3115.IS_DEL = 0 AND V3115.VAL <> :V$YEAR AND V3115.VAL <> :V$YEAR + 1
    WHERE L69.PARENT_ID = :V$OU_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL
    AND NOT EXISTS(
      SELECT FIRST 1 1
      FROM LINKS L400
      JOIN LINKS L54 ON L54.PARENT_ID = L400.OBJ_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
      JOIN LINKS L256 ON L256.PARENT_ID = L54.OBJ_ID AND L256.OBJ_TYPE_ID = 256 AND L256.DATE_DEL IS NULL
      JOIN LINKS L10 ON L10.PARENT_ID = L256.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      WHERE L400.PARENT_ID = L57.OBJ_ID AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL
    )
    ORDER BY 1
    INTO :V$OP_ID
  DO
  BEGIN
    -- Удаляем ссылки на этапы (мониторинг ?), но оставляем в самих УП
    FOR
      SELECT L54.OBJ_ID
      FROM LINKS L400
      JOIN LINKS L54 ON L54.PARENT_ID = L400.OBJ_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
      WHERE L400.PARENT_ID = :V$OP_ID AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL
      ORDER BY 1
      INTO :V$PLAN_ID
    DO
    BEGIN
      UPDATE LINKS
      SET DATE_DEL = CURRENT_TIMESTAMP
      WHERE OBJ_ID = :V$PLAN_ID AND PARENT_TYPE_ID <> 400 AND DATE_DEL IS NULL;
    END

    -- Удаляем ссылки на учебные планы, но оставляем в ОП
    FOR
      SELECT L400.OBJ_ID
      FROM LINKS L400
      WHERE L400.PARENT_ID = :V$OP_ID AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL
      ORDER BY 1
      INTO :V$PLAN_ID
    DO
    BEGIN
      UPDATE LINKS
      SET DATE_DEL = CURRENT_TIMESTAMP
      WHERE OBJ_ID = :V$PLAN_ID AND PARENT_TYPE_ID <> 57 AND DATE_DEL IS NULL;
    END

    -- Удаляем ОП - все наполнение вниз от нее останется неудаленным для истории
    UPDATE LINKS
    SET DATE_DEL = CURRENT_TIMESTAMP
    WHERE PARENT_TYPE_ID = 69 AND OBJ_ID = :V$OP_ID AND DATE_DEL IS NULL;
  END

  -- Восстановить ошибочно удаленные ОП ДО
  -- удаляются только те, где школа задала год публикации - с пустым годом они не должны были удалиться
  IF(CURRENT_DATE < '01.08.2025') THEN
  BEGIN
    FOR
      SELECT L57.LINK_ID
      FROM LINKS L69
      -- Только ДО
      JOIN VALL V2450 ON V2450.OBJ_ID = L69.OBJ_ID AND V2450.PARAM_ID = 2450 AND V2450.IS_DEL = 0 AND V2450.LISTVAL_ID = 11386
      JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
      JOIN VALI V3115 ON V3115.OBJ_ID = L57.OBJ_ID AND V3115.PARAM_ID = 3115 AND V3115.IS_DEL = 0 AND V3115.VAL <> :V$YEAR AND V3115.VAL <> :V$YEAR + 1
      WHERE L69.PARENT_ID = :V$OU_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL > '10.05.2025' AND L69.DATE_DEL < '01.08.2025'
      ORDER BY 1
      INTO :V$OP_ID
    DO
    BEGIN
      UPDATE LINKS
      SET DATE_DEL = NULL
      WHERE LINK_ID = :V$OP_ID;
    END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PLAN_CONTENT_GET (
    I$OBJ_ID BIGINT,
    I$USER_ID BIGINT = null)
RETURNS (
    LISTVAL_ID BIGINT,
    PARENT_ID BIGINT,
    VAL VARCHAR(4000),
    VAL_LONG VARCHAR(4000),
    TAG VARCHAR(100),
    "FILTER" VARCHAR(255))
AS
declare variable V$LANG_CODE varchar(2);
declare variable V$CURRENT_KIND integer;
declare variable V$OBJ_ID bigint;
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :V$LANG_CODE;

    FOR
        SELECT V2217.LISTVAL_ID
        FROM VALL V2217
        WHERE V2217.PARAM_ID = 2217
        AND V2217.OBJ_ID = :I$OBJ_ID
        AND V2217.IS_DEL = 0
        INTO :V$CURRENT_KIND
    DO
    BEGIN
        --Реорганизация
        IF (V$CURRENT_KIND = 10997) THEN
        BEGIN
            FOR
                SELECT LV.LISTVAL_ID,
                       LV.PARENT_ID,
                       R.VAL,
                       R.VAL_LONG,
                       LV.TAG
                FROM LISTVALS LV
        
                LEFT JOIN RES_GET(LV.RES_ID,  :V$LANG_CODE) R ON 1=1
        
                WHERE LV.LIST_ID = 275
                AND LV.PARENT_ID IS NULL
                AND IS_DEL = 0

                ORDER BY SORT_ORDER
        
                INTO :LISTVAL_ID,
                     :PARENT_ID,
                     :VAL,
                     :VAL_LONG,
                     :TAG
            DO
            BEGIN
                SUSPEND;
            END
        END
        --Изменения типа ОООД на:
        ELSE IF (V$CURRENT_KIND = 10998) THEN
        BEGIN
            FOR
                SELECT LV.LISTVAL_ID,
                       LV.PARENT_ID,
                       R.VAL,
                       R.VAL_LONG,
                       LV.TAG
                FROM LISTVALS LV
        
                LEFT JOIN RES_GET(LV.RES_ID,  :V$LANG_CODE) R ON 1=1
        
                WHERE LV.LIST_ID = 260
                AND IS_DEL = 0

                ORDER BY SORT_ORDER
        
                INTO :LISTVAL_ID,
                     :PARENT_ID,
                     :VAL,
                     :VAL_LONG,
                     :TAG
            DO
            BEGIN
                SUSPEND;
            END
        END
        --Изменение организационно-правовой формы ОООД на:
        ELSE IF (V$CURRENT_KIND = 10999) THEN
        BEGIN
            FOR
                SELECT LV.LISTVAL_ID,
                       LV.PARENT_ID,
                       R.VAL,
                       R.VAL_LONG,
                       LV.TAG
                FROM LISTVALS LV
        
                LEFT JOIN RES_GET(LV.RES_ID,  :V$LANG_CODE) R ON 1=1
        
                WHERE LV.LIST_ID = 258
                AND IS_DEL = 0

                ORDER BY SORT_ORDER
        
                INTO :LISTVAL_ID,
                     :PARENT_ID,
                     :VAL,
                     :VAL_LONG,
                     :TAG
            DO
            BEGIN
                SUSPEND;
            END
        END
        --Изменение структуры ОООД на:
        ELSE IF (V$CURRENT_KIND = 11000) THEN
        BEGIN
            FOR
                SELECT LV.LISTVAL_ID,
                       LV.PARENT_ID,
                       R.VAL,
                       R.VAL_LONG,
                       LV.TAG
                FROM LISTVALS LV
        
                LEFT JOIN RES_GET(LV.RES_ID,  :V$LANG_CODE) R ON 1=1
        
                WHERE LV.LIST_ID = 278
                AND IS_DEL = 0

                ORDER BY SORT_ORDER
        
                INTO :LISTVAL_ID,
                     :PARENT_ID,
                     :VAL,
                     :VAL_LONG,
                     :TAG
            DO
            BEGIN
                SUSPEND;
            END
        END
        --Государственная аккредитация
        ELSE IF (V$CURRENT_KIND = 11001) THEN
        BEGIN
            FOR
                SELECT LV.LISTVAL_ID,
                       LV.PARENT_ID,
                       R.VAL,
                       R.VAL_LONG,
                       LV.TAG
                FROM LISTVALS LV
        
                LEFT JOIN RES_GET(LV.RES_ID,  :V$LANG_CODE) R ON 1=1
        
                WHERE LV.LIST_ID = 280
                AND IS_DEL = 0

                ORDER BY SORT_ORDER
        
                INTO :LISTVAL_ID,
                     :PARENT_ID,
                     :VAL,
                     :VAL_LONG,
                     :TAG
            DO
            BEGIN
                SUSPEND;
            END
        END
        --Лицензирование
        ELSE IF (V$CURRENT_KIND = 11002) THEN
        BEGIN
            FOR
                SELECT LV.LISTVAL_ID,
                       LV.PARENT_ID,
                       R.VAL,
                       R.VAL_LONG,
                       LV.TAG
                FROM LISTVALS LV
        
                LEFT JOIN RES_GET(LV.RES_ID,  :V$LANG_CODE) R ON 1=1
        
                WHERE LV.LIST_ID = 279
                AND IS_DEL = 0

                ORDER BY SORT_ORDER
        
                INTO :LISTVAL_ID,
                     :PARENT_ID,
                     :VAL,
                     :VAL_LONG,
                     :TAG
            DO
            BEGIN
                SUSPEND;
            END
        END
        --Капитальный ремонт/реконструкция  здания
        ELSE IF (V$CURRENT_KIND = 11003) THEN
        BEGIN
            SELECT PARENT_TYPE_ID, PARENT_ID
            FROM LINKS
            WHERE OBJ_ID = :I$OBJ_ID
            AND DATE_DEL IS NULL
            AND OBJ_TYPE_ID = 273
            INTO V$CURRENT_KIND, :V$OBJ_ID;

            FOR
                SELECT
                0 LISTVAL_ID,
                NULL PARENT_ID,
                V421.VAL,
                NULL VAL_LONG,
                NULL TAG
                
                FROM LINKS L2
                
                JOIN LINKS L73
                ON L73.PARENT_ID = L2.OBJ_ID
                AND L73.DATE_DEL IS NULL
                AND L73.OBJ_TYPE_ID = 73
                
                JOIN LINKS L16
                ON L16.PARENT_ID = L73.OBJ_ID
                AND L16.DATE_DEL IS NULL
                AND L16.OBJ_TYPE_ID = 16
                
                JOIN VALS V421
                ON V421.PARAM_ID = 421
                AND V421.IS_DEL = 0
                AND V421.OBJ_ID = L16.OBJ_ID
                
                WHERE L2.OBJ_TYPE_ID = 2
                AND L2.DATE_DEL IS NULL
                AND L2.OBJ_ID = :V$OBJ_ID
                AND L2.PARENT_ID IS NULL
        
                INTO :LISTVAL_ID,
                     :PARENT_ID,
                     :VAL,
                     :VAL_LONG,
                     :TAG
            DO
            BEGIN
                SUSPEND;
            END
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PLAN_COUNT_CLASS_ADD
AS
declare variable V$OU_ID bigint;
declare variable V$OBJ_ID bigint;
declare variable V$BLOB_ID bigint;
BEGIN
    SELECT DISTINCT OBJ_ID FROM LINKS
    WHERE OBJ_TYPE_ID = 2
    AND DATE_DEL IS NULL
    INTO :V$OU_ID;

    IF ( V$OU_ID IS NOT NULL ) THEN
    BEGIN
        V$OBJ_ID = NULL;
        SELECT L.OBJ_ID
        FROM LINKS L
        
        JOIN VALI V2284
        ON V2284.PARAM_ID = 2284
        AND V2284.IS_DEL = 0
        AND V2284.OBJ_ID = L.OBJ_ID
        AND V2284.VAL = 0

        WHERE L.OBJ_TYPE_ID = 274
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :V$OU_ID
        INTO :V$OBJ_ID;

        IF (V$OBJ_ID IS NULL) THEN
        BEGIN
            SELECT OBJ_ID FROM OBJECT_ADD(:V$OU_ID, 274) INTO :V$OBJ_ID;
            SELECT BLOB_ID FROM VAL_ADD(2284, :V$OBJ_ID, 0) INTO :V$BLOB_ID;
        END

        V$OBJ_ID = NULL;
        SELECT L.OBJ_ID
        FROM LINKS L
        
        JOIN VALI V2284
        ON V2284.PARAM_ID = 2284
        AND V2284.IS_DEL = 0
        AND V2284.OBJ_ID = L.OBJ_ID
        AND V2284.VAL = 1

        WHERE L.OBJ_TYPE_ID = 274
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :V$OU_ID
        INTO :V$OBJ_ID;

        IF (V$OBJ_ID IS NULL) THEN
        BEGIN
            SELECT OBJ_ID FROM OBJECT_ADD(:V$OU_ID, 274) INTO :V$OBJ_ID;
            SELECT BLOB_ID FROM VAL_ADD(2284, :V$OBJ_ID, 1) INTO :V$BLOB_ID;
        END

        V$OBJ_ID = NULL;
        SELECT L.OBJ_ID
        FROM LINKS L
        
        JOIN VALI V2284
        ON V2284.PARAM_ID = 2284
        AND V2284.IS_DEL = 0
        AND V2284.OBJ_ID = L.OBJ_ID
        AND V2284.VAL = 2

        WHERE L.OBJ_TYPE_ID = 274
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :V$OU_ID
        INTO :V$OBJ_ID;

        IF (V$OBJ_ID IS NULL) THEN
        BEGIN
            SELECT OBJ_ID FROM OBJECT_ADD(:V$OU_ID, 274) INTO :V$OBJ_ID;
            SELECT BLOB_ID FROM VAL_ADD(2284, :V$OBJ_ID, 2) INTO :V$BLOB_ID;
        END

        V$OBJ_ID = NULL;
        SELECT L.OBJ_ID
        FROM LINKS L
        
        JOIN VALI V2284
        ON V2284.PARAM_ID = 2284
        AND V2284.IS_DEL = 0
        AND V2284.OBJ_ID = L.OBJ_ID
        AND V2284.VAL = 3

        WHERE L.OBJ_TYPE_ID = 274
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :V$OU_ID
        INTO :V$OBJ_ID;

        IF (V$OBJ_ID IS NULL) THEN
        BEGIN
            SELECT OBJ_ID FROM OBJECT_ADD(:V$OU_ID, 274) INTO :V$OBJ_ID;
            SELECT BLOB_ID FROM VAL_ADD(2284, :V$OBJ_ID, 3) INTO :V$BLOB_ID;
        END



        V$OBJ_ID = NULL;
        SELECT L.OBJ_ID
        FROM LINKS L
        
        JOIN VALI V2286
        ON V2286.PARAM_ID = 2286
        AND V2286.IS_DEL = 0
        AND V2286.OBJ_ID = L.OBJ_ID
        AND V2286.VAL = 1

        WHERE L.OBJ_TYPE_ID = 277
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :V$OU_ID
        INTO :V$OBJ_ID;

        IF (V$OBJ_ID IS NULL) THEN
        BEGIN
            SELECT OBJ_ID FROM OBJECT_ADD(:V$OU_ID, 277) INTO :V$OBJ_ID;
            SELECT BLOB_ID FROM VAL_ADD(2286, :V$OBJ_ID, 1) INTO :V$BLOB_ID;
        END

        V$OBJ_ID = NULL;
        SELECT L.OBJ_ID
        FROM LINKS L
        
        JOIN VALI V2286
        ON V2286.PARAM_ID = 2286
        AND V2286.IS_DEL = 0
        AND V2286.OBJ_ID = L.OBJ_ID
        AND V2286.VAL = 2

        WHERE L.OBJ_TYPE_ID = 277
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :V$OU_ID
        INTO :V$OBJ_ID;

        IF (V$OBJ_ID IS NULL) THEN
        BEGIN
            SELECT OBJ_ID FROM OBJECT_ADD(:V$OU_ID, 277) INTO :V$OBJ_ID;
            SELECT BLOB_ID FROM VAL_ADD(2286, :V$OBJ_ID, 2) INTO :V$BLOB_ID;
        END

        V$OBJ_ID = NULL;
        SELECT L.OBJ_ID
        FROM LINKS L
        
        JOIN VALI V2286
        ON V2286.PARAM_ID = 2286
        AND V2286.IS_DEL = 0
        AND V2286.OBJ_ID = L.OBJ_ID
        AND V2286.VAL = 3

        WHERE L.OBJ_TYPE_ID = 277
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :V$OU_ID
        INTO :V$OBJ_ID;

        IF (V$OBJ_ID IS NULL) THEN
        BEGIN
            SELECT OBJ_ID FROM OBJECT_ADD(:V$OU_ID, 277) INTO :V$OBJ_ID;
            SELECT BLOB_ID FROM VAL_ADD(2286, :V$OBJ_ID, 3) INTO :V$BLOB_ID;
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PLAN_COUNT_CLASS_DATA_GET RETURNS (
    UYEAR VARCHAR(100),
    P1 INTEGER,
    P2 INTEGER,
    P3 INTEGER,
    P4 INTEGER,
    P5 INTEGER,
    P6 INTEGER,
    P7 INTEGER,
    P8 INTEGER,
    P9 INTEGER,
    P10 INTEGER,
    P11 INTEGER,
    NYEAR INTEGER)
AS
declare variable V$CLASS_NUMBER integer;
declare variable V$OBJ_ID bigint;
BEGIN
    FOR
        SELECT L.OBJ_ID FROM LINKS L
    
        JOIN VALI V2284
        ON V2284.PARAM_ID = 2284
        AND V2284.OBJ_ID = L.OBJ_ID
        AND V2284.IS_DEL = 0
        AND V2284.VAL = 0
        
        WHERE L.OBJ_TYPE_ID = 274
        AND L.DATE_DEL IS NULL
        AND L.PARENT_TYPE_ID = 2
        INTO :V$OBJ_ID
    DO
    BEGIN
        P1 = NULL;
        P2 = NULL;
        P3 = NULL;
        P4 = NULL;
        P5 = NULL;
        P6 = NULL;
        P7 = NULL;
        P8 = NULL;
        P9 = NULL;
        P10 = NULL;
        P11 = NULL;

        NYEAR = 0;

        SELECT V.V
        FROM VAL_GET(:V$OBJ_ID, 2236) V
        INTO :UYEAR;

        SELECT V.V
        FROM VAL_GET(:V$OBJ_ID, 2221) V
        INTO :P1;

        SELECT V.V
        FROM VAL_GET(:V$OBJ_ID, 2222) V
        INTO :P2;

        SELECT V.V
        FROM VAL_GET(:V$OBJ_ID, 2223) V
        INTO :P3;

        SELECT V.V
        FROM VAL_GET(:V$OBJ_ID, 2224) V
        INTO :P4;

        SELECT V.V
        FROM VAL_GET(:V$OBJ_ID, 2225) V
        INTO :P5;

        SELECT V.V
        FROM VAL_GET(:V$OBJ_ID, 2226) V
        INTO :P6;

        SELECT V.V
        FROM VAL_GET(:V$OBJ_ID, 2227) V
        INTO :P7;

        SELECT V.V
        FROM VAL_GET(:V$OBJ_ID, 2228) V
        INTO :P8;

        SELECT V.V
        FROM VAL_GET(:V$OBJ_ID, 2229) V
        INTO :P9;

        SELECT V.V
        FROM VAL_GET(:V$OBJ_ID, 2230) V
        INTO :P10;

        SELECT V.V
        FROM VAL_GET(:V$OBJ_ID, 2231) V
        INTO :P11;

        SUSPEND;
    END

    FOR
        SELECT L.OBJ_ID, V2286.VAL FROM LINKS L
    
        JOIN VALI V2286
        ON V2286.PARAM_ID = 2286
        AND V2286.OBJ_ID = L.OBJ_ID
        AND V2286.IS_DEL = 0
        
        WHERE L.OBJ_TYPE_ID = 277
        AND L.DATE_DEL IS NULL
        AND L.PARENT_TYPE_ID = 2
        
        ORDER BY V2286.VAL
        INTO :V$OBJ_ID, :NYEAR
    DO
    BEGIN
        P1 = NULL;
        P2 = NULL;
        P3 = NULL;
        P4 = NULL;
        P5 = NULL;
        P6 = NULL;
        P7 = NULL;
        P8 = NULL;
        P9 = NULL;
        P10 = NULL;
        P11 = NULL;

        SELECT V.V
        FROM VAL_GET(:V$OBJ_ID, 2252) V
        INTO :UYEAR;

        SELECT V.VAL
        FROM VALI V
        WHERE V.PARAM_ID = 2253
        AND V.IS_DEL = 0
        AND V.OBJ_ID = :V$OBJ_ID
        INTO :P1;

        SELECT V.VAL
        FROM VALI V
        WHERE V.PARAM_ID = 2254
        AND V.IS_DEL = 0
        AND V.OBJ_ID = :V$OBJ_ID
        INTO :P2;

        SELECT V.VAL
        FROM VALI V
        WHERE V.PARAM_ID = 2255
        AND V.IS_DEL = 0
        AND V.OBJ_ID = :V$OBJ_ID
        INTO :P3;

        SELECT V.VAL
        FROM VALI V
        WHERE V.PARAM_ID = 2256
        AND V.IS_DEL = 0
        AND V.OBJ_ID = :V$OBJ_ID
        INTO :P4;

        SELECT V.VAL
        FROM VALI V
        WHERE V.PARAM_ID = 2257
        AND V.IS_DEL = 0
        AND V.OBJ_ID = :V$OBJ_ID
        INTO :P5;

        SELECT V.VAL
        FROM VALI V
        WHERE V.PARAM_ID = 2258
        AND V.IS_DEL = 0
        AND V.OBJ_ID = :V$OBJ_ID
        INTO :P6;

        SELECT V.VAL
        FROM VALI V
        WHERE V.PARAM_ID = 2259
        AND V.IS_DEL = 0
        AND V.OBJ_ID = :V$OBJ_ID
        INTO :P7;

        SELECT V.VAL
        FROM VALI V
        WHERE V.PARAM_ID = 2260
        AND V.IS_DEL = 0
        AND V.OBJ_ID = :V$OBJ_ID
        INTO :P8;

        SELECT V.VAL
        FROM VALI V
        WHERE V.PARAM_ID = 2261
        AND V.IS_DEL = 0
        AND V.OBJ_ID = :V$OBJ_ID
        INTO :P9;

        SELECT V.VAL
        FROM VALI V
        WHERE V.PARAM_ID = 2262
        AND V.IS_DEL = 0
        AND V.OBJ_ID = :V$OBJ_ID
        INTO :P10;

        SELECT V.VAL
        FROM VALI V
        WHERE V.PARAM_ID = 2263
        AND V.IS_DEL = 0
        AND V.OBJ_ID = :V$OBJ_ID
        INTO :P11;

        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PLAN_COUNT_CLASS_DATA_SET (
    I$P1 INTEGER,
    I$P2 INTEGER,
    I$P3 INTEGER,
    I$P4 INTEGER,
    I$P5 INTEGER,
    I$P6 INTEGER,
    I$P7 INTEGER,
    I$P8 INTEGER,
    I$P9 INTEGER,
    I$P10 INTEGER,
    I$P11 INTEGER,
    I$NYEAR INTEGER)
AS
declare variable V$OBJ_ID bigint;
declare variable V$BLOB_ID bigint;
BEGIN
    SELECT L.OBJ_ID FROM LINKS L
    
    JOIN VALI V2286
    ON V2286.PARAM_ID = 2286
    AND V2286.OBJ_ID = L.OBJ_ID
    AND V2286.IS_DEL = 0
    AND V2286.VAL = :I$NYEAR
    
    WHERE L.OBJ_TYPE_ID = 277
    AND L.DATE_DEL IS NULL
    AND L.PARENT_TYPE_ID = 2
    
    ORDER BY V2286.VAL
    INTO :V$OBJ_ID;

    IF (V$OBJ_ID IS NOT NULL) THEN
    BEGIN
        SELECT BLOB_ID FROM VAL_ADD(2253,:V$OBJ_ID, 0, NULL, 1) INTO :V$BLOB_ID;
        IF (:I$P1 IS NOT NULL) THEN
        BEGIN
            SELECT BLOB_ID FROM VAL_ADD(2253,:V$OBJ_ID,:I$P1) INTO :V$BLOB_ID;
        END

        SELECT BLOB_ID FROM VAL_ADD(2254,:V$OBJ_ID, 0, NULL, 1) INTO :V$BLOB_ID;
        IF (:I$P2 IS NOT NULL) THEN
        BEGIN
            SELECT BLOB_ID FROM VAL_ADD(2254,:V$OBJ_ID,:I$P2) INTO :V$BLOB_ID;
        END

        SELECT BLOB_ID FROM VAL_ADD(2255,:V$OBJ_ID, 0, NULL, 1) INTO :V$BLOB_ID;
        IF (:I$P3 IS NOT NULL) THEN
        BEGIN
            SELECT BLOB_ID FROM VAL_ADD(2255,:V$OBJ_ID,:I$P3) INTO :V$BLOB_ID;
        END

        SELECT BLOB_ID FROM VAL_ADD(2256,:V$OBJ_ID, 0, NULL, 1) INTO :V$BLOB_ID;
        IF (:I$P4 IS NOT NULL) THEN
        BEGIN
            SELECT BLOB_ID FROM VAL_ADD(2256,:V$OBJ_ID,:I$P4) INTO :V$BLOB_ID;
        END

        SELECT BLOB_ID FROM VAL_ADD(2257,:V$OBJ_ID, 0, NULL, 1) INTO :V$BLOB_ID;
        IF (:I$P5 IS NOT NULL) THEN
        BEGIN
            SELECT BLOB_ID FROM VAL_ADD(2257,:V$OBJ_ID,:I$P5) INTO :V$BLOB_ID;
        END

        SELECT BLOB_ID FROM VAL_ADD(2258,:V$OBJ_ID, 0, NULL, 1) INTO :V$BLOB_ID;
        IF (:I$P6 IS NOT NULL) THEN
        BEGIN
            SELECT BLOB_ID FROM VAL_ADD(2258,:V$OBJ_ID,:I$P6) INTO :V$BLOB_ID;
        END

        SELECT BLOB_ID FROM VAL_ADD(2259,:V$OBJ_ID, 0, NULL, 1) INTO :V$BLOB_ID;
        IF (:I$P7 IS NOT NULL) THEN
        BEGIN
            SELECT BLOB_ID FROM VAL_ADD(2259,:V$OBJ_ID,:I$P7) INTO :V$BLOB_ID;
        END

        SELECT BLOB_ID FROM VAL_ADD(2260,:V$OBJ_ID, 0, NULL, 1) INTO :V$BLOB_ID;
        IF (:I$P8 IS NOT NULL) THEN
        BEGIN
            SELECT BLOB_ID FROM VAL_ADD(2260,:V$OBJ_ID,:I$P8) INTO :V$BLOB_ID;
        END

        SELECT BLOB_ID FROM VAL_ADD(2261,:V$OBJ_ID, 0, NULL, 1) INTO :V$BLOB_ID;
        IF (:I$P9 IS NOT NULL) THEN
        BEGIN
            SELECT BLOB_ID FROM VAL_ADD(2261,:V$OBJ_ID,:I$P9) INTO :V$BLOB_ID;
        END

        SELECT BLOB_ID FROM VAL_ADD(2262,:V$OBJ_ID, 0, NULL, 1) INTO :V$BLOB_ID;
        IF (:I$P10 IS NOT NULL) THEN
        BEGIN
            SELECT BLOB_ID FROM VAL_ADD(2262,:V$OBJ_ID,:I$P10) INTO :V$BLOB_ID;
        END

        SELECT BLOB_ID FROM VAL_ADD(2263,:V$OBJ_ID, 0, NULL, 1) INTO :V$BLOB_ID;
        IF (:I$P11 IS NOT NULL) THEN
        BEGIN
            SELECT BLOB_ID FROM VAL_ADD(2263,:V$OBJ_ID,:I$P11) INTO :V$BLOB_ID;
        END
    END

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PLAN_COUNT_CLASS_TRANSFER (
    I$USER_ID BIGINT)
AS
declare variable V$OBJ_ID1 bigint;
declare variable V$OBJ_ID2 bigint;
declare variable V$OBJ_ID3 bigint;
declare variable V$BLOB_ID bigint;
declare variable V$N integer;
BEGIN
    SELECT L.OBJ_ID
    FROM LINKS L
    
    JOIN VALI V
    ON V.PARAM_ID = 2286
    AND V.OBJ_ID = L.OBJ_ID
    AND V.IS_DEL = 0
    AND V.VAL = 1
    
    WHERE L.DATE_DEL IS NULL
    AND L.OBJ_TYPE_ID = 277
    AND L.PARENT_TYPE_ID = 2
    INTO :V$OBJ_ID1;

    SELECT L.OBJ_ID
    FROM LINKS L
    
    JOIN VALI V
    ON V.PARAM_ID = 2286
    AND V.OBJ_ID = L.OBJ_ID
    AND V.IS_DEL = 0
    AND V.VAL = 2
    
    WHERE L.DATE_DEL IS NULL
    AND L.OBJ_TYPE_ID = 277
    AND L.PARENT_TYPE_ID = 2
    INTO :V$OBJ_ID2;

    SELECT L.OBJ_ID
    FROM LINKS L
    
    JOIN VALI V
    ON V.PARAM_ID = 2286
    AND V.OBJ_ID = L.OBJ_ID
    AND V.IS_DEL = 0
    AND V.VAL = 3
    
    WHERE L.DATE_DEL IS NULL
    AND L.OBJ_TYPE_ID = 277
    AND L.PARENT_TYPE_ID = 2
    INTO :V$OBJ_ID3;

--    UPDATE OR INSERT INTO VALI (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
--        VALUES (2253, :V$OBJ_ID3, :I$USER_ID, 1, 1);
--    UPDATE OR INSERT INTO VALI (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
--        VALUES (2254, :V$OBJ_ID3, :I$USER_ID, 1, 1);
--    UPDATE OR INSERT INTO VALI (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
--        VALUES (2255, :V$OBJ_ID3, :I$USER_ID, 1, 1);
--    UPDATE OR INSERT INTO VALI (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
--        VALUES (2256, :V$OBJ_ID3, :I$USER_ID, 1, 1);
--    UPDATE OR INSERT INTO VALI (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
--        VALUES (2257, :V$OBJ_ID3, :I$USER_ID, 1, 1);
--    UPDATE OR INSERT INTO VALI (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
--        VALUES (2258, :V$OBJ_ID3, :I$USER_ID, 1, 1);
--    UPDATE OR INSERT INTO VALI (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
--        VALUES (2259, :V$OBJ_ID3, :I$USER_ID, 1, 1);
--    UPDATE OR INSERT INTO VALI (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
--        VALUES (2260, :V$OBJ_ID3, :I$USER_ID, 1, 1);
--    UPDATE OR INSERT INTO VALI (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
--        VALUES (2261, :V$OBJ_ID3, :I$USER_ID, 1, 1);
--    UPDATE OR INSERT INTO VALI (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
--        VALUES (2262, :V$OBJ_ID3, :I$USER_ID, 1, 1);
--    UPDATE OR INSERT INTO VALI (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
--        VALUES (2263, :V$OBJ_ID3, :I$USER_ID, 1, 1);
    
    SELECT BLOB_ID FROM VAL_ADD(2253, :V$OBJ_ID3, 1, :I$USER_ID,1) INTO V$BLOB_ID;
    SELECT BLOB_ID FROM VAL_ADD(2254, :V$OBJ_ID3, 1, :I$USER_ID,1) INTO V$BLOB_ID;
    SELECT BLOB_ID FROM VAL_ADD(2255, :V$OBJ_ID3, 1, :I$USER_ID,1) INTO V$BLOB_ID;
    SELECT BLOB_ID FROM VAL_ADD(2256, :V$OBJ_ID3, 1, :I$USER_ID,1) INTO V$BLOB_ID;
    SELECT BLOB_ID FROM VAL_ADD(2257, :V$OBJ_ID3, 1, :I$USER_ID,1) INTO V$BLOB_ID;
    SELECT BLOB_ID FROM VAL_ADD(2258, :V$OBJ_ID3, 1, :I$USER_ID,1) INTO V$BLOB_ID;
    SELECT BLOB_ID FROM VAL_ADD(2259, :V$OBJ_ID3, 1, :I$USER_ID,1) INTO V$BLOB_ID;
    SELECT BLOB_ID FROM VAL_ADD(2260, :V$OBJ_ID3, 1, :I$USER_ID,1) INTO V$BLOB_ID;
    SELECT BLOB_ID FROM VAL_ADD(2261, :V$OBJ_ID3, 1, :I$USER_ID,1) INTO V$BLOB_ID;
    SELECT BLOB_ID FROM VAL_ADD(2262, :V$OBJ_ID3, 1, :I$USER_ID,1) INTO V$BLOB_ID;
    SELECT BLOB_ID FROM VAL_ADD(2263, :V$OBJ_ID3, 1, :I$USER_ID,1) INTO V$BLOB_ID;


    SELECT V.I FROM VAL_GET(:V$OBJ_ID2,2253, 0, :I$USER_ID) V INTO V$N;
    IF (V$N>0) THEN
    BEGIN
        SELECT BLOB_ID FROM VAL_ADD(2254,:V$OBJ_ID3,:V$N, :I$USER_ID) INTO V$BLOB_ID;
    END
    SELECT V.I FROM VAL_GET(:V$OBJ_ID2,2254, 0, :I$USER_ID) V INTO V$N;
    IF (V$N>0) THEN
    BEGIN
        SELECT BLOB_ID FROM VAL_ADD(2255,:V$OBJ_ID3,:V$N, :I$USER_ID) INTO V$BLOB_ID;
    END
    SELECT V.I FROM VAL_GET(:V$OBJ_ID2,2255, 0, :I$USER_ID) V INTO V$N;
    IF (V$N>0) THEN
    BEGIN
        SELECT BLOB_ID FROM VAL_ADD(2256,:V$OBJ_ID3,:V$N, :I$USER_ID) INTO V$BLOB_ID;
    END
    SELECT V.I FROM VAL_GET(:V$OBJ_ID2,2256, 0, :I$USER_ID) V INTO V$N;
    IF (V$N>0) THEN
    BEGIN
        SELECT BLOB_ID FROM VAL_ADD(2257,:V$OBJ_ID3,:V$N, :I$USER_ID) INTO V$BLOB_ID;
    END
    SELECT V.I FROM VAL_GET(:V$OBJ_ID2,2257, 0, :I$USER_ID) V INTO V$N;
    IF (V$N>0) THEN
    BEGIN
        SELECT BLOB_ID FROM VAL_ADD(2258,:V$OBJ_ID3,:V$N, :I$USER_ID) INTO V$BLOB_ID;
    END
    SELECT V.I FROM VAL_GET(:V$OBJ_ID2,2258, 0, :I$USER_ID) V INTO V$N;
    IF (V$N>0) THEN
    BEGIN
        SELECT BLOB_ID FROM VAL_ADD(2259,:V$OBJ_ID3,:V$N, :I$USER_ID) INTO V$BLOB_ID;
    END
    SELECT V.I FROM VAL_GET(:V$OBJ_ID2,2259, 0, :I$USER_ID) V INTO V$N;
    IF (V$N>0) THEN
    BEGIN
        SELECT BLOB_ID FROM VAL_ADD(2260,:V$OBJ_ID3,:V$N, :I$USER_ID) INTO V$BLOB_ID;
    END
    SELECT V.I FROM VAL_GET(:V$OBJ_ID2,2260, 0, :I$USER_ID) V INTO V$N;
    IF (V$N>0) THEN
    BEGIN
        SELECT BLOB_ID FROM VAL_ADD(2261,:V$OBJ_ID3,:V$N, :I$USER_ID) INTO V$BLOB_ID;
    END
    SELECT V.I FROM VAL_GET(:V$OBJ_ID2,2261, 0, :I$USER_ID) V INTO V$N;
    IF (V$N>0) THEN
    BEGIN
        SELECT BLOB_ID FROM VAL_ADD(2262,:V$OBJ_ID3,:V$N, :I$USER_ID) INTO V$BLOB_ID;
    END
    SELECT V.I FROM VAL_GET(:V$OBJ_ID2,2262, 0, :I$USER_ID) V INTO V$N;
    IF (V$N>0) THEN
    BEGIN
        SELECT BLOB_ID FROM VAL_ADD(2263,:V$OBJ_ID3,:V$N, :I$USER_ID) INTO V$BLOB_ID;
    END

--    UPDATE OR INSERT INTO VALI (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
--        VALUES (2253, :V$OBJ_ID2, :I$USER_ID, 1, 1);
--    UPDATE OR INSERT INTO VALI (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
--        VALUES (2254, :V$OBJ_ID2, :I$USER_ID, 1, 1);
--    UPDATE OR INSERT INTO VALI (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
--        VALUES (2255, :V$OBJ_ID2, :I$USER_ID, 1, 1);
--    UPDATE OR INSERT INTO VALI (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
--        VALUES (2256, :V$OBJ_ID2, :I$USER_ID, 1, 1);
--    UPDATE OR INSERT INTO VALI (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
--        VALUES (2257, :V$OBJ_ID2, :I$USER_ID, 1, 1);
--    UPDATE OR INSERT INTO VALI (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
--        VALUES (2258, :V$OBJ_ID2, :I$USER_ID, 1, 1);
--    UPDATE OR INSERT INTO VALI (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
--        VALUES (2259, :V$OBJ_ID2, :I$USER_ID, 1, 1);
--    UPDATE OR INSERT INTO VALI (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
--        VALUES (2260, :V$OBJ_ID2, :I$USER_ID, 1, 1);
--    UPDATE OR INSERT INTO VALI (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
--        VALUES (2261, :V$OBJ_ID2, :I$USER_ID, 1, 1);
--    UPDATE OR INSERT INTO VALI (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
--        VALUES (2262, :V$OBJ_ID2, :I$USER_ID, 1, 1);
--    UPDATE OR INSERT INTO VALI (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
--        VALUES (2263, :V$OBJ_ID2, :I$USER_ID, 1, 1);

    SELECT BLOB_ID FROM VAL_ADD(2253, :V$OBJ_ID2, 1, :I$USER_ID,1) INTO V$BLOB_ID;
    SELECT BLOB_ID FROM VAL_ADD(2254, :V$OBJ_ID2, 1, :I$USER_ID,1) INTO V$BLOB_ID;
    SELECT BLOB_ID FROM VAL_ADD(2255, :V$OBJ_ID2, 1, :I$USER_ID,1) INTO V$BLOB_ID;
    SELECT BLOB_ID FROM VAL_ADD(2256, :V$OBJ_ID2, 1, :I$USER_ID,1) INTO V$BLOB_ID;
    SELECT BLOB_ID FROM VAL_ADD(2257, :V$OBJ_ID2, 1, :I$USER_ID,1) INTO V$BLOB_ID;
    SELECT BLOB_ID FROM VAL_ADD(2258, :V$OBJ_ID2, 1, :I$USER_ID,1) INTO V$BLOB_ID;
    SELECT BLOB_ID FROM VAL_ADD(2259, :V$OBJ_ID2, 1, :I$USER_ID,1) INTO V$BLOB_ID;
    SELECT BLOB_ID FROM VAL_ADD(2260, :V$OBJ_ID2, 1, :I$USER_ID,1) INTO V$BLOB_ID;
    SELECT BLOB_ID FROM VAL_ADD(2261, :V$OBJ_ID2, 1, :I$USER_ID,1) INTO V$BLOB_ID;
    SELECT BLOB_ID FROM VAL_ADD(2262, :V$OBJ_ID2, 1, :I$USER_ID,1) INTO V$BLOB_ID;
    SELECT BLOB_ID FROM VAL_ADD(2263, :V$OBJ_ID2, 1, :I$USER_ID,1) INTO V$BLOB_ID;

    SELECT V.I FROM VAL_GET(:V$OBJ_ID1,2253, 0, :I$USER_ID) V INTO V$N;
    IF (V$N>0) THEN
    BEGIN
        SELECT BLOB_ID FROM VAL_ADD(2254,:V$OBJ_ID2,:V$N, :I$USER_ID) INTO V$BLOB_ID;
    END
    SELECT V.I FROM VAL_GET(:V$OBJ_ID1,2254, 0, :I$USER_ID) V INTO V$N;
    IF (V$N>0) THEN
    BEGIN
        SELECT BLOB_ID FROM VAL_ADD(2255,:V$OBJ_ID2,:V$N, :I$USER_ID) INTO V$BLOB_ID;
    END
    SELECT V.I FROM VAL_GET(:V$OBJ_ID1,2255, 0, :I$USER_ID) V INTO V$N;
    IF (V$N>0) THEN
    BEGIN
        SELECT BLOB_ID FROM VAL_ADD(2256,:V$OBJ_ID2,:V$N, :I$USER_ID) INTO V$BLOB_ID;
    END
    SELECT V.I FROM VAL_GET(:V$OBJ_ID1,2256, 0, :I$USER_ID) V INTO V$N;
    IF (V$N>0) THEN
    BEGIN
        SELECT BLOB_ID FROM VAL_ADD(2257,:V$OBJ_ID2,:V$N, :I$USER_ID) INTO V$BLOB_ID;
    END
    SELECT V.I FROM VAL_GET(:V$OBJ_ID1,2257, 0, :I$USER_ID) V INTO V$N;
    IF (V$N>0) THEN
    BEGIN
        SELECT BLOB_ID FROM VAL_ADD(2258,:V$OBJ_ID2,:V$N, :I$USER_ID) INTO V$BLOB_ID;
    END
    SELECT V.I FROM VAL_GET(:V$OBJ_ID1,2258, 0, :I$USER_ID) V INTO V$N;
    IF (V$N>0) THEN
    BEGIN
        SELECT BLOB_ID FROM VAL_ADD(2259,:V$OBJ_ID2,:V$N, :I$USER_ID) INTO V$BLOB_ID;
    END
    SELECT V.I FROM VAL_GET(:V$OBJ_ID1,2259, 0, :I$USER_ID) V INTO V$N;
    IF (V$N>0) THEN
    BEGIN
        SELECT BLOB_ID FROM VAL_ADD(2260,:V$OBJ_ID2,:V$N, :I$USER_ID) INTO V$BLOB_ID;
    END
    SELECT V.I FROM VAL_GET(:V$OBJ_ID1,2260, 0, :I$USER_ID) V INTO V$N;
    IF (V$N>0) THEN
    BEGIN
        SELECT BLOB_ID FROM VAL_ADD(2261,:V$OBJ_ID2,:V$N, :I$USER_ID) INTO V$BLOB_ID;
    END
    SELECT V.I FROM VAL_GET(:V$OBJ_ID1,2261, 0, :I$USER_ID) V INTO V$N;
    IF (V$N>0) THEN
    BEGIN
        SELECT BLOB_ID FROM VAL_ADD(2262,:V$OBJ_ID2,:V$N, :I$USER_ID) INTO V$BLOB_ID;
    END
    SELECT V.I FROM VAL_GET(:V$OBJ_ID1,2262, 0, :I$USER_ID) V INTO V$N;
    IF (V$N>0) THEN
    BEGIN
        SELECT BLOB_ID FROM VAL_ADD(2263,:V$OBJ_ID2,:V$N, :I$USER_ID) INTO V$BLOB_ID;
    END


    UPDATE OR INSERT INTO VALI (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
        VALUES (2253, :V$OBJ_ID1, :I$USER_ID, 1, 1);
    UPDATE OR INSERT INTO VALI (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
        VALUES (2254, :V$OBJ_ID1, :I$USER_ID, 1, 1);
    UPDATE OR INSERT INTO VALI (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
        VALUES (2255, :V$OBJ_ID1, :I$USER_ID, 1, 1);
    UPDATE OR INSERT INTO VALI (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
        VALUES (2256, :V$OBJ_ID1, :I$USER_ID, 1, 1);
    UPDATE OR INSERT INTO VALI (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
        VALUES (2257, :V$OBJ_ID1, :I$USER_ID, 1, 1);
    UPDATE OR INSERT INTO VALI (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
        VALUES (2258, :V$OBJ_ID1, :I$USER_ID, 1, 1);
    UPDATE OR INSERT INTO VALI (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
        VALUES (2259, :V$OBJ_ID1, :I$USER_ID, 1, 1);
    UPDATE OR INSERT INTO VALI (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
        VALUES (2260, :V$OBJ_ID1, :I$USER_ID, 1, 1);
    UPDATE OR INSERT INTO VALI (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
        VALUES (2261, :V$OBJ_ID1, :I$USER_ID, 1, 1);
    UPDATE OR INSERT INTO VALI (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
        VALUES (2262, :V$OBJ_ID1, :I$USER_ID, 1, 1);
    UPDATE OR INSERT INTO VALI (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
        VALUES (2263, :V$OBJ_ID1, :I$USER_ID, 1, 1);
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PLAN_COUNT_ODOD_ADD
AS
declare variable V$OU_ID bigint;
declare variable V$OBJ_ID bigint;
declare variable V$BLOB_ID bigint;
BEGIN
    SELECT DISTINCT OBJ_ID FROM LINKS
    WHERE OBJ_TYPE_ID = 2
    AND DATE_DEL IS NULL
    INTO :V$OU_ID;

    IF ( V$OU_ID IS NOT NULL ) THEN
    BEGIN
        V$OBJ_ID = NULL;
        SELECT L.OBJ_ID
        FROM LINKS L
        
        JOIN VALI V2284
        ON V2284.PARAM_ID = 2308
        AND V2284.IS_DEL = 0
        AND V2284.OBJ_ID = L.OBJ_ID
        AND V2284.VAL = 0

        WHERE L.OBJ_TYPE_ID = 282
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :V$OU_ID
        INTO :V$OBJ_ID;

        IF (V$OBJ_ID IS NULL) THEN
        BEGIN
            SELECT OBJ_ID FROM OBJECT_ADD(:V$OU_ID, 282) INTO :V$OBJ_ID;
            SELECT BLOB_ID FROM VAL_ADD(2308, :V$OBJ_ID, 0) INTO :V$BLOB_ID;
        END

        V$OBJ_ID = NULL;
        SELECT L.OBJ_ID
        FROM LINKS L
        
        JOIN VALI V2284
        ON V2284.PARAM_ID = 2308
        AND V2284.IS_DEL = 0
        AND V2284.OBJ_ID = L.OBJ_ID
        AND V2284.VAL = 1

        WHERE L.OBJ_TYPE_ID = 282
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :V$OU_ID
        INTO :V$OBJ_ID;

        IF (V$OBJ_ID IS NULL) THEN
        BEGIN
            SELECT OBJ_ID FROM OBJECT_ADD(:V$OU_ID, 282) INTO :V$OBJ_ID;
            SELECT BLOB_ID FROM VAL_ADD(2308, :V$OBJ_ID, 1) INTO :V$BLOB_ID;
        END

        V$OBJ_ID = NULL;
        SELECT L.OBJ_ID
        FROM LINKS L
        
        JOIN VALI V2284
        ON V2284.PARAM_ID = 2308
        AND V2284.IS_DEL = 0
        AND V2284.OBJ_ID = L.OBJ_ID
        AND V2284.VAL = 2

        WHERE L.OBJ_TYPE_ID = 282
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :V$OU_ID
        INTO :V$OBJ_ID;

        IF (V$OBJ_ID IS NULL) THEN
        BEGIN
            SELECT OBJ_ID FROM OBJECT_ADD(:V$OU_ID, 282) INTO :V$OBJ_ID;
            SELECT BLOB_ID FROM VAL_ADD(2308, :V$OBJ_ID, 2) INTO :V$BLOB_ID;
        END

        V$OBJ_ID = NULL;
        SELECT L.OBJ_ID
        FROM LINKS L
        
        JOIN VALI V2284
        ON V2284.PARAM_ID = 2308
        AND V2284.IS_DEL = 0
        AND V2284.OBJ_ID = L.OBJ_ID
        AND V2284.VAL = 3

        WHERE L.OBJ_TYPE_ID = 282
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :V$OU_ID
        INTO :V$OBJ_ID;

        IF (V$OBJ_ID IS NULL) THEN
        BEGIN
            SELECT OBJ_ID FROM OBJECT_ADD(:V$OU_ID, 282) INTO :V$OBJ_ID;
            SELECT BLOB_ID FROM VAL_ADD(2308, :V$OBJ_ID, 3) INTO :V$BLOB_ID;
        END



        V$OBJ_ID = NULL;
        SELECT L.OBJ_ID
        FROM LINKS L
        
        JOIN VALI V2286
        ON V2286.PARAM_ID = 2328
        AND V2286.IS_DEL = 0
        AND V2286.OBJ_ID = L.OBJ_ID
        AND V2286.VAL = 1

        WHERE L.OBJ_TYPE_ID = 283
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :V$OU_ID
        INTO :V$OBJ_ID;

        IF (V$OBJ_ID IS NULL) THEN
        BEGIN
            SELECT OBJ_ID FROM OBJECT_ADD(:V$OU_ID, 283) INTO :V$OBJ_ID;
            SELECT BLOB_ID FROM VAL_ADD(2328, :V$OBJ_ID, 1) INTO :V$BLOB_ID;
        END

        V$OBJ_ID = NULL;
        SELECT L.OBJ_ID
        FROM LINKS L
        
        JOIN VALI V2286
        ON V2286.PARAM_ID = 2328
        AND V2286.IS_DEL = 0
        AND V2286.OBJ_ID = L.OBJ_ID
        AND V2286.VAL = 2

        WHERE L.OBJ_TYPE_ID = 283
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :V$OU_ID
        INTO :V$OBJ_ID;

        IF (V$OBJ_ID IS NULL) THEN
        BEGIN
            SELECT OBJ_ID FROM OBJECT_ADD(:V$OU_ID, 283) INTO :V$OBJ_ID;
            SELECT BLOB_ID FROM VAL_ADD(2328, :V$OBJ_ID, 2) INTO :V$BLOB_ID;
        END

        V$OBJ_ID = NULL;
        SELECT L.OBJ_ID
        FROM LINKS L
        
        JOIN VALI V2286
        ON V2286.PARAM_ID = 2328
        AND V2286.IS_DEL = 0
        AND V2286.OBJ_ID = L.OBJ_ID
        AND V2286.VAL = 3

        WHERE L.OBJ_TYPE_ID = 283
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :V$OU_ID
        INTO :V$OBJ_ID;

        IF (V$OBJ_ID IS NULL) THEN
        BEGIN
            SELECT OBJ_ID FROM OBJECT_ADD(:V$OU_ID, 283) INTO :V$OBJ_ID;
            SELECT BLOB_ID FROM VAL_ADD(2328, :V$OBJ_ID, 3) INTO :V$BLOB_ID;
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PLAN_COUNT_ODOD_DISTRICT_ADD
AS
declare variable V$DISTRICT_ID bigint;
declare variable V$OBJ_ID bigint;
declare variable V$BLOB_ID bigint;
BEGIN
    SELECT OBJ_ID FROM LINKS
    WHERE OBJ_TYPE_ID = 111
    AND PARENT_ID IS NULL
    AND DATE_DEL IS NULL
    INTO :V$DISTRICT_ID;

    IF ( V$DISTRICT_ID IS NOT NULL ) THEN
    BEGIN
        V$OBJ_ID = NULL;
        SELECT L.OBJ_ID
        FROM LINKS L
        
        JOIN VALI V2286
        ON V2286.PARAM_ID = 2328
        AND V2286.IS_DEL = 0
        AND V2286.OBJ_ID = L.OBJ_ID
        AND V2286.VAL = 0

        WHERE L.OBJ_TYPE_ID = 283
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :V$DISTRICT_ID
        INTO :V$OBJ_ID;

        IF (V$OBJ_ID IS NULL) THEN
        BEGIN
            SELECT OBJ_ID FROM OBJECT_ADD(:V$DISTRICT_ID, 283) INTO :V$OBJ_ID;
            SELECT BLOB_ID FROM VAL_ADD(2328, :V$OBJ_ID, 0) INTO :V$BLOB_ID;
        END

        V$OBJ_ID = NULL;
        SELECT L.OBJ_ID
        FROM LINKS L
        
        JOIN VALI V2286
        ON V2286.PARAM_ID = 2328
        AND V2286.IS_DEL = 0
        AND V2286.OBJ_ID = L.OBJ_ID
        AND V2286.VAL = 1

        WHERE L.OBJ_TYPE_ID = 283
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :V$DISTRICT_ID
        INTO :V$OBJ_ID;

        IF (V$OBJ_ID IS NULL) THEN
        BEGIN
            SELECT OBJ_ID FROM OBJECT_ADD(:V$DISTRICT_ID, 283) INTO :V$OBJ_ID;
            SELECT BLOB_ID FROM VAL_ADD(2328, :V$OBJ_ID, 1) INTO :V$BLOB_ID;
        END

        V$OBJ_ID = NULL;
        SELECT L.OBJ_ID
        FROM LINKS L
        
        JOIN VALI V2286
        ON V2286.PARAM_ID = 2328
        AND V2286.IS_DEL = 0
        AND V2286.OBJ_ID = L.OBJ_ID
        AND V2286.VAL = 2

        WHERE L.OBJ_TYPE_ID = 283
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :V$DISTRICT_ID
        INTO :V$OBJ_ID;

        IF (V$OBJ_ID IS NULL) THEN
        BEGIN
            SELECT OBJ_ID FROM OBJECT_ADD(:V$DISTRICT_ID, 283) INTO :V$OBJ_ID;
            SELECT BLOB_ID FROM VAL_ADD(2328, :V$OBJ_ID, 2) INTO :V$BLOB_ID;
        END

        V$OBJ_ID = NULL;
        SELECT L.OBJ_ID
        FROM LINKS L
        
        JOIN VALI V2286
        ON V2286.PARAM_ID = 2328
        AND V2286.IS_DEL = 0
        AND V2286.OBJ_ID = L.OBJ_ID
        AND V2286.VAL = 3

        WHERE L.OBJ_TYPE_ID = 283
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :V$DISTRICT_ID
        INTO :V$OBJ_ID;

        IF (V$OBJ_ID IS NULL) THEN
        BEGIN
            SELECT OBJ_ID FROM OBJECT_ADD(:V$DISTRICT_ID, 283) INTO :V$OBJ_ID;
            SELECT BLOB_ID FROM VAL_ADD(2328, :V$OBJ_ID, 3) INTO :V$BLOB_ID;
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PLAN_COUNT_PUPIL_ADD
AS
declare variable V$OU_ID bigint;
declare variable V$OBJ_ID bigint;
declare variable V$BLOB_ID bigint;
BEGIN
    SELECT DISTINCT OBJ_ID FROM LINKS
    WHERE OBJ_TYPE_ID = 2
    AND DATE_DEL IS NULL
    INTO :V$OU_ID;

    IF ( V$OU_ID IS NOT NULL ) THEN
    BEGIN
        V$OBJ_ID = NULL;
        SELECT L.OBJ_ID
        FROM LINKS L
        
        JOIN VALI V2285
        ON V2285.PARAM_ID = 2285
        AND V2285.IS_DEL = 0
        AND V2285.OBJ_ID = L.OBJ_ID
        AND V2285.VAL = 0

        WHERE L.OBJ_TYPE_ID = 275
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :V$OU_ID
        INTO :V$OBJ_ID;

        IF (V$OBJ_ID IS NULL) THEN
        BEGIN
            SELECT OBJ_ID FROM OBJECT_ADD(:V$OU_ID, 275) INTO :V$OBJ_ID;
            SELECT BLOB_ID FROM VAL_ADD(2285, :V$OBJ_ID, 0) INTO :V$BLOB_ID;
        END

        V$OBJ_ID = NULL;
        SELECT L.OBJ_ID
        FROM LINKS L
        
        JOIN VALI V2285
        ON V2285.PARAM_ID = 2285
        AND V2285.IS_DEL = 0
        AND V2285.OBJ_ID = L.OBJ_ID
        AND V2285.VAL = 1

        WHERE L.OBJ_TYPE_ID = 275
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :V$OU_ID
        INTO :V$OBJ_ID;

        IF (V$OBJ_ID IS NULL) THEN
        BEGIN
            SELECT OBJ_ID FROM OBJECT_ADD(:V$OU_ID, 275) INTO :V$OBJ_ID;
            SELECT BLOB_ID FROM VAL_ADD(2285, :V$OBJ_ID, 1) INTO :V$BLOB_ID;
        END

        V$OBJ_ID = NULL;
        SELECT L.OBJ_ID
        FROM LINKS L
        
        JOIN VALI V2285
        ON V2285.PARAM_ID = 2285
        AND V2285.IS_DEL = 0
        AND V2285.OBJ_ID = L.OBJ_ID
        AND V2285.VAL = 2

        WHERE L.OBJ_TYPE_ID = 275
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :V$OU_ID
        INTO :V$OBJ_ID;

        IF (V$OBJ_ID IS NULL) THEN
        BEGIN
            SELECT OBJ_ID FROM OBJECT_ADD(:V$OU_ID, 275) INTO :V$OBJ_ID;
            SELECT BLOB_ID FROM VAL_ADD(2285, :V$OBJ_ID, 2) INTO :V$BLOB_ID;
        END

        V$OBJ_ID = NULL;
        SELECT L.OBJ_ID
        FROM LINKS L
        
        JOIN VALI V2285
        ON V2285.PARAM_ID = 2285
        AND V2285.IS_DEL = 0
        AND V2285.OBJ_ID = L.OBJ_ID
        AND V2285.VAL = 3

        WHERE L.OBJ_TYPE_ID = 275
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :V$OU_ID
        INTO :V$OBJ_ID;

        IF (V$OBJ_ID IS NULL) THEN
        BEGIN
            SELECT OBJ_ID FROM OBJECT_ADD(:V$OU_ID, 275) INTO :V$OBJ_ID;
            SELECT BLOB_ID FROM VAL_ADD(2285, :V$OBJ_ID, 3) INTO :V$BLOB_ID;
        END



        V$OBJ_ID = NULL;
        SELECT L.OBJ_ID
        FROM LINKS L
        
        JOIN VALI V2285
        ON V2285.PARAM_ID = 2287
        AND V2285.IS_DEL = 0
        AND V2285.OBJ_ID = L.OBJ_ID
        AND V2285.VAL = 1

        WHERE L.OBJ_TYPE_ID = 278
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :V$OU_ID
        INTO :V$OBJ_ID;

        IF (V$OBJ_ID IS NULL) THEN
        BEGIN
            SELECT OBJ_ID FROM OBJECT_ADD(:V$OU_ID, 278) INTO :V$OBJ_ID;
            SELECT BLOB_ID FROM VAL_ADD(2287, :V$OBJ_ID, 1) INTO :V$BLOB_ID;
        END

        V$OBJ_ID = NULL;
        SELECT L.OBJ_ID
        FROM LINKS L
        
        JOIN VALI V2285
        ON V2285.PARAM_ID = 2287
        AND V2285.IS_DEL = 0
        AND V2285.OBJ_ID = L.OBJ_ID
        AND V2285.VAL = 2

        WHERE L.OBJ_TYPE_ID = 278
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :V$OU_ID
        INTO :V$OBJ_ID;

        IF (V$OBJ_ID IS NULL) THEN
        BEGIN
            SELECT OBJ_ID FROM OBJECT_ADD(:V$OU_ID, 278) INTO :V$OBJ_ID;
            SELECT BLOB_ID FROM VAL_ADD(2287, :V$OBJ_ID, 2) INTO :V$BLOB_ID;
        END

        V$OBJ_ID = NULL;
        SELECT L.OBJ_ID
        FROM LINKS L
        
        JOIN VALI V2285
        ON V2285.PARAM_ID = 2287
        AND V2285.IS_DEL = 0
        AND V2285.OBJ_ID = L.OBJ_ID
        AND V2285.VAL = 3

        WHERE L.OBJ_TYPE_ID = 278
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :V$OU_ID
        INTO :V$OBJ_ID;

        IF (V$OBJ_ID IS NULL) THEN
        BEGIN
            SELECT OBJ_ID FROM OBJECT_ADD(:V$OU_ID, 278) INTO :V$OBJ_ID;
            SELECT BLOB_ID FROM VAL_ADD(2287, :V$OBJ_ID, 3) INTO :V$BLOB_ID;
        END
    END

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PLAN_COUNT_PUPIL_DATA_GET RETURNS (
    UYEAR VARCHAR(100),
    P1 INTEGER,
    P2 INTEGER,
    P3 INTEGER,
    P4 INTEGER,
    P5 INTEGER,
    P6 INTEGER,
    P7 INTEGER,
    P8 INTEGER,
    P9 INTEGER,
    P10 INTEGER,
    P11 INTEGER,
    NYEAR INTEGER)
AS
declare variable V$OBJ_ID bigint;
BEGIN
    FOR
        SELECT L.OBJ_ID FROM LINKS L
    
        JOIN VALI V2285
        ON V2285.PARAM_ID = 2285
        AND V2285.OBJ_ID = L.OBJ_ID
        AND V2285.IS_DEL = 0
        AND V2285.VAL = 0
        
        WHERE L.OBJ_TYPE_ID = 275
        AND L.DATE_DEL IS NULL
        AND L.PARENT_TYPE_ID = 2
        INTO :V$OBJ_ID
    DO
    BEGIN
        P1 = NULL;
        P2 = NULL;
        P3 = NULL;
        P4 = NULL;
        P5 = NULL;
        P6 = NULL;
        P7 = NULL;
        P8 = NULL;
        P9 = NULL;
        P10 = NULL;
        P11 = NULL;

        NYEAR = 0;

        SELECT V.V
        FROM VAL_GET(:V$OBJ_ID, 2288) V
        INTO :UYEAR;

        SELECT V.V
        FROM VAL_GET(:V$OBJ_ID, 2237) V
        INTO :P1;

        SELECT V.V
        FROM VAL_GET(:V$OBJ_ID, 2238) V
        INTO :P2;

        SELECT V.V
        FROM VAL_GET(:V$OBJ_ID, 2239) V
        INTO :P3;

        SELECT V.V
        FROM VAL_GET(:V$OBJ_ID, 2240) V
        INTO :P4;

        SELECT V.V
        FROM VAL_GET(:V$OBJ_ID, 2241) V
        INTO :P5;

        SELECT V.V
        FROM VAL_GET(:V$OBJ_ID, 2242) V
        INTO :P6;

        SELECT V.V
        FROM VAL_GET(:V$OBJ_ID, 2243) V
        INTO :P7;

        SELECT V.V
        FROM VAL_GET(:V$OBJ_ID, 2244) V
        INTO :P8;

        SELECT V.V
        FROM VAL_GET(:V$OBJ_ID, 2245) V
        INTO :P9;

        SELECT V.V
        FROM VAL_GET(:V$OBJ_ID, 2246) V
        INTO :P10;

        SELECT V.V
        FROM VAL_GET(:V$OBJ_ID, 2247) V
        INTO :P11;

        SUSPEND;
    END
    
    FOR
        SELECT L.OBJ_ID, V2286.VAL FROM LINKS L
    
        JOIN VALI V2286
        ON V2286.PARAM_ID = 2287
        AND V2286.OBJ_ID = L.OBJ_ID
        AND V2286.IS_DEL = 0
        
        WHERE L.OBJ_TYPE_ID = 278
        AND L.DATE_DEL IS NULL
        AND L.PARENT_TYPE_ID = 2
        
        ORDER BY V2286.VAL
        INTO :V$OBJ_ID, :NYEAR
    DO
    BEGIN
        P1 = NULL;
        P2 = NULL;
        P3 = NULL;
        P4 = NULL;
        P5 = NULL;
        P6 = NULL;
        P7 = NULL;
        P8 = NULL;
        P9 = NULL;
        P10 = NULL;
        P11 = NULL;

        SELECT V.V
        FROM VAL_GET(:V$OBJ_ID, 2268) V
        INTO :UYEAR;

        SELECT V.VAL
        FROM VALI V
        WHERE V.PARAM_ID = 2269
        AND V.IS_DEL = 0
        AND V.OBJ_ID = :V$OBJ_ID
        INTO :P1;

        SELECT V.VAL
        FROM VALI V
        WHERE V.PARAM_ID = 2270
        AND V.IS_DEL = 0
        AND V.OBJ_ID = :V$OBJ_ID
        INTO :P2;

        SELECT V.VAL
        FROM VALI V
        WHERE V.PARAM_ID = 2271
        AND V.IS_DEL = 0
        AND V.OBJ_ID = :V$OBJ_ID
        INTO :P3;

        SELECT V.VAL
        FROM VALI V
        WHERE V.PARAM_ID = 2272
        AND V.IS_DEL = 0
        AND V.OBJ_ID = :V$OBJ_ID
        INTO :P4;

        SELECT V.VAL
        FROM VALI V
        WHERE V.PARAM_ID = 2273
        AND V.IS_DEL = 0
        AND V.OBJ_ID = :V$OBJ_ID
        INTO :P5;

        SELECT V.VAL
        FROM VALI V
        WHERE V.PARAM_ID = 2274
        AND V.IS_DEL = 0
        AND V.OBJ_ID = :V$OBJ_ID
        INTO :P6;

        SELECT V.VAL
        FROM VALI V
        WHERE V.PARAM_ID = 2275
        AND V.IS_DEL = 0
        AND V.OBJ_ID = :V$OBJ_ID
        INTO :P7;

        SELECT V.VAL
        FROM VALI V
        WHERE V.PARAM_ID = 2276
        AND V.IS_DEL = 0
        AND V.OBJ_ID = :V$OBJ_ID
        INTO :P8;

        SELECT V.VAL
        FROM VALI V
        WHERE V.PARAM_ID = 2277
        AND V.IS_DEL = 0
        AND V.OBJ_ID = :V$OBJ_ID
        INTO :P9;

        SELECT V.VAL
        FROM VALI V
        WHERE V.PARAM_ID = 2278
        AND V.IS_DEL = 0
        AND V.OBJ_ID = :V$OBJ_ID
        INTO :P10;

        SELECT V.VAL
        FROM VALI V
        WHERE V.PARAM_ID = 2279
        AND V.IS_DEL = 0
        AND V.OBJ_ID = :V$OBJ_ID
        INTO :P11;

        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PLAN_COUNT_PUPIL_DATA_SET (
    I$P1 INTEGER,
    I$P2 INTEGER,
    I$P3 INTEGER,
    I$P4 INTEGER,
    I$P5 INTEGER,
    I$P6 INTEGER,
    I$P7 INTEGER,
    I$P8 INTEGER,
    I$P9 INTEGER,
    I$P10 INTEGER,
    I$P11 INTEGER,
    I$NYEAR INTEGER)
AS
declare variable V$OBJ_ID bigint;
declare variable V$BLOB_ID bigint;
BEGIN
    SELECT L.OBJ_ID FROM LINKS L
    
    JOIN VALI V2287
    ON V2287.PARAM_ID = 2287
    AND V2287.OBJ_ID = L.OBJ_ID
    AND V2287.IS_DEL = 0
    AND V2287.VAL = :I$NYEAR
    
    WHERE L.OBJ_TYPE_ID = 278
    AND L.DATE_DEL IS NULL
    AND L.PARENT_TYPE_ID = 2
    
    ORDER BY V2287.VAL
    INTO :V$OBJ_ID;

    IF (V$OBJ_ID IS NOT NULL) THEN
    BEGIN
        SELECT BLOB_ID FROM VAL_ADD(2269,:V$OBJ_ID, 0, NULL, 1) INTO :V$BLOB_ID;
        IF (:I$P1 IS NOT NULL) THEN
        BEGIN
            SELECT BLOB_ID FROM VAL_ADD(2269,:V$OBJ_ID,:I$P1) INTO :V$BLOB_ID;
        END

        SELECT BLOB_ID FROM VAL_ADD(2270,:V$OBJ_ID, 0, NULL, 1) INTO :V$BLOB_ID;
        IF (:I$P2 IS NOT NULL) THEN
        BEGIN
            SELECT BLOB_ID FROM VAL_ADD(2270,:V$OBJ_ID,:I$P2) INTO :V$BLOB_ID;
        END

        SELECT BLOB_ID FROM VAL_ADD(2271,:V$OBJ_ID, 0, NULL, 1) INTO :V$BLOB_ID;
        IF (:I$P3 IS NOT NULL) THEN
        BEGIN
            SELECT BLOB_ID FROM VAL_ADD(2271,:V$OBJ_ID,:I$P3) INTO :V$BLOB_ID;
        END
        
        SELECT BLOB_ID FROM VAL_ADD(2272,:V$OBJ_ID, 0, NULL, 1) INTO :V$BLOB_ID;
        IF (:I$P4 IS NOT NULL) THEN
        BEGIN
            SELECT BLOB_ID FROM VAL_ADD(2272,:V$OBJ_ID,:I$P4) INTO :V$BLOB_ID;
        END

        SELECT BLOB_ID FROM VAL_ADD(2273,:V$OBJ_ID, 0, NULL, 1) INTO :V$BLOB_ID;
        IF (:I$P5 IS NOT NULL) THEN
        BEGIN
            SELECT BLOB_ID FROM VAL_ADD(2273,:V$OBJ_ID,:I$P5) INTO :V$BLOB_ID;
        END

        SELECT BLOB_ID FROM VAL_ADD(2274,:V$OBJ_ID, 0, NULL, 1) INTO :V$BLOB_ID;
        IF (:I$P6 IS NOT NULL) THEN
        BEGIN
            SELECT BLOB_ID FROM VAL_ADD(2274,:V$OBJ_ID,:I$P6) INTO :V$BLOB_ID;
        END

        SELECT BLOB_ID FROM VAL_ADD(2275,:V$OBJ_ID, 0, NULL, 1) INTO :V$BLOB_ID;
        IF (:I$P7 IS NOT NULL) THEN
        BEGIN
            SELECT BLOB_ID FROM VAL_ADD(2275,:V$OBJ_ID,:I$P7) INTO :V$BLOB_ID;
        END

        SELECT BLOB_ID FROM VAL_ADD(2276,:V$OBJ_ID, 0, NULL, 1) INTO :V$BLOB_ID;
        IF (:I$P8 IS NOT NULL) THEN
        BEGIN
            SELECT BLOB_ID FROM VAL_ADD(2276,:V$OBJ_ID,:I$P8) INTO :V$BLOB_ID;
        END

        SELECT BLOB_ID FROM VAL_ADD(2277,:V$OBJ_ID, 0, NULL, 1) INTO :V$BLOB_ID;
        IF (:I$P9 IS NOT NULL) THEN
        BEGIN
            SELECT BLOB_ID FROM VAL_ADD(2277,:V$OBJ_ID,:I$P9) INTO :V$BLOB_ID;
        END

        SELECT BLOB_ID FROM VAL_ADD(2278,:V$OBJ_ID, 0, NULL, 1) INTO :V$BLOB_ID;
        IF (:I$P10 IS NOT NULL) THEN
        BEGIN
            SELECT BLOB_ID FROM VAL_ADD(2278,:V$OBJ_ID,:I$P10) INTO :V$BLOB_ID;
        END

        SELECT BLOB_ID FROM VAL_ADD(2279,:V$OBJ_ID, 0, NULL, 1) INTO :V$BLOB_ID;
        IF (:I$P11 IS NOT NULL) THEN
        BEGIN
            SELECT BLOB_ID FROM VAL_ADD(2279,:V$OBJ_ID,:I$P11) INTO :V$BLOB_ID;
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PLAN_COUNT_PUPIL_DISTRICT_ADD
AS
declare variable V$DISTRICT_ID bigint;
declare variable V$OBJ_ID bigint;
declare variable V$BLOB_ID bigint;
BEGIN
    SELECT OBJ_ID FROM LINKS
    WHERE OBJ_TYPE_ID = 111
    AND PARENT_ID IS NULL
    AND DATE_DEL IS NULL
    INTO :V$DISTRICT_ID;

    IF ( V$DISTRICT_ID IS NOT NULL ) THEN
    BEGIN
        V$OBJ_ID = NULL;
        SELECT L.OBJ_ID
        FROM LINKS L
        
        JOIN VALI V2285
        ON V2285.PARAM_ID = 2287
        AND V2285.IS_DEL = 0
        AND V2285.OBJ_ID = L.OBJ_ID
        AND V2285.VAL = 0
        
        WHERE L.OBJ_TYPE_ID = 278
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :V$DISTRICT_ID
        INTO :V$OBJ_ID;

        IF (V$OBJ_ID IS NULL) THEN
        BEGIN
            SELECT OBJ_ID FROM OBJECT_ADD(:V$DISTRICT_ID, 278) INTO :V$OBJ_ID;
            SELECT BLOB_ID FROM VAL_ADD(2287, :V$OBJ_ID, 0) INTO :V$BLOB_ID;
            SELECT BLOB_ID FROM VAL_ADD(2331, :V$OBJ_ID, 2) INTO :V$BLOB_ID;
        END

        V$OBJ_ID = NULL;
        SELECT L.OBJ_ID
        FROM LINKS L
        
        JOIN VALI V2285
        ON V2285.PARAM_ID = 2287
        AND V2285.IS_DEL = 0
        AND V2285.OBJ_ID = L.OBJ_ID
        AND V2285.VAL = 1
        
        WHERE L.OBJ_TYPE_ID = 278
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :V$DISTRICT_ID
        INTO :V$OBJ_ID;

        IF (V$OBJ_ID IS NULL) THEN
        BEGIN
            SELECT OBJ_ID FROM OBJECT_ADD(:V$DISTRICT_ID, 278) INTO :V$OBJ_ID;
            SELECT BLOB_ID FROM VAL_ADD(2287, :V$OBJ_ID, 1) INTO :V$BLOB_ID;
            SELECT BLOB_ID FROM VAL_ADD(2331, :V$OBJ_ID, 2) INTO :V$BLOB_ID;
        END

        V$OBJ_ID = NULL;
        SELECT L.OBJ_ID
        FROM LINKS L
        
        JOIN VALI V2285
        ON V2285.PARAM_ID = 2287
        AND V2285.IS_DEL = 0
        AND V2285.OBJ_ID = L.OBJ_ID
        AND V2285.VAL = 2
        
        WHERE L.OBJ_TYPE_ID = 278
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :V$DISTRICT_ID
        INTO :V$OBJ_ID;

        IF (V$OBJ_ID IS NULL) THEN
        BEGIN
            SELECT OBJ_ID FROM OBJECT_ADD(:V$DISTRICT_ID, 278) INTO :V$OBJ_ID;
            SELECT BLOB_ID FROM VAL_ADD(2287, :V$OBJ_ID, 2) INTO :V$BLOB_ID;
            SELECT BLOB_ID FROM VAL_ADD(2331, :V$OBJ_ID, 2) INTO :V$BLOB_ID;
        END

        V$OBJ_ID = NULL;
        SELECT L.OBJ_ID
        FROM LINKS L
        
        JOIN VALI V2285
        ON V2285.PARAM_ID = 2287
        AND V2285.IS_DEL = 0
        AND V2285.OBJ_ID = L.OBJ_ID
        AND V2285.VAL = 3
        
        WHERE L.OBJ_TYPE_ID = 278
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :V$DISTRICT_ID
        INTO :V$OBJ_ID;

        IF (V$OBJ_ID IS NULL) THEN
        BEGIN
            SELECT OBJ_ID FROM OBJECT_ADD(:V$DISTRICT_ID, 278) INTO :V$OBJ_ID;
            SELECT BLOB_ID FROM VAL_ADD(2287, :V$OBJ_ID, 3) INTO :V$BLOB_ID;
            SELECT BLOB_ID FROM VAL_ADD(2331, :V$OBJ_ID, 2) INTO :V$BLOB_ID;
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PLAN_COUNT_PUPIL_REGION_ADD
AS
declare variable V$REGION_ID bigint;
declare variable V$OBJ_ID bigint;
declare variable V$BLOB_ID bigint;
BEGIN
    SELECT OBJ_ID FROM LINKS
    WHERE OBJ_TYPE_ID = 112
    AND PARENT_ID IS NULL
    AND DATE_DEL IS NULL
    INTO :V$REGION_ID;

    IF ( V$REGION_ID IS NOT NULL ) THEN
    BEGIN
        V$OBJ_ID = NULL;
        SELECT L.OBJ_ID
        FROM LINKS L
        
        JOIN VALI V2285
        ON V2285.PARAM_ID = 2287
        AND V2285.IS_DEL = 0
        AND V2285.OBJ_ID = L.OBJ_ID
        AND V2285.VAL = 0
        
        WHERE L.OBJ_TYPE_ID = 278
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :V$REGION_ID
        INTO :V$OBJ_ID;

        IF (V$OBJ_ID IS NULL) THEN
        BEGIN
            SELECT OBJ_ID FROM OBJECT_ADD(:V$REGION_ID, 278) INTO :V$OBJ_ID;
            SELECT BLOB_ID FROM VAL_ADD(2287, :V$OBJ_ID, 0) INTO :V$BLOB_ID;
            SELECT BLOB_ID FROM VAL_ADD(2331, :V$OBJ_ID, 2) INTO :V$BLOB_ID;
        END

        V$OBJ_ID = NULL;
        SELECT L.OBJ_ID
        FROM LINKS L
        
        JOIN VALI V2285
        ON V2285.PARAM_ID = 2287
        AND V2285.IS_DEL = 0
        AND V2285.OBJ_ID = L.OBJ_ID
        AND V2285.VAL = 1
        
        WHERE L.OBJ_TYPE_ID = 278
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :V$REGION_ID
        INTO :V$OBJ_ID;

        IF (V$OBJ_ID IS NULL) THEN
        BEGIN
            SELECT OBJ_ID FROM OBJECT_ADD(:V$REGION_ID, 278) INTO :V$OBJ_ID;
            SELECT BLOB_ID FROM VAL_ADD(2287, :V$OBJ_ID, 1) INTO :V$BLOB_ID;
            SELECT BLOB_ID FROM VAL_ADD(2331, :V$OBJ_ID, 2) INTO :V$BLOB_ID;
        END

        V$OBJ_ID = NULL;
        SELECT L.OBJ_ID
        FROM LINKS L
        
        JOIN VALI V2285
        ON V2285.PARAM_ID = 2287
        AND V2285.IS_DEL = 0
        AND V2285.OBJ_ID = L.OBJ_ID
        AND V2285.VAL = 2
        
        WHERE L.OBJ_TYPE_ID = 278
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :V$REGION_ID
        INTO :V$OBJ_ID;

        IF (V$OBJ_ID IS NULL) THEN
        BEGIN
            SELECT OBJ_ID FROM OBJECT_ADD(:V$REGION_ID, 278) INTO :V$OBJ_ID;
            SELECT BLOB_ID FROM VAL_ADD(2287, :V$OBJ_ID, 2) INTO :V$BLOB_ID;
            SELECT BLOB_ID FROM VAL_ADD(2331, :V$OBJ_ID, 2) INTO :V$BLOB_ID;
        END

        V$OBJ_ID = NULL;
        SELECT L.OBJ_ID
        FROM LINKS L
        
        JOIN VALI V2285
        ON V2285.PARAM_ID = 2287
        AND V2285.IS_DEL = 0
        AND V2285.OBJ_ID = L.OBJ_ID
        AND V2285.VAL = 3
        
        WHERE L.OBJ_TYPE_ID = 278
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :V$REGION_ID
        INTO :V$OBJ_ID;

        IF (V$OBJ_ID IS NULL) THEN
        BEGIN
            SELECT OBJ_ID FROM OBJECT_ADD(:V$REGION_ID, 278) INTO :V$OBJ_ID;
            SELECT BLOB_ID FROM VAL_ADD(2287, :V$OBJ_ID, 3) INTO :V$BLOB_ID;
            SELECT BLOB_ID FROM VAL_ADD(2331, :V$OBJ_ID, 2) INTO :V$BLOB_ID;
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PLAN_COUNT_PUPIL_TO_DISTR_COPY
AS
declare variable V$OBJ_ID bigint;
declare variable V$YEAR_NUMBER integer;
declare variable V$LISTVAL integer;
declare variable V$COUNT integer;
declare variable V$BLOB_ID bigint;
BEGIN
    FOR
        SELECT L278.OBJ_ID,
         V2287.VAL,
         V2331.LISTVAL_ID
        FROM LINKS L111
        
        JOIN LINKS L278
        ON L278.OBJ_TYPE_ID = 278
        AND L278.DATE_DEL IS NULL
        AND L278.PARENT_ID = L111.OBJ_ID
        
        JOIN VALI V2287
        ON V2287.PARAM_ID = 2287
        AND V2287.OBJ_ID = L278.OBJ_ID
        AND V2287.IS_DEL = 0
        
        JOIN VALL V2331
        ON V2331.PARAM_ID = 2331
        AND V2331.OBJ_ID = L278.OBJ_ID
        AND V2331.IS_DEL = 0
    
        WHERE L111.OBJ_TYPE_ID = 111
        AND L111.DATE_DEL IS NULL
        AND L111.PARENT_ID IS NULL
        INTO :V$OBJ_ID, :V$YEAR_NUMBER, :V$LISTVAL
    DO
    BEGIN
        IF (V$LISTVAL = 2) THEN
        BEGIN
            --1 параллель
            V$COUNT = 0;

            SELECT BLOB_ID FROM VAL_ADD(2269, :V$OBJ_ID, :V$COUNT, NULL, 1) INTO :V$BLOB_ID;

            SELECT SUM(COALESCE(CAST(V2237.V AS INTEGER),0))
            FROM LINKS L111
            
            JOIN LINKS L2
            ON L2.OBJ_TYPE_ID = 2
            AND L2.DATE_DEL IS NULL
            AND L2.PARENT_ID = L111.OBJ_ID
            
            JOIN LINKS L275
            ON L275.OBJ_TYPE_ID = 275
            AND L275.DATE_DEL IS NULL
            AND L275.PARENT_ID = L2.OBJ_ID
            
            JOIN VALI V2285
            ON V2285.PARAM_ID = 2285
            AND V2285.OBJ_ID = L275.OBJ_ID
            AND V2285.IS_DEL = 0
            AND V2285.VAL = :V$YEAR_NUMBER
            
            LEFT JOIN VAL_GET(L275.OBJ_ID, 2237) V2237 ON 1=1
            
            WHERE L111.OBJ_TYPE_ID = 111
            AND L111.DATE_DEL IS NULL
            AND L111.PARENT_ID IS NULL
            INTO :V$COUNT;

            SELECT BLOB_ID FROM VAL_ADD(2269, :V$OBJ_ID, :V$COUNT) INTO :V$BLOB_ID;

            --2 параллель
            V$COUNT = 0;

            SELECT BLOB_ID FROM VAL_ADD(2270, :V$OBJ_ID, :V$COUNT, NULL, 1) INTO :V$BLOB_ID;

            SELECT SUM(COALESCE(CAST(V2238.V AS INTEGER),0))
            FROM LINKS L111
            
            JOIN LINKS L2
            ON L2.OBJ_TYPE_ID = 2
            AND L2.DATE_DEL IS NULL
            AND L2.PARENT_ID = L111.OBJ_ID
            
            JOIN LINKS L275
            ON L275.OBJ_TYPE_ID = 275
            AND L275.DATE_DEL IS NULL
            AND L275.PARENT_ID = L2.OBJ_ID
            
            JOIN VALI V2285
            ON V2285.PARAM_ID = 2285
            AND V2285.OBJ_ID = L275.OBJ_ID
            AND V2285.IS_DEL = 0
            AND V2285.VAL = :V$YEAR_NUMBER
            
            LEFT JOIN VAL_GET(L275.OBJ_ID, 2238) V2238 ON 1=1
            
            WHERE L111.OBJ_TYPE_ID = 111
            AND L111.DATE_DEL IS NULL
            AND L111.PARENT_ID IS NULL
            INTO :V$COUNT;

            SELECT BLOB_ID FROM VAL_ADD(2270, :V$OBJ_ID, :V$COUNT) INTO :V$BLOB_ID;

            --3 параллель
            V$COUNT = 0;

            SELECT BLOB_ID FROM VAL_ADD(2271, :V$OBJ_ID, :V$COUNT, NULL, 1) INTO :V$BLOB_ID;

            SELECT SUM(COALESCE(CAST(V2239.V AS INTEGER),0))
            FROM LINKS L111
            
            JOIN LINKS L2
            ON L2.OBJ_TYPE_ID = 2
            AND L2.DATE_DEL IS NULL
            AND L2.PARENT_ID = L111.OBJ_ID
            
            JOIN LINKS L275
            ON L275.OBJ_TYPE_ID = 275
            AND L275.DATE_DEL IS NULL
            AND L275.PARENT_ID = L2.OBJ_ID
            
            JOIN VALI V2285
            ON V2285.PARAM_ID = 2285
            AND V2285.OBJ_ID = L275.OBJ_ID
            AND V2285.IS_DEL = 0
            AND V2285.VAL = :V$YEAR_NUMBER
            
            LEFT JOIN VAL_GET(L275.OBJ_ID, 2239) V2239 ON 1=1
            
            WHERE L111.OBJ_TYPE_ID = 111
            AND L111.DATE_DEL IS NULL
            AND L111.PARENT_ID IS NULL
            INTO :V$COUNT;

            SELECT BLOB_ID FROM VAL_ADD(2271, :V$OBJ_ID, :V$COUNT) INTO :V$BLOB_ID;

            --4 параллель
            V$COUNT = 0;

            SELECT BLOB_ID FROM VAL_ADD(2272, :V$OBJ_ID, :V$COUNT, NULL, 1) INTO :V$BLOB_ID;

            SELECT SUM(COALESCE(CAST(V2240.V AS INTEGER),0))
            FROM LINKS L111
            
            JOIN LINKS L2
            ON L2.OBJ_TYPE_ID = 2
            AND L2.DATE_DEL IS NULL
            AND L2.PARENT_ID = L111.OBJ_ID
            
            JOIN LINKS L275
            ON L275.OBJ_TYPE_ID = 275
            AND L275.DATE_DEL IS NULL
            AND L275.PARENT_ID = L2.OBJ_ID
            
            JOIN VALI V2285
            ON V2285.PARAM_ID = 2285
            AND V2285.OBJ_ID = L275.OBJ_ID
            AND V2285.IS_DEL = 0
            AND V2285.VAL = :V$YEAR_NUMBER
            
            LEFT JOIN VAL_GET(L275.OBJ_ID, 2240) V2240 ON 1=1
            
            WHERE L111.OBJ_TYPE_ID = 111
            AND L111.DATE_DEL IS NULL
            AND L111.PARENT_ID IS NULL
            INTO :V$COUNT;

            SELECT BLOB_ID FROM VAL_ADD(2272, :V$OBJ_ID, :V$COUNT) INTO :V$BLOB_ID;

            --5 параллель
            V$COUNT = 0;

            SELECT BLOB_ID FROM VAL_ADD(2273, :V$OBJ_ID, :V$COUNT, NULL, 1) INTO :V$BLOB_ID;

            SELECT SUM(COALESCE(CAST(V2241.V AS INTEGER),0))
            FROM LINKS L111
            
            JOIN LINKS L2
            ON L2.OBJ_TYPE_ID = 2
            AND L2.DATE_DEL IS NULL
            AND L2.PARENT_ID = L111.OBJ_ID
            
            JOIN LINKS L275
            ON L275.OBJ_TYPE_ID = 275
            AND L275.DATE_DEL IS NULL
            AND L275.PARENT_ID = L2.OBJ_ID
            
            JOIN VALI V2285
            ON V2285.PARAM_ID = 2285
            AND V2285.OBJ_ID = L275.OBJ_ID
            AND V2285.IS_DEL = 0
            AND V2285.VAL = :V$YEAR_NUMBER
            
            LEFT JOIN VAL_GET(L275.OBJ_ID, 2241) V2241 ON 1=1
            
            WHERE L111.OBJ_TYPE_ID = 111
            AND L111.DATE_DEL IS NULL
            AND L111.PARENT_ID IS NULL
            INTO :V$COUNT;

            SELECT BLOB_ID FROM VAL_ADD(2273, :V$OBJ_ID, :V$COUNT) INTO :V$BLOB_ID;

            --6 параллель
            V$COUNT = 0;

            SELECT BLOB_ID FROM VAL_ADD(2274, :V$OBJ_ID, :V$COUNT, NULL, 1) INTO :V$BLOB_ID;

            SELECT SUM(COALESCE(CAST(V2242.V AS INTEGER),0))
            FROM LINKS L111
            
            JOIN LINKS L2
            ON L2.OBJ_TYPE_ID = 2
            AND L2.DATE_DEL IS NULL
            AND L2.PARENT_ID = L111.OBJ_ID
            
            JOIN LINKS L275
            ON L275.OBJ_TYPE_ID = 275
            AND L275.DATE_DEL IS NULL
            AND L275.PARENT_ID = L2.OBJ_ID
            
            JOIN VALI V2285
            ON V2285.PARAM_ID = 2285
            AND V2285.OBJ_ID = L275.OBJ_ID
            AND V2285.IS_DEL = 0
            AND V2285.VAL = :V$YEAR_NUMBER
            
            LEFT JOIN VAL_GET(L275.OBJ_ID, 2242) V2242 ON 1=1
            
            WHERE L111.OBJ_TYPE_ID = 111
            AND L111.DATE_DEL IS NULL
            AND L111.PARENT_ID IS NULL
            INTO :V$COUNT;

            SELECT BLOB_ID FROM VAL_ADD(2274, :V$OBJ_ID, :V$COUNT) INTO :V$BLOB_ID;

            --7 параллель
            V$COUNT = 0;

            SELECT BLOB_ID FROM VAL_ADD(2275, :V$OBJ_ID, :V$COUNT, NULL, 1) INTO :V$BLOB_ID;

            SELECT SUM(COALESCE(CAST(V2243.V AS INTEGER),0))
            FROM LINKS L111
            
            JOIN LINKS L2
            ON L2.OBJ_TYPE_ID = 2
            AND L2.DATE_DEL IS NULL
            AND L2.PARENT_ID = L111.OBJ_ID
            
            JOIN LINKS L275
            ON L275.OBJ_TYPE_ID = 275
            AND L275.DATE_DEL IS NULL
            AND L275.PARENT_ID = L2.OBJ_ID
            
            JOIN VALI V2285
            ON V2285.PARAM_ID = 2285
            AND V2285.OBJ_ID = L275.OBJ_ID
            AND V2285.IS_DEL = 0
            AND V2285.VAL = :V$YEAR_NUMBER
            
            LEFT JOIN VAL_GET(L275.OBJ_ID, 2243) V2243 ON 1=1
            
            WHERE L111.OBJ_TYPE_ID = 111
            AND L111.DATE_DEL IS NULL
            AND L111.PARENT_ID IS NULL
            INTO :V$COUNT;

            SELECT BLOB_ID FROM VAL_ADD(2275, :V$OBJ_ID, :V$COUNT) INTO :V$BLOB_ID;

            --8 параллель
            V$COUNT = 0;

            SELECT BLOB_ID FROM VAL_ADD(2276, :V$OBJ_ID, :V$COUNT, NULL, 1) INTO :V$BLOB_ID;

            SELECT SUM(COALESCE(CAST(V2244.V AS INTEGER),0))
            FROM LINKS L111
            
            JOIN LINKS L2
            ON L2.OBJ_TYPE_ID = 2
            AND L2.DATE_DEL IS NULL
            AND L2.PARENT_ID = L111.OBJ_ID
            
            JOIN LINKS L275
            ON L275.OBJ_TYPE_ID = 275
            AND L275.DATE_DEL IS NULL
            AND L275.PARENT_ID = L2.OBJ_ID
            
            JOIN VALI V2285
            ON V2285.PARAM_ID = 2285
            AND V2285.OBJ_ID = L275.OBJ_ID
            AND V2285.IS_DEL = 0
            AND V2285.VAL = :V$YEAR_NUMBER
            
            LEFT JOIN VAL_GET(L275.OBJ_ID, 2244) V2244 ON 1=1
            
            WHERE L111.OBJ_TYPE_ID = 111
            AND L111.DATE_DEL IS NULL
            AND L111.PARENT_ID IS NULL
            INTO :V$COUNT;

            SELECT BLOB_ID FROM VAL_ADD(2276, :V$OBJ_ID, :V$COUNT) INTO :V$BLOB_ID;

            --9 параллель
            V$COUNT = 0;

            SELECT BLOB_ID FROM VAL_ADD(2277, :V$OBJ_ID, :V$COUNT, NULL, 1) INTO :V$BLOB_ID;

            SELECT SUM(COALESCE(CAST(V2245.V AS INTEGER),0))
            FROM LINKS L111
            
            JOIN LINKS L2
            ON L2.OBJ_TYPE_ID = 2
            AND L2.DATE_DEL IS NULL
            AND L2.PARENT_ID = L111.OBJ_ID
            
            JOIN LINKS L275
            ON L275.OBJ_TYPE_ID = 275
            AND L275.DATE_DEL IS NULL
            AND L275.PARENT_ID = L2.OBJ_ID
            
            JOIN VALI V2285
            ON V2285.PARAM_ID = 2285
            AND V2285.OBJ_ID = L275.OBJ_ID
            AND V2285.IS_DEL = 0
            AND V2285.VAL = :V$YEAR_NUMBER
            
            LEFT JOIN VAL_GET(L275.OBJ_ID, 2245) V2245 ON 1=1
            
            WHERE L111.OBJ_TYPE_ID = 111
            AND L111.DATE_DEL IS NULL
            AND L111.PARENT_ID IS NULL
            INTO :V$COUNT;

            SELECT BLOB_ID FROM VAL_ADD(2277, :V$OBJ_ID, :V$COUNT) INTO :V$BLOB_ID;

            --10 параллель
            V$COUNT = 0;

            SELECT BLOB_ID FROM VAL_ADD(2278, :V$OBJ_ID, :V$COUNT, NULL, 1) INTO :V$BLOB_ID;

            SELECT SUM(COALESCE(CAST(V2246.V AS INTEGER),0))
            FROM LINKS L111
            
            JOIN LINKS L2
            ON L2.OBJ_TYPE_ID = 2
            AND L2.DATE_DEL IS NULL
            AND L2.PARENT_ID = L111.OBJ_ID
            
            JOIN LINKS L275
            ON L275.OBJ_TYPE_ID = 275
            AND L275.DATE_DEL IS NULL
            AND L275.PARENT_ID = L2.OBJ_ID
            
            JOIN VALI V2285
            ON V2285.PARAM_ID = 2285
            AND V2285.OBJ_ID = L275.OBJ_ID
            AND V2285.IS_DEL = 0
            AND V2285.VAL = :V$YEAR_NUMBER
            
            LEFT JOIN VAL_GET(L275.OBJ_ID, 2246) V2246 ON 1=1
            
            WHERE L111.OBJ_TYPE_ID = 111
            AND L111.DATE_DEL IS NULL
            AND L111.PARENT_ID IS NULL
            INTO :V$COUNT;

            SELECT BLOB_ID FROM VAL_ADD(2278, :V$OBJ_ID, :V$COUNT) INTO :V$BLOB_ID;

            --11 параллель
            V$COUNT = 0;

            SELECT BLOB_ID FROM VAL_ADD(2279, :V$OBJ_ID, :V$COUNT, NULL, 1) INTO :V$BLOB_ID;

            SELECT SUM(COALESCE(CAST(V2247.V AS INTEGER),0))
            FROM LINKS L111
            
            JOIN LINKS L2
            ON L2.OBJ_TYPE_ID = 2
            AND L2.DATE_DEL IS NULL
            AND L2.PARENT_ID = L111.OBJ_ID
            
            JOIN LINKS L275
            ON L275.OBJ_TYPE_ID = 275
            AND L275.DATE_DEL IS NULL
            AND L275.PARENT_ID = L2.OBJ_ID
            
            JOIN VALI V2285
            ON V2285.PARAM_ID = 2285
            AND V2285.OBJ_ID = L275.OBJ_ID
            AND V2285.IS_DEL = 0
            AND V2285.VAL = :V$YEAR_NUMBER
            
            LEFT JOIN VAL_GET(L275.OBJ_ID, 2247) V2247 ON 1=1
            
            WHERE L111.OBJ_TYPE_ID = 111
            AND L111.DATE_DEL IS NULL
            AND L111.PARENT_ID IS NULL
            INTO :V$COUNT;

            SELECT BLOB_ID FROM VAL_ADD(2279, :V$OBJ_ID, :V$COUNT) INTO :V$BLOB_ID;
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PLAN_COUNT_PUPIL_TO_REGION_COPY
AS
declare variable V$OBJ_ID bigint;
declare variable V$YEAR_NUMBER integer;
declare variable V$LISTVAL integer;
declare variable V$COUNT integer;
declare variable V$BLOB_ID bigint;
BEGIN
    FOR
       SELECT L278.OBJ_ID,
         V2287.VAL,
         V2331.LISTVAL_ID
        FROM LINKS L112
        
        JOIN LINKS L278
        ON L278.OBJ_TYPE_ID = 278
        AND L278.DATE_DEL IS NULL
        AND L278.PARENT_ID = L112.OBJ_ID
        
        JOIN VALI V2287
        ON V2287.PARAM_ID = 2287
        AND V2287.OBJ_ID = L278.OBJ_ID
        AND V2287.IS_DEL = 0
        
        JOIN VALL V2331
        ON V2331.PARAM_ID = 2331
        AND V2331.OBJ_ID = L278.OBJ_ID
        AND V2331.IS_DEL = 0
        
        WHERE L112.OBJ_TYPE_ID = 112
        AND L112.DATE_DEL IS NULL
        AND L112.PARENT_ID IS NULL
        INTO :V$OBJ_ID, :V$YEAR_NUMBER, :V$LISTVAL
    DO
    BEGIN
        IF (V$LISTVAL = 2) THEN
        BEGIN
            --1 параллель
            V$COUNT = 0;

            SELECT BLOB_ID FROM VAL_ADD(2269, :V$OBJ_ID, :V$COUNT, NULL, 1) INTO :V$BLOB_ID;

            SELECT COALESCE(SUM(COALESCE(CAST(V2269.VAL AS INTEGER),0)),0)
            FROM LINKS L112
            
            JOIN LINKS L111
            ON L111.OBJ_TYPE_ID = 111
            AND L111.DATE_DEL IS NULL
            AND L111.PARENT_ID = L112.OBJ_ID
            
            JOIN LINKS L278
            ON L278.OBJ_TYPE_ID = 278
            AND L278.DATE_DEL IS NULL
            AND L278.PARENT_ID = L111.OBJ_ID
            
            JOIN VALI V2287
            ON V2287.PARAM_ID = 2287
            AND V2287.OBJ_ID = L278.OBJ_ID
            AND V2287.IS_DEL = 0
            AND V2287.VAL = :V$YEAR_NUMBER
            
            JOIN VALI V2269
            ON V2269.OBJ_ID = L278.OBJ_ID
            AND V2269.PARAM_ID = 2269
            AND V2269.IS_DEL = 0
            
            WHERE L112.OBJ_TYPE_ID = 112
            AND L112.DATE_DEL IS NULL
            AND L112.PARENT_ID IS NULL
            INTO :V$COUNT;

            SELECT BLOB_ID FROM VAL_ADD(2269, :V$OBJ_ID, :V$COUNT) INTO :V$BLOB_ID;

            --2 параллель
            V$COUNT = 0;

            SELECT BLOB_ID FROM VAL_ADD(2270, :V$OBJ_ID, :V$COUNT, NULL, 1) INTO :V$BLOB_ID;

            SELECT COALESCE(SUM(COALESCE(CAST(V2269.VAL AS INTEGER),0)),0)
            FROM LINKS L112
            
            JOIN LINKS L111
            ON L111.OBJ_TYPE_ID = 111
            AND L111.DATE_DEL IS NULL
            AND L111.PARENT_ID = L112.OBJ_ID
            
            JOIN LINKS L278
            ON L278.OBJ_TYPE_ID = 278
            AND L278.DATE_DEL IS NULL
            AND L278.PARENT_ID = L111.OBJ_ID
            
            JOIN VALI V2287
            ON V2287.PARAM_ID = 2287
            AND V2287.OBJ_ID = L278.OBJ_ID
            AND V2287.IS_DEL = 0
            AND V2287.VAL = :V$YEAR_NUMBER
            
            JOIN VALI V2269
            ON V2269.OBJ_ID = L278.OBJ_ID
            AND V2269.PARAM_ID = 2270
            AND V2269.IS_DEL = 0

            WHERE L112.OBJ_TYPE_ID = 112
            AND L112.DATE_DEL IS NULL
            AND L112.PARENT_ID IS NULL
            INTO :V$COUNT;

            SELECT BLOB_ID FROM VAL_ADD(2270, :V$OBJ_ID, :V$COUNT) INTO :V$BLOB_ID;

            --3 параллель
            V$COUNT = 0;

            SELECT BLOB_ID FROM VAL_ADD(2271, :V$OBJ_ID, :V$COUNT, NULL, 1) INTO :V$BLOB_ID;

            SELECT COALESCE(SUM(COALESCE(CAST(V2269.VAL AS INTEGER),0)),0)
            FROM LINKS L112
            
            JOIN LINKS L111
            ON L111.OBJ_TYPE_ID = 111
            AND L111.DATE_DEL IS NULL
            AND L111.PARENT_ID = L112.OBJ_ID
            
            JOIN LINKS L278
            ON L278.OBJ_TYPE_ID = 278
            AND L278.DATE_DEL IS NULL
            AND L278.PARENT_ID = L111.OBJ_ID
            
            JOIN VALI V2287
            ON V2287.PARAM_ID = 2287
            AND V2287.OBJ_ID = L278.OBJ_ID
            AND V2287.IS_DEL = 0
            AND V2287.VAL = :V$YEAR_NUMBER
            
            JOIN VALI V2269
            ON V2269.OBJ_ID = L278.OBJ_ID
            AND V2269.PARAM_ID = 2271
            AND V2269.IS_DEL = 0
            
            WHERE L112.OBJ_TYPE_ID = 112
            AND L112.DATE_DEL IS NULL
            AND L112.PARENT_ID IS NULL
            INTO :V$COUNT;

            SELECT BLOB_ID FROM VAL_ADD(2271, :V$OBJ_ID, :V$COUNT) INTO :V$BLOB_ID;

            --4 параллель
            V$COUNT = 0;

            SELECT BLOB_ID FROM VAL_ADD(2272, :V$OBJ_ID, :V$COUNT, NULL, 1) INTO :V$BLOB_ID;

            SELECT COALESCE(SUM(COALESCE(CAST(V2269.VAL AS INTEGER),0)),0)
            FROM LINKS L112
            
            JOIN LINKS L111
            ON L111.OBJ_TYPE_ID = 111
            AND L111.DATE_DEL IS NULL
            AND L111.PARENT_ID = L112.OBJ_ID
            
            JOIN LINKS L278
            ON L278.OBJ_TYPE_ID = 278
            AND L278.DATE_DEL IS NULL
            AND L278.PARENT_ID = L111.OBJ_ID
            
            JOIN VALI V2287
            ON V2287.PARAM_ID = 2287
            AND V2287.OBJ_ID = L278.OBJ_ID
            AND V2287.IS_DEL = 0
            AND V2287.VAL = :V$YEAR_NUMBER
            
            JOIN VALI V2269
            ON V2269.OBJ_ID = L278.OBJ_ID
            AND V2269.PARAM_ID = 2272
            AND V2269.IS_DEL = 0
            
            WHERE L112.OBJ_TYPE_ID = 112
            AND L112.DATE_DEL IS NULL
            AND L112.PARENT_ID IS NULL
            INTO :V$COUNT;

            SELECT BLOB_ID FROM VAL_ADD(2272, :V$OBJ_ID, :V$COUNT) INTO :V$BLOB_ID;

            --5 параллель
            V$COUNT = 0;

            SELECT BLOB_ID FROM VAL_ADD(2273, :V$OBJ_ID, :V$COUNT, NULL, 1) INTO :V$BLOB_ID;

            SELECT COALESCE(SUM(COALESCE(CAST(V2269.VAL AS INTEGER),0)),0)
            FROM LINKS L112
            
            JOIN LINKS L111
            ON L111.OBJ_TYPE_ID = 111
            AND L111.DATE_DEL IS NULL
            AND L111.PARENT_ID = L112.OBJ_ID
            
            JOIN LINKS L278
            ON L278.OBJ_TYPE_ID = 278
            AND L278.DATE_DEL IS NULL
            AND L278.PARENT_ID = L111.OBJ_ID
            
            JOIN VALI V2287
            ON V2287.PARAM_ID = 2287
            AND V2287.OBJ_ID = L278.OBJ_ID
            AND V2287.IS_DEL = 0
            AND V2287.VAL = :V$YEAR_NUMBER
            
            JOIN VALI V2269
            ON V2269.OBJ_ID = L278.OBJ_ID
            AND V2269.PARAM_ID = 2273
            AND V2269.IS_DEL = 0
            
            WHERE L112.OBJ_TYPE_ID = 112
            AND L112.DATE_DEL IS NULL
            AND L112.PARENT_ID IS NULL
            INTO :V$COUNT;

            SELECT BLOB_ID FROM VAL_ADD(2273, :V$OBJ_ID, :V$COUNT) INTO :V$BLOB_ID;

            --6 параллель
            V$COUNT = 0;

            SELECT BLOB_ID FROM VAL_ADD(2274, :V$OBJ_ID, :V$COUNT, NULL, 1) INTO :V$BLOB_ID;

            SELECT COALESCE(SUM(COALESCE(CAST(V2269.VAL AS INTEGER),0)),0)
            FROM LINKS L112
            
            JOIN LINKS L111
            ON L111.OBJ_TYPE_ID = 111
            AND L111.DATE_DEL IS NULL
            AND L111.PARENT_ID = L112.OBJ_ID
            
            JOIN LINKS L278
            ON L278.OBJ_TYPE_ID = 278
            AND L278.DATE_DEL IS NULL
            AND L278.PARENT_ID = L111.OBJ_ID
            
            JOIN VALI V2287
            ON V2287.PARAM_ID = 2287
            AND V2287.OBJ_ID = L278.OBJ_ID
            AND V2287.IS_DEL = 0
            AND V2287.VAL = :V$YEAR_NUMBER
            
            JOIN VALI V2269
            ON V2269.OBJ_ID = L278.OBJ_ID
            AND V2269.PARAM_ID = 2274
            AND V2269.IS_DEL = 0
            
            WHERE L112.OBJ_TYPE_ID = 112
            AND L112.DATE_DEL IS NULL
            AND L112.PARENT_ID IS NULL
            INTO :V$COUNT;

            SELECT BLOB_ID FROM VAL_ADD(2274, :V$OBJ_ID, :V$COUNT) INTO :V$BLOB_ID;

            --7 параллель
            V$COUNT = 0;

            SELECT BLOB_ID FROM VAL_ADD(2275, :V$OBJ_ID, :V$COUNT, NULL, 1) INTO :V$BLOB_ID;

            SELECT COALESCE(SUM(COALESCE(CAST(V2269.VAL AS INTEGER),0)),0)
            FROM LINKS L112
            
            JOIN LINKS L111
            ON L111.OBJ_TYPE_ID = 111
            AND L111.DATE_DEL IS NULL
            AND L111.PARENT_ID = L112.OBJ_ID
            
            JOIN LINKS L278
            ON L278.OBJ_TYPE_ID = 278
            AND L278.DATE_DEL IS NULL
            AND L278.PARENT_ID = L111.OBJ_ID
            
            JOIN VALI V2287
            ON V2287.PARAM_ID = 2287
            AND V2287.OBJ_ID = L278.OBJ_ID
            AND V2287.IS_DEL = 0
            AND V2287.VAL = :V$YEAR_NUMBER
            
            JOIN VALI V2269
            ON V2269.OBJ_ID = L278.OBJ_ID
            AND V2269.PARAM_ID = 2275
            AND V2269.IS_DEL = 0
            
            WHERE L112.OBJ_TYPE_ID = 112
            AND L112.DATE_DEL IS NULL
            AND L112.PARENT_ID IS NULL
            INTO :V$COUNT;

            SELECT BLOB_ID FROM VAL_ADD(2275, :V$OBJ_ID, :V$COUNT) INTO :V$BLOB_ID;

            --8 параллель
            V$COUNT = 0;

            SELECT BLOB_ID FROM VAL_ADD(2276, :V$OBJ_ID, :V$COUNT, NULL, 1) INTO :V$BLOB_ID;

            SELECT COALESCE(SUM(COALESCE(CAST(V2269.VAL AS INTEGER),0)),0)
            FROM LINKS L112
            
            JOIN LINKS L111
            ON L111.OBJ_TYPE_ID = 111
            AND L111.DATE_DEL IS NULL
            AND L111.PARENT_ID = L112.OBJ_ID
            
            JOIN LINKS L278
            ON L278.OBJ_TYPE_ID = 278
            AND L278.DATE_DEL IS NULL
            AND L278.PARENT_ID = L111.OBJ_ID
            
            JOIN VALI V2287
            ON V2287.PARAM_ID = 2287
            AND V2287.OBJ_ID = L278.OBJ_ID
            AND V2287.IS_DEL = 0
            AND V2287.VAL = :V$YEAR_NUMBER
            
            JOIN VALI V2269
            ON V2269.OBJ_ID = L278.OBJ_ID
            AND V2269.PARAM_ID = 2276
            AND V2269.IS_DEL = 0
            
            WHERE L112.OBJ_TYPE_ID = 112
            AND L112.DATE_DEL IS NULL
            AND L112.PARENT_ID IS NULL
            INTO :V$COUNT;

            SELECT BLOB_ID FROM VAL_ADD(2276, :V$OBJ_ID, :V$COUNT) INTO :V$BLOB_ID;

            --9 параллель
            V$COUNT = 0;

            SELECT BLOB_ID FROM VAL_ADD(2277, :V$OBJ_ID, :V$COUNT, NULL, 1) INTO :V$BLOB_ID;

            SELECT COALESCE(SUM(COALESCE(CAST(V2269.VAL AS INTEGER),0)),0)
            FROM LINKS L112
            
            JOIN LINKS L111
            ON L111.OBJ_TYPE_ID = 111
            AND L111.DATE_DEL IS NULL
            AND L111.PARENT_ID = L112.OBJ_ID
            
            JOIN LINKS L278
            ON L278.OBJ_TYPE_ID = 278
            AND L278.DATE_DEL IS NULL
            AND L278.PARENT_ID = L111.OBJ_ID
            
            JOIN VALI V2287
            ON V2287.PARAM_ID = 2287
            AND V2287.OBJ_ID = L278.OBJ_ID
            AND V2287.IS_DEL = 0
            AND V2287.VAL = :V$YEAR_NUMBER
            
            JOIN VALI V2269
            ON V2269.OBJ_ID = L278.OBJ_ID
            AND V2269.PARAM_ID = 2277
            AND V2269.IS_DEL = 0
            
            WHERE L112.OBJ_TYPE_ID = 112
            AND L112.DATE_DEL IS NULL
            AND L112.PARENT_ID IS NULL
            INTO :V$COUNT;

            SELECT BLOB_ID FROM VAL_ADD(2277, :V$OBJ_ID, :V$COUNT) INTO :V$BLOB_ID;

            --10 параллель
            V$COUNT = 0;

            SELECT BLOB_ID FROM VAL_ADD(2278, :V$OBJ_ID, :V$COUNT, NULL, 1) INTO :V$BLOB_ID;

            SELECT COALESCE(SUM(COALESCE(CAST(V2269.VAL AS INTEGER),0)),0)
            FROM LINKS L112
            
            JOIN LINKS L111
            ON L111.OBJ_TYPE_ID = 111
            AND L111.DATE_DEL IS NULL
            AND L111.PARENT_ID = L112.OBJ_ID
            
            JOIN LINKS L278
            ON L278.OBJ_TYPE_ID = 278
            AND L278.DATE_DEL IS NULL
            AND L278.PARENT_ID = L111.OBJ_ID
            
            JOIN VALI V2287
            ON V2287.PARAM_ID = 2287
            AND V2287.OBJ_ID = L278.OBJ_ID
            AND V2287.IS_DEL = 0
            AND V2287.VAL = :V$YEAR_NUMBER
            
            JOIN VALI V2269
            ON V2269.OBJ_ID = L278.OBJ_ID
            AND V2269.PARAM_ID = 2278
            AND V2269.IS_DEL = 0
            
            WHERE L112.OBJ_TYPE_ID = 112
            AND L112.DATE_DEL IS NULL
            AND L112.PARENT_ID IS NULL
            INTO :V$COUNT;

            SELECT BLOB_ID FROM VAL_ADD(2278, :V$OBJ_ID, :V$COUNT) INTO :V$BLOB_ID;

            --11 параллель
            V$COUNT = 0;

            SELECT BLOB_ID FROM VAL_ADD(2279, :V$OBJ_ID, :V$COUNT, NULL, 1) INTO :V$BLOB_ID;

            SELECT COALESCE(SUM(COALESCE(CAST(V2269.VAL AS INTEGER),0)),0)
            FROM LINKS L112
            
            JOIN LINKS L111
            ON L111.OBJ_TYPE_ID = 111
            AND L111.DATE_DEL IS NULL
            AND L111.PARENT_ID = L112.OBJ_ID
            
            JOIN LINKS L278
            ON L278.OBJ_TYPE_ID = 278
            AND L278.DATE_DEL IS NULL
            AND L278.PARENT_ID = L111.OBJ_ID
            
            JOIN VALI V2287
            ON V2287.PARAM_ID = 2287
            AND V2287.OBJ_ID = L278.OBJ_ID
            AND V2287.IS_DEL = 0
            AND V2287.VAL = :V$YEAR_NUMBER
            
            JOIN VALI V2269
            ON V2269.OBJ_ID = L278.OBJ_ID
            AND V2269.PARAM_ID = 2279
            AND V2269.IS_DEL = 0
            
            WHERE L112.OBJ_TYPE_ID = 112
            AND L112.DATE_DEL IS NULL
            AND L112.PARENT_ID IS NULL
            INTO :V$COUNT;

            SELECT BLOB_ID FROM VAL_ADD(2279, :V$OBJ_ID, :V$COUNT) INTO :V$BLOB_ID;
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PLAN_COUNT_PUPIL_TRANSFER (
    I$USER_ID BIGINT)
AS
declare variable V$OBJ_ID1 bigint;
declare variable V$OBJ_ID2 bigint;
declare variable V$OBJ_ID3 bigint;
declare variable V$BLOB_ID bigint;
declare variable V$N integer;
BEGIN
    SELECT L.OBJ_ID
    FROM LINKS L
    
    JOIN VALI V
    ON V.PARAM_ID = 2287
    AND V.OBJ_ID = L.OBJ_ID
    AND V.IS_DEL = 0
    AND V.VAL = 1
    
    WHERE L.DATE_DEL IS NULL
    AND L.OBJ_TYPE_ID = 278
    AND L.PARENT_TYPE_ID = 2
    INTO :V$OBJ_ID1;

    SELECT L.OBJ_ID
    FROM LINKS L
    
    JOIN VALI V
    ON V.PARAM_ID = 2287
    AND V.OBJ_ID = L.OBJ_ID
    AND V.IS_DEL = 0
    AND V.VAL = 2
    
    WHERE L.DATE_DEL IS NULL
    AND L.OBJ_TYPE_ID = 278
    AND L.PARENT_TYPE_ID = 2
    INTO :V$OBJ_ID2;

    SELECT L.OBJ_ID
    FROM LINKS L
    
    JOIN VALI V
    ON V.PARAM_ID = 2287
    AND V.OBJ_ID = L.OBJ_ID
    AND V.IS_DEL = 0
    AND V.VAL = 3
    
    WHERE L.DATE_DEL IS NULL
    AND L.OBJ_TYPE_ID = 278
    AND L.PARENT_TYPE_ID = 2
    INTO :V$OBJ_ID3;

--    UPDATE OR INSERT INTO VALI (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
--        VALUES (2269, :V$OBJ_ID3, :I$USER_ID, 1, 1);
--    UPDATE OR INSERT INTO VALI (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
--        VALUES (2270, :V$OBJ_ID3, :I$USER_ID, 1, 1);
--    UPDATE OR INSERT INTO VALI (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
--        VALUES (2271, :V$OBJ_ID3, :I$USER_ID, 1, 1);
--    UPDATE OR INSERT INTO VALI (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
--        VALUES (2272, :V$OBJ_ID3, :I$USER_ID, 1, 1);
--    UPDATE OR INSERT INTO VALI (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
--        VALUES (2273, :V$OBJ_ID3, :I$USER_ID, 1, 1);
--    UPDATE OR INSERT INTO VALI (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
--        VALUES (2274, :V$OBJ_ID3, :I$USER_ID, 1, 1);
--    UPDATE OR INSERT INTO VALI (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
--        VALUES (2275, :V$OBJ_ID3, :I$USER_ID, 1, 1);
--    UPDATE OR INSERT INTO VALI (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
--        VALUES (2276, :V$OBJ_ID3, :I$USER_ID, 1, 1);
--    UPDATE OR INSERT INTO VALI (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
--        VALUES (2277, :V$OBJ_ID3, :I$USER_ID, 1, 1);
--    UPDATE OR INSERT INTO VALI (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
--        VALUES (2278, :V$OBJ_ID3, :I$USER_ID, 1, 1);
--    UPDATE OR INSERT INTO VALI (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
--        VALUES (2279, :V$OBJ_ID3, :I$USER_ID, 1, 1);

    SELECT BLOB_ID FROM VAL_ADD(2269, :V$OBJ_ID3, 1, :I$USER_ID,1) INTO V$BLOB_ID;
    SELECT BLOB_ID FROM VAL_ADD(2270, :V$OBJ_ID3, 1, :I$USER_ID,1) INTO V$BLOB_ID;
    SELECT BLOB_ID FROM VAL_ADD(2271, :V$OBJ_ID3, 1, :I$USER_ID,1) INTO V$BLOB_ID;
    SELECT BLOB_ID FROM VAL_ADD(2272, :V$OBJ_ID3, 1, :I$USER_ID,1) INTO V$BLOB_ID;
    SELECT BLOB_ID FROM VAL_ADD(2273, :V$OBJ_ID3, 1, :I$USER_ID,1) INTO V$BLOB_ID;
    SELECT BLOB_ID FROM VAL_ADD(2274, :V$OBJ_ID3, 1, :I$USER_ID,1) INTO V$BLOB_ID;
    SELECT BLOB_ID FROM VAL_ADD(2275, :V$OBJ_ID3, 1, :I$USER_ID,1) INTO V$BLOB_ID;
    SELECT BLOB_ID FROM VAL_ADD(2276, :V$OBJ_ID3, 1, :I$USER_ID,1) INTO V$BLOB_ID;
    SELECT BLOB_ID FROM VAL_ADD(2277, :V$OBJ_ID3, 1, :I$USER_ID,1) INTO V$BLOB_ID;
    SELECT BLOB_ID FROM VAL_ADD(2278, :V$OBJ_ID3, 1, :I$USER_ID,1) INTO V$BLOB_ID;
    SELECT BLOB_ID FROM VAL_ADD(2279, :V$OBJ_ID3, 1, :I$USER_ID,1) INTO V$BLOB_ID;

    SELECT V.I FROM VAL_GET(:V$OBJ_ID2,2269, 0, :I$USER_ID) V INTO V$N;
    IF (V$N>0) THEN
    BEGIN
        SELECT BLOB_ID FROM VAL_ADD(2270,:V$OBJ_ID3,:V$N, :I$USER_ID) INTO V$BLOB_ID;
    END
    SELECT V.I FROM VAL_GET(:V$OBJ_ID2,2270, 0, :I$USER_ID) V INTO V$N;
    IF (V$N>0) THEN
    BEGIN
        SELECT BLOB_ID FROM VAL_ADD(2271,:V$OBJ_ID3,:V$N, :I$USER_ID) INTO V$BLOB_ID;
    END
    SELECT V.I FROM VAL_GET(:V$OBJ_ID2,2271, 0, :I$USER_ID) V INTO V$N;
    IF (V$N>0) THEN
    BEGIN
        SELECT BLOB_ID FROM VAL_ADD(2272,:V$OBJ_ID3,:V$N, :I$USER_ID) INTO V$BLOB_ID;
    END
    SELECT V.I FROM VAL_GET(:V$OBJ_ID2,2272, 0, :I$USER_ID) V INTO V$N;
    IF (V$N>0) THEN
    BEGIN
        SELECT BLOB_ID FROM VAL_ADD(2273,:V$OBJ_ID3,:V$N, :I$USER_ID) INTO V$BLOB_ID;
    END
    SELECT V.I FROM VAL_GET(:V$OBJ_ID2,2273, 0, :I$USER_ID) V INTO V$N;
    IF (V$N>0) THEN
    BEGIN
        SELECT BLOB_ID FROM VAL_ADD(2274,:V$OBJ_ID3,:V$N, :I$USER_ID) INTO V$BLOB_ID;
    END
    SELECT V.I FROM VAL_GET(:V$OBJ_ID2,2274, 0, :I$USER_ID) V INTO V$N;
    IF (V$N>0) THEN
    BEGIN
        SELECT BLOB_ID FROM VAL_ADD(2275,:V$OBJ_ID3,:V$N, :I$USER_ID) INTO V$BLOB_ID;
    END
    SELECT V.I FROM VAL_GET(:V$OBJ_ID2,2275, 0, :I$USER_ID) V INTO V$N;
    IF (V$N>0) THEN
    BEGIN
        SELECT BLOB_ID FROM VAL_ADD(2276,:V$OBJ_ID3,:V$N, :I$USER_ID) INTO V$BLOB_ID;
    END
    SELECT V.I FROM VAL_GET(:V$OBJ_ID2,2276, 0, :I$USER_ID) V INTO V$N;
    IF (V$N>0) THEN
    BEGIN
        SELECT BLOB_ID FROM VAL_ADD(2277,:V$OBJ_ID3,:V$N, :I$USER_ID) INTO V$BLOB_ID;
    END
    SELECT V.I FROM VAL_GET(:V$OBJ_ID2,2277, 0, :I$USER_ID) V INTO V$N;
    IF (V$N>0) THEN
    BEGIN
        SELECT BLOB_ID FROM VAL_ADD(2278,:V$OBJ_ID3,:V$N, :I$USER_ID) INTO V$BLOB_ID;
    END
    SELECT V.I FROM VAL_GET(:V$OBJ_ID2,2278, 0, :I$USER_ID) V INTO V$N;
    IF (V$N>0) THEN
    BEGIN
        SELECT BLOB_ID FROM VAL_ADD(2279,:V$OBJ_ID3,:V$N, :I$USER_ID) INTO V$BLOB_ID;
    END

--    UPDATE OR INSERT INTO VALI (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
--        VALUES (2269, :V$OBJ_ID2, :I$USER_ID, 1, 1);
--    UPDATE OR INSERT INTO VALI (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
--        VALUES (2270, :V$OBJ_ID2, :I$USER_ID, 1, 1);
--    UPDATE OR INSERT INTO VALI (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
--        VALUES (2271, :V$OBJ_ID2, :I$USER_ID, 1, 1);
--    UPDATE OR INSERT INTO VALI (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
--        VALUES (2272, :V$OBJ_ID2, :I$USER_ID, 1, 1);
--    UPDATE OR INSERT INTO VALI (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
--        VALUES (2273, :V$OBJ_ID2, :I$USER_ID, 1, 1);
--    UPDATE OR INSERT INTO VALI (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
--        VALUES (2274, :V$OBJ_ID2, :I$USER_ID, 1, 1);
--    UPDATE OR INSERT INTO VALI (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
--        VALUES (2275, :V$OBJ_ID2, :I$USER_ID, 1, 1);
--    UPDATE OR INSERT INTO VALI (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
--        VALUES (2276, :V$OBJ_ID2, :I$USER_ID, 1, 1);
--    UPDATE OR INSERT INTO VALI (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
--        VALUES (2277, :V$OBJ_ID2, :I$USER_ID, 1, 1);
--    UPDATE OR INSERT INTO VALI (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
--        VALUES (2278, :V$OBJ_ID2, :I$USER_ID, 1, 1);
--    UPDATE OR INSERT INTO VALI (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
--        VALUES (2279, :V$OBJ_ID2, :I$USER_ID, 1, 1);

    SELECT BLOB_ID FROM VAL_ADD(2269, :V$OBJ_ID2, 1, :I$USER_ID,1) INTO V$BLOB_ID;
    SELECT BLOB_ID FROM VAL_ADD(2270, :V$OBJ_ID2, 1, :I$USER_ID,1) INTO V$BLOB_ID;
    SELECT BLOB_ID FROM VAL_ADD(2271, :V$OBJ_ID2, 1, :I$USER_ID,1) INTO V$BLOB_ID;
    SELECT BLOB_ID FROM VAL_ADD(2272, :V$OBJ_ID2, 1, :I$USER_ID,1) INTO V$BLOB_ID;
    SELECT BLOB_ID FROM VAL_ADD(2273, :V$OBJ_ID2, 1, :I$USER_ID,1) INTO V$BLOB_ID;
    SELECT BLOB_ID FROM VAL_ADD(2274, :V$OBJ_ID2, 1, :I$USER_ID,1) INTO V$BLOB_ID;
    SELECT BLOB_ID FROM VAL_ADD(2275, :V$OBJ_ID2, 1, :I$USER_ID,1) INTO V$BLOB_ID;
    SELECT BLOB_ID FROM VAL_ADD(2276, :V$OBJ_ID2, 1, :I$USER_ID,1) INTO V$BLOB_ID;
    SELECT BLOB_ID FROM VAL_ADD(2277, :V$OBJ_ID2, 1, :I$USER_ID,1) INTO V$BLOB_ID;
    SELECT BLOB_ID FROM VAL_ADD(2278, :V$OBJ_ID2, 1, :I$USER_ID,1) INTO V$BLOB_ID;
    SELECT BLOB_ID FROM VAL_ADD(2279, :V$OBJ_ID2, 1, :I$USER_ID,1) INTO V$BLOB_ID;



    SELECT V.I FROM VAL_GET(:V$OBJ_ID1,2269, 0, :I$USER_ID) V INTO V$N;
    IF (V$N>0) THEN
    BEGIN
        SELECT BLOB_ID FROM VAL_ADD(2270,:V$OBJ_ID2,:V$N, :I$USER_ID) INTO V$BLOB_ID;
    END
    SELECT V.I FROM VAL_GET(:V$OBJ_ID1,2270, 0, :I$USER_ID) V INTO V$N;
    IF (V$N>0) THEN
    BEGIN
        SELECT BLOB_ID FROM VAL_ADD(2271,:V$OBJ_ID2,:V$N, :I$USER_ID) INTO V$BLOB_ID;
    END
    SELECT V.I FROM VAL_GET(:V$OBJ_ID1,2271, 0, :I$USER_ID) V INTO V$N;
    IF (V$N>0) THEN
    BEGIN
        SELECT BLOB_ID FROM VAL_ADD(2272,:V$OBJ_ID2,:V$N, :I$USER_ID) INTO V$BLOB_ID;
    END
    SELECT V.I FROM VAL_GET(:V$OBJ_ID1,2272, 0, :I$USER_ID) V INTO V$N;
    IF (V$N>0) THEN
    BEGIN
        SELECT BLOB_ID FROM VAL_ADD(2273,:V$OBJ_ID2,:V$N, :I$USER_ID) INTO V$BLOB_ID;
    END
    SELECT V.I FROM VAL_GET(:V$OBJ_ID1,2273, 0, :I$USER_ID) V INTO V$N;
    IF (V$N>0) THEN
    BEGIN
        SELECT BLOB_ID FROM VAL_ADD(2274,:V$OBJ_ID2,:V$N, :I$USER_ID) INTO V$BLOB_ID;
    END
    SELECT V.I FROM VAL_GET(:V$OBJ_ID1,2274, 0, :I$USER_ID) V INTO V$N;
    IF (V$N>0) THEN
    BEGIN
        SELECT BLOB_ID FROM VAL_ADD(2275,:V$OBJ_ID2,:V$N, :I$USER_ID) INTO V$BLOB_ID;
    END
    SELECT V.I FROM VAL_GET(:V$OBJ_ID1,2275, 0, :I$USER_ID) V INTO V$N;
    IF (V$N>0) THEN
    BEGIN
        SELECT BLOB_ID FROM VAL_ADD(2276,:V$OBJ_ID2,:V$N, :I$USER_ID) INTO V$BLOB_ID;
    END
    SELECT V.I FROM VAL_GET(:V$OBJ_ID1,2276, 0, :I$USER_ID) V INTO V$N;
    IF (V$N>0) THEN
    BEGIN
        SELECT BLOB_ID FROM VAL_ADD(2277,:V$OBJ_ID2,:V$N, :I$USER_ID) INTO V$BLOB_ID;
    END
    SELECT V.I FROM VAL_GET(:V$OBJ_ID1,2277, 0, :I$USER_ID) V INTO V$N;
    IF (V$N>0) THEN
    BEGIN
        SELECT BLOB_ID FROM VAL_ADD(2278,:V$OBJ_ID2,:V$N, :I$USER_ID) INTO V$BLOB_ID;
    END
    SELECT V.I FROM VAL_GET(:V$OBJ_ID1,2278, 0, :I$USER_ID) V INTO V$N;
    IF (V$N>0) THEN
    BEGIN
        SELECT BLOB_ID FROM VAL_ADD(2279,:V$OBJ_ID2,:V$N, :I$USER_ID) INTO V$BLOB_ID;
    END


    UPDATE OR INSERT INTO VALI (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
        VALUES (2269, :V$OBJ_ID1, :I$USER_ID, 1, 1);
    UPDATE OR INSERT INTO VALI (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
        VALUES (2270, :V$OBJ_ID1, :I$USER_ID, 1, 1);
    UPDATE OR INSERT INTO VALI (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
        VALUES (2271, :V$OBJ_ID1, :I$USER_ID, 1, 1);
    UPDATE OR INSERT INTO VALI (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
        VALUES (2272, :V$OBJ_ID1, :I$USER_ID, 1, 1);
    UPDATE OR INSERT INTO VALI (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
        VALUES (2273, :V$OBJ_ID1, :I$USER_ID, 1, 1);
    UPDATE OR INSERT INTO VALI (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
        VALUES (2274, :V$OBJ_ID1, :I$USER_ID, 1, 1);
    UPDATE OR INSERT INTO VALI (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
        VALUES (2275, :V$OBJ_ID1, :I$USER_ID, 1, 1);
    UPDATE OR INSERT INTO VALI (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
        VALUES (2276, :V$OBJ_ID1, :I$USER_ID, 1, 1);
    UPDATE OR INSERT INTO VALI (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
        VALUES (2277, :V$OBJ_ID1, :I$USER_ID, 1, 1);
    UPDATE OR INSERT INTO VALI (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
        VALUES (2278, :V$OBJ_ID1, :I$USER_ID, 1, 1);
    UPDATE OR INSERT INTO VALI (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
        VALUES (2279, :V$OBJ_ID1, :I$USER_ID, 1, 1);
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PLAN_DELETE_ROW (
    I$PLAN_ID BIGINT,
    I$ROW_ID BIGINT,
    I$USER_ID VARCHAR(40))
AS
declare variable V$ROW_ID bigint;
declare variable V$OBJ_ID bigint;
declare variable V$SUBJECT_ID bigint;
declare variable V$STATUS bigint;
declare variable V$ROW_TYPE smallint;
declare variable V$PARENT_ID bigint;
begin

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = -1;

  -- Проверяем статус УП
  SELECT FIRST 1 V3013.LISTVAL_ID
  FROM VALL V3013
  WHERE V3013.OBJ_ID = :I$PLAN_ID AND V3013.PARAM_ID = 3013 AND V3013.IS_DEL = 0
  INTO :V$STATUS;

  -- Рекурсивно удаляем все вложенные элементы
  FOR
    SELECT S.OBJ_ID
    FROM PLAN_SUBJECTS S
    WHERE S.DATE_DEL IS NULL AND S.PLAN_ID = :I$PLAN_ID AND S.PARENT_ID = :I$ROW_ID
    INTO :V$ROW_ID
  DO
  BEGIN
    EXECUTE PROCEDURE PLAN_DELETE_ROW(:I$PLAN_ID, :V$ROW_ID, :I$USER_ID);
  END

  -- Если мы - предмет, проверяем нет ли журналов по данному предмету у учащихся

  -- Удаляем себя, но если нас уже удалили - не ругаемся
  V$ROW_ID = NULL;
  SELECT S.OBJ_ID, S.SUBJECT_ID, S.ROW_TYPE, S.PARENT_ID
  FROM PLAN_SUBJECTS S
  WHERE S.DATE_DEL IS NULL AND S.PLAN_ID = :I$PLAN_ID AND S.OBJ_ID = :I$ROW_ID
  INTO :V$ROW_ID, :V$SUBJECT_ID, :V$ROW_TYPE, :V$PARENT_ID;

  IF(V$ROW_ID IS NULL) THEN EXIT;

  IF(EXISTS(
    SELECT FIRST 1 1
    FROM CJ2_JOURNAL J
    WHERE J.DATE_DEL IS NULL AND J.REF_ID = :I$PLAN_ID AND J.SUBJECT_ID = :V$SUBJECT_ID
  )) THEN EXCEPTION DATA_ERROR 'Нельзя удалить предмет ' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$SUBJECT_ID)) || ', когда есть связанный с ним журнал';

  UPDATE PLAN_SUBJECTS
  SET DATE_DEL = CURRENT_TIMESTAMP
  WHERE OBJ_ID = :V$ROW_ID;

  -- Удаляем связанные ресурсы
  FOR
    SELECT L.OBJ_ID
    FROM PLAN_LOADS L
    WHERE L.SUBJECT_ID = :I$ROW_ID AND L.DATE_DEL IS NULL
    INTO :V$OBJ_ID
  DO
  BEGIN
    UPDATE PLAN_RESOURCES
    SET DATE_DEL = CURRENT_TIMESTAMP
    WHERE LOAD_ID = :V$OBJ_ID AND DATE_DEL IS NULL;
  END

  -- Удаляем все строки нагрузки
  UPDATE PLAN_LOADS
  SET DATE_DEL = CURRENT_TIMESTAMP
  WHERE SUBJECT_ID = :I$ROW_ID AND DATE_DEL IS NULL;

  -- Логгируем только предметы
  IF(V$STATUS = 11715 AND V$ROW_TYPE = 10) THEN
  INSERT INTO HISTVALS
  (TABLE_NAME, OBJ_ID, USER_ID, PARAM_ID, OPT_ID, PARENT_ID, OLD_VAL, VAL)
  VALUES ('PLAN', :I$PLAN_ID, :I$USER_ID, :V$PARENT_ID, :V$SUBJECT_ID, 0, 'Удален предмет', (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$SUBJECT_ID)));

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PLAN_DELTA_SUBJECT_GET (
    I$PLAN_ID BIGINT,
    I$SRC_ID BIGINT,
    I$LEVEL_ID BIGINT)
RETURNS (
    N INTEGER,
    SUBJECTS_MISS VARCHAR(5000),
    SUBJECTS_MORE VARCHAR(5000),
    SUBJECTS_REPLACEMENT VARCHAR(5000))
AS
declare variable V$OBJ_ID bigint;
declare variable S varchar(1000);
declare variable V$MISS integer;
declare variable V$MORE integer;
declare variable V$FOP_FIX smallint;
begin

  -- Идем чисто по формальному списку предметов, игнорируя наличие часов

  N = 0;
  V$MISS = 0;
  V$MORE = 0;
  SUBJECTS_MISS = '';
  SUBJECTS_MORE = '';
  SUBJECTS_REPLACEMENT = '';

  -- Признак временной подмены Технологии в ФОП в 2023
  V$FOP_FIX = 0;
  SELECT FIRST 1 1
  FROM LINKS LP57
  JOIN VALI V3115 ON V3115.OBJ_ID = LP57.PARENT_ID AND V3115.PARAM_ID = 3115 AND V3115.IS_DEL = 0 AND V3115.VAL < 2024
  JOIN VALL V3014 ON V3014.OBJ_ID = LP57.OBJ_ID AND V3014.PARAM_ID = 3014 AND V3014.IS_DEL = 0 AND V3014.LISTVAL_ID = 14184
  WHERE LP57.OBJ_ID = :I$PLAN_ID AND LP57.PARENT_TYPE_ID = 57 AND LP57.DATE_DEL IS NULL
  INTO :V$FOP_FIX;

  FOR
    SELECT DISTINCT PS.SUBJECT_ID, C.CAPTION
    FROM PLAN_SUBJECTS PS
    JOIN PLAN_SUBJECTS PS2 ON PS2.OBJ_ID = PS.PARENT_ID AND PS2.FIELD_ID IN (13303)
    LEFT JOIN OBJECT_CAPTION_GET(PS.SUBJECT_ID) C ON 1 = 1
    WHERE PS.DATE_DEL IS NULL AND PS.PLAN_ID = :I$SRC_ID AND PS.ROW_TYPE = 10
    AND NOT EXISTS (
      SELECT FIRST 1 1
      FROM PLAN_SUBJECTS PSX
      JOIN PLAN_SUBJECTS PSX2 ON PSX2.OBJ_ID = PSX.PARENT_ID AND PSX2.FIELD_ID IN (13303)
      WHERE PSX.DATE_DEL IS NULL AND PSX.PLAN_ID = :I$PLAN_ID AND (PSX.SUBJECT_ID = PS.SUBJECT_ID OR PSX.SRC_SUBJECT_ID = PS.SUBJECT_ID
        OR (:V$FOP_FIX = 1 AND PS.SUBJECT_ID = 38703 AND (PSX.SUBJECT_ID = 200 OR PSX.SRC_SUBJECT_ID = 200))
        OR (:V$FOP_FIX = 1 AND PS.SUBJECT_ID = 38700 AND (PSX.SUBJECT_ID = 206 OR PSX.SRC_SUBJECT_ID = 206))
      )
    )
    ORDER BY 2
    INTO :V$OBJ_ID, :S
  DO
  BEGIN
    -- Режем 200 символов от названия
    S = SUBSTRING(S FROM 1 FOR 200);
    IF(CHAR_LENGTH(SUBJECTS_MISS) + CHAR_LENGTH(S) < 4990) THEN
    BEGIN
      IF(CHAR_LENGTH(SUBJECTS_MISS) > 0) THEN SUBJECTS_MISS = SUBJECTS_MISS || '; ';
      SUBJECTS_MISS = SUBJECTS_MISS || S;
    END
    V$MISS = V$MISS + 1;
  END

  FOR
    SELECT DISTINCT COALESCE(PS.SRC_SUBJECT_ID, PS.SUBJECT_ID)
    FROM PLAN_SUBJECTS PS
    JOIN PLAN_SUBJECTS PS2 ON PS2.OBJ_ID = PS.PARENT_ID AND PS2.FIELD_ID IN (13303)
    WHERE PS.DATE_DEL IS NULL AND PS.PLAN_ID = :I$PLAN_ID AND PS.ROW_TYPE = 10
    AND NOT EXISTS (
      SELECT FIRST 1 1
      FROM PLAN_SUBJECTS PSX
      JOIN PLAN_SUBJECTS PSX2 ON PSX2.OBJ_ID = PSX.PARENT_ID AND PSX2.FIELD_ID IN (13303)
      WHERE PSX.DATE_DEL IS NULL AND PSX.PLAN_ID = :I$SRC_ID AND PS.ROW_TYPE = 10 AND (PSX.SUBJECT_ID = PS.SRC_SUBJECT_ID OR PSX.SUBJECT_ID = PS.SUBJECT_ID
        OR (:V$FOP_FIX = 1 AND PSX.SUBJECT_ID = 38703 AND (PS.SUBJECT_ID = 200 OR PS.SRC_SUBJECT_ID = 200))
        OR (:V$FOP_FIX = 1 AND PSX.SUBJECT_ID = 38700 AND (PS.SUBJECT_ID = 206 OR PS.SRC_SUBJECT_ID = 206))
      )
    )
    INTO :V$OBJ_ID
  DO
  BEGIN
    -- Второй иностранный в ООО пропускаем
    IF(V$OBJ_ID <> 32810 OR I$LEVEL_ID <> 5341) THEN
    BEGIN
      -- Режем 200 символов от названия
      S = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$OBJ_ID));
      S = SUBSTRING(S FROM 1 FOR 200);
      IF(CHAR_LENGTH(SUBJECTS_MORE) + CHAR_LENGTH(S) < 4990) THEN
      BEGIN
        IF(CHAR_LENGTH(SUBJECTS_MORE) > 0) THEN SUBJECTS_MORE = SUBJECTS_MORE || '; ';
        SUBJECTS_MORE = SUBJECTS_MORE || S;
      END
      V$MORE = V$MORE + 1;
    END
  END

  FOR
    SELECT DISTINCT SUBSTRING(C1.CAPTION FROM 1 FOR 100) || ' = ' || SUBSTRING(C2.CAPTION FROM 1 FOR 100)
    FROM PLAN_SUBJECTS PS
    JOIN PLAN_SUBJECTS PS2 ON PS2.OBJ_ID = PS.PARENT_ID AND PS2.FIELD_ID IN (13303)
    LEFT JOIN OBJECT_CAPTION_GET(PS.SUBJECT_ID) C1 ON 1=1
    LEFT JOIN OBJECT_CAPTION_GET(PS.SRC_SUBJECT_ID) C2 ON 1=1
    WHERE PS.DATE_DEL IS NULL AND PS.PLAN_ID = :I$PLAN_ID AND PS.ROW_TYPE = 10 AND PS.SRC_SUBJECT_ID IS NOT NULL
    ORDER BY 1
    INTO :S
  DO
  BEGIN
    IF(CHAR_LENGTH(SUBJECTS_REPLACEMENT) + CHAR_LENGTH(S) < 4990) THEN
    BEGIN
      IF(CHAR_LENGTH(SUBJECTS_REPLACEMENT) > 0) THEN SUBJECTS_REPLACEMENT = SUBJECTS_REPLACEMENT || '; ';
      SUBJECTS_REPLACEMENT = SUBJECTS_REPLACEMENT || S;
    END
  END

  IF (V$MISS > 0) THEN
  BEGIN
    N = -V$MISS;
  END
  ELSE IF (V$MORE > 0) THEN
  BEGIN
    N = V$MORE;
  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PLAN_DO_FUNC (
    I$OU_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$PARAM_ID BIGINT)
RETURNS (
    VAL VARCHAR(4000))
AS
declare variable V$DT date;
declare variable V$I integer;
declare variable V$MON_ID bigint;
declare variable V$LISTVAL_ID integer;
declare variable V$OBJ_ID bigint;
BEGIN
    SELECT DISTINCT OBJ_ID FROM LINKS
    WHERE OBJ_TYPE_ID = 162
    AND PARENT_ID = :I$OU_ID
    AND DATE_DEL IS NULL
    INTO :V$MON_ID;

    IF (I$PARAM_ID = 2236) THEN
    BEGIN
        SELECT VAL FROM VALI
        WHERE OBJ_ID = :I$OBJ_ID
        AND IS_DEL = 0
        AND PARAM_ID = 2284
        INTO :V$LISTVAL_ID;


        V$I = EXTRACT(YEAR FROM CURRENT_DATE);
        V$DT = '1.09.' || V$I;
        
        IF (CURRENT_DATE < V$DT) THEN
        BEGIN
            VAL = 'Количество классов в ' || (V$I - 1 + V$LISTVAL_ID) || '-' || (V$I + V$LISTVAL_ID)|| ' уч.году';
        END
        ELSE
        BEGIN
            VAL = 'Количество классов в ' || (V$I + V$LISTVAL_ID) || '-' || (V$I + 1 + V$LISTVAL_ID) || ' уч.году';
        END
    END
    ELSE IF (I$PARAM_ID = 2252) THEN
    BEGIN
        SELECT VAL FROM VALI
        WHERE OBJ_ID = :I$OBJ_ID
        AND IS_DEL = 0
        AND PARAM_ID = 2286
        INTO :V$LISTVAL_ID;


        V$I = EXTRACT(YEAR FROM CURRENT_DATE);
        V$DT = '1.09.' || V$I;
        
        IF (CURRENT_DATE < V$DT) THEN
        BEGIN
            VAL = 'Количество классов в ' || (V$I - 1 + V$LISTVAL_ID) || '-' || (V$I + V$LISTVAL_ID)|| ' уч.году';
        END
        ELSE
        BEGIN
            VAL = 'Количество классов в ' || (V$I + V$LISTVAL_ID) || '-' || (V$I + 1 + V$LISTVAL_ID) || ' уч.году';
        END
    END
    ELSE IF (I$PARAM_ID = 2288) THEN
    BEGIN
        SELECT VAL FROM VALI
        WHERE OBJ_ID = :I$OBJ_ID
        AND IS_DEL = 0
        AND PARAM_ID = 2285
        INTO :V$LISTVAL_ID;


        V$I = EXTRACT(YEAR FROM CURRENT_DATE);
        V$DT = '1.09.' || V$I;
        
        IF (CURRENT_DATE < V$DT) THEN
        BEGIN
        --Количество классов в  уч.году
            VAL = 'Контингент учащихся в ' || (V$I - 1 + V$LISTVAL_ID) || '-' || (V$I + V$LISTVAL_ID)|| ' уч.году';
        END
        ELSE
        BEGIN
            VAL = 'Контингент учащихся в ' || (V$I + V$LISTVAL_ID) || '-' || (V$I + 1 + V$LISTVAL_ID) || ' уч.году';
        END
    END
    ELSE IF (I$PARAM_ID = 2268) THEN
    BEGIN
        SELECT VAL FROM VALI
        WHERE OBJ_ID = :I$OBJ_ID
        AND IS_DEL = 0
        AND PARAM_ID = 2287
        INTO :V$LISTVAL_ID;


        V$I = EXTRACT(YEAR FROM CURRENT_DATE);
        V$DT = '1.09.' || V$I;
        
        IF (CURRENT_DATE < V$DT) THEN
        BEGIN
        --Количество классов в  уч.году
            VAL = 'Контингент учащихся в ' || (V$I - 1 + V$LISTVAL_ID) || '-' || (V$I + V$LISTVAL_ID)|| ' уч.году';
        END
        ELSE
        BEGIN
            VAL = 'Контингент учащихся в ' || (V$I + V$LISTVAL_ID) || '-' || (V$I + 1 + V$LISTVAL_ID) || ' уч.году';
        END
    END
    ELSE IF (I$PARAM_ID = 2298) THEN
    BEGIN
        SELECT VAL FROM VALI
        WHERE OBJ_ID = :I$OBJ_ID
        AND IS_DEL = 0
        AND PARAM_ID = 2308
        INTO :V$LISTVAL_ID;


        V$I = EXTRACT(YEAR FROM CURRENT_DATE);
        V$DT = '1.09.' || V$I;
        
        IF (CURRENT_DATE < V$DT) THEN
        BEGIN
        --Количество классов в  уч.году
            VAL = 'Контингент учащихся в ' || (V$I - 1 + V$LISTVAL_ID) || '-' || (V$I + V$LISTVAL_ID)|| ' уч.году';
        END
        ELSE
        BEGIN
            VAL = 'Контингент учащихся в ' || (V$I + V$LISTVAL_ID) || '-' || (V$I + 1 + V$LISTVAL_ID) || ' уч.году';
        END
    END
    ELSE IF (I$PARAM_ID = 2309) THEN
    BEGIN
        SELECT VAL FROM VALI
        WHERE OBJ_ID = :I$OBJ_ID
        AND IS_DEL = 0
        AND PARAM_ID = 2328
        INTO :V$LISTVAL_ID;


        V$I = EXTRACT(YEAR FROM CURRENT_DATE);
        V$DT = '1.09.' || V$I;
        
        IF (CURRENT_DATE < V$DT) THEN
        BEGIN
        --Количество классов в  уч.году
            VAL = 'Контингент учащихся в ' || (V$I - 1 + V$LISTVAL_ID) || '-' || (V$I + V$LISTVAL_ID)|| ' уч.году';
        END
        ELSE
        BEGIN
            VAL = 'Контингент учащихся в ' || (V$I + V$LISTVAL_ID) || '-' || (V$I + 1 + V$LISTVAL_ID) || ' уч.году';
        END
    END
    ELSE IF (I$PARAM_ID = 2289) THEN
    BEGIN
        SELECT VAL FROM VALI
        WHERE OBJ_ID = :I$OBJ_ID
        AND IS_DEL = 0
        AND PARAM_ID = 2299
        INTO :V$LISTVAL_ID;


        V$I = EXTRACT(YEAR FROM CURRENT_DATE);
        V$DT = '1.09.' || V$I;
        
        IF (CURRENT_DATE < V$DT) THEN
        BEGIN
        --Количество классов в  уч.году
            VAL = 'Количество профильных классов в ' || (V$I - 1 + V$LISTVAL_ID) || '-' || (V$I + V$LISTVAL_ID)|| ' уч.году';
        END
        ELSE
        BEGIN
            VAL = 'Количество профильных классов в ' || (V$I + V$LISTVAL_ID) || '-' || (V$I + 1 + V$LISTVAL_ID) || ' уч.году';
        END
    END
    ELSE IF (I$PARAM_ID = 2318) THEN
    BEGIN
        SELECT VAL FROM VALI
        WHERE OBJ_ID = :I$OBJ_ID
        AND IS_DEL = 0
        AND PARAM_ID = 2327
        INTO :V$LISTVAL_ID;


        V$I = EXTRACT(YEAR FROM CURRENT_DATE);
        V$DT = '1.09.' || V$I;
        
        IF (CURRENT_DATE < V$DT) THEN
        BEGIN
        --Количество классов в  уч.году
            VAL = 'Количество профильных классов в ' || (V$I - 1 + V$LISTVAL_ID) || '-' || (V$I + V$LISTVAL_ID)|| ' уч.году';
        END
        ELSE
        BEGIN
            VAL = 'Количество профильных классов в ' || (V$I + V$LISTVAL_ID) || '-' || (V$I + 1 + V$LISTVAL_ID) || ' уч.году';
        END
    END
    ELSE IF (I$PARAM_ID IN (2221,2222,2223,2224,2225,2226,2227,2228,2229,2230,2231,2232,2233,2234,2235)) THEN
    BEGIN
        SELECT VAL FROM VALI
        WHERE OBJ_ID = :I$OBJ_ID
        AND IS_DEL = 0
        AND PARAM_ID = 2284
        INTO :V$I;

        IF (V$I = 0) THEN
        BEGIN
            IF (I$PARAM_ID IN (2221,2222,2223,2224,2225,2226,2227,2228,2229,2230,2231)) THEN
            BEGIN
                IF (I$PARAM_ID = 2221) THEN
                BEGIN
                    V$LISTVAL_ID = 37;
                END
                ELSE IF (I$PARAM_ID = 2222) THEN
                BEGIN
                    V$LISTVAL_ID = 38;
                END
                ELSE IF (I$PARAM_ID = 2223) THEN
                BEGIN
                    V$LISTVAL_ID = 39;
                END
                ELSE IF (I$PARAM_ID = 2224) THEN
                BEGIN
                    V$LISTVAL_ID = 40;
                END
                ELSE IF (I$PARAM_ID = 2225) THEN
                BEGIN
                    V$LISTVAL_ID = 41;
                END
                ELSE IF (I$PARAM_ID = 2226) THEN
                BEGIN
                    V$LISTVAL_ID = 42;
                END
                ELSE IF (I$PARAM_ID = 2227) THEN
                BEGIN
                    V$LISTVAL_ID = 43;
                END
                ELSE IF (I$PARAM_ID = 2228) THEN
                BEGIN
                    V$LISTVAL_ID = 44;
                END
                ELSE IF (I$PARAM_ID = 2229) THEN
                BEGIN
                    V$LISTVAL_ID = 45;
                END
                ELSE IF (I$PARAM_ID = 2230) THEN
                BEGIN
                    V$LISTVAL_ID = 46;
                END
                ELSE IF (I$PARAM_ID = 2231) THEN
                BEGIN
                    V$LISTVAL_ID = 47;
                END
                SELECT COUNT(L9.OBJ_ID)
                FROM LINKS L7
        
                JOIN LINKS L8
                ON L8.PARENT_ID = L7.OBJ_ID
                AND L8.DATE_DEL IS NULL
                AND L8.OBJ_TYPE_ID = 8
        
                JOIN VALL VL
                ON VL.OBJ_ID = L8.OBJ_ID
                AND VL.IS_DEL = 0
                AND VL.PARAM_ID = 49
                AND VL.LISTVAL_ID = :V$LISTVAL_ID
        
                JOIN LINKS L9
                ON L9.PARENT_ID = L8.OBJ_ID
                AND L9.DATE_DEL IS NULL
                AND L9.OBJ_TYPE_ID = 9
        
                JOIN VALL V592
                ON V592.OBJ_ID = L9.OBJ_ID
                AND V592.IS_DEL = 0
                AND V592.PARAM_ID = 592
                AND V592.LISTVAL_ID = 197
        
                WHERE L7.PARENT_ID = :I$OU_ID
                AND L7.DATE_DEL IS NULL
                AND L7.OBJ_TYPE_ID = 7
        
                INTO :VAL;
            END
            ELSE IF (I$PARAM_ID = 2232) THEN
            BEGIN
                SELECT COUNT(L9.OBJ_ID)
                FROM LINKS L7
        
                JOIN LINKS L8
                ON L8.PARENT_ID = L7.OBJ_ID
                AND L8.DATE_DEL IS NULL
                AND L8.OBJ_TYPE_ID = 8
        
                JOIN VALL VL
                ON VL.OBJ_ID = L8.OBJ_ID
                AND VL.IS_DEL = 0
                AND VL.PARAM_ID = 49
                AND VL.LISTVAL_ID IN (37, 38, 39, 40)
        
                JOIN LINKS L9
                ON L9.PARENT_ID = L8.OBJ_ID
                AND L9.DATE_DEL IS NULL
                AND L9.OBJ_TYPE_ID = 9
        
                JOIN VALL V592
                ON V592.OBJ_ID = L9.OBJ_ID
                AND V592.IS_DEL = 0
                AND V592.PARAM_ID = 592
                AND V592.LISTVAL_ID = 197
        
                WHERE L7.PARENT_ID = :I$OU_ID
                AND L7.DATE_DEL IS NULL
                AND L7.OBJ_TYPE_ID = 7
        
                INTO :VAL;
            END
            ELSE IF (I$PARAM_ID = 2233) THEN
            BEGIN
                SELECT COUNT(L9.OBJ_ID)
                FROM LINKS L7
        
                JOIN LINKS L8
                ON L8.PARENT_ID = L7.OBJ_ID
                AND L8.DATE_DEL IS NULL
                AND L8.OBJ_TYPE_ID = 8
        
                JOIN VALL VL
                ON VL.OBJ_ID = L8.OBJ_ID
                AND VL.IS_DEL = 0
                AND VL.PARAM_ID = 49
                AND VL.LISTVAL_ID IN (41, 42, 43, 44, 45)
        
                JOIN LINKS L9
                ON L9.PARENT_ID = L8.OBJ_ID
                AND L9.DATE_DEL IS NULL
                AND L9.OBJ_TYPE_ID = 9
        
                JOIN VALL V592
                ON V592.OBJ_ID = L9.OBJ_ID
                AND V592.IS_DEL = 0
                AND V592.PARAM_ID = 592
                AND V592.LISTVAL_ID = 197
        
                WHERE L7.PARENT_ID = :I$OU_ID
                AND L7.DATE_DEL IS NULL
                AND L7.OBJ_TYPE_ID = 7
        
                INTO :VAL;
            END
            ELSE IF (I$PARAM_ID = 2234) THEN
            BEGIN
                SELECT COUNT(L9.OBJ_ID)
                FROM LINKS L7
        
                JOIN LINKS L8
                ON L8.PARENT_ID = L7.OBJ_ID
                AND L8.DATE_DEL IS NULL
                AND L8.OBJ_TYPE_ID = 8
        
                JOIN VALL VL
                ON VL.OBJ_ID = L8.OBJ_ID
                AND VL.IS_DEL = 0
                AND VL.PARAM_ID = 49
                AND VL.LISTVAL_ID IN (46, 47)
        
                JOIN LINKS L9
                ON L9.PARENT_ID = L8.OBJ_ID
                AND L9.DATE_DEL IS NULL
                AND L9.OBJ_TYPE_ID = 9
        
                JOIN VALL V592
                ON V592.OBJ_ID = L9.OBJ_ID
                AND V592.IS_DEL = 0
                AND V592.PARAM_ID = 592
                AND V592.LISTVAL_ID = 197
        
                WHERE L7.PARENT_ID = :I$OU_ID
                AND L7.DATE_DEL IS NULL
                AND L7.OBJ_TYPE_ID = 7
        
                INTO :VAL;
            END
            ELSE IF (I$PARAM_ID = 2235) THEN
            BEGIN
                SELECT COUNT(L9.OBJ_ID)
                FROM LINKS L7
        
                JOIN LINKS L8
                ON L8.PARENT_ID = L7.OBJ_ID
                AND L8.DATE_DEL IS NULL
                AND L8.OBJ_TYPE_ID = 8
        
                JOIN VALL VL
                ON VL.OBJ_ID = L8.OBJ_ID
                AND VL.IS_DEL = 0
                AND VL.PARAM_ID = 49
                AND VL.LISTVAL_ID IN (37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47)
        
                JOIN LINKS L9
                ON L9.PARENT_ID = L8.OBJ_ID
                AND L9.DATE_DEL IS NULL
                AND L9.OBJ_TYPE_ID = 9
        
                JOIN VALL V592
                ON V592.OBJ_ID = L9.OBJ_ID
                AND V592.IS_DEL = 0
                AND V592.PARAM_ID = 592
                AND V592.LISTVAL_ID = 197
        
                WHERE L7.PARENT_ID = :I$OU_ID
                AND L7.DATE_DEL IS NULL
                AND L7.OBJ_TYPE_ID = 7
        
                INTO :VAL;
            END
        END
        ELSE
        BEGIN
            SELECT L.OBJ_ID FROM LINKS L

            JOIN VALI V2286
            ON V2286.PARAM_ID = 2286
            AND V2286.OBJ_ID = L.OBJ_ID
            AND V2286.IS_DEL = 0
            AND V2286.VAL = :V$I

            JOIN LINKS L274
            ON L274.OBJ_ID = :I$OBJ_ID
            AND L274.DATE_DEL IS NULL
            AND L274.OBJ_TYPE_ID = 274

            WHERE L.OBJ_TYPE_ID = 277
            AND L.DATE_DEL IS NULL
            AND L.PARENT_TYPE_ID = 2
            AND L.PARENT_ID = L274.PARENT_ID
            
            ORDER BY V2286.VAL
            INTO :V$OBJ_ID;

            IF (V$OBJ_ID IS NOT NULL) THEN
            BEGIN
                IF (I$PARAM_ID IN (2221,2222,2223,2224,2225,2226,2227,2228,2229,2230,2231)) THEN
                BEGIN
                    IF (I$PARAM_ID = 2221) THEN
                    BEGIN
                        V$LISTVAL_ID = 2253;
                    END
                    ELSE IF (I$PARAM_ID = 2222) THEN
                    BEGIN
                        V$LISTVAL_ID = 2254;
                    END
                    ELSE IF (I$PARAM_ID = 2223) THEN
                    BEGIN
                        V$LISTVAL_ID = 2255;
                    END
                    ELSE IF (I$PARAM_ID = 2224) THEN
                    BEGIN
                        V$LISTVAL_ID = 2256;
                    END
                    ELSE IF (I$PARAM_ID = 2225) THEN
                    BEGIN
                        V$LISTVAL_ID = 2257;
                    END
                    ELSE IF (I$PARAM_ID = 2226) THEN
                    BEGIN
                        V$LISTVAL_ID = 2258;
                    END
                    ELSE IF (I$PARAM_ID = 2227) THEN
                    BEGIN
                        V$LISTVAL_ID = 2259;
                    END
                    ELSE IF (I$PARAM_ID = 2228) THEN
                    BEGIN
                        V$LISTVAL_ID = 2260;
                    END
                    ELSE IF (I$PARAM_ID = 2229) THEN
                    BEGIN
                        V$LISTVAL_ID = 2261;
                    END
                    ELSE IF (I$PARAM_ID = 2230) THEN
                    BEGIN
                        V$LISTVAL_ID = 2262;
                    END
                    ELSE IF (I$PARAM_ID = 2231) THEN
                    BEGIN
                        V$LISTVAL_ID = 2263;
                    END
    
                    SELECT V.VAL FROM VALI V
                    WHERE V.PARAM_ID = :V$LISTVAL_ID
                    AND V.OBJ_ID = :V$OBJ_ID
                    AND V.IS_DEL = 0
                    INTO :VAL;
                END
                ELSE IF (I$PARAM_ID = 2232) THEN
                BEGIN
                    SELECT SUM(V.VAL) FROM VALI V
                    WHERE V.PARAM_ID in (2253,2254,2255,2256)
                    AND V.OBJ_ID = :V$OBJ_ID
                    AND V.IS_DEL = 0
                    INTO :VAL;
                END
                ELSE IF (I$PARAM_ID = 2233) THEN
                BEGIN
                    SELECT SUM(V.VAL) FROM VALI V
                    WHERE V.PARAM_ID in (2257,2258,2259,2260,2261)
                    AND V.OBJ_ID = :V$OBJ_ID
                    AND V.IS_DEL = 0
                    INTO :VAL;
                END
                ELSE IF (I$PARAM_ID = 2234) THEN
                BEGIN
                    SELECT SUM(V.VAL) FROM VALI V
                    WHERE V.PARAM_ID in (2262,2263)
                    AND V.OBJ_ID = :V$OBJ_ID
                    AND V.IS_DEL = 0
                    INTO :VAL;
                END
                ELSE IF (I$PARAM_ID = 2235) THEN
                BEGIN
                    SELECT SUM(V.VAL) FROM VALI V
                    WHERE V.PARAM_ID in (2253,2254,2255,2256,2257,2258,2259,2260,2261,2262,2263)
                    AND V.OBJ_ID = :V$OBJ_ID
                    AND V.IS_DEL = 0
                    INTO :VAL;
                END
            END
        END
    END
    ELSE IF (I$PARAM_ID IN (2237,2238,2239,2240,2241,2242,2243,2244,2245,2246,2247,2248,2249,2250,2251)) THEN
    BEGIN
        SELECT VAL FROM VALI
        WHERE OBJ_ID = :I$OBJ_ID
        AND IS_DEL = 0
        AND PARAM_ID = 2285
        INTO :V$I;

        IF (V$I = 0) THEN
        BEGIN
            IF (I$PARAM_ID IN (2237,2238,2239,2240,2241,2242,2243,2244,2245,2246,2247)) THEN
            BEGIN
                SELECT VAL FROM VALI
                WHERE OBJ_ID = :I$OBJ_ID
                AND IS_DEL = 0
                AND PARAM_ID = 2285
                INTO :V$I;
        
                IF (V$I = 0) THEN
                BEGIN
                    IF (I$PARAM_ID = 2237) THEN
                    BEGIN
                        V$LISTVAL_ID = 37;
                    END
                    ELSE IF (I$PARAM_ID = 2238) THEN
                    BEGIN
                        V$LISTVAL_ID = 38;
                    END
                    ELSE IF (I$PARAM_ID = 2239) THEN
                    BEGIN
                        V$LISTVAL_ID = 39;
                    END
                    ELSE IF (I$PARAM_ID = 2240) THEN
                    BEGIN
                        V$LISTVAL_ID = 40;
                    END
                    ELSE IF (I$PARAM_ID = 2241) THEN
                    BEGIN
                        V$LISTVAL_ID = 41;
                    END
                    ELSE IF (I$PARAM_ID = 2242) THEN
                    BEGIN
                        V$LISTVAL_ID = 42;
                    END
                    ELSE IF (I$PARAM_ID = 2243) THEN
                    BEGIN
                        V$LISTVAL_ID = 43;
                    END
                    ELSE IF (I$PARAM_ID = 2244) THEN
                    BEGIN
                        V$LISTVAL_ID = 44;
                    END
                    ELSE IF (I$PARAM_ID = 2245) THEN
                    BEGIN
                        V$LISTVAL_ID = 45;
                    END
                    ELSE IF (I$PARAM_ID = 2246) THEN
                    BEGIN
                        V$LISTVAL_ID = 46;
                    END
                    ELSE IF (I$PARAM_ID = 2247) THEN
                    BEGIN
                        V$LISTVAL_ID = 47;
                    END
                    SELECT COUNT(L10.OBJ_ID)
                    FROM LINKS L7
            
                    JOIN LINKS L8
                    ON L8.PARENT_ID = L7.OBJ_ID
                    AND L8.DATE_DEL IS NULL
                    AND L8.OBJ_TYPE_ID = 8
            
                    JOIN VALL VL
                    ON VL.OBJ_ID = L8.OBJ_ID
                    AND VL.IS_DEL = 0
                    AND VL.PARAM_ID = 49
                    AND VL.LISTVAL_ID = :V$LISTVAL_ID
            
                    JOIN LINKS L9
                    ON L9.PARENT_ID = L8.OBJ_ID
                    AND L9.DATE_DEL IS NULL
                    AND L9.OBJ_TYPE_ID = 9
            
                    JOIN VALL V592
                    ON V592.OBJ_ID = L9.OBJ_ID
                    AND V592.IS_DEL = 0
                    AND V592.PARAM_ID = 592
                    AND V592.LISTVAL_ID = 197
            
                    JOIN LINKS L10
                    ON L10.PARENT_ID = L9.OBJ_ID
                    AND L10.DATE_DEL IS NULL
                    AND L10.OBJ_TYPE_ID = 10
            
                    WHERE L7.PARENT_ID = :I$OU_ID
                    AND L7.DATE_DEL IS NULL
                    AND L7.OBJ_TYPE_ID = 7
            
                    INTO :VAL;
                END
            END
            ELSE IF (I$PARAM_ID = 2248) THEN
            BEGIN
                SELECT COUNT(L10.OBJ_ID)
                FROM LINKS L7
        
                JOIN LINKS L8
                ON L8.PARENT_ID = L7.OBJ_ID
                AND L8.DATE_DEL IS NULL
                AND L8.OBJ_TYPE_ID = 8
        
                JOIN VALL VL
                ON VL.OBJ_ID = L8.OBJ_ID
                AND VL.IS_DEL = 0
                AND VL.PARAM_ID = 49
                AND VL.LISTVAL_ID IN (37, 38, 39, 40)
        
                JOIN LINKS L9
                ON L9.PARENT_ID = L8.OBJ_ID
                AND L9.DATE_DEL IS NULL
                AND L9.OBJ_TYPE_ID = 9
        
                JOIN VALL V592
                ON V592.OBJ_ID = L9.OBJ_ID
                AND V592.IS_DEL = 0
                AND V592.PARAM_ID = 592
                AND V592.LISTVAL_ID = 197
        
                JOIN LINKS L10
                ON L10.PARENT_ID = L9.OBJ_ID
                AND L10.DATE_DEL IS NULL
                AND L10.OBJ_TYPE_ID = 10
        
                WHERE L7.PARENT_ID = :I$OU_ID
                AND L7.DATE_DEL IS NULL
                AND L7.OBJ_TYPE_ID = 7
        
                INTO :VAL;
            END
            ELSE IF (I$PARAM_ID = 2249) THEN
            BEGIN
                SELECT COUNT(L10.OBJ_ID)
                FROM LINKS L7
        
                JOIN LINKS L8
                ON L8.PARENT_ID = L7.OBJ_ID
                AND L8.DATE_DEL IS NULL
                AND L8.OBJ_TYPE_ID = 8
        
                JOIN VALL VL
                ON VL.OBJ_ID = L8.OBJ_ID
                AND VL.IS_DEL = 0
                AND VL.PARAM_ID = 49
                AND VL.LISTVAL_ID IN (41, 42, 43, 44, 45)
        
                JOIN LINKS L9
                ON L9.PARENT_ID = L8.OBJ_ID
                AND L9.DATE_DEL IS NULL
                AND L9.OBJ_TYPE_ID = 9
        
                JOIN VALL V592
                ON V592.OBJ_ID = L9.OBJ_ID
                AND V592.IS_DEL = 0
                AND V592.PARAM_ID = 592
                AND V592.LISTVAL_ID = 197
        
                JOIN LINKS L10
                ON L10.PARENT_ID = L9.OBJ_ID
                AND L10.DATE_DEL IS NULL
                AND L10.OBJ_TYPE_ID = 10
        
                WHERE L7.PARENT_ID = :I$OU_ID
                AND L7.DATE_DEL IS NULL
                AND L7.OBJ_TYPE_ID = 7
        
                INTO :VAL;
            END
            ELSE IF (I$PARAM_ID = 2250) THEN
            BEGIN
                SELECT COUNT(L10.OBJ_ID)
                FROM LINKS L7
        
                JOIN LINKS L8
                ON L8.PARENT_ID = L7.OBJ_ID
                AND L8.DATE_DEL IS NULL
                AND L8.OBJ_TYPE_ID = 8
        
                JOIN VALL VL
                ON VL.OBJ_ID = L8.OBJ_ID
                AND VL.IS_DEL = 0
                AND VL.PARAM_ID = 49
                AND VL.LISTVAL_ID IN (46, 47)
        
                JOIN LINKS L9
                ON L9.PARENT_ID = L8.OBJ_ID
                AND L9.DATE_DEL IS NULL
                AND L9.OBJ_TYPE_ID = 9
        
                JOIN VALL V592
                ON V592.OBJ_ID = L9.OBJ_ID
                AND V592.IS_DEL = 0
                AND V592.PARAM_ID = 592
                AND V592.LISTVAL_ID = 197
        
                JOIN LINKS L10
                ON L10.PARENT_ID = L9.OBJ_ID
                AND L10.DATE_DEL IS NULL
                AND L10.OBJ_TYPE_ID = 10
        
                WHERE L7.PARENT_ID = :I$OU_ID
                AND L7.DATE_DEL IS NULL
                AND L7.OBJ_TYPE_ID = 7
        
                INTO :VAL;
            END
            ELSE IF (I$PARAM_ID = 2251) THEN
            BEGIN
                SELECT COUNT(L10.OBJ_ID)
                FROM LINKS L7
        
                JOIN LINKS L8
                ON L8.PARENT_ID = L7.OBJ_ID
                AND L8.DATE_DEL IS NULL
                AND L8.OBJ_TYPE_ID = 8
        
                JOIN VALL VL
                ON VL.OBJ_ID = L8.OBJ_ID
                AND VL.IS_DEL = 0
                AND VL.PARAM_ID = 49
                AND VL.LISTVAL_ID IN (37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47)
        
                JOIN LINKS L9
                ON L9.PARENT_ID = L8.OBJ_ID
                AND L9.DATE_DEL IS NULL
                AND L9.OBJ_TYPE_ID = 9
        
                JOIN VALL V592
                ON V592.OBJ_ID = L9.OBJ_ID
                AND V592.IS_DEL = 0
                AND V592.PARAM_ID = 592
                AND V592.LISTVAL_ID = 197
        
                JOIN LINKS L10
                ON L10.PARENT_ID = L9.OBJ_ID
                AND L10.DATE_DEL IS NULL
                AND L10.OBJ_TYPE_ID = 10
        
                WHERE L7.PARENT_ID = :I$OU_ID
                AND L7.DATE_DEL IS NULL
                AND L7.OBJ_TYPE_ID = 7
        
                INTO :VAL;
            END
        END
        ELSE
        BEGIN
            SELECT L.OBJ_ID FROM LINKS L

            JOIN VALI V2287
            ON V2287.PARAM_ID = 2287
            AND V2287.OBJ_ID = L.OBJ_ID
            AND V2287.IS_DEL = 0
            AND V2287.VAL = :V$I
            
            JOIN LINKS L275
            ON L275.OBJ_ID = :I$OBJ_ID
            AND L275.DATE_DEL IS NULL
            AND L275.OBJ_TYPE_ID = 275

            WHERE L.OBJ_TYPE_ID = 278
            AND L.DATE_DEL IS NULL
            AND L.PARENT_TYPE_ID = 2
            AND L.PARENT_ID = L275.PARENT_ID
            
            ORDER BY V2287.VAL
            INTO :V$OBJ_ID;

            IF (V$OBJ_ID IS NOT NULL) THEN
            BEGIN
                IF (I$PARAM_ID IN (2237,2238,2239,2240,2241,2242,2243,2244,2245,2246,2247)) THEN
                BEGIN
                    IF (I$PARAM_ID = 2237) THEN
                    BEGIN
                        V$LISTVAL_ID = 2269;
                    END
                    ELSE IF (I$PARAM_ID = 2238) THEN
                    BEGIN
                        V$LISTVAL_ID = 2270;
                    END
                    ELSE IF (I$PARAM_ID = 2239) THEN
                    BEGIN
                        V$LISTVAL_ID = 2271;
                    END
                    ELSE IF (I$PARAM_ID = 2240) THEN
                    BEGIN
                        V$LISTVAL_ID = 2272;
                    END
                    ELSE IF (I$PARAM_ID = 2241) THEN
                    BEGIN
                        V$LISTVAL_ID = 2273;
                    END
                    ELSE IF (I$PARAM_ID = 2242) THEN
                    BEGIN
                        V$LISTVAL_ID = 2274;
                    END
                    ELSE IF (I$PARAM_ID = 2243) THEN
                    BEGIN
                        V$LISTVAL_ID = 2275;
                    END
                    ELSE IF (I$PARAM_ID = 2244) THEN
                    BEGIN
                        V$LISTVAL_ID = 2276;
                    END
                    ELSE IF (I$PARAM_ID = 2245) THEN
                    BEGIN
                        V$LISTVAL_ID = 2277;
                    END
                    ELSE IF (I$PARAM_ID = 2246) THEN
                    BEGIN
                        V$LISTVAL_ID = 2278;
                    END
                    ELSE IF (I$PARAM_ID = 2247) THEN
                    BEGIN
                        V$LISTVAL_ID = 2279;
                    END
    
                    SELECT V.VAL FROM VALI V
                    WHERE V.PARAM_ID = :V$LISTVAL_ID
                    AND V.OBJ_ID = :V$OBJ_ID
                    AND V.IS_DEL = 0
                    INTO :VAL;
                END
                ELSE IF (I$PARAM_ID = 2248) THEN
                BEGIN
                    SELECT SUM(V.VAL) FROM VALI V
                    WHERE V.PARAM_ID in (2269,2270,2271,2272)
                    AND V.OBJ_ID = :V$OBJ_ID
                    AND V.IS_DEL = 0
                    INTO :VAL;
                END
                ELSE IF (I$PARAM_ID = 2249) THEN
                BEGIN
                    SELECT SUM(V.VAL) FROM VALI V
                    WHERE V.PARAM_ID in (2273,2274,2275,2276,2277)
                    AND V.OBJ_ID = :V$OBJ_ID
                    AND V.IS_DEL = 0
                    INTO :VAL;
                END
                ELSE IF (I$PARAM_ID = 2250) THEN
                BEGIN
                    SELECT SUM(V.VAL) FROM VALI V
                    WHERE V.PARAM_ID in (2278,2279)
                    AND V.OBJ_ID = :V$OBJ_ID
                    AND V.IS_DEL = 0
                    INTO :VAL;
                END
                ELSE IF (I$PARAM_ID = 2251) THEN
                BEGIN
                    SELECT SUM(V.VAL) FROM VALI V
                    WHERE V.PARAM_ID in (2269,2270,2271,2272,2273,2274,2275,2276,2277,2278,2279)
                    AND V.OBJ_ID = :V$OBJ_ID
                    AND V.IS_DEL = 0
                    INTO :VAL;
                END
            END
        END
    END
    ELSE IF (I$PARAM_ID IN (2291,2292,2293,2294,2295,2296,2297)) THEN
    BEGIN
        SELECT V.LISTVAL_ID FROM
        VALL V
        WHERE V.OBJ_ID = :I$OBJ_ID
        AND V.IS_DEL = 0
        AND V.PARAM_ID = 2290
        INTO :V$LISTVAL_ID;

        SELECT V.VAL FROM
        VALI V
        WHERE V.OBJ_ID = :I$OBJ_ID
        AND V.IS_DEL = 0
        AND V.PARAM_ID = 2299
        INTO :V$I;

        SELECT L.OBJ_ID FROM LINKS L

        JOIN VALI VI
        ON VI.PARAM_ID = 2327
        AND VI.OBJ_ID = L.OBJ_ID
        AND VI.IS_DEL = 0
        AND VI.VAL = :V$I
        
        JOIN VALL VL
        ON VL.PARAM_ID = 2319
        AND VL.OBJ_ID = L.OBJ_ID
        AND VL.IS_DEL = 0
        AND VL.LISTVAL_ID = :V$LISTVAL_ID
        
        WHERE L.OBJ_TYPE_ID = 281
        AND L.DATE_DEL IS NULL
        AND L.PARENT_TYPE_ID = 2
        INTO :V$OBJ_ID;

        IF (I$PARAM_ID = 2291) THEN
        BEGIN
            SELECT V.VAL
            FROM VALI V
            WHERE V.IS_DEL = 0
            AND V.OBJ_ID = :V$OBJ_ID
            AND V.PARAM_ID = 2320
            INTO :VAL;
        END
        ELSE IF (I$PARAM_ID = 2292) THEN
        BEGIN
            SELECT V.VAL
            FROM VALI V
            WHERE V.IS_DEL = 0
            AND V.OBJ_ID = :V$OBJ_ID
            AND V.PARAM_ID = 2321
            INTO :VAL;
        END
        ELSE IF (I$PARAM_ID = 2293) THEN
        BEGIN
            SELECT V.VAL
            FROM VALI V
            WHERE V.IS_DEL = 0
            AND V.OBJ_ID = :V$OBJ_ID
            AND V.PARAM_ID = 2322
            INTO :VAL;
        END
        ELSE IF (I$PARAM_ID = 2294) THEN
        BEGIN
            SELECT V.VAL
            FROM VALI V
            WHERE V.IS_DEL = 0
            AND V.OBJ_ID = :V$OBJ_ID
            AND V.PARAM_ID = 2323
            INTO :VAL;
        END
        ELSE IF (I$PARAM_ID = 2295) THEN
        BEGIN
            SELECT V.VAL
            FROM VALI V
            WHERE V.IS_DEL = 0
            AND V.OBJ_ID = :V$OBJ_ID
            AND V.PARAM_ID = 2324
            INTO :VAL;
        END
        ELSE IF (I$PARAM_ID = 2296) THEN
        BEGIN
            SELECT V.VAL
            FROM VALI V
            WHERE V.IS_DEL = 0
            AND V.OBJ_ID = :V$OBJ_ID
            AND V.PARAM_ID = 2325
            INTO :VAL;
        END
        ELSE IF (I$PARAM_ID = 2297) THEN
        BEGIN
            SELECT V.VAL
            FROM VALI V
            WHERE V.IS_DEL = 0
            AND V.OBJ_ID = :V$OBJ_ID
            AND V.PARAM_ID = 2326
            INTO :VAL;
        END
    END
    ELSE IF (I$PARAM_ID IN (2300,2301,2302,2303,2304,2305,2306,2307)) THEN
    BEGIN
        SELECT V.VAL FROM
        VALI V
        WHERE V.OBJ_ID = :I$OBJ_ID
        AND V.IS_DEL = 0
        AND V.PARAM_ID = 2308
        INTO :V$I;

        IF (V$I = 0) THEN
        BEGIN
            IF (I$PARAM_ID = 2300) THEN
            BEGIN
                SELECT V2198.V FROM LINKS L
        
                JOIN VALL V2196
                ON V2196.OBJ_ID = L.OBJ_ID
                AND V2196.IS_DEL = 0
                AND V2196.PARAM_ID = 2196
                AND V2196.LISTVAL_ID = 1722
                
                LEFT JOIN VAL_GET(L.OBJ_ID, 2198) V2198 ON 1=1
        
                WHERE L.OBJ_TYPE_ID = 265
                AND L.PARENT_ID = :V$MON_ID
                AND L.DATE_DEL IS NULL
                INTO :VAL;
            END
            ELSE IF (I$PARAM_ID = 2301) THEN
            BEGIN
                SELECT V2198.V FROM LINKS L
        
                JOIN VALL V2196
                ON V2196.OBJ_ID = L.OBJ_ID
                AND V2196.IS_DEL = 0
                AND V2196.PARAM_ID = 2196
                AND V2196.LISTVAL_ID = 1723
                
                LEFT JOIN VAL_GET(L.OBJ_ID, 2198) V2198 ON 1=1
                
                WHERE L.OBJ_TYPE_ID = 265
                AND L.PARENT_ID = :V$MON_ID
                AND L.DATE_DEL IS NULL
                INTO :VAL;
            END
            ELSE IF (I$PARAM_ID = 2302) THEN
            BEGIN
                SELECT V2198.V FROM LINKS L
        
                JOIN VALL V2196
                ON V2196.OBJ_ID = L.OBJ_ID
                AND V2196.IS_DEL = 0
                AND V2196.PARAM_ID = 2196
                AND V2196.LISTVAL_ID = 1725
                
                LEFT JOIN VAL_GET(L.OBJ_ID, 2198) V2198 ON 1=1
                
                WHERE L.OBJ_TYPE_ID = 265
                AND L.PARENT_ID = :V$MON_ID
                AND L.DATE_DEL IS NULL
                INTO :VAL;
            END
            ELSE IF (I$PARAM_ID = 2303) THEN
            BEGIN
                SELECT V2198.V FROM LINKS L
        
                JOIN VALL V2196
                ON V2196.OBJ_ID = L.OBJ_ID
                AND V2196.IS_DEL = 0
                AND V2196.PARAM_ID = 2196
                AND V2196.LISTVAL_ID = 1726
                
                LEFT JOIN VAL_GET(L.OBJ_ID, 2198) V2198 ON 1=1
                
                WHERE L.OBJ_TYPE_ID = 265
                AND L.PARENT_ID = :V$MON_ID
                AND L.DATE_DEL IS NULL
                INTO :VAL;
            END
            ELSE IF (I$PARAM_ID = 2304) THEN
            BEGIN
                SELECT V2198.V FROM LINKS L
        
                JOIN VALL V2196
                ON V2196.OBJ_ID = L.OBJ_ID
                AND V2196.IS_DEL = 0
                AND V2196.PARAM_ID = 2196
                AND V2196.LISTVAL_ID = 1724
                
                LEFT JOIN VAL_GET(L.OBJ_ID, 2198) V2198 ON 1=1
                
                WHERE L.OBJ_TYPE_ID = 265
                AND L.PARENT_ID = :V$MON_ID
                AND L.DATE_DEL IS NULL
                INTO :VAL;
            END
            ELSE IF (I$PARAM_ID = 2305) THEN
            BEGIN
                SELECT V2198.V FROM LINKS L
        
                JOIN VALL V2196
                ON V2196.OBJ_ID = L.OBJ_ID
                AND V2196.IS_DEL = 0
                AND V2196.PARAM_ID = 2196
                AND V2196.LISTVAL_ID = 1727
                
                LEFT JOIN VAL_GET(L.OBJ_ID, 2198) V2198 ON 1=1
                
                WHERE L.OBJ_TYPE_ID = 265
                AND L.PARENT_ID = :V$MON_ID
                AND L.DATE_DEL IS NULL
                INTO :VAL;
            END
            ELSE IF (I$PARAM_ID = 2306) THEN
            BEGIN
                SELECT V2198.V FROM LINKS L
            
                JOIN VALL V2196
                ON V2196.OBJ_ID = L.OBJ_ID
                AND V2196.IS_DEL = 0
                AND V2196.PARAM_ID = 2196
                AND V2196.LISTVAL_ID = 10973
                
                LEFT JOIN VAL_GET(L.OBJ_ID, 2198) V2198 ON 1=1
                
                WHERE L.OBJ_TYPE_ID = 265
                AND L.PARENT_ID = :V$MON_ID
                AND L.DATE_DEL IS NULL
                INTO :VAL;
            END
            ELSE IF (I$PARAM_ID = 2307) THEN
            BEGIN
                SELECT V2198.V FROM LINKS L
        
                JOIN VALL V2196
                ON V2196.OBJ_ID = L.OBJ_ID
                AND V2196.IS_DEL = 0
                AND V2196.PARAM_ID = 2196
                AND V2196.LISTVAL_ID = 10974
                
                LEFT JOIN VAL_GET(L.OBJ_ID, 2198) V2198 ON 1=1
                
                WHERE L.OBJ_TYPE_ID = 265
                AND L.PARENT_ID = :V$MON_ID
                AND L.DATE_DEL IS NULL
                INTO :VAL;
            END
        END
        ELSE
        BEGIN
            SELECT L.OBJ_ID FROM LINKS L

            JOIN VALI VI
            ON VI.PARAM_ID = 2328
            AND VI.OBJ_ID = L.OBJ_ID
            AND VI.IS_DEL = 0
            AND VI.VAL = :V$I

            JOIN LINKS L282
            ON L282.OBJ_ID = :I$OBJ_ID
            AND L282.DATE_DEL IS NULL
            AND L282.OBJ_TYPE_ID = 282

            WHERE L.OBJ_TYPE_ID = 283
            AND L.DATE_DEL IS NULL
            AND L.PARENT_TYPE_ID = 2
            AND L.PARENT_ID = L282.PARENT_ID
            INTO :V$OBJ_ID;
    
            IF (I$PARAM_ID = 2300) THEN
            BEGIN
                SELECT V.VAL
                FROM VALI V
                WHERE V.IS_DEL = 0
                AND V.OBJ_ID = :V$OBJ_ID
                AND V.PARAM_ID = 2310
                INTO :VAL;
            END
            ELSE IF (I$PARAM_ID = 2301) THEN
            BEGIN
                SELECT V.VAL
                FROM VALI V
                WHERE V.IS_DEL = 0
                AND V.OBJ_ID = :V$OBJ_ID
                AND V.PARAM_ID = 2311
                INTO :VAL;
            END
            ELSE IF (I$PARAM_ID = 2302) THEN
            BEGIN
                SELECT V.VAL
                FROM VALI V
                WHERE V.IS_DEL = 0
                AND V.OBJ_ID = :V$OBJ_ID
                AND V.PARAM_ID = 2312
                INTO :VAL;
            END
            ELSE IF (I$PARAM_ID = 2303) THEN
            BEGIN
                SELECT V.VAL
                FROM VALI V
                WHERE V.IS_DEL = 0
                AND V.OBJ_ID = :V$OBJ_ID
                AND V.PARAM_ID = 2313
                INTO :VAL;
            END
            ELSE IF (I$PARAM_ID = 2304) THEN
            BEGIN
                SELECT V.VAL
                FROM VALI V
                WHERE V.IS_DEL = 0
                AND V.OBJ_ID = :V$OBJ_ID
                AND V.PARAM_ID = 2314
                INTO :VAL;
            END
            ELSE IF (I$PARAM_ID = 2305) THEN
            BEGIN
                SELECT V.VAL
                FROM VALI V
                WHERE V.IS_DEL = 0
                AND V.OBJ_ID = :V$OBJ_ID
                AND V.PARAM_ID = 2315
                INTO :VAL;
            END
            ELSE IF (I$PARAM_ID = 2306) THEN
            BEGIN
                SELECT V.VAL
                FROM VALI V
                WHERE V.IS_DEL = 0
                AND V.OBJ_ID = :V$OBJ_ID
                AND V.PARAM_ID = 2316
                INTO :VAL;
            END
            ELSE IF (I$PARAM_ID = 2307) THEN
            BEGIN
                SELECT SUM(V.VAL)
                FROM VALI V
                WHERE V.IS_DEL = 0
                AND V.OBJ_ID = :V$OBJ_ID
                AND V.PARAM_ID IN (2310,2311,2312,2313,2314,2315,2316)
                INTO :VAL;
            END 
        END
    END
    ELSE IF (I$PARAM_ID = 2280) THEN
    BEGIN
        SELECT SUM(V.VAL) FROM VALI V
        WHERE V.PARAM_ID in (2269,2270,2271,2272)
        AND V.OBJ_ID = :I$OBJ_ID
        AND V.IS_DEL = 0
        INTO :VAL;
    END
    ELSE IF (I$PARAM_ID = 2281) THEN
    BEGIN
        SELECT SUM(V.VAL) FROM VALI V
        WHERE V.PARAM_ID in (2273,2274,2275,2276,2277)
        AND V.OBJ_ID = :I$OBJ_ID
        AND V.IS_DEL = 0
        INTO :VAL;
    END
    ELSE IF (I$PARAM_ID = 2282) THEN
    BEGIN
        SELECT SUM(V.VAL) FROM VALI V
        WHERE V.PARAM_ID in (2278,2279)
        AND V.OBJ_ID = :I$OBJ_ID
        AND V.IS_DEL = 0
        INTO :VAL;
    END
    ELSE IF (I$PARAM_ID = 2283) THEN
    BEGIN
        SELECT SUM(V.VAL) FROM VALI V
        WHERE V.PARAM_ID in (2269,2270,2271,2272,2273,2274,2275,2276,2277,2278,2279)
        AND V.OBJ_ID = :I$OBJ_ID
        AND V.IS_DEL = 0
        INTO :VAL;
    END
    ELSE IF (I$PARAM_ID = 2317) THEN
    BEGIN
        SELECT SUM(V.VAL) FROM VALI V
        WHERE V.PARAM_ID in (2310,2311,2312,2313,2314,2315,2316)
        AND V.OBJ_ID = :I$OBJ_ID
        AND V.IS_DEL = 0
        INTO :VAL;
    END
    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PLAN_EVENTS_TO_REGION_COPY
AS
declare variable V$OBJ_ID bigint;
declare variable V$LISTVAL integer;
declare variable V$BLOB_ID bigint;
declare variable V$NEWOBJ_ID bigint;
declare variable V$REGION_ID bigint;
BEGIN
    SELECT L.OBJ_ID
    FROM LINKS L
    WHERE L.OBJ_TYPE_ID = 112
    AND L.DATE_DEL IS NULL
    AND L.PARENT_ID IS NULL
    INTO :V$REGION_ID;
    
    FOR
        SELECT L.OBJ_ID,
         V2333.LISTVAL_ID
        FROM LINKS L

        JOIN VALL V2333
        ON V2333.PARAM_ID = 2333
        AND V2333.OBJ_ID = L.OBJ_ID
        AND V2333.IS_DEL = 0

        WHERE L.OBJ_TYPE_ID = 273
        AND L.DATE_DEL IS NULL
        AND L.PARENT_TYPE_ID = 111
        INTO :V$OBJ_ID, :V$LISTVAL
    DO
    BEGIN
        IF (V$LISTVAL = 2) THEN
        BEGIN
            SELECT OBJ_ID FROM OBJECT_ADD(:V$REGION_ID, 273) INTO :V$NEWOBJ_ID;

            IF (V$NEWOBJ_ID IS NOT NULL) THEN
            BEGIN
                EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ_ID, 2217, :V$NEWOBJ_ID, 2217);
                EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ_ID, 2218, :V$NEWOBJ_ID, 2219);
                EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ_ID, 2219, :V$NEWOBJ_ID, 2219);
                EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ_ID, 2329, :V$NEWOBJ_ID, 2329);
                EXECUTE PROCEDURE COPY_PARAM_VALUE(:V$OBJ_ID, 2220, :V$NEWOBJ_ID, 2220);
                SELECT BLOB_ID FROM VAL_ADD(2330, :V$NEWOBJ_ID, 'ОУО')INTO :V$BLOB_ID;
            END
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PLAN_GET (
    I$OBJ_ID BIGINT,
    I$APP VARCHAR(100),
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE S VARCHAR(1000);
DECLARE VARIABLE SS VARCHAR(1000);
DECLARE VARIABLE S2 VARCHAR(1000);
DECLARE VARIABLE V$CODE VARCHAR(100);
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$STAGE_ID BIGINT;
DECLARE VARIABLE V$SUBJECT_ID BIGINT;
DECLARE VARIABLE V$SRC_SUBJECT_ID BIGINT;
DECLARE VARIABLE V$FIELD_ID BIGINT;
DECLARE VARIABLE V$SORT_INDEX INTEGER;
DECLARE VARIABLE V$LEVEL_INDEX INTEGER;
DECLARE VARIABLE V$LEVEL_ID BIGINT;
DECLARE VARIABLE V$PARENT_ID BIGINT;
DECLARE VARIABLE V$IS_ADV SMALLINT;
DECLARE VARIABLE V$FOLDER_TYPE BIGINT;
DECLARE VARIABLE V$WEEKS FLOAT;
DECLARE VARIABLE V$LOAD_HOURS_S1 FLOAT;
DECLARE VARIABLE V$LOAD_HOURS_S2 FLOAT;
DECLARE VARIABLE V$CONTROL_Q1 BIGINT;
DECLARE VARIABLE V$CONTROL_Q2 BIGINT;
DECLARE VARIABLE V$DBLEVEL SMALLINT;
DECLARE VARIABLE V$IS_VD SMALLINT;
DECLARE VARIABLE V$TYPE CHAR(1);
DECLARE VARIABLE V$WEEKDAYS BIGINT;
DECLARE VARIABLE V$WDPLAN BIGINT;
DECLARE VARIABLE V$W2 BIGINT;
DECLARE VARIABLE V$STD_ID BIGINT;
DECLARE VARIABLE V$PROFILE_ID BIGINT;
DECLARE VARIABLE V$BASE_ID BIGINT;
DECLARE VARIABLE V$BASE_ID2 BIGINT;
DECLARE VARIABLE V$ADV_ID BIGINT;
DECLARE VARIABLE V$STM SMALLINT;
DECLARE VARIABLE V$HOURS_THEORY1 FLOAT;
DECLARE VARIABLE V$HOURS_PR1 FLOAT;
DECLARE VARIABLE V$HOURS_DX1 FLOAT;
DECLARE VARIABLE V$HOURS_IND1 FLOAT;
DECLARE VARIABLE V$MAXLOAD INTEGER;
DECLARE VARIABLE V$STYPE BIGINT;
DECLARE VARIABLE V$PT BIGINT;
DECLARE VARIABLE V$REF_ID BIGINT;
DECLARE VARIABLE V$HOURS_MAX FLOAT;
DECLARE VARIABLE V$HOURS_CR1 FLOAT;
DECLARE VARIABLE V$HOURS_ATT1 FLOAT;
DECLARE VARIABLE V$HOURS_GIA FLOAT;
DECLARE VARIABLE V$HOURS_REST FLOAT;
DECLARE VARIABLE V$YEAR INTEGER;
begin

  -- Проверяем права доступа
  SELECT FIRST 1 L400.PARENT_TYPE_ID
  FROM LINKS L400
  WHERE L400.OBJ_ID = :I$OBJ_ID AND L400.PARENT_TYPE_ID IN (55, 57) AND L400.DATE_DEL IS NULL
  INTO :V$PT;

  IF(V$PT IS NULL) THEN EXCEPTION DATA_ERROR 'Учебный план не найден или был удален';

  -- Тип лицензии и уровень базы
  TAG_NAME = 'ou_type';
  SELECT STATUS
  FROM OU_LICENCE_TYPE
  INTO :V$TYPE;
  VAL = V$TYPE;
  SUSPEND;

  -- Тип лицензии и уровень базы
  TAG_NAME = 'lic_id';
  SELECT GEN
  FROM GEN
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'db_level';
  SELECT KEY_VAL
  FROM KEYS
  WHERE KEY_CODE = 'LEVEL'
  INTO :V$DBLEVEL;
  VAL = V$DBLEVEL;
  SUSPEND;

  TAG_NAME = 'id';
  VAL = I$OBJ_ID;
  SUSPEND;

  TAG_NAME = 'parent_type_id';
  VAL = V$PT;
  SUSPEND;

  -- Метка времени изменения
  TAG_NAME = 'timemark';
  VAL = NULL;
  SELECT FIRST 1 DI.VAL
  FROM LINKS L
  LEFT JOIN DATE2ISO(L.DATE_MODIFY, 1) DI ON 1 = 1
  WHERE L.OBJ_ID = :I$OBJ_ID
  INTO :VAL;
  SUSPEND;

  -- Заголовок УП
  VAL = NULL;
  SELECT V
  FROM VAL_GET(:I$OBJ_ID, 3012)
  INTO :VAL;
  TAG_NAME = 'name';
  SUSPEND;

  -- Для УП в шаблонах относим план к ВД по ключевым словам в названии
  V$IS_VD = NULL;
  SELECT I
  FROM VAL_GET(:I$OBJ_ID, 3022)
  WHERE IS_EXISTS = 1
  INTO :V$IS_VD;
  IF(V$PT = 55) THEN
  BEGIN
    -- Название сейчас в VAL
    IF(UPPER(VAL) LIKE '%ВНЕУРОЧН%' OR VAL LIKE '% ВД' OR VAL LIKE '% ВД %') THEN V$IS_VD = 2;
  END
  TAG_NAME = 'is_vd';
  VAL = V$IS_VD;
  SUSPEND;

  SELECT I, V
  FROM VAL_GET(:I$OBJ_ID, 3013)
  INTO :VAL, :S;
  TAG_NAME = 'state_id';
  VAL = VAL;
  SUSPEND;
  TAG_NAME = 'state_name';
  VAL = S;
  SUSPEND;

  SELECT I, V
  FROM VAL_GET(:I$OBJ_ID, 3014)
  INTO :V$STD_ID, :S;
  TAG_NAME = 'std_id';
  VAL = V$STD_ID;
  SUSPEND;
  TAG_NAME = 'std_name';
  VAL = S;
  SUSPEND;

  SELECT I, V
  FROM VAL_GET(:I$OBJ_ID, 3015)
  INTO :VAL, :S;
  TAG_NAME = 'form_id';
  VAL = VAL;
  SUSPEND;
  TAG_NAME = 'form_name';
  VAL = S;
  SUSPEND;

  SELECT I, V
  FROM VAL_GET(:I$OBJ_ID, 3016)
  INTO :VAL, :S;
  TAG_NAME = 'type_id';
  SUSPEND;
  TAG_NAME = 'type_name';
  VAL = S;
  SUSPEND;

  SELECT I, V
  FROM VAL_GET(:I$OBJ_ID, 3112)
  INTO :V$PROFILE_ID, :S;
  TAG_NAME = 'profile_id';
  VAL = V$PROFILE_ID;
  SUSPEND;
  TAG_NAME = 'profile_name';
  VAL = S;
  SUSPEND;

  SELECT V
  FROM VAL_GET(:I$OBJ_ID, 3018)
  INTO :VAL;
  TAG_NAME = 'order_num';
  SUSPEND;
  SELECT VD.VAL
  FROM VAL_GET(:I$OBJ_ID, 3019) VG
  LEFT JOIN DATE2ISO(VG.D, 0) VD ON 1 = 1
  INTO :VAL;
  TAG_NAME = 'order_date';
  SUSPEND;

  -- Уровень ОП - либо из ОП, либо из поля в шаблонном УП
  SELECT FIRST 1 V1594.LISTVAL_ID, V3115.VAL
  FROM LINKS LP57
  JOIN VALL V1594 ON V1594.OBJ_ID = LP57.PARENT_ID AND V1594.PARAM_ID = 1594 AND V1594.IS_DEL = 0
  LEFT JOIN VALI V3115 ON V3115.OBJ_ID = LP57.PARENT_ID AND V3115.PARAM_ID = 3115 AND V3115.IS_DEL = 0
  WHERE LP57.OBJ_ID = :I$OBJ_ID AND LP57.PARENT_TYPE_ID = 57 AND LP57.DATE_DEL IS NULL
  INTO :V$LEVEL_ID, :V$YEAR;

  -- -1 в длительности недели нужен чтобы занулить дни недели в этапе
  IF(V$LEVEL_ID IS NULL) THEN
  BEGIN
    SELECT V3345.LISTVAL_ID
    FROM VALL V3345
    WHERE V3345.OBJ_ID = :I$OBJ_ID AND V3345.PARAM_ID = 3345 AND V3345.IS_DEL = 0
    INTO :V$LEVEL_ID;

    -- Неделю из УП берем только в шаблоне
    SELECT V3346.LISTVAL_ID
    FROM VALL V3346
    WHERE V3346.OBJ_ID = :I$OBJ_ID AND V3346.PARAM_ID = 3346 AND V3346.IS_DEL = 0
    INTO :V$WDPLAN;
  END

  IF(V$LEVEL_ID IS NULL AND V$TYPE = 'O') THEN EXCEPTION DATA_ERROR 'Не указан уровень образования в образовательной программе, либо в шаблоне';

  TAG_NAME = 'level_id';
  VAL = V$LEVEL_ID;
  SUSPEND;

  TAG_NAME = 'year';
  VAL = V$YEAR;
  SUSPEND;

  TAG_NAME = 'is_adapt';
  VAL = NULL;
  SELECT V.I
  FROM LINKS LP57
  LEFT JOIN VAL_GET(LP57.PARENT_ID, 2379) V ON 1 = 1
  WHERE LP57.OBJ_ID = :I$OBJ_ID AND LP57.PARENT_TYPE_ID = 57 AND LP57.DATE_DEL IS NULL
  INTO :VAL;
  SUSPEND;

  -- Список этапов обучения
  TAG_NAME = 'stages';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'stages::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L.OBJ_ID, V381.LISTVAL_ID, R381.VAL, V2837.LISTVAL_ID, V382.VAL, V383.VAL
    FROM LINKS L
    JOIN VALL V381 ON V381.OBJ_ID = L.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
    JOIN LISTVALS LV381 ON LV381.LISTVAL_ID = V381.LISTVAL_ID
    JOIN RES R381 ON R381.RES_ID = LV381.RES_ID AND R381.LANG_CODE = 'RU'
    LEFT JOIN VALL V2837 ON V2837.OBJ_ID = L.OBJ_ID AND V2837.PARAM_ID = 2837 AND V2837.IS_DEL = 0
    JOIN VALI V382 ON V382.OBJ_ID = L.OBJ_ID AND V382.PARAM_ID = 382 AND V382.IS_DEL = 0
    LEFT JOIN VALI V383 ON V383.OBJ_ID = L.OBJ_ID AND V383.PARAM_ID = 383 AND V383.IS_DEL = 0
    WHERE L.PARENT_ID = :I$OBJ_ID AND L.OBJ_TYPE_ID = 54 AND L.DATE_DEL IS NULL
    ORDER BY LV381.COST
    INTO :V$OBJ_ID, :V$STAGE_ID, :S, :V$WEEKDAYS, :V$W2, :V$MAXLOAD
  DO
  BEGIN
    TAG_NAME = 'stages:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'stages:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'stages:r:stage';
    VAL = V$STAGE_ID;
    SUSPEND;
    TAG_NAME = 'stages:r:name';
    -- Оптимизация названий для ДОУ
    S = REPLACE(S, 'Первая', '1-я');
    S = REPLACE(S, 'Вторая', '2-я');
    S = REPLACE(S, 'ранняя', 'ран');
    S = REPLACE(S, 'младшая', 'мл');
    S = REPLACE(S, 'средняя', 'ср');
    S = REPLACE(S, 'старшая', 'ст');
    S = REPLACE(S, 'подготовительная', 'подг');
    S = REPLACE(S, 'Разновозрастная', 'Р-возр');
    VAL = S;
    SUSPEND;
    TAG_NAME = 'stages:r:weekdays';
    -- Если план шаблонный, заменяем на количество дней из самого плана
    -- если -1, то зануляем дни недели
    IF(V$WDPLAN IS NOT NULL) THEN V$WEEKDAYS = V$WDPLAN;
    IF(V$WEEKDAYS IS NULL OR V$WEEKDAYS < 0) THEN VAL = NULL;
    ELSE VAL = IIF(V$WEEKDAYS = 11718, 5, 6);
    SUSPEND;
    TAG_NAME = 'stages:r:weeks';
    VAL = V$W2;
    SUSPEND;
    TAG_NAME = 'stages:r:maxload';
    VAL = V$MAXLOAD;
    SUSPEND;

    IF(V$LEVEL_ID = 5346 AND NOT EXISTS(SELECT FIRST 1 1 FROM VALI WHERE OBJ_ID = :V$OBJ_ID AND PARAM_ID = 1762 AND IS_DEL = 0)) THEN
      EXCEPTION DATA_ERROR 'Не указано количество учебных периодов (семестров) в одном из этапов';
  END

  -- Предметы и дисциплины, построчно
  -- При создании нового плана каталог выдаем принудительно
  TAG_NAME = 'subjects';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'subjects::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT S.OBJ_ID, S.SUBJECT_ID, S.SRC_SUBJECT_ID, S.FIELD_ID, S.SORT_INDEX, S.PARENT_ID, S.LEVEL_INDEX, S.IS_ADV, S.IS_STM,
      VN1.VAL, VN2.VAL, R.VAL, S.ROW_TYPE, V3158.LISTVAL_ID, V3159.VAL, S.ROW_CODE
    FROM PLAN_SUBJECTS S
    -- Названия предметов нельзя брать по caption, в колледжах они составные
    LEFT JOIN VALS VN1 ON VN1.OBJ_ID = S.SUBJECT_ID AND VN1.PARAM_ID IN (376, 1751) AND VN1.IS_DEL = 0
    LEFT JOIN VALS VN2 ON VN2.OBJ_ID = S.SRC_SUBJECT_ID AND VN2.PARAM_ID IN (376, 1751) AND VN2.IS_DEL = 0
    LEFT JOIN LISTVALS LV ON LV.LISTVAL_ID = S.FIELD_ID
    LEFT JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
    -- Тип предмета
    LEFT JOIN VALL V3158 ON V3158.OBJ_ID = S.SUBJECT_ID AND V3158.PARAM_ID = 3158 AND V3158.IS_DEL = 0
    -- Эталонный предмет
    LEFT JOIN VALR V3159 ON V3159.OBJ_ID = S.SUBJECT_ID AND V3159.PARAM_ID = 3159 AND V3159.IS_DEL = 0
    WHERE S.DATE_DEL IS NULL AND S.PLAN_ID = :I$OBJ_ID
    ORDER BY S.GLOBAL_INDEX
    INTO :V$OBJ_ID, :V$SUBJECT_ID, :V$SRC_SUBJECT_ID, :V$FIELD_ID, :V$SORT_INDEX, :V$PARENT_ID, :V$LEVEL_INDEX, :V$IS_ADV, :V$STM,
      :S, :SS, :S2, :V$FOLDER_TYPE, :V$STYPE, :V$REF_ID, :V$CODE
  DO
  BEGIN
    IF(V$STD_ID = 11720 AND V$FIELD_ID = 13303) THEN S2 = 'Федеральный компонент';
    IF(V$STD_ID = 11720 AND V$FIELD_ID = 13304) THEN S2 = 'Региональный и компонент ОООД';

    TAG_NAME = 'subjects:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'subjects:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'subjects:r:parent_id';
    VAL = V$PARENT_ID;
    SUSPEND;
    TAG_NAME = 'subjects:r:level';
    VAL = V$LEVEL_INDEX;
    SUSPEND;
    TAG_NAME = 'subjects:r:type';
    VAL = V$FOLDER_TYPE;
    SUSPEND;
    TAG_NAME = 'subjects:r:code';
    VAL = V$CODE;
    SUSPEND;
    TAG_NAME = 'subjects:r:stype';
    VAL = V$STYPE;
    SUSPEND;
    TAG_NAME = 'subjects:r:subject_id';
    VAL = V$SUBJECT_ID;
    SUSPEND;
    TAG_NAME = 'subjects:r:src_subject_id';
    VAL = V$SRC_SUBJECT_ID;
    SUSPEND;
    TAG_NAME = 'subjects:r:subject_name';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'subjects:r:src_subject_name';
    VAL = SS;
    SUSPEND;
    TAG_NAME = 'subjects:r:field_id';
    VAL = V$FIELD_ID;
    SUSPEND;
    TAG_NAME = 'subjects:r:field_name';
    VAL = S2;
    SUSPEND;
    TAG_NAME = 'subjects:r:sort_index';
    VAL = V$SORT_INDEX;
    SUSPEND;
    TAG_NAME = 'subjects:r:is_adv';
    VAL = V$IS_ADV;
    SUSPEND;
    TAG_NAME = 'subjects:r:is_stm';
    VAL = V$STM;
    SUSPEND;
    TAG_NAME = 'subjects:r:ref_id';
    VAL = V$REF_ID;
    SUSPEND;

    -- Суммарные цифры по строке - только где это реальный предмет, а не раздел
    -- некоторые цифры идут только для строки целиком, а не для конкретного этапа, пока это все про запас
    IF(V$FOLDER_TYPE = 10) THEN
    BEGIN
    END

    -- Выдаем цифры по пронумерованным этапам
    TAG_NAME = 'subjects:r:load::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT PL.STAGE_ID, LV381.COST, PL.WEEKS, PL.LOAD_HOURS_S1, PL.LOAD_HOURS_S2, PL.CONTROL_Q1, PL.CONTROL_Q2, PL.HOURS_THEORY1, PL.HOURS_PR1, PL.HOURS_DX1, PL.HOURS_IND1,
        PL.HOURS_MAX, PL.HOURS_CR1, PL.HOURS_ATT1, PL.HOURS_GIA, PL.HOURS_REST
      FROM LINKS L
      JOIN VALL V381 ON V381.OBJ_ID = L.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
      JOIN LISTVALS LV381 ON LV381.LISTVAL_ID = V381.LISTVAL_ID
      JOIN PLAN_LOADS PL ON PL.STAGE_ID = L.OBJ_ID AND PL.SUBJECT_ID = :V$OBJ_ID AND PL.DATE_DEL IS NULL
      WHERE L.PARENT_ID = :I$OBJ_ID AND L.OBJ_TYPE_ID = 54 AND L.DATE_DEL IS NULL
      UNION
      SELECT NULL, NULL, PL.WEEKS, PL.LOAD_HOURS_S1, PL.LOAD_HOURS_S2, PL.CONTROL_Q1, PL.CONTROL_Q2, PL.HOURS_THEORY1, PL.HOURS_PR1, PL.HOURS_DX1, PL.HOURS_IND1,
        PL.HOURS_MAX, PL.HOURS_CR1, PL.HOURS_ATT1, PL.HOURS_GIA, PL.HOURS_REST
      FROM PLAN_LOADS PL
      WHERE PL.STAGE_ID IS NULL AND PL.SUBJECT_ID = :V$OBJ_ID AND PL.DATE_DEL IS NULL
      ORDER BY 2
      INTO :V$STAGE_ID, :V$REF_ID, :V$WEEKS, :V$LOAD_HOURS_S1, :V$LOAD_HOURS_S2, :V$CONTROL_Q1, :V$CONTROL_Q2, :V$HOURS_THEORY1, :V$HOURS_PR1, :V$HOURS_DX1, :V$HOURS_IND1,
        :V$HOURS_MAX, :V$HOURS_CR1, :V$HOURS_ATT1, :V$HOURS_GIA, :V$HOURS_REST
    DO
    BEGIN
      TAG_NAME = 'subjects:r:load:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'subjects:r:load:r:stage_id';
      VAL = V$STAGE_ID;
      SUSPEND;
      TAG_NAME = 'subjects:r:load:r:weeks';
      VAL = V$WEEKS;
      SUSPEND;
      TAG_NAME = 'subjects:r:load:r:hours1';
      VAL = V$LOAD_HOURS_S1;
      SUSPEND;
      TAG_NAME = 'subjects:r:load:r:hours2';
      VAL = V$LOAD_HOURS_S2;
      SUSPEND;
      TAG_NAME = 'subjects:r:load:r:control1';
      VAL = V$CONTROL_Q1;
      SUSPEND;
      TAG_NAME = 'subjects:r:load:r:control2';
      VAL = V$CONTROL_Q2;
      SUSPEND;
      TAG_NAME = 'subjects:r:load:r:htheory1';
      VAL = V$HOURS_THEORY1;
      SUSPEND;
      TAG_NAME = 'subjects:r:load:r:hpr1';
      VAL = V$HOURS_PR1;
      SUSPEND;
      TAG_NAME = 'subjects:r:load:r:hdx1';
      VAL = V$HOURS_DX1;
      SUSPEND;
      TAG_NAME = 'subjects:r:load:r:hind1';
      VAL = V$HOURS_IND1;
      SUSPEND;
      TAG_NAME = 'subjects:r:load:r:hmax';
      VAL = V$HOURS_MAX;
      SUSPEND;
      TAG_NAME = 'subjects:r:load:r:hcr1';
      VAL = V$HOURS_CR1;
      SUSPEND;
      TAG_NAME = 'subjects:r:load:r:hatt1';
      VAL = V$HOURS_ATT1;
      SUSPEND;
      TAG_NAME = 'subjects:r:load:r:hgia';
      VAL = V$HOURS_GIA;
      SUSPEND;
      TAG_NAME = 'subjects:r:load:r:hrest';
      VAL = V$HOURS_REST;
      SUSPEND;
    END

  END

  -- Справочники
  -- Разделы, доступные для выбора в корне списка
  -- Предметы по выбору выдаем только для УП СО
  TAG_NAME = 'blocks';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'blocks::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT LISTVAL_ID, VAL
    FROM OBJECT_LISTVALS_LIST(245, 1)
    WHERE
      ("FILTER" LIKE '%GOU%' AND :V$LEVEL_ID IN (5339, 5341, 5343, 13272) AND ((:V$IS_VD = 2 AND LISTVAL_ID = 12927) OR (:V$IS_VD <> 2 AND LISTVAL_ID NOT IN (12926, 12927)))) -- школа
      OR (:I$APP = 'copp' AND "FILTER" LIKE '%COPP%') -- ЦОПП, модули
      OR (:V$LEVEL_ID = 5346 AND :I$APP <> 'copp' AND "FILTER" NOT LIKE '%COPP%' AND LISTVAL_ID IN (5240, 5245, 5248, 5249)) -- обычные колледжи - ВД тут не должно быть
      OR (:V$LEVEL_ID = 5358 AND 0 = 1) -- ОДОД :V$TYPE = 'U'
      OR (:V$LEVEL_ID = 5337 AND "FILTER" LIKE '%DOU%') -- ДОУ
      OR (:V$LEVEL_ID = 5361 AND 0 = 1) -- ДПО :V$TYPE = 'P'
    INTO :V$OBJ_ID, :S
  DO
  BEGIN
    TAG_NAME = 'blocks:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'blocks:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'blocks:r:name';
    IF(V$STD_ID = 11720 AND V$OBJ_ID = 13303) THEN S = 'Федеральный компонент';
    IF(V$STD_ID = 11720 AND V$OBJ_ID = 13304) THEN S = 'Региональный и компонент ОООД';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'blocks:r:type';
    VAL = '0';
    SUSPEND;
  END

  -- Виды контролей
  TAG_NAME = 'ctypes';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'ctypes::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT LISTVAL_ID, VAL
    FROM OBJECT_LISTVALS_LIST(246, 1)
    -- Дофильтровать !
    INTO :V$OBJ_ID, :S
  DO
  BEGIN
    TAG_NAME = 'ctypes:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'ctypes:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'ctypes:r:name';
    VAL = S;
    SUSPEND;
  END

  -- Список эталонных предметов по уровню и профилю - и сразу с часами для верификации
  -- Пока берем из старых учебных планов
  IF(V$PT <> 55) THEN
  BEGIN

    -- Базовый / базовый 5-дневка
    SELECT FIRST 1 L400.OBJ_ID
    FROM LINKS L400
    JOIN VALL V3347 ON V3347.OBJ_ID = L400.OBJ_ID AND V3347.PARAM_ID = 3347 AND V3347.IS_DEL = 0 AND V3347.LISTVAL_ID = 2
    JOIN VALL V3345 ON V3345.OBJ_ID = L400.OBJ_ID AND V3345.PARAM_ID = 3345 AND V3345.IS_DEL = 0 AND V3345.LISTVAL_ID = :V$LEVEL_ID
    JOIN VALL V3014 ON V3014.OBJ_ID = L400.OBJ_ID AND V3014.PARAM_ID = 3014 AND V3014.IS_DEL = 0 AND V3014.LISTVAL_ID = :V$STD_ID
    JOIN VALL V3112 ON V3112.OBJ_ID = L400.OBJ_ID AND V3112.PARAM_ID = 3112 AND V3112.IS_DEL = 0 AND V3112.LISTVAL_ID = 10955
    LEFT JOIN VALL V3346 ON V3346.OBJ_ID = L400.OBJ_ID AND V3346.PARAM_ID = 3346 AND V3346.IS_DEL = 0
    WHERE L400.PARENT_ID = 258 AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL AND (:V$STD_ID NOT IN (13452, 14184) OR V3346.LISTVAL_ID = 11718 OR V3346.LISTVAL_ID IS NULL)
      AND (L400.REASON_ID IS NULL OR L400.REASON_ID <= :V$YEAR)
    ORDER BY L400.REASON_ID DESC NULLS LAST, V3346.LISTVAL_ID NULLS FIRST
    INTO :V$BASE_ID;

    -- Базовый / базовый 6-дневка
    SELECT FIRST 1 L400.OBJ_ID
    FROM LINKS L400
    JOIN VALL V3347 ON V3347.OBJ_ID = L400.OBJ_ID AND V3347.PARAM_ID = 3347 AND V3347.IS_DEL = 0 AND V3347.LISTVAL_ID = 2
    JOIN VALL V3345 ON V3345.OBJ_ID = L400.OBJ_ID AND V3345.PARAM_ID = 3345 AND V3345.IS_DEL = 0 AND V3345.LISTVAL_ID = :V$LEVEL_ID
    JOIN VALL V3014 ON V3014.OBJ_ID = L400.OBJ_ID AND V3014.PARAM_ID = 3014 AND V3014.IS_DEL = 0 AND V3014.LISTVAL_ID = :V$STD_ID
    JOIN VALL V3112 ON V3112.OBJ_ID = L400.OBJ_ID AND V3112.PARAM_ID = 3112 AND V3112.IS_DEL = 0 AND V3112.LISTVAL_ID = 10955
    LEFT JOIN VALL V3346 ON V3346.OBJ_ID = L400.OBJ_ID AND V3346.PARAM_ID = 3346 AND V3346.IS_DEL = 0
    WHERE L400.PARENT_ID = 258 AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL AND (:V$STD_ID NOT IN (13452, 14184) OR V3346.LISTVAL_ID = 11719 OR V3346.LISTVAL_ID IS NULL)
      AND (L400.REASON_ID IS NULL OR L400.REASON_ID <= :V$YEAR)
    ORDER BY L400.REASON_ID DESC NULLS LAST, V3346.LISTVAL_ID NULLS FIRST
    INTO :V$BASE_ID2;

    IF(V$BASE_ID IS NULL AND V$STD_ID IN (13452, 14184)) THEN
    BEGIN
      -- Не нашли подходящий - берем хотя бы старый ФГОС
      SELECT FIRST 1 L400.OBJ_ID
      FROM LINKS L400
      JOIN VALL V3347 ON V3347.OBJ_ID = L400.OBJ_ID AND V3347.PARAM_ID = 3347 AND V3347.IS_DEL = 0 AND V3347.LISTVAL_ID = 2
      JOIN VALL V3345 ON V3345.OBJ_ID = L400.OBJ_ID AND V3345.PARAM_ID = 3345 AND V3345.IS_DEL = 0 AND V3345.LISTVAL_ID = :V$LEVEL_ID
      JOIN VALL V3014 ON V3014.OBJ_ID = L400.OBJ_ID AND V3014.PARAM_ID = 3014 AND V3014.IS_DEL = 0 AND V3014.LISTVAL_ID = 11721
      JOIN VALL V3112 ON V3112.OBJ_ID = L400.OBJ_ID AND V3112.PARAM_ID = 3112 AND V3112.IS_DEL = 0 AND V3112.LISTVAL_ID = 10955
      WHERE L400.PARENT_ID = 258 AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL
      ORDER BY 1
      INTO :V$BASE_ID;
    END

    IF(V$BASE_ID2 IS NULL) THEN V$BASE_ID2 = V$BASE_ID;

    SELECT FIRST 1 L400.OBJ_ID
    FROM LINKS L400
    JOIN VALL V3347 ON V3347.OBJ_ID = L400.OBJ_ID AND V3347.PARAM_ID = 3347 AND V3347.IS_DEL = 0 AND V3347.LISTVAL_ID = 2
    JOIN VALL V3345 ON V3345.OBJ_ID = L400.OBJ_ID AND V3345.PARAM_ID = 3345 AND V3345.IS_DEL = 0 AND V3345.LISTVAL_ID = :V$LEVEL_ID
    JOIN VALL V3014 ON V3014.OBJ_ID = L400.OBJ_ID AND V3014.PARAM_ID = 3014 AND V3014.IS_DEL = 0 AND V3014.LISTVAL_ID = :V$STD_ID
    LEFT JOIN VALL V3112 ON V3112.OBJ_ID = L400.OBJ_ID AND V3112.PARAM_ID = 3112 AND V3112.IS_DEL = 0
    WHERE L400.PARENT_ID = 258 AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL AND V3112.LISTVAL_ID IS NULL
    ORDER BY 1
    INTO :V$ADV_ID;

  END

  -- Предметы в обоих недельных шаблонах должны совпадать
  TAG_NAME = 'basesubj';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'basesubj::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    -- Только в новом формате
    SELECT DISTINCT PS.SUBJECT_ID, V3159.VAL, C.CAPTION
    FROM PLAN_SUBJECTS PS
    LEFT JOIN OBJECT_CAPTION_GET(PS.SUBJECT_ID) C ON 1 = 1
    LEFT JOIN VALR V3159 ON V3159.OBJ_ID = PS.SUBJECT_ID AND V3159.PARAM_ID = 3159 AND V3159.IS_DEL = 0
    WHERE PS.DATE_DEL IS NULL AND PS.PLAN_ID = :V$BASE_ID AND PS.ROW_TYPE = 10
    -- Второй иностранный язык есть везде
    UNION
    SELECT L51.OBJ_ID, NULL, C.CAPTION
    FROM LINKS L51
    LEFT JOIN OBJECT_CAPTION_GET(L51.OBJ_ID) C ON 1 = 1
    WHERE L51.PARENT_ID = 32771 AND L51.OBJ_ID = 32810 AND L51.DATE_DEL IS NULL
    INTO :V$SUBJECT_ID, :V$SRC_SUBJECT_ID, :S
  DO
  BEGIN
    TAG_NAME = 'basesubj:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'basesubj:r:id';
    VAL = V$SUBJECT_ID;
    SUSPEND;
    -- Мастер-предмет для проверок по математике ООО, СОО
    TAG_NAME = 'basesubj:r:ref_id';
    VAL = V$SRC_SUBJECT_ID;
    SUSPEND;
    TAG_NAME = 'basesubj:r:name';
    VAL = S;
    SUSPEND;
    -- Часы нагрузки в формате level=hours, соответствующие нужной неделе
    TAG_NAME = 'basesubj:r:hours';
    VAL = '';
    FOR
      SELECT STAGE_ID, SUM(IIF(HTYPE = 0, HOURS, 0)), SUM(IIF(HTYPE = 1, HOURS, 0))
      FROM (
        -- Только в новом формате
        SELECT V381.LISTVAL_ID STAGE_ID, PL.LOAD_HOURS HOURS, 0 HTYPE
        FROM LINKS L54
        JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
        JOIN PLAN_SUBJECTS PS ON PS.DATE_DEL IS NULL AND PS.PLAN_ID = L54.PARENT_ID AND PS.SUBJECT_ID = :V$SUBJECT_ID
        JOIN PLAN_LOADS PL ON PL.DATE_DEL IS NULL AND PL.SUBJECT_ID = PS.OBJ_ID AND PL.STAGE_ID = L54.OBJ_ID AND PL.LOAD_HOURS > 0
        WHERE L54.PARENT_ID = :V$BASE_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
        UNION
        SELECT V381.LISTVAL_ID STAGE_ID, PL.LOAD_HOURS HOURS, 1 HTYPE
        FROM LINKS L54
        JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
        JOIN PLAN_SUBJECTS PS ON PS.DATE_DEL IS NULL AND PS.PLAN_ID = L54.PARENT_ID AND PS.SUBJECT_ID = :V$SUBJECT_ID
        JOIN PLAN_LOADS PL ON PL.DATE_DEL IS NULL AND PL.SUBJECT_ID = PS.OBJ_ID AND PL.STAGE_ID = L54.OBJ_ID AND PL.LOAD_HOURS > 0
        WHERE L54.PARENT_ID = :V$BASE_ID2 AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
      )
      GROUP BY 1
      INTO :V$STAGE_ID, :V$LOAD_HOURS_S1, :V$LOAD_HOURS_S2
    DO
    BEGIN
      IF(VAL <> '') THEN VAL = VAL || ';';
      -- Берем часы для 5 или 6-дневки. Если не нашли ничего, берем 6-дневку
      IF(EXISTS(
        SELECT FIRST 1 1
        FROM LINKS L54
        JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0 AND V381.LISTVAL_ID = :V$STAGE_ID
        JOIN VALL V2837 ON V2837.OBJ_ID = L54.OBJ_ID AND V2837.PARAM_ID = 2837 AND V2837.IS_DEL = 0 AND V2837.LISTVAL_ID = 11718
        WHERE L54.PARENT_ID = :I$OBJ_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
      ))
      THEN VAL = VAL || V$STAGE_ID || '=' || CAST(V$LOAD_HOURS_S1 AS NUMERIC(18, 1));
      ELSE VAL = VAL || V$STAGE_ID || '=' || CAST(V$LOAD_HOURS_S2 AS NUMERIC(18, 1));
    END
    SUSPEND;
  END

  TAG_NAME = 'advsubj';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'advsubj::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    -- Только в новом формате
    SELECT DISTINCT PS.SUBJECT_ID, C.CAPTION
    FROM PLAN_SUBJECTS PS
    LEFT JOIN OBJECT_CAPTION_GET(PS.SUBJECT_ID) C ON 1 = 1
    WHERE PS.DATE_DEL IS NULL AND PS.PLAN_ID = :V$ADV_ID AND PS.ROW_TYPE = 10
    INTO :V$SUBJECT_ID, :S
  DO
  BEGIN
    TAG_NAME = 'advsubj:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'advsubj:r:id';
    VAL = V$SUBJECT_ID;
    SUSPEND;
    TAG_NAME = 'advsubj:r:name';
    VAL = S;
    SUSPEND;
    -- Часы нагрузки в формате level=hours
    TAG_NAME = 'advsubj:r:hours';
    VAL = '';
    FOR
      SELECT V381.LISTVAL_ID, PL.LOAD_HOURS
      FROM LINKS L54
      JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
      JOIN PLAN_SUBJECTS PS ON PS.DATE_DEL IS NULL AND PS.PLAN_ID = L54.PARENT_ID AND PS.SUBJECT_ID = :V$SUBJECT_ID
      JOIN PLAN_LOADS PL ON PL.DATE_DEL IS NULL AND PL.SUBJECT_ID = PS.OBJ_ID AND PL.STAGE_ID = L54.OBJ_ID AND PL.LOAD_HOURS > 0
      WHERE L54.PARENT_ID = :V$ADV_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
      INTO :V$STAGE_ID, :V$LOAD_HOURS_S1
    DO
    BEGIN
      IF(VAL <> '') THEN VAL = VAL || ';';
      VAL = VAL || V$STAGE_ID || '=' || CAST(V$LOAD_HOURS_S1 AS NUMERIC(18, 1));
    END
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PLAN_GUP_RECALC (
    I$GUP_ID BIGINT)
AS
declare variable V$STAGE_ID bigint;
declare variable V$PLAN_ID bigint;
declare variable V$SEPT20 date;
declare variable N integer;
begin

  -- Год к которому относить берем из года утверждения ОП
  SELECT FIRST 1 LP54.PARENT_ID, LP400.PARENT_ID, V3115.VAL
  FROM LINKS LP54
  JOIN LINKS LP400 ON LP400.OBJ_ID = LP54.PARENT_ID AND LP400.PARENT_TYPE_ID = 400
  JOIN LINKS LP57 ON LP57.OBJ_ID = LP400.PARENT_ID AND LP57.PARENT_TYPE_ID = 57
  JOIN VALI V3115 ON V3115.OBJ_ID = LP57.PARENT_ID AND V3115.PARAM_ID = 3115 AND V3115.IS_DEL = 0
  WHERE LP54.OBJ_ID = :I$GUP_ID AND LP54.PARENT_TYPE_ID = 54
  ORDER BY LP54.DATE_DEL NULLS FIRST
  INTO :V$STAGE_ID, :V$PLAN_ID, :N;

  IF(V$STAGE_ID IS NULL) THEN EXIT;

  V$SEPT20 = '20.09.' || N;

  -- Текущее количество учащихся по этапу
  SELECT COUNT(*)
  FROM LINKS L256
  JOIN LINKS L10 ON L10.PARENT_ID = L256.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
  WHERE L256.PARENT_ID = :V$STAGE_ID AND L256.OBJ_TYPE_ID = 256 AND L256.DATE_DEL IS NULL
  INTO :N;

  UPDATE OR INSERT INTO VALI
  (OBJ_ID, PARAM_ID, IS_DEL, VAL)
  VALUES (:V$STAGE_ID, 3444, 0, :N);

  -- Текущее количество учащихся по УП
  SELECT COUNT(*)
  FROM LINKS L54
  JOIN LINKS L256 ON L256.PARENT_ID = L54.OBJ_ID AND L256.OBJ_TYPE_ID = 256 AND L256.DATE_DEL IS NULL
  JOIN LINKS L10 ON L10.PARENT_ID = L256.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
  WHERE L54.PARENT_ID = :V$PLAN_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
  INTO :N;

  UPDATE OR INSERT INTO VALI
  (OBJ_ID, PARAM_ID, IS_DEL, VAL)
  VALUES (:V$PLAN_ID, 3442, 0, :N);

  -- Количество обучающихся на 20.09
  SELECT COUNT(DISTINCT M.PERSON_ID)
  FROM LINKS L54
  JOIN LINKS L256 ON L256.PARENT_ID = L54.OBJ_ID AND L256.OBJ_TYPE_ID = 256 AND L256.DATE_DEL IS NULL
  JOIN PERSON_MOVEMENTS M ON M.DATE_DEL IS NULL AND M.GROUP_ID = L256.OBJ_ID AND M.DATE_IN <= :V$SEPT20 AND (M.DATE_OUT IS NULL OR M.DATE_OUT > :V$SEPT20)
  WHERE L54.PARENT_ID = :V$PLAN_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
  INTO :N;

  UPDATE OR INSERT INTO VALI
  (OBJ_ID, PARAM_ID, IS_DEL, VAL)
  VALUES (:V$PLAN_ID, 3441, 0, :N);

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PLAN_HISTORY_REPORT (
    I$OBJ_ID BIGINT)
RETURNS (
    VAL VARCHAR(4000))
AS
declare variable V$DT timestamp;
declare variable V$PARENT_ID bigint;
declare variable V$FC varchar(1000);
declare variable V$FLAGS bigint;
declare variable S1 varchar(1500);
declare variable S2 varchar(1500);
declare variable U varchar(400);
declare variable S varchar(400);
begin

  VAL = '<!DOCTYPE html>';
  VAL = VAL || '<html lang="ru">';
  VAL = VAL || '<head>';
  VAL = VAL || '<meta charset="utf-8" />';
  VAL = VAL || '<style>';
  VAL = VAL || 'html { font-family: Tahoma, Verdana, Arial;';
  VAL = VAL || 'font-size: 10pt; ';
  VAL = VAL || '} ';
  VAL = VAL || '.title1 { font-size: 150%;';
  VAL = VAL || 'padding: 8px;';
  VAL = VAL || 'margin-bottom: 4px;';
  VAL = VAL || 'font-weight: bold;';
  VAL = VAL || 'background-color: #D4E157;';
  VAL = VAL || '} ';
  VAL = VAL || '.title2 { ';
  VAL = VAL || 'padding: 4px;';
  VAL = VAL || 'font-weight: bold;';
  VAL = VAL || '} ';
  VAL = VAL || 'p { ';
  VAL = VAL || 'padding: 4px;';
  VAL = VAL || '} ';
  VAL = VAL || 'td { ';
  VAL = VAL || 'padding: 0.25em 0.5em; ';
  VAL = VAL || 'border-right: 1px solid #808080; ';
  VAL = VAL || 'border-bottom: 1px solid #808080; ';
  VAL = VAL || 'max-width: 20rem; ';
  VAL = VAL || '} ';
  VAL = VAL || 'td:first-child { ';
  VAL = VAL || 'border-left: 1px solid #808080; ';
  VAL = VAL || '} ';
  VAL = VAL || 'tr:first-child td { ';
  VAL = VAL || 'border-top: 1px solid #808080; ';
  VAL = VAL || '} ';
  VAL = VAL || '</style>';

  VAL = VAL || '</head>';
  VAL = VAL || '<body>';
  SUSPEND;

  -- Заголовок отчета
  VAL = '<div class="title1">История изменений учебного плана</div>';

  VAL = VAL || '<div class="title2">' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$OBJ_ID)) || '</div>';
  VAL = VAL || '<p>В истории изменений фиксируются только изменения, внесенные в статусе "действующий"</p>';

  -- Заголовок таблицы
  VAL = VAL || '<table class="table" cellspacing="0" cellpadding="0" style="width: 100%">';

  VAL = VAL || '<tr class="thd">';
  VAL = VAL || '<td>Дата, время</td>';
  VAL = VAL || '<td>Кто изменил</td>';
  VAL = VAL || '<td>Состав изменений</td>';
  VAL = VAL || '</tr>';
  SUSPEND;

  FOR
    SELECT H.DATE_ADD, H.PARAM_ID, FC.VAL, H.PARENT_ID, H.OLD_VAL, H.VAL, IIF(H.USER_ID = -1, 'Веб-администратор', COALESCE(U.DESCRIPTION, U.USER_NAME))
    FROM HISTVALS H
    LEFT JOIN PLAN_SUBJECTS PS ON PS.OBJ_ID = H.PARENT_ID
    LEFT JOIN LISTVAL_TEXT(PS.FIELD_ID) FC ON 1 = 1
    LEFT JOIN USERS U ON U.USER_ID = H.USER_ID
    WHERE H.TABLE_NAME = 'PLAN' AND H.OBJ_ID = :I$OBJ_ID
    UNION ALL
    SELECT H.DATE_ADD, NULL, R.VAL, P.PARAM_TYPE, H.OLD_VAL, H.VAL, IIF(H.USER_ID = -1, 'Веб-администратор', COALESCE(U.DESCRIPTION, U.USER_NAME))
    FROM HISTVALS H
    LEFT JOIN PARAMS P ON P.PARAM_ID = H.PARAM_ID
    LEFT JOIN RES R ON R.RES_ID = P.RES_ID AND R.LANG_CODE = 'RU'
    LEFT JOIN USERS U ON U.USER_ID = H.USER_ID
    WHERE H.TABLE_NAME = 'VAL' AND H.OBJ_ID = :I$OBJ_ID
    ORDER BY 1
    INTO :V$DT, :V$PARENT_ID, :V$FC, :V$FLAGS, :S1, :S2, :U
  DO
  BEGIN
    IF(S1 IS NULL) THEN S1 = '';
    ELSE IF(S1 = 'Удален предмет') THEN BEGIN
    END
    ELSE IF(S1 = 'Новый предмет' OR S1 = 'Изменение предмета') THEN BEGIN
      S = '';
      IF(BIN_AND(V$FLAGS, 1) <> 0) THEN S = S || ', углубленное изучение'; ELSE S = S || ', базовый';
      IF(BIN_AND(V$FLAGS, 2) <> 0) THEN S = S || ', потоковый'; ELSE S = S || ', не-потоковый';
      IF(SUBSTRING(S FROM 1 FOR 1) = ',') THEN S = SUBSTRING(S FROM 2);
      S2 = S2 || ', атрибуты: ' || S;
    END

    -- Изменение атрибутов самого УП
    IF(V$PARENT_ID IS NULL) THEN
    BEGIN
      -- Конвертируем LISTVAL в текст
      IF(V$FLAGS = 6) THEN
      BEGIN
        IF(S1 <> '') THEN
        SELECT LV.VAL
        FROM LISTVAL_TEXT(CAST(:S1 AS BIGINT)) LV
        INTO :S1;

        IF(S2 <> '') THEN
        SELECT LV.VAL
        FROM LISTVAL_TEXT(CAST(:S2 AS BIGINT)) LV
        INTO :S2;
      END

      IF(V$FC IS NOT NULL) THEN S1 = 'Атрибут <b>' || V$FC || '</b>, старое значение ' || S1;
      IF(V$FC IS NOT NULL) THEN S2 = ', новое значение ' || S2;
      V$FC = NULL;
    END

    IF(V$FC IS NULL) THEN V$FC = ''; ELSE V$FC = ', в разделе: ' || V$FC;

    VAL = '<tr><td>' || V$DT || '</td>';
    VAL = VAL || '<td>' || COALESCE(U, '') || '</td>';
    VAL = VAL || '<td>' || S1 || COALESCE(' ' || S2, '') || V$FC || '</td>';
    VAL = VAL || '</tr>';
    SUSPEND;
  END

  VAL = '</table></body></html>';
  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PLAN_IMPORT_CLEAR (
    OBJ_ID BIGINT)
AS
declare variable N integer;
declare variable RUN_ID bigint;
begin
    N = 0;

    -- Не трогаем утвержденные УП
    SELECT FIRST 1 1
    FROM VALL
    WHERE OBJ_ID = :OBJ_ID AND PARAM_ID = 2470 AND IS_DEL = 0 AND LISTVAL_ID = 11715
    INTO :N;

    IF(N > 0) THEN EXCEPTION DATA_ERROR 'Нельзя импортировать действующие УП. Для импорта переведите УП в статус проекта';

    -- Проверяем, чтобы не было учебных коллективов
    SELECT FIRST 1 1
    FROM LINKS L54
    JOIN LINKS LG ON LG.PARENT_ID = L54.OBJ_ID AND LG.DATE_DEL IS NULL AND LG.OBJ_TYPE_ID IN (256, 346)
    WHERE L54.PARENT_ID = :OBJ_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
    INTO :N;

    IF(N > 0) THEN EXCEPTION DATA_ERROR 'Импорт не может быть проведен для плана, к которому привязаны учебные коллективы или создано деление на потоки';

    -- Удаляем профильные предметы
    UPDATE LINKS L51
    SET L51.DATE_DEL = CURRENT_TIMESTAMP
    WHERE L51.PARENT_ID = :OBJ_ID AND L51.OBJ_TYPE_ID = 51 AND L51.DATE_DEL IS NULL;

    -- Удаляем нагрузки учебного плана для всех этапов
    FOR
      SELECT L56.LINK_ID
      FROM LINKS L49
      JOIN LINKS L56 ON L56.PARENT_ID = L49.OBJ_ID AND L56.OBJ_TYPE_ID = 56 AND L56.DATE_DEL IS NULL
      WHERE L49.PARENT_ID = :OBJ_ID AND L49.OBJ_TYPE_ID = 49 AND L49.DATE_DEL IS NULL
      INTO :RUN_ID
    DO
    BEGIN
      UPDATE LINKS SET DATE_DEL = CURRENT_TIMESTAMP WHERE LINK_ID = :RUN_ID;
    END

    -- Удаляем предметы из компонентов
    FOR
      SELECT L51.LINK_ID
      FROM LINKS L49
      JOIN LINKS L51 ON L51.PARENT_ID = L49.OBJ_ID AND L51.OBJ_TYPE_ID = 51 AND L51.DATE_DEL IS NULL
      WHERE L49.PARENT_ID = :OBJ_ID AND L49.OBJ_TYPE_ID = 49 AND L49.DATE_DEL IS NULL
      INTO :RUN_ID
    DO
    BEGIN
      UPDATE LINKS SET DATE_DEL = CURRENT_TIMESTAMP WHERE LINK_ID = :RUN_ID;
    END

    -- Удаляем предметы и компоненты
    UPDATE LINKS
    SET DATE_DEL = NULL
    WHERE PARENT_ID = :OBJ_ID AND OBJ_TYPE_ID IN (49, 54) AND DATE_DEL IS NULL;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PLAN_IMPORT_LOAD (
    OBJ_ID BIGINT,
    COMPONENT_INDEX BIGINT,
    SUBJECT_ID BIGINT,
    STAGE_ID BIGINT,
    DURATION INTEGER,
    LOAD_HOURS INTEGER)
AS
declare variable CV1 bigint;
declare variable CV2 bigint;
declare variable COMPONENT_ID bigint;
declare variable LOAD_ID bigint;
declare variable LINK1 bigint;
declare variable LINK2 bigint;
declare variable LINK3 bigint;
declare variable BLOB_ID bigint;
begin
  IF(COMPONENT_INDEX = 1) THEN CV1 = 780;
  ELSE IF(COMPONENT_INDEX = 2) THEN CV1 = 782;
  ELSE IF(COMPONENT_INDEX = 12752) THEN CV1 = 780;
  ELSE IF(COMPONENT_INDEX = 12753) THEN CV1 = 782;
  IF(CV1 = 780) THEN CV2 = 12752; ELSE CV2 = 12753;

  SELECT FIRST 1 L49.OBJ_ID
  FROM LINKS L49
  JOIN VALL V372 ON V372.OBJ_ID = L49.OBJ_ID AND V372.PARAM_ID = 372 AND V372.IS_DEL = 0 AND (V372.LISTVAL_ID = :CV1 OR V372.LISTVAL_ID = :CV2)
  WHERE L49.PARENT_ID = :OBJ_ID AND L49.OBJ_TYPE_ID = 49 AND L49.DATE_DEL IS NULL
  INTO :COMPONENT_ID;

  IF(COMPONENT_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не удалось найти один из компонентов учебного плана (нагрузки)';

  -- Ищем нагрузку на пересечении указанных трех метрик
  SELECT FIRST 1 L54_56.OBJ_ID, L54_56.LINK_ID, L49_56.LINK_ID, L51_56.LINK_ID
  FROM LINKS L54_56
  JOIN LINKS L49_56 ON L49_56.PARENT_ID = :COMPONENT_ID AND L49_56.OBJ_ID = L54_56.OBJ_ID
  JOIN LINKS L51 ON L51.PARENT_ID = :COMPONENT_ID AND L51.OBJ_ID = :SUBJECT_ID AND L51.DATE_DEL IS NULL
  JOIN LINKS L51_56 ON L51_56.PARENT_ID = L51.OBJ_ID AND L51_56.OBJ_ID = L54_56.OBJ_ID
  WHERE L54_56.PARENT_ID = :STAGE_ID AND L54_56.OBJ_TYPE_ID = 56
  ORDER BY L54_56.DATE_MODIFY DESC
  INTO :LOAD_ID, :LINK1, :LINK2, :LINK3;

  IF(LOAD_ID IS NULL) THEN
  BEGIN
    -- Создаем новый объект нагрузки
    SELECT OBJ_ID FROM OBJECT_ADD(:STAGE_ID, 56) INTO :LOAD_ID;
    SELECT LINK_ID FROM OBJECT_ADD_LINK(:COMPONENT_ID, :LOAD_ID, 56) INTO :LINK2;
    SELECT LINK_ID FROM OBJECT_ADD_LINK(:SUBJECT_ID, :LOAD_ID, 56) INTO :LINK3;
  END
  ELSE
  BEGIN
    -- Восстанавливаем старую связь
    UPDATE LINKS SET DATE_DEL = NULL WHERE LINK_ID = :LINK1 AND DATE_DEL IS NOT NULL;
    UPDATE LINKS SET DATE_DEL = NULL WHERE LINK_ID = :LINK2 AND DATE_DEL IS NOT NULL;
    UPDATE LINKS SET DATE_DEL = NULL WHERE LINK_ID = :LINK3 AND DATE_DEL IS NOT NULL;
  END

  SELECT BLOB_ID FROM VAL_ADD(2547, :LOAD_ID, :DURATION) INTO :BLOB_ID;
  SELECT BLOB_ID FROM VAL_ADD(385, :LOAD_ID, :LOAD_HOURS) INTO :BLOB_ID;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PLAN_IMPORT_STAGE (
    OBJ_ID BIGINT,
    STAGE_INDEX INTEGER,
    WEEK_LENGTH INTEGER,
    DURATION INTEGER,
    WEEK_LOAD INTEGER)
RETURNS (
    STAGE_ID BIGINT)
AS
declare variable STAGE_LV bigint;
declare variable LINK_ID bigint;
declare variable BLOB_ID bigint;
begin
  -- Идентифицируем этап обучения
  SELECT LISTVAL_ID
  FROM LISTVALS
  WHERE LIST_ID = 25 AND IS_DEL = 0 AND TAG = :STAGE_INDEX AND PARENT_ID = 2141
  INTO :STAGE_LV;

  IF(STAGE_LV IS NULL) THEN EXCEPTION DATA_ERROR 'Не удалось идентифицировать этап обучения';

  SELECT FIRST 1 L54.LINK_ID, L54.OBJ_ID
  FROM LINKS L54
  JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0 AND V381.LISTVAL_ID = :STAGE_LV
  WHERE L54.PARENT_ID = :OBJ_ID AND L54.OBJ_TYPE_ID = 54
  INTO :LINK_ID, :STAGE_ID;

  IF(LINK_ID IS NULL) THEN
  BEGIN
    SELECT OBJ_ID FROM OBJECT_ADD(:OBJ_ID, 54) INTO :STAGE_ID;
    SELECT BLOB_ID FROM VAL_ADD(381, :STAGE_ID, :STAGE_LV) INTO :BLOB_ID;
  END
  ELSE
  BEGIN
    -- Восстанавливаем старую связь
    UPDATE LINKS SET DATE_DEL = NULL WHERE LINK_ID = :LINK_ID AND DATE_DEL IS NOT NULL;
  END

  -- Учебная неделя
  IF(WEEK_LENGTH IS NOT NULL) THEN
  BEGIN
    SELECT BLOB_ID FROM VAL_ADD(2837, :STAGE_ID, IIF(:WEEK_LENGTH = 5, 11718, 11719)) INTO :BLOB_ID;
  END

  SELECT BLOB_ID FROM VAL_ADD(382, :STAGE_ID, :DURATION) INTO :BLOB_ID;

  IF(WEEK_LOAD IS NOT NULL) THEN
  BEGIN
    SELECT BLOB_ID FROM VAL_ADD(383, :STAGE_ID, :WEEK_LOAD) INTO :BLOB_ID;
  END

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PLAN_IMPORT_SUBJECT (
    OBJ_ID BIGINT,
    COMPONENT_INDEX BIGINT,
    SUBJECT_NAME VARCHAR(1000),
    MASTER_NAME VARCHAR(1000),
    IS_PROFILE INTEGER)
RETURNS (
    SUBJECT_ID BIGINT)
AS
declare variable CV1 bigint;
declare variable CV2 bigint;
declare variable COMPONENT_ID bigint;
declare variable LINK_ID bigint;
begin
  -- CV1 как по ФБУП-2004, CV2 как по ФГОС
  IF(COMPONENT_INDEX = 1) THEN CV1 = 780;
  ELSE IF(COMPONENT_INDEX = 2) THEN CV1 = 782;
  ELSE IF(COMPONENT_INDEX = 12752) THEN CV1 = 780;
  ELSE IF(COMPONENT_INDEX = 12753) THEN CV1 = 782;
  IF(CV1 = 780) THEN CV2 = 12752; ELSE CV2 = 12753;

  SELECT FIRST 1 L49.OBJ_ID
  FROM LINKS L49
  JOIN VALL V372 ON V372.OBJ_ID = L49.OBJ_ID AND V372.PARAM_ID = 372 AND V372.IS_DEL = 0 AND (V372.LISTVAL_ID = :CV1 OR V372.LISTVAL_ID = :CV2)
  WHERE L49.PARENT_ID = :OBJ_ID AND L49.OBJ_TYPE_ID = 49 AND L49.DATE_DEL IS NULL
  INTO :COMPONENT_ID;

  IF(COMPONENT_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не удалось найти один из компонентов учебного плана';

  -- Идентифицируем исходный предмет из общеобразовательных
  SELECT FIRST 1 L51.OBJ_ID
  FROM LINKS L51
  JOIN VALS V376 ON V376.OBJ_ID = L51.OBJ_ID AND V376.PARAM_ID = 376 AND V376.IS_DEL = 0 AND UPPER(V376.VAL) = UPPER(:SUBJECT_NAME)
  WHERE L51.PARENT_ID = 32771 AND L51.OBJ_TYPE_ID = 51 AND L51.DATE_DEL IS NULL
  INTO :SUBJECT_ID;

  IF(SUBJECT_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не удалось идентифицировать предмет "' || SUBJECT_NAME || '". Необходимо внести все предметы в справочник перед началом импорта.';

  SELECT FIRST 1 LINK_ID
  FROM LINKS
  WHERE PARENT_ID = :COMPONENT_ID AND OBJ_ID = :SUBJECT_ID
  ORDER BY DATE_MODIFY DESC
  INTO :LINK_ID;

  IF(LINK_ID IS NULL) THEN
  BEGIN
    -- Добавляем новую связь
    SELECT LINK_ID FROM OBJECT_ADD_LINK(:COMPONENT_ID, :SUBJECT_ID, 51) INTO :LINK_ID;
  END
  ELSE
  BEGIN
    -- Восстанавливаем старую связь
    UPDATE LINKS SET DATE_DEL = NULL WHERE LINK_ID = :LINK_ID AND DATE_DEL IS NOT NULL;
  END

  -- Если предмет профильный, создаем связь из УП
  IF(IS_PROFILE <> 0) THEN
  BEGIN
    LINK_ID = NULL;
    SELECT FIRST 1 LINK_ID
    FROM LINKS
    WHERE PARENT_ID = :OBJ_ID AND OBJ_ID = :SUBJECT_ID
    ORDER BY DATE_MODIFY DESC
    INTO :LINK_ID;

    IF(LINK_ID IS NULL) THEN
    BEGIN
      -- Добавляем новую связь
      SELECT LINK_ID FROM OBJECT_ADD_LINK(:OBJ_ID, :SUBJECT_ID, 51) INTO :LINK_ID;
    END
    ELSE
    BEGIN
      -- Восстанавливаем старую связь
      UPDATE LINKS SET DATE_DEL = NULL WHERE LINK_ID = :LINK_ID AND DATE_DEL IS NOT NULL;
    END
  END

  -- Если есть мастер-предмет, формируем запись замены
  IF(MASTER_NAME IS NOT NULL AND MASTER_NAME <> '') THEN
  BEGIN
  END

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PLAN_IMPORT_TITLE (
    OBJ_ID BIGINT,
    STD_NUM INTEGER,
    PROFILE_NAME VARCHAR(1000))
AS
declare variable BLOB_ID bigint;
declare variable CV1 bigint;
declare variable CV2 bigint;
declare variable COMP_ID bigint;
declare variable LINK_ID bigint;
begin

    -- Устанавливаем требуемый номер образовательного стандарта
    IF(STD_NUM = 1) THEN STD_NUM = 11721;
    ELSE IF(STD_NUM = 2) THEN STD_NUM = 11720;
    ELSE EXCEPTION DATA_ERROR 'Недопустимый номер образовательного стандарта';

    SELECT BLOB_ID FROM VAL_ADD(2478, :OBJ_ID, :STD_NUM) INTO :BLOB_ID;

    -- Воссоздаем структуру компонентов УП
    -- 1. Инвариантный компонент
    IF(STD_NUM = 11721) THEN
    BEGIN
      -- ФГОС
      CV1 = 12752;
      CV2 = 780;
    END
    ELSE
    BEGIN
      -- ФБУП-2004
      CV1 = 780;
      CV2 = 12752;
    END

    SELECT FIRST 1 L49.LINK_ID, L49.OBJ_ID
    FROM LINKS L49
    JOIN VALL V372 ON V372.OBJ_ID = L49.OBJ_ID AND V372.PARAM_ID = 372 AND V372.IS_DEL = 0 AND (V372.LISTVAL_ID = :CV1 OR V372.LISTVAL_ID = :CV2)
    WHERE L49.PARENT_ID = :OBJ_ID AND L49.OBJ_TYPE_ID = 49
    ORDER BY L49.DATE_MODIFY DESC
    INTO :LINK_ID, :COMP_ID;

    IF(LINK_ID IS NULL) THEN
    BEGIN
      -- Создаем новый этап
      SELECT OBJ_ID FROM OBJECT_ADD(:OBJ_ID, 49) INTO :COMP_ID;
    END
    ELSE
    BEGIN
      -- Восстанавливаем удаление
      UPDATE LINKS SET DATE_DEL = NULL WHERE LINK_ID = :LINK_ID AND DATE_DEL IS NOT NULL;
    END
    -- Правим LV
    SELECT BLOB_ID FROM VAL_ADD(372, :COMP_ID, :CV1) INTO :BLOB_ID;

    -- 2. Вариативный компонент
    IF(STD_NUM = 11721) THEN
    BEGIN
      -- ФГОС
      CV1 = 12753;
      CV2 = 782;
    END
    ELSE
    BEGIN
      -- ФБУП-2004
      CV1 = 782;
      CV2 = 12753;
    END

    SELECT FIRST 1 L49.LINK_ID, L49.OBJ_ID
    FROM LINKS L49
    JOIN VALL V372 ON V372.OBJ_ID = L49.OBJ_ID AND V372.PARAM_ID = 372 AND V372.IS_DEL = 0 AND (V372.LISTVAL_ID = :CV1 OR V372.LISTVAL_ID = :CV2)
    WHERE L49.PARENT_ID = :OBJ_ID AND L49.OBJ_TYPE_ID = 49
    ORDER BY L49.DATE_MODIFY DESC
    INTO :LINK_ID, :COMP_ID;

    IF(LINK_ID IS NULL) THEN
    BEGIN
      -- Создаем новый этап
      SELECT OBJ_ID FROM OBJECT_ADD(:OBJ_ID, 49) INTO :COMP_ID;
    END
    ELSE
    BEGIN
      -- Восстанавливаем удаление
      UPDATE LINKS SET DATE_DEL = NULL WHERE LINK_ID = :LINK_ID AND DATE_DEL IS NOT NULL;
    END
    -- Правим LV
    SELECT BLOB_ID FROM VAL_ADD(372, :COMP_ID, :CV1) INTO :BLOB_ID;

    -- Профиль - только если задан, уровень не проверяем
    IF(PROFILE_NAME IS NOT NULL AND PROFILE_NAME <> '') THEN
    BEGIN
      CV1 = NULL;

      SELECT LV.LISTVAL_ID
      FROM LISTVALS LV
      JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU' AND R.VAL = :PROFILE_NAME
      WHERE LV.LIST_ID = 272 AND LV.IS_DEL = 0
      INTO :CV1;

      IF(CV1 IS NULL) THEN EXCEPTION DATA_ERROR 'Не удалось найти профиль, соответствующий указанному в файле импорта';
      SELECT BLOB_ID FROM VAL_ADD(2166, :OBJ_ID, :CV1) INTO :BLOB_ID;
    END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PLAN_KIND_GET (
    I$OBJ_ID BIGINT,
    I$USER_ID BIGINT = null)
RETURNS (
    LISTVAL_ID BIGINT,
    PARENT_ID BIGINT,
    VAL VARCHAR(4000),
    VAL_LONG VARCHAR(4000),
    TAG VARCHAR(100),
    "FILTER" VARCHAR(255))
AS
declare variable V$LANG_CODE varchar(2);
declare variable V$KIND_OBJ integer;
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :V$LANG_CODE;

    SELECT PARENT_TYPE_ID
    FROM LINKS
    WHERE OBJ_ID = :I$OBJ_ID
    AND DATE_DEL IS NULL
    AND OBJ_TYPE_ID = 273
    INTO V$KIND_OBJ;

    
    IF (V$KIND_OBJ = 2) THEN
    BEGIN
        FOR
            SELECT LV.LISTVAL_ID,
                   LV.PARENT_ID,
                   R.VAL,
                   R.VAL_LONG,
                   LV.TAG
            FROM LISTVALS LV
    
            LEFT JOIN RES_GET(LV.RES_ID,  :V$LANG_CODE) R ON 1=1
    
            WHERE LV.LIST_ID = 277
            AND LV.PARENT_ID IS NULL
            AND IS_DEL = 0
            AND LV."FILTER" LIKE 'OU'
    
            ORDER BY SORT_ORDER
    
            INTO :LISTVAL_ID,
                 :PARENT_ID,
                 :VAL,
                 :VAL_LONG,
                 :TAG
        DO
        BEGIN
            SUSPEND;
        END
    END
    ELSE IF (V$KIND_OBJ = 111) THEN
    BEGIN
        FOR
            SELECT LV.LISTVAL_ID,
                   LV.PARENT_ID,
                   R.VAL,
                   R.VAL_LONG,
                   LV.TAG
            FROM LISTVALS LV
    
            LEFT JOIN RES_GET(LV.RES_ID,  :V$LANG_CODE) R ON 1=1
    
            WHERE LV.LIST_ID = 277
            AND LV.PARENT_ID IS NULL
            AND IS_DEL = 0
            AND LV."FILTER" LIKE 'DR'
    
            ORDER BY SORT_ORDER
    
            INTO :LISTVAL_ID,
                 :PARENT_ID,
                 :VAL,
                 :VAL_LONG,
                 :TAG
        DO
        BEGIN
            SUSPEND;
        END
    END
    ELSE IF (V$KIND_OBJ = 112) THEN
    BEGIN
        FOR
            SELECT LV.LISTVAL_ID,
                   LV.PARENT_ID,
                   R.VAL,
                   R.VAL_LONG,
                   LV.TAG
            FROM LISTVALS LV
    
            LEFT JOIN RES_GET(LV.RES_ID,  :V$LANG_CODE) R ON 1=1
    
            WHERE LV.LIST_ID = 277
            AND LV.PARENT_ID IS NULL
            AND IS_DEL = 0
            AND LV.LISTVAL_ID IN (11043, 11044, 11045)

            ORDER BY SORT_ORDER
    
            INTO :LISTVAL_ID,
                 :PARENT_ID,
                 :VAL,
                 :VAL_LONG,
                 :TAG
        DO
        BEGIN
            SUSPEND;
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PLAN_MM_GET (
    I$PLAN_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(4000))
AS
declare variable V$GROUP_ID bigint;
declare variable V$STAGE bigint;
declare variable V$IS_VD bigint;
declare variable V$PERSON_ID bigint;
declare variable V$YEAR_ID bigint;
declare variable V$SUBJECT_ID bigint;
declare variable V$SBG_ID bigint;
declare variable V$MD bigint;
declare variable V$H integer;
declare variable S varchar(1000);
declare variable S2 varchar(1000);
declare variable S3 varchar(400);
declare variable T integer;
begin

  -- Тип ВД
  SELECT I
  FROM VAL_GET(:I$PLAN_ID, 3022)
  INTO :V$IS_VD;
  TAG_NAME = 'is_vd';
  VAL = V$IS_VD;
  SUSPEND;

  SELECT FIRST 1 V1236.LISTVAL_ID
  FROM OBJECT_PARENTS_GET(:I$PLAN_ID, 2) P
  JOIN VALL V1236 ON V1236.OBJ_ID = P.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  INTO :V$YEAR_ID;

  IF(V$IS_VD = 3) THEN
  BEGIN
    -- Общеобразовательные УП

    TAG_NAME = 'students::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT L256.OBJ_ID, LV.COST, C.CAPTION
      FROM LINKS L54
      JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
      JOIN LISTVALS LV ON LV.LISTVAL_ID = V381.LISTVAL_ID
      JOIN LINKS L256 ON L256.PARENT_ID = L54.OBJ_ID AND L256.OBJ_TYPE_ID = 256 AND L256.DATE_DEL IS NULL
      LEFT JOIN OBJECT_CAPTION_GET(L256.OBJ_ID) C ON 1 = 1
      WHERE L54.PARENT_ID = :I$PLAN_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL AND POSITION('будущий ' IN C.CAPTION) <= 0
      ORDER BY LV.COST, 3
      INTO :V$GROUP_ID, :V$STAGE, :S
    DO
    BEGIN
      FOR
        SELECT L10.OBJ_ID, C.CAPTION
        FROM LINKS L10
        LEFT JOIN OBJECT_CAPTION_GET(L10.OBJ_ID, 23) C ON 1 = 1
        WHERE L10.PARENT_ID = :V$GROUP_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        ORDER BY 2
        INTO :V$PERSON_ID, :S2
      DO
      BEGIN
        TAG_NAME = 'students:r';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'students:r:id';
        VAL = V$PERSON_ID;
        SUSPEND;
        TAG_NAME = 'students:r:gup_id';
        VAL = V$GROUP_ID;
        SUSPEND;
        TAG_NAME = 'students:r:stage';
        VAL = V$STAGE;
        SUSPEND;
        TAG_NAME = 'students:r:name';
        VAL = S2;
        SUSPEND;
        TAG_NAME = 'students:r:gup_name';
        VAL = S;
        SUSPEND;
        TAG_NAME = 'students:r:modules';
        SELECT V FROM VAL_GET(:V$PERSON_ID, 2838) INTO :VAL;
        SUSPEND;
        TAG_NAME = 'students:r:groups';
        VAL = '';
        FOR
          SELECT DISTINCT M.GROUP_ID
          FROM PERSON_MOVEMENTS M
          JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.JOURNAL_TYPE = 0 AND J.YEAR_ID = :V$YEAR_ID AND J.GRADE_ID = M.GROUP_ID AND J.GRADE_TYPE_ID = 179
          WHERE M.DATE_DEL IS NULL AND M.DATE_OUT IS NULL AND M.PERSON_ID = :V$PERSON_ID
          INTO :V$SBG_ID
        DO
        BEGIN
          IF(VAL <> '') THEN VAL = VAL || ',';
          VAL = VAL || V$SBG_ID;
        END
        SUSPEND;
      END
    END

    -- Групповые предметы - либо предметы по выбору, либо курсовой предмет
    TAG_NAME = 'subjects::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT PS.OBJ_ID, PS.SUBJECT_ID, V3158.LISTVAL_ID, C.CAPTION, V377.SVAL, SUM(COALESCE(L.LOAD_HOURS_S1, 0) + COALESCE(L.LOAD_HOURS_S2, 0))
      FROM PLAN_SUBJECTS PS
      JOIN PLAN_SUBJECTS PSP ON PSP.OBJ_ID = PS.PARENT_ID
      JOIN PLAN_LOADS L ON L.DATE_DEL IS NULL AND L.SUBJECT_ID = PS.OBJ_ID AND (L.LOAD_HOURS_S1 > 0 OR L.LOAD_HOURS_S2 > 0)
      LEFT JOIN OBJECT_CAPTION_GET(PS.SUBJECT_ID) C ON 1 = 1
      LEFT JOIN VALL V3158 ON V3158.OBJ_ID = PS.SUBJECT_ID AND V3158.PARAM_ID = 3158 AND V3158.IS_DEL = 0
      LEFT JOIN VALS V377 ON V377.OBJ_ID = PS.SUBJECT_ID AND V377.PARAM_ID = 377 AND V377.IS_DEL = 0
      WHERE PS.PLAN_ID = :I$PLAN_ID AND PS.DATE_DEL IS NULL AND PS.ROW_TYPE = 10
        AND ((PSP.FIELD_ID = 12928 AND PS.SUBJECT_ID = 34607) OR V3158.LISTVAL_ID = 13462)
      GROUP BY 1, 2, 3, 4, 5
      HAVING COUNT(*) > 0
      ORDER BY 4
      INTO :V$GROUP_ID, :V$SUBJECT_ID, :V$MD, :S, :S2, :T
    DO
    BEGIN
      TAG_NAME = 'subjects:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'subjects:r:id';
      VAL = V$SUBJECT_ID;
      SUSPEND;
      TAG_NAME = 'subjects:r:name';
      VAL = S;
      SUSPEND;
      TAG_NAME = 'subjects:r:code';
      VAL = S2;
      SUSPEND;
      TAG_NAME = 'subjects:r:type';
      IF(V$SUBJECT_ID = 34607) THEN VAL = '0';
      --ELSE IF(V$MD = 13454) THEN VAL = '0';
      ELSE VAL = '1';
      SUSPEND;
      -- Какие этапы обучения предусмотрены для данного предмета
      TAG_NAME = 'subjects:r:stages';
      VAL = '';
      S2 = '';
      FOR
        SELECT LV.COST, SUM(COALESCE(L.LOAD_HOURS_S1, 0) + COALESCE(L.LOAD_HOURS_S2, 0))
        FROM PLAN_LOADS L
        JOIN VALL V381 ON V381.OBJ_ID = L.STAGE_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
        JOIN LISTVALS LV ON LV.LISTVAL_ID = V381.LISTVAL_ID
        WHERE L.DATE_DEL IS NULL AND L.SUBJECT_ID = :V$GROUP_ID AND (L.LOAD_HOURS_S1 > 0 OR L.LOAD_HOURS_S2 > 0)
        GROUP BY 1
        HAVING COUNT(*) > 0
        ORDER BY 1
        INTO :V$STAGE, :T
      DO
      BEGIN
        IF(VAL <> '') THEN VAL = VAL || ';';
        VAL = VAL || V$STAGE;
        IF(S2 <> '') THEN S2 = S2 || ';';
        S2 = S2 || T;
      END
      SUSPEND;
      TAG_NAME = 'subjects:r:hours';
      VAL = S2;
      SUSPEND;

      TAG_NAME = 'subjects:r:modules';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'subjects:r:modules::json&colon;array';
      VAL = 1;
      SUSPEND;
      IF(V$SUBJECT_ID = 34607) THEN
      BEGIN
        -- Ограничение может быть индивидуальное по предмету
        FOR
          SELECT PS2.SUBJECT_ID, C.CAPTION, V377.SVAL, SUM(COALESCE(L.LOAD_HOURS_S1, 0) + COALESCE(L.LOAD_HOURS_S2, 0))
          FROM PLAN_SUBJECTS PS
          JOIN PLAN_SUBJECTS PS2 ON PS2.DATE_DEL IS NULL AND PS2.PARENT_ID = PS.PARENT_ID AND PS2.SUBJECT_ID <> PS.SUBJECT_ID
          JOIN PLAN_LOADS L ON L.DATE_DEL IS NULL AND L.SUBJECT_ID = PS.OBJ_ID AND (L.LOAD_HOURS_S1 > 0 OR L.LOAD_HOURS_S2 > 0)
          LEFT JOIN OBJECT_CAPTION_GET(PS2.SUBJECT_ID) C ON 1 = 1
          LEFT JOIN VALS V377 ON V377.OBJ_ID = PS2.SUBJECT_ID AND V377.PARAM_ID = 377 AND V377.IS_DEL = 0
          WHERE PS.DATE_DEL IS NULL AND PS.SUBJECT_ID = 34607 AND PS.PLAN_ID = :I$PLAN_ID
          GROUP BY 1, 2, 3
          HAVING COUNT(*) > 0
          ORDER BY 3
          INTO :V$SBG_ID, :S, :S3, :T
        DO
        BEGIN
          TAG_NAME = 'subjects:r:modules:r';
          VAL = NULL;
          SUSPEND;
          TAG_NAME = 'subjects:r:modules:r:id';
          VAL = V$SBG_ID;
          SUSPEND;
          TAG_NAME = 'subjects:r:modules:r:name';
          VAL = S;
          SUSPEND;
          TAG_NAME = 'subjects:r:modules:r:code';
          VAL = S3;
          SUSPEND;
          TAG_NAME = 'subjects:r:modules:r:stages';
          VAL = '';
          S2 = '';
          FOR
            SELECT LV.COST, SUM(COALESCE(L.LOAD_HOURS_S1, 0) + COALESCE(L.LOAD_HOURS_S2, 0))
            FROM PLAN_SUBJECTS PS
            JOIN PLAN_LOADS L ON L.DATE_DEL IS NULL AND L.SUBJECT_ID = PS.OBJ_ID
            JOIN VALL V381 ON V381.OBJ_ID = L.STAGE_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
            JOIN LISTVALS LV ON LV.LISTVAL_ID = V381.LISTVAL_ID
            WHERE PS.DATE_DEL IS NULL AND PS.PLAN_ID = :I$PLAN_ID AND PS.SUBJECT_ID = :V$SBG_ID AND (L.LOAD_HOURS_S1 > 0 OR L.LOAD_HOURS_S2 > 0)
            GROUP BY 1
            HAVING COUNT(*) > 0
            ORDER BY 1
            INTO :V$STAGE, :T
          DO
          BEGIN
            IF(VAL <> '') THEN VAL = VAL || ';';
            VAL = VAL || V$STAGE;
            IF(S2 <> '') THEN S2 = S2 || ';';
            S2 = S2 || T;
          END
          SUSPEND;
          TAG_NAME = 'subjects:r:modules:r:hours';
          VAL = S2;
          SUSPEND;
          -- Группы по данному предмету
          TAG_NAME = 'subjects:r:modules:r:groups::json&colon;array';
          VAL = 1;
          SUSPEND;
          FOR
            SELECT J.GRADE_ID, J.STAGE_MASK, J.JOURNAL_NAME, J.HOURS
            FROM CJ2_JOURNAL J
            WHERE J.DATE_DEL IS NULL AND J.YEAR_ID = :V$YEAR_ID AND J.JOURNAL_TYPE = 0 AND J.GRADE_TYPE_ID = 179 AND J.SUBJECT_ID = :V$SBG_ID AND J.REF_ID = :I$PLAN_ID
            INTO :V$GROUP_ID, :V$STAGE, :S, :V$H
          DO
          BEGIN
            TAG_NAME = 'subjects:r:modules:r:groups:r';
            VAL = NULL;
            SUSPEND;
            TAG_NAME = 'subjects:r:modules:r:groups:r:id';
            VAL = V$GROUP_ID;
            SUSPEND;
            TAG_NAME = 'subjects:r:modules:r:groups:r:stagemask';
            VAL = V$STAGE;
            SUSPEND;
            TAG_NAME = 'subjects:r:modules:r:groups:r:name';
            VAL = S;
            SUSPEND;
            TAG_NAME = 'subjects:r:modules:r:groups:r:hours';
            VAL = V$H;
            SUSPEND;
          END
        END
      END
      ELSE
      BEGIN
        FOR
          SELECT V3159.OBJ_ID, C.CAPTION, V377.SVAL
          FROM LINKS L51
          JOIN VALR V3159 ON V3159.PARAM_ID = 3159 AND V3159.VAL = L51.OBJ_ID AND V3159.IS_DEL = 0
          JOIN VALL V3158 ON V3158.OBJ_ID = V3159.OBJ_ID AND V3158.PARAM_ID = 3158 AND V3158.IS_DEL = 0 AND V3158.LISTVAL_ID IN (13456, 13457)
          LEFT JOIN OBJECT_CAPTION_GET(V3159.OBJ_ID) C ON 1 = 1
          LEFT JOIN VALS V377 ON V377.OBJ_ID = V3159.OBJ_ID AND V377.PARAM_ID = 377 AND V377.IS_DEL = 0
          WHERE L51.OBJ_ID = :V$SUBJECT_ID AND L51.PARENT_TYPE_ID = 301 AND L51.DATE_DEL IS NULL
          ORDER BY 2
          INTO :V$SBG_ID, :S, :S3
        DO
        BEGIN
          TAG_NAME = 'subjects:r:modules:r';
          VAL = NULL;
          SUSPEND;
          TAG_NAME = 'subjects:r:modules:r:id';
          VAL = V$SBG_ID;
          SUSPEND;
          TAG_NAME = 'subjects:r:modules:r:name';
          VAL = S;
          SUSPEND;
          TAG_NAME = 'subjects:r:modules:r:code';
          VAL = S3;
          SUSPEND;
          -- Группы по данному предмету
          TAG_NAME = 'subjects:r:modules:r:groups::json&colon;array';
          VAL = 1;
          SUSPEND;
          FOR
            SELECT J.GRADE_ID, J.STAGE_MASK, J.JOURNAL_NAME, J.HOURS
            FROM CJ2_JOURNAL J
            WHERE J.DATE_DEL IS NULL AND J.YEAR_ID = :V$YEAR_ID AND J.JOURNAL_TYPE = 0 AND J.GRADE_TYPE_ID = 179 AND J.SUBJECT_ID = :V$SBG_ID AND J.REF_ID = :I$PLAN_ID
            INTO :V$GROUP_ID, :V$STAGE, :S, :V$H
          DO
          BEGIN
            TAG_NAME = 'subjects:r:modules:r:groups:r';
            VAL = NULL;
            SUSPEND;
            TAG_NAME = 'subjects:r:modules:r:groups:r:id';
            VAL = V$GROUP_ID;
            SUSPEND;
            TAG_NAME = 'subjects:r:modules:r:groups:r:stagemask';
            VAL = V$STAGE;
            SUSPEND;
            TAG_NAME = 'subjects:r:modules:r:groups:r:name';
            VAL = S;
            SUSPEND;
            TAG_NAME = 'subjects:r:modules:r:groups:r:hours';
            VAL = V$H;
            SUSPEND;
          END
        END
      END
    END
  END
  ELSE IF(V$IS_VD = 2) THEN
  BEGIN
    -- Внеурочка

    -- Тащим всех студентов в рампах данной ОП
    TAG_NAME = 'students::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT L256.OBJ_ID, LV.COST, C.CAPTION
      FROM LINKS LP57
      JOIN LINKS L400 ON L400.PARENT_ID = LP57.PARENT_ID AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL
      -- общеобразовательные УП
      JOIN VALL V3022 ON V3022.OBJ_ID = L400.OBJ_ID AND V3022.PARAM_ID = 3022 AND V3022.IS_DEL = 0 AND V3022.LISTVAL_ID = 3
      JOIN LINKS L54 ON L54.PARENT_ID = L400.OBJ_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
      JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
      JOIN LISTVALS LV ON LV.LISTVAL_ID = V381.LISTVAL_ID
      JOIN LINKS L256 ON L256.PARENT_ID = L54.OBJ_ID AND L256.OBJ_TYPE_ID = 256 AND L256.DATE_DEL IS NULL
      LEFT JOIN OBJECT_CAPTION_GET(L256.OBJ_ID) C ON 1 = 1
      WHERE LP57.OBJ_ID = :I$PLAN_ID AND LP57.PARENT_TYPE_ID = 57 AND LP57.DATE_DEL IS NULL AND POSITION('будущий ' IN C.CAPTION) <= 0
      ORDER BY LV.COST, 3
      INTO :V$GROUP_ID, :V$STAGE, :S
    DO
    BEGIN
      FOR
        SELECT L10.OBJ_ID, C.CAPTION
        FROM LINKS L10
        LEFT JOIN OBJECT_CAPTION_GET(L10.OBJ_ID, 23) C ON 1 = 1
        WHERE L10.PARENT_ID = :V$GROUP_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        ORDER BY 2
        INTO :V$PERSON_ID, :S2
      DO
      BEGIN
        TAG_NAME = 'students:r';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'students:r:id';
        VAL = V$PERSON_ID;
        SUSPEND;
        TAG_NAME = 'students:r:gup_id';
        VAL = V$GROUP_ID;
        SUSPEND;
        TAG_NAME = 'students:r:stage';
        VAL = V$STAGE;
        SUSPEND;
        TAG_NAME = 'students:r:name';
        VAL = S2;
        SUSPEND;
        TAG_NAME = 'students:r:gup_name';
        VAL = S;
        SUSPEND;
        TAG_NAME = 'students:r:modules';
        SELECT V FROM VAL_GET(:V$PERSON_ID, 3466) INTO :VAL;
        SUSPEND;
        TAG_NAME = 'students:r:groups';
        VAL = '';
        FOR
          SELECT DISTINCT M.GROUP_ID
          FROM PERSON_MOVEMENTS M
          JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.JOURNAL_TYPE = 1 AND J.YEAR_ID = :V$YEAR_ID AND J.GRADE_ID = M.GROUP_ID AND J.GRADE_TYPE_ID = 179
          WHERE M.DATE_DEL IS NULL AND M.DATE_OUT IS NULL AND M.PERSON_ID = :V$PERSON_ID
          INTO :V$SBG_ID
        DO
        BEGIN
          IF(VAL <> '') THEN VAL = VAL || ',';
          VAL = VAL || V$SBG_ID;
        END
        SUSPEND;
      END
    END

    -- Групповые предметы - тут вообще все
    TAG_NAME = 'subjects::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT PS.OBJ_ID, PS.SUBJECT_ID, V3377.LISTVAL_ID, C.CAPTION, V377.SVAL, SUM(COALESCE(L.LOAD_HOURS_S1, 0) + COALESCE(L.LOAD_HOURS_S2, 0))
      FROM PLAN_SUBJECTS PS
      JOIN PLAN_SUBJECTS PSP ON PSP.OBJ_ID = PS.PARENT_ID
      JOIN PLAN_LOADS L ON L.DATE_DEL IS NULL AND L.SUBJECT_ID = PS.OBJ_ID AND (L.LOAD_HOURS_S1 > 0 OR L.LOAD_HOURS_S2 > 0)
      LEFT JOIN OBJECT_CAPTION_GET(PS.SUBJECT_ID) C ON 1 = 1
      LEFT JOIN VALL V3377 ON V3377.OBJ_ID = PS.SUBJECT_ID AND V3377.PARAM_ID = 3377 AND V3377.IS_DEL = 0
      LEFT JOIN VALS V377 ON V377.OBJ_ID = PS.SUBJECT_ID AND V377.PARAM_ID = 377 AND V377.IS_DEL = 0
      WHERE PS.PLAN_ID = :I$PLAN_ID AND PS.DATE_DEL IS NULL AND PS.ROW_TYPE = 10
      GROUP BY 1, 2, 3, 4, 5
      HAVING COUNT(*) > 0
      ORDER BY 4
      INTO :V$GROUP_ID, :V$SUBJECT_ID, :V$MD, :S, :S2, :T
    DO
    BEGIN
      TAG_NAME = 'subjects:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'subjects:r:id';
      VAL = V$SUBJECT_ID;
      SUSPEND;
      TAG_NAME = 'subjects:r:name';
      VAL = S;
      SUSPEND;
      TAG_NAME = 'subjects:r:code';
      VAL = S2;
      SUSPEND;
      -- Тут другое деление по типам - в обычных 0/1, тут 2/3 (2 = обязательный, 3 = необязательный)
      TAG_NAME = 'subjects:r:type';
      IF(V$MD = 2) THEN VAL = '2';
      ELSE VAL = '3';
      SUSPEND;
      -- Какие этапы обучения предусмотрены для данного предмета
      TAG_NAME = 'subjects:r:stages';
      VAL = '';
      S2 = '';
      FOR
        SELECT LV.COST, SUM(COALESCE(L.LOAD_HOURS_S1, 0) + COALESCE(L.LOAD_HOURS_S2, 0))
        FROM PLAN_LOADS L
        JOIN VALL V381 ON V381.OBJ_ID = L.STAGE_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
        JOIN LISTVALS LV ON LV.LISTVAL_ID = V381.LISTVAL_ID
        WHERE L.DATE_DEL IS NULL AND L.SUBJECT_ID = :V$GROUP_ID AND (L.LOAD_HOURS_S1 > 0 OR L.LOAD_HOURS_S2 > 0)
        GROUP BY 1
        HAVING COUNT(*) > 0
        ORDER BY 1
        INTO :V$STAGE, :T
      DO
      BEGIN
        IF(VAL <> '') THEN VAL = VAL || ';';
        VAL = VAL || V$STAGE;
        IF(S2 <> '') THEN S2 = S2 || ';';
        S2 = S2 || T;
      END
      SUSPEND;
      TAG_NAME = 'subjects:r:hours';
      VAL = S2;
      SUSPEND;

      -- Группы по данному предмету
      TAG_NAME = 'subjects:r:groups::json&colon;array';
      VAL = 1;
      SUSPEND;
      FOR
        SELECT J.GRADE_ID, J.STAGE_MASK, J.JOURNAL_NAME, J.HOURS
        FROM CJ2_JOURNAL J
        WHERE J.DATE_DEL IS NULL AND J.YEAR_ID = :V$YEAR_ID AND J.JOURNAL_TYPE = 1 AND J.GRADE_TYPE_ID = 179 AND J.SUBJECT_ID = :V$SUBJECT_ID AND J.REF_ID = :I$PLAN_ID
        INTO :V$GROUP_ID, :V$STAGE, :S, :V$H
      DO
      BEGIN
        TAG_NAME = 'subjects:r:groups:r';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'subjects:r:groups:r:id';
        VAL = V$GROUP_ID;
        SUSPEND;
        TAG_NAME = 'subjects:r:groups:r:stagemask';
        VAL = V$STAGE;
        SUSPEND;
        TAG_NAME = 'subjects:r:groups:r:name';
        VAL = S;
        SUSPEND;
        TAG_NAME = 'subjects:r:groups:r:hours';
        VAL = V$H;
        SUSPEND;
      END
    END

  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PLAN_ODOD_DATA_GET RETURNS (
    P1 INTEGER,
    P2 INTEGER,
    P3 INTEGER,
    P4 INTEGER,
    P5 INTEGER,
    P6 INTEGER,
    P7 INTEGER,
    UYEAR VARCHAR(100),
    NYEAR INTEGER)
AS
declare variable V$OBJ_ID bigint;
BEGIN
    FOR
        SELECT L.OBJ_ID FROM LINKS L
    
        JOIN VALI V2308
        ON V2308.PARAM_ID = 2308
        AND V2308.OBJ_ID = L.OBJ_ID
        AND V2308.IS_DEL = 0
        AND V2308.VAL = 0
        
        WHERE L.OBJ_TYPE_ID = 282
        AND L.DATE_DEL IS NULL
        AND L.PARENT_TYPE_ID = 2
        INTO :V$OBJ_ID
    DO
    BEGIN
        P1 = NULL;
        P2 = NULL;
        P3 = NULL;
        P4 = NULL;
        P5 = NULL;
        P6 = NULL;
        P7 = NULL;

        NYEAR = 0;

        SELECT V.V
        FROM VAL_GET(:V$OBJ_ID, 2298) V
        INTO :UYEAR;

        SELECT V.V
        FROM VAL_GET(:V$OBJ_ID, 2300) V
        INTO :P1;

        SELECT V.V
        FROM VAL_GET(:V$OBJ_ID, 2301) V
        INTO :P2;

        SELECT V.V
        FROM VAL_GET(:V$OBJ_ID, 2302) V
        INTO :P3;

        SELECT V.V
        FROM VAL_GET(:V$OBJ_ID, 2303) V
        INTO :P4;

        SELECT V.V
        FROM VAL_GET(:V$OBJ_ID, 2304) V
        INTO :P5;

        SELECT V.V
        FROM VAL_GET(:V$OBJ_ID, 2305) V
        INTO :P6;

        SELECT V.V
        FROM VAL_GET(:V$OBJ_ID, 2306) V
        INTO :P7;

        SUSPEND;
    END

    FOR
        SELECT L.OBJ_ID, V2286.VAL FROM LINKS L

        JOIN VALI V2286
        ON V2286.PARAM_ID = 2328
        AND V2286.OBJ_ID = L.OBJ_ID
        AND V2286.IS_DEL = 0
        
        WHERE L.OBJ_TYPE_ID = 283
        AND L.DATE_DEL IS NULL
        AND L.PARENT_TYPE_ID = 2
        
        ORDER BY V2286.VAL
        INTO :V$OBJ_ID, :NYEAR
    DO
    BEGIN
        P1 = NULL;
        P2 = NULL;
        P3 = NULL;
        P4 = NULL;
        P5 = NULL;
        P6 = NULL;
        P7 = NULL;

        SELECT V.V
        FROM VAL_GET(:V$OBJ_ID, 2309) V
        INTO :UYEAR;

        SELECT V.VAL
        FROM VALI V
        WHERE V.PARAM_ID = 2310
        AND V.IS_DEL = 0
        AND V.OBJ_ID = :V$OBJ_ID
        INTO :P1;

        SELECT V.VAL
        FROM VALI V
        WHERE V.PARAM_ID = 2311
        AND V.IS_DEL = 0
        AND V.OBJ_ID = :V$OBJ_ID
        INTO :P2;

        SELECT V.VAL
        FROM VALI V
        WHERE V.PARAM_ID = 2312
        AND V.IS_DEL = 0
        AND V.OBJ_ID = :V$OBJ_ID
        INTO :P3;

        SELECT V.VAL
        FROM VALI V
        WHERE V.PARAM_ID = 2313
        AND V.IS_DEL = 0
        AND V.OBJ_ID = :V$OBJ_ID
        INTO :P4;

        SELECT V.VAL
        FROM VALI V
        WHERE V.PARAM_ID = 2314
        AND V.IS_DEL = 0
        AND V.OBJ_ID = :V$OBJ_ID
        INTO :P5;

        SELECT V.VAL
        FROM VALI V
        WHERE V.PARAM_ID = 2315
        AND V.IS_DEL = 0
        AND V.OBJ_ID = :V$OBJ_ID
        INTO :P6;

        SELECT V.VAL
        FROM VALI V
        WHERE V.PARAM_ID = 2316
        AND V.IS_DEL = 0
        AND V.OBJ_ID = :V$OBJ_ID
        INTO :P7;

        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PLAN_ODOD_DATA_SET (
    I$P1 INTEGER,
    I$P2 INTEGER,
    I$P3 INTEGER,
    I$P4 INTEGER,
    I$P5 INTEGER,
    I$P6 INTEGER,
    I$P7 INTEGER,
    I$NYEAR INTEGER)
AS
declare variable V$OBJ_ID bigint;
declare variable V$BLOB_ID bigint;
BEGIN
    SELECT L.OBJ_ID FROM LINKS L
    
    JOIN VALI V2328
    ON V2328.PARAM_ID = 2328
    AND V2328.OBJ_ID = L.OBJ_ID
    AND V2328.IS_DEL = 0
    AND V2328.VAL = :I$NYEAR
    
    WHERE L.OBJ_TYPE_ID = 283
    AND L.DATE_DEL IS NULL
    AND L.PARENT_TYPE_ID = 2
    
    ORDER BY V2328.VAL
    INTO :V$OBJ_ID;

    IF (V$OBJ_ID IS NOT NULL) THEN
    BEGIN
        SELECT BLOB_ID FROM VAL_ADD(2310,:V$OBJ_ID, 0, NULL, 1) INTO :V$BLOB_ID;
        IF (:I$P1 IS NOT NULL) THEN
        BEGIN
            SELECT BLOB_ID FROM VAL_ADD(2310,:V$OBJ_ID,:I$P1) INTO :V$BLOB_ID;
        END

        SELECT BLOB_ID FROM VAL_ADD(2311,:V$OBJ_ID, 0, NULL, 1) INTO :V$BLOB_ID;
        IF (:I$P2 IS NOT NULL) THEN
        BEGIN
            SELECT BLOB_ID FROM VAL_ADD(2311,:V$OBJ_ID,:I$P2) INTO :V$BLOB_ID;
        END

        SELECT BLOB_ID FROM VAL_ADD(2312,:V$OBJ_ID, 0, NULL, 1) INTO :V$BLOB_ID;
        IF (:I$P3 IS NOT NULL) THEN
        BEGIN
            SELECT BLOB_ID FROM VAL_ADD(2312,:V$OBJ_ID,:I$P3) INTO :V$BLOB_ID;
        END

        SELECT BLOB_ID FROM VAL_ADD(2313,:V$OBJ_ID, 0, NULL, 1) INTO :V$BLOB_ID;
        IF (:I$P4 IS NOT NULL) THEN
        BEGIN
            SELECT BLOB_ID FROM VAL_ADD(2313,:V$OBJ_ID,:I$P4) INTO :V$BLOB_ID;
        END

        SELECT BLOB_ID FROM VAL_ADD(2314,:V$OBJ_ID, 0, NULL, 1) INTO :V$BLOB_ID;
        IF (:I$P5 IS NOT NULL) THEN
        BEGIN
            SELECT BLOB_ID FROM VAL_ADD(2314,:V$OBJ_ID,:I$P5) INTO :V$BLOB_ID;
        END

        SELECT BLOB_ID FROM VAL_ADD(2315,:V$OBJ_ID, 0, NULL, 1) INTO :V$BLOB_ID;
        IF (:I$P6 IS NOT NULL) THEN
        BEGIN
            SELECT BLOB_ID FROM VAL_ADD(2315,:V$OBJ_ID,:I$P6) INTO :V$BLOB_ID;
        END

        SELECT BLOB_ID FROM VAL_ADD(2316,:V$OBJ_ID, 0, NULL, 1) INTO :V$BLOB_ID;
        IF (:I$P7 IS NOT NULL) THEN
        BEGIN
            SELECT BLOB_ID FROM VAL_ADD(2316,:V$OBJ_ID,:I$P7) INTO :V$BLOB_ID;
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PLAN_OO_GET (
    I$OBJ_ID BIGINT,
    I$USER_ID BIGINT = null)
RETURNS (
    LISTVAL_ID BIGINT,
    PARENT_ID BIGINT,
    VAL VARCHAR(4000),
    VAL_LONG VARCHAR(4000),
    TAG VARCHAR(100),
    "FILTER" VARCHAR(255))
AS
declare variable V$LANG_CODE varchar(2);
declare variable V$KIND_OBJ integer;
declare variable V$OBJ_ID bigint;
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :V$LANG_CODE;

    SELECT PARENT_TYPE_ID, PARENT_ID
    FROM LINKS
    WHERE OBJ_ID = :I$OBJ_ID
    AND DATE_DEL IS NULL
    AND OBJ_TYPE_ID = 273
    INTO V$KIND_OBJ, :V$OBJ_ID;

    IF (V$KIND_OBJ = 111) THEN
    BEGIN
        FOR
            SELECT
            0 LISTVAL_ID,
            NULL PARENT_ID,
            V2.VAL,
            NULL VAL_LONG,
            NULL TAG
            FROM LINKS L
            
            JOIN VALS V2
            ON V2.PARAM_ID = 2
            AND V2.IS_DEL = 0
            AND V2.OBJ_ID = L.OBJ_ID
            
            WHERE L.OBJ_TYPE_ID = 2
            AND L.DATE_DEL IS NULL
            AND L.PARENT_TYPE_ID = 111
            AND L.PARENT_ID = :V$OBJ_ID

            INTO :LISTVAL_ID,
                 :PARENT_ID,
                 :VAL,
                 :VAL_LONG,
                 :TAG
        DO
        BEGIN
            SUSPEND;
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PLAN_PERIOD_GET (
    I$USER_ID BIGINT = null)
RETURNS (
    LISTVAL_ID BIGINT,
    PARENT_ID BIGINT,
    VAL VARCHAR(4000),
    VAL_LONG VARCHAR(4000),
    TAG VARCHAR(100),
    "FILTER" VARCHAR(255))
AS
declare variable V$RES_ID bigint;
declare variable V$LANG_CODE varchar(2);
declare variable V$I integer;
declare variable V$DATE date;
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :V$LANG_CODE;


    V$I = EXTRACT(YEAR FROM CURRENT_DATE);
    V$DATE = '1.09.' || V$I;
    
    IF (CURRENT_DATE < V$DATE) THEN
    BEGIN
        V$I = V$I;
    END
    ELSE
    BEGIN
        V$I = V$I + 1;
    END

    FOR
        SELECT LV.LISTVAL_ID,
               LV.PARENT_ID,
               R.VAL,
               R.VAL_LONG,
               LV.TAG
        FROM LISTVALS LV

        LEFT JOIN RES_GET(LV.RES_ID,  :V$LANG_CODE) R ON 1=1

        WHERE LV.LIST_ID = 29
        AND LV.PARENT_ID IS NULL
        AND IS_DEL = 0
        AND R.VAL_LONG BETWEEN (:V$I + 1) AND (:V$I + 3)

        ORDER BY SORT_ORDER

        INTO :LISTVAL_ID,
             :PARENT_ID,
             :VAL,
             :VAL_LONG,
             :TAG
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PLAN_PROFILE_ADD
AS
declare variable V$OU_ID bigint;
declare variable V$OBJ_ID bigint;
declare variable V$BLOB_ID bigint;
BEGIN
    SELECT DISTINCT OBJ_ID FROM LINKS
    WHERE OBJ_TYPE_ID = 2
    AND DATE_DEL IS NULL
    INTO :V$OU_ID;

    IF ( V$OU_ID IS NOT NULL ) THEN
    BEGIN
        V$OBJ_ID = NULL;
        SELECT L.OBJ_ID
        FROM LINKS L
        
        JOIN VALI V2284
        ON V2284.PARAM_ID = 2299
        AND V2284.IS_DEL = 0
        AND V2284.OBJ_ID = L.OBJ_ID
        AND V2284.VAL = 0
        
        JOIN VALL V2290
        ON V2290.PARAM_ID = 2290
        AND V2290.IS_DEL = 0
        AND V2290.OBJ_ID = L.OBJ_ID
        AND V2290.LISTVAL_ID = 46

        WHERE L.OBJ_TYPE_ID = 279
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :V$OU_ID
        INTO :V$OBJ_ID;

        IF (V$OBJ_ID IS NULL) THEN
        BEGIN
            SELECT OBJ_ID FROM OBJECT_ADD(:V$OU_ID, 279) INTO :V$OBJ_ID;
            SELECT BLOB_ID FROM VAL_ADD(2299, :V$OBJ_ID, 0) INTO :V$BLOB_ID;
            SELECT BLOB_ID FROM VAL_ADD(2290, :V$OBJ_ID, 46) INTO :V$BLOB_ID;
        END

        V$OBJ_ID = NULL;
        SELECT L.OBJ_ID
        FROM LINKS L
        
        JOIN VALI V2284
        ON V2284.PARAM_ID = 2299
        AND V2284.IS_DEL = 0
        AND V2284.OBJ_ID = L.OBJ_ID
        AND V2284.VAL = 0
        
        JOIN VALL V2290
        ON V2290.PARAM_ID = 2290
        AND V2290.IS_DEL = 0
        AND V2290.OBJ_ID = L.OBJ_ID
        AND V2290.LISTVAL_ID = 47

        WHERE L.OBJ_TYPE_ID = 279
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :V$OU_ID
        INTO :V$OBJ_ID;

        IF (V$OBJ_ID IS NULL) THEN
        BEGIN
            SELECT OBJ_ID FROM OBJECT_ADD(:V$OU_ID, 279) INTO :V$OBJ_ID;
            SELECT BLOB_ID FROM VAL_ADD(2299, :V$OBJ_ID, 0) INTO :V$BLOB_ID;
            SELECT BLOB_ID FROM VAL_ADD(2290, :V$OBJ_ID, 47) INTO :V$BLOB_ID;
        END


        V$OBJ_ID = NULL;
        SELECT L.OBJ_ID
        FROM LINKS L
        
        JOIN VALI V2284
        ON V2284.PARAM_ID = 2299
        AND V2284.IS_DEL = 0
        AND V2284.OBJ_ID = L.OBJ_ID
        AND V2284.VAL = 1
        
        JOIN VALL V2290
        ON V2290.PARAM_ID = 2290
        AND V2290.IS_DEL = 0
        AND V2290.OBJ_ID = L.OBJ_ID
        AND V2290.LISTVAL_ID = 46

        WHERE L.OBJ_TYPE_ID = 279
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :V$OU_ID
        INTO :V$OBJ_ID;

        IF (V$OBJ_ID IS NULL) THEN
        BEGIN
            SELECT OBJ_ID FROM OBJECT_ADD(:V$OU_ID, 279) INTO :V$OBJ_ID;
            SELECT BLOB_ID FROM VAL_ADD(2299, :V$OBJ_ID, 1) INTO :V$BLOB_ID;
            SELECT BLOB_ID FROM VAL_ADD(2290, :V$OBJ_ID, 46) INTO :V$BLOB_ID;
        END

        V$OBJ_ID = NULL;
        SELECT L.OBJ_ID
        FROM LINKS L
        
        JOIN VALI V2284
        ON V2284.PARAM_ID = 2299
        AND V2284.IS_DEL = 0
        AND V2284.OBJ_ID = L.OBJ_ID
        AND V2284.VAL = 1
        
        JOIN VALL V2290
        ON V2290.PARAM_ID = 2290
        AND V2290.IS_DEL = 0
        AND V2290.OBJ_ID = L.OBJ_ID
        AND V2290.LISTVAL_ID = 47

        WHERE L.OBJ_TYPE_ID = 279
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :V$OU_ID
        INTO :V$OBJ_ID;

        IF (V$OBJ_ID IS NULL) THEN
        BEGIN
            SELECT OBJ_ID FROM OBJECT_ADD(:V$OU_ID, 279) INTO :V$OBJ_ID;
            SELECT BLOB_ID FROM VAL_ADD(2299, :V$OBJ_ID, 1) INTO :V$BLOB_ID;
            SELECT BLOB_ID FROM VAL_ADD(2290, :V$OBJ_ID, 47) INTO :V$BLOB_ID;
        END


        V$OBJ_ID = NULL;
        SELECT L.OBJ_ID
        FROM LINKS L
        
        JOIN VALI V2284
        ON V2284.PARAM_ID = 2299
        AND V2284.IS_DEL = 0
        AND V2284.OBJ_ID = L.OBJ_ID
        AND V2284.VAL = 2
        
        JOIN VALL V2290
        ON V2290.PARAM_ID = 2290
        AND V2290.IS_DEL = 0
        AND V2290.OBJ_ID = L.OBJ_ID
        AND V2290.LISTVAL_ID = 46

        WHERE L.OBJ_TYPE_ID = 279
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :V$OU_ID
        INTO :V$OBJ_ID;

        IF (V$OBJ_ID IS NULL) THEN
        BEGIN
            SELECT OBJ_ID FROM OBJECT_ADD(:V$OU_ID, 279) INTO :V$OBJ_ID;
            SELECT BLOB_ID FROM VAL_ADD(2299, :V$OBJ_ID, 2) INTO :V$BLOB_ID;
            SELECT BLOB_ID FROM VAL_ADD(2290, :V$OBJ_ID, 46) INTO :V$BLOB_ID;
        END

        V$OBJ_ID = NULL;
        SELECT L.OBJ_ID
        FROM LINKS L
        
        JOIN VALI V2284
        ON V2284.PARAM_ID = 2299
        AND V2284.IS_DEL = 0
        AND V2284.OBJ_ID = L.OBJ_ID
        AND V2284.VAL = 2
        
        JOIN VALL V2290
        ON V2290.PARAM_ID = 2290
        AND V2290.IS_DEL = 0
        AND V2290.OBJ_ID = L.OBJ_ID
        AND V2290.LISTVAL_ID = 47

        WHERE L.OBJ_TYPE_ID = 279
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :V$OU_ID
        INTO :V$OBJ_ID;

        IF (V$OBJ_ID IS NULL) THEN
        BEGIN
            SELECT OBJ_ID FROM OBJECT_ADD(:V$OU_ID, 279) INTO :V$OBJ_ID;
            SELECT BLOB_ID FROM VAL_ADD(2299, :V$OBJ_ID, 2) INTO :V$BLOB_ID;
            SELECT BLOB_ID FROM VAL_ADD(2290, :V$OBJ_ID, 47) INTO :V$BLOB_ID;
        END


        V$OBJ_ID = NULL;
        SELECT L.OBJ_ID
        FROM LINKS L
        
        JOIN VALI V2284
        ON V2284.PARAM_ID = 2299
        AND V2284.IS_DEL = 0
        AND V2284.OBJ_ID = L.OBJ_ID
        AND V2284.VAL = 3
        
        JOIN VALL V2290
        ON V2290.PARAM_ID = 2290
        AND V2290.IS_DEL = 0
        AND V2290.OBJ_ID = L.OBJ_ID
        AND V2290.LISTVAL_ID = 46

        WHERE L.OBJ_TYPE_ID = 279
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :V$OU_ID
        INTO :V$OBJ_ID;

        IF (V$OBJ_ID IS NULL) THEN
        BEGIN
            SELECT OBJ_ID FROM OBJECT_ADD(:V$OU_ID, 279) INTO :V$OBJ_ID;
            SELECT BLOB_ID FROM VAL_ADD(2299, :V$OBJ_ID, 3) INTO :V$BLOB_ID;
            SELECT BLOB_ID FROM VAL_ADD(2290, :V$OBJ_ID, 46) INTO :V$BLOB_ID;
        END

        V$OBJ_ID = NULL;
        SELECT L.OBJ_ID
        FROM LINKS L
        
        JOIN VALI V2284
        ON V2284.PARAM_ID = 2299
        AND V2284.IS_DEL = 0
        AND V2284.OBJ_ID = L.OBJ_ID
        AND V2284.VAL = 3
        
        JOIN VALL V2290
        ON V2290.PARAM_ID = 2290
        AND V2290.IS_DEL = 0
        AND V2290.OBJ_ID = L.OBJ_ID
        AND V2290.LISTVAL_ID = 47

        WHERE L.OBJ_TYPE_ID = 279
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :V$OU_ID
        INTO :V$OBJ_ID;

        IF (V$OBJ_ID IS NULL) THEN
        BEGIN
            SELECT OBJ_ID FROM OBJECT_ADD(:V$OU_ID, 279) INTO :V$OBJ_ID;
            SELECT BLOB_ID FROM VAL_ADD(2299, :V$OBJ_ID, 3) INTO :V$BLOB_ID;
            SELECT BLOB_ID FROM VAL_ADD(2290, :V$OBJ_ID, 47) INTO :V$BLOB_ID;
        END





        V$OBJ_ID = NULL;
        SELECT L.OBJ_ID
        FROM LINKS L
        
        JOIN VALI V2284
        ON V2284.PARAM_ID = 2327
        AND V2284.IS_DEL = 0
        AND V2284.OBJ_ID = L.OBJ_ID
        AND V2284.VAL = 0
        
        JOIN VALL V2290
        ON V2290.PARAM_ID = 2319
        AND V2290.IS_DEL = 0
        AND V2290.OBJ_ID = L.OBJ_ID
        AND V2290.LISTVAL_ID = 46

        WHERE L.OBJ_TYPE_ID = 281
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :V$OU_ID
        INTO :V$OBJ_ID;

        IF (V$OBJ_ID IS NULL) THEN
        BEGIN
            SELECT OBJ_ID FROM OBJECT_ADD(:V$OU_ID, 281) INTO :V$OBJ_ID;
            SELECT BLOB_ID FROM VAL_ADD(2327, :V$OBJ_ID, 0) INTO :V$BLOB_ID;
            SELECT BLOB_ID FROM VAL_ADD(2319, :V$OBJ_ID, 46) INTO :V$BLOB_ID;
        END

        V$OBJ_ID = NULL;
        SELECT L.OBJ_ID
        FROM LINKS L
        
        JOIN VALI V2284
        ON V2284.PARAM_ID = 2327
        AND V2284.IS_DEL = 0
        AND V2284.OBJ_ID = L.OBJ_ID
        AND V2284.VAL = 0
        
        JOIN VALL V2290
        ON V2290.PARAM_ID = 2319
        AND V2290.IS_DEL = 0
        AND V2290.OBJ_ID = L.OBJ_ID
        AND V2290.LISTVAL_ID = 47

        WHERE L.OBJ_TYPE_ID = 281
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :V$OU_ID
        INTO :V$OBJ_ID;

        IF (V$OBJ_ID IS NULL) THEN
        BEGIN
            SELECT OBJ_ID FROM OBJECT_ADD(:V$OU_ID, 281) INTO :V$OBJ_ID;
            SELECT BLOB_ID FROM VAL_ADD(2327, :V$OBJ_ID, 0) INTO :V$BLOB_ID;
            SELECT BLOB_ID FROM VAL_ADD(2319, :V$OBJ_ID, 47) INTO :V$BLOB_ID;
        END


        V$OBJ_ID = NULL;
        SELECT L.OBJ_ID
        FROM LINKS L
        
        JOIN VALI V2284
        ON V2284.PARAM_ID = 2327
        AND V2284.IS_DEL = 0
        AND V2284.OBJ_ID = L.OBJ_ID
        AND V2284.VAL = 1
        
        JOIN VALL V2290
        ON V2290.PARAM_ID = 2319
        AND V2290.IS_DEL = 0
        AND V2290.OBJ_ID = L.OBJ_ID
        AND V2290.LISTVAL_ID = 46

        WHERE L.OBJ_TYPE_ID = 281
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :V$OU_ID
        INTO :V$OBJ_ID;

        IF (V$OBJ_ID IS NULL) THEN
        BEGIN
            SELECT OBJ_ID FROM OBJECT_ADD(:V$OU_ID, 281) INTO :V$OBJ_ID;
            SELECT BLOB_ID FROM VAL_ADD(2327, :V$OBJ_ID, 1) INTO :V$BLOB_ID;
            SELECT BLOB_ID FROM VAL_ADD(2319, :V$OBJ_ID, 46) INTO :V$BLOB_ID;
        END

        V$OBJ_ID = NULL;
        SELECT L.OBJ_ID
        FROM LINKS L
        
        JOIN VALI V2284
        ON V2284.PARAM_ID = 2327
        AND V2284.IS_DEL = 0
        AND V2284.OBJ_ID = L.OBJ_ID
        AND V2284.VAL = 1
        
        JOIN VALL V2290
        ON V2290.PARAM_ID = 2319
        AND V2290.IS_DEL = 0
        AND V2290.OBJ_ID = L.OBJ_ID
        AND V2290.LISTVAL_ID = 47

        WHERE L.OBJ_TYPE_ID = 281
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :V$OU_ID
        INTO :V$OBJ_ID;

        IF (V$OBJ_ID IS NULL) THEN
        BEGIN
            SELECT OBJ_ID FROM OBJECT_ADD(:V$OU_ID, 281) INTO :V$OBJ_ID;
            SELECT BLOB_ID FROM VAL_ADD(2327, :V$OBJ_ID, 1) INTO :V$BLOB_ID;
            SELECT BLOB_ID FROM VAL_ADD(2319, :V$OBJ_ID, 47) INTO :V$BLOB_ID;
        END


        V$OBJ_ID = NULL;
        SELECT L.OBJ_ID
        FROM LINKS L
        
        JOIN VALI V2284
        ON V2284.PARAM_ID = 2327
        AND V2284.IS_DEL = 0
        AND V2284.OBJ_ID = L.OBJ_ID
        AND V2284.VAL = 2
        
        JOIN VALL V2290
        ON V2290.PARAM_ID = 2319
        AND V2290.IS_DEL = 0
        AND V2290.OBJ_ID = L.OBJ_ID
        AND V2290.LISTVAL_ID = 46

        WHERE L.OBJ_TYPE_ID = 281
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :V$OU_ID
        INTO :V$OBJ_ID;

        IF (V$OBJ_ID IS NULL) THEN
        BEGIN
            SELECT OBJ_ID FROM OBJECT_ADD(:V$OU_ID, 281) INTO :V$OBJ_ID;
            SELECT BLOB_ID FROM VAL_ADD(2327, :V$OBJ_ID, 2) INTO :V$BLOB_ID;
            SELECT BLOB_ID FROM VAL_ADD(2319, :V$OBJ_ID, 46) INTO :V$BLOB_ID;
        END

        V$OBJ_ID = NULL;
        SELECT L.OBJ_ID
        FROM LINKS L
        
        JOIN VALI V2284
        ON V2284.PARAM_ID = 2327
        AND V2284.IS_DEL = 0
        AND V2284.OBJ_ID = L.OBJ_ID
        AND V2284.VAL = 2
        
        JOIN VALL V2290
        ON V2290.PARAM_ID = 2319
        AND V2290.IS_DEL = 0
        AND V2290.OBJ_ID = L.OBJ_ID
        AND V2290.LISTVAL_ID = 47

        WHERE L.OBJ_TYPE_ID = 281
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :V$OU_ID
        INTO :V$OBJ_ID;

        IF (V$OBJ_ID IS NULL) THEN
        BEGIN
            SELECT OBJ_ID FROM OBJECT_ADD(:V$OU_ID, 281) INTO :V$OBJ_ID;
            SELECT BLOB_ID FROM VAL_ADD(2327, :V$OBJ_ID, 2) INTO :V$BLOB_ID;
            SELECT BLOB_ID FROM VAL_ADD(2319, :V$OBJ_ID, 47) INTO :V$BLOB_ID;
        END


        V$OBJ_ID = NULL;
        SELECT L.OBJ_ID
        FROM LINKS L
        
        JOIN VALI V2284
        ON V2284.PARAM_ID = 2327
        AND V2284.IS_DEL = 0
        AND V2284.OBJ_ID = L.OBJ_ID
        AND V2284.VAL = 3
        
        JOIN VALL V2290
        ON V2290.PARAM_ID = 2319
        AND V2290.IS_DEL = 0
        AND V2290.OBJ_ID = L.OBJ_ID
        AND V2290.LISTVAL_ID = 46

        WHERE L.OBJ_TYPE_ID = 281
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :V$OU_ID
        INTO :V$OBJ_ID;

        IF (V$OBJ_ID IS NULL) THEN
        BEGIN
            SELECT OBJ_ID FROM OBJECT_ADD(:V$OU_ID, 281) INTO :V$OBJ_ID;
            SELECT BLOB_ID FROM VAL_ADD(2327, :V$OBJ_ID, 3) INTO :V$BLOB_ID;
            SELECT BLOB_ID FROM VAL_ADD(2319, :V$OBJ_ID, 46) INTO :V$BLOB_ID;
        END

        V$OBJ_ID = NULL;
        SELECT L.OBJ_ID
        FROM LINKS L
        
        JOIN VALI V2284
        ON V2284.PARAM_ID = 2327
        AND V2284.IS_DEL = 0
        AND V2284.OBJ_ID = L.OBJ_ID
        AND V2284.VAL = 3
        
        JOIN VALL V2290
        ON V2290.PARAM_ID = 2319
        AND V2290.IS_DEL = 0
        AND V2290.OBJ_ID = L.OBJ_ID
        AND V2290.LISTVAL_ID = 47

        WHERE L.OBJ_TYPE_ID = 281
        AND L.DATE_DEL IS NULL
        AND L.PARENT_ID = :V$OU_ID
        INTO :V$OBJ_ID;

        IF (V$OBJ_ID IS NULL) THEN
        BEGIN
            SELECT OBJ_ID FROM OBJECT_ADD(:V$OU_ID, 281) INTO :V$OBJ_ID;
            SELECT BLOB_ID FROM VAL_ADD(2327, :V$OBJ_ID, 3) INTO :V$BLOB_ID;
            SELECT BLOB_ID FROM VAL_ADD(2319, :V$OBJ_ID, 47) INTO :V$BLOB_ID;
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PLAN_PROFILE_DATA_GET RETURNS (
    NYEAR INTEGER,
    NPARAL INTEGER,
    UYEAR VARCHAR(100),
    UPARAL VARCHAR(20),
    P1 INTEGER,
    P2 INTEGER,
    P3 INTEGER,
    P4 INTEGER,
    P5 INTEGER,
    P6 INTEGER,
    P7 INTEGER)
AS
declare variable V$OBJ_ID bigint;
BEGIN
    FOR
        SELECT L.OBJ_ID,
        V2327.VAL,
        V2319.LISTVAL_ID,
        CASE WHEN V2319.LISTVAL_ID = 46 THEN '10 параллель'
             WHEN V2319.LISTVAL_ID = 47 THEN '11 параллель'
        END
        FROM LINKS L
    
        JOIN VALI V2327
        ON V2327.PARAM_ID = 2327
        AND V2327.OBJ_ID = L.OBJ_ID
        AND V2327.IS_DEL = 0

        JOIN VALL V2319
        ON V2319.PARAM_ID = 2319
        AND V2319.OBJ_ID = L.OBJ_ID
        AND V2319.IS_DEL = 0

        WHERE L.OBJ_TYPE_ID = 281
        AND L.DATE_DEL IS NULL
        AND L.PARENT_TYPE_ID = 2
        
        ORDER BY V2327.VAL
        INTO :V$OBJ_ID, :NYEAR, :NPARAL, :UPARAL
    DO
    BEGIN
        P1 = NULL;
        P2 = NULL;
        P3 = NULL;
        P4 = NULL;
        P5 = NULL;
        P6 = NULL;
        P7 = NULL;

        SELECT V.V
        FROM VAL_GET(:V$OBJ_ID, 2318) V
        INTO :UYEAR;

        SELECT V.VAL
        FROM VALI V
        WHERE V.PARAM_ID = 2320
        AND V.IS_DEL = 0
        AND V.OBJ_ID = :V$OBJ_ID
        INTO :P1;

        SELECT V.VAL
        FROM VALI V
        WHERE V.PARAM_ID = 2321
        AND V.IS_DEL = 0
        AND V.OBJ_ID = :V$OBJ_ID
        INTO :P2;

        SELECT V.VAL
        FROM VALI V
        WHERE V.PARAM_ID = 2322
        AND V.IS_DEL = 0
        AND V.OBJ_ID = :V$OBJ_ID
        INTO :P3;

        SELECT V.VAL
        FROM VALI V
        WHERE V.PARAM_ID = 2323
        AND V.IS_DEL = 0
        AND V.OBJ_ID = :V$OBJ_ID
        INTO :P4;

        SELECT V.VAL
        FROM VALI V
        WHERE V.PARAM_ID = 2324
        AND V.IS_DEL = 0
        AND V.OBJ_ID = :V$OBJ_ID
        INTO :P5;

        SELECT V.VAL
        FROM VALI V
        WHERE V.PARAM_ID = 2325
        AND V.IS_DEL = 0
        AND V.OBJ_ID = :V$OBJ_ID
        INTO :P6;

        SELECT V.VAL
        FROM VALI V
        WHERE V.PARAM_ID = 2326
        AND V.IS_DEL = 0
        AND V.OBJ_ID = :V$OBJ_ID
        INTO :P7;

        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PLAN_PROFILE_DATA_SET (
    I$P1 INTEGER,
    I$P2 INTEGER,
    I$P3 INTEGER,
    I$P4 INTEGER,
    I$P5 INTEGER,
    I$P6 INTEGER,
    I$P7 INTEGER,
    I$NYEAR INTEGER,
    I$NPARAL INTEGER)
AS
declare variable V$OBJ_ID bigint;
declare variable V$BLOB_ID bigint;
BEGIN
    SELECT L.OBJ_ID

    FROM LINKS L

    JOIN VALI V2327
    ON V2327.PARAM_ID = 2327
    AND V2327.OBJ_ID = L.OBJ_ID
    AND V2327.IS_DEL = 0
    AND V2327.VAL = :I$NYEAR

    JOIN VALL V2319
    ON V2319.PARAM_ID = 2319
    AND V2319.OBJ_ID = L.OBJ_ID
    AND V2319.IS_DEL = 0
    AND V2319.LISTVAL_ID = :I$NPARAL

    WHERE L.OBJ_TYPE_ID = 281
    AND L.DATE_DEL IS NULL
    AND L.PARENT_TYPE_ID = 2
    
    ORDER BY V2327.VAL
    INTO :V$OBJ_ID;


    IF (V$OBJ_ID IS NOT NULL) THEN
    BEGIN
        IF (:I$P1 IS NOT NULL) THEN
        BEGIN
            SELECT BLOB_ID FROM VAL_ADD(2320,:V$OBJ_ID,:I$P1) INTO :V$BLOB_ID;
        END

        IF (:I$P2 IS NOT NULL) THEN
        BEGIN
            SELECT BLOB_ID FROM VAL_ADD(2321,:V$OBJ_ID,:I$P2) INTO :V$BLOB_ID;
        END

        IF (:I$P3 IS NOT NULL) THEN
        BEGIN
            SELECT BLOB_ID FROM VAL_ADD(2322,:V$OBJ_ID,:I$P3) INTO :V$BLOB_ID;
        END

        IF (:I$P4 IS NOT NULL) THEN
        BEGIN
            SELECT BLOB_ID FROM VAL_ADD(2323,:V$OBJ_ID,:I$P4) INTO :V$BLOB_ID;
        END

        IF (:I$P5 IS NOT NULL) THEN
        BEGIN
            SELECT BLOB_ID FROM VAL_ADD(2324,:V$OBJ_ID,:I$P5) INTO :V$BLOB_ID;
        END

        IF (:I$P6 IS NOT NULL) THEN
        BEGIN
            SELECT BLOB_ID FROM VAL_ADD(2325,:V$OBJ_ID,:I$P6) INTO :V$BLOB_ID;
        END

        IF (:I$P7 IS NOT NULL) THEN
        BEGIN
            SELECT BLOB_ID FROM VAL_ADD(2326,:V$OBJ_ID,:I$P7) INTO :V$BLOB_ID;
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PLAN_PROFILE_VALIDATE (
    I$OBJ_ID BIGINT,
    I$STANDARD BIGINT)
AS
DECLARE VARIABLE V$PROFILE BIGINT;
DECLARE VARIABLE V$PARAM_ID BIGINT;
DECLARE VARIABLE N INTEGER;
DECLARE VARIABLE V$SUBJECT_ID BIGINT;
DECLARE VARIABLE V$FIELD_ID BIGINT;
DECLARE VARIABLE V$NEW_ID BIGINT;
DECLARE VARIABLE V$STAGE_ID BIGINT;
DECLARE VARIABLE V$YEAR INTEGER;
DECLARE VARIABLE V$IS_FOP SMALLINT;
begin

  SELECT FIRST 1 LISTVAL_ID, PARAM_ID
  FROM VALL
  WHERE OBJ_ID = :I$OBJ_ID AND PARAM_ID IN (2166, 3112) AND IS_DEL = 0
  INTO :V$PROFILE, :V$PARAM_ID;

  IF(V$PROFILE IS NOT NULL) THEN
  BEGIN

    SELECT COUNT(*)
    FROM OBJECT_LISTVALS_UPPROFILE(272, 1, :V$PARAM_ID, :I$OBJ_ID)
    WHERE LISTVAL_ID = :V$PROFILE
    INTO :N;

    IF(N = 0) THEN EXCEPTION DATA_ERROR 'Данный профиль недоступен в выбранном образовательном стандарте. Удалите профиль, измените стандарт, и установите профиль заново';

  END

  -- Пересчитываем предметные области - только для СОО
  -- и только общеобразовательные
  SELECT V1594.LISTVAL_ID, COALESCE(V3115.VAL, 2024)
  FROM LINKS LP57
  JOIN VALL V1594 ON V1594.OBJ_ID = LP57.PARENT_ID AND V1594.PARAM_ID = 1594 AND V1594.IS_DEL = 0
  LEFT JOIN VALI V3115 ON V3115.OBJ_ID = LP57.PARENT_ID AND V3115.PARAM_ID = 3115 AND V3115.IS_DEL = 0
  WHERE LP57.OBJ_ID = :I$OBJ_ID AND LP57.PARENT_TYPE_ID = 57 AND LP57.DATE_DEL IS NULL
  INTO :V$STAGE_ID, :V$YEAR;

  V$IS_FOP = IIF(I$STANDARD IN (14184, 14186), 1, 0);

  FOR
    SELECT PS.OBJ_ID, PS.SUBJECT_ID, PS.FIELD_ID
    FROM PLAN_SUBJECTS PS
    JOIN LINKS LP301 ON LP301.OBJ_ID = PS.SUBJECT_ID AND LP301.PARENT_ID = 32771 AND LP301.DATE_DEL IS NULL
    WHERE PS.PLAN_ID = :I$OBJ_ID AND PS.ROW_TYPE = 10 AND :V$STAGE_ID IS NOT NULL
    ORDER BY 1
    INTO :V$PARAM_ID, :V$SUBJECT_ID, :V$FIELD_ID
  DO
  BEGIN
    V$NEW_ID = NULL;
    SELECT FIRST 1 V2462.LISTVAL_ID
    FROM LINKS L302
    JOIN VALL V2462 ON V2462.OBJ_ID = L302.OBJ_ID AND V2462.PARAM_ID = 2462 AND V2462.IS_DEL = 0
    WHERE L302.PARENT_ID = :V$SUBJECT_ID AND L302.OBJ_TYPE_ID = 302 AND L302.DATE_DEL IS NULL
    AND (
      ((:V$STAGE_ID = 5339) AND (V2462.LISTVAL_ID IN (12740, 11680, 11682, 11685, 11686, 11689, 11693, 11694, 11695))) OR
      ((:V$STAGE_ID = 5341) AND (V2462.LISTVAL_ID IN (11684, 11681, 11683, 11685, 11687, 11690, 11691, 11693, 11694, 11696))) OR
      -- Естественные и общественные науки
      -- Старые стандарты
      ((:V$STAGE_ID = 5343) AND (:V$IS_FOP = 0) AND (V2462.LISTVAL_ID IN (11684, 11681, 11683, 11685, 11688, 11690, 11692, 11693, 11694, 11696, 11697))) OR
      -- Новый стандарт
      ((:V$STAGE_ID = 5343) AND (:V$IS_FOP = 1) AND (V2462.LISTVAL_ID IN (11684, 11681, 11683, 11685, 11687, 11690, 11691, 11693, 11694, 11696, 11697))) OR
      ((:V$STAGE_ID IN (5341, 5343)) AND (V2462.LISTVAL_ID IN (14552, 14553) AND :V$YEAR >= 2024))
    )
    ORDER BY V2462.LISTVAL_ID DESC -- сначала более поздние, чтобы брать первично более изменения 2024 года
    INTO :V$NEW_ID;

    IF(V$FIELD_ID <> V$NEW_ID) THEN
    UPDATE PLAN_SUBJECTS
    SET FIELD_ID = :V$NEW_ID
    WHERE OBJ_ID = :V$PARAM_ID;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PLAN_RECALC (
    I$PLAN_ID BIGINT,
    I$USER_ID VARCHAR(40))
AS
declare variable V$TYPE_ID bigint;
declare variable V$STAGE_ID bigint;
declare variable V$WEEKS integer;
declare variable N integer;
declare variable TMP bigint;
declare variable V$EXT smallint;
declare variable W integer;
declare variable V$WW bigint;
declare variable H float;
declare variable S varchar(4000);
declare variable SN varchar(4000);
declare variable SS varchar(400);
declare variable SNS varchar(400);
begin

  -- USER_ID NULL если пересчет со стороны ГЗ

  IF(I$USER_ID IS NOT NULL) THEN
  BEGIN

    -- Пересчет фактической нагрузки в часах по этапам, и сразу смотрим учебную неделю
    W = NULL;
    FOR
      SELECT L54.OBJ_ID, V382.VAL, V2837.LISTVAL_ID
      FROM LINKS L54
      JOIN VALI V382 ON V382.OBJ_ID = L54.OBJ_ID AND V382.PARAM_ID = 382 AND V382.IS_DEL = 0
      LEFT JOIN VALL V2837 ON V2837.OBJ_ID = L54.OBJ_ID AND V2837.PARAM_ID = 2837 AND V2837.IS_DEL = 0
      WHERE L54.PARENT_ID = :I$PLAN_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
      INTO :V$STAGE_ID, :V$WEEKS, :V$WW
    DO
    BEGIN
      N = 0;
      SELECT SUM(COALESCE(L.LOAD_HOURS_S1, 0) + COALESCE(L.LOAD_HOURS_S2, 0))
      FROM PLAN_LOADS L
      JOIN PLAN_SUBJECTS S ON S.DATE_DEL IS NULL AND S.OBJ_ID = L.SUBJECT_ID AND S.ROW_TYPE = 10
      JOIN PLAN_SUBJECTS PS ON PS.DATE_DEL IS NULL AND PS.OBJ_ID = S.PARENT_ID
      WHERE L.DATE_DEL IS NULL AND L.STAGE_ID = :V$STAGE_ID AND (S.SUBJECT_ID = 34607 OR PS.FIELD_ID <> 12928)
      INTO :N;

      IF(V$WEEKS > 0 AND N > 0) THEN N = N / V$WEEKS; ELSE N = 0;

      UPDATE OR INSERT INTO VALI
      (OBJ_ID, PARAM_ID, IS_DEL, VAL)
      VALUES (:I$PLAN_ID, 1185, 0, :N);

      -- Учебная неделя
      IF(V$WW = 11718) THEN V$WW = 5; ELSE V$WW = 6;
      IF(W IS NULL) THEN W = V$WW;
      ELSE IF(W <> V$WW) THEN W = 0;
    END

    -- Наличие углубленных предметов и сами предметы
    S = '';
    FOR
      SELECT COALESCE(S.SRC_SUBJECT_ID, S.SUBJECT_ID), SUM(L.LOAD_HOURS)
      FROM PLAN_SUBJECTS S
      JOIN PLAN_LOADS L ON L.DATE_DEL IS NULL AND L.SUBJECT_ID = S.OBJ_ID AND L.LOAD_HOURS > 0 AND L.STAGE_ID IS NOT NULL
      WHERE S.DATE_DEL IS NULL AND S.PLAN_ID = :I$PLAN_ID AND S.IS_ADV = 1
      GROUP BY 1
      INTO :TMP, :H
    DO
    BEGIN
      IF(S <> '') THEN S = S || ', ';
      SS = CAST(H AS NUMERIC(18, 2));
      SS = REPLACE(SS, '.00', '');
      S = S || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:TMP)) || ': ' || SS || 'ч';
      V$EXT = 1;
    END

    UPDATE OR INSERT INTO VALL
    (OBJ_ID, PARAM_ID, IS_DEL, LISTVAL_ID)
    VALUES (:I$PLAN_ID, 3436, 0, IIF(:V$EXT = 1, 2, 3));

    UPDATE OR INSERT INTO VALS
    (OBJ_ID, PARAM_ID, IS_DEL, VAL)
    VALUES (:I$PLAN_ID, 3439, 0, :S);

    -- Учебная неделя
    UPDATE OR INSERT INTO VALI
    (OBJ_ID, PARAM_ID, IS_DEL, VAL)
    VALUES (:I$PLAN_ID, 3438, 0, COALESCE(:W, 0));

    -- Общие часы, считаем по строкам разделов !!! могут быть случаи когда разделов нет !!!
    H = NULL;
    SELECT SUM(L.LOAD_HOURS)
    FROM PLAN_SUBJECTS PS
    JOIN PLAN_LOADS L ON L.DATE_DEL IS NULL AND L.SUBJECT_ID = PS.OBJ_ID AND L.STAGE_ID IS NULL
    WHERE PS.DATE_DEL IS NULL AND PS.ROW_TYPE = 0 AND PS.PLAN_ID = :I$PLAN_ID AND PS.PARENT_ID IS NULL
    INTO :H;

    UPDATE OR INSERT INTO VALI
    (OBJ_ID, PARAM_ID, IS_DEL, VAL)
    VALUES (:I$PLAN_ID, 3445, 0, COALESCE(:H, 0));

  END

  -- Список ГЗ - обновляем всегда
  -- В качестве I$PLAN_ID может быть указан ID показателя услуги
  IF(I$USER_ID IS NULL) THEN
  BEGIN
    SELECT OBJ.TYPE_ID
    FROM OBJECTS OBJ
    LEFT JOIN VALL V3244 ON V3244.OBJ_ID = OBJ.OBJ_ID AND V3244.PARAM_ID = 3244 AND V3244.IS_DEL = 0
    WHERE OBJ.OBJ_ID = :I$PLAN_ID AND (V3244.LISTVAL_ID IS NULL OR V3244.LISTVAL_ID = 13847)
    INTO :V$TYPE_ID;

    IF(V$TYPE_ID IS NULL) THEN EXIT;
    IF(V$TYPE_ID = 443) THEN
    BEGIN
      -- Пересчитываем все УП в данном ГЗ
      FOR
        SELECT DISTINCT OBJ.OBJ_ID
        FROM LINKS LP442
        JOIN LINKS L495 ON L495.PARENT_ID = LP442.PARENT_ID AND L495.OBJ_TYPE_ID = 495 AND L495.DATE_DEL IS NULL
        JOIN VALR V3427 ON V3427.OBJ_ID = L495.OBJ_ID AND V3427.PARAM_ID = 3427 AND V3427.IS_DEL = 0
        JOIN OBJECTS OBJ ON OBJ.OBJ_ID = V3427.VAL AND OBJ.TYPE_ID = 400
        WHERE LP442.OBJ_ID = :I$PLAN_ID AND LP442.PARENT_TYPE_ID = 442 AND LP442.DATE_DEL IS NULL
        INTO :V$STAGE_ID
      DO
      BEGIN
        EXECUTE PROCEDURE PLAN_RECALC(:V$STAGE_ID, NULL);
      END
      EXIT;
    END
  END

  N = 0;
  S = '';
  SN = '';
  FOR
    SELECT DISTINCT V3222.SVAL, V3220.SVAL
    FROM VALR V
    JOIN LINKS LP442 ON LP442.OBJ_ID = V.OBJ_ID AND LP442.PARENT_TYPE_ID = 442 AND LP442.DATE_DEL IS NULL
    JOIN VALS V3222 ON V3222.OBJ_ID = LP442.PARENT_ID AND V3222.PARAM_ID = 3222 AND V3222.IS_DEL = 0
    JOIN VALS V3220 ON V3220.OBJ_ID = LP442.PARENT_ID AND V3220.PARAM_ID = 3220 AND V3220.IS_DEL = 0
    WHERE V.PARAM_ID = 3427 AND V.IS_DEL = 0 AND V.VAL = :I$PLAN_ID
    ORDER BY 1
    INTO :SS, :SNS
  DO
  BEGIN
    IF(S <> '') THEN S = S || ', ';
    S = S || SS;
    IF(SN <> '') THEN SN = SN || ', ';
    SN = SN || SNS;
  END

  UPDATE OR INSERT INTO VALS
  (OBJ_ID, PARAM_ID, IS_DEL, VAL)
  VALUES (:I$PLAN_ID, 3437, 0, :S);

  UPDATE OR INSERT INTO VALS
  (OBJ_ID, PARAM_ID, IS_DEL, VAL)
  VALUES (:I$PLAN_ID, 3443, 0, :SN);

  -- Численность по ГЗ
  N = NULL;
  SELECT SUM(V3247.VAL)
  FROM VALR V
  JOIN LINKS LP442 ON LP442.OBJ_ID = V.OBJ_ID AND LP442.PARENT_TYPE_ID = 442 AND LP442.DATE_DEL IS NULL
  JOIN LINKS L443 ON L443.PARENT_ID = LP442.PARENT_ID AND L443.OBJ_TYPE_ID = 443 AND L443.DATE_DEL IS NULL
  JOIN VALL V3244 ON V3244.OBJ_ID = L443.OBJ_ID AND V3244.PARAM_ID = 3244 AND V3244.IS_DEL = 0 AND V3244.LISTVAL_ID = 13847 -- человек
  JOIN VALF V3247 ON V3247.OBJ_ID = L443.OBJ_ID AND V3247.PARAM_ID = 3247 AND V3247.IS_DEL = 0
  WHERE V.PARAM_ID = 3427 AND V.IS_DEL = 0 AND V.VAL = :I$PLAN_ID
  INTO :N;

  UPDATE OR INSERT INTO VALI
  (OBJ_ID, PARAM_ID, IS_DEL, VAL)
  VALUES (:I$PLAN_ID, 3440, 0, COALESCE(:N, 0));

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PLAN_REPORT_COUNT_ODOD_BY_OU RETURNS (
    OU_NAME VARCHAR(200),
    YEAR0 INTEGER,
    YEAR1 INTEGER,
    YEAR2 INTEGER,
    YEAR3 INTEGER)
AS
declare variable V$OU_ID bigint;
declare variable V$YEAR_NUMBER integer;
declare variable V$YEAR0 integer;
declare variable V$YEAR1 integer;
declare variable V$YEAR2 integer;
declare variable V$YEAR3 integer;
BEGIN
    V$YEAR0 = 0;
    V$YEAR1 = 0;
    V$YEAR2 = 0;
    V$YEAR3 = 0;

    FOR
        SELECT L2.OBJ_ID, C.CAPTION
        FROM LINKS L111
        
        JOIN LINKS L2
        ON L2.OBJ_TYPE_ID = 2
        AND L2.DATE_DEL IS NULL
        AND L2.PARENT_ID = L111.OBJ_ID
        
        LEFT JOIN OBJECT_CAPTION_GET(L2.OBJ_ID) C ON 1=1
        
        WHERE L111.OBJ_TYPE_ID = 111
        AND L111.DATE_DEL IS NULL
        AND L111.PARENT_ID IS NULL

        ORDER BY  C.SORT_ORDER

        INTO :V$OU_ID, :OU_NAME
    DO
    BEGIN
        YEAR0 = NULL;
        YEAR1 = NULL;
        YEAR2 = NULL;
        YEAR3 = NULL;

        SELECT V.V
        FROM LINKS L282
        
        JOIN VALI V2308
        ON V2308.PARAM_ID = 2308
        AND V2308.OBJ_ID = L282.OBJ_ID
        AND V2308.IS_DEL =0
        AND V2308.VAL = 0
        
        LEFT JOIN VAL_GET(L282.OBJ_ID, 2307) V ON 1=1
        
        WHERE L282.OBJ_TYPE_ID = 282
        AND L282.PARENT_ID = :V$OU_ID
        AND L282.DATE_DEL IS NULL

        INTO :YEAR0;

        SELECT V.V
        FROM LINKS L282
        
        JOIN VALI V2285
        ON V2285.PARAM_ID = 2308
        AND V2285.OBJ_ID = L282.OBJ_ID
        AND V2285.IS_DEL =0
        AND V2285.VAL = 1
        
        LEFT JOIN VAL_GET(L282.OBJ_ID, 2307) V ON 1=1
        
        WHERE L282.OBJ_TYPE_ID = 282
        AND L282.PARENT_ID = :V$OU_ID
        AND L282.DATE_DEL IS NULL

        INTO :YEAR1;

        SELECT V.V
        FROM LINKS L282
        
        JOIN VALI V2285
        ON V2285.PARAM_ID = 2308
        AND V2285.OBJ_ID = L282.OBJ_ID
        AND V2285.IS_DEL =0
        AND V2285.VAL = 2
        
        LEFT JOIN VAL_GET(L282.OBJ_ID, 2307) V ON 1=1
        
        WHERE L282.OBJ_TYPE_ID = 282
        AND L282.PARENT_ID = :V$OU_ID
        AND L282.DATE_DEL IS NULL

        INTO :YEAR2;

        SELECT V.V
        FROM LINKS L282
        
        JOIN VALI V2285
        ON V2285.PARAM_ID = 2308
        AND V2285.OBJ_ID = L282.OBJ_ID
        AND V2285.IS_DEL =0
        AND V2285.VAL = 3
        
        LEFT JOIN VAL_GET(L282.OBJ_ID, 2307) V ON 1=1
        
        WHERE L282.OBJ_TYPE_ID = 282
        AND L282.PARENT_ID = :V$OU_ID
        AND L282.DATE_DEL IS NULL

        INTO :YEAR3;

        IF (YEAR0 IS NOT NULL) THEN V$YEAR0 = V$YEAR0 + YEAR0;
        IF (YEAR1 IS NOT NULL) THEN V$YEAR1 = V$YEAR1 + YEAR1;
        IF (YEAR2 IS NOT NULL) THEN V$YEAR2 = V$YEAR2 + YEAR2;
        IF (YEAR3 IS NOT NULL) THEN V$YEAR3 = V$YEAR3 + YEAR3;
        SUSPEND;
    END

        OU_NAME = 'Всего';
        YEAR0 = V$YEAR0;
        YEAR1 = V$YEAR1;
        YEAR2 = V$YEAR2;
        YEAR3 = V$YEAR3;
        SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PLAN_REPORT_COUNT_PUPIL_BY_DSTR RETURNS (
    DISTRICT_NAME VARCHAR(200),
    YEAR0 INTEGER,
    YEAR1 INTEGER,
    YEAR2 INTEGER,
    YEAR3 INTEGER)
AS
declare variable V$DISTRICT_ID bigint;
declare variable V$YEAR_NUMBER integer;
declare variable V$YEAR0 integer;
declare variable V$YEAR1 integer;
declare variable V$YEAR2 integer;
declare variable V$YEAR3 integer;
BEGIN
    V$YEAR0 = 0;
    V$YEAR1 = 0;
    V$YEAR2 = 0;
    V$YEAR3 = 0;

    FOR
        SELECT L111.OBJ_ID, C.CAPTION
        FROM LINKS L112
        
        JOIN LINKS L111
        ON L111.OBJ_TYPE_ID = 111
        AND L111.DATE_DEL IS NULL
        AND L111.PARENT_ID = L112.OBJ_ID
        
        LEFT JOIN OBJECT_CAPTION_GET(L111.OBJ_ID) C ON 1=1
        
        WHERE L112.OBJ_TYPE_ID = 112
        AND L112.DATE_DEL IS NULL
        AND L112.PARENT_ID IS NULL
        
        ORDER BY  C.SORT_ORDER

        INTO :V$DISTRICT_ID, :DISTRICT_NAME
    DO
    BEGIN
        YEAR0 = NULL;
        YEAR1 = NULL;
        YEAR2 = NULL;
        YEAR3 = NULL;

        SELECT V.V
        FROM LINKS L278
        
        JOIN VALI V2285
        ON V2285.PARAM_ID = 2287
        AND V2285.OBJ_ID = L278.OBJ_ID
        AND V2285.IS_DEL =0
        AND V2285.VAL = 0
        
        LEFT JOIN VAL_GET(L278.OBJ_ID, 2283) V ON 1=1
        
        WHERE L278.OBJ_TYPE_ID = 278
        AND L278.PARENT_ID = :V$DISTRICT_ID
        AND L278.DATE_DEL IS NULL

        INTO :YEAR0;

        SELECT V.V
        FROM LINKS L275
        
        JOIN VALI V2285
        ON V2285.PARAM_ID = 2287
        AND V2285.OBJ_ID = L275.OBJ_ID
        AND V2285.IS_DEL =0
        AND V2285.VAL = 1
        
        LEFT JOIN VAL_GET(L275.OBJ_ID, 2283) V ON 1=1
        
        WHERE L275.OBJ_TYPE_ID = 278
        AND L275.PARENT_ID = :V$DISTRICT_ID
        AND L275.DATE_DEL IS NULL

        INTO :YEAR1;

        SELECT V.V
        FROM LINKS L275
        
        JOIN VALI V2285
        ON V2285.PARAM_ID = 2287
        AND V2285.OBJ_ID = L275.OBJ_ID
        AND V2285.IS_DEL =0
        AND V2285.VAL = 2
        
        LEFT JOIN VAL_GET(L275.OBJ_ID, 2283) V ON 1=1
        
        WHERE L275.OBJ_TYPE_ID = 278
        AND L275.PARENT_ID = :V$DISTRICT_ID
        AND L275.DATE_DEL IS NULL

        INTO :YEAR2;

        SELECT V.V
        FROM LINKS L275
        
        JOIN VALI V2285
        ON V2285.PARAM_ID = 2287
        AND V2285.OBJ_ID = L275.OBJ_ID
        AND V2285.IS_DEL =0
        AND V2285.VAL = 3
        
        LEFT JOIN VAL_GET(L275.OBJ_ID, 2283) V ON 1=1
        
        WHERE L275.OBJ_TYPE_ID = 278
        AND L275.PARENT_ID = :V$DISTRICT_ID
        AND L275.DATE_DEL IS NULL

        INTO :YEAR3;

        IF (YEAR0 IS NOT NULL) THEN V$YEAR0 = V$YEAR0 + YEAR0;
        IF (YEAR1 IS NOT NULL) THEN V$YEAR1 = V$YEAR1 + YEAR1;
        IF (YEAR2 IS NOT NULL) THEN V$YEAR2 = V$YEAR2 + YEAR2;
        IF (YEAR3 IS NOT NULL) THEN V$YEAR3 = V$YEAR3 + YEAR3;
        SUSPEND;
    END

        DISTRICT_NAME = 'ВСЕГО';
        YEAR0 = V$YEAR0;
        YEAR1 = V$YEAR1;
        YEAR2 = V$YEAR2;
        YEAR3 = V$YEAR3;
        SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PLAN_REPORT_COUNT_PUPIL_BY_OU RETURNS (
    OU_NAME VARCHAR(200),
    YEAR0 INTEGER,
    YEAR1 INTEGER,
    YEAR2 INTEGER,
    YEAR3 INTEGER)
AS
declare variable V$OU_ID bigint;
declare variable V$YEAR_NUMBER integer;
declare variable V$YEAR0 integer;
declare variable V$YEAR1 integer;
declare variable V$YEAR2 integer;
declare variable V$YEAR3 integer;
BEGIN
    V$YEAR0 = 0;
    V$YEAR1 = 0;
    V$YEAR2 = 0;
    V$YEAR3 = 0;

    FOR
        SELECT L2.OBJ_ID, C.CAPTION
        FROM LINKS L111
        
        JOIN LINKS L2
        ON L2.OBJ_TYPE_ID = 2
        AND L2.DATE_DEL IS NULL
        AND L2.PARENT_ID = L111.OBJ_ID
        
        LEFT JOIN OBJECT_CAPTION_GET(L2.OBJ_ID) C ON 1=1
        
        WHERE L111.OBJ_TYPE_ID = 111
        AND L111.DATE_DEL IS NULL
        AND L111.PARENT_ID IS NULL

        ORDER BY  C.SORT_ORDER

        INTO :V$OU_ID, :OU_NAME
    DO
    BEGIN
        YEAR0 = NULL;
        YEAR1 = NULL;
        YEAR2 = NULL;
        YEAR3 = NULL;

        SELECT V.V
        FROM LINKS L275
        
        JOIN VALI V2285
        ON V2285.PARAM_ID = 2285
        AND V2285.OBJ_ID = L275.OBJ_ID
        AND V2285.IS_DEL =0
        AND V2285.VAL = 0
        
        LEFT JOIN VAL_GET(L275.OBJ_ID, 2251) V ON 1=1
        
        WHERE L275.OBJ_TYPE_ID = 275
        AND L275.PARENT_ID = :V$OU_ID
        AND L275.DATE_DEL IS NULL

        INTO :YEAR0;

        SELECT V.V
        FROM LINKS L275
        
        JOIN VALI V2285
        ON V2285.PARAM_ID = 2285
        AND V2285.OBJ_ID = L275.OBJ_ID
        AND V2285.IS_DEL =0
        AND V2285.VAL = 1
        
        LEFT JOIN VAL_GET(L275.OBJ_ID, 2251) V ON 1=1
        
        WHERE L275.OBJ_TYPE_ID = 275
        AND L275.PARENT_ID = :V$OU_ID
        AND L275.DATE_DEL IS NULL

        INTO :YEAR1;

        SELECT V.V
        FROM LINKS L275
        
        JOIN VALI V2285
        ON V2285.PARAM_ID = 2285
        AND V2285.OBJ_ID = L275.OBJ_ID
        AND V2285.IS_DEL =0
        AND V2285.VAL = 2
        
        LEFT JOIN VAL_GET(L275.OBJ_ID, 2251) V ON 1=1
        
        WHERE L275.OBJ_TYPE_ID = 275
        AND L275.PARENT_ID = :V$OU_ID
        AND L275.DATE_DEL IS NULL

        INTO :YEAR2;

        SELECT V.V
        FROM LINKS L275
        
        JOIN VALI V2285
        ON V2285.PARAM_ID = 2285
        AND V2285.OBJ_ID = L275.OBJ_ID
        AND V2285.IS_DEL =0
        AND V2285.VAL = 3
        
        LEFT JOIN VAL_GET(L275.OBJ_ID, 2251) V ON 1=1
        
        WHERE L275.OBJ_TYPE_ID = 275
        AND L275.PARENT_ID = :V$OU_ID
        AND L275.DATE_DEL IS NULL

        INTO :YEAR3;

        IF (YEAR0 IS NOT NULL) THEN V$YEAR0 = V$YEAR0 + YEAR0;
        IF (YEAR1 IS NOT NULL) THEN V$YEAR1 = V$YEAR1 + YEAR1;
        IF (YEAR2 IS NOT NULL) THEN V$YEAR2 = V$YEAR2 + YEAR2;
        IF (YEAR3 IS NOT NULL) THEN V$YEAR3 = V$YEAR3 + YEAR3;
        SUSPEND;
    END

        OU_NAME = 'Всего';
        YEAR0 = V$YEAR0;
        YEAR1 = V$YEAR1;
        YEAR2 = V$YEAR2;
        YEAR3 = V$YEAR3;
        SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PLAN_REPORT_DISTRICT_ALL_EVENTS (
    I$OBJ_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    P1 VARCHAR(500),
    P2 VARCHAR(500),
    P3 VARCHAR(500),
    P4 VARCHAR(500),
    P5 VARCHAR(500),
    P6 VARCHAR(500))
AS
declare variable V$OBJ_ID bigint;
declare variable V$PARENT_TYPE integer;
declare variable V$LANG_CODE varchar(2);
declare variable V$PARENT_ID bigint;
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :V$LANG_CODE;

    FOR
        SELECT L273.OBJ_ID,
         L273.PARENT_TYPE_ID,
         L273.PARENT_ID
        FROM LINKS L111
        
        JOIN LINKS L2
        ON L2.OBJ_TYPE_ID = 2
        AND L2.DATE_DEL IS NULL
        AND L2.PARENT_ID = L111.OBJ_ID
        
        JOIN LINKS L273
        ON L273.OBJ_TYPE_ID = 273
        AND L273.DATE_DEL IS NULL
        AND L273.PARENT_ID = L2.OBJ_ID
        
        WHERE L111.OBJ_TYPE_ID = 111
        AND L111.DATE_DEL IS NULL
        AND L111.OBJ_ID = :I$OBJ_ID
        
        UNION
        
        SELECT L273.OBJ_ID,
         L273.PARENT_TYPE_ID,
         L273.PARENT_ID
        FROM LINKS L111
        
        JOIN LINKS L273
        ON L273.OBJ_TYPE_ID = 273
        AND L273.DATE_DEL IS NULL
        AND L273.PARENT_ID = L111.OBJ_ID
        
        WHERE L111.OBJ_TYPE_ID = 111
        AND L111.DATE_DEL IS NULL
        AND L111.obj_id = :i$obj_id
        INTO :V$OBJ_ID, :V$PARENT_TYPE, :V$PARENT_ID
    DO
    BEGIN
        P1 = NULL;
        SELECT R.VAL

        FROM VALL V
        
        JOIN LISTVALS LV
        ON  LV.LISTVAL_ID = V.LISTVAL_ID
        
        LEFT JOIN RES_GET(LV.RES_ID, :V$LANG_CODE) R ON 1=1
        
        WHERE V.OBJ_ID = :V$OBJ_ID
        AND V.IS_DEL = 0
        AND V.PARAM_ID = 2217
        INTO :P1;
        
        P2 = NULL;
        IF (V$PARENT_TYPE = 2) THEN
        BEGIN
           P2 = 'ОО';
        END
        ELSE IF (V$PARENT_TYPE = 111) THEN
        BEGIN
            P2 = 'ОУО';
        END

        P3 = NULL;
        SELECT R.VAL

        FROM VALL V
        
        JOIN LISTVALS LV
        ON  LV.LISTVAL_ID = V.LISTVAL_ID
        
        LEFT JOIN RES_GET(LV.RES_ID, :V$LANG_CODE) R ON 1=1
        
        WHERE V.OBJ_ID = :V$OBJ_ID
        AND V.IS_DEL = 0
        AND V.PARAM_ID = 2218
        INTO :P3;

        P4 = NULL;
        SELECT V.VAL

        FROM VALS V
        
        WHERE V.OBJ_ID = :V$OBJ_ID
        AND V.IS_DEL = 0
        AND V.PARAM_ID = 2219
        INTO :P4;

        P5 = NULL;
        IF (V$PARENT_TYPE = 2) THEN
        BEGIN
            SELECT V.VAL

            FROM VALS V
            
            WHERE V.OBJ_ID = :V$PARENT_ID
            AND V.IS_DEL = 0
            AND V.PARAM_ID = 2
            INTO :P5;
        END
        ELSE IF (V$PARENT_TYPE = 111) THEN
        BEGIN
            SELECT V.VAL

            FROM VALS V
            
            WHERE V.OBJ_ID = :V$OBJ_ID
            AND V.IS_DEL = 0
            AND V.PARAM_ID = 2329
            INTO :P5;
        END


        P6 = NULL;
        SELECT V.VAL

        FROM VALS V
        
        WHERE V.OBJ_ID = :V$OBJ_ID
        AND V.IS_DEL = 0
        AND V.PARAM_ID = 2220
        INTO :P6;

        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PLAN_REPORT_LOAD_BY_OU RETURNS (
    OU_NAME VARCHAR(200),
    YEAR0F INTEGER,
    YEAR0P INTEGER,
    YEAR1F INTEGER,
    YEAR1P INTEGER,
    YEAR2F INTEGER,
    YEAR2P INTEGER)
AS
declare variable V$OU_ID bigint;
declare variable V$LOAD0 integer;
declare variable V$LOAD_ARCH integer;
declare variable V$OBJ_ID bigint;
declare variable V$Y integer;
declare variable V$DT date;
declare variable V$YEAR_VAL varchar(9);
BEGIN
    FOR
        SELECT L2.OBJ_ID, C.CAPTION
        FROM LINKS L111
        
        JOIN LINKS L2
        ON L2.OBJ_TYPE_ID = 2
        AND L2.DATE_DEL IS NULL
        AND L2.PARENT_ID = L111.OBJ_ID
        
        LEFT JOIN OBJECT_CAPTION_GET(L2.OBJ_ID) C ON 1=1
        
        WHERE L111.OBJ_TYPE_ID = 111
        AND L111.DATE_DEL IS NULL
        AND L111.PARENT_ID IS NULL

        ORDER BY  C.SORT_ORDER

        INTO :V$OU_ID, :OU_NAME
    DO
    BEGIN
        YEAR0F = NULL;
        YEAR1F = NULL;
        YEAR2F = NULL;
        YEAR0P = NULL;
        YEAR1P = NULL;
        YEAR2P = NULL;

        FOR
            SELECT L270.OBJ_ID
            FROM LINKS L162
            
            JOIN LINKS L270
            ON L270.OBJ_TYPE_ID = 270
            AND L270.DATE_DEL IS NULL
            AND L270.PARENT_ID = L162.OBJ_ID
            
            WHERE L162.OBJ_TYPE_ID = 162
            AND L162.DATE_DEL IS NULL
            AND L162.PARENT_ID = :V$OU_ID
            INTO :V$OBJ_ID
        DO
        BEGIN
            SELECT V.V FROM VAL_GET(:V$OBJ_ID, 2202) V INTO YEAR0F;
            SELECT V.V FROM VAL_GET(:V$OBJ_ID, 2205) V INTO YEAR0P;
        END

        V$Y = EXTRACT(YEAR FROM CURRENT_DATE);
        V$DT = '1.09.' || V$Y;
        
        IF (CURRENT_DATE < V$DT) THEN
        BEGIN
            V$YEAR_VAL = (V$Y - 2) || '-' || (V$Y - 1);
        END
        ELSE
        BEGIN
            V$YEAR_VAL = (V$Y -1) || '-' || V$Y ;
        END

        FOR
            SELECT L271.OBJ_ID
            FROM LINKS L238
            
            JOIN LINKS L271
            ON L271.OBJ_TYPE_ID = 271
            AND L271.DATE_DEL IS NULL
            AND L271.PARENT_ID = L238.OBJ_ID
            
            JOIN VALS V2207
            ON  V2207.PARAM_ID = 2207
            AND V2207.IS_DEL = 0
            AND V2207.OBJ_ID = L271.OBJ_ID
            AND V2207.VAL LIKE :V$YEAR_VAL
            
            WHERE L238.OBJ_TYPE_ID = 238
            AND L238.DATE_DEL IS NULL
            AND L238.PARENT_ID = :V$OU_ID
            INTO :V$OBJ_ID
        DO
        BEGIN
            SELECT V.V FROM VAL_GET(:V$OBJ_ID, 2208) V INTO YEAR1F;
            SELECT V.V FROM VAL_GET(:V$OBJ_ID, 2211) V INTO YEAR1P;
        END

        V$Y = EXTRACT(YEAR FROM CURRENT_DATE);
        V$DT = '1.09.' || V$Y;
        
        IF (CURRENT_DATE < V$DT) THEN
        BEGIN
            V$YEAR_VAL = (V$Y - 3) || '-' || (V$Y - 2);
        END
        ELSE
        BEGIN
            V$YEAR_VAL = (V$Y - 2) || '-' || (V$Y - 1) ;
        END

        FOR
            SELECT L271.OBJ_ID
            FROM LINKS L238
            
            JOIN LINKS L271
            ON L271.OBJ_TYPE_ID = 271
            AND L271.DATE_DEL IS NULL
            AND L271.PARENT_ID = L238.OBJ_ID
            
            JOIN VALS V2207
            ON  V2207.PARAM_ID = 2207
            AND V2207.IS_DEL = 0
            AND V2207.OBJ_ID = L271.OBJ_ID
            AND V2207.VAL LIKE :V$YEAR_VAL
            
            WHERE L238.OBJ_TYPE_ID = 238
            AND L238.DATE_DEL IS NULL
            AND L238.PARENT_ID = :V$OU_ID
            INTO :V$OBJ_ID
        DO
        BEGIN
            SELECT V.V FROM VAL_GET(:V$OBJ_ID, 2208) V INTO YEAR2F;
            SELECT V.V FROM VAL_GET(:V$OBJ_ID, 2211) V INTO YEAR2P;
        END
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PLAN_REPORT_YEARS_DOWN_3_GET (
    I$BEGIN VARCHAR(200),
    I$END VARCHAR(200))
RETURNS (
    YEAR11 VARCHAR(50),
    YEAR12 VARCHAR(50),
    YEAR21 VARCHAR(50),
    YEAR22 VARCHAR(50),
    YEAR31 VARCHAR(50),
    YEAR32 VARCHAR(50))
AS
declare variable V$DT date;
declare variable V$Y integer;
BEGIN
    V$Y = EXTRACT(YEAR FROM CURRENT_DATE);
    V$DT = '1.09.' || V$Y;
    
    IF (CURRENT_DATE < V$DT) THEN
    BEGIN
        YEAR11 = I$BEGIN || (V$Y - 1) || '-' || V$Y || I$END;
        YEAR12 = I$BEGIN || (V$Y - 2) || '-' || (V$Y - 1) || I$END;
        YEAR21 = I$BEGIN || (V$Y - 3) || '-' || (V$Y - 2) || I$END;
        YEAR22 = I$BEGIN || (V$Y - 1) || '-' || V$Y || I$END;
        YEAR31 = I$BEGIN || (V$Y - 2) || '-' || (V$Y - 1) || I$END;
        YEAR32 = I$BEGIN || (V$Y - 3) || '-' || (V$Y - 2) || I$END;
    END
    ELSE
    BEGIN
        YEAR11 = I$BEGIN || (V$Y) || '-' || (V$Y + 1) || I$END;
        YEAR12 = I$BEGIN || (V$Y - 1) || '-' || (V$Y) || I$END;
        YEAR21 = I$BEGIN || (V$Y - 2) || '-' || (V$Y - 1) || I$END;
        YEAR22 = I$BEGIN || (V$Y) || '-' || (V$Y + 1) || I$END;
        YEAR31 = I$BEGIN || (V$Y - 1) || '-' || (V$Y) || I$END;
        YEAR32 = I$BEGIN || (V$Y - 2) || '-' || (V$Y - 1) || I$END;
    END
    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PLAN_REPORT_YEARS_UP_4_GET (
    I$BEGIN VARCHAR(200),
    I$END VARCHAR(200))
RETURNS (
    YEAR1 VARCHAR(50),
    YEAR2 VARCHAR(50),
    YEAR3 VARCHAR(50),
    YEAR4 VARCHAR(50))
AS
declare variable V$DT date;
declare variable V$Y integer;
BEGIN
    V$Y = EXTRACT(YEAR FROM CURRENT_DATE);
    V$DT = '1.09.' || V$Y;
    
    IF (CURRENT_DATE < V$DT) THEN
    BEGIN
        YEAR1 = I$BEGIN || (V$Y - 1) || '-' || V$Y || I$END;
        YEAR2 = I$BEGIN || (V$Y) || '-' || (V$Y + 1) || I$END;
        YEAR3 = I$BEGIN || (V$Y + 1) || '-' || (V$Y + 2) || I$END;
        YEAR4 = I$BEGIN || (V$Y + 2) || '-' || (V$Y + 3) || I$END;
    END
    ELSE
    BEGIN
        YEAR1 = I$BEGIN || (V$Y) || '-' || (V$Y + 1) || I$END;
        YEAR2 = I$BEGIN || (V$Y + 1) || '-' || (V$Y + 2) || I$END;
        YEAR3 = I$BEGIN || (V$Y + 2) || '-' || (V$Y + 3) || I$END;
        YEAR4 = I$BEGIN || (V$Y + 3) || '-' || (V$Y + 4) || I$END;
    END
    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PLAN_RESOURCES_SELECT (
    I$PLAN_ID BIGINT,
    I$SUBJECT_ID BIGINT,
    I$STAGE_ID BIGINT,
    I$RES_TYPE SMALLINT,
    I$USER_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    RES_ID BIGINT,
    CAPTION VARCHAR(4000),
    SUBJECT_NAME VARCHAR(1000),
    AVAIL_QTY DOUBLE PRECISION,
    QTY DOUBLE PRECISION)
AS
declare variable V$LOAD_ID bigint;
declare variable V$STAGE bigint;
declare variable V$OU_ID bigint;
declare variable V$SUBJECT_ID bigint;
declare variable V$SRC_SUBJECT_ID bigint;
declare variable V$OU_LICENCE_TYPE char(1);
declare variable V$STAGES varchar(100);
declare variable V$ST1 integer;
declare variable V$ST2 integer;
declare variable V$USED_QTY double precision;
begin

  V$OU_LICENCE_TYPE = (SELECT STATUS FROM OU_LICENCE_TYPE);

  SELECT L.OBJ_ID, LV.COST, S.SUBJECT_ID, S.SRC_SUBJECT_ID
  FROM PLAN_LOADS L
  JOIN PLAN_SUBJECTS S ON S.OBJ_ID = L.SUBJECT_ID AND S.DATE_DEL IS NULL AND S.PLAN_ID = :I$PLAN_ID
  JOIN VALL V381 ON V381.OBJ_ID = L.STAGE_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V381.LISTVAL_ID
  WHERE L.DATE_DEL IS NULL AND L.SUBJECT_ID = :I$SUBJECT_ID AND L.STAGE_ID = :I$STAGE_ID
  INTO :V$LOAD_ID, :V$STAGE, :V$SUBJECT_ID, :V$SRC_SUBJECT_ID;

  IF(V$LOAD_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Учебный план, этап или предмет не найдены или были удалены';

  V$OU_ID = (SELECT FIRST 1 OBJ_ID FROM OBJECT_PARENTS_GET(:I$PLAN_ID, 2));

  -- Сначала выдаем те ресурсы, которые и так назначены
  FOR
    SELECT R.OBJ_ID, R.RES_ID, R.QTY, C.CAPTION, COALESCE(VQ.VAL, 1)
    FROM PLAN_RESOURCES R
    -- Название
    LEFT JOIN OBJECT_CAPTION_GET(R.RES_ID) C ON 1 = 1
    -- Количество экземпляров или копий
    LEFT JOIN VALI VQ ON VQ.OBJ_ID = R.RES_ID AND VQ.PARAM_ID IN (605, 607, 648, 640) AND VQ.IS_DEL = 0
    WHERE R.DATE_DEL IS NULL AND R.LOAD_ID = :V$LOAD_ID AND R.RES_TYPE_ID = :I$RES_TYPE
    INTO :OBJ_ID, :RES_ID, :QTY, :CAPTION, :AVAIL_QTY
  DO
  BEGIN
    -- Получаем наименование ресурса
    IF(I$RES_TYPE = 1) THEN
    BEGIN
      -- Учебная программа
      -- !!!
    END
    ELSE IF(I$RES_TYPE IN (2, 3, 4)) THEN
    BEGIN
      -- Печатный ресурс
    END
    ELSE IF(I$RES_TYPE = 5) THEN
    BEGIN
      -- Электронный ресурс
    END

    -- Вычитаем количество, занятое в других местах
    -- !!!

    SUSPEND;
  END

  -- Показываем доступные ресурсы в этой ОУ, не задействованные в данном месте
  IF(I$RES_TYPE = 1) THEN
  BEGIN
  END
  ELSE IF(I$RES_TYPE IN (2, 3, 4)) THEN
  BEGIN
    -- Печатные издания
    FOR
      SELECT NULL, L107.OBJ_ID, 0, C.CAPTION, VQ.VAL, CS.CAPTION, COALESCE(V2658.VAL, '')
      FROM LINKS L105
      JOIN LINKS L107 ON L107.PARENT_ID = L105.OBJ_ID AND L107.OBJ_TYPE_ID = 107 AND L107.DATE_DEL IS NULL
      -- Не задействован
      LEFT JOIN PLAN_RESOURCES R ON R.LOAD_ID = :V$LOAD_ID AND R.DATE_DEL IS NULL AND R.RES_ID = L107.OBJ_ID AND R.RES_TYPE_ID = :I$RES_TYPE
      -- Тип = указанный
      JOIN VALL V653 ON V653.OBJ_ID = L107.OBJ_ID AND V653.PARAM_ID = 653 AND V653.IS_DEL = 0 AND V653.LISTVAL_ID = 2095 + :I$RES_TYPE
      -- Предмет = указанный для школ, любой для ЦОПП
      LEFT JOIN VALR V654 ON V654.OBJ_ID = L107.OBJ_ID AND V654.PARAM_ID = 654 AND V654.IS_DEL = 0
      -- Параллель
      LEFT JOIN VALS V2658 ON V2658.OBJ_ID = L107.OBJ_ID AND V2658.PARAM_ID = 2658 AND V2658.IS_DEL = 0
      -- Название
      LEFT JOIN OBJECT_CAPTION_GET(L107.OBJ_ID) C ON 1 = 1
      -- Название предмета
      LEFT JOIN OBJECT_CAPTION_GET(V654.VAL) CS ON 1 = 1
      -- Количество экземпляров или копий
      LEFT JOIN VALI VQ ON VQ.OBJ_ID = L107.OBJ_ID AND VQ.PARAM_ID IN (648, 640) AND VQ.IS_DEL = 0
      -- Всегда разрешаем выбор всех предметов в колледжах и в индивидуальном проекте
      WHERE L105.PARENT_ID = :V$OU_ID AND L105.OBJ_TYPE_ID = 105 AND L105.DATE_DEL IS NULL AND R.OBJ_ID IS NULL
        AND (:V$OU_LICENCE_TYPE = 'C' OR V654.VAL = :V$SUBJECT_ID OR :V$SUBJECT_ID = 34651)
      INTO :OBJ_ID, :RES_ID, :QTY, :CAPTION, :AVAIL_QTY, :SUBJECT_NAME, :V$STAGES
    DO
    BEGIN
      -- Сколько занято в других УП или нагрузках ? вычитаем его из доступного количества
      -- Но для индивидуального проекта в том же УП оставляем учебники доступными для выбора
      SELECT COALESCE(SUM(R.QTY), 0)
      FROM PLAN_RESOURCES R
      JOIN PLAN_LOADS L ON L.OBJ_ID = R.LOAD_ID AND L.DATE_DEL IS NULL
      JOIN PLAN_SUBJECTS S ON S.OBJ_ID = L.SUBJECT_ID AND S.DATE_DEL IS NULL AND (:V$SUBJECT_ID <> 34651 OR S.PLAN_ID <> :I$PLAN_ID)
      WHERE R.DATE_DEL IS NULL AND R.RES_ID = :RES_ID
      INTO :V$USED_QTY;

      AVAIL_QTY = AVAIL_QTY - V$USED_QTY;
      IF(AVAIL_QTY < 0) THEN AVAIL_QTY = 0;

      -- Проверяем параллель
      IF(V$STAGES = '') THEN
      BEGIN
        V$ST1 = -1;
        V$ST2 = -1;
      END
      ELSE IF(POSITION('-' IN V$STAGES) > 0) THEN
      BEGIN
        V$ST1 = SUBSTRING(V$STAGES FROM 1 FOR POSITION('-' IN V$STAGES) - 1);
        V$ST2 = SUBSTRING(V$STAGES FROM POSITION('-' IN V$STAGES) + 1);
      END
      ELSE
      BEGIN
        V$ST1 = V$STAGES;
        V$ST2 = V$STAGES;
      END

      IF(V$STAGE >= V$ST1 AND V$STAGE <= V$ST2) THEN SUSPEND;
    END
  END
  ELSE IF(I$RES_TYPE = 5) THEN
  BEGIN
    -- Электронные ресурсы
    FOR
      SELECT NULL, L106.OBJ_ID, 0, C.CAPTION, VQ.VAL
      FROM LINKS L104
      JOIN LINKS L106 ON L106.PARENT_ID = L104.OBJ_ID AND L106.OBJ_TYPE_ID = 106 AND L106.DATE_DEL IS NULL
      -- Не задействован
      LEFT JOIN PLAN_RESOURCES R ON R.LOAD_ID = :V$LOAD_ID AND R.DATE_DEL IS NULL AND R.RES_ID = L106.OBJ_ID AND R.RES_TYPE_ID = :I$RES_TYPE
      -- Название
      LEFT JOIN OBJECT_CAPTION_GET(L106.OBJ_ID) C ON 1 = 1
      -- Количество экземпляров или копий
      LEFT JOIN VALI VQ ON VQ.OBJ_ID = L106.OBJ_ID AND VQ.PARAM_ID IN (648, 640) AND VQ.IS_DEL = 0
      WHERE L104.PARENT_ID = :V$OU_ID AND L104.OBJ_TYPE_ID = 104 AND L104.DATE_DEL IS NULL AND R.OBJ_ID IS NULL
      INTO :OBJ_ID, :RES_ID, :QTY, :CAPTION, :AVAIL_QTY
    DO
    BEGIN
      SUSPEND;
    END
  END
  ELSE IF(I$RES_TYPE = 6) THEN
  BEGIN
    -- ТСО
    FOR
      SELECT NULL, L95.OBJ_ID, 0, C.CAPTION, VQ.VAL
      FROM LINKS L23
      JOIN LINKS L95 ON L95.PARENT_ID = L23.OBJ_ID AND L95.OBJ_TYPE_ID = 95 AND L95.DATE_DEL IS NULL
      -- Не задействован
      LEFT JOIN PLAN_RESOURCES R ON R.LOAD_ID = :V$LOAD_ID AND R.DATE_DEL IS NULL AND R.RES_ID = L95.OBJ_ID AND R.RES_TYPE_ID = :I$RES_TYPE
      -- Название
      LEFT JOIN OBJECT_CAPTION_GET(L95.OBJ_ID) C ON 1 = 1
      -- Количество экземпляров или копий
      LEFT JOIN VALI VQ ON VQ.OBJ_ID = L95.OBJ_ID AND VQ.PARAM_ID = 605 AND VQ.IS_DEL = 0
      WHERE L23.PARENT_ID = :V$OU_ID AND L23.OBJ_TYPE_ID = 23 AND L23.DATE_DEL IS NULL AND R.OBJ_ID IS NULL
      INTO :OBJ_ID, :RES_ID, :QTY, :CAPTION, :AVAIL_QTY
    DO
    BEGIN
      SUSPEND;
    END
  END
  ELSE IF(I$RES_TYPE = 7) THEN
  BEGIN
    -- Учебное оборудование
    FOR
      SELECT NULL, L97.OBJ_ID, 0, C.CAPTION, VQ.VAL, IIF(V643.VAL IS NULL, '', CS.CAPTION)
      FROM LINKS L92
      JOIN LINKS L97 ON L97.PARENT_ID = L92.OBJ_ID AND L97.OBJ_TYPE_ID = 97 AND L97.DATE_DEL IS NULL
      -- Не задействован
      LEFT JOIN PLAN_RESOURCES R ON R.LOAD_ID = :V$LOAD_ID AND R.DATE_DEL IS NULL AND R.RES_ID = L97.OBJ_ID AND R.RES_TYPE_ID = :I$RES_TYPE
      -- Название
      LEFT JOIN OBJECT_CAPTION_GET(L97.OBJ_ID) C ON 1 = 1
      -- Количество экземпляров или копий
      LEFT JOIN VALI VQ ON VQ.OBJ_ID = L97.OBJ_ID AND VQ.PARAM_ID = 607 AND VQ.IS_DEL = 0
      -- Предмет
      LEFT JOIN VALR V643 ON V643.OBJ_ID = L97.OBJ_ID AND V643.PARAM_ID = 643 AND V643.IS_DEL = 0
      LEFT JOIN OBJECT_CAPTION_GET(V643.VAL) CS ON 1 = 1
      WHERE L92.PARENT_ID = :V$OU_ID AND L92.OBJ_TYPE_ID = 92 AND L92.DATE_DEL IS NULL AND R.OBJ_ID IS NULL
      INTO :OBJ_ID, :RES_ID, :QTY, :CAPTION, :AVAIL_QTY, :SUBJECT_NAME
    DO
    BEGIN
      SUSPEND;
    END
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PLAN_RESOURCE_SAVE (
    I$SUBJECT_ID BIGINT NOT NULL,
    I$STAGE_ID BIGINT,
    I$RES_TYPE SMALLINT NOT NULL,
    I$RES_ID BIGINT NOT NULL,
    I$QTY DOUBLE PRECISION NOT NULL,
    I$USER_ID VARCHAR(40))
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$LOAD_ID bigint;
declare variable V$PLAN_ID bigint;
declare variable V$TYPE_ID bigint;
declare variable V$QTY double precision;
declare variable V$VP_TYPE bigint;
declare variable V$OP_YEAR integer;
declare variable V$EXCLUDE_YEAR integer;
declare variable V$GEN bigint;
declare variable V$MULTIPLIER bigint;
declare variable V$EXCLUDE varchar(40);
begin

  IF(I$QTY < 0) THEN EXCEPTION DATA_ERROR 'Отрицательное количество недопустимо';

  -- Проверяем, что ресурс имеется и требуемого типа
  SELECT FIRST 1 LR.OBJ_TYPE_ID, COALESCE(VQ.VAL, 1), V653.LISTVAL_ID
  FROM LINKS LR
  LEFT JOIN VALI VQ ON VQ.OBJ_ID = LR.OBJ_ID AND VQ.PARAM_ID IN (605, 607, 648, 640) AND VQ.IS_DEL = 0
  LEFT JOIN VALL V653 ON V653.OBJ_ID = LR.OBJ_ID AND V653.PARAM_ID = 653 AND V653.IS_DEL = 0
  WHERE LR.PARENT_TYPE_ID IN (23, 92, 104, 105) AND LR.OBJ_ID = :I$RES_ID AND LR.DATE_DEL IS NULL
  INTO :V$TYPE_ID, :V$QTY, :V$VP_TYPE;

  IF(V$TYPE_ID IS NULL AND I$QTY > 0) THEN EXCEPTION DATA_ERROR 'Ресурс не найден';
  IF(V$QTY > 0 AND I$RES_TYPE IN (2, 3, 4) AND V$VP_TYPE <> 2095 + I$RES_TYPE) THEN EXCEPTION DATA_ERROR 'Тип ресурса не соответствует или был изменен';

  -- Проверяем учебный план
  SELECT LP.OBJ_ID, L.OBJ_ID
  FROM PLAN_LOADS L
  JOIN PLAN_SUBJECTS S ON S.OBJ_ID = L.SUBJECT_ID AND S.DATE_DEL IS NULL
  JOIN LINKS LP ON LP.OBJ_ID = S.PLAN_ID AND LP.PARENT_TYPE_ID IN (57) AND LP.DATE_DEL IS NULL
  WHERE L.SUBJECT_ID = :I$SUBJECT_ID AND L.STAGE_ID = :I$STAGE_ID AND L.DATE_DEL IS NULL
  INTO :V$PLAN_ID, :V$LOAD_ID;

  IF(V$PLAN_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Учебный план, этап плана или предмет (дисциплина) не найдены';

  -- Проверка прав доступа к приложению и утвержденного статуса
  SELECT FIRST 1 GEN, MULTIPLIER
  FROM GEN
  INTO :V$GEN, :V$MULTIPLIER;

  IF(V$PLAN_ID / V$MULTIPLIER <> V$GEN) THEN EXCEPTION DATA_ERROR 'Нельзя изменять данный учебный план';

  IF(I$QTY < 0.01) THEN
  BEGIN
    -- Удалить
    SELECT FIRST 1 R.OBJ_ID
    FROM PLAN_RESOURCES R
    WHERE R.LOAD_ID = :V$LOAD_ID AND R.RES_ID = :I$RES_ID AND R.DATE_DEL IS NULL
    INTO :OBJ_ID;

    IF(OBJ_ID IS NOT NULL) THEN
    BEGIN
      UPDATE PLAN_RESOURCES
      SET DATE_DEL = CURRENT_TIMESTAMP
      WHERE OBJ_ID = :OBJ_ID;
    END
  END
  ELSE
  BEGIN
    -- Назначить или изменить
    IF(I$QTY > V$QTY) THEN EXCEPTION DATA_ERROR 'Нельзя выбрать больше ресурсов, чем имеется';

    -- Запрет выбирать старые учебники
    IF(V$TYPE_ID = 107) THEN
    BEGIN

      SELECT V3115.VAL
      FROM LINKS LP57
      JOIN VALI V3115 ON V3115.OBJ_ID = LP57.PARENT_ID AND V3115.PARAM_ID = 3115 AND V3115.IS_DEL = 0
      WHERE LP57.OBJ_ID = :V$PLAN_ID AND LP57.PARENT_TYPE_ID = 57 AND LP57.DATE_DEL IS NULL
      INTO :V$OP_YEAR;

      SELECT I.VAL
      FROM LIB_FP_BOOK_INFO_GET(:I$RES_ID, 2656) I
      INTO :V$EXCLUDE;

      IF(V$OP_YEAR IS NULL) THEN EXCEPTION DATA_ERROR 'Не указан год утверждения образовательной программы';

      IF(V$EXCLUDE <> '') THEN
      BEGIN
        IF(CHAR_LENGTH(V$EXCLUDE) = 4) THEN
        BEGIN
          V$EXCLUDE_YEAR = V$EXCLUDE; -- указан год, старая схема
        END
        ELSE
        BEGIN
          -- указана дата, исключается все обычно маем, берем год по году даты
          V$EXCLUDE_YEAR = SUBSTRING(V$EXCLUDE FROM 7);
        END
        IF(V$OP_YEAR >= V$EXCLUDE_YEAR) THEN EXCEPTION DATA_ERROR 'Нельзя использовать учебник, исключенный из ФПУ, для новых образовательных программ';
      END

    END

    SELECT FIRST 1 R.OBJ_ID, R.QTY
    FROM PLAN_RESOURCES R
    WHERE R.LOAD_ID = :V$LOAD_ID AND R.RES_ID = :I$RES_ID AND R.DATE_DEL IS NULL
    INTO :OBJ_ID, :V$QTY;

    IF(OBJ_ID IS NULL) THEN
    BEGIN
      INSERT INTO PLAN_RESOURCES
      (LOAD_ID, RES_TYPE_ID, RES_ID, QTY)
      VALUES (:V$LOAD_ID, :I$RES_TYPE, :I$RES_ID, :I$QTY)
      RETURNING OBJ_ID INTO :OBJ_ID;
    END
    ELSE IF(V$QTY <> I$QTY) THEN
    BEGIN
      UPDATE PLAN_RESOURCES
      SET QTY = :I$QTY
      WHERE OBJ_ID = :OBJ_ID;
    END
  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PLAN_RES_GET (
    I$OBJ_ID BIGINT,
    I$RES_ID INTEGER,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(4000))
AS
declare variable V$STAGE_ID bigint;
declare variable V$SUBJECT_ID bigint;
declare variable V$OBJ_ID bigint;
declare variable V$RES_ID bigint;
declare variable V$STAGE bigint;
declare variable V$QTY double precision;
begin

  -- Сначала отдаем все нагрузки
  FOR
    SELECT TAG_NAME, VAL
    FROM PLAN_GET(:I$OBJ_ID, NULL, :I$USER_ID)
    INTO :TAG_NAME, :VAL
  DO
  BEGIN
    SUSPEND;
  END

  -- Количества учеников
  TAG_NAME = 'needqty::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L.SUBJECT_ID, L.STAGE_ID
    FROM PLAN_SUBJECTS S
    JOIN PLAN_LOADS L ON L.DATE_DEL IS NULL AND L.SUBJECT_ID = S.OBJ_ID
    WHERE S.DATE_DEL IS NULL AND S.PLAN_ID = :I$OBJ_ID AND S.ROW_TYPE = 10
    INTO :V$SUBJECT_ID, :V$STAGE_ID
  DO
  BEGIN
    TAG_NAME = 'needqty:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'needqty:r:subject_id';
    VAL = V$SUBJECT_ID;
    SUSPEND;
    TAG_NAME = 'needqty:r:stage_id';
    VAL = V$STAGE_ID;
    SUSPEND;

    TAG_NAME = 'needqty:r:value';
    SELECT COUNT(*)
    FROM LINKS L256
    JOIN LINKS L10 ON L10.PARENT_ID = L256.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    WHERE L256.PARENT_ID = :V$STAGE_ID AND L256.OBJ_TYPE_ID = 256 AND L256.DATE_DEL IS NULL
    INTO :VAL;
    SUSPEND;
  END

  -- Выдаем данные по каждой строке
  TAG_NAME = 'resources::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L.SUBJECT_ID, L.STAGE_ID, R.OBJ_ID, R.RES_ID, R.QTY, V381.LISTVAL_ID
    FROM PLAN_SUBJECTS S
    JOIN PLAN_LOADS L ON L.DATE_DEL IS NULL AND L.SUBJECT_ID = S.OBJ_ID
    JOIN VALL V381 ON V381.OBJ_ID = L.STAGE_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
    JOIN PLAN_RESOURCES R ON R.DATE_DEL IS NULL AND R.LOAD_ID = L.OBJ_ID AND R.RES_TYPE_ID = :I$RES_ID
    WHERE S.DATE_DEL IS NULL AND S.PLAN_ID = :I$OBJ_ID AND S.ROW_TYPE = 10
    INTO :V$SUBJECT_ID, :V$STAGE_ID, :V$OBJ_ID, :V$RES_ID, :V$QTY, :V$STAGE
  DO
  BEGIN
    TAG_NAME = 'resources:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'resources:r:subject_id';
    VAL = V$SUBJECT_ID;
    SUSPEND;
    TAG_NAME = 'resources:r:stage_id';
    VAL = V$STAGE_ID;
    SUSPEND;
    TAG_NAME = 'resources:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'resources:r:res_id';
    VAL = V$RES_ID;
    SUSPEND;
    TAG_NAME = 'resources:r:qty';
    VAL = V$QTY;
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PLAN_SAVE_LOAD (
    I$SUBJECT_ID BIGINT,
    I$STAGE_ID BIGINT,
    I$WEEKS SMALLINT,
    I$HOURS1 FLOAT,
    I$HOURS2 FLOAT,
    I$CONTROL1 BIGINT,
    I$CONTROL2 BIGINT,
    I$HTHEORY1 FLOAT,
    I$HPR1 FLOAT,
    I$HDX1 FLOAT,
    I$HIND1 FLOAT,
    I$HMAX FLOAT,
    I$HCR1 FLOAT,
    I$HATT1 FLOAT,
    I$HGIA FLOAT,
    I$HREST FLOAT,
    I$USER_ID VARCHAR(40))
AS
declare variable V$OU_TYPE varchar(2);
declare variable V$OBJ_ID bigint;
declare variable V$LEVEL_ID bigint;
declare variable V$DATE_DEL timestamp;
declare variable V$RT smallint;
declare variable V$SUBJECT_ID bigint;
declare variable V$WEEKS smallint;
declare variable V$LOAD_HOURS_N float;
declare variable V$LOAD_HOURS float;
declare variable V$LOAD_HOURS_S1 float;
declare variable V$LOAD_HOURS_S2 float;
declare variable V$CONTROL_Q1 bigint;
declare variable V$CONTROL_Q2 bigint;
declare variable V$HOURS_THEORY1 float;
declare variable V$HOURS_PR1 float;
declare variable V$HOURS_DX1 float;
declare variable V$HOURS_IND1 float;
declare variable V$PLAN_ID bigint;
declare variable V$STAGE_ID bigint;
declare variable V$HOURS double precision;
declare variable V$HMAX float;
declare variable V$HCR1 float;
declare variable V$HATT1 float;
declare variable V$HGIA float;
declare variable V$HREST float;
declare variable V$STATUS bigint;
declare variable V$PARENT_ID bigint;
begin

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = -1;

  -- stage_id = null - суммарная строка по разделу
  IF(I$STAGE_ID = 0) THEN I$STAGE_ID = NULL;

  V$OU_TYPE = (SELECT STATUS FROM OU_LICENCE_TYPE);

  SELECT S.ROW_TYPE, S.SUBJECT_ID, S.PLAN_ID, S.PARENT_ID
  FROM PLAN_SUBJECTS S
  WHERE S.OBJ_ID = :I$SUBJECT_ID
  INTO :V$RT, :V$SUBJECT_ID, :V$PLAN_ID, :V$PARENT_ID;

  SELECT FIRST 1 V1594.LISTVAL_ID
  FROM LINKS LP57
  JOIN VALL V1594 ON V1594.OBJ_ID = LP57.PARENT_ID AND V1594.PARAM_ID = 1594 AND V1594.IS_DEL = 0
  WHERE LP57.OBJ_ID = :V$PLAN_ID AND LP57.PARENT_TYPE_ID = 57 AND LP57.DATE_DEL IS NULL
  INTO :V$LEVEL_ID;

  -- -1 в длительности недели нужен чтобы занулить дни недели в этапе
  IF(V$LEVEL_ID IS NULL) THEN
  BEGIN
    SELECT V3345.LISTVAL_ID
    FROM VALL V3345
    WHERE V3345.OBJ_ID = :V$PLAN_ID AND V3345.PARAM_ID = 3345 AND V3345.IS_DEL = 0
    INTO :V$LEVEL_ID;
  END

  -- Проверяем статус УП
  SELECT FIRST 1 V3013.LISTVAL_ID
  FROM VALL V3013
  WHERE V3013.OBJ_ID = :V$PLAN_ID AND V3013.PARAM_ID = 3013 AND V3013.IS_DEL = 0
  INTO :V$STATUS;

  SELECT FIRST 1 L.OBJ_ID, L.DATE_DEL, L.WEEKS, L.LOAD_HOURS, L.LOAD_HOURS_S1, L.LOAD_HOURS_S2, L.CONTROL_Q1, L.CONTROL_Q2,
    L.HOURS_THEORY1, L.HOURS_PR1, L.HOURS_DX1, L.HOURS_IND1, L.HOURS_MAX, L.HOURS_CR1, L.HOURS_ATT1, L.HOURS_GIA, L.HOURS_REST
  FROM PLAN_LOADS L
  WHERE L.SUBJECT_ID = :I$SUBJECT_ID AND (L.STAGE_ID = :I$STAGE_ID OR (L.STAGE_ID IS NULL AND :I$STAGE_ID IS NULL))
  INTO :V$OBJ_ID, :V$DATE_DEL, :V$WEEKS, :V$LOAD_HOURS, :V$LOAD_HOURS_S1, :V$LOAD_HOURS_S2, :V$CONTROL_Q1, :V$CONTROL_Q2,
    :V$HOURS_THEORY1, :V$HOURS_PR1, :V$HOURS_DX1, :V$HOURS_IND1, :V$HMAX, :V$HCR1, :V$HATT1, :V$HGIA, :V$HREST;

  IF(I$HOURS1 <= 0) THEN I$HOURS1 = NULL;
  IF(I$HOURS2 <= 0) THEN I$HOURS2 = NULL;
  -- Для СПО количество недель по этапу ставим 1, они вносятся целиком на курс
  IF(I$WEEKS <= 0) THEN I$WEEKS = NULL;
  IF(V$LEVEL_ID = 5346 AND I$STAGE_ID IS NOT NULL) THEN I$WEEKS = 1;
  IF(I$CONTROL1 IS NULL OR I$CONTROL1 = 0) THEN I$CONTROL1 = 5254;
  IF(I$CONTROL2 IS NULL OR I$CONTROL2 = 0) THEN I$CONTROL2 = 5254;
  IF(I$CONTROL1 <> 5254 AND (I$HOURS1 = 0 OR I$HOURS1 IS NULL)) THEN EXCEPTION DATA_ERROR 'Нельзя установить контроль без часов нагрузки';
  IF(I$CONTROL2 <> 5254 AND (I$HOURS2 = 0 OR I$HOURS2 IS NULL)) THEN EXCEPTION DATA_ERROR 'Нельзя установить контроль без часов нагрузки';

  IF(V$RT = 10 AND I$STAGE_ID IS NOT NULL AND I$WEEKS IS NULL AND (I$HOURS1 IS NOT NULL OR I$HOURS2 IS NOT NULL)) THEN EXCEPTION DATA_ERROR 'Нельзя указать часы нагрузки без количества недель обучения для ' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$SUBJECT_ID));

  -- Для ДПО проверяем соответствие часов
  IF(V$OU_TYPE = 'P') THEN
  BEGIN
    IF(COALESCE(I$HOURS1, 0) < COALESCE(I$HTHEORY1, 0) + COALESCE(I$HPR1, 0) + COALESCE(I$HDX1, 0) + COALESCE(I$HIND1, 0))
      THEN EXCEPTION DATA_ERROR 'Общее количество часов в строке не соответствует разбивке по видам занятий';
  END

  V$LOAD_HOURS_N = COALESCE(I$HOURS1, 0) + COALESCE(I$HOURS2, 0);

  IF(I$HOURS1 IS NULL AND I$HOURS2 IS NULL AND I$WEEKS IS NULL AND I$STAGE_ID IS NOT NULL) THEN
  BEGIN
    -- Удаляем запись и чистим ресурсы, но только для рядовых строк - суммарные строки по разделу оставляем
    IF(V$OBJ_ID IS NOT NULL AND V$DATE_DEL IS NULL) THEN
    BEGIN
      -- Нельзя удалять часы, если созданы журналы по данному предмету и этому этапу
      SELECT COALESCE(SUM(PL.LOAD_HOURS), 0)
      FROM PLAN_SUBJECTS PS
      JOIN PLAN_LOADS PL ON PL.DATE_DEL IS NULL AND PL.SUBJECT_ID = PS.OBJ_ID AND PL.SUBJECT_ID <> :I$SUBJECT_ID AND PL.STAGE_ID = :I$STAGE_ID
      WHERE PS.DATE_DEL IS NULL AND PS.SUBJECT_ID = :V$SUBJECT_ID AND PS.ROW_TYPE = 10 AND PS.PLAN_ID = :V$PLAN_ID
      INTO :V$HOURS;

      IF(V$HOURS = 0) THEN
      BEGIN
        SELECT V381.LISTVAL_ID
        FROM VALL V381
        WHERE V381.OBJ_ID = :I$STAGE_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
        INTO :V$STAGE_ID;

        IF(EXISTS(
          SELECT FIRST 1 1
          FROM CJ2_JOURNAL J
          WHERE J.DATE_DEL IS NULL AND J.SUBJECT_ID = :V$SUBJECT_ID AND J.STAGE_INDEX = :V$STAGE_ID AND J.REF_ID = :V$PLAN_ID
        ))
        THEN EXCEPTION DATA_ERROR 'Нельзя обнулять нагрузку, когда уже созданы журналы для данного УП для данного сечения предмет-этап';
      END

      UPDATE PLAN_LOADS
      SET DATE_DEL = CURRENT_TIMESTAMP
      WHERE OBJ_ID = :V$OBJ_ID;

      UPDATE PLAN_RESOURCES
      SET DATE_DEL = CURRENT_TIMESTAMP
      WHERE LOAD_ID = :V$OBJ_ID AND DATE_DEL IS NULL;
    END
  END
  ELSE
  BEGIN
    -- Добавляем или обновляем
    IF(I$WEEKS <= 0) THEN EXCEPTION DATA_ERROR 'Число недель должно быть положительным';

    IF(V$OBJ_ID IS NULL) THEN
    BEGIN
      INSERT INTO PLAN_LOADS
      (SUBJECT_ID, STAGE_ID, WEEKS, LOAD_HOURS, LOAD_HOURS_S1, LOAD_HOURS_S2, CONTROL_Q1, CONTROL_Q2,
        HOURS_THEORY1, HOURS_PR1, HOURS_DX1, HOURS_IND1, HOURS_MAX, HOURS_CR1, HOURS_ATT1, HOURS_GIA, HOURS_REST)
      VALUES (:I$SUBJECT_ID, :I$STAGE_ID, :I$WEEKS, :V$LOAD_HOURS_N, :I$HOURS1, :I$HOURS2, :I$CONTROL1, :I$CONTROL2,
        :I$HTHEORY1, :I$HPR1, :I$HDX1, :I$HIND1, :I$HMAX, :I$HCR1, :I$HATT1, :I$HGIA, :I$HREST);

      -- Логгируем только предметы
      IF(V$STATUS = 11715 AND V$RT = 10) THEN
      INSERT INTO HISTVALS
      (TABLE_NAME, OBJ_ID, USER_ID, PARAM_ID, OPT_ID, PARENT_ID, OLD_VAL, VAL)
      VALUES ('PLAN', :V$PLAN_ID, :I$USER_ID, :V$PARENT_ID, :V$SUBJECT_ID, :V$PARENT_ID, 'Задание нагрузки по ' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$SUBJECT_ID)),
        (SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$STAGE_ID)) || ', ' || :V$LOAD_HOURS_N);

    END
    ELSE IF(V$DATE_DEL IS NOT NULL OR COALESCE(I$WEEKS, 0) <> COALESCE(V$WEEKS, 0) OR COALESCE(V$LOAD_HOURS_N, 0) <> COALESCE(V$LOAD_HOURS, 0)
      OR COALESCE(I$HOURS1, 0) <> COALESCE(V$LOAD_HOURS_S1, 0) OR COALESCE(I$HOURS2, 0) <> COALESCE(V$LOAD_HOURS_S2, 0)
      OR COALESCE(I$CONTROL1, 0) <> COALESCE(V$CONTROL_Q1, 0) OR COALESCE(I$CONTROL2, 0) <> COALESCE(V$CONTROL_Q2, 0)
      OR COALESCE(I$HTHEORY1, 0) <> COALESCE(V$HOURS_THEORY1, 0) OR COALESCE(I$HPR1, 0) <> COALESCE(V$HOURS_PR1, 0)
      OR COALESCE(I$HDX1, 0) <> COALESCE(V$HOURS_DX1, 0) OR COALESCE(I$HIND1, 0) <> COALESCE(V$HOURS_IND1, 0)
      OR COALESCE(I$HMAX, 0) <> COALESCE(V$HMAX, 0) OR COALESCE(I$HCR1, 0) <> COALESCE(V$HCR1, 0)
      OR COALESCE(I$HATT1, 0) <> COALESCE(V$HATT1, 0) OR COALESCE(I$HGIA, 0) <> COALESCE(V$HGIA, 0)
      OR COALESCE(I$HREST, 0) <> COALESCE(V$HREST, 0)
    ) THEN
    BEGIN
      UPDATE PLAN_LOADS
      SET DATE_DEL = NULL, WEEKS = :I$WEEKS, LOAD_HOURS = :V$LOAD_HOURS_N,
        LOAD_HOURS_S1 = :I$HOURS1, LOAD_HOURS_S2 = :I$HOURS2, CONTROL_Q1 = :I$CONTROL1, CONTROL_Q2 = :I$CONTROL2,
        HOURS_THEORY1 = :I$HTHEORY1, HOURS_PR1 = :I$HPR1, HOURS_DX1 = :I$HDX1, HOURS_IND1 = :I$HIND1,
        HOURS_MAX = :I$HMAX, HOURS_CR1 = :I$HCR1, HOURS_ATT1 = :I$HATT1, HOURS_GIA = :I$HGIA, HOURS_REST = :I$HREST
      WHERE OBJ_ID = :V$OBJ_ID;

      -- Логгируем только предметы
      IF(V$STATUS = 11715 AND V$RT = 10) THEN
      INSERT INTO HISTVALS
      (TABLE_NAME, OBJ_ID, USER_ID, PARAM_ID, OPT_ID, PARENT_ID, OLD_VAL, VAL)
      VALUES ('PLAN', :V$PLAN_ID, :I$USER_ID, :V$PARENT_ID, :V$SUBJECT_ID, 0, 'Изменение нагрузки по ' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$SUBJECT_ID)),
        (SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$STAGE_ID)) || ', ' || :V$LOAD_HOURS_N);
    END
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PLAN_SET_ROW (
    I$PLAN_ID BIGINT,
    I$ROW_ID BIGINT,
    I$PARENT_ID BIGINT,
    I$LEVEL_INDEX SMALLINT,
    I$SORT_INDEX SMALLINT,
    I$GLOBAL_INDEX SMALLINT,
    I$TYPE SMALLINT,
    I$FIELD_ID BIGINT,
    I$SUBJECT_ID BIGINT,
    I$SRC_SUBJECT_ID BIGINT,
    I$IS_ADV SMALLINT,
    I$IS_STM SMALLINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$DATE_DEL timestamp;
declare variable V$FIELD_ID bigint;
declare variable V$SRC_SUBJECT_ID bigint;
declare variable V$IS_ADV smallint;
declare variable V$IS_STM smallint;
declare variable V$GLOBAL_INDEX integer;
declare variable V$SORT_INDEX integer;
declare variable V$LEVEL_INDEX integer;
declare variable V$BL varchar(200);
declare variable V$OP_ID bigint;
declare variable V$FLT varchar(100);
declare variable V$STD_ID bigint;
declare variable V$STATUS bigint;
begin

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = -1;

  -- Проверяем PARENT, только раздел
  IF(I$PARENT_ID IS NOT NULL AND NOT EXISTS(
    SELECT FIRST 1 1
    FROM PLAN_SUBJECTS S
    WHERE S.PLAN_ID = :I$PLAN_ID AND S.OBJ_ID = :I$PARENT_ID AND S.DATE_DEL IS NULL AND S.ROW_TYPE = 0
  ))
  THEN
    EXCEPTION DATA_ERROR 'Родительская строка не найдена';

  -- Проверяем статус УП
  SELECT FIRST 1 V3013.LISTVAL_ID
  FROM VALL V3013
  WHERE V3013.OBJ_ID = :I$PLAN_ID AND V3013.PARAM_ID = 3013 AND V3013.IS_DEL = 0
  INTO :V$STATUS;

  -- Проверяем, можно ли задавать углубленное изучение предмета
  IF(I$IS_ADV = 1) THEN
  BEGIN
    SELECT V3014.LISTVAL_ID
    FROM VALL V3014
    WHERE V3014.OBJ_ID = :I$PLAN_ID AND V3014.PARAM_ID = 3014 AND V3014.IS_DEL = 0
    INTO :V$STD_ID;

    SELECT FIRST 1 V3156.VAL
    FROM VALS V3156
    WHERE V3156.OBJ_ID = :I$SUBJECT_ID AND V3156.PARAM_ID = 3156 AND V3156.IS_DEL = 0
    INTO :V$BL;
    IF(V$BL IS NULL) THEN V$BL = '';

    SELECT FIRST 1 V1594.LISTVAL_ID
    FROM LINKS LP57
    JOIN VALL V1594 ON V1594.OBJ_ID = LP57.PARENT_ID AND V1594.PARAM_ID = 1594 AND V1594.IS_DEL = 0
    WHERE LP57.OBJ_ID = :I$PLAN_ID AND LP57.PARENT_TYPE_ID = 57 AND LP57.DATE_DEL IS NULL
    INTO :V$OP_ID;

    IF(V$OP_ID IS NULL) THEN
    SELECT FIRST 1 V3345.LISTVAL_ID
    FROM VALL V3345
    WHERE V3345.OBJ_ID = :I$PLAN_ID AND V3345.PARAM_ID = 3345 AND V3345.IS_DEL = 0
    INTO :V$OP_ID;

    IF(V$OP_ID = 5339) THEN V$FLT = 'НОО';
    IF(V$OP_ID = 5341) THEN V$FLT = 'ООО';
    IF(V$OP_ID = 5343) THEN V$FLT = 'СОО';

    IF(V$STD_ID = 14184) THEN
    BEGIN
      V$FLT = 'ФОП+' || V$FLT;
    END
    ELSE
    BEGIN
      V$FLT = 'ФГОС+' || V$FLT;
    END

    IF(POSITION(V$FLT IN V$BL) > 0) THEN EXCEPTION DATA_ERROR 'Предмет ' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$SUBJECT_ID)) ||
      ' не может быть указан для углубленного изучения для данного уровня образования';
  END

  IF(I$ROW_ID IS NULL) THEN
  BEGIN

    -- Есть ли существующая строка на этом уровне ?
    SELECT FIRST 1 S.DATE_DEL, S.OBJ_ID
    FROM PLAN_SUBJECTS S
    WHERE S.PLAN_ID = :I$PLAN_ID AND (S.PARENT_ID = :I$PARENT_ID OR (S.PARENT_ID IS NULL AND :I$PARENT_ID IS NULL)) AND S.ROW_TYPE = :I$TYPE
      AND (S.FIELD_ID = :I$FIELD_ID OR (S.FIELD_ID IS NULL AND :I$FIELD_ID IS NULL))
      AND (S.SUBJECT_ID = :I$SUBJECT_ID OR (S.SUBJECT_ID IS NULL AND :I$SUBJECT_ID IS NULL))
    INTO :V$DATE_DEL, :OBJ_ID;

    IF(OBJ_ID IS NULL) THEN
    BEGIN

      -- Таки добавляем новую строку
      INSERT INTO PLAN_SUBJECTS
      (PLAN_ID, ROW_TYPE, PARENT_ID, LEVEL_INDEX, SORT_INDEX, GLOBAL_INDEX, FIELD_ID, SUBJECT_ID, SRC_SUBJECT_ID, IS_ADV, IS_STM)
      VALUES (:I$PLAN_ID, :I$TYPE, :I$PARENT_ID, :I$LEVEL_INDEX, :I$SORT_INDEX, :I$GLOBAL_INDEX, :I$FIELD_ID, :I$SUBJECT_ID, :I$SRC_SUBJECT_ID, :I$IS_ADV, :I$IS_STM)
      RETURNING OBJ_ID INTO :OBJ_ID;

    END
    ELSE
    BEGIN

      -- Используем существующую строку, может быть только удаленной - иначе это дубликат
      IF(V$DATE_DEL IS NULL) THEN EXCEPTION DATA_ERROR 'Повторное добавление строки или предмета/дисциплины';

      UPDATE PLAN_SUBJECTS
      SET DATE_DEL = NULL, DATE_MODIFY = CURRENT_TIMESTAMP,
        LEVEL_INDEX = :I$LEVEL_INDEX, SORT_INDEX = :I$SORT_INDEX, GLOBAL_INDEX = :I$GLOBAL_INDEX,
        FIELD_ID = :I$FIELD_ID, SUBJECT_ID = :I$SUBJECT_ID, SRC_SUBJECT_ID = :I$SRC_SUBJECT_ID, IS_ADV = :I$IS_ADV, IS_STM = :I$IS_STM
      WHERE OBJ_ID = :OBJ_ID;

    END

    -- Логгируем только предметы
    IF(V$STATUS = 11715 AND I$TYPE = 10) THEN
    INSERT INTO HISTVALS
    (TABLE_NAME, OBJ_ID, USER_ID, PARAM_ID, OPT_ID, PARENT_ID, OLD_VAL, VAL)
    VALUES ('PLAN', :I$PLAN_ID, :I$USER_ID, :I$PARENT_ID, :I$SUBJECT_ID, :I$IS_ADV * 1 + :I$IS_STM * 2, 'Новый предмет', (SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$SUBJECT_ID)));

  END
  ELSE
  BEGIN

    -- Могли поменяться только: FIELD_ID, SRC_SUBJECT_ID, IS_ADV, IS_STM и индексы
    SELECT S.OBJ_ID, S.FIELD_ID, S.SRC_SUBJECT_ID, S.IS_ADV, S.IS_STM, S.GLOBAL_INDEX, S.SORT_INDEX, S.LEVEL_INDEX
    FROM PLAN_SUBJECTS S
    WHERE S.PLAN_ID = :I$PLAN_ID AND S.OBJ_ID = :I$ROW_ID AND S.DATE_DEL IS NULL
    INTO :OBJ_ID, :V$FIELD_ID, :V$SRC_SUBJECT_ID, :V$IS_ADV, :V$IS_STM, :V$GLOBAL_INDEX, :V$SORT_INDEX, :V$LEVEL_INDEX;

    IF(OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Строка не найдена';

    IF(COALESCE(I$FIELD_ID, -9999) <> COALESCE(V$FIELD_ID, -9999) OR COALESCE(I$SRC_SUBJECT_ID, -9999) <> COALESCE(V$SRC_SUBJECT_ID, -9999) OR
      I$IS_ADV <> V$IS_ADV OR I$IS_STM <> V$IS_STM OR I$GLOBAL_INDEX <> V$GLOBAL_INDEX OR I$LEVEL_INDEX <> V$LEVEL_INDEX OR I$SORT_INDEX <> V$SORT_INDEX) THEN
    BEGIN
      UPDATE PLAN_SUBJECTS
      SET DATE_MODIFY = CURRENT_TIMESTAMP,
        LEVEL_INDEX = :I$LEVEL_INDEX, SORT_INDEX = :I$SORT_INDEX, GLOBAL_INDEX = :I$GLOBAL_INDEX,
        FIELD_ID = :I$FIELD_ID, SUBJECT_ID = :I$SUBJECT_ID, SRC_SUBJECT_ID = :I$SRC_SUBJECT_ID, IS_ADV = :I$IS_ADV, IS_STM = :I$IS_STM
      WHERE OBJ_ID = :OBJ_ID;

      IF(V$STATUS = 11715 AND I$TYPE = 10) THEN
      INSERT INTO HISTVALS
      (TABLE_NAME, OBJ_ID, USER_ID, PARAM_ID, OPT_ID, PARENT_ID, OLD_VAL, VAL)
      VALUES ('PLAN', :I$PLAN_ID, :I$USER_ID, :I$PARENT_ID, :I$SUBJECT_ID, :I$IS_ADV * 1 + :I$IS_STM * 2, 'Изменение предмета', (SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$SUBJECT_ID)));
    END

  END

  SUSPEND;
end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PLAN_SOO_SUBJECTS_MISS (
    I$PLAN_ID BIGINT,
    I$STD_ID BIGINT)
RETURNS (
    N INTEGER,
    SUBJECTS_MISS VARCHAR(5000))
AS
declare variable V$SRC varchar(1000);
declare variable V$SUBJECT_ID bigint;
declare variable V$YEAR integer;
declare variable H smallint;
declare variable H1 smallint;
declare variable H2 smallint;
declare variable H3 smallint;
declare variable HS smallint;
begin

  -- 185 русский язык
  -- 187 литература
  -- 178 иностранный язык
  -- 190 математика
  -- 174 история (для ФГОС также Россия в мире, а также Россия в мире и всеобщая история)
  -- 206 ОБЖ vs 38700 ОБЗР (с 2024 года)
  -- 205 физкультура
  -- 175 обществознание, включая экономику и право
  -- 194 обществознание
  -- 177 естествознание
  -- 5516 астрономия
  -- 5518 информатика
  -- 198 физика
  -- 199 химия
  -- 3139 география
  -- 197 биология
  -- 34651 ИП

  SUBJECTS_MISS = '';

  -- Год ОП
  SELECT FIRST 1 V3115.VAL
  FROM LINKS LP57
  JOIN VALI V3115 ON V3115.OBJ_ID = LP57.PARENT_ID AND V3115.PARAM_ID = 3115 AND V3115.IS_DEL = 0
  WHERE LP57.OBJ_ID = :I$PLAN_ID AND LP57.PARENT_TYPE_ID = 57 AND LP57.DATE_DEL IS NULL
  INTO :V$YEAR;
  IF(V$YEAR IS NULL) THEN V$YEAR = EXTRACT(YEAR FROM CURRENT_DATE);

  IF(I$STD_ID = 14184) THEN
  BEGIN
    V$SRC  = '185;187;178;190;5518;174;206;205;194;198;199;3139;197;34651';
    -- ОБЗР вместо ОБЖ
    IF(V$YEAR >= 2024) THEN V$SRC = REPLACE(V$SRC, '206', '38700');
  END
  ELSE
  BEGIN
    V$SRC = '185;187;178;190;174;206;205;5516';
    -- естествознание включая... и обществознание
    IF(I$STD_ID = 11720) THEN V$SRC = V$SRC || ';175;177';
  END

  FOR
    SELECT ID
    FROM EXPLODE_STR(:V$SRC)
    INTO :V$SUBJECT_ID
  DO
  BEGIN
    H = 0;
    H1 = 0;
    H2 = 0;
    H3 = 0;
    SELECT FIRST 1 1
    FROM PLAN_SUBJECTS S
    JOIN PLAN_SUBJECTS S2 ON S2.OBJ_ID = S.PARENT_ID AND S2.FIELD_ID = 13303
    WHERE S.DATE_DEL IS NULL AND S.PLAN_ID = :I$PLAN_ID AND S.ROW_TYPE = 10 AND (S.SUBJECT_ID = :V$SUBJECT_ID OR S.SRC_SUBJECT_ID = :V$SUBJECT_ID)
    INTO :H;

    -- Проверяем альтернативные варианты, разделение на подпредметы
    IF(H = 0) THEN
    BEGIN
      IF(V$SUBJECT_ID = 174 AND I$STD_ID <> 11720) THEN
      BEGIN
        -- История
        SELECT FIRST 1 1
        FROM PLAN_SUBJECTS S
        JOIN PLAN_SUBJECTS S2 ON S2.OBJ_ID = S.PARENT_ID AND S2.FIELD_ID = 13303
        WHERE S.DATE_DEL IS NULL AND S.PLAN_ID = :I$PLAN_ID AND S.ROW_TYPE = 10 AND (S.SUBJECT_ID = 32840 OR S.SRC_SUBJECT_ID = 32840)
        INTO :H;

        IF(H = 0) THEN
        SELECT FIRST 1 1
        FROM PLAN_SUBJECTS S
        JOIN PLAN_SUBJECTS S2 ON S2.OBJ_ID = S.PARENT_ID AND S2.FIELD_ID = 13303
        WHERE S.DATE_DEL IS NULL AND S.PLAN_ID = :I$PLAN_ID AND S.ROW_TYPE = 10 AND (S.SUBJECT_ID = 38154 OR S.SRC_SUBJECT_ID = 38154)
        INTO :H;
      END
      ELSE IF(V$SUBJECT_ID = 175 AND I$STD_ID = 11720) THEN
      BEGIN
        -- Обществознание, включая экономику и право
        SELECT FIRST 1 1
        FROM PLAN_SUBJECTS S
        JOIN PLAN_SUBJECTS S2 ON S2.OBJ_ID = S.PARENT_ID AND S2.FIELD_ID = 13303
        WHERE S.DATE_DEL IS NULL AND S.PLAN_ID = :I$PLAN_ID AND S.ROW_TYPE = 10 AND (S.SUBJECT_ID = 194 OR S.SRC_SUBJECT_ID = 194)
        INTO :H1;

        SELECT FIRST 1 1
        FROM PLAN_SUBJECTS S
        JOIN PLAN_SUBJECTS S2 ON S2.OBJ_ID = S.PARENT_ID AND S2.FIELD_ID = 13303
        WHERE S.DATE_DEL IS NULL AND S.PLAN_ID = :I$PLAN_ID AND S.ROW_TYPE = 10 AND (S.SUBJECT_ID = 32843 OR S.SRC_SUBJECT_ID = 32843)
        INTO :H2;

        SELECT FIRST 1 1
        FROM PLAN_SUBJECTS S
        JOIN PLAN_SUBJECTS S2 ON S2.OBJ_ID = S.PARENT_ID AND S2.FIELD_ID = 13303
        WHERE S.DATE_DEL IS NULL AND S.PLAN_ID = :I$PLAN_ID AND S.ROW_TYPE = 10 AND (S.SUBJECT_ID = 3138 OR S.SRC_SUBJECT_ID = 3138)
        INTO :H3;

        -- Если есть хотя бы один из заменяющих, ругаемся персонально
        HS = H1 + H2 + H3;
        IF(HS > 0 AND HS <> 3) THEN
        BEGIN
          H = 1;
          N = N + 1;
          IF(H1 = 0) THEN
          BEGIN
            IF(SUBJECTS_MISS <> '') THEN SUBJECTS_MISS = SUBJECTS_MISS || '; ';
            SUBJECTS_MISS = SUBJECTS_MISS || (SELECT CAPTION FROM OBJECT_CAPTION_GET(194));
          END
          IF(H2 = 0) THEN
          BEGIN
            IF(SUBJECTS_MISS <> '') THEN SUBJECTS_MISS = SUBJECTS_MISS || '; ';
            SUBJECTS_MISS = SUBJECTS_MISS || (SELECT CAPTION FROM OBJECT_CAPTION_GET(32843));
          END
          IF(H3 = 0) THEN
          BEGIN
            IF(SUBJECTS_MISS <> '') THEN SUBJECTS_MISS = SUBJECTS_MISS || '; ';
            SUBJECTS_MISS = SUBJECTS_MISS || (SELECT CAPTION FROM OBJECT_CAPTION_GET(3138));
          END
        END
      END
      ELSE IF(V$SUBJECT_ID = 177 AND I$STD_ID = 11720) THEN
      BEGIN
        -- Естествознание
        SELECT FIRST 1 1
        FROM PLAN_SUBJECTS S
        JOIN PLAN_SUBJECTS S2 ON S2.OBJ_ID = S.PARENT_ID AND S2.FIELD_ID = 13303
        WHERE S.DATE_DEL IS NULL AND S.PLAN_ID = :I$PLAN_ID AND S.ROW_TYPE = 10 AND (S.SUBJECT_ID = 194 OR S.SRC_SUBJECT_ID = 198)
        INTO :H1;

        SELECT FIRST 1 1
        FROM PLAN_SUBJECTS S
        JOIN PLAN_SUBJECTS S2 ON S2.OBJ_ID = S.PARENT_ID AND S2.FIELD_ID = 13303
        WHERE S.DATE_DEL IS NULL AND S.PLAN_ID = :I$PLAN_ID AND S.ROW_TYPE = 10 AND (S.SUBJECT_ID = 32843 OR S.SRC_SUBJECT_ID = 199)
        INTO :H2;

        SELECT FIRST 1 1
        FROM PLAN_SUBJECTS S
        JOIN PLAN_SUBJECTS S2 ON S2.OBJ_ID = S.PARENT_ID AND S2.FIELD_ID = 13303
        WHERE S.DATE_DEL IS NULL AND S.PLAN_ID = :I$PLAN_ID AND S.ROW_TYPE = 10 AND (S.SUBJECT_ID = 3138 OR S.SRC_SUBJECT_ID = 197)
        INTO :H3;

        -- Если есть хотя бы один из заменяющих, ругаемся персонально
        HS = H1 + H2;
        IF(HS > 0 AND HS <> 3) THEN
        BEGIN
          H = 1;
          N = N + 1;
          IF(H1 = 0) THEN
          BEGIN
            IF(SUBJECTS_MISS <> '') THEN SUBJECTS_MISS = SUBJECTS_MISS || '; ';
            SUBJECTS_MISS = SUBJECTS_MISS || (SELECT CAPTION FROM OBJECT_CAPTION_GET(198));
          END
          IF(H2 = 0) THEN
          BEGIN
            IF(SUBJECTS_MISS <> '') THEN SUBJECTS_MISS = SUBJECTS_MISS || '; ';
            SUBJECTS_MISS = SUBJECTS_MISS || (SELECT CAPTION FROM OBJECT_CAPTION_GET(199));
          END
          IF(H3 = 0) THEN
          BEGIN
            IF(SUBJECTS_MISS <> '') THEN SUBJECTS_MISS = SUBJECTS_MISS || '; ';
            SUBJECTS_MISS = SUBJECTS_MISS || (SELECT CAPTION FROM OBJECT_CAPTION_GET(197));
          END
        END
      END
    END

    IF(H = 0) THEN
    BEGIN
      N = N + 1;
      IF(SUBJECTS_MISS <> '') THEN SUBJECTS_MISS = SUBJECTS_MISS || '; ';
      SUBJECTS_MISS = SUBJECTS_MISS || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$SUBJECT_ID));
    END
  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PLAN_STAGE_VERIFY (
    I$OBJ_ID BIGINT,
    I$USER_ID BIGINT)
AS
DECLARE VARIABLE V$LEVEL_ID BIGINT;
DECLARE VARIABLE V$GEN BIGINT;
DECLARE VARIABLE V$MULT BIGINT;
DECLARE VARIABLE V$LOCAL BIGINT;
DECLARE VARIABLE V$STATE_ID BIGINT;
begin

  -- Проверяем уровень УП
  SELECT FIRST 1 V1594.LISTVAL_ID, V3013.LISTVAL_ID
  FROM LINKS LP57
  JOIN VALL V1594 ON V1594.OBJ_ID = LP57.PARENT_ID AND V1594.PARAM_ID = 1594 AND V1594.IS_DEL = 0
  JOIN VALL V3013 ON V3013.OBJ_ID = LP57.OBJ_ID AND V3013.PARAM_ID = 3013 AND V3013.IS_DEL = 0
  WHERE LP57.OBJ_ID = :I$OBJ_ID AND LP57.PARENT_TYPE_ID = 57 AND LP57.DATE_DEL IS NULL
  INTO :V$LEVEL_ID, :V$STATE_ID;

  -- -1 в длительности недели нужен чтобы занулить дни недели в этапе
  IF(V$LEVEL_ID IS NULL) THEN
  SELECT V3345.LISTVAL_ID
  FROM VALL V3345
  WHERE V3345.OBJ_ID = :I$OBJ_ID AND V3345.PARAM_ID = 3345 AND V3345.IS_DEL = 0
  INTO :V$LEVEL_ID;

  IF(V$LEVEL_ID IN (5346, 5361) AND I$USER_ID IS NOT NULL) THEN
    EXCEPTION DATA_ERROR 'Нельзя заполнять этапы обучения вручную. Укажите количество этапов в поле "Нормативный срок освоения (курсов)"';

  -- Нельзя добавлять когда УП уже действующий. Для шаблонов тут будет NULL и проверка не сработает
  IF(V$STATE_ID <> 11716) THEN
    EXCEPTION DATA_ERROR 'Нельзя добавлять этапы в действующий учебный план';

  -- Запрещаем добавлять этапы в шаблонные УП
  SELECT GEN, MULTIPLIER
  FROM GEN
  INTO :V$GEN, :V$MULT;

  V$LOCAL = I$OBJ_ID / V$MULT;

  IF(V$LOCAL <> V$GEN) THEN EXCEPTION DATA_ERROR 'Нельзя изменять шаблонные учебные планы';

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PLAN_SUBJECTS_SELECT (
    I$PLAN_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$FIELD_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    OBJ_ID BIGINT,
    CAPTION VARCHAR(1000),
    ROW_TYPE SMALLINT,
    FIELD_ID BIGINT,
    FIELD_CAPTION VARCHAR(1000),
    COLOR_ID SMALLINT,
    SUBTYPE_ID BIGINT,
    STYPE BIGINT,
    REF_ID BIGINT)
AS
declare variable V$LICENSE_TYPE char(1);
declare variable V$PARENT_ID bigint;
declare variable V$STAGE_ID bigint;
declare variable V$IS_VD bigint;
declare variable V$IS_FOP smallint;
declare variable V$YEAR integer;
begin

  -- I$OBJ_ID и I$FIELD_ID - идентификаторы раздела в плане (предмет или раздел)
  -- Для подразделов выдается FIELD_ID и CAPTTION
  -- Для узлов выдается полный список полей

  SELECT STATUS FROM OU_LICENCE_TYPE INTO :V$LICENSE_TYPE;

  -- К какому уровню относится УП ?
  SELECT V1594.LISTVAL_ID, V3115.VAL
  FROM LINKS LP57
  JOIN VALL V1594 ON V1594.OBJ_ID = LP57.PARENT_ID AND V1594.PARAM_ID = 1594 AND V1594.IS_DEL = 0 -- и еще параметры 2132, 2146 ?
  LEFT JOIN VALI V3115 ON V3115.OBJ_ID = LP57.PARENT_ID AND V3115.PARAM_ID = 3115 AND V3115.IS_DEL = 0
  WHERE LP57.OBJ_ID = :I$PLAN_ID AND LP57.PARENT_TYPE_ID = 57 AND LP57.DATE_DEL IS NULL -- и еще типы 244, 252
  INTO :V$STAGE_ID, :V$YEAR;

  IF(V$STAGE_ID IS NULL) THEN
  SELECT FIRST 1 V3345.LISTVAL_ID
  FROM VALL V3345
  WHERE V3345.OBJ_ID = :I$PLAN_ID AND V3345.PARAM_ID = 3345 AND V3345.IS_DEL = 0
  INTO :V$STAGE_ID;

  -- Если год публикации не указан, или мы в шаблоне - считаем уже с изменениями 2024
  IF(V$YEAR IS NULL) THEN V$YEAR = 2024;

  -- Для школ выборка идет по основному списку предметов, но в зависимости от плана берутся или общеобразовательные, или ВД
  -- Для колледжей выборка идет по дереву предметов и разделов
  -- Для ДПО выборка идет по модулям, но выдаются всегда все доступные предметы, кроме итогового модуля

  -- Школы: НОО, ООО, СОО и АООП
  -- V$LICENSE_TYPE = 'O'
  IF(V$STAGE_ID IN (5339, 5341, 5343, 13272) AND I$FIELD_ID IN (12926, 12927, 12928, 13303, 13304)) THEN
  BEGIN

    -- Это обычный или внеурочный план ? Выбор из разных разделов
    SELECT V3022.LISTVAL_ID
    FROM VALL V3022
    WHERE V3022.OBJ_ID = :I$PLAN_ID AND V3022.PARAM_ID = 3022 AND V3022.IS_DEL = 0
    INTO :V$IS_VD;

    -- Для ФОП нюансы с предметными областями
    V$IS_FOP = 0;
    SELECT FIRST 1 1
    FROM VALL V3014
    WHERE V3014.OBJ_ID = :I$PLAN_ID AND V3014.PARAM_ID = 3014 AND V3014.IS_DEL = 0 AND V3014.LISTVAL_ID IN (14184, 14186)
    INTO :V$IS_FOP;

    IF(I$FIELD_ID = 12927) THEN V$PARENT_ID = 32772; ELSE V$PARENT_ID = 32771;
    ROW_TYPE = 10;

    FOR
      SELECT L51.OBJ_ID, V376.VAL, IIF(L51.OBJ_ID < 1000000000, 0, 1), V3158.LISTVAL_ID, V3159.VAL
      FROM LINKS L51
      JOIN VALS V376 ON V376.OBJ_ID = L51.OBJ_ID AND V376.PARAM_ID = 376 AND V376.IS_DEL = 0
      LEFT JOIN VALI V375 ON V375.OBJ_ID = L51.OBJ_ID AND V375.PARAM_ID = 375 AND V375.IS_DEL = 0
      -- Элективы - только в разделе элективов, и сам электив нам тоже нужен
      LEFT JOIN VALL V2816 ON V2816.OBJ_ID = L51.OBJ_ID AND V2816.PARAM_ID = 2816 AND V2816.IS_DEL = 0
      LEFT JOIN VALL V3158 ON V3158.OBJ_ID = L51.OBJ_ID AND V3158.PARAM_ID = 3158 AND V3158.IS_DEL = 0
      -- Ссылка на мастер-предмет ФГОС
      LEFT JOIN VALR V3159 ON V3159.OBJ_ID = L51.OBJ_ID AND V3159.PARAM_ID = 3159 AND V3159.IS_DEL = 0
      WHERE L51.PARENT_ID = :V$PARENT_ID AND L51.OBJ_TYPE_ID = 51 AND L51.DATE_DEL IS NULL AND L51.OBJ_ID NOT IN (179)
        AND (
          (:I$FIELD_ID IN (13303, 13304) AND V2816.LISTVAL_ID = 3) OR
          (:I$FIELD_ID = 12928 AND V2816.LISTVAL_ID = 2) OR
          (:I$FIELD_ID = 12926) OR
          (:I$FIELD_ID = 12927)
        )
      ORDER BY V376.VAL
      INTO :OBJ_ID, :CAPTION, :COLOR_ID, :STYPE, :REF_ID
    DO
    BEGIN

      -- Выбираем первую подходящую предметную область для этого уровня образования - для общеобра
      -- Изменение по предметным областям с 2024 учебного года: другие ПО для физкультуры и ОБЗР в ООО и СОО
      -- Для ВД возвращаем направление
      FIELD_ID = NULL;
      FIELD_CAPTION = NULL;

      IF(V$IS_VD = 2) THEN
      BEGIN
        SELECT FIRST 1 V2464.LISTVAL_ID, C.VAL
        FROM VALL V2464
        LEFT JOIN LISTVAL_TEXT(V2464.LISTVAL_ID) C ON 1 = 1
        WHERE V2464.OBJ_ID = :OBJ_ID AND V2464.PARAM_ID = 2464 AND V2464.IS_DEL = 0
        INTO :FIELD_ID, :FIELD_CAPTION;
      END
      ELSE
      BEGIN
        SELECT FIRST 1 V2462.LISTVAL_ID, R.VAL
        FROM LINKS L302
        JOIN VALL V2462 ON V2462.OBJ_ID = L302.OBJ_ID AND V2462.PARAM_ID = 2462 AND V2462.IS_DEL = 0
        JOIN LISTVALS LV ON LV.LISTVAL_ID = V2462.LISTVAL_ID
        JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
        WHERE L302.PARENT_ID = :OBJ_ID AND L302.OBJ_TYPE_ID = 302 AND L302.DATE_DEL IS NULL
        AND (
          ((:V$STAGE_ID = 5339) AND (V2462.LISTVAL_ID IN (12740, 11680, 11682, 11685, 11686, 11689, 11693, 11694, 11695))) OR
          ((:V$STAGE_ID = 5341) AND (V2462.LISTVAL_ID IN (11684, 11681, 11683, 11685, 11687, 11690, 11691, 11693, 11694, 11696))) OR
          -- Естественные и общественные науки
          -- Старые стандарты
          ((:V$STAGE_ID = 5343) AND (:V$IS_FOP = 0) AND (V2462.LISTVAL_ID IN (11684, 11681, 11683, 11685, 11688, 11690, 11692, 11693, 11694, 11696, 11697))) OR
          -- Новый стандарт
          ((:V$STAGE_ID = 5343) AND (:V$IS_FOP = 1) AND (V2462.LISTVAL_ID IN (11684, 11681, 11683, 11685, 11687, 11690, 11691, 11693, 11694, 11696, 11697))) OR
          ((:V$STAGE_ID IN (5341, 5343)) AND (V2462.LISTVAL_ID IN (14552, 14553) AND :V$YEAR >= 2024))
        )
        ORDER BY V2462.LISTVAL_ID DESC -- сначала более поздние, чтобы брать первично более изменения 2024 года
        INTO :FIELD_ID, :FIELD_CAPTION;
      END

      SUSPEND;
    END

  END
  -- СПО
  -- V$LICENSE_TYPE = 'P'
  ELSE IF(V$STAGE_ID IN (5361)) THEN
  BEGIN

    -- В итогах по курсу можно взять только итоговую аттестацию
    IF(I$FIELD_ID = 12975) THEN V$PARENT_ID = 13132;
    ELSE V$PARENT_ID = -1;

    FOR
      SELECT L197.OBJ_ID, V1751.VAL, IIF(L197.OBJ_ID < 1000000000, 0, 1), V1750.LISTVAL_ID
      FROM LINKS L197
      LEFT JOIN VALL V1750 ON V1750.OBJ_ID = L197.OBJ_ID AND V1750.PARAM_ID = 1750 AND V1750.IS_DEL = 0
      LEFT JOIN VALS V1751 ON V1751.OBJ_ID = L197.OBJ_ID AND V1751.PARAM_ID = 1751 AND V1751.IS_DEL = 0
      WHERE L197.PARENT_TYPE_ID = 193 AND L197.OBJ_TYPE_ID = 197 AND L197.DATE_DEL IS NULL
        AND (:V$PARENT_ID < 0 OR V1750.LISTVAL_ID = :V$PARENT_ID)
      ORDER BY 4, 2
      INTO :OBJ_ID, :CAPTION, :COLOR_ID, :SUBTYPE_ID
    DO
    BEGIN
      ROW_TYPE = IIF(I$FIELD_ID = 5247, 0, 10);
      SUSPEND;
    END

  END
  -- СПО ЦОПП
  -- V$LICENSE_TYPE = 'C'
  ELSE IF(V$STAGE_ID IN (5346)) THEN
  BEGIN

    -- Модули - заменяем на выбор предметов
    IF(I$FIELD_ID IS NULL AND I$OBJ_ID IS NOT NULL) THEN
    BEGIN
      I$FIELD_ID = -5247;
    END

    -- Разделы второго уровня
    IF(I$FIELD_ID IN (5240, 5245)) THEN
    BEGIN
      ROW_TYPE = 0;

      FOR
        SELECT LISTVAL_ID, VAL
        FROM OO_FILTRED_LIST(245)
        WHERE (:I$FIELD_ID = 5240 AND LISTVAL_ID IN (5241, 5242, 5243, 5244)) OR
          (:I$FIELD_ID = 5245 AND LISTVAL_ID IN (5246, 5247))
        INTO :FIELD_ID, :CAPTION
      DO
      BEGIN
        SUSPEND;
      END
    END
    -- Дисциплины и предметы - конечный узел
    -- Профессиональные модули - подкаталог (FIELD_ID NULL)
    ELSE
    BEGIN

      IF(I$FIELD_ID IN (5241, 5242, 5243, 5244)) THEN V$PARENT_ID = 3401;
      ELSE IF(I$FIELD_ID = 5246) THEN V$PARENT_ID = 3402;
      ELSE IF(I$FIELD_ID = 5247) THEN V$PARENT_ID = 3403;
      ELSE IF(I$FIELD_ID = 5248) THEN V$PARENT_ID = 3409;
      ELSE IF(I$FIELD_ID = 5249) THEN V$PARENT_ID = 3411;
      ELSE IF(I$FIELD_ID >= 12975 AND I$FIELD_ID <= 12997) THEN V$PARENT_ID = -1; -- все элементы для модулей (ЦОПП)
      ELSE IF(I$FIELD_ID < 0) THEN V$PARENT_ID = -2; -- все элементы для модулей (СПО)

      FOR
        SELECT L197.OBJ_ID, V1751.VAL, IIF(L197.OBJ_ID < 1000000000, 0, 1), V1750.LISTVAL_ID
        FROM LINKS L197
        LEFT JOIN VALL V1750 ON V1750.OBJ_ID = L197.OBJ_ID AND V1750.PARAM_ID = 1750 AND V1750.IS_DEL = 0
        LEFT JOIN VALS V1751 ON V1751.OBJ_ID = L197.OBJ_ID AND V1751.PARAM_ID = 1751 AND V1751.IS_DEL = 0
        WHERE L197.PARENT_TYPE_ID = 193 AND L197.OBJ_TYPE_ID = 197 AND L197.DATE_DEL IS NULL
          -- для профессиональных модулей выбираем из диапазона
          -- для просто модулей выбираем все что угодно
          AND (V1750.LISTVAL_ID = :V$PARENT_ID OR (:V$PARENT_ID < 0 AND V1750.LISTVAL_ID IN (3404, 3406, 3408)))
        ORDER BY 4, 2
        INTO :OBJ_ID, :CAPTION, :COLOR_ID, :SUBTYPE_ID
      DO
      BEGIN
        ROW_TYPE = IIF(I$FIELD_ID = 5247, 0, 10);
        SUSPEND;
      END
    END

  END
  -- ДОУ
  -- V$LICENSE_TYPE = 'D'
  ELSE IF(V$STAGE_ID IN (5337)) THEN
  BEGIN

    V$PARENT_ID = 38699;
    ROW_TYPE = 10;

    FOR
      SELECT L51.OBJ_ID, V376.VAL, IIF(L51.OBJ_ID < 1000000000, 0, 1)
      FROM LINKS L51
      JOIN VALS V376 ON V376.OBJ_ID = L51.OBJ_ID AND V376.PARAM_ID = 376 AND V376.IS_DEL = 0
      LEFT JOIN VALI V375 ON V375.OBJ_ID = L51.OBJ_ID AND V375.PARAM_ID = 375 AND V375.IS_DEL = 0
      WHERE L51.PARENT_ID = :V$PARENT_ID AND L51.OBJ_TYPE_ID = 51 AND L51.DATE_DEL IS NULL
      ORDER BY V376.VAL
      INTO :OBJ_ID, :CAPTION, :COLOR_ID
    DO
    BEGIN
      FIELD_ID = NULL;
      FIELD_CAPTION = NULL;

      SUSPEND;
    END

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PLAN_SUBJECT_HOURS_NEQ (
    I$PLAN_ID BIGINT,
    I$SRC_PLAN_ID5 BIGINT,
    I$SRC_PLAN_ID6 BIGINT,
    I$STD_ID BIGINT,
    I$LEVEL_ID BIGINT,
    I$LANG2 SMALLINT)
RETURNS (
    SUBJECT_ID BIGINT,
    STAGE_ID BIGINT,
    HOURS FLOAT,
    CHECK_HOURS FLOAT)
AS
DECLARE VARIABLE V$WEEK BIGINT;
DECLARE VARIABLE V$ADV SMALLINT;
DECLARE VARIABLE V$SRC_ID BIGINT;
DECLARE VARIABLE V$FOP_FIX SMALLINT;
begin

  -- Признак временной подмены Технологии и ОБЖ в ФОП в 2023
  V$FOP_FIX = 0;
  SELECT FIRST 1 1
  FROM LINKS LP57
  JOIN VALI V3115 ON V3115.OBJ_ID = LP57.PARENT_ID AND V3115.PARAM_ID = 3115 AND V3115.IS_DEL = 0 AND V3115.VAL < 2024
  JOIN VALL V3014 ON V3014.OBJ_ID = LP57.OBJ_ID AND V3014.PARAM_ID = 3014 AND V3014.IS_DEL = 0 AND V3014.LISTVAL_ID = 14184
  WHERE LP57.OBJ_ID = :I$PLAN_ID AND LP57.PARENT_TYPE_ID = 57 AND LP57.DATE_DEL IS NULL
  INTO :V$FOP_FIX;

  -- Сначала идем по предметам проверяемого плана, углубленность у нас будет одинаковая по всем заменам
  -- на выход пойдут только предметы, которые есть в шаблоне - лишние предметы в проверяемом плане не сверяются
  FOR
    SELECT V381.LISTVAL_ID, V2837.LISTVAL_ID, PS.IS_ADV, COALESCE(PS.SRC_SUBJECT_ID, PS.SUBJECT_ID), SUM(COALESCE(PL.LOAD_HOURS, 0))
    FROM PLAN_SUBJECTS PS
    JOIN PLAN_SUBJECTS PS2 ON PS2.OBJ_ID = PS.PARENT_ID AND PS2.FIELD_ID IN (13303)
    JOIN PLAN_LOADS PL ON PL.DATE_DEL IS NULL AND PL.SUBJECT_ID = PS.OBJ_ID
    JOIN VALL V381 ON V381.OBJ_ID = PL.STAGE_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
    JOIN VALL V2837 ON V2837.OBJ_ID = PL.STAGE_ID AND V2837.PARAM_ID = 2837 AND V2837.IS_DEL = 0
    WHERE PS.DATE_DEL IS NULL AND PS.PLAN_ID = :I$PLAN_ID AND PS.ROW_TYPE = 10
    GROUP BY 1, 2, 3, 4
    ORDER BY 1, 4
    INTO :STAGE_ID, :V$WEEK, :V$ADV, :SUBJECT_ID, :HOURS
  DO
  BEGIN

    IF(V$WEEK = 11719) THEN V$SRC_ID = I$SRC_PLAN_ID6; ELSE V$SRC_ID = I$SRC_PLAN_ID5;

    IF(V$FOP_FIX = 1 AND SUBJECT_ID = 200) THEN SUBJECT_ID = 38703; -- сверяем не с технологией, а с трудом
    IF(V$FOP_FIX = 1 AND SUBJECT_ID = 206) THEN SUBJECT_ID = 38700; -- сверяем не с ОБЖ, а с ЗР

    SELECT COALESCE(SUM(PL.LOAD_HOURS), 0)
    FROM PLAN_SUBJECTS PS
    JOIN PLAN_SUBJECTS PS2 ON PS2.OBJ_ID = PS.PARENT_ID AND PS2.FIELD_ID IN (13303)
    JOIN PLAN_LOADS PL ON PL.DATE_DEL IS NULL AND PL.SUBJECT_ID = PS.OBJ_ID
    JOIN VALL V381 ON V381.OBJ_ID = PL.STAGE_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0 AND V381.LISTVAL_ID = :STAGE_ID
    WHERE PS.DATE_DEL IS NULL AND PS.PLAN_ID = :V$SRC_ID AND PS.ROW_TYPE = 10 AND PS.SUBJECT_ID = :SUBJECT_ID
    INTO :CHECK_HOURS;

    -- Второй иностранный - если есть, то 2 часа в неделю --  AND HOURS > 0
    IF(SUBJECT_ID = 32810 AND I$LEVEL_ID = 5341) THEN
    BEGIN
      CHECK_HOURS = 68;
    END

    -- Физкультура (все классы) и физика (9 класс) - проверяем второй наличие второго иностранного
    -- физика это косяк в стандарте
    --IF(I$STD_ID = 14184 AND ((SUBJECT_ID = 205 AND CHECK_HOURS = 102) OR (STAGE_ID = 45 AND SUBJECT_ID = 198 AND CHECK_HOURS = 102))) THEN
    IF(I$STD_ID = 14184 AND (SUBJECT_ID = 205 AND CHECK_HOURS = 102)) THEN
    BEGIN
      IF(I$LANG2 = 1) THEN
      BEGIN
        IF(SUBJECT_ID = 205) THEN CHECK_HOURS = 68;
        --IF(SUBJECT_ID = 198) THEN CHECK_HOURS = 68;
      END
    END

    -- Для ФГОС-2021 и углубленных предметов делаем проверку не на точное равенство, а на не меньше
    IF(I$STD_ID = 13452 AND V$ADV = 1) THEN HOURS = CHECK_HOURS;

    IF(CHECK_HOURS <> HOURS) THEN
    BEGIN
      SUSPEND;
    END

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PLAN_SUBJECT_LINK_LIST (
    I$OBJ_ID BIGINT,
    I$USER_ID BIGINT,
    I$ROOT_ID BIGINT = null)
RETURNS (
    OBJ_ID BIGINT,
    PARENT_ID BIGINT,
    OBJ_CAPTION VARCHAR(4000),
    SORT_ORDER DOUBLE PRECISION,
    COLOR INTEGER)
AS
declare variable V$PARENT_TYPE_ID bigint;
declare variable V$STAGE_TYPE_ID bigint;
declare variable V$IS_ALLOWED smallint;
declare variable V$IS_ELECTIVE bigint;
BEGIN
    PARENT_ID = I$ROOT_ID;
    IF (I$ROOT_ID IS NULL) THEN
    BEGIN
        -- Является ли УП обычным или планом ВД/ГПД - для них предметы берутся из разных каталогов
        IF(EXISTS(
            SELECT FIRST 1 1
            FROM LINKS LP50
            JOIN VALL V2545 ON V2545.OBJ_ID = LP50.PARENT_ID AND V2545.PARAM_ID = 2545 AND V2545.IS_DEL = 0 AND V2545.LISTVAL_ID = 2
            WHERE LP50.OBJ_ID = :I$OBJ_ID AND LP50.PARENT_TYPE_ID = 50 AND LP50.DATE_DEL IS NULL
        ) OR EXISTS(
            SELECT FIRST 1 1
            FROM LINKS LP50
            JOIN LINKS LP57 ON LP57.OBJ_ID = LP50.PARENT_ID AND LP57.PARENT_TYPE_ID = 57 AND LP57.DATE_DEL IS NULL
            JOIN LINKS LP69 ON LP69.OBJ_ID = LP57.PARENT_ID AND LP69.PARENT_TYPE_ID = 69 AND LP69.DATE_DEL IS NULL
            JOIN VALL V2450 ON V2450.OBJ_ID = LP69.PARENT_ID AND V2450.PARAM_ID = 2450 AND V2450.IS_DEL = 0 AND V2450.LISTVAL_ID = 11386
            WHERE LP50.OBJ_ID = :I$OBJ_ID AND LP50.PARENT_TYPE_ID = 50 AND LP50.DATE_DEL IS NULL
        )) THEN
        BEGIN
            I$ROOT_ID = 32772;
        END
        ELSE
        BEGIN
            I$ROOT_ID = 32771;
        END

        -- Получаем тип этапа УП, а также проверяем, является ли УП шаблонным
        SELECT LPX.PARENT_TYPE_ID, V372.LISTVAL_ID
        FROM LINKS LP50
        JOIN LINKS LPX ON LPX.OBJ_ID = LP50.PARENT_ID AND LPX.PARENT_TYPE_ID IN (55, 57, 241, 244, 248, 252) AND LPX.DATE_DEL IS NULL
        JOIN VALL V372 ON V372.OBJ_ID = LP50.OBJ_ID AND V372.PARAM_ID IN (372, 12752) AND V372.IS_DEL = 0
        WHERE LP50.OBJ_ID = :I$OBJ_ID AND LP50.PARENT_TYPE_ID = 50 AND LP50.DATE_DEL IS NULL
        INTO :V$PARENT_TYPE_ID, :V$STAGE_TYPE_ID;
    
        -- Выбираем все предметы в указанном разделе, кроме заголовка предметов по выбору и старого обозначения элективов
        FOR
            SELECT L51.OBJ_ID, V2816.LISTVAL_ID
            FROM LINKS L51
            LEFT JOIN VALL V2816 ON V2816.OBJ_ID = L51.OBJ_ID AND V2816.PARAM_ID = 2816 AND V2816.IS_DEL = 0
            WHERE L51.PARENT_ID = :I$ROOT_ID AND L51.OBJ_TYPE_ID = 51 AND L51.DATE_DEL IS NULL AND L51.OBJ_ID NOT IN (179)
            INTO :OBJ_ID, :V$IS_ELECTIVE
        DO
        BEGIN
            V$IS_ALLOWED = 1;
            -- Для федеральных/обязательных компонентов не даем выбирать элективные курсы
            IF(V$STAGE_TYPE_ID IN (780, 12752)) THEN
            BEGIN
              IF(V$IS_ELECTIVE = 2) THEN V$IS_ALLOWED = 0;
            END
            -- Убираем те, что уже добавлены
            IF (V$IS_ALLOWED = 1 AND NOT EXISTS(
                SELECT FIRST 1 1
                FROM LINKS
                WHERE PARENT_ID = :I$OBJ_ID AND OBJ_ID = :OBJ_ID AND DATE_DEL IS NULL
            )) THEN
            BEGIN
                SELECT CAPTION, SORT_ORDER, COLOR
                FROM OBJECT_CAPTION_GET(:OBJ_ID, NULL, NULL, :I$USER_ID)
                INTO :OBJ_CAPTION, :SORT_ORDER, :COLOR;
    
                SUSPEND;
            END
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PLAN_SUBJECT_LIST (
    I$OBJ_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    PARENT_ID BIGINT,
    OBJ_CAPTION VARCHAR(4000),
    SORT_ORDER DOUBLE PRECISION)
AS
declare variable V$CHECK_CURRICULUM_ID bigint;
declare variable V$STADY_WEEK_ID bigint;
declare variable V$STADY_STANDARD_ID bigint;
declare variable V$LEVEL_ID bigint;
declare variable V$COMPONENT_TYPE_ID bigint;
declare variable V$IS_ALLOWED smallint;
declare variable V$ALT_SUBJECT_ID bigint;
declare variable V$PLAN_STAGE_ID bigint;
BEGIN
    FOR
        -- Выборка для предметов замены (вызов из редактора)
        SELECT FIRST 1 V1594.LISTVAL_ID, V2837.LISTVAL_ID, V2478.LISTVAL_ID, V372.LISTVAL_ID, LP49.PARENT_ID
        FROM LINKS LP49
        JOIN LINKS LP50 ON LP50.OBJ_ID = LP49.PARENT_ID AND LP50.PARENT_TYPE_ID = 50 AND LP50.DATE_DEL IS NULL
        JOIN VALL V372 ON V372.OBJ_ID = LP50.OBJ_ID AND V372.PARAM_ID = 372 AND V372.IS_DEL = 0
        LEFT JOIN LINKS L54 ON L54.OBJ_TYPE_ID = 54 AND L54.PARENT_ID = LP50.PARENT_ID AND L54.DATE_DEL IS NULL
        LEFT JOIN VALL V2837 ON V2837.OBJ_ID = L54.OBJ_ID AND V2837.PARAM_ID = 2837 AND V2837.IS_DEL = 0
        LEFT JOIN VALL V2478 ON V2478.OBJ_ID = LP50.PARENT_ID AND V2478.PARAM_ID = 2478 AND V2478.IS_DEL = 0
        JOIN LINKS LP57 ON LP57.OBJ_ID = LP50.PARENT_ID AND LP57.PARENT_TYPE_ID = 57 AND LP57.DATE_DEL IS NULL
        JOIN VALL V1594 ON V1594.OBJ_ID = LP57.PARENT_ID AND V1594.PARAM_ID = 1594 AND V1594.IS_DEL = 0 AND V1594.LISTVAL_ID IN (5339,5341,5343)
        WHERE LP49.OBJ_ID = :I$OBJ_ID AND LP49.PARENT_TYPE_ID = 49 AND LP49.DATE_DEL IS NULL

        UNION ALL

        -- Выборка для компонентов УП (вызов из CURRICULUM_SUBJECT_TO_FGOS)
        SELECT FIRST 1 V1594.LISTVAL_ID, V2837.LISTVAL_ID, V2478.LISTVAL_ID, V372.LISTVAL_ID, LP50.OBJ_ID
        FROM LINKS LP50
        JOIN VALL V372 ON V372.OBJ_ID = LP50.OBJ_ID AND V372.PARAM_ID = 372 AND V372.IS_DEL = 0
        LEFT JOIN LINKS L54 ON L54.OBJ_TYPE_ID = 54 AND L54.PARENT_ID = LP50.PARENT_ID AND L54.DATE_DEL IS NULL
        LEFT JOIN VALL V2837 ON V2837.OBJ_ID = L54.OBJ_ID AND V2837.PARAM_ID = 2837 AND V2837.IS_DEL = 0
        LEFT JOIN VALL V2478 ON V2478.OBJ_ID = LP50.PARENT_ID AND V2478.PARAM_ID = 2478 AND V2478.IS_DEL = 0
        JOIN LINKS LP57 ON LP57.OBJ_ID = LP50.PARENT_ID AND LP57.PARENT_TYPE_ID = 57 AND LP57.DATE_DEL IS NULL
        JOIN VALL V1594 ON V1594.OBJ_ID = LP57.PARENT_ID AND V1594.PARAM_ID = 1594 AND V1594.IS_DEL = 0 AND V1594.LISTVAL_ID IN (5339,5341,5343)
        WHERE LP50.OBJ_ID = :I$OBJ_ID AND LP50.PARENT_TYPE_ID = 50 AND LP50.DATE_DEL IS NULL

        INTO :V$LEVEL_ID, :V$STADY_WEEK_ID, :V$STADY_STANDARD_ID, :V$COMPONENT_TYPE_ID, :V$PLAN_STAGE_ID
    DO
    BEGIN
        -- Тут должна вернуться ровно одна строчка, соответствующая шаблонному плану
        FOR
            SELECT FIRST 1 L50.OBJ_ID
            FROM LINKS L50
            JOIN VALL V2503 ON V2503.OBJ_ID = L50.OBJ_ID AND V2503.PARAM_ID = 2503 AND V2503.IS_DEL = 0 AND V2503.LISTVAL_ID = :V$LEVEL_ID
            LEFT JOIN LINKS L54 ON L54.OBJ_TYPE_ID = 54 AND L54.PARENT_ID = L50.OBJ_ID AND L54.DATE_DEL IS NULL
            LEFT JOIN VALL V2478 ON V2478.OBJ_ID = L50.OBJ_ID AND V2478.PARAM_ID = 2478 AND V2478.IS_DEL = 0
            JOIN VALL V2466 ON V2466.OBJ_ID = L50.OBJ_ID AND V2466.PARAM_ID = 2466 AND V2466.IS_DEL = 0 AND V2466.LISTVAL_ID = 2
            WHERE L50.PARENT_ID = 258 AND L50.OBJ_TYPE_ID = 50 AND L50.DATE_DEL IS NULL AND ((:V$STADY_STANDARD_ID IS NULL) OR (V2478.LISTVAL_ID = :V$STADY_STANDARD_ID))
            INTO :V$CHECK_CURRICULUM_ID
        DO
        BEGIN
            FOR
                SELECT L51.OBJ_ID
                FROM LINKS L49
                JOIN VALL V372 ON V372.OBJ_ID = L49.OBJ_ID AND V372.PARAM_ID = 372 AND V372.IS_DEL = 0 AND V372.LISTVAL_ID = :V$COMPONENT_TYPE_ID
                JOIN LINKS L51 ON L51.PARENT_ID = L49.OBJ_ID AND L51.OBJ_TYPE_ID = 51 AND L51.DATE_DEL IS NULL
                WHERE L49.PARENT_ID = :V$CHECK_CURRICULUM_ID AND L49.OBJ_TYPE_ID = 49 AND L49.DATE_DEL IS NULL
                INTO :OBJ_ID
            DO
            BEGIN
                V$IS_ALLOWED = 1;
                V$ALT_SUBJECT_ID = NULL;

                -- Обход ситуации с обществознание+экономика+право для среднего образования
                -- В шаблоне стоит обществознание, которое пытается стать заменой - если в нашем плане есть комплексный предмет, не отображаем исходный
                IF(OBJ_ID = 194) THEN V$ALT_SUBJECT_ID = 175;

                -- Возвращаем только предметы, которые сами по себе не перечислены в текущем УП
                -- Выключено, можно брать любые предметы из УП, иначе не внести клоны математик, технологий и физкультур
                IF ((V$IS_ALLOWED = 1) /*AND NOT EXISTS(
                    SELECT FIRST 1 1
                    FROM LINKS
                    WHERE PARENT_ID = :V$PLAN_STAGE_ID AND (OBJ_ID = :OBJ_ID OR OBJ_ID = :V$ALT_SUBJECT_ID) AND DATE_DEL IS NULL
                )*/
                ) THEN
                BEGIN
                    SELECT CAPTION, SORT_ORDER
                    FROM OBJECT_CAPTION_GET(:OBJ_ID, NULL, NULL, :I$USER_ID)
                    INTO :OBJ_CAPTION, :SORT_ORDER;
                
                    SUSPEND;
                END
            END
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PLAN_SUBJECT_LIST2 (
    I$CURRICULUM_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    PARENT_ID BIGINT,
    OBJ_CAPTION VARCHAR(4000),
    SORT_ORDER DOUBLE PRECISION)
AS
declare variable V$CHECK_CURRICULUM_ID bigint;
declare variable V$STADY_WEEK_ID bigint;
declare variable V$STADY_STANDARD_ID bigint;
declare variable V$LEVEL_ID bigint;
declare variable V$COMPONENT_TYPE_ID bigint;
declare variable V$STD bigint;
BEGIN
    FOR
        SELECT DISTINCT L51.OBJ_ID
        FROM LINKS L49
        -- Только федеральный компонент
        JOIN VALL V372 ON V372.OBJ_ID = L49.OBJ_ID AND V372.PARAM_ID = 372 AND V372.IS_DEL = 0 AND V372.LISTVAL_ID IN (780, 12752)
        -- Предметы в компоненте
        JOIN LINKS L51 ON L51.PARENT_ID = L49.OBJ_ID AND L51.OBJ_TYPE_ID = 51 AND L51.DATE_DEL IS NULL
        -- Номер стандарта
        JOIN VALL V2478 ON V2478.OBJ_ID = L49.PARENT_ID AND V2478.PARAM_ID = 2478 AND V2478.IS_DEL = 0
        WHERE L49.PARENT_ID = :I$CURRICULUM_ID AND L49.OBJ_TYPE_ID = 49 AND L49.DATE_DEL IS NULL
            AND (V2478.LISTVAL_ID = 11720 OR
                -- Для ФГОС запрещаем Обществознание, Россия в мире, Физкультура, Экология, ОБЖ, Индпроект
                L51.OBJ_ID NOT IN (194, 32840, 205, 3160, 206, 34651)
            )
        INTO :OBJ_ID
    DO
    BEGIN
        IF (NOT EXISTS(
            SELECT FIRST 1 1
            FROM LINKS
            WHERE PARENT_ID = :I$CURRICULUM_ID AND OBJ_ID = :OBJ_ID AND DATE_DEL IS NULL
        )) THEN
        BEGIN
            SELECT CAPTION, SORT_ORDER
            FROM OBJECT_CAPTION_GET(:OBJ_ID, NULL, NULL, :I$USER_ID)
            INTO :OBJ_CAPTION, :SORT_ORDER;
                
            SUSPEND;
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PLAN_VOSP_GET (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(2000))
AS
DECLARE VARIABLE V$CJ_ID BIGINT;
DECLARE VARIABLE V$ATTR_ID BIGINT;
DECLARE VARIABLE V$ID BIGINT;
DECLARE VARIABLE V$REF_ID BIGINT;
DECLARE VARIABLE V$DT TIMESTAMP;
DECLARE VARIABLE V$OU_ID BIGINT;
DECLARE VARIABLE V$DE_ID BIGINT;
DECLARE VARIABLE V$STAGE BIGINT;
DECLARE VARIABLE S1 VARCHAR(100);
DECLARE VARIABLE S2 VARCHAR(400);
DECLARE VARIABLE S3 VARCHAR(1000);
begin

  SELECT FIRST 1 J.OBJ_ID, J.DATE_MODIFY
  FROM CJ2_JOURNAL J
  WHERE J.DATE_DEL IS NULL AND J.REF_ID = :I$OBJ_ID
  INTO :V$CJ_ID, :V$DT;

  FOR
    SELECT TAG_NAME, VAL
    FROM CJ2_JOURNAL_GET(:I$USER_ID, :V$CJ_ID, NULL, NULL)
    INTO :TAG_NAME, :VAL
  DO
  BEGIN
    SUSPEND;
  END

  -- Признак утверждения
  TAG_NAME = 'plan_status';
  VAL = NULL;
  SELECT V.LISTVAL_ID
  FROM VALL V
  WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 3373 AND V.IS_DEL = 0
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'dt';
  VAL = (SELECT VAL FROM DATE2ISO(:V$DT));
  SUSPEND;

  -- Дополнительные атрибуты к мероприятиям
  TAG_NAME = 'attrs::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
    SELECT A.OBJ_ID, A.LESSON_ID, A.ATTR_NAME, A.ATTR_VALUE, A.REF_ID, IIF(OBJ.TYPE_ID = 2, 'Все классы', COALESCE(LC.VAL, C.CAPTION))
    FROM CJ2_JOURNAL_LESSONS L
    JOIN CJ2_LESSON_ATTRS A ON A.DATE_DEL IS NULL AND A.LESSON_ID = L.OBJ_ID
    LEFT JOIN OBJECTS OBJ ON OBJ.OBJ_ID = A.REF_ID AND A.REF_ID IS NOT NULL
    LEFT JOIN OBJECT_CAPTION_GET(A.REF_ID) C ON A.REF_ID IS NOT NULL
    LEFT JOIN LISTVAL_TEXT(A.LISTVAL_ID) LC ON A.LISTVAL_ID IS NOT NULL
    WHERE L.DATE_DEL IS NULL AND L.CJ_ID = :V$CJ_ID
    INTO :V$ATTR_ID, :V$ID, :S1, :S2, :V$REF_ID, :S3
  DO
  BEGIN
    TAG_NAME = 'attrs:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'attrs:r:id';
    VAL = V$ATTR_ID;
    SUSPEND;
    TAG_NAME = 'attrs:r:lesson_id';
    VAL = V$ID;
    SUSPEND;
    TAG_NAME = 'attrs:r:name';
    VAL = S1;
    SUSPEND;
    TAG_NAME = 'attrs:r:value';
    VAL = COALESCE(S2, S3);
    SUSPEND;
    TAG_NAME = 'attrs:r:ref_id';
    VAL = V$REF_ID;
    SUSPEND;
  END

  TAG_NAME = 'mchoose::json&colon;array';
  VAL = 1;
  SUSPEND;
  -- Вся организация
  TAG_NAME = 'mchoose:r';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'mchoose:r:id';
  SELECT FIRST 1 L2.OBJ_ID
  FROM LINKS L2
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$OU_ID;
  VAL = V$OU_ID;
  SUSPEND;
  TAG_NAME = 'mchoose:r:name';
  VAL = 'Все классы';
  SUSPEND;
  -- Диапазон классов по уровню образования
  -- Убираем отсюда ДОО и СПО, оставляем только школьные
  FOR
    SELECT L7.OBJ_ID, V43.LISTVAL_ID
    FROM LINKS L7
    JOIN VALL V43 ON V43.OBJ_ID = L7.OBJ_ID AND V43.PARAM_ID = 43
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V43.LISTVAL_ID
    WHERE L7.PARENT_ID = :V$OU_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    ORDER BY LV.COST
    INTO :V$DE_ID, :V$STAGE
  DO
  BEGIN
    TAG_NAME = 'mchoose:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'mchoose:r:id';
    VAL = V$DE_ID;
    SUSPEND;
    TAG_NAME = 'mchoose:r:name';
    VAL = NULL;
    SELECT CAST(MIN(LV.COST) AS INTEGER)
    FROM LINKS L8
    JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V49.LISTVAL_ID
    WHERE L8.PARENT_ID = :V$DE_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    INTO :VAL;
    SELECT :VAL || '-' || CAST(MAX(LV.COST) AS INTEGER) || ' классы'
    FROM LINKS L8
    JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V49.LISTVAL_ID
    WHERE L8.PARENT_ID = :V$DE_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    INTO :VAL;
    IF(VAL IS NULL) THEN VAL = '???-??? классы';
    SUSPEND;
  END
  -- Конкретные параллели
  FOR
    SELECT L8.OBJ_ID, REPLACE(C.CAPTION, 'параллель', 'классы')
    FROM LINKS L7
    JOIN VALL V43 ON V43.OBJ_ID = L7.OBJ_ID AND V43.PARAM_ID = 43
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    LEFT JOIN OBJECT_CAPTION_GET(L8.OBJ_ID) C ON 1 = 1
    WHERE L7.PARENT_ID = :V$OU_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    ORDER BY C.SORT_ORDER
    INTO :V$DE_ID, :S1
  DO
  BEGIN
    TAG_NAME = 'mchoose:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'mchoose:r:id';
    VAL = V$DE_ID;
    SUSPEND;
    TAG_NAME = 'mchoose:r:name';
    VAL = S1;
    SUSPEND;
  END
  -- Конкретные классы
  FOR
    SELECT L9.OBJ_ID, REPLACE(C.CAPTION, 'параллель', 'классы')
    FROM LINKS L7
    JOIN VALL V43 ON V43.OBJ_ID = L7.OBJ_ID AND V43.PARAM_ID = 43
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
    LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C ON 1 = 1
    WHERE L7.PARENT_ID = :V$OU_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    ORDER BY C.SORT_ORDER
    INTO :V$DE_ID, :S1
  DO
  BEGIN
    TAG_NAME = 'mchoose:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'mchoose:r:id';
    VAL = V$DE_ID;
    SUSPEND;
    TAG_NAME = 'mchoose:r:name';
    VAL = S1;
    SUSPEND;
  END

  -- ФИО и должность руководителя для экспорта
  TAG_NAME = 'sign_title';
  VAL = NULL;
  S1 = NULL;
  SELECT POST, F || ' ' || SUBSTRING(I FROM 1 FOR 1) || '.' || COALESCE(SUBSTRING(O FROM 1 FOR 1) || '.', ''), V2.VAL, V5.VAL
  FROM LINKS L2
  LEFT JOIN R_SPB_POST_DIRECTOR(L2.OBJ_ID, 1) C ON 1 = 1
  LEFT JOIN VALS V2 ON V2.OBJ_ID = L2.OBJ_ID AND V2.PARAM_ID = 2 AND V2.IS_DEL = 0
  LEFT JOIN VALS V5 ON V5.OBJ_ID = L2.OBJ_ID AND V5.PARAM_ID = 5 AND V5.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :VAL, :S1, :S2, :S3;
  SUSPEND;

  TAG_NAME = 'sign_name';
  VAL = S1;
  SUSPEND;

  -- Реквизиты
  TAG_NAME = 'order_num';
  VAL = NULL;
  SELECT V.VAL
  FROM VALS V
  WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 3375 AND V.IS_DEL = 0
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'order_date';
  VAL = NULL;
  SELECT C.VAL
  FROM VALD V
  LEFT JOIN DATE2SCRIPT(V.VAL) C ON 1 = 1
  WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 3376 AND V.IS_DEL = 0
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'year_name';
  VAL = NULL;
  SELECT C.VAL
  FROM VALL V
  LEFT JOIN LISTVAL_TEXT(V.LISTVAL_ID) C ON 1 = 1
  WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 3372 AND V.IS_DEL = 0
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'org_name_short';
  VAL = S2;
  SUSPEND;

  TAG_NAME = 'org_name_full';
  VAL = S3;
  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PLAN_WP_GET (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V VARCHAR(1000);
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$SUBJECT_ID BIGINT;
DECLARE VARIABLE S VARCHAR(1000);
DECLARE VARIABLE V$LEVEL_ID BIGINT;
begin

  SELECT V.VAL
  FROM VALS V
  WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 3592 AND V.IS_DEL = 0
  INTO :V;

  SELECT FIRST 1 V1594.LISTVAL_ID
  FROM LINKS LP57
  JOIN VALL V1594 ON V1594.OBJ_ID = LP57.PARENT_ID AND V1594.PARAM_ID = 1594 AND V1594.IS_DEL = 0
  WHERE LP57.OBJ_ID = :I$OBJ_ID AND LP57.PARENT_TYPE_ID = 57 AND LP57.DATE_DEL IS NULL
  INTO :V$LEVEL_ID;

  IF(V$LEVEL_ID = 5339) THEN V$LEVEL_ID = 22;
  ELSE IF(V$LEVEL_ID = 5341) THEN V$LEVEL_ID = 26;
  ELSE IF(V$LEVEL_ID = 5343) THEN V$LEVEL_ID = 27;
  -- АООП ?

  -- Текущий список рабочих программ
  TAG_NAME = 'wp::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L.ID, P.SUBJECT_ID, P.OBJ_NAME
    FROM STR_TO_ID_LIST(:V) L
    JOIN PTP P ON P.OBJ_ID = L.ID
    ORDER BY 3
    INTO :V$OBJ_ID, :V$SUBJECT_ID, :S
  DO
  BEGIN
    TAG_NAME = 'wp:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'wp:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'wp:r:subject_id';
    VAL = V$SUBJECT_ID;
    SUSPEND;
    TAG_NAME = 'wp:r:name';
    VAL = S;
    SUSPEND;
  END

  -- Список доступных для выбора программ
  TAG_NAME = 'selection::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT P.OBJ_ID, P.SUBJECT_ID, P.OBJ_NAME
    FROM PTP P
    WHERE P.DATE_DEL IS NULL AND P.LEVEL_ID = 2167 AND P.EDU_LEVEL_ID = :V$LEVEL_ID AND EXISTS(
      SELECT FIRST 1 1
      FROM PLAN_SUBJECTS PS
      JOIN PLAN_LOADS PL ON PL.DATE_DEL IS NULL AND PL.SUBJECT_ID = PS.OBJ_ID AND PL.LOAD_HOURS > 0
      WHERE PS.DATE_DEL IS NULL AND PS.PLAN_ID = :I$OBJ_ID AND PS.ROW_TYPE = 10
    )
    ORDER BY 3
    INTO :V$OBJ_ID, :V$SUBJECT_ID, :S
  DO
  BEGIN
    TAG_NAME = 'selection:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'selection:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'selection:r:subject_id';
    VAL = V$SUBJECT_ID;
    SUSPEND;
    TAG_NAME = 'selection:r:name';
    VAL = S;
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PMPK_PKG_DATA (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
begin

  -- Запрашивать можно только в предварительном приеме и в классе
  -- !!!

  TAG_NAME = 'name_last';
  VAL = NULL;
  SELECT V.VAL
  FROM VALS V
  WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 55 AND V.IS_DEL = 0
  INTO :VAL;
  IF(VAL IS NULL) THEN EXCEPTION DATA_ERROR 'Персона не найдена';
  SUSPEND;

  TAG_NAME = 'name_first';
  VAL = NULL;
  SELECT V.VAL
  FROM VALS V
  WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 56 AND V.IS_DEL = 0
  INTO :VAL;
  IF(VAL IS NULL) THEN EXCEPTION DATA_ERROR 'Персона не найдена';
  SUSPEND;

  TAG_NAME = 'name_mid';
  VAL = NULL;
  SELECT V.VAL
  FROM VALS V
  WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 57 AND V.IS_DEL = 0
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'birth_date';
  VAL = NULL;
  SELECT C.VAL || 'T00:00:00'
  FROM VALD V
  LEFT JOIN DATE2ISO(V.VAL, 0) C ON 1 = 1
  WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 89 AND V.IS_DEL = 0
  INTO :VAL;
  IF(VAL IS NULL) THEN EXCEPTION DATA_ERROR 'Персона не найдена или не указана дата рождения';
  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PMPK_SEND_DATA (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(4000))
AS
declare variable V$TYPE_ID bigint;
declare variable V$OBJ_ID bigint;
declare variable V$DATE date;
declare variable V$OGRN varchar(100);
declare variable V$TERM_ID bigint;
declare variable V$UID varchar(40);
declare variable V$DT varchar(30);
declare variable V$DTT varchar(30);
declare variable N integer;
declare variable V$SECTION bigint;
declare variable S varchar(4000);
declare variable V$VALID bigint;
begin

  SELECT TYPE_ID
  FROM OBJECTS
  WHERE OBJ_ID = :I$OBJ_ID
  INTO :V$TYPE_ID;

  N = 0;

  -- Шлем требования с датой от начала текущего учебного года
  TAG_NAME = 'date';
  SELECT LV.TAG, V9.VAL
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN VALS V9 ON V9.OBJ_ID = L2.OBJ_ID AND V9.PARAM_ID = 9 AND V9.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :VAL, :V$OGRN;
  IF(VAL IS NULL) THEN EXCEPTION DATA_ERROR 'Не указан учебный год или ОГРН';
  V$DATE = CAST(VAL AS DATE);
  SUSPEND;

  TAG_NAME = 'ogrn';
  VAL = V$OGRN;
  SUSPEND;

  TAG_NAME = 'year';
  VAL = V$DATE;
  SUSPEND;

  TAG_NAME = 'items::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT DISTINCT L10.OBJ_ID
    FROM LINKS L10
    JOIN LINKS L461 ON L461.PARENT_ID = L10.OBJ_ID AND L461.OBJ_TYPE_ID = 461 AND L461.DATE_DEL IS NULL
    JOIN VALD V3307 ON V3307.OBJ_ID = L461.OBJ_ID AND V3307.PARAM_ID = 3307 AND V3307.IS_DEL = 0 AND V3307.VAL >= :V$DATE
    WHERE L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL AND ((L10.PARENT_TYPE_ID = 9 AND :V$TYPE_ID = 10) OR L10.PARENT_ID = :I$OBJ_ID)
    INTO :V$OBJ_ID
  DO
  BEGIN
    TAG_NAME = 'items:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'items:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'items:r:name_last';
    VAL = NULL;
    SELECT V.VAL FROM VALS V WHERE V.OBJ_ID = :V$OBJ_ID AND V.PARAM_ID = 55 AND V.IS_DEL = 0 INTO :VAL;
    SUSPEND;
    TAG_NAME = 'items:r:name_first';
    VAL = NULL;
    SELECT V.VAL FROM VALS V WHERE V.OBJ_ID = :V$OBJ_ID AND V.PARAM_ID = 56 AND V.IS_DEL = 0 INTO :VAL;
    SUSPEND;
    TAG_NAME = 'items:r:name_mid';
    VAL = NULL;
    SELECT V.VAL FROM VALS V WHERE V.OBJ_ID = :V$OBJ_ID AND V.PARAM_ID = 57 AND V.IS_DEL = 0 INTO :VAL;
    SUSPEND;
    TAG_NAME = 'items:r:birth_date';
    VAL = NULL;
    SELECT C.VAL || 'T00:00:00'
    FROM VALD V
    LEFT JOIN DATE2ISO(V.VAL, 0) C ON 1 = 1
    WHERE V.OBJ_ID = :V$OBJ_ID AND V.PARAM_ID = 89 AND V.IS_DEL = 0 INTO :VAL;
    SUSPEND;
    TAG_NAME = 'items:r:snils';
    VAL = NULL;
    SELECT V.VAL FROM VALS V WHERE V.OBJ_ID = :V$OBJ_ID AND V.PARAM_ID = 1409 AND V.IS_DEL = 0 INTO :VAL;
    SUSPEND;

    -- Временно выборка сделана только по еще не отправленным данным
    TAG_NAME = 'items:r:items::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT L461.OBJ_ID, PL.UID, VD.VAL, V3306.LISTVAL_ID, VDD.VAL, V3309.VAL, V3310.LISTVAL_ID
      FROM LINKS L461
      JOIN VALD V3307 ON V3307.OBJ_ID = L461.OBJ_ID AND V3307.PARAM_ID = 3307 AND V3307.IS_DEL = 0 AND V3307.VAL >= :V$DATE
      LEFT JOIN PMPK_LINKS PL ON PL.PERSON_ID = L461.PARENT_ID AND PL.TERM_ID = L461.OBJ_ID
      LEFT JOIN DATE2ISO(V3307.VAL, 0) VD ON 1 = 1
      JOIN VALL V3306 ON V3306.OBJ_ID = L461.OBJ_ID AND V3306.PARAM_ID = 3306 AND V3306.IS_DEL = 0
      LEFT JOIN VALD V3308 ON V3308.OBJ_ID = L461.OBJ_ID AND V3308.PARAM_ID = 3308 AND V3308.IS_DEL = 0
      LEFT JOIN DATE2ISO(V3308.VAL, 0) VDD ON 1 = 1
      LEFT JOIN VALS V3309 ON V3309.OBJ_ID = L461.OBJ_ID AND V3309.PARAM_ID = 3309 AND V3309.IS_DEL = 0
      JOIN VALL V3310 ON V3310.OBJ_ID = L461.OBJ_ID AND V3310.PARAM_ID = 3310 AND V3310.IS_DEL = 0
      WHERE L461.PARENT_ID = :V$OBJ_ID AND L461.OBJ_TYPE_ID = 461 AND L461.DATE_DEL IS NULL AND PL.UID IS NULL
      ORDER BY 1
      INTO :V$TERM_ID, :V$UID, :V$DT, :V$SECTION, :V$DTT, :S, :V$VALID
    DO
    BEGIN
      TAG_NAME = 'items:r:items:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'items:r:items:r:id';
      VAL = V$TERM_ID;
      SUSPEND;
      TAG_NAME = 'items:r:items:r:uid';
      VAL = V$UID;
      SUSPEND;
      TAG_NAME = 'items:r:items:r:date';
      VAL = V$DT;
      SUSPEND;
      TAG_NAME = 'items:r:items:r:date_till';
      VAL = V$DTT;
      SUSPEND;
      TAG_NAME = 'items:r:items:r:section';
      VAL = (SELECT VAL FROM LISTVAL_TEXT(:V$SECTION));
      SUSPEND;
      TAG_NAME = 'items:r:items:r:content';
      VAL = S;
      SUSPEND;
      TAG_NAME = 'items:r:items:r:valid';
      VAL = IIF(V$VALID = 2, 1, 0);
      SUSPEND;

      N = N + 1;
    END
  END

  IF(N = 0) THEN EXCEPTION DATA_ERROR 'Нет данных для отправки';

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PORTAL_BROKEN_UID_GET RETURNS (
    STUDENT_CAPTION VARCHAR(4000))
AS
declare variable SCHOOL_ID bigint;
declare variable CLASS_ID bigint;
declare variable SCHOLAR_ID bigint;
declare variable PARENT_ID bigint;
declare variable EXT_PARENT_ID bigint;
BEGIN
    SELECT FIRST 1 L.OBJ_ID
    FROM LINKS L
    WHERE L.PARENT_ID IS NULL
    AND L.OBJ_TYPE_ID = 2
    AND L.DATE_DEL IS NULL
    INTO :SCHOOL_ID;

    FOR
        SELECT L9.OBJ_ID,
               L10.OBJ_ID,
               L20.OBJ_ID,
               L10.EXT_OBJ_ID
        FROM LINKS L7

        JOIN LINKS L8
        ON L8.PARENT_ID = L7.OBJ_ID
        AND L8.OBJ_TYPE_ID = 8
        AND L8.DATE_DEL IS NULL

        JOIN LINKS L9
        ON L9.PARENT_ID = L8.OBJ_ID
        AND L9.OBJ_TYPE_ID = 9
        AND L9.DATE_DEL IS NULL

        JOIN LINKS L10
        ON L10.PARENT_ID = L9.OBJ_ID
        AND L10.OBJ_TYPE_ID = 10
        AND L10.DATE_DEL IS NULL

        JOIN LINKS L20
        ON L20.PARENT_ID = L10.OBJ_ID
        AND L20.OBJ_TYPE_ID = 20
        AND L20.DATE_DEL IS NULL

        LEFT JOIN VALS V2
        ON V2.OBJ_ID = L20.OBJ_ID
        AND V2.PARAM_ID = 155
        AND V2.IS_DEL = 0

        JOIN VALS V1
        ON V1.OBJ_ID = L20.EXT_OBJ_ID
        AND V1.PARAM_ID = 1570
        AND V1.IS_DEL = 0

        WHERE L7.PARENT_ID = :SCHOOL_ID
        AND L7.OBJ_TYPE_ID = 7
        AND L7.DATE_DEL IS NULL

        AND V2.VAL IS NULL
        INTO :CLASS_ID,
             :SCHOLAR_ID,
             :PARENT_ID,
             :EXT_PARENT_ID
    DO
    BEGIN
        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:CLASS_ID)
        INTO :STUDENT_CAPTION;

        SELECT :STUDENT_CAPTION || ', ' || CAPTION
        FROM OBJECT_CAPTION_GET(:SCHOLAR_ID)
        INTO :STUDENT_CAPTION;

        SELECT :STUDENT_CAPTION || ', ' || V
        FROM VAL_GET(:EXT_PARENT_ID, 1573)
        INTO :STUDENT_CAPTION;

        SELECT :STUDENT_CAPTION || ' ' || CAPTION
        FROM OBJECT_CAPTION_GET(:PARENT_ID)
        INTO :STUDENT_CAPTION;

        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PORTAL_CLASSES_DELETED_GET (
    BEGIN_DATE TIMESTAMP,
    END_DATE TIMESTAMP)
RETURNS (
    CLASS_ID BIGINT)
AS
declare variable SCHOOL_ID bigint;
declare variable N integer;
BEGIN
    SELECT FIRST 1 L.OBJ_ID
    FROM LINKS L
    WHERE L.PARENT_ID IS NULL AND L.OBJ_TYPE_ID = 2 AND L.DATE_DEL IS NULL
    INTO :SCHOOL_ID;

    FOR
        -- С 2017 снова возвращено на выборку по классам
        -- Внимание: в течение учебного года категорически не допускается удалять уровни и этапы обучения !!!
        SELECT DISTINCT L9.OBJ_ID
        FROM LINKS L7
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NOT NULL AND ((:BEGIN_DATE IS NULL) OR (L9.DATE_DEL >= :BEGIN_DATE))
        WHERE L7.PARENT_ID = :SCHOOL_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
        INTO :CLASS_ID
    DO
    BEGIN
        -- Выдаем только те классы, на которые больше нет связей
        N = 0;
        SELECT FIRST 1 1
        FROM LINKS LP8
        WHERE LP8.OBJ_ID = :CLASS_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
        INTO :N;

        IF(N = 0) THEN SUSPEND;
    END

    -- Удаляем классы-экстернаты
    FOR
        SELECT DISTINCT L187.OBJ_ID
        FROM LINKS L7
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
        JOIN LINKS L187 ON L187.PARENT_ID = L8.OBJ_ID AND L187.OBJ_TYPE_ID = 187 AND L187.DATE_DEL IS NULL
        WHERE L7.PARENT_ID = :SCHOOL_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
        INTO :CLASS_ID
    DO
    BEGIN
        SUSPEND;
    END

END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PORTAL_CLASSES_GET (
    I$BEGIN_DATE TIMESTAMP,
    I$END_DATE TIMESTAMP,
    I$USER_ID BIGINT)
RETURNS (
    CLASS_ID BIGINT,
    GRADE_NAME VARCHAR(4000),
    STAGE_NAME VARCHAR(4000),
    CLASS_NAME VARCHAR(4000),
    CLASS_MASTER_ID BIGINT,
    PERIOD_ID BIGINT)
AS
declare variable SCHOOL_ID bigint;
declare variable DATE_MODIFY timestamp;
declare variable DATE_MODIFY_MASTER timestamp;
declare variable IS_MODIFIED smallint;
declare variable LANG_CODE varchar(2);
BEGIN
    SELECT LANG_CODE FROM USERS WHERE USER_ID = :I$USER_ID INTO :LANG_CODE;

    SELECT FIRST 1 L.OBJ_ID
    FROM LINKS L
    WHERE L.PARENT_ID IS NULL AND L.OBJ_TYPE_ID = 2 AND L.DATE_DEL IS NULL
    INTO :SCHOOL_ID;

    -- Выборка классов идет по реальным классам, а не по ГУП как было в 2016 !
    FOR
        SELECT L9.OBJ_ID, L9.DATE_MODIFY, R43.VAL, R49.VAL, C9.CAPTION, V53.VAL, V53.DATE_MODIFY
        -- Уровни образования
        FROM LINKS L7
        JOIN VALL V43 ON V43.OBJ_ID = L7.OBJ_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0
        JOIN LISTVALS LV43 ON LV43.LISTVAL_ID = V43.LISTVAL_ID
        JOIN RES R43 ON R43.RES_ID = LV43.RES_ID AND R43.LANG_CODE = 'RU'
        -- Этапы
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
        JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
        JOIN LISTVALS LV49 ON LV49.LISTVAL_ID = V49.LISTVAL_ID
        JOIN RES R49 ON R49.RES_ID = LV49.RES_ID AND R49.LANG_CODE = 'RU'
        -- Обычные классы и классы-экстернаты
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
        LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C9 ON 1 = 1
        -- Классный руководитель
        LEFT JOIN VALR V53 ON V53.PARAM_ID = 53 AND V53.OBJ_ID = L9.OBJ_ID AND V53.IS_DEL = 0
        WHERE L7.PARENT_ID = :SCHOOL_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
        ORDER BY LV43.SORT_ORDER, LV49.SORT_ORDER, L9.OBJ_ID
        INTO :CLASS_ID, :DATE_MODIFY, :GRADE_NAME, :STAGE_NAME, :CLASS_NAME, :CLASS_MASTER_ID, :DATE_MODIFY_MASTER
    DO
    BEGIN

        IS_MODIFIED = 0;
        PERIOD_ID = NULL;

        IF (((I$BEGIN_DATE IS NULL) OR (DATE_MODIFY >= I$BEGIN_DATE)) AND (DATE_MODIFY <= I$END_DATE)) THEN IS_MODIFIED = 1;

        -- Изменение буквы класса или названия класса-экстерната
        SELECT V.DATE_MODIFY
        FROM VALS V
        WHERE V.PARAM_ID IN (54, 1652) AND V.OBJ_ID = :CLASS_ID AND V.IS_DEL = 0
        INTO :DATE_MODIFY;

        IF (((I$BEGIN_DATE IS NULL) OR (DATE_MODIFY >= I$BEGIN_DATE)) AND (DATE_MODIFY <= I$END_DATE)) THEN IS_MODIFIED = 1;
        IF (((I$BEGIN_DATE IS NULL) OR (DATE_MODIFY_MASTER >= I$BEGIN_DATE)) AND (DATE_MODIFY_MASTER <= I$END_DATE)) THEN IS_MODIFIED = 1;

        -- Учебные периоды - поскольку они прикреплены не к классам, а к ГУП - выбираем первое что найдется среди учеников класса
        SELECT FIRST 1 LP151.PARENT_ID, LP151.DATE_MODIFY
        FROM LINKS L10
        -- ГУП или поток
        JOIN LINKS LPG ON LPG.OBJ_ID = L10.OBJ_ID AND LPG.PARENT_TYPE_ID IN (256, 347) AND LPG.DATE_DEL IS NULL
        -- Расписание учебных периодов
        JOIN LINKS LP151 ON LP151.OBJ_ID = LPG.PARENT_ID AND LP151.PARENT_TYPE_ID = 151 AND LP151.DATE_DEL IS NULL
        WHERE L10.PARENT_ID = :CLASS_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        INTO :PERIOD_ID, :DATE_MODIFY;

        IF (((I$BEGIN_DATE IS NULL) OR (DATE_MODIFY >= I$BEGIN_DATE)) AND (DATE_MODIFY <= I$END_DATE)) THEN IS_MODIFIED = 1;

        IF (IS_MODIFIED = 1) THEN SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PORTAL_DIRECTORS_DELETED_GET (
    BEGIN_DATE TIMESTAMP,
    END_DATE TIMESTAMP)
RETURNS (
    DIRECTOR_ID BIGINT)
AS
declare variable SCHOOL_ID bigint;
declare variable DATE_MODIFY timestamp;
declare variable IS_MODIFIED smallint;
BEGIN
    SELECT FIRST 1 L.OBJ_ID
    FROM LINKS L
    WHERE L.PARENT_ID IS NULL AND L.OBJ_TYPE_ID = 2 AND L.DATE_DEL IS NULL
    INTO :SCHOOL_ID;

    FOR SELECT L14.OBJ_ID, V74.DATE_MODIFY
        FROM LINKS L14
        JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
        JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0 AND V73.VAL <= CURRENT_DATE
        JOIN VALR V69 ON V69.OBJ_ID = L15.OBJ_ID AND V69.PARAM_ID = 69 AND V69.IS_DEL = 0
        JOIN VALL V64 ON V64.OBJ_ID = V69.VAL AND V64.PARAM_ID = 64 AND V64.IS_DEL = 0 AND V64.LISTVAL_ID = 56
        JOIN VALL V58 ON V58.OBJ_ID = V69.VAL AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0
        JOIN LISTVALS LV ON LV.LISTVAL_ID = V58.LISTVAL_ID
        JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0 AND V74.VAL IS NOT NULL
        WHERE L14.PARENT_ID = :SCHOOL_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
        INTO :DIRECTOR_ID, :DATE_MODIFY
    DO
    BEGIN
        IF (((BEGIN_DATE IS NULL) OR (DATE_MODIFY >= BEGIN_DATE)) AND (DATE_MODIFY <= END_DATE)) THEN SUSPEND;
    END

    FOR SELECT L14.OBJ_ID, V74.DATE_MODIFY
        FROM LINKS L84
        JOIN LINKS L14 ON L14.PARENT_ID = L84.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
        JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
        JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0 AND V73.VAL <= CURRENT_DATE
        JOIN VALR V69 ON V69.OBJ_ID = L15.OBJ_ID AND V69.PARAM_ID = 69 AND V69.IS_DEL = 0
        JOIN VALL V64 ON V64.OBJ_ID = V69.VAL AND V64.PARAM_ID = 64 AND V64.IS_DEL = 0 AND V64.LISTVAL_ID = 56
        JOIN VALL V58 ON V58.OBJ_ID = V69.VAL AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0
        JOIN LISTVALS LV ON LV.LISTVAL_ID = V58.LISTVAL_ID
        JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0 AND V74.VAL IS NOT NULL
        WHERE L84.PARENT_ID = :SCHOOL_ID AND L84.OBJ_TYPE_ID = 84 AND L84.DATE_DEL IS NULL
        INTO :DIRECTOR_ID, :DATE_MODIFY
    DO
    BEGIN
        IF (((BEGIN_DATE IS NULL) OR (DATE_MODIFY >= BEGIN_DATE)) AND (DATE_MODIFY <= END_DATE)) THEN SUSPEND;
    END

END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PORTAL_DIRECTORS_GET (
    BEGIN_DATE TIMESTAMP,
    END_DATE TIMESTAMP,
    I$USER_ID BIGINT)
RETURNS (
    DIRECTOR_ID BIGINT,
    UID VARCHAR(4000),
    FIO VARCHAR(4000),
    POST VARCHAR(4000))
AS
declare variable SCHOOL_ID bigint;
declare variable DATE_MODIFY timestamp;
declare variable IS_MODIFIED smallint;
declare variable V varchar(4000);
declare variable LANG_CODE varchar(2);
BEGIN
    SELECT LANG_CODE FROM USERS WHERE USER_ID = :I$USER_ID INTO :LANG_CODE;

    SELECT FIRST 1 L.OBJ_ID
    FROM LINKS L
    WHERE L.PARENT_ID IS NULL AND L.OBJ_TYPE_ID = 2 AND L.DATE_DEL IS NULL
    INTO :SCHOOL_ID;

    FOR SELECT FIRST 1 L14.OBJ_ID, R.VAL, L15.DATE_MODIFY
        FROM LINKS L14
        JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
        JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0 AND V73.VAL <= CURRENT_DATE
        JOIN VALR V69 ON V69.OBJ_ID = L15.OBJ_ID AND V69.PARAM_ID = 69 AND V69.IS_DEL = 0
        JOIN VALL V64 ON V64.OBJ_ID = V69.VAL AND V64.PARAM_ID = 64 AND V64.IS_DEL = 0 AND V64.LISTVAL_ID = 56
        JOIN VALL V58 ON V58.OBJ_ID = V69.VAL AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0
        JOIN LISTVALS LV ON LV.LISTVAL_ID = V58.LISTVAL_ID
        LEFT JOIN RES_GET(LV.RES_ID,  :LANG_CODE) R ON 1=1
        LEFT JOIN VALD V74 ON V74.PARAM_ID = 74 AND V74.OBJ_ID = L15.OBJ_ID
        WHERE L14.PARENT_ID = :SCHOOL_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL AND (V74.VAL IS NULL OR V74.IS_DEL = 1)
        INTO :DIRECTOR_ID, :POST, :DATE_MODIFY
    DO
    BEGIN
        IS_MODIFIED = 0;
        V = '';
        UID = NULL;

        IF (((BEGIN_DATE IS NULL) OR (DATE_MODIFY >= BEGIN_DATE)) AND (DATE_MODIFY <= END_DATE)) THEN IS_MODIFIED = 1;

        SELECT V.VAL, V.DATE_MODIFY
        FROM VALS V
        WHERE V.PARAM_ID = 59 AND V.OBJ_ID = :DIRECTOR_ID AND V.IS_DEL = 0
        INTO :V, :DATE_MODIFY;

        FIO = V;

        IF (((BEGIN_DATE IS NULL) OR (DATE_MODIFY >= BEGIN_DATE)) AND (DATE_MODIFY <= END_DATE)) THEN IS_MODIFIED = 1;

        V = '';

        SELECT V.VAL, V.DATE_MODIFY
        FROM VALS V
        WHERE V.PARAM_ID = 60 AND V.OBJ_ID = :DIRECTOR_ID AND V.IS_DEL = 0
        INTO :V, :DATE_MODIFY;

        IF (V > '') THEN FIO = FIO || ' ' || V;

        IF (((BEGIN_DATE IS NULL) OR (DATE_MODIFY >= BEGIN_DATE)) AND (DATE_MODIFY <= END_DATE)) THEN IS_MODIFIED = 1;

        V = '';

        SELECT V.VAL, V.DATE_MODIFY
        FROM VALS V
        WHERE V.PARAM_ID = 61 AND V.OBJ_ID = :DIRECTOR_ID AND V.IS_DEL = 0
        INTO :V, :DATE_MODIFY;

        IF (V > '') THEN FIO = FIO || ' ' || V;

        IF (((BEGIN_DATE IS NULL) OR (DATE_MODIFY >= BEGIN_DATE)) AND (DATE_MODIFY <= END_DATE)) THEN IS_MODIFIED = 1;

        SELECT V.VAL, V.DATE_MODIFY
        FROM VALS V
        WHERE V.PARAM_ID = 267 AND V.OBJ_ID = :DIRECTOR_ID AND V.IS_DEL = 0
        INTO :UID, :DATE_MODIFY;

        IF (((BEGIN_DATE IS NULL) OR (DATE_MODIFY >= BEGIN_DATE)) AND (DATE_MODIFY <= END_DATE)) THEN IS_MODIFIED = 1;

        IF ((IS_MODIFIED = 1) AND (FIO > '') AND (UID IS NOT NULL)) THEN SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PORTAL_EVENTS_DELETED_GET (
    BEGIN_DATE TIMESTAMP,
    END_DATE TIMESTAMP)
RETURNS (
    EVENT_ID BIGINT)
AS
BEGIN
    FOR SELECT L22.OBJ_ID
        FROM PORTAL_STUDENTS_WITH_UID_LIST(:BEGIN_DATE, :END_DATE) G
        INNER JOIN LINKS L22 ON L22.PARENT_ID = G.STUDENT_ID
        WHERE L22.OBJ_TYPE_ID = 22
          AND L22.DATE_DEL IS NOT NULL
          AND L22.DATE_MODIFY  <= :END_DATE
          AND ((:BEGIN_DATE IS NULL) OR (G.IS_FULL_EXPORT = 1) OR (L22.DATE_MODIFY >= :BEGIN_DATE))
        INTO :EVENT_ID
    DO
        SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PORTAL_EVENTS_GET (
    BEGIN_DATE TIMESTAMP,
    END_DATE TIMESTAMP,
    I$USER_ID BIGINT)
RETURNS (
    EVENT_ID BIGINT,
    STUDENT_ID BIGINT,
    TEACHER_ID BIGINT,
    EVENT_DATE DATE,
    EVENT_NAME VARCHAR(4000),
    EVENT_THEME VARCHAR(4000),
    EVENT_ACHIEVEMENT VARCHAR(4000),
    EVENT_AWARDS VARCHAR(4000))
AS
declare variable DATE_MODIFY timestamp;
declare variable IS_MODIFIED smallint;
declare variable IS_FULL_EXPORT smallint;
declare variable LANG_CODE varchar(2);
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :LANG_CODE;

    FOR
        SELECT G.STUDENT_ID, L22.OBJ_ID, G.IS_FULL_EXPORT, L22.DATE_MODIFY
        FROM PORTAL_STUDENTS_WITH_UID_LIST(:BEGIN_DATE, :END_DATE) G
        JOIN LINKS L22 ON L22.PARENT_ID = G.STUDENT_ID
        WHERE L22.OBJ_TYPE_ID = 22 AND L22.DATE_DEL IS NULL
        INTO :STUDENT_ID, :EVENT_ID, :IS_FULL_EXPORT, :DATE_MODIFY
    DO
    BEGIN
        IS_MODIFIED = 0;
        TEACHER_ID = NULL;
        EVENT_DATE = NULL;
        EVENT_NAME = NULL;
        EVENT_THEME = NULL;
        EVENT_ACHIEVEMENT = NULL;
        EVENT_AWARDS = NULL;

        IF (((BEGIN_DATE IS NULL) OR (IS_FULL_EXPORT = 1) OR (DATE_MODIFY >= BEGIN_DATE)) AND (DATE_MODIFY <= END_DATE)) THEN IS_MODIFIED = 1;

        SELECT V.VAL, V.DATE_MODIFY
        FROM VALR V
        WHERE V.PARAM_ID = 170 AND V.OBJ_ID = :EVENT_ID AND V.IS_DEL = 0
        INTO :TEACHER_ID, :DATE_MODIFY;

        IF (((BEGIN_DATE IS NULL) OR (IS_FULL_EXPORT = 1) OR (DATE_MODIFY >= BEGIN_DATE)) AND (DATE_MODIFY <= END_DATE)) THEN IS_MODIFIED = 1;

        SELECT V.VAL, V.DATE_MODIFY
        FROM VALD V
        WHERE V.PARAM_ID = 166 AND V.OBJ_ID = :EVENT_ID AND V.IS_DEL = 0
        INTO :EVENT_DATE, :DATE_MODIFY;

        IF (((BEGIN_DATE IS NULL) OR (IS_FULL_EXPORT = 1) OR (DATE_MODIFY >= BEGIN_DATE)) AND (DATE_MODIFY <= END_DATE)) THEN IS_MODIFIED = 1;

        SELECT V.VAL, V.DATE_MODIFY
        FROM VALS V
        WHERE V.PARAM_ID = 167 AND V.OBJ_ID = :EVENT_ID AND V.IS_DEL = 0
        INTO :EVENT_NAME, :DATE_MODIFY;

        IF (((BEGIN_DATE IS NULL) OR (IS_FULL_EXPORT = 1) OR (DATE_MODIFY >= BEGIN_DATE)) AND (DATE_MODIFY <= END_DATE)) THEN IS_MODIFIED = 1;

        SELECT V.VAL, V.DATE_MODIFY
        FROM VALS V
        WHERE V.PARAM_ID = 168 AND V.OBJ_ID = :EVENT_ID AND V.IS_DEL = 0
        INTO :EVENT_THEME, :DATE_MODIFY;

        IF (((BEGIN_DATE IS NULL) OR (IS_FULL_EXPORT = 1) OR (DATE_MODIFY >= BEGIN_DATE)) AND (DATE_MODIFY <= END_DATE)) THEN IS_MODIFIED = 1;

        SELECT R.VAL, V.DATE_MODIFY
        FROM VALL V
        JOIN LISTVALS LV ON LV.LISTVAL_ID = V.LISTVAL_ID
        LEFT JOIN RES_GET(LV.RES_ID,  :LANG_CODE) R ON 1=1
        WHERE V.PARAM_ID = 169 AND V.OBJ_ID = :EVENT_ID AND V.IS_DEL = 0
        INTO :EVENT_ACHIEVEMENT, :DATE_MODIFY;

        IF (((BEGIN_DATE IS NULL) OR (IS_FULL_EXPORT = 1) OR (DATE_MODIFY >= BEGIN_DATE)) AND (DATE_MODIFY <= END_DATE)) THEN
            IS_MODIFIED = 1;

        SELECT R.VAL, V.DATE_MODIFY
        FROM VALL V
        JOIN LISTVALS LV ON LV.LISTVAL_ID = V.LISTVAL_ID
        LEFT JOIN RES_GET(LV.RES_ID,  :LANG_CODE) R ON 1=1
        WHERE V.PARAM_ID = 237 AND V.OBJ_ID = :EVENT_ID AND V.IS_DEL = 0
        INTO :EVENT_AWARDS, :DATE_MODIFY;

        IF (((BEGIN_DATE IS NULL) OR (IS_FULL_EXPORT = 1) OR (DATE_MODIFY >= BEGIN_DATE)) AND (DATE_MODIFY <= END_DATE)) THEN IS_MODIFIED = 1;

        IF ((IS_MODIFIED = 1) AND (EVENT_DATE IS NOT NULL) AND (EVENT_NAME IS NOT NULL)) THEN SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PORTAL_EXPORT_PROPERTIES_GET RETURNS (
    FTP_ADDRESS VARCHAR(100),
    FTP_LOGIN VARCHAR(100),
    FTP_PWD VARCHAR(100),
    FTP_MODE VARCHAR(100),
    PROXY_IS_USE VARCHAR(100),
    PROXY_ADDRESS VARCHAR(100),
    PROXY_PORT VARCHAR(100),
    EXPORT_INTERVAL VARCHAR(100),
    PROXY_LOGIN VARCHAR(100),
    PROXY_PWD VARCHAR(100),
    ROD_ADDRESS VARCHAR(100),
    ROD_LOGIN VARCHAR(100),
    ROD_PWD VARCHAR(100),
    ROD_TIMEOUT VARCHAR(100),
    ROD_EXPORT_INTERVAL VARCHAR(100),
    KONTINGENT_ADDRESS VARCHAR(100),
    KONTINGENT_PORT VARCHAR(100),
    KONTINGENT_LOGIN VARCHAR(100),
    KONTINGENT_PWD VARCHAR(100),
    KONTINGENT_TIMEOUT VARCHAR(100),
    KONTINGENT_EXPORT_INTERVAL VARCHAR(100))
AS
BEGIN
    SELECT FIRST 1 INFO_VAL FROM INFO  WHERE INFO_CODE = 'PORTAL_FTP_ADDRESS' INTO :FTP_ADDRESS;
    SELECT FIRST 1 INFO_VAL FROM INFO  WHERE INFO_CODE = 'PORTAL_FTP_LOGIN' INTO :FTP_LOGIN;
    SELECT FIRST 1 INFO_VAL FROM INFO  WHERE INFO_CODE = 'PORTAL_FTP_PWD' INTO :FTP_PWD;
    SELECT FIRST 1 INFO_VAL FROM INFO  WHERE INFO_CODE = 'PORTAL_FTP_MODE' INTO :FTP_MODE;
    SELECT FIRST 1 INFO_VAL FROM INFO  WHERE INFO_CODE = 'PORTAL_EXPORT_INTERVAL' INTO :EXPORT_INTERVAL;
    SELECT FIRST 1 INFO_VAL FROM INFO  WHERE INFO_CODE = 'PORTAL_PROXY_IS_USE' INTO :PROXY_IS_USE;
    SELECT FIRST 1 INFO_VAL FROM INFO  WHERE INFO_CODE = 'PORTAL_PROXY_ADDRESS' INTO :PROXY_ADDRESS;
    SELECT FIRST 1 INFO_VAL FROM INFO  WHERE INFO_CODE = 'PORTAL_PROXY_PORT' INTO :PROXY_PORT;
    SELECT FIRST 1 INFO_VAL FROM INFO  WHERE INFO_CODE = 'PROXY_LOGIN' INTO :PROXY_LOGIN;
    SELECT FIRST 1 INFO_VAL FROM INFO  WHERE INFO_CODE = 'PROXY_PWD' INTO :PROXY_PWD;

    SELECT FIRST 1 INFO_VAL FROM INFO  WHERE INFO_CODE = 'ROD_ADDRESS' INTO :ROD_ADDRESS;
    SELECT FIRST 1 INFO_VAL FROM INFO  WHERE INFO_CODE = 'ROD_LOGIN' INTO :ROD_LOGIN;
    SELECT FIRST 1 INFO_VAL FROM INFO  WHERE INFO_CODE = 'ROD_PWD' INTO :ROD_PWD;
    SELECT FIRST 1 INFO_VAL FROM INFO  WHERE INFO_CODE = 'ROD_TIMEOUT' INTO :ROD_TIMEOUT;
    SELECT FIRST 1 INFO_VAL FROM INFO  WHERE INFO_CODE = 'ROD_EXPORT_INTERVAL' INTO :ROD_EXPORT_INTERVAL;

    KONTINGENT_ADDRESS = 'example.ru:/uploaddir';
    KONTINGENT_PORT = '22';
    KONTINGENT_LOGIN = 'username';
    KONTINGENT_TIMEOUT = '30';
    KONTINGENT_EXPORT_INTERVAL = '1440';
    SELECT FIRST 1 INFO_VAL FROM INFO  WHERE INFO_CODE = 'KONTINGENT_FTP_ADDRESS' INTO :KONTINGENT_ADDRESS;
    SELECT FIRST 1 INFO_VAL FROM INFO  WHERE INFO_CODE = 'KONTINGENT_FTP_PORT' INTO :KONTINGENT_PORT;
    SELECT FIRST 1 INFO_VAL FROM INFO  WHERE INFO_CODE = 'KONTINGENT_FTP_LOGIN' INTO :KONTINGENT_LOGIN;
    SELECT FIRST 1 INFO_VAL FROM INFO  WHERE INFO_CODE = 'KONTINGENT_FTP_PWD' INTO :KONTINGENT_PWD;
    SELECT FIRST 1 INFO_VAL FROM INFO  WHERE INFO_CODE = 'KONTINGENT_FTP_MODE' INTO :KONTINGENT_TIMEOUT;
    SELECT FIRST 1 INFO_VAL FROM INFO  WHERE INFO_CODE = 'KONTINGENT_EXPORT_INTERVAL' INTO :KONTINGENT_EXPORT_INTERVAL;

    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PORTAL_EXPORT_PROPERTIES_SET (
    FTP_ADDRESS VARCHAR(100),
    FTP_LOGIN VARCHAR(100),
    FTP_PWD VARCHAR(100),
    FTP_MODE VARCHAR(100),
    PROXY_IS_USE VARCHAR(100),
    PROXY_ADDRESS VARCHAR(100),
    PROXY_PORT VARCHAR(100),
    EXPORT_INTERVAL VARCHAR(100),
    PROXY_LOGIN VARCHAR(100),
    PROXY_PWD VARCHAR(100))
AS
BEGIN
    UPDATE OR INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
    VALUES ('PORTAL_FTP_ADDRESS', 'PORTAL_FTP_ADDRESS', :FTP_ADDRESS)
    MATCHING (INFO_CODE);

    UPDATE OR INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
    VALUES ('PORTAL_FTP_LOGIN', 'PORTAL_FTP_LOGIN', :FTP_LOGIN)
    MATCHING (INFO_CODE);

    UPDATE OR INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
    VALUES ('PORTAL_FTP_PWD', 'PORTAL_FTP_PWD', :FTP_PWD)
    MATCHING (INFO_CODE);

    UPDATE OR INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
    VALUES ('PORTAL_FTP_MODE', 'PORTAL_FTP_MODE', :FTP_MODE)
    MATCHING (INFO_CODE);

    UPDATE OR INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
    VALUES ('PORTAL_PROXY_IS_USE', 'PORTAL_PROXY_IS_USE', :PROXY_IS_USE)
    MATCHING (INFO_CODE);

    UPDATE OR INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
    VALUES ('PORTAL_PROXY_ADDRESS', 'PORTAL_PROXY_ADDRESS', :PROXY_ADDRESS)
    MATCHING (INFO_CODE);

    UPDATE OR INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
    VALUES ('PORTAL_PROXY_PORT', 'PORTAL_PROXY_PORT', :PROXY_PORT)
    MATCHING (INFO_CODE);

    UPDATE OR INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
    VALUES ('PORTAL_EXPORT_INTERVAL', 'PORTAL_EXPORT_INTERVAL', :EXPORT_INTERVAL)
    MATCHING (INFO_CODE);

    UPDATE OR INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
    VALUES ('PROXY_LOGIN', 'PROXY_LOGIN', :PROXY_LOGIN)
    MATCHING (INFO_CODE);

    UPDATE OR INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
    VALUES ('PROXY_PWD', 'PROXY_PWD', :PROXY_PWD)
    MATCHING (INFO_CODE);
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PORTAL_GIA_ASSN (
    I$BEGIN_DATE TIMESTAMP,
    I$END_DATE TIMESTAMP)
RETURNS (
    TAG_NAME VARCHAR(255),
    VAL VARCHAR(4000))
AS
declare variable YEAR_ID bigint;
declare variable YEAR_NUM integer;
declare variable YEAR_NAME varchar(100);
declare variable OBJ_ID bigint;
declare variable EXAM_DATE date;
declare variable EXAM_STAGE bigint;
declare variable EXAM_TYPE bigint;
declare variable EXAM_SUBJECT bigint;
declare variable PUPIL_ID bigint;
declare variable ASSN_ID bigint;
declare variable HAVE_UID smallint;
declare variable IS_MODIFIED smallint;
begin
    -- Сначала список эказменов
    VAL = NULL;
    TAG_NAME = 'exam_assn:exams';
    SUSPEND;

    -- Получаем текущий учебный год - он точно должен быть уникален
    YEAR_NUM = EXTRACT(YEAR FROM CURRENT_DATE);
    IF(EXTRACT(MONTH FROM CURRENT_DATE) < 9) THEN YEAR_NAME = (YEAR_NUM - 1 )|| '-' || YEAR_NUM; ELSE YEAR_NAME = YEAR_NUM || '-' || (YEAR_NUM + 1);

    SELECT L119.OBJ_ID
    FROM LISTVALS L29
    JOIN RES R29 ON R29.RES_ID = L29.RES_ID AND R29.LANG_CODE = 'RU' AND R29.VAL = :YEAR_NAME
    JOIN LINKS L119 ON L119.PARENT_TYPE_ID = 118 AND L119.OBJ_TYPE_ID = 119 AND L119.DATE_DEL IS NULL
    JOIN VALL V742 ON V742.OBJ_ID = L119.OBJ_ID AND V742.PARAM_ID = 742 AND V742.LISTVAL_ID = L29.LISTVAL_ID AND V742.IS_DEL = 0
    WHERE L29.LIST_ID = 29 AND L29.IS_DEL = 0
    INTO :YEAR_ID;

    -- Если года нет, выдаем пустой id и заканчиваем
    IF(YEAR_ID IS NULL) THEN
    BEGIN
        VAL = '';
        TAG_NAME = 'exam_assn:exams::period_id';
        SUSPEND;
        EXIT;
    END

    VAL = YEAR_ID;
    TAG_NAME = 'exam_assn:exams::period_id';
    SUSPEND;

    -- Список экзаменов, которые поменялись в указанный период времени
    FOR
        SELECT L120.OBJ_ID, V804.VAL, V801.LISTVAL_ID, V802.LISTVAL_ID, V803.LISTVAL_ID
        FROM LINKS L120
        JOIN VALL V801 ON V801.OBJ_ID = L120.OBJ_ID AND V801.PARAM_ID = 801 AND V801.IS_DEL = 0
        JOIN VALL V802 ON V802.OBJ_ID = L120.OBJ_ID AND V802.PARAM_ID = 802 AND V802.IS_DEL = 0
        JOIN VALL V803 ON V803.OBJ_ID = L120.OBJ_ID AND V803.PARAM_ID = 803 AND V803.IS_DEL = 0
        JOIN VALD V804 ON V804.OBJ_ID = L120.OBJ_ID AND V804.PARAM_ID = 804 AND V804.IS_DEL = 0
        WHERE L120.PARENT_ID = :YEAR_ID AND L120.OBJ_TYPE_ID = 120 AND L120.DATE_DEL IS NULL
            AND (:I$BEGIN_DATE IS NULL OR L120.DATE_MODIFY >= :I$BEGIN_DATE)
        INTO :OBJ_ID, :EXAM_DATE, :EXAM_STAGE, :EXAM_TYPE, :EXAM_SUBJECT
    DO
    BEGIN
        -- Новый тег
        VAL = NULL;
        TAG_NAME = 'exam_assn:exams:exam';
        SUSPEND;
        -- ID
        VAL = OBJ_ID;
        TAG_NAME = 'exam_assn:exams:exam::id';
        SUSPEND;
        -- Дата
        VAL = EXAM_DATE;
        TAG_NAME = 'exam_assn:exams:exam::date';
        SUSPEND;
        -- Ступень
        VAL = EXAM_STAGE;
        TAG_NAME = 'exam_assn:exams:exam::stage';
        SUSPEND;
        -- Тип
        VAL = EXAM_TYPE;
        TAG_NAME = 'exam_assn:exams:exam::type';
        SUSPEND;
        -- Предмет
        VAL = EXAM_SUBJECT;
        TAG_NAME = 'exam_assn:exams:exam::subject';
        SUSPEND;
    END
    -- Удаленные экзамены
    VAL = NULL;
    TAG_NAME = 'exam_assn:exams_deleted';
    SUSPEND;
    FOR
        SELECT L120.OBJ_ID
        FROM LINKS L120
        WHERE L120.PARENT_ID = :YEAR_ID AND L120.OBJ_TYPE_ID = 120 AND L120.DATE_DEL IS NOT NULL
            AND (:I$BEGIN_DATE IS NULL OR L120.DATE_DEL >= :I$BEGIN_DATE)
        INTO :OBJ_ID
    DO
    BEGIN
        VAL = NULL;
        TAG_NAME = 'exam_assn:exams_deleted:exam';
        SUSPEND;
        VAL = OBJ_ID;
        TAG_NAME = 'exam_assn:exams_deleted:exam::id';
        SUSPEND;
    END

    -- Список всех назначений, которые поменялись в указанный промежуток времени, для учеников, у которых имеется код
    VAL = NULL;
    TAG_NAME = 'exam_assn:assn';
    SUSPEND;
    FOR
        SELECT L120.OBJ_ID, L10.PARENT_ID, L10.LINK_ID
        FROM LINKS L120
        JOIN LINKS L10 ON L10.OBJ_ID = L120.OBJ_ID AND L10.PARENT_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
            AND (:I$BEGIN_DATE IS NULL OR L10.DATE_INS >= :I$BEGIN_DATE)
        WHERE L120.PARENT_ID = :YEAR_ID AND L120.OBJ_TYPE_ID = 120 AND L120.DATE_DEL IS NULL
        ORDER BY 1, 2
        INTO :OBJ_ID, :PUPIL_ID, :ASSN_ID
    DO
    BEGIN
        HAVE_UID = 0;

        -- Есть ли у ученика портальный ID ?
        SELECT FIRST 1 1
        FROM LINKS L20
        JOIN VALS V1570 ON V1570.OBJ_ID = L20.EXT_OBJ_ID AND V1570.PARAM_ID = 1570 AND V1570.IS_DEL = 0
        JOIN VALS V155 ON V155.OBJ_ID = L20.OBJ_ID AND V155.PARAM_ID = 155 AND V155.IS_DEL = 0
        WHERE L20.PARENT_ID = :PUPIL_ID AND L20.OBJ_TYPE_ID = 20 AND L20.DATE_DEL IS NULL
        INTO :HAVE_UID;

        IF(HAVE_UID = 1) THEN
        BEGIN

            IS_MODIFIED = 0;

            -- Изменение портального ID ученика
            SELECT FIRST 1 1
            FROM LINKS L
            JOIN VALS V1 ON V1.OBJ_ID = L.EXT_OBJ_ID AND V1.PARAM_ID = 1570 AND (:I$BEGIN_DATE IS NULL OR V1.DATE_MODIFY >= :I$BEGIN_DATE) AND V1.DATE_MODIFY <= :I$END_DATE
            WHERE L.PARENT_ID = :PUPIL_ID AND L.OBJ_TYPE_ID = 20 AND L.DATE_DEL IS NULL
            INTO :IS_MODIFIED;

            -- Изменение портального ID родителя
            SELECT FIRST 1 1
            FROM LINKS L
            JOIN VALS V1 ON V1.OBJ_ID = L.OBJ_ID AND V1.PARAM_ID = 155 AND (:I$BEGIN_DATE IS NULL OR V1.DATE_MODIFY >= :I$BEGIN_DATE) AND V1.DATE_MODIFY <= :I$END_DATE
            WHERE L.PARENT_ID = :PUPIL_ID AND L.OBJ_TYPE_ID = 20 AND L.DATE_DEL IS NULL
            INTO :IS_MODIFIED;

            IF(IS_MODIFIED = 1) THEN
            BEGIN
                VAL = NULL;
                TAG_NAME = 'exam_assn:assn:assn';
                SUSPEND;
                VAL = ASSN_ID;
                TAG_NAME = 'exam_assn:assn:assn::id';
                SUSPEND;
                VAL = OBJ_ID;
                TAG_NAME = 'exam_assn:assn:assn::exam_id';
                SUSPEND;
                VAL = PUPIL_ID;
                TAG_NAME = 'exam_assn:assn:assn::pupil_id';
                SUSPEND;
            END
        END
    END
    -- Удаленные назначения - везде где есть или когда-то был ID
    VAL = NULL;
    TAG_NAME = 'exam_assn:assn_deleted';
    SUSPEND;
    FOR
        SELECT L10.LINK_ID
        FROM LINKS L120
        JOIN LINKS L10 ON L10.OBJ_ID = L120.OBJ_ID AND L10.PARENT_TYPE_ID = 10 AND L10.DATE_DEL IS NOT NULL
            AND (:I$BEGIN_DATE IS NULL OR L10.DATE_DEL >= :I$BEGIN_DATE)
        WHERE L120.PARENT_ID = :YEAR_ID AND L120.OBJ_TYPE_ID = 120 AND L120.DATE_DEL IS NULL
        INTO :ASSN_ID
    DO
    BEGIN
        HAVE_UID = 0;

        SELECT FIRST 1 1
        FROM LINKS L20
        JOIN VALS V1570 ON V1570.OBJ_ID = L20.EXT_OBJ_ID AND V1570.PARAM_ID = 1570
        JOIN VALS V155 ON V155.OBJ_ID = L20.OBJ_ID AND V155.PARAM_ID = 155
        WHERE L20.PARENT_ID = :PUPIL_ID AND L20.OBJ_TYPE_ID = 20
        INTO :HAVE_UID;

        IF(HAVE_UID = 1) THEN
        BEGIN
            VAL = NULL;
            TAG_NAME = 'exam_assn:assn_deleted:assn';
            SUSPEND;
            VAL = ASSN_ID;
            TAG_NAME = 'exam_assn:assn_deleted:assn::id';
            SUSPEND;
        END
    END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PORTAL_GIA_MARKS_DELETED_GET (
    BEGIN_DATE TIMESTAMP,
    END_DATE TIMESTAMP)
RETURNS (
    USE_MARK_ID BIGINT)
AS
BEGIN
    FOR SELECT L123.OBJ_ID
        FROM PORTAL_STUDENTS_WITH_UID_LIST(:BEGIN_DATE, :END_DATE) G
        JOIN LINKS L123 ON L123.PARENT_ID = G.STUDENT_ID
        WHERE L123.OBJ_TYPE_ID = 123
          AND L123.DATE_DEL IS NOT NULL
          AND L123.DATE_MODIFY <= :END_DATE
          AND ((:BEGIN_DATE IS NULL) OR (G.IS_FULL_EXPORT = 1) OR (L123.DATE_MODIFY >= :BEGIN_DATE))
        INTO :USE_MARK_ID
    DO
        SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PORTAL_GIA_MARKS_GET (
    I$BEGIN_DATE TIMESTAMP,
    I$END_DATE TIMESTAMP,
    I$USER_ID BIGINT)
RETURNS (
    USE_MARK_ID BIGINT,
    GIA_SUBJECT_CODE SMALLINT,
    STUDENT_ID BIGINT,
    GIA_YEAR SMALLINT,
    GIA_TYPE SMALLINT,
    MARK_100 SMALLINT,
    MARK SMALLINT,
    RESULTS_A VARCHAR(400),
    RESULTS_B VARCHAR(400),
    RESULTS_C VARCHAR(400),
    RESULTS_D VARCHAR(400))
AS
declare variable LANG_CODE varchar(2);
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :LANG_CODE;

    FOR
        SELECT L123.OBJ_ID, SB.TAG, G.STUDENT_ID, V816.VAL, V817.VAL, R.VAL_LONG, RS.VAL_LONG, V808.VAL, V809.VAL, V810.VAL, V811.VAL
        FROM PORTAL_STUDENTS_WITH_UID_LIST(:I$BEGIN_DATE, :I$END_DATE) G
        JOIN LINKS L120 ON L120.PARENT_ID = G.STUDENT_ID AND L120.OBJ_TYPE_ID = 120 AND L120.DATE_DEL IS NULL
        JOIN LINKS L123 ON L123.PARENT_ID = G.STUDENT_ID AND L123.OBJ_TYPE_ID = 123 AND L123.DATE_DEL IS NULL
        JOIN LINKS L123_L120 ON L123_L120.PARENT_ID = L120.OBJ_ID AND L123_L120.OBJ_ID = L123.OBJ_ID AND L123_L120.OBJ_TYPE_ID = 123 AND L123_L120.DATE_DEL IS NULL
        JOIN LINKS L119 ON L119.OBJ_ID = L120.OBJ_ID AND L119.PARENT_TYPE_ID = 119 AND L119.DATE_DEL IS NULL
        JOIN VALL V803 ON V803.OBJ_ID = L120.OBJ_ID AND V803.PARAM_ID = 803 AND V803.IS_DEL = 0
        JOIN LISTVALS SB ON SB.LISTVAL_ID = V803.LISTVAL_ID
        JOIN VALL V801 ON V801.OBJ_ID = L120.OBJ_ID AND V801.PARAM_ID = 801 AND V801.IS_DEL = 0
        JOIN LISTVALS LV ON LV.LISTVAL_ID = V801.LISTVAL_ID
        LEFT JOIN RES_GET(LV.RES_ID,  :LANG_CODE) R ON 1=1
        JOIN VALL V742 ON V742.OBJ_ID = L119.PARENT_ID AND V742.PARAM_ID = 742 AND V742.IS_DEL = 0
        JOIN LISTVALS LS ON LS.LISTVAL_ID = V742.LISTVAL_ID
        LEFT JOIN RES_GET(LS.RES_ID,  :LANG_CODE) RS ON 1=1
        JOIN VALI V816 ON V816.OBJ_ID = L123.OBJ_ID AND V816.PARAM_ID = 816 AND V816.IS_DEL = 0
        JOIN VALI V817 ON V817.OBJ_ID = L123.OBJ_ID AND V817.PARAM_ID = 817 AND V817.IS_DEL = 0
        -- Баллы по разделам
        LEFT JOIN VALS V808 ON V808.OBJ_ID = L123.OBJ_ID AND V808.PARAM_ID = 808 AND V808.IS_DEL = 0
        LEFT JOIN VALS V809 ON V809.OBJ_ID = L123.OBJ_ID AND V809.PARAM_ID = 809 AND V809.IS_DEL = 0
        LEFT JOIN VALS V810 ON V810.OBJ_ID = L123.OBJ_ID AND V810.PARAM_ID = 810 AND V810.IS_DEL = 0
        LEFT JOIN VALS V811 ON V811.OBJ_ID = L123.OBJ_ID AND V811.PARAM_ID = 811 AND V811.IS_DEL = 0
        WHERE V816.DATE_MODIFY <= :I$END_DATE
          AND ((:I$BEGIN_DATE IS NULL) OR (G.IS_FULL_EXPORT = 1) OR (V816.DATE_MODIFY >= :I$BEGIN_DATE))
        INTO :USE_MARK_ID, :GIA_SUBJECT_CODE, :STUDENT_ID, :MARK_100, :MARK, :GIA_TYPE, :GIA_YEAR, :RESULTS_A, :RESULTS_B, :RESULTS_C, :RESULTS_D
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PORTAL_GIS_DATA_GET (
    I$USER_ID BIGINT)
RETURNS (
    SCHOOL_ID BIGINT,
    FIELD_BLOCK VARCHAR(10),
    FIELD_TYPE VARCHAR(10),
    FIELD_NAME VARCHAR(30),
    FIELD_ITEM VARCHAR(10),
    FIELD_VAL VARCHAR(4000))
AS
declare variable ROOT_ID bigint;
declare variable OGRN varchar(100);
declare variable FULLNAME varchar(4000);
declare variable SHORTNAME varchar(1000);
declare variable OUTYPE integer;
declare variable OUKIND integer;
declare variable F varchar(250);
declare variable I varchar(250);
declare variable O varchar(250);
declare variable POST varchar(250);
declare variable REGION varchar(255);
declare variable DISTRICT varchar(255);
declare variable TOWN varchar(255);
declare variable SETTLEMENT varchar(255);
declare variable STREET varchar(255);
declare variable HOUSE varchar(10);
declare variable LITER varchar(10);
declare variable CORP varchar(10);
declare variable FLAT varchar(10);
declare variable POST_INDEX varchar(20);
declare variable BUILDING_ID bigint;
BEGIN
    SELECT FIRST 1 L.OBJ_ID
    FROM LINKS L
    WHERE L.PARENT_ID IS NULL
      AND ((L.OBJ_TYPE_ID = 111) OR (L.OBJ_TYPE_ID = 112)) /* district or region */
      AND L.DATE_DEL IS NULL
    INTO :ROOT_ID;

    FOR SELECT O.OBJ_ID, V9.VAL, V2.VAL, V5.VAL, V11.LISTVAL_ID, V10.LISTVAL_ID
        FROM OBJECT_CHILDREN_GET_DEEP(:ROOT_ID, 2, 2) O
        INNER JOIN VALS V9 ON V9.OBJ_ID = O.OBJ_ID
        INNER JOIN VALS V2 ON V2.OBJ_ID = O.OBJ_ID
        INNER JOIN VALS V5 ON V5.OBJ_ID = O.OBJ_ID
        INNER JOIN VALL V11 ON V11.OBJ_ID = O.OBJ_ID
        INNER JOIN VALL V10 ON V10.OBJ_ID = O.OBJ_ID
        WHERE V9.PARAM_ID = 9
          AND V9.IS_DEL = 0
          AND V2.PARAM_ID = 2
          AND V2.IS_DEL = 0
          AND V5.PARAM_ID = 5
          AND V5.IS_DEL = 0
          AND V11.PARAM_ID = 11
          AND V11.IS_DEL = 0
          AND V10.PARAM_ID = 10
          AND V10.IS_DEL = 0
        INTO :SCHOOL_ID, :OGRN, :SHORTNAME, :FULLNAME, :OUTYPE, :OUKIND
    DO
    BEGIN
        /* required */
        FIELD_BLOCK = 'required';

        FIELD_TYPE = 'string';
        FIELD_ITEM = '';
        FIELD_NAME = 'uid';/* OGRN */
        FIELD_VAL = OGRN;
        SUSPEND;
        FIELD_TYPE = 'string';
        FIELD_ITEM = '';
        FIELD_NAME = 'Short_name';
        FIELD_VAL = SHORTNAME;
        SUSPEND;
        FIELD_TYPE = 'string';
        FIELD_ITEM = '';
        FIELD_NAME = 'Charter_full_name';
        FIELD_VAL = FULLNAME;
        SUSPEND;
        FIELD_NAME = 'Charter_short_name';
        FIELD_ITEM = '';
        FIELD_TYPE = 'string';
        SELECT V
        FROM VAL_GET(:SCHOOL_ID, 999, 0, :I$USER_ID)
        INTO :FIELD_VAL;
        SUSPEND;
        FIELD_NAME = 'School_number';
        FIELD_ITEM = '';
        FIELD_TYPE = 'int';
        SELECT V
        FROM VAL_GET(:SCHOOL_ID, 17, 0, :I$USER_ID)
        INTO :FIELD_VAL;
        IF (FIELD_VAL != '') THEN
        BEGIN
            SUSPEND;
        END

        DISTRICT = '';
        SELECT V.LISTVAL_ID
        FROM LINKS L111
        JOIN VALL V
        ON V.OBJ_ID = L111.PARENT_ID
        AND V.PARAM_ID = 665
        AND V.IS_DEL = 0
        WHERE L111.OBJ_ID = :SCHOOL_ID
        AND L111.PARENT_TYPE_ID = 111
        AND L111.DATE_DEL IS NULL
        INTO :DISTRICT;
        FIELD_NAME = 'District';
        FIELD_TYPE = 'int';
        FIELD_ITEM = '';
        FIELD_VAL = DISTRICT;
        SUSPEND;
        FIELD_TYPE = 'int';
        FIELD_ITEM = '';
        FIELD_NAME = 'School_type';
        FIELD_VAL = OUTYPE;
        SUSPEND;
        FIELD_TYPE = 'int';
        FIELD_ITEM = '';
        FIELD_NAME = 'School_kind';
        FIELD_VAL = OUKIND;
        SUSPEND;

        FIELD_NAME = 'School_subtype';
        FIELD_ITEM = '';
        FIELD_TYPE = 'string';
        OUTYPE = 0;
        SELECT V
        FROM VAL_GET(:SCHOOL_ID, 937, 0, :I$USER_ID)
        INTO :FIELD_VAL;
        IF (FIELD_VAL != '') THEN
        BEGIN
            SUSPEND;
        END

        FIELD_NAME = 'OPF';
        FIELD_ITEM = '';
        FIELD_TYPE = 'int';
        SELECT I
        FROM VAL_GET(:SCHOOL_ID, 8, 0, :I$USER_ID)
        INTO :FIELD_VAL;
        SUSPEND;

        FIELD_NAME = 'legal_address';
        FIELD_TYPE = 'address';
        REGION = '';
        DISTRICT = '';
        TOWN = '';
        SETTLEMENT = '';
        STREET = '';
        HOUSE = '';
        LITER = '';
        CORP = '';
        FLAT = '';
        POST_INDEX = '';
        SELECT REGION, DISTRICT, TOWN, SETTLEMENT, STREET, HOUSE, LITER, CORP, FLAT, POST_INDEX
        FROM VALA
        WHERE PARAM_ID = 27
          AND OBJ_ID = :SCHOOL_ID
        INTO :REGION, :DISTRICT, :TOWN, :SETTLEMENT, :STREET, :HOUSE, :LITER, :CORP, :FLAT, :POST_INDEX;

        IF ((REGION != '')
        OR (DISTRICT != '')
        OR (TOWN != '')
        OR (SETTLEMENT != '')
        OR (STREET != '')
        OR (HOUSE != '')
        OR (LITER != '')
        OR (CORP != '')
        OR (FLAT != ''))
        THEN
        BEGIN
            FIELD_ITEM = 'Region';
            FIELD_VAL = REGION;
            SUSPEND;
            FIELD_ITEM = 'District';
            FIELD_VAL = DISTRICT;
            SUSPEND;
            FIELD_ITEM = 'Town';
            FIELD_VAL = TOWN;
            SUSPEND;
            FIELD_ITEM = 'Settlement';
            FIELD_VAL = SETTLEMENT;
            SUSPEND;
            FIELD_ITEM = 'Street';
            FIELD_VAL = STREET;
            SUSPEND;
            FIELD_ITEM = 'House';
            FIELD_VAL = HOUSE;
            SUSPEND;
            FIELD_ITEM = 'Liter';
            FIELD_VAL = LITER;
            SUSPEND;
            FIELD_ITEM = 'Corp';
            FIELD_VAL = CORP;
            SUSPEND;
            FIELD_ITEM = 'Flat';
            FIELD_VAL = FLAT;
            SUSPEND;
            FIELD_ITEM = 'Index';
            FIELD_VAL = POST_INDEX;
            SUSPEND;
        END

        FIELD_NAME = 'Phone_reception';
        FIELD_TYPE = 'string';
        FIELD_ITEM = '';
        SELECT V
        FROM VAL_GET(:SCHOOL_ID, 29, 0, :I$USER_ID)
        INTO :FIELD_VAL;
        SUSPEND;

        FIELD_NAME = 'Fax';
        FIELD_TYPE = 'string';
        FIELD_ITEM = '';
        SELECT V
        FROM VAL_GET(:SCHOOL_ID, 30, 0, :I$USER_ID)
        INTO :FIELD_VAL;
        SUSPEND;


        F = '';
        I = '';
        O = '';
        POST = '';
        SELECT F, I, O, POST
        FROM R_SPB_POST_DIRECTOR(:SCHOOL_ID, :I$USER_ID)
        INTO :F, :I, :O, :POST;

        FIELD_NAME = 'Post_of_head';
        FIELD_ITEM = '';
        FIELD_TYPE = 'string';
        FIELD_VAL = POST;
        SUSPEND;

        FIELD_NAME = 'Head';
        FIELD_TYPE = 'list';
        FIELD_VAL = F;
        FIELD_ITEM = 'Surname';
        SUSPEND;
        FIELD_VAL = I;
        FIELD_ITEM = 'Name';
        SUSPEND;
        FIELD_VAL = O;
        FIELD_ITEM = 'Patronymic';
        SUSPEND;

        FIELD_NAME = 'http_address';
        FIELD_ITEM = '';
        FIELD_TYPE = 'string';
        SELECT V
        FROM VAL_GET(:SCHOOL_ID, 36, 0, :I$USER_ID)
        INTO :FIELD_VAL;
        SUSPEND;
        FIELD_TYPE = 'string';
        FIELD_ITEM = '';
        FIELD_NAME = 'OGRN';/* OGRN */
        FIELD_VAL = OGRN;
        SUSPEND;





        FOR
            SELECT L16.OBJ_ID
            FROM LINKS L73
            JOIN LINKS L16
            ON L16.PARENT_ID = L73.OBJ_ID
            AND L16.OBJ_TYPE_ID = 16
            AND L16.DATE_DEL IS NULL
            WHERE L73.PARENT_ID = :SCHOOL_ID
            AND L73.OBJ_TYPE_ID = 73
            AND L73.DATE_DEL IS NULL
            INTO :BUILDING_ID
        DO
        BEGIN
            FIELD_BLOCK = 'building';

            SHORTNAME = '';
            SELECT V
            FROM VAL_GET(:BUILDING_ID, 421, 0, :I$USER_ID)
            INTO :SHORTNAME;

            FIELD_NAME = 'Name';
            FIELD_ITEM = 'Name';
            FIELD_TYPE = 'string';
            FIELD_VAL = SHORTNAME;
            SUSPEND;

            FIELD_NAME = 'Address';
            FIELD_TYPE = 'address';
            REGION = '';
            DISTRICT = '';
            TOWN = '';
            SETTLEMENT = '';
            STREET = '';
            HOUSE = '';
            LITER = '';
            CORP = '';
            FLAT = '';
            POST_INDEX = '';
            SELECT REGION, DISTRICT, TOWN, SETTLEMENT, STREET, HOUSE, LITER, CORP, FLAT, POST_INDEX
            FROM VALA
            WHERE PARAM_ID = 420
                AND OBJ_ID = :BUILDING_ID
            INTO :REGION, :DISTRICT, :TOWN, :SETTLEMENT, :STREET, :HOUSE, :LITER, :CORP, :FLAT, :POST_INDEX;

            IF ((REGION != '')
            OR (DISTRICT != '')
            OR (TOWN != '')
            OR (SETTLEMENT != '')
            OR (STREET != '')
            OR (HOUSE != '')
            OR (LITER != '')
            OR (CORP != '')
            OR (FLAT != ''))
            THEN
            BEGIN
                FIELD_ITEM = 'Region';
                FIELD_VAL = REGION;
                SUSPEND;
                FIELD_ITEM = 'District';
                FIELD_VAL = DISTRICT;
                SUSPEND;
                FIELD_ITEM = 'Town';
                FIELD_VAL = TOWN;
                SUSPEND;
                FIELD_ITEM = 'Settlement';
                FIELD_VAL = SETTLEMENT;
                SUSPEND;
                FIELD_ITEM = 'Street';
                FIELD_VAL = STREET;
                SUSPEND;
                FIELD_ITEM = 'House';
                FIELD_VAL = HOUSE;
                SUSPEND;
                FIELD_ITEM = 'Liter';
                FIELD_VAL = LITER;
                SUSPEND;
                FIELD_ITEM = 'Corp';
                FIELD_VAL = CORP;
                SUSPEND;
                FIELD_ITEM = 'Flat';
                FIELD_VAL = FLAT;
                SUSPEND;
                FIELD_ITEM = 'Index';
                FIELD_VAL = POST_INDEX;
                SUSPEND;
            END
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PORTAL_GROUP_TEACHER (
    GROUP_ID BIGINT,
    SUBJECT_ID BIGINT)
RETURNS (
    TEACHER_ID BIGINT,
    DATE_MODIFY TIMESTAMP)
AS
begin

    -- На всякий случай выбираем не более одной записи
    SELECT FIRST 1 LP14.PARENT_ID, LP14.DATE_MODIFY
    -- Нагрузка учебного коллектива
    FROM LINKS L58
    -- Связь с нагрузкой УП
    JOIN LINKS LP56 ON LP56.OBJ_ID = L58.OBJ_ID AND LP56.PARENT_TYPE_ID = 56 AND LP56.DATE_DEL IS NULL
    -- Нагрузка по требуемому предмету
    JOIN LINKS LP51 ON LP51.OBJ_ID = LP56.PARENT_ID AND LP51.PARENT_TYPE_ID = 51 AND LP51.DATE_DEL IS NULL AND LP51.PARENT_ID = :SUBJECT_ID
    -- Назначенный преподаватель
    JOIN LINKS LP14 ON LP14.OBJ_ID = L58.OBJ_ID AND LP14.PARENT_TYPE_ID = 14 AND LP14.DATE_DEL IS NULL
    WHERE L58.PARENT_ID = :GROUP_ID AND L58.OBJ_TYPE_ID = 58 AND L58.DATE_DEL IS NULL
    INTO :TEACHER_ID, :DATE_MODIFY;

    SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PORTAL_LAST_EXPORT_DATE_GET RETURNS (
    DT VARCHAR(30))
AS
BEGIN
    SELECT FIRST 1 INFO_VAL
    FROM INFO
    WHERE INFO_CODE = 'PORTAL_LAST_EXPORT_DATE'
    INTO :DT;

    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PORTAL_LAST_EXPORT_DATE_SET (
    I$DT TIMESTAMP)
AS
BEGIN
    UPDATE OR INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
    VALUES ('PORTAL_LAST_EXPORT_DATE', 'PORTAL_LAST_EXPORT_DATE', :I$DT)
    MATCHING (INFO_CODE);
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PORTAL_LAST_MARKS_DELETED_GET (
    BEGIN_DATE TIMESTAMP,
    END_DATE TIMESTAMP)
RETURNS (
    LAST_MARK_ID BIGINT)
AS
BEGIN
    FOR
        SELECT M.MARK_ID
        FROM PORTAL_STUDENTS_WITH_UID_LIST(:BEGIN_DATE, :END_DATE) G
        JOIN VALM M ON M.PUPIL_ID = G.STUDENT_ID
        WHERE M.IS_DEL <> 0
            AND M.DATE_MODIFY <= :END_DATE AND ((:BEGIN_DATE IS NULL) OR (G.IS_FULL_EXPORT = 1) OR (M.DATE_MODIFY >= :BEGIN_DATE))
        INTO :LAST_MARK_ID
    DO
        SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PORTAL_LAST_MARKS_GET (
    I$BEGIN_DATE TIMESTAMP,
    I$END_DATE TIMESTAMP,
    I$USER_ID BIGINT)
RETURNS (
    LAST_MARK_ID BIGINT,
    SUBJECT_ID BIGINT,
    STUDENT_ID BIGINT,
    SCHOOL_YEAR VARCHAR(4000),
    MARK_NAME VARCHAR(4000),
    FINAL_NAME VARCHAR(4000))
AS
declare variable LANG_CODE varchar(2);
BEGIN
    SELECT LANG_CODE FROM USERS WHERE USER_ID = :I$USER_ID INTO :LANG_CODE;

    FOR
        SELECT M.MARK_ID, M.SUBJECT_ID, G.STUDENT_ID, R3.VAL_LONG, R1.VAL, RY.VAL
        FROM PORTAL_STUDENTS_WITH_UID_LIST(:I$BEGIN_DATE, :I$END_DATE) G
        JOIN VALM M ON M.PUPIL_ID = G.STUDENT_ID
        JOIN LISTVALS L1 ON L1.LISTVAL_ID = M.MARKTYPE_ID
        JOIN LISTVALS L3 ON L3.LISTVAL_ID = M.MARKVAL_ID
        JOIN LISTVALS LY ON LY.LISTVAL_ID = M.YEAR_ID
        LEFT JOIN RES_GET(L1.RES_ID, :LANG_CODE) R1 ON 1=1
        LEFT JOIN RES_GET(L3.RES_ID, :LANG_CODE) R3 ON 1=1
        LEFT JOIN RES_GET(LY.RES_ID, :LANG_CODE) RY ON 1=1
        WHERE M.IS_DEL = 0
          AND M.DATE_MODIFY <= :I$END_DATE
          AND ((:I$BEGIN_DATE IS NULL) OR (G.IS_FULL_EXPORT = 1) OR (M.DATE_MODIFY >= :I$BEGIN_DATE))
          AND M.MARKTYPE_ID = 3011 /* годовая, 3013 - итоговая */
        INTO :LAST_MARK_ID, :SUBJECT_ID, :STUDENT_ID, :MARK_NAME, :FINAL_NAME, :SCHOOL_YEAR
    DO
        SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PORTAL_LIST_GROUPS (
    GROUP_ID BIGINT,
    STUDENT_ID BIGINT = null)
RETURNS (
    CLASS_ID BIGINT,
    VIRT_ID BIGINT)
AS
declare variable YEAR_START_DATE date;
begin

    -- Изменения учеников в классах берем только за текущий учебный год
    IF(EXTRACT(MONTH FROM CURRENT_DATE) <= 8) THEN
    BEGIN
        -- Учебный год, начавшийся в прошлом году
        YEAR_START_DATE = '01.09.' || (EXTRACT(YEAR FROM CURRENT_DATE) - 1);
    END
    ELSE
    BEGIN
        -- Учебный год, начавшийся в текущем году
        YEAR_START_DATE = '01.09.' || EXTRACT(YEAR FROM CURRENT_DATE);
    END

    FOR
        SELECT DISTINCT LP9.PARENT_ID, VID9.VIRT_ID
        FROM LINKS L10
        -- Все классы, где ученик числился в текущем учебном году
        JOIN LINKS LP9 ON LP9.OBJ_ID = L10.OBJ_ID AND LP9.PARENT_TYPE_ID = 9 AND (LP9.DATE_DEL IS NULL OR LP9.DATE_DEL >= :YEAR_START_DATE)
        LEFT JOIN CLASS_VIRT_ID(LP9.PARENT_ID, LP9.PARENT_TYPE_ID) VID9 ON 1 = 1
        -- На всякий случай фильтр по дате удаления, чтобы заработало на старых данных в 2017
        WHERE L10.PARENT_ID = :GROUP_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL AND (L10.DATE_DEL IS NULL OR L10.DATE_DEL >= :YEAR_START_DATE)
        INTO :GROUP_ID, :VIRT_ID
    DO
    BEGIN
        SUSPEND;
    END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PORTAL_OGRN_GET RETURNS (
    OGRN VARCHAR(4000))
AS
declare variable SCHOOL_ID bigint;
BEGIN
    SELECT FIRST 1 L.OBJ_ID
    FROM LINKS L
    WHERE L.PARENT_ID IS NULL AND L.OBJ_TYPE_ID = 2 AND L.DATE_DEL IS NULL
    INTO :SCHOOL_ID;

    SELECT V.VAL
    FROM VALS V
    WHERE V.PARAM_ID = 9 AND V.OBJ_ID = :SCHOOL_ID AND V.IS_DEL = 0
    INTO :OGRN;

    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PORTAL_OU_DATA_GET (
    I$USER_ID BIGINT)
RETURNS (
    SCHOOL_ID BIGINT,
    FIELD_BLOCK VARCHAR(10),
    FIELD_TYPE VARCHAR(10),
    FIELD_NAME VARCHAR(30),
    FIELD_ITEM VARCHAR(10),
    FIELD_VAL VARCHAR(4000))
AS
declare variable ROOT_ID bigint;
declare variable OGRN varchar(100);
declare variable FULLNAME varchar(4000);
declare variable SHORTNAME varchar(1000);
declare variable OUTYPE integer;
declare variable OUKIND integer;
declare variable F varchar(250);
declare variable I varchar(250);
declare variable O varchar(250);
declare variable POST varchar(250);
declare variable REGION varchar(255);
declare variable DISTRICT varchar(255);
declare variable TOWN varchar(255);
declare variable SETTLEMENT varchar(255);
declare variable STREET varchar(255);
declare variable HOUSE varchar(10);
declare variable LITER varchar(10);
declare variable CORP varchar(10);
declare variable FLAT varchar(10);
declare variable POST_INDEX varchar(20);
declare variable LANG_CODE varchar(2);
declare variable ALT_NAME varchar(1000);
declare variable LIC_TYPE varchar(1);
BEGIN
    SELECT LANG_CODE FROM USERS WHERE USER_ID = :I$USER_ID INTO :LANG_CODE;

    -- Тип лицензии нужен для подмены наименования колледжей
    SELECT STATUS FROM OU_LICENCE_TYPE INTO :LIC_TYPE;

    SELECT FIRST 1 L.OBJ_ID
    FROM LINKS L
    WHERE L.PARENT_ID IS NULL AND ((L.OBJ_TYPE_ID = 111) OR (L.OBJ_TYPE_ID = 112)) AND L.DATE_DEL IS NULL
    INTO :ROOT_ID;

    FOR
        SELECT O.OBJ_ID, V9.VAL, V5.VAL, V2.VAL, V11.LISTVAL_ID, V10.LISTVAL_ID, V999.VAL
        FROM OBJECT_CHILDREN_GET_DEEP(:ROOT_ID, 2, 2) O
        JOIN VALS V9 ON V9.OBJ_ID = O.OBJ_ID AND V9.PARAM_ID = 9 AND V9.IS_DEL = 0
        JOIN VALS V2 ON V2.OBJ_ID = O.OBJ_ID AND V2.PARAM_ID = 2 AND V2.IS_DEL = 0
        JOIN VALS V5 ON V5.OBJ_ID = O.OBJ_ID AND V5.PARAM_ID = 5 AND V5.IS_DEL = 0
        JOIN VALL V11 ON V11.OBJ_ID = O.OBJ_ID AND V11.PARAM_ID = 11 AND V11.IS_DEL = 0
        JOIN VALL V10 ON V10.OBJ_ID = O.OBJ_ID AND V10.PARAM_ID = 10 AND V10.IS_DEL = 0
        LEFT JOIN VALS V999 ON V999.OBJ_ID = O.OBJ_ID AND V999.PARAM_ID = 999 AND V999.IS_DEL = 0
        INTO :SCHOOL_ID, :OGRN, :FULLNAME, :SHORTNAME, :OUTYPE, :OUKIND, :ALT_NAME
    DO
    BEGIN
        /* reduired */
        FIELD_BLOCK = 'reduired';

        FIELD_TYPE = 'string';
        FIELD_ITEM = '';
        FIELD_NAME = 'uid';/* OGRN */
        FIELD_VAL = OGRN;
        SUSPEND;
        FIELD_TYPE = 'string';
        FIELD_ITEM = '';
        FIELD_NAME = 'fullname';
        FIELD_VAL = FULLNAME;
        SUSPEND;
        FIELD_TYPE = 'string';
        FIELD_ITEM = '';
        FIELD_NAME = 'shortname';
        -- Для колледжей вместо краткого названия (которое на самом деле код) возвращаем краткое наименование по уставу
        IF(LIC_TYPE = 'C' AND ALT_NAME IS NOT NULL) THEN FIELD_VAL = ALT_NAME; ELSE FIELD_VAL = SHORTNAME;
        SUSPEND;
        FIELD_TYPE = 'int';
        FIELD_ITEM = '';
        FIELD_NAME = 'ouType';
        FIELD_VAL = OUTYPE;
        SUSPEND;
        FIELD_TYPE = 'int';
        FIELD_ITEM = '';
        FIELD_NAME = 'ouKind';
        FIELD_VAL = OUKIND;
        SUSPEND;

        /* additional */
        FIELD_BLOCK = 'additional';

        FIELD_NAME = 'Номер ОУ';
        FIELD_ITEM = '';
        FIELD_TYPE = 'int';
        FIELD_VAL = '';
        SELECT V
        FROM VAL_GET(:SCHOOL_ID, 17, 0, :I$USER_ID)
        INTO :FIELD_VAL;
        IF (FIELD_VAL > '') THEN SUSPEND;

        FIELD_NAME = 'Адрес электронной почты';
        FIELD_ITEM = '';
        FIELD_TYPE = 'string';
        FIELD_VAL = '';
        SELECT V
        FROM VAL_GET(:SCHOOL_ID, 35, 0, :I$USER_ID)
        INTO :FIELD_VAL;
        IF (FIELD_VAL > '') THEN SUSPEND;

        FIELD_NAME = 'Адрес сайта';
        FIELD_ITEM = '';
        FIELD_TYPE = 'string';
        FIELD_VAL = '';
        SELECT V
        FROM VAL_GET(:SCHOOL_ID, 36, 0, :I$USER_ID)
        INTO :FIELD_VAL;
        IF (FIELD_VAL > '') THEN SUSPEND;

        FIELD_NAME = 'ОКТМО';
        FIELD_ITEM = '';
        FIELD_TYPE = 'string';
        FIELD_VAL = '';
        SELECT V
        FROM VAL_GET(:SCHOOL_ID, 2440, 0, :I$USER_ID)
        INTO :FIELD_VAL;
        IF (FIELD_VAL > '') THEN SUSPEND;

        F = '';
        I = '';
        O = '';
        POST = '';
        SELECT F, I, O, POST
        FROM R_SPB_POST_DIRECTOR(:SCHOOL_ID,:I$USER_ID)
        INTO :F, :I, :O, :POST;

        FIELD_NAME = 'Должность руководителя';
        FIELD_ITEM = '';
        FIELD_TYPE = 'string';
        FIELD_VAL = POST;
        IF (FIELD_VAL > '') THEN SUSPEND;

        FIELD_NAME = 'ФИО руководителя';
        FIELD_TYPE = 'list';
        FIELD_VAL = F;
        FIELD_ITEM = 'Фамилия';
        IF (FIELD_VAL > '') THEN SUSPEND;
        FIELD_VAL = I;
        FIELD_ITEM = 'Имя';
        IF (FIELD_VAL > '') THEN SUSPEND;
        FIELD_VAL = O;
        FIELD_ITEM = 'Отчество';
        IF (FIELD_VAL > '') THEN SUSPEND;

        FIELD_NAME = 'Телефон';
        FIELD_TYPE = 'string';
        FIELD_ITEM = '';
        FIELD_VAL = '';
        SELECT V
        FROM VAL_GET(:SCHOOL_ID, 29, 0, :I$USER_ID)
        INTO :FIELD_VAL;
        IF (FIELD_VAL > '') THEN SUSPEND;

        FIELD_NAME = 'Подведомственность ОУО';
        FIELD_TYPE = 'string';
        FIELD_ITEM = '';
        FIELD_VAL = '';
        IF(LIC_TYPE = 'C') THEN
        BEGIN
            SELECT V
            FROM VAL_GET(:SCHOOL_ID, 6)
            WHERE IS_EXISTS = 1
            INTO :FIELD_VAL;
        END
        ELSE
        BEGIN
            SELECT R.VAL
            FROM LINKS L
            JOIN VALL VL ON VL.OBJ_ID = L.PARENT_ID AND VL.PARAM_ID = 665 AND VL.IS_DEL = 0
            JOIN LISTVALS LV ON LV.LISTVAL_ID = VL.LISTVAL_ID
            LEFT JOIN RES_GET(LV.RES_ID, :LANG_CODE) R ON 1 = 1
            WHERE L.PARENT_TYPE_ID = 111 AND L.OBJ_ID = :SCHOOL_ID AND L.DATE_DEL IS NULL
            INTO :FIELD_VAL;
        END
        IF (FIELD_VAL > '') THEN SUSPEND;

        FIELD_NAME = 'Адрес ОУ';
        FIELD_TYPE = 'address';
        REGION = '';
        DISTRICT = '';
        TOWN = '';
        SETTLEMENT = '';
        STREET = '';
        HOUSE = '';
        LITER = '';
        CORP = '';
        FLAT = '';
        POST_INDEX = '';
        SELECT REGION, DISTRICT, TOWN, SETTLEMENT, STREET, HOUSE, LITER, CORP, FLAT, POST_INDEX
        FROM VALA
        WHERE PARAM_ID = 27 AND OBJ_ID = :SCHOOL_ID
        INTO :REGION, :DISTRICT, :TOWN, :SETTLEMENT, :STREET, :HOUSE, :LITER, :CORP, :FLAT, :POST_INDEX;

        FIELD_ITEM = 'region';
        FIELD_VAL = REGION;
        IF (FIELD_VAL > '') THEN SUSPEND;
        FIELD_ITEM = 'district';
        FIELD_VAL = DISTRICT;
        IF (FIELD_VAL > '') THEN SUSPEND;
        FIELD_ITEM = 'town';
        FIELD_VAL = TOWN;
        IF (FIELD_VAL > '') THEN SUSPEND;
        FIELD_ITEM = 'settlement';
        FIELD_VAL = SETTLEMENT;
        IF (FIELD_VAL > '') THEN SUSPEND;
        FIELD_ITEM = 'street';
        FIELD_VAL = STREET;
        IF (FIELD_VAL > '') THEN SUSPEND;
        FIELD_ITEM = 'house';
        FIELD_VAL = HOUSE;
        IF (FIELD_VAL > '') THEN SUSPEND;
        FIELD_ITEM = 'liter';
        FIELD_VAL = LITER;
        IF (FIELD_VAL > '') THEN SUSPEND;
        FIELD_ITEM = 'corp';
        FIELD_VAL = CORP;
        IF (FIELD_VAL > '') THEN SUSPEND;
        FIELD_ITEM = 'flat';
        FIELD_VAL = FLAT;
        IF (FIELD_VAL > '') THEN SUSPEND;
        FIELD_ITEM = 'post_index';
        FIELD_VAL = POST_INDEX;
        IF (FIELD_VAL > '') THEN SUSPEND;

    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PORTAL_PERIODS_DELETED_GET (
    BEGIN_DATE TIMESTAMP,
    END_DATE TIMESTAMP)
RETURNS (
    PERIOD_ID BIGINT)
AS
declare variable SCHOOL_ID bigint;
BEGIN
    SELECT FIRST 1 L.OBJ_ID
    FROM LINKS L
    WHERE L.PARENT_ID IS NULL AND L.OBJ_TYPE_ID = 2 AND L.DATE_DEL IS NULL
    INTO :SCHOOL_ID;

    FOR SELECT L151.OBJ_ID
        FROM LINKS L150
        JOIN LINKS L151 ON L151.PARENT_ID = L150.OBJ_ID AND L151.OBJ_TYPE_ID = 151 AND L151.DATE_DEL IS NOT NULL AND L151.DATE_MODIFY <= :END_DATE
            AND ((:BEGIN_DATE IS NULL) OR (L151.DATE_MODIFY >= :BEGIN_DATE))
        WHERE L150.PARENT_ID = :SCHOOL_ID AND L150.OBJ_TYPE_ID = 150 AND L150.DATE_DEL IS NULL
        INTO :PERIOD_ID
    DO
        SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PORTAL_PERIODS_GET (
    BEGIN_DATE TIMESTAMP,
    END_DATE TIMESTAMP,
    I$USER_ID BIGINT)
RETURNS (
    PERIOD_ID BIGINT,
    INTERVAL_NAME VARCHAR(4000),
    INTERVAL_BEGIN DATE,
    INTERVAL_END DATE)
AS
declare variable SCHOOL_ID bigint;
declare variable DATE_MODIFY1 timestamp;
declare variable DATE_MODIFY2 timestamp;
declare variable DATE_MODIFY3 timestamp;
declare variable DATE_MODIFY4 timestamp;
declare variable IS_MODIFIED smallint;
declare variable LANG_CODE varchar(2);
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :LANG_CODE;

    SELECT FIRST 1 L.OBJ_ID
    FROM LINKS L
    WHERE L.PARENT_ID IS NULL AND L.OBJ_TYPE_ID = 2 AND L.DATE_DEL IS NULL
    INTO :SCHOOL_ID;

    FOR
        SELECT L151.OBJ_ID
        FROM LINKS L150
        JOIN LINKS L151 ON L151.PARENT_ID = L150.OBJ_ID AND L151.OBJ_TYPE_ID = 151 AND L151.DATE_DEL IS NULL
        WHERE L150.PARENT_ID = :SCHOOL_ID AND L150.OBJ_TYPE_ID = 150 AND L150.DATE_DEL IS NULL
        INTO :PERIOD_ID
    DO
    BEGIN
        IS_MODIFIED = 0;

        FOR
            SELECT L154.DATE_MODIFY, V1170.DATE_MODIFY, V1169.DATE_MODIFY, V1174.DATE_MODIFY
            FROM LINKS L154
            JOIN VALL V1170 ON V1170.OBJ_ID = L154.OBJ_ID AND V1170.PARAM_ID = 1170 AND V1170.IS_DEL = 0
            JOIN VALD V1169 ON V1169.OBJ_ID = L154.OBJ_ID AND V1169.PARAM_ID = 1169 AND V1169.IS_DEL = 0
            JOIN VALD V1174 ON V1174.OBJ_ID = L154.OBJ_ID AND V1174.PARAM_ID = 1174 AND V1174.IS_DEL = 0
            WHERE L154.PARENT_ID = :PERIOD_ID AND L154.OBJ_TYPE_ID = 154 --  AND L154.DATE_DEL IS NULL
            INTO :DATE_MODIFY1, :DATE_MODIFY2, :DATE_MODIFY3, :DATE_MODIFY4
        DO
        BEGIN
            IF (((BEGIN_DATE IS NULL) OR (DATE_MODIFY1 >= BEGIN_DATE)) AND (DATE_MODIFY1 <= END_DATE)) THEN IS_MODIFIED = 1;
            IF (((BEGIN_DATE IS NULL) OR (DATE_MODIFY2 >= BEGIN_DATE)) AND (DATE_MODIFY2 <= END_DATE)) THEN IS_MODIFIED = 1;
            IF (((BEGIN_DATE IS NULL) OR (DATE_MODIFY3 >= BEGIN_DATE)) AND (DATE_MODIFY3 <= END_DATE)) THEN IS_MODIFIED = 1;
            IF (((BEGIN_DATE IS NULL) OR (DATE_MODIFY4 >= BEGIN_DATE)) AND (DATE_MODIFY4 <= END_DATE)) THEN IS_MODIFIED = 1;
        END

        IF (IS_MODIFIED = 1) THEN
        BEGIN
            FOR
                SELECT R.VAL, V1169.VAL, V1174.VAL
                FROM LINKS L154
                JOIN VALL V1170 ON V1170.OBJ_ID = L154.OBJ_ID AND V1170.PARAM_ID = 1170 AND V1170.IS_DEL = 0
                JOIN VALD V1169 ON V1169.OBJ_ID = L154.OBJ_ID AND V1169.PARAM_ID = 1169 AND V1169.IS_DEL = 0
                JOIN VALD V1174 ON V1174.OBJ_ID = L154.OBJ_ID AND V1174.PARAM_ID = 1174 AND V1174.IS_DEL = 0
                JOIN LISTVALS LV ON LV.LISTVAL_ID = V1170.LISTVAL_ID
                LEFT JOIN RES_GET(LV.RES_ID,  :LANG_CODE) R ON 1 = 1
                WHERE L154.PARENT_ID = :PERIOD_ID AND L154.OBJ_TYPE_ID = 154 AND L154.DATE_DEL IS NULL
                ORDER BY LV.SORT_ORDER
                INTO :INTERVAL_NAME, :INTERVAL_BEGIN, :INTERVAL_END
            DO
            BEGIN
                SUSPEND;
            END
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PORTAL_STUDENTS_DELETED_GET (
    BEGIN_DATE TIMESTAMP,
    END_DATE TIMESTAMP)
RETURNS (
    STUDENT_ID BIGINT,
    RETIRED VARCHAR(4000))
AS
declare variable SCHOOL_ID bigint;
declare variable IS_MODIFIED smallint;
declare variable HAVE_UID smallint;
declare variable DATE_MODIFY date;
BEGIN
    SELECT FIRST 1 L.OBJ_ID
    FROM LINKS L
    WHERE L.PARENT_ID IS NULL AND L.OBJ_TYPE_ID = 2 AND L.DATE_DEL IS NULL
    INTO :SCHOOL_ID;

    -- Куда могут деваться ученики:
    -- Ученики, у которых был удален портальный идентификатор ученика или родителя
    RETIRED = NULL;

    FOR
        SELECT L10.OBJ_ID
        FROM LINKS L7
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
        JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        WHERE L7.PARENT_ID = :SCHOOL_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
        INTO :STUDENT_ID
    DO
    BEGIN
        HAVE_UID = 0;

        -- Наличие пары портальных ID
        SELECT FIRST 1 1
        FROM LINKS L
        JOIN VALS V1 ON V1.OBJ_ID = L.EXT_OBJ_ID AND V1.PARAM_ID = 1570 AND V1.IS_DEL = 0
        JOIN VALS V2 ON V2.OBJ_ID = L.OBJ_ID AND V2.PARAM_ID = 155 AND V2.IS_DEL = 0
        WHERE L.PARENT_ID = :STUDENT_ID AND L.OBJ_TYPE_ID = 20 AND L.DATE_DEL IS NULL
        INTO :HAVE_UID;

        -- Не осталось ни одной живой пары ID
        IF (HAVE_UID = 0) THEN
        BEGIN
            IS_MODIFIED = 0;

            -- Удален ID ученика
            SELECT FIRST 1 1
            FROM LINKS L
            JOIN VALS V1 ON V1.OBJ_ID = L.EXT_OBJ_ID AND V1.PARAM_ID = 1570 AND V1.IS_DEL = 1 AND V1.DATE_MODIFY >= :BEGIN_DATE AND V1.DATE_MODIFY <= :END_DATE
            WHERE L.PARENT_ID = :STUDENT_ID AND L.OBJ_TYPE_ID = 20 AND L.DATE_DEL IS NULL
            INTO :IS_MODIFIED;

            -- Удален ID родителя
            SELECT FIRST 1 1
            FROM LINKS L
            JOIN VALS V1 ON V1.OBJ_ID = L.OBJ_ID AND V1.PARAM_ID = 155 AND V1.IS_DEL = 1 AND V1.DATE_MODIFY >= :BEGIN_DATE AND V1.DATE_MODIFY <= :END_DATE
            WHERE L.PARENT_ID = :STUDENT_ID AND L.OBJ_TYPE_ID = 20 AND L.DATE_DEL IS NULL
            INTO :IS_MODIFIED;

            IF (IS_MODIFIED = 1) THEN SUSPEND;
        END
    END

    -- Выбывшие и выпустившиеся ученики. Выборка по типу 81 устарела ?
    RETIRED = 'true';

    FOR
        SELECT L10.OBJ_ID, L10.DATE_MODIFY
        FROM LINKS L78
        JOIN LINKS LXX ON LXX.PARENT_ID = L78.OBJ_ID AND LXX.OBJ_TYPE_ID IN (81, 82, 83) AND LXX.DATE_DEL IS NULL
        JOIN LINKS L10 ON L10.PARENT_ID = LXX.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        WHERE L78.PARENT_ID = :SCHOOL_ID AND L78.OBJ_TYPE_ID = 78 AND L78.DATE_DEL IS NULL
        INTO :STUDENT_ID, :DATE_MODIFY
    DO
    BEGIN

        IS_MODIFIED = 0;
        IF (DATE_MODIFY >= BEGIN_DATE AND DATE_MODIFY <= END_DATE) THEN IS_MODIFIED = 1;

        IF (IS_MODIFIED = 1) THEN
        BEGIN
            HAVE_UID = 0;

            -- Если когда-либо у ученика были портальные ID
            SELECT FIRST 1 1
            FROM LINKS L
            JOIN VALS V1 ON V1.OBJ_ID = L.EXT_OBJ_ID AND V1.PARAM_ID = 1570
            JOIN VALS V2 ON V2.OBJ_ID = L.OBJ_ID AND V2.PARAM_ID = 155
            WHERE L.PARENT_ID = :STUDENT_ID AND L.OBJ_TYPE_ID = 20 AND L.DATE_DEL IS NULL
            INTO :HAVE_UID;

            IF (HAVE_UID = 1) THEN SUSPEND;
        END

    END

END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PORTAL_STUDENTS_PARENT_GET (
    STUDENT_ID BIGINT)
RETURNS (
    SUID VARCHAR(4000),
    PUID VARCHAR(4000))
AS
BEGIN
    FOR
        SELECT V1.VAL, V2.VAL
        FROM LINKS L
        JOIN VALS V1 ON V1.OBJ_ID = L.EXT_OBJ_ID AND V1.PARAM_ID = 1570 AND V1.IS_DEL = 0
        JOIN VALS V2 ON V2.OBJ_ID = L.OBJ_ID AND V2.PARAM_ID = 155 AND V2.IS_DEL = 0
        WHERE L.PARENT_ID = :STUDENT_ID AND L.OBJ_TYPE_ID = 20 AND L.DATE_DEL IS NULL
        INTO :SUID, :PUID
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PORTAL_STUDENTS_WITH_UID_LIST (
    BEGIN_DATE TIMESTAMP,
    END_DATE TIMESTAMP)
RETURNS (
    STUDENT_ID BIGINT,
    IS_FULL_EXPORT SMALLINT)
AS
declare variable SCHOOL_ID bigint;
declare variable FLAG1 smallint;
declare variable FLAG2 smallint;
declare variable DATE_MODIFY1 timestamp;
declare variable DATE_MODIFY2 timestamp;
BEGIN
    SELECT FIRST 1 L.OBJ_ID
    FROM LINKS L
    WHERE L.PARENT_ID IS NULL AND L.OBJ_TYPE_ID = 2 AND L.DATE_DEL IS NULL
    INTO :SCHOOL_ID;

    FOR
        SELECT L10.OBJ_ID
        FROM LINKS L7
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
        JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        WHERE L7.PARENT_ID = :SCHOOL_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
        INTO :STUDENT_ID
    DO
    BEGIN

        FLAG1 = 0;
        FLAG2 = 0;
        IS_FULL_EXPORT = 0;

        FOR
            SELECT V1.DATE_MODIFY, V2.DATE_MODIFY
            FROM LINKS L20
            JOIN VALS V1 ON V1.OBJ_ID = L20.EXT_OBJ_ID AND V1.PARAM_ID = 1570 AND V1.IS_DEL = 0 AND V1.DATE_MODIFY <= :END_DATE
            JOIN VALS V2 ON V2.OBJ_ID = L20.OBJ_ID AND V2.PARAM_ID = 155 AND V2.IS_DEL = 0 AND V2.DATE_MODIFY <= :END_DATE
            WHERE L20.PARENT_ID = :STUDENT_ID AND L20.OBJ_TYPE_ID = 20 AND L20.DATE_DEL IS NULL
            INTO :DATE_MODIFY1, :DATE_MODIFY2
        DO
        BEGIN
            IF ((BEGIN_DATE IS NULL) OR (DATE_MODIFY1 >= BEGIN_DATE) OR (DATE_MODIFY2 >= BEGIN_DATE)) THEN FLAG1 = 1;
            ELSE FLAG2 = 1;
        END

        IF ((FLAG1 = 1) AND (FLAG2 = 0)) THEN IS_FULL_EXPORT = 1;

        IF ((FLAG1 = 1) OR (FLAG2 = 1)) THEN SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PORTAL_SUBJECTS_GET (
    BEGIN_DATE TIMESTAMP,
    END_DATE TIMESTAMP)
RETURNS (
    SUBJECT_ID BIGINT,
    SUBJECT_NAME VARCHAR(4000),
    SUBJECT_CODE VARCHAR(4000),
    SUBJECT_GIA_CODE VARCHAR(4000))
AS
declare variable DATE_MODIFY timestamp;
declare variable IS_MODIFIED smallint;
BEGIN
    FOR
        SELECT L51.OBJ_ID, L51.DATE_MODIFY
        FROM LINKS L301
        JOIN LINKS L51 ON L51.PARENT_ID = L301.OBJ_ID AND L51.OBJ_TYPE_ID = 51 AND L51.DATE_DEL IS NULL
        WHERE L301.PARENT_ID = 208 AND L301.OBJ_TYPE_ID = 301 AND L301.DATE_DEL IS NULL
        INTO :SUBJECT_ID, :DATE_MODIFY
    DO
    BEGIN
        IS_MODIFIED = 0;
        SUBJECT_NAME = NULL;
        SUBJECT_CODE = NULL;
        SUBJECT_GIA_CODE = NULL;

        IF (((BEGIN_DATE IS NULL) OR (DATE_MODIFY >= BEGIN_DATE)) AND (DATE_MODIFY <= END_DATE)) THEN IS_MODIFIED = 1;

        SELECT V.VAL, V.DATE_MODIFY
        FROM VALS V
        WHERE V.PARAM_ID = 376 AND V.OBJ_ID = :SUBJECT_ID AND V.IS_DEL = 0
        INTO :SUBJECT_NAME, :DATE_MODIFY;

        IF (((BEGIN_DATE IS NULL) OR (DATE_MODIFY >= BEGIN_DATE)) AND (DATE_MODIFY <= END_DATE)) THEN IS_MODIFIED = 1;

        SELECT V.VAL, V.DATE_MODIFY
        FROM VALS V
        WHERE V.PARAM_ID = 377 AND V.OBJ_ID = :SUBJECT_ID AND V.IS_DEL = 0
        INTO :SUBJECT_CODE, :DATE_MODIFY;

        IF (((BEGIN_DATE IS NULL) OR (DATE_MODIFY >= BEGIN_DATE)) AND (DATE_MODIFY <= END_DATE)) THEN IS_MODIFIED = 1;

        -- Поблажка в 2017 году - если код предмета не заполнен, выдаем левый кодл
        IF(SUBJECT_CODE IS NULL) THEN SUBJECT_CODE = 'НЗПЛ';

        SELECT V.VAL, V.DATE_MODIFY
        FROM VALI V
        WHERE V.PARAM_ID = 600 AND V.OBJ_ID = :SUBJECT_ID AND V.IS_DEL = 0
        INTO :SUBJECT_GIA_CODE, :DATE_MODIFY;

        IF (((BEGIN_DATE IS NULL) OR (DATE_MODIFY >= BEGIN_DATE)) AND (DATE_MODIFY <= END_DATE)) THEN IS_MODIFIED = 1;

        IF ((IS_MODIFIED = 1) AND (SUBJECT_NAME IS NOT NULL) AND (SUBJECT_CODE IS NOT NULL)) THEN SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PORTAL_TEACHERS_GET (
    BEGIN_DATE TIMESTAMP,
    END_DATE TIMESTAMP)
RETURNS (
    TEACHER_ID BIGINT,
    UID VARCHAR(4000),
    FIO VARCHAR(4000),
    RETIRED BIGINT)
AS
declare variable SCHOOL_ID bigint;
declare variable DATE_MODIFY timestamp;
declare variable IS_MODIFIED smallint;
declare variable YEAR_START_DATE date;
declare variable V varchar(4000);
BEGIN
    SELECT FIRST 1 L.OBJ_ID
    FROM LINKS L
    WHERE L.PARENT_ID IS NULL AND L.OBJ_TYPE_ID = 2 AND L.DATE_DEL IS NULL
    INTO :SCHOOL_ID;

    IF(EXTRACT(MONTH FROM CURRENT_DATE) <= 8) THEN
    BEGIN
        -- Учебный год, начавшийся в прошлом году
        YEAR_START_DATE = '01.09.' || (EXTRACT(YEAR FROM CURRENT_DATE) - 1);
    END
    ELSE
    BEGIN
        -- Учебный год, начавшийся в текущем году
        YEAR_START_DATE = '01.09.' || EXTRACT(YEAR FROM CURRENT_DATE);
    END

    FOR
        -- Все работающие в данный момент сотрудники
        SELECT L.OBJ_ID, L.DATE_MODIFY, L.PARENT_TYPE_ID
        FROM LINKS L
        WHERE L.PARENT_ID = :SCHOOL_ID AND L.OBJ_TYPE_ID = 14 AND L.DATE_DEL IS NULL
        -- Все сотрудники, которые были уволены в течение текущего учебного года
        UNION
        SELECT L14.OBJ_ID, L14.DATE_MODIFY, L14.PARENT_TYPE_ID
        -- Выборка по папке уволенных
        FROM LINKS L84
        -- Все уволенные учителя
        JOIN LINKS L14 ON L14.PARENT_ID = L84.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL AND L14.DATE_INS >= :YEAR_START_DATE
        WHERE L84.PARENT_ID = :SCHOOL_ID AND L84.OBJ_TYPE_ID = 84 AND L84.DATE_DEL IS NULL
        INTO :TEACHER_ID, :DATE_MODIFY, :RETIRED
    DO
    BEGIN
        IS_MODIFIED = 0;
        V = '';
        UID = NULL;

        IF (((BEGIN_DATE IS NULL) OR (DATE_MODIFY >= BEGIN_DATE)) AND (DATE_MODIFY <= END_DATE)) THEN IS_MODIFIED = 1;

        SELECT V.VAL, V.DATE_MODIFY
        FROM VALS V
        WHERE V.PARAM_ID = 59 AND V.OBJ_ID = :TEACHER_ID AND V.IS_DEL = 0
        INTO :V, :DATE_MODIFY;

        FIO = V;

        IF (((BEGIN_DATE IS NULL) OR (DATE_MODIFY >= BEGIN_DATE)) AND (DATE_MODIFY <= END_DATE)) THEN IS_MODIFIED = 1;

        V = '';

        SELECT V.VAL, V.DATE_MODIFY
        FROM VALS V
        WHERE V.PARAM_ID = 60 AND V.OBJ_ID = :TEACHER_ID AND V.IS_DEL = 0
        INTO :V, :DATE_MODIFY;

        IF (V > '') THEN FIO = FIO || ' ' || V;

        IF (((BEGIN_DATE IS NULL) OR (DATE_MODIFY >= BEGIN_DATE)) AND (DATE_MODIFY <= END_DATE)) THEN IS_MODIFIED = 1;

        V = '';

        SELECT V.VAL, V.DATE_MODIFY
        FROM VALS V
        WHERE V.PARAM_ID = 61 AND V.OBJ_ID = :TEACHER_ID AND V.IS_DEL = 0
        INTO :V, :DATE_MODIFY;

        IF (V > '') THEN FIO = FIO || ' ' || V;

        IF (((BEGIN_DATE IS NULL) OR (DATE_MODIFY >= BEGIN_DATE)) AND (DATE_MODIFY <= END_DATE)) THEN IS_MODIFIED = 1;

        SELECT V.VAL, V.DATE_MODIFY
        FROM VALS V
        WHERE V.PARAM_ID = 267 AND V.OBJ_ID = :TEACHER_ID AND V.IS_DEL = 0
        INTO :UID, :DATE_MODIFY;

        IF (((BEGIN_DATE IS NULL) OR (DATE_MODIFY >= BEGIN_DATE)) AND (DATE_MODIFY <= END_DATE)) THEN IS_MODIFIED = 1;

        IF ((IS_MODIFIED = 1) AND (FIO > '')) THEN SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE POSTEVENT (
    I$EVENT VARCHAR(20),
    I$MSG VARCHAR(4000) = NULL)
AS
BEGIN
/*  DELETE FROM MESSAGES;
  INSERT INTO MESSAGES (MSG) VALUES (:MSG);
  OK=1;
  SUSPEND;*/
  POST_EVENT I$EVENT;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PR3_FIND_EMPLOYEES (
    I$NAME_LAST VARCHAR(400),
    I$NAME_FIRST VARCHAR(400),
    I$NAME_MID VARCHAR(400),
    I$BIRTH_DATE DATE,
    I$SNILS VARCHAR(40),
    I$DOC_TYPE BIGINT,
    I$DOC_SERIE VARCHAR(40),
    I$DOC_NUM VARCHAR(40),
    I$DOC_DATE DATE,
    I$USER_ID VARCHAR(40),
    I$FROM_IP VARCHAR(200) = NULL)
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$ID BIGINT;
DECLARE VARIABLE V$LAST_NAME VARCHAR(400);
DECLARE VARIABLE V$FIRST_NAME VARCHAR(400);
DECLARE VARIABLE V$MIDDLE_NAME VARCHAR(400);
DECLARE VARIABLE V$BIRTH_DATE DATE;
DECLARE VARIABLE V$SNILS VARCHAR(40);
DECLARE VARIABLE V$CLASS_NAME VARCHAR(400);
DECLARE VARIABLE V$ROW_CLASS VARCHAR(100);
DECLARE VARIABLE V$OK SMALLINT;
DECLARE VARIABLE S VARCHAR(4000);
begin

  IF(I$DOC_TYPE IS NOT NULL) THEN
  BEGIN
    IF(I$DOC_NUM IS NULL AND I$DOC_DATE IS NULL) THEN EXCEPTION DATA_ERROR 'Если указан тип документа, должно быть указано хотя бы одно значение поля документа';
  END

  I$SNILS = REPLACE(I$SNILS, ' ', '');
  I$SNILS = REPLACE(I$SNILS, '-', '');
  I$NAME_FIRST = UPPER(TRIM(I$NAME_FIRST));
  I$NAME_FIRST = REPLACE(I$NAME_FIRST, 'Ё', 'Е');
  I$NAME_FIRST = REPLACE(I$NAME_FIRST, '-', '');
  I$NAME_FIRST = REPLACE(I$NAME_FIRST, ' ', '');
  I$NAME_MID = UPPER(TRIM(I$NAME_MID));
  I$NAME_MID = REPLACE(I$NAME_MID, 'Ё', 'Е');
  I$NAME_MID = REPLACE(I$NAME_MID, '-', '');
  I$NAME_MID = REPLACE(I$NAME_MID, ' ', '');
  I$NAME_LAST = UPPER(TRIM(I$NAME_LAST));
  I$NAME_LAST = REPLACE(I$NAME_LAST, 'Ё', 'Е');
  I$NAME_LAST = REPLACE(I$NAME_LAST, '-', '');
  I$NAME_LAST = REPLACE(I$NAME_LAST, ' ', '');
  I$DOC_SERIE = UPPER(TRIM(I$NAME_LAST));
  I$DOC_NUM = UPPER(TRIM(I$DOC_NUM));

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  S = 'Поиск сотрудника';
  IF(COALESCE(I$NAME_LAST, '') <> '') THEN S = S || ',Ф=' || I$NAME_LAST;
  IF(COALESCE(I$NAME_FIRST, '') <> '') THEN S = S || ',И=' || I$NAME_FIRST;
  IF(COALESCE(I$NAME_MID, '') <> '') THEN S = S || ',О=' || I$NAME_MID;
  IF(COALESCE(I$BIRTH_DATE, '') <> '') THEN S = S || ',ДР=' || I$BIRTH_DATE;
  IF(COALESCE(V$SNILS, '') <> '') THEN S = S || ',СНИЛС=' || V$SNILS;
  IF(COALESCE(I$DOC_SERIE, '') <> '') THEN S = S || ',ДС=' || I$DOC_SERIE;
  IF(COALESCE(I$DOC_NUM, '') <> '') THEN S = S || ',ДН=' || I$DOC_NUM;
  IF(COALESCE(I$DOC_DATE, '') <> '') THEN S = S || ',ДД=' || I$DOC_DATE;

  INSERT INTO PDA_LOG
  (USER_ID, OBJ_ID, LEVEL_ID, FROM_IP, EXTRA_DATA)
  VALUES (:I$USER_ID, NULL, NULL, :I$FROM_IP, SUBSTRING(:S FROM 1 FOR 1000));

  -- Отдельно проверяем, что такой документ не внесен еще у кого-нибудь, но с другими ФИО
  IF(I$DOC_TYPE IS NOT NULL) THEN
  BEGIN
    -- !!!
  END

  FOR
    SELECT DISTINCT ID, LAST_NAME, FIRST_NAME, MIDDLE_NAME, BIRTH_DATE, SNILS, CLASS_NAME, ROW_CLASS
    FROM (
      -- Выбывшие
      SELECT L14.OBJ_ID ID, CAST(V59.VAL AS VARCHAR(200)) LAST_NAME, CAST(V60.VAL AS VARCHAR(200)) FIRST_NAME, CAST(V61.VAL AS VARCHAR(200)) MIDDLE_NAME,
        V241.VAL BIRTH_DATE, CAST(V2455.VAL AS VARCHAR(20)) SNILS, 'Бывший сотрудник' CLASS_NAME, NULL ROW_CLASS
      FROM LINKS L84
      JOIN LINKS L14 ON L14.PARENT_ID = L84.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
      JOIN VALS V59 ON V59.OBJ_ID = L14.OBJ_ID AND V59.PARAM_ID = 59 AND V59.IS_DEL = 0
      JOIN VALS V60 ON V60.OBJ_ID = L14.OBJ_ID AND V60.PARAM_ID = 60 AND V60.IS_DEL = 0
      LEFT JOIN VALS V61 ON V61.OBJ_ID = L14.OBJ_ID AND V61.PARAM_ID = 61 AND V61.IS_DEL = 0
      JOIN VALD V241 ON V241.OBJ_ID = L14.OBJ_ID AND V241.PARAM_ID = 241 AND V241.IS_DEL = 0
      LEFT JOIN VALS V2455 ON V2455.OBJ_ID = L14.OBJ_ID AND V2455.PARAM_ID = 2455 AND V2455.IS_DEL = 0
      WHERE L84.PARENT_TYPE_ID = 2 AND L84.OBJ_TYPE_ID = 84 AND L84.DATE_DEL IS NULL AND (
        -- Фамилия + имя + отчество
        (V59.XVAL STARTING WITH :I$NAME_LAST AND V60.XVAL STARTING WITH :I$NAME_FIRST AND V61.XVAL STARTING WITH :I$NAME_MID)
        -- Фамилия + имя + ДР
        OR (V59.XVAL STARTING WITH :I$NAME_LAST AND V60.XVAL STARTING WITH :I$NAME_FIRST AND V241.VAL = :I$BIRTH_DATE)
        -- Фамилия + отчество + ДР
        OR (V59.XVAL STARTING WITH :I$NAME_LAST AND (V61.XVAL STARTING WITH :I$NAME_MID OR :I$NAME_MID IS NULL) AND V241.VAL = :I$BIRTH_DATE)
        -- имя + отчество + ДР
        OR (V60.XVAL STARTING WITH :I$NAME_FIRST AND (V61.XVAL STARTING WITH :I$NAME_MID OR :I$NAME_MID IS NULL) AND V241.VAL = :I$BIRTH_DATE)
        -- СНИЛС отдельно
        OR (V2455.XVAL = :I$SNILS)
      )
      -- Выбывшие по документу
      UNION
      SELECT L14.OBJ_ID ID, CAST(V59.VAL AS VARCHAR(200)) LAST_NAME, CAST(V60.VAL AS VARCHAR(200)) FIRST_NAME, CAST(V61.VAL AS VARCHAR(200)) MIDDLE_NAME,
        V241.VAL BIRTH_DATE, CAST(V2455.VAL AS VARCHAR(20)) SNILS, 'Бывший сотрудник' CLASS_NAME, NULL ROW_CLASS
      FROM LINKS L84
      JOIN LINKS L14 ON L14.PARENT_ID = L84.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
      JOIN VALS V59 ON V59.OBJ_ID = L14.OBJ_ID AND V59.PARAM_ID = 59 AND V59.IS_DEL = 0
      JOIN VALS V60 ON V60.OBJ_ID = L14.OBJ_ID AND V60.PARAM_ID = 60 AND V60.IS_DEL = 0
      LEFT JOIN VALS V61 ON V61.OBJ_ID = L14.OBJ_ID AND V61.PARAM_ID = 61 AND V61.IS_DEL = 0
      JOIN VALD V241 ON V241.OBJ_ID = L14.OBJ_ID AND V241.PARAM_ID = 241 AND V241.IS_DEL = 0
      LEFT JOIN VALS V2455 ON V2455.OBJ_ID = L14.OBJ_ID AND V2455.PARAM_ID = 2455 AND V2455.IS_DEL = 0
      JOIN LINKS L79 ON L79.PARENT_ID = L14.OBJ_ID AND L79.OBJ_TYPE_ID = 79 AND L79.DATE_DEL IS NULL
      JOIN VALS V559 ON V559.OBJ_ID = L79.OBJ_ID AND V559.PARAM_ID = 559 AND V559.IS_DEL = 0 AND (V559.SVAL = :I$DOC_NUM OR :I$DOC_NUM IS NULL)
      JOIN VALD V560 ON V560.OBJ_ID = L79.OBJ_ID AND V560.PARAM_ID = 560 AND V560.IS_DEL = 0 AND (V560.VAL = :I$DOC_DATE OR :I$DOC_DATE IS NULL)
      WHERE L84.PARENT_TYPE_ID = 2 AND L84.OBJ_TYPE_ID = 84 AND L84.DATE_DEL IS NULL AND (:I$DOC_NUM IS NOT NULL OR :I$DOC_DATE IS NOT NULL)
      -- Действующие сотрудники
      UNION
      SELECT L14.OBJ_ID ID, CAST(V59.VAL AS VARCHAR(200)) LAST_NAME, CAST(V60.VAL AS VARCHAR(200)) FIRST_NAME, CAST(V61.VAL AS VARCHAR(200)) MIDDLE_NAME,
        V241.VAL BIRTH_DATE, CAST(V2455.VAL AS VARCHAR(20)) SNILS, 'Действующий сотрудник' CLASS_NAME, 'alert' ROW_CLASS
      FROM LINKS L14
      JOIN VALS V59 ON V59.OBJ_ID = L14.OBJ_ID AND V59.PARAM_ID = 59 AND V59.IS_DEL = 0
      JOIN VALS V60 ON V60.OBJ_ID = L14.OBJ_ID AND V60.PARAM_ID = 60 AND V60.IS_DEL = 0
      LEFT JOIN VALS V61 ON V61.OBJ_ID = L14.OBJ_ID AND V61.PARAM_ID = 61 AND V61.IS_DEL = 0
      JOIN VALD V241 ON V241.OBJ_ID = L14.OBJ_ID AND V241.PARAM_ID = 241 AND V241.IS_DEL = 0
      LEFT JOIN VALS V2455 ON V2455.OBJ_ID = L14.OBJ_ID AND V2455.PARAM_ID = 2455 AND V2455.IS_DEL = 0
      WHERE L14.PARENT_TYPE_ID IN (2, 211) AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL AND (
        -- Фамилия + имя + отчество
        (V59.XVAL STARTING WITH :I$NAME_LAST AND V60.XVAL STARTING WITH :I$NAME_FIRST AND V61.XVAL STARTING WITH :I$NAME_MID)
        -- Фамилия + имя + ДР
        OR (V59.XVAL STARTING WITH :I$NAME_LAST AND V60.XVAL STARTING WITH :I$NAME_FIRST AND V241.VAL = :I$BIRTH_DATE)
        -- Фамилия + отчество + ДР
        OR (V59.XVAL STARTING WITH :I$NAME_LAST AND (V61.XVAL STARTING WITH :I$NAME_MID OR :I$NAME_MID IS NULL) AND V241.VAL = :I$BIRTH_DATE)
        -- имя + отчество + ДР
        OR (V60.XVAL STARTING WITH :I$NAME_FIRST AND (V61.XVAL STARTING WITH :I$NAME_MID OR :I$NAME_MID IS NULL) AND V241.VAL = :I$BIRTH_DATE)
        -- СНИЛС отдельно
        OR (V2455.XVAL = :I$SNILS)
      )
      -- Действующие по документу - в самой организации и в подразделениях
      UNION
      SELECT L14.OBJ_ID ID, CAST(V59.VAL AS VARCHAR(200)) LAST_NAME, CAST(V60.VAL AS VARCHAR(200)) FIRST_NAME, CAST(V61.VAL AS VARCHAR(200)) MIDDLE_NAME,
        V241.VAL BIRTH_DATE, CAST(V2455.VAL AS VARCHAR(20)) SNILS, 'Действующий сотрудник' CLASS_NAME, 'alert' ROW_CLASS
      FROM LINKS L14
      JOIN VALS V59 ON V59.OBJ_ID = L14.OBJ_ID AND V59.PARAM_ID = 59 AND V59.IS_DEL = 0
      JOIN VALS V60 ON V60.OBJ_ID = L14.OBJ_ID AND V60.PARAM_ID = 60 AND V60.IS_DEL = 0
      LEFT JOIN VALS V61 ON V61.OBJ_ID = L14.OBJ_ID AND V61.PARAM_ID = 61 AND V61.IS_DEL = 0
      JOIN VALD V241 ON V241.OBJ_ID = L14.OBJ_ID AND V241.PARAM_ID = 241 AND V241.IS_DEL = 0
      LEFT JOIN VALS V2455 ON V2455.OBJ_ID = L14.OBJ_ID AND V2455.PARAM_ID = 2455 AND V2455.IS_DEL = 0
      JOIN LINKS L79 ON L79.PARENT_ID = L14.OBJ_ID AND L79.OBJ_TYPE_ID = 79 AND L79.DATE_DEL IS NULL
      JOIN VALS V559 ON V559.OBJ_ID = L79.OBJ_ID AND V559.PARAM_ID = 559 AND V559.IS_DEL = 0 AND (V559.SVAL = :I$DOC_NUM OR :I$DOC_NUM IS NULL)
      JOIN VALD V560 ON V560.OBJ_ID = L79.OBJ_ID AND V560.PARAM_ID = 560 AND V560.IS_DEL = 0 AND (V560.VAL = :I$DOC_DATE OR :I$DOC_DATE IS NULL)
      WHERE L14.PARENT_TYPE_ID IN (2, 211) AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL AND (:I$DOC_NUM IS NOT NULL OR :I$DOC_DATE IS NOT NULL)
    ) L
    INTO :V$ID, :V$LAST_NAME, :V$FIRST_NAME, :V$MIDDLE_NAME, :V$BIRTH_DATE, :V$SNILS, :V$CLASS_NAME, :V$ROW_CLASS
  DO
  BEGIN

    TAG_NAME = 'r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'r:id';
    VAL = V$ID;
    SUSPEND;
    TAG_NAME = 'r:last_name';
    VAL = V$LAST_NAME;
    SUSPEND;
    TAG_NAME = 'r:first_name';
    VAL = V$FIRST_NAME;
    SUSPEND;
    TAG_NAME = 'r:middle_name';
    VAL = V$MIDDLE_NAME;
    SUSPEND;
    TAG_NAME = 'r:birth_date';
    VAL = (SELECT RESULT FROM DATE2STR(:V$BIRTH_DATE));
    SUSPEND;
    TAG_NAME = 'r:snils';
    VAL = V$SNILS;
    SUSPEND;
    TAG_NAME = 'r:class_name';
    VAL = V$CLASS_NAME;
    SUSPEND;
    TAG_NAME = 'r:row_class';
    VAL = V$ROW_CLASS;
    SUSPEND;

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PR3_FIND_PARENTS (
    I$NAME_LAST VARCHAR(400),
    I$NAME_FIRST VARCHAR(400),
    I$NAME_MID VARCHAR(400),
    I$BIRTH_DATE DATE,
    I$SNILS VARCHAR(40),
    I$USER_ID VARCHAR(40),
    I$FROM_IP VARCHAR(200) = NULL)
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$ID BIGINT;
DECLARE VARIABLE V$LAST_NAME VARCHAR(400);
DECLARE VARIABLE V$FIRST_NAME VARCHAR(400);
DECLARE VARIABLE V$MIDDLE_NAME VARCHAR(400);
DECLARE VARIABLE V$BIRTH_DATE DATE;
DECLARE VARIABLE V$SNILS VARCHAR(40);
DECLARE VARIABLE V$CLASS_NAME VARCHAR(1000);
DECLARE VARIABLE V$ROW_CLASS VARCHAR(100);
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE S VARCHAR(4000);
begin

  I$SNILS = REPLACE(I$SNILS, ' ', '');
  I$SNILS = REPLACE(I$SNILS, '-', '');
  I$NAME_FIRST = UPPER(TRIM(I$NAME_FIRST));
  I$NAME_MID = UPPER(TRIM(I$NAME_MID));
  I$NAME_LAST = UPPER(TRIM(I$NAME_LAST));
  V$ROW_CLASS = NULL;

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  S = 'Поиск родителя';
  IF(COALESCE(I$NAME_LAST, '') <> '') THEN S = S || ',Ф=' || I$NAME_LAST;
  IF(COALESCE(I$NAME_FIRST, '') <> '') THEN S = S || ',И=' || I$NAME_FIRST;
  IF(COALESCE(I$NAME_MID, '') <> '') THEN S = S || ',О=' || I$NAME_MID;
  IF(COALESCE(I$BIRTH_DATE, '') <> '') THEN S = S || ',ДР=' || I$BIRTH_DATE;
  IF(COALESCE(V$SNILS, '') <> '') THEN S = S || ',СНИЛС=' || V$SNILS;

  INSERT INTO PDA_LOG
  (USER_ID, OBJ_ID, LEVEL_ID, FROM_IP, EXTRA_DATA)
  VALUES (:I$USER_ID, NULL, NULL, :I$FROM_IP, SUBSTRING(:S FROM 1 FOR 1000));

  FOR
    SELECT DISTINCT L20.OBJ_ID
    FROM LINKS L20
    JOIN VALS V128 ON V128.OBJ_ID = L20.OBJ_ID AND V128.PARAM_ID = 128 AND V128.IS_DEL = 0
    JOIN VALS V129 ON V129.OBJ_ID = L20.OBJ_ID AND V129.PARAM_ID = 129 AND V129.IS_DEL = 0
    LEFT JOIN VALS V130 ON V130.OBJ_ID = L20.OBJ_ID AND V130.PARAM_ID = 130 AND V130.IS_DEL = 0
    LEFT JOIN VALD V143 ON V143.OBJ_ID = L20.OBJ_ID AND V143.PARAM_ID = 143 AND V143.IS_DEL = 0
    LEFT JOIN VALS V2365 ON V2365.OBJ_ID = L20.OBJ_ID AND V2365.PARAM_ID = 2365 AND V2365.IS_DEL = 0
    WHERE L20.PARENT_TYPE_ID = 10 AND L20.OBJ_TYPE_ID = 20 AND L20.DATE_DEL IS NULL
      AND (UPPER(V128.VAL) LIKE '%' || :I$NAME_LAST || '%' OR :I$NAME_LAST IS NULL)
      AND (UPPER(V129.VAL) LIKE '%' || :I$NAME_FIRST || '%' OR :I$NAME_FIRST IS NULL)
      AND (UPPER(V130.VAL) LIKE '%' || :I$NAME_MID || '%' OR :I$NAME_MID IS NULL OR V130.VAL IS NULL)
      AND (V143.VAL = :I$BIRTH_DATE OR :I$BIRTH_DATE IS NULL OR V143.VAL IS NULL)
      AND (REPLACE(REPLACE(V2365.VAL, ' ', ''), '-', '') = :I$SNILS OR :I$SNILS IS NULL OR V2365.VAL IS NULL)
    INTO :V$ID
  DO
  BEGIN
    V$CLASS_NAME = '';
    FOR
      SELECT LP10.PARENT_ID, C.CAPTION
      FROM LINKS LP10
      LEFT JOIN OBJECT_CAPTION_GET(LP10.PARENT_ID) C ON 1 = 1
      WHERE LP10.OBJ_ID = :V$ID AND LP10.PARENT_TYPE_ID = 10 AND LP10.DATE_DEL IS NULL
      ORDER BY 2
      INTO :V$OBJ_ID, :V$LAST_NAME
    DO
    BEGIN
      IF(V$CLASS_NAME <> '') THEN V$CLASS_NAME = V$CLASS_NAME || ', ';

      V$FIRST_NAME = '';
      SELECT FIRST 1 ' - ' || C.CAPTION
      FROM LINKS LPG
      LEFT JOIN OBJECT_CAPTION_GET(LPG.PARENT_ID) C ON 1 = 1
      WHERE LPG.OBJ_ID = :V$OBJ_ID AND LPG.PARENT_TYPE_ID IN (9, 125, 187, 81, 82, 83, 84, 290) AND LPG.DATE_DEL IS NULL
      INTO :V$FIRST_NAME;

      V$CLASS_NAME = V$CLASS_NAME || V$LAST_NAME || V$FIRST_NAME;
    END

    SELECT V128.SVAL, V129.SVAL, V130.SVAL, V143.VAL BIRTH_DATE, V2365.SVAL
    FROM OBJECTS L20
    JOIN VALS V128 ON V128.OBJ_ID = L20.OBJ_ID AND V128.PARAM_ID = 128 AND V128.IS_DEL = 0
    JOIN VALS V129 ON V129.OBJ_ID = L20.OBJ_ID AND V129.PARAM_ID = 129 AND V129.IS_DEL = 0
    LEFT JOIN VALS V130 ON V130.OBJ_ID = L20.OBJ_ID AND V130.PARAM_ID = 130 AND V130.IS_DEL = 0
    LEFT JOIN VALD V143 ON V143.OBJ_ID = L20.OBJ_ID AND V143.PARAM_ID = 143 AND V143.IS_DEL = 0
    LEFT JOIN VALS V2365 ON V2365.OBJ_ID = L20.OBJ_ID AND V2365.PARAM_ID = 2365 AND V2365.IS_DEL = 0
    WHERE L20.OBJ_ID = :V$ID
    INTO :V$LAST_NAME, :V$FIRST_NAME, :V$MIDDLE_NAME, :V$BIRTH_DATE, :V$SNILS;

    TAG_NAME = 'r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'r:id';
    VAL = V$ID;
    SUSPEND;
    TAG_NAME = 'r:last_name';
    VAL = V$LAST_NAME;
    SUSPEND;
    TAG_NAME = 'r:first_name';
    VAL = V$FIRST_NAME;
    SUSPEND;
    TAG_NAME = 'r:middle_name';
    VAL = V$MIDDLE_NAME;
    SUSPEND;
    TAG_NAME = 'r:birth_date';
    VAL = (SELECT RESULT FROM DATE2STR(:V$BIRTH_DATE));
    SUSPEND;
    TAG_NAME = 'r:snils';
    VAL = V$SNILS;
    SUSPEND;
    TAG_NAME = 'r:class_name';
    VAL = V$CLASS_NAME;
    SUSPEND;
    TAG_NAME = 'r:row_class';
    VAL = V$ROW_CLASS;
    SUSPEND;

    -- Добавляем сюда поля, которые уже заполнены
    TAG_NAME = 'r:citizenship';
    SELECT V, I FROM VAL_GET(:V$ID, 1559) WHERE IS_EXISTS = 1 INTO :V$CLASS_NAME, :VAL;
    SUSPEND;
    TAG_NAME = 'r:citizenship_text';
    VAL = V$CLASS_NAME;
    SUSPEND;
    TAG_NAME = 'r:home_phone';
    VAL = (SELECT V FROM VAL_GET(:V$ID, 145) WHERE IS_EXISTS = 1);
    SUSPEND;
    TAG_NAME = 'r:mobile_phone';
    VAL = (SELECT V FROM VAL_GET(:V$ID, 146) WHERE IS_EXISTS = 1);
    SUSPEND;
    TAG_NAME = 'r:email';
    VAL = (SELECT V FROM VAL_GET(:V$ID, 144) WHERE IS_EXISTS = 1);
    SUSPEND;
    TAG_NAME = 'r:work_place';
    VAL = (SELECT V FROM VAL_GET(:V$ID, 139) WHERE IS_EXISTS = 1);
    SUSPEND;
    TAG_NAME = 'r:job_name';
    VAL = (SELECT V FROM VAL_GET(:V$ID, 140) WHERE IS_EXISTS = 1);
    SUSPEND;
    TAG_NAME = 'r:work_phone';
    VAL = (SELECT V FROM VAL_GET(:V$ID, 141) WHERE IS_EXISTS = 1);
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PR3_FIND_STUDENTS (
    I$NAME_LAST VARCHAR(400),
    I$NAME_FIRST VARCHAR(400),
    I$NAME_MID VARCHAR(400),
    I$BIRTH_DATE DATE,
    I$SNILS VARCHAR(40),
    I$DOC_TYPE BIGINT,
    I$DOC_SERIE VARCHAR(40),
    I$DOC_NUM VARCHAR(40),
    I$DOC_DATE DATE,
    I$USER_ID VARCHAR(40),
    I$OBJ_ID BIGINT = NULL,
    I$FROM_IP VARCHAR(200) = NULL)
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$ID BIGINT;
DECLARE VARIABLE V$LAST_NAME VARCHAR(400);
DECLARE VARIABLE V$FIRST_NAME VARCHAR(400);
DECLARE VARIABLE V$MIDDLE_NAME VARCHAR(400);
DECLARE VARIABLE V$BIRTH_DATE DATE;
DECLARE VARIABLE V$SNILS VARCHAR(40);
DECLARE VARIABLE V$CLASS_NAME VARCHAR(400);
DECLARE VARIABLE V$ROW_CLASS VARCHAR(100);
DECLARE VARIABLE V$TYPE_ID BIGINT;
DECLARE VARIABLE S VARCHAR(4000);
begin

  IF(I$DOC_TYPE IS NOT NULL) THEN
  BEGIN
    IF(I$DOC_NUM IS NULL AND I$DOC_DATE IS NULL) THEN EXCEPTION DATA_ERROR 'Если указан тип документа, должно быть указано хотя бы одно значение поля документа';
  END

  I$SNILS = REPLACE(I$SNILS, ' ', '');
  I$SNILS = REPLACE(I$SNILS, '-', '');
  I$NAME_FIRST = UPPER(TRIM(I$NAME_FIRST));
  I$NAME_FIRST = REPLACE(I$NAME_FIRST, 'Ё', 'Е');
  I$NAME_FIRST = REPLACE(I$NAME_FIRST, '-', '');
  I$NAME_FIRST = REPLACE(I$NAME_FIRST, ' ', '');
  I$NAME_MID = UPPER(TRIM(I$NAME_MID));
  I$NAME_MID = REPLACE(I$NAME_MID, 'Ё', 'Е');
  I$NAME_MID = REPLACE(I$NAME_MID, '-', '');
  I$NAME_MID = REPLACE(I$NAME_MID, ' ', '');
  I$NAME_LAST = UPPER(TRIM(I$NAME_LAST));
  I$NAME_LAST = REPLACE(I$NAME_LAST, 'Ё', 'Е');
  I$NAME_LAST = REPLACE(I$NAME_LAST, '-', '');
  I$NAME_LAST = REPLACE(I$NAME_LAST, ' ', '');
  I$DOC_SERIE = UPPER(TRIM(I$NAME_LAST));
  I$DOC_NUM = UPPER(TRIM(I$DOC_NUM));

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  S = 'Поиск обучающегося';
  IF(COALESCE(I$NAME_LAST, '') <> '') THEN S = S || ',Ф=' || I$NAME_LAST;
  IF(COALESCE(I$NAME_FIRST, '') <> '') THEN S = S || ',И=' || I$NAME_FIRST;
  IF(COALESCE(I$NAME_MID, '') <> '') THEN S = S || ',О=' || I$NAME_MID;
  IF(COALESCE(I$BIRTH_DATE, '') <> '') THEN S = S || ',ДР=' || I$BIRTH_DATE;
  IF(COALESCE(V$SNILS, '') <> '') THEN S = S || ',СНИЛС=' || V$SNILS;
  IF(COALESCE(I$DOC_SERIE, '') <> '') THEN S = S || ',ДС=' || I$DOC_SERIE;
  IF(COALESCE(I$DOC_NUM, '') <> '') THEN S = S || ',ДН=' || I$DOC_NUM;
  IF(COALESCE(I$DOC_DATE, '') <> '') THEN S = S || ',ДД=' || I$DOC_DATE;

  INSERT INTO PDA_LOG
  (USER_ID, OBJ_ID, LEVEL_ID, FROM_IP, EXTRA_DATA)
  VALUES (:I$USER_ID, NULL, NULL, :I$FROM_IP, SUBSTRING(:S FROM 1 FOR 1000));

  -- Отдельно проверяем, что такой документ не внесен еще у кого-нибудь, но с другими ФИО
  IF(I$DOC_TYPE IS NOT NULL) THEN
  BEGIN
    -- !!!
  END

  -- Поиск делаем по всем совпадениям, исключая поочередно один из параметров
  -- К результатам добавляем поиск по номеру и дате документа, если он был указан

  FOR
    SELECT DISTINCT ID, LAST_NAME, FIRST_NAME, MIDDLE_NAME, BIRTH_DATE, SNILS, CLASS_NAME, ROW_CLASS
    FROM (
      -- Выбывшие, окончившие, предварительный прием
      SELECT L10.OBJ_ID ID, CAST(V55.VAL AS VARCHAR(200)) LAST_NAME, CAST(V56.VAL AS VARCHAR(200)) FIRST_NAME, CAST(V57.VAL AS VARCHAR(200)) MIDDLE_NAME,
        V89.VAL BIRTH_DATE, CAST(V1409.SVAL AS VARCHAR(20)) SNILS, IIF(L78.OBJ_TYPE_ID = 78, 'Выбывший учащийся', 'Предварительный прием') CLASS_NAME, NULL ROW_CLASS
      FROM LINKS L78
      JOIN LINKS L8X ON L8X.PARENT_ID = L78.OBJ_ID AND L8X.OBJ_TYPE_ID IN (81, 82, 83, 84, 290) AND L8X.DATE_DEL IS NULL
      JOIN LINKS L10 ON L10.PARENT_ID = L8X.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      JOIN VALS V55 ON V55.OBJ_ID = L10.OBJ_ID AND V55.PARAM_ID = 55 AND V55.IS_DEL = 0
      JOIN VALS V56 ON V56.OBJ_ID = L10.OBJ_ID AND V56.PARAM_ID = 56 AND V56.IS_DEL = 0
      LEFT JOIN VALS V57 ON V57.OBJ_ID = L10.OBJ_ID AND V57.PARAM_ID = 57 AND V57.IS_DEL = 0
      JOIN VALD V89 ON V89.OBJ_ID = L10.OBJ_ID AND V89.PARAM_ID = 89 AND V89.IS_DEL = 0
      LEFT JOIN VALS V1409 ON V1409.OBJ_ID = L10.OBJ_ID AND V1409.PARAM_ID = 1409 AND V1409.IS_DEL = 0
      WHERE L78.PARENT_TYPE_ID = 2 AND L78.OBJ_TYPE_ID IN (77, 78) AND L78.DATE_DEL IS NULL AND (
        -- Фамилия + имя + отчество
        (V55.XVAL STARTING WITH :I$NAME_LAST AND V56.XVAL STARTING WITH :I$NAME_FIRST AND V57.XVAL STARTING WITH :I$NAME_MID)
        -- Фамилия + имя + ДР
        OR (V55.XVAL STARTING WITH :I$NAME_LAST AND V56.XVAL STARTING WITH :I$NAME_FIRST AND V89.VAL = :I$BIRTH_DATE)
        -- Фамилия + отчество + ДР
        OR (V55.XVAL STARTING WITH :I$NAME_LAST AND (V57.XVAL STARTING WITH :I$NAME_MID OR :I$NAME_MID IS NULL) AND V89.VAL = :I$BIRTH_DATE)
        -- имя + отчество + ДР
        OR (V56.XVAL STARTING WITH :I$NAME_FIRST AND (V57.XVAL STARTING WITH :I$NAME_MID OR :I$NAME_MID IS NULL) AND V89.VAL = :I$BIRTH_DATE)
        -- СНИЛС отдельно
        OR (V1409.XVAL = :I$SNILS)
        -- по конкретной персоне для справки
        OR (L10.OBJ_ID = :I$OBJ_ID AND :I$OBJ_ID IS NOT NULL)
      )
      -- По номеру документа
      UNION
      SELECT L10.OBJ_ID ID, CAST(V55.VAL AS VARCHAR(200)) LAST_NAME, CAST(V56.VAL AS VARCHAR(200)) FIRST_NAME, CAST(V57.VAL AS VARCHAR(200)) MIDDLE_NAME,
        V89.VAL BIRTH_DATE, CAST(V1409.SVAL AS VARCHAR(20)) SNILS, IIF(L78.OBJ_TYPE_ID = 78, 'Выбывший учащийся', 'Предварительный прием') CLASS_NAME, NULL ROW_CLASS
      FROM LINKS L78
      JOIN LINKS L8X ON L8X.PARENT_ID = L78.OBJ_ID AND L8X.OBJ_TYPE_ID IN (81, 82, 83, 84, 290) AND L8X.DATE_DEL IS NULL
      JOIN LINKS L10 ON L10.PARENT_ID = L8X.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      JOIN VALS V55 ON V55.OBJ_ID = L10.OBJ_ID AND V55.PARAM_ID = 55 AND V55.IS_DEL = 0
      JOIN VALS V56 ON V56.OBJ_ID = L10.OBJ_ID AND V56.PARAM_ID = 56 AND V56.IS_DEL = 0
      LEFT JOIN VALS V57 ON V57.OBJ_ID = L10.OBJ_ID AND V57.PARAM_ID = 57 AND V57.IS_DEL = 0
      JOIN VALD V89 ON V89.OBJ_ID = L10.OBJ_ID AND V89.PARAM_ID = 89 AND V89.IS_DEL = 0
      LEFT JOIN VALS V1409 ON V1409.OBJ_ID = L10.OBJ_ID AND V1409.PARAM_ID = 1409 AND V1409.IS_DEL = 0
      JOIN LINKS L79 ON L79.PARENT_ID = L10.OBJ_ID AND L79.OBJ_TYPE_ID = 79 AND L79.DATE_DEL IS NULL
      JOIN VALS V559 ON V559.OBJ_ID = L79.OBJ_ID AND V559.PARAM_ID = 559 AND V559.IS_DEL = 0 AND (V559.SVAL = :I$DOC_NUM OR :I$DOC_NUM IS NULL)
      JOIN VALD V560 ON V560.OBJ_ID = L79.OBJ_ID AND V560.PARAM_ID = 560 AND V560.IS_DEL = 0 AND (V560.VAL = :I$DOC_DATE OR :I$DOC_DATE IS NULL)
      WHERE L78.PARENT_TYPE_ID = 2 AND L78.OBJ_TYPE_ID IN (77, 78) AND L78.DATE_DEL IS NULL AND (:I$DOC_NUM IS NOT NULL OR :I$DOC_DATE IS NOT NULL)
      -- Действующие
      UNION
      SELECT L10.OBJ_ID ID, CAST(V55.VAL AS VARCHAR(200)) LAST_NAME, CAST(V56.VAL AS VARCHAR(200)) FIRST_NAME, CAST(V57.VAL AS VARCHAR(200)) MIDDLE_NAME,
        V89.VAL BIRTH_DATE, CAST(V1409.SVAL AS VARCHAR(20)) SNILS, CAST('Действующий учащийся ' || C.SCAPTION AS VARCHAR(400)) CLASS_NAME, 'alert' ROW_CLASS
      FROM LINKS L7
      JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 187) AND L9.DATE_DEL IS NULL
      JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      JOIN VALS V55 ON V55.OBJ_ID = L10.OBJ_ID AND V55.PARAM_ID = 55 AND V55.IS_DEL = 0
      JOIN VALS V56 ON V56.OBJ_ID = L10.OBJ_ID AND V56.PARAM_ID = 56 AND V56.IS_DEL = 0
      LEFT JOIN VALS V57 ON V57.OBJ_ID = L10.OBJ_ID AND V57.PARAM_ID = 57 AND V57.IS_DEL = 0
      JOIN VALD V89 ON V89.OBJ_ID = L10.OBJ_ID AND V89.PARAM_ID = 89 AND V89.IS_DEL = 0
      LEFT JOIN VALS V1409 ON V1409.OBJ_ID = L10.OBJ_ID AND V1409.PARAM_ID = 1409 AND V1409.IS_DEL = 0
      LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C ON 1 = 1
      WHERE L7.PARENT_TYPE_ID = 2 AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL AND (
        -- Фамилия + имя + отчество
        (V55.XVAL STARTING WITH :I$NAME_LAST AND V56.XVAL STARTING WITH :I$NAME_FIRST AND V57.XVAL STARTING WITH :I$NAME_MID)
        -- Фамилия + имя + ДР
        OR (V55.XVAL STARTING WITH :I$NAME_LAST AND V56.XVAL STARTING WITH :I$NAME_FIRST AND V89.VAL = :I$BIRTH_DATE)
        -- Фамилия + отчество + ДР
        OR (V55.XVAL STARTING WITH :I$NAME_LAST AND (V57.XVAL STARTING WITH :I$NAME_MID OR :I$NAME_MID IS NULL) AND V89.VAL = :I$BIRTH_DATE)
        -- имя + отчество + ДР
        OR (V56.XVAL STARTING WITH :I$NAME_FIRST AND (V57.XVAL STARTING WITH :I$NAME_MID OR :I$NAME_MID IS NULL) AND V89.VAL = :I$BIRTH_DATE)
        -- СНИЛС отдельно
        OR (V1409.XVAL = :I$SNILS)
        -- по конкретной персоны для справки
        OR (L10.OBJ_ID = :I$OBJ_ID AND :I$OBJ_ID IS NOT NULL)
      )
      -- Действующие по номеру документа
      UNION
      SELECT L10.OBJ_ID ID, CAST(V55.VAL AS VARCHAR(200)) LAST_NAME, CAST(V56.VAL AS VARCHAR(200)) FIRST_NAME, CAST(V57.VAL AS VARCHAR(200)) MIDDLE_NAME,
        V89.VAL BIRTH_DATE, CAST(V1409.SVAL AS VARCHAR(20)) SNILS, CAST('Действующий учащийся ' || C.SCAPTION AS VARCHAR(400)) CLASS_NAME, 'alert' ROW_CLASS
      FROM LINKS L7
      JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 187) AND L9.DATE_DEL IS NULL
      JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      JOIN VALS V55 ON V55.OBJ_ID = L10.OBJ_ID AND V55.PARAM_ID = 55 AND V55.IS_DEL = 0
      JOIN VALS V56 ON V56.OBJ_ID = L10.OBJ_ID AND V56.PARAM_ID = 56 AND V56.IS_DEL = 0
      LEFT JOIN VALS V57 ON V57.OBJ_ID = L10.OBJ_ID AND V57.PARAM_ID = 57 AND V57.IS_DEL = 0
      JOIN VALD V89 ON V89.OBJ_ID = L10.OBJ_ID AND V89.PARAM_ID = 89 AND V89.IS_DEL = 0
      LEFT JOIN VALS V1409 ON V1409.OBJ_ID = L10.OBJ_ID AND V1409.PARAM_ID = 1409 AND V1409.IS_DEL = 0
      LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C ON 1 = 1
      JOIN LINKS L79 ON L79.PARENT_ID = L10.OBJ_ID AND L79.OBJ_TYPE_ID = 79 AND L79.DATE_DEL IS NULL
      JOIN VALS V559 ON V559.OBJ_ID = L79.OBJ_ID AND V559.PARAM_ID = 559 AND V559.IS_DEL = 0 AND (V559.SVAL = :I$DOC_NUM OR :I$DOC_NUM IS NULL)
      JOIN VALD V560 ON V560.OBJ_ID = L79.OBJ_ID AND V560.PARAM_ID = 560 AND V560.IS_DEL = 0 AND (V560.VAL = :I$DOC_DATE OR :I$DOC_DATE IS NULL)
      WHERE L7.PARENT_TYPE_ID = 2 AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL AND (:I$DOC_NUM IS NOT NULL OR :I$DOC_DATE IS NOT NULL)
      -- Предварительный прием !!!
    ) L
    INTO :V$ID, :V$LAST_NAME, :V$FIRST_NAME, :V$MIDDLE_NAME, :V$BIRTH_DATE, :V$SNILS, :V$CLASS_NAME, :V$ROW_CLASS
  DO
  BEGIN

    TAG_NAME = 'r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'r:id';
    VAL = V$ID;
    SUSPEND;
    TAG_NAME = 'r:last_name';
    VAL = V$LAST_NAME;
    SUSPEND;
    TAG_NAME = 'r:first_name';
    VAL = V$FIRST_NAME;
    SUSPEND;
    TAG_NAME = 'r:middle_name';
    VAL = V$MIDDLE_NAME;
    SUSPEND;
    TAG_NAME = 'r:birth_date';
    VAL = (SELECT RESULT FROM DATE2STR(:V$BIRTH_DATE));
    SUSPEND;
    TAG_NAME = 'r:snils';
    VAL = V$SNILS;
    SUSPEND;
    TAG_NAME = 'r:class_name';
    VAL = TRIM(V$CLASS_NAME);
    SUSPEND;
    TAG_NAME = 'r:row_class';
    VAL = V$ROW_CLASS;
    SUSPEND;

    -- Год окончания/выбытия
    TAG_NAME = 'r:leave_year';
    VAL = NULL;
    V$TYPE_ID = NULL;
    SELECT FIRST 1 L.PARENT_TYPE_ID, V.VAL
    FROM LINKS L
    JOIN VALI V ON V.OBJ_ID = L.PARENT_ID AND V.PARAM_ID IN (445, 449, 451) AND V.IS_DEL = 0
    WHERE L.OBJ_ID = :V$ID AND L.PARENT_TYPE_ID IN (81, 82, 83) AND L.DATE_DEL IS NULL
    INTO :V$TYPE_ID, :VAL;
    SUSPEND;
    TAG_NAME = 'r:leave_type';
    VAL = V$TYPE_ID;
    SUSPEND;

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PRE_ACCEPT_PERSON (
    I$OBJ_ID BIGINT = NULL)
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$TYPE_ID BIGINT;
DECLARE VARIABLE V$PARENT_ID BIGINT;
DECLARE VARIABLE V$PARENT_TYPE_ID BIGINT;
DECLARE VARIABLE V$STAGE_ID BIGINT;
DECLARE VARIABLE V$STAGE_PARENT BIGINT;
DECLARE VARIABLE V$DATE_OUT DATE;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$LEVEL_ID BIGINT;
DECLARE VARIABLE V$DEST_STAGE BIGINT;
DECLARE VARIABLE V$YEAR_ID BIGINT;
DECLARE VARIABLE V$Y INTEGER;
DECLARE VARIABLE V$GUP_ID BIGINT;
DECLARE VARIABLE M BIGINT;
DECLARE VARIABLE N INTEGER;
DECLARE VARIABLE S VARCHAR(1000);
DECLARE VARIABLE S2 VARCHAR(1000);
DECLARE VARIABLE V$OBJ_TYPE BIGINT;
DECLARE VARIABLE V$YC1 VARCHAR(40);
DECLARE VARIABLE V$YC2 VARCHAR(40);
DECLARE VARIABLE V$YC3 VARCHAR(40);
DECLARE VARIABLE V$YC4 VARCHAR(40);
begin

  -- Проверка корректности предварительного приема
  IF(I$OBJ_ID IS NOT NULL) THEN
  BEGIN
    SELECT TYPE_ID
    FROM OBJECTS
    WHERE OBJ_ID = :I$OBJ_ID
    INTO :V$TYPE_ID;

    IF(V$TYPE_ID = 290 AND NOT EXISTS(
      SELECT FIRST 1 1
      FROM VALL V
      WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 2346 AND V.IS_DEL = 0
    ))
    THEN
      EXCEPTION DATA_ERROR 'Не указан этап зачисления для предварительного приема';
  END

  TAG_NAME = 'last_name';
  VAL = NULL;
  SELECT FIRST 1 P.EDIT_MASK
  FROM PARAMS P
  WHERE P.PARAM_ID = 55
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'first_name';
  VAL = NULL;
  SELECT FIRST 1 P.EDIT_MASK
  FROM PARAMS P
  WHERE P.PARAM_ID = 56
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'middle_name';
  VAL = NULL;
  SELECT FIRST 1 P.EDIT_MASK
  FROM PARAMS P
  WHERE P.PARAM_ID = 57
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'snils';
  VAL = NULL;
  SELECT FIRST 1 P.EDIT_MASK
  FROM PARAMS P
  WHERE P.PARAM_ID = 1409
  INTO :VAL;
  SUSPEND;

  -- Для обучающихся - надо получить данные где он числится сейчас
  -- и куда его можно перевести
  IF(V$TYPE_ID = 10) THEN
  BEGIN
    SELECT FIRST 1 LV.COST, V1236.LISTVAL_ID
    FROM LINKS L2
    JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :V$Y, :V$YEAR_ID;

    -- Какие ступени обучения у нас вообще продекларированы ? Часть операций может быть ограничена
    TAG_NAME = 'has_do';
    VAL = 0;
    SUSPEND;

    TAG_NAME = 'has_oo';
    VAL = 0;
    SUSPEND;

    TAG_NAME = 'has_spo';
    VAL = 0;
    SUSPEND;

    SELECT FIRST 1 LPG.PARENT_ID, LPG.PARENT_TYPE_ID
    FROM LINKS LPG
    WHERE LPG.OBJ_ID = :I$OBJ_ID AND LPG.PARENT_TYPE_ID IN (9, 125, 187, 289, 290, 81, 82, 83) AND LPG.DATE_DEL IS NULL
    -- папки выбывших идут с самым низким приоритетом
    ORDER BY IIF(LPG.PARENT_TYPE_ID IN (81, 82, 83), 9999, LPG.PARENT_TYPE_ID)
    INTO :V$PARENT_ID, :V$PARENT_TYPE_ID;

    IF(V$PARENT_TYPE_ID IN (9, 125, 187)) THEN
      SELECT V49.LISTVAL_ID, LV.PARENT_ID
      FROM LINKS LP8
      JOIN VALL V49 ON V49.OBJ_ID = LP8.PARENT_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
      JOIN LISTVALS LV ON LV.LISTVAL_ID = V49.LISTVAL_ID
      WHERE LP8.OBJ_ID = :V$PARENT_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
      INTO :V$STAGE_ID, :V$STAGE_PARENT;
    ELSE IF(V$PARENT_TYPE_ID = 290) THEN
      SELECT V.LISTVAL_ID, LV.PARENT_ID
      FROM VALL V
      JOIN LISTVALS LV ON LV.LISTVAL_ID = V.LISTVAL_ID
      WHERE V.OBJ_ID = :V$PARENT_ID AND V.PARAM_ID = 2346 AND V.IS_DEL = 0
      INTO :V$STAGE_ID, :V$STAGE_PARENT;
    ELSE
      SELECT FIRST 1 M.STAGE_ID, LV.PARENT_ID, M.DATE_OUT
      FROM PERSON_MOVEMENTS M
      JOIN LISTVALS LV ON LV.LISTVAL_ID = M.STAGE_ID
      WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :I$OBJ_ID AND M.GROUP_TYPE_ID IN (9, 290)
      ORDER BY M.DATE_IN DESC
      INTO :V$STAGE_ID, :V$STAGE_PARENT, :V$DATE_OUT;

    TAG_NAME = 'current_in';
    VAL = V$PARENT_TYPE_ID;
    SUSPEND;

    TAG_NAME = 'stage_id';
    VAL = V$STAGE_ID;
    SUSPEND;

    TAG_NAME = 'stage_parent';
    VAL = V$STAGE_PARENT;
    SUSPEND;

    -- Если выбыл более 1 года назад, очищаем запреты
    IF(V$PARENT_TYPE_ID IN (81, 82, 83) AND V$DATE_OUT < DATEADD(-11 MONTH TO CURRENT_DATE)) THEN
    BEGIN
      V$STAGE_ID = NULL;
      V$STAGE_PARENT = NULL;
    END

    -- Из учебного коллектива обратно в предварительный прием вернуть нельзя
    -- Внимание: level_id для предварительного приема и для классов идут из разных справочников
    TAG_NAME = 'groups::json&colon;array';
    VAL = 1;
    SUSPEND;
    -- Предварительный прием - только если ученик не числится, числится в экстернате или сдающих ЕГЭ
    -- Из СПО вернуться в сад нельзя
    IF(V$PARENT_TYPE_ID IN (81, 82, 83, 125, 187, 290)) THEN
    FOR
      SELECT L290.OBJ_ID, C.CAPTION, LV.PARENT_ID, V2346.LISTVAL_ID, LV.COST
      FROM LINKS L2
      JOIN LINKS L77 ON L77.PARENT_ID = L2.OBJ_ID AND L77.OBJ_TYPE_ID = 77 AND L77.DATE_DEL IS NULL
      JOIN LINKS L290 ON L290.PARENT_ID = L77.OBJ_ID AND L290.OBJ_TYPE_ID = 290 AND L290.DATE_DEL IS NULL AND L290.OBJ_ID <> :V$PARENT_ID
      JOIN VALL V2346 ON V2346.OBJ_ID = L290.OBJ_ID AND V2346.PARAM_ID = 2346 AND V2346.IS_DEL = 0
      JOIN LISTVALS LV ON LV.LISTVAL_ID = V2346.LISTVAL_ID
      LEFT JOIN OBJECT_CAPTION_GET(L290.OBJ_ID) C ON 1 = 1
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      ORDER BY 3, 5
      INTO :V$OBJ_ID, :S, :V$LEVEL_ID, :V$DEST_STAGE, :N
    DO
    BEGIN
      IF(V$OBJ_ID IS NOT NULL) THEN
      BEGIN
        TAG_NAME = 'groups:r';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'groups:r:id';
        VAL = V$OBJ_ID;
        SUSPEND;
        TAG_NAME = 'groups:r:type_id';
        VAL = 290;
        SUSPEND;
        TAG_NAME = 'groups:r:name';
        VAL = S;
        SUSPEND;
        TAG_NAME = 'groups:r:stage_id';
        VAL = V$DEST_STAGE;
        SUSPEND;
        TAG_NAME = 'groups:r:edu_level';
        VAL = V$LEVEL_ID;
        SUSPEND;
      END
    END
    -- Действующие учебные коллективы и экстернаты
    -- если ученик является действующим или в предварительном приеме - только той же ступени обучения
    FOR
      SELECT L9.OBJ_ID, C.CAPTION, V43.LISTVAL_ID, V49.LISTVAL_ID, LV49.COST, L9.OBJ_TYPE_ID
      FROM LINKS L2
      JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
      JOIN VALL V43 ON V43.OBJ_ID = L7.OBJ_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0 AND V43.LISTVAL_ID IN (3263, 3264, 22, 26, 27, 28, 29, 13129, 13131)
      JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
      JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
      JOIN LISTVALS LV49 ON LV49.LISTVAL_ID = V49.LISTVAL_ID
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 187) AND L9.DATE_DEL IS NULL AND L9.OBJ_ID <> :V$PARENT_ID
      LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C ON 1 = 1
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      ORDER BY 3, 5
      INTO :V$OBJ_ID, :S, :V$LEVEL_ID, :V$DEST_STAGE, :N, :V$OBJ_TYPE
    DO
    BEGIN
      -- Из сада можно перейти только в сад
      IF(V$STAGE_PARENT = 2140 AND V$LEVEL_ID NOT IN (3263, 3264)) THEN V$OBJ_ID = NULL;
      -- Для предварительного приема ДОУ запрещаем перевод напрямую в группу
      IF(V$STAGE_PARENT = 2140 AND V$PARENT_TYPE_ID = 290) THEN V$OBJ_ID = NULL;
      -- Из школы в сад перейти нельзя, но в СПО можно
      IF(V$STAGE_PARENT IN (2141, 12941) AND V$LEVEL_ID IN (3263, 3264)) THEN V$OBJ_ID = NULL;
      -- Из СПО в сад перейти нельзя, но в школу можно
      IF(V$STAGE_PARENT = 2142 AND V$LEVEL_ID IN (3263, 3264)) THEN V$OBJ_ID = NULL;

      IF(V$OBJ_ID IS NOT NULL) THEN
      BEGIN
        TAG_NAME = 'groups:r';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'groups:r:id';
        VAL = V$OBJ_ID;
        SUSPEND;
        TAG_NAME = 'groups:r:type_id';
        VAL = V$OBJ_TYPE;
        SUSPEND;
        TAG_NAME = 'groups:r:name';
        VAL = S;
        SUSPEND;
        TAG_NAME = 'groups:r:stage_id';
        VAL = V$DEST_STAGE;
        SUSPEND;
        TAG_NAME = 'groups:r:edu_level';
        VAL = V$LEVEL_ID;
        SUSPEND;
      END
    END

    -- Сдача ГИА, не выдаем
    -- Прием идет только отдельной кнопкой, через ACCEPT_GIA_DTL

    -- Академический отпуск, только если ученик и СПО, и только в действующей группе
    -- создаем папку если ее не было раньше
    IF(V$STAGE_PARENT = 2142 AND V$PARENT_TYPE_ID = 9) THEN
    BEGIN
      V$OBJ_ID = NULL;
      SELECT FIRST 1 L7.OBJ_ID, L289.OBJ_ID
      FROM LINKS L2
      JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
      JOIN VALL V43 ON V43.OBJ_ID = L7.OBJ_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0 AND V43.LISTVAL_ID = 29
      LEFT JOIN LINKS L289 ON L289.PARENT_ID = L7.OBJ_ID AND L289.OBJ_TYPE_ID = 289 AND L289.DATE_DEL IS NULL
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      INTO :V$DEST_STAGE, :V$OBJ_ID;

      IF(V$OBJ_ID IS NULL) THEN
      BEGIN
        IF(V$DEST_STAGE IS NULL) THEN EXCEPTION DATA_ERROR 'Не найден раздел СПО в учебных коллективах';
        SELECT OBJ_ID FROM OBJECT_ADD(:V$DEST_STAGE, 289) INTO :V$OBJ_ID;
      END

      TAG_NAME = 'groups:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'groups:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'groups:r:type_id';
      VAL = 289;
      SUSPEND;
      TAG_NAME = 'groups:r:name';
      VAL = 'Академический отпуск';
      SUSPEND;
    END

    -- Список учебных групп
    -- Группы только ОО. В СПО будет автоматическое распределение в ГУП, а в ДОО ГУП вообще нет
    V$YC1 = V$Y || '/' || (V$Y + 1); --- XXXX/XXXX
    V$YC2 = V$Y || '/' || SUBSTRING(V$Y + 1 FROM 3); --- XXXX/XX
    V$YC3 = V$Y || '-' || (V$Y + 1); --- XXXX-XXXX
    V$YC4 = V$Y || '-' || SUBSTRING(V$Y + 1 FROM 3); --- XXXX-XX

    TAG_NAME = 'gup::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT L256.OBJ_ID, V381.LISTVAL_ID, C.CAPTION, LV.COST
      FROM LINKS L2
      JOIN LINKS L69 ON L69.PARENT_ID = L2.OBJ_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL
      JOIN VALL V2450 ON V2450.OBJ_ID = L69.OBJ_ID AND V2450.PARAM_ID = 2450 AND V2450.IS_DEL = 0 AND V2450.LISTVAL_ID = 11385
      JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
      JOIN VALI V3115 ON V3115.OBJ_ID = L57.OBJ_ID AND V3115.PARAM_ID = 3115 AND V3115.IS_DEL = 0
      JOIN LINKS L400 ON L400.PARENT_ID = L57.OBJ_ID AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL
      JOIN VALS V3012 ON V3012.OBJ_ID = L400.OBJ_ID AND V3012.PARAM_ID = 3012 AND V3012.IS_DEL = 0
      JOIN VALL V3013 ON V3013.OBJ_ID = L400.OBJ_ID AND V3013.PARAM_ID = 3013 AND V3013.IS_DEL = 0 AND V3013.LISTVAL_ID = 11715
      JOIN LINKS L54 ON L54.PARENT_ID = L400.OBJ_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
      JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
      JOIN LISTVALS LV ON LV.LISTVAL_ID = V381.LISTVAL_ID
      JOIN LINKS L256 ON L256.PARENT_ID = L54.OBJ_ID AND L256.OBJ_TYPE_ID = 256 AND L256.DATE_DEL IS NULL
      LEFT JOIN OBJECT_CAPTION_GET(L256.OBJ_ID) C ON 1 = 1
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
        AND (V3115.VAL = :V$Y OR POSITION(:V$YC1 IN V3012.SVAL) > 0 OR POSITION(:V$YC2 IN V3012.SVAL) > 0 OR POSITION(:V$YC3 IN V3012.SVAL) > 0 OR POSITION(:V$YC4 IN V3012.SVAL) > 0)
      ORDER BY 2, 3
      INTO :V$OBJ_ID, :V$DEST_STAGE, :S, :N
    DO
    BEGIN
      TAG_NAME = 'gup:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'gup:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'gup:r:name';
      VAL = S;
      SUSPEND;
      TAG_NAME = 'gup:r:stage_id';
      VAL = V$DEST_STAGE;
      SUSPEND;
      -- Нужен чтобы склеивать ГУП и ГПП
      TAG_NAME = 'gup:r:stage_cost';
      VAL = N;
      SUSPEND;
    END

    -- Предметные группы, проверяем наличие связи с ГУП
    TAG_NAME = 'gsubj::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT CJ.GRADE_ID, CJ.STAGE_INDEX, CJ.JOURNAL_NAME, V.VAL, LV.PARENT_ID, V3370.VAL, CJ.STAGE_MASK
      FROM CJ2_JOURNAL CJ
      JOIN LISTVALS LV ON LV.LISTVAL_ID = CJ.STAGE_INDEX
      -- Из какой группы большинство учеников ?
      LEFT JOIN VALR V3370 ON V3370.OBJ_ID = CJ.GRADE_ID AND V3370.PARAM_ID = 3370 AND V3370.IS_DEL = 0
      JOIN VALS V ON V.OBJ_ID = CJ.SUBJECT_ID AND V.PARAM_ID IN (376, 1751) AND V.IS_DEL = 0
      -- исключаем ГПП, однозначно связанные с ГУП
      LEFT JOIN LINKS L179 ON L179.OBJ_ID = CJ.GRADE_ID AND L179.PARENT_TYPE_ID = 2 AND L179.DATE_DEL IS NULL
      WHERE CJ.DATE_DEL IS NULL AND CJ.YEAR_ID = :V$YEAR_ID AND CJ.JOURNAL_TYPE = 0 AND CJ.GRADE_TYPE_ID = 179 AND L179.EXT_OBJ_ID IS NULL
      ORDER BY 3, 4
      INTO :V$OBJ_ID, :V$DEST_STAGE, :S2, :S, :V$LEVEL_ID, :V$GUP_ID, :M
    DO
    BEGIN
      TAG_NAME = 'gsubj:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'gsubj:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'gsubj:r:subject_name';
      VAL = S;
      SUSPEND;
      TAG_NAME = 'gsubj:r:name';
      VAL = S2;
      SUSPEND;
      TAG_NAME = 'gsubj:r:stage_id';
      VAL = V$DEST_STAGE;
      SUSPEND;
      TAG_NAME = 'gsubj:r:level_id';
      VAL = V$LEVEL_ID;
      SUSPEND;
      -- Выбор идет не собственно по stage_id, а по маске - тут надо разделять уровни образования
      TAG_NAME = 'gsubj:r:stage_mask';
      VAL = M;
      SUSPEND;
      -- Если группа целиком из учеников одной ГУП, то и новых учеников предполагается брать оттуда же
      TAG_NAME = 'gsubj:r:gup_id';
      VAL = V$GUP_ID;
      SUSPEND;
    END

    TAG_NAME = 'reasons::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT LISTVAL_ID, VAL
      FROM LISTVALS_LIST(122)
      INTO :V$OBJ_ID, :S
    DO
    BEGIN
      TAG_NAME = 'reasons:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'reasons:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'reasons:r:value';
      VAL = S;
      SUSPEND;
    END
  END

  -- Специальное значение для экстерната
  TAG_NAME = 'reasons:r';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'reasons:r:id';
  VAL = 12905;
  SUSPEND;
  TAG_NAME = 'reasons:r:value';
  VAL = 'Принят на семейное обучение';
  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PRG3_ABSENCE_IMPORT (
    TEACHER_FIO VARCHAR(400),
    DATE_FROM DATE,
    DATE_TO DATE,
    REASON_TEXT VARCHAR(200))
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$PERSON_ID bigint;
declare variable V$REASON_ID bigint;
begin

  -- Пытаемся идентифицировать сотрудника
  TEACHER_FIO = REPLACE(TEACHER_FIO, ' ', '');

  SELECT FIRST 1 L14.OBJ_ID
  FROM LINKS L14
  JOIN VALS V59 ON V59.OBJ_ID = L14.OBJ_ID AND V59.PARAM_ID = 59 AND V59.IS_DEL = 0
  JOIN VALS V60 ON V60.OBJ_ID = L14.OBJ_ID AND V60.PARAM_ID = 60 AND V60.IS_DEL = 0
  LEFT JOIN VALS V61 ON V61.OBJ_ID = L14.OBJ_ID AND V61.PARAM_ID = 61 AND V61.IS_DEL = 0
  WHERE L14.OBJ_TYPE_ID = 14 AND L14.PARENT_TYPE_ID IN (2, 211) AND L14.DATE_DEL IS NULL
      AND UPPER(V59.VAL || V60.VAL || COALESCE(V61.VAL, '')) = UPPER(:TEACHER_FIO)
  INTO :V$PERSON_ID;

  IF(V$PERSON_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Сотрудник ' || TEACHER_FIO || ' не идентифицирован';

  -- Причина
  SELECT LV.LISTVAL_ID
  FROM LISTVALS LV
  JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU' AND UPPER(R.VAL) = UPPER(:REASON_TEXT)
  WHERE LV.LIST_ID = 317 AND LV.IS_DEL = 0
  INTO :V$REASON_ID;

  IF(V$REASON_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Неизвестная причина отсутствия';

  --
  SELECT FIRST 1 OBJ_ID
  FROM CJ2_REPL_PLAN
  WHERE PERSON_ID = :V$PERSON_ID AND REASON_ID = :V$REASON_ID AND DATE_DEL IS NULL AND DATE_FROM = :DATE_FROM
  INTO :OBJ_ID;

  IF(OBJ_ID IS NULL) THEN
  BEGIN

      INSERT INTO CJ2_REPL_PLAN
      (PERSON_ID, REASON_ID, DATE_FROM, DATE_TO)
      VALUES (:V$PERSON_ID, :V$REASON_ID, :DATE_FROM, :DATE_TO)
      RETURNING OBJ_ID INTO :OBJ_ID;

  END
  ELSE
  BEGIN

      UPDATE CJ2_REPL_PLAN
      SET DATE_TO = :DATE_TO
      WHERE OBJ_ID = :OBJ_ID;

  END

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PRG_PLAN_CMP_TYPES (
    OBJ_ID BIGINT)
RETURNS (
    LISTVAL_ID BIGINT,
    PARENT_ID BIGINT,
    VAL VARCHAR(4000),
    VAL_LONG VARCHAR(4000))
AS
declare variable V$OU_LICENCE_TYPE varchar(1);
declare variable STD_NUM bigint;
declare variable FILTER_S varchar(100);
declare variable APPLY smallint;
declare variable IS_VD bigint;
begin
  -- Получаем номер образовательного стандарта для данного УП (по-умолчанию используем 1), а также признак внеурочки
  SELECT V2478.LISTVAL_ID, V2545.LISTVAL_ID
  FROM LINKS LP50
  LEFT JOIN VALL V2478 ON V2478.OBJ_ID = LP50.PARENT_ID AND V2478.PARAM_ID = 2478 AND V2478.IS_DEL = 0
  LEFT JOIN VALL V2545 ON V2545.OBJ_ID = LP50.PARENT_ID AND V2545.PARAM_ID = 2545 AND V2545.IS_DEL = 0
  WHERE LP50.PARENT_TYPE_ID = 50 AND LP50.OBJ_ID = :OBJ_ID AND LP50.DATE_DEL is null
  INTO :STD_NUM, :IS_VD;

  IF(STD_NUM IS NULL) THEN STD_NUM = 11720;
  IF(IS_VD IS NULL) THEN IS_VD = 3;

  -- Получаем тип лицензии
  SELECT STATUS FROM OU_LICENCE_TYPE INTO :V$OU_LICENCE_TYPE;

  IF(V$OU_LICENCE_TYPE = 'D') THEN FILTER_S = '%DOU%';
  ELSE IF(V$OU_LICENCE_TYPE = 'O') THEN FILTER_S = '%GOU%';
  ELSE IF(V$OU_LICENCE_TYPE = 'C') THEN FILTER_S = '%COLLEGE%';
  ELSE IF(V$OU_LICENCE_TYPE = 'U') THEN FILTER_S = '%UDOD%';

  FOR
    SELECT L.LISTVAL_ID, L.PARENT_ID, R.VAL, R.VAL_LONG
    FROM LISTVALS L
    JOIN RES R ON R.RES_ID = L.RES_ID AND R.LANG_CODE = 'RU' AND R.IS_DEL = 0
    WHERE L.LIST_ID = 116 AND L.IS_DEL = 0 AND L."FILTER" SIMILAR TO :FILTER_S
    INTO :LISTVAL_ID, :PARENT_ID, :VAL, :VAL_LONG
  DO
  BEGIN
    APPLY = 1;
    IF(STD_NUM = 11720) THEN
    BEGIN
      -- Тип 1 или по-умолчанию
      IF(LISTVAL_ID NOT IN (780, 781, 782)) THEN APPLY = 0;
    END
    ELSE
    BEGIN
      -- Тип 2
      IF(LISTVAL_ID IN (780, 781, 782)) THEN APPLY = 0;
    END
    -- Для ВД разрешаем только вариативную часть
    IF(IS_VD = 2 AND LISTVAL_ID <> 12753) THEN APPLY = 0;
    IF(APPLY > 0) THEN SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PROCEDURES_EXPORT (
    I$CONTENT SMALLINT = 1)
RETURNS (
    VAL VARCHAR(4000) CHARACTER SET WIN1251)
AS
DECLARE VARIABLE S VARCHAR(80);
DECLARE VARIABLE I SMALLINT;
DECLARE VARIABLE Q SMALLINT;
begin
  FOR
    SELECT P.RDB$PROCEDURE_NAME, P.RDB$PROCEDURE_ID, P.RDB$PROCEDURE_OUTPUTS
    FROM RDB$PROCEDURES P
    WHERE P.RDB$SYSTEM_FLAG = 0
    ORDER BY 1
    INTO :S, :I, :Q
  DO
  BEGIN
    VAL = 'CREATE OR ALTER PROCEDURE ' || TRIM(S);
    IF(I > 0) THEN
    BEGIN
      VAL = VAL || ' (';
      VAL = VAL || ')';
    END
    IF(Q > 0) THEN
    BEGIN
      VAL = VAL || ' RETURNS (';
      VAL = VAL || ')';
    END
    IF(I$CONTENT = 0) THEN
    BEGIN
      VAL = VAL || ' AS BEGIN';
      IF(Q > 0) THEN VAL = VAL || 'SUSPEND;';
      VAL = VAL || ' END ^';
      SUSPEND;
    END
    ELSE
    BEGIN
      VAL = VAL || ' AS';
      SUSPEND;
      SELECT P.RDB$PROCEDURE_SOURCE
      FROM RDB$PROCEDURES P
      WHERE P.RDB$PROCEDURE_NAME = :S
      INTO :VAL;
      SUSPEND;
      VAL = 'END ^';
      SUSPEND;
    END
  END
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PROCESS_VERIFY (
    I$OBJ_ID BIGINT)
AS
declare variable V$ROOT_ID bigint;
declare variable V$ROW_ID bigint;
declare variable V$PARAM_ID bigint;
declare variable V$TYPE_ID bigint;
declare variable V$PATH bigint;
declare variable V$ACTIVE bigint;
declare variable V$PARAMTYPE smallint;
declare variable V$FLT varchar(1000);
declare variable V$OU_ID bigint;
declare variable V$GEN bigint;
declare variable V$LV bigint;
declare variable V$N1 bigint;
declare variable V$N2 bigint;
declare variable V$C1 integer;
declare variable V$C2 integer;
declare variable V$OBJ_ID bigint;
declare variable V$ACT bigint;
declare variable V$ROOT_TYPE bigint;
begin

  SELECT FIRST 1 L.OBJ_ID
  FROM LINKS L
  WHERE L.PARENT_ID IS NULL AND L.OBJ_TYPE_ID IN (111, 112) AND L.DATE_DEL IS NULL
  INTO :V$ROOT_ID;

  -- Перерасчет по региону
  IF(I$OBJ_ID = V$ROOT_ID) THEN I$OBJ_ID = NULL;

  SELECT MULTIPLIER
  FROM GEN
  INTO :V$GEN;

  FOR
    SELECT DISTINCT L2.OBJ_ID
    FROM LINKS L2
    WHERE L2.PARENT_TYPE_ID IN (111, 112) AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      AND (:I$OBJ_ID IS NULL OR L2.PARENT_ID = :I$OBJ_ID)
    ORDER BY 1
    INTO :V$OU_ID
  DO
  BEGIN
    UPDATE VERIFY_VALS
    SET CNT = 0, FCNT = 0
    WHERE OBJ_ID = :V$OU_ID AND (COALESCE(CNT, 0) <> 0 OR COALESCE(FCNT, 0) <> 0);
  END

  FOR
    SELECT L498.OBJ_ID, V3449.VAL, V3453.VAL, P.PARAM_TYPE, V3468.LISTVAL_ID, V3454.LISTVAL_ID, V3455.VAL
    FROM LINKS L498
    JOIN VALI V3449 ON V3449.OBJ_ID = L498.OBJ_ID AND V3449.PARAM_ID = 3449 AND V3449.IS_DEL = 0
    JOIN VALI V3453 ON V3453.OBJ_ID = L498.OBJ_ID AND V3453.PARAM_ID = 3453 AND V3453.IS_DEL = 0
    JOIN VALL V3468 ON V3468.OBJ_ID = L498.OBJ_ID AND V3468.PARAM_ID = 3468 AND V3468.IS_DEL = 0
    JOIN VALL V3454 ON V3454.OBJ_ID = L498.OBJ_ID AND V3454.PARAM_ID = 3454 AND V3454.IS_DEL = 0 AND V3454.LISTVAL_ID <> 15821 -- не отключена
    JOIN PARAMS P ON P.PARAM_ID = V3449.VAL
    LEFT JOIN VALS V3455 ON V3455.OBJ_ID = L498.OBJ_ID AND V3455.PARAM_ID = 3455 AND V3455.IS_DEL = 0 -- фильтр - опционально
    WHERE L498.PARENT_ID = :V$ROOT_ID AND L498.OBJ_TYPE_ID = 498 AND L498.DATE_DEL IS NULL
    INTO :V$ROW_ID, :V$PARAM_ID, :V$TYPE_ID, :V$PARAMTYPE, :V$PATH, :V$ACTIVE, :V$FLT
  DO
  BEGIN

    -- Идем по ОУ
    FOR
      SELECT DISTINCT L2.OBJ_ID
      FROM LINKS L2
      WHERE L2.PARENT_TYPE_ID IN (111, 112) AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
        AND (:I$OBJ_ID IS NULL OR L2.PARENT_ID = :I$OBJ_ID)
      ORDER BY 1
      INTO :V$OU_ID
    DO
    BEGIN

      V$N1 = V$OU_ID / V$GEN;
      V$N2 = (V$N1 + 1) * V$GEN;
      V$N1 = V$N1 * V$GEN;
      V$ROOT_TYPE = NULL;

      IF(V$ACTIVE <> 15821) THEN
      BEGIN
        IF(V$PARAMTYPE = 6 AND V$FLT IS NOT NULL) THEN
        BEGIN
          -- Отдельная ветка на EXISTS(LISTVAL_ID), общий счетчик нас будет интересовать только в особых случаях
          -- Подсчет идет по родительским сущностям !
          -- Например, наличие документа ОУ конкретного типа; наличие паспорта; наличие свидетельства о рождении
          V$LV = V$FLT;
          V$C1 = 0;
          V$C2 = 0;

          -- Выборка обучающихся - выбираем все типы обучающихся
          IF(V$PATH IN (14550, 14551, 15815)) THEN V$ROOT_TYPE = NULL;
          ELSE IF(V$PATH IN (15816, 15817, 15818)) THEN V$ROOT_TYPE = 14;
          ELSE IF(V$PATH IN (15824, 15825, 15826)) THEN V$ROOT_TYPE = 20;
          ELSE IF(V$TYPE_ID = 17) THEN V$ROOT_TYPE = 2;
          ELSE V$ROOT_TYPE = 2; -- !!!

          FOR
            SELECT L.OBJ_ID
            FROM PROCESS_VERIFY_OBJ(:V$OU_ID, :V$N1, :V$N2, :V$ROOT_TYPE, :V$PATH) L
            LEFT JOIN PROCESS_VERIFY_SUBFLT(L.TYPE_ID, L.OBJ_ID, NULL, NULL, :V$PARAM_ID, :V$LV) SF ON 1 = 1
            WHERE SF.IS_MATCH = 1
            INTO :V$OBJ_ID
          DO
          BEGIN
            V$C1 = V$C1 + 1;
            IF(NOT EXISTS(
              SELECT FIRST 1 1
              FROM LINKS LC
              JOIN VALL V ON V.OBJ_ID = LC.OBJ_ID AND V.PARAM_ID = :V$PARAM_ID AND V.IS_DEL = 0 AND V.LISTVAL_ID = :V$LV
              WHERE LC.PARENT_ID = :V$OBJ_ID AND LC.OBJ_TYPE_ID = :V$TYPE_ID AND LC.DATE_DEL IS NULL
            ))
            THEN
              V$C2 = V$C2 + 1;
          END
        END
        ELSE
        BEGIN
          V$C1 = 0;
          V$C2 = 0;

          IF(V$FLT IS NULL) THEN
          BEGIN
            -- Фильтра нет, проверяем просто незаполненность поля
            SELECT COUNT(*), SUM(IIF(V.IS_EXISTS = 1, 0, 1))
            FROM PROCESS_VERIFY_OBJ(:V$OU_ID, :V$N1, :V$N2, :V$TYPE_ID, :V$PATH) L
            LEFT JOIN VAL_GET(L.OBJ_ID, :V$PARAM_ID) V ON 1 = 1
            INTO :V$C1, :V$C2;

            V$C2 = COALESCE(V$C2, 0);
          END
          ELSE
          BEGIN
          END
        END

        -- Для полей самой ОООД показываем не проценты, а да/нет
        IF(V$TYPE_ID = 2 OR V$ROOT_TYPE = 2) THEN V$C1 = NULL;

        UPDATE OR INSERT INTO VERIFY_VALS
        (OBJ_ID, PARAM_ID, CNT, FCNT)
        VALUES (:V$OU_ID, :V$ROW_ID, :V$C1, :V$C2)
        MATCHING (OBJ_ID, PARAM_ID);

      END -- ACTIVE

    END

  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PROCESS_VERIFY_OBJ (
    I$OU_ID BIGINT,
    I$FROM_ID BIGINT,
    I$TO_ID BIGINT,
    I$TYPE_ID BIGINT,
    I$PATH BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    TYPE_ID BIGINT)
AS
begin

  -- Выборка с конкретизацией по персонам - может быть по самим персонам, либо по подчиненным объектам персон
  -- TYPE_ID может быть указан NULL чтобы выбрать всех обучающихся (только первые три ветки PATH)
  -- только для основной ветки, где выбираются сами обучающиеся

  IF(I$PATH = 14550) THEN
  BEGIN
    -- Действующие обучающиеся
    IF(I$TYPE_ID IN (10, 126)) THEN
    BEGIN
      FOR
        SELECT DISTINCT OBJ_ID, OBJ_TYPE_ID
        FROM (
          -- классы
          SELECT LX.OBJ_ID, LX.OBJ_TYPE_ID
          FROM LINKS L7
          JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
          JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 187, 125) AND L9.DATE_DEL IS NULL
          JOIN LINKS LX ON LX.PARENT_ID = L9.OBJ_ID AND LX.DATE_DEL IS NULL
            AND ((:I$TYPE_ID IS NOT NULL AND LX.OBJ_TYPE_ID = :I$TYPE_ID) OR (:I$TYPE_ID IS NULL AND LX.OBJ_TYPE_ID IN (10, 126)))
          WHERE L7.PARENT_ID = :I$OU_ID AND L7.OBJ_TYPE_ID IN (7, 502) AND L7.DATE_DEL IS NULL
          -- предварительный прием
          UNION
          SELECT LX.OBJ_ID, LX.OBJ_TYPE_ID
          FROM LINKS L77
          JOIN LINKS L290 ON L290.PARENT_ID = L77.OBJ_ID AND L290.OBJ_TYPE_ID = 290 AND L290.DATE_DEL IS NULL
          JOIN LINKS LX ON LX.PARENT_ID = L290.OBJ_ID AND LX.DATE_DEL IS NULL
            AND ((:I$TYPE_ID IS NOT NULL AND LX.OBJ_TYPE_ID = :I$TYPE_ID) OR (:I$TYPE_ID IS NULL AND LX.OBJ_TYPE_ID IN (10, 126)))
          WHERE L77.PARENT_ID = :I$OU_ID AND L77.OBJ_TYPE_ID = 77 AND L77.DATE_DEL IS NULL
        )
        INTO :OBJ_ID, :TYPE_ID
      DO
        SUSPEND;
    END
    ELSE
    BEGIN
      FOR
        SELECT DISTINCT OBJ_ID, OBJ_TYPE_ID
        FROM (
          -- классы
          SELECT LX.OBJ_ID, LX.OBJ_TYPE_ID
          FROM LINKS L7
          JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
          JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 187, 125) AND L9.DATE_DEL IS NULL
          JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID IN (10, 126) AND L10.DATE_DEL IS NULL
          JOIN LINKS LX ON LX.PARENT_ID = L10.OBJ_ID AND LX.OBJ_TYPE_ID = :I$TYPE_ID AND LX.DATE_DEL IS NULL
          WHERE L7.PARENT_ID = :I$OU_ID AND L7.OBJ_TYPE_ID IN (7, 502) AND L7.DATE_DEL IS NULL
          -- предварительный прием
          UNION
          SELECT LX.OBJ_ID, LX.OBJ_TYPE_ID
          FROM LINKS L77
          JOIN LINKS L290 ON L290.PARENT_ID = L77.OBJ_ID AND L290.OBJ_TYPE_ID = 290 AND L290.DATE_DEL IS NULL
          JOIN LINKS L10 ON L10.PARENT_ID = L290.OBJ_ID AND L10.OBJ_TYPE_ID IN (10, 126) AND L10.DATE_DEL IS NULL
          JOIN LINKS LX ON LX.PARENT_ID = L10.OBJ_ID AND LX.OBJ_TYPE_ID = :I$TYPE_ID AND LX.DATE_DEL IS NULL
          WHERE L77.PARENT_ID = :I$OU_ID AND L77.OBJ_TYPE_ID = 77 AND L77.DATE_DEL IS NULL
        )
        INTO :OBJ_ID, :TYPE_ID
      DO
        SUSPEND;
    END
  END
  ELSE IF(I$PATH = 14551) THEN
  BEGIN
    -- Не действующие обучающиеся
    IF(I$TYPE_ID IN (10, 126)) THEN
    BEGIN
      FOR
        SELECT DISTINCT LX.OBJ_ID, LX.OBJ_TYPE_ID
        FROM LINKS L78
        JOIN LINKS L8X ON L8X.PARENT_ID = L78.OBJ_ID AND L8X.OBJ_TYPE_ID IN (81, 82, 83) AND L8X.DATE_DEL IS NULL
        JOIN LINKS LX ON LX.PARENT_ID = L8X.OBJ_ID AND LX.DATE_DEL IS NULL
          AND ((:I$TYPE_ID IS NOT NULL AND LX.OBJ_TYPE_ID = :I$TYPE_ID) OR (:I$TYPE_ID IS NULL AND LX.OBJ_TYPE_ID IN (10, 126)))
        WHERE L78.PARENT_ID = :I$OU_ID AND L78.OBJ_TYPE_ID = 78 AND L78.DATE_DEL IS NULL
        INTO :OBJ_ID, :TYPE_ID
      DO
        SUSPEND;
    END
    ELSE
    BEGIN
      FOR
        SELECT DISTINCT LX.OBJ_ID, LX.OBJ_TYPE_ID
        FROM LINKS L78
        JOIN LINKS L8X ON L8X.PARENT_ID = L78.OBJ_ID AND L8X.OBJ_TYPE_ID IN (81, 82, 83) AND L8X.DATE_DEL IS NULL
        JOIN LINKS L10 ON L10.PARENT_ID = L8X.OBJ_ID AND L10.OBJ_TYPE_ID IN (10, 126) AND L10.DATE_DEL IS NULL
        JOIN LINKS LX ON LX.PARENT_ID = L10.OBJ_ID AND LX.OBJ_TYPE_ID = :I$TYPE_ID AND LX.DATE_DEL IS NULL
        WHERE L78.PARENT_ID = :I$OU_ID AND L78.OBJ_TYPE_ID = 78 AND L78.DATE_DEL IS NULL
        INTO :OBJ_ID, :TYPE_ID
      DO
        SUSPEND;
    END
  END
  ELSE IF(I$PATH = 15815) THEN
  BEGIN
    -- Все обучающиеся
    IF(I$TYPE_ID IN (10, 126)) THEN
    BEGIN
      FOR
        SELECT DISTINCT OBJ_ID, OBJ_TYPE_ID
        FROM (
          -- классы
          SELECT LX.OBJ_ID, LX.OBJ_TYPE_ID
          FROM LINKS L7
          JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
          JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 187, 125) AND L9.DATE_DEL IS NULL
          JOIN LINKS LX ON LX.PARENT_ID = L9.OBJ_ID AND LX.DATE_DEL IS NULL
            AND ((:I$TYPE_ID IS NOT NULL AND LX.OBJ_TYPE_ID = :I$TYPE_ID) OR (:I$TYPE_ID IS NULL AND LX.OBJ_TYPE_ID IN (10, 126)))
          WHERE L7.PARENT_ID = :I$OU_ID AND L7.OBJ_TYPE_ID IN (7, 502) AND L7.DATE_DEL IS NULL
          -- предварительный прием
          UNION
          SELECT LX.OBJ_ID, LX.OBJ_TYPE_ID
          FROM LINKS L77
          JOIN LINKS L290 ON L290.PARENT_ID = L77.OBJ_ID AND L290.OBJ_TYPE_ID = 290 AND L290.DATE_DEL IS NULL
          JOIN LINKS LX ON LX.PARENT_ID = L290.OBJ_ID AND LX.DATE_DEL IS NULL
            AND ((:I$TYPE_ID IS NOT NULL AND LX.OBJ_TYPE_ID = :I$TYPE_ID) OR (:I$TYPE_ID IS NULL AND LX.OBJ_TYPE_ID IN (10, 126)))
          WHERE L77.PARENT_ID = :I$OU_ID AND L77.OBJ_TYPE_ID = 77 AND L77.DATE_DEL IS NULL
          -- выбывшие
          UNION
          SELECT LX.OBJ_ID, LX.OBJ_TYPE_ID
          FROM LINKS L78
          JOIN LINKS L8X ON L8X.PARENT_ID = L78.OBJ_ID AND L8X.OBJ_TYPE_ID IN (81, 82, 83) AND L8X.DATE_DEL IS NULL
          JOIN LINKS LX ON LX.PARENT_ID = L8X.OBJ_ID AND LX.DATE_DEL IS NULL
            AND ((:I$TYPE_ID IS NOT NULL AND LX.OBJ_TYPE_ID = :I$TYPE_ID) OR (:I$TYPE_ID IS NULL AND LX.OBJ_TYPE_ID IN (10, 126)))
          WHERE L78.PARENT_ID = :I$OU_ID AND L78.OBJ_TYPE_ID = 78 AND L78.DATE_DEL IS NULL
        )
        INTO :OBJ_ID, :TYPE_ID
      DO
        SUSPEND;
    END
    ELSE
    BEGIN
      FOR
        SELECT DISTINCT OBJ_ID, OBJ_TYPE_ID
        FROM (
          -- классы
          SELECT LX.OBJ_ID, LX.OBJ_TYPE_ID
          FROM LINKS L7
          JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
          JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 187, 125) AND L9.DATE_DEL IS NULL
          JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID IN (10, 126) AND L10.DATE_DEL IS NULL
          JOIN LINKS LX ON LX.PARENT_ID = L10.OBJ_ID AND LX.OBJ_TYPE_ID = :I$TYPE_ID AND LX.DATE_DEL IS NULL
          WHERE L7.PARENT_ID = :I$OU_ID AND L7.OBJ_TYPE_ID IN (7, 502) AND L7.DATE_DEL IS NULL
          -- предварительный прием
          UNION
          SELECT LX.OBJ_ID, LX.OBJ_TYPE_ID
          FROM LINKS L77
          JOIN LINKS L290 ON L290.PARENT_ID = L77.OBJ_ID AND L290.OBJ_TYPE_ID = 290 AND L290.DATE_DEL IS NULL
          JOIN LINKS L10 ON L10.PARENT_ID = L290.OBJ_ID AND L10.OBJ_TYPE_ID IN (10, 126) AND L10.DATE_DEL IS NULL
          JOIN LINKS LX ON LX.PARENT_ID = L10.OBJ_ID AND LX.OBJ_TYPE_ID = :I$TYPE_ID AND LX.DATE_DEL IS NULL
          WHERE L77.PARENT_ID = :I$OU_ID AND L77.OBJ_TYPE_ID = 77 AND L77.DATE_DEL IS NULL
          -- выбывшие
          UNION
          SELECT LX.OBJ_ID, LX.OBJ_TYPE_ID
          FROM LINKS L78
          JOIN LINKS L8X ON L8X.PARENT_ID = L78.OBJ_ID AND L8X.OBJ_TYPE_ID IN (81, 82, 83) AND L8X.DATE_DEL IS NULL
          JOIN LINKS L10 ON L10.PARENT_ID = L8X.OBJ_ID AND L10.OBJ_TYPE_ID IN (10, 126) AND L10.DATE_DEL IS NULL
          JOIN LINKS LX ON LX.PARENT_ID = L10.OBJ_ID AND LX.OBJ_TYPE_ID = :I$TYPE_ID AND LX.DATE_DEL IS NULL
          WHERE L78.PARENT_ID = :I$OU_ID AND L78.OBJ_TYPE_ID = 78 AND L78.DATE_DEL IS NULL
        )
        INTO :OBJ_ID, :TYPE_ID
      DO
        SUSPEND;
    END
  END
  ELSE IF(I$PATH = 15816) THEN
  BEGIN
    -- Действующие сотрудники
    IF(I$TYPE_ID = 14) THEN
    BEGIN
      FOR
        SELECT DISTINCT OBJ_ID, OBJ_TYPE_ID
        FROM (
          SELECT LX.OBJ_ID, LX.OBJ_TYPE_ID
          FROM LINKS LX
          WHERE LX.PARENT_ID = :I$OU_ID AND LX.OBJ_TYPE_ID = :I$TYPE_ID AND LX.DATE_DEL IS NULL
          -- подразделения
          UNION
          SELECT LX.OBJ_ID, LX.OBJ_TYPE_ID
          FROM LINKS L211
          JOIN LINKS LX ON LX.PARENT_ID = L211.OBJ_ID AND LX.OBJ_TYPE_ID = :I$TYPE_ID AND LX.DATE_DEL IS NULL
          WHERE L211.PARENT_ID = :I$OU_ID AND L211.OBJ_TYPE_ID = 211 AND L211.DATE_DEL IS NULL
        )
        INTO :OBJ_ID, :TYPE_ID
      DO
        SUSPEND;
    END
    ELSE
    BEGIN
      FOR
        SELECT DISTINCT OBJ_ID, OBJ_TYPE_ID
        FROM (
          SELECT LX.OBJ_ID, LX.OBJ_TYPE_ID
          FROM LINKS L14
          JOIN LINKS LX ON LX.PARENT_ID = L14.OBJ_ID AND LX.OBJ_TYPE_ID = :I$TYPE_ID AND LX.DATE_DEL IS NULL
          WHERE L14.PARENT_ID = :I$OU_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
          -- подразделения
          UNION
          SELECT LX.OBJ_ID, LX.OBJ_TYPE_ID
          FROM LINKS L211
          JOIN LINKS L14 ON L14.PARENT_ID = L211.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
          JOIN LINKS LX ON LX.PARENT_ID = L14.OBJ_ID AND LX.OBJ_TYPE_ID = :I$TYPE_ID AND LX.DATE_DEL IS NULL
          WHERE L211.PARENT_ID = :I$OU_ID AND L211.OBJ_TYPE_ID = 211 AND L211.DATE_DEL IS NULL
        )
        INTO :OBJ_ID, :TYPE_ID
      DO
        SUSPEND;
    END
  END
  ELSE IF(I$PATH = 15817) THEN
  BEGIN
    -- Не действующие сотрудники
    IF(I$TYPE_ID = 14) THEN
    BEGIN
      FOR
        SELECT DISTINCT LX.OBJ_ID, LX.OBJ_TYPE_ID
        FROM LINKS L84
        JOIN LINKS LX ON LX.PARENT_ID = L84.OBJ_ID AND LX.OBJ_TYPE_ID = :I$TYPE_ID AND LX.DATE_DEL IS NULL
        WHERE L84.PARENT_ID = :I$OU_ID AND L84.OBJ_TYPE_ID = 84 AND L84.DATE_DEL IS NULL
        INTO :OBJ_ID, :TYPE_ID
      DO
        SUSPEND;
    END
    ELSE
    BEGIN
      FOR
        SELECT DISTINCT LX.OBJ_ID, LX.OBJ_TYPE_ID
        FROM LINKS L84
        JOIN LINKS L14 ON L14.PARENT_ID = L84.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
        JOIN LINKS LX ON LX.PARENT_ID = L14.OBJ_ID AND LX.OBJ_TYPE_ID = :I$TYPE_ID AND LX.DATE_DEL IS NULL
        WHERE L84.PARENT_ID = :I$OU_ID AND L84.OBJ_TYPE_ID = 84 AND L84.DATE_DEL IS NULL
        INTO :OBJ_ID, :TYPE_ID
      DO
        SUSPEND;
    END
  END
  ELSE IF(I$PATH = 15818) THEN
  BEGIN
    -- Все сотрудники
    IF(I$TYPE_ID = 14) THEN
    BEGIN
      FOR
        SELECT DISTINCT OBJ_ID, OBJ_TYPE_ID
        FROM (
          SELECT LX.OBJ_ID, LX.OBJ_TYPE_ID
          FROM LINKS LX
          WHERE LX.PARENT_ID = :I$OU_ID AND LX.OBJ_TYPE_ID = :I$TYPE_ID AND LX.DATE_DEL IS NULL
          -- подразделения
          UNION
          SELECT LX.OBJ_ID, LX.OBJ_TYPE_ID
          FROM LINKS L211
          JOIN LINKS LX ON LX.PARENT_ID = L211.OBJ_ID AND LX.OBJ_TYPE_ID = :I$TYPE_ID AND LX.DATE_DEL IS NULL
          WHERE L211.PARENT_ID = :I$OU_ID AND L211.OBJ_TYPE_ID = 211 AND L211.DATE_DEL IS NULL
          -- уволенные
          UNION
          SELECT LX.OBJ_ID, LX.OBJ_TYPE_ID
          FROM LINKS L84
          JOIN LINKS LX ON LX.PARENT_ID = L84.OBJ_ID AND LX.OBJ_TYPE_ID = :I$TYPE_ID AND LX.DATE_DEL IS NULL
          WHERE L84.PARENT_ID = :I$OU_ID AND L84.OBJ_TYPE_ID = 84 AND L84.DATE_DEL IS NULL
        )
        INTO :OBJ_ID, :TYPE_ID
      DO
        SUSPEND;
    END
    ELSE
    BEGIN
      FOR
        SELECT DISTINCT OBJ_ID, OBJ_TYPE_ID
        FROM (
          SELECT LX.OBJ_ID, LX.OBJ_TYPE_ID
          FROM LINKS L14
          JOIN LINKS LX ON LX.PARENT_ID = L14.OBJ_ID AND LX.OBJ_TYPE_ID = :I$TYPE_ID AND LX.DATE_DEL IS NULL
          WHERE L14.PARENT_ID = :I$OU_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
          -- подразделения
          UNION
          SELECT LX.OBJ_ID, LX.OBJ_TYPE_ID
          FROM LINKS L211
          JOIN LINKS L14 ON L14.PARENT_ID = L211.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
          JOIN LINKS LX ON LX.PARENT_ID = L14.OBJ_ID AND LX.OBJ_TYPE_ID = :I$TYPE_ID AND LX.DATE_DEL IS NULL
          WHERE L211.PARENT_ID = :I$OU_ID AND L211.OBJ_TYPE_ID = 211 AND L211.DATE_DEL IS NULL
          -- уволенные
          UNION
          SELECT LX.OBJ_ID, LX.OBJ_TYPE_ID
          FROM LINKS L84
          JOIN LINKS L14 ON L14.PARENT_ID = L84.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
          JOIN LINKS LX ON LX.PARENT_ID = L14.OBJ_ID AND LX.OBJ_TYPE_ID = :I$TYPE_ID AND LX.DATE_DEL IS NULL
          WHERE L84.PARENT_ID = :I$OU_ID AND L84.OBJ_TYPE_ID = 84 AND L84.DATE_DEL IS NULL
        )
        INTO :OBJ_ID, :TYPE_ID
      DO
        SUSPEND;
    END
  END
  ELSE IF(I$PATH = 15824) THEN
  BEGIN
    -- Родители действующих
    IF(I$TYPE_ID = 20) THEN
    BEGIN
      FOR
        SELECT DISTINCT OBJ_ID, OBJ_TYPE_ID
        FROM (
          -- классы
          SELECT LX.OBJ_ID, LX.OBJ_TYPE_ID
          FROM LINKS L7
          JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
          JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 187, 125) AND L9.DATE_DEL IS NULL
          JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
          JOIN LINKS LX ON LX.PARENT_ID = L10.OBJ_ID AND LX.OBJ_TYPE_ID = :I$TYPE_ID AND LX.DATE_DEL IS NULL
          WHERE L7.PARENT_ID = :I$OU_ID AND L7.OBJ_TYPE_ID IN (7, 502) AND L7.DATE_DEL IS NULL
          -- предварительный прием
          UNION
          SELECT LX.OBJ_ID, LX.OBJ_TYPE_ID
          FROM LINKS L77
          JOIN LINKS L290 ON L290.PARENT_ID = L77.OBJ_ID AND L290.OBJ_TYPE_ID = 290 AND L290.DATE_DEL IS NULL
          JOIN LINKS L10 ON L10.PARENT_ID = L290.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
          JOIN LINKS LX ON LX.PARENT_ID = L10.OBJ_ID AND LX.OBJ_TYPE_ID = :I$TYPE_ID AND LX.DATE_DEL IS NULL
          WHERE L77.PARENT_ID = :I$OU_ID AND L77.OBJ_TYPE_ID = 77 AND L77.DATE_DEL IS NULL
        )
        INTO :OBJ_ID, :TYPE_ID
      DO
        SUSPEND;
    END
    ELSE
    BEGIN
      FOR
        SELECT DISTINCT OBJ_ID, OBJ_TYPE_ID
        FROM (
          -- классы
          SELECT LX.OBJ_ID, LX.OBJ_TYPE_ID
          FROM LINKS L7
          JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
          JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 187, 125) AND L9.DATE_DEL IS NULL
          JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
          JOIN LINKS L20 ON L20.PARENT_ID = L10.OBJ_ID AND L20.OBJ_TYPE_ID = 20 AND L20.DATE_DEL IS NULL
          JOIN LINKS LX ON LX.PARENT_ID = L20.OBJ_ID AND LX.OBJ_TYPE_ID = :I$TYPE_ID AND LX.DATE_DEL IS NULL
          WHERE L7.PARENT_ID = :I$OU_ID AND L7.OBJ_TYPE_ID IN (7, 502) AND L7.DATE_DEL IS NULL
          -- предварительный прием
          UNION
          SELECT LX.OBJ_ID, LX.OBJ_TYPE_ID
          FROM LINKS L77
          JOIN LINKS L290 ON L290.PARENT_ID = L77.OBJ_ID AND L290.OBJ_TYPE_ID = 290 AND L290.DATE_DEL IS NULL
          JOIN LINKS L10 ON L10.PARENT_ID = L290.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
          JOIN LINKS L20 ON L20.PARENT_ID = L10.OBJ_ID AND L20.OBJ_TYPE_ID = 20 AND L20.DATE_DEL IS NULL
          JOIN LINKS LX ON LX.PARENT_ID = L20.OBJ_ID AND LX.OBJ_TYPE_ID = :I$TYPE_ID AND LX.DATE_DEL IS NULL
          WHERE L77.PARENT_ID = :I$OU_ID AND L77.OBJ_TYPE_ID = 77 AND L77.DATE_DEL IS NULL
        )
        INTO :OBJ_ID, :TYPE_ID
      DO
        SUSPEND;
    END
  END
  ELSE IF(I$PATH = 15825) THEN
  BEGIN
    -- Родители выбывших
    IF(I$TYPE_ID = 20) THEN
    BEGIN
      FOR
        SELECT DISTINCT LX.OBJ_ID, LX.OBJ_TYPE_ID
        FROM LINKS L78
        JOIN LINKS L8X ON L8X.PARENT_ID = L78.OBJ_ID AND L8X.OBJ_TYPE_ID IN (81, 82, 83) AND L8X.DATE_DEL IS NULL
        JOIN LINKS L10 ON L10.PARENT_ID = L8X.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        JOIN LINKS LX ON LX.PARENT_ID = L10.OBJ_ID AND LX.OBJ_TYPE_ID = :I$TYPE_ID AND LX.DATE_DEL IS NULL
        WHERE L78.PARENT_ID = :I$OU_ID AND L78.OBJ_TYPE_ID = 78 AND L78.DATE_DEL IS NULL
        INTO :OBJ_ID, :TYPE_ID
      DO
        SUSPEND;
    END
    ELSE
    BEGIN
      FOR
        SELECT DISTINCT LX.OBJ_ID, LX.OBJ_TYPE_ID
        FROM LINKS L78
        JOIN LINKS L8X ON L8X.PARENT_ID = L78.OBJ_ID AND L8X.OBJ_TYPE_ID IN (81, 82, 83) AND L8X.DATE_DEL IS NULL
        JOIN LINKS L10 ON L10.PARENT_ID = L8X.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        JOIN LINKS L20 ON L20.PARENT_ID = L10.OBJ_ID AND L20.OBJ_TYPE_ID = 20 AND L20.DATE_DEL IS NULL
        JOIN LINKS LX ON LX.PARENT_ID = L20.OBJ_ID AND LX.OBJ_TYPE_ID = :I$TYPE_ID AND LX.DATE_DEL IS NULL
        WHERE L78.PARENT_ID = :I$OU_ID AND L78.OBJ_TYPE_ID = 78 AND L78.DATE_DEL IS NULL
        INTO :OBJ_ID, :TYPE_ID
      DO
        SUSPEND;
    END
  END
  ELSE IF(I$PATH = 15826) THEN
  BEGIN
    -- Родители все
    IF(I$TYPE_ID = 20) THEN
    BEGIN
      FOR
        SELECT DISTINCT OBJ_ID, OBJ_TYPE_ID
        FROM (
          -- классы
          SELECT LX.OBJ_ID, LX.OBJ_TYPE_ID
          FROM LINKS L7
          JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
          JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 187, 125) AND L9.DATE_DEL IS NULL
          JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
          JOIN LINKS LX ON LX.PARENT_ID = L10.OBJ_ID AND LX.OBJ_TYPE_ID = :I$TYPE_ID AND LX.DATE_DEL IS NULL
          WHERE L7.PARENT_ID = :I$OU_ID AND L7.OBJ_TYPE_ID IN (7, 502) AND L7.DATE_DEL IS NULL
          -- предварительный прием
          UNION
          SELECT LX.OBJ_ID, LX.OBJ_TYPE_ID
          FROM LINKS L77
          JOIN LINKS L290 ON L290.PARENT_ID = L77.OBJ_ID AND L290.OBJ_TYPE_ID = 290 AND L290.DATE_DEL IS NULL
          JOIN LINKS L10 ON L10.PARENT_ID = L290.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
          JOIN LINKS LX ON LX.PARENT_ID = L10.OBJ_ID AND LX.OBJ_TYPE_ID = :I$TYPE_ID AND LX.DATE_DEL IS NULL
          WHERE L77.PARENT_ID = :I$OU_ID AND L77.OBJ_TYPE_ID = 77 AND L77.DATE_DEL IS NULL
          -- выбывшие
          UNION
          SELECT LX.OBJ_ID, LX.OBJ_TYPE_ID
          FROM LINKS L78
          JOIN LINKS L8X ON L8X.PARENT_ID = L78.OBJ_ID AND L8X.OBJ_TYPE_ID IN (81, 82, 83) AND L8X.DATE_DEL IS NULL
          JOIN LINKS L10 ON L10.PARENT_ID = L8X.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
          JOIN LINKS LX ON LX.PARENT_ID = L10.OBJ_ID AND LX.OBJ_TYPE_ID = :I$TYPE_ID AND LX.DATE_DEL IS NULL
          WHERE L78.PARENT_ID = :I$OU_ID AND L78.OBJ_TYPE_ID = 78 AND L78.DATE_DEL IS NULL
        )
        INTO :OBJ_ID, :TYPE_ID
      DO
        SUSPEND;
    END
    ELSE
    BEGIN
      FOR
        SELECT DISTINCT OBJ_ID, OBJ_TYPE_ID
        FROM (
          -- классы
          SELECT LX.OBJ_ID, LX.OBJ_TYPE_ID
          FROM LINKS L7
          JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
          JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 187, 125) AND L9.DATE_DEL IS NULL
          JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
          JOIN LINKS L20 ON L20.PARENT_ID = L10.OBJ_ID AND L20.OBJ_TYPE_ID = 20 AND L20.DATE_DEL IS NULL
          JOIN LINKS LX ON LX.PARENT_ID = L20.OBJ_ID AND LX.OBJ_TYPE_ID = :I$TYPE_ID AND LX.DATE_DEL IS NULL
          WHERE L7.PARENT_ID = :I$OU_ID AND L7.OBJ_TYPE_ID IN (7, 502) AND L7.DATE_DEL IS NULL
          -- предварительный прием
          UNION
          SELECT LX.OBJ_ID, LX.OBJ_TYPE_ID
          FROM LINKS L77
          JOIN LINKS L290 ON L290.PARENT_ID = L77.OBJ_ID AND L290.OBJ_TYPE_ID = 290 AND L290.DATE_DEL IS NULL
          JOIN LINKS L10 ON L10.PARENT_ID = L290.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
          JOIN LINKS L20 ON L20.PARENT_ID = L10.OBJ_ID AND L20.OBJ_TYPE_ID = 20 AND L20.DATE_DEL IS NULL
          JOIN LINKS LX ON LX.PARENT_ID = L20.OBJ_ID AND LX.OBJ_TYPE_ID = :I$TYPE_ID AND LX.DATE_DEL IS NULL
          WHERE L77.PARENT_ID = :I$OU_ID AND L77.OBJ_TYPE_ID = 77 AND L77.DATE_DEL IS NULL
          -- выбывшие
          UNION
          SELECT LX.OBJ_ID, LX.OBJ_TYPE_ID
          FROM LINKS L78
          JOIN LINKS L8X ON L8X.PARENT_ID = L78.OBJ_ID AND L8X.OBJ_TYPE_ID IN (81, 82, 83) AND L8X.DATE_DEL IS NULL
          JOIN LINKS L10 ON L10.PARENT_ID = L8X.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
          JOIN LINKS L20 ON L20.PARENT_ID = L10.OBJ_ID AND L20.OBJ_TYPE_ID = 20 AND L20.DATE_DEL IS NULL
          JOIN LINKS LX ON LX.PARENT_ID = L20.OBJ_ID AND LX.OBJ_TYPE_ID = :I$TYPE_ID AND LX.DATE_DEL IS NULL
          WHERE L78.PARENT_ID = :I$OU_ID AND L78.OBJ_TYPE_ID = 78 AND L78.DATE_DEL IS NULL
        )
        INTO :OBJ_ID, :TYPE_ID
      DO
        SUSPEND;
    END
  END
  ELSE IF(I$PATH = 14549) THEN
  BEGIN
    -- Прочие действующие, смотрим по дате или по статусу
    -- 613 - статус документа ОООД
    -- 687 - отметка о выбытии МТР
    FOR
      SELECT DISTINCT L.OBJ_ID, L.OBJ_TYPE_ID
      FROM LINKS L
      LEFT JOIN VALL VL ON VL.OBJ_ID = L.OBJ_ID AND VL.PARAM_ID IN (613) AND VL.IS_DEL = 0
      LEFT JOIN VALD VD ON VD.OBJ_ID = L.OBJ_ID AND VD.PARAM_ID IN (687) AND VD.IS_DEL = 0
      WHERE L.OBJ_ID >= :I$FROM_ID AND L.OBJ_ID < :I$TO_ID AND L.DATE_DEL IS NULL AND L.OBJ_TYPE_ID = :I$TYPE_ID
        AND VD.VAL IS NULL AND (VL.LISTVAL_ID IS NULL OR VL.LISTVAL_ID NOT IN (1893))
      INTO :OBJ_ID, :TYPE_ID
    DO
      SUSPEND;
  END
  ELSE IF(I$PATH = 15819) THEN
  BEGIN
    -- Прочие не действующие, смотрим по дате или по статусу
    FOR
      SELECT DISTINCT L.OBJ_ID, L.OBJ_TYPE_ID
      FROM LINKS L
      LEFT JOIN VALL VL ON VL.OBJ_ID = L.OBJ_ID AND VL.PARAM_ID IN (613) AND VL.IS_DEL = 0
      LEFT JOIN VALD VD ON VD.OBJ_ID = L.OBJ_ID AND VD.PARAM_ID IN (687) AND VD.IS_DEL = 0
      WHERE L.OBJ_ID >= :I$FROM_ID AND L.OBJ_ID < :I$TO_ID AND L.DATE_DEL IS NULL AND L.OBJ_TYPE_ID = :I$TYPE_ID
        AND (VD.VAL IS NOT NULL OR VL.LISTVAL_ID IN (1893))
      INTO :OBJ_ID, :TYPE_ID
    DO
      SUSPEND;
  END
  ELSE IF(I$PATH = 15820) THEN
  BEGIN
    -- Прочие все
    FOR
      SELECT DISTINCT L.OBJ_ID, L.OBJ_TYPE_ID
      FROM LINKS L
      WHERE L.OBJ_ID >= :I$FROM_ID AND L.OBJ_ID < :I$TO_ID AND L.DATE_DEL IS NULL AND L.OBJ_TYPE_ID = :I$TYPE_ID
      INTO :OBJ_ID, :TYPE_ID
    DO
      SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PROCESS_VERIFY_SUBFLT (
    I$PARENT_TYPE_ID BIGINT,
    I$PARENT_ID BIGINT,
    I$OBJ_TYPE_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$PARAM_ID BIGINT,
    I$PARAM_LV BIGINT)
RETURNS (
    IS_MATCH SMALLINT)
AS
declare variable V$D date;
begin
  IS_MATCH = 1;

  IF(I$PARAM_ID = 441 AND I$PARAM_LV = 1370) THEN
  BEGIN
    -- Свидетельство о рождении, актуально только для действующих обучающихся классов, у сотрудников маскируем
    -- Маскируем иностранцев
    IS_MATCH = 0;
    IF(I$PARENT_TYPE_ID = 10) THEN
    BEGIN
      SELECT FIRST 1 1
      FROM VALL V
      WHERE V.OBJ_ID = :I$PARENT_ID AND V.PARAM_ID = 91 AND V.IS_DEL = 0 AND V.LISTVAL_ID = 1515
      INTO :IS_MATCH;
    END
  END
  ELSE IF(I$PARAM_ID = 441 AND I$PARAM_LV = 1368) THEN
  BEGIN
    -- Паспорт РФ - только для граждан РФ и актуально только для действующих обучающихся классов
    IS_MATCH = 0;
    SELECT FIRST 1 1
    FROM VALL V
    WHERE V.OBJ_ID = :I$PARENT_ID AND V.PARAM_ID IN (91, 243, 2931) AND V.IS_DEL = 0 AND V.LISTVAL_ID = 1515
    INTO :IS_MATCH;

    -- Маскируем тех, кому не исполнилось 14 лет (14x12 + запас 3 месяца)
    -- только обучающихся
    IF(IS_MATCH = 1) THEN
    BEGIN
      SELECT FIRST 1 V.VAL
      FROM VALD V
      WHERE V.OBJ_ID = :I$PARENT_ID AND V.PARAM_ID = 89 AND V.IS_DEL = 0
      INTO :V$D;

      IF(V$D > DATEADD(-171 MONTH TO CURRENT_DATE)) THEN IS_MATCH = 0;
    END

    -- Маскируем не действующих учеников, сотрудников
    IF(IS_MATCH = 1) THEN
    BEGIN
      IF(NOT EXISTS(
        SELECT FIRST 1 1
        FROM LINKS LP
        WHERE LP.OBJ_ID = :I$PARENT_ID AND LP.PARENT_TYPE_ID IN (9, 187, 2, 211, 125) AND LP.DATE_DEL IS NULL
      ))
      THEN
        IS_MATCH = 0;
    END
  END

  SUSPEND;
end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PROJECT_NAME_GET RETURNS (
    VAL VARCHAR(4000))
AS
begin
  SELECT KEY_VAL
  FROM KEYS
  WHERE KEY_CODE = 'PROJECT_NAME'
  INTO :VAL;
  suspend;
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PROJECT_TYPE RETURNS (
    STATUS VARCHAR(25))
AS
begin
    STATUS = '';
    IF (EXISTS(
        SELECT 1
        FROM KEYS
        WHERE KEY_CODE = 'PROJECT_NAME'
        AND KEY_VAL LIKE 'Параграф%'
    )) THEN
    BEGIN
        STATUS = 'Параграф';
    END
    ELSE IF (EXISTS(
        SELECT 1
        FROM KEYS
        WHERE KEY_CODE = 'PROJECT_NAME'
        AND KEY_VAL LIKE 'Апостроф%'
    )) THEN
    BEGIN
        STATUS = 'Апостроф';
    END
    SUSPEND;
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PTP_ALT_SUBJECTS (
    I$SUBJECT_ID BIGINT)
RETURNS (
    SUBJECT_ID BIGINT)
AS
declare variable SUBJECT_CAPTION varchar(1000);
declare variable IS_FOREIGN smallint;
begin

    SELECT CAPTION
    FROM OBJECT_CAPTION_GET(:I$SUBJECT_ID)
    INTO :SUBJECT_CAPTION;

    IS_FOREIGN = 0;
    IF(POSITION('ностранный', SUBJECT_CAPTION) > 0 AND POSITION('зык', SUBJECT_CAPTION) > 0) THEN IS_FOREIGN = 1;

    -- I$SUBJECT_ID - код предмета из УП (может быть местный вариант иностранных языков)
    FOR
        -- Сам исходный предмет
        SELECT :I$SUBJECT_ID FROM RDB$DATABASE

        UNION

        -- Если запрошенный предмет содержит слова ИНОСТРАННЫЙ и ЯЗЫК, то также добавляем первый и второй иностранный языки
        SELECT 178 FROM RDB$DATABASE
        WHERE :IS_FOREIGN = 1
        UNION
        SELECT 32810 FROM RDB$DATABASE
        WHERE :IS_FOREIGN = 1

        -- Возможные предметы из шаблонного УП, которые указаны в качестве замены для данного предмета
        UNION 
        SELECT DISTINCT V2718.VAL
        -- Заменяемый предмет
        FROM VALR V2719
        -- Ссылка на замену существует
        JOIN LINKS L349 ON L349.OBJ_ID = V2719.OBJ_ID AND L349.OBJ_TYPE_ID = 349 AND L349.PARENT_TYPE_ID = 49 AND L349.DATE_DEL IS NULL
        -- Компонент УП существует
        JOIN LINKS LP50 ON LP50.OBJ_ID = L349.PARENT_ID AND LP50.PARENT_TYPE_ID = 50 AND LP50.DATE_DEL IS NULL
        -- И ОП существует
        JOIN LINKS LPP ON LPP.OBJ_ID = LP50.PARENT_ID AND LPP.PARENT_TYPE_ID IN (57, 252, 244) AND LPP.DATE_DEL IS NULL
        -- Предмет по шаблону
        JOIN VALR V2718 ON V2718.OBJ_ID = L349.OBJ_ID AND V2718.PARAM_ID = 2718 AND V2718.IS_DEL = 0
        WHERE V2719.PARAM_ID = 2719 AND V2719.VAL = :I$SUBJECT_ID AND V2719.IS_DEL = 0

        -- И в обратную сторону - предметы из школьных УП, для которых в качестве замены указан данный предмет
        UNION
        SELECT DISTINCT V2719.VAL
        -- Заменяемый предмет
        FROM VALR V2718
        -- Ссылка на замену существует
        JOIN LINKS L349 ON L349.OBJ_ID = V2718.OBJ_ID AND L349.OBJ_TYPE_ID = 349 AND L349.PARENT_TYPE_ID = 49 AND L349.DATE_DEL IS NULL
        -- Компонент УП существует
        JOIN LINKS LP50 ON LP50.OBJ_ID = L349.PARENT_ID AND LP50.PARENT_TYPE_ID = 50 AND LP50.DATE_DEL IS NULL
        -- И ОП существует
        JOIN LINKS LPP ON LPP.OBJ_ID = LP50.PARENT_ID AND LPP.PARENT_TYPE_ID IN (57, 252, 244) AND LPP.DATE_DEL IS NULL
        -- Предмет по шаблону
        JOIN VALR V2719 ON V2719.OBJ_ID = L349.OBJ_ID AND V2719.PARAM_ID = 2719 AND V2718.IS_DEL = 0
        WHERE V2718.PARAM_ID = 2718 AND V2718.VAL = :I$SUBJECT_ID AND V2718.IS_DEL = 0

        INTO :SUBJECT_ID
    DO
    BEGIN
        SUSPEND;
    END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PTP_ASSIGNMENTS_LIST (
    I$PTP_ID BIGINT)
RETURNS (
    VAL VARCHAR(4000),
    MAXSTATE SMALLINT,
    HAS_CHILDREN SMALLINT)
AS
declare variable V$STATE smallint;
declare variable V$NAME varchar(200);
begin
  VAL = '';
  MAXSTATE = 0;
  HAS_CHILDREN = 0;

  FOR
    SELECT P.APPROVAL_STATE, SUBSTRING(J.JOURNAL_NAME FROM 1 FOR 100)
    FROM CJ2_JOURNAL_PTP P
    JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.OBJ_ID = P.CJ_ID
    WHERE P.DATE_DEL IS NULL AND P.PTP_ID = :I$PTP_ID AND P.APPROVAL_STATE < 3
    INTO :V$STATE, :V$NAME
  DO
  BEGIN

    IF(V$STATE = 0) THEN V$NAME = V$NAME || ' (проект)';
    ELSE IF(V$STATE = 1) THEN V$NAME = V$NAME || ' (к утв)';
    ELSE IF(V$STATE = 2) THEN V$NAME = V$NAME || ' (действ)';

    MAXSTATE = BIN_OR(MAXSTATE, BIN_SHL(1, V$STATE));

    IF(CHAR_LENGTH(VAL) + CHAR_LENGTH(V$NAME) < 3990) THEN
    BEGIN
      IF(VAL <> '') THEN VAL = VAL || ', ';
      VAL = VAL || V$NAME;
    END

  END

  SELECT FIRST 1 1
  FROM PTP P
  WHERE P.DATE_DEL IS NULL AND P.PARENT_ID = :I$PTP_ID
  INTO :HAS_CHILDREN;

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PTP_CEC_SPLIT (
    I$PTP_ID BIGINT)
RETURNS (
    LESSON_ID BIGINT,
    CEC_TEXT VARCHAR(400),
    CEC_ID BIGINT)
AS
declare variable V$SUBJECT_ID bigint;
declare variable V$NAME varchar(400);
declare variable V$CEC_ID bigint;
declare variable S varchar(8000);
declare variable P integer;
begin

  SELECT P.SUBJECT_ID, P.OBJ_NAME
  FROM PTP P
  WHERE P.OBJ_ID = :I$PTP_ID AND P.DATE_DEL IS NULL AND P.LEVEL_ID = 2167
  INTO :V$SUBJECT_ID, :V$NAME;

  IF(V$SUBJECT_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Рабочая программа не найдена';

  SELECT FIRST 1 C.OBJ_ID
  FROM CEC C
  WHERE C.DATE_DEL IS NULL AND C.SUBJECT_ID = :V$SUBJECT_ID AND C.CAPTION = :V$NAME AND C.TYPE_ID = 10000
  INTO :V$CEC_ID;

  IF(V$CEC_ID IS NULL) THEN
  BEGIN
    INSERT INTO CEC
    (SUBJECT_ID, TYPE_ID, CAPTION)
    VALUES (:V$SUBJECT_ID, 10000, :V$NAME)
    RETURNING OBJ_ID INTO :V$CEC_ID;
  END

  FOR
    SELECT L.OBJ_ID, L.H_TEXT
    FROM PTP_LESSONS L
    WHERE L.DATE_DEL IS NULL AND L.PTP_ID = :I$PTP_ID AND L.LESSON_NUM > 0 AND L.H_TEXT IS NOT NULL
    ORDER BY L.LESSON_NUM
    INTO :LESSON_ID, :S
  DO
  BEGIN

    -- Временно работаем только с короткими элементами, не содержащими переводов строки
    IF(CHAR_LENGTH(S) < 100 AND POSITION(ASCII_CHAR(13) || ASCII_CHAR(10) IN S) <= 0) THEN
    BEGIN

      S = REPLACE(S, ASCII_CHAR(13) || ASCII_CHAR(10), '');
      S = REPLACE(S, ASCII_CHAR(13), '');
      WHILE(CHAR_LENGTH(S) > 0) DO
      BEGIN
        P = POSITION(ASCII_CHAR(10) IN S);
        IF(P <= 0) THEN P = CHAR_LENGTH(S) + 1;

        CEC_TEXT = SUBSTRING(SUBSTRING(S FROM 1 FOR P - 1) FROM 1 FOR 400);
        S = SUBSTRING(S FROM P + 1);

        SUSPEND;
      END
    END
  END

  WHEN ANY DO EXCEPTION DATA_ERROR 'Ошибка на строке ' || LESSON_ID;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PTP_EDS_REPORT (
    I$OBJ_ID BIGINT,
    I$FILTER SMALLINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    VAL VARCHAR(4000))
AS
declare variable V$ROLE smallint;
declare variable V$N1 integer;
declare variable V$N2 integer;
declare variable V$N3 integer;
declare variable V$N4 integer;
declare variable V$N5 integer;
declare variable V$N6 integer;
declare variable V$N7 integer;
declare variable V$N8 integer;
declare variable V$N9 integer;
declare variable V$NX integer;
declare variable V$SUBJECT_ID bigint;
declare variable V$SA_ID bigint;
declare variable V$TEACHER_ID bigint;
declare variable V$PT bigint;
declare variable PS varchar(400);
declare variable S varchar(400);
begin

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  SELECT U.USER_TYPE
  FROM USERS U
  WHERE U.USER_ID = :I$USER_ID
  INTO :V$ROLE;

  V$N1 = 0;
  V$N2 = 0;
  V$N3 = 0;
  V$N4 = 0;
  V$N5 = 0;
  V$N6 = 0;
  V$N7 = 0;
  V$N8 = 0;
  V$N9 = 0;
  V$NX = 0;
  V$PT = -1;

  VAL = '<table class="ui small compact striped celled fixed table">';
  VAL = VAL || '<thead><tr>';
    VAL = VAL || '<th style="width: 30%">ФИО учителя</th>';
    VAL = VAL || '<th style="width: 10%">Итого</th>';
    VAL = VAL || '<th>Русский язык и литература</th>';
    VAL = VAL || '<th>Математика и информатика</th>';
    VAL = VAL || '<th>Иностранный язык</th>';
    VAL = VAL || '<th>Обществознание</th>';
    VAL = VAL || '<th>Естествознание</th>';
    VAL = VAL || '<th>ОРКСЭ</th>';
    VAL = VAL || '<th>Искусство</th>';
    VAL = VAL || '<th>Физическая культура, ОБЖ</th>';
    VAL = VAL || '<th>Технология</th>';
    VAL = VAL || '<th>Прочие</th>';
  VAL = VAL || '</tr></thead>';
  VAL = VAL || '<tbody>';
  SUSPEND;

  FOR
    SELECT M.TEACHER_ID, C.CAPTION, M.SUBJECT_ID, (SELECT FIRST 1 V2462.LISTVAL_ID
      FROM LINKS L302
      JOIN VALL V2462 ON V2462.OBJ_ID = L302.OBJ_ID AND V2462.PARAM_ID = 2462 AND V2462.IS_DEL = 0
      WHERE L302.PARENT_ID = M.SUBJECT_ID AND L302.OBJ_TYPE_ID = 302 AND L302.DATE_DEL IS NULL
    ) SA_ID
    FROM PTP P
    JOIN CJ2_JOURNAL_PTP J ON J.DATE_DEL IS NULL AND J.PTP_ID = P.OBJ_ID AND J.APPROVAL_STATE = 2
    JOIN CJ2_JOURNAL M ON M.OBJ_ID = J.CJ_ID AND M.DATE_DEL IS NULL AND M.JOURNAL_TYPE = 0 AND M.TEACHER_ID IS NOT NULL
    JOIN PTP_LESSONS L ON L.DATE_DEL IS NULL AND L.PTP_ID = P.OBJ_ID AND (UPPER(L.EXTRA_TEXT) LIKE '%DO2%' OR UPPER(L.EXTRA_TEXT) LIKE '%VIDEOPORRAL%')
    LEFT JOIN OBJECT_CAPTION_GET(M.TEACHER_ID) C ON 1 = 1
    WHERE P.DATE_DEL IS NULL AND (:V$ROLE IN (1, 5, 6) OR M.TEACHER_ID = :I$USER_ID)
    ORDER BY 2, 1
    INTO :V$TEACHER_ID, :S, :V$SUBJECT_ID, :V$SA_ID
  DO
  BEGIN
    IF(V$TEACHER_ID <> V$PT) THEN
    BEGIN
      IF(V$PT >= 0) THEN
      BEGIN
        VAL = '<tr>';
          VAL = VAL || '<td>' || PS || '</td>';
          VAL = VAL || '<td class="positive">' || (V$N1 + V$N2 + V$N3 + V$N4 + V$N5 + V$N6 + V$N7 + V$N8 + V$N9 + V$NX) || '</td>';
          VAL = VAL || '<td>' || IIF(V$N1 > 0, V$N1, '') || '</td>';
          VAL = VAL || '<td>' || IIF(V$N2 > 0, V$N2, '') || '</td>';
          VAL = VAL || '<td>' || IIF(V$N3 > 0, V$N3, '') || '</td>';
          VAL = VAL || '<td>' || IIF(V$N4 > 0, V$N4, '') || '</td>';
          VAL = VAL || '<td>' || IIF(V$N5 > 0, V$N5, '') || '</td>';
          VAL = VAL || '<td>' || IIF(V$N6 > 0, V$N6, '') || '</td>';
          VAL = VAL || '<td>' || IIF(V$N7 > 0, V$N7, '') || '</td>';
          VAL = VAL || '<td>' || IIF(V$N8 > 0, V$N8, '') || '</td>';
          VAL = VAL || '<td>' || IIF(V$N9 > 0, V$N9, '') || '</td>';
          VAL = VAL || '<td>' || IIF(V$NX > 0, V$NX, '') || '</td>';
        VAL = VAL || '</tr>';
        SUSPEND;
      END

      V$PT = COALESCE(V$TEACHER_ID, 0);
      PS = S;
      V$N1 = 0;
      V$N2 = 0;
      V$N3 = 0;
      V$N4 = 0;
      V$N5 = 0;
      V$N6 = 0;
      V$N7 = 0;
      V$N8 = 0;
      V$N9 = 0;
      V$NX = 0;
    END

    IF(V$SA_ID IN (11680, 11681)) THEN V$N1 = V$N1 + 1; -- русский и литра
    ELSE IF(V$SA_ID IN (11685)) THEN V$N2 = V$N2 + 1; -- математика и информатика
    ELSE IF(V$SA_ID IN (11684, 12740)) THEN V$N3 = V$N3 + 1; -- иностранный
    ELSE IF(V$SA_ID IN (11686, 11687, 11688)) THEN V$N4 = V$N4 + 1; -- обществознание
    ELSE IF(V$SA_ID IN (11691, 11692)) THEN V$N5 = V$N5 + 1; -- естествознание
    ELSE IF(V$SA_ID IN (11689, 11690)) THEN V$N6 = V$N6 + 1; -- орксэ
    ELSE IF(V$SA_ID IN (11693)) THEN V$N7 = V$N7 + 1; -- искусство
    ELSE IF(V$SA_ID IN (11695, 11696, 11697)) THEN V$N8 = V$N8 + 1; -- физра, обж
    ELSE IF(V$SA_ID IN (11694)) THEN V$N9 = V$N9 + 1; -- технология
    ELSE V$NX = V$NX + 1;
  END

  ----
      IF(V$PT >= 0) THEN
      BEGIN
        VAL = '<tr>';
          VAL = VAL || '<td>' || PS || '</td>';
          VAL = VAL || '<td class="positive">' || (V$N1 + V$N2 + V$N3 + V$N4 + V$N5 + V$N6 + V$N7 + V$N8 + V$N9 + V$NX) || '</td>';
          VAL = VAL || '<td>' || IIF(V$N1 > 0, V$N1, '') || '</td>';
          VAL = VAL || '<td>' || IIF(V$N2 > 0, V$N2, '') || '</td>';
          VAL = VAL || '<td>' || IIF(V$N3 > 0, V$N3, '') || '</td>';
          VAL = VAL || '<td>' || IIF(V$N4 > 0, V$N4, '') || '</td>';
          VAL = VAL || '<td>' || IIF(V$N5 > 0, V$N5, '') || '</td>';
          VAL = VAL || '<td>' || IIF(V$N6 > 0, V$N6, '') || '</td>';
          VAL = VAL || '<td>' || IIF(V$N7 > 0, V$N7, '') || '</td>';
          VAL = VAL || '<td>' || IIF(V$N8 > 0, V$N8, '') || '</td>';
          VAL = VAL || '<td>' || IIF(V$N9 > 0, V$N9, '') || '</td>';
          VAL = VAL || '<td>' || IIF(V$NX > 0, V$NX, '') || '</td>';
        VAL = VAL || '</tr>';
        SUSPEND;
      END
  -----

  VAL = '</tbody></table>';
  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PTP_EDS_REPORT2 (
    I$OBJ_ID BIGINT,
    I$FILTER SMALLINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    VAL VARCHAR(4000))
AS
declare variable V$ROLE smallint;
declare variable V$REF_ID bigint;
declare variable V$PTP_ID bigint;
declare variable V$PNAME varchar(1000);
declare variable V$SNAME varchar(400);
declare variable V$LNAME varchar(400);
declare variable V$SUBJECT_ID bigint;
declare variable V$TEACHER_ID bigint;
declare variable V$HOURS integer;
declare variable V$EDS integer;
begin

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  SELECT U.USER_TYPE, U.OBJ_ID
  FROM USERS U
  WHERE U.USER_ID = :I$USER_ID
  INTO :V$ROLE, :V$REF_ID;

  VAL = '<table class="ui small compact striped celled fixed table">';
  VAL = VAL || '<thead><tr>';
    VAL = VAL || '<th>Название ПТП</th>';
    VAL = VAL || '<th>Предмет</th>';
    VAL = VAL || '<th>Тип, этап</th>';
    VAL = VAL || '<th>Обьем, часов</th>';
    VAL = VAL || '<th>Где задействован</th>';
    VAL = VAL || '<th>Сервисы ЭДС</th>';
  VAL = VAL || '</tr></thead>';
  VAL = VAL || '<tbody>';
  SUSPEND;

  FOR
    SELECT P.OBJ_ID, P.OBJ_NAME, C.CAPTION, L.VAL, P.SUBJECT_ID, P.OWNER_ID, P.PTP_HOURS, (SELECT COUNT(*) FROM PTP_LESSONS L WHERE L.DATE_DEL IS NULL AND L.PTP_ID = P.OBJ_ID AND (UPPER(L.EXTRA_TEXT) LIKE '%DO2%' OR UPPER(L.EXTRA_TEXT) LIKE '%VIDEOPORRAL%'))
    FROM PTP P
    LEFT JOIN OBJECT_CAPTION_GET(P.SUBJECT_ID) C ON 1 = 1
    LEFT JOIN LISTVAL_TEXT(P.LEVEL_ID) L ON 1 = 1
    WHERE P.DATE_DEL IS NULL AND (:V$ROLE IN (1, 5, 6) OR P.OWNER_ID = :V$REF_ID)
    ORDER BY 3, 2
    INTO :V$PTP_ID, :V$PNAME, :V$SNAME, :V$LNAME, :V$SUBJECT_ID, :V$TEACHER_ID, :V$HOURS, :V$EDS
  DO
  BEGIN
    IF(V$EDS > 0) THEN
    BEGIN
      VAL = '<tr>';
        VAL = VAL || '<td>' || V$PNAME || '</td>';
        VAL = VAL || '<td>' || V$SNAME || '</td>';
        VAL = VAL || '<td>' || V$LNAME || '</td>';
        VAL = VAL || '<td>' || V$HOURS || '</td>';
        SUSPEND;

        VAL = '';
        FOR
          SELECT J.JOURNAL_NAME
          FROM CJ2_JOURNAL_PTP P
          JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.OBJ_ID = P.CJ_ID
          WHERE P.DATE_DEL IS NULL AND P.PTP_ID = :V$PTP_ID AND P.APPROVAL_STATE = 3
          INTO :V$SNAME
        DO
        BEGIN
          IF(VAL <> '') THEN VAL = VAL || ', ';
          VAL = VAL || V$SNAME;
        END
        VAL = '<td>' || VAL || '</td>';
        SUSPEND;

        VAL = '<td>' || V$EDS || '</td>';
      VAL = VAL || '</tr>';
      SUSPEND;
    END
  END

  VAL = '</tbody></table>';
  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PTP_STAGE_NAME (
    I$LEVEL_ID BIGINT)
RETURNS (
    CAPTION VARCHAR(200),
    SORT_ORDER SMALLINT)
AS
begin

  IF(I$LEVEL_ID = 2141) THEN
  BEGIN
      CAPTION = 'ГПД';
      SORT_ORDER = -3;
  END
  ELSE IF(I$LEVEL_ID = 2143) THEN
  BEGIN
      CAPTION = 'Дополнительное образование';
      SORT_ORDER = -2;
  END
  ELSE IF(I$LEVEL_ID = 2155) THEN
  BEGIN
      CAPTION = 'Внеурочная деятельность';
      SORT_ORDER = -1;
  END
  ELSE IF(I$LEVEL_ID = 2167) THEN
  BEGIN
      CAPTION = 'Рабочие программы';
      SORT_ORDER = -3;
  END
  ELSE IF(I$LEVEL_ID = 2167) THEN
  BEGIN
      CAPTION = 'Федеральные ПП';
      SORT_ORDER = -3;
  END
  ELSE
  BEGIN
      SELECT R.VAL, LV.SORT_ORDER
      FROM LISTVALS LV
      JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
      WHERE LV.LISTVAL_ID = :I$LEVEL_ID
      INTO :CAPTION, :SORT_ORDER;
  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PTP_TEST_BROWSE (
    I$SUBJECT_ID BIGINT,
    I$STAGE_ID BIGINT,
    I$RANGE INTEGER,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE S VARCHAR(1000);
DECLARE VARIABLE N INTEGER;
DECLARE VARIABLE R SMALLINT;
begin

  -- RANGE: NULL или 0, только шаблоны
  -- 1 - разрешать уже запущенные (связанные с уроками)
  IF(I$RANGE IS NULL) THEN I$RANGE = 0;

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  IF(I$STAGE_ID >= 37 AND I$STAGE_ID <= 47) THEN I$STAGE_ID = 1 + (I$STAGE_ID - 37); -- параллели школы
  ELSE IF(I$STAGE_ID >= 49 AND I$STAGE_ID <= 54) THEN I$STAGE_ID = 41 + (I$STAGE_ID - 49); -- курсы

  TAG_NAME = 'items::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT D.OBJ_ID, D.OBJ_NAME,
      (SELECT COUNT(DISTINCT Q.SORT_INDEX) FROM UT_EXAM_QUESTIONS Q WHERE Q.DATE_DEL IS NULL AND Q.EXAM_ID = D.OBJ_ID),
      IIF(D.EXAM_STATE = 0, 0, 1)
    FROM UT_EXAM_DATES D
    WHERE D.DATE_DEL IS NULL AND D.SUBJECT_ID = :I$SUBJECT_ID AND (D.STAGE_ID = :I$STAGE_ID OR D.STAGE_ID = 20 OR D.STAGE_ID = 100)
      AND D.PLAN_METHOD_ID = 4 AND D.EXAM_DAY_TYPE = 0
      AND (:I$RANGE = 1 OR (D.EXAM_DATE_START IS NULL AND D.EXAM_DATE_END IS NULL AND D.EXAM_STATE = 0))
      AND (D.OWNER_ID IS NULL OR D.OWNER_ID = :I$USER_ID)
    ORDER BY 2
    INTO :V$OBJ_ID, :S, :N, :R
  DO
  BEGIN
    TAG_NAME = 'items:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'items:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'items:r:name';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'items:r:n_questions';
    VAL = N;
    SUSPEND;
    TAG_NAME = 'items:r:running';
    VAL = R;
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PTP_TEST_JOIN (
    I$SUBJECT_ID BIGINT,
    I$STAGE_ID BIGINT,
    I$TEST_ID BIGINT,
    I$GROUP_NAME VARCHAR(400),
    I$THEME VARCHAR(400),
    I$LESSON_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TEST_ID BIGINT,
    NAME VARCHAR(1000),
    TEST_STATE SMALLINT)
AS
DECLARE VARIABLE V$OU_ID BIGINT;
DECLARE VARIABLE V$PERIOD_ID BIGINT;
DECLARE VARIABLE V$OWNER_ID BIGINT;
DECLARE VARIABLE V$ASSIGNED SMALLINT;
DECLARE VARIABLE V$OTHER SMALLINT;
begin

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  SELECT FIRST 1 L2.OBJ_ID, V1236.LISTVAL_ID
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$OU_ID, :V$PERIOD_ID;

  -- Переводим ID в сетку для тестов
  IF(I$STAGE_ID >= 37 AND I$STAGE_ID <= 47) THEN I$STAGE_ID = 1 + (I$STAGE_ID - 37); -- параллели школы
  ELSE IF(I$STAGE_ID >= 49 AND I$STAGE_ID <= 54) THEN I$STAGE_ID = 41 + (I$STAGE_ID - 49); -- курсы

  IF(I$TEST_ID IS NULL) THEN
  BEGIN

    -- Создаем новый тест
    IF(I$GROUP_NAME IS NULL) THEN I$GROUP_NAME = '';
    ELSE I$GROUP_NAME = ' ' || SUBSTRING(I$GROUP_NAME FROM 1 FOR 40);

    NAME = EXTRACT(YEAR FROM CURRENT_DATE) || ' - ' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$SUBJECT_ID)) || I$GROUP_NAME || ' - ' ||
      (SELECT OBJ_NAME FROM UT_EXAM_STAGES WHERE OBJ_ID = :I$STAGE_ID) || ' - ' || I$THEME;

    INSERT INTO UT_EXAM_DATES
    (SUBJECT_ID, STAGE_ID, OBJ_NAME, EXAM_STATE, EXAM_DAY_TYPE, METHOD_ID, PLAN_METHOD_ID, ATTEMPTS, OWNER_ID, H_LEVEL, ORG_REF, PERIOD_ID, 
      FLOW_MODE, C_CALC_MODE, C_EXPERT_NUM, C_DIFF_QUESTION, C_DIFF_TOTAL, EXPERT_ASSN_MODE, LINK_MASK)
    VALUES (:I$SUBJECT_ID, :I$STAGE_ID, SUBSTRING(:NAME FROM 1 FOR 200), 0, 0, 0, 4, 0, :I$USER_ID, 0, :V$OU_ID, :V$PERIOD_ID,
      1, 0, 0, 0, 0, 0, 0)
    RETURNING OBJ_ID INTO :TEST_ID;

    TEST_STATE = 0;

  END
  ELSE
  BEGIN

    -- Выбираем ссылку на тест, сам тест остается в первозданном виде
    -- если до того тест находился в статусе проекта
    -- если тест уже запущен в другом уроке и связан с ученикам, создаем копию и возвращаем ее
    SELECT D.OBJ_ID, D.OBJ_NAME, D.OWNER_ID, D.EXAM_STATE
    FROM UT_EXAM_DATES D
    WHERE D.DATE_DEL IS NULL AND D.OBJ_ID = :I$TEST_ID
    INTO :TEST_ID, :NAME, :V$OWNER_ID, :TEST_STATE;

    IF(TEST_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Тест не найден или был удален';

    V$ASSIGNED = 0;
    SELECT FIRST 1 1
    FROM UT_EXAM_PERSON_ASSN PA
    WHERE PA.DATE_DEL IS NULL AND PA.EXAM_ID = :TEST_ID
    INTO :V$ASSIGNED;

    SELECT FIRST 1 1
    FROM CJ2_CONTROL C
    WHERE C.DATE_DEL IS NULL AND C.LESSON_ID <> :I$LESSON_ID AND C.TEST_ID = :TEST_ID
    INTO :V$OTHER;

    -- Здесь будет ветка только для журналов, хотя в ПТП можно успеть прикрепить тест к уроку с другого компьютера
    IF(V$OTHER = 1 AND TEST_STATE > 0) THEN
    BEGIN
      TEST_STATE = 0;

      SELECT D.OBJ_ID, DD.OBJ_NAME
      FROM UT_TEST_CLONE(:I$TEST_ID, :TEST_STATE, NULL, NULL, NULL, :I$GROUP_NAME) D
      LEFT JOIN UT_EXAM_DATES DD ON DD.OBJ_ID = D.OBJ_ID
      INTO :TEST_ID, :NAME;
    END

  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PUPIL_ACCEPTED_INFO_GET (
    I$PUPIL_ID BIGINT)
RETURNS (
    ACCEPTED_INFO VARCHAR(1000))
AS
declare variable V$MOVE_ID bigint;
declare variable V$433 varchar(1000);
declare variable V$434 varchar(1000);
declare variable V$435 varchar(1000);
declare variable V$YEAR_DATE date;
declare variable V$END_DATE date;
BEGIN
    -- Функция более неработоспособна с переходом на новые реестры движения

    -- Дата зачисления в ОУ
    SELECT I FROM DO_FUNC(:I$PUPIL_ID, 2099)
    INTO :V$MOVE_ID;

    IF(EXTRACT(MONTH FROM CURRENT_DATE) >= 9) THEN V$YEAR_DATE = '02.09.' || EXTRACT(YEAR FROM CURRENT_DATE);
    ELSE V$YEAR_DATE = '02.09.' || (EXTRACT(YEAR FROM CURRENT_DATE) - 1);
    V$END_DATE = '25.05.' || EXTRACT(YEAR FROM V$YEAR_DATE);

    FOR
        SELECT FIRST 1 (SELECT DT FROM CURRENT_DATE_GET(V433.VAL, 'DD.MM.YY')), V434.VAL, (SELECT DT FROM CURRENT_DATE_GET(V435.VAL, 'DD.MM.YY'))
        FROM VALD V433
        LEFT JOIN VALS V434 ON V433.OBJ_ID = V434.OBJ_ID AND V434.PARAM_ID = 434 AND V434.IS_DEL = 0
        LEFT JOIN VALD V435 ON V433.OBJ_ID = V435.OBJ_ID AND V435.PARAM_ID = 435 AND V435.IS_DEL = 0
        WHERE V433.OBJ_ID = :V$MOVE_ID AND V433.PARAM_ID = 433 AND V433.IS_DEL = 0 AND (V433.VAL >= :V$YEAR_DATE) AND (V433.VAL <= :V$END_DATE)
        INTO :V$433, :V$434, :V$435
    DO
    BEGIN
        ACCEPTED_INFO = 'принят';
        IF (V$433 IS NOT NULL) THEN ACCEPTED_INFO = ACCEPTED_INFO || ' ' || V$433 || 'г.';

        IF (V$434 IS NOT NULL OR V$435 IS NOT NULL) THEN
        BEGIN
            IF (V$433 IS NOT NULL) THEN
            BEGIN
                SUSPEND;
            END
            ELSE
            BEGIN
                ACCEPTED_INFO = :ACCEPTED_INFO || ', ';
            END
            ACCEPTED_INFO = 'приказ';

            IF (V$434 IS NOT NULL) THEN
            BEGIN
                ACCEPTED_INFO = ACCEPTED_INFO || ' № ' || V$434;
            END

            IF (V$435 IS NOT NULL) THEN
            BEGIN
                ACCEPTED_INFO = ACCEPTED_INFO || ' от ' || V$435 || 'г.';
            END
        END
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PUPIL_ACCEPT_MOVEMENTS (
    I$GRADE_ID BIGINT,
    I$STUDENT_ID BIGINT,
    I$REASON_ID BIGINT,
    I$DATE DATE,
    I$ORDER_DATE DATE,
    I$ORDER_NUM VARCHAR(400),
    I$USER_ID BIGINT,
    I$ORDER_ID BIGINT = null)
RETURNS (
    MOVE_ID BIGINT)
AS
declare variable V$TYPE bigint;
declare variable V$MOVE_ID bigint;
declare variable TMP bigint;
begin

  SELECT TYPE_ID
  FROM OBJECTS
  WHERE OBJ_ID = :I$GRADE_ID
  INTO :V$TYPE;

  -- Если у нас есть id приказа, берем номер оттуда
  IF(I$ORDER_ID IS NOT NULL) THEN
  BEGIN
    SELECT FIRST 1 S.ORDER_DATE, S.ORDER_NUM
    FROM ORDERS S
    WHERE S.OBJ_ID = :I$ORDER_ID
    INTO :I$ORDER_DATE, :I$ORDER_NUM;
  END

  SELECT OBJ_ID FROM VARGRP_MOVE_PUPIL(:I$STUDENT_ID, :I$GRADE_ID, :I$ORDER_NUM, :I$ORDER_DATE, :I$DATE, 0, :I$USER_ID, :I$ORDER_ID, :I$REASON_ID) INTO :V$MOVE_ID;

  -- Если у нас приказ уже утвержден - обновляем там ссылку на запись движения
  IF(I$ORDER_ID IS NOT NULL) THEN
  BEGIN
    UPDATE ORDER_DATA
    SET ACTION_ID = :V$MOVE_ID
    WHERE ORDER_ID = :I$ORDER_ID AND REF_ID = :I$STUDENT_ID AND DATE_DEL IS NULL;
  END

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PUPIL_ADDITIONAL_EDUCATION_DEL (
    I$OBJ_ID BIGINT)
RETURNS (
    DEL_COUNT SMALLINT)
AS
BEGIN
    UPDATE LINKS
    SET DATE_DEL = CURRENT_TIMESTAMP
    WHERE OBJ_ID = :I$OBJ_ID
    AND OBJ_TYPE_ID = 297
    AND PARENT_TYPE_ID = 10
    AND DATE_DEL IS NULL;

    DEL_COUNT = ROW_COUNT;
    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PUPIL_ADDITIONAL_EDUCATION_LIST (
    I$PUPIL_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    NUMBER SMALLINT,
    OOOD_TYPE_ID BIGINT,
    ORIENTATION_ID BIGINT,
    FINANCING_ID BIGINT,
    YEAR_ID BIGINT)
AS
declare variable V$Y smallint;
declare variable V$DT date;
declare variable V$YEAR_VAL varchar(100);
declare variable V$YEAR_ID bigint;
BEGIN
    V$Y = EXTRACT(YEAR FROM CURRENT_DATE);
    V$DT = '1.09.' || V$Y;
        
    IF (CURRENT_DATE < V$DT) THEN
    BEGIN
        V$YEAR_VAL = (V$Y - 1) || '-' || V$Y;
    END
    ELSE
    BEGIN
        V$YEAR_VAL = V$Y || '-' ||(V$Y + 1);
    END
        
    SELECT FIRST 1
           LV.LISTVAL_ID
    FROM LISTVALS LV
        
    JOIN RES R
    ON R.RES_ID = LV.RES_ID
    AND R.LANG_CODE = 'RU'
        
    WHERE LV.LIST_ID = 29
    AND R.VAL LIKE :V$YEAR_VAL
    INTO :V$YEAR_ID;

    YEAR_ID = V$YEAR_ID;
    SUSPEND;

    FOR
        SELECT L297.OBJ_ID,
               V2394.LISTVAL_ID,
               V2391.LISTVAL_ID,
               V2392.LISTVAL_ID,
               V2393.LISTVAL_ID
        FROM LINKS L297

        JOIN VALL V2394
        ON V2394.OBJ_ID = L297.OBJ_ID
        AND V2394.PARAM_ID = 2394
        AND V2394.IS_DEL = 0

        LEFT JOIN VALL V2391
        ON V2391.OBJ_ID = L297.OBJ_ID
        AND V2391.PARAM_ID = 2391
        AND V2391.IS_DEL = 0

        LEFT JOIN VALL V2392
        ON V2392.OBJ_ID = L297.OBJ_ID
        AND V2392.PARAM_ID = 2392
        AND V2392.IS_DEL = 0

        LEFT JOIN VALL V2393
        ON V2393.OBJ_ID = L297.OBJ_ID
        AND V2393.PARAM_ID = 2393
        AND V2393.IS_DEL = 0

        WHERE L297.PARENT_ID = :I$PUPIL_ID
        AND L297.OBJ_TYPE_ID = 297
        AND L297.DATE_DEL IS NULL
        AND V2394.LISTVAL_ID = :V$YEAR_ID

        INTO :OBJ_ID,
             :YEAR_ID,
             :OOOD_TYPE_ID,
             :ORIENTATION_ID,
             :FINANCING_ID
    DO
    BEGIN
        SELECT V
        FROM VAL_GET(:OBJ_ID, 2389)
        INTO :NUMBER;

        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PUPIL_ADDITIONAL_EDUCATION_SET (
    I$OBJ_ID BIGINT,
    I$PUPIL_ID BIGINT,
    I$OOOD_TYPE_ID BIGINT,
    I$ORIENTATION_ID BIGINT,
    I$FINANCING_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT)
AS
DECLARE VARIABLE V$BLOB_ID BIGINT;
BEGIN
    OBJ_ID = I$OBJ_ID;
    IF (OBJ_ID IS NULL) THEN
    BEGIN
        SELECT OBJ_ID
        FROM OBJECT_ADD(:I$PUPIL_ID, 297)
        INTO :OBJ_ID;
    END
    IF (OBJ_ID IS NOT NULL) THEN
    BEGIN
        SELECT BLOB_ID
        FROM VAL_ADD(2391, :OBJ_ID, :I$OOOD_TYPE_ID)
        INTO :V$BLOB_ID;

        SELECT BLOB_ID
        FROM VAL_ADD(2392, :OBJ_ID, :I$ORIENTATION_ID)
        INTO :V$BLOB_ID;

        SELECT BLOB_ID
        FROM VAL_ADD(2393, :OBJ_ID, :I$FINANCING_ID)
        INTO :V$BLOB_ID;
    END
    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PUPIL_CHILDREN_LIST (
    I$PARENT_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    PUPIL_ID BIGINT,
    PUPIL_NAME VARCHAR(400),
    CLASS_NAME VARCHAR(400),
    DATAPATH VARCHAR(100))
AS
declare variable P bigint;
declare variable OLDP bigint;
begin

  FOR
    SELECT LP10.PARENT_ID, C.CAPTION
    FROM LINKS LP10
    LEFT JOIN OBJECT_CAPTION_GET(LP10.PARENT_ID, 23) C ON 1 = 1
    WHERE LP10.OBJ_ID = :I$PARENT_ID AND LP10.PARENT_TYPE_ID = 10 AND LP10.DATE_DEL IS NULL
    INTO :PUPIL_ID, :PUPIL_NAME
  DO
  BEGIN

    CLASS_NAME = NULL;
    SELECT FIRST 1 C.CAPTION
    FROM LINKS LP9
    LEFT JOIN OBJECT_CAPTION_GET(LP9.PARENT_ID) C ON 1 = 1
    WHERE LP9.OBJ_ID = :PUPIL_ID AND LP9.PARENT_TYPE_ID IN (9, 125, 187, 81, 82, 83, 84, 289, 290, 173) AND LP9.DATE_DEL IS NULL
    ORDER BY IIF(LP9.PARENT_TYPE_ID IN (81, 82, 83, 84), 1, 0)                                   
    INTO :CLASS_NAME;

    DATAPATH = '';
    P = PUPIL_ID;
    WHILE(P IS NOT NULL) DO
    BEGIN

      IF(DATAPATH <> '') THEN DATAPATH = ';' || DATAPATH;
      DATAPATH = P || DATAPATH;

      OLDP = P;
      P = NULL;
      SELECT FIRST 1 LP.PARENT_ID
      FROM LINKS LP
      WHERE LP.OBJ_ID = :OLDP AND LP.PARENT_TYPE_ID IN (9, 125, 187, 81, 82, 83, 84, 289, 290, 173, 8, 7, 2) AND LP.DATE_DEL IS NULL
      ORDER BY IIF(LP.PARENT_TYPE_ID IN (81, 82, 83, 84), 1, 0)
      INTO :P;

    END

    SUSPEND;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PUPIL_DUPLICATE_CHECK (
    I$OBJ_ID BIGINT,
    I$PUPIL_ID BIGINT,
    I$FIRSTNAME VARCHAR(255),
    I$MIDDLENAME VARCHAR(255),
    I$LASTNAME VARCHAR(255),
    I$DOB DATE)
RETURNS (
    IS_DUPLICATE SMALLINT)
AS
declare variable V$OU_LICENCE_TYPE char(1);
begin
  IF(CHAR_LENGTH(I$MIDDLENAME) = 0) THEN I$MIDDLENAME = NULL;

  SELECT STATUS FROM OU_LICENCE_TYPE INTO :V$OU_LICENCE_TYPE;

  IF(V$OU_LICENCE_TYPE = 'O') THEN
  BEGIN

      -- Поиск дубликата в выбывших и ныне учащихся
      SELECT COUNT(*)
      FROM (
          -- Действующие учащиеся
          SELECT DISTINCT L10.OBJ_ID
          FROM LINKS L2
          JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
          JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
          JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 187) AND L9.DATE_DEL IS NULL
          JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
          JOIN VALS L ON L.OBJ_ID = L10.OBJ_ID AND L.PARAM_ID = 55 AND L.IS_DEL = 0
          JOIN VALS F ON F.OBJ_ID = L10.OBJ_ID AND F.PARAM_ID = 56 AND F.IS_DEL = 0
          LEFT JOIN VALS M ON M.OBJ_ID = L10.OBJ_ID AND M.PARAM_ID = 57 AND M.IS_DEL = 0
          LEFT JOIN VALD D ON D.OBJ_ID = L10.OBJ_ID AND D.PARAM_ID = 89 AND D.IS_DEL = 0
          WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
              AND UPPER(L.VAL) = UPPER(TRIM(:I$LASTNAME))
              AND UPPER(F.VAL) = UPPER(TRIM(:I$FIRSTNAME))
              AND ((M.VAL IS NULL AND :I$MIDDLENAME IS NULL) OR (UPPER(M.VAL) = UPPER(TRIM(:I$MIDDLENAME))))
              AND (:I$DOB IS NULL OR D.VAL = :I$DOB)
          -- Выбывшие или выпускники
          UNION
          SELECT DISTINCT L10.OBJ_ID
          FROM LINKS L2
          JOIN LINKS L78 ON L78.PARENT_ID = L2.OBJ_ID AND L78.OBJ_TYPE_ID = 78 AND L78.DATE_DEL IS NULL
          JOIN LINKS L8X ON L8X.PARENT_ID = L78.OBJ_ID AND L8X.OBJ_TYPE_ID IN (81, 82, 83, 84) AND L8X.DATE_DEL IS NULL
          JOIN LINKS L10 ON L10.PARENT_ID = L8X.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
          JOIN VALS L ON L.OBJ_ID = L10.OBJ_ID AND L.PARAM_ID = 55 AND L.IS_DEL = 0
          JOIN VALS F ON F.OBJ_ID = L10.OBJ_ID AND F.PARAM_ID = 56 AND F.IS_DEL = 0
          LEFT JOIN VALS M ON M.OBJ_ID = L10.OBJ_ID AND M.PARAM_ID = 57 AND M.IS_DEL = 0
          LEFT JOIN VALD D ON D.OBJ_ID = L10.OBJ_ID AND D.PARAM_ID = 89 AND D.IS_DEL = 0
          WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
              AND UPPER(L.VAL) = UPPER(TRIM(:I$LASTNAME))
              AND UPPER(F.VAL) = UPPER(TRIM(:I$FIRSTNAME))
              AND ((M.VAL IS NULL AND :I$MIDDLENAME IS NULL) OR (UPPER(M.VAL) = UPPER(TRIM(:I$MIDDLENAME))))
              AND (:I$DOB IS NULL OR D.VAL = :I$DOB)
      )
      INTO :IS_DUPLICATE;

  END
  ELSE
  BEGIN

      -- Поиск дубликата в УДОД
      SELECT COUNT(*)
      FROM LINKS LP243
      JOIN LINKS LP242 ON LP242.OBJ_ID = LP243.PARENT_ID AND LP242.PARENT_TYPE_ID = 242 AND LP242.DATE_DEL IS NULL
      JOIN LINKS LP2_or_211 ON LP2_or_211.OBJ_ID = LP242.PARENT_ID AND LP2_or_211.PARENT_TYPE_ID IN (2, 211) AND LP2_or_211.DATE_DEL IS NULL
      JOIN VALS L ON L.OBJ_ID = LP243.OBJ_ID AND L.PARAM_ID = 55 AND L.IS_DEL = 0
      JOIN VALS F ON F.OBJ_ID = LP243.OBJ_ID AND F.PARAM_ID = 56 AND F.IS_DEL = 0
      LEFT JOIN VALS M ON M.OBJ_ID = LP243.OBJ_ID AND M.PARAM_ID = 57 AND M.IS_DEL = 0
      LEFT JOIN VALD D ON D.OBJ_ID = LP243.OBJ_ID AND D.PARAM_ID = 89 AND D.IS_DEL = 0
      WHERE LP243.OBJ_TYPE_ID = 10 AND LP243.PARENT_TYPE_ID = 243 AND LP243.DATE_DEL IS NULL AND ((:I$PUPIL_ID IS NULL) OR (LP243.OBJ_ID <> :I$PUPIL_ID))
          AND UPPER(L.VAL) = UPPER(TRIM(:I$LASTNAME))
          AND UPPER(F.VAL) = UPPER(TRIM(:I$FIRSTNAME))
          AND ((M.VAL IS NULL AND :I$MIDDLENAME IS NULL) OR (UPPER(M.VAL) = UPPER(TRIM(:I$MIDDLENAME))))
          AND (:I$DOB IS NULL OR D.VAL = :I$DOB)
      INTO :IS_DUPLICATE;

  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PUPIL_DUPLICATE_LIST (
    I$OBJ_ID BIGINT,
    I$PUPIL_ID BIGINT,
    I$LASTNAME VARCHAR(255),
    I$FIRSTNAME VARCHAR(255),
    I$MIDDLENAME VARCHAR(255),
    I$DOB DATE)
RETURNS (
    PUPIL_ID BIGINT,
    PASSPORT_ID BIGINT,
    LASTNAME VARCHAR(100),
    FIRSTNAME VARCHAR(100),
    MIDDLENAME VARCHAR(100),
    DOB DATE,
    SCHOOL_CAPTION VARCHAR(1000),
    SCHOOL_DIST VARCHAR(1000),
    LINK_ID BIGINT,
    CURRENT_CLASS_ID BIGINT,
    CURRENT_CLASS_TYPE_ID BIGINT,
    CLASS_NAME VARCHAR(1000))
AS
declare variable V$TYPE char(1);
BEGIN
  IF(CHAR_LENGTH(I$MIDDLENAME) = 0) THEN I$MIDDLENAME = NULL;

  -- По-разному ищем учащихся в УДОД и ДПО
  SELECT STATUS FROM OU_LICENCE_TYPE INTO :V$TYPE;

  IF(V$TYPE = 'P') THEN
  BEGIN

      -- ДПО: Ищем по всем коллективам, в том числе уже окончивших
      FOR
          SELECT DISTINCT L10.OBJ_ID, CAST(L.VAL AS VARCHAR(100)), CAST(F.VAL AS VARCHAR(100)), CAST(M.VAL AS VARCHAR(100)), D.VAL,
            (SELECT FIRST 1 L79.OBJ_ID FROM LINKS L79 WHERE L79.PARENT_ID = L10.OBJ_ID AND L79.OBJ_TYPE_ID = 79 AND L79.DATE_DEL IS NULL)
          FROM LINKS L10
          JOIN VALS L ON L.OBJ_ID = L10.OBJ_ID AND L.PARAM_ID = 55 AND L.IS_DEL = 0
          JOIN VALS F ON F.OBJ_ID = L10.OBJ_ID AND F.PARAM_ID = 56 AND F.IS_DEL = 0
          LEFT JOIN VALS M ON M.OBJ_ID = L10.OBJ_ID AND M.PARAM_ID = 57 AND M.IS_DEL = 0
          LEFT JOIN VALD D ON D.OBJ_ID = L10.OBJ_ID AND D.PARAM_ID = 89 AND D.IS_DEL = 0
          WHERE L10.PARENT_TYPE_ID = 46 AND L10.OBJ_TYPE_ID = 10
              AND UPPER(L.VAL) = UPPER(TRIM(:I$LASTNAME))
              AND UPPER(F.VAL) = UPPER(TRIM(:I$FIRSTNAME))
              AND ((:I$MIDDLENAME IS NULL) OR (UPPER(M.VAL) = UPPER(TRIM(:I$MIDDLENAME))))
              AND (:I$DOB IS NULL OR D.VAL = :I$DOB)
          INTO :PUPIL_ID, :LASTNAME, :FIRSTNAME, :MIDDLENAME, :DOB, :PASSPORT_ID
      DO
      BEGIN
          LINK_ID = NULL;

          SELECT FIRST 1 LINK_ID
          FROM LINKS
          WHERE PARENT_ID = :I$OBJ_ID AND OBJ_ID = :PUPIL_ID AND DATE_DEL IS NULL
          INTO :LINK_ID;

          SUSPEND;
      END

  END
  ELSE IF(V$TYPE = 'O') THEN
  BEGIN

      -- Для школ ищем вообще везде, включая экстернатников из небытия

      FOR
          SELECT DISTINCT L10.OBJ_ID, CAST(L.VAL AS VARCHAR(100)), CAST(F.VAL AS VARCHAR(100)), CAST(M.VAL AS VARCHAR(100)), D.VAL,
            (SELECT FIRST 1 L79.OBJ_ID FROM LINKS L79 WHERE L79.PARENT_ID = L10.OBJ_ID AND L79.OBJ_TYPE_ID = 79 AND L79.DATE_DEL IS NULL)
          FROM OBJECTS L10
          JOIN VALS L ON L.OBJ_ID = L10.OBJ_ID AND L.PARAM_ID = 55 AND L.IS_DEL = 0
          JOIN VALS F ON F.OBJ_ID = L10.OBJ_ID AND F.PARAM_ID = 56 AND F.IS_DEL = 0
          LEFT JOIN VALS M ON M.OBJ_ID = L10.OBJ_ID AND M.PARAM_ID = 57 AND M.IS_DEL = 0
          LEFT JOIN VALD D ON D.OBJ_ID = L10.OBJ_ID AND D.PARAM_ID = 89 AND D.IS_DEL = 0
          WHERE L10.TYPE_ID = 10
              AND UPPER(L.VAL) = UPPER(TRIM(:I$LASTNAME))
              AND UPPER(F.VAL) = UPPER(TRIM(:I$FIRSTNAME))
              AND ((:I$MIDDLENAME IS NULL) OR (UPPER(M.VAL) = UPPER(TRIM(:I$MIDDLENAME))))
              AND (:I$DOB IS NULL OR D.VAL = :I$DOB)
          INTO :PUPIL_ID, :LASTNAME, :FIRSTNAME, :MIDDLENAME, :DOB, :PASSPORT_ID
      DO
      BEGIN
          LINK_ID = NULL;

          SELECT FIRST 1 LINK_ID
          FROM LINKS
          WHERE PARENT_ID = :I$OBJ_ID AND OBJ_ID = :PUPIL_ID AND DATE_DEL IS NULL
          INTO :LINK_ID;

          CURRENT_CLASS_ID = NULL;
          CURRENT_CLASS_TYPE_ID = NULL;
          CLASS_NAME = NULL;

          SELECT FIRST 1 LPC.PARENT_ID, LPC.PARENT_TYPE_ID, C.CAPTION
          FROM LINKS LPC
          LEFT JOIN OBJECT_CAPTION_GET(LPC.PARENT_ID) C ON 1 = 1
          WHERE LPC.OBJ_ID = :PUPIL_ID AND LPC.PARENT_TYPE_ID IN (9, 187, 81, 82, 83) AND LPC.DATE_DEL IS NULL
          INTO :CURRENT_CLASS_ID, :CURRENT_CLASS_TYPE_ID, :CLASS_NAME;

          SUSPEND;
      END

  END
  ELSE
  BEGIN

      -- УДОД - пока ищем только по живым коллективам

      FOR
          SELECT DISTINCT LP243.OBJ_ID, CAST(L.VAL AS VARCHAR(100)), CAST(F.VAL AS VARCHAR(100)), CAST(M.VAL AS VARCHAR(100)), D.VAL,
            (SELECT FIRST 1 L79.OBJ_ID FROM LINKS L79 WHERE L79.PARENT_ID = LP243.OBJ_ID AND L79.OBJ_TYPE_ID = 79 AND L79.DATE_DEL IS NULL)
          FROM LINKS LP243
          JOIN LINKS LP242 ON LP242.OBJ_ID = LP243.PARENT_ID AND LP242.PARENT_TYPE_ID = 242 AND LP242.DATE_DEL IS NULL
          JOIN LINKS LP2_or_211 ON LP2_or_211.OBJ_ID = LP242.PARENT_ID AND LP2_or_211.PARENT_TYPE_ID IN (2, 211) AND LP2_or_211.DATE_DEL IS NULL
          JOIN VALS L ON L.OBJ_ID = LP243.OBJ_ID AND L.PARAM_ID = 55 AND L.IS_DEL = 0
          JOIN VALS F ON F.OBJ_ID = LP243.OBJ_ID AND F.PARAM_ID = 56 AND F.IS_DEL = 0
          LEFT JOIN VALS M ON M.OBJ_ID = LP243.OBJ_ID AND M.PARAM_ID = 57 AND M.IS_DEL = 0
          LEFT JOIN VALD D ON D.OBJ_ID = LP243.OBJ_ID AND D.PARAM_ID = 89 AND D.IS_DEL = 0
          WHERE LP243.OBJ_TYPE_ID = 10 AND LP243.PARENT_TYPE_ID = 243 AND LP243.DATE_DEL IS NULL AND ((:I$PUPIL_ID IS NULL) OR (LP243.OBJ_ID <> :I$PUPIL_ID))
              AND UPPER(L.VAL) = UPPER(TRIM(:I$LASTNAME))
              AND UPPER(F.VAL) = UPPER(TRIM(:I$FIRSTNAME))
              AND ((:I$MIDDLENAME IS NULL) OR (UPPER(M.VAL) = UPPER(TRIM(:I$MIDDLENAME))))
              AND (:I$DOB IS NULL OR D.VAL = :I$DOB)
          INTO :PUPIL_ID, :LASTNAME, :FIRSTNAME, :MIDDLENAME, :DOB, :PASSPORT_ID
      DO
      BEGIN
          SELECT V FROM VAL_GET(:PUPIL_ID, 117) INTO :SCHOOL_CAPTION;
          SELECT V FROM VAL_GET(:PUPIL_ID, 1345) INTO :SCHOOL_DIST;

          LINK_ID = NULL;

          SELECT FIRST 1 LINK_ID
          FROM LINKS
          WHERE PARENT_ID = :I$OBJ_ID AND OBJ_ID = :PUPIL_ID AND DATE_DEL IS NULL
          INTO :LINK_ID;

          SUSPEND;
      END
  END

END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PUPIL_GPD_LIST_BY_DATE (
    I$SCHOOL_ID BIGINT,
    I$DT DATE)
RETURNS (
    PUPIL_ID BIGINT,
    GRADE_ID BIGINT,
    GRADE_LV BIGINT,
    GPD_ID BIGINT)
AS
declare variable I$DT_REAL date;
declare variable EVENT_TYPE bigint;
declare variable I$SCHOOL_ID2 bigint;
begin

    I$SCHOOL_ID = I$SCHOOL_ID / 1000000000;
    I$SCHOOL_ID2 = I$SCHOOL_ID + 1;
    I$SCHOOL_ID = I$SCHOOL_ID * 1000000000;
    I$SCHOOL_ID2 = I$SCHOOL_ID2 * 1000000000;

    FOR
        SELECT DISTINCT M.PERSON_ID
        FROM PERSON_MOVEMENTS M
        JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 46
        WHERE M.DATE_DEL IS NULL
          AND M.OBJ_ID >= :I$SCHOOL_ID AND M.OBJ_ID < :I$SCHOOL_ID2
          AND M.DATE_IN <= :I$DT AND (M.DATE_OUT IS NULL OR M.DATE_OUT > :I$DT)
        INTO :PUPIL_ID
    DO
    BEGIN

        GPD_ID = NULL;
        GRADE_ID = NULL;
        GRADE_LV = NULL;

        SELECT FIRST 1 M.GROUP_ID, M.STAGE_ID
        FROM PERSON_MOVEMENTS M
        JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 46
        -- Только тип = ГПД
        JOIN VALL V369 ON V369.OBJ_ID = M.GROUP_ID AND V369.PARAM_ID = 369 AND V369.IS_DEL = 0 AND V369.LISTVAL_ID = 1246
        WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :PUPIL_ID
          AND M.DATE_IN <= :I$DT AND (M.DATE_OUT IS NULL OR M.DATE_OUT > :I$DT)
        INTO :GPD_ID, :GRADE_LV;

        IF(GPD_ID IS NOT NULL) THEN SUSPEND;

    END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PUPIL_GROUP_ACCEPT (
    I$STUDENT_ID BIGINT,
    I$GROUPS VARCHAR(400),
    I$ORDER_ID BIGINT = null)
RETURNS (
    OBJ_ID BIGINT,
    MOVE_ID BIGINT)
AS
declare variable V$CURRENT_PARENT bigint;
declare variable V$REASON bigint;
declare variable V$DATE date;
declare variable V$ORDER_DATE date;
declare variable V$ORDER_NUM varchar(400);
declare variable V$ORDER_ID bigint;
declare variable V$ORDER_ROW bigint;
declare variable V$USER_ID bigint;
declare variable V$OLD_GROUPS varchar(400);
begin

  -- I$ORDER_ID указывается когда делается проводка приказа

  -- Куда только что зачислили ?
  SELECT FIRST 1 L.PARENT_TYPE_ID
  FROM LINKS L
  WHERE L.OBJ_ID = :I$STUDENT_ID AND L.PARENT_TYPE_ID IN (9, 125, 187, 277) AND L.DATE_DEL IS NULL
  INTO :V$CURRENT_PARENT;

  -- Если есть только черновик приказа - движения по нему еще нет
  SELECT FIRST 1 OD.OBJ_ID, OD.DST_GROUPS
  FROM ORDER_DATA OD
  JOIN ORDERS O ON O.OBJ_ID = OD.ORDER_ID AND O.DATE_DEL IS NULL AND O.STATE_ID = 11716 AND O.TYPE_ID IN (12929, 12930, 12931, 12937, 12964)
  WHERE OD.DATE_DEL IS NULL AND OD.REF_ID = :I$STUDENT_ID
  INTO :V$ORDER_ROW, :V$OLD_GROUPS;

  -- Для предварительного приема, а также если приказ на несколько учеников - только сохраняем, для остальных сразу же исполняем
  -- В случае если есть приказ - прописываем ученика в нем
  IF(V$CURRENT_PARENT IS NULL OR V$CURRENT_PARENT = 277) THEN
  BEGIN
    -- Есть черновик приказа - отмечаем в нем, не выполняя само зачисление
    IF(COALESCE(V$OLD_GROUPS, '') <> COALESCE(I$GROUPS, '')) THEN
    BEGIN
      IF(V$ORDER_ROW IS NULL) THEN EXCEPTION DATA_ERROR 'Для сохранения групп зачисления должен быть создан индивидуальный или указан групповой приказ';

      UPDATE ORDER_DATA
      SET DST_GROUPS = :I$GROUPS
      WHERE OBJ_ID = :V$ORDER_ROW;
    END
  END
  ELSE IF(I$ORDER_ID IS NULL AND V$ORDER_ROW IS NOT NULL) THEN
  BEGIN
    -- Есть черновик приказа - отмечаем в нем, не выполняя само зачисление
    IF(COALESCE(V$OLD_GROUPS, '') <> COALESCE(I$GROUPS, '')) THEN
    BEGIN
      UPDATE ORDER_DATA
      SET DST_GROUPS = :I$GROUPS
      WHERE OBJ_ID = :V$ORDER_ROW;
    END
  END
  ELSE
  BEGIN

    -- Реквизиты последнего зачисления
    SELECT FIRST 1 M.REASON_IN, M.DATE_IN, M.ORDER_DATE_IN, M.ORDER_NUM_IN, M.ORDER_ID_IN, M.USER_IN
    FROM PERSON_MOVEMENTS M
    JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID IN (9, 125, 187)
    WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :I$STUDENT_ID AND M.DATE_OUT IS NULL
    INTO :V$REASON, :V$DATE, :V$ORDER_DATE, :V$ORDER_NUM, :V$ORDER_ID, :V$USER_ID;

    FOR
      SELECT ID
      FROM EXPLODE_STR(:I$GROUPS, ',')
      INTO :OBJ_ID
    DO
    BEGIN
      SELECT OBJ_ID
      FROM VARGRP_MOVE_PUPIL(:I$STUDENT_ID, :OBJ_ID, :V$ORDER_NUM, :V$ORDER_DATE, :V$DATE, 0, :V$USER_ID, :V$ORDER_ID, :V$REASON)
      INTO :MOVE_ID;

      SUSPEND;
    END

  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PUPIL_LEAVED_INFO_GET (
    I$PUPIL_ID BIGINT)
RETURNS (
    LEAVED_INFO VARCHAR(1000))
AS
declare variable V$433 varchar(1000);
declare variable V$434 varchar(1000);
declare variable V$435 varchar(1000);
BEGIN
    FOR
        SELECT FIRST 1 (SELECT DT FROM CURRENT_DATE_GET(M.DATE_OUT, 'DD.MM.YY')), M.ORDER_NUM_OUT, (SELECT DT FROM CURRENT_DATE_GET(M.ORDER_DATE_OUT, 'DD.MM.YY'))
        FROM LINKS L10
        JOIN PERSON_MOVEMENTS M ON M.DATE_DEL IS NULL AND M.PERSON_ID = L10.OBJ_ID AND M.DATE_OUT IS NOT NULL
        JOIN OBJECTS O ON O.OBJ_ID = M.GROUP_ID AND O.TYPE_ID = 9
        LEFT JOIN LISTVALS LV ON LV.LISTVAL_ID = M.REASON_OUT AND LV."FILTER" SIMILAR TO 'LEAVED%' AND LV.IS_DEL = 0
        WHERE L10.OBJ_ID = :I$PUPIL_ID AND L10.PARENT_TYPE_ID = 82 AND L10.DATE_DEL IS NULL
        ORDER BY M.DATE_OUT DESC
        INTO :V$433, :V$434, :V$435
    DO
    BEGIN
        LEAVED_INFO = 'выбыл';
        IF (:V$433 IS NOT NULL) THEN
        BEGIN
            LEAVED_INFO = :LEAVED_INFO || ' ' || :V$433 || 'г.';
        END

        IF (:V$434 IS NOT NULL OR :V$435 IS NOT NULL) THEN
        BEGIN
            IF (:V$433 IS NOT NULL) THEN
            BEGIN
                SUSPEND;
            END
            ELSE
            BEGIN
                LEAVED_INFO = :LEAVED_INFO || ', ';
            END
            LEAVED_INFO = 'приказ';

            IF (:V$434 IS NOT NULL) THEN
            BEGIN
                LEAVED_INFO = :LEAVED_INFO || ' № ' || :V$434;
            END

            IF (:V$435 IS NOT NULL) THEN
            BEGIN
                LEAVED_INFO = :LEAVED_INFO || ' от ' || :V$435 || 'г.';
            END
        END
        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PUPIL_LIST_BY_DATE (
    I$SCHOOL_ID BIGINT,
    CLASS_TYPE_MIN BIGINT,
    CLASS_TYPE_MAX BIGINT,
    I$DT DATE,
    I$IS_HOME SMALLINT = NULL)
RETURNS (
    PUPIL_ID BIGINT,
    GRADE_ID BIGINT,
    GRADE_LV BIGINT)
AS
DECLARE VARIABLE I$SCHOOL_ID2 BIGINT;
DECLARE VARIABLE I$DT_REAL DATE;
DECLARE VARIABLE V$CURRENT_YEAR INTEGER;
DECLARE VARIABLE V$CURRENT_CAL_YEAR INTEGER;
DECLARE VARIABLE V$PLACE_ID BIGINT;
DECLARE VARIABLE V$MOVE_ID BIGINT;
begin

    I$SCHOOL_ID = I$SCHOOL_ID / 1000000000;
    I$SCHOOL_ID2 = I$SCHOOL_ID + 1;
    I$SCHOOL_ID = I$SCHOOL_ID * 1000000000;
    I$SCHOOL_ID2 = I$SCHOOL_ID2 * 1000000000;

    FOR
        SELECT DISTINCT M.PERSON_ID
        FROM PERSON_MOVEMENTS M
        LEFT JOIN VALL V2169 ON V2169.OBJ_ID = M.PERSON_ID AND V2169.PARAM_ID = 2169 AND V2169.IS_DEL = 0
        WHERE M.DATE_DEL IS NULL AND M.GROUP_TYPE_ID = 9
          AND M.OBJ_ID >= :I$SCHOOL_ID AND M.OBJ_ID < :I$SCHOOL_ID2
          AND M.DATE_IN <= :I$DT AND (M.DATE_OUT IS NULL OR M.DATE_OUT > :I$DT)
          AND (:I$IS_HOME IS NULL OR (:I$IS_HOME = 1 AND V2169.LISTVAL_ID = 2) OR (:I$IS_HOME = 0 AND (V2169.LISTVAL_ID IS NULL OR V2169.LISTVAL_ID = 3)))
        INTO :PUPIL_ID
    DO
    BEGIN

        GRADE_ID = NULL;
        GRADE_LV = NULL;

        SELECT FIRST 1 M.GROUP_ID, M.STAGE_ID
        FROM PERSON_MOVEMENTS M
        LEFT JOIN VALL V2169 ON V2169.OBJ_ID = M.PERSON_ID AND V2169.PARAM_ID = 2169 AND V2169.IS_DEL = 0
        -- Тип класса
        JOIN VALL V592 ON V592.OBJ_ID = M.GROUP_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND (V592.LISTVAL_ID >= :CLASS_TYPE_MIN AND V592.LISTVAL_ID <= :CLASS_TYPE_MAX)
        WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :PUPIL_ID AND M.GROUP_TYPE_ID = 9
          AND M.DATE_IN <= :I$DT AND (M.DATE_OUT IS NULL OR M.DATE_OUT > :I$DT)
          AND (:I$IS_HOME IS NULL OR (:I$IS_HOME = 1 AND V2169.LISTVAL_ID = 2) OR (:I$IS_HOME = 0 AND (V2169.LISTVAL_ID IS NULL OR V2169.LISTVAL_ID = 3)))
        INTO :GRADE_ID, :GRADE_LV;

        IF(GRADE_ID IS NOT NULL) THEN SUSPEND;

    END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PUPIL_MOVEMENT_LIST (
    I$PUPIL_ID BIGINT)
RETURNS (
    MOVEMENT_ID BIGINT,
    CLASS_ID BIGINT,
    MOVEMENT_TYPE VARCHAR(80),
    MOVEMENT_DATE DATE,
    MOVEMENT_ORDER_NUMBER VARCHAR(50),
    MOVEMENT_ORDER_DATE DATE,
    MOVEMENT_TO_STAGE VARCHAR(80),
    MOVEMENT_TO_CLASS VARCHAR(400),
    MOVEMENT_RECORD_TYPE VARCHAR(80),
    ENABLED SMALLINT,
    GROUPING_NAME VARCHAR(400))
AS
declare variable V$STUDY_DATE_START date;
declare variable V$MOVEMENT_TYPE bigint;
declare variable V$MOVEMENT_TO_STAGE bigint;
declare variable V$MOVEMENT_RECORD_TYPE bigint;
BEGIN
    -- Текущий учебный год из настроек движения
    SELECT FIRST 1 LV.TAG
    FROM LINKS L2
    JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :V$STUDY_DATE_START;

    IF(V$STUDY_DATE_START IS NULL) THEN EXCEPTION DATA_ERROR 'Не указан учебный год в настройках организации';

    -- Сортируем по дате движения, затем по ID линка если что-то слетело
    FOR
        SELECT M.OBJ_ID, M.DATE_IN, M.REASON_IN, M.ORDER_NUM_IN, M.ORDER_DATE_IN, M.STAGE_ID, M.GROUP_ID, M.NAME_IN, 903, NULL
        FROM PERSON_MOVEMENTS M
        JOIN OBJECTS O ON O.OBJ_ID = M.GROUP_ID AND O.TYPE_ID IN (9, 187, 289)
        WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :I$PUPIL_ID
        UNION
        SELECT M.OBJ_ID, M.DATE_OUT, M.REASON_OUT, M.ORDER_NUM_OUT, M.ORDER_DATE_OUT, M.STAGE_ID, M.GROUP_ID, 'Выбытие из ' || M.NAME_IN, 903, NULL
        FROM PERSON_MOVEMENTS M
        JOIN OBJECTS O ON O.OBJ_ID = M.GROUP_ID AND O.TYPE_ID IN (9, 187, 289)
        WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :I$PUPIL_ID AND M.DATE_OUT IS NOT NULL
        ORDER BY 2, 1
        INTO :MOVEMENT_ID, :MOVEMENT_DATE, :V$MOVEMENT_TYPE, :MOVEMENT_ORDER_NUMBER, :MOVEMENT_ORDER_DATE, :V$MOVEMENT_TO_STAGE, :CLASS_ID,
            :MOVEMENT_TO_CLASS, :V$MOVEMENT_RECORD_TYPE, :GROUPING_NAME
    DO
    BEGIN
        IF ((CLASS_ID IS NOT NULL) AND (MOVEMENT_DATE >= V$STUDY_DATE_START)) THEN ENABLED = 1; ELSE ENABLED = 0;

        SELECT VAL FROM LISTVAL_TEXT(:V$MOVEMENT_TYPE) INTO :MOVEMENT_TYPE;
        SELECT VAL FROM LISTVAL_TEXT(:V$MOVEMENT_TO_STAGE) INTO :MOVEMENT_TO_STAGE;
        SELECT VAL FROM LISTVAL_TEXT(:V$MOVEMENT_RECORD_TYPE) INTO :MOVEMENT_RECORD_TYPE;
        GROUPING_NAME = MOVEMENT_TO_CLASS;

        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PUPIL_PARENTS_DUPLICATE_CHECK (
    I$PUPIL_ID BIGINT,
    I$PARENTS_ID BIGINT,
    I$FIRSTNAME VARCHAR(255),
    I$MIDDLENAME VARCHAR(255),
    I$LASTNAME VARCHAR(255),
    I$DOB DATE)
RETURNS (
    IS_DUPLICATE SMALLINT)
AS
declare variable V$SCHOOL_ID bigint;
begin
    FOR
        SELECT FIRST 1
               OBJ_ID
        FROM OBJECT_PARENTS_GET(:I$PUPIL_ID, 2)
        INTO :V$SCHOOL_ID
    DO
    BEGIN
        FOR
            SELECT COUNT(*)
            FROM LINKS L7

            JOIN LINKS L8
            ON L8.PARENT_ID = L7.OBJ_ID
            AND L8.OBJ_TYPE_ID = 8
            AND L8.DATE_DEL IS NULL

            JOIN LINKS L9
            ON L9.PARENT_ID = L8.OBJ_ID
            AND L9.OBJ_TYPE_ID = 9
            AND L9.DATE_DEL IS NULL

            JOIN LINKS L10
            ON L10.PARENT_ID = L9.OBJ_ID
            AND L10.OBJ_TYPE_ID = 10
            AND L10.DATE_DEL IS NULL

            JOIN LINKS L20
            ON L20.PARENT_ID = L10.OBJ_ID
            AND L20.OBJ_TYPE_ID = 20
            AND L20.DATE_DEL IS NULL

            JOIN VALS L
            ON L.OBJ_ID = L20.OBJ_ID
            AND L.PARAM_ID = 128
            AND L.IS_DEL = 0

            JOIN VALS F
            ON F.OBJ_ID = L20.OBJ_ID
            AND F.PARAM_ID = 129
            AND F.IS_DEL = 0

            LEFT JOIN VALS M
            ON M.OBJ_ID = L20.OBJ_ID
            AND M.PARAM_ID = 130
            AND M.IS_DEL = 0

            LEFT JOIN VALD D
            ON D.OBJ_ID = L20.OBJ_ID
            AND D.PARAM_ID = 143
            AND D.IS_DEL = 0

            WHERE L7.PARENT_ID = :V$SCHOOL_ID
            AND L7.OBJ_TYPE_ID = 7
            AND L7.DATE_DEL IS NULL
            AND ((:I$PARENTS_ID IS NULL) OR (L20.OBJ_ID <> :I$PARENTS_ID))

            AND L.VAL LIKE :I$LASTNAME
            AND F.VAL LIKE :I$FIRSTNAME
            AND M.VAL LIKE :I$MIDDLENAME
            AND D.VAL = :I$DOB

            INTO :IS_DUPLICATE
        DO
        BEGIN
            SUSPEND;
        END
    END        
end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PUPIL_PARENTS_LIST (
    I$PUPIL_ID BIGINT,
    I$PARENTS_ID BIGINT,
    I$LASTNAME VARCHAR(255),
    I$FIRSTNAME VARCHAR(255),
    I$MIDDLENAME VARCHAR(255),
    I$DOB DATE,
    I$SHOW_EMPLOYEE SMALLINT = 0)
RETURNS (
    STATUS VARCHAR(255),
    PARENT_ID BIGINT,
    PASSPORT_ID BIGINT,
    IS_EMPLOYEE SMALLINT,
    LASTNAME VARCHAR(100),
    FIRSTNAME VARCHAR(100),
    MIDDLENAME VARCHAR(100),
    DOB DATE,
    ADRESS VARCHAR(1000))
AS
declare variable V$SCHOOL_ID bigint;
BEGIN
    FOR
        SELECT FIRST 1
               OBJ_ID
        FROM OBJECT_PARENTS_GET(:I$PUPIL_ID, 2)
        INTO :V$SCHOOL_ID
    DO
    BEGIN
        FOR
            SELECT DISTINCT
                   L20.OBJ_ID,
                   (SELECT FIRST 1 L79.OBJ_ID FROM LINKS L79 WHERE L79.PARENT_ID = L20.OBJ_ID AND L79.OBJ_TYPE_ID = 79 AND L79.DATE_DEL IS NULL),
                   0,
                   CAST(L.VAL AS VARCHAR(100)),
                   CAST(F.VAL AS VARCHAR(100)),
                   CAST(M.VAL AS VARCHAR(100)),
                   D.VAL,
                   CAST(A.VAL AS VARCHAR(1000)),
                   'Родитель'
            FROM LINKS L211

            JOIN LINKS L242
            ON L242.PARENT_ID = L211.OBJ_ID
            AND L242.OBJ_TYPE_ID = 242
            AND L242.DATE_DEL IS NULL

            JOIN LINKS L243
            ON L243.PARENT_ID = L242.OBJ_ID
            AND L243.OBJ_TYPE_ID = 243
            AND L243.DATE_DEL IS NULL

            JOIN LINKS L10
            ON L10.PARENT_ID = L243.OBJ_ID
            AND L10.OBJ_TYPE_ID = 10
            AND L10.DATE_DEL IS NULL

            JOIN LINKS L20
            ON L20.PARENT_ID = L10.OBJ_ID
            AND L20.OBJ_TYPE_ID = 20
            AND L20.DATE_DEL IS NULL

            JOIN VALS L
            ON L.OBJ_ID = L20.OBJ_ID
            AND L.PARAM_ID = 128
            AND L.IS_DEL = 0

            JOIN VALS F
            ON F.OBJ_ID = L20.OBJ_ID
            AND F.PARAM_ID = 129
            AND F.IS_DEL = 0

            LEFT JOIN VALS M
            ON M.OBJ_ID = L20.OBJ_ID
            AND M.PARAM_ID = 130
            AND M.IS_DEL = 0

            LEFT JOIN VALD D
            ON D.OBJ_ID = L20.OBJ_ID
            AND D.PARAM_ID = 143
            AND D.IS_DEL = 0

            LEFT JOIN ADR_GET(147, L20.OBJ_ID, 0) AS A
            ON 1=1

            WHERE L211.PARENT_ID = :V$SCHOOL_ID
            AND L211.OBJ_TYPE_ID = 211
            AND L211.DATE_DEL IS NULL
            AND ((:I$PARENTS_ID IS NULL) OR (L20.OBJ_ID <> :I$PARENTS_ID))

            AND L.VAL LIKE :I$LASTNAME
            AND F.VAL LIKE :I$FIRSTNAME
            AND ((:I$MIDDLENAME IS NULL) OR (M.VAL LIKE :I$MIDDLENAME))
            AND ((:I$DOB IS NULL) OR (D.VAL = :I$DOB))

            UNION ALL

            SELECT DISTINCT
                   L20.OBJ_ID,
                   (SELECT FIRST 1 L79.OBJ_ID FROM LINKS L79 WHERE L79.PARENT_ID = L20.OBJ_ID AND L79.OBJ_TYPE_ID = 79 AND L79.DATE_DEL IS NULL),
                   0,
                   CAST(L.VAL AS VARCHAR(100)),
                   CAST(F.VAL AS VARCHAR(100)),
                   CAST(M.VAL AS VARCHAR(100)),
                   D.VAL,
                   CAST(A.VAL AS VARCHAR(1000)),
                   'Родитель'
            FROM LINKS L7

            JOIN LINKS L8
            ON L8.PARENT_ID = L7.OBJ_ID
            AND L8.OBJ_TYPE_ID = 8
            AND L8.DATE_DEL IS NULL

            JOIN LINKS L9
            ON L9.PARENT_ID = L8.OBJ_ID
            AND L9.OBJ_TYPE_ID IN (9, 187)
            AND L9.DATE_DEL IS NULL

            JOIN LINKS L10
            ON L10.PARENT_ID = L9.OBJ_ID
            AND L10.OBJ_TYPE_ID = 10
            AND L10.DATE_DEL IS NULL

            JOIN LINKS L20
            ON L20.PARENT_ID = L10.OBJ_ID
            AND L20.OBJ_TYPE_ID = 20
            AND L20.DATE_DEL IS NULL

            JOIN VALS L
            ON L.OBJ_ID = L20.OBJ_ID
            AND L.PARAM_ID = 128
            AND L.IS_DEL = 0

            JOIN VALS F
            ON F.OBJ_ID = L20.OBJ_ID
            AND F.PARAM_ID = 129
            AND F.IS_DEL = 0

            LEFT JOIN VALS M
            ON M.OBJ_ID = L20.OBJ_ID
            AND M.PARAM_ID = 130
            AND M.IS_DEL = 0

            LEFT JOIN VALD D
            ON D.OBJ_ID = L20.OBJ_ID
            AND D.PARAM_ID = 143
            AND D.IS_DEL = 0

            LEFT JOIN ADR_GET(147, L20.OBJ_ID, 0) AS A
            ON 1=1

            WHERE L7.PARENT_ID = :V$SCHOOL_ID
            AND L7.OBJ_TYPE_ID = 7
            AND L7.DATE_DEL IS NULL
            AND ((:I$PARENTS_ID IS NULL) OR (L20.OBJ_ID <> :I$PARENTS_ID))

            AND L.VAL LIKE :I$LASTNAME
            AND F.VAL LIKE :I$FIRSTNAME
            AND ((:I$MIDDLENAME IS NULL) OR (M.VAL LIKE :I$MIDDLENAME))
            AND ((:I$DOB IS NULL) OR (D.VAL = :I$DOB))

            UNION ALL

            SELECT L14.OBJ_ID,
                   (SELECT FIRST 1 L79.OBJ_ID FROM LINKS L79 WHERE L79.PARENT_ID = L14.OBJ_ID AND L79.OBJ_TYPE_ID = 79 AND L79.DATE_DEL IS NULL),
                   1,
                   CAST(L.VAL AS VARCHAR(100)),
                   CAST(F.VAL AS VARCHAR(100)),
                   CAST(M.VAL AS VARCHAR(100)),
                   D.VAL,
                   CAST(A.VAL AS VARCHAR(1000)),
                   'Сотрудник'
            FROM LINKS l14

            JOIN VALS L
            ON L.OBJ_ID = L14.OBJ_ID
            AND L.PARAM_ID = 59
            AND L.IS_DEL = 0

            JOIN VALS F
            ON F.OBJ_ID = L14.OBJ_ID
            AND F.PARAM_ID = 60
            AND F.IS_DEL = 0

            LEFT JOIN VALS M
            ON M.OBJ_ID = L14.OBJ_ID
            AND M.PARAM_ID = 61
            AND M.IS_DEL = 0

            LEFT JOIN VALD D
            ON D.OBJ_ID = L14.OBJ_ID
            AND D.PARAM_ID = 241
            AND D.IS_DEL = 0

            LEFT JOIN ADR_GET(255, L14.OBJ_ID, 0) AS A
            ON 1=1

            WHERE :I$SHOW_EMPLOYEE = 1
            AND L14.PARENT_ID = :V$SCHOOL_ID
            AND L14.OBJ_TYPE_ID = 14
            AND L14.DATE_DEL IS NULL

            AND L.VAL LIKE :I$LASTNAME
            AND F.VAL LIKE :I$FIRSTNAME
            AND ((:I$MIDDLENAME IS NULL) OR (M.VAL LIKE :I$MIDDLENAME))
            AND ((:I$DOB IS NULL) OR (D.VAL = :I$DOB))

            UNION ALL

            SELECT L14.OBJ_ID,
                   (SELECT FIRST 1 L79.OBJ_ID FROM LINKS L79 WHERE L79.PARENT_ID = L14.OBJ_ID AND L79.OBJ_TYPE_ID = 79 AND L79.DATE_DEL IS NULL),
                   1,
                   CAST(L.VAL AS VARCHAR(100)),
                   CAST(F.VAL AS VARCHAR(100)),
                   CAST(M.VAL AS VARCHAR(100)),
                   D.VAL,
                   CAST(A.VAL AS VARCHAR(1000)),
                   'Сотрудник'
            FROM LINKS L211

            JOIN LINKS l14
            ON L14.PARENT_ID = L211.OBJ_ID
            AND L14.OBJ_TYPE_ID = 14
            AND L14.DATE_DEL IS NULL

            JOIN VALS L
            ON L.OBJ_ID = L14.OBJ_ID
            AND L.PARAM_ID = 59
            AND L.IS_DEL = 0

            JOIN VALS F
            ON F.OBJ_ID = L14.OBJ_ID
            AND F.PARAM_ID = 60
            AND F.IS_DEL = 0

            LEFT JOIN VALS M
            ON M.OBJ_ID = L14.OBJ_ID
            AND M.PARAM_ID = 61
            AND M.IS_DEL = 0

            LEFT JOIN VALD D
            ON D.OBJ_ID = L14.OBJ_ID
            AND D.PARAM_ID = 241
            AND D.IS_DEL = 0

            LEFT JOIN ADR_GET(255, L14.OBJ_ID, 0) AS A
            ON 1=1

            WHERE :I$SHOW_EMPLOYEE = 1
            AND L211.PARENT_ID = :V$SCHOOL_ID
            AND L211.OBJ_TYPE_ID = 211
            AND L211.DATE_DEL IS NULL

            AND L.VAL LIKE :I$LASTNAME
            AND F.VAL LIKE :I$FIRSTNAME
            AND ((:I$MIDDLENAME IS NULL) OR (M.VAL LIKE :I$MIDDLENAME))
            AND ((:I$DOB IS NULL) OR (D.VAL = :I$DOB))

            INTO :PARENT_ID,
                 :PASSPORT_ID,
                 :IS_EMPLOYEE,
                 :LASTNAME,
                 :FIRSTNAME,
                 :MIDDLENAME,
                 :DOB,
                 :ADRESS,
                 :STATUS
        DO
        BEGIN
            SUSPEND;
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE PUPIL_REGION_COUNT_GET (
    I$DT DATE,
    I$USER_ID BIGINT)
RETURNS (
    DISTRICT_NAME VARCHAR(255),
    PART1P1 INTEGER,
    PART1P2 INTEGER,
    PART1P3 INTEGER,
    PART1P4 INTEGER,
    PART1P5 INTEGER,
    PART1P6 INTEGER,
    PART1P7 INTEGER,
    PART1P8 INTEGER,
    PART1ALL INTEGER,
    PART2P1 INTEGER,
    PART2P2 INTEGER,
    PART2P3 INTEGER,
    PART2P4 INTEGER,
    PART2ALL INTEGER,
    PART3P1 INTEGER,
    PART3P2 INTEGER,
    PART3P3 INTEGER,
    PART3ALL INTEGER,
    COUNT_ALL INTEGER)
AS
declare variable V$DISTRICT_ID bigint;
declare variable V$OU_ID bigint;
declare variable V$OU_TYPE integer;
declare variable V$SCHOOLAR_ID bigint;
declare variable V$LISTVAL_ID bigint;
declare variable V$OU_KIND integer;
declare variable V$COUNT integer;
declare variable V$ALLPART1P1 integer;
declare variable V$ALLPART1P2 integer;
declare variable V$ALLPART1P3 integer;
declare variable V$ALLPART1P4 integer;
declare variable V$ALLPART1P5 integer;
declare variable V$ALLPART1P6 integer;
declare variable V$ALLPART1P7 integer;
declare variable V$ALLPART1P8 integer;
declare variable V$ALLPART1ALL integer;
declare variable V$ALLPART2P1 integer;
declare variable V$ALLPART2P2 integer;
declare variable V$ALLPART2P3 integer;
declare variable V$ALLPART2P4 integer;
declare variable V$ALLPART2ALL integer;
declare variable V$ALLPART3P1 integer;
declare variable V$ALLPART3P2 integer;
declare variable V$ALLPART3P3 integer;
declare variable V$ALLPART3ALL integer;
declare variable V$ALLCOUNT_ALL integer;
declare variable V$LANG_CODE varchar(2);
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :V$LANG_CODE;
       
    V$ALLPART1P1 = 0;
    V$ALLPART1P2 = 0;
    V$ALLPART1P3 = 0;
    V$ALLPART1P4 = 0;
    V$ALLPART1P5 = 0;
    V$ALLPART1P6 = 0;
    V$ALLPART1P7 = 0;
    V$ALLPART1P8 = 0;
    V$ALLPART1ALL = 0;
    V$ALLPART2P1 = 0;
    V$ALLPART2P2 = 0;
    V$ALLPART2P3 = 0;
    V$ALLPART2P4 = 0;
    V$ALLPART2ALL = 0;
    V$ALLPART3P1 = 0;
    V$ALLPART3P2 = 0;
    V$ALLPART3P3 = 0;
    V$ALLPART3ALL = 0;
    V$ALLCOUNT_ALL = 0;
    FOR
        SELECT L111.OBJ_ID, R665.VAL
        FROM LINKS L112
        JOIN LINKS L111 ON L111.OBJ_TYPE_ID = 111 AND L111.DATE_DEL IS NULL AND L111.PARENT_ID = L112.OBJ_ID
        JOIN VALL V665 ON V665.PARAM_ID = 665 AND V665.IS_DEL = 0 AND V665.OBJ_ID = L111.OBJ_ID
        JOIN LISTVALS LV665 ON LV665.LISTVAL_ID = V665.LISTVAL_ID
        LEFT JOIN RES_GET(LV665.RES_ID, :V$LANG_CODE) R665 ON 1 = 1
        WHERE L112.PARENT_ID IS NULL AND L112.OBJ_TYPE_ID = 112 AND L112.DATE_DEL IS NULL
        ORDER BY LV665.SORT_ORDER
        INTO :V$DISTRICT_ID, :DISTRICT_NAME
    DO
    BEGIN
        PART1P1 = 0;
        PART1P2 = 0;
        PART1P3 = 0;
        PART1P4 = 0;
        PART1P5 = 0;
        PART1P6 = 0;
        PART1P7 = 0;
        PART1P8 = 0;
        PART1ALL = 0;
        PART2P1 = 0;
        PART2P2 = 0;
        PART2P3 = 0;
        PART2P4 = 0;
        PART2ALL = 0;
        PART3P1 = 0;
        PART3P2 = 0;
        PART3P3 = 0;
        PART3ALL = 0;
        COUNT_ALL = 0;

        FOR
            SELECT L2.OBJ_ID, V10.LISTVAL_ID, V11.LISTVAL_ID
            FROM LINKS L2
            JOIN VALL V10 ON V10.PARAM_ID = 10 AND V10.IS_DEL = 0 AND V10.OBJ_ID = L2.OBJ_ID
            JOIN VALL V11 ON V11.PARAM_ID = 11 AND V11.IS_DEL = 0 AND V11.OBJ_ID = L2.OBJ_ID
            WHERE L2.PARENT_ID = :V$DISTRICT_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
            INTO :V$OU_ID, :V$OU_KIND, :V$OU_TYPE
        DO
        BEGIN
            SELECT COUNT(DISTINCT L10.OBJ_ID)
            FROM LINKS L7
            JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.DATE_DEL IS NULL AND L8.OBJ_TYPE_ID = 8
            JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.DATE_DEL IS NULL AND L9.OBJ_TYPE_ID = 9
            JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.DATE_DEL IS NULL AND L10.OBJ_TYPE_ID = 10
            JOIN PERSON_MOVEMENTS M ON M.DATE_DEL IS NULL AND M.PERSON_ID = L10.OBJ_ID AND M.GROUP_ID = L9.OBJ_ID AND M.DATE_IN <= :I$DT AND M.REASON_IN IN (810, 3276, 3277, 3278)
            WHERE L7.PARENT_ID = :V$OU_ID AND L7.DATE_DEL IS NULL AND L7.OBJ_TYPE_ID = 7
            INTO :V$COUNT;

            --kind
            IF (V$OU_KIND = 948) THEN
            BEGIN
                PART1P1 = PART1P1 + V$COUNT;
            END
            ELSE IF (V$OU_KIND = 949) THEN
            BEGIN
                PART1P2 = PART1P2 + V$COUNT;
            END
            ELSE IF (V$OU_KIND = 2613) THEN
            BEGIN
                PART1P3 = PART1P3 + V$COUNT;
            END
            ELSE IF (V$OU_KIND = 952) THEN
            BEGIN
                PART1P4 = PART1P4 + V$COUNT;
            END
            ELSE IF (V$OU_KIND = 2614) THEN
            BEGIN
                PART1P5 = PART1P5 + V$COUNT;
            END
            ELSE IF (V$OU_KIND = 951) THEN
            BEGIN
                PART1P6 = PART1P6 + V$COUNT;
            END
            ELSE IF (V$OU_KIND = 953) THEN
            BEGIN
                PART1P7 = PART1P7 + V$COUNT;
            END
            ELSE IF (V$OU_KIND = 950) THEN
            BEGIN
                PART1P8 = PART1P8 + V$COUNT;
            END
            PART1ALL = PART1P1 + PART1P2 + PART1P3 + PART1P4 + PART1P5 + PART1P6 + PART1P7 + PART1P8;

            IF (V$OU_KIND = 955) THEN
            BEGIN
                PART2P1 = PART2P1 + V$COUNT;
            END
            ELSE IF (V$OU_KIND = 956) THEN
            BEGIN
                PART2P2 = PART2P2 + V$COUNT;
            END
            ELSE IF (V$OU_KIND = 957) THEN
            BEGIN
                PART2P3 = PART2P3 + V$COUNT;
            END
            ELSE IF (V$OU_KIND = 2216) THEN
            BEGIN
                PART2P4 = PART2P4 + V$COUNT;
            END
            PART2ALL = PART2P1 + PART2P2 + PART2P3 + PART2P4;

            --type
            IF (V$OU_TYPE = 958) THEN
            BEGIN
                PART3P1 = PART3P1 + V$COUNT;
            END
            ELSE IF ( (V$OU_TYPE = 978)AND(V$OU_KIND <> 2216) ) THEN
            BEGIN
                PART3P2 = PART3P2 + V$COUNT;
            END
            ELSE IF (V$OU_TYPE = 994) THEN
            BEGIN
                PART3P3 = PART3P3 + V$COUNT;
            END
            PART3ALL = PART3P1 + PART3P2 + PART3P3;

            COUNT_ALL = PART1ALL + PART2ALL + PART3ALL;

        END

        SUSPEND;

        V$ALLPART1P1 = V$ALLPART1P1 +   PART1P1;
        V$ALLPART1P2 = V$ALLPART1P2 +   PART1P2;
        V$ALLPART1P3 = V$ALLPART1P3 +   PART1P3;
        V$ALLPART1P4 = V$ALLPART1P4 +   PART1P4;
        V$ALLPART1P5 = V$ALLPART1P5 +   PART1P5;
        V$ALLPART1P6 = V$ALLPART1P6 +   PART1P6;
        V$ALLPART1P7 = V$ALLPART1P7 +   PART1P7;
        V$ALLPART1P8 = V$ALLPART1P8 +   PART1P8;
        V$ALLPART1ALL = V$ALLPART1ALL + PART1ALL;
        V$ALLPART2P1 = V$ALLPART2P1 +   PART2P1;
        V$ALLPART2P2 = V$ALLPART2P2 +   PART2P2;
        V$ALLPART2P3 = V$ALLPART2P3 +   PART2P3;
        V$ALLPART2P4 = V$ALLPART2P4 +   PART2P4;
        V$ALLPART2ALL = V$ALLPART2ALL + PART2ALL;
        V$ALLPART3P1 = V$ALLPART3P1 +   PART3P1;
        V$ALLPART3P2 = V$ALLPART3P2 +   PART3P2;
        V$ALLPART3P3 = V$ALLPART3P3 +   PART3P3;
        V$ALLPART3ALL = V$ALLPART3ALL + PART3ALL;
        V$ALLCOUNT_ALL = V$ALLCOUNT_ALL + COUNT_ALL;
    END

    DISTRICT_NAME = 'Общий итог';
    PART1P1 = V$ALLPART1P1;
    PART1P2 = V$ALLPART1P2;
    PART1P3 = V$ALLPART1P3;
    PART1P4 = V$ALLPART1P4;
    PART1P5 = V$ALLPART1P5;
    PART1P6 = V$ALLPART1P6;
    PART1P7 = V$ALLPART1P7;
    PART1P8 = V$ALLPART1P8;
    PART1ALL =V$ALLPART1ALL;
    PART2P1 = V$ALLPART2P1;
    PART2P2 = V$ALLPART2P2;
    PART2P3 = V$ALLPART2P3;
    PART2P4 = V$ALLPART2P4;
    PART2ALL =V$ALLPART2ALL;
    PART3P1 = V$ALLPART3P1;
    PART3P2 = V$ALLPART3P2;
    PART3P3 = V$ALLPART3P3;
    PART3ALL =V$ALLPART3ALL;
    COUNT_ALL = V$ALLCOUNT_ALL;
    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE QUERYS_LIST (
    I$REPORT_ID BIGINT,
    I$LANG_CODE VARCHAR(2) = 'RU')
RETURNS (
    REPORT_ID BIGINT,
    RES_ID BIGINT,
    QUERY_NUM SMALLINT,
    QUERY_TYPE SMALLINT,
    IS_INSERT SMALLINT,
    SQL_TEXT VARCHAR(1000),
    WARNING_CAPTION VARCHAR(4000),
    IS_DEL SMALLINT)
AS
BEGIN
    FOR
        SELECT REPORT_ID,
               QUERY_NUM,
               QUERY_TYPE,
               IS_INSERT,
               SQL_TEXT,
               IS_DEL,
               RES_ID
        FROM QUERYS
        WHERE REPORT_ID = :I$REPORT_ID
        ORDER BY QUERY_NUM
        INTO   :REPORT_ID,
               :QUERY_NUM,
               :QUERY_TYPE,
               :IS_INSERT,
               :SQL_TEXT,
               :IS_DEL,
               :RES_ID
    DO
    BEGIN
        SELECT VAL FROM RES_GET(:RES_ID, :I$LANG_CODE) INTO :WARNING_CAPTION;
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE QUERYTYPES_LIST RETURNS (
    QUERY_TYPE SMALLINT,
    QUERY_NAME VARCHAR(100))
AS
BEGIN
    FOR
        SELECT QUERY_TYPE,
               QUERY_NAME
        FROM QUERYTYPES
        INTO   :QUERY_TYPE,
               :QUERY_NAME
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE QUERY_ADD (
    I$REPORT_ID BIGINT,
    I$RES_ID BIGINT,
    I$QUERY_NUM SMALLINT,
    I$QUERY_TYPE SMALLINT,
    I$IS_INSERT SMALLINT,
    I$SQL_TEXT VARCHAR(1000),
    I$WARNING_CAPTION VARCHAR(4000),
    I$LANG_CODE CHAR(2),
    I$IS_DEL SMALLINT = 0)
RETURNS (
    REPORT_ID BIGINT,
    QUERY_NUM SMALLINT)
AS
BEGIN
    IF (I$SQL_TEXT IS NULL) THEN I$SQL_TEXT = '';

    REPORT_ID = I$REPORT_ID;
    QUERY_NUM = I$QUERY_NUM;

    UPDATE OR INSERT INTO QUERYS (REPORT_ID, QUERY_NUM, QUERY_TYPE, IS_INSERT, SQL_TEXT, IS_DEL)
    VALUES (:I$REPORT_ID, :I$QUERY_NUM, :I$QUERY_TYPE, :I$IS_INSERT, :I$SQL_TEXT, :I$IS_DEL)
    RETURNING RES_ID, REPORT_ID, QUERY_NUM INTO :I$RES_ID, :REPORT_ID, :QUERY_NUM;
    IF (I$RES_ID IS NOT NULL) THEN
    BEGIN
        IF (I$WARNING_CAPTION IS NULL) THEN
        BEGIN
            I$WARNING_CAPTION = '';
        END
        EXECUTE PROCEDURE RES_ADD (:I$RES_ID,:I$LANG_CODE,:I$WARNING_CAPTION);
    END
    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE READ_REGISTRATION_PARAMS (
    I$PUPIL_ID BIGINT)
RETURNS (
    NUMBER VARCHAR(100),
    "DATE" DATE,
    DATE_FROM DATE,
    DATE_TO DATE,
    AUTHOR VARCHAR(2000),
    FILENAME VARCHAR(2000))
AS
declare variable V$OBJ_ID bigint;
BEGIN   
    SELECT FIRST 1
        OBJ_ID
    FROM LINKS
    WHERE PARENT_ID = :I$PUPIL_ID
    AND OBJ_TYPE_ID = 293
    AND DATE_DEL IS NULL
    INTO :V$OBJ_ID;
    IF (V$OBJ_ID IS NOT NULL) THEN
    BEGIN
        SELECT V
        FROM VAL_GET(:V$OBJ_ID, 2358)
        INTO :NUMBER;

        SELECT D
        FROM VAL_GET(:V$OBJ_ID, 2359)
        INTO :"DATE";

        SELECT D
        FROM VAL_GET(:V$OBJ_ID, 2360)
        INTO :DATE_FROM;

        SELECT D
        FROM VAL_GET(:V$OBJ_ID, 2361)
        INTO :DATE_TO;

        SELECT V
        FROM VAL_GET(:V$OBJ_ID, 2362)
        INTO :AUTHOR;

        SELECT V
        FROM VAL_GET(:V$OBJ_ID, 2363)
        INTO :FILENAME;
    END
    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE RECALC_STUDENT_AGG (
    I$STUDENT_ID BIGINT,
    I$YEAR_ID BIGINT)
AS
declare variable V$YEAR integer;
declare variable V$ID bigint;
declare variable V$V float;
declare variable V$N float;
declare variable V$CNT integer;
declare variable V$RN float;
declare variable V$RV float;
declare variable V$MCOST float;
declare variable V float;
declare variable LV float;
declare variable S varchar(400);
declare variable V$G1 bigint;
declare variable V$G2 bigint;
declare variable V$G3 bigint;
begin

  SELECT Y.COST
  FROM LISTVALS Y
  WHERE Y.LISTVAL_ID = :I$YEAR_ID
  INTO :V$YEAR;

  -- По элементам содержания, которые попадались в текущем году (даже удаленные)
  FOR
    SELECT DISTINCT LC.CEC_ID
    FROM CJ2_MARK M
    JOIN CJ2_CONTROL C ON C.CONTROL_ID = M.CONTROL_ID AND C.CONTROL_TYPE_ID <> 0 AND C.CONTROL_TYPE_ID <> 30000
    JOIN CJ2_JOURNAL_LESSONS L ON L.OBJ_ID = C.LESSON_ID
    JOIN CJ2_JOURNAL J ON J.OBJ_ID = L.CJ_ID AND J.YEAR_ID = :I$YEAR_ID
    JOIN CJ2_LESSON_CEC LC ON LC.LESSON_ID = C.LESSON_ID
    WHERE M.DATE_DEL IS NULL AND M.STUDENT_ID = :I$STUDENT_ID AND M.FINAL_ID IS NULL
    INTO :V$ID
  DO
  BEGIN

    -- Если ЭС ссылается на другой ЭС, то заменяем на id родителя
    -- !!!

    -- Выбираем последнюю запись за прошлые годы
    V$N = 0;
    V$V = 0;
    SELECT FIRST 1 X.NTOTAL, X.VTOTAL
    FROM VALX X
    JOIN LISTVALS LV ON LV.LISTVAL_ID = X.YEAR_ID AND LV.COST < :V$YEAR
    WHERE X.PUPIL_ID = :I$STUDENT_ID AND X.CEC_ID = :V$ID AND X.USA_ID = 0
    ORDER BY LV.COST DESC
    INTO :V$N, :V$V;

    -- Суммируем текущий год, тут придется делать перебор
    V$CNT = 0;
    V$RN = 0;
    V$RV = 0;
    FOR
      SELECT MT.MARK_COST
      FROM CJ2_JOURNAL J
      JOIN CJ2_JOURNAL_LESSONS L ON L.DATE_DEL IS NULL AND L.CJ_ID = J.OBJ_ID AND L.DE_ID IS NOT NULL
      JOIN CJ2_LESSON_CEC LC ON LC.LESSON_ID = L.OBJ_ID AND LC.CEC_ID = :V$ID AND LC.IS_DEL = 0
      JOIN CJ2_CONTROL C ON C.DATE_DEL IS NULL AND C.LESSON_ID = L.OBJ_ID AND C.CONTROL_TYPE_ID <> 0 AND C.CONTROL_TYPE_ID <> 30000
      JOIN CJ2_MARK M ON M.DATE_DEL IS NULL AND M.CONTROL_ID = C.CONTROL_ID AND M.STUDENT_ID = :I$STUDENT_ID
      JOIN CJ2_MARK_TYPE MT ON MT.MARK_TYPE_ID = M.MARK_TYPE_ID
      WHERE J.DATE_DEL IS NULL AND J.YEAR_ID = :I$YEAR_ID
      INTO :V$MCOST
    DO
    BEGIN
      V$CNT = V$CNT + 1;
      V$RN = V$RN + 1;
      V$RV = V$RV + V$MCOST;
    END

    IF((V$RN + V$N) <= 0) THEN V = 0;
    ELSE V = (V$RV + V$V) / (V$RN + V$N);
    IF(V$RN <= 0) THEN LV = 0;
    ELSE LV = V$RV / V$RN;

    -- Удалять нельзя, поэтому если накосячили - будут хвосты

    UPDATE OR INSERT INTO VALX
    (PUPIL_ID, USA_ID, CEC_ID, YEAR_ID, NVALS, YTOTAL, NTOTAL, YVAL, VTOTAL, LVAL, VAL)
    VALUES (:I$STUDENT_ID, 0, :V$ID, :I$YEAR_ID, :V$CNT, :V$RN, :V$RN + :V$N, :V$RV, :V$RV + :V$V, :LV, :V)
    MATCHING (PUPIL_ID, USA_ID, CEC_ID, YEAR_ID);

  END

  -- По учебным действиям. Шкала может быть только зачет-незачет
  FOR
    SELECT DISTINCT U.USA_ID, U.GROUP_ID, U.SUBGROUP_ID, U.ITEM_ID
    FROM CJ2_MARK M
    JOIN CJ2_CONTROL C ON C.CONTROL_ID = M.CONTROL_ID AND C.CONTROL_TYPE_ID = 30000
    JOIN CJ2_JOURNAL_LESSONS L ON L.OBJ_ID = C.LESSON_ID
    JOIN CJ2_JOURNAL J ON J.OBJ_ID = L.CJ_ID AND J.YEAR_ID = :I$YEAR_ID
    JOIN CJ2_LESSON_UUD U ON U.CONTROL_ID = C.CONTROL_ID
    WHERE M.DATE_DEL IS NULL AND M.STUDENT_ID = :I$STUDENT_ID AND M.FINAL_ID IS NULL
    INTO :V$ID, :V$G1, :V$G2, :V$G3
  DO
  BEGIN

    -- Выбираем последнюю запись за прошлые годы
    V$N = 0;
    V$V = 0;
    SELECT FIRST 1 X.NTOTAL, X.VTOTAL
    FROM VALX X
    JOIN LISTVALS LV ON LV.LISTVAL_ID = X.YEAR_ID AND LV.COST < :V$YEAR
    WHERE X.PUPIL_ID = :I$STUDENT_ID AND X.USA_ID = :V$ID AND X.CEC_ID = 0
    ORDER BY LV.COST DESC
    INTO :V$N, :V$V;

    -- Суммируем текущий год, тут придется делать перебор (шкала 1-3-5)
    V$CNT = 0;
    V$RN = 0;
    V$RV = 0;
    FOR
      SELECT (MT.MARK_COST - 3) * 5.0 / 2
      FROM CJ2_JOURNAL J
      JOIN CJ2_JOURNAL_LESSONS L ON L.DATE_DEL IS NULL AND L.CJ_ID = J.OBJ_ID
      JOIN CJ2_CONTROL C ON C.DATE_DEL IS NULL AND C.LESSON_ID = L.OBJ_ID AND C.CONTROL_TYPE_ID = 30000
      JOIN CJ2_LESSON_UUD U ON U.CONTROL_ID = C.CONTROL_ID AND U.USA_ID = :V$ID AND U.IS_DEL = 0
      JOIN CJ2_MARK M ON M.DATE_DEL IS NULL AND M.CONTROL_ID = C.CONTROL_ID AND M.STUDENT_ID = :I$STUDENT_ID
      JOIN CJ2_MARK_TYPE MT ON MT.MARK_TYPE_ID = M.MARK_TYPE_ID
      WHERE J.DATE_DEL IS NULL AND J.YEAR_ID = :I$YEAR_ID
      INTO :V$MCOST
    DO
    BEGIN
      V$CNT = V$CNT + 1;
      V$RN = V$RN + 1;
      V$RV = V$RV + V$MCOST;
    END

    IF((V$RN + V$N) <= 0) THEN V = 0;
    ELSE V = (V$RV + V$V) / (V$RN + V$N);
    IF(V$RN <= 0) THEN LV = 0;
    ELSE LV = V$RV / V$RN;

    -- Удалять нельзя, поэтому если накосячили - будут хвосты

    UPDATE OR INSERT INTO VALX
    (PUPIL_ID, USA_ID, USA_GROUP, USA_SUBGROUP, USA_ITEM, CEC_ID, YEAR_ID, NVALS, YTOTAL, NTOTAL, YVAL, VTOTAL, LVAL, VAL)
    VALUES (:I$STUDENT_ID, :V$ID, :V$G1, :V$G2, :V$G3, 0, :I$YEAR_ID, :V$CNT, :V$RN, :V$RN + :V$N, :V$RV, :V$RV + :V$V, :LV, :V)
    MATCHING (PUPIL_ID, USA_ID, CEC_ID, YEAR_ID);
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE REFERENCE_LIST (
    I$TYPE_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    OBJ_CAPTION VARCHAR(4000))
AS
BEGIN
    FOR
        SELECT DISTINCT O.OBJ_ID
        FROM OBJECTS O
        INNER JOIN LINKS L ON L.OBJ_ID = O.OBJ_ID
        WHERE O.TYPE_ID = :I$TYPE_ID
        AND L.DATE_DEL IS NULL
        INTO   :OBJ_ID
    DO
    BEGIN
        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:OBJ_ID, NULL)
        INTO :OBJ_CAPTION;
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE REGION_APPLY_TIMEMARK (
    I$TM TIMESTAMP)
AS
DECLARE VARIABLE V$ID BIGINT;
begin

  SELECT INFO_ID
  FROM INFO
  WHERE INFO_CODE = 'LAST_REGION_EXPORT'
  INTO :V$ID;

  IF(V$ID IS NULL) THEN
  BEGIN

    INSERT INTO INFO
    (INFO_CODE, INFO_NAME, INFO_VAL)
    VALUES ('LAST_REGION_EXPORT', 'LAST_REGION_EXPORT', :I$TM);

  END
  ELSE
  BEGIN

    UPDATE INFO
    SET INFO_VAL = :I$TM
    WHERE INFO_ID = :V$ID;

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE REGION_SERIALIZE_PRE
AS
DECLARE VARIABLE V$S VARCHAR(1000);
begin

  -- Запускаем верификацию и кидаем ошибку, если есть статус 3
  V$S = NULL;
  SELECT FIRST 1 C.ERROR_TEXT
  FROM LINKS L2
  LEFT JOIN VERIFY_ALL(L2.OBJ_ID) C ON 1 = 1
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND C.ERROR_TYPE = 3
  INTO :V$S;

  IF(V$S IS NOT NULL) THEN EXCEPTION DATA_ERROR 'Ошибка верификации: ' || V$S;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE REGION_SERIALIZE_TM (
    I$DATE TIMESTAMP)
RETURNS (
    TM TIMESTAMP,
    CURRENT_TM TIMESTAMP,
    LIC_ID BIGINT)
AS
DECLARE VARIABLE V$S VARCHAR(1000);
DECLARE VARIABLE V$LAST_DATE TIMESTAMP;
begin

  SELECT INFO_VAL FROM INFO WHERE INFO_CODE = 'LAST_REGION_EXPORT' INTO :V$S;
  IF(V$S = '') THEN V$S = NULL;
  V$LAST_DATE = V$S;

  IF((I$DATE IS NOT NULL AND V$LAST_DATE <> I$DATE) OR V$LAST_DATE IS NULL) THEN I$DATE = NULL;

  CURRENT_TM = CURRENT_TIMESTAMP;

  SELECT GEN
  FROM GEN
  INTO :LIC_ID;

  TM = I$DATE;
  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE REMOVE_FALSE_PUPIL_WITH_EDU_DOC (
    I$YEAR BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    "COUNT" SMALLINT)
AS
DECLARE VARIABLE V$PUPIL_ID BIGINT;
DECLARE VARIABLE V$STAGE_ID BIGINT;
DECLARE VARIABLE V$CLASS_ID BIGINT;
begin
    "COUNT" = 0;
    FOR
        SELECT L7.OBJ_ID,
               L10.OBJ_ID,
               L125.OBJ_ID
        FROM LINKS L2

        JOIN LINKS L7
        ON L7.PARENT_ID = L2.OBJ_ID
        AND L7.OBJ_TYPE_ID IN (7, 502)
        AND L7.DATE_DEL IS NULL

        JOIN LINKS L8
        ON L8.PARENT_ID = L7.OBJ_ID
        AND L8.OBJ_TYPE_ID = 8
        AND L8.DATE_DEL IS NULL

        JOIN LINKS L125
        ON L125.PARENT_ID = L8.OBJ_ID
        AND L125.OBJ_TYPE_ID = 125
        AND L125.DATE_DEL IS NULL

        JOIN LINKS L10
        ON L10.PARENT_ID = L125.OBJ_ID
        AND L10.OBJ_TYPE_ID = 10
        AND L10.DATE_DEL IS NULL
        AND EXISTS(
            SELECT FIRST 1 1
            FROM LINKS L
            WHERE L.OBJ_ID = L10.OBJ_ID
            AND L.PARENT_TYPE_ID IN (81,82,83)
            AND L.DATE_DEL IS NULL
        )

        WHERE L2.PARENT_ID IS NULL
        AND L2.OBJ_TYPE_ID = 2
        AND L2.DATE_DEL IS NULL

        INTO :V$STAGE_ID,
             :V$PUPIL_ID,
             :V$CLASS_ID
    DO
    BEGIN
        IF ((SELECT FIRST 1
                    FORM_ID
             FROM CERTIFICATE_PUPIL_INFO_GET (
                :I$YEAR,
                :V$STAGE_ID,
                :V$PUPIL_ID,
                :I$USER_ID
             )) IS NOT NULL) THEN
        BEGIN
            UPDATE LINKS
            SET DATE_DEL = CURRENT_TIMESTAMP
            WHERE OBJ_ID = :V$PUPIL_ID
            AND PARENT_ID = :V$CLASS_ID
            AND DATE_DEL IS NULL;

            "COUNT" = "COUNT" + 1;
        END
    END
    SUSPEND;
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE REPORTS_LEVEL_LIST (
    I$USER_ID BIGINT,
    I$LEVEL_ID BIGINT)
RETURNS (
    REPORT_ID BIGINT,
    TYPE_ID BIGINT,
    TEMPL_ID BIGINT,
    SORT_ORDER SMALLINT,
    REPORT_CAPTION VARCHAR(4000),
    TAG VARCHAR(100),
    GROUP_CAPTION VARCHAR(100))
AS
declare variable LANG_CODE char(2) = 'RU';
declare variable RES_ID bigint;
BEGIN

    SELECT LANG_CODE FROM USERS WHERE USER_ID = :I$USER_ID INTO :LANG_CODE;

    FOR
        SELECT R.REPORT_ID, R.TYPE_ID, R.RES_ID, R.TEMPL_ID, R.SORT_ORDER, R.TAG, L.GROUP_NAME
        FROM REPORTS R
        JOIN LREPORTS L ON L.REPORT_ID = R.REPORT_ID AND L.IS_DEL = 0 AND L.LEVEL_ID = :I$LEVEL_ID
        WHERE R.IS_DEL = 0
        ORDER BY L.GROUP_NAME, R.SORT_ORDER
        INTO :REPORT_ID, :TYPE_ID, :RES_ID, :TEMPL_ID, :SORT_ORDER, :TAG, :GROUP_CAPTION
    DO
    BEGIN
        SELECT VAL FROM RES_GET(:RES_ID, :LANG_CODE) INTO :REPORT_CAPTION;
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE REPORTS_LIST (
    I$LANG_CODE VARCHAR(2) = 'RU')
RETURNS (
    REPORT_ID BIGINT,
    TYPE_ID BIGINT,
    RES_ID BIGINT,
    TEMPL_ID BIGINT,
    SORT_ORDER SMALLINT,
    IS_DEL SMALLINT,
    REPORT_CAPTION VARCHAR(4000),
    TAG VARCHAR(100))
AS
BEGIN
    FOR
        SELECT R.REPORT_ID,
               R.TYPE_ID,
               R.RES_ID,
               R.TEMPL_ID,
               R.SORT_ORDER,
               R.IS_DEL,
               R.TAG
        FROM REPORTS R
        ORDER BY R.SORT_ORDER
        INTO   :REPORT_ID,
               :TYPE_ID,
               :RES_ID,
               :TEMPL_ID,
               :SORT_ORDER,
               :IS_DEL,
               :TAG
    DO
    BEGIN
        SELECT VAL FROM RES_GET(:RES_ID, :I$LANG_CODE) INTO :REPORT_CAPTION;
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE REPORT_357_358 (
    I$OBJ_ID_T57 BIGINT,
    I$OBJ_ID_T69 BIGINT,
    I$IS_ACTUAL INTEGER = null,
    I$ADAPTED INTEGER = null)
RETURNS (
    O$OOOD_NAME VARCHAR(100),
    O$OBJ_ID_T50 BIGINT,
    O$OBJ_ID_T57 BIGINT,
    O$R2470_VAL VARCHAR(100),
    O$V374_VAL VARCHAR(100),
    O$R2478_VAL VARCHAR(100),
    O$R2101_VAL VARCHAR(100),
    O$R2166_VAL VARCHAR(100),
    O$PLANTYPE INTEGER,
    O$STUDYLEVEL INTEGER)
AS
BEGIN

    SELECT FIRST 1 COALESCE(LEFT(V2.VAL, 100),'') FROM LINKS LP2
    JOIN LINKS L57 ON LP2.OBJ_ID = L57.PARENT_ID AND L57.OBJ_TYPE_ID = 57 AND L57.PARENT_TYPE_ID = 69 AND L57.DATE_DEL IS NULL
    JOIN VALS V2 ON V2.OBJ_ID = LP2.PARENT_ID AND V2.PARAM_ID = 2 AND V2.IS_DEL = 0
    WHERE LP2.OBJ_TYPE_ID = 69 AND  LP2.PARENT_TYPE_ID = 2 AND LP2.DATE_DEL IS NULL
      AND ((L57.OBJ_ID = :I$OBJ_ID_T57)  OR (:I$OBJ_ID_T57 IS NULL)) AND ((L57.PARENT_ID = :I$OBJ_ID_T69)  OR (:I$OBJ_ID_T69 IS NULL))
    INTO :O$OOOD_NAME;

    FOR
    SELECT L50.OBJ_ID, L57.OBJ_ID, COALESCE(LEFT(R2470.VAL, 100),''), V1594.LISTVAL_ID
    FROM LINKS L50
    JOIN LINKS L57 ON L57.OBJ_ID = L50.PARENT_ID AND L57.OBJ_TYPE_ID = 57 AND L57.PARENT_TYPE_ID = 69 AND L57.DATE_DEL IS NULL
    JOIN VALL V2450 ON V2450.OBJ_ID = L57.PARENT_ID AND V2450.LISTVAL_ID = 11385 AND V2450.PARAM_ID = 2450 AND V2450.IS_DEL = 0 --  Образовательные программы общего образования
    JOIN VALL V2545 ON V2545.OBJ_ID = L50.OBJ_ID AND V2545.LISTVAL_ID <> 2 AND V2545.PARAM_ID = 2545 AND V2545.IS_DEL = 0 -- НЕ План внеурочной деятельности
    LEFT JOIN VALL V2470 ON V2470.OBJ_ID = L50.OBJ_ID  AND V2470.PARAM_ID = 2470 AND V2470.IS_DEL = 0
    LEFT JOIN LISTVALS LV2470 ON LV2470.LISTVAL_ID = V2470.LISTVAL_ID AND LV2470.IS_DEL = 0
    LEFT JOIN RES R2470 ON R2470.RES_ID = LV2470.RES_ID AND R2470.LANG_CODE = 'RU' AND R2470.IS_DEL = 0
    LEFT JOIN VALL V2379 ON V2379.OBJ_ID = L50.PARENT_ID AND V2379.PARAM_ID = 2379 AND V2379.IS_DEL = 0
    LEFT JOIN VALL V1594 ON V1594.OBJ_ID = L57.OBJ_ID AND V1594.PARAM_ID = 1594 AND V1594.IS_DEL = 0 --   уровень образования
    WHERE L50.OBJ_TYPE_ID = 50 AND L50.DATE_DEL IS NULL AND (L57.OBJ_ID = :I$OBJ_ID_T57  or (:I$OBJ_ID_T57 IS NULL)) AND (L57.PARENT_ID = :I$OBJ_ID_T69 or (:I$OBJ_ID_T69 IS NULL))
          AND ((V2470.LISTVAL_ID = 11715 and :I$IS_ACTUAL = 1) or (V2470.LISTVAL_ID <> 11715 and :I$IS_ACTUAL = 0) or (:I$IS_ACTUAL IS NULL)) -- 11715 - Действующий
          AND ((V2379.LISTVAL_ID = 11187 and :I$ADAPTED = 0) or (V2379.LISTVAL_ID <> 11187 and :I$ADAPTED = 1) or (:I$ADAPTED IS NULL)) -- 11187 -  Не адаптирована
    INTO :O$OBJ_ID_T50, :O$OBJ_ID_T57, :O$R2470_VAL, :O$STUDYLEVEL
    

    DO
    BEGIN
        SELECT LEFT(V374.VAL, 100) V374_VAL,
               COALESCE(LEFT(R2478.VAL, 100),'') R2478_VAL,
               COALESCE(LEFT(R2101.VAL, 100),'') R2101_VAL,
               COALESCE(LEFT(R2166.VAL, 100),'') R2166_VAL,
               (case V2478.LISTVAL_ID when 11720 then 1 else 2 end)
              FROM OBJECTS OB 
              LEFT JOIN VALS V374 ON V374.OBJ_ID = OB.OBJ_ID  AND V374.PARAM_ID = 374 AND V374.IS_DEL = 0 
        
              LEFT JOIN VALL V2478 ON V2478.OBJ_ID = OB.OBJ_ID  AND V2478.PARAM_ID = 2478 AND V2478.IS_DEL = 0 
              LEFT JOIN LISTVALS LV2478 ON LV2478.LISTVAL_ID = V2478.LISTVAL_ID AND LV2478.IS_DEL = 0 
              LEFT JOIN RES R2478 ON R2478.RES_ID = LV2478.RES_ID AND R2478.LANG_CODE = 'RU' AND R2478.IS_DEL = 0
        
              LEFT JOIN VALL V2101 ON V2101.OBJ_ID = OB.OBJ_ID  AND V2101.PARAM_ID = 2101 AND V2101.IS_DEL = 0 
              LEFT JOIN LISTVALS LV2101 ON LV2101.LISTVAL_ID = V2101.LISTVAL_ID AND LV2101.IS_DEL = 0 
              LEFT JOIN RES R2101 ON R2101.RES_ID = LV2101.RES_ID AND R2101.LANG_CODE = 'RU' AND R2101.IS_DEL = 0
        
              LEFT JOIN VALL V2166 ON V2166.OBJ_ID = OB.OBJ_ID  AND V2166.PARAM_ID = 2166 AND V2166.IS_DEL = 0
              LEFT JOIN LISTVALS LV2166 ON LV2166.LISTVAL_ID = V2166.LISTVAL_ID AND LV2166.IS_DEL = 0
              LEFT JOIN RES R2166 ON R2166.RES_ID = LV2166.RES_ID AND R2166.LANG_CODE = 'RU' AND R2166.IS_DEL = 0
        
              WHERE OB.OBJ_ID = :O$OBJ_ID_T50 and OB.TYPE_ID = 50   -- Учебный план
        INTO :O$V374_VAL, :O$R2478_VAL, :O$R2101_VAL, :O$R2166_VAL, :O$PLANTYPE;

        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE REPORT_85K_NEW (
    I$OBJ_ID BIGINT,
    I$DATE DATE)
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$HAS_DOO SMALLINT;
DECLARE VARIABLE DB_LVL SMALLINT;
DECLARE VARIABLE OU_TYPE BIGINT;
DECLARE VARIABLE OU_OPF BIGINT;
DECLARE VARIABLE P_1890 BIGINT;
DECLARE VARIABLE V$ID BIGINT;
DECLARE VARIABLE V$GROUP_ID BIGINT;
DECLARE VARIABLE V$TYPE_ID BIGINT;
DECLARE VARIABLE V$PERSON_ID BIGINT;
DECLARE VARIABLE V$CNT BIGINT;
DECLARE VARIABLE V$GROUP_AGE BIGINT;
DECLARE VARIABLE V$OVZ BIGINT;
DECLARE VARIABLE V$DT_FROM DATE;
DECLARE VARIABLE V$DT DATE;
DECLARE VARIABLE V$DT1 DATE;
DECLARE VARIABLE V$DT_EDU DATE;
DECLARE VARIABLE V$TAG VARCHAR(10);
DECLARE VARIABLE V$S VARCHAR(10);
DECLARE VARIABLE V$JOB_NAME VARCHAR(1000);
DECLARE VARIABLE V$SPEC VARCHAR(1000);
DECLARE VARIABLE YR INTEGER;
DECLARE VARIABLE I INTEGER;
DECLARE VARIABLE F FLOAT;
DECLARE VARIABLE F1 FLOAT;
DECLARE VARIABLE V$RATE_USED FLOAT;
DECLARE VARIABLE V$RATE_FREE FLOAT;
DECLARE VARIABLE V$ADAPT_ID BIGINT;
DECLARE VARIABLE CURR_Y INTEGER;
begin
  YR = EXTRACT(YEAR FROM :I$DATE);
  TAG_NAME = 'year';
  VAL = YR;
  SUSPEND;

  -- найдем текущий учебный год
  SELECT LV.COST
  FROM VALL V
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V.LISTVAL_ID AND LV.IS_DEL = 0
  WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 1236 AND V.IS_DEL = 0
  INTO :CURR_Y;

  -- дата начала отчетного периода
  TAG_NAME = 'dt_from';
  V$DT_FROM = CAST(YR || '-01-01' AS DATE);
  SELECT VAL FROM DATE2ISO(:V$DT_FROM) INTO :VAL;
  SUSPEND;

  -- дата заполнения формы отчетности
  TAG_NAME = 'fillout_date';
  VAL = LPAD(EXTRACT(DAY FROM CURRENT_DATE), 2, '0');
  SUSPEND;
  TAG_NAME = 'fillout_month';
  VAL = LPAD(EXTRACT(MONTH FROM CURRENT_DATE), 2, '0');
  SUSPEND;
  TAG_NAME = 'fillout_year';
  VAL = SUBSTRING(EXTRACT(YEAR FROM CURRENT_DATE) FROM 4);
  SUSPEND;

  SELECT HAS_DOO FROM R_85K_NEW_HAS_DOO(:I$OBJ_ID) INTO :V$HAS_DOO;
  IF (V$HAS_DOO = 0) THEN EXIT;
  SELECT K.KEY_VAL
  FROM KEYS K
  WHERE K.KEY_CODE = 'LEVEL'
  INTO :DB_LVL;

  -- Раздел 1. Сведения об организации (на конец отчетного года)
  -- 102  тип поселения («1» – городская местность, «2» – сельская местность)
  TAG_NAME = 'settlement_type';
  VAL = 1;
  SUSPEND;
  IF (DB_LVL = 1) THEN BEGIN -- ОУ
    -- OU_TYPE
    -- SELECT V.LISTVAL_ID FROM VALL V WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 11 AND V.IS_DEL = 0 INTO :OU_TYPE;
    -- OU_OPF
    SELECT L.LISTVAL_ID
    FROM VALL V, LISTVALS L
    WHERE L.LISTVAL_ID = V.LISTVAL_ID
      AND V.OBJ_ID = :I$OBJ_ID
      AND L.LIST_ID IN (4, 258) AND L.IS_DEL = 0
      AND V.PARAM_ID = 8 AND V.IS_DEL = 0
    INTO :OU_OPF;
    -- P_1890
    SELECT V.LISTVAL_ID FROM VALL V WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 1890 AND V.IS_DEL = 0 INTO :P_1890;

    -- шапка
    SELECT OBJ_ID, FIO, POST
    FROM R_SPB_POST_DIRECTOR(:I$OBJ_ID, NULL)
    INTO :V$ID, :V$SPEC, :V$JOB_NAME;
    TAG_NAME = 'director_fio';
    VAL = V$SPEC;
    SUSPEND;
    TAG_NAME = 'director_post';
    VAL = V$JOB_NAME;
    SUSPEND;
    TAG_NAME = 'director_phone';
    VAL = NULL;
    SELECT VAL FROM VALS WHERE OBJ_ID = :I$OBJ_ID AND PARAM_ID = 28 AND IS_DEL = 0 INTO :VAL;
    SUSPEND;
    TAG_NAME = 'director_email';
    VAL = NULL;
    SELECT VAL FROM VALS WHERE OBJ_ID = :I$OBJ_ID AND PARAM_ID = 35 AND IS_DEL = 0 INTO :VAL;
    SUSPEND;
    TAG_NAME = 'ou_site';
    VAL = NULL;
    SELECT VAL FROM VALS WHERE OBJ_ID = :I$OBJ_ID AND PARAM_ID = 36 AND IS_DEL = 0 INTO :VAL;
    SUSPEND;

    SELECT V FROM VAL_GET(:I$OBJ_ID, 5) INTO VAL;
    TAG_NAME = 'ou_name';
    SUSPEND;
    SELECT VAL FROM ADR_GET(27,:I$OBJ_ID) INTO VAL;
    TAG_NAME = 'ou_address';
    SUSPEND;
    SELECT V FROM VAL_GET(:I$OBJ_ID, 9) INTO VAL;
    TAG_NAME = 'ogrn';
    SUSPEND;

    -- 101  тип
    TAG_NAME = 'type';
    --«5» – дошкольная образовательная организация;
    --«2» – обособленное подразделение (филиал) дошкольной образовательной организации;
    --«3» – обособленное подразделение (филиал) общеобразовательной организации;
    --«13» – подразделения (группы), осуществляющие образовательную деятельность по образовательным программам дошкольного образования, присмотр и уход за детьми организованные при общеобразовательной организации;
    IF (P_1890 = 5425 AND OU_OPF NOT IN (1735, 5405)) THEN VAL = 5;
    ELSE IF (P_1890 = 5425 AND OU_OPF IN (1735, 5405)) THEN VAL = 2;
    ELSE IF (P_1890 = 5426 AND OU_OPF IN (1735, 5405)) THEN VAL = 3;
    SUSPEND;
    -- 103 статус организации
    TAG_NAME = 'status';
    --«1» – функционирует;
    --«2» – организация временно не работает из-за проведения капитального ремонта или реконструкции;
    --«3» – организация функционирует и одно из зданий находится в аварийном состоянии;
    --«4» – деятельность приостановлена;
    --«5» – организация функционирует и одно из зданий требует капитального ремонта.
    VAL = NULL;
    SELECT V.LISTVAL_ID FROM VALL V WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 2371 AND V.IS_DEL = 0 INTO :VAL;
    IF (VAL = 11178) THEN VAL = 1;
    ELSE IF (VAL IN (11179, 11180)) THEN VAL = 2;
    ELSE IF (VAL = 11181) THEN VAL = 4;
    SUSPEND;
    -- 104 режим функционирования («2» – пятидневный;«3» – шестидневный;«14» – семидневный)
    TAG_NAME = 'operation_mode';
    VAL = NULL;
    SELECT IIF(SUM(IIF(V551.LISTVAL_ID = 1342, 1, 0)) >
               SUM(IIF(V551.LISTVAL_ID = 1342, 0, 1)), 1, 2)
    FROM LINKS L7
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
    JOIN VALL V551 ON V551.OBJ_ID = L9.OBJ_ID AND V551.PARAM_ID = 551 AND V551.IS_DEL = 0
    WHERE L7.PARENT_ID = :I$OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    INTO :VAL;
    SUSPEND;
    -- 105 коллегиальный орган   (0/1)
    TAG_NAME = 'has_board';
    VAL = IIF(:OU_OPF NOT IN (1735, 5405), 1, 0);
    SUSPEND;
  END

  -- Раздел 2. Режим работы групп и численность воспитанников в них
  TAG_NAME = 'groups::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT LISTVAL_ID
    FROM LISTVALS
    WHERE LIST_ID = 227 AND IS_DEL = 0
    ORDER BY 1
    INTO :V$ID
  DO
  BEGIN
    V$GROUP_ID = 0;
    V$PERSON_ID = 0;

    SELECT COALESCE(COUNT(DISTINCT M.GROUP_ID), 0), COALESCE(COUNT(DISTINCT M.PERSON_ID), 0)
    FROM PERSON_MOVEMENTS M
    JOIN LINKS L9 ON L9.OBJ_ID = M.GROUP_ID AND L9.PARENT_TYPE_ID = 8 AND (L9.DATE_DEL IS NULL OR L9.DATE_DEL > :I$DATE)
    JOIN VALL V1558 ON V1558.OBJ_ID = L9.OBJ_ID AND V1558.PARAM_ID = 1558 AND V1558.IS_DEL = 0 AND V1558.LISTVAL_ID = :V$ID
    JOIN LINKS L8 ON L8.OBJ_ID = L9.PARENT_ID AND L8.PARENT_TYPE_ID = 7 AND L8.DATE_DEL IS NULL
    JOIN LINKS L7 ON L7.OBJ_ID = L8.PARENT_ID AND L7.PARENT_TYPE_ID = 2 AND L7.DATE_DEL IS NULL
    JOIN VALL V43 ON V43.OBJ_ID = L7.OBJ_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0 AND V43.LISTVAL_ID IN (21, 3263, 3264) -- ступень ДО
    WHERE M.DATE_DEL IS NULL AND M.GROUP_TYPE_ID = 9 AND M.IS_VD = 0 AND (M.DATE_OUT IS NULL OR M.DATE_OUT > :I$DATE) AND
       ((:DB_LVL = 1 AND M.OU_ID = :I$OBJ_ID) OR
       (:DB_LVL = 2 AND M.OU_ID IN (SELECT L.OBJ_ID FROM LINKS L WHERE L.OBJ_TYPE_ID = 2 AND L.PARENT_ID = :I$OBJ_ID AND L.DATE_DEL IS NULL)) OR
       (:DB_LVL = 3 AND M.OU_ID IN (SELECT L.OBJ_ID FROM LINKS L WHERE L.OBJ_TYPE_ID = 2 AND L.PARENT_TYPE_ID = 111 AND L.DATE_DEL IS NULL)))
    GROUP BY V1558.LISTVAL_ID
    ORDER BY 1
    INTO :V$GROUP_ID, :V$PERSON_ID;

    TAG_NAME = 'groups:itm';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'groups:itm:type_id';
    VAL = V$ID;
    SUSPEND;
    TAG_NAME = 'groups:itm:group_cnt';
    VAL = V$GROUP_ID;
    SUSPEND;
    TAG_NAME = 'groups:itm:person_cnt';
    VAL = V$PERSON_ID;
    SUSPEND;
  END

  -- Раздел 3. Язык обучения и воспитания, человек
  TAG_NAME = 'pupil_cnt';
  VAL = 0;
  SELECT COALESCE(COUNT(DISTINCT M.PERSON_ID), 0)
  FROM PERSON_MOVEMENTS M
  JOIN LINKS L9 ON L9.OBJ_ID = M.GROUP_ID AND L9.PARENT_TYPE_ID = 8 AND (L9.DATE_DEL IS NULL OR L9.DATE_DEL > :I$DATE)
  JOIN LINKS L8 ON L8.OBJ_ID = L9.PARENT_ID AND L8.PARENT_TYPE_ID = 7 AND L8.DATE_DEL IS NULL
  JOIN LINKS L7 ON L7.OBJ_ID = L8.PARENT_ID AND L7.PARENT_TYPE_ID = 2 AND L7.DATE_DEL IS NULL
  JOIN VALL V43 ON V43.OBJ_ID = L7.OBJ_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0 AND V43.LISTVAL_ID IN (21, 3263, 3264) -- ступень ДО
  WHERE M.DATE_DEL IS NULL AND M.GROUP_TYPE_ID = 9 AND M.IS_VD = 0 AND (M.DATE_OUT IS NULL OR M.DATE_OUT > :I$DATE) AND
    ((:DB_LVL = 1 AND M.OU_ID = :I$OBJ_ID) OR
    (:DB_LVL = 2 AND M.OU_ID IN (SELECT L.OBJ_ID FROM LINKS L WHERE L.OBJ_TYPE_ID = 2 AND L.PARENT_ID = :I$OBJ_ID AND L.DATE_DEL IS NULL)) OR
    (:DB_LVL = 3 AND M.OU_ID IN (SELECT L.OBJ_ID FROM LINKS L WHERE L.OBJ_TYPE_ID = 2 AND L.PARENT_TYPE_ID = 111 AND L.DATE_DEL IS NULL)))
  INTO :VAL;
  SUSPEND;
  TAG_NAME = 'lang_id';
  VAL = 199; -- код русского языка по ОКИН
  SUSPEND;

  -- Раздел 4. Распределение групп по направленности и возрасту детей, единица
  TAG_NAME = 'group_scope::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT LISTVAL_ID
    FROM LISTVALS
    WHERE LIST_ID = 224 AND IS_DEL = 0 AND PARENT_ID IS NULL
    ORDER BY 1
    INTO :V$TYPE_ID
  DO
  BEGIN
    FOR
      SELECT TAG
      FROM LISTVALS
      WHERE LIST_ID = 25 AND IS_DEL = 0 AND PARENT_ID = 2140
      ORDER BY CAST(TAG AS INTEGER)
      INTO :V$S
    DO
    BEGIN
      V$CNT = 0;
      SELECT COALESCE(COUNT(DISTINCT M.GROUP_ID), 0)
      FROM PERSON_MOVEMENTS M
      JOIN LINKS L9 ON L9.OBJ_ID = M.GROUP_ID AND L9.PARENT_TYPE_ID = 8 AND (L9.DATE_DEL IS NULL OR L9.DATE_DEL > :I$DATE)
      JOIN VALL V1549 ON V1549.OBJ_ID = L9.OBJ_ID AND V1549.PARAM_ID = 1549 AND V1549.IS_DEL = 0 AND V1549.LISTVAL_ID = :V$TYPE_ID -- направленность группы
      JOIN LINKS L8 ON L8.OBJ_ID = L9.PARENT_ID AND L8.PARENT_TYPE_ID = 7 AND L8.DATE_DEL IS NULL
      JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0 -- этап
      JOIN LISTVALS LV ON LV.LISTVAL_ID = V49.LISTVAL_ID AND LV.IS_DEL = 0 AND LV.TAG = :V$S -- возраст группы
      JOIN LINKS L7 ON L7.OBJ_ID = L8.PARENT_ID AND L7.PARENT_TYPE_ID = 2 AND L7.DATE_DEL IS NULL
      JOIN VALL V43 ON V43.OBJ_ID = L7.OBJ_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0 AND V43.LISTVAL_ID IN (21, 3263, 3264) -- ступень ДО
      WHERE M.DATE_DEL IS NULL AND M.GROUP_TYPE_ID = 9 AND (M.DATE_OUT IS NULL OR M.DATE_OUT > :I$DATE) AND
        ((:DB_LVL = 1 AND M.OU_ID = :I$OBJ_ID) OR
        (:DB_LVL = 2 AND M.OU_ID IN (SELECT L.OBJ_ID FROM LINKS L WHERE L.OBJ_TYPE_ID = 2 AND L.PARENT_ID = :I$OBJ_ID AND L.DATE_DEL IS NULL)) OR
        (:DB_LVL = 3 AND M.OU_ID IN (SELECT L.OBJ_ID FROM LINKS L WHERE L.OBJ_TYPE_ID = 2 AND L.PARENT_TYPE_ID = 111 AND L.DATE_DEL IS NULL)))
      INTO :V$CNT;

      TAG_NAME = 'group_scope:itm';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'group_scope:itm:type_id';
      VAL = V$TYPE_ID;
      SUSPEND;
      TAG_NAME = 'group_scope:itm:age';
      VAL = V$S;
      SUSPEND;
      TAG_NAME = 'group_scope:itm:cnt';
      VAL = V$CNT;
      SUSPEND;
    END
  END

  -- Раздел 5. Распределение мест в группах по направленности и возрасту детей, единица
  -- Для количества мест используем «Кол-во ученических мест, нормативное». Из всей таблицы знаем только значение графы 3 (для сада только)
  -- Определяем  принадлежность здания к ДО ступени образования по наличию игровых/групповых комнат
  TAG_NAME = 'slot_cnt';
  SELECT SUM(V503.VAL)
  FROM LINKS L73
  JOIN LINKS L16 ON L16.PARENT_ID = L73.OBJ_ID AND L16.OBJ_TYPE_ID = 16 AND L16.DATE_DEL IS NULL
  JOIN VALI V503 ON V503.OBJ_ID = L16.OBJ_ID AND V503.PARAM_ID = 503 AND V503.IS_DEL = 0
  WHERE L73.OBJ_TYPE_ID = 73 AND L73.DATE_DEL IS NULL AND
    ((:DB_LVL = 1 AND L73.PARENT_ID = :I$OBJ_ID) OR
    (:DB_LVL = 2 AND L73.PARENT_ID IN (SELECT L.OBJ_ID FROM LINKS L WHERE L.OBJ_TYPE_ID = 2 AND L.PARENT_ID = :I$OBJ_ID AND L.DATE_DEL IS NULL)) OR
    (:DB_LVL = 3 AND L73.PARENT_ID IN (SELECT L.OBJ_ID FROM LINKS L WHERE L.OBJ_TYPE_ID = 2 AND L.PARENT_TYPE_ID = 111 AND L.DATE_DEL IS NULL)))
    AND L16.OBJ_ID IN (
      SELECT DISTINCT L61.PARENT_ID
      FROM LINKS L61
      JOIN VALL V526 ON V526.OBJ_ID = L61.OBJ_ID AND V526.PARAM_ID = 526 AND V526.IS_DEL = 0 AND V526.LISTVAL_ID IN (10957, 10958)
      WHERE L61.OBJ_TYPE_ID = 61 AND L61.PARENT_TYPE_ID = 16 AND L61.DATE_DEL IS NULL)
  INTO :VAL;
  SUSPEND;

  -- Раздел 6 и 7. Численность воспитанников в группах, человек (на конец отчетного года)
  TAG_NAME = 'students::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT DISTINCT CAST(LV.TAG AS INTEGER), M.PERSON_ID, V207.LISTVAL_ID, IIF(V2373.LISTVAL_ID IS NOT NULL, IIF(V2375.VAL IS NOT NULL AND V2375.VAL <= :I$DATE, V2373.LISTVAL_ID, NULL), NULL),
      V91.LISTVAL_ID, M.GROUP_ID, V2379.LISTVAL_ID, M.ADAPT_ID
    FROM PERSON_MOVEMENTS M
    JOIN LINKS L9 ON L9.OBJ_ID = M.GROUP_ID AND L9.PARENT_TYPE_ID = 8 AND (L9.DATE_DEL IS NULL OR L9.DATE_DEL > :I$DATE)
    JOIN VALL V1549 ON V1549.OBJ_ID = L9.OBJ_ID AND V1549.PARAM_ID = 1549 AND V1549.IS_DEL = 0 --AND (:I$GROUP_TYPE IS NULL OR V1549.LISTVAL_ID = :I$GROUP_TYPE)  -- направленность группы
    JOIN LINKS L8 ON L8.OBJ_ID = L9.PARENT_ID AND L8.PARENT_TYPE_ID = 7 AND L8.DATE_DEL IS NULL
    JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0                    -- этап
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V49.LISTVAL_ID AND LV.IS_DEL = 0
    JOIN LINKS L7 ON L7.OBJ_ID = L8.PARENT_ID AND L7.PARENT_TYPE_ID = 2 AND L7.DATE_DEL IS NULL
    JOIN VALL V43 ON V43.OBJ_ID = L7.OBJ_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0 AND V43.LISTVAL_ID IN (21, 3263, 3264) -- ступень ДО
    LEFT JOIN VALL V91 ON V91.OBJ_ID = M.PERSON_ID AND V91.PARAM_ID = 91 AND V91.IS_DEL = 0             -- гражданство
    LEFT JOIN VALL V207 ON V207.OBJ_ID = M.PERSON_ID AND V207.PARAM_ID = 207 AND V207.IS_DEL = 0        -- ОВЗ
    LEFT JOIN LINKS L295 ON L295.PARENT_ID = M.PERSON_ID AND L295.OBJ_TYPE_ID = 295 AND (L295.DATE_DEL IS NULL OR L295.DATE_DEL > :I$DATE)
    LEFT JOIN VALL V2373 ON V2373.OBJ_ID = L295.OBJ_ID AND V2373.PARAM_ID = 2373 AND V2373.IS_DEL = 0   -- группа инвалидности
    LEFT JOIN VALD V2375 ON V2375.OBJ_ID = L295.OBJ_ID AND V2375.PARAM_ID = 2375 AND V2375.IS_DEL = 0   -- срок действия группы инвалидности
    LEFT JOIN VALR V3075 ON V3075.OBJ_ID = M.GROUP_ID AND V3075.PARAM_ID = 3075 AND V3075.IS_DEL = 0    -- УП группы
    LEFT JOIN LINKS LP57 ON LP57.OBJ_ID = V3075.VAL AND LP57.PARENT_TYPE_ID = 57 AND LP57.DATE_DEL IS NULL
    LEFT JOIN VALL V2379 ON V2379.OBJ_ID = LP57.PARENT_ID AND V2379.PARAM_ID = 2379 AND V2379.IS_DEL = 0-- адаптированность ОП
    WHERE M.DATE_DEL IS NULL AND M.GROUP_TYPE_ID = 9 AND (M.DATE_OUT IS NULL OR M.DATE_OUT > :I$DATE) AND
      ((:DB_LVL = 1 AND M.OU_ID = :I$OBJ_ID) OR
      (:DB_LVL = 2 AND M.OU_ID IN (SELECT L.OBJ_ID FROM LINKS L WHERE L.OBJ_TYPE_ID = 2 AND L.PARENT_ID = :I$OBJ_ID AND L.DATE_DEL IS NULL)) OR
      (:DB_LVL = 3 AND M.OU_ID IN (SELECT L.OBJ_ID FROM LINKS L WHERE L.OBJ_TYPE_ID = 2 AND L.PARENT_TYPE_ID = 111 AND L.DATE_DEL IS NULL)))
    ORDER BY M.GROUP_ID
    INTO :V$GROUP_AGE, :V$PERSON_ID, :V$OVZ, :V$GROUP_ID, :V$ID, :V$TYPE_ID, :V$CNT, :V$ADAPT_ID
  DO
  BEGIN
    TAG_NAME = 'students:itm';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'students:itm:grp_age';
    VAL = V$GROUP_AGE;
    SUSPEND;
    TAG_NAME = 'students:itm:ovz';
    VAL = V$OVZ;
    SUSPEND;
    TAG_NAME = 'students:itm:disability';
    VAL = V$GROUP_ID;
    SUSPEND;
    TAG_NAME = 'students:itm:nation';
    VAL = V$ID;
    SUSPEND;
    TAG_NAME = 'students:itm:grp_type_id';
    VAL = NULL;
    SELECT I FROM VAL_GET(:V$TYPE_ID, 1549) INTO VAL;
    SUSPEND;
    -- найдем полный возраст в годах на конец отчетного периода
    TAG_NAME = 'students:itm:age';
    SELECT V FROM VAL_GET(:V$PERSON_ID, 89) INTO :V$DT;
    VAL = NULL;
    VAL = DATEDIFF(YEAR, V$DT, I$DATE);
    SUSPEND;
    TAG_NAME = 'students:itm:sex';
    VAL = NULL;
    SELECT I FROM VAL_GET(:V$PERSON_ID, 88) INTO :VAL;
    SUSPEND;
    -- Адаптированность можно найти через параметр класса если год совпадает с учебным. Иначе надо искать в движениях
    TAG_NAME = 'students:itm:is_adapt';
    VAL = NULL;
    IF (YR = CURR_Y) THEN VAL = V$CNT <> 11187; ELSE VAL = :V$ADAPT_ID <> 11187;
    SUSPEND;
  END

  -- Среднегодовая численность воспитанников. Перебираем месяцы. Ищем численность на 1-e число кажого месяца, в итоге выдаем среднее арифметическое
  TAG_NAME = 'student_avg_cnt';
  VAL = NULL;
  I = 0;
  WHILE (I < 12) DO
  BEGIN
    I = I + 1;
    SELECT CAST(:YR || '-' || :I || '-01' AS DATE) FROM RDB$DATABASE INTO :V$DT1;
    SELECT COALESCE(:F, 0) + COALESCE(COUNT(DISTINCT M.PERSON_ID), 0)
    FROM PERSON_MOVEMENTS M
    JOIN LINKS L9 ON L9.OBJ_ID = M.GROUP_ID AND L9.PARENT_TYPE_ID = 8 AND (L9.DATE_DEL IS NULL OR L9.DATE_DEL > :V$DT1)
    JOIN LINKS L8 ON L8.OBJ_ID = L9.PARENT_ID AND L8.PARENT_TYPE_ID = 7 AND L8.DATE_DEL IS NULL
    JOIN LINKS L7 ON L7.OBJ_ID = L8.PARENT_ID AND L7.PARENT_TYPE_ID = 2 AND L7.DATE_DEL IS NULL
    JOIN VALL V43 ON V43.OBJ_ID = L7.OBJ_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0 AND V43.LISTVAL_ID IN (21, 3263, 3264) -- ступень ДО
    WHERE M.DATE_DEL IS NULL AND M.GROUP_TYPE_ID = 9 AND M.IS_VD = 0 AND (M.DATE_OUT IS NULL OR M.DATE_OUT > :V$DT1) AND
      ((:DB_LVL = 1 AND M.OU_ID = :I$OBJ_ID) OR
      (:DB_LVL = 2 AND M.OU_ID IN (SELECT L.OBJ_ID FROM LINKS L WHERE L.OBJ_TYPE_ID = 2 AND L.PARENT_ID = :I$OBJ_ID AND L.DATE_DEL IS NULL)) OR
      (:DB_LVL = 3 AND M.OU_ID IN (SELECT L.OBJ_ID FROM LINKS L WHERE L.OBJ_TYPE_ID = 2 AND L.PARENT_TYPE_ID = 111 AND L.DATE_DEL IS NULL)))
    INTO :F;
  END
  VAL = CAST(F / 12 AS NUMERIC(14, 2));
  SUSPEND;

  -- Раздел 8-12. Движение работников, образование, стаж, тип трудоустройства
  -- Проверим, есть ли штатные расписания
  IF (NOT EXISTS(SELECT FIRST 1 1
    FROM LINKS L505
    JOIN VALD V3487 ON V3487.OBJ_ID = L505.OBJ_ID AND V3487.PARAM_ID = 3487 AND V3487.IS_DEL = 0
    JOIN VALL V3490 ON V3490.OBJ_ID = L505.OBJ_ID AND V3490.PARAM_ID = 3490 AND V3490.IS_DEL = 0 AND V3490.LISTVAL_ID IN (11715, 14261) -- действующее или архивное
    LEFT JOIN VALD V3489 ON V3489.OBJ_ID = L505.OBJ_ID AND V3489.PARAM_ID = 3489 AND V3489.IS_DEL = 0
    WHERE L505.OBJ_TYPE_ID = 505 AND L505.DATE_DEL IS NULL
      AND L505.PARENT_ID = (SELECT FIRST 1 L508.OBJ_ID FROM LINKS L508 WHERE L508.OBJ_TYPE_ID = 508 AND L508.DATE_DEL IS NULL AND
        ((:DB_LVL = 1 AND L508.PARENT_ID = :I$OBJ_ID) OR
        (:DB_LVL = 2 AND L508.PARENT_ID IN (SELECT L.OBJ_ID FROM LINKS L WHERE L.OBJ_TYPE_ID = 2 AND L.PARENT_ID = :I$OBJ_ID AND L.DATE_DEL IS NULL)) OR
        (:DB_LVL = 3 AND L508.PARENT_ID IN (SELECT L.OBJ_ID FROM LINKS L WHERE L.OBJ_TYPE_ID = 2 AND L.PARENT_TYPE_ID = 111 AND L.DATE_DEL IS NULL))))
      AND (V3490.LISTVAL_ID = 11715 OR (V3490.LISTVAL_ID = 14261 AND V3487.VAL <= :I$DATE AND V3489.VAL > :I$DATE))     -- действующее ШР на конец отчетного периода или просто действующее ШР.
  ) AND DB_LVL = 1) THEN
    EXCEPTION DATA_ERROR('Не найдено ни одно штатное расписание, действующее на конец отчетного периода, а также не найдено действующее штатное расписание');

  TAG_NAME = 'employees::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    -- выборка должностей на основе ШР
    SELECT V3492.LISTVAL_ID, V3493.VAL, V3494.VAL
    FROM LINKS L505
    JOIN VALL V3490 ON V3490.OBJ_ID = L505.OBJ_ID AND V3490.PARAM_ID = 3490 AND V3490.IS_DEL = 0 AND V3490.LISTVAL_ID IN (11715, 14261) -- действующее или архивное
    JOIN VALD V3487 ON V3487.OBJ_ID = L505.OBJ_ID AND V3487.PARAM_ID = 3487 AND V3487.IS_DEL = 0
    JOIN LINKS L506 ON L506.PARENT_ID = L505.OBJ_ID AND L506.OBJ_TYPE_ID = 506 AND L506.DATE_DEL IS NULL
    JOIN VALL V3492 ON V3492.OBJ_ID = L506.OBJ_ID AND V3492.PARAM_ID = 3492 AND V3492.IS_DEL = 0                        -- должность
    JOIN LISTVALS LV58 ON LV58.LISTVAL_ID = V3492.LISTVAL_ID AND LV58.IS_DEL = 0
    JOIN VALS V3494 ON V3494.OBJ_ID = L506.OBJ_ID AND V3494.PARAM_ID = 3494 AND V3494.IS_DEL = 0                        -- должность название
    LEFT JOIN VALF V3493 ON V3493.OBJ_ID = L506.OBJ_ID AND V3493.PARAM_ID = 3493 AND V3493.IS_DEL = 0 AND V3493.VAL > 0 -- кол-во ставок
    LEFT JOIN VALD V3489 ON V3489.OBJ_ID = L505.OBJ_ID AND V3489.PARAM_ID = 3489 AND V3489.IS_DEL = 0
    WHERE L505.OBJ_TYPE_ID = 505 AND L505.DATE_DEL IS NULL
      AND L505.PARENT_ID = (SELECT FIRST 1 L508.OBJ_ID FROM LINKS L508 WHERE L508.OBJ_TYPE_ID = 508 AND L508.DATE_DEL IS NULL AND
        ((:DB_LVL = 1 AND L508.PARENT_ID = :I$OBJ_ID) OR
        (:DB_LVL = 2 AND L508.PARENT_ID IN (SELECT L.OBJ_ID FROM LINKS L WHERE L.OBJ_TYPE_ID = 2 AND L.PARENT_ID = :I$OBJ_ID AND L.DATE_DEL IS NULL)) OR
        (:DB_LVL = 3 AND L508.PARENT_ID IN (SELECT L.OBJ_ID FROM LINKS L WHERE L.OBJ_TYPE_ID = 2 AND L.PARENT_TYPE_ID = 111 AND L.DATE_DEL IS NULL))))
      AND ((V3490.LISTVAL_ID = 14261 AND V3487.VAL <= :I$DATE AND V3489.VAL > :I$DATE) OR V3490.LISTVAL_ID = 11715)     -- действующее ШР на конец отчетного периода или просто действующее ШР.
    ORDER BY 1, 3
    INTO :V$ID, :F, :V$JOB_NAME
  DO
  BEGIN
    -- Для того, чтобы определить, являетcя ли должность педагогической, необходимо найти соответствующую строке ШР должность и ее атрибут 400 (nnn или LV.Tag = 'U' ??)
    V$TYPE_ID = NULL;
    V$S = NULL;
    SELECT FIRST 1 L13.OBJ_ID, TEACH_JB.V, COALESCE(LV.TAG, LV."FILTER"), V2850.VAL, V2851.VAL
    FROM LINKS L13
    JOIN VALL V58 ON V58.OBJ_ID = L13.OBJ_ID AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0 AND (V58.LISTVAL_ID = :V$ID)
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V58.LISTVAL_ID AND LV.IS_DEL = 0
    JOIN VALS V66 ON V66.OBJ_ID = L13.OBJ_ID AND V66.PARAM_ID = 66 AND V66.IS_DEL = 0 AND UPPER(TRIM(V66.VAL)) = UPPER(TRIM(:V$JOB_NAME))
    JOIN VALF V2850 ON V2850.OBJ_ID = L13.OBJ_ID AND V2850.PARAM_ID = 2850 AND V2850.IS_DEL = 0
    JOIN VALF V2851 ON V2851.OBJ_ID = L13.OBJ_ID AND V2851.PARAM_ID = 2851 AND V2851.IS_DEL = 0
    LEFT JOIN VAL_GET(L13.OBJ_ID, 400, 0) TEACH_JB ON 1 = 1 -- пед должность
    WHERE L13.OBJ_TYPE_ID = 13 AND L13.DATE_DEL IS NULL
      AND (L13.PARENT_ID = :I$OBJ_ID OR L13.PARENT_ID IN (SELECT DISTINCT L.OBJ_ID FROM LINKS L WHERE L.OBJ_TYPE_ID = 211 AND L.PARENT_ID = :I$OBJ_ID AND L.DATE_DEL IS NULL))
    INTO :V$TYPE_ID, :V$S, :V$TAG, :V$RATE_USED, :V$RATE_FREE;

    FOR
      SELECT IIF(V587.LISTVAL_ID = 207, V71.VAL, 0), V73.VAL, V74.VAL, V458.LISTVAL_ID, V587.LISTVAL_ID, LP14.PARENT_ID
      FROM LINKS L15
      JOIN VALF V71 ON V71.OBJ_ID = L15.OBJ_ID AND V71.PARAM_ID = 71 AND V71.IS_DEL = 0           -- кол-во занимаемых ставок
      JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0           -- дата приема
      JOIN VALL V587 ON V587.OBJ_ID = L15.OBJ_ID AND V587.PARAM_ID = 587 AND V587.IS_DEL = 0      -- условия приёма на должность
      JOIN LINKS LP14 ON LP14.OBJ_ID = L15.OBJ_ID AND LP14.PARENT_TYPE_ID = 14 AND LP14.DATE_DEL IS NULL
      LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0      -- дата увольнения
      LEFT JOIN VALL V458 ON V458.OBJ_ID = L15.OBJ_ID AND V458.PARAM_ID = 458 AND V458.IS_DEL = 0 -- основание для увольнения
      WHERE L15.OBJ_TYPE_ID = 15 AND L15.PARENT_ID = :V$TYPE_ID AND L15.DATE_DEL IS NULL
        AND (V74.VAL IS NULL OR V74.VAL >= :V$DT_FROM) -- отбрасываем движения, завершившиеся до начала отчетного периода
      INTO :F1, :V$DT, :V$DT1, :V$GROUP_ID, :V$CNT, :V$PERSON_ID
    DO
    BEGIN
      TAG_NAME = 'employees:itm';
      VAL = NULL;
      SUSPEND;
      --TAG_NAME = 'employees:itm:person_id'; --nnn для отладки
      --VAL = V$PERSON_ID;
      --SUSPEND;
      TAG_NAME = 'employees:itm:job_id';
      VAL = :V$ID;
      SUSPEND;
      --TAG_NAME = 'employees:itm:job_name'; --nnn для отладки
      --VAL = V$JOB_NAME;
      --SUSPEND;
      TAG_NAME = 'employees:itm:is_teach';
      VAL = V$S;
      SUSPEND;
      TAG_NAME = 'employees:itm:job_tag';
      VAL = V$TAG;
      SUSPEND;
      TAG_NAME = 'employees:itm:rate';
      VAL = CAST(F AS NUMERIC(15, 2));
      SUSPEND;
      TAG_NAME = 'employees:itm:rate_used';
      VAL = CAST(V$RATE_USED AS NUMERIC(15, 2));
      SUSPEND;
      TAG_NAME = 'employees:itm:rate_used_list';
      VAL = CAST(F1 AS NUMERIC(15, 2));
      SUSPEND;
      TAG_NAME = 'employees:itm:rate_free';
      VAL = CAST(V$RATE_FREE AS NUMERIC(15, 2));
      SUSPEND;
      TAG_NAME = 'employees:itm:dt_admission';
      SELECT VAL FROM DATE2ISO(:V$DT) INTO :VAL;
      SUSPEND;
      TAG_NAME = 'employees:itm:dt_discharge';
      SELECT VAL FROM DATE2ISO(:V$DT1) INTO :VAL;
      SUSPEND;
      TAG_NAME = 'employees:itm:discharge_id';
      VAL = :V$GROUP_ID;
      SUSPEND;
      TAG_NAME = 'employees:itm:admission_id';
      VAL = :V$CNT;
      SUSPEND;
      I = NULL;
      SELECT I FROM VAL_GET(:V$PERSON_ID, 239) INTO :VAL;
      TAG_NAME = 'employees:itm:sex';
      SUSPEND;
      -- найдем полный возраст в годах на конец отчетного периода
      SELECT V FROM VAL_GET(:V$PERSON_ID, 241) INTO :V$DT;
      TAG_NAME = 'employees:itm:age';
      V$DT1 = CAST(YR + 1 AS VARCHAR(4)) || '-01-01';
      VAL = DATEDIFF(YEAR, V$DT, V$DT1);
      SUSPEND;
      -- Квалификационная категория по основной должности
      TAG_NAME = 'employees:itm:qual_cat';
      SELECT I FROM VAL_GET(:V$PERSON_ID, 281) INTO :VAL;
      SUSPEND;
      -- Стаж работы, в днях
      TAG_NAME = 'employees:itm:experience_ttl';
      I = NULL;
      SELECT SUM(V.DAYS360_COUNT)
      FROM LINKS L85
      JOIN VALL V465 ON V465.OBJ_ID = L85.OBJ_ID AND V465.PARAM_ID = 465 AND V465.IS_DEL = 0 AND V465.LISTVAL_ID = 941 -- общий
      JOIN VALD V466 ON V466.OBJ_ID = L85.OBJ_ID AND V466.PARAM_ID = 466 AND V466.IS_DEL = 0
      LEFT JOIN VALD V467 ON V467.OBJ_ID = L85.OBJ_ID AND V467.PARAM_ID = 467 AND V467.IS_DEL = 0
      LEFT JOIN GET_DAYS360_COUNT(V466.VAL, COALESCE(V467.VAL, :I$DATE)) V ON 1 = 1
      WHERE L85.PARENT_ID = :V$PERSON_ID AND L85.OBJ_TYPE_ID = 85 AND L85.DATE_DEL IS NULL
      INTO :I;
      SELECT CAST(:I / 360 AS INTEGER) FROM RDB$DATABASE INTO :VAL;
      SUSPEND;
      TAG_NAME = 'employees:itm:experience_teach';
      I = NULL;
      SELECT SUM(V.DAYS360_COUNT)
      FROM LINKS L85
      JOIN VALL V465 ON V465.OBJ_ID = L85.OBJ_ID AND V465.PARAM_ID = 465 AND V465.IS_DEL = 0 AND V465.LISTVAL_ID = 942 -- педагогический
      JOIN VALD V466 ON V466.OBJ_ID = L85.OBJ_ID AND V466.PARAM_ID = 466 AND V466.IS_DEL = 0
      LEFT JOIN VALD V467 ON V467.OBJ_ID = L85.OBJ_ID AND V467.PARAM_ID = 467 AND V467.IS_DEL = 0
      LEFT JOIN GET_DAYS360_COUNT(V466.VAL, COALESCE(V467.VAL, :I$DATE)) V ON 1 = 1
      WHERE L85.PARENT_ID = :V$PERSON_ID AND L85.OBJ_TYPE_ID = 85 AND L85.DATE_DEL IS NULL
      INTO :I;
      SELECT CAST(:I / 360 AS INTEGER) FROM RDB$DATABASE INTO :VAL;
      SUSPEND;
      -- образование сотрудника
      V$OVZ = NULL;
      V$DT1 = NULL;
      V$SPEC = NULL;
      SELECT FIRST 1 V284.LISTVAL_ID, V290.VAL, V291.VAL
      FROM LINKS L33
      JOIN VALL V284 ON V284.OBJ_ID = L33.OBJ_ID AND V284.PARAM_ID = 284 AND V284.IS_DEL = 0
      JOIN VALD V290 ON V290.OBJ_ID = L33.OBJ_ID AND V290.PARAM_ID = 290 AND V290.IS_DEL = 0
      JOIN VALS V291 ON V291.OBJ_ID = L33.OBJ_ID AND V291.PARAM_ID = 291 AND V291.IS_DEL = 0
      WHERE L33.PARENT_ID = :V$PERSON_ID AND L33.OBJ_TYPE_ID = 33 AND L33.DATE_DEL IS NULL
      ORDER BY V290.VAL DESC
      INTO :V$OVZ, :V$DT1, :V$SPEC;
      TAG_NAME = 'employees:itm:edu_type';
      VAL = V$OVZ;
      SUSPEND;
      TAG_NAME = 'employees:itm:edu_complete_dt';
      SELECT VAL FROM DATE2ISO(:V$DT1) INTO :VAL;
      SUSPEND;
      TAG_NAME = 'employees:itm:diploma_spec';
      VAL = V$SPEC;
      SUSPEND;
      -- Дата последнего Повышения квалификации и Профессиональной переподготовки
      TAG_NAME = 'employees:itm:edu_retraining_dt';
      SELECT FIRST 1 V300.VAL
      FROM LINKS L35
      JOIN VALD V300 ON V300.OBJ_ID = L35.OBJ_ID AND V300.PARAM_ID IN (300, 310) AND V300.IS_DEL = 0
      WHERE L35.PARENT_ID = :V$PERSON_ID AND L35.OBJ_TYPE_ID IN (35, 36) AND L35.DATE_DEL IS NULL
      INTO :V$DT_EDU;
      SELECT VAL FROM DATE2ISO(:V$DT_EDU) INTO :VAL;
      SUSPEND;
    END
  END

  -- Раздел 13-14, 16. Здания, оснащение + интеpнет
  TAG_NAME = 'buildings::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT DISTINCT L16.OBJ_ID, V3402.VAL
    FROM LINKS L73
    JOIN LINKS L16 ON L16.PARENT_ID = L73.OBJ_ID AND L16.OBJ_TYPE_ID = 16 AND L16.DATE_DEL IS NULL --AND L16.DATE_INS <= :I$DATE  -- по состоянию на конец отчетного года
    LEFT JOIN VALR V3408 ON V3408.OBJ_ID = L16.OBJ_ID AND V3408.PARAM_ID = 3408 AND V3408.IS_DEL = 0
    LEFT JOIN VALF V3402 ON V3402.OBJ_ID = V3408.VAL AND V3402.PARAM_ID = 3402 AND V3402.IS_DEL = 0 -- площадь земельного участка
    LEFT JOIN LINKS L61 ON L61.PARENT_ID = L16.OBJ_ID AND L61.OBJ_TYPE_ID = 61 AND L61.DATE_DEL IS NULL
    LEFT JOIN VALL V526 ON V526.OBJ_ID = L61.OBJ_ID AND V526.PARAM_ID = 526 AND V526.IS_DEL = 0
    LEFT JOIN LINKS L257 ON L257.PARENT_ID = L16.OBJ_ID AND L257.OBJ_TYPE_ID = 257 AND L257.DATE_DEL IS NULL
    LEFT JOIN LINKS L ON L.PARENT_ID = L257.OBJ_ID AND L.OBJ_TYPE_ID = 61 AND L.DATE_DEL IS NULL
    LEFT JOIN VALL V ON V.OBJ_ID = L.OBJ_ID AND V.PARAM_ID = 526 AND V.IS_DEL = 0
    WHERE L73.OBJ_TYPE_ID = 73 AND L73.DATE_DEL IS NULL AND
      ((:DB_LVL = 1 AND L73.PARENT_ID = :I$OBJ_ID) OR
      (:DB_LVL = 2 AND L73.PARENT_ID IN (SELECT L.OBJ_ID FROM LINKS L WHERE L.OBJ_TYPE_ID = 2 AND L.PARENT_ID = :I$OBJ_ID AND L.DATE_DEL IS NULL)) OR
      (:DB_LVL = 3 AND L73.PARENT_ID IN (SELECT L.OBJ_ID FROM LINKS L WHERE L.OBJ_TYPE_ID = 2 AND L.PARENT_TYPE_ID = 111 AND L.DATE_DEL IS NULL)))
      AND (V526.LISTVAL_ID IN (10957, 10958) OR V.LISTVAL_ID IN (10957, 10958)) --групповая (игровая)
    INTO :V$ID, :F1
  DO
  BEGIN
    TAG_NAME = 'buildings:itm';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'buildings:itm:id';
    VAL = V$ID;
    SUSPEND;
    TAG_NAME = 'buildings:itm:land_property';
    VAL = NULL;
    VAL = CAST(F1 AS NUMERIC(15, 1));
    SUSPEND;
    TAG_NAME = 'buildings:itm:square';
    VAL = NULL;
    SELECT V.VAL FROM VALF V WHERE V.OBJ_ID = :V$ID AND V.PARAM_ID = 496 AND V.IS_DEL = 0 INTO :F;
    VAL = CAST(F AS NUMERIC(15, 1));
    SUSPEND;
    TAG_NAME = 'buildings:itm:square_study';
    VAL = NULL;
    SELECT V.VAL FROM VALF V WHERE V.OBJ_ID = :V$ID AND V.PARAM_ID = 499 AND V.IS_DEL = 0 INTO :F;
    VAL = CAST(F AS NUMERIC(15, 1));
    SUSPEND;
    TAG_NAME = 'buildings:itm:owner_type';
    VAL = NULL;
    SELECT V.LISTVAL_ID FROM VALL V WHERE V.OBJ_ID = :V$ID AND V.PARAM_ID = 504 AND V.IS_DEL = 0 INTO :VAL;
    SUSPEND;
    TAG_NAME = 'buildings:itm:plumbing';
    VAL = NULL;
    SELECT V.LISTVAL_ID FROM VALL V WHERE V.OBJ_ID = :V$ID AND V.PARAM_ID = 510 AND V.IS_DEL = 0 INTO :VAL;
    SUSPEND;
    TAG_NAME = 'buildings:itm:heating';
    VAL = NULL;
    SELECT V.LISTVAL_ID FROM VALL V WHERE V.OBJ_ID = :V$ID AND V.PARAM_ID = 509 AND V.IS_DEL = 0 INTO :VAL;
    SUSPEND;
    TAG_NAME = 'buildings:itm:drain';
    VAL = NULL;
    SELECT V.LISTVAL_ID FROM VALL V WHERE V.OBJ_ID = :V$ID AND V.PARAM_ID = 511 AND V.IS_DEL = 0 INTO :VAL;
    SUSPEND;
    TAG_NAME = 'buildings:itm:walls_material';
    VAL = NULL;
    SELECT V.LISTVAL_ID FROM VALL V WHERE V.OBJ_ID = :V$ID AND V.PARAM_ID = 489 AND V.IS_DEL = 0 INTO :VAL;
    SUSPEND;
    TAG_NAME = 'buildings:itm:state';
    VAL = NULL;
    SELECT V.LISTVAL_ID FROM VALL V WHERE V.OBJ_ID = :V$ID AND V.PARAM_ID = 488 AND V.IS_DEL = 0 INTO :VAL;
    SUSPEND;
  END

  -- Раздел 13. Здания, скорость подключения к интернет
  TAG_NAME = 'internet::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT DISTINCT L61.OBJ_ID, MAX(V701.VAL)
    FROM LINKS L116
    JOIN VALI V701 ON V701.OBJ_ID = L116.OBJ_ID AND V701.PARAM_ID = 701 AND V701.IS_DEL = 0
    JOIN LINKS L117 ON L117.PARENT_ID = L116.OBJ_ID AND L117.OBJ_TYPE_ID = 117 AND L117.DATE_DEL IS NULL
      --AND L117.DATE_INS <= :I$DATE -- данные могут быть внесчены задним числом и учтены не будут. Лучше выводить на текущий момент, пользователь подправит руками, если что
    JOIN VALR V703 ON V703.OBJ_ID = L117.OBJ_ID AND V703.PARAM_ID = 703 AND V703.IS_DEL = 0
    JOIN LINKS L61 ON L61.OBJ_ID = V703.VAL AND L61.OBJ_TYPE_ID = 61 AND L61.DATE_DEL IS NULL
    WHERE L116.OBJ_TYPE_ID = 116 AND L116.DATE_DEL IS NULL AND
      ((:DB_LVL = 1 AND L116.PARENT_ID = :I$OBJ_ID) OR
      (:DB_LVL = 2 AND L116.PARENT_ID IN (SELECT L.OBJ_ID FROM LINKS L WHERE L.OBJ_TYPE_ID = 2 AND L.PARENT_ID = :I$OBJ_ID AND L.DATE_DEL IS NULL)) OR
      (:DB_LVL = 3 AND L116.PARENT_ID IN (SELECT L.OBJ_ID FROM LINKS L WHERE L.OBJ_TYPE_ID = 2 AND L.PARENT_TYPE_ID = 111 AND L.DATE_DEL IS NULL)))
    GROUP BY 1
    INTO :V$ID, :V$CNT
  DO
  BEGIN
    TAG_NAME = 'internet:itm';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'internet:itm:building_cnt';
    VAL = V$ID;
    SUSPEND;
    TAG_NAME = 'internet:itm:speed';
    VAL = V$CNT;
    SUSPEND;
  END

  -- Раздел 15 Помещения
  TAG_NAME = 'rooms::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT DISTINCT LV.LISTVAL_ID, COUNT(IIF(V526.OBJ_ID IS NOT NULL, 1, NULL))
    FROM LISTVALS LV
    LEFT JOIN VALL V526 ON V526.PARAM_ID = 526 AND V526.IS_DEL = 0 AND V526.LISTVAL_ID = LV.LISTVAL_ID
    LEFT JOIN LINKS L ON L.OBJ_ID = V526.OBJ_ID AND L.DATE_DEL IS NULL AND L.PARENT_ID IN
      (SELECT DISTINCT L16.OBJ_ID  -- из зданий берет только те, где есть группы ДОУ
      FROM LINKS L73
      JOIN LINKS L16 ON L16.PARENT_ID = L73.OBJ_ID AND L16.OBJ_TYPE_ID = 16 AND L16.DATE_DEL IS NULL --AND L16.DATE_INS <= :I$DATE  -- по состоянию на конец отчетного года
      LEFT JOIN LINKS L61 ON L61.PARENT_ID = L16.OBJ_ID AND L61.OBJ_TYPE_ID = 61 AND L61.DATE_DEL IS NULL
      LEFT JOIN VALL V526 ON V526.OBJ_ID = L61.OBJ_ID AND V526.PARAM_ID = 526 AND V526.IS_DEL = 0
      LEFT JOIN LINKS L257 ON L257.PARENT_ID = L16.OBJ_ID AND L257.OBJ_TYPE_ID = 257 AND L257.DATE_DEL IS NULL
      LEFT JOIN LINKS L ON L.PARENT_ID = L257.OBJ_ID AND L.OBJ_TYPE_ID = 61 AND L.DATE_DEL IS NULL
      LEFT JOIN VALL V ON V.OBJ_ID = L.OBJ_ID AND V.PARAM_ID = 526 AND V.IS_DEL = 0
      WHERE L73.OBJ_TYPE_ID = 73 AND L73.DATE_DEL IS NULL AND
        ((:DB_LVL = 1 AND L73.PARENT_ID = :I$OBJ_ID) OR
        (:DB_LVL = 2 AND L73.PARENT_ID IN (SELECT L.OBJ_ID FROM LINKS L WHERE L.OBJ_TYPE_ID = 2 AND L.PARENT_ID = :I$OBJ_ID AND L.DATE_DEL IS NULL)) OR
        (:DB_LVL = 3 AND L73.PARENT_ID IN (SELECT L.OBJ_ID FROM LINKS L WHERE L.OBJ_TYPE_ID = 2 AND L.PARENT_TYPE_ID = 111 AND L.DATE_DEL IS NULL)))
        AND (V526.LISTVAL_ID IN (10957, 10958) OR V.LISTVAL_ID IN (10957, 10958)) --групповая (игровая)) --групповая (игровая)
      )
    WHERE LV.LIST_ID = 20 AND LV.PARENT_ID IS NOT NULL AND LV.IS_DEL = 0
    GROUP BY 1
    ORDER BY 1
    INTO :V$TYPE_ID, :V$CNT
  DO
  BEGIN
    TAG_NAME = 'rooms:itm';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'rooms:itm:type';
    VAL = V$TYPE_ID;
    SUSPEND;
    TAG_NAME = 'rooms:itm:count';
    VAL = V$CNT;
    SUSPEND;
  END

  -- Раздел 18. МТР
  TAG_NAME = 'mtr::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT DISTINCT L114.OBJ_ID, V626.LISTVAL_ID, V604.LISTVAL_ID
    FROM LINKS L23
    JOIN LINKS L95 ON L95.PARENT_ID = L23.OBJ_ID AND L95.OBJ_TYPE_ID = 95 AND L95.DATE_DEL IS NULL      -- ТСО
    JOIN VALL V626 ON V626.OBJ_ID = L95.OBJ_ID AND V626.PARAM_ID = 626 AND V626.IS_DEL = 0              -- группа
    JOIN VALL V604 ON V604.OBJ_ID = L95.OBJ_ID AND V604.PARAM_ID = 604 AND V604.IS_DEL = 0              -- подгруппа
    JOIN LINKS L114 ON L114.PARENT_ID = L95.OBJ_ID AND L114.OBJ_TYPE_ID = 114 AND L114.DATE_DEL IS NULL -- инвентаризационная карта
      AND L114.DATE_INS <= :I$DATE                                                                      -- по состоянию на конец отчетного года
    JOIN VALS V682 ON V682.OBJ_ID = L114.OBJ_ID AND V682.PARAM_ID = 682 AND V682.IS_DEL = 0             -- год выпуска
      AND V682.VAL <= EXTRACT(YEAR FROM :I$DATE)
    LEFT JOIN VALD V687 ON V687.OBJ_ID = L114.OBJ_ID AND V687.PARAM_ID = 687 AND V687.IS_DEL = 0        -- дата вывода из эксплуатации
    WHERE L23.OBJ_TYPE_ID = 23 AND L23.DATE_DEL IS NULL AND
      V687.VAL IS NULL AND                   -- эксплуатируется
      ((:DB_LVL = 1 AND L23.PARENT_ID = :I$OBJ_ID) OR
      (:DB_LVL = 2 AND L23.PARENT_ID IN (SELECT L.OBJ_ID FROM LINKS L WHERE L.OBJ_TYPE_ID = 2 AND L.PARENT_ID = :I$OBJ_ID AND L.DATE_DEL IS NULL)) OR
      (:DB_LVL = 3 AND L23.PARENT_ID IN (SELECT L.OBJ_ID FROM LINKS L WHERE L.OBJ_TYPE_ID = 2 AND L.PARENT_TYPE_ID = 111 AND L.DATE_DEL IS NULL)))
    INTO :V$OVZ, :V$GROUP_ID, :V$ID
  DO
  BEGIN
    TAG_NAME = 'mtr:itm';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'mtr:itm:group_id';
    VAL = V$GROUP_ID;
    SUSPEND;
    TAG_NAME = 'mtr:itm:subgroup_id';
    VAL = V$ID;
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE REPORT_ADD (
    I$REPORT_ID BIGINT,
    I$TYPE_ID BIGINT,
    I$RES_ID BIGINT,
    I$TEMPL_ID BIGINT,
    I$LANG_CODE CHAR(2),
    I$REPORT_CAPTION VARCHAR(4000),
    I$TAG VARCHAR(100),
    I$IS_DEL SMALLINT = 0)
RETURNS (
    REPORT_ID BIGINT,
    RES_ID BIGINT)
AS
declare variable SORT_ORDER smallint;
BEGIN
    REPORT_ID = I$REPORT_ID;
    RES_ID = I$RES_ID;
    IF (:REPORT_ID IS NULL) THEN
    BEGIN
        SELECT MAX(SORT_ORDER) + 1
        FROM REPORTS
        INTO  :SORT_ORDER;
        IF (SORT_ORDER IS NULL) THEN
        BEGIN
            SORT_ORDER = 1;
        END

        INSERT INTO REPORTS
        (
            TYPE_ID,
            SORT_ORDER,
            TEMPL_ID,
            TAG
        )
        VALUES
        (
            :I$TYPE_ID,
            :SORT_ORDER,
            :I$TEMPL_ID,
            :I$TAG
        )
        RETURNING RES_ID
        INTO :RES_ID;
    END
    ELSE
    BEGIN
        UPDATE REPORTS
        SET TYPE_ID = :I$TYPE_ID,
            TEMPL_ID = :I$TEMPL_ID,
            TAG = :I$TAG,
            IS_DEL = :I$IS_DEL
        WHERE REPORT_ID = :REPORT_ID;
    END

    IF (RES_ID IS NOT NULL) THEN
    BEGIN
        EXECUTE PROCEDURE RES_ADD (:RES_ID,:I$LANG_CODE,:I$REPORT_CAPTION);
    END

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE REPORT_CJ_CORRS (
    I$OBJ_ID BIGINT)
RETURNS (
    REG_NAME VARCHAR(100),
    OOOD_NAME VARCHAR(400),
    OOOD_NUM VARCHAR(30),
    CLASS_NUM VARCHAR(20),
    CLASS_NAME VARCHAR(200),
    PUPIL_NAME VARCHAR(400),
    SUBJECT_NAME VARCHAR(600),
    USER_NAME VARCHAR(400),
    DATE_SRC VARCHAR(16),
    DATE_DST VARCHAR(16),
    TEXT_SRC VARCHAR(1000),
    TEXT_DST VARCHAR(1000),
    REASON VARCHAR(1000))
AS
declare variable OBJ_ID bigint;
declare variable OO_ID bigint;
declare variable M1 bigint;
declare variable M2 bigint;
declare variable OBJ_TYPE bigint;
declare variable FILTER_DISTRICT bigint;
declare variable FILTER_OO bigint;
begin
  -- Проверяем, что за фильтр нам свалился
  SELECT TYPE_ID FROM OBJECTS WHERE OBJ_ID = :I$OBJ_ID INTO :OBJ_TYPE;
  IF(OBJ_TYPE = 2) THEN FILTER_OO = I$OBJ_ID;
  ELSE IF(OBJ_TYPE = 111) THEN FILTER_DISTRICT = I$OBJ_ID;

  FOR
    SELECT C.CAPTION, L2.OBJ_ID, V2.VAL, V17.VAL
    FROM LINKS L2
    LEFT JOIN VALS V2 ON V2.OBJ_ID = L2.OBJ_ID AND V2.PARAM_ID = 2 AND V2.IS_DEL = 0
    LEFT JOIN VALI V17 ON V17.OBJ_ID = L2.OBJ_ID AND V17.PARAM_ID = 17 AND V17.IS_DEL = 0
    LEFT JOIN OBJECT_CAPTION_GET(L2.PARENT_ID) C ON 1 = 1
    WHERE L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND (L2.PARENT_TYPE_ID IS NULL OR L2.PARENT_TYPE_ID = 111)
      AND (:FILTER_DISTRICT IS NULL OR L2.PARENT_ID = :FILTER_DISTRICT) AND (:FILTER_OO IS NULL OR L2.OBJ_ID = :FILTER_OO)
    INTO :REG_NAME, :OO_ID, :OOOD_NAME, :OOOD_NUM
  DO
  BEGIN
      M1 = OO_ID / 1000000000;
      M2 = (M1 + 1) * 1000000000;
      M1 = M1 * 1000000000;

      FOR
          SELECT DISTINCT M.OBJ_ID
          FROM CS_METADATA M
          WHERE M.OBJ_ID >= :M1 AND M.OBJ_ID < :M2
          INTO :OBJ_ID
      DO
      BEGIN

          CLASS_NUM = NULL;
          CLASS_NAME = NULL;
          PUPIL_NAME = NULL;
          USER_NAME = NULL;
          USER_NAME = NULL;
          DATE_SRC = NULL;
          DATE_DST = NULL;
          TEXT_SRC = NULL;
          TEXT_DST = NULL;
          REASON = NULL;

          SELECT C.CAPTION, R.VAL
          FROM CS_METADATA M
          JOIN LINKS LP8 ON LP8.OBJ_ID = M.ATTRVALUE AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
          -- Только выпускные
          JOIN VALL V2388 ON V2388.OBJ_ID = LP8.OBJ_ID AND V2388.PARAM_ID = 2388 AND V2388.IS_DEL = 0 AND V2388.LISTVAL_ID <> 11217
          JOIN VALL V49 ON V49.OBJ_ID = LP8.PARENT_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
          JOIN LISTVALS LV ON LV.LISTVAL_ID = V49.LISTVAL_ID
          JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
          LEFT JOIN OBJECT_CAPTION_GET(M.ATTRVALUE) C ON 1 = 1
          WHERE M.OBJ_ID = :OBJ_ID AND M.ATTRNAME = 'CLASS_ID'
          INTO :CLASS_NAME, :CLASS_NUM;

          IF(CLASS_NUM IS NOT NULL) THEN CLASS_NUM = SUBSTRING(CLASS_NUM FROM 1 FOR POSITION(' ' IN CLASS_NUM) - 1);

          SELECT V55.VAL || ' ' || V56.VAL || COALESCE(' ' || V57.VAL, '')
          FROM CS_METADATA M
          JOIN VALS V55 ON V55.OBJ_ID = M.ATTRVALUE AND V55.PARAM_ID = 55 AND V55.IS_DEL = 0
          JOIN VALS V56 ON V56.OBJ_ID = M.ATTRVALUE AND V56.PARAM_ID = 56 AND V56.IS_DEL = 0
          LEFT JOIN VALS V57 ON V57.OBJ_ID = M.ATTRVALUE AND V57.PARAM_ID = 57 AND V57.IS_DEL = 0
          WHERE M.OBJ_ID = :OBJ_ID AND M.ATTRNAME = 'PUPIL_ID'
          INTO :PUPIL_NAME;

          SELECT C.CAPTION
          FROM CS_METADATA M
          LEFT JOIN OBJECT_CAPTION_GET(M.ATTRVALUE) C ON 1 = 1
          WHERE M.OBJ_ID = :OBJ_ID AND M.ATTRNAME = 'SUBJECT_ID'
          INTO :SUBJECT_NAME;

          SELECT C.CAPTION
          FROM CS_METADATA M
          LEFT JOIN OBJECT_CAPTION_GET(M.ATTRVALUE) C ON 1 = 1
          WHERE M.OBJ_ID = :OBJ_ID AND M.ATTRNAME = 'USER_ID' AND M.ATTRVALUE <> ''
          INTO :USER_NAME;

          SELECT M.ATTRVALUE
          FROM CS_METADATA M
          WHERE M.OBJ_ID = :OBJ_ID AND M.ATTRNAME = 'MARK_DATE'
          INTO :DATE_SRC;

          SELECT M.ATTRVALUE
          FROM CS_METADATA M
          WHERE M.OBJ_ID = :OBJ_ID AND M.ATTRNAME = 'APPLY_DATE'
          INTO :DATE_DST;

          SELECT M.ATTRVALUE
          FROM CS_METADATA M
          WHERE M.OBJ_ID = :OBJ_ID AND M.ATTRNAME = 'MARK_OLD'
          INTO :TEXT_SRC;

          SELECT M.ATTRVALUE
          FROM CS_METADATA M
          WHERE M.OBJ_ID = :OBJ_ID AND M.ATTRNAME = 'MARK_NEW'
          INTO :TEXT_DST;

          SELECT M.ATTRVALUE
          FROM CS_METADATA M
          WHERE M.OBJ_ID = :OBJ_ID AND M.ATTRNAME = 'REASON'
          INTO :REASON;

          IF(CLASS_NUM IS NOT NULL) THEN SUSPEND;

      END
  END
end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE REPORT_CLASSNET (
    I$SCHOOL_ID BIGINT,
    I$DATE DATE = CURRENT_DATE,
    I$LEVEL_ID BIGINT = NULL,
    I$FILTER VARCHAR(100) = NULL,
    I$MASTER_ID BIGINT = NULL)
RETURNS (
    VAL VARCHAR(4000))
AS
DECLARE VARIABLE V$TYPE_ID BIGINT;
DECLARE VARIABLE V$NAME VARCHAR(400);
DECLARE VARIABLE V$MASTER_VAL VARCHAR(250);
DECLARE VARIABLE V$COLOR VARCHAR(100);
DECLARE VARIABLE V$CLASS_NUM INTEGER;
DECLARE VARIABLE V$CLASS_CNT INTEGER;
DECLARE VARIABLE V$SCHOLAR_CNT INTEGER;
DECLARE VARIABLE V$CLASS_PUB_CNT INTEGER;
DECLARE VARIABLE V$SCHOLAR_PUB_CNT INTEGER;
DECLARE VARIABLE V$CLASS_INC_CNT INTEGER;
DECLARE VARIABLE V$CLASS_ZPR_CNT INTEGER;
DECLARE VARIABLE V$SCHOLAR_ZPR_CNT INTEGER;
DECLARE VARIABLE V$SCHOLAR_HOUSE_CNT INTEGER;
DECLARE VARIABLE V$CLASS_AVG NUMERIC(7,1);
DECLARE VARIABLE V$CLASS_NOT_ZPR_AVG NUMERIC(7,1);
DECLARE VARIABLE VAL1 VARCHAR(250);
DECLARE VARIABLE VAL2 VARCHAR(250);
DECLARE VARIABLE VAL3 VARCHAR(250);
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$STAGE_ID BIGINT;
DECLARE VARIABLE V$DIR BIGINT;
DECLARE VARIABLE V$OVZ BIGINT;
DECLARE VARIABLE V$ATHOME BIGINT;
DECLARE VARIABLE V$LEVEL_ID2 BIGINT;
DECLARE VARIABLE V$LEVEL_ID3 BIGINT;
DECLARE VARIABLE V$COST INTEGER;
DECLARE VARIABLE V$STAGE_ID2 BIGINT;
DECLARE VARIABLE V$STAGE_ID3 BIGINT;
DECLARE VARIABLE V$STAGE_ID4 BIGINT;
DECLARE VARIABLE V$STAGE_ID5 BIGINT;
DECLARE VARIABLE V$STAGE_ID6 BIGINT;
DECLARE VARIABLE V$STAGE_ID7 BIGINT;
begin

  -- Конструкция сделана чтобы выбирать данные через выборку отчетов в тонком клиенте
  -- I$LEVEL_ID - ступень образования (21, 22, 29 для ДОО, ОО, СПО), NULL если выбираем в старом формате

  -- Два параметра зависят от уровня, на котором выбираются. Для района (выдает только список ОУ):
  -- I$FILTER - включать коммерческие ОУ 0/1
  -- I$MASTER_ID - только ОУ указанного подчинения, ID по полю #6 справочник 166, может быть NULL или 0 если все
  -- Для ОУ, если оба параметра
  -- оба дополнительных параметра = NULL, сводная таблица по ОУ
  -- об дополнительных параметра <> NULL, детализация по ОУ
  -- I$FILTER - селектор по ОВЗ (0 = все, 1 = без ОВЗ, 2 = с ОВЗ) для района, селектор строки для ОУ
  -- I$MASTER_ID - выбор столбца

  -- Если параметр I$SCHOOL_ID не указан - выбираем главный корень дерева, ОУ или район
  IF(I$SCHOOL_ID IS NULL) THEN
    SELECT FIRST 1 OBJ_ID
    FROM LINKS
    WHERE PARENT_ID IS NULL AND OBJ_TYPE_ID IN (2, 111) AND DATE_DEL IS NULL
    INTO :I$SCHOOL_ID;

  IF(I$DATE IS NULL) THEN I$DATE = CURRENT_DATE;

  -- Смотрим тип объекта
  SELECT TYPE_ID
  FROM OBJECTS
  WHERE OBJ_ID = :I$SCHOOL_ID
  INTO :V$TYPE_ID;

  -- Старый формат выдачи
  IF(I$LEVEL_ID IS NULL) THEN
  BEGIN
    VAL = '<!DOCTYPE html>';
    VAL = VAL || '<html lang="ru">';
    VAL = VAL || '<head>';
    VAL = VAL || '<meta charset="utf-8" />';
    VAL = VAL || '<style>';
    VAL = VAL || 'html { font-family: Tahoma, Verdana, Arial;';
    VAL = VAL || 'font-size: 10pt; ';
    VAL = VAL || '} ';
    VAL = VAL || '.title1 { margin-bottom: 1em;';
    VAL = VAL || 'font-size: 120%;';
    VAL = VAL || 'font-weight: bold';
    VAL = VAL || '} ';
    VAL = VAL || 'table { border-collapse: collapse;';
    VAL = VAL || '} ';
    VAL = VAL || 'td, th { padding: 0.5em 1em;';
    VAL = VAL || 'border: 1px solid rgba(0,0,0,0.4);';
    VAL = VAL || 'text-align: left;';
    VAL = VAL || '} ';
    VAL = VAL || 'thead tr {';
    VAL = VAL || 'border-bottom: 1px solid rgba(0,0,0,0.4);';
    VAL = VAL || '} ';
    VAL = VAL || '.main td.ax { cursor: pointer;';
    VAL = VAL || 'transition: all 0.3s ease;';
    VAL = VAL || '} ';
    VAL = VAL || '.main td.ax:hover { background: rgba(0,0,0,0.1);';
    VAL = VAL || '} ';
    VAL = VAL || '.shade { display: none;';
    VAL = VAL || 'position: absolute;';
    VAL = VAL || 'left: 0;';
    VAL = VAL || 'top: 0;';
    VAL = VAL || 'right: 0;';
    VAL = VAL || 'bottom: 0;';
    VAL = VAL || 'background: rgba(0,0,0,0.8);';
    VAL = VAL || 'text-align: center;';
    VAL = VAL || 'padding-top: 20px';
    VAL = VAL || '} ';
    VAL = VAL || '.dtl { display: none;';
    VAL = VAL || 'border-radius: 4px;';
    VAL = VAL || 'border: 2px solid #000;';
    VAL = VAL || 'background: #fff;';
    VAL = VAL || 'padding: 1em;';
    VAL = VAL || 'text-align: left;';
    VAL = VAL || '} ';
    VAL = VAL || '.dtl .title { padding: 0.5em 1em;';
    VAL = VAL || 'font-size: 120%;';
    VAL = VAL || 'font-weight: bold;';
    VAL = VAL || 'cursor: pointer;';
    VAL = VAL || '} ';
    VAL = VAL || '.dtl .table { min-width: 40vw;';
    VAL = VAL || '} ';
    VAL = VAL || '.dtl .content { overflow-y: auto;';
    VAL = VAL || 'overflow-x: hidden;';
    VAL = VAL || 'height: 80vh;';
    VAL = VAL || '} ';
    VAL = VAL || '</style>';

    VAL = VAL || '</head>';
    VAL = VAL || '<body>';

    -- Заголовок отчета
    VAL = VAL || '<div class="title1">Отчет сеть классов по ' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$SCHOOL_ID)) || ' по состоянию на ' || (SELECT RESULT FROM DATE2STR(:I$DATE)) || '</div>';
    SUSPEND;

    -- Таблица и столбцы
    VAL = '<table class="table main" cellspacing="0" cellpadding="0" style="width: 100%"><thead><tr>';
    VAL = VAL || '<th>' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$SCHOOL_ID)) || '</th>';
    VAL = VAL || '<th>всего классов в школе</th>';
    VAL = VAL || '<th>всего уч-ся в школе</th>';
    VAL = VAL || '<th>общеобраз классы</th>';
    VAL = VAL || '<th>кол-во уч-ся общеобр</th>';
    VAL = VAL || '<th>кол-во классов имеющих в своем составе лиц с ОВЗ</th>';
    VAL = VAL || '<th>кол-во классов ОВЗ</th>';
    VAL = VAL || '<th>всего кол-во уч-ся ОВЗ</th>';
    VAL = VAL || '<th>ср наполн. по ОУ</th>';
    VAL = VAL || '<th>ср наполн. без корр</th>';
    VAL = VAL || '<th>кол-во надомников</th>';
    VAL = VAL || '<th>в т.ч. получ. питание</th>';
    VAL = VAL || '</tr></thead><tbody>';
    SUSPEND;

    FOR
      SELECT COLOR, NAME, CLASS_NUM, CLASS_CNT, SCHOLAR_CNT, CLASS_PUB_CNT, SCHOLAR_PUB_CNT, CLASS_INC_CNT, CLASS_ZPR_CNT, SCHOLAR_ZPR_CNT, SCHOLAR_HOUSE_CNT, CLASS_AVG, CLASS_NOT_ZPR_AVG
      FROM OU_CLASS_REPORT(:I$SCHOOL_ID, :I$DATE)
      INTO :V$COLOR, :V$NAME, :V$CLASS_NUM, :V$CLASS_CNT, :V$SCHOLAR_CNT, :V$CLASS_PUB_CNT, :V$SCHOLAR_PUB_CNT, :V$CLASS_INC_CNT, :V$CLASS_ZPR_CNT, :V$SCHOLAR_ZPR_CNT, :V$SCHOLAR_HOUSE_CNT, :V$CLASS_AVG, :V$CLASS_NOT_ZPR_AVG
    DO
    BEGIN
      -- IF(V$COLOR IS NULL OR V$COLOR = '') THEN V$COLOR = ''; ELSE V$COLOR = 'background: ' || REPLACE(V$COLOR, '$', '#');

      VAL = '<tr data-nx="' || V$CLASS_NUM || '">';
      VAL = VAL || '<td>' || V$NAME || '</td>';
      VAL = VAL || '<td>' || COALESCE(V$CLASS_CNT, '') || '</td>';
      VAL = VAL || '<td class="ax" onclick="details(' || V$CLASS_NUM || ', 0)">' || COALESCE(V$SCHOLAR_CNT, '') || '</td>';
      VAL = VAL || '<td>' || COALESCE(V$CLASS_PUB_CNT, '') || '</td>';
      VAL = VAL || '<td class="ax" onclick="details(' || V$CLASS_NUM || ', 1)">' || COALESCE(V$SCHOLAR_PUB_CNT, '') || '</td>';
      VAL = VAL || '<td>' || COALESCE(V$CLASS_INC_CNT, '') || '</td>';
      VAL = VAL || '<td>' || COALESCE(V$CLASS_ZPR_CNT, '') || '</td>';
      VAL = VAL || '<td class="ax" onclick="details(' || V$CLASS_NUM || ', 3)">' || COALESCE(V$SCHOLAR_ZPR_CNT, '') || '</td>';
      VAL = VAL || '<td>' || COALESCE(V$CLASS_AVG, '') || '</td>';
      VAL = VAL || '<td>' || COALESCE(V$CLASS_NOT_ZPR_AVG, '') || '</td>';
      VAL = VAL || '<td class="ax" onclick="details(' || V$CLASS_NUM || ', 2)">' || COALESCE(V$SCHOLAR_HOUSE_CNT, '') || '</td>';
      VAL = VAL || '<td></td>';
      VAL = VAL || '</tr>';
      SUSPEND;
    END

    VAL = '</tbody></table>';
    SUSPEND;
    VAL = '</body></html>';
    SUSPEND;

  END
  ELSE
  BEGIN

    IF(I$LEVEL_ID = 21) THEN
    BEGIN
      V$LEVEL_ID2 = 3263;
      V$LEVEL_ID3 = 3264;
    END
    ELSE IF(I$LEVEL_ID = 22) THEN
    BEGIN
      V$LEVEL_ID2 = 26;
      V$LEVEL_ID3 = 27;
    END

    -- Новый формат выдачи, тут будет всегда json - сборка форматирования идет на фронте
    IF(V$TYPE_ID = 111) THEN
    BEGIN
      -- Список ОУ с указанными критериями отбора
      VAL = '{"date":"' || (SELECT RESULT FROM DATE2STR(:I$DATE)) || '","level_id":"' || I$LEVEL_ID || '","items":[';
      SUSPEND;

      IF(I$MASTER_ID IS NOT NULL) THEN
        SELECT FIRST 1 V.VAL
        FROM LISTVALS_LIST(166) V      -- подчинение
        WHERE V.LISTVAL_ID = :I$MASTER_ID
        INTO :V$MASTER_VAL;

      V$CLASS_NUM = 0;
      FOR
        SELECT L2.OBJ_ID, COALESCE(V17.VAL, ''), COALESCE(V2.SVAL, '')
        FROM LINKS L2
        LEFT JOIN VALI V17 ON V17.OBJ_ID = L2.OBJ_ID AND V17.PARAM_ID = 17 AND V17.IS_DEL = 0
        LEFT JOIN VALS V2 ON V2.OBJ_ID = L2.OBJ_ID AND V2.PARAM_ID = IIF(:I$LEVEL_ID = 29, 999, 2) AND V2.IS_DEL = 0
        LEFT JOIN VALS V6 ON V6.OBJ_ID = L2.OBJ_ID AND V6.PARAM_ID = 6 AND V6.IS_DEL = 0
        LEFT JOIN VALL V8 ON V8.OBJ_ID = L2.OBJ_ID AND V8.PARAM_ID = 8 AND V8.IS_DEL = 0
        WHERE L2.PARENT_ID = :I$SCHOOL_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
          AND (:I$FILTER IS NULL OR :I$FILTER = '2' OR (:I$FILTER = '3' AND COALESCE(V8.LISTVAL_ID, 0) <> 5404))
          AND (:V$MASTER_VAL IS NULL OR V6.SVAL = :V$MASTER_VAL)
        ORDER BY 2 NULLS LAST, 3
        INTO :V$OBJ_ID, :VAL1, :V$NAME
      DO
      BEGIN
        IF(V$CLASS_NUM = 1) THEN VAL = ','; ELSE VAL = '';
        VAL = VAL || '{"id":"' || V$OBJ_ID || '","num":"' || V$CLASS_NUM || '","name":"' || (SELECT VAL FROM ESCAPE_STR(:V$NAME)) || '","school_num":"' || VAL1|| '"}';
        V$CLASS_NUM = 1;
        SUSPEND;
      END

      VAL = ']}';
      SUSPEND;
    END
    ELSE IF(V$TYPE_ID = 2 AND I$FILTER IS NULL AND I$MASTER_ID IS NULL) THEN
    BEGIN
      -- Сводная выборка по ОУ
      VAL = '{"date":"' || (SELECT RESULT FROM DATE2STR(:I$DATE)) || '","level_id":"' || I$LEVEL_ID || '","groups":[';
      SUSPEND;
      V$CLASS_NUM = 0;
      -- Все учебные коллективы на нужную дату, включая ГПД и экстернаты
      -- ГПД считаем по числу детей в них числящихся, только в текущем учебном году
      FOR
        SELECT DISTINCT M.GROUP_TYPE_ID + IIF(V369.LISTVAL_ID = 3318, 1000, 0), M.GROUP_ID, M.STAGE_ID, UPPER(M.NAME_IN), V592.LISTVAL_ID, LV.COST, V1549.LISTVAL_ID
        FROM PERSON_MOVEMENTS M
        LEFT JOIN VALL V592 ON V592.OBJ_ID = M.GROUP_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND M.GROUP_TYPE_ID = 9
        LEFT JOIN VALL V1549 ON V1549.OBJ_ID = M.GROUP_ID AND V1549.PARAM_ID = 1549 AND V1549.IS_DEL = 0 AND M.GROUP_TYPE_ID = 9
        LEFT JOIN VALL V369 ON V369.OBJ_ID = M.GROUP_ID AND V369.PARAM_ID = 369 AND V369.IS_DEL = 0 AND M.GROUP_TYPE_ID = 46
        LEFT JOIN LISTVALS LV ON LV.LISTVAL_ID = M.STAGE_ID
        WHERE M.DATE_DEL IS NULL AND M.GROUP_TYPE_ID IN (9, 46, 187, 289) AND M.DATE_IN <= :I$DATE AND (M.DATE_OUT > :I$DATE OR M.DATE_OUT IS NULL) -- , 289 зачем тут академический отпуск?
          AND (M.GROUP_TYPE_ID <> 46 OR V369.LISTVAL_ID IN (1246, 3318))
          AND (M.LEVEL_ID = :I$LEVEL_ID OR M.LEVEL_ID = :V$LEVEL_ID2 OR M.LEVEL_ID = :V$LEVEL_ID3 OR M.GROUP_TYPE_ID = 46) -- чтобы не потерять кружки и ГПД
          AND M.OU_ID = :I$SCHOOL_ID
        ORDER BY 1, 6, 4
        INTO :V$TYPE_ID, :V$OBJ_ID, :V$STAGE_ID, :V$NAME, :V$OVZ, :V$COST, :V$DIR
      DO
      BEGIN
        IF(V$CLASS_NUM = 1) THEN VAL = ','; ELSE VAL = '';
        VAL = VAL || '{"id":"' || V$OBJ_ID || '","type_id":' || V$TYPE_ID || ',"stage":"' || COALESCE(V$STAGE_ID, '') || '","name":"' ||
          (SELECT VAL FROM ESCAPE_STR(:V$NAME)) || '","ovz":"' || COALESCE(V$OVZ, '') || '","sindex":' || COALESCE(V$COST, 0) || ',"dir":"' || COALESCE(V$DIR, '') || '"}';
        SUSPEND;                                                                                                         
        V$CLASS_NUM = 1;
      END

      VAL = '],"students":[';
      SUSPEND;
      V$CLASS_NUM = 0;
      FOR
        SELECT M.PERSON_ID, MIN(M.STAGE_ID), IIF(V207.LISTVAL_ID IS NULL OR V207.LISTVAL_ID = 13289, 0, 1), IIF(V2169.LISTVAL_ID IS NULL OR V2169.LISTVAL_ID = 3, 0, 1),
          LIST(CAST(M.GROUP_ID AS VARCHAR(40)), ',')
        FROM PERSON_MOVEMENTS M
        LEFT JOIN VALL V207 ON V207.OBJ_ID = M.PERSON_ID AND V207.PARAM_ID = 207 AND V207.IS_DEL = 0
        LEFT JOIN VALL V2169 ON V2169.OBJ_ID = M.PERSON_ID AND V2169.PARAM_ID = 2169 AND V2169.IS_DEL = 0
        LEFT JOIN VALL V369 ON V369.OBJ_ID = M.GROUP_ID AND V369.PARAM_ID = 369 AND V369.IS_DEL = 0 AND M.GROUP_TYPE_ID = 46
        WHERE M.DATE_DEL IS NULL AND M.GROUP_TYPE_ID IN (9, 46, 187, 289) AND M.DATE_IN <= :I$DATE AND (M.DATE_OUT > :I$DATE OR M.DATE_OUT IS NULL)
          AND (M.GROUP_TYPE_ID <> 46 OR V369.LISTVAL_ID IN (1246, 3318))
          AND (M.LEVEL_ID = :I$LEVEL_ID OR M.LEVEL_ID = :V$LEVEL_ID2 OR M.LEVEL_ID = :V$LEVEL_ID3)
          AND M.OU_ID = :I$SCHOOL_ID
        GROUP BY 1, 3, 4
        INTO :V$OBJ_ID, :V$STAGE_ID, :V$OVZ, :V$ATHOME, :V$NAME
      DO
      BEGIN
        -- id ученика не выдаем
        IF(V$CLASS_NUM = 1) THEN VAL = ','; ELSE VAL = '';
        VAL = VAL || '{"ovz":' || V$OVZ || ',"stage":"' || COALESCE(V$STAGE_ID, '0') || '","home":' || V$ATHOME || ',"groups":"' || V$NAME || '"}';
        SUSPEND;
        V$CLASS_NUM = 1;
      END

      VAL = '],"stages":[';
      SUSPEND;
      V$CLASS_NUM = 0;
      FOR
        SELECT L.LISTVAL_ID, L.VAL
        FROM LISTVALS_LIST(25) L
        WHERE L.IS_DEL = 0
        INTO :V$STAGE_ID, :V$NAME
      DO
      BEGIN
        IF(V$CLASS_NUM = 1) THEN VAL = ','; ELSE VAL = '';
        VAL = VAL || '{"stage":"' || V$STAGE_ID || '","name":"' || (SELECT VAL FROM ESCAPE_STR(:V$NAME)) || '"}';
        SUSPEND;
        V$CLASS_NUM = 1;
      END

      VAL = ']}';
      SUSPEND;
    END
    ELSE IF(V$TYPE_ID = 2 AND (I$FILTER IS NOT NULL OR I$MASTER_ID IS NOT NULL)) THEN
    BEGIN
      -- Детализация по ОУ
      -- I$MASTER_ID - номер столбца, I$FILTER - либо числовой код итоговой строки, либо s + id этапа

      IF(SUBSTRING(I$FILTER FROM 1 FOR 1) = 's') THEN
      BEGIN
        -- Конкретная параллель
        V$STAGE_ID = SUBSTRING(I$FILTER FROM 2);
        V$TYPE_ID = 9;
      END
      ELSE
      BEGIN
        -- Диапазон этапов, либо ГПД или ОДОД
        IF(I$FILTER = '-1') THEN
        BEGIN
          V$TYPE_ID = 9;
        END
        ELSE IF(I$FILTER = '46') THEN
        BEGIN
          V$TYPE_ID = 46;
          V$OBJ_ID = 1246;
        END
        ELSE IF(I$FILTER = '1046') THEN
        BEGIN
          V$TYPE_ID = 46;
          V$OBJ_ID = 3318;
        END
        ELSE IF(I$FILTER = '0') THEN
        BEGIN
          V$TYPE_ID = 9;
          V$STAGE_ID = 49;
          V$STAGE_ID2 = 50;
          V$STAGE_ID3 = 51;
          V$STAGE_ID4 = 52;
          V$STAGE_ID5 = 53;
          V$STAGE_ID6 = 54;
        END
        ELSE IF(I$FILTER = '1') THEN
        BEGIN
          V$TYPE_ID = 9;
          V$STAGE_ID = 30;
          V$STAGE_ID2 = 31;
          V$STAGE_ID3 = 32;
          V$STAGE_ID4 = 33;
          V$STAGE_ID5 = 3261;
        END
        ELSE IF(I$FILTER = '2') THEN
        BEGIN
          V$TYPE_ID = 9;
          V$STAGE_ID = 34;
          V$STAGE_ID2 = 35;
          V$STAGE_ID3 = 36;
          V$STAGE_ID4 = 3262;
        END
        ELSE IF(I$FILTER = '11') THEN
        BEGIN
          V$TYPE_ID = 9;
          V$STAGE_ID = 37;
          V$STAGE_ID2 = 38;
          V$STAGE_ID3 = 39;
          V$STAGE_ID4 = 40;
          V$STAGE_ID5 = 12942;
          V$STAGE_ID6 = 12950;
        END
        ELSE IF(I$FILTER = '12') THEN
        BEGIN
          V$TYPE_ID = 9;
          V$STAGE_ID = 41;
          V$STAGE_ID2 = 42;
          V$STAGE_ID3 = 43;
          V$STAGE_ID4 = 44;
          V$STAGE_ID5 = 45;
          V$STAGE_ID6 = 12951;
          V$STAGE_ID7 = 12960;
        END
        ELSE IF(I$FILTER = '13') THEN
        BEGIN
          V$TYPE_ID = 9;
          V$STAGE_ID = 46;
          V$STAGE_ID2 = 47;
          V$STAGE_ID3 = 48;
          V$STAGE_ID4 = 12961;
        END
      END

      VAL = '{"items":[';
      SUSPEND;
      V$CLASS_NUM = 0;

      -- Классы или группы
      IF(
        (I$MASTER_ID IN (1, 3, 5, 7, 9) AND I$LEVEL_ID = 21)
        OR (I$MASTER_ID IN (1, 3, 5, 6) AND I$LEVEL_ID = 22)
      ) THEN
      BEGIN
        FOR
          SELECT DISTINCT M.NAME_IN, LV.COST
          FROM PERSON_MOVEMENTS M
          LEFT JOIN VALL V592 ON V592.OBJ_ID = M.GROUP_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND M.GROUP_TYPE_ID = 9
          LEFT JOIN VALL V1549 ON V1549.OBJ_ID = M.GROUP_ID AND V1549.PARAM_ID = 1549 AND V1549.IS_DEL = 0 AND M.GROUP_TYPE_ID = 9
          LEFT JOIN VALL V369 ON V369.OBJ_ID = M.GROUP_ID AND V369.PARAM_ID = 369 AND V369.IS_DEL = 0 AND M.GROUP_TYPE_ID = 46
          LEFT JOIN LISTVALS LV ON LV.LISTVAL_ID = M.STAGE_ID
          WHERE M.DATE_DEL IS NULL AND M.GROUP_TYPE_ID = :V$TYPE_ID AND M.DATE_IN <= :I$DATE AND (M.DATE_OUT > :I$DATE OR M.DATE_OUT IS NULL)
            AND M.OU_ID = :I$SCHOOL_ID
            AND (M.GROUP_TYPE_ID <> 46 OR V369.LISTVAL_ID = :V$OBJ_ID)
            AND (M.LEVEL_ID = :I$LEVEL_ID OR M.LEVEL_ID = :V$LEVEL_ID2 OR M.LEVEL_ID = :V$LEVEL_ID3)
            AND (:V$STAGE_ID IS NULL OR M.STAGE_ID = :V$STAGE_ID OR M.STAGE_ID = :V$STAGE_ID2 OR M.STAGE_ID = :V$STAGE_ID3
              OR M.STAGE_ID = :V$STAGE_ID4 OR M.STAGE_ID = :V$STAGE_ID5 OR M.STAGE_ID = :V$STAGE_ID6 OR M.STAGE_ID = :V$STAGE_ID7)
            AND (
              (:I$MASTER_ID = 1)
              OR (:I$LEVEL_ID = 21 AND :I$MASTER_ID = 3 AND V1549.LISTVAL_ID = 3265)
              OR (:I$LEVEL_ID = 21 AND :I$MASTER_ID = 5 AND V1549.LISTVAL_ID = 3266)
              OR (:I$LEVEL_ID = 21 AND :I$MASTER_ID = 7 AND V1549.LISTVAL_ID = 3267)
              OR (:I$LEVEL_ID = 21 AND :I$MASTER_ID = 9 AND V1549.LISTVAL_ID = 3268)
              OR (:I$LEVEL_ID = 22 AND :I$MASTER_ID = 3 AND V592.LISTVAL_ID = 197)
              OR (:I$LEVEL_ID = 22 AND :I$MASTER_ID = 5 AND V592.LISTVAL_ID = 13274)
              OR (:I$LEVEL_ID = 22 AND :I$MASTER_ID = 6 AND V592.LISTVAL_ID = 13275)
            )
          ORDER BY 2, 1
          INTO :V$NAME, :V$COST
        DO
        BEGIN
          IF(V$CLASS_NUM = 1) THEN VAL = ','; ELSE VAL = '';
          VAL = VAL || '{"value":"' || (SELECT VAL FROM ESCAPE_STR(:V$NAME)) || '"}';
          SUSPEND;
          V$CLASS_NUM = 1;
        END
      END
      -- Обучающиеся
      ELSE
      BEGIN
        -- Экстернат ?
        IF(I$MASTER_ID = 11) THEN V$TYPE_ID = 187;
        -- Академический отпуск ?
        ELSE IF(I$MASTER_ID = 4) THEN V$TYPE_ID = 289; -- 12 ?

        FOR
          SELECT DISTINCT C.C1, M.NAME_IN, LV.COST
          FROM PERSON_MOVEMENTS M
          LEFT JOIN VALL V592 ON V592.OBJ_ID = M.GROUP_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND M.GROUP_TYPE_ID = 9
          LEFT JOIN VALL V1549 ON V1549.OBJ_ID = M.GROUP_ID AND V1549.PARAM_ID = 1549 AND V1549.IS_DEL = 0 AND M.GROUP_TYPE_ID = 9
          LEFT JOIN VALL V369 ON V369.OBJ_ID = M.GROUP_ID AND V369.PARAM_ID = 369 AND V369.IS_DEL = 0 AND M.GROUP_TYPE_ID = 46
          LEFT JOIN VALL V207 ON V207.OBJ_ID = M.PERSON_ID AND V207.PARAM_ID = 207 AND V207.IS_DEL = 0
          LEFT JOIN VALL V2169 ON V2169.OBJ_ID = M.PERSON_ID AND V2169.PARAM_ID = 2169 AND V2169.IS_DEL = 0
          LEFT JOIN LISTVALS LV ON LV.LISTVAL_ID = M.STAGE_ID
          LEFT JOIN BUILD_REP_FIO(M.PERSON_ID, 55, 56, 57, 1) C ON 1 = 1
          WHERE M.DATE_DEL IS NULL AND M.GROUP_TYPE_ID = :V$TYPE_ID AND M.DATE_IN <= :I$DATE AND (M.DATE_OUT > :I$DATE OR M.DATE_OUT IS NULL)
            AND M.OU_ID = :I$SCHOOL_ID
            AND (M.GROUP_TYPE_ID <> 46 OR V369.LISTVAL_ID = :V$OBJ_ID)
            AND (M.LEVEL_ID = :I$LEVEL_ID OR M.LEVEL_ID = :V$LEVEL_ID2 OR M.LEVEL_ID = :V$LEVEL_ID3)
            AND (:V$STAGE_ID IS NULL OR M.STAGE_ID = :V$STAGE_ID OR M.STAGE_ID = :V$STAGE_ID2 OR M.STAGE_ID = :V$STAGE_ID3
              OR M.STAGE_ID = :V$STAGE_ID4 OR M.STAGE_ID = :V$STAGE_ID5 OR M.STAGE_ID = :V$STAGE_ID6 OR M.STAGE_ID = :V$STAGE_ID7)
            AND (
              (:I$MASTER_ID = 2)
              OR (:I$LEVEL_ID = 21 AND :I$MASTER_ID = 4 AND V1549.LISTVAL_ID = 3265)
              OR (:I$LEVEL_ID = 21 AND :I$MASTER_ID = 6 AND V1549.LISTVAL_ID = 3266)
              OR (:I$LEVEL_ID = 21 AND :I$MASTER_ID = 0 AND V1549.LISTVAL_ID = 3267)
              OR (:I$LEVEL_ID = 21 AND :I$MASTER_ID = 10 AND V1549.LISTVAL_ID = 3268)
              OR (:I$LEVEL_ID = 22 AND :I$MASTER_ID = 4 AND V592.LISTVAL_ID = 197)
              OR (:I$LEVEL_ID = 22 AND :I$MASTER_ID = 7 AND V592.LISTVAL_ID = 13275)
              OR (:I$LEVEL_ID = 21 AND :I$MASTER_ID = 10 AND V2169.LISTVAL_ID = 2) -- надомники
              OR (:I$LEVEL_ID = 22 AND :I$MASTER_ID = 11 AND M.GROUP_TYPE_ID = 187) -- экстернат
            )
          ORDER BY 3, 2, 1
          INTO :V$NAME, :V$MASTER_VAL, :V$COST
        DO
        BEGIN
          IF(V$CLASS_NUM = 1) THEN VAL = ','; ELSE VAL = '';
          VAL = VAL || '{"value":"' || (SELECT VAL FROM ESCAPE_STR(:V$NAME)) || '","group":"' || (SELECT VAL FROM ESCAPE_STR(:V$MASTER_VAL)) || '"}';
          SUSPEND;
          V$CLASS_NUM = 1;
        END
      END

      VAL = ']}';
      SUSPEND;

    END
    ELSE
      EXCEPTION DATA_ERROR 'Недопустимый параметр выборки';

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE REPORT_DO (
    I$OBJ_ID BIGINT)
RETURNS (
    VAL VARCHAR(4000))
AS
declare variable V$TYPE_ID bigint;
declare variable V$STAGE bigint;
declare variable V$PREV bigint;
declare variable S varchar(1000);
declare variable V$N1 bigint;
declare variable V$N2 bigint;
declare variable N1 bigint;
declare variable N2 bigint;
declare variable R1 integer;
declare variable R2 integer;
begin

  SELECT TYPE_ID FROM OBJECTS WHERE OBJ_ID = :I$OBJ_ID INTO :V$TYPE_ID;

  IF(V$TYPE_ID = 162) THEN
  BEGIN
    V$TYPE_ID = 2;
    I$OBJ_ID = (SELECT FIRST 1 PARENT_ID FROM LINKS L2 WHERE L2.OBJ_ID = :I$OBJ_ID AND L2.PARENT_TYPE_ID = 2 AND L2.DATE_DEL IS NULL);
  END

  VAL = '<!DOCTYPE html>';
  VAL = VAL || '<html lang="ru">';
  VAL = VAL || '<head>';
  VAL = VAL || '<meta charset="utf-8" />';
  VAL = VAL || '<style>';
  VAL = VAL || 'html { font-family: Tahoma, Verdana, Arial;';
  VAL = VAL || 'font-size: 10pt; ';
  VAL = VAL || '} ';
  VAL = VAL || '.title1 { font-size: 150%;';
  VAL = VAL || 'padding: 8px;';
  VAL = VAL || 'margin-bottom: 4px;';
  VAL = VAL || 'font-weight: bold;';
  VAL = VAL || 'background-color: #D4E157;';
  VAL = VAL || '} ';
  VAL = VAL || '.title2 { ';
  VAL = VAL || 'padding: 4px;';
  VAL = VAL || 'font-weight: bold;';
  VAL = VAL || '} ';
  VAL = VAL || 'td { padding: 0.5em 1em;';
  VAL = VAL || 'border: 1px solid #000; ';
  VAL = VAL || '} ';
  VAL = VAL || '</style>';

  VAL = VAL || '</head>';
  VAL = VAL || '<body>';
  SUSPEND;

  -- Заголовок отчета
  VAL = '<div class="title1">Занятость детей в дополнительном образовании</div>';
  VAL = VAL || '<div class="title2">' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$OBJ_ID)) || '</div>';

  VAL = VAL || '<table class="table" cellspacing="0" cellpadding="0" style="width: 100%">';

  VAL = VAL || '<tr class="thd">';
  VAL = VAL || '<td style="width: 30%" class="sortable text">';
  IF(V$TYPE_ID = 2) THEN VAL = VAL || 'Учебный коллектив';
  IF(V$TYPE_ID = 111) THEN VAL = VAL || 'ОООД';
  IF(V$TYPE_ID = 112) THEN VAL = VAL || 'Район';
  VAL = VAL || '</td>';
  VAL = VAL || '<td>Количество детей от 5 до 18 лет</td>';
  VAL = VAL || '<td>Количество детей от 5 до 18 лет, которые занимаются дополнительным образованием</td>';
  VAL = VAL || '<td>% охвата</td>';
  VAL = VAL || '</tr>';
  SUSPEND;

  N1 = 0;
  N2 = 0;
  R1 = 0;
  R2 = 0;

  IF(V$TYPE_ID = 2) THEN
  BEGIN
    V$PREV = NULL;
    FOR
      SELECT V3104.LISTVAL_ID, C.CAPTION, V3101.VAL, V3102.VAL
      FROM LINKS L162
      JOIN LINKS L421 ON L421.PARENT_ID = L162.OBJ_ID AND L421.OBJ_TYPE_ID = 421 AND L421.DATE_DEL IS NULL
      JOIN VALL V3104 ON V3104.OBJ_ID = L421.OBJ_ID AND V3104.PARAM_ID = 3104 AND V3104.IS_DEL = 0
      JOIN LISTVALS LV ON LV.LISTVAL_ID = V3104.LISTVAL_ID
      JOIN VALR V3100 ON V3100.OBJ_ID = L421.OBJ_ID AND V3100.PARAM_ID = 3100 AND V3100.IS_DEL = 0
      LEFT JOIN OBJECT_CAPTION_GET(V3100.VAL) C ON 1 = 1
      JOIN VALI V3101 ON V3101.OBJ_ID = L421.OBJ_ID AND V3101.PARAM_ID = 3101 AND V3101.IS_DEL = 0
      JOIN VALI V3102 ON V3102.OBJ_ID = L421.OBJ_ID AND V3102.PARAM_ID = 3102 AND V3102.IS_DEL = 0
      WHERE L162.PARENT_ID = :I$OBJ_ID AND L162.OBJ_TYPE_ID = 162 AND L162.DATE_DEL IS NULL
      ORDER BY LV.COST, 2
      INTO :V$STAGE, :S, :V$N1, :V$N2
    DO
    BEGIN
      IF(V$PREV <> V$STAGE) THEN
      BEGIN
        VAL = '<tr style="font-weight: bold">';
        VAL = VAL || '<td>Итого по этапу</td>';
        VAL = VAL || '<td>' || N1 || '</td>';
        VAL = VAL || '<td>' || N2 || '</td>';
        IF(N1 <= 0 OR N2 <= 0) THEN VAL = VAL || '<td></td>';
        ELSE VAL = VAL || '<td>' || CAST(100.0 * N2 / N1 AS NUMERIC(18, 2)) || '</td>';
        VAL = VAL || '</tr>';
        SUSPEND;
        N1 = 0;
        N2 = 0;
      END
      V$PREV = V$STAGE;

      VAL = '<tr>';
      VAL = VAL || '<td>' || (SELECT VAL FROM ESCAPE_STR(:S)) || '</td>';
      VAL = VAL || '<td>' || V$N1 || '</td>';
      VAL = VAL || '<td>' || V$N2 || '</td>';
      IF(V$N1 <= 0 OR V$N2 <= 0) THEN VAL = VAL || '<td></td>';
      ELSE VAL = VAL || '<td>' || CAST(100.0 * V$N2 / V$N1 AS NUMERIC(18, 2)) || '</td>';
      VAL = VAL || '</tr>';
      N1 = N1 + V$N1;
      N2 = N2 + V$N2;
      R1 = R1 + V$N1;
      R2 = R2 + V$N2;
      SUSPEND;
    END

    VAL = '<tr style="font-weight: bold">';
    VAL = VAL || '<td>Итого по этапу</td>';
    VAL = VAL || '<td>' || N1 || '</td>';
    VAL = VAL || '<td>' || N2 || '</td>';
    IF(N1 <= 0 OR N2 <= 0) THEN VAL = VAL || '<td></td>';
    ELSE VAL = VAL || '<td>' || CAST(100.0 * N2 / N1 AS NUMERIC(18, 2)) || '</td>';
    VAL = VAL || '</tr>';
    SUSPEND;

  END
  ELSE IF(V$TYPE_ID = 111) THEN
  BEGIN

    FOR
      SELECT C.CAPTION, SUM(V3101.VAL), SUM(V3102.VAL)
      FROM LINKS L2
      LEFT JOIN VALS V6 ON V6.OBJ_ID = L2.OBJ_ID AND V6.PARAM_ID = 6 AND V6.IS_DEL = 0
      LEFT JOIN VALL V8 ON V8.OBJ_ID = L2.OBJ_ID AND V8.PARAM_ID = 8 AND V8.IS_DEL = 0
      LEFT JOIN LINKS L162 ON L162.PARENT_ID = L2.OBJ_ID AND L162.OBJ_TYPE_ID = 162 AND L162.DATE_DEL IS NULL
      LEFT JOIN LINKS L421 ON L421.PARENT_ID = L162.OBJ_ID AND L421.OBJ_TYPE_ID = 421 AND L421.DATE_DEL IS NULL
      LEFT JOIN VALI V3101 ON V3101.OBJ_ID = L421.OBJ_ID AND V3101.PARAM_ID = 3101 AND V3101.IS_DEL = 0
      LEFT JOIN VALI V3102 ON V3102.OBJ_ID = L421.OBJ_ID AND V3102.PARAM_ID = 3102 AND V3102.IS_DEL = 0
      LEFT JOIN OBJECT_CAPTION_GET(L2.OBJ_ID) C ON 1 = 1
      WHERE L2.PARENT_ID = :I$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
        AND (V6.VAL IS NULL OR V6.VAL = 'Комитет по образованию Санкт-Петербурга') AND (V8.LISTVAL_ID IS NULL OR V8.LISTVAL_ID <> 5404)
      GROUP BY 1
      ORDER BY 1
      INTO :S, :V$N1, :V$N2
    DO
    BEGIN
      VAL = '<tr>';
      VAL = VAL || '<td>' || (SELECT VAL FROM ESCAPE_STR(:S)) || '</td>';
      VAL = VAL || '<td>' || V$N1 || '</td>';
      VAL = VAL || '<td>' || V$N2 || '</td>';
      IF(V$N1 <= 0 OR V$N2 <= 0) THEN VAL = VAL || '<td></td>';
      ELSE VAL = VAL || '<td>' || CAST(100.0 * V$N2 / V$N1 AS NUMERIC(18, 2)) || '</td>';
      VAL = VAL || '</tr>';
      R1 = R1 + V$N1;
      R2 = R2 + V$N2;
      SUSPEND;
    END

  END
  ELSE IF(V$TYPE_ID = 112) THEN
  BEGIN

    FOR
      SELECT C.CAPTION, SUM(V3101.VAL), SUM(V3102.VAL)
      FROM LINKS L111
      LEFT JOIN LINKS L2 ON L2.PARENT_ID = L111.OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      LEFT JOIN VALS V6 ON V6.OBJ_ID = L2.OBJ_ID AND V6.PARAM_ID = 6 AND V6.IS_DEL = 0
      LEFT JOIN VALL V8 ON V8.OBJ_ID = L2.OBJ_ID AND V8.PARAM_ID = 8 AND V8.IS_DEL = 0
      LEFT JOIN LINKS L162 ON L162.PARENT_ID = L2.OBJ_ID AND L162.OBJ_TYPE_ID = 162 AND L162.DATE_DEL IS NULL
      LEFT JOIN LINKS L421 ON L421.PARENT_ID = L162.OBJ_ID AND L421.OBJ_TYPE_ID = 421 AND L421.DATE_DEL IS NULL
      LEFT JOIN VALI V3101 ON V3101.OBJ_ID = L421.OBJ_ID AND V3101.PARAM_ID = 3101 AND V3101.IS_DEL = 0
      LEFT JOIN VALI V3102 ON V3102.OBJ_ID = L421.OBJ_ID AND V3102.PARAM_ID = 3102 AND V3102.IS_DEL = 0
      LEFT JOIN OBJECT_CAPTION_GET(L111.OBJ_ID) C ON 1 = 1
      WHERE L111.PARENT_ID = :I$OBJ_ID AND L111.OBJ_TYPE_ID = 111 AND L111.DATE_DEL IS NULL
        AND (V6.VAL IS NULL OR V6.VAL = 'Комитет по образованию Санкт-Петербурга') AND (V8.LISTVAL_ID IS NULL OR V8.LISTVAL_ID <> 5404)
      GROUP BY 1
      ORDER BY 1
      INTO :S, :V$N1, :V$N2
    DO
    BEGIN
      VAL = '<tr>';
      VAL = VAL || '<td>' || (SELECT VAL FROM ESCAPE_STR(:S)) || '</td>';
      VAL = VAL || '<td>' || V$N1 || '</td>';
      VAL = VAL || '<td>' || V$N2 || '</td>';
      IF(V$N1 <= 0 OR V$N2 <= 0) THEN VAL = VAL || '<td></td>';
      ELSE VAL = VAL || '<td>' || CAST(100.0 * V$N2 / V$N1 AS NUMERIC(18, 2)) || '</td>';
      VAL = VAL || '</tr>';
      R1 = R1 + V$N1;
      R2 = R2 + V$N2;
      SUSPEND;
    END

  END

  VAL = '<tr style="font-weight: bold">';
  VAL = VAL || '<td>Всего</td>';
  VAL = VAL || '<td>' || R1 || '</td>';
  VAL = VAL || '<td>' || R2 || '</td>';
  IF(R1 <= 0 OR R2 <= 0) THEN VAL = VAL || '<td></td>';
  ELSE VAL = VAL || '<td>' || CAST(100.0 * R2 / R1 AS NUMERIC(18, 2)) || '</td>';
  VAL = VAL || '</tr>';
  SUSPEND;

  VAL = '</table></body></html>';
  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE REPORT_EMPLOYEES_LIST (
    OBJ_ID BIGINT)
RETURNS (
    ROW_NUM INTEGER,
    FIO VARCHAR(400),
    JOB_GROUP VARCHAR(200),
    JOB_NAME VARCHAR(400),
    SUBJECT_NAME VARCHAR(2000),
    EDU_NAME VARCHAR(400),
    SC_NAME VARCHAR(100),
    SC_TITLE VARCHAR(100),
    SC_STR VARCHAR(100),
    QUAL_CAT VARCHAR(100),
    ATT_DATE DATE,
    WORK_AGE VARCHAR(30),
    EDU_AGE VARCHAR(30),
    OO_AGE VARCHAR(30),
    JOB_AGE VARCHAR(30),
    EDU_KIND VARCHAR(100),
    EDU_ORG VARCHAR(600),
    SPECIALITY VARCHAR(400),
    EDU_QUAL VARCHAR(400),
    EDU_PROFILE VARCHAR(100),
    CC_DC VARCHAR(200),
    CC_OO VARCHAR(600),
    CC_DATE DATE,
    CC_SPEC VARCHAR(300),
    CC_QUAL VARCHAR(200),
    KR_KIND VARCHAR(200),
    KR_OO VARCHAR(600),
    KR_COURSE VARCHAR(600),
    KR_CKIND VARCHAR(40),
    KR_DURATION INTEGER,
    KR_DKIND VARCHAR(40),
    KR_DATE DATE)
AS
declare variable PERSON_ID bigint;
declare variable ASSN_ID bigint;
declare variable JOB_ID bigint;
declare variable EDU_ID bigint;
declare variable S varchar(2000);
begin
  ROW_NUM = 1;

  IF(OBJ_ID IS NULL) THEN
  BEGIN
      SELECT FIRST 1 L2.OBJ_ID
      FROM LINKS L2
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      INTO :OBJ_ID;
  END

  FOR
      SELECT L14.OBJ_ID, C.CAPTION, R.VAL
      FROM LINKS L14
      LEFT JOIN OBJECT_CAPTION_GET(L14.OBJ_ID) C ON 1 = 1
      LEFT JOIN VALL V269 ON V269.OBJ_ID = L14.OBJ_ID AND V269.PARAM_ID = 269 AND V269.IS_DEL = 0
      LEFT JOIN LISTVALS LV ON LV.LISTVAL_ID = V269.LISTVAL_ID
      LEFT JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
      WHERE L14.PARENT_ID = :OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
      ORDER BY 2
      INTO :PERSON_ID, :FIO, :JOB_GROUP
  DO
  BEGIN

      JOB_NAME = NULL;
      SUBJECT_NAME = '';
      EDU_NAME = NULL;
      SC_NAME = NULL;
      SC_TITLE = NULL;
      SC_STR = NULL;
      QUAL_CAT = NULL;
      ATT_DATE = NULL;
      WORK_AGE = NULL;
      EDU_AGE = NULL;
      OO_AGE = NULL;
      JOB_AGE = NULL;
      EDU_KIND = NULL;
      EDU_ORG = NULL;
      SPECIALITY = NULL;
      EDU_QUAL = NULL;
      EDU_PROFILE = NULL;
      CC_DC = NULL;
      CC_OO = NULL;
      CC_DATE = NULL;
      CC_SPEC = NULL;
      CC_QUAL = NULL;
      KR_KIND = NULL;
      KR_OO = NULL;
      KR_COURSE = NULL;
      KR_CKIND = NULL;
      KR_DURATION = NULL;
      KR_DKIND = NULL;
      KR_DATE = NULL;

      -- Выбираем основную должность
      JOB_ID = NULL;
      ASSN_ID = NULL;

      SELECT FIRST 1 L15.OBJ_ID, LP13.PARENT_ID
      FROM LINKS L15
      JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
      JOIN VALL V72 ON V72.OBJ_ID = L15.OBJ_ID AND V72.PARAM_ID = 72 AND V72.IS_DEL = 0 AND V72.LISTVAL_ID = 934
      LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
      WHERE L15.PARENT_ID = :PERSON_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL AND (V74.VAL IS NULL OR V74.VAL > CURRENT_DATE)
      INTO :ASSN_ID, :JOB_ID;

      IF(JOB_ID IS NOT NULL) THEN
      BEGIN

          -- Должность по штату
          SELECT V589.VAL
          FROM VALS V589
          WHERE V589.OBJ_ID = :JOB_ID AND V589.PARAM_ID = 589 AND V589.IS_DEL = 0
          INTO :JOB_NAME;

          -- Предподаваемые предметы
          FOR
              SELECT DISTINCT C.CAPTION
              FROM (
                SELECT DISTINCT J.SUBJECT_ID, J.JOURNAL_TYPE
                FROM CJ2_JOURNAL J
                WHERE J.DATE_DEL IS NULL AND J.TEACHER_ID = :PERSON_ID AND J.SUBJECT_ID IS NOT NULL AND J.JOURNAL_TYPE = 0
                ORDER BY 2 -- сначала общеобр, потом ВД, и остальное
              ) JS
              LEFT JOIN OBJECT_CAPTION_GET(JS.SUBJECT_ID) C ON 1 = 1
              ORDER BY 1
              INTO :S
          DO
          BEGIN
              IF((CHAR_LENGTH(SUBJECT_NAME) + CHAR_LENGTH(S)) < 1980) THEN
              BEGIN
                  IF(CHAR_LENGTH(SUBJECT_NAME) > 0) THEN SUBJECT_NAME = SUBJECT_NAME || ', ';
                  SUBJECT_NAME = SUBJECT_NAME || S;
              END
          END

          -- Образование
          SELECT R.VAL
          FROM VALL V278
          JOIN LISTVALS LV ON LV.LISTVAL_ID = V278.LISTVAL_ID
          JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
          WHERE V278.OBJ_ID = :PERSON_ID AND V278.PARAM_ID = 278 AND V278.IS_DEL = 0
          INTO :EDU_NAME;

          -- Ученая степень
          SELECT R.VAL
          FROM VALL V279
          JOIN LISTVALS LV ON LV.LISTVAL_ID = V279.LISTVAL_ID
          JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
          WHERE V279.OBJ_ID = :PERSON_ID AND V279.PARAM_ID = 279 AND V279.IS_DEL = 0
          INTO :SC_NAME;

          -- Звание
          SELECT R.VAL
          FROM VALL V280
          JOIN LISTVALS LV ON LV.LISTVAL_ID = V280.LISTVAL_ID
          JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
          WHERE V280.OBJ_ID = :PERSON_ID AND V280.PARAM_ID = 280 AND V280.IS_DEL = 0
          INTO :SC_TITLE;

          -- Ученое звание
          SELECT R.VAL
          FROM VALL V1373
          JOIN LISTVALS LV ON LV.LISTVAL_ID = V1373.LISTVAL_ID
          JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
          WHERE V1373.OBJ_ID = :PERSON_ID AND V1373.PARAM_ID = 1373 AND V1373.IS_DEL = 0
          INTO :SC_STR;

          -- Квалификационная категория
          SELECT R.VAL
          FROM VALL V1790
          JOIN LISTVALS LV ON LV.LISTVAL_ID = V1790.LISTVAL_ID
          JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
          WHERE V1790.OBJ_ID = :ASSN_ID AND V1790.PARAM_ID = 1790 AND V1790.IS_DEL = 0
          INTO :QUAL_CAT;

          -- Дата последней аттестации
          SELECT MAX(V544.VAL)
          FROM LINKS L34
          JOIN VALD V544 ON V544.OBJ_ID = L34.OBJ_ID AND V544.PARAM_ID = 544 AND V544.IS_DEL = 0
          JOIN VALL V545 ON V545.OBJ_ID = L34.OBJ_ID AND V545.PARAM_ID = 545 AND V545.IS_DEL = 0 AND V545.LISTVAL_ID IN (1208, 1209, 1210)
          WHERE L34.PARENT_ID = :PERSON_ID AND L34.OBJ_TYPE_ID = 34 AND L34.DATE_DEL IS NULL
          INTO :ATT_DATE;

          -- Стаж
          SELECT T.VAL
          FROM VAL_GET(:PERSON_ID, 462) VG
          LEFT JOIN WORKDAYS_TO_TEXT(VG.V) T ON 1 = 1
          INTO :WORK_AGE;

          SELECT T.VAL
          FROM VAL_GET(:PERSON_ID, 463) VG
          LEFT JOIN WORKDAYS_TO_TEXT(VG.V) T ON 1 = 1
          INTO :EDU_AGE;

          SELECT T.VAL
          FROM VAL_GET(:PERSON_ID, 464) VG
          LEFT JOIN WORKDAYS_TO_TEXT(VG.V) T ON 1 = 1
          INTO :OO_AGE;

          SELECT T.VAL
          FROM VAL_GET(:PERSON_ID, 609) VG
          LEFT JOIN WORKDAYS_TO_TEXT(VG.V) T ON 1 = 1
          INTO :JOB_AGE;

          -- Образование
          EDU_ID = NULL;

          SELECT FIRST 1 L33.OBJ_ID, R.VAL, SUBSTRING(V285.VAL FROM 1 FOR 600)
          FROM LINKS L33
          JOIN VALL V284 ON V284.OBJ_ID = L33.OBJ_ID AND V284.PARAM_ID = 284 AND V284.IS_DEL = 0
          JOIN LISTVALS LV ON LV.LISTVAL_ID = V284.LISTVAL_ID
          JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
          JOIN VALD V290 ON V290.OBJ_ID = L33.OBJ_ID AND V290.PARAM_ID = 290 AND V290.IS_DEL = 0
          JOIN VALS V285 ON V285.OBJ_ID = L33.OBJ_ID AND V285.PARAM_ID = 285 AND V285.IS_DEL = 0
          WHERE L33.PARENT_ID = :PERSON_ID AND L33.OBJ_TYPE_ID = 33 AND L33.DATE_DEL IS NULL
          ORDER BY LV.COST, V290.VAL DESC
          INTO :EDU_ID, :EDU_KIND, :EDU_ORG;

          SELECT SUBSTRING(V291.VAL FROM 1 FOR 400)
          FROM VALS V291
          WHERE V291.OBJ_ID = :EDU_ID AND V291.PARAM_ID = 291 AND V291.IS_DEL = 0
          INTO :SPECIALITY;

          SELECT SUBSTRING(V292.VAL FROM 1 FOR 400)
          FROM VALS V292
          WHERE V292.OBJ_ID = :EDU_ID AND V292.PARAM_ID = 292 AND V292.IS_DEL = 0
          INTO :EDU_QUAL;

          SELECT SUBSTRING(R293.VAL FROM 1 FOR 400)
          FROM VALL V293
          JOIN LISTVALS LV293 ON LV293.LISTVAL_ID = V293.LISTVAL_ID
          JOIN RES R293 ON R293.RES_ID = LV293.RES_ID AND R293.LANG_CODE = 'RU'
          WHERE V293.OBJ_ID = :EDU_ID AND V293.PARAM_ID = 293 AND V293.IS_DEL = 0
          INTO :EDU_PROFILE;

          -- Переподготовка (последняя)
          EDU_ID = NULL;

          SELECT FIRST 1 L35.OBJ_ID, SUBSTRING(R.VAL FROM 1 FOR 200), V300.VAL, SUBSTRING(V296.VAL FROM 1 FOR 600)
          FROM LINKS L35
          JOIN VALL V297 ON V297.OBJ_ID = L35.OBJ_ID AND V297.PARAM_ID = 297 AND V297.IS_DEL = 0
          JOIN LISTVALS LV ON LV.LISTVAL_ID = V297.LISTVAL_ID
          JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
          JOIN VALD V300 ON V300.OBJ_ID = L35.OBJ_ID AND V300.PARAM_ID = 300 AND V300.IS_DEL = 0
          JOIN VALS V296 ON V296.OBJ_ID = L35.OBJ_ID AND V296.PARAM_ID = 296 AND V296.IS_DEL = 0
          WHERE L35.PARENT_ID = :PERSON_ID AND L35.OBJ_TYPE_ID = 35 AND L35.DATE_DEL IS NULL
          ORDER BY V300.VAL DESC
          INTO :EDU_ID, :CC_DC, :CC_DATE, :CC_OO;

          SELECT SUBSTRING(V301.VAL FROM 1 FOR 300)
          FROM VALS V301
          WHERE V301.OBJ_ID = :EDU_ID AND V301.PARAM_ID = 301 AND V301.IS_DEL = 0
          INTO :CC_SPEC;

          SELECT SUBSTRING(V302.VAL FROM 1 FOR 200)
          FROM VALS V302
          WHERE V302.OBJ_ID = :EDU_ID AND V302.PARAM_ID = 302 AND V302.IS_DEL = 0
          INTO :CC_QUAL;

          -- Курсы повышения квалификации (последние)
          EDU_ID = NULL;

          SELECT FIRST 1 L36.OBJ_ID, R.VAL, V310.VAL, V304.VAL
          FROM LINKS L36
          JOIN VALL V303 ON V303.OBJ_ID = L36.OBJ_ID AND V303.PARAM_ID = 303 AND V303.IS_DEL = 0
          JOIN LISTVALS LV ON LV.LISTVAL_ID = V303.LISTVAL_ID
          JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
          JOIN VALD V310 ON V310.OBJ_ID = L36.OBJ_ID AND V310.PARAM_ID = 310 AND V310.IS_DEL = 0
          JOIN VALS V304 ON V304.OBJ_ID = L36.OBJ_ID AND V304.PARAM_ID = 304 AND V304.IS_DEL = 0
          WHERE L36.PARENT_ID = :PERSON_ID AND L36.OBJ_TYPE_ID = 36 AND L36.DATE_DEL IS NULL
          ORDER BY V310.VAL DESC
          INTO :EDU_ID, :KR_KIND, :KR_DATE, :KR_OO;

          SELECT V305.VAL
          FROM VALS V305
          WHERE V305.OBJ_ID = :EDU_ID AND V305.PARAM_ID = 305 AND V305.IS_DEL = 0
          INTO :KR_COURSE;

          SELECT R1024.VAL
          FROM VALL V1024
          JOIN LISTVALS LV1024 ON LV1024.LISTVAL_ID = V1024.LISTVAL_ID
          JOIN RES R1024 ON R1024.RES_ID = LV1024.RES_ID AND R1024.LANG_CODE = 'RU'
          WHERE V1024.OBJ_ID = :EDU_ID AND V1024.PARAM_ID = 1024 AND V1024.IS_DEL = 0
          INTO :KR_CKIND;

          SELECT V306.VAL
          FROM VALI V306
          WHERE V306.OBJ_ID = :EDU_ID AND V306.PARAM_ID = 306 AND V306.IS_DEL = 0
          INTO :KR_DURATION;

          SELECT R307.VAL
          FROM VALL V307
          JOIN LISTVALS LV307 ON LV307.LISTVAL_ID = V307.LISTVAL_ID
          JOIN RES R307 ON R307.RES_ID = LV307.RES_ID AND R307.LANG_CODE = 'RU'
          WHERE V307.OBJ_ID = :EDU_ID AND V307.PARAM_ID = 307 AND V307.IS_DEL = 0
          INTO :KR_DKIND;

      END

      SUSPEND;
      ROW_NUM = ROW_NUM + 1;

  END

  WHEN ANY DO
  BEGIN
    EXCEPTION DATA_ERROR 'Ошибка на персоне ' || PERSON_ID;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE REPORT_EMP_FORM (
    I$OBJ_ID BIGINT,
    I$PLACE VARCHAR(1000),
    I$NUMBER VARCHAR(1000))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$STATUS VARCHAR(2);
DECLARE VARIABLE S VARCHAR(1000);
DECLARE VARIABLE S2 VARCHAR(1000);
DECLARE VARIABLE S3 VARCHAR(400);
DECLARE VARIABLE S4 VARCHAR(400);
DECLARE VARIABLE S5 VARCHAR(400);
DECLARE VARIABLE S6 VARCHAR(400);
DECLARE VARIABLE N INTEGER;
begin

  SELECT FIRST 1 L2.OBJ_ID
  FROM LINKS L2
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$OBJ_ID;

  V$STATUS = (SELECT STATUS FROM OU_LICENCE_TYPE);
  TAG_NAME = 'licence_type';
  VAL = V$STATUS;
  SUSPEND;

  TAG_NAME = 'form_place';
  VAL = I$PLACE;
  SUSPEND;

  TAG_NAME = 'form_number';
  VAL = I$NUMBER;
  SUSPEND;

  TAG_NAME = 'date';
  SELECT VAL FROM DATE2SCRIPT(CURRENT_DATE, 1) INTO :VAL;
  SUSPEND;

  TAG_NAME = 'ou_full_name';
  SELECT UPPER(V) FROM VAL_GET(:V$OBJ_ID, 5) INTO :VAL;
  SUSPEND;

  TAG_NAME = 'ou_address';
  SELECT UPPER(V) FROM VAL_GET(:V$OBJ_ID, 27) INTO :VAL;
  SUSPEND;

  TAG_NAME = 'ou_phone';
  SELECT V FROM VAL_GET(:V$OBJ_ID, 29) INTO :VAL;
  SUSPEND;

  TAG_NAME = 'ou_fax';
  S = '';
  SELECT V FROM VAL_GET(:V$OBJ_ID, 30) INTO :S;
  IF (VAL <> S) THEN
    VAL = '/' || S;
  ELSE
    VAL = '';
  SUSPEND;

  TAG_NAME = 'ou_email';
  SELECT V FROM VAL_GET(:V$OBJ_ID, 35) INTO :VAL;
  SUSPEND;

  TAG_NAME = 'ou_okpo';
  SELECT V FROM VAL_GET(:V$OBJ_ID, 16) INTO :VAL;
  SUSPEND;

  TAG_NAME = 'ou_ogrn';
  SELECT V FROM VAL_GET(:V$OBJ_ID, 9) INTO :VAL;
  SUSPEND;

  TAG_NAME = 'ou_inn';
  SELECT V FROM VAL_GET(:V$OBJ_ID, 33) INTO :VAL;
  SUSPEND;

  TAG_NAME = 'ou_kpp';
  SELECT V FROM VAL_GET(:V$OBJ_ID, 34) INTO :VAL;
  SUSPEND;

  TAG_NAME = 'ou_okogu';
  SELECT V FROM VAL_GET(:V$OBJ_ID, 19) INTO :VAL;
  SUSPEND;

  TAG_NAME = 'director_fio';
  SELECT SUBSTRING(TRIM(I) FROM 1 FOR 1) || '.' || SUBSTRING(TRIM(O) FROM 1 FOR 1) || '.'|| F, POST
  FROM R_SPB_POST_DIRECTOR(:V$OBJ_ID, 1)
  INTO :VAL, :S;
  SUSPEND;

  TAG_NAME = 'director_post';
  --IF(V$STATUS = 'O') THEN S = S || ' школы';
  VAL = S;
  SELECT COALESCE(V, '') FROM VAL_GET(:V$OBJ_ID, 2) INTO :S;
  VAL = VAL || ' ' || S;
  SUSPEND;

  TAG_NAME = 'name_dative';
  SELECT DC.F || ' ' || DC.I || ' ' || DC.O
  FROM RDB$DATABASE
  LEFT JOIN BUILD_REP_FIO(:I$OBJ_ID, 59, 60, 61) BF ON 1 = 1
  LEFT JOIN DATIVECASE(BF.F, BF.I, BF.O) DC ON 1 = 1
  WHERE 1 = 1
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'gen_title';
  SELECT CASE WHEN I = 183 THEN 'он' WHEN I = 182 THEN 'она' END FROM VAL_GET(:I$OBJ_ID, 239) INTO :VAL;
  SUSPEND;

  TAG_NAME = 'ou_name_gen';
  SELECT OFG.RESULT FROM VAL_GET(:V$OBJ_ID, 5) V
  LEFT JOIN OU_FULLNAME_GENITIVE(V.V) OFG ON 1 = 1
  INTO :VAL;
  SUSPEND;

  -- Все обращения к PARAGRAF_EMPLOYEE_JOB_GET убрали
  -- Основная должность
  VAL = NULL;
  S = NULL;
  SELECT FIRST 1 COALESCE(V3543.VAL, V66.VAL), DC.VAL, V1638.VAL, DOGD.VAL, V455.VAL, ORDD.VAL
  FROM LINKS L15
  JOIN VALL V72 ON V72.OBJ_ID = L15.OBJ_ID AND V72.PARAM_ID = 72 AND V72.IS_DEL = 0 AND V72.LISTVAL_ID = 934
  JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0
  LEFT JOIN DATE2SCRIPT(V73.VAL, 1) DC ON 1 = 1
  LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
  JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
  LEFT JOIN VALS V66 ON V66.OBJ_ID = LP13.PARENT_ID AND V66.PARAM_ID = 66 AND V66.IS_DEL = 0
  LEFT JOIN VALS V3543 ON V3543.OBJ_ID = L15.OBJ_ID AND V3543.PARAM_ID = 3543 AND V3543.IS_DEL = 0
  LEFT JOIN VALS V1638 ON V1638.OBJ_ID = L15.OBJ_ID AND V1638.PARAM_ID = 1638 AND V1638.IS_DEL = 0
  LEFT JOIN VALD V1639 ON V1639.OBJ_ID = L15.OBJ_ID AND V1639.PARAM_ID = 1639 AND V1639.IS_DEL = 0
  LEFT JOIN DATE2SCRIPT(V1639.VAL, 1) DOGD ON 1 = 1
  LEFT JOIN VALS V455 ON V455.OBJ_ID = L15.OBJ_ID AND V455.PARAM_ID = 455 AND V455.IS_DEL = 0
  LEFT JOIN VALD V454 ON V454.OBJ_ID = L15.OBJ_ID AND V454.PARAM_ID = 454 AND V454.IS_DEL = 0
  LEFT JOIN DATE2SCRIPT(V454.VAL, 1) ORDD ON 1 = 1
  WHERE L15.PARENT_ID = :I$OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL AND V74.VAL IS NULL
  INTO :VAL, :S, :S3, :S4, :S5, :S6;

  TAG_NAME = 'main_job';
  SUSPEND;
  TAG_NAME = 'main_job_date';
  VAL = S;
  SUSPEND;
  TAG_NAME = 'main_contract_num';
  VAL = S3;
  SUSPEND;
  TAG_NAME = 'main_contract_date';
  VAL = S4;
  SUSPEND;
  TAG_NAME = 'main_order_num';
  VAL = S5;
  SUSPEND;
  TAG_NAME = 'main_order_date';
  VAL = S6;
  SUSPEND;

  TAG_NAME = 'sec_job::json&colon;array';
  VAL = 1;
  SUSPEND;
  N = 0;

  FOR
    SELECT FIRST 1 COALESCE(V3543.VAL, V66.VAL), DC.VAL, V1638.VAL, DOGD.VAL, V455.VAL, ORDD.VAL
    FROM LINKS L15
    JOIN VALL V72 ON V72.OBJ_ID = L15.OBJ_ID AND V72.PARAM_ID = 72 AND V72.IS_DEL = 0 AND V72.LISTVAL_ID = 935
    JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0
    LEFT JOIN DATE2SCRIPT(V73.VAL, 1) DC ON 1 = 1
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
    JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
    LEFT JOIN VALS V66 ON V66.OBJ_ID = LP13.PARENT_ID AND V66.PARAM_ID = 66 AND V66.IS_DEL = 0
    LEFT JOIN VALS V3543 ON V3543.OBJ_ID = L15.OBJ_ID AND V3543.PARAM_ID = 3543 AND V3543.IS_DEL = 0
    LEFT JOIN VALS V1638 ON V1638.OBJ_ID = L15.OBJ_ID AND V1638.PARAM_ID = 1638 AND V1638.IS_DEL = 0
    LEFT JOIN VALD V1639 ON V1639.OBJ_ID = L15.OBJ_ID AND V1639.PARAM_ID = 1639 AND V1639.IS_DEL = 0
    LEFT JOIN DATE2SCRIPT(V1639.VAL, 1) DOGD ON 1 = 1
    LEFT JOIN VALS V455 ON V455.OBJ_ID = L15.OBJ_ID AND V455.PARAM_ID = 455 AND V455.IS_DEL = 0
    LEFT JOIN VALD V454 ON V454.OBJ_ID = L15.OBJ_ID AND V454.PARAM_ID = 454 AND V454.IS_DEL = 0
    LEFT JOIN DATE2SCRIPT(V454.VAL, 1) ORDD ON 1 = 1
    WHERE L15.PARENT_ID = :I$OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL AND V74.VAL IS NULL
    INTO :S, :S2, :S3, :S4, :S5, :S6
  DO
  BEGIN
    TAG_NAME = 'sec_job:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'sec_job:r:name';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'sec_job:r:date';
    VAL = S2;
    SUSPEND;
    TAG_NAME = 'sec_job:r:contract_num';
    VAL = S3;
    SUSPEND;
    TAG_NAME = 'sec_job:r:contract_date';
    VAL = S4;
    SUSPEND;
    TAG_NAME = 'sec_job:r:order_num';
    VAL = S5;
    SUSPEND;
    TAG_NAME = 'sec_job:r:order_date';
    VAL = S6;
    SUSPEND;
    N = N + 1;
  END

  -- Титул если есть дополнительные должности
  TAG_NAME = 'sec_title';
  IF(N = 0) THEN VAL = '.'; ELSE VAL = ', а также по дополнительным должностям:';
  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE REPORT_FIS_FRDO (
    I$REC_ID BIGINT = null,
    I$PUPIL_ID BIGINT = null,
    I$USER_ID BIGINT = 1,
    I$DATE1 DATE = null,
    I$DATE2 DATE = null,
    I$STAGE_ID BIGINT = null,
    I$VALID SMALLINT = null)
RETURNS (
    CERTIFICATE_NAME VARCHAR(50),
    CERTIFICATE_TYPE VARCHAR(100),
    CERTIFICATE_STATUS VARCHAR(30),
    CONFIRMATION_OF_LOSS VARCHAR(10),
    CONFIRMATION_OF_EXCHANGE VARCHAR(10),
    CONFIRMATION_OF_DROP VARCHAR(10),
    STAGE VARCHAR(100),
    FORM_SERIA VARCHAR(20),
    FORM_NUMBER VARCHAR(20),
    GIVE_DATE DATE,
    REGNO VARCHAR(20),
    IN_YEAR INTEGER,
    OUT_YEAR INTEGER,
    TRAINING_PERIOD VARCHAR(20),
    F VARCHAR(200),
    I VARCHAR(200),
    O VARCHAR(200),
    DOB DATE,
    SNILS VARCHAR(20),
    CITIZENSHIP VARCHAR(200),
    EDU_AVAIL VARCHAR(50),
    SEX VARCHAR(10),
    PAY_SRC VARCHAR(100),
    EDU_FORM VARCHAR(50),
    ORIG_CERTIFICATE_NAME VARCHAR(50),
    ORIG_FORM_SERIA VARCHAR(20),
    ORIG_FORM_NUMBER VARCHAR(20),
    ORIG_REGNO VARCHAR(20),
    ORIG_GIVE_DATE DATE,
    ORIG_F VARCHAR(200),
    ORIG_I VARCHAR(200),
    ORIG_O VARCHAR(200))
AS
--declare variable I$PUPIL_ID bigint;
declare variable REC_ID bigint;
declare variable V$OU_ID bigint;
declare variable V$PUPIL_ID bigint;
declare variable V$CERTIFICATE_STATUS_ID bigint;
declare variable V$STAGE_TYPE_ID bigint;
declare variable V$PUPIL_TYPE_ID bigint;
declare variable V$DOB date;
declare variable V$BLOB_ID bigint;
declare variable V$CERTIFICATE_TYPE_ID bigint;
declare variable V$ORI_ID bigint;
declare variable V$CONT_ID bigint;
declare variable V$REC_PARENT_ID bigint;
declare variable V$DOC_ID bigint;
declare variable V$DOCTYPE bigint;
declare variable V$EDU_AVAIL bigint;
declare variable V$EDU_FORM bigint;
declare variable V$PAY_ID bigint;
declare variable IS_VALID_REC smallint;
declare variable PUPIL_INFO_ID bigint;
declare variable FORM_ID bigint;
declare variable ORDER_ID bigint;
declare variable ORDER_DATE date;
declare variable S varchar(400);
BEGIN

  -- Если даты не указаны - берем текущий учебный год
  IF(I$DATE1 IS NULL AND I$DATE2 IS NULL) THEN
  BEGIN
      I$DATE1 = '01.09.' || IIF(EXTRACT(MONTH FROM CURRENT_DATE) < 9, EXTRACT(YEAR FROM CURRENT_DATE) - 1, EXTRACT(YEAR FROM CURRENT_DATE));
  END

  FOR
      -- Основные документы об образованию по книге выдачи (временно, до завершения переноса)
      SELECT
          L234.OBJ_ID, V1872.VAL, O.TYPE_ID,
          V43.LISTVAL_ID, -- уровень образования
          V1880.LISTVAL_ID, -- статус бланка
          L236.OBJ_ID, -- ID бланка
          V1878.VAL, -- номер бланка
          V1881.VAL, -- серия бланка
          V2355.VAL, -- ID контейнера
          V2356.VAL, -- ID документа об образовании
          V50.LISTVAL_ID, -- Тип документа
          L234.PARENT_ID, -- Уровень образования
          V566.VAL
      FROM LINKS L234 -- Тип объекта: Запись о выдаче документа об образовании в книге регистрации (#234)
      JOIN VALL V43 ON V43.OBJ_ID = L234.PARENT_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0
      JOIN VALR V1872 ON V1872.PARAM_ID = 1872 AND V1872.OBJ_ID = L234.OBJ_ID AND V1872.IS_DEL = 0
      JOIN VALR V1877 ON V1877.OBJ_ID = L234.OBJ_ID AND V1877.PARAM_ID = 1877 AND V1877.IS_DEL = 0
      JOIN VALD V1876 ON V1876.OBJ_ID = L234.OBJ_ID AND V1876.PARAM_ID = 1876 AND V1876.IS_DEL = 0
          AND (:I$DATE1 IS NULL OR V1876.VAL >= :I$DATE1) AND (:I$DATE2 IS NULL OR V1876.VAL <= :I$DATE2)
      LEFT JOIN OBJECTS O ON O.OBJ_ID = V1872.VAL
      LEFT JOIN LINKS L236 ON L236.OBJ_ID = V1877.VAL AND L236.DATE_DEL IS NULL
      LEFT JOIN VALS V1878 ON V1878.OBJ_ID = L236.OBJ_ID AND V1878.PARAM_ID = 1878 AND V1878.IS_DEL = 0 --номер бланка
      LEFT JOIN VALL V1880 ON V1880.OBJ_ID = L236.OBJ_ID AND V1880.PARAM_ID = 1880 AND V1880.IS_DEL = 0
      LEFT JOIN LINKS LP228 ON LP228.OBJ_ID = L236.OBJ_ID AND LP228.PARENT_TYPE_ID = 228 AND LP228.DATE_DEL IS NULL
      LEFT JOIN VALS V1881 ON V1881.OBJ_ID = LP228.PARENT_ID AND V1881.PARAM_ID = 1881 AND V1881.IS_DEL = 0
      LEFT JOIN VALR V2355 ON V2355.OBJ_ID = L234.OBJ_ID AND V2355.PARAM_ID = 2355 AND V2355.IS_DEL = 0
      LEFT JOIN VALR V2356 ON V2356.OBJ_ID = L234.OBJ_ID AND V2356.PARAM_ID = 2356 AND V2356.IS_DEL = 0
      LEFT JOIN VALL V50 ON V50.OBJ_ID = V2356.VAL AND V50.PARAM_ID = 50 AND V50.IS_DEL = 0
      LEFT JOIN VALD V566 ON V566.OBJ_ID = V2356.VAL AND V566.PARAM_ID = 566 AND V566.IS_DEL = 0
      WHERE L234.PARENT_ID IS NOT NULL AND L234.OBJ_TYPE_ID = 234 AND L234.DATE_DEL IS NULL
          AND V1880.LISTVAL_ID <> 5441 -- испорченный бланк (убираем)
          AND (:I$REC_ID IS NULL OR L234.OBJ_ID = :I$REC_ID) -- по конкретной записи
          AND (:I$PUPIL_ID IS NULL OR V1872.VAL = :I$PUPIL_ID) -- по конкретному ученику
          AND (:I$STAGE_ID IS NULL OR V43.LISTVAL_ID = :I$STAGE_ID)
      -- Новый формат журнала документов об образовании
      INTO :REC_ID, :V$PUPIL_ID, :V$PUPIL_TYPE_ID, :V$STAGE_TYPE_ID,
          :V$CERTIFICATE_STATUS_ID, :FORM_ID, :FORM_NUMBER, :FORM_SERIA, :V$CONT_ID,
          :V$DOC_ID, :V$DOCTYPE, :V$REC_PARENT_ID, :GIVE_DATE
  DO
  BEGIN
      SELECT FIRST 1 P.OBJ_ID
      FROM OBJECT_PARENTS_GET(:V$PUPIL_ID, 2) P
      INTO :V$OU_ID;

      CONFIRMATION_OF_LOSS = 'Нет'; -- Подтверждение утраты
      CONFIRMATION_OF_EXCHANGE = 'Нет'; -- Подтверждение обмена
      CONFIRMATION_OF_DROP = 'Нет'; -- Подтверждение уничтожения

      -- проверяем наличие дубликата (более нового дубликата)
      IF(EXISTS(
          SELECT FIRST 1 1
          FROM LINKS L11
          JOIN VALL V50 ON V50.OBJ_ID = L11.OBJ_ID AND V50.PARAM_ID = 50 AND V50.IS_DEL = 0 AND V50.LISTVAL_ID = :V$DOCTYPE
          JOIN VALL V2458 ON V2458.OBJ_ID = L11.OBJ_ID AND V2458.PARAM_ID = 2458 AND V2458.IS_DEL = 0 AND V2458.LISTVAL_ID = 5440
          WHERE L11.PARENT_ID = :V$PUPIL_ID AND L11.OBJ_TYPE_ID = 11 AND L11.DATE_DEL IS NULL AND L11.OBJ_ID > :V$DOC_ID
      ))
      THEN
      BEGIN
          CONFIRMATION_OF_LOSS = 'Да'; -- Подтверждение утраты
          CONFIRMATION_OF_EXCHANGE = 'Да'; -- Подтверждение обмена
      END

      -- В случае дубликата ищем последний (наибольший по id) реальный контейнер выдачи аттестата
      IF (V$CERTIFICATE_STATUS_ID = 5440) THEN
      BEGIN
          SELECT MAX(V2355.VAL)
          FROM LINKS L234
          JOIN VALR V1872 ON V1872.OBJ_ID = L234.OBJ_ID AND V1872.PARAM_ID = 1872 AND V1872.IS_DEL = 0 AND V1872.VAL = :V$PUPIL_ID
          JOIN VALR V2355 ON V2355.OBJ_ID = L234.OBJ_ID AND V2355.PARAM_ID = 2355 AND V2355.IS_DEL = 0
          WHERE L234.PARENT_ID = :V$REC_PARENT_ID AND L234.OBJ_TYPE_ID = 234 AND L234.DATE_DEL IS NULL
          INTO :V$CONT_ID;
      END

      -- данные для печати аттестата
      SELECT FIRST 1 L230.OBJ_ID, V1857.VAL
      FROM LINKS L292
      JOIN LINKS L230 ON L230.PARENT_ID = L292.OBJ_ID AND L230.OBJ_TYPE_ID = 230 AND L230.DATE_DEL IS NULL
      JOIN VALI V1857 ON V1857.OBJ_ID = L230.OBJ_ID AND V1857.PARAM_ID = 1857 AND V1857.IS_DEL = 0
      --LEFT JOIN VALS V2884 ON V2884.OBJ_ID = L230.OBJ_ID AND V2884.PARAM_ID = 2884 AND V2884.IS_DEL = 0
      WHERE L292.PARENT_ID = :V$PUPIL_ID AND L292.OBJ_ID = :V$CONT_ID AND L292.DATE_DEL IS NULL
      ORDER BY V1857.VAL DESC
      INTO :PUPIL_INFO_ID, :OUT_YEAR;

      -- регистрационный номер - его нет, поэтому берем номер справки
      REGNO = NULL;
      /*SELECT FIRST 1 V565.SVAL
      FROM LINKS L11
      JOIN VALL V50 ON V50.OBJ_ID = L11.OBJ_ID AND V50.PARAM_ID = 50 AND V50.IS_DEL = 0 AND V50.LISTVAL_ID = 11137
      JOIN VALD V566 ON V566.OBJ_ID = L11.OBJ_ID AND V566.PARAM_ID = 566 AND V566.IS_DEL = 0 AND EXTRACT(YEAR FROM V566.VAL) = :OUT_YEAR
      JOIN VALS V565 ON V565.OBJ_ID = L11.OBJ_ID AND V565.PARAM_ID = 565 AND V565.IS_DEL = 0
      WHERE L11.PARENT_ID = :V$PUPIL_ID AND L11.OBJ_TYPE_ID = 11 AND L11.DATE_DEL IS NULL
      ORDER BY V566.VAL DESC*/

      SELECT :OUT_YEAR || '/' || I
      FROM VAL_GET(:REC_ID, 1871, 0, :I$USER_ID)
      INTO :REGNO;
    
      IF (PUPIL_INFO_ID IS NULL) THEN
      BEGIN
          IF (V$PUPIL_TYPE_ID = 10) THEN
          BEGIN
              SELECT V FROM VAL_GET(:V$PUPIL_ID, 55, 0, :I$USER_ID) INTO :F;
              SELECT V FROM VAL_GET(:V$PUPIL_ID, 56, 0, :I$USER_ID) INTO :I;
              SELECT V FROM VAL_GET(:V$PUPIL_ID, 57, 0, :I$USER_ID) INTO :O;
              SELECT D FROM VAL_GET(:V$PUPIL_ID, 89, 0, :I$USER_ID) INTO :DOB;
          END
          ELSE IF (V$PUPIL_TYPE_ID = 126) THEN
          BEGIN
              SELECT V FROM VAL_GET(:V$PUPIL_ID, 827, 0, :I$USER_ID) INTO :F;
              SELECT V FROM VAL_GET(:V$PUPIL_ID, 828, 0, :I$USER_ID) INTO :I;
              SELECT V FROM VAL_GET(:V$PUPIL_ID, 829, 0, :I$USER_ID) INTO :O;
              SELECT D FROM VAL_GET(:V$PUPIL_ID, 830, 0, :I$USER_ID) INTO :DOB;
          END

          IF (V$STAGE_TYPE_ID = 26) THEN V$CERTIFICATE_TYPE_ID = 5377; ELSE V$CERTIFICATE_TYPE_ID = 5379;
      END
      ELSE
      BEGIN
          SELECT I FROM VAL_GET(:PUPIL_INFO_ID, 1855, 0, :I$USER_ID) INTO :ORDER_ID;
          SELECT D FROM VAL_GET(:PUPIL_INFO_ID, 1856, 0, :I$USER_ID) INTO :ORDER_DATE;

          IF(GIVE_DATE IS NULL) THEN
          BEGIN
              SELECT D FROM VAL_GET(:PUPIL_INFO_ID, 1884, 0, :I$USER_ID) INTO :GIVE_DATE;
          END

          -- Год поступления получаем из реестра движения
          SELECT FIRST 1 EXTRACT(YEAR FROM M.DATE_IN)
          FROM PERSON_MOVEMENTS M
          JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
          WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :V$PUPIL_ID AND M.REASON_IN IN (805, 806, 3140)
          ORDER BY M.DATE_IN DESC
          INTO :IN_YEAR;

          TRAINING_PERIOD = '=(RC[-1]-RC[-2])';
          IF(IN_YEAR > OUT_YEAR) THEN IN_YEAR = NULL;

          IF (V$PUPIL_TYPE_ID = 10) THEN
          BEGIN
              SELECT V FROM VAL_GET(:V$PUPIL_ID, 55, 0, :I$USER_ID) INTO :F;
              SELECT V FROM VAL_GET(:V$PUPIL_ID, 56, 0, :I$USER_ID) INTO :I;
              SELECT V FROM VAL_GET(:V$PUPIL_ID, 57, 0, :I$USER_ID) INTO :O;
              SELECT D FROM VAL_GET(:V$PUPIL_ID, 89, 0, :I$USER_ID) INTO :V$DOB;
          END
          ELSE IF (V$PUPIL_TYPE_ID = 126) THEN
          BEGIN
              SELECT V FROM VAL_GET(:V$PUPIL_ID, 827, 0, :I$USER_ID) INTO :F;
              SELECT V FROM VAL_GET(:V$PUPIL_ID, 828, 0, :I$USER_ID) INTO :I;
              SELECT V FROM VAL_GET(:V$PUPIL_ID, 829, 0, :I$USER_ID) INTO :O;
              SELECT D FROM VAL_GET(:V$PUPIL_ID, 830, 0, :I$USER_ID) INTO :V$DOB;
          END
    
          SELECT D FROM VAL_GET(:PUPIL_INFO_ID, 1859, 0, :I$USER_ID) INTO :DOB;
    
          IF (DOB <> V$DOB) THEN
          BEGIN
              SELECT BLOB_ID FROM VAL_ADD(1859, :PUPIL_INFO_ID, :V$DOB) INTO :V$BLOB_ID;
              DOB = V$DOB;
          END

          SELECT I FROM VAL_GET(:PUPIL_INFO_ID, 1860, 0, :I$USER_ID) INTO :V$CERTIFICATE_TYPE_ID;
      END

      SELECT UPPER(LEFT(V, 1)) || SUBSTRING(V FROM 2 FOR 2) FROM VAL_GET (:V$PUPIL_ID, 88, 0, :I$USER_ID) INTO :SEX;

      /*SELECT CASE
          WHEN I = 0 THEN ''  --'лица без гражданства'
          WHEN I = 1515 THEN 'РФ'
          WHEN I in (1516, 1519, 1526, 1532, 1564, 1585, 1592, 1602, 1607, 1623, 1675, 1684, 1687, 1688, 1707) THEN 'ближнее (из стран СНГ, Балтии, Грузии, Абхазии и Южной Осетии)'
          ELSE 'дальнее (других иностранных - кроме стран СНГ, Балтии, Грузии, Абхазии и Южной Осетии)'
      END
      FROM VAL_GET(:V$PUPIL_ID, 91, 0, :I$USER_ID)
      */
      SELECT COALESCE(LV.TAG, '')
      FROM VALL V91
      JOIN LISTVALS LV ON LV.LISTVAL_ID = V91.LISTVAL_ID
      WHERE V91.OBJ_ID = :V$PUPIL_ID AND V91.PARAM_ID = 91 AND V91.IS_DEL = 0
      INTO :CITIZENSHIP;

      -- место рождения в 2021 форме неактуально
      --SELECT V FROM VAL_GET(:V$PUPIL_ID, 1343, 0, :I$USER_ID) INTO :BPL;

      SELECT V FROM VAL_GET(:V$PUPIL_ID, 1409, 0, :I$USER_ID) INTO :SNILS;

      SELECT CAST(RES.VAL AS VARCHAR(100)), LEFT(RES.VAL, POSITION(' ', RES.VAL))
      FROM LISTVALS LV
      JOIN RES ON RES.RES_ID = LV.RES_ID AND RES.LANG_CODE = 'RU' AND RES.IS_DEL = 0
      WHERE LV.LISTVAL_ID = :V$CERTIFICATE_TYPE_ID AND LV.IS_DEL = 0
      INTO :CERTIFICATE_TYPE, :CERTIFICATE_NAME;

      -- Уровень образования
      SELECT CAST(RES.VAL AS VARCHAR(100))
      FROM LISTVALS LV
      JOIN RES ON RES.RES_ID = LV.RES_ID AND RES.LANG_CODE = 'RU' AND RES.IS_DEL = 0
      WHERE LV.LISTVAL_ID = :V$STAGE_TYPE_ID AND LV.IS_DEL = 0
      INTO :STAGE;

      -- статус документа
      IF (V$CERTIFICATE_STATUS_ID = 5439) THEN V$CERTIFICATE_STATUS_ID = 5438;
      SELECT CAST(RES.VAL AS VARCHAR(100))
      FROM LISTVALS LV
      JOIN RES ON RES.RES_ID = LV.RES_ID AND RES.LANG_CODE = 'RU' AND RES.IS_DEL = 0
      WHERE LV.LISTVAL_ID = :V$CERTIFICATE_STATUS_ID AND LV.IS_DEL = 0
      INTO :CERTIFICATE_STATUS;
      IF (CERTIFICATE_STATUS = 'Первичный') THEN CERTIFICATE_STATUS = 'Оригинал';

      -- Форма получения образования
      V$EDU_AVAIL = NULL;
      SELECT FIRST 1 V1888.LISTVAL_ID
      FROM VALL V1888
      WHERE V1888.OBJ_ID = :V$PUPIL_ID AND V1888.PARAM_ID = 1888 AND V1888.IS_DEL = 0
      INTO :V$EDU_AVAIL;
      IF(V$EDU_AVAIL = 5421) THEN EDU_AVAIL = 'вне образовательной организации'; ELSE EDU_AVAIL = 'в образовательной организации';

      -- Форма финансирования
      -- в школах если не указано = смотрим подчинение
      V$PAY_ID = NULL;
      SELECT FIRST 1 V1812.LISTVAL_ID
      FROM VALL V1812
      WHERE V1812.OBJ_ID = :V$PUPIL_ID AND V1812.PARAM_ID = 1812 AND V1812.IS_DEL = 0
      INTO :V$PAY_ID;

      IF(V$PAY_ID IS NULL) THEN
      BEGIN
        SELECT COALESCE(V.V, '')
        FROM VAL_GET(:V$OU_ID, 8) V
        WHERE V.IS_EXISTS = 1
        INTO :S;

        IF(POSITION('едерал' IN S) > 0) THEN V$PAY_ID = 5257;
        ELSE IF(POSITION('егион' IN S) > 0) THEN V$PAY_ID = 5258;
        ELSE IF(POSITION('униципа' IN S) > 0) THEN V$PAY_ID = 5259;
        ELSE V$PAY_ID = 0;
      END

      IF(V$PAY_ID = 5257) THEN PAY_SRC = 'Федеральный бюджет';
      ELSE IF(V$PAY_ID = 5258) THEN PAY_SRC = 'Региональный бюджет';
      ELSE IF(V$PAY_ID = 5259) THEN PAY_SRC = 'Местный бюджет';
      ELSE PAY_SRC = '';

      -- Форма обучения
      V$EDU_FORM = NULL;
      SELECT FIRST 1 V80.LISTVAL_ID
      FROM VALL V80
      WHERE V80.OBJ_ID = :V$PUPIL_ID AND V80.PARAM_ID = 80 AND V80.IS_DEL = 0
      INTO :V$EDU_FORM;
      IF(V$EDU_FORM = 5418) THEN EDU_FORM = 'Очная';
      ELSE IF(V$EDU_FORM = 5419) THEN EDU_FORM = 'Очно-заочная (вечерняя)';
      ELSE IF(V$EDU_FORM = 5420) THEN EDU_FORM = 'Заочная';
      ELSE EDU_FORM = '';

      V$ORI_ID = NULL;
      ORIG_CERTIFICATE_NAME = NULL;    -- Наименование документа об образовании (оригинала)
      ORIG_FORM_SERIA = NULL;          -- Серия (оригинала)
      ORIG_FORM_NUMBER = NULL;         -- Номер (оригинала)
      ORIG_REGNO = NULL;               -- Регистрационный N (оригинала)
      ORIG_GIVE_DATE = NULL;           -- Дата выдачи (оригинала)
      ORIG_F = NULL;                   -- Фамилия получателя (оригинала)
      ORIG_I = NULL;                   -- Имя получателя (оригинала)
      ORIG_O = NULL;                   -- Отчество получателя (оригинала)

      -- если это дубликат, ищем первоначальный документ
      IF (V$CERTIFICATE_STATUS_ID = 5440) THEN
      BEGIN
          SELECT FIRST 1 V1872.OBJ_ID FROM VALR V1872 --ученик
          JOIN VALR V2356 ON V2356.OBJ_ID = V1872.OBJ_ID AND V2356.PARAM_ID = 2356 AND V2356.IS_DEL = 0  --документ
          JOIN VALL V50 ON V50.OBJ_ID = V2356.VAL AND V50.PARAM_ID = 50 AND V50.IS_DEL = 0 AND V50.LISTVAL_ID = :V$DOCTYPE --тип документа
          JOIN VALR V1877 ON V1877.OBJ_ID = V1872.OBJ_ID AND V1877.PARAM_ID = 1877 AND V1877.IS_DEL = 0  --бланк
          JOIN LINKS L236 ON L236.OBJ_ID = V1877.VAL AND L236.DATE_DEL IS NULL
          JOIN VALL V1880 ON V1880.OBJ_ID = L236.OBJ_ID AND V1880.PARAM_ID = 1880 AND V1880.IS_DEL = 0 AND V1880.LISTVAL_ID IN (5438, 5439) --первичный, взамен испорченого
          WHERE V1872.VAL = :V$PUPIL_ID AND V1872.PARAM_ID = 1872 AND V1872.IS_DEL = 0
          ORDER BY V1872.OBJ_ID
          INTO :V$ORI_ID;

          IF (V$ORI_ID IS NOT NULL) THEN
          BEGIN
              SELECT FIRST 1 CERTIFICATE_TYPE,    --Наименование документа об образовании (оригинала)
                  FORM_SERIA,          -- Серия (оригинала)
                  FORM_NUMBER,         -- Номер (оригинала)
                  REGNO,               -- Регистрационный N (оригинала)
                  GIVE_DATE,           -- Дата выдачи (оригинала)
                  F,                   -- Фамилия получателя (оригинала)
                  I,                   -- Имя получателя (оригинала)
                  O                    -- Отчество получателя (оригинала)
              FROM REPORT_FIS_FRDO(:V$ORI_ID)
              INTO
                  :ORIG_CERTIFICATE_NAME,    -- Наименование документа об образовании (оригинала)
                  :ORIG_FORM_SERIA,          -- Серия (оригинала)
                  :ORIG_FORM_NUMBER,         -- Номер (оригинала)
                  :ORIG_REGNO,               -- Регистрационный N (оригинала)
                  :ORIG_GIVE_DATE,           -- Дата выдачи (оригинала)
                  :ORIG_F,                   -- Фамилия получателя (оригинала)
                  :ORIG_I,                   -- Имя получателя (оригинала)
                  :ORIG_O;                   -- Отчество получателя (оригинала)
          END
      END

      IF((CHAR_LENGTH(COALESCE(F, '')) > 0) AND (CHAR_LENGTH(COALESCE(I, '')) > 0) AND (O IS NULL OR O = '')) THEN O = 'Нет';

      IF(
          (CERTIFICATE_NAME IS NULL OR CERTIFICATE_TYPE IS NULL OR CERTIFICATE_STATUS IS NULL OR CONFIRMATION_OF_LOSS IS NULL OR CONFIRMATION_OF_EXCHANGE IS NULL OR
              STAGE IS NULL OR FORM_SERIA IS NULL OR FORM_NUMBER IS NULL OR GIVE_DATE IS NULL OR IN_YEAR IS NULL OR OUT_YEAR IS NULL OR F IS NULL OR
              I IS NULL OR O IS NULL OR DOB IS NULL OR SEX IS NULL) OR
          (V$CERTIFICATE_STATUS_ID = 5440 AND
              (ORIG_CERTIFICATE_NAME IS NULL OR ORIG_FORM_SERIA IS NULL OR ORIG_FORM_NUMBER IS NULL OR ORIG_GIVE_DATE IS NULL OR ORIG_F IS NULL OR ORIG_I IS NULL OR ORIG_O IS NULL)
          )
      )
      THEN IS_VALID_REC = 0; ELSE IS_VALID_REC = 1;

      FORM_SERIA = '''' || FORM_SERIA;
      FORM_NUMBER = '''' || FORM_NUMBER;
      -- ORIG_FORM_SERIA = '''' || ORIG_FORM_SERIA;
      -- ORIG_FORM_NUMBER = '''' || ORIG_FORM_NUMBER;

      IF(I$VALID IS NULL OR I$VALID = IS_VALID_REC) THEN SUSPEND;
  END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE REPORT_FSPEO_DATA (
    I$SECTION INTEGER NOT NULL)
RETURNS (
    SECTION_NO VARCHAR(10),
    TITLE VARCHAR(200),
    VAL INTEGER,
    CONDITION VARCHAR(1000),
    HELPER VARCHAR(1000),
    ONE_STRING SMALLINT)
AS
declare variable V$Y integer;
declare variable V$DTS date;
declare variable V$DTSN date;
declare variable V$DTJ date;
declare variable V$FLAG smallint;
BEGIN

  V$Y = EXTRACT(YEAR FROM CURRENT_DATE);
  V$DTS = '1.09.' || V$Y;
  V$DTSN = '1.09.' || (V$Y+1);
  V$DTJ = '01.01.' || (V$Y+1);

  VAL = 0;
  V$FLAG = 0;
  ONE_STRING = 0;

  IF (I$SECTION = 0) THEN
  BEGIN
    SECTION_NO = '19.';
    TITLE = 'Общая численность детей, зачисленных в ДОО.';
    CONDITION = 'Общая численность детей, зачисленных в ДОО на дату сдачи отчетности, в разрезе возрастных категорий.';
    HELPER = 'Передается общая численность детей, числящихся в ДОО на дату сдачи отчетности (имеются приказы о зачислении данных детей в ДОО). Дата расчета возраста ребенка: на 1 сентября текущего календарного года.';
    FOR
      SELECT DATEDIFF(MONTH, V89.VAL, :V$DTS) FROM LINKS L2
        JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
        JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        JOIN VALD V89 ON V89.OBJ_ID = L10.OBJ_ID AND V89.PARAM_ID = 89 AND V89.IS_DEL = 0
      WHERE L2.OBJ_TYPE_ID = 2 AND L2.PARENT_ID IS NULL AND L2.DATE_DEL IS NULL
      INTO VAL
    DO BEGIN
      V$FLAG = 1;
      SUSPEND;
    END
  END

  ELSE IF (I$SECTION = 1) THEN
  BEGIN
    SECTION_NO = '19.1';
    TITLE = 'Общая численность детей, зачисленных в ДОО.';
    CONDITION = 'Общая численность детей, зачисленных в ДОО на дату сдачи отчетности, в разрезе возрастных категорий.';
    HELPER = 'Передается общая численность детей, числящихся в ДОО на дату сдачи отчетности (имеются приказы о зачислении данных детей в ДОО). Дата расчета возраста ребенка: на текущую дату.';
    FOR
      SELECT DATEDIFF(MONTH, V89.VAL, CURRENT_DATE) FROM LINKS L2
        JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
        JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        JOIN VALD V89 ON V89.OBJ_ID = L10.OBJ_ID AND V89.PARAM_ID = 89 AND V89.IS_DEL = 0
      WHERE L2.OBJ_TYPE_ID = 2 AND L2.PARENT_ID IS NULL AND L2.DATE_DEL IS NULL
      INTO VAL
    DO BEGIN
      V$FLAG = 1;
      SUSPEND;
    END
  END

  ELSE IF (I$SECTION = 2) THEN
  BEGIN
    SECTION_NO = '19.2';
    TITLE = 'Общая численность детей, зачисленных в ДОО.';
    CONDITION = 'Общая численность детей, зачисленных в ДОО на дату сдачи отчетности, в разрезе возрастных категорий.';
    HELPER = 'Передается общая численность детей, числящихся в ДОО на дату сдачи отчетности (имеются приказы о зачислении данных детей в ДОО). Дата расчета возраста ребенка: на 1 января следующего календарного года.';
    FOR
      SELECT DATEDIFF(MONTH, V89.VAL, :V$DTJ) FROM LINKS L2
        JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
        JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        JOIN VALD V89 ON V89.OBJ_ID = L10.OBJ_ID AND V89.PARAM_ID = 89 AND V89.IS_DEL = 0
      WHERE L2.OBJ_TYPE_ID = 2 AND L2.PARENT_ID IS NULL AND L2.DATE_DEL IS NULL
      INTO VAL
    DO BEGIN
      V$FLAG = 1;
      SUSPEND;
    END
  END

--  ELSE IF (I$SECTION = 3) THEN
--  BEGIN
--    SECTION_NO = '21.';
--    TITLE = 'Общая численность детей, получающих дошкольное образование в семейных дошкольных группах.';
--    CONDITION = 'Общая численность детей, получающих дошкольное образование в семейных дошкольных группах, в разрезе возрастных категорий.';
--    HELPER = 'Передается общая численность детей, зачисленных в семейные дошкольные группы, на дату сдачи отчетности. Дата расчета возраста ребенка: на текущую дату.';
--    VAL = 0;
--    V$FLAG = 1;
--    SUSPEND;
--  END

  ELSE IF (I$SECTION = 4) THEN
  BEGIN
    SECTION_NO = '22.';
    TITLE = 'Общая численность детей, зачисленных в группы для детей с ОВЗ.';
    CONDITION = 'Общая численность детей, зачисленных в группы для детей с ОВЗ, в разрезе возрастных категорий.';
    HELPER = 'ОВЗ – вид группы – компенсирующая. Передается общая численность детей, зачисленных в группы для детей с ОВЗ.Дата расчета возраста ребенка: на текущую дату.';
    FOR
      SELECT DATEDIFF(MONTH, V89.VAL, CURRENT_DATE) FROM LINKS L2
        JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
        -- вид группы
        JOIN VALL V1549 ON V1549.OBJ_ID = L9.OBJ_ID AND V1549.PARAM_ID = 1549 AND V1549.IS_DEL = 0 AND V1549.LISTVAL_ID IN (3266, 3268)
        JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        JOIN VALD V89 ON V89.OBJ_ID = L10.OBJ_ID AND V89.PARAM_ID = 89 AND V89.IS_DEL = 0
      WHERE L2.OBJ_TYPE_ID = 2 AND L2.PARENT_ID IS NULL AND L2.DATE_DEL IS NULL
      INTO VAL
    DO BEGIN
      V$FLAG = 1;
      SUSPEND;
    END
  END

  ELSE IF (I$SECTION = 5) THEN
  BEGIN
    SECTION_NO = '22.1';
    TITLE = 'Численность детей с ОВЗ, зачисленных в группы для детей с нарушением слуха.';
    CONDITION = 'Общая численность детей с ОВЗ, зачисленных в группы для детей с нарушением слуха, в разрезе возрастных категорий.';
    HELPER = 'Передается общая численность детей с ОВЗ, зачисленных в группы компенсирующей и комбинированной направленности для детей с нарушением слуха. Дата расчета возраста ребенка: на текущую дату.';
    FOR
      SELECT DATEDIFF(MONTH, V89.VAL, CURRENT_DATE) FROM LINKS L2
        JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
        -- вид группы
        JOIN VALL V1549 ON V1549.OBJ_ID = L9.OBJ_ID AND V1549.PARAM_ID = 1549 AND V1549.IS_DEL = 0 AND V1549.LISTVAL_ID = 3266
        -- направленность
        JOIN VALL V1655 ON V1655.OBJ_ID = L9.OBJ_ID AND V1655.PARAM_ID = 1655 AND V1655.IS_DEL = 0 AND V1655.LISTVAL_ID = 3388
        JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        JOIN VALD V89 ON V89.OBJ_ID = L10.OBJ_ID AND V89.PARAM_ID = 89 AND V89.IS_DEL = 0
      WHERE L2.OBJ_TYPE_ID = 2 AND L2.PARENT_ID IS NULL AND L2.DATE_DEL IS NULL
      INTO VAL
    DO BEGIN
      V$FLAG = 1;
      SUSPEND;
    END
  END

  ELSE IF (I$SECTION = 6) THEN
  BEGIN
    SECTION_NO = '22.2';
    TITLE = 'Численность детей с ОВЗ, зачисленных в группы для детей с нарушением речи.';
    CONDITION = 'Общая численность детей с ОВЗ, зачисленных в группы для детей с нарушением речи, в разрезе возрастных категорий.';
    HELPER = 'Передается общая численность детей с ОВЗ, зачисленных в группы компенсирующей и комбинированной направленности для детей с нарушением речи. Дата расчета возраста ребенка: на текущую дату.';
    FOR
      SELECT DATEDIFF(MONTH, V89.VAL, CURRENT_DATE) FROM LINKS L2
        JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
        -- вид группы
        JOIN VALL V1549 ON V1549.OBJ_ID = L9.OBJ_ID AND V1549.PARAM_ID = 1549 AND V1549.IS_DEL = 0 AND V1549.LISTVAL_ID = 3266
        -- направленность
        JOIN VALL V1655 ON V1655.OBJ_ID = L9.OBJ_ID AND V1655.PARAM_ID = 1655 AND V1655.IS_DEL = 0 AND V1655.LISTVAL_ID = 3389
        JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        JOIN VALD V89 ON V89.OBJ_ID = L10.OBJ_ID AND V89.PARAM_ID = 89 AND V89.IS_DEL = 0
      WHERE L2.OBJ_TYPE_ID = 2 AND L2.PARENT_ID IS NULL AND L2.DATE_DEL IS NULL
      INTO VAL
    DO BEGIN
      V$FLAG = 1;
      SUSPEND;
    END
  END

  ELSE IF (I$SECTION = 7) THEN
  BEGIN
    SECTION_NO = '22.3';
    TITLE = 'Численность детей с ОВЗ, зачисленных в группы для детей с нарушением зрения';
    CONDITION = 'Общая численность детей с ОВЗ, зачисленных в группы для детей с нарушением зрения, в разрезе возрастных категорий.';
    HELPER = 'Передается общая численность детей с ОВЗ, зачисленных в группы компенсирующей и комбинированной направленности для детей с нарушением зрения. Дата расчета возраста ребенка: на текущую дату.';
    FOR
      SELECT DATEDIFF(MONTH, V89.VAL, CURRENT_DATE) FROM LINKS L2
        JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
        -- вид группы
        JOIN VALL V1549 ON V1549.OBJ_ID = L9.OBJ_ID AND V1549.PARAM_ID = 1549 AND V1549.IS_DEL = 0 AND V1549.LISTVAL_ID = 3266
        -- направленность
        JOIN VALL V1655 ON V1655.OBJ_ID = L9.OBJ_ID AND V1655.PARAM_ID = 1655 AND V1655.IS_DEL = 0 AND V1655.LISTVAL_ID = 3390
        JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        JOIN VALD V89 ON V89.OBJ_ID = L10.OBJ_ID AND V89.PARAM_ID = 89 AND V89.IS_DEL = 0
      WHERE L2.OBJ_TYPE_ID = 2 AND L2.PARENT_ID IS NULL AND L2.DATE_DEL IS NULL
      INTO VAL
    DO BEGIN
      V$FLAG = 1;
      SUSPEND;
    END
  END

  ELSE IF (I$SECTION = 8) THEN
  BEGIN
    SECTION_NO = '22.4';
    TITLE = 'Численность детей с ОВЗ, зачисленных в группы для детей с нарушением интеллекта.';
    CONDITION = 'Общая численность детей с ОВЗ, зачисленных в группы для детей с нарушением интеллекта, в разрезе возрастных категорий.';
    HELPER = 'Передается общая численность детей с ОВЗ, зачисленных в группы компенсирующей и комбинированной направленности для детей с нарушением интеллекта. Дата расчета возраста ребенка: на текущую дату.';
    FOR
      SELECT DATEDIFF(MONTH, V89.VAL, CURRENT_DATE) FROM LINKS L2
        JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
        -- вид группы
        JOIN VALL V1549 ON V1549.OBJ_ID = L9.OBJ_ID AND V1549.PARAM_ID = 1549 AND V1549.IS_DEL = 0 AND V1549.LISTVAL_ID = 3266
        -- направленность
        JOIN VALL V1655 ON V1655.OBJ_ID = L9.OBJ_ID AND V1655.PARAM_ID = 1655 AND V1655.IS_DEL = 0 AND V1655.LISTVAL_ID = 3391
        JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        JOIN VALD V89 ON V89.OBJ_ID = L10.OBJ_ID AND V89.PARAM_ID = 89 AND V89.IS_DEL = 0
      WHERE L2.OBJ_TYPE_ID = 2 AND L2.PARENT_ID IS NULL AND L2.DATE_DEL IS NULL
      INTO VAL
    DO BEGIN
      V$FLAG = 1;
      SUSPEND;
    END
  END

  ELSE IF (I$SECTION = 9) THEN
  BEGIN
    SECTION_NO = '22.5';
    TITLE = 'Численность детей с ОВЗ, зачисленных в группы для детей с задержкой психического развития.';
    CONDITION = 'Общая численность детей с ОВЗ, зачисленных в группы для детей с задержкой психического развития, в разрезе возрастных категорий.';
    HELPER = 'Передается общая численность детей с ОВЗ, зачисленных в группы компенсирующей и комбинированной направленности для детей с задержкой психического развития. Дата расчета возраста ребенка: на текущую дату.';
    FOR
      SELECT DATEDIFF(MONTH, V89.VAL, CURRENT_DATE) FROM LINKS L2
        JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
        -- вид группы
        JOIN VALL V1549 ON V1549.OBJ_ID = L9.OBJ_ID AND V1549.PARAM_ID = 1549 AND V1549.IS_DEL = 0 AND V1549.LISTVAL_ID = 3266
        -- направленность
        JOIN VALL V1655 ON V1655.OBJ_ID = L9.OBJ_ID AND V1655.PARAM_ID = 1655 AND V1655.IS_DEL = 0 AND V1655.LISTVAL_ID = 3392
        JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        JOIN VALD V89 ON V89.OBJ_ID = L10.OBJ_ID AND V89.PARAM_ID = 89 AND V89.IS_DEL = 0
      WHERE L2.OBJ_TYPE_ID = 2 AND L2.PARENT_ID IS NULL AND L2.DATE_DEL IS NULL
      INTO VAL
    DO BEGIN
      V$FLAG = 1;
      SUSPEND;
    END
  END

  ELSE IF (I$SECTION = 10) THEN
  BEGIN
    SECTION_NO = '22.6';
    TITLE = 'Численность детей с ОВЗ, зачисленных в группы для детей с нарушением опорно-двигательного аппарата.';
    CONDITION = 'Общая численность детей с ОВЗ, зачисленных в группы для детей с нарушением опорно-двигательного аппарата, в разрезе возрастных категорий.';
    HELPER = 'Передается общая численность детей с ОВЗ, зачисленных в группы компенсирующей и комбинированной направленности для детей с нарушением опорно-двигательного аппарата. Дата расчета возраста ребенка: на текущую дату.';
    FOR
      SELECT DATEDIFF(MONTH, V89.VAL, CURRENT_DATE) FROM LINKS L2
        JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
        -- вид группы
        JOIN VALL V1549 ON V1549.OBJ_ID = L9.OBJ_ID AND V1549.PARAM_ID = 1549 AND V1549.IS_DEL = 0 AND V1549.LISTVAL_ID = 3266
        -- направленность
        JOIN VALL V1655 ON V1655.OBJ_ID = L9.OBJ_ID AND V1655.PARAM_ID = 1655 AND V1655.IS_DEL = 0 AND V1655.LISTVAL_ID = 3393
        JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        JOIN VALD V89 ON V89.OBJ_ID = L10.OBJ_ID AND V89.PARAM_ID = 89 AND V89.IS_DEL = 0
      WHERE L2.OBJ_TYPE_ID = 2 AND L2.PARENT_ID IS NULL AND L2.DATE_DEL IS NULL
      INTO VAL
    DO BEGIN
      V$FLAG = 1;
      SUSPEND;
    END
  END

  ELSE IF (I$SECTION = 11) THEN
  BEGIN
    SECTION_NO = '22.7';
    TITLE = 'Численность детей с ОВЗ, зачисленных в группы для детей со сложным дефектом.';
    CONDITION = 'Общая численность детей с ОВЗ, зачисленных в группы для детей со сложным дефектом, в разрезе возрастных категорий.';
    HELPER = 'Передается общая численность детей с ОВЗ, зачисленных в группы компенсирующей и комбинированной направленности для детей со сложным дефектом. Дата расчета возраста ребенка: на текущую дату.';
    FOR
      SELECT DATEDIFF(MONTH, V89.VAL, CURRENT_DATE) FROM LINKS L2
        JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
        -- вид группы
        JOIN VALL V1549 ON V1549.OBJ_ID = L9.OBJ_ID AND V1549.PARAM_ID = 1549 AND V1549.IS_DEL = 0 AND V1549.LISTVAL_ID = 3266
        -- направленность
        JOIN VALL V1655 ON V1655.OBJ_ID = L9.OBJ_ID AND V1655.PARAM_ID = 1655 AND V1655.IS_DEL = 0 AND V1655.LISTVAL_ID = 3394
        JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        JOIN VALD V89 ON V89.OBJ_ID = L10.OBJ_ID AND V89.PARAM_ID = 89 AND V89.IS_DEL = 0
      WHERE L2.OBJ_TYPE_ID = 2 AND L2.PARENT_ID IS NULL AND L2.DATE_DEL IS NULL
      INTO VAL
    DO BEGIN
      V$FLAG = 1;
      SUSPEND;
    END
  END

  ELSE IF (I$SECTION = 12) THEN
  BEGIN
    SECTION_NO = '22.8';
    TITLE = 'Численность детей с ОВЗ, зачисленных в группы для детей с иными ограниченными возможностями здоровья.';
    CONDITION = 'Общая численность детей с ОВЗ, зачисленных в группы для детей с иными ограниченными возможностями здоровья, в разрезе возрастных категорий.';
    HELPER = 'Передается общая численность детей с ОВЗ, зачисленных в группы компенсирующей и комбинированной направленности для детей с иными ограниченными возможностями здоровья. Дата расчета возраста ребенка: на текущую дату.';
    FOR
      SELECT DATEDIFF(MONTH, V89.VAL, CURRENT_DATE) FROM LINKS L2
        JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
        -- вид группы
        JOIN VALL V1549 ON V1549.OBJ_ID = L9.OBJ_ID AND V1549.PARAM_ID = 1549 AND V1549.IS_DEL = 0 AND V1549.LISTVAL_ID = 3266
        -- направленность
        JOIN VALL V1655 ON V1655.OBJ_ID = L9.OBJ_ID AND V1655.PARAM_ID = 1655 AND V1655.IS_DEL = 0 AND V1655.LISTVAL_ID = 3395
        JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        JOIN VALD V89 ON V89.OBJ_ID = L10.OBJ_ID AND V89.PARAM_ID = 89 AND V89.IS_DEL = 0
      WHERE L2.OBJ_TYPE_ID = 2 AND L2.PARENT_ID IS NULL AND L2.DATE_DEL IS NULL
      INTO VAL
    DO BEGIN
      V$FLAG = 1;
      SUSPEND;
    END
  END

  ELSE IF (I$SECTION = 13) THEN
  BEGIN
    SECTION_NO = '23.';
    TITLE = 'Общая численность детей, зачисленных в группы компенсирующей направленности.';
    CONDITION = 'Общая численность детей, зачисленных в группы компенсирующей направленности, в разрезе возрастных категорий.';
    HELPER = 'Передается общая численность детей, зачисленных в группы компенсирующей направленности. Дата расчета возраста ребенка: на текущую дату.';
    FOR
      SELECT DATEDIFF(MONTH, V89.VAL, CURRENT_DATE) FROM LINKS L2
        JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
        -- вид группы
        JOIN VALL V1549 ON V1549.OBJ_ID = L9.OBJ_ID AND V1549.PARAM_ID = 1549 AND V1549.IS_DEL = 0 AND V1549.LISTVAL_ID = 3266
        JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        JOIN VALD V89 ON V89.OBJ_ID = L10.OBJ_ID AND V89.PARAM_ID = 89 AND V89.IS_DEL = 0
      WHERE L2.OBJ_TYPE_ID = 2 AND L2.PARENT_ID IS NULL AND L2.DATE_DEL IS NULL
      INTO VAL
    DO BEGIN
      V$FLAG = 1;
      SUSPEND;
    END
  END

  ELSE IF (I$SECTION = 14) THEN
  BEGIN
    SECTION_NO = '24.';
    TITLE = 'Общая численность детей, зачисленных в группы оздоровительной направленности.';
    CONDITION = 'Общая численность детей, зачисленных в группы оздоровительной направленности, в разрезе возрастных категорий.';
    HELPER = 'Передается общая численность детей, зачисленных в группы оздоровительной направленности. Дата расчета возраста ребенка: на текущую дату.';
    FOR
      SELECT DATEDIFF(MONTH, V89.VAL, CURRENT_DATE) FROM LINKS L2
        JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
        -- вид группы
        JOIN VALL V1549 ON V1549.OBJ_ID = L9.OBJ_ID AND V1549.PARAM_ID = 1549 AND V1549.IS_DEL = 0 AND V1549.LISTVAL_ID = 3267
        JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        JOIN VALD V89 ON V89.OBJ_ID = L10.OBJ_ID AND V89.PARAM_ID = 89 AND V89.IS_DEL = 0
      WHERE L2.OBJ_TYPE_ID = 2 AND L2.PARENT_ID IS NULL AND L2.DATE_DEL IS NULL
      INTO VAL
    DO BEGIN
      V$FLAG = 1;
      SUSPEND;
    END
  END

--  ELSE IF (I$SECTION = 15) THEN
--  BEGIN
--    SECTION_NO = '25.';
--    TITLE = 'Общая численность детей, посещающих дошкольные группы без реализации образовательных программ.';
--    CONDITION = 'Общая численность детей, посещающих дошкольные группы без реализации образовательных программ, в разрезе возрастных категорий.';
--    HELPER = 'Передается общая численность детей, зачисленных в группы  по присмотру и уходу и группы для детей раннего возраста (без реализации образовательной программы).';
--    VAL = 0;
--    V$FLAG = 1;
--    SUSPEND;
--  END

  ELSE IF (I$SECTION = 16) THEN
  BEGIN
    SECTION_NO = '26.';
    TITLE = 'Общая численность детей, посещающих группы круглосуточного пребывания детей.';
    CONDITION = 'Общая численность детей, посещающих группы круглосуточного пребывания детей, в разрезе возрастных категорий.';
    HELPER = 'Передается общая численность детей, посещающих группы круглосуточного пребывания детей. Дата расчета возраста ребенка: на текущую дату.';
    FOR
      SELECT DATEDIFF(MONTH, V89.VAL, CURRENT_DATE) FROM LINKS L2
        JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
        -- режим работы
        JOIN VALL V1558 ON V1558.OBJ_ID = L9.OBJ_ID AND V1558.PARAM_ID = 1558 AND V1558.IS_DEL = 0 AND V1558.LISTVAL_ID = 3295
        JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        JOIN VALD V89 ON V89.OBJ_ID = L10.OBJ_ID AND V89.PARAM_ID = 89 AND V89.IS_DEL = 0
      WHERE L2.OBJ_TYPE_ID = 2 AND L2.PARENT_ID IS NULL AND L2.DATE_DEL IS NULL
      INTO VAL
    DO BEGIN
      V$FLAG = 1;
      SUSPEND;
    END
  END

  ELSE IF (I$SECTION = 17) THEN
  BEGIN
    SECTION_NO = '27.';
    TITLE = 'Общая численность детей, зачисленных в группы кратковременного пребывания детей.';
    CONDITION = 'Общая численность детей, зачисленных в группы кратковременного пребывания детей, в разрезе возрастных категорий.';
    HELPER = 'Передается общая численность детей, зачисленных в группы кратковременного пребывания детей. Дата расчета возраста ребенка: на текущую дату.';
    FOR
      SELECT DATEDIFF(MONTH, V89.VAL, CURRENT_DATE) FROM LINKS L2
        JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
        -- режим работы
        JOIN VALL V1558 ON V1558.OBJ_ID = L9.OBJ_ID AND V1558.PARAM_ID = 1558 AND V1558.IS_DEL = 0 AND V1558.LISTVAL_ID = 3296
        JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        JOIN VALD V89 ON V89.OBJ_ID = L10.OBJ_ID AND V89.PARAM_ID = 89 AND V89.IS_DEL = 0
      WHERE L2.OBJ_TYPE_ID = 2 AND L2.PARENT_ID IS NULL AND L2.DATE_DEL IS NULL
      INTO VAL
    DO BEGIN
      V$FLAG = 1;
      SUSPEND;
    END
  END

--  ELSE IF (I$SECTION = 18) THEN
--  BEGIN
--    SECTION_NO = '28.';
--    TITLE = 'Общая численность детей, посещающих ДОО в режиме кратковременного пребывания.';
--    CONDITION = 'Общая численность детей, посещающих ДОО в режиме кратковременного пребывания, в разрезе возрастных категорий.';
--    HELPER = 'Передается общая численность детей, посещающих ДОО в режиме кратковременного пребывания вне зависимости от режима работы группы.';
--    VAL = 0;
--    V$FLAG = 1;
--    SUSPEND;
--  END

  ELSE IF (I$SECTION = 19) THEN
  BEGIN
    SECTION_NO = '29.';
    TITLE = 'Прогнозируемое уменьшение контингента в связи с переходом в школу.';
    CONDITION = 'Общая численность детей, зачисленных ДОО, которые планируют уйти из ДОО по окончании текущего учебного года в связи с зачислением в 1 класс.';
    HELPER = 'Передается общая численность детей, зачисленных ДОО, которые планируют уйти из ДОО по окончании текущего учебного года в связи с зачислением в 1 класс.';
    FOR
      SELECT COUNT(1) FROM LINKS L2
        JOIN LINKS L7  ON L7.PARENT_ID = L2.OBJ_ID  AND L7.OBJ_TYPE_ID = 7   AND L7.DATE_DEL IS NULL
        JOIN LINKS L8  ON L8.PARENT_ID = L7.OBJ_ID  AND L8.OBJ_TYPE_ID = 8   AND L8.DATE_DEL IS NULL
        -- этап обучения
        JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0 AND V49.LISTVAL_ID IN (36, 3262)
        JOIN LINKS L9  ON L9.PARENT_ID = L8.OBJ_ID  AND L9.OBJ_TYPE_ID = 9   AND L9.DATE_DEL IS NULL
        JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        JOIN VALD V89 ON V89.OBJ_ID = L10.OBJ_ID AND V89.PARAM_ID = 89 AND V89.IS_DEL = 0
      WHERE L2.OBJ_TYPE_ID = 2 AND L2.PARENT_ID IS NULL AND L2.DATE_DEL IS NULL
        AND (((CURRENT_DATE < :V$DTS) AND (DATEDIFF(MONTH, V89.VAL, :V$DTS) > 77)) OR ((CURRENT_DATE >= :V$DTS) AND (DATEDIFF(MONTH, V89.VAL, :V$DTSN) > 77)))
      INTO VAL
    DO BEGIN
      V$FLAG = 1;
      ONE_STRING = 1;
      SUSPEND;
    END
  END

--  ELSE IF (I$SECTION = 20) THEN
--  BEGIN
--    SECTION_NO = '29.1';
--    TITLE = 'Прогнозируемое уменьшение контингента воспитанников в связи с переходом в другую ДОО.';
--    CONDITION = 'Прогнозируемое уменьшение контингента воспитанников в связи с переходом в другую ДОО.';
--    HELPER = 'Передается общая численность детей, зачисленных в текущую ДОО, желающих сменить данную ДОО на другую, получивших направление в другую ДОО, но еще не отчисленных из данной ДОО. Детей показывать в ДОО, которую они посещают в текущий момент. Дата расчета возраста ребенка: на текущую дату.';
--    VAL = 0;
--    V$FLAG = 1;
--    SUSPEND;
--  END

  ELSE IF (I$SECTION = 21) THEN
  BEGIN
    SECTION_NO = '30.';
    TITLE = 'Численность детей-инвалидов, не имеющих ограниченные возможности здоровья.';
    CONDITION = 'Общая численность детей-инвалидов, не имеющих ограниченные возможности здоровья, в разрезе возрастных категорий.';
    HELPER = 'Передается численность детей-инвалидов, зачисленных в ДОО, не имеющих ограниченных возможностей здоровья. Дата расчета возраста ребенка: на текущую дату.';
    FOR
      SELECT DATEDIFF(MONTH, V89.VAL, CURRENT_DATE) FROM LINKS L2
        JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
        -- вид группы
        JOIN VALL V1549 ON V1549.OBJ_ID = L9.OBJ_ID AND V1549.PARAM_ID = 1549 AND V1549.IS_DEL = 0 AND V1549.LISTVAL_ID = 3266
        -- направленность
        JOIN VALL V1655 ON V1655.OBJ_ID = L9.OBJ_ID AND V1655.PARAM_ID = 1655 AND V1655.IS_DEL = 0 AND V1655.LISTVAL_ID = 3395
        JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        JOIN VALD V89 ON V89.OBJ_ID = L10.OBJ_ID AND V89.PARAM_ID = 89 AND V89.IS_DEL = 0
        -- группа здоровья
        JOIN VALL V208 ON V208.OBJ_ID = L10.OBJ_ID AND V208.PARAM_ID = 208 AND V208.IS_DEL = 0 AND V208.LISTVAL_ID = 499
      WHERE L2.OBJ_TYPE_ID = 2 AND L2.PARENT_ID IS NULL AND L2.DATE_DEL IS NULL
      INTO VAL
    DO BEGIN
      V$FLAG = 1;
      SUSPEND;
    END
  END

  ELSE IF (I$SECTION = 22) THEN
  BEGIN
    SECTION_NO = '30.1';
    TITLE = 'Численность детей-инвалидов, имеющих ограниченные возможности здоровья.';
    CONDITION = 'Общая численность детей-инвалидов, имеющих ограниченные возможности здоровья, в разрезе возрастных категорий.';
    HELPER = 'Передается численность детей-инвалидов, зачисленных в ДОО, имеющих ограниченных возможностей здоровья, посещающих группы любой направленности. Дата расчета возраста ребенка: на текущую дату.';
    FOR
      SELECT DATEDIFF(MONTH, V89.VAL, CURRENT_DATE) FROM LINKS L2
        JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
        JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        JOIN VALD V89 ON V89.OBJ_ID = L10.OBJ_ID AND V89.PARAM_ID = 89 AND V89.IS_DEL = 0
        -- ОВЗ = ДА или конкретная категория
        JOIN VALL V207 ON V207.OBJ_ID = L10.OBJ_ID AND V207.PARAM_ID = 207 AND V207.IS_DEL = 0 AND (V207.LISTVAL_ID = 4 OR V207.LISTVAL_ID NOT IN (5, 13289))
        -- группа здоровья
        JOIN VALL V208 ON V208.OBJ_ID = L10.OBJ_ID AND V208.PARAM_ID = 208 AND V208.IS_DEL = 0 AND V208.LISTVAL_ID = 499
      WHERE L2.OBJ_TYPE_ID = 2 AND L2.PARENT_ID IS NULL AND L2.DATE_DEL IS NULL
      INTO VAL
    DO BEGIN
      V$FLAG = 1;
      SUSPEND;
    END
  END

  ELSE IF (I$SECTION = 23) THEN
  BEGIN
    SECTION_NO = '30.2';
    TITLE = 'Численность детей, не имеющих инвалидности, но имеющих ограниченные возможности здоровья.';
    CONDITION = 'Общая численность детей, не имеющих инвалидности, но имеющих ограниченные возможности здоровья, в разрезе возрастных категорий.';
    HELPER = 'Передается численность, зачисленных в ДОО, не имеющих инвалидности, но имеющих ограниченных возможностей здоровья, посещающих группы любой направленности. Дата расчета возраста ребенка: на текущую дату.';
    FOR
      SELECT DATEDIFF(MONTH, V89.VAL, CURRENT_DATE) FROM LINKS L2
        JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
        JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        JOIN VALD V89 ON V89.OBJ_ID = L10.OBJ_ID AND V89.PARAM_ID = 89 AND V89.IS_DEL = 0
        -- ОВЗ = НЕТ
        JOIN VALL V207 ON V207.OBJ_ID = L10.OBJ_ID AND V207.PARAM_ID = 207 AND V207.IS_DEL = 0 AND V207.LISTVAL_ID IN (5, 13289)
        -- группа здоровья
        JOIN VALL V208 ON V208.OBJ_ID = L10.OBJ_ID AND V208.PARAM_ID = 208 AND V208.IS_DEL = 0 AND V208.LISTVAL_ID <> 499
      WHERE L2.OBJ_TYPE_ID = 2 AND L2.PARENT_ID IS NULL AND L2.DATE_DEL IS NULL
      INTO VAL
    DO BEGIN
      V$FLAG = 1;
      SUSPEND;
    END
  END

  ELSE IF (I$SECTION = 24) THEN
  BEGIN
    SECTION_NO = '32.';
    TITLE = 'Численность детей, получивших путевки в ДОО.';
    CONDITION = 'Общая численность детей, получивших направления в ДОО и зачисленных в ДОО в текущем календарном году.';
    HELPER = 'Передается численность детей, получивших направления в ДОО и зачисленных в ДОО в текущем календарном году.';
    FOR
      SELECT COUNT(1) FROM LINKS L2
        JOIN LINKS L7  ON L7.PARENT_ID = L2.OBJ_ID  AND L7.OBJ_TYPE_ID = 7   AND L7.DATE_DEL IS NULL
        JOIN LINKS L8  ON L8.PARENT_ID = L7.OBJ_ID  AND L8.OBJ_TYPE_ID = 8   AND L8.DATE_DEL IS NULL
        JOIN LINKS L9  ON L9.PARENT_ID = L8.OBJ_ID  AND L9.OBJ_TYPE_ID = 9   AND L9.DATE_DEL IS NULL
        JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        JOIN LINKS L76 ON L76.PARENT_ID = L10.OBJ_ID AND L76.OBJ_TYPE_ID = 76 AND L76.DATE_DEL IS NULL
        JOIN VALL V432 ON V432.OBJ_ID = L76.OBJ_ID AND V432.PARAM_ID = 432 AND V432.IS_DEL = 0 AND V432.LISTVAL_ID = 3276 --Принят(а)
        JOIN VALD V433 ON V433.OBJ_ID = L76.OBJ_ID AND V433.PARAM_ID = 433 AND V432.IS_DEL = 0
          AND V433.VAL >= '01.01.' || EXTRACT(YEAR FROM CURRENT_DATE) --Дата приёма = в текущем календарном году
      WHERE L2.OBJ_TYPE_ID = 2 AND L2.PARENT_ID IS NULL AND L2.DATE_DEL IS NULL
      INTO VAL
    DO BEGIN
      V$FLAG = 1;
      ONE_STRING = 1;
      SUSPEND;
    END
  END

  IF (V$FLAG = 0) THEN
    SUSPEND;

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE REPORT_FSPEO_HTML RETURNS (
    HTML VARCHAR(8000))
AS
declare variable V$G1 integer;
declare variable V$G2 integer;
declare variable V$G3 integer;
declare variable V$G4 integer;
declare variable V$G5 integer;
declare variable V$G6 integer;
declare variable V$G7 integer;
declare variable V$G8 integer;
declare variable V$G9 integer;
declare variable V$G10 integer;
declare variable V$G11 integer;
declare variable V$G12 integer;
declare variable V$G13 integer;
declare variable V$G14 integer;
declare variable V$G15 integer;
declare variable V$G16 integer;
declare variable V$ITER integer;
declare variable V$SECTION_NO varchar(10);
declare variable V$TITLE varchar(1000);
declare variable V$VAL integer;
declare variable V$CONDITION varchar(1000);
declare variable V$HELPER varchar(1000);
declare variable V$ONE_STRING smallint;
begin
  HTML =
  '
  <html lang="ru">
  <head>
    <meta charset="utf-8" />
    <title>Расчет показателей, передаваемых региональной системой в Федеральную систему показателей Электронной очереди версия 4.0.</title>
  </head>
  <body>
    <table style="width:100%; border-collapse: collapse;">
      <tr>
        <th colspan="5"><h2>Расчет показателей, передаваемых региональной системой в Федеральную систему показателей Электронной очереди версия 4.0.</h2></th>
      </tr>
      <tr>
        <th style="border: 1px solid black;">Наименование</th>
        <th style="border: 1px solid black;">Условия вывода</th> 
        <th style="border: 1px solid black;">Возрастные категории</th>
        <th style="border: 1px solid black;">Значения</th>
        <th style="border: 1px solid black;">Условия расчета</th>
      </tr>';
  SUSPEND;
  V$ITER = 0;
  WHILE (V$ITER < 25) DO
  BEGIN
    IF (V$ITER NOT IN (3, 15, 18, 20)) THEN
    BEGIN
      V$G1=0;
      V$G2=0;
      V$G3=0;
      V$G4=0;
      V$G5=0;
      V$G6=0;
      V$G7=0;
      V$G8=0;
      V$G9=0;
      V$G10=0;
      V$G11=0;
      V$G12=0;
      V$G13=0;
      V$G14=0;
      V$G15=0;
      V$G16=0;
      FOR
        SELECT SECTION_NO, TITLE, VAL, CONDITION, HELPER, ONE_STRING FROM REPORT_FSPEO_DATA(:V$ITER)
        INTO V$SECTION_NO, V$TITLE, V$VAL, V$CONDITION, V$HELPER, V$ONE_STRING
      DO BEGIN
        -- от 2 месяцев до 6 месяцев;
        IF ((V$VAL >= 2) AND (V$VAL < 6)) THEN
          V$G1 = V$G1 + 1;
        -- от 6 месяцев до 1 года;
        ELSE IF ((V$VAL >= 6) AND (V$VAL < 12)) THEN
          V$G2 = V$G2 + 1;
        -- от 1 года до 1,5 года;
        ELSE IF ((V$VAL >= 12) AND (V$VAL < 18)) THEN
          V$G3 = V$G3 + 1;
        -- от 1,5 до 2 лет;
        ELSE IF ((V$VAL >= 18) AND (V$VAL < 24)) THEN
          V$G4 = V$G4 + 1;
        -- от 2 до 2,5 лет;
        ELSE IF ((V$VAL >= 24) AND (V$VAL < 30)) THEN
          V$G5 = V$G5 + 1;
        -- от 2,5 до 3 лет;
        ELSE IF ((V$VAL >= 30) AND (V$VAL < 36)) THEN
          V$G6 = V$G6 + 1;
        -- от 3 до 3,5 лет;
        ELSE IF ((V$VAL >= 36) AND (V$VAL < 42)) THEN
          V$G7 = V$G7 + 1;
        -- от 3,5 до 4 лет;
        ELSE IF ((V$VAL >= 42) AND (V$VAL < 48)) THEN
          V$G8 = V$G8 + 1;
        -- от 4 до 4,5 лет;
        ELSE IF ((V$VAL >= 48) AND (V$VAL < 54)) THEN
          V$G9 = V$G9 + 1;
        -- от 4,5 до 5 лет;
        ELSE IF ((V$VAL >= 54) AND (V$VAL < 60)) THEN
          V$G10 = V$G10 + 1;
        -- от 5 до 5,5 лет;
        ELSE IF ((V$VAL >= 60) AND (V$VAL < 66)) THEN
          V$G11 = V$G11 + 1;
        -- от 5,5 до 6 лет;
        ELSE IF ((V$VAL >= 66) AND (V$VAL < 72)) THEN
          V$G12 = V$G12 + 1;
        -- от 6 до 6,5 лет;
        ELSE IF ((V$VAL >= 72) AND (V$VAL < 78)) THEN
          V$G13 = V$G13 + 1;
        -- от 6,5 до 7 лет;
        ELSE IF ((V$VAL >= 78) AND (V$VAL < 84)) THEN
          V$G14 = V$G14 + 1;
        -- от 7 до 7,5 лет;
        ELSE IF ((V$VAL >= 84) AND (V$VAL < 90)) THEN
          V$G15 = V$G15 + 1;
        -- от 7,5 лет и старше.
        ELSE IF (V$VAL >= 90) THEN
          V$G16 = V$G16 + 1;
      END
  
      IF (V$ONE_STRING = 1) THEN
      BEGIN
        HTML =
        '
        <tr>
          <td style="border: 1px solid black;">' || V$SECTION_NO || ' ' || V$TITLE || '</td>
          <td style="border: 1px solid black;">' || V$CONDITION || '</td>
          <td style="border: 1px solid black;"></td>
          <td style="border: 1px solid black; text-align: center;">' || CAST(V$VAL as varchar(10)) || '</td>
          <td style="border: 1px solid black;">' || V$HELPER || '</td>
        </tr>';
        SUSPEND;
      END
      ELSE BEGIN
        HTML =
        '
        <tr>
          <td style="border-top: 1px solid black; border-left: 1px solid black; border-right: 1px solid black;">' || V$SECTION_NO || ' ' || V$TITLE || '</td>
          <td style="border-top: 1px solid black; border-left: 1px solid black; border-right: 1px solid black;">' || V$CONDITION || '</td>
          <td style="border-top: 1px solid black; border-left: 1px solid black; border-right: 1px solid black;">от 2 месяцев до 6 месяцев</td>
          <td style="border-top: 1px solid black; border-left: 1px solid black; border-right: 1px solid black; text-align: center;">' || CAST(V$G1 as varchar(10)) || '</td>
          <td style="border-top: 1px solid black; border-left: 1px solid black; border-right: 1px solid black;">' || V$HELPER || '</td>
        </tr>
        <tr>
          <td style="border-left: 1px solid black; border-right: 1px solid black;"></td>
          <td style="border-left: 1px solid black; border-right: 1px solid black;"></td>
          <td style="border: 1px solid black;">от 6 месяцев до 1 года</td>
          <td style="border: 1px solid black; text-align: center;">' || CAST(V$G2 as varchar(10)) || '</td>
          <td style="border-left: 1px solid black; border-right: 1px solid black;"></td>
        </tr>
        <tr>
          <td style="border-left: 1px solid black; border-right: 1px solid black;"></td>
          <td style="border-left: 1px solid black; border-right: 1px solid black;"></td>
          <td style="border: 1px solid black;">от 1 года до 1,5 года</td>
          <td style="border: 1px solid black; text-align: center;">' || CAST(V$G3 as varchar(10)) || '</td>
          <td style="border-left: 1px solid black; border-right: 1px solid black;"></td>
        </tr>
        <tr>
          <td style="border-left: 1px solid black; border-right: 1px solid black;"></td>
          <td style="border-left: 1px solid black; border-right: 1px solid black;"></td>
          <td style="border: 1px solid black;">от 1,5 до 2 лет</td>
          <td style="border: 1px solid black; text-align: center;">' || CAST(V$G4 as varchar(10)) || '</td>
          <td style="border-left: 1px solid black; border-right: 1px solid black;"></td>
        </tr>
        <tr>
          <td style="border-left: 1px solid black; border-right: 1px solid black;"></td>
          <td style="border-left: 1px solid black; border-right: 1px solid black;"></td>
          <td style="border: 1px solid black;">от 2 до 2,5 лет</td>
          <td style="border: 1px solid black; text-align: center;">' || CAST(V$G5 as varchar(10)) || '</td>
          <td style="border-left: 1px solid black; border-right: 1px solid black;"></td>
        </tr>
        <tr>
          <td style="border-left: 1px solid black; border-right: 1px solid black;"></td>
          <td style="border-left: 1px solid black; border-right: 1px solid black;"></td>
          <td style="border: 1px solid black;">от 2,5 до 3 лет</td>
          <td style="border: 1px solid black; text-align: center;">' || CAST(V$G6 as varchar(10)) || '</td>
          <td style="border-left: 1px solid black; border-right: 1px solid black;"></td>
        </tr>
        <tr>
          <td style="border-left: 1px solid black; border-right: 1px solid black;"></td>
          <td style="border-left: 1px solid black; border-right: 1px solid black;"></td>
          <td style="border: 1px solid black;">от 3 до 3,5 лет</td>
          <td style="border: 1px solid black; text-align: center;">' || CAST(V$G7 as varchar(10)) || '</td>
          <td style="border-left: 1px solid black; border-right: 1px solid black;"></td>
        </tr>
        <tr>
          <td style="border-left: 1px solid black; border-right: 1px solid black;"></td>
          <td style="border-left: 1px solid black; border-right: 1px solid black;"></td>
          <td style="border: 1px solid black;">от 3,5 до 4 лет</td>
          <td style="border: 1px solid black; text-align: center;">' || CAST(V$G8 as varchar(10)) || '</td>
          <td style="border-left: 1px solid black; border-right: 1px solid black;"></td>
        </tr>
        <tr>
          <td style="border-left: 1px solid black; border-right: 1px solid black;"></td>
          <td style="border-left: 1px solid black; border-right: 1px solid black;"></td>
          <td style="border: 1px solid black;">от 4 до 4,5 лет</td>
          <td style="border: 1px solid black; text-align: center;">' || CAST(V$G9 as varchar(10)) || '</td>
          <td style="border-left: 1px solid black; border-right: 1px solid black;"></td>
        </tr>
        <tr>
          <td style="border-left: 1px solid black; border-right: 1px solid black;"></td>
          <td style="border-left: 1px solid black; border-right: 1px solid black;"></td>
          <td style="border: 1px solid black;">от 4,5 до 5 лет</td>
          <td style="border: 1px solid black; text-align: center;">' || CAST(V$G10 as varchar(10)) || '</td>
          <td style="border-left: 1px solid black; border-right: 1px solid black;"></td>
        </tr>
        <tr>
          <td style="border-left: 1px solid black; border-right: 1px solid black;"></td>
          <td style="border-left: 1px solid black; border-right: 1px solid black;"></td>
          <td style="border: 1px solid black;">от 5 до 5,5 лет</td>
          <td style="border: 1px solid black; text-align: center;">' || CAST(V$G11 as varchar(10)) || '</td>
          <td style="border-left: 1px solid black; border-right: 1px solid black;"></td>
        </tr>
        <tr>
          <td style="border-left: 1px solid black; border-right: 1px solid black;"></td>
          <td style="border-left: 1px solid black; border-right: 1px solid black;"></td>
          <td style="border: 1px solid black;">от 5,5 до 6 лет</td>
          <td style="border: 1px solid black; text-align: center;">' || CAST(V$G12 as varchar(10)) || '</td>
          <td style="border-left: 1px solid black; border-right: 1px solid black;"></td>
        </tr>
        <tr>
          <td style="border-left: 1px solid black; border-right: 1px solid black;"></td>
          <td style="border-left: 1px solid black; border-right: 1px solid black;"></td>
          <td style="border: 1px solid black;">от 6 до 6,5 лет</td>
          <td style="border: 1px solid black; text-align: center;">' || CAST(V$G13 as varchar(10)) || '</td>
          <td style="border-left: 1px solid black; border-right: 1px solid black;"></td>
        </tr>
        <tr>
          <td style="border-left: 1px solid black; border-right: 1px solid black;"></td>
          <td style="border-left: 1px solid black; border-right: 1px solid black;"></td>
          <td style="border: 1px solid black;">от 6,5 до 7 лет</td>
          <td style="border: 1px solid black; text-align: center;">' || CAST(V$G14 as varchar(10)) || '</td>
          <td style="border-left: 1px solid black; border-right: 1px solid black;"></td>
        </tr>
        <tr>
          <td style="border-left: 1px solid black; border-right: 1px solid black;"></td>
          <td style="border-left: 1px solid black; border-right: 1px solid black;"></td>
          <td style="border: 1px solid black;">от 7 до 7,5 лет</td>
          <td style="border: 1px solid black; text-align: center;">' || CAST(V$G15 as varchar(10)) || '</td>
          <td style="border-left: 1px solid black; border-right: 1px solid black;"></td>
        </tr>
        <tr>
          <td style="border-bottom: 1px solid black; border-left: 1px solid black; border-right: 1px solid black;"></td>
          <td style="border-bottom: 1px solid black; border-left: 1px solid black; border-right: 1px solid black;"></td>
          <td style="border-bottom: 1px solid black; border: 1px solid black;">от 7,5 лет и старше</td>
          <td style="border-bottom: 1px solid black; border: 1px solid black; text-align: center;">' || CAST(V$G16 as varchar(10)) || '</td>
          <td style="border-bottom: 1px solid black; border-left: 1px solid black; border-right: 1px solid black;"></td>
        </tr>';
        SUSPEND;
      END
    END
    V$ITER = V$ITER + 1;
  END

  HTML =
  '
      </table>
  </body>
  </html>';
  SUSPEND;
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE REPORT_FSPEO_JSON RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
declare variable V$G1 integer;
declare variable V$G2 integer;
declare variable V$G3 integer;
declare variable V$G4 integer;
declare variable V$G5 integer;
declare variable V$G6 integer;
declare variable V$G7 integer;
declare variable V$G8 integer;
declare variable V$G9 integer;
declare variable V$G10 integer;
declare variable V$G11 integer;
declare variable V$G12 integer;
declare variable V$G13 integer;
declare variable V$G14 integer;
declare variable V$G15 integer;
declare variable V$G16 integer;
declare variable V$ITER integer;
declare variable V$SECTION_NO varchar(10);
declare variable V$TITLE varchar(1000);
declare variable V$VAL integer;
declare variable V$CONDITION varchar(1000);
declare variable V$HELPER varchar(1000);
declare variable V$ONE_STRING smallint;
begin
  TAG_NAME = 'data';
  VAL = NULL;
  SUSPEND;

  TAG_NAME = 'data:list::json&colon;array';
  VAL = 1;
  SUSPEND;

  V$ITER = 0;
  WHILE (V$ITER < 25) DO
  BEGIN
    IF (V$ITER NOT IN (3, 15, 18, 20)) THEN
    BEGIN
      V$G1=0;
      V$G2=0;
      V$G3=0;
      V$G4=0;
      V$G5=0;
      V$G6=0;
      V$G7=0;
      V$G8=0;
      V$G9=0;
      V$G10=0;
      V$G11=0;
      V$G12=0;
      V$G13=0;
      V$G14=0;
      V$G15=0;
      V$G16=0;
      FOR
        SELECT SECTION_NO, TITLE, VAL, CONDITION, HELPER, ONE_STRING FROM REPORT_FSPEO_DATA(:V$ITER)
        INTO V$SECTION_NO, V$TITLE, V$VAL, V$CONDITION, V$HELPER, V$ONE_STRING
      DO BEGIN
        -- от 2 месяцев до 6 месяцев;
        IF ((V$VAL >= 2) AND (V$VAL < 6)) THEN
          V$G1 = V$G1 + 1;
        -- от 6 месяцев до 1 года;
        ELSE IF ((V$VAL >= 6) AND (V$VAL < 12)) THEN
          V$G2 = V$G2 + 1;
        -- от 1 года до 1,5 года;
        ELSE IF ((V$VAL >= 12) AND (V$VAL < 18)) THEN
          V$G3 = V$G3 + 1;
        -- от 1,5 до 2 лет;
        ELSE IF ((V$VAL >= 18) AND (V$VAL < 24)) THEN
          V$G4 = V$G4 + 1;
        -- от 2 до 2,5 лет;
        ELSE IF ((V$VAL >= 24) AND (V$VAL < 30)) THEN
          V$G5 = V$G5 + 1;
        -- от 2,5 до 3 лет;
        ELSE IF ((V$VAL >= 30) AND (V$VAL < 36)) THEN
          V$G6 = V$G6 + 1;
        -- от 3 до 3,5 лет;
        ELSE IF ((V$VAL >= 36) AND (V$VAL < 42)) THEN
          V$G7 = V$G7 + 1;
        -- от 3,5 до 4 лет;
        ELSE IF ((V$VAL >= 42) AND (V$VAL < 48)) THEN
          V$G8 = V$G8 + 1;
        -- от 4 до 4,5 лет;
        ELSE IF ((V$VAL >= 48) AND (V$VAL < 54)) THEN
          V$G9 = V$G9 + 1;
        -- от 4,5 до 5 лет;
        ELSE IF ((V$VAL >= 54) AND (V$VAL < 60)) THEN
          V$G10 = V$G10 + 1;
        -- от 5 до 5,5 лет;
        ELSE IF ((V$VAL >= 60) AND (V$VAL < 66)) THEN
          V$G11 = V$G11 + 1;
        -- от 5,5 до 6 лет;
        ELSE IF ((V$VAL >= 66) AND (V$VAL < 72)) THEN
          V$G12 = V$G12 + 1;
        -- от 6 до 6,5 лет;
        ELSE IF ((V$VAL >= 72) AND (V$VAL < 78)) THEN
          V$G13 = V$G13 + 1;
        -- от 6,5 до 7 лет;
        ELSE IF ((V$VAL >= 78) AND (V$VAL < 84)) THEN
          V$G14 = V$G14 + 1;
        -- от 7 до 7,5 лет;
        ELSE IF ((V$VAL >= 84) AND (V$VAL < 90)) THEN
          V$G15 = V$G15 + 1;
        -- от 7,5 лет и старше.
        ELSE IF (V$VAL >= 90) THEN
          V$G16 = V$G16 + 1;
      END
  
      IF (V$ONE_STRING = 1) THEN
      BEGIN
        TAG_NAME = 'data:list:l';
        VAL = NULL;
        SUSPEND;
  
        TAG_NAME = 'data:list:l:title';
        VAL = V$SECTION_NO || ' ' || V$TITLE;
        SUSPEND;
  
        TAG_NAME = 'data:list:l:value';
        VAL = CAST(V$VAL as varchar(10));
        SUSPEND;
  
        TAG_NAME = 'data:list:l:id';
        VAL = 'data[' || V$SECTION_NO || ' ' || V$CONDITION || ']';
        SUSPEND;
  
        TAG_NAME = 'data:list:l:helper';
        VAL = V$HELPER;
        SUSPEND;
      END
      ELSE BEGIN
        TAG_NAME = 'data:list:l';
        VAL = NULL;
        SUSPEND;
  
        TAG_NAME = 'data:list:l:title';
        VAL = V$SECTION_NO || ' ' || V$TITLE;
        SUSPEND;
  
        TAG_NAME = 'data:list:l:fields::json&colon;array';
        VAL = 1;
        SUSPEND;
  
        TAG_NAME = 'data:list:l:fields:field';
        VAL = NULL;
        SUSPEND;
  
        TAG_NAME = 'data:list:l:fields:field:name';
        VAL = 'от 2 месяцев до 6 месяцев';
        SUSPEND;
  
        TAG_NAME = 'data:list:l:fields:field:value';
        VAL = CAST(V$G1 as varchar(10));
        SUSPEND;
  
        TAG_NAME = 'data:list:l:fields:field:id';
        VAL = 'data[' || V$SECTION_NO || ' ' || V$CONDITION || '][от 2 месяцев до 6 месяцев]';
        SUSPEND;
  
        TAG_NAME = 'data:list:l:fields:field:block';
        VAL = 'data[' || V$SECTION_NO || ' ' || V$CONDITION || '][от 2 месяцев до 6 месяцев]';
        SUSPEND;
  
        TAG_NAME = 'data:list:l:fields:field';
        VAL = NULL;
        SUSPEND;
  
        TAG_NAME = 'data:list:l:fields:field:name';
        VAL = 'от 6 месяцев до 1 года';
        SUSPEND;
  
        TAG_NAME = 'data:list:l:fields:field:value';
        VAL = CAST(V$G2 as varchar(10));
        SUSPEND;
  
        TAG_NAME = 'data:list:l:fields:field:id';
        VAL = 'data[' || V$SECTION_NO || ' ' || V$CONDITION || '][от 6 месяцев до 1 года]';
        SUSPEND;
  
        TAG_NAME = 'data:list:l:fields:field:block';
        VAL = 'data[' || V$SECTION_NO || ' ' || V$CONDITION || '][от 6 месяцев до 1 года]';
        SUSPEND;
  
        TAG_NAME = 'data:list:l:fields:field';
        VAL = NULL;
        SUSPEND;
  
        TAG_NAME = 'data:list:l:fields:field:name';
        VAL = 'от 1 года до 1,5 года';
        SUSPEND;
  
        TAG_NAME = 'data:list:l:fields:field:value';
        VAL = CAST(V$G3 as varchar(10));
        SUSPEND;
  
        TAG_NAME = 'data:list:l:fields:field:id';
        VAL = 'data[' || V$SECTION_NO || ' ' || V$CONDITION || '][от 1 года до 1,5 года]';
        SUSPEND;
  
        TAG_NAME = 'data:list:l:fields:field:block';
        VAL = 'data[' || V$SECTION_NO || ' ' || V$CONDITION || '][от 1 года до 1,5 года]';
        SUSPEND;
  
        TAG_NAME = 'data:list:l:fields:field';
        VAL = NULL;
        SUSPEND;
  
        TAG_NAME = 'data:list:l:fields:field:name';
        VAL = 'от 1,5 до 2 лет';
        SUSPEND;
  
        TAG_NAME = 'data:list:l:fields:field:value';
        VAL = CAST(V$G4 as varchar(10));
        SUSPEND;
  
        TAG_NAME = 'data:list:l:fields:field:id';
        VAL = 'data[' || V$SECTION_NO || ' ' || V$CONDITION || '][от 1,5 до 2 лет]';
        SUSPEND;
  
        TAG_NAME = 'data:list:l:fields:field:block';
        VAL = 'data[' || V$SECTION_NO || ' ' || V$CONDITION || '][от 1,5 до 2 лет]';
        SUSPEND;
  
        TAG_NAME = 'data:list:l:fields:field';
        VAL = NULL;
        SUSPEND;
  
        TAG_NAME = 'data:list:l:fields:field:name';
        VAL = 'от 2 года до 2,5 года';
        SUSPEND;
  
        TAG_NAME = 'data:list:l:fields:field:value';
        VAL = CAST(V$G5 as varchar(10));
        SUSPEND;
  
        TAG_NAME = 'data:list:l:fields:field:id';
        VAL = 'data[' || V$SECTION_NO || ' ' || V$CONDITION || '][от 2 до 2,5 года]';
        SUSPEND;
  
        TAG_NAME = 'data:list:l:fields:field:block';
        VAL = 'data[' || V$SECTION_NO || ' ' || V$CONDITION || '][от 2 до 2,5 года]';
        SUSPEND;
  
        TAG_NAME = 'data:list:l:fields:field';
        VAL = NULL;
        SUSPEND;
  
        TAG_NAME = 'data:list:l:fields:field:name';
        VAL = 'от 2,5 до 3 лет';
        SUSPEND;
  
        TAG_NAME = 'data:list:l:fields:field:value';
        VAL = CAST(V$G6 as varchar(10));
        SUSPEND;
  
        TAG_NAME = 'data:list:l:fields:field:id';
        VAL = 'data[' || V$SECTION_NO || ' ' || V$CONDITION || '][от 2,5 до 3 лет]';
        SUSPEND;
  
        TAG_NAME = 'data:list:l:fields:field:block';
        VAL = 'data[' || V$SECTION_NO || ' ' || V$CONDITION || '][от 2,5 до 3 лет]';
        SUSPEND;
  
        TAG_NAME = 'data:list:l:fields:field';
        VAL = NULL;
        SUSPEND;
  
        TAG_NAME = 'data:list:l:fields:field:name';
        VAL = 'от 3 года до 3,5 года';
        SUSPEND;
  
        TAG_NAME = 'data:list:l:fields:field:value';
        VAL = CAST(V$G7 as varchar(10));
        SUSPEND;
  
        TAG_NAME = 'data:list:l:fields:field:id';
        VAL = 'data[' || V$SECTION_NO || ' ' || V$CONDITION || '][от 3 до 3,5 года]';
        SUSPEND;
  
        TAG_NAME = 'data:list:l:fields:field:block';
        VAL = 'data[' || V$SECTION_NO || ' ' || V$CONDITION || '][от 3 до 3,5 года]';
        SUSPEND;
  
        TAG_NAME = 'data:list:l:fields:field';
        VAL = NULL;
        SUSPEND;
  
        TAG_NAME = 'data:list:l:fields:field:name';
        VAL = 'от 3,5 до 4 лет';
        SUSPEND;
  
        TAG_NAME = 'data:list:l:fields:field:value';
        VAL = CAST(V$G8 as varchar(10));
        SUSPEND;
  
        TAG_NAME = 'data:list:l:fields:field:id';
        VAL = 'data[' || V$SECTION_NO || ' ' || V$CONDITION || '][от 3,5 до 4 лет]';
        SUSPEND;
  
        TAG_NAME = 'data:list:l:fields:field:block';
        VAL = 'data[' || V$SECTION_NO || ' ' || V$CONDITION || '][от 3,5 до 4 лет]';
        SUSPEND;
  
        TAG_NAME = 'data:list:l:fields:field';
        VAL = NULL;
        SUSPEND;
  
        TAG_NAME = 'data:list:l:fields:field:name';
        VAL = 'от 4 года до 4,5 года';
        SUSPEND;
  
        TAG_NAME = 'data:list:l:fields:field:value';
        VAL = CAST(V$G9 as varchar(10));
        SUSPEND;
  
        TAG_NAME = 'data:list:l:fields:field:id';
        VAL = 'data[' || V$SECTION_NO || ' ' || V$CONDITION || '][от 4 до 4,5 года]';
        SUSPEND;
  
        TAG_NAME = 'data:list:l:fields:field:block';
        VAL = 'data[' || V$SECTION_NO || ' ' || V$CONDITION || '][от 4 до 4,5 года]';
        SUSPEND;
  
        TAG_NAME = 'data:list:l:fields:field';
        VAL = NULL;
        SUSPEND;
  
        TAG_NAME = 'data:list:l:fields:field:name';
        VAL = 'от 4,5 до 5 лет';
        SUSPEND;
  
        TAG_NAME = 'data:list:l:fields:field:value';
        VAL = CAST(V$G10 as varchar(10));
        SUSPEND;
  
        TAG_NAME = 'data:list:l:fields:field:id';
        VAL = 'data[' || V$SECTION_NO || ' ' || V$CONDITION || '][от 4,5 до 5 лет]';
        SUSPEND;
  
        TAG_NAME = 'data:list:l:fields:field:block';
        VAL = 'data[' || V$SECTION_NO || ' ' || V$CONDITION || '][от 4,5 до 5 лет]';
        SUSPEND;
  
        TAG_NAME = 'data:list:l:fields:field';
        VAL = NULL;
        SUSPEND;
  
        TAG_NAME = 'data:list:l:fields:field:name';
        VAL = 'от 5 года до 5,5 года';
        SUSPEND;
  
        TAG_NAME = 'data:list:l:fields:field:value';
        VAL = CAST(V$G11 as varchar(10));
        SUSPEND;
  
        TAG_NAME = 'data:list:l:fields:field:id';
        VAL = 'data[' || V$SECTION_NO || ' ' || V$CONDITION || '][от 5 до 5,5 года]';
        SUSPEND;
  
        TAG_NAME = 'data:list:l:fields:field:block';
        VAL = 'data[' || V$SECTION_NO || ' ' || V$CONDITION || '][от 5 до 5,5 года]';
        SUSPEND;
  
        TAG_NAME = 'data:list:l:fields:field';
        VAL = NULL;
        SUSPEND;
  
        TAG_NAME = 'data:list:l:fields:field:name';
        VAL = 'от 5,5 до 6 лет';
        SUSPEND;
  
        TAG_NAME = 'data:list:l:fields:field:value';
        VAL = CAST(V$G12 as varchar(10));
        SUSPEND;
  
        TAG_NAME = 'data:list:l:fields:field:id';
        VAL = 'data[' || V$SECTION_NO || ' ' || V$CONDITION || '][от 5,5 до 6 лет]';
        SUSPEND;
  
        TAG_NAME = 'data:list:l:fields:field:block';
        VAL = 'data[' || V$SECTION_NO || ' ' || V$CONDITION || '][от 5,5 до 6 лет]';
        SUSPEND;
  
        TAG_NAME = 'data:list:l:fields:field';
        VAL = NULL;
        SUSPEND;
  
        TAG_NAME = 'data:list:l:fields:field:name';
        VAL = 'от 6 года до 6,5 года';
        SUSPEND;
  
        TAG_NAME = 'data:list:l:fields:field:value';
        VAL = CAST(V$G13 as varchar(10));
        SUSPEND;
  
        TAG_NAME = 'data:list:l:fields:field:id';
        VAL = 'data[' || V$SECTION_NO || ' ' || V$CONDITION || '][от 6 до 6,5 года]';
        SUSPEND;
  
        TAG_NAME = 'data:list:l:fields:field:block';
        VAL = 'data[' || V$SECTION_NO || ' ' || V$CONDITION || '][от 6 до 6,5 года]';
        SUSPEND;
  
        TAG_NAME = 'data:list:l:fields:field';
        VAL = NULL;
        SUSPEND;
  
        TAG_NAME = 'data:list:l:fields:field:name';
        VAL = 'от 6,5 до 7 лет';
        SUSPEND;
  
        TAG_NAME = 'data:list:l:fields:field:value';
        VAL = CAST(V$G14 as varchar(10));
        SUSPEND;
  
        TAG_NAME = 'data:list:l:fields:field:id';
        VAL = 'data[' || V$SECTION_NO || ' ' || V$CONDITION || '][от 6,5 до 7 лет]';
        SUSPEND;
  
        TAG_NAME = 'data:list:l:fields:field:block';
        VAL = 'data[' || V$SECTION_NO || ' ' || V$CONDITION || '][от 6,5 до 7 лет]';
        SUSPEND;
  
        TAG_NAME = 'data:list:l:fields:field';
        VAL = NULL;
        SUSPEND;
  
        TAG_NAME = 'data:list:l:fields:field:name';
        VAL = 'от 7 до 7,5 лет';
        SUSPEND;
  
        TAG_NAME = 'data:list:l:fields:field:value';
        VAL = CAST(V$G15 as varchar(10));
        SUSPEND;
  
        TAG_NAME = 'data:list:l:fields:field:id';
        VAL = 'data[' || V$SECTION_NO || ' ' || V$CONDITION || '][от 7 до 7,5 лет]';
        SUSPEND;
  
        TAG_NAME = 'data:list:l:fields:field:block';
        VAL = 'data[' || V$SECTION_NO || ' ' || V$CONDITION || '][от 7 до 7,5 лет]';
        SUSPEND;
  
        TAG_NAME = 'data:list:l:fields:field';
        VAL = NULL;
        SUSPEND;
  
        TAG_NAME = 'data:list:l:fields:field:name';
        VAL = 'от 7,5 лет и старше';
        SUSPEND;
  
        TAG_NAME = 'data:list:l:fields:field:value';
        VAL = CAST(V$G16 as varchar(10));
        SUSPEND;
  
        TAG_NAME = 'data:list:l:fields:field:id';
        VAL = 'data[' || V$SECTION_NO || ' ' || V$CONDITION || '][от 7,5 лет и старше]';
        SUSPEND;
  
        TAG_NAME = 'data:list:l:fields:field:block';
        VAL = 'data[' || V$SECTION_NO || ' ' || V$CONDITION || '][от 7,5 лет и старше]';
        SUSPEND;
  
        TAG_NAME = 'data:list:l:helper';
        VAL = V$HELPER;
        SUSPEND;
      END
    END
    V$ITER = V$ITER + 1;
  END
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE REPORT_GET (
    I$REPORT_ID BIGINT,
    I$LANG_CODE CHAR(2) = 'RU')
RETURNS (
    REPORT_ID BIGINT,
    TYPE_ID BIGINT,
    RES_ID BIGINT,
    REPORT_CAPTION VARCHAR(4000),
    TAG VARCHAR(100),
    TEMPL_ID BIGINT,
    SORT_ORDER SMALLINT,
    IS_DEL SMALLINT,
    IS_REPL SMALLINT)
AS
BEGIN
    IS_REPL = 0;

    REPORT_ID = I$REPORT_ID;
    SELECT TYPE_ID,
           RES_ID,
           TEMPL_ID,
           SORT_ORDER,
           IS_DEL,
           TAG
    FROM REPORTS REP
    WHERE REP.REPORT_ID = :I$REPORT_ID
    INTO   :TYPE_ID,
           :RES_ID,
           :TEMPL_ID,
           :SORT_ORDER,
           :IS_DEL,
           :TAG;
    SELECT VAL
    FROM RES_GET(:RES_ID, :I$LANG_CODE)
    INTO   :REPORT_CAPTION;
    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE REPORT_MOVE (
    I$REPORT_ID BIGINT,
    I$MOVE SMALLINT)
RETURNS (
    SORT_ORDER SMALLINT)
AS
DECLARE VARIABLE REPORT_ID BIGINT = NULL;
BEGIN
   SELECT SORT_ORDER FROM REPORTS WHERE REPORT_ID = :I$REPORT_ID INTO :SORT_ORDER;

   SELECT REPORT_ID FROM REPORTS WHERE SORT_ORDER = (:SORT_ORDER + :I$MOVE) INTO :REPORT_ID;

   IF (REPORT_ID IS NOT NULL) THEN
   BEGIN
      UPDATE REPORTS SET SORT_ORDER = :SORT_ORDER WHERE REPORT_ID = :REPORT_ID;
      UPDATE REPORTS SET SORT_ORDER = (:SORT_ORDER + :I$MOVE) WHERE REPORT_ID = :I$REPORT_ID;
   END
   SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE REPORT_MTR (
    OBJ_ID BIGINT,
    MTR_GROUP_ID BIGINT,
    SUBTYPE SMALLINT = 0)
RETURNS (
    VAL VARCHAR(6000))
AS
declare variable V$OBJ_TYPE bigint;
declare variable V$YEAR_MIN integer;
declare variable V$YEAR_MAX integer;
declare variable V$YEAR_LIM integer;
declare variable V$YEAR integer;
declare variable V$OO_ID bigint;
declare variable V$PREV_ID bigint;
declare variable V$DIST_NAME varchar(400);
declare variable V$OO_NAME varchar(1000);
declare variable V$OE varchar(20);
declare variable V$GROUP_ID bigint;
declare variable V$SUBGROUP_ID bigint;
declare variable N smallint;
declare variable VN integer;
declare variable NC integer;
declare variable NI integer;
begin

  -- SUBTYPE задает вид отчета для ОУ: 0 = по комплексам, 1 = по ТСО

  VAL = '<!DOCTYPE html>';
  VAL = VAL || '<html lang="ru">';
  VAL = VAL || '<head>';
  VAL = VAL || '<meta charset="utf-8" />';

  VAL = VAL || '<style>';
  VAL = VAL || 'html { font-family: Tahoma, Verdana, Arial;';
  VAL = VAL || 'font-size: 10pt; ';
  VAL = VAL || '} ';
  VAL = VAL || '.title1 { font-size: 150%;';
  VAL = VAL || 'padding: 8px;';
  VAL = VAL || 'margin-bottom: 10px;';
  VAL = VAL || 'font-weight: bold;';
  VAL = VAL || 'color: #1B5E20;';
  VAL = VAL || '} ';
  VAL = VAL || '.title2 { font-size: 120%;';
  VAL = VAL || 'padding: 8px;';
  VAL = VAL || 'margin-bottom: 20px;';
  VAL = VAL || 'font-weight: bold;';
  VAL = VAL || 'color: #827717;';
  VAL = VAL || '} ';
  VAL = VAL || '.details {';
  VAL = VAL || 'border: 2px solid #e0e0e0;';
  VAL = VAL || 'border-collapse: collapse;';
  VAL = VAL || '} ';
  VAL = VAL || '.details tr th {';
  VAL = VAL || 'font-weight: normal;';
  VAL = VAL || 'padding: 2px 4px;';
  VAL = VAL || 'background-color: #F9FBE7;';
  VAL = VAL || 'border: 1px solid #e0e0e0;';
  VAL = VAL || '} ';
  VAL = VAL || '.details tr td {';
  VAL = VAL || 'padding: 2px 4px;';
  VAL = VAL || 'border: 1px solid #e0e0e0;';
  VAL = VAL || 'text-align: left;';
  VAL = VAL || '} ';
  VAL = VAL || '.odd td {';
  VAL = VAL || 'background-color: #f7f7f7;';
  VAL = VAL || '} ';
  VAL = VAL || '.totals td {';
  VAL = VAL || 'background-color: #F9FBE7;';
  VAL = VAL || 'font-weight: bold;';
  VAL = VAL || 'border-top: 2px solid black;';
  VAL = VAL || 'border-top: 2px solid black ! important;';
  VAL = VAL || '} ';
  VAL = VAL || '.sum {';
  VAL = VAL || 'background-color: #B9F6CA;';
  VAL = VAL || 'font-weight: bold;';
  VAL = VAL || '} ';
  VAL = VAL || 'tr.odd .sum {';
  VAL = VAL || 'background-color: #CCFF90;';
  VAL = VAL || '} ';
  VAL = VAL || '.dl td {';
  VAL = VAL || 'border-top: 2px solid black;';
  VAL = VAL || 'border-top: 2px solid black ! important;';
  VAL = VAL || '} ';
  VAL = VAL || '</style>';

  VAL = VAL || '</head>';
  VAL = VAL || '<body style="padding: 8px;">';

  -- Заголовок отчета
  SELECT TYPE_ID
  FROM OBJECTS
  WHERE OBJ_ID = :OBJ_ID
  INTO :V$OBJ_TYPE;

  V$DIST_NAME = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:OBJ_ID));
  VAL = VAL || '<div class="title1">Отчет по МТР ' || V$DIST_NAME || '</div>';

  IF(MTR_GROUP_ID IS NOT NULL) THEN
  BEGIN
      VAL = VAL || '<div class="title2">Группа оборудования: ' || (SELECT R.VAL FROM LISTVALS LV, RES R WHERE LV.LISTVAL_ID = :MTR_GROUP_ID AND R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU') || '</div>';
  END

  -- Заголовок таблиц
  VAL = VAL || '<table class="details" cellspacing="0" cellpadding="0">';
  SUSPEND;
  VAL = '';
  V$YEAR_LIM = 2011;

  -- Выбираем минимальную и максимальную дату выпуска
  -- Внимание: поле год выпуска может содержать не только год, но и дату выпуска
  IF(V$OBJ_TYPE = 2 AND SUBTYPE = 0) THEN
  BEGIN
      -- Ищем организацию, где в МТР есть хрень с неправильно заполненным полем
      SELECT FIRST 1 C.CAPTION
      FROM LINKS L23
      JOIN LINKS L128 ON L128.PARENT_ID = L23.OBJ_ID AND L128.OBJ_TYPE_ID = 128 AND L128.DATE_DEL IS NULL
      JOIN VALL V876 ON V876.OBJ_ID = L128.OBJ_ID AND V876.PARAM_ID = 876 AND V876.IS_DEL = 0 AND (:MTR_GROUP_ID IS NULL OR V876.LISTVAL_ID = :MTR_GROUP_ID)
      JOIN VALS V878 ON V878.OBJ_ID = L128.OBJ_ID AND V878.PARAM_ID = 878 AND V878.IS_DEL = 0
      LEFT JOIN OBJECT_CAPTION_GET(L23.PARENT_ID) C ON 1 = 1
      WHERE L23.PARENT_ID = :OBJ_ID AND L23.OBJ_TYPE_ID = 23 AND L23.DATE_DEL IS NULL AND
          CHAR_LENGTH(V878.VAL) <> 4 AND CHAR_LENGTH(V878.VAL) <> 10
      INTO :V$OO_NAME;
      IF(V$OO_NAME IS NOT NULL) THEN EXCEPTION DATA_ERROR 'Неверное заполнение года выпуска МТР как минимум в ' || V$OO_NAME;

      SELECT MIN(Y.Y), MAX(Y.Y)
      FROM LINKS L23
      JOIN LINKS L128 ON L128.PARENT_ID = L23.OBJ_ID AND L128.OBJ_TYPE_ID = 128 AND L128.DATE_DEL IS NULL
      JOIN VALL V876 ON V876.OBJ_ID = L128.OBJ_ID AND V876.PARAM_ID = 876 AND V876.IS_DEL = 0 AND (:MTR_GROUP_ID IS NULL OR V876.LISTVAL_ID = :MTR_GROUP_ID)
      JOIN VALS V878 ON V878.OBJ_ID = L128.OBJ_ID AND V878.PARAM_ID = 878 AND V878.IS_DEL = 0
      LEFT JOIN STR_TO_YEAR(V878.VAL) Y ON 1 = 1
      WHERE L23.PARENT_ID = :OBJ_ID AND L23.OBJ_TYPE_ID = 23 AND L23.DATE_DEL IS NULL
      INTO :V$YEAR_MIN, :V$YEAR_MAX;
  END
  ELSE IF(V$OBJ_TYPE = 2 AND SUBTYPE = 1) THEN
  BEGIN
      -- Ищем организацию, где в МТР есть хрень с неправильно заполненным полем
      SELECT FIRST 1 C.CAPTION
      FROM LINKS L23
      JOIN LINKS L95 ON L95.PARENT_ID = L23.OBJ_ID AND L95.OBJ_TYPE_ID = 95 AND L95.DATE_DEL IS NULL
      JOIN VALL V626 ON V626.OBJ_ID = L95.OBJ_ID AND V626.PARAM_ID = 626 AND V626.IS_DEL = 0 AND (:MTR_GROUP_ID IS NULL OR V626.LISTVAL_ID = :MTR_GROUP_ID)
      JOIN LINKS L114 ON L114.PARENT_ID = L95.OBJ_ID AND L114.OBJ_TYPE_ID = 114 AND L114.DATE_DEL IS NULL
      JOIN VALS V682 ON V682.OBJ_ID = L114.OBJ_ID AND V682.PARAM_ID = 682 AND V682.IS_DEL = 0
      LEFT JOIN OBJECT_CAPTION_GET(L23.PARENT_ID) C ON 1 = 1
      WHERE L23.PARENT_ID = :OBJ_ID AND L23.OBJ_TYPE_ID = 23 AND L23.DATE_DEL IS NULL AND
          CHAR_LENGTH(V682.VAL) <> 4 AND CHAR_LENGTH(V682.VAL) <> 10
      INTO :V$OO_NAME;
      IF(V$OO_NAME IS NOT NULL) THEN EXCEPTION DATA_ERROR 'Неверное заполнение года выпуска МТР как минимум в одной из карточек';

      SELECT MIN(Y.Y), MAX(Y.Y)
      FROM LINKS L23
      JOIN LINKS L95 ON L95.PARENT_ID = L23.OBJ_ID AND L95.OBJ_TYPE_ID = 95 AND L95.DATE_DEL IS NULL
      JOIN VALL V626 ON V626.OBJ_ID = L95.OBJ_ID AND V626.PARAM_ID = 626 AND V626.IS_DEL = 0 AND (:MTR_GROUP_ID IS NULL OR V626.LISTVAL_ID = :MTR_GROUP_ID)
      JOIN LINKS L114 ON L114.PARENT_ID = L95.OBJ_ID AND L114.OBJ_TYPE_ID = 114 AND L114.DATE_DEL IS NULL
      JOIN VALS V682 ON V682.OBJ_ID = L114.OBJ_ID AND V682.PARAM_ID = 682 AND V682.IS_DEL = 0
      LEFT JOIN STR_TO_YEAR(V682.VAL) Y ON 1 = 1
      WHERE L23.PARENT_ID = :OBJ_ID AND L23.OBJ_TYPE_ID = 23 AND L23.DATE_DEL IS NULL
      INTO :V$YEAR_MIN, :V$YEAR_MAX;
  END
  ELSE
  BEGIN
      -- Ищем организацию, где в МТР есть хрень с неправильно заполненным полем
      SELECT FIRST 1 C.CAPTION
      FROM LINKS L2
      JOIN LINKS L23 ON L23.PARENT_ID = L2.OBJ_ID AND L23.OBJ_TYPE_ID = 23 AND L23.DATE_DEL IS NULL
      JOIN LINKS L95 ON L95.PARENT_ID = L23.OBJ_ID AND L95.OBJ_TYPE_ID = 95 AND L95.DATE_DEL IS NULL
      JOIN VALL V626 ON V626.OBJ_ID = L95.OBJ_ID AND V626.PARAM_ID = 626 AND V626.IS_DEL = 0 AND (:MTR_GROUP_ID IS NULL OR V626.LISTVAL_ID = :MTR_GROUP_ID)
      JOIN LINKS L114 ON L114.PARENT_ID = L95.OBJ_ID AND L114.OBJ_TYPE_ID = 114 AND L114.DATE_DEL IS NULL
      JOIN VALS V682 ON V682.OBJ_ID = L114.OBJ_ID AND V682.PARAM_ID = 682 AND V682.IS_DEL = 0
      LEFT JOIN OBJECT_CAPTION_GET(L23.PARENT_ID) C ON 1 = 1
      WHERE L2.PARENT_ID = :OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND
          CHAR_LENGTH(V682.VAL) <> 4 AND CHAR_LENGTH(V682.VAL) <> 10
      INTO :V$OO_NAME;
      IF(V$OO_NAME IS NOT NULL) THEN EXCEPTION DATA_ERROR 'Неверное заполнение года выпуска МТР как минимум в ' || V$OO_NAME;

      SELECT MIN(Y.Y), MAX(Y.Y)
      FROM LINKS L2
      JOIN LINKS L23 ON L23.PARENT_ID = L2.OBJ_ID AND L23.OBJ_TYPE_ID = 23 AND L23.DATE_DEL IS NULL
      JOIN LINKS L95 ON L95.PARENT_ID = L23.OBJ_ID AND L95.OBJ_TYPE_ID = 95 AND L95.DATE_DEL IS NULL
      JOIN VALL V626 ON V626.OBJ_ID = L95.OBJ_ID AND V626.PARAM_ID = 626 AND V626.IS_DEL = 0 AND V626.LISTVAL_ID = :MTR_GROUP_ID
      JOIN LINKS L114 ON L114.PARENT_ID = L95.OBJ_ID AND L114.OBJ_TYPE_ID = 114 AND L114.DATE_DEL IS NULL
      JOIN VALS V682 ON V682.OBJ_ID = L114.OBJ_ID AND V682.PARAM_ID = 682 AND V682.IS_DEL = 0
      LEFT JOIN STR_TO_YEAR(V682.VAL) Y ON 1 = 1
      WHERE L2.PARENT_ID = :OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      INTO :V$YEAR_MIN, :V$YEAR_MAX;
  END

  V$OO_NAME = '(Текущая организация)';

  IF(V$YEAR_MIN IS NULL) THEN
  BEGIN
    V$YEAR_MIN = EXTRACT(YEAR FROM CURRENT_DATE);
    V$YEAR_MAX = V$YEAR_MIN;
  END

  IF(V$OBJ_TYPE = 2 AND SUBTYPE = 0) THEN
  BEGIN
      -- Отчет по комплексам
      IF(V$YEAR_MIN < 2010) THEN V$YEAR_MIN = 2010;
      VAL = VAL || '<tr>';
      VAL = VAL || '<th class="c1"></th>';
      V$YEAR = V$YEAR_MIN;
      WHILE(V$YEAR <= V$YEAR_MAX)
      DO
      BEGIN
          IF(V$YEAR = V$YEAR_MIN) THEN VAL = VAL || '<th colspan="2">' || V$YEAR || ' и ранее, Н/У</th>';
          ELSE VAL = VAL || '<th colspan="2">' || V$YEAR || '</th>';
          V$YEAR = V$YEAR + 1;
      END
      VAL = VAL || '<th colspan="2">Всего</th>';
      VAL = VAL || '<th colspan="2">Всего с 2011</th>';
      VAL = VAL || '</tr>';
      SUSPEND;
      VAL = '';
      VAL = VAL || '<tr>';
      VAL = VAL || '<th class="c1">Группа комплекса компьютерного оборудования</th>';
      V$YEAR = V$YEAR_MIN;
      WHILE(V$YEAR <= V$YEAR_MAX)
      DO
      BEGIN
          VAL = VAL || '<th>#компл</th>';
          VAL = VAL || '<th>#мест</th>';
          V$YEAR = V$YEAR + 1;
      END
      VAL = VAL || '<th>#компл</th>';
      VAL = VAL || '<th>#мест</th>';
      VAL = VAL || '<th>#компл</th>';
      VAL = VAL || '<th>#мест</th>';
      VAL = VAL || '</tr>';
      SUSPEND;

      N = 0;

      FOR
          SELECT DISTINCT V876.LISTVAL_ID, R.VAL
          FROM LINKS L23
          JOIN LINKS L128 ON L128.PARENT_ID = L23.OBJ_ID AND L128.OBJ_TYPE_ID = 128 AND L128.DATE_DEL IS NULL
          JOIN VALL V876 ON V876.OBJ_ID = L128.OBJ_ID AND V876.PARAM_ID = 876 AND V876.IS_DEL = 0 AND (:MTR_GROUP_ID IS NULL OR V876.LISTVAL_ID = :MTR_GROUP_ID)
          JOIN LISTVALS LV ON LV.LISTVAL_ID = V876.LISTVAL_ID
          JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
          WHERE L23.PARENT_ID = :OBJ_ID AND L23.OBJ_TYPE_ID = 23 AND L23.DATE_DEL IS NULL
          ORDER BY 2
          INTO :V$SUBGROUP_ID, :VAL
      DO
      BEGIN

          IF(N = 0) THEN
            VAL = '<tr class="odd"><td class="c1">' || (SELECT VAL FROM ESCAPE_STR(:VAL)) || '</td>';
          ELSE
            VAL = '<tr class="even"><td class="c1">' || (SELECT VAL FROM ESCAPE_STR(:VAL)) || '</td>';

          V$YEAR = V$YEAR_MIN;
          WHILE(V$YEAR <= V$YEAR_MAX)
          DO
          BEGIN

              NC = 0;
              SELECT COUNT(*)
              FROM LINKS L23
              JOIN LINKS L128 ON L128.PARENT_ID = L23.OBJ_ID AND L128.OBJ_TYPE_ID = 128 AND L128.DATE_DEL IS NULL
              JOIN VALL V876 ON V876.OBJ_ID = L128.OBJ_ID AND V876.PARAM_ID = 876 AND V876.IS_DEL = 0 AND V876.LISTVAL_ID = :V$SUBGROUP_ID
              LEFT JOIN VALI V888 ON V888.OBJ_ID = L128.OBJ_ID AND V888.PARAM_ID = 888 AND V888.IS_DEL = 0
              LEFT JOIN VALS V878 ON V878.OBJ_ID = L128.OBJ_ID AND V878.PARAM_ID = 878 AND V878.IS_DEL = 0
              LEFT JOIN STR_TO_YEAR(V878.VAL) Y ON 1 = 1
              WHERE L23.PARENT_ID = :OBJ_ID AND L23.OBJ_TYPE_ID = 23 AND L23.DATE_DEL IS NULL
                AND (
                  (:V$YEAR = :V$YEAR_MIN AND (Y.Y IS NULL OR Y.Y <= :V$YEAR_MIN)) OR
                  (:V$YEAR > :V$YEAR_MIN AND Y.Y = :V$YEAR)
                )
              INTO :NC;

              VAL = VAL || '<td>' || IIF(NC > 0, NC, '') || '</td>';

              SELECT SUM(V888.VAL)
              FROM LINKS L23
              JOIN LINKS L128 ON L128.PARENT_ID = L23.OBJ_ID AND L128.OBJ_TYPE_ID = 128 AND L128.DATE_DEL IS NULL
              JOIN VALL V876 ON V876.OBJ_ID = L128.OBJ_ID AND V876.PARAM_ID = 876 AND V876.IS_DEL = 0 AND V876.LISTVAL_ID = :V$SUBGROUP_ID
              LEFT JOIN VALI V888 ON V888.OBJ_ID = L128.OBJ_ID AND V888.PARAM_ID = 888 AND V888.IS_DEL = 0
              LEFT JOIN VALS V878 ON V878.OBJ_ID = L128.OBJ_ID AND V878.PARAM_ID = 878 AND V878.IS_DEL = 0
              LEFT JOIN STR_TO_YEAR(V878.VAL) Y ON 1 = 1
              WHERE L23.PARENT_ID = :OBJ_ID AND L23.OBJ_TYPE_ID = 23 AND L23.DATE_DEL IS NULL
                AND (
                  (:V$YEAR = :V$YEAR_MIN AND (Y.Y IS NULL OR Y.Y <= :V$YEAR_MIN)) OR
                  (:V$YEAR > :V$YEAR_MIN AND Y.Y = :V$YEAR)
                )
              INTO :NI;
              IF(NI IS NULL) THEN NI = 0;

              VAL = VAL || '<td>' || IIF(NI > 0, NI, '') || '</td>';

              V$YEAR = V$YEAR + 1;

          END

          -- Общий итог по строке
          NC = 0;
          SELECT COUNT(*)
          FROM LINKS L23
          JOIN LINKS L128 ON L128.PARENT_ID = L23.OBJ_ID AND L128.OBJ_TYPE_ID = 128 AND L128.DATE_DEL IS NULL
          JOIN VALL V876 ON V876.OBJ_ID = L128.OBJ_ID AND V876.PARAM_ID = 876 AND V876.IS_DEL = 0 AND V876.LISTVAL_ID = :V$SUBGROUP_ID
          LEFT JOIN VALI V888 ON V888.OBJ_ID = L128.OBJ_ID AND V888.PARAM_ID = 888 AND V888.IS_DEL = 0
          WHERE L23.PARENT_ID = :OBJ_ID AND L23.OBJ_TYPE_ID = 23 AND L23.DATE_DEL IS NULL
          INTO :NC;

          VAL = VAL || '<td>' || IIF(NC > 0, NC, '') || '</td>';

          SELECT SUM(V888.VAL)
          FROM LINKS L23
          JOIN LINKS L128 ON L128.PARENT_ID = L23.OBJ_ID AND L128.OBJ_TYPE_ID = 128 AND L128.DATE_DEL IS NULL
          JOIN VALL V876 ON V876.OBJ_ID = L128.OBJ_ID AND V876.PARAM_ID = 876 AND V876.IS_DEL = 0 AND V876.LISTVAL_ID = :V$SUBGROUP_ID
          LEFT JOIN VALI V888 ON V888.OBJ_ID = L128.OBJ_ID AND V888.PARAM_ID = 888 AND V888.IS_DEL = 0
          WHERE L23.PARENT_ID = :OBJ_ID AND L23.OBJ_TYPE_ID = 23 AND L23.DATE_DEL IS NULL
          INTO :NI;
          IF(NI IS NULL) THEN NI = 0;

          VAL = VAL || '<td>' || IIF(NI > 0, NI, '') || '</td>';

          -- Лимитированный итог

          NC = 0;
          SELECT COUNT(*)
          FROM LINKS L23
          JOIN LINKS L128 ON L128.PARENT_ID = L23.OBJ_ID AND L128.OBJ_TYPE_ID = 128 AND L128.DATE_DEL IS NULL
          JOIN VALL V876 ON V876.OBJ_ID = L128.OBJ_ID AND V876.PARAM_ID = 876 AND V876.IS_DEL = 0 AND V876.LISTVAL_ID = :V$SUBGROUP_ID
          LEFT JOIN VALI V888 ON V888.OBJ_ID = L128.OBJ_ID AND V888.PARAM_ID = 888 AND V888.IS_DEL = 0
          JOIN VALS V878 ON V878.OBJ_ID = L128.OBJ_ID AND V878.PARAM_ID = 878 AND V878.IS_DEL = 0
          LEFT JOIN STR_TO_YEAR(V878.VAL) Y ON 1 = 1
          WHERE L23.PARENT_ID = :OBJ_ID AND L23.OBJ_TYPE_ID = 23 AND L23.DATE_DEL IS NULL AND Y.Y >= :V$YEAR_LIM
          INTO :NC;

          VAL = VAL || '<td>' || IIF(NC > 0, NC, '') || '</td>';

          NI = 0;
          SELECT SUM(V888.VAL)
          FROM LINKS L23
          JOIN LINKS L128 ON L128.PARENT_ID = L23.OBJ_ID AND L128.OBJ_TYPE_ID = 128 AND L128.DATE_DEL IS NULL
          JOIN VALL V876 ON V876.OBJ_ID = L128.OBJ_ID AND V876.PARAM_ID = 876 AND V876.IS_DEL = 0 AND V876.LISTVAL_ID = :V$SUBGROUP_ID
          LEFT JOIN VALI V888 ON V888.OBJ_ID = L128.OBJ_ID AND V888.PARAM_ID = 888 AND V888.IS_DEL = 0
          JOIN VALS V878 ON V878.OBJ_ID = L128.OBJ_ID AND V878.PARAM_ID = 878 AND V878.IS_DEL = 0
          LEFT JOIN STR_TO_YEAR(V878.VAL) Y ON 1 = 1
          WHERE L23.PARENT_ID = :OBJ_ID AND L23.OBJ_TYPE_ID = 23 AND L23.DATE_DEL IS NULL AND Y.Y >= :V$YEAR_LIM
          INTO :NI;
          IF(NI IS NULL) THEN NI = 0;

          VAL = VAL || '<td>' || IIF(NI > 0, NI, '') || '</td>';

          IF(N = 0) THEN N = 1; ELSE N = 0;
          VAL = VAL || '</tr>';
          SUSPEND;

      END

      VAL = '<tr class="odd"><td class="c1">' || (SELECT VAL FROM ESCAPE_STR(:VAL)) || '</td>';

  END
  ELSE IF(V$OBJ_TYPE = 2 AND SUBTYPE = 1) THEN
  BEGIN
      -- Отчет по ТСО
      IF(V$YEAR_MIN < 2010) THEN V$YEAR_MIN = 2010;
      VAL = VAL || '<tr>';
      VAL = VAL || '<th class="c1">Группа</th>';
      VAL = VAL || '<th class="c2">Подгруппа</th>';
      V$YEAR = V$YEAR_MIN;
      WHILE(V$YEAR <= V$YEAR_MAX)
      DO
      BEGIN
          IF(V$YEAR = V$YEAR_MIN) THEN VAL = VAL || '<th><= ' || V$YEAR || ', Н/У</th>';
          ELSE VAL = VAL || '<th>' || V$YEAR || '</th>';
          V$YEAR = V$YEAR + 1;
      END
      VAL = VAL || '<th>Всего</th>';
      VAL = VAL || '<th>Всего с 2011</th>';
      VAL = VAL || '</tr>';
      SUSPEND;

      -- Цикл по группам оборудования
      FOR
          SELECT DISTINCT V626.LISTVAL_ID, R.VAL
          FROM LINKS L23
          JOIN LINKS L95 ON L95.PARENT_ID = L23.OBJ_ID AND L95.OBJ_TYPE_ID = 95 AND L95.DATE_DEL IS NULL
          JOIN VALL V626 ON V626.OBJ_ID = L95.OBJ_ID AND V626.PARAM_ID = 626 AND V626.IS_DEL = 0 AND (:MTR_GROUP_ID IS NULL OR V626.LISTVAL_ID = :MTR_GROUP_ID)
          JOIN LISTVALS LV ON LV.LISTVAL_ID = V626.LISTVAL_ID
          JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
          JOIN LINKS L114 ON L114.PARENT_ID = L95.OBJ_ID AND L114.OBJ_TYPE_ID = 114 AND L114.DATE_DEL IS NULL
          ORDER BY 2
          INTO :V$GROUP_ID, :V$DIST_NAME
      DO
      BEGIN

          -- Раскраска каждый раз с начала, цикл по подгруппам
          N = 0;
          FOR
              SELECT DISTINCT V604.LISTVAL_ID, R.VAL
              FROM LINKS L23
              JOIN LINKS L95 ON L95.PARENT_ID = L23.OBJ_ID AND L95.OBJ_TYPE_ID = 95 AND L95.DATE_DEL IS NULL
              JOIN VALL V626 ON V626.OBJ_ID = L95.OBJ_ID AND V626.PARAM_ID = 626 AND V626.IS_DEL = 0 AND V626.LISTVAL_ID = :V$GROUP_ID
              JOIN VALL V604 ON V604.OBJ_ID = L95.OBJ_ID AND V604.PARAM_ID = 604 AND V604.IS_DEL = 0
              JOIN LISTVALS LV ON LV.LISTVAL_ID = V604.LISTVAL_ID
              JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
              JOIN LINKS L114 ON L114.PARENT_ID = L95.OBJ_ID AND L114.OBJ_TYPE_ID = 114 AND L114.DATE_DEL IS NULL
              ORDER BY 2
              INTO :V$SUBGROUP_ID, :V$OO_NAME
          DO
          BEGIN

              IF(N = 0) THEN
                VAL = '<tr class="odd"><td class="c1">' || V$DIST_NAME || '</td><td class="c2">' || (SELECT VAL FROM ESCAPE_STR(:V$OO_NAME)) || '</td>';
              ELSE
                VAL = '<tr class="even"><td class="c1">' || V$DIST_NAME || '</td><td class="c2">' || (SELECT VAL FROM ESCAPE_STR(:V$OO_NAME)) || '</td>';

              V$YEAR = V$YEAR_MIN;
              VN = 0;

              WHILE(V$YEAR <= V$YEAR_MAX)
              DO
              BEGIN

                  SELECT COUNT(*)
                  FROM LINKS L23
                  JOIN LINKS L95 ON L95.PARENT_ID = L23.OBJ_ID AND L95.OBJ_TYPE_ID = 95 AND L95.DATE_DEL IS NULL
                  JOIN VALL V604 ON V604.OBJ_ID = L95.OBJ_ID AND V604.PARAM_ID = 604 AND V604.IS_DEL = 0 AND V604.LISTVAL_ID = :V$SUBGROUP_ID
                  JOIN LINKS L114 ON L114.PARENT_ID = L95.OBJ_ID AND L114.OBJ_TYPE_ID = 114 AND L114.DATE_DEL IS NULL
                  LEFT JOIN VALS V682 ON V682.OBJ_ID = L114.OBJ_ID AND V682.PARAM_ID = 682 AND V682.IS_DEL = 0
                  JOIN VALI V605 ON V605.OBJ_ID = L95.OBJ_ID AND V605.PARAM_ID = 605 AND V605.IS_DEL = 0
                  LEFT JOIN STR_TO_YEAR(V682.VAL) Y ON 1 = 1
                  WHERE L23.PARENT_ID = :OBJ_ID AND L23.OBJ_TYPE_ID = 23 AND L23.DATE_DEL IS NULL
                    AND (
                      (:V$YEAR = :V$YEAR_MIN AND (Y.Y IS NULL OR Y.Y <= :V$YEAR_MIN)) OR
                      (:V$YEAR > :V$YEAR_MIN AND Y.Y = :V$YEAR)
                    )
                  INTO :NC;

                  VAL = VAL || '<td>' || IIF(NC > 0, NC, '') || '</td>';
                  VN = VN + NC;
                  V$YEAR = V$YEAR + 1;

              END

              VAL = VAL || '<td class="sum">' || IIF(VN > 0, VN, '') || '</td>';

              SELECT COUNT(*)
              FROM LINKS L23
              JOIN LINKS L95 ON L95.PARENT_ID = L23.OBJ_ID AND L95.OBJ_TYPE_ID = 95 AND L95.DATE_DEL IS NULL
              JOIN VALL V604 ON V604.OBJ_ID = L95.OBJ_ID AND V604.PARAM_ID = 604 AND V604.IS_DEL = 0 AND V604.LISTVAL_ID = :V$SUBGROUP_ID
              JOIN LINKS L114 ON L114.PARENT_ID = L95.OBJ_ID AND L114.OBJ_TYPE_ID = 114 AND L114.DATE_DEL IS NULL
              JOIN VALS V682 ON V682.OBJ_ID = L114.OBJ_ID AND V682.PARAM_ID = 682 AND V682.IS_DEL = 0
              JOIN VALI V605 ON V605.OBJ_ID = L95.OBJ_ID AND V605.PARAM_ID = 605 AND V605.IS_DEL = 0
              LEFT JOIN STR_TO_YEAR(V682.VAL) Y ON 1 = 1
              WHERE L23.PARENT_ID = :OBJ_ID AND L23.OBJ_TYPE_ID = 23 AND L23.DATE_DEL IS NULL AND Y.Y >= :V$YEAR_LIM
              INTO :VN;

              VAL = VAL || '<td>' || IIF(VN > 0, VN, '') || '</td>';
              VAL = VAL || '</tr>';

              IF(N = 0) THEN N = 1; ELSE N = 0;
              SUSPEND;

          END

          -- Итог по группе
          VAL = '<tr class="totals"><td class="c1">' || V$DIST_NAME || ' (всего по группе)</td><td class="c2"></td>';

          V$YEAR = V$YEAR_MIN;
          VN = 0;

          WHILE(V$YEAR <= V$YEAR_MAX)
          DO
          BEGIN

              SELECT COUNT(*)
              FROM LINKS L23
              JOIN LINKS L95 ON L95.PARENT_ID = L23.OBJ_ID AND L95.OBJ_TYPE_ID = 95 AND L95.DATE_DEL IS NULL
              JOIN VALL V626 ON V626.OBJ_ID = L95.OBJ_ID AND V626.PARAM_ID = 626 AND V626.IS_DEL = 0 AND V626.LISTVAL_ID = :V$GROUP_ID
              JOIN LINKS L114 ON L114.PARENT_ID = L95.OBJ_ID AND L114.OBJ_TYPE_ID = 114 AND L114.DATE_DEL IS NULL
              LEFT JOIN VALS V682 ON V682.OBJ_ID = L114.OBJ_ID AND V682.PARAM_ID = 682 AND V682.IS_DEL = 0
              JOIN VALI V605 ON V605.OBJ_ID = L95.OBJ_ID AND V605.PARAM_ID = 605 AND V605.IS_DEL = 0
              LEFT JOIN STR_TO_YEAR(V682.VAL) Y ON 1 = 1
              WHERE L23.PARENT_ID = :OBJ_ID AND L23.OBJ_TYPE_ID = 23 AND L23.DATE_DEL IS NULL
                AND (
                  (:V$YEAR = :V$YEAR_MIN AND (Y.Y IS NULL OR Y.Y <= :V$YEAR_MIN)) OR
                  (:V$YEAR > :V$YEAR_MIN AND Y.Y = :V$YEAR)
                )
              INTO :NC;

              VAL = VAL || '<td>' || IIF(NC > 0, NC, '') || '</td>';
              VN = VN + NC;
              V$YEAR = V$YEAR + 1;

          END

          VAL = VAL || '<td class="sum">' || IIF(VN > 0, VN, '') || '</td>';

          SELECT COUNT(*)
          FROM LINKS L23
          JOIN LINKS L95 ON L95.PARENT_ID = L23.OBJ_ID AND L95.OBJ_TYPE_ID = 95 AND L95.DATE_DEL IS NULL
          JOIN VALL V626 ON V626.OBJ_ID = L95.OBJ_ID AND V626.PARAM_ID = 626 AND V626.IS_DEL = 0 AND V626.LISTVAL_ID = :V$GROUP_ID
          JOIN LINKS L114 ON L114.PARENT_ID = L95.OBJ_ID AND L114.OBJ_TYPE_ID = 114 AND L114.DATE_DEL IS NULL
          JOIN VALS V682 ON V682.OBJ_ID = L114.OBJ_ID AND V682.PARAM_ID = 682 AND V682.IS_DEL = 0
          JOIN VALI V605 ON V605.OBJ_ID = L95.OBJ_ID AND V605.PARAM_ID = 605 AND V605.IS_DEL = 0
          LEFT JOIN STR_TO_YEAR(V682.VAL) Y ON 1 = 1
          WHERE L23.PARENT_ID = :OBJ_ID AND L23.OBJ_TYPE_ID = 23 AND L23.DATE_DEL IS NULL AND Y.Y >= :V$YEAR_LIM
          INTO :VN;

          VAL = VAL || '<td>' || IIF(VN > 0, VN, '') || '</td>';
          VAL = VAL || '</tr>';

          SUSPEND;


      END

  END
  ELSE
  BEGIN

      IF(V$YEAR_MIN < 2000) THEN V$YEAR_MIN = 2000;

      VAL = VAL || '<tr>';
      VAL = VAL || '<th class="c1">Район</th>';
      VAL = VAL || '<th class="c2">Наименование учреждения</th>';
      VAL = VAL || '<th class="c3">Подгруппа оборудования</th>';
      VAL = VAL || '<th>Н/У</th>';
      V$YEAR = V$YEAR_MIN;
      WHILE(V$YEAR <= V$YEAR_MAX)
      DO
      BEGIN
          VAL = VAL || '<th>' || V$YEAR || '</th>';
          V$YEAR = V$YEAR + 1;
      END
      VAL = VAL || '<th>Общий итог</th>';
      VAL = VAL || '</tr>';
      SUSPEND;

      V$PREV_ID = NULL;

      FOR
          SELECT L2.OBJ_ID, V2.VAL
          FROM LINKS L2
          JOIN VALS V2 ON V2.OBJ_ID = L2.OBJ_ID AND V2.PARAM_ID = 2 AND V2.IS_DEL = 0
          WHERE L2.PARENT_ID = :OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
          ORDER BY 2
          INTO :V$OO_ID, :V$OO_NAME
      DO
      BEGIN

          -- Счетчик строк
          VN = 0;

          FOR
              SELECT DISTINCT V604.LISTVAL_ID, R.VAL
              FROM LINKS L23
              JOIN LINKS L95 ON L95.PARENT_ID = L23.OBJ_ID AND L95.OBJ_TYPE_ID = 95 AND L95.DATE_DEL IS NULL
              JOIN VALL V626 ON V626.OBJ_ID = L95.OBJ_ID AND V626.PARAM_ID = 626 AND V626.IS_DEL = 0 AND V626.LISTVAL_ID = :MTR_GROUP_ID
              JOIN VALL V604 ON V604.OBJ_ID = L95.OBJ_ID AND V604.PARAM_ID = 604 AND V604.IS_DEL = 0
              JOIN LISTVALS LV ON LV.LISTVAL_ID = V604.LISTVAL_ID
              JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
              WHERE L23.PARENT_ID = :V$OO_ID AND L23.OBJ_TYPE_ID = 23 AND L23.DATE_DEL IS NULL
              ORDER BY 2
              INTO :V$SUBGROUP_ID, :VAL
          DO
          BEGIN

              IF(V$OO_ID <> V$PREV_ID AND V$PREV_ID IS NOT NULL) THEN V$OE = ' dl'; ELSE V$OE = '';
              V$PREV_ID = V$OO_ID;

              IF(N = 0) THEN
                VAL = '<tr class="odd' || V$OE || '"><td class="c1">' || V$DIST_NAME || '</td><td class="c2">' || (SELECT VAL FROM ESCAPE_STR(:V$OO_NAME)) ||
                  '</td><td class="c3">' || (SELECT VAL FROM ESCAPE_STR(:VAL)) || '</td>';
              ELSE
                VAL = '<tr class="even' || V$OE || '"><td class="c1">' || V$DIST_NAME || '</td><td class="c2">' || (SELECT VAL FROM ESCAPE_STR(:V$OO_NAME)) ||
                  '</td><td class="c3">' || (SELECT VAL FROM ESCAPE_STR(:VAL)) || '</td>';

              -- Сначала где год выпуска не указан или старше начального
              NC = 0;
              SELECT COUNT(*)
              FROM LINKS L23
              JOIN LINKS L95 ON L95.PARENT_ID = L23.OBJ_ID AND L95.OBJ_TYPE_ID = 95 AND L95.DATE_DEL IS NULL
              JOIN VALL V604 ON V604.OBJ_ID = L95.OBJ_ID AND V604.PARAM_ID = 604 AND V604.IS_DEL = 0 AND V604.LISTVAL_ID = :V$SUBGROUP_ID
              JOIN LINKS L114 ON L114.PARENT_ID = L95.OBJ_ID AND L114.OBJ_TYPE_ID = 114 AND L114.DATE_DEL IS NULL
              LEFT JOIN VALS V682 ON V682.OBJ_ID = L114.OBJ_ID AND V682.PARAM_ID = 682 AND V682.IS_DEL = 0
              JOIN VALI V605 ON V605.OBJ_ID = L95.OBJ_ID AND V605.PARAM_ID = 605 AND V605.IS_DEL = 0
              LEFT JOIN STR_TO_YEAR(V682.VAL) Y ON 1 = 1
              WHERE L23.PARENT_ID = :V$OO_ID AND L23.OBJ_TYPE_ID = 23 AND L23.DATE_DEL IS NULL AND Y.Y IS NULL
              INTO :NI;
              IF(NI IS NULL) THEN NI = 0;
              VAL = VAL || '<td>' || IIF(NI > 0, NI, '') || '</td>';
              NC = NC + NI;

              -- Далее по конкретным годам
              V$YEAR = V$YEAR_MIN;
              WHILE(V$YEAR <= V$YEAR_MAX)
              DO
              BEGIN
                  SELECT COUNT(*)
                  FROM LINKS L23
                  JOIN LINKS L95 ON L95.PARENT_ID = L23.OBJ_ID AND L95.OBJ_TYPE_ID = 95 AND L95.DATE_DEL IS NULL
                  JOIN VALL V604 ON V604.OBJ_ID = L95.OBJ_ID AND V604.PARAM_ID = 604 AND V604.IS_DEL = 0 AND V604.LISTVAL_ID = :V$SUBGROUP_ID
                  JOIN LINKS L114 ON L114.PARENT_ID = L95.OBJ_ID AND L114.OBJ_TYPE_ID = 114 AND L114.DATE_DEL IS NULL
                  LEFT JOIN VALS V682 ON V682.OBJ_ID = L114.OBJ_ID AND V682.PARAM_ID = 682 AND V682.IS_DEL = 0
                  JOIN VALI V605 ON V605.OBJ_ID = L95.OBJ_ID AND V605.PARAM_ID = 605 AND V605.IS_DEL = 0
                  LEFT JOIN STR_TO_YEAR(V682.VAL) Y ON 1 = 1
                  WHERE L23.PARENT_ID = :V$OO_ID AND L23.OBJ_TYPE_ID = 23 AND L23.DATE_DEL IS NULL
                    AND ((:V$YEAR = :V$YEAR_MIN AND Y.Y <= :V$YEAR) OR (:V$YEAR > :V$YEAR_MIN AND Y.Y = :V$YEAR))
                  INTO :NI;
                  IF(NI IS NULL) THEN NI = 0;
                  VAL = VAL || '<td>' || IIF(NI > 0, NI, '') || '</td>';
                  NC = NC + NI;
                  V$YEAR = V$YEAR + 1;
              END

              VAL = VAL || '<td class="sum">' || IIF(NC > 0, NC, '') || '</td>';

              IF(N = 0) THEN N = 1; ELSE N = 0;
              VAL = VAL || '</tr>';
              SUSPEND;

              VN = VN + 1;

          END

          -- Если вдруг в ОО ничего нет, выводим пустую строку
          IF(VN = 0) THEN
          BEGIN
              IF(V$OO_ID <> V$PREV_ID AND V$PREV_ID IS NOT NULL) THEN V$OE = ' dl'; ELSE V$OE = '';
              V$PREV_ID = V$OO_ID;

              IF(N = 0) THEN
                VAL = '<tr class="odd' || V$OE || '"><td class="c1">' || V$DIST_NAME || '</td><td class="c2">' || (SELECT VAL FROM ESCAPE_STR(:V$OO_NAME)) ||
                  '</td><td class="c3"></td>';
              ELSE
                VAL = '<tr class="even' || V$OE || '"><td class="c1">' || V$DIST_NAME || '</td><td class="c2">' || (SELECT VAL FROM ESCAPE_STR(:V$OO_NAME)) ||
                  '</td><td class="c3"></td>';
              VAL = VAL || '<td>-</td>';
              V$YEAR = V$YEAR_MIN;
              WHILE(V$YEAR <= V$YEAR_MAX)
              DO
              BEGIN
                  VAL = VAL || '<td>-</td>';
                  V$YEAR = V$YEAR + 1;
              END
              VAL = VAL || '<td class="sum">-</td>';
              VAL = VAL || '</tr>';
              SUSPEND;
          END

      END

      -- Итоговая строка
      VAL = '<tr class="totals"><td class="c1"></td><td class="c2">Итого:</td><td class="c3"></td>';

      NC = 0;
      SELECT COUNT(*)
      FROM LINKS L2
      JOIN LINKS L23 ON L23.PARENT_ID = L2.OBJ_ID AND L23.OBJ_TYPE_ID = 23 AND L23.DATE_DEL IS NULL
      JOIN LINKS L95 ON L95.PARENT_ID = L23.OBJ_ID AND L95.OBJ_TYPE_ID = 95 AND L95.DATE_DEL IS NULL
      JOIN VALL V626 ON V626.OBJ_ID = L95.OBJ_ID AND V626.PARAM_ID = 626 AND V626.IS_DEL = 0 AND V626.LISTVAL_ID = :MTR_GROUP_ID
      JOIN LINKS L114 ON L114.PARENT_ID = L95.OBJ_ID AND L114.OBJ_TYPE_ID = 114 AND L114.DATE_DEL IS NULL
      LEFT JOIN VALS V682 ON V682.OBJ_ID = L114.OBJ_ID AND V682.PARAM_ID = 682 AND V682.IS_DEL = 0
      JOIN VALI V605 ON V605.OBJ_ID = L95.OBJ_ID AND V605.PARAM_ID = 605 AND V605.IS_DEL = 0
      LEFT JOIN STR_TO_YEAR(V682.VAL) Y ON 1 = 1
      WHERE L2.PARENT_ID = :OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND Y.Y IS NULL
      INTO :NI;
      IF(NI IS NULL) THEN NI = 0;
      VAL = VAL || '<td>' || IIF(NI > 0, NI, '') || '</td>';
      NC = NC + NI;

      -- Далее по конкретным годам
      V$YEAR = V$YEAR_MIN;
      WHILE(V$YEAR <= V$YEAR_MAX)
      DO
      BEGIN
          SELECT COUNT(*)
          FROM LINKS L2
          JOIN LINKS L23 ON L23.PARENT_ID = L2.OBJ_ID AND L23.OBJ_TYPE_ID = 23 AND L23.DATE_DEL IS NULL
          JOIN LINKS L95 ON L95.PARENT_ID = L23.OBJ_ID AND L95.OBJ_TYPE_ID = 95 AND L95.DATE_DEL IS NULL
          JOIN VALL V626 ON V626.OBJ_ID = L95.OBJ_ID AND V626.PARAM_ID = 626 AND V626.IS_DEL = 0 AND V626.LISTVAL_ID = :MTR_GROUP_ID
          JOIN LINKS L114 ON L114.PARENT_ID = L95.OBJ_ID AND L114.OBJ_TYPE_ID = 114 AND L114.DATE_DEL IS NULL
          LEFT JOIN VALS V682 ON V682.OBJ_ID = L114.OBJ_ID AND V682.PARAM_ID = 682 AND V682.IS_DEL = 0
          JOIN VALI V605 ON V605.OBJ_ID = L95.OBJ_ID AND V605.PARAM_ID = 605 AND V605.IS_DEL = 0
          LEFT JOIN STR_TO_YEAR(V682.VAL) Y ON 1 = 1
          WHERE L2.PARENT_ID = :OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
            AND ((:V$YEAR = :V$YEAR_MIN AND Y.Y <= :V$YEAR) OR (:V$YEAR > :V$YEAR_MIN AND Y.Y = :V$YEAR))
          INTO :NI;
          IF(NI IS NULL) THEN NI = 0;
          VAL = VAL || '<td>' || IIF(NI > 0, NI, '') || '</td>';
          NC = NC + NI;
          V$YEAR = V$YEAR + 1;
      END

      VAL = VAL || '<td>' || IIF(NC > 0, NC, '') || '</td>';

      VAL = VAL || '</tr>';
      SUSPEND;

  END

  VAL = '</table></html></body>';
  SUSPEND;

  WHEN SQLCODE -413 DO
  BEGIN
      EXCEPTION DATA_ERROR 'При формировании отчета произошла ошибка. Проверьте заполнение поля "год выпуска (изготовления)" в ' || V$OO_NAME;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE REPORT_MTR13 (
    OBJ_ID BIGINT,
    REPORT_DATE DATE)
RETURNS (
    VAL VARCHAR(6000))
AS
declare variable V$TYPE_ID bigint;
declare variable V$OBJ_ID bigint;
declare variable V$DATE_CHANGE timestamp;
declare variable V$ATTR_CHANGE timestamp;
declare variable VT timestamp;
declare variable N integer;
declare variable S varchar(100);
begin

  VAL = '<!DOCTYPE html>';
  VAL = VAL || '<html lang="ru">';
  VAL = VAL || '<head>';
  VAL = VAL || '<meta charset="utf-8" />';

  VAL = VAL || '<style>';
  VAL = VAL || 'html { font-family: Tahoma, Verdana, Arial;';
  VAL = VAL || 'font-size: 10pt; ';
  VAL = VAL || '} ';
  VAL = VAL || '.title1 { font-size: 150%;';
  VAL = VAL || 'padding: 8px;';
  VAL = VAL || 'margin-bottom: 4px;';
  VAL = VAL || 'font-weight: bold;';
  VAL = VAL || 'background-color: #D4E157;';
  VAL = VAL || '} ';
  VAL = VAL || '.title2 { ';
  VAL = VAL || 'padding: 4px;';
  VAL = VAL || 'font-weight: bold;';
  VAL = VAL || '} ';
  VAL = VAL || '.details {';
  VAL = VAL || 'width: 100%;';
  VAL = VAL || 'margin-top: 10px;';
  VAL = VAL || 'border: 1px solid #e0e0e0;';
  VAL = VAL || '} ';
  VAL = VAL || '.details tr td {';
  VAL = VAL || 'padding: 2px 4px;';
  VAL = VAL || 'border-right: 1px solid #e0e0e0;';
  VAL = VAL || 'text-align: left;';
  VAL = VAL || '} ';
  VAL = VAL || '.odd td {';
  VAL = VAL || 'background-color: #f7f7f7;';
  VAL = VAL || '} ';
  VAL = VAL || '.thd {';
  VAL = VAL || 'background-color: #c9d728;';
  VAL = VAL || '} ';
  VAL = VAL || '.block {';
  VAL = VAL || 'background-color: #F0F4C3;';
  VAL = VAL || '} ';

  VAL = VAL || '</style>';

  VAL = VAL || '</head>';
  VAL = VAL || '<body style="padding: 8px;">';

  -- Заголовок отчета
  VAL = VAL || '<div class="title1">Движение МТР по ' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:OBJ_ID)) || '</div>';

  IF(REPORT_DATE IS NULL) THEN VAL = VAL || '<div class="title2">За все время</div>';
  ELSE VAL = VAL || '<div class="title2">' || (SELECT RESULT FROM DATE2STR(:REPORT_DATE)) || '</div>';

  VAL = VAL || '<table class="details" cellspacing="0" cellpadding="0">';

  VAL = VAL || '<tr class="thd">';
  VAL = VAL || '<td class="title">Вид, наименование МТР</td>';
  VAL = VAL || '<td class="date">Дата</td>';
  VAL = VAL || '</tr>';

  SUSPEND;

  FOR
      SELECT OBJ_ID, C.CAPTION
      FROM LINKS L
      LEFT JOIN OBJECT_CAPTION_GET(L.OBJ_ID) C ON 1 = 1
      WHERE L.PARENT_ID = :OBJ_ID AND L.DATE_DEL IS NULL AND L.OBJ_TYPE_ID IN (74, 23, 92, 104, 105)
      INTO :V$TYPE_ID, :VAL
  DO
  BEGIN

      VAL = '<tr class="block"><td colspan="2">' || (SELECT VAL FROM ESCAPE_STR(:VAL)) || '</td>';
      SUSPEND;

      N = 0;

      FOR
          SELECT L2.OBJ_ID, C.CAPTION, L2.DATE_MODIFY
          FROM LINKS L1
          JOIN LINKS L2 ON L2.PARENT_ID = L1.OBJ_ID AND L2.OBJ_TYPE_ID IN (114) AND L2.DATE_DEL IS NULL
          LEFT JOIN OBJECT_CAPTION_GET(L2.OBJ_ID) C ON 1 = 1
          WHERE L1.PARENT_ID = :V$TYPE_ID AND L1.OBJ_TYPE_ID IN (94, 95, 97) AND L1.DATE_DEL IS NULL
          UNION
          SELECT L1.OBJ_ID, C.CAPTION, L1.DATE_MODIFY
          FROM LINKS L1
          LEFT JOIN OBJECT_CAPTION_GET(L1.OBJ_ID) C ON 1 = 1
          WHERE L1.PARENT_ID = :V$TYPE_ID AND L1.OBJ_TYPE_ID IN (106, 107) AND L1.DATE_DEL IS NULL
          ORDER BY 2
          INTO :V$OBJ_ID, :VAL, :V$DATE_CHANGE
      DO
      BEGIN

          V$ATTR_CHANGE = '01.01.2000';
          VT = NULL;
          SELECT MAX(DATE_MODIFY) FROM VALS WHERE OBJ_ID = :V$OBJ_ID AND IS_DEL = 0 INTO :VT;
          IF(VT > V$ATTR_CHANGE) THEN V$ATTR_CHANGE = VT;
          VT = NULL;
          SELECT MAX(DATE_MODIFY) FROM VALD WHERE OBJ_ID = :V$OBJ_ID AND IS_DEL = 0 INTO :VT;
          IF(VT > V$ATTR_CHANGE) THEN V$ATTR_CHANGE = VT;
          VT = NULL;
          SELECT MAX(DATE_MODIFY) FROM VALI WHERE OBJ_ID = :V$OBJ_ID AND IS_DEL = 0 INTO :VT;
          IF(VT > V$ATTR_CHANGE) THEN V$ATTR_CHANGE = VT;
          VT = NULL;
          SELECT MAX(DATE_MODIFY) FROM VALL WHERE OBJ_ID = :V$OBJ_ID AND IS_DEL = 0 INTO :VT;
          IF(VT > V$ATTR_CHANGE) THEN V$ATTR_CHANGE = VT;

          IF(REPORT_DATE IS NULL OR V$DATE_CHANGE >= REPORT_DATE OR V$ATTR_CHANGE >= REPORT_DATE) THEN
          BEGIN

              IF(N = 0) THEN S = ''; ELSE S = 'odd';
              IF(N = 0) THEN N = 1; ELSE N = 0;

              VAL = '<tr class="' || S || '"><td class="title">' || (SELECT VAL FROM ESCAPE_STR(:VAL)) || '</td>';
              SUSPEND;

              IF(V$ATTR_CHANGE > V$DATE_CHANGE) THEN VT = V$ATTR_CHANGE; ELSE VT = V$DATE_CHANGE;
              VAL = '<td class="date">' || (SELECT RESULT FROM DATE2STR(:VT)) || '</td>';
              SUSPEND;

          END

      END

  END

  VAL = '</table>';
  VAL = VAL || '</body>';
  VAL = VAL || '</html>';
  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE REPORT_OO1 (
    I$OBJ_ID BIGINT)
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(2000))
AS
DECLARE VARIABLE V$YEAR INTEGER;
DECLARE VARIABLE V$DATE DATE;
DECLARE VARIABLE V SMALLINT;
DECLARE VARIABLE VV SMALLINT;
DECLARE VARIABLE V1 BIGINT;
DECLARE VARIABLE V2 BIGINT;
DECLARE VARIABLE VSUB VARCHAR(400);
DECLARE VARIABLE VX INTEGER;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$GRADE_ID BIGINT;
DECLARE VARIABLE V$STAGE_ID BIGINT;
DECLARE VARIABLE V$LEVEL_ID BIGINT;
DECLARE VARIABLE V$GROUP_ID BIGINT;
DECLARE VARIABLE V$OP_ID BIGINT;
DECLARE VARIABLE V$PLAN_ID BIGINT;
DECLARE VARIABLE V$OVZ SMALLINT;
DECLARE VARIABLE V$PS INTEGER;
DECLARE VARIABLE V$IS_PERSONAL SMALLINT;
DECLARE VARIABLE V$SY SMALLINT;
DECLARE VARIABLE D1 DATE;
DECLARE VARIABLE D2 DATE;
DECLARE VARIABLE N INTEGER;
begin

  -- Дата на 20 сентября, перевод года считаем сентябрем
  -- Также есть ссылки в REPORT_OO1_XXXX
  V$YEAR = EXTRACT(YEAR FROM CURRENT_DATE);
  IF(EXTRACT(MONTH FROM CURRENT_DATE) < 9) THEN V$YEAR = V$YEAR - 1;
  V$DATE = '20.09.' || V$YEAR;

  -------------------------
  -- Титульный лист
  -- Дата и учебный год - два поля одинаковые
  TAG_NAME = '@1:BS11';
  VAL = EXTRACT(YEAR FROM V$DATE);
  SUSPEND;
  TAG_NAME = '@1:CK12';
  SUSPEND;

  TAG_NAME = '@1:AV29';
  VAL = (SELECT V FROM VAL_GET(:I$OBJ_ID, 5)); -- наименование
  SUSPEND;

  TAG_NAME = '@1:S31';
  VAL = (SELECT VAL FROM ADR_GET(27, :I$OBJ_ID)); -- адрес
  SUSPEND;

  TAG_NAME = '@1:R37';
  VAL = (SELECT V FROM VAL_GET(:I$OBJ_ID, 16)); -- ОКПО
  SUSPEND;

  TAG_NAME = '@1:BR37';
  VAL = (SELECT V FROM VAL_GET(:I$OBJ_ID, 33)); -- ИНН
  SUSPEND;

  TAG_NAME = '@1:CT37';
  VAL = (SELECT V FROM VAL_GET(:I$OBJ_ID, 34)); -- КПП
  SUSPEND;

  TAG_NAME = '@1:DX37';
  VAL = (SELECT V FROM VAL_GET(:I$OBJ_ID, 9)); -- ОГРН
  SUSPEND;

  -------------------------
  -- Раздел 1.1
  TAG_NAME = '@2:BU7'; -- Наличие лицензии
  VAL = 2;
  SELECT FIRST 1 1
  FROM LINKS L17
  JOIN VALL V471 ON V471.OBJ_ID = L17.OBJ_ID AND V471.PARAM_ID = 471 AND V471.IS_DEL = 0 AND V471.LISTVAL_ID IN (1052, 18624)
  JOIN VALD V482 ON V482.OBJ_ID = L17.OBJ_ID AND V482.PARAM_ID = 482 AND V482.IS_DEL = 0 AND V482.VAL <= :V$DATE
  LEFT JOIN VALD V483 ON V483.OBJ_ID = L17.OBJ_ID AND V483.PARAM_ID = 483 AND V483.IS_DEL = 0
  LEFT JOIN VALL V613 ON V613.OBJ_ID = L17.OBJ_ID AND V613.PARAM_ID = 613 AND V613.IS_DEL = 0
  WHERE L17.PARENT_ID = :I$OBJ_ID AND L17.OBJ_TYPE_ID = 17 AND L17.DATE_DEL IS NULL
      AND (V483.VAL IS NULL OR V483.VAL > :V$DATE) AND (V613.LISTVAL_ID IS NULL OR V613.LISTVAL_ID IN (1982, 1984))
  INTO :VAL;
  SUSPEND;

  TAG_NAME = '@2:BU8'; -- Наличие аккредитации
  VAL = 2;
  SELECT FIRST 1 1
  FROM LINKS L17
  JOIN VALL V471 ON V471.OBJ_ID = L17.OBJ_ID AND V471.PARAM_ID = 471 AND V471.IS_DEL = 0 AND V471.LISTVAL_ID IN (1053, 18625)
  JOIN VALD V482 ON V482.OBJ_ID = L17.OBJ_ID AND V482.PARAM_ID = 482 AND V482.IS_DEL = 0 AND V482.VAL <= :V$DATE
  LEFT JOIN VALD V483 ON V483.OBJ_ID = L17.OBJ_ID AND V483.PARAM_ID = 483 AND V483.IS_DEL = 0
  LEFT JOIN VALL V613 ON V613.OBJ_ID = L17.OBJ_ID AND V613.PARAM_ID = 613 AND V613.IS_DEL = 0
  WHERE L17.PARENT_ID = :I$OBJ_ID AND L17.OBJ_TYPE_ID = 17 AND L17.DATE_DEL IS NULL
      AND (V483.VAL IS NULL OR V483.VAL > :V$DATE) AND (V613.LISTVAL_ID IS NULL OR V613.LISTVAL_ID IN (1982, 1984))
  INTO :VAL;
  SUSPEND;

  V = 0;

  -- остальные поля заполняем вручную

  TAG_NAME = '@2:BU13'; -- Попечительский совет
  VAL = (SELECT V FROM VAL_GET(:I$OBJ_ID, 32));
  IF(VAL = 'Есть') THEN BEGIN VAL = 1; V = V + 1; END ELSE VAL = 2;
  SUSPEND;

  TAG_NAME = '@2:BU9'; -- Коллегиальные органы управления
  IF(V > 0) THEN VAL = 1; ELSE VAL = 2;
  SUSPEND;

  -------------------------
  -- Раздел 1.2 (классификация ОУ)
  V = 0; -- общий счетчик особенностей

  -- Тип (V1) и вид ОУ (V2)
  SELECT V10.LISTVAL_ID, LV.PARENT_ID
  FROM VALL V10
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V10.LISTVAL_ID
  WHERE V10.OBJ_ID = :I$OBJ_ID AND V10.PARAM_ID = 10 AND V10.IS_DEL = 0
  INTO :V1, :V2;

  SELECT LOWER(V937.VAL)
  FROM VALS V937
  WHERE V937.OBJ_ID = :I$OBJ_ID AND V937.PARAM_ID = 937 AND V937.IS_DEL = 0
  INTO :VSUB;

  TAG_NAME = '@2:CS27'; -- Интернат (вид = интернаты)
  IF(V2 = 969) THEN BEGIN VAL = 1; V = V + 1; END ELSE VAL = 2;
  SUSPEND;

  TAG_NAME = '@2:CS29'; -- Не интернат, но имеет интернат - всегда НЕТ
  VAL = 2;
  SUSPEND;

  TAG_NAME = '@2:CS30'; -- Вечерняя школа (тип = ...)
  IF(V1 IN (965, 2219, 2220)) THEN BEGIN VAL = 1; V = V + 1; END ELSE VAL = 2;
  SUSPEND;

  TAG_NAME = '@2:CS31'; -- Не вечерняя школа (тип = ...), но с очно-заочными классами. Это только колледжи
  VV = (SELECT COUNT(*)
    FROM LINKS L7
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
    JOIN VALL V1768 ON V1768.OBJ_ID = L9.OBJ_ID AND V1768.PARAM_ID = 1768 AND V1768.IS_DEL = 0 AND V1768.LISTVAL_ID IN (154, 155)
    WHERE L7.PARENT_ID = :I$OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
  );
  IF(V1 NOT IN (965, 2219, 2220) AND VV > 0) THEN BEGIN VAL = 1; V = V + 1; END ELSE VAL = 2;
  SUSPEND;

  -- Школа для детей с ОВЗ
  VV = 0; -- счетчик особенностей с ОВЗ

  IF(V2 = 978 OR V1 IN (985, 986, 2224, 2225)) THEN
  BEGIN
    VV = 1; -- суммарно = ДА
    TAG_NAME = '@2:CS33';
    VAL = IIF(POSITION('глух' IN VSUB) > 0, 1, 2);
    SUSPEND;
    TAG_NAME = '@2:CS34';
    VAL = IIF(POSITION('слабослыш' IN VSUB) > 0, 1, 2);
    SUSPEND;
    TAG_NAME = '@2:CS35';
    VAL = IIF(POSITION('слеп' IN VSUB) > 0, 1, 2);
    SUSPEND;
    TAG_NAME = '@2:CS36';
    VAL = IIF(POSITION('слабовид' IN VSUB) > 0, 1, 2);
    SUSPEND;
    TAG_NAME = '@2:CS37';
    VAL = IIF(POSITION('нарушениями речи' IN VSUB) > 0, 1, 2);
    SUSPEND;
    TAG_NAME = '@2:CS38';
    VAL = IIF(POSITION('опорно' IN VSUB) > 0, 1, 2);
    SUSPEND;
    TAG_NAME = '@2:CS39';
    VAL = IIF(POSITION('психич' IN VSUB) > 0, 1, 2);
    SUSPEND;
    TAG_NAME = '@2:CS40';
    VAL = IIF(POSITION('аути' IN VSUB) > 0, 1, 2);
    SUSPEND;
    TAG_NAME = '@2:CS41';
    VAL = IIF(POSITION('сложн' IN VSUB) > 0, 1, 2);
    SUSPEND;
    TAG_NAME = '@2:CS42';
    VAL = IIF(POSITION('друг' IN VSUB) > 0, 1, 2);
    SUSPEND;
  END
  ELSE
  BEGIN
    -- Все строки НЕТ
    VAL = 2;
    TAG_NAME = '@2:CS33';
    SUSPEND;
    TAG_NAME = '@2:CS34';
    SUSPEND;
    TAG_NAME = '@2:CS35';
    SUSPEND;
    TAG_NAME = '@2:CS36';
    SUSPEND;
    TAG_NAME = '@2:CS37';
    SUSPEND;
    TAG_NAME = '@2:CS38';
    SUSPEND;
    TAG_NAME = '@2:CS39';
    SUSPEND;
    TAG_NAME = '@2:CS40';
    SUSPEND;
    TAG_NAME = '@2:CS41';
    SUSPEND;
    TAG_NAME = '@2:CS42';
    SUSPEND;
  END

  TAG_NAME = '@2:CS32'; -- суммарно
  IF(VV > 0) THEN BEGIN VAL = 1; V = V + 1; END ELSE VAL = 2;
  SUSPEND;

  -- Школа с классами ОВЗ
  TAG_NAME = '@2:CS43';
  IF(VV = 0 AND EXISTS(
    SELECT FIRST 1 1
    FROM LINKS L7
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_TYPE_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_TYPE_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
    JOIN VALL V592 ON V592.OBJ_ID = L9.OBJ_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID <> 13275
    WHERE L7.PARENT_ID = :I$OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
  )) THEN BEGIN VAL = 1; V = V + 1; END ELSE VAL = 2;
  SUSPEND;

  -- Девиантное поведение
  TAG_NAME = '@2:CS44';
  VAL = IIF(V2 = 2221, 1, 2);
  SUSPEND;

  -- Дошкольный и младший школьный возраст
  TAG_NAME = '@2:CS45';
  VAL = IIF(V2 = 954, 1, 2); -- V1 = 961 ?
  SUSPEND;

  -- Длительное лечение
  TAG_NAME = '@2:CS46';
  VAL = IIF(V2 = 975, 1, 2);
  SUSPEND;

  -- Псих-пед
  TAG_NAME = '@2:CS47';
  VAL = IIF(V2 = 1003, 1, 2);
  SUSPEND;

  -- Для детей-сирот
  TAG_NAME = '@2:CS48';
  VAL = IIF(V2 = 981, 1, 2);
  SUSPEND;

  -- Центр образования
  TAG_NAME = '@2:CS49';
  VAL = IIF(V1 = 967, 1, 2);
  SUSPEND;

  -- ФСИН
  TAG_NAME = '@2:CS50';
  VAL = IIF(V1 IN (2219, 2220), 1, 2);
  SUSPEND;

  -- Углубленное изучение

  TAG_NAME = '@2:CS52'; -- углубленное изучение предмета (школа)
  IF(V1 = 964) THEN BEGIN VAL = 1; V = V + 1; END ELSE VAL = 2;
  SUSPEND;

  TAG_NAME = '@2:CS54'; -- отдельные классы с углубленным изучением предметов
  VAL = 2;
  IF(V1 <> 964) THEN
  SELECT FIRST 1 1
  FROM LINKS L7
  JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_TYPE_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
  JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_TYPE_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
  JOIN VALL V591 ON V591.OBJ_ID = L9.OBJ_ID AND V591.PARAM_ID = 591 AND V591.IS_DEL = 0 AND V591.LISTVAL_ID <> 1731
  WHERE L7.PARENT_ID = :I$OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
  INTO :VAL;
  IF(VAL = '1') THEN V = V + 1;
  SUSPEND;

  TAG_NAME = '@2:CS55'; -- гимназия
  IF(V1 IN (959, 970)) THEN BEGIN VAL = 1; V = V + 1; END ELSE VAL = 2;
  SUSPEND;

  TAG_NAME = '@2:CS55'; -- гимназические классы НЕТ
  VAL = 2;
  SUSPEND;

  TAG_NAME = '@2:P57'; -- лицей
  IF(V1 IN (960, 971)) THEN BEGIN VAL = 1; V = V + 1; END ELSE VAL = 2;
  SUSPEND;

  TAG_NAME = '@2:CS58'; -- лицейские классы НЕТ
  VAL = 2;
  SUSPEND;

  TAG_NAME = '@2:CS59'; -- президентское суворовское училище НЕТ
  VAL = 2;
  SUSPEND;

  TAG_NAME = '@2:CS61'; -- суворовское училище
  IF(V1 = 989) THEN BEGIN VAL = 1; V = V + 1; END ELSE VAL = 2;
  SUSPEND;

  TAG_NAME = '@2:CS62'; -- нахимовское училище
  IF(V1 = 990) THEN BEGIN VAL = 1; V = V + 1; END ELSE VAL = 2;
  SUSPEND;

  TAG_NAME = '@2:CS63'; -- морской кадетский корпус
  VAL = 2;
  SUSPEND;

  TAG_NAME = '@2:CS54'; -- кадетский корпус
  IF(V1 IN (988, 991)) THEN BEGIN VAL = 1; V = V + 1; END ELSE VAL = 2;
  SUSPEND;

  TAG_NAME = '@2:CS65'; -- кадетская школа
  IF(V1 IN (968, 973)) THEN BEGIN VAL = 1; V = V + 1; END ELSE VAL = 2;
  SUSPEND;

  TAG_NAME = '@2:CS68'; -- Другие
  VAL = 2;
  SUSPEND;

  TAG_NAME = '@2:CS26'; -- Есть особенности
  IF(V > 0) THEN VAL = 1; ELSE VAL = 2;
  SUSPEND;

  TAG_NAME = '@2:CS69'; -- Нет особенностей
  IF(V = 0) THEN VAL = 1; ELSE VAL = 2;
  SUSPEND;

  -------------------------
  -- Формирование промежуточных данных по учащимся и классам
  DELETE FROM REPORT_D12 WHERE 1 = 1;

  FOR
      SELECT DISTINCT M.PERSON_ID
      FROM PERSON_MOVEMENTS M
      JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
      WHERE M.DATE_DEL IS NULL AND M.DATE_IN <= :V$DATE AND (M.DATE_OUT IS NULL OR M.DATE_OUT > :V$DATE)
      INTO :V$OBJ_ID
  DO
  BEGIN

      -- Где учащийся находился на 20.09 ?
      -- Предполагается, что ОВЗшность класса меняться не должна, а при смене типа старый класс распускается, и создается новый другого типа
      V$GRADE_ID = NULL;
      V$STAGE_ID = NULL;
      V$LEVEL_ID = NULL;
      V = NULL;

      SELECT FIRST 1 M.GROUP_ID, M.STAGE_ID, M.PLAN_STAGES, M.STAGE_YEAR, IIF(V592.LISTVAL_ID = 13275, 1, 0), IIF(COALESCE(V1362.LISTVAL_ID, 3) = 3, 0, 1)
      FROM PERSON_MOVEMENTS M
      JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
      LEFT JOIN VALL V592 ON V592.OBJ_ID = M.GROUP_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0
      LEFT JOIN VALL V1362 ON V1362.OBJ_ID = M.GROUP_ID AND V1362.PARAM_ID = 1362 AND V1362.IS_DEL = 0
      WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :V$OBJ_ID AND M.DATE_IN <= :V$DATE AND (M.DATE_OUT IS NULL OR M.DATE_OUT > :V$DATE)
      INTO :V$GRADE_ID, :V$STAGE_ID, :V$PS, :V$OVZ, :V$SY, :V;

      SELECT FIRST 1 V43.LISTVAL_ID
      FROM LINKS LP8
      JOIN LINKS LP7 ON LP7.OBJ_ID = LP8.PARENT_ID AND LP7.PARENT_TYPE_ID = 7 AND LP7.DATE_DEL IS NULL
      JOIN VALL V43 ON V43.OBJ_ID = LP7.PARENT_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0
      WHERE LP8.OBJ_ID = :V$GRADE_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
      INTO :V$LEVEL_ID;

      IF(V$LEVEL_ID = 22) THEN V$LEVEL_ID = 1;
      ELSE IF(V$LEVEL_ID = 26) THEN V$LEVEL_ID = 2;
      ELSE IF(V$LEVEL_ID = 27) THEN V$LEVEL_ID = 3;
      ELSE V$LEVEL_ID = 0;

      -- Обычные классы и классы первого-второго годов обучения - последние кодируем 11XX, 12XX
      -- Классы ОВЗ кодируются как 10XX, если ученик в ОП с дополнительными годами обучения
      -- Если была ошибка, и класс не ОВЗ - игнорируем год в движении
      V$STAGE_ID = V$STAGE_ID - 36;
      IF(V$OVZ = 1) THEN BEGIN
        IF(V$SY IS NULL) THEN
        BEGIN
          IF((V$STAGE_ID IN (1, 2, 3, 4) AND V$PS > 4) OR (V$STAGE_ID IN (5, 6, 7, 8, 9) AND V$PS > 5) OR (V$STAGE_ID IN (10, 11) AND V$PS > 2)) THEN V$STAGE_ID = 1000 + V$STAGE_ID;
        END
        ELSE
        BEGIN
          V$STAGE_ID = V$STAGE_ID + 1000 + 100 * V$SY;
        END
      END
      IF(V = 1 AND V <= 12) THEN V$STAGE_ID = - V$STAGE_ID; -- инвертируем знак для выпускных классов, нулевой точно не выпускной

      -- Привязка к ОП+УП через реестр движения, приоритет по дате прихода в ГУП
      V$OP_ID = NULL;
      V$GROUP_ID = NULL;
      V$IS_PERSONAL = 0;

      SELECT FIRST 1 M.GROUP_ID
      FROM PERSON_MOVEMENTS M
      JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 256
      WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :V$OBJ_ID AND M.DATE_IN <= :V$DATE AND (M.DATE_OUT IS NULL OR M.DATE_OUT > :V$DATE)
      INTO :V$GROUP_ID;

      SELECT FIRST 1 LP57.PARENT_ID, LP400.PARENT_ID, IIF(COALESCE(V3016.LISTVAL_ID, 5465) = 5465, 0, 1)
      FROM LINKS LP54
      JOIN LINKS LP400 ON LP400.OBJ_ID = LP54.PARENT_ID AND LP400.PARENT_TYPE_ID = 400 AND LP400.DATE_DEL IS NULL
      LEFT JOIN VALL V3016 ON V3016.OBJ_ID = LP400.PARENT_ID AND V3016.PARAM_ID = 3016 AND V3016.IS_DEL = 0
      JOIN LINKS LP57 ON LP57.OBJ_ID = LP400.PARENT_ID AND LP57.PARENT_TYPE_ID = 57 AND LP57.DATE_DEL IS NULL
      WHERE LP54.OBJ_ID = :V$GROUP_ID AND LP54.PARENT_TYPE_ID = 54
      INTO :V$OP_ID, :V$PLAN_ID, :V$IS_PERSONAL;

      -- SCHOOL_ID - ID УП
      -- CLASS_ID - ID класса
      -- CLASS_TYPE_ID - ID ОП
      -- ROW_NUM - этап обучения (параллель) (L8) - перекодируем в 0..12, для выпускных классов минусовой знак
      -- C1 = уровень образования (L7) - перекодируем в 1/2/3
      -- C2 = индивидуальный УП (0 / 1)
      -- C3 = возраст на 1 января

      V = (SELECT AGE FROM CALC_AGE((SELECT VAL FROM VALD WHERE OBJ_ID = :V$OBJ_ID AND PARAM_ID = 89 AND IS_DEL = 0), '01.01.' || (:V$YEAR + 1)));

      IF(V$PLAN_ID IS NULL) THEN V$PLAN_ID = 0; -- затычка для предотвращения NULL

      INSERT INTO REPORT_D12
      (SCHOOL_ID, SCHOLAR_ID, CLASS_ID, CLASS_TYPE_ID, ROW_NUM, C1, C2, C3)
      VALUES (:V$PLAN_ID, :V$OBJ_ID, :V$GRADE_ID, :V$OP_ID, :V$STAGE_ID, :V$LEVEL_ID, :V$IS_PERSONAL, :V);

  END

  --V = (select count(*) from REPORT_D12 where C1 <> 1);
  --exception data_error 'zz ' || V;

  -------------------------
  -- Раздел 1.3 (численность обучающихся)
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R13 INTO :TAG_NAME, :VAL DO SUSPEND;

  -------------------------
  -- Разделы 2.1 (численность обучающихся и классы по параллелям)
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R211(NULL) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R212(NULL) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R213(NULL) INTO :TAG_NAME, :VAL DO SUSPEND;

  -------------------------
  -- Раздел 2.2 (численность обучающихся и классы по параллелям, обычные классы с детьми с ОВЗ), теперь без учета формы
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R22(NULL) INTO :TAG_NAME, :VAL DO SUSPEND;

  -- Раздел 2.3 (обучающиеся по сетевым, индивидуальным и прочим особым УП), теперь без учета формы
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R23(NULL) INTO :TAG_NAME, :VAL DO SUSPEND;

  -- Разделы 2.4 (количество классов)
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R24(:I$OBJ_ID, 5418) INTO :TAG_NAME, :VAL DO
  BEGIN
    SUSPEND;
    -- Столбец 4 повторяет столбец 3
    TAG_NAME = REPLACE(TAG_NAME, 'BS', 'CI');
    SUSPEND;
  END
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R24(:I$OBJ_ID, 5419) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R24(:I$OBJ_ID, 5420) INTO :TAG_NAME, :VAL DO SUSPEND;

  -- Раздел 2.5.X.X (численность окончивших за прошлый год)
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R251(:I$OBJ_ID, NULL) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R252(:I$OBJ_ID, NULL) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R253(:I$OBJ_ID, NULL) INTO :TAG_NAME, :VAL DO SUSPEND;

  -- Раздел 2.6 (результаты ГИА)

  -- Раздел 2.7 (разбивка учащихся по возрасту) - был 2.14
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R27(:I$OBJ_ID, 0) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R27(:I$OBJ_ID, 1) INTO :TAG_NAME, :VAL DO SUSPEND;

  -- Раздел 2.8 (выбытие обучающихся)
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R28(:I$OBJ_ID) INTO :TAG_NAME, :VAL DO SUSPEND;

  -- Раздел 2.9 (сменность занятий и ГПД)
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R29(:I$OBJ_ID) INTO :TAG_NAME, :VAL DO SUSPEND;
  /*
  -- Раздел 2.10 (иностранные языки)
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R210(5418) INTO :TAG_NAME, :VAL DO SUSPEND;
  --FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R210(5419) INTO :TAG_NAME, :VAL DO SUSPEND;
  --FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R210(5420) INTO :TAG_NAME, :VAL DO SUSPEND;

  -- Раздел 2.11 (углубленное изучение предметов)

  -- Раздел 2.12 (профили)

  -- Раздел 2.13 (профессиональное обучение) - не заполняем

  -- Раздел 2.15 (разбивка учащихся по языку обучения)
  */
  -------------------------
  -- Формирование промежуточных данных по сотрудникам
  DELETE FROM REPORT_D12 WHERE 1 = 1;

  FOR
      -- действующие учащиеся
      SELECT L14.OBJ_ID
      FROM LINKS L14
      WHERE L14.PARENT_ID = :I$OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
      -- уволенные
      UNION
      SELECT L14.OBJ_ID
      FROM LINKS L84
      JOIN LINKS L14 ON L14.PARENT_ID = L84.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
      WHERE L84.PARENT_ID = :I$OBJ_ID AND L84.OBJ_TYPE_ID = 84 AND L84.DATE_DEL IS NULL
      INTO :V$OBJ_ID
  DO
  BEGIN

      -- Была ли действующая ставка на указанную дату ?
      V = 0;
      SELECT FIRST 1 1
      FROM LINKS L15
      JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0 AND V73.VAL <= :V$DATE
      LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
      WHERE L15.PARENT_ID = :V$OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL AND (V74.VAL IS NULL OR V74.VAL >= :V$DATE)
      INTO :V;

      IF(V > 0) THEN
      BEGIN

          -- CLASS_ID - 0
          -- CLASS_TYPE_ID - 0
          -- ROW_NUM - внешний совместитель (0 / 1)
          -- C1 = общий стаж
          -- C2 = педагогический стаж
          -- C3 = возраст на 1 января

          V = (SELECT AGE FROM CALC_AGE((SELECT VAL FROM VALD WHERE OBJ_ID = :V$OBJ_ID AND PARAM_ID = 241 AND IS_DEL = 0), '01.01.' || (:V$YEAR + 1)));

          -- Подсчет стажа
          V1 = 0;
          V2 = 0;
          FOR
              SELECT V465.LISTVAL_ID, V466.VAL, V467.VAL
              FROM LINKS L85
              JOIN VALL V465 ON V465.OBJ_ID = L85.OBJ_ID AND V465.PARAM_ID = 465 AND V465.IS_DEL = 0 AND V465.LISTVAL_ID IN (941, 942)
              JOIN VALD V466 ON V466.OBJ_ID = L85.OBJ_ID AND V466.PARAM_ID = 466 AND V466.IS_DEL = 0 AND V466.VAL <= :V$DATE
              LEFT JOIN VALD V467 ON V467.OBJ_ID = L85.OBJ_ID AND V467.PARAM_ID = 467 AND V467.IS_DEL = 0
              WHERE L85.PARENT_ID = :V$OBJ_ID AND L85.OBJ_TYPE_ID = 85 AND L85.DATE_DEL IS NULL
              INTO :V$STAGE_ID, :D1, :D2
          DO
          BEGIN
              IF(D2 IS NULL) THEN D2 = V$DATE;
              VX = (SELECT DAYS360_COUNT FROM GET_DAYS360_COUNT(:D1, :D2));
              IF(V$STAGE_ID = 941) THEN V1 = V1 + VX; ELSE V2 = V2 + VX;
          END

          INSERT INTO REPORT_D12
          (SCHOOL_ID, SCHOLAR_ID, CLASS_ID, CLASS_TYPE_ID, ROW_NUM, C1, C2, C3)
          VALUES (:I$OBJ_ID, :V$OBJ_ID, 0, 0, 0, :V1 / 360, :V2 / 360, :V);

      END

  END

  -- Раздел 3 (сотрудники)
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R31 INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R32 INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R331 INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R34(:I$OBJ_ID) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R35 INTO :TAG_NAME, :VAL DO SUSPEND;

  -------------------------
  TAG_NAME = '@1';
  VAL = '';
  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE REPORT_OO1_IN_VCS (
    I$PERSON_ID BIGINT,
    I$DATE_START DATE,
    I$DATE_END DATE)
RETURNS (
    GROUP_ID BIGINT,
    SUBGROUP_ID BIGINT,
    POSITION_ID BIGINT,
    POSITION_TYPE BIGINT,
    IS_EDU SMALLINT,
    RATE DOUBLE PRECISION)
AS
begin

  FOR
      SELECT V63.LISTVAL_ID, V64.LISTVAL_ID, V58.LISTVAL_ID, V71.VAL, V587.LISTVAL_ID, IIF(T.SORT_ORDER = 2, 1, 0)
      FROM LINKS L15
      JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0 AND V73.VAL >= :I$DATE_START AND V73.VAL < :I$DATE_END
      JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
      JOIN VALL V63 ON V63.OBJ_ID = LP13.PARENT_ID AND V63.PARAM_ID = 63 AND V63.IS_DEL = 0
      JOIN VALL V64 ON V64.OBJ_ID = LP13.PARENT_ID AND V64.PARAM_ID = 64 AND V64.IS_DEL = 0
      JOIN VALL V58 ON V58.OBJ_ID = LP13.PARENT_ID AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0
      JOIN VALF V71 ON V71.OBJ_ID = L15.OBJ_ID AND V71.PARAM_ID = 71 AND V71.IS_DEL = 0
      JOIN VALL V587 ON V587.OBJ_ID = L15.OBJ_ID AND V587.PARAM_ID = 587 AND V587.IS_DEL = 0
      LEFT JOIN DO_FUNC(LP13.PARENT_ID, 400) T ON 1 = 1
      WHERE L15.PARENT_ID = :I$PERSON_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
      INTO :GROUP_ID, :SUBGROUP_ID, :POSITION_ID, :RATE, :POSITION_TYPE, :IS_EDU
  DO
  BEGIN
      SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE REPORT_OO1_OUT_VCS (
    I$PERSON_ID BIGINT,
    I$DATE_START DATE,
    I$DATE_END DATE)
RETURNS (
    GROUP_ID BIGINT,
    SUBGROUP_ID BIGINT,
    POSITION_ID BIGINT,
    POSITION_TYPE BIGINT,
    IS_EDU SMALLINT,
    REASON_ID BIGINT,
    RATE DOUBLE PRECISION)
AS
begin

  FOR
      SELECT V63.LISTVAL_ID, V64.LISTVAL_ID, V58.LISTVAL_ID, V71.VAL, V587.LISTVAL_ID, IIF(T.SORT_ORDER = 2, 1, 0), V461.LISTVAL_ID
      FROM LINKS L15
      JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0 AND V74.VAL >= :I$DATE_START AND V74.VAL < :I$DATE_END
      JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
      JOIN VALL V63 ON V63.OBJ_ID = LP13.PARENT_ID AND V63.PARAM_ID = 63 AND V63.IS_DEL = 0
      JOIN VALL V64 ON V64.OBJ_ID = LP13.PARENT_ID AND V64.PARAM_ID = 64 AND V64.IS_DEL = 0
      JOIN VALL V58 ON V58.OBJ_ID = LP13.PARENT_ID AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0
      JOIN VALF V71 ON V71.OBJ_ID = L15.OBJ_ID AND V71.PARAM_ID = 71 AND V71.IS_DEL = 0
      JOIN VALL V587 ON V587.OBJ_ID = L15.OBJ_ID AND V587.PARAM_ID = 587 AND V587.IS_DEL = 0
      LEFT JOIN VALL V461 ON V461.OBJ_ID = L15.OBJ_ID AND V461.PARAM_ID = 461 AND V461.IS_DEL = 0
      LEFT JOIN DO_FUNC(LP13.PARENT_ID, 400) T ON 1 = 1
      WHERE L15.PARENT_ID = :I$PERSON_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
      INTO :GROUP_ID, :SUBGROUP_ID, :POSITION_ID, :RATE, :POSITION_TYPE, :IS_EDU, :REASON_ID
  DO
  BEGIN
      SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE REPORT_OO1_R13 RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(100))
AS
begin

  -- Всего
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R13_ROW(76, NULL, NULL) INTO :TAG_NAME, :VAL DO SUSPEND;

  -- Начальное
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R13_ROW(77, 1, NULL) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R13_ROW(78, 1, 11188) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R13_ROW(79, 1, 11192) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R13_ROW(81, 1, 11191, 11193) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R13_ROW(82, 1, 11190) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R13_ROW(83, 1, 11189) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R13_ROW(84, 1, 11195) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R13_ROW(85, 1, 11194) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R13_ROW(86, 1, 11196) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R13_ROW(87, 1, 13269) INTO :TAG_NAME, :VAL DO SUSPEND;

  -- Основное
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R13_ROW(88, 2, NULL) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R13_ROW(89, 2, 11188) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R13_ROW(90, 2, 11192) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R13_ROW(92, 2, 11191, 11193) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R13_ROW(93, 2, 11190) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R13_ROW(94, 2, 11189) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R13_ROW(95, 2, 11195) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R13_ROW(96, 2, 11194) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R13_ROW(97, 2, 11196) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R13_ROW(98, 2, 13269) INTO :TAG_NAME, :VAL DO SUSPEND;

  -- Среднее
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R13_ROW(99, 3, NULL) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R13_ROW(100, 3, 11188) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R13_ROW(101, 3, 11192) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R13_ROW(103, 3, 11191, 11193) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R13_ROW(104, 3, 11190) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R13_ROW(105, 3, 11189) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R13_ROW(106, 3, 11195) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R13_ROW(107, 3, 11194) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R13_ROW(108, 3, 11196) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R13_ROW(109, 3, 13269) INTO :TAG_NAME, :VAL DO SUSPEND;

  -- Умственная отсталость
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R13_ROW(110, NULL, 11197, 11198) INTO :TAG_NAME, :VAL DO SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE REPORT_OO1_R13_ROW (
    I$ROW SMALLINT,
    I$STAGE_ID INTEGER,
    I$ADAPT_ID BIGINT,
    I$ADAPT_ID2 BIGINT = null)
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(100))
AS
begin

  -- STAGE это уровень образования 1-2-3

  -- Всего
  TAG_NAME = '@2:AS' || I$ROW || ':I';
  SELECT COUNT(*)
  FROM REPORT_D12 D
  LEFT JOIN VALL V2379 ON V2379.OBJ_ID = D.CLASS_TYPE_ID AND V2379.PARAM_ID = 2379 AND V2379.IS_DEL = 0
  WHERE (:I$STAGE_ID IS NULL OR D.C1 = :I$STAGE_ID) AND (
      :I$ADAPT_ID IS NULL OR                                -- всего
      :I$ADAPT_ID = 11188 AND V2379.LISTVAL_ID <> 11187 OR  -- адаптированные всего
      :I$ADAPT_ID = V2379.LISTVAL_ID OR                     -- конкретный вид
      :I$ADAPT_ID2 = V2379.LISTVAL_ID
  )
  INTO :VAL;
  SUSPEND;

  -- Сетевые
  TAG_NAME = '@2:BJ' || I$ROW || ':I';
  SELECT COUNT(*)
  FROM REPORT_D12 D
  JOIN VALL V1891 ON V1891.OBJ_ID = D.CLASS_TYPE_ID AND V1891.PARAM_ID = 1891 AND V1891.IS_DEL = 0 AND V1891.LISTVAL_ID = 2
  LEFT JOIN VALL V2379 ON V2379.OBJ_ID = D.CLASS_TYPE_ID AND V2379.PARAM_ID = 2379 AND V2379.IS_DEL = 0
  WHERE (:I$STAGE_ID IS NULL OR D.C1 = :I$STAGE_ID) AND (
      :I$ADAPT_ID IS NULL OR                                -- всего
      :I$ADAPT_ID = 11188 AND V2379.LISTVAL_ID <> 11187 OR  -- адаптированные всего
      :I$ADAPT_ID = V2379.LISTVAL_ID OR                     -- конкретный вид
      :I$ADAPT_ID2 = V2379.LISTVAL_ID
  )
  INTO :VAL;
  SUSPEND;

  -- Электронное обучение

  -- Дистанционные технологии

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE REPORT_OO1_R210 (
    I$STUDY_TYPE BIGINT)
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(100))
AS
begin

  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R210_COL(:I$STUDY_TYPE, 'P', 1) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R210_COL(:I$STUDY_TYPE, 'Q', 2) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R210_COL(:I$STUDY_TYPE, 'R', 3) INTO :TAG_NAME, :VAL DO SUSPEND;

  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R210_COL(:I$STUDY_TYPE, 'S', 4) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R210_COL(:I$STUDY_TYPE, 'T', 5) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R210_COL(:I$STUDY_TYPE, 'U', 6) INTO :TAG_NAME, :VAL DO SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE REPORT_OO1_R210_COL (
    I$STUDY_TYPE BIGINT,
    I$COL VARCHAR(10),
    I$CS SMALLINT)
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(100))
AS
declare variable V$PREFIX varchar(10);
declare variable V$STAGE_ID bigint;
declare variable V$PLAN_ID bigint;
declare variable V$PERSON_ID bigint;
declare variable V$STAGE_NUM bigint;
declare variable N integer;
declare variable V$N1 integer;
declare variable V$N2 integer;
declare variable V$N3 integer;
declare variable V$N4 integer;
declare variable V$N5 integer;
declare variable V$N6 integer;
declare variable V$N7 integer;
declare variable V$N8 integer;
declare variable V$N9 integer;
declare variable V$N10 integer;
declare variable V$N11 integer;
declare variable V$N12 integer;
declare variable V$N13 integer;
declare variable V$N14 integer;
declare variable V$N15 integer;
declare variable V$N16 integer;
begin

  IF(I$STUDY_TYPE = 5418) THEN V$PREFIX = '@45:';
  ELSE IF(I$STUDY_TYPE = 5419) THEN V$PREFIX = '@46:';
  ELSE IF(I$STUDY_TYPE = 5420) THEN V$PREFIX = '@47:';

  IF(I$CS IN (1, 4)) THEN V$STAGE_ID = 22;
  ELSE IF(I$CS IN (2, 5)) THEN V$STAGE_ID = 26;
  ELSE IF(I$CS IN (3, 6)) THEN V$STAGE_ID = 27;

  -- 11-е классы считаются отдельно выпускные и не-выпускные
  V$N1 = 0;
  V$N2 = 0;
  V$N3 = 0;
  V$N4 = 0;
  V$N5 = 0;
  V$N6 = 0;
  V$N7 = 0;
  V$N8 = 0;
  V$N9 = 0;
  V$N10 = 0;
  V$N11 = 0;
  V$N12 = 0;
  V$N13 = 0;
  V$N14 = 0;
  V$N15 = 0;
  V$N16 = 0;

  FOR
      SELECT D.SCHOOL_ID, ABS(D.ROW_NUM), D.SCHOLAR_ID
      FROM REPORT_D12 D
      JOIN LINKS LP8 ON LP8.OBJ_ID = D.CLASS_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
      JOIN LINKS LP7 ON LP7.OBJ_ID = LP8.PARENT_ID AND LP7.PARENT_TYPE_ID = 7 AND LP7.DATE_DEL IS NULL
      JOIN VALL V43 ON V43.OBJ_ID = LP7.PARENT_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0 AND V43.LISTVAL_ID = :V$STAGE_ID
      JOIN VALL V80 ON V80.OBJ_ID = D.SCHOLAR_ID AND V80.PARAM_ID = 80 AND V80.IS_DEL = 0 AND V80.LISTVAL_ID = :I$STUDY_TYPE
      JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND
        (
            (:I$CS IN (1, 2, 3) AND V592.LISTVAL_ID = 197) OR
            (:I$CS IN (4, 5, 6) AND V592.LISTVAL_ID NOT IN (197, 198))
        )
      INTO :V$PLAN_ID, :V$STAGE_NUM, :V$PERSON_ID
  DO
  BEGIN

      IF(V$STAGE_NUM = 0) THEN V$STAGE_NUM = 12765; ELSE V$STAGE_NUM = V$STAGE_NUM + 36;

      /*-- Идем по всем предметам УП
      FOR
          SELECT DISTINCT L51.OBJ_ID
          FROM LINKS L54
          JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0 AND V381.LISTVAL_ID = :V$STAGE_NUM
          JOIN LINKS L56 ON L56.PARENT_ID = L54.OBJ_ID AND L56.OBJ_TYPE_ID = 56 AND L56.DATE_DEL IS NULL
          JOIN LINKS L49 ON L49.PARENT_ID = L54.PARENT_ID AND L49.OBJ_TYPE_ID = 49 AND L49.DATE_DEL IS NULL
          JOIN LINKS L56_2 ON L56_2.PARENT_ID = L49.OBJ_ID AND L56_2.OBJ_ID = L56.OBJ_ID AND L56_2.DATE_DEL IS NULL
          JOIN LINKS L51 ON L51.PARENT_ID = L49.OBJ_ID AND L51.OBJ_TYPE_ID = 51 AND L51.DATE_DEL IS NULL
          JOIN LINKS L56_3 ON L56_3.PARENT_ID = L51.OBJ_ID AND L56_3.OBJ_ID = L56.OBJ_ID AND L56_3.DATE_DEL IS NULL
          JOIN VALI V385 ON V385.OBJ_ID = L56.OBJ_ID AND V385.PARAM_ID = 385 AND V385.IS_DEL = 0 AND V385.VAL > 0
          JOIN LINKS L302 ON L302.OBJ_ID = L51.OBJ_ID AND L302.OBJ_TYPE_ID = 302 AND L302.DATE_DEL IS NULL
          WHERE L54.PARENT_ID = :V$PLAN_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
          INTO :
      DO
      BEGIN
      END

      IF() THEN
      BEGIN
          V$N1 = V$N1 + N;
          V$N2 = V$N2 + N;
      END*/

  END

  TAG_NAME = V$PREFIX || I$COL || '21:I';
  VAL = V$N1;
  SUSPEND;

  TAG_NAME = V$PREFIX || I$COL || '22:I';
  VAL = V$N2;
  SUSPEND;

  TAG_NAME = V$PREFIX || I$COL || '23:I';
  VAL = V$N3;
  SUSPEND;

  TAG_NAME = V$PREFIX || I$COL || '24:I';
  VAL = V$N4;
  SUSPEND;

  TAG_NAME = V$PREFIX || I$COL || '25:I';
  VAL = V$N5;
  SUSPEND;

  TAG_NAME = V$PREFIX || I$COL || '26:I';
  VAL = V$N6;
  SUSPEND;

  TAG_NAME = V$PREFIX || I$COL || '27:I';
  VAL = V$N7;
  SUSPEND;

  TAG_NAME = V$PREFIX || I$COL || '28:I';
  VAL = V$N8;
  SUSPEND;

  TAG_NAME = V$PREFIX || I$COL || '29:I';
  VAL = V$N9;
  SUSPEND;

  TAG_NAME = V$PREFIX || I$COL || '30:I';
  VAL = V$N10;
  SUSPEND;

  TAG_NAME = V$PREFIX || I$COL || '31:I';
  VAL = V$N11;
  SUSPEND;

  TAG_NAME = V$PREFIX || I$COL || '32:I';
  VAL = V$N12;
  SUSPEND;

  TAG_NAME = V$PREFIX || I$COL || '33:I';
  VAL = V$N13;
  SUSPEND;

  TAG_NAME = V$PREFIX || I$COL || '34:I';
  VAL = V$N14;
  SUSPEND;

  TAG_NAME = V$PREFIX || I$COL || '35:I';
  VAL = V$N15;
  SUSPEND;

  TAG_NAME = V$PREFIX || I$COL || '36:I';
  VAL = V$N16;
  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE REPORT_OO1_R211 (
    I$STUDY_TYPE BIGINT)
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(100))
AS
begin

  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R211_COL(:I$STUDY_TYPE, 'BJ', NULL) INTO :TAG_NAME, :VAL DO SUSPEND;

  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R211_COL(:I$STUDY_TYPE, 'BQ', 1) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R211_COL(:I$STUDY_TYPE, 'BX', 2) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R211_COL(:I$STUDY_TYPE, 'CE', 3) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R211_COL(:I$STUDY_TYPE, 'CL', 4) INTO :TAG_NAME, :VAL DO SUSPEND;

  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R211_COL(:I$STUDY_TYPE, 'CS', 5) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R211_COL(:I$STUDY_TYPE, 'CZ', 6) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R211_COL(:I$STUDY_TYPE, 'DG', 7) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R211_COL(:I$STUDY_TYPE, 'DN', 8) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R211_COL(:I$STUDY_TYPE, 'DU', 9) INTO :TAG_NAME, :VAL DO SUSPEND;

  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R211_COL(:I$STUDY_TYPE, 'EB', 10) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R211_COL(:I$STUDY_TYPE, 'EI', -11) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R211_COL(:I$STUDY_TYPE, 'ET', 11) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R211_COL(:I$STUDY_TYPE, 'FA', 12) INTO :TAG_NAME, :VAL DO SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE REPORT_OO1_R211_COL (
    I$STUDY_TYPE BIGINT,
    I$COL VARCHAR(10),
    I$GRADE SMALLINT)
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(100))
AS
declare variable V$PREFIX varchar(10);
declare variable V$GRADE2 integer;
declare variable V$YEAR integer;
declare variable V$DATE date;
begin

  -- Только для общеобразовательных классов
  -- STUDY_TYPE игнорируем

  V$YEAR = EXTRACT(YEAR FROM CURRENT_DATE);
  IF(EXTRACT(MONTH FROM CURRENT_DATE) < 9) THEN V$YEAR = V$YEAR - 1;
  V$DATE = '20.09.' || V$YEAR;

  V$PREFIX = '@3:';

  -- 11-е классы считаются отдельно выпускные и не-выпускные
  IF(I$GRADE NOT IN (11, -11)) THEN V$GRADE2 = - I$GRADE;

  -- Классов без углубленного изучения предметов
  TAG_NAME = V$PREFIX || I$COL || '11:I';
  SELECT COUNT(DISTINCT D.CLASS_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 197
  LEFT JOIN VALL V591 ON V591.OBJ_ID = D.CLASS_ID AND V591.PARAM_ID = 591 AND V591.IS_DEL = 0
  WHERE (:I$GRADE IS NULL OR D.ROW_NUM = :I$GRADE OR D.ROW_NUM = :V$GRADE2)
      AND (V591.LISTVAL_ID IS NULL OR V591.LISTVAL_ID = 1731)
  INTO :VAL;
  SUSPEND;

  -- + Обучающихся там
  TAG_NAME = V$PREFIX || I$COL || '12:I';
  SELECT COUNT(*)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 197
  LEFT JOIN VALL V591 ON V591.OBJ_ID = D.CLASS_ID AND V591.PARAM_ID = 591 AND V591.IS_DEL = 0
  WHERE (:I$GRADE IS NULL OR D.ROW_NUM = :I$GRADE OR D.ROW_NUM = :V$GRADE2)
      AND (V591.LISTVAL_ID IS NULL OR V591.LISTVAL_ID = 1731)
  INTO :VAL;
  SUSPEND;

  -- Классов с углубленным изучением предметов
  TAG_NAME = V$PREFIX || I$COL || '13:I';
  SELECT COUNT(DISTINCT D.CLASS_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 197
  LEFT JOIN VALL V591 ON V591.OBJ_ID = D.CLASS_ID AND V591.PARAM_ID = 591 AND V591.IS_DEL = 0
  WHERE (:I$GRADE IS NULL OR D.ROW_NUM = :I$GRADE OR D.ROW_NUM = :V$GRADE2)
      AND V591.LISTVAL_ID <> 1731
  INTO :VAL;
  SUSPEND;

  -- + Обучающихся там
  TAG_NAME = V$PREFIX || I$COL || '14:I';
  SELECT COUNT(*)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 197
  LEFT JOIN VALL V591 ON V591.OBJ_ID = D.CLASS_ID AND V591.PARAM_ID = 591 AND V591.IS_DEL = 0
  WHERE (:I$GRADE IS NULL OR D.ROW_NUM = :I$GRADE OR D.ROW_NUM = :V$GRADE2)
      AND V591.LISTVAL_ID <> 1731
  INTO :VAL;
  SUSPEND;

  -- Гимназический класс

  -- Лицейский класс

  -- Сумма по всем видам классов
  TAG_NAME = V$PREFIX || I$COL || '19:I';
  SELECT COUNT(DISTINCT D.CLASS_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 197
  WHERE (:I$GRADE IS NULL OR D.ROW_NUM = :I$GRADE OR D.ROW_NUM = :V$GRADE2)
  INTO :VAL;
  SUSPEND;

  -- + Обучающихся там
  TAG_NAME = V$PREFIX || I$COL || '20:I';
  SELECT COUNT(*)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 197
  WHERE (:I$GRADE IS NULL OR D.ROW_NUM = :I$GRADE OR D.ROW_NUM = :V$GRADE2)
  INTO :VAL;
  SUSPEND;

  -- + Обучающихся очно
  TAG_NAME = V$PREFIX || I$COL || '21:I';
  SELECT COUNT(*)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 197
  JOIN VALL V80 ON V80.OBJ_ID = D.SCHOLAR_ID AND V80.PARAM_ID = 80 AND V80.IS_DEL = 0 AND V80.LISTVAL_ID = 5418
  WHERE (:I$GRADE IS NULL OR D.ROW_NUM = :I$GRADE OR D.ROW_NUM = :V$GRADE2)
  INTO :VAL;
  SUSPEND;

  -- + Обучающихся очно-заочно
  TAG_NAME = V$PREFIX || I$COL || '23:I';
  SELECT COUNT(*)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 197
  JOIN VALL V80 ON V80.OBJ_ID = D.SCHOLAR_ID AND V80.PARAM_ID = 80 AND V80.IS_DEL = 0 AND V80.LISTVAL_ID = 5419
  WHERE (:I$GRADE IS NULL OR D.ROW_NUM = :I$GRADE OR D.ROW_NUM = :V$GRADE2)
  INTO :VAL;
  SUSPEND;

  -- + Обучающихся заочно
  TAG_NAME = V$PREFIX || I$COL || '24:I';
  SELECT COUNT(*)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 197
  JOIN VALL V80 ON V80.OBJ_ID = D.SCHOLAR_ID AND V80.PARAM_ID = 80 AND V80.IS_DEL = 0 AND V80.LISTVAL_ID = 5420
  WHERE (:I$GRADE IS NULL OR D.ROW_NUM = :I$GRADE OR D.ROW_NUM = :V$GRADE2)
  INTO :VAL;
  SUSPEND;

  -- + Воспитанники (считаем что у нас все такие)
  TAG_NAME = V$PREFIX || I$COL || '25:I';
  SELECT COUNT(*)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 197
  WHERE (:I$GRADE IS NULL OR D.ROW_NUM = :I$GRADE OR D.ROW_NUM = :V$GRADE2)
  INTO :VAL;
  SUSPEND;

  -- + Девочки
  TAG_NAME = V$PREFIX || I$COL || '27:I';
  SELECT COUNT(*)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 197
  JOIN VALL V88 ON V88.OBJ_ID = D.SCHOLAR_ID AND V88.PARAM_ID = 88 AND V88.IS_DEL = 0 AND V88.LISTVAL_ID = 182
  WHERE (:I$GRADE IS NULL OR D.ROW_NUM = :I$GRADE OR D.ROW_NUM = :V$GRADE2)
  INTO :VAL;
  SUSPEND;

  -- + Оставленные на второй год обучения
  TAG_NAME = V$PREFIX || I$COL || '28:I';
  SELECT COUNT(*)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 197
  LEFT JOIN IS_SECOND_YEAR(D.SCHOLAR_ID, :V$DATE) SY ON 1 = 1
  WHERE (:I$GRADE IS NULL OR D.ROW_NUM = :I$GRADE OR D.ROW_NUM = :V$GRADE2) AND SY.VAL = 1
  INTO :VAL;
  SUSPEND;

  -- + Учащиеся с ОВЗ всего
  TAG_NAME = V$PREFIX || I$COL || '29:I';
  SELECT COUNT(*)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 197
  JOIN VALL V207 ON V207.OBJ_ID = D.SCHOLAR_ID AND V207.PARAM_ID = 207 AND V207.IS_DEL = 0 AND V207.LISTVAL_ID <> 13289
  WHERE (:I$GRADE IS NULL OR D.ROW_NUM = :I$GRADE OR D.ROW_NUM = :V$GRADE2)
  INTO :VAL;
  SUSPEND;

  -- + Учащиеся с ОВЗ + инвалиды
  TAG_NAME = V$PREFIX || I$COL || '30:I';
  SELECT COUNT(DISTINCT D.SCHOLAR_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 197
  JOIN VALL V207 ON V207.OBJ_ID = D.SCHOLAR_ID AND V207.PARAM_ID = 207 AND V207.IS_DEL = 0 AND V207.LISTVAL_ID <> 13289
  JOIN LINKS L295 ON L295.PARENT_ID = D.SCHOLAR_ID AND L295.OBJ_TYPE_ID = 295 AND L295.DATE_DEL IS NULL
  JOIN VALL V2373 ON V2373.OBJ_ID = L295.OBJ_ID AND V2373.PARAM_ID = 2373 AND V2373.IS_DEL = 0 AND V2373.LISTVAL_ID <> 11171
  LEFT JOIN VALD V2375 ON V2375.OBJ_ID = L295.OBJ_ID AND V2375.PARAM_ID = 2375 AND V2375.IS_DEL = 0
  WHERE (:I$GRADE IS NULL OR D.ROW_NUM = :I$GRADE OR D.ROW_NUM = :V$GRADE2) AND (V2375.VAL IS NULL OR V2375.VAL >= :V$DATE)
  INTO :VAL;
  SUSPEND;

  -- + Учащиеся с ОВЗ + дети-инвалиды
  TAG_NAME = V$PREFIX || I$COL || '31:I';
  SELECT COUNT(DISTINCT D.SCHOLAR_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 197
  JOIN VALL V207 ON V207.OBJ_ID = D.SCHOLAR_ID AND V207.PARAM_ID = 207 AND V207.IS_DEL = 0 AND V207.LISTVAL_ID <> 13289
  JOIN LINKS L295 ON L295.PARENT_ID = D.SCHOLAR_ID AND L295.OBJ_TYPE_ID = 295 AND L295.DATE_DEL IS NULL
  JOIN VALL V2373 ON V2373.OBJ_ID = L295.OBJ_ID AND V2373.PARAM_ID = 2373 AND V2373.IS_DEL = 0 AND V2373.LISTVAL_ID = 11171
  LEFT JOIN VALD V2375 ON V2375.OBJ_ID = L295.OBJ_ID AND V2375.PARAM_ID = 2375 AND V2375.IS_DEL = 0
  WHERE (:I$GRADE IS NULL OR D.ROW_NUM = :I$GRADE OR D.ROW_NUM = :V$GRADE2) AND (V2375.VAL IS NULL OR V2375.VAL >= :V$DATE)
  INTO :VAL;
  SUSPEND;

  -- + Учащиеся без ОВЗ + инвалиды
  TAG_NAME = V$PREFIX || I$COL || '33:I';
  SELECT COUNT(DISTINCT D.SCHOLAR_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 197
  JOIN VALL V207 ON V207.OBJ_ID = D.SCHOLAR_ID AND V207.PARAM_ID = 207 AND V207.IS_DEL = 0 AND V207.LISTVAL_ID = 13289
  JOIN LINKS L295 ON L295.PARENT_ID = D.SCHOLAR_ID AND L295.OBJ_TYPE_ID = 295 AND L295.DATE_DEL IS NULL
  JOIN VALL V2373 ON V2373.OBJ_ID = L295.OBJ_ID AND V2373.PARAM_ID = 2373 AND V2373.IS_DEL = 0 AND V2373.LISTVAL_ID <> 11171
  LEFT JOIN VALD V2375 ON V2375.OBJ_ID = L295.OBJ_ID AND V2375.PARAM_ID = 2375 AND V2375.IS_DEL = 0
  WHERE (:I$GRADE IS NULL OR D.ROW_NUM = :I$GRADE OR D.ROW_NUM = :V$GRADE2) AND (V2375.VAL IS NULL OR V2375.VAL >= :V$DATE)
  INTO :VAL;
  SUSPEND;

  -- + Учащиеся без ОВЗ + дети-инвалиды
  TAG_NAME = V$PREFIX || I$COL || '34:I';
  SELECT COUNT(DISTINCT D.SCHOLAR_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 197
  JOIN VALL V207 ON V207.OBJ_ID = D.SCHOLAR_ID AND V207.PARAM_ID = 207 AND V207.IS_DEL = 0 AND V207.LISTVAL_ID = 13289
  JOIN LINKS L295 ON L295.PARENT_ID = D.SCHOLAR_ID AND L295.OBJ_TYPE_ID = 295 AND L295.DATE_DEL IS NULL
  JOIN VALL V2373 ON V2373.OBJ_ID = L295.OBJ_ID AND V2373.PARAM_ID = 2373 AND V2373.IS_DEL = 0 AND V2373.LISTVAL_ID = 11171
  JOIN VALD V2375 ON V2375.OBJ_ID = L295.OBJ_ID AND V2375.PARAM_ID = 2375 AND V2375.IS_DEL = 0 AND V2375.VAL >= :V$DATE
  WHERE (:I$GRADE IS NULL OR D.ROW_NUM = :I$GRADE OR D.ROW_NUM = :V$GRADE2)
  INTO :VAL;
  SUSPEND;

  -- + Дети-сироты
  TAG_NAME = V$PREFIX || I$COL || '35:I';
  SELECT COUNT(DISTINCT D.SCHOLAR_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 197
  JOIN VALL V2364 ON V2364.OBJ_ID = D.SCHOLAR_ID AND V2364.PARAM_ID = 2364 AND V2364.IS_DEL = 0 AND V2364.LISTVAL_ID IN (11138, 11139)
  WHERE (:I$GRADE IS NULL OR D.ROW_NUM = :I$GRADE OR D.ROW_NUM = :V$GRADE2)
  INTO :VAL;
  SUSPEND;

  -- + Дети-сироты в числе воспитанников = просто сироты
  TAG_NAME = V$PREFIX || I$COL || '36:I';
  SELECT COUNT(DISTINCT D.SCHOLAR_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 197
  JOIN VALL V2364 ON V2364.OBJ_ID = D.SCHOLAR_ID AND V2364.PARAM_ID = 2364 AND V2364.IS_DEL = 0 AND V2364.LISTVAL_ID IN (11138, 11139)
  WHERE (:I$GRADE IS NULL OR D.ROW_NUM = :I$GRADE OR D.ROW_NUM = :V$GRADE2)
  INTO :VAL;
  SUSPEND;

  -- иностранцы
  TAG_NAME = V$PREFIX || I$COL || '37:I';
  SELECT COUNT(DISTINCT D.SCHOLAR_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 197
  JOIN VALL V91 ON V91.OBJ_ID = D.SCHOLAR_ID AND V91.PARAM_ID = 91 AND V91.IS_DEL = 0 AND V91.LISTVAL_ID <> 1515
  WHERE (:I$GRADE IS NULL OR D.ROW_NUM = :I$GRADE OR D.ROW_NUM = :V$GRADE2)
  INTO :VAL;
  SUSPEND;

  -- лица без гражданства
  TAG_NAME = V$PREFIX || I$COL || '39:I';
  SELECT COUNT(DISTINCT D.SCHOLAR_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 197
  LEFT JOIN VALL V91 ON V91.OBJ_ID = D.SCHOLAR_ID AND V91.PARAM_ID = 91 AND V91.IS_DEL = 0
  WHERE (:I$GRADE IS NULL OR D.ROW_NUM = :I$GRADE OR D.ROW_NUM = :V$GRADE2) AND V91.LISTVAL_ID IS NULL
  INTO :VAL;
  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE REPORT_OO1_R212 (
    I$STUDY_TYPE BIGINT)
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(100))
AS
begin

  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R212_COL(:I$STUDY_TYPE, 'BE', NULL) INTO :TAG_NAME, :VAL DO SUSPEND;

  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R212_COL(:I$STUDY_TYPE, 'BL', 1) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R212_COL(:I$STUDY_TYPE, 'BR', 2) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R212_COL(:I$STUDY_TYPE, 'BX', 3) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R212_COL(:I$STUDY_TYPE, 'CD', 4) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R212_COL(:I$STUDY_TYPE, 'CJ', 1001) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R212_COL(:I$STUDY_TYPE, 'CP', 1101) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R212_COL(:I$STUDY_TYPE, 'CW', 1201) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R212_COL(:I$STUDY_TYPE, 'DD', 1002) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R212_COL(:I$STUDY_TYPE, 'DJ', 1102) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R212_COL(:I$STUDY_TYPE, 'DQ', 1202) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R212_COL(:I$STUDY_TYPE, 'DX', 1003) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R212_COL(:I$STUDY_TYPE, 'ED', 1103) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R212_COL(:I$STUDY_TYPE, 'EK', 1203) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R212_COL(:I$STUDY_TYPE, 'ER', 1004) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R212_COL(:I$STUDY_TYPE, 'EX', 1104) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R212_COL(:I$STUDY_TYPE, 'FE', 1204) INTO :TAG_NAME, :VAL DO SUSPEND;

  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R212_COL(:I$STUDY_TYPE, 'AV', 5) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R212_COL(:I$STUDY_TYPE, 'BA', 6) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R212_COL(:I$STUDY_TYPE, 'BF', 7) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R212_COL(:I$STUDY_TYPE, 'BK', 8) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R212_COL(:I$STUDY_TYPE, 'BP', 9) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R212_COL(:I$STUDY_TYPE, 'BU', 1005) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R212_COL(:I$STUDY_TYPE, 'BZ', 1105) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R212_COL(:I$STUDY_TYPE, 'CG', 1205) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R212_COL(:I$STUDY_TYPE, 'CN', 1006) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R212_COL(:I$STUDY_TYPE, 'CS', 1106) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R212_COL(:I$STUDY_TYPE, 'CZ', 1206) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R212_COL(:I$STUDY_TYPE, 'DG', 1007) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R212_COL(:I$STUDY_TYPE, 'DL', 1107) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R212_COL(:I$STUDY_TYPE, 'DS', 1207) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R212_COL(:I$STUDY_TYPE, 'DZ', 1008) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R212_COL(:I$STUDY_TYPE, 'EE', 1108) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R212_COL(:I$STUDY_TYPE, 'EL', 1208) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R212_COL(:I$STUDY_TYPE, 'ES', 1009) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R212_COL(:I$STUDY_TYPE, 'EX', 1109) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R212_COL(:I$STUDY_TYPE, 'FE', 1209) INTO :TAG_NAME, :VAL DO SUSPEND;

  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R212_COL(:I$STUDY_TYPE, 'AZ', 10) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R212_COL(:I$STUDY_TYPE, 'BH', 11) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R212_COL(:I$STUDY_TYPE, 'BP', 1010) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R212_COL(:I$STUDY_TYPE, 'BW', 1110) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R212_COL(:I$STUDY_TYPE, 'CE', 1210) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R212_COL(:I$STUDY_TYPE, 'CM', 1011) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R212_COL(:I$STUDY_TYPE, 'CU', 1111) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R212_COL(:I$STUDY_TYPE, 'DC', 1211) INTO :TAG_NAME, :VAL DO SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE REPORT_OO1_R212_COL (
    I$STUDY_TYPE BIGINT,
    I$COL VARCHAR(10),
    I$GRADE SMALLINT)
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(100))
AS
declare variable V$PREFIX varchar(10);
declare variable V$YEAR integer;
declare variable V$DATE date;
declare variable V$BASESTAGE integer;
begin

  -- Классы с ОВЗ, кроме умственной отсталости
  -- STUDY_TYPE игнорируем

  V$YEAR = EXTRACT(YEAR FROM CURRENT_DATE);
  IF(EXTRACT(MONTH FROM CURRENT_DATE) < 9) THEN V$YEAR = V$YEAR - 1;
  V$DATE = '20.09.' || V$YEAR;

  V$PREFIX = '@3:';

  V$BASESTAGE = MOD(I$GRADE, 100);

  -- Классов для глухих
  IF(V$BASESTAGE IS NULL OR V$BASESTAGE <= 4) THEN TAG_NAME = V$PREFIX || I$COL || '46:I';
  ELSE IF(V$BASESTAGE <= 9) THEN TAG_NAME = V$PREFIX || I$COL || '96:I';
  ELSE TAG_NAME = V$PREFIX || I$COL || '150:I';
  SELECT COUNT(DISTINCT D.CLASS_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 13275
  JOIN VALL V554 ON V554.OBJ_ID = D.CLASS_ID AND V554.PARAM_ID = 554 AND V554.IS_DEL = 0 AND V554.LISTVAL_ID = 13276
  WHERE (:I$GRADE IS NULL OR D.ROW_NUM = :I$GRADE)
  INTO :VAL;
  SUSPEND;

  -- Обучающихся Классов для глухих
  IF(V$BASESTAGE IS NULL OR V$BASESTAGE <= 4) THEN TAG_NAME = V$PREFIX || I$COL || '47:I';
  ELSE IF(V$BASESTAGE <= 9) THEN TAG_NAME = V$PREFIX || I$COL || '97:I';
  ELSE TAG_NAME = V$PREFIX || I$COL || '151:I';
  SELECT COUNT(DISTINCT D.SCHOLAR_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 13275
  JOIN VALL V554 ON V554.OBJ_ID = D.CLASS_ID AND V554.PARAM_ID = 554 AND V554.IS_DEL = 0 AND V554.LISTVAL_ID = 13276
  WHERE (:I$GRADE IS NULL OR D.ROW_NUM = :I$GRADE)
  INTO :VAL;
  SUSPEND;

  -- Классов для слабослышащих
  IF(V$BASESTAGE IS NULL OR V$BASESTAGE <= 4) THEN TAG_NAME = V$PREFIX || I$COL || '48:I';
  ELSE IF(V$BASESTAGE <= 9) THEN TAG_NAME = V$PREFIX || I$COL || '98:I';
  ELSE TAG_NAME = V$PREFIX || I$COL || '152:I';
  SELECT COUNT(DISTINCT D.CLASS_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 13275
  JOIN VALL V554 ON V554.OBJ_ID = D.CLASS_ID AND V554.PARAM_ID = 554 AND V554.IS_DEL = 0 AND V554.LISTVAL_ID = 13277
  WHERE (:I$GRADE IS NULL OR D.ROW_NUM = :I$GRADE)
  INTO :VAL;
  SUSPEND;

  -- Обучающихся Классов для слабослышащих
  IF(V$BASESTAGE IS NULL OR V$BASESTAGE <= 4) THEN TAG_NAME = V$PREFIX || I$COL || '49:I';
  ELSE IF(V$BASESTAGE <= 9) THEN TAG_NAME = V$PREFIX || I$COL || '99:I';
  ELSE TAG_NAME = V$PREFIX || I$COL || '153:I';
  SELECT COUNT(DISTINCT D.SCHOLAR_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 13275
  JOIN VALL V554 ON V554.OBJ_ID = D.CLASS_ID AND V554.PARAM_ID = 554 AND V554.IS_DEL = 0 AND V554.LISTVAL_ID = 13277
  WHERE (:I$GRADE IS NULL OR D.ROW_NUM = :I$GRADE)
  INTO :VAL;
  SUSPEND;

  -- Классов для слепых
  IF(V$BASESTAGE IS NULL OR V$BASESTAGE <= 4) THEN TAG_NAME = V$PREFIX || I$COL || '50:I';
  ELSE IF(V$BASESTAGE <= 9) THEN TAG_NAME = V$PREFIX || I$COL || '100:I';
  ELSE TAG_NAME = V$PREFIX || I$COL || '154:I';
  SELECT COUNT(DISTINCT D.CLASS_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 13275
  JOIN VALL V554 ON V554.OBJ_ID = D.CLASS_ID AND V554.PARAM_ID = 554 AND V554.IS_DEL = 0 AND V554.LISTVAL_ID = 13278
  WHERE (:I$GRADE IS NULL OR D.ROW_NUM = :I$GRADE)
  INTO :VAL;
  SUSPEND;

  -- слепых Обучающихся Классов для слепых
  IF(V$BASESTAGE IS NULL OR V$BASESTAGE <= 4) THEN TAG_NAME = V$PREFIX || I$COL || '51:I';
  ELSE IF(V$BASESTAGE <= 9) THEN TAG_NAME = V$PREFIX || I$COL || '101:I';
  ELSE TAG_NAME = V$PREFIX || I$COL || '155:I';
  SELECT COUNT(DISTINCT D.SCHOLAR_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 13275
  JOIN VALL V554 ON V554.OBJ_ID = D.CLASS_ID AND V554.PARAM_ID = 554 AND V554.IS_DEL = 0 AND V554.LISTVAL_ID = 13278
  JOIN VALL V207 ON V207.OBJ_ID = D.SCHOLAR_ID AND V207.PARAM_ID = 207 AND V207.IS_DEL = 0 AND V207.LISTVAL_ID = 13293
  WHERE (:I$GRADE IS NULL OR D.ROW_NUM = :I$GRADE)
  INTO :VAL;
  SUSPEND;

  -- слабовидящих Обучающихся Классов для слепых
  IF(V$BASESTAGE IS NULL OR V$BASESTAGE <= 4) THEN TAG_NAME = V$PREFIX || I$COL || '53:I';
  ELSE IF(V$BASESTAGE <= 9) THEN TAG_NAME = V$PREFIX || I$COL || '103:I';
  ELSE TAG_NAME = V$PREFIX || I$COL || '157:I';
  SELECT COUNT(DISTINCT D.SCHOLAR_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 13275
  JOIN VALL V554 ON V554.OBJ_ID = D.CLASS_ID AND V554.PARAM_ID = 554 AND V554.IS_DEL = 0 AND V554.LISTVAL_ID = 13278
  JOIN VALL V207 ON V207.OBJ_ID = D.SCHOLAR_ID AND V207.PARAM_ID = 207 AND V207.IS_DEL = 0 AND V207.LISTVAL_ID = 13294
  WHERE (:I$GRADE IS NULL OR D.ROW_NUM = :I$GRADE)
  INTO :VAL;
  SUSPEND;

  -- Классов для слабовидящих
  IF(V$BASESTAGE IS NULL OR V$BASESTAGE <= 4) THEN TAG_NAME = V$PREFIX || I$COL || '54:I';
  ELSE IF(V$BASESTAGE <= 9) THEN TAG_NAME = V$PREFIX || I$COL || '104:I';
  ELSE TAG_NAME = V$PREFIX || I$COL || '158:I';
  SELECT COUNT(DISTINCT D.CLASS_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 13275
  JOIN VALL V554 ON V554.OBJ_ID = D.CLASS_ID AND V554.PARAM_ID = 554 AND V554.IS_DEL = 0 AND V554.LISTVAL_ID = 13279
  WHERE (:I$GRADE IS NULL OR D.ROW_NUM = :I$GRADE)
  INTO :VAL;
  SUSPEND;

  -- слабовидящих Обучающихся Классов для слабовидящих
  IF(V$BASESTAGE IS NULL OR V$BASESTAGE <= 4) THEN TAG_NAME = V$PREFIX || I$COL || '55:I';
  ELSE IF(V$BASESTAGE <= 9) THEN TAG_NAME = V$PREFIX || I$COL || '105:I';
  ELSE TAG_NAME = V$PREFIX || I$COL || '159:I';
  SELECT COUNT(DISTINCT D.SCHOLAR_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 13275
  JOIN VALL V554 ON V554.OBJ_ID = D.CLASS_ID AND V554.PARAM_ID = 554 AND V554.IS_DEL = 0 AND V554.LISTVAL_ID = 13279
  JOIN VALL V207 ON V207.OBJ_ID = D.SCHOLAR_ID AND V207.PARAM_ID = 207 AND V207.IS_DEL = 0 AND V207.LISTVAL_ID = 13294
  WHERE (:I$GRADE IS NULL OR D.ROW_NUM = :I$GRADE)
  INTO :VAL;
  SUSPEND;

  -- слепых Обучающихся Классов для слабовидящих
  IF(V$BASESTAGE IS NULL OR V$BASESTAGE <= 4) THEN TAG_NAME = V$PREFIX || I$COL || '57:I';
  ELSE IF(V$BASESTAGE <= 9) THEN TAG_NAME = V$PREFIX || I$COL || '107:I';
  ELSE TAG_NAME = V$PREFIX || I$COL || '161:I';
  SELECT COUNT(DISTINCT D.SCHOLAR_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 13275
  JOIN VALL V554 ON V554.OBJ_ID = D.CLASS_ID AND V554.PARAM_ID = 554 AND V554.IS_DEL = 0 AND V554.LISTVAL_ID = 13279
  JOIN VALL V207 ON V207.OBJ_ID = D.SCHOLAR_ID AND V207.PARAM_ID = 207 AND V207.IS_DEL = 0 AND V207.LISTVAL_ID = 13293
  WHERE (:I$GRADE IS NULL OR D.ROW_NUM = :I$GRADE)
  INTO :VAL;
  SUSPEND;

  -- Классов для нарушений речи
  IF(V$BASESTAGE IS NULL OR V$BASESTAGE <= 4) THEN TAG_NAME = V$PREFIX || I$COL || '58:I';
  ELSE IF(V$BASESTAGE <= 9) THEN TAG_NAME = V$PREFIX || I$COL || '108:I';
  ELSE TAG_NAME = V$PREFIX || I$COL || '162:I';
  SELECT COUNT(DISTINCT D.CLASS_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 13275
  JOIN VALL V554 ON V554.OBJ_ID = D.CLASS_ID AND V554.PARAM_ID = 554 AND V554.IS_DEL = 0 AND V554.LISTVAL_ID = 13280
  WHERE (:I$GRADE IS NULL OR D.ROW_NUM = :I$GRADE)
  INTO :VAL;
  SUSPEND;

  -- Обучающихся Классов для нарушений речи
  IF(V$BASESTAGE IS NULL OR V$BASESTAGE <= 4) THEN TAG_NAME = V$PREFIX || I$COL || '59:I';
  ELSE IF(V$BASESTAGE <= 9) THEN TAG_NAME = V$PREFIX || I$COL || '109:I';
  ELSE TAG_NAME = V$PREFIX || I$COL || '163:I';
  SELECT COUNT(DISTINCT D.SCHOLAR_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 13275
  JOIN VALL V554 ON V554.OBJ_ID = D.CLASS_ID AND V554.PARAM_ID = 554 AND V554.IS_DEL = 0 AND V554.LISTVAL_ID = 13280
  WHERE (:I$GRADE IS NULL OR D.ROW_NUM = :I$GRADE)
  INTO :VAL;
  SUSPEND;

  -- Классов для нарушений ОД
  IF(V$BASESTAGE IS NULL OR V$BASESTAGE <= 4) THEN TAG_NAME = V$PREFIX || I$COL || '60:I';
  ELSE IF(V$BASESTAGE <= 9) THEN TAG_NAME = V$PREFIX || I$COL || '110:I';
  ELSE TAG_NAME = V$PREFIX || I$COL || '164:I';
  SELECT COUNT(DISTINCT D.CLASS_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 13275
  JOIN VALL V554 ON V554.OBJ_ID = D.CLASS_ID AND V554.PARAM_ID = 554 AND V554.IS_DEL = 0 AND V554.LISTVAL_ID = 13281
  WHERE (:I$GRADE IS NULL OR D.ROW_NUM = :I$GRADE)
  INTO :VAL;
  SUSPEND;

  -- Обучающихся Классов для нарушений ОД
  IF(V$BASESTAGE IS NULL OR V$BASESTAGE <= 4) THEN TAG_NAME = V$PREFIX || I$COL || '61:I';
  ELSE IF(V$BASESTAGE <= 9) THEN TAG_NAME = V$PREFIX || I$COL || '111:I';
  ELSE TAG_NAME = V$PREFIX || I$COL || '165:I';
  SELECT COUNT(DISTINCT D.SCHOLAR_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 13275
  JOIN VALL V554 ON V554.OBJ_ID = D.CLASS_ID AND V554.PARAM_ID = 554 AND V554.IS_DEL = 0 AND V554.LISTVAL_ID = 13281
  WHERE (:I$GRADE IS NULL OR D.ROW_NUM = :I$GRADE)
  INTO :VAL;
  SUSPEND;

  -- Классов для задержки развития
  IF(V$BASESTAGE IS NULL OR V$BASESTAGE <= 4) THEN TAG_NAME = V$PREFIX || I$COL || '62:I';
  ELSE IF(V$BASESTAGE <= 9) THEN TAG_NAME = V$PREFIX || I$COL || '112:I';
  ELSE TAG_NAME = V$PREFIX || I$COL || '166:I';
  SELECT COUNT(DISTINCT D.CLASS_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 13275
  JOIN VALL V554 ON V554.OBJ_ID = D.CLASS_ID AND V554.PARAM_ID = 554 AND V554.IS_DEL = 0 AND V554.LISTVAL_ID = 13282
  WHERE (:I$GRADE IS NULL OR D.ROW_NUM = :I$GRADE)
  INTO :VAL;
  SUSPEND;

  -- Обучающихся Классов для задержки развития
  IF(V$BASESTAGE IS NULL OR V$BASESTAGE <= 4) THEN TAG_NAME = V$PREFIX || I$COL || '63:I';
  ELSE IF(V$BASESTAGE <= 9) THEN TAG_NAME = V$PREFIX || I$COL || '113:I';
  ELSE TAG_NAME = V$PREFIX || I$COL || '167:I';
  SELECT COUNT(DISTINCT D.SCHOLAR_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 13275
  JOIN VALL V554 ON V554.OBJ_ID = D.CLASS_ID AND V554.PARAM_ID = 554 AND V554.IS_DEL = 0 AND V554.LISTVAL_ID = 13282
  WHERE (:I$GRADE IS NULL OR D.ROW_NUM = :I$GRADE)
  INTO :VAL;
  SUSPEND;

  -- Классов для аутизма
  IF(V$BASESTAGE IS NULL OR V$BASESTAGE <= 4) THEN TAG_NAME = V$PREFIX || I$COL || '64:I';
  ELSE IF(V$BASESTAGE <= 9) THEN TAG_NAME = V$PREFIX || I$COL || '114:I';
  ELSE TAG_NAME = V$PREFIX || I$COL || '168:I';
  SELECT COUNT(DISTINCT D.CLASS_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 13275
  JOIN VALL V554 ON V554.OBJ_ID = D.CLASS_ID AND V554.PARAM_ID = 554 AND V554.IS_DEL = 0 AND V554.LISTVAL_ID = 13284
  WHERE (:I$GRADE IS NULL OR D.ROW_NUM = :I$GRADE)
  INTO :VAL;
  SUSPEND;

  -- Обучающихся Классов для аутизма
  IF(V$BASESTAGE IS NULL OR V$BASESTAGE <= 4) THEN TAG_NAME = V$PREFIX || I$COL || '65:I';
  ELSE IF(V$BASESTAGE <= 9) THEN TAG_NAME = V$PREFIX || I$COL || '115:I';
  ELSE TAG_NAME = V$PREFIX || I$COL || '169:I';
  SELECT COUNT(DISTINCT D.SCHOLAR_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 13275
  JOIN VALL V554 ON V554.OBJ_ID = D.CLASS_ID AND V554.PARAM_ID = 554 AND V554.IS_DEL = 0 AND V554.LISTVAL_ID = 13284
  WHERE (:I$GRADE IS NULL OR D.ROW_NUM = :I$GRADE)
  INTO :VAL;
  SUSPEND;

  -- Классов со сложными дефектами
  IF(V$BASESTAGE IS NULL OR V$BASESTAGE <= 4) THEN TAG_NAME = V$PREFIX || I$COL || '66:I';
  ELSE IF(V$BASESTAGE <= 9) THEN TAG_NAME = V$PREFIX || I$COL || '116:I';
  ELSE TAG_NAME = V$PREFIX || I$COL || '170:I';
  SELECT COUNT(DISTINCT D.CLASS_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 13275
  JOIN VALL V554 ON V554.OBJ_ID = D.CLASS_ID AND V554.PARAM_ID = 554 AND V554.IS_DEL = 0 AND V554.LISTVAL_ID = 13285
  WHERE (:I$GRADE IS NULL OR D.ROW_NUM = :I$GRADE)
  INTO :VAL;
  SUSPEND;

  -- Обучающихся Классов со сложными дефектами
  IF(V$BASESTAGE IS NULL OR V$BASESTAGE <= 4) THEN TAG_NAME = V$PREFIX || I$COL || '67:I';
  ELSE IF(V$BASESTAGE <= 9) THEN TAG_NAME = V$PREFIX || I$COL || '117:I';
  ELSE TAG_NAME = V$PREFIX || I$COL || '171:I';
  SELECT COUNT(DISTINCT D.SCHOLAR_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 13275
  JOIN VALL V554 ON V554.OBJ_ID = D.CLASS_ID AND V554.PARAM_ID = 554 AND V554.IS_DEL = 0 AND V554.LISTVAL_ID = 13285
  WHERE (:I$GRADE IS NULL OR D.ROW_NUM = :I$GRADE)
  INTO :VAL;
  SUSPEND;

  -- Классов прочих
  IF(V$BASESTAGE IS NULL OR V$BASESTAGE <= 4) THEN TAG_NAME = V$PREFIX || I$COL || '68:I';
  ELSE IF(V$BASESTAGE <= 9) THEN TAG_NAME = V$PREFIX || I$COL || '118:I';
  ELSE TAG_NAME = V$PREFIX || I$COL || '172:I';
  SELECT COUNT(DISTINCT D.CLASS_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 13275
  JOIN VALL V554 ON V554.OBJ_ID = D.CLASS_ID AND V554.PARAM_ID = 554 AND V554.IS_DEL = 0 AND V554.LISTVAL_ID = 13286
  WHERE (:I$GRADE IS NULL OR D.ROW_NUM = :I$GRADE)
  INTO :VAL;
  SUSPEND;

  -- Обучающихся Классов прочих
  IF(V$BASESTAGE IS NULL OR V$BASESTAGE <= 4) THEN TAG_NAME = V$PREFIX || I$COL || '69:I';
  ELSE IF(V$BASESTAGE <= 9) THEN TAG_NAME = V$PREFIX || I$COL || '122:I';
  ELSE TAG_NAME = V$PREFIX || I$COL || '173:I';
  SELECT COUNT(DISTINCT D.SCHOLAR_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 13275
  JOIN VALL V554 ON V554.OBJ_ID = D.CLASS_ID AND V554.PARAM_ID = 554 AND V554.IS_DEL = 0 AND V554.LISTVAL_ID = 13286
  WHERE (:I$GRADE IS NULL OR D.ROW_NUM = :I$GRADE)
  INTO :VAL;
  SUSPEND;

  -- Классов всего
  IF(V$BASESTAGE IS NULL OR V$BASESTAGE <= 4) THEN TAG_NAME = V$PREFIX || I$COL || '70:I';
  ELSE IF(V$BASESTAGE <= 9) THEN TAG_NAME = V$PREFIX || I$COL || '123:I';
  ELSE TAG_NAME = V$PREFIX || I$COL || '174:I';
  SELECT COUNT(DISTINCT D.CLASS_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 13275
  JOIN VALL V554 ON V554.OBJ_ID = D.CLASS_ID AND V554.PARAM_ID = 554 AND V554.IS_DEL = 0 AND V554.LISTVAL_ID <> 13283
  WHERE (:I$GRADE IS NULL OR D.ROW_NUM = :I$GRADE)
  INTO :VAL;
  SUSPEND;

  -- Обучающихся Классов всего
  IF(V$BASESTAGE IS NULL OR V$BASESTAGE <= 4) THEN TAG_NAME = V$PREFIX || I$COL || '71:I';
  ELSE IF(V$BASESTAGE <= 9) THEN TAG_NAME = V$PREFIX || I$COL || '124:I';
  ELSE TAG_NAME = V$PREFIX || I$COL || '175:I';
  SELECT COUNT(DISTINCT D.SCHOLAR_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 13275
  JOIN VALL V554 ON V554.OBJ_ID = D.CLASS_ID AND V554.PARAM_ID = 554 AND V554.IS_DEL = 0 AND V554.LISTVAL_ID <> 13283
  WHERE (:I$GRADE IS NULL OR D.ROW_NUM = :I$GRADE)
  INTO :VAL;
  SUSPEND;

  -- Обучающихся Классов всего очно
  IF(V$BASESTAGE IS NULL OR V$BASESTAGE <= 4) THEN TAG_NAME = V$PREFIX || I$COL || '73:I';
  ELSE IF(V$BASESTAGE <= 9) THEN TAG_NAME = V$PREFIX || I$COL || '126:I';
  ELSE TAG_NAME = V$PREFIX || I$COL || '177:I';
  SELECT COUNT(DISTINCT D.SCHOLAR_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 13275
  JOIN VALL V554 ON V554.OBJ_ID = D.CLASS_ID AND V554.PARAM_ID = 554 AND V554.IS_DEL = 0 AND V554.LISTVAL_ID <> 13283
  JOIN VALL V80 ON V80.OBJ_ID = D.SCHOLAR_ID AND V80.PARAM_ID = 80 AND V80.IS_DEL = 0 AND V80.LISTVAL_ID = 5418
  WHERE (:I$GRADE IS NULL OR D.ROW_NUM = :I$GRADE)
  INTO :VAL;
  SUSPEND;

  -- Обучающихся Классов всего очно-заочно
  IF(V$BASESTAGE IS NULL OR V$BASESTAGE <= 4) THEN TAG_NAME = V$PREFIX || I$COL || '74:I';
  ELSE IF(V$BASESTAGE <= 9) THEN TAG_NAME = V$PREFIX || I$COL || '128:I';
  ELSE TAG_NAME = V$PREFIX || I$COL || '179:I';
  SELECT COUNT(DISTINCT D.SCHOLAR_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 13275
  JOIN VALL V554 ON V554.OBJ_ID = D.CLASS_ID AND V554.PARAM_ID = 554 AND V554.IS_DEL = 0 AND V554.LISTVAL_ID <> 13283
  JOIN VALL V80 ON V80.OBJ_ID = D.SCHOLAR_ID AND V80.PARAM_ID = 80 AND V80.IS_DEL = 0 AND V80.LISTVAL_ID = 5419
  WHERE (:I$GRADE IS NULL OR D.ROW_NUM = :I$GRADE)
  INTO :VAL;
  SUSPEND;

  -- Обучающихся Классов всего заочно
  IF(V$BASESTAGE IS NULL OR V$BASESTAGE <= 4) THEN TAG_NAME = V$PREFIX || I$COL || '75:I';
  ELSE IF(V$BASESTAGE <= 9) THEN TAG_NAME = V$PREFIX || I$COL || '129:I';
  ELSE TAG_NAME = V$PREFIX || I$COL || '180:I';
  SELECT COUNT(DISTINCT D.SCHOLAR_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 13275
  JOIN VALL V554 ON V554.OBJ_ID = D.CLASS_ID AND V554.PARAM_ID = 554 AND V554.IS_DEL = 0 AND V554.LISTVAL_ID <> 13283
  JOIN VALL V80 ON V80.OBJ_ID = D.SCHOLAR_ID AND V80.PARAM_ID = 80 AND V80.IS_DEL = 0 AND V80.LISTVAL_ID = 5420
  WHERE (:I$GRADE IS NULL OR D.ROW_NUM = :I$GRADE)
  INTO :VAL;
  SUSPEND;

  -- Воспитанники ХЗ кто такие

  -- Обучающихся Классов всего девочки
  IF(V$BASESTAGE IS NULL OR V$BASESTAGE <= 4) THEN TAG_NAME = V$PREFIX || I$COL || '78:I';
  ELSE IF(V$BASESTAGE <= 9) THEN TAG_NAME = V$PREFIX || I$COL || '132:I';
  ELSE TAG_NAME = V$PREFIX || I$COL || '183:I';
  SELECT COUNT(DISTINCT D.SCHOLAR_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 13275
  JOIN VALL V554 ON V554.OBJ_ID = D.CLASS_ID AND V554.PARAM_ID = 554 AND V554.IS_DEL = 0 AND V554.LISTVAL_ID <> 13283
  JOIN VALL V88 ON V88.OBJ_ID = D.SCHOLAR_ID AND V88.PARAM_ID = 88 AND V88.IS_DEL = 0 AND V88.LISTVAL_ID = 182
  WHERE (:I$GRADE IS NULL OR D.ROW_NUM = :I$GRADE)
  INTO :VAL;
  SUSPEND;

  -- Обучающихся Классов всего ОВЗ
  IF(V$BASESTAGE IS NULL OR V$BASESTAGE <= 4) THEN TAG_NAME = V$PREFIX || I$COL || '79:I';
  ELSE IF(V$BASESTAGE <= 9) THEN TAG_NAME = V$PREFIX || I$COL || '133:I';
  ELSE TAG_NAME = V$PREFIX || I$COL || '184:I';
  SELECT COUNT(DISTINCT D.SCHOLAR_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 13275
  JOIN VALL V554 ON V554.OBJ_ID = D.CLASS_ID AND V554.PARAM_ID = 554 AND V554.IS_DEL = 0 AND V554.LISTVAL_ID <> 13283
  JOIN VALL V207 ON V207.OBJ_ID = D.SCHOLAR_ID AND V207.PARAM_ID = 207 AND V207.IS_DEL = 0 AND V207.LISTVAL_ID <> 13289
  WHERE (:I$GRADE IS NULL OR D.ROW_NUM = :I$GRADE)
  INTO :VAL;
  SUSPEND;

  -- Обучающихся Классов всего ОВЗ + инвалиды
  IF(V$BASESTAGE IS NULL OR V$BASESTAGE <= 4) THEN TAG_NAME = V$PREFIX || I$COL || '80:I';
  ELSE IF(V$BASESTAGE <= 9) THEN TAG_NAME = V$PREFIX || I$COL || '134:I';
  ELSE TAG_NAME = V$PREFIX || I$COL || '185:I';
  SELECT COUNT(DISTINCT D.SCHOLAR_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 13275
  JOIN VALL V554 ON V554.OBJ_ID = D.CLASS_ID AND V554.PARAM_ID = 554 AND V554.IS_DEL = 0 AND V554.LISTVAL_ID <> 13283
  JOIN VALL V207 ON V207.OBJ_ID = D.SCHOLAR_ID AND V207.PARAM_ID = 207 AND V207.IS_DEL = 0 AND V207.LISTVAL_ID <> 13289
  JOIN LINKS L295 ON L295.PARENT_ID = D.SCHOLAR_ID AND L295.OBJ_TYPE_ID = 295 AND L295.DATE_DEL IS NULL
  JOIN VALL V2373 ON V2373.OBJ_ID = L295.OBJ_ID AND V2373.PARAM_ID = 2373 AND V2373.IS_DEL = 0 AND V2373.LISTVAL_ID <> 11171
  LEFT JOIN VALD V2375 ON V2375.OBJ_ID = L295.OBJ_ID AND V2375.PARAM_ID = 2375 AND V2375.IS_DEL = 0
  WHERE (:I$GRADE IS NULL OR D.ROW_NUM = :I$GRADE) AND (V2375.VAL IS NULL OR V2375.VAL >= :V$DATE)
  INTO :VAL;
  SUSPEND;

  -- Обучающихся Классов всего ОВЗ + дети-инвалиды
  IF(V$BASESTAGE IS NULL OR V$BASESTAGE <= 4) THEN TAG_NAME = V$PREFIX || I$COL || '82:I';
  ELSE IF(V$BASESTAGE <= 9) THEN TAG_NAME = V$PREFIX || I$COL || '136:I';
  ELSE TAG_NAME = V$PREFIX || I$COL || '187:I';
  SELECT COUNT(DISTINCT D.SCHOLAR_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 13275
  JOIN VALL V554 ON V554.OBJ_ID = D.CLASS_ID AND V554.PARAM_ID = 554 AND V554.IS_DEL = 0 AND V554.LISTVAL_ID <> 13283
  JOIN VALL V207 ON V207.OBJ_ID = D.SCHOLAR_ID AND V207.PARAM_ID = 207 AND V207.IS_DEL = 0 AND V207.LISTVAL_ID <> 13289
  JOIN LINKS L295 ON L295.PARENT_ID = D.SCHOLAR_ID AND L295.OBJ_TYPE_ID = 295 AND L295.DATE_DEL IS NULL
  JOIN VALL V2373 ON V2373.OBJ_ID = L295.OBJ_ID AND V2373.PARAM_ID = 2373 AND V2373.IS_DEL = 0 AND V2373.LISTVAL_ID = 11171
  LEFT JOIN VALD V2375 ON V2375.OBJ_ID = L295.OBJ_ID AND V2375.PARAM_ID = 2375 AND V2375.IS_DEL = 0
  WHERE (:I$GRADE IS NULL OR D.ROW_NUM = :I$GRADE) AND (V2375.VAL IS NULL OR V2375.VAL >= :V$DATE)
  INTO :VAL;
  SUSPEND;

  -- Обучающихся Классов всего ОВЗ + инвалиды, но не ОВЗ
  IF(V$BASESTAGE IS NULL OR V$BASESTAGE <= 4) THEN TAG_NAME = V$PREFIX || I$COL || '83:I';
  ELSE IF(V$BASESTAGE <= 9) THEN TAG_NAME = V$PREFIX || I$COL || '137:I';
  ELSE TAG_NAME = V$PREFIX || I$COL || '188:I';
  SELECT COUNT(DISTINCT D.SCHOLAR_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 13275
  JOIN VALL V554 ON V554.OBJ_ID = D.CLASS_ID AND V554.PARAM_ID = 554 AND V554.IS_DEL = 0 AND V554.LISTVAL_ID <> 13283
  JOIN VALL V207 ON V207.OBJ_ID = D.SCHOLAR_ID AND V207.PARAM_ID = 207 AND V207.IS_DEL = 0 AND V207.LISTVAL_ID = 13289
  JOIN LINKS L295 ON L295.PARENT_ID = D.SCHOLAR_ID AND L295.OBJ_TYPE_ID = 295 AND L295.DATE_DEL IS NULL
  JOIN VALL V2373 ON V2373.OBJ_ID = L295.OBJ_ID AND V2373.PARAM_ID = 2373 AND V2373.IS_DEL = 0 AND V2373.LISTVAL_ID <> 11171
  LEFT JOIN VALD V2375 ON V2375.OBJ_ID = L295.OBJ_ID AND V2375.PARAM_ID = 2375 AND V2375.IS_DEL = 0
  WHERE (:I$GRADE IS NULL OR D.ROW_NUM = :I$GRADE) AND (V2375.VAL IS NULL OR V2375.VAL >= :V$DATE)
  INTO :VAL;
  SUSPEND;

  -- Обучающихся Классов всего ОВЗ + дети-инвалиды, но не ОВЗ
  IF(V$BASESTAGE IS NULL OR V$BASESTAGE <= 4) THEN TAG_NAME = V$PREFIX || I$COL || '84:I';
  ELSE IF(V$BASESTAGE <= 9) THEN TAG_NAME = V$PREFIX || I$COL || '138:I';
  ELSE TAG_NAME = V$PREFIX || I$COL || '189:I';
  SELECT COUNT(DISTINCT D.SCHOLAR_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 13275
  JOIN VALL V554 ON V554.OBJ_ID = D.CLASS_ID AND V554.PARAM_ID = 554 AND V554.IS_DEL = 0 AND V554.LISTVAL_ID <> 13283
  JOIN VALL V207 ON V207.OBJ_ID = D.SCHOLAR_ID AND V207.PARAM_ID = 207 AND V207.IS_DEL = 0 AND V207.LISTVAL_ID = 13289
  JOIN LINKS L295 ON L295.PARENT_ID = D.SCHOLAR_ID AND L295.OBJ_TYPE_ID = 295 AND L295.DATE_DEL IS NULL
  JOIN VALL V2373 ON V2373.OBJ_ID = L295.OBJ_ID AND V2373.PARAM_ID = 2373 AND V2373.IS_DEL = 0 AND V2373.LISTVAL_ID = 11171
  LEFT JOIN VALD V2375 ON V2375.OBJ_ID = L295.OBJ_ID AND V2375.PARAM_ID = 2375 AND V2375.IS_DEL = 0
  WHERE (:I$GRADE IS NULL OR D.ROW_NUM = :I$GRADE) AND (V2375.VAL IS NULL OR V2375.VAL >= :V$DATE)
  INTO :VAL;
  SUSPEND;

  -- Обучающихся Классов всего ОВЗ + дети-сироты и без попечения
  IF(V$BASESTAGE IS NULL OR V$BASESTAGE <= 4) THEN TAG_NAME = V$PREFIX || I$COL || '85:I';
  ELSE IF(V$BASESTAGE <= 9) THEN TAG_NAME = V$PREFIX || I$COL || '139:I';
  ELSE TAG_NAME = V$PREFIX || I$COL || '190:I';
  SELECT COUNT(DISTINCT D.SCHOLAR_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 13275
  JOIN VALL V554 ON V554.OBJ_ID = D.CLASS_ID AND V554.PARAM_ID = 554 AND V554.IS_DEL = 0 AND V554.LISTVAL_ID <> 13283
  JOIN VALL V2364 ON V2364.OBJ_ID = D.SCHOLAR_ID AND V2364.PARAM_ID = 2364 AND V2364.IS_DEL = 0 AND V2364.LISTVAL_ID IN (11138, 11139)
  WHERE (:I$GRADE IS NULL OR D.ROW_NUM = :I$GRADE)
  INTO :VAL;
  SUSPEND;

  -- Обучающихся Классов всего ОВЗ + иностранцы
  IF(V$BASESTAGE IS NULL OR V$BASESTAGE <= 4) THEN TAG_NAME = V$PREFIX || I$COL || '87:I';
  ELSE IF(V$BASESTAGE <= 9) THEN TAG_NAME = V$PREFIX || I$COL || '141:I';
  ELSE TAG_NAME = V$PREFIX || I$COL || '192:I';
  SELECT COUNT(DISTINCT D.SCHOLAR_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 13275
  JOIN VALL V554 ON V554.OBJ_ID = D.CLASS_ID AND V554.PARAM_ID = 554 AND V554.IS_DEL = 0 AND V554.LISTVAL_ID <> 13283
  JOIN VALL V91 ON V91.OBJ_ID = D.SCHOLAR_ID AND V91.PARAM_ID = 91 AND V91.IS_DEL = 0 AND V91.LISTVAL_ID <> 1515
  WHERE (:I$GRADE IS NULL OR D.ROW_NUM = :I$GRADE)
  INTO :VAL;
  SUSPEND;

  -- Обучающихся Классов всего ОВЗ + без гражданства
  IF(V$BASESTAGE IS NULL OR V$BASESTAGE <= 4) THEN TAG_NAME = V$PREFIX || I$COL || '87:I';
  ELSE IF(V$BASESTAGE <= 9) THEN TAG_NAME = V$PREFIX || I$COL || '141:I';
  ELSE TAG_NAME = V$PREFIX || I$COL || '192:I';
  SELECT COUNT(DISTINCT D.SCHOLAR_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 13275
  JOIN VALL V554 ON V554.OBJ_ID = D.CLASS_ID AND V554.PARAM_ID = 554 AND V554.IS_DEL = 0 AND V554.LISTVAL_ID <> 13283
  LEFT JOIN VALL V91 ON V91.OBJ_ID = D.SCHOLAR_ID AND V91.PARAM_ID = 91 AND V91.IS_DEL = 0
  WHERE (:I$GRADE IS NULL OR D.ROW_NUM = :I$GRADE) AND V91.LISTVAL_ID IS NULL
  INTO :VAL;
  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE REPORT_OO1_R213 (
    I$STUDY_TYPE BIGINT)
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(100))
AS
begin

  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R213_COL(:I$STUDY_TYPE, 'BN', NULL) INTO :TAG_NAME, :VAL DO SUSPEND;

  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R213_COL(:I$STUDY_TYPE, 'BU', 1) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R213_COL(:I$STUDY_TYPE, 'CA', 1101) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R213_COL(:I$STUDY_TYPE, 'CH', 1201) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R213_COL(:I$STUDY_TYPE, 'CO', 2) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R213_COL(:I$STUDY_TYPE, 'CU', 3) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R213_COL(:I$STUDY_TYPE, 'DA', 4) INTO :TAG_NAME, :VAL DO SUSPEND;

  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R213_COL(:I$STUDY_TYPE, 'DH', 5) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R213_COL(:I$STUDY_TYPE, 'DO', 6) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R213_COL(:I$STUDY_TYPE, 'DV', 7) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R213_COL(:I$STUDY_TYPE, 'EC', 8) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R213_COL(:I$STUDY_TYPE, 'EJ', 9) INTO :TAG_NAME, :VAL DO SUSPEND;

  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R213_COL(:I$STUDY_TYPE, 'EQ', 10) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R213_COL(:I$STUDY_TYPE, 'EX', 11) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R213_COL(:I$STUDY_TYPE, 'FV', 12) INTO :TAG_NAME, :VAL DO SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE REPORT_OO1_R213_COL (
    I$STUDY_TYPE BIGINT,
    I$COL VARCHAR(10),
    I$GRADE SMALLINT)
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(100))
AS
declare variable V$PREFIX varchar(10);
declare variable V$YEAR integer;
declare variable V$DATE date;
declare variable V$BASESTAGE integer;
begin

  -- Классы с ОВЗ, кроме умственной отсталости
  -- STUDY_TYPE игнорируем

  V$YEAR = EXTRACT(YEAR FROM CURRENT_DATE);
  IF(EXTRACT(MONTH FROM CURRENT_DATE) < 9) THEN V$YEAR = V$YEAR - 1;
  V$DATE = '20.09.' || V$YEAR;

  V$PREFIX = '@3:';

  V$BASESTAGE = MOD(I$GRADE, 100);

  -- Классов 9 лет
  TAG_NAME = V$PREFIX || I$COL || '201:I';
  SELECT COUNT(DISTINCT D.CLASS_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 13275
  JOIN VALL V554 ON V554.OBJ_ID = D.CLASS_ID AND V554.PARAM_ID = 554 AND V554.IS_DEL = 0 AND V554.LISTVAL_ID = 13283
  JOIN PERSON_MOVEMENTS M ON M.DATE_DEL IS NULL AND M.PERSON_ID = D.SCHOLAR_ID AND M.GROUP_ID = D.CLASS_ID AND (M.DATE_OUT IS NULL OR M.DATE_OUT > :V$DATE) AND M.PLAN_STAGES = 9
  WHERE (:I$GRADE IS NULL OR D.ROW_NUM = :I$GRADE)
  INTO :VAL;
  SUSPEND;

  -- Обучающихся Классов 9 лет
  TAG_NAME = V$PREFIX || I$COL || '202:I';
  SELECT COUNT(DISTINCT D.SCHOLAR_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 13275
  JOIN VALL V554 ON V554.OBJ_ID = D.CLASS_ID AND V554.PARAM_ID = 554 AND V554.IS_DEL = 0 AND V554.LISTVAL_ID = 13283
  JOIN PERSON_MOVEMENTS M ON M.DATE_DEL IS NULL AND M.PERSON_ID = D.SCHOLAR_ID AND M.GROUP_ID = D.CLASS_ID AND (M.DATE_OUT IS NULL OR M.DATE_OUT > :V$DATE) AND M.PLAN_STAGES = 9
  WHERE (:I$GRADE IS NULL OR D.ROW_NUM = :I$GRADE)
  INTO :VAL;
  SUSPEND;

  -- Классов 10 лет
  TAG_NAME = V$PREFIX || I$COL || '203:I';
  SELECT COUNT(DISTINCT D.CLASS_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 13275
  JOIN VALL V554 ON V554.OBJ_ID = D.CLASS_ID AND V554.PARAM_ID = 554 AND V554.IS_DEL = 0 AND V554.LISTVAL_ID = 13283
  JOIN PERSON_MOVEMENTS M ON M.DATE_DEL IS NULL AND M.PERSON_ID = D.SCHOLAR_ID AND M.GROUP_ID = D.CLASS_ID AND (M.DATE_OUT IS NULL OR M.DATE_OUT > :V$DATE) AND M.PLAN_STAGES = 10
  WHERE (:I$GRADE IS NULL OR D.ROW_NUM = :I$GRADE)
  INTO :VAL;
  SUSPEND;

  -- Обучающихся Классов 10 лет
  TAG_NAME = V$PREFIX || I$COL || '204:I';
  SELECT COUNT(DISTINCT D.SCHOLAR_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 13275
  JOIN VALL V554 ON V554.OBJ_ID = D.CLASS_ID AND V554.PARAM_ID = 554 AND V554.IS_DEL = 0 AND V554.LISTVAL_ID = 13283
  JOIN PERSON_MOVEMENTS M ON M.DATE_DEL IS NULL AND M.PERSON_ID = D.SCHOLAR_ID AND M.GROUP_ID = D.CLASS_ID AND (M.DATE_OUT IS NULL OR M.DATE_OUT > :V$DATE) AND M.PLAN_STAGES = 10
  WHERE (:I$GRADE IS NULL OR D.ROW_NUM = :I$GRADE)
  INTO :VAL;
  SUSPEND;

  -- Классов 11 лет
  TAG_NAME = V$PREFIX || I$COL || '205:I';
  SELECT COUNT(DISTINCT D.CLASS_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 13275
  JOIN VALL V554 ON V554.OBJ_ID = D.CLASS_ID AND V554.PARAM_ID = 554 AND V554.IS_DEL = 0 AND V554.LISTVAL_ID = 13283
  JOIN PERSON_MOVEMENTS M ON M.DATE_DEL IS NULL AND M.PERSON_ID = D.SCHOLAR_ID AND M.GROUP_ID = D.CLASS_ID AND (M.DATE_OUT IS NULL OR M.DATE_OUT > :V$DATE) AND M.PLAN_STAGES = 11
  WHERE (:I$GRADE IS NULL OR D.ROW_NUM = :I$GRADE)
  INTO :VAL;
  SUSPEND;

  -- Обучающихся Классов 11 лет
  TAG_NAME = V$PREFIX || I$COL || '206:I';
  SELECT COUNT(DISTINCT D.SCHOLAR_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 13275
  JOIN VALL V554 ON V554.OBJ_ID = D.CLASS_ID AND V554.PARAM_ID = 554 AND V554.IS_DEL = 0 AND V554.LISTVAL_ID = 13283
  JOIN PERSON_MOVEMENTS M ON M.DATE_DEL IS NULL AND M.PERSON_ID = D.SCHOLAR_ID AND M.GROUP_ID = D.CLASS_ID AND (M.DATE_OUT IS NULL OR M.DATE_OUT > :V$DATE) AND M.PLAN_STAGES = 11
  WHERE (:I$GRADE IS NULL OR D.ROW_NUM = :I$GRADE)
  INTO :VAL;
  SUSPEND;

  -- Классов 12 лет
  TAG_NAME = V$PREFIX || I$COL || '207:I';
  SELECT COUNT(DISTINCT D.CLASS_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 13275
  JOIN VALL V554 ON V554.OBJ_ID = D.CLASS_ID AND V554.PARAM_ID = 554 AND V554.IS_DEL = 0 AND V554.LISTVAL_ID = 13283
  JOIN PERSON_MOVEMENTS M ON M.DATE_DEL IS NULL AND M.PERSON_ID = D.SCHOLAR_ID AND M.GROUP_ID = D.CLASS_ID AND (M.DATE_OUT IS NULL OR M.DATE_OUT > :V$DATE) AND M.PLAN_STAGES = 12
  WHERE (:I$GRADE IS NULL OR D.ROW_NUM = :I$GRADE)
  INTO :VAL;
  SUSPEND;

  -- Обучающихся Классов 12 лет
  TAG_NAME = V$PREFIX || I$COL || '208:I';
  SELECT COUNT(DISTINCT D.SCHOLAR_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 13275
  JOIN VALL V554 ON V554.OBJ_ID = D.CLASS_ID AND V554.PARAM_ID = 554 AND V554.IS_DEL = 0 AND V554.LISTVAL_ID = 13279
  JOIN PERSON_MOVEMENTS M ON M.DATE_DEL IS NULL AND M.PERSON_ID = D.SCHOLAR_ID AND M.GROUP_ID = D.CLASS_ID AND (M.DATE_OUT IS NULL OR M.DATE_OUT > :V$DATE) AND M.PLAN_STAGES = 12
  WHERE (:I$GRADE IS NULL OR D.ROW_NUM = :I$GRADE)
  INTO :VAL;
  SUSPEND;

  -- Классов 13 лет
  TAG_NAME = V$PREFIX || I$COL || '209:I';
  SELECT COUNT(DISTINCT D.CLASS_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 13275
  JOIN VALL V554 ON V554.OBJ_ID = D.CLASS_ID AND V554.PARAM_ID = 554 AND V554.IS_DEL = 0 AND V554.LISTVAL_ID = 13283
  JOIN PERSON_MOVEMENTS M ON M.DATE_DEL IS NULL AND M.PERSON_ID = D.SCHOLAR_ID AND M.GROUP_ID = D.CLASS_ID AND (M.DATE_OUT IS NULL OR M.DATE_OUT > :V$DATE) AND M.PLAN_STAGES = 13
  WHERE (:I$GRADE IS NULL OR D.ROW_NUM = :I$GRADE)
  INTO :VAL;
  SUSPEND;

  -- Обучающихся Классов 13 лет
  TAG_NAME = V$PREFIX || I$COL || '210:I';
  SELECT COUNT(DISTINCT D.SCHOLAR_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 13275
  JOIN VALL V554 ON V554.OBJ_ID = D.CLASS_ID AND V554.PARAM_ID = 554 AND V554.IS_DEL = 0 AND V554.LISTVAL_ID = 13283
  JOIN PERSON_MOVEMENTS M ON M.DATE_DEL IS NULL AND M.PERSON_ID = D.SCHOLAR_ID AND M.GROUP_ID = D.CLASS_ID AND (M.DATE_OUT IS NULL OR M.DATE_OUT > :V$DATE) AND M.PLAN_STAGES = 13
  WHERE (:I$GRADE IS NULL OR D.ROW_NUM = :I$GRADE)
  INTO :VAL;
  SUSPEND;

  -- Классов всего
  TAG_NAME = V$PREFIX || I$COL || '211:I';
  SELECT COUNT(DISTINCT D.CLASS_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 13275
  JOIN VALL V554 ON V554.OBJ_ID = D.CLASS_ID AND V554.PARAM_ID = 554 AND V554.IS_DEL = 0 AND V554.LISTVAL_ID = 13283
  WHERE (:I$GRADE IS NULL OR D.ROW_NUM = :I$GRADE)
  INTO :VAL;
  SUSPEND;

  -- Обучающихся Классов всего
  TAG_NAME = V$PREFIX || I$COL || '212:I';
  SELECT COUNT(DISTINCT D.SCHOLAR_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 13275
  JOIN VALL V554 ON V554.OBJ_ID = D.CLASS_ID AND V554.PARAM_ID = 554 AND V554.IS_DEL = 0 AND V554.LISTVAL_ID = 13283
  WHERE (:I$GRADE IS NULL OR D.ROW_NUM = :I$GRADE)
  INTO :VAL;
  SUSPEND;

  -- Обучающихся Классов всего очно
  TAG_NAME = V$PREFIX || I$COL || '213:I';
  SELECT COUNT(DISTINCT D.SCHOLAR_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 13275
  JOIN VALL V554 ON V554.OBJ_ID = D.CLASS_ID AND V554.PARAM_ID = 554 AND V554.IS_DEL = 0 AND V554.LISTVAL_ID = 13283
  JOIN VALL V80 ON V80.OBJ_ID = D.SCHOLAR_ID AND V80.PARAM_ID = 80 AND V80.IS_DEL = 0 AND V80.LISTVAL_ID = 5418
  WHERE (:I$GRADE IS NULL OR D.ROW_NUM = :I$GRADE)
  INTO :VAL;
  SUSPEND;

  -- Обучающихся Классов всего очно-заочно
  TAG_NAME = V$PREFIX || I$COL || '214:I';
  SELECT COUNT(DISTINCT D.SCHOLAR_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 13275
  JOIN VALL V554 ON V554.OBJ_ID = D.CLASS_ID AND V554.PARAM_ID = 554 AND V554.IS_DEL = 0 AND V554.LISTVAL_ID = 13283
  JOIN VALL V80 ON V80.OBJ_ID = D.SCHOLAR_ID AND V80.PARAM_ID = 80 AND V80.IS_DEL = 0 AND V80.LISTVAL_ID = 5419
  WHERE (:I$GRADE IS NULL OR D.ROW_NUM = :I$GRADE)
  INTO :VAL;
  SUSPEND;

  -- Обучающихся Классов всего заочно
  TAG_NAME = V$PREFIX || I$COL || '215:I';
  SELECT COUNT(DISTINCT D.SCHOLAR_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 13275
  JOIN VALL V554 ON V554.OBJ_ID = D.CLASS_ID AND V554.PARAM_ID = 554 AND V554.IS_DEL = 0 AND V554.LISTVAL_ID = 13283
  JOIN VALL V80 ON V80.OBJ_ID = D.SCHOLAR_ID AND V80.PARAM_ID = 80 AND V80.IS_DEL = 0 AND V80.LISTVAL_ID = 5420
  WHERE (:I$GRADE IS NULL OR D.ROW_NUM = :I$GRADE)
  INTO :VAL;
  SUSPEND;

  -- Воспитанники ХЗ кто такие

  -- Обучающихся Классов всего девочки
  TAG_NAME = V$PREFIX || I$COL || '218:I';
  SELECT COUNT(DISTINCT D.SCHOLAR_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 13275
  JOIN VALL V554 ON V554.OBJ_ID = D.CLASS_ID AND V554.PARAM_ID = 554 AND V554.IS_DEL = 0 AND V554.LISTVAL_ID = 13283
  JOIN VALL V88 ON V88.OBJ_ID = D.SCHOLAR_ID AND V88.PARAM_ID = 88 AND V88.IS_DEL = 0 AND V88.LISTVAL_ID = 182
  WHERE (:I$GRADE IS NULL OR D.ROW_NUM = :I$GRADE)
  INTO :VAL;
  SUSPEND;

  -- Обучающихся Классов всего ОВЗ
  TAG_NAME = V$PREFIX || I$COL || '219:I';
  SELECT COUNT(DISTINCT D.SCHOLAR_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 13275
  JOIN VALL V554 ON V554.OBJ_ID = D.CLASS_ID AND V554.PARAM_ID = 554 AND V554.IS_DEL = 0 AND V554.LISTVAL_ID = 13283
  JOIN VALL V207 ON V207.OBJ_ID = D.SCHOLAR_ID AND V207.PARAM_ID = 207 AND V207.IS_DEL = 0 AND V207.LISTVAL_ID <> 13289
  WHERE (:I$GRADE IS NULL OR D.ROW_NUM = :I$GRADE)
  INTO :VAL;
  SUSPEND;

  -- Обучающихся Классов всего ОВЗ + инвалиды
  TAG_NAME = V$PREFIX || I$COL || '220:I';
  SELECT COUNT(DISTINCT D.SCHOLAR_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 13275
  JOIN VALL V554 ON V554.OBJ_ID = D.CLASS_ID AND V554.PARAM_ID = 554 AND V554.IS_DEL = 0 AND V554.LISTVAL_ID = 13283
  JOIN VALL V207 ON V207.OBJ_ID = D.SCHOLAR_ID AND V207.PARAM_ID = 207 AND V207.IS_DEL = 0 AND V207.LISTVAL_ID <> 13289
  JOIN LINKS L295 ON L295.PARENT_ID = D.SCHOLAR_ID AND L295.OBJ_TYPE_ID = 295 AND L295.DATE_DEL IS NULL
  JOIN VALL V2373 ON V2373.OBJ_ID = L295.OBJ_ID AND V2373.PARAM_ID = 2373 AND V2373.IS_DEL = 0 AND V2373.LISTVAL_ID <> 11171
  LEFT JOIN VALD V2375 ON V2375.OBJ_ID = L295.OBJ_ID AND V2375.PARAM_ID = 2375 AND V2375.IS_DEL = 0
  WHERE (:I$GRADE IS NULL OR D.ROW_NUM = :I$GRADE) AND (V2375.VAL IS NULL OR V2375.VAL >= :V$DATE)
  INTO :VAL;
  SUSPEND;

  -- Обучающихся Классов всего ОВЗ + дети-инвалиды
  TAG_NAME = V$PREFIX || I$COL || '222:I';
  SELECT COUNT(DISTINCT D.SCHOLAR_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 13275
  JOIN VALL V554 ON V554.OBJ_ID = D.CLASS_ID AND V554.PARAM_ID = 554 AND V554.IS_DEL = 0 AND V554.LISTVAL_ID = 13283
  JOIN VALL V207 ON V207.OBJ_ID = D.SCHOLAR_ID AND V207.PARAM_ID = 207 AND V207.IS_DEL = 0 AND V207.LISTVAL_ID <> 13289
  JOIN LINKS L295 ON L295.PARENT_ID = D.SCHOLAR_ID AND L295.OBJ_TYPE_ID = 295 AND L295.DATE_DEL IS NULL
  JOIN VALL V2373 ON V2373.OBJ_ID = L295.OBJ_ID AND V2373.PARAM_ID = 2373 AND V2373.IS_DEL = 0 AND V2373.LISTVAL_ID = 11171
  LEFT JOIN VALD V2375 ON V2375.OBJ_ID = L295.OBJ_ID AND V2375.PARAM_ID = 2375 AND V2375.IS_DEL = 0
  WHERE (:I$GRADE IS NULL OR D.ROW_NUM = :I$GRADE) AND (V2375.VAL IS NULL OR V2375.VAL >= :V$DATE)
  INTO :VAL;
  SUSPEND;

  -- Обучающихся Классов всего ОВЗ + инвалиды, но не ОВЗ
  TAG_NAME = V$PREFIX || I$COL || '223:I';
  SELECT COUNT(DISTINCT D.SCHOLAR_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 13275
  JOIN VALL V554 ON V554.OBJ_ID = D.CLASS_ID AND V554.PARAM_ID = 554 AND V554.IS_DEL = 0 AND V554.LISTVAL_ID = 13283
  JOIN VALL V207 ON V207.OBJ_ID = D.SCHOLAR_ID AND V207.PARAM_ID = 207 AND V207.IS_DEL = 0 AND V207.LISTVAL_ID = 13289
  JOIN LINKS L295 ON L295.PARENT_ID = D.SCHOLAR_ID AND L295.OBJ_TYPE_ID = 295 AND L295.DATE_DEL IS NULL
  JOIN VALL V2373 ON V2373.OBJ_ID = L295.OBJ_ID AND V2373.PARAM_ID = 2373 AND V2373.IS_DEL = 0 AND V2373.LISTVAL_ID <> 11171
  LEFT JOIN VALD V2375 ON V2375.OBJ_ID = L295.OBJ_ID AND V2375.PARAM_ID = 2375 AND V2375.IS_DEL = 0
  WHERE (:I$GRADE IS NULL OR D.ROW_NUM = :I$GRADE) AND (V2375.VAL IS NULL OR V2375.VAL >= :V$DATE)
  INTO :VAL;
  SUSPEND;

  -- Обучающихся Классов всего ОВЗ + дети-инвалиды, но не ОВЗ
  TAG_NAME = V$PREFIX || I$COL || '224:I';
  SELECT COUNT(DISTINCT D.SCHOLAR_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 13275
  JOIN VALL V554 ON V554.OBJ_ID = D.CLASS_ID AND V554.PARAM_ID = 554 AND V554.IS_DEL = 0 AND V554.LISTVAL_ID = 13283
  JOIN VALL V207 ON V207.OBJ_ID = D.SCHOLAR_ID AND V207.PARAM_ID = 207 AND V207.IS_DEL = 0 AND V207.LISTVAL_ID = 13289
  JOIN LINKS L295 ON L295.PARENT_ID = D.SCHOLAR_ID AND L295.OBJ_TYPE_ID = 295 AND L295.DATE_DEL IS NULL
  JOIN VALL V2373 ON V2373.OBJ_ID = L295.OBJ_ID AND V2373.PARAM_ID = 2373 AND V2373.IS_DEL = 0 AND V2373.LISTVAL_ID = 11171
  LEFT JOIN VALD V2375 ON V2375.OBJ_ID = L295.OBJ_ID AND V2375.PARAM_ID = 2375 AND V2375.IS_DEL = 0
  WHERE (:I$GRADE IS NULL OR D.ROW_NUM = :I$GRADE) AND (V2375.VAL IS NULL OR V2375.VAL >= :V$DATE)
  INTO :VAL;
  SUSPEND;

  -- Обучающихся Классов всего ОВЗ + дети-сироты и без попечения
  TAG_NAME = V$PREFIX || I$COL || '225:I';
  SELECT COUNT(DISTINCT D.SCHOLAR_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 13275
  JOIN VALL V554 ON V554.OBJ_ID = D.CLASS_ID AND V554.PARAM_ID = 554 AND V554.IS_DEL = 0 AND V554.LISTVAL_ID = 13283
  JOIN VALL V2364 ON V2364.OBJ_ID = D.SCHOLAR_ID AND V2364.PARAM_ID = 2364 AND V2364.IS_DEL = 0 AND V2364.LISTVAL_ID IN (11138, 11139)
  WHERE (:I$GRADE IS NULL OR D.ROW_NUM = :I$GRADE)
  INTO :VAL;
  SUSPEND;

  -- Обучающихся Классов всего ОВЗ + иностранцы
  TAG_NAME = V$PREFIX || I$COL || '227:I';
  SELECT COUNT(DISTINCT D.SCHOLAR_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 13275
  JOIN VALL V554 ON V554.OBJ_ID = D.CLASS_ID AND V554.PARAM_ID = 554 AND V554.IS_DEL = 0 AND V554.LISTVAL_ID = 13283
  JOIN VALL V91 ON V91.OBJ_ID = D.SCHOLAR_ID AND V91.PARAM_ID = 91 AND V91.IS_DEL = 0 AND V91.LISTVAL_ID <> 1515
  WHERE (:I$GRADE IS NULL OR D.ROW_NUM = :I$GRADE)
  INTO :VAL;
  SUSPEND;

  -- Обучающихся Классов всего ОВЗ + без гражданства
  TAG_NAME = V$PREFIX || I$COL || '229:I';
  SELECT COUNT(DISTINCT D.SCHOLAR_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 13275
  JOIN VALL V554 ON V554.OBJ_ID = D.CLASS_ID AND V554.PARAM_ID = 554 AND V554.IS_DEL = 0 AND V554.LISTVAL_ID = 13283
  LEFT JOIN VALL V91 ON V91.OBJ_ID = D.SCHOLAR_ID AND V91.PARAM_ID = 91 AND V91.IS_DEL = 0
  WHERE (:I$GRADE IS NULL OR D.ROW_NUM = :I$GRADE) AND V91.LISTVAL_ID IS NULL
  INTO :VAL;
  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE REPORT_OO1_R22 (
    I$STUDY_TYPE BIGINT)
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(100))
AS
declare variable V$YEAR integer;
declare variable V$DATE date;
declare variable V$PREFIX varchar(10);
begin

  -- I$STUDY_TYPE теперь игнорируется

  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R22_COL(:I$STUDY_TYPE, 'AJ', NULL) INTO :TAG_NAME, :VAL DO SUSPEND;

  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R22_COL(:I$STUDY_TYPE, 'AT', 1) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R22_COL(:I$STUDY_TYPE, 'AZ', 2) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R22_COL(:I$STUDY_TYPE, 'BF', 3) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R22_COL(:I$STUDY_TYPE, 'BL', 4) INTO :TAG_NAME, :VAL DO SUSPEND;

  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R22_COL(:I$STUDY_TYPE, 'BR', 5) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R22_COL(:I$STUDY_TYPE, 'BX', 6) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R22_COL(:I$STUDY_TYPE, 'CD', 7) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R22_COL(:I$STUDY_TYPE, 'CJ', 8) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R22_COL(:I$STUDY_TYPE, 'CP', 9) INTO :TAG_NAME, :VAL DO SUSPEND;

  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R22_COL(:I$STUDY_TYPE, 'CV', 10) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R22_COL(:I$STUDY_TYPE, 'DB', -11) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R22_COL(:I$STUDY_TYPE, 'DI', 11) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R22_COL(:I$STUDY_TYPE, 'DP', 12) INTO :TAG_NAME, :VAL DO SUSPEND;

  -- Особые строки по инвалидам формируются внутри запроса по 12-й параллели

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE REPORT_OO1_R22_COL (
    I$STUDY_TYPE BIGINT,
    I$COL VARCHAR(10),
    I$GRADE SMALLINT)
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(100))
AS
declare variable V$PREFIX varchar(10);
declare variable V$GRADE2 integer;
declare variable V$YEAR integer;
declare variable V$DATE date;
declare variable V$CLASS_ID bigint;
declare variable V$CNT integer;
declare variable V$N_ALL integer;
declare variable V$N240 integer;
declare variable V$N242 integer;
declare variable V$N243 integer;
declare variable V$N244 integer;
declare variable V$N245 integer;
declare variable V$N246 integer;
declare variable V$N247 integer;
declare variable V$N248 integer;
declare variable V$N249 integer;
declare variable V$N250 integer;
declare variable V$N251 integer;
declare variable V$N252 integer;
begin

  -- Только для общеобразовательных классов

  V$YEAR = EXTRACT(YEAR FROM CURRENT_DATE);
  IF(EXTRACT(MONTH FROM CURRENT_DATE) < 9) THEN V$YEAR = V$YEAR - 1;
  V$DATE = '20.09.' || V$YEAR;

  V$PREFIX = '@3:';

  -- 11-е классы считаются отдельно выпускные и не-выпускные
  IF(I$GRADE NOT IN (11, -11)) THEN V$GRADE2 = - I$GRADE;

  -- Собираем статистику
  V$CNT = 0;
  V$N_ALL = 0;
  V$N240 = 0;
  V$N242 = 0;
  V$N243 = 0;
  V$N244 = 0;
  V$N245 = 0;
  V$N246 = 0;
  V$N247 = 0;
  V$N248 = 0;
  V$N249 = 0;
  V$N250 = 0;
  V$N251 = 0;
  V$N252 = 0;

  FOR
      SELECT DISTINCT D.CLASS_ID
      FROM REPORT_D12 D
      JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 197
      JOIN VALL V208 ON V208.OBJ_ID = D.SCHOLAR_ID AND V208.PARAM_ID = 208 AND V208.IS_DEL = 0 AND V208.LISTVAL_ID <> 499
      WHERE (:I$GRADE IS NULL OR D.ROW_NUM = :I$GRADE OR D.ROW_NUM = :V$GRADE2)
      INTO :V$CLASS_ID
  DO
  BEGIN

      V$CNT = V$CNT + 1;
      V$N_ALL = V$N_ALL + (
          SELECT COUNT(*)
          FROM REPORT_D12 D
          WHERE D.CLASS_ID = :V$CLASS_ID
      );

      -- Глухие
      V$N240 = V$N240 + (
          SELECT COUNT(*)
          FROM REPORT_D12 D
          JOIN VALL V2364 ON V2364.OBJ_ID = D.SCHOLAR_ID AND V2364.PARAM_ID = 2364 AND V2364.IS_DEL = 0 AND V2364.LISTVAL_ID = 999999 -- !!!
          WHERE D.CLASS_ID = :V$CLASS_ID
      );

      -- Слабослышащие
      V$N242 = V$N242 + (
          SELECT COUNT(*)
          FROM REPORT_D12 D
          JOIN VALL V2364 ON V2364.OBJ_ID = D.SCHOLAR_ID AND V2364.PARAM_ID = 2364 AND V2364.IS_DEL = 0 AND V2364.LISTVAL_ID = 11147
          WHERE D.CLASS_ID = :V$CLASS_ID
      );

      -- Позднооглохшие
      V$N243 = V$N243 + (
          SELECT COUNT(*)
          FROM REPORT_D12 D
          JOIN VALL V2364 ON V2364.OBJ_ID = D.SCHOLAR_ID AND V2364.PARAM_ID = 2364 AND V2364.IS_DEL = 0 AND V2364.LISTVAL_ID = 999999 -- !!!
          WHERE D.CLASS_ID = :V$CLASS_ID
      );

      -- Слепые
      V$N244 = V$N244 + (
          SELECT COUNT(*)
          FROM REPORT_D12 D
          JOIN VALL V2364 ON V2364.OBJ_ID = D.SCHOLAR_ID AND V2364.PARAM_ID = 2364 AND V2364.IS_DEL = 0 AND V2364.LISTVAL_ID = 999999 -- !!!
          WHERE D.CLASS_ID = :V$CLASS_ID
      );

      -- Слабовидящие
      V$N245 = V$N245 + (
          SELECT COUNT(*)
          FROM REPORT_D12 D
          JOIN VALL V2364 ON V2364.OBJ_ID = D.SCHOLAR_ID AND V2364.PARAM_ID = 2364 AND V2364.IS_DEL = 0 AND V2364.LISTVAL_ID = 11148
          WHERE D.CLASS_ID = :V$CLASS_ID
      );

      -- Тяжелые нарушения речи
      V$N246 = V$N246 + (
          SELECT COUNT(*)
          FROM REPORT_D12 D
          JOIN VALL V2364 ON V2364.OBJ_ID = D.SCHOLAR_ID AND V2364.PARAM_ID = 2364 AND V2364.IS_DEL = 0 AND V2364.LISTVAL_ID = 11149
          WHERE D.CLASS_ID = :V$CLASS_ID
      );

      -- Нарушения ОДП
      V$N247 = V$N247 + (
          SELECT COUNT(*)
          FROM REPORT_D12 D
          JOIN VALL V2364 ON V2364.OBJ_ID = D.SCHOLAR_ID AND V2364.PARAM_ID = 2364 AND V2364.IS_DEL = 0 AND V2364.LISTVAL_ID IN (11150, 11151)
          WHERE D.CLASS_ID = :V$CLASS_ID
      );

      -- Задержка псих. развития
      V$N248 = V$N248 + (
          SELECT COUNT(*)
          FROM REPORT_D12 D
          JOIN VALL V2364 ON V2364.OBJ_ID = D.SCHOLAR_ID AND V2364.PARAM_ID = 2364 AND V2364.IS_DEL = 0 AND V2364.LISTVAL_ID = 11154
          WHERE D.CLASS_ID = :V$CLASS_ID
      );

      -- УО
      V$N249 = V$N249 + (
          SELECT COUNT(*)
          FROM REPORT_D12 D
          JOIN VALL V2364 ON V2364.OBJ_ID = D.SCHOLAR_ID AND V2364.PARAM_ID = 2364 AND V2364.IS_DEL = 0 AND V2364.LISTVAL_ID = 11152
          WHERE D.CLASS_ID = :V$CLASS_ID
      );

      -- аутизм
      V$N250 = V$N250 + (
          SELECT COUNT(*)
          FROM REPORT_D12 D
          JOIN VALL V2364 ON V2364.OBJ_ID = D.SCHOLAR_ID AND V2364.PARAM_ID = 2364 AND V2364.IS_DEL = 0 AND V2364.LISTVAL_ID = 11153
          WHERE D.CLASS_ID = :V$CLASS_ID
      );

      -- сложные дефекты
      V$N251 = V$N251 + (
          SELECT COUNT(*)
          FROM REPORT_D12 D
          JOIN VALL V2364 ON V2364.OBJ_ID = D.SCHOLAR_ID AND V2364.PARAM_ID = 2364 AND V2364.IS_DEL = 0 AND V2364.LISTVAL_ID = 11157
          WHERE D.CLASS_ID = :V$CLASS_ID
      );

      -- с иными ОВЗ - группа здоровья кроме 1-й, и не задан ранее перечисленный вид ОВЗ
      V$N252 = V$N252 + (
          SELECT COUNT(*)
          FROM REPORT_D12 D
          JOIN VALL V208 ON V208.OBJ_ID = D.SCHOLAR_ID AND V208.PARAM_ID = 208 AND V208.IS_DEL = 0 AND V208.LISTVAL_ID <> 499
          LEFT JOIN VALL V2364 ON V2364.OBJ_ID = D.SCHOLAR_ID AND V2364.PARAM_ID = 2364 AND V2364.IS_DEL = 0
          LEFT JOIN LISTVALS LP ON LP.LISTVAL_ID = V2364.LISTVAL_ID
          WHERE D.CLASS_ID = :V$CLASS_ID
              AND (V2364.LISTVAL_ID IS NULL OR (LP.PARENT_ID = 11146 AND LP.LISTVAL_ID NOT IN (11147, 11148, 11149, 11150, 11151, 11152, 11153, 11154, 11157)))
      );

  END

  -- Классов всего
  TAG_NAME = V$PREFIX || I$COL || '238:I';
  VAL = V$CNT;
  SUSPEND;

  -- Учащихся всего
  TAG_NAME = V$PREFIX || I$COL || '239:I';
  VAL = V$N_ALL;
  SUSPEND;

  TAG_NAME = V$PREFIX || I$COL || '240:I';
  VAL = V$N240;
  SUSPEND;

  TAG_NAME = V$PREFIX || I$COL || '242:I';
  VAL = V$N242;
  SUSPEND;

  TAG_NAME = V$PREFIX || I$COL || '243:I';
  VAL = V$N243;
  SUSPEND;

  TAG_NAME = V$PREFIX || I$COL || '244:I';
  VAL = V$N244;
  SUSPEND;

  TAG_NAME = V$PREFIX || I$COL || '245:I';
  VAL = V$N245;
  SUSPEND;

  TAG_NAME = V$PREFIX || I$COL || '246:I';
  VAL = V$N246;
  SUSPEND;

  TAG_NAME = V$PREFIX || I$COL || '247:I';
  VAL = V$N247;
  SUSPEND;

  TAG_NAME = V$PREFIX || I$COL || '248:I';
  VAL = V$N248;
  SUSPEND;

  TAG_NAME = V$PREFIX || I$COL || '249:I';
  VAL = V$N249;
  SUSPEND;

  TAG_NAME = V$PREFIX || I$COL || '250:I';
  VAL = V$N250;
  SUSPEND;

  TAG_NAME = V$PREFIX || I$COL || '251:I';
  VAL = V$N251;
  SUSPEND;

  TAG_NAME = V$PREFIX || I$COL || '252:I';
  VAL = V$N252;
  SUSPEND;

  -- Для 12-й параллели делаем еще две дополнительных выборки по инвалидам и детям инвалидам
  IF(I$GRADE IS NULL OR I$GRADE <> 12) THEN EXIT;

  -- !!!

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE REPORT_OO1_R23 (
    I$STUDY_TYPE BIGINT)
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(100))
AS
begin

  -- I$STUDY_TYPE больше не имеет значения

  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R23_ROW(1, :I$STUDY_TYPE) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R23_ROW(2, :I$STUDY_TYPE) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R23_ROW(4, :I$STUDY_TYPE) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R23_ROW(5, :I$STUDY_TYPE) INTO :TAG_NAME, :VAL DO SUSPEND;
  --FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R23_ROW(6, :I$STUDY_TYPE) INTO :TAG_NAME, :VAL DO SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE REPORT_OO1_R23_ROW (
    I$ROW SMALLINT,
    I$STUDY_TYPE BIGINT)
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(100))
AS
declare variable V$PREFIX varchar(10);
declare variable V$RS varchar(10);
declare variable V$YEAR integer;
declare variable V$DATE date;
declare variable V$FILTER_PERSONAL bigint;
declare variable V$FILTER_NET bigint;
declare variable V$FILTER_DIST bigint;
begin

  V$YEAR = EXTRACT(YEAR FROM CURRENT_DATE);
  IF(EXTRACT(MONTH FROM CURRENT_DATE) < 9) THEN V$YEAR = V$YEAR - 1;
  V$DATE = '20.09.' || V$YEAR;

  V$PREFIX = '@3:';

  -- I$STUDY_TYPE пофиг

  IF(I$ROW = 2) THEN V$FILTER_NET = 2; -- сетевое обучение
  -- IF(I$ROW = 3) THEN ...; -- электронное обучение
  IF(I$ROW = 4) THEN V$FILTER_DIST = 2; -- дистанционные технологии
  IF(I$ROW = 5) THEN V$FILTER_PERSONAL = 1; -- индивидуальные УП
  -- IF(I$ROW = 6) THEN ...; -- обучение на дому
  -- IF(I$ROW = 7) THEN ...; -- обучение в медицинской организации
  -- строки 8 и 9 вообще не считаем

  IF(I$ROW = 1) THEN V$RS = '262';
  ELSE IF(I$ROW = 2) THEN V$RS = '263';
  ELSE IF(I$ROW = 3) THEN V$RS = '265';
  ELSE IF(I$ROW = 4) THEN V$RS = '266';
  ELSE IF(I$ROW = 5) THEN V$RS = '267';
  ELSE IF(I$ROW = 6) THEN V$RS = '268';
  ELSE IF(I$ROW = 7) THEN V$RS = '269';

  -- Всего
  TAG_NAME = V$PREFIX || 'AN' || V$RS || ':I';
  SELECT COUNT(*)
  FROM REPORT_D12 D
  LEFT JOIN VALL V1891 ON V1891.OBJ_ID = D.CLASS_TYPE_ID AND V1891.PARAM_ID = 1891 AND V1891.IS_DEL = 0
  LEFT JOIN VALL V2833 ON V2833.OBJ_ID = D.CLASS_TYPE_ID AND V2833.PARAM_ID = 2833 AND V2833.IS_DEL = 0
  WHERE (:V$FILTER_PERSONAL IS NULL OR D.C2 = :V$FILTER_PERSONAL) AND (:V$FILTER_NET IS NULL OR V1891.LISTVAL_ID = :V$FILTER_NET)
    AND (:V$FILTER_DIST IS NULL OR V2833.LISTVAL_ID = :V$FILTER_DIST)
  INTO :VAL;
  SUSPEND;

  -- Всего обучающихся, обычные классы
  TAG_NAME = V$PREFIX || 'AX' || V$RS || ':I';
  SELECT COUNT(*)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 197
  LEFT JOIN VALL V1891 ON V1891.OBJ_ID = D.CLASS_TYPE_ID AND V1891.PARAM_ID = 1891 AND V1891.IS_DEL = 0
  LEFT JOIN VALL V2833 ON V2833.OBJ_ID = D.CLASS_TYPE_ID AND V2833.PARAM_ID = 2833 AND V2833.IS_DEL = 0
  WHERE (:V$FILTER_PERSONAL IS NULL OR D.C2 = :V$FILTER_PERSONAL) AND (:V$FILTER_NET IS NULL OR V1891.LISTVAL_ID = :V$FILTER_NET)
    AND (:V$FILTER_DIST IS NULL OR V2833.LISTVAL_ID = :V$FILTER_DIST)
  INTO :VAL;
  SUSPEND;
  -- Учащиеся с ОВЗ, обычные классы
  TAG_NAME = V$PREFIX || 'BE' || V$RS || ':I';
  SELECT COUNT(*)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 197
  JOIN VALL V208 ON V208.OBJ_ID = D.SCHOLAR_ID AND V208.PARAM_ID = 208 AND V208.IS_DEL = 0 AND V208.LISTVAL_ID <> 499
  LEFT JOIN VALL V1891 ON V1891.OBJ_ID = D.CLASS_TYPE_ID AND V1891.PARAM_ID = 1891 AND V1891.IS_DEL = 0
  LEFT JOIN VALL V2833 ON V2833.OBJ_ID = D.CLASS_TYPE_ID AND V2833.PARAM_ID = 2833 AND V2833.IS_DEL = 0
  WHERE (:V$FILTER_PERSONAL IS NULL OR D.C2 = :V$FILTER_PERSONAL) AND (:V$FILTER_NET IS NULL OR V1891.LISTVAL_ID = :V$FILTER_NET)
    AND (:V$FILTER_DIST IS NULL OR V2833.LISTVAL_ID = :V$FILTER_DIST)
  INTO :VAL;
  SUSPEND;
  -- Учащиеся-инвалиды с ОВЗ, обычные классы
  TAG_NAME = V$PREFIX || 'BN' || V$RS || ':I';
  SELECT COUNT(DISTINCT D.SCHOLAR_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 197
  JOIN VALL V208 ON V208.OBJ_ID = D.SCHOLAR_ID AND V208.PARAM_ID = 208 AND V208.IS_DEL = 0 AND V208.LISTVAL_ID <> 499
  JOIN LINKS L295 ON L295.PARENT_ID = D.SCHOLAR_ID AND L295.OBJ_TYPE_ID = 295 AND L295.DATE_DEL IS NULL
  JOIN VALL V2373 ON V2373.OBJ_ID = L295.OBJ_ID AND V2373.PARAM_ID = 2373 AND V2373.IS_DEL = 0 AND V2373.LISTVAL_ID <> 11171
  LEFT JOIN VALD V2375 ON V2375.OBJ_ID = L295.OBJ_ID AND V2375.PARAM_ID = 2375 AND V2375.IS_DEL = 0
  LEFT JOIN VALL V1891 ON V1891.OBJ_ID = D.CLASS_TYPE_ID AND V1891.PARAM_ID = 1891 AND V1891.IS_DEL = 0
  LEFT JOIN VALL V2833 ON V2833.OBJ_ID = D.CLASS_TYPE_ID AND V2833.PARAM_ID = 2833 AND V2833.IS_DEL = 0
  WHERE (:V$FILTER_PERSONAL IS NULL OR D.C2 = :V$FILTER_PERSONAL) AND (:V$FILTER_NET IS NULL OR V1891.LISTVAL_ID = :V$FILTER_NET)
    AND (:V$FILTER_DIST IS NULL OR V2833.LISTVAL_ID = :V$FILTER_DIST)
    AND (V2375.VAL IS NULL OR V2375.VAL >= :V$DATE)
  INTO :VAL;
  SUSPEND;
  -- Учащиеся-дети-инвалиды с ОВЗ, обычные классы
  TAG_NAME = V$PREFIX || 'BW' || V$RS || ':I';
  SELECT COUNT(DISTINCT D.SCHOLAR_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 197
  JOIN VALL V208 ON V208.OBJ_ID = D.SCHOLAR_ID AND V208.PARAM_ID = 208 AND V208.IS_DEL = 0 AND V208.LISTVAL_ID <> 499
  JOIN LINKS L295 ON L295.PARENT_ID = D.SCHOLAR_ID AND L295.OBJ_TYPE_ID = 295 AND L295.DATE_DEL IS NULL
  JOIN VALL V2373 ON V2373.OBJ_ID = L295.OBJ_ID AND V2373.PARAM_ID = 2373 AND V2373.IS_DEL = 0 AND V2373.LISTVAL_ID = 11171
  LEFT JOIN VALD V2375 ON V2375.OBJ_ID = L295.OBJ_ID AND V2375.PARAM_ID = 2375 AND V2375.IS_DEL = 0
  LEFT JOIN VALL V1891 ON V1891.OBJ_ID = D.CLASS_TYPE_ID AND V1891.PARAM_ID = 1891 AND V1891.IS_DEL = 0
  LEFT JOIN VALL V2833 ON V2833.OBJ_ID = D.CLASS_TYPE_ID AND V2833.PARAM_ID = 2833 AND V2833.IS_DEL = 0
  WHERE (:V$FILTER_PERSONAL IS NULL OR D.C2 = :V$FILTER_PERSONAL) AND (:V$FILTER_NET IS NULL OR V1891.LISTVAL_ID = :V$FILTER_NET)
    AND (:V$FILTER_DIST IS NULL OR V2833.LISTVAL_ID = :V$FILTER_DIST)
    AND (V2375.VAL IS NULL OR V2375.VAL >= :V$DATE)
  INTO :VAL;
  SUSPEND;
  -- Учащиеся-инвалиды без ОВЗ, обычные классы
  TAG_NAME = V$PREFIX || 'CE' || V$RS || ':I';
  SELECT COUNT(DISTINCT D.SCHOLAR_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 197
  JOIN VALL V208 ON V208.OBJ_ID = D.SCHOLAR_ID AND V208.PARAM_ID = 208 AND V208.IS_DEL = 0 AND V208.LISTVAL_ID = 499
  JOIN LINKS L295 ON L295.PARENT_ID = D.SCHOLAR_ID AND L295.OBJ_TYPE_ID = 295 AND L295.DATE_DEL IS NULL
  JOIN VALL V2373 ON V2373.OBJ_ID = L295.OBJ_ID AND V2373.PARAM_ID = 2373 AND V2373.IS_DEL = 0 AND V2373.LISTVAL_ID <> 11171
  LEFT JOIN VALD V2375 ON V2375.OBJ_ID = L295.OBJ_ID AND V2375.PARAM_ID = 2375 AND V2375.IS_DEL = 0
  LEFT JOIN VALL V1891 ON V1891.OBJ_ID = D.CLASS_TYPE_ID AND V1891.PARAM_ID = 1891 AND V1891.IS_DEL = 0
  LEFT JOIN VALL V2833 ON V2833.OBJ_ID = D.CLASS_TYPE_ID AND V2833.PARAM_ID = 2833 AND V2833.IS_DEL = 0
  WHERE (:V$FILTER_PERSONAL IS NULL OR D.C2 = :V$FILTER_PERSONAL) AND (:V$FILTER_NET IS NULL OR V1891.LISTVAL_ID = :V$FILTER_NET)
    AND (:V$FILTER_DIST IS NULL OR V2833.LISTVAL_ID = :V$FILTER_DIST)
    AND (V2375.VAL IS NULL OR V2375.VAL >= :V$DATE)
  INTO :VAL;
  SUSPEND;
  -- Учащиеся-дети-инвалиды без ОВЗ, обычные классы
  TAG_NAME = V$PREFIX || 'CM' || V$RS || ':I';
  SELECT COUNT(DISTINCT D.SCHOLAR_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 197
  JOIN VALL V208 ON V208.OBJ_ID = D.SCHOLAR_ID AND V208.PARAM_ID = 208 AND V208.IS_DEL = 0 AND V208.LISTVAL_ID = 499
  JOIN LINKS L295 ON L295.PARENT_ID = D.SCHOLAR_ID AND L295.OBJ_TYPE_ID = 295 AND L295.DATE_DEL IS NULL
  JOIN VALL V2373 ON V2373.OBJ_ID = L295.OBJ_ID AND V2373.PARAM_ID = 2373 AND V2373.IS_DEL = 0 AND V2373.LISTVAL_ID = 11171
  LEFT JOIN VALD V2375 ON V2375.OBJ_ID = L295.OBJ_ID AND V2375.PARAM_ID = 2375 AND V2375.IS_DEL = 0
  LEFT JOIN VALL V1891 ON V1891.OBJ_ID = D.CLASS_TYPE_ID AND V1891.PARAM_ID = 1891 AND V1891.IS_DEL = 0
  LEFT JOIN VALL V2833 ON V2833.OBJ_ID = D.CLASS_TYPE_ID AND V2833.PARAM_ID = 2833 AND V2833.IS_DEL = 0
  WHERE (:V$FILTER_PERSONAL IS NULL OR D.C2 = :V$FILTER_PERSONAL) AND (:V$FILTER_NET IS NULL OR V1891.LISTVAL_ID = :V$FILTER_NET)
    AND (:V$FILTER_DIST IS NULL OR V2833.LISTVAL_ID = :V$FILTER_DIST)
    AND (V2375.VAL IS NULL OR V2375.VAL >= :V$DATE)
  INTO :VAL;
  SUSPEND;

  -- Всего обучающихся, классы ОВЗ
  TAG_NAME = V$PREFIX || 'CU' || V$RS || ':I';
  SELECT COUNT(*)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID <> 197
  LEFT JOIN VALL V1891 ON V1891.OBJ_ID = D.CLASS_TYPE_ID AND V1891.PARAM_ID = 1891 AND V1891.IS_DEL = 0
  LEFT JOIN VALL V2833 ON V2833.OBJ_ID = D.CLASS_TYPE_ID AND V2833.PARAM_ID = 2833 AND V2833.IS_DEL = 0
  WHERE (:V$FILTER_PERSONAL IS NULL OR D.C2 = :V$FILTER_PERSONAL) AND (:V$FILTER_NET IS NULL OR V1891.LISTVAL_ID = :V$FILTER_NET)
    AND (:V$FILTER_DIST IS NULL OR V2833.LISTVAL_ID = :V$FILTER_DIST)
  INTO :VAL;
  SUSPEND;
  -- Учащиеся с ОВЗ, классы ОВЗ
  TAG_NAME = V$PREFIX || 'DB' || V$RS || ':I';
  SELECT COUNT(*)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID <> 197
  JOIN VALL V208 ON V208.OBJ_ID = D.SCHOLAR_ID AND V208.PARAM_ID = 208 AND V208.IS_DEL = 0 AND V208.LISTVAL_ID <> 499
  LEFT JOIN VALL V1891 ON V1891.OBJ_ID = D.CLASS_TYPE_ID AND V1891.PARAM_ID = 1891 AND V1891.IS_DEL = 0
  LEFT JOIN VALL V2833 ON V2833.OBJ_ID = D.CLASS_TYPE_ID AND V2833.PARAM_ID = 2833 AND V2833.IS_DEL = 0
  WHERE (:V$FILTER_PERSONAL IS NULL OR D.C2 = :V$FILTER_PERSONAL) AND (:V$FILTER_NET IS NULL OR V1891.LISTVAL_ID = :V$FILTER_NET)
    AND (:V$FILTER_DIST IS NULL OR V2833.LISTVAL_ID = :V$FILTER_DIST)
  INTO :VAL;
  SUSPEND;
  -- Учащиеся-инвалиды с ОВЗ, классы ОВЗ
  TAG_NAME = V$PREFIX || 'DK' || V$RS || ':I';
  SELECT COUNT(DISTINCT D.SCHOLAR_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID <> 197
  JOIN VALL V208 ON V208.OBJ_ID = D.SCHOLAR_ID AND V208.PARAM_ID = 208 AND V208.IS_DEL = 0 AND V208.LISTVAL_ID <> 499
  JOIN LINKS L295 ON L295.PARENT_ID = D.SCHOLAR_ID AND L295.OBJ_TYPE_ID = 295 AND L295.DATE_DEL IS NULL
  JOIN VALL V2373 ON V2373.OBJ_ID = L295.OBJ_ID AND V2373.PARAM_ID = 2373 AND V2373.IS_DEL = 0 AND V2373.LISTVAL_ID <> 11171
  LEFT JOIN VALD V2375 ON V2375.OBJ_ID = L295.OBJ_ID AND V2375.PARAM_ID = 2375 AND V2375.IS_DEL = 0
  LEFT JOIN VALL V1891 ON V1891.OBJ_ID = D.CLASS_TYPE_ID AND V1891.PARAM_ID = 1891 AND V1891.IS_DEL = 0
  LEFT JOIN VALL V2833 ON V2833.OBJ_ID = D.CLASS_TYPE_ID AND V2833.PARAM_ID = 2833 AND V2833.IS_DEL = 0
  WHERE (:V$FILTER_PERSONAL IS NULL OR D.C2 = :V$FILTER_PERSONAL) AND (:V$FILTER_NET IS NULL OR V1891.LISTVAL_ID = :V$FILTER_NET)
    AND (:V$FILTER_DIST IS NULL OR V2833.LISTVAL_ID = :V$FILTER_DIST)
    AND (V2375.VAL IS NULL OR V2375.VAL >= :V$DATE)
  INTO :VAL;
  SUSPEND;
  -- Учащиеся-дети-инвалиды с ОВЗ, классы ОВЗ
  TAG_NAME = V$PREFIX || 'DT' || V$RS || ':I';
  SELECT COUNT(DISTINCT D.SCHOLAR_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID <> 197
  JOIN VALL V208 ON V208.OBJ_ID = D.SCHOLAR_ID AND V208.PARAM_ID = 208 AND V208.IS_DEL = 0 AND V208.LISTVAL_ID <> 499
  JOIN LINKS L295 ON L295.PARENT_ID = D.SCHOLAR_ID AND L295.OBJ_TYPE_ID = 295 AND L295.DATE_DEL IS NULL
  JOIN VALL V2373 ON V2373.OBJ_ID = L295.OBJ_ID AND V2373.PARAM_ID = 2373 AND V2373.IS_DEL = 0 AND V2373.LISTVAL_ID = 11171
  LEFT JOIN VALD V2375 ON V2375.OBJ_ID = L295.OBJ_ID AND V2375.PARAM_ID = 2375 AND V2375.IS_DEL = 0
  LEFT JOIN VALL V1891 ON V1891.OBJ_ID = D.CLASS_TYPE_ID AND V1891.PARAM_ID = 1891 AND V1891.IS_DEL = 0
  LEFT JOIN VALL V2833 ON V2833.OBJ_ID = D.CLASS_TYPE_ID AND V2833.PARAM_ID = 2833 AND V2833.IS_DEL = 0
  WHERE (:V$FILTER_PERSONAL IS NULL OR D.C2 = :V$FILTER_PERSONAL) AND (:V$FILTER_NET IS NULL OR V1891.LISTVAL_ID = :V$FILTER_NET)
    AND (:V$FILTER_DIST IS NULL OR V2833.LISTVAL_ID = :V$FILTER_DIST)
    AND (V2375.VAL IS NULL OR V2375.VAL >= :V$DATE)
  INTO :VAL;
  SUSPEND;
  -- Учащиеся-инвалиды без ОВЗ, классы ОВЗ
  TAG_NAME = V$PREFIX || 'EB' || V$RS || ':I';
  SELECT COUNT(DISTINCT D.SCHOLAR_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID <> 197
  JOIN VALL V208 ON V208.OBJ_ID = D.SCHOLAR_ID AND V208.PARAM_ID = 208 AND V208.IS_DEL = 0 AND V208.LISTVAL_ID = 499
  JOIN LINKS L295 ON L295.PARENT_ID = D.SCHOLAR_ID AND L295.OBJ_TYPE_ID = 295 AND L295.DATE_DEL IS NULL
  JOIN VALL V2373 ON V2373.OBJ_ID = L295.OBJ_ID AND V2373.PARAM_ID = 2373 AND V2373.IS_DEL = 0 AND V2373.LISTVAL_ID <> 11171
  LEFT JOIN VALD V2375 ON V2375.OBJ_ID = L295.OBJ_ID AND V2375.PARAM_ID = 2375 AND V2375.IS_DEL = 0
  LEFT JOIN VALL V1891 ON V1891.OBJ_ID = D.CLASS_TYPE_ID AND V1891.PARAM_ID = 1891 AND V1891.IS_DEL = 0
  LEFT JOIN VALL V2833 ON V2833.OBJ_ID = D.CLASS_TYPE_ID AND V2833.PARAM_ID = 2833 AND V2833.IS_DEL = 0
  WHERE (:V$FILTER_PERSONAL IS NULL OR D.C2 = :V$FILTER_PERSONAL) AND (:V$FILTER_NET IS NULL OR V1891.LISTVAL_ID = :V$FILTER_NET)
    AND (:V$FILTER_DIST IS NULL OR V2833.LISTVAL_ID = :V$FILTER_DIST)
    AND (V2375.VAL IS NULL OR V2375.VAL >= :V$DATE)
  INTO :VAL;
  SUSPEND;
  -- Учащиеся-дети-инвалиды без ОВЗ, классы ОВЗ
  TAG_NAME = V$PREFIX || 'EJ' || V$RS || ':I';
  SELECT COUNT(DISTINCT D.SCHOLAR_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID <> 197
  JOIN VALL V208 ON V208.OBJ_ID = D.SCHOLAR_ID AND V208.PARAM_ID = 208 AND V208.IS_DEL = 0 AND V208.LISTVAL_ID = 499
  JOIN LINKS L295 ON L295.PARENT_ID = D.SCHOLAR_ID AND L295.OBJ_TYPE_ID = 295 AND L295.DATE_DEL IS NULL
  JOIN VALL V2373 ON V2373.OBJ_ID = L295.OBJ_ID AND V2373.PARAM_ID = 2373 AND V2373.IS_DEL = 0 AND V2373.LISTVAL_ID = 11171
  LEFT JOIN VALD V2375 ON V2375.OBJ_ID = L295.OBJ_ID AND V2375.PARAM_ID = 2375 AND V2375.IS_DEL = 0
  LEFT JOIN VALL V1891 ON V1891.OBJ_ID = D.CLASS_TYPE_ID AND V1891.PARAM_ID = 1891 AND V1891.IS_DEL = 0
  LEFT JOIN VALL V2833 ON V2833.OBJ_ID = D.CLASS_TYPE_ID AND V2833.PARAM_ID = 2833 AND V2833.IS_DEL = 0
  WHERE (:V$FILTER_PERSONAL IS NULL OR D.C2 = :V$FILTER_PERSONAL) AND (:V$FILTER_NET IS NULL OR V1891.LISTVAL_ID = :V$FILTER_NET)
    AND (:V$FILTER_DIST IS NULL OR V2833.LISTVAL_ID = :V$FILTER_DIST)
    AND (V2375.VAL IS NULL OR V2375.VAL >= :V$DATE)
  INTO :VAL;
  SUSPEND;

  -- Разбивка по очности обучения
  -- очно
  TAG_NAME = V$PREFIX || 'ER' || V$RS || ':I';
  SELECT COUNT(*)
  FROM REPORT_D12 D
  JOIN VALL V80 ON V80.OBJ_ID = D.SCHOLAR_ID AND V80.PARAM_ID = 80 AND V80.IS_DEL = 0 AND V80.LISTVAL_ID = 5418
  LEFT JOIN VALL V1891 ON V1891.OBJ_ID = D.CLASS_TYPE_ID AND V1891.PARAM_ID = 1891 AND V1891.IS_DEL = 0
  LEFT JOIN VALL V2833 ON V2833.OBJ_ID = D.CLASS_TYPE_ID AND V2833.PARAM_ID = 2833 AND V2833.IS_DEL = 0
  WHERE (:V$FILTER_PERSONAL IS NULL OR D.C2 = :V$FILTER_PERSONAL) AND (:V$FILTER_NET IS NULL OR V1891.LISTVAL_ID = :V$FILTER_NET)
    AND (:V$FILTER_DIST IS NULL OR V2833.LISTVAL_ID = :V$FILTER_DIST)
  INTO :VAL;
  SUSPEND;

  -- очно-заочно
  TAG_NAME = V$PREFIX || 'EX' || V$RS || ':I';
  SELECT COUNT(*)
  FROM REPORT_D12 D
  JOIN VALL V80 ON V80.OBJ_ID = D.SCHOLAR_ID AND V80.PARAM_ID = 80 AND V80.IS_DEL = 0 AND V80.LISTVAL_ID = 5419
  LEFT JOIN VALL V1891 ON V1891.OBJ_ID = D.CLASS_TYPE_ID AND V1891.PARAM_ID = 1891 AND V1891.IS_DEL = 0
  LEFT JOIN VALL V2833 ON V2833.OBJ_ID = D.CLASS_TYPE_ID AND V2833.PARAM_ID = 2833 AND V2833.IS_DEL = 0
  WHERE (:V$FILTER_PERSONAL IS NULL OR D.C2 = :V$FILTER_PERSONAL) AND (:V$FILTER_NET IS NULL OR V1891.LISTVAL_ID = :V$FILTER_NET)
    AND (:V$FILTER_DIST IS NULL OR V2833.LISTVAL_ID = :V$FILTER_DIST)
  INTO :VAL;
  SUSPEND;

  -- заочно
  TAG_NAME = V$PREFIX || 'FE' || V$RS || ':I';
  SELECT COUNT(*)
  FROM REPORT_D12 D
  JOIN VALL V80 ON V80.OBJ_ID = D.SCHOLAR_ID AND V80.PARAM_ID = 80 AND V80.IS_DEL = 0 AND V80.LISTVAL_ID = 5420
  LEFT JOIN VALL V1891 ON V1891.OBJ_ID = D.CLASS_TYPE_ID AND V1891.PARAM_ID = 1891 AND V1891.IS_DEL = 0
  LEFT JOIN VALL V2833 ON V2833.OBJ_ID = D.CLASS_TYPE_ID AND V2833.PARAM_ID = 2833 AND V2833.IS_DEL = 0
  WHERE (:V$FILTER_PERSONAL IS NULL OR D.C2 = :V$FILTER_PERSONAL) AND (:V$FILTER_NET IS NULL OR V1891.LISTVAL_ID = :V$FILTER_NET)
    AND (:V$FILTER_DIST IS NULL OR V2833.LISTVAL_ID = :V$FILTER_DIST)
  INTO :VAL;
  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE REPORT_OO1_R24 (
    I$OU_ID BIGINT,
    I$STUDY_TYPE BIGINT)
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(100))
AS
declare variable V$PREFIX varchar(10);
declare variable V$OU_AREA bigint;
declare variable V$COL varchar(10);
declare variable V$N integer;
begin

  V$PREFIX = '@4:';

  IF(I$STUDY_TYPE = 5418) THEN V$COL = 'BS';
  ELSE IF(I$STUDY_TYPE = 5419) THEN V$COL = 'EE';
  ELSE IF(I$STUDY_TYPE = 5420) THEN V$COL = 'ES';

  -- Тип школы - городская или сельская ?
  SELECT COALESCE(V15.LISTVAL_ID, 1045)
  FROM VALL V15
  WHERE V15.OBJ_ID = :I$OU_ID AND V15.PARAM_ID = 15 AND V15.IS_DEL = 0
  INTO :V$OU_AREA;

  IF(V$OU_AREA = 1046) THEN V$N = 14; ELSE V$N = 25;

  -- Всего классов
  TAG_NAME = V$PREFIX || V$COL || '9:I';
  SELECT COUNT(DISTINCT D.CLASS_ID)
  FROM REPORT_D12 D
  JOIN VALL V80 ON V80.OBJ_ID = D.SCHOLAR_ID AND V80.PARAM_ID = 80 AND V80.IS_DEL = 0 AND V80.LISTVAL_ID = :I$STUDY_TYPE
  INTO :VAL;
  SUSPEND;

  -- 1-4 классы
  TAG_NAME = V$PREFIX || V$COL || '10:I';
  SELECT COUNT(DISTINCT D.CLASS_ID)
  FROM REPORT_D12 D
  JOIN VALL V80 ON V80.OBJ_ID = D.SCHOLAR_ID AND V80.PARAM_ID = 80 AND V80.IS_DEL = 0 AND V80.LISTVAL_ID = :I$STUDY_TYPE
  WHERE D.ROW_NUM IN (1, 2, 3, 4, -1, -2, -3, -4)
  INTO :VAL;
  SUSPEND;

  -- 5-9 классы
  TAG_NAME = V$PREFIX || V$COL || '12:I';
  SELECT COUNT(DISTINCT D.CLASS_ID)
  FROM REPORT_D12 D
  JOIN VALL V80 ON V80.OBJ_ID = D.SCHOLAR_ID AND V80.PARAM_ID = 80 AND V80.IS_DEL = 0 AND V80.LISTVAL_ID = :I$STUDY_TYPE
  WHERE D.ROW_NUM IN (5, 6, 7, 8, 9, -5, -6, -7, -8, -9)
  INTO :VAL;
  SUSPEND;

  -- 10+ классы
  TAG_NAME = V$PREFIX || V$COL || '13:I';
  SELECT COUNT(DISTINCT D.CLASS_ID)
  FROM REPORT_D12 D
  JOIN VALL V80 ON V80.OBJ_ID = D.SCHOLAR_ID AND V80.PARAM_ID = 80 AND V80.IS_DEL = 0 AND V80.LISTVAL_ID = :I$STUDY_TYPE
  WHERE D.ROW_NUM IN (10, 11, 12, -10, -11, -12)
  INTO :VAL;
  SUSPEND;

  -- Недокомплектованные классы
  TAG_NAME = V$PREFIX || V$COL || '14:I';
  SELECT COUNT(DISTINCT D.CLASS_ID)
  FROM REPORT_D12 D
  JOIN VALL V80 ON V80.OBJ_ID = D.SCHOLAR_ID AND V80.PARAM_ID = 80 AND V80.IS_DEL = 0 AND V80.LISTVAL_ID = :I$STUDY_TYPE
  WHERE (SELECT COUNT(*) FROM REPORT_D12 C WHERE C.CLASS_ID = D.CLASS_ID) < :V$N
  INTO :VAL;
  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE REPORT_OO1_R251 (
    I$OU_ID BIGINT,
    I$STUDY_TYPE BIGINT)
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(100))
AS
begin

  -- I$STUDY_TYPE не учитываем, подсчет сразу всех

  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R251_COL(:I$OU_ID, :I$STUDY_TYPE, 'AX', NULL) INTO :TAG_NAME, :VAL DO SUSPEND;

  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R251_COL(:I$OU_ID, :I$STUDY_TYPE, 'BG', 1) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R251_COL(:I$OU_ID, :I$STUDY_TYPE, 'BO', 2) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R251_COL(:I$OU_ID, :I$STUDY_TYPE, 'BW', 3) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R251_COL(:I$OU_ID, :I$STUDY_TYPE, 'CE', 4) INTO :TAG_NAME, :VAL DO SUSPEND;

  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R251_COL(:I$OU_ID, :I$STUDY_TYPE, 'CM', 5) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R251_COL(:I$OU_ID, :I$STUDY_TYPE, 'CU', 6) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R251_COL(:I$OU_ID, :I$STUDY_TYPE, 'DC', 7) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R251_COL(:I$OU_ID, :I$STUDY_TYPE, 'DK', 8) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R251_COL(:I$OU_ID, :I$STUDY_TYPE, 'DS', 9) INTO :TAG_NAME, :VAL DO SUSPEND;

  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R251_COL(:I$OU_ID, :I$STUDY_TYPE, 'EA', 10) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R251_COL(:I$OU_ID, :I$STUDY_TYPE, 'EI', -11) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R251_COL(:I$OU_ID, :I$STUDY_TYPE, 'ES', 11) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R251_COL(:I$OU_ID, :I$STUDY_TYPE, 'FA', 12) INTO :TAG_NAME, :VAL DO SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE REPORT_OO1_R251_COL (
    I$OU_ID BIGINT,
    I$STUDY_TYPE BIGINT,
    I$COL VARCHAR(10),
    I$GRADE SMALLINT)
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(100))
AS
declare variable V$PREFIX varchar(10);
declare variable V$YEAR integer;
declare variable V$DATE date;
declare variable V$DATE_FROM date;
declare variable V$STAGE_ID bigint;
declare variable V$CLASS_ID bigint;
declare variable V$OBJ_ID bigint;
declare variable V$STUDY_TYPE bigint;
declare variable V$CLASS_TYPE bigint;
declare variable V$N1 integer;
declare variable V$N2 integer;
declare variable V$N3 integer;
declare variable V$N4 integer;
declare variable V$N5 integer;
declare variable V$N6 integer;
declare variable V$N7 integer;
declare variable V$N8 integer;
begin

  -- Только для общеобразовательных классов

  V$YEAR = EXTRACT(YEAR FROM CURRENT_DATE);
  IF(EXTRACT(MONTH FROM CURRENT_DATE) < 9) THEN V$YEAR = V$YEAR - 1;
  V$DATE = '20.09.' || V$YEAR;
  V$DATE_FROM = '01.08.' || (V$YEAR - 1);

  V$PREFIX = '@4:';

  -- 11-е классы считаются отдельно выпускные и не-выпускные
  V$N1 = 0;
  V$N2 = 0;
  V$N3 = 0;
  V$N4 = 0;
  V$N5 = 0;
  V$N6 = 0;
  V$N7 = 0;
  V$N8 = 0;

  FOR
      SELECT DISTINCT M.PERSON_ID
      FROM PERSON_MOVEMENTS M
      JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID IN (9, 187)
      WHERE M.DATE_DEL IS NULL AND M.DATE_IN < :V$DATE AND M.DATE_OUT >= :V$DATE_FROM
      INTO :V$OBJ_ID
  DO
  BEGIN

      V$STUDY_TYPE = NULL;
      SELECT FIRST 1 V80.LISTVAL_ID
      FROM VALL V80
      WHERE V80.OBJ_ID = :V$OBJ_ID AND V80.PARAM_ID = 80 AND V80.IS_DEL = 0
      INTO :V$STUDY_TYPE;

      -- В каком классе была последняя запись движения в прошлом году ? + признак выпускного класса
      V$STAGE_ID = NULL;
      SELECT FIRST 1 M.GROUP_ID, M.STAGE_ID, G.TYPE_ID
      FROM PERSON_MOVEMENTS M
      JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID IN (9, 187)
      WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :V$OBJ_ID AND M.DATE_IN < :V$DATE AND M.DATE_OUT >= :V$DATE_FROM
      ORDER BY M.DATE_OUT DESC
      INTO :V$CLASS_ID, :V$STAGE_ID, :V$CLASS_TYPE;

      -- Переводим в номер параллели
      V$STAGE_ID = V$STAGE_ID - 36;
      IF(V$STAGE_ID > 12) THEN V$STAGE_ID = 0; -- нулевой параллели больше нет

      -- Это та параллель, которая нам нужна ? Отдельно проверяем выпускные классы
      IF(V$STAGE_ID IS NOT NULL AND (I$GRADE IS NULL OR V$STAGE_ID = ABS(I$GRADE))) THEN
      BEGIN
          IF(I$GRADE < 0) THEN
          BEGIN
              -- Выпускной ли класс ?
              IF(NOT EXISTS(
                  SELECT FIRST 1 1
                  FROM VALL V1362
                  WHERE V1362.OBJ_ID = :V$CLASS_ID AND V1362.PARAM_ID = 1362 AND V1362.IS_DEL = 0 AND V1362.LISTVAL_ID = 2
              ))
              THEN V$STAGE_ID = NULL;
          END

          -- Убираем классы ОВЗ
          IF(V$STAGE_ID IS NOT NULL AND EXISTS(
              SELECT FIRST 1 1
              FROM VALL V592
              WHERE V592.OBJ_ID = :V$CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 13275
          ))
          THEN V$STAGE_ID = NULL;
      END
      ELSE V$STAGE_ID = NULL;

      IF(V$STAGE_ID IS NOT NULL) THEN
      BEGIN
          V$N1 = V$N1 + 1; -- всего
          IF(V$CLASS_TYPE = 9) THEN
          BEGIN
              V$N2 = V$N2 + 1; -- всего
              IF(V$STUDY_TYPE = 5418) THEN V$N3 = V$N3 + 1; -- очно
              IF(V$STUDY_TYPE = 5419) THEN V$N4 = V$N4 + 1; -- очно-заочно
              IF(V$STUDY_TYPE = 5420) THEN V$N5 = V$N5 + 1; -- заочно
          END
          -- отдельно подсчет экстернатов
          IF(V$CLASS_TYPE = 187) THEN
          BEGIN
              V$N6 = V$N6 + 1; -- все экстерны
              IF(V$STUDY_TYPE = 5422) THEN V$N7 = V$N7 + 1; -- семейное
              IF(V$STUDY_TYPE = 5423) THEN V$N8 = V$N8 + 1; -- самообразование
          END
      END

  END

  TAG_NAME = V$PREFIX || I$COL || '24:I';
  VAL = V$N1;
  SUSPEND;

  TAG_NAME = V$PREFIX || I$COL || '25:I';
  VAL = V$N2;
  SUSPEND;

  TAG_NAME = V$PREFIX || I$COL || '26:I';
  VAL = V$N3;
  SUSPEND;

  TAG_NAME = V$PREFIX || I$COL || '28:I';
  VAL = V$N4;
  SUSPEND;

  TAG_NAME = V$PREFIX || I$COL || '29:I';
  VAL = V$N5;
  SUSPEND;

  TAG_NAME = V$PREFIX || I$COL || '30:I';
  VAL = V$N6;
  SUSPEND;

  TAG_NAME = V$PREFIX || I$COL || '31:I';
  VAL = V$N7;
  SUSPEND;

  TAG_NAME = V$PREFIX || I$COL || '33:I';
  VAL = V$N8;
  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE REPORT_OO1_R252 (
    I$OU_ID BIGINT,
    I$STUDY_TYPE BIGINT)
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(100))
AS
begin

  -- I$STUDY_TYPE не учитываем, подсчет сразу всех

  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R252_COL(:I$OU_ID, :I$STUDY_TYPE, 'AZ', NULL) INTO :TAG_NAME, :VAL DO SUSPEND;

  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R252_COL(:I$OU_ID, :I$STUDY_TYPE, 'BH', 1) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R252_COL(:I$OU_ID, :I$STUDY_TYPE, 'BN', 2) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R252_COL(:I$OU_ID, :I$STUDY_TYPE, 'BT', 3) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R252_COL(:I$OU_ID, :I$STUDY_TYPE, 'BZ', 4) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R252_COL(:I$OU_ID, :I$STUDY_TYPE, 'CF', 1001) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R252_COL(:I$OU_ID, :I$STUDY_TYPE, 'CM', 1101) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R252_COL(:I$OU_ID, :I$STUDY_TYPE, 'CT', 1201) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R252_COL(:I$OU_ID, :I$STUDY_TYPE, 'DA', 1002) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R252_COL(:I$OU_ID, :I$STUDY_TYPE, 'DH', 1102) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R252_COL(:I$OU_ID, :I$STUDY_TYPE, 'DO', 1202) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R252_COL(:I$OU_ID, :I$STUDY_TYPE, 'DV', 1003) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R252_COL(:I$OU_ID, :I$STUDY_TYPE, 'EC', 1103) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R252_COL(:I$OU_ID, :I$STUDY_TYPE, 'EJ', 1203) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R252_COL(:I$OU_ID, :I$STUDY_TYPE, 'EQ', 1004) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R252_COL(:I$OU_ID, :I$STUDY_TYPE, 'EX', 1104) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R252_COL(:I$OU_ID, :I$STUDY_TYPE, 'FE', 1204) INTO :TAG_NAME, :VAL DO SUSPEND;

  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R252_COL(:I$OU_ID, :I$STUDY_TYPE, 'AU', 5) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R252_COL(:I$OU_ID, :I$STUDY_TYPE, 'AZ', 6) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R252_COL(:I$OU_ID, :I$STUDY_TYPE, 'BE', 7) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R252_COL(:I$OU_ID, :I$STUDY_TYPE, 'BJ', 8) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R252_COL(:I$OU_ID, :I$STUDY_TYPE, 'BO', 9) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R252_COL(:I$OU_ID, :I$STUDY_TYPE, 'BT', 1005) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R252_COL(:I$OU_ID, :I$STUDY_TYPE, 'BY', 1105) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R252_COL(:I$OU_ID, :I$STUDY_TYPE, 'CF', 1205) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R252_COL(:I$OU_ID, :I$STUDY_TYPE, 'CM', 1006) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R252_COL(:I$OU_ID, :I$STUDY_TYPE, 'CR', 1106) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R252_COL(:I$OU_ID, :I$STUDY_TYPE, 'CY', 1206) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R252_COL(:I$OU_ID, :I$STUDY_TYPE, 'DF', 1007) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R252_COL(:I$OU_ID, :I$STUDY_TYPE, 'DK', 1107) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R252_COL(:I$OU_ID, :I$STUDY_TYPE, 'DR', 1207) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R252_COL(:I$OU_ID, :I$STUDY_TYPE, 'DY', 1008) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R252_COL(:I$OU_ID, :I$STUDY_TYPE, 'ED', 1108) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R252_COL(:I$OU_ID, :I$STUDY_TYPE, 'EK', 1208) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R252_COL(:I$OU_ID, :I$STUDY_TYPE, 'ER', 1009) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R252_COL(:I$OU_ID, :I$STUDY_TYPE, 'EX', 1109) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R252_COL(:I$OU_ID, :I$STUDY_TYPE, 'FE', 1209) INTO :TAG_NAME, :VAL DO SUSPEND;

  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R252_COL(:I$OU_ID, :I$STUDY_TYPE, 'BS', 10) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R252_COL(:I$OU_ID, :I$STUDY_TYPE, 'CJ', 11) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R252_COL(:I$OU_ID, :I$STUDY_TYPE, 'CZ', 1010) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R252_COL(:I$OU_ID, :I$STUDY_TYPE, 'DJ', 1110) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R252_COL(:I$OU_ID, :I$STUDY_TYPE, 'DU', 1210) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R252_COL(:I$OU_ID, :I$STUDY_TYPE, 'EF', 1011) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R252_COL(:I$OU_ID, :I$STUDY_TYPE, 'EN', 1111) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R252_COL(:I$OU_ID, :I$STUDY_TYPE, 'EY', 1211) INTO :TAG_NAME, :VAL DO SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE REPORT_OO1_R252_COL (
    I$OU_ID BIGINT,
    I$STUDY_TYPE BIGINT,
    I$COL VARCHAR(10),
    I$GRADE SMALLINT)
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(100))
AS
declare variable V$PREFIX varchar(10);
declare variable V$YEAR integer;
declare variable V$DATE date;
declare variable V$DATE_FROM date;
declare variable V$GRADE integer;
declare variable V$STAGE_ID bigint;
declare variable V$CLASS_ID bigint;
declare variable V$OBJ_ID bigint;
declare variable V$STUDY_TYPE bigint;
declare variable V$CLASS_TYPE bigint;
declare variable V$PSTAGES smallint;
declare variable V$Y smallint;
declare variable V$SY smallint;
declare variable V$N1 integer;
declare variable V$N2 integer;
declare variable V$N3 integer;
declare variable V$N4 integer;
declare variable V$N5 integer;
declare variable V$N6 integer;
declare variable V$N7 integer;
declare variable V$N8 integer;
declare variable V$ROW integer;
begin

  -- Только для классов ОВЗ, но не умственной отсталости
  -- Выпускных классов тут вообще нет

  V$YEAR = EXTRACT(YEAR FROM CURRENT_DATE);
  IF(EXTRACT(MONTH FROM CURRENT_DATE) < 9) THEN V$YEAR = V$YEAR - 1;
  V$DATE = '20.09.' || V$YEAR;
  V$DATE_FROM = '01.08.' || (V$YEAR - 1);

  -- В зависимости от значения GRADE, выбираем разные УП и разные года обучения
  V$GRADE = MOD(I$GRADE, 100);
  IF(I$GRADE < 1000) THEN V$Y = NULL;
  ELSE IF(I$GRADE < 1100) THEN V$Y = 0;
  ELSE IF(I$GRADE < 1200) THEN V$Y = 1;
  ELSE V$Y = 2;

  V$PREFIX = '@4:';

  V$N1 = 0;
  V$N2 = 0;
  V$N3 = 0;
  V$N4 = 0;
  V$N5 = 0;
  V$N6 = 0;
  V$N7 = 0;
  V$N8 = 0;

  FOR
      SELECT DISTINCT M.PERSON_ID
      FROM PERSON_MOVEMENTS M
      JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID IN (9, 187)
      WHERE M.DATE_DEL IS NULL AND M.DATE_IN < :V$DATE AND M.DATE_OUT >= :V$DATE_FROM
      INTO :V$OBJ_ID
  DO
  BEGIN

      V$STUDY_TYPE = NULL;
      SELECT FIRST 1 V80.LISTVAL_ID
      FROM VALL V80
      WHERE V80.OBJ_ID = :V$OBJ_ID AND V80.PARAM_ID = 80 AND V80.IS_DEL = 0
      INTO :V$STUDY_TYPE;

      -- В каком классе была последняя запись движения в прошлом году ?
      -- и сразу берем параллель
      -- количество лет ОП берем из УП - функционал добавлен с 09.2022
      V$STAGE_ID = NULL;
      SELECT FIRST 1 M.GROUP_ID, M.STAGE_ID - 36, G.TYPE_ID, M.PLAN_STAGES, M.STAGE_YEAR
      FROM PERSON_MOVEMENTS M
      JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID IN (9, 187)
      WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :V$OBJ_ID AND M.DATE_IN < :V$DATE AND M.DATE_OUT >= :V$DATE_FROM
      ORDER BY M.DATE_OUT DESC
      INTO :V$CLASS_ID, :V$STAGE_ID, :V$CLASS_TYPE, :V$PSTAGES, :V$SY;

      -- Если год обучения не указан, проверяем количество этапов УП
      IF(V$SY IS NULL) THEN
      BEGIN
          IF((V$STAGE_ID IN (1, 2, 3, 4) AND V$PSTAGES > 4) OR (V$STAGE_ID IN (5, 6, 7, 8, 9) AND V$PSTAGES > 5) OR (V$STAGE_ID IN (10, 11) AND V$PSTAGES > 2)) THEN V$SY = 0;
      END

      -- Это та параллель, которая нам нужна ?
      IF(V$STAGE_ID IS NOT NULL AND (I$GRADE IS NULL OR (V$STAGE_ID = V$GRADE AND COALESCE(V$SY, -1) = COALESCE(V$Y, -1)))) THEN
      BEGIN
          -- Убираем классы не-ОВЗ и не-умственной отсталости
          IF(V$STAGE_ID IS NOT NULL AND NOT EXISTS(
              SELECT FIRST 1 1
              FROM VALL V592
              JOIN VALL V554 ON V554.OBJ_ID = V592.OBJ_ID AND V554.PARAM_ID = 554 AND V554.IS_DEL = 0 AND V554.LISTVAL_ID <> 13283
              WHERE V592.OBJ_ID = :V$CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 13275
          ))
          THEN V$STAGE_ID = NULL;
      END
      ELSE V$STAGE_ID = NULL;

      IF(V$STAGE_ID IS NOT NULL) THEN
      BEGIN
          V$N1 = V$N1 + 1; -- всего
          IF(V$CLASS_TYPE = 9) THEN
          BEGIN
              V$N2 = V$N2 + 1; -- всего
              IF(V$STUDY_TYPE = 5418) THEN V$N3 = V$N3 + 1; -- очно
              IF(V$STUDY_TYPE = 5419) THEN V$N4 = V$N4 + 1; -- очно-заочно
              IF(V$STUDY_TYPE = 5420) THEN V$N5 = V$N5 + 1; -- заочно
          END
          -- отдельно подсчет экстернатов
          IF(V$CLASS_TYPE = 187) THEN
          BEGIN
              V$N6 = V$N6 + 1; -- все экстерны
              IF(V$STUDY_TYPE = 5422) THEN V$N7 = V$N7 + 1; -- семейное
              IF(V$STUDY_TYPE = 5423) THEN V$N8 = V$N8 + 1; -- самообразование
          END
      END

  END

  -- У нас несколько таблиц, смотрим в какую попадаем
  IF(V$GRADE < 5) THEN V$ROW = 42;
  ELSE IF(V$GRADE < 10) THEN V$ROW = 57;
  ELSE V$ROW = 71;

  TAG_NAME = V$PREFIX || I$COL || (V$ROW + 0) || ':I';
  VAL = V$N1;
  SUSPEND;

  TAG_NAME = V$PREFIX || I$COL || (V$ROW + 1) || ':I';
  VAL = V$N2;
  SUSPEND;

  TAG_NAME = V$PREFIX || I$COL || (V$ROW + 2) || ':I';
  VAL = V$N3;
  SUSPEND;

  TAG_NAME = V$PREFIX || I$COL || (V$ROW + 4) || ':I';
  VAL = V$N4;
  SUSPEND;

  TAG_NAME = V$PREFIX || I$COL || (V$ROW + 5) || ':I';
  VAL = V$N5;
  SUSPEND;

  TAG_NAME = V$PREFIX || I$COL || (V$ROW + 6) || ':I';
  VAL = V$N6;
  SUSPEND;

  TAG_NAME = V$PREFIX || I$COL || (V$ROW + 7) || ':I';
  VAL = V$N7;
  SUSPEND;

  TAG_NAME = V$PREFIX || I$COL || (V$ROW + 9) || ':I';
  VAL = V$N8;
  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE REPORT_OO1_R253 (
    I$OU_ID BIGINT,
    I$STUDY_TYPE BIGINT)
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(100))
AS
begin

  -- I$STUDY_TYPE не учитываем, подсчет сразу всех

  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R253_COL(:I$OU_ID, :I$STUDY_TYPE, 'BP', NULL) INTO :TAG_NAME, :VAL DO SUSPEND;

  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R253_COL(:I$OU_ID, :I$STUDY_TYPE, 'BW', 1) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R253_COL(:I$OU_ID, :I$STUDY_TYPE, 'CC', 1101) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R253_COL(:I$OU_ID, :I$STUDY_TYPE, 'CL', 1201) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R253_COL(:I$OU_ID, :I$STUDY_TYPE, 'CU', 2) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R253_COL(:I$OU_ID, :I$STUDY_TYPE, 'DA', 3) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R253_COL(:I$OU_ID, :I$STUDY_TYPE, 'DG', 4) INTO :TAG_NAME, :VAL DO SUSPEND;

  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R253_COL(:I$OU_ID, :I$STUDY_TYPE, 'DM', 5) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R253_COL(:I$OU_ID, :I$STUDY_TYPE, 'DS', 6) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R253_COL(:I$OU_ID, :I$STUDY_TYPE, 'DY', 7) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R253_COL(:I$OU_ID, :I$STUDY_TYPE, 'EE', 8) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R253_COL(:I$OU_ID, :I$STUDY_TYPE, 'EK', 9) INTO :TAG_NAME, :VAL DO SUSPEND;

  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R253_COL(:I$OU_ID, :I$STUDY_TYPE, 'EQ', 10) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R253_COL(:I$OU_ID, :I$STUDY_TYPE, 'EW', 11) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R253_COL(:I$OU_ID, :I$STUDY_TYPE, 'FC', 12) INTO :TAG_NAME, :VAL DO SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE REPORT_OO1_R253_COL (
    I$OU_ID BIGINT,
    I$STUDY_TYPE BIGINT,
    I$COL VARCHAR(10),
    I$GRADE SMALLINT)
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(100))
AS
declare variable V$PREFIX varchar(10);
declare variable V$YEAR integer;
declare variable V$DATE date;
declare variable V$DATE_FROM date;
declare variable V$STAGE_ID bigint;
declare variable V$CLASS_ID bigint;
declare variable V$OBJ_ID bigint;
declare variable V$STUDY_TYPE bigint;
declare variable V$CLASS_TYPE bigint;
declare variable V$GRADE bigint;
declare variable V$PSTAGES smallint;
declare variable V$Y smallint;
declare variable V$SY smallint;
declare variable V$N1 integer;
declare variable V$N2 integer;
declare variable V$N3 integer;
declare variable V$N4 integer;
declare variable V$N5 integer;
declare variable V$N5_9 integer;
declare variable V$N5_10 integer;
declare variable V$N5_11 integer;
declare variable V$N5_12 integer;
declare variable V$N5_13 integer;
declare variable V$N6 integer;
declare variable V$N6_9 integer;
declare variable V$N6_10 integer;
declare variable V$N6_11 integer;
declare variable V$N6_12 integer;
declare variable V$N6_13 integer;
declare variable V$N7 integer;
begin

  -- Только для классов ОВЗ для умственно отсталых

  V$YEAR = EXTRACT(YEAR FROM CURRENT_DATE);
  IF(EXTRACT(MONTH FROM CURRENT_DATE) < 9) THEN V$YEAR = V$YEAR - 1;
  V$DATE = '20.09.' || V$YEAR;
  V$DATE_FROM = '01.08.' || (V$YEAR - 1);

  -- В зависимости от значения GRADE, выбираем разные УП и разные года обучения
  V$GRADE = MOD(I$GRADE, 100);
  IF(I$GRADE < 1000) THEN V$Y = NULL;
  ELSE IF(I$GRADE < 1100) THEN V$Y = 0;
  ELSE IF(I$GRADE < 1200) THEN V$Y = 1;
  ELSE V$Y = 2;

  V$PREFIX = '@4:';

  V$N1 = 0;
  V$N2 = 0;
  V$N3 = 0;
  V$N4 = 0;
  V$N5 = 0;
  V$N5_9 = 0;
  V$N5_10 = 0;
  V$N5_11 = 0;
  V$N5_12 = 0;
  V$N5_13 = 0;
  V$N6 = 0;
  V$N6_9 = 0;
  V$N6_10 = 0;
  V$N6_11 = 0;
  V$N6_12 = 0;
  V$N6_13 = 0;
  V$N7 = 0;

  FOR
      SELECT DISTINCT M.PERSON_ID
      FROM PERSON_MOVEMENTS M
      JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID IN (9, 187)
      WHERE M.DATE_DEL IS NULL AND M.DATE_IN < :V$DATE AND M.DATE_OUT >= :V$DATE_FROM
      INTO :V$OBJ_ID
  DO
  BEGIN

      V$STUDY_TYPE = NULL;
      SELECT FIRST 1 V80.LISTVAL_ID
      FROM VALL V80
      WHERE V80.OBJ_ID = :V$OBJ_ID AND V80.PARAM_ID = 80 AND V80.IS_DEL = 0
      INTO :V$STUDY_TYPE;

      -- В каком классе была последняя запись движения в прошлом году ?
      V$STAGE_ID = NULL;
      SELECT FIRST 1 M.GROUP_ID, M.STAGE_ID - 36, G.TYPE_ID, M.PLAN_STAGES, M.STAGE_YEAR
      FROM PERSON_MOVEMENTS M
      JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID IN (9, 187)
      WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :V$OBJ_ID AND M.DATE_IN < :V$DATE AND M.DATE_OUT >= :V$DATE_FROM
      ORDER BY M.DATE_OUT DESC
      INTO :V$CLASS_ID, :V$STAGE_ID, :V$CLASS_TYPE, :V$PSTAGES, :V$SY;

      -- Если год обучения не указан, проверяем количество этапов УП
      IF(V$SY IS NULL) THEN
      BEGIN
          IF((V$STAGE_ID IN (1, 2, 3, 4) AND V$PSTAGES > 4) OR (V$STAGE_ID IN (5, 6, 7, 8, 9) AND V$PSTAGES > 5) OR (V$STAGE_ID IN (10, 11) AND V$PSTAGES > 2)) THEN V$SY = 0;
      END

      -- Это та параллель, которая нам нужна ?
      IF(V$STAGE_ID IS NOT NULL AND (I$GRADE IS NULL OR (V$STAGE_ID = V$GRADE AND COALESCE(V$SY, -1) = COALESCE(V$Y, -1)))) THEN
      BEGIN
          -- Убираем классы ОВЗ
          IF(V$STAGE_ID IS NOT NULL AND NOT EXISTS(
              SELECT FIRST 1 1
              FROM VALL V592
              JOIN VALL V554 ON V554.OBJ_ID = V592.OBJ_ID AND V554.PARAM_ID = 554 AND V554.IS_DEL = 0 AND V554.LISTVAL_ID = 13283
              WHERE V592.OBJ_ID = :V$CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 13275
          ))
          THEN V$STAGE_ID = NULL;
      END
      ELSE V$STAGE_ID = NULL;

      IF(V$STAGE_ID IS NOT NULL) THEN
      BEGIN
          V$N1 = V$N1 + 1; -- всего
          IF(V$CLASS_TYPE = 9) THEN
          BEGIN
              V$N2 = V$N2 + 1; -- всего
              IF(V$STUDY_TYPE = 5418) THEN V$N3 = V$N3 + 1; -- очно
              IF(V$STUDY_TYPE = 5419) THEN V$N4 = V$N4 + 1; -- очно-заочно
              IF(V$STUDY_TYPE = 5420) THEN V$N5 = V$N5 + 1; -- заочно
              IF(V$PSTAGES = 9) THEN V$N5_9 = V$N5_9 + 1;
              IF(V$PSTAGES = 10) THEN V$N5_10 = V$N5_10 + 1;
              IF(V$PSTAGES = 11) THEN V$N5_11 = V$N5_11 + 1;
              IF(V$PSTAGES = 12) THEN V$N5_12 = V$N5_12 + 1;
              IF(V$PSTAGES = 13) THEN V$N5_13 = V$N5_13 + 1;
          END
          -- отдельно подсчет экстернатов
          IF(V$CLASS_TYPE = 187) THEN
          BEGIN
              V$N6 = V$N6 + 1; -- все экстерны
              IF(V$PSTAGES = 9) THEN V$N6_9 = V$N6_9 + 1;
              IF(V$PSTAGES = 10) THEN V$N6_10 = V$N6_10 + 1;
              IF(V$PSTAGES = 11) THEN V$N6_11 = V$N6_11 + 1;
              IF(V$PSTAGES = 12) THEN V$N6_12 = V$N6_12 + 1;
              IF(V$PSTAGES = 13) THEN V$N6_13 = V$N6_13 + 1;
              IF(V$STUDY_TYPE = 5422) THEN V$N7 = V$N7 + 1; -- семейное
          END
      END

  END

  TAG_NAME = V$PREFIX || I$COL || '87:I';
  VAL = V$N1;
  SUSPEND;

  TAG_NAME = V$PREFIX || I$COL || '88:I';
  VAL = V$N2;
  SUSPEND;

  TAG_NAME = V$PREFIX || I$COL || '89:I';
  VAL = V$N3;
  SUSPEND;

  TAG_NAME = V$PREFIX || I$COL || '90:I';
  VAL = V$N4;
  SUSPEND;

  TAG_NAME = V$PREFIX || I$COL || '91:I';
  VAL = V$N5;
  SUSPEND;

  TAG_NAME = V$PREFIX || I$COL || '92:I';
  VAL = V$N5_9;
  SUSPEND;
  TAG_NAME = V$PREFIX || I$COL || '93:I';
  VAL = V$N5_10;
  SUSPEND;
  TAG_NAME = V$PREFIX || I$COL || '94:I';
  VAL = V$N5_11;
  SUSPEND;
  TAG_NAME = V$PREFIX || I$COL || '95:I';
  VAL = V$N5_12;
  SUSPEND;
  TAG_NAME = V$PREFIX || I$COL || '96:I';
  VAL = V$N5_13;
  SUSPEND;

  TAG_NAME = V$PREFIX || I$COL || '97:I';
  VAL = V$N6;
  SUSPEND;

  TAG_NAME = V$PREFIX || I$COL || '98:I';
  VAL = V$N6_9;
  SUSPEND;
  TAG_NAME = V$PREFIX || I$COL || '99:I';
  VAL = V$N6_10;
  SUSPEND;
  TAG_NAME = V$PREFIX || I$COL || '100:I';
  VAL = V$N6_11;
  SUSPEND;
  TAG_NAME = V$PREFIX || I$COL || '101:I';
  VAL = V$N6_12;
  SUSPEND;
  TAG_NAME = V$PREFIX || I$COL || '102:I';
  VAL = V$N6_13;
  SUSPEND;

  TAG_NAME = V$PREFIX || I$COL || '104:I';
  VAL = V$N7;
  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE REPORT_OO1_R27 (
    I$OU_ID BIGINT,
    I$OVZ BIGINT)
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(100))
AS
declare variable V$AGE smallint;
declare variable V$ROW smallint;
begin

  V$AGE = 5;
  V$ROW = 0;

  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R27_ROW(:I$OU_ID, :I$OVZ, IIF(:I$OVZ = 0, 186, 233), NULL) INTO :TAG_NAME, :VAL DO SUSPEND;

  WHILE(V$AGE <= 40) DO
  BEGIN

    FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R27_ROW(:I$OU_ID, :I$OVZ, IIF(:I$OVZ = 0, 187, 234) + :V$ROW, :V$AGE) INTO :TAG_NAME, :VAL DO SUSPEND;

    IF(V$AGE < 30) THEN V$AGE = V$AGE + 1;
    ELSE V$AGE = V$AGE + 5;

    V$ROW = V$ROW + 1;
    IF(V$ROW = 1) THEN V$ROW = V$ROW + 1; -- первая строка - двойная

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE REPORT_OO1_R27_ROW (
    I$OU_ID BIGINT,
    I$OVZ SMALLINT,
    I$ROW INTEGER,
    I$AGE SMALLINT)
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(100))
AS
declare variable V$PREFIX varchar(20);
declare variable V$YEAR integer;
declare variable V$DATE date;
declare variable AGE1 integer;
declare variable AGE2 integer;
declare variable V$N integer;
declare variable V integer;
begin

  V$PREFIX = '@4:';
  V$N = 0;

  IF(I$AGE IS NULL) THEN BEGIN AGE1 = 0; AGE2 = 9999; END
  IF(I$AGE < 30) THEN BEGIN AGE1 = I$AGE; AGE2 = I$AGE; END
  ELSE IF(I$AGE < 40) THEN BEGIN AGE1 = I$AGE; AGE2 = I$AGE + 4; END
  ELSE BEGIN AGE1 = I$AGE; AGE2 = 9999; END

  V$YEAR = EXTRACT(YEAR FROM CURRENT_DATE);
  IF(EXTRACT(MONTH FROM CURRENT_DATE) < 9) THEN V$YEAR = V$YEAR - 1;
  V$DATE = '20.09.' || V$YEAR;

  -- Из всех уровней исключаем умственную отсталость, по ней цифра идет в отдельный столбец

  -- 1-4 классы
  TAG_NAME = V$PREFIX || IIF(I$OVZ = 0, 'AU', 'AN') || I$ROW || ':I';
  SELECT COUNT(*)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND ((:I$OVZ = 0 AND V592.LISTVAL_ID <> 13275) OR (:I$OVZ = 1 AND V592.LISTVAL_ID = 13275))
  LEFT JOIN VALL V554 ON V554.OBJ_ID = D.CLASS_ID AND V554.PARAM_ID = 554 AND V554.IS_DEL = 0
  WHERE D.ROW_NUM IN (1, 2, 3, 4, -1, -2, -3, -4, 1001, 1002, 1003, 1004, 1101, 1102, 1103, 1104, 1201, 1202, 1203, 1204) AND D.C3 >= :AGE1 AND D.C3 <= :AGE2
    AND (:I$OVZ = 0 OR V554.LISTVAL_ID <> 13283)
  INTO :V;
  VAL = V;
  V$N = V$N + V;
  SUSPEND;

  -- Девочки
  TAG_NAME = V$PREFIX || IIF(I$OVZ = 0, 'BF', 'AV') || I$ROW || ':I';
  SELECT COUNT(*)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND ((:I$OVZ = 0 AND V592.LISTVAL_ID <> 13275) OR (:I$OVZ = 1 AND V592.LISTVAL_ID = 13275))
  LEFT JOIN VALL V554 ON V554.OBJ_ID = D.CLASS_ID AND V554.PARAM_ID = 554 AND V554.IS_DEL = 0
  JOIN VALL V88 ON V88.OBJ_ID = D.SCHOLAR_ID AND V88.PARAM_ID = 88 AND V88.IS_DEL = 0 AND V88.LISTVAL_ID = 182
  WHERE D.ROW_NUM IN (1, 2, 3, 4, -1, -2, -3, -4, 1001, 1002, 1003, 1004, 1101, 1102, 1103, 1104, 1201, 1202, 1203, 1204) AND D.C3 >= :AGE1 AND D.C3 <= :AGE2
    AND (:I$OVZ = 0 OR V554.LISTVAL_ID <> 13283)
  INTO :VAL;
  SUSPEND;

  -- 1 классы или 1 классы 1 год обучения (второгодников исключаем только для общеобра)
  TAG_NAME = V$PREFIX || IIF(I$OVZ = 0, 'BL', 'BB') || I$ROW || ':I';
  IF(I$OVZ = 0) THEN
  SELECT COUNT(*)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID <> 13275
  LEFT JOIN PERSON_MOVEMENTS M ON M.DATE_DEL IS NULL AND M.PERSON_ID = D.SCHOLAR_ID AND M.GROUP_ID = D.CLASS_ID AND M.REASON_IN = 810 AND M.STAGE_ID = 37
    AND M.DATE_IN <= :V$DATE AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :V$DATE)
  WHERE D.ROW_NUM IN (1, -1) AND D.C3 >= :AGE1 AND D.C3 <= :AGE2 AND M.OBJ_ID IS NULL
  INTO :VAL;
  ELSE
  SELECT COUNT(*)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 13275
  JOIN VALL V554 ON V554.OBJ_ID = D.CLASS_ID AND V554.PARAM_ID = 554 AND V554.IS_DEL = 0 AND V554.LISTVAL_ID <> 13283
  WHERE D.ROW_NUM IN (1, -1, 1001, 1101) AND D.C3 >= :AGE1 AND D.C3 <= :AGE2
  INTO :VAL;
  SUSPEND;

  -- 5-9 классы
  TAG_NAME = V$PREFIX || IIF(I$OVZ = 0, 'BY', 'BM') || I$ROW || ':I';
  SELECT COUNT(*)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND ((:I$OVZ = 0 AND V592.LISTVAL_ID <> 13275) OR (:I$OVZ = 1 AND V592.LISTVAL_ID = 13275))
  LEFT JOIN VALL V554 ON V554.OBJ_ID = D.CLASS_ID AND V554.PARAM_ID = 554 AND V554.IS_DEL = 0
  WHERE D.ROW_NUM IN (5, 6, 7, 8, 9, -5, -6, -7, -8, -9, 1005, 1006, 1007, 1008, 1009, 1105, 1106, 1107, 1108, 1109, 1205, 1206, 1207, 1208, 1209) AND D.C3 >= :AGE1 AND D.C3 <= :AGE2
    AND (:I$OVZ = 0 OR V554.LISTVAL_ID <> 13283)
  INTO :V;
  VAL = V;
  V$N = V$N + V;
  SUSPEND;

  -- Девочки
  TAG_NAME = V$PREFIX || IIF(I$OVZ = 0, 'CJ', 'BV') || I$ROW || ':I';
  SELECT COUNT(*)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND ((:I$OVZ = 0 AND V592.LISTVAL_ID <> 13275) OR (:I$OVZ = 1 AND V592.LISTVAL_ID = 13275))
  LEFT JOIN VALL V554 ON V554.OBJ_ID = D.CLASS_ID AND V554.PARAM_ID = 554 AND V554.IS_DEL = 0
  JOIN VALL V88 ON V88.OBJ_ID = D.SCHOLAR_ID AND V88.PARAM_ID = 88 AND V88.IS_DEL = 0 AND V88.LISTVAL_ID = 182
  WHERE D.ROW_NUM IN (5, 6, 7, 8, 9, -5, -6, -7, -8, -9, 1005, 1006, 1007, 1008, 1009, 1105, 1106, 1107, 1108, 1109, 1205, 1206, 1207, 1208, 1209) AND D.C3 >= :AGE1 AND D.C3 <= :AGE2
    AND (:I$OVZ = 0 OR V554.LISTVAL_ID <> 13283)
  INTO :VAL;
  SUSPEND;

  -- 5 классы или 5 классы 1 год обучения (второгодников исключаем только для общеобра)
  TAG_NAME = V$PREFIX || IIF(I$OVZ = 0, 'CP', 'CB') || I$ROW || ':I';
  IF(I$OVZ = 0) THEN
  SELECT COUNT(*)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID <> 13275
  LEFT JOIN PERSON_MOVEMENTS M ON M.DATE_DEL IS NULL AND M.PERSON_ID = D.SCHOLAR_ID AND M.GROUP_ID = D.CLASS_ID AND M.REASON_IN = 810 AND M.STAGE_ID = 41
    AND M.DATE_IN <= :V$DATE AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :V$DATE)
  WHERE D.ROW_NUM IN (5, -5) AND D.C3 >= :AGE1 AND D.C3 <= :AGE2 AND M.OBJ_ID IS NULL
  INTO :VAL;
  ELSE
  SELECT COUNT(*)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 13275
  JOIN VALL V554 ON V554.OBJ_ID = D.CLASS_ID AND V554.PARAM_ID = 554 AND V554.IS_DEL = 0 AND V554.LISTVAL_ID <> 13283
  WHERE D.ROW_NUM IN (5, -5, 1005, 1105) AND D.C3 >= :AGE1 AND D.C3 <= :AGE2
  INTO :VAL;
  SUSPEND;

  -- 10-12 классы
  TAG_NAME = V$PREFIX || IIF(I$OVZ = 0, 'DC', 'CM') || I$ROW || ':I';
  SELECT COUNT(*)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND ((:I$OVZ = 0 AND V592.LISTVAL_ID <> 13275) OR (:I$OVZ = 1 AND V592.LISTVAL_ID = 13275))
  LEFT JOIN VALL V554 ON V554.OBJ_ID = D.CLASS_ID AND V554.PARAM_ID = 554 AND V554.IS_DEL = 0
  WHERE D.ROW_NUM IN (10, 11, 12, -10, -11, -12, 1010, 1011, 1110, 1111, 1210, 1211) AND D.C3 >= :AGE1 AND D.C3 <= :AGE2
    AND (:I$OVZ = 0 OR V554.LISTVAL_ID <> 13283)
  INTO :V;
  VAL = V;
  V$N = V$N + V;
  SUSPEND;

  -- Девочки
  TAG_NAME = V$PREFIX || IIF(I$OVZ = 0, 'DN', 'CV') || I$ROW || ':I';
  SELECT COUNT(*)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND ((:I$OVZ = 0 AND V592.LISTVAL_ID <> 13275) OR (:I$OVZ = 1 AND V592.LISTVAL_ID = 13275))
  LEFT JOIN VALL V554 ON V554.OBJ_ID = D.CLASS_ID AND V554.PARAM_ID = 554 AND V554.IS_DEL = 0
  JOIN VALL V88 ON V88.OBJ_ID = D.SCHOLAR_ID AND V88.PARAM_ID = 88 AND V88.IS_DEL = 0 AND V88.LISTVAL_ID = 182
  WHERE D.ROW_NUM IN (10, 11, -10, -11, 1010, 1011, 1110, 1111, 1210, 1211) AND D.C3 >= :AGE1 AND D.C3 <= :AGE2
    AND (:I$OVZ = 0 OR V554.LISTVAL_ID <> 13283)
  INTO :VAL;
  SUSPEND;

  -- 10 классы или 10 классы 1 год обучения (второгодников исключаем только для общеобра)
  TAG_NAME = V$PREFIX || IIF(I$OVZ = 0, 'DT', 'DB') || I$ROW || ':I';
  IF(I$OVZ = 0) THEN
  SELECT COUNT(*)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID <> 13275
  LEFT JOIN PERSON_MOVEMENTS M ON M.DATE_DEL IS NULL AND M.PERSON_ID = D.SCHOLAR_ID AND M.GROUP_ID = D.CLASS_ID AND M.REASON_IN = 810 AND M.STAGE_ID = 46
    AND M.DATE_IN <= :V$DATE AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :V$DATE)
  WHERE D.ROW_NUM IN (10, -10) AND D.C3 >= :AGE1 AND D.C3 <= :AGE2 AND M.OBJ_ID IS NULL
  INTO :VAL;
  ELSE
  SELECT COUNT(*)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 13275
  JOIN VALL V554 ON V554.OBJ_ID = D.CLASS_ID AND V554.PARAM_ID = 554 AND V554.IS_DEL = 0 AND V554.LISTVAL_ID <> 13283
  WHERE D.ROW_NUM IN (10, -10, 1010, 1110) AND D.C3 >= :AGE1 AND D.C3 <= :AGE2
  INTO :VAL;
  SUSPEND;

  -- Интеллектуальные нарушения - только таблица ОВЗ
  IF(I$OVZ = 1) THEN
  BEGIN

    TAG_NAME = V$PREFIX || 'DM' || I$ROW || ':I';
    SELECT COUNT(*)
    FROM REPORT_D12 D
    JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 13275
    JOIN VALL V554 ON V554.OBJ_ID = D.CLASS_ID AND V554.PARAM_ID = 554 AND V554.IS_DEL = 0 AND V554.LISTVAL_ID = 13283
    WHERE D.C3 >= :AGE1 AND D.C3 <= :AGE2
    INTO :V;
    VAL = V;
    V$N = V$N + V;
    SUSPEND;

    TAG_NAME = V$PREFIX || 'DW' || I$ROW || ':I';
    SELECT COUNT(*)
    FROM REPORT_D12 D
    JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 13275
    JOIN VALL V554 ON V554.OBJ_ID = D.CLASS_ID AND V554.PARAM_ID = 554 AND V554.IS_DEL = 0 AND V554.LISTVAL_ID = 13283
    JOIN VALL V88 ON V88.OBJ_ID = D.SCHOLAR_ID AND V88.PARAM_ID = 88 AND V88.IS_DEL = 0 AND V88.LISTVAL_ID = 182
    WHERE D.C3 >= :AGE1 AND D.C3 <= :AGE2
    INTO :VAL;
    SUSPEND;

    TAG_NAME = V$PREFIX || 'EC' || I$ROW || ':I';
    SELECT COUNT(*)
    FROM REPORT_D12 D
    JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 13275
    JOIN VALL V554 ON V554.OBJ_ID = D.CLASS_ID AND V554.PARAM_ID = 554 AND V554.IS_DEL = 0 AND V554.LISTVAL_ID = 13283
    WHERE D.ROW_NUM IN (1, -1, 1001, 1101) AND D.C3 >= :AGE1 AND D.C3 <= :AGE2
    INTO :VAL;
    SUSPEND;

  END

  -- Всего обучающихся
  TAG_NAME = V$PREFIX || IIF(I$OVZ = 0, 'AJ', 'AF') || I$ROW || ':I';
  VAL = V$N;
  SUSPEND;

  -- Заочно и очно-заочно
  TAG_NAME = V$PREFIX || IIF(I$OVZ = 0, 'EG', 'EJ') || I$ROW || ':I';
  SELECT COUNT(*)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND ((:I$OVZ = 0 AND V592.LISTVAL_ID <> 13275) OR (:I$OVZ = 1 AND V592.LISTVAL_ID = 13275))
  LEFT JOIN VALL V554 ON V554.OBJ_ID = D.CLASS_ID AND V554.PARAM_ID = 554 AND V554.IS_DEL = 0
  JOIN VALL V80 ON V80.OBJ_ID = D.SCHOLAR_ID AND V80.PARAM_ID = 80 AND V80.IS_DEL = 0 AND V80.LISTVAL_ID IN (5419, 5420)
  WHERE D.C3 >= :AGE1 AND D.C3 <= :AGE2
  INTO :VAL;
  SUSPEND;

  -- Иностранцы
  TAG_NAME = V$PREFIX || IIF(I$OVZ = 0, 'EO', 'ER') || I$ROW || ':I';
  SELECT COUNT(*)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND ((:I$OVZ = 0 AND V592.LISTVAL_ID <> 13275) OR (:I$OVZ = 1 AND V592.LISTVAL_ID = 13275))
  LEFT JOIN VALL V554 ON V554.OBJ_ID = D.CLASS_ID AND V554.PARAM_ID = 554 AND V554.IS_DEL = 0
  JOIN VALL V91 ON V91.OBJ_ID = D.SCHOLAR_ID AND V91.PARAM_ID = 91 AND V91.IS_DEL = 0 AND V91.LISTVAL_ID <> 1515
  WHERE D.C3 >= :AGE1 AND D.C3 <= :AGE2
  INTO :VAL;
  SUSPEND;

  -- Без гражданства
  TAG_NAME = V$PREFIX || IIF(I$OVZ = 0, 'FE', 'FF') || I$ROW || ':I';
  SELECT COUNT(*)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND ((:I$OVZ = 0 AND V592.LISTVAL_ID <> 13275) OR (:I$OVZ = 1 AND V592.LISTVAL_ID = 13275))
  LEFT JOIN VALL V554 ON V554.OBJ_ID = D.CLASS_ID AND V554.PARAM_ID = 554 AND V554.IS_DEL = 0
  LEFT JOIN VALL V91 ON V91.OBJ_ID = D.SCHOLAR_ID AND V91.PARAM_ID = 91 AND V91.IS_DEL = 0
  WHERE D.C3 >= :AGE1 AND D.C3 <= :AGE2 AND V91.LISTVAL_ID IS NULL
  INTO :VAL;
  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE REPORT_OO1_R28 (
    I$OU_ID BIGINT)
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(100))
AS
begin

  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R28_COL(:I$OU_ID, 'AZ', NULL, NULL, 0, NULL) INTO :TAG_NAME, :VAL DO SUSPEND;

  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R28_COL(:I$OU_ID, 'BH', 1, 0, 0, NULL) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R28_COL(:I$OU_ID, 'BT', 2, 0, 0, NULL) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R28_COL(:I$OU_ID, 'CE', 3, 0, 0, NULL) INTO :TAG_NAME, :VAL DO SUSPEND;

  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R28_COL(:I$OU_ID, 'CP', 1, 1, 0, NULL) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R28_COL(:I$OU_ID, 'DA', 2, 1, 0, NULL) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R28_COL(:I$OU_ID, 'DL', 3, 1, 0, NULL) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R28_COL(:I$OU_ID, 'DW', NULL, 2, 0, NULL) INTO :TAG_NAME, :VAL DO SUSPEND;

  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R28_COL(:I$OU_ID, 'EI', NULL, NULL, 1, NULL) INTO :TAG_NAME, :VAL DO SUSPEND;

  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R28_COL(:I$OU_ID, 'ER', NULL, NULL, 0, 5418) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R28_COL(:I$OU_ID, 'EX', NULL, NULL, 0, 5419) INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R28_COL(:I$OU_ID, 'FE', NULL, NULL, 0, 5420) INTO :TAG_NAME, :VAL DO SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE REPORT_OO1_R28_COL (
    I$OU_ID BIGINT,
    I$COL VARCHAR(10),
    I$STAGE SMALLINT,
    I$OVZ SMALLINT,
    I$Y18 SMALLINT,
    I$FORM BIGINT)
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(100))
AS
declare variable V$PREFIX varchar(20);
declare variable V$YEAR integer;
declare variable V$DATE date;
declare variable V$DATE_FROM date;
declare variable V$STAGE bigint;
declare variable V$PERSON_ID bigint;
declare variable V$GROUP_ID bigint;
declare variable V$DATE_OUT date;
declare variable V$MOVE_ID bigint;
declare variable V$N1 integer;
declare variable V$N2 integer;
declare variable V$N3 integer;
declare variable V$N4 integer;
declare variable V$N5 integer;
declare variable V$N6 integer;
declare variable V$N7 integer;
declare variable V$N8 integer;
declare variable V$N9 integer;
declare variable V$N10 integer;
declare variable V$N11 integer;
declare variable V$N12 integer;
declare variable V$N13 integer;
begin

  V$PREFIX = '@4:';

  V$YEAR = EXTRACT(YEAR FROM CURRENT_DATE);
  IF(EXTRACT(MONTH FROM CURRENT_DATE) < 9) THEN V$YEAR = V$YEAR - 1;
  V$DATE = '20.09.' || V$YEAR;
  V$DATE_FROM = '01.08.' || (V$YEAR - 1);

  IF(I$STAGE = 1) THEN V$STAGE = 22;
  ELSE IF(I$STAGE = 2) THEN V$STAGE = 26;
  ELSE IF(I$STAGE = 3) THEN V$STAGE = 27;

  V$N1 = 0;
  V$N2 = 0;
  V$N3 = 0;
  V$N4 = 0;
  V$N5 = 0;
  V$N6 = 0;
  V$N7 = 0;
  V$N8 = 0;
  V$N9 = 0;
  V$N10 = 0;
  V$N11 = 0;
  V$N12 = 0;
  V$N13 = 0;

  FOR
    SELECT M.PERSON_ID, M.GROUP_ID, M.DATE_OUT, M.OBJ_ID
    FROM PERSON_MOVEMENTS M
    JOIN VALL V592 ON V592.OBJ_ID = M.GROUP_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND ((:I$OVZ = 0 AND V592.LISTVAL_ID <> 13275) OR (:I$OVZ = 1 AND V592.LISTVAL_ID = 13275))
    LEFT JOIN VALL V554 ON V554.OBJ_ID = M.GROUP_ID AND V554.PARAM_ID = 554 AND V554.IS_DEL = 0
    JOIN VALD V89 ON V89.OBJ_ID = M.PERSON_ID AND V89.PARAM_ID = 89 AND V89.IS_DEL = 0
    LEFT JOIN VALL V80 ON V80.OBJ_ID = M.PERSON_ID AND V80.PARAM_ID = 80 AND V80.IS_DEL = 0
    WHERE M.DATE_DEL IS NULL AND M.GROUP_TYPE_ID IN (9, 187) AND M.DATE_OUT >= :V$DATE_FROM AND M.DATE_OUT < :V$DATE AND M.REASON_OUT IN (807, 811)
      AND (:V$STAGE IS NULL OR M.LEVEL_ID = :V$STAGE)
      AND (:I$Y18 = 0 OR V89.VAL < DATEADD(-18 YEAR TO M.DATE_OUT))
      AND (:I$OVZ = 0 OR (:I$OVZ = 1 AND V554.LISTVAL_ID <> 13283) OR (:I$OVZ = 2 AND V554.LISTVAL_ID = 13283))
      AND (:I$FORM IS NULL OR V80.LISTVAL_ID = :I$FORM)
    ORDER BY 1, 3
    INTO :V$PERSON_ID, :V$GROUP_ID, :V$DATE_OUT, :V$MOVE_ID
  DO
  BEGIN
    V$N1 = V$N1 + 1;
  END


  TAG_NAME = V$PREFIX || I$COL || '276:I';
  VAL = V$N1;
  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE REPORT_OO1_R29 (
    I$OU_ID BIGINT)
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(100))
AS
begin

  -- Учащиеся 1-4 классы, 1 смена
  TAG_NAME = '@5:BR9:I';
  SELECT COUNT(DISTINCT D.SCHOLAR_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 197
  JOIN VALI V706 ON V706.OBJ_ID = D.CLASS_ID AND V706.PARAM_ID = 706 AND V706.IS_DEL = 0 AND V706.VAL = 1
  WHERE D.ROW_NUM IN (1, 2, 3, 4, -1, -2, -3, -4)
  INTO :VAL;
  SUSPEND;

  -- Учащиеся 1-4 классы, 2 смена
  TAG_NAME = '@5:CI9:I';
  SELECT COUNT(DISTINCT D.SCHOLAR_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 197
  JOIN VALI V706 ON V706.OBJ_ID = D.CLASS_ID AND V706.PARAM_ID = 706 AND V706.IS_DEL = 0 AND V706.VAL = 2
  WHERE D.ROW_NUM IN (1, 2, 3, 4, -1, -2, -3, -4)
  INTO :VAL;
  SUSPEND;

  -- Учащиеся 1-4 классы, 3 смена
  TAG_NAME = '@5:CZ9:I';
  SELECT COUNT(DISTINCT D.SCHOLAR_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 197
  JOIN VALI V706 ON V706.OBJ_ID = D.CLASS_ID AND V706.PARAM_ID = 706 AND V706.IS_DEL = 0 AND V706.VAL = 3
  WHERE D.ROW_NUM IN (1, 2, 3, 4, -1, -2, -3, -4)
  INTO :VAL;
  SUSPEND;

  -- ГПД для 1-4 классов
  TAG_NAME = '@5:DQ9:I';
  SELECT COUNT(DISTINCT L46.OBJ_ID)
  FROM LINKS L86
  JOIN LINKS L46 ON L46.PARENT_ID = L86.OBJ_ID AND L46.OBJ_TYPE_ID = 46 AND L46.DATE_DEL IS NULL
  JOIN VALL V369 ON V369.OBJ_ID = L46.OBJ_ID AND V369.PARAM_ID = 369 AND V369.IS_DEL = 0 AND V369.LISTVAL_ID = 1246 -- ГПД
  JOIN LINKS L9 ON L9.PARENT_ID = L46.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
  JOIN LINKS LP8 ON LP8.OBJ_ID = L9.OBJ_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
  JOIN VALL V49 ON V49.OBJ_ID = LP8.PARENT_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0 AND V49.LISTVAL_ID IN (37, 38, 39, 40)
  WHERE L86.PARENT_ID = :I$OU_ID AND L86.OBJ_TYPE_ID = 86 AND L86.DATE_DEL IS NULL
  INTO :VAL;
  SUSPEND;

  -- Учащиеся 1-4 классы, посещавшие ГПД на указанную дату
  -- Пока проверка на конкретную дату забита !!!
  TAG_NAME = '@5:EH9:I';
  SELECT COUNT(DISTINCT D.SCHOLAR_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 197
  JOIN LINKS LP46 ON LP46.OBJ_ID = D.SCHOLAR_ID AND LP46.PARENT_TYPE_ID = 46
  JOIN VALL V369 ON V369.OBJ_ID = LP46.PARENT_TYPE_ID AND V369.PARAM_ID = 369 AND V369.IS_DEL = 0 AND V369.LISTVAL_ID = 1246 -- ГПД
  WHERE D.ROW_NUM IN (1, 2, 3, 4, -1, -2, -3, -4)
  INTO :VAL;
  SUSPEND;

  -- Учащиеся 5-9 классы, 1 смена
  TAG_NAME = '@5:BR10:I';
  SELECT COUNT(DISTINCT D.SCHOLAR_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 197
  JOIN VALI V706 ON V706.OBJ_ID = D.CLASS_ID AND V706.PARAM_ID = 706 AND V706.IS_DEL = 0 AND V706.VAL = 1
  WHERE D.ROW_NUM IN (5, 6, 7, 8, 9, -5, -6, -7, -8, -9)
  INTO :VAL;
  SUSPEND;

  -- Учащиеся 5-9 классы, 2 смена
  TAG_NAME = '@5:CI10:I';
  SELECT COUNT(DISTINCT D.SCHOLAR_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 197
  JOIN VALI V706 ON V706.OBJ_ID = D.CLASS_ID AND V706.PARAM_ID = 706 AND V706.IS_DEL = 0 AND V706.VAL = 2
  WHERE D.ROW_NUM IN (5, 6, 7, 8, 9, -5, -6, -7, -8, -9)
  INTO :VAL;
  SUSPEND;

  -- Учащиеся 5-9 классы, 3 смена
  TAG_NAME = '@5:CZ10:I';
  SELECT COUNT(DISTINCT D.SCHOLAR_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 197
  JOIN VALI V706 ON V706.OBJ_ID = D.CLASS_ID AND V706.PARAM_ID = 706 AND V706.IS_DEL = 0 AND V706.VAL = 3
  WHERE D.ROW_NUM IN (5, 6, 7, 8, 9, -5, -6, -7, -8, -9)
  INTO :VAL;
  SUSPEND;

  -- ГПД для 5-9 классов
  TAG_NAME = '@5:DQ10:I';
  SELECT COUNT(DISTINCT L46.OBJ_ID)
  FROM LINKS L86
  JOIN LINKS L46 ON L46.PARENT_ID = L86.OBJ_ID AND L46.OBJ_TYPE_ID = 46 AND L46.DATE_DEL IS NULL
  JOIN VALL V369 ON V369.OBJ_ID = L46.OBJ_ID AND V369.PARAM_ID = 369 AND V369.IS_DEL = 0 AND V369.LISTVAL_ID = 1246 -- ГПД
  JOIN LINKS L9 ON L9.PARENT_ID = L46.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
  JOIN LINKS LP8 ON LP8.OBJ_ID = L9.OBJ_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
  JOIN VALL V49 ON V49.OBJ_ID = LP8.PARENT_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0 AND V49.LISTVAL_ID IN (41, 42, 43, 44, 45)
  WHERE L86.PARENT_ID = :I$OU_ID AND L86.OBJ_TYPE_ID = 86 AND L86.DATE_DEL IS NULL
  INTO :VAL;
  SUSPEND;

  -- Учащиеся 5-9 классы, посещавшие ГПД на указанную дату
  -- Пока проверка на конкретную дату забита !!!
  TAG_NAME = '@5:EH10:I';
  SELECT COUNT(DISTINCT D.SCHOLAR_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 197
  JOIN LINKS LP46 ON LP46.OBJ_ID = D.SCHOLAR_ID AND LP46.PARENT_TYPE_ID = 46
  JOIN VALL V369 ON V369.OBJ_ID = LP46.PARENT_TYPE_ID AND V369.PARAM_ID = 369 AND V369.IS_DEL = 0 AND V369.LISTVAL_ID = 1246 -- ГПД
  WHERE D.ROW_NUM IN (5, 6, 7, 8, 9, -5, -6, -7, -8, -9)
  INTO :VAL;
  SUSPEND;

  -- Учащиеся 10-12 классы, 1 смена
  TAG_NAME = '@5:BR11:I';
  SELECT COUNT(DISTINCT D.SCHOLAR_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 197
  JOIN VALI V706 ON V706.OBJ_ID = D.CLASS_ID AND V706.PARAM_ID = 706 AND V706.IS_DEL = 0 AND V706.VAL = 1
  WHERE D.ROW_NUM IN (10, 11, 12, -10, -11, -12)
  INTO :VAL;
  SUSPEND;

  -- Учащиеся 5-9 классы, 2 смена
  TAG_NAME = '@5:CI11:I';
  SELECT COUNT(DISTINCT D.SCHOLAR_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 197
  JOIN VALI V706 ON V706.OBJ_ID = D.CLASS_ID AND V706.PARAM_ID = 706 AND V706.IS_DEL = 0 AND V706.VAL = 2
  WHERE D.ROW_NUM IN (10, 11, 12, -10, -11, -12)
  INTO :VAL;
  SUSPEND;

  -- Учащиеся 10-12 классы, 3 смена
  TAG_NAME = '@5:CZ11:I';
  SELECT COUNT(DISTINCT D.SCHOLAR_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 197
  JOIN VALI V706 ON V706.OBJ_ID = D.CLASS_ID AND V706.PARAM_ID = 706 AND V706.IS_DEL = 0 AND V706.VAL = 3
  WHERE D.ROW_NUM IN (10, 11, 12, -10, -11, -12)
  INTO :VAL;
  SUSPEND;

  -- Учащиеся *, 1 смена
  TAG_NAME = '@5:BR9:I';
  SELECT COUNT(DISTINCT D.SCHOLAR_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 197
  JOIN VALI V706 ON V706.OBJ_ID = D.CLASS_ID AND V706.PARAM_ID = 706 AND V706.IS_DEL = 0 AND V706.VAL = 1
  INTO :VAL;
  SUSPEND;

  -- Учащиеся *, 2 смена
  TAG_NAME = '@5:CI9:I';
  SELECT COUNT(DISTINCT D.SCHOLAR_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 197
  JOIN VALI V706 ON V706.OBJ_ID = D.CLASS_ID AND V706.PARAM_ID = 706 AND V706.IS_DEL = 0 AND V706.VAL = 2
  INTO :VAL;
  SUSPEND;

  -- Учащиеся *, 3 смена
  TAG_NAME = '@5:CZ9:I';
  SELECT COUNT(DISTINCT D.SCHOLAR_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 197
  JOIN VALI V706 ON V706.OBJ_ID = D.CLASS_ID AND V706.PARAM_ID = 706 AND V706.IS_DEL = 0 AND V706.VAL = 3
  INTO :VAL;
  SUSPEND;

  -- ГПД для *
  TAG_NAME = '@5:DQ9:I';
  SELECT COUNT(DISTINCT L46.OBJ_ID)
  FROM LINKS L86
  JOIN LINKS L46 ON L46.PARENT_ID = L86.OBJ_ID AND L46.OBJ_TYPE_ID = 46 AND L46.DATE_DEL IS NULL
  JOIN VALL V369 ON V369.OBJ_ID = L46.OBJ_ID AND V369.PARAM_ID = 369 AND V369.IS_DEL = 0 AND V369.LISTVAL_ID = 1246 -- ГПД
  WHERE L86.PARENT_ID = :I$OU_ID AND L86.OBJ_TYPE_ID = 86 AND L86.DATE_DEL IS NULL
  INTO :VAL;
  SUSPEND;

  -- Учащиеся *, посещавшие ГПД на указанную дату
  -- Пока проверка на конкретную дату забита !!!
  TAG_NAME = '@5:EH9:I';
  SELECT COUNT(DISTINCT D.SCHOLAR_ID)
  FROM REPORT_D12 D
  JOIN VALL V592 ON V592.OBJ_ID = D.CLASS_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 197
  JOIN LINKS LP46 ON LP46.OBJ_ID = D.SCHOLAR_ID AND LP46.PARENT_TYPE_ID = 46
  JOIN VALL V369 ON V369.OBJ_ID = LP46.PARENT_TYPE_ID AND V369.PARAM_ID = 369 AND V369.IS_DEL = 0 AND V369.LISTVAL_ID = 1246 -- ГПД
  INTO :VAL;
  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE REPORT_OO1_R31 RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(100))
AS
begin

  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R31_COL(1, 'AM') INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R31_COL(2, 'AV') INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R31_COL(3, 'BD') INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R31_COL(4, 'BL') INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R31_COL(5, 'BU') INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R31_COL(6, 'CD') INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R31_COL(7, 'CN') INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R31_COL(8, 'CW') INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R31_COL(9, 'DH') INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R31_COL(10, 'DP') INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R31_COL(11, 'DZ') INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R31_COL(12, 'EI') INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R31_COL(13, 'ER') INTO :TAG_NAME, :VAL DO SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE REPORT_OO1_R31_COL (
    I$COL SMALLINT,
    I$CS VARCHAR(10))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(100))
AS
declare variable V$YEAR integer;
declare variable V$DATE date;
declare variable V$PREFIX varchar(10);
declare variable V$PERSON_ID bigint;
declare variable V$MATCH smallint;
declare variable V$N_ALL integer;
declare variable V$N2 integer;
declare variable V$N3 integer;
declare variable V$N4 integer;
declare variable V$N5 integer;
declare variable V$N6 integer;
declare variable V$N7 integer;
declare variable V$N8 integer;
declare variable V$N9 integer;
declare variable V$N10 integer;
declare variable V$N11 integer;
declare variable V$N12 integer;
declare variable V$N13 integer;
declare variable V$N14 integer;
declare variable V$N15 integer;
declare variable V$N16 integer;
declare variable V$N17 integer;
declare variable V$N18 integer;
declare variable V$N19 integer;
declare variable V$N20 integer;
declare variable V$N21 integer;
declare variable V$N22 integer;
declare variable V$N23 integer;
declare variable V$N24 integer;
declare variable V$N25 integer;
declare variable V$N26 integer;
declare variable V$N27 integer;
declare variable V$N28 integer;
declare variable V$N29 integer;
declare variable V$N30 integer;
declare variable V$N31 integer;
declare variable V$N32 integer;
declare variable V$N33 integer;
declare variable V$N34 integer;
declare variable V$N35 integer;
declare variable V$N36 integer;
declare variable V$N37 integer;
declare variable V$N38 integer;
declare variable V$X1 integer;
declare variable V$X2 integer;
declare variable V$X3 integer;
declare variable V$X4 integer;
declare variable V$X5 integer;
declare variable V$X6 integer;
declare variable V$X7 integer;
declare variable V$X8 integer;
declare variable V$IS_UP smallint;
begin

  V$YEAR = EXTRACT(YEAR FROM CURRENT_DATE);
  IF(EXTRACT(MONTH FROM CURRENT_DATE) < 9) THEN V$YEAR = V$YEAR - 1;
  V$DATE = '20.09.' || V$YEAR;

  V$PREFIX = '@6:';
  IF(I$COL = 100) THEN V$PREFIX = '@7:'; -- копия в раздел 3.4 (тут отличаются номера строк)

  V$N_ALL = 0;
  V$N2 = 0;
  V$N3 = 0;
  V$N4 = 0;
  V$N5 = 0;
  V$N6 = 0;
  V$N7 = 0;
  V$N8 = 0;
  V$N9 = 0;
  V$N10 = 0;
  V$N11 = 0;
  V$N12 = 0;
  V$N13 = 0;
  V$N14 = 0;
  V$N15 = 0;
  V$N16 = 0;
  V$N17 = 0;
  V$N18 = 0;
  V$N19 = 0;
  V$N20 = 0;
  V$N21 = 0;
  V$N22 = 0;
  V$N23 = 0;
  V$N24 = 0;
  V$N25 = 0;
  V$N26 = 0;
  V$N27 = 0;
  V$N28 = 0;
  V$N29 = 0;
  V$N30 = 0;
  V$N31 = 0;
  V$N32 = 0;
  V$N33 = 0;
  V$N34 = 0;
  V$N35 = 0;
  V$N36 = 0;
  V$N37 = 0;
  V$N38 = 0;
  V$X1 = 0;
  V$X2 = 0;
  V$X3 = 0;
  V$X4 = 0;
  V$X5 = 0;
  V$X6 = 0;
  V$X7 = 0;
  V$X8 = 0;

  FOR
      SELECT D.SCHOLAR_ID
      FROM REPORT_D12 D
      JOIN VALL V239 ON V239.OBJ_ID = D.SCHOLAR_ID AND V239.PARAM_ID = 239 AND V239.IS_DEL = 0  -- пол
      LEFT JOIN VALL V278 ON V278.OBJ_ID = D.SCHOLAR_ID AND V278.PARAM_ID = 278 AND V278.IS_DEL = 0 -- образование
      LEFT JOIN VALL V279 ON V279.OBJ_ID = D.SCHOLAR_ID AND V279.PARAM_ID = 279 AND V279.IS_DEL = 0 -- ученая степень
      LEFT JOIN VALL V1373 ON V1373.OBJ_ID = D.SCHOLAR_ID AND V1373.PARAM_ID = 1373 AND V1373.IS_DEL = 0 -- ученое звание
      LEFT JOIN VALL V281 ON V281.OBJ_ID = D.SCHOLAR_ID AND V281.PARAM_ID = 281 AND V281.IS_DEL = 0 -- квалификационная категория
      WHERE (:I$COL = 1 OR :I$COL = 100) OR -- все сотрудники (100 - для раздела 3.5)
        (:I$COL = 2 AND V278.LISTVAL_ID IN (620, 3031, 3032)) OR -- высшее образование
        (:I$COL = 3 AND V278.LISTVAL_ID IN (620, 3031, 3032)) OR -- высшее образование + педагогическое
        (:I$COL = 4 AND V278.LISTVAL_ID IN (620, 3031, 3032) AND V279.LISTVAL_ID = 628) OR -- высшее образование + доктор
        (:I$COL = 5 AND V278.LISTVAL_ID IN (620, 3031, 3032) AND V279.LISTVAL_ID = 627) OR -- высшее образование + кандидат
        (:I$COL = 6 AND V278.LISTVAL_ID IN (620, 3031, 3032) AND V1373.LISTVAL_ID = 2998) OR -- высшее образование + профессор
        (:I$COL = 7 AND V278.LISTVAL_ID IN (620, 3031, 3032) AND V1373.LISTVAL_ID = 2997) OR -- высшее образование + доцент
        (:I$COL = 8 AND V278.LISTVAL_ID = 622) OR -- среднее профессиональное образование
        (:I$COL = 9 AND V278.LISTVAL_ID = 622) OR -- среднее профессиональное образование + педагогическое
        (:I$COL = 10 AND V278.LISTVAL_ID = 624) OR -- среднее профессиональное образование, но на самом деле начальное !
        (:I$COL = 11 AND V281.LISTVAL_ID = 635) OR -- высшая категория
        (:I$COL = 12 AND V281.LISTVAL_ID = 634) OR -- первая категория
        (:I$COL = 13 AND V239.LISTVAL_ID = 182) -- женщины
      INTO :V$PERSON_ID
  DO
  BEGIN

      V$MATCH = 1;

      -- Дофильтровываем по педагогическим должностям
      IF(I$COL IN (3, 9)) THEN
      BEGIN
          V$MATCH = 0;
          SELECT FIRST 1 1
          FROM LINKS L33
          JOIN VALL V293 ON V293.OBJ_ID = L33.OBJ_ID AND V293.PARAM_ID = 293 AND V293.IS_DEL = 0 AND V293.LISTVAL_ID = 647
          WHERE L33.PARENT_ID = :V$PERSON_ID AND L33.OBJ_TYPE_ID = 33 AND L33.DATE_DEL IS NULL
          INTO :V$MATCH;
      END

      IF(V$MATCH = 1) THEN
      BEGIN
          -- повышение квалификации или переподготовки в последние 3 года - делаем только для столбца 1
          V$IS_UP = 0;
          IF(I$COL = 1) THEN
          BEGIN
              SELECT FIRST 1 1
              FROM LINKS L35
              JOIN VALD V300 ON V300.OBJ_ID = L35.OBJ_ID AND V300.PARAM_ID = 300 AND V300.IS_DEL = 0 AND V300.VAL >= DATEADD(-3 YEAR TO :V$DATE)
              WHERE L35.PARENT_ID = :V$PERSON_ID AND L35.OBJ_TYPE_ID = 35 AND L35.DATE_DEL IS NULL
              UNION
              SELECT FIRST 1 1
              FROM LINKS L36
              JOIN VALD V310 ON V310.OBJ_ID = L36.OBJ_ID AND V310.PARAM_ID = 310 AND V310.IS_DEL = 0 AND V310.VAL >= DATEADD(-3 YEAR TO :V$DATE)
              WHERE L36.PARENT_ID = :V$PERSON_ID AND L36.OBJ_TYPE_ID = 36 AND L36.DATE_DEL IS NULL
              INTO :V$IS_UP;
          END

          -- общий счетчик
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720))) THEN V$N_ALL = V$N_ALL + 1;
          -- руководители все
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.GROUP_ID = 55)) THEN
          BEGIN
              V$N2 = V$N2 + 1;
              IF(V$IS_UP = 1) THEN V$X1 = V$X1 + 1;
          END
          -- директор
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 64)) THEN
          BEGIN
              V$N3 = V$N3 + 1;
              IF(V$IS_UP = 1) THEN V$X2 = V$X2 + 1;
          END
          -- зам директора
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 80)) THEN V$N4 = V$N4 + 1;
          -- рук филиала
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 68)) THEN V$N5 = V$N5 + 1;
          -- все педагоги
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.IS_EDU = 1)) THEN BEGIN
              V$N6 = V$N6 + 1;
              IF(V$IS_UP = 1) THEN V$X3 = V$X3 + 1;
          END
          -- учителя
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.SUBGROUP_ID = 98)) THEN
          BEGIN
              V$N7 = V$N7 + 1;
              IF(V$IS_UP = 1) THEN V$X4 = V$X4 + 1;
          END
          -- учителя начального образования
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 108)) THEN V$N8 = V$N8 + 1;
          -- учителя русского и литературы
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID IN (112, 1260))) THEN V$N9 = V$N9 + 1;
          -- учителя языков народов России
          -- IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 108)) THEN V$N10 = V$N10 + 1;
          -- история, экономика, право, обществознание
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID IN (104, 1268, 1273, 1278, 1282))) THEN V$N11 = V$N11 + 1;
          -- информатика и ИКТ
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 102)) THEN V$N12 = V$N12 + 1;
          -- физика
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 115)) THEN V$N13 = V$N13 + 1;
          -- математика
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 105)) THEN V$N14 = V$N14 + 1;
          -- химия
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 118)) THEN V$N15 = V$N15 + 1;
          -- география
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 101)) THEN V$N16 = V$N16 + 1;
          -- биология                                                                                                                                     
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 100)) THEN V$N17 = V$N17 + 1;
          -- иностранные языки
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID IN (99, 109, 117, 1264))) THEN V$N18 = V$N18 + 1;
          -- иностранные - английский
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 99)) THEN V$N19 = V$N19 + 1;
          -- иностранные - немецкий
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 109)) THEN V$N20 = V$N20 + 1;
          -- иностранные - французский
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 117)) THEN V$N21 = V$N21 + 1;
          -- физкультура
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 116)) THEN V$N22 = V$N22 + 1;
          -- труд и технология
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID IN (114, 1286))) THEN V$N23 = V$N23 + 1;
          -- музыка и пение
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 106)) THEN V$N24 = V$N24 + 1;
          -- изо и черчение
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID IN (111, 3148))) THEN V$N25 = V$N25 + 1;
          -- обж
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 110)) THEN V$N26 = V$N26 + 1;
          -- прочее
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID IN (107, 1283, 1285, 122))) THEN V$N27 = V$N27 + 1;
          -- учитель-логопед
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 119)) THEN V$N28 = V$N28 + 1;
          -- учитель-дефектолог - без раскрытия
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 120)) THEN V$N29 = V$N29 + 1;
          -- социальный педагог
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 1251)) THEN V$N30 = V$N30 + 1;
          -- педагог ДО + педагог-организатор
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID IN (143, 144))) THEN V$N31 = V$N31 + 1;
          -- педагог-психолог
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 140)) THEN V$N32 = V$N32 + 1;
          -- воспитатель
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.SUBGROUP_ID = 125)) THEN V$N33 = V$N33 + 1;
          -- мастер ПО
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.SUBGROUP_ID = 129)) THEN V$N34 = V$N34 + 1;
          -- тьютор
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 1291)) THEN V$N35 = V$N35 + 1;
          -- прочие
          -- IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 1291)) THEN V$N36 = V$N36 + 1;
          -- учебно-вспомогательный
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.SUBGROUP_ID = 1313)) THEN V$N37 = V$N37 + 1;
          -- иной персонал
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.SUBGROUP_ID = 1257)) THEN V$N38 = V$N38 + 1;
      END

  END

  -- Нумерация строк в разделе 3.4 (COL=100) отличается от раздела 3.1, коррекция делается в REPORT_OO1_R34

  TAG_NAME = V$PREFIX || I$CS || '12:I';
  VAL = V$N_ALL;
  SUSPEND;
  TAG_NAME = V$PREFIX || I$CS || '13:I';
  VAL = V$N2;
  SUSPEND;
  TAG_NAME = V$PREFIX || I$CS || '14:I';
  VAL = V$N3;
  SUSPEND;
  TAG_NAME = V$PREFIX || I$CS || '16:I';
  VAL = V$N4;
  SUSPEND;
  TAG_NAME = V$PREFIX || I$CS || '17:I';
  VAL = V$N5;
  SUSPEND;
  TAG_NAME = V$PREFIX || I$CS || '18:I';
  VAL = V$N6;
  SUSPEND;
  TAG_NAME = V$PREFIX || I$CS || '19:I';
  VAL = V$N7;
  SUSPEND;
  TAG_NAME = V$PREFIX || I$CS || '20:I';
  VAL = V$N8;
  SUSPEND;
  TAG_NAME = V$PREFIX || I$CS || '22:I';
  VAL = V$N9;
  SUSPEND;
  TAG_NAME = V$PREFIX || I$CS || '23:I';
  VAL = V$N10;
  SUSPEND;
  TAG_NAME = V$PREFIX || I$CS || '25:I';
  VAL = V$N11;
  SUSPEND;
  TAG_NAME = V$PREFIX || I$CS || '27:I';
  VAL = V$N12;
  SUSPEND;
  TAG_NAME = V$PREFIX || I$CS || '28:I';
  VAL = V$N13;
  SUSPEND;
  TAG_NAME = V$PREFIX || I$CS || '29:I';
  VAL = V$N14;
  SUSPEND;
  TAG_NAME = V$PREFIX || I$CS || '30:I';
  VAL = V$N15;
  SUSPEND;
  TAG_NAME = V$PREFIX || I$CS || '32:I';
  VAL = V$N16;
  SUSPEND;
  TAG_NAME = V$PREFIX || I$CS || '33:I';
  VAL = V$N17;
  SUSPEND;
  TAG_NAME = V$PREFIX || I$CS || '34:I';
  VAL = V$N18;
  SUSPEND;
  TAG_NAME = V$PREFIX || I$CS || '35:I';
  VAL = V$N19;
  SUSPEND;
  TAG_NAME = V$PREFIX || I$CS || '37:I';
  VAL = V$N20;
  SUSPEND;                      
  TAG_NAME = V$PREFIX || I$CS || '38:I';
  VAL = V$N21;
  SUSPEND;
  TAG_NAME = V$PREFIX || I$CS || '39:I';
  VAL = V$N22;
  SUSPEND;
  TAG_NAME = V$PREFIX || I$CS || '40:I';
  VAL = V$N23;
  SUSPEND;
  TAG_NAME = V$PREFIX || I$CS || '41:I';
  VAL = V$N24;
  SUSPEND;
  TAG_NAME = V$PREFIX || I$CS || '42:I';
  VAL = V$N25;
  SUSPEND;
  TAG_NAME = V$PREFIX || I$CS || '44:I';
  VAL = V$N26;
  SUSPEND;
  TAG_NAME = V$PREFIX || I$CS || '46:I';
  VAL = V$N27;
  SUSPEND;
  TAG_NAME = V$PREFIX || I$CS || '47:I';
  VAL = V$N28;
  SUSPEND;
  TAG_NAME = V$PREFIX || I$CS || '48:I';
  VAL = V$N29;
  SUSPEND;
  -- три строки вариантов дефектологов - пропускаем
  TAG_NAME = V$PREFIX || I$CS || '53:I';
  VAL = V$N30;
  SUSPEND;
  TAG_NAME = V$PREFIX || I$CS || '54:I';
  VAL = V$N31;
  SUSPEND;
  TAG_NAME = V$PREFIX || I$CS || '55:I';
  VAL = V$N32;
  SUSPEND;
  TAG_NAME = V$PREFIX || I$CS || '56:I';
  VAL = V$N33;
  SUSPEND;
  TAG_NAME = V$PREFIX || I$CS || '57:I';
  VAL = V$N34;
  SUSPEND;
  TAG_NAME = V$PREFIX || I$CS || '58:I';
  VAL = V$N35;
  SUSPEND;
  TAG_NAME = V$PREFIX || I$CS || '59:I';
  VAL = V$N36;
  SUSPEND;
  TAG_NAME = V$PREFIX || I$CS || '60:I';
  VAL = V$N37;
  SUSPEND;
  TAG_NAME = V$PREFIX || I$CS || '61:I';
  VAL = V$N38;
  SUSPEND;

  -- Дополнение - только в первом столбце
  IF(I$COL = 1) THEN
  BEGIN
      I$CS = 'CF';

      TAG_NAME = V$PREFIX || I$CS || '80:I';
      VAL = V$X1;
      SUSPEND;
      TAG_NAME = V$PREFIX || I$CS || '81:I';
      VAL = V$X2;
      SUSPEND;
      TAG_NAME = V$PREFIX || I$CS || '83:I';
      VAL = V$X3;
      SUSPEND;
      TAG_NAME = V$PREFIX || I$CS || '84:I';
      VAL = V$X4;
      SUSPEND;
      TAG_NAME = V$PREFIX || I$CS || '85:I';
      VAL = V$X5;
      SUSPEND;
      TAG_NAME = V$PREFIX || I$CS || '86:I';
      VAL = V$X6;
      SUSPEND;
      TAG_NAME = V$PREFIX || I$CS || '88:I';
      VAL = V$X7;
      SUSPEND;
      TAG_NAME = V$PREFIX || I$CS || '89:I';
      VAL = V$X8;
      SUSPEND;

      -- Имеющие компьютеры
      TAG_NAME = V$PREFIX || I$CS || '91:I';
      VAL = '';
      SUSPEND;

      -- Классное руководство всего
      TAG_NAME = V$PREFIX || I$CS || '93:I';
      VAL = '';
      SUSPEND;

      -- Классное руководство в 1 классе
      TAG_NAME = V$PREFIX || I$CS || '95:I';
      VAL = '';
      SUSPEND;
      -- Классное руководство в 2+ классах
      TAG_NAME = V$PREFIX || I$CS || '96:I';
      VAL = '';
      SUSPEND;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE REPORT_OO1_R32 RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(100))
AS
begin

  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R32_COL(1, 'AS') INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R32_COL(2, 'BD') INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R32_COL(3, 'BV') INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R32_COL(4, 'CN') INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R32_COL(5, 'DF') INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R32_COL(6, 'DX') INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R32_COL(7, 'EP') INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R32_COL(8, 'AO') INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R32_COL(9, 'BI') INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R32_COL(10, 'BW') INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R32_COL(11, 'CK') INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R32_COL(12, 'CY') INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R32_COL(13, 'DM') INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R32_COL(14, 'EA') INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R32_COL(15, 'EO') INTO :TAG_NAME, :VAL DO SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE REPORT_OO1_R32_COL (
    I$COL SMALLINT,
    I$CS VARCHAR(10))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(100))
AS
declare variable V$YEAR integer;
declare variable V$DATE date;
declare variable V$PERSON_ID bigint;
declare variable V$N_ALL integer;
declare variable V$N2 integer;
declare variable V$N3 integer;
declare variable V$N4 integer;
declare variable V$N5 integer;
declare variable V$N6 integer;
declare variable V$N7 integer;
declare variable V$N8 integer;
declare variable V$N9 integer;
declare variable V$N10 integer;
declare variable V$N11 integer;
declare variable V$N12 integer;
declare variable V$N13 integer;
declare variable V$N14 integer;
declare variable V$N15 integer;
declare variable V$N16 integer;
declare variable V$N17 integer;
declare variable V$N18 integer;
declare variable V$N19 integer;
declare variable V$N20 integer;
declare variable V$N21 integer;
declare variable V$N22 integer;
declare variable V$N23 integer;
declare variable V$N24 integer;
declare variable V$N25 integer;
declare variable V$N26 integer;
declare variable V$N27 integer;
declare variable V$N28 integer;
declare variable V$N29 integer;
declare variable V$N30 integer;
declare variable V$N31 integer;
declare variable V$N32 integer;
declare variable V$N33 integer;
declare variable V$N34 integer;
declare variable V$N35 integer;
declare variable V$N36 integer;
declare variable V$N37 integer;
declare variable V$N38 integer;
begin

  V$YEAR = EXTRACT(YEAR FROM CURRENT_DATE);
  IF(EXTRACT(MONTH FROM CURRENT_DATE) < 9) THEN V$YEAR = V$YEAR - 1;
  V$DATE = '20.09.' || V$YEAR;

  -- В старом отчете шло общей таблицей, теперь разбито на два блока

  V$N_ALL = 0;
  V$N2 = 0;
  V$N3 = 0;
  V$N4 = 0;
  V$N5 = 0;
  V$N6 = 0;
  V$N7 = 0;
  V$N8 = 0;
  V$N9 = 0;
  V$N10 = 0;
  V$N11 = 0;
  V$N12 = 0;
  V$N13 = 0;
  V$N14 = 0;
  V$N15 = 0;
  V$N16 = 0;
  V$N17 = 0;
  V$N18 = 0;
  V$N19 = 0;
  V$N20 = 0;
  V$N21 = 0;
  V$N22 = 0;
  V$N23 = 0;
  V$N24 = 0;
  V$N25 = 0;
  V$N26 = 0;
  V$N27 = 0;
  V$N28 = 0;
  V$N29 = 0;
  V$N30 = 0;
  V$N31 = 0;
  V$N32 = 0;
  V$N33 = 0;
  V$N34 = 0;
  V$N35 = 0;
  V$N36 = 0;
  V$N37 = 0;
  V$N38 = 0;

  FOR
      SELECT D.SCHOLAR_ID
      FROM REPORT_D12 D
      JOIN VALL V239 ON V239.OBJ_ID = D.SCHOLAR_ID AND V239.PARAM_ID = 239 AND V239.IS_DEL = 0  -- пол
      LEFT JOIN VALL V278 ON V278.OBJ_ID = D.SCHOLAR_ID AND V278.PARAM_ID = 278 AND V278.IS_DEL = 0 -- образование
      LEFT JOIN VALL V279 ON V279.OBJ_ID = D.SCHOLAR_ID AND V279.PARAM_ID = 279 AND V279.IS_DEL = 0 -- ученая степень
      LEFT JOIN VALL V1373 ON V1373.OBJ_ID = D.SCHOLAR_ID AND V1373.PARAM_ID = 1373 AND V1373.IS_DEL = 0 -- ученое звание
      LEFT JOIN VALL V281 ON V281.OBJ_ID = D.SCHOLAR_ID AND V281.PARAM_ID = 281 AND V281.IS_DEL = 0 -- квалификационная категория
      WHERE (:I$COL = 1) OR -- все сотрудники
        (:I$COL = 2 AND D.C1 < 3) OR -- общ стаж < 3
        (:I$COL = 3 AND D.C1 >= 3 AND D.C1 < 5) OR -- общ стаж 3..5
        (:I$COL = 4 AND D.C1 >= 5 AND D.C1 < 10) OR -- общ стаж 5..10
        (:I$COL = 5 AND D.C1 >= 10 AND D.C1 < 15) OR -- общ стаж 10..15
        (:I$COL = 6 AND D.C1 >= 15 AND D.C1 < 20) OR -- общ стаж 15..20
        (:I$COL = 7 AND D.C1 >= 20) OR -- общ стаж 20+
        (:I$COL = 8 AND D.C2 > 0) OR -- пед стаж > 0
        (:I$COL = 9 AND D.C2 > 0 AND D.C2 < 3) OR -- пед стаж < 3
        (:I$COL = 10 AND D.C2 >= 3 AND D.C2 < 5) OR -- пед стаж 3..5
        (:I$COL = 11 AND D.C2 >= 5 AND D.C2 < 10) OR -- пед стаж 5..10
        (:I$COL = 12 AND D.C2 >= 10 AND D.C2 < 15) OR -- пед стаж 10..15
        (:I$COL = 13 AND D.C2 >= 15 AND D.C2 < 20) OR -- пед стаж 15..20
        (:I$COL = 14 AND D.C2 >= 20) OR -- пед стаж 20+
        (:I$COL = 15 AND D.C2 = 0) -- пед стаж 0
      INTO :V$PERSON_ID
  DO
  BEGIN

          -- общий счетчик
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720))) THEN V$N_ALL = V$N_ALL + 1;
          -- руководители все
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.GROUP_ID = 55)) THEN V$N2 = V$N2 + 1;
          -- директор
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 64)) THEN V$N3 = V$N3 + 1;
          -- зам директора
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 80)) THEN V$N4 = V$N4 + 1;
          -- рук филиала
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 68)) THEN V$N5 = V$N5 + 1;
          -- все педагоги
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.IS_EDU = 1)) THEN  V$N6 = V$N6 + 1;
          -- учителя
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.SUBGROUP_ID = 98)) THEN V$N7 = V$N7 + 1;
          -- учителя начального образования
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 108)) THEN V$N8 = V$N8 + 1;
          -- учителя русского и литературы
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID IN (112, 1260))) THEN V$N9 = V$N9 + 1;
          -- учителя языков народов России
          -- IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 108)) THEN V$N10 = V$N10 + 1;
          -- история, экономика, право, обществознание
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID IN (104, 1268, 1273, 1278, 1282))) THEN V$N11 = V$N11 + 1;
          -- информатика и ИКТ
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 102)) THEN V$N12 = V$N12 + 1;
          -- физика
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 115)) THEN V$N13 = V$N13 + 1;
          -- математика
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 105)) THEN V$N14 = V$N14 + 1;
          -- химия
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 118)) THEN V$N15 = V$N15 + 1;
          -- география
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 101)) THEN V$N16 = V$N16 + 1;
          -- биология                                                                                                                                     
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 100)) THEN V$N17 = V$N17 + 1;
          -- иностранные языки
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID IN (99, 109, 117, 1264))) THEN V$N18 = V$N18 + 1;
          -- иностранные - английский
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 99)) THEN V$N19 = V$N19 + 1;
          -- иностранные - немецкий
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 109)) THEN V$N20 = V$N20 + 1;
          -- иностранные - французский
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 117)) THEN V$N21 = V$N21 + 1;
          -- физкультура
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 116)) THEN V$N22 = V$N22 + 1;
          -- труд и технология
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID IN (114, 1286))) THEN V$N23 = V$N23 + 1;
          -- музыка и пение
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 106)) THEN V$N24 = V$N24 + 1;
          -- изо и черчение
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID IN (111, 3148))) THEN V$N25 = V$N25 + 1;
          -- обж
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 110)) THEN V$N26 = V$N26 + 1;
          -- прочее
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID IN (107, 1283, 1285, 122))) THEN V$N27 = V$N27 + 1;
          -- учитель-логопед
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 119)) THEN V$N28 = V$N28 + 1;
          -- учитель-дефектолог - без раскрытия
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 120)) THEN V$N29 = V$N29 + 1;
          -- социальный педагог
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 1251)) THEN V$N30 = V$N30 + 1;
          -- педагог ДО + педагог-организатор
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID IN (143, 144))) THEN V$N31 = V$N31 + 1;
          -- педагог-психолог
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 140)) THEN V$N32 = V$N32 + 1;
          -- воспитатель
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.SUBGROUP_ID = 125)) THEN V$N33 = V$N33 + 1;
          -- мастер ПО
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.SUBGROUP_ID = 129)) THEN V$N34 = V$N34 + 1;
          -- тьютор
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 1291)) THEN V$N35 = V$N35 + 1;
          -- прочие
          -- IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 1291)) THEN V$N36 = V$N36 + 1;
          -- учебно-вспомогательный
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.SUBGROUP_ID = 1313)) THEN V$N37 = V$N37 + 1;
          -- иной персонал
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.SUBGROUP_ID = 1257)) THEN V$N38 = V$N38 + 1;

  END

  IF(I$COL <= 7) THEN
  BEGIN
  TAG_NAME = '@6:' || I$CS || '104:I';
  VAL = V$N_ALL;
  SUSPEND;
  TAG_NAME = '@6:' || I$CS || '105:I';
  VAL = V$N2;
  SUSPEND;
  TAG_NAME = '@6:' || I$CS || '106:I';
  VAL = V$N3;
  SUSPEND;
  TAG_NAME = '@6:' || I$CS || '108:I';
  VAL = V$N4;
  SUSPEND;
  TAG_NAME = '@6:' || I$CS || '109:I';
  VAL = V$N5;
  SUSPEND;
  TAG_NAME = '@6:' || I$CS || '110:I';
  VAL = V$N6;
  SUSPEND;
  TAG_NAME = '@6:' || I$CS || '111:I';
  VAL = V$N7;
  SUSPEND;
  TAG_NAME = '@6:' || I$CS || '112:I';
  VAL = V$N8;
  SUSPEND;
  TAG_NAME = '@6:' || I$CS || '114:I';
  VAL = V$N9;
  SUSPEND;
  TAG_NAME = '@6:' || I$CS || '115:I';
  VAL = V$N10;
  SUSPEND;
  TAG_NAME = '@6:' || I$CS || '119:I';
  VAL = V$N11;
  SUSPEND;
  TAG_NAME = '@6:' || I$CS || '119:I';
  VAL = V$N12;
  SUSPEND;
  TAG_NAME = '@6:' || I$CS || '120:I';
  VAL = V$N13;
  SUSPEND;
  TAG_NAME = '@6:' || I$CS || '121:I';
  VAL = V$N14;
  SUSPEND;
  TAG_NAME = '@6:' || I$CS || '122:I';
  VAL = V$N15;
  SUSPEND;
  TAG_NAME = '@6:' || I$CS || '123:I';
  VAL = V$N16;
  SUSPEND;
  TAG_NAME = '@6:' || I$CS || '124:I';
  VAL = V$N17;
  SUSPEND;
  TAG_NAME = '@6:' || I$CS || '125:I';
  VAL = V$N18;
  SUSPEND;
  TAG_NAME = '@6:' || I$CS || '126:I';
  VAL = V$N19;
  SUSPEND;
  TAG_NAME = '@6:' || I$CS || '128:I';
  VAL = V$N20;
  SUSPEND;                      
  TAG_NAME = '@6:' || I$CS || '129:I';
  VAL = V$N21;
  SUSPEND;
  TAG_NAME = '@6:' || I$CS || '130:I';
  VAL = V$N22;
  SUSPEND;
  TAG_NAME = '@6:' || I$CS || '131:I';
  VAL = V$N23;
  SUSPEND;
  TAG_NAME = '@6:' || I$CS || '132:I';
  VAL = V$N24;
  SUSPEND;
  TAG_NAME = '@6:' || I$CS || '133:I';
  VAL = V$N25;
  SUSPEND;
  TAG_NAME = '@6:' || I$CS || '136:I';
  VAL = V$N26;
  SUSPEND;
  TAG_NAME = '@6:' || I$CS || '138:I';
  VAL = V$N27;
  SUSPEND;
  TAG_NAME = '@6:' || I$CS || '139:I';
  VAL = V$N28;
  SUSPEND;
  TAG_NAME = '@6:' || I$CS || '140:I';
  VAL = V$N29;
  SUSPEND;
  -- три строки вариантов дефектологов - пропускаем
  TAG_NAME = '@6:' || I$CS || '145:I';
  VAL = V$N30;
  SUSPEND;
  TAG_NAME = '@6:' || I$CS || '146:I';
  VAL = V$N31;
  SUSPEND;
  TAG_NAME = '@6:' || I$CS || '147:I';
  VAL = V$N32;
  SUSPEND;
  TAG_NAME = '@6:' || I$CS || '148:I';
  VAL = V$N33;
  SUSPEND;
  TAG_NAME = '@6:' || I$CS || '149:I';
  VAL = V$N34;
  SUSPEND;
  TAG_NAME = '@6:' || I$CS || '150:I';
  VAL = V$N35;
  SUSPEND;
  TAG_NAME = '@6:' || I$CS || '151:I';
  VAL = V$N36;
  SUSPEND;
  TAG_NAME = '@6:' || I$CS || '152:I';
  VAL = V$N37;
  SUSPEND;
  TAG_NAME = '@6:' || I$CS || '153:I';
  VAL = V$N38;
  SUSPEND;
  END
  ELSE
  BEGIN
  TAG_NAME = '@6:' || I$CS || '168:I';
  VAL = V$N_ALL;
  SUSPEND;
  TAG_NAME = '@6:' || I$CS || '169:I';
  VAL = V$N2;
  SUSPEND;
  TAG_NAME = '@6:' || I$CS || '170:I';
  VAL = V$N3;
  SUSPEND;
  TAG_NAME = '@6:' || I$CS || '172:I';
  VAL = V$N4;
  SUSPEND;
  TAG_NAME = '@6:' || I$CS || '173:I';
  VAL = V$N5;
  SUSPEND;
  TAG_NAME = '@6:' || I$CS || '174:I';
  VAL = V$N6;
  SUSPEND;
  TAG_NAME = '@6:' || I$CS || '175:I';
  VAL = V$N7;
  SUSPEND;
  TAG_NAME = '@6:' || I$CS || '176:I';
  VAL = V$N8;
  SUSPEND;
  TAG_NAME = '@6:' || I$CS || '178:I';
  VAL = V$N9;
  SUSPEND;
  TAG_NAME = '@6:' || I$CS || '179:I';
  VAL = V$N10;
  SUSPEND;
  TAG_NAME = '@6:' || I$CS || '181:I';
  VAL = V$N11;
  SUSPEND;
  TAG_NAME = '@6:' || I$CS || '183:I';
  VAL = V$N12;
  SUSPEND;
  TAG_NAME = '@6:' || I$CS || '184:I';
  VAL = V$N13;
  SUSPEND;
  TAG_NAME = '@6:' || I$CS || '185:I';
  VAL = V$N14;
  SUSPEND;
  TAG_NAME = '@6:' || I$CS || '186:I';
  VAL = V$N15;
  SUSPEND;
  TAG_NAME = '@6:' || I$CS || '187:I';
  VAL = V$N16;
  SUSPEND;
  TAG_NAME = '@6:' || I$CS || '188:I';
  VAL = V$N17;
  SUSPEND;
  TAG_NAME = '@6:' || I$CS || '189:I';
  VAL = V$N18;
  SUSPEND;
  TAG_NAME = '@6:' || I$CS || '190:I';
  VAL = V$N19;
  SUSPEND;
  TAG_NAME = '@6:' || I$CS || '192:I';
  VAL = V$N20;
  SUSPEND;                      
  TAG_NAME = '@6:' || I$CS || '193:I';
  VAL = V$N21;
  SUSPEND;
  TAG_NAME = '@6:' || I$CS || '194:I';
  VAL = V$N22;
  SUSPEND;
  TAG_NAME = '@6:' || I$CS || '195:I';
  VAL = V$N23;
  SUSPEND;
  TAG_NAME = '@6:' || I$CS || '196:I';
  VAL = V$N24;
  SUSPEND;
  TAG_NAME = '@6:' || I$CS || '198:I';
  VAL = V$N25;
  SUSPEND;
  TAG_NAME = '@6:' || I$CS || '200:I';
  VAL = V$N26;
  SUSPEND;
  TAG_NAME = '@6:' || I$CS || '202:I';
  VAL = V$N27;
  SUSPEND;
  TAG_NAME = '@6:' || I$CS || '203:I';
  VAL = V$N28;
  SUSPEND;
  TAG_NAME = '@6:' || I$CS || '204:I';
  VAL = V$N29;
  SUSPEND;
  -- три строки вариантов дефектологов - пропускаем
  TAG_NAME = '@6:' || I$CS || '209:I';
  VAL = V$N30;
  SUSPEND;
  TAG_NAME = '@6:' || I$CS || '210:I';
  VAL = V$N31;
  SUSPEND;
  TAG_NAME = '@6:' || I$CS || '211:I';
  VAL = V$N32;
  SUSPEND;
  TAG_NAME = '@6:' || I$CS || '212:I';
  VAL = V$N33;
  SUSPEND;
  TAG_NAME = '@6:' || I$CS || '213:I';
  VAL = V$N34;
  SUSPEND;
  TAG_NAME = '@6:' || I$CS || '214:I';
  VAL = V$N35;
  SUSPEND;
  TAG_NAME = '@6:' || I$CS || '215:I';
  VAL = V$N36;
  SUSPEND;
  TAG_NAME = '@6:' || I$CS || '216:I';
  VAL = V$N37;
  SUSPEND;
  TAG_NAME = '@6:' || I$CS || '217:I';
  VAL = V$N38;
  SUSPEND;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE REPORT_OO1_R331 RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(100))
AS
begin

  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R331_COL(1, 'CG') INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R331_COL(2, 'DA') INTO :TAG_NAME, :VAL DO SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE REPORT_OO1_R331_COL (
    I$COL SMALLINT,
    I$CS VARCHAR(10))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(100))
AS
declare variable V$YEAR integer;
declare variable V$DATE date;
declare variable V$PERSON_ID bigint;
declare variable V$N_ALL integer;
declare variable V$N2 integer;
declare variable V$N3 integer;
declare variable V$N4 integer;
declare variable V$N5 integer;
declare variable V$N6 integer;
declare variable V$N7 integer;
declare variable V$N8 integer;
declare variable V$N9 integer;
declare variable V$N10 integer;
declare variable V$N11 integer;
declare variable V$N12 integer;
declare variable V$N13 integer;
declare variable V$N14 integer;
declare variable V$N15 integer;
declare variable V$N16 integer;
declare variable V$N17 integer;
declare variable V$N18 integer;
declare variable V$N19 integer;
declare variable V$N20 integer;
declare variable V$N21 integer;
declare variable V$N22 integer;
declare variable V$N23 integer;
declare variable V$N24 integer;
declare variable V$N25 integer;
declare variable V$N26 integer;
declare variable V$N27 integer;
declare variable V$N28 integer;
declare variable V$N29 integer;
declare variable V$N30 integer;
declare variable V$N31 integer;
declare variable V$N32 integer;
declare variable V$N33 integer;
declare variable V$N34 integer;
declare variable V$N35 integer;
begin

  V$YEAR = EXTRACT(YEAR FROM CURRENT_DATE);
  IF(EXTRACT(MONTH FROM CURRENT_DATE) < 9) THEN V$YEAR = V$YEAR - 1;
  V$DATE = '20.09.' || V$YEAR;

  V$N_ALL = 0;
  V$N2 = 0;
  V$N3 = 0;
  V$N4 = 0;
  V$N5 = 0;
  V$N6 = 0;
  V$N7 = 0;
  V$N8 = 0;
  V$N9 = 0;
  V$N10 = 0;
  V$N11 = 0;
  V$N12 = 0;
  V$N13 = 0;
  V$N14 = 0;
  V$N15 = 0;
  V$N16 = 0;
  V$N17 = 0;
  V$N18 = 0;
  V$N19 = 0;
  V$N20 = 0;
  V$N21 = 0;
  V$N22 = 0;
  V$N23 = 0;
  V$N24 = 0;
  V$N25 = 0;
  V$N26 = 0;
  V$N27 = 0;
  V$N28 = 0;
  V$N29 = 0;
  V$N30 = 0;
  V$N31 = 0;
  V$N32 = 0;
  V$N33 = 0;
  V$N34 = 0;
  V$N35 = 0;

  FOR
      SELECT D.SCHOLAR_ID
      FROM REPORT_D12 D
      JOIN VALL V239 ON V239.OBJ_ID = D.SCHOLAR_ID AND V239.PARAM_ID = 239 AND V239.IS_DEL = 0  -- пол
      WHERE (:I$COL = 1) OR -- все сотрудники
        (:I$COL = 2 AND V239.LISTVAL_ID = 182) -- < 25 жен
      INTO :V$PERSON_ID
  DO
  BEGIN

          -- общий счетчик
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (208, 12824))) THEN V$N_ALL = V$N_ALL + 1;
          -- руководители все
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (208, 12824) AND V.GROUP_ID = 55)) THEN V$N2 = V$N2 + 1;
          -- все педагоги
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (208, 12824) AND V.IS_EDU = 1)) THEN  V$N3 = V$N3 + 1;
          -- учителя
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (208, 12824) AND V.SUBGROUP_ID = 98)) THEN V$N4 = V$N4 + 1;
          -- учителя начального образования
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (208, 12824) AND V.POSITION_ID = 108)) THEN V$N5 = V$N5 + 1;
          -- учителя русского и литературы
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (208, 12824) AND V.POSITION_ID IN (112, 1260))) THEN V$N6 = V$N6 + 1;
          -- учителя языков народов России
          -- IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (208, 12824) AND V.POSITION_ID = 108)) THEN V$N7 = V$N7 + 1;
          -- история, экономика, право, обществознание
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (208, 12824) AND V.POSITION_ID IN (104, 1268, 1273, 1278, 1282))) THEN V$N8 = V$N8 + 1;
          -- информатика и ИКТ
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (208, 12824) AND V.POSITION_ID = 102)) THEN V$N9 = V$N9 + 1;
          -- физика
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (208, 12824) AND V.POSITION_ID = 115)) THEN V$N10 = V$N10 + 1;
          -- математика
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (208, 12824) AND V.POSITION_ID = 105)) THEN V$N11 = V$N11 + 1;
          -- химия
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (208, 12824) AND V.POSITION_ID = 118)) THEN V$N12 = V$N12 + 1;
          -- география
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (208, 12824) AND V.POSITION_ID = 101)) THEN V$N13 = V$N13 + 1;
          -- биология                                                                                                                                     
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (208, 12824) AND V.POSITION_ID = 100)) THEN V$N14 = V$N14 + 1;
          -- иностранные языки
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (208, 12824) AND V.POSITION_ID IN (99, 109, 117, 1264))) THEN V$N15 = V$N15 + 1;
          -- иностранные - английский
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (208, 12824) AND V.POSITION_ID = 99)) THEN V$N16 = V$N16 + 1;
          -- иностранные - немецкий
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (208, 12824) AND V.POSITION_ID = 109)) THEN V$N17 = V$N17 + 1;
          -- иностранные - французский
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (208, 12824) AND V.POSITION_ID = 117)) THEN V$N18 = V$N18 + 1;
          -- физкультура
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (208, 12824) AND V.POSITION_ID = 116)) THEN V$N19 = V$N19 + 1;
          -- труд и технология
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (208, 12824) AND V.POSITION_ID IN (114, 1286))) THEN V$N20 = V$N20 + 1;
          -- музыка и пение
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (208, 12824) AND V.POSITION_ID = 106)) THEN V$N21 = V$N21 + 1;
          -- изо и черчение
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (208, 12824) AND V.POSITION_ID IN (111, 3148))) THEN V$N22 = V$N22 + 1;
          -- обж
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (208, 12824) AND V.POSITION_ID = 110)) THEN V$N23 = V$N23 + 1;
          -- прочее
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (208, 12824) AND V.POSITION_ID IN (107, 1283, 1285, 122))) THEN V$N24 = V$N24 + 1;
          -- учитель-логопед
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (208, 12824) AND V.POSITION_ID = 119)) THEN V$N25 = V$N25 + 1;
          -- учитель-дефектолог - без раскрытия
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (208, 12824) AND V.POSITION_ID = 120)) THEN V$N26 = V$N26 + 1;
          -- социальный педагог
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (208, 12824) AND V.POSITION_ID = 1251)) THEN V$N27 = V$N27 + 1;
          -- педагог ДО + педагог-организатор
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (208, 12824) AND V.POSITION_ID IN (143, 144))) THEN V$N28 = V$N28 + 1;
          -- педагог-психолог
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (208, 12824) AND V.POSITION_ID = 140)) THEN V$N29 = V$N29 + 1;
          -- воспитатель
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (208, 12824) AND V.SUBGROUP_ID = 125)) THEN V$N30 = V$N30 + 1;
          -- мастер ПО
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (208, 12824) AND V.SUBGROUP_ID = 129)) THEN V$N31 = V$N31 + 1;
          -- тьютор
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (208, 12824) AND V.POSITION_ID = 1291)) THEN V$N32 = V$N32 + 1;
          -- прочие
          -- IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (208, 12824) AND V.POSITION_ID = 1291)) THEN V$N33 = V$N33 + 1;
          -- учебно-вспомогательный
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (208, 12824) AND V.SUBGROUP_ID = 1313)) THEN V$N34 = V$N34 + 1;
          -- иной персонал
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (208, 12824) AND V.SUBGROUP_ID = 1257)) THEN V$N35 = V$N35 + 1;

  END

  TAG_NAME = '@7:' || I$CS || '8:I';
  VAL = V$N_ALL;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '9:I';
  VAL = V$N2;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '10:I';
  VAL = V$N3;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '11:I';
  VAL = V$N4;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '12:I';
  VAL = V$N5;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '14:I';
  VAL = V$N6;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '15:I';
  VAL = V$N7;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '16:I';
  VAL = V$N8;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '17:I';
  VAL = V$N9;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '18:I';
  VAL = V$N10;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '19:I';
  VAL = V$N11;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '20:I';
  VAL = V$N12;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '21:I';
  VAL = V$N13;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '22:I';
  VAL = V$N14;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '23:I';
  VAL = V$N15;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '24:I';
  VAL = V$N16;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '26:I';
  VAL = V$N17;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '27:I';
  VAL = V$N18;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '28:I';
  VAL = V$N19;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '29:I';
  VAL = V$N20;
  SUSPEND;                      
  TAG_NAME = '@7:' || I$CS || '30:I';
  VAL = V$N21;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '31:I';
  VAL = V$N22;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '32:I';
  VAL = V$N23;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '33:I';
  VAL = V$N24;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '34:I';
  VAL = V$N25;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '35:I';
  VAL = V$N26;
  SUSPEND;
  -- три строки вариантов дефектологов - пропускаем
  TAG_NAME = '@7:' || I$CS || '41:I';
  VAL = V$N27;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '42:I';
  VAL = V$N28;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '33:I';
  VAL = V$N29;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '44:I';
  VAL = V$N30;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '45:I';
  VAL = V$N31;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '46:I';
  VAL = V$N32;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '47:I';
  VAL = V$N33;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '48:I';
  VAL = V$N34;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '49:I';
  VAL = V$N35;
  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE REPORT_OO1_R34 (
    I$OU_ID BIGINT)
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(100))
AS
declare variable S1 varchar(10);
declare variable S2 varchar(10);
declare variable NROW integer;
begin

  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R34_COL(:I$OU_ID, 1, 'AS') INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R34_COL(:I$OU_ID, 2, 'BB') INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R34_COL(:I$OU_ID, 3, 'BJ') INTO :TAG_NAME, :VAL DO SUSPEND;

  --FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R34_EA_COL(:I$OU_ID, 4, 'BV') INTO :TAG_NAME, :VAL DO SUSPEND;

  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R34_IN_COL(:I$OU_ID, 5, 'CI') INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R34_IN_COL(:I$OU_ID, 6, 'CQ') INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R34_IN_COL(:I$OU_ID, 7, 'DI') INTO :TAG_NAME, :VAL DO SUSPEND;

  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R34_OUT_COL(:I$OU_ID, 8, 'DT') INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R34_OUT_COL(:I$OU_ID, 9, 'EB') INTO :TAG_NAME, :VAL DO SUSPEND;

  -- Для 10-го столбца используем данные раздела 3.1, корректируем номера строк
  -- в исходном начиная с 12-й, тут с 93-й
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R31_COL(100, 'EN') INTO :TAG_NAME, :VAL DO
  BEGIN
    S1 = SUBSTRING(TAG_NAME FROM 1 FOR 5);
    NROW = SUBSTRING(TAG_NAME FROM 6 FOR 2);
    S2 = SUBSTRING(TAG_NAME FROM 8);
    NROW = NROW + 93 - 12;
    TAG_NAME = S1 || NROW || S2;
    SUSPEND;
  END

  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R34_COL(:I$OU_ID, 11, 'FB') INTO :TAG_NAME, :VAL DO SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE REPORT_OO1_R34_COL (
    I$OU_ID BIGINT,
    I$COL SMALLINT,
    I$CS VARCHAR(10))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(100))
AS
DECLARE VARIABLE V$YEAR INTEGER;
DECLARE VARIABLE V$DATE DATE;
DECLARE VARIABLE V$PERSON_ID BIGINT;
DECLARE VARIABLE R FLOAT;
DECLARE VARIABLE V$N_ALL FLOAT;
DECLARE VARIABLE V$N2 FLOAT;
DECLARE VARIABLE V$N3 FLOAT;
DECLARE VARIABLE V$N4 FLOAT;
DECLARE VARIABLE V$N5 FLOAT;
DECLARE VARIABLE V$N6 FLOAT;
DECLARE VARIABLE V$N7 FLOAT;
DECLARE VARIABLE V$N40 FLOAT;
DECLARE VARIABLE V$N41 FLOAT;
begin

  V$YEAR = EXTRACT(YEAR FROM CURRENT_DATE);
  IF(EXTRACT(MONTH FROM CURRENT_DATE) < 9) THEN V$YEAR = V$YEAR - 1;
  V$DATE = '20.09.' || V$YEAR;

  -- Текущая занятость ставок в ОУ

  V$N_ALL = 0;
  V$N2 = 0;
  V$N3 = 0;
  V$N4 = 0;
  V$N5 = 0;
  V$N6 = 0;
  V$N7 = 0;
  V$N40 = 0;
  V$N41 = 0;

  -- Идем по занятым ставкам - кроме столбца с штатным количеством
  IF(I$COL <> 1) THEN
  FOR
      -- Действующие
      SELECT L14.OBJ_ID
      FROM LINKS L14
      WHERE L14.PARENT_ID = :I$OU_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
      -- Уволенные
      UNION
      SELECT L14.OBJ_ID
      FROM LINKS L84
      JOIN LINKS L14 ON L14.PARENT_ID = L84.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
      WHERE L84.PARENT_ID = :I$OU_ID AND L84.OBJ_TYPE_ID = 84 AND L84.DATE_DEL IS NULL
      INTO :V$PERSON_ID
  DO
  BEGIN

      -- общий счетчик
      FOR SELECT RATE FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V
      WHERE (:I$COL <> 3 OR V.POSITION_TYPE IN (207, 1720))
      INTO :R
      DO V$N_ALL = V$N_ALL + R;
      -- руководители все
      FOR SELECT RATE FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V
      WHERE (:I$COL <> 3 OR V.POSITION_TYPE IN (207, 1720)) AND V.GROUP_ID = 55
      INTO :R
      DO V$N2 = V$N2 + R;
      -- директор
      FOR SELECT RATE FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V
      WHERE (:I$COL <> 3 OR V.POSITION_TYPE IN (207, 1720)) AND V.POSITION_ID = 64
      INTO :R
      DO V$N3 = V$N3 + R;
      -- зам директора
      FOR SELECT RATE FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V
      WHERE (:I$COL <> 3 OR V.POSITION_TYPE IN (207, 1720)) AND V.POSITION_ID = 80
      INTO :R
      DO V$N4 = V$N4 + R;
      -- рук филиала
      FOR SELECT RATE FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V
      WHERE (:I$COL <> 3 OR V.POSITION_TYPE IN (207, 1720)) AND V.POSITION_ID = 68
      INTO :R
      DO V$N5 = V$N5 + R;
      -- все педагоги
      FOR SELECT RATE FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V
      WHERE (:I$COL <> 3 OR V.POSITION_TYPE IN (207, 1720)) AND V.IS_EDU = 1
      INTO :R
      DO V$N6 = V$N6 + R;
      -- учителя
      FOR SELECT RATE FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V
      WHERE (:I$COL <> 3 OR V.POSITION_TYPE IN (207, 1720)) AND V.SUBGROUP_ID = 98
      INTO :R
      DO V$N7 = V$N7 + R;
      -- учебно-вспомогательный
      FOR SELECT RATE FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V
      WHERE (:I$COL <> 3 OR V.POSITION_TYPE IN (207, 1720)) AND V.SUBGROUP_ID = 1313
      INTO :R
      DO V$N40 = V$N40 + R;
      -- иной персонал
      FOR SELECT RATE FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V
      WHERE (:I$COL <> 3 OR V.POSITION_TYPE IN (207, 1720)) AND V.SUBGROUP_ID = 1257
      INTO :R
      DO V$N41 = V$N41 + R;

  END

  -- Постпроцессинг
  IF(I$COL IN (1, 11)) THEN
  BEGIN
      -- Тут только установленные ставки
      -- Для общего количества ставок складываем именные с учительскими
      V$N_ALL = (
          SELECT COALESCE(SUM(V62.VAL), 0)
          FROM LINKS L13
          JOIN VALF V62 ON V62.OBJ_ID = L13.OBJ_ID AND V62.PARAM_ID = 62 AND V62.IS_DEL = 0
          WHERE L13.PARENT_ID = :I$OU_ID AND L13.OBJ_TYPE_ID = 13 AND L13.DATE_DEL IS NULL
      ) + (
          SELECT COALESCE(V1342.VAL, 0) FROM VALF V1342 WHERE V1342.OBJ_ID = :I$OU_ID AND V1342.PARAM_ID = 1342 AND V1342.IS_DEL = 0
      ) - V$N_ALL;
      V$N2 = (
          SELECT COALESCE(SUM(V62.VAL), 0)
          FROM LINKS L13
          JOIN VALL V63 ON V63.OBJ_ID = L13.OBJ_ID AND V63.PARAM_ID = 63 AND V63.IS_DEL = 0 AND V63.LISTVAL_ID = 55
          JOIN VALF V62 ON V62.OBJ_ID = L13.OBJ_ID AND V62.PARAM_ID = 62 AND V62.IS_DEL = 0
          WHERE L13.PARENT_ID = :I$OU_ID AND L13.OBJ_TYPE_ID = 13 AND L13.DATE_DEL IS NULL
      ) - V$N2;
      V$N3 = (
          SELECT COALESCE(SUM(V62.VAL), 0)
          FROM LINKS L13
          JOIN VALL V64 ON V64.OBJ_ID = L13.OBJ_ID AND V64.PARAM_ID = 64 AND V64.IS_DEL = 0 AND V64.LISTVAL_ID = 56
          JOIN VALF V62 ON V62.OBJ_ID = L13.OBJ_ID AND V62.PARAM_ID = 62 AND V62.IS_DEL = 0
          WHERE L13.PARENT_ID = :I$OU_ID AND L13.OBJ_TYPE_ID = 13 AND L13.DATE_DEL IS NULL
      ) - V$N3;
      V$N4 = (
          SELECT COALESCE(SUM(V62.VAL), 0)
          FROM LINKS L13
          JOIN VALL V58 ON V58.OBJ_ID = L13.OBJ_ID AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0 AND V58.LISTVAL_ID = 80
          JOIN VALF V62 ON V62.OBJ_ID = L13.OBJ_ID AND V62.PARAM_ID = 62 AND V62.IS_DEL = 0
          WHERE L13.PARENT_ID = :I$OU_ID AND L13.OBJ_TYPE_ID = 13 AND L13.DATE_DEL IS NULL
      ) - V$N4;
      V$N5 = (
          SELECT COALESCE(SUM(V62.VAL), 0)
          FROM LINKS L13
          JOIN VALL V58 ON V58.OBJ_ID = L13.OBJ_ID AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0 AND V58.LISTVAL_ID = 68
          JOIN VALF V62 ON V62.OBJ_ID = L13.OBJ_ID AND V62.PARAM_ID = 62 AND V62.IS_DEL = 0
          WHERE L13.PARENT_ID = :I$OU_ID AND L13.OBJ_TYPE_ID = 13 AND L13.DATE_DEL IS NULL
      ) - V$N5;
      V$N6 = (
          SELECT COALESCE(SUM(V62.VAL), 0)
          FROM LINKS L13
          JOIN VALF V62 ON V62.OBJ_ID = L13.OBJ_ID AND V62.PARAM_ID = 62 AND V62.IS_DEL = 0
          LEFT JOIN DO_FUNC(L13.OBJ_ID, 400) T ON 1 = 1
          WHERE L13.PARENT_ID = :I$OU_ID AND L13.OBJ_TYPE_ID = 13 AND L13.DATE_DEL IS NULL AND T.SORT_ORDER = 2
      ) + (
          SELECT COALESCE(V1342.VAL, 0) FROM VALF V1342 WHERE V1342.OBJ_ID = :I$OU_ID AND V1342.PARAM_ID = 1342 AND V1342.IS_DEL = 0
      ) - V$N6;
      V$N7 = (SELECT COALESCE(V1342.VAL, 0) FROM VALF V1342 WHERE V1342.OBJ_ID = :I$OU_ID AND V1342.PARAM_ID = 1342 AND V1342.IS_DEL = 0) - V$N7;
      V$N40 = (
          SELECT COALESCE(SUM(V62.VAL), 0)
          FROM LINKS L13
          JOIN VALL V64 ON V64.OBJ_ID = L13.OBJ_ID AND V64.PARAM_ID = 64 AND V64.IS_DEL = 0 AND V64.LISTVAL_ID = 1313
          JOIN VALF V62 ON V62.OBJ_ID = L13.OBJ_ID AND V62.PARAM_ID = 62 AND V62.IS_DEL = 0
          WHERE L13.PARENT_ID = :I$OU_ID AND L13.OBJ_TYPE_ID = 13 AND L13.DATE_DEL IS NULL
      ) - V$N40;
      V$N41 = (
          SELECT COALESCE(SUM(V62.VAL), 0)
          FROM LINKS L13
          JOIN VALL V64 ON V64.OBJ_ID = L13.OBJ_ID AND V64.PARAM_ID = 64 AND V64.IS_DEL = 0 AND V64.LISTVAL_ID = 1257
          JOIN VALF V62 ON V62.OBJ_ID = L13.OBJ_ID AND V62.PARAM_ID = 62 AND V62.IS_DEL = 0
          WHERE L13.PARENT_ID = :I$OU_ID AND L13.OBJ_TYPE_ID = 13 AND L13.DATE_DEL IS NULL
      ) - V$N41;
  END

  TAG_NAME = '@7:' || I$CS || '93:F';
  VAL = V$N_ALL;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '94:F';
  VAL = V$N2;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '95:F';
  VAL = V$N3;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '97:F';
  VAL = V$N4;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '98:F';
  VAL = V$N5;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '99:F';
  VAL = V$N6;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '100:F';
  VAL = V$N7;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '138:F';
  VAL = V$N40;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '139:F';
  VAL = V$N41;
  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE REPORT_OO1_R34_EA_COL (
    I$OU_ID BIGINT,
    I$COL SMALLINT,
    I$CS VARCHAR(10))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(100))
AS
declare variable V$YEAR integer;
declare variable V$DATE date;
declare variable V$PERSON_ID bigint;
declare variable V$N_ALL integer;
declare variable V$N2 integer;
declare variable V$N3 integer;
declare variable V$N4 integer;
declare variable V$N5 integer;
declare variable V$N6 integer;
declare variable V$N7 integer;
declare variable V$N8 integer;
declare variable V$N9 integer;
declare variable V$N10 integer;
declare variable V$N11 integer;
declare variable V$N12 integer;
declare variable V$N13 integer;
declare variable V$N14 integer;
declare variable V$N15 integer;
declare variable V$N16 integer;
declare variable V$N17 integer;
declare variable V$N18 integer;
declare variable V$N19 integer;
declare variable V$N20 integer;
declare variable V$N21 integer;
declare variable V$N22 integer;
declare variable V$N23 integer;
declare variable V$N24 integer;
declare variable V$N25 integer;
declare variable V$N26 integer;
declare variable V$N27 integer;
declare variable V$N28 integer;
declare variable V$N29 integer;
declare variable V$N30 integer;
declare variable V$N31 integer;
declare variable V$N32 integer;
declare variable V$N33 integer;
declare variable V$N34 integer;
declare variable V$N35 integer;
declare variable V$N36 integer;
declare variable V$N37 integer;
declare variable V$N38 integer;
begin

  V$YEAR = EXTRACT(YEAR FROM CURRENT_DATE);
  IF(EXTRACT(MONTH FROM CURRENT_DATE) < 9) THEN V$YEAR = V$YEAR - 1;
  V$DATE = '20.09.' || V$YEAR;

  -- Количество сотрудников на начало учебного прошлого года
  V$DATE = DATEADD(-1 YEAR TO V$DATE);

  V$N_ALL = 0;
  V$N2 = 0;
  V$N3 = 0;
  V$N4 = 0;
  V$N5 = 0;
  V$N6 = 0;
  V$N7 = 0;
  V$N8 = 0;
  V$N9 = 0;
  V$N10 = 0;
  V$N11 = 0;
  V$N12 = 0;
  V$N13 = 0;
  V$N14 = 0;
  V$N15 = 0;
  V$N16 = 0;
  V$N17 = 0;
  V$N18 = 0;
  V$N19 = 0;
  V$N20 = 0;
  V$N21 = 0;
  V$N22 = 0;
  V$N23 = 0;
  V$N24 = 0;
  V$N25 = 0;
  V$N26 = 0;
  V$N27 = 0;
  V$N28 = 0;
  V$N29 = 0;
  V$N30 = 0;
  V$N31 = 0;
  V$N32 = 0;
  V$N33 = 0;
  V$N34 = 0;
  V$N35 = 0;
  V$N36 = 0;
  V$N37 = 0;
  V$N38 = 0;

  FOR
      -- Действующие
      SELECT L14.OBJ_ID
      FROM LINKS L14
      WHERE L14.PARENT_ID = :I$OU_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
      -- Уволенные
      UNION
      SELECT L14.OBJ_ID
      FROM LINKS L84
      JOIN LINKS L14 ON L14.PARENT_ID = L84.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
      WHERE L84.PARENT_ID = :I$OU_ID AND L84.OBJ_TYPE_ID = 84 AND L84.DATE_DEL IS NULL
      INTO :V$PERSON_ID
  DO
  BEGIN

          -- общий счетчик
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720))) THEN V$N_ALL = V$N_ALL + 1;
          -- руководители все
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.GROUP_ID = 55)) THEN V$N2 = V$N2 + 1;
          -- директор
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 64)) THEN V$N3 = V$N3 + 1;
          -- зам директора
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 80)) THEN V$N4 = V$N4 + 1;
          -- рук филиала
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 68)) THEN V$N5 = V$N5 + 1;
          -- все педагоги
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.IS_EDU = 1)) THEN  V$N6 = V$N6 + 1;
          -- учителя
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.SUBGROUP_ID = 98)) THEN V$N7 = V$N7 + 1;
          -- учителя начального образования
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 108)) THEN V$N8 = V$N8 + 1;
          -- учителя русского и литературы
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID IN (112, 1260))) THEN V$N9 = V$N9 + 1;
          -- учителя языков народов России
          -- IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 108)) THEN V$N10 = V$N10 + 1;
          -- история, экономика, право, обществознание
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID IN (104, 1268, 1273, 1278, 1282))) THEN V$N11 = V$N11 + 1;
          -- информатика и ИКТ
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 102)) THEN V$N12 = V$N12 + 1;
          -- физика
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 115)) THEN V$N13 = V$N13 + 1;
          -- математика
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 105)) THEN V$N14 = V$N14 + 1;
          -- химия
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 118)) THEN V$N15 = V$N15 + 1;
          -- география
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 101)) THEN V$N16 = V$N16 + 1;
          -- биология                                                                                                                                     
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 100)) THEN V$N17 = V$N17 + 1;
          -- иностранные языки
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID IN (99, 109, 117, 1264))) THEN V$N18 = V$N18 + 1;
          -- иностранные - английский
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 99)) THEN V$N19 = V$N19 + 1;
          -- иностранные - немецкий
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 109)) THEN V$N20 = V$N20 + 1;
          -- иностранные - французский
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 117)) THEN V$N21 = V$N21 + 1;
          -- физкультура
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 116)) THEN V$N22 = V$N22 + 1;
          -- труд и технология
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID IN (114, 1286))) THEN V$N23 = V$N23 + 1;
          -- музыка и пение
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 106)) THEN V$N24 = V$N24 + 1;
          -- изо и черчение
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID IN (111, 3148))) THEN V$N25 = V$N25 + 1;
          -- обж
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 110)) THEN V$N26 = V$N26 + 1;
          -- прочее
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID IN (107, 1283, 1285, 122))) THEN V$N27 = V$N27 + 1;
          -- учитель-логопед
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 119)) THEN V$N28 = V$N28 + 1;
          -- учитель-дефектолог - без раскрытия
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 120)) THEN V$N29 = V$N29 + 1;
          -- социальный педагог
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 1251)) THEN V$N30 = V$N30 + 1;
          -- педагог ДО + педагог-организатор
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID IN (143, 144))) THEN V$N31 = V$N31 + 1;
          -- педагог-психолог
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 140)) THEN V$N32 = V$N32 + 1;
          -- воспитатель
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.SUBGROUP_ID = 125)) THEN V$N33 = V$N33 + 1;
          -- мастер ПО
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.SUBGROUP_ID = 129)) THEN V$N34 = V$N34 + 1;
          -- тьютор
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 1291)) THEN V$N35 = V$N35 + 1;
          -- прочие
          -- IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 1291)) THEN V$N36 = V$N36 + 1;
          -- учебно-вспомогательный
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.SUBGROUP_ID = 1313)) THEN V$N37 = V$N37 + 1;
          -- иной персонал
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.SUBGROUP_ID = 1257)) THEN V$N38 = V$N38 + 1;

  END

  TAG_NAME = '@7:' || I$CS || '93:I';
  VAL = V$N_ALL;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '94:I';
  VAL = V$N2;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '95:I';
  VAL = V$N3;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '97:I';
  VAL = V$N4;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '98:I';
  VAL = V$N5;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '99:I';
  VAL = V$N6;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '100:I';
  VAL = V$N7;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '102:I';
  VAL = V$N8;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '104:I';
  VAL = V$N9;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '105:I';
  VAL = V$N10;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '106:I';
  VAL = V$N11;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '108:I';
  VAL = V$N12;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '109:I';
  VAL = V$N13;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '110:I';
  VAL = V$N14;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '111:I';
  VAL = V$N15;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '112:I';
  VAL = V$N16;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '113:I';
  VAL = V$N17;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '114:I';
  VAL = V$N18;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '115:I';
  VAL = V$N19;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '117:I';
  VAL = V$N20;
  SUSPEND;                      
  TAG_NAME = '@7:' || I$CS || '118:I';
  VAL = V$N21;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '119:I';
  VAL = V$N22;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '120:I';
  VAL = V$N23;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '121:I';
  VAL = V$N24;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '122:I';
  VAL = V$N25;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '123:I';
  VAL = V$N26;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '124:I';
  VAL = V$N27;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '125:I';
  VAL = V$N28;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '126:I';
  VAL = V$N29;
  SUSPEND;
  -- три строки вариантов дефектологов - пропускаем
  TAG_NAME = '@7:' || I$CS || '131:I';
  VAL = V$N30;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '132:I';
  VAL = V$N31;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '133:I';
  VAL = V$N32;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '134:I';
  VAL = V$N33;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '135:I';
  VAL = V$N34;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '136:I';
  VAL = V$N35;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '137:I';
  VAL = V$N36;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '138:I';
  VAL = V$N37;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '139:I';
  VAL = V$N38;
  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE REPORT_OO1_R34_IN_COL (
    I$OU_ID BIGINT,
    I$COL SMALLINT,
    I$CS VARCHAR(10))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(100))
AS
declare variable V$YEAR integer;
declare variable V$DATE date;
declare variable V$DATE_PREV date;
declare variable V$PERSON_ID bigint;
declare variable V$N_ALL integer;
declare variable V$N2 integer;
declare variable V$N3 integer;
declare variable V$N4 integer;
declare variable V$N5 integer;
declare variable V$N6 integer;
declare variable V$N7 integer;
declare variable V$N8 integer;
declare variable V$N9 integer;
declare variable V$N10 integer;
declare variable V$N11 integer;
declare variable V$N12 integer;
declare variable V$N13 integer;
declare variable V$N14 integer;
declare variable V$N15 integer;
declare variable V$N16 integer;
declare variable V$N17 integer;
declare variable V$N18 integer;
declare variable V$N19 integer;
declare variable V$N20 integer;
declare variable V$N21 integer;
declare variable V$N22 integer;
declare variable V$N23 integer;
declare variable V$N24 integer;
declare variable V$N25 integer;
declare variable V$N26 integer;
declare variable V$N27 integer;
declare variable V$N28 integer;
declare variable V$N29 integer;
declare variable V$N30 integer;
declare variable V$N31 integer;
declare variable V$N32 integer;
declare variable V$N33 integer;
declare variable V$N34 integer;
declare variable V$N35 integer;
declare variable V$N36 integer;
declare variable V$N37 integer;
declare variable V$N38 integer;
begin

  V$YEAR = EXTRACT(YEAR FROM CURRENT_DATE);
  IF(EXTRACT(MONTH FROM CURRENT_DATE) < 9) THEN V$YEAR = V$YEAR - 1;
  V$DATE = '20.09.' || V$YEAR;
  V$DATE_PREV = DATEADD(-1 YEAR TO V$DATE);

  -- Данные по приему персонала за прошлый учебный год

  V$N_ALL = 0;
  V$N2 = 0;
  V$N3 = 0;
  V$N4 = 0;
  V$N5 = 0;
  V$N6 = 0;
  V$N7 = 0;
  V$N8 = 0;
  V$N9 = 0;
  V$N10 = 0;
  V$N11 = 0;
  V$N12 = 0;
  V$N13 = 0;
  V$N14 = 0;
  V$N15 = 0;
  V$N16 = 0;
  V$N17 = 0;
  V$N18 = 0;
  V$N19 = 0;
  V$N20 = 0;
  V$N21 = 0;
  V$N22 = 0;
  V$N23 = 0;
  V$N24 = 0;
  V$N25 = 0;
  V$N26 = 0;
  V$N27 = 0;
  V$N28 = 0;
  V$N29 = 0;
  V$N30 = 0;
  V$N31 = 0;
  V$N32 = 0;
  V$N33 = 0;
  V$N34 = 0;
  V$N35 = 0;
  V$N36 = 0;
  V$N37 = 0;
  V$N38 = 0;

  -- Идем по всем назначениям на должность всех сотрудников, а не только действующих

  FOR
      -- Действующие
      SELECT L14.OBJ_ID
      FROM LINKS L14
      LEFT JOIN VALL V278 ON V278.OBJ_ID = L14.OBJ_ID AND V278.PARAM_ID = 278 AND V278.IS_DEL = 0 -- образование
      LEFT JOIN IS_YOUNG_EMPLOYEE(L14.OBJ_ID, DATEADD(-4 MONTH TO :V$DATE_PREV), :V$DATE_PREV) IY ON 1 = 1
      WHERE (L14.PARENT_ID = :I$OU_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL) AND (
        (:I$COL = 5) OR
        (:I$COL = 6 AND V278.LISTVAL_ID = 622 AND IY.VAL = 1) OR -- СПО
        (:I$COL = 7 AND V278.LISTVAL_ID IN (620, 3031, 3032) AND IY.VAL = 1) -- ВО
      )
      -- Уволенные
      UNION
      SELECT L14.OBJ_ID
      FROM LINKS L84
      JOIN LINKS L14 ON L14.PARENT_ID = L84.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
      LEFT JOIN VALL V278 ON V278.OBJ_ID = L14.OBJ_ID AND V278.PARAM_ID = 278 AND V278.IS_DEL = 0 -- образование
      LEFT JOIN IS_YOUNG_EMPLOYEE(L14.OBJ_ID, DATEADD(-4 MONTH TO :V$DATE_PREV), :V$DATE_PREV) IY ON 1 = 1
      WHERE (L84.PARENT_ID = :I$OU_ID AND L84.OBJ_TYPE_ID = 84 AND L84.DATE_DEL IS NULL) AND (
        (:I$COL = 5) OR
        (:I$COL = 6 AND V278.LISTVAL_ID = 622 AND IY.VAL = 1) OR -- выпускники с СПО
        (:I$COL = 7 AND V278.LISTVAL_ID IN (620, 3031, 3032) AND IY.VAL = 1) -- выпускники с ВО
      )
      INTO :V$PERSON_ID
  DO
  BEGIN

      -- общий счетчик
      IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_IN_VCS(:V$PERSON_ID, :V$DATE_PREV, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720))) THEN
          IF(NOT EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE_PREV) V WHERE V.POSITION_TYPE IN (207, 1720))) THEN V$N_ALL = V$N_ALL + 1;
      -- руководители все
      IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_IN_VCS(:V$PERSON_ID, :V$DATE_PREV, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.GROUP_ID = 55)) THEN
          IF(NOT EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE_PREV) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.GROUP_ID = 55)) THEN V$N2 = V$N2 + 1;
      -- директор
      IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_IN_VCS(:V$PERSON_ID, :V$DATE_PREV, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 64)) THEN
          IF(NOT EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE_PREV) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 64)) THEN V$N3 = V$N3 + 1;
      -- зам директора
      IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_IN_VCS(:V$PERSON_ID, :V$DATE_PREV, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 80)) THEN
          IF(NOT EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE_PREV) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 80)) THEN V$N4 = V$N4 + 1;
      -- рук филиала
      IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_IN_VCS(:V$PERSON_ID, :V$DATE_PREV, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 68)) THEN
          IF(NOT EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE_PREV) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 68)) THEN V$N5 = V$N5 + 1;
      -- все педагоги
      IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_IN_VCS(:V$PERSON_ID, :V$DATE_PREV, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.IS_EDU = 1)) THEN  V$N6 = V$N6 + 1;
      -- учителя
      IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_IN_VCS(:V$PERSON_ID, :V$DATE_PREV, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.SUBGROUP_ID = 98)) THEN
          IF(NOT EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE_PREV) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.SUBGROUP_ID = 98)) THEN V$N7 = V$N7 + 1;
      -- учителя начального образования
      IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_IN_VCS(:V$PERSON_ID, :V$DATE_PREV, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 108)) THEN
          IF(NOT EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE_PREV) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 108)) THEN V$N8 = V$N8 + 1;
      -- учителя русского и литературы
      IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_IN_VCS(:V$PERSON_ID, :V$DATE_PREV, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID IN (112, 1260))) THEN
          IF(NOT EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE_PREV) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID IN (112, 1260))) THEN V$N9 = V$N9 + 1;
      -- учителя языков народов России
      -- IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_IN_VCS(:V$PERSON_ID, :V$DATE_PREV, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 108)) THEN V$N10 = V$N10 + 1;
      -- история, экономика, право, обществознание
      IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_IN_VCS(:V$PERSON_ID, :V$DATE_PREV, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID IN (104, 1268, 1273, 1278, 1282))) THEN
          IF(NOT EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE_PREV) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID IN (104, 1268, 1273, 1278, 1282))) THEN V$N11 = V$N11 + 1;
      -- информатика и ИКТ
      IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_IN_VCS(:V$PERSON_ID, :V$DATE_PREV, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 102)) THEN
          IF(NOT EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE_PREV) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 102)) THEN V$N12 = V$N12 + 1;
      -- физика
      IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_IN_VCS(:V$PERSON_ID, :V$DATE_PREV, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 115)) THEN
          IF(NOT EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE_PREV) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 115)) THEN V$N13 = V$N13 + 1;
      -- математика
      IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_IN_VCS(:V$PERSON_ID, :V$DATE_PREV, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 105)) THEN
          IF(NOT EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE_PREV) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 105)) THEN V$N14 = V$N14 + 1;
      -- химия
      IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_IN_VCS(:V$PERSON_ID, :V$DATE_PREV, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 118)) THEN
          IF(NOT EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE_PREV) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 118)) THEN V$N15 = V$N15 + 1;
      -- география
      IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_IN_VCS(:V$PERSON_ID, :V$DATE_PREV, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 101)) THEN
          IF(NOT EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE_PREV) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 101)) THEN V$N16 = V$N16 + 1;
      -- биология
      IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_IN_VCS(:V$PERSON_ID, :V$DATE_PREV, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 100)) THEN
          IF(NOT EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE_PREV) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 100)) THEN V$N17 = V$N17 + 1;
      -- иностранные языки
      IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_IN_VCS(:V$PERSON_ID, :V$DATE_PREV, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID IN (99, 109, 117, 1264))) THEN
          IF(NOT EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE_PREV) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID IN (99, 109, 117, 1264))) THEN V$N18 = V$N18 + 1;
      -- иностранные - английский
      IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_IN_VCS(:V$PERSON_ID, :V$DATE_PREV, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 99)) THEN
          IF(NOT EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE_PREV) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 99)) THEN V$N19 = V$N19 + 1;
      -- иностранные - немецкий
      IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_IN_VCS(:V$PERSON_ID, :V$DATE_PREV, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 109)) THEN
          IF(NOT EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE_PREV) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 109)) THEN V$N20 = V$N20 + 1;
      -- иностранные - французский
      IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_IN_VCS(:V$PERSON_ID, :V$DATE_PREV, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 117)) THEN
          IF(NOT EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE_PREV) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 117)) THEN V$N21 = V$N21 + 1;
      -- физкультура
      IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_IN_VCS(:V$PERSON_ID, :V$DATE_PREV, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 116)) THEN
          IF(NOT EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE_PREV) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 116)) THEN V$N22 = V$N22 + 1;
      -- труд и технология
      IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_IN_VCS(:V$PERSON_ID, :V$DATE_PREV, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID IN (114, 1286))) THEN
          IF(NOT EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE_PREV) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID IN (114, 1286))) THEN V$N23 = V$N23 + 1;
      -- музыка и пение
      IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_IN_VCS(:V$PERSON_ID, :V$DATE_PREV, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 106)) THEN
          IF(NOT EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE_PREV) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 106)) THEN V$N24 = V$N24 + 1;
      -- изо и черчение
      IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_IN_VCS(:V$PERSON_ID, :V$DATE_PREV, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID IN (111, 3148))) THEN
          IF(NOT EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE_PREV) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID IN (111, 3148))) THEN V$N25 = V$N25 + 1;
      -- обж
      IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_IN_VCS(:V$PERSON_ID, :V$DATE_PREV, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 110)) THEN
          IF(NOT EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE_PREV) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 110)) THEN V$N26 = V$N26 + 1;
      -- прочее
      IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_IN_VCS(:V$PERSON_ID, :V$DATE_PREV, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID IN (107, 1283, 1285, 122))) THEN
          IF(NOT EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE_PREV) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID IN (107, 1283, 1285, 122))) THEN V$N27 = V$N27 + 1;
      -- учитель-логопед
      IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_IN_VCS(:V$PERSON_ID, :V$DATE_PREV, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 119)) THEN
          IF(NOT EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE_PREV) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 119)) THEN V$N28 = V$N28 + 1;
      -- учитель-дефектолог - без раскрытия
      IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_IN_VCS(:V$PERSON_ID, :V$DATE_PREV, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 120)) THEN
          IF(NOT EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE_PREV) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 120)) THEN V$N29 = V$N29 + 1;
      -- социальный педагог
      IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_IN_VCS(:V$PERSON_ID, :V$DATE_PREV, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 1251)) THEN
          IF(NOT EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE_PREV) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 1251)) THEN V$N30 = V$N30 + 1;
      -- педагог ДО + педагог-организатор
      IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_IN_VCS(:V$PERSON_ID, :V$DATE_PREV, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID IN (143, 144))) THEN
          IF(NOT EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE_PREV) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID IN (143, 144))) THEN V$N31 = V$N31 + 1;
      -- педагог-психолог
      IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_IN_VCS(:V$PERSON_ID, :V$DATE_PREV, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 140)) THEN
          IF(NOT EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE_PREV) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 140)) THEN V$N32 = V$N32 + 1;
      -- воспитатель
      IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_IN_VCS(:V$PERSON_ID, :V$DATE_PREV, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.SUBGROUP_ID = 125)) THEN
          IF(NOT EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE_PREV) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.SUBGROUP_ID = 125)) THEN V$N33 = V$N33 + 1;
      -- мастер ПО
      IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_IN_VCS(:V$PERSON_ID, :V$DATE_PREV, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.SUBGROUP_ID = 129)) THEN
          IF(NOT EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE_PREV) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.SUBGROUP_ID = 129)) THEN V$N34 = V$N34 + 1;
      -- тьютор
      IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_IN_VCS(:V$PERSON_ID, :V$DATE_PREV, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 1291)) THEN
          IF(NOT EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE_PREV) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 1291)) THEN V$N35 = V$N35 + 1;
      -- прочие
      -- IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_IN_VCS(:V$PERSON_ID, :V$DATE_PREV, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 1291)) THEN V$N36 = V$N36 + 1;
      -- учебно-вспомогательный
      IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_IN_VCS(:V$PERSON_ID, :V$DATE_PREV, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.SUBGROUP_ID = 1313)) THEN
          IF(NOT EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE_PREV) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.SUBGROUP_ID = 1313)) THEN V$N37 = V$N37 + 1;
      -- иной персонал
      IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_IN_VCS(:V$PERSON_ID, :V$DATE_PREV, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.SUBGROUP_ID = 1257)) THEN
          IF(NOT EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE_PREV) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.SUBGROUP_ID = 1257)) THEN V$N38 = V$N38 + 1;

  END

  TAG_NAME = '@7:' || I$CS || '93:I';
  VAL = V$N_ALL;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '94:I';
  VAL = V$N2;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '95:I';
  VAL = V$N3;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '97:I';
  VAL = V$N4;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '98:I';
  VAL = V$N5;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '99:I';
  VAL = V$N6;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '100:I';
  VAL = V$N7;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '102:I';
  VAL = V$N8;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '104:I';
  VAL = V$N9;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '105:I';
  VAL = V$N10;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '106:I';
  VAL = V$N11;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '108:I';
  VAL = V$N12;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '109:I';
  VAL = V$N13;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '110:I';
  VAL = V$N14;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '111:I';
  VAL = V$N15;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '112:I';
  VAL = V$N16;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '113:I';
  VAL = V$N17;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '114:I';
  VAL = V$N18;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '115:I';
  VAL = V$N19;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '116:I';
  VAL = V$N20;
  SUSPEND;                      
  TAG_NAME = '@7:' || I$CS || '118:I';
  VAL = V$N21;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '119:I';
  VAL = V$N22;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '120:I';
  VAL = V$N23;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '121:I';
  VAL = V$N24;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '122:I';
  VAL = V$N25;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '123:I';
  VAL = V$N26;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '124:I';
  VAL = V$N27;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '125:I';
  VAL = V$N28;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '126:I';
  VAL = V$N29;
  SUSPEND;
  -- три строки вариантов дефектологов - пропускаем
  TAG_NAME = '@7:' || I$CS || '131:I';
  VAL = V$N30;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '132:I';
  VAL = V$N31;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '133:I';
  VAL = V$N32;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '134:I';
  VAL = V$N33;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '135:I';
  VAL = V$N34;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '136:I';
  VAL = V$N35;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '137:I';
  VAL = V$N36;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '138:I';
  VAL = V$N37;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '139:I';
  VAL = V$N38;
  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE REPORT_OO1_R34_OUT_COL (
    I$OU_ID BIGINT,
    I$COL SMALLINT,
    I$CS VARCHAR(10))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(100))
AS
declare variable V$YEAR integer;
declare variable V$DATE date;
declare variable V$DATE_PREV date;
declare variable V$PERSON_ID bigint;
declare variable V$N_ALL integer;
declare variable V$N2 integer;
declare variable V$N3 integer;
declare variable V$N4 integer;
declare variable V$N5 integer;
declare variable V$N6 integer;
declare variable V$N7 integer;
declare variable V$N8 integer;
declare variable V$N9 integer;
declare variable V$N10 integer;
declare variable V$N11 integer;
declare variable V$N12 integer;
declare variable V$N13 integer;
declare variable V$N14 integer;
declare variable V$N15 integer;
declare variable V$N16 integer;
declare variable V$N17 integer;
declare variable V$N18 integer;
declare variable V$N19 integer;
declare variable V$N20 integer;
declare variable V$N21 integer;
declare variable V$N22 integer;
declare variable V$N23 integer;
declare variable V$N24 integer;
declare variable V$N25 integer;
declare variable V$N26 integer;
declare variable V$N27 integer;
declare variable V$N28 integer;
declare variable V$N29 integer;
declare variable V$N30 integer;
declare variable V$N31 integer;
declare variable V$N32 integer;
declare variable V$N33 integer;
declare variable V$N34 integer;
declare variable V$N35 integer;
declare variable V$N36 integer;
declare variable V$N37 integer;
declare variable V$N38 integer;
begin

  V$YEAR = EXTRACT(YEAR FROM CURRENT_DATE);
  IF(EXTRACT(MONTH FROM CURRENT_DATE) < 9) THEN V$YEAR = V$YEAR - 1;
  V$DATE = '20.09.' || V$YEAR;
  V$DATE_PREV = DATEADD(-1 YEAR TO V$DATE);

  -- Данные по выбытию персонала за прошлый учебный год

  V$N_ALL = 0;
  V$N2 = 0;
  V$N3 = 0;
  V$N4 = 0;
  V$N5 = 0;
  V$N6 = 0;
  V$N7 = 0;
  V$N8 = 0;
  V$N9 = 0;
  V$N10 = 0;
  V$N11 = 0;
  V$N12 = 0;
  V$N13 = 0;
  V$N14 = 0;
  V$N15 = 0;
  V$N16 = 0;
  V$N17 = 0;
  V$N18 = 0;
  V$N19 = 0;
  V$N20 = 0;
  V$N21 = 0;
  V$N22 = 0;
  V$N23 = 0;
  V$N24 = 0;
  V$N25 = 0;
  V$N26 = 0;
  V$N27 = 0;
  V$N28 = 0;
  V$N29 = 0;
  V$N30 = 0;
  V$N31 = 0;
  V$N32 = 0;
  V$N33 = 0;
  V$N34 = 0;
  V$N35 = 0;
  V$N36 = 0;
  V$N37 = 0;
  V$N38 = 0;

  -- Идем по всем назначениям на должность всех сотрудников, а не только действующих

  FOR
      -- Действующие
      SELECT L14.OBJ_ID
      FROM LINKS L14
      WHERE L14.PARENT_ID = :I$OU_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
      -- Уволенные
      UNION
      SELECT L14.OBJ_ID
      FROM LINKS L84
      JOIN LINKS L14 ON L14.PARENT_ID = L84.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
      WHERE L84.PARENT_ID = :I$OU_ID AND L84.OBJ_TYPE_ID = 84 AND L84.DATE_DEL IS NULL
      INTO :V$PERSON_ID
  DO
  BEGIN

      -- общий счетчик
      IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_OUT_VCS(:V$PERSON_ID, :V$DATE_PREV, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND (:I$COL = 8 OR V.REASON_ID = 2142))) THEN
          IF(NOT EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720))) THEN V$N_ALL = V$N_ALL + 1;
      -- руководители все
      IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_OUT_VCS(:V$PERSON_ID, :V$DATE_PREV, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND (:I$COL = 8 OR V.REASON_ID = 2142) AND V.GROUP_ID = 55)) THEN
          IF(NOT EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.GROUP_ID = 55)) THEN V$N2 = V$N2 + 1;
      -- директор
      IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_OUT_VCS(:V$PERSON_ID, :V$DATE_PREV, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND (:I$COL = 8 OR V.REASON_ID = 2142) AND V.POSITION_ID = 64)) THEN
          IF(NOT EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 64)) THEN V$N3 = V$N3 + 1;
      -- зам директора
      IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_OUT_VCS(:V$PERSON_ID, :V$DATE_PREV, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND (:I$COL = 8 OR V.REASON_ID = 2142) AND V.POSITION_ID = 80)) THEN
          IF(NOT EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 80)) THEN V$N4 = V$N4 + 1;
      -- рук филиала
      IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_OUT_VCS(:V$PERSON_ID, :V$DATE_PREV, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND (:I$COL = 8 OR V.REASON_ID = 2142) AND V.POSITION_ID = 68)) THEN
          IF(NOT EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 68)) THEN V$N5 = V$N5 + 1;
      -- все педагоги
      IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_OUT_VCS(:V$PERSON_ID, :V$DATE_PREV, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND (:I$COL = 8 OR V.REASON_ID = 2142) AND V.IS_EDU = 1)) THEN V$N6 = V$N6 + 1;
      -- учителя
      IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_OUT_VCS(:V$PERSON_ID, :V$DATE_PREV, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND (:I$COL = 8 OR V.REASON_ID = 2142) AND V.SUBGROUP_ID = 98)) THEN
          IF(NOT EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.SUBGROUP_ID = 98)) THEN V$N7 = V$N7 + 1;
      -- учителя начального образования
      IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_OUT_VCS(:V$PERSON_ID, :V$DATE_PREV, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND (:I$COL = 8 OR V.REASON_ID = 2142) AND V.POSITION_ID = 108)) THEN
          IF(NOT EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 108)) THEN V$N8 = V$N8 + 1;
      -- учителя русского и литературы
      IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_OUT_VCS(:V$PERSON_ID, :V$DATE_PREV, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND (:I$COL = 8 OR V.REASON_ID = 2142) AND V.POSITION_ID IN (112, 1260))) THEN
          IF(NOT EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID IN (112, 1260))) THEN V$N9 = V$N9 + 1;
      -- учителя языков народов России
      -- IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_OUT_VCS(:V$PERSON_ID, :V$DATE_PREV, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND (:I$COL = 8 OR V.REASON_ID = 2142) AND V.POSITION_ID = 108)) THEN V$N10 = V$N10 + 1;
      -- история, экономика, право, обществознание
      IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_OUT_VCS(:V$PERSON_ID, :V$DATE_PREV, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND (:I$COL = 8 OR V.REASON_ID = 2142) AND V.POSITION_ID IN (104, 1268, 1273, 1278, 1282))) THEN
          IF(NOT EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID IN (104, 1268, 1273, 1278, 1282))) THEN V$N11 = V$N11 + 1;
      -- информатика и ИКТ
      IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_OUT_VCS(:V$PERSON_ID, :V$DATE_PREV, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND (:I$COL = 8 OR V.REASON_ID = 2142) AND V.POSITION_ID = 102)) THEN
          IF(NOT EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 102)) THEN V$N12 = V$N12 + 1;
      -- физика
      IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_OUT_VCS(:V$PERSON_ID, :V$DATE_PREV, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND (:I$COL = 8 OR V.REASON_ID = 2142) AND V.POSITION_ID = 115)) THEN
          IF(NOT EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 115)) THEN V$N13 = V$N13 + 1;
      -- математика
      IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_OUT_VCS(:V$PERSON_ID, :V$DATE_PREV, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND (:I$COL = 8 OR V.REASON_ID = 2142) AND V.POSITION_ID = 105)) THEN
          IF(NOT EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 105)) THEN V$N14 = V$N14 + 1;
      -- химия
      IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_OUT_VCS(:V$PERSON_ID, :V$DATE_PREV, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND (:I$COL = 8 OR V.REASON_ID = 2142) AND V.POSITION_ID = 118)) THEN
          IF(NOT EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 118)) THEN V$N15 = V$N15 + 1;
      -- география
      IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_OUT_VCS(:V$PERSON_ID, :V$DATE_PREV, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND (:I$COL = 8 OR V.REASON_ID = 2142) AND V.POSITION_ID = 101)) THEN
          IF(NOT EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 101)) THEN V$N16 = V$N16 + 1;
      -- биология
      IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_OUT_VCS(:V$PERSON_ID, :V$DATE_PREV, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND (:I$COL = 8 OR V.REASON_ID = 2142) AND V.POSITION_ID = 100)) THEN
          IF(NOT EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 100)) THEN V$N17 = V$N17 + 1;
      -- иностранные языки
      IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_OUT_VCS(:V$PERSON_ID, :V$DATE_PREV, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND (:I$COL = 8 OR V.REASON_ID = 2142) AND V.POSITION_ID IN (99, 109, 117, 1264))) THEN
          IF(NOT EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID IN (99, 109, 117, 1264))) THEN V$N18 = V$N18 + 1;
      -- иностранные - английский
      IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_OUT_VCS(:V$PERSON_ID, :V$DATE_PREV, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND (:I$COL = 8 OR V.REASON_ID = 2142) AND V.POSITION_ID = 99)) THEN
          IF(NOT EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 99)) THEN V$N19 = V$N19 + 1;
      -- иностранные - немецкий
      IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_OUT_VCS(:V$PERSON_ID, :V$DATE_PREV, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND (:I$COL = 8 OR V.REASON_ID = 2142) AND V.POSITION_ID = 109)) THEN
          IF(NOT EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 109)) THEN V$N20 = V$N20 + 1;
      -- иностранные - французский
      IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_OUT_VCS(:V$PERSON_ID, :V$DATE_PREV, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND (:I$COL = 8 OR V.REASON_ID = 2142) AND V.POSITION_ID = 117)) THEN
          IF(NOT EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 117)) THEN V$N21 = V$N21 + 1;
      -- физкультура
      IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_OUT_VCS(:V$PERSON_ID, :V$DATE_PREV, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND (:I$COL = 8 OR V.REASON_ID = 2142) AND V.POSITION_ID = 116)) THEN
          IF(NOT EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 116)) THEN V$N22 = V$N22 + 1;
      -- труд и технология
      IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_OUT_VCS(:V$PERSON_ID, :V$DATE_PREV, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND (:I$COL = 8 OR V.REASON_ID = 2142) AND V.POSITION_ID IN (114, 1286))) THEN
          IF(NOT EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID IN (114, 1286))) THEN V$N23 = V$N23 + 1;
      -- музыка и пение
      IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_OUT_VCS(:V$PERSON_ID, :V$DATE_PREV, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND (:I$COL = 8 OR V.REASON_ID = 2142) AND V.POSITION_ID = 106)) THEN
          IF(NOT EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 106)) THEN V$N24 = V$N24 + 1;
      -- изо и черчение
      IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_OUT_VCS(:V$PERSON_ID, :V$DATE_PREV, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND (:I$COL = 8 OR V.REASON_ID = 2142) AND V.POSITION_ID IN (111, 3148))) THEN
          IF(NOT EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID IN (111, 3148))) THEN V$N25 = V$N25 + 1;
      -- обж
      IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_OUT_VCS(:V$PERSON_ID, :V$DATE_PREV, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND (:I$COL = 8 OR V.REASON_ID = 2142) AND V.POSITION_ID = 110)) THEN
          IF(NOT EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 110)) THEN V$N26 = V$N26 + 1;
      -- прочее
      IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_OUT_VCS(:V$PERSON_ID, :V$DATE_PREV, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND (:I$COL = 8 OR V.REASON_ID = 2142) AND V.POSITION_ID IN (107, 1283, 1285, 122))) THEN
          IF(NOT EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID IN (107, 1283, 1285, 122))) THEN V$N27 = V$N27 + 1;
      -- учитель-логопед
      IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_OUT_VCS(:V$PERSON_ID, :V$DATE_PREV, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND (:I$COL = 8 OR V.REASON_ID = 2142) AND V.POSITION_ID = 119)) THEN
          IF(NOT EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 119)) THEN V$N28 = V$N28 + 1;
      -- учитель-дефектолог - без раскрытия
      IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_OUT_VCS(:V$PERSON_ID, :V$DATE_PREV, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND (:I$COL = 8 OR V.REASON_ID = 2142) AND V.POSITION_ID = 120)) THEN
          IF(NOT EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 120)) THEN V$N29 = V$N29 + 1;
      -- социальный педагог
      IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_OUT_VCS(:V$PERSON_ID, :V$DATE_PREV, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND (:I$COL = 8 OR V.REASON_ID = 2142) AND V.POSITION_ID = 1251)) THEN
          IF(NOT EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 1251)) THEN V$N30 = V$N30 + 1;
      -- педагог ДО + педагог-организатор
      IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_OUT_VCS(:V$PERSON_ID, :V$DATE_PREV, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND (:I$COL = 8 OR V.REASON_ID = 2142) AND V.POSITION_ID IN (143, 144))) THEN
          IF(NOT EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID IN (143, 144))) THEN V$N31 = V$N31 + 1;
      -- педагог-психолог
      IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_OUT_VCS(:V$PERSON_ID, :V$DATE_PREV, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND (:I$COL = 8 OR V.REASON_ID = 2142) AND V.POSITION_ID = 140)) THEN
          IF(NOT EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 140)) THEN V$N32 = V$N32 + 1;
      -- воспитатель
      IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_OUT_VCS(:V$PERSON_ID, :V$DATE_PREV, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND (:I$COL = 8 OR V.REASON_ID = 2142) AND V.SUBGROUP_ID = 125)) THEN
          IF(NOT EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.SUBGROUP_ID = 125)) THEN V$N33 = V$N33 + 1;
      -- мастер ПО
      IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_OUT_VCS(:V$PERSON_ID, :V$DATE_PREV, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND (:I$COL = 8 OR V.REASON_ID = 2142) AND V.SUBGROUP_ID = 129)) THEN
          IF(NOT EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.SUBGROUP_ID = 129)) THEN V$N34 = V$N34 + 1;
      -- тьютор
      IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_OUT_VCS(:V$PERSON_ID, :V$DATE_PREV, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND (:I$COL = 8 OR V.REASON_ID = 2142) AND V.POSITION_ID = 1291)) THEN
          IF(NOT EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 1291)) THEN V$N35 = V$N35 + 1;
      -- прочие
      -- IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_OUT_VCS(:V$PERSON_ID, :V$DATE_PREV, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND (:I$COL = 8 OR V.REASON_ID = 2142) AND V.POSITION_ID = 1291)) THEN V$N36 = V$N36 + 1;
      -- учебно-вспомогательный
      IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_OUT_VCS(:V$PERSON_ID, :V$DATE_PREV, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND (:I$COL = 8 OR V.REASON_ID = 2142) AND V.SUBGROUP_ID = 1313)) THEN
          IF(NOT EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.SUBGROUP_ID = 1313)) THEN V$N37 = V$N37 + 1;
      -- иной персонал
      IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_OUT_VCS(:V$PERSON_ID, :V$DATE_PREV, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND (:I$COL = 8 OR V.REASON_ID = 2142) AND V.SUBGROUP_ID = 1257)) THEN
          IF(NOT EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.SUBGROUP_ID = 1257)) THEN V$N38 = V$N38 + 1;

  END

  TAG_NAME = '@7:' || I$CS || '93:I';
  VAL = V$N_ALL;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '94:I';
  VAL = V$N2;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '95:I';
  VAL = V$N3;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '97:I';
  VAL = V$N4;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '98:I';
  VAL = V$N5;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '99:I';
  VAL = V$N6;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '100:I';
  VAL = V$N7;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '102:I';
  VAL = V$N8;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '104:I';
  VAL = V$N9;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '105:I';
  VAL = V$N10;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '106:I';
  VAL = V$N11;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '108:I';
  VAL = V$N12;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '109:I';
  VAL = V$N13;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '110:I';
  VAL = V$N14;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '111:I';
  VAL = V$N15;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '112:I';
  VAL = V$N16;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '113:I';
  VAL = V$N17;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '114:I';
  VAL = V$N18;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '115:I';
  VAL = V$N19;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '116:I';
  VAL = V$N20;
  SUSPEND;                      
  TAG_NAME = '@7:' || I$CS || '118:I';
  VAL = V$N21;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '119:I';
  VAL = V$N22;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '120:I';
  VAL = V$N23;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '121:I';
  VAL = V$N24;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '122:I';
  VAL = V$N25;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '123:I';
  VAL = V$N26;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '124:I';
  VAL = V$N27;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '125:I';
  VAL = V$N28;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '126:I';
  VAL = V$N29;
  SUSPEND;
  -- три строки вариантов дефектологов - пропускаем
  TAG_NAME = '@7:' || I$CS || '131:I';
  VAL = V$N30;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '132:I';
  VAL = V$N31;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '133:I';
  VAL = V$N32;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '134:I';
  VAL = V$N33;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '135:I';
  VAL = V$N34;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '136:I';
  VAL = V$N35;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '137:I';
  VAL = V$N36;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '138:I';
  VAL = V$N37;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '139:I';
  VAL = V$N38;
  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE REPORT_OO1_R35 RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(100))
AS
begin

  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R35_COL(1, 'AI') INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R35_COL(2, 'AV') INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R35_COL(3, 'BA') INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R35_COL(4, 'BH') INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R35_COL(5, 'BM') INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R35_COL(6, 'BT') INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R35_COL(7, 'BY') INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R35_COL(8, 'CF') INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R35_COL(9, 'CK') INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R35_COL(10, 'CR') INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R35_COL(11, 'CW') INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R35_COL(12, 'DD') INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R35_COL(13, 'DI') INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R35_COL(14, 'DP') INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R35_COL(15, 'DU') INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R35_COL(16, 'EB') INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R35_COL(17, 'EG') INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R35_COL(18, 'EN') INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R35_COL(19, 'ES') INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R35_COL(20, 'EZ') INTO :TAG_NAME, :VAL DO SUSPEND;
  FOR SELECT TAG_NAME, VAL FROM REPORT_OO1_R35_COL(21, 'FE') INTO :TAG_NAME, :VAL DO SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE REPORT_OO1_R35_COL (
    I$COL SMALLINT,
    I$CS VARCHAR(10))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(100))
AS
declare variable V$YEAR integer;
declare variable V$DATE date;
declare variable V$PERSON_ID bigint;
declare variable V$N_ALL integer;
declare variable V$N2 integer;
declare variable V$N3 integer;
declare variable V$N4 integer;
declare variable V$N5 integer;
declare variable V$N6 integer;
declare variable V$N7 integer;
declare variable V$N8 integer;
declare variable V$N9 integer;
declare variable V$N10 integer;
declare variable V$N11 integer;
declare variable V$N12 integer;
declare variable V$N13 integer;
declare variable V$N14 integer;
declare variable V$N15 integer;
declare variable V$N16 integer;
declare variable V$N17 integer;
declare variable V$N18 integer;
declare variable V$N19 integer;
declare variable V$N20 integer;
declare variable V$N21 integer;
declare variable V$N22 integer;
declare variable V$N23 integer;
declare variable V$N24 integer;
declare variable V$N25 integer;
declare variable V$N26 integer;
declare variable V$N27 integer;
declare variable V$N28 integer;
declare variable V$N29 integer;
declare variable V$N30 integer;
declare variable V$N31 integer;
declare variable V$N32 integer;
declare variable V$N33 integer;
declare variable V$N34 integer;
declare variable V$N35 integer;
declare variable V$N36 integer;
declare variable V$N37 integer;
declare variable V$N38 integer;
begin

  V$YEAR = EXTRACT(YEAR FROM CURRENT_DATE);
  IF(EXTRACT(MONTH FROM CURRENT_DATE) < 9) THEN V$YEAR = V$YEAR - 1;
  V$DATE = '20.09.' || V$YEAR;

  V$N_ALL = 0;
  V$N2 = 0;
  V$N3 = 0;
  V$N4 = 0;
  V$N5 = 0;
  V$N6 = 0;
  V$N7 = 0;
  V$N8 = 0;
  V$N9 = 0;
  V$N10 = 0;
  V$N11 = 0;
  V$N12 = 0;
  V$N13 = 0;
  V$N14 = 0;
  V$N15 = 0;
  V$N16 = 0;
  V$N17 = 0;
  V$N18 = 0;
  V$N19 = 0;
  V$N20 = 0;
  V$N21 = 0;
  V$N22 = 0;
  V$N23 = 0;
  V$N24 = 0;
  V$N25 = 0;
  V$N26 = 0;
  V$N27 = 0;
  V$N28 = 0;
  V$N29 = 0;
  V$N30 = 0;
  V$N31 = 0;
  V$N32 = 0;
  V$N33 = 0;
  V$N34 = 0;
  V$N35 = 0;
  V$N36 = 0;
  V$N37 = 0;
  V$N38 = 0;

  FOR
      SELECT D.SCHOLAR_ID
      FROM REPORT_D12 D
      JOIN VALL V239 ON V239.OBJ_ID = D.SCHOLAR_ID AND V239.PARAM_ID = 239 AND V239.IS_DEL = 0  -- пол
      WHERE (:I$COL = 1) OR -- все сотрудники
        (:I$COL = 2 AND D.C3 < 25) OR -- < 25
        (:I$COL = 3 AND D.C3 > 25 AND V239.LISTVAL_ID = 182) OR -- < 25 жен
        (:I$COL = 4 AND D.C3 >= 25 AND D.C3 <= 29) OR -- 25-29
        (:I$COL = 5 AND D.C3 >= 25 AND D.C3 <= 29 AND V239.LISTVAL_ID = 182) OR -- 25-29 жен
        (:I$COL = 6 AND D.C3 >= 30 AND D.C3 <= 34) OR -- 30-34
        (:I$COL = 7 AND D.C3 >= 30 AND D.C3 <= 34 AND V239.LISTVAL_ID = 182) OR -- 30-34 жен
        (:I$COL = 8 AND D.C3 >= 35 AND D.C3 <= 39) OR -- 35-39
        (:I$COL = 9 AND D.C3 >= 35 AND D.C3 <= 39 AND V239.LISTVAL_ID = 182) OR -- 35-39 жен
        (:I$COL = 10 AND D.C3 >= 40 AND D.C3 <= 44) OR -- 40-44
        (:I$COL = 11 AND D.C3 >= 40 AND D.C3 <= 44 AND V239.LISTVAL_ID = 182) OR -- 40-44 жен
        (:I$COL = 12 AND D.C3 >= 45 AND D.C3 <= 49) OR -- 45-49
        (:I$COL = 13 AND D.C3 >= 45 AND D.C3 <= 49 AND V239.LISTVAL_ID = 182) OR -- 45-49 жен
        (:I$COL = 14 AND D.C3 >= 50 AND D.C3 <= 54) OR -- 50-54
        (:I$COL = 15 AND D.C3 >= 50 AND D.C3 <= 54 AND V239.LISTVAL_ID = 182) OR -- 50-54 жен
        (:I$COL = 16 AND D.C3 >= 55 AND D.C3 <= 59) OR -- 55-59
        (:I$COL = 17 AND D.C3 >= 55 AND D.C3 <= 59 AND V239.LISTVAL_ID = 182) OR -- 55-59 жен
        (:I$COL = 18 AND D.C3 >= 60 AND D.C3 <= 64) OR -- 60-64
        (:I$COL = 19 AND D.C3 >= 60 AND D.C3 <= 64 AND V239.LISTVAL_ID = 182) OR -- 60-64 жен
        (:I$COL = 20 AND D.C3 >= 65) OR -- 65+
        (:I$COL = 21 AND D.C3 >= 65 AND V239.LISTVAL_ID = 182) -- 65+ жен
      INTO :V$PERSON_ID
  DO
  BEGIN

          -- общий счетчик
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720))) THEN V$N_ALL = V$N_ALL + 1;
          -- руководители все
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.GROUP_ID = 55)) THEN V$N2 = V$N2 + 1;
          -- директор
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 64)) THEN V$N3 = V$N3 + 1;
          -- зам директора
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 80)) THEN V$N4 = V$N4 + 1;
          -- рук филиала
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 68)) THEN V$N5 = V$N5 + 1;
          -- все педагоги
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.IS_EDU = 1)) THEN  V$N6 = V$N6 + 1;
          -- учителя
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.SUBGROUP_ID = 98)) THEN V$N7 = V$N7 + 1;
          -- учителя начального образования
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 108)) THEN V$N8 = V$N8 + 1;
          -- учителя русского и литературы
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID IN (112, 1260))) THEN V$N9 = V$N9 + 1;
          -- учителя языков народов России
          -- IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 108)) THEN V$N10 = V$N10 + 1;
          -- история, экономика, право, обществознание
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID IN (104, 1268, 1273, 1278, 1282))) THEN V$N11 = V$N11 + 1;
          -- информатика и ИКТ
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 102)) THEN V$N12 = V$N12 + 1;
          -- физика
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 115)) THEN V$N13 = V$N13 + 1;
          -- математика
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 105)) THEN V$N14 = V$N14 + 1;
          -- химия
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 118)) THEN V$N15 = V$N15 + 1;
          -- география
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 101)) THEN V$N16 = V$N16 + 1;
          -- биология                                                                                                                                     
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 100)) THEN V$N17 = V$N17 + 1;
          -- иностранные языки
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID IN (99, 109, 117, 1264))) THEN V$N18 = V$N18 + 1;
          -- иностранные - английский
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 99)) THEN V$N19 = V$N19 + 1;
          -- иностранные - немецкий
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 109)) THEN V$N20 = V$N20 + 1;
          -- иностранные - французский
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 117)) THEN V$N21 = V$N21 + 1;
          -- физкультура
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 116)) THEN V$N22 = V$N22 + 1;
          -- труд и технология
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID IN (114, 1286))) THEN V$N23 = V$N23 + 1;
          -- музыка и пение
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 106)) THEN V$N24 = V$N24 + 1;
          -- изо и черчение
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID IN (111, 3148))) THEN V$N25 = V$N25 + 1;
          -- обж
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 110)) THEN V$N26 = V$N26 + 1;
          -- прочее
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID IN (107, 1283, 1285, 122))) THEN V$N27 = V$N27 + 1;
          -- учитель-логопед
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 119)) THEN V$N28 = V$N28 + 1;
          -- учитель-дефектолог - без раскрытия
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 120)) THEN V$N29 = V$N29 + 1;
          -- социальный педагог
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 1251)) THEN V$N30 = V$N30 + 1;
          -- педагог ДО + педагог-организатор
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID IN (143, 144))) THEN V$N31 = V$N31 + 1;
          -- педагог-психолог
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 140)) THEN V$N32 = V$N32 + 1;
          -- воспитатель
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.SUBGROUP_ID = 125)) THEN V$N33 = V$N33 + 1;
          -- мастер ПО
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.SUBGROUP_ID = 129)) THEN V$N34 = V$N34 + 1;
          -- тьютор
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 1291)) THEN V$N35 = V$N35 + 1;
          -- прочие
          -- IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.POSITION_ID = 1291)) THEN V$N36 = V$N36 + 1;
          -- учебно-вспомогательный
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.SUBGROUP_ID = 1313)) THEN V$N37 = V$N37 + 1;
          -- иной персонал
          IF(EXISTS(SELECT FIRST 1 1 FROM REPORT_OO1_VCS(:V$PERSON_ID, :V$DATE) V WHERE V.POSITION_TYPE IN (207, 1720) AND V.SUBGROUP_ID = 1257)) THEN V$N38 = V$N38 + 1;

  END

  TAG_NAME = '@7:' || I$CS || '159:I';
  VAL = V$N_ALL;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '160:I';
  VAL = V$N2;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '161:I';
  VAL = V$N3;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '163:I';
  VAL = V$N4;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '164:I';
  VAL = V$N5;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '165:I';
  VAL = V$N6;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '166:I';
  VAL = V$N7;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '167:I';
  VAL = V$N8;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '170:I';
  VAL = V$N9;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '174:I';
  VAL = V$N10;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '174:I';
  VAL = V$N11;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '176:I';
  VAL = V$N12;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '177:I';
  VAL = V$N13;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '178:I';
  VAL = V$N14;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '179:I';
  VAL = V$N15;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '180:I';
  VAL = V$N16;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '181:I';
  VAL = V$N17;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '182:I';
  VAL = V$N18;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '183:I';
  VAL = V$N19;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '185:I';
  VAL = V$N20;
  SUSPEND;                      
  TAG_NAME = '@7:' || I$CS || '186:I';
  VAL = V$N21;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '187:I';
  VAL = V$N22;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '188:I';
  VAL = V$N23;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '190:I';
  VAL = V$N24;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '191:I';
  VAL = V$N25;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '193:I';
  VAL = V$N26;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '195:I';
  VAL = V$N27;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '196:I';
  VAL = V$N28;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '197:I';
  VAL = V$N29;
  SUSPEND;
  -- три строки вариантов дефектологов - пропускаем
  TAG_NAME = '@7:' || I$CS || '202:I';
  VAL = V$N30;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '203:I';
  VAL = V$N31;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '204:I';
  VAL = V$N32;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '205:I';
  VAL = V$N33;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '206:I';
  VAL = V$N34;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '207:I';
  VAL = V$N35;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '208:I';
  VAL = V$N36;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '209:I';
  VAL = V$N37;
  SUSPEND;
  TAG_NAME = '@7:' || I$CS || '211:I';
  VAL = V$N38;
  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE REPORT_OO1_VCS (
    I$PERSON_ID BIGINT,
    I$DATE DATE)
RETURNS (
    GROUP_ID BIGINT,
    SUBGROUP_ID BIGINT,
    POSITION_ID BIGINT,
    POSITION_TYPE BIGINT,
    IS_EDU SMALLINT,
    RATE DOUBLE PRECISION)
AS
begin

  FOR
      SELECT V63.LISTVAL_ID, V64.LISTVAL_ID, V58.LISTVAL_ID, V71.VAL, V587.LISTVAL_ID, IIF(T.SORT_ORDER = 2, 1, 0)
      FROM LINKS L15
      JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0 AND V73.VAL <= :I$DATE
      LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
      JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
      JOIN VALL V63 ON V63.OBJ_ID = LP13.PARENT_ID AND V63.PARAM_ID = 63 AND V63.IS_DEL = 0
      JOIN VALL V64 ON V64.OBJ_ID = LP13.PARENT_ID AND V64.PARAM_ID = 64 AND V64.IS_DEL = 0
      JOIN VALL V58 ON V58.OBJ_ID = LP13.PARENT_ID AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0
      JOIN VALF V71 ON V71.OBJ_ID = L15.OBJ_ID AND V71.PARAM_ID = 71 AND V71.IS_DEL = 0
      JOIN VALL V587 ON V587.OBJ_ID = L15.OBJ_ID AND V587.PARAM_ID = 587 AND V587.IS_DEL = 0
      LEFT JOIN DO_FUNC(LP13.PARENT_ID, 400) T ON 1 = 1
      WHERE L15.PARENT_ID = :I$PERSON_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL AND (V74.VAL IS NULL OR V74.VAL >= :I$DATE)
      INTO :GROUP_ID, :SUBGROUP_ID, :POSITION_ID, :RATE, :POSITION_TYPE, :IS_EDU
  DO
  BEGIN
      SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE REPORT_PROGNOSE_STUDENTS (
    OBJ_ID BIGINT,
    KO_FILTER VARCHAR(100) = null)
RETURNS (
    VAL VARCHAR(6000))
AS
declare variable V$OBJ_TYPE bigint;
declare variable OU_TYPE char(1);
declare variable N_TOTAL integer;
declare variable N integer;
declare variable N_CROSS integer;
declare variable V$STAGE_LV bigint;
declare variable V$PREV_STAGE_LV bigint;
declare variable G integer;
declare variable SCHOOL_ID bigint;
declare variable S varchar(1000);
declare variable G_TOTAL integer;
declare variable G_GRADUATE integer;
declare variable G_TOTAL1 integer;
declare variable G_TOTAL9 integer;
declare variable R integer;
begin
  VAL = '<!DOCTYPE html>';
  VAL = VAL || '<html lang="ru">';
  VAL = VAL || '<head>';
  VAL = VAL || '<meta charset="utf-8" />';

  VAL = VAL || '<style>';
  VAL = VAL || 'html { font-family: Tahoma, Verdana, Arial;';
  VAL = VAL || 'font-size: 10pt; ';
  VAL = VAL || '} ';
  VAL = VAL || '.title1 { font-size: 150%;';
  VAL = VAL || 'padding: 8px;';
  VAL = VAL || 'margin-bottom: 10px;';
  VAL = VAL || 'font-weight: bold;';
  VAL = VAL || 'color: #1B5E20;';
  VAL = VAL || '} ';
  VAL = VAL || '.title2 { font-size: 120%;';
  VAL = VAL || 'padding: 8px;';
  VAL = VAL || 'margin-bottom: 20px;';
  VAL = VAL || 'font-weight: bold;';
  VAL = VAL || 'color: #827717;';
  VAL = VAL || '} ';
  VAL = VAL || '.details {';
  VAL = VAL || 'width: 100%;';
  VAL = VAL || 'border: 2px solid #e0e0e0;';
  VAL = VAL || 'border-collapse: collapse;';
  VAL = VAL || '} ';
  VAL = VAL || '.details tr td {';
  VAL = VAL || 'padding: 2px 4px;';
  VAL = VAL || 'border: 1px solid #e0e0e0;';
  VAL = VAL || 'text-align: left;';
  VAL = VAL || '} ';
  VAL = VAL || '.odd td {';
  VAL = VAL || 'background-color: #f7f7f7;';
  VAL = VAL || '} ';
  VAL = VAL || '.thd {';
  VAL = VAL || 'background-color: #F0F4C3;';
  VAL = VAL || '} ';
  VAL = VAL || '</style>';

  VAL = VAL || '</head>';
  VAL = VAL || '<body style="padding: 8px;">';

  -- Заголовок отчета
  SELECT TYPE_ID
  FROM OBJECTS
  WHERE OBJ_ID = :OBJ_ID
  INTO :V$OBJ_TYPE;

  IF(V$OBJ_TYPE = 2) THEN VAL = VAL || '<div class="title1">Предварительный расчет контингента на 01.09</div>';
  ELSE IF(V$OBJ_TYPE = 111) THEN
  BEGIN
    VAL = VAL || '<div class="title1">Предварительный расчет контингента на 01.09 (' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:OBJ_ID)) || ')</div>';
  END
  ELSE EXIT;

  IF(KO_FILTER = 'Да') THEN VAL = VAL || '<div class="title2">Только ОООД подчинения КО</div>';

  -- Заголовок таблиц
  VAL = VAL || '<table class="details" cellspacing="0" cellpadding="0">';
  SUSPEND;
  VAL = '';

  SELECT STATUS FROM OU_LICENCE_TYPE INTO :OU_TYPE;

  -- Школа
  IF(V$OBJ_TYPE = 2 AND OU_TYPE = 'O') THEN
  BEGIN

    VAL = VAL || '<tr class="thd">';
    VAL = VAL || '<td style="width: 50%">Этап</td>';
    VAL = VAL || '<td style="width: 50%">Количество обучающихся</td>';
    VAL = VAL || '</tr>';

    G = 0;
    V$PREV_STAGE_LV = NULL;
    N_TOTAL = 0;

    WHILE(G <= 12) DO
    BEGIN

      IF(G = 0) THEN V$STAGE_LV = 12765; ELSE V$STAGE_LV = 37 + G - 1;

      SELECT COUNT(*)
      FROM LINKS L77
      JOIN LINKS L290 ON L290.PARENT_ID = L77.OBJ_ID AND L290.OBJ_TYPE_ID = 290 AND L290.DATE_DEL IS NULL
      JOIN VALL V2346 ON V2346.OBJ_ID = L290.OBJ_ID AND V2346.PARAM_ID = 2346 AND V2346.IS_DEL = 0 AND V2346.LISTVAL_ID = :V$STAGE_LV
      JOIN LINKS L10 ON L10.PARENT_ID = L290.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      WHERE L77.PARENT_ID = :OBJ_ID AND L77.OBJ_TYPE_ID = 77 AND L77.DATE_DEL IS NULL
      INTO :N;

      SELECT COUNT(*)
      FROM LINKS L7
      JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
      JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0 AND V49.LISTVAL_ID = :V$PREV_STAGE_LV
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
      LEFT JOIN VALL V2388 ON V2388.OBJ_ID = L9.OBJ_ID AND V2388.PARAM_ID = 2388 AND V2388.IS_DEL = 0
      JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      WHERE L7.PARENT_ID = :OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
        AND (V2388.LISTVAL_ID IS NULL OR (:V$PREV_STAGE_LV NOT IN (47, 48)) OR (:V$PREV_STAGE_LV IN (47, 48) AND V2388.LISTVAL_ID = 11217))
      INTO :N_CROSS;

      VAL = VAL || '<tr>';
      VAL = VAL || '<td>' || G || ' параллель</td>';
      VAL = VAL || '<td>' || (N + N_CROSS) || '</td>';
      VAL = VAL || '</tr>';

      G = G + 1;
      V$PREV_STAGE_LV = V$STAGE_LV;
      N_TOTAL = N_TOTAL + N + N_CROSS;
    END

    VAL = VAL || '<tr class="thd">';
    VAL = VAL || '<td>Всего</td>';
    VAL = VAL || '<td>' || N_TOTAL || '</td>';
    VAL = VAL || '</tr>';

    N = 0;
    SELECT COUNT(*)
    FROM LINKS L7
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0 AND V49.LISTVAL_ID IN (47, 48)
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
    JOIN VALL V2388 ON V2388.OBJ_ID = L9.OBJ_ID AND V2388.PARAM_ID = 2388 AND V2388.IS_DEL = 0 AND V2388.LISTVAL_ID <> 11217
    JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    WHERE L7.PARENT_ID = :OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    INTO :N;

    VAL = VAL || '<tr>';
    VAL = VAL || '<td>Количество выпускников</td>';
    VAL = VAL || '<td>' || N || '</td>';
    VAL = VAL || '</tr>';

  END
  -- ДОУ
  ELSE IF(V$OBJ_TYPE = 2 AND OU_TYPE = 'D') THEN
  BEGIN

    V$PREV_STAGE_LV = NULL;
    N_TOTAL = 0;

    VAL = VAL || '<tr class="thd">';
    VAL = VAL || '<td style="width: 50%">Этап</td>';
    VAL = VAL || '<td style="width: 50%">Количество воспитанников</td>';
    VAL = VAL || '</tr>';

    FOR
       SELECT LV.LISTVAL_ID, R.VAL
       FROM LISTVALS LV
       JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
       WHERE LV.LIST_ID = 25 AND LV.IS_DEL = 0 AND LV.PARENT_ID = 2140
       ORDER BY LV.COST
       INTO :V$STAGE_LV, :S
    DO
    BEGIN

      SELECT COUNT(*)
      FROM LINKS L77
      JOIN LINKS L290 ON L290.PARENT_ID = L77.OBJ_ID AND L290.OBJ_TYPE_ID = 290 AND L290.DATE_DEL IS NULL
      JOIN VALL V2346 ON V2346.OBJ_ID = L290.OBJ_ID AND V2346.PARAM_ID = 2346 AND V2346.IS_DEL = 0 AND V2346.LISTVAL_ID = :V$STAGE_LV
      JOIN LINKS L10 ON L10.PARENT_ID = L290.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      WHERE L77.PARENT_ID = :OBJ_ID AND L77.OBJ_TYPE_ID = 77 AND L77.DATE_DEL IS NULL
      INTO :N;

      -- Для разновозрастных групп перевод из группы того же типа
      IF(V$STAGE_LV IN (33, 3262)) THEN V$PREV_STAGE_LV = V$STAGE_LV;
      -- Для второй младшей группы корректируем предыдущий этап
      IF(V$STAGE_LV = 3261) THEN V$PREV_STAGE_LV = 32;

      SELECT COUNT(*)
      FROM LINKS L7
      JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
      JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0 AND V49.LISTVAL_ID = :V$PREV_STAGE_LV
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
      JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      WHERE L7.PARENT_ID = :OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
      INTO :N_CROSS;

      VAL = VAL || '<tr>';
      VAL = VAL || '<td style="width: 50%">' || S || '</td>';
      VAL = VAL || '<td style="width: 50%">' || (N + N_CROSS) || '</td>';
      VAL = VAL || '</tr>';

      V$PREV_STAGE_LV = V$STAGE_LV;
      N_TOTAL = N_TOTAL + N + N_CROSS;

      IF(CHAR_LENGTH(VAL) > 4000) THEN
      BEGIN
        SUSPEND;
        VAL = '';
      END

    END

    VAL = VAL || '<tr class="thd">';
    VAL = VAL || '<td>Всего</td>';
    VAL = VAL || '<td>' || N_TOTAL || '</td>';
    VAL = VAL || '</tr>';

    N = 0;
    SELECT COUNT(*)
    FROM LINKS L7
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0 AND V49.LISTVAL_ID = 36
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
    JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    WHERE L7.PARENT_ID = :OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    INTO :N;

    VAL = VAL || '<tr>';
    VAL = VAL || '<td>Количество выпускников</td>';
    VAL = VAL || '<td>' || N || '</td>';
    VAL = VAL || '</tr>';

  END
  -- Школы, район
  ELSE IF(V$OBJ_TYPE = 111 AND OU_TYPE = 'O') THEN
  BEGIN

    VAL = VAL || '<tr class="thd">';
    VAL = VAL || '<td style="width: 40%">ОООД</td>';
    VAL = VAL || '<td style="width: 15%">Количество обучающихся (всего)</td>';
    VAL = VAL || '<td style="width: 15%">Из них количество первоклассников</td>';
    VAL = VAL || '<td style="width: 15%">Из них количество 9-классников</td>';
    VAL = VAL || '<td style="width: 15%">Количество выпускников</td>';
    VAL = VAL || '</tr>';

    R = 0;
    G_TOTAL = 0;
    G_TOTAL1 = 0;
    G_GRADUATE = 0;
    G_TOTAL9 = 0;

    FOR
        SELECT L2.OBJ_ID, C.CAPTION
        FROM LINKS L2
        LEFT JOIN VALS V6 ON V6.OBJ_ID = L2.OBJ_ID AND V6.PARAM_ID = 6 AND V6.IS_DEL = 0
        LEFT JOIN VALL V8 ON V8.OBJ_ID = L2.OBJ_ID AND V8.PARAM_ID = 8 AND V8.IS_DEL = 0
        LEFT JOIN OBJECT_CAPTION_GET(L2.OBJ_ID) C ON 1 = 1
        WHERE L2.PARENT_ID = :OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
          AND (:KO_FILTER IS NULL OR :KO_FILTER = 'Нет' OR
            (:KO_FILTER = 'Да' AND (V6.VAL IS NULL OR V6.VAL = 'Комитет по образованию Санкт-Петербурга') AND (V8.LISTVAL_ID IS NULL OR V8.LISTVAL_ID <> 5404))
          )
        ORDER BY 2
        INTO :SCHOOL_ID, :S
    DO
    BEGIN

      VAL = VAL || '<tr class="';
      IF(R = 0) THEN VAL = VAL || 'odd'; ELSE VAL = VAL || 'even';
      IF(R = 0) THEN R = 1; ELSE R = 0;
      VAL = VAL || '">';

      VAL = VAL || '<td>' || S || '</td>';

      -- Сумма зачисляемых
      SELECT COUNT(*)
      FROM LINKS L77
      JOIN LINKS L290 ON L290.PARENT_ID = L77.OBJ_ID AND L290.OBJ_TYPE_ID = 290 AND L290.DATE_DEL IS NULL
      JOIN VALL V2346 ON V2346.OBJ_ID = L290.OBJ_ID AND V2346.PARAM_ID = 2346 AND V2346.IS_DEL = 0
      JOIN LINKS L10 ON L10.PARENT_ID = L290.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      WHERE L77.PARENT_ID = :SCHOOL_ID AND L77.OBJ_TYPE_ID = 77 AND L77.DATE_DEL IS NULL
      INTO :N;

      -- Сумма переходящих, кроме выпускных классов 11 и 12 параллелей
      SELECT COUNT(*)
      FROM LINKS L7
      JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
      JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
      LEFT JOIN VALL V2388 ON V2388.OBJ_ID = L9.OBJ_ID AND V2388.PARAM_ID = 2388 AND V2388.IS_DEL = 0
      JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      WHERE L7.PARENT_ID = :SCHOOL_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
        AND (V2388.LISTVAL_ID IS NULL OR (V49.LISTVAL_ID NOT IN (47, 48)) OR (V49.LISTVAL_ID IN (47, 48) AND V2388.LISTVAL_ID = 11217))
      INTO :N_CROSS;

      VAL = VAL || '<td>' || (N + N_CROSS) || '</td>';
      G_TOTAL = G_TOTAL + N + N_CROSS;

      -- Сумма зачисляемых в 1 класс
      SELECT COUNT(*)
      FROM LINKS L77
      JOIN LINKS L290 ON L290.PARENT_ID = L77.OBJ_ID AND L290.OBJ_TYPE_ID = 290 AND L290.DATE_DEL IS NULL
      JOIN VALL V2346 ON V2346.OBJ_ID = L290.OBJ_ID AND V2346.PARAM_ID = 2346 AND V2346.IS_DEL = 0 AND V2346.LISTVAL_ID = 37
      JOIN LINKS L10 ON L10.PARENT_ID = L290.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      WHERE L77.PARENT_ID = :SCHOOL_ID AND L77.OBJ_TYPE_ID = 77 AND L77.DATE_DEL IS NULL
      INTO :N;

      -- Сумма учеников 0-й параллели
      SELECT COUNT(*)
      FROM LINKS L7
      JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
      JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0 AND V49.LISTVAL_ID = 12765
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
      JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      WHERE L7.PARENT_ID = :SCHOOL_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
      INTO :N_CROSS;

      VAL = VAL || '<td>' || (N + N_CROSS) || '</td>';
      G_TOTAL1 = G_TOTAL1 + N + N_CROSS;

      SELECT COUNT(*)
      FROM LINKS L7
      JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
      JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0 AND V49.LISTVAL_ID = 45
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
      JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      WHERE L7.PARENT_ID = :SCHOOL_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
      INTO :N;

      VAL = VAL || '<td>' || N || '</td>';
      G_TOTAL9 = G_TOTAL9 + N;

      SELECT COUNT(*)
      FROM LINKS L7
      JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
      JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0 AND V49.LISTVAL_ID IN (47, 48)
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
      JOIN VALL V2388 ON V2388.OBJ_ID = L9.OBJ_ID AND V2388.PARAM_ID = 2388 AND V2388.IS_DEL = 0 AND V2388.LISTVAL_ID <> 11217
      JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      WHERE L7.PARENT_ID = :SCHOOL_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
      INTO :N;

      VAL = VAL || '<td>' || N || '</td>';
      G_GRADUATE = G_GRADUATE + N;

      VAL = VAL || '</tr>';

    END

    VAL = VAL || '<tr class="thd">';
    VAL = VAL || '<td>Всего</td>';
    VAL = VAL || '<td>' || G_TOTAL || '</td>';
    VAL = VAL || '<td>' || G_TOTAL1 || '</td>';
    VAL = VAL || '<td>' || G_TOTAL9 || '</td>';
    VAL = VAL || '<td>' || G_GRADUATE || '</td>';
    VAL = VAL || '</tr>';

    IF(CHAR_LENGTH(VAL) > 4000) THEN
    BEGIN
      SUSPEND;
      VAL = '';
    END

  END
  -- ДОУ, район
  ELSE IF(V$OBJ_TYPE = 111 AND OU_TYPE = 'D') THEN
  BEGIN

    VAL = VAL || '<tr>';
    VAL = VAL || '<td style="width: 50%">ОООД</td>';
    VAL = VAL || '<td style="width: 25%">Количество воспитанников</td>';
    VAL = VAL || '<td style="width: 25%">Количество выпускников</td>';
    VAL = VAL || '</tr>';

    R = 0;
    G_TOTAL = 0;
    G_TOTAL1 = 0;
    G_GRADUATE = 0;

    FOR
        SELECT L2.OBJ_ID, C.CAPTION
        FROM LINKS L2
        LEFT JOIN VALS V6 ON V6.OBJ_ID = L2.OBJ_ID AND V6.PARAM_ID = 6 AND V6.IS_DEL = 0
        LEFT JOIN VALL V8 ON V8.OBJ_ID = L2.OBJ_ID AND V8.PARAM_ID = 8 AND V8.IS_DEL = 0
        LEFT JOIN OBJECT_CAPTION_GET(L2.OBJ_ID) C ON 1 = 1
        WHERE L2.PARENT_ID = :OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
          AND (:KO_FILTER IS NULL OR :KO_FILTER = 'Нет' OR
            (:KO_FILTER = 'Да' AND (V6.VAL IS NULL OR V6.VAL = 'Комитет по образованию Санкт-Петербурга') AND (V8.LISTVAL_ID IS NULL OR V8.LISTVAL_ID <> 5404))
          )
        ORDER BY 2
        INTO :SCHOOL_ID, :S
    DO
    BEGIN

      VAL = VAL || '<tr class="';
      IF(R = 0) THEN VAL = VAL || 'odd'; ELSE VAL = VAL || 'even';
      IF(R = 0) THEN R = 1; ELSE R = 0;
      VAL = VAL || '">';

      VAL = VAL || '<td>' || S || '</td>';

      -- Сумма зачисляемых
      SELECT COUNT(*)
      FROM LINKS L77
      JOIN LINKS L290 ON L290.PARENT_ID = L77.OBJ_ID AND L290.OBJ_TYPE_ID = 290 AND L290.DATE_DEL IS NULL
      JOIN VALL V2346 ON V2346.OBJ_ID = L290.OBJ_ID AND V2346.PARAM_ID = 2346 AND V2346.IS_DEL = 0
      JOIN LINKS L10 ON L10.PARENT_ID = L290.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      WHERE L77.PARENT_ID = :SCHOOL_ID AND L77.OBJ_TYPE_ID = 77 AND L77.DATE_DEL IS NULL
      INTO :N;

      -- Сумма переходящих, кроме подготовительных
      SELECT COUNT(*)
      FROM LINKS L7
      JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
      JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0 AND V49.LISTVAL_ID <> 36
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
      JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      WHERE L7.PARENT_ID = :SCHOOL_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
      INTO :N_CROSS;

      VAL = VAL || '<td>' || (N + N_CROSS) || '</td>';
      G_TOTAL = G_TOTAL + N + N_CROSS;

      SELECT COUNT(*)
      FROM LINKS L7
      JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
      JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0 AND V49.LISTVAL_ID = 36
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
      JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      WHERE L7.PARENT_ID = :SCHOOL_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
      INTO :N;

      VAL = VAL || '<td>' || N || '</td>';
      G_GRADUATE = G_GRADUATE + N;
      VAL = VAL || '</tr>';

      IF(CHAR_LENGTH(VAL) > 4000) THEN
      BEGIN
        SUSPEND;
        VAL = '';
      END

    END

    VAL = VAL || '<tr class="thd">';
    VAL = VAL || '<td>Всего</td>';
    VAL = VAL || '<td>' || G_TOTAL || '</td>';
    VAL = VAL || '<td>' || G_GRADUATE || '</td>';
    VAL = VAL || '</tr>';

    IF(CHAR_LENGTH(VAL) > 4000) THEN
    BEGIN
      SUSPEND;
      VAL = '';
    END

  END

  -- Выводим остатки из буфера и заканчиваем таблицу
  VAL = VAL || '</table>';
  VAL = VAL || '</body>';
  VAL = VAL || '</html>';

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE REPORT_RKSYNC (
    I$OBJ_ID BIGINT,
    I$LEVEL_ID BIGINT)
RETURNS (
    VAL VARCHAR(4000))
AS
DECLARE VARIABLE V$DATE TIMESTAMP;
DECLARE VARIABLE V$NAME VARCHAR(1000);
DECLARE VARIABLE V$TEXT VARCHAR(4000);
DECLARE VARIABLE V$VERTEXT VARCHAR(1000);
DECLARE VARIABLE V$TYPE_ID BIGINT;
DECLARE VARIABLE N SMALLINT;
DECLARE VARIABLE CC INTEGER;
DECLARE VARIABLE S VARCHAR(100);
DECLARE VARIABLE T VARCHAR(1000);
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$PARENT_ID BIGINT;
DECLARE VARIABLE V$STATE INTEGER;
DECLARE VARIABLE V$IS_STUFF SMALLINT;
begin

  SELECT FIRST 1 R.VAL
  FROM LEVELS L
  JOIN TASKS T ON T.TASK_ID = L.TASK_ID
  JOIN RES R ON R.RES_ID = T.RES_ID AND R.LANG_CODE = 'RU'
  WHERE L.LEVEL_ID = :I$LEVEL_ID
  INTO :S;

  V$IS_STUFF = 0;
  IF(POSITION('сотрудников' IN S) > 0) THEN V$IS_STUFF = 1;

  VAL = '<!DOCTYPE html>';
  VAL = VAL || '<html lang="ru">';
  VAL = VAL || '<head>';
  VAL = VAL || '<meta charset="utf-8" />';

  VAL = VAL || '<style>';
  VAL = VAL || 'html { font-family: Tahoma, Verdana, Arial;';
  VAL = VAL || 'font-size: 10pt; ';
  VAL = VAL || '} ';
  VAL = VAL || '.title1 { font-size: 150%;';
  VAL = VAL || 'margin-bottom: 10px;';
  VAL = VAL || 'font-weight: bold;';
  VAL = VAL || '} ';
  VAL = VAL || '.details {';
  VAL = VAL || 'width: 100%;';
  VAL = VAL || 'margin-top: 10px;';
  VAL = VAL || 'border: 1px solid #e0e0e0;';
  VAL = VAL || '} ';
  VAL = VAL || '.details tr td {';
  VAL = VAL || 'padding: 2px 4px;';
  VAL = VAL || 'border-right: 1px solid #e0e0e0;';
  VAL = VAL || 'text-align: left;';
  VAL = VAL || '} ';
  VAL = VAL || '.odd td {';
  VAL = VAL || 'background-color: #f7f7f7;';
  VAL = VAL || '} ';
  VAL = VAL || '.thd td {';
  VAL = VAL || 'font-weight: bold;';
  VAL = VAL || 'border-bottom: 2px solid #a0a0a0 ! important;';
  VAL = VAL || '} ';

  VAL = VAL || '</style>';

  VAL = VAL || '</head>';
  VAL = VAL || '<body style="padding: 8px;">';

  -- Заголовок отчета
  VAL = VAL || '<div class="title1">Отчет по синхронизации данных РК по ' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$OBJ_ID)) || '</div>';

  VAL = VAL || '<table class="details" cellspacing="0" cellpadding="0">';

  VAL = VAL || '<tr class="thd">';
  VAL = VAL || '<td class="fio">ФИО</td>';
  VAL = VAL || '<td class="type">Тип персоны</td>';
  VAL = VAL || '<td class="dt">Дата, время</td>';
  VAL = VAL || '<td class="text">Описание проблемы</td>';
  VAL = VAL || '<td class="text">Статус верификации</td>';
  VAL = VAL || '</tr>';

  SUSPEND;

  N = 0;
  CC = 0;
  FOR
    SELECT L.DATE_MODIFY, L.STATE_ID, L.PERSON_ID, CAST(V1.VAL || ' ' || V2.VAL || COALESCE(' ' || V3.VAL, '') AS VARCHAR(400)), OBJ.TYPE_ID, L.MSG, L.VER_MSG
    FROM SYNC_LOG L
    JOIN OBJECTS OBJ ON OBJ.OBJ_ID = L.PERSON_ID
    JOIN VALS V1 ON V1.OBJ_ID = L.PERSON_ID AND V1.PARAM_ID IN (55, 59, 128) AND V1.IS_DEL = 0
    JOIN VALS V2 ON V2.OBJ_ID = L.PERSON_ID AND V2.PARAM_ID IN (56, 60, 129) AND V2.IS_DEL = 0
    LEFT JOIN VALS V3 ON V3.OBJ_ID = L.PERSON_ID AND V3.PARAM_ID IN (57, 61, 130) AND V3.IS_DEL = 0
    WHERE (L.STATE_ID <> 0 OR L.MSG IS NOT NULL OR L.VER_MSG IS NOT NULL) AND ((:V$IS_STUFF = 1 AND OBJ.TYPE_ID = 14) OR (:V$IS_STUFF = 0 AND OBJ.TYPE_ID <> 14))
    AND EXISTS(
      SELECT FIRST 1 1
      FROM LINKS LP
      WHERE LP.OBJ_ID = OBJ.OBJ_ID AND LP.PARENT_TYPE_ID IN (9, 46, 125, 187, 289, 290, 2, 211, 81, 82, 83, 84) AND LP.DATE_DEL IS NULL
    )
    ORDER BY 4
    INTO :V$DATE, :V$STATE, :V$OBJ_ID, :V$NAME, :V$TYPE_ID, :V$TEXT, :V$VERTEXT
  DO
  BEGIN
    IF(N = 0) THEN S = ''; ELSE S = 'odd';
    IF(N = 0) THEN N = 1; ELSE N = 0;

    IF(V$TYPE_ID = 10) THEN T = 'обучающийся';
    ELSE IF(V$TYPE_ID = 14) THEN T = 'сотрудник';
    ELSE IF(V$TYPE_ID = 20) THEN T = 'родитель/представитель';

    -- Выбираем действующий класс или родителя
    V$PARENT_ID = NULL;
    SELECT FIRST 1 PARENT_ID
    FROM LINKS L
    WHERE L.OBJ_ID = :V$OBJ_ID AND L.PARENT_TYPE_ID IN (9, 187, 290, 10) AND L.DATE_DEL IS NULL
    INTO :V$PARENT_ID;

    IF(V$PARENT_ID IS NOT NULL) THEN T = T || ' (' || (SELECT SCAPTION FROM OBJECT_CAPTION_GET(:V$PARENT_ID)) || ')';
    ELSE
    BEGIN
      -- В выбывших или уволенных ?
      SELECT FIRST 1 PARENT_ID
      FROM LINKS L
      WHERE L.OBJ_ID = :V$OBJ_ID AND L.PARENT_TYPE_ID IN (81, 82, 83, 84) AND L.DATE_DEL IS NULL
      INTO :V$PARENT_ID;

      IF(V$PARENT_ID IS NOT NULL) THEN T = T || ' (' || (SELECT SCAPTION FROM OBJECT_CAPTION_GET(:V$PARENT_ID)) || ')';
      ELSE
      BEGIN
        SELECT FIRST 1 PARENT_ID
        FROM LINKS L
        WHERE L.OBJ_ID = :V$OBJ_ID AND L.PARENT_TYPE_ID = 46 AND L.DATE_DEL IS NULL
        INTO :V$PARENT_ID;

        IF(V$PARENT_ID IS NOT NULL) THEN T = T || ' (' || (SELECT SCAPTION FROM OBJECT_CAPTION_GET(:V$PARENT_ID)) || ')';
      END
    END

    V$TEXT = COALESCE(V$TEXT, '');
    IF(V$TEXT = 'null') THEN V$TEXT = '';
    IF (V$TEXT = '' AND V$STATE <> 0) THEN
    BEGIN
      IF (V$STATE = -2) THEN V$TEXT = 'Конфликт данных, требуется ручное вмешательство';
      ELSE IF (V$STATE = -1) THEN V$TEXT = 'Идентификатор отозван, требуется перерегистрация';
      ELSE IF (V$STATE = 1) THEN V$TEXT = 'Изменения применены без миграции';
      ELSE IF (V$STATE = 2) THEN V$TEXT = 'Выполнено склеивание с другой записью';
      ELSE IF (V$STATE = 3) THEN V$TEXT = 'Перекреплено к другой записи';
      ELSE V$TEXT = 'Неизвестный статус';
    END

    VAL = '<tr class="' || S || '" data-state="' || V$STATE || '">';
    VAL = VAL || '<td class="fio">' || V$NAME || '</td>';
    VAL = VAL || '<td class="type">' || T || '</td>';
    VAL = VAL || '<td class="dt">' || (SELECT RESULT FROM DATE2STR(:V$DATE)) || '</td>';
    VAL = VAL || '<td class="text">' || V$TEXT || '</td>';
    VAL = VAL || '<td class="text">' || COALESCE(V$VERTEXT, '') || '</td>';
    VAL = VAL || '</tr>';
    CC = CC + 1;
    SUSPEND;
  END

  -- Замечания по зачислению в другие ОООД
  FOR
    SELECT VE.DATE_MODIFY, L10.OBJ_ID, CAST(V1.VAL || ' ' || V2.VAL || COALESCE(' ' || V3.VAL, '') AS VARCHAR(400)), L10.OBJ_TYPE_ID, VE.VAL
    FROM LINKS L10
    JOIN VALS V1 ON V1.OBJ_ID = L10.OBJ_ID AND V1.PARAM_ID IN (55, 59, 128) AND V1.IS_DEL = 0
    JOIN VALS V2 ON V2.OBJ_ID = L10.OBJ_ID AND V2.PARAM_ID IN (56, 60, 129) AND V2.IS_DEL = 0
    LEFT JOIN VALS V3 ON V3.OBJ_ID = L10.OBJ_ID AND V3.PARAM_ID IN (57, 61, 130) AND V3.IS_DEL = 0
    JOIN VALS VE ON VE.OBJ_ID = L10.OBJ_ID AND VE.PARAM_ID = 3446 AND VE.IS_DEL = 0
    WHERE L10.PARENT_TYPE_ID IN (9, 187, 290) AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    ORDER BY 4
    INTO :V$DATE, :V$OBJ_ID, :V$NAME, :V$TYPE_ID, :V$TEXT
  DO
  BEGIN
    IF(N = 0) THEN S = ''; ELSE S = 'odd';
    IF(N = 0) THEN N = 1; ELSE N = 0;

    T = 'обучающийся';

    VAL = '<tr class="' || S || '">';
    VAL = VAL || '<td class="fio">' || V$NAME || '</td>';
    VAL = VAL || '<td class="type">' || T || '</td>';
    VAL = VAL || '<td class="dt">' || (SELECT RESULT FROM DATE2STR(:V$DATE)) || '</td>';
    VAL = VAL || '<td class="text">Конфликт зачисления</td>';
    VAL = VAL || '<td class="text">' || V$TEXT || '</td>';
    VAL = VAL || '</tr>';

    CC = CC + 1;
    SUSPEND;
  END

  VAL = '</table>';

  IF(CC = 0) THEN
  BEGIN
      VAL = VAL || '<p>Нет замечаний по синхронизации. Это может означать, что их действительно нет, либо синхронизация не прошла по системным (сетевым) причинам, ';
      VAL = VAL || 'либо идентификаторы персон не присваивались и синхронизоровать нечего</p>';
  END

  VAL = VAL || '</body>';
  VAL = VAL || '</html>';
  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE REPORT_RKS_CARDS (
    I$OBJ_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    VAL VARCHAR(4000))
AS
declare variable V$OBJ_ID bigint;
declare variable N integer;
declare variable CC integer;
declare variable S varchar(100);
declare variable S2 varchar(1000);
declare variable S3 varchar(1000);
declare variable V$GO double precision;
declare variable V$SO double precision;
declare variable RKID varchar(100);
declare variable ULS varchar(100);
begin

  VAL = '<!DOCTYPE html>';
  VAL = VAL || '<html lang="ru">';
  VAL = VAL || '<head>';
  VAL = VAL || '<meta charset="utf-8" />';

  VAL = VAL || '<style>';
  VAL = VAL || 'html { font-family: Tahoma, Verdana, Arial;';
  VAL = VAL || 'font-size: 10pt; ';
  VAL = VAL || '} ';
  VAL = VAL || '.title1 { font-size: 150%;';
  VAL = VAL || 'margin-bottom: 10px;';
  VAL = VAL || 'font-weight: bold;';
  VAL = VAL || '} ';
  VAL = VAL || '.details {';
  VAL = VAL || 'width: 100%;';
  VAL = VAL || 'margin-top: 10px;';
  VAL = VAL || 'border: 1px solid #e0e0e0;';
  VAL = VAL || '} ';
  VAL = VAL || '.details tr td {';
  VAL = VAL || 'padding: 2px 4px;';
  VAL = VAL || 'border-right: 1px solid #e0e0e0;';
  VAL = VAL || 'text-align: left;';
  VAL = VAL || '} ';
  VAL = VAL || '.odd td {';
  VAL = VAL || 'background-color: #f7f7f7;';
  VAL = VAL || '} ';
  VAL = VAL || '.thd td {';
  VAL = VAL || 'font-weight: bold;';
  VAL = VAL || 'border-bottom: 2px solid #a0a0a0 ! important;';
  VAL = VAL || '} ';

  VAL = VAL || '</style>';

  VAL = VAL || '</head>';
  VAL = VAL || '<body style="padding: 8px;">';

  -- Заголовок отчета
  VAL = VAL || '<div class="title1">Отчет по готовности к выдаче школьных карт по ' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$OBJ_ID)) || '</div>';

  VAL = VAL || '<table class="details" cellspacing="0" cellpadding="0">';

  VAL = VAL || '<tr class="thd">';
  VAL = VAL || '<td class="fio">ФИО</td>';
  VAL = VAL || '<td class="text">Класс, этап обучения</td>';
  VAL = VAL || '<td class="text">УЛС</td>';
  VAL = VAL || '<td class="text">РегИД</td>';
  VAL = VAL || '</tr>';

  SUSPEND;

  N = 0;
  CC = 0;

  -- Сначала предварительный прием, потом действующие обучающиеся, потом сотрудники
  FOR
    SELECT L10.OBJ_ID, 0, CS.SORT_ORDER, CS.CAPTION, C.CAPTION, V2912.SVAL, V3482.SVAL
    FROM LINKS L2
    JOIN LINKS L77 ON L77.PARENT_ID = L2.OBJ_ID AND L77.OBJ_TYPE_ID = 77 AND L77.DATE_DEL IS NULL
    JOIN LINKS L290 ON L290.PARENT_ID = L77.OBJ_ID AND L290.OBJ_TYPE_ID = 290 AND L290.DATE_DEL IS NULL
    LEFT JOIN OBJECT_CAPTION_GET(L290.OBJ_ID) CS ON 1 = 1
    JOIN LINKS L10 ON L10.PARENT_ID = L290.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    LEFT JOIN OBJECT_CAPTION_GET(L10.OBJ_ID, 23) C ON 1 = 1
    LEFT JOIN VALS V2912 ON V2912.OBJ_ID = L10.OBJ_ID AND V2912.PARAM_ID = 2912 AND V2912.IS_DEL = 0
    LEFT JOIN VALS V3482 ON V3482.OBJ_ID = L10.OBJ_ID AND V3482.PARAM_ID = 3482 AND V3482.IS_DEL = 0
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND (V2912.SVAL IS NULL OR V3482.SVAL IS NULL)
    UNION
    SELECT L10.OBJ_ID, 1, CS.SORT_ORDER, CS.CAPTION, C.CAPTION, V2912.SVAL, V3482.SVAL
    FROM LINKS L2
    JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
    LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) CS ON 1 = 1
    JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    LEFT JOIN OBJECT_CAPTION_GET(L10.OBJ_ID, 23) C ON 1 = 1
    LEFT JOIN VALS V2912 ON V2912.OBJ_ID = L10.OBJ_ID AND V2912.PARAM_ID = 2912 AND V2912.IS_DEL = 0
    LEFT JOIN VALS V3482 ON V3482.OBJ_ID = L10.OBJ_ID AND V3482.PARAM_ID = 3482 AND V3482.IS_DEL = 0
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND (V2912.SVAL IS NULL OR V3482.SVAL IS NULL)
    UNION
    SELECT L14.OBJ_ID, 99, 0, 'Сотрудник', C.CAPTION, V2915.SVAL, NULL
    FROM LINKS L2
    JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
    LEFT JOIN OBJECT_CAPTION_GET(L14.OBJ_ID) C ON 1 = 1
    LEFT JOIN VALS V2915 ON V2915.OBJ_ID = L14.OBJ_ID AND V2915.PARAM_ID = 2915 AND V2915.IS_DEL = 0
    -- LEFT JOIN VALS V3482 ON V3482.OBJ_ID = L14.OBJ_ID AND V3482.PARAM_ID = 3482 AND V3482.IS_DEL = 0
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND (V2915.SVAL IS NULL /*OR V3482.SVAL IS NULL*/)
    ORDER BY 2, 3, 4, 5
    INTO :V$OBJ_ID, :V$GO, :V$SO, :S2, :S3, :RKID, :ULS
  DO
  BEGIN
    IF(N = 0) THEN S = ''; ELSE S = 'odd';
    IF(N = 0) THEN N = 1; ELSE N = 0;

    RKID = REPLACE(REPLACE(LOWER(RKID), '{', ''), '}', '');
    IF(POSITION(':' IN RKID) > 0) THEN RKID = SUBSTRING(RKID FROM 1 FOR POSITION(':' IN RKID) - 1);

    VAL = '<tr class="' || S || '">';
    VAL = VAL || '<td class="fio">' || S3 || '</td>';
    VAL = VAL || '<td class="text">' || S2 || '</td>';
    VAL = VAL || '<td class="text">' || COALESCE(ULS, '-') || '</td>';
    VAL = VAL || '<td class="text">' || COALESCE(RKID, '-') || '</td>';
    VAL = VAL || '</tr>';

    CC = CC + 1;
    SUSPEND;
  END

  VAL = '</table>';

  IF(CC = 0) THEN
  BEGIN
    VAL = VAL || '<p>Замечания по картам отсутствуют</p>';
  END

  VAL = VAL || '</body>';
  VAL = VAL || '</html>';
  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE REPORT_SCHOLAR (
    I$USER_ID BIGINT = 1)
RETURNS (
    DISTRICT_ID BIGINT,
    F1 VARCHAR(500),
    F2 INTEGER,
    F3 INTEGER,
    F4 INTEGER,
    F5 INTEGER,
    F6 INTEGER,
    F7 INTEGER,
    F8 INTEGER,
    F9 INTEGER,
    F10 INTEGER,
    F11 INTEGER,
    F12 INTEGER,
    F13 INTEGER,
    F14 INTEGER,
    F15 INTEGER,
    F16 INTEGER,
    F17 INTEGER,
    F18 INTEGER,
    F19 INTEGER,
    F20 INTEGER,
    F21 INTEGER,
    F22 INTEGER,
    F23 INTEGER,
    F24 INTEGER,
    F25 INTEGER)
AS
declare variable LANG_CODE varchar(2);
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :LANG_CODE;

    FOR
        SELECT
            DISTRICT_ID,
            (SELECT V FROM VAL_GET(DISTRICT_ID, 665)) F1,
            SUM(F3+F4+F5+F6+F7+F8+F9+F10+F19) + SUM(F16+F20+F21+F22) F2,
            IIF(SUM(F3) = 0, NULL, SUM(F3)) F3,
            IIF(SUM(F4) = 0, NULL, SUM(F4)) F4,
            IIF(SUM(F5) = 0, NULL, SUM(F5)) F5,
            IIF(SUM(F6) = 0, NULL, SUM(F6)) F6,
            IIF(SUM(F7) = 0, NULL, SUM(F7)) F7,
            IIF(SUM(F8) = 0, NULL, SUM(F8)) F8,
            IIF(SUM(F9) = 0, NULL, SUM(F9)) F9,
            IIF(SUM(F10) = 0, NULL, SUM(F10)) F10,
            IIF(SUM(F11) = 0, NULL, SUM(F11)) F11,
            IIF(SUM(F12) = 0, NULL, SUM(F12)) F12,
            IIF(SUM(F13) = 0, NULL, SUM(F13)) F13,
            IIF(SUM(F14) = 0, NULL, SUM(F14)) F14,
            IIF(SUM(F15) = 0, NULL, SUM(F15)) F15,
            IIF(SUM(F16) = 0, NULL, SUM(F16)) F16,
            IIF(SUM(F17) = 0, NULL, SUM(F17)) F17,
            IIF(SUM(F18) = 0, NULL, SUM(F18)) F18,
            IIF(SUM(F19) = 0, NULL, SUM(F19)) F19,
            IIF(SUM(F20) = 0, NULL, SUM(F20)) F20,
            IIF(SUM(F21) = 0, NULL, SUM(F21)) F21,
            IIF(SUM(F22) = 0, NULL, SUM(F22)) F22,
            IIF(SUM(F23) = 0, NULL, SUM(F23)) F23,
            IIF(SUM(F24) = 0, NULL, SUM(F24)) F24,
            SUM(F3+F4+F5+F6+F7+F8+F9+F10+F19) + SUM(F16+F20+F22) + SUM(F21+F23+F24) F25
        FROM (
            SELECT
                DISTRICT_ID,
                IIF(SCHOOL_OPF IN ('7','10') AND IS_SUB = 1 AND SCHOOL_TYPE = '01' AND IS_PUB = 0, SCHOLAR_CNT, 0) F3,
                IIF(SCHOOL_OPF IN ('7','10') AND IS_SUB = 1 AND (SCHOOL_VID = '0201' OR (SCHOOL_VID = '0105' AND IS_PUB = 1)), SCHOLAR_CNT, 0) F4,
                IIF(SCHOOL_OPF IN ('7','10') AND IS_SUB = 1 AND SCHOOL_VID IN ('0106', '0202', '0502'), SCHOLAR_CNT, 0) F5,
                IIF(SCHOOL_OPF IN ('7','10') AND IS_SUB = 1 AND SCHOOL_VID IN ('0101', '0203', '0503'), SCHOLAR_CNT, 0) F6,
                IIF(SCHOOL_OPF IN ('7','10') AND IS_SUB = 1 AND SCHOOL_VID IN ('0102', '0204'), SCHOLAR_CNT, 0) F7,
                IIF(SCHOOL_OPF IN ('7','10') AND IS_SUB = 1 AND SCHOOL_VID IN ('0103', '0205'), SCHOLAR_CNT, 0) F8,
                IIF(SCHOOL_OPF IN ('7','10') AND IS_SUB = 1 AND SCHOOL_VID IN ('0104', '0206') AND IS_SUB = 1, SCHOLAR_CNT, 0) F9,
                IIF(SCHOOL_OPF IN ('7','10') AND IS_SUB = 1 AND SCHOOL_TYPE = '03' AND IS_KADET = 1, SCHOLAR_CNT, 0) F10,
                IIF(SCHOOL_OPF IN ('7','10') AND IS_SUB = 1 AND SCHOOL_VID = '0202', SCHOLAR_CNT, 0) F11,
                IIF(SCHOOL_OPF IN ('7','10') AND IS_SUB = 1 AND SCHOOL_VID = '0203', SCHOLAR_CNT, 0) F12,
                IIF(SCHOOL_OPF IN ('7','10') AND IS_SUB = 1 AND SCHOOL_VID = '0204', SCHOLAR_CNT, 0) F13,
                IIF(SCHOOL_OPF IN ('7','10') AND IS_SUB = 1 AND SCHOOL_VID = '0205', SCHOLAR_CNT, 0) F14,
                IIF(SCHOOL_OPF IN ('7','10') AND IS_SUB = 1 AND SCHOOL_VID IN ('0502', '0503'), SCHOLAR_CNT, 0) F15,
                IIF(SCHOOL_OPF IN ('7','10') AND IS_SUB = 1 AND (SCHOOL_TYPE = '06' OR SCHOOL_VID IN ('0504', '0505')), SCHOLAR_CNT, 0) F16,
                IIF(SCHOOL_OPF IN ('7','10') AND IS_SUB = 1 AND SCHOOL_VID IN ('0603', '0505'), SCHOLAR_CNT, 0) F17,
                IIF(SCHOOL_OPF IN ('7','10') AND IS_SUB = 1 AND SCHOOL_VID IN ('0504', '0505'), SCHOLAR_CNT, 0) F18,
                IIF(SCHOOL_OPF IN ('7','10') AND IS_SUB = 1 AND SCHOOL_TYPE = '07', SCHOLAR_CNT, 0) F19,
                IIF(SCHOOL_OPF IN ('7','10') AND IS_SUB = 1 AND SCHOOL_TYPE = '09', SCHOLAR_CNT, 0) F20,
                IIF(V_TYPE = 2221, SCHOLAR_CNT, 0) F21,
                IIF(SCHOOL_OPF IN ('7','10') AND IS_SUB = 1 AND SCHOOL_TYPE = '10', SCHOLAR_CNT, 0) F22,
                IIF(SCHOOL_OPF = '4', SCHOLAR_CNT, 0) F23,
                IIF(SCHOOL_OPF <> '4' AND (SCHOOL_OPF NOT IN ('7','10') OR IS_SUB = 0 OR (SCHOOL_TYPE = '03' AND IS_KADET = 0)) AND V_TYPE <> 2221, SCHOLAR_CNT, 0) F24
            FROM (
                SELECT
                    L111.OBJ_ID DISTRICT_ID, L2.OBJ_ID SCHOOL_ID,
                    IIF((SELECT FIRST 1 LOWER(VAL)
                         FROM RES
                         WHERE RES_ID = L_VID.RES_ID
                           AND LANG_CODE = :LANG_CODE
                           AND IS_DEL = 0) LIKE 'кадетская школа%', 1, 0) IS_KADET,
                    L_VID.TAG SCHOOL_VID, L_OPF.TAG SCHOOL_OPF,
                    SUBSTRING(L_VID.TAG FROM 1 FOR 1) SCHOOL_TYPE,
                    IIF(LOWER(V_SUB.VAL) LIKE 'комитет по %образованию%'
                           OR LOWER(V_SUB.VAL) LIKE 'администрация%района%', 1, 0) IS_SUB,
                    IIF((SELECT FIRST 1 LOWER(VAL)
                         FROM RES
                         WHERE RES_ID = L_TYPE.RES_ID
                           AND LANG_CODE = :LANG_CODE
                           AND IS_DEL = 0) LIKE 'общеобразовательные%', 1, 0) IS_PUB,
                   (SELECT COUNT(1) FROM LINKS L7
                    INNER JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID
                    INNER JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID
                    INNER JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID
                    WHERE L7.PARENT_ID = L2.OBJ_ID
                      AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
                      AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
                      AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
                      AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL) SCHOLAR_CNT,
                    V_TYPE.LISTVAL_ID V_TYPE
                FROM VALL V_VID, LISTVALS L_VID,
                     VALL V_OPF, LISTVALS L_OPF,
                     VALL V_TYPE, LISTVALS L_TYPE,
                     LINKS L111, LINKS L2
                LEFT JOIN VALS V_SUB ON V_SUB.OBJ_ID = L2.OBJ_ID
                    AND V_SUB.PARAM_ID = 6 AND V_SUB.IS_DEL = 0
                WHERE L2.PARENT_ID = L111.OBJ_ID
                    AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
                    AND L111.OBJ_TYPE_ID = 111 AND L111.DATE_DEL IS NULL
                    AND L_VID.LISTVAL_ID = V_VID.LISTVAL_ID AND V_VID.OBJ_ID = L2.OBJ_ID
                    AND L_VID.LIST_ID = 6 AND L_VID.IS_DEL = 0
                    AND V_VID.PARAM_ID = 10 AND V_VID.IS_DEL = 0
                    AND L_OPF.LISTVAL_ID = V_OPF.LISTVAL_ID AND V_OPF.OBJ_ID = L2.OBJ_ID
                    AND L_OPF.LIST_ID IN (4, 258) AND L_OPF.IS_DEL = 0
                    AND V_OPF.PARAM_ID = 8 AND V_OPF.IS_DEL = 0
                    AND L_TYPE.LISTVAL_ID = V_TYPE.LISTVAL_ID AND V_TYPE.OBJ_ID = L2.OBJ_ID
                    AND L_TYPE.LIST_ID = 6 AND L_TYPE.IS_DEL = 0
                    AND V_TYPE.PARAM_ID = 11 AND V_TYPE.IS_DEL = 0
                )
            )
        GROUP BY DISTRICT_ID
        INTO :DISTRICT_ID, :F1, :F2, :F3, :F4, :F5, :F6, :F7, :F8, :F9, :F10,
             :F11, :F12, :F13, :F14, :F15, :F16, :F17, :F18, :F19, :F20,
             :F21, :F22, :F23, :F24, :F25
    DO
    BEGIN
        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE REPORT_SCHOLAR_DTL (
    I$DISTRICT_ID BIGINT NOT NULL,
    I$N INTEGER NOT NULL,
    I$USER_ID BIGINT = 1)
RETURNS (
    F1 VARCHAR(250),
    VAL2 INTEGER)
AS
declare variable LANG_CODE varchar(2);
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :LANG_CODE;

    FOR
        SELECT
            COALESCE(V_NUM.VAL, (SELECT V FROM VAL_GET(LL.SCHOOL_ID, 2))) F1,
           (SELECT COUNT(1) FROM LINKS L7
            INNER JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID
            INNER JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID
            INNER JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID
            WHERE L7.PARENT_ID = SCHOOL_ID
              AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
              AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
              AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
              AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL) VAL2
        FROM (
            SELECT
                L2.OBJ_ID SCHOOL_ID,
                IIF((SELECT FIRST 1 LOWER(VAL)
                     FROM RES
                     WHERE RES_ID = L_VID.RES_ID
                       AND LANG_CODE = :LANG_CODE
                       AND IS_DEL = 0) LIKE 'кадетская школа%', 1, 0) IS_KADET,
                L_VID.TAG SCHOOL_VID, L_OPF.TAG SCHOOL_OPF,
                SUBSTRING(L_VID.TAG FROM 1 FOR 1) SCHOOL_TYPE,
                IIF(LOWER(V_SUB.VAL) LIKE 'комитет по %образованию%'
                       OR LOWER(V_SUB.VAL) LIKE 'администрация%района%', 1, 0) IS_SUB,
                IIF((SELECT FIRST 1 LOWER(VAL)
                     FROM RES
                     WHERE RES_ID = L_TYPE.RES_ID
                       AND LANG_CODE = :LANG_CODE
                       AND IS_DEL = 0) LIKE 'общеобразовательные%', 1, 0) IS_PUB,
                V_TYPE.LISTVAL_ID V_TYPE
            FROM VALL V_VID, LISTVALS L_VID,
                 VALL V_OPF, LISTVALS L_OPF,
                 VALL V_TYPE, LISTVALS L_TYPE,
                 LINKS L2
            LEFT JOIN VALS V_SUB ON V_SUB.OBJ_ID = L2.OBJ_ID
                AND V_SUB.PARAM_ID = 6 AND V_SUB.IS_DEL = 0
            WHERE L2.PARENT_ID = :I$DISTRICT_ID
              AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
              AND L_VID.LISTVAL_ID = V_VID.LISTVAL_ID AND V_VID.OBJ_ID = L2.OBJ_ID
              AND L_VID.LIST_ID = 6 AND L_VID.IS_DEL = 0
              AND V_VID.PARAM_ID = 10 AND V_VID.IS_DEL = 0
              AND L_OPF.LISTVAL_ID = V_OPF.LISTVAL_ID AND V_OPF.OBJ_ID = L2.OBJ_ID
              AND L_OPF.LIST_ID IN (4, 258) AND L_OPF.IS_DEL = 0
              AND V_OPF.PARAM_ID = 8 AND V_OPF.IS_DEL = 0
              AND L_TYPE.LISTVAL_ID = V_TYPE.LISTVAL_ID AND V_TYPE.OBJ_ID = L2.OBJ_ID
              AND L_TYPE.LIST_ID = 6 AND L_TYPE.IS_DEL = 0
              AND V_TYPE.PARAM_ID = 11 AND V_TYPE.IS_DEL = 0
            ) LL
        LEFT JOIN VALI V_NUM ON V_NUM.OBJ_ID = LL.SCHOOL_ID
            AND V_NUM.PARAM_ID = 17 AND V_NUM.IS_DEL = 0
        WHERE (:I$N =  3 AND SCHOOL_OPF IN ('7','10') AND IS_SUB = 1 AND SCHOOL_TYPE = '01' AND IS_PUB = 0)
           OR (:I$N =  4 AND SCHOOL_OPF IN ('7','10') AND IS_SUB = 1 AND (SCHOOL_VID = '0201' OR (SCHOOL_VID = '0105' AND IS_PUB = 1)))
           OR (:I$N =  5 AND SCHOOL_OPF IN ('7','10') AND IS_SUB = 1 AND SCHOOL_VID IN ('0106', '0202', '0502'))
           OR (:I$N =  6 AND SCHOOL_OPF IN ('7','10') AND IS_SUB = 1 AND SCHOOL_VID IN ('0101', '0203', '0503'))
           OR (:I$N =  7 AND SCHOOL_OPF IN ('7','10') AND IS_SUB = 1 AND SCHOOL_VID IN ('0102', '0204'))
           OR (:I$N =  8 AND SCHOOL_OPF IN ('7','10') AND IS_SUB = 1 AND SCHOOL_VID IN ('0103', '0205'))
           OR (:I$N =  9 AND SCHOOL_OPF IN ('7','10') AND IS_SUB = 1 AND SCHOOL_VID IN ('0104', '0206') AND IS_SUB = 1)
           OR (:I$N = 10 AND SCHOOL_OPF IN ('7','10') AND IS_SUB = 1 AND SCHOOL_TYPE = '03' AND IS_KADET = 1)
           OR (:I$N = 11 AND SCHOOL_OPF IN ('7','10') AND IS_SUB = 1 AND SCHOOL_VID = '0202')
           OR (:I$N = 12 AND SCHOOL_OPF IN ('7','10') AND IS_SUB = 1 AND SCHOOL_VID = '0203')
           OR (:I$N = 13 AND SCHOOL_OPF IN ('7','10') AND IS_SUB = 1 AND SCHOOL_VID = '0204')
           OR (:I$N = 14 AND SCHOOL_OPF IN ('7','10') AND IS_SUB = 1 AND SCHOOL_VID = '0205')
           OR (:I$N = 15 AND SCHOOL_OPF IN ('7','10') AND IS_SUB = 1 AND SCHOOL_VID IN ('0502', '0503'))
           OR (:I$N = 16 AND SCHOOL_OPF IN ('7','10') AND IS_SUB = 1 AND (SCHOOL_TYPE = '06' OR SCHOOL_VID IN ('0504', '0505')))
           OR (:I$N = 17 AND SCHOOL_OPF IN ('7','10') AND IS_SUB = 1 AND SCHOOL_VID IN ('0603', '0505'))
           OR (:I$N = 18 AND SCHOOL_OPF IN ('7','10') AND IS_SUB = 1 AND SCHOOL_VID IN ('0504', '0505'))
           OR (:I$N = 19 AND SCHOOL_OPF IN ('7','10') AND IS_SUB = 1 AND SCHOOL_TYPE = '07')
           OR (:I$N = 20 AND SCHOOL_OPF IN ('7','10') AND IS_SUB = 1 AND SCHOOL_TYPE = '09')
           OR (:I$N = 21 AND V_TYPE = 2221)
           OR (:I$N = 22 AND SCHOOL_OPF IN ('7','10') AND IS_SUB = 1 AND SCHOOL_TYPE = '10')
           OR (:I$N = 23 AND SCHOOL_OPF = '4')
           OR (:I$N = 24 AND SCHOOL_OPF <> '4' AND (SCHOOL_OPF NOT IN ('7','10') OR IS_SUB = 0 OR (SCHOOL_TYPE = '03' AND IS_KADET = 0)) AND V_TYPE <> 2221)
        INTO :F1, :VAL2
    DO
    BEGIN
        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE REPORT_STUDENTS_NG (
    I$OBJ_ID BIGINT)
RETURNS (
    VAL VARCHAR(4000))
AS
declare variable V$STUDENT_ID bigint;
declare variable V$CLASS_NAME varchar(400);
declare variable V$STUDENT_NAME varchar(400);
declare variable V$GUP_ID bigint;
declare variable V$PLAN_ID bigint;
declare variable V$STAGE_ID bigint;
declare variable V$SUBJECT_ID bigint;
declare variable V$SUBJECT_NAME varchar(400);
declare variable N integer;
begin

  IF(I$OBJ_ID IS NULL) THEN
  SELECT FIRST 1 L2.OBJ_ID
  FROM LINKS L2
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :I$OBJ_ID;

  VAL = '<!DOCTYPE html>';
  VAL = VAL || '<html lang="ru">';
  VAL = VAL || '<head>';
  VAL = VAL || '<meta charset="utf-8" />';
  VAL = VAL || '<style>';
  VAL = VAL || 'html { font-family: Tahoma, Verdana, Arial;';
  VAL = VAL || 'font-size: 10pt; ';
  VAL = VAL || '} ';
  VAL = VAL || '.title1 { font-size: 150%;';
  VAL = VAL || 'padding: 8px;';
  VAL = VAL || 'margin-bottom: 4px;';
  VAL = VAL || 'font-weight: bold;';
  VAL = VAL || 'background-color: #D4E157;';
  VAL = VAL || '} ';
  VAL = VAL || 'table { table-layout: fixed;';
  VAL = VAL || '} ';
  VAL = VAL || 'th { font-weight: bold;';
  VAL = VAL || 'border-bottom: 2px solid #000;';
  VAL = VAL || '} ';
  VAL = VAL || 'th, td { padding: 0.3em 0.5em;';
  VAL = VAL || '} ';
  VAL = VAL || 'tbody tr:nth-child(even) { background: #f0f0f0;';
  VAL = VAL || '} ';
  VAL = VAL || '</style>';

  VAL = VAL || '</head>';
  VAL = VAL || '<body>';

  VAL = VAL || '<div class="title1">Обучающиеся, не распределенные по группам</div>';

  VAL = VAL || '<table cellspacing="0" cellpadding="0">';
  VAL = VAL || '<thead><tr>';
    VAL = VAL || '<th>Обучающийся</th>';
    VAL = VAL || '<th>Учебный коллектив</th>';
    VAL = VAL || '<th>Примечания</th>';
  VAL = VAL || '</tr><thead>';
  VAL = VAL || '<tbody>';
  SUSPEND;

  FOR
    SELECT L10.OBJ_ID, C1.SCAPTION, C2.SCAPTION
    FROM LINKS L2
    JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
    JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C1 ON 1 = 1
    LEFT JOIN OBJECT_CAPTION_GET(L10.OBJ_ID, 23) C2 ON 1 = 1
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    ORDER BY C1.SORT_ORDER, C1.SCAPTION, C2.SCAPTION
    INTO :V$STUDENT_ID, :V$CLASS_NAME, :V$STUDENT_NAME
  DO
  BEGIN

    V$GUP_ID = NULL;
    V$PLAN_ID = NULL;
    V$STAGE_ID = NULL;

    SELECT FIRST 1 LP256.PARENT_ID, LP400.PARENT_ID, LP54.PARENT_ID
    FROM LINKS LP256
    JOIN LINKS LP54 ON LP54.OBJ_ID = LP256.PARENT_ID AND LP54.PARENT_TYPE_ID = 54 AND LP54.DATE_DEL IS NULL
    JOIN LINKS LP400 ON LP400.OBJ_ID = LP54.PARENT_ID AND LP400.PARENT_TYPE_ID = 400 AND LP400.DATE_DEL IS NULL
    WHERE LP256.OBJ_ID = :V$STUDENT_ID AND LP256.PARENT_TYPE_ID = 256 AND LP256.DATE_DEL IS NULL
    INTO :V$GUP_ID, :V$PLAN_ID, :V$STAGE_ID;

    VAL = '<tr>';

    IF(V$GUP_ID IS NULL) THEN
    BEGIN
      VAL = VAL || '<td>' || V$STUDENT_NAME || '</td>';
      VAL = VAL || '<td>' || V$CLASS_NAME || '</td>';
      VAL = VAL || '<td>Не распределен в ГУП</td>';
      VAL = VAL || '</tr>';
      SUSPEND;
    END
    ELSE
    BEGIN
      -- Есть в ГУП. Проверяем, во все ли поточные предметы распределен, кроме элективов
      N = 0;
      VAL = VAL || '<td>' || V$STUDENT_NAME || '</td>';
      VAL = VAL || '<td>' || V$CLASS_NAME || '</td>';
      VAL = VAL || '<td>';

      FOR
        SELECT DISTINCT PS.SUBJECT_ID, C.CAPTION
        FROM PLAN_SUBJECTS PS
        JOIN PLAN_LOADS PL ON PL.DATE_DEL IS NULL AND PL.SUBJECT_ID = PS.OBJ_ID AND PL.STAGE_ID = :V$STAGE_ID
          AND (COALESCE(PL.LOAD_HOURS_S1, 0) + COALESCE(PL.LOAD_HOURS_S2, 0)) > 0
        LEFT JOIN VALL V2816 ON V2816.OBJ_ID = PS.SUBJECT_ID AND V2816.PARAM_ID = 2816 AND V2816.IS_DEL = 0
        LEFT JOIN OBJECT_CAPTION_GET(PS.SUBJECT_ID) C ON 1 = 1
        WHERE PS.DATE_DEL IS NULL AND PS.PLAN_ID = :V$PLAN_ID AND PS.ROW_TYPE = 10
          AND (V2816.LISTVAL_ID IS NULL OR V2816.LISTVAL_ID = 3)
        ORDER BY 2
        INTO :V$SUBJECT_ID, :V$SUBJECT_NAME
      DO
      BEGIN
        -- Дополнительно проверяем модульные предметы
        IF(NOT EXISTS(
          SELECT FIRST 1 1
          FROM LINKS LP179
          JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.GRADE_ID = LP179.PARENT_ID
          LEFT JOIN VALR V3159 ON V3159.OBJ_ID = J.SUBJECT_ID AND V3159.PARAM_ID = 3159 AND V3159.IS_DEL = 0
          WHERE LP179.OBJ_ID = :V$STUDENT_ID AND LP179.PARENT_TYPE_ID = 179 AND LP179.DATE_DEL IS NULL
            AND (J.SUBJECT_ID = :V$SUBJECT_ID OR V3159.VAL = :V$SUBJECT_ID)
        )) THEN
        BEGIN
          IF(CHARACTER_LENGTH(VAL) + CHARACTER_LENGTH(V$SUBJECT_NAME) < 3900) THEN
          BEGIN
            IF(N > 0) THEN VAL = VAL || ', ';
            VAL = VAL || V$SUBJECT_NAME;
          END
          N = N + 1;
        END
      END

      VAL = VAL || '</td>';
      VAL = VAL || '</tr>';
      IF(N > 0) THEN SUSPEND;
    END

  END

  -- Закрываем таблицу
  VAL = '</table></body></html>';
  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE REPORT_UP_CONTROL_P1 (
    OBJ_ID BIGINT)
RETURNS (
    OO_NAME VARCHAR(1000),
    OO_DISTRICT VARCHAR(400),
    LEVEL_NAME VARCHAR(400),
    V1 VARCHAR(10),
    V2 VARCHAR(10),
    V3 INTEGER,
    V4 INTEGER,
    V5 VARCHAR(1000),
    V6 INTEGER,
    V7 INTEGER,
    V8 INTEGER,
    V9 INTEGER)
AS
declare variable V$SCHOOL_ID bigint;
declare variable V$VAL double precision;
declare variable V$STR varchar(1000);
declare variable V$P integer;
declare variable V$N integer;
begin

  /* Перерасчет СМИР */
  SELECT COUNT(*) FROM EXPORT_LOCAL_DO_FUNC INTO :V$VAL;

  /* Выбираем сразу сечение район-школа */
  /* Отчет может быть выбран на уровнях (OBJ_ID): Мониторинг, Школа, Район, Регион  */

  FOR
    SELECT L2.PARENT_ID, V2.VAL, R111.VAL
    FROM LINKS L2
    JOIN VALS V2 on V2.OBJ_ID = L2.PARENT_ID and V2.PARAM_ID = 2 and V2.IS_DEL = 0
    -- район
    LEFT JOIN LINKS L111 on L111.OBJ_ID = L2.PARENT_ID and L111.PARENT_TYPE_ID = 111 and L111.DATE_DEL is null
    LEFT JOIN VALL V665 on V665.OBJ_ID = L111.PARENT_ID and V665.PARAM_ID in (665, 1406) and V665.IS_DEL = 0
    LEFT JOIN LISTVALS LV111 on LV111.LISTVAL_ID = V665.LISTVAL_ID
    LEFT JOIN RES R111 on R111.RES_ID = LV111.RES_ID and R111.LANG_CODE = 'RU'
    -- регион
    LEFT JOIN LINKS L112 on L112.OBJ_ID = L111.PARENT_ID and L112.PARENT_TYPE_ID = 112 and L112.DATE_DEL is null
    WHERE L2.PARENT_TYPE_ID = 2 and L2.OBJ_TYPE_ID = 162 and L2.DATE_DEL is null and
      (L2.OBJ_ID = :OBJ_ID or L2.PARENT_ID = :OBJ_ID or L111.PARENT_ID = :OBJ_ID or L112.PARENT_ID = :OBJ_ID)
    ORDER BY 3, 2
    INTO :V$SCHOOL_ID, :OO_NAME, :OO_DISTRICT
  DO
  BEGIN

    /* Восстанавливаем обратно ID объекта мониторинг */
    OBJ_ID = NULL;

    SELECT L162.OBJ_ID
    FROM LINKS L162
    WHERE L162.PARENT_ID = :V$SCHOOL_ID and L162.OBJ_TYPE_ID = 162 and L162.DATE_DEL is null
    INTO :OBJ_ID;

    /* Первая группа */
    LEVEL_NAME = 'Начальное образование';

    /* Соответствие общего количества часов УП */
    V1 = NULL;

    FOR SELECT V2486.LISTVAL_ID
    FROM LINKS L305                                                                             
    JOIN VALL V2483 on V2483.OBJ_ID = L305.OBJ_ID and V2483.PARAM_ID = 2483 and V2483.IS_DEL = 0 and V2483.LISTVAL_ID in (5339, 5340)
    JOIN VALL V2486 on V2486.OBJ_ID = L305.OBJ_ID and V2486.PARAM_ID = 2486 and V2486.IS_DEL = 0
    WHERE L305.PARENT_ID = :OBJ_ID and L305.OBJ_TYPE_ID = 305 and L305.DATE_DEL is null
    INTO :V$VAL
    DO
    BEGIN
        IF(V$VAL = 3) THEN V1 = 'Нет';
        ELSE IF(V$VAL = 2 and V1 is null) THEN V1 = 'Да';
    END

    /* Соответствие количества часов обязательной части УП */
    V2 = NULL;

    FOR SELECT V2487.LISTVAL_ID
    FROM LINKS L305
    JOIN VALL V2483 on V2483.OBJ_ID = L305.OBJ_ID and V2483.PARAM_ID = 2483 and V2483.IS_DEL = 0 and V2483.LISTVAL_ID in (5339, 5340)
    JOIN VALL V2487 on V2487.OBJ_ID = L305.OBJ_ID and V2487.PARAM_ID = 2487 and V2487.IS_DEL = 0
    WHERE L305.PARENT_ID = :OBJ_ID and L305.OBJ_TYPE_ID = 305 and L305.DATE_DEL is null
    INTO :V$VAL
    DO
    BEGIN
        IF(V$VAL = 3) THEN V2 = 'Нет';
        ELSE IF(V$VAL = 2 and V2 is null) THEN V2 = 'Да';
    END

    /* Несоответствие в часах по обязательной части */
    V3 = NULL;

    SELECT COUNT(*)
    FROM LINKS L307
    /* Учебный план */
    JOIN VALR V2493 on V2493.OBJ_ID = L307.OBJ_ID and V2493.PARAM_ID = 2493 and V2493.IS_DEL = 0
    /* Учебная программа */
    JOIN LINKS L57 on L57.OBJ_ID = V2493.VAL and L57.PARENT_TYPE_ID = 57 and L57.DATE_DEL is null
    /* Уровень */
    JOIN VALL V1832 on V1832.OBJ_ID = L57.PARENT_ID and V1832.PARAM_ID = 1832 and V1832.IS_DEL = 0 and V1832.LISTVAL_ID in (5339, 5340)
    /* Количество часов */
    JOIN VALI V2487 on V2487.OBJ_ID = L307.OBJ_ID and V2487.PARAM_ID = 2487 and V2487.IS_DEL = 0 and V2487.VAL > 0
    WHERE L307.PARENT_ID = :OBJ_ID and L307.OBJ_TYPE_ID = 307 and L307.DATE_DEL is null
    INTO :V3;

    IF(V3 is null) THEN V3 = 0;

    /* Несоответствие в часах по части ОО */
    V4 = NULL;

    SELECT COUNT(*)
    FROM LINKS L309
    /* Учебный план */
    JOIN VALR V2498 on V2498.OBJ_ID = L309.OBJ_ID and V2498.PARAM_ID = 2498 and V2498.IS_DEL = 0
    /* Учебная программа */
    JOIN LINKS L57 on L57.OBJ_ID = V2498.VAL and L57.PARENT_TYPE_ID = 57 and L57.DATE_DEL is null
    /* Уровень */
    JOIN VALL V1832 on V1832.OBJ_ID = L57.PARENT_ID and V1832.PARAM_ID = 1832 and V1832.IS_DEL = 0 and V1832.LISTVAL_ID in (5339, 5340)
    /* Количество часов */
    JOIN VALI V2501 on V2501.OBJ_ID = L309.OBJ_ID and V2501.PARAM_ID = 2501 and V2501.IS_DEL = 0 and V2501.VAL > 0
    WHERE L309.PARENT_ID = :OBJ_ID and L309.OBJ_TYPE_ID = 309 and L309.DATE_DEL is null
    INTO :V4;

    IF(V4 is null) THEN V4 = 0;

    /* Пустые */
    V5 = NULL;
    V6 = NULL;

    /* Неутвержденные ПТП */
    V7 = NULL;

    SELECT COUNT(*)
    FROM LINKS L313
    /* Учебный план */
    JOIN VALR V2511 on V2511.OBJ_ID = L313.OBJ_ID and V2511.PARAM_ID = 2511 and V2511.IS_DEL = 0
    /* Учебная программа */
    JOIN LINKS L57 on L57.OBJ_ID = V2511.VAL and L57.PARENT_TYPE_ID = 57 and L57.DATE_DEL is null
    /* Уровень */
    JOIN VALL V1832 on V1832.OBJ_ID = L57.PARENT_ID and V1832.PARAM_ID = 1832 and V1832.IS_DEL = 0 and V1832.LISTVAL_ID in (5339, 5340)
    WHERE L313.PARENT_ID = :OBJ_ID and L313.OBJ_TYPE_ID = 313 and L313.DATE_DEL is null
    INTO :V7;

    IF(V7 is null) THEN V7 = 0;

    /* Соответствие часов ПТП и УП */
    V8 = NULL;

    SELECT COUNT(*)
    FROM LINKS L315
    /* Учебный план */
    JOIN VALR V2515 on V2515.OBJ_ID = L315.OBJ_ID and V2515.PARAM_ID = 2515 and V2515.IS_DEL = 0
    /* Учебная программа */
    JOIN LINKS L57 on L57.OBJ_ID = V2515.VAL and L57.PARENT_TYPE_ID = 57 and L57.DATE_DEL is null
    /* Уровень */
    JOIN VALL V1832 on V1832.OBJ_ID = L57.PARENT_ID and V1832.PARAM_ID = 1832 and V1832.IS_DEL = 0 and V1832.LISTVAL_ID in (5339, 5340)
    WHERE L315.PARENT_ID = :OBJ_ID and L315.OBJ_TYPE_ID = 315 and L315.DATE_DEL is null
    INTO :V8;

    IF(V8 is null) THEN V8 = 0;

    /* Количество несоответствий по выполнению УП */
    /* Средний процент выполнения */
    SELECT AVG(V2530.VAL)
    FROM LINKS L316
    /* Этап */
    JOIN VALR V2522 on V2522.OBJ_ID = L316.OBJ_ID and V2522.PARAM_ID = 2522 and V2522.IS_DEL = 0
    /* Учебный план */
    JOIN LINKS L50 on L50.OBJ_ID = V2522.VAL and L50.PARENT_TYPE_ID = 50 and L50.DATE_DEL is null
    /* Учебная программа */
    JOIN LINKS L57 on L57.OBJ_ID = L50.PARENT_ID and L57.PARENT_TYPE_ID = 57 and L57.DATE_DEL is null
    /* Уровень */
    JOIN VALL V1832 on V1832.OBJ_ID = L57.PARENT_ID and V1832.PARAM_ID = 1832 and V1832.IS_DEL = 0 and V1832.LISTVAL_ID in (5339, 5340)
    /* % выполнения */
    JOIN VALF V2530 on V2530.OBJ_ID = L316.OBJ_ID and V2530.PARAM_ID = 2530 and V2530.IS_DEL = 0
    WHERE L316.PARENT_ID = :OBJ_ID and L316.OBJ_TYPE_ID = 316 and L316.DATE_DEL is null
    INTO :V$VAL;

    /* Количество строк с отклонениями */
    V9 = NULL;

    SELECT COUNT(*)
    FROM LINKS L316
    /* Этап */
    JOIN VALR V2522 on V2522.OBJ_ID = L316.OBJ_ID and V2522.PARAM_ID = 2522 and V2522.IS_DEL = 0
    /* Учебный план */
    JOIN LINKS L50 on L50.OBJ_ID = V2522.VAL and L50.PARENT_TYPE_ID = 50 and L50.DATE_DEL is null
    /* Учебная программа */
    JOIN LINKS L57 on L57.OBJ_ID = L50.PARENT_ID and L57.PARENT_TYPE_ID = 57 and L57.DATE_DEL is null
    /* Уровень */
    JOIN VALL V1832 on V1832.OBJ_ID = L57.PARENT_ID and V1832.PARAM_ID = 1832 and V1832.IS_DEL = 0 and V1832.LISTVAL_ID in (5339, 5340)
    /* % выполнения */
    JOIN VALF V2530 on V2530.OBJ_ID = L316.OBJ_ID and V2530.PARAM_ID = 2530 and V2530.IS_DEL = 0
    WHERE L316.PARENT_ID = :OBJ_ID and L316.OBJ_TYPE_ID = 316 and L316.DATE_DEL is null and (ABS(V2530.VAL - :V$VAL) > (:V$VAL * 0.1))
    INTO :V9;

    IF(V9 is null) THEN V9 = 0;

    SUSPEND;

    /* Вторая группа */
    LEVEL_NAME = 'Основное образование';

    /* Соответствие общего количества часов УП */
    V1 = NULL;

    FOR SELECT V2486.LISTVAL_ID
    FROM LINKS L305                                                                             
    JOIN VALL V2483 on V2483.OBJ_ID = L305.OBJ_ID and V2483.PARAM_ID = 2483 and V2483.IS_DEL = 0 and V2483.LISTVAL_ID in (5341, 5342)
    JOIN VALL V2486 on V2486.OBJ_ID = L305.OBJ_ID and V2486.PARAM_ID = 2486 and V2486.IS_DEL = 0
    WHERE L305.PARENT_ID = :OBJ_ID and L305.OBJ_TYPE_ID = 305 and L305.DATE_DEL is null
    INTO :V$VAL
    DO
    BEGIN
        IF(V$VAL = 3) THEN V1 = 'Нет';
        ELSE IF(V$VAL = 2 and V1 is null) THEN V1 = 'Да';
    END

    /* Соответствие количества часов обязательной части УП */
    V2 = NULL;

    FOR SELECT V2487.LISTVAL_ID
    FROM LINKS L305
    JOIN VALL V2483 on V2483.OBJ_ID = L305.OBJ_ID and V2483.PARAM_ID = 2483 and V2483.IS_DEL = 0 and V2483.LISTVAL_ID in (5341, 5342)
    JOIN VALL V2487 on V2487.OBJ_ID = L305.OBJ_ID and V2487.PARAM_ID = 2487 and V2487.IS_DEL = 0
    WHERE L305.PARENT_ID = :OBJ_ID and L305.OBJ_TYPE_ID = 305 and L305.DATE_DEL is null
    INTO :V$VAL
    DO
    BEGIN
        IF(V$VAL = 3) THEN V2 = 'Нет';
        ELSE IF(V$VAL = 2 and V2 is null) THEN V2 = 'Да';
    END

    /* Несоответствие в часах по обязательной части */
    V3 = NULL;

    SELECT COUNT(*)
    FROM LINKS L307
    /* Учебный план */
    JOIN VALR V2493 on V2493.OBJ_ID = L307.OBJ_ID and V2493.PARAM_ID = 2493 and V2493.IS_DEL = 0
    /* Учебная программа */
    JOIN LINKS L57 on L57.OBJ_ID = V2493.VAL and L57.PARENT_TYPE_ID = 57 and L57.DATE_DEL is null
    /* Уровень */
    JOIN VALL V1832 on V1832.OBJ_ID = L57.PARENT_ID and V1832.PARAM_ID = 1832 and V1832.IS_DEL = 0 and V1832.LISTVAL_ID in (5341, 5342)
    JOIN VALI V2487 on V2487.OBJ_ID = L307.OBJ_ID and V2487.PARAM_ID = 2487 and V2487.IS_DEL = 0 and V2487.VAL > 0
    WHERE L307.PARENT_ID = :OBJ_ID and L307.OBJ_TYPE_ID = 307 and L307.DATE_DEL is null
    INTO :V3;

    IF(V3 is null) THEN V3 = 0;

    /* Несоответствие в часах по части ОО */
    V4 = NULL;

    SELECT COUNT(*)
    FROM LINKS L309
    /* Учебный план */
    JOIN VALR V2498 on V2498.OBJ_ID = L309.OBJ_ID and V2498.PARAM_ID = 2498 and V2498.IS_DEL = 0
    /* Учебная программа */
    JOIN LINKS L57 on L57.OBJ_ID = V2498.VAL and L57.PARENT_TYPE_ID = 57 and L57.DATE_DEL is null
    /* Уровень */
    JOIN VALL V1832 on V1832.OBJ_ID = L57.PARENT_ID and V1832.PARAM_ID = 1832 and V1832.IS_DEL = 0 and V1832.LISTVAL_ID in (5341, 5342)
    JOIN VALI V2501 on V2501.OBJ_ID = L309.OBJ_ID and V2501.PARAM_ID = 2501 and V2501.IS_DEL = 0 and V2501.VAL > 0
    WHERE L309.PARENT_ID = :OBJ_ID and L309.OBJ_TYPE_ID = 309 and L309.DATE_DEL is null
    INTO :V4;

    IF(V4 is null) THEN V4 = 0;

    /* Пустые */
    V5 = NULL;
    V6 = NULL;

    /* Неутвержденные ПТП */
    V7 = NULL;

    SELECT COUNT(*)
    FROM LINKS L313
    /* Учебный план */
    JOIN VALR V2511 on V2511.OBJ_ID = L313.OBJ_ID and V2511.PARAM_ID = 2511 and V2511.IS_DEL = 0
    /* Учебная программа */
    JOIN LINKS L57 on L57.OBJ_ID = V2511.VAL and L57.PARENT_TYPE_ID = 57 and L57.DATE_DEL is null
    /* Уровень */
    JOIN VALL V1832 on V1832.OBJ_ID = L57.PARENT_ID and V1832.PARAM_ID = 1832 and V1832.IS_DEL = 0 and V1832.LISTVAL_ID in (5341, 5342)
    WHERE L313.PARENT_ID = :OBJ_ID and L313.OBJ_TYPE_ID = 313 and L313.DATE_DEL is null
    INTO :V7;

    IF(V7 is null) THEN V7 = 0;

    /* Соответствие часов ПТП и УП */
    V8 = NULL;

    SELECT COUNT(*)
    FROM LINKS L315
    /* Учебный план */
    JOIN VALR V2515 on V2515.OBJ_ID = L315.OBJ_ID and V2515.PARAM_ID = 2515 and V2515.IS_DEL = 0
    /* Учебная программа */
    JOIN LINKS L57 on L57.OBJ_ID = V2515.VAL and L57.PARENT_TYPE_ID = 57 and L57.DATE_DEL is null
    /* Уровень */
    JOIN VALL V1832 on V1832.OBJ_ID = L57.PARENT_ID and V1832.PARAM_ID = 1832 and V1832.IS_DEL = 0 and V1832.LISTVAL_ID in (5341, 5342)
    WHERE L315.PARENT_ID = :OBJ_ID and L315.OBJ_TYPE_ID = 315 and L315.DATE_DEL is null
    INTO :V8;

    IF(V8 is null) THEN V8 = 0;

    /* Количество несоответствий по выполнению УП */
    /* Средний процент выполнения */
    SELECT AVG(V2530.VAL)
    FROM LINKS L316
    /* Этап */
    JOIN VALR V2522 on V2522.OBJ_ID = L316.OBJ_ID and V2522.PARAM_ID = 2522 and V2522.IS_DEL = 0
    /* Учебный план */
    JOIN LINKS L50 on L50.OBJ_ID = V2522.VAL and L50.PARENT_TYPE_ID = 50 and L50.DATE_DEL is null
    /* Учебная программа */
    JOIN LINKS L57 on L57.OBJ_ID = L50.PARENT_ID and L57.PARENT_TYPE_ID = 57 and L57.DATE_DEL is null
    /* Уровень */
    JOIN VALL V1832 on V1832.OBJ_ID = L57.PARENT_ID and V1832.PARAM_ID = 1832 and V1832.IS_DEL = 0 and V1832.LISTVAL_ID in (5341, 5342)
    /* % выполнения */
    JOIN VALF V2530 on V2530.OBJ_ID = L316.OBJ_ID and V2530.PARAM_ID = 2530 and V2530.IS_DEL = 0
    WHERE L316.PARENT_ID = :OBJ_ID and L316.OBJ_TYPE_ID = 316 and L316.DATE_DEL is null
    INTO :V$VAL;

    /* Количество строк с отклонениями */
    V9 = NULL;

    SELECT COUNT(*)
    FROM LINKS L316
    /* Этап */
    JOIN VALR V2522 on V2522.OBJ_ID = L316.OBJ_ID and V2522.PARAM_ID = 2522 and V2522.IS_DEL = 0
    /* Учебный план */
    JOIN LINKS L50 on L50.OBJ_ID = V2522.VAL and L50.PARENT_TYPE_ID = 50 and L50.DATE_DEL is null
    /* Учебная программа */
    JOIN LINKS L57 on L57.OBJ_ID = L50.PARENT_ID and L57.PARENT_TYPE_ID = 57 and L57.DATE_DEL is null
    /* Уровень */
    JOIN VALL V1832 on V1832.OBJ_ID = L57.PARENT_ID and V1832.PARAM_ID = 1832 and V1832.IS_DEL = 0 and V1832.LISTVAL_ID in (5341, 5342)
    /* % выполнения */
    JOIN VALF V2530 on V2530.OBJ_ID = L316.OBJ_ID and V2530.PARAM_ID = 2530 and V2530.IS_DEL = 0
    WHERE L316.PARENT_ID = :OBJ_ID and L316.OBJ_TYPE_ID = 316 and L316.DATE_DEL is null and (ABS(V2530.VAL - :V$VAL) > (:V$VAL * 0.1))
    INTO :V9;

    IF(V9 is null) THEN V9 = 0;

    SUSPEND;

    /* Третья группа */
    LEVEL_NAME = 'Среднее образование';

    /* Соответствие общего количества часов УП */
    V1 = NULL;

    FOR SELECT V2758.LISTVAL_ID
    FROM LINKS L357
    /* Учебный план */
    JOIN VALR V2745 on V2745.OBJ_ID = L357.OBJ_ID and V2745.PARAM_ID = 2745 and V2745.IS_DEL = 0
    /* Учебная программа */
    JOIN LINKS L57 on L57.OBJ_ID = V2745.VAL and L57.PARENT_TYPE_ID = 57 and L57.DATE_DEL is null
    /* Уровень */
    JOIN VALL V1832 on V1832.OBJ_ID = L57.PARENT_ID and V1832.PARAM_ID = 1832 and V1832.IS_DEL = 0 and V1832.LISTVAL_ID in (5343, 5344)
    JOIN VALL V2758 on V2758.OBJ_ID = L357.OBJ_ID and V2758.PARAM_ID = 2758 and V2758.IS_DEL = 0
    WHERE L357.PARENT_ID = :OBJ_ID and L357.OBJ_TYPE_ID = 357 and L357.DATE_DEL is null
    INTO :V$VAL
    DO
    BEGIN
        IF(V$VAL = 3) THEN V1 = 'Нет';
        ELSE IF(V$VAL = 2 and V1 is null) THEN V1 = 'Да';
    END

    /* Соответствие количества часов обязательной части УП */
    V2 = NULL;

    FOR SELECT V2752.LISTVAL_ID
    FROM LINKS L357
    /* Учебный план */
    JOIN VALR V2745 on V2745.OBJ_ID = L357.OBJ_ID and V2745.PARAM_ID = 2745 and V2745.IS_DEL = 0
    /* Учебная программа */
    JOIN LINKS L57 on L57.OBJ_ID = V2745.VAL and L57.PARENT_TYPE_ID = 57 and L57.DATE_DEL is null
    /* Уровень */
    JOIN VALL V1832 on V1832.OBJ_ID = L57.PARENT_ID and V1832.PARAM_ID = 1832 and V1832.IS_DEL = 0 and V1832.LISTVAL_ID in (5343, 5344)
    JOIN VALL V2752 on V2752.OBJ_ID = L357.OBJ_ID and V2752.PARAM_ID = 2752 and V2752.IS_DEL = 0
    WHERE L357.PARENT_ID = :OBJ_ID and L357.OBJ_TYPE_ID = 357 and L357.DATE_DEL is null
    INTO :V$VAL
    DO
    BEGIN
        IF(V$VAL = 3) THEN V2 = 'Нет';
        ELSE IF(V$VAL = 2 and V2 is null) THEN V2 = 'Да';
    END

    /* Пустые */
    V3 = NULL;
    V4 = NULL;

    /* Профильные предметы */
    V5 = '';

    FOR SELECT V2751.VAL
    FROM LINKS L357
    /* Учебный план */
    JOIN VALR V2745 on V2745.OBJ_ID = L357.OBJ_ID and V2745.PARAM_ID = 2745 and V2745.IS_DEL = 0
    /* Учебная программа */
    JOIN LINKS L57 on L57.OBJ_ID = V2745.VAL and L57.PARENT_TYPE_ID = 57 and L57.DATE_DEL is null
    /* Уровень */
    JOIN VALL V1832 on V1832.OBJ_ID = L57.PARENT_ID and V1832.PARAM_ID = 1832 and V1832.IS_DEL = 0 and V1832.LISTVAL_ID in (5343, 5344)
    JOIN VALS V2751 on V2751.OBJ_ID = L357.OBJ_ID and V2751.PARAM_ID = 2751 and V2751.IS_DEL = 0
    WHERE L357.PARENT_ID = :OBJ_ID and L357.OBJ_TYPE_ID = 357 and L357.DATE_DEL is null
    INTO :V$STR
    DO
    BEGIN
        -- Подсчет количества предметов в списке
        V$N = 0;
        WHILE(V$STR <> '') DO
        BEGIN
            V$N = V$N + 1;
            V$P = position(';', V$STR);
            IF(V$P <= 0) THEN V$P = 9999;
            V$STR = substring(V$STR from V$P + 1);
        END
        --
        IF(V5 <> '') THEN V5 = V5 || ',';
        V5 = V5 || CAST(V$N as varchar(10));
    END

    /* Соответствие по часам профильных предметов */
    V6 = NULL;

    SELECT COUNT(*)
    FROM LINKS L360
    /* Учебный план */
    JOIN VALR V2763 on V2763.OBJ_ID = L360.OBJ_ID and V2763.PARAM_ID = 2763 and V2763.IS_DEL = 0
    /* Учебная программа */
    JOIN LINKS L57 on L57.OBJ_ID = V2763.VAL and L57.PARENT_TYPE_ID = 57 and L57.DATE_DEL is null
    /* Уровень */
    JOIN VALL V1832 on V1832.OBJ_ID = L57.PARENT_ID and V1832.PARAM_ID = 1832 and V1832.IS_DEL = 0 and V1832.LISTVAL_ID in (5343, 5344)
    WHERE L360.PARENT_ID = :OBJ_ID and L360.OBJ_TYPE_ID = 360 and L360.DATE_DEL is null
    INTO :V6;

    IF(V6 is null) THEN V6 = 0;

    /* Неутвержденные ПТП */
    V7 = NULL;

    SELECT COUNT(*)
    FROM LINKS L313
    /* Учебный план */
    JOIN VALR V2511 on V2511.OBJ_ID = L313.OBJ_ID and V2511.PARAM_ID = 2511 and V2511.IS_DEL = 0
    /* Учебная программа */
    JOIN LINKS L57 on L57.OBJ_ID = V2511.VAL and L57.PARENT_TYPE_ID = 57 and L57.DATE_DEL is null
    /* Уровень */
    JOIN VALL V1832 on V1832.OBJ_ID = L57.PARENT_ID and V1832.PARAM_ID = 1832 and V1832.IS_DEL = 0 and V1832.LISTVAL_ID in (5343, 5344)
    WHERE L313.PARENT_ID = :OBJ_ID and L313.OBJ_TYPE_ID = 313 and L313.DATE_DEL is null
    INTO :V7;

    IF(V7 is null) THEN V7 = 0;

    /* Соответствие часов ПТП и УП */
    V8 = NULL;

    SELECT COUNT(*)
    FROM LINKS L315
    /* Учебный план */
    JOIN VALR V2515 on V2515.OBJ_ID = L315.OBJ_ID and V2515.PARAM_ID = 2515 and V2515.IS_DEL = 0
    /* Учебная программа */
    JOIN LINKS L57 on L57.OBJ_ID = V2515.VAL and L57.PARENT_TYPE_ID = 57 and L57.DATE_DEL is null
    /* Уровень */
    JOIN VALL V1832 on V1832.OBJ_ID = L57.PARENT_ID and V1832.PARAM_ID = 1832 and V1832.IS_DEL = 0 and V1832.LISTVAL_ID in (5343, 5344)
    WHERE L315.PARENT_ID = :OBJ_ID and L315.OBJ_TYPE_ID = 315 and L315.DATE_DEL is null
    INTO :V8;

    IF(V8 is null) THEN V8 = 0;

    /* Количество несоответствий по выполнению УП */
    /* Средний процент выполнения */
    SELECT AVG(V2530.VAL)
    FROM LINKS L316
    /* Этап */
    JOIN VALR V2522 on V2522.OBJ_ID = L316.OBJ_ID and V2522.PARAM_ID = 2522 and V2522.IS_DEL = 0
    /* Учебный план */
    JOIN LINKS L50 on L50.OBJ_ID = V2522.VAL and L50.PARENT_TYPE_ID = 50 and L50.DATE_DEL is null
    /* Учебная программа */
    JOIN LINKS L57 on L57.OBJ_ID = L50.PARENT_ID and L57.PARENT_TYPE_ID = 57 and L57.DATE_DEL is null
    /* Уровень */
    JOIN VALL V1832 on V1832.OBJ_ID = L57.PARENT_ID and V1832.PARAM_ID = 1832 and V1832.IS_DEL = 0 and V1832.LISTVAL_ID in (5343, 5344)
    /* % выполнения */
    JOIN VALF V2530 on V2530.OBJ_ID = L316.OBJ_ID and V2530.PARAM_ID = 2530 and V2530.IS_DEL = 0
    WHERE L316.PARENT_ID = :OBJ_ID and L316.OBJ_TYPE_ID = 316 and L316.DATE_DEL is null
    INTO :V$VAL;

    /* Количество строк с отклонениями */
    V9 = NULL;

    SELECT COUNT(*)
    FROM LINKS L316
    /* Этап */
    JOIN VALR V2522 on V2522.OBJ_ID = L316.OBJ_ID and V2522.PARAM_ID = 2522 and V2522.IS_DEL = 0
    /* Учебный план */
    JOIN LINKS L50 on L50.OBJ_ID = V2522.VAL and L50.PARENT_TYPE_ID = 50 and L50.DATE_DEL is null
    /* Учебная программа */
    JOIN LINKS L57 on L57.OBJ_ID = L50.PARENT_ID and L57.PARENT_TYPE_ID = 57 and L57.DATE_DEL is null
    /* Уровень */
    JOIN VALL V1832 on V1832.OBJ_ID = L57.PARENT_ID and V1832.PARAM_ID = 1832 and V1832.IS_DEL = 0 and V1832.LISTVAL_ID in (5343, 5344)
    /* % выполнения */
    JOIN VALF V2530 on V2530.OBJ_ID = L316.OBJ_ID and V2530.PARAM_ID = 2530 and V2530.IS_DEL = 0
    WHERE L316.PARENT_ID = :OBJ_ID and L316.OBJ_TYPE_ID = 316 and L316.DATE_DEL is null and (ABS(V2530.VAL - :V$VAL) > (:V$VAL * 0.1))
    INTO :V9;

    IF(V9 is null) THEN V9 = 0;

    SUSPEND;

  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE REPORT_UP_CONTROL_P2 (
    OBJ_ID BIGINT)
RETURNS (
    OO_NAME VARCHAR(1000),
    OO_DISTRICT VARCHAR(400),
    V1 VARCHAR(10),
    V2 VARCHAR(10),
    V3 VARCHAR(10),
    V4 VARCHAR(10),
    V5 VARCHAR(10),
    V6 VARCHAR(10),
    V7 VARCHAR(10),
    V8 INTEGER,
    V9 INTEGER,
    PUPIL_ALL INTEGER,
    PUPIL_CNT INTEGER,
    V14 INTEGER,
    V11 INTEGER,
    V12 INTEGER,
    V13 INTEGER)
AS
DECLARE VARIABLE V$SCHOOL_ID BIGINT;
DECLARE VARIABLE V$VAL INTEGER;
DECLARE VARIABLE V$TMP VARCHAR(1000);
begin

  /* Перерасчет СМИР */
  SELECT COUNT(*) FROM EXPORT_LOCAL_DO_FUNC INTO :V$VAL;

  /* Выбираем сразу сечение район-школа */
  /* Отчет может быть выбран на уровнях (OBJ_ID): Мониторинг, Школа, Район, Регион  */

  FOR
    SELECT L2.PARENT_ID, V2.VAL, R111.VAL, CNT.VAL
    FROM LINKS L2
    JOIN VALS V2 on V2.OBJ_ID = L2.PARENT_ID and V2.PARAM_ID = 2 and V2.IS_DEL = 0
    JOIN VALL V11 on V11.OBJ_ID = L2.PARENT_ID and V11.PARAM_ID = 11 and V11.IS_DEL = 0 and V11.LISTVAL_ID not in (978, 2216, 979, 980)
    -- исключаем частные организации
    JOIN VALL V8 on V8.OBJ_ID = L2.PARENT_ID and V8.PARAM_ID = 8 and V8.IS_DEL = 0 and V8.LISTVAL_ID <> 5404
    -- район
    LEFT JOIN LINKS L111 on L111.OBJ_ID = L2.PARENT_ID and L111.PARENT_TYPE_ID = 111 and L111.DATE_DEL is null
    LEFT JOIN VALL V665 on V665.OBJ_ID = L111.PARENT_ID and V665.PARAM_ID in (665, 1406) and V665.IS_DEL = 0
    LEFT JOIN LISTVALS LV111 on LV111.LISTVAL_ID = V665.LISTVAL_ID
    LEFT JOIN RES R111 on R111.RES_ID = LV111.RES_ID and R111.LANG_CODE = 'RU'
    -- регион
    LEFT JOIN LINKS L112 on L112.OBJ_ID = L111.PARENT_ID and L112.PARENT_TYPE_ID = 112 and L112.DATE_DEL is null
    -- количество учащихся (контингент)
    LEFT JOIN DO_FUNC_COUNT(L2.PARENT_ID, 6) CNT ON 1 = 1
    WHERE L2.PARENT_TYPE_ID = 2 and L2.OBJ_TYPE_ID = 162 and L2.DATE_DEL is null and
      (L2.OBJ_ID = :OBJ_ID or L2.PARENT_ID = :OBJ_ID or L111.PARENT_ID = :OBJ_ID or L112.PARENT_ID = :OBJ_ID)
    ORDER BY 3, 2
    INTO :V$SCHOOL_ID, :OO_NAME, :OO_DISTRICT, :PUPIL_ALL
  DO
  BEGIN

    /* Пропускаем неподведомственные организации */
    SELECT V6.VAL
    FROM VALS V6
    WHERE V6.OBJ_ID = :V$SCHOOL_ID and V6.PARAM_ID = 6 and V6.IS_DEL = 0
    INTO :V$TMP;

    /* Восстанавливаем обратно ID объекта мониторинг */
    OBJ_ID = NULL;

    SELECT L162.OBJ_ID
    FROM LINKS L162
    WHERE L162.PARENT_ID = :V$SCHOOL_ID and L162.OBJ_TYPE_ID = 162 and L162.DATE_DEL is null
    INTO :OBJ_ID;

    /* Медицинский комплекс */
    V$VAL = 0;

    SELECT FIRST 1 1
    FROM LINKS L325
    JOIN VALS V2555 on V2555.OBJ_ID = L325.OBJ_ID and V2555.PARAM_ID = 2555 and V2555.IS_DEL = 0 and UPPER(V2555.VAL) LIKE '%МЕДИЦИНСКИЙ КОМПЛЕКС%'
    WHERE L325.PARENT_ID = :OBJ_ID and L325.OBJ_TYPE_ID = 325 and L325.DATE_DEL is null
    INTO :V$VAL;

    IF(V$VAL > 0) THEN V1 = 'Да'; ELSE V1 = 'Нет';

    /* Спортивный комплекс */
    V$VAL = 0;

    SELECT FIRST 1 1
    FROM LINKS L325
    JOIN VALS V2555 on V2555.OBJ_ID = L325.OBJ_ID and V2555.PARAM_ID = 2555 and V2555.IS_DEL = 0 and UPPER(V2555.VAL) LIKE '%СПОРТИВНЫЙ КОМПЛЕКС%'
    WHERE L325.PARENT_ID = :OBJ_ID and L325.OBJ_TYPE_ID = 325 and L325.DATE_DEL is null
    INTO :V$VAL;

    IF(V$VAL > 0) THEN V2 = 'Да'; ELSE V2 = 'Нет';

    /* Библиотека */
    V$VAL = 0;

    SELECT FIRST 1 1
    FROM LINKS L325
    JOIN VALS V2555 on V2555.OBJ_ID = L325.OBJ_ID and V2555.PARAM_ID = 2555 and V2555.IS_DEL = 0 and UPPER(V2555.VAL) LIKE '%БИБЛИОТЕКА%'
    WHERE L325.PARENT_ID = :OBJ_ID and L325.OBJ_TYPE_ID = 325 and L325.DATE_DEL is null
    INTO :V$VAL;

    IF(V$VAL > 0) THEN V3 = 'Да'; ELSE V3 = 'Нет';

    /* Столовая */
    V$VAL = 0;

    SELECT FIRST 1 1
    FROM LINKS L325
    JOIN VALS V2555 on V2555.OBJ_ID = L325.OBJ_ID and V2555.PARAM_ID = 2555 and V2555.IS_DEL = 0 and UPPER(V2555.VAL) LIKE '%СТОЛОВАЯ%'
    WHERE L325.PARENT_ID = :OBJ_ID and L325.OBJ_TYPE_ID = 325 and L325.DATE_DEL is null
    INTO :V$VAL;

    IF(V$VAL > 0) THEN V4 = 'Да'; ELSE V4 = 'Нет';

    /* Специализированные кабинеты */
    V$VAL = 0;

    SELECT FIRST 1 1
    FROM LINKS L325
    JOIN VALS V25X2 on V25X2.OBJ_ID = L325.OBJ_ID and V25X2.PARAM_ID IN (2572, 2582) and V25X2.IS_DEL = 0 and
        ((UPPER(V25X2.VAL) LIKE '%БИОЛОГИИ%') or (UPPER(V25X2.VAL) LIKE '%ФИЗИКИ%') or (UPPER(V25X2.VAL) LIKE '%ХИМИИ%') or
         (UPPER(V25X2.VAL) LIKE '%ЯЗЫКА%') or (UPPER(V25X2.VAL) LIKE '%ГЕОГРАФИИ%') or (UPPER(V25X2.VAL) LIKE '%МАТЕМАТИКИ%') or
         (UPPER(V25X2.VAL) LIKE '%ИСТОРИИ%')
        )
    WHERE L325.PARENT_ID = :OBJ_ID and L325.OBJ_TYPE_ID IN (328, 329) and L325.DATE_DEL is null
    INTO :V$VAL;

    IF(V$VAL > 0) THEN V5 = 'Да'; ELSE V5 = 'Нет';

    /* Учительская */
    V$VAL = 0;

    SELECT FIRST 1 1
    FROM LINKS L325
    JOIN VALS V2555 on V2555.OBJ_ID = L325.OBJ_ID and V2555.PARAM_ID = 2555 and V2555.IS_DEL = 0 and UPPER(V2555.VAL) LIKE '%УЧИТЕЛЬСКАЯ%'
    WHERE L325.PARENT_ID = :OBJ_ID and L325.OBJ_TYPE_ID = 325 and L325.DATE_DEL is null
    INTO :V$VAL;

    IF(V$VAL > 0) THEN V6 = 'Да'; ELSE V6 = 'Нет';

    /* Компьютерные классы */
    V7 = NULL;

    SELECT VAL
    FROM MONITORING_DO_FUNC(:V$SCHOOL_ID, 1452, 1)
    INTO :V7;

    IF((V7 IS NULL) or (V7 = '')) THEN V7 = 'Нет';
    ELSE IF(CAST(V7 as INTEGER) = 0) THEN V7 = 'Нет';
    ELSE V7 = 'Да';

    /* Требования по квалификации */
    V8 = NULL;
    V9 = NULL;

    SELECT SUM(V2664.VAL)
    FROM LINKS L340
    JOIN VALI V2664 on V2664.OBJ_ID = L340.OBJ_ID and V2664.PARAM_ID = 2664 and V2664.IS_DEL = 0
    WHERE L340.PARENT_ID = :OBJ_ID and L340.OBJ_TYPE_ID = 340 and L340.DATE_DEL is null
    INTO :V8;

    SELECT SUM(V2665.VAL)
    FROM LINKS L340
    JOIN VALI V2665 on V2665.OBJ_ID = L340.OBJ_ID and V2665.PARAM_ID = 2665 and V2665.IS_DEL = 0
    WHERE L340.PARENT_ID = :OBJ_ID and L340.OBJ_TYPE_ID = 340 and L340.DATE_DEL is null
    INTO :V9;

    /* Обеспеченность учебниками */
    V11 = NULL;
    V12 = NULL;
    V13 = NULL;
    V14 = NULL;

    SELECT SUM(V2685.VAL), SUM(V2688.VAL), SUM(V2689.VAL + V2690.VAL + V2691.VAL), SUM(V2772.VAL), SUM(V2686.VAL)
    FROM LINKS L345
    /* Количество учащихся */
    JOIN VALI V2685 on V2685.OBJ_ID = L345.OBJ_ID and V2685.PARAM_ID = 2685 and V2685.IS_DEL = 0
    /* Обеспечены учебниками из ФПУ - формально лишнее */
    JOIN VALI V2686 on V2686.OBJ_ID = L345.OBJ_ID and V2686.PARAM_ID = 2686 and V2686.IS_DEL = 0
    /* Не обеспечены по 1 предмету */
    JOIN VALI V2688 on V2688.OBJ_ID = L345.OBJ_ID and V2688.PARAM_ID = 2688 and V2688.IS_DEL = 0
    /* Не обеспечены по 2 предметам */
    JOIN VALI V2689 on V2689.OBJ_ID = L345.OBJ_ID and V2689.PARAM_ID = 2689 and V2689.IS_DEL = 0
    /* Не обеспечены по 3 предметам */
    JOIN VALI V2690 on V2690.OBJ_ID = L345.OBJ_ID and V2690.PARAM_ID = 2690 and V2690.IS_DEL = 0
    /* Не обеспечены по 4 предметам */
    JOIN VALI V2691 on V2691.OBJ_ID = L345.OBJ_ID and V2691.PARAM_ID = 2691 and V2691.IS_DEL = 0
    /* Не обеспечены по 5+ предметам */
    JOIN VALI V2772 on V2772.OBJ_ID = L345.OBJ_ID and V2772.PARAM_ID = 2772 and V2772.IS_DEL = 0
    WHERE L345.PARENT_ID = :OBJ_ID and L345.OBJ_TYPE_ID = 345 and L345.DATE_DEL is null
    INTO :PUPIL_CNT, :V11, :V12, :V13, :V14;

    -- Только подведомственные школы
    IF(V$TMP = 'Комитет по образованию Санкт-Петербурга') THEN SUSPEND;

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE REPORT_VAL_GET (
    I$REPORT_ID BIGINT,
    I$QUERY_NUM SMALLINT,
    I$OBJ_ID BIGINT = NULL,
    I$USER_ID BIGINT = 1,
    I$PARAM_VAL BIGINT = NULL,
    I$PARAM2_VAL BIGINT = NULL)
RETURNS (
    V VARCHAR(4000),
    V2 VARCHAR(1000),
    V3 VARCHAR(255),
    V4 VARCHAR(255),
    V5 VARCHAR(255))
AS
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$VAL_ID BIGINT;
DECLARE VARIABLE V$I INTEGER;
DECLARE VARIABLE V$S VARCHAR(4000);
DECLARE VARIABLE V$I2 INTEGER;
DECLARE VARIABLE V$F SMALLINT;
DECLARE VARIABLE Y SMALLINT;
DECLARE VARIABLE DT DATE;
DECLARE VARIABLE V$YEAR SMALLINT;
DECLARE VARIABLE N INTEGER;
BEGIN
    Y = EXTRACT(YEAR FROM CURRENT_DATE);
    DT = '1.09.' || Y;
        
    IF (CURRENT_DATE < DT) THEN
    BEGIN
        V$YEAR = Y;
    END
    ELSE
    BEGIN
        V$YEAR = Y + 1;
    END

    IF (:I$REPORT_ID = 301) THEN
    -- Форма Т-2
    BEGIN
        -- page #1
        IF (I$QUERY_NUM < 103) THEN
        BEGIN
            SELECT OBJ_ID FROM OBJECT_PARENTS_GET(:I$OBJ_ID, 2)
            INTO :I$OBJ_ID;
        END
        IF (I$QUERY_NUM = 100) THEN
        BEGIN
            SELECT V FROM VAL_GET(:I$OBJ_ID, 16)
            INTO :V;
            IF (SUBSTRING(:V FROM 1 FOR 1) = '0') THEN
            BEGIN
                V = ASCII_CHAR(10) || :V || ASCII_CHAR(10);
            END
        END
        IF (I$QUERY_NUM = 101) THEN
        BEGIN
            SELECT V FROM VAL_GET(:I$OBJ_ID, 5)
            INTO :V;
            SELECT VAL FROM STRING_PART(:V, 0, 70)
            INTO :V;
        END
        IF (I$QUERY_NUM = 102) THEN
        BEGIN
            SELECT V FROM VAL_GET(:I$OBJ_ID, 5)
            INTO :V;
            SELECT TRIM(
                (SELECT VAL FROM STRING_PART(:V, 1, 70)) || ' ' ||
                (SELECT VAL FROM STRING_PART(:V, 2, 70)))
            FROM RDB$DATABASE
            INTO :V;
        END
        IF (I$QUERY_NUM = 103) THEN
        BEGIN
            V = CURRENT_DATE;
        END
        IF (I$QUERY_NUM = 104) THEN
        BEGIN
            SELECT V FROM VAL_GET(:I$OBJ_ID, 273)
            INTO :V;
        END
        IF (I$QUERY_NUM = 105) THEN
        BEGIN
            SELECT V FROM VAL_GET(:I$OBJ_ID, 250)
            INTO :V;
        END
        IF (I$QUERY_NUM = 106) THEN
        BEGIN
            SELECT FIRST 1 ''''||V571.VAL
            FROM LINKS L12
            JOIN VALL V51 ON V51.OBJ_ID = L12.OBJ_ID
              AND V51.PARAM_ID = 51
              AND V51.IS_DEL = 0
              AND V51.LISTVAL_ID = 1384
            JOIN VALS V571 ON V571.OBJ_ID = L12.OBJ_ID
              AND V571.PARAM_ID = 571
              AND V571.IS_DEL = 0
            WHERE L12.PARENT_ID = :I$OBJ_ID
              AND L12.OBJ_TYPE_ID = 12
              AND L12.DATE_DEL IS NULL
            INTO :V;
        END
        IF (I$QUERY_NUM = 107) THEN
        BEGIN
            SELECT SUBSTRING(V FROM 1 FOR 1) FROM VAL_GET(:I$OBJ_ID, 59)
            INTO :V;
        END
        IF (I$QUERY_NUM IN (108, 109, 111, 112)) THEN
        BEGIN
            SELECT FIRST 1
                L15.OBJ_ID,
                V587.LISTVAL_ID
            FROM LINKS L15
            JOIN VALL V72 ON V72.OBJ_ID = L15.OBJ_ID
              AND V72.PARAM_ID = 72
              AND V72.IS_DEL = 0
            JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID
              AND V73.PARAM_ID = 73
              AND V73.IS_DEL = 0
              AND V73.VAL <= CURRENT_DATE
            LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID
              AND V74.PARAM_ID = 74
              AND V74.IS_DEL = 0
            JOIN VALL V587 ON V587.OBJ_ID = L15.OBJ_ID
              AND V587.PARAM_ID = 587
              AND V587.IS_DEL = 0
            WHERE L15.OBJ_TYPE_ID = 15
              AND L15.PARENT_ID = :I$OBJ_ID
              AND L15.DATE_DEL IS NULL
            ORDER BY
                IIF(V74.VAL IS NULL OR V74.VAL >= CURRENT_DATE, 0, 1),
                V72.LISTVAL_ID,
                V587.LISTVAL_ID
            INTO :V$OBJ_ID, :V$VAL_ID;

            IF (I$QUERY_NUM = 108) THEN
            BEGIN
                V = CASE :V$VAL_ID
                        WHEN 209 THEN 'почасовой'
                        WHEN 1720 THEN 'временный'
                        WHEN 12824 THEN 'временный'
                        ELSE 'постоянный'
                    END;
            END
            IF (I$QUERY_NUM = 109) THEN
            BEGIN
                V = IIF(:V$VAL_ID IN (208, 209), 'по совместительству', 'основная');
            END
            IF (I$QUERY_NUM = 111) THEN
            BEGIN
                SELECT V FROM VAL_GET(:V$OBJ_ID, 1638)
                INTO :V;
            END
            IF (I$QUERY_NUM = 112) THEN
            BEGIN
                SELECT D FROM VAL_GET(:V$OBJ_ID, 1639)
                INTO :V;
            END
        END
        IF (I$QUERY_NUM = 110) THEN
        BEGIN
            SELECT SUBSTRING(V FROM 1 FOR 1)
            FROM VAL_GET(:I$OBJ_ID, 239)
            INTO :V;
        END
        IF (I$QUERY_NUM = 113) THEN
        BEGIN
            SELECT V FROM VAL_GET(:I$OBJ_ID, 59)
            INTO :V;
        END
        IF (I$QUERY_NUM = 114) THEN
        BEGIN
            SELECT V FROM VAL_GET(:I$OBJ_ID, 60)
            INTO :V;
        END
        IF (I$QUERY_NUM = 115) THEN
        BEGIN
            SELECT V FROM VAL_GET(:I$OBJ_ID, 61)
            INTO :V;
        END
        IF (I$QUERY_NUM = 116) THEN
        BEGIN
            SELECT DT FROM CURRENT_DATE_GET((SELECT D FROM VAL_GET(:I$OBJ_ID, 241)), 'DD MONTH YYYY')
            INTO :V;
        END
        IF (I$QUERY_NUM = 117) THEN
        BEGIN
            SELECT D FROM VAL_GET(:I$OBJ_ID, 241)
            INTO :V;
        END
        IF (I$QUERY_NUM = 118) THEN
        BEGIN
            SELECT V FROM VAL_GET(:I$OBJ_ID, 244)
            INTO :V;
        END
        IF (I$QUERY_NUM = 120) THEN
        BEGIN
            SELECT V FROM VAL_GET(:I$OBJ_ID, 243)
            INTO :V;
        END
        IF (I$QUERY_NUM = 128) THEN
        BEGIN
            SELECT V FROM VAL_GET(:I$OBJ_ID, 278)
            INTO :V;
        END
        IF (I$QUERY_NUM BETWEEN 130 AND 151) THEN
        BEGIN
            FOR SELECT FIRST 2 L33.OBJ_ID
                FROM LINKS L33
                LEFT JOIN VALL V284 ON V284.OBJ_ID = L33.OBJ_ID
                  AND V284.PARAM_ID = 284
                  AND V284.IS_DEL = 0
                WHERE L33.OBJ_TYPE_ID = 33
                  AND L33.PARENT_ID = :I$OBJ_ID
                  AND L33.DATE_DEL IS NULL
                  AND (V284.LISTVAL_ID IS NULL OR V284.LISTVAL_ID NOT IN (3031, 3032, 5256))
                ORDER BY V284.LISTVAL_ID
                INTO :V$OBJ_ID
            DO
            BEGIN
                IF (I$QUERY_NUM = 130) THEN
                BEGIN
                    SELECT V FROM VAL_GET(:V$OBJ_ID, 285)
                    INTO :V;
                END
                IF (I$QUERY_NUM = 133) THEN
                BEGIN
                    SELECT V FROM VAL_GET(:V$OBJ_ID, 286)
                    INTO :V;
                END
                IF (I$QUERY_NUM = 134) THEN
                BEGIN
                    SELECT V FROM VAL_GET(:V$OBJ_ID, 287)
                    INTO :V;
                END
                IF (I$QUERY_NUM = 135) THEN
                BEGIN
                    SELECT V FROM VAL_GET(:V$OBJ_ID, 288)
                    INTO :V;
                    IF (SUBSTRING(:V FROM 1 FOR 1) = '0') THEN
                    BEGIN
                        V = ASCII_CHAR(10) || :V || ASCII_CHAR(10);
                    END
                END
                IF (I$QUERY_NUM = 136) THEN
                BEGIN
                    SELECT EXTRACT(YEAR FROM D) FROM VAL_GET(:V$OBJ_ID, 290)
                    INTO :V;
                END
                IF (I$QUERY_NUM = 137) THEN
                BEGIN
                    SELECT V FROM VAL_GET(:V$OBJ_ID, 292)
                    INTO :V;
                END
                IF (I$QUERY_NUM = 139) THEN
                BEGIN
                    SELECT V FROM VAL_GET(:V$OBJ_ID, 291)
                    INTO :V;
                    WHILE (:V <> '' AND SUBSTRING(:V FROM 1 FOR 1) IN ('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ' ', '.')) DO
                    BEGIN
                        V = SUBSTRING(:V FROM 2 FOR CHAR_LENGTH(:V));
                    END
                END
                IF (I$QUERY_NUM = 140) THEN
                BEGIN
                    SELECT V FROM VAL_GET(:V$OBJ_ID, 291)
                    INTO :V$S;
                    V = '';
                    V$I = 1;
                    WHILE (CHAR_LENGTH(:V$S) >= :V$I AND SUBSTRING(:V$S FROM :V$I FOR 1) IN ('0', '1', '2', '3', '4', '5', '6', '7', '8', '9')) DO
                    BEGIN
                        V = :V || SUBSTRING(:V$S FROM :V$I FOR 1);
                        V$I = :V$I + 1;
                    END
                    IF (SUBSTRING(:V FROM 1 FOR 1) = '0') THEN
                    BEGIN
                        V = ASCII_CHAR(10) || :V || ASCII_CHAR(10);
                    END
                END
                I$QUERY_NUM = :I$QUERY_NUM - 11;
            END
        END
        IF (I$QUERY_NUM BETWEEN 152 AND 159) THEN
        BEGIN
            SELECT FIRST 1 L33.OBJ_ID
            FROM LINKS L33
            JOIN VALL V284 ON V284.OBJ_ID = L33.OBJ_ID
              AND V284.PARAM_ID = 284
              AND V284.IS_DEL = 0
              AND V284.LISTVAL_ID IN (3031, 3032, 5256)
            WHERE L33.OBJ_TYPE_ID = 33
              AND L33.PARENT_ID = :I$OBJ_ID
              AND L33.DATE_DEL IS NULL
            ORDER BY V284.LISTVAL_ID
            INTO :V$OBJ_ID;
            IF (I$QUERY_NUM = 152) THEN
            BEGIN
                SELECT V FROM VAL_GET(:V$OBJ_ID, 284)
                INTO :V;
            END
            IF (I$QUERY_NUM = 154) THEN
            BEGIN
                SELECT V FROM VAL_GET(:V$OBJ_ID, 285)
                INTO :V;
            END
            IF (I$QUERY_NUM = 155) THEN
            BEGIN
                SELECT V FROM VAL_GET(:V$OBJ_ID, 286)
                INTO :V$S;

                SELECT TRIM(
                    (SELECT V FROM VAL_GET(:V$OBJ_ID, 287)) || ' ' ||
                    (SELECT V FROM VAL_GET(:V$OBJ_ID, 288)))
                FROM RDB$DATABASE
                INTO :V;

                IF (:V$S <> '' AND :V <> '') THEN
                BEGIN
                    V$S = :V$S || ', ';
                END
                V$S = :V$S || :V;

                SELECT D FROM VAL_GET(:V$OBJ_ID, 290)
                INTO :V;

                IF (:V$S <> '' AND :V <> '') THEN
                BEGIN
                    V$S = :V$S || ', ';
                END
                V = :V$S || :V;
            END
            IF (I$QUERY_NUM = 156) THEN
            BEGIN
                SELECT EXTRACT(YEAR FROM D) FROM VAL_GET(:V$OBJ_ID, 290)
                INTO :V;
            END
            IF (I$QUERY_NUM IN (157, 158)) THEN
            BEGIN
                SELECT V FROM VAL_GET(:V$OBJ_ID, 291)
                INTO :V;
                WHILE (:V <> '' AND SUBSTRING(:V FROM 1 FOR 1) IN ('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ' ', '.')) DO
                BEGIN
                    V = SUBSTRING(:V FROM 2 FOR CHAR_LENGTH(:V));
                END
                SELECT VAL FROM STRING_PART(:V, :I$QUERY_NUM - 157, 60)
                INTO :V;
            END
            IF (I$QUERY_NUM = 159) THEN
            BEGIN
                SELECT V FROM VAL_GET(:V$OBJ_ID, 291)
                INTO :V$S;
                V = '';
                V$I = 1;
                WHILE (CHAR_LENGTH(:V$S) >= :V$I AND SUBSTRING(:V$S FROM :V$I FOR 1) IN ('0', '1', '2', '3', '4', '5', '6', '7', '8', '9')) DO
                BEGIN
                    V = :V || SUBSTRING(:V$S FROM :V$I FOR 1);
                    V$I = :V$I + 1;
                END
                IF (SUBSTRING(:V FROM 1 FOR 1) = '0') THEN
                BEGIN
                    V = ASCII_CHAR(10) || :V || ASCII_CHAR(10);
                END
            END
        END
        IF (I$QUERY_NUM BETWEEN 160 AND 163) THEN
        BEGIN
            FOR SELECT FIRST 2 L15.OBJ_ID
                FROM LINKS L15
                JOIN VALL V72 ON V72.OBJ_ID = L15.OBJ_ID
                  AND V72.PARAM_ID = 72
                  AND V72.IS_DEL = 0
                JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID
                  AND V73.PARAM_ID = 73
                  AND V73.IS_DEL = 0
                  AND V73.VAL <= CURRENT_DATE
                LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID
                  AND V74.PARAM_ID = 74
                  AND V74.IS_DEL = 0
                JOIN VALL V587 ON V587.OBJ_ID = L15.OBJ_ID
                  AND V587.PARAM_ID = 587
                  AND V587.IS_DEL = 0
                WHERE L15.OBJ_TYPE_ID = 15
                  AND L15.PARENT_ID = :I$OBJ_ID
                  AND L15.DATE_DEL IS NULL
                ORDER BY
                    IIF(V74.VAL IS NULL OR V74.VAL >= CURRENT_DATE, 0, 1),
                    V72.LISTVAL_ID,
                    V587.LISTVAL_ID
                INTO :V$OBJ_ID
            DO
            BEGIN
                IF (I$QUERY_NUM = 160) THEN
                BEGIN
                    SELECT V FROM VAL_GET(:V$OBJ_ID, 69)
                    INTO :V;
                END
                I$QUERY_NUM = :I$QUERY_NUM - 2;
            END
        END
        -- page #2
        IF (I$QUERY_NUM = 200) THEN
        BEGIN
            SELECT DT FROM CURRENT_DATE_GET(CURRENT_DATE, 'DD')
            INTO :V;
            IF (SUBSTRING(:V FROM 1 FOR 1) = '0') THEN
            BEGIN
                V = ASCII_CHAR(10) || :V || ASCII_CHAR(10);
            END
        END
        IF (I$QUERY_NUM = 201) THEN
        BEGIN
            SELECT DT FROM CURRENT_DATE_GET(CURRENT_DATE, 'MONTH')
            INTO :V;
        END
        IF (I$QUERY_NUM = 202) THEN
        BEGIN
            SELECT DT FROM CURRENT_DATE_GET(CURRENT_DATE, 'YY')
            INTO :V;
        END
        IF (I$QUERY_NUM BETWEEN 203 AND 205) THEN
        BEGIN
            SELECT SUM(SE.DAYS360_COUNT)
            FROM PARAGRAF_EMPLOYEE_SENIORITY_LST(:I$OBJ_ID, CURRENT_DATE) SE
            WHERE SE.SENIORITY_TYPE = 941
            INTO :V$I;

            IF(I$QUERY_NUM = 203) THEN
            BEGIN
                N = V$I / 30;
                V = V$I - N * 30;
            END
            ELSE IF(I$QUERY_NUM = 204) THEN
            BEGIN
                N = V$I / 360;
                N = V$I - N * 360;
                V = N / 30;
            END
            ELSE IF(I$QUERY_NUM = 205) THEN
            BEGIN
                V = V$I / 360;
            END
            ELSE V = NULL;

        END
        IF (I$QUERY_NUM = 215) THEN
        BEGIN
            SELECT V FROM VAL_GET(:I$OBJ_ID, 311)
            INTO :V;
        END
        IF (I$QUERY_NUM BETWEEN 217 AND 221) THEN
        BEGIN
            SELECT FIRST 1 L79.OBJ_ID,
                   TRIM(V442.VAL || ' ' || V559.VAL)
            FROM LINKS L79
    
            JOIN VALL V441 ON V441.OBJ_ID = L79.OBJ_ID
              AND V441.PARAM_ID = 441
              AND V441.IS_DEL = 0
              AND V441.LISTVAL_ID IN (1368, 1369, 1373, 3172)

            LEFT JOIN VALS V442
            ON V442.OBJ_ID = L79.OBJ_ID
            AND V442.PARAM_ID = 442
            AND V442.IS_DEL = 0
    
            JOIN VALS V559
            ON V559.OBJ_ID = L79.OBJ_ID
            AND V559.PARAM_ID = 559
            AND V559.IS_DEL = 0
    
            LEFT JOIN VALD V561
            ON V561.OBJ_ID = L79.OBJ_ID
            AND V561.PARAM_ID = 561
            AND V561.IS_DEL = 0
    
            WHERE L79.PARENT_ID = :I$OBJ_ID
            AND L79.OBJ_TYPE_ID = 79
            AND L79.DATE_DEL IS NULL
            AND (V561.VAL IS NULL OR V561.VAL > CURRENT_DATE)

            ORDER BY V441.LISTVAL_ID
            INTO :V$OBJ_ID, :V$S;

            IF (I$QUERY_NUM = 217) THEN
            BEGIN
                V = :V$S;
            END
            IF (I$QUERY_NUM = 218) THEN
            BEGIN
                SELECT DT FROM CURRENT_DATE_GET((SELECT D FROM VAL_GET(:V$OBJ_ID, 560)), 'DD')
                INTO :V;
                IF (SUBSTRING(:V FROM 1 FOR 1) = '0') THEN
                BEGIN
                    V = ASCII_CHAR(10) || :V || ASCII_CHAR(10);
                END
            END
            IF (I$QUERY_NUM = 219) THEN
            BEGIN
                SELECT DT FROM CURRENT_DATE_GET((SELECT D FROM VAL_GET(:V$OBJ_ID, 560)), 'MONTH')
                INTO :V;
            END
            IF (I$QUERY_NUM = 220) THEN
            BEGIN
                V = EXTRACT(YEAR FROM (SELECT D FROM VAL_GET(:V$OBJ_ID, 560)));
            END
            IF (I$QUERY_NUM = 221) THEN
            BEGIN
                SELECT V FROM VAL_GET(:V$OBJ_ID, 562)
                INTO :V;
            END
        END
        IF (I$QUERY_NUM = 222) THEN
        BEGIN
            SELECT POST_INDEX FROM ADR_GET(262, :I$OBJ_ID)
            INTO :V;
        END
        IF (I$QUERY_NUM IN (223, 224)) THEN
        BEGIN
            SELECT VAL FROM ADR_GET(262, :I$OBJ_ID, 0, 0)
            INTO :V;
            SELECT VAL FROM STRING_PART(:V, :I$QUERY_NUM - 223, 80)
            INTO :V;
        END
        IF (I$QUERY_NUM = 225) THEN
        BEGIN
            SELECT POST_INDEX FROM ADR_GET(255, :I$OBJ_ID)
            INTO :V;
        END
        IF (I$QUERY_NUM IN (226, 227)) THEN
        BEGIN
            SELECT VAL FROM ADR_GET(255, :I$OBJ_ID, 0, 0)
            INTO :V;
            SELECT VAL FROM STRING_PART(:V, :I$QUERY_NUM - 226, 80)
            INTO :V;
        END
        IF (I$QUERY_NUM = 228) THEN
        BEGIN
            SELECT V FROM VAL_GET(:I$OBJ_ID, 253)
            INTO :V;
            IF (CHAR_LENGTH(:V) < 5) THEN
            BEGIN
                SELECT V FROM VAL_GET(:I$OBJ_ID, 254)
                INTO :V;
            END
        END
        IF (I$QUERY_NUM = 229) THEN
        BEGIN
            SELECT V FROM VAL_GET(:I$OBJ_ID, 317)
            INTO :V;
        END
        IF (I$QUERY_NUM = 230) THEN
        BEGIN
            SELECT V FROM VAL_GET(:I$OBJ_ID, 320)
            INTO :V;
        END
        IF (I$QUERY_NUM = 231) THEN
        BEGIN
            SELECT V FROM VAL_GET(:I$OBJ_ID, 318)
            INTO :V;
        END
        IF (I$QUERY_NUM = 232) THEN
        BEGIN
            SELECT V FROM VAL_GET(:I$OBJ_ID, 322)
            INTO :V;
        END
        IF (I$QUERY_NUM = 233) THEN
        BEGIN
            SELECT V FROM VAL_GET(:I$OBJ_ID, 319)
            INTO :V;
            SELECT VAL FROM STRING_PART(:V, 0, 14)
            INTO :V;
        END
        IF (I$QUERY_NUM = 234) THEN
        BEGIN
            SELECT V FROM VAL_GET(:I$OBJ_ID, 319)
            INTO :V;
            SELECT TRIM(
                (SELECT VAL FROM STRING_PART(:V, 1, 14)) || ' ' ||
                (SELECT VAL FROM STRING_PART(:V, 2, 14)) || ' ' ||
                (SELECT VAL FROM STRING_PART(:V, 3, 14)))
            FROM RDB$DATABASE
            INTO :V;
        END
        IF (I$QUERY_NUM = 235) THEN
        BEGIN
            SELECT V FROM VAL_GET(:I$OBJ_ID, 323)
            INTO :V;
            SELECT VAL FROM STRING_PART(:V, 0, 20)
            INTO :V;
        END
        IF (I$QUERY_NUM = 236) THEN
        BEGIN
            SELECT V FROM VAL_GET(:I$OBJ_ID, 323)
            INTO :V;
            SELECT TRIM(
                (SELECT VAL FROM STRING_PART(:V, 1, 20)) || ' ' ||
                (SELECT VAL FROM STRING_PART(:V, 2, 20)) || ' ' ||
                (SELECT VAL FROM STRING_PART(:V, 3, 20)))
            FROM RDB$DATABASE
            INTO :V;
        END
        IF (I$QUERY_NUM = 239) THEN
        BEGIN
            SELECT V FROM VAL_GET(:I$OBJ_ID, 321)
            INTO :V;
        END
        -- page #3
        IF (I$QUERY_NUM BETWEEN 300 AND 369) THEN
        BEGIN
            FOR SELECT FIRST 7
                    L15.OBJ_ID,
                    V73.VAL
                FROM LINKS L15
                JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID
                  AND V73.PARAM_ID = 73
                  AND V73.IS_DEL = 0
                  AND V73.VAL <= CURRENT_DATE
                WHERE L15.OBJ_TYPE_ID = 15
                  AND L15.PARENT_ID = :I$OBJ_ID
                  AND L15.DATE_DEL IS NULL
                ORDER BY V73.VAL DESC
                INTO :V$OBJ_ID, :V$S
            DO
            BEGIN
                IF (I$QUERY_NUM = 300) THEN
                BEGIN
                    V = :V$S;
                END

                IF (I$QUERY_NUM IN (302, 307)) THEN
                BEGIN
                    SELECT V FROM VAL_GET(:V$OBJ_ID, 69)
                    INTO :V$S;
                    SELECT IIF(:V$S = '' OR V = '', :V$S, :V$S || ', ') || V
                    FROM VAL_GET(:V$OBJ_ID, 588)
                    INTO :V;
                    SELECT VAL FROM STRING_PART(:V, IIF(:I$QUERY_NUM = 302, 0, 1), 25)
                    INTO :V;
                END

                IF (I$QUERY_NUM IN (304, 309)) THEN
                BEGIN
                    SELECT COALESCE(D, '') FROM VAL_GET(:V$OBJ_ID, 454)
                    INTO :V$S;
                    SELECT TRIM(IIF(:V$S = '', '', 'приказ от ' || :V$S) || ' ' || IIF(V = '', '', '№' || V))
                    FROM VAL_GET(:V$OBJ_ID, 455)
                    INTO :V;
                    SELECT VAL FROM STRING_PART(:V, IIF(:I$QUERY_NUM = 304, 0, 1), 25)
                    INTO :V;
                END

                I$QUERY_NUM = :I$QUERY_NUM - 10;
            END
        END
        IF (I$QUERY_NUM BETWEEN 370 AND 384) THEN
        BEGIN
            FOR SELECT FIRST 3
                    L34.OBJ_ID,
                    L34.OBJ_TYPE_ID,
                    V544.VAL
                FROM LINKS L34
                JOIN VALD V544 ON V544.OBJ_ID = L34.OBJ_ID
                  AND V544.PARAM_ID IN (544, 1232)
                  AND V544.IS_DEL = 0
                  AND V544.VAL <= CURRENT_DATE
                WHERE L34.OBJ_TYPE_ID IN (34, 156)
                  AND L34.PARENT_ID = :I$OBJ_ID
                  AND L34.DATE_DEL IS NULL
                ORDER BY V544.VAL DESC
                INTO :V$OBJ_ID, :V$VAL_ID, :V$S
            DO
            BEGIN
                IF (I$QUERY_NUM = 370) THEN
                BEGIN
                    V = :V$S;
                END
                IF (I$QUERY_NUM = 371) THEN
                BEGIN
                    SELECT V FROM VAL_GET(:V$OBJ_ID, IIF(:V$VAL_ID = 34, 545, 1233))
                    INTO :V;
                END
                IF (I$QUERY_NUM = 372) THEN
                BEGIN
                    SELECT V FROM VAL_GET(:V$OBJ_ID, IIF(:V$VAL_ID = 34, 294, 1234))
                    INTO :V;
                END

                I$QUERY_NUM = :I$QUERY_NUM - 5;
            END
        END
        IF (I$QUERY_NUM BETWEEN 385 AND 408) THEN
        BEGIN
            FOR SELECT FIRST 3
                    L36.OBJ_ID,
                    V310.VAL
                FROM LINKS L36
                LEFT JOIN VALD V310 ON V310.OBJ_ID = L36.OBJ_ID
                  AND V310.PARAM_ID = 310
                  AND V310.IS_DEL = 0
                  AND V310.VAL <= CURRENT_DATE
                WHERE L36.OBJ_TYPE_ID = 36
                  AND L36.PARENT_ID = :I$OBJ_ID
                  AND L36.DATE_DEL IS NULL
                ORDER BY V310.VAL DESC
                INTO :V$OBJ_ID, :V$S
            DO
            BEGIN
                IF (I$QUERY_NUM = 387) THEN
                BEGIN
                    SELECT V FROM VAL_GET(:V$OBJ_ID, 303)
                    INTO :V$S;
                    SELECT IIF(:V$S = '' OR V = '', :V$S, :V$S || ', ') || V
                    FROM VAL_GET(:V$OBJ_ID, 1024)
                    INTO :V$S;
                    SELECT IIF(:V$S = '' OR V = '', :V$S, :V$S || ', ') || V
                    FROM VAL_GET(:V$OBJ_ID, 305)
                    INTO :V;
                END
                IF (I$QUERY_NUM = 388) THEN
                BEGIN
                    SELECT V FROM VAL_GET(:V$OBJ_ID, 2335)
                    INTO :V;
                    IF (CHAR_LENGTH(:V) < 3) THEN
                    BEGIN
                        SELECT V FROM VAL_GET(:V$OBJ_ID, 304)
                        INTO :V;
                    END
                END
                IF (I$QUERY_NUM = 389) THEN
                BEGIN
                    SELECT V FROM VAL_GET(:V$OBJ_ID, 307)
                    INTO :V;
                END
                IF (I$QUERY_NUM = 390) THEN
                BEGIN
                    SELECT V FROM VAL_GET(:V$OBJ_ID, 308)
                    INTO :V$S;
                    SELECT TRIM(:V$S || ' ' || V)
                    FROM VAL_GET(:V$OBJ_ID, 309)
                    INTO :V;
                END
                IF (I$QUERY_NUM = 391) THEN
                BEGIN
                    V = :V$S;
                END

                I$QUERY_NUM = :I$QUERY_NUM - 8;
            END
        END
        IF (I$QUERY_NUM BETWEEN 409 AND 429) THEN
        BEGIN
            FOR SELECT FIRST 3
                    L35.OBJ_ID,
                    V300.VAL
                FROM LINKS L35
                LEFT JOIN VALD V300 ON V300.OBJ_ID = L35.OBJ_ID
                  AND V300.PARAM_ID = 300
                  AND V300.IS_DEL = 0
                  AND V300.VAL <= CURRENT_DATE
                WHERE L35.OBJ_TYPE_ID = 35
                  AND L35.PARENT_ID = :I$OBJ_ID
                  AND L35.DATE_DEL IS NULL
                ORDER BY V300.VAL DESC
                INTO :V$OBJ_ID, :V$S
            DO
            BEGIN
                IF (I$QUERY_NUM = 411) THEN
                BEGIN
                    SELECT V FROM VAL_GET(:V$OBJ_ID, 301)
                    INTO :V$S;
                    SELECT IIF(:V$S = '' OR V = '', :V$S, :V$S || ', ') || V
                    FROM VAL_GET(:V$OBJ_ID, 302)
                    INTO :V;
                END
                IF (I$QUERY_NUM = 412) THEN
                BEGIN
                    SELECT V FROM VAL_GET(:V$OBJ_ID, 297)
                    INTO :V;
                END
                IF (I$QUERY_NUM = 413) THEN
                BEGIN
                    SELECT V FROM VAL_GET(:V$OBJ_ID, 298)
                    INTO :V$S;
                    SELECT TRIM(:V$S || ' ' || V)
                    FROM VAL_GET(:V$OBJ_ID, 299)
                    INTO :V;
                END
                IF (I$QUERY_NUM = 414) THEN
                BEGIN
                    V = :V$S;
                END

                I$QUERY_NUM = :I$QUERY_NUM - 7;
            END
        END
        -- page #4
        IF (I$QUERY_NUM BETWEEN 458 AND 469) THEN
        BEGIN
            FOR SELECT FIRST 3
                    L38.OBJ_ID,
                    L38.OBJ_TYPE_ID,
                    V339.VAL
                FROM LINKS L38
                LEFT JOIN VALD V339 ON V339.OBJ_ID = L38.OBJ_ID
                  AND V339.PARAM_ID IN (339, 343, 347)
                  AND V339.IS_DEL = 0
                WHERE L38.OBJ_TYPE_ID BETWEEN 38 AND 40
                  AND L38.PARENT_ID = :I$OBJ_ID
                  AND L38.DATE_DEL IS NULL
                  AND (V339.VAL IS NULL OR V339.VAL <= CURRENT_DATE)
                ORDER BY V339.VAL DESC
                INTO :V$OBJ_ID, :V$VAL_ID, :V$S
            DO
            BEGIN
                IF (I$QUERY_NUM = 458) THEN
                BEGIN
                    SELECT V FROM VAL_GET(:V$OBJ_ID,
                        CASE :V$VAL_ID
                            WHEN 38 THEN 337
                            WHEN 39 THEN 345
                            ELSE 341
                        END)
                    INTO :V;
                END
                IF (I$QUERY_NUM = 460) THEN
                BEGIN
                    SELECT V FROM VAL_GET(:V$OBJ_ID,
                        CASE :V$VAL_ID
                            WHEN 38 THEN 338
                            WHEN 39 THEN 346
                            ELSE 342
                        END)
                    INTO :V;
                END
                IF (I$QUERY_NUM = 461) THEN
                BEGIN
                    V = :V$S;
                END

                I$QUERY_NUM = :I$QUERY_NUM - 4;
            END
        END
        IF (I$QUERY_NUM BETWEEN 470 AND 532) THEN
        BEGIN
            FOR SELECT FIRST 9
                    L37.OBJ_ID,
                    V327.VAL
                FROM LINKS L37
                LEFT JOIN VALD V327 ON V327.OBJ_ID = L37.OBJ_ID
                  AND V327.PARAM_ID = 327
                  AND V327.IS_DEL = 0
                WHERE L37.OBJ_TYPE_ID = 37
                  AND L37.PARENT_ID = :I$OBJ_ID
                  AND L37.DATE_DEL IS NULL
                  AND (V327.VAL IS NULL OR V327.VAL <= CURRENT_DATE)
                ORDER BY V327.VAL DESC
                INTO :V$OBJ_ID, :V$S
            DO
            BEGIN
                IF (I$QUERY_NUM = 470) THEN
                BEGIN
                    SELECT V FROM VAL_GET(:V$OBJ_ID, 326)
                    INTO :V;
                END
                IF (I$QUERY_NUM = 471) THEN
                BEGIN
                    SELECT V FROM VAL_GET(:V$OBJ_ID, 325)
                    INTO :V;
                END
                IF (I$QUERY_NUM = 473) THEN
                BEGIN
                    SELECT V FROM VAL_GET(:V$OBJ_ID, 329)
                    INTO :V;
                END
                IF (I$QUERY_NUM = 474) THEN
                BEGIN
                    V = :V$S;
                END
                IF (I$QUERY_NUM = 475) THEN
                BEGIN
                    SELECT D FROM VAL_GET(:V$OBJ_ID, 328)
                    INTO :V;
                END

                I$QUERY_NUM = :I$QUERY_NUM - 7;
            END
        END
        IF (I$QUERY_NUM BETWEEN 561 AND 568 AND EXISTS(
            SELECT 1
            FROM LINKS L14
            WHERE L14.OBJ_ID = :I$OBJ_ID
              AND L14.PARENT_TYPE_ID+0 = 84
              AND L14.DATE_DEL IS NULL)) THEN
        BEGIN
            FOR SELECT FIRST 1
                    L15.OBJ_ID
                FROM LINKS L15
                JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID
                  AND V74.PARAM_ID = 74
                  AND V74.IS_DEL = 0
                  AND V74.VAL <= CURRENT_DATE
                WHERE L15.OBJ_TYPE_ID = 15
                  AND L15.PARENT_ID = :I$OBJ_ID
                  AND L15.DATE_DEL IS NULL
                ORDER BY V74.VAL DESC
                INTO :V$OBJ_ID
            DO
            BEGIN
                IF (I$QUERY_NUM = 561) THEN
                BEGIN
                    SELECT V FROM VAL_GET(:V$OBJ_ID, 458)
                    INTO :V;
                END
                IF (I$QUERY_NUM = 562) THEN
                    BEGIN
                    SELECT DT FROM CURRENT_DATE_GET((SELECT D FROM VAL_GET(:V$OBJ_ID, 74)), 'DD')
                    INTO :V;
                    IF (SUBSTRING(:V FROM 1 FOR 1) = '0') THEN
                    BEGIN
                        V = ASCII_CHAR(10) || :V || ASCII_CHAR(10);
                    END
                END
                IF (I$QUERY_NUM = 563) THEN
                BEGIN
                    SELECT DT FROM CURRENT_DATE_GET((SELECT D FROM VAL_GET(:V$OBJ_ID, 74)), 'MONTH')
                    INTO :V;
                END
                IF (I$QUERY_NUM = 564) THEN
                BEGIN
                    SELECT DT FROM CURRENT_DATE_GET((SELECT D FROM VAL_GET(:V$OBJ_ID, 74)), 'YY')
                    INTO :V;
                END
                IF (I$QUERY_NUM = 565) THEN
                BEGIN
                    SELECT V FROM VAL_GET(:V$OBJ_ID, 457)
                    INTO :V;
                END
                IF (I$QUERY_NUM = 566) THEN
                    BEGIN
                    SELECT DT FROM CURRENT_DATE_GET((SELECT D FROM VAL_GET(:V$OBJ_ID, 456)), 'DD')
                    INTO :V;
                    IF (SUBSTRING(:V FROM 1 FOR 1) = '0') THEN
                    BEGIN
                        V = ASCII_CHAR(10) || :V || ASCII_CHAR(10);
                    END
                END
                IF (I$QUERY_NUM = 567) THEN
                BEGIN
                    SELECT DT FROM CURRENT_DATE_GET((SELECT D FROM VAL_GET(:V$OBJ_ID, 456)), 'MONTH')
                    INTO :V;
                END
                IF (I$QUERY_NUM = 568) THEN
                BEGIN
                    SELECT DT FROM CURRENT_DATE_GET((SELECT D FROM VAL_GET(:V$OBJ_ID, 456)), 'YY')
                    INTO :V;
                END
            END
        END
    END

    IF (:I$REPORT_ID = 302) THEN
    -- Справка об обучении
    BEGIN
        IF (I$QUERY_NUM = 10) THEN
        BEGIN
            SELECT V
            FROM VAL_GET(:I$OBJ_ID, 2353)
            INTO :V;
        END
        IF (I$QUERY_NUM = 60) THEN
        BEGIN
            SELECT FIRST 1 L222.OBJ_ID
            FROM OBJECT_PARENTS_GET(:I$OBJ_ID, 7) P
            JOIN LINKS L222 ON L222.PARENT_ID = P.OBJ_ID
              AND L222.OBJ_TYPE_ID = 222
              AND L222.DATE_DEL IS NULL
            INTO :V$VAL_ID;

            SELECT REPLACE(V, ASCII_CHAR(13) || ASCII_CHAR(10), ' ')
            FROM VAL_GET(:V$VAL_ID, 2352)
            INTO :V$S;

            IF (CHAR_LENGTH(:V$S) < 5) THEN
            BEGIN
                SELECT FIRST 1 OBJ_ID
                FROM OBJECT_PARENTS_GET(:I$OBJ_ID, 2)
                INTO :V$VAL_ID;

                SELECT V FROM VAL_GET(:V$VAL_ID, 5)
                INTO :V$S;
            END
            V$S = 'в ' || V$S;

            V$I = 0;
            WHILE (1 = 1) DO
            BEGIN
                SELECT VAL FROM STRING_PART(:V$S, :V$I, 70)
                INTO :V;
                V$I = :V$I + 1;
                IF ((SELECT VAL FROM STRING_PART(:V$S, :V$I, 70)) = '') THEN
                BEGIN
                    V = :V || ',';
                    BREAK;
                END
                SUSPEND;
            END
            SUSPEND;

            V = 'находящемся по адресу:';

            SELECT V
            FROM VAL_GET(:V$VAL_ID, 1835)
            INTO :V$S;

            IF (CHAR_LENGTH(:V$S) < 5) THEN
            BEGIN
                SELECT FIRST 1 OBJ_ID
                FROM OBJECT_PARENTS_GET(:I$OBJ_ID, 2)
                INTO :V$VAL_ID;

                SELECT VAL FROM ADR_GET(27, :V$VAL_ID, 0, 0)
                INTO :V$S;
            END

            V$I = 0;
            WHILE ((SELECT VAL FROM STRING_PART(:V$S, :V$I, 70)) <> '') DO
            BEGIN
                SUSPEND;
                SELECT VAL FROM STRING_PART(:V$S, :V$I, 70)
                INTO :V;
                V$I = :V$I + 1;
            END
        END
        IF (I$QUERY_NUM = 120) THEN
        BEGIN
            SELECT FIRST 1 NAME_IN
            FROM (
              SELECT M.DATE_IN DT, M.NAME_IN
              FROM PERSON_MOVEMENTS M
              JOIN OBJECTS O ON O.OBJ_ID = M.GROUP_ID AND O.TYPE_ID = 9
              WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :I$OBJ_ID AND EXTRACT(YEAR FROM M.DATE_IN) = :I$PARAM_VAL
              UNION
              SELECT M.DATE_OUT DT, M.NAME_IN
              FROM PERSON_MOVEMENTS M
              JOIN OBJECTS O ON O.OBJ_ID = M.GROUP_ID AND O.TYPE_ID = 9
              WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :I$OBJ_ID AND EXTRACT(YEAR FROM M.DATE_IN) = :I$PARAM_VAL AND M.DATE_OUT IS NOT NULL
              ORDER BY 1 DESC
            )
            INTO :V;
        END
        IF (I$QUERY_NUM = 130) THEN
        BEGIN
            V$I = 0;
            FOR SELECT
                    SUBJECT_NAME,
                    MARK_YEAR,
                    MARK_FIN,
                    MARK_GIA
                FROM CERT_STUDY_PUPIL_LOAD_SUBJECTS(COALESCE(:I$PARAM_VAL, :V$YEAR), :I$OBJ_ID, NULL, :I$USER_ID)
                WHERE INCLUDING_TYPE_ID = 5381
                  OR (INCLUDING_TYPE_ID IS NULL AND IS_PLAN = 1 AND IS_BASE = 1)
                INTO :V2, :V3, :V4, :V5
            DO
            BEGIN
                V$I = :V$I + 1;
                V = :V$I;
                SUSPEND;
            END
        END
        IF (I$QUERY_NUM = 140) THEN
        BEGIN
            SELECT FIRST 1 L222.OBJ_ID
            FROM OBJECT_PARENTS_GET(:I$OBJ_ID, 7) P
            JOIN LINKS L222 ON L222.PARENT_ID = P.OBJ_ID
              AND L222.OBJ_TYPE_ID = 222
              AND L222.DATE_DEL IS NULL
            INTO :V$VAL_ID;

            SELECT V
            FROM VAL_GET(:V$VAL_ID, 1836)
            INTO :V;

            IF (CHAR_LENGTH(:V) < 5) THEN
            BEGIN
                SELECT FIRST 1 OBJ_ID
                FROM OBJECT_PARENTS_GET(:I$OBJ_ID, 2)
                INTO :V$VAL_ID;

                SELECT V FROM VAL_GET(:V$VAL_ID, 1178)
                INTO :V;
            END
        END
    END
    IF (:I$REPORT_ID = 305) THEN
    -- Регистрация выдачи дубликатов аттестатов
    BEGIN
        IF (I$QUERY_NUM = 20) THEN
        BEGIN
            SELECT FIRST 1 GRADUATE_YEAR
            FROM CERTIFICATE_PUPIL_INFO_GET(:V$YEAR, NULL, :I$OBJ_ID, :I$USER_ID)
            INTO :V;
        END
        IF (I$QUERY_NUM = 30) THEN
        BEGIN
            SELECT FIRST 1
                ORI_UNUMBER,
                ORI_DATEVID,
                ASCII_CHAR(10) || ORI_KSNB || ASCII_CHAR(10),
                DUP_NUMORDER,
                DUP_DATEORDER
            FROM CERTIFICATE_REG_DUPL_INFO_GET(:I$OBJ_ID, :I$USER_ID)
            INTO :V, :V2, :V3, :V4, :V5;
        END
        IF (I$QUERY_NUM = 40) THEN
        BEGIN
            SELECT FIRST 1 DUP_DATEVID
            FROM CERTIFICATE_REG_DUPL_INFO_GET(:I$OBJ_ID, :I$USER_ID)
            INTO :V;
        END
        IF (I$QUERY_NUM = 50) THEN
        BEGIN
            SELECT FIRST 1  ASCII_CHAR(10) || DUP_KSNB || ASCII_CHAR(10)
            FROM CERTIFICATE_REG_DUPL_INFO_GET(:I$OBJ_ID, :I$USER_ID)
            INTO :V;
        END
        IF (I$QUERY_NUM = 60) THEN
        BEGIN
            SELECT FIRST 1 REPLACE(FIO, ASCII_CHAR(13) || ASCII_CHAR(10), ' ')
            FROM CERTIFICATE_PUPIL_INFO_GET(:V$YEAR, NULL, :I$OBJ_ID, :I$USER_ID)
            INTO :V;
        END
        IF (I$QUERY_NUM = 70) THEN
        BEGIN
            SELECT FIRST 1 DUP_RECEIVER
            FROM CERTIFICATE_REG_DUPL_INFO_GET(:I$OBJ_ID, :I$USER_ID)
            INTO :V;
        END
        IF (I$QUERY_NUM = 130) THEN
        BEGIN
            V$F = 1;
            V$I = 0;
            -- предметы и отметки слева
            FOR SELECT FIRST 13
                    SUBJECT_NAME,
                    CASE MARK
                        WHEN '5' THEN '5 (отлично)'
                        WHEN '4' THEN '4 (хорошо)'
                        WHEN '3' THEN '3 (удовл.)'
                        WHEN '2' THEN '2 (неудовл.)'
                        ELSE MARK
                    END
                FROM CERTIFICATE_PUPIL_LOAD_SUBJECTS(COALESCE(:I$PARAM2_VAL, :V$YEAR), :I$OBJ_ID, NULL, :I$PARAM_VAL, :I$USER_ID)
                WHERE INCLUDING_TYPE_ID = 5381
                ORDER BY SORT_ORDER, SUBJECT_NAME
                INTO :V, :V2
            DO
            BEGIN
                V$I = V$I + 1;
                -- предметы и отметки справа
                IF (:V$F = 1) THEN
                BEGIN
                    V$F = 0;
                    V$I2 = 0;
                    FOR SELECT
                        SUBJECT_NAME,
                        CASE MARK
                            WHEN '5' THEN '5 (отлично)'
                            WHEN '4' THEN '4 (хорошо)'
                            WHEN '3' THEN '3 (удовл.)'
                            WHEN '2' THEN '2 (неудовл.)'
                            ELSE MARK
                        END
                        FROM CERTIFICATE_PUPIL_LOAD_SUBJECTS(COALESCE(:I$PARAM2_VAL, :V$YEAR), :I$OBJ_ID, NULL, :I$PARAM_VAL, :I$USER_ID)
                        WHERE INCLUDING_TYPE_ID = 5381
                        ORDER BY SORT_ORDER, SUBJECT_NAME
                        INTO :V3, :V4
                    DO
                    BEGIN
                        V$I2 = V$I2 + 1;
                        IF (:V$I2 = :V$I + 13) THEN
                        BEGIN
                            V$F = 1;
                            BREAK;
                        END
                    END
                END
                IF (:V$F = 0) THEN
                BEGIN
                    V3 = '';
                    V4 = '';
                END
                SUSPEND;
            END
        END
        IF (I$QUERY_NUM = 100) THEN
        BEGIN
            SELECT LIST(SUBJECT_NAME, ', ')
            FROM (
                SELECT SUBJECT_NAME
                FROM CERTIFICATE_PUPIL_LOAD_SUBJECTS(COALESCE(:I$PARAM2_VAL, :V$YEAR), :I$OBJ_ID, NULL, :I$PARAM_VAL, :I$USER_ID)
                WHERE INCLUDING_TYPE_ID = 5382
                ORDER BY INCLUDING_TYPE_ID, SORT_ORDER, SUBJECT_NAME
            )
            INTO :V;
        END
    END

    IF (:I$REPORT_ID IN (319, 320)) THEN
    -- Справка по месту требования
    -- и
    -- Справка в военкомат (ф 2)
    BEGIN
        IF (I$QUERY_NUM < 100 OR :I$QUERY_NUM = 130) THEN
        BEGIN
            SELECT FIRST 1 OBJ_ID
            FROM OBJECT_PARENTS_GET(:I$OBJ_ID, 2)
            INTO :V$OBJ_ID;

            V$VAL_ID = CASE :I$QUERY_NUM
                           WHEN 10 THEN 7
                           WHEN 20 THEN 5
                           WHEN 30 THEN 27
                           WHEN 40 THEN 29
                           WHEN 50 THEN 30
                           WHEN 60 THEN 33
                           WHEN 70 THEN 34
                           WHEN 80 THEN 16
                           WHEN 90 THEN 9
                           WHEN 130 THEN 5
                       END;

            SELECT V FROM VAL_GET(:V$OBJ_ID, :V$VAL_ID)
            INTO :V;
        END

        IF (I$QUERY_NUM = 100) THEN
        BEGIN
            SELECT DC.F || ' ' || DC.I || ' ' || DC.O
            FROM RDB$DATABASE
            LEFT JOIN BUILD_REP_FIO(:I$OBJ_ID, 55,56,57) BF ON 1=1
            LEFT JOIN DATIVECASE(BF.F, BF.I, BF.O) DC ON 1=1
            INTO :V;
        END

        IF (I$QUERY_NUM = 105) THEN
        BEGIN
            SELECT V FROM VAL_GET(:I$OBJ_ID, 1349)
            INTO :V;
        END

        IF (I$QUERY_NUM = 110) THEN
        BEGIN
            SELECT OBJ_ID FROM OBJECT_PARENTS_GET(:I$OBJ_ID, 8)
            INTO :V$OBJ_ID;

            SELECT V || IIF(:I$REPORT_ID = 320, '-м', '-го') FROM VAL_GET(:V$OBJ_ID, 1393)
            INTO :V;
        END

        IF (I$QUERY_NUM = 120) THEN
        BEGIN
            SELECT I FROM VAL_GET(:I$OBJ_ID, 80)
            INTO :V$I;

            V = CASE :V$I
                    WHEN 5419 THEN 'очно-заочно'
                    WHEN 5420 THEN 'заочно'
                    ELSE 'очно'
                END;
            V = TRIM(:V) || IIF(:I$REPORT_ID = 320, 'й', 'го');
        END

        IF (I$QUERY_NUM = 125) THEN
        BEGIN
            SELECT V FROM VAL_GET(:I$OBJ_ID, 2164)
            INTO :V;
        END

        IF (I$QUERY_NUM IN (140, 150, 160)) THEN
        BEGIN
            SELECT OBJ_ID FROM OBJECT_PARENTS_GET(:I$OBJ_ID, 8)
            INTO :V$OBJ_ID;

            SELECT I FROM VAL_GET(:V$OBJ_ID, 49)
            INTO :V$I;

            SELECT FIRST 1
                CASE :I$QUERY_NUM
                    WHEN 140 THEN IIF(:I$REPORT_ID = 320, CAST(EXTRACT(YEAR FROM DT) AS VARCHAR(100)), DT)
                    WHEN 150 THEN ORDER_NUM
                    WHEN 160 THEN ORDER_DATE
                END
            FROM (
              SELECT M.DATE_IN DT, M.NAME_IN, M.ORDER_NUM_IN ORDER_NUM, M.ORDER_DATE_IN ORDER_DATE
              FROM PERSON_MOVEMENTS M
              JOIN OBJECTS O ON O.OBJ_ID = M.GROUP_ID AND O.TYPE_ID = 9
              WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :I$OBJ_ID
              UNION
              SELECT M.DATE_OUT DT, M.NAME_IN, M.ORDER_NUM_OUT ORDER_NUM, M.ORDER_DATE_OUT ORDER_DATE
              FROM PERSON_MOVEMENTS M
              JOIN OBJECTS O ON O.OBJ_ID = M.GROUP_ID AND O.TYPE_ID = 9
              WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :I$OBJ_ID
              ORDER BY 1
            )
            INTO :V;
        END

        IF (I$QUERY_NUM IN (135, 145, 155)) THEN
        BEGIN
            SELECT FIRST 1 OBJ_ID
            FROM OBJECT_PARENTS_GET(:I$OBJ_ID, 2)
            INTO :V$OBJ_ID;

            SELECT FIRST 1
                CASE :I$QUERY_NUM
                    WHEN 135 THEN (SELECT V FROM VAL_GET(L17.OBJ_ID, 480))
                    WHEN 145 THEN V482.VAL
                    WHEN 155 THEN (SELECT D FROM VAL_GET(L17.OBJ_ID, 483))
                END
            FROM LINKS L17
            JOIN VALL V471 ON V471.OBJ_ID = L17.OBJ_ID
              AND V471.PARAM_ID = 471
              AND V471.IS_DEL = 0
              AND V471.LISTVAL_ID IN (1053, 18625)
            JOIN VALD V482 ON V482.OBJ_ID = L17.OBJ_ID
              AND V482.PARAM_ID = 482
              AND V482.IS_DEL = 0
            WHERE L17.PARENT_ID = :V$OBJ_ID
              AND L17.OBJ_TYPE_ID = 17
              AND L17.DATE_DEL IS NULL
            ORDER BY V482.VAL DESC
            INTO :V;
        END

        IF (I$QUERY_NUM = 170) THEN
        BEGIN
            SELECT IIF(I = 5260, 'платное', 'бюджетное')
            FROM VAL_GET(:I$OBJ_ID, 1812)
            INTO :V;
        END

        IF (I$QUERY_NUM = 180) THEN
        BEGIN
            SELECT FIRST 1 OBJ_ID
            FROM OBJECT_PARENTS_GET(:I$OBJ_ID, 2)
            INTO :V$OBJ_ID;

            SELECT SUBSTRING(TRIM(I) FROM 1 FOR 1) || '.' || SUBSTRING(TRIM(O) FROM 1 FOR 1) || '.'|| F
            FROM GIA_GET_DIRECTOR_FIO(:V$OBJ_ID, :I$USER_ID)
            INTO :V;
        END

        IF (I$QUERY_NUM > 130 AND :V IS NULL) THEN
        BEGIN
            V = '__________';
        END
    END

    IF (NOT(:I$REPORT_ID IN (302, 305) AND :I$QUERY_NUM = 130)) THEN
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE RESET_REGISTRATION_DATE (
    OBJ_ID BIGINT)
AS
begin
  UPDATE VALD
  SET IS_DEL = 1
  WHERE OBJ_ID = :OBJ_ID AND PARAM_ID IN (1347, 2835) AND IS_DEL = 0;
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE RES_ADD (
    I$RES_ID BIGINT,
    I$LANG_CODE CHAR(2),
    I$VAL VARCHAR(4000),
    I$VAL_LONG VARCHAR(4000) = NULL)
AS
BEGIN
    UPDATE OR INSERT INTO RES (RES_ID, LANG_CODE, VAL, VAL_LONG)
    VALUES (:I$RES_ID, :I$LANG_CODE, :I$VAL, :I$VAL_LONG);
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE RES_DEL (
    I$RES_ID BIGINT,
    I$LANG_CODE CHAR(2) = NULL,
    I$IS_DEL SMALLINT = 1)
AS
BEGIN
   IF (I$LANG_CODE IS NULL) THEN
      UPDATE RES SET
        IS_DEL  = :I$IS_DEL
      WHERE RES_ID = :I$RES_ID;
   ELSE
      UPDATE RES SET
        IS_DEL  = :I$IS_DEL
      WHERE RES_ID = :I$RES_ID AND LANG_CODE = :I$LANG_CODE;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE RES_GET (
    I$RES_ID BIGINT,
    I$LANG_CODE CHAR(2))
RETURNS (
    VAL VARCHAR(4000),
    VAL_LONG VARCHAR(4000))
AS
declare variable V$OU_LICENCE_TYPE varchar(1);
BEGIN
    SELECT VAL, VAL_LONG
    FROM RES
    WHERE RES_ID = :I$RES_ID AND LANG_CODE = :I$LANG_CODE AND IS_DEL = 0
    INTO :VAL, :VAL_LONG;

    IF (ROW_COUNT = 0) THEN
    BEGIN
        SELECT VAL, VAL_LONG
        FROM RES
        WHERE RES_ID = :I$RES_ID AND LANG_CODE = 'RU' AND IS_DEL = 0
        INTO :VAL, :VAL_LONG;
    END

    /* #1512 - коррекция наименования общей ОП (#57) для колледжа */
    IF(I$RES_ID = 1853) THEN
    BEGIN
        SELECT STATUS FROM OU_LICENCE_TYPE INTO :V$OU_LICENCE_TYPE;
        IF(V$OU_LICENCE_TYPE = 'C') THEN VAL = 'Образовательная программа среднего профессионального образования';
    END

    IF (ROW_COUNT = 0) THEN
    BEGIN
        VAL = '';
        VAL_LONG = '';
    END
    IF (VAL = '<empty>') THEN
    BEGIN
        VAL = '';
    END

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE RES_LIST (
    I$RES_ID BIGINT)
RETURNS (
    RES_ID BIGINT,
    LANG_CODE CHAR(2),
    VAL VARCHAR(4000))
AS
BEGIN
    RES_ID = I$RES_ID;
    FOR
        SELECT L.LANG_CODE,
               R.VAL
        FROM LANGS L
        LEFT JOIN RES R
        ON R.LANG_CODE = L.LANG_CODE
        AND R.RES_ID = :I$RES_ID
        INTO   :LANG_CODE,
               :VAL
   DO SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE RGN_ALLOWED_PARENTS (
    I$TYPE_ID BIGINT)
RETURNS (
    TYPE_ID BIGINT)
AS
declare variable V$LEVEL smallint;
begin

  SELECT KEY_VAL FROM KEYS WHERE KEY_CODE = 'LEVEL' INTO :V$LEVEL;

  -- Предустановленные типы для корневого объекта уровня ОУ, район, регион
  IF(V$LEVEL = 1) THEN
  BEGIN
    IF(I$TYPE_ID = 2) THEN
    BEGIN
      TYPE_ID = NULL;
      SUSPEND;
    END
  END
  ELSE IF(V$LEVEL = 2) THEN
  BEGIN
    IF(I$TYPE_ID = 111) THEN
    BEGIN
      TYPE_ID = NULL;
      SUSPEND;
    END
  END
  ELSE IF(V$LEVEL = 3) THEN
  BEGIN
    IF(I$TYPE_ID = 112) THEN
    BEGIN
      TYPE_ID = NULL;
      SUSPEND;
    END
  END

  -- Далее выборка из реальных типов
  FOR
    SELECT DISTINCT P.TYPE_ID
    FROM LTYPES LT
    JOIN LEVELS L ON L.LEVEL_ID = LT.LEVEL_ID AND L.IS_DEL = 0
    JOIN TASKS T ON T.TASK_ID = L.TASK_ID AND T.IS_DEL = 0
    JOIN MODULES M ON M.MODULE_ID = T.MODULE_ID AND M.IS_DEL = 0 AND M.IS_ACTIVE = 1
    JOIN PARENTS P ON P.TYPE_ID = LT.TYPE_ID AND P.IS_DEL = 0 AND P.CHILD_ID = :I$TYPE_ID
    JOIN LTYPES LT2 ON LT2.LEVEL_ID = LT.LEVEL_ID AND LT2.TYPE_ID = P.CHILD_ID AND LT2.IS_DEL = 0
    WHERE LT.IS_DEL = 0 AND LT.EDIT_TYPE >= 0
    INTO :TYPE_ID
  DO
  BEGIN
    -- Скрываем пару (14, 2)
    IF(I$TYPE_ID <> 2 OR TYPE_ID <> 14) THEN SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE RGN_FILTER_SET (
    I$ROW_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$DELETED SMALLINT,
    I$SORT_INDEX INTEGER,
    I$PARAM_ID BIGINT,
    I$EQU_INDEX SMALLINT,
    I$EQU_VALUE VARCHAR(400),
    I$EQU_VALUE2 VARCHAR(400))
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$PARAM_ID bigint;
declare variable V$SORT_INDEX bigint;
declare variable V$EQU_INDEX smallint;
declare variable V$EQU_VALUE varchar(400);
declare variable V$EQU_VALUE2 varchar(400);
begin

  IF(I$OBJ_ID IS NOT NULL) THEN
  BEGIN
    SELECT D.OBJ_ID, D.SORT_INDEX, D.PARAM_ID, D.EQU_INDEX, D.EQU_VALUE, D.EQU_VALUE2
    FROM RGN_REPORT_LFILTERS D
    WHERE D.DATE_DEL IS NULL AND D.LEVEL_ID = :I$ROW_ID AND D.OBJ_ID = :I$OBJ_ID
    INTO :OBJ_ID, :V$SORT_INDEX, :V$PARAM_ID, :V$EQU_INDEX, :V$EQU_VALUE, :V$EQU_VALUE2;

    IF(OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Запись не найдена или была удалена';
  END

  IF(I$DELETED = 1) THEN
  BEGIN

    -- Удаление
    UPDATE RGN_REPORT_LFILTERS
    SET DATE_DEL = CURRENT_TIMESTAMP
    WHERE OBJ_ID = :OBJ_ID;

  END
  ELSE IF(OBJ_ID IS NULL) THEN
  BEGIN

    INSERT INTO RGN_REPORT_LFILTERS
    (LEVEL_ID, SORT_INDEX, PARAM_ID, EQU_INDEX, EQU_VALUE, EQU_VALUE2)
    VALUES (:I$ROW_ID, :I$SORT_INDEX, :I$PARAM_ID, :I$EQU_INDEX, :I$EQU_VALUE, :I$EQU_VALUE2)
    RETURNING OBJ_ID INTO :OBJ_ID;

  END
  ELSE
  BEGIN

    IF(I$SORT_INDEX <> V$SORT_INDEX OR I$PARAM_ID <> V$PARAM_ID OR COALESCE(I$EQU_INDEX, -1) <> COALESCE(V$EQU_INDEX, -1) OR
      COALESCE(I$EQU_VALUE, '') <> COALESCE(V$EQU_VALUE, '') OR COALESCE(I$EQU_VALUE2, '') <> COALESCE(V$EQU_VALUE2, '')) THEN
    BEGIN

      UPDATE RGN_REPORT_LFILTERS
      SET SORT_INDEX = :I$SORT_INDEX, PARAM_ID = :I$PARAM_ID, EQU_INDEX = :I$EQU_INDEX, EQU_VALUE = :I$EQU_VALUE, EQU_VALUE2 = :I$EQU_VALUE2
      WHERE OBJ_ID = :OBJ_ID;

    END

  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE RGN_ITEM_SET (
    I$RGN_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40),
    I$DELETED SMALLINT,
    I$PARENT_ID BIGINT,
    I$SORT_INDEX INTEGER,
    I$TYPE_ID BIGINT,
    I$LIST_MODE SMALLINT)
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$SORT_INDEX integer;
declare variable V$TYPE_ID bigint;
declare variable V$PARENT_ID bigint;
declare variable V$LIST_MODE smallint;
begin

  IF(I$OBJ_ID IS NOT NULL) THEN
  BEGIN
    SELECT D.OBJ_ID, D.SORT_INDEX, D.TYPE_ID, D.PARENT_ID, D.LIST_MODE
    FROM RGN_REPORT_LEVELS D
    WHERE D.DATE_DEL IS NULL AND D.REPORT_ID = :I$RGN_ID AND D.OBJ_ID = :I$OBJ_ID
    INTO :OBJ_ID, :V$SORT_INDEX, :V$TYPE_ID, :V$PARENT_ID, :V$LIST_MODE;

    IF(OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Запись не найдена или была удалена';
  END

  IF(I$DELETED = 1) THEN
  BEGIN

    -- Удаление. Предполагаются что все остальные в цепочке тоже будут удалены
    UPDATE RGN_REPORT_LEVELS
    SET DATE_DEL = CURRENT_TIMESTAMP
    WHERE OBJ_ID = :I$OBJ_ID;

  END
  ELSE IF(I$OBJ_ID IS NULL) THEN
  BEGIN

    INSERT INTO RGN_REPORT_LEVELS
    (REPORT_ID, SORT_INDEX, TYPE_ID, LIST_MODE)
    VALUES (:I$RGN_ID, :I$SORT_INDEX, :I$TYPE_ID, :I$LIST_MODE)
    RETURNING OBJ_ID INTO :OBJ_ID;

  END
  ELSE
  BEGIN

    IF(I$SORT_INDEX <> V$SORT_INDEX OR I$TYPE_ID <> V$TYPE_ID OR I$LIST_MODE <> V$LIST_MODE OR I$PARENT_ID <> V$PARENT_ID) THEN
    BEGIN

      UPDATE RGN_REPORT_LEVELS
      SET SORT_INDEX = :I$SORT_INDEX, PARENT_ID = :I$PARENT_ID, TYPE_ID = :I$TYPE_ID, LIST_MODE = :I$LIST_MODE
      WHERE OBJ_ID = :OBJ_ID;

    END

  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE RGN_MENU (
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
declare variable V$OBJ_ID bigint;
declare variable V$OBJ_NAME varchar(1000);
declare variable V$ICON_NAME varchar(100);
declare variable V$COLOR varchar(40);
declare variable V$SIZE smallint;
declare variable V$SORT_INDEX integer;
declare variable V$IS_LIVE smallint;
declare variable V$LAST_TYPE_ID bigint;
declare variable V$TYPE_NAME varchar(400);
declare variable V$LIVE_VALUE float;
declare variable V$IS_ARCHIVE smallint;
declare variable V$LIVE_VALUES varchar(4000);
begin

  -- Список отчетов
  TAG_NAME = 'items::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT R.OBJ_ID, R.OBJ_NAME, R.ICON_NAME, R.COLOR, R.SORT_INDEX, R.IS_LIVE, R.LAST_TYPE_ID, RR.VAL, R.LIVE_VALUE, R.TILE_SIZE, R.IS_ARCHIVE, R.LIVE_VALUES
    FROM RGN_REPORTS R
    LEFT JOIN TYPES T ON T.TYPE_ID = R.LAST_TYPE_ID
    LEFT JOIN RES RR ON RR.RES_ID = T.RES_ID AND RR.LANG_CODE = 'RU'
    WHERE R.DATE_DEL IS NULL
    ORDER BY R.SORT_INDEX
    INTO :V$OBJ_ID, :V$OBJ_NAME, :V$ICON_NAME, :V$COLOR, :V$SORT_INDEX, :V$IS_LIVE, :V$LAST_TYPE_ID, :V$TYPE_NAME, :V$LIVE_VALUE, :V$SIZE, :V$IS_ARCHIVE, :V$LIVE_VALUES
  DO
  BEGIN
    TAG_NAME = 'items:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'items:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'items:r:name';
    VAL = V$OBJ_NAME;
    SUSPEND;
    TAG_NAME = 'items:r:icon';
    VAL = V$ICON_NAME;
    SUSPEND;
    TAG_NAME = 'items:r:color';
    VAL = V$COLOR;
    SUSPEND;
    TAG_NAME = 'items:r:size';
    VAL = V$SIZE;
    SUSPEND;
    TAG_NAME = 'items:r:obj_type_id';
    VAL = V$LAST_TYPE_ID;
    SUSPEND;
    TAG_NAME = 'items:r:obj_type_name';
    VAL = V$TYPE_NAME;
    SUSPEND;
    TAG_NAME = 'items:r:live';
    VAL = V$IS_LIVE;
    SUSPEND;
    TAG_NAME = 'items:r:live_value';
    VAL = V$LIVE_VALUE;
    SUSPEND;
    TAG_NAME = 'items:r:live_values';
    VAL = V$LIVE_VALUES;
    SUSPEND;
    TAG_NAME = 'items:r:archive';
    VAL = V$IS_ARCHIVE;
    SUSPEND;
    TAG_NAME = 'items:r:sort_index';
    VAL = V$SORT_INDEX;
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE RGN_PARAM_SET (
    I$ROW_ID BIGINT,
    I$DELETED SMALLINT,
    I$SORT_INDEX INTEGER,
    I$PARAM_ID BIGINT,
    I$ALIAS VARCHAR(100))
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$SORT_INDEX bigint;
begin

  SELECT D.OBJ_ID, D.SORT_INDEX
  FROM RGN_REPORT_LPARAMS D
  WHERE D.DATE_DEL IS NULL AND D.LEVEL_ID = :I$ROW_ID AND D.PARAM_ID = :I$PARAM_ID
  INTO :OBJ_ID, :V$SORT_INDEX;

  IF(I$DELETED = 1) THEN
  BEGIN

    -- Удаление. Предполагаются что все остальные в цепочке тоже будут удалены
    UPDATE RGN_REPORT_LPARAMS
    SET DATE_DEL = CURRENT_TIMESTAMP
    WHERE OBJ_ID = :OBJ_ID;

  END
  ELSE IF(OBJ_ID IS NULL) THEN
  BEGIN

    INSERT INTO RGN_REPORT_LPARAMS
    (LEVEL_ID, SORT_INDEX, PARAM_ID)
    VALUES (:I$ROW_ID, :I$SORT_INDEX, :I$PARAM_ID)
    RETURNING OBJ_ID INTO :OBJ_ID;

  END
  ELSE
  BEGIN

    IF(I$SORT_INDEX <> V$SORT_INDEX) THEN
    BEGIN

      UPDATE RGN_REPORT_LPARAMS
      SET SORT_INDEX = :I$SORT_INDEX
      WHERE OBJ_ID = :OBJ_ID;

    END

  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE RGN_POSTFIX (
    I$OBJ_ID BIGINT)
AS
declare variable V$LAST_ID bigint;
declare variable V$OLD_ID bigint;
begin

  SELECT FIRST 1 L.TYPE_ID
  FROM RGN_REPORT_LEVELS L
  WHERE L.DATE_DEL IS NULL AND L.REPORT_ID = :I$OBJ_ID
  ORDER BY L.SORT_INDEX DESC
  INTO :V$LAST_ID;

  SELECT R.LAST_TYPE_ID
  FROM RGN_REPORTS R
  WHERE R.OBJ_ID = :I$OBJ_ID
  INTO :V$OLD_ID;

  IF(COALESCE(V$LAST_ID, 0) <> COALESCE(V$OLD_ID, 0)) THEN
  BEGIN
    UPDATE RGN_REPORTS
    SET LAST_TYPE_ID = :V$LAST_ID
    WHERE OBJ_ID = :I$OBJ_ID;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE RGN_REPORT_DELETE (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
AS
begin

  IF(NOT EXISTS(
    SELECT 1
    FROM RGN_REPORTS
    WHERE OBJ_ID = :I$OBJ_ID AND DATE_DEL IS NULL
  ))
  THEN EXCEPTION DATA_ERROR 'Запись не найдена';

  UPDATE RGN_REPORTS
  SET DATE_DEL = CURRENT_TIMESTAMP
  WHERE OBJ_ID = :I$OBJ_ID;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE RGN_REPORT_GET (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
declare variable V$OBJ_ID bigint;
declare variable V$OBJ_NAME varchar(400);
declare variable V$ICON_NAME varchar(100);
declare variable V$COLOR varchar(40);
declare variable V$SORT_INDEX integer;
declare variable V$IS_LIVE smallint;
declare variable V$SIZE smallint;
declare variable V$IS_ARCHIVE smallint;
declare variable V$PARENT_ID bigint;
declare variable V$LIST_MODE smallint;
declare variable V$LEVEL integer;
declare variable V$TYPE_ID bigint;
declare variable V$EV varchar(200);
declare variable V$EV2 integer;
declare variable V$TAB_NAME varchar(400);
begin

  SELECT R.OBJ_ID, R.OBJ_NAME, R.ICON_NAME, R.COLOR, R.SORT_INDEX, R.IS_LIVE, R.TILE_SIZE, R.IS_ARCHIVE
  FROM RGN_REPORTS R
  WHERE R.DATE_DEL IS NULL AND R.OBJ_ID = :I$OBJ_ID
  INTO :V$OBJ_ID, :V$OBJ_NAME, :V$ICON_NAME, :V$COLOR, :V$SORT_INDEX, :V$IS_LIVE, :V$SIZE, :V$IS_ARCHIVE;

  IF(I$OBJ_ID IS NOT NULL AND V$OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Запись не найдена или была удалена';

  SELECT KEY_VAL
  FROM KEYS
  WHERE KEY_CODE = 'LEVEL'
  INTO :V$LEVEL;

  TAG_NAME = 'id';
  VAL = V$OBJ_ID;
  SUSPEND;
  TAG_NAME = 'name';
  VAL = V$OBJ_NAME;
  SUSPEND;
  TAG_NAME = 'icon';
  VAL = V$ICON_NAME;
  SUSPEND;
  TAG_NAME = 'color';
  VAL = V$COLOR;
  SUSPEND;
  TAG_NAME = 'size';
  VAL = V$SIZE;
  SUSPEND;
  TAG_NAME = 'live';
  VAL = V$IS_LIVE;
  SUSPEND;
  TAG_NAME = 'archive';
  VAL = V$IS_ARCHIVE;
  SUSPEND;
  TAG_NAME = 'sort_index';
  VAL = V$SORT_INDEX;
  SUSPEND;

  -- Справочник типов объектов
  TAG_NAME = 'types::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT T.TYPE_ID, R.VAL
    FROM TYPES T
    JOIN RES R ON R.RES_ID = T.RES_ID AND R.LANG_CODE = 'RU'
    WHERE T.TYPE_ID IN (2, 111, 112, 17, /* Обучающиеся */ 7, 8, 9, 10, 20, 125, 187, /* Сотрудники и должности */ 13, 14, 15, 31, 33, 34, 35, 36, 37, 38, 39, 40, 156, 211, 376,
      /* Здания и помещения */ 73, 16, 61, /* Оснащение */ 74, 92, 94, 104, 105, 106, 107, 108, 109)
    ORDER BY 1
    INTO :V$OBJ_ID, :V$OBJ_NAME
  DO
  BEGIN
    TAG_NAME = 'types:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'types:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'types:r:name';
    VAL = V$OBJ_NAME;
    SUSPEND;
    -- Параметры, которые могут быть видны для данной лицензии
    TAG_NAME = 'types:r:params::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT DISTINCT P.PARAM_ID, R.VAL, P.PARAM_TYPE, TR.VAL
      FROM PARAMS P
      JOIN RES R ON R.RES_ID = P.RES_ID AND R.LANG_CODE = 'RU'
      JOIN LPARAMS LP ON LP.PARAM_ID = P.PARAM_ID AND LP.IS_DEL = 0 AND LP.EDIT_TYPE >= 0
      JOIN LEVELS L ON L.LEVEL_ID = LP.LEVEL_ID AND L.IS_DEL = 0
      JOIN TASKS T ON T.TASK_ID = L.TASK_ID AND T.IS_DEL = 0
      JOIN MODULES M ON M.MODULE_ID = T.MODULE_ID AND M.IS_DEL = 0 AND M.IS_ACTIVE = 1
      LEFT JOIN TABS TB ON TB.TAB_ID = P.TAB_ID
      LEFT JOIN RES TR ON TR.RES_ID = TB.RES_ID AND TR.LANG_CODE = 'RU'
      WHERE P.IS_DEL = 0 AND P.TYPE_ID = :V$OBJ_ID
      ORDER BY P.GRID_ORDER
      INTO :V$PARENT_ID, :V$OBJ_NAME, :V$TYPE_ID, :V$TAB_NAME
    DO
    BEGIN
      TAG_NAME = 'types:r:params:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'types:r:params:r:id';
      VAL = V$PARENT_ID;
      SUSPEND;
      TAG_NAME = 'types:r:params:r:name';
      VAL = V$OBJ_NAME;
      SUSPEND;
      TAG_NAME = 'types:r:params:r:type';
      VAL = V$TYPE_ID;
      SUSPEND;
      TAG_NAME = 'types:r:params:r:tab_name';
      VAL = V$TAB_NAME;
      SUSPEND;
    END
  END

  -- Справочник допустимой иерархии объектов
  -- Отдаем что есть для данной лицензии, а там как получится; отдельно выдаем корень
  TAG_NAME = 'parents::json&colon;array';
  VAL = 1;
  SUSPEND;
  -- Теперь сами
  FOR
    SELECT TYPE_ID, CHILD_ID
    FROM RGN_REPORT_LINKS
    INTO :V$PARENT_ID, :V$OBJ_ID
  DO
  BEGIN
    TAG_NAME = 'parents:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'parents:r:type_id';
    VAL = V$PARENT_ID;
    SUSPEND;
    TAG_NAME = 'parents:r:child_id';
    VAL = V$OBJ_ID;
    SUSPEND;
  END

  -- Уровни объектов отчета
  TAG_NAME = 'items::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L.OBJ_ID, L.PARENT_ID, L.LIST_MODE, L.TYPE_ID, L.SORT_INDEX
    FROM RGN_REPORT_LEVELS L
    WHERE L.DATE_DEL IS NULL AND L.REPORT_ID = :I$OBJ_ID
    ORDER BY L.SORT_INDEX
    INTO :V$OBJ_ID, :V$PARENT_ID, :V$LIST_MODE, :V$TYPE_ID, :V$SORT_INDEX
  DO
  BEGIN
    TAG_NAME = 'items:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'items:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'items:r:parent_id';
    VAL = V$PARENT_ID;
    SUSPEND;
    TAG_NAME = 'items:r:list_mode';
    VAL = V$LIST_MODE;
    SUSPEND;
    TAG_NAME = 'items:r:type_id';
    VAL = V$TYPE_ID;
    SUSPEND;
    TAG_NAME = 'items:r:sort_index';
    VAL = V$SORT_INDEX;
    SUSPEND;

    -- Выводимые поля
    TAG_NAME = 'items:r:params::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT P.PARAM_ID, P.PARAM_ALIAS
      FROM RGN_REPORT_LPARAMS P
      WHERE P.DATE_DEL IS NULL AND P.LEVEL_ID = :V$OBJ_ID
      ORDER BY P.SORT_INDEX
      INTO :V$PARENT_ID, :V$OBJ_NAME
    DO
    BEGIN
      TAG_NAME = 'items:r:params:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'items:r:params:r:id';
      VAL = V$PARENT_ID;
      SUSPEND;
      TAG_NAME = 'items:r:params:r:alias';
      VAL = V$OBJ_NAME;
      SUSPEND;
    END

    -- Фильтры по полям
    TAG_NAME = 'items:r:filters::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT P.OBJ_ID, P.PARAM_ID, P.EQU_INDEX, P.EQU_VALUE, P.EQU_VALUE2, PT.TYPE_ID
      FROM RGN_REPORT_LFILTERS P
      JOIN PARAMS PT ON PT.PARAM_ID = P.PARAM_ID
      WHERE P.DATE_DEL IS NULL AND P.LEVEL_ID = :V$OBJ_ID
      ORDER BY P.SORT_INDEX
      INTO :V$TYPE_ID, :V$PARENT_ID, :V$LEVEL, :V$EV, :V$EV2, :V$LIST_MODE
    DO
    BEGIN
      TAG_NAME = 'items:r:filters:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'items:r:filters:r:id';
      VAL = V$TYPE_ID;
      SUSPEND;
      TAG_NAME = 'items:r:filters:r:param_id';
      VAL = V$PARENT_ID;
      SUSPEND;
      TAG_NAME = 'items:r:filters:r:equ';
      VAL = V$LEVEL;
      SUSPEND;
      TAG_NAME = 'items:r:filters:r:value';
      VAL = V$EV;
      SUSPEND;
      TAG_NAME = 'items:r:filters:r:value2';
      VAL = V$EV2;
      SUSPEND;
      -- Для списковых значений делаем расшифровку значения
      IF(V$LIST_MODE = 6) THEN
      BEGIN
        TAG_NAME = 'items:r:filters:r:value_text';
        VAL = NULL;
        SELECT R.VAL
        FROM LISTVALS LV
        JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
        WHERE LV.LISTVAL_ID = CAST(:V$EV AS BIGINT)
        INTO :VAL;
        SUSPEND;
      END
    END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE RGN_REPORT_LINKS RETURNS (
    TYPE_ID BIGINT,
    CHILD_ID BIGINT)
AS
declare variable V$TYPE char(1);
declare variable V$LEVEL smallint;
begin

  SELECT STATUS FROM OU_LICENCE_TYPE INTO :V$TYPE;
  SELECT KEY_VAL FROM KEYS WHERE KEY_CODE = 'LEVEL' INTO :V$LEVEL;

  TYPE_ID = NULL;
  IF(V$LEVEL = 3) THEN CHILD_ID = 112;
  ELSE IF(V$LEVEL = 2) THEN CHILD_ID = 111;
  ELSE CHILD_ID = 2;
  SUSPEND;

  IF(V$LEVEL >= 2) THEN
  BEGIN
    TYPE_ID = 111;
    CHILD_ID = 2;
    SUSPEND;
  END

  IF(V$LEVEL >= 2) THEN
  BEGIN
    TYPE_ID = 112;
    CHILD_ID = 111;
    SUSPEND;
  END

  FOR
    SELECT DISTINCT P.TYPE_ID, P.CHILD_ID
    FROM LTYPES LT
    JOIN LEVELS L ON L.LEVEL_ID = LT.LEVEL_ID AND L.IS_DEL = 0
    JOIN TASKS T ON T.TASK_ID = L.TASK_ID AND T.IS_DEL = 0
    JOIN MODULES M ON M.MODULE_ID = T.MODULE_ID AND M.IS_DEL = 0 AND M.IS_ACTIVE = 1
    -- дочерние тоже должны быть видимы
    JOIN PARENTS P ON P.TYPE_ID = LT.TYPE_ID AND P.IS_DEL = 0
    JOIN LTYPES LT2 ON LT2.LEVEL_ID = LT.LEVEL_ID AND LT2.TYPE_ID = P.CHILD_ID AND LT2.IS_DEL = 0
    WHERE LT.IS_DEL = 0 AND LT.EDIT_TYPE >= 0
      -- В пределах уровней: учебные коллективы, сотрудники, личные дела, должности и т.д.
      AND (:V$TYPE = 'O' AND LT.LEVEL_ID IN (205, 15, 57, 24, 48, 56, 49, 50, 52, 53, 126,
        /* DISTR */ 11, 17, 27, 65, 116, 120, 128, 213,
        /* REG */ 12, 18, 29, 66, 121, 127, 214))
    INTO :TYPE_ID, :CHILD_ID
  DO
  BEGIN
    -- Прячем пару *->2
    IF(CHILD_ID <> 2) THEN SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE RGN_REPORT_SET (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40),
    I$NAME VARCHAR(400),
    I$ICON VARCHAR(100),
    I$COLOR VARCHAR(40),
    I$SIZE SMALLINT,
    I$LIVE SMALLINT,
    I$IS_ARCHIVE SMALLINT,
    I$SORT_INDEX INTEGER)
RETURNS (
    OBJ_ID BIGINT)
AS
begin

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  IF(I$OBJ_ID IS NULL) THEN
  BEGIN

    INSERT INTO RGN_REPORTS
    (OBJ_NAME, ICON_NAME, COLOR, IS_LIVE, USER_ID, SORT_INDEX, TILE_SIZE, IS_ARCHIVE)
    VALUES (:I$NAME, :I$ICON, :I$COLOR, :I$LIVE, :I$USER_ID, :I$SORT_INDEX, :I$SIZE, :I$IS_ARCHIVE)
    RETURNING OBJ_ID INTO :OBJ_ID;

  END
  ELSE
  BEGIN

    SELECT R.OBJ_ID
    FROM RGN_REPORTS R
    WHERE R.OBJ_ID = :I$OBJ_ID AND R.DATE_DEL IS NULL
    INTO :OBJ_ID;

    IF(OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Запись не найдена или была удалена';

    UPDATE RGN_REPORTS
    SET OBJ_NAME = :I$NAME, ICON_NAME = :I$ICON, COLOR = :I$COLOR, IS_LIVE = :I$LIVE, SORT_INDEX = :I$SORT_INDEX, TILE_SIZE = :I$SIZE, IS_ARCHIVE = :I$IS_ARCHIVE
    WHERE OBJ_ID = :OBJ_ID;

  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE RIK83 (
    I$OBJ_ID BIGINT,
    I$N INTEGER,
    I$SELF_FL SMALLINT = 0)
RETURNS (
    V03 INTEGER,
    V04 NUMERIC(11,2),
    V05 INTEGER,
    V06 INTEGER,
    V07 INTEGER,
    V08 INTEGER,
    V09 INTEGER,
    V10 INTEGER,
    V11 INTEGER,
    V12 INTEGER,
    V13 INTEGER,
    V14 INTEGER,
    V15 INTEGER,
    V16 INTEGER,
    V17 INTEGER,
    V18 INTEGER,
    V19 INTEGER,
    V20 INTEGER,
    V21 INTEGER,
    V22 INTEGER,
    V23 INTEGER,
    V24 INTEGER,
    V25 INTEGER,
    V26 INTEGER,
    V27 INTEGER,
    V28 INTEGER,
    V29 INTEGER,
    V30 INTEGER)
AS
declare variable POST_ID bigint;
declare variable POST_GROUP bigint;
declare variable POST_PODGROUP bigint;
declare variable POST_FUNC bigint;
declare variable V400LISTVAL_ID bigint;
declare variable POST_NAME varchar(4000);
declare variable V varchar(4000);
declare variable WORKER_ID bigint;
declare variable OU_TYPE bigint;
declare variable CORRECT_CLASS integer;
declare variable G smallint;
declare variable N smallint;
BEGIN
    V03 = 0;

    V05 = 0;
    V06 = 0;
    V07 = 0;
    V08 = 0;
    V09 = 0;
    V10 = 0;
    V11 = 0;
    V12 = 0;
    V13 = 0;
    V14 = 0;
    V15 = 0;
    V16 = 0;
    V17 = 0;
    V18 = 0;
    V19 = 0;
    V20 = 0;
    V21 = 0;
    V22 = 0;
    V23 = 0;
    V24 = 0;
    V25 = 0;
    V26 = 0;
    V27 = 0;
    V28 = 0;
    V29 = 0;
    V30 = 0;

    FOR SELECT L14.OBJ_ID, V69.VAL, V63.LISTVAL_ID, V64.LISTVAL_ID, V58.LISTVAL_ID,
           (SELECT SORT_ORDER FROM DO_FUNC(V69.VAL, 400)), V66.VAL, V11.LISTVAL_ID
        FROM LINKS L14
        INNER JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID
        INNER JOIN VALL V11 ON V11.OBJ_ID = L14.PARENT_ID
        INNER JOIN VALL V72 ON V72.OBJ_ID = L15.OBJ_ID
        INNER JOIN VALR V69 ON V69.OBJ_ID = L15.OBJ_ID
        INNER JOIN VALL V63 ON V63.OBJ_ID = V69.VAL
        INNER JOIN VALL V64 ON V64.OBJ_ID = V69.VAL
        INNER JOIN VALL V58 ON V58.OBJ_ID = V69.VAL
        INNER JOIN VALS V66 ON V66.OBJ_ID = V69.VAL
        LEFT JOIN VALD V74 ON V74.PARAM_ID = 74 AND V74.OBJ_ID = L15.OBJ_ID AND V74.IS_DEL = 0
        LEFT JOIN VALL V274 ON V274.PARAM_ID = 274 AND V274.OBJ_ID = L14.OBJ_ID AND V274.IS_DEL = 0
        WHERE L14.PARENT_ID = :I$OBJ_ID
          AND L14.OBJ_TYPE_ID = 14
          AND L14.DATE_DEL IS NULL
          AND L15.OBJ_TYPE_ID = 15
          AND L15.DATE_DEL IS NULL
          AND V72.PARAM_ID = 72
          AND V72.IS_DEL = 0
          AND V72.LISTVAL_ID = 934
          AND V69.PARAM_ID = 69
          AND V69.IS_DEL = 0
          AND V63.PARAM_ID = 63
          AND V63.IS_DEL = 0
          AND V64.PARAM_ID = 64
          AND V64.IS_DEL = 0
          AND V58.PARAM_ID = 58
          AND V58.IS_DEL = 0
          AND V66.PARAM_ID = 66
          AND V66.IS_DEL = 0
          AND V74.VAL IS NULL
          AND V11.PARAM_ID = 11
          AND V11.IS_DEL = 0
          AND ((V274.LISTVAL_ID IS NULL) OR (V274.LISTVAL_ID = 602) OR (V274.LISTVAL_ID = 604))
        INTO :WORKER_ID, :POST_ID, :POST_GROUP, :POST_PODGROUP, :POST_FUNC, :V400LISTVAL_ID, :POST_NAME, :OU_TYPE
    DO
    BEGIN
        IF ((I$N >= 1) AND (I$N <= 40) AND (POST_FUNC <> 1267) AND (POST_FUNC <> 1284) AND (POST_FUNC <> 1298)) THEN
        BEGIN
            IF (I$N = 1) THEN
            BEGIN
                SELECT X03, X04, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21,
                       X22, X23, X24, X25, X26, X27, X28, X29, X30
                FROM RIK83_INFO(:POST_ID, :WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18,
                     :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30;
                V = POST_NAME;
            END
            ELSE
            IF ((I$N >= 2) AND (I$N <= 6) AND (POST_GROUP = 55)) THEN
            BEGIN
                IF ((I$N = 2) AND (POST_GROUP = 55)) THEN
                BEGIN
                    SELECT X03, X04, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20,
                           X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                    FROM RIK83_INFO(:POST_ID, :WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                    INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18,
                         :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30;
                    V = POST_NAME;
                END
                ELSE
                BEGIN
                    IF (POST_FUNC = 69) THEN
                    BEGIN
                        IF (I$N = 5) THEN
                        BEGIN
                            SELECT X03, X04, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19,
                                   X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                            FROM RIK83_INFO(:POST_ID, :WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                            INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16,
                                 :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30;
                            V = POST_NAME;
                        END
                    END
                    ELSE
                    IF (POST_PODGROUP = 56) THEN
                    BEGIN
                        IF (I$N = 3) THEN
                        BEGIN
                            SELECT X03, X04, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19,
                                   X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                            FROM RIK83_INFO(:POST_ID, :WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                            INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16,
                                 :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30;
                            V = POST_NAME;
                        END
                    END
                    ELSE
                    IF (POST_PODGROUP = 113) THEN
                    BEGIN
                        IF (I$N = 4) THEN
                        BEGIN
                            SELECT X03, X04, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19,
                                   X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                            FROM RIK83_INFO(:POST_ID, :WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                            INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16,
                                 :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30;
                            V = POST_NAME;
                        END
                    END
                    ELSE
                    IF (POST_PODGROUP = 70) THEN
                    BEGIN
                        IF (I$N = 6) THEN
                        BEGIN
                            SELECT X03, X04, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19,
                                   X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                            FROM RIK83_INFO(:POST_ID, :WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                            INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16,
                                 :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30;
                            V = POST_NAME;
                        END
                    END
                END
            END
            ELSE
            IF ((I$N >= 7) AND (I$N <= 35) AND (POST_GROUP = 97)) THEN
            BEGIN
                IF (I$N = 7 AND V400LISTVAL_ID = 2) THEN
                BEGIN
                    SELECT X03, NULL, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20,
                           X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                    FROM RIK83_INFO(:POST_ID, :WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                    INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18,
                         :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30;
                    V = POST_NAME;
                END
                ELSE
                BEGIN
                    IF (POST_FUNC = 119) THEN
                    BEGIN
                        IF (I$N = 29) THEN
                        BEGIN
                            SELECT X03, NULL, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19,
                                   X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                            FROM RIK83_INFO(:POST_ID, :WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                            INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16,
                                 :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30;
                            V = POST_NAME;
                        END
                    END
                    ELSE
                    IF (POST_FUNC = 130) THEN
                    BEGIN
                        IF (I$N = 30) THEN
                        BEGIN
                            SELECT X03, NULL, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19,
                                   X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                            FROM RIK83_INFO(:POST_ID, :WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                            INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16,
                                 :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30;
                            V = POST_NAME;
                        END
                    END
                    ELSE
                    IF (POST_FUNC = 145) THEN
                    BEGIN
                        IF (I$N = 31) THEN
                        BEGIN
                            SELECT X03, NULL, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19,
                                   X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                            FROM RIK83_INFO(:POST_ID, :WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                            INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16,
                                 :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30;
                            V = POST_NAME;
                        END
                    END
                    ELSE
                    IF (POST_FUNC = 1251) THEN
                    BEGIN
                        IF (I$N = 32) THEN
                        BEGIN
                            SELECT X03, NULL, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19,
                                   X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                            FROM RIK83_INFO(:POST_ID, :WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                            INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16,
                                 :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30;
                            V = POST_NAME;
                        END
                    END
                    ELSE
                    IF (POST_FUNC = 1291) THEN
                    BEGIN
                        IF (I$N = 34) THEN
                        BEGIN
                            SELECT X03, NULL, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19,
                                   X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                            FROM RIK83_INFO(:POST_ID, :WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                            INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16,
                                 :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30;
                            V = POST_NAME;
                        END
                    END
                    ELSE
                    IF (POST_PODGROUP = 125) THEN
                    BEGIN
                        IF (I$N = 33) THEN
                        BEGIN
                            SELECT X03, NULL, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19,
                                   X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                            FROM RIK83_INFO(:POST_ID, :WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                            INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16,
                                 :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30;
                            V = POST_NAME;
                        END
                    END
                    ELSE
                    IF (POST_PODGROUP = 98) THEN
                    BEGIN
                        IF ((I$N = 8) OR ((I$N = 36) AND (OU_TYPE = 978))) THEN
                        BEGIN
                            SELECT X03, NULL, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19,
                                   X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                            FROM RIK83_INFO(:POST_ID, :WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                            INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16,
                                 :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30;
                            V = POST_NAME;
                        END
                        ELSE
                        BEGIN
                            IF (POST_FUNC = 108) THEN
                            BEGIN
                                IF (I$N = 9) THEN
                                BEGIN
                                    SELECT X03, NULL, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17,
                                           X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                                    FROM RIK83_INFO(:POST_ID, :WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                                    INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15,
                                         :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28,
                                         :V29, :V30;
                                    V = POST_NAME;
                                END
                            END
                            ELSE
                            IF ((POST_FUNC = 112) OR (POST_FUNC = 1260)) THEN
                            BEGIN
                                IF (I$N = 10) THEN
                                BEGIN
                                    SELECT X03, NULL, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17,
                                           X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                                    FROM RIK83_INFO(:POST_ID, :WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                                    INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15,
                                         :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28,
                                         :V29, :V30;
                                    V = POST_NAME;
                                END
                            END
                            ELSE
                            IF ((POST_FUNC = 104) OR (POST_FUNC = 1268) OR (POST_FUNC = 1273) OR (POST_FUNC = 1278)) THEN
                            BEGIN
                                IF (I$N = 12) THEN
                                BEGIN
                                    SELECT X03, NULL, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17,
                                           X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                                    FROM RIK83_INFO(:POST_ID, :WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                                    INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15,
                                         :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28,
                                         :V29, :V30;
                                    V = POST_NAME;
                                END
                            END
                            ELSE
                            IF (POST_FUNC = 105) THEN
                            BEGIN
                                IF (I$N = 13) THEN
                                BEGIN
                                    SELECT X03, NULL, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17,
                                           X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                                    FROM RIK83_INFO(:POST_ID, :WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                                    INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15,
                                         :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28,
                                         :V29, :V30;
                                    V = POST_NAME;
                                END
                            END
                            ELSE
                            IF (POST_FUNC = 102) THEN
                            BEGIN
                                IF (I$N = 14) THEN
                                BEGIN
                                    SELECT X03, NULL, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17,
                                           X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                                    FROM RIK83_INFO(:POST_ID, :WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                                    INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15,
                                         :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28,
                                         :V29, :V30;
                                    V = POST_NAME;
                                END
                            END
                            ELSE
                            IF (POST_FUNC = 115) THEN
                            BEGIN
                                IF (I$N = 15) THEN
                                BEGIN
                                    SELECT X03, NULL, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17,
                                           X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                                    FROM RIK83_INFO(:POST_ID, :WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                                    INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15,
                                         :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28,
                                         :V29, :V30;
                                    V = POST_NAME;
                                END
                            END
                            ELSE
                            IF (POST_FUNC = 118) THEN
                            BEGIN
                                IF (I$N = 16) THEN
                                BEGIN
                                    SELECT X03, NULL, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17,
                                           X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                                    FROM RIK83_INFO(:POST_ID, :WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                                    INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15,
                                         :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28,
                                         :V29, :V30;
                                    V = POST_NAME;
                                END
                            END
                            ELSE
                            IF (POST_FUNC = 101) THEN
                            BEGIN
                                IF (I$N = 17) THEN
                                BEGIN
                                    SELECT X03, NULL, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17,
                                           X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                                    FROM RIK83_INFO(:POST_ID, :WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                                    INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15,
                                         :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28,
                                         :V29, :V30;
                                    V = POST_NAME;
                                END
                            END
                            ELSE
                            IF (POST_FUNC = 100) THEN
                            BEGIN
                                IF (I$N = 18) THEN
                                BEGIN
                                    SELECT X03, NULL, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17,
                                           X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                                    FROM RIK83_INFO(:POST_ID, :WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                                    INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15,
                                         :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28,
                                         :V29, :V30;
                                    V = POST_NAME;
                                END
                            END
                            ELSE
                            IF (POST_FUNC = 99) THEN
                            BEGIN
                                IF (I$N = 19) THEN
                                BEGIN
                                    SELECT X03, NULL, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17,
                                           X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                                    FROM RIK83_INFO(:POST_ID, :WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                                    INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15,
                                         :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28,
                                         :V29, :V30;
                                    V = POST_NAME;
                                END
                            END
                            ELSE
                            IF (POST_FUNC = 109) THEN
                            BEGIN
                                IF (I$N = 20) THEN
                                BEGIN
                                    SELECT X03, NULL, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17,
                                           X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                                    FROM RIK83_INFO(:POST_ID, :WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                                    INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15,
                                         :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28,
                                         :V29, :V30;
                                    V = POST_NAME;
                                END
                            END
                            ELSE
                            IF (POST_FUNC = 117) THEN
                            BEGIN
                                IF (I$N = 21) THEN
                                BEGIN
                                    SELECT X03, NULL, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17,
                                           X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                                    FROM RIK83_INFO(:POST_ID, :WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                                    INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15,
                                         :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28,
                                         :V29, :V30;
                                    V = POST_NAME;
                                END
                            END
                            ELSE
                            IF (POST_FUNC = 1264) THEN
                            BEGIN
                                IF (I$N = 22) THEN
                                BEGIN
                                    SELECT X03, NULL, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17,
                                           X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                                    FROM RIK83_INFO(:POST_ID, :WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                                    INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15,
                                         :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28,
                                         :V29, :V30;
                                    V = POST_NAME;
                                END
                            END
                            ELSE
                            IF (POST_FUNC = 106) THEN
                            BEGIN
                                IF (I$N = 23) THEN
                                BEGIN
                                    SELECT X03, NULL, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17,
                                           X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                                    FROM RIK83_INFO(:POST_ID, :WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                                    INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15,
                                         :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28,
                                         :V29, :V30;
                                    V = POST_NAME;
                                END
                            END
                            ELSE
                            IF (POST_FUNC IN (111, 3148)) THEN
                            BEGIN
                                IF (I$N = 24) THEN
                                BEGIN
                                    SELECT X03, NULL, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17,
                                           X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                                    FROM RIK83_INFO(:POST_ID, :WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                                    INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15,
                                         :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28,
                                         :V29, :V30;
                                    V = POST_NAME;
                                END
                            END
                            ELSE
                            IF (POST_FUNC IN (110, 121)) THEN
                            BEGIN
                                IF (I$N = 25) THEN
                                BEGIN
                                    SELECT X03, NULL, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17,
                                           X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                                    FROM RIK83_INFO(:POST_ID, :WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                                    INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15,
                                         :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28,
                                         :V29, :V30;
                                    V = POST_NAME;
                                END
                            END
                            ELSE
                            IF (POST_FUNC = 116) THEN
                            BEGIN
                                IF (I$N = 26) THEN
                                BEGIN
                                    SELECT X03, NULL, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17,
                                           X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                                    FROM RIK83_INFO(:POST_ID, :WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                                    INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15,
                                         :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28,
                                         :V29, :V30;
                                    V = POST_NAME;
                                END
                            END
                            ELSE
                            IF (POST_FUNC = 114) THEN
                            BEGIN
                                IF (I$N = 27) THEN
                                BEGIN
                                    SELECT X03, NULL, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17,
                                           X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                                    FROM RIK83_INFO(:POST_ID, :WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                                    INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15,
                                         :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28,
                                         :V29, :V30;
                                    V = POST_NAME;
                                END
                            END
                            ELSE
                            IF (I$N = 28) THEN
                            BEGIN
                                SELECT X03, NULL, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18,
                                       X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                                FROM RIK83_INFO(:POST_ID, :WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                                INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16,
                                     :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30;
                                V = POST_NAME;
                            END
                        END
                    END
                    ELSE
                    IF (I$N = 35 AND V400LISTVAL_ID = 2) THEN
                    BEGIN
                        SELECT X03, NULL, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19,
                               X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                        FROM RIK83_INFO(:POST_ID, :WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                        INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17,
                             :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30;
                        V = POST_NAME;
                    END
                END
            END
            ELSE
            IF ((I$N = 36) AND (OU_TYPE <> 978) AND (POST_GROUP = 97)) THEN
            BEGIN
                CORRECT_CLASS = 0;

                SELECT FIRST 1 1
                FROM LINKS L58
                INNER JOIN LINKS L9 ON L9.OBJ_ID = L58.OBJ_ID
                INNER JOIN VALL V592 ON V592.OBJ_ID = L9.PARENT_ID
                WHERE L58.PARENT_ID = :WORKER_ID
                  AND L58.OBJ_TYPE_ID = 58
                  AND L58.DATE_DEL IS NULL
                  AND L9.PARENT_TYPE_ID = 9
                  AND L9.DATE_DEL IS NULL
                  AND V592.PARAM_ID = 592
                  AND V592.IS_DEL = 0
                  AND V592.LISTVAL_ID > 197
                INTO :CORRECT_CLASS;

                IF (CORRECT_CLASS = 1) THEN
                BEGIN
                    SELECT X03, NULL, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20,
                           X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                    FROM RIK83_INFO(:POST_ID, :WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                    INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18,
                         :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30;
                    V = POST_NAME;
                END
            END
            ELSE
            IF ((I$N >= 38) AND (I$N <= 39) AND (POST_GROUP = 1310 OR (POST_GROUP = 97 AND V400LISTVAL_ID <> 2))) THEN
            BEGIN
                IF (I$N = 38) THEN
                BEGIN
                    SELECT X03, X04, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20,
                           X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                    FROM RIK83_INFO(:POST_ID, :WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                    INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18,
                         :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30;
                    V = POST_NAME;
                END
            END
            ELSE
            IF ((I$N = 40) AND (POST_GROUP = 1323)) THEN
            BEGIN
                SELECT X03, X04, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21,
                       X22, X23, X24, X25, X26, X27, X28, X29, X30
                FROM RIK83_INFO(:POST_ID, :WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18,
                     :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30;
                V = POST_NAME;
            END
        END
        ELSE
        IF ((I$N = 41) AND ((POST_FUNC = 1267) OR (POST_FUNC = 1284) OR (POST_FUNC = 1298))) THEN
        BEGIN
            V03 = :V03 + 1;
            V = POST_NAME;
        END
        ELSE
        IF ((I$N = 42) AND ((POST_FUNC = 1267) OR (POST_FUNC = 1284) OR (POST_FUNC = 1298))) THEN
        BEGIN
            SELECT X05 + X14
            FROM RIK83_INFO(:POST_ID, :WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14)
            INTO :V05;
            V = POST_NAME;
        END
        ELSE
        IF ((I$N = 43) AND (POST_FUNC = 1267)) THEN
        BEGIN
            V03 = :V03 + 1;
            V = POST_NAME;
        END
        ELSE
        IF ((I$N = 44) AND ((POST_FUNC = 1284) OR (POST_FUNC = 1298))) THEN
        BEGIN
            V03 = :V03 + 1;
            V = POST_NAME;
        END
        ELSE
        IF ((I$N = 45) AND (POST_FUNC = 120)) THEN
        BEGIN
            SELECT X03
            FROM RIK83_INFO(:POST_ID, :WORKER_ID, :V03)
            INTO :V03;
        END
        ELSE
        IF ((I$N = 46) AND (POST_FUNC = 120)) THEN
        BEGIN
            SELECT :V03 + X13
            FROM RIK83_INFO(:POST_ID, :WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13)
            INTO :V03;
        END
        ELSE
        IF ((I$N = 47) AND (POST_PODGROUP = 98)) THEN
        BEGIN
            SELECT :V03 + IIF(AGE < 30, 1, 0)
            FROM RIK83_INFO(:POST_ID, :WORKER_ID, 0)
            INTO :V03;
        END
        IF ((I$N = 48) AND (POST_GROUP = 55)) THEN
        BEGIN
            SELECT :V03 +  IIF((
                SELECT FIRST 1 1
                FROM LINKS L36
                INNER JOIN VALD V310 ON V310.OBJ_ID = L36.OBJ_ID
                WHERE L36.PARENT_ID = :WORKER_ID
                  AND L36.OBJ_TYPE_ID IN (35, 36)
                  AND L36.DATE_DEL IS NULL
                  AND V310.PARAM_ID IN (300, 310)
                  AND V310.IS_DEL = 0
                  AND V310.VAL >= DATEADD(-3 YEAR TO CURRENT_DATE)) = 1, 1, 0)
            FROM RIK83_INFO(:POST_ID, :WORKER_ID, 0)
            INTO :V03;
        END

    END

    /* FREE POSTS */
    /* STAVKI UCHITEL - OTDELNO */
    IF (:I$N BETWEEN 9 AND 28) THEN
    BEGIN
        SELECT
            IIF(SUM(IIF(N = :I$N, 1, 0)) = 0, NULL, SUM(X04) + (
                SELECT COALESCE(SUM(V.VAL), 0)
                FROM LINKS L2
                INNER JOIN VALF V ON V.OBJ_ID = L2.OBJ_ID
                WHERE L2.DATE_DEL IS NULL
                  AND L2.OBJ_TYPE_ID = 2
                  AND V.PARAM_ID = 1342
                  AND V.IS_DEL = 0
                  AND L2.OBJ_ID = :I$OBJ_ID)) V04,
            COUNT(DISTINCT(N)) G,
            MAX(N) N
        FROM (
            SELECT
                IIF(LV.TAG = 'U', 0, COALESCE(V62.VAL, 0)) - (SELECT Z FROM RIK83_STAVOK(L13.OBJ_ID)) X04,
                CASE
                    WHEN V58.LISTVAL_ID = 108 THEN 9
                    WHEN V58.LISTVAL_ID IN (112, 1260) THEN 10
                    WHEN V64.LISTVAL_ID = 70 THEN 11
                    WHEN V58.LISTVAL_ID IN (104, 1268, 1273, 1278) THEN 12
                    WHEN V58.LISTVAL_ID = 105 THEN 13
                    WHEN V58.LISTVAL_ID = 102 THEN 14
                    WHEN V58.LISTVAL_ID = 115 THEN 15
                    WHEN V58.LISTVAL_ID = 118 THEN 16
                    WHEN V58.LISTVAL_ID = 101 THEN 17
                    WHEN V58.LISTVAL_ID = 100 THEN 18
                    WHEN V58.LISTVAL_ID = 99 THEN 19
                    WHEN V58.LISTVAL_ID = 109 THEN 20
                    WHEN V58.LISTVAL_ID = 117 THEN 21
                    WHEN V58.LISTVAL_ID = 1264 THEN 22
                    WHEN V58.LISTVAL_ID = 106 THEN 23
                    WHEN V58.LISTVAL_ID IN (111, 3148) THEN 24
                    WHEN V58.LISTVAL_ID IN (110, 121) THEN 25
                    WHEN V58.LISTVAL_ID = 116 THEN 26
                    WHEN V58.LISTVAL_ID = 114 THEN 27
                    WHEN V58.LISTVAL_ID NOT IN (119,130,145,1251,1291,108,112,1260,104,1268,1273,1278,105,102,115,118,101,100,99,109,117,1264,106,111,3148,110,121,116,114) THEN 28
                END N
            FROM LINKS L13
            INNER JOIN VALL V11 ON V11.OBJ_ID = :I$OBJ_ID
            INNER JOIN VALL V10 ON V10.OBJ_ID = :I$OBJ_ID
            INNER JOIN VALL V63 ON V63.OBJ_ID = L13.OBJ_ID
            INNER JOIN VALL V64 ON V64.OBJ_ID = L13.OBJ_ID
            INNER JOIN VALL V58 ON V58.OBJ_ID = L13.OBJ_ID
            LEFT JOIN VALF V62 ON V62.OBJ_ID = L13.OBJ_ID
              AND V62.PARAM_ID = 62
              AND V62.IS_DEL = 0
            INNER JOIN LISTVALS LV ON LV.LISTVAL_ID = V58.LISTVAL_ID
            WHERE L13.PARENT_ID = :I$OBJ_ID
              AND V11.PARAM_ID = 11
              AND V11.IS_DEL = 0
              AND V10.PARAM_ID = 10
              AND V10.IS_DEL = 0
              AND L13.OBJ_TYPE_ID = 13
              AND L13.DATE_DEL IS NULL
              AND V63.PARAM_ID = 63
              AND V63.IS_DEL = 0
              AND V64.PARAM_ID = 64
              AND V64.IS_DEL = 0
              AND V58.PARAM_ID = 58
              AND V58.IS_DEL = 0
              AND V58.LISTVAL_ID NOT IN (1267, 1284, 1298)
              AND V63.LISTVAL_ID = 97 AND V64.LISTVAL_ID = 98 AND V58.LISTVAL_ID NOT IN (119,130,145,1251,1291))
        INTO :V04, :G, :N;
        IF (:V04 IS NOT NULL) THEN
        BEGIN
            -- учителя-логопеды
            SELECT IIF(V04 > 0, 0, V04) + :V04
            FROM RIK83(:I$OBJ_ID, 29, 1)
            INTO :V04;
            -- размажем вакансии учителей по всем их должностям
            V04 = :V04/:G + IIF(:I$N = :N, :V04 - (:V04/:G)*:G, 0);
        END
    END
    ELSE
    BEGIN
        SELECT
            X04 + IIF(:I$N IN (1, 7, 8), (
                SELECT COALESCE(SUM(V.VAL), 0)
                FROM LINKS L2
                INNER JOIN VALF V ON V.OBJ_ID = L2.OBJ_ID
                WHERE L2.DATE_DEL IS NULL
                  AND L2.OBJ_TYPE_ID = 2
                  AND V.PARAM_ID = 1342
                  AND V.IS_DEL = 0
                  AND L2.OBJ_ID = :I$OBJ_ID), 0)
        FROM (
            SELECT
                SUM(IIF(LV.TAG = 'U', 0, COALESCE(V62.VAL, 0)) - (SELECT Z FROM RIK83_STAVOK(L13.OBJ_ID))) X04
            FROM LINKS L13
            INNER JOIN VALL V11 ON V11.OBJ_ID = :I$OBJ_ID
            INNER JOIN VALL V10 ON V10.OBJ_ID = :I$OBJ_ID
            INNER JOIN VALL V63 ON V63.OBJ_ID = L13.OBJ_ID
            INNER JOIN VALL V64 ON V64.OBJ_ID = L13.OBJ_ID
            INNER JOIN VALL V58 ON V58.OBJ_ID = L13.OBJ_ID
            LEFT JOIN VALF V62 ON V62.OBJ_ID = L13.OBJ_ID
              AND V62.PARAM_ID = 62
              AND V62.IS_DEL = 0
            INNER JOIN LISTVALS LV ON LV.LISTVAL_ID = V58.LISTVAL_ID
            WHERE L13.PARENT_ID = :I$OBJ_ID
              AND V11.PARAM_ID = 11
              AND V11.IS_DEL = 0
              AND V10.PARAM_ID = 10
              AND V10.IS_DEL = 0
              AND L13.OBJ_TYPE_ID = 13
              AND L13.DATE_DEL IS NULL
              AND V63.PARAM_ID = 63
              AND V63.IS_DEL = 0
              AND V64.PARAM_ID = 64
              AND V64.IS_DEL = 0
              AND V58.PARAM_ID = 58
              AND V58.IS_DEL = 0
              AND V58.LISTVAL_ID NOT IN (1267, 1284, 1298)
              AND ((:I$N = 1)
                OR (:I$N = 2 AND V63.LISTVAL_ID = 55)
                OR (:I$N = 3 AND V63.LISTVAL_ID = 55 AND V64.LISTVAL_ID = 56 AND V58.LISTVAL_ID <> 69)
                OR (:I$N = 4 AND V63.LISTVAL_ID = 55 AND V64.LISTVAL_ID = 113 AND V58.LISTVAL_ID <> 69)
                OR (:I$N = 5 AND V63.LISTVAL_ID = 55 AND V58.LISTVAL_ID = 69)
                OR (:I$N = 6 AND V63.LISTVAL_ID = 55 AND V64.LISTVAL_ID = 70 AND V58.LISTVAL_ID <> 69)
                OR (:I$N = 7 AND V63.LISTVAL_ID = 97 AND (SELECT SORT_ORDER FROM DO_FUNC(L13.OBJ_ID, 400)) = 2)
                OR (:I$N = 8 AND V63.LISTVAL_ID = 97 AND V64.LISTVAL_ID = 98 AND V58.LISTVAL_ID NOT IN (119,130,145,1251,1291))
                OR (:I$N = 9 AND V63.LISTVAL_ID = 97 AND V64.LISTVAL_ID = 98 AND V58.LISTVAL_ID = 108)
                OR (:I$N = 10 AND V63.LISTVAL_ID = 97 AND V64.LISTVAL_ID = 98 AND V58.LISTVAL_ID IN (112, 1260))
                OR (:I$N = 11 AND V63.LISTVAL_ID = 97 AND V64.LISTVAL_ID = 70)
                OR (:I$N = 12 AND V63.LISTVAL_ID = 97 AND V64.LISTVAL_ID = 98 AND V58.LISTVAL_ID IN (104, 1268, 1273, 1278))
                OR (:I$N = 13 AND V63.LISTVAL_ID = 97 AND V64.LISTVAL_ID = 98 AND V58.LISTVAL_ID = 105)
                OR (:I$N = 14 AND V63.LISTVAL_ID = 97 AND V64.LISTVAL_ID = 98 AND V58.LISTVAL_ID = 102)
                OR (:I$N = 15 AND V63.LISTVAL_ID = 97 AND V64.LISTVAL_ID = 98 AND V58.LISTVAL_ID = 115)
                OR (:I$N = 16 AND V63.LISTVAL_ID = 97 AND V64.LISTVAL_ID = 98 AND V58.LISTVAL_ID = 118)
                OR (:I$N = 17 AND V63.LISTVAL_ID = 97 AND V64.LISTVAL_ID = 98 AND V58.LISTVAL_ID = 101)
                OR (:I$N = 18 AND V63.LISTVAL_ID = 97 AND V64.LISTVAL_ID = 98 AND V58.LISTVAL_ID = 100)
                OR (:I$N = 19 AND V63.LISTVAL_ID = 97 AND V64.LISTVAL_ID = 98 AND V58.LISTVAL_ID = 99)
                OR (:I$N = 20 AND V63.LISTVAL_ID = 97 AND V64.LISTVAL_ID = 98 AND V58.LISTVAL_ID = 109)
                OR (:I$N = 21 AND V63.LISTVAL_ID = 97 AND V64.LISTVAL_ID = 98 AND V58.LISTVAL_ID = 117)
                OR (:I$N = 22 AND V63.LISTVAL_ID = 97 AND V64.LISTVAL_ID = 98 AND V58.LISTVAL_ID = 1264)
                OR (:I$N = 23 AND V63.LISTVAL_ID = 97 AND V64.LISTVAL_ID = 98 AND V58.LISTVAL_ID = 106)
                OR (:I$N = 24 AND V63.LISTVAL_ID = 97 AND V64.LISTVAL_ID = 98 AND V58.LISTVAL_ID IN (111, 3148))
                OR (:I$N = 25 AND V63.LISTVAL_ID = 97 AND V64.LISTVAL_ID = 98 AND V58.LISTVAL_ID IN (110, 121))
                OR (:I$N = 26 AND V63.LISTVAL_ID = 97 AND V64.LISTVAL_ID = 98 AND V58.LISTVAL_ID = 116)
                OR (:I$N = 27 AND V63.LISTVAL_ID = 97 AND V64.LISTVAL_ID = 98 AND V58.LISTVAL_ID = 114)
                OR (:I$N = 28 AND V63.LISTVAL_ID = 97 AND V64.LISTVAL_ID = 98 AND
                    V58.LISTVAL_ID NOT IN (119,130,145,1251,1291,108,112,1260,104,1268,1273,1278,105,102,115,118,101,100,99,109,117,1264,106,111,3148,110,121,116,114))
                OR (:I$N = 29 AND V63.LISTVAL_ID = 97 AND V58.LISTVAL_ID = 119)
                OR (:I$N = 30 AND V63.LISTVAL_ID = 97 AND V58.LISTVAL_ID = 130)
                OR (:I$N = 31 AND V63.LISTVAL_ID = 97 AND V58.LISTVAL_ID = 145)
                OR (:I$N = 32 AND V63.LISTVAL_ID = 97 AND V58.LISTVAL_ID = 1251)
                OR (:I$N = 33 AND V63.LISTVAL_ID = 97 AND V64.LISTVAL_ID = 125 AND V58.LISTVAL_ID NOT IN (119,130,145,1251,1291))
                OR (:I$N = 34 AND V63.LISTVAL_ID = 97 AND V58.LISTVAL_ID = 1291)
                OR (:I$N = 35 AND V63.LISTVAL_ID = 97 AND (SELECT SORT_ORDER FROM DO_FUNC(L13.OBJ_ID, 400)) = 2 AND
                    V64.LISTVAL_ID NOT IN (98, 125) AND V58.LISTVAL_ID NOT IN (119,130,145,1251,1291))
                OR (:I$N = 38 AND (V63.LISTVAL_ID = 1310 OR (V63.LISTVAL_ID = 97 AND (SELECT SORT_ORDER FROM DO_FUNC(L13.OBJ_ID, 400)) <> 2)))
                OR (:I$N = 40 AND V63.LISTVAL_ID = 1323)))
        INTO :V04;
        -- учителя-логопеды
        IF (:I$N = 8) THEN
        BEGIN
            SELECT IIF(V04 > 0, 0, V04) + :V04
            FROM RIK83(:I$OBJ_ID, 29, 1)
            INTO :V04;
        END
        IF (:I$N = 29 AND :V04 < 0 AND :I$SELF_FL = 0) THEN
        BEGIN
            V04 = 0;
        END
    END

    V04 = COALESCE(:V04, 0);

    SUSPEND;

END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE RIK83_ALL (
    I$OBJ_ID BIGINT NOT NULL,
    I$POD_NAME VARCHAR(1000) = NULL,
    I$OPF_NAME VARCHAR(1000) = NULL,
    REFRESH_FL SMALLINT = 1,
    R_1DO_6_FL SMALLINT = 0,
    I$G SMALLINT = NULL,
    I$N SMALLINT = NULL,
    I$DT DATE = CURRENT_DATE)
RETURNS (
    G SMALLINT,
    N SMALLINT,
    V03 INTEGER,
    V04 NUMERIC(11,2),
    V05 INTEGER,
    V06 INTEGER,
    V07 INTEGER,
    V08 INTEGER,
    V09 INTEGER,
    V10 INTEGER,
    V11 INTEGER,
    V12 INTEGER,
    V13 INTEGER,
    V14 INTEGER,
    V15 INTEGER,
    V16 INTEGER,
    V17 INTEGER,
    V18 INTEGER,
    V19 INTEGER,
    V20 INTEGER,
    V21 INTEGER,
    V22 INTEGER,
    V23 INTEGER,
    V24 INTEGER,
    V25 INTEGER,
    V26 INTEGER,
    V27 INTEGER,
    V28 INTEGER,
    V29 INTEGER,
    V30 INTEGER)
AS
DECLARE VARIABLE OBJ_TYPE_ID BIGINT;
DECLARE VARIABLE V$SCHOOL_ID BIGINT;
DECLARE VARIABLE V$OPF_ID BIGINT;
BEGIN
    SELECT TYPE_ID
    FROM OBJECTS
    WHERE OBJ_ID = :I$OBJ_ID
    INTO :OBJ_TYPE_ID;

    I$POD_NAME = IIF(I$POD_NAME = '', NULL, :I$POD_NAME);

    IF (:I$OPF_NAME IS NOT NULL) THEN
    BEGIN
        SELECT LISTVAL_ID
        FROM LISTVALS_LIST(258)
        WHERE VAL = :I$OPF_NAME
        INTO :V$OPF_ID;
    END

    IF (:REFRESH_FL = 1) THEN
    BEGIN
        DELETE FROM REPORT_RIK83 WHERE 1=1;
        EXECUTE PROCEDURE RIK83_INSERT(:I$OBJ_ID, :I$POD_NAME, :V$OPF_ID, :R_1DO_6_FL, COALESCE(:I$DT, CURRENT_DATE));
        /* STAVKI UCHITEL - OTDELNO */
        INSERT INTO REPORT_RIK83(G, N1, N, SCHOOL_ID, V04)
        SELECT
            G, N1,
            CASE
                WHEN G = 1 THEN NULL
                WHEN N1 < 3 THEN N1
                WHEN G > 4 AND N1 = 38 THEN 5
                WHEN (G BETWEEN 2 AND 4 AND N1 = 38) OR (G > 4 AND G <> 7 AND N1 = 40) THEN 6
                WHEN G = 7 AND N1 = 40 THEN 7
                WHEN G BETWEEN 2 AND 4 AND N1 = 40 THEN 8
            END N,
            SCHOOL_ID,
            X04 + IIF(N1 IN (1, 7, 8), (
                SELECT COALESCE(SUM(V.VAL), 0)
                FROM LINKS L2
                INNER JOIN VALF V ON V.OBJ_ID = L2.OBJ_ID
                WHERE L2.DATE_DEL IS NULL
                  AND L2.OBJ_TYPE_ID = 2
                  AND V.PARAM_ID = 1342
                  AND V.IS_DEL = 0
                  AND L2.OBJ_ID = SCHOOL_ID), 0)
        FROM (
            SELECT
                CASE
                    WHEN :OBJ_TYPE_ID = 2 THEN 1
                    WHEN V11.LISTVAL_ID = 954 THEN 2
                    WHEN V11.LISTVAL_ID = 958 THEN 3
                    WHEN V11.LISTVAL_ID = 969 THEN 4
                    WHEN V10.LISTVAL_ID IN (968, 973) THEN 5
                    WHEN V10.LISTVAL_ID = 974 THEN 6
                    WHEN V11.LISTVAL_ID = 978 THEN 7
                    WHEN V11.LISTVAL_ID = 2221 THEN 8
                    WHEN V11.LISTVAL_ID = 981 THEN 9
                    WHEN V11.LISTVAL_ID = 975 THEN 10
                    WHEN V11.LISTVAL_ID = 1003 THEN 11
                    ELSE 1
                END G,
                N1,
                L2.OBJ_ID SCHOOL_ID,
                SUM(IIF(LV.TAG = 'U', 0, COALESCE(V62.VAL, 0)) - IIF(N1 BETWEEN 9 AND 28, 0, (SELECT Z FROM RIK83_STAVOK(L13.OBJ_ID)))) X04
            FROM LINKS L2
            LEFT JOIN VALS V6 ON V6.OBJ_ID = L2.OBJ_ID
              AND V6.PARAM_ID = 6
              AND V6.IS_DEL = 0
            LEFT JOIN VALL V8 ON V8.OBJ_ID = L2.OBJ_ID
              AND V8.PARAM_ID = 8
              AND V8.IS_DEL = 0
            INNER JOIN LINKS L13 ON (L13.PARENT_ID = L2.OBJ_ID)
            INNER JOIN VALL V11 ON V11.OBJ_ID = L2.OBJ_ID
            INNER JOIN VALL V10 ON V10.OBJ_ID = L2.OBJ_ID
            INNER JOIN VALL V63 ON V63.OBJ_ID = L13.OBJ_ID
            INNER JOIN VALL V64 ON V64.OBJ_ID = L13.OBJ_ID
            INNER JOIN VALL V58 ON V58.OBJ_ID = L13.OBJ_ID
            LEFT JOIN VALF V62 ON V62.OBJ_ID = L13.OBJ_ID
              AND V62.PARAM_ID = 62
              AND V62.IS_DEL = 0
            INNER JOIN LISTVALS LV ON LV.LISTVAL_ID = V58.LISTVAL_ID,
           (SELECT     1 N1 FROM RDB$DATABASE UNION SELECT  2 FROM RDB$DATABASE UNION SELECT  3 FROM RDB$DATABASE
            UNION SELECT  4 FROM RDB$DATABASE UNION SELECT  5 FROM RDB$DATABASE UNION SELECT  6 FROM RDB$DATABASE
            UNION SELECT  7 FROM RDB$DATABASE UNION SELECT  8 FROM RDB$DATABASE UNION SELECT  9 FROM RDB$DATABASE
            UNION SELECT 10 FROM RDB$DATABASE UNION SELECT 11 FROM RDB$DATABASE UNION SELECT 12 FROM RDB$DATABASE
            UNION SELECT 13 FROM RDB$DATABASE UNION SELECT 14 FROM RDB$DATABASE UNION SELECT 15 FROM RDB$DATABASE
            UNION SELECT 16 FROM RDB$DATABASE UNION SELECT 17 FROM RDB$DATABASE UNION SELECT 18 FROM RDB$DATABASE
            UNION SELECT 19 FROM RDB$DATABASE UNION SELECT 20 FROM RDB$DATABASE UNION SELECT 21 FROM RDB$DATABASE
            UNION SELECT 22 FROM RDB$DATABASE UNION SELECT 23 FROM RDB$DATABASE UNION SELECT 24 FROM RDB$DATABASE
            UNION SELECT 25 FROM RDB$DATABASE UNION SELECT 26 FROM RDB$DATABASE UNION SELECT 27 FROM RDB$DATABASE
            UNION SELECT 28 FROM RDB$DATABASE UNION SELECT 29 FROM RDB$DATABASE UNION SELECT 30 FROM RDB$DATABASE
            UNION SELECT 31 FROM RDB$DATABASE UNION SELECT 32 FROM RDB$DATABASE UNION SELECT 33 FROM RDB$DATABASE
            UNION SELECT 34 FROM RDB$DATABASE UNION SELECT 35 FROM RDB$DATABASE UNION SELECT 36 FROM RDB$DATABASE
            UNION SELECT 38 FROM RDB$DATABASE UNION SELECT 40 FROM RDB$DATABASE)
            WHERE L2.DATE_DEL IS NULL
              AND L2.OBJ_TYPE_ID = 2
              AND ((:OBJ_TYPE_ID = 2 AND L13.PARENT_ID = :I$OBJ_ID) OR
                   (:OBJ_TYPE_ID = 111 AND L2.PARENT_ID = :I$OBJ_ID))
              AND (:I$POD_NAME IS NULL OR V6.VAL = :I$POD_NAME)
              AND (:V$OPF_ID IS NULL OR V8.LISTVAL_ID <> :V$OPF_ID)
              AND V11.PARAM_ID = 11
              AND V11.IS_DEL = 0
              AND V10.PARAM_ID = 10
              AND V10.IS_DEL = 0
              AND L13.OBJ_TYPE_ID = 13
              AND L13.DATE_DEL IS NULL
              AND V63.PARAM_ID = 63
              AND V63.IS_DEL = 0
              AND V64.PARAM_ID = 64
              AND V64.IS_DEL = 0
              AND V58.PARAM_ID = 58
              AND V58.IS_DEL = 0
              AND V58.LISTVAL_ID NOT IN (1267, 1284, 1298)
              AND ((N1 = 1)
                OR (N1 = 2 AND V63.LISTVAL_ID = 55)
                OR (N1 = 3 AND V63.LISTVAL_ID = 55 AND V64.LISTVAL_ID = 56 AND V58.LISTVAL_ID <> 69)
                OR (N1 = 4 AND V63.LISTVAL_ID = 55 AND V64.LISTVAL_ID = 113 AND V58.LISTVAL_ID <> 69)
                OR (N1 = 5 AND V63.LISTVAL_ID = 55 AND V58.LISTVAL_ID = 69)
                OR (N1 = 6 AND V63.LISTVAL_ID = 55 AND V64.LISTVAL_ID = 70 AND V58.LISTVAL_ID <> 69)
                OR (N1 = 7 AND V63.LISTVAL_ID = 97 AND (SELECT SORT_ORDER FROM DO_FUNC(L13.OBJ_ID, 400)) = 2)
                OR (N1 = 8 AND V63.LISTVAL_ID = 97 AND V64.LISTVAL_ID = 98 AND V58.LISTVAL_ID NOT IN (119,130,145,1251,1291))
                OR (N1 = 9 AND V63.LISTVAL_ID = 97 AND V64.LISTVAL_ID = 98 AND V58.LISTVAL_ID = 108)
                OR (N1 = 10 AND V63.LISTVAL_ID = 97 AND V64.LISTVAL_ID = 98 AND V58.LISTVAL_ID IN (112, 1260))
                OR (N1 = 11 AND V63.LISTVAL_ID = 97 AND V64.LISTVAL_ID = 70)
                OR (N1 = 12 AND V63.LISTVAL_ID = 97 AND V64.LISTVAL_ID = 98 AND V58.LISTVAL_ID IN (104, 1268, 1273, 1278))
                OR (N1 = 13 AND V63.LISTVAL_ID = 97 AND V64.LISTVAL_ID = 98 AND V58.LISTVAL_ID = 105)
                OR (N1 = 14 AND V63.LISTVAL_ID = 97 AND V64.LISTVAL_ID = 98 AND V58.LISTVAL_ID = 102)
                OR (N1 = 15 AND V63.LISTVAL_ID = 97 AND V64.LISTVAL_ID = 98 AND V58.LISTVAL_ID = 115)
                OR (N1 = 16 AND V63.LISTVAL_ID = 97 AND V64.LISTVAL_ID = 98 AND V58.LISTVAL_ID = 118)
                OR (N1 = 17 AND V63.LISTVAL_ID = 97 AND V64.LISTVAL_ID = 98 AND V58.LISTVAL_ID = 101)
                OR (N1 = 18 AND V63.LISTVAL_ID = 97 AND V64.LISTVAL_ID = 98 AND V58.LISTVAL_ID = 100)
                OR (N1 = 19 AND V63.LISTVAL_ID = 97 AND V64.LISTVAL_ID = 98 AND V58.LISTVAL_ID = 99)
                OR (N1 = 20 AND V63.LISTVAL_ID = 97 AND V64.LISTVAL_ID = 98 AND V58.LISTVAL_ID = 109)
                OR (N1 = 21 AND V63.LISTVAL_ID = 97 AND V64.LISTVAL_ID = 98 AND V58.LISTVAL_ID = 117)
                OR (N1 = 22 AND V63.LISTVAL_ID = 97 AND V64.LISTVAL_ID = 98 AND V58.LISTVAL_ID = 1264)
                OR (N1 = 23 AND V63.LISTVAL_ID = 97 AND V64.LISTVAL_ID = 98 AND V58.LISTVAL_ID = 106)
                OR (N1 = 24 AND V63.LISTVAL_ID = 97 AND V64.LISTVAL_ID = 98 AND V58.LISTVAL_ID IN (111, 3148))
                OR (N1 = 25 AND V63.LISTVAL_ID = 97 AND V64.LISTVAL_ID = 98 AND V58.LISTVAL_ID IN (110, 121))
                OR (N1 = 26 AND V63.LISTVAL_ID = 97 AND V64.LISTVAL_ID = 98 AND V58.LISTVAL_ID = 116)
                OR (N1 = 27 AND V63.LISTVAL_ID = 97 AND V64.LISTVAL_ID = 98 AND V58.LISTVAL_ID = 114)
                OR (N1 = 28 AND V63.LISTVAL_ID = 97 AND V64.LISTVAL_ID = 98 AND
                    V58.LISTVAL_ID NOT IN (119,130,145,1251,1291,108,112,1260,104,1268,1273,1278,105,102,115,118,101,100,99,109,117,1264,106,111,3148,110,121,116,114))
                OR (N1 = 29 AND V63.LISTVAL_ID = 97 AND V58.LISTVAL_ID = 119)
                OR (N1 = 30 AND :R_1DO_6_FL = 0 AND V63.LISTVAL_ID = 97 AND V58.LISTVAL_ID = 130)
                OR (N1 = 30 AND :R_1DO_6_FL = 1 AND V63.LISTVAL_ID = 97 AND V58.LISTVAL_ID = 143)
                OR (N1 = 31 AND :R_1DO_6_FL = 0 AND V63.LISTVAL_ID = 97 AND V58.LISTVAL_ID = 145)
                OR (N1 = 31 AND :R_1DO_6_FL = 1 AND V63.LISTVAL_ID = 97 AND V58.LISTVAL_ID = 144)
                OR (N1 = 32 AND V63.LISTVAL_ID = 97 AND V58.LISTVAL_ID = 1251)
                OR (N1 = 33 AND :R_1DO_6_FL = 0 AND V63.LISTVAL_ID = 97 AND V64.LISTVAL_ID = 125 AND V58.LISTVAL_ID NOT IN (119,130,145,1251,1291))
                OR (N1 = 33 AND :R_1DO_6_FL = 1 AND V63.LISTVAL_ID = 97 AND V64.LISTVAL_ID = 1256)
                OR (N1 = 34 AND :R_1DO_6_FL = 0 AND V63.LISTVAL_ID = 97 AND V58.LISTVAL_ID = 1291)
                OR (N1 = 34 AND :R_1DO_6_FL = 1 AND V63.LISTVAL_ID = 97 AND V58.LISTVAL_ID = 133)
                OR (N1 = 35 AND :R_1DO_6_FL = 0 AND V63.LISTVAL_ID = 97 AND (SELECT SORT_ORDER FROM DO_FUNC(L13.OBJ_ID, 400)) = 2 AND
                    V64.LISTVAL_ID NOT IN (98, 125) AND V58.LISTVAL_ID NOT IN (119,130,145,1251,1291))
                OR (N1 = 35 AND :R_1DO_6_FL = 1 AND V63.LISTVAL_ID = 97 AND (SELECT SORT_ORDER FROM DO_FUNC(L13.OBJ_ID, 400)) = 2 AND
                    V64.LISTVAL_ID NOT IN (98, 125) AND V58.LISTVAL_ID NOT IN (143,144,1251,1256,133))
                OR (N1 = 38 AND (V63.LISTVAL_ID = 1310 OR (V63.LISTVAL_ID = 97 AND (SELECT SORT_ORDER FROM DO_FUNC(L13.OBJ_ID, 400)) <> 2)))
                OR (N1 = 40 AND V63.LISTVAL_ID = 1323))
            GROUP BY G, N1, L2.OBJ_ID);
    END
    -- учителя-логопеды
    FOR SELECT
            SCHOOL_ID,
            V04
        FROM REPORT_RIK83
        WHERE V04 IS NOT NULL
          AND N1 = 29
        INTO :V$SCHOOL_ID, :V04
    DO
    BEGIN
        IF (:V04 < 0) THEN
        BEGIN
            UPDATE REPORT_RIK83
            SET V04 = IIF(N1 = 8, V04 + :V04, 0)
            WHERE V04 IS NOT NULL
              AND N1 IN (8, 29)
              AND SCHOOL_ID = :V$SCHOOL_ID;
        END
    END
    -- размажем вакансии учителей по всем их должностям
    FOR SELECT
            SCHOOL_ID,
            V04
        FROM REPORT_RIK83
        WHERE V04 IS NOT NULL
          AND N1 = 8
        INTO :V$SCHOOL_ID, :V04
    DO
    BEGIN
        SELECT COUNT(1), MAX(N1)
        FROM REPORT_RIK83
        WHERE V04 IS NOT NULL
          AND N1 BETWEEN 9 AND 28
          AND SCHOOL_ID = :V$SCHOOL_ID
        INTO :G, :N;

        UPDATE REPORT_RIK83
        SET V04 = :V04/:G + IIF(N1 = :N, :V04 - (:V04/:G)*:G, 0)
        WHERE V04 IS NOT NULL
          AND N1 BETWEEN 9 AND 28
          AND SCHOOL_ID = :V$SCHOOL_ID;
    END

    FOR
        SELECT
            1 G, N1,
            SUM(IIF(V13 = 0, V03, 0)) X03, SUM(V04)                  X04, SUM(IIF(V13 = 0, V05, 0)) X05, SUM(IIF(V13 = 0, V06, 0)) X06,
            SUM(IIF(V13 = 0, V07, 0)) X07, SUM(IIF(V13 = 0, V08, 0)) X08, SUM(IIF(V13 = 0, V09, 0)) X09, SUM(IIF(V13 = 0, V10, 0)) X10,
            SUM(IIF(V13 = 0, V11, 0)) X11, SUM(IIF(V13 = 0, V12, 0)) X12, SUM(V13) X13                 , SUM(V14) X14,
            SUM(IIF(V13 = 0, V15, 0)) X15, SUM(IIF(V13 = 0, V16, 0)) X16, SUM(IIF(V13 = 0, V17, 0)) X17, SUM(IIF(V13 = 0, V18, 0)) X18,
            SUM(IIF(V13 = 0, V19, 0)) X19, SUM(IIF(V13 = 0, V20, 0)) X20, SUM(IIF(V13 = 0, V21, 0)) X21, SUM(IIF(V13 = 0, V22, 0)) X22,
            SUM(IIF(V13 = 0, V23, 0)) X23, SUM(IIF(V13 = 0, V24, 0)) X24, SUM(IIF(V13 = 0, V25, 0)) X25, SUM(IIF(V13 = 0, V26, 0)) X26,
            SUM(IIF(V13 = 0, V27, 0)) X27, SUM(IIF(V13 = 0, V28, 0)) X28, SUM(IIF(V13 = 0, V29, 0)) X29, SUM(IIF(V13 = 0, V30, 0)) X30
        FROM REPORT_RIK83
        WHERE N1 IS NOT NULL
          AND (:I$G IS NULL OR :I$G = 1)
          AND (:I$N IS NULL OR :I$N = N1)
          AND N1 <= 40
        GROUP BY N1
        UNION ALL
        SELECT
            1 G, N1,
            SUM(V03) X03, NULL, NULL, NULL,
            NULL, NULL, NULL, NULL,
            NULL, NULL, NULL, NULL,
            NULL, NULL, NULL, NULL,
            NULL, NULL, NULL, NULL,
            NULL, NULL, NULL, NULL,
            NULL, NULL, NULL, NULL
        FROM REPORT_RIK83
        WHERE N1 IS NOT NULL
          AND (:I$G IS NULL OR :I$G = 1)
          AND (:I$N IS NULL OR :I$N = N1)
          AND N1 > 40
        GROUP BY N1
        UNION ALL
        SELECT
            G, N,
            SUM(IIF(V13 = 0, V03, 0)) X03, SUM(V04) X04                 , SUM(IIF(V13 = 0, V05, 0)) X05, SUM(IIF(V13 = 0, V06, 0)) X06,
            SUM(IIF(V13 = 0, V07, 0)) X07, SUM(IIF(V13 = 0, V08, 0)) X08, SUM(IIF(V13 = 0, V09, 0)) X09, SUM(IIF(V13 = 0, V10, 0)) X10,
            SUM(IIF(V13 = 0, V11, 0)) X11, SUM(IIF(V13 = 0, V12, 0)) X12, SUM(V13) X13                 , SUM(V14) X14,
            SUM(IIF(V13 = 0, V15, 0)) X15, SUM(IIF(V13 = 0, V16, 0)) X16, SUM(IIF(V13 = 0, V17, 0)) X17, SUM(IIF(V13 = 0, V18, 0)) X18,
            SUM(IIF(V13 = 0, V19, 0)) X19, SUM(IIF(V13 = 0, V20, 0)) X20, SUM(IIF(V13 = 0, V21, 0)) X21, SUM(IIF(V13 = 0, V22, 0)) X22,
            SUM(IIF(V13 = 0, V23, 0)) X23, SUM(IIF(V13 = 0, V24, 0)) X24, SUM(IIF(V13 = 0, V25, 0)) X25, SUM(IIF(V13 = 0, V26, 0)) X26,
            SUM(IIF(V13 = 0, V27, 0)) X27, SUM(IIF(V13 = 0, V28, 0)) X28, SUM(IIF(V13 = 0, V29, 0)) X29, SUM(IIF(V13 = 0, V30, 0)) X30
        FROM REPORT_RIK83
        WHERE N IS NOT NULL
          AND (:I$G IS NULL OR :I$G = G)
          AND (:I$N IS NULL OR :I$N = N)
        GROUP BY G, N
        INTO :G, :N,
             :V03, :V04, :V05, :V06, :V07, :V08, :V09,
             :V10, :V11, :V12, :V13, :V14, :V15, :V16,
             :V17, :V18, :V19, :V20, :V21, :V22, :V23,
             :V24, :V25, :V26, :V27, :V28, :V29, :V30
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE RIK83_DISTR1_1 (
    I$OBJ_ID BIGINT,
    I$N INTEGER)
RETURNS (
    V03 INTEGER,
    V04 NUMERIC(11,2),
    V05 INTEGER,
    V06 INTEGER,
    V07 INTEGER,
    V08 INTEGER,
    V09 INTEGER,
    V10 INTEGER,
    V11 INTEGER,
    V12 INTEGER,
    V13 INTEGER,
    V14 INTEGER,
    V15 INTEGER,
    V16 INTEGER,
    V17 INTEGER,
    V18 INTEGER,
    V19 INTEGER,
    V20 INTEGER,
    V21 INTEGER,
    V22 INTEGER,
    V23 INTEGER,
    V24 INTEGER,
    V25 INTEGER,
    V26 INTEGER,
    V27 INTEGER,
    V28 INTEGER,
    V29 INTEGER,
    V30 INTEGER)
AS
DECLARE VARIABLE V$POST_ID BIGINT;
DECLARE VARIABLE V$POST_GROUP BIGINT;
DECLARE VARIABLE V$POST_PODGROUP BIGINT;
DECLARE VARIABLE V$POST_FUNC BIGINT;
DECLARE VARIABLE V$STAVOK NUMERIC(11,2);
DECLARE VARIABLE V$Y NUMERIC(11,2);
DECLARE VARIABLE V$POST_NAME VARCHAR(4000);
DECLARE VARIABLE V$V VARCHAR(4000);
DECLARE VARIABLE V$WORKER_ID BIGINT;
DECLARE VARIABLE V$OU_TYPE BIGINT;
DECLARE VARIABLE V$CORRECT_CLASS INTEGER;
DECLARE VARIABLE V$TAG VARCHAR(100);
BEGIN
    V03 = 0;

    V05 = 0;
    V06 = 0;
    V07 = 0;
    V08 = 0;
    V09 = 0;
    V10 = 0;
    V11 = 0;
    V12 = 0;
    V13 = 0;
    V14 = 0;
    V15 = 0;
    V16 = 0;
    V17 = 0;
    V18 = 0;
    V19 = 0;
    V20 = 0;
    V21 = 0;
    V22 = 0;
    V23 = 0;
    V24 = 0;
    V25 = 0;
    V26 = 0;
    V27 = 0;
    V28 = 0;
    V29 = 0;
    V30 = 0;

    FOR SELECT L14.OBJ_ID, V69.VAL, V63.LISTVAL_ID, V64.LISTVAL_ID, V58.LISTVAL_ID, V66.VAL, V11.LISTVAL_ID
        FROM LINKS L2
        INNER JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID
        INNER JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID
        INNER JOIN VALL V11 ON V11.OBJ_ID = L14.PARENT_ID
        INNER JOIN VALL V72 ON V72.OBJ_ID = L15.OBJ_ID
        INNER JOIN VALR V69 ON V69.OBJ_ID = L15.OBJ_ID
        INNER JOIN VALL V63 ON V63.OBJ_ID = V69.VAL
        INNER JOIN VALL V64 ON V64.OBJ_ID = V69.VAL
        INNER JOIN VALL V58 ON V58.OBJ_ID = V69.VAL
        INNER JOIN VALS V66 ON V66.OBJ_ID = V69.VAL
        LEFT JOIN VALD V74 ON V74.PARAM_ID = 74 AND V74.OBJ_ID = L15.OBJ_ID AND V74.IS_DEL = 0
        LEFT JOIN VALL V274 ON V274.PARAM_ID = 274 AND V274.OBJ_ID = L14.OBJ_ID AND V274.IS_DEL = 0
        WHERE L2.DATE_DEL IS NULL
          AND L2.OBJ_TYPE_ID = 2
          AND L2.PARENT_ID = :I$OBJ_ID
          AND L14.OBJ_TYPE_ID = 14
          AND L14.DATE_DEL IS NULL
          AND L15.OBJ_TYPE_ID = 15
          AND L15.DATE_DEL IS NULL
          AND V72.PARAM_ID = 72
          AND V72.IS_DEL = 0
          AND V72.LISTVAL_ID = 934
          AND V69.PARAM_ID = 69
          AND V69.IS_DEL = 0
          AND V63.PARAM_ID = 63
          AND V63.IS_DEL = 0
          AND V64.PARAM_ID = 64
          AND V64.IS_DEL = 0
          AND V58.PARAM_ID = 58
          AND V58.IS_DEL = 0
          AND V66.PARAM_ID = 66
          AND V66.IS_DEL = 0
          AND V74.VAL IS NULL
          AND V11.PARAM_ID = 11
          AND V11.IS_DEL = 0
          AND ((V274.LISTVAL_ID IS NULL) OR (V274.LISTVAL_ID = 602) OR (V274.LISTVAL_ID = 604))
        INTO :V$WORKER_ID, :V$POST_ID, :V$POST_GROUP, :V$POST_PODGROUP, :V$POST_FUNC, :V$POST_NAME, :V$OU_TYPE
    DO
    BEGIN
        IF ((I$N >= 1) AND (I$N <= 40) AND (V$POST_FUNC <> 1267) AND (V$POST_FUNC <> 1284) AND (V$POST_FUNC <> 1298)) THEN
        BEGIN
            IF (I$N = 1) THEN
            BEGIN
                SELECT X03, X04, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27,
                     :V28, :V29, :V30;
                V$V = V$POST_NAME;
            END
            ELSE
            IF ((I$N >= 2) AND (I$N <= 6) AND (V$POST_GROUP = 55)) THEN
            BEGIN
                IF ((I$N = 2) AND (V$POST_GROUP = 55)) THEN
                BEGIN
                    SELECT X03, X04, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                    FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                    INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26,
                         :V27, :V28, :V29, :V30;
                    V$V = V$POST_NAME;
                END
                ELSE
                BEGIN
                    IF (V$POST_FUNC = 69) THEN
                    BEGIN
                        IF (I$N = 5) THEN
                        BEGIN
                            SELECT X03, X04, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29,
                                   X30
                            FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                            INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25,
                                 :V26, :V27, :V28, :V29, :V30;
                            V$V = V$POST_NAME;
                        END
                    END
                    ELSE
                    IF (V$POST_PODGROUP = 56) THEN
                    BEGIN
                        IF (I$N = 3) THEN
                        BEGIN
                            SELECT X03, X04, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29,
                                   X30
                            FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                            INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25,
                                 :V26, :V27, :V28, :V29, :V30;
                            V$V = V$POST_NAME;
                        END
                    END
                    ELSE
                    IF (V$POST_PODGROUP = 113) THEN
                    BEGIN
                        IF (I$N = 4) THEN
                        BEGIN
                            SELECT X03, X04, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29,
                                   X30
                            FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                            INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25,
                                 :V26, :V27, :V28, :V29, :V30;
                            V$V = V$POST_NAME;
                        END
                    END
                    ELSE
                    IF (V$POST_PODGROUP = 70) THEN
                    BEGIN
                        IF (I$N = 6) THEN
                        BEGIN
                            SELECT X03, X04, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29,
                                   X30
                            FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                            INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25,
                                 :V26, :V27, :V28, :V29, :V30;
                            V$V = V$POST_NAME;
                        END
                    END
                END
            END
            ELSE
            IF ((I$N >= 7) AND (I$N <= 35) AND (V$POST_GROUP = 97)) THEN
            BEGIN
                IF (I$N = 7) THEN
                BEGIN
                    SELECT X03, NULL, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                    FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                    INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26,
                         :V27, :V28, :V29, :V30;
                    V$V = V$POST_NAME;
                END
                ELSE
                BEGIN
                    IF (V$POST_FUNC = 119) THEN
                    BEGIN
                        IF (I$N = 29) THEN
                        BEGIN
                            SELECT X03, NULL, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29,
                                   X30
                            FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                            INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25,
                                 :V26, :V27, :V28, :V29, :V30;
                            V$V = V$POST_NAME;
                        END
                    END
                    ELSE
                    IF (V$POST_FUNC = 130) THEN
                    BEGIN
                        IF (I$N = 30) THEN
                        BEGIN
                            SELECT X03, NULL, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29,
                                   X30
                            FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                            INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25,
                                 :V26, :V27, :V28, :V29, :V30;
                            V$V = V$POST_NAME;
                        END
                    END
                    ELSE
                    IF (V$POST_FUNC = 145) THEN
                    BEGIN
                        IF (I$N = 31) THEN
                        BEGIN
                            SELECT X03, NULL, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29,
                                   X30
                            FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                            INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25,
                                 :V26, :V27, :V28, :V29, :V30;
                            V$V = V$POST_NAME;
                        END
                    END
                    ELSE
                    IF (V$POST_FUNC = 1251) THEN
                    BEGIN
                        IF (I$N = 32) THEN
                        BEGIN
                            SELECT X03, NULL, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29,
                                   X30
                            FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                            INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25,
                                 :V26, :V27, :V28, :V29, :V30;
                            V$V = V$POST_NAME;
                        END
                    END
                    ELSE
                    IF (V$POST_FUNC = 1291) THEN
                    BEGIN
                        IF (I$N = 34) THEN
                        BEGIN
                            SELECT X03, NULL, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29,
                                   X30
                            FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                            INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25,
                                 :V26, :V27, :V28, :V29, :V30;
                            V$V = V$POST_NAME;
                        END
                    END
                    ELSE
                    IF (V$POST_PODGROUP = 125) THEN
                    BEGIN
                        IF (I$N = 33) THEN
                        BEGIN
                            SELECT X03, NULL, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29,
                                   X30
                            FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                            INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25,
                                 :V26, :V27, :V28, :V29, :V30;
                            V$V = V$POST_NAME;
                        END
                    END
                    ELSE
                    IF (V$POST_PODGROUP = 98) THEN
                    BEGIN
                        IF ((I$N = 8) OR ((I$N = 36) AND (V$OU_TYPE = 978))) THEN
                        BEGIN
                            SELECT X03, NULL, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29,
                                   X30
                            FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                            INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25,
                                 :V26, :V27, :V28, :V29, :V30;
                            V$V = V$POST_NAME;
                        END
                        ELSE
                        BEGIN
                            IF (V$POST_FUNC = 108) THEN
                            BEGIN
                                IF (I$N = 9) THEN
                                BEGIN
                                    SELECT X03, NULL, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27,
                                           X28, X29, X30
                                    FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                                    INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23,
                                         :V24, :V25, :V26, :V27, :V28, :V29, :V30;
                                    V$V = V$POST_NAME;
                                END
                            END
                            ELSE
                            IF ((V$POST_FUNC = 112) OR (V$POST_FUNC = 1260)) THEN
                            BEGIN
                                IF (I$N = 10) THEN
                                BEGIN
                                    SELECT X03, NULL, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27,
                                           X28, X29, X30
                                    FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                                    INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23,
                                         :V24, :V25, :V26, :V27, :V28, :V29, :V30;
                                    V$V = V$POST_NAME;
                                END
                            END
                            ELSE
                            IF ((V$POST_FUNC = 104) OR (V$POST_FUNC = 1268) OR (V$POST_FUNC = 1273) OR (V$POST_FUNC = 1278)) THEN
                            BEGIN
                                IF (I$N = 12) THEN
                                BEGIN
                                    SELECT X03, NULL, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27,
                                           X28, X29, X30
                                    FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                                    INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23,
                                         :V24, :V25, :V26, :V27, :V28, :V29, :V30;
                                    V$V = V$POST_NAME;
                                END
                            END
                            ELSE
                            IF (V$POST_FUNC = 105) THEN
                            BEGIN
                                IF (I$N = 13) THEN
                                BEGIN
                                    SELECT X03, NULL, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27,
                                           X28, X29, X30
                                    FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                                    INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23,
                                         :V24, :V25, :V26, :V27, :V28, :V29, :V30;
                                    V$V = V$POST_NAME;
                                END
                            END
                            ELSE
                            IF (V$POST_FUNC = 102) THEN
                            BEGIN
                                IF (I$N = 14) THEN
                                BEGIN
                                    SELECT X03, NULL, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27,
                                           X28, X29, X30
                                    FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                                    INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23,
                                         :V24, :V25, :V26, :V27, :V28, :V29, :V30;
                                    V$V = V$POST_NAME;
                                END
                            END
                            ELSE
                            IF (V$POST_FUNC = 115) THEN
                            BEGIN
                                IF (I$N = 15) THEN
                                BEGIN
                                    SELECT X03, NULL, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27,
                                           X28, X29, X30
                                    FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                                    INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23,
                                         :V24, :V25, :V26, :V27, :V28, :V29, :V30;
                                    V$V = V$POST_NAME;
                                END
                            END
                            ELSE
                            IF (V$POST_FUNC = 118) THEN
                            BEGIN
                                IF (I$N = 16) THEN
                                BEGIN
                                    SELECT X03, NULL, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27,
                                           X28, X29, X30
                                    FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                                    INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23,
                                         :V24, :V25, :V26, :V27, :V28, :V29, :V30;
                                    V$V = V$POST_NAME;
                                END
                            END
                            ELSE
                            IF (V$POST_FUNC = 101) THEN
                            BEGIN
                                IF (I$N = 17) THEN
                                BEGIN
                                    SELECT X03, NULL, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27,
                                           X28, X29, X30
                                    FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                                    INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23,
                                         :V24, :V25, :V26, :V27, :V28, :V29, :V30;
                                    V$V = V$POST_NAME;
                                END
                            END
                            ELSE
                            IF (V$POST_FUNC = 100) THEN
                            BEGIN
                                IF (I$N = 18) THEN
                                BEGIN
                                    SELECT X03, NULL, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27,
                                           X28, X29, X30
                                    FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                                    INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23,
                                         :V24, :V25, :V26, :V27, :V28, :V29, :V30;
                                    V$V = V$POST_NAME;
                                END
                            END
                            ELSE
                            IF (V$POST_FUNC = 99) THEN
                            BEGIN
                                IF (I$N = 19) THEN
                                BEGIN
                                    SELECT X03, NULL, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27,
                                           X28, X29, X30
                                    FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                                    INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23,
                                         :V24, :V25, :V26, :V27, :V28, :V29, :V30;
                                    V$V = V$POST_NAME;
                                END
                            END
                            ELSE
                            IF (V$POST_FUNC = 109) THEN
                            BEGIN
                                IF (I$N = 20) THEN
                                BEGIN
                                    SELECT X03, NULL, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27,
                                           X28, X29, X30
                                    FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                                    INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23,
                                         :V24, :V25, :V26, :V27, :V28, :V29, :V30;
                                    V$V = V$POST_NAME;
                                END
                            END
                            ELSE
                            IF (V$POST_FUNC = 117) THEN
                            BEGIN
                                IF (I$N = 21) THEN
                                BEGIN
                                    SELECT X03, NULL, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27,
                                           X28, X29, X30
                                    FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                                    INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23,
                                         :V24, :V25, :V26, :V27, :V28, :V29, :V30;
                                    V$V = V$POST_NAME;
                                END
                            END
                            ELSE
                            IF (V$POST_FUNC = 1264) THEN
                            BEGIN
                                IF (I$N = 22) THEN
                                BEGIN
                                    SELECT X03, NULL, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27,
                                           X28, X29, X30
                                    FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                                    INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23,
                                         :V24, :V25, :V26, :V27, :V28, :V29, :V30;
                                    V$V = V$POST_NAME;
                                END
                            END
                            ELSE
                            IF (V$POST_FUNC = 106) THEN
                            BEGIN
                                IF (I$N = 23) THEN
                                BEGIN
                                    SELECT X03, NULL, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27,
                                           X28, X29, X30
                                    FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                                    INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23,
                                         :V24, :V25, :V26, :V27, :V28, :V29, :V30;
                                    V$V = V$POST_NAME;
                                END
                            END
                            ELSE
                            IF (V$POST_FUNC = 111) THEN
                            BEGIN
                                IF (I$N = 24) THEN
                                BEGIN
                                    SELECT X03, NULL, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27,
                                           X28, X29, X30
                                    FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                                    INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23,
                                         :V24, :V25, :V26, :V27, :V28, :V29, :V30;
                                    V$V = V$POST_NAME;
                                END
                            END
                            ELSE
                            IF (V$POST_FUNC = 110) THEN
                            BEGIN
                                IF (I$N = 25) THEN
                                BEGIN
                                    SELECT X03, NULL, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27,
                                           X28, X29, X30
                                    FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                                    INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23,
                                         :V24, :V25, :V26, :V27, :V28, :V29, :V30;
                                    V$V = V$POST_NAME;
                                END
                            END
                            ELSE
                            IF (V$POST_FUNC = 116) THEN
                            BEGIN
                                IF (I$N = 26) THEN
                                BEGIN
                                    SELECT X03, NULL, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27,
                                           X28, X29, X30
                                    FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                                    INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23,
                                         :V24, :V25, :V26, :V27, :V28, :V29, :V30;
                                    V$V = V$POST_NAME;
                                END
                            END
                            ELSE
                            IF (V$POST_FUNC = 114) THEN
                            BEGIN
                                IF (I$N = 27) THEN
                                BEGIN
                                    SELECT X03, NULL, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27,
                                           X28, X29, X30
                                    FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                                    INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23,
                                         :V24, :V25, :V26, :V27, :V28, :V29, :V30;
                                    V$V = V$POST_NAME;
                                END
                            END
                            ELSE
                            IF (I$N = 28) THEN
                            BEGIN
                                SELECT X03, NULL, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28,
                                       X29, X30
                                FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                                INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24,
                                     :V25, :V26, :V27, :V28, :V29, :V30;
                                V$V = V$POST_NAME;
                            END
                        END
                    END
                    ELSE
                    IF (I$N = 35) THEN
                    BEGIN
                        SELECT X03, NULL, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29,
                               X30
                        FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                        INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25,
                             :V26, :V27, :V28, :V29, :V30;
                        V$V = V$POST_NAME;
                    END
                END
            END
            ELSE
            IF ((I$N = 36) AND (V$OU_TYPE <> 978) AND (V$POST_GROUP = 97)) THEN
            BEGIN
                V$CORRECT_CLASS = 0;

                SELECT FIRST 1 1
                FROM LINKS L58
                INNER JOIN LINKS L9 ON L9.OBJ_ID = L58.OBJ_ID
                INNER JOIN VALL V592 ON V592.OBJ_ID = L9.PARENT_ID
                WHERE L58.PARENT_ID = :V$WORKER_ID
                  AND L58.OBJ_TYPE_ID = 58
                  AND L58.DATE_DEL IS NULL
                  AND L9.PARENT_TYPE_ID = 9
                  AND L9.DATE_DEL IS NULL
                  AND V592.PARAM_ID = 592
                  AND V592.IS_DEL = 0
                  AND V592.LISTVAL_ID > 197
                INTO :V$CORRECT_CLASS;

                IF (V$CORRECT_CLASS = 1) THEN
                BEGIN
                    SELECT X03, NULL, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                    FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                    INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26,
                         :V27, :V28, :V29, :V30;
                    V$V = V$POST_NAME;
                END
            END
            ELSE
            IF ((I$N >= 38) AND (I$N <= 39) AND (V$POST_GROUP = 1310)) THEN
            BEGIN
                IF (I$N = 38) THEN
                BEGIN
                    SELECT X03, X04, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                    FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                    INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26,
                         :V27, :V28, :V29, :V30;
                    V$V = V$POST_NAME;
                END
            END
            ELSE
            IF ((I$N = 40) AND (V$POST_GROUP = 1323)) THEN
            BEGIN
                SELECT X03, X04, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27,
                     :V28, :V29, :V30;
                V$V = V$POST_NAME;
            END
        END
        ELSE
        IF ((I$N = 41) AND ((V$POST_FUNC = 1267) OR (V$POST_FUNC = 1284) OR (V$POST_FUNC = 1298))) THEN
        BEGIN
            SELECT X03
            FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03)
            INTO :V03;
            V$V = V$POST_NAME;
        END
        ELSE
        IF ((I$N = 42) AND ((V$POST_FUNC = 1267) OR (V$POST_FUNC = 1284) OR (V$POST_FUNC = 1298))) THEN
        BEGIN
            SELECT X05
            FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05)
            INTO :V05;
            V$V = V$POST_NAME;
        END
        ELSE
        IF ((I$N = 43) AND (V$POST_FUNC = 1267)) THEN
        BEGIN
            SELECT X03
            FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03)
            INTO :V03;
            V$V = V$POST_NAME;
        END
        ELSE
        IF ((I$N = 44) AND ((V$POST_FUNC = 1284) OR (V$POST_FUNC = 1298))) THEN
        BEGIN
            SELECT X03
            FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03)
            INTO :V03;
            V$V = V$POST_NAME;
        END

    END

    /* FREE POSTS */

    IF (I$N IN (1, 2, 3, 4, 5, 6, 38, 40)) THEN
    BEGIN
        V04 = 0;

        /* STAVKI UCHITEL - OTDELNO */
        IF (I$N = 1) THEN
        BEGIN
            SELECT SUM(V.VAL)
            FROM LINKS L2
            INNER JOIN VALF V ON (V.OBJ_ID = L2.OBJ_ID)
            WHERE L2.DATE_DEL IS NULL
              AND L2.OBJ_TYPE_ID = 2
              AND V.PARAM_ID = 1342
              AND V.IS_DEL = 0
              AND L2.PARENT_ID = :I$OBJ_ID
            INTO :V04;
        END

        FOR SELECT L13.OBJ_ID, V63.LISTVAL_ID, V64.LISTVAL_ID, V58.LISTVAL_ID, V62.VAL, LV.TAG
            FROM LINKS L2
            INNER JOIN LINKS L13 ON (L13.PARENT_ID = L2.OBJ_ID)
            INNER JOIN VALL V63 ON V63.OBJ_ID = L13.OBJ_ID
            INNER JOIN VALL V64 ON V64.OBJ_ID = L13.OBJ_ID
            INNER JOIN VALL V58 ON V58.OBJ_ID = L13.OBJ_ID
            INNER JOIN VALF V62 ON V62.OBJ_ID = L13.OBJ_ID
            INNER JOIN LISTVALS LV ON LV.LISTVAL_ID = V58.LISTVAL_ID
            WHERE L2.DATE_DEL IS NULL
              AND L2.OBJ_TYPE_ID = 2
              AND L2.PARENT_ID = :I$OBJ_ID
              AND L13.OBJ_TYPE_ID = 13
              AND L13.DATE_DEL IS NULL
              AND V63.PARAM_ID = 63
              AND V63.IS_DEL = 0
              AND V64.PARAM_ID = 64
              AND V64.IS_DEL = 0
              AND V58.PARAM_ID = 58
              AND V58.IS_DEL = 0
              AND V62.PARAM_ID = 62
              AND V62.IS_DEL = 0
              AND V58.LISTVAL_ID <> 1267
              AND V58.LISTVAL_ID <> 1284
              AND V58.LISTVAL_ID <> 1298
            INTO :V$POST_ID, :V$POST_GROUP, :V$POST_PODGROUP, :V$POST_FUNC, :V$STAVOK, :V$TAG
        DO
        BEGIN
            V$Y = 0;
            /* STAVKI UCHITEL - OTDELNO */
            IF (V$TAG = 'U') THEN
            BEGIN
                V$STAVOK = 0;
            END

            IF (I$N = 1) THEN
            BEGIN
                SELECT Z
                FROM RIK83_STAVOK(:V$POST_ID)
                INTO :V$Y;
                V04 = V04 + V$STAVOK - V$Y;
            END
            ELSE
            IF ((I$N >= 2) AND (I$N <= 6) AND (V$POST_GROUP = 55)) THEN
            BEGIN
                IF ((I$N = 2) AND (V$POST_GROUP = 55)) THEN
                BEGIN
                    SELECT Z
                    FROM RIK83_STAVOK(:V$POST_ID)
                    INTO :V$Y;
                    V04 = V04 + V$STAVOK - V$Y;
                END
                ELSE
                BEGIN
                    IF (V$POST_FUNC = 69) THEN
                    BEGIN
                        IF (I$N = 5) THEN
                        BEGIN
                            SELECT Z
                            FROM RIK83_STAVOK(:V$POST_ID)
                            INTO :V$Y;
                            V04 = V04 + V$STAVOK - V$Y;
                        END
                    END
                    ELSE
                    IF (V$POST_PODGROUP = 56) THEN
                    BEGIN
                        IF (I$N = 3) THEN
                        BEGIN
                            SELECT Z
                            FROM RIK83_STAVOK(:V$POST_ID)
                            INTO :V$Y;
                            V04 = V04 + V$STAVOK - V$Y;
                        END
                    END
                    ELSE
                    IF (V$POST_PODGROUP = 113) THEN
                    BEGIN
                        IF (I$N = 4) THEN
                        BEGIN
                            SELECT Z
                            FROM RIK83_STAVOK(:V$POST_ID)
                            INTO :V$Y;
                            V04 = V04 + V$STAVOK - V$Y;
                        END
                    END
                    ELSE
                    IF (V$POST_PODGROUP = 70) THEN
                    BEGIN
                        IF (I$N = 6) THEN
                        BEGIN
                            SELECT Z
                            FROM RIK83_STAVOK(:V$POST_ID)
                            INTO :V$Y;
                            V04 = V04 + V$STAVOK - V$Y;
                        END
                    END
                END
            END
            ELSE
            IF ((I$N = 38) AND (V$POST_GROUP = 1310)) THEN
            BEGIN
                SELECT Z
                FROM RIK83_STAVOK(:V$POST_ID)
                INTO :V$Y;
                V04 = V04 + V$STAVOK - V$Y;
            END
            ELSE
            IF ((I$N = 40) AND (V$POST_GROUP = 1323)) THEN
            BEGIN
                SELECT Z
                FROM RIK83_STAVOK(:V$POST_ID)
                INTO :V$Y;
                V04 = V04 + V$STAVOK - V$Y;
            END
        END
    END
    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE RIK83_DISTR1_10 (
    I$OBJ_ID BIGINT,
    I$N INTEGER)
RETURNS (
    V03 INTEGER,
    V04 NUMERIC(11,2),
    V05 INTEGER,
    V06 INTEGER,
    V07 INTEGER,
    V08 INTEGER,
    V09 INTEGER,
    V10 INTEGER,
    V11 INTEGER,
    V12 INTEGER,
    V13 INTEGER,
    V14 INTEGER,
    V15 INTEGER,
    V16 INTEGER,
    V17 INTEGER,
    V18 INTEGER,
    V19 INTEGER,
    V20 INTEGER,
    V21 INTEGER,
    V22 INTEGER,
    V23 INTEGER,
    V24 INTEGER,
    V25 INTEGER,
    V26 INTEGER,
    V27 INTEGER,
    V28 INTEGER,
    V29 INTEGER,
    V30 INTEGER)
AS
DECLARE VARIABLE V$POST_ID BIGINT;
DECLARE VARIABLE V$POST_GROUP BIGINT;
DECLARE VARIABLE V$POST_PODGROUP BIGINT;
DECLARE VARIABLE V$POST_FUNC BIGINT;
DECLARE VARIABLE V$STAVOK NUMERIC(11,2);
DECLARE VARIABLE V$Y NUMERIC(11,2);
DECLARE VARIABLE V$POST_NAME VARCHAR(4000);
DECLARE VARIABLE V$V VARCHAR(4000);
DECLARE VARIABLE V$WORKER_ID BIGINT;
DECLARE VARIABLE V$OU_TYPE BIGINT;--declare variable V$CORRECT_CLASS integer;
DECLARE VARIABLE V$TAG VARCHAR(100);
BEGIN
    V03 = 0;

    V05 = 0;
    V06 = 0;
    V07 = 0;
    V08 = 0;
    V09 = 0;
    V10 = 0;
    V11 = 0;
    V12 = 0;
    V13 = 0;
    V14 = 0;
    V15 = 0;
    V16 = 0;
    V17 = 0;
    V18 = 0;
    V19 = 0;
    V20 = 0;
    V21 = 0;
    V22 = 0;
    V23 = 0;
    V24 = 0;
    V25 = 0;
    V26 = 0;
    V27 = 0;
    V28 = 0;
    V29 = 0;
    V30 = 0;

    FOR SELECT L14.OBJ_ID, V69.VAL, V63.LISTVAL_ID, V64.LISTVAL_ID, V58.LISTVAL_ID, V66.VAL, V11.LISTVAL_ID
        FROM LINKS L2
        INNER JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID
        INNER JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID
        INNER JOIN VALL V11 ON V11.OBJ_ID = L14.PARENT_ID
        INNER JOIN VALL V72 ON V72.OBJ_ID = L15.OBJ_ID
        INNER JOIN VALR V69 ON V69.OBJ_ID = L15.OBJ_ID
        INNER JOIN VALL V63 ON V63.OBJ_ID = V69.VAL
        INNER JOIN VALL V64 ON V64.OBJ_ID = V69.VAL
        INNER JOIN VALL V58 ON V58.OBJ_ID = V69.VAL
        INNER JOIN VALS V66 ON V66.OBJ_ID = V69.VAL
        LEFT JOIN VALD V74 ON V74.PARAM_ID = 74 AND V74.OBJ_ID = L15.OBJ_ID AND V74.IS_DEL = 0
        LEFT JOIN VALL V274 ON V274.PARAM_ID = 274 AND V274.OBJ_ID = L14.OBJ_ID AND V274.IS_DEL = 0
        WHERE L2.DATE_DEL IS NULL
          AND L2.OBJ_TYPE_ID = 2
          AND L2.PARENT_ID = :I$OBJ_ID
          AND L14.OBJ_TYPE_ID = 14
          AND L14.DATE_DEL IS NULL
          AND L15.OBJ_TYPE_ID = 15
          AND L15.DATE_DEL IS NULL
          AND V72.PARAM_ID = 72
          AND V72.IS_DEL = 0
          AND V72.LISTVAL_ID = 934
          AND V69.PARAM_ID = 69
          AND V69.IS_DEL = 0
          AND V63.PARAM_ID = 63
          AND V63.IS_DEL = 0
          AND V64.PARAM_ID = 64
          AND V64.IS_DEL = 0
          AND V58.PARAM_ID = 58
          AND V58.IS_DEL = 0
          AND V66.PARAM_ID = 66
          AND V66.IS_DEL = 0
          AND V74.VAL IS NULL
          AND V11.PARAM_ID = 11
          AND V11.IS_DEL = 0
          AND V11.LISTVAL_ID = 975
          AND ((V274.LISTVAL_ID IS NULL) OR (V274.LISTVAL_ID = 602) OR (V274.LISTVAL_ID = 604))
        INTO :V$WORKER_ID, :V$POST_ID, :V$POST_GROUP, :V$POST_PODGROUP, :V$POST_FUNC, :V$POST_NAME, :V$OU_TYPE
    DO
    BEGIN
        IF ((I$N >= 1) AND (I$N <= 6) AND (V$POST_FUNC <> 1267) AND (V$POST_FUNC <> 1284) AND (V$POST_FUNC <> 1298)) THEN
        BEGIN
            IF (I$N = 1) THEN
            BEGIN
                SELECT X03, X04, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27,
                     :V28, :V29, :V30;
                V$V = V$POST_NAME;
            END
            ELSE
            IF ((I$N = 2) AND (V$POST_GROUP = 55)) THEN
            BEGIN
                SELECT X03, X04, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27,
                     :V28, :V29, :V30;
                V$V = V$POST_NAME;
            END
            ELSE
            IF (((I$N >= 3) OR (I$N <= 4)) AND (V$POST_GROUP = 97)) THEN
            BEGIN
                IF (I$N = 3) THEN
                BEGIN
                    SELECT X03, X04, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                    FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                    INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26,
                         :V27, :V28, :V29, :V30;
                    V$V = V$POST_NAME;
                END
                ELSE
                IF (V$POST_PODGROUP = 98) THEN
                BEGIN
                    IF ((I$N = 4) AND (V$OU_TYPE = 978)) THEN
                    BEGIN
                        SELECT X03, NULL, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29,
                               X30
                        FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                        INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25,
                             :V26, :V27, :V28, :V29, :V30;
                        V$V = V$POST_NAME;
                    END
                END
            END

            ELSE
            IF ((I$N >= 5) AND (V$POST_GROUP = 1310)) THEN
            BEGIN
                SELECT X03, X04, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27,
                     :V28, :V29, :V30;
                V$V = V$POST_NAME;
            END
            ELSE
            IF ((I$N = 6) AND (V$POST_GROUP = 1323)) THEN
            BEGIN
                SELECT X03, X04, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27,
                     :V28, :V29, :V30;
                V$V = V$POST_NAME;
            END
        END
        ELSE
        IF ((I$N = 8) AND ((V$POST_FUNC = 1267) OR (V$POST_FUNC = 1284) OR (V$POST_FUNC = 1298))) THEN
        BEGIN
            SELECT X03
            FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03)
            INTO :V03;
            V$V = V$POST_NAME;
        END
        ELSE
        IF ((I$N = 9) AND (V$POST_FUNC = 1267)) THEN
        BEGIN
            SELECT X03
            FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03)
            INTO :V03;
            V$V = V$POST_NAME;
        END
        ELSE
        IF ((I$N = 10) AND ((V$POST_FUNC = 1284) OR (V$POST_FUNC = 1298))) THEN
        BEGIN
            SELECT X03
            FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03)
            INTO :V03;
            V$V = V$POST_NAME;
        END

    END

    /* FREE POSTS */

    IF (I$N IN (1, 2, 5, 6)) THEN
    BEGIN
        V04 = 0;

        /* STAVKI UCHITEL - OTDELNO */
        IF (I$N = 1) THEN
        BEGIN
            SELECT SUM(V.VAL)
            FROM LINKS L2
            INNER JOIN VALF V ON (V.OBJ_ID = L2.OBJ_ID)
            INNER JOIN VALL V11 ON (V11.OBJ_ID = L2.OBJ_ID)
            WHERE L2.DATE_DEL IS NULL
              AND L2.OBJ_TYPE_ID = 2
              AND V11.PARAM_ID = 11
              AND V11.IS_DEL = 0
              AND V11.LISTVAL_ID = 975
              AND V.PARAM_ID = 1342
              AND V.IS_DEL = 0
              AND L2.PARENT_ID = :I$OBJ_ID
            INTO :V04;
        END

        FOR SELECT L13.OBJ_ID, V63.LISTVAL_ID, V64.LISTVAL_ID, V58.LISTVAL_ID, V62.VAL, LV.TAG
            FROM LINKS L2
            INNER JOIN LINKS L13 ON (L13.PARENT_ID = L2.OBJ_ID)
            INNER JOIN VALL V11 ON V11.OBJ_ID = L2.OBJ_ID
            INNER JOIN VALL V63 ON V63.OBJ_ID = L13.OBJ_ID
            INNER JOIN VALL V64 ON V64.OBJ_ID = L13.OBJ_ID
            INNER JOIN VALL V58 ON V58.OBJ_ID = L13.OBJ_ID
            INNER JOIN VALF V62 ON V62.OBJ_ID = L13.OBJ_ID
            INNER JOIN LISTVALS LV ON LV.LISTVAL_ID = V58.LISTVAL_ID
            WHERE L2.DATE_DEL IS NULL
              AND L2.OBJ_TYPE_ID = 2
              AND L2.PARENT_ID = :I$OBJ_ID
              AND V11.PARAM_ID = 11
              AND V11.IS_DEL = 0
              AND V11.LISTVAL_ID = 975
              AND L13.OBJ_TYPE_ID = 13
              AND L13.DATE_DEL IS NULL
              AND V63.PARAM_ID = 63
              AND V63.IS_DEL = 0
              AND V64.PARAM_ID = 64
              AND V64.IS_DEL = 0
              AND V58.PARAM_ID = 58
              AND V58.IS_DEL = 0
              AND V62.PARAM_ID = 62
              AND V62.IS_DEL = 0
              AND V58.LISTVAL_ID <> 1267
              AND V58.LISTVAL_ID <> 1284
              AND V58.LISTVAL_ID <> 1298
            INTO :V$POST_ID, :V$POST_GROUP, :V$POST_PODGROUP, :V$POST_FUNC, :V$STAVOK, :V$TAG
        DO
        BEGIN
            V$Y = 0;
            /* STAVKI UCHITEL - OTDELNO */
            IF (V$TAG = 'U') THEN
            BEGIN
                V$STAVOK = 0;
            END

            IF (I$N = 1) THEN
            BEGIN
                SELECT Z
                FROM RIK83_STAVOK(:V$POST_ID)
                INTO :V$Y;
                V04 = V04 + V$STAVOK - V$Y;
            END
            ELSE
            IF ((I$N = 2) AND (V$POST_GROUP = 55)) THEN
            BEGIN
                SELECT Z
                FROM RIK83_STAVOK(:V$POST_ID)
                INTO :V$Y;
                V04 = V04 + V$STAVOK - V$Y;
            END

            ELSE
            IF ((I$N = 5) AND (V$POST_GROUP = 1310)) THEN
            BEGIN
                SELECT Z
                FROM RIK83_STAVOK(:V$POST_ID)
                INTO :V$Y;
                V04 = V04 + V$STAVOK - V$Y;
            END
            ELSE
            IF ((I$N = 6) AND (V$POST_GROUP = 1323)) THEN
            BEGIN
                SELECT Z
                FROM RIK83_STAVOK(:V$POST_ID)
                INTO :V$Y;
                V04 = V04 + V$STAVOK - V$Y;
            END

        END

    END
    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE RIK83_DISTR1_11 (
    I$OBJ_ID BIGINT,
    I$N INTEGER)
RETURNS (
    V03 INTEGER,
    V04 NUMERIC(11,2),
    V05 INTEGER,
    V06 INTEGER,
    V07 INTEGER,
    V08 INTEGER,
    V09 INTEGER,
    V10 INTEGER,
    V11 INTEGER,
    V12 INTEGER,
    V13 INTEGER,
    V14 INTEGER,
    V15 INTEGER,
    V16 INTEGER,
    V17 INTEGER,
    V18 INTEGER,
    V19 INTEGER,
    V20 INTEGER,
    V21 INTEGER,
    V22 INTEGER,
    V23 INTEGER,
    V24 INTEGER,
    V25 INTEGER,
    V26 INTEGER,
    V27 INTEGER,
    V28 INTEGER,
    V29 INTEGER,
    V30 INTEGER)
AS
DECLARE VARIABLE V$POST_ID BIGINT;
DECLARE VARIABLE V$POST_GROUP BIGINT;
DECLARE VARIABLE V$POST_PODGROUP BIGINT;
DECLARE VARIABLE V$POST_FUNC BIGINT;
DECLARE VARIABLE V$STAVOK NUMERIC(11,2);
DECLARE VARIABLE V$Y NUMERIC(11,2);
DECLARE VARIABLE V$POST_NAME VARCHAR(4000);
DECLARE VARIABLE V$V VARCHAR(4000);
DECLARE VARIABLE V$WORKER_ID BIGINT;
DECLARE VARIABLE V$OU_TYPE BIGINT;--declare variable V$CORRECT_CLASS integer;
DECLARE VARIABLE V$TAG VARCHAR(100);
BEGIN
    V03 = 0;

    V05 = 0;
    V06 = 0;
    V07 = 0;
    V08 = 0;
    V09 = 0;
    V10 = 0;
    V11 = 0;
    V12 = 0;
    V13 = 0;
    V14 = 0;
    V15 = 0;
    V16 = 0;
    V17 = 0;
    V18 = 0;
    V19 = 0;
    V20 = 0;
    V21 = 0;
    V22 = 0;
    V23 = 0;
    V24 = 0;
    V25 = 0;
    V26 = 0;
    V27 = 0;
    V28 = 0;
    V29 = 0;
    V30 = 0;

    FOR SELECT L14.OBJ_ID, V69.VAL, V63.LISTVAL_ID, V64.LISTVAL_ID, V58.LISTVAL_ID, V66.VAL, V11.LISTVAL_ID
        FROM LINKS L2
        INNER JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID
        INNER JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID
        INNER JOIN VALL V11 ON V11.OBJ_ID = L14.PARENT_ID
        INNER JOIN VALL V72 ON V72.OBJ_ID = L15.OBJ_ID
        INNER JOIN VALR V69 ON V69.OBJ_ID = L15.OBJ_ID
        INNER JOIN VALL V63 ON V63.OBJ_ID = V69.VAL
        INNER JOIN VALL V64 ON V64.OBJ_ID = V69.VAL
        INNER JOIN VALL V58 ON V58.OBJ_ID = V69.VAL
        INNER JOIN VALS V66 ON V66.OBJ_ID = V69.VAL
        LEFT JOIN VALD V74 ON V74.PARAM_ID = 74 AND V74.OBJ_ID = L15.OBJ_ID AND V74.IS_DEL = 0
        LEFT JOIN VALL V274 ON V274.PARAM_ID = 274 AND V274.OBJ_ID = L14.OBJ_ID AND V274.IS_DEL = 0
        WHERE L2.DATE_DEL IS NULL
          AND L2.OBJ_TYPE_ID = 2
          AND L2.PARENT_ID = :I$OBJ_ID
          AND L14.OBJ_TYPE_ID = 14
          AND L14.DATE_DEL IS NULL
          AND L15.OBJ_TYPE_ID = 15
          AND L15.DATE_DEL IS NULL
          AND V72.PARAM_ID = 72
          AND V72.IS_DEL = 0
          AND V72.LISTVAL_ID = 934
          AND V69.PARAM_ID = 69
          AND V69.IS_DEL = 0
          AND V63.PARAM_ID = 63
          AND V63.IS_DEL = 0
          AND V64.PARAM_ID = 64
          AND V64.IS_DEL = 0
          AND V58.PARAM_ID = 58
          AND V58.IS_DEL = 0
          AND V66.PARAM_ID = 66
          AND V66.IS_DEL = 0
          AND V74.VAL IS NULL
          AND V11.PARAM_ID = 11
          AND V11.IS_DEL = 0
          AND V11.LISTVAL_ID = 1003
          AND ((V274.LISTVAL_ID IS NULL) OR (V274.LISTVAL_ID = 602) OR (V274.LISTVAL_ID = 604))
        INTO :V$WORKER_ID, :V$POST_ID, :V$POST_GROUP, :V$POST_PODGROUP, :V$POST_FUNC, :V$POST_NAME, :V$OU_TYPE
    DO
    BEGIN
        IF ((I$N >= 1) AND (I$N <= 6) AND (V$POST_FUNC <> 1267) AND (V$POST_FUNC <> 1284) AND (V$POST_FUNC <> 1298)) THEN
        BEGIN
            IF (I$N = 1) THEN
            BEGIN
                SELECT X03, X04, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27,
                     :V28, :V29, :V30;
                V$V = V$POST_NAME;
            END
            ELSE
            IF ((I$N = 2) AND (V$POST_GROUP = 55)) THEN
            BEGIN
                SELECT X03, X04, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27,
                     :V28, :V29, :V30;
                V$V = V$POST_NAME;
            END
            ELSE
            IF (((I$N >= 3) OR (I$N <= 4)) AND (V$POST_GROUP = 97)) THEN
            BEGIN
                IF (I$N = 3) THEN
                BEGIN
                    SELECT X03, X04, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                    FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                    INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26,
                         :V27, :V28, :V29, :V30;
                    V$V = V$POST_NAME;
                END
                ELSE
                IF (V$POST_PODGROUP = 98) THEN
                BEGIN
                    IF ((I$N = 4) AND (V$OU_TYPE = 978)) THEN
                    BEGIN
                        SELECT X03, NULL, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29,
                               X30
                        FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                        INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25,
                             :V26, :V27, :V28, :V29, :V30;
                        V$V = V$POST_NAME;
                    END
                END
            END

            ELSE
            IF ((I$N >= 5) AND (V$POST_GROUP = 1310)) THEN
            BEGIN
                SELECT X03, X04, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27,
                     :V28, :V29, :V30;
                V$V = V$POST_NAME;
            END
            ELSE
            IF ((I$N = 6) AND (V$POST_GROUP = 1323)) THEN
            BEGIN
                SELECT X03, X04, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27,
                     :V28, :V29, :V30;
                V$V = V$POST_NAME;
            END
        END
        ELSE
        IF ((I$N = 8) AND ((V$POST_FUNC = 1267) OR (V$POST_FUNC = 1284) OR (V$POST_FUNC = 1298))) THEN
        BEGIN
            SELECT X03
            FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03)
            INTO :V03;
            V$V = V$POST_NAME;
        END
        ELSE
        IF ((I$N = 9) AND (V$POST_FUNC = 1267)) THEN
        BEGIN
            SELECT X03
            FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03)
            INTO :V03;
            V$V = V$POST_NAME;
        END
        ELSE
        IF ((I$N = 10) AND ((V$POST_FUNC = 1284) OR (V$POST_FUNC = 1298))) THEN
        BEGIN
            SELECT X03
            FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03)
            INTO :V03;
            V$V = V$POST_NAME;
        END

    END

    /* FREE POSTS */

    IF (I$N IN (1, 2, 5, 6)) THEN
    BEGIN
        V04 = 0;

        /* STAVKI UCHITEL - OTDELNO */
        IF (I$N = 1) THEN
        BEGIN
            SELECT SUM(V.VAL)
            FROM LINKS L2
            INNER JOIN VALF V ON (V.OBJ_ID = L2.OBJ_ID)
            INNER JOIN VALL V11 ON (V11.OBJ_ID = L2.OBJ_ID)
            WHERE L2.DATE_DEL IS NULL
              AND L2.OBJ_TYPE_ID = 2
              AND V11.PARAM_ID = 11
              AND V11.IS_DEL = 0
              AND V11.LISTVAL_ID = 1003
              AND V.PARAM_ID = 1342
              AND V.IS_DEL = 0
              AND L2.PARENT_ID = :I$OBJ_ID
            INTO :V04;
        END

        FOR SELECT L13.OBJ_ID, V63.LISTVAL_ID, V64.LISTVAL_ID, V58.LISTVAL_ID, V62.VAL, LV.TAG
            FROM LINKS L2
            INNER JOIN LINKS L13 ON (L13.PARENT_ID = L2.OBJ_ID)
            INNER JOIN VALL V11 ON V11.OBJ_ID = L2.OBJ_ID
            INNER JOIN VALL V63 ON V63.OBJ_ID = L13.OBJ_ID
            INNER JOIN VALL V64 ON V64.OBJ_ID = L13.OBJ_ID
            INNER JOIN VALL V58 ON V58.OBJ_ID = L13.OBJ_ID
            INNER JOIN VALF V62 ON V62.OBJ_ID = L13.OBJ_ID
            INNER JOIN LISTVALS LV ON LV.LISTVAL_ID = V58.LISTVAL_ID
            WHERE L2.DATE_DEL IS NULL
              AND L2.OBJ_TYPE_ID = 2
              AND L2.PARENT_ID = :I$OBJ_ID
              AND V11.PARAM_ID = 11
              AND V11.IS_DEL = 0
              AND V11.LISTVAL_ID = 1003
              AND L13.OBJ_TYPE_ID = 13
              AND L13.DATE_DEL IS NULL
              AND V63.PARAM_ID = 63
              AND V63.IS_DEL = 0
              AND V64.PARAM_ID = 64
              AND V64.IS_DEL = 0
              AND V58.PARAM_ID = 58
              AND V58.IS_DEL = 0
              AND V62.PARAM_ID = 62
              AND V62.IS_DEL = 0
              AND V58.LISTVAL_ID <> 1267
              AND V58.LISTVAL_ID <> 1284
              AND V58.LISTVAL_ID <> 1298
            INTO :V$POST_ID, :V$POST_GROUP, :V$POST_PODGROUP, :V$POST_FUNC, :V$STAVOK, :V$TAG
        DO
        BEGIN
            V$Y = 0;
            /* STAVKI UCHITEL - OTDELNO */
            IF (V$TAG = 'U') THEN
            BEGIN
                V$STAVOK = 0;
            END

            IF (I$N = 1) THEN
            BEGIN
                SELECT Z
                FROM RIK83_STAVOK(:V$POST_ID)
                INTO :V$Y;
                V04 = V04 + V$STAVOK - V$Y;
            END
            ELSE
            IF ((I$N = 2) AND (V$POST_GROUP = 55)) THEN
            BEGIN
                SELECT Z
                FROM RIK83_STAVOK(:V$POST_ID)
                INTO :V$Y;
                V04 = V04 + V$STAVOK - V$Y;
            END

            ELSE
            IF ((I$N = 5) AND (V$POST_GROUP = 1310)) THEN
            BEGIN
                SELECT Z
                FROM RIK83_STAVOK(:V$POST_ID)
                INTO :V$Y;
                V04 = V04 + V$STAVOK - V$Y;
            END
            ELSE
            IF ((I$N = 6) AND (V$POST_GROUP = 1323)) THEN
            BEGIN
                SELECT Z
                FROM RIK83_STAVOK(:V$POST_ID)
                INTO :V$Y;
                V04 = V04 + V$STAVOK - V$Y;
            END

        END

    END
    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE RIK83_DISTR1_2 (
    I$OBJ_ID BIGINT,
    I$N INTEGER)
RETURNS (
    V03 INTEGER,
    V04 NUMERIC(11,2),
    V05 INTEGER,
    V06 INTEGER,
    V07 INTEGER,
    V08 INTEGER,
    V09 INTEGER,
    V10 INTEGER,
    V11 INTEGER,
    V12 INTEGER,
    V13 INTEGER,
    V14 INTEGER,
    V15 INTEGER,
    V16 INTEGER,
    V17 INTEGER,
    V18 INTEGER,
    V19 INTEGER,
    V20 INTEGER,
    V21 INTEGER,
    V22 INTEGER,
    V23 INTEGER,
    V24 INTEGER,
    V25 INTEGER,
    V26 INTEGER,
    V27 INTEGER,
    V28 INTEGER,
    V29 INTEGER,
    V30 INTEGER)
AS
DECLARE VARIABLE V$POST_ID BIGINT;
DECLARE VARIABLE V$POST_GROUP BIGINT;
DECLARE VARIABLE V$POST_PODGROUP BIGINT;
DECLARE VARIABLE V$POST_FUNC BIGINT;
DECLARE VARIABLE V$STAVOK NUMERIC(11,2);
DECLARE VARIABLE V$Y NUMERIC(11,2);
DECLARE VARIABLE V$POST_NAME VARCHAR(4000);
DECLARE VARIABLE V$V VARCHAR(4000);
DECLARE VARIABLE V$WORKER_ID BIGINT;
DECLARE VARIABLE V$OU_TYPE BIGINT;
DECLARE VARIABLE V$CORRECT_CLASS INTEGER;
DECLARE VARIABLE V$TAG VARCHAR(100);
BEGIN
    V03 = 0;

    V05 = 0;
    V06 = 0;
    V07 = 0;
    V08 = 0;
    V09 = 0;
    V10 = 0;
    V11 = 0;
    V12 = 0;
    V13 = 0;
    V14 = 0;
    V15 = 0;
    V16 = 0;
    V17 = 0;
    V18 = 0;
    V19 = 0;
    V20 = 0;
    V21 = 0;
    V22 = 0;
    V23 = 0;
    V24 = 0;
    V25 = 0;
    V26 = 0;
    V27 = 0;
    V28 = 0;
    V29 = 0;
    V30 = 0;

    FOR SELECT L14.OBJ_ID, V69.VAL, V63.LISTVAL_ID, V64.LISTVAL_ID, V58.LISTVAL_ID, V66.VAL, V11.LISTVAL_ID
        FROM LINKS L2
        INNER JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID
        INNER JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID
        INNER JOIN VALL V11 ON V11.OBJ_ID = L14.PARENT_ID
        INNER JOIN VALL V72 ON V72.OBJ_ID = L15.OBJ_ID
        INNER JOIN VALR V69 ON V69.OBJ_ID = L15.OBJ_ID
        INNER JOIN VALL V63 ON V63.OBJ_ID = V69.VAL
        INNER JOIN VALL V64 ON V64.OBJ_ID = V69.VAL
        INNER JOIN VALL V58 ON V58.OBJ_ID = V69.VAL
        INNER JOIN VALS V66 ON V66.OBJ_ID = V69.VAL
        LEFT JOIN VALD V74 ON V74.PARAM_ID = 74 AND V74.OBJ_ID = L15.OBJ_ID AND V74.IS_DEL = 0
        LEFT JOIN VALL V274 ON V274.PARAM_ID = 274 AND V274.OBJ_ID = L14.OBJ_ID AND V274.IS_DEL = 0
        WHERE L2.DATE_DEL IS NULL
          AND L2.OBJ_TYPE_ID = 2
          AND L2.PARENT_ID = :I$OBJ_ID
          AND L14.OBJ_TYPE_ID = 14
          AND L14.DATE_DEL IS NULL
          AND L15.OBJ_TYPE_ID = 15
          AND L15.DATE_DEL IS NULL
          AND V72.PARAM_ID = 72
          AND V72.IS_DEL = 0
          AND V72.LISTVAL_ID = 934
          AND V69.PARAM_ID = 69
          AND V69.IS_DEL = 0
          AND V63.PARAM_ID = 63
          AND V63.IS_DEL = 0
          AND V64.PARAM_ID = 64
          AND V64.IS_DEL = 0
          AND V58.PARAM_ID = 58
          AND V58.IS_DEL = 0
          AND V66.PARAM_ID = 66
          AND V66.IS_DEL = 0
          AND V74.VAL IS NULL
          AND V11.PARAM_ID = 11
          AND V11.IS_DEL = 0
          AND V11.LISTVAL_ID = 954
          AND ((V274.LISTVAL_ID IS NULL) OR (V274.LISTVAL_ID = 602) OR (V274.LISTVAL_ID = 604))
        INTO :V$WORKER_ID, :V$POST_ID, :V$POST_GROUP, :V$POST_PODGROUP, :V$POST_FUNC, :V$POST_NAME, :V$OU_TYPE
    DO
    BEGIN
        IF ((I$N >= 1) AND (I$N <= 8) AND (V$POST_FUNC <> 1267) AND (V$POST_FUNC <> 1284) AND (V$POST_FUNC <> 1298)) THEN
        BEGIN
            IF (I$N = 1) THEN
            BEGIN
                SELECT X03, X04, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27,
                     :V28, :V29, :V30;
                V$V = V$POST_NAME;
            END
            ELSE
            IF ((I$N = 2) AND (V$POST_GROUP = 55)) THEN
            BEGIN
                SELECT X03, X04, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27,
                     :V28, :V29, :V30;
                V$V = V$POST_NAME;
            END
            ELSE
            IF (((I$N >= 3) OR (I$N <= 5)) AND (V$POST_GROUP = 97)) THEN
            BEGIN
                IF (I$N = 3) THEN
                BEGIN
                    SELECT X03, X04, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                    FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                    INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26,
                         :V27, :V28, :V29, :V30;
                    V$V = V$POST_NAME;
                END
                ELSE
                IF (V$POST_PODGROUP = 98) THEN
                BEGIN
                    IF ((I$N = 4) OR ((I$N = 5) AND (V$OU_TYPE = 978))) THEN
                    BEGIN
                        SELECT X03, NULL, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29,
                               X30
                        FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                        INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25,
                             :V26, :V27, :V28, :V29, :V30;
                        V$V = V$POST_NAME;
                    END
                END
            END
            ELSE
            IF ((I$N = 5) AND (V$OU_TYPE <> 978) AND (V$POST_GROUP = 97)) THEN
            BEGIN
                V$CORRECT_CLASS = 0;

                SELECT FIRST 1 1
                FROM LINKS L58
                INNER JOIN LINKS L9 ON L9.OBJ_ID = L58.OBJ_ID
                INNER JOIN VALL V592 ON V592.OBJ_ID = L9.PARENT_ID
                WHERE L58.PARENT_ID = :V$WORKER_ID
                  AND L58.OBJ_TYPE_ID = 58
                  AND L58.DATE_DEL IS NULL
                  AND L9.PARENT_TYPE_ID = 9
                  AND L9.DATE_DEL IS NULL
                  AND V592.PARAM_ID = 592
                  AND V592.IS_DEL = 0
                  AND V592.LISTVAL_ID > 197
                INTO :V$CORRECT_CLASS;

                IF (V$CORRECT_CLASS = 1) THEN
                BEGIN
                    SELECT X03, NULL, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                    FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                    INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26,
                         :V27, :V28, :V29, :V30;
                    V$V = V$POST_NAME;
                END
            END
            ELSE
            IF ((I$N >= 6) AND (I$N <= 7) AND (V$POST_GROUP = 1310)) THEN
            BEGIN
                IF (I$N = 6) THEN
                BEGIN
                    SELECT X03, X04, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                    FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                    INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26,
                         :V27, :V28, :V29, :V30;
                    V$V = V$POST_NAME;
                END
            END
            ELSE
            IF ((I$N = 8) AND (V$POST_GROUP = 1323)) THEN
            BEGIN
                SELECT X03, X04, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27,
                     :V28, :V29, :V30;
                V$V = V$POST_NAME;
            END
        END
    END

    /* FREE POSTS */

    IF (I$N IN (1, 2, 6, 8)) THEN
    BEGIN
        V04 = 0;

        /* STAVKI UCHITEL - OTDELNO */
        IF (I$N = 1) THEN
        BEGIN
            SELECT SUM(V.VAL)
            FROM LINKS L2
            INNER JOIN VALF V ON (V.OBJ_ID = L2.OBJ_ID)
            INNER JOIN VALL V11 ON V11.OBJ_ID = L2.OBJ_ID
            WHERE L2.DATE_DEL IS NULL
              AND L2.OBJ_TYPE_ID = 2
              AND V11.PARAM_ID = 11
              AND V11.IS_DEL = 0
              AND V11.LISTVAL_ID = 954
              AND V.PARAM_ID = 1342
              AND V.IS_DEL = 0
              AND L2.PARENT_ID = :I$OBJ_ID
            INTO :V04;
        END

        FOR SELECT L13.OBJ_ID, V63.LISTVAL_ID, V64.LISTVAL_ID, V58.LISTVAL_ID, V62.VAL, LV.TAG
            FROM LINKS L2
            INNER JOIN LINKS L13 ON (L13.PARENT_ID = L2.OBJ_ID)
            INNER JOIN VALL V11 ON V11.OBJ_ID = L2.OBJ_ID
            INNER JOIN VALL V63 ON V63.OBJ_ID = L13.OBJ_ID
            INNER JOIN VALL V64 ON V64.OBJ_ID = L13.OBJ_ID
            INNER JOIN VALL V58 ON V58.OBJ_ID = L13.OBJ_ID
            INNER JOIN VALF V62 ON V62.OBJ_ID = L13.OBJ_ID
            INNER JOIN LISTVALS LV ON LV.LISTVAL_ID = V58.LISTVAL_ID
            WHERE L2.DATE_DEL IS NULL
              AND L2.OBJ_TYPE_ID = 2
              AND L2.PARENT_ID = :I$OBJ_ID
              AND V11.PARAM_ID = 11
              AND V11.IS_DEL = 0
              AND V11.LISTVAL_ID = 954
              AND L13.OBJ_TYPE_ID = 13
              AND L13.DATE_DEL IS NULL
              AND V63.PARAM_ID = 63
              AND V63.IS_DEL = 0
              AND V64.PARAM_ID = 64
              AND V64.IS_DEL = 0
              AND V58.PARAM_ID = 58
              AND V58.IS_DEL = 0
              AND V62.PARAM_ID = 62
              AND V62.IS_DEL = 0
              AND V58.LISTVAL_ID <> 1267
              AND V58.LISTVAL_ID <> 1284
              AND V58.LISTVAL_ID <> 1298
            INTO :V$POST_ID, :V$POST_GROUP, :V$POST_PODGROUP, :V$POST_FUNC, :V$STAVOK, :V$TAG
        DO
        BEGIN
            V$Y = 0;
            /* STAVKI UCHITEL - OTDELNO */
            IF (V$TAG = 'U') THEN
            BEGIN
                V$STAVOK = 0;
            END

            IF (I$N = 1) THEN
            BEGIN
                SELECT Z
                FROM RIK83_STAVOK(:V$POST_ID)
                INTO :V$Y;
                V04 = V04 + V$STAVOK - V$Y;
            END
            ELSE
            IF ((I$N = 2) AND (V$POST_GROUP = 55)) THEN
            BEGIN
                SELECT Z
                FROM RIK83_STAVOK(:V$POST_ID)
                INTO :V$Y;
                V04 = V04 + V$STAVOK - V$Y;
            END

            ELSE
            IF ((I$N = 6) AND (V$POST_GROUP = 1310)) THEN
            BEGIN
                SELECT Z
                FROM RIK83_STAVOK(:V$POST_ID)
                INTO :V$Y;
                V04 = V04 + V$STAVOK - V$Y;
            END
            ELSE
            IF ((I$N = 8) AND (V$POST_GROUP = 1323)) THEN
            BEGIN
                SELECT Z
                FROM RIK83_STAVOK(:V$POST_ID)
                INTO :V$Y;
                V04 = V04 + V$STAVOK - V$Y;
            END

        END

    END
    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE RIK83_DISTR1_3 (
    I$OBJ_ID BIGINT,
    I$N INTEGER)
RETURNS (
    V03 INTEGER,
    V04 NUMERIC(11,2),
    V05 INTEGER,
    V06 INTEGER,
    V07 INTEGER,
    V08 INTEGER,
    V09 INTEGER,
    V10 INTEGER,
    V11 INTEGER,
    V12 INTEGER,
    V13 INTEGER,
    V14 INTEGER,
    V15 INTEGER,
    V16 INTEGER,
    V17 INTEGER,
    V18 INTEGER,
    V19 INTEGER,
    V20 INTEGER,
    V21 INTEGER,
    V22 INTEGER,
    V23 INTEGER,
    V24 INTEGER,
    V25 INTEGER,
    V26 INTEGER,
    V27 INTEGER,
    V28 INTEGER,
    V29 INTEGER,
    V30 INTEGER)
AS
DECLARE VARIABLE V$POST_ID BIGINT;
DECLARE VARIABLE V$POST_GROUP BIGINT;
DECLARE VARIABLE V$POST_PODGROUP BIGINT;
DECLARE VARIABLE V$POST_FUNC BIGINT;
DECLARE VARIABLE V$STAVOK NUMERIC(11,2);
DECLARE VARIABLE V$Y NUMERIC(11,2);
DECLARE VARIABLE V$POST_NAME VARCHAR(4000);
DECLARE VARIABLE V$V VARCHAR(4000);
DECLARE VARIABLE V$WORKER_ID BIGINT;
DECLARE VARIABLE V$OU_TYPE BIGINT;
DECLARE VARIABLE V$CORRECT_CLASS INTEGER;
DECLARE VARIABLE V$TAG VARCHAR(100);
BEGIN
    V03 = 0;

    V05 = 0;
    V06 = 0;
    V07 = 0;
    V08 = 0;
    V09 = 0;
    V10 = 0;
    V11 = 0;
    V12 = 0;
    V13 = 0;
    V14 = 0;
    V15 = 0;
    V16 = 0;
    V17 = 0;
    V18 = 0;
    V19 = 0;
    V20 = 0;
    V21 = 0;
    V22 = 0;
    V23 = 0;
    V24 = 0;
    V25 = 0;
    V26 = 0;
    V27 = 0;
    V28 = 0;
    V29 = 0;
    V30 = 0;

    FOR SELECT L14.OBJ_ID, V69.VAL, V63.LISTVAL_ID, V64.LISTVAL_ID, V58.LISTVAL_ID, V66.VAL, V11.LISTVAL_ID
        FROM LINKS L2
        INNER JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID
        INNER JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID
        INNER JOIN VALL V11 ON V11.OBJ_ID = L14.PARENT_ID
        INNER JOIN VALL V72 ON V72.OBJ_ID = L15.OBJ_ID
        INNER JOIN VALR V69 ON V69.OBJ_ID = L15.OBJ_ID
        INNER JOIN VALL V63 ON V63.OBJ_ID = V69.VAL
        INNER JOIN VALL V64 ON V64.OBJ_ID = V69.VAL
        INNER JOIN VALL V58 ON V58.OBJ_ID = V69.VAL
        INNER JOIN VALS V66 ON V66.OBJ_ID = V69.VAL
        LEFT JOIN VALD V74 ON V74.PARAM_ID = 74 AND V74.OBJ_ID = L15.OBJ_ID AND V74.IS_DEL = 0
        LEFT JOIN VALL V274 ON V274.PARAM_ID = 274 AND V274.OBJ_ID = L14.OBJ_ID AND V274.IS_DEL = 0
        WHERE L2.DATE_DEL IS NULL
          AND L2.OBJ_TYPE_ID = 2
          AND L2.PARENT_ID = :I$OBJ_ID
          AND L14.OBJ_TYPE_ID = 14
          AND L14.DATE_DEL IS NULL
          AND L15.OBJ_TYPE_ID = 15
          AND L15.DATE_DEL IS NULL
          AND V72.PARAM_ID = 72
          AND V72.IS_DEL = 0
          AND V72.LISTVAL_ID = 934
          AND V69.PARAM_ID = 69
          AND V69.IS_DEL = 0
          AND V63.PARAM_ID = 63
          AND V63.IS_DEL = 0
          AND V64.PARAM_ID = 64
          AND V64.IS_DEL = 0
          AND V58.PARAM_ID = 58
          AND V58.IS_DEL = 0
          AND V66.PARAM_ID = 66
          AND V66.IS_DEL = 0
          AND V74.VAL IS NULL
          AND V11.PARAM_ID = 11
          AND V11.IS_DEL = 0
          AND V11.LISTVAL_ID = 958
          AND ((V274.LISTVAL_ID IS NULL) OR (V274.LISTVAL_ID = 602) OR (V274.LISTVAL_ID = 604))
        INTO :V$WORKER_ID, :V$POST_ID, :V$POST_GROUP, :V$POST_PODGROUP, :V$POST_FUNC, :V$POST_NAME, :V$OU_TYPE
    DO
    BEGIN
        IF ((I$N >= 1) AND (I$N <= 8) AND (V$POST_FUNC <> 1267) AND (V$POST_FUNC <> 1284) AND (V$POST_FUNC <> 1298)) THEN
        BEGIN
            IF (I$N = 1) THEN
            BEGIN
                SELECT X03, X04, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27,
                     :V28, :V29, :V30;
                V$V = V$POST_NAME;
            END
            ELSE
            IF ((I$N = 2) AND (V$POST_GROUP = 55)) THEN
            BEGIN
                SELECT X03, X04, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27,
                     :V28, :V29, :V30;
                V$V = V$POST_NAME;
            END
            ELSE
            IF (((I$N >= 3) OR (I$N <= 5)) AND (V$POST_GROUP = 97)) THEN
            BEGIN
                IF (I$N = 3) THEN
                BEGIN
                    SELECT X03, X04, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                    FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                    INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26,
                         :V27, :V28, :V29, :V30;
                    V$V = V$POST_NAME;
                END
                ELSE
                IF (V$POST_PODGROUP = 98) THEN
                BEGIN
                    IF ((I$N = 4) OR ((I$N = 5) AND (V$OU_TYPE = 978))) THEN
                    BEGIN
                        SELECT X03, NULL, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29,
                               X30
                        FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                        INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25,
                             :V26, :V27, :V28, :V29, :V30;
                        V$V = V$POST_NAME;
                    END
                END
            END
            ELSE
            IF ((I$N = 5) AND (V$OU_TYPE <> 978) AND (V$POST_GROUP = 97)) THEN
            BEGIN
                V$CORRECT_CLASS = 0;

                SELECT FIRST 1 1
                FROM LINKS L58
                INNER JOIN LINKS L9 ON L9.OBJ_ID = L58.OBJ_ID
                INNER JOIN VALL V592 ON V592.OBJ_ID = L9.PARENT_ID
                WHERE L58.PARENT_ID = :V$WORKER_ID
                  AND L58.OBJ_TYPE_ID = 58
                  AND L58.DATE_DEL IS NULL
                  AND L9.PARENT_TYPE_ID = 9
                  AND L9.DATE_DEL IS NULL
                  AND V592.PARAM_ID = 592
                  AND V592.IS_DEL = 0
                  AND V592.LISTVAL_ID > 197
                INTO :V$CORRECT_CLASS;

                IF (V$CORRECT_CLASS = 1) THEN
                BEGIN
                    SELECT X03, NULL, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                    FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                    INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26,
                         :V27, :V28, :V29, :V30;
                    V$V = V$POST_NAME;
                END
            END
            ELSE
            IF ((I$N >= 6) AND (I$N <= 7) AND (V$POST_GROUP = 1310)) THEN
            BEGIN
                IF (I$N = 6) THEN
                BEGIN
                    SELECT X03, X04, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                    FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                    INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26,
                         :V27, :V28, :V29, :V30;
                    V$V = V$POST_NAME;
                END
            END
            ELSE
            IF ((I$N = 8) AND (V$POST_GROUP = 1323)) THEN
            BEGIN
                SELECT X03, X04, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27,
                     :V28, :V29, :V30;
                V$V = V$POST_NAME;
            END
        END
        ELSE
        IF ((I$N = 9) AND ((V$POST_FUNC = 1267) OR (V$POST_FUNC = 1284) OR (V$POST_FUNC = 1298))) THEN
        BEGIN
            SELECT X03
            FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03)
            INTO :V03;
            V$V = V$POST_NAME;
        END
        ELSE
        IF ((I$N = 10) AND (V$POST_FUNC = 1267)) THEN
        BEGIN
            SELECT X03
            FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03)
            INTO :V03;
            V$V = V$POST_NAME;
        END
        ELSE
        IF ((I$N = 11) AND ((V$POST_FUNC = 1284) OR (V$POST_FUNC = 1298))) THEN
        BEGIN
            SELECT X03
            FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03)
            INTO :V03;
            V$V = V$POST_NAME;
        END

    END

    /* FREE POSTS */

    IF (I$N IN (1, 2, 6, 8)) THEN
    BEGIN
        V04 = 0;

        /* STAVKI UCHITEL - OTDELNO */
        IF (I$N = 1) THEN
        BEGIN
            SELECT SUM(V.VAL)
            FROM LINKS L2
            INNER JOIN VALF V ON (V.OBJ_ID = L2.OBJ_ID)
            INNER JOIN VALL V11 ON (V11.OBJ_ID = L2.OBJ_ID)
            WHERE L2.DATE_DEL IS NULL
              AND L2.OBJ_TYPE_ID = 2
              AND V11.PARAM_ID = 11
              AND V11.IS_DEL = 0
              AND V11.LISTVAL_ID = 958
              AND V.PARAM_ID = 1342
              AND V.IS_DEL = 0
              AND L2.PARENT_ID = :I$OBJ_ID
            INTO :V04;
        END

        FOR SELECT L13.OBJ_ID, V63.LISTVAL_ID, V64.LISTVAL_ID, V58.LISTVAL_ID, V62.VAL, LV.TAG
            FROM LINKS L2
            INNER JOIN LINKS L13 ON (L13.PARENT_ID = L2.OBJ_ID)
            INNER JOIN VALL V11 ON V11.OBJ_ID = L2.OBJ_ID
            INNER JOIN VALL V63 ON V63.OBJ_ID = L13.OBJ_ID
            INNER JOIN VALL V64 ON V64.OBJ_ID = L13.OBJ_ID
            INNER JOIN VALL V58 ON V58.OBJ_ID = L13.OBJ_ID
            INNER JOIN VALF V62 ON V62.OBJ_ID = L13.OBJ_ID
            INNER JOIN LISTVALS LV ON LV.LISTVAL_ID = V58.LISTVAL_ID
            WHERE L2.DATE_DEL IS NULL
              AND L2.OBJ_TYPE_ID = 2
              AND L2.PARENT_ID = :I$OBJ_ID
              AND V11.PARAM_ID = 11
              AND V11.IS_DEL = 0
              AND V11.LISTVAL_ID = 958
              AND L13.OBJ_TYPE_ID = 13
              AND L13.DATE_DEL IS NULL
              AND V63.PARAM_ID = 63
              AND V63.IS_DEL = 0
              AND V64.PARAM_ID = 64
              AND V64.IS_DEL = 0
              AND V58.PARAM_ID = 58
              AND V58.IS_DEL = 0
              AND V62.PARAM_ID = 62
              AND V62.IS_DEL = 0
              AND V58.LISTVAL_ID <> 1267
              AND V58.LISTVAL_ID <> 1284
              AND V58.LISTVAL_ID <> 1298
            INTO :V$POST_ID, :V$POST_GROUP, :V$POST_PODGROUP, :V$POST_FUNC, :V$STAVOK, :V$TAG
        DO
        BEGIN
            V$Y = 0;
            /* STAVKI UCHITEL - OTDELNO */
            IF (V$TAG = 'U') THEN
            BEGIN
                V$STAVOK = 0;
            END

            IF (I$N = 1) THEN
            BEGIN
                SELECT Z
                FROM RIK83_STAVOK(:V$POST_ID)
                INTO :V$Y;
                V04 = V04 + V$STAVOK - V$Y;
            END
            ELSE
            IF ((I$N = 2) AND (V$POST_GROUP = 55)) THEN
            BEGIN
                SELECT Z
                FROM RIK83_STAVOK(:V$POST_ID)
                INTO :V$Y;
                V04 = V04 + V$STAVOK - V$Y;
            END

            ELSE
            IF ((I$N = 6) AND (V$POST_GROUP = 1310)) THEN
            BEGIN
                SELECT Z
                FROM RIK83_STAVOK(:V$POST_ID)
                INTO :V$Y;
                V04 = V04 + V$STAVOK - V$Y;
            END
            ELSE
            IF ((I$N = 8) AND (V$POST_GROUP = 1323)) THEN
            BEGIN
                SELECT Z
                FROM RIK83_STAVOK(:V$POST_ID)
                INTO :V$Y;
                V04 = V04 + V$STAVOK - V$Y;
            END

        END

    END
    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE RIK83_DISTR1_4 (
    I$OBJ_ID BIGINT,
    I$N INTEGER)
RETURNS (
    V03 INTEGER,
    V04 NUMERIC(11,2),
    V05 INTEGER,
    V06 INTEGER,
    V07 INTEGER,
    V08 INTEGER,
    V09 INTEGER,
    V10 INTEGER,
    V11 INTEGER,
    V12 INTEGER,
    V13 INTEGER,
    V14 INTEGER,
    V15 INTEGER,
    V16 INTEGER,
    V17 INTEGER,
    V18 INTEGER,
    V19 INTEGER,
    V20 INTEGER,
    V21 INTEGER,
    V22 INTEGER,
    V23 INTEGER,
    V24 INTEGER,
    V25 INTEGER,
    V26 INTEGER,
    V27 INTEGER,
    V28 INTEGER,
    V29 INTEGER,
    V30 INTEGER)
AS
DECLARE VARIABLE V$POST_ID BIGINT;
DECLARE VARIABLE V$POST_GROUP BIGINT;
DECLARE VARIABLE V$POST_PODGROUP BIGINT;
DECLARE VARIABLE V$POST_FUNC BIGINT;
DECLARE VARIABLE V$STAVOK NUMERIC(11,2);
DECLARE VARIABLE V$Y NUMERIC(11,2);
DECLARE VARIABLE V$POST_NAME VARCHAR(4000);
DECLARE VARIABLE V$V VARCHAR(4000);
DECLARE VARIABLE V$WORKER_ID BIGINT;
DECLARE VARIABLE V$OU_TYPE BIGINT;
DECLARE VARIABLE V$CORRECT_CLASS INTEGER;
DECLARE VARIABLE V$TAG VARCHAR(100);
BEGIN
    V03 = 0;

    V05 = 0;
    V06 = 0;
    V07 = 0;
    V08 = 0;
    V09 = 0;
    V10 = 0;
    V11 = 0;
    V12 = 0;
    V13 = 0;
    V14 = 0;
    V15 = 0;
    V16 = 0;
    V17 = 0;
    V18 = 0;
    V19 = 0;
    V20 = 0;
    V21 = 0;
    V22 = 0;
    V23 = 0;
    V24 = 0;
    V25 = 0;
    V26 = 0;
    V27 = 0;
    V28 = 0;
    V29 = 0;
    V30 = 0;

    FOR SELECT L14.OBJ_ID, V69.VAL, V63.LISTVAL_ID, V64.LISTVAL_ID, V58.LISTVAL_ID, V66.VAL, V11.LISTVAL_ID
        FROM LINKS L2
        INNER JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID
        INNER JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID
        INNER JOIN VALL V11 ON V11.OBJ_ID = L14.PARENT_ID
        INNER JOIN VALL V72 ON V72.OBJ_ID = L15.OBJ_ID
        INNER JOIN VALR V69 ON V69.OBJ_ID = L15.OBJ_ID
        INNER JOIN VALL V63 ON V63.OBJ_ID = V69.VAL
        INNER JOIN VALL V64 ON V64.OBJ_ID = V69.VAL
        INNER JOIN VALL V58 ON V58.OBJ_ID = V69.VAL
        INNER JOIN VALS V66 ON V66.OBJ_ID = V69.VAL
        LEFT JOIN VALD V74 ON V74.PARAM_ID = 74 AND V74.OBJ_ID = L15.OBJ_ID AND V74.IS_DEL = 0
        LEFT JOIN VALL V274 ON V274.PARAM_ID = 274 AND V274.OBJ_ID = L14.OBJ_ID AND V274.IS_DEL = 0
        WHERE L2.DATE_DEL IS NULL
          AND L2.OBJ_TYPE_ID = 2
          AND L2.PARENT_ID = :I$OBJ_ID
          AND L14.OBJ_TYPE_ID = 14
          AND L14.DATE_DEL IS NULL
          AND L15.OBJ_TYPE_ID = 15
          AND L15.DATE_DEL IS NULL
          AND V72.PARAM_ID = 72
          AND V72.IS_DEL = 0
          AND V72.LISTVAL_ID = 934
          AND V69.PARAM_ID = 69
          AND V69.IS_DEL = 0
          AND V63.PARAM_ID = 63
          AND V63.IS_DEL = 0
          AND V64.PARAM_ID = 64
          AND V64.IS_DEL = 0
          AND V58.PARAM_ID = 58
          AND V58.IS_DEL = 0
          AND V66.PARAM_ID = 66
          AND V66.IS_DEL = 0
          AND V74.VAL IS NULL
          AND V11.PARAM_ID = 11
          AND V11.IS_DEL = 0
          AND V11.LISTVAL_ID = 969
          AND ((V274.LISTVAL_ID IS NULL) OR (V274.LISTVAL_ID = 602) OR (V274.LISTVAL_ID = 604))
        INTO :V$WORKER_ID, :V$POST_ID, :V$POST_GROUP, :V$POST_PODGROUP, :V$POST_FUNC, :V$POST_NAME, :V$OU_TYPE
    DO
    BEGIN
        IF ((I$N >= 1) AND (I$N <= 8) AND (V$POST_FUNC <> 1267) AND (V$POST_FUNC <> 1284) AND (V$POST_FUNC <> 1298)) THEN
        BEGIN
            IF (I$N = 1) THEN
            BEGIN
                SELECT X03, X04, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27,
                     :V28, :V29, :V30;
                V$V = V$POST_NAME;
            END
            ELSE
            IF ((I$N = 2) AND (V$POST_GROUP = 55)) THEN
            BEGIN
                SELECT X03, X04, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27,
                     :V28, :V29, :V30;
                V$V = V$POST_NAME;
            END
            ELSE
            IF (((I$N >= 3) OR (I$N <= 5)) AND (V$POST_GROUP = 97)) THEN
            BEGIN
                IF (I$N = 3) THEN
                BEGIN
                    SELECT X03, X04, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                    FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                    INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26,
                         :V27, :V28, :V29, :V30;
                    V$V = V$POST_NAME;
                END
                ELSE
                IF (V$POST_PODGROUP = 98) THEN
                BEGIN
                    IF ((I$N = 4) OR ((I$N = 5) AND (V$OU_TYPE = 978))) THEN
                    BEGIN
                        SELECT X03, NULL, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29,
                               X30
                        FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                        INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25,
                             :V26, :V27, :V28, :V29, :V30;
                        V$V = V$POST_NAME;
                    END
                END
            END
            ELSE
            IF ((I$N = 5) AND (V$OU_TYPE <> 978) AND (V$POST_GROUP = 97)) THEN
            BEGIN
                V$CORRECT_CLASS = 0;

                SELECT FIRST 1 1
                FROM LINKS L58
                INNER JOIN LINKS L9 ON L9.OBJ_ID = L58.OBJ_ID
                INNER JOIN VALL V592 ON V592.OBJ_ID = L9.PARENT_ID
                WHERE L58.PARENT_ID = :V$WORKER_ID
                  AND L58.OBJ_TYPE_ID = 58
                  AND L58.DATE_DEL IS NULL
                  AND L9.PARENT_TYPE_ID = 9
                  AND L9.DATE_DEL IS NULL
                  AND V592.PARAM_ID = 592
                  AND V592.IS_DEL = 0
                  AND V592.LISTVAL_ID > 197
                INTO :V$CORRECT_CLASS;

                IF (V$CORRECT_CLASS = 1) THEN
                BEGIN
                    SELECT X03, NULL, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                    FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                    INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26,
                         :V27, :V28, :V29, :V30;
                    V$V = V$POST_NAME;
                END
            END
            ELSE
            IF ((I$N >= 6) AND (I$N <= 7) AND (V$POST_GROUP = 1310)) THEN
            BEGIN
                IF (I$N = 6) THEN
                BEGIN
                    SELECT X03, X04, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                    FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                    INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26,
                         :V27, :V28, :V29, :V30;
                    V$V = V$POST_NAME;
                END
            END
            ELSE
            IF ((I$N = 8) AND (V$POST_GROUP = 1323)) THEN
            BEGIN
                SELECT X03, X04, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27,
                     :V28, :V29, :V30;
                V$V = V$POST_NAME;
            END
        END
    END

    /* FREE POSTS */

    IF (I$N IN (1, 2, 6, 8)) THEN
    BEGIN
        V04 = 0;

        /* STAVKI UCHITEL - OTDELNO */
        IF (I$N = 1) THEN
        BEGIN
            SELECT SUM(V.VAL)
            FROM LINKS L2
            INNER JOIN VALF V ON (V.OBJ_ID = L2.OBJ_ID)
            INNER JOIN VALL V11 ON (V11.OBJ_ID = L2.OBJ_ID)
            WHERE L2.DATE_DEL IS NULL
              AND L2.OBJ_TYPE_ID = 2
              AND V11.PARAM_ID = 11
              AND V11.IS_DEL = 0
              AND V11.LISTVAL_ID = 969
              AND V.PARAM_ID = 1342
              AND V.IS_DEL = 0
              AND L2.PARENT_ID = :I$OBJ_ID
            INTO :V04;
        END

        FOR SELECT L13.OBJ_ID, V63.LISTVAL_ID, V64.LISTVAL_ID, V58.LISTVAL_ID, V62.VAL, LV.TAG
            FROM LINKS L2
            INNER JOIN LINKS L13 ON (L13.PARENT_ID = L2.OBJ_ID)
            INNER JOIN VALL V11 ON V11.OBJ_ID = L2.OBJ_ID
            INNER JOIN VALL V63 ON V63.OBJ_ID = L13.OBJ_ID
            INNER JOIN VALL V64 ON V64.OBJ_ID = L13.OBJ_ID
            INNER JOIN VALL V58 ON V58.OBJ_ID = L13.OBJ_ID
            INNER JOIN VALF V62 ON V62.OBJ_ID = L13.OBJ_ID
            INNER JOIN LISTVALS LV ON LV.LISTVAL_ID = V58.LISTVAL_ID
            WHERE L2.DATE_DEL IS NULL
              AND L2.OBJ_TYPE_ID = 2
              AND L2.PARENT_ID = :I$OBJ_ID
              AND V11.PARAM_ID = 11
              AND V11.IS_DEL = 0
              AND V11.LISTVAL_ID = 969
              AND L13.OBJ_TYPE_ID = 13
              AND L13.DATE_DEL IS NULL
              AND V63.PARAM_ID = 63
              AND V63.IS_DEL = 0
              AND V64.PARAM_ID = 64
              AND V64.IS_DEL = 0
              AND V58.PARAM_ID = 58
              AND V58.IS_DEL = 0
              AND V62.PARAM_ID = 62
              AND V62.IS_DEL = 0
              AND V58.LISTVAL_ID <> 1267
              AND V58.LISTVAL_ID <> 1284
              AND V58.LISTVAL_ID <> 1298
            INTO :V$POST_ID, :V$POST_GROUP, :V$POST_PODGROUP, :V$POST_FUNC, :V$STAVOK, :V$TAG
        DO
        BEGIN
            V$Y = 0;
            /* STAVKI UCHITEL - OTDELNO */
            IF (V$TAG = 'U') THEN
            BEGIN
                V$STAVOK = 0;
            END

            IF (I$N = 1) THEN
            BEGIN
                SELECT Z
                FROM RIK83_STAVOK(:V$POST_ID)
                INTO :V$Y;
                V04 = V04 + V$STAVOK - V$Y;
            END
            ELSE
            IF ((I$N = 2) AND (V$POST_GROUP = 55)) THEN
            BEGIN
                SELECT Z
                FROM RIK83_STAVOK(:V$POST_ID)
                INTO :V$Y;
                V04 = V04 + V$STAVOK - V$Y;
            END

            ELSE
            IF ((I$N = 6) AND (V$POST_GROUP = 1310)) THEN
            BEGIN
                SELECT Z
                FROM RIK83_STAVOK(:V$POST_ID)
                INTO :V$Y;
                V04 = V04 + V$STAVOK - V$Y;
            END
            ELSE
            IF ((I$N = 8) AND (V$POST_GROUP = 1323)) THEN
            BEGIN
                SELECT Z
                FROM RIK83_STAVOK(:V$POST_ID)
                INTO :V$Y;
                V04 = V04 + V$STAVOK - V$Y;
            END

        END

    END
    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE RIK83_DISTR1_5 (
    I$OBJ_ID BIGINT,
    I$N INTEGER)
RETURNS (
    V03 INTEGER,
    V04 NUMERIC(11,2),
    V05 INTEGER,
    V06 INTEGER,
    V07 INTEGER,
    V08 INTEGER,
    V09 INTEGER,
    V10 INTEGER,
    V11 INTEGER,
    V12 INTEGER,
    V13 INTEGER,
    V14 INTEGER,
    V15 INTEGER,
    V16 INTEGER,
    V17 INTEGER,
    V18 INTEGER,
    V19 INTEGER,
    V20 INTEGER,
    V21 INTEGER,
    V22 INTEGER,
    V23 INTEGER,
    V24 INTEGER,
    V25 INTEGER,
    V26 INTEGER,
    V27 INTEGER,
    V28 INTEGER,
    V29 INTEGER,
    V30 INTEGER)
AS
DECLARE VARIABLE V$POST_ID BIGINT;
DECLARE VARIABLE V$POST_GROUP BIGINT;
DECLARE VARIABLE V$POST_PODGROUP BIGINT;
DECLARE VARIABLE V$POST_FUNC BIGINT;
DECLARE VARIABLE V$STAVOK NUMERIC(11,2);
DECLARE VARIABLE V$Y NUMERIC(11,2);
DECLARE VARIABLE V$POST_NAME VARCHAR(4000);
DECLARE VARIABLE V$V VARCHAR(4000);
DECLARE VARIABLE V$WORKER_ID BIGINT;
DECLARE VARIABLE V$OU_TYPE BIGINT;--declare variable V$CORRECT_CLASS integer;
DECLARE VARIABLE V$TAG VARCHAR(100);
BEGIN
    V03 = 0;

    V05 = 0;
    V06 = 0;
    V07 = 0;
    V08 = 0;
    V09 = 0;
    V10 = 0;
    V11 = 0;
    V12 = 0;
    V13 = 0;
    V14 = 0;
    V15 = 0;
    V16 = 0;
    V17 = 0;
    V18 = 0;
    V19 = 0;
    V20 = 0;
    V21 = 0;
    V22 = 0;
    V23 = 0;
    V24 = 0;
    V25 = 0;
    V26 = 0;
    V27 = 0;
    V28 = 0;
    V29 = 0;
    V30 = 0;

    FOR SELECT L14.OBJ_ID, V69.VAL, V63.LISTVAL_ID, V64.LISTVAL_ID, V58.LISTVAL_ID, V66.VAL, V11.LISTVAL_ID
        FROM LINKS L2
        INNER JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID
        INNER JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID
        INNER JOIN VALL V11 ON V11.OBJ_ID = L14.PARENT_ID
        INNER JOIN VALL V10 ON V10.OBJ_ID = L2.OBJ_ID
        INNER JOIN VALL V72 ON V72.OBJ_ID = L15.OBJ_ID
        INNER JOIN VALR V69 ON V69.OBJ_ID = L15.OBJ_ID
        INNER JOIN VALL V63 ON V63.OBJ_ID = V69.VAL
        INNER JOIN VALL V64 ON V64.OBJ_ID = V69.VAL
        INNER JOIN VALL V58 ON V58.OBJ_ID = V69.VAL
        INNER JOIN VALS V66 ON V66.OBJ_ID = V69.VAL
        LEFT JOIN VALD V74 ON V74.PARAM_ID = 74 AND V74.OBJ_ID = L15.OBJ_ID AND V74.IS_DEL = 0
        LEFT JOIN VALL V274 ON V274.PARAM_ID = 274 AND V274.OBJ_ID = L14.OBJ_ID AND V274.IS_DEL = 0
        WHERE L2.DATE_DEL IS NULL
          AND L2.OBJ_TYPE_ID = 2
          AND L2.PARENT_ID = :I$OBJ_ID
          AND L14.OBJ_TYPE_ID = 14
          AND L14.DATE_DEL IS NULL
          AND L15.OBJ_TYPE_ID = 15
          AND L15.DATE_DEL IS NULL
          AND V72.PARAM_ID = 72
          AND V72.IS_DEL = 0
          AND V72.LISTVAL_ID = 934
          AND V69.PARAM_ID = 69
          AND V69.IS_DEL = 0
          AND V63.PARAM_ID = 63
          AND V63.IS_DEL = 0
          AND V64.PARAM_ID = 64
          AND V64.IS_DEL = 0
          AND V58.PARAM_ID = 58
          AND V58.IS_DEL = 0
          AND V66.PARAM_ID = 66
          AND V66.IS_DEL = 0
          AND V74.VAL IS NULL
          AND V11.PARAM_ID = 11
          AND V11.IS_DEL = 0
          AND V10.PARAM_ID = 10
          AND V10.IS_DEL = 0
          AND V10.LISTVAL_ID IN (968, 973)
          AND ((V274.LISTVAL_ID IS NULL) OR (V274.LISTVAL_ID = 602) OR (V274.LISTVAL_ID = 604))
        INTO :V$WORKER_ID, :V$POST_ID, :V$POST_GROUP, :V$POST_PODGROUP, :V$POST_FUNC, :V$POST_NAME, :V$OU_TYPE
    DO
    BEGIN
        IF ((I$N >= 1) AND (I$N <= 6) AND (V$POST_FUNC <> 1267) AND (V$POST_FUNC <> 1284) AND (V$POST_FUNC <> 1298)) THEN
        BEGIN
            IF (I$N = 1) THEN
            BEGIN
                SELECT X03, X04, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27,
                     :V28, :V29, :V30;
                V$V = V$POST_NAME;
            END
            ELSE
            IF ((I$N = 2) AND (V$POST_GROUP = 55)) THEN
            BEGIN
                SELECT X03, X04, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27,
                     :V28, :V29, :V30;
                V$V = V$POST_NAME;
            END
            ELSE
            IF (((I$N >= 3) OR (I$N <= 4)) AND (V$POST_GROUP = 97)) THEN
            BEGIN
                IF (I$N = 3) THEN
                BEGIN
                    SELECT X03, X04, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                    FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                    INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26,
                         :V27, :V28, :V29, :V30;
                    V$V = V$POST_NAME;
                END
                ELSE
                IF (V$POST_PODGROUP = 98) THEN
                BEGIN
                    IF ((I$N = 4) AND (V$OU_TYPE = 978)) THEN
                    BEGIN
                        SELECT X03, NULL, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29,
                               X30
                        FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                        INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25,
                             :V26, :V27, :V28, :V29, :V30;
                        V$V = V$POST_NAME;
                    END
                END
            END

            ELSE
            IF ((I$N >= 5) AND (V$POST_GROUP = 1310)) THEN
            BEGIN
                SELECT X03, X04, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27,
                     :V28, :V29, :V30;
                V$V = V$POST_NAME;
            END
            ELSE
            IF ((I$N = 6) AND (V$POST_GROUP = 1323)) THEN
            BEGIN
                SELECT X03, X04, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27,
                     :V28, :V29, :V30;
                V$V = V$POST_NAME;
            END
        END
    END

    /* FREE POSTS */

    IF (I$N IN (1, 2, 5, 6)) THEN
    BEGIN
        V04 = 0;

        /* STAVKI UCHITEL - OTDELNO */
        IF (I$N = 1) THEN
        BEGIN
            SELECT SUM(V.VAL)
            FROM LINKS L2
            INNER JOIN VALF V ON (V.OBJ_ID = L2.OBJ_ID)
            INNER JOIN VALL V10 ON (V10.OBJ_ID = L2.OBJ_ID)
            WHERE L2.DATE_DEL IS NULL
              AND L2.OBJ_TYPE_ID = 2
              AND V10.PARAM_ID = 10
              AND V10.IS_DEL = 0
              AND V10.LISTVAL_ID IN (968, 973)
              AND V.PARAM_ID = 1342
              AND V.IS_DEL = 0
              AND L2.PARENT_ID = :I$OBJ_ID
            INTO :V04;
        END

        FOR SELECT L13.OBJ_ID, V63.LISTVAL_ID, V64.LISTVAL_ID, V58.LISTVAL_ID, V62.VAL, LV.TAG
            FROM LINKS L2
            INNER JOIN LINKS L13 ON (L13.PARENT_ID = L2.OBJ_ID)
            INNER JOIN VALL V10 ON V10.OBJ_ID = L2.OBJ_ID
            INNER JOIN VALL V63 ON V63.OBJ_ID = L13.OBJ_ID
            INNER JOIN VALL V64 ON V64.OBJ_ID = L13.OBJ_ID
            INNER JOIN VALL V58 ON V58.OBJ_ID = L13.OBJ_ID
            INNER JOIN VALF V62 ON V62.OBJ_ID = L13.OBJ_ID
            INNER JOIN LISTVALS LV ON LV.LISTVAL_ID = V58.LISTVAL_ID
            WHERE L2.DATE_DEL IS NULL
              AND L2.OBJ_TYPE_ID = 2
              AND L2.PARENT_ID = :I$OBJ_ID
              AND V10.PARAM_ID = 10
              AND V10.IS_DEL = 0
              AND V10.LISTVAL_ID IN (968, 973)
              AND L13.OBJ_TYPE_ID = 13
              AND L13.DATE_DEL IS NULL
              AND V63.PARAM_ID = 63
              AND V63.IS_DEL = 0
              AND V64.PARAM_ID = 64
              AND V64.IS_DEL = 0
              AND V58.PARAM_ID = 58
              AND V58.IS_DEL = 0
              AND V62.PARAM_ID = 62
              AND V62.IS_DEL = 0
              AND V58.LISTVAL_ID <> 1267
              AND V58.LISTVAL_ID <> 1284
              AND V58.LISTVAL_ID <> 1298
            INTO :V$POST_ID, :V$POST_GROUP, :V$POST_PODGROUP, :V$POST_FUNC, :V$STAVOK, :V$TAG
        DO
        BEGIN
            V$Y = 0;
            /* STAVKI UCHITEL - OTDELNO */
            IF (V$TAG = 'U') THEN
            BEGIN
                V$STAVOK = 0;
            END

            IF (I$N = 1) THEN
            BEGIN
                SELECT Z
                FROM RIK83_STAVOK(:V$POST_ID)
                INTO :V$Y;
                V04 = V04 + V$STAVOK - V$Y;
            END
            ELSE
            IF ((I$N = 2) AND (V$POST_GROUP = 55)) THEN
            BEGIN
                SELECT Z
                FROM RIK83_STAVOK(:V$POST_ID)
                INTO :V$Y;
                V04 = V04 + V$STAVOK - V$Y;
            END

            ELSE
            IF ((I$N = 5) AND (V$POST_GROUP = 1310)) THEN
            BEGIN
                SELECT Z
                FROM RIK83_STAVOK(:V$POST_ID)
                INTO :V$Y;
                V04 = V04 + V$STAVOK - V$Y;
            END
            ELSE
            IF ((I$N = 6) AND (V$POST_GROUP = 1323)) THEN
            BEGIN
                SELECT Z
                FROM RIK83_STAVOK(:V$POST_ID)
                INTO :V$Y;
                V04 = V04 + V$STAVOK - V$Y;
            END

        END

    END
    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE RIK83_DISTR1_6 (
    I$OBJ_ID BIGINT,
    I$N INTEGER)
RETURNS (
    V03 INTEGER,
    V04 NUMERIC(11,2),
    V05 INTEGER,
    V06 INTEGER,
    V07 INTEGER,
    V08 INTEGER,
    V09 INTEGER,
    V10 INTEGER,
    V11 INTEGER,
    V12 INTEGER,
    V13 INTEGER,
    V14 INTEGER,
    V15 INTEGER,
    V16 INTEGER,
    V17 INTEGER,
    V18 INTEGER,
    V19 INTEGER,
    V20 INTEGER,
    V21 INTEGER,
    V22 INTEGER,
    V23 INTEGER,
    V24 INTEGER,
    V25 INTEGER,
    V26 INTEGER,
    V27 INTEGER,
    V28 INTEGER,
    V29 INTEGER,
    V30 INTEGER)
AS
DECLARE VARIABLE V$POST_ID BIGINT;
DECLARE VARIABLE V$POST_GROUP BIGINT;
DECLARE VARIABLE V$POST_PODGROUP BIGINT;
DECLARE VARIABLE V$POST_FUNC BIGINT;
DECLARE VARIABLE V$STAVOK NUMERIC(11,2);
DECLARE VARIABLE V$Y NUMERIC(11,2);
DECLARE VARIABLE V$POST_NAME VARCHAR(4000);
DECLARE VARIABLE V$V VARCHAR(4000);
DECLARE VARIABLE V$WORKER_ID BIGINT;
DECLARE VARIABLE V$OU_TYPE BIGINT;--declare variable V$CORRECT_CLASS integer;
DECLARE VARIABLE V$TAG VARCHAR(100);
BEGIN
    V03 = 0;

    V05 = 0;
    V06 = 0;
    V07 = 0;
    V08 = 0;
    V09 = 0;
    V10 = 0;
    V11 = 0;
    V12 = 0;
    V13 = 0;
    V14 = 0;
    V15 = 0;
    V16 = 0;
    V17 = 0;
    V18 = 0;
    V19 = 0;
    V20 = 0;
    V21 = 0;
    V22 = 0;
    V23 = 0;
    V24 = 0;
    V25 = 0;
    V26 = 0;
    V27 = 0;
    V28 = 0;
    V29 = 0;
    V30 = 0;

    FOR SELECT L14.OBJ_ID, V69.VAL, V63.LISTVAL_ID, V64.LISTVAL_ID, V58.LISTVAL_ID, V66.VAL, V11.LISTVAL_ID
        FROM LINKS L2
        INNER JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID
        INNER JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID
        INNER JOIN VALL V11 ON V11.OBJ_ID = L14.PARENT_ID
        INNER JOIN VALL V10 ON V10.OBJ_ID = L2.OBJ_ID
        INNER JOIN VALL V72 ON V72.OBJ_ID = L15.OBJ_ID
        INNER JOIN VALR V69 ON V69.OBJ_ID = L15.OBJ_ID
        INNER JOIN VALL V63 ON V63.OBJ_ID = V69.VAL
        INNER JOIN VALL V64 ON V64.OBJ_ID = V69.VAL
        INNER JOIN VALL V58 ON V58.OBJ_ID = V69.VAL
        INNER JOIN VALS V66 ON V66.OBJ_ID = V69.VAL
        LEFT JOIN VALD V74 ON V74.PARAM_ID = 74 AND V74.OBJ_ID = L15.OBJ_ID AND V74.IS_DEL = 0
        LEFT JOIN VALL V274 ON V274.PARAM_ID = 274 AND V274.OBJ_ID = L14.OBJ_ID AND V274.IS_DEL = 0
        WHERE L2.DATE_DEL IS NULL
          AND L2.OBJ_TYPE_ID = 2
          AND L2.PARENT_ID = :I$OBJ_ID
          AND L14.OBJ_TYPE_ID = 14
          AND L14.DATE_DEL IS NULL
          AND L15.OBJ_TYPE_ID = 15
          AND L15.DATE_DEL IS NULL
          AND V72.PARAM_ID = 72
          AND V72.IS_DEL = 0
          AND V72.LISTVAL_ID = 934
          AND V69.PARAM_ID = 69
          AND V69.IS_DEL = 0
          AND V63.PARAM_ID = 63
          AND V63.IS_DEL = 0
          AND V64.PARAM_ID = 64
          AND V64.IS_DEL = 0
          AND V58.PARAM_ID = 58
          AND V58.IS_DEL = 0
          AND V66.PARAM_ID = 66
          AND V66.IS_DEL = 0
          AND V74.VAL IS NULL
          AND V11.PARAM_ID = 11
          AND V11.IS_DEL = 0
          AND V10.PARAM_ID = 10
          AND V10.IS_DEL = 0
          AND V10.LISTVAL_ID = 974
          AND ((V274.LISTVAL_ID IS NULL) OR (V274.LISTVAL_ID = 602) OR (V274.LISTVAL_ID = 604))
        INTO :V$WORKER_ID, :V$POST_ID, :V$POST_GROUP, :V$POST_PODGROUP, :V$POST_FUNC, :V$POST_NAME, :V$OU_TYPE
    DO
    BEGIN
        IF ((I$N >= 1) AND (I$N <= 6) AND (V$POST_FUNC <> 1267) AND (V$POST_FUNC <> 1284) AND (V$POST_FUNC <> 1298)) THEN
        BEGIN
            IF (I$N = 1) THEN
            BEGIN
                SELECT X03, X04, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27,
                     :V28, :V29, :V30;
                V$V = V$POST_NAME;
            END
            ELSE
            IF ((I$N = 2) AND (V$POST_GROUP = 55)) THEN
            BEGIN
                SELECT X03, X04, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27,
                     :V28, :V29, :V30;
                V$V = V$POST_NAME;
            END
            ELSE
            IF (((I$N >= 3) OR (I$N <= 4)) AND (V$POST_GROUP = 97)) THEN
            BEGIN
                IF (I$N = 3) THEN
                BEGIN
                    SELECT X03, X04, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                    FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                    INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26,
                         :V27, :V28, :V29, :V30;
                    V$V = V$POST_NAME;
                END
                ELSE
                IF (V$POST_PODGROUP = 98) THEN
                BEGIN
                    IF ((I$N = 4) AND (V$OU_TYPE = 978)) THEN
                    BEGIN
                        SELECT X03, NULL, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29,
                               X30
                        FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                        INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25,
                             :V26, :V27, :V28, :V29, :V30;
                        V$V = V$POST_NAME;
                    END
                END
            END

            ELSE
            IF ((I$N >= 5) AND (V$POST_GROUP = 1310)) THEN
            BEGIN
                SELECT X03, X04, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27,
                     :V28, :V29, :V30;
                V$V = V$POST_NAME;
            END
            ELSE
            IF ((I$N = 6) AND (V$POST_GROUP = 1323)) THEN
            BEGIN
                SELECT X03, X04, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27,
                     :V28, :V29, :V30;
                V$V = V$POST_NAME;
            END
        END
    END

    /* FREE POSTS */

    IF (I$N IN (1, 2, 5, 6)) THEN
    BEGIN
        V04 = 0;

        /* STAVKI UCHITEL - OTDELNO */
        IF (I$N = 1) THEN
        BEGIN
            SELECT SUM(V.VAL)
            FROM LINKS L2
            INNER JOIN VALF V ON (V.OBJ_ID = L2.OBJ_ID)
            INNER JOIN VALL V10 ON (V10.OBJ_ID = L2.OBJ_ID)
            WHERE L2.DATE_DEL IS NULL
              AND L2.OBJ_TYPE_ID = 2
              AND V10.PARAM_ID = 10
              AND V10.IS_DEL = 0
              AND V10.LISTVAL_ID = 974
              AND V.PARAM_ID = 1342
              AND V.IS_DEL = 0
              AND L2.PARENT_ID = :I$OBJ_ID
            INTO :V04;
        END

        FOR SELECT L13.OBJ_ID, V63.LISTVAL_ID, V64.LISTVAL_ID, V58.LISTVAL_ID, V62.VAL, LV.TAG
            FROM LINKS L2
            INNER JOIN LINKS L13 ON (L13.PARENT_ID = L2.OBJ_ID)
            INNER JOIN VALL V10 ON V10.OBJ_ID = L2.OBJ_ID
            INNER JOIN VALL V63 ON V63.OBJ_ID = L13.OBJ_ID
            INNER JOIN VALL V64 ON V64.OBJ_ID = L13.OBJ_ID
            INNER JOIN VALL V58 ON V58.OBJ_ID = L13.OBJ_ID
            INNER JOIN VALF V62 ON V62.OBJ_ID = L13.OBJ_ID
            INNER JOIN LISTVALS LV ON LV.LISTVAL_ID = V58.LISTVAL_ID
            WHERE L2.DATE_DEL IS NULL
              AND L2.OBJ_TYPE_ID = 2
              AND L2.PARENT_ID = :I$OBJ_ID
              AND V10.PARAM_ID = 10
              AND V10.IS_DEL = 0
              AND V10.LISTVAL_ID = 974
              AND L13.OBJ_TYPE_ID = 13
              AND L13.DATE_DEL IS NULL
              AND V63.PARAM_ID = 63
              AND V63.IS_DEL = 0
              AND V64.PARAM_ID = 64
              AND V64.IS_DEL = 0
              AND V58.PARAM_ID = 58
              AND V58.IS_DEL = 0
              AND V62.PARAM_ID = 62
              AND V62.IS_DEL = 0
              AND V58.LISTVAL_ID <> 1267
              AND V58.LISTVAL_ID <> 1284
              AND V58.LISTVAL_ID <> 1298
            INTO :V$POST_ID, :V$POST_GROUP, :V$POST_PODGROUP, :V$POST_FUNC, :V$STAVOK, :V$TAG
        DO
        BEGIN
            V$Y = 0;
            /* STAVKI UCHITEL - OTDELNO */
            IF (V$TAG = 'U') THEN
            BEGIN
                V$STAVOK = 0;
            END

            IF (I$N = 1) THEN
            BEGIN
                SELECT Z
                FROM RIK83_STAVOK(:V$POST_ID)
                INTO :V$Y;
                V04 = V04 + V$STAVOK - V$Y;
            END
            ELSE
            IF ((I$N = 2) AND (V$POST_GROUP = 55)) THEN
            BEGIN
                SELECT Z
                FROM RIK83_STAVOK(:V$POST_ID)
                INTO :V$Y;
                V04 = V04 + V$STAVOK - V$Y;
            END

            ELSE
            IF ((I$N = 5) AND (V$POST_GROUP = 1310)) THEN
            BEGIN
                SELECT Z
                FROM RIK83_STAVOK(:V$POST_ID)
                INTO :V$Y;
                V04 = V04 + V$STAVOK - V$Y;
            END
            ELSE
            IF ((I$N = 6) AND (V$POST_GROUP = 1323)) THEN
            BEGIN
                SELECT Z
                FROM RIK83_STAVOK(:V$POST_ID)
                INTO :V$Y;
                V04 = V04 + V$STAVOK - V$Y;
            END

        END

    END
    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE RIK83_DISTR1_7 (
    I$OBJ_ID BIGINT,
    I$N INTEGER)
RETURNS (
    V03 INTEGER,
    V04 NUMERIC(11,2),
    V05 INTEGER,
    V06 INTEGER,
    V07 INTEGER,
    V08 INTEGER,
    V09 INTEGER,
    V10 INTEGER,
    V11 INTEGER,
    V12 INTEGER,
    V13 INTEGER,
    V14 INTEGER,
    V15 INTEGER,
    V16 INTEGER,
    V17 INTEGER,
    V18 INTEGER,
    V19 INTEGER,
    V20 INTEGER,
    V21 INTEGER,
    V22 INTEGER,
    V23 INTEGER,
    V24 INTEGER,
    V25 INTEGER,
    V26 INTEGER,
    V27 INTEGER,
    V28 INTEGER,
    V29 INTEGER,
    V30 INTEGER)
AS
DECLARE VARIABLE V$POST_ID BIGINT;
DECLARE VARIABLE V$POST_GROUP BIGINT;
DECLARE VARIABLE V$POST_PODGROUP BIGINT;
DECLARE VARIABLE V$POST_FUNC BIGINT;
DECLARE VARIABLE V$STAVOK NUMERIC(11,2);
DECLARE VARIABLE V$Y NUMERIC(11,2);
DECLARE VARIABLE V$POST_NAME VARCHAR(4000);
DECLARE VARIABLE V$V VARCHAR(4000);
DECLARE VARIABLE V$WORKER_ID BIGINT;
DECLARE VARIABLE V$OU_TYPE BIGINT;
DECLARE VARIABLE V$CORRECT_CLASS INTEGER;
DECLARE VARIABLE V$TAG VARCHAR(100);
BEGIN
    V03 = 0;

    V05 = 0;
    V06 = 0;
    V07 = 0;
    V08 = 0;
    V09 = 0;
    V10 = 0;
    V11 = 0;
    V12 = 0;
    V13 = 0;
    V14 = 0;
    V15 = 0;
    V16 = 0;
    V17 = 0;
    V18 = 0;
    V19 = 0;
    V20 = 0;
    V21 = 0;
    V22 = 0;
    V23 = 0;
    V24 = 0;
    V25 = 0;
    V26 = 0;
    V27 = 0;
    V28 = 0;
    V29 = 0;
    V30 = 0;

    FOR SELECT L14.OBJ_ID, V69.VAL, V63.LISTVAL_ID, V64.LISTVAL_ID, V58.LISTVAL_ID, V66.VAL, V11.LISTVAL_ID
        FROM LINKS L2
        INNER JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID
        INNER JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID
        INNER JOIN VALL V11 ON V11.OBJ_ID = L14.PARENT_ID
        INNER JOIN VALL V72 ON V72.OBJ_ID = L15.OBJ_ID
        INNER JOIN VALR V69 ON V69.OBJ_ID = L15.OBJ_ID
        INNER JOIN VALL V63 ON V63.OBJ_ID = V69.VAL
        INNER JOIN VALL V64 ON V64.OBJ_ID = V69.VAL
        INNER JOIN VALL V58 ON V58.OBJ_ID = V69.VAL
        INNER JOIN VALS V66 ON V66.OBJ_ID = V69.VAL
        LEFT JOIN VALD V74 ON V74.PARAM_ID = 74 AND V74.OBJ_ID = L15.OBJ_ID AND V74.IS_DEL = 0
        LEFT JOIN VALL V274 ON V274.PARAM_ID = 274 AND V274.OBJ_ID = L14.OBJ_ID AND V274.IS_DEL = 0
        WHERE L2.DATE_DEL IS NULL
          AND L2.OBJ_TYPE_ID = 2
          AND L2.PARENT_ID = :I$OBJ_ID
          AND L14.OBJ_TYPE_ID = 14
          AND L14.DATE_DEL IS NULL
          AND L15.OBJ_TYPE_ID = 15
          AND L15.DATE_DEL IS NULL
          AND V72.PARAM_ID = 72
          AND V72.IS_DEL = 0
          AND V72.LISTVAL_ID = 934
          AND V69.PARAM_ID = 69
          AND V69.IS_DEL = 0
          AND V63.PARAM_ID = 63
          AND V63.IS_DEL = 0
          AND V64.PARAM_ID = 64
          AND V64.IS_DEL = 0
          AND V58.PARAM_ID = 58
          AND V58.IS_DEL = 0
          AND V66.PARAM_ID = 66
          AND V66.IS_DEL = 0
          AND V74.VAL IS NULL
          AND V11.PARAM_ID = 11
          AND V11.IS_DEL = 0
          AND V11.LISTVAL_ID = 978
          AND ((V274.LISTVAL_ID IS NULL) OR (V274.LISTVAL_ID = 602) OR (V274.LISTVAL_ID = 604))
        INTO :V$WORKER_ID, :V$POST_ID, :V$POST_GROUP, :V$POST_PODGROUP, :V$POST_FUNC, :V$POST_NAME, :V$OU_TYPE
    DO
    BEGIN
        IF ((I$N >= 1) AND (I$N <= 7) AND (V$POST_FUNC <> 1267) AND (V$POST_FUNC <> 1284) AND (V$POST_FUNC <> 1298)) THEN
        BEGIN
            IF (I$N = 1) THEN
            BEGIN
                SELECT X03, X04, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27,
                     :V28, :V29, :V30;
                V$V = V$POST_NAME;
            END
            ELSE
            IF ((I$N = 2) AND (V$POST_GROUP = 55)) THEN
            BEGIN
                SELECT X03, X04, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27,
                     :V28, :V29, :V30;
                V$V = V$POST_NAME;
            END
            ELSE
            IF (((I$N >= 3) OR (I$N <= 4)) AND (V$POST_GROUP = 97)) THEN
            BEGIN
                IF (I$N = 3) THEN
                BEGIN
                    SELECT X03, X04, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                    FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                    INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26,
                         :V27, :V28, :V29, :V30;
                    V$V = V$POST_NAME;
                END
                ELSE
                IF (V$POST_PODGROUP = 98) THEN
                BEGIN
                    IF (I$N = 4) THEN
                    BEGIN
                        SELECT X03, NULL, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29,
                               X30
                        FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                        INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25,
                             :V26, :V27, :V28, :V29, :V30;
                        V$V = V$POST_NAME;
                    END
                END
            END
            ELSE
            IF ((I$N >= 5) AND (I$N <= 6) AND (V$POST_GROUP = 1310)) THEN
            BEGIN
                IF (I$N = 5) THEN
                BEGIN
                    SELECT X03, X04, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                    FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                    INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26,
                         :V27, :V28, :V29, :V30;
                    V$V = V$POST_NAME;
                END
            END
            ELSE
            IF ((I$N = 7) AND (V$POST_GROUP = 1323)) THEN
            BEGIN
                SELECT X03, X04, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27,
                     :V28, :V29, :V30;
                V$V = V$POST_NAME;
            END
        END
        ELSE
        IF ((I$N = 8) AND ((V$POST_FUNC = 1267) OR (V$POST_FUNC = 1284) OR (V$POST_FUNC = 1298))) THEN
        BEGIN
            SELECT X03
            FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03)
            INTO :V03;
            V$V = V$POST_NAME;
        END
        ELSE
        IF ((I$N = 9) AND (V$POST_FUNC = 1267)) THEN
        BEGIN
            SELECT X03
            FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03)
            INTO :V03;
            V$V = V$POST_NAME;
        END
        ELSE
        IF ((I$N = 10) AND ((V$POST_FUNC = 1284) OR (V$POST_FUNC = 1298))) THEN
        BEGIN
            SELECT X03
            FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03)
            INTO :V03;
            V$V = V$POST_NAME;
        END

    END

    /* FREE POSTS */

    IF (I$N IN (1, 2, 5, 7)) THEN
    BEGIN
        V04 = 0;

        /* STAVKI UCHITEL - OTDELNO */
        IF (I$N = 1) THEN
        BEGIN
            SELECT SUM(V.VAL)
            FROM LINKS L2
            INNER JOIN VALF V ON (V.OBJ_ID = L2.OBJ_ID)
            INNER JOIN VALL V11 ON (V11.OBJ_ID = L2.OBJ_ID)
            WHERE L2.DATE_DEL IS NULL
              AND L2.OBJ_TYPE_ID = 2
              AND V11.PARAM_ID = 11
              AND V11.IS_DEL = 0
              AND V11.LISTVAL_ID = 978
              AND V.PARAM_ID = 1342
              AND V.IS_DEL = 0
              AND L2.PARENT_ID = :I$OBJ_ID
            INTO :V04;
        END

        FOR SELECT L13.OBJ_ID, V63.LISTVAL_ID, V64.LISTVAL_ID, V58.LISTVAL_ID, V62.VAL, LV.TAG
            FROM LINKS L2
            INNER JOIN LINKS L13 ON (L13.PARENT_ID = L2.OBJ_ID)
            INNER JOIN VALL V11 ON V11.OBJ_ID = L2.OBJ_ID
            INNER JOIN VALL V63 ON V63.OBJ_ID = L13.OBJ_ID
            INNER JOIN VALL V64 ON V64.OBJ_ID = L13.OBJ_ID
            INNER JOIN VALL V58 ON V58.OBJ_ID = L13.OBJ_ID
            INNER JOIN VALF V62 ON V62.OBJ_ID = L13.OBJ_ID
            INNER JOIN LISTVALS LV ON LV.LISTVAL_ID = V58.LISTVAL_ID
            WHERE L2.DATE_DEL IS NULL
              AND L2.OBJ_TYPE_ID = 2
              AND L2.PARENT_ID = :I$OBJ_ID
              AND V11.PARAM_ID = 11
              AND V11.IS_DEL = 0
              AND V11.LISTVAL_ID = 978
              AND L13.OBJ_TYPE_ID = 13
              AND L13.DATE_DEL IS NULL
              AND V63.PARAM_ID = 63
              AND V63.IS_DEL = 0
              AND V64.PARAM_ID = 64
              AND V64.IS_DEL = 0
              AND V58.PARAM_ID = 58
              AND V58.IS_DEL = 0
              AND V62.PARAM_ID = 62
              AND V62.IS_DEL = 0
              AND V58.LISTVAL_ID <> 1267
              AND V58.LISTVAL_ID <> 1284
              AND V58.LISTVAL_ID <> 1298
            INTO :V$POST_ID, :V$POST_GROUP, :V$POST_PODGROUP, :V$POST_FUNC, :V$STAVOK, :V$TAG
        DO
        BEGIN
            V$Y = 0;
            /* STAVKI UCHITEL - OTDELNO */
            IF (V$TAG = 'U') THEN
            BEGIN
                V$STAVOK = 0;
            END

            IF (I$N = 1) THEN
            BEGIN
                SELECT Z
                FROM RIK83_STAVOK(:V$POST_ID)
                INTO :V$Y;
                V04 = V04 + V$STAVOK - V$Y;
            END
            ELSE
            IF ((I$N = 2) AND (V$POST_GROUP = 55)) THEN
            BEGIN
                SELECT Z
                FROM RIK83_STAVOK(:V$POST_ID)
                INTO :V$Y;
                V04 = V04 + V$STAVOK - V$Y;
            END

            ELSE
            IF ((I$N = 5) AND (V$POST_GROUP = 1310)) THEN
            BEGIN
                SELECT Z
                FROM RIK83_STAVOK(:V$POST_ID)
                INTO :V$Y;
                V04 = V04 + V$STAVOK - V$Y;
            END
            ELSE
            IF ((I$N = 7) AND (V$POST_GROUP = 1323)) THEN
            BEGIN
                SELECT Z
                FROM RIK83_STAVOK(:V$POST_ID)
                INTO :V$Y;
                V04 = V04 + V$STAVOK - V$Y;
            END

        END

    END
    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE RIK83_DISTR1_8 (
    I$OBJ_ID BIGINT,
    I$N INTEGER)
RETURNS (
    V03 INTEGER,
    V04 NUMERIC(11,2),
    V05 INTEGER,
    V06 INTEGER,
    V07 INTEGER,
    V08 INTEGER,
    V09 INTEGER,
    V10 INTEGER,
    V11 INTEGER,
    V12 INTEGER,
    V13 INTEGER,
    V14 INTEGER,
    V15 INTEGER,
    V16 INTEGER,
    V17 INTEGER,
    V18 INTEGER,
    V19 INTEGER,
    V20 INTEGER,
    V21 INTEGER,
    V22 INTEGER,
    V23 INTEGER,
    V24 INTEGER,
    V25 INTEGER,
    V26 INTEGER,
    V27 INTEGER,
    V28 INTEGER,
    V29 INTEGER,
    V30 INTEGER)
AS
DECLARE VARIABLE V$POST_ID BIGINT;
DECLARE VARIABLE V$POST_GROUP BIGINT;
DECLARE VARIABLE V$POST_PODGROUP BIGINT;
DECLARE VARIABLE V$POST_FUNC BIGINT;
DECLARE VARIABLE V$STAVOK NUMERIC(11,2);
DECLARE VARIABLE V$Y NUMERIC(11,2);
DECLARE VARIABLE V$POST_NAME VARCHAR(4000);
DECLARE VARIABLE V$V VARCHAR(4000);
DECLARE VARIABLE V$WORKER_ID BIGINT;
DECLARE VARIABLE V$OU_TYPE BIGINT; --declare variable V$CORRECT_CLASS integer;
DECLARE VARIABLE V$TAG VARCHAR(100);
BEGIN
    V03 = 0;

    V05 = 0;
    V06 = 0;
    V07 = 0;
    V08 = 0;
    V09 = 0;
    V10 = 0;
    V11 = 0;
    V12 = 0;
    V13 = 0;
    V14 = 0;
    V15 = 0;
    V16 = 0;
    V17 = 0;
    V18 = 0;
    V19 = 0;
    V20 = 0;
    V21 = 0;
    V22 = 0;
    V23 = 0;
    V24 = 0;
    V25 = 0;
    V26 = 0;
    V27 = 0;
    V28 = 0;
    V29 = 0;
    V30 = 0;

    FOR SELECT L14.OBJ_ID, V69.VAL, V63.LISTVAL_ID, V64.LISTVAL_ID, V58.LISTVAL_ID, V66.VAL, V11.LISTVAL_ID
        FROM LINKS L2
        INNER JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID
        INNER JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID
        INNER JOIN VALL V11 ON V11.OBJ_ID = L14.PARENT_ID
        INNER JOIN VALL V72 ON V72.OBJ_ID = L15.OBJ_ID
        INNER JOIN VALR V69 ON V69.OBJ_ID = L15.OBJ_ID
        INNER JOIN VALL V63 ON V63.OBJ_ID = V69.VAL
        INNER JOIN VALL V64 ON V64.OBJ_ID = V69.VAL
        INNER JOIN VALL V58 ON V58.OBJ_ID = V69.VAL
        INNER JOIN VALS V66 ON V66.OBJ_ID = V69.VAL
        LEFT JOIN VALD V74 ON V74.PARAM_ID = 74 AND V74.OBJ_ID = L15.OBJ_ID AND V74.IS_DEL = 0
        LEFT JOIN VALL V274 ON V274.PARAM_ID = 274 AND V274.OBJ_ID = L14.OBJ_ID AND V274.IS_DEL = 0
        WHERE L2.DATE_DEL IS NULL
          AND L2.OBJ_TYPE_ID = 2
          AND L2.PARENT_ID = :I$OBJ_ID
          AND L14.OBJ_TYPE_ID = 14
          AND L14.DATE_DEL IS NULL
          AND L15.OBJ_TYPE_ID = 15
          AND L15.DATE_DEL IS NULL
          AND V72.PARAM_ID = 72
          AND V72.IS_DEL = 0
          AND V72.LISTVAL_ID = 934
          AND V69.PARAM_ID = 69
          AND V69.IS_DEL = 0
          AND V63.PARAM_ID = 63
          AND V63.IS_DEL = 0
          AND V64.PARAM_ID = 64
          AND V64.IS_DEL = 0
          AND V58.PARAM_ID = 58
          AND V58.IS_DEL = 0
          AND V66.PARAM_ID = 66
          AND V66.IS_DEL = 0
          AND V74.VAL IS NULL
          AND V11.PARAM_ID = 11
          AND V11.IS_DEL = 0
          AND V11.LISTVAL_ID = 2221
          AND ((V274.LISTVAL_ID IS NULL) OR (V274.LISTVAL_ID = 602) OR (V274.LISTVAL_ID = 604))
        INTO :V$WORKER_ID, :V$POST_ID, :V$POST_GROUP, :V$POST_PODGROUP, :V$POST_FUNC, :V$POST_NAME, :V$OU_TYPE
    DO
    BEGIN
        IF ((I$N >= 1) AND (I$N <= 6) AND (V$POST_FUNC <> 1267) AND (V$POST_FUNC <> 1284) AND (V$POST_FUNC <> 1298)) THEN
        BEGIN
            IF (I$N = 1) THEN
            BEGIN
                SELECT X03, X04, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27,
                     :V28, :V29, :V30;
                V$V = V$POST_NAME;
            END
            ELSE
            IF ((I$N = 2) AND (V$POST_GROUP = 55)) THEN
            BEGIN
                SELECT X03, X04, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27,
                     :V28, :V29, :V30;
                V$V = V$POST_NAME;
            END
            ELSE
            IF (((I$N >= 3) OR (I$N <= 4)) AND (V$POST_GROUP = 97)) THEN
            BEGIN
                IF (I$N = 3) THEN
                BEGIN
                    SELECT X03, X04, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                    FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                    INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26,
                         :V27, :V28, :V29, :V30;
                    V$V = V$POST_NAME;
                END
                ELSE
                IF (V$POST_PODGROUP = 98) THEN
                BEGIN
                    IF ((I$N = 4) AND (V$OU_TYPE = 978)) THEN
                    BEGIN
                        SELECT X03, NULL, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29,
                               X30
                        FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                        INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25,
                             :V26, :V27, :V28, :V29, :V30;
                        V$V = V$POST_NAME;
                    END
                END
            END

            ELSE
            IF ((I$N >= 5) AND (V$POST_GROUP = 1310)) THEN
            BEGIN
                SELECT X03, X04, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27,
                     :V28, :V29, :V30;
                V$V = V$POST_NAME;
            END
            ELSE
            IF ((I$N = 6) AND (V$POST_GROUP = 1323)) THEN
            BEGIN
                SELECT X03, X04, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27,
                     :V28, :V29, :V30;
                V$V = V$POST_NAME;
            END
        END
    END

    /* FREE POSTS */

    IF (I$N IN (1, 2, 5, 6)) THEN
    BEGIN
        V04 = 0;

        /* STAVKI UCHITEL - OTDELNO */
        IF (I$N = 1) THEN
        BEGIN
            SELECT SUM(V.VAL)
            FROM LINKS L2
            INNER JOIN VALF V ON (V.OBJ_ID = L2.OBJ_ID)
            INNER JOIN VALL V11 ON (V11.OBJ_ID = L2.OBJ_ID)
            WHERE L2.DATE_DEL IS NULL
              AND L2.OBJ_TYPE_ID = 2
              AND V11.PARAM_ID = 11
              AND V11.IS_DEL = 0
              AND V11.LISTVAL_ID = 2221
              AND V.PARAM_ID = 1342
              AND V.IS_DEL = 0
              AND L2.PARENT_ID = :I$OBJ_ID
            INTO :V04;
        END

        FOR SELECT L13.OBJ_ID, V63.LISTVAL_ID, V64.LISTVAL_ID, V58.LISTVAL_ID, V62.VAL, LV.TAG
            FROM LINKS L2
            INNER JOIN LINKS L13 ON (L13.PARENT_ID = L2.OBJ_ID)
            INNER JOIN VALL V11 ON V11.OBJ_ID = L2.OBJ_ID
            INNER JOIN VALL V63 ON V63.OBJ_ID = L13.OBJ_ID
            INNER JOIN VALL V64 ON V64.OBJ_ID = L13.OBJ_ID
            INNER JOIN VALL V58 ON V58.OBJ_ID = L13.OBJ_ID
            INNER JOIN VALF V62 ON V62.OBJ_ID = L13.OBJ_ID
            INNER JOIN LISTVALS LV ON LV.LISTVAL_ID = V58.LISTVAL_ID
            WHERE L2.DATE_DEL IS NULL
              AND L2.OBJ_TYPE_ID = 2
              AND L2.PARENT_ID = :I$OBJ_ID
              AND V11.PARAM_ID = 11
              AND V11.IS_DEL = 0
              AND V11.LISTVAL_ID = 2221
              AND L13.OBJ_TYPE_ID = 13
              AND L13.DATE_DEL IS NULL
              AND V63.PARAM_ID = 63
              AND V63.IS_DEL = 0
              AND V64.PARAM_ID = 64
              AND V64.IS_DEL = 0
              AND V58.PARAM_ID = 58
              AND V58.IS_DEL = 0
              AND V62.PARAM_ID = 62
              AND V62.IS_DEL = 0
              AND V58.LISTVAL_ID <> 1267
              AND V58.LISTVAL_ID <> 1284
              AND V58.LISTVAL_ID <> 1298
            INTO :V$POST_ID, :V$POST_GROUP, :V$POST_PODGROUP, :V$POST_FUNC, :V$STAVOK, :V$TAG
        DO
        BEGIN
            V$Y = 0;
            /* STAVKI UCHITEL - OTDELNO */
            IF (V$TAG = 'U') THEN
            BEGIN
                V$STAVOK = 0;
            END

            IF (I$N = 1) THEN
            BEGIN
                SELECT Z
                FROM RIK83_STAVOK(:V$POST_ID)
                INTO :V$Y;
                V04 = V04 + V$STAVOK - V$Y;
            END
            ELSE
            IF ((I$N = 2) AND (V$POST_GROUP = 55)) THEN
            BEGIN
                SELECT Z
                FROM RIK83_STAVOK(:V$POST_ID)
                INTO :V$Y;
                V04 = V04 + V$STAVOK - V$Y;
            END

            ELSE
            IF ((I$N = 5) AND (V$POST_GROUP = 1310)) THEN
            BEGIN
                SELECT Z
                FROM RIK83_STAVOK(:V$POST_ID)
                INTO :V$Y;
                V04 = V04 + V$STAVOK - V$Y;
            END
            ELSE
            IF ((I$N = 6) AND (V$POST_GROUP = 1323)) THEN
            BEGIN
                SELECT Z
                FROM RIK83_STAVOK(:V$POST_ID)
                INTO :V$Y;
                V04 = V04 + V$STAVOK - V$Y;
            END

        END

    END
    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE RIK83_DISTR1_9 (
    I$OBJ_ID BIGINT,
    I$N INTEGER)
RETURNS (
    V03 INTEGER,
    V04 NUMERIC(11,2),
    V05 INTEGER,
    V06 INTEGER,
    V07 INTEGER,
    V08 INTEGER,
    V09 INTEGER,
    V10 INTEGER,
    V11 INTEGER,
    V12 INTEGER,
    V13 INTEGER,
    V14 INTEGER,
    V15 INTEGER,
    V16 INTEGER,
    V17 INTEGER,
    V18 INTEGER,
    V19 INTEGER,
    V20 INTEGER,
    V21 INTEGER,
    V22 INTEGER,
    V23 INTEGER,
    V24 INTEGER,
    V25 INTEGER,
    V26 INTEGER,
    V27 INTEGER,
    V28 INTEGER,
    V29 INTEGER,
    V30 INTEGER)
AS
DECLARE VARIABLE V$POST_ID BIGINT;
DECLARE VARIABLE V$POST_GROUP BIGINT;
DECLARE VARIABLE V$POST_PODGROUP BIGINT;
DECLARE VARIABLE V$POST_FUNC BIGINT;
DECLARE VARIABLE V$STAVOK NUMERIC(11,2);
DECLARE VARIABLE V$Y NUMERIC(11,2);
DECLARE VARIABLE V$POST_NAME VARCHAR(4000);
DECLARE VARIABLE V$V VARCHAR(4000);
DECLARE VARIABLE V$WORKER_ID BIGINT;
DECLARE VARIABLE V$OU_TYPE BIGINT;--declare variable V$CORRECT_CLASS integer;
DECLARE VARIABLE V$TAG VARCHAR(100);
BEGIN
    V03 = 0;

    V05 = 0;
    V06 = 0;
    V07 = 0;
    V08 = 0;
    V09 = 0;
    V10 = 0;
    V11 = 0;
    V12 = 0;
    V13 = 0;
    V14 = 0;
    V15 = 0;
    V16 = 0;
    V17 = 0;
    V18 = 0;
    V19 = 0;
    V20 = 0;
    V21 = 0;
    V22 = 0;
    V23 = 0;
    V24 = 0;
    V25 = 0;
    V26 = 0;
    V27 = 0;
    V28 = 0;
    V29 = 0;
    V30 = 0;

    FOR SELECT L14.OBJ_ID, V69.VAL, V63.LISTVAL_ID, V64.LISTVAL_ID, V58.LISTVAL_ID, V66.VAL, V11.LISTVAL_ID
        FROM LINKS L2
        INNER JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID
        INNER JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID
        INNER JOIN VALL V11 ON V11.OBJ_ID = L14.PARENT_ID
        INNER JOIN VALL V72 ON V72.OBJ_ID = L15.OBJ_ID
        INNER JOIN VALR V69 ON V69.OBJ_ID = L15.OBJ_ID
        INNER JOIN VALL V63 ON V63.OBJ_ID = V69.VAL
        INNER JOIN VALL V64 ON V64.OBJ_ID = V69.VAL
        INNER JOIN VALL V58 ON V58.OBJ_ID = V69.VAL
        INNER JOIN VALS V66 ON V66.OBJ_ID = V69.VAL
        LEFT JOIN VALD V74 ON V74.PARAM_ID = 74 AND V74.OBJ_ID = L15.OBJ_ID AND V74.IS_DEL = 0
        LEFT JOIN VALL V274 ON V274.PARAM_ID = 274 AND V274.OBJ_ID = L14.OBJ_ID AND V274.IS_DEL = 0
        WHERE L2.DATE_DEL IS NULL
          AND L2.OBJ_TYPE_ID = 2
          AND L2.PARENT_ID = :I$OBJ_ID
          AND L14.OBJ_TYPE_ID = 14
          AND L14.DATE_DEL IS NULL
          AND L15.OBJ_TYPE_ID = 15
          AND L15.DATE_DEL IS NULL
          AND V72.PARAM_ID = 72
          AND V72.IS_DEL = 0
          AND V72.LISTVAL_ID = 934
          AND V69.PARAM_ID = 69
          AND V69.IS_DEL = 0
          AND V63.PARAM_ID = 63
          AND V63.IS_DEL = 0
          AND V64.PARAM_ID = 64
          AND V64.IS_DEL = 0
          AND V58.PARAM_ID = 58
          AND V58.IS_DEL = 0
          AND V66.PARAM_ID = 66
          AND V66.IS_DEL = 0
          AND V74.VAL IS NULL
          AND V11.PARAM_ID = 11
          AND V11.IS_DEL = 0
          AND V11.LISTVAL_ID = 981
          AND ((V274.LISTVAL_ID IS NULL) OR (V274.LISTVAL_ID = 602) OR (V274.LISTVAL_ID = 604))
        INTO :V$WORKER_ID, :V$POST_ID, :V$POST_GROUP, :V$POST_PODGROUP, :V$POST_FUNC, :V$POST_NAME, :V$OU_TYPE
    DO
    BEGIN
        IF ((I$N >= 1) AND (I$N <= 6) AND (V$POST_FUNC <> 1267) AND (V$POST_FUNC <> 1284) AND (V$POST_FUNC <> 1298)) THEN
        BEGIN
            IF (I$N = 1) THEN
            BEGIN
                SELECT X03, X04, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27,
                     :V28, :V29, :V30;
                V$V = V$POST_NAME;
            END
            ELSE
            IF ((I$N = 2) AND (V$POST_GROUP = 55)) THEN
            BEGIN
                SELECT X03, X04, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27,
                     :V28, :V29, :V30;
                V$V = V$POST_NAME;
            END
            ELSE
            IF (((I$N >= 3) OR (I$N <= 4)) AND (V$POST_GROUP = 97)) THEN
            BEGIN
                IF (I$N = 3) THEN
                BEGIN
                    SELECT X03, X04, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                    FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                    INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26,
                         :V27, :V28, :V29, :V30;
                    V$V = V$POST_NAME;
                END
                ELSE
                IF (V$POST_PODGROUP = 98) THEN
                BEGIN
                    IF ((I$N = 4) AND (V$OU_TYPE = 978)) THEN
                    BEGIN
                        SELECT X03, NULL, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29,
                               X30
                        FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                        INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25,
                             :V26, :V27, :V28, :V29, :V30;
                        V$V = V$POST_NAME;
                    END
                END
            END

            ELSE
            IF ((I$N >= 5) AND (V$POST_GROUP = 1310)) THEN
            BEGIN
                SELECT X03, X04, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27,
                     :V28, :V29, :V30;
                V$V = V$POST_NAME;
            END
            ELSE
            IF ((I$N = 6) AND (V$POST_GROUP = 1323)) THEN
            BEGIN
                SELECT X03, X04, X05, X06, X07, X08, X09, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30
                FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30)
                INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20, :V21, :V22, :V23, :V24, :V25, :V26, :V27,
                     :V28, :V29, :V30;
                V$V = V$POST_NAME;
            END
        END
        ELSE
        IF ((I$N = 8) AND ((V$POST_FUNC = 1267) OR (V$POST_FUNC = 1284) OR (V$POST_FUNC = 1298))) THEN
        BEGIN
            SELECT X03
            FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03)
            INTO :V03;
            V$V = V$POST_NAME;
        END
        ELSE
        IF ((I$N = 9) AND (V$POST_FUNC = 1267)) THEN
        BEGIN
            SELECT X03
            FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03)
            INTO :V03;
            V$V = V$POST_NAME;
        END
        ELSE
        IF ((I$N = 10) AND ((V$POST_FUNC = 1284) OR (V$POST_FUNC = 1298))) THEN
        BEGIN
            SELECT X03
            FROM RIK83_INFO(:V$POST_ID, :V$WORKER_ID, :V03)
            INTO :V03;
            V$V = V$POST_NAME;
        END

    END

    /* FREE POSTS */

    IF (I$N IN (1, 2, 5, 6)) THEN
    BEGIN
        V04 = 0;

        /* STAVKI UCHITEL - OTDELNO */
        IF (I$N = 1) THEN
        BEGIN
            SELECT SUM(V.VAL)
            FROM LINKS L2
            INNER JOIN VALF V ON (V.OBJ_ID = L2.OBJ_ID)
            INNER JOIN VALL V11 ON (V11.OBJ_ID = L2.OBJ_ID)
            WHERE L2.DATE_DEL IS NULL
              AND L2.OBJ_TYPE_ID = 2
              AND V11.PARAM_ID = 11
              AND V11.IS_DEL = 0
              AND V11.LISTVAL_ID = 981
              AND V.PARAM_ID = 1342
              AND V.IS_DEL = 0
              AND L2.PARENT_ID = :I$OBJ_ID
            INTO :V04;
        END

        FOR SELECT L13.OBJ_ID, V63.LISTVAL_ID, V64.LISTVAL_ID, V58.LISTVAL_ID, V62.VAL, LV.TAG
            FROM LINKS L2
            INNER JOIN LINKS L13 ON (L13.PARENT_ID = L2.OBJ_ID)
            INNER JOIN VALL V11 ON V11.OBJ_ID = L2.OBJ_ID
            INNER JOIN VALL V63 ON V63.OBJ_ID = L13.OBJ_ID
            INNER JOIN VALL V64 ON V64.OBJ_ID = L13.OBJ_ID
            INNER JOIN VALL V58 ON V58.OBJ_ID = L13.OBJ_ID
            INNER JOIN VALF V62 ON V62.OBJ_ID = L13.OBJ_ID
            INNER JOIN LISTVALS LV ON LV.LISTVAL_ID = V58.LISTVAL_ID
            WHERE L2.DATE_DEL IS NULL
              AND L2.OBJ_TYPE_ID = 2
              AND L2.PARENT_ID = :I$OBJ_ID
              AND V11.PARAM_ID = 11
              AND V11.IS_DEL = 0
              AND V11.LISTVAL_ID = 981
              AND L13.OBJ_TYPE_ID = 13
              AND L13.DATE_DEL IS NULL
              AND V63.PARAM_ID = 63
              AND V63.IS_DEL = 0
              AND V64.PARAM_ID = 64
              AND V64.IS_DEL = 0
              AND V58.PARAM_ID = 58
              AND V58.IS_DEL = 0
              AND V62.PARAM_ID = 62
              AND V62.IS_DEL = 0
              AND V58.LISTVAL_ID <> 1267
              AND V58.LISTVAL_ID <> 1284
              AND V58.LISTVAL_ID <> 1298
            INTO :V$POST_ID, :V$POST_GROUP, :V$POST_PODGROUP, :V$POST_FUNC, :V$STAVOK, :V$TAG
        DO
        BEGIN
            V$Y = 0;
            /* STAVKI UCHITEL - OTDELNO */
            IF (V$TAG = 'U') THEN
            BEGIN
                V$STAVOK = 0;
            END

            IF (I$N = 1) THEN
            BEGIN
                SELECT Z
                FROM RIK83_STAVOK(:V$POST_ID)
                INTO :V$Y;
                V04 = V04 + V$STAVOK - V$Y;
            END
            ELSE
            IF ((I$N = 2) AND (V$POST_GROUP = 55)) THEN
            BEGIN
                SELECT Z
                FROM RIK83_STAVOK(:V$POST_ID)
                INTO :V$Y;
                V04 = V04 + V$STAVOK - V$Y;
            END

            ELSE
            IF ((I$N = 5) AND (V$POST_GROUP = 1310)) THEN
            BEGIN
                SELECT Z
                FROM RIK83_STAVOK(:V$POST_ID)
                INTO :V$Y;
                V04 = V04 + V$STAVOK - V$Y;
            END
            ELSE
            IF ((I$N = 6) AND (V$POST_GROUP = 1323)) THEN
            BEGIN
                SELECT Z
                FROM RIK83_STAVOK(:V$POST_ID)
                INTO :V$Y;
                V04 = V04 + V$STAVOK - V$Y;
            END

        END

    END
    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE RIK83_DTL (
    G SMALLINT NOT NULL,
    N SMALLINT NOT NULL,
    V SMALLINT NOT NULL,
    BY_SCHOOL SMALLINT = 0)
RETURNS (
    NAME VARCHAR(250),
    CNT DOUBLE PRECISION,
    VAL1 VARCHAR(250))
AS
DECLARE VARIABLE LEVEL_ID SMALLINT;
BEGIN
    SELECT KEY_VAL FROM KEYS
    WHERE KEY_CODE = 'LEVEL'
    INTO :LEVEL_ID;

    IF (BY_SCHOOL = 1) THEN
    BEGIN
        FOR
            SELECT
               (SELECT CAPTION FROM OBJECT_CAPTION_GET(SCHOOL_ID)) NAME,
                IIF(:V = 4, SUM(V04), COUNT(1)) CNT
            FROM REPORT_RIK83
            WHERE (:G = 1 OR G = :G) AND ((:G = 1 AND N1 = :N) OR (:G > 1 AND N = :N))
              AND ((:V =  3 AND V03 = 1 AND V13 = 0) OR (:V =  4 AND V04 <> 0)
                OR (:V =  5 AND V05 = 1 AND V13 = 0) OR (:V =  6 AND V06 = 1 AND V13 = 0)
                OR (:V =  7 AND V07 = 1 AND V13 = 0) OR (:V =  8 AND V08 = 1 AND V13 = 0)
                OR (:V =  9 AND V09 = 1 AND V13 = 0) OR (:V = 10 AND V10 = 1 AND V13 = 0)
                OR (:V = 11 AND V11 = 1 AND V13 = 0) OR (:V = 12 AND V12 = 1 AND V13 = 0)
                OR (:V = 13 AND V13 = 1) OR (:V = 14 AND V14 = 1)
                OR (:V = 15 AND V15 = 1 AND V13 = 0) OR (:V = 16 AND V16 = 1 AND V13 = 0)
                OR (:V = 17 AND V17 = 1 AND V13 = 0) OR (:V = 18 AND V18 = 1 AND V13 = 0)
                OR (:V = 19 AND V19 = 1 AND V13 = 0) OR (:V = 20 AND V20 = 1 AND V13 = 0)
                OR (:V = 21 AND V21 = 1 AND V13 = 0) OR (:V = 22 AND V22 = 1 AND V13 = 0)
                OR (:V = 23 AND V23 = 1 AND V13 = 0) OR (:V = 24 AND V24 = 1 AND V13 = 0)
                OR (:V = 25 AND V25 = 1 AND V13 = 0) OR (:V = 26 AND V26 = 1 AND V13 = 0)
                OR (:V = 27 AND V27 = 1 AND V13 = 0) OR (:V = 28 AND V28 = 1 AND V13 = 0)
                OR (:V = 29 AND V29 = 1 AND V13 = 0) OR (:V = 30 AND V30 = 1 AND V13 = 0))
            GROUP BY SCHOOL_ID
            ORDER BY NAME
            INTO :NAME, :CNT
        DO
        BEGIN
            SUSPEND;
        END
    END
    ELSE
    BEGIN
        FOR
            SELECT
               IIF(:LEVEL_ID = 1, NULL, (SELECT CAPTION FROM OBJECT_CAPTION_GET(SCHOOL_ID))) NAME,
               (SELECT CAPTION FROM THE_CAPTION_TEACHER(TEACHER_ID)) VAL1
            FROM REPORT_RIK83
            WHERE (:G = 1 OR G = :G) AND ((:G = 1 AND N1 = :N) OR (:G > 1 AND N = :N))
              AND ((:V =  3 AND V03 = 1 AND (V13 = 0 OR N1 > 40))
                OR (:V =  5 AND V05 = 1 AND V13 = 0) OR (:V =  6 AND V06 = 1 AND V13 = 0)
                OR (:V =  7 AND V07 = 1 AND V13 = 0) OR (:V =  8 AND V08 = 1 AND V13 = 0)
                OR (:V =  9 AND V09 = 1 AND V13 = 0) OR (:V = 10 AND V10 = 1 AND V13 = 0)
                OR (:V = 11 AND V11 = 1 AND V13 = 0) OR (:V = 12 AND V12 = 1 AND V13 = 0)
                OR (:V = 13 AND V13 = 1) OR (:V = 14 AND V14 = 1)
                OR (:V = 15 AND V15 = 1 AND V13 = 0) OR (:V = 16 AND V16 = 1 AND V13 = 0)
                OR (:V = 17 AND V17 = 1 AND V13 = 0) OR (:V = 18 AND V18 = 1 AND V13 = 0)
                OR (:V = 19 AND V19 = 1 AND V13 = 0) OR (:V = 20 AND V20 = 1 AND V13 = 0)
                OR (:V = 21 AND V21 = 1 AND V13 = 0) OR (:V = 22 AND V22 = 1 AND V13 = 0)
                OR (:V = 23 AND V23 = 1 AND V13 = 0) OR (:V = 24 AND V24 = 1 AND V13 = 0)
                OR (:V = 25 AND V25 = 1 AND V13 = 0) OR (:V = 26 AND V26 = 1 AND V13 = 0)
                OR (:V = 27 AND V27 = 1 AND V13 = 0) OR (:V = 28 AND V28 = 1 AND V13 = 0)
                OR (:V = 29 AND V29 = 1 AND V13 = 0) OR (:V = 30 AND V30 = 1 AND V13 = 0))
            ORDER BY NAME, VAL1
            INTO :NAME, :VAL1
        DO
        BEGIN
            SUSPEND;
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE RIK83_GRID (
    I$OBJ_ID BIGINT NOT NULL,
    I$POD_NAME VARCHAR(1000),
    I$OPF_NAME VARCHAR(1000),
    I$G SMALLINT,
    I$N SMALLINT)
RETURNS (
    V03 INTEGER,
    V04 NUMERIC(11,2),
    V05 INTEGER,
    V06 INTEGER,
    V07 INTEGER,
    V08 INTEGER,
    V09 INTEGER,
    V10 INTEGER,
    V11 INTEGER,
    V12 INTEGER,
    V13 INTEGER,
    V14 INTEGER,
    V15 INTEGER,
    V16 INTEGER,
    V17 INTEGER,
    V18 INTEGER,
    V19 INTEGER,
    V20 INTEGER,
    V21 INTEGER,
    V22 INTEGER,
    V23 INTEGER,
    V24 INTEGER,
    V25 INTEGER,
    V26 INTEGER,
    V27 INTEGER,
    V28 INTEGER,
    V29 INTEGER,
    V30 INTEGER)
AS
BEGIN
    FOR
        SELECT
            V03, V04, V05, V06, V07, V08, V09,
            V10, V11, V12, V13, V14, V15, V16,
            V17, V18, V19, V20, V21, V22, V23,
            V24, V25, V26, V27, V28, V29, V30
        FROM RIK83_ALL(:I$OBJ_ID, :I$POD_NAME, :I$OPF_NAME, IIF(:I$G = 1 AND :I$N = 1, 1, 0), 0, :I$G, :I$N)
        INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09,
             :V10, :V11, :V12, :V13, :V14, :V15, :V16,
             :V17, :V18, :V19, :V20, :V21, :V22, :V23,
             :V24, :V25, :V26, :V27, :V28, :V29, :V30
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE RIK83_INFO (
    I$POST_ID BIGINT,
    I$WORKER_ID BIGINT,
    V03 INTEGER = null,
    V04 NUMERIC(11,2) = null,
    V05 INTEGER = null,
    V06 INTEGER = null,
    V07 INTEGER = null,
    V08 INTEGER = null,
    V09 INTEGER = null,
    V10 INTEGER = null,
    V11 INTEGER = null,
    V12 INTEGER = null,
    V13 INTEGER = null,
    V14 INTEGER = null,
    V15 INTEGER = null,
    V16 INTEGER = null,
    V17 INTEGER = null,
    V18 INTEGER = null,
    V19 INTEGER = null,
    V20 INTEGER = null,
    V21 INTEGER = null,
    V22 INTEGER = null,
    V23 INTEGER = null,
    V24 INTEGER = null,
    V25 INTEGER = null,
    V26 INTEGER = null,
    V27 INTEGER = null,
    V28 INTEGER = null,
    V29 INTEGER = null,
    V30 INTEGER = null)
RETURNS (
    X03 INTEGER,
    X04 NUMERIC(11,2),
    X05 INTEGER,
    X06 INTEGER,
    X07 INTEGER,
    X08 INTEGER,
    X09 INTEGER,
    X10 INTEGER,
    X11 INTEGER,
    X12 INTEGER,
    X13 INTEGER,
    X14 INTEGER,
    X15 INTEGER,
    X16 INTEGER,
    X17 INTEGER,
    X18 INTEGER,
    X19 INTEGER,
    X20 INTEGER,
    X21 INTEGER,
    X22 INTEGER,
    X23 INTEGER,
    X24 INTEGER,
    X25 INTEGER,
    X26 INTEGER,
    X27 INTEGER,
    X28 INTEGER,
    X29 INTEGER,
    X30 INTEGER,
    AGE SMALLINT)
AS
declare variable Y numeric(11,2);
declare variable I integer;
declare variable J integer;
declare variable LISTVAL_ID bigint;
declare variable V$Y1 smallint;
declare variable V$M1 smallint;
declare variable V$D1 smallint;
declare variable V$Y2 smallint;
declare variable V$M2 smallint;
declare variable V$D2 smallint;
declare variable SEX smallint;
declare variable V8O integer;
declare variable V8D integer;
BEGIN
    X03 = V03;
    X04 = V04;
    X05 = V05;
    X06 = V06;
    X07 = V07;
    X08 = V08;
    X09 = V09;
    X10 = V10;
    X11 = V11;
    X12 = V12;
    X13 = V13;
    X14 = V14;
    X15 = V15;
    X16 = V16;
    X17 = V17;
    X18 = V18;
    X19 = V19;
    X20 = V20;
    X21 = V21;
    X22 = V22;
    X23 = V23;
    X24 = V24;
    X25 = V25;
    X26 = V26;
    X27 = V27;
    X28 = V28;
    X29 = V29;
    X30 = V30;

    SEX = 0;

    SELECT COUNT(*),
        SUM(IIF(V72O.IS_DEL IS NULL, 0, 1)) V8O,
        SUM(IIF(V72D.IS_DEL IS NULL, 0, 1)) V8D
    FROM LINKS L15
    LEFT JOIN VALD V74 ON V74.PARAM_ID = 74 AND V74.OBJ_ID = L15.OBJ_ID AND V74.IS_DEL = 0
    LEFT JOIN VALL V72O ON V72O.OBJ_ID = L15.OBJ_ID AND V72O.PARAM_ID = 72 AND V72O.IS_DEL = 0 AND V72O.LISTVAL_ID = 934
    LEFT JOIN VALL V72D ON V72D.OBJ_ID = L15.OBJ_ID AND V72D.PARAM_ID = 72 AND V72D.IS_DEL = 0 AND V72D.LISTVAL_ID = 935
    WHERE L15.PARENT_ID = :I$WORKER_ID
      AND L15.OBJ_TYPE_ID = 15
      AND L15.DATE_DEL IS NULL
      AND V74.VAL IS NULL
    INTO :I, :V8O, V8D;

    SELECT FIRST 1 1
    FROM VALL V
    WHERE V.PARAM_ID = 239
      AND V.OBJ_ID = :I$WORKER_ID
      AND V.IS_DEL = 0
      AND V.LISTVAL_ID = 182
    INTO :SEX;

    SELECT COUNT(*)
    FROM LINKS L15
    INNER JOIN VALL V587 ON V587.OBJ_ID = L15.OBJ_ID
    LEFT JOIN VALD V74 ON V74.PARAM_ID = 74 AND V74.OBJ_ID = L15.OBJ_ID AND V74.IS_DEL = 0
    WHERE L15.PARENT_ID = :I$WORKER_ID
      AND L15.OBJ_TYPE_ID = 15
      AND L15.DATE_DEL IS NULL
      AND V587.PARAM_ID = 587
      AND V587.IS_DEL = 0
      AND V587.LISTVAL_ID = 208
      AND V74.VAL IS NULL
    INTO :J;

    IF ((I > 0) AND (J > 0) AND (I = J)) THEN
    BEGIN
        X13 = X13 + 1;
        X14 = X14 + SEX;
        SUSPEND;
        EXIT;
    END

    X03 = X03 + 1;

    IF (V8O > 0 AND V8D > 0) THEN
    BEGIN
        X08 = X08 + 1;
    END

    X05 = X05 + SEX;

    SELECT SUM(V71.VAL)
    FROM LINKS L15
    INNER JOIN VALF V71 ON V71.OBJ_ID = L15.OBJ_ID
    LEFT JOIN VALD V74 ON V74.PARAM_ID = 74 AND V74.OBJ_ID = L15.OBJ_ID AND V74.IS_DEL = 0
    WHERE L15.PARENT_ID = :I$WORKER_ID
      AND L15.OBJ_TYPE_ID = 15
      AND L15.DATE_DEL IS NULL
      AND V71.PARAM_ID = 71
      AND V71.IS_DEL = 0
      AND V74.VAL IS NULL
    INTO :Y;
    IF (Y > 0.99) THEN
    BEGIN
        X07 = X07 + 1;
    END
    ELSE
    BEGIN
        X06 = X06 + 1;
    END

    LISTVAL_ID = 0;
    SELECT LISTVAL_ID FROM VACANCY_GET_CAT(:I$WORKER_ID) INTO :LISTVAL_ID;

    IF (LISTVAL_ID = 635) THEN
    BEGIN
        X09 = X09 + 1;
    END
    ELSE
    IF (LISTVAL_ID = 634) THEN
    BEGIN
        X10 = X10 + 1;
    END
    ELSE
    IF (LISTVAL_ID = 633) THEN
    BEGIN
        X11 = X11 + 1;
    END
    ELSE
    IF (LISTVAL_ID = 632) THEN
    BEGIN
        X12 = X12 + 1;
    END

    LISTVAL_ID = 0;
    SELECT V.LISTVAL_ID
    FROM VALL V
    WHERE V.PARAM_ID = 278
      AND V.OBJ_ID = :I$WORKER_ID
      AND V.IS_DEL = 0
    INTO :LISTVAL_ID;

    IF (LISTVAL_ID IN (620, 3031, 3032)) THEN
    BEGIN
        X15 = X15 + 1;

        LISTVAL_ID = 0;
        SELECT FIRST 1 V293.LISTVAL_ID
        FROM LINKS L33
        INNER JOIN VALL V284 ON V284.OBJ_ID = L33.OBJ_ID
        INNER JOIN VALL V293 ON V293.OBJ_ID = L33.OBJ_ID
        WHERE L33.PARENT_ID = :I$WORKER_ID
          AND L33.OBJ_TYPE_ID = 33
          AND L33.DATE_DEL IS NULL
          AND V284.PARAM_ID = 284
          AND V284.IS_DEL = 0
          AND V284.LISTVAL_ID IN (620, 3031, 3032)
          AND V293.PARAM_ID = 293
          AND V293.IS_DEL = 0
          -- AMINKO
          AND V293.LISTVAL_ID = 647
        INTO :LISTVAL_ID;

        IF (LISTVAL_ID = 647) THEN
        BEGIN
            X16 = X16 + 1;
        END
    END
    ELSE
    IF (LISTVAL_ID = 622) THEN
    BEGIN
        X17 = X17 + 1;

        LISTVAL_ID = 0;
        SELECT FIRST 1 V293.LISTVAL_ID
        FROM LINKS L33
        INNER JOIN VALL V284 ON V284.OBJ_ID = L33.OBJ_ID
        INNER JOIN VALL V293 ON V293.OBJ_ID = L33.OBJ_ID
        WHERE L33.PARENT_ID = :I$WORKER_ID
          AND L33.OBJ_TYPE_ID = 33
          AND L33.DATE_DEL IS NULL
          AND V284.PARAM_ID = 284
          AND V284.IS_DEL = 0
          AND V284.LISTVAL_ID = 622
          AND V293.PARAM_ID = 293
          AND V293.IS_DEL = 0
        INTO :LISTVAL_ID;

        IF (LISTVAL_ID = 647) THEN
        BEGIN
            X18 = X18 + 1;
        END
    END
    ELSE
    IF (LISTVAL_ID = 624) THEN
    BEGIN
        X19 = X19 + 1;
    END
    ELSE
    IF (LISTVAL_ID = 623) THEN
    BEGIN
        X20 = X20 + 1;
    END

    Y = 0;
    SELECT SUM(DAYS360_COUNT)
    FROM PARAGRAF_EMPLOYEE_SENIORITY_LST(:I$WORKER_ID)
    WHERE SENIORITY_TYPE = 941
    INTO :Y;
    IF (Y IS NULL) THEN
        Y = 0;

    IF (Y < 640) THEN
    BEGIN
        X21 = X21 + 1;
    END
    ELSE
    IF (Y < 1800) THEN
    BEGIN
        X22 = X22 + 1;
    END
    ELSE
    IF (Y < 3600) THEN
    BEGIN
        X23 = X23 + 1;
    END
    ELSE
    IF (Y < 6400) THEN
    BEGIN
        X24 = X24 + 1;
    END
    ELSE
    BEGIN
        X25 = X25 + 1;
    END

    V$Y2 = EXTRACT(YEAR FROM CURRENT_DATE);
    V$M2 = 9;
    V$D2 = 20;
    SELECT FIRST 1 EXTRACT(YEAR FROM V.VAL), EXTRACT(MONTH FROM V.VAL), EXTRACT(DAY FROM V.VAL)
    FROM VALD V
    WHERE V.PARAM_ID = 241
      AND V.OBJ_ID = :I$WORKER_ID
      AND V.IS_DEL = 0
    INTO :V$Y1, :V$M1, :V$D1;
    Y = V$Y2 - V$Y1;
    IF ((V$M2 * 32 + V$D2) < (V$M1 * 32 + V$D1)) THEN
    BEGIN
        Y = Y - 1;
    END
    AGE = Y;
    IF (Y IS NULL) THEN
        Y = 0;
    IF (Y < 25) THEN
    BEGIN
        X26 = X26 + 1;
    END
    ELSE
    IF (Y < 35) THEN
    BEGIN
        X27 = X27 + 1;
    END
    ELSE
    BEGIN
        X28 = X28 + 1;
        IF ((SEX = 0) AND (Y >= 60)) THEN
        BEGIN
            X29 = X29 + 1;
        END
        IF ((SEX = 1) AND (Y >= 55)) THEN
        BEGIN
            X29 = X29 + 1;
            X30 = X30 + SEX;
        END
    END

    SUSPEND;

END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE RIK83_INSERT (
    I$OBJ_ID BIGINT NOT NULL,
    I$POD_NAME VARCHAR(1000) = null,
    I$OPF_ID VARCHAR(1000) = null,
    R_1DO_6_FL SMALLINT = 0,
    I$DT DATE = current_date)
AS
declare variable OBJ_TYPE_ID bigint;
BEGIN
    SELECT TYPE_ID
    FROM OBJECTS
    WHERE OBJ_ID = :I$OBJ_ID
    INTO :OBJ_TYPE_ID;

    INSERT INTO REPORT_RIK83(G, N1, N, SCHOOL_ID, TEACHER_ID,
        V03, V05, V06, V07, V08, V09, V10, V11, V12,
        V13, V14, V15, V16, V17, V18, V19, V20, V21,
        V22, V23, V24, V25, V26, V27, V28, V29, V30)
    SELECT
        G,
        IIF(N1 IN (8, 36) AND :R_1DO_6_FL = 0 AND V58LISTVAL_ID IN (119,130,145,1251,1291), NULL, N1) N1,
        CASE
            WHEN G = 1 THEN NULL
            WHEN N1 < 3 THEN N1
            WHEN N1 = 7 THEN 3
            WHEN N1 = 8 THEN 4
            WHEN (G BETWEEN 2 AND 4 AND N1 = 36) OR (G > 4 AND N1 = 38) THEN 5
            WHEN (G BETWEEN 2 AND 4 AND N1 = 38) OR (G > 4 AND G <> 7 AND N1 = 40) THEN 6
            WHEN (G = 7 AND N1 = 40) OR (G > 8 AND N1 = 41) THEN 7
            WHEN (G BETWEEN 2 AND 4 AND N1 = 40) OR (G = 7 AND N1 = 41) OR (G > 8 AND N1 = 43) THEN 8
            WHEN (G = 3 AND N1 = 41) OR (G = 7 AND N1 = 43) OR (G > 8 AND N1 = 44) THEN 9
            WHEN (G = 3 AND N1 = 43) OR (G = 7 AND N1 = 44) THEN 10
            WHEN  G = 3 AND N1 = 44 THEN 11
        END N,
        SCHOOL_ID,
        TEACHER_ID,
        1 X03,
        IIF(N1 > 40, NULL, SEX) X05,
        IIF(N1 > 40, NULL, IIF(Y > 0.99, 0, 1)) X06,
        IIF(N1 > 40, NULL, IIF(Y > 0.99, 1, 0)) X07,
        IIF(N1 > 40, NULL, IIF(V8O > 0 AND V8D > 0, 1, 0)) X08,
        IIF(N1 > 40, NULL, IIF(V281 = 635, 1, 0)) X09,
        IIF(N1 > 40, NULL, IIF(V281 = 634, 1, 0)) X10,
        IIF(N1 > 40, NULL, IIF(V281 = 633, 1, 0)) X11,
        IIF(N1 > 40, NULL, IIF(V281 = 632, 1, 0)) X12,
        IIF(I > 0 AND J > 0 AND I = J, 1, 0) X13,
        IIF(N1 > 40, NULL, IIF(I > 0 AND J > 0 AND I = J, SEX, 0)) X14,
        IIF(N1 > 40, NULL, IIF(LIST278 IN (620, 3031, 3032), 1, 0)) X15,
        IIF(N1 > 40, NULL, IIF(LIST278 IN (620, 3031, 3032), (
            SELECT FIRST 1 1
            FROM LINKS L33
            INNER JOIN VALL V284 ON V284.OBJ_ID = L33.OBJ_ID
            INNER JOIN VALL V293 ON V293.OBJ_ID = L33.OBJ_ID
            WHERE L33.PARENT_ID = TEACHER_ID
              AND L33.OBJ_TYPE_ID = 33
              AND L33.DATE_DEL IS NULL
              AND V284.PARAM_ID = 284
              AND V284.IS_DEL = 0
              AND V284.LISTVAL_ID IN (620, 3031, 3032)
              AND V293.PARAM_ID = 293
              AND V293.LISTVAL_ID = 647
              AND V293.IS_DEL = 0),0)) X16,
        IIF(N1 > 40, NULL, IIF(LIST278 = 622, 1, 0)) X17,
        IIF(N1 > 40, NULL, IIF(LIST278 = 622, (
            SELECT FIRST 1 1
            FROM LINKS L33
            INNER JOIN VALL V284 ON V284.OBJ_ID = L33.OBJ_ID
            INNER JOIN VALL V293 ON V293.OBJ_ID = L33.OBJ_ID
            WHERE L33.PARENT_ID = TEACHER_ID
              AND L33.OBJ_TYPE_ID = 33
              AND L33.DATE_DEL IS NULL
              AND V284.PARAM_ID = 284
              AND V284.IS_DEL = 0
              AND V284.LISTVAL_ID = 622
              AND V293.PARAM_ID = 293 AND V293.LISTVAL_ID = 647
              AND V293.IS_DEL = 0),0)) X18,
        IIF(N1 > 40, NULL, IIF(LIST278 = 624, 1, 0)) X19,
        IIF(N1 > 40, NULL, IIF(LIST278 = 623, 1, 0)) X20,
        IIF(N1 > 40, NULL, IIF(COALESCE(DAYS360_COUNT,0) < 640, 1, 0)) X21,
        IIF(N1 > 40, NULL, IIF(DAYS360_COUNT BETWEEN 640 and 1799, 1, 0)) X22,
        IIF(N1 > 40, NULL, IIF(DAYS360_COUNT BETWEEN 1800 and 3599, 1, 0)) X23,
        IIF(N1 > 40, NULL, IIF(DAYS360_COUNT BETWEEN 3600 and 6399, 1, 0)) X24,
        IIF(N1 > 40, NULL, IIF(DAYS360_COUNT >= 6400 , 1, 0)) X25,
        IIF(N1 > 40, NULL, IIF(VAL241 < 25 , 1, 0)) X26,
        IIF(N1 > 40, NULL, IIF(VAL241 BETWEEN 25 AND 34, 1, 0)) X27,
        IIF(N1 > 40, NULL, IIF(VAL241 >= 35, 1, 0)) X28,
        IIF(N1 > 40, NULL, IIF(VAL241 >= 60 - SEX*5, 1, 0)) X29,
        IIF(N1 > 40, NULL, IIF(VAL241 >= 55 AND SEX = 1, SEX, 0)) X30
    FROM (
        SELECT
            CASE
                WHEN :OBJ_TYPE_ID = 2 THEN 1
                WHEN V11.LISTVAL_ID = 954 THEN 2
                WHEN V11.LISTVAL_ID = 958 THEN 3
                WHEN V11.LISTVAL_ID = 969 THEN 4
                WHEN V10.LISTVAL_ID IN (968, 973) THEN 5
                WHEN V10.LISTVAL_ID = 974 THEN 6
                WHEN V11.LISTVAL_ID = 978 THEN 7
                WHEN V11.LISTVAL_ID = 2221 THEN 8
                WHEN V11.LISTVAL_ID = 981 THEN 9
                WHEN V11.LISTVAL_ID = 975 THEN 10
                WHEN V11.LISTVAL_ID = 1003 THEN 11
                ELSE 1
            END G,
            V63.LISTVAL_ID V63LISTVAL_ID,
            V64.LISTVAL_ID V64LISTVAL_ID,
            V58.LISTVAL_ID V58LISTVAL_ID,
            (SELECT SORT_ORDER FROM DO_FUNC(V69.VAL, 400)) V400LISTVAL_ID,
            V11.LISTVAL_ID V11LISTVAL_ID,
            L14.OBJ_ID TEACHER_ID,
            L2.OBJ_ID SCHOOL_ID,
            COALESCE((
                SELECT FIRST 1 1 FROM VALL V
                WHERE V.PARAM_ID = 239
                  AND V.OBJ_ID = L14.OBJ_ID
                  AND V.IS_DEL = 0
                  AND V.LISTVAL_ID = 182),0) SEX,
           LIST281.LISTVAL_ID V281,
           (SELECT V.LISTVAL_ID
                FROM VALL V
                WHERE V.PARAM_ID = 278 AND V.OBJ_ID = L14.OBJ_ID AND V.IS_DEL = 0) LIST278,
            COALESCE((
                SELECT FIRST 1 EXTRACT(YEAR FROM :I$DT) - EXTRACT(YEAR FROM V.VAL) -
                   IIF(EXTRACT(MONTH FROM :I$DT)*32 + EXTRACT(DAY FROM :I$DT) < EXTRACT(MONTH FROM V.VAL)*32 + EXTRACT(DAY FROM V.VAL), 1, 0)
                FROM VALD V
                WHERE V.PARAM_ID = 241
                  AND V.OBJ_ID = L14.OBJ_ID
                  AND V.IS_DEL = 0), 0) VAL241
        FROM LINKS L2
        LEFT JOIN VALS V6 ON V6.OBJ_ID = L2.OBJ_ID AND V6.PARAM_ID = 6 AND V6.IS_DEL = 0
        LEFT JOIN VALL V8 ON V8.OBJ_ID = L2.OBJ_ID AND V8.PARAM_ID = 8 AND V8.IS_DEL = 0
        JOIN (
            SELECT COALESCE(L84.PARENT_ID, COALESCE(L211.PARENT_ID, LL14.PARENT_ID)) PARENT_ID, LL14.OBJ_ID
            FROM LINKS LL14
            LEFT JOIN LINKS L84 ON L84.OBJ_ID = LL14.PARENT_ID AND L84.OBJ_TYPE_ID = 84 AND L84.DATE_DEL IS NULL
            -- for UDOD
            LEFT JOIN LINKS L211 ON L211.OBJ_ID = LL14.PARENT_ID AND L211.OBJ_TYPE_ID = 211 AND L211.DATE_DEL IS NULL
            WHERE LL14.OBJ_TYPE_ID = 14 AND LL14.DATE_DEL IS NULL
        ) L14 ON L14.PARENT_ID = L2.OBJ_ID
        JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
        JOIN VALL V11 ON V11.OBJ_ID = L14.PARENT_ID AND V11.PARAM_ID = 11 AND V11.IS_DEL = 0
        JOIN VALL V10 ON V10.OBJ_ID = L2.OBJ_ID AND V10.PARAM_ID = 10 AND V10.IS_DEL = 0
        JOIN VALL V72 ON V72.OBJ_ID = L15.OBJ_ID AND V72.PARAM_ID = 72 AND V72.IS_DEL = 0 AND V72.LISTVAL_ID = 934
        JOIN VALR V69 ON V69.OBJ_ID = L15.OBJ_ID AND V69.PARAM_ID = 69 AND V69.IS_DEL = 0
        JOIN VALL V63 ON V63.OBJ_ID = V69.VAL AND V63.PARAM_ID = 63 AND V63.IS_DEL = 0
        JOIN VALL V64 ON V64.OBJ_ID = V69.VAL AND V64.PARAM_ID = 64 AND V64.IS_DEL = 0
        JOIN VALL V58 ON V58.OBJ_ID = V69.VAL AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0
        LEFT JOIN VALD V73 ON V73.PARAM_ID = 73 AND V73.OBJ_ID = L15.OBJ_ID AND V73.IS_DEL = 0
        LEFT JOIN VALD V74 ON V74.PARAM_ID = 74 AND V74.OBJ_ID = L15.OBJ_ID AND V74.IS_DEL = 0
        LEFT JOIN VALL V274 ON V274.PARAM_ID = 274 AND V274.OBJ_ID = L14.OBJ_ID AND V274.IS_DEL = 0
        LEFT JOIN VACANCY_GET_CAT(L14.OBJ_ID) LIST281 ON 1 = 1
        WHERE L2.DATE_DEL IS NULL AND L2.OBJ_TYPE_ID = 2
          AND ((:OBJ_TYPE_ID = 2 AND L14.PARENT_ID = :I$OBJ_ID) OR
               (:OBJ_TYPE_ID = 111 AND L2.PARENT_ID = :I$OBJ_ID))
          AND (:I$POD_NAME IS NULL OR V6.VAL = :I$POD_NAME)
          AND (:I$OPF_ID IS NULL OR V8.LISTVAL_ID <> :I$OPF_ID)
          AND :I$DT BETWEEN COALESCE(V73.VAL, :I$DT) AND COALESCE(V74.VAL, :I$DT)
          AND (V274.LISTVAL_ID IS NULL OR V274.LISTVAL_ID IN (602, 604))
        ) V,
       (SELECT
            SUM(V71.VAL) Y,
            COUNT(1) I,
            SUM(IIF(V587.IS_DEL IS NULL, 0, 1)) J,
            SUM(IIF(V72O.IS_DEL IS NULL, 0, 1)) V8O,
            SUM(IIF(V72D.IS_DEL IS NULL, 0, 1)) V8D,
            L15.PARENT_ID PARENT_ID
            FROM LINKS L15
            LEFT JOIN VALF V71 ON V71.OBJ_ID = L15.OBJ_ID AND V71.PARAM_ID = 71 AND V71.IS_DEL = 0
            LEFT JOIN VALD V73 ON V73.PARAM_ID = 73 AND V73.OBJ_ID = L15.OBJ_ID AND V73.IS_DEL = 0
            LEFT JOIN VALD V74 ON V74.PARAM_ID = 74 AND V74.OBJ_ID = L15.OBJ_ID AND V74.IS_DEL = 0
            LEFT JOIN VALL V587 ON V587.OBJ_ID = L15.OBJ_ID AND V587.PARAM_ID = 587 AND V587.IS_DEL = 0 AND V587.LISTVAL_ID = 208
            LEFT JOIN VALL V72O ON V72O.OBJ_ID = L15.OBJ_ID AND V72O.PARAM_ID = 72 AND V72O.IS_DEL = 0 AND V72O.LISTVAL_ID = 934
            LEFT JOIN VALL V72D ON V72D.OBJ_ID = L15.OBJ_ID AND V72D.PARAM_ID = 72 AND V72D.IS_DEL = 0 AND V72D.LISTVAL_ID = 935
            WHERE L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL AND :I$DT BETWEEN COALESCE(V73.VAL, :I$DT) AND COALESCE(V74.VAL, :I$DT)
            GROUP BY L15.PARENT_ID
        ) V7,
       (SELECT
            PARENT_ID,
            SUM(DAYS360_COUNT) DAYS360_COUNT
        FROM (
            SELECT L85.PARENT_ID,
               (SELECT DAYS360_COUNT
                FROM GET_DAYS360_COUNT(
                   (SELECT VAL FROM VALD
                    WHERE PARAM_ID = 466
                      AND OBJ_ID = L85.OBJ_ID
                      AND IS_DEL = 0),
                   COALESCE((SELECT VAL FROM VALD
                    WHERE PARAM_ID = 467
                      AND OBJ_ID = L85.OBJ_ID
                      AND IS_DEL = 0), :I$DT))) DAYS360_COUNT
            FROM LINKS L85
            LEFT JOIN VALL V465 ON V465.OBJ_ID = L85.OBJ_ID AND V465.PARAM_ID = 465 AND V465.IS_DEL = 0
            WHERE L85.OBJ_TYPE_ID = 85 AND L85.DATE_DEL IS NULL AND V465.LISTVAL_ID = 941
            UNION ALL
            SELECT PARENT_ID, 0 FROM LINKS L15
            LEFT JOIN VALD V73 ON V73.PARAM_ID = 73 AND V73.OBJ_ID = L15.OBJ_ID AND V73.IS_DEL = 0
            LEFT JOIN VALD V74 ON V74.PARAM_ID = 74 AND V74.OBJ_ID = L15.OBJ_ID AND V74.IS_DEL = 0
            WHERE L15.OBJ_TYPE_ID = 15 AND :I$DT BETWEEN COALESCE(V73.VAL, :I$DT) AND COALESCE(V74.VAL, :I$DT) AND L15.DATE_DEL IS NULL)
        GROUP BY PARENT_ID
        ) V85,
       (SELECT     1 N1 FROM RDB$DATABASE UNION SELECT  2 FROM RDB$DATABASE UNION SELECT  3 FROM RDB$DATABASE
        UNION SELECT  4 FROM RDB$DATABASE UNION SELECT  5 FROM RDB$DATABASE UNION SELECT  6 FROM RDB$DATABASE
        UNION SELECT  7 FROM RDB$DATABASE UNION SELECT  8 FROM RDB$DATABASE UNION SELECT  9 FROM RDB$DATABASE
        UNION SELECT 10 FROM RDB$DATABASE UNION SELECT 11 FROM RDB$DATABASE UNION SELECT 12 FROM RDB$DATABASE
        UNION SELECT 13 FROM RDB$DATABASE UNION SELECT 14 FROM RDB$DATABASE UNION SELECT 15 FROM RDB$DATABASE
        UNION SELECT 16 FROM RDB$DATABASE UNION SELECT 17 FROM RDB$DATABASE UNION SELECT 18 FROM RDB$DATABASE
        UNION SELECT 19 FROM RDB$DATABASE UNION SELECT 20 FROM RDB$DATABASE UNION SELECT 21 FROM RDB$DATABASE
        UNION SELECT 22 FROM RDB$DATABASE UNION SELECT 23 FROM RDB$DATABASE UNION SELECT 24 FROM RDB$DATABASE
        UNION SELECT 25 FROM RDB$DATABASE UNION SELECT 26 FROM RDB$DATABASE UNION SELECT 27 FROM RDB$DATABASE
        UNION SELECT 28 FROM RDB$DATABASE UNION SELECT 29 FROM RDB$DATABASE UNION SELECT 30 FROM RDB$DATABASE
        UNION SELECT 31 FROM RDB$DATABASE UNION SELECT 32 FROM RDB$DATABASE UNION SELECT 33 FROM RDB$DATABASE
        UNION SELECT 34 FROM RDB$DATABASE UNION SELECT 35 FROM RDB$DATABASE UNION SELECT 36 FROM RDB$DATABASE
        UNION SELECT 38 FROM RDB$DATABASE UNION SELECT 40 FROM RDB$DATABASE UNION SELECT 41 FROM RDB$DATABASE
        UNION SELECT 42 FROM RDB$DATABASE UNION SELECT 43 FROM RDB$DATABASE UNION SELECT 44 FROM RDB$DATABASE
        UNION SELECT 45 FROM RDB$DATABASE UNION SELECT 46 FROM RDB$DATABASE UNION SELECT 47 FROM RDB$DATABASE
        UNION SELECT 48 FROM RDB$DATABASE)
    WHERE V.TEACHER_ID = V7.PARENT_ID
      AND V85.PARENT_ID = V7.PARENT_ID
      AND ((V58LISTVAL_ID NOT IN (1267,1284,1298)
      AND ((N1 = 1)
        OR (N1 = 2 AND V63LISTVAL_ID = 55)
        OR (N1 = 3 AND V63LISTVAL_ID = 55 AND V64LISTVAL_ID = 56 AND V58LISTVAL_ID <> 69)
        OR (N1 = 4 AND V63LISTVAL_ID = 55 AND V64LISTVAL_ID = 113 AND V58LISTVAL_ID <> 69)
        OR (N1 = 5 AND V63LISTVAL_ID = 55 AND V58LISTVAL_ID = 69)
        OR (N1 = 6 AND V63LISTVAL_ID = 55 AND V64LISTVAL_ID = 70 AND V58LISTVAL_ID <> 69)
        OR (N1 = 7 AND V63LISTVAL_ID = 97 AND V400LISTVAL_ID = 2)
        OR (N1 = 8 AND V63LISTVAL_ID = 97 AND V64LISTVAL_ID = 98 AND V58LISTVAL_ID NOT IN (119,130,145,1251,1291))
        OR (N1 = 9 AND V63LISTVAL_ID = 97 AND V64LISTVAL_ID = 98 AND V58LISTVAL_ID = 108)
        OR (N1 = 10 AND V63LISTVAL_ID = 97 AND V64LISTVAL_ID = 98 AND V58LISTVAL_ID IN (112, 1260))
        OR (N1 = 11 AND V63LISTVAL_ID = 97 AND V64LISTVAL_ID = 70)
        OR (N1 = 12 AND V63LISTVAL_ID = 97 AND V64LISTVAL_ID = 98 AND V58LISTVAL_ID IN (104, 1268, 1273, 1278))
        OR (N1 = 13 AND V63LISTVAL_ID = 97 AND V64LISTVAL_ID = 98 AND V58LISTVAL_ID = 105)
        OR (N1 = 14 AND V63LISTVAL_ID = 97 AND V64LISTVAL_ID = 98 AND V58LISTVAL_ID = 102)
        OR (N1 = 15 AND V63LISTVAL_ID = 97 AND V64LISTVAL_ID = 98 AND V58LISTVAL_ID = 115)
        OR (N1 = 16 AND V63LISTVAL_ID = 97 AND V64LISTVAL_ID = 98 AND V58LISTVAL_ID = 118)
        OR (N1 = 17 AND V63LISTVAL_ID = 97 AND V64LISTVAL_ID = 98 AND V58LISTVAL_ID = 101)
        OR (N1 = 18 AND V63LISTVAL_ID = 97 AND V64LISTVAL_ID = 98 AND V58LISTVAL_ID = 100)
        OR (N1 = 19 AND V63LISTVAL_ID = 97 AND V64LISTVAL_ID = 98 AND V58LISTVAL_ID = 99)
        OR (N1 = 20 AND V63LISTVAL_ID = 97 AND V64LISTVAL_ID = 98 AND V58LISTVAL_ID = 109)
        OR (N1 = 21 AND V63LISTVAL_ID = 97 AND V64LISTVAL_ID = 98 AND V58LISTVAL_ID = 117)
        OR (N1 = 22 AND V63LISTVAL_ID = 97 AND V64LISTVAL_ID = 98 AND V58LISTVAL_ID = 1264)
        OR (N1 = 23 AND V63LISTVAL_ID = 97 AND V64LISTVAL_ID = 98 AND V58LISTVAL_ID = 106)
        OR (N1 = 24 AND V63LISTVAL_ID = 97 AND V64LISTVAL_ID = 98 AND V58LISTVAL_ID IN (111, 3148))
        OR (N1 = 25 AND V63LISTVAL_ID = 97 AND V64LISTVAL_ID = 98 AND V58LISTVAL_ID IN (110, 121))
        OR (N1 = 26 AND V63LISTVAL_ID = 97 AND V64LISTVAL_ID = 98 AND V58LISTVAL_ID = 116)
        OR (N1 = 27 AND V63LISTVAL_ID = 97 AND V64LISTVAL_ID = 98 AND V58LISTVAL_ID = 114)
        OR (N1 = 28 AND V63LISTVAL_ID = 97 AND V64LISTVAL_ID = 98 AND
            V58LISTVAL_ID NOT IN (119,130,145,1251,1291,108,112,1260,104,1268,1273,1278,105,102,115,118,101,100,99,109,117,1264,106,111,3148,110,121,116,114))
        OR (N1 = 29 AND V63LISTVAL_ID = 97 AND V58LISTVAL_ID = 119)
        OR (N1 = 30 AND :R_1DO_6_FL = 0 AND V63LISTVAL_ID = 97 AND V58LISTVAL_ID = 130)
        OR (N1 = 30 AND :R_1DO_6_FL = 1 AND V63LISTVAL_ID = 97 AND V58LISTVAL_ID = 143)
        OR (N1 = 31 AND :R_1DO_6_FL = 0 AND V63LISTVAL_ID = 97 AND V58LISTVAL_ID = 145)
        OR (N1 = 31 AND :R_1DO_6_FL = 1 AND V63LISTVAL_ID = 97 AND V58LISTVAL_ID = 144)
        OR (N1 = 32 AND V63LISTVAL_ID = 97 AND V58LISTVAL_ID = 1251)
        OR (N1 = 33 AND :R_1DO_6_FL = 0 AND V63LISTVAL_ID = 97 AND V64LISTVAL_ID = 125 AND V58LISTVAL_ID NOT IN (119,130,145,1251,1291))
        OR (N1 = 33 AND :R_1DO_6_FL = 1 AND V63LISTVAL_ID = 97 AND V64LISTVAL_ID = 1256)
        OR (N1 = 34 AND :R_1DO_6_FL = 0 AND V63LISTVAL_ID = 97 AND V58LISTVAL_ID = 1291)
        OR (N1 = 34 AND :R_1DO_6_FL = 1 AND V63LISTVAL_ID = 97 AND V58LISTVAL_ID = 133)
        OR (N1 = 35 AND :R_1DO_6_FL = 0 AND V63LISTVAL_ID = 97 AND V400LISTVAL_ID = 2 AND
            V64LISTVAL_ID NOT IN (98, 125) AND V58LISTVAL_ID NOT IN (119,130,145,1251,1291))
        OR (N1 = 35 AND :R_1DO_6_FL = 1 AND V63LISTVAL_ID = 97 AND V400LISTVAL_ID = 2 AND
            V64LISTVAL_ID NOT IN (98, 125) AND V58LISTVAL_ID NOT IN (143,144,1251,1256,133))
        OR (N1 = 36 AND V63LISTVAL_ID = 97 AND V11LISTVAL_ID <> 978 AND (
            SELECT FIRST 1 1
            FROM LINKS L58
            JOIN LINKS L9 ON L9.OBJ_ID = L58.OBJ_ID AND L9.PARENT_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
            JOIN VALL V592 ON V592.OBJ_ID = L9.PARENT_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID > 197
            WHERE L58.PARENT_ID = TEACHER_ID AND L58.OBJ_TYPE_ID = 58 AND L58.DATE_DEL IS NULL)
            = 1)
        OR (N1 = 38 AND (V63LISTVAL_ID = 1310 OR (V63LISTVAL_ID = 97 AND V400LISTVAL_ID <> 2)))
        OR (N1 = 40 AND V63LISTVAL_ID = 1323)))
        OR (N1 = 41 AND V58LISTVAL_ID IN (1267,1284,1298))
        OR (N1 = 42 AND SEX = 1 AND V58LISTVAL_ID IN (1267,1284,1298))
        OR (N1 = 43 AND V58LISTVAL_ID = 1267)
        OR (N1 = 44 AND V58LISTVAL_ID IN (1284,1298))
        OR (N1 = 45 AND V58LISTVAL_ID = 120 AND NOT (I > 0 AND J > 0 AND I = J))
        OR (N1 = 46 AND V58LISTVAL_ID = 120 AND I > 0 AND J > 0 AND I = J)
        OR (N1 = 47 AND V63LISTVAL_ID = 97 AND V64LISTVAL_ID = 98 AND NOT (I > 0 AND J > 0 AND I = J) AND VAL241 < 30)
        OR (N1 = 48 AND V63LISTVAL_ID = 55 AND NOT (I > 0 AND J > 0 AND I = J) AND (
            SELECT FIRST 1 1
            FROM LINKS L36
            JOIN VALD V310 ON V310.OBJ_ID = L36.OBJ_ID AND V310.PARAM_ID IN (300, 310) AND V310.IS_DEL = 0 AND V310.VAL >= DATEADD(-3 YEAR TO :I$DT)
            WHERE L36.PARENT_ID = TEACHER_ID AND L36.OBJ_TYPE_ID IN (35, 36) AND L36.DATE_DEL IS NULL) = 1));
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE RIK83_STAVOK (
    I$POST_ID BIGINT)
RETURNS (
    Z NUMERIC(11,2))
AS
BEGIN
    SELECT SUM(V71.VAL)
    FROM LINKS L15
    INNER JOIN VALF V71 ON V71.OBJ_ID = L15.OBJ_ID
    LEFT JOIN VALD V74 ON V74.PARAM_ID = 74 AND V74.OBJ_ID = L15.OBJ_ID AND V74.IS_DEL = 0
    WHERE L15.PARENT_ID = :I$POST_ID
      AND L15.OBJ_TYPE_ID = 15
      AND L15.DATE_DEL IS NULL
      AND V71.PARAM_ID = 71
      AND V71.IS_DEL = 0
      AND V74.VAL IS NULL
    INTO :Z;

    IF (Z IS NULL) THEN Z = 0;

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE RKS_ACCEPT_CHECK (
    I$NAME_LAST VARCHAR(200),
    I$NAME_FIRST VARCHAR(200),
    I$NAME_MID VARCHAR(200),
    I$BIRTH_DATE DATE,
    I$SNILS VARCHAR(200),
    I$CLAIM_ID VARCHAR(40),
    I$REG_ID VARCHAR(40),
    I$PASS_TYPE BIGINT = null,
    I$PASS_DATE DATE = null,
    I$PASS_NUM VARCHAR(100) = null)
RETURNS (
    IS_EXIST SMALLINT,
    MATCH_FIO SMALLINT,
    OBJ_ID BIGINT,
    TYPE_ID BIGINT)
AS
begin

  I$SNILS = REPLACE(REPLACE(I$SNILS, ' ', ''), '-', '');
  I$NAME_LAST = REPLACE(REPLACE(REPLACE(UPPER(SUBSTRING(I$NAME_LAST FROM 1 FOR 40)), 'Ё', 'Е'), '-', ''), ' ', '');
  I$NAME_FIRST = REPLACE(REPLACE(REPLACE(UPPER(SUBSTRING(I$NAME_FIRST FROM 1 FOR 40)), 'Ё', 'Е'), '-', ''), ' ', '');
  I$NAME_MID = REPLACE(REPLACE(REPLACE(UPPER(SUBSTRING(I$NAME_MID FROM 1 FOR 40)), 'Ё', 'Е'), '-', ''), ' ', '');

  I$REG_ID = UPPER(I$REG_ID);

  -- IS_EXIST: возможные значения 0, 1, 2, 3
  IS_EXIST = 0; -- не найден, можно принимать
  MATCH_FIO = 0; -- признак того, что сравнение получилось по ФИО и ДР

  -- Сначала по id заявления
  SELECT FIRST 1 LPG.OBJ_ID, LPG.PARENT_TYPE_ID, 2
  FROM VALS V3349
  JOIN LINKS LPG ON LPG.OBJ_ID = V3349.OBJ_ID AND LPG.PARENT_TYPE_ID IN (290, 9, 187, 81, 82, 83) AND LPG.DATE_DEL IS NULL
  WHERE V3349.PARAM_ID = 3349 AND V3349.SVAL = :I$CLAIM_ID AND V3349.IS_DEL = 0
  INTO :OBJ_ID, :TYPE_ID, :MATCH_FIO;

  -- Затем по регид, приходится учитывать все варианты формата - lower или upper, с суффиксом и без, со скобками и без
  SELECT FIRST 1 LPG.OBJ_ID, LPG.PARENT_TYPE_ID, 2
  FROM VALS V2912
  JOIN LINKS LPG ON LPG.OBJ_ID = V2912.OBJ_ID AND LPG.PARENT_TYPE_ID IN (290, 9, 187, 81, 82, 83) AND LPG.DATE_DEL IS NULL
  WHERE V2912.PARAM_ID = 2912 AND UPPER(SUBSTRING(V2912.SVAL FROM 1 FOR 36)) = :I$REG_ID AND V2912.IS_DEL = 0
  INTO :OBJ_ID, :TYPE_ID, :MATCH_FIO;

  -- Затем по СНИЛС
  IF(OBJ_ID IS NULL AND I$SNILS IS NOT NULL) THEN
  SELECT FIRST 1 LPG.OBJ_ID, LPG.PARENT_TYPE_ID, 2
  FROM VALS V1409
  JOIN LINKS LPG ON LPG.OBJ_ID = V1409.OBJ_ID AND LPG.PARENT_TYPE_ID IN (290, 9, 187, 81, 82, 83) AND LPG.DATE_DEL IS NULL
  WHERE V1409.PARAM_ID = 1409 AND V1409.XVAL = :I$SNILS AND V1409.IS_DEL = 0
  INTO :OBJ_ID, :TYPE_ID, :MATCH_FIO;

  -- Затем по ФИО и дате рождения - некритическое
  IF(OBJ_ID IS NULL) THEN
  SELECT FIRST 1 LPG.OBJ_ID, LPG.PARENT_TYPE_ID, 1
  FROM VALS V55
  JOIN VALS V56 ON V56.OBJ_ID = V55.OBJ_ID AND V56.PARAM_ID = 56 AND V56.IS_DEL = 0 AND V56.XVAL = :I$NAME_FIRST
  LEFT JOIN VALS V57 ON V57.OBJ_ID = V55.OBJ_ID AND V57.PARAM_ID = 57 AND V57.IS_DEL = 0
  JOIN VALD V89 ON V89.OBJ_ID = V55.OBJ_ID AND V89.PARAM_ID = 89 AND V89.IS_DEL = 0 AND V89.VAL = :I$BIRTH_DATE
  JOIN LINKS LPG ON LPG.OBJ_ID = V55.OBJ_ID AND LPG.PARENT_TYPE_ID IN (290, 9, 187, 81, 82, 83) AND LPG.DATE_DEL IS NULL
  WHERE V55.PARAM_ID = 55 AND V55.XVAL = :I$NAME_LAST AND V55.IS_DEL = 0
    AND (V57.XVAL = :I$NAME_MID OR :I$NAME_MID IS NULL)
  INTO :OBJ_ID, :TYPE_ID, :MATCH_FIO;

  -- По номеру, дате и типу документа - некритическое
  IF(OBJ_ID IS NULL AND I$PASS_TYPE IS NOT NULL) THEN
  SELECT FIRST 1 LPG.OBJ_ID, LPG.PARENT_TYPE_ID, 1
  FROM VALS V559
  JOIN VALD V560 ON V560.OBJ_ID = V559.OBJ_ID AND V560.PARAM_ID = 560 AND V560.IS_DEL = 0 AND V560.VAL = :I$PASS_DATE
  JOIN VALL V441 ON V441.OBJ_ID = V559.OBJ_ID AND V441.PARAM_ID = 441 AND V441.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V441.LISTVAL_ID AND LV.TAG = CAST(:I$PASS_TYPE AS VARCHAR(20))
  JOIN LINKS LP10 ON LP10.OBJ_ID = V559.OBJ_ID AND LP10.PARENT_TYPE_ID = 10 AND LP10.DATE_DEL IS NULL
  JOIN LINKS LPG ON LPG.OBJ_ID = LP10.PARENT_ID AND LPG.PARENT_TYPE_ID IN (290, 9, 187, 81, 82, 83) AND LPG.DATE_DEL IS NULL
  WHERE V559.PARAM_ID = 559 AND V559.SVAL = :I$PASS_NUM AND V559.IS_DEL = 0
  INTO :OBJ_ID, :TYPE_ID, :MATCH_FIO;

  IF(OBJ_ID IS NOT NULL) THEN
  BEGIN
    IF(TYPE_ID = 290) THEN IS_EXIST = 1; -- уже есть в предварительном приеме
    ELSE IF(TYPE_ID IN (9, 187)) THEN IS_EXIST = 2; -- уже есть в классе
    ELSE IS_EXIST = 3; -- в выбывших
  END

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE RKS_ACCEPT_QUEUE (
    I$CLAIM_ID VARCHAR(40),
    I$REG_ID VARCHAR(100),
    I$STAGE VARCHAR(100),
    I$NAME_LAST VARCHAR(200),
    I$NAME_FIRST VARCHAR(200),
    I$NAME_MID VARCHAR(200),
    I$BIRTH_DATE DATE,
    I$SNILS VARCHAR(40),
    I$SEX VARCHAR(40),
    I$PASS_TYPE VARCHAR(100),
    I$PASS_SERIE VARCHAR(100),
    I$PASS_NUM VARCHAR(100),
    I$PASS_DATE DATE,
    I$PASS_ISSUER VARCHAR(1000),
    I$CITIZENSHIP VARCHAR(200),
    I$BIRTH_PLACE VARCHAR(200),
    I$REG_TYPE VARCHAR(40),
    I$REQUEST_DATE DATE,
    I$STUDY_YEAR INTEGER,
    I$BENEFIT_NAME VARCHAR(400),
    I$BENEFIT_NAME2 VARCHAR(400),
    I$USER_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT)
AS
DECLARE VARIABLE V$OU_ID BIGINT;
DECLARE VARIABLE V$STAGE_ID BIGINT;
DECLARE VARIABLE V$FOLDER_ID BIGINT;
DECLARE VARIABLE V$PARENT_TYPE BIGINT;
DECLARE VARIABLE S VARCHAR(400);
DECLARE VARIABLE SS VARCHAR(100);
DECLARE VARIABLE T BIGINT;
DECLARE VARIABLE V$SEX BIGINT;
DECLARE VARIABLE V$CITIZENSHIP BIGINT;
DECLARE VARIABLE V$REG BIGINT;
DECLARE VARIABLE V$PASS_ID BIGINT;
DECLARE VARIABLE V$PASS_TYPE BIGINT;
DECLARE VARIABLE V$STATUS VARCHAR(2);
DECLARE VARIABLE V$BN BIGINT;
begin

  V$STATUS = (SELECT STATUS FROM OU_LICENCE_TYPE);

  I$REG_ID = UPPER(I$REG_ID);
  IF(SUBSTRING(I$REG_ID FROM 1 FOR 1) = '{') THEN I$REG_ID = SUBSTRING(I$REG_ID FROM 2);
  IF(POSITION(':' IN I$REG_ID) > 0) THEN I$REG_ID = SUBSTRING(I$REG_ID FROM 1 FOR POSITION(':' IN I$REG_ID) - 1);

  -- Переформатируем СНИЛС, чтобы наверняка
  I$SNILS = REPLACE(REPLACE(I$SNILS, ' ', ''), '-', '');
  IF(CHAR_LENGTH(I$SNILS) = 11) THEN I$SNILS = SUBSTRING(I$SNILS FROM 1 FOR 3) || '-' || SUBSTRING(I$SNILS FROM 4 FOR 3) || '-' ||
    SUBSTRING(I$SNILS FROM 7 FOR 3) || ' ' || SUBSTRING(I$SNILS FROM 10 FOR 2);
  IF(I$SNILS IS NOT NULL AND EXISTS(SELECT 1 FROM CHECK_SNILS(:I$SNILS) WHERE IS_REAL = 0))
    THEN EXCEPTION DATA_ERROR 'Введенный СНИЛС некорректен';

  -- Не даем принимать по тому же заявлению
  SELECT FIRST 1 LPG.OBJ_ID, LPG.PARENT_TYPE_ID, ', по id заявления'
  FROM VALS V3349
  JOIN LINKS LPG ON LPG.OBJ_ID = V3349.OBJ_ID AND LPG.PARENT_TYPE_ID IN (290, 9, 187, 81, 82, 83) AND LPG.DATE_DEL IS NULL
  WHERE V3349.PARAM_ID = 3349 AND V3349.SVAL = :I$CLAIM_ID AND V3349.IS_DEL = 0
  INTO :OBJ_ID, :V$PARENT_TYPE, :SS;

  -- Если есть РегИД или СНИЛС - не позволяем зачислять повторно
  IF(OBJ_ID IS NULL AND I$REG_ID IS NOT NULL) THEN
  SELECT FIRST 1 LPG.OBJ_ID, LPG.PARENT_TYPE_ID, ', по РегИД'
  FROM VALS V2912
  JOIN LINKS LPG ON LPG.OBJ_ID = V2912.OBJ_ID AND LPG.PARENT_TYPE_ID IN (290, 9, 187, 81, 82, 83) AND LPG.DATE_DEL IS NULL
  WHERE V2912.PARAM_ID = 2912 AND UPPER(SUBSTRING(V2912.SVAL FROM 1 FOR 36)) = :I$REG_ID AND V2912.IS_DEL = 0
  INTO :OBJ_ID, :V$PARENT_TYPE, :SS;

  IF(OBJ_ID IS NULL AND I$SNILS IS NOT NULL) THEN
  SELECT FIRST 1 LPG.OBJ_ID, LPG.PARENT_TYPE_ID, ', по СНИЛС'
  FROM VALS V1409
  JOIN LINKS LPG ON LPG.OBJ_ID = V1409.OBJ_ID AND LPG.PARENT_TYPE_ID IN (290, 9, 187, 81, 82, 83) AND LPG.DATE_DEL IS NULL
  WHERE V1409.PARAM_ID = 1409 AND V1409.XVAL = :I$SNILS AND V1409.IS_DEL = 0
  INTO :OBJ_ID, :V$PARENT_TYPE, :SS;

  -- Не должно быть совпадения по идентифицирующему документу (номер и дата)
  IF(OBJ_ID IS NULL) THEN
  SELECT FIRST 1 LPG.OBJ_ID, LPG.PARENT_TYPE_ID, ', по номеру документа'
  FROM VALS V559
  JOIN VALD V560 ON V560.OBJ_ID = V559.OBJ_ID AND V560.PARAM_ID = 560 AND V560.IS_DEL = 0 AND V560.VAL = :I$PASS_DATE
  JOIN LINKS LP10 ON LP10.OBJ_ID = V559.OBJ_ID AND LP10.PARENT_TYPE_ID = 10 AND LP10.DATE_DEL IS NULL
  JOIN LINKS LPG ON LPG.OBJ_ID = LP10.PARENT_ID AND LPG.PARENT_TYPE_ID IN (290, 9, 187, 81, 82, 83) AND LPG.DATE_DEL IS NULL
  WHERE V559.PARAM_ID = 559 AND V559.SVAL = :I$PASS_NUM AND V559.IS_DEL = 0
  INTO :OBJ_ID, :V$PARENT_TYPE, :SS;

  IF(OBJ_ID IS NOT NULL) THEN
  BEGIN
    IF(V$PARENT_TYPE = 290) THEN S = 'Предварительный прием';
    ELSE IF(V$PARENT_TYPE = 9) THEN S = 'Действующий учебный коллектив';
    ELSE IF(V$PARENT_TYPE = 187) THEN S = 'Действующий класс-экстернат';
    ELSE S = 'Выбывшие';
    EXCEPTION DATA_ERROR 'Данный обучающийся уже внесен в систему (' || S || COALESCE(SS, '') || '). Повторное зачисление невозможно';
  END

  SELECT FIRST 1 L77.OBJ_ID
  FROM LINKS L2
  JOIN LINKS L77 ON L77.PARENT_ID = L2.OBJ_ID AND L77.OBJ_TYPE_ID = 77 AND L77.DATE_DEL IS NULL
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$OU_ID;

  IF(V$OU_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Объект ОУ или папка предварительного зачисления не найдены';

  -- Проверяем этап зачисления, создаем по необходимости
  -- Если этап указан цифрой - берем напрямую; если текстом - то берем дополнительно
  IF(V$STATUS = 'C') THEN
  BEGIN
    SELECT FIRST 1 LV.LISTVAL_ID
    FROM LISTVALS LV
    LEFT JOIN LISTVAL_TEXT(LV.LISTVAL_ID) C ON 1 = 1
    WHERE LV.LIST_ID = 25 AND LV.PARENT_ID = 2142 AND LV.IS_DEL = 0 AND C.VAL = :I$STAGE AND LV.LISTVAL_ID <> 13145
    INTO :V$STAGE_ID;

    IF(V$STAGE_ID IS NULL) THEN
    SELECT FIRST 1 LV.LISTVAL_ID
    FROM LISTVALS LV
    WHERE LV.LIST_ID = 25 AND LV.PARENT_ID = 2142 AND LV.IS_DEL = 0 AND LV.LISTVAL_ID <> 13145 AND CAST(CAST(LV.COST AS INTEGER) AS VARCHAR(100)) = :I$STAGE
    INTO :V$STAGE_ID;
  END
  ELSE
  BEGIN
    SELECT FIRST 1 LV.LISTVAL_ID
    FROM LISTVALS LV
    LEFT JOIN LISTVAL_TEXT(LV.LISTVAL_ID) C ON 1 = 1
    WHERE LV.LIST_ID = 25 AND LV.PARENT_ID IN (2141, 12941) AND LV.IS_DEL = 0 AND C.VAL = :I$STAGE
    INTO :V$STAGE_ID;

    IF(V$STAGE_ID IS NULL) THEN
    SELECT FIRST 1 LV.LISTVAL_ID
    FROM LISTVALS LV
    WHERE LV.LIST_ID = 25 AND LV.PARENT_ID = 2141 AND LV.IS_DEL = 0 AND CAST(CAST(LV.COST AS INTEGER) AS VARCHAR(100)) = :I$STAGE
    INTO :V$STAGE_ID;
  END

  IF(V$STAGE_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не удалось определить этап обучения';

  SELECT FIRST 1 L290.OBJ_ID
  FROM LINKS L290
  JOIN VALL V2346 ON V2346.OBJ_ID = L290.OBJ_ID AND V2346.PARAM_ID = 2346 AND V2346.IS_DEL = 0 AND V2346.LISTVAL_ID = :V$STAGE_ID
  WHERE L290.PARENT_ID = :V$OU_ID AND L290.OBJ_TYPE_ID = 290 AND L290.DATE_DEL IS NULL
  INTO :V$FOLDER_ID;

  IF(V$FOLDER_ID IS NULL) THEN
  BEGIN
    SELECT OBJ_ID FROM OBJECT_ADD(:V$OU_ID, 290, NULL, NULL, :I$USER_ID) INTO :V$FOLDER_ID;
    SELECT BLOB_ID FROM VAL_ADD(2346, :V$FOLDER_ID, :V$STAGE_ID) INTO :T;
  END

  -- Вносим данные
  SELECT OBJ_ID FROM OBJECT_ADD(:V$FOLDER_ID, 10, NULL, NULL, :I$USER_ID) INTO :OBJ_ID;
  SELECT BLOB_ID FROM VAL_ADD(55, :OBJ_ID, :I$NAME_LAST) INTO :T;
  SELECT BLOB_ID FROM VAL_ADD(56, :OBJ_ID, :I$NAME_FIRST) INTO :T;
  SELECT BLOB_ID FROM VAL_ADD(57, :OBJ_ID, :I$NAME_MID) INTO :T;
  SELECT BLOB_ID FROM VAL_ADD(89, :OBJ_ID, :I$BIRTH_DATE) INTO :T;
  SELECT BLOB_ID FROM VAL_ADD(2912, :OBJ_ID, :I$REG_ID) INTO :T;
  SELECT BLOB_ID FROM VAL_ADD(1409, :OBJ_ID, :I$SNILS) INTO :T;
  SELECT BLOB_ID FROM VAL_ADD(3349, :OBJ_ID, :I$CLAIM_ID) INTO :T;

  IF(I$SEX = 'Мужской') THEN V$SEX = 183;
  IF(I$SEX = 'Женский') THEN V$SEX = 182;
  SELECT BLOB_ID FROM VAL_ADD(88, :OBJ_ID, :V$SEX) INTO :T;

  SELECT BLOB_ID FROM VAL_ADD(1343, :OBJ_ID, :I$BIRTH_PLACE) INTO :T;

  I$CITIZENSHIP = UPPER(TRIM(REPLACE(I$CITIZENSHIP, '  ', '')));
  SELECT FIRST 1 LV.LISTVAL_ID
  FROM LISTVALS LV
  JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
  WHERE LV.LIST_ID = 146 AND LV.IS_DEL = 0 AND (LV.TAG = :I$CITIZENSHIP OR UPPER(R.VAL) = :I$CITIZENSHIP)
  INTO :V$CITIZENSHIP;
  SELECT BLOB_ID FROM VAL_ADD(91, :OBJ_ID, :V$CITIZENSHIP) INTO :T;

  IF(I$REG_TYPE = 'Постоянная') THEN V$REG = 1217;
  IF(I$REG_TYPE = 'Временная') THEN V$REG = 1218;
  SELECT BLOB_ID FROM VAL_ADD(108, :OBJ_ID, :V$REG) INTO :T;

  V$BN = NULL;
  I$BENEFIT_NAME = UPPER(I$BENEFIT_NAME);
  SELECT FIRST 1 LV.LISTVAL_ID
  FROM LISTVALS LV
  JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
  WHERE LV.LIST_ID = 375 AND LV.IS_DEL = 0 AND UPPER(R.VAL) = :I$BENEFIT_NAME
  INTO :V$BN;
  SELECT BLOB_ID FROM VAL_ADD(3593, :OBJ_ID, :V$BN) INTO :T;
  V$BN = NULL;
  I$BENEFIT_NAME2 = UPPER(I$BENEFIT_NAME2);
  SELECT FIRST 1 LV.LISTVAL_ID
  FROM LISTVALS LV
  JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
  WHERE LV.LIST_ID = 375 AND LV.IS_DEL = 0 AND UPPER(R.VAL) = :I$BENEFIT_NAME2
  INTO :V$BN;
  SELECT BLOB_ID FROM VAL_ADD(3594, :OBJ_ID, :V$BN) INTO :T;

  SELECT BLOB_ID FROM VAL_ADD(2738, :OBJ_ID, :I$REQUEST_DATE) INTO :T;

  -- Сами адреса вносим не тут, а внешним запросом уже после получения OBJ_ID

  -- Проверяем документы
  SELECT FIRST 1 LV.LISTVAL_ID
  FROM LISTVALS LV
  LEFT JOIN LISTVAL_TEXT(LV.LISTVAL_ID) C ON 1 = 1
  WHERE LV.LIST_ID = 143 AND C.VAL = :I$PASS_TYPE AND LV.IS_DEL = 0
  INTO :V$PASS_TYPE;

  IF(V$PASS_TYPE IS NOT NULL) THEN
  BEGIN

    SELECT FIRST 1 L79.OBJ_ID
    FROM LINKS L79
    JOIN VALL V441 ON V441.OBJ_ID = L79.OBJ_ID AND V441.PARAM_ID = 441 AND V441.IS_DEL = 0 AND V441.LISTVAL_ID = :V$PASS_TYPE
    JOIN VALS V559 ON V559.OBJ_ID = L79.OBJ_ID AND V559.PARAM_ID = 559 AND V559.IS_DEL = 0 AND UPPER(V559.SVAL) = UPPER(:I$PASS_NUM)
    JOIN VALD V560 ON V560.OBJ_ID = L79.OBJ_ID AND V560.PARAM_ID = 560 AND V560.IS_DEL = 0 AND V560.VAL = :I$PASS_DATE
    WHERE L79.PARENT_ID = :OBJ_ID AND L79.OBJ_TYPE_ID = 79 AND L79.DATE_DEL IS NULL
    INTO :V$PASS_ID;

    IF(V$PASS_ID IS NULL) THEN
    BEGIN
      SELECT OBJ_ID FROM OBJECT_ADD(:OBJ_ID, 79, NULL, NULL, :I$USER_ID) INTO :V$PASS_ID;
      SELECT BLOB_ID FROM VAL_ADD(441, :V$PASS_ID, :V$PASS_TYPE) INTO :T;
      SELECT BLOB_ID FROM VAL_ADD(442, :V$PASS_ID, :I$PASS_SERIE) INTO :T;
      SELECT BLOB_ID FROM VAL_ADD(559, :V$PASS_ID, :I$PASS_NUM) INTO :T;
      SELECT BLOB_ID FROM VAL_ADD(560, :V$PASS_ID, :I$PASS_DATE) INTO :T;
      SELECT BLOB_ID FROM VAL_ADD(562, :V$PASS_ID, :I$PASS_ISSUER) INTO :T;
    END

  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE RKS_ACCEPT_WARNING (
    I$REG_ID VARCHAR(100),
    I$OU_NAME VARCHAR(4000),
    I$OU_PHONE VARCHAR(400),
    I$OU_EMAIL VARCHAR(400),
    I$OU_AREA VARCHAR(100),
    I$GRADE_NAME VARCHAR(400))
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable T integer;
begin

  I$OU_NAME = COALESCE(I$OU_NAME, '???') || COALESCE(', ' || I$OU_PHONE, '') || COALESCE(', ' || I$OU_EMAIL, '') ||
    COALESCE(', ' || I$OU_AREA, '') || COALESCE(', ' || I$GRADE_NAME, '');

  I$REG_ID = UPPER(I$REG_ID);
  IF(SUBSTRING(I$REG_ID FROM 1 FOR 1) = '{') THEN I$REG_ID = SUBSTRING(I$REG_ID FROM 2);
  IF(POSITION(':' IN I$REG_ID) > 0) THEN I$REG_ID = SUBSTRING(I$REG_ID FROM 1 FOR POSITION(':' IN I$REG_ID) - 1);

  -- Обновляем только действующих персон
  SELECT FIRST 1 V2912.OBJ_ID
  FROM VALS V2912
  JOIN LINKS LP ON LP.OBJ_ID = V2912.OBJ_ID AND LP.PARENT_TYPE_ID IN (9, 187, 290) AND LP.DATE_DEL IS NULL
  WHERE V2912.PARAM_ID = 2912 AND UPPER(SUBSTRING(V2912.SVAL FROM 1 FOR 36)) = :I$REG_ID AND V2912.IS_DEL = 0
  INTO :OBJ_ID;

  IF(OBJ_ID IS NOT NULL) THEN
  BEGIN

    SELECT 1 FROM VAL_ADD(3446, :OBJ_ID, :I$OU_NAME) INTO :T;

    SUSPEND;

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE RKS_ACTIVE_PERSON_IDS RETURNS (
    OBJ_ID BIGINT)
AS
begin

  -- Функция потеряла актуальность ?

  FOR
    -- Ученики
    SELECT DISTINCT L10.OBJ_ID
    FROM LINKS L2
    JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 187) AND L9.DATE_DEL IS NULL
    JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    JOIN VALS V2912 ON V2912.OBJ_ID = L10.OBJ_ID AND V2912.PARAM_ID = 2912 AND V2912.IS_DEL = 0
    JOIN SYNC_LOG L ON L.PERSON_ID = L10.OBJ_ID AND L.VER_MSG IS NOT NULL
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    -- Предварительный прием ???
    -- Сотрудники
    UNION
    SELECT DISTINCT L14.OBJ_ID
    FROM LINKS L2
    JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
    JOIN VALS V2915 ON V2915.OBJ_ID = L14.OBJ_ID AND V2915.PARAM_ID = 2915 AND V2915.IS_DEL = 0
    JOIN SYNC_LOG L ON L.PERSON_ID = L14.OBJ_ID AND L.VER_MSG IS NOT NULL
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :OBJ_ID
  DO
  BEGIN
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE RKS_APPLY_PERSON (
    I$OBJ_ID BIGINT,
    I$STATUS INTEGER,
    I$REG_ID VARCHAR(100),
    I$MSG VARCHAR(1000))
AS
declare variable V$TMP bigint;
declare variable V$TYPE_ID bigint;
declare variable V$REG_PARAM_ID bigint;
declare variable V$REASON_PARAM_ID bigint;
declare variable V$OLD_REG varchar(100);
declare variable V$REASON_ID bigint;
declare variable V$OBJ_ID bigint;
declare variable V$OLD_STATE smallint;
declare variable V$MSG varchar(1000);
begin

  -- Сбрасываем причину изменения персональных данных
  -- код причины 0 (нет изменений) попасть сюда не может
  -- отрицательные коды = ошибка
  -- положительные коды = успешная смена статуса

  SELECT TYPE_ID
  FROM OBJECTS
  WHERE OBJ_ID = :I$OBJ_ID
  INTO :V$TYPE_ID;

  IF(V$TYPE_ID = 10) THEN
  BEGIN
      V$REG_PARAM_ID = 2912;
      V$REASON_PARAM_ID = 3006;
  END
  ELSE IF(V$TYPE_ID = 14) THEN
  BEGIN
      V$REG_PARAM_ID = 2915;
      V$REASON_PARAM_ID = 3007;
  END
  ELSE IF(V$TYPE_ID = 20) THEN
  BEGIN
      V$REG_PARAM_ID = 2917;
      V$REASON_PARAM_ID = 3008;
  END

  SELECT VR.VAL
  FROM VALS VR
  WHERE VR.OBJ_ID = :I$OBJ_ID AND VR.PARAM_ID = :V$REG_PARAM_ID AND VR.IS_DEL = 0
  INTO :V$OLD_REG;

  SELECT VR.LISTVAL_ID
  FROM VALL VR
  WHERE VR.OBJ_ID = :I$OBJ_ID AND VR.PARAM_ID = :V$REASON_PARAM_ID AND VR.IS_DEL = 0
  INTO :V$REASON_ID;

  -- Удаляем выданный ранее REG_ID, если он утрачен, и удаляем причину изменения
  IF(V$OLD_REG IS NOT NULL AND I$REG_ID IS NULL) THEN
  BEGIN
      UPDATE VALL
      SET IS_DEL = 1
      WHERE OBJ_ID = :I$OBJ_ID AND PARAM_ID = :V$REASON_PARAM_ID AND IS_DEL = 0;
      UPDATE VALS
      SET IS_DEL = 1
      WHERE OBJ_ID = :I$OBJ_ID AND PARAM_ID = :V$REG_PARAM_ID AND IS_DEL = 0;
  END
  -- Заменяем старый REG_ID на новый
  ELSE IF(V$OLD_REG <> I$REG_ID OR (V$OLD_REG IS NULL AND I$REG_ID IS NOT NULL)) THEN
  BEGIN
      SELECT BLOB_ID FROM VAL_ADD(:V$REG_PARAM_ID, :I$OBJ_ID, :I$REG_ID) INTO :V$TMP;
  END
  -- Удаляем REG_ID совсем, требуется перерегистрация
  -- как сюда вообще можно попасть, если REG_ID = null и пойдем по первой проверке ?
  ELSE IF(I$STATUS = -1) THEN
  BEGIN
      SELECT BLOB_ID FROM VAL_ADD(:V$REG_PARAM_ID, :I$OBJ_ID, '') INTO :V$TMP;
  END
  -- Персона как бы есть, но имеет место конфликт - ничего не исправляем, просто фиксируем сообщение
  ELSE IF(I$STATUS = -2) THEN
  BEGIN
  END

  -- Всегда затираем причину изменения
  IF(V$REASON_ID IS NOT NULL) THEN
  BEGIN
      UPDATE VALL
      SET IS_DEL = 1
      WHERE OBJ_ID = :I$OBJ_ID AND PARAM_ID = :V$REASON_PARAM_ID AND IS_DEL = 0;
  END

  -- Фиксируем статус
  SELECT FIRST 1 OBJ_ID, STATE_ID, MSG
  FROM SYNC_LOG
  WHERE PERSON_ID = :I$OBJ_ID
  INTO :V$OBJ_ID, :V$OLD_STATE, :V$MSG;

  IF(V$OBJ_ID IS NULL) THEN
  BEGIN
      INSERT INTO SYNC_LOG
      (PERSON_ID, STATE_ID, MSG)
      VALUES (:I$OBJ_ID, :I$STATUS, :I$MSG);
  END
  ELSE
  BEGIN
      UPDATE SYNC_LOG
      SET STATE_ID = :I$STATUS, MSG = :I$MSG, DATE_MODIFY = CURRENT_TIMESTAMP
      WHERE OBJ_ID = :V$OBJ_ID;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE RKS_APPLY_TIMEMARK (
    I$TM TIMESTAMP)
AS
declare variable V$ID bigint;
begin

  SELECT INFO_ID
  FROM INFO
  WHERE INFO_CODE = 'LAST_RKS_EXPORT'
  INTO :V$ID;

  IF(V$ID IS NULL) THEN
  BEGIN

    INSERT INTO INFO
    (INFO_CODE, INFO_NAME, INFO_VAL)
    VALUES ('LAST_RKS_EXPORT', 'LAST_RKS_EXPORT', :I$TM);

  END
  ELSE
  BEGIN

    UPDATE INFO
    SET INFO_VAL = :I$TM
    WHERE INFO_ID = :V$ID;

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE RKS_APPLY_WARNING (
    I$REG_ID VARCHAR(100),
    I$MSG VARCHAR(1000),
    I$OBJ_ID BIGINT = null)
RETURNS (
    OBJ_ID BIGINT)
AS
begin

  IF(I$OBJ_ID IS NOT NULL) THEN OBJ_ID = I$OBJ_ID;
  ELSE
  BEGIN
    SELECT FIRST 1 V.OBJ_ID
    FROM VALS V
    JOIN LINKS LP ON LP.OBJ_ID = V.OBJ_ID AND LP.PARENT_TYPE_ID IN (2, 211, 9, 187, 289, 290) AND LP.DATE_DEL IS NULL
    WHERE (V.PARAM_ID = 2912 OR V.PARAM_ID = 2915) AND V.SVAL = :I$REG_ID AND V.IS_DEL = 0
    INTO :OBJ_ID;
  END

  IF(I$MSG = 'null' OR I$MSG = '') THEN I$MSG = NULL;

  IF(OBJ_ID IS NOT NULL) THEN
  BEGIN
    IF(EXISTS(
      SELECT FIRST 1 1
      FROM SYNC_LOG L
      WHERE L.PERSON_ID = :OBJ_ID
    )) THEN
    BEGIN
      UPDATE SYNC_LOG SET VER_MSG = :I$MSG WHERE PERSON_ID = :OBJ_ID;
    END
    ELSE IF(I$MSG IS NOT NULL) THEN
    BEGIN
      INSERT INTO SYNC_LOG
      (PERSON_ID, STATE_ID, VER_MSG)
      VALUES (:OBJ_ID, 0, :I$MSG);
    END

    SUSPEND;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE RKS_DN_QUEUE (
    I$REG_ID VARCHAR(100) NOT NULL,
    I$REL_NAME VARCHAR(200) NOT NULL,
    I$PERSON_CODE VARCHAR(100) NOT NULL,
    I$REL_CODE VARCHAR(100) NOT NULL)
RETURNS (
    OBJ_ID BIGINT,
    REL_ID BIGINT)
AS
declare variable V$REL_CODE varchar(100);
declare variable V$EXT_ID bigint;
declare variable V$PERSON_CODE varchar(100);
declare variable V$REL_NAME varchar(400);
declare variable T integer;
declare variable P integer;
declare variable S1 varchar(100);
declare variable S2 varchar(100);
begin

  I$REG_ID = UPPER(I$REG_ID);
  IF(SUBSTRING(I$REG_ID FROM 1 FOR 1) = '{') THEN I$REG_ID = SUBSTRING(I$REG_ID FROM 2);
  IF(POSITION(':' IN I$REG_ID) > 0) THEN I$REG_ID = SUBSTRING(I$REG_ID FROM 1 FOR POSITION(':' IN I$REG_ID) - 1);

  -- Ищем ученика с нужным ID
  SELECT FIRST 1 V2912.OBJ_ID
  FROM VALS V2912
  JOIN LINKS LP ON LP.OBJ_ID = V2912.OBJ_ID AND LP.PARENT_TYPE_ID IN (9, 187, 290) AND LP.DATE_DEL IS NULL
  WHERE V2912.PARAM_ID = 2912 AND UPPER(SUBSTRING(V2912.SVAL FROM 1 FOR 36)) = :I$REG_ID AND V2912.IS_DEL = 0
  INTO :OBJ_ID;

  -- Не нашли ученика
  IF(OBJ_ID IS NULL) THEN EXIT;

  -- Есть ли родитель ?
  V$REL_NAME = REPLACE(REPLACE(REPLACE(UPPER(I$REL_NAME), 'Ё', 'Е'), '-', ''), ' ', '');

  SELECT FIRST 1 L20.OBJ_ID, L20.EXT_OBJ_ID, V155.VAL, V1570.VAL
  FROM LINKS L20
  LEFT JOIN VALS V1570 ON V1570.OBJ_ID = L20.EXT_OBJ_ID AND V1570.PARAM_ID = 1570 AND V1570.IS_DEL = 0
  LEFT JOIN VALS V155 ON V155.OBJ_ID = L20.OBJ_ID AND V155.PARAM_ID = 155 AND V155.IS_DEL = 0
  LEFT JOIN OBJECT_CAPTION_GET(L20.OBJ_ID) C ON 1 = 1
  WHERE L20.PARENT_ID = :OBJ_ID AND L20.OBJ_TYPE_ID = 20 AND L20.DATE_DEL IS NULL
    AND REPLACE(REPLACE(REPLACE(UPPER(C.CAPTION), 'Ё', 'Е'), '-', ''), ' ', '') = :V$REL_NAME
  INTO :REL_ID, :V$EXT_ID, :V$REL_CODE, :V$PERSON_CODE;

  -- Если не нашли родителя по ФИО, надо проверить по коду
  IF(REL_ID IS NULL) THEN
  BEGIN
    SELECT FIRST 1 L20.OBJ_ID, L20.EXT_OBJ_ID, V155.VAL, V1570.VAL
    FROM LINKS L20
    JOIN VALS V155 ON V155.OBJ_ID = L20.OBJ_ID AND V155.PARAM_ID = 155 AND V155.IS_DEL = 0 AND V155.SVAL = :I$REL_CODE
    LEFT JOIN VALS V1570 ON V1570.OBJ_ID = L20.EXT_OBJ_ID AND V1570.PARAM_ID = 1570 AND V1570.IS_DEL = 0
    WHERE L20.PARENT_ID = :OBJ_ID AND L20.OBJ_TYPE_ID = 20 AND L20.DATE_DEL IS NULL
    INTO :REL_ID, :V$EXT_ID, :V$REL_CODE, :V$PERSON_CODE;
  END

  -- На всякий случай проверяем, что у нас нет другого ученика, с новым PERSON_CODE
  IF(EXISTS(
    SELECT FIRST 1 1
    FROM VALS V1570
    JOIN LINKS LP10 ON LP10.EXT_OBJ_ID = V1570.OBJ_ID AND LP10.PARENT_TYPE_ID = 10 AND LP10.DATE_DEL IS NULL AND LP10.PARENT_ID <> :OBJ_ID
    JOIN LINKS LPG ON LPG.OBJ_ID = LP10.PARENT_ID AND LPG.PARENT_TYPE_ID IN (9, 187, 290, 81, 82, 83, 84) AND LPG.DATE_DEL IS NULL
    WHERE V1570.PARAM_ID = 1570 AND V1570.SVAL = :I$PERSON_CODE AND V1570.IS_DEL = 0
  ))
  THEN EXCEPTION DATA_ERROR 'В системе уже есть ученик с указанным кодом подключения';

  IF(REL_ID IS NULL) THEN
  BEGIN
    -- Добавляем родителя
    -- Пытаемся разделить ФИО ровно на три части. Все чему не повезло идет в отчество
    -- !!! Проверить, нет ли родителя с таким ФИО ?
    I$REL_NAME = TRIM(I$REL_NAME);
    P = POSITION(' ' IN I$REL_NAME);
    IF(P <= 0) THEN EXCEPTION DATA_ERROR 'Не удалось разложить ФИО представителя по компонентам';
    S1 = SUBSTRING(I$REL_NAME FROM 1 FOR P - 1);
    I$REL_NAME = SUBSTRING(I$REL_NAME FROM P + 1);
    P = POSITION(' ' IN I$REL_NAME);
    IF(P <= 0) THEN EXCEPTION DATA_ERROR 'Не удалось разложить ФИО представителя по компонентам';
    S2 = SUBSTRING(I$REL_NAME FROM 1 FOR P - 1);
    I$REL_NAME = SUBSTRING(I$REL_NAME FROM P + 1);

    SELECT OBJ_ID, EXT_OBJ_ID FROM OBJECT_ADD(:OBJ_ID, 20, NULL, NULL, NULL, 0, NULL, CURRENT_TIMESTAMP, 168) INTO :REL_ID, :V$EXT_ID;
    SELECT 1 FROM VAL_ADD(128, :REL_ID, :S1) INTO :T;
    SELECT 1 FROM VAL_ADD(129, :REL_ID, :S2) INTO :T;
    SELECT 1 FROM VAL_ADD(130, :REL_ID, :I$REL_NAME) INTO :T;
  END
  ELSE
  BEGIN
    -- Обновить родителя, ФИО не трогаем
  END

  SELECT 1 FROM VAL_ADD(155, :REL_ID, :I$REL_CODE) INTO :T;
  SELECT 1 FROM VAL_ADD(1570, :V$EXT_ID, :I$PERSON_CODE) INTO :T;

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE RKS_DO_EVENT (
    I$REG_ID VARCHAR(100),
    I$REC_ID VARCHAR(40),
    I$ORG_NAME VARCHAR(400),
    I$DATE_FROM DATE,
    I$DATE_TO DATE,
    I$STAGE_NAME VARCHAR(400),
    I$DO_NAME VARCHAR(400),
    I$TYPE_ID BIGINT,
    I$DIR_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$PERSON_ID bigint;
declare variable S varchar(1000);
declare variable T bigint;
begin

  I$REG_ID = UPPER(I$REG_ID);
  IF(SUBSTRING(I$REG_ID FROM 1 FOR 1) = '{') THEN I$REG_ID = SUBSTRING(I$REG_ID FROM 2);
  IF(POSITION(':' IN I$REG_ID) > 0) THEN I$REG_ID = SUBSTRING(I$REG_ID FROM 1 FOR POSITION(':' IN I$REG_ID) - 1);

  -- Обновляем только действующих персон
  SELECT FIRST 1 V2912.OBJ_ID
  FROM VALS V2912
  JOIN LINKS LP ON LP.OBJ_ID = V2912.OBJ_ID AND LP.PARENT_TYPE_ID IN (9, 187, 290) AND LP.DATE_DEL IS NULL
  WHERE V2912.PARAM_ID = 2912 AND UPPER(SUBSTRING(V2912.SVAL FROM 1 FOR 36)) = :I$REG_ID AND V2912.IS_DEL = 0
  INTO :V$PERSON_ID;

  IF(V$PERSON_ID IS NOT NULL) THEN
  BEGIN

    SELECT FIRST 1 L297.OBJ_ID
    FROM LINKS L297
    JOIN VALS V3188 ON V3188.OBJ_ID = L297.OBJ_ID AND V3188.PARAM_ID = 3188 AND V3188.IS_DEL = 0 AND V3188.SVAL = :I$REC_ID
    WHERE L297.PARENT_ID = :V$PERSON_ID AND L297.OBJ_TYPE_ID = 297 AND L297.DATE_DEL IS NULL
    INTO :OBJ_ID;

    S = COALESCE(I$DO_NAME, '');
    IF(CHAR_LENGTH(S) > 0 AND CHAR_LENGTH(I$STAGE_NAME) > 0) THEN S = S || ' - ' || I$STAGE_NAME;

    IF(OBJ_ID IS NULL) THEN
    BEGIN

      SELECT OBJ_ID FROM OBJECT_ADD(:V$PERSON_ID, 297) INTO :OBJ_ID;
      SELECT 1 FROM VAL_ADD(3188, :OBJ_ID, :I$REC_ID) INTO :T;
      SELECT 1 FROM VAL_ADD(3183, :OBJ_ID, :I$DATE_FROM) INTO :T;
      SELECT 1 FROM VAL_ADD(3184, :OBJ_ID, :I$DATE_TO) INTO :T;
      SELECT 1 FROM VAL_ADD(3187, :OBJ_ID, :I$ORG_NAME) INTO :T;
      SELECT 1 FROM VAL_ADD(3189, :OBJ_ID, :S) INTO :T;
      -- SELECT 1 FROM VAL_ADD(2392, :OBJ_ID, :I$TYPE_ID) INTO :T;
      SELECT 1 FROM VAL_ADD(2392, :OBJ_ID, :I$DIR_ID) INTO :T;

    END
    ELSE
    BEGIN

      SELECT 1 FROM VAL_ADD(3183, :OBJ_ID, :I$DATE_FROM) INTO :T;
      SELECT 1 FROM VAL_ADD(3184, :OBJ_ID, :I$DATE_TO) INTO :T;
      SELECT 1 FROM VAL_ADD(3187, :OBJ_ID, :I$ORG_NAME) INTO :T;
      SELECT 1 FROM VAL_ADD(3189, :OBJ_ID, :S) INTO :T;
      -- SELECT 1 FROM VAL_ADD(2392, :OBJ_ID, :I$TYPE_ID) INTO :T;
      SELECT 1 FROM VAL_ADD(2392, :OBJ_ID, :I$DIR_ID) INTO :T;

    END

  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE RKS_LIST_PERSONS (
    LEVEL_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    PERSON_FIO VARCHAR(1000),
    PERSON_TYPE_ID BIGINT,
    GRADE_NAME VARCHAR(1000))
AS
DECLARE VARIABLE V$SCHOOL_ID BIGINT;
DECLARE VARIABLE N INTEGER;
DECLARE VARIABLE V$STATUS VARCHAR(1);
begin

  SELECT L2.OBJ_ID
  FROM LINKS L2
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$SCHOOL_ID;

  V$STATUS = (SELECT STATUS FROM OU_LICENCE_TYPE);

  -- Сотрудники
  GRADE_NAME = 'Сотрудники';

  FOR
      -- Сама организация
      SELECT L14.OBJ_ID, C.CAPTION, L14.OBJ_TYPE_ID
      FROM LINKS L14
      -- Фильтр по сотрудникам, у кого не заполнен ID РК
      LEFT JOIN VALS V2915 ON V2915.OBJ_ID = L14.OBJ_ID AND V2915.PARAM_ID = 2915 AND V2915.IS_DEL = 0
      LEFT JOIN OBJECT_CAPTION_GET(L14.OBJ_ID) C ON 1 = 1
      WHERE L14.PARENT_ID = :V$SCHOOL_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL AND V2915.VAL IS NULL AND :LEVEL_ID = 14
      UNION
      -- Подразделения
      SELECT L14.OBJ_ID, C.CAPTION, L14.OBJ_TYPE_ID
      FROM LINKS L211
      JOIN LINKS L14 ON L14.PARENT_ID = L211.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
      -- Фильтр по сотрудникам, у кого не заполнен ID РК
      LEFT JOIN VALS V2915 ON V2915.OBJ_ID = L14.OBJ_ID AND V2915.PARAM_ID = 2915 AND V2915.IS_DEL = 0
      LEFT JOIN OBJECT_CAPTION_GET(L14.OBJ_ID) C ON 1 = 1
      WHERE L211.PARENT_ID = :V$SCHOOL_ID AND L211.OBJ_TYPE_ID = 211 AND L211.DATE_DEL IS NULL AND V2915.VAL IS NULL AND :LEVEL_ID = 14
      ORDER BY 2
      INTO :OBJ_ID, :PERSON_FIO, :PERSON_TYPE_ID
  DO
  BEGIN
      SUSPEND;
  END

  -- Действующие учащиеся
  FOR
      SELECT L10.OBJ_ID, C.CAPTION, L10.OBJ_TYPE_ID, CG.CAPTION
      FROM LINKS L7
      JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
      JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
      JOIN LISTVALS LV49 ON LV49.LISTVAL_ID = V49.LISTVAL_ID
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 125, 187) AND L9.DATE_DEL IS NULL
      JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      -- Фильтр по ученикам, у кого не заполнен ID РК
      LEFT JOIN VALS V2912 ON V2912.OBJ_ID = L10.OBJ_ID AND V2912.PARAM_ID = 2912 AND V2912.IS_DEL = 0
      LEFT JOIN OBJECT_CAPTION_GET(L10.OBJ_ID, 23) C ON 1 = 1
      LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) CG ON 1 = 1
      WHERE L7.PARENT_ID = :V$SCHOOL_ID AND L7.OBJ_TYPE_ID IN (7, 502) AND L7.DATE_DEL IS NULL AND V2912.VAL IS NULL AND :LEVEL_ID = 10
      ORDER BY LV49.SORT_ORDER, 4, 2
      INTO :OBJ_ID, :PERSON_FIO, :PERSON_TYPE_ID, :GRADE_NAME
  DO
  BEGIN
      SUSPEND;
  END

  -- Предварительный прием
  FOR
      SELECT L10.OBJ_ID, C.CAPTION, L10.OBJ_TYPE_ID, 'Предварительный прием: ' || CG.CAPTION
      FROM LINKS L77
      JOIN LINKS L290 ON L290.PARENT_ID = L77.OBJ_ID AND L290.OBJ_TYPE_ID = 290 AND L290.DATE_DEL IS NULL
      JOIN VALL V2346 ON V2346.OBJ_ID = L290.OBJ_ID AND V2346.PARAM_ID = 2346 AND V2346.IS_DEL = 0
      JOIN LISTVALS LV2346 ON LV2346.LISTVAL_ID = V2346.LISTVAL_ID
      JOIN LINKS L10 ON L10.PARENT_ID = L290.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      -- Фильтр по ученикам, у кого не заполнен ID РК
      LEFT JOIN VALS V2912 ON V2912.OBJ_ID = L10.OBJ_ID AND V2912.PARAM_ID = 2912 AND V2912.IS_DEL = 0
      LEFT JOIN OBJECT_CAPTION_GET(L10.OBJ_ID, 23) C ON 1 = 1
      LEFT JOIN OBJECT_CAPTION_GET(L290.OBJ_ID) CG ON 1 = 1
      WHERE L77.PARENT_ID = :V$SCHOOL_ID AND L77.OBJ_TYPE_ID = 77 AND L77.DATE_DEL IS NULL AND V2912.VAL IS NULL AND :LEVEL_ID = 10
      ORDER BY LV2346.SORT_ORDER, 4, 2
      INTO :OBJ_ID, :PERSON_FIO, :PERSON_TYPE_ID, :GRADE_NAME
  DO
  BEGIN
      SUSPEND;
  END

  -- Действующие учащиеся секции ДО, при этом не являющиеся штатными учениками ОУ
  -- новая схема для ДО 7 -> 46, даже не будем тип группы проверять
  -- сюда же добавляем ГПД (500 -> 46)
  FOR
      SELECT L10.OBJ_ID, C.CAPTION, L10.OBJ_TYPE_ID, CG.CAPTION
      FROM LINKS L86
      JOIN LINKS L46 ON L46.PARENT_ID = L86.OBJ_ID AND L46.OBJ_TYPE_ID = 46 AND L46.DATE_DEL IS NULL
      JOIN VALL V369 ON V369.OBJ_ID = L46.OBJ_ID AND V369.PARAM_ID = 369 AND V369.IS_DEL = 0 -- ГПД и так отсекутся - там дети только из числа учащихся
      JOIN LINKS L10 ON L10.PARENT_ID = L46.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      -- Фильтр по ученикам, у кого не заполнен ID РК
      LEFT JOIN VALS V2912 ON V2912.OBJ_ID = L10.OBJ_ID AND V2912.PARAM_ID = 2912 AND V2912.IS_DEL = 0
      LEFT JOIN OBJECT_CAPTION_GET(L10.OBJ_ID, 23) C ON 1 = 1
      LEFT JOIN OBJECT_CAPTION_GET(L46.OBJ_ID) CG ON 1 = 1
      -- Является ли действующим учащимся ?
      LEFT JOIN LINKS LP9 ON LP9.OBJ_ID = L10.OBJ_ID AND LP9.PARENT_TYPE_ID IN (9, 125, 187, 290) AND LP9.DATE_DEL IS NULL
      WHERE L86.PARENT_ID = :V$SCHOOL_ID AND L86.OBJ_TYPE_ID IN (86, 500, 7) AND L86.DATE_DEL IS NULL AND LP9.PARENT_ID IS NULL AND V2912.VAL IS NULL
        AND (:LEVEL_ID = 11 OR (:LEVEL_ID = 10 AND :V$STATUS = 'S'))
      ORDER BY 4, 2
      INTO :OBJ_ID, :PERSON_FIO, :PERSON_TYPE_ID, :GRADE_NAME
  DO
  BEGIN
      SUSPEND;
  END

  -- Родственники действующих учащихся, отмеченные как постоянные сопровождающие
  GRADE_NAME = 'Постоянные сопровождающие';
  FOR
      SELECT DISTINCT L20.OBJ_ID, C.CAPTION, L20.OBJ_TYPE_ID
      FROM LINKS L7
      JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
      JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
      JOIN LISTVALS LV49 ON LV49.LISTVAL_ID = V49.LISTVAL_ID
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 125, 187) AND L9.DATE_DEL IS NULL
      JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      JOIN LINKS L20 ON L20.PARENT_ID = L10.OBJ_ID AND L20.OBJ_TYPE_ID = 20 AND L20.DATE_DEL IS NULL
      -- Только постоянные сопровождающие
      JOIN VALL V2818 ON V2818.OBJ_ID = L20.OBJ_ID AND V2818.PARAM_ID = 2818 AND V2818.IS_DEL = 0 AND V2818.LISTVAL_ID = 2
      -- Фильтр по сопровождающим, у кого не заполнен ID РК
      LEFT JOIN VALS V2917 ON V2917.OBJ_ID = L20.OBJ_ID AND V2917.PARAM_ID = 2917 AND V2917.IS_DEL = 0
      LEFT JOIN OBJECT_CAPTION_GET(L20.OBJ_ID) C ON 1 = 1
      WHERE L7.PARENT_ID = :V$SCHOOL_ID AND L7.OBJ_TYPE_ID IN (7, 502) AND L7.DATE_DEL IS NULL AND V2917.VAL IS NULL AND :LEVEL_ID = 10
      ORDER BY LV49.SORT_ORDER, C.CAPTION
      INTO :OBJ_ID, :PERSON_FIO, :PERSON_TYPE_ID
  DO
  BEGIN
      -- Добавляем ФИО ребенка
      SELECT FIRST 1 :PERSON_FIO || ' (' || C.CAPTION || ')'
      FROM LINKS LP10
      LEFT JOIN OBJECT_CAPTION_GET(LP10.PARENT_ID) C ON 1 = 1
      WHERE LP10.OBJ_ID = :OBJ_ID AND LP10.PARENT_TYPE_ID = 10 AND LP10.DATE_DEL IS NULL
      INTO :PERSON_FIO;

      SUSPEND;
  END

  -- Родственники зачисляемых (пропускаем уже выведенных как родственники действующих учеников)
  FOR
      SELECT L20.OBJ_ID, C.CAPTION, L20.OBJ_TYPE_ID
      FROM LINKS L77
      JOIN LINKS L290 ON L290.PARENT_ID = L77.OBJ_ID AND L290.OBJ_TYPE_ID = 290 AND L290.DATE_DEL IS NULL
      JOIN VALL V2346 ON V2346.OBJ_ID = L290.OBJ_ID AND V2346.PARAM_ID = 2346 AND V2346.IS_DEL = 0
      JOIN LISTVALS LV2346 ON LV2346.LISTVAL_ID = V2346.LISTVAL_ID
      JOIN LINKS L10 ON L10.PARENT_ID = L290.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      JOIN LINKS L20 ON L20.PARENT_ID = L10.OBJ_ID AND L20.OBJ_TYPE_ID = 20 AND L20.DATE_DEL IS NULL
      -- Только постоянные сопровождающие
      JOIN VALL V2818 ON V2818.OBJ_ID = L20.OBJ_ID AND V2818.PARAM_ID = 2818 AND V2818.IS_DEL = 0 AND V2818.LISTVAL_ID = 2
      -- Фильтр по сопровождающим, у кого не заполнен ID РК
      LEFT JOIN VALS V2917 ON V2917.OBJ_ID = L20.OBJ_ID AND V2917.PARAM_ID = 2917 AND V2917.IS_DEL = 0
      LEFT JOIN OBJECT_CAPTION_GET(L10.OBJ_ID) C ON 1 = 1
      WHERE L77.PARENT_ID = :V$SCHOOL_ID AND L77.OBJ_TYPE_ID = 77 AND L77.DATE_DEL IS NULL AND V2917.VAL IS NULL AND :LEVEL_ID = 10
      ORDER BY LV2346.SORT_ORDER, 2
      INTO :OBJ_ID, :PERSON_FIO, :PERSON_TYPE_ID
  DO
  BEGIN
      N = 0;

      SELECT FIRST 1 1
      FROM LINKS LP10
      JOIN LINKS LP9 ON LP9.OBJ_ID = LP10.PARENT_ID AND LP9.PARENT_TYPE_ID IN (9, 125, 187) AND LP9.DATE_DEL IS NULL
      WHERE LP10.OBJ_ID = :OBJ_ID AND LP10.PARENT_TYPE_ID = 10 AND LP10.DATE_DEL IS NULL
      INTO :N;

      IF(N = 0) THEN
      BEGIN
          -- Добавляем ФИО ребенка
          SELECT FIRST 1 :PERSON_FIO || '(' || C.CAPTION || ')'
          FROM LINKS LP10
          LEFT JOIN OBJECT_CAPTION_GET(LP10.PARENT_ID) C ON 1 = 1
          WHERE LP10.OBJ_ID = :OBJ_ID AND LP10.PARENT_TYPE_ID = 10 AND LP10.DATE_DEL IS NULL
          INTO :PERSON_FIO;

          SUSPEND;
      END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE RKS_OD_EVENT (
    I$REG_ID VARCHAR(40),
    I$REC_ID VARCHAR(40),
    I$EVENT_DATE DATE,
    I$STAGE_ID BIGINT,
    I$LEVEL_ID SMALLINT,
    I$SUBJECT_ID BIGINT,
    I$PRE_VAL FLOAT,
    I$PRE_CUSTOM_VAL FLOAT,
    I$RES_VAL FLOAT,
    I$RES_CUSTOM_VAL FLOAT,
    I$RESULT_ID SMALLINT)
RETURNS (
    OBJ_ID BIGINT)
AS
DECLARE VARIABLE V$PERSON_ID BIGINT;
DECLARE VARIABLE V$LEVEL_ID BIGINT;
DECLARE VARIABLE V$RESULT_ID BIGINT;
DECLARE VARIABLE V$NAME VARCHAR(400);
DECLARE VARIABLE T BIGINT;
begin

  -- Актуальность процедуры утрачена, заменено на UT_EXAM_OLYMPIC_RES

  I$REG_ID = UPPER(I$REG_ID);
  IF(SUBSTRING(I$REG_ID FROM 1 FOR 1) = '{') THEN I$REG_ID = SUBSTRING(I$REG_ID FROM 2);
  IF(POSITION(':' IN I$REG_ID) > 0) THEN I$REG_ID = SUBSTRING(I$REG_ID FROM 1 FOR POSITION(':' IN I$REG_ID) - 1);

  -- Обновляем только действующих персон
  SELECT FIRST 1 V2912.OBJ_ID
  FROM VALS V2912
  JOIN LINKS LP ON LP.OBJ_ID = V2912.OBJ_ID AND LP.PARENT_TYPE_ID IN (9, 187, 290) AND LP.DATE_DEL IS NULL
  WHERE V2912.PARAM_ID = 2912 AND UPPER(SUBSTRING(V2912.SVAL FROM 1 FOR 36)) = :I$REG_ID AND V2912.IS_DEL = 0
  INTO :V$PERSON_ID;

  IF(V$PERSON_ID IS NOT NULL) THEN
  BEGIN

    SELECT FIRST 1 L22.OBJ_ID
    FROM LINKS L22
    JOIN VALS V2879 ON V2879.OBJ_ID = L22.OBJ_ID AND V2879.PARAM_ID = 2879 AND V2879.IS_DEL = 0 AND V2879.SVAL = :I$REC_ID
    WHERE L22.PARENT_ID = :V$PERSON_ID AND L22.OBJ_TYPE_ID = 22 AND L22.DATE_DEL IS NULL
    INTO :OBJ_ID;

    IF(I$SUBJECT_ID IS NULL) THEN V$NAME = 'Олимпиада (неизвестный предмет)';
    ELSE V$NAME = 'Олимпиада по ' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$SUBJECT_ID));

    IF(I$LEVEL_ID = 0) THEN V$LEVEL_ID = 5286;
    ELSE IF(I$LEVEL_ID = 1) THEN V$LEVEL_ID = 5288;
    ELSE IF(I$LEVEL_ID = 2) THEN V$LEVEL_ID = 5289;

    IF(I$RESULT_ID = 0) THEN V$RESULT_ID = 5281;
    ELSE IF(I$RESULT_ID = 1) THEN V$RESULT_ID = 5282;
    ELSE IF(I$RESULT_ID = 2) THEN V$RESULT_ID = 5283;

    IF(OBJ_ID IS NULL) THEN
    BEGIN

      SELECT OBJ_ID FROM OBJECT_ADD(:V$PERSON_ID, 22) INTO :OBJ_ID;
      SELECT 1 FROM VAL_ADD(2879, :OBJ_ID, :I$REC_ID) INTO :T;
      SELECT 1 FROM VAL_ADD(166, :OBJ_ID, :I$EVENT_DATE) INTO :T;
      SELECT 1 FROM VAL_ADD(1818, :OBJ_ID, :V$NAME) INTO :T;
      SELECT 1 FROM VAL_ADD(1819, :OBJ_ID, :V$LEVEL_ID) INTO :T;
      SELECT 1 FROM VAL_ADD(237, :OBJ_ID, :V$RESULT_ID) INTO :T;
      --SELECT 1 FROM VAL_ADD(167, :OBJ_ID, 'олимпиада') INTO :T;

    END
    ELSE
    BEGIN

      SELECT 1 FROM VAL_ADD(166, :OBJ_ID, :I$EVENT_DATE) INTO :T;
      SELECT 1 FROM VAL_ADD(1818, :OBJ_ID, :V$NAME) INTO :T;
      SELECT 1 FROM VAL_ADD(1819, :OBJ_ID, :V$LEVEL_ID) INTO :T;
      SELECT 1 FROM VAL_ADD(237, :OBJ_ID, :V$RESULT_ID) INTO :T;

    END

  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE RKS_OU_INFO RETURNS (
    OBJ_ID BIGINT,
    NAME_SHORT VARCHAR(1000),
    EMAIL VARCHAR(1000))
AS
begin

  SELECT FIRST 1 L2.OBJ_ID, V2.VAL, V35.VAL
  FROM LINKS L2
  LEFT JOIN VALS V2 ON V2.OBJ_ID = L2.OBJ_ID AND V2.PARAM_ID = 2 AND V2.IS_DEL = 0
  LEFT JOIN VALS V35 ON V35.OBJ_ID = L2.OBJ_ID AND V35.PARAM_ID = 35 AND V35.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :OBJ_ID, :NAME_SHORT, :EMAIL;

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE RKS_SAVE_PERSON_ID (
    PERSON_ID BIGINT,
    REG_ID VARCHAR(100),
    I$MODE SMALLINT = 0,
    I$STATUS SMALLINT = 0)
AS
declare variable TYPE_ID bigint;
declare variable PARAM_ID bigint;
declare variable TMP bigint;
declare variable V$OLD_ID varchar(100);
declare variable V$LD_STATUS bigint;
declare variable V$DUB_ID bigint;
begin

  -- Сохраняем только для уровня ОУ
  IF(NOT EXISTS(SELECT 1 FROM KEYS WHERE KEY_CODE = 'LEVEL' AND KEY_VAL = '1')) THEN EXIT;

  -- MODE: 0 = Параграф, 1 = реестр MG*
  -- смысл MODE утрачен

  -- STATUS: признак разрешения получения личного дела обучающегося
  -- 0 = неизвестно, 1 = разрешено, 2 = запрещено

  REG_ID = UPPER(REG_ID);

  SELECT TYPE_ID
  FROM OBJECTS
  WHERE OBJ_ID = :PERSON_ID
  INTO :TYPE_ID;

  IF(TYPE_ID = 10) THEN PARAM_ID = 2912;
  ELSE IF(TYPE_ID = 14) THEN PARAM_ID = 2915;
  ELSE IF(TYPE_ID = 20) THEN PARAM_ID = 2917;
  ELSE EXCEPTION DATA_ERROR 'Объект не является персоналией';

  -- Проверяем уникальность регID в пределах активных объектов одного типа
  -- !!! TODO разобраться в случае совпадения РегИД и различия персональных данных в парах сотрудник-ученик, сотрудник-родитель
  SELECT FIRST 1 V.OBJ_ID
  FROM VALS V
  JOIN LINKS LP ON LP.OBJ_ID = V.OBJ_ID AND LP.PARENT_TYPE_ID IN (10, 2, 211, 9, 187, 125, 46, 290, 81, 82, 83, 84, 289) AND LP.DATE_DEL IS NULL
  WHERE V.PARAM_ID = :PARAM_ID AND UPPER(SUBSTRING(V.SVAL FROM 1 FOR 36)) = :REG_ID AND V.IS_DEL = 0
  INTO :V$DUB_ID;

  IF(V$DUB_ID IS NOT NULL) THEN
    EXCEPTION DATA_ERROR 'Критическая ошибка: дублирование РегИД у персон одного типа, конфликт с ' ||
      (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$DUB_ID));

  -- Если регID изменился - записываем новое значение
  SELECT VAL
  FROM VALS
  WHERE OBJ_ID = :PERSON_ID AND PARAM_ID = :PARAM_ID AND IS_DEL = 0
  INTO :V$OLD_ID;

  IF(COALESCE(V$OLD_ID, '') <> COALESCE(REG_ID, '')) THEN
  BEGIN
      SELECT BLOB_ID FROM VAL_ADD(:PARAM_ID, :PERSON_ID, :REG_ID) INTO :TMP;
  END

  IF(TYPE_ID = 10) THEN
  BEGIN
    SELECT FIRST 1 V3447.LISTVAL_ID
    FROM VALL V3447
    WHERE V3447.OBJ_ID = :PERSON_ID AND V3447.PARAM_ID = 3447 AND V3447.IS_DEL = 0
    INTO :V$LD_STATUS;

    -- По-умолчанию - статус личного дела неизвестен
    IF(I$STATUS = 0) THEN
    BEGIN
      IF(V$LD_STATUS IS NULL) THEN
      BEGIN
        -- Ставим статус = неизвестно
        SELECT 1 FROM VAL_ADD(3447, :PERSON_ID, 14297) INTO :V$OLD_ID;
      END
    END
    -- Разрешено блокирование личного дела
    ELSE IF(I$STATUS = 1) THEN
    BEGIN
      IF(V$LD_STATUS IS NULL OR V$LD_STATUS <> 14298) THEN
      BEGIN
        -- Фиксируем что личное дело у нас
        -- сами данные личного дела должны быть разобраны в той же транзакции
        SELECT 1 FROM VAL_ADD(3447, :PERSON_ID, 14298) INTO :V$OLD_ID;
      END
    END
    -- Запрет личного дела
    ELSE IF(I$STATUS = 2) THEN
    BEGIN
      IF(V$LD_STATUS IS NULL OR V$LD_STATUS IN (14298, 14299)) THEN
      BEGIN
        -- Ставим статус = неизвестно
        SELECT 1 FROM VAL_ADD(3447, :PERSON_ID, 14297) INTO :V$OLD_ID;
      END
    END
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE RKS_SAVE_ULS (
    I$REG_ID VARCHAR(100),
    I$VAL VARCHAR(100))
RETURNS (
    OBJ_ID BIGINT,
    TYPE_ID BIGINT)
AS
declare variable T integer;
begin

  I$REG_ID = UPPER(I$REG_ID);
  IF(SUBSTRING(I$REG_ID FROM 1 FOR 1) = '{') THEN I$REG_ID = SUBSTRING(I$REG_ID FROM 2);
  IF(POSITION(':' IN I$REG_ID) > 0) THEN I$REG_ID = SUBSTRING(I$REG_ID FROM 1 FOR POSITION(':' IN I$REG_ID) - 1);

  FOR
    SELECT V2912.OBJ_ID, LP.OBJ_TYPE_ID
    FROM VALS V2912
    JOIN LINKS LP ON LP.OBJ_ID = V2912.OBJ_ID AND LP.PARENT_TYPE_ID IN (9, 187, 290) AND LP.DATE_DEL IS NULL
    WHERE V2912.PARAM_ID = 2912 AND UPPER(SUBSTRING(V2912.SVAL FROM 1 FOR 36)) = :I$REG_ID AND V2912.IS_DEL = 0
    INTO :OBJ_ID, :TYPE_ID
  DO
  BEGIN
    SELECT 1 FROM VAL_ADD(3482, :OBJ_ID, :I$VAL) INTO :T;
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE RKS_SERIALIZE (
    I$OBJ_ID BIGINT,
    I$MODE SMALLINT = 0,
    I$EXCEPT SMALLINT NOT NULL = 1)
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$OU_LICENCE_TYPE CHAR(1);
DECLARE VARIABLE V$TYPE BIGINT;
DECLARE VARIABLE V$ORG_ID BIGINT;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$TYPE_ID BIGINT;
DECLARE VARIABLE V$S VARCHAR(1000);
DECLARE VARIABLE V$D1 DATE;
DECLARE VARIABLE V$D2 DATE;
DECLARE VARIABLE V$REF_ID BIGINT;
DECLARE VARIABLE V$JOB_ID BIGINT;
DECLARE VARIABLE V$MOVE_TYPE BIGINT;
DECLARE VARIABLE V$GROUP_TYPE BIGINT;
DECLARE VARIABLE V$NAME VARCHAR(1000);
DECLARE VARIABLE V$GRADE_ID BIGINT;
DECLARE VARIABLE V$REG_ID VARCHAR(100);
DECLARE VARIABLE V$PERSON_ID BIGINT;
DECLARE VARIABLE V$REASON1 BIGINT;
DECLARE VARIABLE V$REASON2 BIGINT;
DECLARE VARIABLE V$SUBJECT_ID BIGINT;
DECLARE VARIABLE V$STAGE_ID BIGINT;
DECLARE VARIABLE V$TEACHER_ID BIGINT;
DECLARE VARIABLE V$YEAR_ID BIGINT;
DECLARE VARIABLE V$MARKTYPE_ID BIGINT;
DECLARE VARIABLE V$MARKVAL_ID BIGINT;
DECLARE VARIABLE V$USERTYPE INTEGER;
DECLARE VARIABLE V$PREV_MOVE BIGINT;
DECLARE VARIABLE V$PREV_GID BIGINT;
DECLARE VARIABLE V$PREV_STAGE BIGINT;
DECLARE VARIABLE V$PREV_GT BIGINT;
DECLARE VARIABLE V$PREV_MT BIGINT;
DECLARE VARIABLE V$SRC1 BIGINT;
DECLARE VARIABLE V$SRC2 BIGINT;
DECLARE VARIABLE V$S1 VARCHAR(1000);
DECLARE VARIABLE V$S2 VARCHAR(1000);
DECLARE VARIABLE V$QUAL VARCHAR(1000);
DECLARE VARIABLE V$LD_STATUS BIGINT;
DECLARE VARIABLE V$DT TIMESTAMP;
DECLARE VARIABLE V$MDT TIMESTAMP;
DECLARE VARIABLE V$LEVEL_ID BIGINT;
begin

  -- Заменяет две функции из RKS_GET_xxx
  -- I$MODE: 0 = из Параграфа, 1 = реестр MG* (в этом случае будет ограниченный функционал)
  -- смысл MODE утрачен

  V$OU_LICENCE_TYPE = (SELECT STATUS FROM OU_LICENCE_TYPE);

  SELECT D.TYPE_ID
  FROM OBJECTS D
  WHERE D.OBJ_ID = :I$OBJ_ID
  INTO :V$TYPE;

  IF(V$TYPE IS NULL) THEN EXCEPTION DATA_ERROR 'Объект не найден: ' || COALESCE(I$OBJ_ID, '-');

  -- Ищем организацию среди возможных родителей персоны - в том числе по удаленным веткам
  -- Классы и группы, ОДОД в отделах
  SELECT FIRST 1 LP2.PARENT_ID
  FROM LINKS LPG
  JOIN LINKS LP8 ON LP8.OBJ_ID = LPG.PARENT_ID AND LP8.PARENT_TYPE_ID IN (8, 242)
  JOIN LINKS LP7 ON LP7.OBJ_ID = LP8.PARENT_ID AND LP7.PARENT_TYPE_ID IN (7, 211)
  JOIN LINKS LP2 ON LP2.OBJ_ID = LP7.PARENT_ID AND LP2.PARENT_TYPE_ID = 2
  WHERE LPG.OBJ_ID = :I$OBJ_ID AND LPG.PARENT_TYPE_ID IN (9, 187, 243)
  INTO :V$ORG_ID;

  -- Выбывшие, окончившие, предварительный прием, кружки, ОДОД, академический отпуск
  IF(V$ORG_ID IS NULL) THEN
  SELECT FIRST 1 LP2.PARENT_ID
  FROM LINKS LPG
  JOIN LINKS LPGG ON LPGG.OBJ_ID = LPG.PARENT_ID AND LPGG.PARENT_TYPE_ID IN (78, 77, 86, 242, 7)
  JOIN LINKS LP2 ON LP2.OBJ_ID = LPGG.PARENT_ID AND LP2.PARENT_TYPE_ID = 2
  WHERE LPG.OBJ_ID = :I$OBJ_ID AND LPG.PARENT_TYPE_ID IN (289, 290, 81, 82, 83, 46, 243)
  INTO :V$ORG_ID;

  -- Сотрудники
  IF(V$ORG_ID IS NULL) THEN
  SELECT FIRST 1 LP2.PARENT_ID
  FROM LINKS LP2
  WHERE LP2.OBJ_ID = :I$OBJ_ID AND LP2.PARENT_TYPE_ID = 2
  INTO :V$ORG_ID;

  -- Уволенные, сотрудники отделов
  IF(V$ORG_ID IS NULL) THEN
  SELECT FIRST 1 LP2.PARENT_ID
  FROM LINKS LPG
  JOIN LINKS LP2 ON LP2.OBJ_ID = LPG.PARENT_ID AND LP2.PARENT_TYPE_ID = 2
  WHERE LPG.OBJ_ID = :I$OBJ_ID AND LPG.PARENT_TYPE_ID IN (84, 211)
  INTO :V$ORG_ID;

  -- Постоянные сопровождающие действующих учеников
  IF(V$ORG_ID IS NULL) THEN
  SELECT FIRST 1 LP2.PARENT_ID
  FROM LINKS LP10
  JOIN LINKS LP9 ON LP9.OBJ_ID = LP10.PARENT_ID AND LP9.PARENT_TYPE_ID IN (9, 187, 243)
  JOIN LINKS LP8 ON LP8.OBJ_ID = LP9.PARENT_ID AND LP8.PARENT_TYPE_ID IN (8, 242)
  JOIN LINKS LP7 ON LP7.OBJ_ID = LP8.PARENT_ID AND LP7.PARENT_TYPE_ID IN (7, 211)
  JOIN LINKS LP2 ON LP2.OBJ_ID = LP7.PARENT_ID AND LP2.PARENT_TYPE_ID = 2
  WHERE LP10.OBJ_ID = :I$OBJ_ID AND LP10.PARENT_TYPE_ID = 10
  INTO :V$ORG_ID;

  -- Постоянные сопровождающие выбывших учеников и предварительного приема
  IF(V$ORG_ID IS NULL) THEN
  SELECT FIRST 1 LP2.PARENT_ID
  FROM LINKS LP10
  JOIN LINKS LPG ON LPG.OBJ_ID = LP10.PARENT_ID AND LPG.PARENT_TYPE_ID IN (290, 81, 82, 83, 46, 243)
  JOIN LINKS LPGG ON LPGG.OBJ_ID = LPG.PARENT_ID AND LPGG.PARENT_TYPE_ID IN (78, 77, 86, 242)
  JOIN LINKS LP2 ON LP2.OBJ_ID = LPGG.PARENT_ID AND LP2.PARENT_TYPE_ID = 2
  WHERE LP10.OBJ_ID = :I$OBJ_ID AND LP10.PARENT_TYPE_ID = 10
  INTO :V$ORG_ID;

  IF(V$ORG_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Образовательная организация не идентифицирована для ' || COALESCE(I$OBJ_ID, '?');

  TAG_NAME = 'person_id';
  VAL = I$OBJ_ID;
  SUSPEND;

  TAG_NAME = 'org_id';
  VAL = V$ORG_ID;
  SUSPEND;

  TAG_NAME = 'reason';
  VAL = NULL;
  SELECT LISTVAL_ID
  FROM VALL
  WHERE OBJ_ID = :I$OBJ_ID AND PARAM_ID IN (3006, 3007, 3008) AND IS_DEL = 0
  INTO :VAL;
  IF(VAL = '12913') THEN VAL = '0';
  IF(VAL = '12914') THEN VAL = '1';
  IF(VAL = '12915') THEN VAL = '2';
  SUSPEND;

  TAG_NAME = 'type_id';
  VAL = V$TYPE;
  SUSPEND;

  TAG_NAME = 'name_last';
  VAL = NULL;
  SELECT VAL
  FROM VALS
  WHERE OBJ_ID = :I$OBJ_ID AND IS_DEL = 0 AND PARAM_ID = IIF(:V$TYPE = 10, 55, IIF(:V$TYPE = 14, 59, 128))
  INTO :VAL;
  IF(VAL IS NULL) THEN EXCEPTION DATA_ERROR 'Отсутствует фамилия';
  SUSPEND;

  TAG_NAME = 'name_first';
  VAL = NULL;
  SELECT VAL
  FROM VALS
  WHERE OBJ_ID = :I$OBJ_ID AND IS_DEL = 0 AND PARAM_ID = IIF(:V$TYPE = 10, 56, IIF(:V$TYPE = 14, 60, 129))
  INTO :VAL;
  IF(VAL IS NULL) THEN EXCEPTION DATA_ERROR 'Отсутствует имя';
  SUSPEND;

  TAG_NAME = 'name_mid';
  VAL = NULL;
  SELECT VAL
  FROM VALS
  WHERE OBJ_ID = :I$OBJ_ID AND IS_DEL = 0 AND PARAM_ID = IIF(:V$TYPE = 10, 57, IIF(:V$TYPE = 14, 61, 130))
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'birth_date';
  VAL = NULL;
  SELECT V.VAL
  FROM VALD D
  LEFT JOIN DATE2ISO(D.VAL, 0) V ON 1 = 1
  WHERE D.OBJ_ID = :I$OBJ_ID AND D.IS_DEL = 0 AND PARAM_ID = IIF(:V$TYPE = 10, 89, IIF(:V$TYPE = 14, 241, 143))
  INTO :VAL;
  IF(VAL IS NULL) THEN EXCEPTION DATA_ERROR 'Отсутствует дата рождения';
  SUSPEND;

  TAG_NAME = 'snils';
  VAL = NULL;
  SELECT VAL
  FROM VALS
  WHERE OBJ_ID = :I$OBJ_ID AND IS_DEL = 0 AND PARAM_ID = IIF(:V$TYPE = 10, 1409, IIF(:V$TYPE = 14, 2455, 2365))
  INTO :VAL;
  IF(VAL IS NOT NULL) THEN
  BEGIN
    VAL = REPLACE(VAL, ' ', '');
    VAL = REPLACE(VAL, '-', '');
    VAL = REPLACE(VAL, '=', '');
    VAL = REPLACE(VAL, '.', '');
    VAL = REPLACE(VAL, ',', '');
  END
  SUSPEND;

  TAG_NAME = 'sex';
  VAL = NULL;
  SELECT IIF(LISTVAL_ID = 183, 0, 1)
  FROM VALL
  WHERE OBJ_ID = :I$OBJ_ID AND IS_DEL = 0 AND PARAM_ID = IIF(:V$TYPE = 10, 88, IIF(:V$TYPE = 14, 239, 2544))
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'reg_id';
  VAL = NULL;
  SELECT VAL
  FROM VALS
  WHERE OBJ_ID = :I$OBJ_ID AND IS_DEL = 0 AND PARAM_ID = IIF(:V$TYPE = 10, 2912, IIF(:V$TYPE = 14, 2915, 2917))
  INTO :V$REG_ID;
  VAL = V$REG_ID;
  SUSPEND;

  TAG_NAME = 'claim_id';
  VAL = NULL;
  SELECT VAL
  FROM VALS
  WHERE OBJ_ID = :I$OBJ_ID AND PARAM_ID IN (3349) AND IS_DEL = 0
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'uls';
  VAL = NULL;
  SELECT VAL
  FROM VALS
  WHERE OBJ_ID = :I$OBJ_ID AND PARAM_ID IN (3482) AND IS_DEL = 0
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'esia';
  VAL = NULL;
  SELECT VAL
  FROM VALS
  WHERE OBJ_ID = :I$OBJ_ID AND PARAM_ID IN (3060, 3141, 3061) AND IS_DEL = 0
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'addr_reg';
  VAL = NULL;
  V$S = NULL;
  IF(V$TYPE = 10) THEN SELECT VAL, HOUSEGUID FROM ADR_GET(111, :I$OBJ_ID) INTO :VAL, :V$S;
  ELSE IF(V$TYPE = 14) THEN SELECT VAL, HOUSEGUID FROM ADR_GET(262, :I$OBJ_ID) INTO :VAL, :V$S;
  ELSE IF(V$TYPE = 20) THEN SELECT VAL, HOUSEGUID FROM ADR_GET(1561, :I$OBJ_ID) INTO :VAL, :V$S;
  SUSPEND;

  TAG_NAME = 'addr_reg_id';
  VAL = V$S;
  SUSPEND;

  TAG_NAME = 'addr_fact';
  VAL = NULL;
  V$S = NULL;
  IF(V$TYPE = 10) THEN SELECT VAL, HOUSEGUID FROM ADR_GET(103, :I$OBJ_ID) INTO :VAL, :V$S;
  ELSE IF(V$TYPE = 14) THEN SELECT VAL, HOUSEGUID FROM ADR_GET(255, :I$OBJ_ID) INTO :VAL, :V$S;
  ELSE IF(V$TYPE = 20) THEN SELECT VAL, HOUSEGUID FROM ADR_GET(147, :I$OBJ_ID) INTO :VAL, :V$S;
  SUSPEND;

  TAG_NAME = 'addr_fact_id';
  VAL = V$S;
  SUSPEND;

  TAG_NAME = 'birth_place';
  VAL = NULL;
  SELECT VAL
  FROM VALS
  WHERE OBJ_ID = :I$OBJ_ID AND PARAM_ID IN (1343, 244, 2543) AND IS_DEL = 0
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'citizenship';
  VAL = NULL;
  SELECT LISTVAL_ID
  FROM VALL
  WHERE OBJ_ID = :I$OBJ_ID AND PARAM_ID IN (91, 243, 1559) AND IS_DEL = 0
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'rddm_first';
  VAL = NULL;
  SELECT IIF(LISTVAL_ID = 2, 1, 0)
  FROM VALL
  WHERE OBJ_ID = :I$OBJ_ID AND PARAM_ID IN (3358) AND IS_DEL = 0
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'username';
  VAL = NULL;
  SELECT U.USER_NAME, U.PWD, U.USER_TYPE
  FROM USERS U
  WHERE U.OBJ_ID = :I$OBJ_ID AND U.DATE_DEL IS NULL
  INTO :VAL, :V$NAME, :V$USERTYPE;
  SUSPEND;

  TAG_NAME = 'pwd';
  VAL = V$NAME;
  SUSPEND;

  TAG_NAME = 'usertype';
  VAL = V$USERTYPE;
  SUSPEND;

  -- Идентифицирующие документы - выбираем для всех персон с данным ID
  -- При начальной выдаче id - только по самой указанной персоне
  TAG_NAME = 'documents::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT DISTINCT L79.OBJ_ID, LV441.TAG
    FROM VALS VG
    -- тут могут быть дубли
    JOIN LINKS LPG ON LPG.OBJ_ID = VG.OBJ_ID AND LPG.PARENT_TYPE_ID IN (9, 46, 187, 2, 211, 81, 82, 83, 84, 289, 290) AND LPG.DATE_DEL IS NULL
    -- сами документы
    JOIN LINKS L79 ON L79.PARENT_ID = LPG.OBJ_ID AND L79.OBJ_TYPE_ID = 79 AND L79.DATE_DEL IS NULL
    JOIN VALL V441 ON V441.OBJ_ID = L79.OBJ_ID AND V441.PARAM_ID = 441 AND V441.IS_DEL = 0
    JOIN LISTVALS LV441 ON LV441.LISTVAL_ID = V441.LISTVAL_ID AND LV441.TAG <> ''
    LEFT JOIN VALS V559 ON V559.OBJ_ID = L79.OBJ_ID AND V559.PARAM_ID = 559 AND V559.IS_DEL = 0
    LEFT JOIN VALD V560 ON V560.OBJ_ID = L79.OBJ_ID AND V560.PARAM_ID = 560 AND V560.IS_DEL = 0
    LEFT JOIN VALS V562 ON V562.OBJ_ID = L79.OBJ_ID AND V562.PARAM_ID = 562 AND V562.IS_DEL = 0
    LEFT JOIN VALL V614 ON V614.OBJ_ID = L79.OBJ_ID AND V614.PARAM_ID = 614 AND V614.IS_DEL = 0
    WHERE VG.PARAM_ID IN (2912, 2915, 2917) AND VG.IS_DEL = 0 AND VG.SVAL = :V$REG_ID AND :V$REG_ID IS NOT NULL
    -- !!! в перспективе убрать фильтр
    AND (:I$EXCEPT = 1 OR (V559.VAL IS NOT NULL AND V560.VAL IS NOT NULL AND V562.VAL IS NOT NULL AND V614.LISTVAL_ID IS NOT NULL))
    UNION
    SELECT DISTINCT L79.OBJ_ID, LV441.TAG
    FROM OBJECTS LPG
    -- сами документы
    JOIN LINKS L79 ON L79.PARENT_ID = LPG.OBJ_ID AND L79.OBJ_TYPE_ID = 79 AND L79.DATE_DEL IS NULL
    JOIN VALL V441 ON V441.OBJ_ID = L79.OBJ_ID AND V441.PARAM_ID = 441 AND V441.IS_DEL = 0
    JOIN LISTVALS LV441 ON LV441.LISTVAL_ID = V441.LISTVAL_ID AND LV441.TAG <> ''
    LEFT JOIN VALS V559 ON V559.OBJ_ID = L79.OBJ_ID AND V559.PARAM_ID = 559 AND V559.IS_DEL = 0
    LEFT JOIN VALD V560 ON V560.OBJ_ID = L79.OBJ_ID AND V560.PARAM_ID = 560 AND V560.IS_DEL = 0
    LEFT JOIN VALS V562 ON V562.OBJ_ID = L79.OBJ_ID AND V562.PARAM_ID = 562 AND V562.IS_DEL = 0
    LEFT JOIN VALL V614 ON V614.OBJ_ID = L79.OBJ_ID AND V614.PARAM_ID = 614 AND V614.IS_DEL = 0
    WHERE :V$REG_ID IS NULL AND LPG.OBJ_ID = :I$OBJ_ID
    -- !!! в перспективе убрать фильтр
    AND (:I$EXCEPT = 1 OR (V559.VAL IS NOT NULL AND V560.VAL IS NOT NULL AND V562.VAL IS NOT NULL AND V614.LISTVAL_ID IS NOT NULL))
    INTO :V$OBJ_ID, :V$S
  DO
  BEGIN
    TAG_NAME = 'documents:document';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'documents:document:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'documents:document:type';
    VAL = V$S;
    SUSPEND;
    TAG_NAME = 'documents:document:serie';
    VAL = NULL;
    SELECT V.VAL
    FROM VALS V
    WHERE V.OBJ_ID = :V$OBJ_ID AND V.PARAM_ID = 442 AND V.IS_DEL = 0
    INTO :VAL;
    SUSPEND;
    TAG_NAME = 'documents:document:number';
    VAL = NULL;
    SELECT V.VAL
    FROM VALS V
    WHERE V.OBJ_ID = :V$OBJ_ID AND V.PARAM_ID = 559 AND V.IS_DEL = 0
    INTO :VAL;
    IF(VAL IS NULL) THEN EXCEPTION DATA_ERROR 'Не указан номер документа';
    SUSPEND;
    TAG_NAME = 'documents:document:issue_date';
    VAL = NULL;
    SELECT D.VAL
    FROM VALD V
    LEFT JOIN DATE2ISO(V.VAL, 0) D ON 1 = 1
    WHERE V.OBJ_ID = :V$OBJ_ID AND V.PARAM_ID = 560 AND V.IS_DEL = 0
    INTO :VAL;
    IF(VAL IS NULL) THEN EXCEPTION DATA_ERROR 'Не указана дата выдачи документа';
    SUSPEND;
    TAG_NAME = 'documents:document:expire_date';
    VAL = NULL;
    SELECT D.VAL
    FROM VALD V
    LEFT JOIN DATE2ISO(V.VAL, 0) D ON 1 = 1
    WHERE V.OBJ_ID = :V$OBJ_ID AND V.PARAM_ID = 561 AND V.IS_DEL = 0
    INTO :VAL;
    SUSPEND;
    TAG_NAME = 'documents:document:issued_by';
    VAL = NULL;
    SELECT V.VAL
    FROM VALS V
    WHERE V.OBJ_ID = :V$OBJ_ID AND V.PARAM_ID = 562 AND V.IS_DEL = 0
    INTO :VAL;
    IF(VAL IS NULL) THEN EXCEPTION DATA_ERROR 'Не указано, кем выдан документ';
    SUSPEND;
    TAG_NAME = 'documents:document:is_active';
    VAL = NULL;
    SELECT IIF(V.LISTVAL_ID = 1982, 1, 0)
    FROM VALL V
    WHERE V.OBJ_ID = :V$OBJ_ID AND V.PARAM_ID = 614 AND V.IS_DEL = 0
    INTO :VAL;
    IF(VAL IS NULL) THEN EXCEPTION DATA_ERROR 'Не указан статус документа';
    SUSPEND;
    TAG_NAME = 'documents:document:file_name';
    V$SRC1 = NULL;
    VAL = NULL;
    SELECT V.VAL, V.BLOB_ID
    FROM VALB V
    WHERE V.OBJ_ID = :V$OBJ_ID AND V.PARAM_ID = 576 AND V.IS_DEL = 0
    INTO :VAL, :V$SRC1;
    SUSPEND;
    TAG_NAME = 'documents:document:file_id';
    VAL = V$SRC1;
    SUSPEND;
  END

  -- Дополнительные документы
  -- должен быть указан тип, дата и либо номер, либо скан
  TAG_NAME = 'ext_docs::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT DISTINCT L12.OBJ_ID, V51.LISTVAL_ID
    FROM VALS VG
    -- тут могут быть дубли
    JOIN LINKS LPG ON LPG.OBJ_ID = VG.OBJ_ID AND LPG.PARENT_TYPE_ID IN (9, 46, 187, 2, 211, 81, 82, 83, 84, 289, 290) AND LPG.DATE_DEL IS NULL
    -- сами документы
    JOIN LINKS L12 ON L12.PARENT_ID = LPG.OBJ_ID AND L12.OBJ_TYPE_ID = 12 AND L12.DATE_DEL IS NULL
    JOIN VALL V51 ON V51.OBJ_ID = L12.OBJ_ID AND V51.PARAM_ID = 51 AND V51.IS_DEL = 0
    LEFT JOIN VALD V572 ON V572.OBJ_ID = L12.OBJ_ID AND V572.PARAM_ID = 572 AND V572.IS_DEL = 0
    LEFT JOIN VALS V571 ON V571.OBJ_ID = L12.OBJ_ID AND V571.PARAM_ID = 571 AND V571.IS_DEL = 0
    LEFT JOIN VALB V578 ON V578.OBJ_ID = L12.OBJ_ID AND V578.PARAM_ID = 578 AND V578.IS_DEL = 0
    WHERE VG.PARAM_ID IN (2912, 2915, 2917) AND VG.IS_DEL = 0 AND VG.SVAL = :V$REG_ID AND :V$REG_ID IS NOT NULL
      AND (V571.VAL IS NOT NULL OR V578.VAL IS NOT NULL)
    UNION
    SELECT DISTINCT L12.OBJ_ID, V51.LISTVAL_ID
    FROM OBJECTS LPG
    -- сами документы
    JOIN LINKS L12 ON L12.PARENT_ID = LPG.OBJ_ID AND L12.OBJ_TYPE_ID = 12 AND L12.DATE_DEL IS NULL
    JOIN VALL V51 ON V51.OBJ_ID = L12.OBJ_ID AND V51.PARAM_ID = 51 AND V51.IS_DEL = 0
    LEFT JOIN VALD V572 ON V572.OBJ_ID = L12.OBJ_ID AND V572.PARAM_ID = 572 AND V572.IS_DEL = 0
    LEFT JOIN VALS V571 ON V571.OBJ_ID = L12.OBJ_ID AND V571.PARAM_ID = 571 AND V571.IS_DEL = 0
    LEFT JOIN VALB V578 ON V578.OBJ_ID = L12.OBJ_ID AND V578.PARAM_ID = 578 AND V578.IS_DEL = 0
    WHERE :V$REG_ID IS NULL AND LPG.OBJ_ID = :I$OBJ_ID
    -- Заключение ПМПК - выгружаем с id самой персоны
    UNION
    SELECT DISTINCT LPG.OBJ_ID, 14303
    FROM VALS VG
    -- тут могут быть дубли
    JOIN LINKS LPG ON LPG.OBJ_ID = VG.OBJ_ID AND LPG.PARENT_TYPE_ID IN (9, 46, 187, 2, 211, 81, 82, 83, 84, 289, 290) AND LPG.DATE_DEL IS NULL
    -- скан заключения
    JOIN VALB V3304 ON V3304.OBJ_ID = LPG.OBJ_ID AND V3304.PARAM_ID = 3304 AND V3304.IS_DEL = 0
    WHERE VG.PARAM_ID IN (2912, 2915, 2917) AND VG.IS_DEL = 0 AND VG.SVAL = :V$REG_ID AND :V$REG_ID IS NOT NULL
    INTO :V$OBJ_ID, :V$TYPE_ID
  DO
  BEGIN
    TAG_NAME = 'ext_docs:document';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'ext_docs:document:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'ext_docs:document:type';
    VAL = V$TYPE_ID;
    SUSPEND;
    TAG_NAME = 'ext_docs:document:number';
    VAL = NULL;
    SELECT FIRST 1 COALESCE(V570.VAL || '№', '') || V571.VAL
    FROM VALS V571
    LEFT JOIN VALS V570 ON V570.OBJ_ID = V571.OBJ_ID AND V570.PARAM_ID = 570 AND V570.IS_DEL = 0
    WHERE V571.OBJ_ID = :V$OBJ_ID AND V571.PARAM_ID = 571 AND V571.IS_DEL = 0
    INTO :VAL;
    SUSPEND;
    TAG_NAME = 'ext_docs:document:issue_date';
    VAL = NULL;
    SELECT FIRST 1 C.VAL
    FROM VALD V572
    LEFT JOIN DATE2ISO(V572.VAL, 0) C ON 1 = 1
    WHERE V572.OBJ_ID = :V$OBJ_ID AND V572.PARAM_ID = 572 AND V572.IS_DEL = 0
    INTO :VAL;
    SUSPEND;
    TAG_NAME = 'ext_docs:document:expire_date';
    VAL = NULL;
    SELECT FIRST 1 C.VAL
    FROM VALD V573
    LEFT JOIN DATE2ISO(V573.VAL, 0) C ON 1 = 1
    WHERE V573.OBJ_ID = :V$OBJ_ID AND V573.PARAM_ID = 573 AND V573.IS_DEL = 0
    INTO :VAL;
    SUSPEND;
    TAG_NAME = 'ext_docs:document:issued_by';
    VAL = NULL;
    SELECT V.VAL
    FROM VALS V
    WHERE V.OBJ_ID = :V$OBJ_ID AND V.PARAM_ID = 574 AND V.IS_DEL = 0
    INTO :VAL;
    TAG_NAME = 'ext_docs:document:file_name';
    V$SRC1 = NULL;
    VAL = NULL;
    SELECT V.VAL, V.BLOB_ID
    FROM VALB V
    WHERE V.OBJ_ID = :V$OBJ_ID AND V.PARAM_ID IN (578, 3304) AND V.IS_DEL = 0
    INTO :VAL, :V$SRC1;
    SUSPEND;
    TAG_NAME = 'ext_docs:document:file_id';
    VAL = V$SRC1;
    SUSPEND;
  END

  -- Реестр движения - идем по всем инкарнациям
  TAG_NAME = 'movements::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT DISTINCT VG.OBJ_ID
    FROM VALS VG
    -- тут могут быть дубли
    JOIN LINKS LPG ON LPG.OBJ_ID = VG.OBJ_ID AND LPG.PARENT_TYPE_ID IN (9, 46, 187, 2, 211, 81, 82, 83, 84, 289, 290) AND LPG.DATE_DEL IS NULL
    WHERE VG.PARAM_ID IN (2912, 2915, 2917) AND VG.IS_DEL = 0 AND VG.SVAL = :V$REG_ID AND :V$REG_ID IS NOT NULL
    UNION
    SELECT LPG.OBJ_ID
    FROM OBJECTS LPG
    WHERE LPG.OBJ_ID = :I$OBJ_ID
    INTO :V$PERSON_ID
  DO
  BEGIN
    -- Должности
    FOR
      SELECT L15.OBJ_ID, V73.VAL, V74.VAL, LP13.PARENT_ID, V1394.LISTVAL_ID, R.VAL, V587.LISTVAL_ID, V66.VAL, IIF(V72.LISTVAL_ID = 935, 0, 1), V458.LISTVAL_ID
      FROM LINKS L15
      JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
      JOIN VALS V66 ON V66.OBJ_ID = LP13.PARENT_ID AND V66.PARAM_ID = 66 AND V66.IS_DEL = 0
      JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0
      JOIN VALL V1394 ON V1394.OBJ_ID = L15.OBJ_ID AND V1394.PARAM_ID = 1394 AND V1394.IS_DEL = 0
      JOIN LISTVALS LV ON LV.LISTVAL_ID = V1394.LISTVAL_ID
      JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
      LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
      LEFT JOIN VALL V587 ON V587.OBJ_ID = L15.OBJ_ID AND V587.PARAM_ID = 587 AND V587.IS_DEL = 0
      -- Основная или дополнительная
      JOIN VALL V72 ON V72.OBJ_ID = L15.OBJ_ID AND V72.PARAM_ID = 72 AND V72.IS_DEL = 0
      -- Основание увольнения
      LEFT JOIN VALL V458 ON V458.OBJ_ID = L15.OBJ_ID AND V458.PARAM_ID = 458 AND V458.IS_DEL = 0
      WHERE L15.PARENT_ID = :V$PERSON_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
      INTO :V$OBJ_ID, :V$D1, :V$D2, :V$REF_ID, :V$JOB_ID, :V$S, :V$GRADE_ID, :V$NAME, :V$REASON1, :V$REASON2
    DO
    BEGIN
      TAG_NAME = 'movements:movement';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'movements:movement:type';
      VAL = 'job';
      SUSPEND;
      TAG_NAME = 'movements:movement:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'movements:movement:job_id';
      VAL = V$REF_ID;
      SUSPEND;
      -- Условия приема
      TAG_NAME = 'movements:movement:pm_id';
      VAL = V$GRADE_ID;
      SUSPEND;
      TAG_NAME = 'movements:movement:date_from';
      VAL = (SELECT VAL FROM DATE2ISO(:V$D1, 0));
      SUSPEND;
      TAG_NAME = 'movements:movement:date_to';
      VAL = (SELECT VAL FROM DATE2ISO(:V$D2, 0));
      SUSPEND;
      TAG_NAME = 'movements:movement:function_id';
      VAL = V$JOB_ID;
      SUSPEND;
      -- Должность как функция
      TAG_NAME = 'movements:movement:name';
      VAL = V$S;
      SUSPEND;
      -- Реальное название должности
      TAG_NAME = 'movements:movement:lcname';
      VAL = V$NAME;
      SUSPEND;
      -- Основная 1, дополнительная 0
      TAG_NAME = 'movements:movement:grade_type';
      VAL = V$REASON1;
      SUSPEND;
      TAG_NAME = 'movements:movement:reason_out';
      VAL = V$REASON2;
      SUSPEND;
    END

      -- Движение в классах, наслоений тут быть не должно, а само движение должно быть выстроено в порядке возрастания ID
    FOR
      SELECT M.OBJ_ID, M.TYPE_IN, M.STAGE_ID, O.TYPE_ID, M.GROUP_ID, M.DATE_IN, M.DATE_OUT, M.NAME_IN, M.REASON_IN, M.REASON_OUT, M.SOURCE_IN, M.SOURCE_OUT, M.LEVEL_ID
      FROM PERSON_MOVEMENTS M
      JOIN OBJECTS O ON O.OBJ_ID = M.GROUP_ID AND O.TYPE_ID IN (9, 187, 46)
      WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :V$PERSON_ID
      ORDER BY M.OBJ_ID
      INTO :V$OBJ_ID, :V$MOVE_TYPE, :V$STAGE_ID, :V$GROUP_TYPE, :V$REF_ID, :V$D1, :V$D2, :V$NAME, :V$REASON1, :V$REASON2, :V$SRC1, :V$SRC2, :V$LEVEL_ID
    DO
    BEGIN
      TAG_NAME = 'movements:movement';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'movements:movement:type';
      VAL = 'study';
      SUSPEND;
      TAG_NAME = 'movements:movement:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'movements:movement:grade_id';
      VAL = V$REF_ID;
      SUSPEND;
      TAG_NAME = 'movements:movement:grade_type';
      VAL = V$GROUP_TYPE;
      SUSPEND;
      TAG_NAME = 'movements:movement:stage_id';
      VAL = V$STAGE_ID;
      SUSPEND;
      TAG_NAME = 'movements:movement:move_type';
      VAL = V$MOVE_TYPE;
      SUSPEND;
      TAG_NAME = 'movements:movement:date_from';
      VAL = (SELECT VAL FROM DATE2ISO(:V$D1, 0));
      SUSPEND;
      TAG_NAME = 'movements:movement:date_to';
      VAL = (SELECT VAL FROM DATE2ISO(:V$D2, 0));
      SUSPEND;
      TAG_NAME = 'movements:movement:name';
      VAL = V$NAME;
      SUSPEND;
      TAG_NAME = 'movements:movement:reason_in';
      VAL = V$REASON1;
      SUSPEND;
      TAG_NAME = 'movements:movement:reason_out';
      VAL = V$REASON2;
      SUSPEND;
      TAG_NAME = 'movements:movement:src_in';
      VAL = V$SRC1;
      SUSPEND;
      TAG_NAME = 'movements:movement:src_out';
      VAL = V$SRC2;
      SUSPEND;
      TAG_NAME = 'movements:movement:level';
      VAL = V$LEVEL_ID;
      SUSPEND;
    END

    -- Предварительный прием
    FOR
      SELECT LP290.LINK_ID, V2346.LISTVAL_ID, LP290.DATE_INS, COALESCE(V3025.SVAL, C.CAPTION)
      FROM LINKS LP290
      JOIN VALL V2346 ON V2346.OBJ_ID = LP290.PARENT_ID AND V2346.PARAM_ID = 2346 AND V2346.IS_DEL = 0
      LEFT JOIN OBJECT_CAPTION_GET(LP290.PARENT_ID) C ON 1 = 1
      LEFT JOIN VALS V3025 ON V3025.OBJ_ID = LP290.OBJ_ID AND V3025.PARAM_ID = 3025 AND V3025.IS_DEL = 0
      WHERE LP290.OBJ_ID = :V$PERSON_ID AND LP290.PARENT_TYPE_ID = 290 AND LP290.DATE_DEL IS NULL
      INTO :V$OBJ_ID, :V$STAGE_ID, :V$D1, :V$NAME
    DO
    BEGIN
      TAG_NAME = 'movements:movement';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'movements:movement:type';
      VAL = 'study';
      SUSPEND;
      TAG_NAME = 'movements:movement:id';
      VAL = - V$OBJ_ID; -- вносим с отрицательным id
      SUSPEND;
      TAG_NAME = 'movements:movement:grade_id';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'movements:movement:grade_type';
      VAL = 290;
      SUSPEND;
      TAG_NAME = 'movements:movement:stage_id';
      VAL = V$STAGE_ID;
      SUSPEND;
      TAG_NAME = 'movements:movement:move_type';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'movements:movement:date_from';
      VAL = (SELECT VAL FROM DATE2ISO(:V$D1, 0));
      SUSPEND;
      TAG_NAME = 'movements:movement:date_to';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'movements:movement:name';
      VAL = V$NAME;
      SUSPEND;
      TAG_NAME = 'movements:movement:reason_in';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'movements:movement:reason_out';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'movements:movement:src_in';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'movements:movement:src_out';
      VAL = NULL;
      SUSPEND;
    END

    -- Движение в старом формате для не-школ, уровень региона
    -- Убрать после конвертации в новый формат !
    IF(V$OU_LICENCE_TYPE = 'D' OR V$OU_LICENCE_TYPE = 'U' OR V$OU_LICENCE_TYPE = 'C') THEN
    BEGIN
      V$PREV_MOVE = NULL;
      V$D1 = NULL;
      FOR
        SELECT L76.OBJ_ID, V433.VAL, V432.LISTVAL_ID, V437.VAL, V436.LISTVAL_ID, V438.VAL, R.TYPE_ID, V1350.LISTVAL_ID
        FROM LINKS L76
        JOIN VALD V433 ON V433.OBJ_ID = L76.OBJ_ID AND V433.PARAM_ID = 433 AND V433.IS_DEL = 0
        JOIN VALL V432 ON V432.OBJ_ID = L76.OBJ_ID AND V432.PARAM_ID = 432 AND V432.IS_DEL = 0
        JOIN VALS V437 ON V437.OBJ_ID = L76.OBJ_ID AND V437.PARAM_ID = 437 AND V437.IS_DEL = 0
        LEFT JOIN VALL V436 ON V436.OBJ_ID = L76.OBJ_ID AND V436.PARAM_ID = 436 AND V436.IS_DEL = 0
        LEFT JOIN VALR V438 ON V438.OBJ_ID = L76.OBJ_ID AND V438.PARAM_ID = 438 AND V438.IS_DEL = 0
        LEFT JOIN OBJECTS R ON R.OBJ_ID = V438.VAL
        LEFT JOIN VALL V1350 ON V1350.OBJ_ID = L76.OBJ_ID AND V1350.PARAM_ID = 1350 AND V1350.IS_DEL = 0
        WHERE L76.PARENT_ID = :V$PERSON_ID AND L76.OBJ_TYPE_ID = 76 AND L76.DATE_DEL IS NULL
        ORDER BY 2, 1
        INTO :V$OBJ_ID, :V$D2, :V$REASON2, :V$S, :V$STAGE_ID, :V$GRADE_ID, :V$GROUP_TYPE, :V$MOVE_TYPE
      DO
      BEGIN
        -- Если это выбытие или перевод - выдаем запись
        IF(V$PREV_MOVE IS NOT NULL) THEN
        BEGIN
          TAG_NAME = 'movements:movement';
          VAL = NULL;
          SUSPEND;
          TAG_NAME = 'movements:movement:type';
          VAL = 'study';
          SUSPEND;
          TAG_NAME = 'movements:movement:id';
          VAL = V$PREV_MOVE;
          SUSPEND;
          TAG_NAME = 'movements:movement:grade_id';
          VAL = V$PREV_GID;
          SUSPEND;
          TAG_NAME = 'movements:movement:grade_type';
          VAL = V$PREV_GT;
          SUSPEND;
          TAG_NAME = 'movements:movement:stage_id';
          VAL = V$PREV_STAGE;
          SUSPEND;
          TAG_NAME = 'movements:movement:move_type';
          VAL = V$PREV_MT;
          SUSPEND;
          TAG_NAME = 'movements:movement:date_from';
          VAL = (SELECT VAL FROM DATE2ISO(:V$D1, 0));
          SUSPEND;
          TAG_NAME = 'movements:movement:date_to';
          VAL = (SELECT VAL FROM DATE2ISO(:V$D2, 0));
          SUSPEND;
          TAG_NAME = 'movements:movement:name';
          VAL = V$NAME;
          SUSPEND;
          TAG_NAME = 'movements:movement:reason_in';
          VAL = V$REASON1;
          SUSPEND;
          TAG_NAME = 'movements:movement:reason_out';
          VAL = V$REASON2;
          SUSPEND;
        END

        -- Во всех случаях кроме выбытия запоминаем новые данные
        IF(V$REASON2 IN (811, 812, 5316, 5317, 5318, 5319, 11093, 5548, 5549)) THEN
        BEGIN
          V$PREV_MOVE = NULL;
        END
        ELSE
        BEGIN
          V$PREV_MOVE = V$OBJ_ID;
          V$REASON1 = V$REASON2;
          V$D1 = V$D2;
          V$NAME = V$S;
          V$PREV_STAGE = V$STAGE_ID;
          V$PREV_GID = V$GRADE_ID;
          V$PREV_GT = V$GROUP_TYPE;
          V$PREV_MT = V$MOVE_TYPE;
        END
      END

      -- Если это выбытие или перевод - выдаем запись
      IF(V$PREV_MOVE IS NOT NULL) THEN
      BEGIN
        TAG_NAME = 'movements:movement';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'movements:movement:type';
        VAL = 'study';
        SUSPEND;
        TAG_NAME = 'movements:movement:id';
        VAL = V$PREV_MOVE;
        SUSPEND;
        TAG_NAME = 'movements:movement:grade_id';
        VAL = V$PREV_GID;
        SUSPEND;
        TAG_NAME = 'movements:movement:grade_type';
        VAL = V$PREV_GT;
        SUSPEND;
        TAG_NAME = 'movements:movement:stage_id';
        VAL = V$PREV_STAGE;
        SUSPEND;
        TAG_NAME = 'movements:movement:move_type';
        VAL = V$PREV_MT;
        SUSPEND;
        TAG_NAME = 'movements:movement:date_from';
        VAL = (SELECT VAL FROM DATE2ISO(:V$D1, 0));
        SUSPEND;
        TAG_NAME = 'movements:movement:date_to';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'movements:movement:name';
        VAL = V$NAME;
        SUSPEND;
        TAG_NAME = 'movements:movement:reason_in';
        VAL = V$REASON1;
        SUSPEND;
        TAG_NAME = 'movements:movement:reason_out';
        VAL = NULL;
        SUSPEND;
      END

    END

  END

  -- Итоговые отметки
  TAG_NAME = 'marks::json&colon;array';
  VAL = NULL;
  SUSPEND;
  FOR
    SELECT M.MARK_ID, M.SUBJECT_ID, M.STAGE_ID, M.GRADE_ID, M.TEACHER_ID, M.YEAR_ID, M.MARKTYPE_ID, M.MARKVAL_ID, M.MARK_DATE
    FROM VALM M
    WHERE M.IS_DEL = 0 AND M.PUPIL_ID = :I$OBJ_ID AND (M.IS_NATIVE IS NULL OR M.IS_NATIVE = 1)
    INTO :V$OBJ_ID, :V$SUBJECT_ID, :V$STAGE_ID, :V$GRADE_ID, :V$TEACHER_ID, :V$YEAR_ID, :V$MARKTYPE_ID, :V$MARKVAL_ID, :V$D1
  DO
  BEGIN
    TAG_NAME = 'marks:mark';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'marks:mark:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'marks:mark:subject_id';
    VAL = V$SUBJECT_ID;
    SUSPEND;
    TAG_NAME = 'marks:mark:stage_id';
    VAL = V$STAGE_ID;
    SUSPEND;
    TAG_NAME = 'marks:mark:grade_id';
    VAL = V$GRADE_ID;
    SUSPEND;
    TAG_NAME = 'marks:mark:teacher_id';
    VAL = V$TEACHER_ID;
    SUSPEND;
    TAG_NAME = 'marks:mark:year_id';
    VAL = V$YEAR_ID;
    SUSPEND;
    TAG_NAME = 'marks:mark:mt_id';
    VAL = V$MARKTYPE_ID;
    SUSPEND;
    TAG_NAME = 'marks:mark:val';
    VAL = V$MARKVAL_ID;
    SUSPEND;
    TAG_NAME = 'marks:mark:date';
    VAL = (SELECT VAL FROM DATE2ISO(:V$D1, 0));
    SUSPEND;
  END

  -- Документы, связанные с образованием
  TAG_NAME = 'edu_docs::json&colon;array';
  VAL = NULL;
  SUSPEND;
  FOR
    -- Документы об образовании обучающегося
    SELECT L11.OBJ_ID, L11.OBJ_TYPE_ID, V50.LISTVAL_ID, NULL, V564.SVAL, V565.SVAL, V566.VAL,
      V568.VAL, V2969.SVAL, V2138.SVAL, NULL, NULL
    FROM LINKS L11
    JOIN VALS V569 ON V569.OBJ_ID = L11.OBJ_ID AND V569.PARAM_ID = 569 AND V569.IS_DEL = 0
    JOIN VALL V50 ON V50.OBJ_ID = L11.OBJ_ID AND V50.PARAM_ID = 50 AND V50.IS_DEL = 0
    LEFT JOIN VALS V564 ON V564.OBJ_ID = L11.OBJ_ID AND V564.PARAM_ID = 564 AND V564.IS_DEL = 0
    JOIN VALS V565 ON V565.OBJ_ID = L11.OBJ_ID AND V565.PARAM_ID = 565 AND V565.IS_DEL = 0
    JOIN VALD V566 ON V566.OBJ_ID = L11.OBJ_ID AND V566.PARAM_ID = 566 AND V566.IS_DEL = 0
    LEFT JOIN VALS V568 ON V568.OBJ_ID = L11.OBJ_ID AND V568.PARAM_ID = 568 AND V568.IS_DEL = 0
    LEFT JOIN VALS V2969 ON V2969.OBJ_ID = L11.OBJ_ID AND V2969.PARAM_ID = 2969 AND V2969.IS_DEL = 0
    LEFT JOIN VALS V2138 ON V2138.OBJ_ID = L11.OBJ_ID AND V2138.PARAM_ID = 2138 AND V2138.IS_DEL = 0
    WHERE L11.PARENT_ID = :I$OBJ_ID AND L11.OBJ_TYPE_ID = 11 AND L11.DATE_DEL IS NULL
    -- Документы об образовании сотрудника
    UNION ALL
    SELECT L33.OBJ_ID, L33.OBJ_TYPE_ID, V286.LISTVAL_ID, V284.LISTVAL_ID, V287.SVAL, V288.SVAL, V290.VAL,
      V285.VAL, NULL, V292.SVAL, V291.SVAL, V293.LISTVAL_ID
    FROM LINKS L33
    JOIN VALL V286 ON V286.OBJ_ID = L33.OBJ_ID AND V286.PARAM_ID = 286 AND V286.IS_DEL = 0
    JOIN VALL V284 ON V284.OBJ_ID = L33.OBJ_ID AND V284.PARAM_ID = 284 AND V284.IS_DEL = 0
    LEFT JOIN VALL V289 ON V289.OBJ_ID = L33.OBJ_ID AND V289.PARAM_ID = 289 AND V289.IS_DEL = 0 -- вид диплома
    LEFT JOIN VALS V287 ON V287.OBJ_ID = L33.OBJ_ID AND V287.PARAM_ID = 287 AND V287.IS_DEL = 0
    JOIN VALS V288 ON V288.OBJ_ID = L33.OBJ_ID AND V288.PARAM_ID = 288 AND V288.IS_DEL = 0
    JOIN VALD V290 ON V290.OBJ_ID = L33.OBJ_ID AND V290.PARAM_ID = 290 AND V290.IS_DEL = 0
    JOIN VALS V285 ON V285.OBJ_ID = L33.OBJ_ID AND V285.PARAM_ID = 285 AND V285.IS_DEL = 0 -- организация
    LEFT JOIN VALS V292 ON V292.OBJ_ID = L33.OBJ_ID AND V292.PARAM_ID = 292 AND V292.IS_DEL = 0 -- квалификация
    LEFT JOIN VALS V291 ON V291.OBJ_ID = L33.OBJ_ID AND V291.PARAM_ID = 291 AND V291.IS_DEL = 0 -- специальность
    LEFT JOIN VALL V293 ON V293.OBJ_ID = L33.OBJ_ID AND V293.PARAM_ID = 293 AND V293.IS_DEL = 0 -- профиль образования
    WHERE L33.PARENT_ID = :I$OBJ_ID AND L33.OBJ_TYPE_ID = 33 AND L33.DATE_DEL IS NULL
    -- Переподготовка
    UNION ALL
    SELECT L35.OBJ_ID, L35.OBJ_TYPE_ID, V297.LISTVAL_ID, NULL, V298.SVAL, V299.SVAL, V300.VAL,
      V296.VAL, NULL, V302.SVAL, V301.SVAL, NULL
    FROM LINKS L35
    JOIN VALL V297 ON V297.OBJ_ID = L35.OBJ_ID AND V297.PARAM_ID = 297 AND V297.IS_DEL = 0
    LEFT JOIN VALS V298 ON V298.OBJ_ID = L35.OBJ_ID AND V298.PARAM_ID = 298 AND V298.IS_DEL = 0
    JOIN VALS V299 ON V299.OBJ_ID = L35.OBJ_ID AND V299.PARAM_ID = 299 AND V299.IS_DEL = 0
    JOIN VALD V300 ON V300.OBJ_ID = L35.OBJ_ID AND V300.PARAM_ID = 300 AND V300.IS_DEL = 0
    JOIN VALS V296 ON V296.OBJ_ID = L35.OBJ_ID AND V296.PARAM_ID = 296 AND V296.IS_DEL = 0 -- организация
    LEFT JOIN VALS V302 ON V302.OBJ_ID = L35.OBJ_ID AND V302.PARAM_ID = 302 AND V302.IS_DEL = 0 -- квалификация
    LEFT JOIN VALS V301 ON V301.OBJ_ID = L35.OBJ_ID AND V301.PARAM_ID = 301 AND V301.IS_DEL = 0 -- специальность
    WHERE L35.PARENT_ID = :I$OBJ_ID AND L35.OBJ_TYPE_ID = 35 AND L35.DATE_DEL IS NULL
    -- Повышение квалификации
    UNION ALL
    SELECT L36.OBJ_ID, L36.OBJ_TYPE_ID, V307.LISTVAL_ID, V303.LISTVAL_ID, V308.SVAL, V309.SVAL, V310.VAL,
      V304.VAL, NULL, V305.SVAL, V306.VAL, V1024.LISTVAL_ID
    FROM LINKS L36
    JOIN VALL V307 ON V307.OBJ_ID = L36.OBJ_ID AND V307.PARAM_ID = 307 AND V307.IS_DEL = 0 --
    JOIN VALL V303 ON V303.OBJ_ID = L36.OBJ_ID AND V303.PARAM_ID = 303 AND V303.IS_DEL = 0 -- вид
    LEFT JOIN VALL V1024 ON V1024.OBJ_ID = L36.OBJ_ID AND V1024.PARAM_ID = 1024 AND V1024.IS_DEL = 0 -- тип курса -> профиль
    LEFT JOIN VALS V308 ON V308.OBJ_ID = L36.OBJ_ID AND V308.PARAM_ID = 308 AND V308.IS_DEL = 0
    JOIN VALS V309 ON V309.OBJ_ID = L36.OBJ_ID AND V309.PARAM_ID = 309 AND V309.IS_DEL = 0
    JOIN VALD V310 ON V310.OBJ_ID = L36.OBJ_ID AND V310.PARAM_ID = 310 AND V310.IS_DEL = 0
    JOIN VALS V304 ON V304.OBJ_ID = L36.OBJ_ID AND V304.PARAM_ID = 304 AND V304.IS_DEL = 0 -- организация
    LEFT JOIN VALS V305 ON V305.OBJ_ID = L36.OBJ_ID AND V305.PARAM_ID = 305 AND V305.IS_DEL = 0 -- название курса
    LEFT JOIN VALI V306 ON V306.OBJ_ID = L36.OBJ_ID AND V306.PARAM_ID = 306 AND V306.IS_DEL = 0 -- часы
    WHERE L36.PARENT_ID = :I$OBJ_ID AND L36.OBJ_TYPE_ID = 36 AND L36.DATE_DEL IS NULL
    -- Аттестация на категорию - номера и серии нет
    UNION ALL
    SELECT L34.OBJ_ID, L34.OBJ_TYPE_ID, V545.LISTVAL_ID, NULL, NULL, NULL, V544.VAL,
      NULL, NULL, V294.SVAL, C.VAL, V2347.LISTVAL_ID
    FROM LINKS L34
    JOIN VALL V545 ON V545.OBJ_ID = L34.OBJ_ID AND V545.PARAM_ID = 545 AND V545.IS_DEL = 0 -- решение
    JOIN VALL V2347 ON V2347.OBJ_ID = L34.OBJ_ID AND V2347.PARAM_ID = 2347 AND V2347.IS_DEL = 0 -- код должности
    LEFT JOIN LISTVAL_TEXT(V2347.LISTVAL_ID) C ON 1 = 1
    JOIN VALD V544 ON V544.OBJ_ID = L34.OBJ_ID AND V544.PARAM_ID = 544 AND V544.IS_DEL = 0
    LEFT JOIN VALS V294 ON V294.OBJ_ID = L34.OBJ_ID AND V294.PARAM_ID = 294 AND V294.IS_DEL = 0 -- основание
    WHERE L34.PARENT_ID = :I$OBJ_ID AND L34.OBJ_TYPE_ID = 34 AND L34.DATE_DEL IS NULL
    -- Аттестация на соответствие должности - номера и серии нет, в reg_id запоминаем id самой должности
    UNION ALL
    SELECT L156.OBJ_ID, L156.OBJ_TYPE_ID, V1233.LISTVAL_ID, NULL, NULL, NULL, V1232.VAL,
      ORG.CAPTION, V2348.VAL, V1234.SVAL, C.CAPTION, V1235.LISTVAL_ID
    FROM LINKS L156
    JOIN VALL V1233 ON V1233.OBJ_ID = L156.OBJ_ID AND V1233.PARAM_ID = 1233 AND V1233.IS_DEL = 0 -- решение
    JOIN VALL V1235 ON V1235.OBJ_ID = L156.OBJ_ID AND V1235.PARAM_ID = 1235 AND V1235.IS_DEL = 0 -- код должности
    JOIN VALR V2348 ON V2348.OBJ_ID = L156.OBJ_ID AND V2348.PARAM_ID = 2348 AND V2348.IS_DEL = 0 -- id должности
    LEFT JOIN OBJECT_CAPTION_GET(V2348.VAL) C ON 1 = 1
    JOIN VALD V1232 ON V1232.OBJ_ID = L156.OBJ_ID AND V1232.PARAM_ID = 1232 AND V1232.IS_DEL = 0
    LEFT JOIN VALS V1234 ON V1234.OBJ_ID = L156.OBJ_ID AND V1234.PARAM_ID = 1234 AND V1234.IS_DEL = 0 -- основание
    LEFT JOIN OBJECT_CAPTION_GET(:V$ORG_ID) ORG ON 1 = 1
    WHERE L156.PARENT_ID = :I$OBJ_ID AND L156.OBJ_TYPE_ID = 156 AND L156.DATE_DEL IS NULL
    INTO :V$OBJ_ID, :V$TYPE_ID, :V$GRADE_ID, :V$STAGE_ID, :V$S1, :V$S2, :V$D1,
      :V$S, :V$REG_ID, :V$QUAL, :V$NAME, :V$MARKTYPE_ID
  DO
  BEGIN
    -- Заполняем этап для аттестатов
    IF(V$STAGE_ID IS NULL) THEN
    BEGIN
      IF(V$GRADE_ID IN (1375, 3241, 11137)) THEN V$STAGE_ID = 26; -- ООО и справка
      IF(V$GRADE_ID IN (1376, 3240)) THEN V$STAGE_ID = 27; -- СОО
      IF(V$GRADE_ID IN (1380, 12785)) THEN V$STAGE_ID = 29; -- СПО
    END

    TAG_NAME = 'edu_docs:item';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'edu_docs:item:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'edu_docs:item:obj_type';
    VAL = V$TYPE_ID;
    SUSPEND;
    TAG_NAME = 'edu_docs:item:type_id';
    VAL = V$GRADE_ID;
    SUSPEND;
    TAG_NAME = 'edu_docs:item:stage_id';
    VAL = V$STAGE_ID;
    SUSPEND;
    TAG_NAME = 'edu_docs:item:doc_serie';
    VAL = V$S1;
    SUSPEND;
    TAG_NAME = 'edu_docs:item:doc_num';
    VAL = V$S2;
    SUSPEND;
    TAG_NAME = 'edu_docs:item:doc_date';
    VAL = (SELECT VAL FROM DATE2ISO(:V$D1, 0));
    SUSPEND;
    TAG_NAME = 'edu_docs:item:issuer';
    VAL = V$S;
    SUSPEND;
    TAG_NAME = 'edu_docs:item:reg_num';
    VAL = V$REG_ID;
    SUSPEND;
    TAG_NAME = 'edu_docs:item:qual';
    VAL = V$QUAL;
    SUSPEND;
    TAG_NAME = 'edu_docs:item:spec';
    VAL = V$NAME;
    SUSPEND;
    TAG_NAME = 'edu_docs:item:profile_id';
    VAL = V$MARKTYPE_ID;
    SUSPEND;
  END

  -- Выгружаем данные личного дела ученика только если статус позволяет
  SELECT FIRST 1 V3447.LISTVAL_ID
  FROM VALL V3447
  WHERE V3447.OBJ_ID = :I$OBJ_ID AND V3447.PARAM_ID = 3447 AND V3447.IS_DEL = 0
  INTO :V$LD_STATUS;

  IF(V$LD_STATUS IN (14298, 14299)) THEN
  BEGIN
    TAG_NAME = 'ld::json&colon;array';
    VAL = NULL;
    SUSPEND;
    -- Данные по здоровью
    FOR
      SELECT V.PARAM_ID, V.LISTVAL_ID, V.DATE_MODIFY
      FROM VALL V
      WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID IN (207, 208, 176, 1374) AND V.IS_DEL = 0
      UNION ALL
      SELECT V.PARAM_ID, SUBSTRING(V.VAL FROM 1 FOR 1000), V.DATE_MODIFY
      FROM VALS V
      WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID IN (2546, 3116, 229) AND V.IS_DEL = 0
      ORDER BY 1
      INTO :V$MARKTYPE_ID, :V$QUAL, :V$DT
    DO
    BEGIN
      IF(V$MDT IS NULL) THEN V$MDT = V$DT; ELSE V$MDT = MAXVALUE(V$MDT, V$DT);
      TAG_NAME = 'ld:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'ld:r:id';
      VAL = I$OBJ_ID || ':' || V$MARKTYPE_ID;
      SUSPEND;
      TAG_NAME = 'ld:r:value';
      VAL = V$QUAL;
      SUSPEND;
    END
    -- Метка времени последнего изменения ЛД
    TAG_NAME = 'ld_dt';
    VAL = (SELECT VAL FROM DATE2ISO(:V$MDT));
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE RKS_SERIALIZE_ALL (
    I$DATE TIMESTAMP)
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$S VARCHAR(100);
DECLARE VARIABLE V$LAST_DATE TIMESTAMP;
DECLARE VARIABLE V$PERSON_ID BIGINT;
DECLARE VARIABLE V$LINK_DT TIMESTAMP;
DECLARE VARIABLE V$PARAM_DT TIMESTAMP;
DECLARE VARIABLE V$DOCUMENT_DT TIMESTAMP;
DECLARE VARIABLE V$EXT_DT TIMESTAMP;
DECLARE VARIABLE NX INTEGER;
DECLARE VARIABLE V$STATUS VARCHAR(10);
DECLARE VARIABLE V$CONFLICT SMALLINT;
begin
  -- Если DATE совпадает с нашими зафиксированными от последней отправки данными - выгружаем как запросили
  -- если не совпадает, выполняем полную выгрузку

  SELECT INFO_VAL FROM INFO WHERE INFO_CODE = 'LAST_RKS_EXPORT' INTO :V$S;
  IF(V$S = '') THEN V$S = NULL;
  V$LAST_DATE = V$S;

  IF((I$DATE IS NOT NULL AND V$LAST_DATE <> I$DATE) OR V$LAST_DATE IS NULL) THEN I$DATE = NULL;

  V$STATUS = (SELECT STATUS FROM OU_LICENCE_TYPE);

  FOR
    SELECT TAG_NAME, VAL
    FROM RKS_SERIALIZE_HEADERS(:I$DATE, 1)
    INTO :TAG_NAME, :VAL
  DO
  BEGIN
    SUSPEND;
  END

  NX = 0;

  -- Обновляем только те записи, где есть код РК
  TAG_NAME = 'persons::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT DISTINCT L10.OBJ_ID
    FROM LINKS L10
    JOIN VALS V2912 ON V2912.OBJ_ID = L10.OBJ_ID AND V2912.PARAM_ID = 2912 AND V2912.IS_DEL = 0
    JOIN VALS V55 ON V55.OBJ_ID = L10.OBJ_ID AND V55.PARAM_ID = 55 AND V55.IS_DEL = 0
    JOIN VALS V56 ON V56.OBJ_ID = L10.OBJ_ID AND V56.PARAM_ID = 56 AND V56.IS_DEL = 0
    JOIN VALD V89 ON V89.OBJ_ID = L10.OBJ_ID AND V89.PARAM_ID = 89 AND V89.IS_DEL = 0
    WHERE L10.PARENT_TYPE_ID IN (9, 187, 81, 82, 83, 46, 289, 290) AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    UNION
    SELECT DISTINCT L14.OBJ_ID
    FROM LINKS L14
    JOIN VALS V2915 ON V2915.OBJ_ID = L14.OBJ_ID AND V2915.PARAM_ID = 2915 AND V2915.IS_DEL = 0
    JOIN VALS V59 ON V59.OBJ_ID = L14.OBJ_ID AND V59.PARAM_ID = 59 AND V59.IS_DEL = 0
    JOIN VALS V60 ON V60.OBJ_ID = L14.OBJ_ID AND V60.PARAM_ID = 60 AND V60.IS_DEL = 0
    JOIN VALD V241 ON V241.OBJ_ID = L14.OBJ_ID AND V241.PARAM_ID = 241 AND V241.IS_DEL = 0
    WHERE L14.PARENT_TYPE_ID IN (2, 211, 84) AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
    INTO :V$PERSON_ID
  DO
  BEGIN
    -- Обновляем только записи, где были изменения в самой записи, документах или записях движения
    SELECT MAX(LP.DATE_MODIFY)
    FROM LINKS LP
    WHERE LP.OBJ_ID = :V$PERSON_ID AND LP.PARENT_TYPE_ID IN (9, 187, 81, 82, 83, 46, 2, 211, 84, 289, 290) AND LP.DATE_DEL IS NULL
    INTO :V$LINK_DT;

    -- Изменения в документах
    V$DOCUMENT_DT = NULL;
    SELECT MAX(LD.DATE_MODIFY)
    FROM LINKS LD
    WHERE LD.PARENT_ID = :V$PERSON_ID AND LD.OBJ_TYPE_ID = 79
    INTO :V$DOCUMENT_DT;

    V$EXT_DT = NULL;
    SELECT MAX(LD.DATE_MODIFY)
    FROM LINKS LD
    WHERE LD.PARENT_ID = :V$PERSON_ID AND LD.OBJ_TYPE_ID = 12
    INTO :V$EXT_DT;

    -- Смотрим основные атрибуты (при изменении документов также поменяется причина изменения)
    V$PARAM_DT = NULL;
    SELECT MAX(DT)
    FROM (
      SELECT MAX(V.DATE_MODIFY) DT
      FROM VALS V
      WHERE V.OBJ_ID = :V$PERSON_ID AND V.PARAM_ID IN (55, 56, 57, 59, 60, 61, 128, 129, 130, 3060, 3061, 3141, 3482, 3025)
      UNION
      SELECT MAX(V.DATE_MODIFY) DT
      FROM VALD V
      WHERE V.OBJ_ID = :V$PERSON_ID AND V.PARAM_ID IN (89, 241)
      UNION
      SELECT MAX(V.DATE_MODIFY) DT
      FROM VALL V
      WHERE V.OBJ_ID = :V$PERSON_ID AND V.PARAM_ID IN (88, 239, 3006, 3007, 3008)
      UNION
      SELECT MAX(V.DATE_MODIFY) DT
      FROM VALM V
      WHERE V.PUPIL_ID = :V$PERSON_ID
      UNION
      -- изменение скана документа
      SELECT MAX(V.DATE_MODIFY) DT
      FROM LINKS L
      JOIN VALB V ON V.OBJ_ID = L.OBJ_ID AND V.PARAM_ID IN (576, 578)
      WHERE L.PARENT_ID = :V$PERSON_ID AND L.OBJ_TYPE_ID IN (79, 12) AND L.DATE_DEL IS NULL
      UNION
      SELECT MAX(V.DATE_MODIFY) DT
      FROM USERS V
      WHERE V.OBJ_ID = :V$PERSON_ID AND V.DATE_DEL IS NULL
    )
    INTO :V$PARAM_DT;

    V$CONFLICT = 0;
    SELECT FIRST 1 1
    FROM SYNC_LOG L
    WHERE L.PERSON_ID = :V$PERSON_ID AND L.MSG IS NOT NULL AND L.MSG <> ''
    INTO :V$CONFLICT;

    -- Дополнительные документы запись персоны не меняют - надо проверять отдельно

    IF(I$DATE IS NULL OR V$LINK_DT >= :I$DATE OR V$DOCUMENT_DT >= :I$DATE OR V$PARAM_DT >= :I$DATE OR V$EXT_DT >= :I$DATE OR V$CONFLICT <> 0) THEN
    BEGIN
      TAG_NAME = 'persons:person';
      VAL = NULL;
      SUSPEND;
      FOR
        SELECT TAG_NAME, VAL
        FROM RKS_SERIALIZE(:V$PERSON_ID, 0, 0)
        INTO :TAG_NAME, :VAL
      DO
      BEGIN
        TAG_NAME = 'persons:person:' || TAG_NAME;
        SUSPEND;
      END

      -- Максимально 200 учеников в пакете
      NX = NX + 1;
      IF(NX >= 200) THEN
      BEGIN
        NX = 0;
        TAG_NAME = NULL;
        VAL = 'DIVIDE';
        SUSPEND;
        FOR
          SELECT TAG_NAME, VAL
          FROM RKS_SERIALIZE_HEADERS(:I$DATE)
          INTO :TAG_NAME, :VAL
        DO
        BEGIN
          SUSPEND;
        END
        TAG_NAME = 'persons::json&colon;array';
        VAL = 1;
        SUSPEND;
      END

    END

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE RKS_SERIALIZE_DPO (
    I$DATE TIMESTAMP)
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(1000))
AS
declare variable V$PARENT_ID bigint;
declare variable V$OBJ_ID bigint;
declare variable V$DT timestamp;
declare variable V$DT0 timestamp;
declare variable V$DT1 timestamp;
declare variable V$DT2 timestamp;
declare variable V$DT3 timestamp;
declare variable V$DT4 timestamp;
declare variable V$DT5 timestamp;
declare variable V$DT6 timestamp;
declare variable V$DT7 timestamp;
declare variable V$DT8 timestamp;
declare variable S varchar(4000);
declare variable S2 varchar(4000);
declare variable V$TYPE bigint;
declare variable V$N1 bigint;
declare variable V$N2 bigint;
declare variable V$TYPE2 bigint;
declare variable V$FORM bigint;
declare variable V$CODE varchar(40);
declare variable V$ORDER_NUM varchar(40);
declare variable V$ORDER_DATE date;
declare variable V$D1 date;
declare variable V$D2 date;
begin

  FOR
    SELECT TAG_NAME, VAL
    FROM RKS_SERIALIZE_HEADERS(:I$DATE)
    INTO :TAG_NAME, :VAL
  DO
  BEGIN
    SUSPEND;
  END

  -- Каталоги образовательных программ
  TAG_NAME = 'programfolders::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L69.OBJ_ID, L69.DATE_DEL, L69.DATE_MODIFY, V412.DATE_MODIFY, V2450.DATE_MODIFY, V412.VAL, V2450.LISTVAL_ID
    FROM LINKS L69
    LEFT JOIN VALS V412 ON V412.OBJ_ID = L69.OBJ_ID AND V412.PARAM_ID = 412 AND V412.IS_DEL = 0
    LEFT JOIN VALL V2450 ON V2450.OBJ_ID = L69.OBJ_ID AND V2450.PARAM_ID = 2450 AND V2450.IS_DEL = 0
    WHERE L69.PARENT_TYPE_ID = 2 AND L69.OBJ_TYPE_ID = 69
    INTO :V$OBJ_ID, :V$DT, :V$DT0, :V$DT1, :V$DT2, :S, :V$TYPE
  DO
  BEGIN
    IF(:I$DATE IS NULL OR V$DT >= :I$DATE OR V$DT0 >= :I$DATE OR V$DT1 >= :I$DATE OR V$DT2 >= :I$DATE) THEN
    BEGIN
      TAG_NAME = 'programfolders:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'programfolders:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      IF(V$DT IS NOT NULL) THEN
      BEGIN
        TAG_NAME = 'programfolders:r:deleted';
        VAL = 1;
        SUSPEND;
      END
      ELSE
      BEGIN
        TAG_NAME = 'programfolders:r:type';
        VAL = V$TYPE;
        SUSPEND;
        TAG_NAME = 'programfolders:r:name';
        VAL = S;
        SUSPEND;
      END
    END
  END

  -- Образовательные программы
  TAG_NAME = 'programs::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L57.PARENT_ID, L57.OBJ_ID, L57.DATE_DEL, L57.DATE_MODIFY, V386.DATE_MODIFY, V1832.DATE_MODIFY, V1891.DATE_MODIFY, V2833.DATE_MODIFY,
      V386.VAL, V1832.LISTVAL_ID, IIF(V1891.LISTVAL_ID IS NULL OR V1891.LISTVAL_ID = 3, 0, 1), IIF(V2833.LISTVAL_ID IS NULL OR V2833.LISTVAL_ID = 3, 0, 1)
    FROM LINKS L57
    LEFT JOIN VALS V386 ON V386.OBJ_ID = L57.OBJ_ID AND V386.PARAM_ID = 386 AND V386.IS_DEL = 0
    LEFT JOIN VALL V1832 ON V1832.OBJ_ID = L57.OBJ_ID AND V1832.PARAM_ID = 1832 AND V1832.IS_DEL = 0
    LEFT JOIN VALL V1891 ON V1891.OBJ_ID = L57.OBJ_ID AND V1891.PARAM_ID = 1891 AND V1891.IS_DEL = 0
    LEFT JOIN VALL V2833 ON V2833.OBJ_ID = L57.OBJ_ID AND V2833.PARAM_ID = 2833 AND V2833.IS_DEL = 0
    WHERE L57.PARENT_TYPE_ID = 69 AND L57.OBJ_TYPE_ID = 57
    INTO :V$PARENT_ID, :V$OBJ_ID, :V$DT, :V$DT0, :V$DT1, :V$DT2, :V$DT3, :V$DT4, :S, :V$TYPE, :V$N1, :V$N2
  DO
  BEGIN
    IF(:I$DATE IS NULL OR V$DT >= :I$DATE OR V$DT0 >= :I$DATE OR V$DT1 >= :I$DATE OR V$DT2 >= :I$DATE OR V$DT3 >= :I$DATE OR V$DT4 >= :I$DATE) THEN
    BEGIN
      TAG_NAME = 'programs:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'programs:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      IF(V$DT IS NOT NULL) THEN
      BEGIN
        TAG_NAME = 'programs:r:deleted';
        VAL = 1;
        SUSPEND;
      END
      ELSE
      BEGIN
        TAG_NAME = 'programs:r:catalog_id';
        VAL = V$PARENT_ID;
        SUSPEND;
        TAG_NAME = 'programs:r:type';
        VAL = V$TYPE;
        SUSPEND;
        TAG_NAME = 'programs:r:name';
        VAL = S;
        SUSPEND;
        TAG_NAME = 'programs:r:is_network';
        VAL = V$N1;
        SUSPEND;
        TAG_NAME = 'programs:r:is_remote';
        VAL = V$N2;
        SUSPEND;
        TAG_NAME = 'programs:r:duration_stages';
        VAL = NULL;
        SUSPEND;
      END
    END
  END

  -- Сами УП
  TAG_NAME = 'plans::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L400.PARENT_ID, L400.OBJ_ID, L400.DATE_DEL, L400.DATE_MODIFY, V3012.DATE_MODIFY, V3013.DATE_MODIFY, V3016.DATE_MODIFY, V3015.DATE_MODIFY,
      V3154.DATE_MODIFY, V3018.DATE_MODIFY, V3019.DATE_MODIFY, V3153.DATE_MODIFY,
      V3012.VAL, V3013.LISTVAL_ID, V3016.LISTVAL_ID, V3015.LISTVAL_ID, V3154.VAL, V3018.VAL, V3019.VAL, V3153.VAL
    FROM LINKS L400
    LEFT JOIN VALS V3012 ON V3012.OBJ_ID = L400.OBJ_ID AND V3012.PARAM_ID = 3012 AND V3012.IS_DEL = 0
    LEFT JOIN VALL V3013 ON V3013.OBJ_ID = L400.OBJ_ID AND V3013.PARAM_ID = 3013 AND V3013.IS_DEL = 0
    LEFT JOIN VALL V3016 ON V3016.OBJ_ID = L400.OBJ_ID AND V3016.PARAM_ID = 3016 AND V3016.IS_DEL = 0
    LEFT JOIN VALL V3015 ON V3015.OBJ_ID = L400.OBJ_ID AND V3015.PARAM_ID = 3015 AND V3015.IS_DEL = 0
    LEFT JOIN VALS V3018 ON V3018.OBJ_ID = L400.OBJ_ID AND V3018.PARAM_ID = 3018 AND V3018.IS_DEL = 0
    LEFT JOIN VALD V3019 ON V3019.OBJ_ID = L400.OBJ_ID AND V3019.PARAM_ID = 3019 AND V3019.IS_DEL = 0
    LEFT JOIN VALS V3154 ON V3154.OBJ_ID = L400.OBJ_ID AND V3154.PARAM_ID = 3154 AND V3154.IS_DEL = 0
    LEFT JOIN VALS V3153 ON V3153.OBJ_ID = L400.OBJ_ID AND V3153.PARAM_ID = 3153 AND V3153.IS_DEL = 0
    WHERE L400.PARENT_TYPE_ID = 57 AND L400.OBJ_TYPE_ID = 400 AND (:I$DATE IS NULL OR L400.DATE_MODIFY >= :I$DATE)
    INTO :V$PARENT_ID, :V$OBJ_ID, :V$DT, :V$DT0, :V$DT1, :V$DT2, :V$DT3, :V$DT4, :V$DT5, :V$DT6, :V$DT7, :V$DT8,
      :S, :V$TYPE, :V$TYPE2, :V$FORM, :V$CODE, :V$ORDER_NUM, :V$ORDER_DATE, :S2
  DO
  BEGIN
    IF(:I$DATE IS NULL OR V$DT >= :I$DATE OR V$DT0 >= :I$DATE OR V$DT1 >= :I$DATE OR V$DT2 >= :I$DATE OR V$DT3 >= :I$DATE OR V$DT4 >= :I$DATE
       OR V$DT5 >= :I$DATE OR V$DT6 >= :I$DATE OR V$DT7 >= :I$DATE OR V$DT8 >= :I$DATE) THEN
    BEGIN
      TAG_NAME = 'plans:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'plans:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      IF(V$DT IS NOT NULL) THEN
      BEGIN
        TAG_NAME = 'plans:r:deleted';
        VAL = 1;
        SUSPEND;
      END
      ELSE
      BEGIN
        TAG_NAME = 'plans:r:op_id';
        VAL = V$PARENT_ID;
        SUSPEND;
        TAG_NAME = 'plans:r:state_id';
        VAL = V$TYPE;
        SUSPEND;
        TAG_NAME = 'plans:r:name';
        VAL = S;
        SUSPEND;
        TAG_NAME = 'plans:r:type_id';
        VAL = V$TYPE2;
        SUSPEND;
        TAG_NAME = 'plans:r:study_form_id';
        VAL = V$FORM;
        SUSPEND;
        TAG_NAME = 'plans:r:dpo_code';
        VAL = V$CODE;
        SUSPEND;
        TAG_NAME = 'plans:r:description';
        VAL = S2;
        SUSPEND;
        TAG_NAME = 'plans:r:order_date';
        VAL = (SELECT VAL FROM DATE2ISO(:V$ORDER_DATE, 0));
        SUSPEND;
        TAG_NAME = 'plans:r:order_num';
        VAL = V$ORDER_NUM;
        SUSPEND;
        TAG_NAME = 'plans:r:load_hours';
        VAL = NULL;
        SELECT SUM(COALESCE(PL.LOAD_HOURS_S1, 0) + COALESCE(PL.LOAD_HOURS_S2, 0))
        FROM PLAN_SUBJECTS PS
        JOIN PLAN_LOADS PL ON PL.DATE_DEL IS NULL AND PL.SUBJECT_ID = PS.OBJ_ID
        WHERE PS.DATE_DEL IS NULL AND PS.PLAN_ID = :V$OBJ_ID AND PS.ROW_TYPE = 10
        INTO :VAL;
        SUSPEND;
      END
    END
  END

  -- Группы
  TAG_NAME = 'dpogroups::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L46.OBJ_ID, L46.DATE_DEL, L46.DATE_MODIFY, V549.DATE_MODIFY, V2823.DATE_MODIFY, V2959.DATE_MODIFY, V2960.DATE_MODIFY, V369.DATE_MODIFY,
      V2137.DATE_MODIFY, V2825.DATE_MODIFY, NULL,
      V549.VAL, V2823.VAL, V2959.VAL, V2960.VAL, V369.LISTVAL_ID, V2137.LISTVAL_ID, V2825.LISTVAL_ID
    FROM LINKS L46
    LEFT JOIN VALS V549 ON V549.OBJ_ID = L46.OBJ_ID AND V549.PARAM_ID = 549 AND V549.IS_DEL = 0
    LEFT JOIN VALR V2823 ON V2823.OBJ_ID = L46.OBJ_ID AND V2823.PARAM_ID = 2823 AND V2823.IS_DEL = 0
    LEFT JOIN VALD V2959 ON V2959.OBJ_ID = L46.OBJ_ID AND V2959.PARAM_ID = 2959 AND V2959.IS_DEL = 0
    LEFT JOIN VALD V2960 ON V2960.OBJ_ID = L46.OBJ_ID AND V2960.PARAM_ID = 2960 AND V2960.IS_DEL = 0
    LEFT JOIN VALL V369 ON V369.OBJ_ID = L46.OBJ_ID AND V369.PARAM_ID = 369 AND V369.IS_DEL = 0
    LEFT JOIN VALL V2137 ON V2137.OBJ_ID = L46.OBJ_ID AND V2137.PARAM_ID = 2137 AND V2137.IS_DEL = 0
    LEFT JOIN VALL V2825 ON V2825.OBJ_ID = L46.OBJ_ID AND V2825.PARAM_ID = 2825 AND V2825.IS_DEL = 0
    WHERE L46.PARENT_TYPE_ID = 86 AND L46.OBJ_TYPE_ID = 46
    INTO :V$OBJ_ID, :V$DT, :V$DT0, :V$DT1, :V$DT2, :V$DT3, :V$DT4, :V$DT5, :V$DT6, :V$DT7, :V$DT8,
      :S, :V$PARENT_ID, :V$D1, :V$D2, :V$TYPE, :V$FORM, :V$TYPE2
  DO
  BEGIN
    IF(:I$DATE IS NULL OR V$DT >= :I$DATE OR V$DT0 >= :I$DATE OR V$DT1 >= :I$DATE OR V$DT2 >= :I$DATE OR V$DT3 >= :I$DATE OR V$DT4 >= :I$DATE
       OR V$DT5 >= :I$DATE OR V$DT6 >= :I$DATE OR V$DT7 >= :I$DATE OR V$DT8 >= :I$DATE) THEN
    BEGIN
      TAG_NAME = 'dpogroups:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'dpogroups:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      IF(V$DT IS NOT NULL) THEN
      BEGIN
        TAG_NAME = 'dpogroups:r:deleted';
        VAL = 1;
        SUSPEND;
      END
      ELSE
      BEGIN
        TAG_NAME = 'dpogroups:r:plan_id';
        VAL = V$PARENT_ID;
        SUSPEND;
        TAG_NAME = 'dpogroups:r:name';
        VAL = S;
        SUSPEND;
        TAG_NAME = 'dpogroups:r:type_id';
        VAL = V$TYPE;
        SUSPEND;
        TAG_NAME = 'dpogroups:r:form_id';
        VAL = V$FORM;
        SUSPEND;
        TAG_NAME = 'dpogroups:r:financing_id';
        VAL = V$TYPE2;
        SUSPEND;
        TAG_NAME = 'dpogroups:r:state_id';
        VAL = 0;
        SUSPEND;
        TAG_NAME = 'dpogroups:r:date_from';
        VAL = (SELECT VAL FROM DATE2ISO(:V$D1, 0));
        SUSPEND;
        TAG_NAME = 'dpogroups:r:date_to';
        VAL = (SELECT VAL FROM DATE2ISO(:V$D2, 0));
        SUSPEND;
      END
    END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE RKS_SERIALIZE_GRADES RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$TYPE_ID BIGINT;
DECLARE VARIABLE V$GRADE_ID BIGINT;
DECLARE VARIABLE V$STAGE_ID BIGINT;
DECLARE VARIABLE V$EXIT BIGINT;
DECLARE VARIABLE V$GT BIGINT;
DECLARE VARIABLE V$GC BIGINT;
DECLARE VARIABLE S VARCHAR(400);
BEGIN

  TAG_NAME = 'grades::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L9.OBJ_TYPE_ID, L9.OBJ_TYPE_ID, V49.LISTVAL_ID, V54.SVAL, V1362.LISTVAL_ID, V592.LISTVAL_ID, V554.LISTVAL_ID
    FROM LINKS L2
    JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID IN (7, 502) AND L7.DATE_DEL IS NULL
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 125, 187, 403) AND L9.DATE_DEL IS NULL
    LEFT JOIN VALS V54 ON V54.OBJ_ID = L9.OBJ_ID AND V54.PARAM_ID IN (54, 820, 1652, 3026) AND V54.IS_DEL = 0
    LEFT JOIN VALL V1362 ON V1362.OBJ_ID = L9.OBJ_ID AND V1362.PARAM_ID IN (1362, 2419, 2418) AND V1362.IS_DEL = 0
    LEFT JOIN VALL V592 ON V592.OBJ_ID = L9.OBJ_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0
    LEFT JOIN VALL V554 ON V554.OBJ_ID = L9.OBJ_ID AND V554.PARAM_ID = 554 AND V554.IS_DEL = 0
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :V$TYPE_ID, :V$GRADE_ID, :V$STAGE_ID, :S, :V$EXIT, :V$GT, :V$GC
  DO
  BEGIN
    TAG_NAME = 'grades:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'grades:r:id';
    VAL = V$GRADE_ID;
    SUSPEND;
    TAG_NAME = 'grades:r:type_id';
    VAL = V$TYPE_ID;
    SUSPEND;
    TAG_NAME = 'grades:r:stage_id';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'grades:r:name';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'grades:r:graduate';
    VAL = V$EXIT;
    SUSPEND;
    TAG_NAME = 'grades:r:ovzcontent';
    VAL = V$GT;
    SUSPEND;
    TAG_NAME = 'grades:r:ovztype';
    VAL = V$GC;
    SUSPEND;
  END

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE RKS_SERIALIZE_HEADERS (
    I$DATE TIMESTAMP,
    I$ORGDATA SMALLINT = 0)
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(1000))
AS
declare variable V$ID bigint;
declare variable V$S varchar(1000);
declare variable V$STATUS char(1);
begin

  V$STATUS = (SELECT STATUS FROM OU_LICENCE_TYPE);

  TAG_NAME = 'headers:org_id';
  VAL = NULL;
  SELECT FIRST 1 L2.OBJ_ID
  FROM LINKS L2
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$ID;
  VAL = V$ID;
  IF(VAL IS NULL) THEN EXCEPTION DATA_ERROR 'Запись организации не найдена';
  SUSPEND;

  TAG_NAME = 'headers:timemark';
  VAL = (SELECT VAL FROM DATE2ISO(:I$DATE, 1));
  SUSPEND;

  TAG_NAME = 'headers:now';
  VAL = (SELECT VAL FROM DATE2ISO(CURRENT_TIMESTAMP, 1));
  SUSPEND;

  -- Серийный номер базы
  TAG_NAME = 'headers:dbserial';
  VAL = NULL;
  SELECT FIRST 1 INFO_VAL FROM INFO WHERE INFO_CODE = 'LAST_BACKUP' INTO :VAL;
  SUSPEND;

  -- Версия FB
  TAG_NAME = 'headers:dbversion';
  VAL = NULL;
  SELECT RDB$GET_CONTEXT('SYSTEM', 'ENGINE_VERSION') FROM RDB$DATABASE INTO :VAL;
  SUSPEND;

  -- Реквизиты организации
  IF(I$ORGDATA <> 0) THEN
  BEGIN
    TAG_NAME = 'orgdata:status';
    VAL = (SELECT LISTVAL_ID FROM VALL WHERE OBJ_ID = :V$ID AND PARAM_ID = 2371 AND IS_DEL = 0);
    SUSPEND;

    TAG_NAME = 'orgdata:inn';
    VAL = (SELECT VAL FROM VALS WHERE OBJ_ID = :V$ID AND PARAM_ID = 33 AND IS_DEL = 0);
    SUSPEND;

    TAG_NAME = 'orgdata:ogrn';
    VAL = (SELECT VAL FROM VALS WHERE OBJ_ID = :V$ID AND PARAM_ID = 9 AND IS_DEL = 0);
    SUSPEND;

    -- В колледжах вместо параметра 2 выдаем
    TAG_NAME = 'orgdata:name_short';
    IF(V$STATUS = 'C') THEN
    VAL = (SELECT VAL FROM VALS WHERE OBJ_ID = :V$ID AND PARAM_ID = 999 AND IS_DEL = 0);
    ELSE
    VAL = (SELECT VAL FROM VALS WHERE OBJ_ID = :V$ID AND PARAM_ID = 2 AND IS_DEL = 0);
    SUSPEND;

    TAG_NAME = 'orgdata:name_full';
    VAL = (SELECT VAL FROM VALS WHERE OBJ_ID = :V$ID AND PARAM_ID = 5 AND IS_DEL = 0);
    SUSPEND;

    -- Руководитель
    SELECT POST, F || ' ' || I || COALESCE(' ' || O, '')
    FROM R_SPB_POST_DIRECTOR(:V$ID, 1)
    INTO :VAL, :V$S;

    TAG_NAME = 'orgdata:head_post';
    SUSPEND;

    TAG_NAME = 'orgdata:head_fio';
    VAL = V$S;
    SUSPEND;

    TAG_NAME = 'orgdata:reg_address';
    VAL = (SELECT VAL FROM ADR_GET(27, :V$ID));
    SUSPEND;

    TAG_NAME = 'orgdata:gia_code';
    VAL = (SELECT VAL FROM VALI WHERE OBJ_ID = :V$ID AND PARAM_ID = 1364 AND IS_DEL = 0);
    SUSPEND;

    TAG_NAME = 'orgdata:ppe_code';
    VAL = (SELECT VAL FROM VALI WHERE OBJ_ID = :V$ID AND PARAM_ID = 1365 AND IS_DEL = 0);
    SUSPEND;

    TAG_NAME = 'orgdata:org_type';
    VAL = (SELECT LISTVAL_ID FROM VALL WHERE OBJ_ID = :V$ID AND PARAM_ID = 1890 AND IS_DEL = 0);
    SUSPEND;

    TAG_NAME = 'orgdata:prop_type';
    VAL = NULL;
    SUSPEND;

    TAG_NAME = 'orgdata:opf';
    VAL = (SELECT LISTVAL_ID FROM VALL WHERE OBJ_ID = :V$ID AND PARAM_ID = 8 AND IS_DEL = 0);
    SUSPEND;

    TAG_NAME = 'orgdata:phones';
    VAL = (SELECT VAL FROM VALS WHERE OBJ_ID = :V$ID AND PARAM_ID = 29 AND IS_DEL = 0);
    SUSPEND;

    TAG_NAME = 'orgdata:faxes';
    VAL = (SELECT VAL FROM VALS WHERE OBJ_ID = :V$ID AND PARAM_ID = 30 AND IS_DEL = 0);
    SUSPEND;

    TAG_NAME = 'orgdata:email';
    VAL = (SELECT VAL FROM VALS WHERE OBJ_ID = :V$ID AND PARAM_ID = 35 AND IS_DEL = 0);
    SUSPEND;

    TAG_NAME = 'orgdata:website';
    VAL = (SELECT VAL FROM VALS WHERE OBJ_ID = :V$ID AND PARAM_ID = 36 AND IS_DEL = 0);
    SUSPEND;

    TAG_NAME = 'orgdata:fisoko_id';
    VAL = (SELECT VAL FROM VALS WHERE OBJ_ID = :V$ID AND PARAM_ID = 2951 AND IS_DEL = 0);
    SUSPEND;

    TAG_NAME = 'orgdata:appversion';
    VAL = (SELECT VER_MAJOR || '.' || VER_MINOR || '.' || VER_RELEASE || '.' || VER_BUILD FROM VER);
    SUSPEND;

  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE RKS_SERIALIZE_NOULS RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
declare variable V varchar(100);
begin

  -- Только действующие сотрудники, обучающиеся и предварительный прием
  -- родители - разборки персонально
  -- сотрудников временно прячем из-за отсутствия поля

  TAG_NAME = 'no_uls::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT DISTINCT V2912.SVAL
    FROM LINKS L2
    JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
    JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    JOIN VALS V2912 ON V2912.OBJ_ID = L10.OBJ_ID AND V2912.PARAM_ID = 2912 AND V2912.IS_DEL = 0
    LEFT JOIN VALS V3482 ON V3482.OBJ_ID = L10.OBJ_ID AND V3482.PARAM_ID = 3482 AND V3482.IS_DEL = 0
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND V3482.VAL IS NULL
    UNION
    SELECT DISTINCT V2912.SVAL
    FROM LINKS L2
    JOIN LINKS L77 ON L77.PARENT_ID = L2.OBJ_ID AND L77.OBJ_TYPE_ID = 77 AND L77.DATE_DEL IS NULL
    JOIN LINKS L290 ON L290.PARENT_ID = L77.OBJ_ID AND L290.OBJ_TYPE_ID = 290 AND L290.DATE_DEL IS NULL
    JOIN LINKS L10 ON L10.PARENT_ID = L290.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    JOIN VALS V2912 ON V2912.OBJ_ID = L10.OBJ_ID AND V2912.PARAM_ID = 2912 AND V2912.IS_DEL = 0
    LEFT JOIN VALS V3482 ON V3482.OBJ_ID = L10.OBJ_ID AND V3482.PARAM_ID = 3482 AND V3482.IS_DEL = 0
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND V3482.VAL IS NULL
    INTO :V
  DO
  BEGIN
    TAG_NAME = 'no_uls:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'no_uls:r:id';
    VAL = V;
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE RKS_SERIALIZE_OODATA (
    I$DT TIMESTAMP)
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(4000))
AS
declare variable V$OBJ_ID bigint;
declare variable V$DT timestamp;
declare variable V$DT2 timestamp;
declare variable S varchar(1000);
declare variable S2 varchar(1000);
declare variable S3 varchar(1000);
declare variable S4 varchar(1000);
declare variable S5 varchar(1000);
declare variable F1 float;
declare variable F2 float;
declare variable F3 float;
declare variable F4 float;
declare variable F5 float;
declare variable LV1 bigint;
declare variable LV2 bigint;
declare variable LV3 bigint;
declare variable LV4 bigint;
declare variable REF1 bigint;
declare variable D1 date;
declare variable D2 date;
declare variable D3 date;
declare variable I1 integer;
declare variable I2 integer;
declare variable I3 integer;
declare variable I4 integer;
declare variable I5 integer;
declare variable B1 bigint;
begin

  -- Земельные участки
  TAG_NAME = 'steads::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L490.OBJ_ID, MAXVALUE(L490.DATE_MODIFY, V3403.DATE_MODIFY, V3400.DATE_MODIFY, V3402.DATE_MODIFY, V3404.DATE_MODIFY, V3405.DATE_MODIFY),
      V3403.VAL, V3400.VAL, V3402.VAL, V3404.LISTVAL_ID, V3405.VAL, A.VAL, A.STREETGUID
    FROM LINKS L2
    JOIN LINKS L488 ON L488.PARENT_ID = L2.OBJ_ID AND L488.OBJ_TYPE_ID = 488 AND L488.DATE_DEL IS NULL
    JOIN LINKS L490 ON L490.PARENT_ID = L488.OBJ_ID AND L490.OBJ_TYPE_ID = 490 AND L490.DATE_DEL IS NULL
    JOIN VALS V3403 ON V3403.OBJ_ID = L490.OBJ_ID AND V3403.PARAM_ID = 3403 AND V3403.IS_DEL = 0 -- название
    JOIN VALS V3400 ON V3400.OBJ_ID = L490.OBJ_ID AND V3400.PARAM_ID = 3400 AND V3400.IS_DEL = 0 -- кадаст
    LEFT JOIN VALF V3402 ON V3402.OBJ_ID = L490.OBJ_ID AND V3402.PARAM_ID = 3402 AND V3402.IS_DEL = 0 -- площадь
    LEFT JOIN VALL V3404 ON V3404.OBJ_ID = L490.OBJ_ID AND V3404.PARAM_ID = 3404 AND V3404.IS_DEL = 0 -- ограждение
    LEFT JOIN VALF V3405 ON V3405.OBJ_ID = L490.OBJ_ID AND V3405.PARAM_ID = 3405 AND V3405.IS_DEL = 0 -- высота огр
    LEFT JOIN ADR_GET(3401, L490.OBJ_ID) A ON 1 = 1 -- адрес
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :V$OBJ_ID, :V$DT, :S, :S2, :F1, :LV1, :F2, :S3, :S4
  DO
  BEGIN
    IF(I$DT IS NULL OR V$DT >= I$DT) THEN
    BEGIN
      TAG_NAME = 'steads:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'steads:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'steads:r:name';
      VAL = S;
      SUSPEND;
      TAG_NAME = 'steads:r:code';
      VAL = S3;
      SUSPEND;
      TAG_NAME = 'steads:r:square';
      VAL = CAST(F1 AS NUMERIC(18, 2));
      SUSPEND;
      TAG_NAME = 'steads:r:fence_type';
      VAL = LV1;
      SUSPEND;
      TAG_NAME = 'steads:r:fence_height';
      VAL = CAST(F2 AS NUMERIC(18, 2));
      SUSPEND;
      TAG_NAME = 'steads:r:address';
      VAL = S3;
      SUSPEND;
      TAG_NAME = 'steads:r:street_id';
      VAL = S4;
      SUSPEND;
    END
  END

  -- Здания
  TAG_NAME = 'buildings::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L16.OBJ_ID,
      MAXVALUE(L16.DATE_MODIFY, V421.DATE_MODIFY, V3167.DATE_MODIFY, V3408.DATE_MODIFY, V496.DATE_MODIFY, V497.DATE_MODIFY, V498.DATE_MODIFY, V499.DATE_MODIFY,
        V3166.DATE_MODIFY, V493.DATE_MODIFY, V3163.DATE_MODIFY, V3164.DATE_MODIFY, V3165.DATE_MODIFY, V500.DATE_MODIFY, V501.DATE_MODIFY, V502.DATE_MODIFY, V503.DATE_MODIFY,
        V485.DATE_MODIFY, V504.DATE_MODIFY, V3168.DATE_MODIFY),
      V421.VAL, V3167.VAL, V3408.VAL, A.VAL, A.STREETGUID,
      V496.VAL, V497.VAL, V498.VAL, V499.VAL, V3166.VAL, V493.VAL, V3163.VAL, V3164.VAL, V3165.LISTVAL_ID,
      V500.VAL, V501.VAL, V502.VAL, V503.VAL, V3099.I, V485.LISTVAL_ID, V504.LISTVAL_ID, V3168.LISTVAL_ID
    FROM LINKS L2
    JOIN LINKS L73 ON L73.PARENT_ID = L2.OBJ_ID AND L73.OBJ_TYPE_ID = 73 AND L73.DATE_DEL IS NULL
    JOIN LINKS L16 ON L16.PARENT_ID = L73.OBJ_ID AND L16.OBJ_TYPE_ID = 16 AND L16.DATE_DEL IS NULL
    JOIN VALS V421 ON V421.OBJ_ID = L16.OBJ_ID AND V421.PARAM_ID = 421 AND V421.IS_DEL = 0 -- название
    JOIN VALS V3167 ON V3167.OBJ_ID = L16.OBJ_ID AND V3167.PARAM_ID = 3167 AND V3167.IS_DEL = 0 -- кадаст
    LEFT JOIN VALR V3408 ON V3408.OBJ_ID = L16.OBJ_ID AND V3408.PARAM_ID = 3408 AND V3408.IS_DEL = 0 -- земельный участок
    LEFT JOIN VALF V496 ON V496.OBJ_ID = L16.OBJ_ID AND V496.PARAM_ID = 496 AND V496.IS_DEL = 0 -- площадь
    LEFT JOIN VALF V497 ON V497.OBJ_ID = L16.OBJ_ID AND V497.PARAM_ID = 497 AND V497.IS_DEL = 0 -- кубатура
    LEFT JOIN VALF V498 ON V498.OBJ_ID = L16.OBJ_ID AND V498.PARAM_ID = 498 AND V498.IS_DEL = 0 -- полезная площадь
    LEFT JOIN VALF V499 ON V499.OBJ_ID = L16.OBJ_ID AND V499.PARAM_ID = 499 AND V499.IS_DEL = 0 -- площадь уч-лаб
    LEFT JOIN VALF V3166 ON V3166.OBJ_ID = L16.OBJ_ID AND V3166.PARAM_ID = 3166 AND V3166.IS_DEL = 0 -- площадь застройки
    LEFT JOIN VALD V493 ON V493.OBJ_ID = L16.OBJ_ID AND V493.PARAM_ID = 493 AND V493.IS_DEL = 0 -- дата постройки
    LEFT JOIN VALD V3163 ON V3163.OBJ_ID = L16.OBJ_ID AND V3163.PARAM_ID = 3163 AND V3163.IS_DEL = 0 -- дата начала эксплуатации
    LEFT JOIN VALD V3164 ON V3164.OBJ_ID = L16.OBJ_ID AND V3164.PARAM_ID = 3164 AND V3164.IS_DEL = 0 -- дата окончания эксплуатации
    LEFT JOIN VALL V3165 ON V3165.OBJ_ID = L16.OBJ_ID AND V3165.PARAM_ID = 3165 AND V3165.IS_DEL = 0 -- причина окончания эксплуатации
    LEFT JOIN VALI V500 ON V500.OBJ_ID = L16.OBJ_ID AND V500.PARAM_ID = 500 AND V500.IS_DEL = 0 -- кол-во учпом проектное
    LEFT JOIN VALI V501 ON V501.OBJ_ID = L16.OBJ_ID AND V501.PARAM_ID = 501 AND V501.IS_DEL = 0 -- кол-во учпом факт
    LEFT JOIN VALI V502 ON V502.OBJ_ID = L16.OBJ_ID AND V502.PARAM_ID = 502 AND V502.IS_DEL = 0 -- кол-во учеников проектное
    LEFT JOIN VALI V503 ON V503.OBJ_ID = L16.OBJ_ID AND V503.PARAM_ID = 503 AND V503.IS_DEL = 0 -- кол-во учеников нормативное
    LEFT JOIN VAL_GET(3099, L16.OBJ_ID) V3099 ON 1 = 1 -- кол-во посадочных мест фактическое
    LEFT JOIN VALL V485 ON V485.OBJ_ID = L16.OBJ_ID AND V485.PARAM_ID = 485 AND V485.IS_DEL = 0 -- назначение
    LEFT JOIN VALL V504 ON V504.OBJ_ID = L16.OBJ_ID AND V504.PARAM_ID = 504 AND V504.IS_DEL = 0 -- форма владения
    LEFT JOIN VALL V3168 ON V3168.OBJ_ID = L16.OBJ_ID AND V3168.PARAM_ID = 3168 AND V3168.IS_DEL = 0 -- отраслевая принадлежность
    LEFT JOIN ADR_GET(420, L16.OBJ_ID) A ON 1 = 1 -- адрес
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :V$OBJ_ID, :V$DT, :S, :S2, :REF1, :S3, :S4,
      :F1, :F2, :F3, :F4, :F5, :D1, :D2, :D3, :LV1,
      :I1, :I2, :I3, :I4, :I5, :LV2, :LV3, :LV4
  DO
  BEGIN
    IF(I$DT IS NULL OR V$DT >= I$DT) THEN
    BEGIN
      TAG_NAME = 'buildings:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'buildings:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'buildings:r:name';
      VAL = S;
      SUSPEND;
      TAG_NAME = 'buildings:r:code';
      VAL = S2;
      SUSPEND;
      TAG_NAME = 'buildings:r:address';
      VAL = S3;
      SUSPEND;
      TAG_NAME = 'buildings:r:street_id';
      VAL = S4;
      SUSPEND;
      TAG_NAME = 'buildings:r:stead_id';
      VAL = REF1;
      SUSPEND;
      TAG_NAME = 'buildings:r:square_all';
      VAL = CAST(F1 AS NUMERIC(18, 2));
      SUSPEND;
      TAG_NAME = 'buildings:r:volume';
      VAL = CAST(F2 AS NUMERIC(18, 2));
      SUSPEND;
      TAG_NAME = 'buildings:r:square_use';
      VAL = CAST(F3 AS NUMERIC(18, 2));
      SUSPEND;
      TAG_NAME = 'buildings:r:square_lab';
      VAL = CAST(F4 AS NUMERIC(18, 2));
      SUSPEND;
      TAG_NAME = 'buildings:r:square_build';
      VAL = CAST(F5 AS NUMERIC(18, 2));
      SUSPEND;
      TAG_NAME = 'buildings:r:build_date';
      VAL = (SELECT VAL FROM DATE2ISO(:D1, 0));
      SUSPEND;
      TAG_NAME = 'buildings:r:use_date_start';
      VAL = (SELECT VAL FROM DATE2ISO(:D2, 0));
      SUSPEND;
      TAG_NAME = 'buildings:r:use_date_end';
      VAL = (SELECT VAL FROM DATE2ISO(:D3, 0));
      SUSPEND;
      TAG_NAME = 'buildings:r:use_end_reason';
      VAL = LV1;
      SUSPEND;
      TAG_NAME = 'buildings:r:labrooms_prj';
      VAL = I1;
      SUSPEND;
      TAG_NAME = 'buildings:r:labrooms_fact';
      VAL = I2;
      SUSPEND;
      TAG_NAME = 'buildings:r:places_prj';
      VAL = I3;
      SUSPEND;
      TAG_NAME = 'buildings:r:places_norm';
      VAL = I4;
      SUSPEND;
      TAG_NAME = 'buildings:r:places_fact';
      VAL = I5;
      SUSPEND;
      TAG_NAME = 'buildings:r:purpose';
      VAL = LV2;
      SUSPEND;
      TAG_NAME = 'buildings:r:own_form';
      VAL = LV3;
      SUSPEND;
      TAG_NAME = 'buildings:r:ind_type';
      VAL = LV4;
      SUSPEND;
    END
  END

  -- Сооружения
  TAG_NAME = 'ifobjects::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L492.OBJ_ID,
      MAXVALUE(L492.DATE_MODIFY, V3406.DATE_MODIFY, V3407.DATE_MODIFY, V3398.DATE_MODIFY, V3410.DATE_MODIFY, V3411.DATE_MODIFY),
      V3406.VAL, V3398.LISTVAL_ID, V3407.VAL, V3410.VAL, V3411.VAL
    FROM LINKS L2
    JOIN LINKS L73 ON L73.PARENT_ID = L2.OBJ_ID AND L73.OBJ_TYPE_ID = 73 AND L73.DATE_DEL IS NULL
    JOIN LINKS L492 ON L492.PARENT_ID = L73.OBJ_ID AND L492.OBJ_TYPE_ID = 492 AND L492.DATE_DEL IS NULL
    JOIN VALS V3406 ON V3406.OBJ_ID = L492.OBJ_ID AND V3406.PARAM_ID = 3406 AND V3406.IS_DEL = 0 -- название
    JOIN VALL V3398 ON V3398.OBJ_ID = L492.OBJ_ID AND V3398.PARAM_ID = 3398 AND V3398.IS_DEL = 0 -- тип
    LEFT JOIN VALR V3407 ON V3407.OBJ_ID = L492.OBJ_ID AND V3407.PARAM_ID = 3407 AND V3407.IS_DEL = 0 -- земельный участок
    LEFT JOIN VALD V3410 ON V3410.OBJ_ID = L492.OBJ_ID AND V3410.PARAM_ID = 3410 AND V3410.IS_DEL = 0 -- дата ввода
    LEFT JOIN VALD V3411 ON V3411.OBJ_ID = L492.OBJ_ID AND V3411.PARAM_ID = 3411 AND V3411.IS_DEL = 0 -- дата вывода
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :V$OBJ_ID, :V$DT, :S, :LV1, :REF1, :D1, :D2
  DO
  BEGIN
    IF(I$DT IS NULL OR V$DT >= I$DT) THEN
    BEGIN
      TAG_NAME = 'ifobjects:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'ifobjects:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'ifobjects:r:name';
      VAL = S;
      SUSPEND;
      TAG_NAME = 'ifobjects:r:type_id';
      VAL = LV1;
      SUSPEND;
      TAG_NAME = 'ifobjects:r:stead_id';
      VAL = REF1;
      SUSPEND;
      TAG_NAME = 'ifobjects:r:use_date_start';
      VAL = (SELECT VAL FROM DATE2ISO(:D1, 0));
      SUSPEND;
      TAG_NAME = 'ifobjects:r:use_date_end';
      VAL = (SELECT VAL FROM DATE2ISO(:D2, 0));
      SUSPEND;
    END
  END

  -- Документы жизненного цикла организации
  TAG_NAME = 'lcd::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L497.OBJ_ID,
      MAXVALUE(L497.DATE_MODIFY, V3430.DATE_MODIFY, V3431.DATE_MODIFY, V3432.DATE_MODIFY, V3433.DATE_MODIFY, V471.DATE_MODIFY, V596.DATE_MODIFY,
        V482.DATE_MODIFY, V479.DATE_MODIFY, V480.DATE_MODIFY, V598.DATE_MODIFY, V478.DATE_MODIFY, V597.DATE_MODIFY),
      V3430.LISTVAL_ID, V3431.VAL, V3432.VAL, V3434.VAL, V3433.VAL, V471.LISTVAL_ID, V596.VAL,
      V482.VAL, COALESCE(V479.SVAL || ' ', '') || COALESCE(V480.SVAL, ''), V598.SVAL, COALESCE(V597.VAL, V478.VAL), COALESCE(V597.BLOB_ID, V478.BLOB_ID)
    FROM LINKS L2
    JOIN LINKS L497 ON L497.PARENT_ID = L2.OBJ_ID AND L497.OBJ_TYPE_ID = 497 AND L497.DATE_DEL IS NULL
    JOIN VALL V3430 ON V3430.OBJ_ID = L497.OBJ_ID AND V3430.PARAM_ID = 3430 AND V3430.IS_DEL = 0 -- статус
    JOIN VALD V3431 ON V3431.OBJ_ID = L497.OBJ_ID AND V3431.PARAM_ID = 3431 AND V3431.IS_DEL = 0 -- дата начала
    LEFT JOIN VALD V3432 ON V3432.OBJ_ID = L497.OBJ_ID AND V3432.PARAM_ID = 3432 AND V3432.IS_DEL = 0 -- дата окончания
    LEFT JOIN VALS V3434 ON V3434.OBJ_ID = L497.OBJ_ID AND V3434.PARAM_ID = 3434 AND V3434.IS_DEL = 0 -- описание
    JOIN VALR V3433 ON V3433.OBJ_ID = L497.OBJ_ID AND V3433.PARAM_ID = 3433 AND V3433.IS_DEL = 0 -- документ
    -- Из самого документа
    JOIN VALL V471 ON V471.OBJ_ID = V3433.VAL AND V471.PARAM_ID = 471 AND V471.IS_DEL = 0 -- тип документа
    JOIN VALS V596 ON V596.OBJ_ID = V3433.VAL AND V596.PARAM_ID = 596 AND V596.IS_DEL = 0 -- название
    JOIN VALD V482 ON V482.OBJ_ID = V3433.VAL AND V482.PARAM_ID = 482 AND V482.IS_DEL = 0 -- дата
    LEFT JOIN VALS V479 ON V479.OBJ_ID = V3433.VAL AND V479.PARAM_ID = 479 AND V479.IS_DEL = 0 -- серия
    LEFT JOIN VALS V480 ON V480.OBJ_ID = V3433.VAL AND V480.PARAM_ID = 480 AND V480.IS_DEL = 0 -- номер
    LEFT JOIN VALS V598 ON V598.OBJ_ID = V3433.VAL AND V598.PARAM_ID = 598 AND V598.IS_DEL = 0 -- ОКУД
    LEFT JOIN VALB V478 ON V478.OBJ_ID = V3433.VAL AND V478.PARAM_ID = 478 AND V478.IS_DEL = 0 -- файл
    LEFT JOIN VALB V597 ON V597.OBJ_ID = V3433.VAL AND V597.PARAM_ID = 597 AND V597.IS_DEL = 0 -- файл титула
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :V$OBJ_ID, :V$DT, :LV1, :D1, :D2, :S, :REF1, :LV2, :S2,
      :D3, :S3, :S4, :S5, :B1
  DO
  BEGIN
    IF(I$DT IS NULL OR V$DT >= I$DT) THEN
    BEGIN
      TAG_NAME = 'lcd:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'lcd:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'lcd:r:doc_id';
      VAL = REF1;
      SUSPEND;
      TAG_NAME = 'lcd:r:state_id';
      VAL = LV1;
      SUSPEND;
      TAG_NAME = 'lcd:r:type_id';
      VAL = LV2;
      SUSPEND;
      TAG_NAME = 'lcd:r:comments';
      VAL = S;
      SUSPEND;
      TAG_NAME = 'lcd:r:name';
      VAL = S2;
      SUSPEND;
      TAG_NAME = 'lcd:r:date_from';
      VAL = (SELECT VAL FROM DATE2ISO(:D1, 0));
      SUSPEND;
      TAG_NAME = 'lcd:r:date_to';
      VAL = (SELECT VAL FROM DATE2ISO(:D2, 0));
      SUSPEND;
      TAG_NAME = 'lcd:r:date';
      VAL = (SELECT VAL FROM DATE2ISO(:D3, 0));
      SUSPEND;
      TAG_NAME = 'lcd:r:number';
      VAL = S3;
      SUSPEND;
      TAG_NAME = 'lcd:r:okud';
      VAL = S4;
      SUSPEND;
      TAG_NAME = 'lcd:r:file_name';
      VAL = S5;
      SUSPEND;
      TAG_NAME = 'lcd:r:file_data';
      VAL = B1;
      SUSPEND;
    END
  END

  -- Предметы для итоговых оценок, у которых есть хотя бы одна ссылка в оценках
  TAG_NAME = 'subjects::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L51.OBJ_ID, L51.OBJ_TYPE_ID, V376.VAL, L51.DATE_MODIFY, V376.DATE_MODIFY
    FROM LINKS L51
    JOIN VALS V376 ON V376.OBJ_ID = L51.OBJ_ID AND V376.PARAM_ID IN (376, 1751) AND V376.IS_DEL = 0
    WHERE L51.PARENT_ID IN (32771, 12313) AND L51.OBJ_TYPE_ID IN (51, 197) AND L51.OBJ_ID > 1000000000
      AND EXISTS(
        SELECT FIRST 1 1 FROM VALM V WHERE V.IS_DEL = 0 AND V.SUBJECT_ID = L51.OBJ_ID AND (V.IS_NATIVE = 1 OR V.IS_NATIVE IS NULL)
      )
    INTO :V$OBJ_ID, :B1, :S, :V$DT, :V$DT2
  DO
  BEGIN
    IF(I$DT IS NULL OR V$DT >= I$DT OR V$DT2 >= I$DT) THEN
    BEGIN
      TAG_NAME = 'subjects:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'subjects:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'subjects:r:type_id';
      VAL = B1;
      SUSPEND;
      TAG_NAME = 'subjects:r:name';
      VAL = S;
      SUSPEND;
    END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE RKS_SERIALIZE_OVZCNT RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$ADP_ID BIGINT;
DECLARE VARIABLE V$PLAN_ID BIGINT;
DECLARE VARIABLE V$STAGE_ID BIGINT;
DECLARE VARIABLE S VARCHAR(400);
DECLARE VARIABLE N INTEGER;
DECLARE VARIABLE Y INTEGER;
BEGIN

  TAG_NAME = 'ovzcnt::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT V2379.LISTVAL_ID, L400.OBJ_ID, V3012.SVAL, V381.LISTVAL_ID, V3115.VAL, COUNT(*)
    FROM LINKS L2
    JOIN LINKS L69 ON L69.PARENT_ID = L2.OBJ_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL
    JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
    JOIN VALl V2379 ON V2379.OBJ_ID = L57.OBJ_ID AND V2379.PARAM_ID = 2379 AND V2379.IS_DEL = 0 AND V2379.LISTVAL_ID <> 11187
    LEFT JOIN VALI V3115 ON V3115.OBJ_ID = L57.OBJ_ID AND V3115.PARAM_ID = 3115 AND V3115.IS_DEL = 0
    JOIN LINKS L400 ON L400.PARENT_ID = L57.OBJ_ID AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL
    JOIN VALL V3013 ON V3013.OBJ_ID = L400.OBJ_ID AND V3013.PARAM_ID = 3013 AND V3013.IS_DEL = 0 AND V3013.LISTVAL_ID = 11715
    JOIN VALS V3012 ON V3012.OBJ_ID = L400.OBJ_ID AND V3012.PARAM_ID = 3012 AND V3012.IS_DEL = 0
    JOIN LINKS L54 ON L54.PARENT_ID = L400.OBJ_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
    JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
    JOIN LINKS L256 ON L256.PARENT_ID = L54.OBJ_ID AND L256.OBJ_TYPE_ID = 256 AND L256.DATE_DEL IS NULL
    JOIN LINKS L10 ON L10.PARENT_ID = L256.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    GROUP BY 1, 2, 3, 4, 5
    INTO :V$ADP_ID, :V$PLAN_ID, :S, :V$STAGE_ID, :Y, :N
  DO
  BEGIN
    TAG_NAME = 'ovzcnt:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'ovzcnt:r:plan_id';
    VAL = V$PLAN_ID;
    SUSPEND;
    TAG_NAME = 'ovzcnt:r:adapt_id';
    VAL = V$ADP_ID;
    SUSPEND;
    TAG_NAME = 'ovzcnt:r:name';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'ovzcnt:r:stage_id';
    VAL = V$STAGE_ID;
    SUSPEND;
    TAG_NAME = 'ovzcnt:r:year';
    VAL = Y;
    SUSPEND;
    TAG_NAME = 'ovzcnt:r:value';
    VAL = N;
    SUSPEND;
  END

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE RKS_SERIALIZE_PERIODS RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
declare variable V$PERIOD_ID bigint;
declare variable V$OBJ_ID bigint;
declare variable S varchar(1000);
declare variable V$PD bigint;
declare variable V$DATE1 date;
declare variable V$DATE2 date;
begin

  TAG_NAME = 'periods::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L151.OBJ_ID, C.CAPTION
    FROM LINKS L2
    JOIN LINKS L150 ON L150.PARENT_ID = L2.OBJ_ID AND L150.OBJ_TYPE_ID IN (150, 481) AND L150.DATE_DEL IS NULL
    JOIN LINKS L151 ON L151.PARENT_ID = L150.OBJ_ID AND L151.OBJ_TYPE_ID = 151 AND L151.DATE_DEL IS NULL
    LEFT JOIN OBJECT_CAPTION_GET(L151.OBJ_ID) C ON 1 = 1
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :V$PERIOD_ID, :S
  DO
  BEGIN
    TAG_NAME = 'periods:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'periods:r:id';
    VAL = V$PERIOD_ID;
    SUSPEND;
    TAG_NAME = 'periods:r:year_id'; -- признак старого формата
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'periods:r:name';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'periods:r:study::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT L154.OBJ_ID, V1170.LISTVAL_ID, V1169.VAL, V1174.VAL
      FROM LINKS L154
      JOIN VALL V1170 ON V1170.OBJ_ID = L154.OBJ_ID AND V1170.PARAM_ID = 1170 AND V1170.IS_DEL = 0
      JOIN VALD V1169 ON V1169.OBJ_ID = L154.OBJ_ID AND V1169.PARAM_ID = 1169 AND V1169.IS_DEL = 0
      JOIN VALD V1174 ON V1174.OBJ_ID = L154.OBJ_ID AND V1174.PARAM_ID = 1174 AND V1174.IS_DEL = 0
      WHERE L154.PARENT_ID = :V$PERIOD_ID AND L154.OBJ_TYPE_ID = 154 AND L154.DATE_DEL IS NULL
      INTO :V$OBJ_ID, :V$PD, :V$DATE1, :V$DATE2
    DO
    BEGIN
      TAG_NAME = 'periods:r:study:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'periods:r:study:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'periods:r:study:r:type';
      VAL = V$PD;
      SUSPEND;
      TAG_NAME = 'periods:r:study:r:date_from';
      VAL = (SELECT VAL FROM DATE2ISO(:V$DATE1, 0));
      SUSPEND;
      TAG_NAME = 'periods:r:study:r:date_to';
      VAL = (SELECT VAL FROM DATE2ISO(:V$DATE2, 0));
      SUSPEND;
    END
    TAG_NAME = 'periods:r:holidays::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT L450.OBJ_ID, V3263.VAL, V3264.VAL
      FROM LINKS L450
      JOIN VALD V3263 ON V3263.OBJ_ID = L450.OBJ_ID AND V3263.PARAM_ID = 3263 AND V3263.IS_DEL = 0
      JOIN VALD V3264 ON V3264.OBJ_ID = L450.OBJ_ID AND V3264.PARAM_ID = 3264 AND V3264.IS_DEL = 0
      WHERE L450.PARENT_ID = :V$PERIOD_ID AND L450.OBJ_TYPE_ID = 450 AND L450.DATE_DEL IS NULL
      INTO :V$OBJ_ID, :V$DATE1, :V$DATE2
    DO
    BEGIN
      TAG_NAME = 'periods:r:holidays:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'periods:r:holidays:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'periods:r:holidays:r:date_from';
      VAL = (SELECT VAL FROM DATE2ISO(:V$DATE1, 0));
      SUSPEND;
      TAG_NAME = 'periods:r:holidays:r:date_to';
      VAL = (SELECT VAL FROM DATE2ISO(:V$DATE2, 0));
      SUSPEND;
    END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE RKS_UPDATE_ALLOW2 (
    I$STATE SMALLINT)
AS
declare variable V$OBJ_ID bigint;
declare variable V$STATE bigint;
begin

  SELECT FIRST 1 L2.OBJ_ID, COALESCE(V3459.LISTVAL_ID, -1)
  FROM LINKS L2
  LEFT JOIN VALL V3459 ON V3459.OBJ_ID = L2.OBJ_ID AND V3459.PARAM_ID = 3459 AND V3459.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$OBJ_ID, :V$STATE;

  IF(V$OBJ_ID IS NULL) THEN EXIT;
  IF(V$STATE = 2) THEN V$STATE = 1;
  IF(V$STATE = 3) THEN V$STATE = 0;
  IF(V$STATE = I$STATE) THEN EXIT;

  UPDATE OR INSERT INTO VALL
  (OBJ_ID, PARAM_ID, LISTVAL_ID, IS_DEL)
  VALUES (:V$OBJ_ID, 3459, IIF(:I$STATE = 0, 3, 2), 0)
  MATCHING (OBJ_ID, PARAM_ID);

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE ROD_EXPORT (
    I$USER_ID BIGINT = 1)
RETURNS (
    TAG_NAME VARCHAR(255),
    VAL VARCHAR(4000))
AS
BEGIN
    FOR
        SELECT TAG_NAME, VAL
        FROM MONITORING_EXPORT(NULL, :I$USER_ID)
        INTO :TAG_NAME, :VAL
    DO
    BEGIN
        SUSPEND;
    END
    FOR
        SELECT TAG_NAME, VAL
        FROM MONITORING_EXPORT_MONITORING(NULL, :I$USER_ID)
        INTO :TAG_NAME, :VAL
    DO
    BEGIN
        SUSPEND;
    END
    FOR
        SELECT TAG_NAME, VAL
        FROM MONITORING_EXPORT_INFOEQUIPMENT(NULL, :I$USER_ID)
        INTO :TAG_NAME, :VAL
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE ROD_EXPORT_PROPERTIES_SET (
    ROD_ADDRESS VARCHAR(100),
    ROD_LOGIN VARCHAR(100),
    ROD_PWD VARCHAR(100),
    ROD_TIMEOUT VARCHAR(100),
    ROD_EXPORT_INTERVAL VARCHAR(100))
AS
BEGIN
    UPDATE OR INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
    VALUES ('ROD_ADDRESS', 'ROD_ADDRESS', :ROD_ADDRESS)
    MATCHING (INFO_CODE);

    UPDATE OR INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
    VALUES ('ROD_LOGIN', 'ROD_LOGIN', :ROD_LOGIN)
    MATCHING (INFO_CODE);

    UPDATE OR INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
    VALUES ('ROD_PWD', 'ROD_PWD', :ROD_PWD)
    MATCHING (INFO_CODE);

    UPDATE OR INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
    VALUES ('ROD_TIMEOUT', 'ROD_TIMEOUT', :ROD_TIMEOUT)
    MATCHING (INFO_CODE);

    UPDATE OR INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
    VALUES ('ROD_EXPORT_INTERVAL', 'ROD_EXPORT_INTERVAL', :ROD_EXPORT_INTERVAL)
    MATCHING (INFO_CODE);
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE ROD_LAST_EXPORT_DATE_SET (
    I$DT TIMESTAMP)
AS
BEGIN
    UPDATE OR INSERT INTO INFO (INFO_CODE, INFO_NAME, INFO_VAL)
    VALUES ('ROD_LAST_EXPORT_DATE', 'ROD_LAST_EXPORT_DATE', :I$DT)
    MATCHING (INFO_CODE);
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE RPARAMS_LIST (
    I$REPORT_ID BIGINT,
    I$LANG_CODE CHAR(2) = 'RU')
RETURNS (
    REPORT_ID BIGINT,
    RPARAM VARCHAR(100),
    RES_ID BIGINT,
    RPARAM_CAPTION VARCHAR(4000),
    PARAM_TYPE SMALLINT,
    LIST_ID BIGINT,
    SQL_TEXT VARCHAR(1000),
    IS_DEL SMALLINT,
    IS_REQUIRED SMALLINT)
AS
BEGIN
    FOR
        SELECT P.REPORT_ID,
               P.RPARAM,
               P.RES_ID,
               P.PARAM_TYPE,
               P.LIST_ID,
               P.SQL_TEXT,
               P.IS_DEL,
               P.IS_REQUIRED
        FROM RPARAMS P
        LEFT JOIN LISTS L
        ON P.LIST_ID = L.LIST_ID
        WHERE P.REPORT_ID = :I$REPORT_ID
        ORDER BY P.REPORT_ID,
                 P.RPARAM
        INTO   :REPORT_ID,
               :RPARAM,
               :RES_ID,
               :PARAM_TYPE,
               :LIST_ID,
               :SQL_TEXT,
               :IS_DEL,
               :IS_REQUIRED
    DO
    BEGIN
        SELECT VAL
        FROM RES_GET(:RES_ID,  :I$LANG_CODE)
        INTO   :RPARAM_CAPTION;
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE RPARAM_ADD (
    I$REPORT_ID BIGINT,
    I$RPARAM VARCHAR(100),
    I$RES_ID BIGINT,
    I$PARAM_TYPE SMALLINT,
    I$LIST_ID BIGINT,
    I$SQL_TEXT VARCHAR(1000),
    I$LANG_CODE CHAR(2),
    I$RPARAM_CAPTION VARCHAR(4000),
    I$IS_DEL SMALLINT = 0,
    I$IS_REQUIRED SMALLINT = 0)
AS
BEGIN
    UPDATE OR INSERT INTO RPARAMS  (REPORT_ID, RPARAM, PARAM_TYPE, LIST_ID, SQL_TEXT, IS_REQUIRED, IS_DEL)
    VALUES(:I$REPORT_ID, :I$RPARAM, :I$PARAM_TYPE, :I$LIST_ID, :I$SQL_TEXT, :I$IS_REQUIRED, :I$IS_DEL)
    RETURNING RES_ID INTO :I$RES_ID;

    IF (I$RES_ID IS NOT NULL) THEN
    BEGIN
        EXECUTE PROCEDURE RES_ADD (:I$RES_ID,:I$LANG_CODE,:I$RPARAM_CAPTION);
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE RSOKO_CALC_PUPIL_ABSENCES_COUNT (
    I$SCHOOL_ID BIGINT = null)
AS
declare variable V$PUPIL_ID bigint;
declare variable V$ABSENCE_COUNT bigint;
declare variable V$Y1 smallint;
declare variable V$DT1 date;
declare variable V$DT2 date;
declare variable V$BLOB_ID bigint;
BEGIN
    IF (NOT EXISTS(
        SELECT FIRST 1 1
        FROM KEYS
        WHERE KEY_CODE = 'LEVEL' AND KEY_VAL = '1'
    )) THEN
    BEGIN
        EXIT;
    END

    IF (I$SCHOOL_ID IS NULL) THEN
    BEGIN
        SELECT L2.OBJ_ID, CAST(LV.TAG AS DATE)
        FROM LINKS L2
        JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
        JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
        WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
        INTO :I$SCHOOL_ID, :V$DT1;
    END
    IF (I$SCHOOL_ID IS NULL) THEN EXIT;

    V$DT2 = '31.05.' || (EXTRACT(YEAR FROM :V$DT1) + 1);
    FOR
        SELECT L10.OBJ_ID
        FROM LINKS L7
        JOIN VALL V43 ON V43.OBJ_ID = L7.OBJ_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
        JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        WHERE L7.PARENT_ID = :I$SCHOOL_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
        INTO :V$PUPIL_ID
    DO
    BEGIN
        SELECT COUNT(*)
        FROM CJ2_MARK M
        JOIN CJ2_CONTROL C ON C.CONTROL_ID = M.CONTROL_ID AND C.DATE_DEL IS NULL
        JOIN CJ2_JOURNAL_LESSONS L ON L.OBJ_ID = C.LESSON_ID AND L.DATE_DEL IS NULL AND L.LESSON_DATE >= :V$DT1 AND L.LESSON_DATE <= :V$DT2
        JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.OBJ_ID = L.CJ_ID AND J.JOURNAL_TYPE = 0
        WHERE M.DATE_DEL IS NULL AND M.STUDENT_ID = :V$PUPIL_ID AND M.MARK_TYPE_ID IN (91, 92, 93, 94)
        INTO :V$ABSENCE_COUNT;

        SELECT BLOB_ID
        FROM VAL_ADD(1600, :V$PUPIL_ID, :V$ABSENCE_COUNT)
        INTO :V$BLOB_ID;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_1DO_5 (
    I$OBJ_ID BIGINT NOT NULL,
    I$N SMALLINT NOT NULL)
RETURNS (
    V03 INTEGER,
    V04 INTEGER)
AS
DECLARE VARIABLE V$Y_DELTA SMALLINT;
DECLARE VARIABLE V$FROM SMALLINT;
DECLARE VARIABLE V$TO SMALLINT;
BEGIN
    V$Y_DELTA = (SELECT Y FROM CURRENT_YEAR_GET) - (SELECT Y FROM OSH1_YEAR_GET(0));
    V$FROM =
        CASE :I$N
            WHEN 1 THEN 0
            WHEN 2 THEN 5
            WHEN 3 THEN 10
            WHEN 4 THEN 15
            WHEN 5 THEN 18
            WHEN 6 THEN 0
        END;
    V$TO =
        CASE :I$N
            WHEN 1 THEN 4
            WHEN 2 THEN 9
            WHEN 3 THEN 14
            WHEN 4 THEN 17
            WHEN 5 THEN 100
            WHEN 6 THEN 100
        END;
    SELECT oFROM.V3 - oTO.V3, oFROM.V4 - oTO.V4
    FROM OSH1_514(:I$OBJ_ID, :V$FROM - :V$Y_DELTA) oFROM, OSH1_514(:I$OBJ_ID, :V$TO - :V$Y_DELTA + 1) oTO
    INTO :V03, :V04;

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_1DO_6 (
    I$OBJ_ID BIGINT NOT NULL,
    I$N SMALLINT NOT NULL)
RETURNS (
    V03 INTEGER,
    V04 NUMERIC(11,2),
    V05 INTEGER,
    V06 INTEGER,
    V07 INTEGER,
    V08 INTEGER,
    V09 INTEGER,
    V10 INTEGER,
    V11 INTEGER,
    V12 INTEGER,
    V13 INTEGER,
    V14 INTEGER,
    V15 INTEGER,
    V16 INTEGER,
    V17 INTEGER,
    V18 INTEGER,
    V19 INTEGER,
    V20 INTEGER,
    V21 INTEGER,
    V22 INTEGER,
    V23 INTEGER,
    V24 INTEGER,
    V25 INTEGER,
    V26 INTEGER,
    V27 INTEGER,
    V28 INTEGER,
    V29 INTEGER,
    V30 INTEGER,
    V31 INTEGER)
AS
BEGIN
    FOR
        SELECT
            V03, V04, V05, V06, V07, V08, V09,
            V10, V11, V12, V13, V14, V15, V16,
            V17, V18, V19, V20, V21, V22, V23,
            V24, V25, V26, V27, V28, V29, V30
        FROM RIK83_ALL(:I$OBJ_ID, NULL, NULL, IIF(:I$N = 1, 1, 0), 1)
        WHERE (N < 9 AND :I$N = N)
           OR (N BETWEEN 30 AND 35 AND :I$N = N-21)
           OR (N = 38 AND :I$N = 15)
           OR (N BETWEEN 40 AND 44 AND :I$N = N-24)
           OR (N > 46 AND :I$N = N-26)
        INTO :V03, :V04, :V06, :V07, :V08, :V09, :V10,
             :V11, :V12, :V13, :V14, :V15, :V16, :V17,
             :V18, :V19, :V20, :V21, :V22, :V23, :V24,
             :V25, :V26, :V27, :V28, :V29, :V30, :V31
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_1DO_ODOD_1 (
    I$PARAM_ID INTEGER,
    I$YEAR INTEGER = NULL)
RETURNS (
    I INTEGER,
    VAL VARCHAR(200),
    D DATE)
AS
DECLARE VARIABLE V$REPORT_DATE DATE;
DECLARE VARIABLE V$OBJ_ID BIGINT;
begin
  -- если год не указан, то берем текущий
  IF (I$YEAR IS NULL) THEN I$YEAR = EXTRACT(YEAR FROM CURRENT_DATE);

  -- для текущего года берем предыдущий
  IF (I$YEAR = EXTRACT(YEAR FROM CURRENT_DATE) AND (CURRENT_DATE < I$YEAR || '-09-01')) THEN I$YEAR = I$YEAR - 1;

  V$REPORT_DATE = I$YEAR || '-12-25';

  SELECT L2.OBJ_ID FROM LINKS L2
  WHERE L2.OBJ_TYPE_ID = 2 AND ((L2.PARENT_TYPE_ID IS NULL) or (L2.PARENT_TYPE_ID = 111)) AND L2.DATE_DEL IS NULL
  INTO :V$OBJ_ID;

  I = 0;
  VAL = '';

  IF (I$PARAM_ID = 5) THEN
  BEGIN
    I = I$YEAR;
  END

  IF (I$PARAM_ID = 10) THEN
  BEGIN
    SELECT V FROM VAL_GET(:V$OBJ_ID, 999)
    INTO :VAL;
  END

  IF (I$PARAM_ID = 20) THEN
  BEGIN
    SELECT VAL FROM ADR_GET(27,:V$OBJ_ID)
    INTO :VAL;
  END

  IF (I$PARAM_ID = 30) THEN
  BEGIN
    SELECT V FROM VAL_GET(:V$OBJ_ID, 16)
    INTO :VAL;
  END

  --102 Имеет ли учреждение лицензию
  IF (I$PARAM_ID = 102) THEN
  BEGIN
    SELECT
      CASE
        WHEN EXTRACT(YEAR FROM V482.VAL) = :I$YEAR - 1
        THEN 1
        ELSE 2
      END
    FROM LINKS L2
      JOIN LINKS L17 ON L17.PARENT_ID = L2.OBJ_ID AND L17.OBJ_TYPE_ID = 17 AND L17.DATE_DEL IS NULL
      JOIN VALL V471 ON V471.OBJ_ID = L17.OBJ_ID AND V471.PARAM_ID = 471 AND V471.IS_DEL = 0 AND V471.LISTVAL_ID IN (1052, 18624) -- лицензия есть
      JOIN VALD V482 ON V482.OBJ_ID = L17.OBJ_ID AND V482.PARAM_ID = 482 AND V482.IS_DEL = 0 -- дата выдачи
      LEFT JOIN VALD V483 ON V483.OBJ_ID = L17.OBJ_ID AND V483.PARAM_ID = 483 AND V483.IS_DEL = 0 -- дата окончания срока действия
      JOIN VALL V613 ON V613.OBJ_ID = L17.OBJ_ID AND V613.PARAM_ID = 613 AND V613.IS_DEL = 0 AND V613.LISTVAL_ID = 1982 -- действующая
    WHERE L2.OBJ_TYPE_ID = 2 AND ((L2.PARENT_TYPE_ID IS NULL) or (L2.PARENT_TYPE_ID = 111)) AND L2.DATE_DEL IS NULL
      -- если указана дата окончания срока действия, то проверяем на дату предоставления данных
      AND ((V483.VAL IS NULL) OR (V483.VAL > :V$REPORT_DATE))
    INTO :I;
  END
  
  --103 Имеет ли учреждение статус автономного
  IF (I$PARAM_ID = 103) THEN
  BEGIN
    SELECT 1
    FROM LINKS L2
      JOIN VALL V8 ON V8.OBJ_ID = L2.OBJ_ID AND V8.PARAM_ID = 8 AND V8.IS_DEL = 0 AND V8.LISTVAL_ID IN (5397, 5398, 5399)
    WHERE L2.OBJ_TYPE_ID = 2 AND ((L2.PARENT_TYPE_ID IS NULL) or (L2.PARENT_TYPE_ID = 111)) AND L2.DATE_DEL IS NULL
    INTO :I;
  END

  --617-620 не вычисляем
  IF (I$PARAM_ID IN (617, 618, 619, 620)) THEN
  BEGIN
    VAL = '';
  END

  --621 Численность учителей в возрасте до 30 лет (строка 21)
  IF (I$PARAM_ID = 621) THEN
  BEGIN
    SELECT
      COUNT(CASE WHEN (DATEDIFF(DAY, V241.VAL, :V$REPORT_DATE)/365) < 30 THEN 1 ELSE NULL END) CNT
    FROM LINKS L2
      LEFT JOIN LINKS L211 ON L211.PARENT_ID = L2.OBJ_ID AND L211.OBJ_TYPE_ID = 211 AND L211.DATE_DEL IS NULL
      JOIN LINKS L14 ON L14.PARENT_ID IN (L2.OBJ_ID, L211.OBJ_ID) AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
      JOIN VALL V274 ON V274.OBJ_ID = L14.OBJ_ID AND V274.PARAM_ID = 274 AND V274.IS_DEL = 0 AND V274.LISTVAL_ID = 602 -- статус = работающий сотрудник
      JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
      JOIN VALL V72 ON V72.OBJ_ID = L15.OBJ_ID AND V72.PARAM_ID = 72 AND V72.IS_DEL = 0 AND V72.LISTVAL_ID = 934 -- должность = основная
      JOIN VALL V587 ON V587.OBJ_ID = L15.OBJ_ID AND V587.PARAM_ID = 587 AND V587.IS_DEL = 0 AND V587.LISTVAL_ID = 207 -- условия приема на должность = штатный сотрудник
      JOIN VALL V1399 ON V1399.OBJ_ID = L15.OBJ_ID AND V1399.PARAM_ID = 1399 AND V1399.IS_DEL = 0 AND V1399.LISTVAL_ID = 98 -- Подгруппа должностей = учителя, преподаватели
      LEFT JOIN VALD V241 ON V241.OBJ_ID = L14.OBJ_ID AND V241.PARAM_ID = 241 AND V241.IS_DEL = 0
    WHERE L2.OBJ_TYPE_ID = 2 AND ((L2.PARENT_TYPE_ID IS NULL) or (L2.PARENT_TYPE_ID = 111)) AND L2.DATE_DEL IS NULL
    INTO :I;
  END

  --622 Численность руководителей, прошедших в течение последних трех лет повышение квалификации (и (или) профессиональную переподготовку
  IF (I$PARAM_ID = 622) THEN
  BEGIN
    SELECT COUNT(*)
    FROM
      (SELECT
        L14.OBJ_ID
        , COUNT(V300.OBJ_ID) + COUNT(V310.OBJ_ID) CNT
      FROM LINKS L2
        LEFT JOIN LINKS L211 ON L211.PARENT_ID = L2.OBJ_ID AND L211.OBJ_TYPE_ID = 211 AND L211.DATE_DEL IS NULL
        JOIN LINKS L14 ON L14.PARENT_ID IN (L2.OBJ_ID, L211.OBJ_ID) AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
        JOIN VALL V274 ON V274.OBJ_ID = L14.OBJ_ID AND V274.PARAM_ID = 274 AND V274.IS_DEL = 0 AND V274.LISTVAL_ID = 602 -- статус = работающий сотрудник
        JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
        JOIN VALL V72 ON V72.OBJ_ID = L15.OBJ_ID AND V72.PARAM_ID = 72 AND V72.IS_DEL = 0 AND V72.LISTVAL_ID = 934 -- должность = основная
        JOIN VALL V587 ON V587.OBJ_ID = L15.OBJ_ID AND V587.PARAM_ID = 587 AND V587.IS_DEL = 0 AND V587.LISTVAL_ID = 207 -- условия приема на должность = штатный сотрудник
        JOIN VALL V1398 ON V1398.OBJ_ID = L15.OBJ_ID AND V1398.PARAM_ID = 1398 AND V1398.IS_DEL = 0 AND V1398.LISTVAL_ID = 55 -- Группа должностей = руководители
        LEFT JOIN LINKS L35 ON L35.PARENT_ID = L14.OBJ_ID AND L35.OBJ_TYPE_ID = 35 AND L35.DATE_DEL IS NULL --проф. переподготовка
        LEFT JOIN VALD V300 ON V300.OBJ_ID = L35.OBJ_ID AND V300.PARAM_ID = 300 AND V300.IS_DEL = 0 AND (DATEDIFF(DAY, V300.VAL, :V$REPORT_DATE)/365) < 3
        LEFT JOIN LINKS L36 ON L36.PARENT_ID = L14.OBJ_ID AND L36.OBJ_TYPE_ID = 36 AND L36.DATE_DEL IS NULL --повышение квалификации
        LEFT JOIN VALD V310 ON V310.OBJ_ID = L36.OBJ_ID AND V310.PARAM_ID = 310 AND V310.IS_DEL = 0 AND (DATEDIFF(DAY, V310.VAL, :V$REPORT_DATE)/365) < 3
      WHERE L2.OBJ_TYPE_ID = 2 AND ((L2.PARENT_TYPE_ID IS NULL) or (L2.PARENT_TYPE_ID = 111)) AND L2.DATE_DEL IS NULL
      GROUP BY L14.OBJ_ID
      HAVING COUNT(V300.OBJ_ID) + COUNT(V310.OBJ_ID) > 0) t
    INTO :I;
  END

  SUSPEND;
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_1DO_ODOD_2 (
    I$PARAM_ID INTEGER,
    I$YEAR SMALLINT = null)
RETURNS (
    V3 INTEGER,
    V4 VARCHAR(10),
    V5 INTEGER,
    V6 INTEGER,
    V7 VARCHAR(10),
    V8 VARCHAR(10),
    V9 VARCHAR(10),
    V10 VARCHAR(10),
    V11 VARCHAR(10))
AS
declare variable V$OU_ID bigint;
declare variable V$REPORT_DATE date;
begin
  IF (I$YEAR IS NULL) THEN I$YEAR = EXTRACT(YEAR FROM CURRENT_DATE);
  IF (I$YEAR = EXTRACT(YEAR FROM CURRENT_DATE) AND (CURRENT_DATE < I$YEAR||'-09-01')) THEN I$YEAR = I$YEAR - 1;
  V$REPORT_DATE = I$YEAR || '-12-25';

  SELECT FIRST 1 L2.OBJ_ID
  FROM LINKS L2
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$OU_ID;

  V3 = 0;
  V4 = '';
  V5 = 0;
  V6 = 0;
  V7 = '';
  V8 = '';
  V9 = '';
  V10 = '';
  V11 = '';

  IF (I$PARAM_ID = 201) THEN
  BEGIN
    --231 Количество детских коллективов
    SELECT COUNT(DISTINCT GROUP_ID)
    FROM R_1DO_ODOD_2_DTL(:V$OU_ID, NULL, NULL)
    INTO :V3;
  
    --251 Воспитанников всего
    SELECT COUNT(*)
    FROM R_1DO_ODOD_2_DTL(:V$OU_ID, NULL, NULL)
    INTO :V5;

    --261 Воспитанников занимающихся в 2-х и более объединениях
    SELECT COUNT(*)
    FROM (
        SELECT STUDENT_ID, COUNT(*) CNT
        FROM R_1DO_ODOD_2_DTL(:V$OU_ID, NULL, NULL)
        GROUP BY 1
        HAVING COUNT(*) > 1
    )
    INTO :V6;
  END

  IF (I$PARAM_ID = 202) THEN
  BEGIN
    --231 Количество детских коллективов
    SELECT COUNT(DISTINCT GROUP_ID)
    FROM R_1DO_ODOD_2_DTL(:V$OU_ID, 'Техническая', NULL)
    INTO :V3;
  
    --251 Воспитанников всего
    SELECT COUNT(*)
    FROM R_1DO_ODOD_2_DTL(:V$OU_ID, 'Техническая', NULL)
    INTO :V5;

    --261 Воспитанников занимающихся в 2-х и более объединениях
    SELECT COUNT(*)
    FROM (
        SELECT STUDENT_ID, COUNT(*) CNT
        FROM R_1DO_ODOD_2_DTL(:V$OU_ID, 'Техническая', NULL)
        GROUP BY 1
        HAVING COUNT(*) > 1
    )
    INTO :V6;
  END

  IF (I$PARAM_ID = 204) THEN
  BEGIN
    --231 Количество детских коллективов
    SELECT COUNT(DISTINCT GROUP_ID)
    FROM R_1DO_ODOD_2_DTL(:V$OU_ID, 'Эколого-биологическая', NULL)
    INTO :V3;
  
    --251 Воспитанников всего
    SELECT COUNT(*)
    FROM R_1DO_ODOD_2_DTL(:V$OU_ID, 'Эколого-биологическая', NULL)
    INTO :V5;

    --261 Воспитанников занимающихся в 2-х и более объединениях
    SELECT COUNT(*)
    FROM (
        SELECT STUDENT_ID, COUNT(*) CNT
        FROM R_1DO_ODOD_2_DTL(:V$OU_ID, 'Эколого-биологическая', NULL)
        GROUP BY 1
        HAVING COUNT(*) > 1
    )
    INTO :V6;
  END

  IF (I$PARAM_ID = 205) THEN
  BEGIN
    --231 Количество детских коллективов
    SELECT COUNT(DISTINCT GROUP_ID)
    FROM R_1DO_ODOD_2_DTL(:V$OU_ID, 'Туристско-краеведческая', NULL)
    INTO :V3;
  
    --251 Воспитанников всего
    SELECT COUNT(*)
    FROM R_1DO_ODOD_2_DTL(:V$OU_ID, 'Туристско-краеведческая', NULL)
    INTO :V5;

    --261 Воспитанников занимающихся в 2-х и более объединениях
    SELECT COUNT(*)
    FROM (
        SELECT STUDENT_ID, COUNT(*) CNT
        FROM R_1DO_ODOD_2_DTL(:V$OU_ID, 'Туристско-краеведческая', NULL)
        GROUP BY 1
        HAVING COUNT(*) > 1
    )
    INTO :V6;
  END

  IF (I$PARAM_ID = 206) THEN
  BEGIN
    --231 Количество детских коллективов
    SELECT COUNT(DISTINCT GROUP_ID)
    FROM R_1DO_ODOD_2_DTL(:V$OU_ID, 'Физкультурно-спортивная', NULL)
    INTO :V3;
  
    --251 Воспитанников всего
    SELECT COUNT(*)
    FROM R_1DO_ODOD_2_DTL(:V$OU_ID, 'Физкультурно-спортивная', NULL)
    INTO :V5;

    --261 Воспитанников занимающихся в 2-х и более объединениях
    SELECT COUNT(*)
    FROM (
        SELECT STUDENT_ID, COUNT(*) CNT
        FROM R_1DO_ODOD_2_DTL(:V$OU_ID, 'Физкультурно-спортивная', NULL)
        GROUP BY 1
        HAVING COUNT(*) > 1
    )
    INTO :V6;
  END

  IF (I$PARAM_ID = 207) THEN
  BEGIN
    --231 Количество детских коллективов
    SELECT COUNT(DISTINCT GROUP_ID)
    FROM R_1DO_ODOD_2_DTL(:V$OU_ID, 'Художественная', NULL)
    INTO :V3;
  
    --251 Воспитанников всего
    SELECT COUNT(*)
    FROM R_1DO_ODOD_2_DTL(:V$OU_ID, 'Художественная', NULL)
    INTO :V5;

    --261 Воспитанников занимающихся в 2-х и более объединениях
    SELECT COUNT(*)
    FROM (
        SELECT STUDENT_ID, COUNT(*) CNT
        FROM R_1DO_ODOD_2_DTL(:V$OU_ID, 'Художественная', NULL)
        GROUP BY 1
        HAVING COUNT(*) > 1
    )
    INTO :V6;
  END

  -- !!!
  IF (I$PARAM_ID = 208) THEN
  BEGIN
  END

  IF (I$PARAM_ID = 209) THEN
  BEGIN
    --231 Количество детских коллективов
    SELECT COUNT(DISTINCT GROUP_ID)
    FROM R_1DO_ODOD_2_DTL(:V$OU_ID, NULL, NULL)
    WHERE DIR_NAME <> 'Техническая' AND DIR_NAME <> 'Эколого-биологическая' AND DIR_NAME <> 'Туристско-краеведческая'
      AND DIR_NAME <> 'Физкультурно-спортивная' AND DIR_NAME <> 'Художественная'
    INTO :V3;
  
    --251 Воспитанников всего
    SELECT COUNT(*)
    FROM R_1DO_ODOD_2_DTL(:V$OU_ID, NULL, NULL)
    WHERE DIR_NAME <> 'Техническая' AND DIR_NAME <> 'Эколого-биологическая' AND DIR_NAME <> 'Туристско-краеведческая'
      AND DIR_NAME <> 'Физкультурно-спортивная' AND DIR_NAME <> 'Художественная'
    INTO :V5;

    --261 Воспитанников занимающихся в 2-х и более объединениях
    SELECT COUNT(*)
    FROM (
        SELECT STUDENT_ID, COUNT(*) CNT
        FROM R_1DO_ODOD_2_DTL(:V$OU_ID, NULL, NULL)
        WHERE DIR_NAME <> 'Техническая' AND DIR_NAME <> 'Эколого-биологическая' AND DIR_NAME <> 'Туристско-краеведческая'
          AND DIR_NAME <> 'Физкультурно-спортивная' AND DIR_NAME <> 'Художественная'
        GROUP BY 1
        HAVING COUNT(*) > 1
    )
    INTO :V6;
  END

  IF (I$PARAM_ID = 210) THEN
  BEGIN
    --231 Количество детских коллективов
    SELECT COUNT(DISTINCT GROUP_ID)
    FROM R_1DO_ODOD_2_DTL(:V$OU_ID, NULL, 11392)
    INTO :V3;
  
    --251 Воспитанников всего
    SELECT COUNT(*)
    FROM R_1DO_ODOD_2_DTL(:V$OU_ID, NULL, 11392)
    INTO :V5;

    --261 Воспитанников занимающихся в 2-х и более объединениях
    SELECT COUNT(*)
    FROM (
        SELECT STUDENT_ID, COUNT(*) CNT
        FROM R_1DO_ODOD_2_DTL(:V$OU_ID, NULL, 11392)
        GROUP BY 1
        HAVING COUNT(*) > 1
    )
    INTO :V6;
  END

  -- !!!
  IF (I$PARAM_ID = 211) THEN
  BEGIN
  END

  SUSPEND;
end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_1DO_ODOD_2_DTL (
    I$OU_ID BIGINT,
    I$DIR_TYPE VARCHAR(200),
    I$FIN_TYPE BIGINT)
RETURNS (
    STUDENT_ID BIGINT,
    GROUP_ID BIGINT,
    DIR_NAME VARCHAR(200))
AS
begin

  FOR
      SELECT L10.OBJ_ID, L243.OBJ_ID, V2148.VAL
      FROM LINKS L242
      JOIN VALR V2441 ON V2441.OBJ_ID = L242.OBJ_ID AND V2441.PARAM_ID = 2441 AND V2441.IS_DEL = 0 -- обр. программа
      JOIN VALS V2148 ON V2148.OBJ_ID = V2441.VAL AND V2148.PARAM_ID = 2148 AND V2148.IS_DEL = 0 AND (V2148.VAL = :I$DIR_TYPE OR :I$DIR_TYPE IS NULL)
      JOIN VALL V2451 ON V2451.OBJ_ID = L242.OBJ_ID AND V2451.PARAM_ID = 2451 AND V2451.IS_DEL = 0 AND (V2451.LISTVAL_ID = :I$FIN_TYPE OR :I$FIN_TYPE IS NULL)
      JOIN LINKS L243 ON L243.PARENT_ID = L242.OBJ_ID AND L243.OBJ_TYPE_ID = 243 AND L243.DATE_DEL IS NULL
      JOIN LINKS L10 ON L10.PARENT_ID = L243.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      WHERE L242.PARENT_ID = :I$OU_ID AND L242.OBJ_TYPE_ID = 242 AND L242.DATE_DEL IS NULL
      UNION
      SELECT L10.OBJ_ID, L243.OBJ_ID, V2148.VAL
      FROM LINKS L211
      JOIN LINKS L242 ON L242.PARENT_ID = L211.OBJ_ID AND L242.OBJ_TYPE_ID = 242 AND L242.DATE_DEL IS NULL
      JOIN VALR V2441 ON V2441.OBJ_ID = L242.OBJ_ID AND V2441.PARAM_ID = 2441 AND V2441.IS_DEL = 0 -- обр. программа
      JOIN VALS V2148 ON V2148.OBJ_ID = V2441.VAL AND V2148.PARAM_ID = 2148 AND V2148.IS_DEL = 0 AND (V2148.VAL = :I$DIR_TYPE OR :I$DIR_TYPE IS NULL)
      JOIN VALL V2451 ON V2451.OBJ_ID = L242.OBJ_ID AND V2451.PARAM_ID = 2451 AND V2451.IS_DEL = 0 AND (V2451.LISTVAL_ID = :I$FIN_TYPE OR :I$FIN_TYPE IS NULL)
      JOIN LINKS L243 ON L243.PARENT_ID = L242.OBJ_ID AND L243.OBJ_TYPE_ID = 243 AND L243.DATE_DEL IS NULL
      JOIN LINKS L10 ON L10.PARENT_ID = L243.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      WHERE L211.PARENT_ID = :I$OU_ID AND L211.OBJ_TYPE_ID = 211 AND L211.DATE_DEL IS NULL
      INTO :STUDENT_ID, :GROUP_ID, :DIR_NAME
  DO
  BEGIN
      SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_1DO_ODOD_5 (
    I$PARAM_ID INTEGER,
    I$YEAR SMALLINT = null)
RETURNS (
    V3 INTEGER,
    V4 INTEGER)
AS
declare variable V$REPORT_DATE date;
begin

  -- Возвращаем - всего, в том числе девочек

  V$REPORT_DATE = I$YEAR || '-12-25';

  SELECT COUNT(OBJ_ID), SUM(IS_FEM)
  FROM (
      -- Непосредственно
      SELECT DISTINCT L10.OBJ_ID, IIF(V88.LISTVAL_ID = 182, 1, 0) IS_FEM, (DATEDIFF(DAY, V89.VAL, :V$REPORT_DATE) / 365) P_AGE
      FROM LINKS L2
      JOIN LINKS L242 ON L242.PARENT_ID = L2.OBJ_ID AND L242.OBJ_TYPE_ID = 242 AND L242.DATE_DEL IS NULL
      JOIN LINKS L243 ON L243.PARENT_ID = L242.OBJ_ID AND L243.OBJ_TYPE_ID = 243 AND L243.DATE_DEL IS NULL
      JOIN LINKS L10 ON L10.PARENT_ID = L243.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      LEFT JOIN VALL V88 ON V88.OBJ_ID = L10.OBJ_ID AND V88.PARAM_ID = 88 AND V88.IS_DEL = 0 AND V88.LISTVAL_ID = 182
      JOIN VALD V89 ON V89.OBJ_ID = L10.OBJ_ID AND V89.PARAM_ID = 89 AND V89.IS_DEL = 0
      WHERE L2.OBJ_TYPE_ID = 2 AND (L2.PARENT_TYPE_ID IS NULL OR L2.PARENT_TYPE_ID = 111) AND L2.DATE_DEL IS NULL
      -- В подразделениях первого уровня
      UNION
      SELECT DISTINCT L10.OBJ_ID, IIF(V88.LISTVAL_ID = 182, 1, 0) IS_FEM, (DATEDIFF(DAY, V89.VAL, :V$REPORT_DATE) / 365) P_AGE
      FROM LINKS L2
      JOIN LINKS L211 ON L211.PARENT_ID = L2.OBJ_ID AND L211.OBJ_TYPE_ID = 211 AND L211.DATE_DEL IS NULL
      JOIN LINKS L242 ON L242.PARENT_ID = L211.OBJ_ID AND L242.OBJ_TYPE_ID = 242 AND L242.DATE_DEL IS NULL
      JOIN LINKS L243 ON L243.PARENT_ID = L242.OBJ_ID AND L243.OBJ_TYPE_ID = 243 AND L243.DATE_DEL IS NULL
      JOIN LINKS L10 ON L10.PARENT_ID = L243.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      LEFT JOIN VALL V88 ON V88.OBJ_ID = L10.OBJ_ID AND V88.PARAM_ID = 88 AND V88.IS_DEL = 0
      JOIN VALD V89 ON V89.OBJ_ID = L10.OBJ_ID AND V89.PARAM_ID = 89 AND V89.IS_DEL = 0
      WHERE L2.OBJ_TYPE_ID = 2 AND (L2.PARENT_TYPE_ID IS NULL OR L2.PARENT_TYPE_ID = 111) AND L2.DATE_DEL IS NULL
  )
  WHERE
      --501 Воспитанников До 5 лет
      (:I$PARAM_ID = 501 AND P_AGE < 5) OR
       --502 Воспитанников 5-9 лет
      (:I$PARAM_ID = 502 AND P_AGE >= 5 AND P_AGE < 10) OR
      --503 Воспитанников 10-14 лет
      (:I$PARAM_ID = 503 AND P_AGE >= 10 AND P_AGE < 15) OR
      --504 Воспитанников 15-17 лет
      (:I$PARAM_ID = 504 AND P_AGE >= 15 AND P_AGE < 18) OR
      --505 Воспитанников 18 лет и старше
      (:I$PARAM_ID = 505 AND P_AGE >= 18) OR
      --506 Воспитанников всего
      (:I$PARAM_ID = 506)
  INTO :V3, :V4;

  IF(V3 IS NULL) THEN V3 = 0;
  IF(V4 IS NULL) THEN V4 = 0;

  SUSPEND;
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_1DO_ODOD_6_1 (
    I$PARAM_ID INTEGER,
    I$YEAR SMALLINT = null)
RETURNS (
    V3 INTEGER,
    V4 NUMERIC(15,2),
    V5 INTEGER,
    V6 INTEGER,
    V7 INTEGER,
    V8 INTEGER,
    V9 INTEGER,
    V10 INTEGER,
    V11 INTEGER,
    V12 INTEGER,
    V13 INTEGER,
    V14 INTEGER,
    V15 INTEGER,
    V16 INTEGER,
    V17 INTEGER,
    V18 INTEGER,
    V19 INTEGER,
    V20 INTEGER,
    V21 INTEGER,
    V22 INTEGER,
    V23 INTEGER,
    V24 INTEGER,
    V25 INTEGER,
    V26 INTEGER,
    V27 INTEGER,
    V28 INTEGER,
    V29 INTEGER,
    V30 INTEGER,
    V31 INTEGER)
AS
declare variable V$OU_ID bigint;
declare variable V$REPORT_DATE date;
declare variable V$MATCH smallint;
declare variable V$SEX bigint;
declare variable V$BIRTH_DATE date;
declare variable V$FULL_OCCP smallint;
declare variable V$PART_OCCP smallint;
declare variable V$CAT_TOP smallint;
declare variable V$CAT_1 smallint;
declare variable V$CAT_2 smallint;
declare variable V$CAT_NONE smallint;
declare variable V$EDU_ID bigint;
declare variable V$IS_PD smallint;
declare variable V$IS_PD2 smallint;
declare variable V$STAGE_YEARS float;
declare variable V$IS_MANAGER smallint;
declare variable V$IS_M1 smallint;
declare variable V$IS_M2 smallint;
declare variable V$IS_GB smallint;
begin
  IF (I$YEAR IS NULL) THEN I$YEAR = EXTRACT(YEAR FROM CURRENT_DATE);
  IF (I$YEAR = EXTRACT(YEAR FROM CURRENT_DATE) AND (CURRENT_DATE < I$YEAR || '-09-01')) THEN I$YEAR = I$YEAR - 1;
  V$REPORT_DATE = I$YEAR || '-12-25';

  SELECT FIRST 1 L2.OBJ_ID
  FROM LINKS L2
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$OU_ID;

  V3 = 0;
  V4 = 0;
  V5 = 0;
  V6 = 0;
  V7 = 0;
  V8 = 0;
  V9 = 0;
  V10 = 0;
  V11 = 0;
  V12 = 0;
  V13 = 0;
  V14 = 0;
  V15 = 0;
  V16 = 0;
  V17 = 0;
  V18 = 0;
  V19 = 0;
  V20 = 0;
  V21 = 0;
  V22 = 0;
  V23 = 0;
  V24 = 0;
  V25 = 0;
  V26 = 0;
  V27 = 0;
  V28 = 0;
  V29 = 0;
  V30 = 0;
  V31 = 0;

  FOR
    SELECT D.SEX, D.BIRTH_DATE, D.FULL_OCCP, D.PART_OCCP, D.CAT_TOP, D.CAT_1, D.CAT_2, D.CAT_NONE, D.EDU_ID, D.IS_PD, D.IS_PD2, D.STAGE_YEARS,
      D.IS_MANAGER, D.IS_M1, D.IS_M2, D.IS_GB
    FROM R_1DO_ODOD_6_DTL(:V$OU_ID) D
    INTO :V$SEX, :V$BIRTH_DATE, :V$FULL_OCCP, :V$PART_OCCP, :V$CAT_TOP, :V$CAT_1, :V$CAT_2, :V$CAT_NONE, :V$EDU_ID, :V$IS_PD, :V$IS_PD2, :V$STAGE_YEARS,
      :V$IS_MANAGER, :V$IS_M1, :V$IS_M2, :V$IS_GB
  DO
  BEGIN
    V$MATCH = 0;

    -- Общий счетчик
    IF(I$PARAM_ID = 601) THEN V$MATCH = 1;
    -- Руководители всех видов
    ELSE IF(I$PARAM_ID = 602 AND V$IS_MANAGER = 1) THEN V$MATCH = 1;
    -- Реководители
    ELSE IF(I$PARAM_ID = 603 AND V$IS_M1 = 1) THEN V$MATCH = 1;
    -- Заместители
    ELSE IF(I$PARAM_ID = 604 AND V$IS_M2 = 1) THEN V$MATCH = 1;
    -- Главный бухгалтер
    ELSE IF(I$PARAM_ID = 605 AND V$IS_GB = 1) THEN V$MATCH = 1;

    -- Отбираем нужные строки отчета
    IF(V$MATCH = 1) THEN
    BEGIN
      -- Общий счетчик
      V3 = V3 + 1;
      -- Женщины
      IF(V$SEX = 182) THEN V6 = V6 + 1;
      -- Неполная занятость
      IF(V$PART_OCCP = 1) THEN V7 = V7 + 1;
      -- Полная занятость
      IF(V$FULL_OCCP = 1) THEN V8 = V8 + 1;
      -- Совместительство
      -- Категории
      IF(V$CAT_TOP = 1) THEN V10 = V10 + 1;
      ELSE IF(V$CAT_1 = 1) THEN V11 = V11 + 1;
      ELSE IF(V$CAT_2 = 1) THEN V12 = V12 + 1;
      ELSE IF(V$CAT_NONE = 1) THEN V13 = V13 + 1;
      -- Высшее профессиональное образование
      IF(V$EDU_ID IN (620, 3031, 3032)) THEN V16 = V16 + 1;
      -- Педагогичесое образование
      IF(V$IS_PD = 1) THEN V17 = V17 + 1;
      -- Среднее профессиональное образование
      IF(V$EDU_ID = 622) THEN V18 = V18 + 1;
      -- Среднее профессиональное образование + педагогическое
      IF(V$IS_PD2 = 1) THEN V19 = V19 + 1;
      -- Начальное профессиональное образование
      IF(V$EDU_ID = 624) THEN V20 = V20 + 1;
      -- Среднее общее образование
      IF(V$EDU_ID = 623) THEN V21 = V21 + 1;
      -- Стаж
      IF((V$STAGE_YEARS / 365) < 2) THEN V22 = V22 + 1;
      ELSE IF((V$STAGE_YEARS / 365) < 5) THEN V23 = V23 + 1;
      ELSE IF((V$STAGE_YEARS / 365) < 10) THEN V24 = V24 + 1;
      ELSE IF((V$STAGE_YEARS / 365) < 20) THEN V25 = V25 + 1;
      ELSE V26 = V26 + 1;
      -- Возраст
      IF((DATEDIFF(DAY, V$BIRTH_DATE, V$REPORT_DATE) / 365) < 25) THEN V27 = V27 + 1;
      ELSE IF((DATEDIFF(DAY, V$BIRTH_DATE, V$REPORT_DATE) / 365) < 35) THEN V28 = V28 + 1;
      ELSE V29 = V29 + 1;
    END
  END

  FOR
    SELECT D.SEX, D.IS_MANAGER, D.IS_M1, D.IS_M2, D.IS_GB
    FROM R_1DO_ODOD_6_DTL2(:V$OU_ID) D
    INTO :V$SEX, :V$IS_MANAGER, :V$IS_M1, :V$IS_M2, :V$IS_GB
  DO
  BEGIN
    V$MATCH = 0;

    -- Общий счетчик
    IF(I$PARAM_ID = 601) THEN V$MATCH = 1;
    -- Руководители всех видов
    ELSE IF(I$PARAM_ID = 602 AND V$IS_MANAGER = 1) THEN V$MATCH = 1;
    -- Реководители
    ELSE IF(I$PARAM_ID = 603 AND V$IS_M1 = 1) THEN V$MATCH = 1;
    -- Заместители
    ELSE IF(I$PARAM_ID = 604 AND V$IS_M2 = 1) THEN V$MATCH = 1;
    -- Главный бухгалтер
    ELSE IF(I$PARAM_ID = 605 AND V$IS_GB = 1) THEN V$MATCH = 1;

    -- Отбираем нужные строки отчета
    IF(V$MATCH = 1) THEN
    BEGIN
      V9 = V9 + 1;
    END
  END

  FOR
    SELECT D.SEX, D.IS_MANAGER, D.IS_M1, D.IS_M2, D.IS_GB
    FROM R_1DO_ODOD_6_DTL3(:V$OU_ID) D
    INTO :V$SEX, :V$IS_MANAGER, :V$IS_M1, :V$IS_M2, :V$IS_GB
  DO
  BEGIN
    V$MATCH = 0;

    -- Общий счетчик
    IF(I$PARAM_ID = 601) THEN V$MATCH = 1;
    -- Руководители всех видов
    ELSE IF(I$PARAM_ID = 602 AND V$IS_MANAGER = 1) THEN V$MATCH = 1;
    -- Реководители
    ELSE IF(I$PARAM_ID = 603 AND V$IS_M1 = 1) THEN V$MATCH = 1;
    -- Заместители
    ELSE IF(I$PARAM_ID = 604 AND V$IS_M2 = 1) THEN V$MATCH = 1;
    -- Главный бухгалтер
    ELSE IF(I$PARAM_ID = 605 AND V$IS_GB = 1) THEN V$MATCH = 1;

    -- Отбираем нужные строки отчета
    IF(V$MATCH = 1) THEN
    BEGIN
      V14 = V14 + 1;
      IF(V$SEX = 182) THEN V15 = V15 + 1;
    END
  END

  SUSPEND;
end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_1DO_ODOD_6_2 (
    I$PARAM_ID INTEGER,
    I$YEAR SMALLINT = null)
RETURNS (
    V3 INTEGER,
    V4 NUMERIC(15,2),
    V5 INTEGER,
    V6 INTEGER,
    V7 INTEGER,
    V8 INTEGER,
    V9 INTEGER,
    V10 INTEGER,
    V11 INTEGER,
    V12 INTEGER,
    V13 INTEGER,
    V14 INTEGER,
    V15 INTEGER,
    V16 INTEGER,
    V17 INTEGER,
    V18 INTEGER,
    V19 INTEGER,
    V20 INTEGER,
    V21 INTEGER,
    V22 INTEGER,
    V23 INTEGER,
    V24 INTEGER,
    V25 INTEGER,
    V26 INTEGER,
    V27 INTEGER,
    V28 INTEGER,
    V29 INTEGER,
    V30 INTEGER,
    V31 INTEGER)
AS
declare variable V$OU_ID bigint;
declare variable V$REPORT_DATE date;
declare variable V$SEX bigint;
declare variable V$BIRTH_DATE date;
declare variable V$FULL_OCCP smallint;
declare variable V$PART_OCCP smallint;
declare variable V$CAT_TOP smallint;
declare variable V$CAT_1 smallint;
declare variable V$CAT_2 smallint;
declare variable V$CAT_NONE smallint;
declare variable V$EDU_ID bigint;
declare variable V$IS_PD smallint;
declare variable V$IS_PD2 smallint;
declare variable V$STAGE_YEARS float;
declare variable V$MATCH smallint;
declare variable V$IS_MX smallint;
declare variable V$IS_PDD smallint;
declare variable V$IS_TEACHER smallint;
declare variable V$IS_DO smallint;
declare variable V$IS_PORG smallint;
begin
  IF (I$YEAR IS NULL) THEN I$YEAR = EXTRACT(YEAR FROM CURRENT_DATE);
  IF (I$YEAR = EXTRACT(YEAR FROM CURRENT_DATE) AND (CURRENT_DATE < I$YEAR||'-09-01')) THEN I$YEAR = I$YEAR - 1;
  V$REPORT_DATE = I$YEAR || '-12-25';

  SELECT FIRST 1 L2.OBJ_ID
  FROM LINKS L2
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$OU_ID;

  V3 = 0;
  V4 = 0;
  V5 = 0;
  V6 = 0;
  V7 = 0;
  V8 = 0;
  V9 = 0;
  V10 = 0;
  V11 = 0;
  V12 = 0;
  V13 = 0;
  V14 = 0;
  V15 = 0;
  V16 = 0;
  V17 = 0;
  V18 = 0;
  V19 = 0;
  V20 = 0;
  V21 = 0;
  V22 = 0;
  V23 = 0;
  V24 = 0;
  V25 = 0;
  V26 = 0;
  V27 = 0;
  V28 = 0;
  V29 = 0;
  V30 = 0;
  V31 = 0;

  FOR
    SELECT D.SEX, D.BIRTH_DATE, D.FULL_OCCP, D.PART_OCCP, D.CAT_TOP, D.CAT_1, D.CAT_2, D.CAT_NONE, D.EDU_ID, D.IS_PD, D.IS_PD2, D.STAGE_YEARS,
      D.IS_MX, D.IS_PDD, D.IS_TEACHER, D.IS_DO, D.IS_PORG
    FROM R_1DO_ODOD_6_DTL(:V$OU_ID) D
    INTO :V$SEX, :V$BIRTH_DATE, :V$FULL_OCCP, :V$PART_OCCP, :V$CAT_TOP, :V$CAT_1, :V$CAT_2, :V$CAT_NONE, :V$EDU_ID, :V$IS_PD, :V$IS_PD2, :V$STAGE_YEARS,
      :V$IS_MX, :V$IS_PDD, :V$IS_TEACHER, :V$IS_DO, :V$IS_PORG
  DO
  BEGIN
    V$MATCH = 0;

    -- Все остальные варианты руководителей
    IF(I$PARAM_ID = 606 AND V$IS_MX = 1) THEN V$MATCH = 1;
    -- Педагогические работники
    ELSE IF(I$PARAM_ID = 607 AND V$IS_PDD = 1) THEN V$MATCH = 1;
    -- Учителя
    ELSE IF(I$PARAM_ID = 608 AND V$IS_TEACHER = 1) THEN V$MATCH = 1;
    -- Педагоги ДО
    ELSE IF(I$PARAM_ID = 609 AND V$IS_DO = 1) THEN V$MATCH = 1;
    -- Педагоги-организаторы
    ELSE IF(I$PARAM_ID = 610 AND V$IS_PORG = 1) THEN V$MATCH = 1;

    -- Отбираем нужные строки отчета
    IF(V$MATCH = 1) THEN
    BEGIN
      -- Общий счетчик
      V3 = V3 + 1;
      -- Женщины
      IF(V$SEX = 182) THEN V6 = V6 + 1;
      -- Неполная занятость
      IF(V$PART_OCCP = 1) THEN V7 = V7 + 1;
      -- Полная занятость
      IF(V$FULL_OCCP = 1) THEN V8 = V8 + 1;
      -- Совместительство
      -- Категории
      IF(V$CAT_TOP = 1) THEN V10 = V10 + 1;
      ELSE IF(V$CAT_1 = 1) THEN V11 = V11 + 1;
      ELSE IF(V$CAT_2 = 1) THEN V12 = V12 + 1;
      ELSE IF(V$CAT_NONE = 1) THEN V13 = V13 + 1;
      -- Высшее профессиональное образование
      IF(V$EDU_ID IN (620, 3031, 3032)) THEN V16 = V16 + 1;
      -- Педагогичесое образование
      IF(V$IS_PD = 1) THEN V17 = V17 + 1;
      -- Среднее профессиональное образование
      IF(V$EDU_ID = 622) THEN V18 = V18 + 1;
      -- Среднее профессиональное образование + педагогическое
      IF(V$IS_PD2 = 1) THEN V19 = V19 + 1;
      -- Начальное профессиональное образование
      IF(V$EDU_ID = 624) THEN V20 = V20 + 1;
      -- Среднее общее образование
      IF(V$EDU_ID = 623) THEN V21 = V21 + 1;
      -- Стаж
      IF((V$STAGE_YEARS / 365) < 2) THEN V22 = V22 + 1;
      ELSE IF((V$STAGE_YEARS / 365) < 5) THEN V23 = V23 + 1;
      ELSE IF((V$STAGE_YEARS / 365) < 10) THEN V24 = V24 + 1;
      ELSE IF((V$STAGE_YEARS / 365) < 20) THEN V25 = V25 + 1;
      ELSE V26 = V26 + 1;
      -- Возраст
      IF((DATEDIFF(DAY, V$BIRTH_DATE, V$REPORT_DATE) / 365) < 25) THEN V27 = V27 + 1;
      ELSE IF((DATEDIFF(DAY, V$BIRTH_DATE, V$REPORT_DATE) / 365) < 35) THEN V28 = V28 + 1;
      ELSE V29 = V29 + 1;
    END
  END

  FOR
    SELECT D.SEX, D.IS_MX, D.IS_PDD, D.IS_TEACHER, D.IS_DO, D.IS_PORG
    FROM R_1DO_ODOD_6_DTL2(:V$OU_ID) D
    INTO :V$SEX, :V$IS_MX, :V$IS_PDD, :V$IS_TEACHER, :V$IS_DO, :V$IS_PORG
  DO
  BEGIN
    V$MATCH = 0;

    -- Все остальные варианты руководителей
    IF(I$PARAM_ID = 606 AND V$IS_MX = 1) THEN V$MATCH = 1;
    -- Педагогические работники
    ELSE IF(I$PARAM_ID = 607 AND V$IS_PDD = 1) THEN V$MATCH = 1;
    -- Учителя
    ELSE IF(I$PARAM_ID = 608 AND V$IS_TEACHER = 1) THEN V$MATCH = 1;
    -- Педагоги ДО
    ELSE IF(I$PARAM_ID = 609 AND V$IS_DO = 1) THEN V$MATCH = 1;
    -- Педагоги-организаторы
    ELSE IF(I$PARAM_ID = 610 AND V$IS_PORG = 1) THEN V$MATCH = 1;

    -- Отбираем нужные строки отчета
    IF(V$MATCH = 1) THEN
    BEGIN
      V9 = V9 + 1;
    END
  END

  FOR
    SELECT D.SEX, D.IS_MX, D.IS_PDD, D.IS_TEACHER, D.IS_DO, D.IS_PORG
    FROM R_1DO_ODOD_6_DTL3(:V$OU_ID) D
    INTO :V$SEX, :V$IS_MX, :V$IS_PDD, :V$IS_TEACHER, :V$IS_DO, :V$IS_PORG
  DO
  BEGIN
    V$MATCH = 0;

    -- Все остальные варианты руководителей
    IF(I$PARAM_ID = 606 AND V$IS_MX = 1) THEN V$MATCH = 1;
    -- Педагогические работники
    ELSE IF(I$PARAM_ID = 607 AND V$IS_PDD = 1) THEN V$MATCH = 1;
    -- Учителя
    ELSE IF(I$PARAM_ID = 608 AND V$IS_TEACHER = 1) THEN V$MATCH = 1;
    -- Педагоги ДО
    ELSE IF(I$PARAM_ID = 609 AND V$IS_DO = 1) THEN V$MATCH = 1;
    -- Педагоги-организаторы
    ELSE IF(I$PARAM_ID = 610 AND V$IS_PORG = 1) THEN V$MATCH = 1;

    -- Отбираем нужные строки отчета
    IF(V$MATCH = 1) THEN
    BEGIN
      V14 = V14 + 1;
      IF(V$SEX = 182) THEN V15 = V15 + 1;
    END
  END
  
  SUSPEND;
end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_1DO_ODOD_6_3 (
    I$PARAM_ID INTEGER,
    I$YEAR SMALLINT = null)
RETURNS (
    V3 INTEGER,
    V4 NUMERIC(15,2),
    V5 INTEGER,
    V6 INTEGER,
    V7 INTEGER,
    V8 INTEGER,
    V9 INTEGER,
    V10 INTEGER,
    V11 INTEGER,
    V12 INTEGER,
    V13 INTEGER,
    V14 INTEGER,
    V15 INTEGER,
    V16 INTEGER,
    V17 INTEGER,
    V18 INTEGER,
    V19 INTEGER,
    V20 INTEGER,
    V21 INTEGER,
    V22 INTEGER,
    V23 INTEGER,
    V24 INTEGER,
    V25 INTEGER,
    V26 INTEGER,
    V27 INTEGER,
    V28 INTEGER,
    V29 INTEGER,
    V30 INTEGER,
    V31 INTEGER)
AS
declare variable V$OU_ID bigint;
declare variable V$REPORT_DATE date;
declare variable V$SEX bigint;
declare variable V$BIRTH_DATE date;
declare variable V$FULL_OCCP smallint;
declare variable V$PART_OCCP smallint;
declare variable V$CAT_TOP smallint;
declare variable V$CAT_1 smallint;
declare variable V$CAT_2 smallint;
declare variable V$CAT_NONE smallint;
declare variable V$EDU_ID bigint;
declare variable V$IS_PD smallint;
declare variable V$IS_PD2 smallint;
declare variable V$STAGE_YEARS float;
declare variable V$MATCH smallint;
declare variable V$IS_SOC smallint;
declare variable V$IS_MTD smallint;
declare variable V$IS_TRAIN smallint;
declare variable V$IS_PDO smallint;
declare variable V$IS_AUX smallint;
begin
  IF (I$YEAR IS NULL) THEN I$YEAR = EXTRACT(YEAR FROM CURRENT_DATE);
  IF (I$YEAR = EXTRACT(YEAR FROM CURRENT_DATE) AND (CURRENT_DATE < I$YEAR || '-09-01')) THEN I$YEAR = I$YEAR - 1;
  V$REPORT_DATE = I$YEAR || '-12-25';

  SELECT FIRST 1 L2.OBJ_ID
  FROM LINKS L2
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$OU_ID;

  V3 = 0;
  V4 = 0;
  V5 = 0;
  V6 = 0;
  V7 = 0;
  V8 = 0;
  V9 = 0;
  V10 = 0;
  V11 = 0;
  V12 = 0;
  V13 = 0;
  V14 = 0;
  V15 = 0;
  V16 = 0;
  V17 = 0;
  V18 = 0;
  V19 = 0;
  V20 = 0;
  V21 = 0;
  V22 = 0;
  V23 = 0;
  V24 = 0;
  V25 = 0;
  V26 = 0;
  V27 = 0;
  V28 = 0;
  V29 = 0;
  V30 = 0;
  V31 = 0;

  FOR
    SELECT D.SEX, D.BIRTH_DATE, D.FULL_OCCP, D.PART_OCCP, D.CAT_TOP, D.CAT_1, D.CAT_2, D.CAT_NONE, D.EDU_ID, D.IS_PD, D.IS_PD2, D.STAGE_YEARS,
      D.IS_SOC, D.IS_TRAIN, D.IS_MTD, D.IS_PDO, D.IS_AUX
    FROM R_1DO_ODOD_6_DTL(:V$OU_ID) D
    INTO :V$SEX, :V$BIRTH_DATE, :V$FULL_OCCP, :V$PART_OCCP, :V$CAT_TOP, :V$CAT_1, :V$CAT_2, :V$CAT_NONE, :V$EDU_ID, :V$IS_PD, :V$IS_PD2, :V$STAGE_YEARS,
      :V$IS_SOC, :V$IS_TRAIN, :V$IS_MTD, :V$IS_PDO, :V$IS_AUX
  DO
  BEGIN
    V$MATCH = 0;

    -- Социальный педагог
    IF(I$PARAM_ID = 611 AND V$IS_SOC = 1) THEN V$MATCH = 1;
    -- Тренер-преподаватель
    ELSE IF(I$PARAM_ID = 612 AND V$IS_TRAIN = 1) THEN V$MATCH = 1;
    -- Методист
    ELSE IF(I$PARAM_ID = 613 AND V$IS_MTD = 1) THEN V$MATCH = 1;
    -- Прочие педагогические работники
    ELSE IF(I$PARAM_ID = 614 AND V$IS_PDO = 1) THEN V$MATCH = 1;
    -- Вспомогательный персонал
    ELSE IF(I$PARAM_ID = 615 AND V$IS_AUX = 1) THEN V$MATCH = 1;

    -- Отбираем нужные строки отчета
    IF(V$MATCH = 1) THEN
    BEGIN
      -- Общий счетчик
      V3 = V3 + 1;
      -- Женщины
      IF(V$SEX = 182) THEN V6 = V6 + 1;
      -- Неполная занятость
      IF(V$PART_OCCP = 1) THEN V7 = V7 + 1;
      -- Полная занятость
      IF(V$FULL_OCCP = 1) THEN V8 = V8 + 1;
      -- Совместительство
      -- Категории
      IF(V$CAT_TOP = 1) THEN V10 = V10 + 1;
      ELSE IF(V$CAT_1 = 1) THEN V11 = V11 + 1;
      ELSE IF(V$CAT_2 = 1) THEN V12 = V12 + 1;
      ELSE IF(V$CAT_NONE = 1) THEN V13 = V13 + 1;
      -- Высшее профессиональное образование
      IF(V$EDU_ID IN (620, 3031, 3032)) THEN V16 = V16 + 1;
      -- Педагогичесое образование
      IF(V$IS_PD = 1) THEN V17 = V17 + 1;
      -- Среднее профессиональное образование
      IF(V$EDU_ID = 622) THEN V18 = V18 + 1;
      -- Среднее профессиональное образование + педагогическое
      IF(V$IS_PD2 = 1) THEN V19 = V19 + 1;
      -- Начальное профессиональное образование
      IF(V$EDU_ID = 624) THEN V20 = V20 + 1;
      -- Среднее общее образование
      IF(V$EDU_ID = 623) THEN V21 = V21 + 1;
      -- Стаж
      IF((V$STAGE_YEARS / 365) < 2) THEN V22 = V22 + 1;
      ELSE IF((V$STAGE_YEARS / 365) < 5) THEN V23 = V23 + 1;
      ELSE IF((V$STAGE_YEARS / 365) < 10) THEN V24 = V24 + 1;
      ELSE IF((V$STAGE_YEARS / 365) < 20) THEN V25 = V25 + 1;
      ELSE V26 = V26 + 1;
      -- Возраст
      IF((DATEDIFF(DAY, V$BIRTH_DATE, V$REPORT_DATE) / 365) < 25) THEN V27 = V27 + 1;
      ELSE IF((DATEDIFF(DAY, V$BIRTH_DATE, V$REPORT_DATE) / 365) < 35) THEN V28 = V28 + 1;
      ELSE V29 = V29 + 1;
    END
  END

  FOR
    SELECT D.SEX, D.IS_SOC, D.IS_TRAIN, D.IS_MTD, D.IS_PDO, D.IS_AUX
    FROM R_1DO_ODOD_6_DTL2(:V$OU_ID) D
    INTO :V$SEX, :V$IS_SOC, :V$IS_TRAIN, :V$IS_MTD, :V$IS_PDO, :V$IS_AUX
  DO
  BEGIN
    V$MATCH = 0;

    -- Социальный педагог
    IF(I$PARAM_ID = 611 AND V$IS_SOC = 1) THEN V$MATCH = 1;
    -- Тренер-преподаватель
    ELSE IF(I$PARAM_ID = 612 AND V$IS_TRAIN = 1) THEN V$MATCH = 1;
    -- Методист
    ELSE IF(I$PARAM_ID = 613 AND V$IS_MTD = 1) THEN V$MATCH = 1;
    -- Прочие педагогические работники
    ELSE IF(I$PARAM_ID = 614 AND V$IS_PDO = 1) THEN V$MATCH = 1;
    -- Вспомогательный персонал
    ELSE IF(I$PARAM_ID = 615 AND V$IS_AUX = 1) THEN V$MATCH = 1;

    -- Отбираем нужные строки отчета
    IF(V$MATCH = 1) THEN
    BEGIN
      V9 = V9 + 1;
    END
  END

  FOR
    SELECT D.SEX, D.IS_SOC, D.IS_TRAIN, D.IS_MTD, D.IS_PDO, D.IS_AUX
    FROM R_1DO_ODOD_6_DTL3(:V$OU_ID) D
    INTO :V$SEX, :V$IS_SOC, :V$IS_TRAIN, :V$IS_MTD, :V$IS_PDO, :V$IS_AUX
  DO
  BEGIN
    V$MATCH = 0;

    -- Социальный педагог
    IF(I$PARAM_ID = 611 AND V$IS_SOC = 1) THEN V$MATCH = 1;
    -- Тренер-преподаватель
    ELSE IF(I$PARAM_ID = 612 AND V$IS_TRAIN = 1) THEN V$MATCH = 1;
    -- Методист
    ELSE IF(I$PARAM_ID = 613 AND V$IS_MTD = 1) THEN V$MATCH = 1;
    -- Прочие педагогические работники
    ELSE IF(I$PARAM_ID = 614 AND V$IS_PDO = 1) THEN V$MATCH = 1;
    -- Вспомогательный персонал
    ELSE IF(I$PARAM_ID = 615 AND V$IS_AUX = 1) THEN V$MATCH = 1;

    -- Отбираем нужные строки отчета
    IF(V$MATCH = 1) THEN
    BEGIN
      V14 = V14 + 1;
      IF(V$SEX = 182) THEN V15 = V15 + 1;
    END
  END

  SUSPEND;
end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_1DO_ODOD_6_4 (
    I$PARAM_ID INTEGER,
    I$YEAR SMALLINT = null)
RETURNS (
    V3 INTEGER,
    V4 NUMERIC(15,2),
    V5 INTEGER,
    V6 INTEGER,
    V7 INTEGER,
    V8 INTEGER,
    V9 INTEGER,
    V10 INTEGER,
    V11 INTEGER,
    V12 INTEGER,
    V13 INTEGER,
    V14 INTEGER,
    V15 INTEGER,
    V16 INTEGER,
    V17 INTEGER,
    V18 INTEGER,
    V19 INTEGER,
    V20 INTEGER,
    V21 INTEGER,
    V22 INTEGER,
    V23 INTEGER,
    V24 INTEGER,
    V25 INTEGER,
    V26 INTEGER,
    V27 INTEGER,
    V28 INTEGER,
    V29 INTEGER,
    V30 INTEGER,
    V31 INTEGER)
AS
declare variable V$OU_ID bigint;
declare variable V$REPORT_DATE date;
declare variable V$IS_WRK smallint;
declare variable V$SEX bigint;
declare variable V$BIRTH_DATE date;
declare variable V$FULL_OCCP smallint;
declare variable V$PART_OCCP smallint;
declare variable V$CAT_TOP smallint;
declare variable V$CAT_1 smallint;
declare variable V$CAT_2 smallint;
declare variable V$CAT_NONE smallint;
declare variable V$EDU_ID bigint;
declare variable V$IS_PD smallint;
declare variable V$IS_PD2 smallint;
declare variable V$STAGE_YEARS float;
declare variable V$MATCH smallint;
begin
  IF (I$YEAR IS NULL) THEN I$YEAR = EXTRACT(YEAR FROM CURRENT_DATE);
  IF (I$YEAR = EXTRACT(YEAR FROM CURRENT_DATE) AND (CURRENT_DATE < I$YEAR || '-09-01')) THEN I$YEAR = I$YEAR - 1;
  V$REPORT_DATE = I$YEAR || '-12-25';

  SELECT FIRST 1 L2.OBJ_ID
  FROM LINKS L2
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$OU_ID;

  V3 = 0;
  V4 = 0;
  V5 = 0;
  V6 = 0;
  V7 = 0;
  V8 = 0;
  V9 = 0;
  V10 = 0;
  V11 = 0;
  V12 = 0;
  V13 = 0;
  V14 = 0;
  V15 = 0;
  V16 = 0;
  V17 = 0;
  V18 = 0;
  V19 = 0;
  V20 = 0;
  V21 = 0;
  V22 = 0;
  V23 = 0;
  V24 = 0;
  V25 = 0;
  V26 = 0;
  V27 = 0;
  V28 = 0;
  V29 = 0;
  V30 = 0;
  V31 = 0;

  FOR
    SELECT D.SEX, D.BIRTH_DATE, D.FULL_OCCP, D.PART_OCCP, D.CAT_TOP, D.CAT_1, D.CAT_2, D.CAT_NONE, D.EDU_ID, D.IS_PD, D.IS_PD2, D.STAGE_YEARS,
      D.IS_WRK
    FROM R_1DO_ODOD_6_DTL(:V$OU_ID) D
    INTO :V$SEX, :V$BIRTH_DATE, :V$FULL_OCCP, :V$PART_OCCP, :V$CAT_TOP, :V$CAT_1, :V$CAT_2, :V$CAT_NONE, :V$EDU_ID, :V$IS_PD, :V$IS_PD2, :V$STAGE_YEARS,
      :V$IS_WRK
  DO
  BEGIN
    V$MATCH = 0;

    -- Рабочие
    IF(I$PARAM_ID = 616 AND V$IS_WRK = 1) THEN V$MATCH = 1;

    -- Отбираем нужные строки отчета
    IF(V$MATCH = 1) THEN
    BEGIN
      -- Общий счетчик
      V3 = V3 + 1;
      -- Женщины
      IF(V$SEX = 182) THEN V6 = V6 + 1;
      -- Неполная занятость
      IF(V$PART_OCCP = 1) THEN V7 = V7 + 1;
      -- Полная занятость
      IF(V$FULL_OCCP = 1) THEN V8 = V8 + 1;
      -- Совместительство
      -- Категории
      IF(V$CAT_TOP = 1) THEN V10 = V10 + 1;
      ELSE IF(V$CAT_1 = 1) THEN V11 = V11 + 1;
      ELSE IF(V$CAT_2 = 1) THEN V12 = V12 + 1;
      ELSE IF(V$CAT_NONE = 1) THEN V13 = V13 + 1;
      -- Высшее профессиональное образование
      IF(V$EDU_ID IN (620, 3031, 3032)) THEN V16 = V16 + 1;
      -- Педагогичесое образование
      IF(V$IS_PD = 1) THEN V17 = V17 + 1;
      -- Среднее профессиональное образование
      IF(V$EDU_ID = 622) THEN V18 = V18 + 1;
      -- Среднее профессиональное образование + педагогическое
      IF(V$IS_PD2 = 1) THEN V19 = V19 + 1;
      -- Начальное профессиональное образование
      IF(V$EDU_ID = 624) THEN V20 = V20 + 1;
      -- Среднее общее образование
      IF(V$EDU_ID = 623) THEN V21 = V21 + 1;
      -- Стаж
      IF((V$STAGE_YEARS / 365) < 2) THEN V22 = V22 + 1;
      ELSE IF((V$STAGE_YEARS / 365) < 5) THEN V23 = V23 + 1;
      ELSE IF((V$STAGE_YEARS / 365) < 10) THEN V24 = V24 + 1;
      ELSE IF((V$STAGE_YEARS / 365) < 20) THEN V25 = V25 + 1;
      ELSE V26 = V26 + 1;
      -- Возраст
      IF((DATEDIFF(DAY, V$BIRTH_DATE, V$REPORT_DATE) / 365) < 25) THEN V27 = V27 + 1;
      ELSE IF((DATEDIFF(DAY, V$BIRTH_DATE, V$REPORT_DATE) / 365) < 35) THEN V28 = V28 + 1;
      ELSE V29 = V29 + 1;
    END
  END

  FOR
    SELECT D.SEX, D.IS_WRK
    FROM R_1DO_ODOD_6_DTL2(:V$OU_ID) D
    INTO :V$SEX, :V$IS_WRK
  DO
  BEGIN
    V$MATCH = 0;

    -- Рабочие
    IF(I$PARAM_ID = 616 AND V$IS_WRK = 1) THEN V$MATCH = 1;

    -- Отбираем нужные строки отчета
    IF(V$MATCH = 1) THEN
    BEGIN
      V9 = V9 + 1;
    END
  END

  FOR
    SELECT D.SEX, D.IS_WRK
    FROM R_1DO_ODOD_6_DTL3(:V$OU_ID) D
    INTO :V$SEX, :V$IS_WRK
  DO
  BEGIN
    V$MATCH = 0;

    -- Рабочие
    IF(I$PARAM_ID = 616 AND V$IS_WRK = 1) THEN V$MATCH = 1;

    -- Отбираем нужные строки отчета
    IF(V$MATCH = 1) THEN
    BEGIN
      V14 = V14 + 1;
      IF(V$SEX = 182) THEN V15 = V15 + 1;
    END
  END

  SUSPEND;
end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_1DO_ODOD_6_DTL (
    I$OU_ID BIGINT)
RETURNS (
    PERSON_ID BIGINT,
    BIRTH_DATE DATE,
    SEX BIGINT,
    STAGE_YEARS FLOAT,
    EDU_ID BIGINT,
    FULL_OCCP SMALLINT,
    PART_OCCP SMALLINT,
    CAT_TOP SMALLINT,
    CAT_1 SMALLINT,
    CAT_2 SMALLINT,
    CAT_NONE SMALLINT,
    IS_PD SMALLINT,
    IS_PD2 SMALLINT,
    IS_MANAGER SMALLINT,
    IS_M1 SMALLINT,
    IS_M2 SMALLINT,
    IS_GB SMALLINT,
    IS_MX SMALLINT,
    IS_PDD SMALLINT,
    IS_TEACHER SMALLINT,
    IS_DO SMALLINT,
    IS_PORG SMALLINT,
    IS_SOC SMALLINT,
    IS_TRAIN SMALLINT,
    IS_MTD SMALLINT,
    IS_PDO SMALLINT,
    IS_AUX SMALLINT,
    IS_WRK SMALLINT)
AS
declare variable N_JOB integer;
declare variable V$STAV float;
declare variable V$CAT_ID bigint;
declare variable V$EDT_ID bigint;
declare variable V$JOB_GROUP_ID bigint;
declare variable V$JOB_SUBGROUP_ID bigint;
declare variable V$JOB_ID bigint;
declare variable V$JT varchar(400);
declare variable V$PDD smallint;
begin

  -- Тут только основные сотрудники, совместители в DTL2

  FOR
      SELECT L14.OBJ_ID, V241.VAL, V239.LISTVAL_ID, F.VAL, V278.LISTVAL_ID
      FROM LINKS L14
      JOIN VALL V274 ON V274.OBJ_ID = L14.OBJ_ID AND V274.PARAM_ID = 274 AND V274.IS_DEL = 0 AND V274.LISTVAL_ID = 602 -- статус = работающий сотрудник
      LEFT JOIN VALL V239 ON V239.OBJ_ID = L14.OBJ_ID AND V239.PARAM_ID = 239 AND V239.IS_DEL = 0 -- пол
      LEFT JOIN VALL V278 ON V278.OBJ_ID = L14.OBJ_ID AND V278.PARAM_ID = 278 AND V278.IS_DEL = 0
      LEFT JOIN DO_FUNC(L14.OBJ_ID, NULL, 2, 941) F ON 1 = 1
      LEFT JOIN VALD V241 ON V241.OBJ_ID = L14.OBJ_ID AND V241.PARAM_ID = 241 AND V241.IS_DEL = 0
      WHERE L14.PARENT_ID = :I$OU_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
      UNION
      SELECT L14.OBJ_ID, V241.VAL, V239.LISTVAL_ID, F.VAL, V278.LISTVAL_ID
      FROM LINKS L211
      JOIN LINKS L14 ON L14.PARENT_ID = L211.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
      JOIN VALL V274 ON V274.OBJ_ID = L14.OBJ_ID AND V274.PARAM_ID = 274 AND V274.IS_DEL = 0 AND V274.LISTVAL_ID = 602 -- статус = работающий сотрудник
      LEFT JOIN VALL V239 ON V239.OBJ_ID = L14.OBJ_ID AND V239.PARAM_ID = 239 AND V239.IS_DEL = 0 -- пол
      LEFT JOIN VALL V278 ON V278.OBJ_ID = L14.OBJ_ID AND V278.PARAM_ID = 278 AND V278.IS_DEL = 0
      LEFT JOIN DO_FUNC(L14.OBJ_ID, NULL, 2, 941) F ON 1 = 1
      LEFT JOIN VALD V241 ON V241.OBJ_ID = L14.OBJ_ID AND V241.PARAM_ID = 241 AND V241.IS_DEL = 0
      WHERE L211.PARENT_ID = :I$OU_ID AND L211.OBJ_TYPE_ID = 211 AND L211.DATE_DEL IS NULL
      INTO :PERSON_ID, :BIRTH_DATE, :SEX, :STAGE_YEARS, :EDU_ID
  DO
  BEGIN

      N_JOB = 0;
      FULL_OCCP = 0;
      PART_OCCP = 0;
      CAT_TOP = 0;
      CAT_1 = 0;
      CAT_2 = 0;
      CAT_NONE = 0;
      IS_PD = 0;
      IS_PD2 = 0;
      IS_MANAGER = 0;
      IS_M1 = 0;
      IS_M2 = 0;
      IS_GB = 0;
      IS_MX = 0;
      IS_PDD = 0;
      IS_TEACHER = 0;
      IS_DO = 0;
      IS_PORG = 0;
      IS_SOC = 0;
      IS_TRAIN = 0;
      IS_MTD = 0;
      IS_PDO = 0;
      IS_AUX = 0;
      IS_WRK = 0;

      FOR
          SELECT V71.VAL, V1790.LISTVAL_ID, V1398.LISTVAL_ID, V1399.LISTVAL_ID, V1394.LISTVAL_ID, R.VAL, IIF(V2444.VAL = 'Да', 1, 0)
          FROM LINKS L15
          JOIN VALL V72 ON V72.OBJ_ID = L15.OBJ_ID AND V72.PARAM_ID = 72 AND V72.IS_DEL = 0 AND V72.LISTVAL_ID = 934 -- только основная должность
          JOIN VALL V587 ON V587.OBJ_ID = L15.OBJ_ID AND V587.PARAM_ID = 587 AND V587.IS_DEL = 0 AND V587.LISTVAL_ID = 207 -- условия приема на должность = штатный сотрудник
          JOIN VALF V71 ON V71.OBJ_ID = L15.OBJ_ID AND V71.PARAM_ID = 71 AND V71.IS_DEL = 0 -- количество ставок по должности
          JOIN VALL V1790 ON V1790.OBJ_ID = L15.OBJ_ID AND V1790.PARAM_ID = 1790 AND V1790.IS_DEL = 0 -- квалификацинная категория
          JOIN VALL V1398 ON V1398.OBJ_ID = L15.OBJ_ID AND V1398.PARAM_ID = 1398 AND V1398.IS_DEL = 0 -- группа должностей
          JOIN VALL V1399 ON V1399.OBJ_ID = L15.OBJ_ID AND V1399.PARAM_ID = 1399 AND V1399.IS_DEL = 0 -- подгруппа должностей
          JOIN VALL V1394 ON V1394.OBJ_ID = L15.OBJ_ID AND V1394.PARAM_ID = 1394 AND V1394.IS_DEL = 0 -- Должность (как трудовая функция)
          JOIN LISTVALS LV ON LV.LISTVAL_ID = V1394.LISTVAL_ID AND LV.IS_DEL = 0
          JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU' AND R.IS_DEL = 0
          JOIN VALR V69 ON V69.OBJ_ID = L15.OBJ_ID AND V69.PARAM_ID = 69 AND V69.IS_DEL = 0 -- ссылка на должность
          LEFT JOIN DO_FUNC(V69.VAL, 400) V2444 ON 1 = 1
          WHERE L15.PARENT_ID = :PERSON_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
          INTO :V$STAV, :V$CAT_ID, :V$JOB_GROUP_ID, :V$JOB_SUBGROUP_ID, :V$JOB_ID, :V$JT, :V$PDD
      DO
      BEGIN
          N_JOB = N_JOB + 1;
          IF(V$STAV < 1) THEN PART_OCCP = 1;
          IF(V$STAV >= 1) THEN FULL_OCCP = 1;
          IF(V$CAT_ID = 635) THEN CAT_TOP = 1;
          IF(V$CAT_ID = 633) THEN CAT_1 = 1;
          IF(V$CAT_ID = 633) THEN CAT_2 = 1;
          IF(V$CAT_ID = 632) THEN CAT_NONE = 1;
          IF(V$JOB_GROUP_ID = 55) THEN IS_MANAGER = 1;
          IF(V$JOB_SUBGROUP_ID = 56) THEN IS_M1 = 1;
          -- Заместитель руководителя
          IF(V$JOB_SUBGROUP_ID = 113 AND LOWER(:V$JT) LIKE ('заместитель%')) THEN IS_M2 = 1;
          -- Главный бухгалтер
          IF(V$JOB_ID = 69) THEN IS_GB = 1;
          IF(V$JOB_SUBGROUP_ID IN (56, 113) AND V$JOB_ID <> 69 AND LOWER(:V$JT) NOT LIKE ('заместитель%')) THEN IS_MX = 1;
          IF(V$PDD = 1) THEN IS_PDD = 1;
          IF(V$JOB_SUBGROUP_ID = 98) THEN IS_TEACHER = 1;
          IF(V$JOB_ID = 143) THEN IS_DO = 1;
          IF(V$JOB_ID = 144) THEN IS_PORG = 1;
          IF(V$JOB_ID = 1251) THEN IS_SOC = 1;
          IF(V$JOB_ID = 1256) THEN IS_TRAIN = 1;
          IF(V$JOB_ID = 133) THEN IS_MTD = 1;
          IF(V$PDD = 1 AND V$JOB_ID NOT IN (98, 143, 144, 1251, 1256, 133)) THEN IS_PDO = 1;
          IF(V$JOB_SUBGROUP_ID IN (1257, 1313)) THEN IS_AUX = 1;
          IF(V$JOB_SUBGROUP_ID = 1323) THEN IS_WRK = 1;
      END

      -- Образование, профили
      FOR
          SELECT V293.LISTVAL_ID
          FROM LINKS L33
          JOIN VALL V293 ON V293.OBJ_ID = L33.OBJ_ID AND V293.PARAM_ID = 293 AND V293.IS_DEL = 0
          WHERE L33.PARENT_ID = :PERSON_ID AND L33.OBJ_TYPE_ID = 33 AND L33.DATE_DEL IS NULL
          INTO :V$EDT_ID
      DO
      BEGIN
          IF(EDU_ID IN (620, 3031, 3032) AND V$EDT_ID = 647) THEN IS_PD = 1; -- высшее педагогическое
          IF(EDU_ID = 622 AND V$EDT_ID = 647) THEN IS_PD2 = 1; -- среднее профессиональное педагогическое
      END

      IF(N_JOB > 0) THEN SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_1DO_ODOD_6_DTL2 (
    I$OU_ID BIGINT)
RETURNS (
    PERSON_ID BIGINT,
    BIRTH_DATE DATE,
    SEX BIGINT,
    STAGE_YEARS FLOAT,
    EDU_ID BIGINT,
    IS_MANAGER SMALLINT,
    IS_M1 SMALLINT,
    IS_M2 SMALLINT,
    IS_MX SMALLINT,
    IS_GB SMALLINT,
    IS_PDD SMALLINT,
    IS_TEACHER SMALLINT,
    IS_DO SMALLINT,
    IS_PORG SMALLINT,
    IS_SOC SMALLINT,
    IS_TRAIN SMALLINT,
    IS_MTD SMALLINT,
    IS_PDO SMALLINT,
    IS_AUX SMALLINT,
    IS_WRK SMALLINT)
AS
declare variable N_JOB integer;
declare variable V$JOB_GROUP_ID bigint;
declare variable V$JOB_SUBGROUP_ID bigint;
declare variable V$JOB_ID bigint;
declare variable V$JT varchar(400);
declare variable V$PDD smallint;
begin

  -- Внутренние совместители

  FOR
      SELECT L14.OBJ_ID, V241.VAL, V239.LISTVAL_ID, F.VAL, V278.LISTVAL_ID
      FROM LINKS L14
      JOIN VALL V274 ON V274.OBJ_ID = L14.OBJ_ID AND V274.PARAM_ID = 274 AND V274.IS_DEL = 0 AND V274.LISTVAL_ID = 602 -- статус = работающий сотрудник
      LEFT JOIN VALL V239 ON V239.OBJ_ID = L14.OBJ_ID AND V239.PARAM_ID = 239 AND V239.IS_DEL = 0 -- пол
      LEFT JOIN VALL V278 ON V278.OBJ_ID = L14.OBJ_ID AND V278.PARAM_ID = 278 AND V278.IS_DEL = 0
      LEFT JOIN DO_FUNC(L14.OBJ_ID, NULL, 2, 941) F ON 1 = 1
      LEFT JOIN VALD V241 ON V241.OBJ_ID = L14.OBJ_ID AND V241.PARAM_ID = 241 AND V241.IS_DEL = 0
      WHERE L14.PARENT_ID = :I$OU_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
      UNION
      SELECT L14.OBJ_ID, V241.VAL, V239.LISTVAL_ID, F.VAL, V278.LISTVAL_ID
      FROM LINKS L211
      JOIN LINKS L14 ON L14.PARENT_ID = L211.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
      JOIN VALL V274 ON V274.OBJ_ID = L14.OBJ_ID AND V274.PARAM_ID = 274 AND V274.IS_DEL = 0 AND V274.LISTVAL_ID = 602 -- статус = работающий сотрудник
      LEFT JOIN VALL V239 ON V239.OBJ_ID = L14.OBJ_ID AND V239.PARAM_ID = 239 AND V239.IS_DEL = 0 -- пол
      LEFT JOIN VALL V278 ON V278.OBJ_ID = L14.OBJ_ID AND V278.PARAM_ID = 278 AND V278.IS_DEL = 0
      LEFT JOIN DO_FUNC(L14.OBJ_ID, NULL, 2, 941) F ON 1 = 1
      LEFT JOIN VALD V241 ON V241.OBJ_ID = L14.OBJ_ID AND V241.PARAM_ID = 241 AND V241.IS_DEL = 0
      WHERE L211.PARENT_ID = :I$OU_ID AND L211.OBJ_TYPE_ID = 211 AND L211.DATE_DEL IS NULL
      INTO :PERSON_ID, :BIRTH_DATE, :SEX, :STAGE_YEARS, :EDU_ID
  DO
  BEGIN

      N_JOB = 0;
      IS_MANAGER = 0;
      IS_M1 = 0;
      IS_M2 = 0;
      IS_GB = 0;
      IS_MX = 0;
      IS_PDD = 0;
      IS_TEACHER = 0;
      IS_DO = 0;
      IS_PORG = 0;
      IS_SOC = 0;
      IS_TRAIN = 0;
      IS_MTD = 0;
      IS_PDO = 0;
      IS_AUX = 0;
      IS_WRK = 0;

      FOR
          SELECT V1398.LISTVAL_ID, V1399.LISTVAL_ID, V1394.LISTVAL_ID, R.VAL, IIF(V2444.VAL = 'Да', 1, 0)
          FROM LINKS L15
          JOIN VALL V72 ON V72.OBJ_ID = L15.OBJ_ID AND V72.PARAM_ID = 72 AND V72.IS_DEL = 0 AND V72.LISTVAL_ID = 935 -- должность = дополнительная
          JOIN VALL V587 ON V587.OBJ_ID = L15.OBJ_ID AND V587.PARAM_ID = 587 AND V587.IS_DEL = 0 AND V587.LISTVAL_ID = 207 -- условия приема на должность = штатный сотрудник
          JOIN VALL V1398 ON V1398.OBJ_ID = L15.OBJ_ID AND V1398.PARAM_ID = 1398 AND V1398.IS_DEL = 0 -- группа должностей
          JOIN VALL V1399 ON V1399.OBJ_ID = L15.OBJ_ID AND V1399.PARAM_ID = 1399 AND V1399.IS_DEL = 0 -- подгруппа должностей
          JOIN VALL V1394 ON V1394.OBJ_ID = L15.OBJ_ID AND V1394.PARAM_ID = 1394 AND V1394.IS_DEL = 0 -- Должность (как трудовая функция)
          JOIN LISTVALS LV ON LV.LISTVAL_ID = V1394.LISTVAL_ID AND LV.IS_DEL = 0
          JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU' AND R.IS_DEL = 0
          JOIN VALR V69 ON V69.OBJ_ID = L15.OBJ_ID AND V69.PARAM_ID = 69 AND V69.IS_DEL = 0 -- ссылка на должность
          LEFT JOIN DO_FUNC(V69.VAL, 400) V2444 ON 1 = 1
          WHERE L15.PARENT_ID = :PERSON_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
          INTO :V$JOB_GROUP_ID, :V$JOB_SUBGROUP_ID, :V$JOB_ID, :V$JT, :V$PDD
      DO
      BEGIN
          N_JOB = N_JOB + 1;
          IF(V$JOB_GROUP_ID = 55) THEN IS_MANAGER = 1;
          IF(V$JOB_SUBGROUP_ID = 56) THEN IS_M1 = 1;
          -- Заместитель руководителя
          IF(V$JOB_SUBGROUP_ID = 113 AND LOWER(:V$JT) LIKE ('заместитель%')) THEN IS_M2 = 1;
          -- Главный бухгалтер
          IF(V$JOB_ID = 69) THEN IS_GB = 1;
          IF(V$JOB_SUBGROUP_ID IN (56, 113) AND V$JOB_ID <> 69 AND LOWER(:V$JT) NOT LIKE ('заместитель%')) THEN IS_MX = 1;
          IF(V$PDD = 1) THEN IS_PDD = 1;
          IF(V$JOB_SUBGROUP_ID = 98) THEN IS_TEACHER = 1;
          IF(V$JOB_ID = 143) THEN IS_DO = 1;
          IF(V$JOB_ID = 144) THEN IS_PORG = 1;
          IF(V$JOB_ID = 1251) THEN IS_SOC = 1;
          IF(V$JOB_ID = 1256) THEN IS_TRAIN = 1;
          IF(V$JOB_ID = 133) THEN IS_MTD = 1;
          IF(V$PDD = 1 AND V$JOB_ID NOT IN (98, 143, 144, 1251, 1256, 133)) THEN IS_PDO = 1;
          IF(V$JOB_SUBGROUP_ID IN (1257, 1313)) THEN IS_AUX = 1;
          IF(V$JOB_SUBGROUP_ID = 1323) THEN IS_WRK = 1;
      END

      IF(N_JOB > 0) THEN SUSPEND;

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_1DO_ODOD_6_DTL3 (
    I$OU_ID BIGINT)
RETURNS (
    PERSON_ID BIGINT,
    BIRTH_DATE DATE,
    SEX BIGINT,
    STAGE_YEARS FLOAT,
    EDU_ID BIGINT,
    IS_MANAGER SMALLINT,
    IS_M1 SMALLINT,
    IS_M2 SMALLINT,
    IS_GB SMALLINT,
    IS_MX SMALLINT,
    IS_PDD SMALLINT,
    IS_TEACHER SMALLINT,
    IS_DO SMALLINT,
    IS_PORG SMALLINT,
    IS_SOC SMALLINT,
    IS_TRAIN SMALLINT,
    IS_MTD SMALLINT,
    IS_PDO SMALLINT,
    IS_AUX SMALLINT,
    IS_WRK SMALLINT)
AS
declare variable N_JOB integer;
declare variable V$JOB_GROUP_ID bigint;
declare variable V$JOB_SUBGROUP_ID bigint;
declare variable V$JOB_ID bigint;
declare variable V$JT varchar(400);
declare variable V$PDD smallint;
begin

  -- Внешние совместители

  FOR
      SELECT L14.OBJ_ID, V241.VAL, V239.LISTVAL_ID, F.VAL, V278.LISTVAL_ID
      FROM LINKS L14
      JOIN VALL V274 ON V274.OBJ_ID = L14.OBJ_ID AND V274.PARAM_ID = 274 AND V274.IS_DEL = 0 AND V274.LISTVAL_ID = 602 -- статус = работающий сотрудник
      LEFT JOIN VALL V239 ON V239.OBJ_ID = L14.OBJ_ID AND V239.PARAM_ID = 239 AND V239.IS_DEL = 0 -- пол
      LEFT JOIN VALL V278 ON V278.OBJ_ID = L14.OBJ_ID AND V278.PARAM_ID = 278 AND V278.IS_DEL = 0
      LEFT JOIN DO_FUNC(L14.OBJ_ID, NULL, 2, 941) F ON 1 = 1
      LEFT JOIN VALD V241 ON V241.OBJ_ID = L14.OBJ_ID AND V241.PARAM_ID = 241 AND V241.IS_DEL = 0
      WHERE L14.PARENT_ID = :I$OU_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
      UNION
      SELECT L14.OBJ_ID, V241.VAL, V239.LISTVAL_ID, F.VAL, V278.LISTVAL_ID
      FROM LINKS L211
      JOIN LINKS L14 ON L14.PARENT_ID = L211.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
      JOIN VALL V274 ON V274.OBJ_ID = L14.OBJ_ID AND V274.PARAM_ID = 274 AND V274.IS_DEL = 0 AND V274.LISTVAL_ID = 602 -- статус = работающий сотрудник
      LEFT JOIN VALL V239 ON V239.OBJ_ID = L14.OBJ_ID AND V239.PARAM_ID = 239 AND V239.IS_DEL = 0 -- пол
      LEFT JOIN VALL V278 ON V278.OBJ_ID = L14.OBJ_ID AND V278.PARAM_ID = 278 AND V278.IS_DEL = 0
      LEFT JOIN DO_FUNC(L14.OBJ_ID, NULL, 2, 941) F ON 1 = 1
      LEFT JOIN VALD V241 ON V241.OBJ_ID = L14.OBJ_ID AND V241.PARAM_ID = 241 AND V241.IS_DEL = 0
      WHERE L211.PARENT_ID = :I$OU_ID AND L211.OBJ_TYPE_ID = 211 AND L211.DATE_DEL IS NULL
      INTO :PERSON_ID, :BIRTH_DATE, :SEX, :STAGE_YEARS, :EDU_ID
  DO
  BEGIN

      N_JOB = 0;
      IS_MANAGER = 0;
      IS_M1 = 0;
      IS_M2 = 0;
      IS_GB = 0;
      IS_MX = 0;
      IS_PDD = 0;
      IS_TEACHER = 0;
      IS_DO = 0;
      IS_PORG = 0;
      IS_SOC = 0;
      IS_TRAIN = 0;
      IS_MTD = 0;
      IS_PDO = 0;
      IS_AUX = 0;
      IS_WRK = 0;

      FOR
          SELECT V1398.LISTVAL_ID, V1399.LISTVAL_ID, V1394.LISTVAL_ID, R.VAL, IIF(V2444.VAL = 'Да', 1, 0)
          FROM LINKS L15
          JOIN VALL V72 ON V72.OBJ_ID = L15.OBJ_ID AND V72.PARAM_ID = 72 AND V72.IS_DEL = 0 AND V72.LISTVAL_ID = 934 -- должность = основная
          JOIN VALL V587 ON V587.OBJ_ID = L15.OBJ_ID AND V587.PARAM_ID = 587 AND V587.IS_DEL = 0 AND V587.LISTVAL_ID = 208 -- условия приема на должность = совместитель
          JOIN VALL V1398 ON V1398.OBJ_ID = L15.OBJ_ID AND V1398.PARAM_ID = 1398 AND V1398.IS_DEL = 0 -- группа должностей
          JOIN VALL V1399 ON V1399.OBJ_ID = L15.OBJ_ID AND V1399.PARAM_ID = 1399 AND V1399.IS_DEL = 0 -- подгруппа должностей
          JOIN VALL V1394 ON V1394.OBJ_ID = L15.OBJ_ID AND V1394.PARAM_ID = 1394 AND V1394.IS_DEL = 0 -- Должность (как трудовая функция)
          JOIN LISTVALS LV ON LV.LISTVAL_ID = V1394.LISTVAL_ID AND LV.IS_DEL = 0
          JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU' AND R.IS_DEL = 0
          JOIN VALR V69 ON V69.OBJ_ID = L15.OBJ_ID AND V69.PARAM_ID = 69 AND V69.IS_DEL = 0 -- ссылка на должность
          LEFT JOIN DO_FUNC(V69.VAL, 400) V2444 ON 1 = 1
          WHERE L15.PARENT_ID = :PERSON_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
          INTO :V$JOB_GROUP_ID, :V$JOB_SUBGROUP_ID, :V$JOB_ID, :V$JT, :V$PDD
      DO
      BEGIN
          N_JOB = N_JOB + 1;
          IF(V$JOB_GROUP_ID = 55) THEN IS_MANAGER = 1;
          IF(V$JOB_SUBGROUP_ID = 56) THEN IS_M1 = 1;
          -- Заместитель руководителя
          IF(V$JOB_SUBGROUP_ID = 113 AND LOWER(:V$JT) LIKE ('заместитель%')) THEN IS_M2 = 1;
          -- Главный бухгалтер
          IF(V$JOB_ID = 69) THEN IS_GB = 1;
          IF(V$JOB_SUBGROUP_ID IN (56, 113) AND V$JOB_ID <> 69 AND LOWER(:V$JT) NOT LIKE ('заместитель%')) THEN IS_MX = 1;
          IF(V$PDD = 1) THEN IS_PDD = 1;
          IF(V$JOB_SUBGROUP_ID = 98) THEN IS_TEACHER = 1;
          IF(V$JOB_ID = 143) THEN IS_DO = 1;
          IF(V$JOB_ID = 144) THEN IS_PORG = 1;
          IF(V$JOB_ID = 1251) THEN IS_SOC = 1;
          IF(V$JOB_ID = 1256) THEN IS_TRAIN = 1;
          IF(V$JOB_ID = 133) THEN IS_MTD = 1;
          IF(V$PDD = 1 AND V$JOB_ID NOT IN (98, 143, 144, 1251, 1256, 133)) THEN IS_PDO = 1;
          IF(V$JOB_SUBGROUP_ID IN (1257, 1313)) THEN IS_AUX = 1;
          IF(V$JOB_SUBGROUP_ID = 1323) THEN IS_WRK = 1;
      END

      IF(N_JOB > 0) THEN SUSPEND;

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_85K_1 (
    I$OBJ_ID BIGINT NOT NULL,
    I$NUM SMALLINT NOT NULL)
RETURNS (
    V03 SMALLINT)
AS
DECLARE VARIABLE OU_TYPE BIGINT;
DECLARE VARIABLE OU_VID BIGINT;
DECLARE VARIABLE OU_OPF BIGINT;
BEGIN
    IF (:I$NUM < 3) THEN
    BEGIN
        -- OU_TYPE
        SELECT L.LISTVAL_ID
        FROM VALL V, LISTVALS L
        WHERE L.LISTVAL_ID = V.LISTVAL_ID
          AND V.OBJ_ID = :I$OBJ_ID
          AND L.LIST_ID = 6 AND L.IS_DEL = 0
          AND V.PARAM_ID = 11 AND V.IS_DEL = 0
        INTO :OU_TYPE;
    END
    -- TABSHEET 1.1
    IF (:I$NUM = 1) THEN
    BEGIN
        -- OU_VID
        SELECT L.LISTVAL_ID
        FROM VALL V, LISTVALS L
        WHERE L.LISTVAL_ID = V.LISTVAL_ID
          AND V.OBJ_ID = :I$OBJ_ID
          AND L.LIST_ID = 6 AND L.IS_DEL = 0
          AND V.PARAM_ID = 10 AND V.IS_DEL = 0
        INTO :OU_VID;
        --
        V03 = NULL;
        SUSPEND;
        -- 01
        V03 = IIF(:OU_TYPE = 947, 1, 0);
        SUSPEND;
        -- 02
        V03 = IIF(:OU_TYPE = 954, 1, 0);
        SUSPEND;
        --
        V03 = NULL;
        SUSPEND;
        -- 03
        V03 = IIF(:OU_VID = 948, 1, 0);
        SUSPEND;
        -- 04
        V03 = IIF(:OU_VID = 949, 1, 0);
        SUSPEND;
        -- 05
        V03 = IIF(:OU_VID = 950, 1, 0);
        SUSPEND;
        -- 06
        V03 = IIF(:OU_VID = 2614, 1, 0);
        SUSPEND;
        -- 07
        V03 = IIF(:OU_VID = 952, 1, 0);
        SUSPEND;
        -- 08
        V03 = IIF(:OU_VID = 951, 1, 0);
        SUSPEND;
        -- 09
        V03 = IIF(:OU_VID = 2613, 1, 0);
        SUSPEND;
        -- 10
        V03 = IIF(:OU_VID = 953, 1, 0);
        SUSPEND;
        --
        V03 = NULL;
        SUSPEND;
        -- 11
        V03 = IIF(:OU_VID = 955, 1, 0);
        SUSPEND;
        -- 12
        V03 = IIF(:OU_VID = 956, 1, 0);
        SUSPEND;
        -- 13
        V03 = IIF(:OU_VID = 957, 1, 0);
        SUSPEND;
    END
    -- TABSHEET 1.2
    IF (:I$NUM = 2) THEN
    BEGIN
        -- OU_TYPE
        SELECT L.LISTVAL_ID
        FROM VALL V, LISTVALS L
        WHERE L.LISTVAL_ID = V.LISTVAL_ID
          AND V.OBJ_ID = :I$OBJ_ID
          AND L.LIST_ID IN (4, 258) AND L.IS_DEL = 0
          AND V.PARAM_ID = 8 AND V.IS_DEL = 0
        INTO :OU_OPF;
        -- 01
        V03 = IIF(OU_OPF <> 1735 AND :OU_TYPE = 947, 1, 0);
        SUSPEND;
        -- 02
        V03 = IIF(OU_OPF = 1735 AND :OU_TYPE = 947, 1, 0);
        SUSPEND;
        -- 03
        V03 = IIF(OU_OPF = 1735 AND :OU_TYPE = 954, 1, 0);
        SUSPEND;
        -- 04
        V03 = IIF(OU_OPF <> 1735 AND :OU_TYPE = 954, 1, 0);
        SUSPEND;
    END
    -- TABSHEET 1.3
    IF (:I$NUM = 3) THEN
    BEGIN
        -- 01
        V03 = NULL;
        SUSPEND;
        -- 02
        V03 = NULL;
        SUSPEND;
        -- 03
        V03 = NULL;
        SUSPEND;
        -- 04
        V03 = 1;
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_85K_11 (
    I$OBJ_ID BIGINT NOT NULL,
    I$NUM SMALLINT NOT NULL)
RETURNS (
    V03 SMALLINT)
AS
DECLARE VARIABLE OU_TYPE BIGINT;
DECLARE VARIABLE P_1890 BIGINT;
DECLARE VARIABLE OU_OPF BIGINT;
DECLARE VARIABLE FL SMALLINT;
BEGIN
    -- OU_TYPE
    SELECT V.LISTVAL_ID
    FROM VALL V
    WHERE V.OBJ_ID = :I$OBJ_ID
      AND V.PARAM_ID = 11 AND V.IS_DEL = 0
    INTO :OU_TYPE;
    -- OU_OPF
    SELECT L.LISTVAL_ID
    FROM VALL V, LISTVALS L
    WHERE L.LISTVAL_ID = V.LISTVAL_ID
      AND V.OBJ_ID = :I$OBJ_ID
      AND L.LIST_ID IN (4, 258) AND L.IS_DEL = 0
      AND V.PARAM_ID = 8 AND V.IS_DEL = 0
    INTO :OU_OPF;
    -- P_1890
    SELECT V.LISTVAL_ID
    FROM VALL V
    WHERE V.OBJ_ID = :I$OBJ_ID
      AND V.PARAM_ID = 1890 AND V.IS_DEL = 0
    INTO :P_1890;
    -- Дошкольное?
    FL = IIF(:OU_TYPE IN (947, 954) OR :P_1890 = 5425, 1, 0);
    IF (:FL = 1 OR (:OU_OPF IN (1735, 5405) AND (:OU_TYPE IN (958, 969, 975, 1009, 1013, 1017, 1021) OR P_1890 BETWEEN 5426 AND 5430))) THEN
    BEGIN
        -- 01
        V03 = IIF(:FL = 1 AND :OU_OPF NOT IN (1735, 5405), 1, 0);
        IF (:I$NUM = 1) THEN
        BEGIN
            SUSPEND;
        END
        -- 02
        V03 = IIF(:FL = 1 AND :OU_OPF IN (1735, 5405), 1, 0);
        IF (:I$NUM = 2) THEN
        BEGIN
            SUSPEND;
        END
        -- 03
        V03 = IIF(:FL = 0 AND (:OU_TYPE IN (958, 969, 975) OR P_1890 = 5426), 1, 0);
        IF (:I$NUM = 3) THEN
        BEGIN
            SUSPEND;
        END
        FL = IIF(:FL = 1 OR :V03 = 1, 1, 0);
        -- 04
        V03 = IIF(:FL = 0 AND (:OU_TYPE IN (1009, 1013, 1017, 1021) OR P_1890 BETWEEN 5427 AND 5430), 1, 0);
        IF (:I$NUM = 4) THEN
        BEGIN
            SUSPEND;
        END
        -- 05 - 08
        IF (:I$NUM > 4) THEN
        BEGIN
            V03 = NULL;
            SUSPEND;
        END
    END
    ELSE
    BEGIN
        -- 01 - 04
        IF (:I$NUM < 5) THEN
        BEGIN
            V03 = NULL;
            SUSPEND;
        END
        -- 05
        V03 = IIF(:OU_TYPE IN (958, 969, 975) OR P_1890 = 5426, 1, 0);
        IF (:I$NUM = 5) THEN
        BEGIN
            SUSPEND;
        END
        FL = :V03;
        -- 06
        V03 = IIF(:FL = 0 AND (:OU_TYPE IN (1009, 1013, 1017, 1021) OR P_1890 IN (5427, 5428, 5430)), 1, 0);
        IF (:I$NUM = 6) THEN
        BEGIN
            SUSPEND;
        END
        FL = IIF(:FL = 1 OR :V03 = 1, 1, 0);
        -- 07
        V03 = IIF(:FL = 0 AND (:OU_TYPE = 994 OR P_1890 = 5429), 1, 0);
        IF (:I$NUM = 7) THEN
        BEGIN
            SUSPEND;
        END
        FL = IIF(:FL = 1 OR :V03 = 1, 1, 0);
        -- 08
        V03 = IIF(:FL = 0, 1, 0);
        IF (:I$NUM = 8) THEN
        BEGIN
            SUSPEND;
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_85K_12 (
    I$OBJ_ID BIGINT NOT NULL,
    I$NUM SMALLINT NOT NULL)
RETURNS (
    V03 SMALLINT)
AS
BEGIN
    -- 01
    IF (:I$NUM = 1) THEN
    BEGIN
        SELECT IIF(SUM(IIF(V551.LISTVAL_ID = 1342, 1, 0)) >
                   SUM(IIF(V551.LISTVAL_ID = 1342, 0, 1)), 1, 2)
        FROM LINKS L7
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID
          AND L8.OBJ_TYPE_ID = 8
          AND L8.DATE_DEL IS NULL
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID
          AND L9.OBJ_TYPE_ID = 9
          AND L9.DATE_DEL IS NULL
        JOIN VALL V551 ON V551.OBJ_ID = L9.OBJ_ID
          AND V551.PARAM_ID = 551
          AND V551.IS_DEL = 0
        WHERE L7.PARENT_ID = :I$OBJ_ID
          AND L7.OBJ_TYPE_ID = 7
          AND L7.DATE_DEL IS NULL
        INTO :V03;

        SUSPEND;
    END
    -- 04
    IF (:I$NUM = 4) THEN
    BEGIN
        V03 = 1;
        SUSPEND;
    END
    -- 05
    IF (:I$NUM = 5) THEN
    BEGIN
        V03 = 0;

        SELECT FIRST 1 1
        FROM LINKS L17
        JOIN VALL V471 ON V471.OBJ_ID = L17.OBJ_ID AND V471.PARAM_ID = 471 AND V471.IS_DEL = 0 AND V471.LISTVAL_ID IN (1052, 18624)
        JOIN VALL V613 ON V613.OBJ_ID = L17.OBJ_ID AND V613.PARAM_ID = 613 AND V613.IS_DEL = 0 AND V613.LISTVAL_ID IN (1982, 1984)
        WHERE L17.PARENT_ID = :I$OBJ_ID AND L17.OBJ_TYPE_ID = 17 AND L17.DATE_DEL IS NULL
        INTO :V03;

        SUSPEND;
    END
    -- 06
    IF (:I$NUM = 6) THEN
    BEGIN
        SELECT IIF(V03 IS NULL, NULL, 0)
        FROM R_85K_11(:I$OBJ_ID, 1)
        INTO :V03;

        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_85K_2 (
    I$OBJ_ID BIGINT NOT NULL,
    I$N SMALLINT NOT NULL)
RETURNS (
    SCHOLAR_ID BIGINT,
    GROUP_ID BIGINT,
    GROUP_ID_STAGE3 BIGINT)
AS
BEGIN
    FOR
        SELECT
            SCHOLAR_ID, GROUP_ID, GROUP_ID_STAGE3
        FROM (
            SELECT
                L10.OBJ_ID SCHOLAR_ID,
                L9.OBJ_ID GROUP_ID,
                L8.OBJ_ID HIGROUP_ID,
                IIF(:I$N < 19,
                   (SELECT L.LISTVAL_ID
                    FROM VALL V, LISTVALS L
                    WHERE L.LISTVAL_ID = V.LISTVAL_ID
                      AND V.OBJ_ID = L9.OBJ_ID
                      AND L.LIST_ID = 224 AND L.IS_DEL = 0
                      AND V.PARAM_ID = 1549 AND V.IS_DEL = 0),
                   (SELECT L.LISTVAL_ID
                    FROM VALL V, LISTVALS L
                    WHERE L.LISTVAL_ID = V.LISTVAL_ID
                      AND V.OBJ_ID = L9.OBJ_ID
                      AND L.LIST_ID = 227 AND L.IS_DEL = 0
                      AND V.PARAM_ID = 1558 AND V.IS_DEL = 0)) GROUP_TYPE_ID,
                IIF((SELECT L.LISTVAL_ID
                    FROM VALL V, LISTVALS L
                    WHERE L.LISTVAL_ID = V.LISTVAL_ID
                      AND V.OBJ_ID = L8.OBJ_ID
                      AND L.LIST_ID = 25 AND L.IS_DEL = 0
                      AND V.PARAM_ID = 49 AND V.IS_DEL = 0) NOT IN (30,31,32,33), L9.OBJ_ID, NULL) GROUP_ID_STAGE3
            FROM LINKS L7
            INNER JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID
            INNER JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID
            INNER JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID
            WHERE L7.PARENT_ID = :I$OBJ_ID
              AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
              AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
              AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
              AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL)
        WHERE :I$N = 1
          OR (:I$N = 2 AND GROUP_TYPE_ID = 3266)
          OR (:I$N BETWEEN 3 AND 10 AND GROUP_TYPE_ID = 3266 AND (
              SELECT L.LISTVAL_ID
              FROM VALL V, LISTVALS L
              WHERE L.LISTVAL_ID = V.LISTVAL_ID
                AND V.OBJ_ID = GROUP_ID
                AND L.LIST_ID = 224 AND L.IS_DEL = 0
                AND V.PARAM_ID = 1655 AND V.IS_DEL = 0) = 3385 + :I$N)
          OR (:I$N = 11 AND GROUP_TYPE_ID = 3265)
          OR (:I$N = 12 AND GROUP_TYPE_ID = 3267)
          OR (:I$N IN (13, 14) AND GROUP_TYPE_ID = 3267 AND (
              SELECT L.LISTVAL_ID
              FROM VALL V, LISTVALS L
              WHERE L.LISTVAL_ID = V.LISTVAL_ID
                AND V.OBJ_ID = GROUP_ID
                AND L.LIST_ID = 224 AND L.IS_DEL = 0
                AND V.PARAM_ID = 1655 AND V.IS_DEL = 0) = 3383 + :I$N)
          OR (:I$N = 15 AND GROUP_TYPE_ID = 3268)
          OR (:I$N = 17 AND COALESCE(GROUP_TYPE_ID, 3265) NOT BETWEEN 3265 AND 3268)
          OR (:I$N = 18 AND GROUP_ID_STAGE3 IS NULL)
          OR (:I$N = 19 AND GROUP_TYPE_ID = 3296)
          OR (:I$N = 20 AND GROUP_TYPE_ID = 3295)
          OR (:I$N = 21 AND (
              SELECT VAL FROM DO_FUNC(HIGROUP_ID, 1393)) > 12)
        INTO :SCHOLAR_ID, :GROUP_ID, :GROUP_ID_STAGE3
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_85K_21 (
    I$OBJ_ID BIGINT NOT NULL,
    I$N SMALLINT NOT NULL)
RETURNS (
    V03 INTEGER,
    V04 VARCHAR(10),
    V05 VARCHAR(10),
    V06 INTEGER,
    V07 VARCHAR(10))
AS
BEGIN
    IF (:I$N = 18) THEN
    BEGIN
        SUSPEND;
        EXIT;
    END
    V05 = NULL;
    SELECT
        COUNT(1) V03,
        COALESCE(SUM(IIF(GROUP_ID_STAGE3 IS NULL, 0, 1)), 0) V04,
        COUNT(DISTINCT GROUP_ID) V06,
        COUNT(DISTINCT GROUP_ID_STAGE3) V07
    FROM R_85K_2(:I$OBJ_ID, :I$N)
    INTO :V03, :V04, :V06, :V07;
    IF (:I$N > 18) THEN
    BEGIN
        V04 = 'Х';
        V05 = 'Х';
        V07 = 'Х';
    END
    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_85K_21DTL (
    I$OBJ_ID BIGINT NOT NULL,
    I$N SMALLINT NOT NULL,
    I$N2 SMALLINT NOT NULL)
RETURNS (
    VAL1 VARCHAR(250),
    VAL2 VARCHAR(250),
    NAME VARCHAR(250))
AS
BEGIN
    IF (:I$N2 < 5) THEN
    FOR
        SELECT
            (SELECT CAPTION FROM OBJECT_CAPTION_GET(SCHOLAR_ID)) VAL1,
            (SELECT D FROM VAL_GET(SCHOLAR_ID, 89)) VAL2
        FROM R_85K_2(:I$OBJ_ID, :I$N)
        WHERE :I$N2 = 3
          OR (:I$N2 = 4 AND GROUP_ID_STAGE3 IS NOT NULL)
        ORDER BY VAL1
        INTO :VAL1, :VAL2
    DO
    BEGIN
        SUSPEND;
    END
    ELSE
    FOR
        SELECT
            (SELECT CAPTION FROM OBJECT_CAPTION_GET(GROUP_ID)) NAME
        FROM (
            SELECT DISTINCT GROUP_ID
            FROM R_85K_2(:I$OBJ_ID, :I$N)
            WHERE :I$N2 = 6
              OR (:I$N2 = 7 AND GROUP_ID_STAGE3 IS NOT NULL)
        ) ORDER BY NAME
        INTO :NAME
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_85K_22 (
    I$OBJ_ID BIGINT NOT NULL,
    I$N SMALLINT NOT NULL)
RETURNS (
    V03 INTEGER,
    V04 INTEGER,
    V05 INTEGER,
    V06 INTEGER,
    V07 INTEGER,
    V08 INTEGER,
    V09 INTEGER,
    V10 INTEGER,
    V11 INTEGER)
AS
DECLARE VARIABLE V$INVALID_ONLY SMALLINT;
BEGIN
    V$INVALID_ONLY = IIF(:I$N < 3, 0, 1);
    SELECT IIF(:I$N IN (1, 3), V3, V4) FROM OSH1_501(:I$OBJ_ID, 0, 0, :V$INVALID_ONLY) INTO :V04;
    SELECT IIF(:I$N IN (1, 3), V3, V4) FROM OSH1_501(:I$OBJ_ID, 1, 0, :V$INVALID_ONLY) INTO :V05;
    SELECT IIF(:I$N IN (1, 3), V3, V4) FROM OSH1_501(:I$OBJ_ID, 2, 0, :V$INVALID_ONLY) INTO :V06;
    SELECT IIF(:I$N IN (1, 3), V3, V4) FROM OSH1_501(:I$OBJ_ID, 3, 0, :V$INVALID_ONLY) INTO :V07;
    SELECT IIF(:I$N IN (1, 3), V3, V4) FROM OSH1_501(:I$OBJ_ID, 4, 0, :V$INVALID_ONLY) INTO :V08;
    SELECT IIF(:I$N IN (1, 3), V3, V4) FROM OSH1_501(:I$OBJ_ID, 5, 0, :V$INVALID_ONLY) INTO :V09;
    SELECT IIF(:I$N IN (1, 3), V3, V4) FROM OSH1_501(:I$OBJ_ID, 6, 0, :V$INVALID_ONLY) INTO :V10;
    SELECT IIF(:I$N IN (1, 3), V3, V4) FROM OSH1_501(:I$OBJ_ID, 7, 0, :V$INVALID_ONLY) INTO :V11;
    SELECT :V11+IIF(:I$N IN (1, 3), V3, V4) FROM OSH1_501(:I$OBJ_ID, 8, 0, :V$INVALID_ONLY) INTO :V11;
    V03 = COALESCE(:V04 + :V05 + :V06 + :V07, 0) + :V08 + :V09 + :V10 + :V11;
    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_85K_22DTL (
    I$OBJ_ID BIGINT NOT NULL,
    I$N SMALLINT NOT NULL,
    I$N2 SMALLINT NOT NULL)
RETURNS (
    VAL1 VARCHAR(250),
    VAL2 VARCHAR(250))
AS
DECLARE VARIABLE V$INVALID_ONLY SMALLINT;
BEGIN
    V$INVALID_ONLY = IIF(:I$N IN (3, 4), 1, 0);
    I$N = IIF(:I$N IN (2, 4), 6, 5);
    I$N2 = :I$N2 - 9;
    -- <= 7 YEARS OLD
    IF (:I$N2 <= 2) THEN
    FOR
        SELECT VAL1, VAL2
        FROM OSH1_501DTL(:I$OBJ_ID, :I$N2, :I$N, CURRENT_DATE, 0, :V$INVALID_ONLY)
        INTO :VAL1, :VAL2
    DO
    BEGIN
        SUSPEND;
    END
    -- AND 8 YEARS OLD
    IF (:I$N2 = 2) THEN
    FOR
        SELECT VAL1, VAL2
        FROM OSH1_501DTL(:I$OBJ_ID, 3, :I$N, CURRENT_DATE, 0, :V$INVALID_ONLY)
        INTO :VAL1, :VAL2
    DO
    BEGIN
        SUSPEND;
    END
    -- 01.09.YYYY
    IF (:I$N2 > 2) THEN
    FOR
        SELECT VAL1, VAL2
        FROM OSH1_501DTL(:I$OBJ_ID, :I$N2 - 3, :I$N, CURRENT_DATE, 9, :V$INVALID_ONLY)
        INTO :VAL1, :VAL2
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_85K_3 (
    I$OBJ_ID BIGINT NOT NULL,
    I$N SMALLINT NOT NULL)
RETURNS (
    TEACHER_ID BIGINT,
    V03 SMALLINT,
    V04 SMALLINT,
    V05 SMALLINT,
    V06 SMALLINT,
    V07 SMALLINT,
    V08 SMALLINT,
    V09 SMALLINT)
AS
BEGIN
    FOR
        SELECT
            TEACHER_ID,
            IIF(I > 0 AND J > 0 AND I = J, 0, 1) X03,
            IIF(I > 0 AND J > 0 AND I = J, 0, IIF(LIST278 IN (620, 3031, 3032), 1, 0)) X04,
            IIF(I > 0 AND J > 0 AND I = J, 0, IIF(LIST278 IN (620, 3031, 3032), (
                SELECT FIRST 1 1
                FROM LINKS L33
                INNER JOIN VALL V284 ON V284.OBJ_ID = L33.OBJ_ID
                INNER JOIN VALL V293 ON V293.OBJ_ID = L33.OBJ_ID
                WHERE L33.PARENT_ID = TEACHER_ID
                  AND L33.OBJ_TYPE_ID = 33
                  AND L33.DATE_DEL IS NULL
                  AND V284.PARAM_ID = 284
                  AND V284.IS_DEL = 0
                  AND V284.LISTVAL_ID = 620
                  AND V293.PARAM_ID = 293
                  AND V293.LISTVAL_ID = 647
                  AND V293.IS_DEL = 0),0)) X05,
            IIF(I > 0 AND J > 0 AND I = J, 0, IIF(LIST278 = 622, 1, 0)) X06,
            IIF(I > 0 AND J > 0 AND I = J, 0, IIF(LIST278 = 622, (
                SELECT FIRST 1 1
                FROM LINKS L33
                INNER JOIN VALL V284 ON V284.OBJ_ID = L33.OBJ_ID
                INNER JOIN VALL V293 ON V293.OBJ_ID = L33.OBJ_ID
                WHERE L33.PARENT_ID = TEACHER_ID
                  AND L33.OBJ_TYPE_ID = 33
                  AND L33.DATE_DEL IS NULL
                  AND V284.PARAM_ID = 284
                  AND V284.IS_DEL = 0
                  AND V284.LISTVAL_ID = 622
                  AND V293.PARAM_ID = 293 AND V293.LISTVAL_ID = 647
                  AND V293.IS_DEL = 0),0)) X07,
            IIF(I > 0 AND J > 0 AND I = J, 0, SEX) X08,
            IIF(I > 0 AND J > 0 AND I = J, 1, 0) X09
        FROM (
            SELECT
                V63.LISTVAL_ID V63LISTVAL_ID,
                V64.LISTVAL_ID V64LISTVAL_ID,
                V58.LISTVAL_ID V58LISTVAL_ID,
                (SELECT SORT_ORDER FROM DO_FUNC(V69.VAL, 400)) V400LISTVAL_ID,
                L14.OBJ_ID TEACHER_ID,
                COALESCE((
                    SELECT FIRST 1 1 FROM VALL V
                    WHERE V.PARAM_ID = 239
                      AND V.OBJ_ID = L14.OBJ_ID
                      AND V.IS_DEL = 0
                      AND V.LISTVAL_ID = 182),0) SEX,
               (SELECT V.LISTVAL_ID
                    FROM VALL V
                    WHERE V.PARAM_ID = 278
                      AND V.OBJ_ID = L14.OBJ_ID
                      AND V.IS_DEL = 0) LIST278
            FROM LINKS L2
            INNER JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID
            INNER JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID
            INNER JOIN VALL V10 ON V10.OBJ_ID = L2.OBJ_ID
            INNER JOIN VALL V72 ON V72.OBJ_ID = L15.OBJ_ID
            INNER JOIN VALR V69 ON V69.OBJ_ID = L15.OBJ_ID
            INNER JOIN VALL V63 ON V63.OBJ_ID = V69.VAL
            INNER JOIN VALL V64 ON V64.OBJ_ID = V69.VAL
            INNER JOIN VALL V58 ON V58.OBJ_ID = V69.VAL
            LEFT JOIN VALD V74 ON V74.PARAM_ID = 74 AND V74.OBJ_ID = L15.OBJ_ID AND V74.IS_DEL = 0
            LEFT JOIN VALL V274 ON V274.PARAM_ID = 274 AND V274.OBJ_ID = L14.OBJ_ID AND V274.IS_DEL = 0
            WHERE L2.DATE_DEL IS NULL
              AND L2.OBJ_TYPE_ID = 2
              AND L14.PARENT_ID = :I$OBJ_ID
              AND L14.OBJ_TYPE_ID = 14
              AND L14.DATE_DEL IS NULL
              AND L15.OBJ_TYPE_ID = 15
              AND L15.DATE_DEL IS NULL
              AND V72.PARAM_ID = 72
              AND V72.IS_DEL = 0
              AND V72.LISTVAL_ID = 934
              AND V69.PARAM_ID = 69
              AND V69.IS_DEL = 0
              AND V63.PARAM_ID = 63
              AND V63.IS_DEL = 0
              AND V64.PARAM_ID = 64
              AND V64.IS_DEL = 0
              AND V58.PARAM_ID = 58
              AND V58.IS_DEL = 0
              AND V74.VAL IS NULL
              AND V10.PARAM_ID = 10
              AND V10.IS_DEL = 0
              AND V274.LISTVAL_ID IN (602, 604)
            ) V,
           (SELECT
                SUM(V71.VAL) Y,
                COUNT(1) I,
                SUM(IIF(V587.IS_DEL IS NULL, 0, 1)) J,
                L15.PARENT_ID PARENT_ID
                FROM LINKS L15
                LEFT JOIN VALF V71 ON V71.OBJ_ID = L15.OBJ_ID AND V71.PARAM_ID = 71 AND V71.IS_DEL = 0
                LEFT JOIN VALD V74 ON V74.PARAM_ID = 74 AND V74.OBJ_ID = L15.OBJ_ID AND V74.IS_DEL = 0
                LEFT JOIN VALL V587 ON V587.OBJ_ID = L15.OBJ_ID AND V587.PARAM_ID = 587 AND V587.IS_DEL = 0 AND V587.LISTVAL_ID = 208
                WHERE L15.OBJ_TYPE_ID = 15
                  AND L15.DATE_DEL IS NULL
                  AND V74.VAL IS NULL
                GROUP BY L15.PARENT_ID
            ) V7
        WHERE V.TEACHER_ID = V7.PARENT_ID
          AND ((:I$N = 1)
            -- FOR R_85K_32(3), SUM 2 AND 4
            OR (:I$N= -1 AND ((V63LISTVAL_ID = 55 AND V58LISTVAL_ID NOT IN (96,127)) OR V400LISTVAL_ID = 2))
            OR (:I$N = 2 AND V63LISTVAL_ID = 55 AND V58LISTVAL_ID NOT IN (96,127))
            OR (:I$N = 3 AND V63LISTVAL_ID = 55 AND V64LISTVAL_ID IN (56,113) AND V58LISTVAL_ID NOT IN (69,96,127))
            OR (:I$N = 4 AND V400LISTVAL_ID = 2)
            OR (:I$N = 5 AND V400LISTVAL_ID = 2 AND V58LISTVAL_ID = 128)
            OR (:I$N = 6 AND V400LISTVAL_ID = 2 AND V58LISTVAL_ID = 127)
            OR (:I$N = 7 AND V400LISTVAL_ID = 2 AND V58LISTVAL_ID = 140)
            OR (:I$N = 8 AND V400LISTVAL_ID = 2 AND V58LISTVAL_ID = 150)
            OR (:I$N = 9 AND V400LISTVAL_ID = 2 AND V58LISTVAL_ID = 119)
            OR (:I$N = 10 AND V400LISTVAL_ID = 2 AND V58LISTVAL_ID = 120)
            OR (:I$N = 11 AND V400LISTVAL_ID = 2 AND V58LISTVAL_ID = 145)
            OR (:I$N = 12 AND V400LISTVAL_ID = 2 AND V58LISTVAL_ID = 1251)
            OR (:I$N = 13 AND V400LISTVAL_ID = 2 AND V58LISTVAL_ID = 144)
            OR (:I$N = 14 AND V400LISTVAL_ID = 2 AND V58LISTVAL_ID = 143)
            OR (:I$N = 15 AND V400LISTVAL_ID = 2 AND
                V58LISTVAL_ID NOT IN (128,127,140,150,119,120,145,1251,144,143,96))
            OR (:I$N = 16 AND V400LISTVAL_ID <> 2 AND V58LISTVAL_ID = 3035)
            OR (:I$N = 17 AND V400LISTVAL_ID <> 2 AND V58LISTVAL_ID = 1335)
            OR (:I$N = 18 AND V58LISTVAL_ID IN (1267,1284,1298))
            OR (:I$N = 19 AND V58LISTVAL_ID = 1267)
            OR (:I$N = 20 AND V58LISTVAL_ID IN (1284,1298))
            OR (:I$N = 21 AND ((V63LISTVAL_ID <> 55 AND V400LISTVAL_ID <> 2 AND
                V58LISTVAL_ID NOT IN (3035,1335,1267,1284,1298)) OR V58LISTVAL_ID = 96))
            OR (:I$N = 22 AND V58LISTVAL_ID = 96)
            OR (:I$N = 23 AND V63LISTVAL_ID <> 55 AND V400LISTVAL_ID <> 2 AND V58LISTVAL_ID = 1334)
            OR (:I$N = 24 AND V63LISTVAL_ID <> 55 AND V400LISTVAL_ID <> 2 AND
                V58LISTVAL_ID NOT IN (96,1334,3035,1335,1267,1284,1298)))
        INTO :TEACHER_ID, :V03, :V04, :V05, :V06, :V07, :V08, :V09
    DO
    BEGIN
        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_85K_31 (
    I$OBJ_ID BIGINT NOT NULL,
    I$N SMALLINT NOT NULL)
RETURNS (
    V03 INTEGER,
    V04 VARCHAR(10),
    V05 VARCHAR(10),
    V06 VARCHAR(10),
    V07 VARCHAR(10),
    V08 INTEGER,
    V09 VARCHAR(10))
AS
BEGIN
    IF (I$N = 25) THEN
    BEGIN
        V04 = 'X'; V05 = 'X'; V06 = 'X'; V07 = 'X';
        SUSPEND;
        EXIT;
    END
    SELECT SUM(V03), SUM(V04), SUM(V05), SUM(V06), SUM(V07), SUM(V08), SUM(V09)
    FROM R_85K_3(:I$OBJ_ID, :I$N)
    INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09;
    V03 = COALESCE(:V03, 0); V04 = COALESCE(:V04, 0);
    V05 = COALESCE(:V05, 0); V06 = COALESCE(:V06, 0);
    V07 = COALESCE(:V07, 0); V08 = COALESCE(:V08, 0);
    V09 = COALESCE(:V09, 0);
    IF (:I$N = 1 OR :I$N > 15) THEN
    BEGIN
        V04 = 'X'; V05 = 'X'; V06 = 'X'; V07 = 'X';
    END
    IF (:I$N IN (2, 3)) THEN
    BEGIN
        V09 = 'X';
    END
    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_85K_31DTL (
    I$OBJ_ID BIGINT NOT NULL,
    I$N SMALLINT NOT NULL,
    I$N2 SMALLINT NOT NULL)
RETURNS (
    VAL1 VARCHAR(250))
AS
BEGIN
    FOR
        SELECT
            (SELECT CAPTION FROM OBJECT_CAPTION_GET(TEACHER_ID)) VAL1
        FROM R_85K_3(:I$OBJ_ID, :I$N)
        WHERE (:I$N2 = 3 AND V03 = 1)
           OR (:I$N2 = 4 AND V04 = 1)
           OR (:I$N2 = 5 AND V05 = 1)
           OR (:I$N2 = 6 AND V06 = 1)
           OR (:I$N2 = 7 AND V07 = 1)
           OR (:I$N2 = 8 AND V08 = 1)
           OR (:I$N2 = 9 AND V09 = 1)
        ORDER BY VAL1
        INTO :VAL1
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_85K_32 (
    I$OBJ_ID BIGINT NOT NULL,
    I$N SMALLINT NOT NULL)
RETURNS (
    V03 INTEGER,
    V04 INTEGER,
    V05 INTEGER,
    V06 INTEGER,
    V07 INTEGER,
    V08 INTEGER,
    V09 INTEGER,
    V10 INTEGER,
    V11 INTEGER)
AS
DECLARE VARIABLE Y INTEGER;
BEGIN
    IF (:I$N = 1) THEN I$N = -1;
    SELECT Y2 FROM CURRENT_SCHOOL_YEAR_GET INTO :Y;
    SELECT
        COUNT(1),
        COALESCE(SUM(IIF(VAL241 < 25, 1, 0)), 0) V04,
        COALESCE(SUM(IIF(VAL241 BETWEEN 25 AND 29, 1, 0)), 0) V05,
        COALESCE(SUM(IIF(VAL241 BETWEEN 30 AND 39, 1, 0)), 0) V06,
        COALESCE(SUM(IIF(VAL241 BETWEEN 40 AND 44, 1, 0)), 0) V07,
        COALESCE(SUM(IIF(VAL241 BETWEEN 45 AND 49, 1, 0)), 0) V08,
        COALESCE(SUM(IIF(VAL241 BETWEEN 50 AND 54, 1, 0)), 0) V09,
        COALESCE(SUM(IIF(VAL241 BETWEEN 55 AND 59, 1, 0)), 0) V10,
        COALESCE(SUM(IIF(VAL241 > 59, 1, 0)), 0) V11
    FROM (
        SELECT COALESCE((
            SELECT :Y - EXTRACT(YEAR FROM V.VAL) -
                IIF(EXTRACT(MONTH FROM V.VAL) = 1 AND EXTRACT(DAY FROM V.VAL) = 1, 0, 1)
            FROM VALD V
            WHERE V.PARAM_ID = 241
              AND V.OBJ_ID = TEACHER_ID
              AND V.IS_DEL = 0), 0) VAL241
        FROM R_85K_3(:I$OBJ_ID, :I$N)
        WHERE V03 > 0
    ) INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11;
    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_85K_32DTL (
    I$OBJ_ID BIGINT NOT NULL,
    I$N SMALLINT NOT NULL,
    I$N2 SMALLINT NOT NULL)
RETURNS (
    VAL1 VARCHAR(250),
    VAL2 VARCHAR(250))
AS
DECLARE VARIABLE Y INTEGER;
BEGIN
    IF (:I$N = 1) THEN I$N = -1;
    SELECT Y2 FROM CURRENT_SCHOOL_YEAR_GET INTO :Y;
    FOR
        SELECT
            (SELECT CAPTION FROM OBJECT_CAPTION_GET(TEACHER_ID)) VAL1,
            (SELECT D FROM VAL_GET(TEACHER_ID, 241)) VAL2
        FROM (
            SELECT TEACHER_ID, COALESCE((
                SELECT :Y - EXTRACT(YEAR FROM V.VAL) -
                    IIF(EXTRACT(MONTH FROM V.VAL) = 1 AND EXTRACT(DAY FROM V.VAL) = 1, 0, 1)
                FROM VALD V
                WHERE V.PARAM_ID = 241
                  AND V.OBJ_ID = TEACHER_ID
                  AND V.IS_DEL = 0), 0) VAL241
            FROM R_85K_3(:I$OBJ_ID, :I$N)
            WHERE V03 > 0)
        WHERE :I$N2 = 3
          OR (:I$N2 = 4 AND VAL241 < 25)
          OR (:I$N2 = 5 AND VAL241 BETWEEN 25 AND 29)
          OR (:I$N2 = 6 AND VAL241 BETWEEN 30 AND 39)
          OR (:I$N2 = 7 AND VAL241 BETWEEN 40 AND 44)
          OR (:I$N2 = 8 AND VAL241 BETWEEN 45 AND 49)
          OR (:I$N2 = 9 AND VAL241 BETWEEN 50 AND 54)
          OR (:I$N2 =10 AND VAL241 BETWEEN 55 AND 59)
          OR (:I$N2 =11 AND VAL241 > 59)
        ORDER BY VAL1
        INTO :VAL1, :VAL2
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_85K_33 (
    I$OBJ_ID BIGINT NOT NULL,
    I$N SMALLINT NOT NULL)
RETURNS (
    V03 INTEGER,
    V04 INTEGER,
    V05 INTEGER,
    V06 INTEGER,
    V07 INTEGER,
    V08 INTEGER,
    V09 INTEGER,
    V10 INTEGER,
    V11 INTEGER,
    V12 INTEGER,
    V13 INTEGER,
    V14 INTEGER,
    V15 INTEGER,
    V16 INTEGER)
AS
DECLARE VARIABLE Y INTEGER;
DECLARE VARIABLE D DATE;
BEGIN
    IF (:I$N = 1) THEN I$N = -1;
    ELSE I$N = :I$N + 1;
    SELECT Y2 FROM CURRENT_SCHOOL_YEAR_GET INTO :Y;
    D = :Y || '-01-01';
    SELECT
        COUNT(1),
        COALESCE(SUM(IIF(DAYS360_COUNT < 3*360, 1, 0)), 0) V04,
        COALESCE(SUM(IIF(DAYS360_COUNT BETWEEN 3*360 AND 5*360-1, 1, 0)), 0) V05,
        COALESCE(SUM(IIF(DAYS360_COUNT BETWEEN 5*360 AND 10*360-1, 1, 0)), 0) V06,
        COALESCE(SUM(IIF(DAYS360_COUNT BETWEEN 10*360 AND 15*360-1, 1, 0)), 0) V07,
        COALESCE(SUM(IIF(DAYS360_COUNT BETWEEN 15*360 AND 20*360-1, 1, 0)), 0) V08,
        COALESCE(SUM(IIF(DAYS360_COUNT > 20*360, 1, 0)), 0) V09,
        COALESCE(SUM(IIF(DAYS360_PED > 0, 1, 0)), 0) V10,
        COALESCE(SUM(IIF(DAYS360_PED > 0 AND DAYS360_PED < 3*360, 1, 0)), 0) V11,
        COALESCE(SUM(IIF(DAYS360_PED BETWEEN 3*360 AND 5*360-1, 1, 0)), 0) V12,
        COALESCE(SUM(IIF(DAYS360_PED BETWEEN 5*360 AND 10*360-1, 1, 0)), 0) V13,
        COALESCE(SUM(IIF(DAYS360_PED BETWEEN 10*360 AND 15*360-1, 1, 0)), 0) V14,
        COALESCE(SUM(IIF(DAYS360_PED BETWEEN 15*360 AND 20*360-1, 1, 0)), 0) V15,
        COALESCE(SUM(IIF(DAYS360_PED > 20*360, 1, 0)), 0) V16
    FROM (
        SELECT
            COALESCE((SELECT SUM(
                         (SELECT DAYS360_COUNT
                          FROM GET_DAYS360_COUNT(
                             (SELECT VAL FROM VALD
                              WHERE PARAM_ID = 466
                                AND OBJ_ID = L85.OBJ_ID
                                AND IS_DEL = 0),
                             COALESCE((SELECT VAL FROM VALD
                              WHERE PARAM_ID = 467
                                AND OBJ_ID = L85.OBJ_ID
                                AND IS_DEL = 0), :D))))
                      FROM LINKS L85
                      LEFT JOIN VALL V465 ON V465.OBJ_ID = L85.OBJ_ID
                        AND V465.PARAM_ID = 465 AND V465.IS_DEL = 0
                      WHERE L85.OBJ_TYPE_ID = 85
                        AND L85.DATE_DEL IS NULL
                        AND V465.LISTVAL_ID = 941
                        AND L85.PARENT_ID = TEACHER_ID), 0) DAYS360_COUNT,
            COALESCE((SELECT SUM(
                         (SELECT DAYS360_COUNT
                          FROM GET_DAYS360_COUNT(
                             (SELECT VAL FROM VALD
                              WHERE PARAM_ID = 466
                                AND OBJ_ID = L85.OBJ_ID
                                AND IS_DEL = 0),
                              COALESCE((SELECT VAL FROM VALD
                              WHERE PARAM_ID = 467
                                AND OBJ_ID = L85.OBJ_ID
                                AND IS_DEL = 0), :D))))
                      FROM LINKS L85
                      LEFT JOIN VALL V465 ON V465.OBJ_ID = L85.OBJ_ID
                        AND V465.PARAM_ID = 465 AND V465.IS_DEL = 0
                      WHERE L85.OBJ_TYPE_ID = 85
                        AND L85.DATE_DEL IS NULL
                        AND V465.LISTVAL_ID = 942
                        AND L85.PARENT_ID = TEACHER_ID), 0) DAYS360_PED
        FROM R_85K_3(:I$OBJ_ID, :I$N)
        WHERE V03 > 0
    ) INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09,
           :V10, :V11, :V12, :V13, :V14, :V15, :V16;
    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_85K_33DTL (
    I$OBJ_ID BIGINT NOT NULL,
    I$N SMALLINT NOT NULL,
    I$N2 SMALLINT NOT NULL)
RETURNS (
    VAL1 VARCHAR(250))
AS
DECLARE VARIABLE Y INTEGER;
DECLARE VARIABLE D DATE;
BEGIN
    IF (:I$N = 1) THEN I$N = -1;
    ELSE I$N = :I$N + 1;
    SELECT Y2 FROM CURRENT_SCHOOL_YEAR_GET INTO :Y;
    D = :Y || '-01-01';
    FOR
        SELECT
            (SELECT CAPTION FROM OBJECT_CAPTION_GET(TEACHER_ID)) VAL1
        FROM (
            SELECT
                TEACHER_ID,
                COALESCE((SELECT SUM(
                             (SELECT DAYS360_COUNT
                              FROM GET_DAYS360_COUNT(
                                 (SELECT VAL FROM VALD
                                  WHERE PARAM_ID = 466
                                    AND OBJ_ID = L85.OBJ_ID
                                    AND IS_DEL = 0),
                                 COALESCE((SELECT VAL FROM VALD
                                  WHERE PARAM_ID = 467
                                    AND OBJ_ID = L85.OBJ_ID
                                    AND IS_DEL = 0), :D))))
                          FROM LINKS L85
                          LEFT JOIN VALL V465 ON V465.OBJ_ID = L85.OBJ_ID
                            AND V465.PARAM_ID = 465 AND V465.IS_DEL = 0
                          WHERE L85.OBJ_TYPE_ID = 85
                            AND L85.DATE_DEL IS NULL
                            AND V465.LISTVAL_ID = IIF(:I$N2 < 10, 941, 942)
                            AND L85.PARENT_ID = TEACHER_ID), 0) DAYS360_COUNT
        FROM R_85K_3(:I$OBJ_ID, :I$N)
        WHERE V03 > 0)
        WHERE :I$N2 = 3
          OR (:I$N2 = 4 AND DAYS360_COUNT < 3*360)
          OR (:I$N2 = 5 AND DAYS360_COUNT BETWEEN 3*360 AND 5*360-1)
          OR (:I$N2 = 6 AND DAYS360_COUNT BETWEEN 5*360 AND 10*360-1)
          OR (:I$N2 = 7 AND DAYS360_COUNT BETWEEN 10*360 AND 15*360-1)
          OR (:I$N2 = 8 AND DAYS360_COUNT BETWEEN 15*360 AND 20*360-1)
          OR (:I$N2 = 9 AND DAYS360_COUNT > 20*360)
          OR (:I$N2 =10 AND DAYS360_COUNT > 0)
          OR (:I$N2 =11 AND DAYS360_COUNT > 0 AND DAYS360_COUNT < 3*360)
          OR (:I$N2 =12 AND DAYS360_COUNT BETWEEN 3*360 AND 5*360-1)
          OR (:I$N2 =13 AND DAYS360_COUNT BETWEEN 5*360 AND 10*360-1)
          OR (:I$N2 =14 AND DAYS360_COUNT BETWEEN 10*360 AND 15*360-1)
          OR (:I$N2 =15 AND DAYS360_COUNT BETWEEN 15*360 AND 20*360-1)
          OR (:I$N2 =16 AND DAYS360_COUNT > 20*360)
        ORDER BY VAL1
        INTO :VAL1
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_85K_41 (
    I$OBJ_ID BIGINT NOT NULL,
    I$N SMALLINT NOT NULL)
RETURNS (
    V03 DOUBLE PRECISION,
    V04 DOUBLE PRECISION,
    V05 DOUBLE PRECISION,
    V06 DOUBLE PRECISION,
    V07 DOUBLE PRECISION)
AS
DECLARE VARIABLE V$BUILDING_ID BIGINT;
DECLARE VARIABLE V$BUILDING_OWNERSHIP_ID BIGINT;
DECLARE VARIABLE V$S DOUBLE PRECISION;
DECLARE VARIABLE V$P_525 BIGINT;
DECLARE VARIABLE V$P_526 BIGINT;
DECLARE VARIABLE V$P_526_PARENT_ID BIGINT;
DECLARE VARIABLE V$PLACE_CNT INTEGER;
BEGIN
    IF (:I$N IN (5, 10) OR (
        SELECT FIRST 1 V03 FROM R_85K_11(:I$OBJ_ID, 1)) IS NULL) THEN
    BEGIN
        SUSPEND;
        EXIT;
    END

    V03 = 0;
    FOR SELECT L16.OBJ_ID,
               V504.LISTVAL_ID
        FROM LINKS L73
        JOIN LINKS L16 ON L16.PARENT_ID = L73.OBJ_ID
          AND L16.OBJ_TYPE_ID = 16
          AND L16.DATE_DEL IS NULL
        LEFT JOIN VALL V504 ON V504.OBJ_ID = L16.OBJ_ID
          AND V504.PARAM_ID = 504
          AND V504.IS_DEL = 0
        WHERE L73.PARENT_ID = :I$OBJ_ID
          AND L73.OBJ_TYPE_ID = 73
          AND L73.DATE_DEL IS NULL
        INTO :V$BUILDING_ID,
             :V$BUILDING_OWNERSHIP_ID
    DO
    BEGIN
        V$S = 0;

        IF (:I$N = 1) THEN
        BEGIN
            SELECT VAL
            FROM VALF
            WHERE PARAM_ID = 496
              AND OBJ_ID = :V$BUILDING_ID
              AND IS_DEL = 0
            INTO :V$S;
            V03 = :V03 + :V$S;
            V04 = COALESCE(:V04, 0) + IIF(:V$BUILDING_OWNERSHIP_ID = 1112, :V$S, 0);
            V05 = COALESCE(:V05, 0) + IIF(:V$BUILDING_OWNERSHIP_ID = 1113, :V$S, 0);
            V06 = COALESCE(:V06, 0) + IIF(:V$BUILDING_OWNERSHIP_ID = 1114, :V$S, 0);
            V07 = COALESCE(:V07, 0) + IIF(:V$BUILDING_OWNERSHIP_ID NOT IN (1112, 1113, 1114), :V$S, 0);
        END
        ELSE
        BEGIN
            FOR SELECT V533.VAL,
                       V532.VAL,
                       V525.LISTVAL_ID,
                       V526.LISTVAL_ID,
                       LV526.PARENT_ID
                FROM LINKS L61
                JOIN VALL V525 ON V525.OBJ_ID = L61.OBJ_ID
                  AND V525.PARAM_ID = 525
                  AND V525.IS_DEL = 0
                  AND V525.LISTVAL_ID NOT IN (1189, 1195)
                JOIN VALL V526 ON V526.OBJ_ID = L61.OBJ_ID
                  AND V526.PARAM_ID = 526
                  AND V526.IS_DEL = 0
                JOIN LISTVALS LV526 ON LV526.LISTVAL_ID = V526.LISTVAL_ID
                LEFT JOIN VALF V533 ON V533.OBJ_ID = L61.OBJ_ID
                  AND V533.PARAM_ID = 533
                  AND V533.IS_DEL = 0
                LEFT JOIN VALI V532 ON V532.OBJ_ID = L61.OBJ_ID
                  AND V532.PARAM_ID = 532
                  AND V532.IS_DEL = 0
                WHERE L61.PARENT_ID = :V$BUILDING_ID
                  AND L61.OBJ_TYPE_ID = 61
                  AND L61.DATE_DEL IS NULL
                  AND (V533.VAL IS NOT NULL OR :I$N > 5)
                  AND (V532.VAL IS NOT NULL OR :I$N <> 6)
                INTO :V$S,
                     :V$PLACE_CNT,
                     :V$P_525,
                     :V$P_526,
                     :V$P_526_PARENT_ID
            DO
            BEGIN
                IF (:I$N = 2) THEN
                BEGIN
                    V03 = :V03 + :V$S;
                    V04 = COALESCE(:V04, 0) + IIF(:V$BUILDING_OWNERSHIP_ID = 1112, :V$S, 0);
                    V05 = COALESCE(:V05, 0) + IIF(:V$BUILDING_OWNERSHIP_ID = 1113, :V$S, 0);
                    V06 = COALESCE(:V06, 0) + IIF(:V$BUILDING_OWNERSHIP_ID = 1114, :V$S, 0);
                    V07 = COALESCE(:V07, 0) + IIF(:V$BUILDING_OWNERSHIP_ID NOT IN (1112, 1113, 1114), :V$S, 0);
                END
                IF (:I$N = 3 AND (:V$P_526_PARENT_ID = 10956 OR :V$P_526 IN (1175, 10959))) THEN
                BEGIN
                    V03 = :V03 + :V$S;
                END
                IF (:I$N = 4 AND :V$P_526_PARENT_ID NOT IN (10956, 1134, 1150) AND
                    :V$P_526 NOT IN (1175, 10959, 1141, 1144, 1170, 1156) AND :V$P_525 IN (23, 1149)) THEN
                BEGIN
                    V03 = :V03 + :V$S;
                END
                IF (:I$N = 6 AND :V$P_526 = 3290) THEN
                BEGIN
                    V03 = :V03 + :V$PLACE_CNT;
                END
                IF (:I$N = 7 AND :V$P_526 IN (3287, 3288)) THEN
                BEGIN
                    V03 = 1;
                END
                IF (:I$N = 8 AND :V$P_526 IN (1129, 1130, 1131, 3288)) THEN
                BEGIN
                    V03 = 1;
                END
                IF (:I$N = 9 AND :V$P_526 IN (1132)) THEN
                BEGIN
                    V03 = 1;
                END
            END
        END
    END

    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_85K_DISTR_11 (
    I$OBJ_ID BIGINT NOT NULL,
    I$NUM SMALLINT NOT NULL)
RETURNS (
    V03 VARCHAR(250))
AS
BEGIN
    SELECT LIST(VAL||' - '||CNT, ';  ')
    FROM (
        SELECT
            DISTINCT(VAL) VAL,
            COUNT(1) CNT
        FROM (
            SELECT (SELECT V03 FROM R_85K_11(L2.OBJ_ID, :I$NUM)) VAL
            FROM LINKS L2
            WHERE L2.PARENT_ID = :I$OBJ_ID
              AND L2.OBJ_TYPE_ID = 2
              AND L2.DATE_DEL IS NULL)
        WHERE VAL IS NOT NULL
        GROUP BY VAL)
    INTO :V03;

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_85K_DISTR_12 (
    I$OBJ_ID BIGINT NOT NULL,
    I$NUM SMALLINT NOT NULL)
RETURNS (
    V03 VARCHAR(250))
AS
BEGIN
    SELECT LIST(VAL||' - '||CNT, ';  ')
    FROM (
        SELECT
            DISTINCT(VAL) VAL,
            COUNT(1) CNT
        FROM (
            SELECT (SELECT V03 FROM R_85K_12(L2.OBJ_ID, :I$NUM)) VAL
            FROM LINKS L2
            WHERE L2.PARENT_ID = :I$OBJ_ID
              AND L2.OBJ_TYPE_ID = 2
              AND L2.DATE_DEL IS NULL)
        WHERE VAL IS NOT NULL
        GROUP BY VAL)
    INTO :V03;

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_85K_DISTR_21 (
    I$OBJ_ID BIGINT NOT NULL,
    I$N SMALLINT NOT NULL)
RETURNS (
    V03 INTEGER,
    V04 VARCHAR(10),
    V05 VARCHAR(10),
    V06 INTEGER,
    V07 VARCHAR(10))
AS
DECLARE VARIABLE V$OBJ_ID BIGINT;
BEGIN
    IF (:I$N = 18) THEN
    BEGIN
        SUSPEND;
        EXIT;
    END
    V03 = 0;
    V04 = 0;
    V05 = NULL;
    V06 = 0;
    V07 = 0;

    FOR SELECT L2.OBJ_ID
        FROM LINKS L2
        WHERE L2.PARENT_ID = :I$OBJ_ID
          AND L2.OBJ_TYPE_ID = 2
          AND L2.DATE_DEL IS NULL
        INTO :V$OBJ_ID
    DO
    BEGIN
        SELECT
            V03 + :V03,
            IIF(V04 = 'Х', V04, CAST(V04 AS INT) + CAST(:V04 AS INT)),
            V05,
            V06 + :V06,
            IIF(V07 = 'Х', V07, CAST(V07 AS INT) + CAST(:V07 AS INT))
        FROM R_85K_21(:V$OBJ_ID, :I$N)
        INTO :V03, :V04, :V05, :V06, :V07;
    END

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_85K_DISTR_21DTL (
    I$OBJ_ID BIGINT NOT NULL,
    I$N SMALLINT NOT NULL,
    I$N2 SMALLINT NOT NULL)
RETURNS (
    VAL1 VARCHAR(250),
    VAL2 VARCHAR(250),
    NAME VARCHAR(250),
    VAL3 VARCHAR(250))
AS
DECLARE VARIABLE V$OBJ_ID BIGINT;
BEGIN
    FOR SELECT L2.OBJ_ID,
            (SELECT CAPTION FROM OBJECT_CAPTION_GET(L2.OBJ_ID)) VAL3
        FROM LINKS L2
        WHERE L2.PARENT_ID = :I$OBJ_ID
          AND L2.OBJ_TYPE_ID = 2
          AND L2.DATE_DEL IS NULL
        ORDER BY 2
        INTO :V$OBJ_ID, :VAL3
    DO
    BEGIN
        FOR SELECT VAL1, VAL2, NAME
            FROM R_85K_21DTL(:V$OBJ_ID, :I$N, :I$N2)
            INTO :VAL1, :VAL2, :NAME
        DO
        BEGIN
            SUSPEND;
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_85K_DISTR_22 (
    I$OBJ_ID BIGINT NOT NULL,
    I$N SMALLINT NOT NULL)
RETURNS (
    V03 INTEGER,
    V04 INTEGER,
    V05 INTEGER,
    V06 INTEGER,
    V07 INTEGER,
    V08 INTEGER,
    V09 INTEGER,
    V10 INTEGER,
    V11 INTEGER)
AS
DECLARE VARIABLE V$OBJ_ID BIGINT;
BEGIN
    V03 = 0; V04 = 0; V05 = 0;
    V06 = 0; V07 = 0; V08 = 0;
    V09 = 0; V10 = 0; V11 = 0;

    FOR SELECT L2.OBJ_ID
        FROM LINKS L2
        WHERE L2.PARENT_ID = :I$OBJ_ID
          AND L2.OBJ_TYPE_ID = 2
          AND L2.DATE_DEL IS NULL
        INTO :V$OBJ_ID
    DO
    BEGIN
        SELECT
            V03 + :V03, V04 + :V04, V05 + :V05,
            V06 + :V06, V07 + :V07, V08 + :V08,
            V09 + :V09, V10 + :V10, V11 + :V11
        FROM R_85K_22(:V$OBJ_ID, :I$N)
        INTO :V03, :V04, :V05,
             :V06, :V07, :V08,
             :V09, :V10, :V11;
    END

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_85K_DISTR_22DTL (
    I$OBJ_ID BIGINT NOT NULL,
    I$N SMALLINT NOT NULL,
    I$N2 SMALLINT NOT NULL)
RETURNS (
    VAL1 VARCHAR(250),
    VAL2 VARCHAR(250),
    VAL3 VARCHAR(250))
AS
DECLARE VARIABLE V$OBJ_ID BIGINT;
BEGIN
    FOR SELECT L2.OBJ_ID,
            (SELECT CAPTION FROM OBJECT_CAPTION_GET(L2.OBJ_ID)) VAL3
        FROM LINKS L2
        WHERE L2.PARENT_ID = :I$OBJ_ID
          AND L2.OBJ_TYPE_ID = 2
          AND L2.DATE_DEL IS NULL
        ORDER BY 2
        INTO :V$OBJ_ID, :VAL3
    DO
    BEGIN
        FOR SELECT VAL1, VAL2
            FROM R_85K_22DTL(:V$OBJ_ID, :I$N, :I$N2)
            INTO :VAL1, :VAL2
        DO
        BEGIN
            SUSPEND;
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_85K_DISTR_31 (
    I$OBJ_ID BIGINT NOT NULL,
    I$N SMALLINT NOT NULL)
RETURNS (
    V03 INTEGER,
    V04 VARCHAR(10),
    V05 VARCHAR(10),
    V06 VARCHAR(10),
    V07 VARCHAR(10),
    V08 INTEGER,
    V09 VARCHAR(10))
AS
DECLARE VARIABLE V$OBJ_ID BIGINT;
BEGIN
    V03 = 0;
    V04 = 0;
    V05 = 0;
    V06 = 0;
    V07 = 0;
    V08 = 0;
    V09 = 0;

    FOR SELECT L2.OBJ_ID
        FROM LINKS L2
        WHERE L2.PARENT_ID = :I$OBJ_ID
          AND L2.OBJ_TYPE_ID = 2
          AND L2.DATE_DEL IS NULL
        INTO :V$OBJ_ID
    DO
    BEGIN
        SELECT
            V03 + :V03,
            IIF(V04 = 'X', V04, CAST(V04 AS INT) + CAST(:V04 AS INT)),
            IIF(V05 = 'X', V05, CAST(V05 AS INT) + CAST(:V05 AS INT)),
            IIF(V06 = 'X', V06, CAST(V06 AS INT) + CAST(:V06 AS INT)),
            IIF(V07 = 'X', V07, CAST(V07 AS INT) + CAST(:V07 AS INT)),
            V08 + :V08,
            IIF(V09 = 'X', V09, CAST(V09 AS INT) + CAST(:V09 AS INT))
        FROM R_85K_31(:V$OBJ_ID, :I$N)
        INTO :V03, :V04, :V05, :V06, :V07, :V08, :V09;
    END

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_85K_DISTR_31DTL (
    I$OBJ_ID BIGINT NOT NULL,
    I$N SMALLINT NOT NULL,
    I$N2 SMALLINT NOT NULL)
RETURNS (
    VAL1 VARCHAR(250),
    VAL3 VARCHAR(250))
AS
DECLARE VARIABLE V$OBJ_ID BIGINT;
BEGIN
    FOR SELECT L2.OBJ_ID,
            (SELECT CAPTION FROM OBJECT_CAPTION_GET(L2.OBJ_ID)) VAL3
        FROM LINKS L2
        WHERE L2.PARENT_ID = :I$OBJ_ID
          AND L2.OBJ_TYPE_ID = 2
          AND L2.DATE_DEL IS NULL
        ORDER BY 2
        INTO :V$OBJ_ID, :VAL3
    DO
    BEGIN
        FOR SELECT VAL1
            FROM R_85K_31DTL(:V$OBJ_ID, :I$N, :I$N2)
            INTO :VAL1
        DO
        BEGIN
            SUSPEND;
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_85K_DISTR_32 (
    I$OBJ_ID BIGINT NOT NULL,
    I$N SMALLINT NOT NULL)
RETURNS (
    V03 INTEGER,
    V04 INTEGER,
    V05 INTEGER,
    V06 INTEGER,
    V07 INTEGER,
    V08 INTEGER,
    V09 INTEGER,
    V10 INTEGER,
    V11 INTEGER)
AS
DECLARE VARIABLE V$OBJ_ID BIGINT;
BEGIN
    V03 = 0; V04 = 0; V05 = 0;
    V06 = 0; V07 = 0; V08 = 0;
    V09 = 0; V10 = 0; V11 = 0;

    FOR SELECT L2.OBJ_ID
        FROM LINKS L2
        WHERE L2.PARENT_ID = :I$OBJ_ID
          AND L2.OBJ_TYPE_ID = 2
          AND L2.DATE_DEL IS NULL
        INTO :V$OBJ_ID
    DO
    BEGIN
        SELECT
            V03 + :V03, V04 + :V04, V05 + :V05,
            V06 + :V06, V07 + :V07, V08 + :V08,
            V09 + :V09, V10 + :V10, V11 + :V11
        FROM R_85K_32(:V$OBJ_ID, :I$N)
        INTO :V03, :V04, :V05,
             :V06, :V07, :V08,
             :V09, :V10, :V11;
    END

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_85K_DISTR_32DTL (
    I$OBJ_ID BIGINT NOT NULL,
    I$N SMALLINT NOT NULL,
    I$N2 SMALLINT NOT NULL)
RETURNS (
    VAL1 VARCHAR(250),
    VAL2 VARCHAR(250),
    VAL3 VARCHAR(250))
AS
DECLARE VARIABLE V$OBJ_ID BIGINT;
BEGIN
    FOR SELECT L2.OBJ_ID,
            (SELECT CAPTION FROM OBJECT_CAPTION_GET(L2.OBJ_ID)) VAL3
        FROM LINKS L2
        WHERE L2.PARENT_ID = :I$OBJ_ID
          AND L2.OBJ_TYPE_ID = 2
          AND L2.DATE_DEL IS NULL
        ORDER BY 2
        INTO :V$OBJ_ID, :VAL3
    DO
    BEGIN
        FOR SELECT VAL1, VAL2
            FROM R_85K_32DTL(:V$OBJ_ID, :I$N, :I$N2)
            INTO :VAL1, :VAL2
        DO
        BEGIN
            SUSPEND;
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_85K_DISTR_33 (
    I$OBJ_ID BIGINT NOT NULL,
    I$N SMALLINT NOT NULL)
RETURNS (
    V03 INTEGER,
    V04 INTEGER,
    V05 INTEGER,
    V06 INTEGER,
    V07 INTEGER,
    V08 INTEGER,
    V09 INTEGER,
    V10 INTEGER,
    V11 INTEGER,
    V12 INTEGER,
    V13 INTEGER,
    V14 INTEGER,
    V15 INTEGER,
    V16 INTEGER)
AS
DECLARE VARIABLE V$OBJ_ID BIGINT;
BEGIN
    V03 = 0; V04 = 0; V05 = 0;
    V06 = 0; V07 = 0; V08 = 0;
    V09 = 0; V10 = 0; V11 = 0;
    V12 = 0; V13 = 0; V14 = 0;
    V15 = 0; V16 = 0;

    FOR SELECT L2.OBJ_ID
        FROM LINKS L2
        WHERE L2.PARENT_ID = :I$OBJ_ID
          AND L2.OBJ_TYPE_ID = 2
          AND L2.DATE_DEL IS NULL
        INTO :V$OBJ_ID
    DO
    BEGIN
        SELECT
            V03 + :V03, V04 + :V04, V05 + :V05,
            V06 + :V06, V07 + :V07, V08 + :V08,
            V09 + :V09, V10 + :V10, V11 + :V11,
            V12 + :V12, V13 + :V13, V14 + :V14,
            V15 + :V15, V16 + :V16
        FROM R_85K_33(:V$OBJ_ID, :I$N)
        INTO :V03, :V04, :V05,
             :V06, :V07, :V08,
             :V09, :V10, :V11,
             :V12, :V13, :V14,
             :V15, :V16;
    END

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_85K_DISTR_33DTL (
    I$OBJ_ID BIGINT NOT NULL,
    I$N SMALLINT NOT NULL,
    I$N2 SMALLINT NOT NULL)
RETURNS (
    VAL1 VARCHAR(250),
    VAL3 VARCHAR(250))
AS
DECLARE VARIABLE V$OBJ_ID BIGINT;
BEGIN
    FOR SELECT L2.OBJ_ID,
            (SELECT CAPTION FROM OBJECT_CAPTION_GET(L2.OBJ_ID)) VAL3
        FROM LINKS L2
        WHERE L2.PARENT_ID = :I$OBJ_ID
          AND L2.OBJ_TYPE_ID = 2
          AND L2.DATE_DEL IS NULL
        ORDER BY 2
        INTO :V$OBJ_ID, :VAL3
    DO
    BEGIN
        FOR SELECT VAL1
            FROM R_85K_33DTL(:V$OBJ_ID, :I$N, :I$N2)
            INTO :VAL1
        DO
        BEGIN
            SUSPEND;
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_85K_DISTR_41 (
    I$OBJ_ID BIGINT NOT NULL,
    I$N SMALLINT NOT NULL)
RETURNS (
    V03 DOUBLE PRECISION,
    V04 DOUBLE PRECISION,
    V05 DOUBLE PRECISION,
    V06 DOUBLE PRECISION,
    V07 DOUBLE PRECISION)
AS
DECLARE VARIABLE V$OBJ_ID BIGINT;
BEGIN
    V03 = 0; V04 = 0; V05 = 0;
    V06 = 0; V07 = 0;

    FOR SELECT L2.OBJ_ID
        FROM LINKS L2
        WHERE L2.PARENT_ID = :I$OBJ_ID
          AND L2.OBJ_TYPE_ID = 2
          AND L2.DATE_DEL IS NULL
        INTO :V$OBJ_ID
    DO
    BEGIN
        SELECT
            COALESCE(V03, 0) + :V03, COALESCE(V04, 0) + :V04, COALESCE(V05, 0) + :V05,
            COALESCE(V06, 0) + :V06, COALESCE(V07, 0) + :V07
        FROM R_85K_41(:V$OBJ_ID, :I$N)
        INTO :V03, :V04, :V05,
             :V06, :V07;
    END

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_85K_DISTR_42 (
    I$OBJ_ID BIGINT NOT NULL,
    I$NUM SMALLINT NOT NULL)
RETURNS (
    V03 VARCHAR(250))
AS
BEGIN
    IF (:I$NUM < 7) THEN
    BEGIN
        SELECT LIST(VAL||' - '||CNT, ';  ')
        FROM (
            SELECT
                DISTINCT(VAL) VAL,
                COUNT(1) CNT
            FROM (
                SELECT CASE :I$NUM
                    WHEN 1 THEN (SELECT IIF(X = 0, 0, 1) FROM OSH1_1322(L2.OBJ_ID, 1103))
                    WHEN 2 THEN (SELECT IIF(X = 0, 0, 1) FROM OSH1_1322(L2.OBJ_ID, 1104))
                    WHEN 3 THEN (SELECT IIF(X = 0, 0, 1) FROM OSH1_1326(L2.OBJ_ID))
                    WHEN 4 THEN (SELECT IIF(X = 0, 0, 1) FROM OSH1_1328(L2.OBJ_ID))
                    WHEN 5 THEN (SELECT IIF(X = 0, 0, 1) FROM OSH1_1327(L2.OBJ_ID))
                    WHEN 6 THEN (SELECT IIF(X = 0, 0, 1) FROM OSH1_1329(L2.OBJ_ID))
                END VAL
                FROM LINKS L2
                WHERE L2.PARENT_ID = :I$OBJ_ID
                  AND L2.OBJ_TYPE_ID = 2
                  AND L2.DATE_DEL IS NULL)
            WHERE VAL IS NOT NULL
            GROUP BY VAL)
        INTO :V03;
    END
    ELSE
    BEGIN
        V03 = 0;
        SELECT SUM (CASE :I$NUM
            WHEN 7 THEN (SELECT V FROM OSH1_1301(L2.OBJ_ID, 1))
            WHEN 8 THEN (SELECT X FROM OSH1_1322(L2.OBJ_ID, 1104))
            WHEN 9 THEN (SELECT X FROM OSH1_1322(L2.OBJ_ID, 1103))
        END)
        FROM LINKS L2
        WHERE L2.PARENT_ID = :I$OBJ_ID
          AND L2.OBJ_TYPE_ID = 2
          AND L2.DATE_DEL IS NULL
        INTO :V03;
    END

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_85K_NEW_HAS_DOO (
    I$OBJ_ID BIGINT)
RETURNS (
    HAS_DOO SMALLINT)
AS
DECLARE VARIABLE V$STATUS VARCHAR(10);
begin
  HAS_DOO = 0;

  V$STATUS = (SELECT STATUS FROM OU_LICENCE_TYPE);
  IF(V$STATUS = 'D') THEN HAS_DOO = 1;
  ELSE IF(V$STATUS = 'S') THEN
  BEGIN
    SELECT FIRST 1 1
    FROM LINKS L472
    JOIN VALL V3327 ON V3327.OBJ_ID = L472.OBJ_ID AND V3327.PARAM_ID = 3327 AND V3327.IS_DEL = 0 AND V3327.LISTVAL_ID IN (21, 3263, 3264)
    WHERE L472.PARENT_ID = :I$OBJ_ID AND L472.OBJ_TYPE_ID = 472 AND L472.DATE_DEL IS NULL
    INTO :HAS_DOO;
  END
  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_CERTIFICATE_REG_LIST (
    I$OBJ_ID BIGINT,
    I$DT_FROM DATE,
    I$DT_TO DATE,
    I$USER_ID BIGINT)
RETURNS (
    VAL1 INTEGER,
    VAL0 VARCHAR(4000),
    VAL2 VARCHAR(30),
    VAL3 VARCHAR(30),
    VAL4 VARCHAR(1000),
    VAL5 DATE,
    VAL6 DATE,
    VAL7 VARCHAR(255),
    VAL8 VARCHAR(255),
    VAL9 DATE,
    VAL11 VARCHAR(255),
    VAL12 DATE)
AS
declare variable V$STAGE_ID bigint;
declare variable V$CLASS_ID bigint;
declare variable Y1 smallint;
declare variable Y2 smallint;
declare variable I smallint;
BEGIN
    Y1 = EXTRACT(YEAR FROM I$DT_FROM);
    Y2 = EXTRACT(YEAR FROM I$DT_TO);
    I = Y1;
    WHILE (I <= Y2) DO
    BEGIN
        FOR SELECT OBJ_ID
            FROM LINKS L7
            WHERE L7.PARENT_ID = :I$OBJ_ID
              AND L7.OBJ_TYPE_ID+0 = 7
              AND L7.DATE_DEL IS NULL
            INTO :V$STAGE_ID
        DO
        BEGIN
            FOR SELECT OBJ_ID, OBJ_CAPTION
                FROM CERTIFICATE_REG_CLASSES_LIST(:I, :V$STAGE_ID)
                INTO :V$CLASS_ID, :VAL0
            DO
            BEGIN
                FOR SELECT VAL1, VAL2, VAL3, REPLACE(VAL4, ASCII_CHAR(13), '') VAL4, VAL5, VAL6, VAL7, VAL8, VAL9, VAL11, VAL12
                    FROM CERTIFICATE_REG_LIST(:I, :V$CLASS_ID, :V$STAGE_ID, :I$USER_ID)
                    WHERE VAL6 BETWEEN :I$DT_FROM AND :I$DT_TO
                    INTO :VAL1, :VAL2, :VAL3, :VAL4, :VAL5, :VAL6, :VAL7, :VAL8, :VAL9, :VAL11, :VAL12
                DO
                BEGIN
                    SUSPEND;
                END
            END
        END
        I = I + 1;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_CLASS_SHORT_DOU (
    I$REGION_ID BIGINT NOT NULL,
    I$OPF_FILTER VARCHAR(1000),
    I$POD_FILTER VARCHAR(1000))
RETURNS (
    V00 VARCHAR(1000),
    V01 INTEGER,
    V02 INTEGER,
    V03 INTEGER,
    V04 INTEGER,
    V05 INTEGER,
    V06 INTEGER,
    V07 INTEGER,
    V08 INTEGER)
AS
BEGIN
    IF(I$OPF_FILTER = '') THEN I$OPF_FILTER = NULL;
    IF(I$POD_FILTER = '') THEN I$POD_FILTER = NULL;

    FOR SELECT
            (SELECT CAPTION FROM OBJECT_CAPTION_GET(L111.OBJ_ID)) V00,
            COUNT(DISTINCT IIF(V1558.LISTVAL_ID IS NOT NULL AND V11.LISTVAL_ID = 947, L9.OBJ_ID, NULL)),
            SUM(IIF(V1558.LISTVAL_ID IS NOT NULL AND V11.LISTVAL_ID = 947, 1, 0)),
            COUNT(DISTINCT IIF(V1558.LISTVAL_ID IS NOT NULL AND (V11.LISTVAL_ID = 954 OR V10.LISTVAL_ID = 2216), L9.OBJ_ID, NULL)),
            SUM(IIF(V1558.LISTVAL_ID IS NOT NULL AND (V11.LISTVAL_ID = 954 OR V10.LISTVAL_ID = 2216), 1, 0)),
            COUNT(DISTINCT IIF(V11.LISTVAL_ID IN (947, 954) OR V10.LISTVAL_ID = 2216 OR V1558.LISTVAL_ID IS NULL, NULL, L9.OBJ_ID)),
            SUM(IIF(V11.LISTVAL_ID IN (947, 954) OR V10.LISTVAL_ID = 2216 OR V1558.LISTVAL_ID IS NULL, 0, 1)),
            COUNT(DISTINCT IIF(V1558.LISTVAL_ID IS NOT NULL, L9.OBJ_ID, NULL)),
            SUM(IIF(V1558.LISTVAL_ID IS NOT NULL, 1, 0))

        FROM LINKS L111
        JOIN LINKS L2 ON L2.PARENT_ID = L111.OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
        LEFT JOIN VALL V10 ON V10.OBJ_ID = L2.OBJ_ID AND V10.PARAM_ID = 10 AND V10.IS_DEL = 0
        LEFT JOIN VALL V11 ON V11.OBJ_ID = L2.OBJ_ID AND V11.PARAM_ID = 11 AND V11.IS_DEL = 0
        -- Фильтр по подчинению
        LEFT JOIN VALS V6 ON V6.OBJ_ID = L2.OBJ_ID AND V6.PARAM_ID = 6 AND V6.IS_DEL = 0
        -- Включать частные ?
        LEFT JOIN VALL V8 ON V8.OBJ_ID = L2.OBJ_ID AND V8.PARAM_ID = 8 AND V8.IS_DEL = 0
        JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
        LEFT JOIN VALL V1558 ON V1558.OBJ_ID = L9.OBJ_ID AND V1558.PARAM_ID = 1558 AND V1558.IS_DEL = 0 AND V1558.LISTVAL_ID = 3296
        JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        LEFT JOIN VALD V89 ON V89.OBJ_ID = L10.OBJ_ID AND V89.PARAM_ID = 89 AND V89.IS_DEL = 0
        WHERE L111.PARENT_ID = :I$REGION_ID AND L111.OBJ_TYPE_ID = 111 AND L111.DATE_DEL IS NULL AND
            (:I$POD_FILTER IS NULL OR V6.VAL = :I$POD_FILTER) AND (:I$OPF_FILTER IS NULL OR :I$OPF_FILTER = 'Да' OR V8.LISTVAL_ID IS NULL OR V8.LISTVAL_ID <> 5404)
        GROUP BY L111.OBJ_ID
        ORDER BY 1
        INTO :V00, :V01, :V02, :V03, :V04, :V05, :V06, :V07, :V08
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_COMPENSATION_DOU (
    I$OBJ_ID BIGINT,
    I$SUM_COMP NUMERIC(8,2),
    I$DT_FROM DATE,
    I$DT_TO DATE)
RETURNS (
    C1 INTEGER,
    C2 VARCHAR(200),
    C3 VARCHAR(200),
    C4 DATE,
    C5 DATE,
    C6 VARCHAR(10),
    C7 VARCHAR(350),
    C8 VARCHAR(4),
    C9 VARCHAR(10),
    C10 VARCHAR(10),
    C11 VARCHAR(10),
    C12 VARCHAR(10))
AS
declare variable V$PARN_ID bigint;
declare variable V$EXT_OBJ_ID bigint;
declare variable V$CHILD_OBJ_ID bigint;
declare variable V$CODE bigint;
declare variable V$CHILD_NUM varchar(100);
declare variable V$BDT date;
declare variable V$NDT date;
declare variable V$C6_ numeric(8,2);
declare variable V$C8_ integer;
declare variable V$C9_ numeric(8,2);
BEGIN
  IF (I$DT_FROM > I$DT_TO) THEN
  BEGIN
    SUSPEND;
    EXIT;
  END

  C1 = 0;
  FOR
    SELECT D.OBJ_ID, MIN(M.DATE_IN), MAX(M.DATE_OUT)
    FROM OBJECT_CHILDREN_GET_DEEP(:I$OBJ_ID, 10, 4) D
    JOIN PERSON_MOVEMENTS M ON M.DATE_DEL IS NULL AND M.PERSON_ID = D.OBJ_ID AND M.GROUP_TYPE_ID = 9 AND M.DATE_IN <= :I$DT_TO AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :I$DT_FROM)
    GROUP BY 1
    INTO :V$CHILD_OBJ_ID, :V$BDT, :V$NDT
  DO
  BEGIN
    -- Если ученик уходил, но вернулся - скидываем дату окончания
    IF(EXISTS(
      SELECT FIRST 1 1
      FROM LINKS LP9
      WHERE LP9.OBJ_ID = :V$CHILD_OBJ_ID AND LP9.PARENT_TYPE_ID = 9 AND LP9.DATE_DEL IS NULL
    ))
    THEN
      V$NDT = NULL;

    V$PARN_ID = NULL;
    V$EXT_OBJ_ID = NULL;
        
    SELECT CASE SUBSTRING(TRIM(VAL) FROM 1 FOR CHAR_LENGTH(VAL) - 1) WHEN '' THEN 0 ELSE SUBSTRING(TRIM(VAL) FROM 1 FOR CHAR_LENGTH(VAL) - 1) END AS VAL
    FROM DO_FUNC(:V$CHILD_OBJ_ID, 1552, 39)
    INTO :V$C8_;

    SELECT FIRST 1 L20.OBJ_ID, L20.EXT_OBJ_ID
    FROM LINKS L20
    JOIN VALL VL ON VL.OBJ_ID = L20.EXT_OBJ_ID AND VL.PARAM_ID = 2453 AND VL.IS_DEL = 0 AND VL.LISTVAL_ID <> 3303
    WHERE L20.OBJ_TYPE_ID = 20 AND L20.DATE_DEL IS NULL AND L20.PARENT_ID = :V$CHILD_OBJ_ID
    INTO :V$PARN_ID, :V$EXT_OBJ_ID;

    IF (V$C8_ > 0) THEN
    BEGIN
      C1 = C1 + 1;

      SELECT C1
      FROM BUILD_REP_FIO(:V$PARN_ID, 128, 129, 130, 0)
      INTO :C2;

      SELECT C1
      FROM BUILD_REP_FIO(:V$CHILD_OBJ_ID, 55, 56, 57, 1)
      INTO :C3;

      IF (C3 <> '') THEN
      BEGIN
        SELECT :C3 || ' ' || V
        FROM VAL_GET(:V$CHILD_OBJ_ID, 89)
        INTO :C3;
      END
      C4 = V$BDT;
      C5 = V$NDT;

      SELECT VG.V, VG.I FROM VAL_GET(:V$EXT_OBJ_ID, 2453) VG INTO :C7, :V$CODE;
      SELECT SUBSTRING(TRIM(VAL) FROM 1 FOR CHAR_LENGTH(VAL) - 1) FROM DO_FUNC(:V$CHILD_OBJ_ID, 1552, 39) INTO :V$C8_;
      SELECT VL.V FROM VAL_GET(:V$CHILD_OBJ_ID, 1642) VL INTO :V$CHILD_NUM;

      IF (V$CODE IN (3307, 3308) AND (V$CHILD_NUM <> '')) THEN
      BEGIN
        C7 = C7 || ' (' || V$CHILD_NUM || ')';
      END

      V$C6_ = I$SUM_COMP;
      C6 = V$C6_;
      C8 = V$C8_;

      V$C9_ = CAST((V$C6_ * V$C8_) / 100 as NUMERIC(18,2));
      C9 = V$C9_;
      C10 = CAST(:V$C6_ - :V$C9_ as NUMERIC(18,2));

      C11 = '';
      C12 = '';

      SUSPEND;
    END
  END

END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_EMPLOYEE (
    I$OBJ_ID BIGINT,
    I$DT DATE)
RETURNS (
    C1 VARCHAR(500),
    C2 VARCHAR(500),
    C3 VARCHAR(500),
    C4 VARCHAR(500),
    C5 VARCHAR(500),
    C6 VARCHAR(500),
    C7 VARCHAR(500),
    C8 VARCHAR(100),
    C9 VARCHAR(100),
    C10 VARCHAR(100),
    C11 VARCHAR(100))
AS
declare variable V$PERSON_OBJ_ID bigint;
declare variable V$EMPLOYEE integer;
BEGIN

    FOR
        SELECT L14.OBJ_ID

        FROM LINKS L14

        LEFT JOIN VAL_GET(L14.OBJ_ID, 274) V274
        ON (1 = 1)

        WHERE L14.PARENT_ID IN (
            SELECT :I$OBJ_ID
            FROM RDB$DATABASE
            UNION
            -- for UDOD
            SELECT L211.OBJ_ID
            FROM LINKS L211
            WHERE L211.PARENT_ID = :I$OBJ_ID
              AND L211.OBJ_TYPE_ID = 211
              AND L211.DATE_DEL IS NULL)
        AND V274.I = 602
        AND L14.DATE_DEL IS NULL
        AND L14.OBJ_TYPE_ID = 14

        INTO :V$PERSON_OBJ_ID
    DO
    BEGIN
        SELECT V
        FROM VAL_GET(:V$PERSON_OBJ_ID, 59)
        INTO :C1;

        SELECT V
        FROM VAL_GET(:V$PERSON_OBJ_ID, 60)
        INTO :C2;

        SELECT V
        FROM VAL_GET(:V$PERSON_OBJ_ID, 61)
        INTO :C3;

        SELECT V
        FROM VAL_GET(:V$PERSON_OBJ_ID, 278)
        INTO :C4;

        SELECT VAL FROM VACANCY_GET_CAT(:V$PERSON_OBJ_ID) INTO :C5;

        SELECT FIRST 1 V587.V, VG.V

        FROM LINKS L15

        JOIN VALL VL2
        ON VL2.OBJ_ID = L15.OBJ_ID
        AND VL2.PARAM_ID = 72
        AND VL2.LISTVAL_ID = 934
        AND VL2.IS_DEL = 0

        LEFT JOIN VALD V74
        ON V74.OBJ_ID = L15.OBJ_ID
        AND V74.PARAM_ID = 74
        AND V74.IS_DEL = 0

        LEFT JOIN VAL_GET(L15.OBJ_ID, 587) V587
        ON (1 = 1)

        LEFT JOIN VAL_GET(L15.OBJ_ID, 69) VG
        ON (1 = 1)

        WHERE L15.PARENT_ID = :V$PERSON_OBJ_ID
        AND L15.DATE_DEL IS NULL
        AND L15.OBJ_TYPE_ID = 15
        AND ((V74.VAL IS NULL) OR (V74.VAL > :I$DT))

        ORDER BY V587.I

        INTO :C6, :C7;

        SELECT SUM(SE.DAYS360_COUNT)
        FROM PARAGRAF_EMPLOYEE_SENIORITY_LST(:V$PERSON_OBJ_ID, :I$DT) SE
        WHERE SE.SENIORITY_TYPE = 941
        INTO :V$EMPLOYEE;

        SELECT WORK_TIME
        FROM DAYS_COUNT_TO_WORK_TIME(:V$EMPLOYEE)
        INTO :C8;

        SELECT SUM(SE.DAYS360_COUNT)
        FROM PARAGRAF_EMPLOYEE_SENIORITY_LST(:V$PERSON_OBJ_ID, :I$DT) SE
        WHERE SE.SENIORITY_TYPE = 942
        INTO :V$EMPLOYEE;

        SELECT WORK_TIME
        FROM DAYS_COUNT_TO_WORK_TIME(:V$EMPLOYEE)
        INTO :C9;

        SELECT SUM(SE.DAYS360_COUNT)
        FROM PARAGRAF_EMPLOYEE_SENIORITY_LST(:V$PERSON_OBJ_ID, :I$DT) SE
        WHERE SE.SENIORITY_TYPE = 943
        INTO :V$EMPLOYEE;

        SELECT WORK_TIME
        FROM DAYS_COUNT_TO_WORK_TIME(:V$EMPLOYEE)
        INTO :C10;

        SELECT SUM(SE.DAYS360_COUNT)
        FROM PARAGRAF_EMPLOYEE_SENIORITY_LST(:V$PERSON_OBJ_ID, :I$DT) SE
        WHERE SE.SENIORITY_TYPE = 1978
        INTO :V$EMPLOYEE;

        SELECT WORK_TIME
        FROM DAYS_COUNT_TO_WORK_TIME(:V$EMPLOYEE)
        INTO :C11;
        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_EMPLOYEE_DOU (
    I$OBJ_ID BIGINT,
    I$DT DATE,
    I$TEACHER_ONLY SMALLINT = 1)
RETURNS (
    C1 VARCHAR(500),
    C2 VARCHAR(500),
    C3 VARCHAR(500),
    C4 DATE,
    C5 VARCHAR(500),
    C6 VARCHAR(500),
    C7 VARCHAR(500),
    C8 VARCHAR(100),
    C9 VARCHAR(100),
    C10 VARCHAR(100))
AS
declare variable V$PERSON_OBJ_ID bigint;
declare variable V$EMPLOYEE integer;
BEGIN

    FOR
        SELECT L14.OBJ_ID
        FROM LINKS L14
        LEFT JOIN IS_TEACHER(L14.OBJ_ID) V988 ON (1 = 1)
        WHERE L14.PARENT_ID = :I$OBJ_ID AND ((:I$TEACHER_ONLY = 0) OR (:I$TEACHER_ONLY <> 0 AND V988.X = 1)) AND L14.DATE_DEL IS NULL AND L14.OBJ_TYPE_ID = 14
        INTO :V$PERSON_OBJ_ID
    DO
    BEGIN
        SELECT V
        FROM VAL_GET(:V$PERSON_OBJ_ID, 59)
        INTO :C1;

        SELECT V
        FROM VAL_GET(:V$PERSON_OBJ_ID, 60)
        INTO :C2;

        SELECT V
        FROM VAL_GET(:V$PERSON_OBJ_ID, 61)
        INTO :C3;

        SELECT D
        FROM VAL_GET(:V$PERSON_OBJ_ID, 241)
        INTO :C4;

        SELECT V
        FROM VAL_GET(:V$PERSON_OBJ_ID, 278)
        INTO :C5;

        SELECT VAL FROM VACANCY_GET_CAT(:V$PERSON_OBJ_ID) INTO :C6;

        C7 = NULL;
        SELECT FIRST 1 VG.V
        FROM LINKS L15
        JOIN VALL VL1 ON VL1.OBJ_ID = L15.OBJ_ID AND VL1.LISTVAL_ID = 207 AND VL1.PARAM_ID = 587 AND VL1.IS_DEL = 0
        JOIN VALL VL2 ON VL2.OBJ_ID = L15.OBJ_ID AND VL2.PARAM_ID = 72 AND VL2.LISTVAL_ID = 934 AND VL2.IS_DEL = 0
        LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
        LEFT JOIN VAL_GET(L15.OBJ_ID, 69) VG ON (1 = 1)
        WHERE L15.PARENT_ID = :V$PERSON_OBJ_ID AND L15.DATE_DEL IS NULL AND L15.OBJ_TYPE_ID = 15 AND ((V74.VAL IS NULL) OR (V74.VAL > :I$DT))
        INTO :C7;

        -- Если не нашла должности среди штатных сотрудников, берем из всех остальных
        IF(C7 IS NULL) THEN
        BEGIN
            SELECT FIRST 1 VG.V
            FROM LINKS L15
            JOIN VALL VL1 ON VL1.OBJ_ID = L15.OBJ_ID AND VL1.PARAM_ID = 587 AND VL1.IS_DEL = 0
            JOIN VALL VL2 ON VL2.OBJ_ID = L15.OBJ_ID AND VL2.PARAM_ID = 72 AND VL2.LISTVAL_ID = 934 AND VL2.IS_DEL = 0
            LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
            LEFT JOIN VAL_GET(L15.OBJ_ID, 69) VG ON (1 = 1)
            WHERE L15.PARENT_ID = :V$PERSON_OBJ_ID AND L15.DATE_DEL IS NULL AND L15.OBJ_TYPE_ID = 15 AND ((V74.VAL IS NULL) OR (V74.VAL > :I$DT))
            INTO :C7;
        END

        SELECT SUM(SE.DAYS360_COUNT)
        FROM PARAGRAF_EMPLOYEE_SENIORITY_LST(:V$PERSON_OBJ_ID, :I$DT) SE
        WHERE SE.SENIORITY_TYPE = 941
        INTO :V$EMPLOYEE;

        SELECT WORK_TIME
        FROM DAYS_COUNT_TO_WORK_TIME(:V$EMPLOYEE)
        INTO :C8;

        SELECT SUM(SE.DAYS360_COUNT)
        FROM PARAGRAF_EMPLOYEE_SENIORITY_LST(:V$PERSON_OBJ_ID, :I$DT) SE
        WHERE SE.SENIORITY_TYPE = 942
        INTO :V$EMPLOYEE;

        SELECT WORK_TIME
        FROM DAYS_COUNT_TO_WORK_TIME(:V$EMPLOYEE)
        INTO :C9;

        SELECT SUM(SE.DAYS360_COUNT)
        FROM PARAGRAF_EMPLOYEE_SENIORITY_LST(:V$PERSON_OBJ_ID, :I$DT) SE
        WHERE SE.SENIORITY_TYPE = 943
        INTO :V$EMPLOYEE;

        SELECT WORK_TIME
        FROM DAYS_COUNT_TO_WORK_TIME(:V$EMPLOYEE)
        INTO :C10;
        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_EMPLOYEE_IN (
    I$SCHOOL_ID BIGINT,
    I$FROM DATE,
    I$TO DATE)
RETURNS (
    C1 DATE,
    C2 VARCHAR(1000),
    C3 VARCHAR(1000),
    C4 DATE,
    C5 VARCHAR(1000))
AS
DECLARE VARIABLE V$EMPLOYEE_ID BIGINT;
DECLARE VARIABLE V$MOVEMENT_ID BIGINT;
DECLARE VARIABLE V$OBJ_ID BIGINT;
BEGIN
    FOR
        SELECT L14.OBJ_ID

        FROM LINKS L14

        WHERE L14.PARENT_ID IN (
            SELECT :I$SCHOOL_ID
            FROM RDB$DATABASE
            UNION ALL
            SELECT OBJ_ID
            FROM LINKS
            WHERE PARENT_ID = :I$SCHOOL_ID
            AND OBJ_TYPE_ID = 211
            AND DATE_DEL IS NULL
        )
        AND L14.DATE_DEL IS NULL
        AND L14.OBJ_TYPE_ID = 14

        UNION

        SELECT L14.OBJ_ID
        FROM LINKS L84

        JOIN LINKS L14
        ON L14.PARENT_ID = L84.OBJ_ID
        AND L14.DATE_DEL IS NULL
        AND L14.OBJ_TYPE_ID = 14

        WHERE L84.PARENT_ID = :I$SCHOOL_ID
        AND L84.DATE_DEL IS NULL
        AND L84.OBJ_TYPE_ID = 84

        INTO :V$EMPLOYEE_ID
    DO
    BEGIN
        FOR
            SELECT FIRST 1
                   L15.OBJ_ID

            FROM LINKS L15
            WHERE L15.PARENT_ID = :V$EMPLOYEE_ID
            AND L15.DATE_DEL IS NULL
            AND L15.OBJ_TYPE_ID = 15
            -- DATE_INS движения >= DATE_DEL из выбывших
            AND L15.DATE_INS >= COALESCE((
                SELECT MAX(DATE_DEL)
                FROM LINKS
                WHERE OBJ_ID = :V$EMPLOYEE_ID
                  AND PARENT_TYPE_ID = 84
                  AND DATE_DEL IS NOT NULL), L15.DATE_INS)
            INTO :V$MOVEMENT_ID
        DO
        BEGIN
            SELECT D FROM VAL_GET(:V$MOVEMENT_ID,73) INTO :C1;

            IF (C1 >= I$FROM AND C1 <= I$TO) THEN
            BEGIN
                SELECT I FROM VAL_GET(:V$MOVEMENT_ID,70) INTO :V$OBJ_ID;
                SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$OBJ_ID) INTO :C2;

                SELECT V FROM VAL_GET(:V$MOVEMENT_ID,455) INTO :C3;
        
                SELECT D FROM VAL_GET(:V$MOVEMENT_ID,454) INTO :C4;

                SELECT I FROM VAL_GET(:V$MOVEMENT_ID,69) INTO :V$OBJ_ID;
                C5 = '';
                IF (V$OBJ_ID <> 0) THEN
                    SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$OBJ_ID) INTO :C5;

                SUSPEND;
            END
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_EMPLOYEE_OUT (
    I$SCHOOL_ID BIGINT,
    I$FROM DATE,
    I$TO DATE)
RETURNS (
    C1 DATE,
    C2 VARCHAR(1000),
    C3 VARCHAR(1000),
    C4 DATE,
    C5 VARCHAR(1000),
    C6 VARCHAR(1000),
    C7 VARCHAR(1000))
AS
declare variable V$MOVEMENT_ID bigint;
declare variable V$OBJ_ID bigint;
BEGIN
    FOR
        SELECT L15.OBJ_ID

        FROM LINKS L84

        JOIN LINKS L14
        ON L14.PARENT_ID = L84.OBJ_ID
        AND L14.DATE_DEL IS NULL
        AND L14.OBJ_TYPE_ID = 14

        JOIN LINKS L15
        ON L15.PARENT_ID = L14.OBJ_ID
        AND L15.DATE_DEL IS NULL
        AND L15.OBJ_TYPE_ID = 15

        WHERE L84.PARENT_ID = :I$SCHOOL_ID
        AND L84.DATE_DEL IS NULL
        AND L84.OBJ_TYPE_ID = 84

        INTO :V$MOVEMENT_ID
    DO
    BEGIN
            SELECT D FROM VAL_GET(:V$MOVEMENT_ID,74) INTO :C1;

            IF (C1 >= I$FROM AND C1 <= I$TO) THEN
            BEGIN

                SELECT I FROM VAL_GET(:V$MOVEMENT_ID,70) INTO :V$OBJ_ID;
                SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$OBJ_ID) INTO :C2;

                SELECT V FROM VAL_GET(:V$MOVEMENT_ID,457) INTO :C3;

                SELECT D FROM VAL_GET(:V$MOVEMENT_ID,456) INTO :C4;

                SELECT I FROM VAL_GET(:V$MOVEMENT_ID,69) INTO :V$OBJ_ID;
                C5 = '';
                IF (V$OBJ_ID <> 0) THEN
                    SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$OBJ_ID) INTO :C5;

                SELECT V FROM VAL_GET(:V$MOVEMENT_ID,459) INTO :C6;

                SELECT V FROM VAL_GET(:V$MOVEMENT_ID,458) INTO :C7;

                SUSPEND;
            END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_GET_WEBLINKS (
    OBJ_ID BIGINT)
RETURNS (
    OO_NAME VARCHAR(300),
    OO_NUM VARCHAR(10),
    OO_DISTRICT VARCHAR(100),
    OO_KIND VARCHAR(100),
    F_5 VARCHAR(500),
    F_6 VARCHAR(500),
    F_7 VARCHAR(500),
    F_8 VARCHAR(500),
    F_9 VARCHAR(500),
    F_10 VARCHAR(500),
    F_11 VARCHAR(500),
    F_12 VARCHAR(500),
    F_13 VARCHAR(500),
    F_14 VARCHAR(500),
    F_15 VARCHAR(500),
    F_16 VARCHAR(500),
    F_17 VARCHAR(500),
    F_18 VARCHAR(500),
    F_19 VARCHAR(500),
    F_20 VARCHAR(500),
    F_21 VARCHAR(500),
    F_22 VARCHAR(500),
    F_23 VARCHAR(500),
    F_24 VARCHAR(500),
    F_25 VARCHAR(500),
    F_26 VARCHAR(500),
    F_27 VARCHAR(500),
    F_28 VARCHAR(500),
    F_29 VARCHAR(500))
AS
begin
  FOR
    SELECT CAST(V2.VAL as varchar(300)), V17.VAL, CAST(R665.VAL as varchar(100)), CAST(R10.VAL as varchar(100)),
      CAST(V2782.VAL as varchar(500)), CAST(V2783.VAL as varchar(500)), CAST(V2784.VAL as varchar(500)), CAST(V2785.VAL as varchar(500)),
      CAST(V2786.VAL as varchar(500)), CAST(V2787.VAL as varchar(500)), CAST(V2788.VAL as varchar(500)), CAST(V2789.VAL as varchar(500)),
      CAST(V2790.VAL as varchar(500)), CAST(V2791.VAL as varchar(500)), CAST(V2792.VAL as varchar(500)), CAST(V2793.VAL as varchar(500)),
      CAST(V2794.VAL as varchar(500)), CAST(V2795.VAL as varchar(500)), CAST(V2796.VAL as varchar(500)), CAST(V2797.VAL as varchar(500)),
      CAST(V2798.VAL as varchar(500)), CAST(V2799.VAL as varchar(500)), CAST(V2800.VAL as varchar(500)), CAST(V2801.VAL as varchar(500)),
      CAST(V2802.VAL as varchar(500)), CAST(V2804.VAL as varchar(500)), CAST(V2805.VAL as varchar(500)), CAST(V2806.VAL as varchar(500)),
      CAST(V2807.VAL as varchar(500))
    FROM LINKS L2
    LEFT JOIN VALS V2 ON V2.OBJ_ID = L2.OBJ_ID AND V2.PARAM_ID = 2 AND V2.IS_DEL = 0
    LEFT JOIN VALI V17 ON V17.OBJ_ID = L2.OBJ_ID AND V17.PARAM_ID = 17 AND V17.IS_DEL = 0
    LEFT JOIN VALL V665 ON V665.OBJ_ID = L2.PARENT_ID AND V665.PARAM_ID = 665 AND V665.IS_DEL = 0
    LEFT JOIN LISTVALS LV665 ON LV665.LISTVAL_ID = V665.LISTVAL_ID
    LEFT JOIN RES R665 ON R665.RES_ID = LV665.RES_ID AND R665.LANG_CODE = 'RU'
    LEFT JOIN VALL V10 ON V10.OBJ_ID = L2.OBJ_ID AND V10.PARAM_ID = 10 AND V10.IS_DEL = 0
    LEFT JOIN LISTVALS LV10 ON LV10.LISTVAL_ID = V10.LISTVAL_ID
    LEFT JOIN RES R10 ON R10.RES_ID = LV10.RES_ID AND R10.LANG_CODE = 'RU'
    LEFT JOIN VALS V2782 ON V2782.OBJ_ID = L2.OBJ_ID AND V2782.PARAM_ID = 2782 AND V2782.IS_DEL = 0
    LEFT JOIN VALS V2783 ON V2783.OBJ_ID = L2.OBJ_ID AND V2783.PARAM_ID = 2783 AND V2783.IS_DEL = 0
    LEFT JOIN VALS V2784 ON V2784.OBJ_ID = L2.OBJ_ID AND V2784.PARAM_ID = 2784 AND V2784.IS_DEL = 0
    LEFT JOIN VALS V2785 ON V2785.OBJ_ID = L2.OBJ_ID AND V2785.PARAM_ID = 2785 AND V2785.IS_DEL = 0
    LEFT JOIN VALS V2786 ON V2786.OBJ_ID = L2.OBJ_ID AND V2786.PARAM_ID = 2786 AND V2786.IS_DEL = 0
    LEFT JOIN VALS V2787 ON V2787.OBJ_ID = L2.OBJ_ID AND V2787.PARAM_ID = 2787 AND V2787.IS_DEL = 0
    LEFT JOIN VALS V2788 ON V2788.OBJ_ID = L2.OBJ_ID AND V2788.PARAM_ID = 2788 AND V2788.IS_DEL = 0
    LEFT JOIN VALS V2789 ON V2789.OBJ_ID = L2.OBJ_ID AND V2789.PARAM_ID = 2789 AND V2789.IS_DEL = 0
    LEFT JOIN VALS V2790 ON V2790.OBJ_ID = L2.OBJ_ID AND V2790.PARAM_ID = 2790 AND V2790.IS_DEL = 0
    LEFT JOIN VALS V2791 ON V2791.OBJ_ID = L2.OBJ_ID AND V2791.PARAM_ID = 2791 AND V2791.IS_DEL = 0
    LEFT JOIN VALS V2792 ON V2792.OBJ_ID = L2.OBJ_ID AND V2792.PARAM_ID = 2792 AND V2792.IS_DEL = 0
    LEFT JOIN VALS V2793 ON V2793.OBJ_ID = L2.OBJ_ID AND V2793.PARAM_ID = 2793 AND V2793.IS_DEL = 0
    LEFT JOIN VALS V2794 ON V2794.OBJ_ID = L2.OBJ_ID AND V2794.PARAM_ID = 2794 AND V2794.IS_DEL = 0
    LEFT JOIN VALS V2795 ON V2795.OBJ_ID = L2.OBJ_ID AND V2795.PARAM_ID = 2795 AND V2795.IS_DEL = 0
    LEFT JOIN VALS V2796 ON V2796.OBJ_ID = L2.OBJ_ID AND V2796.PARAM_ID = 2796 AND V2796.IS_DEL = 0
    LEFT JOIN VALS V2797 ON V2797.OBJ_ID = L2.OBJ_ID AND V2797.PARAM_ID = 2797 AND V2797.IS_DEL = 0
    LEFT JOIN VALS V2798 ON V2798.OBJ_ID = L2.OBJ_ID AND V2798.PARAM_ID = 2798 AND V2798.IS_DEL = 0
    LEFT JOIN VALS V2799 ON V2799.OBJ_ID = L2.OBJ_ID AND V2799.PARAM_ID = 2799 AND V2799.IS_DEL = 0
    LEFT JOIN VALS V2800 ON V2800.OBJ_ID = L2.OBJ_ID AND V2800.PARAM_ID = 2800 AND V2800.IS_DEL = 0
    LEFT JOIN VALS V2801 ON V2801.OBJ_ID = L2.OBJ_ID AND V2801.PARAM_ID = 2801 AND V2801.IS_DEL = 0
    LEFT JOIN VALS V2802 ON V2802.OBJ_ID = L2.OBJ_ID AND V2802.PARAM_ID = 2802 AND V2802.IS_DEL = 0
    LEFT JOIN VALS V2804 ON V2804.OBJ_ID = L2.OBJ_ID AND V2804.PARAM_ID = 2804 AND V2804.IS_DEL = 0
    LEFT JOIN VALS V2805 ON V2805.OBJ_ID = L2.OBJ_ID AND V2805.PARAM_ID = 2805 AND V2805.IS_DEL = 0
    LEFT JOIN VALS V2806 ON V2806.OBJ_ID = L2.OBJ_ID AND V2806.PARAM_ID = 2806 AND V2806.IS_DEL = 0
    LEFT JOIN VALS V2807 ON V2807.OBJ_ID = L2.OBJ_ID AND V2807.PARAM_ID = 2807 AND V2807.IS_DEL = 0
    WHERE L2.OBJ_TYPE_ID = 2 AND (L2.PARENT_TYPE_ID IS NULL OR L2.PARENT_TYPE_ID IN (111, 112)) AND L2.DATE_DEL IS NULL
    INTO :OO_NAME, :OO_NUM, :OO_DISTRICT, :OO_KIND,
      :F_5, :F_6, :F_7, :F_8,
      :F_9, :F_10, :F_11, :F_12,
      :F_13, :F_14, :F_15, :F_16,
      :F_17, :F_18, :F_19, :F_20,
      :F_21, :F_22, :F_23, :F_24,
      :F_25, :F_26, :F_27, :F_28,
      :F_29
  DO
  BEGIN
    SUSPEND;
  END
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_GET_WEBLINKS_STR (
    OBJ_ID BIGINT)
RETURNS (
    OO_NAME VARCHAR(300),
    OO_NUM VARCHAR(10),
    OO_DISTRICT VARCHAR(100),
    OO_KIND VARCHAR(100),
    F_5 VARCHAR(500),
    F_6 VARCHAR(500),
    F_7 VARCHAR(500),
    F_8 VARCHAR(500),
    F_9 VARCHAR(500),
    F_10 VARCHAR(500),
    F_11 VARCHAR(500),
    F_12 VARCHAR(500),
    F_13 VARCHAR(500),
    F_14 VARCHAR(500),
    F_15 VARCHAR(500),
    F_16 VARCHAR(500),
    F_17 VARCHAR(500))
AS
begin
  FOR
    SELECT CAST(V2.VAL as varchar(300)), V17.VAL, CAST(R665.VAL as varchar(100)), CAST(R10.VAL as varchar(100)),
      CAST(V2777.VAL as varchar(500)), CAST(V2778.VAL as varchar(500)), CAST(V2779.VAL as varchar(500)), CAST(V2780.VAL as varchar(500)),
      CAST(V2781.VAL as varchar(500)), CAST(V2803.VAL as varchar(500)), CAST(V2808.VAL as varchar(500)), CAST(V2809.VAL as varchar(500)),
      CAST(V2810.VAL as varchar(500)), CAST(V2811.VAL as varchar(500)), CAST(V2812.VAL as varchar(500)), CAST(V2813.VAL as varchar(500)),
      CAST(V2814.VAL as varchar(500))
    FROM LINKS L2
    LEFT JOIN VALS V2 ON V2.OBJ_ID = L2.OBJ_ID AND V2.PARAM_ID = 2 AND V2.IS_DEL = 0
    LEFT JOIN VALI V17 ON V17.OBJ_ID = L2.OBJ_ID AND V17.PARAM_ID = 17 AND V17.IS_DEL = 0
    LEFT JOIN VALL V665 ON V665.OBJ_ID = L2.PARENT_ID AND V665.PARAM_ID = 665 AND V665.IS_DEL = 0
    LEFT JOIN LISTVALS LV665 ON LV665.LISTVAL_ID = V665.LISTVAL_ID
    LEFT JOIN RES R665 ON R665.RES_ID = LV665.RES_ID AND R665.LANG_CODE = 'RU'
    LEFT JOIN VALL V10 ON V10.OBJ_ID = L2.OBJ_ID AND V10.PARAM_ID = 10 AND V10.IS_DEL = 0
    LEFT JOIN LISTVALS LV10 ON LV10.LISTVAL_ID = V10.LISTVAL_ID
    LEFT JOIN RES R10 ON R10.RES_ID = LV10.RES_ID AND R10.LANG_CODE = 'RU'
    LEFT JOIN VALS V2777 ON V2777.OBJ_ID = L2.OBJ_ID AND V2777.PARAM_ID = 2777 AND V2777.IS_DEL = 0
    LEFT JOIN VALS V2778 ON V2778.OBJ_ID = L2.OBJ_ID AND V2778.PARAM_ID = 2778 AND V2778.IS_DEL = 0
    LEFT JOIN VALS V2779 ON V2779.OBJ_ID = L2.OBJ_ID AND V2779.PARAM_ID = 2779 AND V2779.IS_DEL = 0
    LEFT JOIN VALS V2780 ON V2780.OBJ_ID = L2.OBJ_ID AND V2780.PARAM_ID = 2780 AND V2780.IS_DEL = 0
    LEFT JOIN VALS V2781 ON V2781.OBJ_ID = L2.OBJ_ID AND V2781.PARAM_ID = 2781 AND V2781.IS_DEL = 0
    LEFT JOIN VALS V2803 ON V2803.OBJ_ID = L2.OBJ_ID AND V2803.PARAM_ID = 2803 AND V2803.IS_DEL = 0
    LEFT JOIN VALS V2808 ON V2808.OBJ_ID = L2.OBJ_ID AND V2808.PARAM_ID = 2808 AND V2808.IS_DEL = 0
    LEFT JOIN VALS V2809 ON V2809.OBJ_ID = L2.OBJ_ID AND V2809.PARAM_ID = 2809 AND V2809.IS_DEL = 0
    LEFT JOIN VALS V2810 ON V2810.OBJ_ID = L2.OBJ_ID AND V2810.PARAM_ID = 2810 AND V2810.IS_DEL = 0
    LEFT JOIN VALS V2811 ON V2811.OBJ_ID = L2.OBJ_ID AND V2811.PARAM_ID = 2811 AND V2811.IS_DEL = 0
    LEFT JOIN VALS V2812 ON V2812.OBJ_ID = L2.OBJ_ID AND V2812.PARAM_ID = 2812 AND V2812.IS_DEL = 0
    LEFT JOIN VALS V2813 ON V2813.OBJ_ID = L2.OBJ_ID AND V2813.PARAM_ID = 2813 AND V2813.IS_DEL = 0
    LEFT JOIN VALS V2814 ON V2814.OBJ_ID = L2.OBJ_ID AND V2814.PARAM_ID = 2814 AND V2814.IS_DEL = 0
    WHERE L2.OBJ_TYPE_ID = 2 AND (L2.PARENT_TYPE_ID IS NULL OR L2.PARENT_TYPE_ID IN (111, 112)) AND L2.DATE_DEL IS NULL
    INTO :OO_NAME, :OO_NUM, :OO_DISTRICT, :OO_KIND,
      :F_5, :F_6, :F_7, :F_8,
      :F_9, :F_10, :F_11, :F_12,
      :F_13, :F_14, :F_15, :F_16,
      :F_17
  DO
  BEGIN
    SUSPEND;
  END
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_HOT_FOOD (
    I$SCHOOL_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    SCHOOLAR VARCHAR(1000),
    CLASS VARCHAR(100),
    FOOD VARCHAR(100),
    SORT_ORDER DOUBLE PRECISION)
AS
declare variable SCHOOLAR_ID bigint;
declare variable CLASS_ID bigint;
declare variable LANG_CODE varchar(2);
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :LANG_CODE;

    FOR SELECT L9.OBJ_ID, L10.OBJ_ID, R.VAL_LONG
        FROM LINKS L7
        INNER JOIN LINKS L8 ON L8.PARENT_ID =L7.OBJ_ID
        INNER JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID
        INNER JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID
        INNER JOIN VALL V189 ON V189.OBJ_ID = L10.OBJ_ID
        INNER JOIN LISTVALS L ON L.LISTVAL_ID = V189.LISTVAL_ID
        LEFT JOIN RES_GET(L.RES_ID,  :LANG_CODE) R ON 1=1
        WHERE L7.PARENT_ID = :I$SCHOOL_ID
          AND L7.OBJ_TYPE_ID = 7
          AND L7.DATE_DEL IS NULL
          AND L8.OBJ_TYPE_ID = 8
          AND L8.DATE_DEL IS NULL
          AND L9.OBJ_TYPE_ID = 9
          AND L9.DATE_DEL IS NULL
          AND L10.OBJ_TYPE_ID = 10
          AND L10.DATE_DEL IS NULL
          AND V189.PARAM_ID = 189
          AND V189.IS_DEL = 0
          AND V189.LISTVAL_ID IN (481,1406,1407,1408,1409,1410,3146,3147)
        INTO :CLASS_ID, :SCHOOLAR_ID, :FOOD
    DO
    BEGIN
        SELECT CAPTION, SORT_ORDER
        FROM OBJECT_CAPTION_GET(:CLASS_ID,NULL,NULL,:I$USER_ID)
        INTO :CLASS, :SORT_ORDER;

        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:SCHOOLAR_ID,NULL,NULL,:I$USER_ID)
        INTO :SCHOOLAR;

        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_HOT_FOOD2 (
    I$SCHOOL_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    V1 VARCHAR(1000),
    V2 VARCHAR(100),
    V3 VARCHAR(100),
    V4 VARCHAR(100),
    V5 VARCHAR(100),
    V6 VARCHAR(100),
    V7 VARCHAR(100),
    V8 VARCHAR(100),
    V9 VARCHAR(1000),
    CLASS_ORDER DOUBLE PRECISION)
AS
declare variable SCHOOLAR_ID bigint;
declare variable CLASS_ID bigint;
declare variable LANG_CODE varchar(2);
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :LANG_CODE;

    SELECT FIRST 1 COUNT(*)
    FROM LINKS L68
    INNER JOIN LINKS L3 ON L3.PARENT_ID = L68.OBJ_ID
    INNER JOIN LINKS L59 ON L59.PARENT_ID = L3.OBJ_ID
    INNER JOIN LINKS L6 ON L6.PARENT_ID = L59.OBJ_ID
    INNER JOIN VALL V1341 ON V1341.OBJ_ID = L59.OBJ_ID
    WHERE L68.PARENT_ID = :I$SCHOOL_ID
      AND L68.OBJ_TYPE_ID = 68
      AND L68.DATE_DEL IS NULL
      AND L3.OBJ_TYPE_ID = 3
      AND L3.DATE_DEL IS NULL
      AND L59.OBJ_TYPE_ID = 59
      AND L59.DATE_DEL IS NULL
      AND L6.OBJ_TYPE_ID = 6
      AND L6.DATE_DEL IS NULL
      AND V1341.PARAM_ID = 1341
      AND V1341.IS_DEL = 0
      AND V1341.LISTVAL_ID = 2
    GROUP BY L59.OBJ_ID
    INTO :V4;

    V5 = '';

    SELECT V
    FROM VAL_GET(:I$SCHOOL_ID, 17, 0, :I$USER_ID)
    INTO :V6;

    IF (V6 = '') THEN
    BEGIN
        SELECT V
        FROM VAL_GET(:I$SCHOOL_ID, 2, 0, :I$USER_ID)
        INTO :V6;
    END

    V7 = EXTRACT(MONTH FROM CURRENT_DATE);
    V8 = EXTRACT(YEAR FROM CURRENT_DATE);

    SELECT F || ' ' || I || ' ' || O
    FROM R_SPB_POST_DIRECTOR(:I$SCHOOL_ID,:I$USER_ID)
    INTO :V9;

    FOR SELECT L9.OBJ_ID, L10.OBJ_ID, R.VAL_LONG
        FROM LINKS L7
        INNER JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID
        INNER JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID
        INNER JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID
        INNER JOIN VALL V189 ON V189.OBJ_ID = L10.OBJ_ID
        INNER JOIN LISTVALS L ON L.LISTVAL_ID = V189.LISTVAL_ID
        LEFT JOIN RES_GET(L.RES_ID,  :LANG_CODE) R ON 1=1
        WHERE L7.PARENT_ID = :I$SCHOOL_ID
          AND L7.OBJ_TYPE_ID = 7
          AND L7.DATE_DEL IS NULL
          AND L8.OBJ_TYPE_ID = 8
          AND L8.DATE_DEL IS NULL
          AND L9.OBJ_TYPE_ID = 9
          AND L9.DATE_DEL IS NULL
          AND L10.OBJ_TYPE_ID = 10
          AND L10.DATE_DEL IS NULL
          AND V189.PARAM_ID = 189
          AND V189.IS_DEL = 0
          AND V189.LISTVAL_ID IN (481, 1406, 1407, 1408, 1409, 1410, 3146, 3147)
        INTO :CLASS_ID, :SCHOOLAR_ID, :V3
    DO
    BEGIN
        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:SCHOOLAR_ID, NULL, NULL, :I$USER_ID)
        INTO :V1;

        SELECT CAPTION, SORT_ORDER
        FROM OBJECT_CAPTION_GET(:CLASS_ID, NULL, NULL, :I$USER_ID)
        INTO :V2, :CLASS_ORDER;

        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_INFOCARD_202 (
    I$OBJ_ID BIGINT)
RETURNS (
    PARAM_VAL VARCHAR(4000))
AS
DECLARE VARIABLE V$CHILD_OBJ_ID BIGINT;
DECLARE VARIABLE V$ADR VARCHAR(500);
BEGIN
    FOR SELECT L16.OBJ_ID
        FROM LINKS L73
        INNER JOIN LINKS L16 ON L16.PARENT_ID = L73.OBJ_ID
        WHERE L73.PARENT_ID = :I$OBJ_ID
          AND L73.OBJ_TYPE_ID = 73
          AND L73.DATE_DEL IS NULL
          AND L16.OBJ_TYPE_ID = 16
          AND L16.DATE_DEL IS NULL
        INTO V$CHILD_OBJ_ID
    DO
    BEGIN
        SELECT V
        FROM VAL_GET(:V$CHILD_OBJ_ID, 421)
        INTO PARAM_VAL;

        SELECT VAL
        FROM ADR_GET(420, :V$CHILD_OBJ_ID)
        INTO :V$ADR;

        PARAM_VAL = :PARAM_VAL || ' ' || :V$ADR;

        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_INFOCARD_209 (
    I$OBJ_ID BIGINT)
RETURNS (
    NAZVANIE_PHIO VARCHAR(500),
    ADRES VARCHAR(500),
    TELEPHON VARCHAR(500))
AS
DECLARE VARIABLE V$CHILD_OBJ_ID BIGINT;
BEGIN
    FOR SELECT L5.OBJ_ID
        FROM LINKS L5
        WHERE L5.PARENT_ID = :I$OBJ_ID
          AND L5.OBJ_TYPE_ID = 5
          AND L5.DATE_DEL IS NULL
        INTO V$CHILD_OBJ_ID
    DO
    BEGIN
        SELECT V
        FROM VAL_GET(:V$CHILD_OBJ_ID, 24)
        INTO NAZVANIE_PHIO;

        SELECT V
        FROM VAL_GET(:V$CHILD_OBJ_ID, 25)
        INTO ADRES;

        SELECT V
        FROM VAL_GET(:V$CHILD_OBJ_ID, 26)
        INTO TELEPHON;
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_INFOCARD_210 (
    I$OBJ_ID BIGINT,
    TYPE_DOC INTEGER,
    FLAG_MAXDATE SMALLINT = 0)
RETURNS (
    ORG VARCHAR(500),
    DOCSERIE VARCHAR(500),
    DOCNO VARCHAR(500),
    STARTDATE VARCHAR(500),
    ENDDATE VARCHAR(500))
AS
DECLARE VARIABLE V$CHILD_OBJ_ID BIGINT;
DECLARE VARIABLE V$TYPE_DOC BIGINT;
DECLARE VARIABLE V$OLD_STARTDATE DATE = '1900-01-01';
DECLARE VARIABLE V$STARTDATE DATE;
BEGIN
    IF (FLAG_MAXDATE = 1) THEN
    BEGIN
        FOR SELECT L17.OBJ_ID
            FROM LINKS L17
            WHERE L17.PARENT_ID = :I$OBJ_ID
              AND L17.OBJ_TYPE_ID = 17
              AND L17.DATE_DEL IS NULL
            INTO V$CHILD_OBJ_ID
        DO
        BEGIN
            SELECT I
            FROM VAL_GET(:V$CHILD_OBJ_ID, 471)
            INTO V$TYPE_DOC;
            IF (:V$TYPE_DOC = TYPE_DOC) THEN
            BEGIN
                SELECT D
                FROM VAL_GET(:V$CHILD_OBJ_ID, 482)
                INTO V$STARTDATE;
                IF (V$STARTDATE > V$OLD_STARTDATE) THEN
                BEGIN
                    SELECT V
                    FROM VAL_GET(:V$CHILD_OBJ_ID, 481)
                    INTO ORG;
                    SELECT V
                    FROM VAL_GET(:V$CHILD_OBJ_ID, 479)
                    INTO DOCSERIE;
                    SELECT V
                    FROM VAL_GET(:V$CHILD_OBJ_ID, 480)
                    INTO DOCNO;
                    SELECT D, V
                    FROM VAL_GET(:V$CHILD_OBJ_ID, 482)
                    INTO V$OLD_STARTDATE, STARTDATE;
                    SELECT V
                    FROM VAL_GET(:V$CHILD_OBJ_ID, 483)
                    INTO ENDDATE;
                END
                SUSPEND;
            END
        END
    END
    ELSE
    BEGIN
        FOR SELECT L17.OBJ_ID
            FROM LINKS L17
            WHERE L17.PARENT_ID = :I$OBJ_ID
              AND L17.OBJ_TYPE_ID = 17
              AND L17.DATE_DEL IS NULL
            INTO V$CHILD_OBJ_ID
        DO
        BEGIN
            SELECT I
            FROM VAL_GET(:V$CHILD_OBJ_ID, 471)
            INTO V$TYPE_DOC;
            IF (:V$TYPE_DOC = TYPE_DOC) THEN
            BEGIN
                SELECT V
                FROM VAL_GET(:V$CHILD_OBJ_ID, 481)
                INTO ORG;
                SELECT V
                FROM VAL_GET(:V$CHILD_OBJ_ID, 479)
                INTO DOCSERIE;
                SELECT V
                FROM VAL_GET(:V$CHILD_OBJ_ID, 480)
                INTO DOCNO;
                SELECT V
                FROM VAL_GET(:V$CHILD_OBJ_ID, 482)
                INTO STARTDATE;
                SELECT V
                FROM VAL_GET(:V$CHILD_OBJ_ID, 483)
                INTO ENDDATE;
                SUSPEND;
            END
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_INFOCARD_225 (
    I$OBJ_ID BIGINT)
RETURNS (
    PROGNAME VARCHAR(500),
    PROGTYPENAME VARCHAR(500),
    PROGLEVELNAME VARCHAR(500),
    KOL_VO_CLASS INTEGER,
    OVERALL INTEGER)
AS
declare variable V$CHILD_OBJ_ID bigint;
declare variable V$TYPE_DOC bigint;
declare variable V$STARTDATE date;
BEGIN
    SELECT FIRST 1 L69.OBJ_ID
    FROM LINKS L69
    WHERE L69.PARENT_ID = :I$OBJ_ID
    AND L69.OBJ_TYPE_ID = 17
    AND L69.DATE_DEL IS NULL
    INTO V$CHILD_OBJ_ID;

    FOR
        SELECT L57.OBJ_ID
        FROM LINKS L57
        WHERE L57.PARENT_ID = :V$CHILD_OBJ_ID
        AND L57.OBJ_TYPE_ID = 57
        AND L57.DATE_DEL IS NULL
        INTO V$CHILD_OBJ_ID
    DO
    BEGIN
        SELECT V
        FROM VAL_GET(:V$CHILD_OBJ_ID, 386)
        INTO PROGNAME;

        SELECT V
        FROM VAL_GET(:V$CHILD_OBJ_ID, 1593)
        INTO PROGTYPENAME;

        SELECT V
        FROM VAL_GET(:V$CHILD_OBJ_ID, 1594)
        INTO PROGLEVELNAME;

        SELECT COUNT(DISTINCT L9.OBJ_ID), COUNT(DISTINCT L10.OBJ_ID)
        FROM LINKS L50
        JOIN LINKS L54 ON L54.PARENT_ID = L50.OBJ_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
        JOIN LINKS L9 ON L9.PARENT_ID = L54.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
        LEFT JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        WHERE L50.OBJ_TYPE_ID = 50
          AND L50.DATE_DEL IS NULL
          AND L50.PARENT_ID = :V$CHILD_OBJ_ID
        INTO KOL_VO_CLASS, OVERALL;

        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_INFOCARD_300 (
    I$OBJ_ID BIGINT,
    TYPE_DOLJ INTEGER)
RETURNS (
    F VARCHAR(100),
    I VARCHAR(100),
    O VARCHAR(100),
    TEL VARCHAR(50),
    TELEPHON_DIREKTORA VARCHAR(500),
    TELEFON_BUHGALTERA VARCHAR(500))
AS
DECLARE VARIABLE V$CHILD_OBJ_ID BIGINT;
DECLARE VARIABLE V$TMP_OBJ_ID BIGINT;
DECLARE VARIABLE V$TYPE_DOLJ BIGINT;
DECLARE VARIABLE V$FIO VARCHAR(500);
BEGIN
    FOR SELECT L13.OBJ_ID
        FROM LINKS L13
        WHERE L13.PARENT_ID = :I$OBJ_ID
          AND L13.OBJ_TYPE_ID = 13
          AND L13.DATE_DEL IS NULL
        INTO V$CHILD_OBJ_ID
    DO
    BEGIN
        SELECT I
        FROM VAL_GET(:V$CHILD_OBJ_ID, 58)
        INTO V$TYPE_DOLJ;
        IF (:V$TYPE_DOLJ = TYPE_DOLJ) THEN
        BEGIN
            FOR SELECT L14.PARENT_ID
                FROM LINKS L15
                JOIN LINKS L14 ON L15.OBJ_ID = L14.OBJ_ID AND L14.PARENT_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
                WHERE L15.OBJ_TYPE_ID = 15
                  AND L15.DATE_DEL IS NULL
                  AND L15.PARENT_ID = :V$CHILD_OBJ_ID
                INTO V$TMP_OBJ_ID
            DO
            BEGIN
                SELECT V
                FROM VAL_GET(:V$TMP_OBJ_ID, 60)
                INTO I;
                SELECT V
                FROM VAL_GET(:V$TMP_OBJ_ID, 59)
                INTO F;
                -- FIO = FIO || ' ' || V$FIO;
                SELECT V
                FROM VAL_GET(:V$TMP_OBJ_ID, 61)
                INTO O;
                --  FIO = FIO || ' ' || V$FIO;
                SELECT V
                FROM VAL_GET(:V$TMP_OBJ_ID, 253)
                INTO TEL;
                SELECT V
                FROM VAL_GET(:I$OBJ_ID, 28)
                INTO TELEPHON_DIREKTORA;
                SELECT V
                FROM VAL_GET(:I$OBJ_ID, 31)
                INTO TELEFON_BUHGALTERA;
                SUSPEND;
            END
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_INFOCARD_400 (
    I$OBJ_ID BIGINT)
RETURNS (
    VAL VARCHAR(10))
AS
declare variable V$TMP integer;
BEGIN
  select count(distinct TEACHER_ID) as val1 from PARAGRAF_GRADE_TEACHERS_LIST(:I$OBJ_ID) INTO V$TMP;
  VAL = :V$TMP;
   SUSPEND;
  select count(distinct TEACHER_ID) as val2 from PARAGRAF_GRADE_TEACHERS_LIST(:I$OBJ_ID)
  join LINKS l15 on l15.PARENT_ID = TEACHER_ID and l15.DATE_DEL is NULL and l15.OBJ_TYPE_ID = 15
  JOIN VALL Vl ON vl.PARAM_ID = 587 and vl.OBJ_ID = l15.OBJ_ID and vl.LISTVAL_ID = 207 INTO VAL;
   SUSPEND;
  select count(distinct TEACHER_ID) as val3 from PARAGRAF_GRADE_TEACHERS_LIST(:I$OBJ_ID)
  join LINKS l15 on l15.PARENT_ID = TEACHER_ID and l15.DATE_DEL is NULL and l15.OBJ_TYPE_ID = 15
  JOIN VALL Vl ON vl.PARAM_ID = 587 and vl.OBJ_ID = l15.OBJ_ID and vl.LISTVAL_ID = 208 INTO VAL;
   SUSPEND;
  select count(distinct TEACHER_ID) as val4 from PARAGRAF_GRADE_TEACHERS_LIST(:I$OBJ_ID)
  join LINKS l15 on l15.PARENT_ID = TEACHER_ID and l15.DATE_DEL is NULL and l15.OBJ_TYPE_ID = 15
  JOIN LINKS l13 ON l13.OBJ_ID = l15.OBJ_ID and l13.DATE_DEL is NULL and l13.PARENT_TYPE_ID = 13
  JOIN VALL Vl ON vl.PARAM_ID = 64 and vl.OBJ_ID = l13.PARENT_ID and vl.LISTVAL_ID in (56, 113)
  JOIN VALF  VF ON vF.PARAM_ID = 71 and vF.OBJ_ID = l15.OBJ_ID and vF.VAL > 0 INTO VAL;
   SUSPEND;
  select count(distinct TEACHER_ID) as val5 from PARAGRAF_GRADE_TEACHERS_LIST(:I$OBJ_ID)
  join LINKS l15 on l15.PARENT_ID = TEACHER_ID and l15.DATE_DEL is NULL and l15.OBJ_TYPE_ID = 15
  JOIN LINKS l13 ON l13.OBJ_ID = l15.OBJ_ID and l13.DATE_DEL is NULL and l13.PARENT_TYPE_ID = 13
  JOIN VALL Vl ON vl.PARAM_ID = 58 and vl.OBJ_ID = l13.PARENT_ID and vl.LISTVAL_ID BETWEEN 99 and 118 or vl.LISTVAL_ID = 121
  JOIN VALF  VF ON vF.PARAM_ID = 71 and vF.OBJ_ID = l15.OBJ_ID and vF.VAL > 0 INTO VAL;
   SUSPEND;
  select count(distinct TEACHER_ID) as val6 from PARAGRAF_GRADE_TEACHERS_LIST(:I$OBJ_ID)
  join LINKS l15 on l15.PARENT_ID = TEACHER_ID and l15.DATE_DEL is NULL and l15.OBJ_TYPE_ID = 15
  JOIN LINKS l13 ON l13.OBJ_ID = l15.OBJ_ID and l13.DATE_DEL is NULL and l13.PARENT_TYPE_ID = 13
  JOIN VALL Vl ON vl.PARAM_ID = 58 and vl.OBJ_ID = l13.PARENT_ID and vl.LISTVAL_ID = 145
  JOIN VALF  VF ON vF.PARAM_ID = 71 and vF.OBJ_ID = l15.OBJ_ID and vF.VAL > 0 INTO VAL;
   SUSPEND;
  select count(distinct TEACHER_ID) as val7 from PARAGRAF_GRADE_TEACHERS_LIST(:I$OBJ_ID)
  join LINKS l15 on l15.PARENT_ID = TEACHER_ID and l15.DATE_DEL is NULL and l15.OBJ_TYPE_ID = 15
  JOIN LINKS l13 ON l13.OBJ_ID = l15.OBJ_ID and l13.DATE_DEL is NULL and l13.PARENT_TYPE_ID = 13
  JOIN VALL Vl ON vl.PARAM_ID = 58 and vl.OBJ_ID = l13.PARENT_ID and vl.LISTVAL_ID = 1251
  JOIN VALF  VF ON vF.PARAM_ID = 71 and vF.OBJ_ID = l15.OBJ_ID and vF.VAL > 0 INTO VAL;
   SUSPEND;
  select count(distinct TEACHER_ID) as val8 from PARAGRAF_GRADE_TEACHERS_LIST(:I$OBJ_ID)
  join LINKS l15 on l15.PARENT_ID = TEACHER_ID and l15.DATE_DEL is NULL and l15.OBJ_TYPE_ID = 15
  JOIN LINKS l13 ON l13.OBJ_ID = l15.OBJ_ID and l13.DATE_DEL is NULL and l13.PARENT_TYPE_ID = 13
  JOIN VALL Vl ON vl.PARAM_ID = 58 and vl.OBJ_ID = l13.PARENT_ID and vl.LISTVAL_ID in (119, 120)
  JOIN VALF  VF ON vF.PARAM_ID = 71 and vF.OBJ_ID = l15.OBJ_ID and vF.VAL > 0 INTO VAL;
   SUSPEND;
  select count(distinct TEACHER_ID) as val9 from PARAGRAF_GRADE_TEACHERS_LIST(:I$OBJ_ID)
  join LINKS l15 on l15.PARENT_ID = TEACHER_ID and l15.DATE_DEL is NULL and l15.OBJ_TYPE_ID = 15
  JOIN LINKS l13 ON l13.OBJ_ID = l15.OBJ_ID and l13.DATE_DEL is NULL and l13.PARENT_TYPE_ID = 13
  JOIN VALL Vl ON vl.PARAM_ID = 58 and vl.OBJ_ID = l13.PARENT_ID and vl.LISTVAL_ID = 1252
  JOIN VALF  VF ON vF.PARAM_ID = 71 and vF.OBJ_ID = l15.OBJ_ID and vF.VAL > 0 INTO VAL;
   SUSPEND;
  select count(distinct TEACHER_ID) as val10 from PARAGRAF_GRADE_TEACHERS_LIST(:I$OBJ_ID)
  join LINKS l15 on l15.PARENT_ID = TEACHER_ID and l15.DATE_DEL is NULL and l15.OBJ_TYPE_ID = 15
  JOIN LINKS l13 ON l13.OBJ_ID = l15.OBJ_ID and l13.DATE_DEL is NULL and l13.PARENT_TYPE_ID = 13
  JOIN VALL Vl ON vl.PARAM_ID = 58 and vl.OBJ_ID = l13.PARENT_ID and vl.LISTVAL_ID = 126
  JOIN VALF  VF ON vF.PARAM_ID = 71 and vF.OBJ_ID = l15.OBJ_ID and vF.VAL > 0 INTO VAL;
   SUSPEND;
  select count(distinct TEACHER_ID) as val11 from PARAGRAF_GRADE_TEACHERS_LIST(:I$OBJ_ID)
  join LINKS l15 on l15.PARENT_ID = TEACHER_ID and l15.DATE_DEL is NULL and l15.OBJ_TYPE_ID = 15
  JOIN LINKS l13 ON l13.OBJ_ID = l15.OBJ_ID and l13.DATE_DEL is NULL and l13.PARENT_TYPE_ID = 13
  JOIN VALL Vl ON vl.PARAM_ID = 58 and vl.OBJ_ID = l13.PARENT_ID and vl.LISTVAL_ID in
  (126,1252,119,120,1251,145,121,142,141,99,100,101,102,103,104,105,106,107,108,109,110,111,
  112,113,114,115,116,117,118,66,67,68,69,64,65)
  JOIN VALF  VF ON vF.PARAM_ID = 71 and vF.OBJ_ID = l15.OBJ_ID and vF.VAL > 0 INTO VAL;
   SUSPEND;
  select count(distinct TEACHER_ID) as val12 from PARAGRAF_GRADE_TEACHERS_LIST(:I$OBJ_ID)
  JOIN LINKS l33 on l33.PARENT_ID = TEACHER_ID and l33.DATE_DEL is NULL and l33.OBJ_TYPE_ID = 33
  JOIN VALL  Vl ON vl.PARAM_ID = 284 and vl.OBJ_ID = l33.OBJ_ID and vl.LISTVAL_ID = 620 INTO VAL;
   SUSPEND;
  select count(distinct TEACHER_ID) as val13 from PARAGRAF_GRADE_TEACHERS_LIST(:I$OBJ_ID)
  JOIN LINKS l33 on l33.PARENT_ID = TEACHER_ID and l33.DATE_DEL is NULL and l33.OBJ_TYPE_ID = 33
  JOIN VALL Vl ON vl.PARAM_ID = 284 and vl.OBJ_ID = l33.OBJ_ID and vl.LISTVAL_ID = 622 INTO VAL;
   SUSPEND;
  select count(distinct TEACHER_ID) as val14 from PARAGRAF_GRADE_TEACHERS_LIST(:I$OBJ_ID)
  JOIN LINKS l33 on l33.PARENT_ID = TEACHER_ID and l33.DATE_DEL is NULL and l33.OBJ_TYPE_ID = 33
  JOIN VALL Vl ON vl.PARAM_ID = 284 and vl.OBJ_ID = l33.OBJ_ID and vl.LISTVAL_ID = 624 INTO VAL;
   SUSPEND;
  select count(distinct TEACHER_ID) as val15 from PARAGRAF_GRADE_TEACHERS_LIST(:I$OBJ_ID)
  JOIN LINKS l33 on l33.PARENT_ID = TEACHER_ID and l33.DATE_DEL is NULL and l33.OBJ_TYPE_ID = 33
  JOIN VALL Vl ON vl.PARAM_ID = 284 and vl.OBJ_ID = l33.OBJ_ID and vl.LISTVAL_ID = 623 INTO VAL;
   SUSPEND;
  --select count(distinct TEACHER_ID) as val16 from PARAGRAF_GRADE_TEACHERS_LIST(:I$OBJ_ID)
  --JOIN VALL  Vl ON vl.PARAM_ID = 281 and vl.OBJ_ID = TEACHER_ID and vl.LISTVAL_ID = 635 INTO VAL;
  VAL = 0;
   SUSPEND;
  --select count(distinct TEACHER_ID) as val7 from PARAGRAF_GRADE_TEACHERS_LIST(:I$OBJ_ID)
  --JOIN VALL Vl ON vl.PARAM_ID = 281 and vl.OBJ_ID = TEACHER_ID and vl.LISTVAL_ID = 634 INTO VAL;
  VAL = 0;
   SUSPEND;
  --select count(distinct TEACHER_ID) as val8 from PARAGRAF_GRADE_TEACHERS_LIST(:I$OBJ_ID)
  --JOIN VALL Vl ON vl.PARAM_ID = 281 and vl.OBJ_ID = TEACHER_ID and vl.LISTVAL_ID = 633 INTO VAL;
  VAL = 0;
   SUSPEND;
  select count(distinct TEACHER_ID) as val9 from PARAGRAF_GRADE_TEACHERS_LIST(:I$OBJ_ID)
  JOIN VALL Vl ON vl.PARAM_ID = 280 and vl.OBJ_ID = TEACHER_ID and vl.LISTVAL_ID = 631 INTO VAL;
   SUSPEND;
  select count(distinct TEACHER_ID) as va20 from PARAGRAF_GRADE_TEACHERS_LIST(:I$OBJ_ID)
  JOIN VALL Vl ON vl.PARAM_ID = 280 and vl.OBJ_ID = TEACHER_ID and vl.LISTVAL_ID = 630 INTO VAL;
   SUSPEND;
  select count(distinct TEACHER_ID) as va21 from PARAGRAF_GRADE_TEACHERS_LIST(:I$OBJ_ID)
  JOIN VALL Vl ON vl.PARAM_ID = 280 and vl.OBJ_ID = TEACHER_ID and not vl.LISTVAL_ID IN (630,631,629) INTO VAL;
   SUSPEND;
  select count(distinct TEACHER_ID) as val22 from PARAGRAF_GRADE_TEACHERS_LIST(:I$OBJ_ID)
  JOIN LINKS l39 on l39.PARENT_ID = TEACHER_ID and l39.DATE_DEL is NULL and l39.OBJ_TYPE_ID = 39
  JOIN VALL Vl ON vl.PARAM_ID = 345 and vl.OBJ_ID = l39.OBJ_ID and vl.LISTVAL_ID = 749 INTO VAL;
   SUSPEND;
    select count(distinct TEACHER_ID) as val23 from PARAGRAF_GRADE_TEACHERS_LIST(2000000001)
  JOIN LINKS l39 on l39.PARENT_ID = TEACHER_ID and l39.DATE_DEL is NULL and l39.OBJ_TYPE_ID = 39
  JOIN VALL Vl ON vl.PARAM_ID = 345 and vl.OBJ_ID = l39.OBJ_ID and vl.LISTVAL_ID = 743 INTO VAL;
   SUSPEND;
     select count(distinct TEACHER_ID) as val6 from PARAGRAF_GRADE_TEACHERS_LIST(2000000001)
  JOIN LINKS l40 on l40.PARENT_ID = TEACHER_ID and l40.DATE_DEL is NULL and l40.OBJ_TYPE_ID = 40
  JOIN VALL Vl ON vl.PARAM_ID = 341 and vl.OBJ_ID = l40.OBJ_ID and vl.LISTVAL_ID = 1216 INTO VAL;
   SUSPEND;
   select count(distinct TEACHER_ID) as val6 from PARAGRAF_GRADE_TEACHERS_LIST(2000000001)
  JOIN LINKS l40 on l40.PARENT_ID = TEACHER_ID and l40.DATE_DEL is NULL and l40.OBJ_TYPE_ID = 40
  JOIN VALL Vl ON vl.PARAM_ID = 341 and vl.OBJ_ID = l40.OBJ_ID and not vl.LISTVAL_ID = 1216 INTO VAL;
   SUSPEND;
  if (:V$TMP>0) then BEGIN
  /*Select Count(TEACHER_ID)*100/(select Count(TEACHER_ID) From PARAGRAF_GRADE_TEACHERS_LIST(:I$OBJ_ID)) as val26
  From PARAGRAF_GRADE_TEACHERS_LIST(:I$OBJ_ID)
  JOIN VALL Vl ON vl.PARAM_ID = 281 and vl.OBJ_ID = TEACHER_ID and vl.LISTVAL_ID in (634, 635) INTO VAL;*/
  VAL = 0;
   SUSPEND;
  /*Select Count(TEACHER_ID)*100/(select Count(TEACHER_ID) From PARAGRAF_GRADE_TEACHERS_LIST(:I$OBJ_ID)) as val27
  From PARAGRAF_GRADE_TEACHERS_LIST(:I$OBJ_ID)
  JOIN VALL Vl ON vl.PARAM_ID = 281 and vl.OBJ_ID = TEACHER_ID and vl.LISTVAL_ID = 633 INTO VAL;*/
  VAL = 0;
   SUSPEND;
  END

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_INFOCARD_600 (
    I$OBJ_ID BIGINT)
RETURNS (
    FORM_NAME VARCHAR(10),
    OCH_GR INTEGER,
    OCH_IND INTEGER,
    OCH_ZOCH_VECH INTEGER,
    ZAOCH INTEGER,
    SEME_OBCH INTEGER,
    SAMOBCHTOTEL INTEGER,
    EKST INTEGER,
    TOTAL INTEGER)
AS
DECLARE VARIABLE V$TMP INTEGER;
BEGIN
    FOR
        SELECT DISTINCT
               L9.OBJ_ID

        FROM LINKS L69

        JOIN LINKS L57
        ON L57.PARENT_ID = L69.OBJ_ID
        AND L57.OBJ_TYPE_ID = 57
        AND L57.DATE_DEL IS NULL

        JOIN LINKS L50
        ON L50.PARENT_ID = L57.OBJ_ID
        AND L50.OBJ_TYPE_ID = 50
        AND L50.DATE_DEL IS NULL

        JOIN LINKS L54
        ON L54.PARENT_ID = L50.OBJ_ID
        AND L54.OBJ_TYPE_ID = 54
        AND L54.DATE_DEL IS NULL

        JOIN LINKS L9
        ON L9.PARENT_ID = L54.OBJ_ID
        AND L9.OBJ_TYPE_ID = 9
        AND L9.DATE_DEL IS NULL

        WHERE L69.OBJ_TYPE_ID = 69
        AND L69.DATE_DEL IS NULL
        AND L69.PARENT_ID = :I$OBJ_ID

        INTO V$TMP
    DO
    BEGIN
        SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$TMP) INTO FORM_NAME;

        SELECT COUNT(DISTINCT L10.OBJ_ID)

        FROM LINKS L10

        JOIN VALL VL
        ON VL.PARAM_ID = 80
        AND VL.OBJ_ID = L10.OBJ_ID
        AND VL.LISTVAL_ID = 153

        WHERE L10.OBJ_TYPE_ID = 10
        AND L10.DATE_DEL IS NULL
        AND L10.PARENT_ID = :V$TMP
        INTO OCH_GR;

        SELECT COUNT(DISTINCT L10.OBJ_ID)

        FROM LINKS L10

        JOIN VALL VL
        ON VL.PARAM_ID = 80
        AND VL.OBJ_ID = L10.OBJ_ID
        AND VL.LISTVAL_ID = 1222

        WHERE L10.OBJ_TYPE_ID = 10
        AND L10.DATE_DEL IS NULL
        AND L10.PARENT_ID = :V$TMP
        INTO OCH_IND;

        SELECT COUNT(DISTINCT L10.OBJ_ID)

        FROM LINKS L10

        JOIN VALL VL
        ON VL.PARAM_ID = 80
        AND VL.OBJ_ID = L10.OBJ_ID
        AND VL.LISTVAL_ID = 154

        WHERE L10.OBJ_TYPE_ID = 10
        AND L10.DATE_DEL IS NULL
        AND L10.PARENT_ID = :V$TMP
        INTO  OCH_ZOCH_VECH;

        SELECT COUNT(DISTINCT L10.OBJ_ID)

        FROM LINKS L10

        JOIN VALL VL
        ON VL.PARAM_ID = 80
        AND VL.OBJ_ID = L10.OBJ_ID
        AND VL.LISTVAL_ID = 155

        WHERE L10.OBJ_TYPE_ID = 10
        AND L10.DATE_DEL IS NULL
        AND L10.PARENT_ID = :V$TMP

        INTO   ZAOCH;

        SELECT COUNT(DISTINCT L10.OBJ_ID)

        FROM LINKS L10

        JOIN VALL VL
        ON VL.PARAM_ID = 80
        AND VL.OBJ_ID = L10.OBJ_ID
        AND VL.LISTVAL_ID = 1220

        WHERE L10.OBJ_TYPE_ID = 10
        AND L10.DATE_DEL IS NULL
        AND L10.PARENT_ID = :V$TMP

        INTO SEME_OBCH;

        SELECT COUNT(DISTINCT L10.OBJ_ID)

        FROM LINKS L10

        JOIN VALL VL
        ON VL.PARAM_ID = 80
        AND VL.OBJ_ID = L10.OBJ_ID
        AND VL.LISTVAL_ID = 1221

        WHERE L10.OBJ_TYPE_ID = 10
        AND L10.DATE_DEL IS NULL
        AND L10.PARENT_ID = :V$TMP

        INTO SAMOBCHTOTEL;

        SELECT COUNT(DISTINCT L10.OBJ_ID)

        FROM LINKS L10

        JOIN VALL VL
        ON VL.PARAM_ID = 80
        AND VL.OBJ_ID = L10.OBJ_ID
        AND VL.LISTVAL_ID = 156

        WHERE L10.OBJ_TYPE_ID = 10
        AND L10.DATE_DEL IS NULL
        AND L10.PARENT_ID = :V$TMP

        INTO EKST;

        TOTAL = :OCH_GR + :OCH_IND + :OCH_ZOCH_VECH + :ZAOCH + :SEME_OBCH + :SAMOBCHTOTEL + :EKST;
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_INFOCARD_610 (
    I$OBJ_ID BIGINT)
RETURNS (
    OCH_GR INTEGER,
    OCH_IND INTEGER,
    OCH_ZOCH_VECH INTEGER,
    ZAOCH INTEGER,
    SEME_OBCH INTEGER,
    SAMOBCHTOTEL INTEGER,
    EKST INTEGER,
    TOTAL INTEGER)
AS
DECLARE VARIABLE V$TMP INTEGER;
BEGIN
    SELECT COUNT(L9.OBJ_ID)

    FROM LINKS L69

    JOIN LINKS L57
    ON L57.PARENT_ID = L69.OBJ_ID
    AND L57.OBJ_TYPE_ID = 57
    AND L57.DATE_DEL IS NULL

    JOIN LINKS L50
    ON L50.PARENT_ID = L57.OBJ_ID
    AND L50.OBJ_TYPE_ID = 50
    AND L50.DATE_DEL IS NULL

    JOIN LINKS L54
    ON L54.PARENT_ID = L50.OBJ_ID
    AND L54.OBJ_TYPE_ID = 54
    AND L54.DATE_DEL IS NULL

    JOIN LINKS L9
    ON L9.PARENT_ID = L54.OBJ_ID
    AND L9.OBJ_TYPE_ID = 9
    AND L9.DATE_DEL IS NULL

    LEFT JOIN LINKS L10
    ON L10.PARENT_ID = L9.OBJ_ID
    AND L10.OBJ_TYPE_ID = 10
    AND L10.DATE_DEL IS NULL

    JOIN VALL VL
    ON VL.PARAM_ID = 80
    AND VL.OBJ_ID = L10.OBJ_ID
    AND VL.LISTVAL_ID = 153

    WHERE L69.OBJ_TYPE_ID = 69
    AND L69.DATE_DEL IS NULL
    AND L69.PARENT_ID = :I$OBJ_ID

    INTO OCH_GR;

    SELECT SUM(DISTINCT L9.OBJ_ID)

    FROM LINKS L69

    JOIN LINKS L57
    ON L57.PARENT_ID = L69.OBJ_ID
    AND L57.OBJ_TYPE_ID = 57
    AND L57.DATE_DEL IS NULL

    JOIN LINKS L50
    ON L50.PARENT_ID = L57.OBJ_ID
    AND L50.OBJ_TYPE_ID = 50
    AND L50.DATE_DEL IS NULL

    JOIN LINKS L54
    ON L54.PARENT_ID = L50.OBJ_ID
    AND L54.OBJ_TYPE_ID = 54
    AND L54.DATE_DEL IS NULL

    JOIN LINKS L9
    ON L9.PARENT_ID = L54.OBJ_ID
    AND L9.OBJ_TYPE_ID = 9
    AND L9.DATE_DEL IS NULL

    LEFT JOIN LINKS L10
    ON L10.PARENT_ID = L9.OBJ_ID
    AND L10.OBJ_TYPE_ID = 10
    AND L10.DATE_DEL IS NULL

    JOIN VALL VL
    ON VL.PARAM_ID = 80
    AND VL.OBJ_ID = L10.OBJ_ID
    AND VL.LISTVAL_ID = 1222

    WHERE L69.OBJ_TYPE_ID = 69
    AND L69.DATE_DEL IS NULL
    AND L69.PARENT_ID = :I$OBJ_ID

    INTO OCH_IND;

    SELECT COUNT(DISTINCT L9.OBJ_ID)

    FROM LINKS L69

    JOIN LINKS L57
    ON L57.PARENT_ID = L69.OBJ_ID
    AND L57.OBJ_TYPE_ID = 57
    AND L57.DATE_DEL IS NULL

    JOIN LINKS L50
    ON L50.PARENT_ID = L57.OBJ_ID
    AND L50.OBJ_TYPE_ID = 50
    AND L50.DATE_DEL IS NULL

    JOIN LINKS L54
    ON L54.PARENT_ID = L50.OBJ_ID
    AND L54.OBJ_TYPE_ID = 54
    AND L54.DATE_DEL IS NULL

    JOIN LINKS L9
    ON L9.PARENT_ID = L54.OBJ_ID
    AND L9.OBJ_TYPE_ID = 9
    AND L9.DATE_DEL IS NULL

    LEFT JOIN LINKS L10
    ON L10.PARENT_ID = L9.OBJ_ID
    AND L10.OBJ_TYPE_ID = 10
    AND L10.DATE_DEL IS NULL

    JOIN VALL VL
    ON VL.PARAM_ID = 80
    AND VL.OBJ_ID = L10.OBJ_ID
    AND VL.LISTVAL_ID = 154

    WHERE L69.OBJ_TYPE_ID = 69
    AND L69.DATE_DEL IS NULL
    AND L69.PARENT_ID = :I$OBJ_ID

    INTO OCH_ZOCH_VECH;

    SELECT COUNT(DISTINCT L9.OBJ_ID)

    FROM LINKS L69

    JOIN LINKS L57
    ON L57.PARENT_ID = L69.OBJ_ID
    AND L57.OBJ_TYPE_ID = 57
    AND L57.DATE_DEL IS NULL

    JOIN LINKS L50
    ON L50.PARENT_ID = L57.OBJ_ID
    AND L50.OBJ_TYPE_ID = 50
    AND L50.DATE_DEL IS NULL

    JOIN LINKS L54
    ON L54.PARENT_ID = L50.OBJ_ID
    AND L54.OBJ_TYPE_ID = 54
    AND L54.DATE_DEL IS NULL

    JOIN LINKS L9
    ON L9.PARENT_ID = L54.OBJ_ID
    AND L9.OBJ_TYPE_ID = 9
    AND L9.DATE_DEL IS NULL

    LEFT JOIN LINKS L10
    ON L10.PARENT_ID = L9.OBJ_ID
    AND L10.OBJ_TYPE_ID = 10
    AND L10.DATE_DEL IS NULL

    JOIN VALL VL
    ON VL.PARAM_ID = 80
    AND VL.OBJ_ID = L10.OBJ_ID
    AND VL.LISTVAL_ID = 155

    WHERE L69.OBJ_TYPE_ID = 69
    AND L69.DATE_DEL IS NULL
    AND L69.PARENT_ID = :I$OBJ_ID

    INTO  ZAOCH;

    SELECT COUNT(DISTINCT L9.OBJ_ID)

    FROM LINKS L69

    JOIN LINKS L57
    ON L57.PARENT_ID = L69.OBJ_ID
    AND L57.OBJ_TYPE_ID = 57
    AND L57.DATE_DEL IS NULL

    JOIN LINKS L50
    ON L50.PARENT_ID = L57.OBJ_ID
    AND L50.OBJ_TYPE_ID = 50
    AND L50.DATE_DEL IS NULL

    JOIN LINKS L54
    ON L54.PARENT_ID = L50.OBJ_ID
    AND L54.OBJ_TYPE_ID = 54
    AND L54.DATE_DEL IS NULL

    JOIN LINKS L9
    ON L9.PARENT_ID = L54.OBJ_ID
    AND L9.OBJ_TYPE_ID = 9
    AND L9.DATE_DEL IS NULL

    LEFT JOIN LINKS L10
    ON L10.PARENT_ID = L9.OBJ_ID
    AND L10.OBJ_TYPE_ID = 10
    AND L10.DATE_DEL IS NULL

    JOIN VALL VL
    ON VL.PARAM_ID = 80
    AND VL.OBJ_ID = L10.OBJ_ID
    AND VL.LISTVAL_ID = 1220

    WHERE L69.OBJ_TYPE_ID = 69
    AND L69.DATE_DEL IS NULL
    AND L69.PARENT_ID = :I$OBJ_ID

    INTO SEME_OBCH;

    SELECT COUNT(DISTINCT L9.OBJ_ID)

    FROM LINKS L69

    JOIN LINKS L57
    ON L57.PARENT_ID = L69.OBJ_ID
    AND L57.OBJ_TYPE_ID = 57
    AND L57.DATE_DEL IS NULL

    JOIN LINKS L50
    ON L50.PARENT_ID = L57.OBJ_ID
    AND L50.OBJ_TYPE_ID = 50
    AND L50.DATE_DEL IS NULL

    JOIN LINKS L54
    ON L54.PARENT_ID = L50.OBJ_ID
    AND L54.OBJ_TYPE_ID = 54
    AND L54.DATE_DEL IS NULL

    JOIN LINKS L9
    ON L9.PARENT_ID = L54.OBJ_ID
    AND L9.OBJ_TYPE_ID = 9
    AND L9.DATE_DEL IS NULL

    LEFT JOIN LINKS L10
    ON L10.PARENT_ID = L9.OBJ_ID
    AND L10.OBJ_TYPE_ID = 10
    AND L10.DATE_DEL IS NULL

    JOIN VALL VL
    ON VL.PARAM_ID = 80
    AND VL.OBJ_ID = L10.OBJ_ID
    AND VL.LISTVAL_ID = 1221

    WHERE L69.OBJ_TYPE_ID = 69
    AND L69.DATE_DEL IS NULL
    AND L69.PARENT_ID = :I$OBJ_ID

    INTO SAMOBCHTOTEL;

    SELECT COUNT(DISTINCT L9.OBJ_ID)

    FROM LINKS L69

    JOIN LINKS L57
    ON L57.PARENT_ID = L69.OBJ_ID
    AND L57.OBJ_TYPE_ID = 57
    AND L57.DATE_DEL IS NULL

    JOIN LINKS L50
    ON L50.PARENT_ID = L57.OBJ_ID
    AND L50.OBJ_TYPE_ID = 50
    AND L50.DATE_DEL IS NULL

    JOIN LINKS L54
    ON L54.PARENT_ID = L50.OBJ_ID
    AND L54.OBJ_TYPE_ID = 54
    AND L54.DATE_DEL IS NULL

    JOIN LINKS L9
    ON L9.PARENT_ID = L54.OBJ_ID
    AND L9.OBJ_TYPE_ID = 9
    AND L9.DATE_DEL IS NULL

    LEFT JOIN LINKS L10
    ON L10.PARENT_ID = L9.OBJ_ID
    AND L10.OBJ_TYPE_ID = 10
    AND L10.DATE_DEL IS NULL

    JOIN VALL VL
    ON VL.PARAM_ID = 80
    AND VL.OBJ_ID = L10.OBJ_ID
    AND VL.LISTVAL_ID = 156

    WHERE L69.OBJ_TYPE_ID = 69
    AND L69.DATE_DEL IS NULL
    AND L69.PARENT_ID = :I$OBJ_ID

    INTO EKST;

    TOTAL = :OCH_GR + :OCH_IND + :OCH_ZOCH_VECH + :ZAOCH + :SEME_OBCH + :SAMOBCHTOTEL + :EKST;
    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_MOVEMENT_DOU (
    I$OBJ_ID BIGINT,
    I$DT DATE)
RETURNS (
    C1 VARCHAR(100),
    C2 VARCHAR(500),
    C3 VARCHAR(100),
    C4 VARCHAR(5),
    C5 INTEGER,
    C6 INTEGER,
    C7 INTEGER,
    C8 INTEGER)
AS
declare variable V$STEP_ID bigint;
declare variable V$COUNT_STEP smallint;
declare variable V$KOD_GROUP_ID bigint;
declare variable V$VID_GROUP_ID bigint;
declare variable V$Y smallint;
declare variable V$M smallint;
declare variable V$BDT date;
declare variable V$NDT date;
declare variable V$C5 integer;
declare variable V$C6 integer;
declare variable V$C7 integer;
declare variable V$C8 integer;
declare variable V$C5_ integer;
declare variable V$C6_ integer;
declare variable V$C7_ integer;
declare variable V$C8_ integer;
BEGIN
  V$COUNT_STEP = 0;
  V$C5_ = 0;
  V$C6_ = 0;
  V$C7_ = 0;
  V$C8_ = 0;
  V$Y = EXTRACT(YEAR FROM I$DT);
  V$M = EXTRACT(MONTH FROM I$DT);
  V$BDT = :V$Y || '-' || :V$M || '-' || '01';
  V$M = :V$M + 1;
  IF (V$M = 13) THEN
  BEGIN
    V$M = 1;
    V$Y = V$Y + 1;
  END
  V$NDT = :V$Y || '-' || :V$M || '-' || '01';

  FOR
    SELECT L7.OBJ_ID
    FROM LINKS L7
    WHERE L7.PARENT_ID = :I$OBJ_ID AND L7.DATE_DEL IS NULL AND L7.OBJ_TYPE_ID = 7
    INTO :V$STEP_ID
  DO
  BEGIN
    V$C5 = 0;
    V$C6 = 0;
    V$C7 = 0;
    V$C8 = 0;
    V$COUNT_STEP = :V$COUNT_STEP + 1;
    SELECT V
    FROM VAL_GET(:V$STEP_ID, 43)
    INTO :C1;
    FOR
      SELECT L8.OBJ_ID
      FROM LINKS L8
      WHERE L8.PARENT_ID = :V$STEP_ID AND L8.DATE_DEL IS NULL AND L8.OBJ_TYPE_ID = 8
      INTO :V$KOD_GROUP_ID
    DO
    BEGIN
      FOR
        SELECT L9.OBJ_ID
        FROM LINKS L9
        WHERE L9.PARENT_ID = :V$KOD_GROUP_ID AND L9.DATE_DEL IS NULL AND L9.OBJ_TYPE_ID = 9
        INTO :V$VID_GROUP_ID
      DO
      BEGIN
        SELECT V
        FROM VAL_GET(:V$VID_GROUP_ID, 555)
        INTO :C2;

        SELECT V
        FROM VAL_GET(:V$VID_GROUP_ID, 1549)
        INTO :C3;

        SELECT V
        FROM VAL_GET(:V$VID_GROUP_ID, 1558)
        INTO :C4;

        C5 = 0;
        C6 = 0;
        C7 = 0;
        C8 = 0;

        -- На начало месяца
        SELECT COUNT(DISTINCT VAL1 || VAL2)
        FROM CLASS_FILLDET(:V$VID_GROUP_ID, :V$BDT - 1)
        INTO :C5;

        -- На конец месяца
        SELECT COUNT(DISTINCT VAL1 || VAL2)
        FROM CLASS_FILLDET(:V$VID_GROUP_ID, :V$NDT - 1)
        INTO :C8;

        -- Прибыло
        SELECT COUNT(DISTINCT M.PERSON_ID)
        FROM PERSON_MOVEMENTS M
        WHERE M.DATE_DEL IS NULL AND M.GROUP_ID = :V$VID_GROUP_ID AND M.REASON_IN IN (810, 3276, 3277, 3278) AND M.DATE_IN >= :V$BDT AND M.DATE_IN < :V$NDT
        INTO :C7;

        C6 = C5 - C8 + C7;
        V$C5 = V$C5 + C5;
        V$C6 = V$C6 + C6;
        V$C7 = V$C7 + C7;
        V$C8 = V$C8 + C8;
        SUSPEND;
      END
    end
    C3 = 'Итого ' || :C1;
    C1 = '';
    C2 = '';
    C4 = '';
    V$C5_ = V$C5_ + V$C5;
    V$C6_ = V$C6_ + V$C6;
    V$C7_ = V$C7_ + V$C7;
    V$C8_ = V$C8_ + V$C8;
    C5 = V$C5;
    C6 = V$C6;
    C7 = V$C7;
    C8 = V$C8;
    SUSPEND;
  END
  C1 = '';
  C2 = '';
  C3 = '';
  C4 = '';
  C5 = NULL;
  C6 = NULL;
  C7 = NULL;
  C8 = NULL;
  SUSPEND;
  C3 = 'Итого по ОООД';
  C5 = V$C5_;
  C6 = V$C6_;
  C7 = V$C7_;
  C8 = V$C8_;
  SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_MOVEMENT_JOURNAL (
    I$DISTR_ID BIGINT,
    I$FROM DATE,
    I$TO DATE)
RETURNS (
    SCHOOLAR_ID BIGINT,
    PUPIL VARCHAR(100),
    SEX VARCHAR(8),
    DATE_BIRTHDAY DATE,
    DATE_OUT DATE,
    OUT_OU VARCHAR(500),
    OUT_CLASS VARCHAR(50),
    OUT_TYPE_CLASS VARCHAR(255),
    OUT_NUM_ORDER VARCHAR(50),
    OUT_DATE_ORDER DATE,
    OUT_IS VARCHAR(100),
    OUT_OU_VID VARCHAR(255),
    OUT_OU_SHORT VARCHAR(500),
    OUT_OU_LEGAL VARCHAR(100),
    OUT_OU_DISTRICT VARCHAR(50),
    OUT_OU_DISTRICT_ID BIGINT,
    DATE_IN DATE,
    IN_OU VARCHAR(500),
    IN_CLASS VARCHAR(50),
    IN_TYPE_CLASS VARCHAR(255),
    IN_NUM_ORDER VARCHAR(50),
    IN_DATE_ORDER DATE,
    IN_IS VARCHAR(100),
    IN_OU_VID VARCHAR(255),
    IN_OU_SHORT VARCHAR(500),
    IN_OU_LEGAL VARCHAR(100),
    IN_OU_DISTRICT VARCHAR(50),
    IN_OU_DISTRICT_ID BIGINT,
    LINK_ID BIGINT,
    TYPE_ SMALLINT)
AS
DECLARE VARIABLE V$SCHOOL_ID BIGINT;
DECLARE VARIABLE V$MOVEMENT_ID BIGINT;
BEGIN
    /* out */

    FOR SELECT L2.OBJ_ID, L10.OBJ_ID, L76.OBJ_ID, DT.VAL, L10.LINK_ID
        FROM LINKS L2
        INNER JOIN LINKS L78 ON L78.PARENT_ID = L2.OBJ_ID
        INNER JOIN LINKS L82 ON L82.PARENT_ID = L78.OBJ_ID
        INNER JOIN LINKS L10 ON L10.PARENT_ID = L82.OBJ_ID
        INNER JOIN LINKS L76 ON L76.PARENT_ID = L10.OBJ_ID
        INNER JOIN VALL VLL ON VLL.OBJ_ID = L76.OBJ_ID
        INNER JOIN VALD DT ON DT.OBJ_ID = L76.OBJ_ID
        WHERE L2.PARENT_ID = :I$DISTR_ID
          AND L2.OBJ_TYPE_ID = 2
          AND L2.DATE_DEL IS NULL
          AND L78.OBJ_TYPE_ID = 78
          AND L78.DATE_DEL IS NULL
          AND L82.OBJ_TYPE_ID IN (82, 83) /* eugene */
          AND L82.DATE_DEL IS NULL
          AND L10.OBJ_TYPE_ID = 10
          AND L10.DATE_DEL IS NULL
          AND L76.OBJ_TYPE_ID = 76
          AND L76.DATE_DEL IS NULL
          AND VLL.PARAM_ID = 432
          AND VLL.IS_DEL = 0
          AND VLL.LISTVAL_ID IN (811, 812) /* vibil and okonchil */
          AND DT.PARAM_ID = 433
          AND DT.IS_DEL = 0
          AND DT.VAL >= :I$FROM
          AND DT.VAL <= :I$TO
        INTO :V$SCHOOL_ID, :SCHOOLAR_ID, :V$MOVEMENT_ID, :DATE_OUT, :LINK_ID
    DO
    BEGIN
        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:SCHOOLAR_ID)
        INTO :PUPIL;

        SELECT V
        FROM VAL_GET(:V$MOVEMENT_ID, 434)
        INTO :OUT_NUM_ORDER;

        SELECT D
        FROM VAL_GET(:V$MOVEMENT_ID, 435)
        INTO :OUT_DATE_ORDER;

        SELECT V
        FROM VAL_GET(:V$SCHOOL_ID, 2)
        INTO :OUT_OU;

        SELECT V
        FROM VAL_GET(:V$MOVEMENT_ID, 1350)
        INTO :OUT_TYPE_CLASS;

        SELECT V
        FROM VAL_GET(:SCHOOLAR_ID, 88)
        INTO :SEX;

        SELECT D
        FROM VAL_GET(:SCHOOLAR_ID, 89)
        INTO :DATE_BIRTHDAY;

        SELECT V
        FROM VAL_GET(:SCHOOLAR_ID, 105)
        INTO :OUT_IS;

        SELECT V
        FROM VAL_GET(:SCHOOLAR_ID, 107)
        INTO :OUT_OU_VID;

        SELECT V
        FROM VAL_GET(:SCHOOLAR_ID, 161)
        INTO :OUT_OU_SHORT;

        SELECT V
        FROM VAL_GET(:SCHOOLAR_ID, 188)
        INTO :OUT_OU_LEGAL;

        SELECT V, I
        FROM VAL_GET(:SCHOOLAR_ID, 1346)
        INTO :OUT_OU_DISTRICT, :OUT_OU_DISTRICT_ID;

        OUT_CLASS = '';

        SELECT FIRST 1 V437.VAL
        FROM LINKS L76
        INNER JOIN VALL VLL ON VLL.OBJ_ID = L76.OBJ_ID
        INNER JOIN VALD DT ON DT.OBJ_ID = L76.OBJ_ID
        LEFT JOIN VALS V437 ON V437.OBJ_ID = L76.OBJ_ID
        WHERE L76.PARENT_ID = :SCHOOLAR_ID
          AND L76.OBJ_TYPE_ID = 76
          AND L76.DATE_DEL IS NULL
          AND VLL.PARAM_ID = 432
          AND VLL.IS_DEL = 0
          AND VLL.LISTVAL_ID >= 805
          AND VLL.LISTVAL_ID <= 810 /* TRANSFERED AND ACCEPTED */
          AND DT.PARAM_ID = 433
          AND DT.IS_DEL = 0
          AND DT.VAL <= :DATE_OUT
          AND V437.PARAM_ID = 437
          AND V437.IS_DEL = 0
        ORDER BY DT.VAL DESC
        INTO :OUT_CLASS;

        TYPE_ = 0;
        SUSPEND;
    END

    /* in */

    DATE_OUT = NULL;
    OUT_OU = NULL;
    OUT_CLASS = NULL;
    OUT_TYPE_CLASS = NULL;
    OUT_NUM_ORDER = NULL;
    OUT_DATE_ORDER = NULL;
    OUT_IS = NULL;
    OUT_OU_VID = NULL;
    OUT_OU_SHORT = NULL;
    OUT_OU_LEGAL = NULL;
    OUT_OU_DISTRICT = NULL;

    FOR SELECT L2.OBJ_ID, L10.OBJ_ID, L76.OBJ_ID, DT.VAL, L10.LINK_ID
        FROM LINKS L2
        INNER JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID
        INNER JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID
        INNER JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID
        INNER JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID
        INNER JOIN LINKS L76 ON L76.PARENT_ID = L10.OBJ_ID
        INNER JOIN VALL VLL ON VLL.OBJ_ID = L76.OBJ_ID
        INNER JOIN VALD DT ON DT.OBJ_ID = L76.OBJ_ID
        WHERE L2.PARENT_ID = :I$DISTR_ID
          AND L2.OBJ_TYPE_ID = 2
          AND L2.DATE_DEL IS NULL
          AND L7.OBJ_TYPE_ID = 7
          AND L7.DATE_DEL IS NULL
          AND L8.OBJ_TYPE_ID = 8
          AND L8.DATE_DEL IS NULL
          AND L9.OBJ_TYPE_ID = 9
          AND L9.DATE_DEL IS NULL
          AND L10.OBJ_TYPE_ID = 10
          AND L10.DATE_DEL IS NULL
          AND L76.OBJ_TYPE_ID = 76
          AND L76.DATE_DEL IS NULL
          AND VLL.PARAM_ID = 432
          AND VLL.IS_DEL = 0
          AND VLL.LISTVAL_ID IN (805, 806) /* eugene */
          AND DT.PARAM_ID = 433
          AND DT.IS_DEL = 0
          AND DT.VAL >= :I$FROM
          AND DT.VAL <= :I$TO
        ORDER BY DT.VAL
        INTO :V$SCHOOL_ID, :SCHOOLAR_ID, :V$MOVEMENT_ID, :DATE_IN, :LINK_ID
    DO
    BEGIN
        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:SCHOOLAR_ID)
        INTO :PUPIL;

        SELECT V
        FROM VAL_GET(:V$MOVEMENT_ID, 434)
        INTO :IN_NUM_ORDER;

        SELECT V
        FROM VAL_GET(:SCHOOLAR_ID, 88)
        INTO :SEX;

        SELECT D
        FROM VAL_GET(:SCHOOLAR_ID, 89)
        INTO :DATE_BIRTHDAY;

        SELECT V
        FROM VAL_GET(:V$MOVEMENT_ID, 1350)
        INTO :IN_TYPE_CLASS;

        SELECT D
        FROM VAL_GET(:V$MOVEMENT_ID, 435)
        INTO :IN_DATE_ORDER;

        SELECT V
        FROM VAL_GET(:SCHOOLAR_ID, 78)
        INTO :IN_IS;

        SELECT V
        FROM VAL_GET(:SCHOOLAR_ID, 104)
        INTO :IN_OU_VID;

        SELECT V
        FROM VAL_GET(:SCHOOLAR_ID, 117)
        INTO :IN_OU_SHORT;

        SELECT V
        FROM VAL_GET(:V$SCHOOL_ID, 2)
        INTO :IN_OU;
        SELECT V
        FROM VAL_GET(:V$MOVEMENT_ID, 437)
        INTO :IN_CLASS;

        SELECT V
        FROM VAL_GET(:SCHOOLAR_ID, 160)
        INTO :IN_OU_LEGAL;

        SELECT V, I
        FROM VAL_GET(:SCHOOLAR_ID, 1345)
        INTO :IN_OU_DISTRICT, :IN_OU_DISTRICT_ID;

        DATE_OUT = DATE_IN;
        TYPE_ = 1;
        SUSPEND;
    END

    FOR SELECT L2.OBJ_ID, L10.OBJ_ID, L76.OBJ_ID, DT.VAL, L10.LINK_ID
        FROM LINKS L2
        INNER JOIN LINKS L78 ON L78.PARENT_ID = L2.OBJ_ID
        INNER JOIN LINKS L82 ON L82.PARENT_ID = L78.OBJ_ID
        INNER JOIN LINKS L10 ON L10.PARENT_ID = L82.OBJ_ID
        INNER JOIN LINKS L76 ON L76.PARENT_ID = L10.OBJ_ID
        INNER JOIN VALL VLL ON VLL.OBJ_ID = L76.OBJ_ID
        INNER JOIN VALD DT ON DT.OBJ_ID = L76.OBJ_ID
        WHERE L2.PARENT_ID = :I$DISTR_ID
          AND L2.OBJ_TYPE_ID = 2
          AND L2.DATE_DEL IS NULL
          AND L78.OBJ_TYPE_ID = 78
          AND L78.DATE_DEL IS NULL
          AND L82.OBJ_TYPE_ID IN (82, 83) /* eugene */
          AND L82.DATE_DEL IS NULL
          AND L10.OBJ_TYPE_ID = 10
          AND L10.DATE_DEL IS NULL
          AND L76.OBJ_TYPE_ID = 76
          AND L76.DATE_DEL IS NULL
          AND VLL.PARAM_ID = 432
          AND VLL.IS_DEL = 0
          AND VLL.LISTVAL_ID IN (805, 806) /* eugene */
          AND DT.PARAM_ID = 433
          AND DT.IS_DEL = 0
          AND DT.VAL >= :I$FROM
          AND DT.VAL <= :I$TO
        ORDER BY DT.VAL
        INTO :V$SCHOOL_ID, :SCHOOLAR_ID, :V$MOVEMENT_ID, :DATE_IN, :LINK_ID
    DO
    BEGIN
        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:SCHOOLAR_ID)
        INTO :PUPIL;

        SELECT V
        FROM VAL_GET(:V$MOVEMENT_ID, 434)
        INTO :IN_NUM_ORDER;

        SELECT D
        FROM VAL_GET(:V$MOVEMENT_ID, 435)
        INTO :IN_DATE_ORDER;

        SELECT V
        FROM VAL_GET(:SCHOOLAR_ID, 88)
        INTO :SEX;

        SELECT D
        FROM VAL_GET(:SCHOOLAR_ID, 89)
        INTO :DATE_BIRTHDAY;

        SELECT V
        FROM VAL_GET(:V$MOVEMENT_ID, 1350)
        INTO :IN_TYPE_CLASS;

        SELECT V
        FROM VAL_GET(:SCHOOLAR_ID, 78)
        INTO :IN_IS;

        SELECT V
        FROM VAL_GET(:SCHOOLAR_ID, 104)
        INTO :IN_OU_VID;

        SELECT V
        FROM VAL_GET(:SCHOOLAR_ID, 117)
        INTO :IN_OU_SHORT;

        SELECT V
        FROM VAL_GET(:V$SCHOOL_ID, 2)
        INTO :IN_OU;

        SELECT V
        FROM VAL_GET(:V$MOVEMENT_ID, 437)
        INTO :IN_CLASS;

        SELECT V
        FROM VAL_GET(:SCHOOLAR_ID, 160)
        INTO :IN_OU_LEGAL;

        SELECT V, I
        FROM VAL_GET(:SCHOOLAR_ID, 1345)
        INTO :IN_OU_DISTRICT, :IN_OU_DISTRICT_ID;

        DATE_OUT = DATE_IN;
        TYPE_ = 1;
        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_MOVEMENT_JOURNAL_SVOD (
    I$DISTR_ID BIGINT,
    I$FROM DATE,
    I$TO DATE)
RETURNS (
    SCHOOLAR_ID BIGINT,
    PUPIL VARCHAR(100),
    SEX VARCHAR(8),
    DATE_BIRTHDAY DATE,
    DATE_OUT DATE,
    OUT_OU VARCHAR(500),
    OUT_CLASS VARCHAR(50),
    OUT_TYPE_CLASS VARCHAR(255),
    OUT_NUM_ORDER VARCHAR(50),
    OUT_DATE_ORDER DATE,
    OUT_IS VARCHAR(100),
    OUT_OU_VID VARCHAR(255),
    OUT_OU_SHORT VARCHAR(500),
    OUT_OU_LEGAL VARCHAR(100),
    OUT_OU_DISTRICT VARCHAR(50),
    OUT_OU_DISTRICT_ID BIGINT,
    DATE_IN DATE,
    IN_OU VARCHAR(500),
    IN_CLASS VARCHAR(50),
    IN_TYPE_CLASS VARCHAR(255),
    IN_NUM_ORDER VARCHAR(50),
    IN_DATE_ORDER DATE,
    IN_IS VARCHAR(100),
    IN_OU_VID VARCHAR(255),
    IN_OU_SHORT VARCHAR(500),
    IN_OU_LEGAL VARCHAR(100),
    IN_OU_DISTRICT VARCHAR(50),
    IN_OU_DISTRICT_ID BIGINT,
    LINK_ID BIGINT,
    INCORRECT_ROW SMALLINT)
AS
DECLARE VARIABLE V$SCHOOLAR_ID BIGINT;
DECLARE VARIABLE V$PUPIL VARCHAR(100);
DECLARE VARIABLE V$SEX VARCHAR(8);
DECLARE VARIABLE V$DATE_BIRTHDAY DATE;
DECLARE VARIABLE V$DATE_OUT DATE;
DECLARE VARIABLE V$DATE_IN DATE;
DECLARE VARIABLE V$OUT_OU VARCHAR(500);
DECLARE VARIABLE V$OUT_CLASS VARCHAR(50);
DECLARE VARIABLE V$OUT_TYPE_CLASS VARCHAR(255);
DECLARE VARIABLE V$OUT_NUM_ORDER VARCHAR(50);
DECLARE VARIABLE V$OUT_DATE_ORDER DATE;
DECLARE VARIABLE V$OUT_IS VARCHAR(100);
DECLARE VARIABLE V$OUT_OU_VID VARCHAR(255);
DECLARE VARIABLE V$OUT_OU_SHORT VARCHAR(500);
DECLARE VARIABLE V$OUT_OU_LEGAL VARCHAR(100);
DECLARE VARIABLE V$OUT_OU_DISTRICT VARCHAR(50);
DECLARE VARIABLE V$OUT_OU_DISTRICT_ID BIGINT;
DECLARE VARIABLE V$IN_OU VARCHAR(500);
DECLARE VARIABLE V$IN_CLASS VARCHAR(50);
DECLARE VARIABLE V$IN_TYPE_CLASS VARCHAR(255);
DECLARE VARIABLE V$IN_NUM_ORDER VARCHAR(50);
DECLARE VARIABLE V$IN_DATE_ORDER DATE;
DECLARE VARIABLE V$IN_IS VARCHAR(100);
DECLARE VARIABLE V$IN_OU_VID VARCHAR(255);
DECLARE VARIABLE V$IN_OU_SHORT VARCHAR(500);
DECLARE VARIABLE V$IN_OU_LEGAL VARCHAR(100);
DECLARE VARIABLE V$IN_OU_DISTRICT VARCHAR(50);
DECLARE VARIABLE V$IN_OU_DISTRICT_ID BIGINT;
DECLARE VARIABLE V$LINK_ID BIGINT;
DECLARE VARIABLE V$TYPE_ SMALLINT;
DECLARE VARIABLE CHECK_NEXT_ROW SMALLINT;
DECLARE VARIABLE DISTRICT_LISTVAL_ID BIGINT;
BEGIN
    CHECK_NEXT_ROW = 0;

    SELECT I
    FROM VAL_GET(:I$DISTR_ID, 665)
    INTO :DISTRICT_LISTVAL_ID;

    FOR SELECT SCHOOLAR_ID, PUPIL, SEX, DATE_BIRTHDAY, DATE_OUT, DATE_IN, OUT_OU, OUT_CLASS, OUT_TYPE_CLASS, OUT_NUM_ORDER, OUT_DATE_ORDER, OUT_IS, OUT_OU_VID,
               OUT_OU_SHORT, OUT_OU_LEGAL, OUT_OU_DISTRICT, OUT_OU_DISTRICT_ID, IN_OU, IN_CLASS, IN_TYPE_CLASS, IN_NUM_ORDER, IN_DATE_ORDER, IN_IS, IN_OU_VID,
               IN_OU_SHORT, IN_OU_LEGAL, IN_OU_DISTRICT, IN_OU_DISTRICT_ID, LINK_ID, TYPE_
        FROM R_MOVEMENT_JOURNAL(:I$DISTR_ID, :I$FROM, :I$TO)
        ORDER BY PUPIL, DATE_BIRTHDAY, DATE_OUT
        INTO V$SCHOOLAR_ID, V$PUPIL, V$SEX, V$DATE_BIRTHDAY, V$DATE_OUT, V$DATE_IN, V$OUT_OU, V$OUT_CLASS, V$OUT_TYPE_CLASS, V$OUT_NUM_ORDER, V$OUT_DATE_ORDER, V$OUT_IS,
             V$OUT_OU_VID, V$OUT_OU_SHORT, V$OUT_OU_LEGAL, V$OUT_OU_DISTRICT, V$OUT_OU_DISTRICT_ID, V$IN_OU, V$IN_CLASS, V$IN_TYPE_CLASS, V$IN_NUM_ORDER, V$IN_DATE_ORDER,
             V$IN_IS, V$IN_OU_VID, V$IN_OU_SHORT, V$IN_OU_LEGAL, V$IN_OU_DISTRICT, V$IN_OU_DISTRICT_ID, V$LINK_ID, V$TYPE_
    DO
    BEGIN
        INCORRECT_ROW = 0;

        IF (V$TYPE_ = 0) THEN
        BEGIN
            /* out */
            IF (CHECK_NEXT_ROW = 1) THEN
                SUSPEND;

            SCHOOLAR_ID = V$SCHOOLAR_ID;
            PUPIL = V$PUPIL;
            SEX = V$SEX;
            DATE_BIRTHDAY = V$DATE_BIRTHDAY;
            DATE_OUT = V$DATE_OUT;
            OUT_OU = V$OUT_OU;
            OUT_CLASS = V$OUT_CLASS;
            OUT_TYPE_CLASS = V$OUT_TYPE_CLASS;
            OUT_NUM_ORDER = V$OUT_NUM_ORDER;
            OUT_DATE_ORDER = V$OUT_DATE_ORDER;
            OUT_IS = V$OUT_IS;
            OUT_OU_VID = V$OUT_OU_VID;
            OUT_OU_SHORT = V$OUT_OU_SHORT;
            OUT_OU_LEGAL = V$OUT_OU_LEGAL;
            OUT_OU_DISTRICT = V$OUT_OU_DISTRICT;
            OUT_OU_DISTRICT_ID = V$OUT_OU_DISTRICT_ID;
            DATE_IN = NULL;
            IN_OU = NULL;
            IN_CLASS = NULL;
            IN_TYPE_CLASS = NULL;
            IN_NUM_ORDER = NULL;
            IN_DATE_ORDER = NULL;
            IN_IS = NULL;
            IN_OU_VID = NULL;
            IN_OU_SHORT = NULL;
            IN_OU_LEGAL = NULL;
            IN_OU_DISTRICT = NULL;
            IN_OU_DISTRICT_ID = NULL;
            LINK_ID = V$LINK_ID;

            CHECK_NEXT_ROW = 1;
        END
        ELSE
        BEGIN
            /* in */

            IF ((V$PUPIL = PUPIL) AND (V$SEX = SEX) AND (V$DATE_BIRTHDAY = DATE_BIRTHDAY) AND (V$IN_OU_DISTRICT = OUT_OU_DISTRICT) AND ((V$IN_OU_SHORT = OUT_OU) OR (V$IN_OU = OUT_OU_SHORT))) THEN
            BEGIN
                SCHOOLAR_ID = V$SCHOOLAR_ID;
                PUPIL = V$PUPIL;
                SEX = V$SEX;
                DATE_BIRTHDAY = V$DATE_BIRTHDAY;
                DATE_IN = V$DATE_IN;
                IN_OU = V$IN_OU;
                IN_CLASS = V$IN_CLASS;
                IN_TYPE_CLASS = V$IN_TYPE_CLASS;
                IN_NUM_ORDER = V$IN_NUM_ORDER;
                IN_DATE_ORDER = V$IN_DATE_ORDER;
                IN_IS = V$IN_IS;
                IN_OU_VID = V$IN_OU_VID;
                IN_OU_SHORT = V$IN_OU_SHORT;
                IN_OU_LEGAL = V$IN_OU_LEGAL;
                IN_OU_DISTRICT = V$IN_OU_DISTRICT;
                IN_OU_DISTRICT_ID = V$IN_OU_DISTRICT_ID;
                LINK_ID = V$LINK_ID;

                SUSPEND;
            END
            ELSE
            BEGIN
                IF (CHECK_NEXT_ROW = 1) THEN
                BEGIN
                    IF (OUT_OU_DISTRICT_ID = DISTRICT_LISTVAL_ID) THEN
                    BEGIN
                        INCORRECT_ROW = 1;
                    END
                    SUSPEND;
                END

                SCHOOLAR_ID = V$SCHOOLAR_ID;
                PUPIL = V$PUPIL;
                SEX = V$SEX;
                DATE_BIRTHDAY = V$DATE_BIRTHDAY;
                DATE_OUT = NULL;
                OUT_OU = NULL;
                OUT_CLASS = NULL;
                OUT_TYPE_CLASS = NULL;
                OUT_NUM_ORDER = NULL;
                OUT_DATE_ORDER = NULL;
                OUT_IS = NULL;
                OUT_OU_VID = NULL;
                OUT_OU_SHORT = NULL;
                OUT_OU_LEGAL = NULL;
                OUT_OU_DISTRICT = NULL;
                OUT_OU_DISTRICT_ID = NULL;
                DATE_IN = V$DATE_IN;
                IN_OU = V$IN_OU;
                IN_CLASS = V$IN_CLASS;
                IN_TYPE_CLASS = V$IN_TYPE_CLASS;
                IN_NUM_ORDER = V$IN_NUM_ORDER;
                IN_DATE_ORDER = V$IN_DATE_ORDER;
                IN_IS = V$IN_IS;
                IN_OU_VID = V$IN_OU_VID;
                IN_OU_SHORT = V$IN_OU_SHORT;
                IN_OU_LEGAL = V$IN_OU_LEGAL;
                IN_OU_DISTRICT = V$IN_OU_DISTRICT;
                IN_OU_DISTRICT_ID = V$IN_OU_DISTRICT_ID;
                LINK_ID = V$LINK_ID;

                IF (IN_OU_DISTRICT_ID = DISTRICT_LISTVAL_ID) THEN
                BEGIN
                    INCORRECT_ROW = 1;
                END
                SUSPEND;
            END
            CHECK_NEXT_ROW = 0;
        END
    END

    IF (CHECK_NEXT_ROW = 1) THEN
        SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_MTR_BY_NUMER_GET (
    I$INVENTORY_NUM VARCHAR(4000))
RETURNS (
    OBJECT_ID BIGINT,
    LINK_ID BIGINT,
    INVENTORY_NUM VARCHAR(4000),
    OBJ_CAPTION VARCHAR(400),
    OWNERSHIP VARCHAR(400),
    LACATION VARCHAR(400),
    RESPONSIBLE VARCHAR(400))
AS
DECLARE VARIABLE OBJ_ID BIGINT;
DECLARE VARIABLE TYPE_ID BIGINT;
DECLARE VARIABLE V VARCHAR(4000);
BEGIN
    /* ROOT OBJECT: OU  OR DISTR OR REGION*/
    /* TYPE OF ROOT OBJECT: 111 - DISTR, 112 - REGION  */
    SELECT FIRST 1 L.OBJ_ID, L.OBJ_TYPE_ID
    FROM LINKS L
    WHERE L.PARENT_ID IS NULL AND
          L.OBJ_TYPE_ID IN (2, 111, 112) AND
          L.DATE_DEL IS NULL
    INTO :OBJ_ID, :TYPE_ID;

    V = UPPER(I$INVENTORY_NUM);

    /* SCHOOL */
    IF (TYPE_ID = 2) THEN
    BEGIN
       FOR SELECT L114.OBJ_ID, L114.LINK_ID
            FROM OBJECT_CHILDREN_GET_DEEP(:OBJ_ID, 114, 3) O
            INNER JOIN LINKS L114 ON L114.OBJ_ID = O.OBJ_ID
            INNER JOIN VALS VS ON VS.OBJ_ID = O.OBJ_ID
            WHERE L114.OBJ_TYPE_ID = 114 AND
                  L114.DATE_DEL IS NULL AND
                  VS.PARAM_ID = 673 AND
                  VS.IS_DEL = 0 AND
                  UPPER(VS.VAL) STARTING WITH :V
            INTO :OBJECT_ID, :LINK_ID
        DO   /* */
        BEGIN
            SELECT V
            FROM VAL_GET(:OBJECT_ID, 673)
            INTO :INVENTORY_NUM;
            SELECT V
            FROM VAL_GET(:OBJECT_ID, 674)
            INTO :OBJ_CAPTION;
            SELECT V
            FROM VAL_GET(:OBJECT_ID, 675)
            INTO :OWNERSHIP;
            SELECT V
            FROM VAL_GET(:OBJECT_ID, 679)
            INTO :LACATION;
            SELECT V
            FROM VAL_GET(:OBJECT_ID, 680)
            INTO :RESPONSIBLE;
            SUSPEND;
        END
    END
    /* DISTRICT */
    IF (TYPE_ID = 111) THEN
    BEGIN
        FOR SELECT L114.OBJ_ID, L114.LINK_ID
            FROM LINKS L2
            INNER JOIN OBJECT_CHILDREN_GET_DEEP(L2.OBJ_ID, 114, 3) O on 1=1
            INNER JOIN LINKS L114 ON L114.OBJ_ID = O.OBJ_ID
            INNER JOIN VALS VS ON VS.OBJ_ID = O.OBJ_ID
            WHERE L2.PARENT_ID = :OBJ_ID AND
                  L2.OBJ_TYPE_ID = 2 AND
                  L2.DATE_DEL IS NULL AND
                  L114.OBJ_TYPE_ID = 114 AND
                  L114.DATE_DEL IS NULL AND
                  VS.PARAM_ID = 673 AND
                  VS.IS_DEL = 0 AND
                  UPPER(VS.VAL) STARTING WITH :V
            INTO :OBJECT_ID, :LINK_ID
        DO
        BEGIN
            SELECT V
            FROM VAL_GET(:OBJECT_ID, 673)
            INTO :I$INVENTORY_NUM;
            SELECT V
            FROM VAL_GET(:OBJECT_ID, 674)
            INTO :OBJ_CAPTION;
            SELECT V
            FROM VAL_GET(:OBJECT_ID, 675)
            INTO :OWNERSHIP;
            SELECT V
            FROM VAL_GET(:OBJECT_ID, 679)
            INTO :LACATION;
            SELECT V
            FROM VAL_GET(:OBJECT_ID, 680)
            INTO :RESPONSIBLE;
            SUSPEND;
        END
    END

    /* REGION */
    IF (TYPE_ID = 112) THEN
    BEGIN
        FOR SELECT L114.OBJ_ID, L114.LINK_ID
            FROM LINKS L2
            INNER JOIN OBJECT_CHILDREN_GET_DEEP(L2.OBJ_ID, 114, 3) O on 1=1
            INNER JOIN LINKS L114 ON L114.OBJ_ID = O.OBJ_ID
            INNER JOIN VALS VS ON VS.OBJ_ID = O.OBJ_ID
            WHERE L2.PARENT_ID = :OBJ_ID AND
                  L2.OBJ_TYPE_ID = 2 AND
                  L2.DATE_DEL IS NULL AND
                  L114.OBJ_TYPE_ID = 114 AND
                  L114.DATE_DEL IS NULL AND
                  VS.PARAM_ID = 673 AND
                  VS.IS_DEL = 0 AND
                  UPPER(VS.VAL) STARTING WITH :V
            INTO :OBJECT_ID, :LINK_ID
        DO
        BEGIN
            SELECT V
            FROM VAL_GET(:OBJECT_ID, 673)
            INTO :I$INVENTORY_NUM;
            SELECT V
            FROM VAL_GET(:OBJECT_ID, 674)
            INTO :OBJ_CAPTION;
            SELECT V
            FROM VAL_GET(:OBJECT_ID, 675)
            INTO :OWNERSHIP;
            SELECT V
            FROM VAL_GET(:OBJECT_ID, 679)
            INTO :LACATION;
            SELECT V
            FROM VAL_GET(:OBJECT_ID, 680)
            INTO :RESPONSIBLE;
            SUSPEND;
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_PRG3_CLASSNET (
    I$OBJ_ID BIGINT,
    I$DT DATE = current_date)
RETURNS (
    V00 INTEGER,
    V01 VARCHAR(1000),
    V02 INTEGER,
    V03 INTEGER,
    V04 INTEGER,
    V05 INTEGER,
    V06 INTEGER,
    V07 INTEGER,
    V08 INTEGER,
    V09 INTEGER,
    V10 INTEGER,
    V11 INTEGER,
    V12 INTEGER,
    V13 INTEGER,
    V14 INTEGER,
    V15 INTEGER,
    V16 INTEGER,
    V17 INTEGER,
    V18 INTEGER,
    V19 INTEGER,
    V20 INTEGER,
    V21 INTEGER,
    V22 INTEGER,
    V23 INTEGER,
    V24 INTEGER,
    V25 INTEGER,
    V26 INTEGER,
    V27 INTEGER,
    V28 INTEGER,
    V29 INTEGER,
    V30 INTEGER,
    V31 INTEGER,
    V32 INTEGER,
    V33 INTEGER,
    V34 INTEGER,
    V35 INTEGER,
    V36 VARCHAR(1000),
    V37 INTEGER,
    V38 INTEGER,
    V39 INTEGER,
    V40 INTEGER,
    V41 INTEGER)
AS
BEGIN

    SELECT 0, V01, V02, V03, V04, V05, V06, V07, V08, V09, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, V20,
           V21, V22, V23, V24, V25, V26, V27, V28, V29, V30, V31, V32, V33, V34, V35, V36, V37, V38, V39, V40, V41
    FROM R_PRG3_CLASSNET_GET_OLD(:I$OBJ_ID, 0, :I$DT)
    INTO :V00, :V01, :V02, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20,
         :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30, :V31, :V32, :V33, :V34, :V35, :V36, :V37, :V38, :V39, :V40, :V41;
    SUSPEND;

    SELECT 1, V01, V02, V03, V04, V05, V06, V07, V08, V09, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, V20,
           V21, V22, V23, V24, V25, V26, V27, V28, V29, V30, V31, V32, V33, V34, V35, V36, V37, V38, V39, V40, V41
    FROM R_PRG3_CLASSNET_GET_OLD(:I$OBJ_ID, 1, :I$DT)
    INTO :V00, :V01, :V02, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20,
         :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30, :V31, :V32, :V33, :V34, :V35, :V36, :V37, V38, V39, :V40, :V41;
    SUSPEND;

    SELECT 2, V01, V02, V03, V04, V05, V06, V07, V08, V09, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, V20,
           V21, V22, V23, V24, V25, V26, V27, V28, V29, V30, V31, V32, V33, V34, V35, V36, V37, V38, V39, V40, V41
    FROM R_PRG3_CLASSNET_GET_OLD(:I$OBJ_ID, 2, :I$DT)
    INTO :V00, :V01, :V02, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20,
         :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30, :V31, :V32, :V33, :V34, :V35, :V36, :V37, :V38, :V39, :V40, :V41;
    SUSPEND;

    SELECT 3, V01, V02, V03, V04, V05, V06, V07, V08, V09, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, V20,
           V21, V22, V23, V24, V25, V26, V27, V28, V29, V30, V31, V32, V33, V34, V35, V36, V37, V38, V39, V40, V41
    FROM R_PRG3_CLASSNET_GET_OLD(:I$OBJ_ID, 3, :I$DT)
    INTO :V00, :V01, :V02, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20,
         :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30, :V31, :V32, :V33, :V34, :V35, :V36, :V37, :V38, :V39, :V40, :V41;
    SUSPEND;

    V00 = 4;
    V01 = '';
    V02 = NULL;
    V03 = NULL;
    V04 = NULL;
    V05 = NULL;
    V06 = NULL;
    V07 = NULL;
    V08 = NULL;
    V09 = NULL;
    V10 = NULL;
    V11 = NULL;
    V12 = NULL;
    V13 = NULL;
    V14 = NULL;
    V15 = NULL;
    V16 = NULL;
    V17 = NULL;
    V18 = NULL;
    V19 = NULL;
    V20 = NULL;
    V21 = NULL;
    V22 = NULL;
    V23 = NULL;
    V24 = NULL;
    V25 = NULL;
    V26 = NULL;
    V27 = NULL;
    V28 = NULL;
    V29 = NULL;
    V30 = NULL;
    V31 = NULL;
    V32 = NULL;
    V33 = NULL;
    V34 = NULL;
    V35 = NULL;
    V36 = '';
    V37 = NULL;
    V38 = NULL;
    V39 = NULL;
    V40 = NULL;
    V41 = NULL;
    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_PRG3_CLASSNET_GET (
    I$SCHOOL_ID BIGINT,
    I$CLASS_TYPE SMALLINT,
    I$DT DATE = current_date)
RETURNS (
    V01 VARCHAR(1000),
    V02 INTEGER,
    V03 INTEGER,
    V04 INTEGER,
    V05 INTEGER,
    V06 INTEGER,
    V07 INTEGER,
    V08 INTEGER,
    V09 INTEGER,
    V10 INTEGER,
    V11 INTEGER,
    V12 INTEGER,
    V13 INTEGER,
    V14 INTEGER,
    V15 INTEGER,
    V16 INTEGER,
    V17 INTEGER,
    V18 INTEGER,
    V19 INTEGER,
    V20 INTEGER,
    V21 INTEGER,
    V22 INTEGER,
    V23 INTEGER,
    V24 INTEGER,
    V25 INTEGER,
    V26 INTEGER,
    V27 INTEGER,
    V28 INTEGER,
    V29 INTEGER,
    V30 INTEGER,
    V31 INTEGER,
    V32 INTEGER,
    V33 INTEGER,
    V34 INTEGER,
    V35 INTEGER,
    V36 VARCHAR(1000),
    V37 INTEGER,
    V38 INTEGER,
    V39 INTEGER,
    V40 INTEGER,
    V41 INTEGER)
AS
declare variable STAGE_ID bigint;
declare variable CLASS_ID bigint;
declare variable CLASS_TYPE_MIN bigint;
declare variable CLASS_TYPE_MAX bigint;
declare variable C integer;
BEGIN

    -- Функция устарела, теперь только R_PRG3_CLASSNET_GET_OLD

    V01 = '';
    V02 = 0;
    V03 = 0;
    V04 = 0;
    V05 = 0;
    V06 = 0;
    V07 = 0;
    V08 = 0;
    V09 = 0;
    V10 = 0;
    V11 = 0;
    V12 = 0;
    V13 = 0;
    V14 = 0;
    V15 = 0;
    V16 = 0;
    V17 = 0;
    V18 = 0;
    V19 = 0;
    V20 = 0;
    V21 = 0;
    V22 = 0;
    V23 = 0;
    V24 = 0;
    V25 = 0;
    V26 = 0;
    V27 = 0;
    V28 = 0;
    V29 = 0;
    V30 = 0;
    V31 = 0;
    V32 = 0;
    V33 = 0;
    V34 = 0;
    V35 = 0;
    V36 = '';
    V37 = NULL;
    V38 = NULL;
    V39 = NULL;
    V40 = NULL;
    V41 = NULL;

    IF (I$CLASS_TYPE = 0) THEN
    BEGIN
        CLASS_TYPE_MIN = 0;
        CLASS_TYPE_MAX = 100000;
        V01 = 'по району';
        V36 = 'по району';
        V37 = 0;
        V38 = 0;
        V39 = 0;
        V40 = 0;
        V41 = 0;
    END
    ELSE
    IF (I$CLASS_TYPE = 1) THEN
    BEGIN
        /* обычные классы */
        CLASS_TYPE_MIN = 197;
        CLASS_TYPE_MAX = 197;
        V01 = 'общ';
        V36 = 'общ';
    END
    ELSE
    IF (I$CLASS_TYPE = 2) THEN
    BEGIN
        /* компенсирующие классы */
        CLASS_TYPE_MIN = 196;
        CLASS_TYPE_MAX = 196;
        V01 = 'комп';
        V36 = 'комп';
    END
    ELSE
    IF (I$CLASS_TYPE = 3) THEN
    BEGIN
        /* Строки зпр (переименованы в корр) */
        CLASS_TYPE_MIN = 198;
        CLASS_TYPE_MAX = 11402;
        V01 = 'корр';
        V36 = 'корр';
    END

    FOR
        SELECT L9.OBJ_ID, V49.LISTVAL_ID
        FROM LINKS L7                                                                            -- Уровень образования
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL -- Этап обучения
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL -- Класс
        JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0         -- Этап -- параллель
        JOIN VALL V592 ON V592.OBJ_ID = L9.OBJ_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID >= :CLASS_TYPE_MIN AND V592.LISTVAL_ID <= :CLASS_TYPE_MAX -- тип
        WHERE L7.PARENT_ID = :I$SCHOOL_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
        INTO :CLASS_ID, :STAGE_ID
    DO
    BEGIN

        C = 0;
        SELECT COUNT(*)
        FROM LINKS L10
        WHERE L10.PARENT_ID = :CLASS_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        INTO :C;

        -- 0 параллель и далее по номерам
        IF (STAGE_ID = 12765) THEN
        BEGIN
            V02 = V02 + 1;
            V03 = V03 + C;
        END
        ELSE IF (STAGE_ID = 37) THEN
        BEGIN
            V04 = V04 + 1;
            V05 = V05 + C;
        END
        ELSE IF (STAGE_ID = 38) THEN
        BEGIN
            V06 = V06 + 1;
            V07 = V07 + C;
        END
        ELSE IF (STAGE_ID = 39) THEN
        BEGIN
            V08 = V08 + 1;
            V09 = V09 + C;
        END
        ELSE IF (STAGE_ID = 40) THEN
        BEGIN
            V10 = V10 + 1;
            V11 = V11 + C;
        END
        ELSE IF (STAGE_ID = 41) THEN
        BEGIN
            V14 = V14 + 1;
            V15 = V15 + C;
        END
        ELSE IF (STAGE_ID = 42) THEN
        BEGIN
            V16 = V16 + 1;
            V17 = V17 + C;
        END
        ELSE IF (STAGE_ID = 43) THEN
        BEGIN
            V18 = V18 + 1;
            V19 = V19 + C;
        END
        ELSE IF (STAGE_ID = 44) THEN
        BEGIN
            V20 = V20 + 1;
            V21 = V21 + C;
        END
        ELSE IF (STAGE_ID = 45) THEN
        BEGIN
            V22 = V22 + 1;
            V23 = V23 + C;
        END
        ELSE IF (STAGE_ID = 46) THEN
        BEGIN
            V26 = V26 + 1;
            V27 = V27 + C;
        END
        ELSE IF (STAGE_ID = 47) THEN
        BEGIN
            V28 = V28 + 1;
            V29 = V29 + C;
        END
        ELSE IF (STAGE_ID = 48) THEN
        BEGIN
            V30 = V30 + 1;
            V31 = V31 + C;
        END
    END

    -- ГПД + надомники + экстернат только в разрезе школы целиком
    IF (I$CLASS_TYPE = 0) THEN
    BEGIN

        -- ГПД
        FOR
            SELECT L46.OBJ_ID
            FROM LINKS L86
            JOIN LINKS L46 ON L46.PARENT_ID = L86.OBJ_ID AND L46.OBJ_TYPE_ID = 46 AND L46.DATE_DEL IS NULL
            JOIN VALL V369 ON V369.OBJ_ID = L46.OBJ_ID AND V369.PARAM_ID = 369 AND V369.IS_DEL = 0 AND V369.LISTVAL_ID = 1246
            WHERE L86.PARENT_ID = :I$SCHOOL_ID AND L86.OBJ_TYPE_ID = 86 AND L86.DATE_DEL IS NULL
            INTO :CLASS_ID
        DO
        BEGIN

            C = 0;
            SELECT COUNT(*)
            FROM LINKS L10
            WHERE L10.PARENT_ID = :CLASS_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
            INTO :C;

            V37 = V37 + 1;
            V38 = V38 + C;

        END

        -- Надомное обучение
        SELECT COUNT(*)
        FROM LINKS L7
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
        JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        JOIN VALL V2169 ON V2169.OBJ_ID = L10.OBJ_ID AND V2169.PARAM_ID = 2169 AND V2169.IS_DEL = 0 AND V2169.LISTVAL_ID = 2
        WHERE L7.PARENT_ID = :I$SCHOOL_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
        INTO :C;

        V39 = V39 + C;
    END

    -- Экстернат
    FOR
        SELECT L187.OBJ_ID
        FROM LINKS L7
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
        JOIN LINKS L187 ON L187.PARENT_ID = L8.OBJ_ID AND L187.OBJ_TYPE_ID = 187 AND L187.DATE_DEL IS NULL
        WHERE L7.PARENT_ID = :I$SCHOOL_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
        INTO :CLASS_ID
    DO
    BEGIN

        C = 0;
        SELECT COUNT(*)
        FROM LINKS L10
        WHERE L10.PARENT_ID = :CLASS_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        INTO :C;

        V40 = V40 + 1;
        V41 = V41 + C;
    END

    -- Начальная школа - итого
    V12 = V02 + V04 + V06 + V08 + V10;
    V13 = V03 + V05 + V07 + V09 + V11;

    -- Общая школа - итого
    V24 = V14 + V16 + V18 + V20 + V22;
    V25 = V15 + V17 + V19 + V21 + V23;

    -- Средняя школа - итого
    V32 = V26 + V28 + V30;
    V33 = V27 + V29 + V31;

    -- Всего по всем уровням
    V34 = V12 + V24 + V32;
    V35 = V13 + V25 + V33;

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_PRG3_CLASSNET_GET_OLD (
    I$SCHOOL_ID BIGINT,
    I$CLASS_TYPE SMALLINT,
    I$DT DATE = current_date)
RETURNS (
    V01 VARCHAR(1000),
    V02 INTEGER,
    V03 INTEGER,
    V04 INTEGER,
    V05 INTEGER,
    V06 INTEGER,
    V07 INTEGER,
    V08 INTEGER,
    V09 INTEGER,
    V10 INTEGER,
    V11 INTEGER,
    V12 INTEGER,
    V13 INTEGER,
    V14 INTEGER,
    V15 INTEGER,
    V16 INTEGER,
    V17 INTEGER,
    V18 INTEGER,
    V19 INTEGER,
    V20 INTEGER,
    V21 INTEGER,
    V22 INTEGER,
    V23 INTEGER,
    V24 INTEGER,
    V25 INTEGER,
    V26 INTEGER,
    V27 INTEGER,
    V28 INTEGER,
    V29 INTEGER,
    V30 INTEGER,
    V31 INTEGER,
    V32 INTEGER,
    V33 INTEGER,
    V34 INTEGER,
    V35 INTEGER,
    V36 VARCHAR(1000),
    V37 INTEGER,
    V38 INTEGER,
    V39 INTEGER,
    V40 INTEGER,
    V41 INTEGER)
AS
declare variable STAGE_ID bigint; /* LV этапа обучения */
declare variable CLASS_TYPE_MIN bigint;
declare variable CLASS_TYPE_MAX bigint;
declare variable C integer;
declare variable A integer;
declare variable TEMP bigint;
declare variable I$SCHOOL_ID2 bigint;
BEGIN
    
    V01 = '';
    V02 = 0;
    V03 = 0;
    V04 = 0;
    V05 = 0;
    V06 = 0;
    V07 = 0;
    V08 = 0;
    V09 = 0;
    V10 = 0;
    V11 = 0;
    V12 = 0;
    V13 = 0;
    V14 = 0;
    V15 = 0;
    V16 = 0;
    V17 = 0;
    V18 = 0;
    V19 = 0;
    V20 = 0;
    V21 = 0;
    V22 = 0;
    V23 = 0;
    V24 = 0;
    V25 = 0;
    V26 = 0;
    V27 = 0;
    V28 = 0;
    V29 = 0;
    V30 = 0;
    V31 = 0;
    V32 = 0;
    V33 = 0;
    V34 = 0;
    V35 = 0;
    V36 = '';
    V37 = NULL;
    V38 = NULL;
    V39 = NULL;
    V40 = NULL;
    V41 = NULL;

    IF (I$CLASS_TYPE = 0) THEN
    BEGIN
        CLASS_TYPE_MIN = 0;
        CLASS_TYPE_MAX = 100000;
        V01 = 'по району';
        V36 = 'по району';
        V37 = 0;
        V38 = 0;
        V39 = 0;
        V40 = 0;
        V41 = 0;
    END
    ELSE
    IF (I$CLASS_TYPE = 1) THEN
    BEGIN
        /* обычные классы */
        CLASS_TYPE_MIN = 197;
        CLASS_TYPE_MAX = 197;
        V01 = 'общ';
        V36 = 'общ';
    END
    ELSE
    IF (I$CLASS_TYPE = 2) THEN
    BEGIN
        /* для детей с ОВЗ */
        CLASS_TYPE_MIN = 13274;
        CLASS_TYPE_MAX = 13274;
        V01 = 'с/ОВЗ';
        V36 = 'с/ОВЗ';
    END
    ELSE
    IF (I$CLASS_TYPE = 3) THEN
    BEGIN
        /* Строки зпр (переименованы в корр) */
        CLASS_TYPE_MIN = 13275;
        CLASS_TYPE_MAX = 13275;
        V01 = 'ОВЗ';
        V36 = 'ОВЗ';
    END

    -- Все отчеты у нас актуальны только на текущий учебный год, поэтому ищем учеников только среди текущих классов и выбывших текущего года
    -- Обычные классы (7 -> 8 -> 9)
    FOR
        SELECT GRADE_LV, GRADE_ID, COUNT(*)
        FROM PUPIL_LIST_BY_DATE(:I$SCHOOL_ID, :CLASS_TYPE_MIN, :CLASS_TYPE_MAX, :I$DT)
        GROUP BY 1, 2
        INTO :STAGE_ID, :TEMP, C
    DO
    BEGIN
        -- 0 параллель и далее по номерам
        IF (STAGE_ID = 12765) THEN
        BEGIN
            V02 = V02 + 1;
            V03 = V03 + C;
        END
        ELSE IF (STAGE_ID = 37) THEN
        BEGIN
            V04 = V04 + 1;
            V05 = V05 + C;
        END
        ELSE IF (STAGE_ID = 38) THEN
        BEGIN
            V06 = V06 + 1;
            V07 = V07 + C;
        END
        ELSE IF (STAGE_ID = 39) THEN
        BEGIN
            V08 = V08 + 1;
            V09 = V09 + C;
        END
        ELSE IF (STAGE_ID = 40) THEN
        BEGIN
            V10 = V10 + 1;
            V11 = V11 + C;
        END
        ELSE IF (STAGE_ID = 41) THEN
        BEGIN
            V14 = V14 + 1;
            V15 = V15 + C;
        END
        ELSE IF (STAGE_ID = 42) THEN
        BEGIN
            V16 = V16 + 1;
            V17 = V17 + C;
        END
        ELSE IF (STAGE_ID = 43) THEN
        BEGIN
            V18 = V18 + 1;
            V19 = V19 + C;
        END
        ELSE IF (STAGE_ID = 44) THEN
        BEGIN
            V20 = V20 + 1;
            V21 = V21 + C;
        END
        ELSE IF (STAGE_ID = 45) THEN
        BEGIN
            V22 = V22 + 1;
            V23 = V23 + C;
        END
        ELSE IF (STAGE_ID = 46) THEN
        BEGIN
            V26 = V26 + 1;
            V27 = V27 + C;
        END
        ELSE IF (STAGE_ID = 47) THEN
        BEGIN
            V28 = V28 + 1;
            V29 = V29 + C;
        END
        ELSE IF (STAGE_ID = 48) THEN
        BEGIN
            V30 = V30 + 1;
            V31 = V31 + C;
        END
    END

    -- ГПД + надомники + экстернат только в разрезе школы целиком
    IF (I$CLASS_TYPE = 0) THEN
    BEGIN

        -- ГПД, переделано на работу с реестром движения
        SELECT COUNT(DISTINCT GPD_ID), COUNT(DISTINCT PUPIL_ID)
        FROM PUPIL_GPD_LIST_BY_DATE(:I$SCHOOL_ID, :I$DT)
        INTO :A, :C;

        V37 = V37 + A;
        V38 = V38 + C;

        -- Надомное обучение
        SELECT COUNT(*)
        FROM PUPIL_LIST_BY_DATE(:I$SCHOOL_ID, 0, 100000, :I$DT, 1)
        INTO :C;

        V39 = V39 + C;

        -- Экстернат
        I$SCHOOL_ID = I$SCHOOL_ID / 1000000000;
        I$SCHOOL_ID2 = I$SCHOOL_ID + 1;
        I$SCHOOL_ID = I$SCHOOL_ID * 1000000000;
        I$SCHOOL_ID2 = I$SCHOOL_ID2 * 1000000000;

        SELECT COUNT(M.GROUP_ID), COUNT(M.PERSON_ID)
        FROM PERSON_MOVEMENTS M
        JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 187
        WHERE M.DATE_DEL IS NULL
            AND M.OBJ_ID >= :I$SCHOOL_ID AND M.OBJ_ID < :I$SCHOOL_ID2
            AND M.DATE_IN <= :I$DT AND (M.DATE_OUT IS NULL OR M.DATE_OUT > :I$DT)
        INTO :A, :C;

        V40 = V40 + A;
        V41 = V41 + C;

    END

    -- Начальная школа - итого
    V12 = V02 + V04 + V06 + V08 + V10;
    V13 = V03 + V05 + V07 + V09 + V11;

    -- Общая школа - итого
    V24 = V14 + V16 + V18 + V20 + V22;
    V25 = V15 + V17 + V19 + V21 + V23;

    -- Средняя школа - итого
    V32 = V26 + V28 + V30;
    V33 = V27 + V29 + V31;

    -- Всего по всем уровням
    V34 = V12 + V24 + V32;
    V35 = V13 + V25 + V33;

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_PRG3_CLASSNET_OU (
    I$OBJ_ID BIGINT,
    I$DT DATE = current_date)
RETURNS (
    SCHOOL_REC INTEGER,
    V00 INTEGER,
    V01 VARCHAR(1000),
    V02 INTEGER,
    V03 INTEGER,
    V04 INTEGER,
    V05 INTEGER,
    V06 INTEGER,
    V07 INTEGER,
    V08 INTEGER,
    V09 INTEGER,
    V10 INTEGER,
    V11 INTEGER,
    V12 INTEGER,
    V13 INTEGER,
    V14 INTEGER,
    V15 INTEGER,
    V16 INTEGER,
    V17 INTEGER,
    V18 INTEGER,
    V19 INTEGER,
    V20 INTEGER,
    V21 INTEGER,
    V22 INTEGER,
    V23 INTEGER,
    V24 INTEGER,
    V25 INTEGER,
    V26 INTEGER,
    V27 INTEGER,
    V28 INTEGER,
    V29 INTEGER,
    V30 INTEGER,
    V31 INTEGER,
    V32 INTEGER,
    V33 INTEGER,
    V34 INTEGER,
    V35 INTEGER,
    V36 VARCHAR(1000),
    V37 INTEGER,
    V38 INTEGER,
    V39 INTEGER,
    V40 INTEGER,
    V41 INTEGER)
AS
--declare variable V00 integer;
declare variable SCHOOL_ID bigint;
declare variable V01_0 varchar(1000);
declare variable V02_0 integer;
declare variable V03_0 integer;
declare variable V04_0 integer;
declare variable V05_0 integer;
declare variable V06_0 integer;
declare variable V07_0 integer;
declare variable V08_0 integer;
declare variable V09_0 integer;
declare variable V10_0 integer;
declare variable V11_0 integer;
declare variable V12_0 integer;
declare variable V13_0 integer;
declare variable V14_0 integer;
declare variable V15_0 integer;
declare variable V16_0 integer;
declare variable V17_0 integer;
declare variable V18_0 integer;
declare variable V19_0 integer;
declare variable V20_0 integer;
declare variable V21_0 integer;
declare variable V22_0 integer;
declare variable V23_0 integer;
declare variable V24_0 integer;
declare variable V25_0 integer;
declare variable V26_0 integer;
declare variable V27_0 integer;
declare variable V28_0 integer;
declare variable V29_0 integer;
declare variable V30_0 integer;
declare variable V31_0 integer;
declare variable V32_0 integer;
declare variable V33_0 integer;
declare variable V34_0 integer;
declare variable V35_0 integer;
declare variable V36_0 varchar(1000);
declare variable V37_0 integer;
declare variable V38_0 integer;
declare variable V39_0 integer;
declare variable V40_0 integer;
declare variable V41_0 integer;
declare variable V01_1 varchar(1000);
declare variable V02_1 integer;
declare variable V03_1 integer;
declare variable V04_1 integer;
declare variable V05_1 integer;
declare variable V06_1 integer;
declare variable V07_1 integer;
declare variable V08_1 integer;
declare variable V09_1 integer;
declare variable V10_1 integer;
declare variable V11_1 integer;
declare variable V12_1 integer;
declare variable V13_1 integer;
declare variable V14_1 integer;
declare variable V15_1 integer;
declare variable V16_1 integer;
declare variable V17_1 integer;
declare variable V18_1 integer;
declare variable V19_1 integer;
declare variable V20_1 integer;
declare variable V21_1 integer;
declare variable V22_1 integer;
declare variable V23_1 integer;
declare variable V24_1 integer;
declare variable V25_1 integer;
declare variable V26_1 integer;
declare variable V27_1 integer;
declare variable V28_1 integer;
declare variable V29_1 integer;
declare variable V30_1 integer;
declare variable V31_1 integer;
declare variable V32_1 integer;
declare variable V33_1 integer;
declare variable V34_1 integer;
declare variable V35_1 integer;
declare variable V36_1 varchar(1000);
declare variable V37_1 integer;
declare variable V38_1 integer;
declare variable V39_1 integer;
declare variable V40_1 integer;
declare variable V41_1 integer;
declare variable V01_2 varchar(1000);
declare variable V02_2 integer;
declare variable V03_2 integer;
declare variable V04_2 integer;
declare variable V05_2 integer;
declare variable V06_2 integer;
declare variable V07_2 integer;
declare variable V08_2 integer;
declare variable V09_2 integer;
declare variable V10_2 integer;
declare variable V11_2 integer;
declare variable V12_2 integer;
declare variable V13_2 integer;
declare variable V14_2 integer;
declare variable V15_2 integer;
declare variable V16_2 integer;
declare variable V17_2 integer;
declare variable V18_2 integer;
declare variable V19_2 integer;
declare variable V20_2 integer;
declare variable V21_2 integer;
declare variable V22_2 integer;
declare variable V23_2 integer;
declare variable V24_2 integer;
declare variable V25_2 integer;
declare variable V26_2 integer;
declare variable V27_2 integer;
declare variable V28_2 integer;
declare variable V29_2 integer;
declare variable V30_2 integer;
declare variable V31_2 integer;
declare variable V32_2 integer;
declare variable V33_2 integer;
declare variable V34_2 integer;
declare variable V35_2 integer;
declare variable V36_2 varchar(1000);
declare variable V37_2 integer;
declare variable V38_2 integer;
declare variable V39_2 integer;
declare variable V40_2 integer;
declare variable V41_2 integer;
declare variable V01_3 varchar(1000);
declare variable V02_3 integer;
declare variable V03_3 integer;
declare variable V04_3 integer;
declare variable V05_3 integer;
declare variable V06_3 integer;
declare variable V07_3 integer;
declare variable V08_3 integer;
declare variable V09_3 integer;
declare variable V10_3 integer;
declare variable V11_3 integer;
declare variable V12_3 integer;
declare variable V13_3 integer;
declare variable V14_3 integer;
declare variable V15_3 integer;
declare variable V16_3 integer;
declare variable V17_3 integer;
declare variable V18_3 integer;
declare variable V19_3 integer;
declare variable V20_3 integer;
declare variable V21_3 integer;
declare variable V22_3 integer;
declare variable V23_3 integer;
declare variable V24_3 integer;
declare variable V25_3 integer;
declare variable V26_3 integer;
declare variable V27_3 integer;
declare variable V28_3 integer;
declare variable V29_3 integer;
declare variable V30_3 integer;
declare variable V31_3 integer;
declare variable V32_3 integer;
declare variable V33_3 integer;
declare variable V34_3 integer;
declare variable V35_3 integer;
declare variable V36_3 varchar(1000);
declare variable V37_3 integer;
declare variable V38_3 integer;
declare variable V39_3 integer;
declare variable V40_3 integer;
declare variable V41_3 integer;
BEGIN
    SCHOOL_REC = 0;

    V01_0 = '';
    V02_0 = 0;
    V03_0 = 0;
    V04_0 = 0;
    V05_0 = 0;
    V06_0 = 0;
    V07_0 = 0;
    V08_0 = 0;
    V09_0 = 0;
    V10_0 = 0;
    V11_0 = 0;
    V12_0 = 0;
    V13_0 = 0;
    V14_0 = 0;
    V15_0 = 0;
    V16_0 = 0;
    V17_0 = 0;
    V18_0 = 0;
    V19_0 = 0;
    V20_0 = 0;
    V21_0 = 0;
    V22_0 = 0;
    V23_0 = 0;
    V24_0 = 0;
    V25_0 = 0;
    V26_0 = 0;
    V27_0 = 0;
    V28_0 = 0;
    V29_0 = 0;
    V30_0 = 0;
    V31_0 = 0;
    V32_0 = 0;
    V33_0 = 0;
    V34_0 = 0;
    V35_0 = 0;
    V36_0 = '';
    V37_0 = 0;
    V38_0 = 0;
    V39_0 = 0;
    V40_0 = 0;
    V41_0 = 0;

    V01_1 = '';
    V02_1 = 0;
    V03_1 = 0;
    V04_1 = 0;
    V05_1 = 0;
    V06_1 = 0;
    V07_1 = 0;
    V08_1 = 0;
    V09_1 = 0;
    V10_1 = 0;
    V11_1 = 0;
    V12_1 = 0;
    V13_1 = 0;
    V14_1 = 0;
    V15_1 = 0;
    V16_1 = 0;
    V17_1 = 0;
    V18_1 = 0;
    V19_1 = 0;
    V20_1 = 0;
    V21_1 = 0;
    V22_1 = 0;
    V23_1 = 0;
    V24_1 = 0;
    V25_1 = 0;
    V26_1 = 0;
    V27_1 = 0;
    V28_1 = 0;
    V29_1 = 0;
    V30_1 = 0;
    V31_1 = 0;
    V32_1 = 0;
    V33_1 = 0;
    V34_1 = 0;
    V35_1 = 0;
    V36_1 = '';
    V37_1 = NULL;
    V38_1 = NULL;
    V39_1 = NULL;
    V40_1 = NULL;
    V41_1 = NULL;

    V01_2 = '';
    V02_2 = 0;
    V03_2 = 0;
    V04_2 = 0;
    V05_2 = 0;
    V06_2 = 0;
    V07_2 = 0;
    V08_2 = 0;
    V09_2 = 0;
    V10_2 = 0;
    V11_2 = 0;
    V12_2 = 0;
    V13_2 = 0;
    V14_2 = 0;
    V15_2 = 0;
    V16_2 = 0;
    V17_2 = 0;
    V18_2 = 0;
    V19_2 = 0;
    V20_2 = 0;
    V21_2 = 0;
    V22_2 = 0;
    V23_2 = 0;
    V24_2 = 0;
    V25_2 = 0;
    V26_2 = 0;
    V27_2 = 0;
    V28_2 = 0;
    V29_2 = 0;
    V30_2 = 0;
    V31_2 = 0;
    V32_2 = 0;
    V33_2 = 0;
    V34_2 = 0;
    V35_2 = 0;
    V36 = '';
    V37_2 = NULL;
    V38_2 = NULL;
    V39_2 = NULL;
    V40_2 = NULL;
    V41_2 = NULL;

    V01_3 = '';
    V02_3 = 0;
    V03_3 = 0;
    V04_3 = 0;
    V05_3 = 0;
    V06_3 = 0;
    V07_3 = 0;
    V08_3 = 0;
    V09_3 = 0;
    V10_3 = 0;
    V11_3 = 0;
    V12_3 = 0;
    V13_3 = 0;
    V14_3 = 0;
    V15_3 = 0;
    V16_3 = 0;
    V17_3 = 0;
    V18_3 = 0;
    V19_3 = 0;
    V20_3 = 0;
    V21_3 = 0;
    V22_3 = 0;
    V23_3 = 0;
    V24_3 = 0;
    V25_3 = 0;
    V26_3 = 0;
    V27_3 = 0;
    V28_3 = 0;
    V29_3 = 0;
    V30_3 = 0;
    V31_3 = 0;
    V32_3 = 0;
    V33_3 = 0;
    V34_3 = 0;
    V35_3 = 0;
    V36_3 = '';
    V37_3 = NULL;
    V38_3 = NULL;
    V39_3 = NULL;
    V40_3 = NULL;
    V41_3 = NULL;

    FOR
        SELECT S.OBJ_ID
        FROM OBJECT_CHILDREN_GET_DEEP(:I$OBJ_ID,2,1) S
        LEFT JOIN VALI V17 ON V17.OBJ_ID = S.OBJ_ID AND V17.PARAM_ID = 17 AND V17.IS_DEL = 0
        ORDER BY V17.VAL
        INTO :SCHOOL_ID
    DO
    BEGIN
        SCHOOL_REC = SCHOOL_REC + 1;
        FOR
            SELECT V00, V01, V02, V03, V04, V05, V06, V07, V08, V09, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, V20, V21,
                   V22, V23, V24, V25, V26, V27, V28, V29, V30, V31, V32, V33, V34, V35, V36, V37, V38, V39, V40, V41
            FROM R_PRG3_CLASSNET(:SCHOOL_ID, :I$DT)
            INTO :V00, :V01, :V02, :V03, :V04, :V05, :V06, :V07, :V08, :V09, :V10, :V11, :V12, :V13, :V14, :V15, :V16, :V17, :V18, :V19, :V20,
                 :V21, :V22, :V23, :V24, :V25, :V26, :V27, :V28, :V29, :V30, :V31, :V32, :V33, :V34, :V35, :V36, :V37, :V38, :V39, :V40, :V41
        DO
        BEGIN
            IF (V39 IS NOT NULL) THEN
            BEGIN
                SELECT V FROM VAL_GET(:SCHOOL_ID, 17) INTO :V01;
                IF (V01 = '') THEN SELECT V FROM VAL_GET(:SCHOOL_ID, 2) INTO :V01;
                V36 = V01;
            END

            IF (V00 = 0) THEN
            BEGIN
              V01_0 = V01;
              V02_0 = V02_0 + V02; V03_0 = V03_0 + V03; V04_0 = V04_0 + V04; V05_0 = V05_0 + V05; V06_0 = V06_0 + V06;
              V07_0 = V07_0 + V07; V08_0 = V08_0 + V08; V09_0 = V09_0 + V09; V10_0 = V10_0 + V10; V11_0 = V11_0 + V11; V12_0 = V12_0 + V12;
              V13_0 = V13_0 + V13; V14_0 = V14_0 + V14; V15_0 = V15_0 + V15; V16_0 = V16_0 + V16; V17_0 = V17_0 + V17; V18_0 = V18_0 + V18;
              V19_0 = V19_0 + V19; V20_0 = V20_0 + V20; V21_0 = V21_0 + V21; V22_0 = V22_0 + V22; V23_0 = V23_0 + V23; V24_0 = V24_0 + V24;
              V25_0 = V25_0 + V25; V26_0 = V26_0 + V26; V27_0 = V27_0 + V27; V28_0 = V28_0 + V28; V29_0 = V29_0 + V29; V30_0 = V30_0 + V30;
              V31_0 = V31_0 + V31; V32_0 = V32_0 + V32; V33_0 = V33_0 + V33; V34_0 = V34_0 + V34; V35_0 = V35_0 + V35; V36_0 = V36;
              V37_0 = V37_0 + V37; V38_0 = V38_0 + V38; V39_0 = V39_0 + V39; V40_0 = V40_0 + V40; V41_0 = V41_0 + V41;
            END
            ELSE
            IF (V00 = 1) THEN
            BEGIN
              V01_1 = V01;
              V02_1 = V02_1 + V02; V03_1 = V03_1 + V03; V04_1 = V04_1 + V04; V05_1 = V05_1 + V05; V06_1 = V06_1 + V06;
              V07_1 = V07_1 + V07; V08_1 = V08_1 + V08; V09_1 = V09_1 + V09; V10_1 = V10_1 + V10; V11_1 = V11_1 + V11; V12_1 = V12_1 + V12;
              V13_1 = V13_1 + V13; V14_1 = V14_1 + V14; V15_1 = V15_1 + V15; V16_1 = V16_1 + V16; V17_1 = V17_1 + V17; V18_1 = V18_1 + V18;
              V19_1 = V19_1 + V19; V20_1 = V20_1 + V20; V21_1 = V21_1 + V21; V22_1 = V22_1 + V22; V23_1 = V23_1 + V23; V24_1 = V24_1 + V24;
              V25_1 = V25_1 + V25; V26_1 = V26_1 + V26; V27_1 = V27_1 + V27; V28_1 = V28_1 + V28; V29_1 = V29_1 + V29; V30_1 = V30_1 + V30;
              V31_1 = V31_1 + V31; V32_1 = V32_1 + V32; V33_1 = V33_1 + V33; V34_1 = V34_1 + V34; V35_1 = V35_1 + V35; V36_1 = V36;
              V37_1 = V37_1 + V37; V38_1 = V38_1 + V38; V39_1 = V39_1 + V39; V40_1 = V40_1 + V40; V41_1 = V41_1 + V41;
            END
            ELSE
            IF (V00 = 2) THEN
            BEGIN
              V01_2 = V01;
              V02_2 = V02_2 + V02; V03_2 = V03_2 + V03; V04_2 = V04_2 + V04; V05_2 = V05_2 + V05; V06_2 = V06_2 + V06;
              V07_2 = V07_2 + V07; V08_2 = V08_2 + V08; V09_2 = V09_2 + V09; V10_2 = V10_2 + V10; V11_2 = V11_2 + V11; V12_2 = V12_2 + V12;
              V13_2 = V13_2 + V13; V14_2 = V14_2 + V14; V15_2 = V15_2 + V15; V16_2 = V16_2 + V16; V17_2 = V17_2 + V17; V18_2 = V18_2 + V18;
              V19_2 = V19_2 + V19; V20_2 = V20_2 + V20; V21_2 = V21_2 + V21; V22_2 = V22_2 + V22; V23_2 = V23_2 + V23; V24_2 = V24_2 + V24;
              V25_2 = V25_2 + V25; V26_2 = V26_2 + V26; V27_2 = V27_2 + V27; V28_2 = V28_2 + V28; V29_2 = V29_2 + V29; V30_2 = V30_2 + V30;
              V31_2 = V31_2 + V31; V32_2 = V32_2 + V32; V33_2 = V33_2 + V33; V34_2 = V34_2 + V34; V35_2 = V35_2 + V35; V36_2 = V36;
              V37_2 = V37_2 + V37; V38_2 = V38_2 + V38; V39_2 = V39_2 + V39; V40_2 = V40_2 + V40; V41_2 = V41_2 + V41;
            END
            ELSE
            IF (V00 = 3) THEN
            BEGIN
              V01_3 = V01;
              V02_3 = V02_3 + V02; V03_3 = V03_3 + V03; V04_3 = V04_3 + V04; V05_3 = V05_3 + V05; V06_3 = V06_3 + V06;
              V07_3 = V07_3 + V07; V08_3 = V08_3 + V08; V09_3 = V09_3 + V09; V10_3 = V10_3 + V10; V11_3 = V11_3 + V11; V12_3 = V12_3 + V12;
              V13_3 = V13_3 + V13; V14_3 = V14_3 + V14; V15_3 = V15_3 + V15; V16_3 = V16_3 + V16; V17_3 = V17_3 + V17; V18_3 = V18_3 + V18;
              V19_3 = V19_3 + V19; V20_3 = V20_3 + V20; V21_3 = V21_3 + V21; V22_3 = V22_3 + V22; V23_3 = V23_3 + V23; V24_3 = V24_3 + V24;
              V25_3 = V25_3 + V25; V26_3 = V26_3 + V26; V27_3 = V27_3 + V27; V28_3 = V28_3 + V28; V29_3 = V29_3 + V29; V30_3 = V30_3 + V30;
              V31_3 = V31_3 + V31; V32_3 = V32_3 + V32; V33_3 = V33_3 + V33; V34_3 = V34_3 + V34; V35_3 = V35_3 + V35; V36_3 = V36;
              V37_3 = V37_3 + V37; V38_3 = V38_3 + V38; V39_3 = V39_3 + V39; V40_3 = V40_3 + V40; V41_3 = V41_3 + V41;
            END

            SUSPEND;
        END
    END

    SCHOOL_REC = 0;

    V00 = 0;
    V01 = 'по району';
    V02 = V02_0; V03 = V03_0; V04 = V04_0; V05 = V05_0; V06 = V06_0;
    V07 = V07_0; V08 = V08_0; V09 = V09_0; V10 = V10_0; V11 = V11_0; V12 = V12_0;
    V13 = V13_0; V14 = V14_0; V15 = V15_0; V16 = V16_0; V17 = V17_0; V18 = V18_0;
    V19 = V19_0; V20 = V20_0; V21 = V21_0; V22 = V22_0; V23 = V23_0; V24 = V24_0;
    V25 = V25_0; V26 = V26_0; V27 = V27_0; V28 = V28_0; V29 = V29_0; V30 = V30_0;
    V31 = V31_0; V32 = V32_0; V33 = V33_0; V34 = V34_0; V35 = V35_0; V36 = 'по району';
    V37 = V37_0; V38 = V38_0; V39 = V39_0; V40 = V40_0; V41 = V41_0;
    SUSPEND;

    V00 = 1;
    V01 = V01_1;
    V02 = V02_1; V03 = V03_1; V04 = V04_1; V05 = V05_1; V06 = V06_1;
    V07 = V07_1; V08 = V08_1; V09 = V09_1; V10 = V10_1; V11 = V11_1; V12 = V12_1;
    V13 = V13_1; V14 = V14_1; V15 = V15_1; V16 = V16_1; V17 = V17_1; V18 = V18_1;
    V19 = V19_1; V20 = V20_1; V21 = V21_1; V22 = V22_1; V23 = V23_1; V24 = V24_1;
    V25 = V25_1; V26 = V26_1; V27 = V27_1; V28 = V28_1; V29 = V29_1; V30 = V30_1;
    V31 = V31_1; V32 = V32_1; V33 = V33_1; V34 = V34_1; V35 = V35_1; V36 = V36_1;
    V37 = V37_1; V38 = V38_1; V39 = V39_1; V40 = V40_1; V41 = V41_1;
    SUSPEND;

    V00 = 2;
    V01 = V01_2;
    V02 = V02_2; V03 = V03_2; V04 = V04_2; V05 = V05_2; V06 = V06_2;
    V07 = V07_2; V08 = V08_2; V09 = V09_2; V10 = V10_2; V11 = V11_2; V12 = V12_2;
    V13 = V13_2; V14 = V14_2; V15 = V15_2; V16 = V16_2; V17 = V17_2; V18 = V18_2;
    V19 = V19_2; V20 = V20_2; V21 = V21_2; V22 = V22_2; V23 = V23_2; V24 = V24_2;
    V25 = V25_2; V26 = V26_2; V27 = V27_2; V28 = V28_2; V29 = V29_2; V30 = V30_2;
    V31 = V31_2; V32 = V32_2; V33 = V33_2; V34 = V34_2; V35 = V35_2; V36 = V36_2;
    V37 = V37_2; V38 = V38_2; V39 = V39_2; V40 = V40_2; V41 = V41_2;
    SUSPEND;

    V00 = 3;
    V01 = V01_3;
    V02 = V02_3; V03 = V03_3; V04 = V04_3; V05 = V05_3; V06 = V06_3;
    V07 = V07_3; V08 = V08_3; V09 = V09_3; V10 = V10_3; V11 = V11_3; V12 = V12_3;
    V13 = V13_3; V14 = V14_3; V15 = V15_3; V16 = V16_3; V17 = V17_3; V18 = V18_3;
    V19 = V19_3; V20 = V20_3; V21 = V21_3; V22 = V22_3; V23 = V23_3; V24 = V24_3;
    V25 = V25_3; V26 = V26_3; V27 = V27_3; V28 = V28_3; V29 = V29_3; V30 = V30_3;
    V31 = V31_3; V32 = V32_3; V33 = V33_3; V34 = V34_3; V35 = V35_3; V36 = V36_3;
    V37 = V37_3; V38 = V38_3; V39 = V39_3; V40 = V40_3; V41 = V41_3;
    SUSPEND;

    V00 = 4;
    V01 = '';
    V02 = NULL; V03 = NULL; V04 = NULL; V05 = NULL; V06 = NULL;
    V07 = NULL; V08 = NULL; V09 = NULL; V10 = NULL; V11 = NULL; V12 = NULL;
    V13 = NULL; V14 = NULL; V15 = NULL; V16 = NULL; V17 = NULL; V18 = NULL;
    V19 = NULL; V20 = NULL; V21 = NULL; V22 = NULL; V23 = NULL; V24 = NULL;
    V25 = NULL; V26 = NULL; V27 = NULL; V28 = NULL; V29 = NULL; V30 = NULL;
    V31 = NULL; V32 = NULL; V33 = NULL; V34 = NULL; V35 = NULL; V36 = '';
    V37 = NULL; V38 = NULL; V39 = NULL; V40 = NULL; V41 = NULL;
    SUSPEND;

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_PRG3_CLASSNET_OULIST (
    I$OBJ_ID BIGINT,
    I$OPF VARCHAR(1000),
    I$POD VARCHAR(1000))
RETURNS (
    OBJ_ID BIGINT,
    CAPTION VARCHAR(1000))
AS
declare variable V$NAME varchar(1000);
begin

  FOR
      SELECT L2.OBJ_ID, COALESCE(CAST(V17.VAL AS VARCHAR(30)), V2.VAL), V2.VAL
      FROM LINKS L2
      JOIN VALS V2 ON V2.OBJ_ID = L2.OBJ_ID AND V2.PARAM_ID = 2 AND V2.IS_DEL = 0
      -- Кроме фильтра по подчинению, при выборе кобра выдаем также Иные некоммерческие
      JOIN VALS V6 ON V6.OBJ_ID = L2.OBJ_ID AND V6.PARAM_ID = 6 AND V6.IS_DEL = 0
      JOIN VALL V8 ON V8.OBJ_ID = L2.OBJ_ID AND V8.PARAM_ID = 8 AND V8.IS_DEL = 0
      JOIN LISTVALS LV8 ON LV8.LISTVAL_ID = V8.LISTVAL_ID
      JOIN RES R8 ON R8.RES_ID = LV8.RES_ID AND R8.LANG_CODE = 'RU'
      LEFT JOIN VALI V17 ON V17.OBJ_ID = L2.OBJ_ID AND V17.PARAM_ID = 17 AND V17.IS_DEL = 0
      WHERE L2.PARENT_ID = :I$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
        AND (:I$POD IS NULL OR V6.VAL = :I$POD OR (:I$POD = 'Комитет по образованию Санкт-Петербурга' AND V8.LISTVAL_ID = 5408))
        AND (:I$OPF IS NULL OR R8.VAL <> :I$OPF)
      ORDER BY 2
      INTO :OBJ_ID, :CAPTION, :V$NAME
  DO
  BEGIN

      -- Если вдруг есть другая школа с таким же названием, вместо номера выдаем краткое наименование
      IF(EXISTS(
          SELECT FIRST 1 1
          FROM LINKS L2
          JOIN VALI V17 ON V17.OBJ_ID = L2.OBJ_ID AND V17.PARAM_ID = 17 AND V17.IS_DEL = 0 AND CAST(V17.VAL AS VARCHAR(30)) = :CAPTION
          WHERE L2.PARENT_ID = :I$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND L2.OBJ_ID <> :OBJ_ID
      ))
      THEN CAPTION = V$NAME;

      SUSPEND;

  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_PRG3_CLASS_FILL (
    I$OBJ_ID BIGINT,
    I$DT DATE,
    I$USER_ID BIGINT,
    I$LEVEL_ID BIGINT)
RETURNS (
    CLASS VARCHAR(1000),
    CL_RUK VARCHAR(1000),
    BOYS INTEGER,
    GIRLS INTEGER,
    TOTAL INTEGER,
    CLASS_ID BIGINT,
    COLOR CHAR(7))
AS
DECLARE VARIABLE GRADE_ID BIGINT;
DECLARE VARIABLE STAGE_ID BIGINT;
DECLARE VARIABLE SEX_ID BIGINT;
DECLARE VARIABLE SCHOLAR_ID BIGINT;
DECLARE VARIABLE GRADE VARCHAR(1000);
DECLARE VARIABLE STAGE VARCHAR(1000);
DECLARE VARIABLE GRADE_BOYS INTEGER;
DECLARE VARIABLE GRADE_GIRLS INTEGER;
DECLARE VARIABLE GRADE_TOTAL INTEGER;
DECLARE VARIABLE STAGE_BOYS INTEGER;
DECLARE VARIABLE STAGE_GIRLS INTEGER;
DECLARE VARIABLE STAGE_TOTAL INTEGER;
DECLARE VARIABLE SCHOOL_BOYS INTEGER;
DECLARE VARIABLE SCHOOL_GIRLS INTEGER;
DECLARE VARIABLE SCHOOL_TOTAL INTEGER;
DECLARE VARIABLE ITOGO VARCHAR(20);
DECLARE VARIABLE ITOGU VARCHAR(20);
DECLARE VARIABLE VSEGO VARCHAR(20);
DECLARE VARIABLE DT_IN DATE;
DECLARE VARIABLE DT_OUT DATE;
DECLARE VARIABLE V$LEVEL_ID1 BIGINT;
DECLARE VARIABLE V$LEVEL_ID2 BIGINT;
DECLARE VARIABLE LANG_CODE VARCHAR(2);
BEGIN
    SELECT LANG_CODE FROM USERS WHERE USER_ID = :I$USER_ID INTO :LANG_CODE;
    IF (I$LEVEL_ID = 22) THEN
    BEGIN
      V$LEVEL_ID1 = 26;
      V$LEVEL_ID2 = 27;
    END

    SELECT WORD FROM REPORT_WORDS WHERE ID = 19 INTO :ITOGO;
    SELECT WORD FROM REPORT_WORDS WHERE ID = 28 INTO :ITOGU;
    SELECT WORD FROM REPORT_WORDS WHERE ID = 18 INTO :VSEGO;

    SCHOOL_BOYS = 0;
    SCHOOL_GIRLS = 0;
    SCHOOL_TOTAL = 0;

    IF(I$OBJ_ID IS NULL) THEN I$OBJ_ID = (SELECT FIRST 1 OBJ_ID FROM LINKS WHERE PARENT_ID IS NULL AND OBJ_TYPE_ID = 2 AND DATE_DEL IS NULL);

    I$DT = COALESCE(:I$DT, CURRENT_DATE);

    -- Первый уровень - по уровням образования
    FOR
        SELECT L.OBJ_ID, R.VAL
        FROM LINKS L
        JOIN VALL VL ON VL.OBJ_ID = L.OBJ_ID AND VL.PARAM_ID = 43 AND VL.IS_DEL = 0
        JOIN LISTVALS LV ON LV.LISTVAL_ID = VL.LISTVAL_ID AND LV.IS_DEL = 0
        AND (:I$LEVEL_ID IS NULL OR (:I$LEVEL_ID NOT IN (22, 26, 27, 29) AND LV.PARENT_ID = :I$LEVEL_ID) OR  -- ДОО
            (LV.LISTVAL_ID = :I$LEVEL_ID AND LV.LISTVAL_ID = :V$LEVEL_ID1 AND LV.LISTVAL_ID = :V$LEVEL_ID2)) -- ОО и СПО
        LEFT JOIN RES_GET(LV.RES_ID, :LANG_CODE) R ON 1 = 1
        WHERE L.PARENT_ID = :I$OBJ_ID AND L.OBJ_TYPE_ID = 7 AND L.DATE_DEL IS NULL
        ORDER BY LV.SORT_ORDER
        INTO :GRADE_ID, :GRADE
    DO
    BEGIN
        GRADE_BOYS = 0;
        GRADE_GIRLS = 0;
        GRADE_TOTAL = 0;

        -- Второй уровень - по параллелям (этапам)
        FOR
            SELECT L.OBJ_ID, ST.VAL
            FROM LINKS L
            JOIN VALL VL ON VL.OBJ_ID = L.OBJ_ID AND VL.PARAM_ID = 49 AND VL.IS_DEL = 0
            LEFT JOIN LISTVAL_TEXT(VL.LISTVAL_ID) ST ON 1 = 1
            WHERE L.PARENT_ID = :GRADE_ID AND L.OBJ_TYPE_ID = 8 AND L.DATE_DEL IS NULL
            ORDER BY ST.SORT_ORDER
            INTO :STAGE_ID, :STAGE
        DO
        BEGIN
            STAGE_BOYS = 0;
            STAGE_GIRLS = 0;
            STAGE_TOTAL = 0;

            -- Третий уровень по классам (группам)
            FOR
                SELECT L.OBJ_ID
                FROM LINKS L
                LEFT JOIN VALS V ON V.OBJ_ID = L.OBJ_ID AND V.PARAM_ID = 54 AND V.IS_DEL = 0
                WHERE L.PARENT_ID = :STAGE_ID AND L.OBJ_TYPE_ID = 9 AND L.DATE_DEL IS NULL
                ORDER BY V.VAL
                INTO :CLASS_ID
            DO
            BEGIN
                COLOR = NULL;
                BOYS = 0;
                GIRLS = 0;
                TOTAL = 0;

                SELECT CAPTION FROM OBJECT_CAPTION_GET(:CLASS_ID) INTO :CLASS;
                SELECT V FROM VAL_GET(:CLASS_ID, 53) INTO :CL_RUK;

                -- Идем по всем учащимся, которые были зачислены в группу до указанной даты
                FOR
                    SELECT DISTINCT M.PERSON_ID, V88.LISTVAL_ID
                    FROM PERSON_MOVEMENTS M
                    JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
                    LEFT JOIN VALL V88 ON V88.PARAM_ID = 88 AND V88.OBJ_ID = M.PERSON_ID AND V88.IS_DEL = 0
                    WHERE M.DATE_DEL IS NULL AND M.DATE_IN <= :I$DT AND (M.DATE_OUT IS NULL OR M.DATE_OUT > :I$DT) AND M.GROUP_ID = :CLASS_ID
                    INTO :SCHOLAR_ID, :SEX_ID
                DO
                BEGIN
                    TOTAL = TOTAL + 1;
                    IF (SEX_ID = 183) THEN BOYS = BOYS + 1;
                    ELSE IF (SEX_ID = 182) THEN GIRLS = GIRLS + 1;
                END

                SUSPEND;

                STAGE_BOYS = STAGE_BOYS + BOYS;
                STAGE_GIRLS = STAGE_GIRLS + GIRLS;
                STAGE_TOTAL = STAGE_TOTAL + TOTAL;
            END

            CLASS_ID = NULL;
            CLASS = VSEGO;
            COLOR = '$CCFFCC';
            CL_RUK = STAGE;
            BOYS = STAGE_BOYS;
            GIRLS = STAGE_GIRLS;
            TOTAL = STAGE_TOTAL;
            SUSPEND;

            GRADE_BOYS = GRADE_BOYS + STAGE_BOYS;
            GRADE_GIRLS = GRADE_GIRLS + STAGE_GIRLS;
            GRADE_TOTAL = GRADE_TOTAL + STAGE_TOTAL;
        END

        CLASS = ITOGO;
        COLOR = '$FFCCCC';
        CL_RUK = GRADE;
        BOYS = GRADE_BOYS;
        GIRLS = GRADE_GIRLS;
        TOTAL = GRADE_TOTAL;
        SUSPEND;

        CLASS = NULL;
        COLOR = NULL;
        CL_RUK = NULL;
        BOYS = NULL;
        GIRLS = NULL;
        TOTAL = NULL;
        SUSPEND;

        SCHOOL_BOYS = SCHOOL_BOYS + GRADE_BOYS;
        SCHOOL_GIRLS = SCHOOL_GIRLS + GRADE_GIRLS;
        SCHOOL_TOTAL = SCHOOL_TOTAL + GRADE_TOTAL;
    END

    CLASS = ITOGU;
    COLOR = '$FFCC99';

    SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$OBJ_ID) INTO :CL_RUK;

    BOYS = SCHOOL_BOYS;
    GIRLS = SCHOOL_GIRLS;
    TOTAL = SCHOOL_TOTAL;
    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_PRG3_CLASS_FILL_DISTR (
    I$OBJ_ID BIGINT,
    I$DT DATE,
    I$USER_ID BIGINT)
RETURNS (
    OU VARCHAR(4000),
    CLASS VARCHAR(1000),
    BOYS INTEGER,
    GIRLS INTEGER,
    TOTAL INTEGER)
AS
declare variable LISTVAL_ID bigint;
declare variable OBJ_ID bigint;
declare variable OU_ID bigint;
declare variable GRADE_ID bigint;
declare variable STAGE_ID bigint;
declare variable CLASS_ID bigint;
declare variable SEX_ID bigint;
declare variable SCHOLAR_ID bigint;
declare variable GRADE varchar(1000);
declare variable STAGE varchar(1000);
declare variable GRADE_BOYS integer;
declare variable GRADE_GIRLS integer;
declare variable GRADE_TOTAL integer;
declare variable STAGE_BOYS integer;
declare variable STAGE_GIRLS integer;
declare variable STAGE_TOTAL integer;
declare variable SCHOOL_BOYS integer;
declare variable SCHOOL_GIRLS integer;
declare variable SCHOOL_TOTAL integer;
declare variable ITOGO varchar(20);
declare variable ITOGU varchar(20);
declare variable VSEGO varchar(20);
declare variable LANG_CODE varchar(2);
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :LANG_CODE;

    SELECT WORD FROM REPORT_WORDS WHERE ID = 19 INTO :ITOGO;
    SELECT WORD FROM REPORT_WORDS WHERE ID = 28 INTO :ITOGU;
    SELECT WORD FROM REPORT_WORDS WHERE ID = 18 INTO :VSEGO;

    SCHOOL_BOYS = 0;
    SCHOOL_GIRLS = 0;
    SCHOOL_TOTAL = 0;

    I$DT = COALESCE(:I$DT, CURRENT_DATE);

    FOR
        SELECT L2.OBJ_ID
        FROM LINKS L2
        WHERE L2.PARENT_ID = :I$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
        ORDER BY L2.OBJ_ID
        INTO :OU_ID
    DO
    BEGIN
        CLASS = NULL;
        BOYS = NULL;
        GIRLS = NULL;
        TOTAL = NULL;
        SELECT V FROM VAL_GET(:OU_ID, 2) INTO :OU;
        SUSPEND;
        OU = NULL;

        ------------------------------------

        SCHOOL_BOYS = 0;
        SCHOOL_GIRLS = 0;
        SCHOOL_TOTAL = 0;

        FOR
            SELECT L.OBJ_ID, R.VAL
            FROM LINKS L
            JOIN VALL VL ON VL.OBJ_ID = L.OBJ_ID AND VL.PARAM_ID = 43 AND VL.IS_DEL = 0
            JOIN LISTVALS LV ON LV.LISTVAL_ID = VL.LISTVAL_ID AND LV.IS_DEL = 0
            LEFT JOIN RES_GET(LV.RES_ID, :LANG_CODE) R ON 1=1
            WHERE L.PARENT_ID = :OU_ID AND L.OBJ_TYPE_ID = 7 AND L.DATE_DEL IS NULL
            ORDER BY LV.SORT_ORDER
            INTO :GRADE_ID, :GRADE
        DO
        BEGIN
            GRADE_BOYS = 0;
            GRADE_GIRLS = 0;
            GRADE_TOTAL = 0;

            FOR
                SELECT L.OBJ_ID, R.VAL
                FROM LINKS L
                JOIN VALL VL ON VL.OBJ_ID = L.OBJ_ID AND VL.PARAM_ID = 49 AND VL.IS_DEL = 0
                JOIN LISTVALS LV ON LV.LISTVAL_ID = VL.LISTVAL_ID AND LV.IS_DEL = 0
                LEFT JOIN RES_GET(LV.RES_ID,  :LANG_CODE) R ON 1=1
                WHERE L.PARENT_ID = :GRADE_ID AND L.OBJ_TYPE_ID = 8 AND L.DATE_DEL IS NULL
                ORDER BY LV.SORT_ORDER
                INTO :STAGE_ID, :STAGE
            DO
            BEGIN
                STAGE_BOYS = 0;
                STAGE_GIRLS = 0;
                STAGE_TOTAL = 0;

                FOR
                    SELECT L.OBJ_ID, C.CAPTION
                    FROM LINKS L
                    LEFT JOIN OBJECT_CAPTION_GET(L.OBJ_ID) C ON 1 = 1
                    WHERE L.PARENT_ID = :STAGE_ID AND L.OBJ_TYPE_ID = 9 AND L.DATE_DEL IS NULL
                    ORDER BY 2
                    INTO :CLASS_ID, :CLASS
                DO
                BEGIN
                    OU = NULL;
                    BOYS = 0;
                    GIRLS = 0;
                    TOTAL = 0;

                    -- Идем по всем учащимся, которые были зачислены в группу до указанной даты
                    FOR
                        SELECT DISTINCT M.PERSON_ID, V88.LISTVAL_ID
                        FROM PERSON_MOVEMENTS M
                        JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
                        LEFT JOIN VALL V88 ON V88.PARAM_ID = 88 AND V88.OBJ_ID = M.PERSON_ID AND V88.IS_DEL = 0
                        WHERE M.DATE_DEL IS NULL AND M.DATE_IN <= :I$DT AND (M.DATE_OUT IS NULL OR M.DATE_OUT > :I$DT) AND M.GROUP_ID = :CLASS_ID
                        INTO :SCHOLAR_ID, :SEX_ID
                    DO
                    BEGIN
                        TOTAL = TOTAL + 1;
                        IF (SEX_ID = 183) THEN BOYS = BOYS + 1;
                        IF (SEX_ID = 182) THEN GIRLS = GIRLS + 1;
                    END

                    SUSPEND;

                    STAGE_BOYS = STAGE_BOYS + BOYS;
                    STAGE_GIRLS = STAGE_GIRLS + GIRLS;
                    STAGE_TOTAL = STAGE_TOTAL + TOTAL;
                END

                OU = VSEGO;
                CLASS = STAGE;
                BOYS = STAGE_BOYS;
                GIRLS = STAGE_GIRLS;
                TOTAL = STAGE_TOTAL;
                SUSPEND;

                GRADE_BOYS = GRADE_BOYS + STAGE_BOYS;
                GRADE_GIRLS = GRADE_GIRLS + STAGE_GIRLS;
                GRADE_TOTAL = GRADE_TOTAL + STAGE_TOTAL;
            END

            OU = ITOGO;
            CLASS = GRADE;
            BOYS = GRADE_BOYS;
            GIRLS = GRADE_GIRLS;
            TOTAL = GRADE_TOTAL;
            SUSPEND;

            OU = NULL;
            CLASS = NULL;
            BOYS = NULL;
            GIRLS = NULL;
            TOTAL = NULL;
            SUSPEND;

            SCHOOL_BOYS = SCHOOL_BOYS + GRADE_BOYS;
            SCHOOL_GIRLS = SCHOOL_GIRLS + GRADE_GIRLS;
            SCHOOL_TOTAL = SCHOOL_TOTAL + GRADE_TOTAL;
        END

        OU = ITOGU;
        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:OU_ID)
        INTO :CLASS;

        BOYS = SCHOOL_BOYS;
        GIRLS = SCHOOL_GIRLS;
        TOTAL = SCHOOL_TOTAL;
        SUSPEND;

        ------------------------------------

        CLASS = NULL;
        BOYS = NULL;
        GIRLS = NULL;
        TOTAL = NULL;
        OU = NULL;
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_PRG3_FILL_DISTR_DOU (
    I$DISTR_ID BIGINT,
    I$OU_TYPE_NUM SMALLINT = 0,
    I$REAL_FL SMALLINT = 1,
    I$OPF_FILTER VARCHAR(1000) = null,
    I$POD_FILTER VARCHAR(1000) = null)
RETURNS (
    OU_ID BIGINT,
    NAME VARCHAR(1000),
    CNT INTEGER)
AS
declare variable V$REGION_ID bigint;
BEGIN
  SELECT FIRST 1 OBJ_ID
  FROM OBJECT_PARENTS_GET(:I$DISTR_ID, 112)
  INTO :V$REGION_ID;

  FOR
    SELECT L2.OU_ID, V1381.VAL
    FROM R_PRG3_FILL_REGION_DOU_ALL(:V$REGION_ID, :I$OPF_FILTER, :I$POD_FILTER) L2
    JOIN VALI V1381 ON V1381.OBJ_ID = L2.OU_ID AND V1381.PARAM_ID = 1381 AND V1381.IS_DEL = 0
    WHERE L2.DISTR_ID = :I$DISTR_ID AND (L2.OU_TYPE_NUM = :I$OU_TYPE_NUM OR NOT (:I$OU_TYPE_NUM BETWEEN 1 AND 3))
    INTO :OU_ID, :CNT
  DO
  BEGIN
    SELECT CAPTION FROM OBJECT_CAPTION_GET(:OU_ID) INTO :NAME;

    IF(I$REAL_FL = 0) THEN
    BEGIN
      SELECT COALESCE(V, 0) FROM VAL_GET(:OU_ID, 2168) INTO :CNT;
    END

    SUSPEND;
  END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_PRG3_FILL_REGION_DOU (
    I$REGION_ID BIGINT,
    I$OPF_FILTER VARCHAR(1000),
    I$POD_FILTER VARCHAR(1000))
RETURNS (
    DISTR_ID BIGINT,
    DISTR_NAME VARCHAR(1000),
    VAL1 INTEGER,
    VAL2 INTEGER,
    VAL3 INTEGER,
    VAL4 INTEGER,
    VAL5 INTEGER,
    VAL6 INTEGER,
    VAL7 INTEGER,
    VAL8 INTEGER,
    VAL9 INTEGER,
    VAL10 INTEGER,
    VAL11 INTEGER,
    VAL12 INTEGER)
AS
BEGIN
    FOR SELECT
            DISTR_ID,
            SUM(IIF(OU_TYPE_NUM = 1, 1, 0)) VAL1,
            SUM(IIF(OU_TYPE_NUM = 1, PLAN_CNT, 0)) VAL2,
            SUM(IIF(OU_TYPE_NUM = 1, REAL_CNT, 0)) VAL3,
            SUM(IIF(OU_TYPE_NUM = 2, 1, 0)) VAL4,
            SUM(IIF(OU_TYPE_NUM = 2, PLAN_CNT, 0)) VAL5,
            SUM(IIF(OU_TYPE_NUM = 2, REAL_CNT, 0)) VAL6,
            SUM(IIF(OU_TYPE_NUM = 3, 1, 0)) VAL7,
            SUM(IIF(OU_TYPE_NUM = 3, PLAN_CNT, 0)) VAL8,
            SUM(IIF(OU_TYPE_NUM = 3, REAL_CNT, 0)) VAL9,
            COUNT(1) VAL10,
            SUM(PLAN_CNT) VAL11,
            SUM(REAL_CNT) VAL12
        FROM (
            SELECT
                L2.DISTR_ID,
                L2.OU_ID,
                L2.OU_TYPE_NUM,
                (SELECT CAST(V AS INT) FROM VAL_GET(L2.OU_ID, 2168)) PLAN_CNT,
                V1381.VAL REAL_CNT
            FROM R_PRG3_FILL_REGION_DOU_ALL(:I$REGION_ID, :I$OPF_FILTER, :I$POD_FILTER) L2
            JOIN VALI V1381 ON V1381.OBJ_ID = L2.OU_ID AND V1381.PARAM_ID = 1381 AND V1381.IS_DEL = 0
        )
        GROUP BY DISTR_ID
        INTO :DISTR_ID, :VAL1, :VAL2, :VAL3, :VAL4, :VAL5, :VAL6, :VAL7, :VAL8, :VAL9, :VAL10, :VAL11, :VAL12
    DO
    BEGIN
        SELECT CAPTION FROM OBJECT_CAPTION_GET(:DISTR_ID) INTO :DISTR_NAME;

        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_PRG3_FILL_REGION_DOU_ALL (
    I$REGION_ID BIGINT,
    I$OPF_FILTER VARCHAR(1000) = null,
    I$POD_FILTER VARCHAR(1000) = null)
RETURNS (
    DISTR_ID BIGINT,
    OU_ID BIGINT,
    OU_TYPE_NUM SMALLINT)
AS
BEGIN
  FOR
    SELECT L111.OBJ_ID, L2.OBJ_ID,
      CASE
        WHEN V11.LISTVAL_ID = 947 THEN 1
        WHEN V11.LISTVAL_ID = 954 OR V10.LISTVAL_ID = 2216 THEN 2
        WHEN V11.LISTVAL_ID IN (958, 969, 975, 994) OR V10.LISTVAL_ID IN (979, 980) THEN 3
      END
    FROM LINKS L111
    JOIN LINKS L2 ON L2.PARENT_ID = L111.OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    JOIN VALL V11 ON V11.OBJ_ID = L2.OBJ_ID AND V11.PARAM_ID = 11 AND V11.IS_DEL = 0
    JOIN VALL V10 ON V10.OBJ_ID = L2.OBJ_ID AND V10.PARAM_ID = 10 AND V10.IS_DEL = 0
    -- Фильтр по подчинению
    LEFT JOIN VALS V6 ON V6.OBJ_ID = L2.OBJ_ID AND V6.PARAM_ID = 6 AND V6.IS_DEL = 0
    -- Включать частные ?
    LEFT JOIN VALL V8 ON V8.OBJ_ID = L2.OBJ_ID AND V8.PARAM_ID = 8 AND V8.IS_DEL = 0
    WHERE L111.PARENT_ID = :I$REGION_ID AND L111.OBJ_TYPE_ID = 111 AND L111.DATE_DEL IS NULL AND
      (:I$POD_FILTER IS NULL OR V6.VAL = :I$POD_FILTER) AND (:I$OPF_FILTER IS NULL OR :I$OPF_FILTER = 'Да' OR V8.LISTVAL_ID IS NULL OR V8.LISTVAL_ID <> 5404)
    INTO :DISTR_ID, :OU_ID, :OU_TYPE_NUM
  DO
  BEGIN
    SUSPEND;
  END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_PRG3_PERSONS_DEGREES (
    I$OBJ_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    F VARCHAR(250),
    I VARCHAR(250),
    O VARCHAR(250),
    DOVJ VARCHAR(4000),
    UCH VARCHAR(250),
    ZVAN VARCHAR(250))
AS
DECLARE VARIABLE V$ID BIGINT;
DECLARE VARIABLE LANG_CODE VARCHAR(2);
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :LANG_CODE;

    FOR SELECT L14.OBJ_ID, VS.VAL, VS1.VAL, VS2.VAL
        FROM (
            SELECT DISTINCT L14.OBJ_ID
            FROM LINKS L14
            WHERE L14.DATE_DEL IS NULL
              AND L14.OBJ_TYPE_ID = 14
              AND L14.PARENT_ID IN (
                SELECT OBJ_ID
                FROM LINKS L
                WHERE L.PARENT_ID = :I$OBJ_ID
                AND L.DATE_DEL IS NULL
                AND L.OBJ_TYPE_ID = 211
    
                UNION ALL
    
                SELECT :I$OBJ_ID
                FROM RDB$DATABASE
                )
        ) L14
        INNER JOIN VALS VS ON VS.IS_DEL = 0 AND VS.OBJ_ID = L14.OBJ_ID AND VS.PARAM_ID = 59
        INNER JOIN VALS VS1 ON VS1.IS_DEL = 0 AND VS1.OBJ_ID = L14.OBJ_ID AND VS1.PARAM_ID = 60
        INNER JOIN VALS VS2 ON VS2.IS_DEL = 0 AND VS2.OBJ_ID = L14.OBJ_ID AND VS2.PARAM_ID = 61
        ORDER BY VS.VAL
        INTO V$ID, :F, :I, :O
    DO
    BEGIN
        DOVJ = '';

        SELECT FIRST 1 R.VAL
        FROM LINKS L
        INNER JOIN VALR V69 ON V69.OBJ_ID = L.OBJ_ID
        INNER JOIN VALL V58 ON V58.OBJ_ID = V69.VAL
        INNER JOIN VALL V72 ON V72.OBJ_ID = L.OBJ_ID
        INNER JOIN LISTVALS LV ON LV.LISTVAL_ID = V58.LISTVAL_ID
        LEFT JOIN RES_GET(LV.RES_ID,  :LANG_CODE) R ON 1=1
        LEFT JOIN VALD V74 ON V74.PARAM_ID = 74 AND V74.OBJ_ID = L.OBJ_ID AND V74.IS_DEL = 0
        WHERE L.PARENT_ID = :V$ID
          AND L.OBJ_TYPE_ID = 15
          AND L.DATE_DEL IS NULL
          AND V69.PARAM_ID = 69
          AND V69.IS_DEL = 0
          AND V58.PARAM_ID = 58
          AND V58.IS_DEL = 0
          AND V72.PARAM_ID = 72
          AND V72.IS_DEL = 0
          AND V72.LISTVAL_ID = 934
          AND V74.VAL IS NULL
        INTO :DOVJ;

        UCH = '';

        ZVAN = '';

        SELECT V
        FROM VAL_GET(:V$ID, 279)
        WHERE I <> 626
        INTO :UCH;

        SELECT V
        FROM VAL_GET(:V$ID, 280)
        WHERE I <> 629
        INTO :ZVAN;

        IF ((UCH > '') OR (ZVAN > '')) THEN SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_PRG3_PERSONS_FLUOROGRAPHY (
    I$OBJ_ID BIGINT,
    I$DT DATE)
RETURNS (
    F VARCHAR(250),
    I VARCHAR(250),
    O VARCHAR(250),
    FLU DATE)
AS
DECLARE VARIABLE V$ID BIGINT;
BEGIN
    FOR SELECT L14.OBJ_ID, VS.VAL, VS1.VAL, VS2.VAL
        FROM (
            SELECT DISTINCT L14.OBJ_ID
            FROM LINKS L14
            WHERE L14.DATE_DEL IS NULL
              AND L14.OBJ_TYPE_ID = 14
              AND L14.PARENT_ID IN (
                SELECT OBJ_ID
                FROM LINKS L
                WHERE L.PARENT_ID = :I$OBJ_ID
                AND L.DATE_DEL IS NULL
                AND L.OBJ_TYPE_ID = 211
    
                UNION ALL
    
                SELECT :I$OBJ_ID
                FROM RDB$DATABASE
                )
        ) L14
        INNER JOIN VALS VS ON VS.IS_DEL = 0 AND VS.OBJ_ID = L14.OBJ_ID AND VS.PARAM_ID = 59
        INNER JOIN VALS VS1 ON VS1.IS_DEL = 0 AND VS1.OBJ_ID = L14.OBJ_ID AND VS1.PARAM_ID = 60
        INNER JOIN VALS VS2 ON VS2.IS_DEL = 0 AND VS2.OBJ_ID = L14.OBJ_ID AND VS2.PARAM_ID = 61
        ORDER BY VS.VAL
        INTO V$ID, :F, :I, :O
    DO
    BEGIN
        FLU = NULL;

        SELECT MAX(VD.VAL)
        FROM LINKS L31
        INNER JOIN VALL VL ON VL.OBJ_ID = L31.OBJ_ID
        INNER JOIN VALD VD ON VD.OBJ_ID = L31.OBJ_ID
        WHERE L31.OBJ_TYPE_ID = 31
          AND L31.DATE_DEL IS NULL
          AND L31.PARENT_ID = :V$ID
          AND VL.PARAM_ID = 214
          AND VL.LISTVAL_ID = 530
          AND VL.IS_DEL = 0
          AND VD.PARAM_ID = 213
          AND VD.IS_DEL = 0
        INTO :FLU;

        IF ((:FLU IS NULL) OR (:FLU < :I$DT)) THEN
        BEGIN
            SUSPEND;
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_PRG3_PERSON_ACHIEVE (
    I$OBJ_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    F VARCHAR(250),
    I VARCHAR(250),
    O VARCHAR(250),
    DOVJ VARCHAR(4000),
    PKPD INTEGER,
    PPO INTEGER,
    PUBL INTEGER,
    UKS INTEGER)
AS
DECLARE VARIABLE V$ID BIGINT;
DECLARE VARIABLE LANG_CODE VARCHAR(2);
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :LANG_CODE;

    FOR SELECT L14.OBJ_ID, VS.VAL, VS1.VAL, VS2.VAL
        FROM (
            SELECT DISTINCT L14.OBJ_ID
            FROM LINKS L14
            WHERE L14.DATE_DEL IS NULL
              AND L14.OBJ_TYPE_ID = 14
              AND L14.PARENT_ID IN (
                SELECT OBJ_ID
                FROM LINKS L
                WHERE L.PARENT_ID = :I$OBJ_ID
                AND L.DATE_DEL IS NULL
                AND L.OBJ_TYPE_ID = 211
    
                UNION ALL
    
                SELECT :I$OBJ_ID
                FROM RDB$DATABASE
                )
        ) L14
        INNER JOIN VALS VS ON VS.IS_DEL = 0 AND VS.OBJ_ID = L14.OBJ_ID AND VS.PARAM_ID = 59
        INNER JOIN VALS VS1 ON VS1.IS_DEL = 0 AND VS1.OBJ_ID = L14.OBJ_ID AND VS1.PARAM_ID = 60
        INNER JOIN VALS VS2 ON VS2.IS_DEL = 0 AND VS2.OBJ_ID = L14.OBJ_ID AND VS2.PARAM_ID = 61
        ORDER BY VS.VAL
        INTO V$ID, :F, :I, :O
    DO
    BEGIN
        DOVJ = '';

        SELECT FIRST 1 R.VAL
        FROM LINKS L
        INNER JOIN VALR V69 ON V69.OBJ_ID = L.OBJ_ID
        INNER JOIN VALL V58 ON V58.OBJ_ID = V69.VAL
        INNER JOIN VALL V72 ON V72.OBJ_ID = L.OBJ_ID
        INNER JOIN LISTVALS LV ON LV.LISTVAL_ID = V58.LISTVAL_ID
        LEFT JOIN RES_GET(LV.RES_ID,  :LANG_CODE) R ON 1=1
        LEFT JOIN VALD V74 ON V74.PARAM_ID = 74 AND V74.OBJ_ID = L.OBJ_ID AND V74.IS_DEL = 0
        WHERE L.PARENT_ID = :V$ID
        AND L.OBJ_TYPE_ID = 15
        AND L.DATE_DEL IS NULL
        AND V69.PARAM_ID = 69
        AND V69.IS_DEL = 0
        AND V58.PARAM_ID = 58
        AND V58.IS_DEL = 0
        AND V72.PARAM_ID = 72
        AND V72.IS_DEL = 0
        AND V72.LISTVAL_ID = 934
        AND V74.VAL IS NULL
        INTO :DOVJ;

        SELECT COUNT(*)
        FROM LINKS L39
        WHERE L39.OBJ_TYPE_ID = 41
          AND L39.DATE_DEL IS NULL
          AND L39.PARENT_ID = :V$ID
        INTO :PKPD;

        SELECT COUNT(*)
        FROM LINKS L39
        WHERE L39.OBJ_TYPE_ID = 42
          AND L39.DATE_DEL IS NULL
          AND L39.PARENT_ID = :V$ID
        INTO :PPO;

        SELECT COUNT(*)
        FROM LINKS L39
        WHERE L39.OBJ_TYPE_ID = 43
          AND L39.DATE_DEL IS NULL
          AND L39.PARENT_ID = :V$ID
        INTO :PUBL;

        SELECT COUNT(*)
        FROM LINKS L39
        WHERE L39.OBJ_TYPE_ID = 44
          AND L39.DATE_DEL IS NULL
          AND L39.PARENT_ID = :V$ID
        INTO :UKS;

        IF ((PKPD > 0) OR (PPO > 0) OR (PUBL > 0) OR (UKS > 0)) THEN  SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_PRG3_PERSON_AWARDS (
    I$OBJ_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    F VARCHAR(250),
    I VARCHAR(250),
    O VARCHAR(250),
    DOVJ VARCHAR(250),
    MED INTEGER,
    OTRN INTEGER,
    REGN INTEGER)
AS
DECLARE VARIABLE V$ID BIGINT;
DECLARE VARIABLE LANG_CODE VARCHAR(2);
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :LANG_CODE;

    FOR SELECT L14.OBJ_ID, VS.VAL, VS1.VAL, VS2.VAL
        FROM (
            SELECT DISTINCT L14.OBJ_ID
            FROM LINKS L14
            WHERE L14.DATE_DEL IS NULL
              AND L14.OBJ_TYPE_ID = 14
              AND L14.PARENT_ID IN (
                SELECT OBJ_ID
                FROM LINKS L
                WHERE L.PARENT_ID = :I$OBJ_ID
                AND L.DATE_DEL IS NULL
                AND L.OBJ_TYPE_ID = 211
    
                UNION ALL
    
                SELECT :I$OBJ_ID
                FROM RDB$DATABASE
                )
        ) L14
        INNER JOIN VALS VS ON VS.IS_DEL = 0 AND VS.OBJ_ID = L14.OBJ_ID AND VS.PARAM_ID = 59
        INNER JOIN VALS VS1 ON VS1.IS_DEL = 0 AND VS1.OBJ_ID = L14.OBJ_ID AND VS1.PARAM_ID = 60
        INNER JOIN VALS VS2 ON VS2.IS_DEL = 0 AND VS2.OBJ_ID = L14.OBJ_ID AND VS2.PARAM_ID = 61
        ORDER BY VS.VAL
        INTO :V$ID, :F, :I, :O
    DO
    BEGIN
        DOVJ = '';

        SELECT FIRST 1 R.VAL
        FROM LINKS L
        INNER JOIN VALR V69 ON V69.OBJ_ID = L.OBJ_ID
        INNER JOIN VALL V58 ON V58.OBJ_ID = V69.VAL
        INNER JOIN VALL V72 ON V72.OBJ_ID = L.OBJ_ID
        INNER JOIN LISTVALS LV ON LV.LISTVAL_ID = V58.LISTVAL_ID
        LEFT JOIN RES_GET(LV.RES_ID,  :LANG_CODE) R ON 1=1
        LEFT JOIN VALD V74 ON V74.PARAM_ID = 74 AND V74.OBJ_ID = L.OBJ_ID AND V74.IS_DEL = 0
        WHERE L.PARENT_ID = :V$ID
        AND L.OBJ_TYPE_ID = 15
        AND L.DATE_DEL IS NULL
        AND V69.PARAM_ID = 69
        AND V69.IS_DEL = 0
        AND V58.PARAM_ID = 58
        AND V58.IS_DEL = 0
        AND V72.PARAM_ID = 72
        AND V72.IS_DEL = 0
        AND V72.LISTVAL_ID = 934
        AND V74.VAL IS NULL
        INTO :DOVJ;
        
        SELECT COUNT(*)
        FROM LINKS L39
        WHERE L39.OBJ_TYPE_ID = 38
          AND L39.DATE_DEL IS NULL
          AND L39.PARENT_ID = :V$ID
        INTO :MED;

        SELECT COUNT(*)
        FROM LINKS L39
        WHERE L39.OBJ_TYPE_ID = 39
          AND L39.DATE_DEL IS NULL
          AND L39.PARENT_ID = :V$ID
        INTO :OTRN;

        SELECT COUNT(*)
        FROM LINKS L39
        WHERE L39.OBJ_TYPE_ID = 40
          AND L39.DATE_DEL IS NULL
          AND L39.PARENT_ID = :V$ID
        INTO :REGN;

        IF ((MED > 0) OR (OTRN > 0) OR (REGN > 0)) THEN  SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_PRG3_STAGE_FILL (
    I$OBJ_ID BIGINT,
    I$DT DATE,
    I$LEVEL_ID BIGINT)
RETURNS (
    STAGE VARCHAR(1000),
    C0 INTEGER,
    C1 INTEGER,
    C2 INTEGER,
    C3 INTEGER,
    C4 INTEGER,
    C5 INTEGER,
    C6 INTEGER,
    C7 INTEGER,
    C8 INTEGER,
    C9 INTEGER,
    C10 INTEGER,
    C11 INTEGER,
    C12 INTEGER,
    C13 INTEGER,
    C14 INTEGER,
    C15 INTEGER,
    C16 INTEGER,
    C17 INTEGER,
    C18 INTEGER,
    C19 INTEGER,
    CLASS INTEGER,
    CFILL INTEGER,
    GPD INTEGER,
    GPDFILL INTEGER)
AS
DECLARE VARIABLE STAGE_ID BIGINT;
DECLARE VARIABLE CLASS_ID BIGINT;
DECLARE VARIABLE OBJ_ID BIGINT;
DECLARE VARIABLE C INTEGER;
DECLARE VARIABLE X INTEGER;
DECLARE VARIABLE NUM INTEGER;
DECLARE VARIABLE S0 INTEGER = 0;
DECLARE VARIABLE S1 INTEGER = 0;
DECLARE VARIABLE S2 INTEGER = 0;
DECLARE VARIABLE S3 INTEGER = 0;
DECLARE VARIABLE S4 INTEGER = 0;
DECLARE VARIABLE S5 INTEGER = 0;
DECLARE VARIABLE S6 INTEGER = 0;
DECLARE VARIABLE S7 INTEGER = 0;
DECLARE VARIABLE S8 INTEGER = 0;
DECLARE VARIABLE S9 INTEGER = 0;
DECLARE VARIABLE S10 INTEGER = 0;
DECLARE VARIABLE S11 INTEGER = 0;
DECLARE VARIABLE S12 INTEGER = 0;
DECLARE VARIABLE S13 INTEGER = 0;
DECLARE VARIABLE S14 INTEGER = 0;
DECLARE VARIABLE S15 INTEGER = 0;
DECLARE VARIABLE S16 INTEGER = 0;
DECLARE VARIABLE S17 INTEGER = 0;
DECLARE VARIABLE S18 INTEGER = 0;
DECLARE VARIABLE S19 INTEGER = 0;
DECLARE VARIABLE SCLASS INTEGER = 0;
DECLARE VARIABLE SFILL INTEGER = 0;
DECLARE VARIABLE KCLASS INTEGER;
DECLARE VARIABLE KFILL INTEGER;
BEGIN

    IF(I$OBJ_ID IS NULL) THEN I$OBJ_ID = (SELECT FIRST 1 OBJ_ID FROM LINKS WHERE PARENT_ID IS NULL AND OBJ_TYPE_ID = 2 AND DATE_DEL IS NULL);

    FOR
        SELECT L7.OBJ_ID
        FROM LINKS L7
        JOIN VALL VL ON VL.OBJ_ID = L7.OBJ_ID AND VL.PARAM_ID = 43 AND VL.IS_DEL = 0
        JOIN LISTVALS LV ON LV.LISTVAL_ID = VL.LISTVAL_ID AND LV.IS_DEL = 0
          AND (:I$LEVEL_ID IS NULL OR (:I$LEVEL_ID NOT IN (22, 26, 27) AND LV.PARENT_ID = :I$LEVEL_ID) OR (:I$LEVEL_ID IN (22, 26, 27) AND LV.LISTVAL_ID IN (22, 26, 27)))
        JOIN OBJECT_CAPTION_GET(L7.OBJ_ID) C ON 1 = 1
        WHERE L7.PARENT_ID = :I$OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
        ORDER BY C.SORT_ORDER
        INTO :OBJ_ID
    DO
    BEGIN
        KCLASS = 0;
        KFILL = 0;
        GPD = NULL;
        GPDFILL = NULL;
        NUM = 0;
        FOR
            SELECT L8.OBJ_ID, LV.TAG
            FROM LINKS L8
            JOIN VALL VL ON VL.OBJ_ID = L8.OBJ_ID AND VL.PARAM_ID = 49 AND VL.IS_DEL = 0
            JOIN LISTVALS LV ON LV.LISTVAL_ID = VL.LISTVAL_ID
            WHERE L8.PARENT_ID = :OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
            ORDER BY LV.SORT_ORDER
            INTO :STAGE_ID, :STAGE
        DO
        BEGIN
            X = 0;
            CFILL = 0;
            NUM = 0;

            C0 = NULL;
            C1 = NULL;
            C2 = NULL;
            C3 = NULL;
            C4 = NULL;
            C5 = NULL;
            C6 = NULL;
            C7 = NULL;
            C8 = NULL;
            C9 = NULL;
            C10 = NULL;
            C11 = NULL;
            C12 = NULL;
            C13 = NULL;
            C14 = NULL;
            C15 = NULL;
            C16 = NULL;
            C17 = NULL;
            C18 = NULL;
            C19 = NULL;
    
            FOR
                SELECT L9.OBJ_ID
                FROM LINKS L9
                LEFT JOIN VALS V54 ON V54.OBJ_ID = L9.OBJ_ID AND V54.PARAM_ID = 54 AND V54.IS_DEL = 0
                WHERE L9.PARENT_ID = :STAGE_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
                ORDER BY V54.VAL
                INTO :CLASS_ID
            DO
            BEGIN
                SELECT COUNT(DISTINCT M.PERSON_ID)
                FROM PERSON_MOVEMENTS M
                WHERE M.DATE_DEL IS NULL AND M.GROUP_ID = :CLASS_ID AND (M.DATE_IN <= :I$DT OR :I$DT IS NULL) AND (M.DATE_OUT IS NULL OR M.DATE_OUT > :I$DT)
                INTO :C;

                IF (X = 0) THEN
                BEGIN
                    C0 = C;
                    S0 = S0 + C;
                END
                IF (X = 1) THEN
                BEGIN
                    C1 = C;
                    S1 = S1 + C;
                END
                IF (X = 2) THEN
                BEGIN
                    C2 = C;
                    S2 = S2 + C;
                END
                IF (X = 3) THEN
                BEGIN
                    C3 = C;
                    S3 = S3 + C;
                END
                IF (X = 4) THEN
                BEGIN
                    C4 = C;
                    S4 = S4 + C;
                END
                IF (X = 5) THEN
                BEGIN
                    C5 = C;
                    S5 = S5 + C;
                END
                IF (X = 6) THEN
                BEGIN
                    C6 = C;
                    S6 = S6 + C;
                END
                IF (X = 7) THEN
                BEGIN
                    C7 = C;
                    S7 = S7 + C;
                END
                IF (X = 8) THEN
                BEGIN
                    C8 = C;
                    S8 = S8 + C;
                END
                IF (X = 9) THEN
                BEGIN
                    C9 = C;
                    S9 = S9 + C;
                END
                IF (X = 10) THEN
                BEGIN
                    C10 = C;
                    S10 = S10 + C;
                END
                IF (X = 11) THEN
                BEGIN
                    C11 = C;
                    S11 = S11 + C;
                END
                IF (X = 12) THEN
                BEGIN
                    C12 = C;
                    S12 = S12 + C;
                END
                IF (X = 13) THEN
                BEGIN
                    C13 = C;
                    S13 = S13 + C;
                END
                IF (X = 14) THEN
                BEGIN
                    C14 = C;
                    S14 = S14 + C;
                END
                IF (X = 15) THEN
                BEGIN
                    C15 = C;
                    S15 = S15 + C;
                END
                IF (X = 16) THEN
                BEGIN
                    C16 = C;
                    S16 = S16 + C;
                END
                IF (X = 17) THEN
                BEGIN
                    C17 = C;
                    S17 = S17 + C;
                END
                IF (X = 18) THEN
                BEGIN
                    C18 = C;
                    S18 = S18 + C;
                END
                IF (X = 19) THEN
                BEGIN
                    C19 = C;
                    S19 = S19 + C;
                END
    
                IF (C > 0) THEN
                BEGIN
                    CFILL = CFILL + C;
                    SFILL = SFILL + C;
                    KFILL = KFILL + C;
                END
    
                X = X + 1;
            END
            CLASS = X;
            SCLASS = SCLASS + CLASS;
            KCLASS = KCLASS + CLASS;
    
            NUM = NUM + 1;
            SUSPEND;
        END
        IF (NUM > 0) THEN
        BEGIN
            C0 = NULL;
            C1 = NULL;
            C2 = NULL;
            C3 = NULL;
            C4 = NULL;
            C5 = NULL;
            C6 = NULL;
            C7 = NULL;
            C8 = NULL;
            C9 = NULL;
            C10 = NULL;
            C11 = NULL;
            C12 = NULL;
            C13 = NULL;
            C14 = NULL;
            C15 = NULL;
            C16 = NULL;
            C17 = NULL;
            C18 = NULL;
            C19 = NULL;
    
            CLASS = KCLASS;
            CFILL = KFILL;

            -- ГПД, куда входят классы этого уровня образования - предполагаем что группы у нас не должны удаляться в течение года
            SELECT COUNT(DISTINCT L46.OBJ_ID)
            FROM LINKS L86
            JOIN LINKS L46 ON L46.PARENT_ID = L86.OBJ_ID AND L46.OBJ_TYPE_ID = 46 AND L46.DATE_DEL IS NULL
            JOIN LINKS L9 ON L9.PARENT_ID = L46.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
            JOIN LINKS LP8 ON LP8.OBJ_ID = L9.OBJ_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
            JOIN LINKS LP7 ON LP7.OBJ_ID = LP8.PARENT_ID AND LP7.PARENT_ID = :OBJ_ID AND LP7.DATE_DEL IS NULL
            JOIN VALL V369 ON V369.OBJ_ID = L46.OBJ_ID AND V369.PARAM_ID = 369 AND V369.IS_DEL = 0 AND V369.LISTVAL_ID = 1246
            WHERE L86.PARENT_ID = :I$OBJ_ID AND L86.OBJ_TYPE_ID = 86 AND L86.DATE_DEL IS NULL
            INTO :GPD;

            SELECT COUNT(DISTINCT L10.OBJ_ID)
            FROM LINKS L86
            JOIN LINKS L46 ON L46.PARENT_ID = L86.OBJ_ID AND L46.OBJ_TYPE_ID = 46 AND L46.DATE_DEL IS NULL
            JOIN LINKS L9 ON L9.PARENT_ID = L46.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
            JOIN LINKS LP8 ON LP8.OBJ_ID = L9.OBJ_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
            JOIN LINKS LP7 ON LP7.OBJ_ID = LP8.PARENT_ID AND LP7.PARENT_ID = :OBJ_ID AND LP7.DATE_DEL IS NULL
            JOIN VALL V369 ON V369.OBJ_ID = L46.OBJ_ID AND V369.PARAM_ID = 369 AND V369.IS_DEL = 0 AND V369.LISTVAL_ID = 1246
            -- Ученики были включены в ГПД до указанной даты, исключены после указанной даты, и пробыли в ней не менее 2 дней
            JOIN LINKS L10 ON L10.PARENT_ID = L46.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND (L10.DATE_INS <= :I$DT)
              AND (L10.DATE_DEL IS NULL OR (L10.DATE_DEL > :I$DT AND DATEDIFF(DAY FROM L10.DATE_INS TO L10.DATE_DEL) > 2))
            WHERE L86.PARENT_ID = :I$OBJ_ID AND L86.OBJ_TYPE_ID = 86 AND L86.DATE_DEL IS NULL
            INTO :GPDFILL;

            -- Итого
            SELECT WORD FROM REPORT_WORDS WHERE ID = 19 INTO :STAGE;

            SUSPEND;
        END
    END

    SELECT WORD FROM REPORT_WORDS WHERE ID = 18 INTO :STAGE;

    C0 = NULL;
    C1 = NULL;
    C2 = NULL;
    C3 = NULL;
    C4 = NULL;
    C5 = NULL;
    C6 = NULL;
    C7 = NULL;
    C8 = NULL;
    C9 = NULL;
    C10 = NULL;
    C11 = NULL;
    C12 = NULL;
    C13 = NULL;
    C14 = NULL;
    C15 = NULL;
    C16 = NULL;
    C17 = NULL;
    C18 = NULL;
    C19 = NULL;


    IF (S0 > 0) THEN  C0 = S0;
    IF (S1 > 0) THEN  C1 = S1;
    IF (S2 > 0) THEN  C2 = S2;
    IF (S3 > 0) THEN  C3 = S3;
    IF (S4 > 0) THEN  C4 = S4;
    IF (S5 > 0) THEN  C5 = S5;
    IF (S6 > 0) THEN  C6 = S6;
    IF (S7 > 0) THEN  C7 = S7;
    IF (S8 > 0) THEN  C8 = S8;
    IF (S9 > 0) THEN  C9 = S9;
    IF (S10 > 0) THEN  C10 = S10;
    IF (S11 > 0) THEN  C11 = S11;
    IF (S12 > 0) THEN  C12 = S12;
    IF (S13 > 0) THEN  C13 = S13;
    IF (S14 > 0) THEN  C14 = S14;
    IF (S15 > 0) THEN  C15 = S15;
    IF (S16 > 0) THEN  C16 = S16;
    IF (S17 > 0) THEN  C17 = S17;
    IF (S18 > 0) THEN  C18 = S18;
    IF (S19 > 0) THEN  C19 = S19;
    CLASS = SCLASS;
    CFILL = SFILL;

    -- ГПД, всех уровней
    SELECT COUNT(DISTINCT L46.OBJ_ID)
    FROM LINKS L86
    JOIN LINKS L46 ON L46.PARENT_ID = L86.OBJ_ID AND L46.OBJ_TYPE_ID = 46 AND L46.DATE_DEL IS NULL
    JOIN LINKS L9 ON L9.PARENT_ID = L46.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
    JOIN LINKS LP8 ON LP8.OBJ_ID = L9.OBJ_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
    JOIN LINKS LP7 ON LP7.OBJ_ID = LP8.PARENT_ID AND LP7.PARENT_TYPE_ID = 7 AND LP7.DATE_DEL IS NULL
    JOIN LINKS LP2 ON LP2.OBJ_ID = LP7.PARENT_ID AND LP2.PARENT_ID = :I$OBJ_ID AND LP2.DATE_DEL IS NULL
    JOIN VALL V369 ON V369.OBJ_ID = L46.OBJ_ID AND V369.PARAM_ID = 369 AND V369.IS_DEL = 0 AND V369.LISTVAL_ID = 1246
    WHERE L86.PARENT_ID = :I$OBJ_ID AND L86.OBJ_TYPE_ID = 86 AND L86.DATE_DEL IS NULL
    INTO :GPD;

    SELECT COUNT(DISTINCT L10.OBJ_ID)
    FROM LINKS L86
    JOIN LINKS L46 ON L46.PARENT_ID = L86.OBJ_ID AND L46.OBJ_TYPE_ID = 46 AND L46.DATE_DEL IS NULL
    JOIN LINKS L9 ON L9.PARENT_ID = L46.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
    JOIN LINKS LP8 ON LP8.OBJ_ID = L9.OBJ_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
    JOIN LINKS LP7 ON LP7.OBJ_ID = LP8.PARENT_ID AND LP7.PARENT_TYPE_ID = 7 AND LP7.DATE_DEL IS NULL
    JOIN LINKS LP2 ON LP2.OBJ_ID = LP7.PARENT_ID AND LP2.PARENT_ID = :I$OBJ_ID AND LP2.DATE_DEL IS NULL
    JOIN VALL V369 ON V369.OBJ_ID = L46.OBJ_ID AND V369.PARAM_ID = 369 AND V369.IS_DEL = 0 AND V369.LISTVAL_ID = 1246
    -- Ученики были включены в ГПД до указанной даты, исключены после указанной даты, и пробыли в ней не менее 2 дней
    JOIN LINKS L10 ON L10.PARENT_ID = L46.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND (L10.DATE_INS <= :I$DT)
      AND (L10.DATE_DEL IS NULL OR (L10.DATE_DEL > :I$DT AND DATEDIFF(DAY FROM L10.DATE_INS TO L10.DATE_DEL) > 2))
    WHERE L86.PARENT_ID = :I$OBJ_ID AND L86.OBJ_TYPE_ID = 86 AND L86.DATE_DEL IS NULL
    INTO :GPDFILL;

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_PRG3_TARIFICATION (
    I$OBJ_ID BIGINT)
RETURNS (
    V01 VARCHAR(10),
    V02 VARCHAR(100),
    V03 VARCHAR(250),
    V04 VARCHAR(250),
    V05 VARCHAR(1000),
    V06 VARCHAR(1000),
    V07 VARCHAR(1000),
    V08 VARCHAR(100),
    V09 VARCHAR(1),
    V10 VARCHAR(1),
    V11 VARCHAR(1),
    V12 VARCHAR(30),
    V13 VARCHAR(30),
    V14 VARCHAR(30),
    V15 VARCHAR(30),
    V16 VARCHAR(30),
    V17 VARCHAR(30),
    V18 VARCHAR(30),
    V19 VARCHAR(1),
    V20 VARCHAR(1),
    V21 VARCHAR(1),
    V22 VARCHAR(1),
    V23 VARCHAR(1),
    V24 VARCHAR(1),
    V25 VARCHAR(1),
    V26 VARCHAR(1),
    V27 VARCHAR(1),
    V28 VARCHAR(1),
    V29 VARCHAR(1),
    V30 VARCHAR(1),
    V31 VARCHAR(1),
    V32 VARCHAR(1),
    V33 VARCHAR(1),
    V34 VARCHAR(1),
    V35 VARCHAR(1),
    V36 VARCHAR(1),
    V37 VARCHAR(1),
    V38 VARCHAR(1),
    V39 VARCHAR(1),
    V40 VARCHAR(1))
AS
declare variable TEACHER_ID bigint;
declare variable TEMP_TEACHER_ID bigint;
declare variable POST_VID_ID bigint;
declare variable POST_ID bigint;
declare variable EDU_TYPE_ID bigint;
declare variable EDU_ID bigint;
declare variable KV_TYPE_ID bigint;
declare variable POST_PED bigint;
declare variable C smallint;
declare variable V varchar(1000);
declare variable FV numeric(15,2);
BEGIN
    V01 = '';
    V02 = '';
    V03 = '';
    V04 = '';
    V05 = '';
    V06 = '';
    V07 = '';
    V08 = '';
    V09 = '';
    V10 = '';
    V11 = '';
    V12 = '';
    V13 = '';
    V14 = '';
    V15 = '';
    V16 = '';
    V17 = '';
    V18 = '';
    V19 = '';
    V20 = '';
    V21 = '';
    V22 = '';
    V23 = '';
    V24 = '';
    V25 = '';
    V26 = '';
    V27 = '';
    V28 = '';
    V29 = '';
    V30 = '';
    V31 = '';
    V32 = '';
    V33 = '';
    V34 = '';
    V35 = '';
    V36 = '';
    V37 = '';
    V38 = '';
    V39 = '';
    V40 = '';

    C = 0;
    TEMP_TEACHER_ID = 0;

    FOR
        SELECT L14.OBJ_ID, V72.LISTVAL_ID, L13.PARENT_ID, V66.VAL, (SELECT SORT_ORDER FROM DO_FUNC(L13.PARENT_ID, 400)) V400LISTVAL_ID
        FROM (
            SELECT DISTINCT L14.OBJ_ID
            FROM LINKS L14
            WHERE L14.DATE_DEL IS NULL AND L14.OBJ_TYPE_ID = 14 AND L14.PARENT_ID IN (
                SELECT OBJ_ID
                FROM LINKS L
                WHERE L.PARENT_ID = :I$OBJ_ID AND L.DATE_DEL IS NULL AND L.OBJ_TYPE_ID = 211
                UNION ALL
                SELECT :I$OBJ_ID FROM RDB$DATABASE
            )
        ) L14
        JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
        JOIN LINKS L13 ON L13.OBJ_ID = L15.OBJ_ID AND L13.PARENT_TYPE_ID = 13 AND L13.DATE_DEL IS NULL
        JOIN VALS V66 ON V66.OBJ_ID = L13.PARENT_ID AND V66.PARAM_ID = 66 AND V66.IS_DEL = 0
        JOIN VALL V72 ON V72.OBJ_ID = L15.OBJ_ID AND V72.PARAM_ID = 72 AND V72.IS_DEL = 0
        JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0 AND V73.VAL <= CURRENT_DATE
        LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
        WHERE ((V74.VAL IS NULL) OR (V74.VAL >= CURRENT_DATE))
        ORDER BY L14.OBJ_ID, V72.LISTVAL_ID, V400LISTVAL_ID
        INTO :TEACHER_ID, :POST_VID_ID, :POST_ID, :V04, :POST_PED
    DO
    BEGIN
        V01 = '';
        V02 = '';
        V03 = '';
        V05 = '';
        V06 = '';
        V07 = '';
        V08 = '';
        EDU_ID = NULL;
        EDU_TYPE_ID = NULL;
        KV_TYPE_ID = NULL;
        V = '';

        IF (TEMP_TEACHER_ID <> TEACHER_ID) THEN
        BEGIN
            TEMP_TEACHER_ID = TEACHER_ID;
            C = C + 1;
            V01 = C;
            SELECT V FROM VAL_GET(:TEACHER_ID, 273) INTO :V02;
            SELECT CAPTION FROM THE_CAPTION_TEACHER(:TEACHER_ID) INTO :V03;

            SELECT I, V FROM VAL_GET(:TEACHER_ID, 278) INTO :EDU_TYPE_ID, :V05;

            FOR SELECT FIRST 1 L33.OBJ_ID
                FROM LINKS L33
                JOIN VALL V284 ON V284.OBJ_ID = L33.OBJ_ID AND V284.PARAM_ID = 284 AND V284.IS_DEL = 0 AND V284.LISTVAL_ID = :EDU_TYPE_ID
                WHERE L33.PARENT_ID = :TEACHER_ID AND L33.OBJ_TYPE_ID = 33 AND L33.DATE_DEL IS NULL
                INTO :EDU_ID
            DO
            BEGIN
                SELECT :V05 || ', ' || ASCII_CHAR(10) || V.VAL
                FROM VALS V
                WHERE V.OBJ_ID = :EDU_ID AND V.PARAM_ID = 285 AND V.IS_DEL = 0
                INTO :V05;

                SELECT V.VAL
                FROM VALS V
                WHERE V.OBJ_ID = :EDU_ID AND V.PARAM_ID = 287 AND V.IS_DEL = 0
                INTO :V;

                SELECT :V05 || ', ' || ASCII_CHAR(10) || :V || ' ' || V.VAL
                FROM VALS V
                WHERE V.OBJ_ID = :EDU_ID AND V.PARAM_ID = 288 AND V.IS_DEL = 0
                INTO :V05;

                SELECT V FROM VAL_GET(:EDU_ID, 290) INTO :V;

                IF (V > '') THEN V05 = V05 || ', ' || ASCII_CHAR(10) || V;
            END

            SELECT VAL FROM VACANCY_GET_CAT(:TEACHER_ID) INTO :V06;
            SELECT V FROM VAL_GET(:TEACHER_ID, 280) WHERE I <> 629 INTO :V07;

            -- Коэффициенты
            -- K2
            SELECT F FROM VAL_GET(:TEACHER_ID, 332) INTO :FV;
            V12 = REPLACE(FV, '.', ',');
            -- K3
            SELECT F FROM VAL_GET(:TEACHER_ID, 333) INTO :FV;
            V13 = REPLACE(FV, '.', ',');
            -- K1
            SELECT F FROM VAL_GET(:TEACHER_ID, 331) INTO :FV;
            V14 = REPLACE(FV, '.', ',');
            -- K4
            SELECT F FROM VAL_GET(:TEACHER_ID, 334) INTO :FV;
            V15 = REPLACE(FV, '.', ',');
            -- K5
            SELECT F FROM VAL_GET(:TEACHER_ID, 335) INTO :FV;
            V17 = REPLACE(FV, '.', ',');
            -- K6
            SELECT F FROM VAL_GET(:TEACHER_ID, 336) INTO :FV;
            V18 = REPLACE(FV, '.', ',');

        END

        V = '';
        IF (POST_PED = 2) THEN
        BEGIN
            SELECT VAL FROM DO_FUNC(:TEACHER_ID, 463) INTO :V;
        END
        ELSE
        BEGIN
            SELECT VAL FROM DO_FUNC(:TEACHER_ID, 462) INTO :V;
        END
        IF (V > '') THEN
        BEGIN
            SELECT WORK_TIME FROM DAYS_COUNT_TO_WORK_TIME(:V) INTO :V08;
        END

        SUSPEND;
    END

END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_PRG3_TOTAL_TEACHER_LOADING (
    I$OBJ_ID BIGINT)
RETURNS (
    TEACHER_CAPTION VARCHAR(4000),
    SUMMARY_LOADING INTEGER,
    GROUP_CAPTION VARCHAR(4000),
    SUBJECT_CAPTION VARCHAR(4000),
    SUBJECT_LOADING INTEGER)
AS
declare variable TEACHER_ID bigint;
declare variable C integer;
BEGIN
    FOR
        SELECT TEACHER_ID, TEACHER_CAPTION
        FROM PARAGRAF_GRADE_TEACHERS_LIST(:I$OBJ_ID)
        ORDER BY TEACHER_CAPTION
        INTO :TEACHER_ID, :TEACHER_CAPTION
    DO
    BEGIN
        SUMMARY_LOADING = 0;
        FOR
            SELECT SUBJECT_LOADING
            FROM PARAGRAF_GRADE_TEACHER_L_LIST(:TEACHER_ID)
            INTO :C
        DO
        BEGIN
            SUMMARY_LOADING = SUMMARY_LOADING + C;
        END

        FOR
            SELECT GROUP_CAPTION, SUBJECT_CAPTION, SUBJECT_LOADING
            FROM PARAGRAF_GRADE_TEACHER_L_LIST(:TEACHER_ID)
            ORDER BY GROUP_CAPTION
            INTO :GROUP_CAPTION, :SUBJECT_CAPTION, :SUBJECT_LOADING
        DO
        BEGIN
            SUSPEND;
            TEACHER_CAPTION = NULL;
            SUMMARY_LOADING = NULL;
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_PRG3_TOTAL_WORKERS (
    I$OBJ_ID BIGINT,
    I$POD_NAME VARCHAR(1000) = null,
    I$OPF_NAME VARCHAR(1000) = null)
RETURNS (
    C BIGINT)
AS
declare variable V10 bigint = 0;
declare variable V11 bigint = 0;
declare variable V12 bigint = 0;
declare variable V13 bigint = 0;
declare variable V14 bigint = 0;
declare variable V15 bigint = 0;
declare variable V16 bigint = 0;
declare variable V17 bigint = 0;
declare variable V18 bigint = 0;
declare variable V19 bigint = 0;
declare variable V110 bigint = 0;
declare variable V111 bigint = 0;
declare variable V112 bigint = 0;
declare variable V20 bigint = 0;
declare variable V21 bigint = 0;
declare variable V22 bigint = 0;
declare variable V23 bigint = 0;
declare variable V24 bigint = 0;
declare variable V25 bigint = 0;
declare variable V26 bigint = 0;
declare variable V27 bigint = 0;
declare variable V28 bigint = 0;
declare variable V29 bigint = 0;
declare variable V210 bigint = 0;
declare variable V211 bigint = 0;
declare variable V212 bigint = 0;
declare variable V213 bigint = 0;
declare variable V214 bigint = 0;
declare variable V215 bigint = 0;
declare variable V216 bigint = 0;
declare variable OBJ_ID bigint;
declare variable LV239 bigint;
declare variable LV274 bigint;
declare variable LV278 bigint;
declare variable LV280 bigint;
declare variable LVCATEGORY bigint;
declare variable LV279 bigint;
declare variable LV587 bigint;
declare variable IS_PEDAGOG integer = 0;
declare variable V$OPF_ID bigint;
BEGIN

    I$POD_NAME = IIF(:I$POD_NAME = '', NULL, :I$POD_NAME);

    IF (:I$OPF_NAME IS NOT NULL) THEN
    BEGIN
        SELECT LISTVAL_ID
        FROM LISTVALS_LIST(258)
        WHERE VAL = :I$OPF_NAME
        INTO :V$OPF_ID;
    END

    FOR
        SELECT C1.OBJ_ID,
               V239.LISTVAL_ID,
               V274.LISTVAL_ID,
               V278.LISTVAL_ID,
               V280.LISTVAL_ID,
               VCAT.LISTVAL_ID,
               V279.LISTVAL_ID
        FROM (
            SELECT DISTINCT L14.OBJ_ID

            FROM LINKS L14
            WHERE L14.PARENT_ID IN (
                SELECT :I$OBJ_ID
                FROM RDB$DATABASE
                UNION ALL
                SELECT OBJ_ID
                FROM LINKS
                WHERE PARENT_ID = :I$OBJ_ID
                AND DATE_DEL IS NULL
                AND OBJ_TYPE_ID = 211
            )
            AND L14.OBJ_TYPE_ID = 14
            AND L14.DATE_DEL IS NULL

            UNION ALL

            SELECT DISTINCT L14.OBJ_ID
            FROM LINKS L2

            JOIN LINKS L14
            ON L14.PARENT_ID IN (
                SELECT L2.OBJ_ID
                FROM RDB$DATABASE
                UNION ALL
                SELECT OBJ_ID
                FROM LINKS
                WHERE PARENT_ID = L2.OBJ_ID
                AND DATE_DEL IS NULL
                AND OBJ_TYPE_ID = 211
            )
            AND L14.OBJ_TYPE_ID = 14
            AND L14.DATE_DEL IS NULL

            LEFT JOIN VALS V6 ON V6.OBJ_ID = L2.OBJ_ID
              AND V6.PARAM_ID = 6
              AND V6.IS_DEL = 0
            LEFT JOIN VALL V8 ON V8.OBJ_ID = L2.OBJ_ID
              AND V8.PARAM_ID = 8
              AND V8.IS_DEL = 0

            WHERE L2.PARENT_ID = :I$OBJ_ID
            AND L2.OBJ_TYPE_ID = 2
            AND L2.DATE_DEL IS NULL
            AND (:I$POD_NAME IS NULL OR V6.VAL = :I$POD_NAME)
            AND (:V$OPF_ID IS NULL OR V8.LISTVAL_ID <> :V$OPF_ID)

            UNION ALL

            SELECT DISTINCT L14.OBJ_ID
            FROM LINKS L111

            JOIN LINKS L2
            ON L2.PARENT_ID = L111.OBJ_ID
            AND L2.OBJ_TYPE_ID = 2
            AND L2.DATE_DEL IS NULL

            JOIN LINKS L14
            ON L14.PARENT_ID IN (
                SELECT L2.OBJ_ID
                FROM RDB$DATABASE
                UNION ALL
                SELECT OBJ_ID
                FROM LINKS
                WHERE PARENT_ID = L2.OBJ_ID
                AND DATE_DEL IS NULL
                AND OBJ_TYPE_ID = 211
            )
            AND L14.OBJ_TYPE_ID = 14
            AND L14.DATE_DEL IS NULL

            WHERE L111.PARENT_ID = :I$OBJ_ID
            AND L111.OBJ_TYPE_ID = 111
            AND L111.DATE_DEL IS NULL

        ) C1
        --OBJECT_CHILDREN_GET_DEEP(:I$OBJ_ID, 14, :DEEP) C1
        LEFT JOIN VALL V239 ON V239.PARAM_ID = 239 AND V239.OBJ_ID = C1.OBJ_ID AND V239.IS_DEL = 0
        LEFT JOIN VALL V274 ON V274.PARAM_ID = 274 AND V274.OBJ_ID = C1.OBJ_ID AND V274.IS_DEL = 0
        LEFT JOIN VALL V278 ON V278.PARAM_ID = 278 AND V278.OBJ_ID = C1.OBJ_ID AND V278.IS_DEL = 0
        LEFT JOIN VACANCY_GET_CAT(C1.OBJ_ID) VCAT ON 1 = 1
        LEFT JOIN VALL V280 ON V280.PARAM_ID = 280 AND V280.OBJ_ID = C1.OBJ_ID AND V280.IS_DEL = 0
        LEFT JOIN VALL V279 ON V279.PARAM_ID = 279 AND V279.OBJ_ID = C1.OBJ_ID AND V279.IS_DEL = 0
        INTO :OBJ_ID, :LV239, :LV274, :LV278, :LV280, :LVCATEGORY, :LV279
    DO
    BEGIN
        V10 = V10 + 1;
        IF (LV239 = 183) THEN V11 = V11 + 1;
        IF (LV239 = 182) THEN V12 = V12 + 1;

        LV587 = 0;

        SELECT FIRST 1 V587.LISTVAL_ID
        FROM LINKS L
        INNER JOIN VALL V72 ON V72.OBJ_ID = L.OBJ_ID
        INNER JOIN VALL V587 ON V587.OBJ_ID = L.OBJ_ID
        LEFT JOIN VALD V74 ON V74.PARAM_ID = 74 AND V74.OBJ_ID = L.OBJ_ID AND V74.IS_DEL = 0
        WHERE L.PARENT_ID = :OBJ_ID
        AND L.OBJ_TYPE_ID = 15
        AND L.DATE_DEL IS NULL
        AND V72.PARAM_ID = 72
        AND V72.IS_DEL = 0
        AND V72.LISTVAL_ID = 934
        AND V587.PARAM_ID = 587
        AND V587.IS_DEL = 0
        AND V74.VAL IS NULL
        INTO :LV587;

        IF (LV587 = 207) THEN V13 = V13 + 1;
        IF (LV587 = 208) THEN V14 = V14 + 1;
        IF (LV587 = 209) THEN V15 = V15 + 1;
        IF (LV587 IN (1720, 12824)) THEN V16 = V16 + 1;

        IF (LV274 = 602) THEN V17 = V17 + 1;
        IF (LV274 = 603) THEN V18 = V18 + 1;
        IF (LV274 = 604) THEN V19 = V19 + 1;
        IF (LV274 = 605) THEN V110 = V110 + 1;
        IF (LV274 = 606) THEN V111 = V111 + 1;
        IF (LV274 = 607) THEN V112 = V112 + 1;

        IS_PEDAGOG = 0;

        SELECT FIRST 1 1
        FROM LINKS L
        INNER JOIN VALR V69 ON V69.OBJ_ID = L.OBJ_ID
        INNER JOIN VALL V587 ON V587.OBJ_ID = L.OBJ_ID
        LEFT JOIN VALD V74 ON V74.PARAM_ID = 74 AND V74.OBJ_ID = L.OBJ_ID AND V74.IS_DEL = 0
        WHERE L.PARENT_ID = :OBJ_ID
        AND L.OBJ_TYPE_ID = 15
        AND L.DATE_DEL IS NULL
        AND V69.PARAM_ID = 69
        AND V69.IS_DEL = 0
        AND (SELECT SORT_ORDER FROM DO_FUNC(V69.VAL, 400)) = 2
        AND V587.PARAM_ID = 587
        AND V587.IS_DEL = 0
        AND V74.VAL IS NULL
        INTO :IS_PEDAGOG;

        IF (IS_PEDAGOG = 1) THEN
        BEGIN
            V20 = V20 + 1;

            IF (LV278 IN (620, 3031, 3032)) THEN V21 = V21 + 1;
            IF (LV278 = 621) THEN V22 = V22 + 1;
            IF (LV278 = 622) THEN V23 = V23 + 1;
            IF (LV278 = 623) THEN V24 = V24 + 1;
            IF (LV278 = 624) THEN V25 = V25 + 1;
            IF (LV278 = 625) THEN V26 = V26 + 1;

            IF (LVCATEGORY = 635) THEN V28 = V28 + 1;
            IF (LVCATEGORY = 634) THEN V29 = V29 + 1;
            IF (LVCATEGORY = 633) THEN V210 = V210 + 1;
            IF (LVCATEGORY = 632) THEN V211 = V211 + 1;

            IF (LV280 = 630) THEN V212 = V212 + 1;
            IF (LV280 = 631) THEN V213 = V213 + 1;
            IF (LV280 = 1207) THEN V214 = V214 + 1;

            IF (LV279 = 628) THEN V215 = V215 + 1;
            IF (LV279 = 627) THEN V216 = V216 + 1;

        END
    END

    C = V10;
    SUSPEND;
    C = NULL;
    SUSPEND;
    C = V11;
    SUSPEND;
    C = V12;
    SUSPEND;
    C = NULL;
    SUSPEND;
    C = V13;
    SUSPEND;
    C = V14;
    SUSPEND;
    C = V15;
    SUSPEND;
    C = V16;
    SUSPEND;
    C = NULL;
    SUSPEND;
    C = V17;
    SUSPEND;
    C = V18;
    SUSPEND;
    C = V19;
    SUSPEND;
    C = V110;
    SUSPEND;
    C = V111;
    SUSPEND;
    C = V112;
    SUSPEND;
    C = NULL;
    SUSPEND;

    C = V20;
    SUSPEND;
    C = NULL;
    SUSPEND;
    C = V21;
    SUSPEND;
    C = V22;
    SUSPEND;
    C = V23;
    SUSPEND;
    C = V24;
    SUSPEND;
    C = V25;
    SUSPEND;
    C = V26;
    SUSPEND;
    C = V27;
    SUSPEND;
    C = NULL;
    SUSPEND;
    C = V28;
    SUSPEND;
    C = V29;
    SUSPEND;
    C = V210;
    SUSPEND;
    C = V211;
    SUSPEND;
    C = NULL;
    SUSPEND;
    C = V212;
    SUSPEND;
    C = V213;
    SUSPEND;
    C = V214;
    SUSPEND;
    C = NULL;
    SUSPEND;
    C = V215;
    SUSPEND;
    C = V216;
    SUSPEND;

END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_PRG3_WORKERS_BIRTHDAY (
    I$OBJ_ID BIGINT)
RETURNS (
    DATEBIRTH DATE,
    F VARCHAR(250),
    I VARCHAR(250),
    O VARCHAR(250))
AS
declare variable OBJ_ID bigint;
declare variable M1 integer;
declare variable M2 integer;
declare variable D1 integer;
declare variable D2 integer;
declare variable M3 integer;
BEGIN
    -- Текущий день
    DATEBIRTH = CURRENT_DATE;
    M1 = EXTRACT(MONTH FROM DATEBIRTH);
    D1 = EXTRACT(DAY FROM DATEBIRTH);
    -- +31 день от текущего
    DATEBIRTH = DATEADD(31 DAY TO DATEBIRTH);
    M2 = EXTRACT(MONTH FROM DATEBIRTH);
    D2 = EXTRACT(DAY FROM DATEBIRTH);
    -- Если вдруг в середину попал третий месяц
    IF(M1 = 12 AND M2 = 2) THEN M3 = 1;
    ELSE IF(M2 > M1 + 1) THEN M3 = M1 + 1;

    FOR
        SELECT DISTINCT L14.OBJ_ID, VD.VAL
        FROM (
            SELECT L14.OBJ_ID
            FROM LINKS L14
            WHERE L14.DATE_DEL IS NULL AND L14.OBJ_TYPE_ID = 14 AND L14.PARENT_ID = :I$OBJ_ID
            UNION
            SELECT L14.OBJ_ID
            FROM LINKS L211
            JOIN LINKS L14 ON L14.DATE_DEL IS NULL AND L14.OBJ_TYPE_ID = 14 AND L14.PARENT_ID = L211.OBJ_ID
            WHERE L211.DATE_DEL IS NULL AND L211.OBJ_TYPE_ID = 211 AND L211.PARENT_ID = :I$OBJ_ID
        ) L14
        JOIN VALD VD ON VD.OBJ_ID = L14.OBJ_ID AND VD.PARAM_ID = 241 AND VD.IS_DEL = 0
          AND (
            (EXTRACT(MONTH FROM VD.VAL) = :M1 AND EXTRACT(DAY FROM VD.VAL) >= :D1) OR
            (EXTRACT(MONTH FROM VD.VAL) = :M2 AND EXTRACT(DAY FROM VD.VAL) <= :D2) OR
            (EXTRACT(MONTH FROM VD.VAL) = :M3)
          )
        ORDER BY EXTRACT(MONTH FROM VD.VAL), EXTRACT(DAY FROM VD.VAL)
        INTO :OBJ_ID, :DATEBIRTH
    DO
    BEGIN
        SELECT V FROM VAL_GET(:OBJ_ID, 59) INTO :F;
        SELECT V FROM VAL_GET(:OBJ_ID, 60) INTO :I;
        SELECT V FROM VAL_GET(:OBJ_ID, 61) INTO :O;

        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_PROF_DOC (
    I$OBJ_ID BIGINT NOT NULL,
    I$DOC_TYPE_ID INTEGER,
    I$DT_FROM DATE,
    I$DT_TO DATE,
    I$USER_ID BIGINT)
RETURNS (
    V1 INTEGER,
    V2 VARCHAR(250),
    V3 DATE,
    V4 VARCHAR(250),
    V5 VARCHAR(250),
    V6 VARCHAR(1000),
    V7 VARCHAR(250),
    V8 SMALLINT)
AS
BEGIN
    V1 = 0;

    FOR
        SELECT
            (SELECT V FROM VAL_GET(L10.OBJ_ID, 55, 0, :I$USER_ID))||' '||
                (SELECT V FROM VAL_GET(L10.OBJ_ID, 56, 0, :I$USER_ID))||' '||
                (SELECT V FROM VAL_GET(L10.OBJ_ID, 57, 0, :I$USER_ID)) V2,
            P566.VAL V3,
            (SELECT V FROM VAL_GET(L11.OBJ_ID, 565, 0, :I$USER_ID)) V4,
            (SELECT V FROM VAL_GET(L11.OBJ_ID, 50, 0, :I$USER_ID)) V5,
            (SELECT FIRST 1
                (SELECT V FROM VAL_GET(L245.PARENT_ID, 2119, 0, :I$USER_ID))
             FROM LINKS L245

             JOIN LINKS L247
             ON L247.PARENT_ID = L245.OBJ_ID
             AND L247.OBJ_TYPE_ID = 247
             AND L247.DATE_DEL IS NULL

             JOIN LINKS LL46
             ON LL46.PARENT_ID = L247.OBJ_ID
             AND LL46.OBJ_TYPE_ID = 46
             AND LL46.DATE_DEL IS NULL

             WHERE L245.OBJ_TYPE_ID = 245
               AND L245.PARENT_TYPE_ID = 244
               AND L245.DATE_DEL IS NULL
               AND LL46.OBJ_ID = L46.OBJ_ID
               AND (SELECT I FROM VAL_GET(L245.PARENT_ID, 2119, 0, :I$USER_ID)) IS NOT NULL) V6,
            (SELECT V FROM VAL_GET(L11.OBJ_ID, 567, 0, :I$USER_ID)) V7

        FROM LINKS L86

        JOIN LINKS L46
        ON L46.PARENT_ID = L86.OBJ_ID
        AND L46.OBJ_TYPE_ID = 46
        AND L46.DATE_DEL IS NULL

        JOIN LINKS L10
        ON L10.PARENT_ID = L46.OBJ_ID
        AND L10.OBJ_TYPE_ID = 10
        AND L10.DATE_DEL IS NULL

        JOIN LINKS L11
        ON L11.PARENT_ID = L10.OBJ_ID
        AND L11.OBJ_TYPE_ID = 11
        AND L11.DATE_DEL IS NULL

        LEFT JOIN VALD P566
        ON P566.OBJ_ID = L11.OBJ_ID
        AND P566.PARAM_ID = 566
        AND P566.IS_DEL = 0

        WHERE L86.PARENT_ID = :I$OBJ_ID
        AND L86.OBJ_TYPE_ID = 86
        AND L86.DATE_DEL IS NULL
        AND (P566.VAL IS NULL OR P566.VAL BETWEEN :I$DT_FROM AND :I$DT_TO)
        AND (:I$DOC_TYPE_ID IS NULL OR (SELECT I FROM VAL_GET(L11.OBJ_ID, 50, 0, :I$USER_ID)) IN (0, :I$DOC_TYPE_ID))

        ORDER BY V3, V6, V2

        INTO :V2, :V3, :V4, :V5, :V6, :V7
    DO
    BEGIN
        V1 = :V1 + 1;
        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_QUAL_PROGRAMS (
    I$OBJ_ID BIGINT,
    I$DT_FROM DATE,
    I$DT_TO DATE)
RETURNS (
    V305 VARCHAR(4000),
    V306 INTEGER,
    CNT INTEGER,
    V4 INTEGER,
    V5 INTEGER,
    V6 INTEGER,
    V7 INTEGER,
    V8 INTEGER,
    V9 INTEGER,
    V10 INTEGER,
    V11 INTEGER,
    V12 INTEGER,
    V13 INTEGER,
    V14 INTEGER,
    V15 INTEGER,
    V16 INTEGER,
    V17 INTEGER,
    V18 INTEGER,
    V19 INTEGER,
    V20 INTEGER,
    V21 INTEGER,
    V22 INTEGER,
    V23 INTEGER)
AS
BEGIN
    FOR
        SELECT DISTINCT
            V305.VAL,
            V306.VAL,
            COUNT(1) CNT,
            SUM(IIF(OU.OWNER_ID = 2628, 1, 0)) V4,
            SUM(IIF(OU.OWNER_ID = 2627, 1, 0)) V5,
            SUM(IIF(OU.OWNER_ID = 2620, 1, 0)) V6,
            SUM(IIF(OU.OWNER_ID = 2621, 1, 0)) V7,
            SUM(IIF(OU.OWNER_ID = 2622, 1, 0)) V8,
            SUM(IIF(OU.OWNER_ID = 2236, 1, 0)) V9,
            SUM(IIF(OU.OWNER_ID = 2626, 1, 0)) V10,
            SUM(IIF(OU.OWNER_ID = 3056, 1, 0)) V11,
            SUM(IIF(OU.OWNER_ID = 2623, 1, 0)) V12,
            SUM(IIF(OU.OWNER_ID = 3057, 1, 0)) V13,
            SUM(IIF(OU.OWNER_ID = 3058, 1, 0)) V14,
            SUM(IIF(OU.OWNER_ID = 3059, 1, 0)) V15,
            SUM(IIF(OU.OWNER_ID = 3060, 1, 0)) V16,
            SUM(IIF(OU.OWNER_ID = 3062, 1, 0)) V17,
            SUM(IIF(OU.OWNER_ID = 3061, 1, 0)) V18,
            SUM(IIF(OU.OWNER_ID = 2624, 1, 0)) V19,
            SUM(IIF(OU.OWNER_ID = 2625, 1, 0)) V20,
            SUM(IIF(OU.OWNER_ID = 3063, 1, 0)) V21,
            SUM(IIF(OU.OWNER_ID = 0, 1, 0)) V22,
            SUM(IIF(OU.OWNER_ID BETWEEN 2620 AND 2628
                 OR OU.OWNER_ID BETWEEN 3056 AND 3063
                 OR OU.OWNER_ID IN (2236, 0), 0, 1)) V23
        FROM OU_LIST_BY_ROOT(:I$OBJ_ID) OU
        JOIN LINKS L14 ON L14.PARENT_ID = OU.OBJ_ID
          AND L14.OBJ_TYPE_ID+0 = 14
          AND L14.DATE_DEL IS NULL
        JOIN LINKS L36 ON L36.PARENT_ID = L14.OBJ_ID
          AND L36.OBJ_TYPE_ID+0 = 36
          AND L36.DATE_DEL IS NULL
        JOIN VALD V310 ON V310.OBJ_ID = L36.OBJ_ID
          AND V310.PARAM_ID = 310
          AND V310.IS_DEL = 0
          AND V310.VAL BETWEEN :I$DT_FROM AND :I$DT_TO
        LEFT JOIN VALI V306 ON V306.OBJ_ID = L36.OBJ_ID
          AND V306.PARAM_ID = 306
          AND V306.IS_DEL = 0
        JOIN VALS V305 ON V305.OBJ_ID = L36.OBJ_ID
          AND V305.PARAM_ID = 305
          AND V305.IS_DEL = 0
        GROUP BY
            V305.VAL,
            V306.VAL
        INTO :V305, :V306, :CNT,
             :V4,  :V5,  :V6,  :V7,
             :V8,  :V9,  :V10, :V11,
             :V12, :V13, :V14, :V15,
             :V16, :V17, :V18, :V19,
             :V20, :V21, :V22, :V23
    DO
    BEGIN
        V4  = IIF(:V4  = 0, NULL, :V4);
        V5  = IIF(:V5  = 0, NULL, :V5);
        V6  = IIF(:V6  = 0, NULL, :V6);
        V7  = IIF(:V7  = 0, NULL, :V7);
        V8  = IIF(:V8  = 0, NULL, :V8);
        V9  = IIF(:V9  = 0, NULL, :V9);
        V10 = IIF(:V10 = 0, NULL, :V10);
        V11 = IIF(:V11 = 0, NULL, :V11);
        V12 = IIF(:V12 = 0, NULL, :V12);
        V13 = IIF(:V13 = 0, NULL, :V13);
        V14 = IIF(:V14 = 0, NULL, :V14);
        V15 = IIF(:V15 = 0, NULL, :V15);
        V16 = IIF(:V16 = 0, NULL, :V16);
        V17 = IIF(:V17 = 0, NULL, :V17);
        V18 = IIF(:V18 = 0, NULL, :V18);
        V19 = IIF(:V19 = 0, NULL, :V19);
        V20 = IIF(:V20 = 0, NULL, :V20);
        V21 = IIF(:V21 = 0, NULL, :V21);
        V22 = IIF(:V22 = 0, NULL, :V22);
        V23 = IIF(:V23 = 0, NULL, :V23);
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_QUAL_WORKERS (
    I$OBJ_ID BIGINT,
    I$DT_FROM DATE,
    I$DT_TO DATE)
RETURNS (
    V1 VARCHAR(300),
    V2 VARCHAR(1000),
    V3 INTEGER,
    V4 VARCHAR(1000),
    V5 VARCHAR(500),
    V6 VARCHAR(1000),
    V7 VARCHAR(1000),
    V8 VARCHAR(300),
    V9 INTEGER,
    V10 VARCHAR(300),
    V11 VARCHAR(100),
    V12 VARCHAR(100),
    V13 DATE)
AS
BEGIN
    FOR
        SELECT
           (SELECT CAPTION FROM OBJECT_CAPTION_GET(L14.OBJ_ID)) V1,
            V999.VAL V2,
            V17.VAL V3,
            OU.OWNER_CAPTION V4,
           (SELECT LIST(DISTINCT(SELECT V FROM VAL_GET(L15.OBJ_ID, 1394)), '; ')
            FROM LINKS L15
            JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID
              AND V73.PARAM_ID = 73
              AND V73.IS_DEL = 0
            LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID
              AND V74.PARAM_ID = 74
              AND V74.IS_DEL = 0
            WHERE L15.OBJ_TYPE_ID = 15
              AND L15.DATE_DEL IS NULL
              AND L15.PARENT_ID = L14.OBJ_ID
              AND V73.VAL <= CURRENT_DATE
              AND (V74.VAL IS NULL OR V74.VAL >= CURRENT_DATE)) V5,
            V305.VAL V6,
            (SELECT V FROM VAL_GET(L36.OBJ_ID, 304)) V7,
            (SELECT V FROM VAL_GET(L36.OBJ_ID, 1024)) V8,
            V306.VAL V9,
            (SELECT V FROM VAL_GET(L36.OBJ_ID, 307)) V10,
            (SELECT V FROM VAL_GET(L36.OBJ_ID, 308)) V11,
            (SELECT V FROM VAL_GET(L36.OBJ_ID, 309)) V12,
            V310.VAL V13
        FROM OU_LIST_BY_ROOT(:I$OBJ_ID) OU
        JOIN LINKS L14 ON L14.PARENT_ID = OU.OBJ_ID
          AND L14.OBJ_TYPE_ID+0 = 14
          AND L14.DATE_DEL IS NULL
        JOIN LINKS L36 ON L36.PARENT_ID = L14.OBJ_ID
          AND L36.OBJ_TYPE_ID+0 = 36
          AND L36.DATE_DEL IS NULL
        JOIN VALD V310 ON V310.OBJ_ID = L36.OBJ_ID
          AND V310.PARAM_ID = 310
          AND V310.IS_DEL = 0
          AND V310.VAL BETWEEN :I$DT_FROM AND :I$DT_TO
        JOIN VALS V999 ON V999.OBJ_ID = OU.OBJ_ID
          AND V999.PARAM_ID = 999
          AND V999.IS_DEL = 0
        JOIN VALI V17 ON V17.OBJ_ID = OU.OBJ_ID
          AND V17.PARAM_ID = 17
          AND V17.IS_DEL = 0
        LEFT JOIN VALS V305 ON V305.OBJ_ID = L36.OBJ_ID
          AND V305.PARAM_ID = 305
          AND V305.IS_DEL = 0
        LEFT JOIN VALI V306 ON V306.OBJ_ID = L36.OBJ_ID
          AND V306.PARAM_ID = 306
          AND V306.IS_DEL = 0
        ORDER BY 1
        INTO :V1, :V2, :V3, :V4, :V5, :V6, :V7,
             :V8, :V9, :V10, :V11, :V12, :V13
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_QUAL_WORKERS_CNT (
    I$OBJ_ID BIGINT,
    I$DT_FROM DATE,
    I$DT_TO DATE)
RETURNS (
    V1 VARCHAR(4000),
    V2 INTEGER,
    V3 VARCHAR(4000),
    V4 INTEGER,
    V5 INTEGER)
AS
BEGIN
    FOR
        SELECT
            V999.VAL,
            V17.VAL,
            OU.OWNER_CAPTION,
            OU.ALL_CNT - OU.MANAGER_CNT,
            OU.MANAGER_CNT
        FROM (
            SELECT
                OU.OBJ_ID,
                OU.OWNER_CAPTION,
                COUNT(1) ALL_CNT,
                SUM((SELECT X FROM IS_MANAGER(OU.TEACHER_ID))) MANAGER_CNT
            FROM (
                SELECT DISTINCT
                    OU.OBJ_ID,
                    OU.OWNER_CAPTION,
                    L14.OBJ_ID TEACHER_ID
                FROM OU_LIST_BY_ROOT(:I$OBJ_ID) OU
                JOIN LINKS L14 ON L14.PARENT_ID = OU.OBJ_ID
                  AND L14.OBJ_TYPE_ID+0 = 14
                  AND L14.DATE_DEL IS NULL
                JOIN LINKS L36 ON L36.PARENT_ID = L14.OBJ_ID
                  AND L36.OBJ_TYPE_ID+0 = 36
                  AND L36.DATE_DEL IS NULL
                JOIN VALD V310 ON V310.OBJ_ID = L36.OBJ_ID
                  AND V310.PARAM_ID = 310
                  AND V310.IS_DEL = 0
                  AND V310.VAL BETWEEN :I$DT_FROM AND :I$DT_TO) OU
            GROUP BY OU.OBJ_ID, OU.OWNER_CAPTION) OU
        JOIN VALS V999 ON V999.OBJ_ID = OU.OBJ_ID
          AND V999.PARAM_ID = 999
          AND V999.IS_DEL = 0
        JOIN VALI V17 ON V17.OBJ_ID = OU.OBJ_ID
          AND V17.PARAM_ID = 17
          AND V17.IS_DEL = 0
        ORDER BY 3, 2
        INTO :V1, :V2, :V3, :V4, :V5
    DO
    BEGIN
        V4  = IIF(:V4  = 0, NULL, :V4);
        V5  = IIF(:V5  = 0, NULL, :V5);
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_SCHOLAR (
    I$SCHOOL_ID BIGINT NOT NULL,
    I$USER_ID BIGINT NOT NULL,
    I$DT DATE = current_date)
RETURNS (
    SCHOLAR_ID BIGINT,
    VID_GROUP BIGINT,
    AGE_GROUP SMALLINT,
    BIRTHDATE DATE)
AS
declare variable V$DATE date;
BEGIN
    FOR SELECT
            L10.OBJ_ID SCHOLAR_ID,
            (SELECT D FROM VAL_GET(L10.OBJ_ID, 89)) BIRTHDATE,
            (SELECT I FROM VAL_GET(L9.OBJ_ID, 1549, 0, :I$USER_ID)) VID_GROUP
        FROM LINKS L7
        INNER JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID
        INNER JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID
        INNER JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID
        WHERE :I$DT >= CURRENT_DATE
          AND L7.PARENT_ID = :I$SCHOOL_ID
          AND L7.OBJ_TYPE_ID = 7
          AND L7.DATE_DEL IS NULL
          AND L8.OBJ_TYPE_ID = 8
          AND L8.DATE_DEL IS NULL
          AND L9.OBJ_TYPE_ID = 9
          AND L9.DATE_DEL IS NULL
          AND L10.OBJ_TYPE_ID = 10
          AND L10.DATE_DEL IS NULL

        UNION ALL

        SELECT
            SCHOLAR_ID,
            (SELECT D FROM VAL_GET(SCHOLAR_ID, 89)) BIRTHDATE,
            (SELECT I FROM VAL_GET(IIF(MOVE_ID = MOVE_LAST OR V438.VAL IS NULL, CLASS_ID, V438.VAL), 1549, 0, :I$USER_ID)) VID_GROUP
        FROM (
            SELECT
                SCHOLAR_ID,
                MOVE_LAST,
                CLASS_ID,
               (SELECT OBJ_ID
                FROM (
                    SELECT FIRST 1 L76.OBJ_ID, V432.LISTVAL_ID
                    FROM LINKS L76
                    INNER JOIN VALD V433 ON V433.OBJ_ID = L76.OBJ_ID
                      AND V433.PARAM_ID = 433
                      AND V433.IS_DEL = 0
                      AND (V433.VAL <= IIF(:I$DT < DT_MAX, :I$DT, DT_MAX)
                        OR V433.VAL > CURRENT_DATE)
                    INNER JOIN VALL V432 ON V432.OBJ_ID = L76.OBJ_ID
                      AND V432.PARAM_ID = 432
                      AND V432.IS_DEL = 0
                    WHERE L76.PARENT_ID = SCHOLAR_ID
                      AND L76.OBJ_TYPE_ID+0 = 76
                      AND L76.DATE_DEL IS NULL
                   ORDER BY
                       V433.VAL DESC,
                       IIF(V49_LISTVAL_ID < 100 AND V432.LISTVAL_ID = 812, 1, V432.LISTVAL_ID) DESC)
                WHERE LISTVAL_ID IN (805, 806, 807, 808, 809, 810, 3140, 3276, 3277, 3278)) MOVE_ID
            FROM (
                SELECT
                    L9.OBJ_ID CLASS_ID,
                    L10.OBJ_ID SCHOLAR_ID,
                    V49.LISTVAL_ID V49_LISTVAL_ID,
                    :I$DT DT_MAX,
                   (SELECT FIRST 1 L76.OBJ_ID
                    FROM LINKS L76
                    INNER JOIN VALD V433 ON V433.OBJ_ID = L76.OBJ_ID
                      AND V433.PARAM_ID = 433
                      AND V433.IS_DEL = 0
                    WHERE L76.PARENT_ID = L10.OBJ_ID
                      AND L76.OBJ_TYPE_ID+0 = 76
                      AND L76.DATE_DEL IS NULL
                    ORDER BY
                        V433.VAL DESC,
                        L76.OBJ_ID DESC) MOVE_LAST
                FROM LINKS L7
                INNER JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID
                  AND L8.OBJ_TYPE_ID+0 = 8
                  AND L8.DATE_DEL IS NULL
                INNER JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID
                  AND V49.PARAM_ID = 49
                  AND V49.IS_DEL = 0
                INNER JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID
                  AND L9.OBJ_TYPE_ID+0 = 9
                  AND L9.DATE_DEL IS NULL
                INNER JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID
                  AND L10.OBJ_TYPE_ID+0 = 10
                  AND L10.DATE_DEL IS NULL
                WHERE :I$DT < CURRENT_DATE
                  AND L7.PARENT_ID = :I$SCHOOL_ID
                  AND L7.OBJ_TYPE_ID+0 = 7
                  AND L7.DATE_DEL IS NULL

                UNION ALL

                SELECT
                    NULL CLASS_ID,
                    L10.OBJ_ID SCHOLAR_ID,
                    100 V49_LISTVAL_ID,
                    IIF(L82.OBJ_TYPE_ID = 83, :I$DT, (
                        SELECT MAX(V433.VAL)
                        FROM LINKS L76
                        INNER JOIN VALD V433 ON V433.OBJ_ID = L76.OBJ_ID
                          AND V433.PARAM_ID = 433
                          AND V433.IS_DEL = 0
                        INNER JOIN VALL V432 ON V432.OBJ_ID = L76.OBJ_ID
                          AND V432.PARAM_ID = 432
                          AND V432.IS_DEL = 0
                          AND V432.LISTVAL_ID = 811
                        WHERE L76.PARENT_ID = L10.OBJ_ID
                          AND L76.OBJ_TYPE_ID+0 = 76
                          AND L76.DATE_DEL IS NULL)) DT_MAX,
                    NULL MOVE_LAST
                FROM LINKS L78
                INNER JOIN LINKS L82 ON L82.PARENT_ID = L78.OBJ_ID
                  AND L82.OBJ_TYPE_ID+0 IN (82, 83)
                  AND L82.DATE_DEL IS NULL
                INNER JOIN LINKS L10 ON L10.PARENT_ID = L82.OBJ_ID
                  AND L10.OBJ_TYPE_ID+0 = 10
                  AND L10.DATE_DEL IS NULL
                WHERE :I$DT < CURRENT_DATE
                  AND L78.PARENT_ID = :I$SCHOOL_ID
                  AND L78.OBJ_TYPE_ID+0 = 78
                  AND L78.DATE_DEL IS NULL)) L10
        LEFT JOIN VALR V438 ON V438.OBJ_ID = MOVE_ID
          AND V438.PARAM_ID = 438
          AND V438.IS_DEL = 0
        WHERE MOVE_ID IS NOT NULL
        INTO :SCHOLAR_ID, :BIRTHDATE, :VID_GROUP
    DO
    BEGIN
        V$DATE = COALESCE(:BIRTHDATE, :I$DT);
        AGE_GROUP = 1;
        WHILE (:AGE_GROUP < 15) DO
        BEGIN
            V$DATE = DATEADD(6 MONTH TO V$DATE);
            IF (V$DATE > I$DT) THEN
            BEGIN
                BREAK;
            END
            AGE_GROUP = :AGE_GROUP + 1;
        END
        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_SCHOLAR2 (
    I$SCHOOL_ID BIGINT NOT NULL,
    I$USER_ID BIGINT,
    I$DT DATE = current_date)
RETURNS (
    SCHOLAR_ID BIGINT,
    VID_GROUP BIGINT,
    WORK_HOURS BIGINT,
    AGE_GROUP SMALLINT,
    BIRTHDATE DATE)
AS
declare variable V$DATE date;
BEGIN
  FOR
    SELECT DISTINCT M.PERSON_ID SCHOLAR_ID,
      (SELECT D FROM VAL_GET(M.PERSON_ID, 89)) BIRTHDATE,
      (SELECT I FROM VAL_GET(M.GROUP_ID, 1549, 0, :I$USER_ID)) VID_GROUP,
      (SELECT I FROM VAL_GET(M.GROUP_ID, 1558, 0, :I$USER_ID)) WORK_HOURS
    FROM PERSON_MOVEMENTS M
    JOIN LINKS LP8 ON LP8.OBJ_ID = M.GROUP_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
    JOIN LINKS LP7 ON LP7.OBJ_ID = LP8.PARENT_ID AND LP7.PARENT_TYPE_ID = 7 AND LP7.DATE_DEL IS NULL
    JOIN LINKS LP2 ON LP2.OBJ_ID = LP7.PARENT_ID AND LP2.PARENT_TYPE_ID = 2 AND LP2.DATE_DEL IS NULL AND LP2.PARENT_ID = :I$SCHOOL_ID
    WHERE M.DATE_DEL IS NULL AND M.GROUP_TYPE_ID = 9 AND M.DATE_IN <= :I$DT -- AND M.REASON_IN IN (3276, 3277, 3278, 810) 
      AND (M.DATE_OUT IS NULL OR M.DATE_OUT > :I$DT)
    INTO :SCHOLAR_ID, :BIRTHDATE, :VID_GROUP, :WORK_HOURS
  DO
  BEGIN
    V$DATE = COALESCE(BIRTHDATE, I$DT);
    AGE_GROUP = 1;
    WHILE (AGE_GROUP < 15) DO
    BEGIN
      V$DATE = DATEADD(6 MONTH TO V$DATE);
      IF (V$DATE > I$DT) THEN BREAK;
      AGE_GROUP = AGE_GROUP + 1;
    END
    SUSPEND;
  END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_SCHOLAR_AGE (
    I$OBJ_ID BIGINT NOT NULL,
    I$DT DATE,
    I$USER_ID BIGINT)
RETURNS (
    V1 VARCHAR(250),
    V2 VARCHAR(250),
    V3 VARCHAR(250),
    V4 VARCHAR(250),
    V5 DATE,
    V6 SMALLINT,
    V7 VARCHAR(250))
AS
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$Y1 SMALLINT;
DECLARE VARIABLE V$M1 SMALLINT;
DECLARE VARIABLE V$D1 SMALLINT;
DECLARE VARIABLE V$Y2 SMALLINT;
DECLARE VARIABLE V$M2 SMALLINT;
DECLARE VARIABLE V$D2 SMALLINT;
DECLARE VARIABLE V$VAL SMALLINT;
BEGIN
    FOR
        SELECT
            L10.OBJ_ID,
            (SELECT V FROM VAL_GET(L9.OBJ_ID, 555, 0, :I$USER_ID)) V1,
            (SELECT V FROM VAL_GET(L9.OBJ_ID, 1549, 0, :I$USER_ID)) V2,
            (SELECT V FROM VAL_GET(L9.OBJ_ID, 1558, 0, :I$USER_ID)) V3,
            (SELECT V FROM VAL_GET(L10.OBJ_ID, 55, 0, :I$USER_ID))||' '||
                (SELECT V FROM VAL_GET(L10.OBJ_ID, 56, 0, :I$USER_ID))||' '||
                (SELECT V FROM VAL_GET(L10.OBJ_ID, 57, 0, :I$USER_ID)) V4,
            (SELECT D FROM VAL_GET(L10.OBJ_ID, 89, 0, :I$USER_ID)) V5
        FROM LINKS L7
        JOIN VALL VL ON VL.OBJ_ID = L7.OBJ_ID AND VL.PARAM_ID = 43 AND VL.IS_DEL = 0
        JOIN LISTVALS LV ON LV.LISTVAL_ID = VL.LISTVAL_ID AND LV.IS_DEL = 0 AND LV.PARENT_ID = 21 --ДО
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
        JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        WHERE L7.PARENT_ID = :I$OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
        ORDER BY V1, V4
        INTO :V$OBJ_ID, :V1, :V2, :V3, :V4, :V5
    DO
    BEGIN
        V6 = EXTRACT(YEAR FROM :I$DT) - EXTRACT(YEAR FROM :V5);
        IF (EXTRACT(MONTH FROM :I$DT) * 32 + EXTRACT(DAY FROM :I$DT) < EXTRACT(MONTH FROM :V5) * 32 + EXTRACT(DAY FROM :V5)) THEN
        BEGIN
            V6 = :V6 - 1;
        END

        SELECT FIRST 1
               EXTRACT(YEAR FROM D),
               EXTRACT(MONTH FROM D),
               EXTRACT(DAY FROM D),
               EXTRACT(YEAR FROM :I$DT),
               EXTRACT(MONTH FROM :I$DT),
               EXTRACT(DAY FROM :I$DT)
        FROM VAL_TAG_GET(:V$OBJ_ID, 'BIRTHDATE')
        INTO :V$Y1, :V$M1, :V$D1, :V$Y2, :V$M2, :V$D2;
        V$VAL = V$Y2 - V$Y1;
        IF ((V$M2 * 32 + V$D2) < (V$M1 * 32 + V$D1)) THEN
        BEGIN
            V$VAL = V$VAL - 1;
        END
        V7 = CAST(V$VAL AS VARCHAR(250));
        IF ((SELECT STATUS FROM OU_LICENCE_TYPE) = 'D') THEN
        BEGIN
            -- year
            IF (V$VAL > 0) THEN
            BEGIN
                V7 = V$VAL || IIF(V$VAL = 1, ' г. ', ' л. ');
            END
            -- month
            V$VAL = V$M2 - V$M1;
            IF (V$D2 < V$D1) THEN
            BEGIN
                V$VAL = V$VAL - 1;
            END
            IF (V$VAL < 0) THEN
            BEGIN
                V$VAL = V$VAL + 12;
            END
            IF (V$VAL > 0) THEN
            BEGIN
                V7 = V7 || V$VAL ||  ' м. ';
            END
            -- day
            V$VAL = V$D2 - V$D1;
            IF (V$VAL < 0) THEN
            BEGIN
                V$VAL = V$VAL + 32;
            END
            IF (V$VAL > 0) THEN
            BEGIN
                V7 = V7 || V$VAL || ' д.';
            END
            V7 = TRIM(V7);
        END

        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_SCHOLAR_BY_NAME_GET (
    I$FIRST_NAME VARCHAR(4000))
RETURNS (
    SCHOLAR_ID BIGINT,
    OU_CAPTION VARCHAR(4000),
    CLASS_CAPTION VARCHAR(400),
    DIVISION_CAPTION VARCHAR(400),
    STRUCTURE_CAPTION VARCHAR(400),
    F VARCHAR(400),
    I VARCHAR(400),
    O VARCHAR(400),
    CLASS_ID BIGINT,
    STRUCTURE_ID BIGINT,
    DIVISION_ID BIGINT,
    LINK_ID BIGINT,
    CLASS_TYPE_ID BIGINT,
    D DATE)
AS
declare variable OBJ_ID bigint;
declare variable TYPE_ID bigint;
declare variable OU_ID bigint;
declare variable V varchar(4000);
BEGIN
    /* ROOT OBJECT: OU  OR DISTR OR REGION*/
    /* TYPE OF ROOT OBJECT: 2 - OU, 111 - DISTR, 112 - REGION  */
    SELECT FIRST 1 L.OBJ_ID, L.OBJ_TYPE_ID
    FROM LINKS L
    WHERE L.PARENT_ID IS NULL AND L.OBJ_TYPE_ID IN (2, 111, 112) AND L.DATE_DEL IS NULL
    INTO :OBJ_ID, :TYPE_ID;

    IF (:TYPE_ID = 112 AND (SELECT STATUS FROM OU_LICENCE_TYPE) = 'C') THEN TYPE_ID = 111;

    V = UPPER(I$FIRST_NAME);

    /* OU */
    IF (TYPE_ID = 2) THEN
    BEGIN
        FOR
            SELECT L10.LINK_ID, L242.PARENT_ID, L243.OBJ_ID, L243.OBJ_TYPE_ID, L10.OBJ_ID, V55.VAL, NULL, L242.OBJ_ID
            FROM LINKS L242
            JOIN LINKS L243 ON L243.PARENT_ID = L242.OBJ_ID AND L243.OBJ_TYPE_ID = 243 AND L243.DATE_DEL IS NULL
            JOIN LINKS L10 ON L10.PARENT_ID = L243.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
            JOIN VALS V55 ON V55.OBJ_ID = L10.OBJ_ID AND V55.PARAM_ID = 55 AND V55.IS_DEL = 0 AND UPPER(V55.VAL) STARTING WITH :V
            WHERE L242.PARENT_ID = :OBJ_ID AND L242.OBJ_TYPE_ID = 242 AND L242.DATE_DEL IS NULL

            UNION ALL

            SELECT L10.LINK_ID, L211.PARENT_ID, L243.OBJ_ID, L243.OBJ_TYPE_ID, L10.OBJ_ID, V55.VAL, L211.OBJ_ID, L242.OBJ_ID
            FROM LINKS L211
            JOIN LINKS L242 ON L242.PARENT_ID = L211.OBJ_ID AND L242.OBJ_TYPE_ID = 242 AND L242.DATE_DEL IS NULL
            JOIN LINKS L243 ON L243.PARENT_ID = L242.OBJ_ID AND L243.OBJ_TYPE_ID = 243 AND L243.DATE_DEL IS NULL
            JOIN LINKS L10 ON L10.PARENT_ID = L243.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
            JOIN VALS V55 ON V55.OBJ_ID = L10.OBJ_ID AND V55.PARAM_ID = 55 AND V55.IS_DEL = 0 AND UPPER(V55.VAL) STARTING WITH :V
            WHERE L211.PARENT_ID = :OBJ_ID AND L211.OBJ_TYPE_ID = 211 AND L211.DATE_DEL IS NULL

            UNION

            SELECT L10.LINK_ID, L7.PARENT_ID, L9.OBJ_ID, L9.OBJ_TYPE_ID, L10.OBJ_ID, V55.VAL, NULL, NULL
            FROM LINKS L7
            JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
            JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 125, 187) AND L9.DATE_DEL IS NULL
            JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
            JOIN VALS V55 ON V55.OBJ_ID = L10.OBJ_ID AND V55.PARAM_ID = 55 AND V55.IS_DEL = 0 AND UPPER(V55.VAL) STARTING WITH :V
            WHERE L7.PARENT_ID = :OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL

            UNION

            SELECT L10.LINK_ID, L78.PARENT_ID, L81.OBJ_ID, L81.OBJ_TYPE_ID, L10.OBJ_ID, V55.VAL, NULL, NULL
            FROM LINKS L78
            JOIN LINKS L81 ON L81.PARENT_ID = L78.OBJ_ID AND L81.OBJ_TYPE_ID = 81 AND L81.DATE_DEL IS NULL
            JOIN LINKS L10 ON L10.PARENT_ID = L81.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
            JOIN VALS V55 ON V55.OBJ_ID = L10.OBJ_ID AND V55.PARAM_ID = 55 AND V55.IS_DEL = 0 AND UPPER(V55.VAL) STARTING WITH :V
            WHERE L78.PARENT_ID = :OBJ_ID AND L78.OBJ_TYPE_ID = 78 AND L78.DATE_DEL IS NULL

            UNION

            SELECT L10.LINK_ID, L78.PARENT_ID, L82.OBJ_ID, L82.OBJ_TYPE_ID, L10.OBJ_ID, V55.VAL, NULL, NULL
            FROM LINKS L78
            JOIN LINKS L82 ON L82.PARENT_ID = L78.OBJ_ID AND L82.OBJ_TYPE_ID = 82 AND L82.DATE_DEL IS NULL
            JOIN LINKS L10 ON L10.PARENT_ID = L82.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
            JOIN VALS V55 ON V55.OBJ_ID = L10.OBJ_ID AND V55.PARAM_ID = 55 AND V55.IS_DEL = 0 AND UPPER(V55.VAL) STARTING WITH :V
            WHERE L78.PARENT_ID = :OBJ_ID AND L78.OBJ_TYPE_ID = 78 AND L78.DATE_DEL IS NULL

            UNION

            SELECT L10.LINK_ID, L78.PARENT_ID, L83.OBJ_ID, L83.OBJ_TYPE_ID, L10.OBJ_ID, V55.VAL,NULL, NULL
            FROM LINKS L78
            JOIN LINKS L83 ON L83.PARENT_ID = L78.OBJ_ID AND L83.OBJ_TYPE_ID = 83 AND L83.DATE_DEL IS NULL
            JOIN LINKS L10 ON L10.PARENT_ID = L83.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
            JOIN VALS V55 ON V55.OBJ_ID = L10.OBJ_ID AND V55.PARAM_ID = 55 AND V55.IS_DEL = 0 AND UPPER(V55.VAL) STARTING WITH :V
            WHERE L78.PARENT_ID = :OBJ_ID AND L78.OBJ_TYPE_ID = 78 AND L78.DATE_DEL IS NULL

            UNION

            SELECT L10.LINK_ID, L7.PARENT_ID, L289.OBJ_ID, L289.OBJ_TYPE_ID, L10.OBJ_ID, V55.VAL, NULL, NULL
            FROM LINKS L7
            JOIN LINKS L289 ON L289.PARENT_ID = L7.OBJ_ID AND L289.OBJ_TYPE_ID = 289 AND L289.DATE_DEL IS NULL
            JOIN LINKS L10 ON L10.PARENT_ID = L289.OBJ_ID AND L10.OBJ_TYPE_ID = 10AND L10.DATE_DEL IS NULL
            JOIN VALS V55 ON V55.OBJ_ID = L10.OBJ_ID AND V55.PARAM_ID = 55 AND V55.IS_DEL = 0 AND UPPER(V55.VAL) STARTING WITH :V
            WHERE L7.PARENT_ID = :OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL

            INTO :LINK_ID, :OU_ID, :CLASS_ID, :CLASS_TYPE_ID, :SCHOLAR_ID, :F, :STRUCTURE_ID, :DIVISION_ID
        DO
        BEGIN
            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:OU_ID)
            INTO :OU_CAPTION;

            IF (STRUCTURE_ID IS NOT NULL) THEN
            BEGIN
                SELECT CAPTION
                FROM OBJECT_CAPTION_GET(:STRUCTURE_ID)
                INTO :STRUCTURE_CAPTION;
            END
            ELSE
            BEGIN
                STRUCTURE_CAPTION = OU_CAPTION;
            END

            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:DIVISION_ID)
            INTO :DIVISION_CAPTION;

            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:CLASS_ID)
            INTO :CLASS_CAPTION;

            SELECT V
            FROM VAL_GET(:SCHOLAR_ID, 56)
            INTO :I;

            SELECT V
            FROM VAL_GET(:SCHOLAR_ID, 57)
            INTO :O;

            SELECT D
            FROM VAL_GET(:SCHOLAR_ID, 89)
            INTO :D;

            SUSPEND;
        END
    END

    /* DISTRICT */
    IF (TYPE_ID = 111) THEN
    BEGIN
        FOR
            SELECT L10.LINK_ID,
                   L2.OBJ_ID,
                   L243.OBJ_ID,
                   L243.OBJ_TYPE_ID,
                   L10.OBJ_ID,
                   V55.VAL,
                   NULL,
                   L242.OBJ_ID

            FROM LINKS L2

            JOIN LINKS L242
            ON L242.PARENT_ID = L2.OBJ_ID
            AND L242.OBJ_TYPE_ID = 242
            AND L242.DATE_DEL IS NULL

            JOIN LINKS L243
            ON L243.PARENT_ID = L242.OBJ_ID
            AND L243.OBJ_TYPE_ID = 243
            AND L243.DATE_DEL IS NULL

            JOIN LINKS L10
            ON L10.PARENT_ID = L243.OBJ_ID
            AND L10.OBJ_TYPE_ID = 10
            AND L10.DATE_DEL IS NULL

            JOIN VALS V55
            ON V55.OBJ_ID = L10.OBJ_ID
            AND V55.PARAM_ID = 55
            AND V55.IS_DEL = 0
            AND UPPER(V55.VAL) STARTING WITH :V

            WHERE L2.PARENT_ID = :OBJ_ID
            AND L2.OBJ_TYPE_ID = 2
            AND L2.DATE_DEL IS NULL

            UNION

            SELECT L10.LINK_ID,
                   L7.PARENT_ID,
                   L9.OBJ_ID,
                   L9.OBJ_TYPE_ID,
                   L10.OBJ_ID,
                   V55.VAL,
                   NULL, 
                   NULL
            FROM LINKS L2

            JOIN LINKS L7
            ON L7.PARENT_ID = L2.OBJ_ID
            AND L7.OBJ_TYPE_ID = 7
            AND L7.DATE_DEL IS NULL

            JOIN LINKS L8
            ON L8.PARENT_ID = L7.OBJ_ID
            AND L8.OBJ_TYPE_ID = 8
            AND L8.DATE_DEL IS NULL

            JOIN LINKS L9
            ON L9.PARENT_ID = L8.OBJ_ID
            AND L9.OBJ_TYPE_ID IN (9, 125, 187)
            AND L9.DATE_DEL IS NULL

            JOIN LINKS L10
            ON L10.PARENT_ID = L9.OBJ_ID
            AND L10.OBJ_TYPE_ID = 10
            AND L10.DATE_DEL IS NULL

            JOIN VALS V55
            ON V55.OBJ_ID = L10.OBJ_ID
            AND V55.PARAM_ID = 55
            AND V55.IS_DEL = 0
            AND UPPER(V55.VAL) STARTING WITH :V

            WHERE L2.PARENT_ID = :OBJ_ID
            AND L2.OBJ_TYPE_ID = 2
            AND L2.DATE_DEL IS NULL

            UNION

            SELECT L10.LINK_ID,
                   L78.PARENT_ID,
                   L81.OBJ_ID,
                   L81.OBJ_TYPE_ID,
                   L10.OBJ_ID,
                   V55.VAL,
                   NULL, 
                   NULL

            FROM LINKS L2

            JOIN LINKS L78
            ON L78.PARENT_ID = L2.OBJ_ID
            AND L78.OBJ_TYPE_ID = 78
            AND L78.DATE_DEL IS NULL

            JOIN LINKS L81
            ON L81.PARENT_ID = L78.OBJ_ID
            AND L81.OBJ_TYPE_ID = 81
            AND L81.DATE_DEL IS NULL

            JOIN LINKS L10
            ON L10.PARENT_ID = L81.OBJ_ID
            AND L10.OBJ_TYPE_ID = 10
            AND L10.DATE_DEL IS NULL

            JOIN VALS V55
            ON V55.OBJ_ID = L10.OBJ_ID
            AND V55.PARAM_ID = 55
            AND V55.IS_DEL = 0
            AND UPPER(V55.VAL) STARTING WITH :V

            WHERE L2.PARENT_ID = :OBJ_ID
            AND L2.OBJ_TYPE_ID = 2
            AND L2.DATE_DEL IS NULL

            UNION

            SELECT L10.LINK_ID,
                   L78.PARENT_ID,
                   L82.OBJ_ID,
                   L82.OBJ_TYPE_ID,
                   L10.OBJ_ID,
                   V55.VAL,
                   NULL, 
                   NULL

            FROM LINKS L2

            JOIN LINKS L78
            ON L78.PARENT_ID = L2.OBJ_ID
            AND L78.OBJ_TYPE_ID = 78
            AND L78.DATE_DEL IS NULL

            JOIN LINKS L82
            ON L82.PARENT_ID = L78.OBJ_ID
            AND L82.OBJ_TYPE_ID = 82
            AND L82.DATE_DEL IS NULL

            JOIN LINKS L10
            ON L10.PARENT_ID = L82.OBJ_ID
            AND L10.OBJ_TYPE_ID = 10
            AND L10.DATE_DEL IS NULL

            JOIN VALS V55
            ON V55.OBJ_ID = L10.OBJ_ID
            AND V55.PARAM_ID = 55
            AND V55.IS_DEL = 0
            AND UPPER(V55.VAL) STARTING WITH :V

            WHERE L2.PARENT_ID = :OBJ_ID
            AND L2.OBJ_TYPE_ID = 2
            AND L2.DATE_DEL IS NULL

            UNION

            SELECT L10.LINK_ID,
                   L78.PARENT_ID,
                   L83.OBJ_ID,
                   L83.OBJ_TYPE_ID,
                   L10.OBJ_ID,
                   V55.VAL,
                   NULL, 
                   NULL

            FROM LINKS L2

            JOIN LINKS L78
            ON L78.PARENT_ID = L2.OBJ_ID
            AND L78.OBJ_TYPE_ID = 78
            AND L78.DATE_DEL IS NULL

            JOIN LINKS L83
            ON L83.PARENT_ID = L78.OBJ_ID
            AND L83.OBJ_TYPE_ID = 83
            AND L83.DATE_DEL IS NULL

            JOIN LINKS L10
            ON L10.PARENT_ID = L83.OBJ_ID
            AND L10.OBJ_TYPE_ID = 10
            AND L10.DATE_DEL IS NULL

            JOIN VALS V55
            ON V55.OBJ_ID = L10.OBJ_ID
            AND V55.PARAM_ID = 55
            AND V55.IS_DEL = 0
            AND UPPER(V55.VAL) STARTING WITH :V

            WHERE L2.PARENT_ID = :OBJ_ID
            AND L2.OBJ_TYPE_ID = 2
            AND L2.DATE_DEL IS NULL

            UNION

            SELECT L10.LINK_ID,
                   L7.PARENT_ID,
                   L289.OBJ_ID,
                   L289.OBJ_TYPE_ID,
                   L10.OBJ_ID,
                   V55.VAL,
                   NULL, 
                   NULL

            FROM LINKS L2

            JOIN LINKS L7
            ON L7.PARENT_ID = L2.OBJ_ID
            AND L7.OBJ_TYPE_ID = 7
            AND L7.DATE_DEL IS NULL

            JOIN LINKS L289
            ON L289.PARENT_ID = L7.OBJ_ID
            AND L289.OBJ_TYPE_ID = 289
            AND L289.DATE_DEL IS NULL

            JOIN LINKS L10
            ON L10.PARENT_ID = L289.OBJ_ID
            AND L10.OBJ_TYPE_ID = 10
            AND L10.DATE_DEL IS NULL

            JOIN VALS V55
            ON V55.OBJ_ID = L10.OBJ_ID
            AND V55.PARAM_ID = 55
            AND V55.IS_DEL = 0
            AND UPPER(V55.VAL) STARTING WITH :V

            WHERE L2.PARENT_ID = :OBJ_ID
            AND L2.OBJ_TYPE_ID = 2
            AND L2.DATE_DEL IS NULL

            UNION

            SELECT L10.LINK_ID,
                   L211.PARENT_ID,
                   L243.OBJ_ID,
                   L243.OBJ_TYPE_ID,
                   L10.OBJ_ID,
                   V55.VAL,
                   L211.OBJ_ID,
                   L242.OBJ_ID

            FROM LINKS L2

            JOIN LINKS L211
            ON L211.PARENT_ID = L2.OBJ_ID
            AND L211.OBJ_TYPE_ID = 211
            AND L211.DATE_DEL IS NULL

            JOIN LINKS L242
            ON L242.PARENT_ID = L211.OBJ_ID
            AND L242.OBJ_TYPE_ID = 242
            AND L242.DATE_DEL IS NULL

            JOIN LINKS L243
            ON L243.PARENT_ID = L242.OBJ_ID
            AND L243.OBJ_TYPE_ID = 243
            AND L243.DATE_DEL IS NULL

            JOIN LINKS L10
            ON L10.PARENT_ID = L243.OBJ_ID
            AND L10.OBJ_TYPE_ID = 10
            AND L10.DATE_DEL IS NULL

            JOIN VALS V55
            ON V55.OBJ_ID = L10.OBJ_ID
            AND V55.PARAM_ID = 55
            AND V55.IS_DEL = 0
            AND UPPER(V55.VAL) STARTING WITH :V

            WHERE L2.PARENT_ID = :OBJ_ID
            AND L2.OBJ_TYPE_ID = 2
            AND L2.DATE_DEL IS NULL

            UNION

            SELECT L10.LINK_ID,
                   L242.PARENT_ID,
                   L243.OBJ_ID,
                   L243.OBJ_TYPE_ID,
                   L10.OBJ_ID,
                   V55.VAL,
                   NULL,
                   L242.OBJ_ID

            FROM LINKS L2

            JOIN LINKS L242
            ON L242.PARENT_ID = L2.OBJ_ID
            AND L242.OBJ_TYPE_ID = 242
            AND L242.DATE_DEL IS NULL

            JOIN LINKS L243
            ON L243.PARENT_ID = L242.OBJ_ID
            AND L243.OBJ_TYPE_ID = 243
            AND L243.DATE_DEL IS NULL

            JOIN LINKS L10
            ON L10.PARENT_ID = L243.OBJ_ID
            AND L10.OBJ_TYPE_ID = 10
            AND L10.DATE_DEL IS NULL

            JOIN VALS V55
            ON V55.OBJ_ID = L10.OBJ_ID
            AND V55.PARAM_ID = 55
            AND V55.IS_DEL = 0
            AND UPPER(V55.VAL) STARTING WITH :V

            WHERE L2.PARENT_ID = :OBJ_ID
            AND L2.OBJ_TYPE_ID = 2
            AND L2.DATE_DEL IS NULL

            INTO :LINK_ID,
                 :OU_ID,
                 :CLASS_ID,
                 :CLASS_TYPE_ID,
                 :SCHOLAR_ID,
                 :F,
                 :STRUCTURE_ID,
                 :DIVISION_ID
        DO
        BEGIN
            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:OU_ID)
            INTO :OU_CAPTION;

            IF (STRUCTURE_ID IS NOT NULL) THEN
            BEGIN
                SELECT CAPTION
                FROM OBJECT_CAPTION_GET(:STRUCTURE_ID)
                INTO :STRUCTURE_CAPTION;
            END
            ELSE
            BEGIN
                STRUCTURE_CAPTION = OU_CAPTION;
            END

            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:DIVISION_ID)
            INTO :DIVISION_CAPTION;

            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:CLASS_ID)
            INTO :CLASS_CAPTION;

            SELECT V
            FROM VAL_GET(:SCHOLAR_ID, 56)
            INTO :I;

            SELECT V
            FROM VAL_GET(:SCHOLAR_ID, 57)
            INTO :O;

            SELECT D
            FROM VAL_GET(:SCHOLAR_ID, 89)
            INTO :D;

            SUSPEND;
        END
    END

    /* REGION */
    IF (TYPE_ID = 112) THEN
    BEGIN
        FOR
            SELECT L10.LINK_ID,
                   L2.OBJ_ID,
                   L243.OBJ_ID,
                   L243.OBJ_TYPE_ID,
                   L10.OBJ_ID,
                   V55.VAL,
                   NULL,
                   L242.OBJ_ID

            FROM LINKS L111

            JOIN LINKS L2
            ON L2.PARENT_ID = L111.OBJ_ID
            AND L2.OBJ_TYPE_ID = 2
            AND L2.DATE_DEL IS NULL

            JOIN LINKS L242
            ON L242.PARENT_ID = L2.OBJ_ID
            AND L242.OBJ_TYPE_ID = 242
            AND L242.DATE_DEL IS NULL

            JOIN LINKS L243
            ON L243.PARENT_ID = L242.OBJ_ID
            AND L243.OBJ_TYPE_ID = 243
            AND L243.DATE_DEL IS NULL

            JOIN LINKS L10
            ON L10.PARENT_ID = L243.OBJ_ID
            AND L10.OBJ_TYPE_ID = 10
            AND L10.DATE_DEL IS NULL

            JOIN VALS V55
            ON V55.OBJ_ID = L10.OBJ_ID
            AND V55.PARAM_ID = 55
            AND V55.IS_DEL = 0
            AND UPPER(V55.VAL) STARTING WITH :V

            WHERE L111.PARENT_ID = :OBJ_ID
            AND L111.OBJ_TYPE_ID = 111
            AND L111.DATE_DEL IS NULL

            UNION

            SELECT L10.LINK_ID,
                   L7.PARENT_ID,
                   L9.OBJ_ID,
                   L9.OBJ_TYPE_ID,
                   L10.OBJ_ID,
                   V55.VAL,
                   NULL,
                   NULL

            FROM LINKS L111

            JOIN LINKS L2
            ON L2.PARENT_ID =  L111.OBJ_ID
            AND L2.OBJ_TYPE_ID = 2
            AND L2.DATE_DEL IS NULL

            JOIN LINKS L7
            ON L7.PARENT_ID = L2.OBJ_ID
            AND L7.OBJ_TYPE_ID = 7
            AND L7.DATE_DEL IS NULL

            JOIN LINKS L8
            ON L8.PARENT_ID = L7.OBJ_ID
            AND L8.OBJ_TYPE_ID = 8
            AND L8.DATE_DEL IS NULL

            JOIN LINKS L9
            ON L9.PARENT_ID = L8.OBJ_ID
            AND L9.OBJ_TYPE_ID IN (9, 125, 187)
            AND L9.DATE_DEL IS NULL

            JOIN LINKS L10
            ON L10.PARENT_ID = L9.OBJ_ID
            AND L10.OBJ_TYPE_ID = 10
            AND L10.DATE_DEL IS NULL

            JOIN VALS V55
            ON V55.OBJ_ID = L10.OBJ_ID
            AND V55.PARAM_ID = 55
            AND V55.IS_DEL = 0
            AND UPPER(V55.VAL) STARTING WITH :V

            WHERE L111.PARENT_ID = :OBJ_ID
            AND L111.OBJ_TYPE_ID = 111
            AND L111.DATE_DEL IS NULL

            UNION

            SELECT L10.LINK_ID,
                   L78.PARENT_ID,
                   L81.OBJ_ID,
                   L81.OBJ_TYPE_ID,
                   L10.OBJ_ID,
                   V55.VAL,
                   NULL,
                   NULL

            FROM LINKS L111

            JOIN LINKS L2
            ON L2.PARENT_ID =  L111.OBJ_ID
            AND L2.OBJ_TYPE_ID = 2
            AND L2.DATE_DEL IS NULL

            JOIN LINKS L78
            ON L78.PARENT_ID = L2.OBJ_ID
            AND L78.OBJ_TYPE_ID = 78
            AND L78.DATE_DEL IS NULL

            JOIN LINKS L81
            ON L81.PARENT_ID = L78.OBJ_ID
            AND L81.OBJ_TYPE_ID = 81
            AND L81.DATE_DEL IS NULL

            JOIN LINKS L10
            ON L10.PARENT_ID = L81.OBJ_ID
            AND L10.OBJ_TYPE_ID = 10
            AND L10.DATE_DEL IS NULL

            JOIN VALS V55
            ON V55.OBJ_ID = L10.OBJ_ID
            AND V55.PARAM_ID = 55
            AND V55.IS_DEL = 0
            AND UPPER(V55.VAL) STARTING WITH :V

            WHERE L111.PARENT_ID = :OBJ_ID
            AND L111.OBJ_TYPE_ID = 111
            AND L111.DATE_DEL IS NULL

            UNION

            SELECT L10.LINK_ID,
                   L78.PARENT_ID,
                   L82.OBJ_ID,
                   L82.OBJ_TYPE_ID,
                   L10.OBJ_ID,
                   V55.VAL,
                   NULL,
                   NULL

            FROM LINKS L111

            JOIN LINKS L2
            ON L2.PARENT_ID =  L111.OBJ_ID
            AND L2.OBJ_TYPE_ID = 2
            AND L2.DATE_DEL IS NULL

            JOIN LINKS L78
            ON L78.PARENT_ID = L2.OBJ_ID
            AND L78.OBJ_TYPE_ID = 78
            AND L78.DATE_DEL IS NULL

            JOIN LINKS L82
            ON L82.PARENT_ID = L78.OBJ_ID
            AND L82.OBJ_TYPE_ID = 82
            AND L82.DATE_DEL IS NULL

            JOIN LINKS L10
            ON L10.PARENT_ID = L82.OBJ_ID
            AND L10.OBJ_TYPE_ID = 10
            AND L10.DATE_DEL IS NULL

            JOIN VALS V55
            ON V55.OBJ_ID = L10.OBJ_ID
            AND V55.PARAM_ID = 55
            AND V55.IS_DEL = 0
            AND UPPER(V55.VAL) STARTING WITH :V

            WHERE L111.PARENT_ID = :OBJ_ID
            AND L111.OBJ_TYPE_ID = 111
            AND L111.DATE_DEL IS NULL

            UNION

            SELECT L10.LINK_ID,
                   L78.PARENT_ID,
                   L83.OBJ_ID,
                   L83.OBJ_TYPE_ID,
                   L10.OBJ_ID,
                   V55.VAL,
                   NULL,
                   NULL

            FROM LINKS L111

            JOIN LINKS L2
            ON L2.PARENT_ID =  L111.OBJ_ID
            AND L2.OBJ_TYPE_ID = 2
            AND L2.DATE_DEL IS NULL

            JOIN LINKS L78
            ON L78.PARENT_ID = L2.OBJ_ID
            AND L78.OBJ_TYPE_ID = 78
            AND L78.DATE_DEL IS NULL

            JOIN LINKS L83
            ON L83.PARENT_ID = L78.OBJ_ID
            AND L83.OBJ_TYPE_ID = 83
            AND L83.DATE_DEL IS NULL

            JOIN LINKS L10
            ON L10.PARENT_ID = L83.OBJ_ID
            AND L10.OBJ_TYPE_ID = 10
            AND L10.DATE_DEL IS NULL

            JOIN VALS V55
            ON V55.OBJ_ID = L10.OBJ_ID
            AND V55.PARAM_ID = 55
            AND V55.IS_DEL = 0
            AND UPPER(V55.VAL) STARTING WITH :V

            WHERE L111.PARENT_ID = :OBJ_ID
            AND L111.OBJ_TYPE_ID = 111
            AND L111.DATE_DEL IS NULL

            UNION

            SELECT L10.LINK_ID,
                   L211.PARENT_ID,
                   L243.OBJ_ID,
                   L243.OBJ_TYPE_ID,
                   L10.OBJ_ID,
                   V55.VAL,
                   L211.OBJ_ID,
                   L242.OBJ_ID

            FROM LINKS L111

            JOIN LINKS L2
            ON L2.PARENT_ID =  L111.OBJ_ID
            AND L2.OBJ_TYPE_ID = 2
            AND L2.DATE_DEL IS NULL

            JOIN LINKS L211
            ON L211.PARENT_ID = L2.OBJ_ID
            AND L211.OBJ_TYPE_ID = 211
            AND L211.DATE_DEL IS NULL

            JOIN LINKS L242
            ON L242.PARENT_ID = L211.OBJ_ID
            AND L242.OBJ_TYPE_ID = 242
            AND L242.DATE_DEL IS NULL

            JOIN LINKS L243
            ON L243.PARENT_ID = L242.OBJ_ID
            AND L243.OBJ_TYPE_ID = 243
            AND L243.DATE_DEL IS NULL

            JOIN LINKS L10
            ON L10.PARENT_ID = L243.OBJ_ID
            AND L10.OBJ_TYPE_ID = 10
            AND L10.DATE_DEL IS NULL

            JOIN VALS V55
            ON V55.OBJ_ID = L10.OBJ_ID
            AND V55.PARAM_ID = 55
            AND V55.IS_DEL = 0
            AND UPPER(V55.VAL) STARTING WITH :V

            WHERE L111.PARENT_ID = :OBJ_ID
            AND L111.OBJ_TYPE_ID = 111
            AND L111.DATE_DEL IS NULL

            UNION

            SELECT L10.LINK_ID,
                   L242.PARENT_ID,
                   L243.OBJ_ID,
                   L243.OBJ_TYPE_ID,
                   L10.OBJ_ID,
                   V55.VAL,
                   NULL,
                   L242.OBJ_ID

            FROM LINKS L111

            JOIN LINKS L2
            ON L2.PARENT_ID =  L111.OBJ_ID
            AND L2.OBJ_TYPE_ID = 2
            AND L2.DATE_DEL IS NULL

            JOIN LINKS L242
            ON L242.PARENT_ID = L2.OBJ_ID
            AND L242.OBJ_TYPE_ID = 242
            AND L242.DATE_DEL IS NULL

            JOIN LINKS L243
            ON L243.PARENT_ID = L242.OBJ_ID
            AND L243.OBJ_TYPE_ID = 243
            AND L243.DATE_DEL IS NULL

            JOIN LINKS L10
            ON L10.PARENT_ID = L243.OBJ_ID
            AND L10.OBJ_TYPE_ID = 10
            AND L10.DATE_DEL IS NULL

            JOIN VALS V55
            ON V55.OBJ_ID = L10.OBJ_ID
            AND V55.PARAM_ID = 55
            AND V55.IS_DEL = 0
            AND UPPER(V55.VAL) STARTING WITH :V

            WHERE L111.PARENT_ID = :OBJ_ID
            AND L111.OBJ_TYPE_ID = 111
            AND L111.DATE_DEL IS NULL

            INTO :LINK_ID,
                 :OU_ID,
                 :CLASS_ID,
                 :CLASS_TYPE_ID,
                 :SCHOLAR_ID,
                 :F,
                 :STRUCTURE_ID,
                 :DIVISION_ID
        DO
        BEGIN
            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:OU_ID)
            INTO :OU_CAPTION;

            IF (STRUCTURE_ID IS NOT NULL) THEN
            BEGIN
                SELECT CAPTION
                FROM OBJECT_CAPTION_GET(:STRUCTURE_ID)
                INTO :STRUCTURE_CAPTION;
            END
            ELSE
            BEGIN
                STRUCTURE_CAPTION = OU_CAPTION;
            END

            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:DIVISION_ID)
            INTO :DIVISION_CAPTION;

            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:CLASS_ID)
            INTO :CLASS_CAPTION;

            SELECT V
            FROM VAL_GET(:SCHOLAR_ID, 56)
            INTO :I;

            SELECT V
            FROM VAL_GET(:SCHOLAR_ID, 57)
            INTO :O;

            SELECT D
            FROM VAL_GET(:SCHOLAR_ID, 89)
            INTO :D;

            SUSPEND;
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_SCHOLAR_BY_PARENT_GET (
    I$PARENT_ID BIGINT)
RETURNS (
    SCHOLAR_ID BIGINT,
    CLASS_CAPTION VARCHAR(400),
    F VARCHAR(400),
    I VARCHAR(400),
    O VARCHAR(400),
    CLASS_ID BIGINT,
    LINK_ID BIGINT)
AS
BEGIN
    FOR SELECT L10.PARENT_ID AS SCHOLAR, L.LINK_ID AS LINK_SCHOLAR, L.PARENT_ID AS CLASS
        FROM LINKS L10
        JOIN LINKS L ON L.OBJ_ID = L10.PARENT_ID AND L.PARENT_TYPE_ID IN (81, 82, 9) AND L.DATE_DEL IS NULL
        WHERE L10.OBJ_ID = :I$PARENT_ID AND
              L10.PARENT_TYPE_ID = 10 AND
              L10.DATE_DEL IS NULL
        INTO SCHOLAR_ID, LINK_ID, CLASS_ID
    DO
    BEGIN
        SELECT F, I, O
        FROM BUILD_REP_FIO(:SCHOLAR_ID, 55, 56, 57)
        INTO F, I, O;

        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:CLASS_ID)
        INTO :CLASS_CAPTION;

        SUSPEND;
    END

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_SCHOLAR_BY_YEAR (
    I$OBJ_ID BIGINT,
    I$Y INTEGER,
    I$USER_ID BIGINT)
RETURNS (
    OU_NAME VARCHAR(4000),
    OU_TYPE VARCHAR(500),
    OU_VID VARCHAR(500),
    OU_ADDRESS VARCHAR(1000),
    OU_DIRECTOR VARCHAR(500),
    OU_PHONE VARCHAR(100),
    OU_EMAIL VARCHAR(100),
    SCHOLAR_COUNT INTEGER)
AS
declare variable TYPE_ID bigint;
declare variable SCHOOL_ID bigint;
declare variable DT1 date;
declare variable DT2 date;
BEGIN
    DT1 = :I$Y || '-01-01';
    DT2 = :I$Y || '-12-31';

    SELECT TYPE_ID FROM OBJECTS WHERE OBJ_ID = :I$OBJ_ID INTO :TYPE_ID;

    IF (TYPE_ID = 111) THEN -- raion
    BEGIN
        FOR
            SELECT L2.OBJ_ID, COUNT(*)
            FROM LINKS L2
            JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
            JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
            JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
            JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
            JOIN VALD V89 ON V89.OBJ_ID = L10.OBJ_ID AND V89.PARAM_ID = 89 AND V89.IS_DEL = 0 AND V89.VAL >= :DT1 AND V89.VAL <= :DT2
            WHERE L2.PARENT_ID = :I$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
            GROUP BY L2.OBJ_ID
            ORDER BY L2.OBJ_ID
            INTO :SCHOOL_ID, :SCHOLAR_COUNT
        DO
        BEGIN
            OU_DIRECTOR = '';
            SELECT V FROM VAL_GET(:SCHOOL_ID,  5, 0, :I$USER_ID) INTO :OU_NAME;
            SELECT V FROM VAL_GET(:SCHOOL_ID, 11, 0, :I$USER_ID) INTO :OU_TYPE;
            SELECT V FROM VAL_GET(:SCHOOL_ID, 10, 0, :I$USER_ID) INTO :OU_VID;
            SELECT V FROM VAL_GET(:SCHOOL_ID, 27, 0, :I$USER_ID) INTO :OU_ADDRESS;
            SELECT F || ' ' || I || ' ' || O FROM R_SPB_POST_DIRECTOR(:SCHOOL_ID, :I$USER_ID) INTO :OU_DIRECTOR;
            SELECT V FROM VAL_GET(:SCHOOL_ID, 29, 0, :I$USER_ID) INTO :OU_PHONE;
            SELECT V FROM VAL_GET(:SCHOOL_ID, 35, 0, :I$USER_ID) INTO :OU_EMAIL;
            SUSPEND;
        END
    END

    IF (TYPE_ID = 112) THEN -- gorod
    BEGIN
        FOR SELECT L2.OBJ_ID, COUNT(*)
            FROM LINKS L111
            JOIN LINKS L2 ON L2.PARENT_ID = L111.OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
            JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
            JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
            JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
            JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
            JOIN VALD V89 ON V89.OBJ_ID = L10.OBJ_ID AND V89.PARAM_ID = 89 AND V89.IS_DEL = 0 AND V89.VAL >= :DT1 AND V89.VAL <= :DT2
            WHERE L111.PARENT_ID = :I$OBJ_ID AND L111.OBJ_TYPE_ID = 111 AND L111.DATE_DEL IS NULL
            GROUP BY L2.OBJ_ID
            ORDER BY L2.OBJ_ID
            INTO :SCHOOL_ID, :SCHOLAR_COUNT
        DO
        BEGIN
            OU_DIRECTOR = '';
            SELECT V FROM VAL_GET(:SCHOOL_ID,  5, 0, :I$USER_ID) INTO :OU_NAME;
            SELECT V FROM VAL_GET(:SCHOOL_ID, 11, 0, :I$USER_ID) INTO :OU_TYPE;
            SELECT V FROM VAL_GET(:SCHOOL_ID, 10, 0, :I$USER_ID) INTO :OU_VID;
            SELECT V FROM VAL_GET(:SCHOOL_ID, 27, 0, :I$USER_ID) INTO :OU_ADDRESS;
            SELECT F || ' ' || I || ' ' || O FROM R_SPB_POST_DIRECTOR(:SCHOOL_ID, :I$USER_ID) INTO :OU_DIRECTOR;
            SELECT V FROM VAL_GET(:SCHOOL_ID, 29, 0, :I$USER_ID) INTO :OU_PHONE;
            SELECT V FROM VAL_GET(:SCHOOL_ID, 35, 0, :I$USER_ID) INTO :OU_EMAIL;
            SUSPEND;
        END
    END

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_SCHOLAR_CNT (
    I$SCHOOL_ID BIGINT NOT NULL,
    I$USER_ID BIGINT,
    I$DT DATE = current_date,
    I$VID_GROUP BIGINT = null)
RETURNS (
    V01 INTEGER,
    V02 INTEGER,
    V03 INTEGER,
    V04 INTEGER,
    V05 INTEGER,
    V06 INTEGER,
    V07 INTEGER,
    V08 INTEGER,
    V09 INTEGER,
    V10 INTEGER,
    V11 INTEGER,
    V12 INTEGER,
    V13 INTEGER,
    V14 INTEGER,
    V15 INTEGER,
    V_ALL INTEGER,
    VID_GROUP BIGINT)
AS
BEGIN
    FOR SELECT
            COALESCE(SUM(IIF(AGE_GROUP =  1, 1, 0)), 0) V01,
            COALESCE(SUM(IIF(AGE_GROUP =  2, 1, 0)), 0) V02,
            COALESCE(SUM(IIF(AGE_GROUP =  3, 1, 0)), 0) V03,
            COALESCE(SUM(IIF(AGE_GROUP =  4, 1, 0)), 0) V04,
            COALESCE(SUM(IIF(AGE_GROUP =  5, 1, 0)), 0) V05,
            COALESCE(SUM(IIF(AGE_GROUP =  6, 1, 0)), 0) V06,
            COALESCE(SUM(IIF(AGE_GROUP =  7, 1, 0)), 0) V07,
            COALESCE(SUM(IIF(AGE_GROUP =  8, 1, 0)), 0) V08,
            COALESCE(SUM(IIF(AGE_GROUP =  9, 1, 0)), 0) V09,
            COALESCE(SUM(IIF(AGE_GROUP = 10, 1, 0)), 0) V10,
            COALESCE(SUM(IIF(AGE_GROUP = 11, 1, 0)), 0) V11,
            COALESCE(SUM(IIF(AGE_GROUP = 12, 1, 0)), 0) V12,
            COALESCE(SUM(IIF(AGE_GROUP = 13, 1, 0)), 0) V13,
            COALESCE(SUM(IIF(AGE_GROUP = 14, 1, 0)), 0) V14,
            COALESCE(SUM(IIF(AGE_GROUP = 15, 1, 0)), 0) V15,
            COUNT(1) V_ALL,
            :I$VID_GROUP
        FROM R_SCHOLAR2(:I$SCHOOL_ID, :I$USER_ID, :I$DT)
        WHERE :I$VID_GROUP IS NULL
           OR ((:I$VID_GROUP = 0) AND (WORK_HOURS = 3296))
           OR ((:I$VID_GROUP = VID_GROUP) AND (:I$VID_GROUP <> 0))
        INTO :V01, :V02, :V03, :V04,
             :V05, :V06, :V07, :V08,
             :V09, :V10, :V11, :V12,
             :V13, :V14, :V15, :V_ALL,
             :VID_GROUP
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_SCHOLAR_CNT_DOU (
    I$OBJ_ID BIGINT NOT NULL,
    I$OPF_FILTER VARCHAR(1000),
    I$POD_FILTER VARCHAR(1000))
RETURNS (
    V00 VARCHAR(1000),
    V01 INTEGER,
    V02 INTEGER,
    V03 INTEGER,
    V04 INTEGER,
    V_ALL INTEGER)
AS
BEGIN
    IF(I$OPF_FILTER = '') THEN I$OPF_FILTER = NULL;
    IF(I$POD_FILTER = '') THEN I$POD_FILTER = NULL;

    FOR
        SELECT (SELECT CAPTION FROM OBJECT_CAPTION_GET(OBJ_ID)) V00, V01, V02, V03, V04, V_ALL
        FROM (
            SELECT
                IIF(L111.OBJ_ID = :I$OBJ_ID, L2.OBJ_ID, L111.OBJ_ID) OBJ_ID,
                SUM(IIF(V89.VAL >= DATEADD(-18 MONTH TO CURRENT_DATE), 1, 0)) V01,
                SUM(IIF(V89.VAL BETWEEN DATEADD(-3 YEAR TO CURRENT_DATE) AND DATEADD(-18 MONTH TO CURRENT_DATE) - 1, 1, 0)) V02,
                SUM(IIF(V89.VAL BETWEEN DATEADD(-7 YEAR TO CURRENT_DATE) AND DATEADD(-3 YEAR TO CURRENT_DATE) - 1, 1, 0)) V03,
                SUM(IIF(V89.VAL < DATEADD(-7 YEAR TO CURRENT_DATE), 1, 0)) V04,
                COUNT(1) V_ALL
    
            FROM (
                SELECT :I$OBJ_ID OBJ_ID
                FROM RDB$DATABASE
                UNION
                SELECT L111.OBJ_ID
                FROM LINKS L111
                WHERE L111.PARENT_ID = :I$OBJ_ID AND L111.OBJ_TYPE_ID = 111 AND L111.DATE_DEL IS NULL) L111
    
            JOIN LINKS L2 ON L2.PARENT_ID = L111.OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
            JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
            JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
            JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
            JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
            LEFT JOIN VALD V89 ON V89.OBJ_ID = L10.OBJ_ID AND V89.PARAM_ID = 89 AND V89.IS_DEL = 0
            -- Фильтр по подчинению
            LEFT JOIN VALS V6 ON V6.OBJ_ID = L2.OBJ_ID AND V6.PARAM_ID = 6 AND V6.IS_DEL = 0
            -- Включать частные ?
            LEFT JOIN VALL V8 ON V8.OBJ_ID = L2.OBJ_ID AND V8.PARAM_ID = 8 AND V8.IS_DEL = 0
            WHERE (:I$POD_FILTER IS NULL OR V6.VAL = :I$POD_FILTER) AND (:I$OPF_FILTER = 'Да' OR V8.LISTVAL_ID IS NULL OR V8.LISTVAL_ID <> 5404)
            GROUP BY OBJ_ID)

        ORDER BY (SELECT IIF(I = 0, 99999, I) FROM VAL_GET(OBJ_ID, 17)), V00
        INTO :V00, :V01, :V02, :V03, :V04, :V_ALL
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_SCHOLAR_DTL (
    I$SCHOOL_ID BIGINT NOT NULL,
    I$USER_ID BIGINT NOT NULL,
    I$DT DATE = current_date,
    I$VID_GROUP BIGINT = null,
    I$AGE_GROUP INTEGER = null)
RETURNS (
    VAL1 VARCHAR(250),
    VAL2 VARCHAR(250))
AS
BEGIN
    FOR SELECT
            (SELECT CAPTION FROM OBJECT_CAPTION_GET(SCHOLAR_ID)) VAL1,
            BIRTHDATE VAL2
        FROM R_SCHOLAR2(:I$SCHOOL_ID, :I$USER_ID, :I$DT)
        WHERE (:I$VID_GROUP IS NULL
               OR ((:I$VID_GROUP = 0) AND (WORK_HOURS = 3296))
               OR ((:I$VID_GROUP = VID_GROUP)) AND (:I$VID_GROUP <> 0))
          AND (:I$AGE_GROUP IS NULL OR :I$AGE_GROUP = AGE_GROUP)
        ORDER BY VAL1
        INTO :VAL1, :VAL2
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_SCHOOLAR_FINISH (
    I$SCHOOL_ID BIGINT,
    I$FROM DATE,
    I$TO DATE,
    I$LEVEL_ID BIGINT = NULL)
RETURNS (
    C1 DATE,
    C2 VARCHAR(1000),
    C3 VARCHAR(1000),
    C4 DATE,
    CC VARCHAR(1000),
    C5 VARCHAR(1000),
    C6 VARCHAR(1000),
    C7 VARCHAR(1000),
    C8 VARCHAR(1000),
    C9 VARCHAR(1000))
AS
DECLARE VARIABLE V$OU_LICENCE_TYPE CHAR(1);
DECLARE VARIABLE V$SCHOOLAR_ID BIGINT;
DECLARE VARIABLE V$MOVEMENT_ID BIGINT;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$STAGE BIGINT;
BEGIN

    SELECT STATUS FROM OU_LICENCE_TYPE INTO :V$OU_LICENCE_TYPE;

    IF(I$SCHOOL_ID IS NULL) THEN I$SCHOOL_ID = (SELECT FIRST 1 OBJ_ID FROM LINKS WHERE PARENT_ID IS NULL AND OBJ_TYPE_ID = 2 AND DATE_DEL IS NULL);

    FOR
      SELECT DISTINCT L.OBJ_ID
      FROM LINKS L78
      JOIN LINKS L ON L.PARENT_ID = L78.OBJ_ID AND L.OBJ_TYPE_ID = 83 AND L.DATE_DEL IS NULL
      WHERE L78.PARENT_ID = :I$SCHOOL_ID AND L78.OBJ_TYPE_ID = 78 AND L78.DATE_DEL IS NULL
      INTO :V$OBJ_ID
    DO
    BEGIN
      FOR
        SELECT M.PERSON_ID, M.OBJ_ID, M.STAGE_ID, M.DATE_OUT, M.ORDER_NUM_OUT, M.ORDER_DATE_OUT, M.NAME_IN, C5.VAL
        FROM LINKS L10
        JOIN PERSON_MOVEMENTS M ON M.DATE_DEL IS NULL AND M.PERSON_ID = L10.OBJ_ID AND (M.DATE_OUT >= :I$FROM OR :I$FROM IS NULL) AND (M.DATE_OUT <= :I$TO OR :I$TO IS NULL)
        JOIN LISTVALS LSTVL ON LSTVL.LISTVAL_ID = M.REASON_OUT AND LSTVL."FILTER" SIMILAR TO '%FINISHED%|%LEAVED%'
        JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID IN (9, 243)
        LEFT JOIN LISTVAL_TEXT(M.REASON_OUT) C5 ON 1 = 1
        WHERE L10.PARENT_ID = :V$OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        INTO :V$SCHOOLAR_ID, :V$MOVEMENT_ID, :V$STAGE, :C1, :C3, :C4, :CC, :C5
      DO
      BEGIN
        IF (V$STAGE < 47) THEN
        BEGIN
          SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$SCHOOLAR_ID) INTO :C2;
          SELECT V FROM VAL_GET(:V$SCHOOLAR_ID, 105) INTO :C6;
          SELECT V FROM VAL_GET(:V$SCHOOLAR_ID, 107) INTO :C7;
          SELECT V FROM VAL_GET(:V$SCHOOLAR_ID, 161) INTO :C8;
          SELECT V FROM VAL_GET(:V$SCHOOLAR_ID, 106) INTO :C9;

          SUSPEND;
        END
      END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_SCHOOLAR_IN (
    I$SCHOOL_ID BIGINT,
    I$FROM DATE,
    I$TO DATE,
    I$LEVEL_ID BIGINT = NULL)
RETURNS (
    C1 DATE,
    C2 VARCHAR(1000),
    C3 VARCHAR(1000),
    C4 DATE,
    C5 VARCHAR(1000),
    C6 VARCHAR(1000),
    C7 VARCHAR(1000),
    C8 VARCHAR(1000),
    C9 VARCHAR(1000))
AS
DECLARE VARIABLE V$SCHOOLAR_ID BIGINT;
DECLARE VARIABLE V$MOVEMENT_ID BIGINT;
BEGIN

    IF(I$SCHOOL_ID IS NULL) THEN I$SCHOOL_ID = (SELECT FIRST 1 OBJ_ID FROM LINKS WHERE PARENT_ID IS NULL AND OBJ_TYPE_ID = 2 AND DATE_DEL IS NULL);

    FOR
        SELECT L10.OBJ_ID, M.OBJ_ID, M.DATE_IN, M.ORDER_NUM_IN, M.ORDER_DATE_IN, ST.VAL, M.NAME_IN
        FROM LINKS L7
        JOIN VALL VL ON VL.OBJ_ID = L7.OBJ_ID AND VL.PARAM_ID = 43 AND VL.IS_DEL = 0
        JOIN LISTVALS LV43 ON LV43.LISTVAL_ID = VL.LISTVAL_ID AND LV43.IS_DEL = 0
          AND (:I$LEVEL_ID IS NULL OR (:I$LEVEL_ID NOT IN (22, 26, 27) AND LV43.PARENT_ID = :I$LEVEL_ID) OR (:I$LEVEL_ID IN (22, 26, 27) AND LV43.LISTVAL_ID IN (22, 26, 27)))
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
        JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        JOIN PERSON_MOVEMENTS M ON M.DATE_DEL IS NULL AND M.PERSON_ID = L10.OBJ_ID AND (M.DATE_IN >= :I$FROM OR :I$FROM IS NULL) AND (M.DATE_IN <= :I$TO OR :I$TO IS NULL)
        JOIN LISTVALS LV ON LV.LISTVAL_ID = M.REASON_IN AND LV."FILTER" SIMILAR TO '%ACCEPTED%'
        JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID IN (9, 243)
        LEFT JOIN LISTVAL_TEXT(M.STAGE_ID) ST ON 1 = 1
        WHERE L7.PARENT_ID = :I$SCHOOL_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
        ORDER BY M.DATE_IN
        INTO :V$SCHOOLAR_ID, :V$MOVEMENT_ID, :C1, C3, :C4, :C8, :C9
    DO
    BEGIN
        C2 = NULL;
        C5 = NULL;
        C6 = NULL;
        C7 = NULL;
        SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$SCHOOLAR_ID, 49) INTO :C2;
        SELECT V FROM VAL_GET(:V$SCHOOLAR_ID, 78) INTO :C5;
        SELECT V FROM VAL_GET(:V$SCHOOLAR_ID, 104) INTO :C6;
        SELECT V FROM VAL_GET(:V$SCHOOLAR_ID, 117) INTO :C7;

        SUSPEND;
    END

    FOR
        SELECT L10.OBJ_ID, M.OBJ_ID, M.DATE_IN, M.ORDER_NUM_IN, M.ORDER_DATE_IN, ST.VAL, M.NAME_IN
        FROM LINKS L78
        JOIN LINKS L ON L.PARENT_ID = L78.OBJ_ID AND L.OBJ_TYPE_ID IN (81, 82, 83) AND L.DATE_DEL IS NULL
        JOIN LINKS L10 ON L10.PARENT_ID = L.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        JOIN PERSON_MOVEMENTS M ON M.DATE_DEL IS NULL AND M.PERSON_ID = L10.OBJ_ID AND (M.DATE_IN >= :I$FROM OR :I$FROM IS NULL) AND (M.DATE_IN <= :I$TO OR :I$TO IS NULL)
        JOIN LISTVALS LV ON LV.LISTVAL_ID = M.REASON_IN AND LV."FILTER" SIMILAR TO '%ACCEPTED%'
        JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID IN (9, 243)
        LEFT JOIN LISTVAL_TEXT(M.STAGE_ID) ST ON 1 = 1
        WHERE L78.PARENT_ID = :I$SCHOOL_ID AND L78.OBJ_TYPE_ID = 78 AND L78.DATE_DEL IS NULL
        ORDER BY M.DATE_IN
        INTO :V$SCHOOLAR_ID, :V$MOVEMENT_ID, :C1, C3, :C4, :C8, :C9
    DO
    BEGIN
        C2 = NULL;
        C5 = NULL;
        C6 = NULL;
        C7 = NULL;
        SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$SCHOOLAR_ID, 49) INTO :C2;
        SELECT V FROM VAL_GET(:V$SCHOOLAR_ID, 78) INTO :C5;
        SELECT V FROM VAL_GET(:V$SCHOOLAR_ID, 104) INTO :C6;
        SELECT V FROM VAL_GET(:V$SCHOOLAR_ID, 117) INTO :C7;

        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_SCHOOLAR_IN_DISTR (
    I$DISTR_ID BIGINT,
    I$FROM DATE,
    I$TO DATE)
RETURNS (
    C1 DATE,
    C8 VARCHAR(500),
    C9 VARCHAR(100),
    C2 VARCHAR(255),
    C3 VARCHAR(100),
    C4 DATE,
    C5 VARCHAR(100),
    C6 VARCHAR(255),
    C7 VARCHAR(500),
    CA VARCHAR(100),
    CB VARCHAR(100))
AS
declare variable V$SCHOOL_ID bigint;
declare variable V$SCHOOLAR_ID bigint;
declare variable V$MOVEMENT_ID bigint;
BEGIN

    FOR
        SELECT L2.OBJ_ID, L10.OBJ_ID, M.OBJ_ID, M.DATE_IN, M.ORDER_NUM_IN, M.ORDER_DATE_IN, ST.VAL, M.NAME_IN
        FROM LINKS L2
        JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
        JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        JOIN PERSON_MOVEMENTS M ON M.DATE_DEL IS NULL AND M.PERSON_ID = L10.OBJ_ID AND (M.DATE_IN >= :I$FROM OR :I$FROM IS NULL) AND (M.DATE_IN <= :I$TO OR :I$TO IS NULL)
        JOIN LISTVALS LV ON LV.LISTVAL_ID = M.REASON_IN AND LV.LISTVAL_ID IN (806, 3276)
        JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID IN (9, 243)
        LEFT JOIN LISTVAL_TEXT(M.STAGE_ID) ST ON 1 = 1
        WHERE L2.PARENT_ID = :I$DISTR_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
        ORDER BY M.DATE_IN
        INTO :V$SCHOOL_ID, :V$SCHOOLAR_ID, :V$MOVEMENT_ID, :C1, C3, :C4, :C8, :C9
    DO
    BEGIN
        C2 = NULL;
        C5 = NULL;
        C6 = NULL;
        C7 = NULL;
        SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$SCHOOLAR_ID, 49) INTO :C2;
        SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$SCHOOL_ID) INTO :C8;

        SELECT V FROM VAL_GET(:V$SCHOOLAR_ID, 78) INTO :C5;
        SELECT V FROM VAL_GET(:V$SCHOOLAR_ID, 104) INTO :C6;
        SELECT V FROM VAL_GET(:V$SCHOOLAR_ID, 117) INTO :C7;
        SELECT V FROM VAL_GET(:V$SCHOOLAR_ID, 160) INTO :CA;
        SELECT V FROM VAL_GET(:V$SCHOOLAR_ID, 1345) INTO :CB;

        SUSPEND;
    END

    FOR
        SELECT L2.OBJ_ID, L10.OBJ_ID, M.OBJ_ID, M.DATE_IN, M.ORDER_NUM_IN, M.ORDER_DATE_IN, ST.VAL, M.NAME_IN
        FROM LINKS L2
        JOIN LINKS L78 ON L78.PARENT_ID = L2.OBJ_ID AND L78.OBJ_TYPE_ID = 78 AND L78.DATE_DEL IS NULL
        JOIN LINKS L ON L.PARENT_ID = L78.OBJ_ID AND L.OBJ_TYPE_ID IN (81, 82, 83) AND L.DATE_DEL IS NULL
        JOIN LINKS L10 ON L10.PARENT_ID = L.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        JOIN PERSON_MOVEMENTS M ON M.DATE_DEL IS NULL AND M.PERSON_ID = L10.OBJ_ID AND (M.DATE_IN >= :I$FROM OR :I$FROM IS NULL) AND (M.DATE_IN <= :I$TO OR :I$TO IS NULL)
        JOIN LISTVALS LV ON LV.LISTVAL_ID = M.REASON_IN AND LV.LISTVAL_ID IN (806, 3276)
        JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID IN (9, 243)
        LEFT JOIN LISTVAL_TEXT(M.STAGE_ID) ST ON 1 = 1
        WHERE L2.PARENT_ID = :I$DISTR_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
        ORDER BY M.DATE_IN
        INTO :V$SCHOOL_ID, :V$SCHOOLAR_ID, :V$MOVEMENT_ID, :C1, C3, :C4, :C8, :C9
    DO
    BEGIN
        C2 = NULL;
        C5 = NULL;
        C6 = NULL;
        C7 = NULL;
        SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$SCHOOLAR_ID, 49) INTO :C2;
        SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$SCHOOL_ID) INTO :C8;
        SELECT V FROM VAL_GET(:V$SCHOOLAR_ID, 78) INTO :C5;
        SELECT V FROM VAL_GET(:V$SCHOOLAR_ID, 104) INTO :C6;
        SELECT V FROM VAL_GET(:V$SCHOOLAR_ID, 117) INTO :C7;

        SUSPEND;
    END

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_SCHOOLAR_OUT (
    I$SCHOOL_ID BIGINT,
    I$FROM DATE,
    I$TO DATE,
    I$LEVEL_ID BIGINT = NULL)
RETURNS (
    C1 DATE,
    C2 VARCHAR(1000),
    C3 VARCHAR(1000),
    C4 DATE,
    CC VARCHAR(1000),
    C5 VARCHAR(1000),
    C6 VARCHAR(1000),
    C7 VARCHAR(1000),
    C8 VARCHAR(1000),
    C9 VARCHAR(1000),
    C0 VARCHAR(1000),
    CR BIGINT)
AS
DECLARE VARIABLE V$SCHOOLAR_ID BIGINT;
DECLARE VARIABLE V$MOVEMENT_ID BIGINT;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$OU_LICENCE_TYPE VARCHAR(1);
DECLARE VARIABLE V$CL_STAGE BIGINT;
DECLARE VARIABLE V$STAGE_PARENT_ID BIGINT;
BEGIN
    SELECT STATUS FROM OU_LICENCE_TYPE INTO :V$OU_LICENCE_TYPE;

    IF(I$SCHOOL_ID IS NULL) THEN I$SCHOOL_ID = (SELECT FIRST 1 OBJ_ID FROM LINKS WHERE PARENT_ID IS NULL AND OBJ_TYPE_ID = 2 AND DATE_DEL IS NULL);

    FOR
        SELECT DISTINCT L.OBJ_ID
        FROM LINKS L78
        JOIN LINKS L ON L.PARENT_ID = L78.OBJ_ID AND L.OBJ_TYPE_ID IN (81, 82) AND L.DATE_DEL IS NULL
        WHERE L78.PARENT_ID = :I$SCHOOL_ID AND L78.OBJ_TYPE_ID = 78 AND L78.DATE_DEL IS NULL
        UNION ALL
        SELECT L9.OBJ_ID
        FROM LINKS L7
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
        WHERE L7.PARENT_ID = :I$SCHOOL_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
        INTO :V$OBJ_ID
    DO
    BEGIN
        FOR
            SELECT M.PERSON_ID, M.DATE_OUT, M.ORDER_NUM_OUT, M.ORDER_DATE_OUT, M.NAME_IN, C5.VAL, M.GROUP_ID, M.STAGE_ID
            FROM LINKS L10
            JOIN PERSON_MOVEMENTS M ON M.DATE_DEL IS NULL AND M.PERSON_ID = L10.OBJ_ID AND (M.DATE_OUT >= :I$FROM OR :I$FROM IS NULL) AND (M.DATE_OUT <= :I$TO OR :I$TO IS NULL)
            JOIN LISTVALS LSTVL ON LSTVL.LISTVAL_ID = M.REASON_OUT AND LSTVL."FILTER" SIMILAR TO '%FINISHED%|%LEAVED%'
            JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID IN (9, 243)
            LEFT JOIN LISTVAL_TEXT(M.REASON_OUT) C5 ON 1 = 1
            WHERE L10.PARENT_ID = :V$OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
            INTO :V$SCHOOLAR_ID, :C1, :C3, :C4, :CC, :C5, :CR, :V$CL_STAGE
        DO
        BEGIN
            IF (V$CL_STAGE IS NOT NULL) THEN
              SELECT PARENT_ID FROM LISTVALS WHERE LISTVAL_ID = :V$CL_STAGE AND IS_DEL = 0 INTO :V$STAGE_PARENT_ID;

            IF (:I$LEVEL_ID IS NULL OR :V$STAGE_PARENT_ID IS NULL OR (:I$LEVEL_ID = 21 AND :V$STAGE_PARENT_ID = 2140) OR (:I$LEVEL_ID IN (22, 26, 27) AND :V$STAGE_PARENT_ID = 2141) OR (:I$LEVEL_ID = 29 AND :V$STAGE_PARENT_ID = 2142)) THEN BEGIN
                SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$SCHOOLAR_ID) INTO :C2;
                SELECT V FROM VAL_GET(:V$SCHOOLAR_ID, 105) INTO :C6;
                SELECT V FROM VAL_GET(:V$SCHOOLAR_ID, 107) INTO :C7;

                IF (V$OU_LICENCE_TYPE IN ('O', 'C', 'S')) THEN
                BEGIN
                    SELECT V FROM VAL_GET(:V$SCHOOLAR_ID, 161) INTO :C8;
                END
                ELSE
                BEGIN
                    SELECT V FROM VAL_GET(:V$SCHOOLAR_ID, 1555) INTO :C8;
                END

                SELECT V FROM VAL_GET(:V$SCHOOLAR_ID, 106) INTO :C9;
                SELECT V FROM VAL_GET(:V$SCHOOLAR_ID, 226) INTO :C0;
            
                SUSPEND;
            END
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_SCHOOLAR_OUT_DISTR (
    I$DISTR_ID BIGINT,
    I$FROM DATE,
    I$TO DATE)
RETURNS (
    C1 DATE,
    C0 VARCHAR(1000),
    C5 VARCHAR(1000),
    C2 VARCHAR(1000),
    C3 VARCHAR(1000),
    C4 DATE,
    C6 VARCHAR(1000),
    C7 VARCHAR(1000),
    C8 VARCHAR(1000),
    CA VARCHAR(1000),
    CB VARCHAR(1000),
    C9 VARCHAR(1000))
AS
declare variable V$OBJ_ID bigint;
declare variable V$SCHOOLAR_ID bigint;
declare variable V$MOVEMENT_ID bigint;
BEGIN

    FOR
        SELECT DISTINCT L.OBJ_ID, C.V
        FROM LINKS L2
        JOIN LINKS L78 ON L78.PARENT_ID = L2.OBJ_ID AND L78.OBJ_TYPE_ID = 78 AND L78.DATE_DEL IS NULL
        JOIN LINKS L ON L.PARENT_ID = L78.OBJ_ID AND L.OBJ_TYPE_ID IN (81, 82) AND L.DATE_DEL IS NULL
        LEFT JOIN VAL_GET(L2.OBJ_ID, 2) C ON 1 = 1
        WHERE L2.PARENT_ID = :I$DISTR_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
        INTO :V$OBJ_ID, :C0
    DO
    BEGIN
        FOR
            SELECT M.PERSON_ID, M.OBJ_ID, M.DATE_OUT, M.ORDER_NUM_OUT, M.ORDER_DATE_OUT, M.NAME_IN
            FROM LINKS L10
            JOIN PERSON_MOVEMENTS M ON M.DATE_DEL IS NULL AND M.PERSON_ID = L10.OBJ_ID AND (M.DATE_OUT >= :I$FROM OR :I$FROM IS NULL) AND (M.DATE_OUT <= :I$TO OR :I$TO IS NULL)
            JOIN LISTVALS LSTVL ON LSTVL.LISTVAL_ID = M.REASON_OUT AND LSTVL."FILTER" SIMILAR TO '%FINISHED%|%LEAVED%'
            JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID IN (9, 243)
            -- LEFT JOIN LISTVAL_TEXT(M.REASON_OUT) C5 ON 1 = 1
            WHERE L10.PARENT_ID = :V$OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
            INTO :V$SCHOOLAR_ID, :V$MOVEMENT_ID, :C1, :C3, :C4, :C5
        DO
        BEGIN
            SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$SCHOOLAR_ID) INTO :C2;
            SELECT V FROM VAL_GET(:V$SCHOOLAR_ID, 105) INTO :C6;
            SELECT V FROM VAL_GET(:V$SCHOOLAR_ID, 107) INTO :C7;
            SELECT V FROM VAL_GET(:V$SCHOOLAR_ID, 161) INTO :C8;
            SELECT V FROM VAL_GET(:V$SCHOOLAR_ID, 188) INTO :CA;
            SELECT V FROM VAL_GET(:V$SCHOOLAR_ID, 1346) INTO :CB;
            SELECT V FROM VAL_GET(:V$SCHOOLAR_ID, 106) INTO :C9;

            SUSPEND;
        END
    END

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_SPB_INFOCARD (
    I$OBJ_ID BIGINT,
    I$Q SMALLINT,
    I$USER_ID BIGINT)
RETURNS (
    V VARCHAR(4000))
AS
declare variable I integer;
declare variable C numeric(9,2);
declare variable TYP varchar(400);
declare variable LANG_CODE varchar(2);
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :LANG_CODE;

    IF (I$Q = 133) THEN
    BEGIN
        SELECT SUM(V62.VAL)
        FROM LINKS L13
        INNER JOIN VALF V62 ON V62.PARAM_ID = 62 AND V62.OBJ_ID = L13.OBJ_ID
        INNER JOIN VALL V400 ON V400.OBJ_ID = V62.OBJ_ID
        WHERE L13.OBJ_TYPE_ID = 13
              AND L13.PARENT_ID = :I$OBJ_ID
              AND L13.DATE_DEL IS NULL
              AND V62.IS_DEL = 0
              AND V400.LISTVAL_ID = 2
        INTO :I;
        V = I;
        SUSPEND;
        EXIT;
    END

    IF (I$Q = 135) THEN
    BEGIN
        SELECT COUNT(*)
        FROM LINKS L13
        INNER JOIN VALL V368 ON V368.PARAM_ID = 368 AND V368.OBJ_ID = L13.OBJ_ID
        WHERE L13.OBJ_TYPE_ID = 14
              AND L13.PARENT_ID = :I$OBJ_ID
              AND L13.DATE_DEL IS NULL
              AND V368.IS_DEL = 0
              AND V368.LISTVAL_ID = 2
        INTO :I;
        V = I;
        SUSPEND;
        EXIT;
    END

    IF (I$Q = 150) THEN
    BEGIN
        SELECT SUM(V62.VAL)
        FROM LINKS L13
        INNER JOIN VALF V62 ON V62.PARAM_ID = 62 AND V62.OBJ_ID = L13.OBJ_ID
        WHERE L13.OBJ_TYPE_ID = 13
              AND L13.PARENT_ID = :I$OBJ_ID
              AND L13.DATE_DEL IS NULL
              AND V62.IS_DEL = 0
              AND V62.OBJ_ID = 1996
        INTO :C;
        V = C;
        SUSPEND;
        EXIT;
    END

    IF (I$Q = 155) THEN
    BEGIN
        V = '____';
        SUSPEND;
        EXIT;
    END

    IF (I$Q = 161) THEN
    BEGIN
        V = 'нет';
        SELECT 'да'
        FROM VALF
        WHERE PARAM_ID = 729
              AND OBJ_ID = :I$OBJ_ID
              AND IS_DEL = 0
              AND VAL > 0
        INTO :V;
        SUSPEND;
        EXIT;
    END

    IF (I$Q = 162) THEN
    BEGIN
        V = 'нет';
        SELECT 'да'
        FROM VALF
        WHERE PARAM_ID = 730
              AND OBJ_ID = :I$OBJ_ID
              AND IS_DEL = 0
              AND VAL > 0
        INTO :V;
        SUSPEND;
        EXIT;
    END

    IF (I$Q = 163) THEN
    BEGIN
        V = 'нет';
        SELECT 'да'
        FROM VALF
        WHERE PARAM_ID = 731
              AND OBJ_ID = :I$OBJ_ID
              AND IS_DEL = 0
              AND VAL > 0
        INTO :V;
        SUSPEND;
        EXIT;
    END

    IF (I$Q = 210) THEN
    BEGIN
        SELECT COUNT(*)
        FROM LINKS L23
        INNER JOIN LINKS L95 ON L95.PARENT_ID = L23.OBJ_ID
        INNER JOIN LINKS L114 ON L114.PARENT_ID = L95.OBJ_ID
        WHERE L23.PARENT_ID = :I$OBJ_ID
              AND L23.OBJ_TYPE_ID = 23
              AND L23.DATE_DEL IS NULL
              AND L95.DATE_DEL IS NULL
              AND L95.OBJ_TYPE_ID = 95
              AND L114.DATE_DEL IS NULL
              AND L114.OBJ_TYPE_ID = 114
        INTO :I;
        V = I;
        SUSPEND;
        EXIT;
    END

    IF (I$Q = 215) THEN
    BEGIN
        SELECT COUNT(*)
        FROM LINKS L23
        INNER JOIN LINKS L95 ON L95.PARENT_ID = L23.OBJ_ID
        INNER JOIN LINKS L114 ON L114.PARENT_ID = L95.OBJ_ID
        INNER JOIN VALS V682 ON V682.OBJ_ID = L114.OBJ_ID AND V682.PARAM_ID = 682
        WHERE L23.PARENT_ID = :I$OBJ_ID
              AND L23.OBJ_TYPE_ID = 23
              AND L23.DATE_DEL IS NULL
              AND L95.DATE_DEL IS NULL
              AND L95.OBJ_TYPE_ID = 95
              AND V682.IS_DEL = 0
              AND L114.DATE_DEL IS NULL
              AND L114.OBJ_TYPE_ID = 114
              AND CAST(V682.VAL AS INTEGER) < 2004
        INTO :I;
        V = I;
        SUSPEND;
        EXIT;
    END

    IF (I$Q = 220) THEN
    BEGIN
        SELECT COUNT(*)
        FROM LINKS L23
        INNER JOIN LINKS L95 ON L95.PARENT_ID = L23.OBJ_ID
        INNER JOIN VALL V604 ON V604.OBJ_ID = L95.OBJ_ID AND V604.PARAM_ID = 604
        INNER JOIN LINKS L114 ON L114.PARENT_ID = L95.OBJ_ID
        WHERE L23.PARENT_ID = :I$OBJ_ID
              AND L23.OBJ_TYPE_ID = 23
              AND L23.DATE_DEL IS NULL
              AND L95.DATE_DEL IS NULL
              AND L95.OBJ_TYPE_ID = 95
              AND V604.IS_DEL = 0
              AND (V604.LISTVAL_ID = 1807) OR (V604.LISTVAL_ID = 1808) OR (V604.LISTVAL_ID = 1809)
              AND L114.DATE_DEL IS NULL
              AND L114.OBJ_TYPE_ID = 114
        INTO :I;
        V = I;
        SUSPEND;
        EXIT;
    END

    IF (I$Q = 230) THEN
    BEGIN
        SELECT COUNT(*)
        FROM LINKS L23
        INNER JOIN LINKS L95 ON L95.PARENT_ID = L23.OBJ_ID
        INNER JOIN VALL V604 ON V604.OBJ_ID = L95.OBJ_ID AND V604.PARAM_ID = 604
        INNER JOIN LINKS L114 ON L114.PARENT_ID = L95.OBJ_ID
        WHERE L23.PARENT_ID = :I$OBJ_ID
              AND L23.OBJ_TYPE_ID = 23
              AND L23.DATE_DEL IS NULL
              AND L95.DATE_DEL IS NULL
              AND L95.OBJ_TYPE_ID = 95
              AND V604.IS_DEL = 0
              AND (V604.LISTVAL_ID = 1804) OR (V604.LISTVAL_ID = 1805) OR (V604.LISTVAL_ID = 1806)
              AND L114.DATE_DEL IS NULL
              AND L114.OBJ_TYPE_ID = 114
        INTO :I;
        V = I;
        SUSPEND;
        EXIT;
    END

    IF (I$Q = 231) THEN
    BEGIN
        V = '____';
        SUSPEND;
        EXIT;
    END

    IF (I$Q = 232) THEN
    BEGIN
        SELECT COUNT(*)
        FROM LINKS L23
        INNER JOIN LINKS L95 ON L95.PARENT_ID = L23.OBJ_ID
        INNER JOIN VALL V604 ON V604.OBJ_ID = L95.OBJ_ID AND V604.PARAM_ID = 604
        INNER JOIN LINKS L114 ON L114.PARENT_ID = L95.OBJ_ID
        INNER JOIN VALR V679 ON V679.OBJ_ID = L114.OBJ_ID AND V679.PARAM_ID = 679
        INNER JOIN VALL V526 ON V526.OBJ_ID = V679.VAL AND V526.PARAM_ID = 526
        WHERE L23.PARENT_ID = :I$OBJ_ID
              AND L23.OBJ_TYPE_ID = 23
              AND L23.DATE_DEL IS NULL
              AND L95.DATE_DEL IS NULL
              AND L95.OBJ_TYPE_ID = 95
              AND V604.IS_DEL = 0
              AND L114.DATE_DEL IS NULL
              AND L114.OBJ_TYPE_ID = 114
              AND ((V604.LISTVAL_ID = 1804) OR (V604.LISTVAL_ID = 1805) OR (V604.LISTVAL_ID = 1806))
              AND V679.IS_DEL = 0
              AND V526.IS_DEL = 0
              AND V526.LISTVAL_ID = 1127
        INTO :I;
        V = I;
        SUSPEND;
        EXIT;
    END

    IF (I$Q = 233) THEN
    BEGIN
        SELECT COUNT(*)
        FROM LINKS L23
        INNER JOIN LINKS L95 ON L95.PARENT_ID = L23.OBJ_ID
        INNER JOIN VALL V604 ON V604.OBJ_ID = L95.OBJ_ID AND V604.PARAM_ID = 604
        INNER JOIN LINKS L114 ON L114.PARENT_ID = L95.OBJ_ID
        INNER JOIN VALR V679 ON V679.OBJ_ID = L114.OBJ_ID AND V679.PARAM_ID = 679
        INNER JOIN VALL V526 ON V526.OBJ_ID = V679.VAL AND V526.PARAM_ID = 526
        WHERE L23.PARENT_ID = :I$OBJ_ID
              AND L23.OBJ_TYPE_ID = 23
              AND L23.DATE_DEL IS NULL
              AND L95.DATE_DEL IS NULL
              AND L95.OBJ_TYPE_ID = 95
              AND V604.IS_DEL = 0
              AND L114.DATE_DEL IS NULL
              AND L114.OBJ_TYPE_ID = 114
              AND ((V604.LISTVAL_ID = 1804) OR (V604.LISTVAL_ID = 1805) OR (V604.LISTVAL_ID = 1806))
              AND V679.IS_DEL = 0
              AND V526.IS_DEL = 0
              AND (SELECT SORT_ORDER FROM DO_FUNC(V679.VAL, 537)) = 4
              AND V526.LISTVAL_ID = 1127
        INTO :I;
        V = I;
        SUSPEND;
        EXIT;
    END

    IF (I$Q = 234) THEN
    BEGIN
        SELECT COUNT(*)
        FROM LINKS L23
        INNER JOIN LINKS L95 ON L95.PARENT_ID = L23.OBJ_ID
        INNER JOIN VALL V604 ON V604.OBJ_ID = L95.OBJ_ID AND V604.PARAM_ID = 604
        INNER JOIN LINKS L114 ON L114.PARENT_ID = L95.OBJ_ID
        INNER JOIN VALR V679 ON V679.OBJ_ID = L114.OBJ_ID AND V679.PARAM_ID = 679
        INNER JOIN VALL V526 ON V526.OBJ_ID = V679.VAL AND V526.PARAM_ID = 526
        WHERE L23.PARENT_ID = :I$OBJ_ID
              AND L23.OBJ_TYPE_ID = 23
              AND L23.DATE_DEL IS NULL
              AND L95.DATE_DEL IS NULL
              AND L95.OBJ_TYPE_ID = 95
              AND V604.IS_DEL = 0
              AND L114.DATE_DEL IS NULL
              AND L114.OBJ_TYPE_ID = 114
              AND ((V604.LISTVAL_ID = 1804) OR (V604.LISTVAL_ID = 1805) OR (V604.LISTVAL_ID = 1806))
              AND V679.IS_DEL = 0
              AND V526.IS_DEL = 0
              AND V526.LISTVAL_ID = 1143
        INTO :I;
        V = I;
        SUSPEND;
        EXIT;
    END

    IF (I$Q = 235) THEN
    BEGIN
        SELECT COUNT(*)
        FROM LINKS L23
        INNER JOIN LINKS L95 ON L95.PARENT_ID = L23.OBJ_ID
        INNER JOIN VALL V604 ON V604.OBJ_ID = L95.OBJ_ID AND V604.PARAM_ID = 604
        INNER JOIN LINKS L114 ON L114.PARENT_ID = L95.OBJ_ID
        INNER JOIN VALR V679 ON V679.OBJ_ID = L114.OBJ_ID AND V679.PARAM_ID = 679
        INNER JOIN VALL V526 ON V526.OBJ_ID = V679.VAL AND V526.PARAM_ID = 526
        WHERE L23.PARENT_ID = :I$OBJ_ID
              AND L23.OBJ_TYPE_ID = 23
              AND L23.DATE_DEL IS NULL
              AND L95.DATE_DEL IS NULL
              AND L95.OBJ_TYPE_ID = 95
              AND V604.IS_DEL = 0
              AND L114.DATE_DEL IS NULL
              AND L114.OBJ_TYPE_ID = 114
              AND ((V604.LISTVAL_ID = 1804) OR (V604.LISTVAL_ID = 1805) OR (V604.LISTVAL_ID = 1806))
              AND V679.IS_DEL = 0
              AND V526.IS_DEL = 0
              AND (SELECT SORT_ORDER FROM DO_FUNC(V679.VAL, 537)) = 4
              AND V526.LISTVAL_ID = 1143
        INTO :I;
        V = I;
        SUSPEND;
        EXIT;
    END

    IF (I$Q = 236) THEN
    BEGIN
        SELECT COUNT(*)
        FROM LINKS L23
        INNER JOIN LINKS L95 ON L95.PARENT_ID = L23.OBJ_ID
        INNER JOIN VALL V604 ON V604.OBJ_ID = L95.OBJ_ID AND V604.PARAM_ID = 604
        INNER JOIN LINKS L114 ON L114.PARENT_ID = L95.OBJ_ID
        INNER JOIN VALR V679 ON V679.OBJ_ID = L114.OBJ_ID AND V679.PARAM_ID = 679
        INNER JOIN VALL V526 ON V526.OBJ_ID = V679.VAL AND V526.PARAM_ID = 526
        WHERE L23.PARENT_ID = :I$OBJ_ID
              AND L23.OBJ_TYPE_ID = 23
              AND L23.DATE_DEL IS NULL
              AND L95.DATE_DEL IS NULL
              AND L95.OBJ_TYPE_ID = 95
              AND V604.IS_DEL = 0
              AND L114.DATE_DEL IS NULL
              AND L114.OBJ_TYPE_ID = 114
              AND ((V604.LISTVAL_ID = 1804) OR (V604.LISTVAL_ID = 1805) OR (V604.LISTVAL_ID = 1806))
              AND V679.IS_DEL = 0
              AND V526.IS_DEL = 0
              AND V526.LISTVAL_ID = 1140
        INTO :I;
        V = I;
        SUSPEND;
        EXIT;
    END

    IF (I$Q = 237) THEN
    BEGIN
        SELECT COUNT(*)
        FROM LINKS L23
        INNER JOIN LINKS L95 ON L95.PARENT_ID = L23.OBJ_ID
        INNER JOIN VALL V604 ON V604.OBJ_ID = L95.OBJ_ID AND V604.PARAM_ID = 604
        INNER JOIN LINKS L114 ON L114.PARENT_ID = L95.OBJ_ID
        INNER JOIN VALR V679 ON V679.OBJ_ID = L114.OBJ_ID AND V679.PARAM_ID = 679
        INNER JOIN VALL V526 ON V526.OBJ_ID = V679.VAL AND V526.PARAM_ID = 526
        WHERE L23.PARENT_ID = :I$OBJ_ID
              AND L23.OBJ_TYPE_ID = 23
              AND L23.DATE_DEL IS NULL
              AND L95.DATE_DEL IS NULL
              AND L95.OBJ_TYPE_ID = 95
              AND V604.IS_DEL = 0
              AND L114.DATE_DEL IS NULL
              AND L114.OBJ_TYPE_ID = 114
              AND ((V604.LISTVAL_ID = 1804) OR (V604.LISTVAL_ID = 1805) OR (V604.LISTVAL_ID = 1806))
              AND V679.IS_DEL = 0
              AND V526.IS_DEL = 0
              AND (SELECT SORT_ORDER FROM DO_FUNC(V679.VAL, 537)) = 4
              AND V526.LISTVAL_ID = 1140
        INTO :I;
        V = I;
        SUSPEND;
        EXIT;
    END

    IF (I$Q = 250) THEN
    BEGIN
        SELECT COUNT(*)
        FROM LINKS L23
        INNER JOIN LINKS L95 ON L95.PARENT_ID = L23.OBJ_ID
        INNER JOIN VALL V604 ON V604.OBJ_ID = L95.OBJ_ID AND V604.PARAM_ID = 604
        INNER JOIN LINKS L114 ON L114.PARENT_ID = L95.OBJ_ID
        WHERE L23.PARENT_ID = :I$OBJ_ID
              AND L23.OBJ_TYPE_ID = 23
              AND L23.DATE_DEL IS NULL
              AND L95.DATE_DEL IS NULL
              AND L95.OBJ_TYPE_ID = 95
              AND V604.IS_DEL = 0
              AND (V604.LISTVAL_ID = 1804) OR (V604.LISTVAL_ID = 1805) OR (V604.LISTVAL_ID = 1806)
              AND L114.DATE_DEL IS NULL
              AND L114.OBJ_TYPE_ID = 114
        INTO :I;

        SELECT VAL
        FROM DO_FUNC(:I$OBJ_ID, 661, 6)
        INTO :C;

        IF (I > 0) THEN
        BEGIN
            C = C / I;
            V = C;
        END
        ELSE
            V = '____';
        SUSPEND;
        EXIT;
    END

    IF (I$Q = 260) THEN
    BEGIN
        SELECT COUNT(*)
        FROM LINKS L23
        INNER JOIN LINKS L95 ON L95.PARENT_ID = L23.OBJ_ID
        INNER JOIN VALL V604 ON V604.OBJ_ID = L95.OBJ_ID AND V604.PARAM_ID = 604
        INNER JOIN LINKS L114 ON L114.PARENT_ID = L95.OBJ_ID
        WHERE L23.PARENT_ID = :I$OBJ_ID
              AND L23.OBJ_TYPE_ID = 23
              AND L23.DATE_DEL IS NULL
              AND L95.DATE_DEL IS NULL
              AND L95.OBJ_TYPE_ID = 95
              AND V604.IS_DEL = 0
              AND (V604.LISTVAL_ID = 1800) OR (V604.LISTVAL_ID = 1801) OR (V604.LISTVAL_ID = 1802)
              AND L114.DATE_DEL IS NULL
              AND L114.OBJ_TYPE_ID = 114
        INTO :I;
        V = I;
        SUSPEND;
        EXIT;
    END

    IF (I$Q = 280) THEN
    BEGIN
        SELECT COUNT(*)
        FROM LINKS L23
        INNER JOIN LINKS L95 ON L95.PARENT_ID = L23.OBJ_ID
        INNER JOIN VALL V19X ON V19X.OBJ_ID = L95.OBJ_ID
        INNER JOIN LINKS L114 ON L114.PARENT_ID = L95.OBJ_ID AND L114.OBJ_TYPE_ID = 114

        WHERE L23.PARENT_ID = :I$OBJ_ID
              AND L23.OBJ_TYPE_ID = 23
              AND L23.DATE_DEL IS NULL
              AND L95.DATE_DEL IS NULL
              AND L95.OBJ_TYPE_ID = 95
              AND V19X.IS_DEL = 0
              AND ((V19X.LISTVAL_ID = 1908) OR (V19X.LISTVAL_ID = 1909) OR (V19X.LISTVAL_ID = 1910))
              AND L114.DATE_DEL IS NULL
        INTO :I;
        V = I;
        SUSPEND;
        EXIT;
    END

    IF (I$Q = 285) THEN
    BEGIN
        SELECT COUNT(*)
        FROM LINKS L23
        INNER JOIN LINKS L95 ON L95.PARENT_ID = L23.OBJ_ID
        INNER JOIN VALL V1905 ON V1905.OBJ_ID = L95.OBJ_ID AND V1905.LISTVAL_ID = 1905
        INNER JOIN LINKS L114 ON L114.PARENT_ID = L95.OBJ_ID AND L114.OBJ_TYPE_ID = 114
        WHERE L23.PARENT_ID = :I$OBJ_ID
              AND L23.OBJ_TYPE_ID = 23
              AND L23.DATE_DEL IS NULL
              AND L95.DATE_DEL IS NULL
              AND L95.OBJ_TYPE_ID = 95
              AND V1905.IS_DEL = 0
              AND L114.DATE_DEL IS NULL
        INTO :I;
        V = I;
        SUSPEND;
        EXIT;
    END

    IF (I$Q = 290) THEN
    BEGIN
        SELECT COUNT(*)
        FROM LINKS L23
        INNER JOIN LINKS L128 ON L128.PARENT_ID = L23.OBJ_ID
        INNER JOIN VALL V2069 ON V2069.OBJ_ID = L128.OBJ_ID AND V2069.LISTVAL_ID = 2069
        WHERE L23.PARENT_ID = :I$OBJ_ID
              AND L23.OBJ_TYPE_ID = 23
              AND L23.DATE_DEL IS NULL
              AND L128.OBJ_TYPE_ID = 128
              AND L128.DATE_DEL IS NULL
              AND V2069.IS_DEL = 0
        INTO :I;
        V = I;
        SUSPEND;
        EXIT;
    END

    IF (I$Q = 291) THEN
    BEGIN
        SELECT SUM(V888.VAL)
        FROM LINKS L23
        INNER JOIN LINKS L128 ON L128.PARENT_ID = L23.OBJ_ID
        INNER JOIN VALL V2069 ON V2069.OBJ_ID = L128.OBJ_ID AND V2069.LISTVAL_ID = 2069
        INNER JOIN VALI V888 ON V888.OBJ_ID = L128.OBJ_ID AND V888.PARAM_ID = 888
        WHERE L23.PARENT_ID = :I$OBJ_ID
              AND L23.OBJ_TYPE_ID = 23
              AND L23.DATE_DEL IS NULL
              AND L128.OBJ_TYPE_ID = 128
              AND L128.DATE_DEL IS NULL
              AND V2069.IS_DEL = 0
              AND V888.IS_DEL = 0
        INTO :C;
        IF (C IS NULL) THEN
            C = 0;
        V = C;
        SUSPEND;
        EXIT;
    END

    IF (I$Q = 292) THEN
    BEGIN
        SELECT COUNT(*)
        FROM LINKS L23
        INNER JOIN LINKS L128 ON L128.PARENT_ID = L23.OBJ_ID
        INNER JOIN VALL V20X ON V20X.OBJ_ID = L128.OBJ_ID
        WHERE L23.PARENT_ID = :I$OBJ_ID
              AND L23.OBJ_TYPE_ID = 23
              AND L23.DATE_DEL IS NULL
              AND L128.OBJ_TYPE_ID = 128
              AND L128.DATE_DEL IS NULL
              AND V20X.IS_DEL = 0
              AND ((V20X.LISTVAL_ID = 2070) OR (V20X.LISTVAL_ID = 2072) OR (V20X.LISTVAL_ID = 2073))
        INTO :I;
        V = I;
        SUSPEND;
        EXIT;
    END

    IF (I$Q = 293) THEN
    BEGIN
        SELECT SUM(V888.VAL)
        FROM LINKS L23
        INNER JOIN LINKS L128 ON L128.PARENT_ID = L23.OBJ_ID
        INNER JOIN VALL V20X ON V20X.OBJ_ID = L128.OBJ_ID
        INNER JOIN VALI V888 ON V888.OBJ_ID = L128.OBJ_ID AND V888.PARAM_ID = 888
        WHERE L23.PARENT_ID = :I$OBJ_ID
              AND L23.OBJ_TYPE_ID = 23
              AND L23.DATE_DEL IS NULL
              AND L128.OBJ_TYPE_ID = 128
              AND L128.DATE_DEL IS NULL
              AND V20X.IS_DEL = 0
              AND V888.IS_DEL = 0
              AND ((V20X.LISTVAL_ID = 2070) OR (V20X.LISTVAL_ID = 2072) OR (V20X.LISTVAL_ID = 2073))
        INTO :C;

        IF (C IS NULL) THEN
            C = 0;
        V = C;
        SUSPEND;
        EXIT;
    END

    IF (I$Q = 294) THEN
    BEGIN
        SELECT COUNT(*)
        FROM LINKS L23
        INNER JOIN LINKS L128 ON L128.PARENT_ID = L23.OBJ_ID
        INNER JOIN VALL V2074 ON V2074.OBJ_ID = L128.OBJ_ID
        WHERE L23.PARENT_ID = :I$OBJ_ID
              AND L23.OBJ_TYPE_ID = 23
              AND L23.DATE_DEL IS NULL
              AND L128.OBJ_TYPE_ID = 128
              AND L128.DATE_DEL IS NULL
              AND V2074.IS_DEL = 0
              AND V2074.LISTVAL_ID = 2074
        INTO :I;
        V = I;
        SUSPEND;
        EXIT;
    END

    IF (I$Q = 295) THEN
    BEGIN
        SELECT SUM(V888.VAL)
        FROM LINKS L23
        INNER JOIN LINKS L128 ON L128.PARENT_ID = L23.OBJ_ID
        INNER JOIN VALL V2074 ON V2074.OBJ_ID = L128.OBJ_ID
        INNER JOIN VALI V888 ON V888.OBJ_ID = L128.OBJ_ID AND V888.PARAM_ID = 888
        WHERE L23.PARENT_ID = :I$OBJ_ID
              AND L23.OBJ_TYPE_ID = 23
              AND L23.DATE_DEL IS NULL
              AND L128.OBJ_TYPE_ID = 128
              AND L128.DATE_DEL IS NULL
              AND V2074.IS_DEL = 0
              AND V888.IS_DEL = 0
              AND V2074.LISTVAL_ID = 2074
        INTO :C;
        IF (C IS NULL) THEN
            C = 0;
        V = C;
        SUSPEND;
        EXIT;
    END

    IF (I$Q = 296) THEN
    BEGIN
        SELECT COUNT(*)
        FROM LINKS L23
        INNER JOIN LINKS L95 ON L95.PARENT_ID = L23.OBJ_ID
        INNER JOIN VALL VX ON VX.OBJ_ID = L95.OBJ_ID
        INNER JOIN LINKS L114 ON L114.PARENT_ID = L95.OBJ_ID AND L114.OBJ_TYPE_ID = 114
        WHERE L23.PARENT_ID = :I$OBJ_ID
              AND L23.OBJ_TYPE_ID = 23
              AND L23.DATE_DEL IS NULL
              AND L95.DATE_DEL IS NULL
              AND L95.OBJ_TYPE_ID = 95
              AND VX.IS_DEL = 0
              AND ((VX.LISTVAL_ID = 1827) OR (VX.LISTVAL_ID = 1898) OR (VX.LISTVAL_ID = 1899) OR (VX.LISTVAL_ID = 1900))
              AND L114.DATE_DEL IS NULL
        INTO :I;
        V = I;
        SUSPEND;
        EXIT;
    END

    IF (I$Q = 298) THEN
    BEGIN
        SELECT COUNT(*)
        FROM LINKS L23
        INNER JOIN LINKS L95 ON L95.PARENT_ID = L23.OBJ_ID
        INNER JOIN VALL V1821 ON V1821.OBJ_ID = L95.OBJ_ID
        INNER JOIN LINKS L114 ON L114.PARENT_ID = L95.OBJ_ID AND L114.OBJ_TYPE_ID = 114
        WHERE L23.PARENT_ID = :I$OBJ_ID
              AND L23.OBJ_TYPE_ID = 23
              AND L23.DATE_DEL IS NULL
              AND L95.DATE_DEL IS NULL
              AND L95.OBJ_TYPE_ID = 95
              AND V1821.IS_DEL = 0
              AND (V1821.LISTVAL_ID = 1821)
              AND L114.DATE_DEL IS NULL
        INTO :I;
        V = I;
        SUSPEND;
        EXIT;
    END

    IF (I$Q = 341) THEN
    BEGIN
        SELECT FIRST 1 R.VAL
        FROM LINKS L116
        INNER JOIN VALL V697 ON V697.OBJ_ID = L116.OBJ_ID
        INNER JOIN VALL V700 ON V700.OBJ_ID = L116.OBJ_ID
        INNER JOIN VALL V695 ON V695.OBJ_ID = L116.OBJ_ID
        INNER JOIN LISTVALS LV ON LV.LISTVAL_ID = V700.LISTVAL_ID
        LEFT JOIN RES_GET(LV.RES_ID,  :LANG_CODE) R ON 1=1
        WHERE L116.OBJ_TYPE_ID = 116
              AND L116.DATE_DEL IS NULL
              AND V697.PARAM_ID = 697
              AND V697.IS_DEL = 0
              AND V700.PARAM_ID = 700
              AND V700.IS_DEL = 0
              AND V697.LISTVAL_ID = 2
              AND V695.PARAM_ID = 695
              AND LV.IS_DEL = 0
        ORDER BY V695.LISTVAL_ID
        INTO :V;
        SUSPEND;
        EXIT;
    END

    IF (I$Q = 343) THEN
    BEGIN
        SELECT FIRST 1 V702.VAL
        FROM LINKS L116
        INNER JOIN VALL V697 ON V697.OBJ_ID = L116.OBJ_ID
        INNER JOIN VALI V702 ON V702.OBJ_ID = L116.OBJ_ID
        INNER JOIN VALL V695 ON V695.OBJ_ID = L116.OBJ_ID
        WHERE L116.OBJ_TYPE_ID = 116
              AND L116.DATE_DEL IS NULL
              AND V697.PARAM_ID = 697
              AND V697.IS_DEL = 0
              AND V702.PARAM_ID = 702
              AND V702.IS_DEL = 0
              AND V697.LISTVAL_ID = 2
              AND V695.PARAM_ID = 695
        ORDER BY V695.LISTVAL_ID
        INTO :V;
        SUSPEND;
        EXIT;
    END

    IF (I$Q = 345) THEN
    BEGIN
        SELECT FIRST 1 R.VAL
        FROM LINKS L116
        INNER JOIN VALL V697 ON V697.OBJ_ID = L116.OBJ_ID
        INNER JOIN VALL V709 ON V709.OBJ_ID = L116.OBJ_ID
        INNER JOIN VALL V695 ON V695.OBJ_ID = L116.OBJ_ID
        INNER JOIN LISTVALS LV ON LV.LISTVAL_ID = V709.LISTVAL_ID
        LEFT JOIN RES_GET(LV.RES_ID,  :LANG_CODE) R ON 1=1
        WHERE L116.OBJ_TYPE_ID = 116
        AND L116.DATE_DEL IS NULL
        AND V697.PARAM_ID = 697
        AND V697.IS_DEL = 0
        AND V709.PARAM_ID = 709
        AND V709.IS_DEL = 0
        AND V697.LISTVAL_ID = 2
        AND V695.PARAM_ID = 695
        AND LV.IS_DEL = 0
        ORDER BY V695.LISTVAL_ID
        INTO :V;
        SUSPEND;
        EXIT;
    END

    IF (I$Q = 348) THEN
    BEGIN
        V = '';
        FOR SELECT DISTINCT V699.VAL
            FROM LINKS L116
            INNER JOIN VALL V697 ON V697.OBJ_ID = L116.OBJ_ID
            INNER JOIN VALS V699 ON V699.OBJ_ID = L116.OBJ_ID
            INNER JOIN VALL V695 ON V695.OBJ_ID = L116.OBJ_ID
            WHERE L116.OBJ_TYPE_ID = 116
                  AND L116.DATE_DEL IS NULL
                  AND V697.PARAM_ID = 697
                  AND V697.IS_DEL = 0
                  AND V699.PARAM_ID = 699
                  AND V699.IS_DEL = 0
                  AND V697.LISTVAL_ID = 2
                  AND V695.PARAM_ID = 695
            ORDER BY V695.LISTVAL_ID
            INTO :TYP
        DO
        BEGIN
            IF (V = '') THEN
                V = TYP;
            ELSE
                V = V || ', ' || TYP;
        END
        SUSPEND;
        EXIT;
    END

END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_SPB_INFOCARD_270 (
    I$OBJ_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    KK VARCHAR(200),
    LVS VARCHAR(4),
    INET VARCHAR(4),
    KONTENT VARCHAR(4),
    LOAD1 INTEGER,
    LOAD2 INTEGER,
    LOAD3 INTEGER,
    ALLIN INTEGER)
AS
declare variable OBJ_ID bigint;
declare variable COUNTK integer;
declare variable YEARV varchar(10);
declare variable LANG_CODE varchar(2);
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :LANG_CODE;

FOR SELECT L128.OBJ_ID
FROM LINKS L23
INNER JOIN LINKS L128 ON L128.PARENT_ID=L23.OBJ_ID
INNER JOIN VALL Vx ON Vx.OBJ_ID=L128.OBJ_ID
WHERE L23.PARENT_ID=:I$OBJ_ID
AND L23.OBJ_TYPE_ID=23
AND L23.DATE_DEL IS NULL
AND L128.DATE_DEL IS NULL
AND L128.OBJ_TYPE_ID=128
AND Vx.IS_DEL=0
AND ((Vx.LISTVAL_ID=2067)or(Vx.LISTVAL_ID=2068))
INTO :OBJ_ID
    DO BEGIN

    SELECT R.VAL
    FROM LINKS L128
    INNER JOIN VALL V206x ON V206x.OBJ_ID=L128.OBJ_ID
    INNER JOIN LISTVALS Lv ON Lv.LISTVAL_ID=V206x.LISTVAL_ID
    LEFT JOIN RES_GET(LV.RES_ID,  :LANG_CODE) R ON 1=1
    WHERE L128.OBJ_ID=:OBJ_ID
    AND L128.OBJ_TYPE_ID=128
    AND V206x.IS_DEL=0
    AND Lv.IS_DEL=0
    AND L128.DATE_DEL IS NULL
    AND ((V206x.LISTVAL_ID=2067)or(V206x.LISTVAL_ID=2068))
    INTO :KK;

    SELECT V878.VAL
    FROM LINKS L128
    INNER JOIN VALS V878 ON V878.OBJ_ID=L128.OBJ_ID AND V878.PARAM_ID=878
    WHERE L128.OBJ_ID=:OBJ_ID
    AND L128.DATE_DEL IS NULL
    AND L128.OBJ_TYPE_ID=128
    AND V878.IS_DEL=0
    INTO :YEARV;

    COUNTK=0;
    SELECT Count(*)
    FROM LINKS L128
    INNER JOIN VALL V206x ON V206x.OBJ_ID=L128.OBJ_ID
    INNER JOIN LISTVALS Lv ON Lv.LISTVAL_ID=V206x.LISTVAL_ID
    INNER JOIN LINKS L114 ON L114.PARENT_ID=L128.OBJ_ID AND L114.OBJ_TYPE_ID=114
    WHERE L128.OBJ_ID=:OBJ_ID
    AND V206x.IS_DEL=0
    AND Lv.IS_DEL=0
    AND ((V206x.LISTVAL_ID=2067)or(V206x.LISTVAL_ID=2068))
    AND L114.DATE_DEL IS NULL
    AND L128.DATE_DEL IS NULL
    AND L128.OBJ_TYPE_ID=128
    INTO :COUNTK ;



    KK=KK || ' / ' || CAST (COUNTK AS VARCHAR(10)) || ' шт.' || ' / ' || YEARV || ' г.в.';


    COUNTK=0;
    LVS='нет';
    SELECT V880.LISTVAL_ID
    FROM LINKS L128
    INNER JOIN VALL V880 ON V880.OBJ_ID=L128.OBJ_ID AND V880.PARAM_ID=880
    WHERE L128.OBJ_ID=:OBJ_ID
    AND L128.DATE_DEL IS NULL
    AND L128.OBJ_TYPE_ID=128
    AND V880.IS_DEL=0
    INTO :COUNTK;
    IF (COUNTK=2)
    THEN LVS='да';
    
    COUNTK=0;
    INET='нет';
    SELECT V881.LISTVAL_ID
    FROM LINKS L128
    INNER JOIN VALL V881 ON V881.OBJ_ID=L128.OBJ_ID AND V881.PARAM_ID=881
    WHERE L128.OBJ_ID=:OBJ_ID
    AND L128.DATE_DEL IS NULL
    AND L128.OBJ_TYPE_ID=128
    AND V881.IS_DEL=0
    INTO :COUNTK;
    IF (COUNTK=2)
    THEN INET='да';


    COUNTK=0;
    KONTENT='нет';
    SELECT V883.LISTVAL_ID
    FROM LINKS L128
    INNER JOIN VALL V883 ON V883.OBJ_ID=L128.OBJ_ID AND V883.PARAM_ID=883
    WHERE L128.OBJ_ID=:OBJ_ID
    AND L128.DATE_DEL IS NULL
    AND L128.OBJ_TYPE_ID=128
    AND V883.IS_DEL=0
    INTO :COUNTK;
    IF (COUNTK=2)
    THEN KONTENT='да';


    LOAD1=0;
    SELECT V884.VAL
    FROM LINKS L128
    INNER JOIN VALI V884 ON V884.OBJ_ID=L128.OBJ_ID AND V884.PARAM_ID=884
    WHERE L128.OBJ_ID=:OBJ_ID
    AND L128.DATE_DEL IS NULL
    AND V884.IS_DEL=0
    AND L128.OBJ_TYPE_ID=128
    INTO :LOAD1;

    LOAD2=0;
    SELECT V885.VAL
    FROM LINKS L128
    INNER JOIN VALI V885 ON V885.OBJ_ID=L128.OBJ_ID AND V885.PARAM_ID=885
    WHERE L128.OBJ_ID=:OBJ_ID
    AND L128.DATE_DEL IS NULL
    AND V885.IS_DEL=0
    INTO :LOAD2;

    LOAD3=0;
    SELECT V886.VAL
    FROM LINKS L128
    INNER JOIN VALI V886 ON V886.OBJ_ID=L128.OBJ_ID AND V886.PARAM_ID=886
    WHERE L128.OBJ_ID=:OBJ_ID
    AND L128.DATE_DEL IS NULL
    AND V886.IS_DEL=0
    INTO :LOAD3;

    ALLIN=LOAD1+LOAD2+LOAD3;
    SUSPEND;

    END




END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_SPB_INF_OU_0 RETURNS (
    X1 VARCHAR(12),
    X2 VARCHAR(12),
    X3 VARCHAR(12))
AS
DECLARE VARIABLE Y1 SMALLINT;
DECLARE VARIABLE Y2 SMALLINT;
BEGIN
    Y1 = EXTRACT(YEAR FROM CURRENT_TIMESTAMP);
    Y2 = Y1 - 1;
    X1  = Y1 || ' - ' || Y2;

    Y1  = Y1 - 2;
    Y2  = Y2 - 2;
    X2  = Y1 || ' - ' || Y2;

    X3  =       ' < ' || Y2;

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_SPB_INF_OU_1 (
    I$OBJ_ID BIGINT,
    I$X SMALLINT)
RETURNS (
    X1 INTEGER,
    X2 INTEGER,
    X3 INTEGER,
    X4 INTEGER,
    X5 NUMERIC(9,3))
AS
declare variable Y smallint;
declare variable C integer;
declare variable OBJ_ID bigint;
declare variable DEEP smallint;
declare variable TYPE_ID bigint;
BEGIN
    DEEP = 0;
    SELECT TYPE_ID FROM OBJECTS WHERE OBJ_ID = :I$OBJ_ID INTO :TYPE_ID;
    IF (TYPE_ID = 2)   THEN DEEP = 0;
    IF (TYPE_ID = 111) THEN DEEP = 1;
    IF (TYPE_ID = 112) THEN DEEP = 2;

    Y = EXTRACT(YEAR FROM CURRENT_TIMESTAMP);
    X1 = 0; X2 = 0; X3 = 0; X4 = 0; X5 = 0;

    C = 0;
    FOR
        SELECT O.OBJ_ID
        FROM OBJECT_CHILDREN_GET_DEEP(:I$OBJ_ID, 2, :DEEP) O
        INTO :OBJ_ID
    DO
    BEGIN
        SELECT :C + COUNT(*)
        FROM LINKS L7
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
        JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        WHERE L7.PARENT_ID = :OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
        INTO :C;

        SELECT :X1 + COALESCE(SUM(VI.VAL),0)
        FROM LINKS L23
        JOIN LINKS L95 ON L95.PARENT_ID = L23.OBJ_ID AND L95.OBJ_TYPE_ID = 95 AND L95.DATE_DEL IS NULL
        JOIN VALS VS ON VS.PARAM_ID = 630 AND VS.OBJ_ID = L95.OBJ_ID AND VS.IS_DEL = 0 AND (
          (CHAR_LENGTH(VS.VAL) = 4 AND ((VS.VAL = :Y) OR (VS.VAL = :Y - 1))) OR
          (CHAR_LENGTH(VS.VAL) = 10 AND ((EXTRACT(YEAR FROM CAST(VS.VAL AS DATE)) = :Y) OR (EXTRACT(YEAR FROM CAST(VS.VAL AS DATE)) = :Y - 1)))
        )
        JOIN VALL VL ON VL.PARAM_ID = 604 AND VL.OBJ_ID = L95.OBJ_ID AND VL.IS_DEL = 0
        JOIN VALI VI ON VI.PARAM_ID = 605 AND VI.OBJ_ID = L95.OBJ_ID AND VI.IS_DEL = 0
        WHERE L23.PARENT_ID = :OBJ_ID AND L23.OBJ_TYPE_ID = 23 AND L23.DATE_DEL IS NULL
        AND (
            ((:I$X = 1) AND (VL.LISTVAL_ID IN (1800,1804,1807)))
            OR
            ((:I$X = 2) AND (VL.LISTVAL_ID IN (1801,1805,1808)))
            OR
            ((:I$X = 3) AND (VL.LISTVAL_ID IN (1802,1806,1809,1803,1810,1811)))
            OR
            ((:I$X = 4) AND (VL.LISTVAL_ID IN (1800,1801,1802)))
            OR
            ((:I$X = 5) AND (VL.LISTVAL_ID IN (1803)))
            OR
            ((:I$X = 6) AND (VL.LISTVAL_ID IN (1804,1805,1806)))
            OR
            ((:I$X = 7) AND (VL.LISTVAL_ID IN (1807,1808,1809)))
            OR
            ((:I$X = 8) AND (VL.LISTVAL_ID IN (1810)))
            OR
            ((:I$X = 9) AND (VL.LISTVAL_ID IN (1811)))
            )
        INTO :X1;

        SELECT :X2 + COALESCE(SUM(VI.VAL),0)
        FROM LINKS L23
        JOIN LINKS L95 ON L95.PARENT_ID = L23.OBJ_ID AND L95.OBJ_TYPE_ID = 95 AND L95.DATE_DEL IS NULL
        JOIN VALS VS ON VS.PARAM_ID = 630 AND VS.OBJ_ID = L95.OBJ_ID AND VS.IS_DEL = 0 AND (
          (CHAR_LENGTH(VS.VAL) = 4 AND ((VS.VAL = :Y - 2) OR (VS.VAL = :Y - 3))) OR
          (CHAR_LENGTH(VS.VAL) = 10 AND ((EXTRACT(YEAR FROM CAST(VS.VAL AS DATE)) = :Y - 2) OR (EXTRACT(YEAR FROM CAST(VS.VAL AS DATE)) = :Y - 3)))
        )
        JOIN VALL VL ON VL.PARAM_ID = 604 AND VL.OBJ_ID = L95.OBJ_ID AND VL.IS_DEL = 0
        JOIN VALI VI ON VI.PARAM_ID = 605 AND VI.OBJ_ID = L95.OBJ_ID AND VI.IS_DEL = 0
        WHERE L23.PARENT_ID = :OBJ_ID AND L23.OBJ_TYPE_ID = 23 AND L23.DATE_DEL IS NULL
        AND (
            ((:I$X = 1) AND (VL.LISTVAL_ID IN (1800,1804,1807)))
            OR
            ((:I$X = 2) AND (VL.LISTVAL_ID IN (1801,1805,1808)))
            OR
            ((:I$X = 3) AND (VL.LISTVAL_ID IN (1802,1806,1809,1803,1810,1811)))
            OR
            ((:I$X = 4) AND (VL.LISTVAL_ID IN (1800,1801,1802)))
            OR
            ((:I$X = 5) AND (VL.LISTVAL_ID IN (1803)))
            OR
            ((:I$X = 6) AND (VL.LISTVAL_ID IN (1804,1805,1806)))
            OR
            ((:I$X = 7) AND (VL.LISTVAL_ID IN (1807,1808,1809)))
            OR
            ((:I$X = 8) AND (VL.LISTVAL_ID IN (1810)))
            OR
            ((:I$X = 9) AND (VL.LISTVAL_ID IN (1811)))
            )
        INTO :X2;

        SELECT :X3 + COALESCE(SUM(VI.VAL),0)
        FROM LINKS L23
        JOIN LINKS L95 ON L95.PARENT_ID = L23.OBJ_ID AND L95.OBJ_TYPE_ID = 95 AND L95.DATE_DEL IS NULL
        JOIN VALS VS ON VS.PARAM_ID = 630 AND VS.OBJ_ID = L95.OBJ_ID AND VS.IS_DEL = 0 AND (
          (CHAR_LENGTH(VS.VAL) = 4 AND CAST(VS.VAL AS SMALLINT) < :Y - 3) OR
          (CHAR_LENGTH(VS.VAL) = 10 AND EXTRACT(YEAR FROM CAST(VS.VAL AS DATE)) < :Y - 3)
        )
        JOIN VALL VL ON VL.PARAM_ID = 604 AND VL.OBJ_ID = L95.OBJ_ID AND VL.IS_DEL = 0
        JOIN VALI VI ON VI.PARAM_ID = 605 AND VI.OBJ_ID = L95.OBJ_ID AND VI.IS_DEL = 0
        WHERE L23.PARENT_ID = :OBJ_ID AND L23.OBJ_TYPE_ID = 23 AND L23.DATE_DEL IS NULL
        AND (
            ((:I$X = 1) AND (VL.LISTVAL_ID IN (1800,1804,1807)))
            OR
            ((:I$X = 2) AND (VL.LISTVAL_ID IN (1801,1805,1808)))
            OR
            ((:I$X = 3) AND (VL.LISTVAL_ID IN (1802,1806,1809,1803,1810,1811)))
            OR
            ((:I$X = 4) AND (VL.LISTVAL_ID IN (1800,1801,1802)))
            OR
            ((:I$X = 5) AND (VL.LISTVAL_ID IN (1803)))
            OR
            ((:I$X = 6) AND (VL.LISTVAL_ID IN (1804,1805,1806)))
            OR
            ((:I$X = 7) AND (VL.LISTVAL_ID IN (1807,1808,1809)))
            OR
            ((:I$X = 8) AND (VL.LISTVAL_ID IN (1810)))
            OR
            ((:I$X = 9) AND (VL.LISTVAL_ID IN (1811)))
            )
        INTO :X3;

    END

    X4 = X1 + X2 + X3;
    IF (C > 0) THEN BEGIN X5 = X4 * 1000 / C; X5 = X5 / 1000; END
    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_SPB_INF_OU_10 (
    I$OBJ_ID BIGINT)
RETURNS (
    C NUMERIC(9,2))
AS
DECLARE VARIABLE D DOUBLE PRECISION;
DECLARE VARIABLE DEEP SMALLINT;
DECLARE VARIABLE TYPE_ID BIGINT;
DECLARE VARIABLE OU_COUNT NUMERIC(9,2);
DECLARE VARIABLE TEACHERS_COUNT NUMERIC(9,2);
BEGIN
    DEEP = 0;
    SELECT TYPE_ID FROM OBJECTS WHERE OBJ_ID = :I$OBJ_ID INTO :TYPE_ID;
    IF (TYPE_ID = 2)   THEN DEEP = 0;
    IF (TYPE_ID = 111) THEN DEEP = 1;
    IF (TYPE_ID = 112) THEN DEEP = 2;

    SELECT COUNT(*)
    FROM OBJECT_CHILDREN_GET_DEEP(:I$OBJ_ID, 2, :DEEP) O
    INTO :OU_COUNT;

    SELECT COUNT(*)
    FROM OBJECT_CHILDREN_GET_DEEP(:I$OBJ_ID, 2, :DEEP) O
    INNER JOIN LINKS L14 ON L14.PARENT_ID = O.OBJ_ID
    WHERE L14.OBJ_TYPE_ID = 14
      AND L14.DATE_DEL IS NULL
    INTO :TEACHERS_COUNT;

    IF (TEACHERS_COUNT = 0) THEN EXIT;

    C = 0;
    SELECT COUNT(*)
    FROM OBJECT_CHILDREN_GET_DEEP(:I$OBJ_ID, 2, :DEEP) O
    INNER JOIN LINKS L14 ON L14.PARENT_ID = O.OBJ_ID
    INNER JOIN VALL V242 ON V242.PARAM_ID = 242 AND V242.OBJ_ID = L14.OBJ_ID
    WHERE L14.OBJ_TYPE_ID = 14
      AND L14.DATE_DEL IS NULL
      AND V242.IS_DEL = 0
      AND V242.LISTVAL_ID = 4
    INTO :C;
    C = C * 100 / TEACHERS_COUNT;
    SUSPEND;  /*1*/

    C = 0;
    SELECT SUM(V238.VAL)
    FROM OBJECT_CHILDREN_GET_DEEP(:I$OBJ_ID, 2, :DEEP) O
    INNER JOIN LINKS L14 ON L14.PARENT_ID = O.OBJ_ID
    INNER JOIN VALI V238 ON V238.PARAM_ID = 238 AND V238.OBJ_ID = L14.OBJ_ID
    WHERE L14.OBJ_TYPE_ID = 14
      AND L14.DATE_DEL IS NULL
      AND V238.IS_DEL = 0
    INTO :C;
    C = C / TEACHERS_COUNT;
    SUSPEND;  /*2*/

    C = 0;
    SELECT SUM(V256.VAL)
    FROM OBJECT_CHILDREN_GET_DEEP(:I$OBJ_ID, 2, :DEEP) O
    INNER JOIN LINKS L14 ON L14.PARENT_ID = O.OBJ_ID
    INNER JOIN VALI V256 ON V256.PARAM_ID = 256 AND V256.OBJ_ID = L14.OBJ_ID
    WHERE L14.OBJ_TYPE_ID = 14
      AND L14.DATE_DEL IS NULL
      AND V256.IS_DEL = 0
    INTO :C;
    C = C / TEACHERS_COUNT;
    SUSPEND;  /*3*/

    C = 0;
    SELECT COUNT(*)
    FROM OBJECT_CHILDREN_GET_DEEP(:I$OBJ_ID, 2, :DEEP) O
    INNER JOIN LINKS L14 ON L14.PARENT_ID = O.OBJ_ID
    INNER JOIN VALL V245 ON V245.PARAM_ID = 245 AND V245.OBJ_ID = L14.OBJ_ID
    WHERE L14.OBJ_TYPE_ID = 14
      AND L14.DATE_DEL IS NULL
      AND V245.IS_DEL = 0
      AND V245.LISTVAL_ID = 4
    INTO :C;
    C = C * 100 / TEACHERS_COUNT;
    SUSPEND;  /*4*/

    C = 0;
    SELECT COUNT(*)
    FROM OBJECT_CHILDREN_GET_DEEP(:I$OBJ_ID, 2, :DEEP) O
    INNER JOIN LINKS L14 ON L14.PARENT_ID = O.OBJ_ID
    INNER JOIN VALL V246 ON V246.PARAM_ID = 246 AND V246.OBJ_ID = L14.OBJ_ID
    WHERE L14.OBJ_TYPE_ID = 14
      AND L14.DATE_DEL IS NULL
      AND V246.IS_DEL = 0
      AND V246.LISTVAL_ID = 4
    INTO :C;
    C = C * 100 / TEACHERS_COUNT;
    SUSPEND;  /*5*/

    C = 0;
    SELECT COUNT(*)
    FROM OBJECT_CHILDREN_GET_DEEP(:I$OBJ_ID, 2, :DEEP) O
    INNER JOIN LINKS L14 ON L14.PARENT_ID = O.OBJ_ID
    INNER JOIN VALL V247 ON V247.PARAM_ID = 247 AND V247.OBJ_ID = L14.OBJ_ID
    WHERE L14.OBJ_TYPE_ID = 14
      AND L14.DATE_DEL IS NULL
      AND V247.IS_DEL = 0
      AND V247.LISTVAL_ID = 2
    INTO :C;
    C = C * 100 / TEACHERS_COUNT;
    SUSPEND;  /*6*/

    C = 0;
    SELECT COUNT(*)
    FROM OBJECT_CHILDREN_GET_DEEP(:I$OBJ_ID, 2, :DEEP) O
    INNER JOIN LINKS L14 ON L14.PARENT_ID = O.OBJ_ID
    INNER JOIN VALL V248 ON V248.PARAM_ID = 248 AND V248.OBJ_ID = L14.OBJ_ID
    WHERE L14.OBJ_TYPE_ID = 14
      AND L14.DATE_DEL IS NULL
      AND V248.IS_DEL = 0
      AND V248.LISTVAL_ID = 4
    INTO :C;
    C = C * 100 / TEACHERS_COUNT;
    SUSPEND;  /*7*/

    C = 0;
    SELECT COUNT(*)
    FROM OBJECT_CHILDREN_GET_DEEP(:I$OBJ_ID, 2, :DEEP) O
    INNER JOIN LINKS L14 ON L14.PARENT_ID = O.OBJ_ID
    INNER JOIN VALL V249 ON V249.PARAM_ID = 249 AND V249.OBJ_ID = L14.OBJ_ID
    WHERE L14.OBJ_TYPE_ID = 14
      AND L14.DATE_DEL IS NULL
      AND V249.IS_DEL = 0
      AND V249.LISTVAL_ID = 4
    INTO :C;
    C = C * 100 / TEACHERS_COUNT;
    SUSPEND;  /*8*/

    C = 0;
    SELECT COUNT(*)
    FROM OBJECT_CHILDREN_GET_DEEP(:I$OBJ_ID, 2, :DEEP) O
    INNER JOIN LINKS L14 ON L14.PARENT_ID = O.OBJ_ID
    INNER JOIN VALL V257 ON V257.PARAM_ID = 257 AND V257.OBJ_ID = L14.OBJ_ID
    WHERE L14.OBJ_TYPE_ID = 14
      AND L14.DATE_DEL IS NULL
      AND V257.IS_DEL = 0
      AND V257.LISTVAL_ID = 2
    INTO :C;
    C = C * 100 / TEACHERS_COUNT;
    SUSPEND;  /*9*/

    C = 0;
    SELECT COUNT(*)
    FROM OBJECT_CHILDREN_GET_DEEP(:I$OBJ_ID, 2, :DEEP) O
    INNER JOIN LINKS L14 ON L14.PARENT_ID = O.OBJ_ID
    INNER JOIN VALL V251 ON V251.PARAM_ID = 251 AND V251.OBJ_ID = L14.OBJ_ID
    WHERE L14.OBJ_TYPE_ID = 14
      AND L14.DATE_DEL IS NULL
      AND V251.IS_DEL = 0
      AND V251.LISTVAL_ID = 2
    INTO :C;
    C = C * 100 / TEACHERS_COUNT;
    SUSPEND;  /*10*/

    C = 0;
    SELECT COUNT(*)
    FROM OBJECT_CHILDREN_GET_DEEP(:I$OBJ_ID, 2, :DEEP) O
    INNER JOIN LINKS L14 ON L14.PARENT_ID = O.OBJ_ID
    INNER JOIN VALL V252 ON V252.PARAM_ID = 252 AND V252.OBJ_ID = L14.OBJ_ID
    WHERE L14.OBJ_TYPE_ID = 14
      AND L14.DATE_DEL IS NULL
      AND V252.IS_DEL = 0
      AND V252.LISTVAL_ID = 2
    INTO :C;
    C = C * 100 / TEACHERS_COUNT;
    SUSPEND;  /*11*/

    C = 0;
    SELECT COUNT(*)
    FROM OBJECT_CHILDREN_GET_DEEP(:I$OBJ_ID, 2, :DEEP) O
    INNER JOIN LINKS L14 ON L14.PARENT_ID = O.OBJ_ID
    INNER JOIN VALL V258 ON V258.PARAM_ID = 258 AND V258.OBJ_ID = L14.OBJ_ID
    WHERE L14.OBJ_TYPE_ID = 14
      AND L14.DATE_DEL IS NULL
      AND V258.IS_DEL = 0
      AND V258.LISTVAL_ID = 2
    INTO :C;
    C = C * 100 / TEACHERS_COUNT;
    SUSPEND;  /*12*/

    C = 0;
    SELECT COUNT(*)
    FROM OBJECT_CHILDREN_GET_DEEP(:I$OBJ_ID, 2, :DEEP) O
    INNER JOIN LINKS L14 ON L14.PARENT_ID = O.OBJ_ID
    INNER JOIN VALL V259 ON V259.PARAM_ID = 259 AND V259.OBJ_ID = L14.OBJ_ID
    WHERE L14.OBJ_TYPE_ID = 14
      AND L14.DATE_DEL IS NULL
      AND V259.IS_DEL = 0
      AND V259.LISTVAL_ID = 2
    INTO :C;
    C = C * 100 / TEACHERS_COUNT;
    SUSPEND;  /*13*/

    C = 0;
    SELECT COUNT(*)
    FROM OBJECT_CHILDREN_GET_DEEP(:I$OBJ_ID, 2, :DEEP) O
    INNER JOIN LINKS L14 ON L14.PARENT_ID = O.OBJ_ID
    INNER JOIN VALL V260 ON V260.PARAM_ID = 260 AND V260.OBJ_ID = L14.OBJ_ID
    WHERE L14.OBJ_TYPE_ID = 14
      AND L14.DATE_DEL IS NULL
      AND V260.IS_DEL = 0
      AND V260.LISTVAL_ID = 2
    INTO :C;
    C = C * 100 / TEACHERS_COUNT;
    SUSPEND;  /*14*/

    D = 0;
    SELECT SUM(V261.VAL)
    FROM OBJECT_CHILDREN_GET_DEEP(:I$OBJ_ID, 2, :DEEP) O
    INNER JOIN LINKS L14 ON L14.PARENT_ID = O.OBJ_ID
    INNER JOIN VALI V261 ON V261.PARAM_ID = 261 AND V261.OBJ_ID = L14.OBJ_ID
    WHERE L14.OBJ_TYPE_ID = 14
      AND L14.DATE_DEL IS NULL
      AND V261.IS_DEL = 0
    INTO :D;
    C = D / TEACHERS_COUNT;
    SUSPEND;  /*15*/

    C = 0;
    SELECT COUNT(*)
    FROM OBJECT_CHILDREN_GET_DEEP(:I$OBJ_ID, 2, :DEEP) O
    INNER JOIN LINKS L14 ON L14.PARENT_ID = O.OBJ_ID
    INNER JOIN VALL V263 ON V263.PARAM_ID = 263 AND V263.OBJ_ID = L14.OBJ_ID
    WHERE L14.OBJ_TYPE_ID = 14
      AND L14.DATE_DEL IS NULL
      AND V263.IS_DEL = 0
      AND V263.LISTVAL_ID = 2
    INTO :C;
    C = C * 100 / TEACHERS_COUNT;
    SUSPEND;  /*16*/

    C = 0;
    SELECT COUNT(*)
    FROM OBJECT_CHILDREN_GET_DEEP(:I$OBJ_ID, 2, :DEEP) O
    INNER JOIN LINKS L14 ON L14.PARENT_ID = O.OBJ_ID
    INNER JOIN VALL V264 ON V264.PARAM_ID = 264 AND V264.OBJ_ID = L14.OBJ_ID
    WHERE L14.OBJ_TYPE_ID = 14
      AND L14.DATE_DEL IS NULL
      AND V264.IS_DEL = 0
      AND V264.LISTVAL_ID = 2
    INTO :C;
    C = C * 100 / TEACHERS_COUNT;
    SUSPEND;  /*17*/

    C = 0;
    SELECT COUNT(*)
    FROM OBJECT_CHILDREN_GET_DEEP(:I$OBJ_ID, 2, :DEEP) O
    INNER JOIN LINKS L14 ON L14.PARENT_ID = O.OBJ_ID
    INNER JOIN VALL V265 ON V265.PARAM_ID = 265 AND V265.OBJ_ID = L14.OBJ_ID
    WHERE L14.OBJ_TYPE_ID = 14
      AND L14.DATE_DEL IS NULL
      AND V265.IS_DEL = 0
      AND V265.LISTVAL_ID = 2
    INTO :C;
    C = C * 100 / TEACHERS_COUNT;
    SUSPEND;  /*18*/


    D = 0;
    SELECT SUM(V735.VAL)
    FROM OBJECT_CHILDREN_GET_DEEP(:I$OBJ_ID, 2, :DEEP) O
    INNER JOIN VALF V735 ON V735.PARAM_ID = 735 AND V735.OBJ_ID = O.OBJ_ID
    WHERE V735.IS_DEL = 0
    INTO :D;
    C = D / OU_COUNT;
    SUSPEND;  /*19*/

    D = 0;
    SELECT SUM(V736.VAL)
    FROM OBJECT_CHILDREN_GET_DEEP(:I$OBJ_ID, 2, :DEEP) O
    INNER JOIN VALF V736 ON V736.PARAM_ID = 736 AND V736.OBJ_ID = O.OBJ_ID
    WHERE V736.IS_DEL = 0
    INTO :D;
    C = D / OU_COUNT;
    SUSPEND;  /*20*/

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_SPB_INF_OU_11 (
    I$OBJ_ID BIGINT)
RETURNS (
    C INTEGER)
AS
DECLARE VARIABLE DEEP SMALLINT;
DECLARE VARIABLE TYPE_ID BIGINT;
BEGIN
    DEEP = 0;
    SELECT TYPE_ID FROM OBJECTS WHERE OBJ_ID = :I$OBJ_ID INTO :TYPE_ID;
    IF (TYPE_ID = 2)   THEN DEEP = 0;
    IF (TYPE_ID = 111) THEN DEEP = 1;
    IF (TYPE_ID = 112) THEN DEEP = 2;

    C = 0;
    SELECT SUM(V738.VAL)
    FROM OBJECT_CHILDREN_GET_DEEP(:I$OBJ_ID, 2, :DEEP) O
    INNER JOIN VALI V738 ON V738.PARAM_ID = 738 AND V738.OBJ_ID = O.OBJ_ID
    WHERE V738.IS_DEL = 0
    INTO :C;
    SUSPEND;

    C = 0;
    SELECT SUM(V739.VAL)
    FROM OBJECT_CHILDREN_GET_DEEP(:I$OBJ_ID, 2, :DEEP) O
    INNER JOIN VALI V739 ON V739.PARAM_ID = 739 AND V739.OBJ_ID = O.OBJ_ID
    WHERE V739.IS_DEL = 0
    INTO :C;
    SUSPEND;

    C = 0;
    SELECT SUM(V740.VAL)
    FROM OBJECT_CHILDREN_GET_DEEP(:I$OBJ_ID, 2, :DEEP) O
    INNER JOIN VALI V740 ON V740.PARAM_ID = 740 AND V740.OBJ_ID = O.OBJ_ID
    WHERE V740.IS_DEL = 0
    INTO :C;
    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_SPB_INF_OU_1_DTL (
    I$OBJ_ID BIGINT,
    I$X SMALLINT,
    I$COL SMALLINT)
RETURNS (
    NAME VARCHAR(1000),
    YYYY VARCHAR(10))
AS
DECLARE VARIABLE Y SMALLINT;
DECLARE VARIABLE OBJ_ID BIGINT;
DECLARE VARIABLE DEEP SMALLINT;
DECLARE VARIABLE TYPE_ID BIGINT;
BEGIN
    DEEP = 0;
    SELECT TYPE_ID FROM OBJECTS WHERE OBJ_ID = :I$OBJ_ID INTO :TYPE_ID;
    IF (TYPE_ID = 2)   THEN DEEP = 0;
    IF (TYPE_ID = 111) THEN DEEP = 1;
    IF (TYPE_ID = 112) THEN DEEP = 2;

    Y = EXTRACT(YEAR FROM CURRENT_TIMESTAMP);

    FOR SELECT O.OBJ_ID FROM OBJECT_CHILDREN_GET_DEEP(:I$OBJ_ID, 2, :DEEP) O INTO :OBJ_ID /*OU*/
    DO
    BEGIN
        FOR SELECT
                (SELECT CAPTION FROM OBJECT_CAPTION_GET(L95.OBJ_ID)),
                VS.VAL

            FROM LINKS L23
    
            JOIN LINKS L95
            ON L95.PARENT_ID = L23.OBJ_ID
    
            JOIN VALS   VS
            ON VS.PARAM_ID = 630
            AND VS.OBJ_ID = L95.OBJ_ID
    
            JOIN VALL   VL
            ON VL.PARAM_ID = 604
            AND VL.OBJ_ID = L95.OBJ_ID

            WHERE L23.PARENT_ID = :OBJ_ID
            AND L23.OBJ_TYPE_ID = 23
            AND L23.DATE_DEL IS NULL
            AND L95.OBJ_TYPE_ID = 95
            AND L95.DATE_DEL IS NULL
            AND VS.IS_DEL = 0
            AND ((:I$COL = 1 AND (VS.VAL = :Y OR VS.VAL = :Y - 1))
              OR (:I$COL = 2 AND (VS.VAL = :Y - 2 OR VS.VAL = :Y - 3))
              OR (:I$COL = 3 AND CAST(VS.VAL AS SMALLINT) < :Y-3)
              OR (:I$COL = 4))
            AND VL.IS_DEL = 0
            AND (
                ((:I$X = 1) AND (VL.LISTVAL_ID IN (1800,1804,1807)))
                OR
                ((:I$X = 2) AND (VL.LISTVAL_ID IN (1801,1805,1808)))
                OR
                ((:I$X = 3) AND (VL.LISTVAL_ID IN (1802,1806,1809,1803,1810,1811)))
                OR
                ((:I$X = 4) AND (VL.LISTVAL_ID IN (1800,1801,1802)))
                OR
                ((:I$X = 5) AND (VL.LISTVAL_ID IN (1803)))
                OR
                ((:I$X = 6) AND (VL.LISTVAL_ID IN (1804,1805,1806)))
                OR
                ((:I$X = 7) AND (VL.LISTVAL_ID IN (1807,1808,1809)))
                OR
                ((:I$X = 8) AND (VL.LISTVAL_ID IN (1810)))
                OR
                ((:I$X = 9) AND (VL.LISTVAL_ID IN (1811)))
                )
            INTO :NAME, :YYYY
        DO
        BEGIN
            SUSPEND;
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_SPB_INF_OU_2 (
    I$OBJ_ID BIGINT)
RETURNS (
    N SMALLINT,
    NM VARCHAR(1000),
    TP VARCHAR(100),
    Y VARCHAR(4),
    X1 INTEGER,
    X2 INTEGER,
    S1 VARCHAR(4),
    S2 VARCHAR(4))
AS
BEGIN
    FOR SELECT N, NM, TP, Y, X1, X2, S1, S2
        FROM R_SPB_INF_OU_2_ALL(:I$OBJ_ID)
        INTO :N, :NM, :TP, :Y, :X1, :X2, :S1, :S2
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_SPB_INF_OU_2_ALL (
    I$OBJ_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    N SMALLINT,
    NM VARCHAR(1000),
    TP VARCHAR(100),
    Y VARCHAR(4),
    X1 INTEGER,
    X2 INTEGER,
    S1 VARCHAR(4),
    S2 VARCHAR(4))
AS
DECLARE VARIABLE LISTVAL_ID BIGINT;
DECLARE VARIABLE LVS BIGINT;
DECLARE VARIABLE INET BIGINT;
DECLARE VARIABLE DEEP SMALLINT;
DECLARE VARIABLE TYPE_ID BIGINT;
BEGIN
    DEEP = 0;
    SELECT TYPE_ID FROM OBJECTS WHERE OBJ_ID = :I$OBJ_ID INTO :TYPE_ID;
    IF (TYPE_ID = 2)   THEN DEEP = 0;
    IF (TYPE_ID = 111) THEN DEEP = 1;
    IF (TYPE_ID = 112) THEN DEEP = 2;

    N = 0;

    FOR SELECT L128.OBJ_ID, V877.VAL, V876.LISTVAL_ID, V878.VAL, V880.LISTVAL_ID, V881.LISTVAL_ID
        FROM OBJECT_CHILDREN_GET_DEEP(:I$OBJ_ID, 2, :DEEP) O
        INNER JOIN LINKS  L23 ON  L23.PARENT_ID = O.OBJ_ID
        INNER JOIN LINKS L128 ON L128.PARENT_ID = L23.OBJ_ID
        INNER JOIN VALS  V877 ON V877.PARAM_ID  = 877 AND V877.OBJ_ID = L128.OBJ_ID
        INNER JOIN VALL  V876 ON V876.PARAM_ID  = 876 AND V876.OBJ_ID = L128.OBJ_ID
        LEFT  JOIN VALS  V878 ON V878.PARAM_ID  = 878 AND V878.OBJ_ID = L128.OBJ_ID AND V878.IS_DEL = 0
        LEFT  JOIN VALL  V880 ON V880.PARAM_ID  = 880 AND V880.OBJ_ID = L128.OBJ_ID AND V880.IS_DEL = 0
        LEFT  JOIN VALL  V881 ON V881.PARAM_ID  = 881 AND V881.OBJ_ID = L128.OBJ_ID AND V881.IS_DEL = 0
        WHERE L23.OBJ_TYPE_ID = 23
        AND L23.DATE_DEL IS NULL
        AND L128.OBJ_TYPE_ID = 128
        AND L128.DATE_DEL IS NULL
        AND V877.IS_DEL = 0
        AND V876.IS_DEL = 0
        AND ((V876.LISTVAL_ID = 2067) OR (V876.LISTVAL_ID = 2068))
        INTO :OBJ_ID, :NM, :LISTVAL_ID, :Y, :LVS, :INET
    DO
    BEGIN
        N = N + 1;
        IF (LISTVAL_ID = 2067) THEN TP = 'стационарный'; ELSE TP = 'мобильный';

        SELECT COUNT(*)
        FROM LINKS  L114
        INNER JOIN LINKS L95 ON L95.OBJ_ID = L114.OBJ_ID
        INNER JOIN VALL V604 ON V604.PARAM_ID=604 AND V604.OBJ_ID=L95.PARENT_ID
        WHERE L114.PARENT_ID = :OBJ_ID
        AND L114.OBJ_TYPE_ID = 114
        AND L114.DATE_DEL IS NULL
        AND L95.PARENT_TYPE_ID = 95
        AND L95.DATE_DEL IS NULL
        AND V604.IS_DEL = 0
        AND ((V604.LISTVAL_ID = 1804) OR (V604.LISTVAL_ID = 1805) OR (V604.LISTVAL_ID = 1806))
        INTO :X1;

        SELECT COUNT(*)
        FROM LINKS  L114
        INNER JOIN LINKS L95 ON L95.OBJ_ID = L114.OBJ_ID
        INNER JOIN VALL V604 ON V604.PARAM_ID=604 AND V604.OBJ_ID=L95.PARENT_ID
        WHERE L114.PARENT_ID = :OBJ_ID
        AND L114.OBJ_TYPE_ID = 114
        AND L114.DATE_DEL IS NULL
        AND L95.PARENT_TYPE_ID = 95
        AND L95.DATE_DEL IS NULL
        AND V604.IS_DEL = 0
        AND ((V604.LISTVAL_ID = 1807) OR (V604.LISTVAL_ID = 1808) OR (V604.LISTVAL_ID = 1809))
        INTO :X2;

        IF (:LVS  = 2) THEN S1 = '+'; ELSE S1 = '';

        IF (:INET = 2) THEN S2 = '+'; ELSE S2 = '';

        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_SPB_INF_OU_2_DTL (
    I$OBJ_ID BIGINT,
    I$IS_TEACHER SMALLINT)
RETURNS (
    NAME VARCHAR(1000),
    YYYY VARCHAR(4))
AS
BEGIN
    FOR SELECT
            (SELECT CAPTION FROM OBJECT_CAPTION_GET(L114.OBJ_ID)),
            V682.VAL
        FROM LINKS L114
        INNER JOIN LINKS L95 ON L95.OBJ_ID = L114.OBJ_ID
        INNER JOIN VALL V604 ON V604.PARAM_ID=604 AND V604.OBJ_ID=L95.PARENT_ID
        LEFT JOIN VALS V682 ON V682.PARAM_ID=682 AND V682.OBJ_ID=L114.OBJ_ID
        WHERE L114.PARENT_ID = :I$OBJ_ID
        AND L114.OBJ_TYPE_ID = 114
        AND L114.DATE_DEL IS NULL
        AND L95.PARENT_TYPE_ID = 95
        AND L95.DATE_DEL IS NULL
        AND V604.IS_DEL = 0
        AND V682.IS_DEL = 0
        AND ((:I$IS_TEACHER = 0 AND V604.LISTVAL_ID BETWEEN 1804 AND 1806)
          OR (:I$IS_TEACHER = 1 AND V604.LISTVAL_ID BETWEEN 1807 AND 1809))

        ORDER BY 1

        INTO :NAME, :YYYY
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_SPB_INF_OU_3 (
    I$OBJ_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    C1 INTEGER,
    C2 VARCHAR(4000),
    C3 INTEGER)
AS
declare variable LISTVAL_ID bigint;
declare variable DEEP smallint;
declare variable TYPE_ID bigint;
declare variable REORDER integer;
declare variable LANG_CODE varchar(2);
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :LANG_CODE;

    C1 = 0;
    DEEP = 0;

    SELECT TYPE_ID
    FROM OBJECTS
    WHERE OBJ_ID = :I$OBJ_ID
    INTO :TYPE_ID;

    IF (TYPE_ID = 2) THEN
    BEGIN
        DEEP = 0;
    END
    IF (TYPE_ID = 111) THEN
    BEGIN
        DEEP = 1;
    END
    IF (TYPE_ID = 112) THEN
    BEGIN
        DEEP = 2;
    END

    FOR
        SELECT LV.LISTVAL_ID,
               R.VAL,
               LV.SORT_ORDER
        FROM LISTVALS LV

        LEFT JOIN RES_GET(LV.RES_ID,  :LANG_CODE) R ON 1=1

        WHERE LV.LIST_ID = 154
        AND LV.LISTVAL_ID NOT IN (2068,2067)

        UNION

        SELECT LV.LISTVAL_ID,
               R.VAL,
               (LV.LISTVAL_ID - 2066)
        FROM LISTVALS LV

        LEFT JOIN RES_GET(LV.RES_ID,  :LANG_CODE) R ON 1=1

        WHERE LV.LIST_ID = 154
        AND LV.LISTVAL_ID IN (2068,2067)

        ORDER BY 2
        INTO :LISTVAL_ID,
             :C2,
             :REORDER
    DO
    BEGIN
        SELECT COUNT(*)

        FROM OBJECT_CHILDREN_GET_DEEP(:I$OBJ_ID, 2, :DEEP) O

        JOIN LINKS L23
        ON L23.PARENT_ID = O.OBJ_ID
        AND L23.OBJ_TYPE_ID = 23
        AND L23.DATE_DEL IS NULL

        JOIN LINKS L128
        ON L128.PARENT_ID = L23.OBJ_ID
        AND L128.OBJ_TYPE_ID = 128
        AND L128.DATE_DEL IS NULL

        JOIN VALL V876
        ON V876.PARAM_ID = 876
        AND L128.OBJ_ID = V876.OBJ_ID
        AND V876.LISTVAL_ID = :LISTVAL_ID
        AND V876.IS_DEL = 0

        INTO :C3;
        C1 = C1 + 1;
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_SPB_INF_OU_3_DTL (
    I$OBJ_ID BIGINT,
    I$LISTVAL_CAPTION VARCHAR(1000),
    I$USER_ID BIGINT)
RETURNS (
    NAME VARCHAR(1000),
    YYYY VARCHAR(4))
AS
DECLARE VARIABLE LISTVAL_ID BIGINT;
DECLARE VARIABLE DEEP SMALLINT;
DECLARE VARIABLE TYPE_ID BIGINT;
DECLARE VARIABLE LANG_CODE VARCHAR(2);
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :LANG_CODE;

    DEEP = 0;

    SELECT TYPE_ID
    FROM OBJECTS
    WHERE OBJ_ID = :I$OBJ_ID
    INTO :TYPE_ID;

    IF (TYPE_ID = 2) THEN
    BEGIN
        DEEP = 0;
    END
    IF (TYPE_ID = 111) THEN
    BEGIN
        DEEP = 1;
    END
    IF (TYPE_ID = 112) THEN
    BEGIN
        DEEP = 2;
    END

    SELECT FIRST 1 LV.LISTVAL_ID
    FROM LISTVALS LV

    LEFT JOIN RES_GET(LV.RES_ID,  :LANG_CODE) R ON 1=1

    WHERE LV.LIST_ID = 154
    AND R.VAL = :I$LISTVAL_CAPTION

    INTO :LISTVAL_ID;

    FOR SELECT
            (SELECT CAPTION FROM OBJECT_CAPTION_GET(L128.OBJ_ID)),
            V878.VAL

        FROM OBJECT_CHILDREN_GET_DEEP(:I$OBJ_ID, 2, :DEEP) O

        JOIN LINKS L23
        ON L23.PARENT_ID = O.OBJ_ID
        AND L23.OBJ_TYPE_ID = 23
        AND L23.DATE_DEL IS NULL

        JOIN LINKS L128
        ON L128.PARENT_ID = L23.OBJ_ID
        AND L128.OBJ_TYPE_ID = 128
        AND L128.DATE_DEL IS NULL

        JOIN VALL V876
        ON V876.PARAM_ID = 876
        AND L128.OBJ_ID = V876.OBJ_ID
        AND V876.LISTVAL_ID = :LISTVAL_ID
        AND V876.IS_DEL = 0

        LEFT JOIN VALS V878
        ON V878.PARAM_ID = 878
        AND L128.OBJ_ID = V878.OBJ_ID
        AND V878.IS_DEL = 0

        ORDER BY 1

        INTO :NAME, :YYYY
    DO
    BEGIN
        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_SPB_INF_OU_4 (
    I$OBJ_ID BIGINT)
RETURNS (
    X INTEGER,
    Y NUMERIC(9,2))
AS
DECLARE VARIABLE OU_ID BIGINT;
DECLARE VARIABLE ROOM_ID BIGINT;
DECLARE VARIABLE LISTVAL_ID BIGINT;
DECLARE VARIABLE TOTAL_ROOMS NUMERIC(9,2);
DECLARE VARIABLE TOTAL_PC NUMERIC(9,2);
DECLARE VARIABLE TOTAL_LVS NUMERIC(9,2);
DECLARE VARIABLE TOTAL_INET NUMERIC(9,2);
DECLARE VARIABLE TOTAL_PREZ NUMERIC(9,2);
DECLARE VARIABLE DEEP SMALLINT;
DECLARE VARIABLE TYPE_ID BIGINT;
BEGIN
    DEEP = 0;
    SELECT TYPE_ID FROM OBJECTS WHERE OBJ_ID = :I$OBJ_ID INTO :TYPE_ID;
    IF (TYPE_ID = 2)   THEN DEEP = 0;
    IF (TYPE_ID = 111) THEN DEEP = 1;
    IF (TYPE_ID = 112) THEN DEEP = 2;

    TOTAL_ROOMS = 0;
    TOTAL_PC    = 0;
    TOTAL_LVS   = 0;
    TOTAL_INET  = 0;
    TOTAL_PREZ  = 0;

    FOR SELECT O.OBJ_ID, L61.OBJ_ID
        FROM OBJECT_CHILDREN_GET_DEEP(:I$OBJ_ID, 2, :DEEP) O
        INNER JOIN LINKS L73 ON L73.PARENT_ID = O.OBJ_ID
        INNER JOIN LINKS L16 ON L16.PARENT_ID = L73.OBJ_ID
        INNER JOIN LINKS L61 ON L61.PARENT_ID = L16.OBJ_ID
        INNER JOIN VALL V526 ON V526.PARAM_ID = 526 AND V526.OBJ_ID = L61.OBJ_ID
        WHERE L73.OBJ_TYPE_ID = 73
              AND L73.DATE_DEL IS NULL
              AND L16.OBJ_TYPE_ID = 16
              AND L16.DATE_DEL IS NULL
              AND L61.OBJ_TYPE_ID = 61
              AND L61.DATE_DEL IS NULL
              AND V526.IS_DEL = 0
              AND ((V526.LISTVAL_ID = 25) OR (V526.LISTVAL_ID = 1126) OR (V526.LISTVAL_ID = 1127) OR (V526.LISTVAL_ID = 1128))
        INTO :OU_ID, :ROOM_ID
    DO
    BEGIN
        TOTAL_ROOMS = TOTAL_ROOMS + 1;

        FOR SELECT FIRST 1 1
            FROM LINKS L23
            INNER JOIN LINKS  L95 ON L95.PARENT_ID  = L23.OBJ_ID
            INNER JOIN VALL  V604 ON V604.PARAM_ID  = 604 AND V604.OBJ_ID = L95.OBJ_ID
            INNER JOIN LINKS L114 ON L114.PARENT_ID = L95.OBJ_ID
            INNER JOIN VALR  V679 ON V679.PARAM_ID  = 679 AND V679.OBJ_ID = L114.OBJ_ID
            WHERE L23.PARENT_ID = :OU_ID
                  AND L23.OBJ_TYPE_ID = 23
                  AND L23.DATE_DEL IS NULL
                  AND L95.OBJ_TYPE_ID = 95
                  AND L95.DATE_DEL IS NULL
                  AND L114.OBJ_TYPE_ID = 114
                  AND L114.DATE_DEL IS NULL
                  AND V604.LISTVAL_ID > 1803
                  AND V604.LISTVAL_ID < 1810
                  AND V604.IS_DEL = 0
                  AND V679.VAL    = :ROOM_ID
                  AND V679.IS_DEL = 0
            INTO :X
        DO
        BEGIN
            TOTAL_PC = TOTAL_PC + X;
        END

        FOR SELECT FIRST 1 1, V697.LISTVAL_ID
            FROM LINKS L116
            INNER JOIN LINKS L117 ON L117.PARENT_ID = L116.OBJ_ID
            INNER JOIN VALR  V703 ON V703.PARAM_ID = 703 AND V703.OBJ_ID = L117.OBJ_ID
            LEFT  JOIN VALL  V697 ON V697.PARAM_ID = 697 AND V697.OBJ_ID = L116.OBJ_ID AND V697.IS_DEL = 0
            WHERE L116.PARENT_ID = :OU_ID
                  AND L116.OBJ_TYPE_ID = 116
                  AND L116.DATE_DEL IS NULL
                  AND L117.OBJ_TYPE_ID = 117
                  AND L117.DATE_DEL IS NULL
                  AND V703.VAL = :ROOM_ID
                  AND V703.IS_DEL = 0
            INTO :X, :LISTVAL_ID
        DO
        BEGIN
            TOTAL_LVS = TOTAL_LVS + X;
            IF (LISTVAL_ID = 2) THEN TOTAL_INET = TOTAL_INET + 1;
        END

        FOR SELECT FIRST 1 1
            FROM LINKS L23
            INNER JOIN LINKS L128 ON L128.PARENT_ID = L23.OBJ_ID
            INNER JOIN VALR  V879 ON V879.PARAM_ID = 879 AND V879.OBJ_ID = L128.OBJ_ID
            INNER JOIN VALL  V876 ON V876.PARAM_ID = 876 AND V876.OBJ_ID = L128.OBJ_ID
            WHERE L23.PARENT_ID = :OU_ID
                  AND L23.OBJ_TYPE_ID = 23
                  AND L23.DATE_DEL IS NULL
                  AND L128.OBJ_TYPE_ID = 128
                  AND L128.DATE_DEL IS NULL
                  AND V879.VAL = :ROOM_ID
                  AND V879.IS_DEL = 0
                  AND V876.LISTVAL_ID = 2079
                  AND V876.IS_DEL = 0
            INTO :X
        DO
        BEGIN
            TOTAL_PREZ = TOTAL_PREZ + X;
        END


    END

    X = TOTAL_ROOMS;
    Y = NULL;
    SUSPEND;

    IF (X = 0) THEN EXIT;


    X = TOTAL_PC;
    Y = TOTAL_PC * 100 / TOTAL_ROOMS;
    SUSPEND;
    X = TOTAL_LVS;
    Y = TOTAL_LVS * 100 / TOTAL_ROOMS;
    SUSPEND;
    X = TOTAL_INET;
    Y = TOTAL_INET * 100 / TOTAL_ROOMS;
    SUSPEND;
    X = TOTAL_PREZ;
    Y = TOTAL_PREZ * 100 / TOTAL_ROOMS;
    SUSPEND;

END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_SPB_INF_OU_41 (
    I$OBJ_ID BIGINT)
RETURNS (
    X INTEGER)
AS
DECLARE VARIABLE OU_ID BIGINT;
DECLARE VARIABLE ROOM_ID BIGINT;
DECLARE VARIABLE LISTVAL_ID BIGINT;
DECLARE VARIABLE PC1 INTEGER;
DECLARE VARIABLE PC2 INTEGER;
DECLARE VARIABLE DEEP SMALLINT;
DECLARE VARIABLE TYPE_ID BIGINT;
BEGIN
    DEEP = 0;
    SELECT TYPE_ID FROM OBJECTS WHERE OBJ_ID = :I$OBJ_ID INTO :TYPE_ID;
    IF (TYPE_ID = 2)   THEN DEEP = 0;
    IF (TYPE_ID = 111) THEN DEEP = 1;
    IF (TYPE_ID = 112) THEN DEEP = 2;

    PC1 = 0;
    PC2 = 0;

    FOR SELECT O.OBJ_ID, L61.OBJ_ID
        FROM OBJECT_CHILDREN_GET_DEEP(:I$OBJ_ID, 2, :DEEP) O
        INNER JOIN LINKS L73 ON L73.PARENT_ID = O.OBJ_ID
        INNER JOIN LINKS L16 ON L16.PARENT_ID = L73.OBJ_ID
        INNER JOIN LINKS L61 ON L61.PARENT_ID = L16.OBJ_ID
        INNER JOIN VALL V526 ON V526.PARAM_ID = 526 AND V526.OBJ_ID = L61.OBJ_ID
        WHERE L73.OBJ_TYPE_ID = 73
              AND L73.DATE_DEL IS NULL
              AND L16.OBJ_TYPE_ID = 16
              AND L16.DATE_DEL IS NULL
              AND L61.OBJ_TYPE_ID = 61
              AND L61.DATE_DEL IS NULL
              AND V526.IS_DEL = 0
              AND ((V526.LISTVAL_ID = 1140) OR (V526.LISTVAL_ID = 1141) OR (V526.LISTVAL_ID = 1142))
        INTO :OU_ID, :ROOM_ID
    DO
    BEGIN

        FOR SELECT V604.LISTVAL_ID
            FROM LINKS L23
            INNER JOIN LINKS  L95 ON L95.PARENT_ID  = L23.OBJ_ID
            INNER JOIN VALL  V604 ON V604.PARAM_ID  = 604 AND V604.OBJ_ID = L95.OBJ_ID
            INNER JOIN LINKS L114 ON L114.PARENT_ID = L95.OBJ_ID
            INNER JOIN VALR  V679 ON V679.PARAM_ID  = 679 AND V679.OBJ_ID = L114.OBJ_ID
            WHERE L23.PARENT_ID = :OU_ID
                  AND L23.OBJ_TYPE_ID = 23
                  AND L23.DATE_DEL IS NULL
                  AND L95.OBJ_TYPE_ID = 95
                  AND L95.DATE_DEL IS NULL
                  AND L114.OBJ_TYPE_ID = 114
                  AND L114.DATE_DEL IS NULL
                  AND V604.LISTVAL_ID > 1803
                  AND V604.LISTVAL_ID < 1810
                  AND V604.IS_DEL = 0
                  AND V679.VAL    = :ROOM_ID
                  AND V679.IS_DEL = 0
            INTO :LISTVAL_ID
        DO
        BEGIN
            PC1 = PC1 + 1;
            IF ((LISTVAL_ID > 1803) AND (LISTVAL_ID < 1807)) THEN PC2 = PC2 + 1;
        END

    END

    X = PC1;
    SUSPEND;
    X = PC2;
    SUSPEND;

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_SPB_INF_OU_41_DTL (
    I$OBJ_ID BIGINT,
    I$ROW SMALLINT)
RETURNS (
    NAME VARCHAR(1000))
AS
DECLARE VARIABLE OU_ID BIGINT;
DECLARE VARIABLE ROOM_ID BIGINT;
DECLARE VARIABLE DEEP SMALLINT;
DECLARE VARIABLE TYPE_ID BIGINT;
BEGIN
    DEEP = 0;
    SELECT TYPE_ID FROM OBJECTS WHERE OBJ_ID = :I$OBJ_ID INTO :TYPE_ID;
    IF (TYPE_ID = 2)   THEN DEEP = 0;
    IF (TYPE_ID = 111) THEN DEEP = 1;
    IF (TYPE_ID = 112) THEN DEEP = 2;

    FOR SELECT O.OBJ_ID, L61.OBJ_ID
        FROM OBJECT_CHILDREN_GET_DEEP(:I$OBJ_ID, 2, :DEEP) O
        INNER JOIN LINKS L73 ON L73.PARENT_ID = O.OBJ_ID
        INNER JOIN LINKS L16 ON L16.PARENT_ID = L73.OBJ_ID
        INNER JOIN LINKS L61 ON L61.PARENT_ID = L16.OBJ_ID
        INNER JOIN VALL V526 ON V526.PARAM_ID = 526 AND V526.OBJ_ID = L61.OBJ_ID
        WHERE L73.OBJ_TYPE_ID = 73
              AND L73.DATE_DEL IS NULL
              AND L16.OBJ_TYPE_ID = 16
              AND L16.DATE_DEL IS NULL
              AND L61.OBJ_TYPE_ID = 61
              AND L61.DATE_DEL IS NULL
              AND V526.IS_DEL = 0
              AND ((V526.LISTVAL_ID = 1140) OR (V526.LISTVAL_ID = 1141) OR (V526.LISTVAL_ID = 1142))
        INTO :OU_ID, :ROOM_ID
    DO
    BEGIN
        FOR SELECT (SELECT CAPTION FROM OBJECT_CAPTION_GET(L114.OBJ_ID))
            FROM LINKS L23
            INNER JOIN LINKS  L95 ON L95.PARENT_ID  = L23.OBJ_ID
            INNER JOIN VALL  V604 ON V604.PARAM_ID  = 604 AND V604.OBJ_ID = L95.OBJ_ID
            INNER JOIN LINKS L114 ON L114.PARENT_ID = L95.OBJ_ID
            INNER JOIN VALR  V679 ON V679.PARAM_ID  = 679 AND V679.OBJ_ID = L114.OBJ_ID
            WHERE L23.PARENT_ID = :OU_ID
                  AND L23.OBJ_TYPE_ID = 23
                  AND L23.DATE_DEL IS NULL
                  AND L95.OBJ_TYPE_ID = 95
                  AND L95.DATE_DEL IS NULL
                  AND L114.OBJ_TYPE_ID = 114
                  AND L114.DATE_DEL IS NULL
                  AND V604.LISTVAL_ID > 1803
                  AND V604.LISTVAL_ID < IIF(:I$ROW = 0, 1810, 1807)
                  AND V604.IS_DEL = 0
                  AND V679.VAL    = :ROOM_ID
                  AND V679.IS_DEL = 0
            INTO :NAME
        DO
        BEGIN
            SUSPEND;
        END

    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_SPB_INF_OU_4_DTL (
    I$OBJ_ID BIGINT,
    I$ROW SMALLINT)
RETURNS (
    NAME VARCHAR(1000))
AS
DECLARE VARIABLE DEEP SMALLINT;
DECLARE VARIABLE TYPE_ID BIGINT;
BEGIN
    DEEP = 0;
    SELECT TYPE_ID FROM OBJECTS WHERE OBJ_ID = :I$OBJ_ID INTO :TYPE_ID;
    IF (TYPE_ID = 2)   THEN DEEP = 0;
    IF (TYPE_ID = 111) THEN DEEP = 1;
    IF (TYPE_ID = 112) THEN DEEP = 2;

    FOR SELECT (SELECT CAPTION FROM OBJECT_CAPTION_GET(L61.OBJ_ID))
        FROM OBJECT_CHILDREN_GET_DEEP(:I$OBJ_ID, 2, :DEEP) O
        INNER JOIN LINKS L73 ON L73.PARENT_ID = O.OBJ_ID
        INNER JOIN LINKS L16 ON L16.PARENT_ID = L73.OBJ_ID
        INNER JOIN LINKS L61 ON L61.PARENT_ID = L16.OBJ_ID
        INNER JOIN VALL V526 ON V526.PARAM_ID = 526 AND V526.OBJ_ID = L61.OBJ_ID
        WHERE L73.OBJ_TYPE_ID = 73
              AND L73.DATE_DEL IS NULL
              AND L16.OBJ_TYPE_ID = 16
              AND L16.DATE_DEL IS NULL
              AND L61.OBJ_TYPE_ID = 61
              AND L61.DATE_DEL IS NULL
              AND V526.IS_DEL = 0
              AND ((V526.LISTVAL_ID = 25) OR (V526.LISTVAL_ID = 1126) OR (V526.LISTVAL_ID = 1127) OR (V526.LISTVAL_ID = 1128))
              AND (:I$ROW = 0
                OR (:I$ROW = 1 AND EXISTS(
                    SELECT FIRST 1 1
                    FROM LINKS L23
                    INNER JOIN LINKS  L95 ON L95.PARENT_ID  = L23.OBJ_ID
                    INNER JOIN VALL  V604 ON V604.PARAM_ID  = 604 AND V604.OBJ_ID = L95.OBJ_ID
                    INNER JOIN LINKS L114 ON L114.PARENT_ID = L95.OBJ_ID
                    INNER JOIN VALR  V679 ON V679.PARAM_ID  = 679 AND V679.OBJ_ID = L114.OBJ_ID
                    WHERE L23.PARENT_ID = O.OBJ_ID
                          AND L23.OBJ_TYPE_ID = 23
                          AND L23.DATE_DEL IS NULL
                          AND L95.OBJ_TYPE_ID = 95
                          AND L95.DATE_DEL IS NULL
                          AND L114.OBJ_TYPE_ID = 114
                          AND L114.DATE_DEL IS NULL
                          AND V604.LISTVAL_ID > 1803
                          AND V604.LISTVAL_ID < 1810
                          AND V604.IS_DEL = 0
                          AND V679.VAL    = L61.OBJ_ID
                          AND V679.IS_DEL = 0))
                OR (:I$ROW IN (2, 3) AND EXISTS(
                    SELECT FIRST 1 1, V697.LISTVAL_ID
                    FROM LINKS L116
                    INNER JOIN LINKS L117 ON L117.PARENT_ID = L116.OBJ_ID
                    INNER JOIN VALR  V703 ON V703.PARAM_ID = 703 AND V703.OBJ_ID = L117.OBJ_ID
                    LEFT  JOIN VALL  V697 ON V697.PARAM_ID = 697 AND V697.OBJ_ID = L116.OBJ_ID AND V697.IS_DEL = 0
                    WHERE L116.PARENT_ID = O.OBJ_ID
                          AND L116.OBJ_TYPE_ID = 116
                          AND L116.DATE_DEL IS NULL
                          AND L117.OBJ_TYPE_ID = 117
                          AND L117.DATE_DEL IS NULL
                          AND V703.VAL = L61.OBJ_ID
                          AND V703.IS_DEL = 0
                          AND (:I$ROW = 3 OR V697.LISTVAL_ID = 2)))
                OR (:I$ROW = 4 AND EXISTS(
                    SELECT FIRST 1 1
                    FROM LINKS L23
                    INNER JOIN LINKS L128 ON L128.PARENT_ID = L23.OBJ_ID
                    INNER JOIN VALR  V879 ON V879.PARAM_ID = 879 AND V879.OBJ_ID = L128.OBJ_ID
                    INNER JOIN VALL  V876 ON V876.PARAM_ID = 876 AND V876.OBJ_ID = L128.OBJ_ID
                    WHERE L23.PARENT_ID = O.OBJ_ID
                          AND L23.OBJ_TYPE_ID = 23
                          AND L23.DATE_DEL IS NULL
                          AND L128.OBJ_TYPE_ID = 128
                          AND L128.DATE_DEL IS NULL
                          AND V879.VAL = L61.OBJ_ID
                          AND V879.IS_DEL = 0
                          AND V876.LISTVAL_ID = 2079
                          AND V876.IS_DEL = 0))
              )
        INTO :NAME
    DO
    BEGIN
        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_SPB_INF_OU_5 (
    I$OBJ_ID BIGINT)
RETURNS (
    Y NUMERIC(9,2))
AS
DECLARE VARIABLE OU_ID BIGINT;
DECLARE VARIABLE ROOM_ID BIGINT;
DECLARE VARIABLE LISTVAL_ID BIGINT;
DECLARE VARIABLE TOTAL_PC        NUMERIC(9,2);
DECLARE VARIABLE TOTAL_PC_LVS    NUMERIC(9,2);
DECLARE VARIABLE TOTAL_PC_INET   NUMERIC(9,2);
DECLARE VARIABLE TOTAL_ROOMS     NUMERIC(9,2);
DECLARE VARIABLE TOTAL_ROOM_LVS  NUMERIC(9,2);
DECLARE VARIABLE TOTAL_ROOM_INET NUMERIC(9,2);
DECLARE VARIABLE TOTAL_LVS       NUMERIC(9,2);
DECLARE VARIABLE TOTAL_LVS_SRV   NUMERIC(9,2);
DECLARE VARIABLE DEEP SMALLINT;
DECLARE VARIABLE TYPE_ID BIGINT;
BEGIN
    DEEP = 0;
    SELECT TYPE_ID FROM OBJECTS WHERE OBJ_ID = :I$OBJ_ID INTO :TYPE_ID;
    IF (TYPE_ID = 2)   THEN DEEP = 0;
    IF (TYPE_ID = 111) THEN DEEP = 1;
    IF (TYPE_ID = 112) THEN DEEP = 2;


    TOTAL_PC = 0;
    TOTAL_PC_LVS    = 0;
    TOTAL_PC_INET   = 0;

    TOTAL_ROOMS = 0;
    TOTAL_ROOM_LVS   = 0;
    TOTAL_ROOM_INET  = 0;

    TOTAL_LVS        = 0;
    TOTAL_LVS_SRV    = 0;


    FOR SELECT O.OBJ_ID, V679.VAL
        FROM OBJECT_CHILDREN_GET_DEEP(:I$OBJ_ID, 2, :DEEP) O
        INNER JOIN LINKS L23 ON L23.PARENT_ID = O.OBJ_ID
        INNER JOIN LINKS  L95 ON L95.PARENT_ID  = L23.OBJ_ID
        INNER JOIN VALL  V626 ON V626.PARAM_ID  = 626 AND V626.OBJ_ID = L95.OBJ_ID
        INNER JOIN LINKS L114 ON L114.PARENT_ID = L95.OBJ_ID
        INNER JOIN VALR  V679 ON V679.PARAM_ID  = 679 AND V679.OBJ_ID = L114.OBJ_ID
        WHERE L23.OBJ_TYPE_ID = 23
          AND L23.DATE_DEL IS NULL
          AND L95.OBJ_TYPE_ID = 95
          AND L95.DATE_DEL IS NULL
          AND L114.OBJ_TYPE_ID = 114
          AND L114.DATE_DEL IS NULL
          AND V626.LISTVAL_ID = 1799
          AND V626.IS_DEL = 0
          AND V679.IS_DEL = 0
        INTO :OU_ID, :ROOM_ID
    DO
    BEGIN
        TOTAL_PC = TOTAL_PC + 1;

        FOR SELECT FIRST 1 V697.LISTVAL_ID
            FROM LINKS L116
            INNER JOIN LINKS L117 ON L117.PARENT_ID = L116.OBJ_ID
            INNER JOIN VALR  V703 ON V703.PARAM_ID = 703 AND V703.OBJ_ID = L117.OBJ_ID
            LEFT  JOIN VALL  V697 ON V697.PARAM_ID = 697 AND V697.OBJ_ID = L116.OBJ_ID AND V697.IS_DEL = 0
            WHERE L116.PARENT_ID = :OU_ID
                  AND L116.OBJ_TYPE_ID = 116
                  AND L116.DATE_DEL IS NULL
                  AND L117.OBJ_TYPE_ID = 117
                  AND L117.DATE_DEL IS NULL
                  AND V703.VAL = :ROOM_ID
                  AND V703.IS_DEL = 0
            INTO :LISTVAL_ID
        DO
        BEGIN
            TOTAL_PC_LVS = TOTAL_PC_LVS + 1;
            IF (LISTVAL_ID = 2) THEN TOTAL_PC_INET = TOTAL_PC_INET + 1;
        END

    END

    Y = 0;
    IF (TOTAL_PC > 0) THEN Y = TOTAL_PC_LVS * 100 / TOTAL_PC;
    SUSPEND;       /* PC WITH LVS */
    Y = 0;
    IF (TOTAL_PC > 0) THEN Y = TOTAL_PC_INET * 100 / TOTAL_PC;
    SUSPEND;       /* PC WITH INET */

    FOR SELECT O.OBJ_ID, L61.OBJ_ID
        FROM OBJECT_CHILDREN_GET_DEEP(:I$OBJ_ID, 2, :DEEP) O
        INNER JOIN LINKS L73 ON L73.PARENT_ID = O.OBJ_ID
        INNER JOIN LINKS L16 ON L16.PARENT_ID = L73.OBJ_ID
        INNER JOIN LINKS L61 ON L61.PARENT_ID = L16.OBJ_ID
        INNER JOIN VALL V526 ON V526.PARAM_ID = 526 AND V526.OBJ_ID = L61.OBJ_ID
        WHERE L73.OBJ_TYPE_ID = 73
              AND L73.DATE_DEL IS NULL
              AND L16.OBJ_TYPE_ID = 16
              AND L16.DATE_DEL IS NULL
              AND L61.OBJ_TYPE_ID = 61
              AND L61.DATE_DEL IS NULL
              AND V526.IS_DEL = 0
              AND ((V526.LISTVAL_ID = 25) OR (V526.LISTVAL_ID = 1126) OR (V526.LISTVAL_ID = 1127) OR (V526.LISTVAL_ID = 1128))
        INTO :OU_ID, :ROOM_ID
    DO
    BEGIN
        TOTAL_ROOMS = TOTAL_ROOMS + 1;

        FOR SELECT FIRST 1 V697.LISTVAL_ID
            FROM LINKS L116
            INNER JOIN LINKS L117 ON L117.PARENT_ID = L116.OBJ_ID
            INNER JOIN VALR  V703 ON V703.PARAM_ID = 703 AND V703.OBJ_ID = L117.OBJ_ID
            LEFT  JOIN VALL  V697 ON V697.PARAM_ID = 697 AND V697.OBJ_ID = L116.OBJ_ID AND V697.IS_DEL = 0
            WHERE L116.PARENT_ID = :OU_ID
                  AND L116.OBJ_TYPE_ID = 116
                  AND L116.DATE_DEL IS NULL
                  AND L117.OBJ_TYPE_ID = 117
                  AND L117.DATE_DEL IS NULL
                  AND V703.VAL = :ROOM_ID
                  AND V703.IS_DEL = 0
            INTO :LISTVAL_ID
        DO
        BEGIN
            TOTAL_ROOM_LVS = TOTAL_ROOM_LVS + 1;
            IF (LISTVAL_ID = 2) THEN TOTAL_ROOM_INET = TOTAL_ROOM_INET + 1;
        END
    END

    Y = 0;
    IF (TOTAL_ROOMS > 0) THEN Y = TOTAL_ROOM_LVS * 100 / TOTAL_ROOMS;
    SUSPEND;       /* ROOMS WITH LVS */
    Y = 0;
    IF (TOTAL_ROOMS > 0) THEN Y = TOTAL_ROOM_INET * 100 / TOTAL_ROOMS;
    SUSPEND;       /* ROOMS WITH INET */

    FOR SELECT O.OBJ_ID, L61.OBJ_ID
        FROM OBJECT_CHILDREN_GET_DEEP(:I$OBJ_ID, 2, :DEEP) O
        INNER JOIN LINKS L73 ON L73.PARENT_ID = O.OBJ_ID
        INNER JOIN LINKS L16 ON L16.PARENT_ID = L73.OBJ_ID
        INNER JOIN LINKS L61 ON L61.PARENT_ID = L16.OBJ_ID
        INNER JOIN VALL V526 ON V526.PARAM_ID = 526 AND V526.OBJ_ID = L61.OBJ_ID
        WHERE L73.OBJ_TYPE_ID = 73
              AND L73.DATE_DEL IS NULL
              AND L16.OBJ_TYPE_ID = 16
              AND L16.DATE_DEL IS NULL
              AND L61.OBJ_TYPE_ID = 61
              AND L61.DATE_DEL IS NULL
              AND V526.IS_DEL = 0
              AND V526.LISTVAL_ID > 1182
              AND V526.LISTVAL_ID < 1189
        INTO :OU_ID, :ROOM_ID
    DO
    BEGIN
        TOTAL_ROOMS = TOTAL_ROOMS + 1;

        FOR SELECT FIRST 1 1
            FROM LINKS L116
            INNER JOIN LINKS L117 ON L117.PARENT_ID = L116.OBJ_ID
            INNER JOIN VALR  V703 ON V703.PARAM_ID = 703 AND V703.OBJ_ID = L117.OBJ_ID
            WHERE L116.PARENT_ID = :OU_ID
                  AND L116.OBJ_TYPE_ID = 116
                  AND L116.DATE_DEL IS NULL
                  AND L117.OBJ_TYPE_ID = 117
                  AND L117.DATE_DEL IS NULL
                  AND V703.VAL = :ROOM_ID
                  AND V703.IS_DEL = 0
            INTO :LISTVAL_ID
        DO
        BEGIN
            TOTAL_ROOM_LVS = TOTAL_ROOM_LVS + 1;
        END
    END

    Y = 0;
    IF (TOTAL_ROOMS > 0) THEN Y = TOTAL_ROOM_LVS * 100 / TOTAL_ROOMS;
    SUSPEND;       /* ADM ROOMS WITH LVS */


    FOR SELECT V882.LISTVAL_ID
        FROM OBJECT_CHILDREN_GET_DEEP(:I$OBJ_ID, 2, :DEEP) O
        INNER JOIN LINKS L116 ON L116.PARENT_ID = O.OBJ_ID
        LEFT  JOIN VALL  V882 ON V882.PARAM_ID  = 882 AND V882.OBJ_ID = L116.OBJ_ID AND V882.IS_DEL = 0
        WHERE L116.OBJ_TYPE_ID = 116
          AND L116.DATE_DEL IS NULL
        INTO :LISTVAL_ID
    DO
    BEGIN
        TOTAL_LVS = TOTAL_LVS + 1;
        IF (LISTVAL_ID = 2) THEN TOTAL_LVS_SRV = TOTAL_LVS_SRV + 1;
    END

    Y = 0;
    IF (TOTAL_LVS > 0) THEN Y = TOTAL_LVS_SRV * 100 / TOTAL_LVS;
    SUSPEND;       /* ROOMS WITH LVS */



END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_SPB_INF_OU_6 (
    I$OBJ_ID BIGINT)
RETURNS (
    V VARCHAR(100))
AS
declare variable PUPIL_COUNT numeric(9,2);
declare variable OBJ_ID bigint;
declare variable DEEP smallint;
declare variable TYPE_ID bigint;
declare variable C numeric(9,2);
BEGIN
    DEEP = 0;
    SELECT TYPE_ID FROM OBJECTS WHERE OBJ_ID = :I$OBJ_ID INTO :TYPE_ID;
    IF (TYPE_ID = 2)   THEN DEEP = 0;
    IF (TYPE_ID = 111) THEN DEEP = 1;
    IF (TYPE_ID = 112) THEN DEEP = 2;

    C = 0;
    SELECT COUNT(*)
    FROM OBJECT_CHILDREN_GET_DEEP(:I$OBJ_ID, 2, :DEEP) O
    INNER JOIN VALS V36 ON V36.PARAM_ID = 36 AND V36.OBJ_ID = O.OBJ_ID
    WHERE V36.IS_DEL = 0
    AND V36.VAL IS NOT NULL
    INTO :C;

    IF (C > 0) THEN V = 'Да'; ELSE V = 'Нет';
    SUSPEND;/*1*/


    C = 0;
    SELECT COUNT(*)
    FROM OBJECT_CHILDREN_GET_DEEP(:I$OBJ_ID, 2, :DEEP) O
    INNER JOIN VALS V712 ON V712.PARAM_ID = 712 AND V712.OBJ_ID = O.OBJ_ID
    WHERE V712.IS_DEL = 0
    AND V712.VAL IS NOT NULL
    INTO :C;

    IF (C > 0) THEN V = 'Да'; ELSE V = 'Нет';
    SUSPEND;  /*2*/

    C = 0;
    SELECT COUNT(*)
    FROM OBJECT_CHILDREN_GET_DEEP(:I$OBJ_ID, 2, :DEEP) O
    INNER JOIN VALS V711 ON V711.PARAM_ID = 711 AND V711.OBJ_ID = O.OBJ_ID
    WHERE V711.IS_DEL = 0
    AND V711.VAL IS NOT NULL
    INTO :C;

    IF (C > 0) THEN V = 'Да'; ELSE V = 'Нет';
    SUSPEND;   /*3*/

    C = 0;
    SELECT COUNT(*)
    FROM OBJECT_CHILDREN_GET_DEEP(:I$OBJ_ID, 2, :DEEP) O
    INNER JOIN VALI V719 ON V719.PARAM_ID = 719 AND V719.OBJ_ID = O.OBJ_ID
    WHERE V719.IS_DEL = 0
    AND V719.VAL > 0
    INTO :C;

    IF (C > 0) THEN V = 'Да'; ELSE V = 'Нет';
    SUSPEND;  /*4*/

    PUPIL_COUNT = 0;
    FOR SELECT O.OBJ_ID
        FROM OBJECT_CHILDREN_GET_DEEP(:I$OBJ_ID, 2, :DEEP) O
        INTO :OBJ_ID
    DO
    BEGIN
        SELECT :PUPIL_COUNT + CAST(VAL AS INTEGER)
        FROM DO_FUNC(:OBJ_ID, 661, 6)
        INTO :PUPIL_COUNT;
    END

    SELECT SUM(V716.VAL)
    FROM OBJECT_CHILDREN_GET_DEEP(:I$OBJ_ID, 2, :DEEP) O
    INNER JOIN VALI V716 ON V716.PARAM_ID = 716 AND V716.OBJ_ID = O.OBJ_ID
    WHERE V716.IS_DEL = 0
    AND (V716.VAL IS NOT NULL)
    INTO :C;

    C = C * 100 / :PUPIL_COUNT;
    V = C;
    V = COALESCE(V, '0');
    SUSPEND;    /*5*/


    SELECT SUM(V717.VAL)
    FROM OBJECT_CHILDREN_GET_DEEP(:I$OBJ_ID, 2, :DEEP) O
    INNER JOIN VALI V717 ON V717.PARAM_ID = 717 AND V717.OBJ_ID = O.OBJ_ID
    WHERE V717.IS_DEL = 0
    AND V717.VAL IS NOT NULL
    INTO :C;

    SELECT COUNT(*)
    FROM OBJECT_CHILDREN_GET_DEEP(:I$OBJ_ID, 2, :DEEP) O
    INNER JOIN LINKS L7 ON L7.PARENT_ID = O.OBJ_ID
    INNER JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID
    INNER JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID
    WHERE L7.PARENT_ID = O.OBJ_ID
    AND L7.OBJ_TYPE_ID = 7
    AND L7.DATE_DEL IS NULL
    AND L8.OBJ_TYPE_ID = 8
    AND L8.DATE_DEL IS NULL
    AND L9.OBJ_TYPE_ID = 9
    AND L9.DATE_DEL IS NULL
    INTO :PUPIL_COUNT;

    C = C * 100 / :PUPIL_COUNT;
    V = C;
    V = COALESCE(V, '0');
    SUSPEND;  /*6*/

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_SPB_INF_OU_7 (
    I$OBJ_ID BIGINT)
RETURNS (
    C NUMERIC(9,2))
AS
DECLARE VARIABLE DEEP SMALLINT;
DECLARE VARIABLE TYPE_ID BIGINT;
BEGIN
    DEEP = 0;
    SELECT TYPE_ID FROM OBJECTS WHERE OBJ_ID = :I$OBJ_ID INTO :TYPE_ID;
    IF (TYPE_ID = 2)   THEN DEEP = 0;
    IF (TYPE_ID = 111) THEN DEEP = 1;
    IF (TYPE_ID = 112) THEN DEEP = 2;

    C = 0;
    SELECT SUM(V721.VAL)
    FROM OBJECT_CHILDREN_GET_DEEP(:I$OBJ_ID, 2, :DEEP) O
    INNER JOIN VALI V721 ON  V721.OBJ_ID = O.OBJ_ID
    WHERE V721.IS_DEL = 0
    AND V721.VAL IS NOT NULL
    AND V721.PARAM_ID = 721
    INTO :C;
    SUSPEND;/*1*/

    C = 0;
    SELECT AVG(V722.VAL)
    FROM OBJECT_CHILDREN_GET_DEEP(:I$OBJ_ID, 2, :DEEP) O
    INNER JOIN VALF V722 ON  V722.OBJ_ID = O.OBJ_ID
    WHERE V722.IS_DEL = 0
    AND V722.VAL IS NOT NULL
    AND V722.PARAM_ID = 722
    INTO :C;
    SUSPEND;/*2*/

    C = 0;
    SELECT SUM(V723.VAL)
    FROM OBJECT_CHILDREN_GET_DEEP(:I$OBJ_ID, 2, :DEEP) O
    INNER JOIN VALI V723 ON  V723.OBJ_ID = O.OBJ_ID
    WHERE V723.IS_DEL = 0
    AND V723.VAL IS NOT NULL
    AND V723.PARAM_ID = 723
    INTO :C;
    SUSPEND;/*3*/


END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_SPB_INF_OU_8 (
    I$OBJ_ID BIGINT)
RETURNS (
    C NUMERIC(9,2))
AS
DECLARE VARIABLE OU_ID BIGINT;
DECLARE VARIABLE ROOM_ID BIGINT;
DECLARE VARIABLE D DOUBLE PRECISION;
DECLARE VARIABLE DEEP SMALLINT;
DECLARE VARIABLE TYPE_ID BIGINT;
DECLARE VARIABLE OU_COUNT NUMERIC(9,2);
DECLARE VARIABLE TEACHERS_COUNT NUMERIC(9,2);
DECLARE VARIABLE PC_COUNT NUMERIC(9,2);
DECLARE VARIABLE LVS_PC_COUNT NUMERIC(9,2);
BEGIN
    DEEP = 0;
    SELECT TYPE_ID FROM OBJECTS WHERE OBJ_ID = :I$OBJ_ID INTO :TYPE_ID;
    IF (TYPE_ID = 2)   THEN DEEP = 0;
    IF (TYPE_ID = 111) THEN DEEP = 1;
    IF (TYPE_ID = 112) THEN DEEP = 2;

    SELECT COUNT(*)
    FROM OBJECT_CHILDREN_GET_DEEP(:I$OBJ_ID, 2, :DEEP) O
    INTO :OU_COUNT;

    TEACHERS_COUNT = 0;

    SELECT SUM(V62.VAL)
    FROM OBJECT_CHILDREN_GET_DEEP(:I$OBJ_ID, 2, :DEEP) O
    INNER JOIN LINKS L13 ON L13.PARENT_ID = O.OBJ_ID
    INNER JOIN VALL  V63 ON V63.PARAM_ID  = 63 AND V63.OBJ_ID = L13.OBJ_ID
    INNER JOIN VALF  V62 ON V62.PARAM_ID  = 62 AND V62.OBJ_ID = L13.OBJ_ID
    WHERE L13.OBJ_TYPE_ID = 13
      AND L13.DATE_DEL IS NULL
      AND V63.IS_DEL = 0
      AND V63.LISTVAL_ID = 55
      AND V62.IS_DEL = 0
    INTO :TEACHERS_COUNT;        /*Ctavok*/

    IF (TEACHERS_COUNT = 0) THEN EXIT;

    PC_COUNT = 0;
    LVS_PC_COUNT = 0;

    FOR SELECT O.OBJ_ID, V679.VAL
        FROM OBJECT_CHILDREN_GET_DEEP(:I$OBJ_ID, 2, :DEEP) O
        INNER JOIN LINKS  L23 ON  L23.PARENT_ID = O.OBJ_ID
        INNER JOIN LINKS  L95 ON  L95.PARENT_ID = L23.OBJ_ID
        INNER JOIN LINKS L114 ON L114.PARENT_ID = L95.OBJ_ID
        INNER JOIN VALL  V604 ON V604.PARAM_ID  = 604 AND V604.OBJ_ID = L95.OBJ_ID
        LEFT  JOIN VALR  V679 ON V679.PARAM_ID  = 679 AND V679.OBJ_ID = L114.OBJ_ID AND V679.IS_DEL = 0
        WHERE L23.OBJ_TYPE_ID = 23
          AND L23.DATE_DEL IS NULL
          AND L95.OBJ_TYPE_ID = 95
          AND L95.DATE_DEL IS NULL
          AND L114.OBJ_TYPE_ID = 114
          AND L114.DATE_DEL IS NULL
          AND V604.IS_DEL = 0
          AND V604.LISTVAL_ID > 1799
          AND V604.LISTVAL_ID < 1803
        INTO :OU_ID, :ROOM_ID
    DO
    BEGIN
        PC_COUNT = PC_COUNT + 1;

        SELECT :LVS_PC_COUNT + COUNT(*)
        FROM LINKS L116
        INNER JOIN LINKS L117 ON L117.PARENT_ID = L116.OBJ_ID
        INNER JOIN VALR  V703 ON V703.PARAM_ID = 703 AND V703.OBJ_ID = L117.OBJ_ID
        LEFT  JOIN VALL  V697 ON V697.PARAM_ID = 697 AND V697.OBJ_ID = L116.OBJ_ID AND V697.IS_DEL = 0
        WHERE L116.PARENT_ID = :OU_ID
          AND L116.OBJ_TYPE_ID = 116
          AND L116.DATE_DEL IS NULL
          AND L117.OBJ_TYPE_ID = 117
          AND L117.DATE_DEL IS NULL
          AND V703.VAL = :ROOM_ID
          AND V703.IS_DEL = 0
        INTO :LVS_PC_COUNT;

    END

    C = PC_COUNT / TEACHERS_COUNT;
    SUSPEND;  /*1*/


    C = LVS_PC_COUNT * 100 / PC_COUNT;
    SUSPEND;  /*2*/

    C = 100;
    SUSPEND;  /*3*/
    SUSPEND;  /*4*/

    D = 0;
    SELECT SUM(V726.VAL)
    FROM OBJECT_CHILDREN_GET_DEEP(:I$OBJ_ID, 2, :DEEP) O
    INNER JOIN VALF V726 ON V726.PARAM_ID = 726 AND V726.OBJ_ID = O.OBJ_ID
    WHERE V726.IS_DEL = 0
    INTO :D;
    C = D / OU_COUNT;
    SUSPEND;  /*5*/

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_SPB_INF_OU_9 (
    I$OBJ_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    C NUMERIC(9,2))
AS
declare variable PUPIL_COUNT numeric(9,2);
declare variable OBJ_ID bigint;
declare variable DEEP smallint;
declare variable TYPE_ID bigint;
declare variable LANG_CODE varchar(2);
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :LANG_CODE;

    DEEP = 0;
    SELECT TYPE_ID FROM OBJECTS WHERE OBJ_ID = :I$OBJ_ID INTO :TYPE_ID;
    IF (TYPE_ID = 2)   THEN DEEP = 0;
    IF (TYPE_ID = 111) THEN DEEP = 1;
    IF (TYPE_ID = 112) THEN DEEP = 2;

    C = 0;
    SELECT COUNT(R.VAL)
    FROM OBJECT_CHILDREN_GET_DEEP(:I$OBJ_ID, 2, :DEEP) O
    INNER JOIN VALL V727 ON  V727.OBJ_ID = O.OBJ_ID
    INNER JOIN LISTVALS LV ON V727.LISTVAL_ID=LV.LISTVAL_ID
    LEFT JOIN RES_GET(LV.RES_ID,  :LANG_CODE) R ON 1=1
    WHERE V727.IS_DEL = 0
    AND V727.IS_DEL =0
    AND LV.IS_DEL =0
    AND (R.VAL ='Р”Р°')
    AND V727.PARAM_ID = 727
    INTO :C;
    SUSPEND;/*1*/


    C = 0;
    SELECT SUM(V728.VAL)
    FROM OBJECT_CHILDREN_GET_DEEP(:I$OBJ_ID, 2, :DEEP) O
    INNER JOIN VALF V728 ON  V728.OBJ_ID = O.OBJ_ID
    WHERE V728.IS_DEL = 0
          AND V728.PARAM_ID = 728
          AND V728.IS_DEL =0
    INTO :C;
    SUSPEND;/*2*/


    C = 0;
    SELECT SUM(V729.VAL)
    FROM OBJECT_CHILDREN_GET_DEEP(:I$OBJ_ID, 2, :DEEP) O
    INNER JOIN VALF V729 ON  V729.OBJ_ID = O.OBJ_ID
    WHERE V729.IS_DEL = 0
          AND V729.IS_DEL =0
          AND V729.PARAM_ID = 729
    INTO :C;
    SUSPEND;/*3*/

    C = 0;
    SELECT SUM(V730.VAL)
    FROM OBJECT_CHILDREN_GET_DEEP(:I$OBJ_ID, 2, :DEEP) O
    INNER JOIN VALF V730 ON  V730.OBJ_ID = O.OBJ_ID
    WHERE V730.IS_DEL = 0
          AND V730.PARAM_ID = 730
          AND V730.IS_DEL =0
    INTO :C;
    SUSPEND;/*4*/

     SELECT SUM(V731.VAL)
    FROM OBJECT_CHILDREN_GET_DEEP(:I$OBJ_ID, 2, :DEEP) O
    INNER JOIN VALF V731 ON  V731.OBJ_ID = O.OBJ_ID
    WHERE V731.IS_DEL = 0
          AND V731.PARAM_ID = 731
          AND V731.IS_DEL =0
    INTO :C;
    SUSPEND;/*5*/

     SELECT SUM(V733.VAL)
    FROM OBJECT_CHILDREN_GET_DEEP(:I$OBJ_ID, 2, :DEEP) O
    INNER JOIN VALF V733 ON  V733.OBJ_ID = O.OBJ_ID
    WHERE V733.IS_DEL = 0
          AND V733.PARAM_ID = 733
          AND V733.IS_DEL =0
    INTO :C;
    SUSPEND;/*6*/

    C = NULL;
    SUSPEND;
    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_SPB_POST_BUHGALTER (
    I$OBJ_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    F VARCHAR(250),
    I VARCHAR(250),
    O VARCHAR(250),
    FIO VARCHAR(250),
    POST VARCHAR(250))
AS
DECLARE VARIABLE LANG_CODE VARCHAR(2);
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :LANG_CODE;

    FOR
      SELECT FIRST 1 L14.OBJ_ID, COALESCE(R.VAL, V66.VAL)
      FROM LINKS L14
      JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
      JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0 AND V73.VAL <= CURRENT_DATE
      JOIN VALR V69 ON V69.OBJ_ID = L15.OBJ_ID AND V69.PARAM_ID = 69 AND V69.IS_DEL = 0
      LEFT JOIN VALL V58 ON V58.OBJ_ID = V69.VAL AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0
      JOIN LISTVALS LV ON LV.LISTVAL_ID = V58.LISTVAL_ID
      LEFT JOIN RES_GET(LV.RES_ID, :LANG_CODE) R ON 1 = 1
      LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
      LEFT JOIN VALS V66 ON V66.OBJ_ID = L15.OBJ_ID AND V66.PARAM_ID = 66 AND V66.IS_DEL = 0
      WHERE L14.PARENT_ID = :I$OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
        AND (UPPER(TRIM(V66.VAL)) = 'ГЛАВНЫЙ БУХГАЛТЕР' OR V58.LISTVAL_ID IN (69, 16138))  -- ГЛАВНЫЙ БУХГАЛТЕР по спискам 21 и 369
        AND V74.VAL IS NULL
      INTO :OBJ_ID, :POST
    DO
    BEGIN
      SELECT V.VAL FROM VALS V WHERE V.PARAM_ID = 59 AND V.OBJ_ID = :OBJ_ID AND V.IS_DEL = 0 INTO :F;
      SELECT V.VAL FROM VALS V WHERE V.PARAM_ID = 60 AND V.OBJ_ID = :OBJ_ID AND V.IS_DEL = 0 INTO :I;
      SELECT V.VAL FROM VALS V WHERE V.PARAM_ID = 61 AND V.OBJ_ID = :OBJ_ID AND V.IS_DEL = 0 INTO :O;

      FIO = F || ' ' || I || ' ' || COALESCE(O, '');
      SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_SPB_POST_DIRECTOR (
    I$OBJ_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    POST_ID BIGINT,
    F VARCHAR(250),
    I VARCHAR(250),
    O VARCHAR(250),
    POST VARCHAR(250),
    FIO VARCHAR(250))
AS
DECLARE VARIABLE LANG_CODE VARCHAR(2);
BEGIN
  SELECT LANG_CODE
  FROM USERS
  WHERE USER_ID = :I$USER_ID
  INTO :LANG_CODE;

  F = '';
  I = '';
  O = '';
  POST = '';
  FOR
    SELECT FIRST 1 L14.OBJ_ID, V66.VAL, V58.LISTVAL_ID
    FROM LINKS L14
    JOIN VALL V274 ON V274.OBJ_ID = L14.OBJ_ID AND V274.PARAM_ID = 274 AND V274.IS_DEL = 0 AND V274.LISTVAL_ID = 602
    JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
    JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0 -- AND V73.VAL <= CURRENT_DATE
    JOIN LINKS L ON L.OBJ_ID = L15.OBJ_ID AND L.PARENT_TYPE_ID = 13 AND L.DATE_DEL IS NULL
    JOIN VALL V58 ON V58.OBJ_ID = L.PARENT_ID AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V58.LISTVAL_ID AND (LV.TAG = 'R1' OR LV."FILTER" = 'R1')
    JOIN VALS V66 ON V66.OBJ_ID = L.PARENT_ID AND V66.PARAM_ID = 66 AND V66.IS_DEL = 0
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
    WHERE L14.PARENT_ID = :I$OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL AND V74.VAL IS NULL
      -- AND (V74.VAL IS NULL OR V74.VAL > CURRENT_DATE)
    INTO :OBJ_ID, :POST, :POST_ID
  DO
  BEGIN
    SELECT V.VAL FROM VALS V WHERE V.PARAM_ID = 59 AND V.OBJ_ID = :OBJ_ID AND V.IS_DEL = 0 INTO :F;
    SELECT V.VAL FROM VALS V WHERE V.PARAM_ID = 60 AND V.OBJ_ID = :OBJ_ID AND V.IS_DEL = 0 INTO :I;
    SELECT V.VAL FROM VALS V WHERE V.PARAM_ID = 61 AND V.OBJ_ID = :OBJ_ID AND V.IS_DEL = 0 INTO :O;

    FIO = F || ' ' || I || ' ' || COALESCE(O, '');
    SUSPEND;
  END

  -- Если штатного директора нет, смотрим ИО
  -- Выключено по указаниям НИП 11.04.2025
  -- Включено обратно 03.07.2025
  IF(FIO IS NULL AND 1 = 1) THEN
  FOR
    -- берем самого свеженазначенного ИО, а то их может быть несколько
    SELECT FIRST 1 L14.OBJ_ID
    FROM LINKS L14
    JOIN VALL V3343 ON V3343.OBJ_ID = L14.OBJ_ID AND V3343.PARAM_ID = 3343 AND V3343.IS_DEL = 0 AND V3343.LISTVAL_ID = 2
    JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
    JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0 -- AND V73.VAL <= CURRENT_DATE
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
    WHERE L14.PARENT_ID = :I$OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL AND V74.VAL IS NULL
    ORDER BY V3343.DATE_MODIFY DESC
    INTO :OBJ_ID
  DO
  BEGIN
    SELECT V.VAL FROM VALS V WHERE V.PARAM_ID = 59 AND V.OBJ_ID = :OBJ_ID AND V.IS_DEL = 0 INTO :F;
    SELECT V.VAL FROM VALS V WHERE V.PARAM_ID = 60 AND V.OBJ_ID = :OBJ_ID AND V.IS_DEL = 0 INTO :I;
    SELECT V.VAL FROM VALS V WHERE V.PARAM_ID = 61 AND V.OBJ_ID = :OBJ_ID AND V.IS_DEL = 0 INTO :O;

    FIO = F || ' ' || I || ' ' || COALESCE(O, '');

    -- В качестве должности ищем самую свежую должность руководителя 1 уровня
    SELECT FIRST 1 V66.VAL, V58.LISTVAL_ID
    FROM LINKS L13
    JOIN VALL V58 ON V58.OBJ_ID = L13.OBJ_ID AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V58.LISTVAL_ID AND (LV.TAG = 'R1' OR LV."FILTER" = 'R1')
    JOIN VALS V66 ON V66.OBJ_ID = L13.OBJ_ID AND V66.PARAM_ID = 66 AND V66.IS_DEL = 0
      AND POSITION('исполняющ' IN V66.VAL) = 0 AND POSITION('обязанности' IN V66.VAL) = 0 -- исключаем должности на местах типа "Исполняющий обязанности того-то"
    WHERE L13.PARENT_ID = :I$OBJ_ID AND L13.OBJ_TYPE_ID = 13 AND L13.DATE_DEL IS NULL
    ORDER BY L13.DATE_INS DESC
    INTO :POST, :POST_ID;

    IF(POSITION('аведующий' IN POST) > 0) THEN POST = 'Исполняющий обязанности ' || REPLACE(POST, 'аведующий', 'аведующего');
    ELSE POST = 'Исполняющий обязанности ' || POST || 'а';

    SUSPEND;
  END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_SPB_POST_EGE_RESPONSIBLE (
    I$OBJ_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    F VARCHAR(250),
    I VARCHAR(250),
    O VARCHAR(250),
    POST VARCHAR(250))
AS
declare variable LANG_CODE varchar(2);
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :LANG_CODE;

    F = '';
    I = '';
    O = '';
    POST = '';
    FOR
        SELECT FIRST 1 O14.OBJ_ID, R.VAL
    --    FROM OBJECT_CHILDREN_GET1L(:I$OBJ_ID, 14) C
        FROM VALR V1369

        JOIN OBJECTS O14
        ON O14.OBJ_ID = V1369.VAL

        JOIN LINKS L15
        ON L15.PARENT_ID = O14.OBJ_ID
        AND L15.OBJ_TYPE_ID = 15
        AND L15.DATE_DEL IS NULL

        JOIN VALD V73
        ON V73.OBJ_ID = L15.OBJ_ID
        AND V73.PARAM_ID = 73
        AND V73.IS_DEL = 0
        AND V73.VAL <= CURRENT_DATE

        JOIN VALR V69
        ON V69.OBJ_ID = L15.OBJ_ID
        AND V69.PARAM_ID = 69
        AND V69.IS_DEL = 0

        JOIN VALL V64
        ON V64.OBJ_ID = V69.VAL
        AND V64.PARAM_ID = 64
        AND V64.IS_DEL = 0

        JOIN VALL V58
        ON V58.OBJ_ID = V69.VAL
        AND V58.PARAM_ID = 58
        AND V58.IS_DEL = 0

        JOIN LISTVALS LV
        ON LV.LISTVAL_ID = V58.LISTVAL_ID

        LEFT JOIN RES_GET(LV.RES_ID,  :LANG_CODE) R ON 1=1

        LEFT JOIN VALD V74
        ON V74.PARAM_ID = 74 AND V74.OBJ_ID = L15.OBJ_ID

        WHERE V1369.OBJ_ID = :I$OBJ_ID
        AND V1369.PARAM_ID = 1369
        AND V1369.IS_DEL = 0
        AND (V74.VAL IS NULL OR V74.IS_DEL = 1)
        INTO :OBJ_ID, :POST
    DO
    BEGIN
        SELECT V.VAL FROM VALS V WHERE V.PARAM_ID = 59 AND V.OBJ_ID = :OBJ_ID AND V.IS_DEL = 0 INTO :F;
        SELECT V.VAL FROM VALS V WHERE V.PARAM_ID = 60 AND V.OBJ_ID = :OBJ_ID AND V.IS_DEL = 0 INTO :I;
        SELECT V.VAL FROM VALS V WHERE V.PARAM_ID = 61 AND V.OBJ_ID = :OBJ_ID AND V.IS_DEL = 0 INTO :O;
        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_SPB_QUAL_DISTR_1 (
    I$OBJ_ID BIGINT)
RETURNS (
    N0 VARCHAR(4),
    OU VARCHAR(1000),
    CS FLOAT,
    CF INTEGER,
    X1 INTEGER,
    X2 INTEGER,
    X3 INTEGER,
    Z1 INTEGER,
    Z2 INTEGER,
    Z3 INTEGER)
AS
DECLARE VARIABLE CURR_YEAR SMALLINT;
DECLARE VARIABLE N INTEGER;
DECLARE VARIABLE OU_ID BIGINT;
BEGIN

    CURR_YEAR = EXTRACT(YEAR FROM CURRENT_TIMESTAMP);

    N   = 0;
    N0  = '';
    OU  = '';
    CS  = null;
    CF  = null;
    X1  = CURR_YEAR + 1;
    X2  = CURR_YEAR + 2;
    X3  = CURR_YEAR + 3;
    Z1  = CURR_YEAR + 1;
    Z2  = CURR_YEAR + 2;
    Z3  = CURR_YEAR + 3;

    SUSPEND;

    FOR SELECT L2.OBJ_ID
        FROM LINKS    L2
        INNER JOIN OBJECTS O2 ON O2.OBJ_ID = L2.OBJ_ID AND O2.TYPE_ID = 2 /* OU */
        WHERE L2.PARENT_ID = :I$OBJ_ID
        AND   L2.DATE_DEL IS NULL
        INTO :OU_ID
    DO
    BEGIN
        X1 = 0; X2 = 0; X3 = 0;
        Z1 = 0; Z2 = 0; Z3 = 0;
        N  = N + 1;
        N0 = N;
        SELECT CAPTION FROM OBJECT_CAPTION_GET(:OU_ID) INTO :OU;

        SELECT SUM(STV.VAL)
        FROM LINKS    L13
        INNER JOIN OBJECTS  O13 ON O13.OBJ_ID = L13.OBJ_ID AND O13.TYPE_ID = 13       /* post */
        INNER JOIN VALF     STV ON STV.PARAM_ID  = 62      AND STV.OBJ_ID = O13.OBJ_ID AND STV.IS_DEL = 0
        WHERE L13.PARENT_ID = :OU_ID
        AND   L13.DATE_DEL IS NULL
        AND   (SELECT SORT_ORDER FROM DO_FUNC(O13.OBJ_ID, 400)) = 2
        INTO :CS;

        SELECT COUNT(*)
        FROM LINKS    L14
        INNER JOIN OBJECTS  O14 ON O14.OBJ_ID = L14.OBJ_ID        AND O14.TYPE_ID = 14       /* worker */
        INNER JOIN LINKS    L15 ON L15.PARENT_ID = O14.OBJ_ID     AND L15.DATE_DEL IS NULL
        INNER JOIN OBJECTS  O15 ON O15.OBJ_ID = L15.OBJ_ID        AND O15.TYPE_ID = 15       /* priem */
        INNER JOIN LINKS    L13 ON L13.OBJ_ID = O15.OBJ_ID        AND L13.DATE_DEL IS NULL
        INNER JOIN OBJECTS  O13 ON O13.OBJ_ID = L13.PARENT_ID     AND O13.TYPE_ID = 13       /* post */
        INNER JOIN VALL     OSN ON OSN.PARAM_ID  = 72      AND OSN.OBJ_ID = O15.OBJ_ID AND OSN.IS_DEL = 0
        INNER JOIN VALD     D73 ON D73.PARAM_ID  = 73      AND D73.OBJ_ID = O15.OBJ_ID AND D73.IS_DEL = 0
        LEFT  JOIN VALD     D74 ON D74.PARAM_ID  = 74      AND D74.OBJ_ID = O15.OBJ_ID AND D74.IS_DEL = 0
        WHERE L14.PARENT_ID = :OU_ID
        AND   L14.DATE_DEL IS NULL
        AND   (SELECT SORT_ORDER FROM DO_FUNC(O13.OBJ_ID, 400)) = 2
        AND   OSN.LISTVAL_ID = 934
        AND   D73.VAL <= CURRENT_DATE
        AND   ((D74.VAL IS NULL) OR (D74.VAL >= CURRENT_DATE))
        INTO :CF;

        SELECT COUNT(*)
        FROM LINKS    L14
        INNER JOIN OBJECTS  O14 ON O14.OBJ_ID = L14.OBJ_ID        AND O14.TYPE_ID = 14       /* worker */
        INNER JOIN LINKS   L100 ON L100.PARENT_ID = O14.OBJ_ID    AND L100.DATE_DEL IS NULL
        INNER JOIN OBJECTS O100 ON O100.OBJ_ID = L100.OBJ_ID      AND O100.TYPE_ID = 100     /* zajavka */
        INNER JOIN VALS       V ON V.PARAM_ID  = 618              AND V.OBJ_ID = L100.OBJ_ID
        WHERE L14.PARENT_ID = :OU_ID
        AND   L14.DATE_DEL IS NULL
        AND   V.VAL = :CURR_YEAR + 1
        AND   V.IS_DEL = 0
        INTO  :X1;

        SELECT COUNT(*)
        FROM LINKS    L14
        INNER JOIN OBJECTS  O14 ON O14.OBJ_ID = L14.OBJ_ID        AND O14.TYPE_ID = 14       /* worker */
        INNER JOIN LINKS   L100 ON L100.PARENT_ID = O14.OBJ_ID    AND L100.DATE_DEL IS NULL
        INNER JOIN OBJECTS O100 ON O100.OBJ_ID = L100.OBJ_ID      AND O100.TYPE_ID = 100     /* zajavka */
        INNER JOIN VALS       V ON V.PARAM_ID  = 618              AND V.OBJ_ID = L100.OBJ_ID
        WHERE L14.PARENT_ID = :OU_ID
        AND   L14.DATE_DEL IS NULL
        AND   V.VAL = :CURR_YEAR + 2
        AND   V.IS_DEL = 0
        INTO  :X2;

        SELECT COUNT(*)
        FROM LINKS    L14
        INNER JOIN OBJECTS  O14 ON O14.OBJ_ID = L14.OBJ_ID        AND O14.TYPE_ID = 14       /* worker */
        INNER JOIN LINKS   L100 ON L100.PARENT_ID = O14.OBJ_ID    AND L100.DATE_DEL IS NULL
        INNER JOIN OBJECTS O100 ON O100.OBJ_ID = L100.OBJ_ID      AND O100.TYPE_ID = 100     /* zajavka */
        INNER JOIN VALS       V ON V.PARAM_ID  = 618              AND V.OBJ_ID = L100.OBJ_ID
        WHERE L14.PARENT_ID = :OU_ID
        AND   L14.DATE_DEL IS NULL
        AND   V.VAL = :CURR_YEAR + 3
        AND   V.IS_DEL = 0
        INTO  :X3;


        SELECT COUNT(*)
        FROM LINKS    L14
        INNER JOIN OBJECTS  O14 ON O14.OBJ_ID = L14.OBJ_ID        AND O14.TYPE_ID = 14       /* worker */
        INNER JOIN LINKS   L100 ON L100.PARENT_ID = O14.OBJ_ID    AND L100.DATE_DEL IS NULL
        INNER JOIN OBJECTS O100 ON O100.OBJ_ID = L100.OBJ_ID      AND O100.TYPE_ID = 101     /* zajavka */
        INNER JOIN VALS       V ON V.PARAM_ID  = 621              AND V.OBJ_ID = L100.OBJ_ID
        WHERE L14.PARENT_ID = :OU_ID
        AND   L14.DATE_DEL IS NULL
        AND   V.VAL = :CURR_YEAR + 1
        AND   V.IS_DEL = 0
        INTO  :Z1;

        SELECT COUNT(*)
        FROM LINKS    L14
        INNER JOIN OBJECTS  O14 ON O14.OBJ_ID = L14.OBJ_ID        AND O14.TYPE_ID = 14       /* worker */
        INNER JOIN LINKS   L100 ON L100.PARENT_ID = O14.OBJ_ID    AND L100.DATE_DEL IS NULL
        INNER JOIN OBJECTS O100 ON O100.OBJ_ID = L100.OBJ_ID      AND O100.TYPE_ID = 101     /* zajavka */
        INNER JOIN VALS       V ON V.PARAM_ID  = 621              AND V.OBJ_ID = L100.OBJ_ID
        WHERE L14.PARENT_ID = :OU_ID
        AND   L14.DATE_DEL IS NULL
        AND   V.VAL = :CURR_YEAR + 2
        AND   V.IS_DEL = 0
        INTO  :Z2;

        SELECT COUNT(*)
        FROM LINKS    L14
        INNER JOIN OBJECTS  O14 ON O14.OBJ_ID = L14.OBJ_ID        AND O14.TYPE_ID = 14       /* worker */
        INNER JOIN LINKS   L100 ON L100.PARENT_ID = O14.OBJ_ID    AND L100.DATE_DEL IS NULL
        INNER JOIN OBJECTS O100 ON O100.OBJ_ID = L100.OBJ_ID      AND O100.TYPE_ID = 101     /* zajavka */
        INNER JOIN VALS       V ON V.PARAM_ID  = 621              AND V.OBJ_ID = L100.OBJ_ID
        WHERE L14.PARENT_ID = :OU_ID
        AND   L14.DATE_DEL IS NULL
        AND   V.VAL = :CURR_YEAR + 3
        AND   V.IS_DEL = 0
        INTO  :Z3;

        SUSPEND;

    END



END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_SPB_QUAL_DISTR_2 (
    I$OBJ_ID BIGINT)
RETURNS (
    N0 VARCHAR(4),
    PT VARCHAR(1000),
    CS FLOAT,
    CF INTEGER,
    X1 INTEGER,
    X2 INTEGER,
    X3 INTEGER)
AS
declare variable CURR_YEAR smallint;
declare variable N integer;
declare variable LISTVAL_ID bigint;
declare variable OU_ID bigint;
BEGIN

    CURR_YEAR = EXTRACT(YEAR FROM CURRENT_TIMESTAMP);

    N   = 0;
    N0  = '';
    PT  = '';
    CS  = null;
    CF  = null;
    X1  = CURR_YEAR + 1;
    X2  = CURR_YEAR + 2;
    X3  = CURR_YEAR + 3;

    SUSPEND;

    FOR
        SELECT LV.LISTVAL_ID,
               R.VAL

        FROM LISTVALS LV

        JOIN RES R
        ON R.RES_ID = LV.RES_ID
        AND R.LANG_CODE = 'RU'

        WHERE LV.LIST_ID = 21
        AND LV.PARENT_ID = 98
        AND R.VAL_LONG = 'Учитель'

        ORDER BY SORT_ORDER
        INTO :LISTVAL_ID, :PT
    DO
    BEGIN
        X1 = 0; X2 = 0; X3 = 0;

        SELECT SUM(STV.VAL)
        FROM OBJECTS         O2
        INNER JOIN LINKS    L13 ON L13.PARENT_ID = O2.OBJ_ID AND L13.DATE_DEL IS NULL
        INNER JOIN OBJECTS  O13 ON O13.OBJ_ID = L13.OBJ_ID   AND O13.TYPE_ID = 13       /* post */
        INNER JOIN VALL     PED ON PED.PARAM_ID  = 58        AND PED.OBJ_ID = O13.OBJ_ID AND PED.IS_DEL = 0
        INNER JOIN VALF     STV ON STV.PARAM_ID  = 62        AND STV.OBJ_ID = O13.OBJ_ID AND STV.IS_DEL = 0
        WHERE O2.TYPE_ID = 2
        AND   PED.LISTVAL_ID = :LISTVAL_ID
        INTO :CS;

        SELECT COUNT(*)
        FROM LINKS    L14
        INNER JOIN OBJECTS  O14 ON O14.OBJ_ID = L14.OBJ_ID        AND O14.TYPE_ID = 14       /* worker */
        INNER JOIN LINKS    L15 ON L15.PARENT_ID = O14.OBJ_ID     AND L15.DATE_DEL IS NULL
        INNER JOIN OBJECTS  O15 ON O15.OBJ_ID = L15.OBJ_ID        AND O15.TYPE_ID = 15       /* priem */
        INNER JOIN LINKS    L13 ON L13.OBJ_ID = O15.OBJ_ID        AND L13.DATE_DEL IS NULL
        INNER JOIN OBJECTS  O13 ON O13.OBJ_ID = L13.PARENT_ID     AND O13.TYPE_ID = 13       /* post */
        INNER JOIN VALL     PED ON PED.PARAM_ID  = 58      AND PED.OBJ_ID = O13.OBJ_ID AND PED.IS_DEL = 0
        INNER JOIN VALL     OSN ON OSN.PARAM_ID  = 72      AND OSN.OBJ_ID = O15.OBJ_ID AND OSN.IS_DEL = 0
        INNER JOIN VALD     D73 ON D73.PARAM_ID  = 73      AND D73.OBJ_ID = O15.OBJ_ID AND D73.IS_DEL = 0
        LEFT  JOIN VALD     D74 ON D74.PARAM_ID  = 74      AND D74.OBJ_ID = O15.OBJ_ID AND D74.IS_DEL = 0
        WHERE L14.PARENT_ID = :OU_ID
        AND   L14.DATE_DEL IS NULL
        AND   PED.LISTVAL_ID = 2
        AND   OSN.LISTVAL_ID = 934
        AND   D73.VAL <= CURRENT_DATE
        AND   ((D74.VAL IS NULL) OR (D74.VAL >= CURRENT_DATE))
        INTO :CF;

/*$$IBEC$$         SELECT COUNT(*)
        FROM LINKS    L14
        INNER JOIN OBJECTS  O14 ON O14.OBJ_ID = L14.OBJ_ID        AND O14.TYPE_ID = 14
        INNER JOIN LINKS   L100 ON L100.PARENT_ID = O14.OBJ_ID    AND L100.DATE_DEL IS NULL
        INNER JOIN OBJECTS O100 ON O100.OBJ_ID = L100.OBJ_ID      AND O100.TYPE_ID = 100
        INNER JOIN VALS       V ON V.PARAM_ID  = 618              AND V.OBJ_ID = L100.OBJ_ID
        WHERE L14.PARENT_ID = :OU_ID
        AND   L14.DATE_DEL IS NULL
        AND   V.VAL = :CURR_YEAR + 1
        AND   V.IS_DEL = 0
        INTO  :X1;


        IF ((X1 > 0) OR (X2 > 0) OR (X3 > 0)) THEN $$IBEC$$*/
        BEGIN
            N  = N + 1;
            N0 = N;
            SUSPEND;
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_SPB_QUAL_DISTR_3 (
    I$OBJ_ID BIGINT)
RETURNS (
    N0 VARCHAR(4),
    DPO VARCHAR(1000),
    X1 INTEGER,
    X2 INTEGER,
    X3 INTEGER)
AS
declare variable CURR_YEAR smallint;
declare variable N integer;
BEGIN

    CURR_YEAR = EXTRACT(YEAR FROM CURRENT_TIMESTAMP);

    N   = 0;
    N0  = '';
    DPO = '';
    X1  = CURR_YEAR + 1;
    X2  = CURR_YEAR + 2;
    X3  = CURR_YEAR + 3;

    SUSPEND;

    FOR
        SELECT R.VAL
        FROM LISTVALS LV

        JOIN RES R
        ON R.RES_ID = LV.RES_ID
        AND R.LANG_CODE = 'RU'

        WHERE LV.LIST_ID = 151
        ORDER BY LV.SORT_ORDER
        INTO :DPO
    DO
    BEGIN
        X1 = 0; X2 = 0; X3 = 0;

        SELECT COUNT(*)
        FROM LINKS    L2
        INNER JOIN OBJECTS O2   ON O2.OBJ_ID = L2.OBJ_ID          AND O2.TYPE_ID = 2         /* OU */
        INNER JOIN LINKS    L14 ON L14.PARENT_ID = O2.OBJ_ID      AND L14.DATE_DEL IS NULL
        INNER JOIN OBJECTS  O14 ON O14.OBJ_ID = L14.OBJ_ID        AND O14.TYPE_ID = 14       /* worker */
        INNER JOIN LINKS   L100 ON L100.PARENT_ID = O14.OBJ_ID    AND L100.DATE_DEL IS NULL
        INNER JOIN OBJECTS O100 ON O100.OBJ_ID = L100.OBJ_ID      AND O100.TYPE_ID = 100     /* zajavka */
        INNER JOIN VALS      VD ON VD.PARAM_ID  = 617             AND VD.OBJ_ID = L100.OBJ_ID  AND VD.IS_DEL = 0
        INNER JOIN VALS      VY ON VY.PARAM_ID  = 618             AND VY.OBJ_ID = L100.OBJ_ID  AND VY.IS_DEL = 0
        WHERE L2.PARENT_ID = :I$OBJ_ID
        AND   L2.DATE_DEL IS NULL
        AND   VY.VAL = :CURR_YEAR + 1
        AND   VD.VAL = :DPO
        INTO :X1;

        SELECT COUNT(*)
        FROM LINKS    L2
        INNER JOIN OBJECTS O2   ON O2.OBJ_ID = L2.OBJ_ID          AND O2.TYPE_ID = 2         /* OU */
        INNER JOIN LINKS    L14 ON L14.PARENT_ID = O2.OBJ_ID      AND L14.DATE_DEL IS NULL
        INNER JOIN OBJECTS  O14 ON O14.OBJ_ID = L14.OBJ_ID        AND O14.TYPE_ID = 14       /* worker */
        INNER JOIN LINKS   L100 ON L100.PARENT_ID = O14.OBJ_ID    AND L100.DATE_DEL IS NULL
        INNER JOIN OBJECTS O100 ON O100.OBJ_ID = L100.OBJ_ID      AND O100.TYPE_ID = 100     /* zajavka */
        INNER JOIN VALS      VD ON VD.PARAM_ID  = 617             AND VD.OBJ_ID = L100.OBJ_ID  AND VD.IS_DEL = 0
        INNER JOIN VALS      VY ON VY.PARAM_ID  = 618             AND VY.OBJ_ID = L100.OBJ_ID  AND VY.IS_DEL = 0
        WHERE L2.PARENT_ID = :I$OBJ_ID
        AND   L2.DATE_DEL IS NULL
        AND   VY.VAL = :CURR_YEAR + 2
        AND   VD.VAL = :DPO
        INTO :X2;

        SELECT COUNT(*)
        FROM LINKS    L2
        INNER JOIN OBJECTS O2   ON O2.OBJ_ID = L2.OBJ_ID          AND O2.TYPE_ID = 2         /* OU */
        INNER JOIN LINKS    L14 ON L14.PARENT_ID = O2.OBJ_ID      AND L14.DATE_DEL IS NULL
        INNER JOIN OBJECTS  O14 ON O14.OBJ_ID = L14.OBJ_ID        AND O14.TYPE_ID = 14       /* worker */
        INNER JOIN LINKS   L100 ON L100.PARENT_ID = O14.OBJ_ID    AND L100.DATE_DEL IS NULL
        INNER JOIN OBJECTS O100 ON O100.OBJ_ID = L100.OBJ_ID      AND O100.TYPE_ID = 100     /* zajavka */
        INNER JOIN VALS      VD ON VD.PARAM_ID  = 617             AND VD.OBJ_ID = L100.OBJ_ID  AND VD.IS_DEL = 0
        INNER JOIN VALS      VY ON VY.PARAM_ID  = 618             AND VY.OBJ_ID = L100.OBJ_ID  AND VY.IS_DEL = 0
        WHERE L2.PARENT_ID = :I$OBJ_ID
        AND   L2.DATE_DEL IS NULL
        AND   VY.VAL = :CURR_YEAR + 3
        AND   VD.VAL = :DPO
        INTO :X3;

        IF ((X1 > 0) OR (X2 > 0) OR (X3 > 0)) THEN
        BEGIN
            N  = N + 1;
            N0 = N;
            SUSPEND;
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_SPB_QUAL_DISTR_4 (
    I$OBJ_ID BIGINT)
RETURNS (
    N INTEGER,
    T VARCHAR(1000),
    F VARCHAR(1000),
    DPO VARCHAR(1000),
    CNT INTEGER)
AS
declare variable LISTVAL_ID bigint;
BEGIN

    FOR
        SELECT R.VAL

        FROM LISTVALS LV

        JOIN RES R
        ON R.RES_ID = LV.RES_ID
        AND R.LANG_CODE = 'RU'

        WHERE LV.LIST_ID = 151

        ORDER BY LV.SORT_ORDER
        INTO :DPO
    DO
    BEGIN
        FOR
            SELECT R.VAL,
                   LV.LISTVAL_ID

            FROM LISTVALS LV

            JOIN RES R
            ON R.RES_ID = LV.RES_ID
            AND R.LANG_CODE = 'RU'

            WHERE LV.LIST_ID = 96

            ORDER BY LV.SORT_ORDER
            INTO :F, :LISTVAL_ID
        DO
        BEGIN
            FOR SELECT VT.VAL, COUNT(O100.OBJ_ID)
                FROM LINKS    L2
                INNER JOIN OBJECTS O2   ON O2.OBJ_ID = L2.OBJ_ID          AND O2.TYPE_ID = 2         /* OU */
                INNER JOIN LINKS    L14 ON L14.PARENT_ID = O2.OBJ_ID      AND L14.DATE_DEL IS NULL
                INNER JOIN OBJECTS  O14 ON O14.OBJ_ID = L14.OBJ_ID        AND O14.TYPE_ID = 14       /* worker */
                INNER JOIN LINKS   L100 ON L100.PARENT_ID = O14.OBJ_ID    AND L100.DATE_DEL IS NULL
                INNER JOIN OBJECTS O100 ON O100.OBJ_ID = L100.OBJ_ID      AND O100.TYPE_ID = 100     /* zajavka */
                INNER JOIN VALS      VT ON VT.PARAM_ID  = 615             AND VT.OBJ_ID = L100.OBJ_ID  AND VT.IS_DEL = 0
                INNER JOIN VALL      VF ON VF.PARAM_ID  = 616             AND VF.OBJ_ID = L100.OBJ_ID  AND VF.IS_DEL = 0
                INNER JOIN VALS      VD ON VD.PARAM_ID  = 617             AND VD.OBJ_ID = L100.OBJ_ID  AND VD.IS_DEL = 0
                INNER JOIN VALS      VY ON VY.PARAM_ID  = 618             AND VY.OBJ_ID = L100.OBJ_ID  AND VY.IS_DEL = 0
                WHERE L2.PARENT_ID = :I$OBJ_ID
                AND   L2.DATE_DEL IS NULL
                AND   VY.VAL > EXTRACT(YEAR FROM CURRENT_TIMESTAMP)
                AND   VF.LISTVAL_ID = :LISTVAL_ID
                AND   VD.VAL = :DPO
                GROUP BY VT.VAL
                INTO :T, :CNT
            DO
            BEGIN
                N  = N + 1;
                SUSPEND;
            END
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_SPB_QUAL_DISTR_5 (
    I$OBJ_ID BIGINT)
RETURNS (
    N0 VARCHAR(4),
    TP VARCHAR(1000),
    CS FLOAT,
    CF INTEGER,
    X1 INTEGER,
    X2 INTEGER,
    X3 INTEGER,
    Z1 INTEGER,
    Z2 INTEGER,
    Z3 INTEGER)
AS
DECLARE VARIABLE CURR_YEAR SMALLINT;
DECLARE VARIABLE N INTEGER;
DECLARE VARIABLE X FLOAT;
DECLARE VARIABLE LISTVAL_ID BIGINT;
DECLARE VARIABLE OU_ID BIGINT;
DECLARE VARIABLE SCS FLOAT;
DECLARE VARIABLE SCF INTEGER;
DECLARE VARIABLE SX1 INTEGER;
DECLARE VARIABLE SX2 INTEGER;
DECLARE VARIABLE SX3 INTEGER;
DECLARE VARIABLE SZ1 INTEGER;
DECLARE VARIABLE SZ2 INTEGER;
DECLARE VARIABLE SZ3 INTEGER;
BEGIN

    CURR_YEAR = EXTRACT(YEAR FROM CURRENT_TIMESTAMP);

    N   = 0;
    N0  = '';
    TP  = '';
    CS  = null;
    CF  = null;
    X1  = CURR_YEAR + 1;
    X2  = CURR_YEAR + 2;
    X3  = CURR_YEAR + 3;
    Z1  = CURR_YEAR + 1;
    Z2  = CURR_YEAR + 2;
    Z3  = CURR_YEAR + 3;

    SCS = 0;
    SCF = 0;
    SX1 = 0;
    SX2 = 0;
    SX3 = 0;
    SZ1 = 0;
    SZ2 = 0;
    SZ3 = 0;

    SUSPEND;

    FOR
        SELECT DISTINCT
               R.VAL,
               LV.LISTVAL_ID
        FROM LISTVALS LV

        JOIN RES R
        ON R.RES_ID = LV.RES_ID
        AND R.LANG_CODE = 'RU'

        JOIN VALL VL
        ON VL.PARAM_ID = 11
        AND VL.LISTVAL_ID = LV.LISTVAL_ID
        AND VL.IS_DEL = 0

        WHERE LV.LIST_ID = 6

        ORDER BY LV.SORT_ORDER
        INTO :TP, :LISTVAL_ID
    DO
    BEGIN

        CS = 0; CF = 0;
        X1 = 0; X2 = 0; X3 = 0;
        Z1 = 0; Z2 = 0; Z3 = 0;
        N  = N + 1;
        N0 = N;

        FOR SELECT L2.OBJ_ID
            FROM LINKS    L2
            INNER JOIN OBJECTS O2 ON O2.OBJ_ID = L2.OBJ_ID AND O2.TYPE_ID = 2 /* OU */
            INNER JOIN VALL VL    ON VL.PARAM_ID = 11      AND VL.OBJ_ID = L2.OBJ_ID
            WHERE L2.PARENT_ID = :I$OBJ_ID
            AND   L2.DATE_DEL IS NULL
            AND VL.LISTVAL_ID = :LISTVAL_ID
            AND VL.IS_DEL = 0
            INTO :OU_ID
        DO
        BEGIN

            SELECT SUM(STV.VAL)
            FROM LINKS    L13
            INNER JOIN OBJECTS  O13 ON O13.OBJ_ID = L13.OBJ_ID AND O13.TYPE_ID = 13       /* post */
            INNER JOIN VALF     STV ON STV.PARAM_ID  = 62      AND STV.OBJ_ID = O13.OBJ_ID AND STV.IS_DEL = 0
            WHERE L13.PARENT_ID = :OU_ID
            AND   L13.DATE_DEL IS NULL
            AND   (SELECT SORT_ORDER FROM DO_FUNC(O13.OBJ_ID, 400)) = 2
            INTO :X;

            CS = CS + X;

            SELECT COUNT(*)
            FROM LINKS    L14
            INNER JOIN OBJECTS  O14 ON O14.OBJ_ID = L14.OBJ_ID        AND O14.TYPE_ID = 14       /* worker */
            INNER JOIN LINKS    L15 ON L15.PARENT_ID = O14.OBJ_ID     AND L15.DATE_DEL IS NULL
            INNER JOIN OBJECTS  O15 ON O15.OBJ_ID = L15.OBJ_ID        AND O15.TYPE_ID = 15       /* priem */
            INNER JOIN LINKS    L13 ON L13.OBJ_ID = O15.OBJ_ID        AND L13.DATE_DEL IS NULL
            INNER JOIN OBJECTS  O13 ON O13.OBJ_ID = L13.PARENT_ID     AND O13.TYPE_ID = 13       /* post */
            INNER JOIN VALL     OSN ON OSN.PARAM_ID  = 72      AND OSN.OBJ_ID = O15.OBJ_ID AND OSN.IS_DEL = 0
            INNER JOIN VALD     D73 ON D73.PARAM_ID  = 73      AND D73.OBJ_ID = O15.OBJ_ID AND D73.IS_DEL = 0
            LEFT  JOIN VALD     D74 ON D74.PARAM_ID  = 74      AND D74.OBJ_ID = O15.OBJ_ID AND D74.IS_DEL = 0
            WHERE L14.PARENT_ID = :OU_ID
            AND   L14.DATE_DEL IS NULL
            AND   (SELECT SORT_ORDER FROM DO_FUNC(O13.OBJ_ID, 400)) = 2
            AND   OSN.LISTVAL_ID = 934
            AND   D73.VAL <= CURRENT_DATE
            AND   ((D74.VAL IS NULL) OR (D74.VAL >= CURRENT_DATE))
            INTO :X;

            CF = CF + X;

            SELECT COUNT(*)
            FROM LINKS    L14
            INNER JOIN OBJECTS  O14 ON O14.OBJ_ID = L14.OBJ_ID        AND O14.TYPE_ID = 14       /* worker */
            INNER JOIN LINKS   L100 ON L100.PARENT_ID = O14.OBJ_ID    AND L100.DATE_DEL IS NULL
            INNER JOIN OBJECTS O100 ON O100.OBJ_ID = L100.OBJ_ID      AND O100.TYPE_ID = 100     /* zajavka */
            INNER JOIN VALS       V ON V.PARAM_ID  = 618              AND V.OBJ_ID = L100.OBJ_ID
            WHERE L14.PARENT_ID = :OU_ID
            AND   L14.DATE_DEL IS NULL
            AND   V.VAL = :CURR_YEAR + 1
            AND   V.IS_DEL = 0
            INTO  :X;

            X1 = X1 + X;

            SELECT COUNT(*)
            FROM LINKS    L14
            INNER JOIN OBJECTS  O14 ON O14.OBJ_ID = L14.OBJ_ID        AND O14.TYPE_ID = 14       /* worker */
            INNER JOIN LINKS   L100 ON L100.PARENT_ID = O14.OBJ_ID    AND L100.DATE_DEL IS NULL
            INNER JOIN OBJECTS O100 ON O100.OBJ_ID = L100.OBJ_ID      AND O100.TYPE_ID = 100     /* zajavka */
            INNER JOIN VALS       V ON V.PARAM_ID  = 618              AND V.OBJ_ID = L100.OBJ_ID
            WHERE L14.PARENT_ID = :OU_ID
            AND   L14.DATE_DEL IS NULL
            AND   V.VAL = :CURR_YEAR + 2
            AND   V.IS_DEL = 0
            INTO  :X;

            X2 = X2 + X;

            SELECT COUNT(*)
            FROM LINKS    L14
            INNER JOIN OBJECTS  O14 ON O14.OBJ_ID = L14.OBJ_ID        AND O14.TYPE_ID = 14       /* worker */
            INNER JOIN LINKS   L100 ON L100.PARENT_ID = O14.OBJ_ID    AND L100.DATE_DEL IS NULL
            INNER JOIN OBJECTS O100 ON O100.OBJ_ID = L100.OBJ_ID      AND O100.TYPE_ID = 100     /* zajavka */
            INNER JOIN VALS       V ON V.PARAM_ID  = 618              AND V.OBJ_ID = L100.OBJ_ID
            WHERE L14.PARENT_ID = :OU_ID
            AND   L14.DATE_DEL IS NULL
            AND   V.VAL = :CURR_YEAR + 3
            AND   V.IS_DEL = 0
            INTO  :X;

            X3 = X3 + X;

            SELECT COUNT(*)
            FROM LINKS    L14
            INNER JOIN OBJECTS  O14 ON O14.OBJ_ID = L14.OBJ_ID        AND O14.TYPE_ID = 14       /* worker */
            INNER JOIN LINKS   L100 ON L100.PARENT_ID = O14.OBJ_ID    AND L100.DATE_DEL IS NULL
            INNER JOIN OBJECTS O100 ON O100.OBJ_ID = L100.OBJ_ID      AND O100.TYPE_ID = 101     /* zajavka */
            INNER JOIN VALS       V ON V.PARAM_ID  = 621              AND V.OBJ_ID = L100.OBJ_ID
            WHERE L14.PARENT_ID = :OU_ID
            AND   L14.DATE_DEL IS NULL
            AND   V.VAL = :CURR_YEAR + 1
            AND   V.IS_DEL = 0
            INTO  :X;

            Z1 = Z1 + X;

            SELECT COUNT(*)
            FROM LINKS    L14
            INNER JOIN OBJECTS  O14 ON O14.OBJ_ID = L14.OBJ_ID        AND O14.TYPE_ID = 14       /* worker */
            INNER JOIN LINKS   L100 ON L100.PARENT_ID = O14.OBJ_ID    AND L100.DATE_DEL IS NULL
            INNER JOIN OBJECTS O100 ON O100.OBJ_ID = L100.OBJ_ID      AND O100.TYPE_ID = 101     /* zajavka */
            INNER JOIN VALS       V ON V.PARAM_ID  = 621              AND V.OBJ_ID = L100.OBJ_ID
            WHERE L14.PARENT_ID = :OU_ID
            AND   L14.DATE_DEL IS NULL
            AND   V.VAL = :CURR_YEAR + 2
            AND   V.IS_DEL = 0
            INTO  :X;

            Z2 = Z2 + X;

            SELECT COUNT(*)
            FROM LINKS    L14
            INNER JOIN OBJECTS  O14 ON O14.OBJ_ID = L14.OBJ_ID        AND O14.TYPE_ID = 14       /* worker */
            INNER JOIN LINKS   L100 ON L100.PARENT_ID = O14.OBJ_ID    AND L100.DATE_DEL IS NULL
            INNER JOIN OBJECTS O100 ON O100.OBJ_ID = L100.OBJ_ID      AND O100.TYPE_ID = 101     /* zajavka */
            INNER JOIN VALS       V ON V.PARAM_ID  = 621              AND V.OBJ_ID = L100.OBJ_ID
            WHERE L14.PARENT_ID = :OU_ID
            AND   L14.DATE_DEL IS NULL
            AND   V.VAL = :CURR_YEAR + 3
            AND   V.IS_DEL = 0
            INTO  :X;

            Z3 = Z3 + X;

        END

        SCS = SCS + CS;
        SCF = SCF + CF;
        SX1 = SX1 + X1;
        SX2 = SX2 + X2;
        SX3 = SX2 + X2;
        SZ1 = SZ1 + Z1;
        SZ2 = SZ2 + Z2;
        SZ3 = SZ3 + Z3;

        SUSPEND;

    END

    N0  = '';
    TP  = 'ИТОГО:';
    CS = SCS;
    CF = SCF;
    X1 = SX1;
    X2 = SX2;
    X3 = SX2;
    Z1 = SZ1;
    Z2 = SZ2;
    Z3 = SZ3;

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_SPB_QUAL_DISTR_6 (
    I$OBJ_ID BIGINT)
RETURNS (
    N0 VARCHAR(4),
    TP VARCHAR(1000),
    CS FLOAT,
    CF INTEGER,
    X1 INTEGER,
    X2 INTEGER,
    X3 INTEGER,
    Z1 INTEGER,
    Z2 INTEGER,
    Z3 INTEGER)
AS
DECLARE VARIABLE CURR_YEAR SMALLINT;
DECLARE VARIABLE N INTEGER;
DECLARE VARIABLE X FLOAT;
DECLARE VARIABLE LISTVAL_ID BIGINT;
DECLARE VARIABLE OU_ID BIGINT;
BEGIN

    CURR_YEAR = EXTRACT(YEAR FROM CURRENT_TIMESTAMP);

    N   = 0;
    N0  = '';
    TP  = '';
    CS  = null;
    CF  = null;
    X1  = CURR_YEAR + 1;
    X2  = CURR_YEAR + 2;
    X3  = CURR_YEAR + 3;
    Z1  = CURR_YEAR + 1;
    Z2  = CURR_YEAR + 2;
    Z3  = CURR_YEAR + 3;

    SUSPEND;
/*
    SELECT COUNT(*)
    FROM  OBJECTS O2
    INNER JOIN LINKS    L14 ON L14.PARENT_ID = O2.OBJ_ID      AND L14.DATE_DEL IS NULL
    INNER JOIN OBJECTS  O14 ON O14.OBJ_ID = L14.OBJ_ID        AND O14.TYPE_ID = 14
    INNER JOIN LINKS   L100 ON L100.PARENT_ID = O14.OBJ_ID    AND L100.DATE_DEL IS NULL
    INNER JOIN OBJECTS O100 ON O100.OBJ_ID = L100.OBJ_ID      AND O100.TYPE_ID = 100
    INNER JOIN VALS       V ON V.PARAM_ID  = 618              AND V.OBJ_ID = L100.OBJ_ID
    WHERE O2.TYPE_ID = 2
    AND   V.VAL = :CURR_YEAR + 1
    AND   V.IS_DEL = 0
    INTO  :C1;

    SELECT COUNT(*)
    FROM  OBJECTS O2
    INNER JOIN LINKS    L14 ON L14.PARENT_ID = O2.OBJ_ID      AND L14.DATE_DEL IS NULL
    INNER JOIN OBJECTS  O14 ON O14.OBJ_ID = L14.OBJ_ID        AND O14.TYPE_ID = 14
    INNER JOIN LINKS   L100 ON L100.PARENT_ID = O14.OBJ_ID    AND L100.DATE_DEL IS NULL
    INNER JOIN OBJECTS O100 ON O100.OBJ_ID = L100.OBJ_ID      AND O100.TYPE_ID = 100
    INNER JOIN VALS       V ON V.PARAM_ID  = 618              AND V.OBJ_ID = L100.OBJ_ID
    WHERE O2.TYPE_ID = 2
    AND   V.VAL = :CURR_YEAR + 2
    AND   V.IS_DEL = 0
    INTO  :C2;

    SELECT COUNT(*)
    FROM  OBJECTS O2
    INNER JOIN LINKS    L14 ON L14.PARENT_ID = O2.OBJ_ID      AND L14.DATE_DEL IS NULL
    INNER JOIN OBJECTS  O14 ON O14.OBJ_ID = L14.OBJ_ID        AND O14.TYPE_ID = 14
    INNER JOIN LINKS   L100 ON L100.PARENT_ID = O14.OBJ_ID    AND L100.DATE_DEL IS NULL
    INNER JOIN OBJECTS O100 ON O100.OBJ_ID = L100.OBJ_ID      AND O100.TYPE_ID = 100
    INNER JOIN VALS       V ON V.PARAM_ID  = 618              AND V.OBJ_ID = L100.OBJ_ID
    WHERE O2.TYPE_ID = 2
    AND   V.VAL = :CURR_YEAR + 3
    AND   V.IS_DEL = 0
    INTO  :C3;

    SELECT COUNT(*)
    FROM  OBJECTS O2
    INNER JOIN LINKS    L14 ON L14.PARENT_ID = O2.OBJ_ID      AND L14.DATE_DEL IS NULL
    INNER JOIN OBJECTS  O14 ON O14.OBJ_ID = L14.OBJ_ID        AND O14.TYPE_ID = 14
    INNER JOIN LINKS   L100 ON L100.PARENT_ID = O14.OBJ_ID    AND L100.DATE_DEL IS NULL
    INNER JOIN OBJECTS O100 ON O100.OBJ_ID = L100.OBJ_ID      AND O100.TYPE_ID = 101
    INNER JOIN VALS       V ON V.PARAM_ID  = 621              AND V.OBJ_ID = L100.OBJ_ID
    WHERE O2.TYPE_ID = 2
    AND   V.VAL = :CURR_YEAR + 1
    AND   V.IS_DEL = 0
    INTO  :D1;

    SELECT COUNT(*)
    FROM  OBJECTS O2
    INNER JOIN LINKS    L14 ON L14.PARENT_ID = O2.OBJ_ID      AND L14.DATE_DEL IS NULL
    INNER JOIN OBJECTS  O14 ON O14.OBJ_ID = L14.OBJ_ID        AND O14.TYPE_ID = 14
    INNER JOIN LINKS   L100 ON L100.PARENT_ID = O14.OBJ_ID    AND L100.DATE_DEL IS NULL
    INNER JOIN OBJECTS O100 ON O100.OBJ_ID = L100.OBJ_ID      AND O100.TYPE_ID = 101
    INNER JOIN VALS       V ON V.PARAM_ID  = 621              AND V.OBJ_ID = L100.OBJ_ID
    WHERE O2.TYPE_ID = 2
    AND   V.VAL = :CURR_YEAR + 2
    AND   V.IS_DEL = 0
    INTO  :D2;

    SELECT COUNT(*)
    FROM  OBJECTS O2
    INNER JOIN LINKS    L14 ON L14.PARENT_ID = O2.OBJ_ID      AND L14.DATE_DEL IS NULL
    INNER JOIN OBJECTS  O14 ON O14.OBJ_ID = L14.OBJ_ID        AND O14.TYPE_ID = 14
    INNER JOIN LINKS   L100 ON L100.PARENT_ID = O14.OBJ_ID    AND L100.DATE_DEL IS NULL
    INNER JOIN OBJECTS O100 ON O100.OBJ_ID = L100.OBJ_ID      AND O100.TYPE_ID = 101
    INNER JOIN VALS       V ON V.PARAM_ID  = 621              AND V.OBJ_ID = L100.OBJ_ID
    WHERE O2.TYPE_ID = 2
    AND   V.VAL = :CURR_YEAR + 3
    AND   V.IS_DEL = 0
    INTO  :D3;
*/
    FOR
        SELECT DISTINCT
               R.VAL,
               LV.LISTVAL_ID

        FROM LISTVALS LV

        JOIN RES R
        ON R.RES_ID = LV.RES_ID
        AND R.LANG_CODE = 'RU'

        JOIN VALL VL
        ON VL.PARAM_ID = 11
        AND VL.LISTVAL_ID = LV.LISTVAL_ID
        AND VL.IS_DEL = 0

        WHERE LV.LIST_ID = 6

        ORDER BY LV.SORT_ORDER
        INTO :TP, :LISTVAL_ID
    DO
    BEGIN

        CS = 0; CF = 0;
        X1 = 0; X2 = 0; X3 = 0;
        Z1 = 0; Z2 = 0; Z3 = 0;
        N  = N + 1;
        N0 = N;

        FOR SELECT L2.OBJ_ID
            FROM LINKS    L2
            INNER JOIN OBJECTS O2 ON O2.OBJ_ID = L2.OBJ_ID AND O2.TYPE_ID = 2 /* OU */
            INNER JOIN VALL VL    ON VL.PARAM_ID = 11      AND VL.OBJ_ID = L2.OBJ_ID
            WHERE L2.PARENT_ID = :I$OBJ_ID
            AND   L2.DATE_DEL IS NULL
            AND VL.LISTVAL_ID = :LISTVAL_ID
            AND VL.IS_DEL = 0
            INTO :OU_ID
        DO
        BEGIN

            SELECT SUM(STV.VAL)
            FROM LINKS    L13
            INNER JOIN OBJECTS  O13 ON O13.OBJ_ID = L13.OBJ_ID AND O13.TYPE_ID = 13       /* post */
            INNER JOIN VALF     STV ON STV.PARAM_ID  = 62      AND STV.OBJ_ID = O13.OBJ_ID AND STV.IS_DEL = 0
            WHERE L13.PARENT_ID = :OU_ID
            AND   L13.DATE_DEL IS NULL
            AND   (SELECT SORT_ORDER FROM DO_FUNC(O13.OBJ_ID, 400)) = 2
            INTO :X;

            CS = CS + X;

            SELECT COUNT(*)
            FROM LINKS    L14
            INNER JOIN OBJECTS  O14 ON O14.OBJ_ID = L14.OBJ_ID        AND O14.TYPE_ID = 14       /* worker */
            INNER JOIN LINKS    L15 ON L15.PARENT_ID = O14.OBJ_ID     AND L15.DATE_DEL IS NULL
            INNER JOIN OBJECTS  O15 ON O15.OBJ_ID = L15.OBJ_ID        AND O15.TYPE_ID = 15       /* priem */
            INNER JOIN LINKS    L13 ON L13.OBJ_ID = O15.OBJ_ID        AND L13.DATE_DEL IS NULL
            INNER JOIN OBJECTS  O13 ON O13.OBJ_ID = L13.PARENT_ID     AND O13.TYPE_ID = 13       /* post */
            INNER JOIN VALL     OSN ON OSN.PARAM_ID  = 72      AND OSN.OBJ_ID = O15.OBJ_ID AND OSN.IS_DEL = 0
            INNER JOIN VALD     D73 ON D73.PARAM_ID  = 73      AND D73.OBJ_ID = O15.OBJ_ID AND D73.IS_DEL = 0
            LEFT  JOIN VALD     D74 ON D74.PARAM_ID  = 74      AND D74.OBJ_ID = O15.OBJ_ID AND D74.IS_DEL = 0
            WHERE L14.PARENT_ID = :OU_ID
            AND   L14.DATE_DEL IS NULL
            AND   (SELECT SORT_ORDER FROM DO_FUNC(O13.OBJ_ID, 400)) = 2
            AND   OSN.LISTVAL_ID = 934
            AND   D73.VAL <= CURRENT_DATE
            AND   ((D74.VAL IS NULL) OR (D74.VAL >= CURRENT_DATE))
            INTO :X;

            CF = CF + X;

            SELECT COUNT(*)
            FROM LINKS    L14
            INNER JOIN OBJECTS  O14 ON O14.OBJ_ID = L14.OBJ_ID        AND O14.TYPE_ID = 14       /* worker */
            INNER JOIN LINKS   L100 ON L100.PARENT_ID = O14.OBJ_ID    AND L100.DATE_DEL IS NULL
            INNER JOIN OBJECTS O100 ON O100.OBJ_ID = L100.OBJ_ID      AND O100.TYPE_ID = 100     /* zajavka */
            INNER JOIN VALS       V ON V.PARAM_ID  = 618              AND V.OBJ_ID = L100.OBJ_ID
            WHERE L14.PARENT_ID = :OU_ID
            AND   L14.DATE_DEL IS NULL
            AND   V.VAL = :CURR_YEAR + 1
            AND   V.IS_DEL = 0
            INTO  :X;

            X1 = X1 + X;

            SELECT COUNT(*)
            FROM LINKS    L14
            INNER JOIN OBJECTS  O14 ON O14.OBJ_ID = L14.OBJ_ID        AND O14.TYPE_ID = 14       /* worker */
            INNER JOIN LINKS   L100 ON L100.PARENT_ID = O14.OBJ_ID    AND L100.DATE_DEL IS NULL
            INNER JOIN OBJECTS O100 ON O100.OBJ_ID = L100.OBJ_ID      AND O100.TYPE_ID = 100     /* zajavka */
            INNER JOIN VALS       V ON V.PARAM_ID  = 618              AND V.OBJ_ID = L100.OBJ_ID
            WHERE L14.PARENT_ID = :OU_ID
            AND   L14.DATE_DEL IS NULL
            AND   V.VAL = :CURR_YEAR + 2
            AND   V.IS_DEL = 0
            INTO  :X;

            X2 = X2 + X;

            SELECT COUNT(*)
            FROM LINKS    L14
            INNER JOIN OBJECTS  O14 ON O14.OBJ_ID = L14.OBJ_ID        AND O14.TYPE_ID = 14       /* worker */
            INNER JOIN LINKS   L100 ON L100.PARENT_ID = O14.OBJ_ID    AND L100.DATE_DEL IS NULL
            INNER JOIN OBJECTS O100 ON O100.OBJ_ID = L100.OBJ_ID      AND O100.TYPE_ID = 100     /* zajavka */
            INNER JOIN VALS       V ON V.PARAM_ID  = 618              AND V.OBJ_ID = L100.OBJ_ID
            WHERE L14.PARENT_ID = :OU_ID
            AND   L14.DATE_DEL IS NULL
            AND   V.VAL = :CURR_YEAR + 3
            AND   V.IS_DEL = 0
            INTO  :X;

            X3 = X3 + X;

            SELECT COUNT(*)
            FROM LINKS    L14
            INNER JOIN OBJECTS  O14 ON O14.OBJ_ID = L14.OBJ_ID        AND O14.TYPE_ID = 14       /* worker */
            INNER JOIN LINKS   L100 ON L100.PARENT_ID = O14.OBJ_ID    AND L100.DATE_DEL IS NULL
            INNER JOIN OBJECTS O100 ON O100.OBJ_ID = L100.OBJ_ID      AND O100.TYPE_ID = 101     /* zajavka */
            INNER JOIN VALS       V ON V.PARAM_ID  = 621              AND V.OBJ_ID = L100.OBJ_ID
            WHERE L14.PARENT_ID = :OU_ID
            AND   L14.DATE_DEL IS NULL
            AND   V.VAL = :CURR_YEAR + 1
            AND   V.IS_DEL = 0
            INTO  :X;

            Z1 = Z1 + X;

            SELECT COUNT(*)
            FROM LINKS    L14
            INNER JOIN OBJECTS  O14 ON O14.OBJ_ID = L14.OBJ_ID        AND O14.TYPE_ID = 14       /* worker */
            INNER JOIN LINKS   L100 ON L100.PARENT_ID = O14.OBJ_ID    AND L100.DATE_DEL IS NULL
            INNER JOIN OBJECTS O100 ON O100.OBJ_ID = L100.OBJ_ID      AND O100.TYPE_ID = 101     /* zajavka */
            INNER JOIN VALS       V ON V.PARAM_ID  = 621              AND V.OBJ_ID = L100.OBJ_ID
            WHERE L14.PARENT_ID = :OU_ID
            AND   L14.DATE_DEL IS NULL
            AND   V.VAL = :CURR_YEAR + 2
            AND   V.IS_DEL = 0
            INTO  :X;

            Z2 = Z2 + X;

            SELECT COUNT(*)
            FROM LINKS    L14
            INNER JOIN OBJECTS  O14 ON O14.OBJ_ID = L14.OBJ_ID        AND O14.TYPE_ID = 14       /* worker */
            INNER JOIN LINKS   L100 ON L100.PARENT_ID = O14.OBJ_ID    AND L100.DATE_DEL IS NULL
            INNER JOIN OBJECTS O100 ON O100.OBJ_ID = L100.OBJ_ID      AND O100.TYPE_ID = 101     /* zajavka */
            INNER JOIN VALS       V ON V.PARAM_ID  = 621              AND V.OBJ_ID = L100.OBJ_ID
            WHERE L14.PARENT_ID = :OU_ID
            AND   L14.DATE_DEL IS NULL
            AND   V.VAL = :CURR_YEAR + 3
            AND   V.IS_DEL = 0
            INTO  :X;

            Z3 = Z3 + X;

        END

        IF (CF > 0) THEN
        BEGIN
            X1 = X1 * 100 / CF;
            X2 = X2 * 100 / CF;
            X3 = X3 * 100 / CF;

            Z1 = Z1 * 100 / CF;
            Z2 = Z2 * 100 / CF;
            Z3 = Z3 * 100 / CF;
        END
        SUSPEND;

    END

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_SPB_QUAL_NEEDS RETURNS (
    N0 VARCHAR(4),
    DPO VARCHAR(1000),
    X4 INTEGER,
    X3 INTEGER,
    X2 INTEGER,
    X1 INTEGER,
    X0 INTEGER,
    XA INTEGER,
    XB INTEGER,
    XC INTEGER)
AS
declare variable N smallint;
declare variable CURR_YEAR smallint;
declare variable OBJ_YEAR smallint;
BEGIN

    CURR_YEAR = EXTRACT(YEAR FROM CURRENT_TIMESTAMP);

    N   = 0;
    N0  = '';
    DPO = '';
    X4  = CURR_YEAR - 4;
    X3  = CURR_YEAR - 3;
    X2  = CURR_YEAR - 2;
    X1  = CURR_YEAR - 1;
    X0  = CURR_YEAR + 0;
    Xa  = CURR_YEAR + 1;
    Xb  = CURR_YEAR + 2;
    Xc  = CURR_YEAR + 3;

    SUSPEND;

    FOR
        SELECT DISTINCT
               R.VAL
        FROM LISTVALS LV

        JOIN RES R
        ON R.RES_ID = LV.RES_ID
        AND R.LANG_CODE = 'RU'

        JOIN VALS DPO
        ON DPO.PARAM_ID = 304
        AND DPO.VAL = R.VAL
        AND DPO.IS_DEL = 0

        WHERE LV.LIST_ID = 151
        ORDER BY LV.SORT_ORDER
        INTO :DPO
    DO
    BEGIN
        X4 = 0; X3 = 0; X2 = 0; X1 = 0; X0 = 0; Xa = 0; Xb = 0; Xc = 0;

        FOR
            SELECT DT.VAL

            FROM VALS DPO

            JOIN OBJECTS O100
            ON O100.OBJ_ID = DPO.OBJ_ID
            AND O100.TYPE_ID = 100

            JOIN LINKS LNK
            ON LNK.OBJ_ID = O100.OBJ_ID
            AND LNK.DATE_DEL IS NULL

            JOIN OBJECTS O14
            ON O14.OBJ_ID = LNK.PARENT_ID
            AND O14.TYPE_ID = 14

            JOIN VALS DT
            ON DT.PARAM_ID = 618
            AND O100.OBJ_ID = DT.OBJ_ID
            AND DT.IS_DEL = 0

            WHERE DPO.PARAM_ID = 617
            AND DPO.VAL = :DPO
            AND DPO.IS_DEL = 0
            INTO :OBJ_YEAR
        DO
        BEGIN
            IF (OBJ_YEAR = CURR_YEAR - 4) THEN X4 = X4 + 1;
            IF (OBJ_YEAR = CURR_YEAR - 3) THEN X3 = X3 + 1;
            IF (OBJ_YEAR = CURR_YEAR - 2) THEN X2 = X2 + 1;
            IF (OBJ_YEAR = CURR_YEAR - 1) THEN X1 = X1 + 1;
            IF (OBJ_YEAR = CURR_YEAR - 0) THEN X0 = X0 + 1;
            IF (OBJ_YEAR = CURR_YEAR + 1) THEN Xa = Xa + 1;
            IF (OBJ_YEAR = CURR_YEAR + 2) THEN Xb = Xb + 1;
            IF (OBJ_YEAR = CURR_YEAR + 3) THEN Xc = Xc + 1;
        END

        IF ((X4 > 0) OR (X3 > 0) OR (X2 > 0) OR (X1 > 0) OR (X0 > 0) OR (Xa > 0) OR (Xb > 0) OR (Xc > 0)) THEN
        BEGIN
            N = N + 1;
            N0 = N;
            SUSPEND;
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_SPB_QUAL_OU_1 (
    I$OBJ_ID BIGINT)
RETURNS (
    N0 VARCHAR(4),
    FIO VARCHAR(1000),
    POST VARCHAR(1000),
    DTQ DATE,
    DTA DATE,
    X1 VARCHAR(4),
    X2 VARCHAR(4),
    X3 VARCHAR(4))
AS
declare variable N smallint;
declare variable CURR_YEAR smallint;
declare variable TEACHER_ID bigint;
declare variable POST_ID bigint;
BEGIN

    CURR_YEAR = EXTRACT(YEAR FROM CURRENT_TIMESTAMP);

    N   = 0;
    N0  = '';
    FIO = '';
    POST= '';
    DTQ = null;
    DTA = null;
    X1  = CURR_YEAR + 1;
    X2  = CURR_YEAR + 2;
    X3  = CURR_YEAR + 3;

    SUSPEND;

    FOR
        SELECT L14.OBJ_ID, LP13.PARENT_ID, C.CAPTION
        FROM (
            SELECT DISTINCT L14.OBJ_ID
            FROM LINKS L14
            WHERE L14.DATE_DEL IS NULL AND L14.OBJ_TYPE_ID = 14 AND L14.PARENT_ID IN (
                SELECT OBJ_ID
                FROM LINKS L
                WHERE L.PARENT_ID = :I$OBJ_ID AND L.DATE_DEL IS NULL AND L.OBJ_TYPE_ID = 211
                UNION ALL
                SELECT :I$OBJ_ID
                FROM RDB$DATABASE
                )
        ) L14
        JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
        JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
        JOIN VALL OSN ON OSN.PARAM_ID = 72 AND OSN.OBJ_ID = L15.OBJ_ID AND OSN.IS_DEL = 0 AND OSN.LISTVAL_ID = 934
        JOIN VALD D73 ON D73.PARAM_ID = 73 AND D73.OBJ_ID = L15.OBJ_ID AND D73.IS_DEL = 0 AND D73.VAL <= CURRENT_DATE
        LEFT JOIN VALD D74 ON D74.PARAM_ID = 74 AND D74.OBJ_ID = L15.OBJ_ID AND D74.IS_DEL = 0
        LEFT JOIN OBJECT_CAPTION_GET(L14.OBJ_ID) C ON 1 = 1
        WHERE (SELECT SORT_ORDER FROM DO_FUNC(LP13.PARENT_ID, 400)) = 2 AND ((D74.VAL IS NULL) OR (D74.VAL >= CURRENT_DATE))
        ORDER BY 3
        INTO :TEACHER_ID, :POST_ID, :FIO
    DO
    BEGIN
        N = N + 1;
        N0 = N;
        X1 = ''; X2 = ''; X3 = ''; DTQ = NULL; DTA = NULL;

        SELECT CAPTION FROM OBJECT_CAPTION_GET(:POST_ID) INTO :POST;

        SELECT MAX(D310.VAL)
        FROM LINKS  L36
        JOIN VALD D310 ON D310.PARAM_ID = 310 AND D310.OBJ_ID = L36.OBJ_ID AND D310.IS_DEL = 0
        WHERE L36.PARENT_ID = :TEACHER_ID AND L36.OBJ_TYPE_ID = 36 AND L36.DATE_DEL IS NULL
        INTO  :DTQ;

        SELECT MAX(D544.VAL)
        FROM LINKS L34
        JOIN VALD D544 ON D544.PARAM_ID = 544 AND D544.OBJ_ID = L34.OBJ_ID AND D544.IS_DEL = 0
        WHERE L34.PARENT_ID = :TEACHER_ID AND L34.OBJ_TYPE_ID = 34 AND L34.DATE_DEL IS NULL
        INTO  :DTA;

        SELECT FIRST 1 'ДА'
        FROM LINKS L
        JOIN VALI V ON V.PARAM_ID = 618 AND V.OBJ_ID = L.OBJ_ID AND V.VAL = :CURR_YEAR + 1 AND V.IS_DEL = 0
        WHERE L.PARENT_ID = :TEACHER_ID AND L.DATE_DEL IS NULL AND L.OBJ_TYPE_ID = 100
        INTO :X1;

        SELECT FIRST 1 'ДА'
        FROM LINKS L
        JOIN VALI V ON V.PARAM_ID = 618 AND V.OBJ_ID = L.OBJ_ID AND V.VAL = :CURR_YEAR + 2 AND V.IS_DEL = 0
        WHERE L.PARENT_ID = :TEACHER_ID AND L.DATE_DEL IS NULL AND L.OBJ_TYPE_ID = 100
        INTO :X2;

        SELECT FIRST 1 'ДА'
        FROM LINKS L
        JOIN VALI V ON V.PARAM_ID = 618 AND V.OBJ_ID = L.OBJ_ID AND V.VAL = :CURR_YEAR + 3 AND V.IS_DEL = 0
        WHERE L.PARENT_ID = :TEACHER_ID AND L.DATE_DEL IS NULL AND L.OBJ_TYPE_ID = 100
        INTO :X3;

        SUSPEND;
    END

END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_SPB_QUAL_OU_1P (
    I$OBJ_ID BIGINT)
RETURNS (
    N0 VARCHAR(4),
    FIO VARCHAR(1000),
    POST VARCHAR(1000),
    DTQ DATE,
    DTA DATE,
    X1 VARCHAR(1000),
    X2 VARCHAR(1000),
    X3 VARCHAR(1000))
AS
declare variable N smallint;
declare variable CURR_YEAR smallint;
declare variable TEACHER_ID bigint;
declare variable POST_ID bigint;
declare variable OBJ_ID bigint;
declare variable FRM varchar(1000);
declare variable DPO varchar(1000);
BEGIN

    CURR_YEAR = EXTRACT(YEAR FROM CURRENT_TIMESTAMP);

    N   = 0;
    N0  = '';
    FIO = '';
    POST= '';
    DTQ = null;
    DTA = null;

    X1  = CURR_YEAR + 1;
    X2  = CURR_YEAR + 2;
    X3  = CURR_YEAR + 3;

    SUSPEND;

    FOR SELECT L14.OBJ_ID, LP13.PARENT_ID
        FROM (
            SELECT DISTINCT L14.OBJ_ID
            FROM LINKS L14
            WHERE L14.DATE_DEL IS NULL AND L14.OBJ_TYPE_ID = 14 AND L14.PARENT_ID IN (
                SELECT OBJ_ID
                FROM LINKS L
                WHERE L.PARENT_ID = :I$OBJ_ID AND L.DATE_DEL IS NULL AND L.OBJ_TYPE_ID = 211
                UNION ALL
                SELECT :I$OBJ_ID
                FROM RDB$DATABASE
                )
        ) L14
        JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
        JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
        JOIN VALL OSN ON OSN.PARAM_ID = 72 AND OSN.OBJ_ID = L15.OBJ_ID AND OSN.IS_DEL = 0 AND OSN.LISTVAL_ID = 934
        JOIN VALD D73 ON D73.PARAM_ID = 73 AND D73.OBJ_ID = L15.OBJ_ID AND D73.IS_DEL = 0 AND D73.VAL <= CURRENT_DATE
        LEFT JOIN VALD D74 ON D74.PARAM_ID = 74 AND D74.OBJ_ID = L15.OBJ_ID AND D74.IS_DEL = 0
        WHERE (SELECT SORT_ORDER FROM DO_FUNC(LP13.PARENT_ID, 400)) = 2 AND ((D74.VAL IS NULL) OR (D74.VAL >= CURRENT_DATE))
        INTO :TEACHER_ID, :POST_ID
    DO
    BEGIN
        N   = N + 1;
        N0  = N;
        X1  = '';
        X2  = '';
        X3  = '';
        DTQ = NULL;
        DTA = NULL;
        OBJ_ID = NULL;

        SELECT CAPTION FROM OBJECT_CAPTION_GET(:TEACHER_ID) INTO :FIO;
        SELECT CAPTION FROM OBJECT_CAPTION_GET(:POST_ID)    INTO :POST;

        SELECT MAX(D310.VAL)
        FROM LINKS L36
        JOIN VALD D310 ON D310.PARAM_ID = 310 AND D310.OBJ_ID = L36.OBJ_ID AND D310.IS_DEL = 0
        WHERE L36.PARENT_ID = :TEACHER_ID AND L36.OBJ_TYPE_ID = 36 AND L36.DATE_DEL IS NULL
        INTO  :DTQ;

        SELECT MAX(D544.VAL)
        FROM LINKS L34
        JOIN VALD D544 ON D544.PARAM_ID = 544 AND D544.OBJ_ID = L34.OBJ_ID AND D544.IS_DEL = 0
        WHERE L34.PARENT_ID = :TEACHER_ID AND L34.OBJ_TYPE_ID = 34 AND L34.DATE_DEL IS NULL
        INTO  :DTA;

        FOR
            SELECT L.OBJ_ID
            FROM LINKS L
            JOIN VALI V ON V.PARAM_ID = 618 AND V.OBJ_ID = L.OBJ_ID AND V.VAL = :CURR_YEAR + 1 AND V.IS_DEL = 0
            WHERE L.PARENT_ID = :TEACHER_ID AND L.OBJ_TYPE_ID = 100 AND L.DATE_DEL IS NULL
            INTO :OBJ_ID
        DO
        BEGIN
            SELECT V FROM VAL_GET(:OBJ_ID, 616) INTO :FRM;
            SELECT V FROM VAL_GET(:OBJ_ID, 617) INTO :DPO;
            IF (X1 = '') THEN X1 = FRM || ' - ' || DPO || '.'; ELSE X1 = FRM || ' - ' || DPO  || '.' || ASCII_CHAR(10) || ASCII_CHAR(10) || X1;
        END

        FOR
            SELECT L.OBJ_ID
            FROM LINKS L
            JOIN VALI V ON V.PARAM_ID = 618 AND V.OBJ_ID = L.OBJ_ID AND V.VAL = :CURR_YEAR + 2 AND V.IS_DEL = 0
            WHERE L.PARENT_ID = :TEACHER_ID AND L.OBJ_TYPE_ID = 100 AND L.DATE_DEL IS NULL
            INTO :OBJ_ID
        DO
        BEGIN
            SELECT V FROM VAL_GET(:OBJ_ID, 616) INTO :FRM;
            SELECT V FROM VAL_GET(:OBJ_ID, 617) INTO :DPO;
            IF (X2 = '') THEN X2 = FRM || ' - ' || DPO || '.'; ELSE X2 = FRM || ' - ' || DPO  || '.' || ASCII_CHAR(10) || ASCII_CHAR(10) || X2;
        END

        FOR
            SELECT L.OBJ_ID
            FROM LINKS L
            JOIN VALI V ON V.PARAM_ID = 618 AND V.OBJ_ID = L.OBJ_ID AND V.VAL = :CURR_YEAR + 3 AND V.IS_DEL = 0
            WHERE L.PARENT_ID = :TEACHER_ID AND L.OBJ_TYPE_ID = 100 AND L.DATE_DEL IS NULL
            INTO :OBJ_ID
        DO
        BEGIN
            SELECT V FROM VAL_GET(:OBJ_ID, 616) INTO :FRM;
            SELECT V FROM VAL_GET(:OBJ_ID, 617) INTO :DPO;
            IF (X3 = '') THEN X3 = FRM || ' - ' || DPO || '.'; ELSE X3 = FRM || ' - ' || DPO  || '.' || ASCII_CHAR(10) || ASCII_CHAR(10) || X3;
        END

        SUSPEND;
    END

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_SPB_QUAL_OU_1SV (
    I$OBJ_ID BIGINT)
RETURNS (
    N0 VARCHAR(4),
    X VARCHAR(4),
    X1 INTEGER,
    X2 INTEGER,
    X3 INTEGER,
    Z1 INTEGER,
    Z2 INTEGER,
    Z3 INTEGER)
AS
declare variable CURR_YEAR smallint;
declare variable TEACHER_ID bigint;
declare variable X0 integer;
BEGIN

    CURR_YEAR = EXTRACT(YEAR FROM CURRENT_TIMESTAMP);

    N0  = '';
    X   = '';
    X1  = CURR_YEAR + 1;
    X2  = CURR_YEAR + 2;
    X3  = CURR_YEAR + 3;
    Z1  = CURR_YEAR + 1;
    Z2  = CURR_YEAR + 2;
    Z3  = CURR_YEAR + 3;

    SUSPEND;

    N0 = 1; X0 = 0; X1 = 0; X2 = 0; X3 = 0;

    FOR
        SELECT L14.OBJ_ID
        FROM (
            SELECT DISTINCT L14.OBJ_ID
            FROM LINKS L14
            WHERE L14.DATE_DEL IS NULL AND L14.OBJ_TYPE_ID = 14 AND L14.PARENT_ID IN (
                SELECT OBJ_ID
                FROM LINKS L
                WHERE L.PARENT_ID = :I$OBJ_ID AND L.DATE_DEL IS NULL AND L.OBJ_TYPE_ID = 211
                UNION ALL
                SELECT :I$OBJ_ID
                FROM RDB$DATABASE
                )
        ) L14
        JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.DATE_DEL IS NULL
        JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
        JOIN VALL OSN ON OSN.PARAM_ID = 72 AND OSN.OBJ_ID = L15.OBJ_ID AND OSN.IS_DEL = 0 AND OSN.LISTVAL_ID = 934
        JOIN VALD D73 ON D73.PARAM_ID = 73 AND D73.OBJ_ID = L15.OBJ_ID AND D73.IS_DEL = 0 AND D73.VAL <= CURRENT_DATE
        LEFT JOIN VALD D74 ON D74.PARAM_ID = 74 AND D74.OBJ_ID = L15.OBJ_ID AND D74.IS_DEL = 0
        WHERE (SELECT SORT_ORDER FROM DO_FUNC(LP13.PARENT_ID, 400)) = 2 AND ((D74.VAL IS NULL) OR (D74.VAL >= CURRENT_DATE))
        INTO :TEACHER_ID
    DO
    BEGIN
        X0 = X0 + 1;

        SELECT COUNT(*) + :X1
        FROM LINKS L
        JOIN VALI V ON V.PARAM_ID = 618 AND V.OBJ_ID = L.OBJ_ID AND V.VAL = :CURR_YEAR + 1 AND V.IS_DEL = 0
        WHERE L.PARENT_ID = :TEACHER_ID AND L.OBJ_TYPE_ID = 100 AND L.DATE_DEL IS NULL
        INTO :X1;

        SELECT COUNT(*) + :X2
        FROM LINKS L
        JOIN VALI V ON V.PARAM_ID = 618 AND V.OBJ_ID = L.OBJ_ID AND V.VAL = :CURR_YEAR + 2 AND V.IS_DEL = 0
        WHERE L.PARENT_ID = :TEACHER_ID AND L.OBJ_TYPE_ID = 100 AND L.DATE_DEL IS NULL
        INTO :X2;

        SELECT COUNT(*) + :X3
        FROM LINKS L
        JOIN VALI V ON V.PARAM_ID = 618 AND V.OBJ_ID = L.OBJ_ID AND V.VAL = :CURR_YEAR + 3 AND V.IS_DEL = 0
        WHERE L.PARENT_ID = :TEACHER_ID AND L.OBJ_TYPE_ID = 100 AND L.DATE_DEL IS NULL
        INTO :X3;
    END

    X = X0;

    IF (X0 > 0) THEN BEGIN
        Z1 = X1 * 100 / X0;
        Z2 = X2 * 100 / X0;
        Z3 = X3 * 100 / X0;
    END

    SUSPEND;

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_SPB_QUAL_OU_2 (
    I$OBJ_ID BIGINT)
RETURNS (
    N0 VARCHAR(4),
    FIO VARCHAR(1000),
    POST VARCHAR(1000),
    X1 VARCHAR(1000),
    X2 VARCHAR(1000),
    X3 VARCHAR(1000))
AS
declare variable N smallint;
declare variable CURR_YEAR smallint;
declare variable TEACHER_ID bigint;
declare variable POST_ID bigint;
declare variable X varchar(1000);
BEGIN

    CURR_YEAR = EXTRACT(YEAR FROM CURRENT_TIMESTAMP);

    N   = 0;
    N0  = '';
    FIO = '';
    POST= '';
    X1  = CURR_YEAR + 1;
    X2  = CURR_YEAR + 2;
    X3  = CURR_YEAR + 3;

    SUSPEND;

    FOR
        SELECT L14.OBJ_ID, LP13.PARENT_ID, C.CAPTION
        FROM (
            SELECT DISTINCT L14.OBJ_ID
            FROM LINKS L14
            WHERE L14.DATE_DEL IS NULL AND L14.OBJ_TYPE_ID = 14 AND L14.PARENT_ID IN (
                SELECT OBJ_ID
                FROM LINKS L
                WHERE L.PARENT_ID = :I$OBJ_ID AND L.DATE_DEL IS NULL AND L.OBJ_TYPE_ID = 211
                UNION ALL
                SELECT :I$OBJ_ID
                FROM RDB$DATABASE
                )
        ) L14
        JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
        JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
        JOIN VALL OSN ON OSN.PARAM_ID = 72 AND OSN.OBJ_ID = L15.OBJ_ID AND OSN.IS_DEL = 0 AND OSN.LISTVAL_ID = 934
        JOIN VALD D73 ON D73.PARAM_ID = 73 AND D73.OBJ_ID = L15.OBJ_ID AND D73.IS_DEL = 0 AND D73.VAL <= CURRENT_DATE
        LEFT JOIN VALD D74 ON D74.PARAM_ID = 74 AND D74.OBJ_ID = L15.OBJ_ID AND D74.IS_DEL = 0
        LEFT JOIN OBJECT_CAPTION_GET(L14.OBJ_ID) C ON 1 = 1
        WHERE (SELECT SORT_ORDER FROM DO_FUNC(LP13.PARENT_ID, 400)) = 2 AND ((D74.VAL IS NULL) OR (D74.VAL >= CURRENT_DATE))
        ORDER BY 3
        INTO :TEACHER_ID, :POST_ID, :FIO
    DO
    BEGIN
        N = N + 1;
        N0 = N;
        X1 = ''; X2 = ''; X3 = '';

        SELECT CAPTION FROM OBJECT_CAPTION_GET(:POST_ID) INTO :POST;

        FOR
            SELECT S.VAL
            FROM LINKS L
            JOIN VALI V ON V.PARAM_ID = 621 AND V.OBJ_ID = L.OBJ_ID AND V.VAL = :CURR_YEAR + 1 AND V.IS_DEL = 0
            JOIN VALS S ON S.PARAM_ID = 620 AND S.OBJ_ID = L.OBJ_ID AND S.IS_DEL = 0
            WHERE L.PARENT_ID = :TEACHER_ID AND L.DATE_DEL IS NULL AND L.OBJ_TYPE_ID = 101
            INTO  :X
        DO
        BEGIN
            IF (X1 = '') THEN X1 = X || '.'; ELSE X1 = X || '; ' || X1;
        END

        FOR
            SELECT S.VAL
            FROM LINKS L
            JOIN VALI V ON V.PARAM_ID = 621 AND V.OBJ_ID = L.OBJ_ID AND V.VAL = :CURR_YEAR + 2 AND V.IS_DEL = 0
            JOIN VALS S ON S.PARAM_ID = 620 AND S.OBJ_ID = L.OBJ_ID AND S.IS_DEL = 0
            WHERE L.PARENT_ID = :TEACHER_ID AND L.DATE_DEL IS NULL AND L.OBJ_TYPE_ID = 101
            INTO  :X
        DO
        BEGIN
            IF (X2 = '') THEN X2 = X || '.'; ELSE X2 = X || '; ' || X2;
        END

        FOR
            SELECT S.VAL
            FROM LINKS L
            JOIN VALI V ON V.PARAM_ID = 621 AND V.OBJ_ID = L.OBJ_ID AND V.VAL = :CURR_YEAR + 3 AND V.IS_DEL = 0
            JOIN VALS S ON S.PARAM_ID = 620 AND S.OBJ_ID = L.OBJ_ID AND S.IS_DEL = 0
            WHERE L.PARENT_ID = :TEACHER_ID AND L.DATE_DEL IS NULL AND L.OBJ_TYPE_ID = 101
            INTO  :X
        DO
        BEGIN
            IF (X3 = '') THEN X3 = X || '.'; ELSE X3 = X || '; ' || X3;
        END

        SUSPEND;
    END

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_SPB_QUAL_REQUEST_LIST (
    I$DPO VARCHAR(4000),
    I$YEAR INTEGER,
    I$USER_ID BIGINT)
RETURNS (
    N INTEGER,
    DISTR VARCHAR(1000),
    OU VARCHAR(1000),
    POST VARCHAR(1000),
    TEACHER VARCHAR(1000),
    OP VARCHAR(4000))
AS
declare variable TEACHER_ID bigint;
declare variable OU_ID bigint;
declare variable DISTR_ID bigint;
BEGIN
    N = 0;
    FOR SELECT O14.OBJ_ID, O2.OBJ_ID, O111.OBJ_ID, V615.VAL
        FROM OBJECTS O100                                                                     /* request */
        INNER JOIN LINKS     L14 ON  L14.OBJ_ID = O100.OBJ_ID    AND  L14.DATE_DEL IS NULL
        INNER JOIN OBJECTS   O14 ON  O14.OBJ_ID = L14.PARENT_ID  AND  O14.TYPE_ID = 14        /* teacher */
        INNER JOIN LINKS      L2 ON   L2.OBJ_ID = O14.OBJ_ID     AND   L2.DATE_DEL IS NULL
        INNER JOIN OBJECTS    O2 ON   O2.OBJ_ID = L2.PARENT_ID   AND   O2.TYPE_ID = 2         /* OU */
        INNER JOIN LINKS    L111 ON L111.OBJ_ID = O2.OBJ_ID      AND L111.DATE_DEL IS NULL
        INNER JOIN OBJECTS  O111 ON O111.OBJ_ID = L111.PARENT_ID AND O111.TYPE_ID = 111       /* district */
        INNER JOIN VALS     V615 ON V615.PARAM_ID = 615          AND V615.OBJ_ID = O100.OBJ_ID   AND V615.IS_DEL = 0
        INNER JOIN VALS     V618 ON V618.PARAM_ID = 618          AND V618.OBJ_ID = O100.OBJ_ID   AND V618.IS_DEL = 0
        INNER JOIN VALS     V617 ON V617.PARAM_ID = 617          AND V617.OBJ_ID = O100.OBJ_ID   AND V617.IS_DEL = 0
        WHERE O100.TYPE_ID = 100
        AND   V618.VAL = :I$YEAR
        AND   V617.VAL = :I$DPO
        INTO :TEACHER_ID, :OU_ID, :DISTR_ID, :OP
    DO
    BEGIN
        SELECT CAPTION      FROM OBJECT_CAPTION_GET(:DISTR_ID,NULL,NULL,:I$USER_ID)   INTO :DISTR;
        SELECT CAPTION      FROM OBJECT_CAPTION_GET(:OU_ID,NULL,NULL,:I$USER_ID)      INTO :OU;
        SELECT CAPTION      FROM OBJECT_CAPTION_GET(:TEACHER_ID,NULL,NULL,:I$USER_ID) INTO :TEACHER;
        SELECT TEACHER_POST FROM R_SPB_TEACHER_POST(:TEACHER_ID,:I$USER_ID) INTO :POST;
        N = N + 1;
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_SPB_SKILL_0 (
    I$X SMALLINT = 10)
RETURNS (
    N0 VARCHAR(4),
    DPO VARCHAR(1000),
    X5 NUMERIC(14,2),
    X4 NUMERIC(14,2),
    X3 NUMERIC(14,2),
    X2 NUMERIC(14,2),
    X1 NUMERIC(14,2),
    X0 NUMERIC(14,2))
AS
declare variable N smallint;
declare variable CURR_YEAR smallint;
declare variable OBJ_YEAR smallint;
declare variable H float;
declare variable H5 float;
declare variable H4 float;
declare variable H3 float;
declare variable H2 float;
declare variable H1 float;
declare variable H0 float;
declare variable C5 float;
declare variable C4 float;
declare variable C3 float;
declare variable C2 float;
declare variable C1 float;
declare variable C0 float;
declare variable T5 integer;
declare variable T4 integer;
declare variable T3 integer;
declare variable T2 integer;
declare variable T1 integer;
declare variable T0 integer;
declare variable Q5 integer;
declare variable Q4 integer;
declare variable Q3 integer;
declare variable Q2 integer;
declare variable Q1 integer;
declare variable Q0 integer;
declare variable S5 numeric(14,2);
declare variable S4 numeric(14,2);
declare variable S3 numeric(14,2);
declare variable S2 numeric(14,2);
declare variable S1 numeric(14,2);
declare variable S0 numeric(14,2);
BEGIN
    /*
        I$X = 10  -  hour
        I$X = 20  -  pupil
        I$X = 30  -  hour / pupil
        I$X = 40  -  percent

        H - DPO total hours
        C - DPO total qualified
        T - total teachers in all OU
        Q - total qualified in all OU

    */

    CURR_YEAR = EXTRACT(YEAR FROM CURRENT_TIMESTAMP);

    N   = 0;
    N0  = '';
    DPO = '';
    X5  = CURR_YEAR - 4;
    X4  = CURR_YEAR - 3;
    X3  = CURR_YEAR - 2;
    X2  = CURR_YEAR - 1;
    X1  = CURR_YEAR - 0;
    X0  = CURR_YEAR + 1;
    S5  = 0;
    S4  = 0;
    S3  = 0;
    S2  = 0;
    S1  = 0;
    S0  = 0;
    SUSPEND;

    IF (I$X = 30) THEN     /* total teachers in all OU */
    BEGIN
        SELECT T FROM R_SPB_TOTAL_TEACHERS(:CURR_YEAR - 4) INTO :T5;
        SELECT T FROM R_SPB_TOTAL_TEACHERS(:CURR_YEAR - 3) INTO :T4;
        SELECT T FROM R_SPB_TOTAL_TEACHERS(:CURR_YEAR - 2) INTO :T3;
        SELECT T FROM R_SPB_TOTAL_TEACHERS(:CURR_YEAR - 1) INTO :T2;
        SELECT T FROM R_SPB_TOTAL_TEACHERS(:CURR_YEAR - 0) INTO :T1;
        T0 = T1+0.6*(T2-T5)+0.2*(T3-T4);
    END

    IF (I$X = 40) THEN     /* total qualified in all OU */
    BEGIN
        SELECT T FROM R_SPB_TOTAL_QUALIFIED(:CURR_YEAR - 4) INTO :Q5;
        SELECT T FROM R_SPB_TOTAL_QUALIFIED(:CURR_YEAR - 3) INTO :Q4;
        SELECT T FROM R_SPB_TOTAL_QUALIFIED(:CURR_YEAR - 2) INTO :Q3;
        SELECT T FROM R_SPB_TOTAL_QUALIFIED(:CURR_YEAR - 1) INTO :Q2;
        SELECT T FROM R_SPB_TOTAL_QUALIFIED(:CURR_YEAR - 0) INTO :Q1;
        Q0 = Q1+0.6*(Q2-Q5)+0.2*(Q3-Q4);
    END

    FOR
        SELECT DISTINCT
               R.VAL
        FROM LISTVALS LV

        JOIN RES R
        ON R.RES_ID = LV.RES_ID
        AND R.LANG_CODE = 'RU'

        JOIN VALS DPO
        ON DPO.PARAM_ID = 304
        AND DPO.VAL = R.VAL
        AND DPO.IS_DEL = 0

        WHERE LV.LIST_ID = 151
        ORDER BY LV.SORT_ORDER
        INTO :DPO
    DO
    BEGIN
        X5 = 0; X4 = 0; X3 = 0; X2 = 0; X1 = 0; X0 = 0;
        C5 = 0; C4 = 0; C3 = 0; C2 = 0; C1 = 0; C0 = 0;
        H5 = 0; H4 = 0; H3 = 0; H2 = 0; H1 = 0; H0 = 0;

        FOR
            SELECT EXTRACT(YEAR FROM DT.VAL),
                   HR.VAL
            FROM VALS DPO

            JOIN OBJECTS O36
            ON O36.OBJ_ID = DPO.OBJ_ID
            AND O36.TYPE_ID = 36

            JOIN LINKS LNK
            ON LNK.OBJ_ID = O36.OBJ_ID
            AND LNK.DATE_DEL IS NULL

            JOIN OBJECTS O14
            ON O14.OBJ_ID = LNK.PARENT_ID
            AND O14.TYPE_ID = 14

            JOIN VALD DT
            ON DT.PARAM_ID = 310
            AND O36.OBJ_ID = DT.OBJ_ID
            AND  DT.IS_DEL = 0

            JOIN VALI HR
            ON HR.PARAM_ID = 306
            AND O36.OBJ_ID = HR.OBJ_ID
            AND HR.IS_DEL = 0

            WHERE DPO.PARAM_ID = 304
            AND DPO.VAL = :DPO
            AND DPO.IS_DEL = 0
            INTO :OBJ_YEAR, :H
        DO
        BEGIN
            IF (OBJ_YEAR = CURR_YEAR - 4) THEN
            BEGIN
                H5 = H5 + H;
                C5 = C5 + 1;
            END
            IF (OBJ_YEAR = CURR_YEAR - 3) THEN
            BEGIN
                H4 = H4 + H;
                C4 = C4 + 1;
            END
            IF (OBJ_YEAR = CURR_YEAR - 2) THEN
            BEGIN
                H3 = H3 + H;
                C3 = C3 + 1;
            END
            IF (OBJ_YEAR = CURR_YEAR - 1) THEN
            BEGIN
                H2 = H2 + H;
                C2 = C2 + 1;
            END
            IF (OBJ_YEAR = CURR_YEAR - 0) THEN
            BEGIN
                H1 = H1 + H;
                C1 = C1 + 1;
            END
        END

        IF ((C5 > 0) OR (C4 > 0) OR (C3 > 0) OR (C2 > 0) OR (C1 > 0)) THEN
        BEGIN
            N  = N + 1;
            N0 = N;
            C0 = C1+0.6*(C2-C5)+0.2*(C3-C4);
            H0 = H1+0.6*(H2-H5)+0.2*(H3-H4);
            IF (C0 < 0) THEN C0 = 0;
            IF (H0 < 0) THEN H0 = 0;

            IF (I$X = 10) THEN
            BEGIN
                X5 = H5; X4 = H4; X3 = H3; X2 = H2; X1 = H1; X0 = H0;
            END

            IF (I$X = 20) THEN
            BEGIN
                X5 = C5; X4 = C4; X3 = C3; X2 = C2; X1 = C1; X0 = C0;
            END

            IF (I$X = 30) THEN
            BEGIN
                IF (T5 > 0) THEN X5 = H5/T5;
                IF (T4 > 0) THEN X4 = H4/T4;
                IF (T3 > 0) THEN X3 = H3/T3;
                IF (T2 > 0) THEN X2 = H2/T2;
                IF (T1 > 0) THEN X1 = H1/T1;
                IF (T0 > 0) THEN X0 = H0/T0;
            END

            IF (I$X = 40) THEN
            BEGIN
                IF (Q5 > 0) THEN X5 = 100*C5/Q5;
                IF (Q4 > 0) THEN X4 = 100*C4/Q4;
                IF (Q3 > 0) THEN X3 = 100*C3/Q3;
                IF (Q2 > 0) THEN X2 = 100*C2/Q2;
                IF (Q1 > 0) THEN X1 = 100*C1/Q1;
                IF (Q0 > 0) THEN X0 = 100*C0/Q0;
            END

            S5 = S5 + X5;  S4 = S4 + X4;  S3 = S3 + X3;  S2 = S2 + X2;  S1 = S1 + X1;  S0 = S0 + X0;

            SUSPEND;
        END
    END

    N0 = ''; DPO = 'ИТОГО:';
    X5 = S5;  X4 = S4;  X3 = S3;  X2 = S2;  X1 = S1;  X0 = S0;
    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_SPB_SKILL_1_VID (
    I$X SMALLINT = 10,
    I$USER_ID BIGINT = 1)
RETURNS (
    N0 VARCHAR(4),
    DPO VARCHAR(1000),
    TOU VARCHAR(1000),
    VOU VARCHAR(1000),
    X5 NUMERIC(14,2),
    X4 NUMERIC(14,2),
    X3 NUMERIC(14,2),
    X2 NUMERIC(14,2),
    X1 NUMERIC(14,2),
    X0 NUMERIC(14,2))
AS
declare variable N smallint;
declare variable CURR_YEAR smallint;
declare variable VID_ID bigint;
declare variable TOU_VAL varchar(1000);
declare variable VOU_VAL varchar(1000);
declare variable CURR_VID bigint;
declare variable OBJ_YEAR smallint;
declare variable H float;
declare variable H5 float;
declare variable H4 float;
declare variable H3 float;
declare variable H2 float;
declare variable H1 float;
declare variable H0 float;
declare variable C5 float;
declare variable C4 float;
declare variable C3 float;
declare variable C2 float;
declare variable C1 float;
declare variable C0 float;
declare variable T5 integer;
declare variable T4 integer;
declare variable T3 integer;
declare variable T2 integer;
declare variable T1 integer;
declare variable T0 integer;
declare variable Q5 integer;
declare variable Q4 integer;
declare variable Q3 integer;
declare variable Q2 integer;
declare variable Q1 integer;
declare variable Q0 integer;
declare variable LANG_CODE varchar(2);
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :LANG_CODE;

    /*
        I$X = 10  -  hour
        I$X = 20  -  pupil
        I$X = 30  -  hour / pupil
        I$X = 40  -  percent

        H - DPO total hours
        C - DPO total qualified
        T - total teachers in all OU
        Q - total qualified in all OU

    */

    CURR_YEAR = EXTRACT(YEAR FROM CURRENT_TIMESTAMP);

    N   = 0;
    N0  = '';
    DPO = '';
    X5  = CURR_YEAR - 4;
    X4  = CURR_YEAR - 3;
    X3  = CURR_YEAR - 2;
    X2  = CURR_YEAR - 1;
    X1  = CURR_YEAR - 0;
    X0  = CURR_YEAR + 1;

    SUSPEND;

    IF (I$X = 30) THEN     /* total teachers in all OU */
    BEGIN
        SELECT T FROM R_SPB_TOTAL_TEACHERS(:CURR_YEAR - 4) INTO :T5;
        SELECT T FROM R_SPB_TOTAL_TEACHERS(:CURR_YEAR - 3) INTO :T4;
        SELECT T FROM R_SPB_TOTAL_TEACHERS(:CURR_YEAR - 2) INTO :T3;
        SELECT T FROM R_SPB_TOTAL_TEACHERS(:CURR_YEAR - 1) INTO :T2;
        SELECT T FROM R_SPB_TOTAL_TEACHERS(:CURR_YEAR - 0) INTO :T1;
        T0 = T1+0.6*(T2-T5)+0.2*(T3-T4);
    END

    IF (I$X = 40) THEN     /* total qualified in all OU */
    BEGIN
        SELECT T FROM R_SPB_TOTAL_QUALIFIED(:CURR_YEAR - 4) INTO :Q5;
        SELECT T FROM R_SPB_TOTAL_QUALIFIED(:CURR_YEAR - 3) INTO :Q4;
        SELECT T FROM R_SPB_TOTAL_QUALIFIED(:CURR_YEAR - 2) INTO :Q3;
        SELECT T FROM R_SPB_TOTAL_QUALIFIED(:CURR_YEAR - 1) INTO :Q2;
        SELECT T FROM R_SPB_TOTAL_QUALIFIED(:CURR_YEAR - 0) INTO :Q1;
        Q0 = Q1+0.6*(Q2-Q5)+0.2*(Q3-Q4);
    END

    FOR
        SELECT DISTINCT
               R.VAL
        FROM LISTVALS LV

        JOIN RES R
        ON R.RES_ID = LV.RES_ID
        AND R.LANG_CODE = 'RU'

        JOIN VALS DPO
        ON DPO.PARAM_ID = 304
        AND DPO.VAL = R.VAL
        AND DPO.IS_DEL = 0

        WHERE LV.LIST_ID = 151
        ORDER BY LV.SORT_ORDER
        INTO :DPO
    DO
    BEGIN

        CURR_VID = 0;
        N0 = '';
        X5 = 0; X4 = 0; X3 = 0; X2 = 0; X1 = 0; X0 = 0;
        C5 = 0; C4 = 0; C3 = 0; C2 = 0; C1 = 0; C0 = 0;
        H5 = 0; H4 = 0; H3 = 0; H2 = 0; H1 = 0; H0 = 0;

        FOR
            SELECT EXTRACT(YEAR FROM DT.VAL),
                   HR.VAL,
                   RT.VAL,
                   RD.VAL,
                   VD.LISTVAL_ID

            FROM VALS DPO

            JOIN OBJECTS O36
            ON O36.OBJ_ID = DPO.OBJ_ID
            AND O36.TYPE_ID = 36

            JOIN LINKS LNK
            ON LNK.OBJ_ID = O36.OBJ_ID
            AND LNK.DATE_DEL IS NULL

            JOIN OBJECTS O14
            ON O14.OBJ_ID = LNK.PARENT_ID
            AND O14.TYPE_ID = 14

            JOIN LINKS LN2
            ON LN2.OBJ_ID = O14.OBJ_ID
            AND LN2.DATE_DEL IS NULL

            JOIN OBJECTS O2
            ON O2.OBJ_ID = LN2.PARENT_ID
            AND O2.TYPE_ID = 2

            JOIN VALL VOU
            ON VOU.PARAM_ID = 10
            AND VOU.OBJ_ID = O2.OBJ_ID
            AND VOU.IS_DEL = 0

            JOIN VALL TOU
            ON TOU.PARAM_ID = 11
            AND TOU.OBJ_ID = O2.OBJ_ID
            AND TOU.IS_DEL = 0

            JOIN VALD DT
            ON DT.PARAM_ID = 310
            AND O36.OBJ_ID = DT.OBJ_ID
            AND DT.IS_DEL = 0

            JOIN VALI HR
            ON HR.PARAM_ID = 306
            AND O36.OBJ_ID = HR.OBJ_ID
            AND HR.IS_DEL = 0

            JOIN LISTVALS VD
            ON VD.LISTVAL_ID = VOU.LISTVAL_ID

            JOIN LISTVALS VT
            ON VT.LISTVAL_ID = TOU.LISTVAL_ID

            LEFT JOIN RES_GET(VD.RES_ID,  :LANG_CODE) RD ON 1=1
            LEFT JOIN RES_GET(VT.RES_ID,  :LANG_CODE) RT ON 1=1

            WHERE DPO.PARAM_ID = 304
            AND DPO.VAL = :DPO
            AND DPO.IS_DEL = 0

            ORDER BY VD.SORT_ORDER
            INTO :OBJ_YEAR,
                 :H,
                 :TOU_VAL,
                 :VOU_VAL,
                 :VID_ID
        DO
        BEGIN
            IF (N0 = '') THEN
            BEGIN
                N0 = '-';
                CURR_VID = VID_ID;
                TOU = TOU_VAL;
                VOU = VOU_VAL;
            END

            IF (CURR_VID <> VID_ID) THEN
            BEGIN

                IF ((C5 > 0) OR (C4 > 0) OR (C3 > 0) OR (C2 > 0) OR (C1 > 0)) THEN
                BEGIN
                    N  = N + 1;
                    N0 = N;
                    C0 = C1+0.6*(C2-C5)+0.2*(C3-C4);
                    H0 = H1+0.6*(H2-H5)+0.2*(H3-H4);
                    IF (C0 < 0) THEN C0 = 0;
                    IF (H0 < 0) THEN H0 = 0;

                    IF (I$X = 10) THEN
                    BEGIN
                        X5 = H5; X4 = H4; X3 = H3; X2 = H2; X1 = H1; X0 = H0;
                    END

                    IF (I$X = 20) THEN
                    BEGIN
                        X5 = C5; X4 = C4; X3 = C3; X2 = C2; X1 = C1; X0 = C0;
                    END

                    IF (I$X = 30) THEN
                    BEGIN
                        IF (T5 > 0) THEN X5 = H5/T5;
                        IF (T4 > 0) THEN X4 = H4/T4;
                        IF (T3 > 0) THEN X3 = H3/T3;
                        IF (T2 > 0) THEN X2 = H2/T2;
                        IF (T1 > 0) THEN X1 = H1/T1;
                        IF (T0 > 0) THEN X0 = H0/T0;
                    END

                    IF (I$X = 40) THEN
                    BEGIN
                        IF (Q5 > 0) THEN X5 = 100*C5/Q5;
                        IF (Q4 > 0) THEN X4 = 100*C4/Q4;
                        IF (Q3 > 0) THEN X3 = 100*C3/Q3;
                        IF (Q2 > 0) THEN X2 = 100*C2/Q2;
                        IF (Q1 > 0) THEN X1 = 100*C1/Q1;
                        IF (Q0 > 0) THEN X0 = 100*C0/Q0;
                    END

                    SUSPEND;
                END

            /*    DPO = '';   */
                X5 = 0; X4 = 0; X3 = 0; X2 = 0; X1 = 0; X0 = 0;
                C5 = 0; C4 = 0; C3 = 0; C2 = 0; C1 = 0; C0 = 0;
                H5 = 0; H4 = 0; H3 = 0; H2 = 0; H1 = 0; H0 = 0;
                CURR_VID = VID_ID;
                TOU = TOU_VAL;
                VOU = VOU_VAL;
            END

            IF (OBJ_YEAR = CURR_YEAR - 4) THEN
            BEGIN
                H5 = H5 + H;
                C5 = C5 + 1;
            END
            IF (OBJ_YEAR = CURR_YEAR - 3) THEN
            BEGIN
                H4 = H4 + H;
                C4 = C4 + 1;
            END
            IF (OBJ_YEAR = CURR_YEAR - 2) THEN
            BEGIN
                H3 = H3 + H;
                C3 = C3 + 1;
            END
            IF (OBJ_YEAR = CURR_YEAR - 1) THEN
            BEGIN
                H2 = H2 + H;
                C2 = C2 + 1;
            END
            IF (OBJ_YEAR = CURR_YEAR - 0) THEN
            BEGIN
                H1 = H1 + H;
                C1 = C1 + 1;
            END
        END

        /* duble */
                IF ((C5 > 0) OR (C4 > 0) OR (C3 > 0) OR (C2 > 0) OR (C1 > 0)) THEN
                BEGIN
                    N  = N + 1;
                    N0 = N;
                    C0 = C1+0.6*(C2-C5)+0.2*(C3-C4);
                    H0 = H1+0.6*(H2-H5)+0.2*(H3-H4);
                    IF (C0 < 0) THEN C0 = 0;
                    IF (H0 < 0) THEN H0 = 0;

                    IF (I$X = 10) THEN
                    BEGIN
                        X5 = H5; X4 = H4; X3 = H3; X2 = H2; X1 = H1; X0 = H0;
                    END

                    IF (I$X = 20) THEN
                    BEGIN
                        X5 = C5; X4 = C4; X3 = C3; X2 = C2; X1 = C1; X0 = C0;
                    END

                    IF (I$X = 30) THEN
                    BEGIN
                        IF (T5 > 0) THEN X5 = H5/T5;
                        IF (T4 > 0) THEN X4 = H4/T4;
                        IF (T3 > 0) THEN X3 = H3/T3;
                        IF (T2 > 0) THEN X2 = H2/T2;
                        IF (T1 > 0) THEN X1 = H1/T1;
                        IF (T0 > 0) THEN X0 = H0/T0;
                    END

                    IF (I$X = 40) THEN
                    BEGIN
                        IF (Q5 > 0) THEN X5 = 100*C5/Q5;
                        IF (Q4 > 0) THEN X4 = 100*C4/Q4;
                        IF (Q3 > 0) THEN X3 = 100*C3/Q3;
                        IF (Q2 > 0) THEN X2 = 100*C2/Q2;
                        IF (Q1 > 0) THEN X1 = 100*C1/Q1;
                        IF (Q0 > 0) THEN X0 = 100*C0/Q0;
                    END

                    SUSPEND;
                END
        /* duble */

    END

    /* TOTAL */


        CURR_VID = 0;
        N0 = ''; N = 0;
        DPO = 'ИТОГО:';
        X5 = 0; X4 = 0; X3 = 0; X2 = 0; X1 = 0; X0 = 0;
        C5 = 0; C4 = 0; C3 = 0; C2 = 0; C1 = 0; C0 = 0;
        H5 = 0; H4 = 0; H3 = 0; H2 = 0; H1 = 0; H0 = 0;

        FOR SELECT EXTRACT(YEAR FROM DT.VAL), HR.VAL, RT.VAL, RD.VAL, VD.LISTVAL_ID
            FROM VALS DPO
            INNER JOIN OBJECTS O36 ON O36.OBJ_ID = DPO.OBJ_ID       AND O36.TYPE_ID = 36
            INNER JOIN LINKS   LNK ON LNK.OBJ_ID = O36.OBJ_ID       AND LNK.DATE_DEL IS NULL
            INNER JOIN OBJECTS O14 ON O14.OBJ_ID = LNK.PARENT_ID    AND O14.TYPE_ID = 14
            INNER JOIN LINKS   LN2 ON LN2.OBJ_ID = O14.OBJ_ID       AND LN2.DATE_DEL IS NULL
            INNER JOIN OBJECTS  O2 ON  O2.OBJ_ID = LN2.PARENT_ID    AND  O2.TYPE_ID = 2
            INNER JOIN VALL    VOU ON VOU.PARAM_ID = 10 AND VOU.OBJ_ID = O2.OBJ_ID  AND VOU.IS_DEL = 0
            INNER JOIN VALL    TOU ON TOU.PARAM_ID = 11 AND TOU.OBJ_ID = O2.OBJ_ID  AND TOU.IS_DEL = 0
            INNER JOIN VALD     DT ON DT.PARAM_ID = 310 AND O36.OBJ_ID = DT.OBJ_ID  AND  DT.IS_DEL = 0
            INNER JOIN VALI     HR ON HR.PARAM_ID = 306 AND O36.OBJ_ID = HR.OBJ_ID  AND  HR.IS_DEL = 0
            INNER JOIN LISTVALS VD ON VD.LISTVAL_ID = VOU.LISTVAL_ID
            INNER JOIN LISTVALS VT ON VT.LISTVAL_ID = TOU.LISTVAL_ID
            LEFT JOIN RES_GET(VD.RES_ID,  :LANG_CODE) RD ON 1=1
            LEFT JOIN RES_GET(VT.RES_ID,  :LANG_CODE) RT ON 1=1
            WHERE DPO.PARAM_ID = 304
            AND DPO.IS_DEL = 0
            ORDER BY VD.SORT_ORDER
            INTO :OBJ_YEAR, :H, :TOU_VAL, :VOU_VAL, :VID_ID
        DO
        BEGIN
            IF (N = 0) THEN
            BEGIN
                N = 1;
                CURR_VID = VID_ID;
                TOU = TOU_VAL;
                VOU = VOU_VAL;
            END

            IF (CURR_VID <> VID_ID) THEN
            BEGIN

                IF ((C5 > 0) OR (C4 > 0) OR (C3 > 0) OR (C2 > 0) OR (C1 > 0)) THEN
                BEGIN
                    N  = N + 1;
                    C0 = C1+0.6*(C2-C5)+0.2*(C3-C4);
                    H0 = H1+0.6*(H2-H5)+0.2*(H3-H4);
                    IF (C0 < 0) THEN C0 = 0;
                    IF (H0 < 0) THEN H0 = 0;

                    IF (I$X = 10) THEN
                    BEGIN
                        X5 = H5; X4 = H4; X3 = H3; X2 = H2; X1 = H1; X0 = H0;
                    END

                    IF (I$X = 20) THEN
                    BEGIN
                        X5 = C5; X4 = C4; X3 = C3; X2 = C2; X1 = C1; X0 = C0;
                    END

                    IF (I$X = 30) THEN
                    BEGIN
                        IF (T5 > 0) THEN X5 = H5/T5;
                        IF (T4 > 0) THEN X4 = H4/T4;
                        IF (T3 > 0) THEN X3 = H3/T3;
                        IF (T2 > 0) THEN X2 = H2/T2;
                        IF (T1 > 0) THEN X1 = H1/T1;
                        IF (T0 > 0) THEN X0 = H0/T0;
                    END

                    IF (I$X = 40) THEN
                    BEGIN
                        IF (Q5 > 0) THEN X5 = 100*C5/Q5;
                        IF (Q4 > 0) THEN X4 = 100*C4/Q4;
                        IF (Q3 > 0) THEN X3 = 100*C3/Q3;
                        IF (Q2 > 0) THEN X2 = 100*C2/Q2;
                        IF (Q1 > 0) THEN X1 = 100*C1/Q1;
                        IF (Q0 > 0) THEN X0 = 100*C0/Q0;
                    END

                    SUSPEND;
                END

            /*    DPO = '';   */
                X5 = 0; X4 = 0; X3 = 0; X2 = 0; X1 = 0; X0 = 0;
                C5 = 0; C4 = 0; C3 = 0; C2 = 0; C1 = 0; C0 = 0;
                H5 = 0; H4 = 0; H3 = 0; H2 = 0; H1 = 0; H0 = 0;
                CURR_VID = VID_ID;
                TOU = TOU_VAL;
                VOU = VOU_VAL;
            END

            IF (OBJ_YEAR = CURR_YEAR - 4) THEN
            BEGIN
                H5 = H5 + H;
                C5 = C5 + 1;
            END
            IF (OBJ_YEAR = CURR_YEAR - 3) THEN
            BEGIN
                H4 = H4 + H;
                C4 = C4 + 1;
            END
            IF (OBJ_YEAR = CURR_YEAR - 2) THEN
            BEGIN
                H3 = H3 + H;
                C3 = C3 + 1;
            END
            IF (OBJ_YEAR = CURR_YEAR - 1) THEN
            BEGIN
                H2 = H2 + H;
                C2 = C2 + 1;
            END
            IF (OBJ_YEAR = CURR_YEAR - 0) THEN
            BEGIN
                H1 = H1 + H;
                C1 = C1 + 1;
            END
        END

        /* duble */
                IF ((C5 > 0) OR (C4 > 0) OR (C3 > 0) OR (C2 > 0) OR (C1 > 0)) THEN
                BEGIN
                    N  = N + 1;
                    C0 = C1+0.6*(C2-C5)+0.2*(C3-C4);
                    H0 = H1+0.6*(H2-H5)+0.2*(H3-H4);
                    IF (C0 < 0) THEN C0 = 0;
                    IF (H0 < 0) THEN H0 = 0;

                    IF (I$X = 10) THEN
                    BEGIN
                        X5 = H5; X4 = H4; X3 = H3; X2 = H2; X1 = H1; X0 = H0;
                    END

                    IF (I$X = 20) THEN
                    BEGIN
                        X5 = C5; X4 = C4; X3 = C3; X2 = C2; X1 = C1; X0 = C0;
                    END

                    IF (I$X = 30) THEN
                    BEGIN
                        IF (T5 > 0) THEN X5 = H5/T5;
                        IF (T4 > 0) THEN X4 = H4/T4;
                        IF (T3 > 0) THEN X3 = H3/T3;
                        IF (T2 > 0) THEN X2 = H2/T2;
                        IF (T1 > 0) THEN X1 = H1/T1;
                        IF (T0 > 0) THEN X0 = H0/T0;
                    END

                    IF (I$X = 40) THEN
                    BEGIN
                        IF (Q5 > 0) THEN X5 = 100*C5/Q5;
                        IF (Q4 > 0) THEN X4 = 100*C4/Q4;
                        IF (Q3 > 0) THEN X3 = 100*C3/Q3;
                        IF (Q2 > 0) THEN X2 = 100*C2/Q2;
                        IF (Q1 > 0) THEN X1 = 100*C1/Q1;
                        IF (Q0 > 0) THEN X0 = 100*C0/Q0;
                    END

                    SUSPEND;
                END
        /* duble */
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_SPB_SKILL_2_QUAL (
    I$X SMALLINT = 10)
RETURNS (
    N0 VARCHAR(4),
    DPO_VAL VARCHAR(1000),
    QUAL VARCHAR(1000),
    X5 NUMERIC(14,2),
    X4 NUMERIC(14,2),
    X3 NUMERIC(14,2),
    X2 NUMERIC(14,2),
    X1 NUMERIC(14,2),
    X0 NUMERIC(14,2))
AS
declare variable N smallint;
declare variable CURR_YEAR smallint;
declare variable OBJ_YEAR smallint;
declare variable DPO varchar(1000);
declare variable LISTVAL_ID bigint;
declare variable H float;
declare variable H5 float;
declare variable H4 float;
declare variable H3 float;
declare variable H2 float;
declare variable H1 float;
declare variable H0 float;
declare variable C5 float;
declare variable C4 float;
declare variable C3 float;
declare variable C2 float;
declare variable C1 float;
declare variable C0 float;
declare variable T5 integer;
declare variable T4 integer;
declare variable T3 integer;
declare variable T2 integer;
declare variable T1 integer;
declare variable T0 integer;
declare variable Q5 integer;
declare variable Q4 integer;
declare variable Q3 integer;
declare variable Q2 integer;
declare variable Q1 integer;
declare variable Q0 integer;
BEGIN
    /*
        I$X = 10  -  hour
        I$X = 20  -  pupil
        I$X = 30  -  hour / pupil
        I$X = 40  -  percent

        H - DPO total hours
        C - DPO total qualified
        T - total teachers in all OU
        Q - total qualified in all OU

    */

    CURR_YEAR = EXTRACT(YEAR FROM CURRENT_TIMESTAMP);

    N   = 0;
    N0  = '';
    DPO = '';
    X5  = CURR_YEAR - 4;
    X4  = CURR_YEAR - 3;
    X3  = CURR_YEAR - 2;
    X2  = CURR_YEAR - 1;
    X1  = CURR_YEAR - 0;
    X0  = CURR_YEAR + 1;

    SUSPEND;

    IF (I$X = 30) THEN     /* total teachers in all OU */
    BEGIN
        SELECT T FROM R_SPB_TOTAL_TEACHERS(:CURR_YEAR - 4) INTO :T5;
        SELECT T FROM R_SPB_TOTAL_TEACHERS(:CURR_YEAR - 3) INTO :T4;
        SELECT T FROM R_SPB_TOTAL_TEACHERS(:CURR_YEAR - 2) INTO :T3;
        SELECT T FROM R_SPB_TOTAL_TEACHERS(:CURR_YEAR - 1) INTO :T2;
        SELECT T FROM R_SPB_TOTAL_TEACHERS(:CURR_YEAR - 0) INTO :T1;
        T0 = T1+0.6*(T2-T5)+0.2*(T3-T4);
    END

    IF (I$X = 40) THEN     /* total qualified in all OU */
    BEGIN
        SELECT T FROM R_SPB_TOTAL_QUALIFIED(:CURR_YEAR - 4) INTO :Q5;
        SELECT T FROM R_SPB_TOTAL_QUALIFIED(:CURR_YEAR - 3) INTO :Q4;
        SELECT T FROM R_SPB_TOTAL_QUALIFIED(:CURR_YEAR - 2) INTO :Q3;
        SELECT T FROM R_SPB_TOTAL_QUALIFIED(:CURR_YEAR - 1) INTO :Q2;
        SELECT T FROM R_SPB_TOTAL_QUALIFIED(:CURR_YEAR - 0) INTO :Q1;
        Q0 = Q1+0.6*(Q2-Q5)+0.2*(Q3-Q4);
    END

    FOR
        SELECT DISTINCT
               R.VAL

        FROM LISTVALS L

        JOIN RES R
        ON R.RES_ID = L.RES_ID
        AND R.LANG_CODE = 'RU'

        JOIN VALS DPO
        ON DPO.PARAM_ID = 304
        AND DPO.VAL = R.VAL
        AND DPO.IS_DEL = 0

        WHERE L.LIST_ID = 151

        ORDER BY L.SORT_ORDER
        INTO :DPO
    DO
    BEGIN
        DPO_VAL = DPO;
        
        FOR
            SELECT L.LISTVAL_ID, R.VAL
            FROM LISTVALS L
            JOIN RES R ON R.RES_ID = L.RES_ID AND R.LANG_CODE = 'RU'
            WHERE L.LIST_ID = 90
            ORDER BY L.SORT_ORDER DESC
            INTO :LISTVAL_ID, :QUAL
        DO
        BEGIN
            X5 = 0; X4 = 0; X3 = 0; X2 = 0; X1 = 0; X0 = 0;
            C5 = 0; C4 = 0; C3 = 0; C2 = 0; C1 = 0; C0 = 0;
            H5 = 0; H4 = 0; H3 = 0; H2 = 0; H1 = 0; H0 = 0;

            FOR SELECT EXTRACT(YEAR FROM DT.VAL), HR.VAL
                FROM VALS DPO
                JOIN OBJECTS O36 ON O36.OBJ_ID = DPO.OBJ_ID AND O36.TYPE_ID = 36
                JOIN LINKS LNK ON LNK.OBJ_ID = O36.OBJ_ID AND LNK.DATE_DEL IS NULL
                JOIN OBJECTS O14 ON O14.OBJ_ID = LNK.PARENT_ID AND O14.TYPE_ID = 14
                LEFT JOIN VACANCY_GET_CAT(O14.OBJ_ID) VCAT ON 1 = 1
                JOIN VALD DT ON DT.PARAM_ID = 310 AND O36.OBJ_ID = DT.OBJ_ID  AND DT.IS_DEL = 0
                JOIN VALI HR ON HR.PARAM_ID = 306 AND O36.OBJ_ID = HR.OBJ_ID  AND HR.IS_DEL = 0
                WHERE DPO.PARAM_ID = 304 AND DPO.VAL = :DPO AND DPO.IS_DEL = 0 AND VCAT.LISTVAL_ID = :LISTVAL_ID
                INTO :OBJ_YEAR, :H
            DO
            BEGIN

                    IF (OBJ_YEAR = CURR_YEAR - 4) THEN
                    BEGIN
                        H5 = H5 + H;
                        C5 = C5 + 1;
                    END
                    IF (OBJ_YEAR = CURR_YEAR - 3) THEN
                    BEGIN
                        H4 = H4 + H;
                        C4 = C4 + 1;
                    END
                    IF (OBJ_YEAR = CURR_YEAR - 2) THEN
                    BEGIN
                        H3 = H3 + H;
                        C3 = C3 + 1;
                    END
                    IF (OBJ_YEAR = CURR_YEAR - 1) THEN
                    BEGIN
                        H2 = H2 + H;
                        C2 = C2 + 1;
                    END
                    IF (OBJ_YEAR = CURR_YEAR - 0) THEN
                    BEGIN
                        H1 = H1 + H;
                        C1 = C1 + 1;
                    END

            END

            IF ((C5 > 0) OR (C4 > 0) OR (C3 > 0) OR (C2 > 0) OR (C1 > 0)) THEN
            BEGIN
                    N  = N + 1;
                    N0 = N;
                    C0 = C1+0.6*(C2-C5)+0.2*(C3-C4);
                    H0 = H1+0.6*(H2-H5)+0.2*(H3-H4);
                    IF (C0 < 0) THEN C0 = 0;
                    IF (H0 < 0) THEN H0 = 0;

                    IF (I$X = 10) THEN
                    BEGIN
                        X5 = H5; X4 = H4; X3 = H3; X2 = H2; X1 = H1; X0 = H0;
                    END

                    IF (I$X = 20) THEN
                    BEGIN
                        X5 = C5; X4 = C4; X3 = C3; X2 = C2; X1 = C1; X0 = C0;
                    END

                    IF (I$X = 30) THEN
                    BEGIN
                        IF (T5 > 0) THEN X5 = H5/T5;
                        IF (T4 > 0) THEN X4 = H4/T4;
                        IF (T3 > 0) THEN X3 = H3/T3;
                        IF (T2 > 0) THEN X2 = H2/T2;
                        IF (T1 > 0) THEN X1 = H1/T1;
                        IF (T0 > 0) THEN X0 = H0/T0;
                    END

                    IF (I$X = 40) THEN
                    BEGIN
                        IF (Q5 > 0) THEN X5 = 100*C5/Q5;
                        IF (Q4 > 0) THEN X4 = 100*C4/Q4;
                        IF (Q3 > 0) THEN X3 = 100*C3/Q3;
                        IF (Q2 > 0) THEN X2 = 100*C2/Q2;
                        IF (Q1 > 0) THEN X1 = 100*C1/Q1;
                        IF (Q0 > 0) THEN X0 = 100*C0/Q0;
                    END

                    SUSPEND;
                    
                  /*  DPO_VAL = '';   */
            END
        END
    END

    /* TOTAL */

        N0 = '';
        DPO_VAL = 'ИТОГО:';
        
        FOR
            SELECT L.LISTVAL_ID, R.VAL
            FROM LISTVALS L
            JOIN RES R ON R.RES_ID = L.RES_ID AND R.LANG_CODE = 'RU'
            WHERE L.LIST_ID = 90
            ORDER BY L.SORT_ORDER DESC
            INTO :LISTVAL_ID, :QUAL
        DO
        BEGIN
            X5 = 0; X4 = 0; X3 = 0; X2 = 0; X1 = 0; X0 = 0;
            C5 = 0; C4 = 0; C3 = 0; C2 = 0; C1 = 0; C0 = 0;
            H5 = 0; H4 = 0; H3 = 0; H2 = 0; H1 = 0; H0 = 0;

            FOR SELECT EXTRACT(YEAR FROM DT.VAL), HR.VAL
                FROM VALS DPO
                JOIN OBJECTS O36 ON O36.OBJ_ID = DPO.OBJ_ID       AND O36.TYPE_ID = 36
                JOIN LINKS   LNK ON LNK.OBJ_ID = O36.OBJ_ID       AND LNK.DATE_DEL IS NULL
                JOIN OBJECTS O14 ON O14.OBJ_ID = LNK.PARENT_ID    AND O14.TYPE_ID = 14
                LEFT JOIN VACANCY_GET_CAT(O14.OBJ_ID) VCAT ON 1 = 1
                JOIN VALD DT ON DT.PARAM_ID = 310 AND O36.OBJ_ID = DT.OBJ_ID  AND DT.IS_DEL = 0
                JOIN VALI HR ON HR.PARAM_ID = 306 AND O36.OBJ_ID = HR.OBJ_ID  AND HR.IS_DEL = 0
                WHERE DPO.PARAM_ID = 304 AND DPO.IS_DEL = 0 AND VCAT.LISTVAL_ID = :LISTVAL_ID
                INTO :OBJ_YEAR, :H
            DO
            BEGIN

                    IF (OBJ_YEAR = CURR_YEAR - 4) THEN
                    BEGIN
                        H5 = H5 + H;
                        C5 = C5 + 1;
                    END
                    IF (OBJ_YEAR = CURR_YEAR - 3) THEN
                    BEGIN
                        H4 = H4 + H;
                        C4 = C4 + 1;
                    END
                    IF (OBJ_YEAR = CURR_YEAR - 2) THEN
                    BEGIN
                        H3 = H3 + H;
                        C3 = C3 + 1;
                    END
                    IF (OBJ_YEAR = CURR_YEAR - 1) THEN
                    BEGIN
                        H2 = H2 + H;
                        C2 = C2 + 1;
                    END
                    IF (OBJ_YEAR = CURR_YEAR - 0) THEN
                    BEGIN
                        H1 = H1 + H;
                        C1 = C1 + 1;
                    END

            END

            IF ((C5 > 0) OR (C4 > 0) OR (C3 > 0) OR (C2 > 0) OR (C1 > 0)) THEN
            BEGIN
                    N  = N + 1;
                    C0 = C1+0.6*(C2-C5)+0.2*(C3-C4);
                    H0 = H1+0.6*(H2-H5)+0.2*(H3-H4);
                    IF (C0 < 0) THEN C0 = 0;
                    IF (H0 < 0) THEN H0 = 0;

                    IF (I$X = 10) THEN
                    BEGIN
                        X5 = H5; X4 = H4; X3 = H3; X2 = H2; X1 = H1; X0 = H0;
                    END

                    IF (I$X = 20) THEN
                    BEGIN
                        X5 = C5; X4 = C4; X3 = C3; X2 = C2; X1 = C1; X0 = C0;
                    END

                    IF (I$X = 30) THEN
                    BEGIN
                        IF (T5 > 0) THEN X5 = H5/T5;
                        IF (T4 > 0) THEN X4 = H4/T4;
                        IF (T3 > 0) THEN X3 = H3/T3;
                        IF (T2 > 0) THEN X2 = H2/T2;
                        IF (T1 > 0) THEN X1 = H1/T1;
                        IF (T0 > 0) THEN X0 = H0/T0;
                    END

                    IF (I$X = 40) THEN
                    BEGIN
                        IF (Q5 > 0) THEN X5 = 100*C5/Q5;
                        IF (Q4 > 0) THEN X4 = 100*C4/Q4;
                        IF (Q3 > 0) THEN X3 = 100*C3/Q3;
                        IF (Q2 > 0) THEN X2 = 100*C2/Q2;
                        IF (Q1 > 0) THEN X1 = 100*C1/Q1;
                        IF (Q0 > 0) THEN X0 = 100*C0/Q0;
                    END

                    SUSPEND;
                    
                  /*  DPO_VAL = '';   */
            END
        END



END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_SPB_SKILL_3_SENIORITY (
    I$X SMALLINT = 10)
RETURNS (
    N0 VARCHAR(4),
    DPO_VAL VARCHAR(1000),
    SENIORITY_VAL VARCHAR(100),
    X5 NUMERIC(14,2),
    X4 NUMERIC(14,2),
    X3 NUMERIC(14,2),
    X2 NUMERIC(14,2),
    X1 NUMERIC(14,2),
    X0 NUMERIC(14,2))
AS
declare variable N smallint;
declare variable CURR_YEAR smallint;
declare variable TEACHER_ID bigint;
declare variable SENIORITY_CNT integer;
declare variable MIN_SENIORITY integer;
declare variable MAX_SENIORITY integer;
declare variable OBJ_YEAR smallint;
declare variable DPO varchar(1000);
declare variable H float;
declare variable H5 float;
declare variable H4 float;
declare variable H3 float;
declare variable H2 float;
declare variable H1 float;
declare variable H0 float;
declare variable C5 float;
declare variable C4 float;
declare variable C3 float;
declare variable C2 float;
declare variable C1 float;
declare variable C0 float;
declare variable T5 integer;
declare variable T4 integer;
declare variable T3 integer;
declare variable T2 integer;
declare variable T1 integer;
declare variable T0 integer;
declare variable Q5 integer;
declare variable Q4 integer;
declare variable Q3 integer;
declare variable Q2 integer;
declare variable Q1 integer;
declare variable Q0 integer;
BEGIN
    /*
        I$X = 10  -  hour
        I$X = 20  -  pupil
        I$X = 30  -  hour / pupil
        I$X = 40  -  percent

        H - DPO total hours
        C - DPO total qualified
        T - total teachers in all OU
        Q - total qualified in all OU

    */

    CURR_YEAR = EXTRACT(YEAR FROM CURRENT_TIMESTAMP);

    N   = 0;
    N0  = '';
    DPO = '';
    X5  = CURR_YEAR - 4;
    X4  = CURR_YEAR - 3;
    X3  = CURR_YEAR - 2;
    X2  = CURR_YEAR - 1;
    X1  = CURR_YEAR - 0;
    X0  = CURR_YEAR + 1;

    SUSPEND;

    IF (I$X = 30) THEN     /* total teachers in all OU */
    BEGIN
        SELECT T FROM R_SPB_TOTAL_TEACHERS(:CURR_YEAR - 4) INTO :T5;
        SELECT T FROM R_SPB_TOTAL_TEACHERS(:CURR_YEAR - 3) INTO :T4;
        SELECT T FROM R_SPB_TOTAL_TEACHERS(:CURR_YEAR - 2) INTO :T3;
        SELECT T FROM R_SPB_TOTAL_TEACHERS(:CURR_YEAR - 1) INTO :T2;
        SELECT T FROM R_SPB_TOTAL_TEACHERS(:CURR_YEAR - 0) INTO :T1;
        T0 = T1+0.6*(T2-T5)+0.2*(T3-T4);
    END

    IF (I$X = 40) THEN     /* total qualified in all OU */
    BEGIN
        SELECT T FROM R_SPB_TOTAL_QUALIFIED(:CURR_YEAR - 4) INTO :Q5;
        SELECT T FROM R_SPB_TOTAL_QUALIFIED(:CURR_YEAR - 3) INTO :Q4;
        SELECT T FROM R_SPB_TOTAL_QUALIFIED(:CURR_YEAR - 2) INTO :Q3;
        SELECT T FROM R_SPB_TOTAL_QUALIFIED(:CURR_YEAR - 1) INTO :Q2;
        SELECT T FROM R_SPB_TOTAL_QUALIFIED(:CURR_YEAR - 0) INTO :Q1;
        Q0 = Q1+0.6*(Q2-Q5)+0.2*(Q3-Q4);
    END

    FOR
        SELECT DISTINCT
               R.VAL
        FROM LISTVALS L

        JOIN RES R
        ON R.RES_ID = L.RES_ID
        AND R.LANG_CODE = 'RU'

        JOIN VALS DPO
        ON DPO.PARAM_ID = 304
        AND DPO.VAL = R.VAL
        AND DPO.IS_DEL = 0

        WHERE L.LIST_ID = 151

        ORDER BY L.SORT_ORDER
        INTO :DPO
    DO
    BEGIN
        DPO_VAL = DPO;
        
        FOR SELECT MIN_SENIORITY, MAX_SENIORITY, SENIORITY_VAL
            FROM R_SPB_TOTAL_SENIORITY
            INTO :MIN_SENIORITY, :MAX_SENIORITY, :SENIORITY_VAL
        DO
        BEGIN
            X5 = 0; X4 = 0; X3 = 0; X2 = 0; X1 = 0; X0 = 0;
            C5 = 0; C4 = 0; C3 = 0; C2 = 0; C1 = 0; C0 = 0;
            H5 = 0; H4 = 0; H3 = 0; H2 = 0; H1 = 0; H0 = 0;

            FOR SELECT EXTRACT(YEAR FROM DT.VAL), HR.VAL, O14.OBJ_ID
                FROM VALS DPO
                INNER JOIN OBJECTS O36 ON O36.OBJ_ID = DPO.OBJ_ID       AND O36.TYPE_ID = 36
                INNER JOIN LINKS   LNK ON LNK.OBJ_ID = O36.OBJ_ID       AND LNK.DATE_DEL IS NULL
                INNER JOIN OBJECTS O14 ON O14.OBJ_ID = LNK.PARENT_ID    AND O14.TYPE_ID = 14
                INNER JOIN VALD     DT ON DT.PARAM_ID = 310 AND O36.OBJ_ID = DT.OBJ_ID  AND DT.IS_DEL = 0
                INNER JOIN VALI     HR ON HR.PARAM_ID = 306 AND O36.OBJ_ID = HR.OBJ_ID  AND HR.IS_DEL = 0
                WHERE DPO.PARAM_ID = 304
                AND DPO.VAL = :DPO
                AND DPO.IS_DEL = 0
                INTO :OBJ_YEAR, :H, :TEACHER_ID
            DO
            BEGIN
                SELECT SUM(DAYS360_COUNT)/360
                FROM PARAGRAF_EMPLOYEE_SENIORITY_LST(:TEACHER_ID)
                WHERE SENIORITY_TYPE = 942
                INTO :SENIORITY_CNT;
                
                IF ((SENIORITY_CNT >= MIN_SENIORITY) AND (SENIORITY_CNT < MAX_SENIORITY)) THEN
                BEGIN
                    IF (OBJ_YEAR = CURR_YEAR - 4) THEN
                    BEGIN
                        H5 = H5 + H;
                        C5 = C5 + 1;
                    END
                    IF (OBJ_YEAR = CURR_YEAR - 3) THEN
                    BEGIN
                        H4 = H4 + H;
                        C4 = C4 + 1;
                    END
                    IF (OBJ_YEAR = CURR_YEAR - 2) THEN
                    BEGIN
                        H3 = H3 + H;
                        C3 = C3 + 1;
                    END
                    IF (OBJ_YEAR = CURR_YEAR - 1) THEN
                    BEGIN
                        H2 = H2 + H;
                        C2 = C2 + 1;
                    END
                    IF (OBJ_YEAR = CURR_YEAR - 0) THEN
                    BEGIN
                        H1 = H1 + H;
                        C1 = C1 + 1;
                    END
                END
            END
            
            IF ((C5 > 0) OR (C4 > 0) OR (C3 > 0) OR (C2 > 0) OR (C1 > 0)) THEN
            BEGIN
                    N  = N + 1;
                    N0 = N;
                    C0 = C1+0.6*(C2-C5)+0.2*(C3-C4);
                    H0 = H1+0.6*(H2-H5)+0.2*(H3-H4);
                    IF (C0 < 0) THEN C0 = 0;
                    IF (H0 < 0) THEN H0 = 0;

                    IF (I$X = 10) THEN
                    BEGIN
                        X5 = H5; X4 = H4; X3 = H3; X2 = H2; X1 = H1; X0 = H0;
                    END

                    IF (I$X = 20) THEN
                    BEGIN
                        X5 = C5; X4 = C4; X3 = C3; X2 = C2; X1 = C1; X0 = C0;
                    END

                    IF (I$X = 30) THEN
                    BEGIN
                        IF (T5 > 0) THEN X5 = H5/T5;
                        IF (T4 > 0) THEN X4 = H4/T4;
                        IF (T3 > 0) THEN X3 = H3/T3;
                        IF (T2 > 0) THEN X2 = H2/T2;
                        IF (T1 > 0) THEN X1 = H1/T1;
                        IF (T0 > 0) THEN X0 = H0/T0;
                    END

                    IF (I$X = 40) THEN
                    BEGIN
                        IF (Q5 > 0) THEN X5 = 100*C5/Q5;
                        IF (Q4 > 0) THEN X4 = 100*C4/Q4;
                        IF (Q3 > 0) THEN X3 = 100*C3/Q3;
                        IF (Q2 > 0) THEN X2 = 100*C2/Q2;
                        IF (Q1 > 0) THEN X1 = 100*C1/Q1;
                        IF (Q0 > 0) THEN X0 = 100*C0/Q0;
                    END

                    SUSPEND;
                    
                 /*   DPO_VAL = '';  */
            END
        END
    END

    /* TOTAL */

        DPO_VAL = 'ИТОГО:';
        N0 = '';
        
        FOR SELECT MIN_SENIORITY, MAX_SENIORITY, SENIORITY_VAL
            FROM R_SPB_TOTAL_SENIORITY
            INTO :MIN_SENIORITY, :MAX_SENIORITY, :SENIORITY_VAL
        DO
        BEGIN
            X5 = 0; X4 = 0; X3 = 0; X2 = 0; X1 = 0; X0 = 0;
            C5 = 0; C4 = 0; C3 = 0; C2 = 0; C1 = 0; C0 = 0;
            H5 = 0; H4 = 0; H3 = 0; H2 = 0; H1 = 0; H0 = 0;

            FOR SELECT EXTRACT(YEAR FROM DT.VAL), HR.VAL, O14.OBJ_ID
                FROM VALS DPO
                INNER JOIN OBJECTS O36 ON O36.OBJ_ID = DPO.OBJ_ID       AND O36.TYPE_ID = 36
                INNER JOIN LINKS   LNK ON LNK.OBJ_ID = O36.OBJ_ID       AND LNK.DATE_DEL IS NULL
                INNER JOIN OBJECTS O14 ON O14.OBJ_ID = LNK.PARENT_ID    AND O14.TYPE_ID = 14
                INNER JOIN VALD     DT ON DT.PARAM_ID = 310 AND O36.OBJ_ID = DT.OBJ_ID  AND DT.IS_DEL = 0
                INNER JOIN VALI     HR ON HR.PARAM_ID = 306 AND O36.OBJ_ID = HR.OBJ_ID  AND HR.IS_DEL = 0
                WHERE DPO.PARAM_ID = 304
                AND DPO.IS_DEL = 0
                INTO :OBJ_YEAR, :H, :TEACHER_ID
            DO
            BEGIN
                SELECT SUM(DAYS360_COUNT)/360
                FROM PARAGRAF_EMPLOYEE_SENIORITY_LST(:TEACHER_ID)
                WHERE SENIORITY_TYPE = 942
                INTO :SENIORITY_CNT;
                
                IF ((SENIORITY_CNT >= MIN_SENIORITY) AND (SENIORITY_CNT < MAX_SENIORITY)) THEN
                BEGIN
                    IF (OBJ_YEAR = CURR_YEAR - 4) THEN
                    BEGIN
                        H5 = H5 + H;
                        C5 = C5 + 1;
                    END
                    IF (OBJ_YEAR = CURR_YEAR - 3) THEN
                    BEGIN
                        H4 = H4 + H;
                        C4 = C4 + 1;
                    END
                    IF (OBJ_YEAR = CURR_YEAR - 2) THEN
                    BEGIN
                        H3 = H3 + H;
                        C3 = C3 + 1;
                    END
                    IF (OBJ_YEAR = CURR_YEAR - 1) THEN
                    BEGIN
                        H2 = H2 + H;
                        C2 = C2 + 1;
                    END
                    IF (OBJ_YEAR = CURR_YEAR - 0) THEN
                    BEGIN
                        H1 = H1 + H;
                        C1 = C1 + 1;
                    END
                END
            END
            
            IF ((C5 > 0) OR (C4 > 0) OR (C3 > 0) OR (C2 > 0) OR (C1 > 0)) THEN
            BEGIN
                    N  = N + 1;
                    C0 = C1+0.6*(C2-C5)+0.2*(C3-C4);
                    H0 = H1+0.6*(H2-H5)+0.2*(H3-H4);
                    IF (C0 < 0) THEN C0 = 0;
                    IF (H0 < 0) THEN H0 = 0;

                    IF (I$X = 10) THEN
                    BEGIN
                        X5 = H5; X4 = H4; X3 = H3; X2 = H2; X1 = H1; X0 = H0;
                    END

                    IF (I$X = 20) THEN
                    BEGIN
                        X5 = C5; X4 = C4; X3 = C3; X2 = C2; X1 = C1; X0 = C0;
                    END

                    IF (I$X = 30) THEN
                    BEGIN
                        IF (T5 > 0) THEN X5 = H5/T5;
                        IF (T4 > 0) THEN X4 = H4/T4;
                        IF (T3 > 0) THEN X3 = H3/T3;
                        IF (T2 > 0) THEN X2 = H2/T2;
                        IF (T1 > 0) THEN X1 = H1/T1;
                        IF (T0 > 0) THEN X0 = H0/T0;
                    END

                    IF (I$X = 40) THEN
                    BEGIN
                        IF (Q5 > 0) THEN X5 = 100*C5/Q5;
                        IF (Q4 > 0) THEN X4 = 100*C4/Q4;
                        IF (Q3 > 0) THEN X3 = 100*C3/Q3;
                        IF (Q2 > 0) THEN X2 = 100*C2/Q2;
                        IF (Q1 > 0) THEN X1 = 100*C1/Q1;
                        IF (Q0 > 0) THEN X0 = 100*C0/Q0;
                    END

                    SUSPEND;
                    
                 /*   DPO_VAL = '';  */
            END
        END


END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_SPB_SKILL_4_POST (
    I$X SMALLINT = 10,
    I$USER_ID BIGINT = 1)
RETURNS (
    N0 VARCHAR(4),
    DPO_VAL VARCHAR(1000),
    POST_VAL VARCHAR(100),
    X5 NUMERIC(14,2),
    X4 NUMERIC(14,2),
    X3 NUMERIC(14,2),
    X2 NUMERIC(14,2),
    X1 NUMERIC(14,2),
    X0 NUMERIC(14,2))
AS
declare variable N smallint;
declare variable CURR_YEAR smallint;
declare variable LISTVAL_ID bigint;
declare variable OBJ_YEAR smallint;
declare variable DPO varchar(1000);
declare variable H float;
declare variable H5 float;
declare variable H4 float;
declare variable H3 float;
declare variable H2 float;
declare variable H1 float;
declare variable H0 float;
declare variable C5 float;
declare variable C4 float;
declare variable C3 float;
declare variable C2 float;
declare variable C1 float;
declare variable C0 float;
declare variable T5 integer;
declare variable T4 integer;
declare variable T3 integer;
declare variable T2 integer;
declare variable T1 integer;
declare variable T0 integer;
declare variable Q5 integer;
declare variable Q4 integer;
declare variable Q3 integer;
declare variable Q2 integer;
declare variable Q1 integer;
declare variable Q0 integer;
declare variable LANG_CODE varchar(2);
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :LANG_CODE;

    /*
        I$X = 10  -  hour
        I$X = 20  -  pupil
        I$X = 30  -  hour / pupil
        I$X = 40  -  percent

        H - DPO total hours
        C - DPO total qualified
        T - total teachers in all OU
        Q - total qualified in all OU

    */

    CURR_YEAR = EXTRACT(YEAR FROM CURRENT_TIMESTAMP);

    N   = 0;
    N0  = '';
    DPO = '';
    X5  = CURR_YEAR - 4;
    X4  = CURR_YEAR - 3;
    X3  = CURR_YEAR - 2;
    X2  = CURR_YEAR - 1;
    X1  = CURR_YEAR - 0;
    X0  = CURR_YEAR + 1;

    SUSPEND;

    IF (I$X = 30) THEN     /* total teachers in all OU */
    BEGIN
        SELECT T FROM R_SPB_TOTAL_TEACHERS(:CURR_YEAR - 4) INTO :T5;
        SELECT T FROM R_SPB_TOTAL_TEACHERS(:CURR_YEAR - 3) INTO :T4;
        SELECT T FROM R_SPB_TOTAL_TEACHERS(:CURR_YEAR - 2) INTO :T3;
        SELECT T FROM R_SPB_TOTAL_TEACHERS(:CURR_YEAR - 1) INTO :T2;
        SELECT T FROM R_SPB_TOTAL_TEACHERS(:CURR_YEAR - 0) INTO :T1;
        T0 = T1+0.6*(T2-T5)+0.2*(T3-T4);
    END

    IF (I$X = 40) THEN     /* total qualified in all OU */
    BEGIN
        SELECT T FROM R_SPB_TOTAL_QUALIFIED(:CURR_YEAR - 4) INTO :Q5;
        SELECT T FROM R_SPB_TOTAL_QUALIFIED(:CURR_YEAR - 3) INTO :Q4;
        SELECT T FROM R_SPB_TOTAL_QUALIFIED(:CURR_YEAR - 2) INTO :Q3;
        SELECT T FROM R_SPB_TOTAL_QUALIFIED(:CURR_YEAR - 1) INTO :Q2;
        SELECT T FROM R_SPB_TOTAL_QUALIFIED(:CURR_YEAR - 0) INTO :Q1;
        Q0 = Q1+0.6*(Q2-Q5)+0.2*(Q3-Q4);
    END

    FOR
        SELECT DISTINCT
               R.VAL
        FROM LISTVALS L

        JOIN RES R
        ON R.RES_ID = L.RES_ID
        AND R.LANG_CODE = 'RU'

        JOIN VALS DPO
        ON DPO.PARAM_ID = 304
        AND DPO.VAL = R.VAL
        AND DPO.IS_DEL = 0

        WHERE L.LIST_ID = 151
        ORDER BY L.SORT_ORDER
        INTO :DPO
    DO
    BEGIN
        DPO_VAL = DPO;
        
        FOR
            SELECT L.LISTVAL_ID,
                   RL.VAL
            FROM LISTVALS L

            LEFT JOIN RES_GET(L.RES_ID,  :LANG_CODE) RL ON 1=1

            JOIN LISTVALS R
            ON R.LISTVAL_ID = 99

            --LEFT JOIN RES_GET(R.RES_ID,  :LANG_CODE) RR ON 1=1

            WHERE L.LIST_ID = 21
            AND L.PARENT_ID = 98
            AND R.LISTVAL_ID = 99

            ORDER BY L.SORT_ORDER
            INTO :LISTVAL_ID, :POST_VAL
        DO
        BEGIN
            X5 = 0; X4 = 0; X3 = 0; X2 = 0; X1 = 0; X0 = 0;
            C5 = 0; C4 = 0; C3 = 0; C2 = 0; C1 = 0; C0 = 0;
            H5 = 0; H4 = 0; H3 = 0; H2 = 0; H1 = 0; H0 = 0;

            FOR SELECT EXTRACT(YEAR FROM DT.VAL), HR.VAL
                FROM VALS DPO
                INNER JOIN OBJECTS O36 ON O36.OBJ_ID = DPO.OBJ_ID       AND O36.TYPE_ID = 36
                INNER JOIN LINKS   LNK ON LNK.OBJ_ID = O36.OBJ_ID       AND LNK.DATE_DEL IS NULL
                INNER JOIN OBJECTS O14 ON O14.OBJ_ID = LNK.PARENT_ID    AND O14.TYPE_ID = 14
                INNER JOIN LINKS   LNP ON O14.OBJ_ID = LNP.PARENT_ID    AND LNP.DATE_DEL IS NULL
                INNER JOIN OBJECTS O15 ON O15.OBJ_ID = LNP.OBJ_ID       AND O15.TYPE_ID = 15
                INNER JOIN VALD     DT ON DT.PARAM_ID   = 310     AND O36.OBJ_ID = DT.OBJ_ID  AND DT.IS_DEL = 0
                INNER JOIN VALI     HR ON HR.PARAM_ID   = 306     AND O36.OBJ_ID = HR.OBJ_ID  AND HR.IS_DEL = 0
                INNER JOIN VALR    R69 ON R69.PARAM_ID  = 69      AND R69.OBJ_ID = O15.OBJ_ID AND R69.IS_DEL = 0
                INNER JOIN VALL    L58 ON L58.PARAM_ID  = 58      AND L58.OBJ_ID = R69.VAL    AND L58.LISTVAL_ID = :LISTVAL_ID AND L58.IS_DEL = 0
                INNER JOIN VALD    D73 ON D73.PARAM_ID  = 73      AND D73.OBJ_ID = O15.OBJ_ID AND D73.IS_DEL = 0
                LEFT  JOIN VALD    D74 ON D74.PARAM_ID  = 74      AND D74.OBJ_ID = O15.OBJ_ID AND D74.IS_DEL = 0
                WHERE DPO.PARAM_ID = 304
                AND DPO.VAL = :DPO
                AND DPO.IS_DEL = 0
                AND (EXTRACT(YEAR FROM D73.VAL) <= EXTRACT(YEAR FROM DT.VAL))
                AND ((D74.VAL IS NULL) OR (EXTRACT(YEAR FROM D74.VAL) >= EXTRACT(YEAR FROM DT.VAL)))
                INTO :OBJ_YEAR, :H
            DO
            BEGIN

                    IF (OBJ_YEAR = CURR_YEAR - 4) THEN
                    BEGIN
                        H5 = H5 + H;
                        C5 = C5 + 1;
                    END
                    IF (OBJ_YEAR = CURR_YEAR - 3) THEN
                    BEGIN
                        H4 = H4 + H;
                        C4 = C4 + 1;
                    END
                    IF (OBJ_YEAR = CURR_YEAR - 2) THEN
                    BEGIN
                        H3 = H3 + H;
                        C3 = C3 + 1;
                    END
                    IF (OBJ_YEAR = CURR_YEAR - 1) THEN
                    BEGIN
                        H2 = H2 + H;
                        C2 = C2 + 1;
                    END
                    IF (OBJ_YEAR = CURR_YEAR - 0) THEN
                    BEGIN
                        H1 = H1 + H;
                        C1 = C1 + 1;
                    END

            END
            
            IF ((C5 > 0) OR (C4 > 0) OR (C3 > 0) OR (C2 > 0) OR (C1 > 0)) THEN
            BEGIN
                    N  = N + 1;
                    N0 = N;
                    C0 = C1+0.6*(C2-C5)+0.2*(C3-C4);
                    H0 = H1+0.6*(H2-H5)+0.2*(H3-H4);
                    IF (C0 < 0) THEN C0 = 0;
                    IF (H0 < 0) THEN H0 = 0;

                    IF (I$X = 10) THEN
                    BEGIN
                        X5 = H5; X4 = H4; X3 = H3; X2 = H2; X1 = H1; X0 = H0;
                    END

                    IF (I$X = 20) THEN
                    BEGIN
                        X5 = C5; X4 = C4; X3 = C3; X2 = C2; X1 = C1; X0 = C0;
                    END

                    IF (I$X = 30) THEN
                    BEGIN
                        IF (T5 > 0) THEN X5 = H5/T5;
                        IF (T4 > 0) THEN X4 = H4/T4;
                        IF (T3 > 0) THEN X3 = H3/T3;
                        IF (T2 > 0) THEN X2 = H2/T2;
                        IF (T1 > 0) THEN X1 = H1/T1;
                        IF (T0 > 0) THEN X0 = H0/T0;
                    END

                    IF (I$X = 40) THEN
                    BEGIN
                        IF (Q5 > 0) THEN X5 = 100*C5/Q5;
                        IF (Q4 > 0) THEN X4 = 100*C4/Q4;
                        IF (Q3 > 0) THEN X3 = 100*C3/Q3;
                        IF (Q2 > 0) THEN X2 = 100*C2/Q2;
                        IF (Q1 > 0) THEN X1 = 100*C1/Q1;
                        IF (Q0 > 0) THEN X0 = 100*C0/Q0;
                    END

                    SUSPEND;
                    
                 /*   DPO_VAL = '';   */
            END
        END
    END

    /* TOTAL */

        SELECT WORD FROM REPORT_WORDS WHERE ID = 28 INTO :DPO_VAL;
        N0 = '';
        
        FOR
            SELECT L.LISTVAL_ID,
                   RL.VAL

            FROM LISTVALS L

            LEFT JOIN RES_GET(L.RES_ID,  :LANG_CODE) RL ON 1=1

            JOIN LISTVALS R
            ON R.LISTVAL_ID = 99

            WHERE L.LIST_ID = 21
            AND L.PARENT_ID = 98

            ORDER BY L.SORT_ORDER
            INTO :LISTVAL_ID, :POST_VAL
        DO
        BEGIN
            X5 = 0; X4 = 0; X3 = 0; X2 = 0; X1 = 0; X0 = 0;
            C5 = 0; C4 = 0; C3 = 0; C2 = 0; C1 = 0; C0 = 0;
            H5 = 0; H4 = 0; H3 = 0; H2 = 0; H1 = 0; H0 = 0;

            FOR SELECT EXTRACT(YEAR FROM DT.VAL), HR.VAL
                FROM VALS DPO
                INNER JOIN OBJECTS O36 ON O36.OBJ_ID = DPO.OBJ_ID       AND O36.TYPE_ID = 36
                INNER JOIN LINKS   LNK ON LNK.OBJ_ID = O36.OBJ_ID       AND LNK.DATE_DEL IS NULL
                INNER JOIN OBJECTS O14 ON O14.OBJ_ID = LNK.PARENT_ID    AND O14.TYPE_ID = 14
                INNER JOIN LINKS   LNP ON O14.OBJ_ID = LNP.PARENT_ID    AND LNP.DATE_DEL IS NULL
                INNER JOIN OBJECTS O15 ON O15.OBJ_ID = LNP.OBJ_ID       AND O15.TYPE_ID = 15
                INNER JOIN VALD     DT ON DT.PARAM_ID   = 310     AND O36.OBJ_ID = DT.OBJ_ID  AND DT.IS_DEL = 0
                INNER JOIN VALI     HR ON HR.PARAM_ID   = 306     AND O36.OBJ_ID = HR.OBJ_ID  AND HR.IS_DEL = 0
                INNER JOIN VALR    R69 ON R69.PARAM_ID  = 69      AND R69.OBJ_ID = O15.OBJ_ID AND R69.IS_DEL = 0
                INNER JOIN VALL    L58 ON L58.PARAM_ID  = 58      AND L58.OBJ_ID = R69.VAL    AND L58.LISTVAL_ID = :LISTVAL_ID AND L58.IS_DEL = 0
                INNER JOIN VALD    D73 ON D73.PARAM_ID  = 73      AND D73.OBJ_ID = O15.OBJ_ID AND D73.IS_DEL = 0
                LEFT  JOIN VALD    D74 ON D74.PARAM_ID  = 74      AND D74.OBJ_ID = O15.OBJ_ID AND D74.IS_DEL = 0
                WHERE DPO.PARAM_ID = 304
                AND DPO.IS_DEL = 0
                AND (EXTRACT(YEAR FROM D73.VAL) <= EXTRACT(YEAR FROM DT.VAL))
                AND ((D74.VAL IS NULL) OR (EXTRACT(YEAR FROM D74.VAL) >= EXTRACT(YEAR FROM DT.VAL)))
                INTO :OBJ_YEAR, :H
            DO
            BEGIN

                    IF (OBJ_YEAR = CURR_YEAR - 4) THEN
                    BEGIN
                        H5 = H5 + H;
                        C5 = C5 + 1;
                    END
                    IF (OBJ_YEAR = CURR_YEAR - 3) THEN
                    BEGIN
                        H4 = H4 + H;
                        C4 = C4 + 1;
                    END
                    IF (OBJ_YEAR = CURR_YEAR - 2) THEN
                    BEGIN
                        H3 = H3 + H;
                        C3 = C3 + 1;
                    END
                    IF (OBJ_YEAR = CURR_YEAR - 1) THEN
                    BEGIN
                        H2 = H2 + H;
                        C2 = C2 + 1;
                    END
                    IF (OBJ_YEAR = CURR_YEAR - 0) THEN
                    BEGIN
                        H1 = H1 + H;
                        C1 = C1 + 1;
                    END

            END
            
            IF ((C5 > 0) OR (C4 > 0) OR (C3 > 0) OR (C2 > 0) OR (C1 > 0)) THEN
            BEGIN
                    N  = N + 1;
                    C0 = C1+0.6*(C2-C5)+0.2*(C3-C4);
                    H0 = H1+0.6*(H2-H5)+0.2*(H3-H4);
                    IF (C0 < 0) THEN C0 = 0;
                    IF (H0 < 0) THEN H0 = 0;

                    IF (I$X = 10) THEN
                    BEGIN
                        X5 = H5; X4 = H4; X3 = H3; X2 = H2; X1 = H1; X0 = H0;
                    END

                    IF (I$X = 20) THEN
                    BEGIN
                        X5 = C5; X4 = C4; X3 = C3; X2 = C2; X1 = C1; X0 = C0;
                    END

                    IF (I$X = 30) THEN
                    BEGIN
                        IF (T5 > 0) THEN X5 = H5/T5;
                        IF (T4 > 0) THEN X4 = H4/T4;
                        IF (T3 > 0) THEN X3 = H3/T3;
                        IF (T2 > 0) THEN X2 = H2/T2;
                        IF (T1 > 0) THEN X1 = H1/T1;
                        IF (T0 > 0) THEN X0 = H0/T0;
                    END

                    IF (I$X = 40) THEN
                    BEGIN
                        IF (Q5 > 0) THEN X5 = 100*C5/Q5;
                        IF (Q4 > 0) THEN X4 = 100*C4/Q4;
                        IF (Q3 > 0) THEN X3 = 100*C3/Q3;
                        IF (Q2 > 0) THEN X2 = 100*C2/Q2;
                        IF (Q1 > 0) THEN X1 = 100*C1/Q1;
                        IF (Q0 > 0) THEN X0 = 100*C0/Q0;
                    END

                    SUSPEND;
                    
                 /*   DPO_VAL = '';   */
            END
        END

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_SPB_TEACHER_POST (
    I$TEACHER_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    TEACHER_POST VARCHAR(4000))
AS
declare variable LANG_CODE varchar(2);
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :LANG_CODE;

        SELECT FIRST 1 R.VAL
        FROM LINKS L15
        INNER JOIN OBJECTS   O15 ON O15.OBJ_ID = L15.OBJ_ID AND O15.TYPE_ID = 15
        INNER JOIN VALR      R70 ON R70.PARAM_ID  = 70      AND R70.OBJ_ID = O15.OBJ_ID AND R70.IS_DEL = 0
        INNER JOIN VALR      R69 ON R69.PARAM_ID  = 69      AND R69.OBJ_ID = O15.OBJ_ID AND R69.IS_DEL = 0
        INNER JOIN LINKS     L13 ON L13.PARENT_ID = R69.VAL AND L13.OBJ_ID = O15.OBJ_ID AND L13.DATE_DEL IS NULL
        INNER JOIN VALL      L58 ON L58.PARAM_ID  = 58      AND L58.OBJ_ID = R69.VAL    AND L58.IS_DEL = 0
        INNER JOIN VALL      L72 ON L72.PARAM_ID  = 72      AND L72.OBJ_ID = O15.OBJ_ID AND L72.IS_DEL = 0
        INNER JOIN VALD      D73 ON D73.PARAM_ID  = 73      AND D73.OBJ_ID = O15.OBJ_ID AND D73.IS_DEL = 0
        LEFT  JOIN VALD      D74 ON D74.PARAM_ID  = 74      AND D74.OBJ_ID = O15.OBJ_ID AND D74.IS_DEL = 0
        INNER JOIN LISTVALS   LS ON LS.LISTVAL_ID = L58.LISTVAL_ID
        LEFT JOIN RES_GET(LS.RES_ID,  :LANG_CODE) R ON 1=1
        WHERE L15.PARENT_ID = :I$TEACHER_ID
        AND (L72.LISTVAL_ID = 934)
        AND (D73.VAL <= CURRENT_TIMESTAMP)
        AND ((D74.VAL IS NULL) OR (D74.VAL >= CURRENT_TIMESTAMP))
        INTO :TEACHER_POST;

        SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_SPB_TOTAL_QUALIFIED (
    I$YEAR SMALLINT = 2009)
RETURNS (
    T INTEGER)
AS
BEGIN
    T = 0;

    SELECT COUNT(*)
    FROM OBJECTS O36
    INNER JOIN LINKS   LNK ON LNK.OBJ_ID = O36.OBJ_ID       AND LNK.DATE_DEL IS NULL
    INNER JOIN OBJECTS O14 ON O14.OBJ_ID = LNK.PARENT_ID    AND O14.TYPE_ID = 14
    INNER JOIN VALD     DT ON DT.PARAM_ID = 310 AND O36.OBJ_ID = DT.OBJ_ID  AND  DT.IS_DEL = 0
    INNER JOIN VALI     HR ON HR.PARAM_ID = 306 AND O36.OBJ_ID = HR.OBJ_ID  AND  HR.IS_DEL = 0
    WHERE O36.TYPE_ID = 36
    AND EXTRACT(YEAR FROM DT.VAL) = :I$YEAR
    INTO :T;

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_SPB_TOTAL_SENIORITY RETURNS (
    MIN_SENIORITY INTEGER,
    MAX_SENIORITY INTEGER,
    SENIORITY_VAL VARCHAR(100))
AS
BEGIN
    MIN_SENIORITY = 0;
    MAX_SENIORITY = 10;
    SENIORITY_VAL = 'До 10 лет';
    SUSPEND;
    MIN_SENIORITY = 10;
    MAX_SENIORITY = 20;
    SENIORITY_VAL = '10-20 лет';
    SUSPEND;
    MIN_SENIORITY = 20;
    MAX_SENIORITY = 30;
    SENIORITY_VAL = '20-30 лет';
    SUSPEND;
    MIN_SENIORITY = 30;
    MAX_SENIORITY = 1000;
    SENIORITY_VAL = 'свыше 30 лет';
    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_SPB_TOTAL_TEACHERS (
    I$YEAR SMALLINT = 2009)
RETURNS (
    T INTEGER)
AS
DECLARE VARIABLE TEACHER_ID BIGINT;
BEGIN
    T = 0;

    FOR SELECT DISTINCT R70.VAL
        FROM OBJECTS O15
        INNER JOIN VALR      R70 ON R70.PARAM_ID  = 70      AND R70.OBJ_ID = O15.OBJ_ID AND R70.IS_DEL = 0
        INNER JOIN VALR      R69 ON R69.PARAM_ID  = 69      AND R69.OBJ_ID = O15.OBJ_ID AND R69.IS_DEL = 0
        INNER JOIN LINKS     L13 ON L13.PARENT_ID = R69.VAL AND L13.OBJ_ID = O15.OBJ_ID AND L13.DATE_DEL IS NULL
        INNER JOIN VALD      D73 ON D73.PARAM_ID  = 73      AND D73.OBJ_ID = O15.OBJ_ID AND D73.IS_DEL = 0
        LEFT  JOIN VALD      D74 ON D74.PARAM_ID  = 74      AND D74.OBJ_ID = O15.OBJ_ID AND D74.IS_DEL = 0
        WHERE O15.TYPE_ID = 15
        AND (EXTRACT(YEAR FROM D73.VAL) <= :I$YEAR)
        AND ((D74.VAL IS NULL) OR (EXTRACT(YEAR FROM D74.VAL) >= :I$YEAR))
        AND (SELECT SORT_ORDER FROM DO_FUNC(R69.VAL, 400)) = 2
        INTO :TEACHER_ID
    DO
    BEGIN
        T = T + 1;
    END

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_TWINS (
    I$OBJ_ID BIGINT,
    DEEP SMALLINT,
    I$USER_ID BIGINT)
RETURNS (
    DISTR VARCHAR(400),
    OU VARCHAR(4000),
    CLASS VARCHAR(400),
    F VARCHAR(400),
    I VARCHAR(400),
    O VARCHAR(400),
    D DATE,
    DOC VARCHAR(400),
    SER VARCHAR(400),
    NUM VARCHAR(400),
    M_DT DATE,
    M_STAGE VARCHAR(400),
    M_CLASS VARCHAR(400),
    M_TYPE VARCHAR(400))
AS
declare variable SCHOOLAR_ID bigint;
declare variable X smallint;
declare variable LANG_CODE varchar(2);
declare variable M_SORT_ORDER smallint;
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :LANG_CODE;

    FOR
        SELECT DISTR, OU, CLASS, F, I, O, D, DOC, SER, NUM, SCHOOLAR_ID
        FROM R_TWINS_FIO(:I$OBJ_ID, :DEEP, :I$USER_ID)
        ORDER BY F, I, O
        INTO :DISTR, :OU, :CLASS, :F, :I, :O, :D, :DOC, :SER, :NUM, :SCHOOLAR_ID
    DO
    BEGIN
        X = 0;
        FOR
            SELECT M.DATE_IN, R2.VAL, M.NAME_IN, R1.VAL, 0 SORT_ORDER
            FROM PERSON_MOVEMENTS M
            JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID IN (9, 125, 187)
            JOIN LISTVALS L1 ON L1.LISTVAL_ID = M.REASON_IN
            LEFT JOIN RES_GET(L1.RES_ID, :LANG_CODE) R1 ON 1 = 1
            LEFT JOIN LISTVALS L2 ON L2.LISTVAL_ID = M.STAGE_ID
            LEFT JOIN RES_GET(L2.RES_ID, :LANG_CODE) R2 ON 1 = 1
            WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :SCHOOLAR_ID
            UNION
            SELECT M.DATE_OUT, R2.VAL, M.NAME_IN, R1.VAL, 1 SORT_ORDER
            FROM PERSON_MOVEMENTS M
            JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID IN (9, 125, 187)
            JOIN LISTVALS L1 ON L1.LISTVAL_ID = M.REASON_OUT
            LEFT JOIN RES_GET(L1.RES_ID, :LANG_CODE) R1 ON 1 = 1
            LEFT JOIN LISTVALS L2 ON L2.LISTVAL_ID = M.STAGE_ID
            LEFT JOIN RES_GET(L2.RES_ID, :LANG_CODE) R2 ON 1 = 1
            WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :SCHOOLAR_ID AND M.DATE_OUT IS NOT NULL
            ORDER BY 1, 5
            INTO :M_DT, :M_STAGE, :M_CLASS, :M_TYPE, :M_SORT_ORDER
        DO
        BEGIN
            SUSPEND;
            X = 1;
            OU = NULL;
            CLASS = NULL;
            F = NULL;
            I = NULL;
            O = NULL;
            D = NULL;
            DOC = NULL;
            SER = NULL;
            NUM = NULL;
        END

        IF (X = 0) THEN SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_TWINSY_FIO (
    I$OBJ_ID BIGINT,
    DEEP SMALLINT,
    I$USER_ID BIGINT)
RETURNS (
    DISTR VARCHAR(400),
    OU VARCHAR(4000),
    CLASS VARCHAR(400),
    F VARCHAR(400),
    I VARCHAR(400),
    O VARCHAR(400),
    D DATE,
    DOC VARCHAR(400),
    SER VARCHAR(400),
    NUM VARCHAR(400),
    ORDER_DATE DATE,
    ORDER_NUM VARCHAR(400))
AS
declare variable DISTR_ID bigint;
declare variable OU_ID bigint;
declare variable CLASS_ID bigint;
declare variable PASSPORT_ID bigint;
declare variable SCHOOLAR_ID bigint;
declare variable LANG_CODE varchar(2);
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :LANG_CODE;

    FOR
        SELECT RT.DISTR_ID, RT.OU_ID, RT.CLASS_ID, RT.SCHOOLAR_ID
        FROM R_TWINSY_ID(:I$OBJ_ID, :DEEP) RT
        INTO :DISTR_ID, :OU_ID, :CLASS_ID, :SCHOOLAR_ID
    DO
    BEGIN
        F = NULL;
        I = NULL;
        O = NULL;
        D = NULL;
        DOC = NULL;
        NUM = NULL;
        SER = NULL;
        PASSPORT_ID = NULL;
        ORDER_DATE = NULL;
        ORDER_NUM = NULL;

        IF (DISTR_ID IS NOT NULL) THEN
        BEGIN
            SELECT CAPTION FROM OBJECT_CAPTION_GET(:DISTR_ID,NULL,NULL,:I$USER_ID) INTO :DISTR;
        END
        SELECT V.VAL FROM VALS V WHERE V.PARAM_ID = 2  AND V.OBJ_ID = :OU_ID AND V.IS_DEL = 0 INTO :OU;
        SELECT CAPTION FROM OBJECT_CAPTION_GET(:CLASS_ID,NULL,NULL,:I$USER_ID) INTO :CLASS;
        SELECT V.VAL FROM VALS V WHERE V.PARAM_ID = 55 AND V.OBJ_ID = :SCHOOLAR_ID AND V.IS_DEL = 0 INTO :F;
        SELECT V.VAL FROM VALS V WHERE V.PARAM_ID = 56 AND V.OBJ_ID = :SCHOOLAR_ID AND V.IS_DEL = 0 INTO :I;
        SELECT V.VAL FROM VALS V WHERE V.PARAM_ID = 57 AND V.OBJ_ID = :SCHOOLAR_ID AND V.IS_DEL = 0 INTO :O;
        SELECT V.VAL FROM VALD V WHERE V.PARAM_ID = 89 AND V.OBJ_ID = :SCHOOLAR_ID AND V.IS_DEL = 0 INTO :D;
        SELECT V.VAL FROM VALD V WHERE V.PARAM_ID = 2442 AND V.OBJ_ID = :SCHOOLAR_ID AND V.IS_DEL = 0 INTO :ORDER_DATE;
        SELECT V.VAL FROM VALS V WHERE V.PARAM_ID = 2443 AND V.OBJ_ID = :SCHOOLAR_ID AND V.IS_DEL = 0 INTO :ORDER_NUM;

        SELECT FIRST 1 L.OBJ_ID, R.VAL
        FROM LINKS L
        JOIN VALL V ON V.OBJ_ID = L.OBJ_ID AND V.PARAM_ID = 441 AND V.IS_DEL = 0
        JOIN LISTVALS LV ON LV.LISTVAL_ID = V.LISTVAL_ID
        LEFT JOIN RES_GET(LV.RES_ID, :LANG_CODE) R ON 1 = 1
        WHERE L.PARENT_ID = :SCHOOLAR_ID AND L.OBJ_TYPE_ID = 79 AND L.DATE_DEL IS NULL
        ORDER BY LV.SORT_ORDER
        INTO :PASSPORT_ID, :DOC;

        SELECT V.VAL FROM VALS V WHERE V.PARAM_ID = 442 AND V.OBJ_ID = :PASSPORT_ID AND V.IS_DEL = 0 INTO :SER;
        SELECT V.VAL FROM VALS V WHERE V.PARAM_ID = 559 AND V.OBJ_ID = :PASSPORT_ID AND V.IS_DEL = 0 INTO :NUM;

        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_TWINSY_ID (
    I$OBJ_ID BIGINT,
    DEEP SMALLINT)
RETURNS (
    DISTR_ID BIGINT,
    OU_ID BIGINT,
    CLASS_ID BIGINT,
    SCHOOLAR_ID BIGINT)
AS
declare variable DOC_ID1 bigint;
declare variable DOC_ID2 bigint;
declare variable X smallint;
declare variable Y smallint;
declare variable DISTR_ID1 bigint;
declare variable OU_ID1 bigint;
declare variable CLASS_ID1 bigint;
declare variable OBJ_ID1 bigint;
declare variable D1 date;
declare variable F1 varchar(4000);
declare variable DISTR_ID2 bigint;
declare variable OU_ID2 bigint;
declare variable CLASS_ID2 bigint;
declare variable OBJ_ID2 bigint;
declare variable D2 date;
declare variable F2 varchar(4000);
BEGIN
    OBJ_ID1 = 0;
    OBJ_ID2 = 0;
    SCHOOLAR_ID = 0;

    IF (DEEP = 1) THEN
    BEGIN
        FOR
            SELECT L2.PARENT_ID, L2.OBJ_ID, L9.OBJ_ID, L10.OBJ_ID, D.VAL, F.VAL
            FROM LINKS L2
            JOIN LINKS L77 ON L77.PARENT_ID = L2.OBJ_ID AND L77.OBJ_TYPE_ID = 77 AND L77.DATE_DEL IS NULL
            JOIN LINKS L9 ON L9.PARENT_ID = L77.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 290) AND L9.DATE_DEL IS NULL
            JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
            JOIN VALD D ON D.OBJ_ID = L10.OBJ_ID AND D.PARAM_ID = 89 AND D.IS_DEL = 0
            JOIN VALS F ON F.OBJ_ID = L10.OBJ_ID AND F.PARAM_ID = 55 AND F.IS_DEL = 0
            WHERE L2.PARENT_ID = :I$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
            ORDER BY D.VAL, F.VAL
            INTO :DISTR_ID2, :OU_ID2, :CLASS_ID2, :OBJ_ID2, :D2, :F2
        DO
        BEGIN
            IF ((D1 = D2) AND (F1 = F2)) THEN
            BEGIN
                FOR
                    SELECT 1
                    FROM VALS I1
                    JOIN VALS I2 ON I1.VAL = I2.VAL AND I2.PARAM_ID = 56 AND I2.OBJ_ID = :OBJ_ID2 AND I2.IS_DEL = 0
                    WHERE I1.PARAM_ID = 56 AND I1.OBJ_ID = :OBJ_ID1 AND I1.IS_DEL = 0
                    INTO :X
                DO
                BEGIN
                    FOR
                        SELECT 1
                        FROM VALS O1
                        INNER JOIN VALS O2 ON O1.VAL = O2.VAL AND O2.PARAM_ID = 57 AND O2.OBJ_ID = :OBJ_ID2 AND O2.IS_DEL = 0
                        WHERE O1.PARAM_ID = 57 AND O1.OBJ_ID = :OBJ_ID1 AND O1.IS_DEL = 0
                        INTO :X
                    DO
                    BEGIN
                        Y = 0;

                        SELECT FIRST 1 1, L79.OBJ_ID, L79_.OBJ_ID
                        FROM LINKS L79
                        JOIN VALL T1 ON T1.OBJ_ID = L79.OBJ_ID AND T1.PARAM_ID = 441 AND T1.IS_DEL = 0
                        JOIN LINKS L79_ ON L79_.PARENT_ID = :OBJ_ID2 AND L79_.OBJ_TYPE_ID = 79 AND L79_.DATE_DEL IS NULL
                        JOIN VALL T2 ON T2.OBJ_ID = L79_.OBJ_ID AND T1.LISTVAL_ID = T2.LISTVAL_ID AND T2.PARAM_ID = 441 AND T2.IS_DEL = 0
                        WHERE L79.PARENT_ID = :OBJ_ID1 AND L79.OBJ_TYPE_ID = 79 AND L79.DATE_DEL IS NULL
                        INTO :Y, :DOC_ID1, :DOC_ID2;

                        IF (Y = 0) THEN
                        BEGIN
                            IF (SCHOOLAR_ID <> OBJ_ID1) THEN
                            BEGIN
                                DISTR_ID = DISTR_ID1;
                                OU_ID = OU_ID1;
                                CLASS_ID = CLASS_ID1;
                                SCHOOLAR_ID = OBJ_ID1;
                                SUSPEND;
                            END

                            IF (SCHOOLAR_ID <> OBJ_ID2) THEN
                            BEGIN
                                DISTR_ID = DISTR_ID2;
                                OU_ID = OU_ID2;
                                CLASS_ID = CLASS_ID2;
                                SCHOOLAR_ID = OBJ_ID2;
                                SUSPEND;
                            END
                        END
                        ELSE
                        BEGIN
                            Y = 0;

                            SELECT FIRST 1 1
                            FROM VALS S1
                            JOIN VALS N1 ON N1.OBJ_ID = S1.OBJ_ID AND N1.PARAM_ID = 559 AND N1.OBJ_ID = :DOC_ID1 AND N1.IS_DEL = 0
                            JOIN VALS S2 ON S1.VAL = S2.VAL AND S2.PARAM_ID = 442 AND S2.OBJ_ID = :DOC_ID2 AND S2.IS_DEL = 0
                            JOIN VALS N2 ON N1.VAL = N2.VAL AND N2.PARAM_ID = 559 AND N2.OBJ_ID = :DOC_ID2 AND N2.IS_DEL = 0
                            WHERE S1.PARAM_ID = 442 AND S1.OBJ_ID = :DOC_ID1 AND S1.IS_DEL = 0
                            INTO :Y;

                            IF (Y = 1) THEN
                            BEGIN
                                IF (SCHOOLAR_ID <> OBJ_ID1) THEN
                                BEGIN
                                    DISTR_ID = DISTR_ID1;
                                    OU_ID = OU_ID1;
                                    CLASS_ID = CLASS_ID1;
                                    SCHOOLAR_ID = OBJ_ID1;
                                    SUSPEND;
                                END

                                IF (SCHOOLAR_ID <> OBJ_ID2) THEN
                                BEGIN
                                    DISTR_ID = DISTR_ID2;
                                    OU_ID = OU_ID2;
                                    CLASS_ID = CLASS_ID2;
                                    SCHOOLAR_ID = OBJ_ID2;
                                    SUSPEND;
                                END
                            END
                        END
                    END
                END
            END

            DISTR_ID1 = DISTR_ID2;
            OU_ID1 = OU_ID2;
            CLASS_ID1 = CLASS_ID2;
            OBJ_ID1 = OBJ_ID2;
            D1 = D2;
            F1 = F2;
        END
    END

    IF (DEEP = 2) THEN
    BEGIN
        FOR
            SELECT L111.OBJ_ID, L2.OBJ_ID, L9.OBJ_ID, L10.OBJ_ID, D.VAL, F.VAL
            FROM LINKS L111
            JOIN LINKS L2 ON L2.PARENT_ID = L111.OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
            JOIN LINKS L77 ON L77.PARENT_ID = L2.OBJ_ID AND L77.OBJ_TYPE_ID = 77 AND L77.DATE_DEL IS NULL
            JOIN LINKS L9 ON L9.PARENT_ID = L77.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 290) AND L9.DATE_DEL IS NULL
            JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
            JOIN VALD D ON D.OBJ_ID = L10.OBJ_ID AND D.PARAM_ID = 89 AND D.IS_DEL = 0
            JOIN VALS F ON F.OBJ_ID = L10.OBJ_ID AND F.PARAM_ID = 55 AND F.IS_DEL = 0
            WHERE L111.PARENT_ID = :I$OBJ_ID AND L111.OBJ_TYPE_ID = 111 AND L111.DATE_DEL IS NULL
            ORDER BY D.VAL, F.VAL
            INTO :DISTR_ID2, :OU_ID2, :CLASS_ID2, :OBJ_ID2, :D2, :F2
        DO
        BEGIN
            IF ((D1 = D2) AND (F1 = F2)) THEN
            BEGIN
                FOR
                    SELECT 1
                    FROM VALS I1
                    JOIN VALS I2 ON I1.VAL = I2.VAL AND I2.PARAM_ID = 56 AND I2.OBJ_ID = :OBJ_ID2 AND I2.IS_DEL = 0
                    WHERE I1.PARAM_ID = 56 AND I1.OBJ_ID = :OBJ_ID1 AND I1.IS_DEL = 0
                    INTO :X
                DO
                BEGIN
                    FOR
                        SELECT 1
                        FROM VALS O1
                        JOIN VALS O2 ON O1.VAL = O2.VAL AND O2.PARAM_ID = 57 AND O2.OBJ_ID = :OBJ_ID2 AND O2.IS_DEL = 0
                        WHERE O1.PARAM_ID = 57 AND O1.OBJ_ID = :OBJ_ID1 AND O1.IS_DEL = 0
                        INTO :X
                    DO
                    BEGIN
                        Y = 0;

                        SELECT FIRST 1 1, L79.OBJ_ID, L79_.OBJ_ID
                        FROM LINKS L79
                        JOIN VALL T1 ON T1.OBJ_ID = L79.OBJ_ID AND T1.PARAM_ID = 441 AND T1.IS_DEL = 0
                        JOIN LINKS L79_ ON L79_.PARENT_ID = :OBJ_ID2 AND L79_.OBJ_TYPE_ID = 79 AND L79_.DATE_DEL IS NULL
                        JOIN VALL T2 ON T2.OBJ_ID = L79_.OBJ_ID AND T1.LISTVAL_ID = T2.LISTVAL_ID AND T2.PARAM_ID = 441 AND T2.IS_DEL = 0
                        WHERE L79.PARENT_ID = :OBJ_ID1 AND L79.OBJ_TYPE_ID = 79 AND L79.DATE_DEL IS NULL
                        INTO :Y, :DOC_ID1, :DOC_ID2;

                        IF (Y = 0) THEN
                        BEGIN
                            IF (SCHOOLAR_ID <> OBJ_ID1) THEN
                            BEGIN
                                DISTR_ID = DISTR_ID1;
                                OU_ID = OU_ID1;
                                CLASS_ID = CLASS_ID1;
                                SCHOOLAR_ID = OBJ_ID1;
                                SUSPEND;
                            END

                            IF (SCHOOLAR_ID <> OBJ_ID2) THEN
                            BEGIN
                                DISTR_ID = DISTR_ID2;
                                OU_ID = OU_ID2;
                                CLASS_ID = CLASS_ID2;
                                SCHOOLAR_ID = OBJ_ID2;
                                SUSPEND;
                            END
                        END
                        ELSE
                        BEGIN
                            Y = 0;

                            SELECT FIRST 1 1
                            FROM VALS S1
                            JOIN VALS N1 ON N1.OBJ_ID = S1.OBJ_ID AND N1.PARAM_ID = 559 AND N1.OBJ_ID = :DOC_ID1 AND N1.IS_DEL = 0
                            JOIN VALS S2 ON S1.VAL = S2.VAL AND S2.PARAM_ID = 442 AND S2.OBJ_ID = :DOC_ID2 AND S2.IS_DEL = 0
                            JOIN VALS N2 ON N1.VAL = N2.VAL AND N2.PARAM_ID = 559 AND N2.OBJ_ID = :DOC_ID2 AND N2.IS_DEL = 0
                            WHERE S1.PARAM_ID = 442 AND S1.OBJ_ID = :DOC_ID1 AND S1.IS_DEL = 0
                            INTO :Y;

                            IF (Y = 1) THEN
                            BEGIN
                                IF (SCHOOLAR_ID <> OBJ_ID1) THEN
                                BEGIN
                                    DISTR_ID = DISTR_ID1;
                                    OU_ID = OU_ID1;
                                    CLASS_ID = CLASS_ID1;
                                    SCHOOLAR_ID = OBJ_ID1;
                                    SUSPEND;
                                END

                                IF (SCHOOLAR_ID <> OBJ_ID2) THEN
                                BEGIN
                                    DISTR_ID = DISTR_ID2;
                                    OU_ID = OU_ID2;
                                    CLASS_ID = CLASS_ID2;
                                    SCHOOLAR_ID = OBJ_ID2;
                                    SUSPEND;
                                END
                            END
                        END
                    END
                END
            END

            DISTR_ID1 = DISTR_ID2;
            OU_ID1 = OU_ID2;
            CLASS_ID1 = CLASS_ID2;
            OBJ_ID1 = OBJ_ID2;
            D1 = D2;
            F1 = F2;
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_TWINS_FIO (
    I$OBJ_ID BIGINT,
    DEEP SMALLINT,
    I$USER_ID BIGINT)
RETURNS (
    DISTR VARCHAR(400),
    OU VARCHAR(4000),
    CLASS VARCHAR(400),
    F VARCHAR(400),
    I VARCHAR(400),
    O VARCHAR(400),
    D DATE,
    DOC VARCHAR(400),
    SER VARCHAR(400),
    NUM VARCHAR(400),
    SCHOOLAR_ID BIGINT)
AS
declare variable DISTR_ID bigint;
declare variable OU_ID bigint;
declare variable CLASS_ID bigint;
declare variable PASSPORT_ID bigint;
declare variable LANG_CODE varchar(2);
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :LANG_CODE;

    FOR
        SELECT RT.DISTR_ID, RT.OU_ID, RT.CLASS_ID, RT.SCHOOLAR_ID
        FROM R_TWINS_ID(:I$OBJ_ID, :DEEP) RT
        INTO :DISTR_ID, :OU_ID, :CLASS_ID, :SCHOOLAR_ID
    DO
    BEGIN
        F = NULL;
        I = NULL;
        O = NULL;
        D = NULL;
        DOC = NULL;
        NUM = NULL;
        SER = NULL;
        PASSPORT_ID = NULL;

        IF (DISTR_ID IS NOT NULL) THEN
        BEGIN
            SELECT CAPTION FROM OBJECT_CAPTION_GET(:DISTR_ID, NULL, NULL, :I$USER_ID) INTO :DISTR;
        END
        SELECT V.VAL FROM VALS V WHERE V.PARAM_ID = 2  AND V.OBJ_ID = :OU_ID AND V.IS_DEL = 0 INTO :OU;
        SELECT CAPTION FROM OBJECT_CAPTION_GET(:CLASS_ID, NULL, NULL, :I$USER_ID) INTO :CLASS;
        SELECT V.VAL FROM VALS V WHERE V.PARAM_ID = 55 AND V.OBJ_ID = :SCHOOLAR_ID AND V.IS_DEL = 0 INTO :F;
        SELECT V.VAL FROM VALS V WHERE V.PARAM_ID = 56 AND V.OBJ_ID = :SCHOOLAR_ID AND V.IS_DEL = 0 INTO :I;
        SELECT V.VAL FROM VALS V WHERE V.PARAM_ID = 57 AND V.OBJ_ID = :SCHOOLAR_ID AND V.IS_DEL = 0 INTO :O;
        SELECT V.VAL FROM VALD V WHERE V.PARAM_ID = 89 AND V.OBJ_ID = :SCHOOLAR_ID AND V.IS_DEL = 0 INTO :D;

        SELECT FIRST 1 L.OBJ_ID, R.VAL
        FROM LINKS L
        JOIN VALL V ON V.OBJ_ID = L.OBJ_ID AND V.PARAM_ID = 441 AND V.IS_DEL = 0
        JOIN LISTVALS LV ON LV.LISTVAL_ID = V.LISTVAL_ID
        LEFT JOIN RES_GET(LV.RES_ID,  :LANG_CODE) R ON 1=1
        WHERE L.PARENT_ID = :SCHOOLAR_ID AND L.OBJ_TYPE_ID = 79 AND L.DATE_DEL IS NULL
        ORDER BY LV.SORT_ORDER
        INTO :PASSPORT_ID, :DOC;

        SELECT V.VAL FROM VALS V WHERE V.PARAM_ID = 442 AND V.OBJ_ID = :PASSPORT_ID AND V.IS_DEL = 0 INTO :SER;
        SELECT V.VAL FROM VALS V WHERE V.PARAM_ID = 559 AND V.OBJ_ID = :PASSPORT_ID AND V.IS_DEL = 0 INTO :NUM;

        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_TWINS_HEAD RETURNS (
    V1 VARCHAR(30),
    V2 VARCHAR(30))
AS
DECLARE VARIABLE V$OU_LICENCE_TYPE VARCHAR(1);
BEGIN
  SELECT STATUS FROM OU_LICENCE_TYPE INTO :V$OU_LICENCE_TYPE;
  V1 = IIF(:V$OU_LICENCE_TYPE = 'D', 'ОООД', 'ОУ');
  V2 = IIF(:V$OU_LICENCE_TYPE = 'D', 'Группа', 'Класс');
  SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_TWINS_ID (
    I$OBJ_ID BIGINT,
    DEEP SMALLINT)
RETURNS (
    DISTR_ID BIGINT,
    OU_ID BIGINT,
    CLASS_ID BIGINT,
    SCHOOLAR_ID BIGINT)
AS
declare variable SD date;
declare variable SF varchar(500);
declare variable SI varchar(500);
declare variable SQ varchar(500);
declare variable V$MATCH smallint;
declare variable V$DUPL_ID bigint;
declare variable V$ONCE bigint;
declare variable V$PERSON_ID bigint;
declare variable OBJ_ID1 bigint;
declare variable OBJ_ID2 bigint;
declare variable F1 varchar(100);
declare variable I1 varchar(100);
declare variable O1 varchar(100);
declare variable D1 date;
declare variable OU_ID2 bigint;
declare variable CLASS_ID2 bigint;
declare variable D2 date;
declare variable F2 varchar(100);
declare variable I2 varchar(100);
declare variable O2 varchar(100);
declare variable X smallint;
declare variable Y smallint;
declare variable DOC_ID1 bigint;
declare variable DOC_ID2 bigint;
declare variable DISTR_ID1 bigint;
declare variable OU_ID1 bigint;
declare variable CLASS_ID1 bigint;
declare variable DISTR_ID2 bigint;
BEGIN
    SCHOOLAR_ID = 0;

    /*FOR
        SELECT NULL, L7.PARENT_ID, L9.OBJ_ID, L10.OBJ_ID, V89.VAL, V55.SVAL, V56.SVAL, V57.SVAL
        FROM LINKS L7
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
        JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        JOIN VALD V89 ON V89.OBJ_ID = L10.OBJ_ID AND V89.PARAM_ID = 89 AND V89.IS_DEL = 0
        JOIN VALS V55 ON V55.OBJ_ID = L10.OBJ_ID AND V55.PARAM_ID = 55 AND V55.IS_DEL = 0
        JOIN VALS V56 ON V56.OBJ_ID = L10.OBJ_ID AND V56.PARAM_ID = 56 AND V56.IS_DEL = 0
        LEFT JOIN VALS V57 ON V57.OBJ_ID = L10.OBJ_ID AND V57.PARAM_ID = 57 AND V57.IS_DEL = 0
        WHERE :DEEP = 0 AND L7.PARENT_ID = :I$OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
        UNION
        SELECT L2.PARENT_ID, L7.PARENT_ID, L9.OBJ_ID, L10.OBJ_ID, V89.VAL, V55.SVAL, V56.SVAL, V57.SVAL
        FROM LINKS L2
        JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
        JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        JOIN VALD V89 ON V89.OBJ_ID = L10.OBJ_ID AND V89.PARAM_ID = 89 AND V89.IS_DEL = 0
        JOIN VALS V55 ON V55.OBJ_ID = L10.OBJ_ID AND V55.PARAM_ID = 55 AND V55.IS_DEL = 0
        JOIN VALS V56 ON V56.OBJ_ID = L10.OBJ_ID AND V56.PARAM_ID = 56 AND V56.IS_DEL = 0
        LEFT JOIN VALS V57 ON V57.OBJ_ID = L10.OBJ_ID AND V57.PARAM_ID = 57 AND V57.IS_DEL = 0
        WHERE :DEEP = 1 AND L2.PARENT_ID = :I$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
        UNION
        SELECT L2.PARENT_ID, L7.PARENT_ID, L9.OBJ_ID, L10.OBJ_ID, V89.VAL, V55.SVAL, V56.SVAL, V57.SVAL
        FROM LINKS L111
        JOIN LINKS L2 ON L2.PARENT_ID = L111.OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
        JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
        JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        JOIN VALD V89 ON V89.OBJ_ID = L10.OBJ_ID AND V89.PARAM_ID = 89 AND V89.IS_DEL = 0
        JOIN VALS V55 ON V55.OBJ_ID = L10.OBJ_ID AND V55.PARAM_ID = 55 AND V55.IS_DEL = 0
        JOIN VALS V56 ON V56.OBJ_ID = L10.OBJ_ID AND V56.PARAM_ID = 56 AND V56.IS_DEL = 0
        LEFT JOIN VALS V57 ON V57.OBJ_ID = L10.OBJ_ID AND V57.PARAM_ID = 57 AND V57.IS_DEL = 0
        WHERE :DEEP = 2 AND L111.PARENT_ID = :I$OBJ_ID AND L111.OBJ_TYPE_ID = 111 AND L111.DATE_DEL IS NULL
        ORDER BY 5, 6, 7, 8
        INTO :DISTR_ID, :OU_ID, :CLASS_ID, :V$PERSON_ID, :SD, :SF, :SI, :SQ
    DO
    BEGIN
        -- После того как выдали всех дубликатов на первом попадании - далее не выдаем
        -- Дубликаты всегда ищем по возрастанию ID, причем выдаем всегда только самого себя - копия ответит за себя позднее
        V$ONCE = 0;

        FOR
            SELECT L10.OBJ_ID
            FROM VALS V55
            JOIN VALS V56 ON V56.OBJ_ID = V55.OBJ_ID AND V56.PARAM_ID = 56 AND V56.IS_DEL = 0 AND V56.SVAL = :SI
            LEFT JOIN VALS V57 ON V57.OBJ_ID = V55.OBJ_ID AND V57.PARAM_ID = 57 AND V57.IS_DEL = 0
            JOIN VALD V89 ON V89.OBJ_ID = V55.OBJ_ID AND V89.PARAM_ID = 89 AND V89.IS_DEL = 0 AND V89.VAL = :SD
            JOIN LINKS L10 ON L10.PARENT_TYPE_ID = 9 AND L10.OBJ_ID = V55.OBJ_ID AND L10.DATE_DEL IS NULL
            -- Сверка, чтобы ученик не оказался в удаленной группе
            JOIN LINKS LP8 ON LP8.PARENT_TYPE_ID = 8 AND LP8.OBJ_ID = L10.PARENT_ID AND LP8.DATE_DEL IS NULL
            WHERE V55.PARAM_ID = 55 AND V55.IS_DEL = 0 AND V55.SVAL = :SF AND (V57.VAL IS NULL OR V57.SVAL = :SQ) AND V55.OBJ_ID <> :V$PERSON_ID
            INTO :V$DUPL_ID
        DO
        BEGIN

            -- Есть ли совпадение по документам ?
            V$MATCH = 0;
            SELECT FIRST 1 1
            FROM LINKS L79
            JOIN VALS S1 ON S1.OBJ_ID = L79.OBJ_ID AND S1.PARAM_ID = 442 AND S1.IS_DEL = 0
            JOIN VALS N1 ON N1.OBJ_ID = L79.OBJ_ID AND N1.PARAM_ID = 559 AND N1.IS_DEL = 0
            JOIN LINKS L79_2 ON L79_2.PARENT_ID = :V$DUPL_ID AND L79_2.OBJ_TYPE_ID = 79 AND L79_2.DATE_DEL IS NULL
            JOIN VALS S2 ON S2.OBJ_ID = L79_2.OBJ_ID AND S2.PARAM_ID = 442 AND S2.IS_DEL = 0
            JOIN VALS N2 ON N2.OBJ_ID = L79_2.OBJ_ID AND N2.PARAM_ID = 559 AND N2.IS_DEL = 0
            LEFT JOIN UNI_STRING_COMPARE(S1.VAL, S2.VAL) USCS ON 1 = 1
            LEFT JOIN UNI_STRING_COMPARE(N1.VAL, N2.VAL) USCN ON 1 = 1
            WHERE L79.PARENT_ID = :V$PERSON_ID AND L79.OBJ_TYPE_ID = 79 AND L79.DATE_DEL IS NULL AND USCN.RESULT = 1 AND USCS.RESULT = 1
            INTO :V$MATCH;

            IF(V$MATCH = 1 AND V$ONCE = 0) THEN
            BEGIN
                V$ONCE = 1;
                SCHOOLAR_ID = V$PERSON_ID;
                SUSPEND;
                BREAK;
            END

        END
    END*/

    OBJ_ID1 = 0;
    OBJ_ID2 = 0;
    SCHOOLAR_ID = 0;

    /*  Инициализация  D1, F1, I1 и O1  */
    F1 = '';
    I1 = '';
    O1 = '';
    D1 = CURRENT_DATE;

    IF (DEEP = 0) THEN
    BEGIN
        FOR SELECT L7.PARENT_ID, L9.OBJ_ID, L10.OBJ_ID, D.VAL, F.VAL, I.VAL
            FROM LINKS L7
            INNER JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID
            INNER JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID
            INNER JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID
            INNER JOIN VALD D ON D.OBJ_ID = L10.OBJ_ID
            INNER JOIN VALS F ON F.OBJ_ID = L10.OBJ_ID
            INNER JOIN VALS I ON I.OBJ_ID = L10.OBJ_ID
            WHERE L7.PARENT_ID = :I$OBJ_ID
              AND L7.OBJ_TYPE_ID = 7
              AND L7.DATE_DEL IS NULL
              AND L8.OBJ_TYPE_ID = 8
              AND L8.DATE_DEL IS NULL
              AND L9.OBJ_TYPE_ID = 9
              AND L9.DATE_DEL IS NULL
              AND L10.OBJ_TYPE_ID = 10
              AND L10.DATE_DEL IS NULL
              AND D.PARAM_ID = 89
              AND D.IS_DEL = 0
              AND F.PARAM_ID = 55
              AND F.IS_DEL = 0
              AND I.PARAM_ID = 56
              AND I.IS_DEL = 0
            ORDER BY D.VAL, F.VAL, I.VAL
            INTO :OU_ID2, :CLASS_ID2, :OBJ_ID2, :D2, :F2, :I2
        DO
        BEGIN
            IF ((D1 = D2) AND (F1 = F2) AND (I1 = I2)) THEN
            BEGIN
                FOR SELECT 1
                    FROM VALS O1
                    INNER JOIN VALS O2 ON O1.VAL = O2.VAL
                    WHERE O1.PARAM_ID = 57
                      AND O1.OBJ_ID = :OBJ_ID1
                      AND O1.IS_DEL = 0
                      AND O2.PARAM_ID = 57
                      AND O2.OBJ_ID = :OBJ_ID2
                      AND O2.IS_DEL = 0
                    INTO :X
                DO
                BEGIN
                    Y = 0;

                    SELECT FIRST 1 1, L79.OBJ_ID, L79_.OBJ_ID
                    FROM LINKS L79
                    INNER JOIN VALL T1 ON T1.OBJ_ID = L79.OBJ_ID
                    INNER JOIN LINKS L79_ ON 1 = 1
                    INNER JOIN VALL T2 ON T2.OBJ_ID = L79_.OBJ_ID AND T1.LISTVAL_ID = T2.LISTVAL_ID
                    WHERE L79.PARENT_ID = :OBJ_ID1
                      AND L79.OBJ_TYPE_ID = 79
                      AND L79.DATE_DEL IS NULL
                      AND T1.PARAM_ID = 441
                      AND T1.IS_DEL = 0
                      AND L79_.PARENT_ID = :OBJ_ID2
                      AND L79_.OBJ_TYPE_ID = 79
                      AND L79_.DATE_DEL IS NULL
                      AND T2.PARAM_ID = 441
                      AND T2.IS_DEL = 0
                    INTO :Y, :DOC_ID1, :DOC_ID2;

                    IF (Y = 0) THEN
                    BEGIN
                        IF (SCHOOLAR_ID <> OBJ_ID1) THEN
                        BEGIN
                            DISTR_ID = DISTR_ID1;
                            OU_ID = OU_ID1;
                            CLASS_ID = CLASS_ID1;
                            SCHOOLAR_ID = OBJ_ID1;
                            SUSPEND;
                        END

                        IF (SCHOOLAR_ID <> OBJ_ID2) THEN
                        BEGIN
                            DISTR_ID = DISTR_ID2;
                            OU_ID = OU_ID2;
                            CLASS_ID = CLASS_ID2;
                            SCHOOLAR_ID = OBJ_ID2;
                            SUSPEND;
                        END
                    END
                    ELSE
                    BEGIN
                        Y = 0;

                        SELECT FIRST 1 1
                        FROM VALS S1
                        INNER JOIN VALS N1 ON N1.OBJ_ID = S1.OBJ_ID
                        INNER JOIN VALS S2 ON 1=1
                        INNER JOIN VALS N2 ON 1=1
                        LEFT JOIN UNI_STRING_COMPARE(S1.VAL, S2.VAL) USCS ON 1=1
                        LEFT JOIN UNI_STRING_COMPARE(N1.VAL, N2.VAL) USCN ON 1=1
                        WHERE S1.PARAM_ID = 442
                          AND S1.OBJ_ID = :DOC_ID1
                          AND S1.IS_DEL = 0
                          AND N1.PARAM_ID = 559
                          AND N1.OBJ_ID = :DOC_ID1
                          AND N1.IS_DEL = 0
                          AND S2.PARAM_ID = 442
                          AND S2.OBJ_ID = :DOC_ID2
                          AND S2.IS_DEL = 0
                          AND N2.PARAM_ID = 559
                          AND N2.OBJ_ID = :DOC_ID2
                          AND N2.IS_DEL = 0
                          AND USCN.RESULT = 1
                          AND USCS.RESULT = 1
                        INTO :Y;

                        IF (Y = 1) THEN
                        BEGIN
                            IF (SCHOOLAR_ID <> OBJ_ID1) THEN
                            BEGIN
                                DISTR_ID = DISTR_ID1;
                                OU_ID = OU_ID1;
                                CLASS_ID = CLASS_ID1;
                                SCHOOLAR_ID = OBJ_ID1;
                                SUSPEND;
                            END

                            IF (SCHOOLAR_ID <> OBJ_ID2) THEN
                            BEGIN
                                DISTR_ID = DISTR_ID2;
                                OU_ID = OU_ID2;
                                CLASS_ID = CLASS_ID2;
                                SCHOOLAR_ID = OBJ_ID2;
                                SUSPEND;
                            END
                        END
                    END
                END
            END

            OU_ID1 = OU_ID2;
            CLASS_ID1 = CLASS_ID2;
            OBJ_ID1 = OBJ_ID2;
            D1 = D2;
            F1 = F2;
            I1 = I2;
        END
    END

    IF (DEEP = 1) THEN
    BEGIN
        FOR SELECT L2.OBJ_ID, L9.OBJ_ID, L10.OBJ_ID, D.VAL, F.VAL, I.VAL
            FROM LINKS L2
            INNER JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID
            INNER JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID
            INNER JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID
            INNER JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID
            INNER JOIN VALD D ON D.OBJ_ID = L10.OBJ_ID
            INNER JOIN VALS F ON F.OBJ_ID = L10.OBJ_ID
            INNER JOIN VALS I ON I.OBJ_ID = L10.OBJ_ID
            WHERE L2.PARENT_ID = :I$OBJ_ID
              AND L2.OBJ_TYPE_ID = 2
              AND L2.DATE_DEL IS NULL
              AND L7.OBJ_TYPE_ID = 7
              AND L7.DATE_DEL IS NULL
              AND L8.OBJ_TYPE_ID = 8
              AND L8.DATE_DEL IS NULL
              AND L9.OBJ_TYPE_ID = 9
              AND L9.DATE_DEL IS NULL
              AND L10.OBJ_TYPE_ID = 10
              AND L10.DATE_DEL IS NULL
              AND D.PARAM_ID = 89
              AND D.IS_DEL = 0
              AND F.PARAM_ID = 55
              AND F.IS_DEL = 0
              AND I.PARAM_ID = 56
              AND I.IS_DEL = 0
            ORDER BY D.VAL, F.VAL, I.VAL
            INTO :OU_ID2, :CLASS_ID2, :OBJ_ID2, :D2, :F2, :I2
        DO
        BEGIN
            IF ((D1 = D2) AND (F1 = F2) AND (I1 = I2)) THEN
            BEGIN
                FOR SELECT 1
                    FROM VALS O1
                    INNER JOIN VALS O2 ON O1.VAL = O2.VAL
                    WHERE O1.PARAM_ID = 57
                      AND O1.OBJ_ID = :OBJ_ID1
                      AND O1.IS_DEL = 0
                      AND O2.PARAM_ID = 57
                      AND O2.OBJ_ID = :OBJ_ID2
                      AND O2.IS_DEL = 0
                    INTO :X
                DO
                BEGIN
                    Y = 0;
    
                    SELECT FIRST 1 1, L79.OBJ_ID, L79_.OBJ_ID
                    FROM LINKS L79
                    INNER JOIN VALL T1 ON T1.OBJ_ID = L79.OBJ_ID
                    INNER JOIN LINKS L79_ ON 1 = 1
                    INNER JOIN VALL T2 ON T2.OBJ_ID = L79_.OBJ_ID AND T1.LISTVAL_ID = T2.LISTVAL_ID
                    WHERE L79.PARENT_ID = :OBJ_ID1
                      AND L79.OBJ_TYPE_ID = 79
                      AND L79.DATE_DEL IS NULL
                      AND T1.PARAM_ID = 441
                      AND T1.IS_DEL = 0
                      AND L79_.PARENT_ID = :OBJ_ID2
                      AND L79_.OBJ_TYPE_ID = 79
                      AND L79_.DATE_DEL IS NULL
                      AND T2.PARAM_ID = 441
                      AND T2.IS_DEL = 0
                    INTO :Y, :DOC_ID1, :DOC_ID2;
    
                    IF (Y = 0) THEN
                    BEGIN
                        IF (SCHOOLAR_ID <> OBJ_ID1) THEN
                        BEGIN
                            DISTR_ID = DISTR_ID1;
                            OU_ID = OU_ID1;
                            CLASS_ID = CLASS_ID1;
                            SCHOOLAR_ID = OBJ_ID1;
                            SUSPEND;
                        END
    
                        IF (SCHOOLAR_ID <> OBJ_ID2) THEN
                        BEGIN
                            DISTR_ID = DISTR_ID2;
                            OU_ID = OU_ID2;
                            CLASS_ID = CLASS_ID2;
                            SCHOOLAR_ID = OBJ_ID2;
                            SUSPEND;
                        END
                    END
                    ELSE
                    BEGIN
                        Y = 0;
    
                        SELECT FIRST 1 1
                        FROM VALS S1
                        INNER JOIN VALS N1 ON N1.OBJ_ID = S1.OBJ_ID
                        INNER JOIN VALS S2 ON 1=1
                        INNER JOIN VALS N2 ON 1=1
                        LEFT JOIN UNI_STRING_COMPARE(S1.VAL, S2.VAL) USCS ON 1=1
                        LEFT JOIN UNI_STRING_COMPARE(N1.VAL, N2.VAL) USCN ON 1=1
                        WHERE S1.PARAM_ID = 442
                          AND S1.OBJ_ID = :DOC_ID1
                          AND S1.IS_DEL = 0
                          AND N1.PARAM_ID = 559
                          AND N1.OBJ_ID = :DOC_ID1
                          AND N1.IS_DEL = 0
                          AND S2.PARAM_ID = 442
                          AND S2.OBJ_ID = :DOC_ID2
                          AND S2.IS_DEL = 0
                          AND N2.PARAM_ID = 559
                          AND N2.OBJ_ID = :DOC_ID2
                          AND N2.IS_DEL = 0
                          AND USCN.RESULT = 1
                          AND USCS.RESULT = 1
                        INTO :Y;
    
                        IF (Y = 1) THEN
                        BEGIN
                            IF (SCHOOLAR_ID <> OBJ_ID1) THEN
                            BEGIN
                                DISTR_ID = DISTR_ID1;
                                OU_ID = OU_ID1;
                                CLASS_ID = CLASS_ID1;
                                SCHOOLAR_ID = OBJ_ID1;
                                SUSPEND;
                            END
    
                            IF (SCHOOLAR_ID <> OBJ_ID2) THEN
                            BEGIN
                                DISTR_ID = DISTR_ID2;
                                OU_ID = OU_ID2;
                                CLASS_ID = CLASS_ID2;
                                SCHOOLAR_ID = OBJ_ID2;
                                SUSPEND;
                            END
                        END
                    END
                END
            END

            OU_ID1 = OU_ID2;
            CLASS_ID1 = CLASS_ID2;
            OBJ_ID1 = OBJ_ID2;
            D1 = D2;
            F1 = F2;
            I1 = I2;
        END
    END

    IF (DEEP = 2) THEN
    BEGIN
        FOR SELECT L111.OBJ_ID, L2.OBJ_ID, L9.OBJ_ID, L10.OBJ_ID, D.VAL, cast(F.VAL as varchar(50)), cast(I.VAL as varchar(50)) , cast(O.VAL as varchar(50))
            FROM LINKS L111                                     -- Район
            INNER JOIN LINKS L2 ON L2.PARENT_ID = L111.OBJ_ID   -- школы
            INNER JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID     -- Уровень образования
            INNER JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID     -- Этап обучения
            INNER JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID     -- Учебный коллектив/Группа
            INNER JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID   -- Обучающийся, воспитанник
            INNER JOIN VALD D ON D.OBJ_ID = L10.OBJ_ID          -- Дата рождения ученика
            INNER JOIN VALS F ON F.OBJ_ID = L10.OBJ_ID          -- Фамилия ученика
            INNER JOIN VALS I ON I.OBJ_ID = L10.OBJ_ID          -- Имя ученика
            INNER JOIN VALS O ON O.OBJ_ID = L10.OBJ_ID          -- Отчество
            WHERE L111.PARENT_ID = :I$OBJ_ID
              AND L111.OBJ_TYPE_ID = 111
              AND L111.DATE_DEL IS NULL
              AND L2.OBJ_TYPE_ID = 2
              AND L2.DATE_DEL IS NULL
              AND L7.OBJ_TYPE_ID = 7
              AND L7.DATE_DEL IS NULL
              AND L8.OBJ_TYPE_ID = 8
              AND L8.DATE_DEL IS NULL
              AND L9.OBJ_TYPE_ID = 9
              AND L9.DATE_DEL IS NULL
              AND L10.OBJ_TYPE_ID = 10
              AND L10.DATE_DEL IS NULL
              AND D.PARAM_ID = 89      -- Дата рождения
              AND D.IS_DEL = 0
              AND F.PARAM_ID = 55      -- Фамилия
              AND F.IS_DEL = 0
              AND I.PARAM_ID = 56      -- Имя
              AND I.IS_DEL = 0
              AND O.PARAM_ID = 57      -- Отчество
              AND O.IS_DEL = 0
            ORDER BY cast(F.VAL as varchar(50)), cast(I.VAL as varchar(50)) , cast(O.VAL as varchar(50)), D.VAL     -- Сортируем список по ФИО и дате рождения
            INTO :DISTR_ID2, :OU_ID2, :CLASS_ID2, :OBJ_ID2, :D2, :F2, :I2, :O2
        DO
        BEGIN
            IF ((D1 = D2) AND (F1 = F2) AND (I1 = I2) AND (O1 = O2) AND (OBJ_ID1 <> OBJ_ID2)) THEN
             /* Ирина Невзорова: В отчёте Дубли нас не интересуют дети, шагающие через класс, их в отчёте быть не должно. (redmine/issues/1600)
                В одной и той же школе идентификатор учащегося совпадает для разных классов , поэтому добавлена проверка (OBJ_ID1 <> OBJ_ID2) */
            BEGIN
                Y = 0;
    
                SELECT FIRST 1 1, L79.OBJ_ID, L79_.OBJ_ID    -- идентификаторы  Документов удостоверяющих личность
                FROM LINKS L79
                INNER JOIN VALL T1 ON T1.OBJ_ID = L79.OBJ_ID
                INNER JOIN LINKS L79_ ON 1 = 1
                INNER JOIN VALL T2 ON T2.OBJ_ID = L79_.OBJ_ID AND T1.LISTVAL_ID = T2.LISTVAL_ID  -- проверка что один тип документа удостоверяющий личность, например 1370 -- Свидетельство о рождении
                WHERE L79.PARENT_ID = :OBJ_ID1
                  AND L79.OBJ_TYPE_ID = 79      -- Документ удостоверяющий личность
                  AND L79.DATE_DEL IS NULL
                  AND T1.PARAM_ID = 441         -- Тип документа
                  AND T1.IS_DEL = 0
                  AND L79_.PARENT_ID = :OBJ_ID2
                  AND L79_.OBJ_TYPE_ID = 79     -- Документ удостоверяющий личность
                  AND L79_.DATE_DEL IS NULL
                  AND T2.PARAM_ID = 441         -- Тип документа
                  AND T2.IS_DEL = 0
                INTO :Y, :DOC_ID1, :DOC_ID2;

                IF (Y = 0) THEN     -- если не один и тотже  Документ удостоверяющий личность добавляем в выборку сравниваемых учеников
                BEGIN
                    IF (SCHOOLAR_ID <> OBJ_ID1) THEN
                    BEGIN
                        DISTR_ID = DISTR_ID1;
                        OU_ID = OU_ID1;
                        CLASS_ID = CLASS_ID1;
                        SCHOOLAR_ID = OBJ_ID1;
                        SUSPEND;
                    END

                    IF (SCHOOLAR_ID <> OBJ_ID2) THEN
                    BEGIN
                        DISTR_ID = DISTR_ID2;
                        OU_ID = OU_ID2;
                        CLASS_ID = CLASS_ID2;
                        SCHOOLAR_ID = OBJ_ID2;
                        SUSPEND;
                    END
                END
                ELSE
                BEGIN   -- если один и тотже  Документ удостоверяющий личность
                    Y = 0;

                    SELECT FIRST 1 1
                    FROM VALS S1
                    INNER JOIN VALS N1 ON N1.OBJ_ID = S1.OBJ_ID
                    INNER JOIN VALS S2 ON 1=1
                    INNER JOIN VALS N2 ON 1=1
                    LEFT JOIN UNI_STRING_COMPARE(S1.VAL, S2.VAL) USCS ON 1=1
                    LEFT JOIN UNI_STRING_COMPARE(N1.VAL, N2.VAL) USCN ON 1=1
                    WHERE S1.PARAM_ID = 442    -- Серия
                      AND S1.OBJ_ID = :DOC_ID1
                      AND S1.IS_DEL = 0        -- Номер
                      AND N1.PARAM_ID = 559
                      AND N1.OBJ_ID = :DOC_ID1
                      AND N1.IS_DEL = 0
                      AND S2.PARAM_ID = 442    -- Серия
                      AND S2.OBJ_ID = :DOC_ID2
                      AND S2.IS_DEL = 0
                      AND N2.PARAM_ID = 559    -- Номер
                      AND N2.OBJ_ID = :DOC_ID2
                      AND N2.IS_DEL = 0
                      AND USCN.RESULT = 1
                      AND USCS.RESULT = 1
                    INTO :Y;

                    IF (Y = 1) THEN    -- если серия и номер Документов удостоверяющих личности совпадают, добавляем в выборку сравниваемых учеников
                    BEGIN
                        IF (SCHOOLAR_ID <> OBJ_ID1) THEN
                        BEGIN
                            DISTR_ID = DISTR_ID1;
                            OU_ID = OU_ID1;
                            CLASS_ID = CLASS_ID1;
                            SCHOOLAR_ID = OBJ_ID1;
                            SUSPEND;
                        END

                        IF (SCHOOLAR_ID <> OBJ_ID2) THEN
                        BEGIN
                            DISTR_ID = DISTR_ID2;
                            OU_ID = OU_ID2;
                            CLASS_ID = CLASS_ID2;
                            SCHOOLAR_ID = OBJ_ID2;
                            SUSPEND;
                        END
                    END
                END
            END

            DISTR_ID1 = DISTR_ID2;
            OU_ID1 = OU_ID2;
            CLASS_ID1 = CLASS_ID2;
            OBJ_ID1 = OBJ_ID2;
            D1 = D2;
            F1 = F2;
            I1 = I2;
            O1 = O2;
        END
    END

END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE R_WORKER_BY_NAME_GET (
    I$FIRST_NAME VARCHAR(4000))
RETURNS (
    SCHOLAR_ID BIGINT,
    OU_CAPTION VARCHAR(4000),
    STRUCTURE_CAPTION VARCHAR(400),
    CLASS_CAPTION VARCHAR(400),
    F VARCHAR(400),
    I VARCHAR(400),
    O VARCHAR(400),
    CLASS_ID BIGINT,
    STRUCTURE_ID BIGINT,
    LINK_ID BIGINT,
    CLASS_TYPE_ID BIGINT,
    D DATE)
AS
declare variable OBJ_ID bigint;
declare variable TYPE_ID bigint;
declare variable OU_ID bigint;
declare variable V varchar(4000);
declare variable V$OU_LICENCE_TYPE varchar(1);
BEGIN
    /* ROOT OBJECT: OU  OR DISTR OR REGION*/
    /* TYPE OF ROOT OBJECT: 111 - DISTR, 112 - REGION  */
    SELECT STATUS FROM OU_LICENCE_TYPE INTO :V$OU_LICENCE_TYPE;

    SELECT FIRST 1 L.OBJ_ID, L.OBJ_TYPE_ID
    FROM LINKS L
    WHERE L.PARENT_ID IS NULL
      AND L.OBJ_TYPE_ID IN (2, 111, 112)
      AND L.DATE_DEL IS NULL
    INTO :OBJ_ID, :TYPE_ID;

    IF (:TYPE_ID = 112 AND (SELECT STATUS FROM OU_LICENCE_TYPE) = 'C') THEN
    BEGIN
        TYPE_ID = 111;
    END

    V = UPPER(I$FIRST_NAME);

    /* SCHOOL */
    IF (TYPE_ID = 2) THEN
    BEGIN
        FOR
            SELECT L14.LINK_ID,
                   L14.PARENT_ID,
                   L14.PARENT_ID,
                   L14.PARENT_TYPE_ID,
                   L14.OBJ_ID,
                   V59.VAL,
                   NULL

            FROM LINKS L14

            JOIN VALS V59
            ON V59.OBJ_ID = L14.OBJ_ID
            AND V59.PARAM_ID = 59
            AND V59.IS_DEL = 0
            AND UPPER(V59.VAL) STARTING WITH :V

            WHERE L14.PARENT_ID = :OBJ_ID
            AND L14.OBJ_TYPE_ID = 14
            AND L14.DATE_DEL IS NULL

            UNION ALL

            SELECT L14.LINK_ID,
                   L211.PARENT_ID,
                   L14.PARENT_ID,
                   L14.PARENT_TYPE_ID,
                   L14.OBJ_ID,
                   V59.VAL,
                   L211.OBJ_ID

            FROM LINKS L211

            JOIN LINKS L14
            ON L14.PARENT_ID = L211.OBJ_ID
            AND L14.OBJ_TYPE_ID = 14
            AND L14.DATE_DEL IS NULL

            JOIN VALS V59
            ON V59.OBJ_ID = L14.OBJ_ID
            AND V59.PARAM_ID = 59
            AND V59.IS_DEL = 0
            AND UPPER(V59.VAL) STARTING WITH :V

            WHERE :V$OU_LICENCE_TYPE = 'U'
            AND L211.PARENT_ID = :OBJ_ID
            AND L211.OBJ_TYPE_ID = 211
            AND L211.DATE_DEL IS NULL

            INTO :LINK_ID,
                 :OU_ID,
                 :CLASS_ID,
                 :CLASS_TYPE_ID,
                 :SCHOLAR_ID,
                 :F,
                 :STRUCTURE_ID
        DO
        BEGIN
            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:OU_ID)
            INTO :OU_CAPTION;

            CLASS_CAPTION = OU_CAPTION;

            IF (STRUCTURE_ID IS NOT NULL) THEN
            BEGIN
                SELECT CAPTION
                FROM OBJECT_CAPTION_GET(:STRUCTURE_ID)
                INTO :STRUCTURE_CAPTION;
            END
            ELSE
            BEGIN
                STRUCTURE_CAPTION = OU_CAPTION;
            END

            SELECT V
            FROM VAL_GET(:SCHOLAR_ID, 60)
            INTO :I;

            SELECT V
            FROM VAL_GET(:SCHOLAR_ID, 61)
            INTO :O;

            SELECT D
            FROM VAL_GET(:SCHOLAR_ID, 241)
            INTO :D;

            SUSPEND;
        END
    END

    /* DISTRICT */
    IF (TYPE_ID = 111) THEN
    BEGIN
        FOR
            SELECT L14.LINK_ID,
                   L14.PARENT_ID,
                   L14.PARENT_ID,
                   L14.PARENT_TYPE_ID,
                   L14.OBJ_ID,
                   V59.VAL,
                   NULL

            FROM LINKS L2

            JOIN LINKS L14
            ON L14.PARENT_ID = L2.OBJ_ID
            AND L14.OBJ_TYPE_ID = 14
            AND L14.DATE_DEL IS NULL

            JOIN VALS V59
            ON V59.OBJ_ID = L14.OBJ_ID
            AND V59.PARAM_ID = 59
            AND V59.IS_DEL = 0
            AND UPPER(V59.VAL) STARTING WITH :V

            WHERE L2.PARENT_ID = :OBJ_ID
            AND L2.OBJ_TYPE_ID = 2
            AND L2.DATE_DEL IS NULL

            UNION ALL

            SELECT L14.LINK_ID,
                   L211.PARENT_ID,
                   L14.PARENT_ID,
                   L14.PARENT_TYPE_ID,
                   L14.OBJ_ID,
                   V59.VAL,
                   L211.OBJ_ID

            FROM LINKS L2

            JOIN LINKS L211
            ON L211.PARENT_ID = L2.OBJ_ID
            AND L211.OBJ_TYPE_ID = 211
            AND L211.DATE_DEL IS NULL

            JOIN LINKS L14
            ON L14.PARENT_ID = L211.OBJ_ID
            AND L14.OBJ_TYPE_ID = 14
            AND L14.DATE_DEL IS NULL

            JOIN VALS V59
            ON V59.OBJ_ID = L14.OBJ_ID
            AND V59.PARAM_ID = 59
            AND V59.IS_DEL = 0
            AND UPPER(V59.VAL) STARTING WITH :V

            WHERE :V$OU_LICENCE_TYPE = 'U'
            AND L2.PARENT_ID = :OBJ_ID
            AND L2.OBJ_TYPE_ID = 2
            AND L2.DATE_DEL IS NULL

            INTO :LINK_ID,
                 :OU_ID,
                 :CLASS_ID,
                 :CLASS_TYPE_ID,
                 :SCHOLAR_ID,
                 :F,
                 :STRUCTURE_ID
        DO
        BEGIN
            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:OU_ID)
            INTO :OU_CAPTION;

            CLASS_CAPTION = OU_CAPTION;

            IF (STRUCTURE_ID IS NOT NULL) THEN
            BEGIN
                SELECT CAPTION
                FROM OBJECT_CAPTION_GET(:STRUCTURE_ID)
                INTO :STRUCTURE_CAPTION;
            END
            ELSE
            BEGIN
                STRUCTURE_CAPTION = OU_CAPTION;
            END

            SELECT V
            FROM VAL_GET(:SCHOLAR_ID, 60)
            INTO :I;

            SELECT V
            FROM VAL_GET(:SCHOLAR_ID, 61)
            INTO :O;

            SELECT D
            FROM VAL_GET(:SCHOLAR_ID, 241)
            INTO :D;

            SUSPEND;
        END
    END

    /* REGION */
    IF (TYPE_ID = 112) THEN
    BEGIN
        FOR
            SELECT L14.LINK_ID,
                   L14.PARENT_ID,
                   L14.PARENT_ID,
                   L14.PARENT_TYPE_ID,
                   L14.OBJ_ID,
                   V59.VAL,
                   NULL

            FROM LINKS L111

            JOIN LINKS L2
            ON L2.PARENT_ID = L111.OBJ_ID
            AND L2.OBJ_TYPE_ID = 2
            AND L2.DATE_DEL IS NULL

            JOIN LINKS L14
            ON L14.PARENT_ID = L2.OBJ_ID
            AND L14.OBJ_TYPE_ID = 14
            AND L14.DATE_DEL IS NULL

            JOIN VALS V59
            ON V59.OBJ_ID = L14.OBJ_ID
            AND V59.PARAM_ID = 59
            AND V59.IS_DEL = 0
            AND UPPER(V59.VAL) STARTING WITH :V

            WHERE L111.PARENT_ID = :OBJ_ID
            AND L111.OBJ_TYPE_ID = 111
            AND L111.DATE_DEL IS NULL

            UNION

            SELECT L14.LINK_ID,
                   L211.PARENT_ID,
                   L14.PARENT_ID,
                   L14.PARENT_TYPE_ID,
                   L14.OBJ_ID,
                   V59.VAL,
                   L211.OBJ_ID

            FROM LINKS L111

            JOIN LINKS L2
            ON L2.PARENT_ID = L111.OBJ_ID
            AND L2.OBJ_TYPE_ID = 2
            AND L2.DATE_DEL IS NULL

            JOIN LINKS L211
            ON L211.PARENT_ID = L2.OBJ_ID
            AND L211.OBJ_TYPE_ID = 211
            AND L211.DATE_DEL IS NULL

            JOIN LINKS L14
            ON L14.PARENT_ID = L211.OBJ_ID
            AND L14.OBJ_TYPE_ID = 14
            AND L14.DATE_DEL IS NULL

            JOIN VALS V59
            ON V59.OBJ_ID = L14.OBJ_ID
            AND V59.PARAM_ID = 59
            AND V59.IS_DEL = 0
            AND UPPER(V59.VAL) STARTING WITH :V

            WHERE :V$OU_LICENCE_TYPE = 'U'

            AND L111.PARENT_ID = :OBJ_ID
            AND L111.OBJ_TYPE_ID = 111
            AND L111.DATE_DEL IS NULL

            INTO :LINK_ID,
                 :OU_ID,
                 :CLASS_ID,
                 :CLASS_TYPE_ID,
                 :SCHOLAR_ID,
                 :F,
                 :STRUCTURE_ID
        DO
        BEGIN
            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:OU_ID)
            INTO :OU_CAPTION;

            CLASS_CAPTION = OU_CAPTION;

            IF (STRUCTURE_ID IS NOT NULL) THEN
            BEGIN
                SELECT CAPTION
                FROM OBJECT_CAPTION_GET(:STRUCTURE_ID)
                INTO :STRUCTURE_CAPTION;
            END
            ELSE
            BEGIN
                STRUCTURE_CAPTION = OU_CAPTION;
            END

            SELECT V
            FROM VAL_GET(:SCHOLAR_ID, 60)
            INTO :I;

            SELECT V
            FROM VAL_GET(:SCHOLAR_ID, 61)
            INTO :O;

            SELECT D
            FROM VAL_GET(:SCHOLAR_ID, 241)
            INTO :D;

            SUSPEND;
        END
    END

END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SAVE_REGISTRATION_PARAMS (
    I$PUPIL_ID BIGINT,
    I$NUMBER VARCHAR(100),
    I$DATE DATE,
    I$DATE_FROM DATE,
    I$DATE_TO DATE,
    I$AUTHOR VARCHAR(2000))
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$BLOB_ID bigint;
BEGIN   
    SELECT FIRST 1
        OBJ_ID
    FROM LINKS
    WHERE PARENT_ID = :I$PUPIL_ID
    AND OBJ_TYPE_ID = 293
    AND DATE_DEL IS NULL
    INTO :OBJ_ID;
    IF (OBJ_ID IS NULL) THEN
    BEGIN
        SELECT OBJ_ID
        FROM OBJECT_ADD(:I$PUPIL_ID, 293)
        INTO :OBJ_ID;
    END
    IF (OBJ_ID IS NOT NULL) THEN
    BEGIN
        SELECT BLOB_ID
        FROM VAL_ADD(2358, :OBJ_ID, :I$NUMBER)
        INTO :V$BLOB_ID;

        SELECT BLOB_ID
        FROM VAL_ADD(2359, :OBJ_ID, :I$DATE)
        INTO :V$BLOB_ID;

        SELECT BLOB_ID
        FROM VAL_ADD(2360, :OBJ_ID, :I$DATE_FROM)
        INTO :V$BLOB_ID;

        SELECT BLOB_ID
        FROM VAL_ADD(2361, :OBJ_ID, :I$DATE_TO)
        INTO :V$BLOB_ID;

        SELECT BLOB_ID
        FROM VAL_ADD(2362, :OBJ_ID, :I$AUTHOR)
        INTO :V$BLOB_ID;
    END
    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SCARDS_CARD_SET (
    I$PERSON_ID BIGINT,
    I$CARD_TYPE SMALLINT,
    I$CARDNUM VARCHAR(100),
    I$USER_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$TYPE_ID bigint;
declare variable V$PARAM_ID bigint;
declare variable T integer;
begin

  SELECT TYPE_ID
  FROM OBJECTS
  WHERE OBJ_ID = :I$PERSON_ID
  INTO :V$TYPE_ID;

  IF(V$TYPE_ID = 10) THEN BEGIN
    V$PARAM_ID = IIF(I$CARD_TYPE = 0, 2855, 2913);
  END
  ELSE IF(V$TYPE_ID = 14) THEN BEGIN
    -- Временных карт тут вообще нет ?
    V$PARAM_ID = 2857;
  END
  ELSE IF(V$TYPE_ID = 20) THEN BEGIN
    V$PARAM_ID = IIF(I$CARD_TYPE = 0, 2918, 2919);
  END
  ELSE EXCEPTION DATA_ERROR 'Недопустимый тип персоны ' || COALESCE(V$TYPE_ID, '?');

  SELECT 1 FROM VAL_ADD(:V$PARAM_ID, :I$PERSON_ID, :I$CARDNUM) INTO :T;

  -- Вносим запись
  -- 2 = новая взамен старой
  IF(I$CARD_TYPE = 2) THEN I$CARD_TYPE = 0;

  SELECT OBJ_ID FROM OBJECT_ADD(:I$PERSON_ID, 455, NULL, NULL, :I$USER_ID) INTO :OBJ_ID;
  SELECT 1 FROM VAL_ADD(3269, :OBJ_ID, CURRENT_TIMESTAMP) INTO :T;
  SELECT 1 FROM VAL_ADD(3270, :OBJ_ID, IIF(:I$CARD_TYPE = 0, 14073, 14074)) INTO :T;
  SELECT 1 FROM VAL_ADD(3273, :OBJ_ID, :I$CARDNUM) INTO :T;

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SCARDS_GET_PERSDATA (
    OBJ_ID BIGINT)
RETURNS (
    SCHOOL_ID BIGINT,
    REG_ID VARCHAR(100),
    SURNAME VARCHAR(1000),
    NAME VARCHAR(1000),
    PATRONYMIC VARCHAR(1000),
    DOB VARCHAR(10),
    PERSON_TYPE BIGINT,
    CLASS VARCHAR(1000),
    BENEFIT VARCHAR(100),
    BENEFIT_FROM VARCHAR(10),
    BENEFIT_TO VARCHAR(10),
    IS_OUTER INTEGER,
    CLASS_TYPE BIGINT,
    "YEAR" INTEGER,
    SNILS VARCHAR(40),
    FROM_FOR BIGINT,
    FROM_SRC BIGINT,
    ULS VARCHAR(100),
    CLAIM_ID VARCHAR(100),
    DOCUMENTS VARCHAR(4000))
AS
declare variable CLASS_ID bigint;
declare variable DOC_ID bigint;
declare variable DOC_TYPE bigint;
declare variable S1 varchar(100);
declare variable S2 varchar(100);
declare variable S3 varchar(100);
begin

  SELECT FIRST 1 LV.COST
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :"YEAR";

  IS_OUTER = 0;

  FOR
      SELECT FIRST 1 LP.OBJ_TYPE_ID, LP.PARENT_TYPE_ID, LP.PARENT_ID, VR.VAL, V1.VAL, V2.VAL, V3.VAL, VD.VAL, VS.VAL, VU.SVAL, VCL.SVAL
      FROM LINKS LP
      JOIN VALS VR ON VR.OBJ_ID = LP.OBJ_ID AND VR.PARAM_ID IN (2912, 2915, 2917) AND VR.IS_DEL = 0
      JOIN VALS V1 ON V1.OBJ_ID = LP.OBJ_ID AND V1.PARAM_ID IN (55, 128, 59) AND V1.IS_DEL = 0
      JOIN VALS V2 ON V2.OBJ_ID = LP.OBJ_ID AND V2.PARAM_ID IN (56, 129, 60) AND V2.IS_DEL = 0
      LEFT JOIN VALS V3 ON V3.OBJ_ID = LP.OBJ_ID AND V3.PARAM_ID IN (57, 130, 61) AND V3.IS_DEL = 0
      JOIN VALD VD ON VD.OBJ_ID = LP.OBJ_ID AND VD.PARAM_ID IN (89, 143, 241) AND VD.IS_DEL = 0
      LEFT JOIN VALS VS ON VS.OBJ_ID = LP.OBJ_ID AND VS.PARAM_ID IN (1409, 2455, 2365) AND VS.IS_DEL = 0
      -- УЛС
      LEFT JOIN VALS VU ON VU.OBJ_ID = LP.OBJ_ID AND VU.PARAM_ID = 3482 AND VU.IS_DEL = 0
      -- Номер заявления зачисления
      LEFT JOIN VALS VCL ON VCL.OBJ_ID = LP.OBJ_ID AND VCL.PARAM_ID = 3349 AND VCL.IS_DEL = 0
      WHERE LP.OBJ_ID = :OBJ_ID AND LP.PARENT_TYPE_ID IN (9, 10, 125, 187, 2, 211, 81, 82, 83, 84, 290) AND LP.DATE_DEL IS NULL
      INTO :PERSON_TYPE, :CLASS_TYPE, :CLASS_ID, :REG_ID, :SURNAME, :NAME, :PATRONYMIC, :DOB, :SNILS, :ULS, :CLAIM_ID
  DO
  BEGIN
      IF(POSITION(':' IN REG_ID) > 0) THEN REG_ID = SUBSTRING(REG_ID FROM 1 FOR POSITION(':' IN REG_ID) - 1);

      IF(PERSON_TYPE = 20) THEN
      BEGIN
          CLASS = 'РДТЛ';
          FROM_SRC = NULL;
          FROM_FOR = NULL;

          -- Достаем школу через ученика (id ученика в CLASS_ID)
          -- Действующий ученик
          SELECT FIRST 1 LP2.PARENT_ID
          FROM LINKS LPG
          JOIN LINKS LP8 ON LP8.OBJ_ID = LPG.PARENT_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
          JOIN LINKS LP7 ON LP7.OBJ_ID = LP8.PARENT_ID AND LP7.PARENT_TYPE_ID = 7 AND LP7.DATE_DEL IS NULL
          JOIN LINKS LP2 ON LP2.OBJ_ID = LP7.PARENT_ID AND LP2.PARENT_TYPE_ID = 2 AND LP2.DATE_DEL IS NULL
          WHERE LPG.OBJ_ID = :CLASS_ID AND LPG.PARENT_TYPE_ID IN (9, 125, 187) AND LPG.DATE_DEL IS NULL
          UNION
          -- Выбывший/окончивший
          SELECT FIRST 1 LP2.PARENT_ID
          FROM LINKS LP8X
          JOIN LINKS LP78 ON LP78.OBJ_ID = LP8X.PARENT_ID AND LP78.PARENT_TYPE_ID = 78 AND LP78.DATE_DEL IS NULL
          JOIN LINKS LP2 ON LP2.OBJ_ID = LP78.PARENT_ID AND LP2.PARENT_TYPE_ID = 2 AND LP2.DATE_DEL IS NULL
          WHERE LP8X.OBJ_ID = :CLASS_ID AND LP8X.PARENT_TYPE_ID IN (81, 82, 83) AND LP8X.DATE_DEL IS NULL
          INTO :SCHOOL_ID;
      END
      ELSE IF(PERSON_TYPE = 14) THEN
      BEGIN
          CLASS = 'СОТР';
          FROM_SRC = NULL;
          FROM_FOR = NULL;

          -- Достаем школу - три маршрута, которые все укладываются в один запрос (уволенные, действующие сотрудники ОУ и действующие сотрудники подразделения)
          SELECT FIRST 1 LP2.PARENT_ID
          FROM LINKS LP2
          WHERE (LP2.OBJ_ID = :CLASS_ID OR LP2.OBJ_ID = :OBJ_ID) AND LP2.PARENT_TYPE_ID = 2 AND LP2.DATE_DEL IS NULL
          INTO :SCHOOL_ID;

          -- Проверяем, есть ли у сотрудника основная должность или он везде совместитель ?
          IF(NOT EXISTS(
              SELECT FIRST 1 1
              FROM LINKS L15
              JOIN VALL V587 ON V587.OBJ_ID = L15.OBJ_ID AND V587.PARAM_ID = 587 AND V587.IS_DEL = 0 AND V587.LISTVAL_ID IN (207, 1720)
              -- неактуальные ставки пропускаем
              LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
              WHERE L15.PARENT_ID = :OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL AND V74.VAL IS NULL
          ))
          THEN PERSON_TYPE = 1014;

      END
      ELSE
      BEGIN
          CLASS = 'НЕТ ДАННЫХ';
          FROM_SRC = NULL;
          FROM_FOR = NULL;

          -- Достаем школу
          -- Действующий ученик
          SELECT FIRST 1 LP2.PARENT_ID
          FROM LINKS LP8
          JOIN LINKS LP7 ON LP7.OBJ_ID = LP8.PARENT_ID AND LP7.PARENT_TYPE_ID = 7 AND LP7.DATE_DEL IS NULL
          JOIN LINKS LP2 ON LP2.OBJ_ID = LP7.PARENT_ID AND LP2.PARENT_TYPE_ID = 2 AND LP2.DATE_DEL IS NULL
          WHERE LP8.OBJ_ID = :CLASS_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
          UNION
          -- Выбывший/окончивший, предварительный прием
          SELECT FIRST 1 LP2.PARENT_ID
          FROM LINKS LP78
          JOIN LINKS LP2 ON LP2.OBJ_ID = LP78.PARENT_ID AND LP2.PARENT_TYPE_ID = 2 AND LP2.DATE_DEL IS NULL
          WHERE LP78.OBJ_ID = :CLASS_ID AND LP78.PARENT_TYPE_ID IN (77, 78) AND LP78.DATE_DEL IS NULL
          INTO :SCHOOL_ID;

          -- Достаем класс
          SELECT FIRST 1 C.CAPTION
          FROM LINKS LPG
          LEFT JOIN OBJECT_CAPTION_GET(LPG.PARENT_ID) C ON 1 = 1
          WHERE LPG.OBJ_ID = :OBJ_ID AND LPG.PARENT_TYPE_ID IN (9, 125, 187, 290) AND LPG.DATE_DEL IS NULL
          INTO :CLASS;

          -- Коды льгот на питание - только у учащихся
          SELECT LV.COST
          FROM VALL V2091
          JOIN LISTVALS LV ON LV.LISTVAL_ID = V2091.LISTVAL_ID
          WHERE V2091.OBJ_ID = :OBJ_ID AND V2091.PARAM_ID = 2091 AND V2091.IS_DEL = 0
          INTO :BENEFIT;

          SELECT DD.VAL
          FROM VALD V2088
          LEFT JOIN DATE2ISO(V2088.VAL, 0) DD ON 1 = 1
          WHERE V2088.OBJ_ID = :OBJ_ID AND V2088.PARAM_ID = 2088 AND V2088.IS_DEL = 0
          INTO :BENEFIT_FROM;

          SELECT DD.VAL
          FROM VALD V2092
          LEFT JOIN DATE2ISO(V2092.VAL, 0) DD ON 1 = 1
          WHERE V2092.OBJ_ID = :OBJ_ID AND V2092.PARAM_ID = 2092 AND V2092.IS_DEL = 0
          INTO :BENEFIT_TO;

          -- Откуда пришел
          SELECT V.LISTVAL_ID
          FROM VALL V
          WHERE V.OBJ_ID = :OBJ_ID AND V.PARAM_ID = 78 AND V.IS_DEL = 0
          INTO :FROM_SRC;

          -- Зачем пришел - из последнего движения
          SELECT FIRST 1 M.REASON_IN
          FROM PERSON_MOVEMENTS M
          JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
          WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :OBJ_ID AND M.DATE_OUT IS NULL
          ORDER BY M.OBJ_ID DESC
          INTO :FROM_FOR;

      END

      DOCUMENTS = '';
      FOR
        SELECT L79.OBJ_ID, LV.TAG, SUBSTRING(COALESCE(V442.VAL, '') FROM 1 FOR 100), SUBSTRING(V559.VAL FROM 1 FOR 100), D.VAL
        FROM LINKS L79
        JOIN VALL V441 ON V441.OBJ_ID = L79.OBJ_ID AND V441.PARAM_ID = 441 AND V441.IS_DEL = 0
        JOIN LISTVALS LV ON LV.LISTVAL_ID = V441.LISTVAL_ID
        JOIN VALD V560 ON V560.OBJ_ID = L79.OBJ_ID AND V560.PARAM_ID = 560 AND V560.IS_DEL = 0
        LEFT JOIN DATE2ISO(V560.VAL, 0) D ON 1 = 1
        JOIN VALS V559 ON V559.OBJ_ID = L79.OBJ_ID AND V559.PARAM_ID = 559 AND V559.IS_DEL = 0
        LEFT JOIN VALS V442 ON V442.OBJ_ID = L79.OBJ_ID AND V442.PARAM_ID = 442 AND V442.IS_DEL = 0
        WHERE L79.PARENT_ID = :OBJ_ID AND L79.OBJ_TYPE_ID = 79 AND L79.DATE_DEL IS NULL
        ORDER BY LV.COST
        INTO :DOC_ID, :DOC_TYPE, :S1, :S2, :S3
      DO
      BEGIN
        -- Форматируем с вертикальной чертой-разделителем
        IF(DOCUMENTS <> '') THEN DOCUMENTS = DOCUMENTS || ';';
        S1 = REPLACE(REPLACE(S1, '|', ''), ';', '');
        S2 = REPLACE(REPLACE(S2, '|', ''), ';', '');
        S3 = REPLACE(REPLACE(S3, '|', ''), ';', '');
        DOCUMENTS = DOCUMENTS || DOC_ID || '|' || DOC_TYPE || '|' || S1 || '|' || S2 || '|' || S3;
      END

      SUSPEND;
  END

  -- Отдельная выборка для внешних учающихся секции ДО
  FROM_FOR = NULL;
  FROM_SRC = NULL;
  BENEFIT = NULL;
  BENEFIT_FROM = NULL;
  BENEFIT_TO = NULL;
  IS_OUTER = 1;

  FOR
      SELECT FIRST 1 LP.OBJ_TYPE_ID, LP.PARENT_TYPE_ID, LP.PARENT_ID, VR.VAL, V1.VAL, V2.VAL, V3.VAL, VD.VAL
      FROM LINKS LP
      JOIN VALS VR ON VR.OBJ_ID = LP.OBJ_ID AND VR.PARAM_ID IN (2912, 2915, 2917) AND VR.IS_DEL = 0
      JOIN VALS V1 ON V1.OBJ_ID = LP.OBJ_ID AND V1.PARAM_ID IN (55, 128, 59) AND V1.IS_DEL = 0
      JOIN VALS V2 ON V2.OBJ_ID = LP.OBJ_ID AND V2.PARAM_ID IN (56, 129, 60) AND V2.IS_DEL = 0
      LEFT JOIN VALS V3 ON V3.OBJ_ID = LP.OBJ_ID AND V3.PARAM_ID IN (57, 130, 61) AND V3.IS_DEL = 0
      JOIN VALD VD ON VD.OBJ_ID = LP.OBJ_ID AND VD.PARAM_ID IN (89, 143, 241) AND VD.IS_DEL = 0
      -- Берем только не-своих учеников
      LEFT JOIN LINKS LPG ON LPG.OBJ_ID = LP.OBJ_ID AND LPG.PARENT_TYPE_ID IN (9, 125, 187, 290) AND LPG.DATE_DEL IS NULL
      WHERE LP.OBJ_ID = :OBJ_ID AND LP.PARENT_TYPE_ID = 46 AND LP.DATE_DEL IS NULL AND LPG.PARENT_ID IS NULL
      INTO :PERSON_TYPE, :CLASS_TYPE, :CLASS_ID, :REG_ID, :SURNAME, :NAME, :PATRONYMIC, :DOB
  DO
  BEGIN
      IF(POSITION(':' IN REG_ID) > 0) THEN REG_ID = SUBSTRING(REG_ID FROM 1 FOR POSITION(':' IN REG_ID) - 1);

      SELECT FIRST 1 LP2.PARENT_ID
      FROM LINKS LP86
      JOIN LINKS LP2 ON LP2.OBJ_ID = LP86.PARENT_ID AND LP2.PARENT_TYPE_ID = 2 AND LP2.DATE_DEL IS NULL
      WHERE LP86.OBJ_ID = :CLASS_ID AND LP86.PARENT_TYPE_ID = 86 AND LP86.DATE_DEL IS NULL
      INTO :SCHOOL_ID;

      DOCUMENTS = '';
      FOR
        SELECT L79.OBJ_ID, LV.TAG, SUBSTRING(COALESCE(V442.VAL, '') FROM 1 FOR 100), SUBSTRING(V559.VAL FROM 1 FOR 100), D.VAL
        FROM LINKS L79
        JOIN VALL V441 ON V441.OBJ_ID = L79.OBJ_ID AND V441.PARAM_ID = 441 AND V441.IS_DEL = 0
        JOIN LISTVALS LV ON LV.LISTVAL_ID = V441.LISTVAL_ID
        JOIN VALD V560 ON V560.OBJ_ID = L79.OBJ_ID AND V560.PARAM_ID = 560 AND V560.IS_DEL = 0
        LEFT JOIN DATE2ISO(V560.VAL, 0) D ON 1 = 1
        JOIN VALS V559 ON V559.OBJ_ID = L79.OBJ_ID AND V559.PARAM_ID = 559 AND V559.IS_DEL = 0
        LEFT JOIN VALS V442 ON V442.OBJ_ID = L79.OBJ_ID AND V442.PARAM_ID = 442 AND V442.IS_DEL = 0
        WHERE L79.PARENT_ID = :OBJ_ID AND L79.OBJ_TYPE_ID = 79 AND L79.DATE_DEL IS NULL
        ORDER BY LV.COST
        INTO :DOC_ID, :DOC_TYPE, :S1, :S2, :S3
      DO
      BEGIN
        -- Форматируем с вертикальной чертой-разделителем
        IF(DOCUMENTS <> '') THEN DOCUMENTS = DOCUMENTS || ';';
        S1 = REPLACE(REPLACE(S1, '|', ''), ';', '');
        S2 = REPLACE(REPLACE(S2, '|', ''), ';', '');
        S3 = REPLACE(REPLACE(S3, '|', ''), ';', '');
        DOCUMENTS = DOCUMENTS || DOC_ID || '|' || DOC_TYPE || '|' || S1 || '|' || S2 || '|' || S3;
      END

      SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SCHEDULE_CJ_IDATA (
    I$SCHEDULE_ID BIGINT,
    I$DATE DATE,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(4000))
AS
declare variable V$SCH_TYPE bigint;
declare variable V$FOLDER_ID bigint;
declare variable V$OP_COUNT integer;
declare variable V$CJ_ID bigint;
declare variable V$CJ_NAME varchar(400);
declare variable V$SUBJECT_ID bigint;
declare variable V$LESSON_NUM integer;
declare variable V$ROOM_ID bigint;
begin

  -- Можно указывать как ленту, так и шаблон расписания
  SELECT TYPE_ID
  FROM OBJECTS
  WHERE OBJ_ID = :I$SCHEDULE_ID
  INTO :V$SCH_TYPE;

  IF(V$SCH_TYPE = 3) THEN V$FOLDER_ID = I$SCHEDULE_ID;
  ELSE V$FOLDER_ID = (SELECT PARENT_ID FROM LINKS WHERE OBJ_ID = :I$SCHEDULE_ID AND PARENT_TYPE_ID = 3 AND DATE_DEL IS NULL);

  -- Сколько у нас указано ОП ?
  SELECT COUNT(*)
  FROM LINKS L57
  WHERE L57.PARENT_ID = :V$FOLDER_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
  INTO :V$OP_COUNT;

  TAG_NAME = 'items::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
    -- Вообще все журналы, если ОП не указаны
    SELECT J.OBJ_ID, J.JOURNAL_NAME, J.SUBJECT_ID, J.ROOM_ID
    FROM CJ2_JOURNAL J
    WHERE J.DATE_DEL IS NULL AND J.JOURNAL_TYPE IN (0, 1) AND :V$OP_COUNT = 0
    -- Журналы из конкретных перечисленных ОП
    UNION
    SELECT J.OBJ_ID, J.JOURNAL_NAME, J.SUBJECT_ID, J.ROOM_ID
    FROM CJ2_JOURNAL J
    JOIN LINKS LP57 ON LP57.OBJ_ID = J.REF_ID AND LP57.PARENT_TYPE_ID = 57 AND LP57.DATE_DEL IS NULL
    JOIN LINKS LP3 ON LP3.OBJ_ID = LP57.PARENT_ID AND LP3.PARENT_ID = :V$FOLDER_ID AND LP3.DATE_DEL IS NULL
    WHERE J.DATE_DEL IS NULL AND J.JOURNAL_TYPE IN (0, 1) AND :V$OP_COUNT <> 0
    ORDER BY 1
    INTO :V$CJ_ID, :V$CJ_NAME, :V$SUBJECT_ID, :V$ROOM_ID
  DO
  BEGIN

    -- Только уроки в стандартной сетке уроков
    FOR
      SELECT L.LESSON_NUM
      FROM CJ2_JOURNAL_LESSONS L
      WHERE L.DATE_DEL IS NULL AND L.CJ_ID = :V$CJ_ID AND L.LESSON_DATE = :I$DATE AND L.LESSON_NUM < 60
      ORDER BY 1
      INTO :V$LESSON_NUM
    DO
    BEGIN
      TAG_NAME = 'items:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'items:r:cj_id';
      VAL = V$CJ_ID;
      SUSPEND;
      TAG_NAME = 'items:r:room_id';
      VAL = V$ROOM_ID;
      SUSPEND;
      TAG_NAME = 'items:r:lesson_num';
      VAL = V$LESSON_NUM;
      SUSPEND;
    END

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SCHEDULE_CLASSES_LIST (
    I$SCHEDULE_TEMPLATE_ID BIGINT)
RETURNS (
    CLASS_ID BIGINT,
    CLASS_CAPTION VARCHAR(4000),
    SORT_ORDER BIGINT)
AS
declare variable OBJ_ID bigint;
declare variable STREAMS_ID bigint;
declare variable STREAM_NAME varchar(1000);
BEGIN
    SELECT FIRST 1 OBJ_ID
    FROM OBJECT_PARENTS_GET(:I$SCHEDULE_TEMPLATE_ID, 3)
    INTO :OBJ_ID;

    FOR
        /* ГУП */
        SELECT DISTINCT L256.OBJ_ID, NULL
        FROM LINKS L57
        JOIN LINKS L50 ON L50.PARENT_ID = L57.OBJ_ID AND L50.OBJ_TYPE_ID = 50 AND L50.DATE_DEL IS NULL
        JOIN LINKS L54 ON L54.PARENT_ID = L50.OBJ_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
        JOIN LINKS L256 ON L256.PARENT_ID = L54.OBJ_ID AND L256.OBJ_TYPE_ID = 256 AND L256.DATE_DEL IS NULL
        WHERE L57.PARENT_ID = :OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL

        UNION

        /* Потоки */
        SELECT DISTINCT L347.OBJ_ID, L346.OBJ_ID
        FROM LINKS L57
        JOIN LINKS L50 ON L50.PARENT_ID = L57.OBJ_ID AND L50.OBJ_TYPE_ID = 50 AND L50.DATE_DEL IS NULL
        JOIN LINKS L54 ON L54.PARENT_ID = L50.OBJ_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
        JOIN LINKS L346 ON L346.PARENT_ID = L54.OBJ_ID AND L346.OBJ_TYPE_ID = 346 AND L346.DATE_DEL IS NULL
        JOIN LINKS L347 ON L347.PARENT_ID = L346.OBJ_ID AND L347.OBJ_TYPE_ID = 347 AND L347.DATE_DEL IS NULL
        WHERE L57.PARENT_ID = :OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL

        INTO :CLASS_ID, :STREAMS_ID
    DO
    BEGIN
        SELECT CAPTION, SORT_ORDER FROM OBJECT_CAPTION_GET(:CLASS_ID, NULL) INTO :CLASS_CAPTION, :SORT_ORDER;

        IF(STREAMS_ID IS NOT NULL AND CHAR_LENGTH(CLASS_CAPTION) < 10) THEN
        BEGIN
            SELECT CAPTION FROM OBJECT_CAPTION_GET(:STREAMS_ID, NULL) INTO :STREAM_NAME;
            CLASS_CAPTION = CLASS_CAPTION || ' - ' || STREAM_NAME;
        END

        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SCHEDULE_COPY (
    I$RASP_ID BIGINT,
    I$SCHEDULE_TEMPLATE_ID BIGINT,
    I$COPY_DESCRIPTION VARCHAR(4000))
RETURNS (
    COPY_ID BIGINT,
    LINK_ID BIGINT)
AS
declare variable V$BLOB_ID bigint;
declare variable V$ELEMENT_ID bigint;
declare variable V$NEW_ELEMENT_ID bigint;
declare variable V$T time;
declare variable V$I bigint;
declare variable V$PARAM_ID bigint;
declare variable V$LINK_ID bigint;
declare variable V$DAY_ID bigint;
declare variable V$NEW_DAY_ID bigint;
declare variable V$HOUR_ID bigint;
declare variable V$NEW_HOUR_ID bigint;
declare variable V$WEEK_START_DATE date;
BEGIN
    SELECT OBJ_ID, LINK_ID
    FROM OBJECT_ADD(:I$RASP_ID, 59)
    INTO :COPY_ID, :LINK_ID;

    SELECT BLOB_ID
    FROM VAL_ADD(403, :COPY_ID, :I$COPY_DESCRIPTION)
    INTO :V$BLOB_ID;

    FOR SELECT L6.OBJ_ID
        FROM LINKS L6
        WHERE L6.PARENT_ID = :I$SCHEDULE_TEMPLATE_ID AND L6.DATE_DEL IS NULL AND L6.OBJ_TYPE_ID = 6
        INTO :V$DAY_ID
    DO
    BEGIN
        SELECT OBJ_ID, LINK_ID
        FROM OBJECT_ADD(:COPY_ID, 6)
        INTO :V$NEW_DAY_ID, :V$LINK_ID;

        UPDATE LINKS L
        SET L.REASON_ID = :V$DAY_ID
        WHERE L.LINK_ID = :V$LINK_ID;

        V$WEEK_START_DATE = NULL;

        SELECT FIRST 1 D
        FROM VAL_GET(:V$DAY_ID, 42)
        INTO :V$WEEK_START_DATE;

        IF (V$WEEK_START_DATE IS NOT NULL) THEN
        BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD(42, :V$NEW_DAY_ID, :V$WEEK_START_DATE)
            INTO :V$BLOB_ID;
        END

        FOR SELECT VL.LISTVAL_ID
            FROM VALL VL
            WHERE VL.OBJ_ID = :V$DAY_ID AND VL.PARAM_ID = 402 AND VL.IS_DEL = 0
            INTO :V$I
        DO
        BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD(402, :V$NEW_DAY_ID, :V$I)
            INTO :V$BLOB_ID;
        END

    END

    FOR SELECT L60.OBJ_ID
        FROM LINKS L60
        WHERE L60.PARENT_ID = :I$SCHEDULE_TEMPLATE_ID AND L60.DATE_DEL IS NULL AND L60.OBJ_TYPE_ID = 60
        INTO :V$HOUR_ID
    DO
    BEGIN
        SELECT OBJ_ID, LINK_ID
        FROM OBJECT_ADD(:COPY_ID, 60)
        INTO :V$NEW_HOUR_ID, :V$LINK_ID;

        UPDATE LINKS L
        SET L.REASON_ID = :V$HOUR_ID
        WHERE L.LINK_ID = :V$LINK_ID;

        FOR SELECT VI.VAL
            FROM VALI VI
            WHERE VI.OBJ_ID = :V$HOUR_ID AND VI.PARAM_ID = 404 AND VI.IS_DEL = 0
            INTO :V$I
        DO
        BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD(404, :V$NEW_HOUR_ID, :V$I)
            INTO :V$BLOB_ID;
        END

        FOR SELECT VT.VAL, VT.PARAM_ID
            FROM VALT VT
            WHERE VT.OBJ_ID = :V$HOUR_ID AND VT.IS_DEL = 0 AND VT.PARAM_ID IN (405, 406)
            INTO :V$T, :V$PARAM_ID
        DO
        BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD(:V$PARAM_ID, :V$NEW_HOUR_ID, :V$T)
            INTO :V$BLOB_ID;
        END
    END

    FOR SELECT L70.OBJ_ID
        FROM LINKS L70
        WHERE L70.PARENT_ID = :I$SCHEDULE_TEMPLATE_ID AND L70.DATE_DEL IS NULL AND L70.OBJ_TYPE_ID = 70
        INTO :V$ELEMENT_ID
    DO
    BEGIN
        SELECT OBJ_ID, LINK_ID
        FROM OBJECT_ADD(:COPY_ID, 70)
        INTO :V$NEW_ELEMENT_ID, :V$LINK_ID;

        FOR SELECT FIRST 1 N.OBJ_ID, N.REASON_ID
            FROM LINKS L
            JOIN LINKS N ON N.REASON_ID = L.PARENT_ID AND N.PARENT_ID = :COPY_ID AND N.OBJ_TYPE_ID = 6 AND N.DATE_DEL IS NULL
            WHERE L.OBJ_ID = :V$ELEMENT_ID AND L.PARENT_TYPE_ID = 6 AND L.DATE_DEL IS NULL
            INTO :V$I, :V$HOUR_ID
        DO
        BEGIN
            SELECT OBJ_ID
            FROM OBJECT_ADD_LINK(:V$I, :V$NEW_ELEMENT_ID, 70) -- , :V$HOUR_ID
            INTO :V$BLOB_ID;
        END

        FOR SELECT FIRST 1 N.OBJ_ID, N.REASON_ID
            FROM LINKS L
            JOIN LINKS N ON N.REASON_ID = L.PARENT_ID AND N.PARENT_ID = :COPY_ID AND N.OBJ_TYPE_ID = 60 AND N.DATE_DEL IS NULL
            WHERE L.OBJ_ID = :V$ELEMENT_ID AND L.PARENT_TYPE_ID = 60 AND L.DATE_DEL IS NULL
            INTO :V$I, :V$DAY_ID
        DO
        BEGIN
            SELECT OBJ_ID
            FROM OBJECT_ADD_LINK(:V$I, :V$NEW_ELEMENT_ID, 70) -- , :V$DAY_ID
            INTO :V$BLOB_ID;
        END

        FOR SELECT FIRST 1 L.PARENT_ID
            FROM LINKS L
            WHERE L.OBJ_ID = :V$ELEMENT_ID AND L.PARENT_TYPE_ID = 14 AND L.DATE_DEL IS NULL
            INTO :V$I
        DO
        BEGIN
            SELECT OBJ_ID
            FROM OBJECT_ADD_LINK(:V$I, :V$NEW_ELEMENT_ID, 70)
            INTO :V$BLOB_ID;
        END

        FOR SELECT FIRST 1 L.PARENT_ID
            FROM LINKS L
            WHERE L.OBJ_ID = :V$ELEMENT_ID AND L.PARENT_TYPE_ID = 61 AND L.DATE_DEL IS NULL
            INTO :V$I
        DO
        BEGIN
            SELECT OBJ_ID
            FROM OBJECT_ADD_LINK(:V$I, :V$NEW_ELEMENT_ID, 70)
            INTO :V$BLOB_ID;
        END

        FOR SELECT L.PARENT_ID
            FROM LINKS L
            WHERE L.OBJ_ID = :V$ELEMENT_ID AND L.PARENT_TYPE_ID = 58 AND L.DATE_DEL IS NULL
            INTO :V$I
        DO
        BEGIN
            SELECT OBJ_ID
            FROM OBJECT_ADD_LINK(:V$I, :V$NEW_ELEMENT_ID, 70)
            INTO :V$BLOB_ID;
        END
    END

    FOR SELECT L59.LINK_ID
        FROM LINKS L59
        WHERE L59.PARENT_ID = :COPY_ID AND L59.REASON_ID IS NOT NULL AND L59.DATE_DEL IS NULL
        INTO :V$I
    DO
    BEGIN
        UPDATE LINKS L
        SET L.REASON_ID = NULL
        WHERE L.LINK_ID = :V$I;
    END

    -- Копирование элементов нового формата
    FOR
        SELECT I.WEEKDAY_NUM, I.LESSON_NUM, I.CJ_ID, I.ROOM_ID
        FROM SCHEDULE_ITEMS I
        WHERE I.DATE_DEL IS NULL AND I.SCHEDULE_ID = :I$SCHEDULE_TEMPLATE_ID
        INTO :V$DAY_ID, :V$HOUR_ID, :V$ELEMENT_ID, :V$BLOB_ID
    DO
    BEGIN
        INSERT INTO SCHEDULE_ITEMS
        (SCHEDULE_ID, WEEKDAY_NUM, LESSON_NUM, CJ_ID, ROOM_ID)
        VALUES (:COPY_ID, :V$DAY_ID, :V$HOUR_ID, :V$ELEMENT_ID, :V$BLOB_ID);
    END

    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SCHEDULE_COPY_ADD (
    I$PERIOD_ID BIGINT,
    I$SCHEDULE_TEMPLATE_ID BIGINT,
    I$WEEK_START_DATE DATE,
    I$COPY_DESCRIPTION VARCHAR(4000))
RETURNS (
    COPY_ID BIGINT,
    LINK_ID BIGINT)
AS
declare variable V$BLOB_ID bigint;
declare variable V$ELEMENT_ID bigint;
declare variable V$NEW_ELEMENT_ID bigint;
declare variable V$NEW_SUBELEMENT_ID bigint;
declare variable V$T time;
declare variable V$I bigint;
declare variable V$PARAM_ID bigint;
declare variable V$GRADE_LOADING_ID bigint;
declare variable V$ROOM_ID bigint;
declare variable V$LINK_ID bigint;
declare variable V$DAY_ID bigint;
declare variable V$NEW_DAY_ID bigint;
declare variable V$HOUR_ID bigint;
declare variable V$NEW_HOUR_ID bigint;
BEGIN
    SELECT OBJ_ID, LINK_ID
    FROM OBJECT_ADD(:I$PERIOD_ID, 63)
    INTO :COPY_ID, :LINK_ID;

    SELECT OBJ_ID
    FROM OBJECT_ADD_LINK(:I$SCHEDULE_TEMPLATE_ID, :COPY_ID, 63)
    INTO :V$BLOB_ID;

    SELECT BLOB_ID
    FROM VAL_ADD(410, :COPY_ID, :I$WEEK_START_DATE)
    INTO :V$BLOB_ID;

    SELECT BLOB_ID
    FROM VAL_ADD(409, :COPY_ID, :I$COPY_DESCRIPTION)
    INTO :V$BLOB_ID;

    FOR SELECT L6.OBJ_ID
        FROM LINKS L6
        WHERE L6.PARENT_ID = :I$SCHEDULE_TEMPLATE_ID AND L6.DATE_DEL IS NULL AND L6.OBJ_TYPE_ID = 6
        INTO :V$DAY_ID
    DO
    BEGIN
        SELECT OBJ_ID, LINK_ID
        FROM OBJECT_ADD(:COPY_ID, 6)
        INTO :V$NEW_DAY_ID, :V$LINK_ID;

        UPDATE LINKS L
        SET L.REASON_ID = :V$DAY_ID
        WHERE L.LINK_ID = :V$LINK_ID;

        SELECT BLOB_ID
        FROM VAL_ADD(42, :V$NEW_DAY_ID, :I$WEEK_START_DATE)
        INTO :V$BLOB_ID;

        I$WEEK_START_DATE = DATEADD(1 DAY TO I$WEEK_START_DATE);

        FOR SELECT VL.LISTVAL_ID
            FROM VALL VL
            WHERE VL.OBJ_ID = :V$DAY_ID AND VL.PARAM_ID = 402 AND VL.IS_DEL = 0
            INTO :V$I
        DO
        BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD(402, :V$NEW_DAY_ID, :V$I)
            INTO :V$BLOB_ID;
        END

    END

    FOR SELECT L60.OBJ_ID
        FROM LINKS L60
        WHERE L60.PARENT_ID = :I$SCHEDULE_TEMPLATE_ID AND L60.DATE_DEL IS NULL AND L60.OBJ_TYPE_ID = 60
        INTO :V$HOUR_ID
    DO
    BEGIN
        SELECT OBJ_ID, LINK_ID
        FROM OBJECT_ADD(:COPY_ID, 60)
        INTO :V$NEW_HOUR_ID, :V$LINK_ID;

        UPDATE LINKS L
        SET L.REASON_ID = :V$HOUR_ID
        WHERE L.LINK_ID = :V$LINK_ID;

        FOR SELECT VI.VAL
            FROM VALI VI
            WHERE VI.OBJ_ID = :V$HOUR_ID AND VI.PARAM_ID = 404 AND VI.IS_DEL = 0
            INTO :V$I
        DO
        BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD(404, :V$NEW_HOUR_ID, :V$I)
            INTO :V$BLOB_ID;
        END

        FOR SELECT VT.VAL, VT.PARAM_ID
            FROM VALT VT
            WHERE VT.OBJ_ID = :V$HOUR_ID AND VT.IS_DEL = 0 AND VT.PARAM_ID IN (405, 406)
            INTO :V$T, :V$PARAM_ID
        DO
        BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD(:V$PARAM_ID, :V$NEW_HOUR_ID, :V$T)
            INTO :V$BLOB_ID;
        END
    END

    FOR SELECT L70.OBJ_ID
        FROM LINKS L70
        WHERE L70.PARENT_ID = :I$SCHEDULE_TEMPLATE_ID AND L70.DATE_DEL IS NULL AND L70.OBJ_TYPE_ID = 70
        INTO :V$ELEMENT_ID
    DO
    BEGIN
        SELECT OBJ_ID, LINK_ID
        FROM OBJECT_ADD(:COPY_ID, 70)
        INTO :V$NEW_ELEMENT_ID, :V$LINK_ID;

        UPDATE LINKS L
        SET L.REASON_ID = :V$ELEMENT_ID
        WHERE L.LINK_ID = :V$LINK_ID;

       /* FOR SELECT VT.VAL, VT.PARAM_ID
            FROM VALT VT
            WHERE VT.OBJ_ID = :V$ELEMENT_ID
              AND VT.IS_DEL = 0
              AND VT.PARAM_ID IN (413, 414)
            INTO :V$T, :V$PARAM_ID
        DO
        BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD(:V$PARAM_ID, :V$NEW_ELEMENT_ID, :V$T)
            INTO :V$BLOB_ID;
        END  */

        FOR SELECT FIRST 1 N.OBJ_ID, N.REASON_ID
            FROM LINKS L
            JOIN LINKS N ON N.REASON_ID = L.PARENT_ID AND N.PARENT_ID = :COPY_ID AND N.OBJ_TYPE_ID = 6 AND N.DATE_DEL IS NULL
            WHERE L.OBJ_ID = :V$ELEMENT_ID AND L.PARENT_TYPE_ID = 6 AND L.DATE_DEL IS NULL
            INTO :V$I, :V$HOUR_ID
        DO
        BEGIN
            SELECT OBJ_ID
            FROM OBJECT_ADD_LINK(:V$I, :V$NEW_ELEMENT_ID, 70, :V$HOUR_ID)
            INTO :V$BLOB_ID;
        END

        FOR SELECT FIRST 1 N.OBJ_ID, N.REASON_ID
            FROM LINKS L
            JOIN LINKS N ON N.REASON_ID = L.PARENT_ID AND N.PARENT_ID = :COPY_ID AND N.OBJ_TYPE_ID = 60 AND N.DATE_DEL IS NULL
            WHERE L.OBJ_ID = :V$ELEMENT_ID AND L.PARENT_TYPE_ID = 60 AND L.DATE_DEL IS NULL
            INTO :V$I, :V$DAY_ID
        DO
        BEGIN
            SELECT OBJ_ID
            FROM OBJECT_ADD_LINK(:V$I, :V$NEW_ELEMENT_ID, 70, :V$DAY_ID)
            INTO :V$BLOB_ID;
        END

        FOR SELECT FIRST 1 L.PARENT_ID
            FROM LINKS L
            WHERE L.OBJ_ID = :V$ELEMENT_ID AND L.PARENT_TYPE_ID = 14 AND L.DATE_DEL IS NULL
            INTO :V$I
        DO
        BEGIN
            SELECT OBJ_ID
            FROM OBJECT_ADD_LINK(:V$I, :V$NEW_ELEMENT_ID, 70)
            INTO :V$BLOB_ID;
        END

        FOR SELECT FIRST 1 L.PARENT_ID
            FROM LINKS L
            WHERE L.OBJ_ID = :V$ELEMENT_ID AND L.PARENT_TYPE_ID = 61 AND L.DATE_DEL IS NULL
            INTO :V$I
        DO
        BEGIN
            SELECT OBJ_ID
            FROM OBJECT_ADD_LINK(:V$I, :V$NEW_ELEMENT_ID, 70)
            INTO :V$BLOB_ID;
        END

        FOR SELECT L.PARENT_ID
            FROM LINKS L
            WHERE L.OBJ_ID = :V$ELEMENT_ID AND L.PARENT_TYPE_ID = 58 AND L.DATE_DEL IS NULL
            INTO :V$I
        DO
        BEGIN
            SELECT OBJ_ID
            FROM OBJECT_ADD_LINK(:V$I, :V$NEW_ELEMENT_ID, 70)
            INTO :V$BLOB_ID;
        END
    END

    -- Копирование элементов нового формата
    FOR
        SELECT I.WEEKDAY_NUM, I.LESSON_NUM, I.CJ_ID, I.ROOM_ID
        FROM SCHEDULE_ITEMS I
        WHERE I.DATE_DEL IS NULL AND I.SCHEDULE_ID = :I$SCHEDULE_TEMPLATE_ID
        INTO :V$DAY_ID, :V$HOUR_ID, :V$ELEMENT_ID, :V$BLOB_ID
    DO
    BEGIN
        INSERT INTO SCHEDULE_ITEMS
        (SCHEDULE_ID, WEEKDAY_NUM, LESSON_NUM, CJ_ID, ROOM_ID)
        VALUES (:COPY_ID, :V$DAY_ID, :V$HOUR_ID, :V$ELEMENT_ID, :V$BLOB_ID);
    END

    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SCHEDULE_DATA_LIST (
    I$SCHEDULE_TEMPLATE_ID BIGINT,
    I$SCHEDULE_ELEMENT_ID BIGINT,
    I$USER_ID BIGINT,
    I$IS_TEMPLATE SMALLINT = 1)
RETURNS (
    SCHEDULE_ELEMENT_ID BIGINT,
    DAY_ID BIGINT,
    DAY_CAPTION VARCHAR(20),
    DAY_DATE DATE,
    DAY_ORDER DOUBLE PRECISION,
    HOUR_ID BIGINT,
    HOUR_NUM INTEGER,
    HOUR_BEGIN TIME,
    HOUR_END TIME,
    GRADE_LOADING_ID BIGINT,
    TEACHER_ID BIGINT,
    TEACHER_CAPTION VARCHAR(1000),
    SUBJECT_ID BIGINT,
    SUBJECT_CAPTION VARCHAR(1000),
    SUBJECT_SMALL_CAPTION VARCHAR(200),
    ROOM_ID BIGINT,
    ROOM_CAPTION VARCHAR(1000),
    CLASS_ID BIGINT,
    CLASS_CAPTION VARCHAR(1000),
    CLASS_ORDER DOUBLE PRECISION,
    SUBGROUP_ID BIGINT,
    SUBGROUP_CAPTION VARCHAR(1000),
    LOADING_COUNT INTEGER,
    GRADE_LOADING_COUNT INTEGER,
    IS_DEL INTEGER,
    IS_INCORRECT_BY_LOADING INTEGER)
AS
BEGIN
    LOADING_COUNT = 0;
    GRADE_LOADING_COUNT = 0;
    IS_DEL = 0;
    IS_INCORRECT_BY_LOADING = 0;

    FOR
        SELECT L70.OBJ_ID, L6.PARENT_ID, L60.PARENT_ID, L58.PARENT_ID, L14.PARENT_ID, L51.PARENT_ID, V376.VAL, V377.VAL, L61.PARENT_ID, TC.CAPTION, RC.CAPTION,
            V42.VAL, V404.VAL, V405.VAL, V406.VAL
        -- Основной цикл по элементам расписания
        FROM LINKS L70
        -- L6 Учебный день (нет в перечне связей ?!)
        JOIN LINKS L6 ON L6.OBJ_ID = L70.OBJ_ID AND L6.PARENT_TYPE_ID = 6 AND L6.DATE_DEL IS NULL
        JOIN LINKS L6_ ON L6_.OBJ_ID = L6.PARENT_ID AND L6_.PARENT_ID = :I$SCHEDULE_TEMPLATE_ID
        -- L60 Учебный час (нет в перечне связей ?!)
        JOIN LINKS L60 ON L60.OBJ_ID = L70.OBJ_ID AND L60.PARENT_TYPE_ID = 60 AND L60.DATE_DEL IS NULL
        JOIN LINKS L60_ ON L60_.OBJ_ID = L60.PARENT_ID AND L60_.PARENT_ID = :I$SCHEDULE_TEMPLATE_ID
        -- L58 Нагрузка учебного коллектива
        JOIN LINKS L58 ON L58.OBJ_ID = L70.OBJ_ID AND L58.PARENT_TYPE_ID = 58 AND L58.DATE_DEL IS NULL
        -- L14 Преподаватель
        JOIN LINKS L14 ON L14.OBJ_ID = L70.OBJ_ID AND L14.PARENT_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
        LEFT JOIN LINKS L14_ ON L14_.OBJ_ID = L58.PARENT_ID AND L14_.PARENT_ID = L14.PARENT_ID AND L14_.PARENT_TYPE_ID = 14 AND L14_.DATE_DEL IS NULL
        -- L51 Предмет с наименованием
        JOIN LINKS L51 ON L51.OBJ_ID = L58.PARENT_ID AND L51.PARENT_TYPE_ID = 51 AND L51.DATE_DEL IS NULL
        JOIN VALS V376 ON V376.OBJ_ID = L51.PARENT_ID AND V376.PARAM_ID = 376 AND V376.IS_DEL = 0
        LEFT JOIN VALS V377 ON V377.OBJ_ID = L51.PARENT_ID AND V377.PARAM_ID = 377 AND V377.IS_DEL = 0
        LEFT JOIN LINKS L61 ON L61.OBJ_ID = L70.OBJ_ID AND L61.PARENT_TYPE_ID = 61 AND L61.DATE_DEL IS NULL
        LEFT JOIN VALD V42 ON V42.PARAM_ID = 42 AND V42.OBJ_ID = L6.PARENT_ID AND V42.IS_DEL = 0
        LEFT JOIN VALI V404 ON V404.PARAM_ID = 404 AND V404.OBJ_ID = L60.PARENT_ID AND V404.IS_DEL = 0
        LEFT JOIN VALT V405 ON V405.PARAM_ID = 405 AND V405.OBJ_ID = L60.PARENT_ID AND V405.IS_DEL = 0
        LEFT JOIN VALT V406 ON V406.PARAM_ID = 406 AND V406.OBJ_ID = L60.PARENT_ID AND V406.IS_DEL = 0
        LEFT JOIN THE_CAPTION_TEACHER(L14.PARENT_ID) AS TC ON 1=1
        LEFT JOIN OBJECT_CAPTION_GET(L61.PARENT_ID, NULL, NULL, :I$USER_ID) AS RC ON 1=1
        WHERE L70.PARENT_ID = :I$SCHEDULE_TEMPLATE_ID AND ((:I$SCHEDULE_ELEMENT_ID IS NULL) OR (L70.OBJ_ID = :I$SCHEDULE_ELEMENT_ID))
            AND ((:I$IS_TEMPLATE = 0) OR (L14_.LINK_ID IS NOT NULL)) AND L70.OBJ_TYPE_ID = 70 AND L70.DATE_DEL IS NULL
        ORDER BY L51.PARENT_ID

        INTO :SCHEDULE_ELEMENT_ID, :DAY_ID, :HOUR_ID, :GRADE_LOADING_ID, :TEACHER_ID, :SUBJECT_ID, :SUBJECT_CAPTION, :SUBJECT_SMALL_CAPTION,
             :ROOM_ID, :TEACHER_CAPTION, :ROOM_CAPTION, :DAY_DATE, :HOUR_NUM, :HOUR_BEGIN, :HOUR_END
    DO
    BEGIN

        CLASS_ID = NULL;
        SUBGROUP_ID = NULL;
        SUBGROUP_CAPTION = '';

        SELECT FIRST 1
               L.PARENT_ID
        FROM LINKS L
        WHERE L.OBJ_ID = :GRADE_LOADING_ID
        AND L.PARENT_TYPE_ID IN (256, 46, 347)  -- CLASS = 9, STREEM = 46, 256 GUP, 347 STREAM
        AND L.DATE_DEL IS NULL
        INTO :CLASS_ID;

        SUBGROUP_ID = CLASS_ID;

        IF (CLASS_ID IS NULL) THEN   -- SUBGROUP = 48
        BEGIN
            SELECT FIRST 1 L48.PARENT_ID, L256.PARENT_ID
            FROM LINKS L48
            JOIN LINKS L47 ON L47.OBJ_ID = L48.PARENT_ID AND L47.PARENT_TYPE_ID = 47 AND L47.DATE_DEL IS NULL
            JOIN LINKS L256 ON L256.OBJ_ID = L47.PARENT_ID AND L256.PARENT_TYPE_ID = 256 AND L256.DATE_DEL IS NULL
            WHERE L48.OBJ_ID = :GRADE_LOADING_ID AND L48.PARENT_TYPE_ID = 48 AND L48.DATE_DEL IS NULL
            INTO :SUBGROUP_ID, CLASS_ID;

            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:SUBGROUP_ID, NULL, NULL, :I$USER_ID)
            INTO SUBGROUP_CAPTION;
        END

        SELECT CAPTION, SORT_ORDER
        FROM OBJECT_CAPTION_GET(:CLASS_ID, NULL, NULL, :I$USER_ID)
        INTO CLASS_CAPTION, CLASS_ORDER;

        SELECT V, SORT_ORDER
        FROM VAL_GET(:DAY_ID, 402, 0, :I$USER_ID)
        INTO :DAY_CAPTION, :DAY_ORDER;

        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SCHEDULE_DAYS_LIST (
    I$SCHEDULE_TEMPLATE_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    DAY_ID BIGINT,
    DAY_CAPTION VARCHAR(4000),
    DAY_DATE DATE,
    DAY_INDEX INTEGER,
    DAY_ORDER SMALLINT)
AS
declare variable LANG_CODE varchar(2);
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :LANG_CODE;

    FOR SELECT L6.OBJ_ID, R.VAL, LV.LISTVAL_ID, V42.VAL, LV.SORT_ORDER
        FROM LINKS L6
        INNER JOIN VALL V402 ON V402.OBJ_ID = L6.OBJ_ID
        INNER JOIN LISTVALS LV ON LV.LISTVAL_ID = V402.LISTVAL_ID
        LEFT JOIN RES_GET(LV.RES_ID,  :LANG_CODE) R ON 1=1
        LEFT JOIN VALD V42 ON V42.PARAM_ID = 42 AND V42.OBJ_ID = L6.OBJ_ID AND V42.IS_DEL = 0
        WHERE L6.PARENT_ID = :I$SCHEDULE_TEMPLATE_ID
          AND L6.DATE_DEL IS NULL
          AND L6.OBJ_TYPE_ID = 6
          AND V402.PARAM_ID = 402
          AND V402.IS_DEL = 0
          AND ((L6.PARENT_TYPE_ID = 59) OR (V42.VAL IS NOT NULL))
        INTO :DAY_ID, :DAY_CAPTION, :DAY_INDEX, :DAY_DATE, :DAY_ORDER
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SCHEDULE_DELETE (
    I$SCHEDULE_ID BIGINT,
    I$ITEM_ID BIGINT,
    I$ITEM_TYPE SMALLINT,
    I$DATE DATE,
    I$LESSON INTEGER,
    I$USER_ID VARCHAR(40))
RETURNS (
    ID BIGINT,
    "DAY" INTEGER,
    "DATE" VARCHAR(40),
    LESSON INTEGER,
    CJ BIGINT,
    ROOM BIGINT,
    DURATION INTEGER,
    TEMPLATE SMALLINT,
    TEACHER BIGINT,
    PARENT BIGINT)
AS
declare variable V$OBJ_ID bigint;
declare variable V$PARENT_ID bigint;
declare variable V$WD integer;
begin

  "DAY" = EXTRACT(MONTH FROM I$DATE) * 100 + EXTRACT(DAY FROM I$DATE);

  V$WD = EXTRACT(WEEKDAY FROM I$DATE);
  IF(V$WD = 0) THEN V$WD = 6; ELSE V$WD = V$WD - 1;

  IF(I$ITEM_TYPE = 0) THEN
  BEGIN
    -- Скрываем шаблонный элемент - физически он не удаляется. Вместо него добавляем замещающий
    SELECT FIRST 1 SI.CJ_ID, SI.ROOM_ID
    FROM SCHEDULE_ITEMS SI
    WHERE SI.DATE_DEL IS NULL AND SI.OBJ_ID = :I$ITEM_ID
    INTO :CJ, :ROOM;

    IF(CJ IS NULL) THEN EXCEPTION DATA_ERROR 'Запись расписания не найдена или была удалена';

    -- Проверяем, что нет другого перекрывающего элемента, добавленного кем-то еще
    SELECT FIRST 1 SI.OBJ_ID
    FROM SCHEDULE_ITEMS SI
    WHERE SI.DATE_DEL IS NULL AND SI.SCHEDULE_ID = :I$SCHEDULE_ID AND SI.LESSON_NUM = :I$LESSON AND SI.WEEKDAY_NUM = :"DAY"
    INTO :ID;

    SELECT FIRST 1 RP.OBJ_ID
    FROM CJ2_REPL_PROCESS RP
    WHERE RP.DATE_DEL IS NULL AND RP.CJ_ID = :CJ AND RP.LESSON_NUM = :I$LESSON AND RP.REPL_DATE = :I$DATE
    INTO :ID;

    IF(ID IS NOT NULL) THEN EXCEPTION DATA_ERROR 'Уже есть замещающая запись для этого урока, возможно созданная другим пользователем';

    -- Добавляем перекрывающую запись - в автоматическом режиме добавляем не замещение, а перекрытие
    -- Признак записи - NULL в поле duration
    INSERT INTO SCHEDULE_ITEMS
    (SCHEDULE_ID, WEEKDAY_NUM, LESSON_NUM, CJ_ID, ROOM_ID, DURATION, PARENT_ID)
    VALUES (:I$SCHEDULE_ID, :"DAY", :I$LESSON, :CJ, :ROOM, NULL, :I$ITEM_ID)
    RETURNING OBJ_ID INTO :ID;

    PARENT = I$ITEM_ID;
    TEACHER = NULL;
    "DAY" = V$WD;
    "DATE" = (SELECT VAL FROM DATE2ISO(:I$DATE, 0));
    LESSON = I$LESSON;
    TEMPLATE = 1;

  END
  ELSE IF(I$ITEM_TYPE = 1) THEN
  BEGIN

    -- Удаляем перекрывающую запись - пустую или реальную
    -- Обратно отдаем основную из шаблона или ничего

    SELECT FIRST 1 SI.OBJ_ID, SI.PARENT_ID
    FROM SCHEDULE_ITEMS SI
    WHERE SI.DATE_DEL IS NULL AND SI.OBJ_ID = :I$ITEM_ID
    INTO :V$OBJ_ID, :V$PARENT_ID;

    IF(V$OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Запись расписания не найдена или была удалена';

    UPDATE SCHEDULE_ITEMS
    SET DATE_DEL = CURRENT_TIMESTAMP
    WHERE OBJ_ID = :I$ITEM_ID;

    SELECT FIRST 1 SI.OBJ_ID, SI.CJ_ID, SI.ROOM_ID, SI.DURATION, SI.WEEKDAY_NUM, SI.LESSON_NUM, J.TEACHER_ID
    FROM SCHEDULE_ITEMS SI
    JOIN CJ2_JOURNAL J ON J.OBJ_ID = SI.CJ_ID
    WHERE SI.DATE_DEL IS NULL AND SI.OBJ_ID = :V$PARENT_ID
    INTO :ID, :CJ, :ROOM, :DURATION, :"DAY", :LESSON, :TEACHER;

    PARENT = NULL;
    TEMPLATE = 0;

  END
  ELSE IF(I$ITEM_TYPE = 2) THEN
  BEGIN

    -- Удаляем запись замещения
    SELECT FIRST 1 RP.CJ_ID, RP.LESSON_NUM
    FROM CJ2_REPL_PROCESS RP
    WHERE RP.DATE_DEL IS NULL AND RP.OBJ_ID = :I$ITEM_ID
    INTO :CJ, :LESSON;

    IF(CJ IS NULL) THEN EXCEPTION DATA_ERROR 'Запись замещения не найдена или была удалена';

    UPDATE CJ2_REPL_PROCESS
    SET DATE_DEL = CURRENT_TIMESTAMP
    WHERE OBJ_ID = :I$ITEM_ID;

    SELECT FIRST 1 SI.OBJ_ID, SI.CJ_ID, SI.ROOM_ID, SI.DURATION, SI.WEEKDAY_NUM, SI.LESSON_NUM, J.TEACHER_ID
    FROM SCHEDULE_ITEMS SI
    JOIN CJ2_JOURNAL J ON J.OBJ_ID = SI.CJ_ID
    WHERE SI.DATE_DEL IS NULL AND SI.CJ_ID = :CJ AND SI.WEEKDAY_NUM = :V$WD AND SI.LESSON_NUM = :LESSON
    INTO :ID, :CJ, :ROOM, :DURATION, :"DAY", :LESSON, :TEACHER;

    PARENT = NULL;
    TEMPLATE = 0;

  END
  ELSE EXCEPTION DATA_ERROR 'Недопустимый тип элемента';

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SCHEDULE_FLOW (
    I$OBJ_ID BIGINT,
    I$DATE DATE,
    I$FULL SMALLINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
declare variable V$TYPE_ID bigint;
declare variable V$OBJ_ID bigint;
declare variable V$DATE_TO date;
declare variable N integer;
declare variable S varchar(1000);
declare variable S1 varchar(1000);
declare variable S2 varchar(1000);
declare variable V$T1 time;
declare variable V$T2 time;
declare variable V$YEAR_ID bigint;
declare variable V$YEAR integer;
declare variable V$OU_ID bigint;
declare variable V$DIFF bigint;
declare variable V$PERDAY float;
declare variable V$OBJ_ID2 bigint;
declare variable V$TEACHER_ID bigint;
declare variable V$SUBJECT_ID bigint;
declare variable V$GRADE_ID bigint;
declare variable V$MG_ID bigint;
declare variable V$DUR integer;
declare variable V$PERWEEK integer;
declare variable V$WEEKDAY_NUM integer;
declare variable V$ROOM_ID bigint;
declare variable V$LESSON_NUM integer;
declare variable V$D1 integer;
declare variable V$D2 integer;
declare variable D date;
declare variable D1 date;
declare variable D2 date;
declare variable V$PD date;
declare variable V$PARENT_ID bigint;
declare variable V$CJ_ID bigint;
declare variable V$IS_STREAM_GROUP integer;
declare variable V$TT1 time;
declare variable V$TT2 time;
begin

  -- I$FULL - полные справочники или частичные при переходе внутри дат

  SELECT TYPE_ID
  FROM OBJECTS
  WHERE OBJ_ID = :I$OBJ_ID
  INTO :V$TYPE_ID;

  TAG_NAME = 'ou_type';
  VAL = (SELECT STATUS FROM OU_LICENCE_TYPE);
  SUSPEND;

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;
  TAG_NAME = 'my_id';
  VAL = NULL;
  SELECT FIRST 1 U.OBJ_ID
  FROM USERS U
  WHERE U.USER_ID = CAST(:I$USER_ID AS BIGINT)
  INTO :VAL;
  SUSPEND;

  SELECT V37.LISTVAL_ID, LP2.PARENT_ID, V3080.VAL, V3081.VAL, LV.COST, CAST(LV.TAG AS DATE)
  FROM LINKS LP68
  JOIN VALL V37 ON V37.OBJ_ID = LP68.OBJ_ID AND V37.PARAM_ID = 37 AND V37.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V37.LISTVAL_ID
  JOIN LINKS LP2 ON LP2.OBJ_ID = LP68.PARENT_ID AND LP2.PARENT_TYPE_ID = 2 AND LP2.DATE_DEL IS NULL
  LEFT JOIN VALT V3080 ON V3080.OBJ_ID = LP68.OBJ_ID AND V3080.PARAM_ID = 3080 AND V3080.IS_DEL = 0
  LEFT JOIN VALT V3081 ON V3081.OBJ_ID = LP68.OBJ_ID AND V3081.PARAM_ID = 3081 AND V3081.IS_DEL = 0
  WHERE LP68.OBJ_ID = :I$OBJ_ID AND LP68.PARENT_TYPE_ID = 68 AND LP68.DATE_DEL IS NULL
  INTO :V$YEAR_ID, :V$OU_ID, :V$T1, :V$T2, :V$YEAR, :V$PD;

  -- Корректируем дату до начала недели (неделя начинается с понедельника)
  IF(I$DATE < '01.09.' || V$YEAR) THEN I$DATE = '01.09.' || V$YEAR;
  N = EXTRACT(WEEKDAY FROM I$DATE);
  IF(N = 0) THEN N = 6; ELSE N = N - 1;
  I$DATE = DATEADD(DAY, -N, I$DATE);
  V$DATE_TO = DATEADD(6 DAY TO I$DATE);

  TAG_NAME = 'date';
  VAL = (SELECT VAL FROM DATE2ISO(:I$DATE, 0));
  SUSPEND;

  TAG_NAME = 'time_start';
  VAL = COALESCE(V$T1, '08:00:00');
  SUSPEND;

  TAG_NAME = 'time_end';
  VAL = COALESCE(V$T2, '18:00:00');
  SUSPEND;

  -- Выдаем дату начала учебного года, для которого задан шаблон
  TAG_NAME = 'period_date';
  VAL = (SELECT VAL FROM DATE2ISO(:V$PD, 0));
  SUSPEND;

  -- Справочник этапов
  TAG_NAME = 'grades::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
    SELECT LISTVAL_ID, VAL
    FROM OO_FILTRED_LIST(25)
    WHERE :I$FULL = 1
    ORDER BY SORT_ORDER
    INTO :V$OBJ_ID, :S
  DO
  BEGIN
    TAG_NAME = 'grades:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'grades:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'grades:r:name';
    VAL = S;
    SUSPEND;
  END

  -- Причины отсутствия
  -- Справочник этапов
  TAG_NAME = 'rreasons::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
    SELECT LISTVAL_ID, VAL
    FROM LISTVALS_LIST(317)
    WHERE :I$FULL = 1 AND IS_DEL = 0
    ORDER BY SORT_ORDER
    INTO :V$OBJ_ID, :S
  DO
  BEGIN
    TAG_NAME = 'rreasons:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'rreasons:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'rreasons:r:name';
    VAL = S;
    SUSPEND;
  END

  -- Список преподавателей, все про запас, и добавить сюда реальных из журналов
  TAG_NAME = 'teachers::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
    SELECT L.TEACHER_ID, L.TEACHER_CAPTION, V3065.VAL
    FROM PARAGRAF_GRADE_TEACHERS_LIST(NULL) L
    LEFT JOIN VALS V3065 ON V3065.OBJ_ID = L.TEACHER_ID AND V3065.PARAM_ID = 3065 AND V3065.IS_DEL = 0
    WHERE :I$FULL = 1
    UNION
    SELECT J.TEACHER_ID, C.CAPTION, V3065.VAL
    FROM CJ2_JOURNAL J
    LEFT JOIN OBJECT_CAPTION_GET(J.TEACHER_ID, NULL) C ON 1 = 1
    LEFT JOIN VALS V3065 ON V3065.OBJ_ID = J.TEACHER_ID AND V3065.PARAM_ID = 3065 AND V3065.IS_DEL = 0
    WHERE J.JOURNAL_TYPE IN (0, 1) AND J.DATE_DEL IS NULL AND J.TEACHER_ID IS NOT NULL AND :I$FULL = 1
    ORDER BY 2
    INTO :V$OBJ_ID, :S, :S1
  DO
  BEGIN
    TAG_NAME = 'teachers:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'teachers:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'teachers:r:name';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'teachers:r:mdays';
    VAL = S1;
    SUSPEND;
  END

  -- Список предметов - выбираем весь список
  TAG_NAME = 'subjects::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
    SELECT DISTINCT SUBJECT_ID, V3066.VAL, V3058.LISTVAL_ID, V3059.VAL, V377.VAL
    FROM CJ2_JOURNAL
    LEFT JOIN VALS V3066 ON V3066.OBJ_ID = SUBJECT_ID AND V3066.PARAM_ID IN (3066, 3067) AND V3066.IS_DEL = 0
    LEFT JOIN VALL V3058 ON V3058.OBJ_ID = SUBJECT_ID AND V3058.PARAM_ID IN (3058) AND V3058.IS_DEL = 0
    LEFT JOIN VALF V3059 ON V3059.OBJ_ID = SUBJECT_ID AND V3059.PARAM_ID IN (3059) AND V3059.IS_DEL = 0
    LEFT JOIN VALS V377 ON V377.OBJ_ID = SUBJECT_ID AND V377.PARAM_ID IN (377, 1752) AND V377.IS_DEL = 0
    WHERE SUBJECT_ID IS NOT NULL AND :I$FULL = 1
    INTO :V$OBJ_ID, :S, :V$DIFF, :V$PERDAY, :S1
  DO
  BEGIN
    TAG_NAME = 'subjects:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'subjects:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'subjects:r:name';
    VAL = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$OBJ_ID));
    SUSPEND;
    TAG_NAME = 'subjects:r:code';
    VAL = S1;
    SUSPEND;
    TAG_NAME = 'subjects:r:color';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'subjects:r:difficulty';
    VAL = V$DIFF;
    SUSPEND;
    TAG_NAME = 'subjects:r:perday';
    VAL = CAST(V$PERDAY AS NUMERIC(18, 1));
    SUSPEND;
  END

  -- Список помещений - в данной ОУ
  TAG_NAME = 'buildings::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
    SELECT L16.OBJ_ID, C.CAPTION
    FROM LINKS L73
    JOIN LINKS L16 ON L16.PARENT_ID = L73.OBJ_ID AND L16.OBJ_TYPE_ID = 16 AND L16.DATE_DEL IS NULL
    LEFT JOIN OBJECT_CAPTION_GET(L16.OBJ_ID) C ON 1 = 1
    WHERE L73.PARENT_ID = :V$OU_ID AND L73.OBJ_TYPE_ID = 73 AND L73.DATE_DEL IS NULL AND :I$FULL = 1
    INTO :V$OBJ_ID, :S
  DO
  BEGIN
    TAG_NAME = 'buildings:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'buildings:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'buildings:r:name';
    VAL = S;
    SUSPEND;

    -- Помещения выбираем только учебно-лабораторные и вспомогательные
    TAG_NAME = 'buildings:r:rooms::json&colon;array';
    VAL = '1';
    SUSPEND;
    FOR
      SELECT L61.OBJ_ID, V407.VAL, V408.VAL, V1344.VAL
      FROM LINKS L61
      JOIN VALL V525 ON V525.OBJ_ID = L61.OBJ_ID AND V525.PARAM_ID = 525 AND V525.IS_DEL = 0 AND V525.LISTVAL_ID IN (23, 12764)
      LEFT JOIN VALR V1344 ON V1344.OBJ_ID = L61.OBJ_ID AND V1344.PARAM_ID = 1344 AND V1344.IS_DEL = 0
      -- Номер и название помещения
      LEFT JOIN VALS V407 ON V407.OBJ_ID = L61.OBJ_ID AND V407.PARAM_ID = 407 AND V407.IS_DEL = 0
      JOIN VALS V408 ON V408.OBJ_ID = L61.OBJ_ID AND V408.PARAM_ID = 408 AND V408.IS_DEL = 0
      WHERE L61.PARENT_ID = :V$OBJ_ID AND L61.OBJ_TYPE_ID = 61 AND L61.DATE_DEL IS NULL
      ORDER BY 2
      INTO :V$OBJ_ID2, :S, :S2, :V$TEACHER_ID
    DO
    BEGIN
      TAG_NAME = 'buildings:r:rooms:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'buildings:r:rooms:r:id';
      VAL = V$OBJ_ID2;
      SUSPEND;
      TAG_NAME = 'buildings:r:rooms:r:name';
      VAL = COALESCE(S, '');
      IF(VAL <> '') THEN VAL = VAL || ' - ';
      VAL = VAL || S2;
      SUSPEND;
      TAG_NAME = 'buildings:r:rooms:r:code';
      VAL = S;
      SUSPEND;
      TAG_NAME = 'buildings:r:rooms:r:shortname';
      VAL = S2;
      SUSPEND;
      TAG_NAME = 'buildings:r:rooms:r:teacher_id';
      VAL = V$TEACHER_ID;
      SUSPEND;
      -- Список предметов, закрепленных за помещением
      TAG_NAME = 'buildings:r:rooms:r:subjects::json&colon;array';
      VAL = 1;
      SUSPEND;
      FOR
        SELECT L51.OBJ_ID
        FROM LINKS L51
        WHERE L51.PARENT_ID = :V$OBJ_ID2 AND L51.OBJ_TYPE_ID IN (51, 197) AND L51.DATE_DEL IS NULL AND 0 = 1
        INTO :V$SUBJECT_ID
      DO
      BEGIN
        TAG_NAME = 'buildings:r:rooms:r:subjects:r';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'buildings:r:rooms:r:subjects:r:id';
        VAL = V$SUBJECT_ID;
        SUSPEND;
      END
    END
  END

  -- Добавляем виртуальный id для помещений на стороне, id помещения будет равно id ОУ чтобы сохранялась связность
  TAG_NAME = 'buildings:r';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'buildings:r:id';
  VAL = '';
  SUSPEND;
  TAG_NAME = 'buildings:r:name';
  VAL = 'Вне ОООД';
  SUSPEND;
  TAG_NAME = 'buildings:r:rooms::json&colon;array';
  VAL = '1';
  SUSPEND;
  TAG_NAME = 'buildings:r:rooms:r';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'buildings:r:rooms:r:id';
  VAL = V$OU_ID;
  SUSPEND;
  TAG_NAME = 'buildings:r:rooms:r:name';
  VAL = 'Вне ОООД';
  SUSPEND;
  TAG_NAME = 'buildings:r:rooms:r:teacher_id';
  VAL = '';
  SUSPEND;
  TAG_NAME = 'buildings:r:rooms:r:subjects::json&colon;array';
  VAL = 1;
  SUSPEND;

  -- Список мастер-групп
  TAG_NAME = 'mgroups::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
    SELECT DISTINCT LPG.EXT_OBJ_ID, C.CAPTION, LV.LISTVAL_ID
    FROM CJ2_JOURNAL J
    JOIN LISTVALS LV ON LV.LISTVAL_ID = J.STAGE_INDEX
    JOIN LINKS LPG ON LPG.OBJ_ID = J.GRADE_ID AND LPG.PARENT_TYPE_ID = 2 AND LPG.DATE_DEL IS NULL AND LPG.EXT_OBJ_ID IS NOT NULL
    LEFT JOIN OBJECT_CAPTION_GET(LPG.EXT_OBJ_ID) C ON 1 = 1
    WHERE J.DATE_DEL IS NULL AND J.YEAR_ID = :V$YEAR_ID AND :I$FULL = 1
    ORDER BY LV.COST, 2
    INTO :V$OBJ_ID, :S, :V$DIFF
  DO
  BEGIN
    TAG_NAME = 'mgroups:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'mgroups:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'mgroups:r:name';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'mgroups:r:stage_id';
    VAL = V$DIFF;
    SUSPEND;
  END

  -- Список всех журналов с названиями предметов, кроме журнала-плана воспитательной работы
  TAG_NAME = 'journals::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
    SELECT J.OBJ_ID, J.JOURNAL_TYPE, J.TEACHER_ID, J.GRADE_ID, J.SUBJECT_ID, J.JOURNAL_NAME, C.CAPTION,
      IIF(J.WEEKS > 0, ROUND(J.HOURS / J.WEEKS), NULL), J.DURATION, COALESCE(LPG.EXT_OBJ_ID, V3370.VAL), J.STAGE_INDEX, J.ROOM_ID,
      COALESCE((SELECT FIRST 1 PS.IS_STM FROM PLAN_SUBJECTS PS WHERE PS.DATE_DEL IS NULL AND PS.PLAN_ID = J.REF_ID AND PS.SUBJECT_ID = J.SUBJECT_ID), 1) IS_STM
    FROM CJ2_JOURNAL J
    LEFT JOIN LISTVALS LV ON LV.LISTVAL_ID = J.STAGE_INDEX
    LEFT JOIN OBJECT_CAPTION_GET(J.GRADE_ID) C ON 1 = 1
    LEFT JOIN LINKS LPG ON LPG.OBJ_ID = J.GRADE_ID AND LPG.PARENT_TYPE_ID = 2 AND LPG.DATE_DEL IS NULL
    LEFT JOIN VALR V3370 ON V3370.OBJ_ID = J.GRADE_ID AND V3370.PARAM_ID = 3370 AND V3370.IS_DEL = 0
    WHERE J.DATE_DEL IS NULL AND J.YEAR_ID = :V$YEAR_ID AND J.JOURNAL_TYPE <> 20 AND :I$FULL = 1
    ORDER BY 10, 2, LV.COST, 6
    INTO :V$OBJ_ID, :N, :V$TEACHER_ID, :V$GRADE_ID, :V$SUBJECT_ID, :S, :S1, :V$PERWEEK, :V$DUR, :V$MG_ID, :V$DIFF, :V$ROOM_ID,:V$IS_STREAM_GROUP
  DO
  BEGIN
    TAG_NAME = 'journals:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'journals:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'journals:r:type';
    VAL = N;
    SUSPEND;
    TAG_NAME = 'journals:r:teacher_id';
    VAL = V$TEACHER_ID;
    SUSPEND;
    -- ссылка на мастер-группу
    -- мастер-группа - это ГУП, из которого были сформированы группы по предмету
    -- все что mg_id null это потоковые группы
    -- также выдаем mg_id со ссылкой на ГУП те потоковые группы, в которых числятся ученики только одного ГУП
    TAG_NAME = 'journals:r:mg_id';
    VAL = V$MG_ID;
    SUSPEND;
    TAG_NAME = 'journals:r:grade_id';
    VAL = V$GRADE_ID;
    SUSPEND;
    TAG_NAME = 'journals:r:grade_name';
    VAL = S1;
    SUSPEND;
    TAG_NAME = 'journals:r:stage_id';
    VAL = V$DIFF;
    SUSPEND;
    TAG_NAME = 'journals:r:subject_id';
    VAL = V$SUBJECT_ID;
    SUSPEND;
    TAG_NAME = 'journals:r:name';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'journals:r:perweek';
    VAL = V$PERWEEK;
    SUSPEND;
    TAG_NAME = 'journals:r:dur';
    VAL = V$DUR;
    SUSPEND;
    -- Ресурсы
    TAG_NAME = 'journals:r:resources';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'journals:r:room_id';
    VAL = V$ROOM_ID;
    SUSPEND;
    -- флаг потоковости группы
    TAG_NAME = 'journals:r:is_stream_group';
    VAL = V$IS_STREAM_GROUP;
    SUSPEND;
  END

  -- Планы воспитательной работы, попадающие по датам в нужный диапазон
  -- только конкретные мероприятия, причем нельзя выбирать мероприятия с длительным сроком (если выбран диапазон дат, будет взята только первая дата)
  -- только утвержденный план
  TAG_NAME = 'vosp::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
    SELECT J.OBJ_ID, L.OBJ_ID, L.LESSON_DATE, L.LESSON_EXTRA, L.LESSON_THEME, L.LESSON_HOURS * 60
    FROM CJ2_JOURNAL J
    JOIN VALL V ON V.OBJ_ID = J.REF_ID AND V.PARAM_ID = 3373 AND V.LISTVAL_ID = 11715 AND V.IS_DEL = 0
    JOIN CJ2_JOURNAL_LESSONS L ON L.DATE_DEL IS NULL AND L.CJ_ID = J.OBJ_ID AND L.LESSON_NUM > 0 AND L.IS_ONLINE = 1
      AND L.LESSON_DATE >= :I$DATE AND L.LESSON_DATE <= :V$DATE_TO
    WHERE J.DATE_DEL IS NULL AND J.YEAR_ID = :V$YEAR_ID AND J.JOURNAL_TYPE = 20
    ORDER BY L.LESSON_DATE
    INTO :V$CJ_ID, :V$OBJ_ID, :D1, :S2, :S, :V$LESSON_NUM
  DO
  BEGIN
    TAG_NAME = 'vosp:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'vosp:r:cj_id';
    VAL = V$CJ_ID;
    SUSPEND;
    TAG_NAME = 'vosp:r:meeting_id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'vosp:r:name';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'vosp:r:day';
    VAL = EXTRACT(MONTH FROM D1) * 100 + EXTRACT(DAY FROM D1);
    SUSPEND;
    -- Если не указано время начала (в extra) или длительность - показываем весь день
    IF(S2 IS NOT NULL AND S2 <> '' AND V$LESSON_NUM > 0) THEN
    BEGIN
      V$TT1 = S2;
      V$TT2 = DATEADD(V$LESSON_NUM MINUTE TO V$TT1);
    END
    ELSE
    BEGIN
      V$TT1 = V$T1;
      V$TT2 = V$T2;
    END
    TAG_NAME = 'vosp:r:time_from';
    VAL = V$TT1;
    SUSPEND;
    TAG_NAME = 'vosp:r:time_to';
    VAL = V$TT2;
    SUSPEND;
    -- Участники, список mg_id (ГУП) через запятую
    TAG_NAME = 'vosp:r:members';
    VAL = '';
    -- + все участники
    FOR
      SELECT M.MG_ID
      FROM VOSP_MEMBERS_LIST(:V$OBJ_ID) M
      INTO :V$OBJ_ID2
    DO
    BEGIN
      IF(VAL <> '') THEN VAL = VAL || ',';
      VAL = VAL || V$OBJ_ID2;
    END
    -- Дальше только если ВСЕ не были выбраны
    IF(VAL = '') THEN
    BEGIN
      -- + уровни обучения !!!
      -- + параллели !!!
      -- + конкретные классы
      FOR
        SELECT DISTINCT COALESCE(LP179.EXT_OBJ_ID, V3370.VAL)
        FROM CJ2_LESSON_ATTRS A
        JOIN OBJECTS O ON O.OBJ_ID = A.REF_ID AND O.TYPE_ID = 9
        JOIN LINKS L10 ON L10.PARENT_ID = A.REF_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        JOIN LINKS LP179 ON LP179.OBJ_ID = L10.OBJ_ID AND LP179.PARENT_TYPE_ID = 179 AND LP179.DATE_DEL IS NULL
        JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.GRADE_ID = LP179.PARENT_ID AND J.YEAR_ID = :V$YEAR_ID
        LEFT JOIN VALR V3370 ON V3370.OBJ_ID = J.GRADE_ID AND V3370.PARAM_ID = 3370 AND V3370.IS_DEL = 0
        WHERE A.DATE_DEL IS NULL AND A.LESSON_ID = :V$OBJ_ID AND A.ATTR_NAME = 'msel' AND (LP179.EXT_OBJ_ID IS NOT NULL OR V3370.VAL IS NOT NULL)
        INTO :V$OBJ_ID2
      DO
      BEGIN
        IF(VAL <> '') THEN VAL = VAL || ',';
        VAL = VAL || V$OBJ_ID2;
      END
    END
    SUSPEND;
  END

  -- Склеиваем расписание по дням недели - предполагается что номера уроков у нас не очень сильно поменяются
  V$WEEKDAY_NUM = 0;
  TAG_NAME = 'days::json&colon;array';
  VAL = '1';
  SUSPEND;
  WHILE(V$WEEKDAY_NUM < 7) DO
  BEGIN
    V$OBJ_ID = NULL;
    SELECT FIRST 1 V402.LISTVAL_ID - 798, R.VAL
    FROM LINKS L59
    JOIN VALL V1341 ON V1341.OBJ_ID = L59.OBJ_ID AND V1341.PARAM_ID = 1341 AND V1341.IS_DEL = 0 AND V1341.LISTVAL_ID = 2 -- выгружаемые на портал / активные
    LEFT JOIN VALD V3120 ON V3120.OBJ_ID = L59.OBJ_ID AND V3120.PARAM_ID = 3120 AND V3120.IS_DEL = 0
    LEFT JOIN VALD V3121 ON V3121.OBJ_ID = L59.OBJ_ID AND V3121.PARAM_ID = 3121 AND V3121.IS_DEL = 0
    JOIN LINKS L6 ON L6.PARENT_ID = L59.OBJ_ID AND L6.OBJ_TYPE_ID = 6 AND L6.DATE_DEL IS NULL
    JOIN VALL V402 ON V402.OBJ_ID = L6.OBJ_ID AND V402.PARAM_ID = 402 AND V402.IS_DEL = 0 AND V402.LISTVAL_ID = 798 + :V$WEEKDAY_NUM
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V402.LISTVAL_ID
    JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
    LEFT JOIN VALD V42 ON V42.OBJ_ID = L6.OBJ_ID AND V42.PARAM_ID = 42 AND V42.IS_DEL = 0
    WHERE L59.PARENT_ID = :I$OBJ_ID AND L59.OBJ_TYPE_ID = 59 AND L59.DATE_DEL IS NULL
      AND (V3120.VAL IS NULL OR V3120.VAL < DATEADD(7 DAY TO :I$DATE))
      AND (V3121.VAL IS NULL OR V3121.VAL >= :I$DATE)
    INTO :V$OBJ_ID, :S;

    IF(V$OBJ_ID IS NOT NULL) THEN
    BEGIN
      TAG_NAME = 'days:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'days:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'days:r:name';
      VAL = S;
      SUSPEND;
      TAG_NAME = 'days:r:date';
      VAL = (SELECT RESULT FROM DATE2STR(DATEADD(:V$OBJ_ID DAY TO :I$DATE)));
      SUSPEND;
      TAG_NAME = 'days:r:dateiso';
      VAL = (SELECT VAL FROM DATE2ISO(DATEADD(:V$OBJ_ID DAY TO :I$DATE), 0));
      SUSPEND;
    END
    V$WEEKDAY_NUM = V$WEEKDAY_NUM + 1;
  END

  -- Номера и время уроков - для фиксированной сетки
  V$LESSON_NUM = -1;
  TAG_NAME = 'lessons::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
    SELECT DISTINCT V404.VAL, V405.VAL, V406.VAL
    FROM LINKS L59
    JOIN VALL V1341 ON V1341.OBJ_ID = L59.OBJ_ID AND V1341.PARAM_ID = 1341 AND V1341.IS_DEL = 0 AND V1341.LISTVAL_ID = 2 -- выгружаемые на портал / активные
    LEFT JOIN VALD V3120 ON V3120.OBJ_ID = L59.OBJ_ID AND V3120.PARAM_ID = 3120 AND V3120.IS_DEL = 0
    LEFT JOIN VALD V3121 ON V3121.OBJ_ID = L59.OBJ_ID AND V3121.PARAM_ID = 3121 AND V3121.IS_DEL = 0
    JOIN LINKS L60 ON L60.PARENT_ID = L59.OBJ_ID AND L60.OBJ_TYPE_ID = 60 AND L60.DATE_DEL IS NULL
    JOIN VALI V404 ON V404.OBJ_ID = L60.OBJ_ID AND V404.PARAM_ID = 404 AND V404.IS_DEL = 0
    LEFT JOIN VALT V405 ON V405.OBJ_ID = L60.OBJ_ID AND V405.PARAM_ID = 405 AND V405.IS_DEL = 0
    LEFT JOIN VALT V406 ON V406.OBJ_ID = L60.OBJ_ID AND V406.PARAM_ID = 406 AND V406.IS_DEL = 0
    WHERE L59.PARENT_ID = :I$OBJ_ID AND L59.OBJ_TYPE_ID = 59 AND L59.DATE_DEL IS NULL
      AND (V3120.VAL IS NULL OR V3120.VAL < DATEADD(7 DAY TO :I$DATE))
      AND (V3121.VAL IS NULL OR V3121.VAL >= :I$DATE)
    ORDER BY 1, 2
    INTO :N, :V$T1, :V$T2
  DO
  BEGIN
    IF(V$LESSON_NUM <> N) THEN
    BEGIN
      TAG_NAME = 'lessons:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'lessons:r:id';
      VAL = N;
      SUSPEND;
      TAG_NAME = 'lessons:r:t_from';
      VAL = V$T1;
      SUSPEND;
      TAG_NAME = 'lessons:r:t_to';
      VAL = V$T2;
      SUSPEND;
    END
    V$LESSON_NUM = N;
  END

  -- Список назначений - фильтруем по дням недели, попадающим в диапазон
  -- Внимание: выборка учителей идет не по журналу, а явно по teacher
  -- тут выдаем все записи шаблона, а дальше на клиенте дофильтровываются те, по которым сделано замещение
  TAG_NAME = 'schedule::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
    SELECT I.OBJ_ID, I.WEEKDAY_NUM, I.LESSON_NUM, I.CJ_ID, I.ROOM_ID, I.DURATION, J.TEACHER_ID, I.EXT_INFO
    FROM LINKS L59
    JOIN VALL V1341 ON V1341.OBJ_ID = L59.OBJ_ID AND V1341.PARAM_ID = 1341 AND V1341.IS_DEL = 0 AND V1341.LISTVAL_ID = 2 -- выгружаемые на портал / активные
    LEFT JOIN VALD V3120 ON V3120.OBJ_ID = L59.OBJ_ID AND V3120.PARAM_ID = 3120 AND V3120.IS_DEL = 0
    LEFT JOIN VALD V3121 ON V3121.OBJ_ID = L59.OBJ_ID AND V3121.PARAM_ID = 3121 AND V3121.IS_DEL = 0
    JOIN SCHEDULE_ITEMS I ON I.DATE_DEL IS NULL AND I.SCHEDULE_ID = L59.OBJ_ID
      AND (V3120.VAL IS NULL OR DATEADD(I.WEEKDAY_NUM DAY TO :I$DATE) >= V3120.VAL)
      AND (V3121.VAL IS NULL OR DATEADD(I.WEEKDAY_NUM DAY TO :I$DATE) <= V3121.VAL)
    JOIN CJ2_JOURNAL J ON J.OBJ_ID = I.CJ_ID
    WHERE L59.PARENT_ID = :I$OBJ_ID AND L59.OBJ_TYPE_ID = 59 AND L59.DATE_DEL IS NULL
      AND (V3120.VAL IS NULL OR V3120.VAL < DATEADD(7 DAY TO :I$DATE))
      AND (V3121.VAL IS NULL OR V3121.VAL >= :I$DATE)
    INTO :V$OBJ_ID, :V$WEEKDAY_NUM, :V$LESSON_NUM, :V$OBJ_ID2, :V$ROOM_ID, :V$DUR, :V$TEACHER_ID, :S
  DO
  BEGIN
    TAG_NAME = 'schedule:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'schedule:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'schedule:r:day';
    VAL = V$WEEKDAY_NUM;
    SUSPEND;
    -- Нумерация lesson: 1..59 - номер урока по расписанию, >= 60 - метка времени в минутах с начала суток
    TAG_NAME = 'schedule:r:lesson';
    VAL = V$LESSON_NUM;
    SUSPEND;
    TAG_NAME = 'schedule:r:cj';
    VAL = V$OBJ_ID2;
    SUSPEND;
    TAG_NAME = 'schedule:r:room';
    VAL = V$ROOM_ID;
    SUSPEND;
    TAG_NAME = 'schedule:r:duration';
    VAL = V$DUR;
    SUSPEND;
    TAG_NAME = 'schedule:r:teacher';
    VAL = V$TEACHER_ID;
    SUSPEND;
    TAG_NAME = 'schedule:r:parent';
    VAL = '';
    SUSPEND;
    TAG_NAME = 'schedule:r:ext_info';
    VAL = S;
    SUSPEND;
  END

  -- Записи индивидуального назначения по датам, причем в качестве номера дня недели тут используется M * 100 + D
  V$D1 = EXTRACT(MONTH FROM I$DATE) * 100 + EXTRACT(DAY FROM I$DATE);
  V$D2 = EXTRACT(MONTH FROM DATEADD(7 DAY TO I$DATE)) * 100 + EXTRACT(DAY FROM DATEADD(7 DAY TO I$DATE));
  TAG_NAME = 'fschedule::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
    SELECT I.OBJ_ID, I.WEEKDAY_NUM, I.LESSON_NUM, I.CJ_ID, I.ROOM_ID, I.DURATION, J.TEACHER_ID, I.PARENT_ID, I.EXT_INFO
    FROM SCHEDULE_ITEMS I
    JOIN CJ2_JOURNAL J ON J.OBJ_ID = I.CJ_ID
    WHERE I.DATE_DEL IS NULL AND I.SCHEDULE_ID = :I$OBJ_ID AND I.WEEKDAY_NUM >= :V$D1 AND I.WEEKDAY_NUM < :V$D2
    INTO :V$OBJ_ID, :V$WEEKDAY_NUM, :V$LESSON_NUM, :V$OBJ_ID2, :V$ROOM_ID, :V$DUR, :V$TEACHER_ID, :V$PARENT_ID, :S
  DO
  BEGIN
    TAG_NAME = 'fschedule:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'fschedule:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'fschedule:r:day';
    -- Тут может получиться переход границы месяца
    IF((V$WEEKDAY_NUM - V$D1) > 7) THEN VAL = V$WEEKDAY_NUM - (V$D2 - 7);
    ELSE VAL = V$WEEKDAY_NUM - V$D1;
    SUSPEND;
    TAG_NAME = 'fschedule:r:date';
    VAL = V$WEEKDAY_NUM;
    SUSPEND;
    TAG_NAME = 'fschedule:r:lesson';
    VAL = V$LESSON_NUM;
    SUSPEND;
    TAG_NAME = 'fschedule:r:cj';
    VAL = V$OBJ_ID2;
    SUSPEND;
    TAG_NAME = 'fschedule:r:room';
    VAL = V$ROOM_ID;
    SUSPEND;
    TAG_NAME = 'fschedule:r:duration';
    VAL = V$DUR;
    SUSPEND;
    TAG_NAME = 'fschedule:r:teacher';
    VAL = V$TEACHER_ID;
    SUSPEND;
    TAG_NAME = 'fschedule:r:parent';
    VAL = V$PARENT_ID;
    SUSPEND;
    TAG_NAME = 'fschedule:r:ext_info';
    VAL = S;
    SUSPEND;
  END

  -- План замещений
  TAG_NAME = 'rplan::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
    SELECT P.OBJ_ID, P.PERSON_ID, P.REASON_ID, P.DATE_FROM, P.DATE_TO
    FROM CJ2_REPL_PLAN P
    WHERE P.DATE_DEL IS NULL AND P.DATE_FROM <= DATEADD(7 DAY TO :I$DATE) AND (P.DATE_TO IS NULL OR P.DATE_TO >= :I$DATE)
    INTO :V$OBJ_ID, :V$GRADE_ID, :V$MG_ID, :D1, :D2
  DO
  BEGIN
    TAG_NAME = 'rplan:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'rplan:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'rplan:r:teacher_id';
    VAL = V$GRADE_ID;
    SUSPEND;
    TAG_NAME = 'rplan:r:reason_id';
    VAL = V$MG_ID;
    SUSPEND;
    TAG_NAME = 'rplan:r:date_from';
    VAL = (SELECT VAL FROM DATE2ISO(:D1, 0));
    SUSPEND;
    TAG_NAME = 'rplan:r:date_to';
    VAL = (SELECT VAL FROM DATE2ISO(:D2, 0));
    SUSPEND;
  END

  -- Записи замен, попадающие в актуальный диапазон по датам
  -- Сюда же попадают обычные замены уроков
  TAG_NAME = 'subst::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
    SELECT P.OBJ_ID, P.REPL_DATE, P.LESSON_NUM, P.REPL_CJ_ID, P.CJ_ID, P.ROOM_ID, COALESCE(J.DURATION, 45), P.REPL_PERSON_ID
    FROM CJ2_REPL_PROCESS P
    JOIN CJ2_JOURNAL J ON J.OBJ_ID = P.CJ_ID
    WHERE P.DATE_DEL IS NULL AND P.REPL_DATE >= :I$DATE AND P.REPL_DATE < DATEADD(7 DAY TO :I$DATE)
    INTO :V$OBJ_ID, :D, :V$LESSON_NUM, :V$OBJ_ID2, :V$CJ_ID, :V$ROOM_ID, :V$DUR, :V$TEACHER_ID
  DO
  BEGIN
    V$WEEKDAY_NUM = EXTRACT(MONTH FROM D) * 100 + EXTRACT(DAY FROM D);
    TAG_NAME = 'subst:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'subst:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'subst:r:day';
    VAL = V$WEEKDAY_NUM - V$D1;
    SUSPEND;
    TAG_NAME = 'subst:r:date';
    VAL = V$WEEKDAY_NUM;
    SUSPEND;
    TAG_NAME = 'subst:r:lesson';
    VAL = V$LESSON_NUM;
    SUSPEND;
    TAG_NAME = 'subst:r:cj';
    VAL = COALESCE(V$OBJ_ID2, V$CJ_ID); -- NULL, если тот же журнал ?
    SUSPEND;
    TAG_NAME = 'subst:r:src_cj';
    VAL = V$CJ_ID;
    SUSPEND;
    TAG_NAME = 'subst:r:room';
    VAL = V$ROOM_ID;
    SUSPEND;
    TAG_NAME = 'subst:r:duration';
    VAL = V$DUR;
    SUSPEND;
    TAG_NAME = 'subst:r:teacher';
    VAL = V$TEACHER_ID;
    SUSPEND;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SCHEDULE_GET (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(1000))
AS
declare variable V$TYPE_ID bigint;
declare variable V$OBJ_ID bigint;
declare variable V$OBJ_ID2 bigint;
declare variable V$OU_ID bigint;
declare variable S varchar(1000);
declare variable S1 varchar(1000);
declare variable S2 varchar(1000);
declare variable V$D1 date;
declare variable V$D2 date;
declare variable V$T1 time;
declare variable V$T2 time;
declare variable N integer;
declare variable V$TEACHER_ID bigint;
declare variable V$GRADE_ID bigint;
declare variable V$SUBJECT_ID bigint;
declare variable V$YEAR_ID bigint;
declare variable V$WEEKDAY_NUM smallint;
declare variable V$LESSON_NUM smallint;
declare variable V$ROOM_ID bigint;
declare variable V$PERWEEK integer;
declare variable V$DIFF bigint;
declare variable V$PERDAY float;
declare variable V$DUR integer;
declare variable V$MG_ID bigint;
declare variable V$IS_STREAM_GROUP integer; /* является ли группа потоковой (английский, технология и т.д.) */
begin

  SELECT TYPE_ID
  FROM OBJECTS
  WHERE OBJ_ID = :I$OBJ_ID
  INTO :V$TYPE_ID;

  TAG_NAME = 'ou_type';
  VAL = (SELECT STATUS FROM OU_LICENCE_TYPE);
  SUSPEND;

  SELECT V37.LISTVAL_ID, LP2.PARENT_ID, V3080.VAL, V3081.VAL
  FROM LINKS LP3
  JOIN VALL V37 ON V37.OBJ_ID = LP3.PARENT_ID AND V37.PARAM_ID = 37 AND V37.IS_DEL = 0
  JOIN LINKS LP68 ON LP68.OBJ_ID = LP3.PARENT_ID AND LP68.PARENT_TYPE_ID = 68 AND LP68.DATE_DEL IS NULL
  JOIN LINKS LP2 ON LP2.OBJ_ID = LP68.PARENT_ID AND LP2.PARENT_TYPE_ID = 2 AND LP2.DATE_DEL IS NULL
  LEFT JOIN VALT V3080 ON V3080.OBJ_ID = LP3.PARENT_ID AND V3080.PARAM_ID = 3080 AND V3080.IS_DEL = 0
  LEFT JOIN VALT V3081 ON V3081.OBJ_ID = LP3.PARENT_ID AND V3081.PARAM_ID = 3081 AND V3081.IS_DEL = 0
  WHERE LP3.OBJ_ID = :I$OBJ_ID AND LP3.PARENT_TYPE_ID = 3 AND LP3.DATE_DEL IS NULL
  UNION
  SELECT V37.LISTVAL_ID, LP2.PARENT_ID, V3080.VAL, V3081.VAL
  FROM LINKS LP4
  JOIN LINKS LP3 ON LP3.OBJ_ID = LP4.PARENT_ID AND LP3.PARENT_TYPE_ID = 3 AND LP3.DATE_DEL IS NULL
  JOIN VALL V37 ON V37.OBJ_ID = LP3.PARENT_ID AND V37.PARAM_ID = 37 AND V37.IS_DEL = 0
  JOIN LINKS LP68 ON LP68.OBJ_ID = LP3.PARENT_ID AND LP68.PARENT_TYPE_ID = 68 AND LP68.DATE_DEL IS NULL
  JOIN LINKS LP2 ON LP2.OBJ_ID = LP68.PARENT_ID AND LP2.PARENT_TYPE_ID = 2 AND LP2.DATE_DEL IS NULL
  LEFT JOIN VALT V3080 ON V3080.OBJ_ID = LP3.PARENT_ID AND V3080.PARAM_ID = 3080 AND V3080.IS_DEL = 0
  LEFT JOIN VALT V3081 ON V3081.OBJ_ID = LP3.PARENT_ID AND V3081.PARAM_ID = 3081 AND V3081.IS_DEL = 0
  WHERE LP4.OBJ_ID = :I$OBJ_ID AND LP4.PARENT_TYPE_ID = 4 AND LP4.DATE_DEL IS NULL
  INTO :V$YEAR_ID, :V$OU_ID, :V$T1, :V$T2;

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;
  TAG_NAME = 'my_id';
  VAL = NULL;
  SELECT FIRST 1 U.OBJ_ID
  FROM USERS U
  WHERE U.USER_ID = CAST(:I$USER_ID AS BIGINT)
  INTO :VAL;
  SUSPEND;

  -- Справочник этапов
  TAG_NAME = 'grades::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
    SELECT LISTVAL_ID, VAL
    FROM OO_FILTRED_LIST(25)
    ORDER BY SORT_ORDER
    INTO :V$OBJ_ID, :S
  DO
  BEGIN
    TAG_NAME = 'grades:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'grades:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'grades:r:name';
    VAL = S;
    SUSPEND;
  END

  -- Для уровня региона выдаем глобальное расписание, для ОУ локальное
  IF(V$TYPE_ID = 112) THEN
  BEGIN

    -- Какой у нас текущий учебный год ?
    TAG_NAME = 'year';
    IF(EXTRACT(MONTH FROM CURRENT_DATE) < 9) THEN VAL = EXTRACT(YEAR FROM CURRENT_DATE) - 1; ELSE VAL = EXTRACT(YEAR FROM CURRENT_DATE);
    SUSPEND;

    -- Дата чтобы показывать кусок следующего года в пограничном режиме
    TAG_NAME = 'date';
    VAL = (SELECT VAL FROM DATE2ISO(CURRENT_DATE));
    SUSPEND;

    -- Уровень региона
    TAG_NAME = 'groups::json&colon;array';
    VAL = '1';
    SUSPEND;
    FOR
      SELECT L2.OBJ_ID, V2.VAL, V43.LISTVAL_ID, L9.OBJ_ID, C.CAPTION, V3071.VAL, V3072.VAL, PC.CAPTION
      FROM LINKS L2
      JOIN VALS V2 ON V2.OBJ_ID = L2.OBJ_ID AND V2.PARAM_ID = 2 AND V2.IS_DEL = 0
      JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
      JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
      JOIN VALL V43 ON V43.OBJ_ID = L7.OBJ_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
      JOIN VALL V3063 ON V3063.OBJ_ID = L9.OBJ_ID AND V3063.PARAM_ID = 3063 AND V3063.IS_DEL = 0 AND V3063.LISTVAL_ID = 2
      JOIN VALR V3075 ON V3075.OBJ_ID = L9.OBJ_ID AND V3075.PARAM_ID = 3075 AND V3075.IS_DEL = 0
      LEFT JOIN VALD V3071 ON V3071.OBJ_ID = L9.OBJ_ID AND V3071.PARAM_ID = 3071 AND V3071.IS_DEL = 0
      LEFT JOIN VALD V3072 ON V3072.OBJ_ID = L9.OBJ_ID AND V3072.PARAM_ID = 3072 AND V3072.IS_DEL = 0
      LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C ON 1 = 1
      LEFT JOIN OBJECT_CAPTION_GET(V3075.VAL) PC ON 1 = 1
      WHERE L2.PARENT_ID = :I$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      ORDER BY 2, 5, 6
      INTO :V$OU_ID, :S, :V$GRADE_ID, :V$OBJ_ID, :S1, :V$D1, :V$D2, :S2
    DO
    BEGIN
      TAG_NAME = 'groups:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'groups:r:ou_id';
      VAL = V$OU_ID;
      SUSPEND;
      TAG_NAME = 'groups:r:ou_name';
      VAL = S;
      SUSPEND;
      TAG_NAME = 'groups:r:grade_id';
      VAL = V$GRADE_ID;
      SUSPEND;
      TAG_NAME = 'groups:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'groups:r:name';
      VAL = S1;
      SUSPEND;
      TAG_NAME = 'groups:r:program_name';
      VAL = S2;
      SUSPEND;
      TAG_NAME = 'groups:r:date_start';
      VAL = (SELECT VAL FROM DATE2ISO(:V$D1, 0));
      SUSPEND;
      TAG_NAME = 'groups:r:date_end';
      VAL = (SELECT VAL FROM DATE2ISO(:V$D2, 0));
      SUSPEND;
    END

  END
  ELSE
  BEGIN

    -- Уровень ОУ
    -- Дни недели
    TAG_NAME = 'days::json&colon;array';
    VAL = '1';
    SUSPEND;
    FOR
      SELECT DISTINCT V402.LISTVAL_ID - 798, R.VAL, C.RESULT
      FROM LINKS L6
      JOIN VALL V402 ON V402.OBJ_ID = L6.OBJ_ID AND V402.PARAM_ID = 402 AND V402.IS_DEL = 0
      JOIN LISTVALS LV ON LV.LISTVAL_ID = V402.LISTVAL_ID
      JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
      LEFT JOIN VALD V42 ON V42.OBJ_ID = L6.OBJ_ID AND V42.PARAM_ID = 42 AND V42.IS_DEL = 0
      LEFT JOIN DATE2STR(V42.VAL) C ON 1 = 1
      WHERE L6.PARENT_ID = :I$OBJ_ID AND L6.OBJ_TYPE_ID = 6 AND L6.DATE_DEL IS NULL
      ORDER BY 1
      INTO :V$OBJ_ID, :S, :S2
    DO
    BEGIN
      TAG_NAME = 'days:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'days:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'days:r:name';
      VAL = S;
      IF(S2 IS NOT NULL) THEN VAL = VAL || ' ' || S2;
      SUSPEND;
    END

    TAG_NAME = 'time_start';
    VAL = COALESCE(V$T1, '08:00:00');
    SUSPEND;

    TAG_NAME = 'time_end';
    VAL = COALESCE(V$T2, '18:00:00');
    SUSPEND;

    -- Номера и время уроков - для фиксированной сетки
    TAG_NAME = 'lessons::json&colon;array';
    VAL = '1';
    SUSPEND;
    FOR
      SELECT DISTINCT V404.VAL, V405.VAL, V406.VAL
      FROM LINKS L60
      JOIN VALI V404 ON V404.OBJ_ID = L60.OBJ_ID AND V404.PARAM_ID = 404 AND V404.IS_DEL = 0
      LEFT JOIN VALT V405 ON V405.OBJ_ID = L60.OBJ_ID AND V405.PARAM_ID = 405 AND V405.IS_DEL = 0
      LEFT JOIN VALT V406 ON V406.OBJ_ID = L60.OBJ_ID AND V406.PARAM_ID = 406 AND V406.IS_DEL = 0
      WHERE L60.PARENT_ID = :I$OBJ_ID AND L60.OBJ_TYPE_ID = 60 AND L60.DATE_DEL IS NULL
      ORDER BY 1
      INTO :N, :V$T1, :V$T2
    DO
    BEGIN
      TAG_NAME = 'lessons:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'lessons:r:id';
      VAL = N;
      SUSPEND;
      TAG_NAME = 'lessons:r:t_from';
      VAL = V$T1;
      SUSPEND;
      TAG_NAME = 'lessons:r:t_to';
      VAL = V$T2;
      SUSPEND;
    END

    -- Список преподавателей, все про запас, и добавить сюда реальных из журналов
    TAG_NAME = 'teachers::json&colon;array';
    VAL = '1';
    SUSPEND;
    FOR
      SELECT L.TEACHER_ID, L.TEACHER_CAPTION, V3065.VAL
      FROM PARAGRAF_GRADE_TEACHERS_LIST(NULL) L
      LEFT JOIN VALS V3065 ON V3065.OBJ_ID = L.TEACHER_ID AND V3065.PARAM_ID = 3065 AND V3065.IS_DEL = 0
      UNION
      SELECT J.TEACHER_ID, C.CAPTION, V3065.VAL
      FROM CJ2_JOURNAL J
      LEFT JOIN OBJECT_CAPTION_GET(J.TEACHER_ID, NULL) C ON 1 = 1
      LEFT JOIN VALS V3065 ON V3065.OBJ_ID = J.TEACHER_ID AND V3065.PARAM_ID = 3065 AND V3065.IS_DEL = 0
      WHERE J.JOURNAL_TYPE IN (0, 1) AND J.DATE_DEL IS NULL AND J.TEACHER_ID IS NOT NULL
      ORDER BY 2
      INTO :V$OBJ_ID, :S, :S1
    DO
    BEGIN
      TAG_NAME = 'teachers:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'teachers:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'teachers:r:name';
      VAL = S;
      SUSPEND;
      TAG_NAME = 'teachers:r:mdays';
      VAL = S1;
      SUSPEND;
    END

    -- Список предметов - выбираем весь список, в том числе удаленные
    TAG_NAME = 'subjects::json&colon;array';
    VAL = '1';
    SUSPEND;
    FOR
      SELECT DISTINCT J.SUBJECT_ID, V3066.VAL, V3058.LISTVAL_ID, V3059.VAL, V377.VAL
      FROM CJ2_JOURNAL J
      LEFT JOIN VALS V3066 ON V3066.OBJ_ID = J.SUBJECT_ID AND V3066.PARAM_ID IN (3066, 3067) AND V3066.IS_DEL = 0
      LEFT JOIN VALL V3058 ON V3058.OBJ_ID = J.SUBJECT_ID AND V3058.PARAM_ID IN (3058) AND V3058.IS_DEL = 0
      LEFT JOIN VALF V3059 ON V3059.OBJ_ID = J.SUBJECT_ID AND V3059.PARAM_ID IN (3059) AND V3059.IS_DEL = 0
      LEFT JOIN VALS V377 ON V377.OBJ_ID = J.SUBJECT_ID AND V377.PARAM_ID IN (377, 1752) AND V377.IS_DEL = 0
      WHERE J.SUBJECT_ID IS NOT NULL AND J.YEAR_ID = :V$YEAR_ID
      INTO :V$OBJ_ID, :S, :V$DIFF, :V$PERDAY, :S1
    DO
    BEGIN
      TAG_NAME = 'subjects:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'subjects:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'subjects:r:name';
      VAL = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$OBJ_ID));
      SUSPEND;
      TAG_NAME = 'subjects:r:code';
      VAL = S1;
      SUSPEND;
      TAG_NAME = 'subjects:r:color';
      VAL = S;
      SUSPEND;
      TAG_NAME = 'subjects:r:difficulty';
      VAL = V$DIFF;
      SUSPEND;
      TAG_NAME = 'subjects:r:perday';
      VAL = CAST(V$PERDAY AS NUMERIC(18, 1));
      SUSPEND;
    END

    -- Список помещений - в данной ОУ
    TAG_NAME = 'buildings::json&colon;array';
    VAL = '1';
    SUSPEND;
    FOR
      SELECT L16.OBJ_ID, C.CAPTION
      FROM LINKS L73
      JOIN LINKS L16 ON L16.PARENT_ID = L73.OBJ_ID AND L16.OBJ_TYPE_ID = 16 AND L16.DATE_DEL IS NULL
      LEFT JOIN OBJECT_CAPTION_GET(L16.OBJ_ID) C ON 1 = 1
      WHERE L73.PARENT_ID = :V$OU_ID AND L73.OBJ_TYPE_ID = 73 AND L73.DATE_DEL IS NULL
      INTO :V$OBJ_ID, :S
    DO
    BEGIN
      TAG_NAME = 'buildings:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'buildings:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'buildings:r:name';
      VAL = S;
      SUSPEND;

      -- Помещения выбираем только учебно-лабораторные и вспомогательные
      TAG_NAME = 'buildings:r:rooms::json&colon;array';
      VAL = '1';
      SUSPEND;
      FOR
        SELECT L61.OBJ_ID, V407.VAL, V408.VAL, V1344.VAL
        FROM LINKS L61
        JOIN VALL V525 ON V525.OBJ_ID = L61.OBJ_ID AND V525.PARAM_ID = 525 AND V525.IS_DEL = 0 AND V525.LISTVAL_ID IN (23, 12764)
        LEFT JOIN VALR V1344 ON V1344.OBJ_ID = L61.OBJ_ID AND V1344.PARAM_ID = 1344 AND V1344.IS_DEL = 0
        -- Номер и название помещения
        LEFT JOIN VALS V407 ON V407.OBJ_ID = L61.OBJ_ID AND V407.PARAM_ID = 407 AND V407.IS_DEL = 0
        JOIN VALS V408 ON V408.OBJ_ID = L61.OBJ_ID AND V408.PARAM_ID = 408 AND V408.IS_DEL = 0
        WHERE L61.PARENT_ID = :V$OBJ_ID AND L61.OBJ_TYPE_ID = 61 AND L61.DATE_DEL IS NULL
        ORDER BY 2
        INTO :V$OBJ_ID2, :S, :S2, :V$TEACHER_ID
      DO
      BEGIN
        TAG_NAME = 'buildings:r:rooms:r';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'buildings:r:rooms:r:id';
        VAL = V$OBJ_ID2;
        SUSPEND;
        TAG_NAME = 'buildings:r:rooms:r:name';
        VAL = COALESCE(S, '');
        IF(VAL <> '') THEN VAL = VAL || ' - ';
        VAL = VAL || S2;
        SUSPEND;
        TAG_NAME = 'buildings:r:rooms:r:code';
        VAL = S;
        SUSPEND;
        TAG_NAME = 'buildings:r:rooms:r:shortname';
        VAL = S2;
        SUSPEND;
        TAG_NAME = 'buildings:r:rooms:r:teacher_id';
        VAL = V$TEACHER_ID;
        SUSPEND;
        -- Список предметов, закрепленных за помещением
        TAG_NAME = 'buildings:r:rooms:r:subjects::json&colon;array';
        VAL = 1;
        SUSPEND;
        FOR
          SELECT L51.OBJ_ID
          FROM LINKS L51
          WHERE L51.PARENT_ID = :V$OBJ_ID2 AND L51.OBJ_TYPE_ID IN (51, 197) AND L51.DATE_DEL IS NULL AND 0 = 1
          INTO :V$SUBJECT_ID
        DO
        BEGIN
          TAG_NAME = 'buildings:r:rooms:r:subjects:r';
          VAL = NULL;
          SUSPEND;
          TAG_NAME = 'buildings:r:rooms:r:subjects:r:id';
          VAL = V$SUBJECT_ID;
          SUSPEND;
        END
      END
    END

    -- Добавляем виртуальный id для помещений на стороне, id помещения будет равно id ОУ чтобы сохранялась связность
    TAG_NAME = 'buildings:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'buildings:r:id';
    VAL = '';
    SUSPEND;
    TAG_NAME = 'buildings:r:name';
    VAL = 'Вне ОООД';
    SUSPEND;
    TAG_NAME = 'buildings:r:rooms::json&colon;array';
    VAL = '1';
    SUSPEND;
    TAG_NAME = 'buildings:r:rooms:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'buildings:r:rooms:r:id';
    VAL = V$OU_ID;
    SUSPEND;
    TAG_NAME = 'buildings:r:rooms:r:name';
    VAL = 'Вне ОООД';
    SUSPEND;
    TAG_NAME = 'buildings:r:rooms:r:teacher_id';
    VAL = '';
    SUSPEND;
    TAG_NAME = 'buildings:r:rooms:r:subjects::json&colon;array';
    VAL = 1;
    SUSPEND;

    -- Список мастер-групп
    -- Крутые школы могут вообще иметь все группы динамическими, и тогда механизм с мастер-группами не будет работать как надо
    TAG_NAME = 'mgroups::json&colon;array';
    VAL = '1';
    SUSPEND;
    FOR
      SELECT DISTINCT LPG.EXT_OBJ_ID, C.CAPTION, LV.LISTVAL_ID
      FROM CJ2_JOURNAL J
      JOIN LISTVALS LV ON LV.LISTVAL_ID = J.STAGE_INDEX
      JOIN LINKS LPG ON LPG.OBJ_ID = J.GRADE_ID AND LPG.PARENT_TYPE_ID = 2 AND LPG.DATE_DEL IS NULL AND LPG.EXT_OBJ_ID IS NOT NULL
      LEFT JOIN OBJECT_CAPTION_GET(LPG.EXT_OBJ_ID) C ON 1 = 1
      WHERE J.DATE_DEL IS NULL AND J.YEAR_ID = :V$YEAR_ID
      ORDER BY LV.COST, 2
      INTO :V$OBJ_ID, :S, :V$DIFF
    DO
    BEGIN
      TAG_NAME = 'mgroups:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'mgroups:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'mgroups:r:name';
      VAL = S;
      SUSPEND;
      TAG_NAME = 'mgroups:r:stage_id';
      VAL = V$DIFF;
      SUSPEND;
    END

    -- Список всех журналов с названиями предметов
    TAG_NAME = 'journals::json&colon;array';
    VAL = '1';
    SUSPEND;
    FOR
      SELECT J.OBJ_ID, J.JOURNAL_TYPE, J.TEACHER_ID, J.GRADE_ID, J.SUBJECT_ID, J.JOURNAL_NAME, C.CAPTION,
        IIF(J.WEEKS > 0, ROUND(J.HOURS / J.WEEKS), NULL), J.DURATION, COALESCE(LPG.EXT_OBJ_ID, V3370.VAL), J.STAGE_INDEX, J.ROOM_ID,
        COALESCE((SELECT FIRST 1 PS.IS_STM FROM PLAN_SUBJECTS PS WHERE PS.DATE_DEL IS NULL AND PS.PLAN_ID = J.REF_ID AND PS.SUBJECT_ID = J.SUBJECT_ID), 1) IS_STM
      FROM CJ2_JOURNAL J
      LEFT JOIN LISTVALS LV ON LV.LISTVAL_ID = J.STAGE_INDEX
      LEFT JOIN OBJECT_CAPTION_GET(J.GRADE_ID) C ON 1 = 1
      LEFT JOIN LINKS LPG ON LPG.OBJ_ID = J.GRADE_ID AND LPG.PARENT_TYPE_ID = 2 AND LPG.DATE_DEL IS NULL
      LEFT JOIN VALR V3370 ON V3370.OBJ_ID = J.GRADE_ID AND V3370.PARAM_ID = 3370 AND V3370.IS_DEL = 0
      WHERE J.DATE_DEL IS NULL AND J.YEAR_ID = :V$YEAR_ID
      ORDER BY 10, 2, LV.COST, 6
      INTO :V$OBJ_ID, :N, :V$TEACHER_ID, :V$GRADE_ID, :V$SUBJECT_ID, :S, :S1, :V$PERWEEK, :V$DUR, :V$MG_ID, :V$DIFF, :V$ROOM_ID,
        :V$IS_STREAM_GROUP
    DO
    BEGIN
      TAG_NAME = 'journals:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'journals:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'journals:r:type';
      VAL = N;
      SUSPEND;
      TAG_NAME = 'journals:r:teacher_id';
      VAL = V$TEACHER_ID;
      SUSPEND;
      -- ссылка на мастер-группу
      -- мастер-группа - это ГУП, из которого были сформированы группы по предмету
      -- все что mg_id null это потоковые группы
      -- также выдаем mg_id со ссылкой на ГУП те потоковые группы, в которых числятся ученики только одного ГУП
      TAG_NAME = 'journals:r:mg_id';
      VAL = V$MG_ID;
      SUSPEND;
      TAG_NAME = 'journals:r:grade_id';
      VAL = V$GRADE_ID;
      SUSPEND;
      TAG_NAME = 'journals:r:grade_name';
      VAL = S1;
      SUSPEND;
      TAG_NAME = 'journals:r:stage_id';
      VAL = V$DIFF;
      SUSPEND;
      TAG_NAME = 'journals:r:subject_id';
      VAL = V$SUBJECT_ID;
      SUSPEND;
      TAG_NAME = 'journals:r:name';
      VAL = S;
      SUSPEND;
      TAG_NAME = 'journals:r:perweek';
      VAL = V$PERWEEK;
      SUSPEND;
      TAG_NAME = 'journals:r:dur';
      VAL = V$DUR;
      SUSPEND;
      -- Ресурсы
      TAG_NAME = 'journals:r:resources';
      VAL = NULL;
      SUSPEND;
      -- Помещение по-умолчанию
      TAG_NAME = 'journals:r:room_id';
      VAL = V$ROOM_ID;
      SUSPEND;
      -- флаг потоковости группы
      TAG_NAME = 'journals:r:is_stream_group';
      VAL = V$IS_STREAM_GROUP;
      SUSPEND;
    END

    -- Список назначений
    TAG_NAME = 'schedule::json&colon;array';
    VAL = '1';
    SUSPEND;
    FOR
      SELECT I.OBJ_ID, I.WEEKDAY_NUM, I.LESSON_NUM, I.CJ_ID, I.ROOM_ID, I.DURATION, I.EXT_INFO
      FROM SCHEDULE_ITEMS I
      WHERE I.DATE_DEL IS NULL AND I.SCHEDULE_ID = :I$OBJ_ID
      INTO :V$OBJ_ID, :V$WEEKDAY_NUM, :V$LESSON_NUM, :V$OBJ_ID2, :V$ROOM_ID, :V$DUR, :S
    DO
    BEGIN
      TAG_NAME = 'schedule:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'schedule:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'schedule:r:day';
      VAL = V$WEEKDAY_NUM;
      SUSPEND;
      -- Нумерация lesson: 1..99 - номер урока по расписанию, >= 60 - метка времени в минутах с начала суток
      TAG_NAME = 'schedule:r:lesson';
      VAL = V$LESSON_NUM;
      SUSPEND;
      TAG_NAME = 'schedule:r:cj';
      VAL = V$OBJ_ID2;
      SUSPEND;
      TAG_NAME = 'schedule:r:room';
      VAL = V$ROOM_ID;
      SUSPEND;
      TAG_NAME = 'schedule:r:duration';
      VAL = V$DUR;
      SUSPEND;
      TAG_NAME = 'schedule:r:ext_info';
      VAL = S;
      SUSPEND;
    END

  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SCHEDULE_GRADE_LIST (
    I$SCHEDULE_TEMPLATE_ID BIGINT,
    I$TEACHER_ID BIGINT,
    I$SUBJECT_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    GRADE_LOADING_ID BIGINT,
    SUBJECT_ID BIGINT,
    TEACHER_ID BIGINT,
    CLASS_CAPTION VARCHAR(1000),
    CLASS_ORDER DOUBLE PRECISION,
    STAGE_LOADING_PERIOD INTEGER,
    LOADING_HOURS DOUBLE PRECISION,
    LOADING_COUNT INTEGER,
    GRADE_LOADING_COUNT INTEGER)
AS
declare variable OBJ_ID bigint;
declare variable CLASS_ID bigint;
declare variable SUBGROUP_ID bigint;
declare variable STAGE_ID bigint;
declare variable PARENT_SUBJECT_ID bigint;
BEGIN
    SELECT FIRST 1 OBJ_ID
    FROM OBJECT_PARENTS_GET(:I$SCHEDULE_TEMPLATE_ID, 3)
    INTO :OBJ_ID;

    FOR
        /* ГУП */
        SELECT L58.OBJ_ID, L256.OBJ_ID, L54.OBJ_ID, L14.PARENT_ID, L51.PARENT_ID, L51_.PARENT_ID, NULL
        FROM LINKS L57
        JOIN LINKS L50 ON L50.PARENT_ID = L57.OBJ_ID AND L50.OBJ_TYPE_ID = 50 AND L50.DATE_DEL IS NULL
        JOIN LINKS L54 ON L54.PARENT_ID = L50.OBJ_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
        JOIN LINKS L256 ON L256.PARENT_ID = L54.OBJ_ID AND L256.OBJ_TYPE_ID = 256 AND L256.DATE_DEL IS NULL
        JOIN LINKS L56 ON L56.PARENT_ID = L54.OBJ_ID AND L56.OBJ_TYPE_ID = 56 AND L56.DATE_DEL IS NULL
        JOIN LINKS L58 ON L58.PARENT_ID = L56.OBJ_ID AND L58.OBJ_TYPE_ID = 58 AND L58.DATE_DEL IS NULL
        JOIN LINKS L58_ ON L58_.PARENT_ID = L256.OBJ_ID AND L58_.OBJ_ID = L58.OBJ_ID AND L58_.OBJ_TYPE_ID = 58 AND L58_.DATE_DEL IS NULL
        JOIN LINKS L14 ON L14.OBJ_ID = L58.OBJ_ID AND L14.PARENT_TYPE_ID = 14 AND L14.DATE_DEL IS NULL AND ((:I$TEACHER_ID IS NULL) OR (L14.PARENT_ID = :I$TEACHER_ID))
        JOIN LINKS L51 ON L51.OBJ_ID = L58.OBJ_ID AND L51.PARENT_TYPE_ID = 51 AND L51.DATE_DEL IS NULL AND ((:I$SUBJECT_ID IS NULL) OR (L51.PARENT_ID = :I$SUBJECT_ID))
        JOIN LINKS L51_ ON L51_.OBJ_ID = L56.OBJ_ID AND L51_.PARENT_TYPE_ID = 51 AND L51_.DATE_DEL IS NULL
        WHERE L57.PARENT_ID = :OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL

        UNION

        /* Подгруппы */

        SELECT L58.OBJ_ID, L256.OBJ_ID, L54.OBJ_ID, L14.PARENT_ID, L51.PARENT_ID, L51_.PARENT_ID, L48.OBJ_ID
        FROM LINKS L57
        JOIN LINKS L50 ON L50.PARENT_ID = L57.OBJ_ID AND L50.OBJ_TYPE_ID = 50 AND L50.DATE_DEL IS NULL
        JOIN LINKS L54 ON L54.PARENT_ID = L50.OBJ_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
        JOIN LINKS L256 ON L256.PARENT_ID = L54.OBJ_ID AND L256.OBJ_TYPE_ID = 256 AND L256.DATE_DEL IS NULL
        JOIN LINKS L47 ON L47.PARENT_ID = L256.OBJ_ID AND L47.OBJ_TYPE_ID = 47 AND L47.DATE_DEL IS NULL
        JOIN LINKS L48 ON L48.PARENT_ID = L47.OBJ_ID AND L48.OBJ_TYPE_ID = 48 AND L48.DATE_DEL IS NULL
        JOIN LINKS L58 ON L58.PARENT_ID = L48.OBJ_ID AND L58.OBJ_TYPE_ID = 58 AND L58.DATE_DEL IS NULL
        JOIN LINKS LP56 ON LP56.OBJ_ID = L58.OBJ_ID AND LP56.PARENT_TYPE_ID = 56 AND LP56.DATE_DEL IS NULL
        JOIN LINKS L56 ON L56.PARENT_ID = L54.OBJ_ID AND L56.OBJ_ID = LP56.PARENT_ID AND L56.DATE_DEL IS NULL
        JOIN LINKS L14 ON L14.OBJ_ID = L58.OBJ_ID AND L14.PARENT_TYPE_ID = 14 AND L14.DATE_DEL IS NULL AND ((:I$TEACHER_ID IS NULL) OR (L14.PARENT_ID = :I$TEACHER_ID))
        JOIN LINKS L51 ON L51.OBJ_ID = L58.OBJ_ID AND L51.PARENT_TYPE_ID = 51 AND L51.DATE_DEL IS NULL AND ((:I$SUBJECT_ID IS NULL) OR (L51.PARENT_ID = :I$SUBJECT_ID))
        JOIN LINKS L51_ ON L51_.OBJ_ID = L56.OBJ_ID AND L51_.PARENT_TYPE_ID = 51 AND L51_.DATE_DEL IS NULL

        /* Проверка принадлежности предмета к делению по подгрупам */
        LEFT JOIN VALR V428 ON V428.OBJ_ID = L47.OBJ_ID AND V428.PARAM_ID = 428 AND V428.IS_DEL = 0
        LEFT JOIN LINKS L48_51 ON L48_51.PARENT_ID = L48.OBJ_ID AND L48_51.OBJ_ID = L51.PARENT_ID AND L48_51.DATE_DEL IS NULL
        WHERE L57.PARENT_ID = :OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL AND ((V428.VAL = L51.PARENT_ID) OR (L48_51.OBJ_ID = L51.PARENT_ID))

        UNION

        /* Потоки */

        SELECT L58.OBJ_ID, L347.OBJ_ID, L54.OBJ_ID, L14.PARENT_ID, L51.PARENT_ID, L51_.PARENT_ID, NULL
        FROM LINKS L57
        JOIN LINKS L50 ON L50.PARENT_ID = L57.OBJ_ID AND L50.OBJ_TYPE_ID = 50 AND L50.DATE_DEL IS NULL
        JOIN LINKS L54 ON L54.PARENT_ID = L50.OBJ_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
        JOIN LINKS L346 ON L346.PARENT_ID = L54.OBJ_ID AND L346.OBJ_TYPE_ID = 346 AND L346.DATE_DEL IS NULL
        JOIN LINKS L347 ON L347.PARENT_ID = L346.OBJ_ID AND L347.OBJ_TYPE_ID = 347 AND L347.DATE_DEL IS NULL
        JOIN LINKS L58 ON L58.PARENT_ID = L347.OBJ_ID AND L58.OBJ_TYPE_ID = 58 AND L58.DATE_DEL IS NULL
        JOIN LINKS LP56 ON LP56.OBJ_ID = L58.OBJ_ID AND LP56.PARENT_TYPE_ID = 56 AND LP56.DATE_DEL IS NULL
        JOIN LINKS L56 ON L56.PARENT_ID = L54.OBJ_ID AND L56.OBJ_ID = LP56.PARENT_ID AND L56.DATE_DEL IS NULL
        JOIN LINKS L14 ON L14.OBJ_ID = L58.OBJ_ID AND L14.PARENT_TYPE_ID = 14 AND L14.DATE_DEL IS NULL AND ((:I$TEACHER_ID IS NULL) OR (L14.PARENT_ID = :I$TEACHER_ID))
        JOIN LINKS L51 ON L51.OBJ_ID = L58.OBJ_ID AND L51.PARENT_TYPE_ID = 51 AND L51.DATE_DEL IS NULL AND ((:I$SUBJECT_ID IS NULL) OR (L51.PARENT_ID = :I$SUBJECT_ID))
        JOIN LINKS L51_ ON L51_.OBJ_ID = L56.OBJ_ID AND L51_.PARENT_TYPE_ID = 51 AND L51_.DATE_DEL IS NULL
        /* Проверка принадлежности предмета к потоку */
        LEFT JOIN VALR V2705 ON V2705.OBJ_ID = L346.OBJ_ID AND V2705.PARAM_ID = 2705 AND V2705.IS_DEL = 0
        WHERE L57.PARENT_ID = :OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL AND (V2705.VAL = L51.PARENT_ID)

        INTO :GRADE_LOADING_ID, :CLASS_ID, :STAGE_ID, :TEACHER_ID, :SUBJECT_ID, :PARENT_SUBJECT_ID, :SUBGROUP_ID
    DO
    BEGIN
        SELECT CAPTION, SORT_ORDER
        FROM OBJECT_CAPTION_GET(:CLASS_ID,NULL,NULL,:I$USER_ID)
        INTO :CLASS_CAPTION, :CLASS_ORDER;

        IF (SUBGROUP_ID IS NOT NULL) THEN
        BEGIN
            SELECT :CLASS_CAPTION || ' (' || CAPTION || ')'
            FROM OBJECT_CAPTION_GET(:SUBGROUP_ID,NULL,NULL,:I$USER_ID)
            INTO :CLASS_CAPTION;
        END

        STAGE_LOADING_PERIOD = 0;
        LOADING_HOURS = 0;
        LOADING_COUNT = 0;
        GRADE_LOADING_COUNT = 0;

        SELECT I FROM VAL_GET(:STAGE_ID, 382, 0, :I$USER_ID) INTO :STAGE_LOADING_PERIOD;

        SELECT SUM(V.VAL)
        FROM LINKS L51
        JOIN LINKS L54 ON L54.OBJ_ID = L51.OBJ_ID AND L54.PARENT_ID = :STAGE_ID AND L54.OBJ_TYPE_ID = 56 AND L54.DATE_DEL IS NULL
        JOIN LINKS L49 ON L49.OBJ_ID = L54.OBJ_ID AND L49.PARENT_TYPE_ID = 49 AND L49.DATE_DEL IS NULL
        JOIN LINKS L49_ ON L49_.PARENT_ID = L49.PARENT_ID AND L49_.OBJ_ID = L51.PARENT_ID AND L49_.DATE_DEL IS NULL
        JOIN VALI V ON V.OBJ_ID = L54.OBJ_ID AND V.PARAM_ID = 385 AND V.IS_DEL = 0 AND V.VAL > 0
        WHERE L51.PARENT_ID = :PARENT_SUBJECT_ID AND L51.OBJ_TYPE_ID = 56 AND L51.DATE_DEL IS NULL
        INTO :LOADING_HOURS;

        IF (LOADING_HOURS IS NULL) THEN LOADING_HOURS = 0;
        IF (STAGE_LOADING_PERIOD > 0) THEN LOADING_COUNT = LOADING_HOURS / STAGE_LOADING_PERIOD;

        SELECT COUNT(*)
        FROM LINKS L70
        JOIN LINKS L58 ON L58.OBJ_ID = L70.OBJ_ID AND L58.PARENT_ID = :GRADE_LOADING_ID AND L58.DATE_DEL IS NULL
        JOIN LINKS L14 ON L14.OBJ_ID = L70.OBJ_ID AND L14.PARENT_ID = :TEACHER_ID AND L14.DATE_DEL IS NULL
        WHERE L70.PARENT_ID = :I$SCHEDULE_TEMPLATE_ID AND L70.OBJ_TYPE_ID = 70 AND L70.DATE_DEL IS NULL
        INTO :GRADE_LOADING_COUNT;

        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SCHEDULE_HOURS_LIST (
    I$SCHEDULE_TEMPLATE_ID BIGINT,
    I$USER_ID BIGINT = null)
RETURNS (
    HOUR_ID BIGINT,
    HOUR_NUMBER INTEGER,
    HOUR_START TIME,
    HOUR_END TIME)
AS
BEGIN
    FOR SELECT L60.OBJ_ID
        FROM LINKS L60
        WHERE L60.PARENT_ID = :I$SCHEDULE_TEMPLATE_ID
          AND L60.OBJ_TYPE_ID = 60
          AND L60.DATE_DEL IS NULL
        INTO :HOUR_ID
    DO
    BEGIN
        SELECT I
        FROM VAL_GET(:HOUR_ID, 404, 0, :I$USER_ID)
        INTO :HOUR_NUMBER;

        SELECT T
        FROM VAL_GET(:HOUR_ID, 405, 0, :I$USER_ID)
        INTO :HOUR_START;

        SELECT T
        FROM VAL_GET(:HOUR_ID, 406, 0, :I$USER_ID)
        INTO :HOUR_END;

        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SCHEDULE_LIST (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    OBJ_ID BIGINT,
    CAPTION VARCHAR(1000))
AS
declare variable V$OBJ_ID bigint;
declare variable S varchar(1000);
begin

  SELECT FIRST 1 OBJ_ID
  FROM OBJECT_PARENTS_GET(:I$OBJ_ID, 3)
  INTO :I$OBJ_ID;

  FOR
    SELECT L59.OBJ_ID, C.CAPTION
    FROM LINKS L59
    LEFT JOIN OBJECT_CAPTION_GET(L59.OBJ_ID) C ON 1 = 1
    WHERE L59.PARENT_ID = :I$OBJ_ID AND L59.OBJ_TYPE_ID = 59 AND L59.DATE_DEL IS NULL
    ORDER BY 2
    INTO :OBJ_ID, :CAPTION
  DO
  BEGIN
    SUSPEND;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SCHEDULE_REPORT_ALL_CLASSES (
    I$SCHEDULE_TEMPLATE_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    COL_NUM SMALLINT,
    VAL VARCHAR(4000),
    DATA VARCHAR(4000),
    ORIENTATION VARCHAR(20))
AS
declare variable DAY_ID bigint;
declare variable DAY_CAPTION varchar(20);
declare variable DAY_DATE date;
declare variable HOUR_ID bigint;
declare variable HOUR_NUM integer;
declare variable CLASS_ID bigint;
declare variable CLASS_CAPTION varchar(1000);
declare variable SUBJECT_CAPTION varchar(1000);
declare variable TEMP_CLASS_ID bigint;
declare variable TEMP_TYPE_ID bigint;
BEGIN
    TEMP_CLASS_ID = 0;

    SELECT TYPE_ID
    FROM OBJECTS O
    WHERE O.OBJ_ID = :I$SCHEDULE_TEMPLATE_ID
    INTO :TEMP_TYPE_ID;

    /* CAPTION */

    COL_NUM = 1;
    VAL = 'Учебный коллектив';
    DATA = NULL;
    ORIENTATION = 'MIXED';
    SUSPEND;

    FOR SELECT DAY_DATE, DAY_CAPTION
        FROM SCHEDULE_DAYS_LIST(:I$SCHEDULE_TEMPLATE_ID, :I$USER_ID)
        ORDER BY DAY_DATE, DAY_ORDER
        INTO :DAY_DATE, :DAY_CAPTION
    DO
    BEGIN
        COL_NUM = COL_NUM + 1;
        VAL = DAY_CAPTION;
        DATA = NULL;
        IF ((TEMP_TYPE_ID = 63) AND (DAY_DATE IS NOT NULL)) THEN
        BEGIN
            VAL = 'EXTRACTDAYOFWEEKDAYMONTHNAME';
            DATA = DAY_DATE;
        END
        SUSPEND;
    END

    /* BODY */

    FOR SELECT CLASS_ID, CLASS_CAPTION
        FROM SCHEDULE_CLASSES_LIST(:I$SCHEDULE_TEMPLATE_ID)
        ORDER BY SORT_ORDER, CLASS_CAPTION
        INTO :CLASS_ID, :CLASS_CAPTION
    DO
    BEGIN
        FOR SELECT HOUR_ID, HOUR_NUMBER
            FROM SCHEDULE_HOURS_LIST(:I$SCHEDULE_TEMPLATE_ID)
            ORDER BY HOUR_NUMBER
            INTO :HOUR_ID, :HOUR_NUM
        DO
        BEGIN
            /* FIRST COLUMN */
            COL_NUM = 1;
            DATA = NULL;
            VAL = NULL;
            IF (TEMP_CLASS_ID <> CLASS_ID) THEN
            BEGIN
                VAL = CLASS_CAPTION;
                TEMP_CLASS_ID = CLASS_ID;
            END
            SUSPEND;

            /* DAYS COLUMNS */
            FOR SELECT DAY_ID
                FROM SCHEDULE_DAYS_LIST(:I$SCHEDULE_TEMPLATE_ID, :I$USER_ID)
                ORDER BY DAY_ORDER
                INTO :DAY_ID
            DO
            BEGIN
                COL_NUM = COL_NUM + 1;
                DATA = NULL;
                VAL = '';

                FOR SELECT V376.VAL
                    FROM LINKS L70
                    INNER JOIN LINKS L6 ON L6.OBJ_ID = L70.OBJ_ID
                    INNER JOIN LINKS L60 ON L60.OBJ_ID = L70.OBJ_ID
                    INNER JOIN LINKS L58 ON L58.OBJ_ID = L70.OBJ_ID
                    INNER JOIN LINKS L9 ON L9.OBJ_ID = L58.PARENT_ID
                    INNER JOIN LINKS L51 ON L51.OBJ_ID = L58.PARENT_ID
                    INNER JOIN VALS V376 ON V376.OBJ_ID = L51.PARENT_ID
                    WHERE L70.PARENT_ID = :I$SCHEDULE_TEMPLATE_ID
                      AND L70.OBJ_TYPE_ID = 70
                      AND L70.DATE_DEL IS NULL
                      AND L6.PARENT_ID = :DAY_ID
                      AND L6.DATE_DEL IS NULL
                      AND L60.PARENT_ID = :HOUR_ID
                      AND L60.DATE_DEL IS NULL
                      AND L58.PARENT_TYPE_ID = 58
                      AND L58.DATE_DEL IS NULL
                      AND L9.PARENT_ID = :CLASS_ID
                      AND L9.DATE_DEL IS NULL
                      AND L51.PARENT_TYPE_ID = 51
                      AND L51.DATE_DEL IS NULL
                      AND V376.PARAM_ID = 376
                      AND V376.IS_DEL = 0

                    UNION

                    SELECT V376.VAL
                    FROM LINKS L70
                    INNER JOIN LINKS L6 ON L6.OBJ_ID = L70.OBJ_ID
                    INNER JOIN LINKS L60 ON L60.OBJ_ID = L70.OBJ_ID
                    INNER JOIN LINKS L58 ON L58.OBJ_ID = L70.OBJ_ID
                    INNER JOIN LINKS L48 ON L48.OBJ_ID = L58.PARENT_ID
                    INNER JOIN LINKS L47 ON L47.OBJ_ID = L48.PARENT_ID
                    INNER JOIN LINKS L9 ON L9.OBJ_ID = L47.PARENT_ID
                    INNER JOIN LINKS L51 ON L51.OBJ_ID = L58.PARENT_ID
                    INNER JOIN VALS V376 ON V376.OBJ_ID = L51.PARENT_ID
                    WHERE L70.PARENT_ID = :I$SCHEDULE_TEMPLATE_ID
                      AND L70.OBJ_TYPE_ID = 70
                      AND L70.DATE_DEL IS NULL
                      AND L6.PARENT_ID = :DAY_ID
                      AND L6.DATE_DEL IS NULL
                      AND L60.PARENT_ID = :HOUR_ID
                      AND L60.DATE_DEL IS NULL
                      AND L58.PARENT_TYPE_ID = 58
                      AND L58.DATE_DEL IS NULL
                      AND L48.PARENT_TYPE_ID = 48
                      AND L48.DATE_DEL IS NULL
                      AND L47.PARENT_TYPE_ID = 47
                      AND L47.DATE_DEL IS NULL
                      AND L9.PARENT_ID = :CLASS_ID
                      AND L9.DATE_DEL IS NULL
                      AND L51.PARENT_TYPE_ID = 51
                      AND L51.DATE_DEL IS NULL
                      AND V376.PARAM_ID = 376
                      AND V376.IS_DEL = 0

                    INTO :SUBJECT_CAPTION
                DO
                BEGIN
                    IF (VAL = '') THEN
                    BEGIN
                        VAL = HOUR_NUM || '. ' || SUBJECT_CAPTION;
                    END
                    ELSE
                    BEGIN
                        VAL = VAL || ASCII_CHAR(10) || HOUR_NUM || '. ' || SUBJECT_CAPTION;
                    END
                END

                SUSPEND;
            END
        END

        /* FINAL ROW: */

        /* FIRST COLUMN */
        COL_NUM = 1;
        DATA = NULL;
        VAL = NULL;
        SUSPEND;

        /* DAYS COLUMNS */
        FOR SELECT DAY_ID
            FROM SCHEDULE_DAYS_LIST(:I$SCHEDULE_TEMPLATE_ID, :I$USER_ID)
            ORDER BY DAY_ORDER
            INTO :DAY_ID
        DO
        BEGIN
            COL_NUM = COL_NUM + 1;
            DATA = NULL;
            VAL = NULL;
            SUSPEND;
        END
    END  
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SCHEDULE_REPORT_ALL_ROOMS (
    I$SCHEDULE_TEMPLATE_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    COL_NUM SMALLINT,
    VAL VARCHAR(4000),
    DATA VARCHAR(4000),
    ORIENTATION VARCHAR(20))
AS
declare variable DAY_ID bigint;
declare variable DAY_CAPTION varchar(20);
declare variable DAY_DATE date;
declare variable HOUR_ID bigint;
declare variable HOUR_NUM integer;
declare variable ROOM_ID bigint;
declare variable ROOM_CAPTION varchar(1000);
declare variable CLASS_ID bigint;
declare variable CLASS_CAPTION varchar(1000);
declare variable SUBGROUP_ID bigint;
declare variable TEMP_ROOM_ID bigint;
declare variable TEMP_TYPE_ID bigint;
BEGIN
    TEMP_ROOM_ID = 0;

    SELECT TYPE_ID
    FROM OBJECTS O
    WHERE O.OBJ_ID = :I$SCHEDULE_TEMPLATE_ID
    INTO :TEMP_TYPE_ID;

    /* CAPTION */

    COL_NUM = 1;
    VAL = 'Кабинет';
    DATA = NULL;
    ORIENTATION = 'MIXED';
    SUSPEND;
    COL_NUM = 2;
    VAL = 'Урок';
    SUSPEND;


    FOR SELECT DAY_DATE, DAY_CAPTION
        FROM SCHEDULE_DAYS_LIST(:I$SCHEDULE_TEMPLATE_ID, :I$USER_ID)
        ORDER BY DAY_DATE, DAY_ORDER
        INTO :DAY_DATE, :DAY_CAPTION
    DO
    BEGIN
        COL_NUM = COL_NUM + 1;
        VAL = DAY_CAPTION;
        DATA = NULL;
        IF ((TEMP_TYPE_ID = 63) AND (DAY_DATE IS NOT NULL)) THEN
        BEGIN
            VAL = 'EXTRACTDAYOFWEEKDAYMONTHNAME';
            DATA = DAY_DATE;
        END
        SUSPEND;
    END

    /* BODY */

    FOR SELECT ROOM_ID, ROOM_CAPTION
        FROM SCHEDULE_ROOMS_LIST(:I$SCHEDULE_TEMPLATE_ID)
        ORDER BY ROOM_NUMBER, ROOM_CAPTION
        INTO :ROOM_ID, :ROOM_CAPTION
    DO
    BEGIN
        FOR SELECT HOUR_ID, HOUR_NUMBER
            FROM SCHEDULE_HOURS_LIST(:I$SCHEDULE_TEMPLATE_ID)
            ORDER BY HOUR_NUMBER
            INTO :HOUR_ID, :HOUR_NUM
        DO
        BEGIN
            /* FIRST COLUMN */
            COL_NUM = 1;
            DATA = NULL;
            VAL = NULL;
            IF (TEMP_ROOM_ID <> ROOM_ID) THEN
            BEGIN
                VAL = ROOM_CAPTION;
                TEMP_ROOM_ID = ROOM_ID;
            END
            SUSPEND;
            COL_NUM = 2;
            VAL = HOUR_NUM;
            SUSPEND;

            /* DAYS COLUMNS */
            FOR SELECT DAY_ID
                FROM SCHEDULE_DAYS_LIST(:I$SCHEDULE_TEMPLATE_ID, :I$USER_ID)
                ORDER BY DAY_ORDER
                INTO :DAY_ID
            DO
            BEGIN
                COL_NUM = COL_NUM + 1;
                DATA = NULL;
                VAL = '';

                FOR SELECT L9.PARENT_ID, NULL
                    FROM LINKS L70
                    INNER JOIN LINKS L6 ON L6.OBJ_ID = L70.OBJ_ID
                    INNER JOIN LINKS L60 ON L60.OBJ_ID = L70.OBJ_ID
                    INNER JOIN LINKS L58 ON L58.OBJ_ID = L70.OBJ_ID
                    INNER JOIN LINKS L61 ON L61.OBJ_ID = L70.OBJ_ID
                    INNER JOIN LINKS L9 ON L9.OBJ_ID = L58.PARENT_ID
                    WHERE L70.PARENT_ID = :I$SCHEDULE_TEMPLATE_ID
                      AND L70.OBJ_TYPE_ID = 70
                      AND L70.DATE_DEL IS NULL
                      AND L6.PARENT_ID = :DAY_ID
                      AND L6.DATE_DEL IS NULL
                      AND L60.PARENT_ID = :HOUR_ID
                      AND L60.DATE_DEL IS NULL
                      AND L58.PARENT_TYPE_ID = 58
                      AND L58.DATE_DEL IS NULL
                      AND L9.PARENT_TYPE_ID = 9
                      AND L9.DATE_DEL IS NULL
                      AND L61.PARENT_ID = :ROOM_ID
                      AND L61.DATE_DEL IS NULL

                    UNION

                    SELECT L9.PARENT_ID, L48.PARENT_ID
                    FROM LINKS L70
                    INNER JOIN LINKS L6 ON L6.OBJ_ID = L70.OBJ_ID
                    INNER JOIN LINKS L60 ON L60.OBJ_ID = L70.OBJ_ID
                    INNER JOIN LINKS L58 ON L58.OBJ_ID = L70.OBJ_ID
                    INNER JOIN LINKS L61 ON L61.OBJ_ID = L70.OBJ_ID
                    INNER JOIN LINKS L48 ON L48.OBJ_ID = L58.PARENT_ID
                    INNER JOIN LINKS L47 ON L47.OBJ_ID = L48.PARENT_ID
                    INNER JOIN LINKS L9 ON L9.OBJ_ID = L47.PARENT_ID
                    WHERE L70.PARENT_ID = :I$SCHEDULE_TEMPLATE_ID
                      AND L70.OBJ_TYPE_ID = 70
                      AND L70.DATE_DEL IS NULL
                      AND L6.PARENT_ID = :DAY_ID
                      AND L6.DATE_DEL IS NULL
                      AND L60.PARENT_ID = :HOUR_ID
                      AND L60.DATE_DEL IS NULL
                      AND L58.PARENT_TYPE_ID = 58
                      AND L58.DATE_DEL IS NULL
                      AND L48.PARENT_TYPE_ID = 48
                      AND L48.DATE_DEL IS NULL
                      AND L47.PARENT_TYPE_ID = 47
                      AND L47.DATE_DEL IS NULL
                      AND L9.PARENT_TYPE_ID = 9
                      AND L9.DATE_DEL IS NULL
                      AND L61.PARENT_ID = :ROOM_ID
                      AND L61.DATE_DEL IS NULL

                    INTO :CLASS_ID, :SUBGROUP_ID
                DO
                BEGIN
                    SELECT CAPTION
                    FROM OBJECT_CAPTION_GET(:CLASS_ID,NULL,NULL,:I$USER_ID)
                    INTO :CLASS_CAPTION;

                    IF (SUBGROUP_ID IS NOT NULL) THEN
                    BEGIN
                        CLASS_CAPTION = '[' || CLASS_CAPTION || ']';
                    END

                    IF (VAL = '') THEN
                    BEGIN
                        VAL = CLASS_CAPTION;
                    END
                    ELSE
                    BEGIN
                        VAL = VAL || ';  ' || CLASS_CAPTION;
                    END
                END

                SUSPEND;
            END
        END

        /* FINAL ROW: */

        /* FIRST COLUMN */
        COL_NUM = 1;
        DATA = NULL;
        VAL = NULL;
        SUSPEND;
        COL_NUM = 2;
        SUSPEND;

        /* DAYS COLUMNS */
        FOR SELECT DAY_ID
            FROM SCHEDULE_DAYS_LIST(:I$SCHEDULE_TEMPLATE_ID, :I$USER_ID)
            ORDER BY DAY_ORDER
            INTO :DAY_ID
        DO
        BEGIN
            COL_NUM = COL_NUM + 1;
            DATA = NULL;
            VAL = NULL;
            SUSPEND;
        END
    END  
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SCHEDULE_REPORT_ALL_TEACHERS (
    I$SCHEDULE_TEMPLATE_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    COL_NUM SMALLINT,
    VAL VARCHAR(4000),
    DATA VARCHAR(4000),
    ORIENTATION VARCHAR(20))
AS
declare variable DAY_ID bigint;
declare variable DAY_CAPTION varchar(20);
declare variable DAY_DATE date;
declare variable HOUR_ID bigint;
declare variable HOUR_NUM integer;
declare variable TEACHER_ID bigint;
declare variable TEACHER_CAPTION varchar(1000);
declare variable ROOM_ID bigint;
declare variable ROOM_CAPTION varchar(1000);
declare variable CLASS_ID bigint;
declare variable CLASS_CAPTION varchar(1000);
declare variable SUBGROUP_ID bigint;
declare variable TEMP_TEACHER_ID bigint;
declare variable TEMP_TYPE_ID bigint;
BEGIN
    TEMP_TEACHER_ID = 0;

    SELECT TYPE_ID
    FROM OBJECTS O
    WHERE O.OBJ_ID = :I$SCHEDULE_TEMPLATE_ID
    INTO :TEMP_TYPE_ID;

    /* CAPTION */

    COL_NUM = 1;
    VAL = 'Фамилия И.О.';
    DATA = NULL;
    ORIENTATION = 'MIXED';
    SUSPEND;
    COL_NUM = 2;
    VAL = 'Урок';
    SUSPEND;


    FOR SELECT DAY_DATE, DAY_CAPTION
        FROM SCHEDULE_DAYS_LIST(:I$SCHEDULE_TEMPLATE_ID, :I$USER_ID)
        ORDER BY DAY_DATE, DAY_ORDER
        INTO :DAY_DATE, :DAY_CAPTION
    DO
    BEGIN
        COL_NUM = COL_NUM + 1;
        VAL = DAY_CAPTION;
        DATA = NULL;
        IF ((TEMP_TYPE_ID = 63) AND (DAY_DATE IS NOT NULL)) THEN
        BEGIN
            VAL = 'EXTRACTDAYOFWEEKDAYMONTHNAME';
            DATA = DAY_DATE;
        END
        SUSPEND;
    END

    /* BODY */

    FOR SELECT TEACHER_ID, TEACHER_CAPTION
        FROM SCHEDULE_TEACHERS_LIST(:I$SCHEDULE_TEMPLATE_ID)
        ORDER BY TEACHER_CAPTION
        INTO :TEACHER_ID, :TEACHER_CAPTION
    DO
    BEGIN
        FOR SELECT HOUR_ID, HOUR_NUMBER
            FROM SCHEDULE_HOURS_LIST(:I$SCHEDULE_TEMPLATE_ID)
            ORDER BY HOUR_NUMBER
            INTO :HOUR_ID, :HOUR_NUM
        DO
        BEGIN
            /* FIRST COLUMN */
            COL_NUM = 1;
            DATA = NULL;
            VAL = NULL;
            IF (TEMP_TEACHER_ID <> TEACHER_ID) THEN
            BEGIN
                VAL = TEACHER_CAPTION;
                TEMP_TEACHER_ID = TEACHER_ID;
            END
            SUSPEND;
            COL_NUM = 2;
            VAL = HOUR_NUM;
            SUSPEND;

            /* DAYS COLUMNS */
            FOR SELECT DAY_ID
                FROM SCHEDULE_DAYS_LIST(:I$SCHEDULE_TEMPLATE_ID, :I$USER_ID)
                ORDER BY DAY_ORDER
                INTO :DAY_ID
            DO
            BEGIN
                COL_NUM = COL_NUM + 1;
                DATA = NULL;
                VAL = '';

                FOR SELECT L9.PARENT_ID, NULL
                    FROM LINKS L70
                    INNER JOIN LINKS L6 ON L6.OBJ_ID = L70.OBJ_ID
                    INNER JOIN LINKS L60 ON L60.OBJ_ID = L70.OBJ_ID
                    INNER JOIN LINKS L58 ON L58.OBJ_ID = L70.OBJ_ID
                    INNER JOIN LINKS L14 ON L14.OBJ_ID = L70.OBJ_ID
                    INNER JOIN LINKS L9 ON L9.OBJ_ID = L58.PARENT_ID
                    WHERE L70.PARENT_ID = :I$SCHEDULE_TEMPLATE_ID
                      AND L70.OBJ_TYPE_ID = 70
                      AND L70.DATE_DEL IS NULL
                      AND L6.PARENT_ID = :DAY_ID
                      AND L6.DATE_DEL IS NULL
                      AND L60.PARENT_ID = :HOUR_ID
                      AND L60.DATE_DEL IS NULL
                      AND L58.PARENT_TYPE_ID = 58
                      AND L58.DATE_DEL IS NULL
                      AND L9.PARENT_TYPE_ID = 9
                      AND L9.DATE_DEL IS NULL
                      AND L14.PARENT_ID = :TEACHER_ID
                      AND L14.DATE_DEL IS NULL

                    UNION

                    SELECT L9.PARENT_ID, L48.PARENT_ID
                    FROM LINKS L70
                    INNER JOIN LINKS L6 ON L6.OBJ_ID = L70.OBJ_ID
                    INNER JOIN LINKS L60 ON L60.OBJ_ID = L70.OBJ_ID
                    INNER JOIN LINKS L58 ON L58.OBJ_ID = L70.OBJ_ID
                    INNER JOIN LINKS L14 ON L14.OBJ_ID = L70.OBJ_ID
                    INNER JOIN LINKS L48 ON L48.OBJ_ID = L58.PARENT_ID
                    INNER JOIN LINKS L47 ON L47.OBJ_ID = L48.PARENT_ID
                    INNER JOIN LINKS L9 ON L9.OBJ_ID = L47.PARENT_ID
                    WHERE L70.PARENT_ID = :I$SCHEDULE_TEMPLATE_ID
                      AND L70.OBJ_TYPE_ID = 70
                      AND L70.DATE_DEL IS NULL
                      AND L6.PARENT_ID = :DAY_ID
                      AND L6.DATE_DEL IS NULL
                      AND L60.PARENT_ID = :HOUR_ID
                      AND L60.DATE_DEL IS NULL
                      AND L58.PARENT_TYPE_ID = 58
                      AND L58.DATE_DEL IS NULL
                      AND L48.PARENT_TYPE_ID = 48
                      AND L48.DATE_DEL IS NULL
                      AND L47.PARENT_TYPE_ID = 47
                      AND L47.DATE_DEL IS NULL
                      AND L9.PARENT_TYPE_ID = 9
                      AND L9.DATE_DEL IS NULL
                      AND L14.PARENT_ID = :TEACHER_ID
                      AND L14.DATE_DEL IS NULL

                    INTO :CLASS_ID, :SUBGROUP_ID
                DO
                BEGIN
                    SELECT CAPTION
                    FROM OBJECT_CAPTION_GET(:CLASS_ID,NULL,NULL,:I$USER_ID)
                    INTO :CLASS_CAPTION;

                    IF (SUBGROUP_ID IS NOT NULL) THEN
                    BEGIN
                        CLASS_CAPTION = '[' || CLASS_CAPTION || ']';
                    END

                    IF (VAL = '') THEN
                    BEGIN
                        VAL = CLASS_CAPTION;
                    END
                    ELSE
                    BEGIN
                        VAL = VAL || ';  ' || CLASS_CAPTION;
                    END
                END

                SUSPEND;
            END
        END

        /* FINAL ROW: */

        /* FIRST COLUMN */
        COL_NUM = 1;
        DATA = NULL;
        VAL = NULL;
        SUSPEND;
        COL_NUM = 2;
        SUSPEND;

        /* DAYS COLUMNS */
        FOR SELECT DAY_ID
            FROM SCHEDULE_DAYS_LIST(:I$SCHEDULE_TEMPLATE_ID, :I$USER_ID)
            ORDER BY DAY_ORDER
            INTO :DAY_ID
        DO
        BEGIN
            COL_NUM = COL_NUM + 1;
            DATA = NULL;
            VAL = NULL;
            SUSPEND;
        END
    END  
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SCHEDULE_REPORT_ALONE_CLASS (
    I$SCHEDULE_TEMPLATE_ID BIGINT,
    I$CLASS_ID BIGINT)
RETURNS (
    C1 VARCHAR(500),
    C2 VARCHAR(500),
    C3 VARCHAR(500),
    C4 VARCHAR(500),
    C5 VARCHAR(500),
    C6 VARCHAR(500))
AS
declare variable SCHEDULE_ELEMENT_ID bigint;
declare variable DAY_ID bigint;
declare variable DAY_CAPTION varchar(20);
declare variable DAY_DATE date;
declare variable DAY_ORDER double precision;
declare variable HOUR_ID bigint;
declare variable HOUR_NUM integer;
declare variable HOUR_BEGIN time;
declare variable HOUR_END time;
declare variable GRADE_LOADING_ID bigint;
declare variable TEACHER_ID bigint;
declare variable TEACHER_CAPTION varchar(1000);
declare variable SUBJECT_ID bigint;
declare variable SUBJECT_CAPTION varchar(1000);
declare variable SUBJECT_SMALL_CAPTION varchar(20);
declare variable ROOM_ID bigint;
declare variable ROOM_CAPTION varchar(1000);
declare variable CLASS_ID bigint;
declare variable CLASS_CAPTION varchar(1000);
declare variable CLASS_ORDER double precision;
declare variable SUBGROUP_ID bigint;
declare variable SUBGROUP_CAPTION varchar(1000);
declare variable TEMP_DAY_ID bigint;
declare variable TEMP_HOUR_NUM integer;
declare variable TEMP_TYPE_ID bigint;
BEGIN
    TEMP_DAY_ID = 0;
    TEMP_HOUR_NUM = 0;

    SELECT TYPE_ID
    FROM OBJECTS O
    WHERE O.OBJ_ID = :I$SCHEDULE_TEMPLATE_ID
    INTO :TEMP_TYPE_ID;

    FOR SELECT SCHEDULE_ELEMENT_ID, DAY_ID, DAY_CAPTION, DAY_DATE, DAY_ORDER, HOUR_ID, HOUR_NUM, HOUR_BEGIN, HOUR_END, GRADE_LOADING_ID, TEACHER_ID, TEACHER_CAPTION, SUBJECT_ID,
               SUBJECT_CAPTION, SUBJECT_SMALL_CAPTION, ROOM_ID, ROOM_CAPTION, CLASS_ID, CLASS_CAPTION, CLASS_ORDER, SUBGROUP_ID, SUBGROUP_CAPTION
        FROM SCHEDULE_DATA_LIST(:I$SCHEDULE_TEMPLATE_ID, NULL, 1)
        WHERE CLASS_ID = :I$CLASS_ID
        ORDER BY DAY_ORDER, HOUR_NUM, SUBJECT_ID
        INTO :SCHEDULE_ELEMENT_ID, :DAY_ID, :DAY_CAPTION, :DAY_DATE, :DAY_ORDER, :HOUR_ID, :HOUR_NUM, :HOUR_BEGIN, :HOUR_END, :GRADE_LOADING_ID, :TEACHER_ID, :TEACHER_CAPTION,
             :SUBJECT_ID, :SUBJECT_CAPTION, :SUBJECT_SMALL_CAPTION, :ROOM_ID, :ROOM_CAPTION, :CLASS_ID, :CLASS_CAPTION, :CLASS_ORDER, :SUBGROUP_ID, :SUBGROUP_CAPTION
    DO
    BEGIN
        C1 = '';
        C2 = '';
        C3 = '';
        C4 = '';
        C5 = '';
        C6 = '';

        IF (TEMP_DAY_ID <> DAY_ID) THEN
        BEGIN
            IF (TEMP_DAY_ID <> 0) THEN
            BEGIN
                SUSPEND;
            END
            C1 = DAY_CAPTION;
            C2 = '';
            IF (TEMP_TYPE_ID = 63) THEN
            BEGIN
                SELECT DT
                FROM CURRENT_DATE_GET(:DAY_DATE)
                INTO :C2;
            END
            SUSPEND;
            TEMP_DAY_ID = DAY_ID;
            C1 = '';
            C2 = '';
        END

        IF (TEMP_HOUR_NUM <> HOUR_NUM) THEN
        BEGIN
            C1 = HOUR_NUM;

            SELECT T
            FROM CURRENT_TIME_GET(:HOUR_BEGIN)
            INTO :C2;

            SELECT :C2 || ' - ' || T
            FROM CURRENT_TIME_GET(:HOUR_END)
            INTO :C2;

            TEMP_HOUR_NUM = HOUR_NUM;
        END

        C3 = SUBJECT_CAPTION;
        C4 = ROOM_CAPTION;
        C5 = TEACHER_CAPTION;
        C6 = SUBGROUP_CAPTION;

        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SCHEDULE_REPORT_ALONE_ROOM (
    I$SCHEDULE_TEMPLATE_ID BIGINT,
    I$ROOM_ID BIGINT)
RETURNS (
    C1 VARCHAR(500),
    C2 VARCHAR(500),
    C3 VARCHAR(500),
    C4 VARCHAR(500),
    C5 VARCHAR(500),
    C6 VARCHAR(500))
AS
declare variable SCHEDULE_ELEMENT_ID bigint;
declare variable DAY_ID bigint;
declare variable DAY_CAPTION varchar(20);
declare variable DAY_DATE date;
declare variable DAY_ORDER double precision;
declare variable HOUR_ID bigint;
declare variable HOUR_NUM integer;
declare variable HOUR_BEGIN time;
declare variable HOUR_END time;
declare variable GRADE_LOADING_ID bigint;
declare variable TEACHER_ID bigint;
declare variable TEACHER_CAPTION varchar(1000);
declare variable SUBJECT_ID bigint;
declare variable SUBJECT_CAPTION varchar(1000);
declare variable SUBJECT_SMALL_CAPTION varchar(20);
declare variable ROOM_ID bigint;
declare variable ROOM_CAPTION varchar(1000);
declare variable CLASS_ID bigint;
declare variable CLASS_CAPTION varchar(1000);
declare variable CLASS_ORDER double precision;
declare variable SUBGROUP_ID bigint;
declare variable SUBGROUP_CAPTION varchar(1000);
declare variable TEMP_DAY_ID bigint;
declare variable TEMP_HOUR_NUM integer;
declare variable TEMP_TYPE_ID bigint;
BEGIN
    TEMP_DAY_ID = 0;
    TEMP_HOUR_NUM = 0;

    SELECT TYPE_ID
    FROM OBJECTS O
    WHERE O.OBJ_ID = :I$SCHEDULE_TEMPLATE_ID
    INTO :TEMP_TYPE_ID;

    FOR SELECT SCHEDULE_ELEMENT_ID, DAY_ID, DAY_CAPTION, DAY_DATE, DAY_ORDER, HOUR_ID, HOUR_NUM, HOUR_BEGIN, HOUR_END, GRADE_LOADING_ID, TEACHER_ID, TEACHER_CAPTION, SUBJECT_ID,
               SUBJECT_CAPTION, SUBJECT_SMALL_CAPTION, ROOM_ID, ROOM_CAPTION, CLASS_ID, CLASS_CAPTION, CLASS_ORDER, SUBGROUP_ID, SUBGROUP_CAPTION
        FROM SCHEDULE_DATA_LIST(:I$SCHEDULE_TEMPLATE_ID, NULL, 1)
        WHERE ROOM_ID = :I$ROOM_ID
        ORDER BY DAY_ORDER, HOUR_NUM, CLASS_ORDER
        INTO :SCHEDULE_ELEMENT_ID, :DAY_ID, :DAY_CAPTION, :DAY_DATE, :DAY_ORDER, :HOUR_ID, :HOUR_NUM, :HOUR_BEGIN, :HOUR_END, :GRADE_LOADING_ID, :TEACHER_ID, :TEACHER_CAPTION,
             :SUBJECT_ID, :SUBJECT_CAPTION, :SUBJECT_SMALL_CAPTION, :ROOM_ID, :ROOM_CAPTION, :CLASS_ID, :CLASS_CAPTION, :CLASS_ORDER, :SUBGROUP_ID, :SUBGROUP_CAPTION
    DO
    BEGIN
        C1 = '';
        C2 = '';
        C3 = '';
        C4 = '';
        C5 = '';
        C6 = '';

        IF (TEMP_DAY_ID <> DAY_ID) THEN
        BEGIN
            IF (TEMP_DAY_ID <> 0) THEN
            BEGIN
                SUSPEND;
            END
            C1 = DAY_CAPTION;
            C2 = '';
            IF (TEMP_TYPE_ID = 63) THEN
            BEGIN
                SELECT DT
                FROM CURRENT_DATE_GET(:DAY_DATE)
                INTO :C2;
            END
            SUSPEND;
            TEMP_DAY_ID = DAY_ID;
            C1 = '';
            C2 = '';
        END

        IF (TEMP_HOUR_NUM <> HOUR_NUM) THEN
        BEGIN
            C1 = HOUR_NUM;

            SELECT T
            FROM CURRENT_TIME_GET(:HOUR_BEGIN)
            INTO :C2;

            SELECT :C2 || ' - ' || T
            FROM CURRENT_TIME_GET(:HOUR_END)
            INTO :C2;

            TEMP_HOUR_NUM = HOUR_NUM;
        END

        C3 = CLASS_CAPTION;
        C4 = SUBJECT_CAPTION;
        C5 = TEACHER_CAPTION;
        C6 = SUBGROUP_CAPTION;

        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SCHEDULE_REPORT_ALONE_TEACHER (
    I$SCHEDULE_TEMPLATE_ID BIGINT,
    I$TEACHER_ID BIGINT)
RETURNS (
    C1 VARCHAR(500),
    C2 VARCHAR(500),
    C3 VARCHAR(500),
    C4 VARCHAR(500),
    C5 VARCHAR(500),
    C6 VARCHAR(500))
AS
declare variable SCHEDULE_ELEMENT_ID bigint;
declare variable DAY_ID bigint;
declare variable DAY_CAPTION varchar(20);
declare variable DAY_DATE date;
declare variable DAY_ORDER double precision;
declare variable HOUR_ID bigint;
declare variable HOUR_NUM integer;
declare variable HOUR_BEGIN time;
declare variable HOUR_END time;
declare variable GRADE_LOADING_ID bigint;
declare variable TEACHER_ID bigint;
declare variable TEACHER_CAPTION varchar(1000);
declare variable SUBJECT_ID bigint;
declare variable SUBJECT_CAPTION varchar(1000);
declare variable SUBJECT_SMALL_CAPTION varchar(20);
declare variable ROOM_ID bigint;
declare variable ROOM_CAPTION varchar(1000);
declare variable CLASS_ID bigint;
declare variable CLASS_CAPTION varchar(1000);
declare variable CLASS_ORDER double precision;
declare variable SUBGROUP_ID bigint;
declare variable SUBGROUP_CAPTION varchar(1000);
declare variable TEMP_DAY_ID bigint;
declare variable TEMP_HOUR_NUM integer;
declare variable TEMP_TYPE_ID bigint;
BEGIN
    TEMP_DAY_ID = 0;
    TEMP_HOUR_NUM = 0;

    SELECT TYPE_ID
    FROM OBJECTS O
    WHERE O.OBJ_ID = :I$SCHEDULE_TEMPLATE_ID
    INTO :TEMP_TYPE_ID;

    FOR SELECT SCHEDULE_ELEMENT_ID, DAY_ID, DAY_CAPTION, DAY_DATE, DAY_ORDER, HOUR_ID, HOUR_NUM, HOUR_BEGIN, HOUR_END, GRADE_LOADING_ID, TEACHER_ID, TEACHER_CAPTION, SUBJECT_ID,
               SUBJECT_CAPTION, SUBJECT_SMALL_CAPTION, ROOM_ID, ROOM_CAPTION, CLASS_ID, CLASS_CAPTION, CLASS_ORDER, SUBGROUP_ID, SUBGROUP_CAPTION
        FROM SCHEDULE_DATA_LIST(:I$SCHEDULE_TEMPLATE_ID, NULL, 1)
        WHERE TEACHER_ID = :I$TEACHER_ID
        ORDER BY DAY_ORDER, HOUR_NUM, CLASS_ORDER
        INTO :SCHEDULE_ELEMENT_ID, :DAY_ID, :DAY_CAPTION, :DAY_DATE, :DAY_ORDER, :HOUR_ID, :HOUR_NUM, :HOUR_BEGIN, :HOUR_END, :GRADE_LOADING_ID, :TEACHER_ID, :TEACHER_CAPTION,
             :SUBJECT_ID, :SUBJECT_CAPTION, :SUBJECT_SMALL_CAPTION, :ROOM_ID, :ROOM_CAPTION, :CLASS_ID, :CLASS_CAPTION, :CLASS_ORDER, :SUBGROUP_ID, :SUBGROUP_CAPTION
    DO
    BEGIN
        C1 = '';
        C2 = '';
        C3 = '';
        C4 = '';
        C5 = '';
        C6 = '';

        IF (TEMP_DAY_ID <> DAY_ID) THEN
        BEGIN
            IF (TEMP_DAY_ID <> 0) THEN
            BEGIN
                SUSPEND;
            END
            C1 = DAY_CAPTION;
            C2 = '';
            IF (TEMP_TYPE_ID = 63) THEN
            BEGIN
                SELECT DT
                FROM CURRENT_DATE_GET(:DAY_DATE)
                INTO :C2;
            END
            SUSPEND;
            TEMP_DAY_ID = DAY_ID;
            C1 = '';
            C2 = '';
        END

        IF (TEMP_HOUR_NUM <> HOUR_NUM) THEN
        BEGIN
            C1 = HOUR_NUM;

            SELECT T
            FROM CURRENT_TIME_GET(:HOUR_BEGIN)
            INTO :C2;

            SELECT :C2 || ' - ' || T
            FROM CURRENT_TIME_GET(:HOUR_END)
            INTO :C2;

            TEMP_HOUR_NUM = HOUR_NUM;
        END

        C3 = CLASS_CAPTION;
        C4 = SUBJECT_CAPTION;
        C5 = ROOM_CAPTION;
        C6 = SUBGROUP_CAPTION;

        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SCHEDULE_ROOMS_LIST (
    I$SCHEDULE_TEMPLATE_ID BIGINT,
    I$USER_ID BIGINT = null)
RETURNS (
    ROOM_ID BIGINT,
    ROOM_CAPTION VARCHAR(1000),
    ROOM_NUMBER VARCHAR(40),
    TEACHER_ID BIGINT)
AS
declare variable OBJ_ID bigint;
BEGIN
    SELECT FIRST 1 OBJ_ID
    FROM OBJECT_PARENTS_GET(:I$SCHEDULE_TEMPLATE_ID, 2)
    INTO :OBJ_ID;

    FOR SELECT L61.OBJ_ID
        FROM LINKS L73
        INNER JOIN LINKS L16 ON L16.PARENT_ID = L73.OBJ_ID
        INNER JOIN LINKS L61 ON L61.PARENT_ID = L16.OBJ_ID
        INNER JOIN VALL V ON V.OBJ_ID = L61.OBJ_ID
        WHERE L73.PARENT_ID = :OBJ_ID
          AND L73.OBJ_TYPE_ID = 73
          AND L73.DATE_DEL IS NULL
          AND L16.OBJ_TYPE_ID = 16
          AND L16.DATE_DEL IS NULL
          AND L61.OBJ_TYPE_ID = 61
          AND L61.DATE_DEL IS NULL
          AND V.PARAM_ID = 525
          AND V.IS_DEL = 0
          AND V.LISTVAL_ID = 23
        INTO :ROOM_ID
    DO
    BEGIN
        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:ROOM_ID, NULL, NULL, :I$USER_ID)
        INTO :ROOM_CAPTION;

        SELECT V
        FROM VAL_GET(:ROOM_ID, 407, 0, :I$USER_ID)
        INTO :ROOM_NUMBER;

        TEACHER_ID = NULL;

        SELECT V.VAL
        FROM VALR V
        WHERE V.PARAM_ID = 1344
          AND V.OBJ_ID = :ROOM_ID
          AND V.IS_DEL = 0
        INTO :TEACHER_ID;

        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SCHEDULE_SET (
    I$SCHEDULE_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$DELETE SMALLINT,
    I$DAY SMALLINT,
    I$DATE DATE,
    I$LESSON SMALLINT,
    I$CJ_ID BIGINT,
    I$ROOM_ID BIGINT,
    I$DURATION SMALLINT,
    I$PARENT_ID BIGINT,
    I$EXT_INFO VARCHAR(1000),
    I$USER_ID VARCHAR(40))
RETURNS (
    ID BIGINT,
    "DAY" INTEGER,
    "DATE" INTEGER,
    LESSON INTEGER,
    CJ BIGINT,
    ROOM BIGINT,
    DURATION INTEGER,
    PARENT BIGINT,
    TEMPLATE INTEGER)
AS
DECLARE VARIABLE V$DAY INTEGER;
DECLARE VARIABLE V$YD DATE;
DECLARE VARIABLE V$DT TIME;
DECLARE VARIABLE TM VARCHAR(10);
DECLARE VARIABLE TH VARCHAR(10);
begin

  -- Задается либо DAY, либо DATE
  IF(I$DELETE = 0 AND I$DAY IS NULL) THEN
  BEGIN
    I$DAY = EXTRACT(WEEKDAY FROM I$DATE);
    IF(I$DAY = 0) THEN I$DAY = 6; ELSE I$DAY = I$DAY - 1;
    V$DAY = EXTRACT(MONTH FROM I$DATE) * 100 + EXTRACT(DAY FROM I$DATE);
  END
  ELSE V$DAY = I$DAY;

  -- Блокируем добавление полных клонов записей
  IF(I$DELETE = 0) THEN
  BEGIN
    IF(EXISTS(
      SELECT FIRST 1 1
      FROM SCHEDULE_ITEMS SI
      WHERE SCHEDULE_ID = :I$SCHEDULE_ID AND (:I$OBJ_ID IS NULL OR OBJ_ID <> :I$OBJ_ID) AND DATE_DEL IS NULL
        AND SI.CJ_ID = :I$CJ_ID AND WEEKDAY_NUM = :V$DAY AND LESSON_NUM = :I$LESSON
    ))
    THEN EXCEPTION DATA_ERROR 'На указанные день/дату и номер урока в данном учебном коллективе уже назначено занятие';

    -- Пересчитываем номер урока в точное время
    IF(I$LESSON < 60) THEN
    BEGIN
      -- Берем по номеру урока, такой в шаблоне обязательно должен быть
      IF(I$DATE IS NULL) THEN
      BEGIN
        SELECT FIRST 1 V405.VAL
        FROM LINKS L60
        JOIN VALI V404 ON V404.OBJ_ID = L60.OBJ_ID AND V404.PARAM_ID = 404 AND V404.IS_DEL = 0 AND V404.VAL = :I$LESSON
        JOIN VALT V405 ON V405.OBJ_ID = L60.OBJ_ID AND V405.PARAM_ID = 405 AND V405.IS_DEL = 0
        WHERE L60.PARENT_ID = :I$SCHEDULE_ID AND L60.OBJ_TYPE_ID = 60 AND L60.DATE_DEL IS NULL
        INTO :V$DT;
      END
      ELSE
      BEGIN
        SELECT FIRST 1 V405.VAL
        FROM LINKS L59
        JOIN VALL V1341 ON V1341.OBJ_ID = L59.OBJ_ID AND V1341.PARAM_ID = 1341 AND V1341.IS_DEL = 0 AND V1341.LISTVAL_ID = 2
        JOIN VALD V3120 ON V3120.OBJ_ID = L59.OBJ_ID AND V3120.PARAM_ID = 3120 AND V3120.IS_DEL = 0 AND V3120.VAL <= :I$DATE
        JOIN VALD V3121 ON V3121.OBJ_ID = L59.OBJ_ID AND V3121.PARAM_ID = 3121 AND V3121.IS_DEL = 0 AND V3121.VAL >= :I$DATE
        JOIN LINKS L60 ON L60.PARENT_ID = L59.OBJ_ID AND L60.OBJ_TYPE_ID = 60 AND L60.DATE_DEL IS NULL
        JOIN VALI V404 ON V404.OBJ_ID = L60.OBJ_ID AND V404.PARAM_ID = 404 AND V404.IS_DEL = 0 AND V404.VAL = :I$LESSON
        JOIN VALT V405 ON V405.OBJ_ID = L60.OBJ_ID AND V405.PARAM_ID = 405 AND V405.IS_DEL = 0
        WHERE L59.PARENT_ID = :I$SCHEDULE_ID AND L59.OBJ_TYPE_ID = 59 AND L59.DATE_DEL IS NULL
        INTO :V$DT;
      END

      IF(V$DT IS NULL) THEN EXCEPTION DATA_ERROR 'Указанный номер урока не найден в шаблоне расписания';
    END
    ELSE
    BEGIN
      -- Берем по времени
      TH = TRUNC(I$LESSON / 60);
      TM = I$LESSON - TRUNC(I$LESSON / 60) * 60;
      IF(CHAR_LENGTH(TH) = 1) THEN TH = '0' || TH;
      IF(CHAR_LENGTH(TM) = 1) THEN TM = '0' || TM;
      V$DT = TH || ':' || TM;
    END
  END

  IF(I$DELETE = 1) THEN
  BEGIN
    IF(I$OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не указан id записи для удаления';

    UPDATE SCHEDULE_ITEMS
    SET DATE_DEL = CURRENT_TIMESTAMP
    WHERE SCHEDULE_ID = :I$SCHEDULE_ID AND OBJ_ID = :I$OBJ_ID AND DATE_DEL IS NULL;
  END
  ELSE IF(I$OBJ_ID IS NULL) THEN
  BEGIN

    IF(I$DURATION < 15 OR I$DURATION > 720) THEN EXCEPTION DATA_ERROR 'Недопустимая длительность занятия (15-720 минут)';

    -- Проверяем, что дата урока попадает в заданный учебный год
    -- это только в ленте
    IF(I$DATE IS NOT NULL) THEN
    BEGIN
      SELECT FIRST 1 CAST(LV.TAG AS DATE)
      FROM VALL V37
      JOIN LISTVALS LV ON LV.LISTVAL_ID = V37.LISTVAL_ID
      WHERE V37.OBJ_ID = :I$SCHEDULE_ID AND V37.PARAM_ID = 37 AND V37.IS_DEL = 0
      INTO :V$YD;

      IF(I$DATE < V$YD OR I$DATE >= DATEADD(1 YEAR TO V$YD)) THEN EXCEPTION DATA_ERROR 'Выбранная дата находится за пределами учебного года, указанного в расписании';
    END

    INSERT INTO SCHEDULE_ITEMS
    (SCHEDULE_ID, WEEKDAY_NUM, LESSON_NUM, CJ_ID, ROOM_ID, DURATION, PARENT_ID, EXT_INFO, LESSON_TIME)
    VALUES (:I$SCHEDULE_ID, :V$DAY, :I$LESSON, :I$CJ_ID, :I$ROOM_ID, :I$DURATION, :I$PARENT_ID, :I$EXT_INFO, :V$DT)
    RETURNING OBJ_ID INTO :ID;

  END
  ELSE
  BEGIN

    SELECT FIRST 1 SI.OBJ_ID
    FROM SCHEDULE_ITEMS SI
    WHERE SI.DATE_DEL IS NULL AND SI.SCHEDULE_ID = :I$SCHEDULE_ID AND SI.OBJ_ID = :I$OBJ_ID
    INTO :ID;

    IF(ID IS NULL) THEN EXCEPTION DATA_ERROR 'Запись расписания не найдена или была удалена';

    UPDATE SCHEDULE_ITEMS
    SET CJ_ID = :I$CJ_ID , ROOM_ID = :I$ROOM_ID, DURATION = :I$DURATION, WEEKDAY_NUM = :V$DAY, LESSON_NUM = :I$LESSON, EXT_INFO = :I$EXT_INFO, LESSON_TIME = :V$DT
    WHERE OBJ_ID = :I$OBJ_ID;

  END

  IF(ID IS NOT NULL) THEN
  BEGIN
    IF(I$DATE IS NOT NULL) THEN "DATE" = EXTRACT(MONTH FROM I$DATE) * 100 + EXTRACT(DAY FROM I$DATE);
    "DAY" = I$DAY;

    LESSON = I$LESSON;
    CJ = I$CJ_ID;
    ROOM = I$ROOM_ID;
    DURATION = I$DURATION;
    PARENT = I$PARENT_ID;
    TEMPLATE = 1;
  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SCHEDULE_SET_SUBST (
    I$OBJ_ID BIGINT,
    I$ID BIGINT,
    I$NEW SMALLINT,
    I$SRC_CJ BIGINT,
    I$DATE DATE,
    I$LESSON INTEGER,
    I$CJ_ID BIGINT,
    I$TEACHER_ID BIGINT,
    I$ROOM_ID BIGINT,
    I$DURATION INTEGER,
    I$USER_ID VARCHAR(40))
RETURNS (
    ID BIGINT,
    "DAY" INTEGER,
    "DATE" INTEGER,
    LESSON INTEGER,
    CJ BIGINT,
    SRC_CJ BIGINT,
    ROOM BIGINT,
    DURATION INTEGER,
    TEACHER BIGINT,
    TEMPLATE INTEGER)
AS
declare variable V$SRC_TEACHER bigint;
declare variable V$PLAN_ID bigint;
begin

  SELECT J.TEACHER_ID
  FROM CJ2_JOURNAL J
  WHERE J.DATE_DEL IS NULL AND J.OBJ_ID = :I$SRC_CJ
  INTO :V$SRC_TEACHER;

  IF(V$SRC_TEACHER IS NULL) THEN EXCEPTION DATA_ERROR 'Штатный преподаватель в журнале изменился, сохранить замещение нельзя';

  SELECT FIRST 1 P.OBJ_ID
  FROM CJ2_REPL_PLAN P
  WHERE P.DATE_DEL IS NULL AND P.PERSON_ID = :V$SRC_TEACHER AND P.DATE_FROM <= :I$DATE AND (P.DATE_TO IS NULL OR P.DATE_TO >= :I$DATE)
  INTO :V$PLAN_ID;

  IF(V$PLAN_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Запись отсутствия штатного преподавателя была удалена, либо измененный диапазон дат не требует замещения на это число';

  IF(I$NEW = 1) THEN
  BEGIN

    -- Проверяем, что это других записей замещения нет - смотрим именно по ссылке на план
    IF(EXISTS(
      SELECT FIRST 1 1
      FROM CJ2_REPL_PROCESS P
      WHERE P.DATE_DEL IS NULL AND (P.PLAN_ID = :V$PLAN_ID OR P.PERSON_ID = :V$SRC_TEACHER) AND P.CJ_ID = :I$SRC_CJ AND P.REPL_DATE = :I$DATE AND P.LESSON_NUM = :I$LESSON
    ))
    THEN EXCEPTION DATA_ERROR 'Замещение данного урока уже внесено';

    INSERT INTO CJ2_REPL_PROCESS
    (PLAN_ID, PERSON_ID, CJ_ID, REPL_DATE, LESSON_NUM, REPL_CJ_ID, REPL_PERSON_ID, ROOM_ID)
    VALUES (:V$PLAN_ID, :V$SRC_TEACHER, :I$SRC_CJ, :I$DATE, :I$LESSON, :I$CJ_ID, :I$TEACHER_ID, :I$ROOM_ID)
    RETURNING OBJ_ID INTO :ID;

  END
  ELSE
  BEGIN

    SELECT FIRST 1 P.OBJ_ID
    FROM CJ2_REPL_PROCESS P
    WHERE P.DATE_DEL IS NULL AND P.OBJ_ID = :I$ID
    INTO :ID;

    IF(ID IS NULL) THEN EXCEPTION DATA_ERROR 'Запись замещения не найдена или была удалена';

    UPDATE CJ2_REPL_PROCESS
    SET REPL_CJ_ID = IIF(:I$CJ_ID = CJ_ID, NULL, :I$CJ_ID), REPL_PERSON_ID = :I$TEACHER_ID, ROOM_ID = :I$ROOM_ID
    WHERE OBJ_ID = :I$ID;

  END

  "DAY" = EXTRACT(WEEKDAY FROM I$DATE);
  IF("DAY" = 0) THEN "DAY" = 6; ELSE "DAY" = "DAY" - 1;

  "DATE" = EXTRACT(MONTH FROM I$DATE) * 100 + EXTRACT(DAY FROM I$DATE);
  LESSON = I$LESSON;
  SRC_CJ = I$SRC_CJ;
  CJ = COALESCE(I$CJ_ID, I$SRC_CJ);
  TEACHER = I$TEACHER_ID;
  ROOM = I$ROOM_ID;
  DURATION = I$DURATION;
  TEMPLATE = 2;

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SCHEDULE_SUBJECTS_LIST (
    I$SCHEDULE_TEMPLATE_ID BIGINT,
    I$TEACHER_ID BIGINT)
RETURNS (
    SUBJECT_ID BIGINT,
    SUBJECT_CAPTION VARCHAR(1000),
    SUBJECT_ORDER DOUBLE PRECISION,
    LOADING_COUNT INTEGER,
    GRADE_LOADING_COUNT INTEGER)
AS
declare variable OBJ_ID bigint;
BEGIN
    LOADING_COUNT = 0;
    GRADE_LOADING_COUNT = 0;

    SELECT FIRST 1
           OBJ_ID
    FROM OBJECT_PARENTS_GET(:I$SCHEDULE_TEMPLATE_ID, 3)
    INTO :OBJ_ID;

    FOR
        /* ГУП */
        SELECT L51.PARENT_ID
        FROM LINKS L57

        JOIN LINKS L50
        ON L50.PARENT_ID = L57.OBJ_ID
        AND L50.OBJ_TYPE_ID = 50
        AND L50.DATE_DEL IS NULL

        JOIN LINKS L54
        ON L54.PARENT_ID = L50.OBJ_ID
        AND L54.OBJ_TYPE_ID = 54
        AND L54.DATE_DEL IS NULL

        JOIN LINKS L256
        ON L256.PARENT_ID = L54.OBJ_ID
        AND L256.OBJ_TYPE_ID = 256
        AND L256.DATE_DEL IS NULL

        JOIN LINKS L56
        ON L56.PARENT_ID = L54.OBJ_ID
        AND L56.OBJ_TYPE_ID = 56
        AND L56.DATE_DEL IS NULL

        JOIN LINKS L58
        ON L58.PARENT_ID = L56.OBJ_ID
        AND L58.OBJ_TYPE_ID = 58
        AND L58.DATE_DEL IS NULL

        JOIN LINKS L58_
        ON L58_.PARENT_ID = L256.OBJ_ID
        AND L58_.OBJ_ID = L58.OBJ_ID
        AND L58_.OBJ_TYPE_ID = 58
        AND L58_.DATE_DEL IS NULL

        JOIN LINKS L14
        ON L14.OBJ_ID = L58.OBJ_ID
        AND L14.PARENT_TYPE_ID = 14
        AND L14.DATE_DEL IS NULL
        AND ((:I$TEACHER_ID IS NULL) OR (L14.PARENT_ID = :I$TEACHER_ID))

        JOIN LINKS L51
        ON L51.OBJ_ID = L58.OBJ_ID
        AND L51.PARENT_TYPE_ID = 51
        AND L51.DATE_DEL IS NULL

        WHERE L57.PARENT_ID = :OBJ_ID
        AND L57.OBJ_TYPE_ID = 57
        AND L57.DATE_DEL IS NULL

        UNION

        /* Подгруппы */

        SELECT L51.PARENT_ID

        FROM LINKS L57

        JOIN LINKS L50
        ON L50.PARENT_ID = L57.OBJ_ID
        AND L50.OBJ_TYPE_ID = 50
        AND L50.DATE_DEL IS NULL

        JOIN LINKS L54
        ON L54.PARENT_ID = L50.OBJ_ID
        AND L54.OBJ_TYPE_ID = 54
        AND L54.DATE_DEL IS NULL

        JOIN LINKS L256
        ON L256.PARENT_ID = L54.OBJ_ID
        AND L256.OBJ_TYPE_ID = 256
        AND L256.DATE_DEL IS NULL

        JOIN LINKS L47
        ON L47.PARENT_ID = L256.OBJ_ID
        AND L47.OBJ_TYPE_ID = 47
        AND L47.DATE_DEL IS NULL

        JOIN LINKS L48
        ON L48.PARENT_ID = L47.OBJ_ID
        AND L48.OBJ_TYPE_ID = 48
        AND L48.DATE_DEL IS NULL

        JOIN LINKS L58
        ON L58.PARENT_ID = L48.OBJ_ID
        AND L58.OBJ_TYPE_ID = 58
        AND L58.DATE_DEL IS NULL

        JOIN LINKS LP56
        ON LP56.OBJ_ID = L58.OBJ_ID
        AND LP56.PARENT_TYPE_ID = 56
        AND LP56.DATE_DEL IS NULL

        JOIN LINKS L56
        ON L56.PARENT_ID = L54.OBJ_ID
        AND L56.OBJ_ID = LP56.PARENT_ID
        AND L56.DATE_DEL IS NULL

        JOIN LINKS L14
        ON L14.OBJ_ID = L58.OBJ_ID
        AND L14.PARENT_TYPE_ID = 14
        AND L14.DATE_DEL IS NULL
        AND ((:I$TEACHER_ID IS NULL) OR (L14.PARENT_ID = :I$TEACHER_ID))

        JOIN LINKS L51
        ON L51.OBJ_ID = L58.OBJ_ID
        AND L51.PARENT_TYPE_ID = 51
        AND L51.DATE_DEL IS NULL

        /* Проверка принадлежности предмета к делению по подгрупам */
        LEFT JOIN VALR V428
        ON V428.OBJ_ID = L47.OBJ_ID
        AND V428.PARAM_ID = 428
        AND V428.IS_DEL = 0

        LEFT JOIN LINKS L48_51
        ON L48_51.PARENT_ID = L48.OBJ_ID
        AND L48_51.OBJ_ID = L51.PARENT_ID
        AND L48_51.DATE_DEL IS NULL

        WHERE L57.PARENT_ID = :OBJ_ID
        AND L57.OBJ_TYPE_ID = 57
        AND L57.DATE_DEL IS NULL

        AND ((V428.VAL = L51.PARENT_ID) OR (L48_51.OBJ_ID = L51.PARENT_ID))

        UNION

        /* Потоки */

        SELECT L51.PARENT_ID

        FROM LINKS L57

        JOIN LINKS L50
        ON L50.PARENT_ID = L57.OBJ_ID
        AND L50.OBJ_TYPE_ID = 50
        AND L50.DATE_DEL IS NULL

        JOIN LINKS L54
        ON L54.PARENT_ID = L50.OBJ_ID
        AND L54.OBJ_TYPE_ID = 54
        AND L54.DATE_DEL IS NULL

        JOIN LINKS L346
        ON L346.PARENT_ID = L54.OBJ_ID
        AND L346.OBJ_TYPE_ID = 346
        AND L346.DATE_DEL IS NULL

        JOIN LINKS L347
        ON L347.PARENT_ID = L346.OBJ_ID
        AND L347.OBJ_TYPE_ID = 347
        AND L347.DATE_DEL IS NULL

        JOIN LINKS L58
        ON L58.PARENT_ID = L347.OBJ_ID
        AND L58.OBJ_TYPE_ID = 58
        AND L58.DATE_DEL IS NULL

        JOIN LINKS LP56
        ON LP56.OBJ_ID = L58.OBJ_ID
        AND LP56.PARENT_TYPE_ID = 56
        AND LP56.DATE_DEL IS NULL

        JOIN LINKS L56
        ON L56.PARENT_ID = L54.OBJ_ID
        AND L56.OBJ_ID = LP56.PARENT_ID
        AND L56.DATE_DEL IS NULL

        JOIN LINKS L14
        ON L14.OBJ_ID = L58.OBJ_ID
        AND L14.PARENT_TYPE_ID = 14
        AND L14.DATE_DEL IS NULL
        AND ((:I$TEACHER_ID IS NULL) OR (L14.PARENT_ID = :I$TEACHER_ID))

        JOIN LINKS L51
        ON L51.OBJ_ID = L58.OBJ_ID
        AND L51.PARENT_TYPE_ID = 51
        AND L51.DATE_DEL IS NULL

        /* Проверка принадлежности предмета к конкретному потоку */
        LEFT JOIN VALR V2705
        ON V2705.OBJ_ID = L346.OBJ_ID
        AND V2705.PARAM_ID = 2705
        AND V2705.IS_DEL = 0

        /* По необходимости добавить сверку по наличию нагрузки по предмету в УП */

        WHERE L57.PARENT_ID = :OBJ_ID
        AND L57.OBJ_TYPE_ID = 57
        AND L57.DATE_DEL IS NULL

        AND (V2705.VAL = L51.PARENT_ID)

        INTO :SUBJECT_ID
    DO
    BEGIN
        SELECT CAPTION, SORT_ORDER
        FROM OBJECT_CAPTION_GET(:SUBJECT_ID)
        INTO :SUBJECT_CAPTION, :SUBJECT_ORDER;

        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SCHEDULE_TEACHERS_LIST (
    I$SCHEDULE_TEMPLATE_ID BIGINT)
RETURNS (
    TEACHER_ID BIGINT,
    TEACHER_CAPTION VARCHAR(4000),
    LOADING_COUNT INTEGER,
    GRADE_LOADING_COUNT INTEGER)
AS
declare variable OBJ_ID bigint;
BEGIN
    LOADING_COUNT = 0;
    GRADE_LOADING_COUNT = 0;

    SELECT FIRST 1 OBJ_ID
    FROM OBJECT_PARENTS_GET(:I$SCHEDULE_TEMPLATE_ID, 3)
    INTO :OBJ_ID;

    FOR
        /* ГУП */
        SELECT L14.PARENT_ID
        FROM LINKS L57
        JOIN LINKS L50 ON L50.PARENT_ID = L57.OBJ_ID AND L50.OBJ_TYPE_ID = 50 AND L50.DATE_DEL IS NULL
        JOIN LINKS L54 ON L54.PARENT_ID = L50.OBJ_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
        JOIN LINKS L256 ON L256.PARENT_ID = L54.OBJ_ID AND L256.OBJ_TYPE_ID = 256 AND L256.DATE_DEL IS NULL
        JOIN LINKS L56 ON L56.PARENT_ID = L54.OBJ_ID AND L56.OBJ_TYPE_ID = 56 AND L56.DATE_DEL IS NULL
        JOIN LINKS L58 ON L58.PARENT_ID = L56.OBJ_ID AND L58.OBJ_TYPE_ID = 58 AND L58.DATE_DEL IS NULL
        JOIN LINKS L58_ ON L58_.PARENT_ID = L256.OBJ_ID AND L58_.OBJ_ID = L58.OBJ_ID AND L58_.OBJ_TYPE_ID = 58 AND L58_.DATE_DEL IS NULL
        JOIN LINKS L14 ON L14.OBJ_ID = L58.OBJ_ID AND L14.PARENT_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
        WHERE L57.PARENT_ID = :OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL

        /* Подгруппы */

        UNION

        SELECT L14.PARENT_ID
        FROM LINKS L57
        JOIN LINKS L50 ON L50.PARENT_ID = L57.OBJ_ID AND L50.OBJ_TYPE_ID = 50 AND L50.DATE_DEL IS NULL
        JOIN LINKS L54 ON L54.PARENT_ID = L50.OBJ_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
        JOIN LINKS L256 ON L256.PARENT_ID = L54.OBJ_ID AND L256.OBJ_TYPE_ID = 256 AND L256.DATE_DEL IS NULL
        JOIN LINKS L47 ON L47.PARENT_ID = L256.OBJ_ID AND L47.OBJ_TYPE_ID = 47 AND L47.DATE_DEL IS NULL
        JOIN LINKS L48 ON L48.PARENT_ID = L47.OBJ_ID AND L48.OBJ_TYPE_ID = 48 AND L48.DATE_DEL IS NULL
        JOIN LINKS L58 ON L58.PARENT_ID = L48.OBJ_ID AND L58.OBJ_TYPE_ID = 58 AND L58.DATE_DEL IS NULL
        JOIN LINKS LP56 ON LP56.OBJ_ID = L58.OBJ_ID AND LP56.PARENT_TYPE_ID = 56 AND LP56.DATE_DEL IS NULL
        JOIN LINKS L56 ON L56.PARENT_ID = L54.OBJ_ID AND L56.OBJ_ID = LP56.PARENT_ID AND L56.DATE_DEL IS NULL
        JOIN LINKS L14 ON L14.OBJ_ID = L58.OBJ_ID AND L14.PARENT_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
        WHERE L57.PARENT_ID = :OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL

        /* Потоки */

        UNION

        SELECT L14.PARENT_ID
        FROM LINKS L57
        JOIN LINKS L50 ON L50.PARENT_ID = L57.OBJ_ID AND L50.OBJ_TYPE_ID = 50 AND L50.DATE_DEL IS NULL
        JOIN LINKS L54 ON L54.PARENT_ID = L50.OBJ_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
        JOIN LINKS L346 ON L346.PARENT_ID = L54.OBJ_ID AND L346.OBJ_TYPE_ID = 346 AND L346.DATE_DEL IS NULL
        JOIN LINKS L347 ON L347.PARENT_ID = L346.OBJ_ID AND L347.OBJ_TYPE_ID = 347 AND L347.DATE_DEL IS NULL
        JOIN LINKS L58 ON L58.PARENT_ID = L347.OBJ_ID AND L58.OBJ_TYPE_ID = 58 AND L58.DATE_DEL IS NULL
        JOIN LINKS LP56 ON LP56.OBJ_ID = L58.OBJ_ID AND LP56.PARENT_TYPE_ID = 56 AND LP56.DATE_DEL IS NULL
        JOIN LINKS L56 ON L56.PARENT_ID = L54.OBJ_ID AND L56.OBJ_ID = LP56.PARENT_ID AND L56.DATE_DEL IS NULL
        JOIN LINKS L14 ON L14.OBJ_ID = L58.OBJ_ID AND L14.PARENT_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
        WHERE L57.PARENT_ID = :OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL

        INTO :TEACHER_ID
    DO
    BEGIN
        SELECT CAPTION
        FROM THE_CAPTION_TEACHER(:TEACHER_ID)
        INTO :TEACHER_CAPTION;
        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SCHEDULE_TO_DATE (
    I$DAYNUM INTEGER,
    I$YEAR INTEGER)
RETURNS (
    DAY_DAY INTEGER,
    DAY_DATE DATE)
AS
declare variable V$M integer;
declare variable V$D integer;
begin

  V$M = I$DAYNUM / 100;
  V$D = I$DAYNUM - V$M * 100;

  IF(V$M < 9) THEN I$YEAR = I$YEAR + 1; -- месяцы январь-август это следующий календарный год
  DAY_DATE = V$D || '.' || V$M || '.' || I$YEAR;

  DAY_DAY = EXTRACT(WEEKDAY FROM DAY_DATE);
  IF(DAY_DAY = 0) THEN DAY_DAY = 6; ELSE DAY_DAY = DAY_DAY - 1;

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SCHOLAR_BY_DATE (
    I$OBJ_ID BIGINT,
    I$DT DATE = current_date)
AS
declare variable DT_IN date;
declare variable DT_OUT date;
declare variable STAGE_LISTVAL_ID bigint;
declare variable CLASS_ID bigint;
declare variable CLASS varchar(100);
declare variable SCHOLAR_ID bigint;
declare variable V$MOVEMENT_ID bigint;
BEGIN
    DELETE FROM REPORT_OSH1 WHERE 1=1;
    FOR
        SELECT L10.OBJ_ID
        FROM LINKS L7
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID
          AND L8.OBJ_TYPE_ID IN (8, 242)
          AND L8.DATE_DEL IS NULL
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID
          AND L9.OBJ_TYPE_ID IN (9, 243)
          AND L9.DATE_DEL IS NULL
        JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID
          AND L10.OBJ_TYPE_ID = 10
          AND L10.DATE_DEL IS NULL
        WHERE L7.OBJ_TYPE_ID IN (7, 211)
          AND L7.PARENT_ID = :I$OBJ_ID
          AND L7.DATE_DEL IS NULL

        UNION
        SELECT L10.OBJ_ID
        FROM LINKS L78
        JOIN LINKS L8_ ON L8_.PARENT_ID = L78.OBJ_ID
          AND L8_.OBJ_TYPE_ID IN (81, 82, 83)
          AND L8_.DATE_DEL IS NULL
        JOIN LINKS L10 ON L10.PARENT_ID = L8_.OBJ_ID
          AND L10.OBJ_TYPE_ID = 10
          AND L10.DATE_DEL IS NULL
        WHERE L78.OBJ_TYPE_ID = 78
          AND L78.PARENT_ID = :I$OBJ_ID
          AND L78.DATE_DEL IS NULL

        INTO :SCHOLAR_ID
    DO
    BEGIN
        DT_IN = NULL;
        DT_OUT = NULL;

        /* find Class IN date in the Movement */
        SELECT FIRST 1
            L76.OBJ_ID MOVEMENT_ID,
            V436.LISTVAL_ID STAGE_LISTVAL_ID,
            V438.VAL CLASS_ID,
            V433.VAL DT_IN

        FROM LINKS L76

        JOIN VALR V438
        ON V438.OBJ_ID = L76.OBJ_ID
        AND V438.PARAM_ID = 438
        AND V438.IS_DEL = 0

        JOIN OBJECTS O
        ON O.OBJ_ID = V438.VAL
        AND O.TYPE_ID IN (9, 187)

        JOIN VALL V432
        ON V432.OBJ_ID = L76.OBJ_ID
        AND V432.PARAM_ID = 432
        AND V432.IS_DEL = 0
        AND V432.LISTVAL_ID >= 805
        AND V432.LISTVAL_ID <= 810

        JOIN VALL V436
        ON V436.OBJ_ID = L76.OBJ_ID
        AND V436.PARAM_ID = 436
        AND V436.IS_DEL = 0

        JOIN VALD V433
        ON V433.OBJ_ID = L76.OBJ_ID
        AND V433.PARAM_ID = 433
        AND V433.IS_DEL = 0
        AND V433.VAL <= :I$DT

        WHERE L76.PARENT_ID = :SCHOLAR_ID
        AND L76.OBJ_TYPE_ID = 76
        AND L76.DATE_DEL IS NULL

        ORDER BY V433.VAL DESC

        INTO :V$MOVEMENT_ID,
             :STAGE_LISTVAL_ID,
             :CLASS_ID,
             :DT_IN;

        IF (:DT_IN IS NOT NULL) THEN
        BEGIN
            /* find Class OUT date in the Movement */
            SELECT MIN(V433.VAL)
    
            FROM LINKS L76
    
            LEFT JOIN VALR V438
            ON V438.OBJ_ID = L76.OBJ_ID
            AND V438.PARAM_ID = 438
            AND V438.IS_DEL = 0
            AND V438.VAL = :CLASS_ID
    
            LEFT JOIN VALL V436
            ON V436.OBJ_ID = L76.OBJ_ID
            AND V436.PARAM_ID = 436
            AND V436.IS_DEL = 0
            AND V436.LISTVAL_ID = :STAGE_LISTVAL_ID
    
            JOIN VALD V433
            ON V433.OBJ_ID = L76.OBJ_ID
            AND V433.PARAM_ID = 433
            AND V433.IS_DEL = 0
            AND V433.VAL >= :DT_IN
    
            WHERE L76.PARENT_ID = :SCHOLAR_ID
            AND L76.OBJ_TYPE_ID = 76
            AND L76.DATE_DEL IS NULL
    
            AND (V438.VAL IS NULL OR V436.LISTVAL_ID IS NULL)
    
            INTO :DT_OUT;
    
            IF (:DT_OUT IS NULL OR :DT_OUT > :I$DT) THEN
            BEGIN
                SELECT V FROM VAL_GET(:V$MOVEMENT_ID, 437) INTO :CLASS;

                INSERT INTO REPORT_OSH1 (STAGE_LISTVAL_ID, CLASS_ID, CLASS, SCHOLAR_ID)
                VALUES (:STAGE_LISTVAL_ID, :CLASS_ID, :CLASS, :SCHOLAR_ID);
            END
        END
    END
    -- ДО и ГПД
    FOR
        SELECT G.GPD_ID, G.CLASS_NUM, G.SCHOLAR_ID
        FROM REPORT_OSH1 R
        JOIN OU_CLASS_REPORT_GPD(:I$OBJ_ID, :I$DT, 0) G
          ON G.SCHOLAR_ID = R.SCHOLAR_ID
        INTO :CLASS_ID, :STAGE_LISTVAL_ID, :SCHOLAR_ID
    DO
    BEGIN
        INSERT INTO REPORT_OSH1 (STREAM_ID, STAGE_LISTVAL_ID, SCHOLAR_ID)
        VALUES (:CLASS_ID, :STAGE_LISTVAL_ID, :SCHOLAR_ID);
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SCHOLAR_CNT_CS_GET RETURNS (
    F1 VARCHAR(40),
    F2 VARCHAR(1000),
    F3 INTEGER,
    F4 INTEGER,
    F5 INTEGER)
AS
declare variable V$OU_LICENCE_TYPE varchar(1);
declare variable V$SORT_ORDER bigint;
declare variable V$F1 integer;
BEGIN
  SELECT STATUS FROM OU_LICENCE_TYPE  INTO :V$OU_LICENCE_TYPE;
  -- если это одод
  if (V$OU_LICENCE_TYPE = 'U') then
  BEGIN
    FOR
      SELECT * FROM SCHOLAR_CNT_UDOD_GET
      INTO :F1, :F2, :F3, :F4, :F5
    DO
      SUSPEND;
  END
  -- если это школа
  ELSE BEGIN
    V$F1 = 0;
    FOR
      SELECT
        CC.SORT_ORDER SORT_ORDER,
        CC.CAPTION CAPTION,
        CAST(BOYS.VAL AS INTEGER) BOY_CNT,
        CAST(GIRLS.VAL AS INTEGER) GIRL_CNT,
        CAST(ALLS.VAL AS INTEGER) ALL_CNT
      
      FROM
        -- учреждение
        LINKS L2
      
        -- уровень образования
        JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
      
        -- параллель
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
      
        -- учебный коллектив
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
        LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) CC ON 1=1
        JOIN DO_FUNC(L9.OBJ_ID, 585) BOYS ON 1=1
        JOIN DO_FUNC(L9.OBJ_ID, 586) GIRLS ON 1=1
        JOIN DO_FUNC(L9.OBJ_ID, 584) ALLS ON 1=1
      
      WHERE
        L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      
      UNION
      
      SELECT
        9999999999999 SORT_ORDER,
        COUNT(DISTINCT L9.OBJ_ID) CAPTION,
        SUM(CAST(BOYS.VAL AS INTEGER)) BOY_CNT,
        SUM(CAST(GIRLS.VAL AS INTEGER)) GIRL_CNT,
        SUM(CAST(ALLS.VAL AS INTEGER)) ALL_CNT
      
      FROM
        -- учреждение
        LINKS L2
      
        -- уровень образования
        JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
      
        -- параллель
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
      
        -- учебный коллектив
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
        LEFT JOIN DO_FUNC(L9.OBJ_ID, 585) BOYS ON 1=1
        JOIN DO_FUNC(L9.OBJ_ID, 586) GIRLS ON 1=1
        JOIN DO_FUNC(L9.OBJ_ID, 584) ALLS ON 1=1
      
      WHERE
        L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      
      ORDER BY 1
      INTO :V$SORT_ORDER, :F2, :F3, :F4, :F5
  
    DO
    BEGIN
      V$F1 = V$F1 + 1;
      if (V$SORT_ORDER = 9999999999999) then
        F1 = 'Итого:';
      else
        F1 = cast(V$F1 as varchar(40));
      SUSPEND;
    END
  END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SCHOLAR_CNT_DISTR_GET RETURNS (
    F1 VARCHAR(1000),
    F2 INTEGER,
    F3 INTEGER)
AS
BEGIN
    FOR SELECT
            (SELECT CAPTION FROM OBJECT_CAPTION_GET(SCHOOL_ID)) F1,
            (SELECT V FROM VAL_GET(SCHOOL_ID, 2168)) F2,
            F3
        FROM (
            SELECT
                SCHOOL_ID,
                SUM(IIF(CLASS_TYPE_ID <> 187 OR CLASS_TYPE_ID IS NULL, C1 + C2 + C3, 0)) F3
            FROM REPORT_D12
            GROUP BY SCHOOL_ID
        )
        ORDER BY (SELECT IIF(I = 0, 99999, I) FROM VAL_GET(SCHOOL_ID, 17)), F1
        INTO :F1, :F2, :F3
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SCHOLAR_CNT_DISTR_GET2 RETURNS (
    F1 VARCHAR(1000),
    F2 INTEGER,
    F3 INTEGER,
    F4 INTEGER,
    F5 INTEGER)
AS
BEGIN
    FOR SELECT
            (SELECT CAPTION FROM OBJECT_CAPTION_GET(SCHOOL_ID)) F1,
            F2, F3, F4, F5
        FROM (
            SELECT
                SCHOOL_ID,
                COUNT(DISTINCT(IIF(CLASS_TYPE_ID <> 187, CLASS_ID, NULL))) F2,
                SUM(IIF(CLASS_TYPE_ID <> 187 OR CLASS_TYPE_ID IS NULL, C1 + C2 + C3, 0)) F3,
                COUNT(DISTINCT(IIF(CLASS_TYPE_ID = 187, CLASS_ID, NULL))) F4,
                SUM(IIF(CLASS_TYPE_ID = 187, C1 + C2 + C3, 0)) F5
            FROM REPORT_D12
            GROUP BY SCHOOL_ID
        )
        ORDER BY (SELECT IIF(I = 0, 99999, I) FROM VAL_GET(SCHOOL_ID, 17)), F1
        INTO :F1, :F2, :F3, :F4, :F5
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SCHOLAR_CNT_DISTR_INS (
    I$OBJ_ID BIGINT,
    I$DT DATE,
    I$STAGE_ID BIGINT)
AS
declare variable V$M1 bigint;
declare variable V$M2 bigint;
declare variable SCHOOL_ID bigint;
declare variable SCHOLAR_ID bigint;
declare variable SCHOLAR_TEMP_ID bigint;
declare variable STAGE_ID bigint;
declare variable BS1 bigint;
declare variable FS1 bigint;
declare variable BS2 bigint;
declare variable FS2 bigint;
declare variable BS3 bigint;
declare variable FS3 bigint;
declare variable STOP_1 smallint = 0;
declare variable CLASS_ID bigint;
declare variable CLASS_TYPE_ID bigint;
BEGIN
    SCHOOL_ID = :I$OBJ_ID;

    SELECT BEGIN_STAGE1, FINAL_STAGE1, IIF(BEGIN_STAGE2 > 41, 41, BEGIN_STAGE2), FINAL_STAGE2, BEGIN_STAGE3, FINAL_STAGE3
    FROM D_12_ADD_GET_STAGES(:I$OBJ_ID)
    INTO :BS1, :FS1, :BS2, :FS2, :BS3, :FS3;

    IF (ROW_COUNT = 0 AND (SELECT STATUS FROM OU_LICENCE_TYPE) <> 'D') THEN
    BEGIN
        EXIT;
    END

    I$OBJ_ID = I$OBJ_ID / 1000000000;
    V$M1 = I$OBJ_ID * 1000000000;
    V$M2 = (I$OBJ_ID + 1) * 1000000000;
    SCHOLAR_TEMP_ID = 0;

    FOR
        SELECT M.PERSON_ID, M.STAGE_ID, M.GROUP_ID, M.TYPE_IN
        FROM PERSON_MOVEMENTS M
        JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9
        WHERE M.DATE_DEL IS NULL AND M.OBJ_ID >= :V$M1 AND M.OBJ_ID < :V$M2
            AND M.DATE_IN <= :I$DT AND (M.DATE_OUT IS NULL OR M.DATE_OUT > :I$DT)
            AND (:I$STAGE_ID IS NULL OR M.STAGE_ID = :I$STAGE_ID)
        ORDER BY M.PERSON_ID, M.DATE_IN
        INTO :SCHOLAR_ID, :STAGE_ID, :CLASS_ID, :CLASS_TYPE_ID
    DO
    BEGIN
        IF (SCHOLAR_TEMP_ID <> SCHOLAR_ID) THEN
        BEGIN
            STOP_1 = 0;
            SCHOLAR_TEMP_ID = SCHOLAR_ID;
        END

        IF (STOP_1 = 0) THEN
        BEGIN
            EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 1, :STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3, :CLASS_ID, :CLASS_TYPE_ID);

            -- проверим выбытие в семью
            IF ((CLASS_TYPE_ID IS NULL OR CLASS_TYPE_ID <> 187) AND (
                SELECT FIRST 1 V105.LISTVAL_ID
                FROM VALL V105
                WHERE V105.PARAM_ID = 105 AND V105.OBJ_ID = :SCHOLAR_ID AND V105.IS_DEL = 0) IN (913, 11200)) THEN
            BEGIN
                CLASS_ID = NULL;
                CLASS_TYPE_ID = NULL;

                SELECT FIRST 1 L10.PARENT_ID, L10.PARENT_TYPE_ID, V49.LISTVAL_ID
                FROM LINKS L10
                JOIN LINKS L187 ON L187.OBJ_ID = L10.PARENT_ID AND L187.PARENT_TYPE_ID = 8
                LEFT JOIN VALL V49 ON V49.OBJ_ID = L187.PARENT_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
                WHERE L10.OBJ_ID = :SCHOLAR_ID AND L10.PARENT_TYPE_ID = 187 AND (:I$STAGE_ID IS NULL OR V49.LISTVAL_ID = :I$STAGE_ID)
                ORDER BY COALESCE(L10.DATE_DEL, '31.12.2099') DESC
                INTO :CLASS_ID, :CLASS_TYPE_ID, :STAGE_ID;

                IF (CLASS_TYPE_ID = 187) THEN
                BEGIN
                    EXECUTE PROCEDURE D_12_ADD_INSERT_ROW(:SCHOOL_ID, :SCHOLAR_ID, 1, :STAGE_ID, :BS1, :FS1, :BS2, :FS2, :BS3, :FS3, :CLASS_ID, 187);
                END
            END

            STOP_1 = 1;
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SCHOLAR_CNT_REGION_CD_GET RETURNS (
    FN INTEGER,
    F1 VARCHAR(1000),
    F2 VARCHAR(1000),
    F3 VARCHAR(1000),
    F4 VARCHAR(1000),
    F5 INTEGER)
AS
BEGIN
  FN = 0;
  IF ((SELECT STATUS FROM OU_LICENCE_TYPE) = 'C') THEN
  BEGIN
    FOR
        SELECT
            CAST(V2.VAL AS VARCHAR(100)) F1,
            CAST(V5.VAL AS VARCHAR(400)) F2,
            CAST(V999.VAL AS VARCHAR(100)) F3,
            CAST(R2163.VAL AS VARCHAR(100)) F4,
            L7.VAL F5
        FROM
        (
          SELECT L7.PARENT_ID, L7.PARENT_TYPE_ID, L7.OBJ_TYPE_ID, L7.DATE_DEL, SUM(V47.VAL) VAL
          FROM LINKS L7
          LEFT JOIN VALI V47 ON V47.OBJ_ID = L7.OBJ_ID AND V47.PARAM_ID = 47 AND V47.IS_DEL = 0
          GROUP BY L7.PARENT_ID, L7.PARENT_TYPE_ID, L7.OBJ_TYPE_ID, L7.DATE_DEL
        ) L7
        LEFT JOIN VALS V2 ON V2.OBJ_ID = L7.PARENT_ID AND V2.PARAM_ID = 2 AND V2.IS_DEL = 0
        LEFT JOIN VALS V5 ON V5.OBJ_ID = L7.PARENT_ID AND V5.PARAM_ID = 5 AND V5.IS_DEL = 0
        LEFT JOIN VALS V999 ON V999.OBJ_ID = L7.PARENT_ID AND V999.PARAM_ID = 999 AND V999.IS_DEL = 0
        LEFT JOIN VALL V2163 ON V2163.OBJ_ID = L7.PARENT_ID AND V2163.PARAM_ID = 2163 AND V2163.IS_DEL = 0
        LEFT JOIN LISTVALS LV2163 ON LV2163.LISTVAL_ID = V2163.LISTVAL_ID AND LV2163.IS_DEL = 0
        LEFT JOIN RES R2163 ON R2163.RES_ID = LV2163.RES_ID AND R2163.LANG_CODE ='RU' AND R2163.IS_DEL = 0
        WHERE
          L7.PARENT_TYPE_ID = 2
          AND L7.OBJ_TYPE_ID = 7
          AND L7.DATE_DEL IS NULL
        ORDER BY F1
        INTO :F1, :F2, :F3, :F4, :F5
    DO
    BEGIN
        FN = FN + 1;
        SUSPEND;
    END
  END
  ELSE BEGIN
    FOR
        SELECT
            CAST(V2.VAL AS VARCHAR(1000)) F1,
            CAST(V5.VAL AS VARCHAR(1000)) F2,
            CAST(V999.VAL AS VARCHAR(1000)) F3,
            (SELECT CAPTION FROM OBJECT_CAPTION_GET(L2.PARENT_ID)) F4,
            SUM(D.cnt) F5
        FROM (
            SELECT
                SCHOOL_ID,
                SUM(IIF(CLASS_TYPE_ID <> 187 OR CLASS_TYPE_ID IS NULL, C1 + C2 + C3, 0)) cnt
            FROM REPORT_D12
            GROUP BY SCHOOL_ID
        ) D
        JOIN LINKS L2 ON L2.OBJ_ID = D.SCHOOL_ID
          AND (L2.PARENT_TYPE_ID = 111 or L2.PARENT_TYPE_ID = 112)
          AND L2.DATE_DEL IS NULL

        LEFT JOIN VALS V2 ON V2.OBJ_ID = L2.OBJ_ID AND V2.PARAM_ID = 2 AND V2.IS_DEL = 0
        LEFT JOIN VALS V5 ON V5.OBJ_ID = L2.OBJ_ID AND V5.PARAM_ID = 5 AND V5.IS_DEL = 0
        LEFT JOIN VALS V999 ON V999.OBJ_ID = L2.OBJ_ID AND V999.PARAM_ID = 999 AND V999.IS_DEL = 0

        GROUP BY
            CAST(V2.VAL AS VARCHAR(1000)),
            CAST(V5.VAL AS VARCHAR(1000)),
            CAST(V999.VAL AS VARCHAR(1000)),
            L2.PARENT_ID

        ORDER BY 1
        INTO :F1, :F2, :F3, :F4, :F5
    DO
    BEGIN
        FN = FN + 1;
        SUSPEND;
    END
  END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SCHOLAR_CNT_REGION_GET RETURNS (
    F1 VARCHAR(1000),
    F2 INTEGER,
    F3 INTEGER)
AS
BEGIN
    FOR
        SELECT
            (SELECT CAPTION FROM OBJECT_CAPTION_GET(L2.PARENT_ID)) F1,
            SUM((SELECT CAST(V AS INT) FROM VAL_GET(SCHOOL_ID, 2168))) F2,
            SUM(F3) F3
        FROM (
            SELECT
                SCHOOL_ID,
                SUM(IIF(CLASS_TYPE_ID <> 187 OR CLASS_TYPE_ID IS NULL, C1 + C2 + C3, 0)) F3
            FROM REPORT_D12
            GROUP BY SCHOOL_ID
        ) D
        JOIN LINKS L2 ON L2.OBJ_ID = D.SCHOOL_ID
          AND L2.PARENT_TYPE_ID = 111
          AND L2.DATE_DEL IS NULL
        GROUP BY L2.PARENT_ID
        ORDER BY 1
        INTO :F1, :F2, :F3
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SCHOLAR_CNT_REGION_GET2 RETURNS (
    F1 VARCHAR(1000),
    F2 INTEGER,
    F3 INTEGER,
    F4 INTEGER,
    F5 INTEGER)
AS
BEGIN
    FOR SELECT
            (SELECT CAPTION FROM OBJECT_CAPTION_GET(L2.PARENT_ID)) F1,
            SUM(F2), SUM(F3), SUM(F4), SUM(F5)
        FROM (
            SELECT
                SCHOOL_ID,
                COUNT(DISTINCT(IIF(CLASS_TYPE_ID <> 187, CLASS_ID, NULL))) F2,
                SUM(IIF(CLASS_TYPE_ID <> 187 OR CLASS_TYPE_ID IS NULL, C1 + C2 + C3, 0)) F3,
                COUNT(DISTINCT(IIF(CLASS_TYPE_ID = 187, CLASS_ID, NULL))) F4,
                SUM(IIF(CLASS_TYPE_ID = 187, C1 + C2 + C3, 0)) F5
            FROM REPORT_D12
            GROUP BY SCHOOL_ID
        ) D
        JOIN LINKS L2 ON L2.OBJ_ID = D.SCHOOL_ID
          AND L2.PARENT_TYPE_ID = 111
          AND L2.DATE_DEL IS NULL
        GROUP BY L2.PARENT_ID
        ORDER BY 1
        INTO :F1, :F2, :F3, :F4, :F5
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SCHOLAR_CNT_UDOD_GET RETURNS (
    F1 VARCHAR(40),
    F2 VARCHAR(1000),
    F3 INTEGER,
    F4 INTEGER,
    F5 INTEGER)
AS
declare variable V$SORT_ORDER bigint;
declare variable V$F1 integer;
BEGIN
  V$F1 = 0;
  FOR
    --если нет подразделений первого уровня 
    SELECT
      CC.SORT_ORDER SORT_ORDER,
      CC.CAPTION CAPTION,
      CAST(BOYS.VAL AS INTEGER) BOY_CNT,
      CAST(GIRLS.VAL AS INTEGER) GIRL_CNT,
      CAST(ALLS.VAL AS INTEGER) ALL_CNT
    
    FROM
      -- учреждение
      LINKS L2

      -- объединение (детский коллектив)
      JOIN LINKS L242 ON L242.PARENT_ID = L2.OBJ_ID AND L242.OBJ_TYPE_ID = 242 AND L242.DATE_DEL IS NULL
      LEFT JOIN OBJECT_CAPTION_GET(L242.OBJ_ID) CC ON 1=1
    
      JOIN DO_FUNC(L242.OBJ_ID, 2142) BOYS ON 1=1
      JOIN DO_FUNC(L242.OBJ_ID, 2143) GIRLS ON 1=1
      JOIN DO_FUNC(L242.OBJ_ID, 2141) ALLS ON 1=1
    
    WHERE
      L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL

    UNION

    SELECT
      CC.SORT_ORDER SORT_ORDER,
      CC.CAPTION CAPTION,
      CAST(BOYS.VAL AS INTEGER) BOY_CNT,
      CAST(GIRLS.VAL AS INTEGER) GIRL_CNT,
      CAST(ALLS.VAL AS INTEGER) ALL_CNT
    
    FROM
      -- учреждение
      LINKS L2
    
      -- структурное подразделение первого уровня
      JOIN LINKS L211 ON L211.PARENT_ID = L2.OBJ_ID AND L211.OBJ_TYPE_ID = 211 AND L211.DATE_DEL IS NULL
    
      -- объединение (детский коллектив)
      JOIN LINKS L242 ON L242.PARENT_ID = L211.OBJ_ID AND L242.OBJ_TYPE_ID = 242 AND L242.DATE_DEL IS NULL
      LEFT JOIN OBJECT_CAPTION_GET(L242.OBJ_ID) CC ON 1=1
    
      JOIN DO_FUNC(L242.OBJ_ID, 2142) BOYS ON 1=1
      JOIN DO_FUNC(L242.OBJ_ID, 2143) GIRLS ON 1=1
      JOIN DO_FUNC(L242.OBJ_ID, 2141) ALLS ON 1=1
    
    WHERE
      L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL

    UNION

    SELECT
      9999999999999 SORT_ORDER,
      COUNT(DISTINCT OBJ_ID) CAPTION,
      SUM(CAST(BOYS.VAL AS INTEGER)) BOY_CNT,
      SUM(CAST(GIRLS.VAL AS INTEGER)) GIRL_CNT,
      SUM(CAST(ALLS.VAL AS INTEGER)) ALL_CNT

    FROM
     (SELECT DISTINCT L242.OBJ_ID
      FROM
        -- учреждение
        LINKS L2
        -- структурное подразделение первого уровня
      LEFT JOIN LINKS L211 ON L211.PARENT_ID = L2.OBJ_ID AND L211.OBJ_TYPE_ID = 211 AND L211.DATE_DEL IS NULL
      -- объединение (детский коллектив)
      JOIN LINKS L242 ON ((L242.PARENT_ID = L211.OBJ_ID) OR (L242.PARENT_ID = L2.OBJ_ID)) AND L242.OBJ_TYPE_ID = 242 AND L242.DATE_DEL IS NULL
      WHERE
        L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      ) a
      JOIN DO_FUNC(OBJ_ID, 2142) BOYS ON 1=1
      JOIN DO_FUNC(OBJ_ID, 2143) GIRLS ON 1=1
      JOIN DO_FUNC(OBJ_ID, 2141) ALLS ON 1=1

    ORDER BY 1

    INTO :V$SORT_ORDER, :F2, :F3, :F4, :F5

  DO
  BEGIN
    V$F1 = V$F1 + 1;
    if (V$SORT_ORDER = 9999999999999) then
      F1 = 'Итого:';
    else
      F1 = cast(V$F1 as varchar(40));
    SUSPEND;
  END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SCHOOL_WEEK_ADD (
    I$OBJ_ID BIGINT,
    I$VAL BIGINT,
    IS_RECURRENCE SMALLINT = 0)
AS
DECLARE VARIABLE V$PARENT_ID BIGINT;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$LISTVAL_ID BIGINT;
DECLARE VARIABLE V$ULTIMATE_LOAD INTEGER;
DECLARE VARIABLE V$BLOB_ID BIGINT;
DECLARE VARIABLE V$ADAPT BIGINT;
BEGIN
  -- Если менялось поле этапа, выбираем само значение длительности недели
  IF(I$VAL IS NULL) THEN
  BEGIN
    SELECT FIRST 1 V2837.LISTVAL_ID
    FROM LINKS LP50
    JOIN VALL V2837 ON V2837.OBJ_ID = LP50.OBJ_ID AND V2837.PARAM_ID = 2837 AND V2837.IS_DEL = 0
    WHERE LP50.OBJ_ID = :I$OBJ_ID AND LP50.PARENT_TYPE_ID IN (50, 400) AND LP50.DATE_DEL IS NULL
    INTO :I$VAL;

    -- Если поля нет - это шаблон УП. Удаляем поле со значением нагрузки
    -- в шаблонах УП в этапах поле недель скрыто, удаляем предельную нагрузку
    IF(I$VAL IS NULL) THEN
    BEGIN
      UPDATE VALI SET IS_DEL = 1 WHERE OBJ_ID = :I$OBJ_ID AND PARAM_ID = 383 AND IS_DEL = 0;
      EXIT;
    END
  END

  -- Выбираем уровень образования - родителя тут не быть не может, но могут из-за копирования оказаться оба атрибута
  -- + стандарт
  SELECT FIRST 1 LP50.PARENT_ID, V2503.LISTVAL_ID, V3014.LISTVAL_ID
  FROM LINKS LP50
  LEFT JOIN VALL V2503 ON V2503.OBJ_ID = LP50.PARENT_ID AND V2503.PARAM_ID IN (2503, 3345) AND V2503.IS_DEL = 0
  LEFT JOIN VALL V3014 ON V3014.OBJ_ID = LP50.PARENT_ID AND V3014.PARAM_ID = 3014 AND V3014.IS_DEL = 0
  WHERE LP50.OBJ_ID = :I$OBJ_ID AND LP50.PARENT_TYPE_ID IN (50, 400) AND LP50.DATE_DEL IS NULL
  INTO :V$PARENT_ID, :V$LISTVAL_ID, :V$ADAPT;

  -- Если уровень образования не получили - значит здесь не шаблон, а реальный УП, и уровень нужно брать выше
  IF(V$LISTVAL_ID IS NULL) THEN
  BEGIN
    SELECT FIRST 1 V1594.LISTVAL_ID, V3014.LISTVAL_ID
    FROM LINKS LP50
    LEFT JOIN VALL V3014 ON V3014.OBJ_ID = LP50.PARENT_ID AND V3014.PARAM_ID = 3014 AND V3014.IS_DEL = 0
    JOIN LINKS LP57 ON LP57.OBJ_ID = LP50.PARENT_ID AND LP57.PARENT_TYPE_ID = 57 AND LP57.DATE_DEL is null
    LEFT JOIN VALL V1594 ON V1594.OBJ_ID = LP57.PARENT_ID AND V1594.PARAM_ID = 1594 AND V1594.IS_DEL = 0
    WHERE LP50.OBJ_ID = :I$OBJ_ID AND LP50.PARENT_TYPE_ID IN (50, 400) AND LP50.DATE_DEL IS NULL
    INTO :V$LISTVAL_ID, :V$ADAPT;
  END

  -- Для этапов, находящихся в ОП начального образования запрещаем 6-дневную неделю
  IF ((V$LISTVAL_ID = 5339) AND (I$VAL = 11719)) THEN
    EXCEPTION DATA_ERROR 'Для начального образования запрещен ввод 6-дневной учебной недели';

  -- Для этапов, находящихся в ОП среднего образования, при вводе длительности учебной недели
  -- обновляем этим значением длительность для всех остальных этапов в данном УП (кроме себя)
  -- Отключено в 2023 с внедрением ФОП
  /*IF (V$LISTVAL_ID = 5343 AND IS_RECURRENCE = 0) THEN
  BEGIN
    FOR
      SELECT L54.OBJ_ID
      FROM LINKS L54
      WHERE L54.OBJ_TYPE_ID = 54 AND L54.PARENT_ID = :V$PARENT_ID AND L54.DATE_DEL IS NULL AND L54.OBJ_ID <> :I$OBJ_ID
      INTO :V$OBJ_ID
    DO
    BEGIN
      -- Обновляем значение непосредственно в таблице, чтобы не зациклиться
      UPDATE OR INSERT INTO VALL
      (OBJ_ID, PARAM_ID, LISTVAL_ID, IS_DEL)
      VALUES (:V$OBJ_ID, 2837, :I$VAL, 0)
      MATCHING (OBJ_ID, PARAM_ID, IS_DEL);
      -- Вызываем рекуррентно пересчет
      EXECUTE PROCEDURE SCHOOL_WEEK_ADD(:V$OBJ_ID, :I$VAL, 1);
    END
  END*/

  -- Получаем номер параллели
  V$LISTVAL_ID = NULL;
  SELECT V381.LISTVAL_ID
  FROM VALL V381
  WHERE V381.PARAM_ID = 381 AND V381.OBJ_ID = :I$OBJ_ID AND V381.IS_DEL = 0
  INTO :V$LISTVAL_ID;

  -- Если вдруг параллель не была указана - удаляем поле предельной нагрузки
  IF(V$LISTVAL_ID IS NULL) THEN
  BEGIN
    UPDATE VALI SET IS_DEL = 1 WHERE OBJ_ID = :I$OBJ_ID AND PARAM_ID = 383 AND IS_DEL = 0;
    EXIT;
  END

  -- Пересчет поля "Предельная нагрузка (уроков в неделю)" у себя

  IF(I$VAL = 11718) THEN
  BEGIN
    -- 5-дневка
    IF(V$LISTVAL_ID IN (37, 12765)) THEN V$ULTIMATE_LOAD = 21;
    ELSE IF(V$LISTVAL_ID IN (38, 39, 40)) THEN V$ULTIMATE_LOAD = 23;
    ELSE IF(V$LISTVAL_ID = 41) THEN V$ULTIMATE_LOAD = 29;
    ELSE IF(V$LISTVAL_ID = 42) THEN V$ULTIMATE_LOAD = 30;
    ELSE IF(V$LISTVAL_ID = 43) THEN V$ULTIMATE_LOAD = 32;
    ELSE IF(V$LISTVAL_ID IN (44, 45)) THEN V$ULTIMATE_LOAD = 33;
    ELSE IF(V$LISTVAL_ID IN (46, 47, 48)) THEN V$ULTIMATE_LOAD = 34;
    ELSE V$ULTIMATE_LOAD = 0;
  END
  ELSE
  BEGIN
    -- 6-дневка
    IF(V$LISTVAL_ID IN (38, 39, 40)) THEN V$ULTIMATE_LOAD = 26;
    ELSE IF(V$LISTVAL_ID = 41) THEN V$ULTIMATE_LOAD = 32;
    ELSE IF(V$LISTVAL_ID = 42) THEN V$ULTIMATE_LOAD = 33;
    ELSE IF(V$LISTVAL_ID = 43) THEN V$ULTIMATE_LOAD = 35;
    ELSE IF(V$LISTVAL_ID IN (44, 45)) THEN V$ULTIMATE_LOAD = 36;
    ELSE IF(V$LISTVAL_ID IN (46, 47, 48)) THEN V$ULTIMATE_LOAD = 37;
    ELSE V$ULTIMATE_LOAD = 0;
  END

  -- Адаптированные УП УО - свои часы
  IF(V$ADAPT = 13273) THEN
  BEGIN
    IF(V$LISTVAL_ID IN (37, 12765)) THEN V$ULTIMATE_LOAD = 21;
    ELSE IF(V$LISTVAL_ID IN (38, 39, 40)) THEN V$ULTIMATE_LOAD = 23;
    ELSE IF(V$LISTVAL_ID = 41) THEN V$ULTIMATE_LOAD = 29;
    ELSE IF(V$LISTVAL_ID = 42) THEN V$ULTIMATE_LOAD = 30;
    ELSE IF(V$LISTVAL_ID IN (43, 44, 45)) THEN V$ULTIMATE_LOAD = 30;
    ELSE IF(V$LISTVAL_ID IN (46, 47, 48)) THEN V$ULTIMATE_LOAD = 30;
  END

  SELECT BLOB_ID FROM VAL_ADD(383, :I$OBJ_ID, :V$ULTIMATE_LOAD) INTO :V$BLOB_ID;

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SCUD_STREAM_EXPORT (
    I$USER_ID BIGINT = null)
RETURNS (
    TAG_NAME VARCHAR(255),
    VAL VARCHAR(4000))
AS
declare variable V$PUPIL_ID bigint;
declare variable V$CLASS_ID bigint;
declare variable V$LASTNAME varchar(1000);
declare variable V$FIRSTNAME varchar(1000);
declare variable V$MIDDLENAME varchar(1000);
declare variable V$SNILS varchar(1000);
declare variable V$DOB date;
declare variable V$BENEFIT_CODE bigint;
declare variable V$BENEFIT_DATE date;
BEGIN
    FOR
        SELECT L10.OBJ_ID,
               V55.VAL,
               V56.VAL,
               V57.VAL,
               V1409.VAL,
               L10.PARENT_ID,
               V89.VAL,
               LV2091.COST,
               V2092.VAL
        FROM LINKS L10

        JOIN VALS V55
        ON V55.OBJ_ID = L10.OBJ_ID
        AND V55.PARAM_ID = 55
        AND V55.IS_DEL = 0

        JOIN VALS V56
        ON V56.OBJ_ID = L10.OBJ_ID
        AND V56.PARAM_ID = 56
        AND V56.IS_DEL = 0

        LEFT JOIN VALD V89
        ON V89.OBJ_ID = L10.OBJ_ID
        AND V89.PARAM_ID = 89
        AND V89.IS_DEL = 0

        LEFT JOIN VALS V57
        ON V57.OBJ_ID = L10.OBJ_ID
        AND V57.PARAM_ID = 57
        AND V57.IS_DEL = 0

        LEFT JOIN VALS V1409
        ON V1409.OBJ_ID = L10.OBJ_ID
        AND V1409.PARAM_ID = 1409
        AND V1409.IS_DEL = 0

        LEFT JOIN VALL V2091
        ON V2091.OBJ_ID = L10.OBJ_ID
        AND V2091.PARAM_ID = 2091
        AND V2091.IS_DEL = 0

        LEFT JOIN LISTVALS LV2091
        ON LV2091.LISTVAL_ID = V2091.LISTVAL_ID

        LEFT JOIN VALD V2092
        ON V2092.OBJ_ID = L10.OBJ_ID
        AND V2092.PARAM_ID = 2092
        AND V2092.IS_DEL = 0

        WHERE L10.PARENT_TYPE_ID IN (9,187,125)
        AND L10.OBJ_TYPE_ID = 10
        AND L10.DATE_DEL IS NULL

        AND EXISTS(
            SELECT FIRST 1 1

            FROM LINKS L
    
            JOIN VALS V1
            ON V1.OBJ_ID = L.EXT_OBJ_ID
            AND V1.PARAM_ID = 1570
            AND V1.IS_DEL = 0
    
            JOIN VALS V2
            ON V2.OBJ_ID = L.OBJ_ID
            AND V2.PARAM_ID = 155
            AND V2.IS_DEL = 0
    
            WHERE L.PARENT_ID = L10.OBJ_ID
            AND L.OBJ_TYPE_ID = 20
            AND L.DATE_DEL IS NULL
        )
        INTO :V$PUPIL_ID,
             :V$LASTNAME,
             :V$FIRSTNAME,
             :V$MIDDLENAME,
             :V$SNILS,
             :V$CLASS_ID,
             :V$DOB,
             :V$BENEFIT_CODE,
             :V$BENEFIT_DATE
    DO
    BEGIN
        VAL = V$PUPIL_ID;
        TAG_NAME = 'pupils:pupil:suid';
        SUSPEND;

        VAL = V$LASTNAME;
        TAG_NAME = 'pupils:pupil:surname';
        SUSPEND;

        VAL = V$FIRSTNAME;
        TAG_NAME = 'pupils:pupil:name';
        SUSPEND;

        VAL = V$MIDDLENAME;
        TAG_NAME = 'pupils:pupil:patronymic';
        SUSPEND;

        VAL = V$SNILS;
        TAG_NAME = 'pupils:pupil:snils';
        SUSPEND;

        FOR
            SELECT REPLACE(CAPTION, ' ', '')
            FROM OBJECT_CAPTION_GET(:V$CLASS_ID)
            INTO :VAL
        DO
        BEGIN
            TAG_NAME = 'pupils:pupil:class';
            SUSPEND;
        END

        VAL = V$DOB;
        TAG_NAME = 'pupils:pupil:dob';
        SUSPEND;

        IF (CHAR_LENGTH(V$BENEFIT_CODE) > 0) THEN
        BEGIN
            VAL = V$BENEFIT_CODE;
            TAG_NAME = 'pupils:pupil:benefit:code';
            SUSPEND;
    
            VAL = V$BENEFIT_DATE;
            TAG_NAME = 'pupils:pupil:benefit:date';
            SUSPEND;
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SDOCS_ADD_PERSON (
    I$NAME_LAST VARCHAR(400),
    I$NAME_FIRST VARCHAR(400),
    I$NAME_MID VARCHAR(400),
    I$BIRTH_DATE DATE,
    I$SNILS VARCHAR(40),
    I$GRAD_YEAR INTEGER,
    I$FINAL_FL SMALLINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    OBJ_ID BIGINT)
AS
DECLARE VARIABLE V$OUT_FOLDER BIGINT;
DECLARE VARIABLE V$OUT_TYPE BIGINT;
DECLARE VARIABLE V$OUT BIGINT;
DECLARE VARIABLE V$SK BIGINT;
DECLARE VARIABLE V$ST BIGINT;
DECLARE VARIABLE V$LAST_STAGE_ID BIGINT;
DECLARE VARIABLE V$OUT_LEVEL BIGINT;
DECLARE VARIABLE V$START_YEAR INTEGER;
DECLARE VARIABLE V$END_YEAR INTEGER;
DECLARE VARIABLE TMP BIGINT;
begin

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  -- На всякий случай проверяем, что такой персоны еще нет
  IF(I$SNILS IS NOT NULL) THEN
  BEGIN
    IF(EXISTS(
      SELECT FIRST 1 1
      FROM VALS V1409
      JOIN LINKS LPG ON LPG.OBJ_ID = V1409.OBJ_ID AND LPG.PARENT_TYPE_ID IN (9, 187, 81, 82, 83, 84) AND LPG.DATE_DEL IS NULL
      WHERE V1409.PARAM_ID = 1409 AND V1409.IS_DEL = 0 AND V1409.SVAL = :I$SNILS
    ))
    THEN EXCEPTION DATA_ERROR 'По указанному СНИЛС в системе найдена персона. Нельзя добавлять другую персону с тем же СНИЛС';
  END

  SELECT FIRST 1 L78.OBJ_ID, V10.LISTVAL_ID, V11.LISTVAL_ID
  FROM LINKS L2
  LEFT JOIN VALL V10 ON V10.OBJ_ID = L2.OBJ_ID AND V10.PARAM_ID = 10 AND V10.IS_DEL = 0
  LEFT JOIN VALL V11 ON V11.OBJ_ID = L2.OBJ_ID AND V11.PARAM_ID = 11 AND V11.IS_DEL = 0
  JOIN LINKS L78 ON L78.PARENT_ID = L2.OBJ_ID AND L78.OBJ_TYPE_ID = 78 AND L78.DATE_DEL IS NULL
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$OUT_FOLDER, :V$SK, :V$ST;

  IF(V$OUT_FOLDER IS NULL) THEN EXCEPTION DATA_ERROR 'Каталог выбывших и окончивших не найден';

  SELECT FIRST 1 LV.LISTVAL_ID
  FROM LINKS L2
  JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID IN (7, 502) AND L7.DATE_DEL IS NULL
  JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
  JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
  JOIN LISTVALS LV ON LV.IS_REPL = V49.LISTVAL_ID
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  ORDER BY LV.COST DESC
  INTO :V$LAST_STAGE_ID;

  V$END_YEAR = I$GRAD_YEAR;
  V$START_YEAR = I$GRAD_YEAR - 1;

  -- Если делается дубликат аттестата, значит человек или окончил школу, или выбыл посередине, получив аттестат уровня ООО
  IF((V$ST = 954) OR (V$SK IN (961, 2213)) OR (V$LAST_STAGE_ID = 40)) THEN
  BEGIN
    -- Каталог = окончившие, начальная школа
    V$OUT_TYPE = 81;
    V$OUT_LEVEL = 22;
  END
  ELSE IF(V$SK IN (962, 2214)) THEN
  BEGIN
    -- Каталог = окончившие, основная школа
    V$OUT_TYPE = 81;
    V$OUT_LEVEL = 26;
  END
  ELSE IF(I$FINAL_FL = 1) THEN
  BEGIN
    -- Просто выпуск, уровень тут не указывается
    -- Сюда попадаем в случае аттестата СОО
    V$OUT_TYPE = 83;
    V$START_YEAR = NULL;
  END
  ELSE BEGIN
    -- Выбывшие
    V$OUT_TYPE = 82;
  END

  SELECT FIRST 1 L.OBJ_ID
  FROM LINKS L
  LEFT JOIN VALL V443 ON V443.OBJ_ID = L.OBJ_ID AND V443.PARAM_ID IN (443, 447, 450) AND V443.IS_DEL = 0 -- тип, уровень
  LEFT JOIN VALI V444 ON V444.OBJ_ID = L.OBJ_ID AND V444.PARAM_ID IN (444, 448) AND V444.IS_DEL = 0 -- год начала
  LEFT JOIN VALI V445 ON V445.OBJ_ID = L.OBJ_ID AND V445.PARAM_ID IN (445, 449, 451) AND V445.IS_DEL = 0 -- год окончания или выпуска
  WHERE L.PARENT_ID = :V$OUT_FOLDER AND L.OBJ_TYPE_ID = :V$OUT_TYPE AND L.DATE_DEL IS NULL
    AND (:V$OUT_LEVEL IS NULL OR V443.LISTVAL_ID = :V$OUT_LEVEL)
    AND (:V$START_YEAR IS NULL OR V444.VAL = :V$START_YEAR)
    AND (:V$END_YEAR IS NULL OR V445.VAL = :V$END_YEAR)
  INTO :V$OUT;

  IF(V$OUT IS NULL) THEN
  BEGIN
    SELECT OBJ_ID FROM OBJECT_ADD(:V$OUT_FOLDER, :V$OUT_TYPE) INTO :V$OUT;
    IF(V$OUT_LEVEL IS NOT NULL) THEN SELECT BLOB_ID FROM VAL_ADD(CASE :V$OUT_TYPE WHEN 81 THEN 443 WHEN 82 THEN 447 ELSE 450 END, :V$OUT, :V$OUT_LEVEL) INTO :TMP;
    IF(V$START_YEAR IS NOT NULL AND V$OUT_TYPE <> 83) THEN SELECT BLOB_ID FROM VAL_ADD(CASE :V$OUT_TYPE WHEN 81 THEN 444 ELSE 448 END, :V$OUT, :V$START_YEAR) INTO :TMP;
    IF(V$END_YEAR IS NOT NULL) THEN SELECT BLOB_ID FROM VAL_ADD(CASE :V$OUT_TYPE WHEN 81 THEN 445 WHEN 82 THEN 449 ELSE 451 END, :V$OUT, :V$END_YEAR) INTO :TMP;
  END

  SELECT OBJ_ID
  FROM OBJECT_ADD(:V$OUT, 10, NULL, NULL, :I$USER_ID)
  INTO :OBJ_ID;

  SELECT BLOB_ID FROM VAL_ADD(55, :OBJ_ID, :I$NAME_LAST) INTO :TMP;
  SELECT BLOB_ID FROM VAL_ADD(56, :OBJ_ID, :I$NAME_FIRST) INTO :TMP;
  SELECT BLOB_ID FROM VAL_ADD(57, :OBJ_ID, :I$NAME_MID) INTO :TMP;
  SELECT BLOB_ID FROM VAL_ADD(89, :OBJ_ID, :I$BIRTH_DATE) INTO :TMP;
  SELECT BLOB_ID FROM VAL_ADD(1409, :OBJ_ID, :I$SNILS) INTO :TMP;

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SDOCS_APPLY_DOC (
    I$PERSON_ID BIGINT,
    I$DOC_ID BIGINT,
    I$DOC_TYPE_ID BIGINT,
    I$ORDER_ID BIGINT,
    V$SERIE VARCHAR(40),
    V$NUM VARCHAR(40),
    I$RN INTEGER,
    I$STATUS BIGINT)
AS
declare variable N integer;
declare variable V$OBJ_ID bigint;
declare variable V$DATE date;
declare variable V$CODE varchar(1000);
declare variable V$DT bigint;
declare variable V$TYPE_ID bigint;
begin

  IF(I$DOC_TYPE_ID = 5377) THEN V$TYPE_ID = 1375; -- ООО
  ELSE IF(I$DOC_TYPE_ID = 5378) THEN V$TYPE_ID = 3241;
  ELSE IF(I$DOC_TYPE_ID = 5379) THEN V$TYPE_ID = 1376; -- СОО
  ELSE IF(I$DOC_TYPE_ID = 5380) THEN V$TYPE_ID = 3240;
  ELSE IF(I$DOC_TYPE_ID = 12766) THEN V$TYPE_ID = 1380; -- СПО
  ELSE IF(I$DOC_TYPE_ID = 12767) THEN V$TYPE_ID = 12785;
  ELSE IF(I$DOC_TYPE_ID = 5385) THEN V$TYPE_ID = 1382; -- свидетельство
  ELSE EXIT;

  -- Нет ли уже этого документа в системе ?
  SELECT FIRST 1 L11.OBJ_ID
  FROM LINKS L11
  JOIN VALI V569 ON V569.OBJ_ID = L11.OBJ_ID AND V569.PARAM_ID = 569 AND V569.IS_DEL = 0 AND V569.VAL = :I$DOC_ID
  WHERE L11.PARENT_ID = :I$PERSON_ID AND L11.OBJ_TYPE_ID = 11 AND L11.DATE_DEL IS NULL
  INTO :V$OBJ_ID;

  SELECT FIRST 1 D.ACTION_DATE
  FROM ORDERS D
  WHERE D.DATE_DEL IS NULL AND D.OBJ_ID = :I$ORDER_ID
  INTO :V$DATE;

  IF(V$OBJ_ID IS NULL) THEN
  SELECT OBJ_ID FROM OBJECT_ADD(:I$PERSON_ID, 11) INTO :V$OBJ_ID;

  SELECT 1 FROM VAL_ADD(50, :V$OBJ_ID, :V$TYPE_ID) INTO :N;

  IF(I$DOC_TYPE_ID IN (5378, 5380, 12767)) THEN V$DT = 2193; ELSE V$DT = 2192;

  SELECT 1 FROM VAL_ADD(705, :V$OBJ_ID, :V$DT) INTO :N;
  SELECT 1 FROM VAL_ADD(564, :V$OBJ_ID, :V$SERIE) INTO :N;
  SELECT 1 FROM VAL_ADD(565, :V$OBJ_ID, :V$NUM) INTO :N;
  SELECT 1 FROM VAL_ADD(566, :V$OBJ_ID, :V$DATE) INTO :N;

  SELECT FIRST 1 TAG FROM LISTVALS LV WHERE LV.LISTVAL_ID = :I$DOC_TYPE_ID INTO :V$CODE;
  SELECT 1 FROM VAL_ADD(567, :V$OBJ_ID, :V$CODE) INTO :N;

  -- Название ОУ
  V$CODE = NULL;
  SELECT FIRST 1 V5.VAL
  FROM LINKS L2
  JOIN VALS V5 ON V5.OBJ_ID = L2.OBJ_ID AND V5.PARAM_ID = 5 AND V5.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$CODE;

  SELECT 1 FROM VAL_ADD(568, :V$OBJ_ID, :V$CODE) INTO :N;

  SELECT 1 FROM VAL_ADD(2969, :V$OBJ_ID, :I$RN) INTO :N;

  SELECT 1 FROM VAL_ADD(2458, :V$OBJ_ID, :I$STATUS) INTO :N;

  SELECT 1 FROM VAL_ADD(569, :V$OBJ_ID, :I$DOC_ID) INTO :N;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SDOCS_APPLY_DUB (
    I$PERSON_ID BIGINT,
    I$DOC_ID BIGINT,
    I$PREV_DOC_ID BIGINT)
AS
declare variable V$OBJ_ID bigint;
declare variable V$PREV_ID bigint;
declare variable V$OBJ_STATE bigint;
declare variable V$PREV_STATE bigint;
declare variable N integer;
begin

  SELECT FIRST 1 L11.OBJ_ID, V2458.LISTVAL_ID
  FROM LINKS L11
  JOIN VALI V569 ON V569.OBJ_ID = L11.OBJ_ID AND V569.PARAM_ID = 569 AND V569.IS_DEL = 0 AND V569.VAL = :I$DOC_ID
  LEFT JOIN VALL V2458 ON V2458.OBJ_ID = L11.OBJ_ID AND V2458.PARAM_ID = 2458 AND V2458.IS_DEL = 0
  WHERE L11.PARENT_ID = :I$PERSON_ID AND L11.OBJ_TYPE_ID = 11 AND L11.DATE_DEL IS NULL
  INTO :V$OBJ_ID, :V$OBJ_STATE;

  SELECT FIRST 1 L11.OBJ_ID, V2458.LISTVAL_ID
  FROM LINKS L11
  JOIN VALI V569 ON V569.OBJ_ID = L11.OBJ_ID AND V569.PARAM_ID = 569 AND V569.IS_DEL = 0 AND V569.VAL = :I$PREV_DOC_ID
  LEFT JOIN VALL V2458 ON V2458.OBJ_ID = L11.OBJ_ID AND V2458.PARAM_ID = 2458 AND V2458.IS_DEL = 0
  WHERE L11.PARENT_ID = :I$PERSON_ID AND L11.OBJ_TYPE_ID = 11 AND L11.DATE_DEL IS NULL
  INTO :V$PREV_ID, :V$PREV_STATE;

  IF(V$OBJ_ID IS NOT NULL AND COALESCE(V$OBJ_STATE, 0) <> 5440) THEN
  SELECT 1 FROM VAL_ADD(2458, :V$OBJ_ID, 5440) INTO :N;

  IF(V$PREV_ID IS NOT NULL AND COALESCE(V$PREV_STATE, 0) <> 5441) THEN
  SELECT 1 FROM VAL_ADD(2458, :V$PREV_ID, 5441) INTO :N;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SDOCS_BLANK_GET (
    I$LEVEL_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
declare variable V$ID bigint;
declare variable V$TEXT varchar(1000);
declare variable V$T bigint;
begin

  -- Функционал утрачен, перенос в DOC

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SDOCS_CHANGE_TYPE (
    I$ORDER_ID BIGINT,
    I$DOC_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$TYPE_ID bigint;
declare variable V$STATE_ID bigint;
declare variable V$PERSON_ID bigint;
declare variable V$SRC_ID bigint;
declare variable V$DATA_ID bigint;
declare variable V$BLANK_ID bigint;
declare variable V$DOC_STATE bigint;
declare variable V$DT_ID bigint;
declare variable V varchar(400);
begin

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  SELECT MON$DATABASE_NAME
  FROM MON$DATABASE
  INTO :V;

  V = REPLACE(V, 'BASE.FDB', 'DOC.FDB');

  SELECT D.TYPE_ID, D.STATE_ID, D.SUBTYPE_ID
  FROM ORDERS D
  WHERE D.OBJ_ID = :I$ORDER_ID AND D.DATE_DEL IS NULL
  INTO :V$TYPE_ID, :V$STATE_ID, :V$DT_ID;

  IF(V$TYPE_ID IS NULL OR V$TYPE_ID <> 13326) THEN EXCEPTION DATA_ERROR 'Приказ не найден или недопустимый тип приказа';
  IF(V$STATE_ID <> 11716) THEN EXCEPTION DATA_ERROR 'Приказ должен находиться в статусе проекта';

  -- Получаем данные документа
  EXECUTE STATEMENT
    'SELECT FIRST 1 ORDER_ID, PERSON_ID, BLANK_ID, STATE_ID
    FROM DOCUMENTS
    WHERE DATE_DEL IS NULL AND OBJ_ID = ' || I$DOC_ID
  ON EXTERNAL :V
  WITH COMMON TRANSACTION
  INTO :V$SRC_ID, :V$PERSON_ID, :V$BLANK_ID, :V$DOC_STATE;

  IF(V$BLANK_ID IS NOT NULL) THEN EXCEPTION DATA_ERROR 'В документе уже выбран бланк, сменить тип нельзя';
  IF(V$DOC_STATE > 1) THEN EXCEPTION DATA_ERROR 'Недопустимый статус документа';
  IF(V$SRC_ID = I$ORDER_ID) THEN EXCEPTION DATA_ERROR 'Выбран тот же приказ, что и уже указан в документе';

  SELECT FIRST 1 OD.OBJ_ID
  FROM ORDER_DATA OD
  WHERE OD.ORDER_ID = :V$SRC_ID AND OD.DATE_DEL IS NULL AND OD.REF_ID = :V$PERSON_ID
  INTO :V$DATA_ID;

  IF(V$DATA_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Обучающийся не числится в первоначальном приказе';

  UPDATE ORDER_DATA
  SET ORDER_ID = :I$ORDER_ID
  WHERE OBJ_ID = :V$DATA_ID;

  -- Обновляем документ
  EXECUTE STATEMENT
    'UPDATE DOCUMENTS
    SET ORDER_ID = ' || I$ORDER_ID || ', DOC_TYPE_ID = ' || V$DT_ID || '
    WHERE OBJ_ID = ' || I$DOC_ID
  ON EXTERNAL :V
  WITH COMMON TRANSACTION;

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SDOCS_DELETE_ORDER (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
AS
DECLARE VARIABLE V$STATE_ID BIGINT;
DECLARE VARIABLE DB VARCHAR(400);
DECLARE VARIABLE N INTEGER;
begin

  SELECT D.STATE_ID
  FROM ORDERS D
  WHERE D.DATE_DEL IS NULL AND D.OBJ_ID = :I$OBJ_ID AND D.TYPE_ID = 13326
  INTO :V$STATE_ID;

  IF(V$STATE_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Запись не найдена';

  SELECT MON$DATABASE_NAME FROM MON$DATABASE INTO :DB;
  DB = REPLACE(DB, 'BASE.FDB', 'DOC.FDB');

  EXECUTE STATEMENT 'SELECT COUNT(*) FROM DOCUMENTS WHERE ORDER_ID = ' || :I$OBJ_ID || ' AND DATE_DEL IS NULL'
  ON EXTERNAL :DB
  WITH COMMON TRANSACTION
  INTO :N;

  IF(N > 0) THEN EXCEPTION DATA_ERROR 'К данному приказу есть прикрепленные аттестаты, нельзя удалить';

  IF(V$STATE_ID = 11715) THEN
  BEGIN
    -- Утвержденный приказ нельзя удалить, поэтому переводим в не-действующий
    UPDATE ORDERS
    SET STATE_ID = 11717
    WHERE OBJ_ID = :I$OBJ_ID;
  END

  EXECUTE PROCEDURE ORDER_DELETE(:I$OBJ_ID, :I$USER_ID);

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SDOCS_DOCUMENT_GET (
    I$PERSON_ID BIGINT,
    I$DOC_TYPE_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(4000))
AS
DECLARE VARIABLE S0 VARCHAR(4000);
DECLARE VARIABLE S1 VARCHAR(4000);
DECLARE VARIABLE S2 VARCHAR(4000);
DECLARE VARIABLE S3 VARCHAR(4000);
DECLARE VARIABLE V$UO VARCHAR(400);
DECLARE VARIABLE V$QUAL VARCHAR(400);
DECLARE VARIABLE V$STAGE_ID BIGINT;
DECLARE VARIABLE V$PARAM_ID BIGINT;
DECLARE VARIABLE V$PARAM_ID2 BIGINT;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$STATE BIGINT;
DECLARE VARIABLE V$LIC_TYPE CHAR(1);
DECLARE VARIABLE V$DUR INTEGER;
DECLARE VARIABLE V$Y INTEGER;
DECLARE VARIABLE V$M INTEGER;
DECLARE VARIABLE V$SUBTYPE_ID BIGINT;
DECLARE VARIABLE V$GRADE_ID BIGINT;
DECLARE VARIABLE V$PL BIGINT;
DECLARE VARIABLE V$OU_ID BIGINT;
DECLARE VARIABLE V$HAS_OO SMALLINT;
DECLARE VARIABLE V$HAS_SPO SMALLINT;
begin

  TAG_NAME = 'lic_type';
  V$LIC_TYPE = (SELECT STATUS FROM OU_LICENCE_TYPE);
  VAL = V$LIC_TYPE;
  SUSPEND;

  SELECT FIRST 1 L2.OBJ_ID
  FROM LINKS L2
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$OU_ID;

  V$HAS_OO = 0;
  V$HAS_SPO = 0;
  SELECT FIRST 1 1
  FROM LINKS L472
  JOIN VALL V3327 ON V3327.OBJ_ID = L472.OBJ_ID AND V3327.PARAM_ID = 3327 AND V3327.IS_DEL = 0 AND V3327.LISTVAL_ID IN (22, 26, 27)
  WHERE L472.PARENT_ID = :V$OU_ID AND L472.OBJ_TYPE_ID = 472 AND L472.DATE_DEL IS NULL
  INTO :V$HAS_OO;

  SELECT FIRST 1 1
  FROM LINKS L472
  JOIN VALL V3327 ON V3327.OBJ_ID = L472.OBJ_ID AND V3327.PARAM_ID = 3327 AND V3327.IS_DEL = 0 AND V3327.LISTVAL_ID IN (28, 29, 13129)
  WHERE L472.PARENT_ID = :V$OU_ID AND L472.OBJ_TYPE_ID = 472 AND L472.DATE_DEL IS NULL
  INTO :V$HAS_SPO;

  -- person_id тут не выдается, его выдает процедура из DOC

  TAG_NAME = 'name_last_org';
  VAL = NULL;
  SELECT V.VAL
  FROM VALS V
  WHERE V.OBJ_ID = :I$PERSON_ID AND V.PARAM_ID IN (55, 827) AND V.IS_DEL = 0
  INTO :VAL;
  IF(VAL IS NULL) THEN EXCEPTION DATA_ERROR 'ФИО персоны или сама персона не найдены';
  SUSPEND;

  TAG_NAME = 'name_first_org';
  VAL = NULL;
  SELECT V.VAL
  FROM VALS V
  WHERE V.OBJ_ID = :I$PERSON_ID AND V.PARAM_ID IN (56, 828) AND V.IS_DEL = 0
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'name_mid_org';
  VAL = NULL;
  SELECT V.VAL
  FROM VALS V
  WHERE V.OBJ_ID = :I$PERSON_ID AND V.PARAM_ID IN (57, 829) AND V.IS_DEL = 0
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'reg_id';
  VAL = NULL;
  SELECT V.VAL
  FROM VALS V
  WHERE V.OBJ_ID = :I$PERSON_ID AND V.PARAM_ID = 2912 AND V.IS_DEL = 0
  INTO :VAL;
  IF(POSITION(':' IN VAL) > 0) THEN VAL = SUBSTRING(VAL FROM 1 FOR POSITION(':' IN VAL) - 1);
  SUSPEND;

  TAG_NAME = 'birth_date_org';
  VAL = NULL;
  SELECT D.VAL
  FROM VALD V
  LEFT JOIN DATE2ISO(V.VAL, 0) D ON 1 = 1
  WHERE V.OBJ_ID = :I$PERSON_ID AND V.PARAM_ID IN (89, 830) AND V.IS_DEL = 0
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'grade_id';
  VAL = NULL;
  SELECT FIRST 1 LPG.PARENT_ID
  FROM LINKS LPG
  WHERE LPG.OBJ_ID = :I$PERSON_ID AND LPG.PARENT_TYPE_ID IN (9, 187, 125) AND LPG.DATE_DEL IS NULL
  INTO :V$GRADE_ID;
  VAL = V$GRADE_ID;
  SUSPEND;

  TAG_NAME = 'grade_name';
  IF(V$OBJ_ID IS NOT NULL) THEN VAL = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$GRADE_ID)); ELSE VAL = NULL;
  SUSPEND;

  -- Наличие и тип медали - актуально только для СОО
  TAG_NAME = 'medal';
  VAL = NULL;
  SELECT FIRST 1 V3479.LISTVAL_ID
  FROM VALL V3479
  WHERE V3479.OBJ_ID = :I$PERSON_ID AND V3479.PARAM_ID = 3479 AND V3479.IS_DEL = 0
  INTO :VAL;
  SUSPEND;

  -- Данные по текущему проекту приказа, пока сам аттестат еще не существует
  TAG_NAME = 'order_id_org';
  VAL = NULL;
  SELECT FIRST 1 D.OBJ_ID, D.DETAILS_TEXT, D.PROJECT_NUM, DD.VAL, DA.VAL, D.SUBTYPE_ID
  FROM ORDERS D
  JOIN ORDER_DATA OD ON OD.DATE_DEL IS NULL AND OD.ORDER_ID = D.OBJ_ID AND OD.REF_ID = :I$PERSON_ID
  LEFT JOIN DATE2ISO(D.ORDER_DATE, 0) DD ON 1 = 1
  LEFT JOIN DATE2ISO(D.ACTION_DATE, 0) DA ON 1 = 1
  WHERE D.DATE_DEL IS NULL AND D.TYPE_ID = 13326 AND D.STATE_ID = 11716
  INTO :VAL, :S0, :S1, :S2, :S3, :V$SUBTYPE_ID;
  SUSPEND;

  TAG_NAME = 'order_comments_org';
  VAL = S0;
  SUSPEND;

  TAG_NAME = 'doc_type_org';
  VAL = V$SUBTYPE_ID;
  SUSPEND;

  TAG_NAME = 'order_project_num_org';
  VAL = S1;
  SUSPEND;

  TAG_NAME = 'order_date_org';
  VAL = S2;
  SUSPEND;

  TAG_NAME = 'print_date_org';
  VAL = S3;
  SUSPEND;

  -- Темы проекта выбираем между НОО-ООО, СПО и дипломным
  -- Если не указано, смотрим по типу приказа
  IF(I$DOC_TYPE_ID IS NULL) THEN
  SELECT FIRST 1 D.SUBTYPE_ID
  FROM ORDER_DATA OD
  JOIN ORDERS D ON D.OBJ_ID = OD.OBJ_ID AND D.DATE_DEL IS NULL AND D.TYPE_ID = 13326 AND D.STATE_ID <> 11717
  WHERE OD.DATE_DEL IS NULL AND OD.REF_ID = :I$PERSON_ID
  ORDER BY D.STATE_ID, D.ORDER_DATE DESC
  INTO :I$DOC_TYPE_ID;

  IF(I$DOC_TYPE_ID IN (5377, 5378, 5385)) THEN BEGIN V$PARAM_ID = 3116; V$PARAM_ID2 = 3348; END
  ELSE IF(I$DOC_TYPE_ID IN (5379, 5380)) THEN BEGIN V$PARAM_ID = 229; V$PARAM_ID2 = 3162; END
  ELSE IF(I$DOC_TYPE_ID IN (12766, 12767)) THEN V$PARAM_ID = 3328;
  ELSE BEGIN V$PARAM_ID = 229; V$PARAM_ID2 = 3162; END

  TAG_NAME = 'project_theme_org';
  VAL = NULL;
  SELECT V.VAL
  FROM VALS V
  WHERE V.OBJ_ID = :I$PERSON_ID AND (V.PARAM_ID = :V$PARAM_ID OR V.PARAM_ID = :V$PARAM_ID2) AND V.IS_DEL = 0
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'dx_theme_org';
  VAL = NULL;
  SELECT V.VAL
  FROM VALS V
  WHERE V.OBJ_ID = :I$PERSON_ID AND V.PARAM_ID = 3360 AND V.IS_DEL = 0
  INTO :VAL;
  SUSPEND;

  S0 = NULL;
  S1 = NULL;
  SELECT FIRST 1 R.VAL, COALESCE(V2822.VAL, LV.TAG), RP.VAL, V3195.VAL, V3198.VAL, LVP.LIST_ID
  FROM LINKS LP9
  JOIN VALL V2165 ON V2165.OBJ_ID = LP9.PARENT_ID AND V2165.PARAM_ID IN (2165, 2821, 3367) AND V2165.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V2165.LISTVAL_ID
  JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
  -- Код профессии или специальности
  LEFT JOIN VALS V2822 ON V2822.OBJ_ID = LP9.PARENT_ID AND V2822.PARAM_ID = 2822 AND V2822.IS_DEL = 0
  JOIN LISTVALS LVP ON LVP.LISTVAL_ID = LV.PARENT_ID
  JOIN RES RP ON RP.RES_ID = LVP.RES_ID AND RP.LANG_CODE = 'RU'
  LEFT JOIN VALS V3195 ON V3195.OBJ_ID = LP9.PARENT_ID AND V3195.PARAM_ID = 3195 AND V3195.IS_DEL = 0
  LEFT JOIN VALS V3198 ON V3198.OBJ_ID = LP9.PARENT_ID AND V3198.PARAM_ID = 3198 AND V3198.IS_DEL = 0
  WHERE LP9.OBJ_ID = :I$PERSON_ID AND LP9.PARENT_TYPE_ID = 9 AND LP9.DATE_DEL IS NULL
  INTO :S0, :S1, :S2, :V$QUAL, :V$UO, :V$PL;

  -- Для ОКПДТР разделы имеют другую структуру
  IF(V$PL = 352) THEN S2 = 'Профессия';

  TAG_NAME = 'prof_org';
  IF(S2 = 'Профессия') THEN VAL = S1 || ' ' || S0; ELSE VAL = NULL;
  SUSPEND;

  TAG_NAME = 'spec_org';
  IF(S2 = 'Специальность') THEN VAL = S1 || ' ' || S0; ELSE VAL = NULL;
  SUSPEND;

  TAG_NAME = 'prev_doc_org';
  VAL = NULL;
  SUSPEND;

  SELECT FIRST 1 V.VAL
  FROM LINKS LP256
  JOIN LINKS LP54 ON LP54.OBJ_ID = LP256.PARENT_ID AND LP54.PARENT_TYPE_ID = 54 AND LP54.DATE_DEL IS NULL
  JOIN LINKS LP400 ON LP400.OBJ_ID = LP54.PARENT_ID AND LP400.PARENT_TYPE_ID = 400 AND LP400.DATE_DEL IS NULL
  JOIN VALI V ON V.OBJ_ID = LP400.PARENT_ID AND V.PARAM_ID = 3352 AND V.IS_DEL = 0
  WHERE LP256.OBJ_ID = :I$PERSON_ID AND LP256.PARENT_TYPE_ID = 256 AND LP256.DATE_DEL IS NULL
  INTO :V$DUR;

  IF(V$DUR IS NULL) THEN
  SELECT FIRST 1 V.VAL
  FROM LINKS LP9
  JOIN VALI V ON V.OBJ_ID = LP9.PARENT_ID AND V.PARAM_ID = 3353 AND V.IS_DEL = 0
  WHERE LP9.OBJ_ID = :I$PERSON_ID AND LP9.PARENT_TYPE_ID = 9
  ORDER BY LP9.DATE_DEL DESC NULLS FIRST
  INTO :V$DUR;

  TAG_NAME = 'op_dur_org';
  VAL = NULL;
  IF(V$DUR IS NOT NULL) THEN
  BEGIN
    V$Y = V$DUR / 12;
    V$M = V$DUR - V$Y * 12;
    IF(V$Y = 1) THEN VAL = '1 год';
    ELSE IF(V$Y IN (2, 3, 4)) THEN VAL = V$Y || ' года';
    ELSE VAL = V$Y || ' лет';

    IF(V$M = 1) THEN VAL = VAL || ' ' || '1 месяц';
    ELSE IF(V$M IN (2, 3, 4)) THEN VAL = VAL || ' ' || V$M || ' месяца';
    ELSE VAL = VAL || ' ' || V$M || ' месяцев';
  END
  SUSPEND;

  TAG_NAME = 'uo_org';
  VAL = V$UO;
  SUSPEND;

  TAG_NAME = 'qual_org';
  VAL = V$QUAL;
  SUSPEND;

  TAG_NAME = 'doc_types::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT C.LISTVAL_ID, C.VAL
    FROM LISTVALS_LIST(256) C
    WHERE C.IS_DEL = 0 AND ((:V$HAS_OO = 1 AND C.LISTVAL_ID IN (5377, 5378, 5379, 5380, 5385)) OR (:V$HAS_SPO = 1 AND C.LISTVAL_ID IN (5379, 5380, 12766, 12767)))
    ORDER BY C.SORT_ORDER
    INTO :V$OBJ_ID, :S1
  DO
  BEGIN
    TAG_NAME = 'doc_types:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'doc_types:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'doc_types:r:value';
    VAL = S1;
    SUSPEND;
    TAG_NAME = 'doc_types:r:stage_id';
    IF(V$OBJ_ID IN (5377, 5378)) THEN VAL = '26';
    ELSE IF(V$OBJ_ID IN (5379, 5380)) THEN VAL = '27';
    ELSE IF(V$OBJ_ID IN (5385)) THEN VAL = '26';
    ELSE IF(V$OBJ_ID IN (12766, 12767)) THEN VAL = '29';
    ELSE VAL = '';
    SUSPEND;
  END

  -- Курсовые работы
  TAG_NAME = 'projects::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L217.OBJ_ID, V1821.VAL, C.VAL
    FROM LINKS L217
    JOIN VALS V1821 ON V1821.OBJ_ID = L217.OBJ_ID AND V1821.PARAM_ID = 1821 AND V1821.IS_DEL = 0
    JOIN VALL V1825 ON V1825.OBJ_ID = L217.OBJ_ID AND V1825.PARAM_ID = 1825 AND V1825.IS_DEL = 0
    LEFT JOIN LISTVAL_TEXT(V1825.LISTVAL_ID) C ON 1 = 1
    WHERE L217.PARENT_ID = :I$PERSON_ID AND L217.OBJ_TYPE_ID = 217 AND L217.DATE_DEL IS NULL
    ORDER BY 1
    INTO :V$OBJ_ID, :S0, :S1
  DO
  BEGIN
    TAG_NAME = 'projects:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'projects:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'projects:r:name';
    VAL = S0;
    SUSPEND;
    TAG_NAME = 'projects:r:mark';
    VAL = S1;
    SUSPEND;
  END

  -- Исходные данные по практикам, копируются в диплом
  -- Собираем вместе по учебному коллективу и конкретному обучающемуся
  TAG_NAME = 'pr_org::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    -- по ученику
    SELECT 1, IIF(V3334.LISTVAL_ID = 3406, 0, 1), L474.COST, V3331.VAL, V3332.VAL, V3333.VAL
    FROM LINKS L474
    JOIN VALL V3334 ON V3334.OBJ_ID = L474.OBJ_ID AND V3334.PARAM_ID = 3334 AND V3334.IS_DEL = 0
    JOIN VALS V3331 ON V3331.OBJ_ID = L474.OBJ_ID AND V3331.PARAM_ID = 3331 AND V3331.IS_DEL = 0
    JOIN VALS V3332 ON V3332.OBJ_ID = L474.OBJ_ID AND V3332.PARAM_ID = 3332 AND V3332.IS_DEL = 0
    JOIN VALS V3333 ON V3333.OBJ_ID = L474.OBJ_ID AND V3333.PARAM_ID = 3333 AND V3333.IS_DEL = 0
    WHERE L474.PARENT_ID = :I$PERSON_ID AND L474.OBJ_TYPE_ID = 474 AND L474.DATE_DEL IS NULL
    -- по группе
    -- todo: убрать разделы, которые заменены в ученике
    UNION ALL
    SELECT 0, IIF(V3334.LISTVAL_ID = 3406, 0, 1), L474.COST, V3331.VAL, V3332.VAL, V3331.VAL
    FROM LINKS L474
    JOIN VALL V3334 ON V3334.OBJ_ID = L474.OBJ_ID AND V3334.PARAM_ID = 3334 AND V3334.IS_DEL = 0
    JOIN VALS V3331 ON V3331.OBJ_ID = L474.OBJ_ID AND V3331.PARAM_ID = 3331 AND V3331.IS_DEL = 0
    JOIN VALS V3332 ON V3332.OBJ_ID = L474.OBJ_ID AND V3332.PARAM_ID = 3332 AND V3332.IS_DEL = 0
    JOIN VALS V3333 ON V3333.OBJ_ID = L474.OBJ_ID AND V3333.PARAM_ID = 3333 AND V3333.IS_DEL = 0
    WHERE L474.PARENT_ID = :V$GRADE_ID AND L474.OBJ_TYPE_ID = 474 AND L474.DATE_DEL IS NULL
    ORDER BY 1, 2, 3
    INTO :V$OBJ_ID, :V$M, :V$Y, :S1, :S2, :S3
  DO
  BEGIN
    TAG_NAME = 'pr_org:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'pr_org:r:p';
    VAL = V$M;
    SUSPEND;
    TAG_NAME = 'pr_org:r:t';
    VAL = S1;
    SUSPEND;
    TAG_NAME = 'pr_org:r:m';
    VAL = S2;
    SUSPEND;
    TAG_NAME = 'pr_org:r:w';
    VAL = S3;
    SUSPEND;
  END

  -- Данные по демонстрационному экзамену
  TAG_NAME = 'kod_org';
  VAL = NULL;
  SELECT V.VAL
  FROM VALS V
  WHERE V.OBJ_ID = :I$PERSON_ID AND V.PARAM_ID = 3337 AND V.IS_DEL = 0
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'oe_org_org';
  VAL = NULL;
  SELECT V.VAL
  FROM VALS V
  WHERE V.OBJ_ID = :I$PERSON_ID AND V.PARAM_ID = 3338 AND V.IS_DEL = 0
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'res_val_org';
  VAL = NULL;
  SELECT CAST(V.VAL AS NUMERIC(18, 2))
  FROM VALF V
  WHERE V.OBJ_ID = :I$PERSON_ID AND V.PARAM_ID = 3341 AND V.IS_DEL = 0
  INTO :VAL;
  VAL = REPLACE(VAL, '.00', '');
  SUSPEND;

  TAG_NAME = 'max_val_org';
  VAL = NULL;
  SELECT V.VAL
  FROM VALI V
  WHERE V.OBJ_ID = :I$PERSON_ID AND V.PARAM_ID = 3342 AND V.IS_DEL = 0
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'res_lv_org';
  VAL = NULL;
  SELECT IIF(V.LISTVAL_ID = 14182, 1, 2)
  FROM VALL V
  WHERE V.OBJ_ID = :I$PERSON_ID AND V.PARAM_ID = 3340 AND V.IS_DEL = 0
  INTO :VAL;
  IF(VAL IS NULL) THEN VAL = '0';
  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SDOCS_LEVELS_LIST (
    I$LEVEL_ID INTEGER,
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    OBJ_ID BIGINT,
    NAME VARCHAR(1000),
    NAME_SHORT VARCHAR(1000),
    LEVEL_ID INTEGER,
    HAS_CHILDREN SMALLINT)
AS
DECLARE VARIABLE V$OU_LICENCE_TYPE CHAR(1);
DECLARE VARIABLE V$USER_TYPE SMALLINT;
DECLARE VARIABLE V$TEACHER_ID BIGINT;
DECLARE VARIABLE V$CLASS_ID BIGINT;
begin

  -- Назначение процедуры неясно, возможно актуальность утрачена

  IF(I$LEVEL_ID IS NULL) THEN I$LEVEL_ID = 0;
  LEVEL_ID = I$LEVEL_ID + 1;

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;
  SELECT USER_TYPE, OBJ_ID FROM USERS WHERE USER_ID = :I$USER_ID INTO :V$USER_TYPE, :V$TEACHER_ID;

  IF(V$USER_TYPE NOT IN (1, 5, 6, 8)) THEN EXCEPTION DATA_ERROR 'Для вашей роли доступ к приложению недоступен';

  IF(V$USER_TYPE = 8) THEN V$CLASS_ID = (SELECT FIRST 1 ROOT_OBJ_ID FROM LUSERS WHERE USER_ID = :I$USER_ID AND ROOT_OBJ_ID IS NOT NULL);

  -- Тип лицензии ОУ
  SELECT STATUS FROM OU_LICENCE_TYPE INTO :V$OU_LICENCE_TYPE;

  -- Выбираем уровни, которые есть в данной ОУ
  IF(I$LEVEL_ID = 0) THEN
  BEGIN
    FOR
      SELECT DISTINCT V43.LISTVAL_ID, R.VAL
      FROM LINKS L7
      JOIN VALL V43 ON V43.OBJ_ID = L7.OBJ_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0
      JOIN LISTVALS LV ON LV.LISTVAL_ID = V43.LISTVAL_ID
      JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
      WHERE L7.PARENT_TYPE_ID = 2 AND L7.OBJ_TYPE_ID IN (7, 502) AND L7.DATE_DEL IS NULL
      ORDER BY LV.COST
      INTO :OBJ_ID, :NAME
    DO
    BEGIN
      IF(OBJ_ID = 22) THEN NAME_SHORT = 'НОО';
      ELSE IF(OBJ_ID = 26) THEN NAME_SHORT = 'ООО';
      ELSE IF(OBJ_ID = 27) THEN NAME_SHORT = 'СОО';
      ELSE IF(OBJ_ID = 28) THEN NAME_SHORT = 'НПО';
      ELSE IF(OBJ_ID = 29) THEN NAME_SHORT = 'СПО';
      ELSE IF(OBJ_ID = 796) THEN NAME_SHORT = 'ВПО';
      ELSE IF(OBJ_ID = 797) THEN NAME_SHORT = 'ППО';
      ELSE NAME_SHORT = '?';

      HAS_CHILDREN = 0;
      SELECT FIRST 1 1
      FROM LINKS L7
      JOIN VALL V43 ON V43.OBJ_ID = L7.OBJ_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0 AND V43.LISTVAL_ID = :OBJ_ID
      JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
      WHERE L7.PARENT_TYPE_ID = 2 AND L7.OBJ_TYPE_ID IN (7, 502) AND L7.DATE_DEL IS NULL
      INTO :HAS_CHILDREN;

      SUSPEND;
    END
  END
  -- Параллели
  ELSE IF(I$LEVEL_ID = 1) THEN
  BEGIN
    FOR
      SELECT L8.OBJ_ID, R.VAL
      FROM LINKS L7
      JOIN VALL V43 ON V43.OBJ_ID = L7.OBJ_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0 AND V43.LISTVAL_ID = :I$OBJ_ID
      JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
      JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
      JOIN LISTVALS LV ON LV.LISTVAL_ID = V49.LISTVAL_ID
      JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
      WHERE L7.PARENT_TYPE_ID = 2 AND L7.OBJ_TYPE_ID IN (7, 502) AND L7.DATE_DEL IS NULL
      ORDER BY LV.COST
      INTO :OBJ_ID, :NAME
    DO
    BEGIN
      HAS_CHILDREN = 0;
      SELECT FIRST 1 1
      FROM LINKS L9
      WHERE L9.PARENT_ID = :OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 125, 187) AND L9.DATE_DEL IS NULL
      INTO :HAS_CHILDREN;

      SUSPEND;
    END
  END
  -- Классы - для классных руководителей ограничиваем их классами
  ELSE IF(I$LEVEL_ID = 2) THEN
  BEGIN
    FOR
      SELECT L9.OBJ_ID, C.CAPTION
      FROM LINKS L9
      LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C ON 1 = 1
      WHERE L9.PARENT_ID = :I$OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 125, 187) AND L9.DATE_DEL IS NULL
        AND (L9.OBJ_ID = :V$CLASS_ID OR :V$CLASS_ID IS NULL)
      ORDER BY 2
      INTO :OBJ_ID, :NAME
    DO
    BEGIN
      HAS_CHILDREN = 0;
      SELECT FIRST 1 1
      FROM LINKS L10
      WHERE L10.PARENT_ID = :OBJ_ID AND L10.OBJ_TYPE_ID IN (10, 126) AND L10.DATE_DEL IS NULL
      INTO :HAS_CHILDREN;

      SUSPEND;
    END
  END
  -- Учащиеся
  ELSE IF(I$LEVEL_ID = 3) THEN
  BEGIN
    HAS_CHILDREN = 0;

    FOR
      SELECT L10.OBJ_ID, V55.VAL || ' ' || V56.VAL
      FROM LINKS L10
      JOIN VALS V55 ON V55.OBJ_ID = L10.OBJ_ID AND V55.PARAM_ID IN (55, 827) AND V55.IS_DEL = 0
      JOIN VALS V56 ON V56.OBJ_ID = L10.OBJ_ID AND V56.PARAM_ID IN (56, 828) AND V56.IS_DEL = 0
      WHERE L10.PARENT_ID = :I$OBJ_ID AND L10.OBJ_TYPE_ID IN (10, 126) AND L10.DATE_DEL IS NULL
        AND (L10.PARENT_ID = :V$CLASS_ID OR :V$CLASS_ID IS NULL)
      ORDER BY 2
      INTO :OBJ_ID, :NAME
    DO
    BEGIN
      SUSPEND;
    END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SDOCS_MARKS_GET (
    I$PERSON_ID BIGINT,
    I$STAGE_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
declare variable V$SUBJECT_ID bigint;
declare variable S varchar(1000);
declare variable V$YEAR_ID bigint;
declare variable V$Y varchar(20);
declare variable V$STAGE_ID bigint;
declare variable V$ST smallint;
declare variable V$MT_ID bigint;
declare variable V$MV_ID bigint;
declare variable V$N smallint;
begin

  TAG_NAME = 'marktypes::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT LISTVAL_ID, VAL
    FROM LISTVALS_LIST(220)
    WHERE IS_DEL = 0
    INTO :V$SUBJECT_ID, :S
  DO
  BEGIN
    TAG_NAME = 'marktypes:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'marktypes:r:id';
    VAL = V$SUBJECT_ID;
    SUSPEND;
    TAG_NAME = 'marktypes:r:val';
    VAL = S;
    SUSPEND;
  END

  TAG_NAME = 'stages::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT LISTVAL_ID, VAL
    FROM LISTVALS_LIST(25)
    WHERE IS_DEL = 0
    INTO :V$SUBJECT_ID, :S
  DO
  BEGIN
    TAG_NAME = 'stages:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'stages:r:id';
    VAL = V$SUBJECT_ID;
    SUSPEND;
    TAG_NAME = 'stages:r:val';
    VAL = S;
    SUSPEND;
  END

  TAG_NAME = 'subjects::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT SUBJECT_ID, C.CAPTION
    FROM (
      SELECT DISTINCT M.SUBJECT_ID
      FROM VALM M
      WHERE M.PUPIL_ID = :I$PERSON_ID AND M.IS_DEL = 0
    )
    LEFT JOIN OBJECT_CAPTION_GET(SUBJECT_ID) C ON 1 = 1
    ORDER BY 2
    INTO :V$SUBJECT_ID, :S
  DO
  BEGIN
    TAG_NAME = 'subjects:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'subjects:r:id';
    VAL = V$SUBJECT_ID;
    SUSPEND;
    TAG_NAME = 'subjects:r:name';
    VAL = S;
    SUSPEND;

    TAG_NAME = 'subjects:r:marks::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT M.YEAR_ID, R.VAL, M.STAGE_ID, LVS.COST, M.MARKTYPE_ID, M.MARKVAL_ID, RV.VAL, M.IS_NATIVE
      FROM VALM M
      JOIN LISTVALS LVY ON LVY.LISTVAL_ID = M.YEAR_ID
      JOIN RES R ON R.RES_ID = LVY.RES_ID AND R.LANG_CODE = 'RU'
      LEFT JOIN LISTVALS LVS ON LVS.LISTVAL_ID = M.STAGE_ID
      JOIN LISTVALS LVMT ON LVMT.LISTVAL_ID = M.MARKTYPE_ID
      JOIN LISTVALS LVMV ON LVMV.LISTVAL_ID = M.MARKVAL_ID
      JOIN RES RV ON RV.RES_ID = LVMV.RES_ID AND RV.LANG_CODE = 'RU'
      WHERE M.PUPIL_ID = :I$PERSON_ID AND M.IS_DEL = 0 AND M.SUBJECT_ID = :V$SUBJECT_ID
      ORDER BY LVY.COST, LVMT.SORT_ORDER
      INTO :V$YEAR_ID, :V$Y, :V$STAGE_ID, :V$ST, :V$MT_ID, :V$MV_ID, :S, :V$N
    DO
    BEGIN
      TAG_NAME = 'subjects:r:marks:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'subjects:r:marks:r:year_id';
      VAL = V$YEAR_ID;
      SUSPEND;
      TAG_NAME = 'subjects:r:marks:r:year';
      VAL = V$Y;
      SUSPEND;
      TAG_NAME = 'subjects:r:marks:r:stage_id';
      VAL = V$STAGE_ID;
      SUSPEND;
      TAG_NAME = 'subjects:r:marks:r:stage';
      VAL = V$ST;
      SUSPEND;
      TAG_NAME = 'subjects:r:marks:r:mt_id';
      VAL = V$MT_ID;
      SUSPEND;
      TAG_NAME = 'subjects:r:marks:r:val';
      VAL = V$MV_ID;
      SUSPEND;
      TAG_NAME = 'subjects:r:marks:r:text';
      VAL = S;
      SUSPEND;
      TAG_NAME = 'subjects:r:marks:r:native';
      VAL = V$N;
      SUSPEND;
    END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SDOCS_MIGRATE RETURNS (
    STUDENT_ID BIGINT,
    BOOK_ID BIGINT,
    DOC_ID BIGINT,
    DOC_TYPE BIGINT,
    ORDER_ID BIGINT,
    BLANK_ID BIGINT,
    STATE_ID BIGINT,
    NAME1 VARCHAR(100),
    NAME2 VARCHAR(100),
    NAME3 VARCHAR(100),
    BS VARCHAR(20),
    BN VARCHAR(20),
    CNT_ID BIGINT,
    DATA_ID BIGINT,
    Y INTEGER,
    PREV_DUBL VARCHAR(40),
    CLASS_NAME VARCHAR(400))
AS
DECLARE VARIABLE V$OU_ID BIGINT;
DECLARE VARIABLE V$ISSUE_DATE DATE;
DECLARE VARIABLE V$PREV_NUM VARCHAR(100);
DECLARE VARIABLE V$UO VARCHAR(100);
DECLARE VARIABLE V$REG VARCHAR(100);
DECLARE VARIABLE V$ORDER_NUM VARCHAR(100);
DECLARE VARIABLE V$ORDER_DATE DATE;
DECLARE VARIABLE V$DOB DATE;
DECLARE VARIABLE V$SUBJTYPE BIGINT;
DECLARE VARIABLE V$ORDER INTEGER;
DECLARE VARIABLE V$MARK VARCHAR(400);
DECLARE VARIABLE V$MARKY VARCHAR(20);
DECLARE VARIABLE V$MARKF VARCHAR(20);
DECLARE VARIABLE V$MARKG VARCHAR(20);
DECLARE VARIABLE V$HOURS VARCHAR(20);
DECLARE VARIABLE V$SUBJECT_ID BIGINT;
DECLARE VARIABLE V$BOOK_REC INTEGER;
DECLARE VARIABLE V$NFROM VARCHAR(20);
DECLARE VARIABLE V$NTO VARCHAR(20);
DECLARE VARIABLE V$BDATE DATE;
DECLARE VARIABLE V$BSUP VARCHAR(1000);
DECLARE VARIABLE S VARCHAR(8000);
DECLARE VARIABLE DB VARCHAR(400);
DECLARE VARIABLE V$REC_DATE VARCHAR(20);
DECLARE VARIABLE V$BLANK_ID BIGINT;
begin

  SELECT MON$DATABASE_NAME FROM MON$DATABASE INTO :DB;
  DB = REPLACE(DB, 'BASE.FDB', 'DOC.FDB');

  SELECT FIRST 1 GEN
  FROM GEN
  INTO :V$OU_ID;

  FOR
    SELECT L10.OBJ_ID, V2355.OBJ_ID, V2355.VAL, L230.OBJ_ID, V1877.VAL, V2354.VAL, V1871.VAL, V1880.LISTVAL_ID
    FROM LINKS L10
    -- Запись в книге регистрации
    JOIN VALR V1872 ON V1872.PARAM_ID = 1872 AND V1872.IS_DEL = 0 AND V1872.VAL = L10.OBJ_ID
    JOIN LINKS L234 ON L234.OBJ_ID = V1872.OBJ_ID AND L234.PARENT_TYPE_ID = 7 AND L234.DATE_DEL IS NULL
    -- Номер в книге выдачи
    JOIN VALI V1871 ON V1871.OBJ_ID = L234.OBJ_ID AND V1871.PARAM_ID = 1871 AND V1871.IS_DEL = 0
    -- Дата выдачи
    JOIN VALD V1876 ON V1876.OBJ_ID = L234.OBJ_ID AND V1876.PARAM_ID = 1876 AND V1876.IS_DEL = 0
    -- Данные бланка - номер бланка и статус, TYPE_ID 236
    JOIN VALR V1877 ON V1877.OBJ_ID = L234.OBJ_ID AND V1877.PARAM_ID = 1877 AND V1877.IS_DEL = 0
    JOIN VALL V1880 ON V1880.OBJ_ID = V1877.VAL AND V1880.PARAM_ID = 1880 AND V1880.IS_DEL = 0
    -- Контейнер выдачи TYPE_ID 292
    JOIN VALR V2355 ON V2355.OBJ_ID = L234.OBJ_ID AND V2355.PARAM_ID = 2355 AND V2355.IS_DEL = 0
    -- Год окончания
    JOIN VALI V2354 ON V2354.OBJ_ID = V2355.VAL AND V2354.PARAM_ID = 2354 AND V2354.IS_DEL = 0
    -- Данные аттестата
    JOIN LINKS L230 ON L230.PARENT_ID = V2355.VAL AND L230.OBJ_TYPE_ID = 230 AND L230.DATE_DEL IS NULL
    WHERE L10.PARENT_TYPE_ID IN (9, 187, 125, 81, 82, 83) AND L10.OBJ_TYPE_ID IN (10, 126) AND L10.DATE_DEL IS NULL
    -- По идее сначала должны идти испорченные бланки, затем рабочие
    ORDER BY 1, 4, 8 DESC
    INTO :STUDENT_ID, :BOOK_ID, :CNT_ID, :DATA_ID, :BLANK_ID, :Y, :V$BOOK_REC, :STATE_ID
  DO
  BEGIN
    -- Получаем поля самого аттестата
    -- Тип документа
    DOC_TYPE = NULL;
    SELECT FIRST 1 V.LISTVAL_ID
    FROM VALL V
    WHERE V.OBJ_ID = :DATA_ID AND V.PARAM_ID = 1860 AND V.IS_DEL = 0
    INTO :DOC_TYPE;

    -- Дата выдачи аттестата на руки
    V$ISSUE_DATE = NULL;
    SELECT FIRST 1 V.VAL
    FROM VALD V
    WHERE V.OBJ_ID = :DATA_ID AND V.PARAM_ID = 1884 AND V.IS_DEL = 0
    INTO :V$ISSUE_DATE;

    -- Номер предыдущего документа
    V$PREV_NUM = NULL;
    SELECT FIRST 1 V.VAL
    FROM VALS V
    WHERE V.OBJ_ID = :DATA_ID AND V.PARAM_ID = 2887 AND V.IS_DEL = 0
    INTO :V$PREV_NUM;

    -- Уровень образования в ПП (СПО)
    V$UO = NULL;
    SELECT FIRST 1 V.VAL
    FROM VALS V
    WHERE V.OBJ_ID = :DATA_ID AND V.PARAM_ID = 2886 AND V.IS_DEL = 0
    INTO :V$UO;

    -- Регистрационный номер
    V$REG = NULL;
    SELECT FIRST 1 V.VAL
    FROM VALS V
    WHERE V.OBJ_ID = :DATA_ID AND V.PARAM_ID = 2884 AND V.IS_DEL = 0
    INTO :V$REG;

    -- Номер приказа, тип 226
    V$ORDER_NUM = NULL;
    SELECT FIRST 1 V1.VAL
    FROM VALR V
    JOIN VALS V1 ON V1.OBJ_ID = V.VAL AND V1.PARAM_ID = 1842 AND V1.IS_DEL = 0
    WHERE V.OBJ_ID = :DATA_ID AND V.PARAM_ID = 1855 AND V.IS_DEL = 0
    INTO :V$ORDER_NUM;

    -- Дата приказа, тип 226
    -- почему-то дату приказа берем не из самого приказа параметр 1843, а из параметров аттестата 1856
    V$ORDER_DATE = NULL;
    SELECT FIRST 1 V.VAL
    FROM VALD V
    WHERE V.OBJ_ID = :DATA_ID AND V.PARAM_ID = 1856 AND V.IS_DEL = 0
    INTO :V$ORDER_DATE;

    -- Дата записи в книге выдачи - берем по дате добавления записи, а не по параметру 1876
    V$REC_DATE = NULL;
    SELECT FIRST 1 CAST(L.DATE_INS AS DATE)
    FROM LINKS L
    WHERE L.OBJ_ID = :BOOK_ID AND L.PARENT_TYPE_ID = 7 AND L.DATE_DEL IS NULL
    INTO :V$REC_DATE;
    IF(V$REC_DATE IS NULL) THEN V$REC_DATE = 'NULL'; ELSE V$REC_DATE = '''' || V$REC_DATE || '''';

    -- Бланк
    BS = NULL;
    BN = NULL;
    SELECT V1881.VAL, V1878.SVAL, V1848.SVAL, V1849.SVAL, V1850.VAL, V1851.SVAL
    FROM LINKS LP228
    JOIN VALS V1878 ON V1878.OBJ_ID = LP228.OBJ_ID AND V1878.PARAM_ID = 1878 AND V1878.IS_DEL = 0
    JOIN VALS V1881 ON V1881.OBJ_ID = LP228.PARENT_ID AND V1881.PARAM_ID = 1881 AND V1881.IS_DEL = 0 -- серия
    JOIN VALS V1848 ON V1848.OBJ_ID = LP228.PARENT_ID AND V1848.PARAM_ID = 1848 AND V1848.IS_DEL = 0 -- нач.номер
    JOIN VALS V1849 ON V1849.OBJ_ID = LP228.PARENT_ID AND V1849.PARAM_ID = 1849 AND V1849.IS_DEL = 0 -- кон.номер
    JOIN VALD V1850 ON V1850.OBJ_ID = LP228.PARENT_ID AND V1850.PARAM_ID = 1850 AND V1850.IS_DEL = 0 -- дата
    JOIN VALS V1851 ON V1851.OBJ_ID = LP228.PARENT_ID AND V1851.PARAM_ID = 1851 AND V1851.IS_DEL = 0 -- поставщик
    WHERE LP228.OBJ_ID = :BLANK_ID AND LP228.PARENT_TYPE_ID = 228 AND LP228.DATE_DEL IS NULL
    INTO :BS, :BN, :V$NFROM, :V$NTO, :V$BDATE, :V$BSUP;

    -- Просто не вносим такой аттестат
    -- IF(BS IS NULL) THEN EXCEPTION DATA_ERROR 'Нет данных по бланку в записи ' || BOOK_ID;

    -- Данные по бланку в случае дубликата
    PREV_DUBL = NULL;
    IF(STATE_ID = 5440) THEN
    SELECT FIRST 1 V1881.VAL || V1878.VAL
    FROM VALR V1872 -- ученик в книге регистрации #234
    JOIN VALR V2356 ON V2356.OBJ_ID = V1872.OBJ_ID AND V2356.PARAM_ID = 2356 AND V2356.IS_DEL = 0  -- документ
    JOIN VALR V1877 ON V1877.OBJ_ID = V1872.OBJ_ID AND V1877.PARAM_ID = 1877 AND V1877.IS_DEL = 0  -- бланк
    JOIN LINKS L236 ON L236.OBJ_ID = V1877.VAL AND L236.PARENT_TYPE_ID = 228 AND L236.DATE_DEL IS NULL -- пакет бланков
    JOIN VALL V1880 ON V1880.OBJ_ID = L236.OBJ_ID AND V1880.PARAM_ID = 1880 AND V1880.IS_DEL = 0 AND V1880.LISTVAL_ID IN (5438, 5439) -- первичный, взамен испорченого
    JOIN VALL V1847 ON V1847.OBJ_ID = L236.PARENT_ID AND V1847.PARAM_ID = 1847 AND V1847.IS_DEL = 0 AND V1847.LISTVAL_ID = :DOC_TYPE -- тип документа
    JOIN VALS V1878 ON V1878.OBJ_ID = L236.OBJ_ID AND V1878.PARAM_ID = 1878 AND V1878.IS_DEL = 0 -- номер
    JOIN VALS V1881 ON V1881.OBJ_ID = L236.PARENT_ID AND V1881.PARAM_ID = 1881 AND V1881.IS_DEL = 0 -- серия
    WHERE V1872.VAL = :STUDENT_ID AND V1872.PARAM_ID = 1872 AND V1872.IS_DEL = 0
    ORDER BY V1872.OBJ_ID
    INTO :PREV_DUBL;

    -- ФИО
    NAME1 = NULL;
    SELECT FIRST 1 V.VAL
    FROM VALS V
    WHERE V.OBJ_ID = :STUDENT_ID AND V.PARAM_ID IN (55, 827) AND V.IS_DEL = 0
    INTO :NAME1;
    NAME2 = NULL;
    SELECT FIRST 1 V.VAL
    FROM VALS V
    WHERE V.OBJ_ID = :STUDENT_ID AND V.PARAM_ID IN (56, 828) AND V.IS_DEL = 0
    INTO :NAME2;
    NAME3 = NULL;
    SELECT FIRST 1 V.VAL
    FROM VALS V
    WHERE V.OBJ_ID = :STUDENT_ID AND V.PARAM_ID IN (57, 829) AND V.IS_DEL = 0
    INTO :NAME3;
    V$DOB = NULL;
    SELECT FIRST 1 V.VAL
    FROM VALD V
    WHERE V.OBJ_ID = :STUDENT_ID AND V.PARAM_ID IN (89, 830) AND V.IS_DEL = 0
    INTO :V$DOB;

    -- Предметы
    S = '[';
    FOR
      SELECT V1852.LISTVAL_ID, V1854.VAL, V1853.VAL, V1870.SVAL, V2349.SVAL, V2350.SVAL, V2351.SVAL, V2880.SVAL
      FROM LINKS L229
      JOIN VALL V1852 ON V1852.OBJ_ID = L229.OBJ_ID AND V1852.PARAM_ID = 1852 AND V1852.IS_DEL = 0 AND V1852.LISTVAL_ID <> 5383
      JOIN VALI V1854 ON V1854.OBJ_ID = L229.OBJ_ID AND V1854.PARAM_ID = 1854 AND V1854.IS_DEL = 0
      JOIN VALR V1853 ON V1853.OBJ_ID = L229.OBJ_ID AND V1853.PARAM_ID = 1853 AND V1853.IS_DEL = 0
      LEFT JOIN VALS V1870 ON V1870.OBJ_ID = L229.OBJ_ID AND V1870.PARAM_ID = 1870 AND V1870.IS_DEL = 0
      LEFT JOIN VALS V2349 ON V2349.OBJ_ID = L229.OBJ_ID AND V2349.PARAM_ID = 2349 AND V2349.IS_DEL = 0
      LEFT JOIN VALS V2350 ON V2350.OBJ_ID = L229.OBJ_ID AND V2350.PARAM_ID = 2350 AND V2350.IS_DEL = 0
      LEFT JOIN VALS V2351 ON V2351.OBJ_ID = L229.OBJ_ID AND V2351.PARAM_ID = 2351 AND V2351.IS_DEL = 0
      LEFT JOIN VALS V2880 ON V2880.OBJ_ID = L229.OBJ_ID AND V2880.PARAM_ID = 2880 AND V2880.IS_DEL = 0
      WHERE L229.PARENT_ID = :CNT_ID AND L229.OBJ_TYPE_ID = 229 AND L229.DATE_DEL IS NULL
      ORDER BY 1, 2
      INTO :V$SUBJTYPE, :V$ORDER, :V$SUBJECT_ID, :V$MARK, :V$MARKY, :V$MARKF, :V$MARKG, :V$HOURS
    DO
    BEGIN
      IF(CHAR_LENGTH(S) > 4) THEN S = S || ',';
      S = S || '{"p":' || IIF(V$SUBJTYPE = 5381, 0, 1);
      S = S || ',"id":"' || V$SUBJECT_ID || '"';
      S = S || ',"m":"' || COALESCE(V$MARK, '?') || '"';
      S = S || ',"h":"' || COALESCE(V$HOURS, '0') || '"';

      -- Название предмета смотрим непосредственно у себя
      V$MARK = NULL;
      SELECT FIRST 1 V1846.VAL
      FROM LINKS L227
      JOIN VALR V1845 ON V1845.OBJ_ID = L227.OBJ_ID AND V1845.PARAM_ID = 1845 AND V1845.IS_DEL = 0 AND V1845.VAL = :V$SUBJECT_ID
      JOIN VALS V1846 ON V1846.OBJ_ID = L227.OBJ_ID AND V1846.PARAM_ID = 1846 AND V1846.IS_DEL = 0
      WHERE L227.PARENT_ID = :CNT_ID AND L227.OBJ_TYPE_ID = 227 AND L227.DATE_DEL IS NULL
      INTO :V$MARK;

      IF(V$MARK IS NULL) THEN V$MARK = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$SUBJECT_ID));
      -- Сначала заменяем парные одиночные кавычки на двойные
      V$MARK = REPLACE(V$MARK, '''''', '"');
      -- Затем оставшиеся одиночные меняем на спецсимвол
      V$MARK = REPLACE(V$MARK, '''', '´');
      -- Сами двойные кавычки надо экранировать
      V$MARK = REPLACE(V$MARK, '"', '\"');

      S = S || ',"t":"' || COALESCE(V$MARK, '?') || '"';
      S = S || '}';
    END
    S = S || ']';

    IF(BS IS NOT NULL) THEN
    BEGIN

      -- Регистрируем приказ
      SELECT OBJ_ID
      FROM SDOCS_MIGRATE_ORDER(:V$ORDER_DATE, :V$ORDER_NUM, :STUDENT_ID, :DOC_TYPE, :V$ISSUE_DATE)
      INTO :ORDER_ID;

      -- Регистрируем пакет бланков и бланк
      V$BSUP = REPLACE(V$BSUP, '''''', '"');
      V$BSUP = REPLACE(V$BSUP, '''', '´');

      V$BLANK_ID = NULL;
      EXECUTE STATEMENT 'SELECT OBJ_ID FROM SDOCS_MIGRATE_BLANK(' || DOC_TYPE || ', ' || V$OU_ID || ', ''' || BS || ''', ''' || BN || ''', ''' ||
        V$NFROM || ''', ''' || V$NTO || ''', ''' || V$BDATE || ''', ''' || V$BSUP || ''', ' || STATE_ID || ')'
      ON EXTERNAL :DB
      WITH COMMON TRANSACTION
      INTO :V$BLANK_ID;

      -- Регистрируем сам аттестат
      IF(NAME1 IS NULL) THEN NAME1 = 'NULL'; ELSE NAME1 = '''' || REPLACE(REPLACE(NAME1, '''''', '"'), '''', '´') || '''';
      IF(NAME2 IS NULL) THEN NAME2 = 'NULL'; ELSE NAME2 = '''' || REPLACE(REPLACE(NAME2, '''''', '"'), '''', '´') || '''';
      IF(NAME3 IS NULL) THEN NAME3 = 'NULL'; ELSE NAME3 = '''' || REPLACE(REPLACE(NAME3, '''''', '"'), '''', '´') || '''';

      CLASS_NAME = NULL;
      SELECT FIRST 1 M.NAME_IN
      FROM PERSON_MOVEMENTS M
      JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID IN (9, 125, 187)
      WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :STUDENT_ID AND M.DATE_IN <= :V$ISSUE_DATE AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= DATEADD(-1 MONTH TO :V$ISSUE_DATE))
      ORDER BY M.DATE_OUT NULLS FIRST
      INTO :CLASS_NAME;
      IF(CLASS_NAME IS NULL) THEN CLASS_NAME = 'NULL'; ELSE CLASS_NAME = '''' || CLASS_NAME || '''';

      IF(PREV_DUBL IS NULL) THEN PREV_DUBL = 'NULL'; ELSE PREV_DUBL = '''' || PREV_DUBL || '''';

      EXECUTE STATEMENT 'SELECT OBJ_ID FROM SDOCS_MIGRATE_DOC(' || DOC_TYPE || ', ' || V$OU_ID || ', ' || STUDENT_ID || ', ' || ORDER_ID || ', ' || V$BLANK_ID || ', ' ||
        STATE_ID || ', ' || NAME1 || ', ' || NAME2 || ', ' || NAME3 || ', ''' || V$DOB || ''', ' || COALESCE(V$BOOK_REC, 'NULL') || ', ' || Y || ', ''' ||
        S || ''', ' || CLASS_NAME || ', ' ||
        'NULL, NULL, NULL, NULL, NULL, NULL, NULL, ''' ||
        V$ORDER_DATE || ''', ''' || V$ISSUE_DATE || ''', ''' || V$ORDER_NUM || ''', ' || V$REC_DATE || ',' || PREV_DUBL || ')'
      ON EXTERNAL :DB
      WITH COMMON TRANSACTION
      INTO :DOC_ID;

      NAME1 = REPLACE(NAME1, '''', '');
      NAME2 = REPLACE(NAME2, '''', '');
      NAME3 = REPLACE(NAME3, '''', '');

      SUSPEND;

      --WHEN ANY DO EXCEPTION DATA_ERROR 'Ошибка на обучающемся ' || STUDENT_ID;

    END

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SDOCS_MIGRATE_LINKS RETURNS (
    PERSON_ID BIGINT,
    DOC_ID BIGINT,
    DOC_TYPE BIGINT,
    DOC_SERIE VARCHAR(40),
    DOC_NUM VARCHAR(40),
    DOC_DATE VARCHAR(20),
    ATT_ID BIGINT)
AS
declare variable DB varchar(400);
declare variable V$TYPE bigint;
begin

  SELECT MON$DATABASE_NAME FROM MON$DATABASE INTO :DB;
  DB = REPLACE(DB, 'BASE.FDB', 'DOC.FDB');

  FOR
    SELECT DISTINCT L10.OBJ_ID, L11.OBJ_ID, V50.LISTVAL_ID, V564.VAL, V565.VAL, D.VAL
    FROM LINKS L10
    JOIN LINKS L11 ON L11.PARENT_ID = L10.OBJ_ID AND L11.OBJ_TYPE_ID = 11 AND L11.DATE_DEL IS NULL
    JOIN VALL V50 ON V50.OBJ_ID = L11.OBJ_ID AND V50.PARAM_ID = 50 AND V50.IS_DEL = 0 AND V50.LISTVAL_ID IN (1375, 3241, 1376, 3240, 1382)
    JOIN VALS V564 ON V564.OBJ_ID = L11.OBJ_ID AND V564.PARAM_ID = 564 AND V564.IS_DEL = 0
    JOIN VALS V565 ON V565.OBJ_ID = L11.OBJ_ID AND V565.PARAM_ID = 565 AND V565.IS_DEL = 0
    JOIN VALD V566 ON V566.OBJ_ID = L11.OBJ_ID AND V566.PARAM_ID = 566 AND V566.IS_DEL = 0
    LEFT JOIN DATE2ISO(V566.VAL, 0) D ON 1 = 1
    WHERE L10.PARENT_TYPE_ID IN (9, 187, 125, 81, 82, 83) AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    INTO :PERSON_ID, :DOC_ID, :DOC_TYPE, :DOC_SERIE, :DOC_NUM, :DOC_DATE
  DO
  BEGIN

    IF(DOC_TYPE = 1375) THEN V$TYPE = 5377;
    ELSE IF(DOC_TYPE = 3241) THEN V$TYPE = 5378;
    ELSE IF(DOC_TYPE = 1376) THEN V$TYPE = 5379;
    ELSE IF(DOC_TYPE = 3240) THEN V$TYPE = 5380;
    ELSE IF(DOC_TYPE = 1382) THEN V$TYPE = 5385;
    ELSE V$TYPE = 0;

    ATT_ID = NULL;
    EXECUTE STATEMENT 'SELECT FIRST 1 D.OBJ_ID
      FROM DOCUMENTS D
      JOIN BLANKS B ON B.DATE_DEL IS NULL AND B.OBJ_ID = D.BLANK_ID
      JOIN BLANK_PACKS P ON P.DATE_DEL IS NULL AND P.OBJ_ID = B.PACK_ID
      WHERE D.DATE_DEL IS NULL AND D.PERSON_ID = ' || PERSON_ID || ' AND D.DOC_TYPE_ID = ' || V$TYPE || ' AND D.ACTION_DATE = ''' || DOC_DATE || '''' ||
        ' AND B.BLANK_NUM = ''' || DOC_NUM || ''' AND P.SERIE = ''' || DOC_SERIE || ''''
    ON EXTERNAL :DB
    WITH COMMON TRANSACTION
    INTO :ATT_ID;

    IF(ATT_ID IS NOT NULL) THEN
    SELECT 1 FROM VAL_ADD(569, :DOC_ID, :ATT_ID) INTO :V$TYPE;

    SUSPEND;
  END

  EXECUTE STATEMENT 'UPDATE BLANK_PACKS SET BLANKS_NUM = CAST(NUM_TO AS BIGINT) - CAST(NUM_FROM AS BIGINT) + 1'
  ON EXTERNAL :DB
  WITH COMMON TRANSACTION;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SDOCS_MIGRATE_ORDER (
    I$ORDER_DATE DATE,
    I$ORDER_NUM VARCHAR(100),
    I$STUDENT_ID BIGINT,
    I$DOC_TYPE BIGINT,
    I$ISSUE_DATE DATE)
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$OBJ_ID bigint;
declare variable S varchar(400);
begin
  SELECT FIRST 1 D.OBJ_ID
  FROM ORDERS D
  WHERE D.DATE_DEL IS NULL AND D.TYPE_ID = 13326 AND D.ORDER_DATE = :I$ORDER_DATE AND D.ORDER_NUM = :I$ORDER_NUM
  INTO :OBJ_ID;

  IF(OBJ_ID IS NULL) THEN
  BEGIN
    INSERT INTO ORDERS
    (ORDER_DATE, ORDER_NUM, ACTION_DATE, TYPE_ID, STATE_ID, SUBTYPE_ID)
    VALUES (:I$ORDER_DATE, :I$ORDER_NUM, :I$ISSUE_DATE, 13326, 11715, :I$DOC_TYPE)
    RETURNING OBJ_ID INTO :OBJ_ID;
  END

  SELECT FIRST 1 OD.OBJ_ID
  FROM ORDER_DATA OD
  WHERE OD.DATE_DEL IS NULL AND OD.ORDER_ID = :OBJ_ID AND OD.REF_ID = :I$STUDENT_ID
  INTO :V$OBJ_ID;

  IF(V$OBJ_ID IS NULL) THEN
  BEGIN
    SELECT FIRST 1 M.NAME_IN
    FROM PERSON_MOVEMENTS M
    JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID IN (9, 125, 187)
    WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :I$STUDENT_ID AND M.DATE_IN <= :I$ISSUE_DATE AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :I$ISSUE_DATE)
    INTO :S;

    INSERT INTO ORDER_DATA
    (ORDER_ID, REF_ID, ACTION_TYPE, GRADE_NAME)
    VALUES (:OBJ_ID, :I$STUDENT_ID, 0, :S)
    RETURNING OBJ_ID INTO :V$OBJ_ID;
  END

  SUSPEND;
end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SDOCS_ORDER_CHECK_PERSON (
    I$ORDER_ID BIGINT,
    I$PERSON_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    STATE_ID BIGINT)
AS
begin

  SELECT FIRST 1 O.STATE_ID
  FROM ORDER_DATA OD
  JOIN ORDERS O ON O.OBJ_ID = OD.ORDER_ID AND O.DATE_DEL IS NULL AND O.OBJ_ID = :I$ORDER_ID AND O.TYPE_ID = 13326
  WHERE OD.DATE_DEL IS NULL AND OD.REF_ID = :I$PERSON_ID
  INTO :STATE_ID;

  IF(STATE_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Приказ для указанной персоны не найден';

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SDOCS_ORDER_DUB (
    I$PERSON_ID BIGINT,
    I$ORDER_DATE DATE,
    I$ORDER_NUM VARCHAR(100),
    I$ACTION_DATE DATE,
    I$SIGNED_BY BIGINT,
    I$SUBTYPE_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable TMP bigint;
begin

  IF(EXISTS(
    SELECT FIRST 1 1
    FROM ORDERS D
    JOIN ORDER_DATA OD ON OD.DATE_DEL IS NULL AND OD.ORDER_ID = D.OBJ_ID AND OD.REF_ID = :I$PERSON_ID
    WHERE D.DATE_DEL IS NULL AND D.STATE_ID = 11716 AND D.TYPE_ID = 13326
  ))
  THEN EXCEPTION DATA_ERROR 'Уже есть открытый проект приказа по документам для данной персоны';

  SELECT OBJ_ID
  FROM SDOCS_ORDER_SET(NULL, :I$USER_ID, :I$ACTION_DATE, :I$ORDER_DATE, :I$ORDER_NUM, 'Выдача дубликата документа для ' ||
    (SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$PERSON_ID)), :I$SIGNED_BY, 11716, :I$SUBTYPE_ID)
  INTO :OBJ_ID;

  SELECT 1 FROM ORDER_SET_ROW(:OBJ_ID, NULL, :I$USER_ID, 0, :I$PERSON_ID, NULL, NULL) INTO :TMP;

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SDOCS_ORDER_GET (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
declare variable V$OBJ_ID bigint;
declare variable V$STATE_ID bigint;
begin

  FOR
    SELECT D.TAG_NAME, D.VAL
    FROM ORDER_GET(:I$OBJ_ID, 13326, :I$USER_ID) D
    INTO :TAG_NAME, :VAL
  DO
  BEGIN
    IF(TAG_NAME = 'state_id:values:value') THEN V$STATE_ID = VAL;
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SDOCS_ORDER_REPORT (
    I$STAGE_ID BIGINT,
    I$TYPE_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    VAL VARCHAR(4000))
AS
declare variable V$YDATE date;
declare variable V$YEAR_ID bigint;
declare variable V$ORDER_ID bigint;
declare variable V$ORDER_NUM varchar(100);
declare variable V$ORDER_DATE date;
declare variable V$ACTION_DATE date;
declare variable V$PERSON_ID bigint;
declare variable V$GRADE_NAME varchar(400);
declare variable S varchar(400);
declare variable SS varchar(1000);
declare variable V$USER_TYPE smallint;
declare variable V$DOC_ID bigint;
declare variable V$MASK smallint;
declare variable V$STATE_ID bigint;
declare variable V$REF_NUM integer;
declare variable V varchar(400);
declare variable V$BLANK varchar(100);
declare variable V$GRADE_ID bigint;
declare variable N1 integer;
declare variable N2 integer;
declare variable V$EXTRA varchar(400);
begin

  SELECT FIRST 1 CAST(LV.TAG AS DATE), LV.LISTVAL_ID
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$YDATE, :V$YEAR_ID;

  SELECT MON$DATABASE_NAME
  FROM MON$DATABASE
  INTO :V;

  V = REPLACE(V, 'BASE.FDB', 'DOC.FDB');

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;
  SELECT USER_TYPE FROM USERS WHERE USER_ID = :I$USER_ID INTO :V$USER_TYPE;

  VAL = '<!DOCTYPE html>';
  VAL = VAL || '<html lang="ru">';
  VAL = VAL || '<head>';
  VAL = VAL || '<meta charset="utf-8" />';
  VAL = VAL || '<style>';
  VAL = VAL || 'html { font-family: Tahoma, Verdana, Arial;';
  VAL = VAL || 'font-size: 10pt; ';
  VAL = VAL || '} ';
  VAL = VAL || '</style>';

  VAL = VAL || '</head>';
  VAL = VAL || '<body>';
  SUSPEND;

  -- Выборка по приказам

  VAL = '<div class="ui small dividing header">Распределение по приказам</div>';
  SUSPEND;

  FOR
    SELECT D.OBJ_ID, D.ORDER_DATE, D.ORDER_NUM, D.ACTION_DATE, D.PROJECT_NUM, D.STATE_ID, D.COMMENTS
    FROM ORDERS D
    WHERE D.DATE_DEL IS NULL AND D.TYPE_ID = 13326 AND D.ACTION_DATE >= :V$YDATE AND D.STATE_ID IN (11715, 11716)
    ORDER BY 1
    INTO :V$ORDER_ID, :V$ORDER_DATE, :V$ORDER_NUM, :V$ACTION_DATE, :S, :V$STATE_ID, :SS
  DO
  BEGIN

    VAL = '<div class="ui small header">Приказ ' || COALESCE(V$ORDER_NUM, ' (проект) ' || S);
    IF(V$ORDER_DATE IS NOT NULL) THEN VAL = VAL || ' от ' || (SELECT RESULT FROM DATE2STR(:V$ORDER_DATE));
    IF(V$STATE_ID = 11716) THEN VAL = VAL || ' (проект ' || S || ')';
    VAL = VAL || '</div>';
    IF(SS IS NOT NULL) THEN VAL = VAL || '<div style="font-size: 90%; color: #2185d0;">' || SS || '</div>';

    VAL = VAL || '<table class="ui small compact fixed striped celled table">';
    VAL = VAL || '<thead><tr>';
      VAL = VAL || '<th>ФИО</th>';
      VAL = VAL || '<th>Класс/группа</th>';
      VAL = VAL || '<th>Проект создан</th>';
      VAL = VAL || '<th>Титул распечатан</th>';
      VAL = VAL || '<th>Печать выполнена</th>';
      VAL = VAL || '<th>Номер бланка</th>';
      VAL = VAL || '<th>Рег. номер</th>';
    VAL = VAL || '</tr></thead><tbody>';
    SUSPEND;

    -- Идем по всем ученикам
    FOR
      SELECT OD.REF_ID, OD.GRADE_NAME, C.CAPTION
      FROM ORDER_DATA OD
      LEFT JOIN OBJECT_CAPTION_GET(OD.REF_ID, 23) C ON 1 = 1
      WHERE OD.DATE_DEL IS NULL AND OD.ORDER_ID = :V$ORDER_ID
      ORDER BY C.SORT_ORDER, 2, 3
      INTO :V$PERSON_ID, :V$GRADE_NAME, :S
    DO
    BEGIN
      V$DOC_ID = NULL;
      V$REF_NUM = NULL;
      V$STATE_ID = NULL;
      V$BLANK = NULL;

      IF(V$GRADE_NAME IS NULL) THEN
      SELECT FIRST 1 C.CAPTION
      FROM LINKS LP9
      LEFT JOIN OBJECT_CAPTION_GET(LP9.PARENT_ID) C ON 1 = 1
      WHERE LP9.OBJ_ID = :V$PERSON_ID AND LP9.PARENT_TYPE_ID IN (9, 125, 187) AND LP9.DATE_DEL IS NULL
      INTO :V$GRADE_NAME;

      V$REF_NUM = NULL;
      V$BLANK = '';
      V$EXTRA = '';
      EXECUTE STATEMENT
        'SELECT FIRST 1 D.OBJ_ID, D.STATE_ID, D.SEQ_NO, D.PRINTED_STATE, BP.SERIE || '' '' || B.BLANK_NUM, BE.ADD_NUMS
        FROM DOCUMENTS D
        LEFT JOIN BLANKS B ON B.DATE_DEL IS NULL AND B.OBJ_ID = D.BLANK_ID
        LEFT JOIN BLANK_PACKS BP ON BP.DATE_DEL IS NULL AND BP.OBJ_ID = B.PACK_ID
        LEFT JOIN SDOCS_ADD_NUMS(B.OBJ_ID, D.OBJ_ID) BE ON 1 = 1
        WHERE D.DATE_DEL IS NULL AND D.ORDER_ID = ' || V$ORDER_ID || ' AND D.PERSON_ID = ' || V$PERSON_ID
      ON EXTERNAL :V
      -- ROLE 'INISSOFT_ROLE'
      WITH COMMON TRANSACTION
      INTO :V$DOC_ID, :V$STATE_ID, :V$REF_NUM, :V$MASK, :V$BLANK, :V$EXTRA;

      IF(V$EXTRA <> '') THEN V$EXTRA = '<br/>' || V$EXTRA;

      VAL = '<tr class="';
        IF(V$DOC_ID IS NULL) THEN VAL = VAL || 'negative';
        ELSE IF(V$REF_NUM IS NOT NULL AND V$STATE_ID IN (1, 4)) THEN VAL = VAL || 'positive';
      VAL = VAL || '">';
        VAL = VAL || '<td>' || S || '</td>';
        VAL = VAL || '<td>' || COALESCE(V$GRADE_NAME, '-') || '</td>';
        VAL = VAL || '<td>' || IIF(V$DOC_ID IS NOT NULL, 'Да', 'Нет') || '</td>';
        VAL = VAL || '<td>' || IIF(BIN_AND(V$MASK, 1) <> 0, 'Да', 'Нет') || '</td>';
        VAL = VAL || '<td>' || IIF(V$STATE_ID IN (1, 4), 'Да', 'Нет') || '</td>';
        VAL = VAL || '<td>' || COALESCE(V$BLANK, '-') || V$EXTRA || '</td>';
        VAL = VAL || '<td>' || COALESCE(V$REF_NUM, '-') || '</td>';
      VAL = VAL || '</tr>';
      SUSPEND;
    END

    VAL = '</tbody>';

    VAL = VAL || '</table>';
    SUSPEND;

  END

  VAL = '</body></html>';
  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SDOCS_ORDER_SET (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40),
    I$ACTION_DATE DATE,
    I$ORDER_DATE DATE,
    I$ORDER_NUM VARCHAR(100),
    I$COMMENTS VARCHAR(1000),
    I$SIGNED_BY BIGINT,
    I$STATE_ID BIGINT,
    I$SUBTYPE_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    STATE_ID BIGINT)
AS
declare variable V$YEAR date;
declare variable V$ORDER_DATE date;
begin

  SELECT FIRST 1 D.ORDER_DATE
  FROM ORDERS D
  WHERE D.DATE_DEL IS NULL AND D.DATE_DEL IS NULL AND D.TYPE_ID = 13326 AND D.OBJ_ID = :I$OBJ_ID
  INTO :V$ORDER_DATE;

  IF(I$STATE_ID IS NULL) THEN I$STATE_ID = 11716;
  IF(I$OBJ_ID IS NULL AND I$STATE_ID <> 11716) THEN EXCEPTION DATA_ERROR 'Новый приказ может добавляться только в статусе проекта';

  -- Теперь требуем оба заполненных поля, неясно зачем изначально разрешали одно
  /*IF(I$ACTION_DATE IS NOT NULL AND I$ORDER_DATE IS NOT NULL) THEN BEGIN END
  ELSE IF(I$ACTION_DATE IS NULL AND I$ORDER_DATE IS NOT NULL) THEN I$ACTION_DATE = I$ORDER_DATE;
  ELSE IF(I$ACTION_DATE IS NOT NULL AND I$ORDER_DATE IS NULL) THEN I$ORDER_DATE = I$ACTION_DATE;
  ELSE EXCEPTION DATA_ERROR 'Должна быть указана как минимум одна из дат';*/

  SELECT FIRST 1 LV.TAG
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$YEAR;

  IF(I$ORDER_DATE < V$YEAR OR I$ORDER_DATE >= DATEADD(1 YEAR TO V$YEAR)) THEN EXCEPTION DATA_ERROR 'Нельзя менять приказы за пределами текущего учебного года';

  SELECT OBJ_ID, STATE_ID
  FROM ORDER_SET(:I$OBJ_ID, :I$USER_ID, NULL, 13326, :I$STATE_ID, :I$ORDER_DATE, :I$ORDER_NUM, :I$ACTION_DATE, :I$SIGNED_BY, NULL, :I$COMMENTS, :I$SUBTYPE_ID)
  INTO :OBJ_ID, :STATE_ID;

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SDOCS_PERSONS_LIST (
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$GRADE_ID BIGINT;
DECLARE VARIABLE V$STAGE_ID BIGINT;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE S VARCHAR(1000);
DECLARE VARIABLE S1 VARCHAR(200);
DECLARE VARIABLE S2 VARCHAR(200);
DECLARE VARIABLE S3 VARCHAR(200);
DECLARE VARIABLE SD DATE;
DECLARE VARIABLE V$ORDER_ID BIGINT;
DECLARE VARIABLE V$ORDER_PN VARCHAR(100);
DECLARE VARIABLE V$ORDER_NUM VARCHAR(100);
DECLARE VARIABLE V$ORDER_DATE DATE;
DECLARE VARIABLE V$S2_ID BIGINT;
begin

  TAG_NAME = 'year_id';
  SELECT FIRST 1 V1236.LISTVAL_ID, R.VAL
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :VAL, :S;
  SUSPEND;

  TAG_NAME = 'year';
  VAL = S;
  SUSPEND;

  TAG_NAME = 'current_year';
  VAL = EXTRACT(YEAR FROM CURRENT_DATE);
  SUSPEND;

  -- 502 - альтернативный маршрут для выборки классов ГИА
  TAG_NAME = 'grades::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT DISTINCT LPG.PARENT_ID, V43.LISTVAL_ID, V49.LISTVAL_ID, C.CAPTION
    FROM ORDERS D
    JOIN ORDER_DATA OD ON OD.DATE_DEL IS NULL AND OD.ORDER_ID = D.OBJ_ID
    JOIN LINKS LPG ON LPG.OBJ_ID = OD.REF_ID AND LPG.PARENT_TYPE_ID IN (9, 125, 187) AND LPG.DATE_DEL IS NULL
    JOIN LINKS LP8 ON LP8.OBJ_ID = LPG.PARENT_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
    JOIN VALL V49 ON V49.OBJ_ID = LP8.PARENT_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V49.LISTVAL_ID
    JOIN LINKS LP7 ON LP7.OBJ_ID = LP8.PARENT_ID AND LP7.PARENT_TYPE_ID IN (7, 502) AND LP7.DATE_DEL IS NULL
    LEFT JOIN VALL V43 ON V43.OBJ_ID = LP7.PARENT_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0
    LEFT JOIN OBJECT_CAPTION_GET(LPG.PARENT_ID) C ON 1 = 1
    WHERE D.DATE_DEL IS NULL AND D.TYPE_ID = 13326 AND D.STATE_ID = 11716
    ORDER BY LV.SORT_ORDER, C.CAPTION
    INTO :V$GRADE_ID, :V$STAGE_ID, :V$S2_ID, :S
  DO
  BEGIN
    TAG_NAME = 'grades:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'grades:r:id';
    VAL = V$GRADE_ID;
    SUSPEND;
    -- А почему он stage_id, когда должно быть level_id ?
    TAG_NAME = 'grades:r:stage_id';
    IF(V$STAGE_ID IS NULL) THEN V$STAGE_ID = IIF(V$S2_ID = 47, 27, 26);
    VAL = V$STAGE_ID;
    SUSPEND;
    TAG_NAME = 'grades:r:name';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'grades:r:persons::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT OD.REF_ID, V55.SVAL, V56.SVAL, V57.SVAL, V89.VAL, D.OBJ_ID, D.PROJECT_NUM, D.COMMENTS, D.ORDER_NUM, D.ORDER_DATE
      FROM ORDERS D
      JOIN ORDER_DATA OD ON OD.DATE_DEL IS NULL AND OD.ORDER_ID = D.OBJ_ID
      JOIN LINKS LPG ON LPG.OBJ_ID = OD.REF_ID AND LPG.PARENT_ID = :V$GRADE_ID AND LPG.DATE_DEL IS NULL
      JOIN VALS V55 ON V55.OBJ_ID = OD.REF_ID AND V55.PARAM_ID IN (55, 827) AND V55.IS_DEL = 0
      JOIN VALS V56 ON V56.OBJ_ID = OD.REF_ID AND V56.PARAM_ID IN (56, 828) AND V56.IS_DEL = 0
      LEFT JOIN VALS V57 ON V57.OBJ_ID = OD.REF_ID AND V57.PARAM_ID IN (57, 829) AND V57.IS_DEL = 0
      JOIN VALD V89 ON V89.OBJ_ID = OD.REF_ID AND V89.PARAM_ID IN (89, 830) AND V89.IS_DEL = 0
      WHERE D.DATE_DEL IS NULL AND D.TYPE_ID = 13326 AND D.STATE_ID = 11716
      ORDER BY 2, 3, 4
      INTO :V$OBJ_ID, :S1, :S2, :S3, :SD, :V$ORDER_ID, :V$ORDER_PN, :S, :V$ORDER_NUM, :V$ORDER_DATE
    DO
    BEGIN
      TAG_NAME = 'grades:r:persons:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'grades:r:persons:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'grades:r:persons:r:name';
      VAL = S1 || ' ' || S2 || COALESCE(' ' || S3, '');
      SUSPEND;
      TAG_NAME = 'grades:r:persons:r:name_last';
      VAL = S1;
      SUSPEND;
      TAG_NAME = 'grades:r:persons:r:name_first';
      VAL = S2;
      SUSPEND;
      TAG_NAME = 'grades:r:persons:r:name_mid';
      VAL = S3;
      SUSPEND;
      TAG_NAME = 'grades:r:persons:r:birth_date';
      VAL = (SELECT RESULT FROM DATE2STR(:SD));
      SUSPEND;
      TAG_NAME = 'grades:r:persons:r:order_id';
      VAL = V$ORDER_ID;
      SUSPEND;
      TAG_NAME = 'grades:r:persons:r:order_num';
      IF(V$ORDER_NUM IS NULL) THEN VAL = V$ORDER_PN; ELSE VAL = V$ORDER_NUM || ' от ' || COALESCE('?', (SELECT RESULT FROM DATE2STR(:V$ORDER_DATE)));
      SUSPEND;
      TAG_NAME = 'grades:r:persons:r:order_cm';
      VAL = S;
      SUSPEND;
      -- Буфер для размещения значения из DOC
      TAG_NAME = 'grades:r:persons:r:doc_id';
      VAL = '';
      SUSPEND;
      TAG_NAME = 'grades:r:persons:r:state_id';
      VAL = '';
      SUSPEND;
    END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SDOCS_SETTINGS_GET (
    I$CLASS_ID BIGINT,
    I$STAGE_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(4000))
AS
DECLARE VARIABLE V$SO BIGINT;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$SUBJECT_ID BIGINT;
DECLARE VARIABLE S VARCHAR(400);
DECLARE VARIABLE FULL_NAME VARCHAR(1000);
DECLARE VARIABLE FULL_NAME_PRINT VARCHAR(1000);
DECLARE VARIABLE FULL_NAME_PRINT2 VARCHAR(1000);
DECLARE VARIABLE OO_PLACE VARCHAR(255);
DECLARE VARIABLE DIRECTOR_FIO VARCHAR(1000);
DECLARE VARIABLE DIRECTOR_JOB BIGINT;
DECLARE VARIABLE V$STAGE_ID BIGINT;
DECLARE VARIABLE V$TYPE_ID BIGINT;
DECLARE VARIABLE V$DATE DATE;
DECLARE VARIABLE V$H FLOAT;
DECLARE VARIABLE N INTEGER;
DECLARE VARIABLE V$HAS_OO SMALLINT;
DECLARE VARIABLE V$HAS_SPO SMALLINT;
DECLARE VARIABLE L BIGINT;
DECLARE VARIABLE LT BIGINT;
begin

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  -- Конструкция с lic_type устарела, нужно ориентироваться на этап обучения
  TAG_NAME = 'lic_type';
  VAL = (SELECT STATUS FROM OU_LICENCE_TYPE);
  SUSPEND;

  V$HAS_OO = 0;
  V$HAS_SPO = 0;

  SELECT FIRST 1 1
  FROM LINKS L472
  JOIN VALL V3327 ON V3327.OBJ_ID = L472.OBJ_ID AND V3327.PARAM_ID = 3327 AND V3327.IS_DEL = 0 AND V3327.LISTVAL_ID IN (22, 26, 27)
  WHERE L472.PARENT_TYPE_ID = 2 AND L472.OBJ_TYPE_ID = 472 AND L472.DATE_DEL IS NULL
  INTO :V$HAS_OO;

  SELECT FIRST 1 1
  FROM LINKS L472
  JOIN VALL V3327 ON V3327.OBJ_ID = L472.OBJ_ID AND V3327.PARAM_ID = 3327 AND V3327.IS_DEL = 0 AND V3327.LISTVAL_ID IN (28, 29, 13129, 13131)
  WHERE L472.PARENT_TYPE_ID = 2 AND L472.OBJ_TYPE_ID = 472 AND L472.DATE_DEL IS NULL
  INTO :V$HAS_SPO;

  -- has_spo нужно спрятать, если класс или этап является школьным
  IF(I$CLASS_ID IS NOT NULL) THEN
  BEGIN
    SELECT FIRST 1 V43.LISTVAL_ID, LP7.PARENT_TYPE_ID
    FROM LINKS LP8
    JOIN LINKS LP7 ON LP7.OBJ_ID = LP8.PARENT_ID AND LP7.PARENT_TYPE_ID IN (7, 502) AND LP7.DATE_DEL IS NULL
    LEFT JOIN VALL V43 ON V43.OBJ_ID = LP7.PARENT_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0
    WHERE LP8.OBJ_ID = :I$CLASS_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
    INTO :L, :LT;
  END
  ELSE IF(I$STAGE_ID IS NOT NULL) THEN
  BEGIN
    SELECT FIRST 1 V43.LISTVAL_ID, LP7.PARENT_TYPE_ID
    FROM LINKS LP7
    LEFT JOIN VALL V43 ON V43.OBJ_ID = LP7.PARENT_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0
    WHERE LP7.OBJ_ID = :I$STAGE_ID AND LP7.PARENT_TYPE_ID IN (7, 502) AND LP7.DATE_DEL IS NULL
    INTO :L, :LT;
  END

  IF(L IN (22, 26, 27) OR LT = 502) THEN V$HAS_SPO = 0;

  TAG_NAME = 'has_oo';
  VAL = V$HAS_OO;
  SUSPEND;
  TAG_NAME = 'has_spo';
  VAL = V$HAS_SPO;
  SUSPEND;

  -- Глобальные настройки, а также данные для меню
  -- Изменение: добавили глобальные настройки для ОУ в целом
  IF(I$CLASS_ID IS NULL) THEN
  BEGIN
    TAG_NAME = 'stages::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT -1 SORT_ORDER, L2.OBJ_ID, NULL, C.CAPTION
      FROM LINKS L2
      LEFT JOIN OBJECT_CAPTION_GET(L2.OBJ_ID) C ON 1 = 1
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      UNION
      SELECT LV.SORT_ORDER, L7.OBJ_ID, V43.LISTVAL_ID, C.CAPTION
      FROM LINKS L2
      JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID IN (7, 502) AND L7.DATE_DEL IS NULL
      LEFT JOIN VALL V43 ON V43.OBJ_ID = L7.OBJ_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0
      LEFT JOIN LISTVALS LV ON LV.LISTVAL_ID = V43.LISTVAL_ID
      LEFT JOIN OBJECT_CAPTION_GET(L7.OBJ_ID) C ON 1 = 1
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND (V43.LISTVAL_ID IN (22, 26, 27, 28, 29) OR L7.PARENT_TYPE_ID = 202)
      ORDER BY 1
      INTO :V$SO, :V$OBJ_ID, :V$STAGE_ID, :S
    DO
    BEGIN
      TAG_NAME = 'stages:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'stages:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'stages:r:stage_id';
      VAL = V$STAGE_ID; -- тут может быть NULL
      SUSPEND;
      TAG_NAME = 'stages:r:name';
      VAL = S;
      SUSPEND;

      SELECT FULL_NAME, FULL_NAME_PRINT, FULL_NAME_PRINT2, OO_PLACE, DIRECTOR_FIO, DIRECTOR_JOB
      FROM CERTIFICATE_OO_SETTINGS_GET(:V$OBJ_ID, :I$USER_ID)
      INTO :FULL_NAME, :FULL_NAME_PRINT, :FULL_NAME_PRINT2, :OO_PLACE, :DIRECTOR_FIO, :DIRECTOR_JOB;

      TAG_NAME = 'stages:r:oo_name';
      VAL = FULL_NAME;
      SUSPEND;
      TAG_NAME = 'stages:r:oo_name_pr';
      VAL = FULL_NAME_PRINT;
      SUSPEND;
      TAG_NAME = 'stages:r:oo_name_pr2';
      VAL = FULL_NAME_PRINT2;
      SUSPEND;
      TAG_NAME = 'stages:r:oo_place';
      VAL = OO_PLACE;
      SUSPEND;
      TAG_NAME = 'stages:r:director_fio';
      VAL = DIRECTOR_FIO;
      SUSPEND;
      TAG_NAME = 'stages:r:director_job';
      VAL = DIRECTOR_JOB;
      SUSPEND;

      -- Количество замен в наименовании предмета
      TAG_NAME = 'stages:r:subject_subst';
      VAL = 0;
      SELECT COUNT(*)
      FROM LINKS L227
      WHERE L227.PARENT_ID = :V$OBJ_ID AND L227.OBJ_TYPE_ID = 227 AND L227.DATE_DEL IS NULL
      INTO :VAL;
      SUSPEND;
    END

    -- Классы, упомянутые в приказах текущего года, только действующие приказы
    SELECT FIRST 1 LV.TAG
    FROM LINKS L2
    JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :V$DATE;

    TAG_NAME = 'grades::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT DISTINCT D.PARENT_ID, C.CAPTION
      FROM (
        SELECT LPG.PARENT_ID
        FROM ORDERS D
        JOIN ORDER_DATA OD ON OD.DATE_DEL IS NULL AND OD.ORDER_ID = D.OBJ_ID
        JOIN LINKS LPG ON LPG.OBJ_ID = OD.REF_ID AND LPG.PARENT_TYPE_ID IN (9, 125, 187) AND LPG.DATE_DEL IS NULL
        WHERE D.DATE_DEL IS NULL AND D.TYPE_ID = 13326 AND (D.ORDER_DATE >= :V$DATE OR D.ORDER_DATE IS NULL) AND D.STATE_ID = 11716
      ) D
      JOIN LINKS LP8 ON LP8.OBJ_ID = D.PARENT_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
      JOIN VALL V49 ON V49.OBJ_ID = LP8.PARENT_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
      JOIN LISTVALS LV ON LV.LISTVAL_ID = V49.LISTVAL_ID
      LEFT JOIN OBJECT_CAPTION_GET(D.PARENT_ID) C ON 1 = 1
      ORDER BY LV.SORT_ORDER, C.CAPTION
      INTO :V$OBJ_ID, :S
    DO
    BEGIN
      TAG_NAME = 'grades:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'grades:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'grades:r:name';
      VAL = S;
      SUSPEND;
    END

    EXIT;
  END

  -- Настройки конкретного класса (json)
  TAG_NAME = 'subject_map';
  VAL = NULL;
  SELECT V.VAL
  FROM VALS V
  WHERE V.OBJ_ID = :I$CLASS_ID AND V.PARAM_ID IN (3150, 3151, 3152) AND V.IS_DEL = 0
  INTO :VAL;
  SUSPEND;

  -- Список замен наименований предметов
  SELECT FIRST 1 LP7.PARENT_ID
  FROM LINKS LP8
  JOIN LINKS LP7 ON LP7.OBJ_ID = LP8.PARENT_ID AND LP7.PARENT_TYPE_ID IN (7, 502) AND LP7.DATE_DEL IS NULL
  WHERE LP8.OBJ_ID = :I$CLASS_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
  INTO :V$STAGE_ID;

  TAG_NAME = 'qual';
  VAL = NULL;
  SELECT V
  FROM VAL_GET(:I$CLASS_ID, 3195)
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'gak_fio';
  VAL = NULL;
  SELECT V
  FROM VAL_GET(:I$CLASS_ID, 3196)
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'gak_date';
  VAL = NULL;
  SELECT DD.VAL
  FROM VAL_GET(:I$CLASS_ID, 3197)
  LEFT JOIN DATE2ISO(D, 0) DD ON 1 = 1
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'uo';
  VAL = NULL;
  SELECT V
  FROM VAL_GET(:I$CLASS_ID, 3198)
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'op_dir';
  VAL = NULL;
  SELECT V
  FROM VAL_GET(:I$CLASS_ID, 3606)
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'old_names';
  VAL = NULL;
  SELECT V
  FROM VAL_GET(:I$CLASS_ID, 3335)
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'to_hours';
  VAL = NULL;
  SELECT V
  FROM VAL_GET(:I$CLASS_ID, 3329)
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'aud_hours';
  VAL = NULL;
  SELECT V
  FROM VAL_GET(:I$CLASS_ID, 3330)
  INTO :VAL;
  SUSPEND;

  -- Если класса нет (дубликат), то подбираем уровень по коду уровня
  IF(V$STAGE_ID IS NULL) THEN
  BEGIN
    SELECT FIRST 1 L7.OBJ_ID
    FROM LINKS L2
    JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    JOIN VALL V43 ON V43.OBJ_ID = L7.OBJ_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0 AND V43.LISTVAL_ID = :I$STAGE_ID
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :V$STAGE_ID;

    IF(V$STAGE_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не найден уровень образования, не удалось найти подходящий вариант';
  END

  -- По предметам сразу делаем разбивку по разделам
  -- Если STAGE_ID < 0, то предметы не выдаем (выборка для печати)
  TAG_NAME = 'subjects::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L.SUBJECT_ID, L.SUBJECT_NAME, L.C_SUBJECT_NAME, L.SUBJECT_TYPE
    FROM CERTIFICATE_CLASS_SUBJECT_LIST(:V$STAGE_ID, :I$CLASS_ID, :I$USER_ID) L
    WHERE :I$STAGE_ID IS NULL OR :I$STAGE_ID > 0
    ORDER BY L.SUBJECT_TYPE, L.SUBJECT_NAME
    INTO :V$OBJ_ID, :FULL_NAME, :FULL_NAME_PRINT, :V$TYPE_ID
  DO
  BEGIN
    TAG_NAME = 'subjects:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'subjects:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'subjects:r:name';
    VAL = FULL_NAME;
    SUSPEND;
    TAG_NAME = 'subjects:r:alt';
    VAL = FULL_NAME_PRINT;
    SUSPEND;
    TAG_NAME = 'subjects:r:type';
    VAL = V$TYPE_ID;
    SUSPEND;
  END

  -- Нагрузка по предметам учебного плана текущего уровня образования, суммируем за все этапы
  -- если учебных планов несколько - выдаем по каждому отдельно
  -- если предмет соответствует базовому - суммируем именно по базовому
  TAG_NAME = 'loads::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    -- Нумерация элементов идет в каждом разделе своя - добавляем номер раздела
    SELECT LP400.PARENT_ID, PS.SUBJECT_ID, MIN(PS2.SORT_INDEX * 1000 + PS.SORT_INDEX)
    FROM LINKS L10
    JOIN LINKS LP256 ON LP256.OBJ_ID = L10.OBJ_ID AND LP256.PARENT_TYPE_ID = 256 AND LP256.DATE_DEL IS NULL
    JOIN LINKS LP54 ON LP54.OBJ_ID = LP256.PARENT_ID AND LP54.PARENT_TYPE_ID = 54 AND LP54.DATE_DEL IS NULL
    JOIN LINKS LP400 ON LP400.OBJ_ID = LP54.PARENT_ID AND LP400.PARENT_TYPE_ID = 400 AND LP400.DATE_DEL IS NULL
    -- Предмет
    JOIN PLAN_SUBJECTS PS ON PS.DATE_DEL IS NULL AND PS.PLAN_ID = LP400.PARENT_ID AND PS.ROW_TYPE = 10
    -- Раздел, кроме предметов по выбору
    JOIN PLAN_SUBJECTS PS2 ON PS2.OBJ_ID = PS.PARENT_ID AND PS2.FIELD_ID <> 12928
    WHERE L10.PARENT_ID = :I$CLASS_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    GROUP BY 1, 2
    ORDER BY 1, 2
    INTO :V$OBJ_ID, :V$SUBJECT_ID, :N
  DO
  BEGIN
    -- Нагрузку суммируем только за 8+ классы и все этапы СПО, чтобы не лезли предметы из 5-6-7 классов с неправильными названиями

    V$H = NULL;
    SELECT SUM(COALESCE(PL.LOAD_HOURS_S1, 0) + COALESCE(PL.LOAD_HOURS_S2, 0))
    FROM PLAN_SUBJECTS PS
    JOIN PLAN_LOADS PL ON PL.DATE_DEL IS NULL AND PL.SUBJECT_ID = PS.OBJ_ID AND PL.STAGE_ID IS NOT NULL
    JOIN VALL V381 ON V381.OBJ_ID = PL.STAGE_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0 AND V381.LISTVAL_ID IN (44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54)
    WHERE PS.DATE_DEL IS NULL AND PS.PLAN_ID = :V$OBJ_ID AND PS.ROW_TYPE = 10 AND (PS.SRC_SUBJECT_ID = :V$SUBJECT_ID OR PS.SUBJECT_ID = :V$SUBJECT_ID)
    INTO :V$H;
    V$H = COALESCE(V$H, 0);

    IF(V$H > 0) THEN
    BEGIN
      TAG_NAME = 'loads:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'loads:r:plan_id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'loads:r:subject_id';
      VAL = V$SUBJECT_ID;
      SUSPEND;
      TAG_NAME = 'loads:r:hours';
      VAL = V$H;
      SUSPEND;
      TAG_NAME = 'loads:r:index';
      VAL = N;
      SUSPEND;
      TAG_NAME = 'loads:r:place';
      IF(V$SUBJECT_ID = 34651) THEN VAL = 1; -- индпроект идет в прочие
      ELSE IF(V$H >= 64) THEN VAL = 0; -- предметы с 64+ часа, идет в основное приложение
      ELSE BEGIN
        -- если есть в обязательной части, идет в основное приложение
        VAL = 1;
        SELECT FIRST 1 0
        FROM PLAN_SUBJECTS PS
        JOIN PLAN_SUBJECTS PS2 ON PS2.OBJ_ID = PS.PARENT_ID AND PS2.FIELD_ID = 13303
        WHERE PS.DATE_DEL IS NULL AND (PS.SUBJECT_ID = :V$SUBJECT_ID OR PS.SRC_SUBJECT_ID = :V$SUBJECT_ID) AND PS.PLAN_ID = :V$OBJ_ID
        INTO :VAL;
      END
      SUSPEND;
    END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SDOCS_STATE_REPORT (
    I$STAGE_ID BIGINT,
    I$TYPE_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    VAL VARCHAR(4000))
AS
DECLARE VARIABLE V$YDATE DATE;
DECLARE VARIABLE V$YEAR_ID BIGINT;
DECLARE VARIABLE V$ORDER_ID BIGINT;
DECLARE VARIABLE V$ORDER_NUM VARCHAR(100);
DECLARE VARIABLE V$ORDER_DATE DATE;
DECLARE VARIABLE V$ACTION_DATE DATE;
DECLARE VARIABLE V$PERSON_ID BIGINT;
DECLARE VARIABLE V$GRADE_NAME VARCHAR(400);
DECLARE VARIABLE S VARCHAR(400);
DECLARE VARIABLE SS VARCHAR(1000);
DECLARE VARIABLE V$USER_TYPE SMALLINT;
DECLARE VARIABLE V$DOC_ID BIGINT;
DECLARE VARIABLE V$MASK SMALLINT;
DECLARE VARIABLE V$STATE_ID BIGINT;
DECLARE VARIABLE V$REF_NUM INTEGER;
DECLARE VARIABLE V VARCHAR(400);
DECLARE VARIABLE V$BLANK VARCHAR(100);
DECLARE VARIABLE V$GRADE_ID BIGINT;
DECLARE VARIABLE N1 INTEGER;
DECLARE VARIABLE N2 INTEGER;
begin

  SELECT FIRST 1 CAST(LV.TAG AS DATE), LV.LISTVAL_ID
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$YDATE, :V$YEAR_ID;

  SELECT MON$DATABASE_NAME
  FROM MON$DATABASE
  INTO :V;

  V = REPLACE(V, 'BASE.FDB', 'DOC.FDB');

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;
  SELECT USER_TYPE FROM USERS WHERE USER_ID = :I$USER_ID INTO :V$USER_TYPE;

  VAL = '<!DOCTYPE html>';
  VAL = VAL || '<html lang="ru">';
  VAL = VAL || '<head>';
  VAL = VAL || '<meta charset="utf-8" />';
  VAL = VAL || '<style>';
  VAL = VAL || 'html { font-family: Tahoma, Verdana, Arial;';
  VAL = VAL || 'font-size: 10pt; ';
  VAL = VAL || '} ';
  VAL = VAL || '</style>';

  VAL = VAL || '</head>';
  VAL = VAL || '<body>';
  SUSPEND;

  -- Заголовок отчета
  -- VAL = '<div class="title1"></div>';

  -- Выборка по классам

  VAL = VAL || '<table class="ui small compact fixed striped celled table">';
  VAL = VAL || '<thead><tr>';
    VAL = VAL || '<th>Класс/группа</th>';
    VAL = VAL || '<th>В приказах</th>';
    VAL = VAL || '<th>Отсутствуют в приказах</th>';
  VAL = VAL || '</tr></thead><tbody>';
  SUSPEND;
  FOR
    SELECT L9.OBJ_ID, C.CAPTION
    FROM LINKS L2
    JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID IN (7, 502) AND L7.DATE_DEL IS NULL
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 125, 187) AND L9.DATE_DEL IS NULL
    LEFT JOIN VALL VX ON VX.OBJ_ID = L9.OBJ_ID AND VX.PARAM_ID IN (2388, 2419, 2418) AND VX.IS_DEL = 0
    LEFT JOIN VALL VE ON VE.OBJ_ID = L9.OBJ_ID AND VE.PARAM_ID = 3344 AND VE.IS_DEL = 0
    LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C ON 1 = 1
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      AND (VX.LISTVAL_ID <> 11217 OR VE.LISTVAL_ID = 2)
    ORDER BY C.SORT_ORDER, C.CAPTION
    INTO :V$GRADE_ID, :S
  DO
  BEGIN
    -- Только действующие обучающиеся
    SELECT COUNT(DISTINCT L10.OBJ_ID)
    FROM LINKS L10
    WHERE L10.DATE_DEL IS NULL AND L10.PARENT_ID = :V$GRADE_ID AND L10.OBJ_TYPE_ID IN (10, 126)
    INTO :N1;

    SELECT COUNT(DISTINCT OD.REF_ID)
    FROM LINKS L10
    JOIN ORDER_DATA OD ON OD.DATE_DEL IS NULL AND OD.REF_ID = L10.OBJ_ID
    JOIN ORDERS D ON D.DATE_DEL IS NULL AND D.OBJ_ID = OD.ORDER_ID AND D.TYPE_ID = 13326 AND D.ACTION_DATE >= :V$YDATE AND D.STATE_ID IN (11715, 11716)
    WHERE L10.DATE_DEL IS NULL AND L10.PARENT_ID = :V$GRADE_ID AND L10.OBJ_TYPE_ID IN (10, 126)
    INTO :N2;

    VAL = '<tr class="';
      IF(N1 <> N2) THEN VAL = VAL || 'negative'; ELSE VAL = VAL || 'positive';
    VAL = VAL || '">';
    VAL = VAL || '<td>' || S || '</td>';

    VAL = VAL || '<td>' || N2 || '</td>';
    VAL = VAL || '<td>' || (N1 - N2) || '</td>';

    VAL = VAL || '</tr>';
    SUSPEND;
  END

  VAL = '</tbody></table>';
  SUSPEND;

  VAL = '</body></html>';
  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SDO_CLASS_LIST (
    I$OBJ_ID BIGINT)
RETURNS (
    F VARCHAR(1000),
    I VARCHAR(1000),
    O VARCHAR(1000),
    L VARCHAR(1000))
AS
DECLARE VARIABLE V$SCHOLAR_ID BIGINT;
DECLARE VARIABLE V$P BIGINT;
DECLARE VARIABLE V$GEN BIGINT;
DECLARE VARIABLE V$D DATE;
BEGIN

    FOR SELECT L.OBJ_ID
        FROM LINKS L
        WHERE L.PARENT_ID = :I$OBJ_ID
          AND L.OBJ_TYPE_ID = 10
          AND L.DATE_DEL IS NULL
        INTO :V$SCHOLAR_ID
    DO
    BEGIN
        F = '';
        I = '';
        O = '';
        L = '';

        SELECT V.VAL
        FROM VALS V
        WHERE V.PARAM_ID = 55
          AND V.OBJ_ID = :V$SCHOLAR_ID
          AND V.IS_DEL = 0
        INTO :F;

        SELECT V.VAL
        FROM VALS V
        WHERE V.PARAM_ID = 56
          AND V.OBJ_ID = :V$SCHOLAR_ID
          AND V.IS_DEL = 0
        INTO :I;

        SELECT V.VAL
        FROM VALS V
        WHERE V.PARAM_ID = 57
          AND V.OBJ_ID = :V$SCHOLAR_ID
          AND V.IS_DEL = 0
        INTO :O;

        SELECT V.VAL
        FROM VALS V
        WHERE V.PARAM_ID = 1380
          AND V.OBJ_ID = :V$SCHOLAR_ID
          AND V.IS_DEL = 0
        INTO :L;

        IF (L = '') THEN
        BEGIN
            SELECT VAL
            FROM TRANSLITERATION(:F)
            INTO L;

            V$D = '2000-01-01';

            SELECT V.VAL
            FROM VALD V
            WHERE V.PARAM_ID = 89
              AND V.OBJ_ID = :V$SCHOLAR_ID
              AND V.IS_DEL = 0
            INTO :V$D;

            SELECT FIRST 1 GEN
            FROM GEN
            INTO :V$GEN;

            V$P = V$SCHOLAR_ID - V$GEN * 1000000000;

            L = L || EXTRACT(DAY FROM V$D) || EXTRACT(MONTH FROM V$D) || CAST(V$P AS VARCHAR(10));

            SELECT BLOB_ID
            FROM VAL_ADD(1380, :V$SCHOLAR_ID, :L)
            INTO :V$P;
        END

        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SDO_EXPORT RETURNS (
    TAG_NAME VARCHAR(255),
    VAL VARCHAR(4000))
AS
declare variable V$SCHOOL_ID bigint;
declare variable V$SDO_ID varchar(1000);
declare variable V$DATE_BIRTH varchar(1000);
declare variable V$OBJ_ID bigint;
declare variable V$OBJ_ID_MORE bigint;
declare variable V$STR varchar(4000);
declare variable V$CLASS_ID bigint;
declare variable V$SUBGROUP_ID bigint;
declare variable V$PUPIL_ID bigint;
BEGIN

    SELECT L.OBJ_ID
    FROM LINKS L
    WHERE L.OBJ_TYPE_ID = 2 AND L.DATE_DEL IS NULL AND L.PARENT_ID IS NULL
    INTO :V$SCHOOL_ID;

    TAG_NAME = 'datapacket::packet_type';
    VAL = 'send_data';
    SUSPEND;

    TAG_NAME = 'datapacket::version';
    SELECT V.VER_MAJOR || '.' || V.VER_MINOR || '.' || V.VER_RELEASE || '.' || V.VER_BUILD
    FROM VER V
    WHERE V.VER_ID = 1
    INTO :VAL;
    SUSPEND;

    TAG_NAME = 'datapacket::level';
    VAL = '1';
    SUSPEND;

    TAG_NAME = 'datapacket::reg_number';
    SELECT GEN
    FROM GEN
    INTO :VAL;
    SUSPEND;

    TAG_NAME = 'datapacket::ogrn';
    SELECT V9.VAL FROM VALS V9
    WHERE V9.OBJ_ID = :V$SCHOOL_ID AND V9.IS_DEL = 0 AND V9.PARAM_ID = 9
    INTO :VAL;
    SUSPEND;

    TAG_NAME = 'datapacket::comp_name';
    SELECT RDB$GET_CONTEXT('SYSTEM', 'CLIENT_ADDRESS')
    FROM RDB$DATABASE
    INTO :VAL;
    SUSPEND;

    TAG_NAME = 'datapacket::interval_end_date';
    SELECT
        lpad(EXTRACT(YEAR FROM CURRENT_DATE),4,'0')||'-'||
        lpad(EXTRACT(MONTH FROM CURRENT_DATE),2,'0')||'-'||
        lpad(EXTRACT(DAY FROM CURRENT_DATE),2,'0')||' '||
        lpad(EXTRACT(HOUR FROM CURRENT_TIME),2,'0')||':'||
        lpad(EXTRACT(MINUTE FROM CURRENT_TIME),2,'0')
    FROM RDB$DATABASE
    INTO :VAL;
    SUSPEND;

    FOR
        -- Обычные сотрудники
        SELECT L14.OBJ_ID, V2152.VAL, CAST(V59.VAL || ' ' || V60.VAL || COALESCE(' ' || V61.VAL, '') AS VARCHAR(1000)),
           LPAD(EXTRACT(DAY FROM V241.VAL), 2, 0) || LPAD(EXTRACT(MONTH FROM V241.VAL), 2, 0) || LPAD(EXTRACT(YEAR FROM V241.VAL), 4, 0)
        FROM LINKS L14
        JOIN VALS V2152 ON V2152.PARAM_ID = 2152 AND V2152.OBJ_ID = L14.OBJ_ID AND V2152.VAL IS NOT NULL AND V2152.IS_DEL = 0
        LEFT JOIN VALS V59 ON V59.OBJ_ID = L14.OBJ_ID AND V59.PARAM_ID = 59 AND V59.IS_DEL = 0
        LEFT JOIN VALS V60 ON V60.OBJ_ID = L14.OBJ_ID AND V60.PARAM_ID = 60 AND V60.IS_DEL = 0
        LEFT JOIN VALS V61 ON V61.OBJ_ID = L14.OBJ_ID AND V61.PARAM_ID = 61 AND V61.IS_DEL = 0
        LEFT JOIN VALD V241 ON V241.OBJ_ID = L14.OBJ_ID AND V241.PARAM_ID = 241 AND V241.IS_DEL = 0
        WHERE L14.OBJ_TYPE_ID = 14 AND L14.PARENT_ID = :V$SCHOOL_ID AND L14.DATE_DEL IS NULL
        -- УДОД, подразделения 1 уровня
        UNION
        SELECT L14.OBJ_ID, V2152.VAL, CAST(V59.VAL || ' ' || V60.VAL || COALESCE(' ' || V61.VAL, '') AS VARCHAR(1000)),
           LPAD(EXTRACT(DAY FROM V241.VAL), 2, 0) || LPAD(EXTRACT(MONTH FROM V241.VAL), 2, 0) || LPAD(EXTRACT(YEAR FROM V241.VAL), 4, 0)
        FROM LINKS L211
        JOIN LINKS L14 ON L14.OBJ_TYPE_ID = 14 AND L14.PARENT_ID = L211.OBJ_ID AND L14.DATE_DEL IS NULL
        JOIN VALS V2152 ON V2152.PARAM_ID = 2152 AND V2152.OBJ_ID = L14.OBJ_ID AND V2152.VAL IS NOT NULL AND V2152.IS_DEL = 0
        LEFT JOIN VALS V59 ON V59.OBJ_ID = L14.OBJ_ID AND V59.PARAM_ID = 59 AND V59.IS_DEL = 0
        LEFT JOIN VALS V60 ON V60.OBJ_ID = L14.OBJ_ID AND V60.PARAM_ID = 60 AND V60.IS_DEL = 0
        LEFT JOIN VALS V61 ON V61.OBJ_ID = L14.OBJ_ID AND V61.PARAM_ID = 61 AND V61.IS_DEL = 0
        LEFT JOIN VALD V241 ON V241.OBJ_ID = L14.OBJ_ID AND V241.PARAM_ID = 241 AND V241.IS_DEL = 0
        WHERE L211.OBJ_TYPE_ID = 211 AND L211.PARENT_ID = :V$SCHOOL_ID AND L211.DATE_DEL IS NULL
        INTO :V$OBJ_ID, :V$SDO_ID, :V$STR, :V$DATE_BIRTH
    DO
    BEGIN
        TAG_NAME = 'datapacket:teachers:teacher::teacher_id';
        VAL = V$OBJ_ID;
        SUSPEND;            

        TAG_NAME = 'datapacket:teachers:teacher::teacher_id_elms';
        VAL = V$SDO_ID;
        SUSPEND;            

        TAG_NAME = 'datapacket:teachers:teacher::fio';
        VAL = V$STR;
        SUSPEND;            

        TAG_NAME = 'datapacket:teachers:teacher::birthdate';
        VAL = V$DATE_BIRTH;
        SUSPEND;            
    END

    FOR
        SELECT L9.OBJ_ID, C.CAPTION
        FROM LINKS L7
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.DATE_DEL IS NULL AND L8.OBJ_TYPE_ID = 8
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.DATE_DEL IS NULL AND L9.OBJ_TYPE_ID IN (9, 187)
        LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C ON 1 = 1
        WHERE L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL AND L7.PARENT_ID = :V$SCHOOL_ID
        -- УДОД
        UNION
        SELECT L243.OBJ_ID, C1.CAPTION || ' - ' || C2.CAPTION
        FROM LINKS L242
        JOIN LINKS L243 ON L243.PARENT_ID = L242.OBJ_ID AND L243.DATE_DEL IS NULL AND L243.OBJ_TYPE_ID = 243
        LEFT JOIN OBJECT_CAPTION_GET(L242.OBJ_ID) C1 ON 1 = 1
        LEFT JOIN OBJECT_CAPTION_GET(L243.OBJ_ID) C2 ON 1 = 1
        WHERE L242.OBJ_TYPE_ID = 242 AND L242.DATE_DEL IS NULL AND L242.PARENT_ID = :V$SCHOOL_ID
        -- УДОД подразделения 1 уровня
        UNION
        SELECT L243.OBJ_ID, C1.CAPTION || ' - ' || C2.CAPTION
        FROM LINKS L211
        JOIN LINKS L242 ON L242.PARENT_ID = L211.OBJ_ID AND L242.DATE_DEL IS NULL AND L242.OBJ_TYPE_ID = 242
        JOIN LINKS L243 ON L243.PARENT_ID = L242.OBJ_ID AND L243.DATE_DEL IS NULL AND L243.OBJ_TYPE_ID = 243
        LEFT JOIN OBJECT_CAPTION_GET(L242.OBJ_ID) C1 ON 1 = 1
        LEFT JOIN OBJECT_CAPTION_GET(L243.OBJ_ID) C2 ON 1 = 1
        WHERE L211.OBJ_TYPE_ID = 211 AND L211.DATE_DEL IS NULL AND L211.PARENT_ID = :V$SCHOOL_ID
        INTO :V$OBJ_ID, :V$STR
    DO
    BEGIN
        TAG_NAME = 'datapacket:classes:class::class_id';
        VAL = V$OBJ_ID;
        SUSPEND;            

        TAG_NAME = 'datapacket:classes:class::class_name';
        VAL = V$STR;
        SUSPEND;               
    END

    FOR
        SELECT L9.OBJ_ID, L48.OBJ_ID, C48.CAPTION
        FROM LINKS L7
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.DATE_DEL IS NULL AND L8.OBJ_TYPE_ID = 8
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.DATE_DEL IS NULL AND L9.OBJ_TYPE_ID IN (9, 187)
        JOIN LINKS L47 ON L47.PARENT_ID = L9.OBJ_ID AND L47.DATE_DEL IS NULL AND L47.OBJ_TYPE_ID = 47
        JOIN LINKS L48 ON L48.PARENT_ID = L47.OBJ_ID AND L48.DATE_DEL IS NULL AND L48.OBJ_TYPE_ID = 48
        LEFT JOIN OBJECT_CAPTION_GET(L48.OBJ_ID) C48 ON 1=1
        WHERE L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL AND L7.PARENT_ID = :V$SCHOOL_ID
        INTO :V$OBJ_ID_MORE, :V$OBJ_ID, :V$STR
    DO
    BEGIN
        TAG_NAME = 'datapacket:subgroups:subgroup::subgroup_id';
        VAL = V$OBJ_ID;
        SUSPEND;            

        TAG_NAME = 'datapacket:subgroups:subgroup::subgroup_name';
        VAL = V$STR;
        SUSPEND;               
        
        TAG_NAME = 'datapacket:subgroups:subgroup::class_id';
        VAL = V$OBJ_ID_MORE;
        SUSPEND;               

    END

    FOR
        -- Школы
        SELECT L9.OBJ_ID, L10.OBJ_ID, V2153.VAL, LPAD(EXTRACT(DAY FROM V89.VAL), 2, 0) || LPAD(EXTRACT(MONTH FROM V89.VAL), 2, 0) || LPAD(EXTRACT(YEAR FROM V89.VAL), 4, 0)
        FROM LINKS L7
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.DATE_DEL IS NULL AND L8.OBJ_TYPE_ID = 8
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.DATE_DEL IS NULL AND L9.OBJ_TYPE_ID IN (9, 187)
        JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.DATE_DEL IS NULL AND L10.OBJ_TYPE_ID = 10
        JOIN VALS V2153 ON V2153.PARAM_ID = 2153 AND V2153.OBJ_ID = L10.OBJ_ID AND V2153.IS_DEL = 0
        LEFT JOIN VALD V89 ON V89.PARAM_ID = 89 AND V89.OBJ_ID = L10.OBJ_ID AND V89.IS_DEL = 0
        WHERE L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL AND L7.PARENT_ID = :V$SCHOOL_ID
        -- УДОД
        UNION
        SELECT L243.OBJ_ID, L10.OBJ_ID, V2153.VAL, LPAD(EXTRACT(DAY FROM V89.VAL), 2, 0) || LPAD(EXTRACT(MONTH FROM V89.VAL), 2, 0) || LPAD(EXTRACT(YEAR FROM V89.VAL), 4, 0)
        FROM LINKS L242
        JOIN LINKS L243 ON L243.PARENT_ID = L242.OBJ_ID AND L243.DATE_DEL IS NULL AND L243.OBJ_TYPE_ID = 243
        JOIN LINKS L10 ON L10.PARENT_ID = L243.OBJ_ID AND L10.DATE_DEL IS NULL AND L10.OBJ_TYPE_ID = 10
        JOIN VALS V2153 ON V2153.PARAM_ID = 2153 AND V2153.OBJ_ID = L10.OBJ_ID AND V2153.IS_DEL = 0
        LEFT JOIN VALD V89 ON V89.PARAM_ID = 89 AND V89.OBJ_ID = L10.OBJ_ID AND V89.IS_DEL = 0
        WHERE L242.OBJ_TYPE_ID = 242 AND L242.DATE_DEL IS NULL AND L242.PARENT_ID = :V$SCHOOL_ID
        -- УДОД подразделения 1 уровня
        UNION
        SELECT L243.OBJ_ID, L10.OBJ_ID, V2153.VAL, LPAD(EXTRACT(DAY FROM V89.VAL), 2, 0) || LPAD(EXTRACT(MONTH FROM V89.VAL), 2, 0) || LPAD(EXTRACT(YEAR FROM V89.VAL), 4, 0)
        FROM LINKS L211
        JOIN LINKS L242 ON L242.PARENT_ID = L211.OBJ_ID AND L242.DATE_DEL IS NULL AND L242.OBJ_TYPE_ID = 242
        JOIN LINKS L243 ON L243.PARENT_ID = L242.OBJ_ID AND L243.DATE_DEL IS NULL AND L243.OBJ_TYPE_ID = 243
        JOIN LINKS L10 ON L10.PARENT_ID = L243.OBJ_ID AND L10.DATE_DEL IS NULL AND L10.OBJ_TYPE_ID = 10
        JOIN VALS V2153 ON V2153.PARAM_ID = 2153 AND V2153.OBJ_ID = L10.OBJ_ID AND V2153.IS_DEL = 0
        LEFT JOIN VALD V89 ON V89.PARAM_ID = 89 AND V89.OBJ_ID = L10.OBJ_ID AND V89.IS_DEL = 0
        WHERE L211.OBJ_TYPE_ID = 211 AND L211.DATE_DEL IS NULL AND L211.PARENT_ID = :V$SCHOOL_ID
        INTO :V$CLASS_ID, :V$PUPIL_ID, :V$SDO_ID, :V$DATE_BIRTH
     DO
     BEGIN
        TAG_NAME = 'datapacket:students:student::student_id';
        VAL = V$PUPIL_ID;
        SUSPEND; 

        TAG_NAME = 'datapacket:students:student::student_id_elms';
        VAL = V$SDO_ID;
        SUSPEND; 

        TAG_NAME = 'datapacket:students:student::class_id';
        VAL = V$CLASS_ID;
        SUSPEND; 

        TAG_NAME = 'datapacket:students:student::birthdate';
        VAL = V$DATE_BIRTH;
        SUSPEND; 

        -- Тут смотрим только школы, и то это все устарело
        FOR
            SELECT LP48.PARENT_ID
            FROM LINKS LP48
            WHERE LP48.OBJ_ID = :V$PUPIL_ID AND LP48.PARENT_TYPE_ID = 48 AND LP48.DATE_DEL IS NULL
            INTO :V$SUBGROUP_ID
        DO
        BEGIN
            TAG_NAME = 'datapacket:students:student:subgroup::subgroup_id';
            VAL = V$SUBGROUP_ID;
            SUSPEND; 
        END
     END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SDO_EXPORT_CLASS (
    I$CLASS_ID BIGINT)
RETURNS (
    TAG_NAME VARCHAR(255),
    VAL VARCHAR(4000))
AS
declare variable V$SCHOOL_ID bigint;
declare variable V$SDO_ID varchar(1000);
declare variable V$DATE_BIRTH varchar(1000);
declare variable V$OBJ_ID bigint;
declare variable V$OBJ_ID_MORE bigint;
declare variable V$STR varchar(4000);
declare variable V$SUBGROUP_ID bigint;
declare variable V$PUPIL_ID bigint;
declare variable V$CLASS_ID bigint;
BEGIN

    SELECT L.OBJ_ID FROM LINKS L
    WHERE L.OBJ_TYPE_ID = 2 AND L.DATE_DEL IS NULL AND L.PARENT_ID IS NULL
    INTO :V$SCHOOL_ID;

    TAG_NAME = 'datapacket::packet_type';
    VAL = 'send_data';
    SUSPEND;

    TAG_NAME = 'datapacket::version';
    SELECT V.VER_MAJOR||'.'||V.VER_MINOR||'.'||V.VER_RELEASE||'.'||V.VER_BUILD FROM VER V
    WHERE V.VER_ID = 1
    INTO :VAL;
    SUSPEND;

    TAG_NAME = 'datapacket::level';
    VAL = '1';
    SUSPEND;

    TAG_NAME = 'datapacket::reg_number';
    SELECT GEN FROM GEN
    INTO :VAL;
    SUSPEND;

    TAG_NAME = 'datapacket::ogrn';
    SELECT V9.VAL FROM VALS V9
    WHERE V9.OBJ_ID = :V$SCHOOL_ID AND V9.IS_DEL = 0 AND V9.PARAM_ID = 9
    INTO :VAL;
    SUSPEND;

    TAG_NAME = 'datapacket::comp_name';
    SELECT RDB$GET_CONTEXT('SYSTEM', 'CLIENT_ADDRESS') FROM RDB$DATABASE
    INTO :VAL;
    SUSPEND;

    TAG_NAME = 'datapacket::interval_end_date';
    SELECT
        lpad(EXTRACT(YEAR FROM CURRENT_DATE),4,'0')||'-'||
        lpad(EXTRACT(MONTH FROM CURRENT_DATE),2,'0')||'-'||
        lpad(EXTRACT(DAY FROM CURRENT_DATE),2,'0')||' '||
        lpad(EXTRACT(HOUR FROM CURRENT_TIME),2,'0')||':'||
        lpad(EXTRACT(MINUTE FROM CURRENT_TIME),2,'0')
    FROM RDB$DATABASE
    INTO :VAL;
    SUSPEND;

    FOR
        SELECT L14.OBJ_ID, V2152.VAL, V59.VAL || ' ' || V60.VAL || ' ' || V61.VAL,
            LPAD(EXTRACT(DAY FROM V241.VAL),2,0)|| LPAD(EXTRACT(MONTH FROM V241.VAL),2,0)|| LPAD(EXTRACT(YEAR FROM V241.VAL),4,0)
        FROM LINKS L14
        JOIN VALS V2152 ON V2152.PARAM_ID = 2152 AND V2152.OBJ_ID = L14.OBJ_ID AND V2152.VAL IS NOT NULL AND V2152.IS_DEL = 0
        LEFT JOIN VALS V59 ON V59.OBJ_ID = L14.OBJ_ID AND V59.PARAM_ID = 59 AND V59.IS_DEL = 0
        LEFT JOIN VALS V60 ON V60.OBJ_ID = L14.OBJ_ID AND V60.PARAM_ID = 60 AND V60.IS_DEL = 0
        LEFT JOIN VALS V61 ON V61.OBJ_ID = L14.OBJ_ID AND V61.PARAM_ID = 61 AND V61.IS_DEL = 0
        LEFT JOIN VALD V241 ON V241.OBJ_ID = L14.OBJ_ID AND V241.PARAM_ID = 241 AND V241.IS_DEL = 0
        WHERE L14.OBJ_TYPE_ID = 14 AND L14.PARENT_ID = :V$SCHOOL_ID AND L14.DATE_DEL IS NULL
        INTO :V$OBJ_ID, :V$SDO_ID, :V$STR, :V$DATE_BIRTH
    DO
    BEGIN
        TAG_NAME = 'datapacket:teachers:teacher::teacher_id';
        VAL = V$OBJ_ID;
        SUSPEND;            

        TAG_NAME = 'datapacket:teachers:teacher::teacher_id_elms';
        VAL = V$SDO_ID;
        SUSPEND;            

        TAG_NAME = 'datapacket:teachers:teacher::fio';
        VAL = V$STR;
        SUSPEND;            

        TAG_NAME = 'datapacket:teachers:teacher::birthdate';
        VAL = V$DATE_BIRTH;
        SUSPEND;            
    END

    FOR
        SELECT L9.OBJ_ID, C.CAPTION
        FROM LINKS L7
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.DATE_DEL IS NULL AND L8.OBJ_TYPE_ID = 8
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.DATE_DEL IS NULL AND L9.OBJ_TYPE_ID IN (9, 187) AND (L9.OBJ_ID = :I$CLASS_ID OR :I$CLASS_ID IS NULL)
        LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C ON 1 = 1
        WHERE L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL AND L7.PARENT_ID = :V$SCHOOL_ID
        -- УДОД
        UNION
        SELECT L243.OBJ_ID, C1.CAPTION || ' - ' || C2.CAPTION
        FROM LINKS L242
        JOIN LINKS L243 ON L243.PARENT_ID = L242.OBJ_ID AND L243.DATE_DEL IS NULL AND L243.OBJ_TYPE_ID = 243 AND (L243.OBJ_ID = :I$CLASS_ID OR :I$CLASS_ID IS NULL)
        LEFT JOIN OBJECT_CAPTION_GET(L242.OBJ_ID) C1 ON 1 = 1
        LEFT JOIN OBJECT_CAPTION_GET(L243.OBJ_ID) C2 ON 1 = 1
        WHERE L242.OBJ_TYPE_ID = 242 AND L242.DATE_DEL IS NULL AND L242.PARENT_ID = :V$SCHOOL_ID
        -- УДОД подразделения 1 уровня
        UNION
        SELECT L243.OBJ_ID, C1.CAPTION || ' - ' || C2.CAPTION
        FROM LINKS L211
        JOIN LINKS L242 ON L242.PARENT_ID = L211.OBJ_ID AND L242.DATE_DEL IS NULL AND L242.OBJ_TYPE_ID = 242
        JOIN LINKS L243 ON L243.PARENT_ID = L242.OBJ_ID AND L243.DATE_DEL IS NULL AND L243.OBJ_TYPE_ID = 243 AND (L243.OBJ_ID = :I$CLASS_ID OR :I$CLASS_ID IS NULL)
        LEFT JOIN OBJECT_CAPTION_GET(L242.OBJ_ID) C1 ON 1 = 1
        LEFT JOIN OBJECT_CAPTION_GET(L243.OBJ_ID) C2 ON 1 = 1
        WHERE L211.OBJ_TYPE_ID = 211 AND L211.DATE_DEL IS NULL AND L211.PARENT_ID = :V$SCHOOL_ID
        INTO :V$OBJ_ID, :V$STR
    DO
    BEGIN
        TAG_NAME = 'datapacket:classes:class::class_id';
        VAL = V$OBJ_ID;
        SUSPEND;            

        TAG_NAME = 'datapacket:classes:class::class_name';
        VAL = V$STR;
        SUSPEND;               
    END

    FOR
        SELECT L9.OBJ_ID, L48.OBJ_ID, C.CAPTION
        FROM LINKS L7
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.DATE_DEL IS NULL AND L8.OBJ_TYPE_ID = 8
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.DATE_DEL IS NULL AND L9.OBJ_TYPE_ID IN (9, 187) AND (L9.OBJ_ID = :I$CLASS_ID OR :I$CLASS_ID IS NULL)
        JOIN LINKS L47 ON L47.PARENT_ID = L9.OBJ_ID AND L47.DATE_DEL IS NULL AND L47.OBJ_TYPE_ID = 47
        JOIN LINKS L48 ON L48.PARENT_ID = L47.OBJ_ID AND L48.DATE_DEL IS NULL AND L48.OBJ_TYPE_ID = 48
        LEFT JOIN OBJECT_CAPTION_GET(L48.OBJ_ID) C ON 1=1
        WHERE L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL AND L7.PARENT_ID = :V$SCHOOL_ID
        INTO :V$OBJ_ID_MORE, :V$OBJ_ID, :V$STR
    DO
    BEGIN
        TAG_NAME = 'datapacket:subgroups:subgroup::subgroup_id';
        VAL = V$OBJ_ID;
        SUSPEND;            

        TAG_NAME = 'datapacket:subgroups:subgroup::subgroup_name';
        VAL = V$STR;
        SUSPEND;               
        
        TAG_NAME = 'datapacket:subgroups:subgroup::class_id';
        VAL = V$OBJ_ID_MORE;
        SUSPEND;
    END

    FOR
        SELECT L10.OBJ_ID, L9.OBJ_ID, V2153.VAL, LPAD(EXTRACT(DAY FROM V89.VAL),2,0) || LPAD(EXTRACT(MONTH FROM V89.VAL),2,0) || LPAD(EXTRACT(YEAR FROM V89.VAL),4,0)
        FROM LINKS L7
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.DATE_DEL IS NULL AND L8.OBJ_TYPE_ID = 8
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.DATE_DEL IS NULL AND L9.OBJ_TYPE_ID IN (9, 187) AND (L9.OBJ_ID = :I$CLASS_ID OR :I$CLASS_ID IS NULL)
        JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.DATE_DEL IS NULL AND L10.OBJ_TYPE_ID = 10
        JOIN VALS V2153 ON V2153.PARAM_ID = 2153 AND V2153.OBJ_ID = L10.OBJ_ID AND V2153.IS_DEL = 0
        LEFT JOIN VALD V89 ON V89.PARAM_ID = 89 AND V89.OBJ_ID = L10.OBJ_ID AND V89.IS_DEL = 0
        WHERE L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL AND L7.PARENT_ID = :V$SCHOOL_ID
        -- УДОД
        UNION
        SELECT L10.OBJ_ID, L243.OBJ_ID, V2153.VAL, LPAD(EXTRACT(DAY FROM V89.VAL), 2, 0) || LPAD(EXTRACT(MONTH FROM V89.VAL), 2, 0) || LPAD(EXTRACT(YEAR FROM V89.VAL), 4, 0)
        FROM LINKS L242
        JOIN LINKS L243 ON L243.PARENT_ID = L242.OBJ_ID AND L243.DATE_DEL IS NULL AND L243.OBJ_TYPE_ID = 243 AND (L243.OBJ_ID = :I$CLASS_ID OR :I$CLASS_ID IS NULL)
        JOIN LINKS L10 ON L10.PARENT_ID = L243.OBJ_ID AND L10.DATE_DEL IS NULL AND L10.OBJ_TYPE_ID = 10
        JOIN VALS V2153 ON V2153.PARAM_ID = 2153 AND V2153.OBJ_ID = L10.OBJ_ID AND V2153.IS_DEL = 0
        LEFT JOIN VALD V89 ON V89.PARAM_ID = 89 AND V89.OBJ_ID = L10.OBJ_ID AND V89.IS_DEL = 0
        WHERE L242.OBJ_TYPE_ID = 242 AND L242.DATE_DEL IS NULL AND L242.PARENT_ID = :V$SCHOOL_ID
        -- УДОД подразделения 1 уровня
        UNION
        SELECT L10.OBJ_ID, L243.OBJ_ID, V2153.VAL, LPAD(EXTRACT(DAY FROM V89.VAL), 2, 0) || LPAD(EXTRACT(MONTH FROM V89.VAL), 2, 0) || LPAD(EXTRACT(YEAR FROM V89.VAL), 4, 0)
        FROM LINKS L211
        JOIN LINKS L242 ON L242.PARENT_ID = L211.OBJ_ID AND L242.DATE_DEL IS NULL AND L242.OBJ_TYPE_ID = 242
        JOIN LINKS L243 ON L243.PARENT_ID = L242.OBJ_ID AND L243.DATE_DEL IS NULL AND L243.OBJ_TYPE_ID = 243 AND (L243.OBJ_ID = :I$CLASS_ID OR :I$CLASS_ID IS NULL)
        JOIN LINKS L10 ON L10.PARENT_ID = L243.OBJ_ID AND L10.DATE_DEL IS NULL AND L10.OBJ_TYPE_ID = 10
        JOIN VALS V2153 ON V2153.PARAM_ID = 2153 AND V2153.OBJ_ID = L10.OBJ_ID AND V2153.IS_DEL = 0
        LEFT JOIN VALD V89 ON V89.PARAM_ID = 89 AND V89.OBJ_ID = L10.OBJ_ID AND V89.IS_DEL = 0
        WHERE L211.OBJ_TYPE_ID = 211 AND L211.DATE_DEL IS NULL AND L211.PARENT_ID = :V$SCHOOL_ID
        INTO :V$PUPIL_ID, :V$CLASS_ID, :V$SDO_ID, :V$DATE_BIRTH
     DO
     BEGIN
        TAG_NAME = 'datapacket:students:student::student_id';
        VAL = V$PUPIL_ID;
        SUSPEND; 

        TAG_NAME = 'datapacket:students:student::student_id_elms';
        VAL = V$SDO_ID;
        SUSPEND; 

        TAG_NAME = 'datapacket:students:student::class_id';
        VAL = V$CLASS_ID;
        SUSPEND; 

        TAG_NAME = 'datapacket:students:student::birthdate';
        VAL = V$DATE_BIRTH;
        SUSPEND; 

        FOR
            SELECT LP48.PARENT_ID
            FROM LINKS LP48
            WHERE LP48.OBJ_ID = :V$PUPIL_ID AND LP48.PARENT_TYPE_ID = 48 AND LP48.DATE_DEL IS NULL
            INTO :V$SUBGROUP_ID
        DO
        BEGIN
            TAG_NAME = 'datapacket:students:student:subgroup::subgroup_id';
            VAL = V$SUBGROUP_ID;
            SUSPEND; 
        END
     END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SDO_OU_NUM RETURNS (
    NUM VARCHAR(4000))
AS
declare variable SCHOOL_ID bigint;
BEGIN
    SELECT FIRST 1 L.OBJ_ID
    FROM LINKS L
    WHERE L.PARENT_ID IS NULL
      AND L.OBJ_TYPE_ID = 2
      AND L.DATE_DEL IS NULL
    INTO :SCHOOL_ID;

    NUM = '';

    SELECT V.VAL
    FROM VALI V
    WHERE V.PARAM_ID = 17
      AND V.OBJ_ID = :SCHOOL_ID
      AND V.IS_DEL = 0
    INTO :NUM;

    IF (NUM = '') THEN
    BEGIN
        SELECT SUBSTRING(V.VAL FROM 1 FOR 32)
        FROM VALS V
        WHERE V.PARAM_ID = 2 AND V.OBJ_ID = :SCHOOL_ID AND V.IS_DEL = 0
        INTO :NUM;
    END

    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SEARCHFIELDS_ADD (
    I$SEARCH_ID BIGINT,
    I$TYPE_ID BIGINT,
    I$PARAM_ID BIGINT,
    I$GRID_ORDER SMALLINT,
    I$SEARCH_AGREGATE VARCHAR(3))
RETURNS (
    SEARCH_ID BIGINT)
AS
BEGIN
    INSERT INTO SEARCHFIELDS (SEARCH_ID, TYPE_ID, PARAM_ID, GRID_ORDER, SEARCH_AGREGATE)
    VALUES (:I$SEARCH_ID, :I$TYPE_ID, :I$PARAM_ID, :I$GRID_ORDER, :I$SEARCH_AGREGATE);

    SEARCH_ID = I$SEARCH_ID;

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SEARCHFIELDS_GET (
    I$SEARCH_ID BIGINT)
RETURNS (
    SEARCH_ID BIGINT,
    TYPE_ID BIGINT,
    PARAM_ID BIGINT,
    GRID_ORDER SMALLINT,
    SEARCH_AGREGATE VARCHAR(3))
AS
BEGIN
    FOR SELECT SEARCH_ID, TYPE_ID, PARAM_ID, GRID_ORDER, SEARCH_AGREGATE
        FROM SEARCHFIELDS
        WHERE SEARCH_ID = :I$SEARCH_ID
        ORDER BY GRID_ORDER
        INTO :SEARCH_ID, :TYPE_ID, :PARAM_ID, :GRID_ORDER, :SEARCH_AGREGATE
    DO
        SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SEARCHPARAMS_ADD (
    I$SEARCH_ID BIGINT,
    I$TYPE_ID BIGINT,
    I$EXT_TYPE_ID BIGINT,
    I$PARAM_ID BIGINT,
    I$SORT_ORDER SMALLINT,
    I$SEARCH_TERM VARCHAR(10),
    I$VAL_S VARCHAR(4000),
    I$VAL_I BIGINT,
    I$VAL_F DOUBLE PRECISION,
    I$VAL_D DATE)
RETURNS (
    SEARCH_ID BIGINT)
AS
BEGIN
    INSERT INTO SEARCHPARAMS (SEARCH_ID, TYPE_ID, EXT_TYPE_ID, PARAM_ID, SORT_ORDER, SEARCH_TERM, VAL_S, VAL_I, VAL_F, VAL_D)
    VALUES (:I$SEARCH_ID, :I$TYPE_ID, :I$EXT_TYPE_ID, :I$PARAM_ID, :I$SORT_ORDER, :I$SEARCH_TERM, :I$VAL_S, :I$VAL_I, :I$VAL_F, :I$VAL_D);

    SEARCH_ID = I$SEARCH_ID;

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SEARCHPARAMS_GET (
    I$SEARCH_ID BIGINT,
    I$LANG_CODE VARCHAR(2) = 'RU')
RETURNS (
    SEARCH_ID BIGINT,
    TYPE_ID BIGINT,
    EXT_TYPE_ID BIGINT,
    PARAM_ID BIGINT,
    ROW_INDEX SMALLINT,
    SEARCH_TERM VARCHAR(10),
    VAL_S VARCHAR(4000),
    VAL_I BIGINT,
    VAL_F DOUBLE PRECISION,
    VAL_D DATE,
    TAB_ID BIGINT,
    TAB_CAPTION VARCHAR(4000),
    TAB_NUM SMALLINT,
    PARAM_TYPE SMALLINT,
    EDIT_TYPE SMALLINT,
    NATIVE SMALLINT,
    CAPTION VARCHAR(4000),
    IS_CHECKED SMALLINT,
    GRID_ORDER SMALLINT,
    LIST_ID BIGINT,
    TAG VARCHAR(100),
    RUN_SQL VARCHAR(1000),
    BKG_COLOR INTEGER)
AS
declare variable TAB_RES_ID bigint;
declare variable PARAM_RES_ID bigint;
declare variable SIZE_RES_ID bigint;
declare variable V varchar(4000);
BEGIN
    IS_CHECKED = 0;
    EDIT_TYPE = 1;
    NATIVE = 1;

    FOR
        SELECT SP.SEARCH_ID,
               SP.TYPE_ID,
               SP.EXT_TYPE_ID,
               SP.PARAM_ID,
               SP.SORT_ORDER,
               SP.SEARCH_TERM,
               SP.VAL_S,
               SP.VAL_I,
               SP.VAL_F,
               SP.VAL_D,
               P.TAB_ID,
               P.PARAM_TYPE,
               P.RES_ID,
               P.SIZE_RES_ID,
               P.GRID_ORDER,
               P.LIST_ID,
               P.TAG,
               P.RUN_SQL,
               PT.BKG_COLOR
        FROM SEARCHPARAMS SP

        JOIN PARAMS P
        ON P.PARAM_ID = SP.PARAM_ID

        JOIN PARAMTYPES PT
        ON PT.PARAM_TYPE = P.PARAM_TYPE

        WHERE SP.SEARCH_ID = :I$SEARCH_ID

        ORDER BY SORT_ORDER

        INTO :SEARCH_ID,
             :TYPE_ID,
             :EXT_TYPE_ID,
             :PARAM_ID,
             :ROW_INDEX,
             :SEARCH_TERM,
             :VAL_S,
             :VAL_I,
             :VAL_F,
             :VAL_D,
             :TAB_ID,
             :PARAM_TYPE,
             :PARAM_RES_ID,
             :SIZE_RES_ID,
             :GRID_ORDER,
             :LIST_ID,
             :TAG,
             :RUN_SQL,
             :BKG_COLOR
    DO
    BEGIN
        TAB_CAPTION = '';
        TAB_NUM = NULL;
        TAB_RES_ID = NULL;

        IF (TAB_ID IS NOT NULL) THEN
        BEGIN
            SELECT T.RES_ID, T.TAB_NUM
            FROM TABS T
            WHERE T.TAB_ID = :TAB_ID
            INTO :TAB_RES_ID, :TAB_NUM;

            SELECT UPPER(VAL)
            FROM RES_GET(:TAB_RES_ID, :I$LANG_CODE)
            INTO :TAB_CAPTION;
        END

        SELECT VAL
        FROM RES_GET(:PARAM_RES_ID, :I$LANG_CODE)
        INTO :CAPTION;

        V = '';

        SELECT VAL
        FROM RES_GET(:SIZE_RES_ID, :I$LANG_CODE)
        INTO :V;

        IF (V > '') THEN
        BEGIN
            CAPTION = CAPTION || ' (' || V || ')';
        END

        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SEARCHTYPES_ADD (
    I$SEARCH_ID BIGINT,
    I$TYPE_ID BIGINT,
    I$SEARCH_ORDER SMALLINT,
    I$SEARCH_TERM VARCHAR(10),
    I$SEARCH_VIEW VARCHAR(10),
    I$OWNER_TYPE_ID BIGINT)
RETURNS (
    SEARCH_ID BIGINT)
AS
BEGIN
    INSERT INTO SEARCHTYPES (SEARCH_ID, TYPE_ID, SEARCH_ORDER, SEARCH_TERM, SEARCH_VIEW, OWNER_TYPE_ID)
    VALUES (:I$SEARCH_ID, :I$TYPE_ID, :I$SEARCH_ORDER, :I$SEARCH_TERM, :I$SEARCH_VIEW, :I$OWNER_TYPE_ID);

    SEARCH_ID = I$SEARCH_ID;

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SEARCHTYPES_GET (
    I$SEARCH_ID BIGINT,
    I$LANG_CODE VARCHAR(2) = 'RU')
RETURNS (
    ROW_INDEX SMALLINT,
    SEARCH_ID BIGINT,
    TYPE_ID BIGINT,
    TYPE_CAPTION VARCHAR(4000),
    SEARCH_ORDER SMALLINT,
    SEARCH_TERM VARCHAR(10),
    SEARCH_VIEW VARCHAR(10),
    COLOR INTEGER,
    OWNER_TYPE_ID BIGINT,
    OWNER_TYPE_CAPTION VARCHAR(4000))
AS
DECLARE VARIABLE RES_ID BIGINT;
DECLARE VARIABLE OWNER_RES_ID BIGINT;
BEGIN
    FOR SELECT ST.SEARCH_ID, ST.TYPE_ID, ST.SEARCH_ORDER, ST.SEARCH_TERM, ST.SEARCH_VIEW, ST.OWNER_TYPE_ID, T.RES_ID, T.COLOR, OT.RES_ID
        FROM SEARCHTYPES ST
        INNER JOIN TYPES T ON T.TYPE_ID = ST.TYPE_ID
        LEFT JOIN TYPES OT ON OT.TYPE_ID = ST.OWNER_TYPE_ID
        WHERE ST.SEARCH_ID = :I$SEARCH_ID
        ORDER BY SEARCH_ORDER
        INTO :SEARCH_ID, :TYPE_ID, :SEARCH_ORDER, :SEARCH_TERM, :SEARCH_VIEW, :OWNER_TYPE_ID, :RES_ID, :COLOR, :OWNER_RES_ID
    DO
    BEGIN
        ROW_INDEX = SEARCH_ORDER;
        TYPE_CAPTION = '';

        SELECT VAL
        FROM RES_GET(:RES_ID, :I$LANG_CODE)
        INTO :TYPE_CAPTION;

        OWNER_TYPE_CAPTION = '';
        IF (OWNER_RES_ID IS NOT NULL) THEN
        BEGIN
            SELECT VAL
            FROM RES_GET(:OWNER_RES_ID, :I$LANG_CODE)
            INTO :OWNER_TYPE_CAPTION;
        END

        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SEARCH_ADD (
    I$SEARCH_ID BIGINT,
    I$USER_ID BIGINT,
    I$TYPE_ID BIGINT,
    I$LEVEL_ID BIGINT,
    I$IS_ACTIVE SMALLINT,
    I$SEARCH_NAME VARCHAR(100))
RETURNS (
    SEARCH_ID BIGINT)
AS
DECLARE VARIABLE TEMP_SEARCH_ID BIGINT;
BEGIN
    SEARCH_ID = NULL;
    TEMP_SEARCH_ID = NULL;

    IF ((I$USER_ID IS NULL) OR
        (I$TYPE_ID IS NULL) OR
        (I$LEVEL_ID IS NULL) OR
        (I$SEARCH_NAME IS NULL) OR
        (I$IS_ACTIVE IS NULL)) THEN
    BEGIN
        SUSPEND;
        EXIT;
    END

    SELECT SEARCH_ID
    FROM SEARCH
    WHERE USER_ID = :I$USER_ID
      AND TYPE_ID = :I$TYPE_ID
      AND LEVEL_ID = :I$LEVEL_ID
      AND SEARCH_NAME = :I$SEARCH_NAME
    INTO :TEMP_SEARCH_ID;

    IF (I$SEARCH_ID IS NULL) THEN
    BEGIN
        I$SEARCH_ID = TEMP_SEARCH_ID;
    END
    ELSE
    BEGIN
        IF ((TEMP_SEARCH_ID IS NOT NULL) AND (I$SEARCH_ID <> TEMP_SEARCH_ID)) THEN
        BEGIN
            DELETE FROM SEARCH WHERE SEARCH_ID = :TEMP_SEARCH_ID;
        END
    END


    IF (I$SEARCH_ID IS NULL) THEN
    BEGIN
        INSERT INTO SEARCH (USER_ID, TYPE_ID, LEVEL_ID, IS_ACTIVE, SEARCH_NAME)
        VALUES (:I$USER_ID, :I$TYPE_ID, :I$LEVEL_ID, :I$IS_ACTIVE, :I$SEARCH_NAME)
        RETURNING SEARCH_ID
        INTO :SEARCH_ID;
    END
    ELSE
    BEGIN
        UPDATE SEARCH
        SET USER_ID = :I$USER_ID,
            TYPE_ID = :I$TYPE_ID,
            LEVEL_ID = :I$LEVEL_ID,
            IS_ACTIVE = :I$IS_ACTIVE,
            SEARCH_NAME = :I$SEARCH_NAME
        WHERE SEARCH_ID = :I$SEARCH_ID;

        SEARCH_ID = I$SEARCH_ID;
    END

    IF (I$IS_ACTIVE = 1) THEN
    BEGIN
        UPDATE SEARCH
        SET IS_ACTIVE = 0
        WHERE SEARCH_ID <> :SEARCH_ID
          AND USER_ID = :I$USER_ID
          AND TYPE_ID = :I$TYPE_ID
          AND LEVEL_ID = :I$LEVEL_ID;
    END

    DELETE FROM SEARCHTYPES WHERE SEARCH_ID = :SEARCH_ID;
    DELETE FROM SEARCHPARAMS WHERE SEARCH_ID = :SEARCH_ID;
    DELETE FROM SEARCHFIELDS WHERE SEARCH_ID = :SEARCH_ID;

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SEARCH_APPLY (
    I$USER_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$LEVEL_ID BIGINT)
RETURNS (
    COL_NUM SMALLINT,
    SEARCH_ORDER SMALLINT,
    PARENT_ID BIGINT,
    LINK_ID BIGINT,
    OBJ_ID BIGINT,
    PARAM_ID BIGINT,
    VAL VARCHAR(4000),
    LISTVAL_ID BIGINT,
    DATA_PATH VARCHAR(200))
AS
declare variable TYPE_ID bigint;
declare variable SEARCH_ID bigint;
declare variable CUR_SEARCH_ORDER smallint;
declare variable MAX_SEARCH_ORDER smallint;
declare variable MAX_ROW_COUNT integer;
declare variable SEARCH_VIEW varchar(10);
declare variable X smallint;
declare variable SEARCH_TYPE_ID bigint;
declare variable OWNER_TYPE_ID bigint;
declare variable TYPE_SEARCH_TERM varchar(10);
declare variable CURR_LINK_ID bigint;
declare variable CURR_PARENT_ID bigint;
declare variable CURR_OBJECT_ID bigint;
declare variable CURR_OBJECT_TYPE_ID bigint;
declare variable CHILD_OBJ_ID bigint;
declare variable OWNER_OBJ_ID bigint;
declare variable CHILD_LINK_ID bigint;
declare variable PARAM_TYPE smallint;
declare variable PARAM_SEARCH_TERM varchar(10);
declare variable VAL_S varchar(4000);
declare variable VAL_I bigint;
declare variable VAL_F double precision;
declare variable VAL_D date;
declare variable CURR_VAL_S varchar(4000);
declare variable CURR_VAL_I bigint;
declare variable CURR_VAL_F double precision;
declare variable CURR_VAL_D date;
declare variable TAG varchar(100);
declare variable IS_OK smallint;
declare variable CHECK_OBJ_ID bigint;
declare variable CHILD_ID bigint;
declare variable CURR_ROOT_TYPE_ID bigint;
declare variable CURR_CHILD_TYPE_ID bigint;
declare variable PT smallint;
declare variable Y integer;
declare variable M integer;
declare variable K smallint;
declare variable H smallint;
declare variable N integer;
declare variable D integer;
declare variable Y1 char(4);
declare variable M1 char(3);
declare variable D1 char(3);
declare variable H1 char(2);
declare variable N1 char(3);
declare variable REGION varchar(255);
declare variable DISTRICT varchar(255);
declare variable TOWN varchar(255);
declare variable SETTLEMENT varchar(255);
declare variable STREET varchar(255);
declare variable HOUSE varchar(10);
declare variable CORP varchar(10);
declare variable LITER varchar(10);
declare variable FLAT varchar(10);
declare variable POST_INDEX varchar(20);
declare variable GCHAR char(3);
declare variable LCHAR char(3);
declare variable MCHAR char(3);
declare variable DCHAR char(3);
declare variable DT timestamp;
declare variable FUNC integer;
declare variable V$EXT_OBJ_ID bigint;
declare variable LANG_CODE varchar(2);
declare variable LICENSE_TYPE varchar(1);
declare variable CHILD_TYPE_ID bigint;
declare variable CURR_DATA_PATH varchar(200);
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :LANG_CODE;

    -- Тип объекта, от которого ищем вниз
    SELECT TYPE_ID
    FROM OBJECTS
    WHERE OBJ_ID = :I$OBJ_ID
    INTO :TYPE_ID;

    -- Пользовательские фильтры для поиска
    SELECT SEARCH_ID
    FROM SEARCH
    WHERE USER_ID = :I$USER_ID AND TYPE_ID = :TYPE_ID AND LEVEL_ID = :I$LEVEL_ID AND IS_ACTIVE = 1
    INTO :SEARCH_ID;

    IF (SEARCH_ID IS NULL) THEN EXIT;

    /* OBJECTS */

    -- Чистим таблицу с результатами поиска и кладем туда корневой объект
    -- Сам объект в выдачу не попадает из-за LINK_ID = null
    DELETE FROM SEARCHING WHERE 1 = 1;
    INSERT INTO SEARCHING (SEARCH_ID, SEARCH_ORDER, LINK_ID, OBJECT_ID, OBJECT_TYPE_ID, IS_OK, DATA_PATH)
    VALUES (:SEARCH_ID, -1, NULL, :I$OBJ_ID, :TYPE_ID, -1, :I$OBJ_ID);

    CURR_ROOT_TYPE_ID = TYPE_ID;

    -- Последовательно идем по условиям фильтрации, в соответствии с порядком сортировки SEARCH_ORDER (0...)
    FOR
        SELECT TYPE_ID, SEARCH_ORDER, SEARCH_TERM, OWNER_TYPE_ID
        FROM SEARCHTYPES
        WHERE SEARCH_ID = :SEARCH_ID
        ORDER BY SEARCH_ORDER
        INTO :SEARCH_TYPE_ID, :SEARCH_ORDER, :TYPE_SEARCH_TERM, :OWNER_TYPE_ID
    DO
    BEGIN
        /* Чистим буфер для хранения типов искомых объектов */
        DELETE FROM SEARCHING_TYPES WHERE 1 = 1;

        -- Пока везде OWNER_TYPE_ID = NULL, используем в качестве типа для поиска заданный в SEARCH_TYPE_ID
        IF (OWNER_TYPE_ID IS NULL) THEN
        BEGIN
            CURR_CHILD_TYPE_ID = SEARCH_TYPE_ID;
        END
        ELSE
        BEGIN
            CURR_CHILD_TYPE_ID = OWNER_TYPE_ID;
        END

        -- Выбираем все возможные сочетания: где указанный искомый тип может присутствовать дочерним на данном уровне
        -- плюс все объекты в маршруте
        FOR
            SELECT DISTINCT TYPE_ID, CHILD_ID
            FROM SEARCH_TYPES_GET(:CURR_ROOT_TYPE_ID, :CURR_CHILD_TYPE_ID, :I$LEVEL_ID)
            WHERE FLAG = 1
            ORDER BY TYPE_ID
            INTO :TYPE_ID, :CHILD_ID
        DO
        BEGIN
            INSERT INTO SEARCHING_TYPES (TYPE_ID, CHILD_ID)
            VALUES (:TYPE_ID, :CHILD_ID);
        END

        -- Колледж: формируем дополнительный маршрут, если текущий уровень = 8 (этап), добавляем академический отпуск (289)
        IF(SEARCH_TYPE_ID = 8) THEN INSERT INTO SEARCHING_TYPES (TYPE_ID, CHILD_ID) VALUES (7, 289);
        -- Колледж: формируем фейковый маршрут 289 => 289 параллельно с 8 => 9
        IF(SEARCH_TYPE_ID = 9) THEN INSERT INTO SEARCHING_TYPES (TYPE_ID, CHILD_ID) VALUES (289, 289);
        -- Колледж: формируем фейковый маршрут 289 => 289 параллельно с 8 => 9
        IF(SEARCH_TYPE_ID = 10) THEN INSERT INTO SEARCHING_TYPES (TYPE_ID, CHILD_ID) VALUES (289, 10);

        -- Следующий уровень дерева
        CURR_ROOT_TYPE_ID = SEARCH_TYPE_ID;

        /* Вынимаем все объекты текущего уровня поиска, являющиеся дочерними для объектов вышестоящего уровня, и также помещаем их в очередь SEARCHING */
        /* Корневой объект имеет SEARCH_ORDER = -1 */
        FOR
            SELECT LINK_ID, OBJECT_ID, OBJECT_TYPE_ID, DATA_PATH
            FROM SEARCHING
            WHERE SEARCH_ID = :SEARCH_ID AND SEARCH_ORDER = :SEARCH_ORDER - 1
            INTO :CURR_LINK_ID, :CURR_OBJECT_ID, :CURR_OBJECT_TYPE_ID, :CURR_DATA_PATH
        DO
        BEGIN
            IF (OWNER_TYPE_ID IS NULL) THEN
            BEGIN
                FOR
                    SELECT OBJ_ID, LINK_ID, TYPE_ID
                    FROM SEARCH_OBJECT_CHILDREN_GET(:CURR_OBJECT_ID, :CURR_LINK_ID, :CURR_OBJECT_TYPE_ID, :SEARCH_TYPE_ID, :I$LEVEL_ID)
                    INTO :CHILD_OBJ_ID, :CHILD_LINK_ID, :CHILD_TYPE_ID
                DO
                BEGIN
                    UPDATE OR INSERT INTO SEARCHING (SEARCH_ID, SEARCH_ORDER, PARENT_ID, PARENT_TYPE_ID, LINK_ID, OBJECT_ID, OBJECT_TYPE_ID, IS_OK, DATA_PATH)
                    VALUES (:SEARCH_ID, :SEARCH_ORDER, :CURR_OBJECT_ID, :CURR_OBJECT_TYPE_ID, :CHILD_LINK_ID, :CHILD_OBJ_ID, :CHILD_TYPE_ID, -1, :CURR_DATA_PATH || ',' || :CHILD_OBJ_ID)
                    MATCHING (SEARCH_ID, SEARCH_ORDER, PARENT_ID, OBJECT_ID, DATA_PATH);
                END
            END
            ELSE
            BEGIN
                FOR
                    SELECT OBJ_ID
                    FROM SEARCH_OBJECT_CHILDREN_GET(:CURR_OBJECT_ID, :CURR_LINK_ID, :CURR_OBJECT_TYPE_ID, :OWNER_TYPE_ID, :I$LEVEL_ID)
                    INTO :OWNER_OBJ_ID
                DO
                BEGIN
                    FOR
                        SELECT L.OBJ_ID, L.LINK_ID
                        FROM LINKS L
                        WHERE L.PARENT_ID = :OWNER_OBJ_ID AND L.OBJ_TYPE_ID = :SEARCH_TYPE_ID AND L.DATE_DEL IS NULL
                        INTO :CHILD_OBJ_ID, :CHILD_LINK_ID
                    DO
                    BEGIN
                        INSERT INTO SEARCHING (SEARCH_ID, SEARCH_ORDER, PARENT_ID, PARENT_TYPE_ID, LINK_ID, OBJECT_ID, OBJECT_TYPE_ID, IS_OK, DATA_PATH)
                        VALUES (:SEARCH_ID, :SEARCH_ORDER, :CURR_OBJECT_ID, :CURR_OBJECT_TYPE_ID, :CHILD_LINK_ID, :CHILD_OBJ_ID, :SEARCH_TYPE_ID, -1, :CURR_DATA_PATH || ',' || :CHILD_OBJ_ID);
                    END
                END
            END
        END

        /* Проверяем условия отбора по параметрам на текущем уровне */
        FOR
            SELECT S.PARAM_ID, S.SEARCH_TERM, S.VAL_S, S.VAL_I, S.VAL_F, S.VAL_D, P.PARAM_TYPE, P.TAG
            FROM SEARCHPARAMS S
            JOIN PARAMS P ON P.PARAM_ID = S.PARAM_ID
            WHERE S.SEARCH_ID = :SEARCH_ID AND S.TYPE_ID = :SEARCH_TYPE_ID
            INTO :PARAM_ID, :PARAM_SEARCH_TERM, :VAL_S, :VAL_I, :VAL_F, :VAL_D, :PARAM_TYPE, :TAG
        DO
        BEGIN
            IF (PARAM_TYPE = 1) THEN
            BEGIN
                FOR
                    SELECT C.OBJECT_ID, V.VAL
                    FROM SEARCHING C
                    JOIN LINKS L ON L.OBJ_ID = C.OBJECT_ID AND L.DATE_DEL IS NULL
                    LEFT JOIN VALI V ON V.PARAM_ID = :PARAM_ID AND V.OBJ_ID IN (C.OBJECT_ID, L.EXT_OBJ_ID) AND V.IS_DEL = 0
                    WHERE C.SEARCH_ID = :SEARCH_ID AND C.SEARCH_ORDER = :SEARCH_ORDER AND (((C.IS_OK <> 0) AND (:TYPE_SEARCH_TERM = 'and')) OR ((C.IS_OK <> 1) AND (:TYPE_SEARCH_TERM = 'or')))
                    INTO :CHECK_OBJ_ID, :CURR_VAL_I
                DO
                BEGIN
                    SELECT C
                    FROM SEARCH_CHECK_BIGINT(:VAL_I, :CURR_VAL_I, :PARAM_SEARCH_TERM)
                    INTO :IS_OK;

                    UPDATE SEARCHING
                    SET IS_OK = :IS_OK
                    WHERE SEARCH_ID = :SEARCH_ID AND SEARCH_ORDER = :SEARCH_ORDER AND OBJECT_ID = :CHECK_OBJ_ID;
                END
            END
            ELSE
            IF (PARAM_TYPE = 2) THEN
            BEGIN
                FOR
                    SELECT C.OBJECT_ID, V.VAL
                    FROM SEARCHING C
                    JOIN LINKS L ON L.OBJ_ID = C.OBJECT_ID AND L.DATE_DEL IS NULL
                    LEFT JOIN VALF V ON V.PARAM_ID = :PARAM_ID AND V.OBJ_ID IN (C.OBJECT_ID, L.EXT_OBJ_ID) AND V.IS_DEL = 0
                    WHERE C.SEARCH_ID = :SEARCH_ID AND C.SEARCH_ORDER = :SEARCH_ORDER AND (((C.IS_OK <> 0) AND (:TYPE_SEARCH_TERM = 'and')) OR ((C.IS_OK <> 1) AND (:TYPE_SEARCH_TERM = 'or')))
                    INTO :CHECK_OBJ_ID, :CURR_VAL_F
                DO
                BEGIN
                    SELECT C
                    FROM SEARCH_CHECK_DOUBLE(:VAL_F, :CURR_VAL_F, :PARAM_SEARCH_TERM)
                    INTO :IS_OK;

                    UPDATE SEARCHING
                    SET IS_OK = :IS_OK
                    WHERE SEARCH_ID = :SEARCH_ID AND SEARCH_ORDER = :SEARCH_ORDER AND OBJECT_ID = :CHECK_OBJ_ID;
                END
            END
            ELSE
            IF (PARAM_TYPE = 4) THEN
            BEGIN
                FOR
                    SELECT C.OBJECT_ID, V.VAL
                    FROM SEARCHING C
                    JOIN LINKS L ON L.OBJ_ID = C.OBJECT_ID AND L.DATE_DEL IS NULL
                    LEFT JOIN VALD V ON V.PARAM_ID = :PARAM_ID AND V.OBJ_ID IN (C.OBJECT_ID, L.EXT_OBJ_ID) AND V.IS_DEL = 0
                    WHERE C.SEARCH_ID = :SEARCH_ID AND C.SEARCH_ORDER = :SEARCH_ORDER AND (((C.IS_OK <> 0) AND (:TYPE_SEARCH_TERM = 'and')) OR ((C.IS_OK <> 1) AND (:TYPE_SEARCH_TERM = 'or')))
                    INTO :CHECK_OBJ_ID, :CURR_VAL_D
                DO
                BEGIN
                    SELECT C
                    FROM SEARCH_CHECK_DATE(:VAL_D, :CURR_VAL_D, :PARAM_SEARCH_TERM)
                    INTO :IS_OK;

                    UPDATE SEARCHING
                    SET IS_OK = :IS_OK
                    WHERE SEARCH_ID = :SEARCH_ID AND SEARCH_ORDER = :SEARCH_ORDER AND OBJECT_ID = :CHECK_OBJ_ID;
                END
            END
            ELSE
            IF (PARAM_TYPE = 6) THEN
            BEGIN
                FOR
                    SELECT C.OBJECT_ID, V.LISTVAL_ID
                    FROM SEARCHING C
                    JOIN LINKS L ON L.OBJ_ID = C.OBJECT_ID AND L.DATE_DEL IS NULL
                    LEFT JOIN VALL V ON V.PARAM_ID = :PARAM_ID AND V.OBJ_ID IN (C.OBJECT_ID, L.EXT_OBJ_ID) AND V.IS_DEL = 0
                    WHERE C.SEARCH_ID = :SEARCH_ID AND C.SEARCH_ORDER = :SEARCH_ORDER AND (((C.IS_OK <> 0) AND (:TYPE_SEARCH_TERM = 'and')) OR ((C.IS_OK <> 1) AND (:TYPE_SEARCH_TERM = 'or')))
                    INTO :CHECK_OBJ_ID, :CURR_VAL_I
                DO
                BEGIN
                    SELECT C
                    FROM SEARCH_CHECK_BIGINT(:VAL_I, :CURR_VAL_I, :PARAM_SEARCH_TERM)
                    INTO :IS_OK;

                    UPDATE SEARCHING
                    SET IS_OK = :IS_OK
                    WHERE SEARCH_ID = :SEARCH_ID AND SEARCH_ORDER = :SEARCH_ORDER AND OBJECT_ID = :CHECK_OBJ_ID;
                END
            END
            ELSE
            IF (PARAM_TYPE IN (7, 8, 9, 10)) THEN
            BEGIN
                FOR
                    SELECT C.OBJECT_ID, V.VAL
                    FROM SEARCHING C
                    JOIN LINKS L ON L.OBJ_ID = C.OBJECT_ID AND L.DATE_DEL IS NULL
                    LEFT JOIN VALS V ON V.PARAM_ID = :PARAM_ID AND V.OBJ_ID IN (C.OBJECT_ID, L.EXT_OBJ_ID) AND V.IS_DEL = 0
                    WHERE C.SEARCH_ID = :SEARCH_ID AND C.SEARCH_ORDER = :SEARCH_ORDER AND (((C.IS_OK <> 0) AND (:TYPE_SEARCH_TERM = 'and')) OR ((C.IS_OK <> 1) AND (:TYPE_SEARCH_TERM = 'or')))
                    INTO :CHECK_OBJ_ID, :CURR_VAL_S
                DO
                BEGIN
                    SELECT C
                    FROM SEARCH_CHECK_STRING(:VAL_S, :CURR_VAL_S, :PARAM_SEARCH_TERM)
                    INTO :IS_OK;

                    UPDATE SEARCHING
                    SET IS_OK = :IS_OK
                    WHERE SEARCH_ID = :SEARCH_ID AND SEARCH_ORDER = :SEARCH_ORDER AND OBJECT_ID = :CHECK_OBJ_ID;
                END
            END
            ELSE
            IF (PARAM_TYPE = 13) THEN
            BEGIN
                FOR
                    SELECT C.OBJECT_ID, V.VAL
                    FROM SEARCHING C
                    JOIN LINKS L ON L.OBJ_ID = C.OBJECT_ID AND L.DATE_DEL IS NULL
                    LEFT JOIN VALR V ON V.PARAM_ID = :PARAM_ID AND V.OBJ_ID IN (C.OBJECT_ID, L.EXT_OBJ_ID) AND V.IS_DEL = 0
                    WHERE C.SEARCH_ID = :SEARCH_ID AND C.SEARCH_ORDER = :SEARCH_ORDER AND (((C.IS_OK <> 0) AND (:TYPE_SEARCH_TERM = 'and')) OR ((C.IS_OK <> 1) AND (:TYPE_SEARCH_TERM = 'or')))
                    INTO :CHECK_OBJ_ID, :CURR_VAL_I
                DO
                BEGIN
                    SELECT C
                    FROM SEARCH_CHECK_BIGINT(:VAL_I, :CURR_VAL_I, :PARAM_SEARCH_TERM)
                    INTO :IS_OK;

                    UPDATE SEARCHING
                    SET IS_OK = :IS_OK
                    WHERE SEARCH_ID = :SEARCH_ID AND SEARCH_ORDER = :SEARCH_ORDER AND OBJECT_ID = :CHECK_OBJ_ID;
                END
            END
            ELSE
            -- CALC_FUNCTION
            IF (PARAM_TYPE = 17 AND TAG = 'INTEGER') THEN
            BEGIN
                FOR
                    SELECT C.OBJECT_ID
                    FROM SEARCHING C
                    WHERE C.SEARCH_ID = :SEARCH_ID AND C.SEARCH_ORDER = :SEARCH_ORDER AND (((C.IS_OK <> 0) AND (:TYPE_SEARCH_TERM = 'and')) OR ((C.IS_OK <> 1) AND (:TYPE_SEARCH_TERM = 'or')))
                    INTO :CHECK_OBJ_ID
                DO
                BEGIN
                    SELECT SORT_ORDER
                    FROM DO_FUNC(:CHECK_OBJ_ID, :PARAM_ID)
                    INTO :CURR_VAL_F;

                    SELECT C
                    FROM SEARCH_CHECK_DOUBLE(:VAL_I, :CURR_VAL_F, :PARAM_SEARCH_TERM)
                    INTO :IS_OK;

                    UPDATE SEARCHING
                    SET IS_OK = :IS_OK
                    WHERE SEARCH_ID = :SEARCH_ID AND SEARCH_ORDER = :SEARCH_ORDER AND OBJECT_ID = :CHECK_OBJ_ID;
                END
            END
            ELSE
            IF (PARAM_TYPE = 17 AND TAG IN ('STRING', 'LIST_VALUE', 'DATE')) THEN
            BEGIN
                FOR
                    SELECT C.OBJECT_ID
                    FROM SEARCHING C
                    WHERE C.SEARCH_ID = :SEARCH_ID AND C.SEARCH_ORDER = :SEARCH_ORDER AND (((C.IS_OK <> 0) AND (:TYPE_SEARCH_TERM = 'and')) OR ((C.IS_OK <> 1) AND (:TYPE_SEARCH_TERM = 'or')))
                    INTO :CHECK_OBJ_ID
                DO
                BEGIN
                    SELECT VAL
                    FROM DO_FUNC(:CHECK_OBJ_ID, :PARAM_ID)
                    INTO :CURR_VAL_S;

                    SELECT C
                    FROM SEARCH_CHECK_STRING(UPPER(:VAL_S), UPPER(:CURR_VAL_S), :PARAM_SEARCH_TERM)
                    INTO :IS_OK;

                    UPDATE SEARCHING
                    SET IS_OK = :IS_OK
                    WHERE SEARCH_ID = :SEARCH_ID AND SEARCH_ORDER = :SEARCH_ORDER AND OBJECT_ID = :CHECK_OBJ_ID;
                END
            END
            ELSE
            IF (PARAM_TYPE = 17 AND TAG = 'AGE') THEN
            BEGIN
                FOR
                    SELECT C.OBJECT_ID
                    FROM SEARCHING C
                    WHERE C.SEARCH_ID = :SEARCH_ID AND C.SEARCH_ORDER = :SEARCH_ORDER AND (((C.IS_OK <> 0) AND (:TYPE_SEARCH_TERM = 'and')) OR ((C.IS_OK <> 1) AND (:TYPE_SEARCH_TERM = 'or')))
                    INTO :CHECK_OBJ_ID
                DO
                BEGIN
                    SELECT STATUS
                    FROM OU_LICENCE_TYPE
                    INTO :LICENSE_TYPE;

                    IF (LICENSE_TYPE = 'D') THEN
                    BEGIN
                        SELECT VAL
                        FROM DO_FUNC(:CHECK_OBJ_ID, :PARAM_ID)
                        INTO :CURR_VAL_S;
    
                        SELECT C
                        FROM SEARCH_CHECK_STRING(UPPER(:VAL_S), UPPER(:CURR_VAL_S), :PARAM_SEARCH_TERM)
                        INTO :IS_OK;
    
                        UPDATE SEARCHING
                        SET IS_OK = :IS_OK
                        WHERE SEARCH_ID = :SEARCH_ID AND SEARCH_ORDER = :SEARCH_ORDER AND OBJECT_ID = :CHECK_OBJ_ID;
                    END
                    ELSE
                    BEGIN
                        SELECT SORT_ORDER
                        FROM DO_FUNC(:CHECK_OBJ_ID, :PARAM_ID)
                        INTO :CURR_VAL_F;
    
                        SELECT C
                        FROM SEARCH_CHECK_DOUBLE(:VAL_I, :CURR_VAL_F, :PARAM_SEARCH_TERM)
                        INTO :IS_OK;
    
                        UPDATE SEARCHING
                        SET IS_OK = :IS_OK
                        WHERE SEARCH_ID = :SEARCH_ID AND SEARCH_ORDER = :SEARCH_ORDER AND OBJECT_ID = :CHECK_OBJ_ID;
                    END
                END
            END
            ELSE
            IF (PARAM_TYPE = 18) THEN
            -- ADDRESS
            BEGIN
                FOR
                    SELECT C.OBJECT_ID, V.STREET
                    FROM SEARCHING C
                    JOIN LINKS L ON L.OBJ_ID = C.OBJECT_ID AND L.DATE_DEL IS NULL
                    LEFT JOIN VALA V ON V.PARAM_ID = :PARAM_ID AND V.OBJ_ID IN (C.OBJECT_ID, L.EXT_OBJ_ID) AND V.IS_DEL = 0
                    WHERE C.SEARCH_ID = :SEARCH_ID AND C.SEARCH_ORDER = :SEARCH_ORDER AND (((C.IS_OK <> 0) AND (:TYPE_SEARCH_TERM = 'and')) OR ((C.IS_OK <> 1) AND (:TYPE_SEARCH_TERM = 'or')))
                    INTO :CHECK_OBJ_ID, :CURR_VAL_S
                DO
                BEGIN
                    SELECT C
                    FROM SEARCH_CHECK_STRING(:VAL_S, :CURR_VAL_S, :PARAM_SEARCH_TERM)
                    INTO :IS_OK;

                    UPDATE SEARCHING
                    SET IS_OK = :IS_OK
                    WHERE SEARCH_ID = :SEARCH_ID AND SEARCH_ORDER = :SEARCH_ORDER AND OBJECT_ID = :CHECK_OBJ_ID;
                END
            END
            ELSE
            IF (PARAM_TYPE = 19) THEN
            BEGIN
                FOR
                    SELECT C.OBJECT_ID
                    FROM SEARCHING C
                    WHERE C.SEARCH_ID = :SEARCH_ID AND C.SEARCH_ORDER = :SEARCH_ORDER AND (((C.IS_OK <> 0) AND (:TYPE_SEARCH_TERM = 'and')) OR ((C.IS_OK <> 1) AND (:TYPE_SEARCH_TERM = 'or')))
                    INTO :CHECK_OBJ_ID
                DO
                BEGIN
                    SELECT VAL
                    FROM DO_FUNC(:CHECK_OBJ_ID, :PARAM_ID, 2)
                    INTO :CURR_VAL_I;

                    SELECT C
                    FROM SEARCH_CHECK_BIGINT(:VAL_I, :CURR_VAL_I, :PARAM_SEARCH_TERM)
                    INTO :IS_OK;

                    UPDATE SEARCHING
                    SET IS_OK = :IS_OK
                    WHERE SEARCH_ID = :SEARCH_ID AND SEARCH_ORDER = :SEARCH_ORDER AND OBJECT_ID = :CHECK_OBJ_ID;
                END
            END
        END

        /* Чистим объекты, не соответствующие критериям поиска */
        DELETE FROM SEARCHING
        WHERE SEARCH_ID = :SEARCH_ID AND SEARCH_ORDER = :SEARCH_ORDER AND IS_OK = 0;
    END

    /* Удаляем ссылки на объекты, у которых отсутствуют дочерние объекты */
    FOR
        SELECT TYPE_ID, SEARCH_ORDER, SEARCH_VIEW
        FROM SEARCHTYPES
        WHERE SEARCH_ID = :SEARCH_ID
        ORDER BY SEARCH_ORDER DESCENDING
        INTO :SEARCH_TYPE_ID, :SEARCH_ORDER, :SEARCH_VIEW
    DO
    BEGIN
        FOR
            SELECT PAR.PARENT_ID, PAR.OBJECT_ID
            FROM SEARCHING PAR
            LEFT JOIN SEARCHING CHI ON CHI.SEARCH_ID = :SEARCH_ID AND CHI.SEARCH_ORDER = :SEARCH_ORDER AND CHI.PARENT_ID = PAR.OBJECT_ID
            WHERE PAR.SEARCH_ID = :SEARCH_ID AND PAR.SEARCH_ORDER = :SEARCH_ORDER - 1 AND (((:SEARCH_VIEW <> 'not_exist') AND (CHI.PARENT_ID IS NULL)) OR ((:SEARCH_VIEW = 'not_exist') AND (CHI.PARENT_ID IS NOT NULL)))
            INTO :CURR_PARENT_ID, :CURR_OBJECT_ID
        DO
        BEGIN
            DELETE FROM SEARCHING
            WHERE SEARCH_ID = :SEARCH_ID AND SEARCH_ORDER = :SEARCH_ORDER - 1 AND PARENT_ID = :CURR_PARENT_ID AND OBJECT_ID = :CURR_OBJECT_ID;
        END
    END

    SELECT COUNT(*)
    FROM SEARCHING
    INTO :CURR_OBJECT_ID;

    -- Как минимум сам объект в буфере должен быть
    IF (CURR_OBJECT_ID < 2) THEN
    BEGIN
        DELETE FROM SEARCHING
        WHERE 1 = 1;
    END

    -- Подсчитываем MAX_ROW_COUNT - количество найденных объектов

    MAX_SEARCH_ORDER = NULL;
    MAX_ROW_COUNT = 0;

    X = 0;
    FOR
        -- выбирается максимальный  ST.SEARCH_ORDER, где SEARCH_VIEW <>   'count' или 'not_exist'  и по нему ищется максимальное кол-во записей
        SELECT ST.SEARCH_ORDER, ST.SEARCH_VIEW
        FROM SEARCHTYPES ST
        WHERE ST.SEARCH_ID = :SEARCH_ID
        ORDER BY ST.SEARCH_ORDER
        INTO :CUR_SEARCH_ORDER, :SEARCH_VIEW
    DO
    BEGIN
        IF (SEARCH_VIEW = 'count') THEN X = 1;
        IF (SEARCH_VIEW = 'not_exist') THEN X = 1;
        IF (X = 0) THEN MAX_SEARCH_ORDER = CUR_SEARCH_ORDER;
    END

    IF (MAX_SEARCH_ORDER IS NOT NULL) THEN
    BEGIN
        SELECT COUNT(1) FROM
        (SELECT DISTINCT PARENT_ID, OBJECT_ID FROM SEARCHING WHERE SEARCH_ID = :SEARCH_ID AND SEARCH_ORDER = :MAX_SEARCH_ORDER)
        INTO :MAX_ROW_COUNT;
    END
    ELSE
    BEGIN
        SELECT FIRST 1 1
        FROM SEARCHING
        WHERE SEARCH_ID = :SEARCH_ID AND SEARCH_ORDER = 0
        INTO :MAX_ROW_COUNT;
    END

    UPDATE SEARCH
    SET MAX_ROW_COUNT = :MAX_ROW_COUNT
    WHERE SEARCH_ID = :SEARCH_ID;

    --exception data_error 'count ' || (select count(*) from searching);

    -- Выдача данных в виде дерева объектов и параметров, сверху вниз

    COL_NUM = -1;

    FOR
        -- выбирается спиок выводимых параметров в отчет по порядку их отображения
        SELECT ST.TYPE_ID, ST.SEARCH_ORDER, ST.SEARCH_VIEW, SF.PARAM_ID, P.PARAM_TYPE, P.DO_FUNC
        FROM SEARCHTYPES ST
        LEFT JOIN SEARCHFIELDS SF ON ST.SEARCH_ID = SF.SEARCH_ID AND ST.TYPE_ID = SF.TYPE_ID
        LEFT JOIN PARAMS P ON P.PARAM_ID = SF.PARAM_ID
        WHERE ST.SEARCH_ID = :SEARCH_ID
        ORDER BY ST.SEARCH_ORDER, SF.GRID_ORDER
        INTO :TYPE_ID, :SEARCH_ORDER, :SEARCH_VIEW, :PARAM_ID, :PT, :FUNC
    DO
    BEGIN
        COL_NUM = COL_NUM + 1;
        DT = NULL;
        VAL = NULL;
        LISTVAL_ID = NULL;

        IF (SEARCH_VIEW = 'count') THEN
        BEGIN
            OBJ_ID = 0;
            PARAM_ID = 0; -- подмена OBJ_ID на нулевой и агрегация по последней части пути

            FOR
                SELECT S.PARENT_ID, COUNT(S.PARENT_ID)
                FROM SEARCHING S
                WHERE S.SEARCH_ID = :SEARCH_ID AND S.SEARCH_ORDER = :SEARCH_ORDER AND S.OBJECT_TYPE_ID = :TYPE_ID
                GROUP BY 1
                ORDER BY 1
                INTO :PARENT_ID, :VAL
            DO
            BEGIN
                DATA_PATH = NULL;
                SELECT FIRST 1 S.DATA_PATH
                FROM SEARCHING S
                WHERE S.SEARCH_ID = :SEARCH_ID AND S.SEARCH_ORDER = :SEARCH_ORDER AND S.OBJECT_TYPE_ID = :TYPE_ID AND S.PARENT_ID = :PARENT_ID
                INTO :DATA_PATH;

                SUSPEND;
            END
            EXIT;
        END
        ELSE IF (SEARCH_VIEW = 'not_exist') THEN EXIT;
        ELSE
        IF (PT = 1) THEN
        BEGIN /* INTEGER */
            FOR
                SELECT S.PARENT_ID, S.OBJECT_ID, S.DATA_PATH, CAST(VAL AS VARCHAR(4000)), MAX(S.LINK_ID)
                FROM SEARCHING S
                JOIN LINKS L ON L.LINK_ID = S.LINK_ID
                LEFT JOIN VALI V ON V.PARAM_ID = :PARAM_ID AND V.OBJ_ID IN (S.OBJECT_ID, L.EXT_OBJ_ID) AND V.IS_DEL = 0
                WHERE S.SEARCH_ID = :SEARCH_ID AND S.SEARCH_ORDER = :SEARCH_ORDER AND S.OBJECT_TYPE_ID = :TYPE_ID
                GROUP BY 1, 2, 3, 4
                INTO :PARENT_ID, :OBJ_ID, :DATA_PATH, :VAL , :LINK_ID
            DO
            BEGIN
                SUSPEND;
            END
        END
        ELSE
        IF (PT = 2) THEN
        BEGIN /* FLOAT */
            FOR
                SELECT S.PARENT_ID, S.OBJECT_ID, S.DATA_PATH, CAST(VAL AS VARCHAR(4000)), MAX(S.LINK_ID)
                FROM SEARCHING S
                JOIN LINKS L ON L.LINK_ID = S.LINK_ID
                LEFT JOIN VALF V ON V.PARAM_ID = :PARAM_ID AND V.OBJ_ID IN (S.OBJECT_ID, L.EXT_OBJ_ID) AND V.IS_DEL = 0
                WHERE S.SEARCH_ID = :SEARCH_ID AND S.SEARCH_ORDER = :SEARCH_ORDER AND S.OBJECT_TYPE_ID = :TYPE_ID
                GROUP BY 1, 2, 3, 4
                INTO :PARENT_ID, :OBJ_ID, :DATA_PATH, :VAL, :LINK_ID
            DO
            BEGIN
                SUSPEND;
            END
        END
        ELSE
        IF (PT = 3) THEN
        BEGIN /* TIMESTAMP */
            FOR
                SELECT S.PARENT_ID, S.OBJECT_ID, S.DATA_PATH, V.VAL, MAX(S.LINK_ID)
                FROM SEARCHING S
                JOIN LINKS L ON L.LINK_ID = S.LINK_ID
                LEFT JOIN VALDT V ON V.PARAM_ID = :PARAM_ID AND V.OBJ_ID IN (S.OBJECT_ID, L.EXT_OBJ_ID) AND V.IS_DEL = 0
                WHERE S.SEARCH_ID = :SEARCH_ID AND S.SEARCH_ORDER = :SEARCH_ORDER AND S.OBJECT_TYPE_ID = :TYPE_ID
                GROUP BY 1, 2, 3, 4
                INTO :PARENT_ID, :OBJ_ID, :DATA_PATH, :DT, :LINK_ID
            DO
            BEGIN
                VAL = NULL;
                IF (DT IS NOT NULL) THEN
                BEGIN
                    Y = EXTRACT(YEAR FROM :DT);
                    M = EXTRACT(MONTH FROM :DT);
                    K = EXTRACT(DAY FROM :DT);
                    H = EXTRACT(HOUR FROM :DT);
                    N = EXTRACT(MINUTE FROM :DT);

                    Y1 = Y;
                    IF (M > 9) THEN
                        M1 = M || '.';
                    ELSE
                        M1 = '0' || M || '.';
                    IF (K > 9) THEN
                        D1 = K || '.';
                    ELSE
                        D1 = '0' || K || '.';
                    IF (H > 9) THEN
                        H1 = H;
                    ELSE
                        H1 = '0' || H;
                    IF (N > 9) THEN
                        N1 = ':' || N;
                    ELSE
                        N1 = ':0' || N;

                    VAL = D1 || M1 || Y1 || ' ' || H1 || N1;
                END

                SUSPEND;
            END
        END
        ELSE
        IF (PT = 4) THEN
        BEGIN /* DATE */
            FOR
                SELECT S.PARENT_ID, S.OBJECT_ID, S.DATA_PATH, V.VAL, MAX(S.LINK_ID)
                FROM SEARCHING S
                JOIN LINKS L ON L.LINK_ID = S.LINK_ID
                LEFT JOIN VALD V ON V.PARAM_ID = :PARAM_ID AND V.OBJ_ID IN (S.OBJECT_ID, L.EXT_OBJ_ID) AND V.IS_DEL = 0
                WHERE S.SEARCH_ID = :SEARCH_ID AND S.SEARCH_ORDER = :SEARCH_ORDER AND S.OBJECT_TYPE_ID = :TYPE_ID
                GROUP BY 1, 2, 3, 4
                INTO :PARENT_ID, :OBJ_ID, :DATA_PATH, :DT, :LINK_ID
            DO
            BEGIN
                VAL = NULL;
                IF (DT IS NOT NULL) THEN
                BEGIN
                    Y = EXTRACT(YEAR FROM :DT);
                    M = EXTRACT(MONTH FROM :DT);
                    K = EXTRACT(DAY FROM :DT);

                    Y1 = Y;
                    IF (M > 9) THEN
                        M1 = M || '.';
                    ELSE
                        M1 = '0' || M || '.';
                    IF (K > 9) THEN
                        D1 = K || '.';
                    ELSE
                        D1 = '0' || K || '.';

                    VAL = D1 || M1 || Y1;
                END

                SUSPEND;
            END
        END
        ELSE
        IF (PT = 5) THEN
        BEGIN /* TIME */
            FOR
                SELECT S.PARENT_ID, S.OBJECT_ID, S.DATA_PATH, V.VAL, MAX(S.LINK_ID)
                FROM SEARCHING S
                JOIN LINKS L ON L.LINK_ID = S.LINK_ID
                LEFT JOIN VALT V ON V.PARAM_ID = :PARAM_ID AND V.OBJ_ID IN (S.OBJECT_ID, L.EXT_OBJ_ID) AND V.IS_DEL = 0
                WHERE S.SEARCH_ID = :SEARCH_ID AND S.SEARCH_ORDER = :SEARCH_ORDER AND S.OBJECT_TYPE_ID = :TYPE_ID
                GROUP BY 1, 2, 3, 4
                INTO :PARENT_ID, :OBJ_ID, :DATA_PATH, :DT, :LINK_ID
            DO
            BEGIN
                VAL = NULL;
                IF (DT IS NOT NULL) THEN
                BEGIN
                    H = EXTRACT(HOUR FROM :DT);
                    N = EXTRACT(MINUTE FROM :DT);

                    IF (H > 9) THEN
                        H1 = H;
                    ELSE
                        H1 = '0' || H;
                    IF (N > 9) THEN
                        N1 = ':' || N;
                    ELSE
                        N1 = ':0' || N;

                    VAL = H1 || N1;
                END
                SUSPEND;
            END

        END
        ELSE
        IF (PT = 6) THEN
        BEGIN
            -- LIST_VALUE
            FOR
                SELECT S.PARENT_ID, S.OBJECT_ID, S.DATA_PATH, LV.LISTVAL_ID, R.VAL, MAX(S.LINK_ID)
                FROM SEARCHING S
                JOIN LINKS L ON L.LINK_ID = S.LINK_ID
                LEFT JOIN VALL V ON V.PARAM_ID = :PARAM_ID AND V.OBJ_ID IN (S.OBJECT_ID, L.EXT_OBJ_ID) AND V.IS_DEL = 0
                LEFT JOIN LISTVALS LV ON LV.LISTVAL_ID = V.LISTVAL_ID
                LEFT JOIN RES_GET(LV.RES_ID,  :LANG_CODE) R ON 1=1
                WHERE S.SEARCH_ID = :SEARCH_ID AND S.SEARCH_ORDER = :SEARCH_ORDER AND S.OBJECT_TYPE_ID = :TYPE_ID
                GROUP BY 1, 2, 3, 4, 5
                INTO :PARENT_ID, :OBJ_ID, :DATA_PATH, :LISTVAL_ID, :VAL, :LINK_ID
            DO
            BEGIN
                SUSPEND;
            END
        END
        ELSE
        IF (PT IN (7, 8, 9, 10, 20)) THEN
        BEGIN
            -- STRING_OR_LIST_VALUE_RO, STRING_OR_LIST_VALUE, STRING, SQL_QUERY, FUNCTION
            FOR
                SELECT S.PARENT_ID, S.OBJECT_ID, S.DATA_PATH, V.VAL, MAX(S.LINK_ID)
                FROM SEARCHING S
                JOIN LINKS L ON L.LINK_ID = S.LINK_ID
                LEFT JOIN VALS V ON V.PARAM_ID = :PARAM_ID AND V.OBJ_ID IN (S.OBJECT_ID, L.EXT_OBJ_ID) AND V.IS_DEL = 0
                WHERE S.SEARCH_ID = :SEARCH_ID AND S.SEARCH_ORDER = :SEARCH_ORDER AND S.OBJECT_TYPE_ID = :TYPE_ID
                GROUP BY 1, 2, 3, 4
                INTO :PARENT_ID, :OBJ_ID, :DATA_PATH, :VAL, :LINK_ID
            DO
            BEGIN
                SUSPEND;
            END
        END
        ELSE
        IF (PT = 13) THEN
        BEGIN
            -- REFERENCE
            FOR
                SELECT S.PARENT_ID, S.OBJECT_ID, S.DATA_PATH, V.VAL, MAX(S.LINK_ID)
                FROM SEARCHING S
                JOIN LINKS L ON L.LINK_ID = S.LINK_ID
                LEFT JOIN VALR V ON V.PARAM_ID = :PARAM_ID AND V.OBJ_ID IN (S.OBJECT_ID, L.EXT_OBJ_ID) AND V.IS_DEL = 0
                WHERE S.SEARCH_ID = :SEARCH_ID AND S.SEARCH_ORDER = :SEARCH_ORDER AND S.OBJECT_TYPE_ID = :TYPE_ID
                GROUP BY 1, 2, 3, 4
                INTO :PARENT_ID, :OBJ_ID, :DATA_PATH, :LISTVAL_ID, :LINK_ID
            DO
            BEGIN
                VAL = NULL;
                IF (LISTVAL_ID IS NOT NULL) THEN
                BEGIN
                    SELECT CAPTION
                    FROM OBJECT_CAPTION_GET(:LISTVAL_ID)
                    INTO :VAL;
                END
                SUSPEND;
            END
        END
        ELSE
        IF (PT = 18) THEN
        BEGIN
            -- ADDRESS
            FOR
                SELECT S.PARENT_ID, S.OBJECT_ID, S.DATA_PATH, V.REGION, V.DISTRICT, V.TOWN, V.SETTLEMENT, V.STREET, V.HOUSE, V.LITER, V.CORP, V.FLAT, V.POST_INDEX, max(S.LINK_ID)
                FROM SEARCHING S
                JOIN LINKS L ON L.LINK_ID = S.LINK_ID
                LEFT JOIN VALA V ON V.PARAM_ID = :PARAM_ID AND V.OBJ_ID IN (S.OBJECT_ID, L.EXT_OBJ_ID) AND V.IS_DEL = 0
                WHERE S.SEARCH_ID = :SEARCH_ID AND S.SEARCH_ORDER = :SEARCH_ORDER AND S.OBJECT_TYPE_ID = :TYPE_ID
                GROUP BY 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13
                INTO :PARENT_ID, :OBJ_ID, :DATA_PATH, :REGION, :DISTRICT, :TOWN, :SETTLEMENT, :STREET, :HOUSE, :LITER, :CORP, :FLAT, :POST_INDEX, :LINK_ID
            DO
            BEGIN
                VAL = '';

                IF (POST_INDEX <> '') THEN
                BEGIN
                    VAL = POST_INDEX;
                END
                IF (REGION <> '') THEN
                BEGIN
                    IF (VAL <> '') THEN
                    BEGIN
                        VAL = VAL || ', ';
                    END
                    VAL = VAL || REGION;
                END
                IF (DISTRICT <> '') THEN
                BEGIN
                    IF (VAL <> '') THEN
                    BEGIN
                        VAL = VAL || ', ';
                    END
                    VAL = VAL || DISTRICT;
                END
                IF (TOWN <> '') THEN
                BEGIN
                    IF (VAL <> '') THEN
                    BEGIN
                        VAL = VAL || ', ';
                    END
                    VAL = VAL || TOWN;
                END
                IF (SETTLEMENT <> '') THEN
                BEGIN
                    IF (VAL <> '') THEN
                    BEGIN
                        VAL = VAL || ', ';
                    END
                    VAL = VAL || SETTLEMENT;
                END
                IF (STREET <> '') THEN
                BEGIN
                    IF (VAL <> '') THEN
                    BEGIN
                        VAL = VAL || ', ';
                    END
                    VAL = VAL || STREET;
                END
                IF (HOUSE <> '') THEN
                BEGIN
                    IF (VAL <> '') THEN
                    BEGIN
                        VAL = VAL || ', д ';
                    END
                    VAL = VAL || HOUSE;
                END
                IF (CORP <> '') THEN
                BEGIN
                    IF (VAL <> '') THEN
                    BEGIN
                        VAL = VAL || ', корп ';
                    END
                    VAL = VAL || CORP;
                END
                IF (LITER <> '') THEN
                BEGIN
                    IF (VAL <> '') THEN
                    BEGIN
                        VAL = VAL || ', литер ';
                    END
                    VAL = VAL || LITER;
                END
                IF (FLAT <> '') THEN
                BEGIN
                    IF (VAL <> '') THEN
                    BEGIN
                        VAL = VAL || ', кв ';
                    END
                    VAL = VAL || FLAT;
                END

                SUSPEND;
            END
        END
        ELSE
        IF (PT = 17 OR PT = 19) THEN
        BEGIN
            IF (FUNC = 2) THEN
            BEGIN
                SELECT WORD
                FROM REPORT_WORDS
                WHERE ID = 22
                INTO :LCHAR;
                SELECT WORD
                FROM REPORT_WORDS
                WHERE ID = 23
                INTO :GCHAR;
                SELECT WORD
                FROM REPORT_WORDS
                WHERE ID = 24
                INTO :MCHAR;
                SELECT WORD
                FROM REPORT_WORDS
                WHERE ID = 25
                INTO :DCHAR;
            END

            FOR
                SELECT S.PARENT_ID, S.OBJECT_ID, S.DATA_PATH, L.EXT_OBJ_ID, MAX(S.LINK_ID)
                FROM SEARCHING S
                JOIN LINKS L ON L.LINK_ID = S.LINK_ID
                WHERE S.SEARCH_ID = :SEARCH_ID AND S.SEARCH_ORDER = :SEARCH_ORDER AND S.OBJECT_TYPE_ID = :TYPE_ID
                GROUP BY 1, 2, 3, 4
                INTO :PARENT_ID, :OBJ_ID, :DATA_PATH, :V$EXT_OBJ_ID, :LINK_ID
            DO
            BEGIN
                SELECT VAL
                FROM DO_FUNC(:OBJ_ID, :PARAM_ID, :FUNC)
                INTO :VAL;

                IF (VAL = '' AND V$EXT_OBJ_ID IS NOT NULL) THEN
                BEGIN
                    SELECT VAL
                    FROM DO_FUNC(:V$EXT_OBJ_ID, :PARAM_ID, :FUNC)
                    INTO :VAL;
                END

                IF ((FUNC = 2) AND (VAL IS NOT NULL) AND (VAL <> '')) THEN
                BEGIN
                    N = VAL;
                    VAL = '';
                    Y = N / 360;
                    N = N - Y * 360;
                    M = N / 30;
                    N = N - M * 30;
                    D = N;

                    IF (Y > 0) THEN
                    BEGIN
                        VAL = Y || LCHAR;
                        IF (Y < 5) THEN
                        BEGIN
                            VAL = Y || GCHAR;
                        END
                    END
                    IF (M > 0) THEN
                    BEGIN
                        VAL = VAL || M || MCHAR;
                    END
                    IF (D > 0) THEN
                    BEGIN
                        VAL = VAL || D || DCHAR;
                    END
                END
                SUSPEND;
            END
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SEARCH_CHECK_BIGINT (
    VAL BIGINT,
    CURR_VAL BIGINT,
    PARAM_SEARCH_TERM VARCHAR(10))
RETURNS (
    C SMALLINT)
AS
BEGIN
    C = 0;
    IF (PARAM_SEARCH_TERM = '=') THEN
    BEGIN
        IF (CURR_VAL = VAL) THEN C = 1;
    END
    ELSE
    IF (PARAM_SEARCH_TERM = '<>') THEN
    BEGIN
        IF (CURR_VAL <> VAL) THEN C = 1;
    END
    ELSE
    IF (PARAM_SEARCH_TERM = '>') THEN
    BEGIN
        IF (CURR_VAL > VAL) THEN C = 1;
    END
    ELSE
    IF (PARAM_SEARCH_TERM = '<') THEN
    BEGIN
        IF (CURR_VAL < VAL) THEN C = 1;
    END
    ELSE
    IF (PARAM_SEARCH_TERM = '>=') THEN
    BEGIN
        IF (CURR_VAL >= VAL) THEN C = 1;
    END
    ELSE
    IF (PARAM_SEARCH_TERM = '<=') THEN
    BEGIN
        IF (CURR_VAL <= VAL) THEN C = 1;
    END
    ELSE
    IF (PARAM_SEARCH_TERM = 'empty') THEN
    BEGIN
        IF (CURR_VAL IS NULL) THEN C = 1;
    END
    ELSE
    IF (PARAM_SEARCH_TERM = 'not_empty') THEN
    BEGIN
        IF (CURR_VAL IS NOT NULL) THEN C = 1;
    END
    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SEARCH_CHECK_DATE (
    VAL DATE,
    CURR_VAL DATE,
    PARAM_SEARCH_TERM VARCHAR(10))
RETURNS (
    C SMALLINT)
AS
BEGIN
    C = 0;
    IF (PARAM_SEARCH_TERM = '=') THEN
    BEGIN
        IF (CURR_VAL = VAL) THEN C = 1;
    END
    ELSE
    IF (PARAM_SEARCH_TERM = '<>') THEN
    BEGIN
        IF (CURR_VAL <> VAL) THEN C = 1;
    END
    ELSE
    IF (PARAM_SEARCH_TERM = '>') THEN
    BEGIN
        IF (CURR_VAL > VAL) THEN C = 1;
    END
    ELSE
    IF (PARAM_SEARCH_TERM = '<') THEN
    BEGIN
        IF (CURR_VAL < VAL) THEN C = 1;
    END
    ELSE
    IF (PARAM_SEARCH_TERM = '>=') THEN
    BEGIN
        IF (CURR_VAL >= VAL) THEN C = 1;
    END
    ELSE
    IF (PARAM_SEARCH_TERM = '<=') THEN
    BEGIN
        IF (CURR_VAL <= VAL) THEN C = 1;
    END
    ELSE
    IF (PARAM_SEARCH_TERM = 'empty') THEN
    BEGIN
        IF (CURR_VAL IS NULL) THEN C = 1;
    END
    ELSE
    IF (PARAM_SEARCH_TERM = 'not_empty') THEN
    BEGIN
        IF (CURR_VAL IS NOT NULL) THEN C = 1;
    END
    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SEARCH_CHECK_DOUBLE (
    VAL DOUBLE PRECISION,
    CURR_VAL DOUBLE PRECISION,
    PARAM_SEARCH_TERM VARCHAR(10))
RETURNS (
    C SMALLINT)
AS
BEGIN
    C = 0;
    IF (PARAM_SEARCH_TERM = '=') THEN
    BEGIN
        IF (CURR_VAL = VAL) THEN C = 1;
    END
    ELSE
    IF (PARAM_SEARCH_TERM = '<>') THEN
    BEGIN
        IF (CURR_VAL <> VAL) THEN C = 1;
    END
    ELSE
    IF (PARAM_SEARCH_TERM = '>') THEN
    BEGIN
        IF (CURR_VAL > VAL) THEN C = 1;
    END
    ELSE
    IF (PARAM_SEARCH_TERM = '<') THEN
    BEGIN
        IF (CURR_VAL < VAL) THEN C = 1;
    END
    ELSE
    IF (PARAM_SEARCH_TERM = '>=') THEN
    BEGIN
        IF (CURR_VAL >= VAL) THEN C = 1;
    END
    ELSE
    IF (PARAM_SEARCH_TERM = '<=') THEN
    BEGIN
        IF (CURR_VAL <= VAL) THEN C = 1;
    END
    ELSE
    IF (PARAM_SEARCH_TERM = 'empty') THEN
    BEGIN
        IF (CURR_VAL IS NULL) THEN C = 1;
    END
    ELSE
    IF (PARAM_SEARCH_TERM = 'not_empty') THEN
    BEGIN
        IF (CURR_VAL IS NOT NULL) THEN C = 1;
    END
    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SEARCH_CHECK_STRING (
    VAL VARCHAR(4000),
    CURR_VAL VARCHAR(4000),
    PARAM_SEARCH_TERM VARCHAR(10))
RETURNS (
    C SMALLINT)
AS
BEGIN
    C = 0;
    IF (PARAM_SEARCH_TERM = '=') THEN
    BEGIN
        IF (CURR_VAL = VAL) THEN C = 1;
    END
    ELSE
    IF (PARAM_SEARCH_TERM = '<>') THEN
    BEGIN
        IF (CURR_VAL <> VAL) THEN C = 1;
    END
    ELSE
    IF (PARAM_SEARCH_TERM = 'empty') THEN
    BEGIN
        IF (CURR_VAL IS NULL) THEN C = 1;
    END
    ELSE
    IF (PARAM_SEARCH_TERM = 'not_empty') THEN
    BEGIN
        IF (CURR_VAL IS NOT NULL) THEN C = 1;
    END
    ELSE
    IF (PARAM_SEARCH_TERM = 'mask') THEN
    BEGIN
        IF (UPPER(CURR_VAL) STARTING WITH UPPER(VAL)) THEN C = 1;
    END
    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SEARCH_COLUMNS_LIST (
    I$USER_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$LEVEL_ID BIGINT)
RETURNS (
    SEARCH_ID BIGINT,
    TYPE_ID BIGINT,
    TYPE_CAPTION VARCHAR(3000),
    SEARCH_ORDER SMALLINT,
    SEARCH_VIEW VARCHAR(10),
    PARAM_ID BIGINT,
    PARAM_TYPE SMALLINT,
    TAG VARCHAR(100),
    EDIT_TYPE SMALLINT,
    LIST_ID BIGINT,
    LIST_EDIT_TYPE SMALLINT,
    EDIT_MASK VARCHAR(200),
    RUN_SQL VARCHAR(1000),
    BKG_COLOR INTEGER,
    PARAM_CAPTION VARCHAR(3000),
    HINT_CAPTION VARCHAR(3000),
    BAND_NUM SMALLINT,
    COL_NUM SMALLINT,
    SEARCH_AGREGATE VARCHAR(3),
    MAX_ROW_COUNT INTEGER)
AS
declare variable ROOT_TYPE_ID bigint;
declare variable TYPE_RES_ID bigint;
declare variable PARAM_RES_ID bigint;
declare variable PARAM_SIZE_RES_ID bigint;
declare variable PARAM_HINT_RES_ID bigint;
declare variable V varchar(4000);
declare variable MAX_SEARCH_ORDER integer;
declare variable READ_ONLY bigint;
declare variable V$LANG_CODE varchar(2);
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :V$LANG_CODE;

    SELECT TYPE_ID
    FROM OBJECTS
    WHERE OBJ_ID = :I$OBJ_ID
    INTO :ROOT_TYPE_ID;

    SELECT S.SEARCH_ID, S.MAX_ROW_COUNT
    FROM SEARCH S
    WHERE S.USER_ID = :I$USER_ID AND S.TYPE_ID = :ROOT_TYPE_ID AND S.LEVEL_ID = :I$LEVEL_ID AND S.IS_ACTIVE = 1
    INTO :SEARCH_ID, :MAX_ROW_COUNT;

    IF (SEARCH_ID IS NULL) THEN EXIT;

    SEARCH_ORDER = NULL;

    SELECT MAX(SEARCH_ORDER)
    FROM SEARCHTYPES
    WHERE SEARCH_ID = :SEARCH_ID
    INTO :MAX_SEARCH_ORDER;

    READ_ONLY = 0;

    SELECT FIRST 1 L.READ_ONLY
    FROM LUSERS L
    WHERE L.LEVEL_ID = :I$LEVEL_ID AND L.USER_ID = :I$USER_ID
    INTO :READ_ONLY;

    COL_NUM = -1;

    FOR
        SELECT ST.TYPE_ID, ST.SEARCH_ORDER, ST.SEARCH_VIEW, SF.PARAM_ID, SF.SEARCH_AGREGATE, T.RES_ID, P.RES_ID, P.SIZE_RES_ID,
          P.PARAM_TYPE, P.TAG, P.LIST_ID, P.EDIT_MASK, P.RUN_SQL, P.HINT_RES_ID, LP.EDIT_TYPE, PT.BKG_COLOR
        FROM SEARCHTYPES ST
        LEFT JOIN SEARCHFIELDS SF ON ST.SEARCH_ID = SF.SEARCH_ID AND ST.TYPE_ID = SF.TYPE_ID
        LEFT JOIN TYPES T ON T.TYPE_ID = ST.TYPE_ID
        LEFT JOIN PARAMS P ON P.PARAM_ID = SF.PARAM_ID
        LEFT JOIN LPARAMS LP ON LP.PARAM_ID = P.PARAM_ID AND LP.LEVEL_ID = :I$LEVEL_ID
        LEFT JOIN PARAMTYPES PT ON PT.PARAM_TYPE = P.PARAM_TYPE
        WHERE ST.SEARCH_ID = :SEARCH_ID
        ORDER BY ST.SEARCH_ORDER, SF.GRID_ORDER
        INTO :TYPE_ID, :SEARCH_ORDER, :SEARCH_VIEW, :PARAM_ID, :SEARCH_AGREGATE, :TYPE_RES_ID, :PARAM_RES_ID, :PARAM_SIZE_RES_ID,
           :PARAM_TYPE, :TAG, :LIST_ID, :EDIT_MASK, :RUN_SQL, :PARAM_HINT_RES_ID, :EDIT_TYPE, :BKG_COLOR
    DO
    BEGIN
        BAND_NUM = SEARCH_ORDER;
        COL_NUM = COL_NUM + 1;
        IF ((READ_ONLY = 1) AND (EDIT_TYPE > 0)) THEN EDIT_TYPE = 0;

        SELECT VAL
        FROM RES_GET(:TYPE_RES_ID, :V$LANG_CODE)
        INTO :TYPE_CAPTION;

        -- Подмена для УДОД
        IF(I$LEVEL_ID IN (243, 267, 286) AND TYPE_ID = 14) THEN TYPE_CAPTION = 'Преподаватель объединения';

        IF (SEARCH_VIEW = 'not_exist') THEN
        BEGIN
            EXIT;
        END
        ELSE IF (SEARCH_VIEW = 'count') THEN BEGIN
            PARAM_ID = 0;
            PARAM_TYPE = 17;

            SELECT WORD
            FROM REPORT_WORDS
            WHERE ID = 33
            INTO :PARAM_CAPTION;

            BKG_COLOR = 15132671;
            HINT_CAPTION = '';
            EDIT_TYPE = 0;
            SEARCH_AGREGATE = '';

            SUSPEND;
            EXIT;
        END
        ELSE
        BEGIN

            SELECT VAL
            FROM RES_GET(:PARAM_RES_ID, :V$LANG_CODE)
            INTO :PARAM_CAPTION;

            V = '';

            SELECT VAL
            FROM RES_GET(:PARAM_SIZE_RES_ID, :V$LANG_CODE)
            INTO :V;

            IF (V > '') THEN
            BEGIN
                PARAM_CAPTION = PARAM_CAPTION || ' (' || V || ')';
            END

            SELECT VAL
            FROM RES_GET(:PARAM_HINT_RES_ID, :V$LANG_CODE)
            INTO :HINT_CAPTION;

            IF (SEARCH_ORDER < MAX_SEARCH_ORDER) THEN
                EDIT_TYPE = 0;
            IF (PARAM_TYPE IN (10, 11, 12, 14, 15, 16, 17, 18, 19)) THEN
                EDIT_TYPE = 0;

            LIST_EDIT_TYPE = -1;
            IF (PARAM_TYPE = 6) THEN
            BEGIN
                SELECT L.EDIT_TYPE
                FROM LLISTS L
                WHERE L.LEVEL_ID = :I$LEVEL_ID AND L.LIST_ID = :LIST_ID AND L.IS_DEL = 0
                INTO :LIST_EDIT_TYPE;
            END
        END

        SUSPEND;

    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SEARCH_DEL (
    I$SEARCH_ID BIGINT)
RETURNS (
    SEARCH_ID BIGINT)
AS
BEGIN
    SEARCH_ID = NULL;

    DELETE FROM SEARCH WHERE SEARCH_ID = :I$SEARCH_ID;

    IF (ROW_COUNT > 0) THEN SEARCH_ID = I$SEARCH_ID;

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SEARCH_FIND (
    I$USER_ID BIGINT,
    I$TYPE_ID BIGINT,
    I$LEVEL_ID BIGINT,
    I$FIND_TYPE_ID BIGINT)
RETURNS (
    SEARCH_ID BIGINT,
    USER_ID BIGINT,
    TYPE_ID BIGINT,
    LEVEL_ID BIGINT,
    IS_ACTIVE SMALLINT,
    SEARCH_NAME VARCHAR(100))
AS
DECLARE VARIABLE FIND_SEARCH_ID BIGINT;
DECLARE VARIABLE MAX_SEARCH_ORDER SMALLINT;
DECLARE VARIABLE PARAM_ID BIGINT;
DECLARE VARIABLE GRID_ORDER SMALLINT;
BEGIN
    FIND_SEARCH_ID = NULL;

    FOR SELECT S.SEARCH_ID, S.USER_ID, S.TYPE_ID, S.LEVEL_ID, S.IS_ACTIVE, S.SEARCH_NAME
        FROM SEARCH S
        WHERE S.USER_ID = :I$USER_ID
          AND S.TYPE_ID = :I$TYPE_ID
          AND S.LEVEL_ID = :I$LEVEL_ID
        ORDER BY S.IS_ACTIVE DESC, S.SEARCH_ID DESC
        INTO :SEARCH_ID, :USER_ID, :TYPE_ID, :LEVEL_ID, :IS_ACTIVE, :SEARCH_NAME
    DO
    BEGIN
        MAX_SEARCH_ORDER = NULL;

        SELECT MAX(S.SEARCH_ORDER)
        FROM SEARCHTYPES S
        WHERE S.SEARCH_ID = :SEARCH_ID
          AND S.SEARCH_VIEW = 'list'
        INTO :MAX_SEARCH_ORDER;

        FIND_SEARCH_ID = NULL;

        SELECT S.SEARCH_ID
        FROM SEARCHTYPES S
        WHERE S.SEARCH_ID = :SEARCH_ID
          AND S.TYPE_ID = :I$FIND_TYPE_ID
          AND S.SEARCH_ORDER = :MAX_SEARCH_ORDER
        INTO :FIND_SEARCH_ID;

        IF (FIND_SEARCH_ID IS NOT NULL) THEN
        BEGIN
            UPDATE SEARCH
            SET IS_ACTIVE = 0
            WHERE SEARCH_ID <> :FIND_SEARCH_ID
              AND USER_ID = :I$USER_ID
              AND TYPE_ID = :I$TYPE_ID
              AND LEVEL_ID = :I$LEVEL_ID;

            UPDATE SEARCH
            SET IS_ACTIVE = 1
            WHERE SEARCH_ID = :FIND_SEARCH_ID
              AND USER_ID = :I$USER_ID
              AND TYPE_ID = :I$TYPE_ID
              AND LEVEL_ID = :I$LEVEL_ID;

            SUSPEND;

            EXIT;
        END
    END

    /* if not find */

    IF (FIND_SEARCH_ID IS NULL) THEN
    BEGIN
        USER_ID = I$USER_ID;
        TYPE_ID = I$TYPE_ID;
        LEVEL_ID = I$LEVEL_ID;
        IS_ACTIVE = 1;

        SELECT WORD
        FROM REPORT_WORDS
        WHERE ID = 38
        INTO :SEARCH_NAME;

        SELECT SEARCH_ID
        FROM SEARCH_ADD(NULL, :USER_ID, :TYPE_ID, :LEVEL_ID, :IS_ACTIVE, :SEARCH_NAME)
        INTO :SEARCH_ID;

        SELECT SEARCH_ID
        FROM SEARCHTYPES_ADD(:SEARCH_ID, :I$FIND_TYPE_ID, 0, 'and', 'list', NULL)
        INTO :SEARCH_ID;

        FOR SELECT P.PARAM_ID, P.GRID_ORDER
            FROM PARAMS P
            WHERE P.TYPE_ID = :I$FIND_TYPE_ID
              AND P.IS_TREEVIEW = 1
              AND P.IS_DEL = 0
            ORDER BY P.GRID_ORDER
            INTO :PARAM_ID, :GRID_ORDER
        DO
        BEGIN
            SELECT SEARCH_ID
            FROM SEARCHFIELDS_ADD(:SEARCH_ID, :I$FIND_TYPE_ID, :PARAM_ID, :GRID_ORDER, '')
            INTO :SEARCH_ID;
        END

        SUSPEND;

        EXIT;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SEARCH_INSERT (
    SEARCH_ID BIGINT NOT NULL,
    SEARCH_ORDER SMALLINT NOT NULL,
    CURR_OBJECT_ID BIGINT,
    CURR_OBJECT_TYPE_ID BIGINT,
    TYPE_SEARCH_TERM VARCHAR(10),
    PRIOR_PARAM_ID BIGINT,
    SEARCH_PARENT_TYPE_ID BIGINT,
    SEARCH_TYPE_ID BIGINT,
    CHECK_OBJ_ID BIGINT,
    CHILD_LINK_ID BIGINT)
AS
DECLARE VARIABLE EXIST_FL SMALLINT;
BEGIN
    EXIST_FL = 0;

    IF ((:PRIOR_PARAM_ID > 0 OR :SEARCH_ORDER = 0) AND EXISTS(
        SELECT FIRST 1 1 FROM SEARCHING
        WHERE SEARCH_ID = :SEARCH_ID
          AND SEARCH_ORDER = :SEARCH_ORDER
          AND OBJECT_ID = :CHECK_OBJ_ID)) THEN
    BEGIN
        EXIST_FL = 1;
    END

    IF (:PRIOR_PARAM_ID > 0 AND :TYPE_SEARCH_TERM = 'and' AND :EXIST_FL = 1) THEN
    BEGIN
        UPDATE SEARCHING
        SET IS_OK = 1
        WHERE SEARCH_ID = :SEARCH_ID
          AND SEARCH_ORDER = :SEARCH_ORDER
          AND OBJECT_ID = :CHECK_OBJ_ID;
    END

    IF (((PRIOR_PARAM_ID = 0) OR (TYPE_SEARCH_TERM = 'or')) AND (EXIST_FL = 0)) THEN
    BEGIN
        -- если параметр был задан
        IF (:CHILD_LINK_ID IS NULL) THEN
        BEGIN
            SELECT FIRST 1 L.PARENT_ID, L.PARENT_TYPE_ID, L.LINK_ID
            FROM LINKS L
            -- поиск только среди объектов предыдущего уровня
            JOIN (SELECT PARENT_TYPE_ID, PARENT_ID, OBJECT_ID
                  FROM SEARCHING
                  WHERE :SEARCH_ORDER > 0
                    AND SEARCH_ID = :SEARCH_ID
                    AND SEARCH_ORDER = :SEARCH_ORDER-1
                  UNION ALL
                  SELECT NULL, NULL, NULL FROM RDB$DATABASE
                  WHERE :SEARCH_ORDER = 0) S
            ON L.PARENT_ID = S.OBJECT_ID OR :SEARCH_ORDER = 0
            WHERE L.OBJ_ID = :CHECK_OBJ_ID
              AND L.DATE_DEL IS NULL
              AND L.OBJ_TYPE_ID = :SEARCH_TYPE_ID
              AND (:SEARCH_PARENT_TYPE_ID IS NULL OR L.PARENT_TYPE_ID = :SEARCH_PARENT_TYPE_ID)
            INTO :CURR_OBJECT_ID, :CURR_OBJECT_TYPE_ID, :CHILD_LINK_ID;
        END

        -- если подходящий по условию объект найден
        IF (:CHILD_LINK_ID IS NOT NULL) THEN
        BEGIN
            INSERT INTO SEARCHING (SEARCH_ID, SEARCH_ORDER, PARENT_ID, PARENT_TYPE_ID, LINK_ID, OBJECT_ID, OBJECT_TYPE_ID, IS_OK)
            VALUES (:SEARCH_ID, :SEARCH_ORDER, :CURR_OBJECT_ID, :CURR_OBJECT_TYPE_ID, :CHILD_LINK_ID, :CHECK_OBJ_ID, :SEARCH_TYPE_ID, 1);
            -- добавим и предка, если это не верхний уровень
            IF (:SEARCH_ORDER > 0) THEN
            BEGIN
                UPDATE SEARCHING
                SET IS_OK = -1
                WHERE SEARCH_ID = :SEARCH_ID
                  AND SEARCH_ORDER = :SEARCH_ORDER-1
                  AND OBJECT_ID = :CURR_OBJECT_ID;
            END
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SEARCH_LIST (
    I$USER_ID BIGINT,
    I$TYPE_ID BIGINT,
    I$LEVEL_ID BIGINT)
RETURNS (
    SEARCH_ID BIGINT,
    USER_ID BIGINT,
    TYPE_ID BIGINT,
    LEVEL_ID BIGINT,
    IS_ACTIVE SMALLINT,
    SEARCH_NAME VARCHAR(100))
AS
BEGIN
    FOR SELECT SEARCH_ID, USER_ID, TYPE_ID, LEVEL_ID, IS_ACTIVE, SEARCH_NAME
        FROM SEARCH
        WHERE USER_ID = :I$USER_ID
          AND TYPE_ID = :I$TYPE_ID
          AND LEVEL_ID = :I$LEVEL_ID
        INTO :SEARCH_ID, :USER_ID, :TYPE_ID, :LEVEL_ID, :IS_ACTIVE, :SEARCH_NAME
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SEARCH_OBJECT_CHILDREN_GET (
    I$OBJ_ID BIGINT,
    I$LINK_ID BIGINT,
    I$TYPE_ID BIGINT,
    I$CHILDREN_TYPE_ID BIGINT,
    I$LEVEL_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    LINK_ID BIGINT,
    TYPE_ID BIGINT)
AS
declare variable L bigint;
declare variable T bigint;
declare variable X bigint;
declare variable ALT_CHILDREN_TYPE_ID bigint = -1;
declare variable V$FAKE_LINK_ID bigint;
BEGIN
    -- Затычка чтобы искать в академическом отпуске
    IF(I$CHILDREN_TYPE_ID = 8) THEN ALT_CHILDREN_TYPE_ID = 289;
    IF(I$CHILDREN_TYPE_ID = 9) THEN ALT_CHILDREN_TYPE_ID = 289;

    -- Когда достигли требуемого типа объекта - возвращаем сам объект
    IF (I$TYPE_ID = I$CHILDREN_TYPE_ID OR I$TYPE_ID = ALT_CHILDREN_TYPE_ID) THEN
    BEGIN
        OBJ_ID = I$OBJ_ID;
        LINK_ID = I$LINK_ID;
        TYPE_ID = I$TYPE_ID;
        SUSPEND;
        EXIT;
    END

    -- Выполняем поиск среди дочерних объектов и перечня типов, допустимых как дочерние на заданном уровне поиска
    FOR
        SELECT L.LINK_ID, L.OBJ_ID, L.OBJ_TYPE_ID
        FROM LINKS L
        WHERE L.PARENT_ID = :I$OBJ_ID
          AND L.PARENT_TYPE_ID = :I$TYPE_ID
          AND L.OBJ_TYPE_ID IN (SELECT CHILD_ID FROM SEARCHING_TYPES WHERE TYPE_ID = :I$TYPE_ID)
          AND L.DATE_DEL IS NULL
        INTO :L, :X, :T
    DO
    BEGIN
        FOR
            SELECT OBJ_ID, LINK_ID, TYPE_ID
            FROM SEARCH_OBJECT_CHILDREN_GET(:X, :L, :T, :I$CHILDREN_TYPE_ID, :I$LEVEL_ID)
            INTO :OBJ_ID, :LINK_ID, :TYPE_ID
        DO
            SUSPEND;
    END

    -- Инжектируем в результаты поиска виртуальные данные
    -- Внимание: для виртуальных записей надо подсунуть любой реальный LINK_ID
    SELECT FIRST 1 LINK_ID
    FROM LINKS
    WHERE DATE_DEL IS NULL
    INTO :V$FAKE_LINK_ID;

    -- Записи реестра движения
    IF(I$TYPE_ID = 10 AND EXISTS(SELECT FIRST 1 1 FROM SEARCHING_TYPES WHERE TYPE_ID = :I$TYPE_ID AND CHILD_ID = 424)) THEN
    BEGIN
        FOR
            SELECT M.OBJ_ID, :V$FAKE_LINK_ID, 424
            FROM PERSON_MOVEMENTS M
            JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 9 -- временно для ускорения выборки, только классы
            WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :I$OBJ_ID
            INTO :OBJ_ID, :LINK_ID, :TYPE_ID
        DO
            SUSPEND;
    END

END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SEARCH_PARAMS_LIST (
    I$TYPE_ID BIGINT,
    I$LEVEL_ID BIGINT,
    I$LANG_CODE VARCHAR(2) = 'RU')
RETURNS (
    TYPE_ID BIGINT,
    EXT_TYPE_ID BIGINT,
    TAB_ID BIGINT,
    TAB_CAPTION VARCHAR(4000),
    TAB_NUM INTEGER,
    PARAM_ID BIGINT,
    PARAM_TYPE SMALLINT,
    EDIT_TYPE SMALLINT,
    NATIVE SMALLINT,
    CAPTION VARCHAR(4000),
    IS_CHECKED SMALLINT,
    GRID_ORDER SMALLINT,
    LIST_ID BIGINT,
    TAG VARCHAR(100),
    RUN_SQL VARCHAR(1000),
    BKG_COLOR INTEGER,
    VAL_S VARCHAR(4000),
    VAL_I BIGINT,
    VAL_F DOUBLE PRECISION,
    VAL_D DATE)
AS
declare variable TAB_RES_ID bigint;
declare variable PARAM_RES_ID bigint;
declare variable SIZE_RES_ID bigint;
declare variable V varchar(4000);
BEGIN
    IS_CHECKED = 0;
    EDIT_TYPE = 1;
    NATIVE = 1;
    VAL_S = NULL;
    VAL_I = NULL;
    VAL_F = NULL;
    VAL_D = NULL;

    FOR
        SELECT T.TAB_ID,
               T.RES_ID,
               T.TAB_NUM,
               P.PARAM_ID,
               P.PARAM_TYPE,
               P.RES_ID,
               P.SIZE_RES_ID,
               P.GRID_ORDER,
               P.TYPE_ID,
               P.LIST_ID,
               P.TAG,
               P.RUN_SQL,
               PT.BKG_COLOR,
               NULL
        FROM TABS T

        JOIN PARAMS P
        ON P.TAB_ID = T.TAB_ID
        AND P.TYPE_ID = :I$TYPE_ID
        AND P.PARAM_TYPE NOT IN (11,12,14,15,16)
        AND P.IS_DEL = 0

        JOIN PARAMTYPES PT
        ON PT.PARAM_TYPE = P.PARAM_TYPE

        JOIN LPARAMS LP
        ON LP.PARAM_ID = P.PARAM_ID
        AND LP.LEVEL_ID = :I$LEVEL_ID
        AND LP.EDIT_TYPE > -1

        WHERE T.TYPE_ID = :I$TYPE_ID
        AND T.IS_DEL = 0

        UNION ALL

        SELECT T.TAB_ID,
               T.RES_ID,
               T.TAB_NUM,
               P.PARAM_ID,
               P.PARAM_TYPE,
               P.RES_ID,
               P.SIZE_RES_ID,
               1000 + P.GRID_ORDER,
               :I$TYPE_ID,
               P.LIST_ID,
               P.TAG,
               P.RUN_SQL,
               PT.BKG_COLOR,
               P.TYPE_ID
        FROM TABS T

        JOIN PARAMS P
        ON P.TAB_ID = T.TAB_ID
        AND P.TYPE_ID = T.TYPE_ID
        AND P.PARAM_TYPE NOT IN (11,12,14,15,16)
        AND P.IS_DEL = 0

        JOIN PARAMTYPES PT
        ON PT.PARAM_TYPE = P.PARAM_TYPE

        JOIN LPARAMS LP
        ON LP.PARAM_ID = P.PARAM_ID
        AND LP.LEVEL_ID = :I$LEVEL_ID
        AND LP.EDIT_TYPE > -1

        WHERE T.TYPE_ID IN (SELECT DISTINCT EXT_OBJ_TYPE_ID FROM LINKS WHERE OBJ_TYPE_ID = :I$TYPE_ID AND DATE_DEL IS NULL AND EXT_OBJ_TYPE_ID IS NOT NULL)
        AND T.IS_DEL = 0

        UNION ALL

        SELECT NULL,
               NULL,
               1000000,
               P.PARAM_ID,
               P.PARAM_TYPE,
               P.RES_ID,
               P.SIZE_RES_ID,
               P.GRID_ORDER,
               P.TYPE_ID,
               P.LIST_ID,
               P.TAG,
               P.RUN_SQL,
               PT.BKG_COLOR,
               NULL
        FROM PARAMS P

        JOIN PARAMTYPES PT
        ON PT.PARAM_TYPE = P.PARAM_TYPE

        JOIN LPARAMS LP
        ON LP.PARAM_ID = P.PARAM_ID
        AND LP.LEVEL_ID = :I$LEVEL_ID AND LP.EDIT_TYPE > -1

        WHERE P.TYPE_ID = :I$TYPE_ID
        AND P.PARAM_TYPE NOT IN (11,12,14,15,16)
        AND P.TAB_ID IS NULL
        AND P.IS_DEL = 0

        ORDER BY 3, 8

        INTO :TAB_ID,
             :TAB_RES_ID,
             :TAB_NUM,
             :PARAM_ID,
             :PARAM_TYPE,
             :PARAM_RES_ID,
             :SIZE_RES_ID,
             :GRID_ORDER,
             :TYPE_ID,
             :LIST_ID,
             :TAG,
             :RUN_SQL,
             :BKG_COLOR,
             :EXT_TYPE_ID
    DO
    BEGIN
        IF (TAB_RES_ID IS NOT NULL) THEN
        BEGIN
            SELECT UPPER(VAL)
            FROM RES_GET(:TAB_RES_ID, :I$LANG_CODE)
            INTO :TAB_CAPTION;
        END
        ELSE
        BEGIN
            TAB_CAPTION = '';
        END

        SELECT VAL
        FROM RES_GET(:PARAM_RES_ID, :I$LANG_CODE)
        INTO :CAPTION;

        V = '';

        SELECT VAL
        FROM RES_GET(:SIZE_RES_ID, :I$LANG_CODE)
        INTO :V;

        IF (V > '') THEN
        BEGIN
            CAPTION = CAPTION || ' (' || V || ')';
        END

        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SEARCH_TYPES_GET (
    I$TYPE_ID BIGINT,
    I$CHILD_ID BIGINT,
    I$LEVEL_ID BIGINT)
RETURNS (
    TYPE_ID BIGINT,
    CHILD_ID BIGINT,
    FLAG SMALLINT)
AS
declare variable T bigint;
declare variable C bigint;
BEGIN
    FLAG = 0;

    FOR SELECT P.TYPE_ID, P.CHILD_ID
        FROM PARENTS P
        INNER JOIN LTYPES LT ON LT.TYPE_ID = P.TYPE_ID
        INNER JOIN LTYPES LC ON LC.TYPE_ID = P.CHILD_ID
        WHERE P.CHILD_ID = :I$CHILD_ID
          AND P.CHILD_ID <> P.TYPE_ID -- SUBJECTS
          AND P.IS_DEL = 0
          AND ((P.IS_ADD = 1) OR (P.IS_INTERNAL_ADD = 1) OR (P.IS_LINK = 1) OR (P.IS_SELECT = 1) OR (P.IS_FROM_LIST = 1))
          AND LT.LEVEL_ID = :I$LEVEL_ID
          AND LT.EDIT_TYPE > -1
          AND LT.IS_DEL = 0
          AND LC.LEVEL_ID = :I$LEVEL_ID
          AND LC.EDIT_TYPE > -1
          AND LC.IS_DEL = 0
        INTO :T, :C
    DO
    BEGIN
        IF (T = I$TYPE_ID) THEN
        BEGIN
            FLAG = 1;
        END
        ELSE
        BEGIN
            FOR SELECT TYPE_ID, CHILD_ID, FLAG
                FROM SEARCH_TYPES_GET(:I$TYPE_ID, :T, :I$LEVEL_ID)
                INTO :TYPE_ID, :CHILD_ID, :FLAG
            DO
            BEGIN
                SUSPEND;
            END
        END

        TYPE_ID = T;
        CHILD_ID = C;
        SUSPEND;

    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SEARCH_TYPES_GET2 (
    I$SEARCH_ID BIGINT)
RETURNS (
    TYPE_ID BIGINT,
    SEARCH_ORDER SMALLINT,
    SEARCH_TERM VARCHAR(10),
    SEARCH_VIEW VARCHAR(10),
    OWNER_TYPE_ID BIGINT,
    IS_SKIPED SMALLINT)
AS
DECLARE VARIABLE V$TYPE_ID BIGINT;
DECLARE VARIABLE V$SEARCH_ORDER SMALLINT;
DECLARE VARIABLE V$SEARCH_TERM VARCHAR(10);
DECLARE VARIABLE V$OWNER_TYPE_ID BIGINT;
DECLARE VARIABLE V$LEVEL_ID BIGINT;
DECLARE VARIABLE V$PARENT_TYPE_ID BIGINT;
BEGIN
    -- процедура возвращает дерево типов объектов поиска, восстанавливая пропущенные пользователем узлы
    IS_SKIPED = 0;
    V$PARENT_TYPE_ID = 2;

    SELECT LEVEL_ID
    FROM SEARCH
    WHERE SEARCH_ID = :I$SEARCH_ID
    INTO :V$LEVEL_ID;

    FOR SELECT TYPE_ID, SEARCH_ORDER, SEARCH_TERM, OWNER_TYPE_ID, SEARCH_VIEW
        FROM SEARCHTYPES
        WHERE SEARCH_ID = :I$SEARCH_ID
        ORDER BY SEARCH_ORDER
        INTO :V$TYPE_ID, :V$SEARCH_ORDER, :V$SEARCH_TERM, :V$OWNER_TYPE_ID, :SEARCH_VIEW
    DO
    BEGIN
        IF (NOT EXISTS(
            SELECT FIRST 1 1
            FROM SEARCH_TYPES_GET(:V$PARENT_TYPE_ID, :V$TYPE_ID, :V$LEVEL_ID)
            WHERE TYPE_ID = :V$PARENT_TYPE_ID
            AND CHILD_ID = :V$TYPE_ID)) THEN
        BEGIN
            -- восстановим узлы между текущим и предыдущим
            FOR SELECT CHILD_ID, :V$SEARCH_ORDER + :IS_SKIPED, NULL, NULL
                FROM SEARCH_TYPES_GET(:V$PARENT_TYPE_ID, :V$TYPE_ID, :V$LEVEL_ID)
                WHERE FLAG = 1
                INTO :TYPE_ID, :SEARCH_ORDER, :SEARCH_TERM, :OWNER_TYPE_ID
            DO
            BEGIN
                IF (:TYPE_ID = :V$TYPE_ID) THEN
                BEGIN
                    BREAK;
                END
                SUSPEND;
                IS_SKIPED = 1;
            END
        END
        V$PARENT_TYPE_ID = :V$TYPE_ID;
        TYPE_ID = :V$TYPE_ID;
        SEARCH_ORDER = :V$SEARCH_ORDER + :IS_SKIPED;
        SEARCH_TERM = :V$SEARCH_TERM;
        OWNER_TYPE_ID = :V$OWNER_TYPE_ID;
        SUSPEND;
        IS_SKIPED = 0;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SERIALIZE_OBJECT (
    PARENT_ID BIGINT,
    OBJ_ID BIGINT,
    TREE_LEVEL SMALLINT = 0,
    EXPAND_REFS SMALLINT = 0,
    MAX_LEVELS SMALLINT = 2,
    LOCAL_ONLY SMALLINT = 0,
    PARENT_TAG VARCHAR(400) = '')
RETURNS (
    TAG VARCHAR(200),
    VAL VARCHAR(6000))
AS
declare variable CHILD_ID bigint;
declare variable TYPE_ID bigint;
declare variable PARAM_ID bigint;
declare variable VAL_I bigint;
declare variable VAL_D date;
declare variable VAL_T time;
declare variable VAL_DT timestamp;
declare variable TMP_ID bigint;
begin
  IF(TREE_LEVEL > MAX_LEVELS) THEN EXIT;

  -- Проверяем наличие такого объекта и получаем его тип
  SELECT OBJ_ID, OBJ_TYPE_ID
  FROM LINKS
  WHERE ((PARENT_ID = :PARENT_ID) OR (PARENT_ID IS NULL AND :PARENT_ID IS NULL)) AND OBJ_ID = :OBJ_ID AND DATE_DEL IS NULL
  INTO :CHILD_ID, :TYPE_ID;

  -- Дополняем путь
  IF(PARENT_TAG <> '') THEN PARENT_TAG = PARENT_TAG || ':';

  -- Выгружаем сам объект
  TAG = PARENT_TAG || 'obj';
  VAL = NULL;
  SUSPEND;

  -- Поля выводим только если объект был найден, иначе будет пустой <obj>
  IF(CHILD_ID IS NOT NULL) THEN 
  BEGIN

      TAG = PARENT_TAG || 'obj::id';
      VAL = CHILD_ID;
      SUSPEND;

      TAG = PARENT_TAG || 'obj::t';
      VAL = TYPE_ID;
      SUSPEND;

      -- Если указано разыменование ссылок, вычисляем формульные поля и также их выдаем, это нужно обязательно делать первым шагом
      FOR
          SELECT P.PARAM_ID, COALESCE(F.VAL, '')
          FROM PARAMS P
          LEFT JOIN DO_FUNC(:OBJ_ID, P.PARAM_ID, P.DO_FUNC, P.AUTO_LISTVAL_ID, 1, :PARENT_ID) F ON 1 = 1
          WHERE P.TYPE_ID = :TYPE_ID AND P.IS_DEL = 0 AND P.PARAM_TYPE IN (17, 19) AND P.DO_FUNC <> '0'
          ORDER BY P.GRID_ORDER
          INTO :PARAM_ID, :VAL
      DO
      BEGIN
          TAG = PARENT_TAG || 'obj::v' || PARAM_ID;
          SUSPEND;
      END

      -- Строковые параметры
      FOR
          SELECT V.PARAM_ID, V.VAL
          FROM VALS V
          JOIN PARAMS P ON P.PARAM_ID = V.PARAM_ID AND P.IS_DEL = 0 AND P.PARAM_TYPE IN (7, 8, 20, 21)
          WHERE V.OBJ_ID = :OBJ_ID AND V.IS_DEL = 0
          ORDER BY 1
          INTO :PARAM_ID, :VAL
      DO
      BEGIN
          TAG = PARENT_TAG || 'obj::v' || PARAM_ID;
          SUSPEND;
      END

      -- Целочисленные параметры
      FOR
          SELECT V.PARAM_ID, V.VAL
          FROM VALI V
          JOIN PARAMS P ON P.PARAM_ID = V.PARAM_ID AND P.IS_DEL = 0 AND P.PARAM_TYPE IN (1)
          WHERE V.OBJ_ID = :OBJ_ID AND V.IS_DEL = 0
          ORDER BY 1
          INTO :PARAM_ID, :VAL
      DO
      BEGIN
          TAG = PARENT_TAG || 'obj::v' || PARAM_ID;
          SUSPEND;
      END

      -- Вещественные параметры
      FOR
          SELECT V.PARAM_ID, V.VAL
          FROM VALF V
          JOIN PARAMS P ON P.PARAM_ID = V.PARAM_ID AND P.IS_DEL = 0 AND P.PARAM_TYPE IN (2)
          WHERE V.OBJ_ID = :OBJ_ID AND V.IS_DEL = 0
          ORDER BY 1
          INTO :PARAM_ID, :VAL
      DO
      BEGIN
          TAG = PARENT_TAG || 'obj::v' || PARAM_ID;
          SUSPEND;
      END

      -- Списковые параметры
      FOR
          SELECT V.PARAM_ID, V.LISTVAL_ID
          FROM VALL V
          JOIN PARAMS P ON P.PARAM_ID = V.PARAM_ID AND P.IS_DEL = 0 AND P.PARAM_TYPE IN (6)
          WHERE V.OBJ_ID = :OBJ_ID AND V.IS_DEL = 0
          ORDER BY 1
          INTO :PARAM_ID, :VAL
      DO
      BEGIN
          TAG = PARENT_TAG || 'obj::v' || PARAM_ID;
          SUSPEND;
      END

      -- Ссылочные параметры
      IF(EXPAND_REFS = 0) THEN
      BEGIN
          -- Если не указано разыменование - выдаем коды объектов
          FOR
              SELECT V.PARAM_ID, V.VAL
              FROM VALR V
              JOIN PARAMS P ON P.PARAM_ID = V.PARAM_ID AND P.IS_DEL = 0 AND P.PARAM_TYPE IN (13)
              WHERE V.OBJ_ID = :OBJ_ID AND V.IS_DEL = 0
              ORDER BY V.PARAM_ID
              INTO :PARAM_ID, :VAL
          DO
          BEGIN
              TAG = PARENT_TAG || 'obj::v' || PARAM_ID;
              SUSPEND;
          END
      END
      ELSE
      BEGIN
          -- Если указано разыменование - разыменовываем, но при этом код тоже выдаем
          FOR
              SELECT V.PARAM_ID, C.CAPTION, V.VAL
              FROM VALR V
              JOIN PARAMS P ON P.PARAM_ID = V.PARAM_ID AND P.IS_DEL = 0 AND P.PARAM_TYPE IN (13)
              LEFT JOIN OBJECT_CAPTION_GET(VAL) C ON 1 = 1
              WHERE V.OBJ_ID = :OBJ_ID AND V.IS_DEL = 0
              ORDER BY 1
              INTO :PARAM_ID, :VAL, :VAL_I
          DO
          BEGIN
              TAG = PARENT_TAG || 'obj::v' || PARAM_ID;
              SUSPEND;
              TAG = PARENT_TAG || 'obj::ref' || PARAM_ID;
              VAL = VAL_I;
              SUSPEND;
          END
      END

      -- Даты
      FOR
          SELECT V.PARAM_ID, V.VAL
          FROM VALD V
          JOIN PARAMS P ON P.PARAM_ID = V.PARAM_ID AND P.IS_DEL = 0 AND P.PARAM_TYPE IN (4)
          WHERE V.OBJ_ID = :OBJ_ID AND V.IS_DEL = 0
          ORDER BY 1
          INTO :PARAM_ID, :VAL_D
      DO
      BEGIN
          TAG = PARENT_TAG || 'obj::v' || PARAM_ID;
          VAL = EXTRACT(YEAR FROM VAL_D) || '-' || EXTRACT(MONTH FROM VAL_D) || '-' || EXTRACT(DAY FROM VAL_D);
          SUSPEND;
      END
      FOR
          SELECT V.PARAM_ID, V.VAL
          FROM VALT V
          JOIN PARAMS P ON P.PARAM_ID = V.PARAM_ID AND P.IS_DEL = 0 AND P.PARAM_TYPE IN (5)
          WHERE V.OBJ_ID = :OBJ_ID AND V.IS_DEL = 0
          ORDER BY 1
          INTO :PARAM_ID, :VAL_T
      DO
      BEGIN
          TAG = PARENT_TAG || 'obj::v' || PARAM_ID;
          VAL = EXTRACT(HOUR FROM VAL_T) || ':' || EXTRACT(MINUTE FROM VAL_T) || '-' || EXTRACT(SECOND FROM VAL_T) || ':' || EXTRACT(MILLISECOND FROM VAL_T) || '"';
          SUSPEND;
      END
      FOR
          SELECT V.PARAM_ID, V.VAL
          FROM VALDT V
          JOIN PARAMS P ON P.PARAM_ID = V.PARAM_ID AND P.IS_DEL = 0 AND P.PARAM_TYPE IN (3)
          WHERE V.OBJ_ID = :OBJ_ID AND V.IS_DEL = 0
          ORDER BY 1
          INTO :PARAM_ID, :VAL_DT
      DO
      BEGIN
          TAG = PARENT_TAG || 'obj::v' || PARAM_ID;
          VAL = EXTRACT(YEAR FROM VAL_DT) || '-' || EXTRACT(MONTH FROM VAL_DT) || '-' || EXTRACT(DAY FROM VAL_DT) ||
              'T' || EXTRACT(HOUR FROM VAL_DT) || ':' || EXTRACT(MINUTE FROM VAL_DT) || '-' || EXTRACT(SECOND FROM VAL_DT) ||
              ':' || EXTRACT(MILLISECOND FROM VAL_DT) || '"';
          SUSPEND;
      END

      -- Адреса
      FOR
          SELECT V.PARAM_ID, COALESCE(REGION, '') || '|' || COALESCE(DISTRICT, '') || '|' || COALESCE(TOWN, '') || '|' || COALESCE(SETTLEMENT, '') || '|' ||
              COALESCE(STREET, '') || '|' || COALESCE(HOUSE, '') || '|' || COALESCE(LITER, '') || '|' ||
              COALESCE(CORP, '') || '|' || COALESCE(FLAT, '') || '|' || COALESCE(POST_INDEX, '') || '|' || COALESCE(OCATD, '') || '|' ||
              COALESCE(FIAS_UID, '') || '|' || COALESCE(STREET_UID, '')
          FROM VALA V
          JOIN PARAMS P ON P.PARAM_ID = V.PARAM_ID AND P.IS_DEL = 0 AND P.PARAM_TYPE IN (18)
          WHERE V.OBJ_ID = :OBJ_ID AND V.IS_DEL = 0
          ORDER BY 1
          INTO :PARAM_ID, :VAL
      DO
      BEGIN
          TAG = PARENT_TAG || 'obj::v' || PARAM_ID;
          SUSPEND;
      END

      -- VALM тут попадаться не должны

  END

  IF((CHILD_ID IS NOT NULL) AND (TREE_LEVEL < MAX_LEVELS - 1)) THEN
  BEGIN

      FOR
          SELECT OBJ_ID, OBJ_TYPE_ID
          FROM LINKS
          WHERE PARENT_ID = :OBJ_ID AND DATE_DEL IS NULL -- AND OBJ_TYPE_ID NOT IN ()
          ORDER BY 2, 1
          INTO :CHILD_ID, :TYPE_ID
      DO
      BEGIN

          IF(LOCAL_ONLY = 0) THEN
          BEGIN
              -- Выгружаем без фильтрации
              FOR
                  SELECT TAG, VAL
                  FROM SERIALIZE_OBJECT(:OBJ_ID, :CHILD_ID, :TREE_LEVEL + 1, :EXPAND_REFS, :MAX_LEVELS, :LOCAL_ONLY, :PARENT_TAG || 'obj:')
                  INTO :TAG, VAL
              DO
              BEGIN
                  SUSPEND;
              END
          END
          ELSE
          BEGIN
              -- Только локальные объекты (созданные не в эталонной базе), исключение для объектов #51 Предмет
              TMP_ID = TRUNC(CHILD_ID / 1000000000);
              IF(TMP_ID <> 0 OR TYPE_ID = 51) THEN
              BEGIN
                  FOR
                      SELECT TAG, VAL
                      FROM SERIALIZE_OBJECT(:OBJ_ID, :CHILD_ID, :TREE_LEVEL + 1, :EXPAND_REFS, :MAX_LEVELS, :LOCAL_ONLY, :PARENT_TAG || 'obj')
                      INTO :TAG, VAL
                  DO
                  BEGIN
                      SUSPEND;
                  END
              END
          END

      END

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SERVICE_MEO_DEFS (
    I$TIMEMARK TIMESTAMP)
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(1000))
AS
declare variable V$OBJ_ID bigint;
declare variable V$YEAR_START date;
declare variable S varchar(1000);
declare variable V$YEAR_ID bigint;
declare variable V$TEACHER_ID bigint;
declare variable V$D1 date;
declare variable V$D2 date;
declare variable V$SUBJECT_ID bigint;
declare variable V$STAGE varchar(100);
declare variable V$GROUP_ID bigint;
declare variable V$TYPE_ID bigint;
begin

  SELECT FIRST 1 CAST(LV.TAG AS DATE), LV.LISTVAL_ID
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$YEAR_START, :V$YEAR_ID;

  -- Список классов отдаем всегда
  TAG_NAME = 'classes::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
    SELECT L9.OBJ_ID, C.CAPTION, LV.TAG
    FROM LINKS L2
    JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V49.LISTVAL_ID
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 187) AND L9.DATE_DEL IS NULL
    LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C ON 1 = 1
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :V$OBJ_ID, :S, :V$STAGE
  DO
  BEGIN
    TAG_NAME = 'classes:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'classes:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'classes:r:name';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'classes:r:stage';
    VAL = V$STAGE;
    SUSPEND;
  END

  -- Предметы
  TAG_NAME = 'subjects::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
    SELECT DISTINCT J.SUBJECT_ID, C.CAPTION
    FROM CJ2_JOURNAL J
    LEFT JOIN OBJECT_CAPTION_GET(J.SUBJECT_ID) C ON 1 = 1
    WHERE J.DATE_DEL IS NULL AND J.YEAR_ID = :V$YEAR_ID AND J.JOURNAL_TYPE IN (0, 1)
      AND (:I$TIMEMARK IS NULL OR J.DATE_MODIFY >= :I$TIMEMARK)
    INTO :V$OBJ_ID, :S
  DO
  BEGIN
    TAG_NAME = 'subjects:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'subjects:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'subjects:r:name';
    VAL = S;
    SUSPEND;
  END

  -- Список групп текущего года
  TAG_NAME = 'groups::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
    SELECT J.OBJ_ID, J.GRADE_ID, J.JOURNAL_NAME || ' - ' || C.CAPTION, J.TEACHER_ID, J.SUBJECT_ID, LV.TAG, J.GRADE_TYPE_ID
    FROM CJ2_JOURNAL J
    JOIN LISTVALS LV ON LV.LISTVAL_ID = J.STAGE_INDEX
    LEFT JOIN OBJECT_CAPTION_GET(J.SUBJECT_ID) C ON 1 = 1
    WHERE J.DATE_DEL IS NULL AND J.YEAR_ID = :V$YEAR_ID AND J.JOURNAL_TYPE IN (0, 1)
      AND (:I$TIMEMARK IS NULL OR J.DATE_MODIFY >= :I$TIMEMARK)
    INTO :V$OBJ_ID, :V$GROUP_ID, :S, :V$TEACHER_ID, :V$SUBJECT_ID, :V$STAGE, :V$TYPE_ID
  DO
  BEGIN
    TAG_NAME = 'groups:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'groups:r:id';
    VAL = V$GROUP_ID;
    SUSPEND;
    TAG_NAME = 'groups:r:journal_id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'groups:r:name';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'groups:r:teacher';
    VAL = V$TEACHER_ID;
    SUSPEND;
    TAG_NAME = 'groups:r:stage';
    VAL = V$STAGE;
    SUSPEND;
    TAG_NAME = 'groups:r:subject';
    VAL = V$SUBJECT_ID;
    SUSPEND;
    TAG_NAME = 'groups:r:class_id';
    VAL = NULL;
    IF(V$TYPE_ID IN (9, 187)) THEN VAL = V$GROUP_ID;
    ELSE BEGIN
      SELECT FIRST 1 M2.GROUP_ID
      FROM PERSON_MOVEMENTS M
      JOIN PERSON_MOVEMENTS M2 ON M2.DATE_DEL IS NULL AND M2.PERSON_ID = M.PERSON_ID AND M2.DATE_OUT IS NULL
      JOIN OBJECTS G ON G.OBJ_ID = M2.GROUP_ID AND G.TYPE_ID IN (9, 187)
      WHERE M.DATE_DEL IS NULL AND M.GROUP_ID = :V$GROUP_ID AND M.DATE_OUT IS NULL
      ORDER BY M2.DATE_IN DESC
      INTO :VAL;
    END
    SUSPEND;
  END

  -- Списки персон
  TAG_NAME = 'persons::json&colon;array';
  VAL = '1';
  SUSPEND;

  -- Учителя, по которым были изменения с указанной метки времени
  FOR
    SELECT DISTINCT L14.OBJ_ID
    FROM LINKS L14
    JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
    WHERE L14.PARENT_TYPE_ID IN (2, 84) AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
      AND (V74.VAL IS NULL OR V74.VAL >= :V$YEAR_START)
      AND (:I$TIMEMARK IS NULL OR L15.DATE_MODIFY >= :I$TIMEMARK OR V74.DATE_MODIFY >= :I$TIMEMARK)
    INTO :V$OBJ_ID
  DO
  BEGIN
    TAG_NAME = 'persons:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'persons:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'persons:r:name';
    VAL = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$OBJ_ID));
    SUSPEND;
    TAG_NAME = 'persons:r:type';
    VAL = 14;
    SUSPEND;
  END

  -- Обучающиеся
  FOR
    SELECT DISTINCT M.PERSON_ID
    FROM PERSON_MOVEMENTS M
    JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID IN (9, 187)
    WHERE M.DATE_DEL IS NULL
      AND M.DATE_IN >= DATEADD(-1 MONTH TO :V$YEAR_START)
      AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :V$YEAR_START)
      AND (:I$TIMEMARK IS NULL OR M.DATE_MODIFY >= :I$TIMEMARK)
    INTO :V$OBJ_ID
  DO
  BEGIN
    TAG_NAME = 'persons:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'persons:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'persons:r:name';
    VAL = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$OBJ_ID, 23));
    SUSPEND;
    TAG_NAME = 'persons:r:type';
    VAL = 10;
    SUSPEND;
    TAG_NAME = 'persons:r:class_id';
    VAL = NULL;
    SELECT FIRST 1 M.GROUP_ID
    FROM PERSON_MOVEMENTS M
    JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID IN (9, 187)
    WHERE M.DATE_DEL IS NULL AND M.DATE_OUT IS NULL AND M.PERSON_ID = :V$OBJ_ID
    ORDER BY M.DATE_OUT DESC NULLS FIRST
    INTO :VAL;
    SUSPEND;
  END

  TAG_NAME = 'movements::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
    SELECT DISTINCT M.GROUP_ID, M.PERSON_ID, M.DATE_IN, M.DATE_OUT
    FROM PERSON_MOVEMENTS M
    JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID IN (9, 187)
    JOIN CJ2_JOURNAL J ON J.GRADE_ID = M.GROUP_ID AND J.JOURNAL_TYPE IN (0, 1)
    WHERE M.DATE_DEL IS NULL
      AND M.DATE_IN >= DATEADD(-1 MONTH TO :V$YEAR_START)
      AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :V$YEAR_START)
      AND (:I$TIMEMARK IS NULL OR J.DATE_MODIFY >= :I$TIMEMARK)
    INTO :V$OBJ_ID, :V$TEACHER_ID, :V$D1, :V$D2
  DO
  BEGIN
    TAG_NAME = 'movements:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'movements:r:group_id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'movements:r:person_id';
    VAL = V$TEACHER_ID;
    SUSPEND;
    TAG_NAME = 'movements:r:date_from';
    VAL = (SELECT VAL FROM DATE2ISO(:V$D1, 0));
    SUSPEND;
    TAG_NAME = 'movements:r:date_to';
    VAL = (SELECT VAL FROM DATE2ISO(:V$D2, 0));
    SUSPEND;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SITELOAD_CONTENT (
    I$TYPE_ID BIGINT = NULL,
    I$OBJ_ID BIGINT = NULL)
RETURNS (
    OBJ_ID BIGINT,
    TYPE_ID BIGINT,
    SITE_URL VARCHAR(1000),
    TEMPLATE_ID BIGINT)
AS
begin

  FOR
    SELECT L514.OBJ_ID, V3520.LISTVAL_ID, V3521.BLOB_ID, V3522.VAL
    FROM LINKS L2
    JOIN LINKS L514 ON L514.PARENT_ID = L2.OBJ_ID AND L514.OBJ_TYPE_ID = 514 AND L514.DATE_DEL IS NULL AND (:I$OBJ_ID IS NULL OR L514.OBJ_ID = :I$OBJ_ID) -- конкретный preview
    JOIN VALL V3519 ON V3519.OBJ_ID = L514.OBJ_ID AND V3519.PARAM_ID = 3519 AND V3519.IS_DEL = 0 AND (V3519.LISTVAL_ID = 2 OR :I$OBJ_ID IS NOT NULL) -- только разрешенные, но для preview все
    JOIN VALL V3520 ON V3520.OBJ_ID = L514.OBJ_ID AND V3520.PARAM_ID = 3520 AND V3520.IS_DEL = 0 AND
      (V3520.LISTVAL_ID = :I$TYPE_ID OR (:I$TYPE_ID IS NULL AND V3520.LISTVAL_ID <> 18602)) -- кроме файлов вложений
    LEFT JOIN VALB V3521 ON V3521.OBJ_ID = L514.OBJ_ID AND V3521.PARAM_ID = 3521 AND V3521.IS_DEL = 0
    LEFT JOIN VALS V3522 ON V3522.OBJ_ID = L514.OBJ_ID AND V3522.PARAM_ID = 3522 AND V3522.IS_DEL = 0
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    ORDER BY 2
    INTO :OBJ_ID, :TYPE_ID, :TEMPLATE_ID, :SITE_URL
  DO
  BEGIN
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SITELOAD_DATA_18581 RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(4000))
AS
DECLARE VARIABLE V$OU_ID BIGINT;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE S1 VARCHAR(1000);
DECLARE VARIABLE S2 VARCHAR(1000);
DECLARE VARIABLE S3 VARCHAR(1000);
DECLARE VARIABLE S4 VARCHAR(1000);
DECLARE VARIABLE V$YEAR_ID BIGINT;
DECLARE VARIABLE V$YEAR VARCHAR(20);
DECLARE VARIABLE V$Y INTEGER;
DECLARE VARIABLE D1 DATE;
DECLARE VARIABLE D2 DATE;
DECLARE VARIABLE N BIGINT;
DECLARE VARIABLE V$LISTVAL_ID BIGINT;
DECLARE VARIABLE T1 TIME;
DECLARE VARIABLE T2 TIME;
DECLARE VARIABLE V$MAX BIGINT;
begin

  SELECT FIRST 1 L2.OBJ_ID, V1236.LISTVAL_ID, C.VAL
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  LEFT JOIN LISTVAL_TEXT(V1236.LISTVAL_ID) C ON 1 = 1
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$OU_ID, :V$YEAR_ID, :V$YEAR;

  TAG_NAME = 'Учебный_год';
  VAL = V$YEAR;
  V$Y = SUBSTRING(V$YEAR FROM 1 FOR 4);
  SUSPEND;

  TAG_NAME = 'НаименованиеОУ:Полное_наименование';
  VAL = NULL;
  SELECT V.VAL
  FROM VALS V
  WHERE V.OBJ_ID = :V$OU_ID AND V.PARAM_ID = 5 AND V.IS_DEL = 0
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'НаименованиеОУ:Сокращенное_наименование';
  VAL = NULL;
  SELECT V.VAL
  FROM VALS V
  WHERE V.OBJ_ID = :V$OU_ID AND V.PARAM_ID = 999 AND V.IS_DEL = 0
  INTO :VAL;
  IF(VAL IS NULL) THEN VAL = 'Сокращенное наименование отсутствует';
  SUSPEND;

  TAG_NAME = 'НаименованиеОУ:Сокращенное_наименование_КАИСКРО';
  VAL = NULL;
  SELECT V.VAL
  FROM VALS V
  WHERE V.OBJ_ID = :V$OU_ID AND V.PARAM_ID = 2 AND V.IS_DEL = 0
  INTO :VAL;
  SUSPEND;

  -- Год и дата открытия взаимоувязаны, сделаны оба чтобы можно было поиграться в шаблоне
  TAG_NAME = 'Дата_открытия';
  VAL = NULL;
  SELECT C.RESULT
  FROM VALD V
  LEFT JOIN DATE2STR(V.VAL) C ON 1 = 1
  WHERE V.OBJ_ID = :V$OU_ID AND V.PARAM_ID = 2187 AND V.IS_DEL = 0
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'Год_открытия';
  VAL = NULL;
  SELECT V.VAL
  FROM VALI V
  WHERE V.OBJ_ID = :V$OU_ID AND V.PARAM_ID = 2188 AND V.IS_DEL = 0
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'Учредители::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT V24.VAL, V3456.VAL, V25.VAL, V26.VAL
    FROM LINKS L5
    LEFT JOIN VALS V24 ON V24.OBJ_ID = L5.OBJ_ID AND V24.PARAM_ID = 24 AND V24.IS_DEL = 0
    LEFT JOIN VALS V3456 ON V3456.OBJ_ID = L5.OBJ_ID AND V3456.PARAM_ID = 3456 AND V3456.IS_DEL = 0
    LEFT JOIN VALS V25 ON V25.OBJ_ID = L5.OBJ_ID AND V25.PARAM_ID = 25 AND V25.IS_DEL = 0
    LEFT JOIN VALS V26 ON V26.OBJ_ID = L5.OBJ_ID AND V26.PARAM_ID = 26 AND V26.IS_DEL = 0
    WHERE L5.PARENT_ID = :V$OU_ID AND L5.OBJ_TYPE_ID = 5 AND L5.DATE_DEL IS NULL
    INTO :S1, :S2, :S3, :S4
  DO
  BEGIN
    TAG_NAME = 'Учредители:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'Учредители:r:Наименование';
    VAL = S1;
    SUSPEND;
    TAG_NAME = 'Учредители:r:ОГРН';
    VAL = S2;
    SUSPEND;
    TAG_NAME = 'Учредители:r:Адрес';
    VAL = S3;
    SUSPEND;
    TAG_NAME = 'Учредители:r:Телефон';
    VAL = S4;
    SUSPEND;
  END

  TAG_NAME = 'Местонахождение_ОУ';
  VAL = NULL;
  SELECT V.VAL
  FROM ADR_GET(27, :V$OU_ID) V
  INTO :VAL;
  SUSPEND;

  -- Выбираем только здания и подразделения, для которых прописан график
  TAG_NAME = 'Режим_работы::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT DISTINCT L16.OBJ_ID, C.CAPTION, A.VAL
    FROM LINKS L73
    JOIN LINKS L16 ON L16.PARENT_ID = L73.OBJ_ID AND L16.OBJ_TYPE_ID = 16 AND L16.DATE_DEL IS NULL
    JOIN LINKS L516 ON L516.PARENT_ID = L16.OBJ_ID AND L516.OBJ_TYPE_ID = 516 AND L516.DATE_DEL IS NULL
    LEFT JOIN OBJECT_CAPTION_GET(L16.OBJ_ID) C ON 1 = 1
    LEFT JOIN ADR_GET(420, L16.OBJ_ID) A ON 1 = 1
    WHERE L73.PARENT_ID = :V$OU_ID AND L73.OBJ_TYPE_ID = 73 AND L73.DATE_DEL IS NULL
    UNION
    SELECT DISTINCT L211.OBJ_ID, C.CAPTION, NULL
    FROM LINKS L211
    JOIN LINKS L516 ON L516.PARENT_ID = L211.OBJ_ID AND L516.OBJ_TYPE_ID = 516 AND L516.DATE_DEL IS NULL
    LEFT JOIN OBJECT_CAPTION_GET(L211.OBJ_ID) C ON 1 = 1
    WHERE L211.PARENT_ID = :V$OU_ID AND L211.OBJ_TYPE_ID = 211 AND L211.DATE_DEL IS NULL
    INTO :V$OBJ_ID, :S1, :S2
  DO
  BEGIN
    TAG_NAME = 'Режим_работы:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'Режим_работы:r:Наименование';
    VAL = S1;
    SUSPEND;
    TAG_NAME = 'Режим_работы:r:Адрес';
    VAL = S2;
    SUSPEND;
    TAG_NAME = 'Режим_работы:r:График::json&colon;array';
    VAL = 1;
    SUSPEND;
    -- Выбираем уникальные сочетания времени, сортируем в порядке возрастания дней недели
    V$MAX = 0;
    FOR
      SELECT MIN(V3530.LISTVAL_ID), MAX(V3530.LISTVAL_ID), V3531.VAL, V3532.VAL
      FROM LINKS L516
      JOIN VALL V3530 ON V3530.OBJ_ID = L516.OBJ_ID AND V3530.PARAM_ID = 3530 AND V3530.IS_DEL = 0
      LEFT JOIN LISTVAL_TEXT(V3530.LISTVAL_ID) C ON 1 = 1
      JOIN VALT V3531 ON V3531.OBJ_ID = L516.OBJ_ID AND V3531.PARAM_ID = 3531 AND V3531.IS_DEL = 0
      JOIN VALT V3532 ON V3532.OBJ_ID = L516.OBJ_ID AND V3532.PARAM_ID = 3532 AND V3532.IS_DEL = 0
      WHERE L516.PARENT_ID = :V$OBJ_ID AND L516.OBJ_TYPE_ID = 516 AND L516.DATE_DEL IS NULL
      GROUP BY 3, 4
      ORDER BY 1, 3
      INTO :V$LISTVAL_ID, :N, :T1, :T2
    DO
    BEGIN
      -- TODO: Дыры в рабочих днях в середине недели
      TAG_NAME = 'Режим_работы:r:График:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'Режим_работы:r:График:r:Дни';
      VAL = '';
      -- Конкретный день
      IF(N = V$LISTVAL_ID) THEN VAL = (SELECT VAL FROM LISTVAL_TEXT(:V$LISTVAL_ID));
      -- Два дня - через запятую
      ELSE IF(N = V$LISTVAL_ID + 1) THEN VAL = (SELECT VAL FROM LISTVAL_TEXT(:V$LISTVAL_ID)) || ', ' || (SELECT VAL FROM LISTVAL_TEXT(:N));
      -- Нескольк дней - через дефис
      ELSE VAL = (SELECT VAL FROM LISTVAL_TEXT(:V$LISTVAL_ID)) || '-' || (SELECT VAL FROM LISTVAL_TEXT(:N));
      SUSPEND;
      TAG_NAME = 'Режим_работы:r:График:r:Время_начала';
      VAL = T1;
      VAL = SUBSTRING(VAL FROM 1 FOR 5);
      SUSPEND;
      TAG_NAME = 'Режим_работы:r:График:r:Время_окончания';
      VAL = T2;
      VAL = SUBSTRING(VAL FROM 1 FOR 5);
      SUSPEND;
      -- Флаг обьединения ячеек, вдруг сделаем
      TAG_NAME = 'Режим_работы:r:График:r:span';
      VAL = 0;
      SUSPEND;
      V$MAX = N;
    END
    -- Выходные дни - берем все что после последнего указанного рабочего дня
    IF(V$MAX < 804) THEN
    BEGIN
      TAG_NAME = 'Режим_работы:r:График:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'Режим_работы:r:График:r:Дни';
      IF(V$MAX = 803) THEN VAL = 'Воскресенье';
      ELSE VAL = (SELECT VAL FROM LISTVAL_TEXT(:V$MAX + 1)) || '-Воскресенье';
      SUSPEND;
      TAG_NAME = 'Режим_работы:r:График:r:Время_начала';
      VAL = 'Не работает';
      SUSPEND;
      TAG_NAME = 'Режим_работы:r:График:r:Время_окончания';
      VAL = NULL;
      SUSPEND;
      -- Флаг обьединения ячеек, вдруг сделаем
      TAG_NAME = 'Режим_работы:r:График:r:span';
      VAL = 1;
      SUSPEND;
    END
  END

  TAG_NAME = 'График_работы::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L151.OBJ_ID, V1147.VAL, MIN(V1169.VAL), MAX(V1174.VAL)
    FROM LINKS L481
    JOIN VALL V3389 ON V3389.OBJ_ID = L481.OBJ_ID AND V3389.PARAM_ID = 3389 AND V3389.IS_DEL = 0 AND V3389.LISTVAL_ID = :V$YEAR_ID
    -- Периоды
    JOIN LINKS L151 ON L151.PARENT_ID = L481.OBJ_ID AND L151.OBJ_TYPE_ID = 151 AND L151.DATE_DEL IS NULL
    JOIN VALS V1147 ON V1147.OBJ_ID = L151.OBJ_ID AND V1147.PARAM_ID = 1147 AND V1147.IS_DEL = 0
    JOIN LINKS L154 ON L154.PARENT_ID = L151.OBJ_ID AND L154.OBJ_TYPE_ID = 154 AND L154.DATE_DEL IS NULL
    JOIN VALD V1169 ON V1169.OBJ_ID = L154.OBJ_ID AND V1169.PARAM_ID = 1169 AND V1169.IS_DEL = 0
    JOIN VALD V1174 ON V1174.OBJ_ID = L154.OBJ_ID AND V1174.PARAM_ID = 1174 AND V1174.IS_DEL = 0
    WHERE L481.PARENT_ID = :V$OU_ID AND L481.OBJ_TYPE_ID = 481 AND L481.DATE_DEL IS NULL
    GROUP BY 1, 2
    ORDER BY 2
    INTO :V$OBJ_ID, :S1, :D1, :D2
  DO
  BEGIN
    TAG_NAME = 'График_работы:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'График_работы:r:Наименование';
    VAL = S1;
    SUSPEND;
    -- Подбираем названия уровней образования, если пусто - поставим название периодов
    TAG_NAME = 'График_работы:r:Уровни_образования';
    VAL = '';
    FOR
      SELECT DISTINCT C.SORT_ORDER, C.CAPTION
      FROM LINKS L7
      JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
      JOIN VALR V3517 ON V3517.OBJ_ID = L9.OBJ_ID AND V3517.PARAM_ID = 3517 AND V3517.IS_DEL = 0 AND V3517.VAL = :V$OBJ_ID
      LEFT JOIN OBJECT_CAPTION_GET(L7.OBJ_ID) C ON 1 = 1
      WHERE L7.PARENT_ID = :V$OU_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
      ORDER BY 1
      INTO :N, :S2
    DO
    BEGIN
      IF(VAL <> '') THEN VAL = VAL || ', ';
      VAL = VAL || S2;
    END
    IF(VAL = '') THEN VAL = S1;
    SUSPEND;
    -- Подбираем варианты исходя из действующих учебных коллективов, которые ссылаются на это расписание
    TAG_NAME = 'График_работы:r:Учебная_неделя';
    VAL = '';
    FOR
      SELECT DISTINCT V551.LISTVAL_ID, C.VAL
      FROM LINKS L7
      JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
      JOIN VALR V3517 ON V3517.OBJ_ID = L9.OBJ_ID AND V3517.PARAM_ID = 3517 AND V3517.IS_DEL = 0 AND V3517.VAL = :V$OBJ_ID
      JOIN VALL V551 ON V551.OBJ_ID = L9.OBJ_ID AND V551.PARAM_ID = 551 AND V551.IS_DEL = 0
      LEFT JOIN LISTVAL_TEXT(V551.LISTVAL_ID) C ON 1 = 1
      WHERE L7.PARENT_ID = :V$OU_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
      ORDER BY 1
      INTO :N, :S1
    DO
    BEGIN
      IF(VAL <> '') THEN VAL = VAL || ', ';
      VAL = VAL || S1;
    END
    -- IF(VAL = '') THEN VAL = '-';
    SUSPEND;
    TAG_NAME = 'График_работы:r:Начало_года';
    VAL = (SELECT RESULT FROM DATE2STR(:D1));
    SUSPEND;
    TAG_NAME = 'График_работы:r:Конец_года';
    VAL = (SELECT RESULT FROM DATE2STR(:D2));
    SUSPEND;
  END

  -- Временно: Выводим все возможные каникулы из всех расписаний
  -- TODO: если набирается более 4 записей каникул (без учета дополнительных у 1 класса), то выводим с группировкой по расписаниям, как они введены
  TAG_NAME = 'Каникулы::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT DISTINCT V3263.VAL, V3264.VAL, V3265.VAL
    FROM LINKS L481
    JOIN VALL V3389 ON V3389.OBJ_ID = L481.OBJ_ID AND V3389.PARAM_ID = 3389 AND V3389.IS_DEL = 0 AND V3389.LISTVAL_ID = :V$YEAR_ID
    -- Периоды
    JOIN LINKS L151 ON L151.PARENT_ID = L481.OBJ_ID AND L151.OBJ_TYPE_ID = 151 AND L151.DATE_DEL IS NULL
    JOIN LINKS L450 ON L450.PARENT_ID = L151.OBJ_ID AND L450.OBJ_TYPE_ID = 450 AND L450.DATE_DEL IS NULL
    JOIN VALD V3263 ON V3263.OBJ_ID = L450.OBJ_ID AND V3263.PARAM_ID = 3263 AND V3263.IS_DEL = 0
    JOIN VALD V3264 ON V3264.OBJ_ID = L450.OBJ_ID AND V3264.PARAM_ID = 3264 AND V3264.IS_DEL = 0
    JOIN VALS V3265 ON V3265.OBJ_ID = L450.OBJ_ID AND V3265.PARAM_ID = 3265 AND V3265.IS_DEL = 0
    WHERE L481.PARENT_ID = :V$OU_ID AND L481.OBJ_TYPE_ID = 481 AND L481.DATE_DEL IS NULL
    ORDER BY 1
    INTO :D1, :D2, :S1
  DO
  BEGIN
    TAG_NAME = 'Каникулы:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'Каникулы:r:Дата_начала';
    VAL = (SELECT RESULT FROM DATE2STR(:D1));
    SUSPEND;
    TAG_NAME = 'Каникулы:r:Дата_окончания';
    VAL = (SELECT RESULT FROM DATE2STR(:D2));
    SUSPEND;
    TAG_NAME = 'Каникулы:r:Наименование';
    VAL = S1;
    SUSPEND;
    TAG_NAME = 'Каникулы:r:Длительность';
    VAL = DATEDIFF(DAY FROM D1 TO D2);
    SUSPEND;
  END

  -- Это двумерная таблица, строки = уровни образования, столбцы = варианты по видам ОП
  -- уровни образования берем из числа указанных для ОУ
  -- для текущего и будущего годов публикации
  TAG_NAME = 'Места_ОД::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT V3327.LISTVAL_ID, C.VAL
    FROM LINKS L472
    JOIN VALL V3327 ON V3327.OBJ_ID = L472.OBJ_ID AND V3327.PARAM_ID = 3327 AND V3327.IS_DEL = 0
    LEFT JOIN LISTVAL_TEXT(V3327.LISTVAL_ID) C ON 1 = 1
    WHERE L472.PARENT_ID = :V$OU_ID AND L472.OBJ_TYPE_ID = 472 AND L472.DATE_DEL IS NULL
    ORDER BY 1
    INTO :V$LISTVAL_ID, :S1
  DO
  BEGIN
    TAG_NAME = 'Места_ОД:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'Места_ОД:r:Уровень_образования';
    VAL = S1;
    SUSPEND;
    TAG_NAME = 'Места_ОД:r:Основная_ОП';
    VAL = 'нет';
    SELECT LIST(CAP, ', ')
    FROM (
      SELECT DISTINCT C.CAPTION || ' - ' || A.VAL CAP
      FROM LINKS L69
      JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
      -- текущий и будущие года
      JOIN VALI V3115 ON V3115.OBJ_ID = L57.OBJ_ID AND V3115.PARAM_ID = 3115 AND V3115.IS_DEL = 0 AND V3115.VAL >= :V$Y
      JOIN LINKS L16 ON L16.PARENT_ID = L57.OBJ_ID AND L16.OBJ_TYPE_ID = 16 AND L16.DATE_DEL IS NULL
      LEFT JOIN OBJECT_CAPTION_GET(L16.OBJ_ID) C ON 1 = 1
      LEFT JOIN ADR_GET(420, L16.OBJ_ID) A ON 1 = 1
      WHERE L69.PARENT_ID = :V$OU_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL
      ORDER BY L16.COST
    )
    INTO :VAL;
    SUSPEND;
    TAG_NAME = 'Места_ОД:r:Дополнительно';
    VAL = 'нет';
    SELECT LIST(CAP, ', ')
    FROM (
      SELECT DISTINCT V1892.VAL || COALESCE(' - ' || A.VAL, '') CAP
      FROM LINKS L69
      JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
      -- текущий и будущие года
      JOIN VALI V3115 ON V3115.OBJ_ID = L57.OBJ_ID AND V3115.PARAM_ID = 3115 AND V3115.IS_DEL = 0 AND V3115.VAL >= :V$Y
      JOIN LINKS L237 ON L237.PARENT_ID = L57.OBJ_ID AND L237.OBJ_TYPE_ID = 237 AND L237.DATE_DEL IS NULL
      JOIN VALS V1892 ON V1892.OBJ_ID = L237.OBJ_ID AND V1892.PARAM_ID = 1892 AND V1892.IS_DEL = 0
      LEFT JOIN ADR_GET(3528, L237.OBJ_ID) A ON 1 = 1
      WHERE L69.PARENT_ID = :V$OU_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL
      ORDER BY V1892.VAL
    )
    INTO :VAL;
    SUSPEND;
    TAG_NAME = 'Места_ОД:r:Практика';
    VAL = 'нет';
    SELECT LIST(CAP, ', ')
    FROM (
      SELECT DISTINCT V3535.VAL CAP
      FROM LINKS L69
      JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
      -- текущий и будущие года
      JOIN VALI V3115 ON V3115.OBJ_ID = L57.OBJ_ID AND V3115.PARAM_ID = 3115 AND V3115.IS_DEL = 0 AND V3115.VAL >= :V$Y
      JOIN LINKS L400 ON L400.PARENT_ID = L57.OBJ_ID AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL
      -- групповой УП
      JOIN VALL V3016 ON V3016.OBJ_ID = L400.OBJ_ID AND V3016.PARAM_ID = 3016 AND V3016.IS_DEL = 0 AND V3016.LISTVAL_ID = 5465
      JOIN VALS V3535 ON V3535.OBJ_ID = L400.OBJ_ID AND V3535.PARAM_ID = 3535 AND V3535.IS_DEL = 0
      WHERE L69.PARENT_ID = :V$OU_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL
      ORDER BY 1
    )
    INTO :VAL;
    SUSPEND;
    TAG_NAME = 'Места_ОД:r:Практическая_подготовка';
    VAL = 'нет';
    SELECT LIST(CAP, ', ')
    FROM (
      SELECT DISTINCT V3536.VAL CAP
      FROM LINKS L69
      JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
      -- текущий и будущие года
      JOIN VALI V3115 ON V3115.OBJ_ID = L57.OBJ_ID AND V3115.PARAM_ID = 3115 AND V3115.IS_DEL = 0 AND V3115.VAL >= :V$Y
      JOIN LINKS L400 ON L400.PARENT_ID = L57.OBJ_ID AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL
      -- групповой УП
      JOIN VALL V3016 ON V3016.OBJ_ID = L400.OBJ_ID AND V3016.PARAM_ID = 3016 AND V3016.IS_DEL = 0 AND V3016.LISTVAL_ID = 5465
      JOIN VALS V3536 ON V3536.OBJ_ID = L400.OBJ_ID AND V3536.PARAM_ID = 3536 AND V3536.IS_DEL = 0
      WHERE L69.PARENT_ID = :V$OU_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL
      ORDER BY 1
    )
    INTO :VAL;
    SUSPEND;
    TAG_NAME = 'Места_ОД:r:Государственная_аттестация';
    VAL = 'нет';
    SELECT LIST(CAP, ', ')
    FROM (
      SELECT DISTINCT V3537.VAL CAP
      FROM LINKS L69
      JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
      -- текущий и будущие года
      JOIN VALI V3115 ON V3115.OBJ_ID = L57.OBJ_ID AND V3115.PARAM_ID = 3115 AND V3115.IS_DEL = 0 AND V3115.VAL >= :V$Y
      JOIN LINKS L400 ON L400.PARENT_ID = L57.OBJ_ID AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL
      -- групповой УП
      JOIN VALL V3016 ON V3016.OBJ_ID = L400.OBJ_ID AND V3016.PARAM_ID = 3016 AND V3016.IS_DEL = 0 AND V3016.LISTVAL_ID = 5465
      JOIN VALS V3537 ON V3537.OBJ_ID = L400.OBJ_ID AND V3537.PARAM_ID = 3537 AND V3537.IS_DEL = 0
      WHERE L69.PARENT_ID = :V$OU_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL
      ORDER BY 1
    )
    INTO :VAL;
    SUSPEND;
  END

  TAG_NAME = 'Лицензия:Номер';
  VAL = NULL;
  S1 = NULL;
  S2 = NULL;
  SELECT FIRST 1 COALESCE(V479.SVAL || ' ', '') || V480.SVAL, D.RESULT, V481.VAL
  FROM LINKS L17
  JOIN VALL V471 ON V471.OBJ_ID = L17.OBJ_ID AND V471.PARAM_ID = 471 AND V471.IS_DEL = 0 AND V471.LISTVAL_ID IN (1052, 18624)
  JOIN VALL V613 ON V613.OBJ_ID = L17.OBJ_ID AND V613.PARAM_ID = 613 AND V613.IS_DEL = 0 AND V613.LISTVAL_ID IN (1982, 1984)
  LEFT JOIN VALS V479 ON V479.OBJ_ID = L17.OBJ_ID AND V479.PARAM_ID = 479 AND V479.IS_DEL = 0
  JOIN VALS V480 ON V480.OBJ_ID = L17.OBJ_ID AND V480.PARAM_ID = 480 AND V480.IS_DEL = 0
  JOIN VALD V482 ON V482.OBJ_ID = L17.OBJ_ID AND V482.PARAM_ID = 482 AND V482.IS_DEL = 0
  LEFT JOIN DATE2STR(V482.VAL) D ON 1 = 1
  -- Кем выдана
  LEFT JOIN VALS V481 ON V481.OBJ_ID = L17.OBJ_ID AND V481.PARAM_ID = 481 AND V481.IS_DEL = 0
  WHERE L17.PARENT_ID = :V$OU_ID AND L17.OBJ_TYPE_ID = 17 AND L17.DATE_DEL IS NULL
  INTO :VAL, :S1, :S2;
  SUSPEND;

  TAG_NAME = 'Лицензия:Дата';
  VAL = S1;
  SUSPEND;

  TAG_NAME = 'Лицензия:Сведения';
  VAL = S2;
  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SITELOAD_DATA_18582 RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(4000))
AS
DECLARE VARIABLE V$OU_ID BIGINT;
DECLARE VARIABLE S1 VARCHAR(1000);
DECLARE VARIABLE S2 VARCHAR(1000);
DECLARE VARIABLE S3 VARCHAR(1000);
DECLARE VARIABLE S4 VARCHAR(1000);
DECLARE VARIABLE S5 VARCHAR(1000);
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$LISTVAL_ID BIGINT;
DECLARE VARIABLE V$BLOB_ID BIGINT;
begin
  SELECT FIRST 1 L2.OBJ_ID
  FROM LINKS L2
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$OU_ID;

  TAG_NAME = 'Структура::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L211.OBJ_ID, V1791.VAL, V1793.LISTVAL_ID, JC.VAL, COALESCE(V3089.VAL, 'Отсутствует'), COALESCE(V3541.VAL, 'Отсутствует'), COALESCE(V3540.VAL, 'Отсутствует')
    FROM LINKS L211
    JOIN VALS V1791 ON V1791.OBJ_ID = L211.OBJ_ID AND V1791.PARAM_ID = 1791 AND V1791.IS_DEL = 0     -- наименование структурного подразделения
    LEFT JOIN VALL V1793 ON V1793.OBJ_ID = L211.OBJ_ID AND V1793.PARAM_ID = 1793 AND V1793.IS_DEL = 0-- должность руководителя подразделения
    LEFT JOIN LISTVAL_TEXT(V1793.LISTVAL_ID) JC ON 1 = 1
    LEFT JOIN VALS V3089 ON V3089.OBJ_ID = L211.OBJ_ID AND V3089.PARAM_ID = 3089 AND V3089.IS_DEL = 0-- электронная почта структурного подразделения
    LEFT JOIN VALS V3541 ON V3541.OBJ_ID = L211.OBJ_ID AND V3541.PARAM_ID = 3541 AND V3541.IS_DEL = 0-- сайт структурного подразделения
    LEFT JOIN VALS V3540 ON V3540.OBJ_ID = L211.OBJ_ID AND V3540.PARAM_ID = 3540 AND V3540.IS_DEL = 0-- адрес структурного подразделения
    WHERE L211.PARENT_ID = :V$OU_ID AND L211.OBJ_TYPE_ID = 211 AND L211.DATE_DEL IS NULL
    ORDER BY 2
    INTO :V$OBJ_ID, :S1, :V$LISTVAL_ID, :S2, :S3, :S4, :S5
  DO
  BEGIN
    TAG_NAME = 'Структура:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'Структура:r:Наименование';
    VAL = S1;
    SUSPEND;
    TAG_NAME = 'Структура:r:Должность_руководителя';
    VAL = S2;
    SUSPEND;
    TAG_NAME = 'Структура:r:Электронная_почта';
    VAL = S3;
    SUSPEND;
    TAG_NAME = 'Структура:r:Сайт';
    VAL = S4;
    SUSPEND;
    TAG_NAME = 'Структура:r:Адрес';
    VAL = S5;
    SUSPEND;

    TAG_NAME = 'Структура:r:Руководитель';
    VAL = NULL;
    SELECT C.C1
    FROM VALR V
    LEFT JOIN BUILD_REP_FIO(V.VAL, 59, 60, 61, 1) C ON 1 = 1
    WHERE OBJ_ID = :V$OBJ_ID AND PARAM_ID = 1794 AND IS_DEL = 0
    INTO :VAL;
    IF (VAL IS NULL) THEN
    BEGIN
      -- Выбираем актуального руководителя подразделения в порядке приоритета
      SELECT FIRST 1 C.C1
      FROM LINKS L13
      JOIN VALL V58 ON V58.OBJ_ID = L13.OBJ_ID AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0 AND V58.LISTVAL_ID = :V$LISTVAL_ID
      JOIN LINKS L15 ON L15.PARENT_ID = L13.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
      LEFT JOIN VALS V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
      JOIN LINKS LP14 ON LP14.OBJ_ID = L15.OBJ_ID AND LP14.PARENT_TYPE_ID = 14 AND LP14.DATE_DEL IS NULL
      LEFT JOIN BUILD_REP_FIO(LP14.PARENT_ID, 59, 60, 61, 1) C ON 1 = 1
      WHERE L13.PARENT_ID = :V$OBJ_ID AND L13.OBJ_TYPE_ID = 13 AND L13.DATE_DEL IS NULL AND V74.VAL IS NULL
      INTO :VAL;
      IF (VAL IS NULL) THEN
      BEGIN
        VAL = 'Отсутствует';
      END
    END
    SUSPEND;

    VAL = NULL;
    SELECT FIRST 1 V478.VAL, V478.BLOB_ID
    FROM VALR V
    JOIN VALB V478 ON V478.OBJ_ID = V.VAL AND V478.PARAM_ID = 478 AND V478.IS_DEL = 0
    WHERE V.OBJ_ID = :V$OBJ_ID AND V.PARAM_ID = 3564 AND V.IS_DEL = 0
    INTO :VAL, :V$BLOB_ID;
    IF (VAL IS NOT NULL) THEN
    BEGIN
      TAG_NAME = 'Структура:r:Нормативный_документ:file_name';
      VAL = VAL;
      SUSPEND;
      TAG_NAME = 'Структура:r:Нормативный_документ:blob_id';
      VAL = V$BLOB_ID;
      SUSPEND;
      TAG_NAME = 'Структура:r:Нормативный_документ:Имеется';
      VAL = 1;
      SUSPEND;
    END
    ELSE
    BEGIN
      TAG_NAME = 'Структура:r:Нормативный_документ:Имеется';
      VAL = 0;
      SUSPEND;
    END

    --nnn Органы управления ОО
  /*  TAG_NAME = 'Структура:r:Органы_управления::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT V3561.VAL, V478.VAL, V478.BLOB_ID
      FROM LINKS L529
      JOIN VALS V3561 ON V3561.OBJ_ID = L529.OBJ_ID AND V3561.PARAM_ID = 3561 AND V3561.IS_DEL = 0
      JOIN VALR V3562 ON V3562.OBJ_ID = L529.OBJ_ID AND V3562.PARAM_ID = 3562 AND V3562.IS_DEL = 0
      JOIN VALB V478 ON V478.OBJ_ID = V3562.VAL AND V478.PARAM_ID = 478 AND V478.IS_DEL = 0
      WHERE L529.OBJ_TYPE_ID = 529 AND L529.PARENT_ID = :V$OU_ID AND L529.DATE_DEL IS NULL
      INTO :VAL, :V$BLOB_ID;
    DO
    BEGIN
      TAG_NAME = 'Структура:Органы_управления:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'Структура:Органы_управления:r:Название';
      VAL = V$BLOB_ID;
      SUSPEND;
      TAG_NAME = 'Структура:Органы_управления:r:Нормативный_акт:Имеется';
      VAL = 1;
      SUSPEND;
    END
    */
  END

  TAG_NAME = 'Объекты_инфраструктуры::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT V3406.VAL
    FROM LINKS L73
    JOIN LINKS L492 ON L492.PARENT_ID = L73.OBJ_ID AND L492.OBJ_TYPE_ID = 492 AND L492.DATE_DEL IS NULL
    JOIN VALS V3406 ON V3406.OBJ_ID = L492.OBJ_ID AND V3406.PARAM_ID = 3406 AND V3406.IS_DEL = 0
    WHERE L73.PARENT_ID = :V$OU_ID AND L73.OBJ_TYPE_ID = 73 AND L73.DATE_DEL IS NULL
    ORDER BY L492.OBJ_ID
    INTO :S1
  DO
  BEGIN
    TAG_NAME = 'Объекты_инфраструктуры:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'Объекты_инфраструктуры:r:Наименование';
    VAL = S1;
    SUSPEND;
  END
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SITELOAD_DATA_18583 RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(4000))
AS
DECLARE VARIABLE V$OU_ID BIGINT;
DECLARE VARIABLE V$ID BIGINT;
DECLARE VARIABLE S1 VARCHAR(1000);
DECLARE VARIABLE S2 VARCHAR(1000);
DECLARE VARIABLE BLOB_ID BIGINT;
DECLARE VARIABLE S4 VARCHAR(1000);
DECLARE VARIABLE CBLOB_ID BIGINT;
DECLARE VARIABLE V$STR VARCHAR(1000);
begin

  SELECT FIRST 1 L2.OBJ_ID
  FROM LINKS L2
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$OU_ID;

  --Основной блок
  --Основные_документы:r образовательной организации
  TAG_NAME = 'Основные_документы::json&colon;array';
  VAL = 1;
  SUSPEND;

  V$ID = NULL;
  SELECT FIRST 1 L17.OBJ_ID, V596.VAL, V478.VAL, V478.BLOB_ID, V3503.VAL, V3503.BLOB_ID
  FROM LINKS L17
  JOIN VALL V613 ON V613.OBJ_ID = L17.OBJ_ID AND V613.PARAM_ID = 613 AND V613.IS_DEL = 0 AND V613.LISTVAL_ID = 1982 -- действующий
  JOIN VALL V471 ON V471.OBJ_ID = L17.OBJ_ID AND V471.PARAM_ID = 471 AND V471.IS_DEL = 0 AND V471.LISTVAL_ID = 1047 -- Устав
  JOIN VALD V482 ON V482.OBJ_ID = L17.OBJ_ID AND V482.PARAM_ID = 482 AND V482.IS_DEL = 0                            -- дата выдачи
  JOIN VALS V596 ON V596.OBJ_ID = L17.OBJ_ID AND V596.PARAM_ID = 596 AND V596.IS_DEL = 0                            -- название
  JOIN VALB V478 ON V478.OBJ_ID = L17.OBJ_ID AND V478.PARAM_ID = 478 AND V478.IS_DEL = 0                            -- файл
  LEFT JOIN VALB V3503 ON V3503.OBJ_ID = L17.OBJ_ID AND V3503.PARAM_ID = 3503 AND V3503.IS_DEL = 0                  -- файл ЦП
  WHERE L17.PARENT_ID = :V$OU_ID AND L17.OBJ_TYPE_ID = 17 AND L17.DATE_DEL IS NULL
  ORDER BY V482.VAL DESC
  INTO :V$ID, :S1, :S2, :BLOB_ID, :S4, :CBLOB_ID;
  -- Файл
  IF (V$ID IS NOT NULL) THEN
  BEGIN
    TAG_NAME = 'Основные_документы:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'Основные_документы:r:docname';
    VAL = S1;
    SUSPEND;
    TAG_NAME = 'Основные_документы:r:file_name';
    VAL = S2;
    SUSPEND;
    TAG_NAME = 'Основные_документы:r:blob_id';
    VAL = BLOB_ID;
    SUSPEND;
    -- Файл с ЭЦП
    TAG_NAME = 'Основные_документы:r:ЭЦП:file_name';
    VAL = S4;
    SUSPEND;
    TAG_NAME = 'Основные_документы:r:ЭЦП:blob_src';
    VAL = BLOB_ID;
    SUSPEND;
    TAG_NAME = 'Основные_документы:r:ЭЦП:blob_id';
    VAL = CBLOB_ID;
    SUSPEND;
  END

  --Правила внутреннего распорядка обучающихся и Правила внутреннего трудового распорядка
  FOR
    SELECT L17.OBJ_ID, V596.VAL, V478.VAL, V478.BLOB_ID, V3503.VAL, V3503.BLOB_ID
    FROM LINKS L17
    JOIN VALL V613 ON V613.OBJ_ID = L17.OBJ_ID AND V613.PARAM_ID = 613 AND V613.IS_DEL = 0 AND V613.LISTVAL_ID = 1982             -- действующий
    JOIN VALL V471 ON V471.OBJ_ID = L17.OBJ_ID AND V471.PARAM_ID = 471 AND V471.IS_DEL = 0 AND V471.LISTVAL_ID IN (18635, 18627)  -- Локальный нормативный акт или положение
    JOIN VALD V482 ON V482.OBJ_ID = L17.OBJ_ID AND V482.PARAM_ID = 482 AND V482.IS_DEL = 0                                        -- дата выдачи
    JOIN VALS V596 ON V596.OBJ_ID = L17.OBJ_ID AND V596.PARAM_ID = 596 AND V596.IS_DEL = 0                                        -- название
    JOIN VALB V478 ON V478.OBJ_ID = L17.OBJ_ID AND V478.PARAM_ID = 478 AND V478.IS_DEL = 0                                        -- файл
    LEFT JOIN VALB V3503 ON V3503.OBJ_ID = L17.OBJ_ID AND V3503.PARAM_ID = 3503 AND V3503.IS_DEL = 0                              -- файл ЦП
    WHERE L17.PARENT_ID = :V$OU_ID AND L17.OBJ_TYPE_ID = 17 AND L17.DATE_DEL IS NULL
      AND V596.VAL CONTAINING 'равил' AND V596.VAL CONTAINING 'внутрен' AND V596.VAL CONTAINING 'поряд'
    ORDER BY V482.VAL DESC
    INTO :V$ID, :S1, :S2, :BLOB_ID, :S4, :CBLOB_ID
  DO
  BEGIN
    TAG_NAME = 'Основные_документы:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'Основные_документы:r:docname';
    VAL = S1;
    SUSPEND;
    TAG_NAME = 'Основные_документы:r:file_name';
    VAL = S2;
    SUSPEND;
    TAG_NAME = 'Основные_документы:r:blob_id';
    VAL = BLOB_ID;
    SUSPEND;
    TAG_NAME = 'Основные_документы:r:ЭЦП:file_name';
    VAL = S4;
    SUSPEND;
    TAG_NAME = 'Основные_документы:r:ЭЦП:blob_src';
    VAL = BLOB_ID;
    SUSPEND;
    TAG_NAME = 'Основные_документы:r:ЭЦП:blob_id';
    VAL = CBLOB_ID;
    SUSPEND;
    V$STR = IIF(V$STR IS NULL, V$ID, V$STR || ',' || V$ID);
  END

  -- Коллективный договор
  V$ID = NULL;
  SELECT FIRST 1 L17.OBJ_ID, V596.VAL, V478.VAL, V478.BLOB_ID, V3503.VAL, V3503.BLOB_ID
  FROM LINKS L17
  JOIN VALL V613 ON V613.OBJ_ID = L17.OBJ_ID AND V613.PARAM_ID = 613 AND V613.IS_DEL = 0 AND V613.LISTVAL_ID = 1982  -- действующий
  JOIN VALL V471 ON V471.OBJ_ID = L17.OBJ_ID AND V471.PARAM_ID = 471 AND V471.IS_DEL = 0 AND V471.LISTVAL_ID = 18631 -- Коллективный договор
  JOIN VALD V482 ON V482.OBJ_ID = L17.OBJ_ID AND V482.PARAM_ID = 482 AND V482.IS_DEL = 0                             -- дата выдачи
  JOIN VALS V596 ON V596.OBJ_ID = L17.OBJ_ID AND V596.PARAM_ID = 596 AND V596.IS_DEL = 0                             -- название
  JOIN VALB V478 ON V478.OBJ_ID = L17.OBJ_ID AND V478.PARAM_ID = 478 AND V478.IS_DEL = 0                             -- файл
  LEFT JOIN VALB V3503 ON V3503.OBJ_ID = L17.OBJ_ID AND V3503.PARAM_ID = 3503 AND V3503.IS_DEL = 0                   -- файл ЦП
  WHERE L17.PARENT_ID = :V$OU_ID AND L17.OBJ_TYPE_ID = 17 AND L17.DATE_DEL IS NULL
  ORDER BY V482.VAL DESC
  INTO :V$ID, :S1, :S2, :BLOB_ID, :S4, :CBLOB_ID;
  -- Файл
  IF (V$ID IS NOT NULL) THEN
  BEGIN
    TAG_NAME = 'Основные_документы:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'Основные_документы:r:docname';
    VAL = S1;
    SUSPEND;
    TAG_NAME = 'Основные_документы:r:file_name';
    VAL = S2;
    SUSPEND;
    TAG_NAME = 'Основные_документы:r:blob_id';
    VAL = BLOB_ID;
    SUSPEND;
    -- Файл с ЭЦП
    TAG_NAME = 'Основные_документы:r:ЭЦП:file_name';
    VAL = S4;
    SUSPEND;
    TAG_NAME = 'Основные_документы:r:ЭЦП:blob_src';
    VAL = BLOB_ID;
    SUSPEND;
    TAG_NAME = 'Основные_документы:r:ЭЦП:blob_id';
    VAL = CBLOB_ID;
    SUSPEND;
  END

  --Отчет о самообследовании образовательной организации
  FOR
    SELECT V596.VAL, V478.VAL, V478.BLOB_ID, V3503.VAL, V3503.BLOB_ID
    FROM LINKS L17
    JOIN VALL V613 ON V613.OBJ_ID = L17.OBJ_ID AND V613.PARAM_ID = 613 AND V613.IS_DEL = 0 AND V613.LISTVAL_ID = 1982             -- действующий
    JOIN VALL V471 ON V471.OBJ_ID = L17.OBJ_ID AND V471.PARAM_ID = 471 AND V471.IS_DEL = 0 AND V471.LISTVAL_ID = 18628            -- отчет
    JOIN VALD V482 ON V482.OBJ_ID = L17.OBJ_ID AND V482.PARAM_ID = 482 AND V482.IS_DEL = 0                                        -- дата выдачи
    JOIN VALS V596 ON V596.OBJ_ID = L17.OBJ_ID AND V596.PARAM_ID = 596 AND V596.IS_DEL = 0                                        -- название
    JOIN VALB V478 ON V478.OBJ_ID = L17.OBJ_ID AND V478.PARAM_ID = 478 AND V478.IS_DEL = 0                                        -- файл
    LEFT JOIN VALB V3503 ON V3503.OBJ_ID = L17.OBJ_ID AND V3503.PARAM_ID = 3503 AND V3503.IS_DEL = 0                              -- файл ЦП
    WHERE L17.PARENT_ID = :V$OU_ID AND L17.OBJ_TYPE_ID = 17 AND L17.DATE_DEL IS NULL
    ORDER BY V482.VAL DESC
    INTO :S1, :S2, :BLOB_ID, :S4, :CBLOB_ID
  DO
  BEGIN
    TAG_NAME = 'Основные_документы:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'Основные_документы:r:docname';
    VAL = S1;
    SUSPEND;
    TAG_NAME = 'Основные_документы:r:file_name';
    VAL = S2;
    SUSPEND;
    TAG_NAME = 'Основные_документы:r:blob_id';
    VAL = BLOB_ID;
    SUSPEND;
    TAG_NAME = 'Основные_документы:r:ЭЦП:file_name';
    VAL = S4;
    SUSPEND;
    TAG_NAME = 'Основные_документы:r:ЭЦП:blob_src';
    VAL = BLOB_ID;
    SUSPEND;
    TAG_NAME = 'Основные_документы:r:ЭЦП:blob_id';
    VAL = CBLOB_ID;
    SUSPEND;
  END

  -- Локальные акты образовательной организации  по основным вопросам организации и осуществления образовательной деятельности
  -- Режим занятий обучающихся
  -- Прием обучающихся
  -- Порядок и основания перевода, отчисления и восстановления обучающихся
  -- Текущий контроль успеваемости и промежуточная аттестация обучающихся: формы, периодичность и порядок
  TAG_NAME = 'Локальные_акты::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L17.OBJ_ID, V596.VAL, V478.VAL, V478.BLOB_ID, V3503.VAL, V3503.BLOB_ID
    FROM LINKS L17
    JOIN VALL V613 ON V613.OBJ_ID = L17.OBJ_ID AND V613.PARAM_ID = 613 AND V613.IS_DEL = 0 AND V613.LISTVAL_ID = 1982 -- действующий
    JOIN VALL V471 ON V471.OBJ_ID = L17.OBJ_ID AND V471.PARAM_ID = 471 AND V471.IS_DEL = 0 AND V471.LISTVAL_ID IN (18635, 18627)  -- Локальный нормативный акт или положение
    JOIN VALD V482 ON V482.OBJ_ID = L17.OBJ_ID AND V482.PARAM_ID = 482 AND V482.IS_DEL = 0                                        -- дата выдачи
    JOIN VALS V596 ON V596.OBJ_ID = L17.OBJ_ID AND V596.PARAM_ID = 596 AND V596.IS_DEL = 0                                        -- название
    JOIN VALB V478 ON V478.OBJ_ID = L17.OBJ_ID AND V478.PARAM_ID = 478 AND V478.IS_DEL = 0                                        -- файл
    LEFT JOIN VALB V3503 ON V3503.OBJ_ID = L17.OBJ_ID AND V3503.PARAM_ID = 3503 AND V3503.IS_DEL = 0                              -- файл ЦП
    WHERE L17.PARENT_ID = :V$OU_ID AND L17.OBJ_TYPE_ID = 17 AND L17.DATE_DEL IS NULL
      AND V596.VAL CONTAINING 'обучающ' AND
      -- !!! тут надо однозначно что-то сделать, иначе мы вытащим слишком много лишних документов с такими многозначными условиями
      (V596.VAL CONTAINING 'рием' OR V596.VAL CONTAINING 'риём' OR V596.VAL CONTAINING 'оряд' OR V596.VAL CONTAINING 'режим'
       OR V596.VAL CONTAINING 'положен' OR V596.VAL CONTAINING 'контрол')
    ORDER BY V482.VAL DESC
    INTO :V$ID, :S1, :S2, :BLOB_ID, :S4, :CBLOB_ID
  DO
  BEGIN
    TAG_NAME = 'Локальные_акты:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'Локальные_акты:r:docname';
    VAL = S1;
    SUSPEND;
    TAG_NAME = 'Локальные_акты:r:file_name';
    VAL = S2;
    SUSPEND;
    TAG_NAME = 'Локальные_акты:r:blob_id';
    VAL = BLOB_ID;
    SUSPEND;
    TAG_NAME = 'Локальные_акты:r:ЭЦП:file_name';
    VAL = S4;
    SUSPEND;
    TAG_NAME = 'Локальные_акты:r:ЭЦП:blob_src';
    VAL = BLOB_ID;
    SUSPEND;
    TAG_NAME = 'Локальные_акты:r:ЭЦП:blob_id';
    VAL = CBLOB_ID;
    SUSPEND;
    V$STR = IIF(V$STR IS NULL, V$ID, V$STR || ',' || V$ID);
  END

  -- Положения об органах управления и структурных подразделениях. Сюда выводим все положения, кроме тех, что были выведены выше
  TAG_NAME = 'Положения::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT V596.VAL, V478.VAL, V478.BLOB_ID, V3503.VAL, V3503.BLOB_ID
    FROM LINKS L17
    JOIN VALL V613 ON V613.OBJ_ID = L17.OBJ_ID AND V613.PARAM_ID = 613 AND V613.IS_DEL = 0 AND V613.LISTVAL_ID = 1982             -- действующий
    JOIN VALL V471 ON V471.OBJ_ID = L17.OBJ_ID AND V471.PARAM_ID = 471 AND V471.IS_DEL = 0 AND V471.LISTVAL_ID = 18635            -- Положение
    JOIN VALD V482 ON V482.OBJ_ID = L17.OBJ_ID AND V482.PARAM_ID = 482 AND V482.IS_DEL = 0                                        -- дата выдачи
    JOIN VALS V596 ON V596.OBJ_ID = L17.OBJ_ID AND V596.PARAM_ID = 596 AND V596.IS_DEL = 0                                        -- название
    JOIN VALB V478 ON V478.OBJ_ID = L17.OBJ_ID AND V478.PARAM_ID = 478 AND V478.IS_DEL = 0                                        -- файл
    LEFT JOIN VALB V3503 ON V3503.OBJ_ID = L17.OBJ_ID AND V3503.PARAM_ID = 3503 AND V3503.IS_DEL = 0                              -- файл ЦП
    WHERE L17.PARENT_ID = :V$OU_ID AND L17.OBJ_TYPE_ID = 17 AND L17.DATE_DEL IS NULL
      AND L17.OBJ_ID NOT IN (SELECT ID FROM STR_TO_ID_LIST(:V$STR))
    ORDER BY V482.VAL DESC
    INTO :S1, :S2, :BLOB_ID, :S4, :CBLOB_ID
  DO
  BEGIN
    TAG_NAME = 'Положения:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'Положения:r:docname';
    VAL = S1;
    SUSPEND;
    TAG_NAME = 'Положения:r:file_name';
    VAL = S2;
    SUSPEND;
    TAG_NAME = 'Положения:r:blob_id';
    VAL = BLOB_ID;
    SUSPEND;
    TAG_NAME = 'Положения:r:ЭЦП:file_name';
    VAL = S4;
    SUSPEND;
    TAG_NAME = 'Положения:r:ЭЦП:blob_src';
    VAL = BLOB_ID;
    SUSPEND;
    TAG_NAME = 'Положения:r:ЭЦП:blob_id';
    VAL = CBLOB_ID;
    SUSPEND;
  END

  -- Предписания органов, осуществляющих государственный контроль (надзор) в сфере образования. Список предписаний со статусом «действующий»
  -- Предписания об органах управления и структурных подразделениях. Сюда выводим все Предписания, кроме тех, что были выведены выше
  TAG_NAME = 'Предписания::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT V596.VAL, V478.VAL, V478.BLOB_ID, V3503.VAL, V3503.BLOB_ID
    FROM LINKS L17
    JOIN VALL V613 ON V613.OBJ_ID = L17.OBJ_ID AND V613.PARAM_ID = 613 AND V613.IS_DEL = 0 AND V613.LISTVAL_ID = 1982             -- действующий
    JOIN VALL V471 ON V471.OBJ_ID = L17.OBJ_ID AND V471.PARAM_ID = 471 AND V471.IS_DEL = 0 AND V471.LISTVAL_ID IN (18629, 18630)  -- Предписания от органов и отчет об исполнении предписания
    JOIN VALD V482 ON V482.OBJ_ID = L17.OBJ_ID AND V482.PARAM_ID = 482 AND V482.IS_DEL = 0                                        -- дата выдачи
    JOIN VALS V596 ON V596.OBJ_ID = L17.OBJ_ID AND V596.PARAM_ID = 596 AND V596.IS_DEL = 0                                        -- название
    JOIN VALB V478 ON V478.OBJ_ID = L17.OBJ_ID AND V478.PARAM_ID = 478 AND V478.IS_DEL = 0                                        -- файл
    LEFT JOIN VALB V3503 ON V3503.OBJ_ID = L17.OBJ_ID AND V3503.PARAM_ID = 3503 AND V3503.IS_DEL = 0                              -- файл ЦП
    WHERE L17.PARENT_ID = :V$OU_ID AND L17.OBJ_TYPE_ID = 17 AND L17.DATE_DEL IS NULL
      AND L17.OBJ_ID NOT IN (SELECT ID FROM STR_TO_ID_LIST(:V$STR))
    ORDER BY V482.VAL DESC
    INTO :S1, :S2, :BLOB_ID, :S4, :CBLOB_ID
  DO
  BEGIN
    TAG_NAME = 'Предписания:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'Предписания:r:docname';
    VAL = S1;
    SUSPEND;
    TAG_NAME = 'Предписания:r:file_name';
    VAL = S2;
    SUSPEND;
    TAG_NAME = 'Предписания:r:blob_id';
    VAL = BLOB_ID;
    SUSPEND;
    TAG_NAME = 'Предписания:r:ЭЦП:file_name';
    VAL = S4;
    SUSPEND;
    TAG_NAME = 'Предписания:r:ЭЦП:blob_src';
    VAL = BLOB_ID;
    SUSPEND;
    TAG_NAME = 'Предписания:r:ЭЦП:blob_id';
    VAL = CBLOB_ID;
    SUSPEND;
  END
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SITELOAD_DATA_18584 RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(4000))
AS
DECLARE VARIABLE V$OU_ID BIGINT;
DECLARE VARIABLE V$Y INTEGER;
DECLARE VARIABLE V$OP_ID BIGINT;
DECLARE VARIABLE S1 VARCHAR(1000);
DECLARE VARIABLE S2 VARCHAR(1000);
DECLARE VARIABLE S3 VARCHAR(1000);
DECLARE VARIABLE S4 VARCHAR(1000);
DECLARE VARIABLE S5 VARCHAR(400);
DECLARE VARIABLE S6 VARCHAR(400);
DECLARE VARIABLE BLOB_ID BIGINT;
DECLARE VARIABLE CBLOB_ID BIGINT;
DECLARE VARIABLE V$LANG_FILE VARCHAR(400);
DECLARE VARIABLE V$LANG_CFILE VARCHAR(400);
DECLARE VARIABLE V$LANG_ID BIGINT;
DECLARE VARIABLE V$LANG_CID BIGINT;
DECLARE VARIABLE V$LEVEL_ID BIGINT;
begin

  SELECT FIRST 1 L2.OBJ_ID, LV.COST
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$OU_ID, :V$Y;

  -- Идем циклом по всем разделам ОП по видам образования, где есть утвержденные УП
  -- с годом опубликования = текущий

  -- Сведения о языке загружаем из общего файла в составе документов
  SELECT FIRST 1 V478.VAL, V478.BLOB_ID, V3503.VAL, V3503.BLOB_ID
  FROM LINKS L17
  JOIN VALL V471 ON V471.OBJ_ID = L17.OBJ_ID AND V471.PARAM_ID = 471 AND V471.IS_DEL = 0 AND V471.LISTVAL_ID = 18640
  JOIN VALB V478 ON V478.OBJ_ID = L17.OBJ_ID AND V478.PARAM_ID = 478 AND V478.IS_DEL = 0
  LEFT JOIN VALB V3503 ON V3503.OBJ_ID = L17.OBJ_ID AND V3503.PARAM_ID = 3503 AND V3503.IS_DEL = 0
  WHERE L17.PARENT_ID = :V$OU_ID AND L17.OBJ_TYPE_ID = 17 AND L17.DATE_DEL IS NULL
  INTO :V$LANG_FILE, :V$LANG_ID, :V$LANG_CFILE, :V$LANG_CID;

  TAG_NAME = 'ДОО::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT DISTINCT L57.OBJ_ID, C.CAPTION, COALESCE(V399.SVAL, 'Не указано'), V3565.VAL, V3565.BLOB_ID, V3566.VAL, V3566.BLOB_ID
    FROM LINKS L69
    JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
    JOIN VALI V3115 ON V3115.OBJ_ID = L57.OBJ_ID AND V3115.PARAM_ID = 3115 AND V3115.IS_DEL = 0 AND V3115.VAL = :V$Y
    JOIN VALL V1594 ON V1594.OBJ_ID = L57.OBJ_ID AND V1594.PARAM_ID = 1594 AND V1594.IS_DEL = 0 AND V1594.LISTVAL_ID = 5337
    LEFT JOIN OBJECT_CAPTION_GET(L57.OBJ_ID) C ON 1 = 1
    LEFT JOIN VALS V399 ON V399.OBJ_ID = L57.OBJ_ID AND V399.PARAM_ID = 399 AND V399.IS_DEL = 0
    LEFT JOIN VALB V3565 ON V3565.OBJ_ID = L57.OBJ_ID AND V3565.PARAM_ID = 3565 AND V3565.IS_DEL = 0
    LEFT JOIN VALB V3566 ON V3566.OBJ_ID = L57.OBJ_ID AND V3566.PARAM_ID = 3566 AND V3566.IS_DEL = 0
    WHERE L69.PARENT_ID = :V$OU_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL
    ORDER BY 2
    INTO :V$OP_ID, :S1, :S2, :S3, :BLOB_ID, :S4, :CBLOB_ID
  DO
  BEGIN
    TAG_NAME = 'ДОО:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'ДОО:r:Наименование_программы';
    VAL = S1;
    SUSPEND;
    TAG_NAME = 'ДОО:r:Нормативный_срок_обучения';
    VAL = S2;
    SUSPEND;
    TAG_NAME = 'ДОО:r:Образовательная_программа:file_name';
    VAL = S3;
    SUSPEND;
    TAG_NAME = 'ДОО:r:Образовательная_программа:blob_id';
    VAL = BLOB_ID;
    SUSPEND;
    TAG_NAME = 'ДОО:r:Образовательная_программа:ЭЦП:file_name';
    VAL = S4;
    SUSPEND;
    TAG_NAME = 'ДОО:r:Образовательная_программа:ЭЦП:blob_src';
    VAL = BLOB_ID;
    SUSPEND;
    TAG_NAME = 'ДОО:r:Образовательная_программа:ЭЦП:blob_id';
    VAL = CBLOB_ID;
    SUSPEND;
    TAG_NAME = 'ДОО:r:Язык_преподавания:file_name';
    VAL = V$LANG_FILE;
    SUSPEND;
    TAG_NAME = 'ДОО:r:Язык_преподавания:blob_id';
    VAL = V$LANG_ID;
    SUSPEND;
    TAG_NAME = 'ДОО:r:Язык_преподавания:ЭЦП:file_name';
    VAL = V$LANG_CFILE;
    SUSPEND;
    TAG_NAME = 'ДОО:r:Язык_преподавания:ЭЦП:blob_src';
    VAL = V$LANG_ID;
    SUSPEND;
    TAG_NAME = 'ДОО:r:Язык_преподавания:ЭЦП:blob_id';
    VAL = V$LANG_CID;
    SUSPEND;
    TAG_NAME = 'ДОО:Численность_обучающихся::json&colon;array';
    VAL = 1;
    SUSPEND;
    -- Тут общая численность
    TAG_NAME = 'ДОО:r:Численность_обучающихся:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'ДОО:r:Численность_обучающихся:r:Этап';
    VAL = 'Всего';
    SUSPEND;
    TAG_NAME = 'ДОО:r:Численность_обучающихся:r:Количество';
    SELECT COUNT(*)
    FROM PERSON_MOVEMENTS M
    WHERE M.DATE_DEL IS NULL AND M.GROUP_TYPE_ID = 9 AND M.DATE_OUT IS NULL AND M.LEVEL_ID IN (3263, 3264)
    INTO :VAL;
    SUSPEND;
    TAG_NAME = 'ДОО:r:Численность_обучающихся:r:Количество_иностранцев';
    SELECT COUNT(*)
    FROM PERSON_MOVEMENTS M
    JOIN VALL V91 ON V91.OBJ_ID = M.PERSON_ID AND V91.PARAM_ID = 91 AND V91.IS_DEL = 0 AND V91.LISTVAL_ID <> 1515 AND M.LEVEL_ID IN (3263, 3264)
    WHERE M.DATE_DEL IS NULL AND M.GROUP_TYPE_ID = 9 AND M.DATE_OUT IS NULL
    INTO :VAL;
    SUSPEND;
  END

  -- Разные варианты по формам обучения выдаем как разные ОП
  TAG_NAME = 'ОО::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT DISTINCT L57.OBJ_ID, C.CAPTION, COALESCE(V399.SVAL, 'Не указано'), V3565.VAL, V3565.BLOB_ID, V3566.VAL, V3566.BLOB_ID,
      CL.VAL, COALESCE(C3015.VAL, 'Нет данных')
    FROM LINKS L69
    JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
    JOIN VALI V3115 ON V3115.OBJ_ID = L57.OBJ_ID AND V3115.PARAM_ID = 3115 AND V3115.IS_DEL = 0 AND V3115.VAL = :V$Y
    JOIN VALL V1594 ON V1594.OBJ_ID = L57.OBJ_ID AND V1594.PARAM_ID = 1594 AND V1594.IS_DEL = 0 AND V1594.LISTVAL_ID IN (5339, 5341, 5343)
    LEFT JOIN LISTVAL_TEXT(V1594.LISTVAL_ID) CL ON 1 = 1
    LEFT JOIN OBJECT_CAPTION_GET(L57.OBJ_ID) C ON 1 = 1
    LEFT JOIN VALS V399 ON V399.OBJ_ID = L57.OBJ_ID AND V399.PARAM_ID = 399 AND V399.IS_DEL = 0
    LEFT JOIN VALB V3565 ON V3565.OBJ_ID = L57.OBJ_ID AND V3565.PARAM_ID = 3565 AND V3565.IS_DEL = 0
    LEFT JOIN VALB V3566 ON V3566.OBJ_ID = L57.OBJ_ID AND V3566.PARAM_ID = 3566 AND V3566.IS_DEL = 0
    -- Остальное добираем по УП
    JOIN LINKS L400 ON L400.PARENT_ID = L57.OBJ_ID AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL
    JOIN VALL V3022 ON V3022.OBJ_ID = L400.OBJ_ID AND V3022.PARAM_ID = 3022 AND V3022.IS_DEL = 0 AND V3022.LISTVAL_ID = 3
    JOIN VALL V3013 ON V3013.OBJ_ID = L400.OBJ_ID AND V3013.PARAM_ID = 3013 AND V3013.IS_DEL = 0 AND V3013.LISTVAL_ID = 11715
    JOIN VALL V3015 ON V3015.OBJ_ID = L400.OBJ_ID AND V3015.PARAM_ID = 3015 AND V3015.IS_DEL = 0
    LEFT JOIN LISTVAL_TEXT(V3015.LISTVAL_ID) C3015 ON 1 = 1
    WHERE L69.PARENT_ID = :V$OU_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL
    ORDER BY V1594.LISTVAL_ID, 2, V3015.LISTVAL_ID
    INTO :V$OP_ID, :S1, :S2, :S3, :BLOB_ID, :S4, :CBLOB_ID, :S5, :S6
  DO
  BEGIN
    TAG_NAME = 'ОО:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'ОО:r:Уровень_образования';
    VAL = S5;
    SUSPEND;
    TAG_NAME = 'ОО:r:Форма_обучения';
    VAL = S6;
    SUSPEND;
    TAG_NAME = 'ОО:r:Наименование_программы';
    VAL = S1;
    SUSPEND;
    TAG_NAME = 'ОО:r:Нормативный_срок_обучения';
    VAL = S2;
    SUSPEND;
    TAG_NAME = 'ОО:r:Образовательная_программа:file_name';
    VAL = S3;
    SUSPEND;
    TAG_NAME = 'ОО:r:Образовательная_программа:blob_id';
    VAL = BLOB_ID;
    SUSPEND;
    TAG_NAME = 'ОО:r:Образовательная_программа:ЭЦП:file_name';
    VAL = S4;
    SUSPEND;
    TAG_NAME = 'ОО:r:Образовательная_программа:ЭЦП:blob_src';
    VAL = BLOB_ID;
    SUSPEND;
    TAG_NAME = 'ОО:r:Образовательная_программа:ЭЦП:blob_id';
    VAL = CBLOB_ID;
    SUSPEND;
    TAG_NAME = 'ОО:r:Язык_преподавания:file_name';
    VAL = V$LANG_FILE;
    SUSPEND;
    TAG_NAME = 'ОО:r:Язык_преподавания:blob_id';
    VAL = V$LANG_ID;
    SUSPEND;
    TAG_NAME = 'ОО:r:Язык_преподавания:ЭЦП:file_name';
    VAL = V$LANG_CFILE;
    SUSPEND;
    TAG_NAME = 'ОО:r:Язык_преподавания:ЭЦП:blob_src';
    VAL = V$LANG_ID;
    SUSPEND;
    TAG_NAME = 'ОО:r:Язык_преподавания:ЭЦП:blob_id';
    VAL = V$LANG_CID;
    SUSPEND;
    TAG_NAME = 'ОО:Численность_обучающихся::json&colon;array';
    VAL = 1;
    SUSPEND;
    -- Численность по уровням
    FOR
      SELECT DISTINCT M.LEVEL_ID
      FROM PERSON_MOVEMENTS M
      WHERE M.DATE_DEL IS NULL AND M.GROUP_TYPE_ID = 9 AND M.DATE_OUT IS NULL AND M.LEVEL_ID IN (22, 26, 27)
      ORDER BY 1
      INTO :V$LEVEL_ID
    DO
    BEGIN
      TAG_NAME = 'ОО:r:Численность_обучающихся:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'ОО:r:Численность_обучающихся:r:Этап';
      VAL = (SELECT VAL FROM LISTVAL_TEXT(:V$LEVEL_ID));
      SUSPEND;
      TAG_NAME = 'ОО:r:Численность_обучающихся:r:Количество';
      SELECT COUNT(*)
      FROM PERSON_MOVEMENTS M
      WHERE M.DATE_DEL IS NULL AND M.GROUP_TYPE_ID = 9 AND M.DATE_OUT IS NULL AND M.LEVEL_ID = :V$LEVEL_ID
      INTO :VAL;
      SUSPEND;
      TAG_NAME = 'ОО:r:Численность_обучающихся:r:Количество_иностранцев';
      SELECT COUNT(*)
      FROM PERSON_MOVEMENTS M
      JOIN VALL V91 ON V91.OBJ_ID = M.PERSON_ID AND V91.PARAM_ID = 91 AND V91.IS_DEL = 0 AND V91.LISTVAL_ID <> 1515
      WHERE M.DATE_DEL IS NULL AND M.GROUP_TYPE_ID = 9 AND M.DATE_OUT IS NULL AND M.LEVEL_ID = :V$LEVEL_ID
      INTO :VAL;
      SUSPEND;
    END
    -- Тут общая численность
    TAG_NAME = 'ОО:r:Численность_обучающихся:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'ОО:r:Численность_обучающихся:r:Этап';
    VAL = 'Всего';
    SUSPEND;
    TAG_NAME = 'ОО:r:Численность_обучающихся:r:Количество';
    SELECT COUNT(*)
    FROM PERSON_MOVEMENTS M
    WHERE M.DATE_DEL IS NULL AND M.GROUP_TYPE_ID = 9 AND M.DATE_OUT IS NULL
    INTO :VAL;
    SUSPEND;
    TAG_NAME = 'ОО:r:Численность_обучающихся:r:Количество_иностранцев';
    SELECT COUNT(*)
    FROM PERSON_MOVEMENTS M
    JOIN VALL V91 ON V91.OBJ_ID = M.PERSON_ID AND V91.PARAM_ID = 91 AND V91.IS_DEL = 0 AND V91.LISTVAL_ID <> 1515
    WHERE M.DATE_DEL IS NULL AND M.GROUP_TYPE_ID = 9 AND M.DATE_OUT IS NULL
    INTO :VAL;
    SUSPEND;
  END

  TAG_NAME = 'СПО::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT DISTINCT L57.OBJ_ID, C.CAPTION, COALESCE(V399.SVAL, 'Не указано'), V3565.VAL, V3565.BLOB_ID, V3566.VAL, V3566.BLOB_ID
    FROM LINKS L69
    JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
    JOIN VALI V3115 ON V3115.OBJ_ID = L57.OBJ_ID AND V3115.PARAM_ID = 3115 AND V3115.IS_DEL = 0 AND V3115.VAL = :V$Y
    JOIN VALL V1594 ON V1594.OBJ_ID = L57.OBJ_ID AND V1594.PARAM_ID = 1594 AND V1594.IS_DEL = 0 AND V1594.LISTVAL_ID = 5346
    LEFT JOIN OBJECT_CAPTION_GET(L57.OBJ_ID) C ON 1 = 1
    LEFT JOIN VALS V399 ON V399.OBJ_ID = L57.OBJ_ID AND V399.PARAM_ID = 399 AND V399.IS_DEL = 0
    LEFT JOIN VALB V3565 ON V3565.OBJ_ID = L57.OBJ_ID AND V3565.PARAM_ID = 3565 AND V3565.IS_DEL = 0
    LEFT JOIN VALB V3566 ON V3566.OBJ_ID = L57.OBJ_ID AND V3566.PARAM_ID = 3566 AND V3566.IS_DEL = 0
    -- Остальное добираем по УП
    JOIN LINKS L400 ON L400.PARENT_ID = L57.OBJ_ID AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL
    JOIN VALL V3013 ON V3013.OBJ_ID = L400.OBJ_ID AND V3013.PARAM_ID = 3013 AND V3013.IS_DEL = 0 AND V3013.LISTVAL_ID = 11715
    JOIN VALL V3015 ON V3015.OBJ_ID = L400.OBJ_ID AND V3015.PARAM_ID = 3015 AND V3015.IS_DEL = 0
    LEFT JOIN LISTVAL_TEXT(V3015.LISTVAL_ID) C3015 ON 1 = 1
    WHERE L69.PARENT_ID = :V$OU_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL
    ORDER BY 2
    INTO :V$OP_ID, :S1, :S2, :S3, :BLOB_ID, :S4, :CBLOB_ID
  DO
  BEGIN
    TAG_NAME = 'СПО:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'СПО:r:Наименование_программы';
    VAL = S1;
    SUSPEND;
    TAG_NAME = 'СПО:r:Нормативный_срок_обучения';
    VAL = S2;
    SUSPEND;
    TAG_NAME = 'СПО:r:Код_профессии_специальности';
    VAL = 'Не указан';
    SELECT FIRST 1 V3476.VAL
    FROM VALS V3476
    WHERE V3476.OBJ_ID = :V$OP_ID AND V3476.PARAM_ID = 3476 AND V3476.IS_DEL = 0
    INTO :VAL;
    SUSPEND;
    TAG_NAME = 'СПО:r:Наименование_профессии_специальности';
    VAL = 'Не указано';
    SELECT FIRST 1 V.VAL
    FROM VALS V
    WHERE V.OBJ_ID = :V$OP_ID AND V.PARAM_ID IN (3473, 3474, 3475) AND V.IS_DEL = 0
    INTO :VAL;
    SUSPEND;
    TAG_NAME = 'СПО:r:Образовательная_программа:file_name';
    VAL = S3;
    SUSPEND;
    TAG_NAME = 'СПО:r:Образовательная_программа:blob_id';
    VAL = BLOB_ID;
    SUSPEND;
    TAG_NAME = 'СПО:r:Образовательная_программа:ЭЦП:file_name';
    VAL = S4;
    SUSPEND;
    TAG_NAME = 'СПО:r:Образовательная_программа:ЭЦП:blob_src';
    VAL = BLOB_ID;
    SUSPEND;
    TAG_NAME = 'СПО:r:Образовательная_программа:ЭЦП:blob_id';
    VAL = CBLOB_ID;
    SUSPEND;
    TAG_NAME = 'СПО:r:Язык_преподавания:file_name';
    VAL = V$LANG_FILE;
    SUSPEND;
    TAG_NAME = 'СПО:r:Язык_преподавания:blob_id';
    VAL = V$LANG_ID;
    SUSPEND;
    TAG_NAME = 'СПО:r:Язык_преподавания:ЭЦП:file_name';
    VAL = V$LANG_CFILE;
    SUSPEND;
    TAG_NAME = 'СПО:r:Язык_преподавания:ЭЦП:blob_src';
    VAL = V$LANG_ID;
    SUSPEND;
    TAG_NAME = 'СПО:r:Язык_преподавания:ЭЦП:blob_id';
    VAL = V$LANG_CID;
    SUSPEND;
    -- Тут общая численность
    TAG_NAME = 'СПО:Численность_обучающихся::json&colon;array';
    VAL = 1;
    SUSPEND;
    TAG_NAME = 'СПО:r:Численность_обучающихся:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'СПО:r:Численность_обучающихся:r:Этап';
    VAL = 'Всего';
    SUSPEND;
    TAG_NAME = 'СПО:r:Численность_обучающихся:r:Количество';
    SELECT COUNT(*)
    FROM PERSON_MOVEMENTS M
    WHERE M.DATE_DEL IS NULL AND M.GROUP_TYPE_ID = 9 AND M.DATE_OUT IS NULL AND M.LEVEL_ID = 28
    INTO :VAL;
    SUSPEND;
    TAG_NAME = 'СПО:r:Численность_обучающихся:r:Количество_иностранцев';
    SELECT COUNT(*)
    FROM PERSON_MOVEMENTS M
    JOIN VALL V91 ON V91.OBJ_ID = M.PERSON_ID AND V91.PARAM_ID = 91 AND V91.IS_DEL = 0 AND V91.LISTVAL_ID <> 1515 AND M.LEVEL_ID = 28
    WHERE M.DATE_DEL IS NULL AND M.GROUP_TYPE_ID = 9 AND M.DATE_OUT IS NULL
    INTO :VAL;
    SUSPEND;
  END

  TAG_NAME = 'ПО::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT DISTINCT L57.OBJ_ID, C.CAPTION, COALESCE(V399.SVAL, 'Не указано'), V3565.VAL, V3565.BLOB_ID, V3566.VAL, V3566.BLOB_ID,
      C3015.VAL
    FROM LINKS L69
    JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
    JOIN VALI V3115 ON V3115.OBJ_ID = L57.OBJ_ID AND V3115.PARAM_ID = 3115 AND V3115.IS_DEL = 0 AND V3115.VAL = :V$Y
    JOIN VALL V1594 ON V1594.OBJ_ID = L57.OBJ_ID AND V1594.PARAM_ID = 1594 AND V1594.IS_DEL = 0 AND V1594.LISTVAL_ID = 5364
    LEFT JOIN OBJECT_CAPTION_GET(L57.OBJ_ID) C ON 1 = 1
    LEFT JOIN VALS V399 ON V399.OBJ_ID = L57.OBJ_ID AND V399.PARAM_ID = 399 AND V399.IS_DEL = 0
    LEFT JOIN VALB V3565 ON V3565.OBJ_ID = L57.OBJ_ID AND V3565.PARAM_ID = 3565 AND V3565.IS_DEL = 0
    LEFT JOIN VALB V3566 ON V3566.OBJ_ID = L57.OBJ_ID AND V3566.PARAM_ID = 3566 AND V3566.IS_DEL = 0
    -- Остальное добираем по УП
    JOIN LINKS L400 ON L400.PARENT_ID = L57.OBJ_ID AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL
    JOIN VALL V3013 ON V3013.OBJ_ID = L400.OBJ_ID AND V3013.PARAM_ID = 3013 AND V3013.IS_DEL = 0 AND V3013.LISTVAL_ID = 11715
    JOIN VALL V3015 ON V3015.OBJ_ID = L400.OBJ_ID AND V3015.PARAM_ID = 3015 AND V3015.IS_DEL = 0
    LEFT JOIN LISTVAL_TEXT(V3015.LISTVAL_ID) C3015 ON 1 = 1
    WHERE L69.PARENT_ID = :V$OU_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL
    ORDER BY 2, V3015.LISTVAL_ID
    INTO :V$OP_ID, :S1, :S2, :S3, :BLOB_ID, :S4, :CBLOB_ID, :S6
  DO
  BEGIN
    TAG_NAME = 'ПО:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'ПО:r:Наименование_программы';
    VAL = S1;
    SUSPEND;
    TAG_NAME = 'ПО:r:Нормативный_срок_обучения';
    VAL = S2;
    SUSPEND;
    TAG_NAME = 'ПО:r:Форма_обучения';
    VAL = S6;
    SUSPEND;
    TAG_NAME = 'ПО:r:Код_профессии_специальности';
    VAL = 'Не указан';
    SELECT FIRST 1 V3476.VAL
    FROM VALS V3476
    WHERE V3476.OBJ_ID = :V$OP_ID AND V3476.PARAM_ID = 3476 AND V3476.IS_DEL = 0
    INTO :VAL;
    SUSPEND;
    TAG_NAME = 'ПО:r:Наименование_профессии_специальности';
    VAL = 'Не указано';
    SELECT FIRST 1 V.VAL
    FROM VALS V
    WHERE V.OBJ_ID = :V$OP_ID AND V.PARAM_ID IN (3473, 3474, 3475) AND V.IS_DEL = 0
    INTO :VAL;
    SUSPEND;
    TAG_NAME = 'ПО:r:Образовательная_программа:file_name';
    VAL = S3;
    SUSPEND;
    TAG_NAME = 'ПО:r:Образовательная_программа:blob_id';
    VAL = BLOB_ID;
    SUSPEND;
    TAG_NAME = 'ПО:r:Образовательная_программа:ЭЦП:file_name';
    VAL = S4;
    SUSPEND;
    TAG_NAME = 'ПО:r:Образовательная_программа:ЭЦП:blob_src';
    VAL = BLOB_ID;
    SUSPEND;
    TAG_NAME = 'ПО:r:Образовательная_программа:ЭЦП:blob_id';
    VAL = CBLOB_ID;
    SUSPEND;
    TAG_NAME = 'ПО:r:Язык_преподавания:file_name';
    VAL = V$LANG_FILE;
    SUSPEND;
    TAG_NAME = 'ПО:r:Язык_преподавания:blob_id';
    VAL = V$LANG_ID;
    SUSPEND;
    TAG_NAME = 'ПО:r:Язык_преподавания:ЭЦП:file_name';
    VAL = V$LANG_CFILE;
    SUSPEND;
    TAG_NAME = 'ПО:r:Язык_преподавания:ЭЦП:blob_src';
    VAL = V$LANG_ID;
    SUSPEND;
    TAG_NAME = 'ПО:r:Язык_преподавания:ЭЦП:blob_id';
    VAL = V$LANG_CID;
    SUSPEND;
    -- Тут общая численность
    TAG_NAME = 'ПО:Численность_обучающихся::json&colon;array';
    VAL = 1;
    SUSPEND;
    TAG_NAME = 'ПО:r:Численность_обучающихся:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'ПО:r:Численность_обучающихся:r:Этап';
    VAL = 'Всего';
    SUSPEND;
    TAG_NAME = 'ПО:r:Численность_обучающихся:r:Количество';
    SELECT COUNT(*)
    FROM PERSON_MOVEMENTS M
    WHERE M.DATE_DEL IS NULL AND M.GROUP_TYPE_ID = 9 AND M.DATE_OUT IS NULL AND M.LEVEL_ID = 13129
    INTO :VAL;
    SUSPEND;
    TAG_NAME = 'ПО:r:Численность_обучающихся:r:Количество_иностранцев';
    SELECT COUNT(*)
    FROM PERSON_MOVEMENTS M
    JOIN VALL V91 ON V91.OBJ_ID = M.PERSON_ID AND V91.PARAM_ID = 91 AND V91.IS_DEL = 0 AND V91.LISTVAL_ID <> 1515 AND M.LEVEL_ID = 13129
    WHERE M.DATE_DEL IS NULL AND M.GROUP_TYPE_ID = 9 AND M.DATE_OUT IS NULL
    INTO :VAL;
    SUSPEND;
  END

  TAG_NAME = 'ДО::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT DISTINCT L57.OBJ_ID, C.CAPTION, COALESCE(V399.SVAL, 'Не указано'), V3565.VAL, V3565.BLOB_ID, V3566.VAL, V3566.BLOB_ID,
      C3015.VAL
    FROM LINKS L69
    JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
    JOIN VALI V3115 ON V3115.OBJ_ID = L57.OBJ_ID AND V3115.PARAM_ID = 3115 AND V3115.IS_DEL = 0 AND V3115.VAL = :V$Y
    JOIN VALL V1594 ON V1594.OBJ_ID = L57.OBJ_ID AND V1594.PARAM_ID = 1594 AND V1594.IS_DEL = 0 AND V1594.LISTVAL_ID = 5358
    LEFT JOIN OBJECT_CAPTION_GET(L57.OBJ_ID) C ON 1 = 1
    LEFT JOIN VALS V399 ON V399.OBJ_ID = L57.OBJ_ID AND V399.PARAM_ID = 399 AND V399.IS_DEL = 0
    LEFT JOIN VALB V3565 ON V3565.OBJ_ID = L57.OBJ_ID AND V3565.PARAM_ID = 3565 AND V3565.IS_DEL = 0
    LEFT JOIN VALB V3566 ON V3566.OBJ_ID = L57.OBJ_ID AND V3566.PARAM_ID = 3566 AND V3566.IS_DEL = 0
    -- Остальное добираем по УП
    JOIN LINKS L400 ON L400.PARENT_ID = L57.OBJ_ID AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL
    JOIN VALL V3013 ON V3013.OBJ_ID = L400.OBJ_ID AND V3013.PARAM_ID = 3013 AND V3013.IS_DEL = 0 AND V3013.LISTVAL_ID = 11715
    JOIN VALL V3015 ON V3015.OBJ_ID = L400.OBJ_ID AND V3015.PARAM_ID = 3015 AND V3015.IS_DEL = 0
    LEFT JOIN LISTVAL_TEXT(V3015.LISTVAL_ID) C3015 ON 1 = 1
    WHERE L69.PARENT_ID = :V$OU_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL
    ORDER BY 2, V3015.LISTVAL_ID
    INTO :V$OP_ID, :S1, :S2, :S3, :BLOB_ID, :S4, :CBLOB_ID, :S6
  DO
  BEGIN
    TAG_NAME = 'ДО:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'ДО:r:Наименование_программы';
    VAL = S1;
    SUSPEND;
    TAG_NAME = 'ДО:r:Нормативный_срок_обучения';
    VAL = S2;
    SUSPEND;
    TAG_NAME = 'ДО:r:Форма_обучения';
    VAL = S6;
    SUSPEND;
    TAG_NAME = 'ДО:r:Образовательная_программа:file_name';
    VAL = S3;
    SUSPEND;
    TAG_NAME = 'ДО:r:Образовательная_программа:blob_id';
    VAL = BLOB_ID;
    SUSPEND;
    TAG_NAME = 'ДО:r:Образовательная_программа:ЭЦП:file_name';
    VAL = S4;
    SUSPEND;
    TAG_NAME = 'ДО:r:Образовательная_программа:ЭЦП:blob_src';
    VAL = BLOB_ID;
    SUSPEND;
    TAG_NAME = 'ДО:r:Образовательная_программа:ЭЦП:blob_id';
    VAL = CBLOB_ID;
    SUSPEND;
    TAG_NAME = 'ДО:r:Язык_преподавания:file_name';
    VAL = V$LANG_FILE;
    SUSPEND;
    TAG_NAME = 'ДО:r:Язык_преподавания:blob_id';
    VAL = V$LANG_ID;
    SUSPEND;
    TAG_NAME = 'ДО:r:Язык_преподавания:ЭЦП:file_name';
    VAL = V$LANG_CFILE;
    SUSPEND;
    TAG_NAME = 'ДО:r:Язык_преподавания:ЭЦП:blob_src';
    VAL = V$LANG_ID;
    SUSPEND;
    TAG_NAME = 'ДО:r:Язык_преподавания:ЭЦП:blob_id';
    VAL = V$LANG_CID;
    SUSPEND;
    -- Тут общая численность
    TAG_NAME = 'ДО:Численность_обучающихся::json&colon;array';
    VAL = 1;
    SUSPEND;
    TAG_NAME = 'ДО:r:Численность_обучающихся:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'ДО:r:Численность_обучающихся:r:Этап';
    VAL = 'Всего';
    SUSPEND;
    TAG_NAME = 'ДО:r:Численность_обучающихся:r:Количество';
    /*SELECT COUNT(*)
    FROM PERSON_MOVEMENTS M
    WHERE M.DATE_DEL IS NULL AND M.GROUP_TYPE_ID = 9 AND M.DATE_OUT IS NULL AND M.LEVEL_ID = 13129
    INTO :VAL;*/
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'ДО:r:Численность_обучающихся:r:Количество_иностранцев';
    /*SELECT COUNT(*)
    FROM PERSON_MOVEMENTS M
    JOIN VALL V91 ON V91.OBJ_ID = M.PERSON_ID AND V91.PARAM_ID = 91 AND V91.IS_DEL = 0 AND V91.LISTVAL_ID <> 1515 AND M.LEVEL_ID = 13129
    WHERE M.DATE_DEL IS NULL AND M.GROUP_TYPE_ID = 9 AND M.DATE_OUT IS NULL
    INTO :VAL;*/
    VAL = NULL;
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SITELOAD_DATA_18585 RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(4000))
AS
DECLARE VARIABLE V$OU_ID BIGINT;
DECLARE VARIABLE V$Y INTEGER;
DECLARE VARIABLE S1 VARCHAR(1000);
DECLARE VARIABLE S2 VARCHAR(1000);
DECLARE VARIABLE S3 VARCHAR(1000);
DECLARE VARIABLE S4 VARCHAR(1000);
begin

  SELECT FIRST 1 L2.OBJ_ID, LV.COST
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$OU_ID, :V$Y;

  TAG_NAME = 'Ссылки::json&colon;array';
  VAL = 1;
  SUSPEND;

  -- Есть ли ДОО ?
  IF(EXISTS(
    SELECT FIRST 1 1
    FROM LINKS L69
    JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
    JOIN VALI V3115 ON V3115.OBJ_ID = L57.OBJ_ID AND V3115.PARAM_ID = 3115 AND V3115.IS_DEL = 0 AND V3115.VAL = :V$Y
    JOIN VALL V1594 ON V1594.OBJ_ID = L57.OBJ_ID AND V1594.PARAM_ID = 1594 AND V1594.IS_DEL = 0 AND V1594.LISTVAL_ID = 5337
    WHERE L69.PARENT_ID = :V$OU_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL
  ))
  THEN
  BEGIN
    TAG_NAME = 'Ссылки:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'Ссылки:r:Наименование';
    VAL = 'Федеральный Государственный Стандарт Дошкольного образования';
    SUSPEND;
    TAG_NAME = 'Ссылки:r:Документ';
    VAL = 'Приказ Минобрнауки России от 17 октября 2013 г. № 1155 «Об утверждении федерального государственного образовательного стандарта дошкольного образования»';
    SUSPEND;
    TAG_NAME = 'Ссылки:r:Ссылка';
    VAL = 'https://docs.edu.gov.ru/document/a72db92c851c9f9c33d52d482420b477/';
    SUSPEND;
  END

  -- Есть ли НОО ?
  IF(EXISTS(
    SELECT FIRST 1 1
    FROM LINKS L69
    JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
    JOIN VALI V3115 ON V3115.OBJ_ID = L57.OBJ_ID AND V3115.PARAM_ID = 3115 AND V3115.IS_DEL = 0 AND V3115.VAL = :V$Y
    JOIN VALL V1594 ON V1594.OBJ_ID = L57.OBJ_ID AND V1594.PARAM_ID = 1594 AND V1594.IS_DEL = 0 AND V1594.LISTVAL_ID = 5339
    WHERE L69.PARENT_ID = :V$OU_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL
  ))
  THEN
  BEGIN
    TAG_NAME = 'Ссылки:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'Ссылки:r:Наименование';
    VAL = 'Федеральный Государственный Стандарт Начального общего образования';
    SUSPEND;
    TAG_NAME = 'Ссылки:r:Документ';
    VAL = 'Приказ Минпросвещения России от 18 июля 2022 г. № 569 «О внесении изменений в федеральный государственный образовательный стандарт начального общего образования, утвержденный приказом Минпросвещения России от 31 мая 2021 г. № 286»';
    SUSPEND;
    TAG_NAME = 'Ссылки:r:Ссылка';
    VAL = 'https://docs.edu.gov.ru/document/41aedd0ec72e8203218ea85d0c518ad5/';
    SUSPEND;
  END

  -- Есть ли ООО ?
  IF(EXISTS(
    SELECT FIRST 1 1
    FROM LINKS L69
    JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
    JOIN VALI V3115 ON V3115.OBJ_ID = L57.OBJ_ID AND V3115.PARAM_ID = 3115 AND V3115.IS_DEL = 0 AND V3115.VAL = :V$Y
    JOIN VALL V1594 ON V1594.OBJ_ID = L57.OBJ_ID AND V1594.PARAM_ID = 1594 AND V1594.IS_DEL = 0 AND V1594.LISTVAL_ID = 5341
    WHERE L69.PARENT_ID = :V$OU_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL
  ))
  THEN
  BEGIN
    TAG_NAME = 'Ссылки:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'Ссылки:r:Наименование';
    VAL = 'Федеральный Государственный Стандарт Основного общего образования';
    SUSPEND;
    TAG_NAME = 'Ссылки:r:Документ';
    VAL = 'Приказ Минпросвещения России от 18 июля 2022 г. № 568 «О внесении изменений в федеральный государственный образовательный стандарт основного общего образования, утвержденный приказом Минпросвещения России от 31 мая 2021 г. № 287»';
    SUSPEND;
    TAG_NAME = 'Ссылки:r:Ссылка';
    VAL = 'https://docs.edu.gov.ru/document/3a8149c34cdc83e75c444be77a4c791a/';
    SUSPEND;
  END

  -- Есть ли СОО ?
  IF(EXISTS(
    SELECT FIRST 1 1
    FROM LINKS L69
    JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
    JOIN VALI V3115 ON V3115.OBJ_ID = L57.OBJ_ID AND V3115.PARAM_ID = 3115 AND V3115.IS_DEL = 0 AND V3115.VAL = :V$Y
    JOIN VALL V1594 ON V1594.OBJ_ID = L57.OBJ_ID AND V1594.PARAM_ID = 1594 AND V1594.IS_DEL = 0 AND V1594.LISTVAL_ID = 5343
    WHERE L69.PARENT_ID = :V$OU_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL
  ))
  THEN
  BEGIN
    TAG_NAME = 'Ссылки:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'Ссылки:r:Наименование';
    VAL = 'Федеральный Государственный Стандарт Среднего общего образования';
    SUSPEND;
    TAG_NAME = 'Ссылки:r:Документ';
    VAL = 'Приказ Минобрнауки России от 17 мая 2012 г. № 413 «Об утверждении федерального государственного образовательного стандарта среднего общего образования»';
    SUSPEND;
    TAG_NAME = 'Ссылки:r:Ссылка';
    VAL = 'https://docs.edu.gov.ru/document/bf0ceabdc94110049a583890956abbfa/';
    SUSPEND;
  END

  -- Есть ли СПО ?

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SITELOAD_DATA_18586 RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(4000))
AS
DECLARE VARIABLE V$ID BIGINT;
DECLARE VARIABLE S1 VARCHAR(1000);
DECLARE VARIABLE V$BLOB_ID BIGINT;
DECLARE VARIABLE V$MAIN VARCHAR(1000);
begin
  -- Руководство
  TAG_NAME = 'Руководство::json&colon;array';
  VAL = 1;
  SUSPEND;

  FOR
    SELECT DISTINCT OBJ_ID
    FROM (
      SELECT L14.OBJ_ID
      FROM LINKS L14
      JOIN VALL V274 ON V274.OBJ_ID = L14.OBJ_ID AND V274.PARAM_ID = 274 AND V274.IS_DEL = 0 AND V274.LISTVAL_ID = 602        -- работающий сотрудник
      JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
      LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0                                  -- дата увольнения
      JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
      JOIN VALL V58 ON V58.OBJ_ID = LP13.PARENT_ID AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0                                   -- должность из списка
      JOIN LISTVALS LV58 ON LV58.LISTVAL_ID = V58.LISTVAL_ID AND (LV58.TAG IN ('R1', 'R2') OR LV58."FILTER" IN ('R1', 'R2'))  -- руководители 1-ого и 2-ого звена
      WHERE L14.OBJ_TYPE_ID = 14 and L14.PARENT_TYPE_ID IN (2, 211) AND L14.DATE_DEL IS NULL AND V74.VAL IS NULL
      ORDER BY LV58.TAG, LV58."FILTER"
    )
    INTO :V$ID
  DO
  BEGIN
    TAG_NAME = 'Руководство:r';
    VAL = NULL;
    SUSPEND;

    SELECT C1 FROM BUILD_REP_FIO(:V$ID, 59, 60, 61, 1) INTO :VAL;
    TAG_NAME = 'Руководство:r:ФИО';
    SUSPEND;

    TAG_NAME = 'Руководство:r:Должность::json&colon;array';
    VAL = 1;
    SUSPEND;
    V$MAIN = NULL;
    FOR
      SELECT V72.LISTVAL_ID, COALESCE(V3543.VAL, V66.VAL, C58.VAL)
      FROM LINKS L15
      JOIN VALL V72 ON V72.OBJ_ID = L15.OBJ_ID AND V72.PARAM_ID = 72 AND V72.IS_DEL = 0 -- основная или дополнительная должность
      LEFT JOIN VALS V3543 ON V3543.OBJ_ID = L15.OBJ_ID AND V3543.PARAM_ID = 3543 AND V3543.IS_DEL = 0  -- название должности по новой схеме
      LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0                     -- дата увольнения
      JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
      JOIN VALL V58 ON V58.OBJ_ID = LP13.PARENT_ID AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0       -- должность из списка
      JOIN LISTVALS LV58 ON LV58.LISTVAL_ID = V58.LISTVAL_ID
      LEFT JOIN LISTVAL_TEXT(V58.LISTVAL_ID) C58 ON 1 = 1
      LEFT JOIN VALS V66 ON V66.OBJ_ID = LP13.PARENT_ID AND V66.PARAM_ID = 66 AND V66.IS_DEL = 0  -- название должности по старой схеме
      WHERE L15.OBJ_TYPE_ID = 15 AND L15.PARENT_ID = :V$ID AND L15.DATE_DEL IS NULL AND V74.VAL IS NULL
      ORDER BY 1, 2 --  LV58.TAG, LV58."FILTER"
      INTO :V$BLOB_ID, :S1
    DO
    BEGIN
      IF(V$BLOB_ID = 934) THEN V$MAIN = S1;
      VAL = NULL;
      TAG_NAME = 'Руководство:r:Должность:r';
      SUSPEND;
      VAL = S1;
      TAG_NAME = 'Руководство:r:Должность:r:Название';
      SUSPEND;
    END

    VAL = COALESCE(V$MAIN, 'Отсутствует');
    TAG_NAME = 'Руководство:r:Основная_Должность';
    SUSPEND;

    VAL = NULL;
    SELECT V3542.VAL
    FROM VALS V3542
    WHERE V3542.OBJ_ID = :V$ID AND V3542.PARAM_ID = 3542 AND V3542.IS_DEL = 0
    INTO :VAL;
    TAG_NAME = 'Руководство:r:Телефон';
    SUSPEND;

    VAL = NULL;
    SELECT V1180.VAL
    FROM VALS V1180
    WHERE V1180.OBJ_ID = :V$ID AND V1180.PARAM_ID = 1180 AND V1180.IS_DEL = 0
    INTO :VAL;
    TAG_NAME = 'Руководство:r:Электронная_почта';
    SUSPEND;

    -- Фотография
    S1 = NULL;
    V$BLOB_ID = NULL;
    SELECT V240.BLOB_ID, V240.VAL
    FROM VALB V240
    WHERE V240.OBJ_ID = :V$ID AND V240.PARAM_ID = 240 AND V240.IS_DEL = 0
    INTO :V$BLOB_ID, :S1;

    TAG_NAME = 'Руководство:r:file_name';
    VAL = S1;
    SUSPEND;
    TAG_NAME = 'Руководство:r:blob_id';
    VAL = V$BLOB_ID;
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SITELOAD_DATA_18587 RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(4000))
AS
DECLARE VARIABLE V$ID BIGINT;
DECLARE VARIABLE V$BLOB_ID BIGINT;
DECLARE VARIABLE V$S VARCHAR(1000);
DECLARE VARIABLE V$LISTVAL_ID BIGINT;
DECLARE VARIABLE V$D DATE;
DECLARE VARIABLE V$MAIN VARCHAR(1000);
DECLARE VARIABLE V$S2 VARCHAR(1000);
DECLARE VARIABLE V$Y10 INTEGER;
DECLARE VARIABLE V$SUBY INTEGER;
begin
  -- Педагогический_состав
  TAG_NAME = 'Педагогический_состав::json&colon;array';
  VAL = 1;
  SUSPEND;
  -- Педагогический_состав
  FOR
    SELECT DISTINCT L14.OBJ_ID, C.CAPTION
    FROM LINKS L14
    JOIN VALL V274 ON V274.OBJ_ID = L14.OBJ_ID AND V274.PARAM_ID = 274 AND V274.IS_DEL = 0 AND V274.LISTVAL_ID = 602        -- работающий сотрудник
    JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0                                 -- дата увольнения
    JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
    LEFT JOIN VALL V58 ON V58.OBJ_ID = LP13.PARENT_ID AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0                            -- должность из списка
    JOIN LISTVALS LV58 ON LV58.LISTVAL_ID = V58.LISTVAL_ID AND (LV58.TAG = 'U' OR LV58."FILTER" = 'U')          -- педагоги
    LEFT JOIN OBJECT_CAPTION_GET(L14.OBJ_ID) C ON 1 = 1
    WHERE L14.OBJ_TYPE_ID = 14 AND L14.PARENT_TYPE_ID IN (2, 211) AND L14.DATE_DEL IS NULL AND V74.VAL IS NULL
    ORDER BY 2
    INTO :V$ID, :V$S
  DO
  BEGIN
    TAG_NAME = 'Педагогический_состав:r';
    VAL = NULL;
    SUSPEND;

    TAG_NAME = 'Педагогический_состав:r:ФИО';
    --SELECT C1 FROM BUILD_REP_FIO(:V$ID, 59, 60, 61, 1) INTO :VAL;
    VAL = V$S;
    SUSPEND;

    -- Должности
    TAG_NAME = 'Педагогический_состав:r:Должность::json&colon;array';
    VAL = 1;
    SUSPEND;
    V$MAIN = NULL;
    FOR
      SELECT V72.LISTVAL_ID, COALESCE(V3543.VAL, V66.VAL, C58.VAL)
      FROM LINKS L15
      JOIN VALL V72 ON V72.OBJ_ID = L15.OBJ_ID AND V72.PARAM_ID = 72 AND V72.IS_DEL = 0 -- основная или дополнительная должность
      LEFT JOIN VALS V3543 ON V3543.OBJ_ID = L15.OBJ_ID AND V3543.PARAM_ID = 3543 AND V3543.IS_DEL = 0  -- название должности по новой схеме
      LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0                                 -- дата увольнения
      JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
      LEFT JOIN VALS V66 ON V66.OBJ_ID = LP13.PARENT_ID AND V66.PARAM_ID = 66 AND V66.IS_DEL = 0  -- название должности
      LEFT JOIN VALL V58 ON V58.OBJ_ID = LP13.PARENT_ID AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0  -- должность из списка
      LEFT JOIN LISTVAL_TEXT(V58.LISTVAL_ID) C58 ON 1 = 1
      WHERE L15.OBJ_TYPE_ID = 15 AND L15.PARENT_ID = :V$ID AND L15.DATE_DEL IS NULL AND V74.VAL IS NULL
      ORDER BY 1, 2
      INTO :V$BLOB_ID, :V$S
    DO
    BEGIN
      VAL = NULL;
      TAG_NAME = 'Педагогический_состав:r:Должность:r';
      SUSPEND;
      VAL = V$S;
      TAG_NAME = 'Педагогический_состав:r:Должность:r:Название';
      SUSPEND;
    END

    VAL = COALESCE(V$MAIN, 'Отсутствует');
    TAG_NAME = 'Педагогический_состав:r:Основная_Должность';
    SUSPEND;

    -- Фотография
    V$S = NULL;
    V$BLOB_ID = NULL;
    SELECT V240.BLOB_ID, V240.VAL
    FROM VALB V240
    WHERE V240.OBJ_ID = :V$ID AND V240.PARAM_ID = 240 AND IS_DEL = 0
    INTO :V$BLOB_ID, :V$S;

    TAG_NAME = 'Педагогический_состав:r:file_name';
    VAL = V$S;
    SUSPEND;
    TAG_NAME = 'Педагогический_состав:r:blob_id';
    VAL = V$BLOB_ID;
    SUSPEND;

    -- Преподаваемые_предметы
    TAG_NAME = 'Педагогический_состав:r:Преподаваемые_предметы::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT L51.OBJ_ID, V376.VAL
      FROM LINKS L51
      JOIN VALS V376 ON V376.OBJ_ID = L51.OBJ_ID AND V376.PARAM_ID = 376 AND V376.IS_DEL = 0
      WHERE L51.PARENT_ID = :V$ID AND L51.OBJ_TYPE_ID = 51 AND L51.DATE_DEL IS NULL
      INTO :V$BLOB_ID, :V$S
    DO
    BEGIN
      TAG_NAME = 'Педагогический_состав:r:Преподаваемые_предметы:r';
      VAL = NULL;
      SUSPEND;

      TAG_NAME = 'Педагогический_состав:r:Преподаваемые_предметы:r:Название';
      VAL = V$S;
      SUSPEND;
    END

    -- наименование общеобразовательных программ, код и наименование профессии, специальностей, в реализации которых участвует педагогический работник
    TAG_NAME = 'Педагогический_состав:r:Образовательные_программы::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT L57.OBJ_ID, V386.VAL, V1754.SVAL
      FROM LINKS L57
      LEFT JOIN VALS V386 ON V386.OBJ_ID = L57.OBJ_ID AND V386.PARAM_ID = 386 AND V386.IS_DEL = 0
      LEFT JOIN VALS V1754 ON V1754.OBJ_ID = L57.OBJ_ID AND V1754.PARAM_ID = 1754 AND V1754.IS_DEL = 0
      WHERE L57.PARENT_ID = :V$ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
      ORDER BY 2
      INTO :V$BLOB_ID, :V$S, :V$MAIN
    DO
    BEGIN
      TAG_NAME = 'Педагогический_состав:r:Образовательные_программы:r';
      VAL = NULL;
      SUSPEND;

      VAL = COALESCE(V$S, 'Данные отсутствуют');
      TAG_NAME = 'Педагогический_состав:r:Образовательные_программы:r:Название';
      SUSPEND;

      -- код профессии, специальностей для СПО
      VAL = COALESCE(V$MAIN, 'Данные отсутствуют');
      TAG_NAME = 'Педагогический_состав:r:Образовательные_программы:r:Код_профессии_специальности';
      SUSPEND;

      -- наименование профессии, специальностей для СПО
      VAL = NULL;
      SELECT FIRST 1 LV.VAL
      FROM VALL V
      JOIN LISTVAL_TEXT(V.LISTVAL_ID) LV ON 1 = 1
      WHERE V.OBJ_ID = :V$BLOB_ID AND V.PARAM_ID IN (1753, 2460, 3378) AND V.IS_DEL = 0
      INTO :VAL;
      IF (VAL IS NULL) THEN VAL = 'Данные отсутствуют';
      TAG_NAME = 'Педагогический_состав:r:Образовательные_программы:r:Название_профессии_специальности';
      SUSPEND;
    END

    -- Квалификация, найдем последнее решение комиссии по cоответствию категории
    V$LISTVAL_ID = NULL;
    V$S = NULL;
    SELECT FIRST 1 V545.LISTVAL_ID, JOB.VAL
    FROM LINKS L34
    JOIN VALD V544 ON V544.OBJ_ID = L34.OBJ_ID AND V544.PARAM_ID = 544 AND V544.IS_DEL = 0      -- дата комиссии
    JOIN VALL V545 ON V545.OBJ_ID = L34.OBJ_ID AND V545.PARAM_ID = 545 AND V545.IS_DEL = 0 AND V545.LISTVAL_ID IN (1208, 1209, 1210) -- решение комиссии
    LEFT JOIN VALL V2347 ON V2347.OBJ_ID = L34.OBJ_ID AND V2347.PARAM_ID = 2347 AND V2347.IS_DEL = 0 -- должность
    LEFT JOIN LISTVAL_TEXT(V2347.LISTVAL_ID) JOB ON 1 = 1
    WHERE L34.PARENT_ID = :V$ID AND L34.OBJ_TYPE_ID = 34 AND L34.DATE_DEL IS NULL
    ORDER BY V544.VAL DESC
    INTO :V$LISTVAL_ID, V$S;

    IF (V$LISTVAL_ID = 1208) THEN VAL = 'Высшая квалификационная категория' || COALESCE(' по должности ' || V$S, '');
    ELSE IF (V$LISTVAL_ID = 1209) THEN VAL = 'Первая квалификационная категория' || COALESCE(' по должности ' || V$S, '');
    ELSE IF (V$LISTVAL_ID = 1210) THEN VAL = 'Вторая квалификационная категория' || COALESCE(' по должности ' || V$S, '');
    ELSE VAL = 'Отсутствует';
    TAG_NAME = 'Педагогический_состав:r:Квалификационная_категория';
    SUSPEND;

    VAL = 'Данные отсутствуют';
    SELECT LV.VAL
    FROM VALL V279
    LEFT JOIN LISTVAL_TEXT(LISTVAL_ID) LV ON 1 = 1
    WHERE V279.OBJ_ID = :V$ID AND V279.PARAM_ID = 279 AND V279.IS_DEL = 0
    INTO :VAL;
    TAG_NAME = 'Педагогический_состав:r:Ученая_степень';
    SUSPEND;

    VAL = 'Данные отсутствуют';
    SELECT LV.VAL
    FROM VALL V280
    LEFT JOIN LISTVAL_TEXT(LISTVAL_ID) LV ON 1 = 1
    WHERE V280.OBJ_ID = :V$ID AND V280.PARAM_ID = 280 AND V280.IS_DEL = 0
    INTO :VAL;
    TAG_NAME = 'Педагогический_состав:r:Звание';
    SUSPEND;

    TAG_NAME = 'Педагогический_состав:r:Уровень_образования::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT L33.OBJ_ID, C284.VAL, V291.VAL, V292.VAL
      FROM LINKS L33
      JOIN VALD V290 ON V290.OBJ_ID = L33.OBJ_ID AND V290.PARAM_ID = 290 AND V290.IS_DEL = 0
      JOIN VALL V284 ON V284.OBJ_ID = L33.OBJ_ID AND V284.PARAM_ID = 284 AND V284.IS_DEL = 0
      LEFT JOIN LISTVAL_TEXT(V284.LISTVAL_ID) C284 ON 1 = 1
      LEFT JOIN VALS V291 ON V291.OBJ_ID = L33.OBJ_ID AND V291.PARAM_ID = 291 AND V291.IS_DEL = 0
      LEFT JOIN VALS V292 ON V292.OBJ_ID = L33.OBJ_ID AND V292.PARAM_ID = 292 AND V292.IS_DEL = 0
      WHERE L33.PARENT_ID = :V$ID AND L33.OBJ_TYPE_ID = 33 AND L33.DATE_DEL IS NULL
      ORDER BY V290.VAL
      INTO :V$BLOB_ID, :V$S, :V$MAIN, :V$S2
    DO
    BEGIN
      VAL = NULL;
      TAG_NAME = 'Педагогический_состав:r:Уровень_образования:r';
      SUSPEND;

      VAL = COALESCE(V$S, 'Данные отсутствуют');
      TAG_NAME = 'Педагогический_состав:r:Уровень_образования:r:Вид_образования';
      SUSPEND;

      VAL = COALESCE(V$MAIN, 'Данные отсутствуют');
      TAG_NAME = 'Педагогический_состав:r:Уровень_образования:r:Специальность';
      SUSPEND;

      VAL = COALESCE(V$S2, 'Данные отсутствуют');
      TAG_NAME = 'Педагогический_состав:r:Уровень_образования:r:Квалификация';
      SUSPEND;
    END

    TAG_NAME = 'Педагогический_состав:r:Профессиональная_переподготовка::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT L35.OBJ_ID, V300.VAL, V296.VAL, V301.VAL, V302.VAL
      FROM LINKS L35
      JOIN VALD V300 ON V300.OBJ_ID = L35.OBJ_ID AND V300.PARAM_ID = 300 AND V300.IS_DEL = 0
      JOIN VALS V296 ON V296.OBJ_ID = L35.OBJ_ID AND V296.PARAM_ID = 296 AND V296.IS_DEL = 0
      LEFT JOIN VALS V301 ON V301.OBJ_ID = L35.OBJ_ID AND V301.PARAM_ID = 301 AND V301.IS_DEL = 0
      LEFT JOIN VALS V302 ON V302.OBJ_ID = L35.OBJ_ID AND V302.PARAM_ID = 302 AND V302.IS_DEL = 0
      WHERE L35.PARENT_ID = :V$ID AND L35.OBJ_TYPE_ID = 35 AND L35.DATE_DEL IS NULL
      ORDER BY V300.VAL
      INTO :V$BLOB_ID, :V$D, :V$S, :V$MAIN, :V$S2
    DO
    BEGIN
      VAL = NULL;
      TAG_NAME = 'Педагогический_состав:r:Профессиональная_переподготовка:r';
      SUSPEND;

      VAL = V$S; -- не может быть пусто
      TAG_NAME = 'Педагогический_состав:r:Профессиональная_переподготовка:r:ОООД_профессиональной_переподготовки';
      SUSPEND;

      VAL = COALESCE(V$MAIN, 'Данные отсутствуют');
      TAG_NAME = 'Педагогический_состав:r:Профессиональная_переподготовка:r:Специальность';
      SUSPEND;

      VAL = COALESCE(V$S2, 'Данные отсутствуют');
      TAG_NAME = 'Педагогический_состав:r:Профессиональная_переподготовка:r:Квалификация';
      SUSPEND;

      VAL = NULL;
      SELECT CAP.VAL
      FROM VALL V297
      LEFT JOIN LISTVAL_TEXT(V297.LISTVAL_ID) CAP ON 1 = 1
      WHERE V297.OBJ_ID = :V$BLOB_ID AND V297.PARAM_ID = 297 AND V297.IS_DEL = 0
      INTO :VAL;
      TAG_NAME = 'Педагогический_состав:r:Профессиональная_переподготовка:r:Вид_документа';
      SUSPEND;

      VAL = (SELECT RESULT FROM DATE2STR(:V$D));
      TAG_NAME = 'Педагогический_состав:r:Профессиональная_переподготовка:r:Дата_выдачи_документа';
      SUSPEND;

      VAL = NULL;
      SELECT V298.VAL
      FROM VALS V298
      WHERE V298.OBJ_ID = :V$BLOB_ID AND V298.PARAM_ID = 298 AND V298.IS_DEL = 0
      INTO :VAL;
      TAG_NAME = 'Педагогический_состав:r:Профессиональная_переподготовка:r:Серия_документа';
      SUSPEND;

      VAL = 'Данные отсутствуют';
      SELECT V299.VAL
      FROM VALS V299
      WHERE V299.OBJ_ID = :V$BLOB_ID AND V299.PARAM_ID = 299 AND V299.IS_DEL = 0
      INTO :VAL;
      TAG_NAME = 'Педагогический_состав:r:Профессиональная_переподготовка:r:Номер_документа';
      SUSPEND;
    END

    TAG_NAME = 'Педагогический_состав:r:Повышение_квалификации::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT L36.OBJ_ID, V310.VAL, C303.VAL, V304.VAL, V305.VAL
      FROM LINKS L36
      JOIN VALD V310 ON V310.OBJ_ID = L36.OBJ_ID AND V310.PARAM_ID = 310 AND V310.IS_DEL = 0 AND DATEDIFF(YEAR, V310.VAL, CURRENT_DATE) < 3  -- дата выдачи за послдение 3 года
      LEFT JOIN VALL V303 ON V303.OBJ_ID = L36.OBJ_ID AND V303.PARAM_ID = 303 AND V303.IS_DEL = 0
      LEFT JOIN LISTVAL_TEXT(V303.LISTVAL_ID) C303 ON 1 = 1
      LEFT JOIN VALS V304 ON V304.OBJ_ID = L36.OBJ_ID AND V304.PARAM_ID = 304 AND V304.IS_DEL = 0
      LEFT JOIN VALS V305 ON V305.OBJ_ID = L36.OBJ_ID AND V305.PARAM_ID = 305 AND V305.IS_DEL = 0
      WHERE L36.PARENT_ID = :V$ID AND L36.OBJ_TYPE_ID = 36 AND L36.DATE_DEL IS NULL
      ORDER BY V310.VAL
      INTO :V$BLOB_ID, :V$D, :V$S, :V$MAIN, :V$S2
    DO
    BEGIN
      VAL = NULL;
      TAG_NAME = 'Педагогический_состав:r:Повышение_квалификации:r';
      SUSPEND;

      VAL = COALESCE(V$S, 'Данные отсутствуют');
      TAG_NAME = 'Педагогический_состав:r:Повышение_квалификации:r:Вид';
      SUSPEND;

      VAL = COALESCE(V$MAIN, 'Данные отсутствуют');
      TAG_NAME = 'Педагогический_состав:r:Повышение_квалификации:r:ОООД_повышения_квалификации';
      SUSPEND;

      VAL = COALESCE(V$S2, 'Данные отсутствуют');
      TAG_NAME = 'Педагогический_состав:r:Повышение_квалификации:r:Название_курса';
      SUSPEND;

      VAL = NULL;
      SELECT CAP.VAL
      FROM VALL V1024
      LEFT JOIN LISTVAL_TEXT(V1024.LISTVAL_ID) CAP ON 1 = 1
      WHERE V1024.OBJ_ID = :V$BLOB_ID AND V1024.PARAM_ID = 1024 AND V1024.IS_DEL = 0
      INTO :VAL;
      TAG_NAME = 'Педагогический_состав:r:Повышение_квалификации:r:Тип_курса';
      SUSPEND;

      VAL = NULL;
      SELECT V306.VAL
      FROM VALI V306
      WHERE V306.OBJ_ID = :V$BLOB_ID AND V306.PARAM_ID = 306 AND V306.IS_DEL = 0
      INTO :VAL;
      TAG_NAME = 'Педагогический_состав:r:Повышение_квалификации:r:Объем_курса';
      SUSPEND;

      VAL = NULL;
      SELECT CAP.VAL
      FROM VALL V307
      LEFT JOIN LISTVAL_TEXT(V307.LISTVAL_ID) CAP ON 1 = 1
      WHERE V307.OBJ_ID = :V$BLOB_ID AND V307.PARAM_ID = 307 AND V307.IS_DEL = 0
      INTO :VAL;
      TAG_NAME = 'Педагогический_состав:r:Повышение_квалификации:r:Вид_документа';
      SUSPEND;

      VAL = (SELECT RESULT FROM DATE2STR(:V$D));
      TAG_NAME = 'Педагогический_состав:r:Повышение_квалификации:r:Дата_выдачи_документа';
      SUSPEND;

      VAL = NULL;
      SELECT V308.VAL
      FROM VALS V308
      WHERE V308.OBJ_ID = :V$BLOB_ID AND V308.PARAM_ID = 308 AND V308.IS_DEL = 0
      INTO :VAL;
      TAG_NAME = 'Педагогический_состав:r:Повышение_квалификации:r:Серия_документа';
      SUSPEND;

      VAL = 'Данные отсутствуют';
      SELECT V309.VAL
      FROM VALS V309
      WHERE V309.OBJ_ID = :V$BLOB_ID AND V309.PARAM_ID = 309 AND V309.IS_DEL = 0
      INTO :VAL;
      TAG_NAME = 'Педагогический_состав:r:Повышение_квалификации:r:Номер_документа';
      SUSPEND;
    END

    -- Педагогический стаж
    V$LISTVAL_ID = NULL;
    SELECT SUM(DATEDIFF(MONTH, V466.VAL, COALESCE(V467.VAL, CURRENT_DATE)))
    FROM LINKS L85
    JOIN VALL V465 ON V465.OBJ_ID = L85.OBJ_ID AND V465.PARAM_ID = 465 AND V465.IS_DEL = 0 AND V465.LISTVAL_ID = 942 -- стаж педагогический
    JOIN VALD V466 ON V466.OBJ_ID = L85.OBJ_ID AND V466.PARAM_ID = 466 AND V466.IS_DEL = 0                           -- дата начала стажа
    LEFT JOIN VALD V467 ON V467.OBJ_ID = L85.OBJ_ID AND V467.PARAM_ID = 467 AND V467.IS_DEL = 0                      -- дата окончания стажа
    WHERE L85.PARENT_ID = :V$ID AND L85.OBJ_TYPE_ID = 85 AND L85.DATE_DEL IS NULL
    INTO :V$LISTVAL_ID;

    TAG_NAME = 'Педагогический_состав:r:Педагогический_стаж';
    IF (V$LISTVAL_ID / 12 > 0) THEN
    BEGIN
      -- При стаже более года указываем только годы
      V$LISTVAL_ID = V$LISTVAL_ID / 12;
      V$Y10 = V$LISTVAL_ID / 10; -- десятки лет
      V$SUBY = V$LISTVAL_ID - V$Y10 * 10; -- единицы лет в десятках

      IF (V$SUBY = 1 AND V$Y10 <> 1) THEN VAL = V$LISTVAL_ID || ' год'; -- все кроме 11 лет
      ELSE IF (V$SUBY IN (2, 3, 4) AND V$Y10 <> 1) THEN VAL = V$LISTVAL_ID || ' годa'; -- кроме 12-13-14 лет
      ELSE VAL = V$LISTVAL_ID || ' лет';
      SUSPEND;
    END
    ELSE
    BEGIN
      VAL = V$LISTVAL_ID || ' мес';
      SUSPEND;
    END
  END
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SITELOAD_DATA_18588 RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(4000))
AS
DECLARE VARIABLE V$OU_ID BIGINT;
DECLARE VARIABLE S1 VARCHAR(1000);
DECLARE VARIABLE BLOB_ID BIGINT;
DECLARE VARIABLE S3 VARCHAR(1000);
DECLARE VARIABLE CBLOB_ID BIGINT;
DECLARE VARIABLE V$ID BIGINT;
DECLARE VARIABLE V$SUM INTEGER;
begin
  SELECT FIRST 1 L2.OBJ_ID
  FROM LINKS L2
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$OU_ID;

  TAG_NAME = 'Количество_кабинетов::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT V421.VAL, R.VAL, COUNT(*)
    FROM LINKS L61
    JOIN VALS V421 ON V421.OBJ_ID = L61.PARENT_ID AND V421.PARAM_ID = 421 AND V421.IS_DEL = 0 -- название здания
    JOIN VALL V526 ON V526.OBJ_ID = L61.OBJ_ID AND V526.PARAM_ID = 526 AND V526.IS_DEL = 0
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V526.LISTVAL_ID AND LV.LIST_ID = 20 AND LV.IS_DEL = 0 AND LV.PARENT_ID = 24
    JOIN RES R ON LV.RES_ID = R.RES_ID AND R.IS_DEL = 0 AND R.LANG_CODE = 'RU'
    WHERE L61.PARENT_TYPE_ID = 16 AND L61.OBJ_TYPE_ID = 61 AND L61.DATE_DEL IS NULL
    GROUP BY 1, 2
    INTO :S1, :S3, :V$ID
  DO
  BEGIN
    TAG_NAME = 'Количество_кабинетов:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'Количество_кабинетов:r:Здание';
    VAL = S1;
    SUSPEND;
    TAG_NAME = 'Количество_кабинетов:r:Тип';
    VAL = S3;
    SUSPEND;
    TAG_NAME = 'Количество_кабинетов:r:Количество';
    VAL = V$ID;
    SUSPEND;
  END

  TAG_NAME = 'Компьютерные_классы::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT V421.VAL, COUNT(*)
    FROM LINKS L61
    JOIN VALS V421 ON V421.OBJ_ID = L61.PARENT_ID AND V421.PARAM_ID = 421 AND V421.IS_DEL = 0
    JOIN VALL V526 ON V526.OBJ_ID = L61.OBJ_ID AND V526.PARAM_ID = 526 AND V526.IS_DEL = 0 AND V526.LISTVAL_ID = 11725
    WHERE L61.PARENT_TYPE_ID = 16 AND L61.OBJ_TYPE_ID = 61 AND L61.DATE_DEL IS NULL
    GROUP BY 1
    INTO :S1, :V$ID
  DO
  BEGIN
    TAG_NAME = 'Компьютерные_классы:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'Компьютерные_классы:r:Здание';
    VAL = S1;
    SUSPEND;
    TAG_NAME = 'Компьютерные_классы:r:Количество';
    VAL = V$ID;
    SUSPEND;
  END

  TAG_NAME = 'Музыкально-спортивные_залы::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT V421.VAL, COUNT(*)
    FROM LINKS L61
    JOIN VALS V421 ON V421.OBJ_ID = L61.PARENT_ID AND V421.PARAM_ID = 421 AND V421.IS_DEL = 0
    JOIN VALL V526 ON V526.OBJ_ID = L61.OBJ_ID AND V526.PARAM_ID = 526 AND V526.IS_DEL = 0 AND V526.LISTVAL_ID IN (3287, 3288)
    WHERE L61.PARENT_TYPE_ID = 16 AND L61.OBJ_TYPE_ID = 61 AND L61.DATE_DEL IS NULL
    GROUP BY 1
    INTO :S1, :V$ID
  DO
  BEGIN
    TAG_NAME = 'Музыкально-спортивные_залы:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'Музыкально-спортивные_залы:r:Здание';
    VAL = S1;
    SUSPEND;
    TAG_NAME = 'Музыкально-спортивные_залы:r:Количество';
    VAL = V$ID;
    SUSPEND;
  END

  TAG_NAME = 'Учебные_лаборатории::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT V421.VAL, COUNT(*)
    FROM LINKS L61
    JOIN VALS V421 ON V421.OBJ_ID = L61.PARENT_ID AND V421.PARAM_ID = 421 AND V421.IS_DEL = 0
    JOIN VALL V526 ON V526.OBJ_ID = L61.OBJ_ID AND V526.PARAM_ID = 526 AND V526.IS_DEL = 0 AND V526.LISTVAL_ID = 1146
    WHERE L61.PARENT_TYPE_ID = 16 AND L61.OBJ_TYPE_ID = 61 AND L61.DATE_DEL IS NULL
    GROUP BY 1
    INTO :S1, :V$ID
  DO
  BEGIN
    TAG_NAME = 'Учебные_лаборатории:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'Учебные_лаборатории:r:Здание';
    VAL = S1;
    SUSPEND;
    TAG_NAME = 'Учебные_лаборатории:r:Количество';
    VAL = V$ID;
    SUSPEND;
  END

  TAG_NAME = 'Учебные_мастерские::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT V421.VAL, COUNT(*)
    FROM LINKS L61
    JOIN VALS V421 ON V421.OBJ_ID = L61.PARENT_ID AND V421.PARAM_ID = 421 AND V421.IS_DEL = 0
    JOIN VALL V526 ON V526.OBJ_ID = L61.OBJ_ID AND V526.PARAM_ID = 526 AND V526.IS_DEL = 0 AND V526.LISTVAL_ID = 1147
    WHERE L61.PARENT_TYPE_ID = 16 AND L61.OBJ_TYPE_ID = 61 AND L61.DATE_DEL IS NULL
    GROUP BY 1
    INTO :S1, :V$ID
  DO
  BEGIN
    TAG_NAME = 'Учебные_лаборатории:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'Учебные_лаборатории:r:Здание';
    VAL = S1;
    SUSPEND;
    TAG_NAME = 'Учебные_лаборатории:r:Количество';
    VAL = V$ID;
    SUSPEND;
  END

  -- Так делать нельзя !!! Объекты в #162 обновляются только специфическим способом
  -- И вообще это переделываем на новую схему в 2024
  VAL = NULL;
  S1 = 'Отсутствует';
  S3 = 'Отсутствует';
  SELECT V1439.VAL, V1440.VAL, V1447.VAL
  FROM LINKS L162
  JOIN VALI V1439 ON V1439.OBJ_ID = L162.OBJ_ID AND V1439.PARAM_ID = 1439 AND V1439.IS_DEL = 0
  JOIN VALI V1440 ON V1440.OBJ_ID = L162.OBJ_ID AND V1440.PARAM_ID = 1440 AND V1440.IS_DEL = 0
  JOIN VALI V1447 ON V1447.OBJ_ID = L162.OBJ_ID AND V1447.PARAM_ID = 1447 AND V1447.IS_DEL = 0
  WHERE L162.PARENT_TYPE_ID = 2 AND L162.OBJ_TYPE_ID = 162 AND L162.DATE_DEL IS NULL
  INTO :VAL, :S1, :S3;
  TAG_NAME = 'Библиотечный_фонд_всего_единиц';
  SUSPEND;
  VAL = S1;
  TAG_NAME = 'Библиотечный_фонд_учебники';
  SUSPEND;
  VAL = S3;
  TAG_NAME = 'Библиотечный_фонд_худ_литература';
  SUSPEND;

  TAG_NAME = 'Библиотека::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT V421.VAL, COALESCE(V408.VAL, R.VAL)
    FROM LINKS L61
    JOIN VALS V421 ON V421.OBJ_ID = L61.PARENT_ID AND V421.PARAM_ID = 421 AND V421.IS_DEL = 0
    JOIN VALL V526 ON V526.OBJ_ID = L61.OBJ_ID AND V526.PARAM_ID = 526 AND V526.IS_DEL = 0
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V526.LISTVAL_ID AND LV.LIST_ID = 20 AND LV.IS_DEL = 0 AND LV.PARENT_ID = 1139
    JOIN RES R ON R.RES_ID = LV.RES_ID AND R.IS_DEL = 0 AND R.LANG_CODE = 'RU'
    LEFT JOIN VALS V408 ON V408.OBJ_ID = L61.OBJ_ID AND V408.PARAM_ID = 408 AND V408.IS_DEL = 0
    WHERE L61.PARENT_TYPE_ID = 16 AND L61.OBJ_TYPE_ID = 61 AND L61.DATE_DEL IS NULL
    ORDER BY 1, 2
    INTO :S1, :S3
  DO
  BEGIN
    TAG_NAME = 'Библиотека:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'Библиотека:r:Здание';
    VAL = S1;
    SUSPEND;
    TAG_NAME = 'Библиотека:r:Помещение';
    VAL = S3;
    SUSPEND;
  END

  -- !!! Возможно тут нужно вывести еще и название здания ?
  TAG_NAME = 'Cпортзалы_перечень::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT V421.VAL, COALESCE(V408.VAL, CAP.VAL)
    FROM LINKS L61
    JOIN VALS V421 ON V421.OBJ_ID = L61.PARENT_ID AND V421.PARAM_ID = 421 AND V421.IS_DEL = 0
    JOIN VALL V526 ON V526.OBJ_ID = L61.OBJ_ID AND V526.PARAM_ID = 526 AND V526.IS_DEL = 0 AND V526.LISTVAL_ID IN (1129, 1130, 1133)
    LEFT JOIN LISTVAL_TEXT(V526.LISTVAL_ID) CAP ON 1 = 1
    LEFT JOIN VALS V408 ON V408.OBJ_ID = L61.OBJ_ID AND V408.PARAM_ID = 408 AND V408.IS_DEL = 0
    WHERE L61.PARENT_TYPE_ID = 16 AND L61.OBJ_TYPE_ID = 61 AND L61.DATE_DEL IS NULL
    ORDER BY 1, 2
    INTO :S1, :S3
  DO
  BEGIN
    TAG_NAME = 'Cпортзалы_перечень:r';
    VAL = NULL;
    SUSPEND;
    VAL = S1;
    TAG_NAME = 'Cпортзалы_перечень:r:Здание';
    SUSPEND;
    VAL = S3;
    TAG_NAME = 'Cпортзалы_перечень:r:Помещение';
    SUSPEND;
  END

  TAG_NAME = 'Cпортзалы_количество';
  SELECT COUNT(*)
  FROM LINKS L61
  JOIN VALL V526 ON V526.OBJ_ID = L61.OBJ_ID AND V526.PARAM_ID = 526 AND V526.IS_DEL = 0 AND V526.LISTVAL_ID IN (1129, 1130, 1133)
  WHERE L61.PARENT_TYPE_ID = 16 AND L61.OBJ_TYPE_ID = 61 AND L61.DATE_DEL IS NULL
  INTO :VAL;
  SUSPEND;

  -- !!! Возможно тут нужно вывести еще и название здания ?
  TAG_NAME = 'Тренажёрные_залы_перечень::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT V421.VAL, COALESCE(V408.VAL, CAP.VAL)
    FROM LINKS L61
    JOIN VALS V421 ON V421.OBJ_ID = L61.PARENT_ID AND V421.PARAM_ID = 421 AND V421.IS_DEL = 0
    JOIN VALL V526 ON V526.OBJ_ID = L61.OBJ_ID AND V526.PARAM_ID = 526 AND V526.IS_DEL = 0 AND V526.LISTVAL_ID = 1131
    LEFT JOIN LISTVAL_TEXT(V526.LISTVAL_ID) CAP ON 1 = 1
    LEFT JOIN VALS V408 ON V408.OBJ_ID = L61.OBJ_ID AND V408.PARAM_ID = 408 AND V408.IS_DEL = 0
    WHERE L61.PARENT_TYPE_ID = 16 AND L61.OBJ_TYPE_ID = 61 AND L61.DATE_DEL IS NULL
    ORDER BY 1, 2
    INTO :S1, :S3
  DO
  BEGIN
    TAG_NAME = 'Тренажёрные_залы_перечень:r';
    VAL = NULL;
    SUSPEND;
    VAL = S1;
    TAG_NAME = 'Тренажёрные_залы_перечень:r:Здание';
    SUSPEND;
    VAL = S3;
    TAG_NAME = 'Тренажёрные_залы_перечень:r:Помещение';
    SUSPEND;
  END

  TAG_NAME = 'Тренажёрные_залы_количество';
  SELECT COUNT(*)
  FROM LINKS L61
  JOIN VALL V526 ON V526.OBJ_ID = L61.OBJ_ID AND V526.PARAM_ID = 526 AND V526.IS_DEL = 0 AND V526.LISTVAL_ID = 1131
  WHERE L61.PARENT_TYPE_ID = 16 AND L61.OBJ_TYPE_ID = 61 AND L61.DATE_DEL IS NULL
  INTO :VAL;
  SUSPEND;

  -- !!! Возможно тут нужно вывести еще и название здания ?
  TAG_NAME = 'Бассейны_перечень::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT V421.VAL, COALESCE(V408.VAL, CAP.VAL)
    FROM LINKS L61
    JOIN VALS V421 ON V421.OBJ_ID = L61.PARENT_ID AND V421.PARAM_ID = 421 AND V421.IS_DEL = 0
    JOIN VALL V526 ON V526.OBJ_ID = L61.OBJ_ID AND V526.PARAM_ID = 526 AND V526.IS_DEL = 0 AND V526.LISTVAL_ID = 1132
    LEFT JOIN LISTVAL_TEXT(V526.LISTVAL_ID) CAP ON 1 = 1
    LEFT JOIN VALS V408 ON V408.OBJ_ID = L61.OBJ_ID AND V408.PARAM_ID = 408 AND V408.IS_DEL = 0
    WHERE L61.PARENT_TYPE_ID = 16 AND L61.OBJ_TYPE_ID = 61 AND L61.DATE_DEL IS NULL
    ORDER BY 1, 2
    INTO :S1, :S3
  DO
  BEGIN
    TAG_NAME = 'Бассейны_перечень:r';
    VAL = NULL;
    SUSPEND;
    VAL = S1;
    TAG_NAME = 'Бассейны_перечень:r:Здание';
    SUSPEND;
    VAL = S3;
    TAG_NAME = 'Бассейны_перечень:r:Помещение';
    SUSPEND;
  END

  TAG_NAME = 'Бассейны_количество';
  SELECT COUNT(*)
  FROM LINKS L61
  JOIN VALL V526 ON V526.OBJ_ID = L61.OBJ_ID AND V526.PARAM_ID = 526 AND V526.IS_DEL = 0 AND V526.LISTVAL_ID = 1132
  WHERE L61.PARENT_TYPE_ID = 16 AND L61.OBJ_TYPE_ID = 61 AND L61.DATE_DEL IS NULL
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'Стадионы::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT COALESCE(V3403.VAL, 'Не указан'), COALESCE(V3406.VAL, LV.VAL)
    FROM LINKS L492
    LEFT JOIN VALR V3407 ON V3407.OBJ_ID = L492.OBJ_ID AND V3407.PARAM_ID = 3407 AND V3407.IS_DEL = 0
    LEFT JOIN VALS V3403 ON V3403.OBJ_ID = V3407.VAL AND V3403.PARAM_ID = 3403 AND V3403.IS_DEL = 0
    JOIN VALL V3398 ON V3398.OBJ_ID = L492.OBJ_ID AND V3398.PARAM_ID = 3398 AND V3398.IS_DEL = 0 AND V3398.LISTVAL_ID IN (14243, 14244)
    LEFT JOIN VALS V3406 ON V3406.OBJ_ID = L492.OBJ_ID AND V3406.PARAM_ID = 3406 AND V3406.IS_DEL = 0
    LEFT JOIN LISTVAL_TEXT(V3398.LISTVAL_ID) LV ON 1 = 1
    WHERE L492.PARENT_TYPE_ID = 73 AND L492.OBJ_TYPE_ID = 492 AND L492.DATE_DEL IS NULL
    ORDER BY 1, 2
    INTO :S1, :S3
  DO
  BEGIN
    TAG_NAME = 'Стадионы:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'Стадионы:r:Земельный_участок';
    VAL = S1;
    SUSPEND;
    TAG_NAME = 'Стадионы:r:Стадион';
    VAL = S3;
    SUSPEND;
  END

  TAG_NAME = 'Спортивные_площадки::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT COALESCE(V3403.VAL, 'Не указан'), COALESCE(V3406.VAL, LV.VAL)
    FROM LINKS L492
    LEFT JOIN VALR V3407 ON V3407.OBJ_ID = L492.OBJ_ID AND V3407.PARAM_ID = 3407 AND V3407.IS_DEL = 0
    LEFT JOIN VALS V3403 ON V3403.OBJ_ID = V3407.VAL AND V3403.PARAM_ID = 3403 AND V3403.IS_DEL = 0
    JOIN VALL V3398 ON V3398.OBJ_ID = L492.OBJ_ID AND V3398.PARAM_ID = 3398 AND V3398.IS_DEL = 0 AND V3398.LISTVAL_ID = 14242
    LEFT JOIN LISTVAL_TEXT(V3398.LISTVAL_ID) LV ON 1 = 1
    LEFT JOIN VALS V3406 ON V3406.OBJ_ID = L492.OBJ_ID AND V3406.PARAM_ID = 3406 AND V3406.IS_DEL = 0
    WHERE L492.PARENT_TYPE_ID = 73 AND L492.OBJ_TYPE_ID = 492 AND L492.DATE_DEL IS NULL
    ORDER BY 1, 2
    INTO :S1, :S3
  DO
  BEGIN
    TAG_NAME = 'Спортивные_площадки:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'Спортивные_площадки:r:Земельный_участок';
    VAL = S1;
    SUSPEND;
    TAG_NAME = 'Спортивные_площадки:r:Площадка';
    VAL = S3;
    SUSPEND;
  END

  TAG_NAME = 'Другие_спортивные_объекты::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT COALESCE(V3403.VAL, 'Не указан'), COALESCE(V3406.VAL, LV.VAL)
    FROM LINKS L492
    LEFT JOIN VALR V3407 ON V3407.OBJ_ID = L492.OBJ_ID AND V3407.PARAM_ID = 3407 AND V3407.IS_DEL = 0
    LEFT JOIN VALS V3403 ON V3403.OBJ_ID = V3407.VAL AND V3403.PARAM_ID = 3403 AND V3403.IS_DEL = 0
    JOIN VALL V3398 ON V3398.OBJ_ID = L492.OBJ_ID AND V3398.PARAM_ID = 3398 AND V3398.IS_DEL = 0 AND V3398.LISTVAL_ID = 14279
    LEFT JOIN LISTVAL_TEXT(V3398.LISTVAL_ID) LV ON 1 = 1
    LEFT JOIN VALS V3406 ON V3406.OBJ_ID = L492.OBJ_ID AND V3406.PARAM_ID = 3406 AND V3406.IS_DEL = 0
    WHERE L492.PARENT_TYPE_ID = 73 AND L492.OBJ_TYPE_ID = 492 AND L492.DATE_DEL IS NULL
    ORDER BY 1, 2
    INTO :S1, :S3
  DO
  BEGIN
    TAG_NAME = 'Другие_спортивные_объекты:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'Другие_спортивные_объекты:r:Земельный_участок';
    VAL = S1;
    SUSPEND;
    TAG_NAME = 'Другие_спортивные_объекты:r:Площадка';
    VAL = S3;
    SUSPEND;
  END

  TAG_NAME = 'Средства_обучения::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT LV.LISTVAL_ID, CAP.VAL
    FROM LISTVALS LV
    LEFT JOIN LISTVAL_TEXT(LV.LISTVAL_ID) CAP ON 1 = 1
    WHERE LV.LIST_ID = 157 AND LV.LISTVAL_ID IN (2091, 2095, 2096)
    INTO :V$ID, :S1
  DO
  BEGIN
    TAG_NAME = 'Средства_обучения:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'Средства_обучения:r:Тип';
    VAL = S1;
    SUSPEND;

    VAL = NULL;
    SELECT SUM(V607.VAL)
    FROM LINKS L97
    JOIN VALL V645 ON V645.OBJ_ID = L97.OBJ_ID AND V645.PARAM_ID = 645 AND V645.IS_DEL = 0 AND V645.LISTVAL_ID = :V$ID
    JOIN VALI V607 ON V607.OBJ_ID = L97.OBJ_ID AND V607.PARAM_ID = 607 AND V607.IS_DEL = 0
    WHERE L97.PARENT_TYPE_ID = 92 AND L97.OBJ_TYPE_ID = 97 AND L97.DATE_DEL IS NULL
    INTO :VAL;
    IF(VAL IS NULL) THEN VAL = 'Отсутствует';
    TAG_NAME = 'Средства_обучения:r:Количество';
    SUSPEND;
  END

  TAG_NAME = 'Средства_обучения:r';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'Средства_обучения:r:Тип';
  VAL = 'Натуральные_объекты_модели';
  SUSPEND;

  VAL = NULL;
  SELECT SUM(V607.VAL)
  FROM LINKS L97
  JOIN VALL V645 ON V645.OBJ_ID = L97.OBJ_ID AND V645.PARAM_ID = 645 AND V645.IS_DEL = 0 AND V645.LISTVAL_ID IN (2093, 2094)
  JOIN VALI V607 ON V607.OBJ_ID = L97.OBJ_ID AND V607.PARAM_ID = 607 AND V607.IS_DEL = 0
  WHERE L97.PARENT_TYPE_ID = 92 AND L97.OBJ_TYPE_ID = 97 AND L97.DATE_DEL IS NULL
  INTO :VAL;
  IF(VAL IS NULL) THEN VAL = 'Отсутствует';
  TAG_NAME = 'Средства_обучения:r:Количество';
  SUSPEND;

  VAL = NULL;
  SELECT SUM(V605.VAL)
  FROM LINKS L95
  JOIN VALL V604 ON V604.OBJ_ID = L95.OBJ_ID AND V604.PARAM_ID = 604 AND V604.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V604.LISTVAL_ID AND LV.LIST_ID = 148 AND LV.IS_DEL = 0 AND LV.PARENT_ID = 1799 -- computers
  JOIN VALI V605 ON V605.OBJ_ID = L95.OBJ_ID AND V605.PARAM_ID = 605 AND V605.IS_DEL = 0
  WHERE L95.PARENT_TYPE_ID = 23 AND L95.OBJ_TYPE_ID = 95 AND L95.DATE_DEL IS NULL
  INTO :VAL;
  IF(VAL IS NULL) THEN VAL = 'Отсутствуют';
  TAG_NAME = 'Компьютеры';
  SUSPEND;

  VAL = NULL;
  SELECT SUM(V605.VAL)
  FROM LINKS L95
  JOIN VALL V604 ON V604.OBJ_ID = L95.OBJ_ID AND V604.PARAM_ID = 604 AND V604.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V604.LISTVAL_ID AND LV.LIST_ID = 148 AND LV.IS_DEL = 0 AND LV.PARENT_ID = 1901 --     Презентационное оборудование
  JOIN VALI V605 ON V605.OBJ_ID = L95.OBJ_ID AND V605.PARAM_ID = 605 AND V605.IS_DEL = 0
  WHERE L95.PARENT_TYPE_ID = 23 AND L95.OBJ_TYPE_ID = 95 AND L95.DATE_DEL IS NULL
  INTO :VAL;
  IF(VAL IS NULL) THEN VAL = 'Отсутствует';
  TAG_NAME = 'Презентационное_оборудование';
  SUSPEND;

  VAL = NULL;
  SELECT SUM(V605.VAL)
  FROM LINKS L95
  JOIN VALL V604 ON V604.OBJ_ID = L95.OBJ_ID AND V604.PARAM_ID = 604 AND V604.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V604.LISTVAL_ID AND LV.LIST_ID = 148 AND LV.IS_DEL = 0 AND LV.LISTVAL_ID IN (1905, 1906, 1907, 11076, 12887, 12892) -- Интерактивное презентационное оборудование
  JOIN VALI V605 ON V605.OBJ_ID = L95.OBJ_ID AND V605.PARAM_ID = 605 AND V605.IS_DEL = 0
  WHERE L95.PARENT_TYPE_ID = 23 AND L95.OBJ_TYPE_ID = 95 AND L95.DATE_DEL IS NULL
  INTO :VAL;
  IF(VAL IS NULL) THEN VAL = 'Отсутствует';
  TAG_NAME = 'Интерактивное_презентационное_оборудование';
  SUSPEND;

  SELECT COUNT(*)
  FROM LINKS L61
  JOIN VALL V485 ON V485.OBJ_ID = L61.PARENT_ID AND V485.PARAM_ID = 485 AND V485.IS_DEL = 0 AND V485.LISTVAL_ID = 1094 -- Общежитие
  JOIN VALL V526 ON V526.OBJ_ID = L61.OBJ_ID AND V526.PARAM_ID = 526 AND V526.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V526.LISTVAL_ID AND LV.LIST_ID = 20 AND LV.IS_DEL = 0 AND LV.PARENT_ID = 1159 -- Спальные помещения
  WHERE L61.PARENT_TYPE_ID = 16 AND L61.OBJ_TYPE_ID = 61 AND L61.DATE_DEL IS NULL
  INTO :VAL;
  TAG_NAME = 'Количество_помещений_в_общежитии';
  SUSPEND;

  -- ищем по типу документа и имени положение о плате за проживание в общежитии
  V$ID = NULL;
  SELECT FIRST 1 L17.OBJ_ID, V478.VAL, V478.BLOB_ID, V3503.VAL, V3503.BLOB_ID
  FROM LINKS L17
  JOIN VALL V471 ON V471.OBJ_ID = L17.OBJ_ID AND V471.PARAM_ID = 471 AND V471.IS_DEL = 0 AND V471.LISTVAL_ID = 18635  -- положение
  JOIN VALL V613 ON V613.OBJ_ID = L17.OBJ_ID AND V613.PARAM_ID = 613 AND V613.IS_DEL = 0 AND V613.LISTVAL_ID = 1982   -- статус действующий
  JOIN VALD V482 ON V482.OBJ_ID = L17.OBJ_ID AND V482.PARAM_ID = 482 AND V482.IS_DEL = 0                              -- дата выдачи
  JOIN VALS V596 ON V596.OBJ_ID = L17.OBJ_ID AND V596.PARAM_ID = 596 AND V596.IS_DEL = 0                              -- название положения
  JOIN VALB V478 ON V478.OBJ_ID = L17.OBJ_ID AND V478.PARAM_ID = 478 AND V478.IS_DEL = 0                              -- файл
  LEFT JOIN VALB V3503 ON V3503.OBJ_ID = L17.OBJ_ID AND V3503.PARAM_ID = 3503 AND V3503.IS_DEL = 0                    -- файл ЦП
  WHERE L17.PARENT_TYPE_ID = 2 AND L17.OBJ_TYPE_ID = 17 AND L17.DATE_DEL IS NULL AND V596.VAL CONTAINING 'плат'
    AND V596.VAL CONTAINING 'общежити'
  ORDER BY V482.VAL DESC
  INTO :V$ID, :S1, :BLOB_ID, :S3, :CBLOB_ID;
  -- Файл с положением
  IF (V$ID IS NOT NULL) THEN
  BEGIN
    TAG_NAME = 'Плата_за_общежитие_положение:Имеется';
    VAL = 1;
    SUSPEND;
    TAG_NAME = 'Плата_за_общежитие_положение:file_name';
    VAL = S1;
    SUSPEND;
    TAG_NAME = 'Плата_за_общежитие_положение:blob_id';
    VAL = BLOB_ID;
    SUSPEND;
    -- Файл с ЭЦП
    TAG_NAME = 'Плата_за_общежитие_положение:ЭЦП:file_name';
    VAL = S3;
    SUSPEND;
    TAG_NAME = 'Плата_за_общежитие_положение:ЭЦП:blob_src';
    VAL = BLOB_ID;
    SUSPEND;
    TAG_NAME = 'Плата_за_общежитие_положение:ЭЦП:blob_id';
    VAL = CBLOB_ID;
    SUSPEND;
  END
  ELSE
  BEGIN
    TAG_NAME = 'Плата_за_общежитие_положение:Имеется';
    VAL = 0;
    SUSPEND;
  END
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SITELOAD_DATA_18589 RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(4000))
AS
DECLARE VARIABLE V$ID BIGINT;
DECLARE VARIABLE S1 VARCHAR(1000);
DECLARE VARIABLE BLOB_ID BIGINT;
DECLARE VARIABLE S3 VARCHAR(1000);
DECLARE VARIABLE CBLOB_ID BIGINT;
BEGIN
  -- Доступная среда

  -- Ищем нормативный акт типа паспорта доступности по названию документа: ДОСТУПНОСТЬ
  -- например, ПАСПОРТ доступности для инвалидов объекта и предоставляемых на нем услуг в сфере образования
  V$ID = NULL;
  SELECT FIRST 1 L17.OBJ_ID, V478.VAL, V478.BLOB_ID, V3503.VAL, V3503.BLOB_ID
  FROM LINKS L17
  JOIN VALD V482 ON V482.OBJ_ID = L17.OBJ_ID AND V482.PARAM_ID = 482 AND V482.IS_DEL = 0                              -- дата выдачи
  JOIN VALS V596 ON V596.OBJ_ID = L17.OBJ_ID AND V596.PARAM_ID = 596 AND V596.IS_DEL = 0                              -- название положения
  JOIN VALB V478 ON V478.OBJ_ID = L17.OBJ_ID AND V478.PARAM_ID = 478 AND V478.IS_DEL = 0                              -- файл
  LEFT JOIN VALB V3503 ON V3503.OBJ_ID = L17.OBJ_ID AND V3503.PARAM_ID = 3503 AND V3503.IS_DEL = 0                    -- файл ЦП
  WHERE L17.PARENT_TYPE_ID = 530 AND L17.OBJ_TYPE_ID = 17 AND L17.DATE_DEL IS NULL AND V596.VAL CONTAINING 'оступност'
  ORDER BY V482.VAL DESC
  INTO :V$ID, :S1, :BLOB_ID, :S3, :CBLOB_ID;

  IF (V$ID IS NOT NULL) THEN
  BEGIN
    TAG_NAME = 'Паспорт_доступности:Имеется';
    VAL = 1;
    SUSPEND;
    -- Файл с положением
    TAG_NAME = 'Паспорт_доступности:file_name';
    VAL = S1;
    SUSPEND;
    TAG_NAME = 'Паспорт_доступности:blob_id';
    VAL = BLOB_ID;
    SUSPEND;
    -- Файл с ЭЦП
    TAG_NAME = 'Паспорт_доступности:ЭЦП:file_name';
    VAL = S3;
    SUSPEND;
    TAG_NAME = 'Паспорт_доступности:ЭЦП:blob_src';
    VAL = S3;
    SUSPEND;
    TAG_NAME = 'Паспорт_доступности:ЭЦП:blob_id';
    VAL = CBLOB_ID;
  END
  ELSE
  BEGIN
    TAG_NAME = 'Паспорт_доступности:Имеется';
    VAL = 0;
    SUSPEND;
  END

  TAG_NAME = 'Специализированные_помещения::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT V421.VAL, COALESCE(V408.VAL, R.VAL)
    FROM LINKS L61
    JOIN VALS V421 ON V421.OBJ_ID = L61.PARENT_ID AND V421.PARAM_ID = 421 AND V421.IS_DEL = 0
    LEFT JOIN VALS V408 ON V408.OBJ_ID = L61.OBJ_ID AND V408.PARAM_ID = 408 AND V408.IS_DEL = 0
    JOIN VALL V526 ON V526.OBJ_ID = L61.OBJ_ID AND V526.PARAM_ID = 526 AND V526.IS_DEL = 0
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V526.LISTVAL_ID AND LV.LIST_ID = 20 AND LV.IS_DEL = 0 AND LV.PARENT_ID = 1134
    JOIN RES R ON LV.RES_ID = R.RES_ID AND R.IS_DEL = 0 AND R.LANG_CODE = 'RU'
    WHERE L61.PARENT_TYPE_ID = 16 AND L61.OBJ_TYPE_ID = 61 AND L61.DATE_DEL IS NULL
    ORDER BY 1, 2
    INTO :S1, :S3
  DO
  BEGIN
    TAG_NAME = 'Специализированные_помещения:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'Специализированные_помещения:r:Здание';
    VAL = S1;
    SUSPEND;
    TAG_NAME = 'Специализированные_помещения:r:Название';
    VAL = S3;
    SUSPEND;
  END

  TAG_NAME = 'Медицинский_блок::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT V421.VAL, COALESCE(V408.VAL, R.VAL)
    FROM LINKS L61
    JOIN VALS V421 ON V421.OBJ_ID = L61.PARENT_ID AND V421.PARAM_ID = 421 AND V421.IS_DEL = 0
    LEFT JOIN VALS V408 ON V408.OBJ_ID = L61.OBJ_ID AND V408.PARAM_ID = 408 AND V408.IS_DEL = 0
    JOIN VALL V526 ON V526.OBJ_ID = L61.OBJ_ID AND V526.PARAM_ID = 526 AND V526.IS_DEL = 0
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V526.LISTVAL_ID AND LV.LIST_ID = 20 AND LV.IS_DEL = 0 AND LV.PARENT_ID = 1150
    JOIN RES R ON LV.RES_ID = R.RES_ID AND R.IS_DEL = 0 AND R.LANG_CODE = 'RU'
    WHERE L61.PARENT_TYPE_ID = 16 AND L61.OBJ_TYPE_ID = 61 AND L61.DATE_DEL IS NULL
    ORDER BY 1
    INTO :S1, :S3
  DO
  BEGIN
    TAG_NAME = 'Медицинский_блок:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'Медицинский_блок:r:Здание';
    VAL = S1;
    SUSPEND;
    TAG_NAME = 'Медицинский_блок:r:Название';
    VAL = S3;
    SUSPEND;
  END

  TAG_NAME = 'Специальные_тех_средства_обучения::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT LV.LISTVAL_ID, R.VAL
    FROM LISTVALS LV
    JOIN RES R ON LV.RES_ID = R.RES_ID AND R.IS_DEL = 0 AND R.LANG_CODE = 'RU'
    WHERE LV.LIST_ID = 148 AND LV.IS_DEL = 0 AND LV.PARENT_ID = 1935 -- Оборудование со специальными функциями
    ORDER BY LV.SORT_ORDER
    INTO :V$ID, :S1
  DO
  BEGIN
    TAG_NAME = 'Специальные_тех_средства_обучения:r';
    VAL = NULL;
    SUSPEND;
    VAL = S1;
    TAG_NAME = 'Специальные_тех_средства_обучения:r:Название';
    SUSPEND;

    VAL = NULL;
    SELECT SUM(V605.VAL)
    FROM LINKS L95
    JOIN VALL V604 ON V604.OBJ_ID = L95.OBJ_ID AND V604.PARAM_ID = 604 AND V604.IS_DEL = 0 AND V604.LISTVAL_ID = :V$ID
    LEFT JOIN VALI V605 ON V605.OBJ_ID = L95.OBJ_ID AND V605.PARAM_ID = 605 AND V605.IS_DEL = 0
    WHERE L95.PARENT_TYPE_ID = 23 AND L95.OBJ_TYPE_ID = 95 AND L95.DATE_DEL IS NULL
    GROUP BY V604.LISTVAL_ID
    INTO :VAL;
    VAL = COALESCE(VAL, 0);
    TAG_NAME = 'Специальные_тех_средства_обучения:r:Количество';
    SUSPEND;
  END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SITELOAD_DATA_18590 RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(4000))
AS
DECLARE VARIABLE V$ID BIGINT;
DECLARE VARIABLE S1 VARCHAR(1000);
DECLARE VARIABLE BLOB_ID BIGINT;
DECLARE VARIABLE S3 VARCHAR(1000);
DECLARE VARIABLE CBLOB_ID BIGINT;
DECLARE VARIABLE S5 VARCHAR(1000);
begin
  -- Порядок оказания платных образовательных услуг
  V$ID = NULL;
  SELECT FIRST 1 L17.OBJ_ID, V478.VAL, V478.BLOB_ID, V3503.VAL, V3503.BLOB_ID
  FROM LINKS L17
  JOIN VALL V471 ON V471.OBJ_ID = L17.OBJ_ID AND V471.PARAM_ID = 471 AND V471.IS_DEL = 0 AND V471.LISTVAL_ID IN (18635, 18627)  -- Локальный нормативный акт или положение
  JOIN VALD V482 ON V482.OBJ_ID = L17.OBJ_ID AND V482.PARAM_ID = 482 AND V482.IS_DEL = 0                                        -- дата выдачи
  JOIN VALS V596 ON V596.OBJ_ID = L17.OBJ_ID AND V596.PARAM_ID = 596 AND V596.IS_DEL = 0                                        -- название
  JOIN VALB V478 ON V478.OBJ_ID = L17.OBJ_ID AND V478.PARAM_ID = 478 AND V478.IS_DEL = 0                                        -- файл
  LEFT JOIN VALB V3503 ON V3503.OBJ_ID = L17.OBJ_ID AND V3503.PARAM_ID = 3503 AND V3503.IS_DEL = 0                              -- файл ЦП
  WHERE L17.PARENT_TYPE_ID IN (2, 530) AND L17.OBJ_TYPE_ID = 17 AND L17.DATE_DEL IS NULL
    AND V596.VAL CONTAINING 'орядок' AND V596.VAL CONTAINING 'латн' AND V596.VAL CONTAINING 'услуг'
  ORDER BY V482.VAL DESC
  INTO :V$ID, :S1, :BLOB_ID, :S3, :CBLOB_ID;
  -- Файл
  IF (V$ID IS NOT NULL) THEN
  BEGIN
    TAG_NAME = 'Порядок_платные_услуги:Имеется';
    VAL = 1;
    SUSPEND;
    TAG_NAME = 'Порядок_платные_услуги:file_name';
    VAL = S1;
    SUSPEND;
    TAG_NAME = 'Порядок_платные_услуги:blob_id';
    VAL = BLOB_ID;
    SUSPEND;
    -- Файл с ЭЦП
    TAG_NAME = 'Порядок_платные_услуги:ЭЦП:file_name';
    VAL = S3;
    SUSPEND;
    TAG_NAME = 'Порядок_платные_услуги:ЭЦП:blob_src';
    VAL = BLOB_ID;
    SUSPEND;
    TAG_NAME = 'Порядок_платные_услуги:ЭЦП:blob_id';
    VAL = CBLOB_ID;
    SUSPEND;
  END
  ELSE
  BEGIN
    TAG_NAME = 'Порядок_платные_услуги:Имеется';
    VAL = 0;
    SUSPEND;
  END

  -- Договор об оказании платных образовательных услуг (образец)
  V$ID = NULL;
  SELECT FIRST 1 L17.OBJ_ID, V478.VAL, V478.BLOB_ID, V3503.VAL, V3503.BLOB_ID
  FROM LINKS L17
  JOIN VALL V471 ON V471.OBJ_ID = L17.OBJ_ID AND V471.PARAM_ID = 471 AND V471.IS_DEL = 0 AND V471.LISTVAL_ID = 18636  -- договор
  JOIN VALD V482 ON V482.OBJ_ID = L17.OBJ_ID AND V482.PARAM_ID = 482 AND V482.IS_DEL = 0                              -- дата выдачи
  JOIN VALS V596 ON V596.OBJ_ID = L17.OBJ_ID AND V596.PARAM_ID = 596 AND V596.IS_DEL = 0                              -- название
  JOIN VALB V478 ON V478.OBJ_ID = L17.OBJ_ID AND V478.PARAM_ID = 478 AND V478.IS_DEL = 0                              -- файл
  LEFT JOIN VALB V3503 ON V3503.OBJ_ID = L17.OBJ_ID AND V3503.PARAM_ID = 3503 AND V3503.IS_DEL = 0                    -- файл ЦП
  WHERE L17.PARENT_TYPE_ID = 2 AND L17.OBJ_TYPE_ID = 17 AND L17.DATE_DEL IS NULL
    AND V596.VAL CONTAINING 'оговор' AND V596.VAL CONTAINING 'платн' AND V596.VAL CONTAINING 'услуг'
  ORDER BY V482.VAL DESC
  INTO :V$ID, :S1, :BLOB_ID, :S3, :CBLOB_ID;
  IF (V$ID IS NOT NULL) THEN
  BEGIN
    -- Файл
    TAG_NAME = 'Договор_платные_услуги:Имеется';
    VAL = 1;
    SUSPEND;
    TAG_NAME = 'Договор_платные_услуги:file_name';
    VAL = S1;
    SUSPEND;
    TAG_NAME = 'Договор_платные_услуги:blob_id';
    VAL = BLOB_ID;
    SUSPEND;
    -- Файл с ЭЦП
    TAG_NAME = 'Договор_платные_услуги:ЭЦП:file_name';
    VAL = S3;
    SUSPEND;
    TAG_NAME = 'Договор_платные_услуги:ЭЦП:blob_src';
    VAL = BLOB_ID;
    SUSPEND;
    TAG_NAME = 'Договор_платные_услуги:ЭЦП:blob_id';
    VAL = CBLOB_ID;
    SUSPEND;
  END
  ELSE
  BEGIN
    TAG_NAME = 'Договор_платные_услуги:Имеется';
    VAL = 0;
    SUSPEND;
  END

  -- Стоимость образовательных платных услуг (ссылка на документ, год)
  V$ID = NULL;
  SELECT FIRST 1 L17.OBJ_ID, V478.VAL, V478.BLOB_ID, V3503.VAL, V3503.BLOB_ID, EXTRACT(YEAR FROM V482.VAL)
  FROM LINKS L17
  JOIN VALL V471 ON V471.OBJ_ID = L17.OBJ_ID AND V471.PARAM_ID = 471 AND V471.IS_DEL = 0 AND V471.LISTVAL_ID IN (18635, 18627)  -- Локальный нормативный акт или положение
  JOIN VALD V482 ON V482.OBJ_ID = L17.OBJ_ID AND V482.PARAM_ID = 482 AND V482.IS_DEL = 0                                        -- дата выдачи
  JOIN VALS V596 ON V596.OBJ_ID = L17.OBJ_ID AND V596.PARAM_ID = 596 AND V596.IS_DEL = 0                                        -- название
  JOIN VALB V478 ON V478.OBJ_ID = L17.OBJ_ID AND V478.PARAM_ID = 478 AND V478.IS_DEL = 0                                        -- файл
  LEFT JOIN VALB V3503 ON V3503.OBJ_ID = L17.OBJ_ID AND V3503.PARAM_ID = 3503 AND V3503.IS_DEL = 0                              -- файл ЦП
  WHERE L17.PARENT_TYPE_ID IN (2, 530) AND L17.OBJ_TYPE_ID = 17 AND L17.DATE_DEL IS NULL
    AND V596.VAL CONTAINING 'тоимость' AND V596.VAL CONTAINING 'платн' AND V596.VAL CONTAINING 'образова' AND V596.VAL CONTAINING 'услуг'
  ORDER BY V482.VAL DESC
  INTO :V$ID, :S1, :BLOB_ID, :S3, :CBLOB_ID, :S5;
  IF (V$ID IS NOT NULL) THEN
  BEGIN
    -- Файл
    TAG_NAME = 'Стоимость_платных_услуг:Имеется';
    VAL = 1;
    SUSPEND;
    TAG_NAME = 'Стоимость_платных_услуг:file_name';
    VAL = S1;
    SUSPEND;
    TAG_NAME = 'Стоимость_платных_услуг:blob_id';
    VAL = BLOB_ID;
    SUSPEND;
    TAG_NAME = 'Стоимость_платных_услуг:Год';
    VAL = S5;
    SUSPEND;
    -- Файл с ЭЦП
    TAG_NAME = 'Стоимость_платных_услуг:ЭЦП:file_name';
    VAL = S3;
    SUSPEND;
    TAG_NAME = 'Стоимость_платных_услуг:ЭЦП:blob_src';
    VAL = BLOB_ID;
    SUSPEND;
    TAG_NAME = 'Стоимость_платных_услуг:ЭЦП:blob_id';
    VAL = CBLOB_ID;
    SUSPEND;
  END
  ELSE
  BEGIN
    TAG_NAME = 'Стоимость_платных_услуг:Имеется';
    VAL = 0;
    SUSPEND;
  END

  -- Стоимость иных платных услуг (присмотр и уход, проживание и др.) (ссылка на документ, год)
  V$ID = NULL;
  SELECT FIRST 1 L17.OBJ_ID, V478.VAL, V478.BLOB_ID, V3503.VAL, V3503.BLOB_ID, EXTRACT(YEAR FROM V482.VAL)
  FROM LINKS L17
  JOIN VALL V471 ON V471.OBJ_ID = L17.OBJ_ID AND V471.PARAM_ID = 471 AND V471.IS_DEL = 0 AND V471.LISTVAL_ID IN (18635, 18627)  -- Локальный нормативный акт или положение
  JOIN VALD V482 ON V482.OBJ_ID = L17.OBJ_ID AND V482.PARAM_ID = 482 AND V482.IS_DEL = 0                                        -- дата выдачи
  JOIN VALS V596 ON V596.OBJ_ID = L17.OBJ_ID AND V596.PARAM_ID = 596 AND V596.IS_DEL = 0                                        -- название
  JOIN VALB V478 ON V478.OBJ_ID = L17.OBJ_ID AND V478.PARAM_ID = 478 AND V478.IS_DEL = 0                                        -- файл
  LEFT JOIN VALB V3503 ON V3503.OBJ_ID = L17.OBJ_ID AND V3503.PARAM_ID = 3503 AND V3503.IS_DEL = 0                              -- файл ЦП
  WHERE L17.PARENT_TYPE_ID IN (2, 530) AND L17.OBJ_TYPE_ID = 17 AND L17.DATE_DEL IS NULL
    AND V596.VAL CONTAINING 'тоимость' AND V596.VAL CONTAINING 'платн' AND V596.VAL CONTAINING 'иных' AND V596.VAL CONTAINING 'услуг'
  ORDER BY V482.VAL DESC
  INTO :V$ID, :S1, :BLOB_ID, :S3, :CBLOB_ID, :S5;
  IF (V$ID IS NOT NULL) THEN
  BEGIN
    -- Файл
    TAG_NAME = 'Стоимость_иных_платных_услуг:Имеется';
    VAL = 1;
    SUSPEND;
    TAG_NAME = 'Стоимость_иных_платных_услуг:file_name';
    VAL = S1;
    SUSPEND;
    TAG_NAME = 'Стоимость_иных_платных_услуг:blob_id';
    VAL = BLOB_ID;
    SUSPEND;
    TAG_NAME = 'Стоимость_иных_платных_услуг:Год';
    VAL = S5;
    SUSPEND;
    -- Файл с ЭЦП
    TAG_NAME = 'Стоимость_иных_платных_услуг:ЭЦП:file_name';
    VAL = S3;
    SUSPEND;
    TAG_NAME = 'Стоимость_иных_платных_услуг:ЭЦП:blob_src';
    VAL = BLOB_ID;
    SUSPEND;
    TAG_NAME = 'Стоимость_иных_платных_услуг:ЭЦП:blob_id';
    VAL = CBLOB_ID;
    SUSPEND;
  END
  ELSE
  BEGIN
    TAG_NAME = 'Стоимость_иных_платных_услуг:Имеется';
    VAL = 0;
    SUSPEND;
  END
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SITELOAD_DATA_18591 RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(4000))
AS
DECLARE VARIABLE V$ID BIGINT;
DECLARE VARIABLE S1 VARCHAR(1000);
DECLARE VARIABLE BLOB_ID BIGINT;
DECLARE VARIABLE S3 VARCHAR(1000);
DECLARE VARIABLE CBLOB_ID BIGINT;
DECLARE VARIABLE S5 VARCHAR(1000);
begin
  -- Справка об объеме образовательной деятельности  (ссылка на документ, год)
  V$ID = NULL;
  SELECT FIRST 1 L17.OBJ_ID, V478.VAL, V478.BLOB_ID, V3503.VAL, V3503.BLOB_ID, EXTRACT(YEAR FROM V482.VAL)
  FROM LINKS L17
  JOIN VALL V471 ON V471.OBJ_ID = L17.OBJ_ID AND V471.PARAM_ID = 471 AND V471.IS_DEL = 0 AND V471.LISTVAL_ID = 18634            -- справка
  JOIN VALD V482 ON V482.OBJ_ID = L17.OBJ_ID AND V482.PARAM_ID = 482 AND V482.IS_DEL = 0                                        -- дата выдачи
  JOIN VALS V596 ON V596.OBJ_ID = L17.OBJ_ID AND V596.PARAM_ID = 596 AND V596.IS_DEL = 0                                        -- название
  JOIN VALB V478 ON V478.OBJ_ID = L17.OBJ_ID AND V478.PARAM_ID = 478 AND V478.IS_DEL = 0                                        -- файл
  LEFT JOIN VALB V3503 ON V3503.OBJ_ID = L17.OBJ_ID AND V3503.PARAM_ID = 3503 AND V3503.IS_DEL = 0                              -- файл ЦП
  WHERE L17.PARENT_TYPE_ID = 2 AND L17.OBJ_TYPE_ID = 17 AND L17.DATE_DEL IS NULL
    AND V596.VAL CONTAINING 'объем' AND V596.VAL CONTAINING 'образовательн' AND V596.VAL CONTAINING 'деятельн'
  ORDER BY V482.VAL DESC
  INTO :V$ID, :S1, :BLOB_ID, :S3, :CBLOB_ID, :S5;
  IF (V$ID IS NOT NULL) THEN
  BEGIN
    -- Файл
    TAG_NAME = 'Справка_объем:Имеется';
    VAL = 1;
    SUSPEND;
    TAG_NAME = 'Справка_объем:file_name';
    VAL = S1;
    SUSPEND;
    TAG_NAME = 'Справка_объем:blob_id';
    VAL = BLOB_ID;
    SUSPEND;
    TAG_NAME = 'Справка_объем:Год';
    VAL = S5;
    SUSPEND;
    -- Файл с ЭЦП
    TAG_NAME = 'Справка_объем:ЭЦП:file_name';
    VAL = S3;
    SUSPEND;
    TAG_NAME = 'Справка_объем:ЭЦП:blob_src';
    VAL = BLOB_ID;
    SUSPEND;
    TAG_NAME = 'Справка_объем:ЭЦП:blob_id';
    VAL = CBLOB_ID;
    SUSPEND;
  END
  ELSE
  BEGIN
    TAG_NAME = 'Справка_объем:Имеется';
    VAL = 0;
    SUSPEND;
  END

  -- Финансовый отчет (ссылка на документ, год)
  V$ID = NULL;
  -- считаем, что финансовый отчет всегда делается за предыдущий год. Поэтому минус год от даты создания отчета
  SELECT FIRST 1 L17.OBJ_ID, V478.VAL, V478.BLOB_ID, V3503.VAL, V3503.BLOB_ID, EXTRACT(YEAR FROM DATEADD(- 1 YEAR TO V482.VAL))
  FROM LINKS L17
  JOIN VALL V471 ON V471.OBJ_ID = L17.OBJ_ID AND V471.PARAM_ID = 471 AND V471.IS_DEL = 0 AND V471.LISTVAL_ID = 18633            -- отчет
  JOIN VALD V482 ON V482.OBJ_ID = L17.OBJ_ID AND V482.PARAM_ID = 482 AND V482.IS_DEL = 0                                        -- дата выдачи
  JOIN VALS V596 ON V596.OBJ_ID = L17.OBJ_ID AND V596.PARAM_ID = 596 AND V596.IS_DEL = 0                                        -- название
  JOIN VALB V478 ON V478.OBJ_ID = L17.OBJ_ID AND V478.PARAM_ID = 478 AND V478.IS_DEL = 0                                        -- файл
  LEFT JOIN VALB V3503 ON V3503.OBJ_ID = L17.OBJ_ID AND V3503.PARAM_ID = 3503 AND V3503.IS_DEL = 0                              -- файл ЦП
  WHERE L17.PARENT_TYPE_ID = 2 AND L17.OBJ_TYPE_ID = 17 AND L17.DATE_DEL IS NULL
    AND V596.VAL CONTAINING 'инансовый' AND V596.VAL CONTAINING 'тчет'
  ORDER BY V482.VAL DESC
  INTO :V$ID, :S1, :BLOB_ID, :S3, :CBLOB_ID, :S5;
  IF (V$ID IS NOT NULL) THEN
  BEGIN
    -- Файл
    TAG_NAME = 'Финансовый_отчет:Имеется';
    VAL = 1;
    SUSPEND;
    TAG_NAME = 'Финансовый_отчет:file_name';
    VAL = S1;
    SUSPEND;
    TAG_NAME = 'Финансовый_отчет:blob_id';
    VAL = BLOB_ID;
    SUSPEND;
    TAG_NAME = 'Финансовый_отчет:Год';
    VAL = S5;
    SUSPEND;
    -- Файл с ЭЦП
    TAG_NAME = 'Финансовый_отчет:ЭЦП:file_name';
    VAL = S3;
    SUSPEND;
    TAG_NAME = 'Финансовый_отчет:ЭЦП:blob_src';
    VAL = BLOB_ID;
    SUSPEND;
    TAG_NAME = 'Финансовый_отчет:ЭЦП:blob_id';
    VAL = CBLOB_ID;
    SUSPEND;
  END
  ELSE
  BEGIN
    TAG_NAME = 'Финансовый_отчет:Имеется';
    VAL = 0;
    SUSPEND;
  END

  -- План финансово-хозяйственной деятельности (ссылка на документ, год)
  V$ID = NULL;
  SELECT FIRST 1 L17.OBJ_ID, V478.VAL, V478.BLOB_ID, V3503.VAL, V3503.BLOB_ID, EXTRACT(YEAR FROM V482.VAL)
  FROM LINKS L17
  JOIN VALL V471 ON V471.OBJ_ID = L17.OBJ_ID AND V471.PARAM_ID = 471 AND V471.IS_DEL = 0 AND V471.LISTVAL_ID IN (18635, 18627)  -- Локальный нормативный акт или положение
  JOIN VALD V482 ON V482.OBJ_ID = L17.OBJ_ID AND V482.PARAM_ID = 482 AND V482.IS_DEL = 0                                        -- дата выдачи
  JOIN VALS V596 ON V596.OBJ_ID = L17.OBJ_ID AND V596.PARAM_ID = 596 AND V596.IS_DEL = 0                                        -- название
  JOIN VALB V478 ON V478.OBJ_ID = L17.OBJ_ID AND V478.PARAM_ID = 478 AND V478.IS_DEL = 0                                        -- файл
  LEFT JOIN VALB V3503 ON V3503.OBJ_ID = L17.OBJ_ID AND V3503.PARAM_ID = 3503 AND V3503.IS_DEL = 0                              -- файл ЦП
  WHERE L17.PARENT_TYPE_ID IN (2, 530) AND L17.OBJ_TYPE_ID = 17 AND L17.DATE_DEL IS NULL
    AND V596.VAL CONTAINING 'лан' AND V596.VAL CONTAINING 'финансов' AND V596.VAL CONTAINING 'хозяйствен' AND V596.VAL CONTAINING 'деятельн'
  ORDER BY V482.VAL DESC
  INTO :V$ID, :S1, :BLOB_ID, :S3, :CBLOB_ID, :S5;
  IF (V$ID IS NOT NULL) THEN
  BEGIN
    -- Файл
    TAG_NAME = 'План_фин_хоз_деятельности:Имеется';
    VAL = 1;
    SUSPEND;
    TAG_NAME = 'План_фин_хоз_деятельности:file_name';
    VAL = S1;
    SUSPEND;
    TAG_NAME = 'План_фин_хоз_деятельности:blob_id';
    VAL = BLOB_ID;
    SUSPEND;
    TAG_NAME = 'План_фин_хоз_деятельности:Год';
    VAL = S5;
    SUSPEND;
    -- Файл с ЭЦП
    TAG_NAME = 'План_фин_хоз_деятельности:ЭЦП:file_name';
    VAL = S3;
    SUSPEND;
    TAG_NAME = 'План_фин_хоз_деятельности:ЭЦП:blob_src';
    VAL = BLOB_ID;
    SUSPEND;
    TAG_NAME = 'План_фин_хоз_деятельности:ЭЦП:blob_id';
    VAL = CBLOB_ID;
    SUSPEND;
  END
  ELSE
  BEGIN
    TAG_NAME = 'План_фин_хоз_деятельности:Имеется';
    VAL = 0;
    SUSPEND;
  END
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SITELOAD_DATA_18592 RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(4000))
AS
DECLARE VARIABLE V$ID BIGINT;
DECLARE VARIABLE S1 VARCHAR(1000);
DECLARE VARIABLE BLOB_ID BIGINT;
DECLARE VARIABLE S3 VARCHAR(1000);
DECLARE VARIABLE CBLOB_ID BIGINT;
DECLARE VARIABLE D1 DATE;
begin
  -- Вакантные места для приема (перевода) обучающихся
  V$ID = NULL;
  SELECT FIRST 1 L17.OBJ_ID, V478.VAL, V478.BLOB_ID, V3503.VAL, V3503.BLOB_ID, V482.VAL
  FROM LINKS L17
  JOIN VALL V471 ON V471.OBJ_ID = L17.OBJ_ID AND V471.PARAM_ID = 471 AND V471.IS_DEL = 0 AND V471.LISTVAL_ID = 18634            -- справка
  JOIN VALD V482 ON V482.OBJ_ID = L17.OBJ_ID AND V482.PARAM_ID = 482 AND V482.IS_DEL = 0                                        -- дата выдачи
  JOIN VALS V596 ON V596.OBJ_ID = L17.OBJ_ID AND V596.PARAM_ID = 596 AND V596.IS_DEL = 0                                        -- название
  JOIN VALB V478 ON V478.OBJ_ID = L17.OBJ_ID AND V478.PARAM_ID = 478 AND V478.IS_DEL = 0                                        -- файл
  LEFT JOIN VALB V3503 ON V3503.OBJ_ID = L17.OBJ_ID AND V3503.PARAM_ID = 3503 AND V3503.IS_DEL = 0                              -- файл ЦП
  WHERE L17.PARENT_TYPE_ID = 2 AND L17.OBJ_TYPE_ID = 17 AND L17.DATE_DEL IS NULL
    AND V596.VAL CONTAINING 'акантн' AND V596.VAL CONTAINING 'места'
  ORDER BY V482.VAL DESC
  INTO :V$ID, :S1, :BLOB_ID, :S3, :CBLOB_ID, :D1;
  IF (V$ID IS NOT NULL) THEN
  BEGIN
    -- Файл
    TAG_NAME = 'Вакантные_места_файл:Имеется';
    VAL = 1;
    SUSPEND;
    TAG_NAME = 'Вакантные_места_файл:file_name';
    VAL = S1;
    SUSPEND;
    TAG_NAME = 'Вакантные_места_файл:blob_id';
    VAL = BLOB_ID;
    SUSPEND;
    TAG_NAME = 'Вакантные_места_файл:на_дату';
    SELECT RESULT FROM DATE2STR(:D1) INTO :VAL;
    SUSPEND;
    TAG_NAME = 'Вакантные_места_файл:ЭЦП:file_name';
    VAL = S3;
    SUSPEND;
    TAG_NAME = 'Вакантные_места_файл:ЭЦП:blob_src';
    VAL = BLOB_ID;
    SUSPEND;
    TAG_NAME = 'Вакантные_места_файл:ЭЦП:blob_id';
    VAL = CBLOB_ID;
    SUSPEND;
  END
  ELSE
  BEGIN
    TAG_NAME = 'Вакантные_места_файл:Имеется';
    VAL = 0;
    SUSPEND;
  END
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SITELOAD_DATA_18593 RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(4000))
AS
DECLARE VARIABLE V$ID BIGINT;
DECLARE VARIABLE S1 VARCHAR(1000);
DECLARE VARIABLE BLOB_ID BIGINT;
DECLARE VARIABLE S3 VARCHAR(1000);
DECLARE VARIABLE CBLOB_ID BIGINT;
begin
  -- Стипендии и меры поддержки обучающихся. Текст по умолчанию: Стипендии обучающимся не предоставляются
  V$ID = NULL;
  SELECT FIRST 1 L17.OBJ_ID, V478.VAL, V478.BLOB_ID, V3503.VAL, V3503.BLOB_ID
  FROM LINKS L17
  JOIN VALL V471 ON V471.OBJ_ID = L17.OBJ_ID AND V471.PARAM_ID = 471 AND V471.IS_DEL = 0 AND V471.LISTVAL_ID IN (18627, 18635)  -- положение, локальный акт
  LEFT JOIN VALD V482 ON V482.OBJ_ID = L17.OBJ_ID AND V482.PARAM_ID = 482 AND V482.IS_DEL = 0                                   -- дата выдачи
  JOIN VALS V596 ON V596.OBJ_ID = L17.OBJ_ID AND V596.PARAM_ID = 596 AND V596.IS_DEL = 0                                        -- название
  JOIN VALB V478 ON V478.OBJ_ID = L17.OBJ_ID AND V478.PARAM_ID = 478 AND V478.IS_DEL = 0                                        -- файл
  LEFT JOIN VALB V3503 ON V3503.OBJ_ID = L17.OBJ_ID AND V3503.PARAM_ID = 3503 AND V3503.IS_DEL = 0                              -- файл ЦП
  WHERE L17.PARENT_TYPE_ID IN (2, 530) AND L17.OBJ_TYPE_ID = 17 AND L17.DATE_DEL IS NULL
    AND V596.VAL CONTAINING 'редоставлен' AND V596.VAL CONTAINING 'стипенд'
  ORDER BY V482.VAL DESC
  INTO :V$ID, :S1, :BLOB_ID, :S3, :CBLOB_ID;
  IF (V$ID IS NOT NULL) THEN
  BEGIN
    -- Файл
    TAG_NAME = 'Предоставление_стипендий_файл:Имеется';
    VAL = 1;
    SUSPEND;
    TAG_NAME = 'Предоставление_стипендий_файл:file_name';
    VAL = S1;
    SUSPEND;
    TAG_NAME = 'Предоставление_стипендий_файл:blob_id';
    VAL = BLOB_ID;
    SUSPEND;
    -- Файл с ЭЦП
    TAG_NAME = 'Предоставление_стипендий_файл:ЭЦП:file_name';
    VAL = S3;
    SUSPEND;
    TAG_NAME = 'Предоставление_стипендий_файл:ЭЦП:blob_src';
    VAL = BLOB_ID;
    SUSPEND;
    TAG_NAME = 'Предоставление_стипендий_файл_ЭЦП:blob_id';
    VAL = CBLOB_ID;
    SUSPEND;
  END
  ELSE
  BEGIN
    TAG_NAME = 'Предоставление_стипендий_файл:Имеется';
    VAL = 0;
    SUSPEND;
  END

  -- Наличие и условия предоставления обучающимся мер социальной поддержки. Текст по умолчанию: Меры социальной поддержки обучающимся предоставляются в соответствии с законодательством Российской Федерации и Санкт-Петербурга и включают льготы по проезду и питанию
  V$ID = NULL;
  SELECT FIRST 1 L17.OBJ_ID, V478.VAL, V478.BLOB_ID, V3503.VAL, V3503.BLOB_ID
  FROM LINKS L17
  JOIN VALL V471 ON V471.OBJ_ID = L17.OBJ_ID AND V471.PARAM_ID = 471 AND V471.IS_DEL = 0 AND V471.LISTVAL_ID IN (18627, 18635)  -- положение, локальный акт
  LEFT JOIN VALD V482 ON V482.OBJ_ID = L17.OBJ_ID AND V482.PARAM_ID = 482 AND V482.IS_DEL = 0                                   -- дата выдачи
  JOIN VALS V596 ON V596.OBJ_ID = L17.OBJ_ID AND V596.PARAM_ID = 596 AND V596.IS_DEL = 0                                        -- название
  JOIN VALB V478 ON V478.OBJ_ID = L17.OBJ_ID AND V478.PARAM_ID = 478 AND V478.IS_DEL = 0                                        -- файл
  LEFT JOIN VALB V3503 ON V3503.OBJ_ID = L17.OBJ_ID AND V3503.PARAM_ID = 3503 AND V3503.IS_DEL = 0                              -- файл ЦП
  WHERE L17.PARENT_TYPE_ID IN (2, 530) AND L17.OBJ_TYPE_ID = 17 AND L17.DATE_DEL IS NULL
    AND V596.VAL CONTAINING 'редоставлен' AND V596.VAL CONTAINING 'мер' AND V596.VAL CONTAINING 'социальн'
  ORDER BY V482.VAL DESC
  INTO :V$ID, :S1, :BLOB_ID, :S3, :CBLOB_ID;
  IF (V$ID IS NOT NULL) THEN
  BEGIN
    -- Файл
    TAG_NAME = 'Предоставление_мер_файл:Имеется';
    VAL = 1;
    SUSPEND;
    TAG_NAME = 'Предоставление_мер_файл:file_name';
    VAL = S1;
    SUSPEND;
    TAG_NAME = 'Предоставление_мер_файл:blob_id';
    VAL = BLOB_ID;
    SUSPEND;
    -- Файл с ЭЦП
    TAG_NAME = 'Предоставление_мер_файл:ЭЦП:file_name';
    VAL = S3;
    SUSPEND;
    TAG_NAME = 'Предоставление_мер_файл:ЭЦП:blob_src';
    VAL = BLOB_ID;
    SUSPEND;
    TAG_NAME = 'Предоставление_мер_файл:ЭЦП:blob_id';
    VAL = CBLOB_ID;
    SUSPEND;
  END
  ELSE
  BEGIN
    TAG_NAME = 'Предоставление_мер_файл:Имеется';
    VAL = 0;
    SUSPEND;
  END

  -- Общежитие, интернат
  VAL = 'Отсутствует';
  V$ID = NULL;
  SELECT L16.OBJ_ID, V421.VAL
  FROM LINKS L16
  JOIN VALL V485 ON V485.OBJ_ID = L16.OBJ_ID AND V485.PARAM_ID = 485 AND V485.IS_DEL = 0 AND V485.LISTVAL_ID = 1094 -- Общежитие
  JOIN VALS V421 ON V421.OBJ_ID = L16.OBJ_ID AND V421.PARAM_ID = 421 AND V421.IS_DEL = 0
  WHERE L16.PARENT_TYPE_ID = 73 AND L16.OBJ_TYPE_ID = 16 AND L16.DATE_DEL IS NULL
  INTO :V$ID, :VAL;
  TAG_NAME = 'Название_общежития';
  SUSPEND;

  SELECT COUNT(*)
  FROM LINKS L61
  JOIN VALL V526 ON V526.OBJ_ID = L61.OBJ_ID AND V526.PARAM_ID = 526 AND V526.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V526.LISTVAL_ID AND LV.LIST_ID = 20 AND LV.IS_DEL = 0 AND LV.PARENT_ID = 1159 -- Спальные помещения
  WHERE L61.PARENT_ID = :V$ID AND L61.OBJ_TYPE_ID = 61 AND L61.DATE_DEL IS NULL
  INTO :VAL;
  TAG_NAME = 'Количество_помещений_в_общежитии';
  SUSPEND;

  -- ищем по типу документа и имени положение о плате за проживание в общежитии
  V$ID = NULL;
  SELECT FIRST 1 L17.OBJ_ID, V478.VAL, V478.BLOB_ID, V3503.VAL, V3503.BLOB_ID
  FROM LINKS L17
  JOIN VALL V471 ON V471.OBJ_ID = L17.OBJ_ID AND V471.PARAM_ID = 471 AND V471.IS_DEL = 0 AND V471.LISTVAL_ID = 18635  -- положение
  JOIN VALL V613 ON V613.OBJ_ID = L17.OBJ_ID AND V613.PARAM_ID = 613 AND V613.IS_DEL = 0 AND V613.LISTVAL_ID = 1982   -- статус действующий
  JOIN VALD V482 ON V482.OBJ_ID = L17.OBJ_ID AND V482.PARAM_ID = 482 AND V482.IS_DEL = 0                              -- дата выдачи
  JOIN VALS V596 ON V596.OBJ_ID = L17.OBJ_ID AND V596.PARAM_ID = 596 AND V596.IS_DEL = 0                              -- название положения
  JOIN VALB V478 ON V478.OBJ_ID = L17.OBJ_ID AND V478.PARAM_ID = 478 AND V478.IS_DEL = 0                              -- файл
  LEFT JOIN VALB V3503 ON V3503.OBJ_ID = L17.OBJ_ID AND V3503.PARAM_ID = 3503 AND V3503.IS_DEL = 0                    -- файл ЦП
  WHERE L17.PARENT_TYPE_ID = 2 AND L17.OBJ_TYPE_ID = 17 AND L17.DATE_DEL IS NULL AND V596.VAL CONTAINING 'плат'
    AND V596.VAL CONTAINING 'общежити'
  ORDER BY V482.VAL DESC
  INTO :V$ID, :S1, :BLOB_ID, :S3, :CBLOB_ID;
  -- Файл с положением
  IF (V$ID IS NOT NULL) THEN
  BEGIN
    TAG_NAME = 'Плата_за_общежитие_положение:Имеется';
    VAL = 1;
    SUSPEND;
    TAG_NAME = 'Плата_за_общежитие_положение:file_name';
    VAL = S1;
    SUSPEND;
    TAG_NAME = 'Плата_за_общежитие_положение:blob_id';
    VAL = BLOB_ID;
    SUSPEND;
    -- Файл с ЭЦП
    TAG_NAME = 'Плата_за_общежитие_положение:ЭЦП:file_name';
    VAL = S3;
    SUSPEND;
    TAG_NAME = 'Плата_за_общежитие_положение:ЭЦП:blob_src';
    VAL = BLOB_ID;
    SUSPEND;
    TAG_NAME = 'Плата_за_общежитие_положение:ЭЦП:blob_id';
    VAL = CBLOB_ID;
    SUSPEND;
  END
  ELSE
  BEGIN
    TAG_NAME = 'Плата_за_общежитие_положение:Имеется';
    VAL = 0;
    SUSPEND;
  END
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SITELOAD_DATA_18594 RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(4000))
AS
DECLARE VARIABLE V$ID BIGINT;
DECLARE VARIABLE S1 VARCHAR(1000);
DECLARE VARIABLE S2 VARCHAR(1000);
DECLARE VARIABLE S3 VARCHAR(1000);
DECLARE VARIABLE S4 VARCHAR(1000);
begin
  TAG_NAME = 'Международное_сотрудничество::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT V596.VAL
    FROM LINKS L17
    JOIN VALL V471 ON V471.OBJ_ID = L17.OBJ_ID AND V471.PARAM_ID = 471 AND V471.IS_DEL = 0 AND V471.LISTVAL_ID = 18632  -- Договор о международном сотрудничестве
    LEFT JOIN VALD V482 ON V482.OBJ_ID = L17.OBJ_ID AND V482.PARAM_ID = 482 AND V482.IS_DEL = 0                         -- дата выдачи
    JOIN VALS V596 ON V596.OBJ_ID = L17.OBJ_ID AND V596.PARAM_ID = 596 AND V596.IS_DEL = 0                              -- название
    WHERE L17.PARENT_TYPE_ID = 2 AND L17.OBJ_TYPE_ID = 17 AND L17.DATE_DEL IS NULL
    ORDER BY V482.VAL
    INTO :S1
  DO
  BEGIN
    -- Файл
    TAG_NAME = 'Международное_сотрудничество:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'Международное_сотрудничество:r:Договор';
    VAL = S1;
    SUSPEND;
  END
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SITELOAD_DATA_18595 RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(4000))
AS
DECLARE VARIABLE V$ID BIGINT;
DECLARE VARIABLE S1 VARCHAR(1000);
DECLARE VARIABLE S2 VARCHAR(1000);
DECLARE VARIABLE S3 VARCHAR(1000);
DECLARE VARIABLE S4 VARCHAR(1000);
begin
  SELECT SRVC_INN, SRVC_NAME
  FROM FOOD_SERVICER_GET
  INTO :S1, :S2;
    
  TAG_NAME = 'Поставщик_ИНН';
  VAL = COALESCE(S1, 'Отсутствует');
  SUSPEND;
  TAG_NAME = 'Поставщик_Название';
  VAL = COALESCE(S2, 'Отсутствует');
  SUSPEND;

  TAG_NAME = 'Общепит::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT DISTINCT L61.PARENT_ID, V421.VAL, ADDR.VAL
    FROM LINKS L61
    JOIN VALS V421 ON V421.OBJ_ID = L61.PARENT_ID AND V421.PARAM_ID = 421 AND V421.IS_DEL = 0 -- здание
    JOIN ADR_GET(420, L61.PARENT_ID) ADDR ON 1 = 1                                            -- адрес
    WHERE L61.PARENT_TYPE_ID = 16 AND L61.OBJ_TYPE_ID = 61 AND L61.DATE_DEL IS NULL
    ORDER BY 2, 3
    INTO :V$ID, :S1, :S2
  DO
  BEGIN
    TAG_NAME = 'Общепит:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'Общепит:r:Здание';
    VAL = S1;
    SUSPEND;
    TAG_NAME = 'Общепит:r:Адрес';
    VAL = S2;
    SUSPEND;

    TAG_NAME = 'Общепит:r:Помещения::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT R.VAL, V532.VAL
      FROM LINKS L61
      JOIN VALI V532 ON V532.OBJ_ID = L61.OBJ_ID AND V532.PARAM_ID = 532 AND V532.IS_DEL = 0
      JOIN VALL V526 ON V526.OBJ_ID = L61.OBJ_ID AND V526.PARAM_ID = 526 AND V526.IS_DEL = 0
      JOIN LISTVALS LV ON LV.LISTVAL_ID = V526.LISTVAL_ID AND LV.LIST_ID = 20 AND LV.IS_DEL = 0 AND LV.PARENT_ID = 1154 --  Общепит
      JOIN RES R ON LV.RES_ID = R.RES_ID AND R.IS_DEL = 0 AND R.LANG_CODE = 'RU'
      WHERE L61.PARENT_ID = :V$ID AND L61.OBJ_TYPE_ID = 61 AND L61.DATE_DEL IS NULL
      INTO :S3, :S4
    DO
    BEGIN
      TAG_NAME = 'Общепит:r:Помещения:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'Общепит:r:Помещения:r:Название';
      VAL = S3;
      SUSPEND;
      TAG_NAME = 'Общепит:r:Помещения:r:Количество_посадочных_мест';
      VAL = S4;
      SUSPEND;
    END
  END
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SITELOAD_GET (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100) NOT NULL,
    VAL VARCHAR(4000))
AS
DECLARE VARIABLE V$TYPE_ID BIGINT;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$EN BIGINT;
DECLARE VARIABLE S VARCHAR(1000);
DECLARE VARIABLE V$TMPL VARCHAR(1000);
DECLARE VARIABLE V$URL VARCHAR(4000);
DECLARE VARIABLE V$DT TIMESTAMP;
DECLARE VARIABLE V$RESULT VARCHAR(1000);
begin

  -- Какой у нас тип объекта ?
  SELECT TYPE_ID
  FROM OBJECTS
  WHERE OBJ_ID = :I$OBJ_ID
  INTO :V$TYPE_ID;

  IF(V$TYPE_ID = 2) THEN
  BEGIN

    -- Список всех выгрузок + сведения о задаче в целом
    TAG_NAME = 'items::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT L514.OBJ_ID, V3520.LISTVAL_ID, C.VAL, V3519.LISTVAL_ID, V3521.VAL, V3522.VAL, V3523.VAL, V3524.VAL
      FROM LINKS L514
      JOIN VALL V3520 ON V3520.OBJ_ID = L514.OBJ_ID AND V3520.PARAM_ID = 3520 AND V3520.IS_DEL = 0
      LEFT JOIN LISTVAL_TEXT(V3520.LISTVAL_ID) C ON 1 = 1
      JOIN VALL V3519 ON V3519.OBJ_ID = L514.OBJ_ID AND V3519.PARAM_ID = 3519 AND V3519.IS_DEL = 0
      LEFT JOIN VALB V3521 ON V3521.OBJ_ID = L514.OBJ_ID AND V3521.PARAM_ID = 3521 AND V3521.IS_DEL = 0
      LEFT JOIN VALS V3522 ON V3522.OBJ_ID = L514.OBJ_ID AND V3522.PARAM_ID = 3522 AND V3522.IS_DEL = 0
      LEFT JOIN VALDT V3523 ON V3523.OBJ_ID = L514.OBJ_ID AND V3523.PARAM_ID = 3523 AND V3523.IS_DEL = 0
      LEFT JOIN VALS V3524 ON V3524.OBJ_ID = L514.OBJ_ID AND V3524.PARAM_ID = 3524 AND V3524.IS_DEL = 0
      WHERE L514.PARENT_ID = :I$OBJ_ID AND L514.OBJ_TYPE_ID = 514 AND L514.DATE_DEL IS NULL
      ORDER BY 2
      INTO :V$OBJ_ID, :V$TYPE_ID, :S, :V$EN, :V$TMPL, :V$URL, :V$DT, :V$RESULT
    DO
    BEGIN
      TAG_NAME = 'items:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'items:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'items:r:type_id';
      VAL = V$TYPE_ID;
      SUSPEND;
      TAG_NAME = 'items:r:type_name';
      VAL = S;
      SUSPEND;
      TAG_NAME = 'items:r:enabled';
      VAL = V$EN;
      SUSPEND;
      TAG_NAME = 'items:r:template';
      VAL = V$TMPL;
      SUSPEND;
      TAG_NAME = 'items:r:url';
      VAL = V$URL;
      SUSPEND;
      TAG_NAME = 'items:r:dt';
      VAL = (SELECT VAL FROM DATE2ISO(:V$DT, 1));
      SUSPEND;
      TAG_NAME = 'items:r:result';
      VAL = V$RESULT;
      SUSPEND;
    END

  END
  ELSE IF(V$TYPE_ID = 514) THEN
  BEGIN

    -- Конкретный файл выгрузки
    SELECT FIRST 1 L514.OBJ_ID, V3520.LISTVAL_ID, C.VAL, V3519.LISTVAL_ID, V3521.VAL, V3522.VAL, V3523.VAL, V3524.VAL
    FROM LINKS L514
    JOIN VALL V3520 ON V3520.OBJ_ID = L514.OBJ_ID AND V3520.PARAM_ID = 3520 AND V3520.IS_DEL = 0
    LEFT JOIN LISTVAL_TEXT(V3520.LISTVAL_ID) C ON 1 = 1
    JOIN VALL V3519 ON V3519.OBJ_ID = L514.OBJ_ID AND V3519.PARAM_ID = 3519 AND V3519.IS_DEL = 0
    LEFT JOIN VALB V3521 ON V3521.OBJ_ID = L514.OBJ_ID AND V3521.PARAM_ID = 3521 AND V3521.IS_DEL = 0
    LEFT JOIN VALS V3522 ON V3522.OBJ_ID = L514.OBJ_ID AND V3522.PARAM_ID = 3522 AND V3522.IS_DEL = 0
    LEFT JOIN VALDT V3523 ON V3523.OBJ_ID = L514.OBJ_ID AND V3523.PARAM_ID = 3523 AND V3523.IS_DEL = 0
    LEFT JOIN VALS V3524 ON V3524.OBJ_ID = L514.OBJ_ID AND V3524.PARAM_ID = 3524 AND V3524.IS_DEL = 0
    WHERE L514.PARENT_TYPE_ID = 2 AND L514.OBJ_ID = :I$OBJ_ID AND L514.OBJ_TYPE_ID = 514 AND L514.DATE_DEL IS NULL
    INTO :V$OBJ_ID, :V$TYPE_ID, :S, :V$EN, :V$TMPL, :V$URL, :V$DT, :V$RESULT;

    IF(V$OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Элемент не найден';

    TAG_NAME = 'id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'type_id';
    VAL = V$TYPE_ID;
    SUSPEND;
    TAG_NAME = 'type_name';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'enabled';
    VAL = V$EN;
    SUSPEND;
    TAG_NAME = 'template';
    VAL = V$TMPL;
    SUSPEND;
    TAG_NAME = 'url';
    VAL = V$URL;
    SUSPEND;
    TAG_NAME = 'dt';
    VAL = (SELECT VAL FROM DATE2ISO(:V$DT, 1));
    SUSPEND;
    TAG_NAME = 'result';
    VAL = V$RESULT;
    SUSPEND;

  END
  ELSE
    EXCEPTION DATA_ERROR 'Недопустимый тип объекта';

  -- Справочник для выбора типов пакетов
  TAG_NAME = 'types::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L.LISTVAL_ID, L.VAL
    FROM LISTVALS_LIST(373) L
    WHERE L.IS_DEL = 0
    INTO :V$OBJ_ID, :S
  DO
  BEGIN
    TAG_NAME = 'types:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'types:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'types:r:value';
    VAL = S;
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SITELOAD_STATUS (
    I$OBJ_ID BIGINT,
    I$STATUS VARCHAR(4000))
AS
begin

  -- Сохраняем данные прямо в таблицу, чтобы не логгировалась история
  IF(I$STATUS IS NULL) THEN I$STATUS = 'Успешно';

  UPDATE OR INSERT INTO VALS
  (OBJ_ID, PARAM_ID, VAL, IS_DEL)
  VALUES (:I$OBJ_ID, 3524, :I$STATUS, 0)
  MATCHING (OBJ_ID, PARAM_ID);

  UPDATE OR INSERT INTO VALDT
  (OBJ_ID, PARAM_ID, VAL, IS_DEL)
  VALUES (:I$OBJ_ID, 3523, CURRENT_TIMESTAMP, 0)
  MATCHING (OBJ_ID, PARAM_ID);

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SMIR_MOVE_ENTER (
    I$OU_ID BIGINT)
RETURNS (
    STUDENT_ID BIGINT,
    NAME_LAST VARCHAR(1000),
    STAGE_ID BIGINT,
    STAGE_INDEX BIGINT,
    GRADE_ID BIGINT,
    PAPER_DATE DATE,
    ORDER_DATE DATE,
    ORDER_NUM VARCHAR(1000),
    DOG_DATE DATE)
AS
declare variable V$YEAR_ID bigint;
declare variable V$YEAR_VAL integer;
declare variable V$TYPE smallint;
declare variable V$MATCH smallint;
declare variable V$ORDER_NUM varchar(1000);
declare variable V$ORDER_DATE date;
begin

  -- Возвращает список учащихся, зачисленных или зачисляемых в текущем учебном году

  SELECT V1236.LISTVAL_ID, LV.COST
  FROM VALL V1236
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE V1236.OBJ_ID = :I$OU_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  INTO :V$YEAR_ID, :V$YEAR_VAL;

  FOR
      -- Действующие учащиеся
      SELECT L10.OBJ_ID, V55.VAL, L8.OBJ_ID, V49.LISTVAL_ID, L9.OBJ_ID, V2716.VAL, V2442.VAL, V2443.VAL, V3001.VAL, 0
      FROM LINKS L7
      JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
      JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
      JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      JOIN VALS V55 ON V55.OBJ_ID = L10.OBJ_ID AND V55.PARAM_ID = 55 AND V55.IS_DEL = 0
      LEFT JOIN VALD V2716 ON V2716.OBJ_ID = L10.OBJ_ID AND V2716.PARAM_ID = 2716 AND V2716.IS_DEL = 0
      LEFT JOIN VALD V2442 ON V2442.OBJ_ID = L10.OBJ_ID AND V2442.PARAM_ID = 2442 AND V2442.IS_DEL = 0
      LEFT JOIN VALS V2443 ON V2443.OBJ_ID = L10.OBJ_ID AND V2443.PARAM_ID = 2443 AND V2443.IS_DEL = 0
      LEFT JOIN VALD V3001 ON V3001.OBJ_ID = L10.OBJ_ID AND V3001.PARAM_ID = 3001 AND V3001.IS_DEL = 0
      WHERE L7.PARENT_ID = :I$OU_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
      -- Предварительный прием
      UNION
      SELECT L10.OBJ_ID, V55.VAL, L290.OBJ_ID, V2346.LISTVAL_ID, L77.OBJ_ID, V2716.VAL, V2442.VAL, V2443.VAL, V3001.VAL, 1
      FROM LINKS L77
      JOIN LINKS L290 ON L290.PARENT_ID = L77.OBJ_ID AND L290.OBJ_TYPE_ID = 290 AND L290.DATE_DEL IS NULL
      JOIN VALL V2346 ON V2346.OBJ_ID = L290.OBJ_ID AND V2346.PARAM_ID = 2346 AND V2346.IS_DEL = 0
      JOIN LINKS L10 ON L10.PARENT_ID = L290.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      JOIN VALS V55 ON V55.OBJ_ID = L10.OBJ_ID AND V55.PARAM_ID = 55 AND V55.IS_DEL = 0
      LEFT JOIN VALD V2716 ON V2716.OBJ_ID = L10.OBJ_ID AND V2716.PARAM_ID = 2716 AND V2716.IS_DEL = 0
      LEFT JOIN VALD V2442 ON V2442.OBJ_ID = L10.OBJ_ID AND V2442.PARAM_ID = 2442 AND V2442.IS_DEL = 0
      LEFT JOIN VALS V2443 ON V2443.OBJ_ID = L10.OBJ_ID AND V2443.PARAM_ID = 2443 AND V2443.IS_DEL = 0
      LEFT JOIN VALD V3001 ON V3001.OBJ_ID = L10.OBJ_ID AND V3001.PARAM_ID = 3001 AND V3001.IS_DEL = 0
      WHERE L77.PARENT_ID = :I$OU_ID AND L77.OBJ_TYPE_ID = 77 AND L77.DATE_DEL IS NULL
      -- Выбывшие в текущем году, и также принятые в текущем году
      UNION
      SELECT L10.OBJ_ID, V55.VAL, NULL, NULL, NULL, V2716.VAL, V2442.VAL, V2443.VAL, V3001.VAL, 2
      FROM LINKS L78
      JOIN LINKS L82 ON L82.PARENT_ID = L78.OBJ_ID AND L82.OBJ_TYPE_ID = 82 AND L82.DATE_DEL IS NULL
      JOIN VALI V448 ON V448.OBJ_ID = L82.OBJ_ID AND V448.PARAM_ID = 448 AND V448.IS_DEL = 0 AND V448.VAL = :V$YEAR_VAL
      JOIN LINKS L10 ON L10.PARENT_ID = L82.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      JOIN VALS V55 ON V55.OBJ_ID = L10.OBJ_ID AND V55.PARAM_ID = 55 AND V55.IS_DEL = 0
      LEFT JOIN VALD V2716 ON V2716.OBJ_ID = L10.OBJ_ID AND V2716.PARAM_ID = 2716 AND V2716.IS_DEL = 0
      LEFT JOIN VALD V2442 ON V2442.OBJ_ID = L10.OBJ_ID AND V2442.PARAM_ID = 2442 AND V2442.IS_DEL = 0
      LEFT JOIN VALS V2443 ON V2443.OBJ_ID = L10.OBJ_ID AND V2443.PARAM_ID = 2443 AND V2443.IS_DEL = 0
      LEFT JOIN VALD V3001 ON V3001.OBJ_ID = L10.OBJ_ID AND V3001.PARAM_ID = 3001 AND V3001.IS_DEL = 0
      WHERE L78.PARENT_ID = :I$OU_ID AND L78.OBJ_TYPE_ID = 78 AND L78.DATE_DEL IS NULL
      INTO :STUDENT_ID, :NAME_LAST, :STAGE_ID, :STAGE_INDEX, :GRADE_ID, :PAPER_DATE, :ORDER_DATE, :ORDER_NUM, :DOG_DATE, :V$TYPE
  DO
  BEGIN
      V$ORDER_DATE = NULL;
      V$ORDER_NUM = NULL;
      -- Для действующих учащихся проверяем, что прибыли в текущем учебном году, и заменяем номер приказа
      IF(V$TYPE = 0) THEN
      BEGIN
          V$MATCH = 0;
          SELECT FIRST 1 1, V435.VAL, V434.VAL
          FROM LINKS L76
          JOIN VALL V432 ON V432.OBJ_ID = L76.OBJ_ID AND V432.PARAM_ID = 432 AND V432.IS_DEL = 0
          JOIN LISTVALS LV ON LV.LISTVAL_ID = V432.LISTVAL_ID AND LV."FILTER" LIKE '%ACCEPTED%'
          JOIN VALD V433 ON V433.OBJ_ID = L76.OBJ_ID AND V433.PARAM_ID = 433 AND V433.IS_DEL = 0 AND V433.VAL >= '25.08.' || :V$YEAR_VAL
          LEFT JOIN VALD V435 ON V435.OBJ_ID = L76.OBJ_ID AND V435.PARAM_ID = 435 AND V435.IS_DEL = 0
          LEFT JOIN VALS V434 ON V434.OBJ_ID = L76.OBJ_ID AND V434.PARAM_ID = 434 AND V434.IS_DEL = 0
          WHERE L76.PARENT_ID = :STUDENT_ID AND L76.OBJ_TYPE_ID = 76 AND L76.DATE_DEL IS NULL
          ORDER BY V433.VAL DESC
          INTO :V$MATCH, :V$ORDER_DATE, :V$ORDER_NUM;

          IF(ORDER_DATE IS NULL) THEN ORDER_DATE = V$ORDER_DATE;
          IF(ORDER_NUM IS NULL) THEN ORDER_NUM = V$ORDER_NUM;
      END
      -- Для предварительного приема всегда ОК
      ELSE IF(V$TYPE = 1) THEN V$MATCH = 1;
      -- Для выбывших проверяем дату зачисления, и восстанавливаем этап и коллектив
      ELSE IF(V$TYPE = 2) THEN
      BEGIN
          V$MATCH = 0;
          SELECT FIRST 1 1, V435.VAL, V434.VAL
          FROM LINKS L76
          JOIN VALL V432 ON V432.OBJ_ID = L76.OBJ_ID AND V432.PARAM_ID = 432 AND V432.IS_DEL = 0
          JOIN LISTVALS LV ON LV.LISTVAL_ID = V432.LISTVAL_ID AND LV."FILTER" LIKE '%ACCEPTED%'
          JOIN VALD V433 ON V433.OBJ_ID = L76.OBJ_ID AND V433.PARAM_ID = 433 AND V433.IS_DEL = 0 AND V433.VAL >= '25.08.' || :V$YEAR_VAL
          LEFT JOIN VALD V435 ON V435.OBJ_ID = L76.OBJ_ID AND V435.PARAM_ID = 435 AND V435.IS_DEL = 0
          LEFT JOIN VALS V434 ON V434.OBJ_ID = L76.OBJ_ID AND V434.PARAM_ID = 434 AND V434.IS_DEL = 0
          WHERE L76.PARENT_ID = :STUDENT_ID AND L76.OBJ_TYPE_ID = 76 AND L76.DATE_DEL IS NULL
          ORDER BY V433.VAL DESC
          INTO :V$MATCH, :V$ORDER_DATE, :V$ORDER_NUM;

          SELECT FIRST 1 V436.LISTVAL_ID, V438.VAL
          FROM LINKS L76
          JOIN VALL V432 ON V432.OBJ_ID = L76.OBJ_ID AND V432.PARAM_ID = 432 AND V432.IS_DEL = 0
          JOIN LISTVALS LV ON LV.LISTVAL_ID = V432.LISTVAL_ID AND (LV."FILTER" LIKE '%ACCEPTED%' OR LV."FILTER" LIKE '%TRANSFERED%')
          JOIN VALD V433 ON V433.OBJ_ID = L76.OBJ_ID AND V433.PARAM_ID = 433 AND V433.IS_DEL = 0 AND V433.VAL >= '25.08.' || :V$YEAR_VAL
          JOIN VALL V436 ON V436.OBJ_ID = L76.OBJ_ID AND V436.PARAM_ID = 436 AND V436.IS_DEL = 0
          JOIN VALR V438 ON V438.OBJ_ID = L76.OBJ_ID AND V438.PARAM_ID = 438 AND V438.IS_DEL = 0
          WHERE L76.PARENT_ID = :STUDENT_ID AND L76.OBJ_TYPE_ID = 76 AND L76.DATE_DEL IS NULL
          ORDER BY V433.VAL DESC
          INTO :STAGE_INDEX, :GRADE_ID;

          IF(ORDER_DATE IS NULL) THEN ORDER_DATE = V$ORDER_DATE;
          IF(ORDER_NUM IS NULL) THEN ORDER_NUM = V$ORDER_NUM;
      END

      IF(V$MATCH = 1 AND EXISTS(SELECT 1 FROM OBJECTS WHERE OBJ_ID = :GRADE_ID AND TYPE_ID = 187)) THEN V$MATCH = 0;

      IF(V$MATCH = 1) THEN SUSPEND;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SMIR_MOVE_ERR_REPORT (
    I$OBJ_ID BIGINT,
    I$TYPE SMALLINT = null)
RETURNS (
    VAL VARCHAR(4000))
AS
declare variable V$TYPE bigint;
declare variable V$STUDENT_ID bigint;
declare variable V$GRADE_ID bigint;
declare variable V$PAPER_DATE date;
declare variable V$ORDER_DATE date;
declare variable V$DOG_DATE date;
declare variable V$ORDER_NUM varchar(1000);
declare variable V$STAGE_NAME varchar(100);
declare variable N integer;
declare variable S varchar(1000);
declare variable N1 integer;
declare variable N2 integer;
declare variable N3 integer;
declare variable N4 integer;
declare variable V$OU_LICENCE_TYPE char(1);
begin

  SELECT TYPE_ID
  FROM OBJECTS
  WHERE OBJ_ID = :I$OBJ_ID
  INTO :V$TYPE;

  IF(V$TYPE = 162) THEN
  BEGIN
      SELECT PARENT_ID
      FROM LINKS
      WHERE OBJ_ID = :I$OBJ_ID AND PARENT_TYPE_ID = 2 AND DATE_DEL IS NULL
      INTO :I$OBJ_ID;
  END

  SELECT STATUS FROM OU_LICENCE_TYPE INTO :V$OU_LICENCE_TYPE;

  N1 = 0;
  N2 = 0;
  N3 = 0;
  N4 = 0;

  -- Таблица стилей
  VAL = '<!DOCTYPE html>';
  VAL = VAL || '<html lang="ru">';
  VAL = VAL || '<head>';
  VAL = VAL || '<meta charset="utf-8" />';

  VAL = VAL || '<style>';
  VAL = VAL || 'html { font-family: Tahoma, Verdana, Arial;';
  VAL = VAL || 'font-size: 10pt; ';
  VAL = VAL || '} ';
  VAL = VAL || 'table { border-collapse: collapse; width: 100%; }';
  VAL = VAL || 'th { border-bottom: 2px solid lightgray; text-align: left; }';
  VAL = VAL || '.e { background-color: #f7f7f7; }';
  VAL = VAL || 'th, td { padding: 0.4em 0.8em }';
  VAL = VAL || '.bordered th, .bordered td { border: 1px solid lightgray; }';
  VAL = VAL || '</style>';

  VAL = VAL || '</head>';
  VAL = VAL || '<body style="padding: 8px;">';
  SUSPEND;

  VAL = '@totals';
  SUSPEND;

  VAL = '<h2>Приказ о зачислении издан с нарушением сроков</h2>';
  VAL = VAL || '<table>';
  VAL = VAL || '<tr>';
  VAL = VAL || '<th>Этап обучения</th>';
  VAL = VAL || '<th>Учебный коллектив</th>';
  VAL = VAL || '<th>ФИО</th>';
  VAL = VAL || '<th>Дата регистрации заявления</th>';
  IF(V$OU_LICENCE_TYPE = 'D') THEN VAL = VAL || '<th>Дата заключения договора</th>';
  VAL = VAL || '<th>Дата приказа</th>';
  VAL = VAL || '<th>Номер приказа</th>';
  VAL = VAL || '</tr>';
  SUSPEND;
  N = 0;
  FOR
      SELECT M.STUDENT_ID, M.NAME_LAST, R.VAL, M.GRADE_ID, M.PAPER_DATE, M.ORDER_DATE, M.ORDER_NUM, M.DOG_DATE
      FROM SMIR_MOVE_ENTER(:I$OBJ_ID) M
      JOIN LISTVALS LV ON LV.LISTVAL_ID = M.STAGE_INDEX
      JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
      JOIN VALL V78 ON V78.OBJ_ID = M.STUDENT_ID AND V78.PARAM_ID = 78 AND V78.IS_DEL = 0 AND V78.LISTVAL_ID IN (817, 3274) -- ранее не обучавшиеся
      -- 7 рабочих дней с даты
      LEFT JOIN WORK_DIFF(M.ORDER_DATE, -7) WD ON 1 = 1
      WHERE M.PAPER_DATE > M.ORDER_DATE OR M.PAPER_DATE < WD.RESULT OR M.PAPER_DATE IS NULL
      ORDER BY M.STAGE_INDEX, 2
      INTO :V$STUDENT_ID, :S, :V$STAGE_NAME, :V$GRADE_ID, :V$PAPER_DATE, :V$ORDER_DATE, :V$ORDER_NUM, :V$DOG_DATE
  DO
  BEGIN
      IF(N = 0) THEN VAL = '<tr class="o">'; ELSE VAL = '<tr class="e">';
      IF(N = 0) THEN N = 1; ELSE N = 0;
      VAL = VAL || '<td>' || V$STAGE_NAME || '</td>';
      VAL = VAL || '<td>' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$GRADE_ID)) || '</td>';

      VAL = VAL || '<td>';
      VAL = VAL || S || ' ';
      S = NULL;
      SELECT VAL FROM VALS WHERE OBJ_ID = :V$STUDENT_ID AND PARAM_ID = 56 AND IS_DEL = 0 INTO :S;
      VAL = VAL || COALESCE(S, '') || ' ';
      S = NULL;
      SELECT VAL FROM VALS WHERE OBJ_ID = :V$STUDENT_ID AND PARAM_ID = 57 AND IS_DEL = 0 INTO :S;
      VAL = VAL || COALESCE(S, '');
      VAL = VAL || '</td>';

      VAL = VAL || '<td>' || COALESCE((SELECT RESULT FROM DATE2STR(:V$PAPER_DATE)), '') || '</td>';
      IF(V$OU_LICENCE_TYPE = 'D') THEN VAL = VAL || '<td>' || (SELECT COALESCE(RESULT, '') FROM DATE2STR(:V$DOG_DATE)) || '</td>';

      VAL = VAL || '<td>' || COALESCE((SELECT RESULT FROM DATE2STR(:V$ORDER_DATE)), '') || '</td>';
      VAL = VAL || '<td>' || COALESCE(V$ORDER_NUM, '') || '</td>';
      VAL = VAL || '</tr>';
      SUSPEND;
      N1 = N1 + 1;
  END
  VAL = '</table>';
  SUSPEND;

  VAL = '<h2>Приказ о зачислении в порядке перевода издан с нарушением сроков</h2>';
  VAL = VAL || '<table>';
  VAL = VAL || '<tr>';
  VAL = VAL || '<th>Этап обучения</th>';
  VAL = VAL || '<th>Учебный коллектив</th>';
  VAL = VAL || '<th>ФИО</th>';
  VAL = VAL || '<th>Дата регистрации заявления</th>';
  IF(V$OU_LICENCE_TYPE = 'D') THEN VAL = VAL || '<th>Дата заключения договора</th>';
  VAL = VAL || '<th>Дата приказа</th>';
  VAL = VAL || '<th>Номер приказа</th>';
  VAL = VAL || '</tr>';
  SUSPEND;
  N = 0;
  FOR
      SELECT M.STUDENT_ID, M.NAME_LAST, R.VAL, M.GRADE_ID, M.PAPER_DATE, M.ORDER_DATE, M.ORDER_NUM, M.DOG_DATE
      FROM SMIR_MOVE_ENTER(:I$OBJ_ID) M
      JOIN LISTVALS LV ON LV.LISTVAL_ID = M.STAGE_INDEX
      JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
      JOIN VALL V78 ON V78.OBJ_ID = M.STUDENT_ID AND V78.PARAM_ID = 78 AND V78.IS_DEL = 0 AND V78.LISTVAL_ID NOT IN (817, 3274) -- все прочие кроме ранее не обучавшихся
      LEFT JOIN WORK_DIFF(M.ORDER_DATE, -3) WD ON 1 = 1
      WHERE M.PAPER_DATE > M.ORDER_DATE OR M.PAPER_DATE < WD.RESULT
      ORDER BY M.STAGE_INDEX, 2
      INTO :V$STUDENT_ID, :S, :V$STAGE_NAME, :V$GRADE_ID, :V$PAPER_DATE, :V$ORDER_DATE, :V$ORDER_NUM, :V$DOG_DATE
  DO
  BEGIN
      IF(N = 0) THEN VAL = '<tr class="o">'; ELSE VAL = '<tr class="e">';
      IF(N = 0) THEN N = 1; ELSE N = 0;
      VAL = VAL || '<td>' || V$STAGE_NAME || '</td>';
      VAL = VAL || '<td>' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$GRADE_ID)) || '</td>';

      VAL = VAL || '<td>';
      VAL = VAL || S || ' ';
      S = NULL;
      SELECT VAL FROM VALS WHERE OBJ_ID = :V$STUDENT_ID AND PARAM_ID = 56 AND IS_DEL = 0 INTO :S;
      VAL = VAL || COALESCE(S, '') || ' ';
      S = NULL;
      SELECT VAL FROM VALS WHERE OBJ_ID = :V$STUDENT_ID AND PARAM_ID = 57 AND IS_DEL = 0 INTO :S;
      VAL = VAL || COALESCE(S, '');
      VAL = VAL || '</td>';

      VAL = VAL || '<td>' || COALESCE((SELECT RESULT FROM DATE2STR(:V$PAPER_DATE)), '') || '</td>';
      IF(V$OU_LICENCE_TYPE = 'D') THEN VAL = VAL || '<td>' || (SELECT COALESCE(RESULT, '') FROM DATE2STR(:V$DOG_DATE)) || '</td>';

      VAL = VAL || '<td>' || COALESCE((SELECT RESULT FROM DATE2STR(:V$ORDER_DATE)), '') || '</td>';
      VAL = VAL || '<td>' || COALESCE(V$ORDER_NUM, '') || '</td>';
      VAL = VAL || '</tr>';
      SUSPEND;
      N2 = N2 + 1;
  END
  VAL = '</table>';
  SUSPEND;

  VAL = '<h2>Отсутствует приказ об отчислении</h2>';
  VAL = VAL || '<table>';
  VAL = VAL || '<tr>';
  VAL = VAL || '<th>ФИО</th>';
  VAL = VAL || '<th>Дата регистрации заявления</th>';
  VAL = VAL || '</tr>';
  SUSPEND;
  N = 0;
  FOR
      SELECT M.STUDENT_ID, M.NAME_LAST, M.PAPER_DATE
      FROM SMIR_MOVE_LEAVE(:I$OBJ_ID) M
      LEFT JOIN WORK_DIFF(CURRENT_DATE, -3) WD ON 1 = 1
      WHERE M.ORDER_DATE IS NULL AND M.PAPER_DATE < WD.RESULT
      ORDER BY M.STAGE_INDEX, 2
      INTO :V$STUDENT_ID, :S, :V$PAPER_DATE
  DO
  BEGIN
      IF(N = 0) THEN VAL = '<tr class="o">'; ELSE VAL = '<tr class="e">';
      IF(N = 0) THEN N = 1; ELSE N = 0;

      VAL = VAL || '<td>';
      VAL = VAL || S || ' ';
      S = NULL;
      SELECT VAL FROM VALS WHERE OBJ_ID = :V$STUDENT_ID AND PARAM_ID = 56 AND IS_DEL = 0 INTO :S;
      VAL = VAL || COALESCE(S, '') || ' ';
      S = NULL;
      SELECT VAL FROM VALS WHERE OBJ_ID = :V$STUDENT_ID AND PARAM_ID = 57 AND IS_DEL = 0 INTO :S;
      VAL = VAL || COALESCE(S, '');
      VAL = VAL || '</td>';

      VAL = VAL || '<td>' || COALESCE((SELECT RESULT FROM DATE2STR(:V$PAPER_DATE)), '') || '</td>';
      VAL = VAL || '</tr>';
      SUSPEND;
      N3 = N3 + 1;
  END
  VAL = '</table>';
  SUSPEND;

  VAL = '<h2>Приказ об отчислении в порядке перевода издан с нарушением сроков</h2>';
  VAL = VAL || '<table>';
  VAL = VAL || '<tr>';
  VAL = VAL || '<th>ФИО</th>';
  VAL = VAL || '<th>Дата регистрации заявления</th>';
  VAL = VAL || '<th>Дата приказа</th>';
  VAL = VAL || '<th>Номер приказа</th>';
  VAL = VAL || '</tr>';
  SUSPEND;
  N = 0;
  FOR
      SELECT M.STUDENT_ID, M.NAME_LAST, M.PAPER_DATE, M.ORDER_DATE, M.ORDER_NUM
      FROM SMIR_MOVE_LEAVE(:I$OBJ_ID) M
      LEFT JOIN WORK_DIFF(M.ORDER_DATE, -3) WD ON 1 = 1
      WHERE M.PAPER_DATE > M.ORDER_DATE OR M.PAPER_DATE < WD.RESULT
      ORDER BY M.STAGE_INDEX, 2
      INTO :V$STUDENT_ID, :S, :V$PAPER_DATE, :V$ORDER_DATE, :V$ORDER_NUM
  DO
  BEGIN
      IF(N = 0) THEN VAL = '<tr class="o">'; ELSE VAL = '<tr class="e">';
      IF(N = 0) THEN N = 1; ELSE N = 0;

      VAL = VAL || '<td>';
      VAL = VAL || S || ' ';
      S = NULL;
      SELECT VAL FROM VALS WHERE OBJ_ID = :V$STUDENT_ID AND PARAM_ID = 56 AND IS_DEL = 0 INTO :S;
      VAL = VAL || COALESCE(S, '') || ' ';
      S = NULL;
      SELECT VAL FROM VALS WHERE OBJ_ID = :V$STUDENT_ID AND PARAM_ID = 57 AND IS_DEL = 0 INTO :S;
      VAL = VAL || COALESCE(S, '');
      VAL = VAL || '</td>';

      VAL = VAL || '<td>' || COALESCE((SELECT RESULT FROM DATE2STR(:V$PAPER_DATE)), '') || '</td>';
      VAL = VAL || '<td>' || COALESCE((SELECT RESULT FROM DATE2STR(:V$ORDER_DATE)), '') || '</td>';
      VAL = VAL || '<td>' || V$ORDER_NUM || '</td>';
      VAL = VAL || '</tr>';
      SUSPEND;
      N4 = N4 + 1;
  END
  VAL = '</table>';
  SUSPEND;

  VAL = '</body></html>';
  SUSPEND;

  -- Итоговая часть, которую нужно переставить в начало документа
  VAL = '@@totals';
  SUSPEND;

  VAL = '<h2>Нарушения порядка приема и отчисления</h2>';
  VAL = VAL || '<table class="bordered">';
  VAL = VAL || '<tr>';
  VAL = VAL || '<th style="width: 25%;">Приказ о зачислении издан с нарушением сроков</th>';
  VAL = VAL || '<th style="width: 25%;">Приказ о зачислении в порядке перевода издан с нарушением сроков</th>';
  VAL = VAL || '<th style="width: 25%;">Отсутствует приказ об отчислении</th>';
  VAL = VAL || '<th style="width: 25%;">Приказ об отчислении в порядке перевода издан с нарушением сроков</th>';
  VAL = VAL || '</tr>';
  VAL = VAL || '<tr>';
  VAL = VAL || '<td>' || N1 || '</td>';
  VAL = VAL || '<td>' || N2 || '</td>';
  VAL = VAL || '<td>' || N3 || '</td>';
  VAL = VAL || '<td>' || N4 || '</td>';
  VAL = VAL || '</tr>';
  VAL = VAL || '</table>';
  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SMIR_MOVE_ERR_REPORT_2 (
    I$OBJ_ID BIGINT,
    I$TYPE SMALLINT = null)
RETURNS (
    VAL VARCHAR(4000))
AS
declare variable V$OU_ID bigint;
declare variable N integer;
declare variable S varchar(1000);
declare variable N1 integer;
declare variable N2 integer;
declare variable N3 integer;
declare variable N4 integer;
declare variable VN1 integer;
declare variable VN2 integer;
declare variable VN3 integer;
declare variable VN4 integer;
declare variable V$OU_LICENCE_TYPE char(1);
begin

  SELECT STATUS FROM OU_LICENCE_TYPE INTO :V$OU_LICENCE_TYPE;

  N1 = 0;
  N2 = 0;
  N3 = 0;
  N4 = 0;

  -- Таблица стилей
  VAL = '<!DOCTYPE html>';
  VAL = VAL || '<html lang="ru">';
  VAL = VAL || '<head>';
  VAL = VAL || '<meta charset="utf-8" />';

  VAL = VAL || '<style>';
  VAL = VAL || 'html { font-family: Tahoma, Verdana, Arial;';
  VAL = VAL || 'font-size: 10pt; ';
  VAL = VAL || '} ';
  VAL = VAL || 'table { border-collapse: collapse; width: 100%; }';
  VAL = VAL || 'th { border-bottom: 2px solid lightgray; text-align: left; }';
  VAL = VAL || '.e { background-color: #f7f7f7; }';
  VAL = VAL || 'th, td { padding: 0.4em 0.8em }';
  VAL = VAL || '.bordered th, .bordered td { border: 1px solid lightgray; }';
  VAL = VAL || '.t { border-top: 2px solid lightgray; font-weight: bold; }';
  VAL = VAL || '</style>';

  VAL = VAL || '</head>';
  VAL = VAL || '<body style="padding: 8px;">';
  SUSPEND;

  VAL = '<h2>Отчет о нарушениях порядка приема для района</h2>';
  VAL = VAL || '<table>';
  VAL = VAL || '<tr>';
  VAL = VAL || '<th>Краткое наименование учреждения</th>';
  VAL = VAL || '<th>Приказ о зачислении издан с нарушением сроков</th>';
  VAL = VAL || '<th>Приказ о зачислении в порядке перевода издан с нарушением сроков</th>';
  VAL = VAL || '<th>Отсутствует приказ об отчислении</th>';
  VAL = VAL || '<th>Приказ об отчислении в порядке перевода издан с нарушением сроков</th>';
  VAL = VAL || '</tr>';
  SUSPEND;
  N = 0;
  FOR
      SELECT L2.OBJ_ID, V2.VAL, COALESCE(V3002.VAL, 0), COALESCE(V3003.VAL, 0), COALESCE(V3004.VAL, 0), COALESCE(V3005.VAL, 0)
      FROM LINKS L2
      JOIN VALS V2 ON V2.OBJ_ID = L2.OBJ_ID AND V2.PARAM_ID = 2 AND V2.IS_DEL = 0
      LEFT JOIN LINKS L162 ON L162.PARENT_ID = L2.OBJ_ID AND L162.OBJ_TYPE_ID = 162 AND L162.DATE_DEL IS NULL
      LEFT JOIN VALI V3002 ON V3002.OBJ_ID = L162.OBJ_ID AND V3002.PARAM_ID = 3002 AND V3002.IS_DEL = 0
      LEFT JOIN VALI V3003 ON V3003.OBJ_ID = L162.OBJ_ID AND V3003.PARAM_ID = 3003 AND V3003.IS_DEL = 0
      LEFT JOIN VALI V3004 ON V3004.OBJ_ID = L162.OBJ_ID AND V3004.PARAM_ID = 3004 AND V3004.IS_DEL = 0
      LEFT JOIN VALI V3005 ON V3005.OBJ_ID = L162.OBJ_ID AND V3005.PARAM_ID = 3005 AND V3005.IS_DEL = 0
      WHERE L2.PARENT_ID = :I$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      ORDER BY 2
      INTO :V$OU_ID, :S, :VN1, :VN2, :VN3, :VN4
  DO
  BEGIN
      IF(N = 0) THEN VAL = '<tr class="o">'; ELSE VAL = '<tr class="e">';
      IF(N = 0) THEN N = 1; ELSE N = 0;
      VAL = VAL || '<td>' || S || '</td>';
      VAL = VAL || '<td>' || VN1 || '</td>';
      VAL = VAL || '<td>' || VN2 || '</td>';
      VAL = VAL || '<td>' || VN3 || '</td>';
      VAL = VAL || '<td>' || VN4 || '</td>';
      VAL = VAL || '</tr>';
      SUSPEND;
      N1 = N1 + VN1;
      N2 = N2 + VN2;
      N3 = N3 + VN3;
      N4 = N4 + VN4;
  END

  VAL = '<tr class="t">';
  VAL = VAL || '<td>Всего по району</td>';
  VAL = VAL || '<td>' || N1 || '</td>';
  VAL = VAL || '<td>' || N2 || '</td>';
  VAL = VAL || '<td>' || N3 || '</td>';
  VAL = VAL || '<td>' || N4 || '</td>';
  VAL = VAL || '</tr>';
  VAL = VAL || '</table>';

  VAL = VAL || '</body></html>';
  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SMIR_MOVE_ERR_REPORT_3 (
    I$OBJ_ID BIGINT,
    I$TYPE SMALLINT = null)
RETURNS (
    VAL VARCHAR(4000))
AS
declare variable V$PREV_ID bigint;
declare variable V$REG_ID bigint;
declare variable V$OU_ID bigint;
declare variable N integer;
declare variable RS varchar(1000);
declare variable S varchar(1000);
declare variable N1 integer;
declare variable N2 integer;
declare variable N3 integer;
declare variable N4 integer;
declare variable RN1 integer;
declare variable RN2 integer;
declare variable RN3 integer;
declare variable RN4 integer;
declare variable VN1 integer;
declare variable VN2 integer;
declare variable VN3 integer;
declare variable VN4 integer;
declare variable V$OU_LICENCE_TYPE char(1);
begin

  SELECT STATUS FROM OU_LICENCE_TYPE INTO :V$OU_LICENCE_TYPE;

  N1 = 0;
  N2 = 0;
  N3 = 0;
  N4 = 0;

  -- Таблица стилей
  VAL = '<!DOCTYPE html>';
  VAL = VAL || '<html lang="ru">';
  VAL = VAL || '<head>';
  VAL = VAL || '<meta charset="utf-8" />';

  VAL = VAL || '<style>';
  VAL = VAL || 'html { font-family: Tahoma, Verdana, Arial;';
  VAL = VAL || 'font-size: 10pt; ';
  VAL = VAL || '} ';
  VAL = VAL || 'table { border-collapse: collapse; width: 100%; }';
  VAL = VAL || 'th { border-bottom: 2px solid lightgray; text-align: left; }';
  VAL = VAL || '.e { background-color: #f7f7f7; }';
  VAL = VAL || 'th, td { padding: 0.4em 0.8em }';
  VAL = VAL || '.bordered th, .bordered td { border: 1px solid lightgray; }';
  VAL = VAL || '.t { border-top: 2px solid lightgray; border-bottom: 2px solid lightgray; font-weight: bold; }';
  VAL = VAL || '</style>';

  VAL = VAL || '</head>';
  VAL = VAL || '<body style="padding: 8px;">';
  SUSPEND;

  VAL = '<h2>Отчет о нарушениях порядка приема для региона</h2>';
  VAL = VAL || '<table>';
  VAL = VAL || '<tr>';
  VAL = VAL || '<th>Район</th>';
  VAL = VAL || '<th>Краткое наименование учреждения</th>';
  VAL = VAL || '<th>Приказ о зачислении издан с нарушением сроков</th>';
  VAL = VAL || '<th>Приказ о зачислении в порядке перевода издан с нарушением сроков</th>';
  VAL = VAL || '<th>Отсутствует приказ об отчислении</th>';
  VAL = VAL || '<th>Приказ об отчислении в порядке перевода издан с нарушением сроков</th>';
  VAL = VAL || '</tr>';
  SUSPEND;
  N = 0;
  V$PREV_ID = -1;
  FOR
      SELECT L111.OBJ_ID, L2.OBJ_ID, V2.VAL, COALESCE(V3002.VAL, 0), COALESCE(V3003.VAL, 0), COALESCE(V3004.VAL, 0), COALESCE(V3005.VAL, 0)
      FROM LINKS L111
      JOIN LINKS L2 ON L2.PARENT_ID = L111.OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      JOIN VALS V2 ON V2.OBJ_ID = L2.OBJ_ID AND V2.PARAM_ID = 2 AND V2.IS_DEL = 0
      LEFT JOIN LINKS L162 ON L162.PARENT_ID = L2.OBJ_ID AND L162.OBJ_TYPE_ID = 162 AND L162.DATE_DEL IS NULL
      LEFT JOIN VALI V3002 ON V3002.OBJ_ID = L162.OBJ_ID AND V3002.PARAM_ID = 3002 AND V3002.IS_DEL = 0
      LEFT JOIN VALI V3003 ON V3003.OBJ_ID = L162.OBJ_ID AND V3003.PARAM_ID = 3003 AND V3003.IS_DEL = 0
      LEFT JOIN VALI V3004 ON V3004.OBJ_ID = L162.OBJ_ID AND V3004.PARAM_ID = 3004 AND V3004.IS_DEL = 0
      LEFT JOIN VALI V3005 ON V3005.OBJ_ID = L162.OBJ_ID AND V3005.PARAM_ID = 3005 AND V3005.IS_DEL = 0
      WHERE L111.PARENT_ID = :I$OBJ_ID AND L111.OBJ_TYPE_ID = 111 AND L111.DATE_DEL IS NULL
      ORDER BY 1, 3
      INTO :V$REG_ID, :V$OU_ID, :S, :VN1, :VN2, :VN3, :VN4
  DO
  BEGIN
      IF(V$REG_ID <> V$PREV_ID) THEN
      BEGIN
          IF(V$PREV_ID > 0) THEN
          BEGIN
              VAL = '<tr class="t">';
              VAL = VAL || '<td>Всего по району</td>';
              VAL = VAL || '<td></td>';
              VAL = VAL || '<td>' || RN1 || '</td>';
              VAL = VAL || '<td>' || RN2 || '</td>';
              VAL = VAL || '<td>' || RN3 || '</td>';
              VAL = VAL || '<td>' || RN4 || '</td>';
              VAL = VAL || '</tr>';
          END
          RS = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$REG_ID));
          RN1 = 0;
          RN2 = 0;
          RN3 = 0;
          RN4 = 0;
          N = 0;
          V$PREV_ID = V$REG_ID;
      END

      IF(N = 0) THEN VAL = '<tr class="o">'; ELSE VAL = '<tr class="e">';
      IF(N = 0) THEN N = 1; ELSE N = 0;
      VAL = VAL || '<td>' || RS || '</td>';
      VAL = VAL || '<td>' || S || '</td>';
      VAL = VAL || '<td>' || VN1 || '</td>';
      VAL = VAL || '<td>' || VN2 || '</td>';
      VAL = VAL || '<td>' || VN3 || '</td>';
      VAL = VAL || '<td>' || VN4 || '</td>';
      VAL = VAL || '</tr>';
      SUSPEND;
      RN1 = RN1 + VN1;
      RN2 = RN2 + VN2;
      RN3 = RN3 + VN3;
      RN4 = RN4 + VN4;
      N1 = N1 + VN1;
      N2 = N2 + VN2;
      N3 = N3 + VN3;
      N4 = N4 + VN4;
  END
  SUSPEND;

  IF(V$REG_ID > 0) THEN
  BEGIN
      VAL = '<tr class="t">';
      VAL = VAL || '<td>Всего по району</td>';
      VAL = VAL || '<td></td>';
      VAL = VAL || '<td>' || RN1 || '</td>';
      VAL = VAL || '<td>' || RN2 || '</td>';
      VAL = VAL || '<td>' || RN3 || '</td>';
      VAL = VAL || '<td>' || RN4 || '</td>';
      VAL = VAL || '</tr>';
      SUSPEND;
  END

  VAL = '<tr class="t">';
  VAL = VAL || '<td>Всего по региону</td>';
  VAL = VAL || '<td></td>';
  VAL = VAL || '<td>' || N1 || '</td>';
  VAL = VAL || '<td>' || N2 || '</td>';
  VAL = VAL || '<td>' || N3 || '</td>';
  VAL = VAL || '<td>' || N4 || '</td>';
  VAL = VAL || '</tr>';
  VAL = VAL || '</table>';

  VAL = VAL || '</body></html>';
  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SMIR_MOVE_LEAVE (
    I$OU_ID BIGINT)
RETURNS (
    STUDENT_ID BIGINT,
    NAME_LAST VARCHAR(1000),
    STAGE_ID BIGINT,
    STAGE_INDEX BIGINT,
    GRADE_ID BIGINT,
    ORDER_DATE DATE,
    PAPER_DATE DATE,
    ORDER_NUM VARCHAR(200))
AS
declare variable V$YEAR_ID bigint;
declare variable V$YEAR_VAL integer;
declare variable V$LEAVE_TYPE smallint;
begin

  -- Возвращает список выбывающих и выбывших учащихся

  SELECT V1236.LISTVAL_ID, LV.COST
  FROM VALL V1236
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE V1236.OBJ_ID = :I$OU_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  INTO :V$YEAR_ID, :V$YEAR_VAL;

  FOR
      -- Действующие учащиеся, по которым подано заявление
      SELECT L10.OBJ_ID, V55.VAL, L8.OBJ_ID, V49.LISTVAL_ID, L9.OBJ_ID, V3000.VAL, 0
      FROM LINKS L7
      JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
      JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
      JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      JOIN VALS V55 ON V55.OBJ_ID = L10.OBJ_ID AND V55.PARAM_ID = 55 AND V55.IS_DEL = 0
      JOIN VALD V3000 ON V3000.OBJ_ID = L10.OBJ_ID AND V3000.PARAM_ID = 3000 AND V3000.IS_DEL = 0
      WHERE L7.PARENT_ID = :I$OU_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
      -- Выбывшие в текущем году
      UNION
      SELECT L10.OBJ_ID, V55.VAL, NULL, NULL, NULL, V3000.VAL, 1
      FROM LINKS L78
      JOIN LINKS L82 ON L82.PARENT_ID = L78.OBJ_ID AND L82.OBJ_TYPE_ID = 82 AND L82.DATE_DEL IS NULL
      JOIN VALI V448 ON V448.OBJ_ID = L82.OBJ_ID AND V448.PARAM_ID = 448 AND V448.IS_DEL = 0 AND V448.VAL = :V$YEAR_VAL
      JOIN LINKS L10 ON L10.PARENT_ID = L82.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      JOIN VALS V55 ON V55.OBJ_ID = L10.OBJ_ID AND V55.PARAM_ID = 55 AND V55.IS_DEL = 0
      JOIN VALD V3000 ON V3000.OBJ_ID = L10.OBJ_ID AND V3000.PARAM_ID = 3000 AND V3000.IS_DEL = 0
      WHERE L78.PARENT_ID = :I$OU_ID AND L78.OBJ_TYPE_ID = 78 AND L78.DATE_DEL IS NULL
      INTO :STUDENT_ID, :NAME_LAST, :STAGE_ID, :STAGE_INDEX, :GRADE_ID, :PAPER_DATE, :V$LEAVE_TYPE
  DO
  BEGIN
      ORDER_DATE = NULL;
      ORDER_NUM = NULL;

      -- А не повторно ли это зачисленные ?
      IF(V$LEAVE_TYPE = 0) THEN
      BEGIN
        IF(EXISTS(
          SELECT FIRST 1 1
          FROM LINKS L76
          JOIN VALL V432 ON V432.OBJ_ID = L76.OBJ_ID AND V432.PARAM_ID = 432 AND V432.IS_DEL = 0
          JOIN LISTVALS LV ON LV.LISTVAL_ID = V432.LISTVAL_ID AND (LV."FILTER" LIKE '%LEAVED%' OR LV."FILTER" LIKE '%FINISHED%')
          JOIN VALD V433 ON V433.OBJ_ID = L76.OBJ_ID AND V433.PARAM_ID = 433 AND V433.IS_DEL = 0
          JOIN VALD V435 ON V435.OBJ_ID = L76.OBJ_ID AND V435.PARAM_ID = 435 AND V435.IS_DEL = 0
          LEFT JOIN VALS V434 ON V434.OBJ_ID = L76.OBJ_ID AND V434.PARAM_ID = 434 AND V434.IS_DEL = 0
          WHERE L76.PARENT_ID = :STUDENT_ID AND L76.OBJ_TYPE_ID = 76 AND L76.DATE_DEL IS NULL
        )) THEN V$LEAVE_TYPE = 1;
      END

      IF(V$LEAVE_TYPE = 1) THEN
      BEGIN
          -- Где учился
          SELECT FIRST 1 V436.LISTVAL_ID, V438.VAL
          FROM LINKS L76
          JOIN VALL V432 ON V432.OBJ_ID = L76.OBJ_ID AND V432.PARAM_ID = 432 AND V432.IS_DEL = 0
          JOIN LISTVALS LV ON LV.LISTVAL_ID = V432.LISTVAL_ID AND (LV."FILTER" LIKE '%ACCEPTED%' OR LV."FILTER" LIKE '%TRANSFERED%')
          JOIN VALD V433 ON V433.OBJ_ID = L76.OBJ_ID AND V433.PARAM_ID = 433 AND V433.IS_DEL = 0 AND V433.VAL >= '25.08.' || :V$YEAR_VAL
          JOIN VALL V436 ON V436.OBJ_ID = L76.OBJ_ID AND V436.PARAM_ID = 436 AND V436.IS_DEL = 0
          JOIN VALR V438 ON V438.OBJ_ID = L76.OBJ_ID AND V438.PARAM_ID = 438 AND V438.IS_DEL = 0
          WHERE L76.PARENT_ID = :STUDENT_ID AND L76.OBJ_TYPE_ID = 76 AND L76.DATE_DEL IS NULL
          ORDER BY V433.VAL DESC
          INTO :STAGE_INDEX, :GRADE_ID;
          -- Когда выбыл
          SELECT FIRST 1 V435.VAL, COALESCE(V434.VAL, '')
          FROM LINKS L76
          JOIN VALL V432 ON V432.OBJ_ID = L76.OBJ_ID AND V432.PARAM_ID = 432 AND V432.IS_DEL = 0
          JOIN LISTVALS LV ON LV.LISTVAL_ID = V432.LISTVAL_ID AND (LV."FILTER" LIKE '%LEAVED%' OR LV."FILTER" LIKE '%FINISHED%')
          JOIN VALD V433 ON V433.OBJ_ID = L76.OBJ_ID AND V433.PARAM_ID = 433 AND V433.IS_DEL = 0
          JOIN VALD V435 ON V435.OBJ_ID = L76.OBJ_ID AND V435.PARAM_ID = 435 AND V435.IS_DEL = 0
          LEFT JOIN VALS V434 ON V434.OBJ_ID = L76.OBJ_ID AND V434.PARAM_ID = 434 AND V434.IS_DEL = 0
          WHERE L76.PARENT_ID = :STUDENT_ID AND L76.OBJ_TYPE_ID = 76 AND L76.DATE_DEL IS NULL
          ORDER BY V433.VAL DESC
          INTO :ORDER_DATE, :ORDER_NUM;

          IF(EXISTS(SELECT 1 FROM OBJECTS WHERE OBJ_ID = :GRADE_ID AND TYPE_ID = 187)) THEN GRADE_ID = NULL;
      END

      IF(GRADE_ID IS NOT NULL) THEN SUSPEND;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SOCPASS_DATA (
    I$PARAM INTEGER,
    I$OBJ_ID BIGINT = null)
RETURNS (
    VAL VARCHAR(1000))
AS
declare variable Y integer;
declare variable VY bigint;
declare variable V$OBJ_ID bigint;
declare variable V$PARAM_ID bigint;
begin

  Y = EXTRACT(YEAR FROM CURRENT_DATE);
  IF(EXTRACT(MONTH FROM CURRENT_DATE) < 9) THEN Y = Y - 1;

  IF(I$PARAM = 10) THEN
  BEGIN
    -- Название ОУ
    SELECT V2.VAL
    FROM LINKS L2
    JOIN VALS V2 ON V2.OBJ_ID = L2.OBJ_ID AND V2.PARAM_ID = 2 AND V2.IS_DEL = 0
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :VAL;
  END
  ELSE IF(I$PARAM = 1010) THEN
  BEGIN
    -- Всего учащихся
    SELECT COUNT(*)
    FROM LINKS L2
    JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL AND (:I$OBJ_ID IS NULL OR L9.OBJ_ID = :I$OBJ_ID)
    JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :VAL;
  END
  ELSE IF(I$PARAM = 1011) THEN
  BEGIN
    -- Девочки
    SELECT COUNT(*)
    FROM LINKS L2
    JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL AND (:I$OBJ_ID IS NULL OR L9.OBJ_ID = :I$OBJ_ID)
    JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    JOIN VALL V88 ON V88.OBJ_ID = L10.OBJ_ID AND V88.PARAM_ID = 88 AND V88.IS_DEL = 0 AND V88.LISTVAL_ID = 182
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :VAL;
  END
  ELSE IF(I$PARAM = 1012) THEN
  BEGIN
    -- Мальчики
    SELECT COUNT(*)
    FROM LINKS L2
    JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL AND (:I$OBJ_ID IS NULL OR L9.OBJ_ID = :I$OBJ_ID)
    JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    JOIN VALL V88 ON V88.OBJ_ID = L10.OBJ_ID AND V88.PARAM_ID = 88 AND V88.IS_DEL = 0 AND V88.LISTVAL_ID = 183
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :VAL;
  END
  ELSE IF(I$PARAM IN (1013, 1014, 1015)) THEN
  BEGIN
    SELECT COUNT(*)
    FROM LINKS L2
    JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    JOIN VALL V43 ON V43.OBJ_ID = L7.OBJ_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0 AND (V43.LISTVAL_ID = IIF(:I$PARAM = 1013, 22, :I$PARAM - 1014 + 26))
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL AND (:I$OBJ_ID IS NULL OR L9.OBJ_ID = :I$OBJ_ID)
    JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :VAL;
  END
  ELSE IF(I$PARAM = 1021) THEN
  BEGIN
    -- Инвалиды
    SELECT COUNT(DISTINCT L10.OBJ_ID)
    FROM LINKS L2
    JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL AND (:I$OBJ_ID IS NULL OR L9.OBJ_ID = :I$OBJ_ID)
    JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    JOIN LINKS L295 ON L295.PARENT_ID = L10.OBJ_ID AND L295.OBJ_TYPE_ID = 295 AND L295.DATE_DEL IS NULL
    LEFT JOIN VALD V2375 ON V2375.OBJ_ID = L295.OBJ_ID AND V2375.PARAM_ID = 2375 AND V2375.IS_DEL = 0
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND (V2375.VAL IS NULL OR V2375.VAL >= CURRENT_DATE)
    INTO :VAL;
  END
  ELSE IF(I$PARAM = 1022) THEN
  BEGIN
    -- ОВЗ
    SELECT COUNT(DISTINCT L10.OBJ_ID)
    FROM LINKS L2
    JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL AND (:I$OBJ_ID IS NULL OR L9.OBJ_ID = :I$OBJ_ID)
    JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    JOIN VALL V207 ON V207.OBJ_ID = L10.OBJ_ID AND V207.PARAM_ID = 207 AND V207.IS_DEL = 0 AND V207.LISTVAL_ID = 4
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :VAL;
  END
  ELSE IF(I$PARAM = 1023) THEN
  BEGIN
    -- Обучающиеся на дому по медпоказаниям
    SELECT COUNT(DISTINCT L10.OBJ_ID)
    FROM LINKS L2
    JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL AND (:I$OBJ_ID IS NULL OR L9.OBJ_ID = :I$OBJ_ID)
    JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    JOIN VALL V2169 ON V2169.OBJ_ID = L10.OBJ_ID AND V2169.PARAM_ID = 2169 AND V2169.IS_DEL = 0 AND V2169.LISTVAL_ID = 2
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :VAL;
  END
  ELSE IF(I$PARAM = 1024) THEN
  BEGIN
    -- Второгодники
    SELECT COUNT(DISTINCT L10.OBJ_ID)
    FROM LINKS L2
    JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL AND (:I$OBJ_ID IS NULL OR L9.OBJ_ID = :I$OBJ_ID)
    JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    -- Последняя запись движения
    AND ((
      SELECT FIRST 1 V432.LISTVAL_ID
      FROM LINKS L76
      JOIN VALD V433 ON V433.OBJ_ID = L76.OBJ_ID AND V433.PARAM_ID = 433 AND V433.IS_DEL = 0
      JOIN VALL V432 ON V432.OBJ_ID = L76.OBJ_ID AND V432.PARAM_ID = 432 AND V432.IS_DEL = 0
      WHERE L76.PARENT_ID = L10.OBJ_ID AND L76.OBJ_TYPE_ID = 76 AND L76.DATE_DEL IS NULL
      ORDER BY V433.VAL DESC, L76.LINK_ID DESC
    ) = 810)
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :VAL;
  END
  ELSE IF(I$PARAM = 1025) THEN
  BEGIN
    -- Не граждане
    SELECT COUNT(DISTINCT L10.OBJ_ID)
    FROM LINKS L2
    JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL AND (:I$OBJ_ID IS NULL OR L9.OBJ_ID = :I$OBJ_ID)
    JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    JOIN VALL V91 ON V91.OBJ_ID = L10.OBJ_ID AND V91.PARAM_ID = 91 AND V91.IS_DEL = 0 AND V91.LISTVAL_ID <> 1515
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :VAL;
  END
  ELSE IF(I$PARAM = 1026) THEN
  BEGIN
    -- Без постоянной регистрации в СПб
    SELECT COUNT(DISTINCT L10.OBJ_ID)
    FROM LINKS L2
    JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL AND (:I$OBJ_ID IS NULL OR L9.OBJ_ID = :I$OBJ_ID)
    JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    JOIN VALL V108 ON V108.OBJ_ID = L10.OBJ_ID AND V108.PARAM_ID = 108 AND V108.IS_DEL = 0 AND V108.LISTVAL_ID = 1219
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :VAL;
  END
  ELSE IF(I$PARAM = 1041) THEN
  BEGIN
    -- Прогульщики, скользящие данные, пропусков более 50%
    SELECT COUNT(*)
    FROM CJ2_PERSON_MISS
    WHERE UPDATED_AT > DATEADD(-1 MONTH TO CURRENT_DATE) AND RATE_MISS < 0.5
    INTO :VAL;
  END
  ELSE IF(I$PARAM = 1042) THEN
  BEGIN
    -- Неуспевающие - три и более двойки за два года
    SELECT COUNT(DISTINCT L10.OBJ_ID)
    FROM LINKS L2
    JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL AND (:I$OBJ_ID IS NULL OR L9.OBJ_ID = :I$OBJ_ID)
    JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    AND ((
      SELECT COUNT(*)
      FROM VALM M
      JOIN LISTVALS LV ON LV.LISTVAL_ID = M.MARK_ID AND LV.COST >= :Y - 1
      WHERE M.PUPIL_ID = L10.OBJ_ID AND M.MARKTYPE_ID IN (3014, 3015)
    ) >= 3)
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :VAL;
  END
  ELSE IF(I$PARAM = 1043) THEN
  BEGIN
    -- Грубые нарушения устава
    SELECT COUNT(DISTINCT L10.OBJ_ID)
    FROM LINKS L2
    JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL AND (:I$OBJ_ID IS NULL OR L9.OBJ_ID = :I$OBJ_ID)
    JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    JOIN LINKS L26 ON L26.PARENT_ID = L10.OBJ_ID AND L26.OBJ_TYPE_ID = 26 AND L26.DATE_DEL IS NULL
    JOIN VALL V190 ON V190.OBJ_ID = L26.OBJ_ID AND V190.PARAM_ID = 190 AND V190.IS_DEL = 0 AND V190.LISTVAL_ID = 1413
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :VAL;
  END
  ELSE IF(I$PARAM = 1045) THEN
  BEGIN
    -- Агрессивное поведение
    SELECT COUNT(DISTINCT L10.OBJ_ID)
    FROM LINKS L2
    JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL AND (:I$OBJ_ID IS NULL OR L9.OBJ_ID = :I$OBJ_ID)
    JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    JOIN LINKS L26 ON L26.PARENT_ID = L10.OBJ_ID AND L26.OBJ_TYPE_ID = 26 AND L26.DATE_DEL IS NULL
    JOIN VALL V190 ON V190.OBJ_ID = L26.OBJ_ID AND V190.PARAM_ID = 190 AND V190.IS_DEL = 0 AND V190.LISTVAL_ID = 485
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :VAL;
  END
  ELSE IF(I$PARAM = 1047) THEN
  BEGIN
    -- На профилактическом учете
    SELECT COUNT(DISTINCT L10.OBJ_ID)
    FROM LINKS L2
    JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL AND (:I$OBJ_ID IS NULL OR L9.OBJ_ID = :I$OBJ_ID)
    JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    JOIN LINKS L26 ON L26.PARENT_ID = L10.OBJ_ID AND L26.OBJ_TYPE_ID = 26 AND L26.DATE_DEL IS NULL
    JOIN VALL V579 ON V579.OBJ_ID = L26.OBJ_ID AND V579.PARAM_ID = 579 AND V579.IS_DEL = 0 AND V579.LISTVAL_ID = 479
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :VAL;
  END
  ELSE IF(I$PARAM = 1061) THEN
  BEGIN
    -- Социально-опасное положение
    SELECT COUNT(DISTINCT L10.OBJ_ID)
    FROM LINKS L2
    JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL AND (:I$OBJ_ID IS NULL OR L9.OBJ_ID = :I$OBJ_ID)
    JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    JOIN LINKS L18 ON L18.PARENT_ID = L10.OBJ_ID AND L18.OBJ_TYPE_ID = 18 AND L18.DATE_DEL IS NULL
    JOIN VALL V121 ON V121.OBJ_ID = L18.OBJ_ID AND V121.PARAM_ID = 121 AND V121.IS_DEL = 0 AND V121.LISTVAL_ID = 210
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :VAL;
  END
  ELSE IF(I$PARAM = 1062) THEN
  BEGIN
    -- Трудная жизненная ситуация
    SELECT COUNT(DISTINCT L10.OBJ_ID)
    FROM LINKS L2
    JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL AND (:I$OBJ_ID IS NULL OR L9.OBJ_ID = :I$OBJ_ID)
    JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    JOIN VALL V2364 ON V2364.OBJ_ID = L10.OBJ_ID AND V2364.PARAM_ID = 2364 AND V2364.IS_DEL = 0
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :VAL;
  END
  ELSE IF(I$PARAM = 1063 OR I$PARAM = 1092) THEN
  BEGIN
    -- УДН
    SELECT COUNT(DISTINCT L10.OBJ_ID)
    FROM LINKS L2
    JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL AND (:I$OBJ_ID IS NULL OR L9.OBJ_ID = :I$OBJ_ID)
    JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    JOIN LINKS L26 ON L26.PARENT_ID = L10.OBJ_ID AND L26.OBJ_TYPE_ID = 26 AND L26.DATE_DEL IS NULL
    JOIN VALL V579 ON V579.OBJ_ID = L26.OBJ_ID AND V579.PARAM_ID = 579 AND V579.IS_DEL = 0 AND V579.LISTVAL_ID = 479
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :VAL;
  END
  ELSE IF(I$PARAM = 1071) THEN
  BEGIN
    -- Родители-инвалиды
    SELECT COUNT(DISTINCT L10.OBJ_ID)
    FROM LINKS L2
    JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL AND (:I$OBJ_ID IS NULL OR L9.OBJ_ID = :I$OBJ_ID)
    JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    JOIN LINKS L18 ON L18.PARENT_ID = L10.OBJ_ID AND L18.OBJ_TYPE_ID = 18 AND L18.DATE_DEL IS NULL
    JOIN VALL V121 ON V121.OBJ_ID = L18.OBJ_ID AND V121.PARAM_ID = 121 AND V121.IS_DEL = 0 AND V121.LISTVAL_ID = 213
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :VAL;
  END
  ELSE IF(I$PARAM = 1072) THEN
  BEGIN
    -- Многодетные семьи
    SELECT COUNT(DISTINCT L10.OBJ_ID)
    FROM LINKS L2
    JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL AND (:I$OBJ_ID IS NULL OR L9.OBJ_ID = :I$OBJ_ID)
    JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    JOIN VALI V119 ON V119.OBJ_ID = L10.OBJ_ID AND V119.PARAM_ID = 109 AND V119.IS_DEL = 0 AND V119.VAL >= 3
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :VAL;
  END
  ELSE IF(I$PARAM = 1073) THEN
  BEGIN
    -- Опекаемые
    SELECT COUNT(DISTINCT L10.OBJ_ID)
    FROM LINKS L2
    JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL AND (:I$OBJ_ID IS NULL OR L9.OBJ_ID = :I$OBJ_ID)
    JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    JOIN LINKS L20 ON L20.PARENT_ID = L10.OBJ_ID AND L20.OBJ_TYPE_ID = 20 AND L20.DATE_DEL IS NULL
    JOIN VALL V1562 ON V1562.OBJ_ID = L20.EXT_OBJ_ID AND V1562.PARAM_ID = 1562 AND V1562.IS_DEL = 0 AND V1562.LISTVAL_ID IN (1231, 1232, 11175)
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :VAL;
  END
  ELSE IF(I$PARAM = 1075) THEN
  BEGIN
    -- Cемьи мигрантов
    SELECT COUNT(DISTINCT L10.OBJ_ID)
    FROM LINKS L2
    JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL AND (:I$OBJ_ID IS NULL OR L9.OBJ_ID = :I$OBJ_ID)
    JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    JOIN LINKS L18 ON L18.PARENT_ID = L10.OBJ_ID AND L18.OBJ_TYPE_ID = 18 AND L18.DATE_DEL IS NULL
    JOIN VALL V121 ON V121.OBJ_ID = L18.OBJ_ID AND V121.PARAM_ID = 121 AND V121.IS_DEL = 0 AND V121.LISTVAL_ID IN (1389, 1391)
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :VAL;
  END
  ELSE IF(I$PARAM = 1076) THEN
  BEGIN
    -- Неблагополучные семьи
    SELECT COUNT(DISTINCT L10.OBJ_ID)
    FROM LINKS L2
    JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL AND (:I$OBJ_ID IS NULL OR L9.OBJ_ID = :I$OBJ_ID)
    JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    JOIN LINKS L18 ON L18.PARENT_ID = L10.OBJ_ID AND L18.OBJ_TYPE_ID = 18 AND L18.DATE_DEL IS NULL
    JOIN VALL V121 ON V121.OBJ_ID = L18.OBJ_ID AND V121.PARAM_ID = 121 AND V121.IS_DEL = 0 AND V121.LISTVAL_ID = 1390
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :VAL;
  END
  ELSE IF(I$PARAM = 1079) THEN
  BEGIN
    -- Из учреждений соцзащиты
    VAL = 0;
  END
  -- Беспризорные, безнадзорные
  ELSE IF(I$PARAM = 1081) THEN
  BEGIN
  END
  -- 1092 уже учтен
  -- Семьи на контроле опеки
  ELSE IF(I$PARAM = 1094) THEN
  BEGIN
  END
  ELSE IF(I$PARAM = 10101) THEN
  BEGIN
    -- Кружки в школе
    SELECT COUNT(DISTINCT L10.OBJ_ID)
    FROM LINKS L2
    JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL AND (:I$OBJ_ID IS NULL OR L9.OBJ_ID = :I$OBJ_ID)
    JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    JOIN LINKS LP46 ON LP46.OBJ_ID = L10.OBJ_ID AND LP46.PARENT_TYPE_ID = 46 AND LP46.DATE_DEL IS NULL
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :VAL;
  END
  ELSE IF(I$PARAM = 10102) THEN
  BEGIN
    -- Кружки вне школы
    SELECT FIRST 1 LV.LISTVAL_ID
    FROM LISTVALS LV
    WHERE LV.LIST_ID = 29 AND LV.IS_DEL = 0 AND LV.COST = :Y
    INTO VY;

    SELECT COUNT(DISTINCT L10.OBJ_ID)
    FROM LINKS L2
    JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL AND (:I$OBJ_ID IS NULL OR L9.OBJ_ID = :I$OBJ_ID)
    JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    JOIN LINKS L297 ON L297.PARENT_ID = L10.OBJ_ID AND L297.PARENT_TYPE_ID = 297 AND L297.DATE_DEL IS NULL
    JOIN VALL V2394 ON V2394.OBJ_ID = L297.OBJ_ID AND V2394.PARAM_ID = 2394 AND V2394.IS_DEL = 0 AND V2394.LISTVAL_ID = :VY
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :VAL;
  END
  ELSE
  BEGIN

    IF(I$PARAM = 1031) THEN V$PARAM_ID = 3033;
    ELSE IF(I$PARAM = 1032) THEN V$PARAM_ID = 3034;
    ELSE IF(I$PARAM = 1033) THEN V$PARAM_ID = 3035;
    ELSE IF(I$PARAM = 1044) THEN V$PARAM_ID = 3036;
    ELSE IF(I$PARAM = 1051) THEN V$PARAM_ID = 3037;
    ELSE IF(I$PARAM = 1064) THEN V$PARAM_ID = 3038;
    ELSE IF(I$PARAM = 1065) THEN V$PARAM_ID = 3039;
    ELSE IF(I$PARAM = 1066) THEN V$PARAM_ID = 3040;
    ELSE IF(I$PARAM = 1067) THEN V$PARAM_ID = 3041;
    ELSE IF(I$PARAM = 1068) THEN V$PARAM_ID = 3042;
    ELSE IF(I$PARAM = 1069) THEN V$PARAM_ID = 3043;
    ELSE IF(I$PARAM = 1071) THEN V$PARAM_ID = 3044;
    ELSE IF(I$PARAM = 1074) THEN V$PARAM_ID = 3045;
    ELSE IF(I$PARAM = 1077) THEN V$PARAM_ID = 3046;
    ELSE IF(I$PARAM = 1078) THEN V$PARAM_ID = 3047;
    ELSE IF(I$PARAM = 1082) THEN V$PARAM_ID = 3048;
    ELSE IF(I$PARAM = 1091) THEN V$PARAM_ID = 3049;
    ELSE IF(I$PARAM = 1093) THEN V$PARAM_ID = 3050;
    ELSE IF(I$PARAM = 1095) THEN V$PARAM_ID = 3051;

    IF(V$PARAM_ID IS NOT NULL) THEN
    BEGIN
      SELECT FIRST 1 L2.OBJ_ID
      FROM LINKS L2
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      INTO :V$OBJ_ID;

      SELECT I FROM VAL_GET(:V$OBJ_ID, :V$PARAM_ID) INTO :VAL;
    END

  END

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SOCPASS_GET (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(1000))
AS
declare variable V$OBJ_TYPE bigint;
declare variable P integer;
begin

  SELECT TYPE_ID FROM OBJECTS WHERE OBJ_ID = :I$OBJ_ID INTO :V$OBJ_TYPE;

  IF(V$OBJ_TYPE = 2) THEN
  BEGIN

    P = 1000;
    WHILE(P <= 10102) DO
    BEGIN
      TAG_NAME = 'param' || P;
      VAL = (SELECT VAL FROM SOCPASS_DATA(:P, NULL));
      IF(VAL IS NOT NULL) THEN SUSPEND;
      P = P + 1;
      -- Прокрутка лишних параметров
      IF(P = 2000) THEN P = 10000;
    END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SOCPASS_SET (
    I$PARAM BIGINT,
    I$VALUE INTEGER,
    I$USER_ID VARCHAR(40))
AS
declare variable V$OBJ_ID bigint;
declare variable V$PARAM_ID bigint;
begin

  IF(I$PARAM = 1031) THEN V$PARAM_ID = 3033;
  ELSE IF(I$PARAM = 1032) THEN V$PARAM_ID = 3034;
  ELSE IF(I$PARAM = 1033) THEN V$PARAM_ID = 3035;
  ELSE IF(I$PARAM = 1044) THEN V$PARAM_ID = 3036;
  ELSE IF(I$PARAM = 1051) THEN V$PARAM_ID = 3037;
  ELSE IF(I$PARAM = 1064) THEN V$PARAM_ID = 3038;
  ELSE IF(I$PARAM = 1065) THEN V$PARAM_ID = 3039;
  ELSE IF(I$PARAM = 1066) THEN V$PARAM_ID = 3040;
  ELSE IF(I$PARAM = 1067) THEN V$PARAM_ID = 3041;
  ELSE IF(I$PARAM = 1068) THEN V$PARAM_ID = 3042;
  ELSE IF(I$PARAM = 1069) THEN V$PARAM_ID = 3043;
  ELSE IF(I$PARAM = 1071) THEN V$PARAM_ID = 3044;
  ELSE IF(I$PARAM = 1074) THEN V$PARAM_ID = 3045;
  ELSE IF(I$PARAM = 1077) THEN V$PARAM_ID = 3046;
  ELSE IF(I$PARAM = 1078) THEN V$PARAM_ID = 3047;
  ELSE IF(I$PARAM = 1082) THEN V$PARAM_ID = 3048;
  ELSE IF(I$PARAM = 1091) THEN V$PARAM_ID = 3049;
  ELSE IF(I$PARAM = 1093) THEN V$PARAM_ID = 3050;
  ELSE IF(I$PARAM = 1095) THEN V$PARAM_ID = 3051;

  SELECT FIRST 1 L.OBJ_ID
  FROM LINKS L
  WHERE L.PARENT_ID IS NULL AND L.OBJ_TYPE_ID = 2 AND L.DATE_DEL IS NULL
  INTO :V$OBJ_ID;

  IF(V$PARAM_ID IS NULL OR V$OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Неизвестный параметр';

  SELECT BLOB_ID FROM VAL_ADD(:V$PARAM_ID, :V$OBJ_ID, :I$VALUE) INTO :V$PARAM_ID;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE STAGE_AVAILABLE_GUP_LIST (
    I$STAGE_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    PARENT_ID BIGINT,
    OBJ_CAPTION VARCHAR(1000))
AS
declare variable V$LISTVAL_ID bigint;
declare variable V$SCHOOL_ID bigint;
BEGIN
    /* если на входе вдруг класс, то поднимаемся на уровень вверх */
    IF ((SELECT FIRST 1 TYPE_ID FROM OBJECTS WHERE OBJ_ID = :I$STAGE_ID) IN (9, 187)) THEN
    BEGIN
        SELECT PARENT_ID FROM LINKS
        WHERE OBJ_ID = :I$STAGE_ID AND PARENT_TYPE_ID = 8 AND DATE_DEL IS NULL
        INTO :I$STAGE_ID;
    END

    PARENT_ID = NULL;
    SELECT FIRST 1 OBJ_ID FROM OBJECT_PARENTS_GET(:I$STAGE_ID, 2)
    INTO :V$SCHOOL_ID;

    FOR
        SELECT V49.LISTVAL_ID
        FROM VALL V49
        WHERE V49.OBJ_ID = :I$STAGE_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
        INTO :V$LISTVAL_ID
    DO
    BEGIN
        FOR
            SELECT L256.OBJ_ID
            FROM LINKS L69
            JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
            JOIN LINKS L400 ON L400.PARENT_ID = L57.OBJ_ID AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL
            JOIN VALL V3022 ON V3022.OBJ_ID = L400.OBJ_ID AND V3022.PARAM_ID = 3022 AND V3022.IS_DEL = 0 AND V3022.LISTVAL_ID = 3 -- отсекаем внеурочку
            JOIN LINKS L54 ON L54.PARENT_ID = L400.OBJ_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
            JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0 AND V381.LISTVAL_ID = :V$LISTVAL_ID
            JOIN LINKS L256 ON L256.PARENT_ID = L54.OBJ_ID AND L256.OBJ_TYPE_ID = 256 AND L256.DATE_DEL IS NULL
            WHERE L69.PARENT_ID = :V$SCHOOL_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL
            INTO :OBJ_ID
        DO
        BEGIN
            SELECT CAPTION FROM OBJECT_CAPTION_GET(:OBJ_ID, NULL, NULL, 1)
            INTO :OBJ_CAPTION;

            SUSPEND;
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE STAGE_GROUPS_LIST (
    PLAN_ID BIGINT,
    STAGE_LV BIGINT)
RETURNS (
    GROUP_ID BIGINT,
    GROUP_TYPE_ID BIGINT,
    GROUP_NAME VARCHAR(1000),
    PARENT_ID BIGINT,
    SUBJECT_ID BIGINT,
    AFFECTS_THIS SMALLINT)
AS
declare variable V$PLAN_TYPE bigint;
declare variable V$SUBJECT_NAME varchar(1000);
declare variable V$TEMP_PLAN_ID bigint;
declare variable V$GUP_ID bigint;
begin

  -- Выборка производится по всем учебным планам в кусте образовательной программы, того же типа по внеурочке
  -- Возвращаем:
  -- ГУП
  -- Деление на потоки (здесь передается SUBJECT_ID; в случае УП ВД передается ссылка на родительский ГУП)
  -- Сами потоки (передается только ссылка на деление на потоки)

  SELECT V2545.LISTVAL_ID
  FROM VALL V2545
  WHERE V2545.OBJ_ID = :PLAN_ID AND V2545.PARAM_ID = 2545 AND V2545.IS_DEL = 0
  INTO :V$PLAN_TYPE;

  IF(V$PLAN_TYPE IS NULL) THEN EXIT;

  -- ГУП и в случае ВД - деление под ними, имитирующее подгруппы
  FOR
      SELECT L256.OBJ_ID, L256.OBJ_TYPE_ID, V2162.VAL, IIF(L50.OBJ_ID = LP57.OBJ_ID, 1, 0), L50.OBJ_ID
      -- Поднимаемся до куста образовательных программ, и запоминаем уровень ОП
      FROM LINKS LP57
      JOIN VALL V1832 ON V1832.OBJ_ID = LP57.PARENT_ID AND V1832.PARAM_ID = 1832 AND V1832.IS_DEL = 0
      JOIN LINKS LP69 ON LP69.OBJ_ID = LP57.PARENT_ID AND LP69.PARENT_TYPE_ID = 69 AND LP69.DATE_DEL IS NULL
      -- Теперь спускаемся вниз
      JOIN LINKS L57 ON L57.PARENT_ID = LP69.PARENT_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
      JOIN VALL V1832D ON V1832D.OBJ_ID = L57.OBJ_ID AND V1832D.PARAM_ID = 1832 AND V1832D.IS_DEL = 0 AND V1832D.LISTVAL_ID = V1832.LISTVAL_ID
      JOIN LINKS L50 ON L50.PARENT_ID = L57.OBJ_ID AND L50.OBJ_TYPE_ID = 50 AND L50.DATE_DEL IS NULL
      LEFT JOIN VALL V2545 ON V2545.OBJ_ID = L50.OBJ_ID AND V2545.PARAM_ID = 2545 AND V2545.IS_DEL = 0 AND V2545.LISTVAL_ID = :V$PLAN_TYPE
      -- И далее по УП
      JOIN LINKS L54 ON L54.PARENT_ID = L50.OBJ_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
      JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0 AND V381.LISTVAL_ID = :STAGE_LV
      JOIN LINKS L256 ON L256.PARENT_ID = L54.OBJ_ID AND L256.OBJ_TYPE_ID = 256 AND L256.DATE_DEL IS NULL
      JOIN VALS V2162 ON V2162.OBJ_ID = L256.OBJ_ID AND V2162.PARAM_ID = 2162 AND V2162.IS_DEL = 0
      WHERE LP57.OBJ_ID = :PLAN_ID AND LP57.PARENT_TYPE_ID = 57 AND LP57.DATE_DEL IS NULL
      INTO :GROUP_ID, :GROUP_TYPE_ID, :GROUP_NAME, :AFFECTS_THIS, :V$TEMP_PLAN_ID
  DO
  BEGIN
    
      -- AFFECTS_THIS также распространяется и на подгруппы/потоки
      PARENT_ID = NULL;
      SUBJECT_ID = NULL;
      SUSPEND;

      IF(V$PLAN_TYPE = 2) THEN
      BEGIN

          V$GUP_ID = GROUP_ID;

          FOR
              SELECT L346.OBJ_ID, L346.OBJ_TYPE_ID, V2704.VAL, V2705.VAL, C51.CAPTION
              FROM LINKS L54
              JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0 AND V381.LISTVAL_ID = :STAGE_LV
              JOIN LINKS L346 ON L346.PARENT_ID = L54.OBJ_ID AND L346.OBJ_TYPE_ID = 346 AND L346.DATE_DEL IS NULL
              -- Деление на потоки с привязкой к вышестоящему ГУП
              JOIN VALR V2914 ON V2914.OBJ_ID = L346.OBJ_ID AND V2914.PARAM_ID = 2914 AND V2914.IS_DEL = 0 AND V2914.VAL = :V$GUP_ID
              JOIN VALS V2704 ON V2704.OBJ_ID = L346.OBJ_ID AND V2704.PARAM_ID = 2704 AND V2704.IS_DEL = 0
              JOIN VALR V2705 ON V2705.OBJ_ID = L346.OBJ_ID AND V2705.PARAM_ID = 2705 AND V2705.IS_DEL = 0
              LEFT JOIN OBJECT_CAPTION_GET(V2705.VAL) C51 ON 1 = 1
              WHERE L54.PARENT_ID = :V$TEMP_PLAN_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
              INTO :GROUP_ID, :GROUP_TYPE_ID, :GROUP_NAME, :SUBJECT_ID, :V$SUBJECT_NAME
          DO
          BEGIN

              PARENT_ID = V$GUP_ID;
              GROUP_NAME = GROUP_NAME || ' - ' || V$SUBJECT_NAME;
              SUSPEND;

              SUBJECT_ID = NULL;
              PARENT_ID = GROUP_ID;

              FOR
                  SELECT L347.OBJ_ID, L347.OBJ_TYPE_ID, V2706.VAL
                  FROM LINKS L347
                  JOIN VALS V2706 ON V2706.OBJ_ID = L347.OBJ_ID AND V2706.PARAM_ID = 2706 AND V2706.IS_DEL = 0
                  WHERE L347.PARENT_ID = :PARENT_ID AND L347.OBJ_TYPE_ID = 347 AND L347.DATE_DEL IS NULL
                  INTO :GROUP_ID, :GROUP_TYPE_ID, :GROUP_NAME
              DO
              BEGIN
                  SUSPEND;
              END

          END

      END

  END

  -- Для общеобразовательных УП показываем нормальные потоки
  IF(V$PLAN_TYPE = 3) THEN
  BEGIN

      FOR
          SELECT L346.OBJ_ID, L346.OBJ_TYPE_ID, V2704.VAL, V2705.VAL, C51.CAPTION, IIF(L50.OBJ_ID = LP57.OBJ_ID, 1, 0)
          -- Поднимаемся до куста образовательных программ, и запоминаем уровень ОП
          FROM LINKS LP57
          JOIN VALL V1832 ON V1832.OBJ_ID = LP57.PARENT_ID AND V1832.PARAM_ID = 1832 AND V1832.IS_DEL = 0
          JOIN LINKS LP69 ON LP69.OBJ_ID = LP57.PARENT_ID AND LP69.PARENT_TYPE_ID = 69 AND LP69.DATE_DEL IS NULL
          -- Теперь спускаемся вниз
          JOIN LINKS L57 ON L57.PARENT_ID = LP69.PARENT_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
          JOIN VALL V1832D ON V1832D.OBJ_ID = L57.OBJ_ID AND V1832D.PARAM_ID = 1832 AND V1832D.IS_DEL = 0 AND V1832D.LISTVAL_ID = V1832.LISTVAL_ID
          JOIN LINKS L50 ON L50.PARENT_ID = L57.OBJ_ID AND L50.OBJ_TYPE_ID = 50 AND L50.DATE_DEL IS NULL
          JOIN VALL V2545 ON V2545.OBJ_ID = L50.OBJ_ID AND V2545.PARAM_ID = 2545 AND V2545.IS_DEL = 0 AND V2545.LISTVAL_ID = :V$PLAN_TYPE
          -- И далее по УП
          JOIN LINKS L54 ON L54.PARENT_ID = L50.OBJ_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
          JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0 AND V381.LISTVAL_ID = :STAGE_LV
          JOIN LINKS L346 ON L346.PARENT_ID = L54.OBJ_ID AND L346.OBJ_TYPE_ID = 346 AND L346.DATE_DEL IS NULL
          JOIN VALS V2704 ON V2704.OBJ_ID = L346.OBJ_ID AND V2704.PARAM_ID = 2704 AND V2704.IS_DEL = 0
          JOIN VALR V2705 ON V2705.OBJ_ID = L346.OBJ_ID AND V2705.PARAM_ID = 2705 AND V2705.IS_DEL = 0
          LEFT JOIN OBJECT_CAPTION_GET(V2705.VAL) C51 ON 1 = 1
          WHERE LP57.OBJ_ID = :PLAN_ID AND LP57.PARENT_TYPE_ID = 57 AND LP57.DATE_DEL IS NULL
          INTO :GROUP_ID, :GROUP_TYPE_ID, :GROUP_NAME, :SUBJECT_ID, :V$SUBJECT_NAME, :AFFECTS_THIS
      DO
      BEGIN

          PARENT_ID = NULL;
          GROUP_NAME = GROUP_NAME || ' - ' || V$SUBJECT_NAME;
          SUSPEND;

          SUBJECT_ID = NULL;
          PARENT_ID = GROUP_ID;

          FOR
              SELECT L347.OBJ_ID, L347.OBJ_TYPE_ID, V2706.VAL
              FROM LINKS L347
              JOIN VALS V2706 ON V2706.OBJ_ID = L347.OBJ_ID AND V2706.PARAM_ID = 2706 AND V2706.IS_DEL = 0
              WHERE L347.PARENT_ID = :PARENT_ID AND L347.OBJ_TYPE_ID = 347 AND L347.DATE_DEL IS NULL
              INTO :GROUP_ID, :GROUP_TYPE_ID, :GROUP_NAME
          DO
          BEGIN
              SUSPEND;
          END

      END

  END
  ELSE
  BEGIN

      -- Для планов ВД дополнительно возвращаем зависшие без связи с ГУП потоки, чтобы исключить ошибку
      FOR
          SELECT L346.OBJ_ID, L346.OBJ_TYPE_ID, V2704.VAL, V2705.VAL, C51.CAPTION, IIF(L50.OBJ_ID = LP57.OBJ_ID, 1, 0)
          -- Поднимаемся до куста образовательных программ, и запоминаем уровень ОП
          FROM LINKS LP57
          JOIN VALL V1832 ON V1832.OBJ_ID = LP57.PARENT_ID AND V1832.PARAM_ID = 1832 AND V1832.IS_DEL = 0
          JOIN LINKS LP69 ON LP69.OBJ_ID = LP57.PARENT_ID AND LP69.PARENT_TYPE_ID = 69 AND LP69.DATE_DEL IS NULL
          -- Теперь спускаемся вниз
          JOIN LINKS L57 ON L57.PARENT_ID = LP69.PARENT_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
          JOIN VALL V1832D ON V1832D.OBJ_ID = L57.OBJ_ID AND V1832D.PARAM_ID = 1832 AND V1832D.IS_DEL = 0 AND V1832D.LISTVAL_ID = V1832.LISTVAL_ID
          JOIN LINKS L50 ON L50.PARENT_ID = L57.OBJ_ID AND L50.OBJ_TYPE_ID = 50 AND L50.DATE_DEL IS NULL
          JOIN VALL V2545 ON V2545.OBJ_ID = L50.OBJ_ID AND V2545.PARAM_ID = 2545 AND V2545.IS_DEL = 0 AND V2545.LISTVAL_ID = :V$PLAN_TYPE
          -- И далее по УП
          JOIN LINKS L54 ON L54.PARENT_ID = L50.OBJ_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
          JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0 AND V381.LISTVAL_ID = :STAGE_LV
          JOIN LINKS L346 ON L346.PARENT_ID = L54.OBJ_ID AND L346.OBJ_TYPE_ID = 346 AND L346.DATE_DEL IS NULL
          JOIN VALS V2704 ON V2704.OBJ_ID = L346.OBJ_ID AND V2704.PARAM_ID = 2704 AND V2704.IS_DEL = 0
          JOIN VALR V2705 ON V2705.OBJ_ID = L346.OBJ_ID AND V2705.PARAM_ID = 2705 AND V2705.IS_DEL = 0
          LEFT JOIN VALR V2914 ON V2914.OBJ_ID = L346.OBJ_ID AND V2914.PARAM_ID = 2914 AND V2914.IS_DEL = 0
          LEFT JOIN OBJECT_CAPTION_GET(V2705.VAL) C51 ON 1 = 1
          WHERE LP57.OBJ_ID = :PLAN_ID AND LP57.PARENT_TYPE_ID = 57 AND LP57.DATE_DEL IS NULL AND V2914.VAL IS NULL
          INTO :GROUP_ID, :GROUP_TYPE_ID, :GROUP_NAME, :SUBJECT_ID, :V$SUBJECT_NAME, :AFFECTS_THIS
      DO
      BEGIN

          PARENT_ID = NULL;
          GROUP_NAME = GROUP_NAME || ' - ' || V$SUBJECT_NAME;
          SUSPEND;

          SUBJECT_ID = NULL;
          PARENT_ID = GROUP_ID;

          FOR
              SELECT L347.OBJ_ID, L347.OBJ_TYPE_ID, V2706.VAL
              FROM LINKS L347
              JOIN VALS V2706 ON V2706.OBJ_ID = L347.OBJ_ID AND V2706.PARAM_ID = 2706 AND V2706.IS_DEL = 0
              WHERE L347.PARENT_ID = :PARENT_ID AND L347.OBJ_TYPE_ID = 347 AND L347.DATE_DEL IS NULL
              INTO :GROUP_ID, :GROUP_TYPE_ID, :GROUP_NAME
          DO
          BEGIN
              SUSPEND;
          END

      END

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE STAGE_GROUPS_MAP (
    PLAN_ID BIGINT,
    STAGE_LV BIGINT)
RETURNS (
    PUPIL_ID BIGINT,
    GROUP_ID BIGINT)
AS
declare variable V$PLAN_TYPE bigint;
begin

  SELECT V2545.LISTVAL_ID
  FROM VALL V2545
  WHERE V2545.OBJ_ID = :PLAN_ID AND V2545.PARAM_ID = 2545 AND V2545.IS_DEL = 0
  INTO :V$PLAN_TYPE;

  IF(V$PLAN_TYPE IS NULL) THEN EXIT;

  -- Идем по всем коллективам всех учебных планов
  FOR
      -- ГУП
      SELECT L256.OBJ_ID, L10.OBJ_ID
      -- Поднимаемся до куста образовательных программ, и запоминаем уровень ОП
      FROM LINKS LP57
      JOIN VALL V1832 ON V1832.OBJ_ID = LP57.PARENT_ID AND V1832.PARAM_ID = 1832 AND V1832.IS_DEL = 0
      JOIN LINKS LP69 ON LP69.OBJ_ID = LP57.PARENT_ID AND LP69.PARENT_TYPE_ID = 69 AND LP69.DATE_DEL IS NULL
      -- Теперь спускаемся вниз
      JOIN LINKS L57 ON L57.PARENT_ID = LP69.PARENT_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
      JOIN VALL V1832D ON V1832D.OBJ_ID = L57.OBJ_ID AND V1832D.PARAM_ID = 1832 AND V1832D.IS_DEL = 0 AND V1832D.LISTVAL_ID = V1832.LISTVAL_ID
      JOIN LINKS L50 ON L50.PARENT_ID = L57.OBJ_ID AND L50.OBJ_TYPE_ID = 50 AND L50.DATE_DEL IS NULL
      JOIN VALL V2545 ON V2545.OBJ_ID = L50.OBJ_ID AND V2545.PARAM_ID = 2545 AND V2545.IS_DEL = 0 AND V2545.LISTVAL_ID = :V$PLAN_TYPE
      -- И далее по УП
      JOIN LINKS L54 ON L54.PARENT_ID = L50.OBJ_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
      JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0 AND V381.LISTVAL_ID = :STAGE_LV
      JOIN LINKS L256 ON L256.PARENT_ID = L54.OBJ_ID AND L256.OBJ_TYPE_ID = 256 AND L256.DATE_DEL IS NULL
      JOIN LINKS L10 ON L10.PARENT_ID = L256.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      WHERE LP57.OBJ_ID = :PLAN_ID AND LP57.PARENT_TYPE_ID = 57 AND LP57.DATE_DEL IS NULL
      -- Потоки
      UNION
      SELECT L347.OBJ_ID, L10.OBJ_ID
      -- Поднимаемся до куста образовательных программ, и запоминаем уровень ОП
      FROM LINKS LP57
      JOIN VALL V1832 ON V1832.OBJ_ID = LP57.PARENT_ID AND V1832.PARAM_ID = 1832 AND V1832.IS_DEL = 0
      JOIN LINKS LP69 ON LP69.OBJ_ID = LP57.PARENT_ID AND LP69.PARENT_TYPE_ID = 69 AND LP69.DATE_DEL IS NULL
      -- Теперь спускаемся вниз
      JOIN LINKS L57 ON L57.PARENT_ID = LP69.PARENT_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
      JOIN VALL V1832D ON V1832D.OBJ_ID = L57.OBJ_ID AND V1832D.PARAM_ID = 1832 AND V1832D.IS_DEL = 0 AND V1832D.LISTVAL_ID = V1832.LISTVAL_ID
      JOIN LINKS L50 ON L50.PARENT_ID = L57.OBJ_ID AND L50.OBJ_TYPE_ID = 50 AND L50.DATE_DEL IS NULL
      JOIN VALL V2545 ON V2545.OBJ_ID = L50.OBJ_ID AND V2545.PARAM_ID = 2545 AND V2545.IS_DEL = 0 AND V2545.LISTVAL_ID = :V$PLAN_TYPE
      -- И далее по УП
      JOIN LINKS L54 ON L54.PARENT_ID = L50.OBJ_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
      JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0 AND V381.LISTVAL_ID = :STAGE_LV
      JOIN LINKS L346 ON L346.PARENT_ID = L54.OBJ_ID AND L346.OBJ_TYPE_ID = 346 AND L346.DATE_DEL IS NULL
      JOIN LINKS L347 ON L347.PARENT_ID = L346.OBJ_ID AND L347.OBJ_TYPE_ID = 347 AND L347.DATE_DEL IS NULL
      JOIN LINKS L10 ON L10.PARENT_ID = L347.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      WHERE LP57.OBJ_ID = :PLAN_ID AND LP57.PARENT_TYPE_ID = 57 AND LP57.DATE_DEL IS NULL
      INTO :GROUP_ID, :PUPIL_ID
  DO
  BEGIN
      SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE STAGE_PUPIL_LIST (
    PLAN_ID BIGINT,
    STAGE_LV BIGINT)
RETURNS (
    PUPIL_ID BIGINT,
    PUPIL_NAME VARCHAR(1000),
    GRADE_ID BIGINT,
    GRADE_NAME VARCHAR(100),
    GRADE_TYPE_ID BIGINT,
    GRADE_SORT DOUBLE PRECISION,
    ACCEPT_DATE DATE)
AS
declare variable V$PLAN_TYPE bigint;
declare variable V$SCHOOL_ID bigint;
declare variable V$ADAPT bigint;
begin

  -- Для общеобразовательных планов фильтр по параллели, для ВД все параллели в рамках УП
  SELECT V2545.LISTVAL_ID
  FROM VALL V2545
  WHERE V2545.OBJ_ID = :PLAN_ID AND V2545.PARAM_ID = 2545 AND V2545.IS_DEL = 0
  INTO :V$PLAN_TYPE;

  -- Восстанавливаем ID ОУ
  SELECT LP2.PARENT_ID, V2379.LISTVAL_ID
  FROM LINKS LP57
  JOIN VALL V2379 ON V2379.OBJ_ID = LP57.PARENT_ID AND V2379.PARAM_ID = 2379 AND V2379.IS_DEL = 0
  JOIN LINKS LP69 ON LP69.OBJ_ID = LP57.PARENT_ID AND LP69.PARENT_TYPE_ID = 69 AND LP69.DATE_DEL IS NULL
  JOIN LINKS LP2 ON LP2.OBJ_ID = LP69.PARENT_ID AND LP2.PARENT_TYPE_ID = 2 AND LP2.DATE_DEL IS NULL
  WHERE LP57.OBJ_ID = :PLAN_ID AND LP57.PARENT_TYPE_ID = 57 AND LP57.DATE_DEL IS NULL
  INTO :V$SCHOOL_ID, :V$ADAPT;

  IF(V$PLAN_TYPE IS NULL OR V$SCHOOL_ID IS NULL) THEN EXIT;

  IF(V$PLAN_TYPE = 3) THEN
  BEGIN
      -- Общеобразовательные планы: точно указанная параллель
      -- В случае с адаптированной ОП пересчитываем номер параллели из варианта ОВЗ в реальный
      -- !!! Нужно дофильтровать только учащихся с ОВЗ
      IF(V$ADAPT IS NOT NULL AND V$ADAPT <> 11187) THEN
      BEGIN
          SELECT FIRST 1 LV2.LISTVAL_ID
          FROM LISTVALS LV
          JOIN LISTVALS LV2 ON LV2.LIST_ID = LV.LIST_ID AND LV2.COST = LV.COST AND LV2.PARENT_ID = 2141
          WHERE LV.LISTVAL_ID = :STAGE_LV
          INTO :STAGE_LV;
      END

      FOR
          -- Реальные учащиеся параллели
          SELECT L9.OBJ_ID, C9.CAPTION, C9.SORT_ORDER, L9.OBJ_TYPE_ID, L10.OBJ_ID, CAST(V55.VAL || COALESCE(' ' || V56.VAL, '') AS VARCHAR(1000))
          FROM LINKS L7
          JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
          JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0 AND V49.LISTVAL_ID = :STAGE_LV
          JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 187) AND L9.DATE_DEL IS NULL
          LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C9 ON 1 = 1
          JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
          JOIN VALS V55 ON V55.OBJ_ID = L10.OBJ_ID AND V55.PARAM_ID = 55 AND V55.IS_DEL = 0
          LEFT JOIN VALS V56 ON V56.OBJ_ID = L10.OBJ_ID AND V56.PARAM_ID = 56 AND V56.IS_DEL = 0
          WHERE L7.PARENT_ID = :V$SCHOOL_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
          -- Добавляем сюда действующих участников ГУП и потоков этой параллели, но переведенных в другие классы
          UNION
          SELECT LP9.PARENT_ID, C9.CAPTION, C9.SORT_ORDER, LP9.PARENT_TYPE_ID, L10.OBJ_ID, CAST(V55.VAL || COALESCE(' ' || V56.VAL, '') AS VARCHAR(1000))
          FROM LINKS L54
          JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0 AND V381.LISTVAL_ID = :STAGE_LV
          JOIN LINKS L256 ON L256.PARENT_ID = L54.OBJ_ID AND L256.OBJ_TYPE_ID = 256 AND L256.DATE_DEL IS NULL
          JOIN LINKS L10 ON L10.PARENT_ID = L256.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
          JOIN LINKS LP9 ON LP9.OBJ_ID = L10.OBJ_ID AND LP9.PARENT_TYPE_ID IN (9, 187) AND LP9.DATE_DEL IS NULL
          LEFT JOIN OBJECT_CAPTION_GET(LP9.PARENT_ID) C9 ON 1 = 1
          JOIN VALS V55 ON V55.OBJ_ID = L10.OBJ_ID AND V55.PARAM_ID = 55 AND V55.IS_DEL = 0
          LEFT JOIN VALS V56 ON V56.OBJ_ID = L10.OBJ_ID AND V56.PARAM_ID = 56 AND V56.IS_DEL = 0
          WHERE L54.PARENT_ID = :PLAN_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
          UNION
          SELECT LP9.PARENT_ID, C9.CAPTION, C9.SORT_ORDER, LP9.PARENT_TYPE_ID, L10.OBJ_ID, CAST(V55.VAL || COALESCE(' ' || V56.VAL, '') AS VARCHAR(1000))
          FROM LINKS L54
          JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0 AND V381.LISTVAL_ID = :STAGE_LV
          JOIN LINKS L346 ON L346.PARENT_ID = L54.OBJ_ID AND L346.OBJ_TYPE_ID = 346 AND L346.DATE_DEL IS NULL
          JOIN LINKS L347 ON L347.PARENT_ID = L346.OBJ_ID AND L347.OBJ_TYPE_ID = 347 AND L347.DATE_DEL IS NULL
          JOIN LINKS L10 ON L10.PARENT_ID = L347.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
          JOIN LINKS LP9 ON LP9.OBJ_ID = L10.OBJ_ID AND LP9.PARENT_TYPE_ID IN (9, 187) AND LP9.DATE_DEL IS NULL
          LEFT JOIN OBJECT_CAPTION_GET(LP9.PARENT_ID) C9 ON 1 = 1
          JOIN VALS V55 ON V55.OBJ_ID = L10.OBJ_ID AND V55.PARAM_ID = 55 AND V55.IS_DEL = 0
          LEFT JOIN VALS V56 ON V56.OBJ_ID = L10.OBJ_ID AND V56.PARAM_ID = 56 AND V56.IS_DEL = 0
          WHERE L54.PARENT_ID = :PLAN_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
          -- А также учеников-потеряшек
          UNION
          SELECT NULL, '?', 9999, 9, L10.OBJ_ID, CAST(V55.VAL || COALESCE(' ' || V56.VAL, '') AS VARCHAR(1000))
          FROM LINKS L54
          JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0 AND V381.LISTVAL_ID = :STAGE_LV
          JOIN LINKS L256 ON L256.PARENT_ID = L54.OBJ_ID AND L256.OBJ_TYPE_ID = 256 AND L256.DATE_DEL IS NULL
          JOIN LINKS L10 ON L10.PARENT_ID = L256.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
          JOIN VALS V55 ON V55.OBJ_ID = L10.OBJ_ID AND V55.PARAM_ID = 55 AND V55.IS_DEL = 0
          LEFT JOIN VALS V56 ON V56.OBJ_ID = L10.OBJ_ID AND V56.PARAM_ID = 56 AND V56.IS_DEL = 0
          WHERE L54.PARENT_ID = :PLAN_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
              AND NOT EXISTS(SELECT 1 FROM LINKS LP9 WHERE LP9.OBJ_ID = L10.OBJ_ID AND LP9.PARENT_TYPE_ID IN (9, 187) AND LP9.DATE_DEL IS NULL)
          UNION
          SELECT NULL, '?', 999, 9, L10.OBJ_ID, CAST(V55.VAL || COALESCE(' ' || V56.VAL, '') AS VARCHAR(1000))
          FROM LINKS L54
          JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0 AND V381.LISTVAL_ID = :STAGE_LV
          JOIN LINKS L346 ON L346.PARENT_ID = L54.OBJ_ID AND L346.OBJ_TYPE_ID = 346 AND L346.DATE_DEL IS NULL
          JOIN LINKS L347 ON L347.PARENT_ID = L346.OBJ_ID AND L347.OBJ_TYPE_ID = 347 AND L347.DATE_DEL IS NULL
          JOIN LINKS L10 ON L10.PARENT_ID = L347.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
          JOIN VALS V55 ON V55.OBJ_ID = L10.OBJ_ID AND V55.PARAM_ID = 55 AND V55.IS_DEL = 0
          LEFT JOIN VALS V56 ON V56.OBJ_ID = L10.OBJ_ID AND V56.PARAM_ID = 56 AND V56.IS_DEL = 0
          WHERE L54.PARENT_ID = :PLAN_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
              AND NOT EXISTS(SELECT 1 FROM LINKS LP9 WHERE LP9.OBJ_ID = L10.OBJ_ID AND LP9.PARENT_TYPE_ID IN (9, 187) AND LP9.DATE_DEL IS NULL)
          INTO :GRADE_ID, :GRADE_NAME, :GRADE_SORT, :GRADE_TYPE_ID, :PUPIL_ID, :PUPIL_NAME
     DO
     BEGIN
          -- Дата зачисления учащегося в текущий класс (берем вообще любое движение - если ученик есть, он явно не выбывший)\
          SELECT FIRST 1 M.DATE_IN
          FROM PERSON_MOVEMENTS M
          JOIN OBJECTS O ON O.OBJ_ID = M.GROUP_ID AND O.TYPE_ID IN (9, 187, 243)
          WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :PUPIL_ID
          ORDER BY M.DATE_IN DESC
          INTO :ACCEPT_DATE;

          SUSPEND;
     END
  END
  ELSE
  BEGIN
      -- Планы ВД: все параллели, которые есть в плане
      FOR
          SELECT L9.OBJ_ID, C9.CAPTION, C9.SORT_ORDER, L9.OBJ_TYPE_ID, L10.OBJ_ID, V55.VAL || COALESCE(' ' || V56.VAL, '')
          FROM LINKS L7
          JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
          JOIN LINKS L54 ON L54.PARENT_ID = :PLAN_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
          JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
          JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0 AND V49.LISTVAL_ID = V381.LISTVAL_ID
          JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 187) AND L9.DATE_DEL IS NULL
          LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C9 ON 1 = 1
          JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
          JOIN VALS V55 ON V55.OBJ_ID = L10.OBJ_ID AND V55.PARAM_ID = 55 AND V55.IS_DEL = 0
          LEFT JOIN VALS V56 ON V56.OBJ_ID = L10.OBJ_ID AND V56.PARAM_ID = 56 AND V56.IS_DEL = 0
          WHERE L7.PARENT_ID = :V$SCHOOL_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
          INTO :GRADE_ID, :GRADE_NAME, :GRADE_SORT, :GRADE_TYPE_ID, :PUPIL_ID, :PUPIL_NAME
     DO
     BEGIN
          -- Дата зачисления учащегося в текущий класс (берем вообще любое движение - если ученик есть, он явно не выбывший)
          SELECT FIRST 1 M.DATE_IN
          FROM PERSON_MOVEMENTS M
          JOIN OBJECTS O ON O.OBJ_ID = M.GROUP_ID AND O.TYPE_ID IN (9, 187, 243)
          WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :PUPIL_ID
          ORDER BY M.DATE_IN DESC
          INTO :ACCEPT_DATE;

          SUSPEND;
     END
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE STAGE_SUBJECTS_LIST (
    PLAN_ID BIGINT,
    STAGE_LV BIGINT)
RETURNS (
    SUBJECT_ID BIGINT,
    SUBJECT_NAME VARCHAR(1000),
    SORT_INDEX DOUBLE PRECISION)
AS
DECLARE VARIABLE V$PLAN_TYPE BIGINT;
DECLARE VARIABLE V$OU_LICENCE_TYPE CHAR(1);
begin

  -- Смысл процедуры утрачен после перехода на УП нового типа

  SELECT STATUS FROM OU_LICENCE_TYPE INTO :V$OU_LICENCE_TYPE;

  -- Для общеобразовательных планов фильтр по параллели, для ВД все параллели в рамках УП (только для школ)
  SELECT V2545.LISTVAL_ID
  FROM VALL V2545
  WHERE V2545.OBJ_ID = :PLAN_ID AND V2545.PARAM_ID = 2545 AND V2545.IS_DEL = 0
  INTO :V$PLAN_TYPE;

  IF(V$OU_LICENCE_TYPE = 'O' AND V$PLAN_TYPE IS NULL) THEN EXIT;

  -- В любом случае выдаем список предметов, отфильтрованный для выбранного этапа

  FOR
      -- Школа
      SELECT DISTINCT LP51.PARENT_ID, C51.CAPTION, C51.SORT_ORDER
      FROM LINKS L54
      JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0 AND V381.LISTVAL_ID = :STAGE_LV
      JOIN LINKS L56 ON L56.PARENT_ID = L54.OBJ_ID AND L56.OBJ_TYPE_ID = 56 AND L56.DATE_DEL IS NULL
      JOIN VALI V385 ON V385.OBJ_ID = L56.OBJ_ID AND V385.PARAM_ID = 385 AND V385.IS_DEL = 0 AND V385.VAL > 0
      JOIN LINKS LP51 ON LP51.OBJ_ID = L56.OBJ_ID AND LP51.PARENT_TYPE_ID = 51 AND LP51.DATE_DEL IS NULL
      LEFT JOIN OBJECT_CAPTION_GET(LP51.PARENT_ID) C51 ON 1 = 1
      WHERE L54.PARENT_ID = :PLAN_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL AND :V$OU_LICENCE_TYPE = 'O'
      -- Для колледжей все сложнее
      UNION
      SELECT DISTINCT T.SUBJECT_ID, C51.CAPTION, C51.SORT_ORDER
      FROM LINKS L54
      JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0 AND V381.LISTVAL_ID = :STAGE_LV
      LEFT JOIN DISCIPLINE_SUBTREE(L54.OBJ_ID) T ON 1 = 1
      LEFT JOIN OBJECT_CAPTION_GET(T.SUBJECT_ID) C51 ON 1 = 1
      WHERE L54.PARENT_ID = :PLAN_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL AND :V$OU_LICENCE_TYPE = 'C'
      INTO :SUBJECT_ID, :SUBJECT_NAME, :SORT_INDEX
  DO
  BEGIN
      SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE STAT_UPDATE_FIELD (
    I$FIELD_ID BIGINT,
    I$GROUPING_ID BIGINT,
    I$PERIOD INTEGER,
    I$VAL DOUBLE PRECISION)
AS
declare variable N integer;
declare variable V$DATE date;
declare variable V$ORG_ID bigint;
begin

  V$DATE = CURRENT_DATE;
  IF(I$PERIOD = 0) THEN
  BEGIN
    -- Еженедельно
    N = EXTRACT(WEEKDAY FROM V$DATE);
    IF(N = 0) THEN N = 6; ELSE N = N - 1;
    V$DATE = DATEADD(- N DAY TO V$DATE);
  END
  ELSE IF(I$PERIOD = 2) THEN
  BEGIN
    -- Ежемесячно
    N = EXTRACT(DAY FROM V$DATE) - 1;
    V$DATE = DATEADD(- N DAY TO V$DATE);
  END

  SELECT FIRST 1 L2.OBJ_ID
  FROM LINKS L2
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$ORG_ID;

  UPDATE OR INSERT INTO CJ2_STUDENT_RATING
  (STUDENT_ID, SUBJECT_ID, FIELD_ID, RATE_DATE, RATE_VALUE)
  VALUES (:V$ORG_ID, :I$GROUPING_ID, :I$FIELD_ID, :V$DATE, :I$VAL)
  MATCHING (STUDENT_ID, SUBJECT_ID, FIELD_ID, RATE_DATE);

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE STDFORM_LIST (
    I$OBJ_ID BIGINT,
    I$LIST_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    PARENT_ID BIGINT,
    LISTVAL_ID BIGINT,
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$STATUS VARCHAR(1);
DECLARE VARIABLE V$LEVEL_ID BIGINT;
DECLARE VARIABLE F VARCHAR(100);
begin
  V$STATUS = (SELECT STATUS FROM OU_LICENCE_TYPE);

  IF(V$STATUS = 'O') THEN F = '%GOU%';
  ELSE IF(V$STATUS = 'D') THEN F = '%DOU%';
  ELSE IF(V$STATUS = 'C') THEN F = '%COLLEGE%';
  ELSE IF(V$STATUS = 'U') THEN F = '%UDOD%';
  ELSE IF(V$STATUS = 'S') THEN
  BEGIN
    SELECT FIRST 1 V43.LISTVAL_ID
    FROM LINKS LP8
    JOIN LINKS LP7 ON LP7.OBJ_ID = LP8.PARENT_ID AND LP7.PARENT_TYPE_ID = 7 AND LP7.DATE_DEL IS NULL
    JOIN VALL V43 ON V43.OBJ_ID = LP7.PARENT_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0
    WHERE LP8.OBJ_ID = :I$OBJ_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
    INTO :V$LEVEL_ID;

    IF(V$LEVEL_ID IN (22, 26, 27)) THEN F = '%GOU%';
    ELSE IF(V$LEVEL_ID IN (3263, 3264)) THEN F = '%DOU%';
    ELSE IF(V$LEVEL_ID IN (28, 29, 13129, 13131)) THEN F = '%COLLEGE%';
    ELSE IF(V$LEVEL_ID IN (13128)) THEN F = '%UDOD%';
  END

  FOR
    SELECT PARENT_ID, LISTVAL_ID, VAL
    FROM LISTVALS_LIST(:I$LIST_ID)
    WHERE IS_DEL = 0 AND (:F IS NULL OR "FILTER" LIKE :F)
    INTO :PARENT_ID, :LISTVAL_ID, :VAL
  DO
  BEGIN
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE STDWEEK_LIST (
    I$OBJ_ID BIGINT,
    I$LIST_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    PARENT_ID BIGINT,
    LISTVAL_ID BIGINT,
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$STATUS VARCHAR(1);
DECLARE VARIABLE V$LEVEL_ID BIGINT;
DECLARE VARIABLE F VARCHAR(100);
begin
  V$STATUS = (SELECT STATUS FROM OU_LICENCE_TYPE);

  IF(V$STATUS = 'O') THEN F = '%GOU%';
  ELSE IF(V$STATUS = 'D') THEN F = '%DOU%';
  ELSE IF(V$STATUS = 'C') THEN F = '%COLLEGE%';
  ELSE IF(V$STATUS = 'U') THEN F = '%UDOD%';
  ELSE IF(V$STATUS = 'S') THEN
  BEGIN
    SELECT FIRST 1 V43.LISTVAL_ID
    FROM LINKS LP8
    JOIN LINKS LP7 ON LP7.OBJ_ID = LP8.PARENT_ID AND LP7.PARENT_TYPE_ID = 7 AND LP7.DATE_DEL IS NULL
    JOIN VALL V43 ON V43.OBJ_ID = LP7.PARENT_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0
    WHERE LP8.OBJ_ID = :I$OBJ_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
    INTO :V$LEVEL_ID;

    IF(V$LEVEL_ID IN (22, 26, 27)) THEN F = '%GOU%';
    ELSE IF(V$LEVEL_ID IN (3263, 3264)) THEN F = '%DOU%';
    ELSE IF(V$LEVEL_ID IN (28, 29, 13129, 13131)) THEN F = '%COLLEGE%';
    ELSE IF(V$LEVEL_ID IN (13128)) THEN F = '%UDOD%';
  END

  FOR
    SELECT PARENT_ID, LISTVAL_ID, VAL
    FROM LISTVALS_LIST(:I$LIST_ID)
    WHERE IS_DEL = 0 AND (:F IS NULL OR "FILTER" LIKE :F)
    INTO :PARENT_ID, :LISTVAL_ID, :VAL
  DO
  BEGIN
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE STEAD_DELETE (
    I$OBJ_ID BIGINT)
AS
declare variable S varchar(1000);
begin

  SELECT FIRST 1 C.CAPTION
  FROM VALR V
  JOIN LINKS LPG ON LPG.OBJ_ID = V.OBJ_ID AND LPG.PARENT_TYPE_ID = 73 AND LPG.DATE_DEL IS NULL
  LEFT JOIN OBJECT_CAPTION_GET(LPG.OBJ_ID) C ON LPG.OBJ_ID IS NOT NULL
  WHERE V.VAL = :I$OBJ_ID AND V.PARAM_ID IN (3407, 3408) AND V.IS_DEL = 0
  INTO :S;

  IF(S IS NOT NULL) THEN EXCEPTION DATA_ERROR 'На данном земельном участке числяться здания или сооружения, проверьте ' || S;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE STREAM_CREATE (
    STAGE_ID BIGINT,
    SUBJECT_ID BIGINT)
RETURNS (
    STREAMS_ID BIGINT)
AS
declare variable TMP bigint;
begin

  -- Проверяем, чтобы деления уже не было
  SELECT FIRST 1 L346.OBJ_ID
  FROM LINKS L346
  JOIN VALR V2705 ON V2705.OBJ_ID = L346.OBJ_ID AND V2705.PARAM_ID = 2705 AND V2705.IS_DEL = 0 AND V2705.VAL = :SUBJECT_ID
  WHERE L346.PARENT_ID = :STAGE_ID AND L346.OBJ_TYPE_ID = 346 AND L346.DATE_DEL is null
  INTO :STREAMS_ID;

  IF(STREAMS_ID IS NULL) THEN
  BEGIN
    SELECT OBJ_ID FROM OBJECT_ADD(:STAGE_ID, 346) INTO :STREAMS_ID;
    SELECT BLOB_ID FROM VAL_ADD(2705, :STREAMS_ID, :SUBJECT_ID) INTO :TMP;
  END

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE STREAM_MOVE_PUPIL (
    I$PUPIL_ID BIGINT,
    I$STREAM_ID BIGINT,
    I$USER_ID BIGINT,
    I$MOVE_TYPE_ID INTEGER = null,
    I$MOVE_DATE DATE = null,
    I$MOVEMENT_SOURCE_ID BIGINT = 902,
    I$LINK_CURGROUP SMALLINT = 0)
AS
declare variable V$BLOB_ID bigint;
declare variable V$MOVEMENT_ID bigint;
declare variable V$CAPTION varchar(1000);
BEGIN


  -- Функционал перенесен в VARRGP*

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE STREAM_MOVE_PUPIL_FRC (
    I$PUPIL_ID BIGINT,
    I$GUP_ID BIGINT,
    I$USER_ID BIGINT,
    I$MOVE_TYPE_ID INTEGER,
    I$MOVE_DATE DATE,
    I$MOVEMENT_SOURCE_ID BIGINT)
AS
declare variable V$G_TYPE bigint;
declare variable V$G_ID bigint;
BEGIN

  -- Функцинал утрачен

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE STREAM_SCHOOLARS_LIST (
    I$STREAM_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    PARENT_ID BIGINT,
    TREE_PARENT_ID VARCHAR(255),
    OBJ_ID BIGINT,
    TREE_OBJ_ID VARCHAR(255),
    TYPE_ID BIGINT,
    OBJ_CAPTION VARCHAR(4000),
    COLOR INTEGER,
    SORT_ORDER VARCHAR(4000))
AS
declare variable V$SCHOOL_ID bigint;
declare variable V$STAGE_ID bigint;
declare variable V$DIVISION_ID bigint;
declare variable V$CLASS_ID bigint;
declare variable V$I smallint;
declare variable V$CLASS_CAPTION varchar(1000);
BEGIN
    SELECT FIRST 1 OBJ_ID FROM OBJECT_PARENTS_GET(:I$STREAM_ID, 346) INTO :V$DIVISION_ID;
    SELECT FIRST 1 OBJ_ID FROM OBJECT_PARENTS_GET(:I$STREAM_ID, 2) INTO :V$SCHOOL_ID;
    SELECT FIRST 1 OBJ_ID FROM OBJECT_PARENTS_GET(:I$STREAM_ID, 54) INTO :V$STAGE_ID;

    FOR
        SELECT L9.OBJ_ID, C.CAPTION
        FROM LINKS L7
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
        JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
        JOIN VALL V381 ON V381.OBJ_ID = :V$STAGE_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0 AND V381.LISTVAL_ID = V49.LISTVAL_ID
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
        LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID, 50, NULL, :I$USER_ID) C ON 1 = 1
        WHERE L7.PARENT_ID = :V$SCHOOL_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
        INTO :V$CLASS_ID, :V$CLASS_CAPTION
    DO
    BEGIN
        V$I = 0;
        FOR
            SELECT L10.PARENT_ID, L10.PARENT_ID, L10.OBJ_ID, L10.OBJ_ID, L10.OBJ_TYPE_ID
            FROM LINKS L10
            WHERE L10.PARENT_ID = :V$CLASS_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
            AND NOT EXISTS(
                SELECT FIRST 1 1
                FROM LINKS L347
                JOIN LINKS L10_2 ON L10_2.PARENT_ID = L347.OBJ_ID AND L10_2.OBJ_TYPE_ID = 10 AND L10_2.DATE_DEL IS NULL AND L10_2.OBJ_ID = L10.OBJ_ID
                WHERE L347.PARENT_ID = :V$DIVISION_ID AND l347.OBJ_TYPE_ID = 347 and l347.DATE_DEL is null
            )
            INTO :PARENT_ID, :TREE_PARENT_ID, :OBJ_ID, :TREE_OBJ_ID, :TYPE_ID
        DO
        BEGIN
            V$I = 1;
            -- Ученики
            SELECT CAPTION, COLOR, :V$CLASS_CAPTION || '  ' || CAPTION
            FROM OBJECT_CAPTION_GET(:OBJ_ID, NULL, NULL, :I$USER_ID)
            INTO :OBJ_CAPTION, :COLOR, :SORT_ORDER;
            SUSPEND;
        END
        IF (V$I = 1) THEN
        BEGIN
            -- Если в классе были ученики, то выдаем в конце сам класс
            PARENT_ID = NULL;
            TREE_PARENT_ID = NULL;
            OBJ_ID = :V$CLASS_ID;
            TREE_OBJ_ID = :V$CLASS_ID;
            TYPE_ID = 9;

            SELECT CAPTION, COLOR, CAPTION
            FROM OBJECT_CAPTION_GET(:OBJ_ID, 50, NULL, :I$USER_ID)
            INTO :OBJ_CAPTION, :COLOR, :SORT_ORDER;

            SUSPEND;
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE STRING_PART (
    I$VALS VARCHAR(4000),
    I$PART SMALLINT,
    I$LENGTH INTEGER)
RETURNS (
    VAL VARCHAR(2000))
AS
declare variable V$I integer;
declare variable V$I2 integer;
declare variable V$I3 integer;
declare variable V$STR varchar(4000);
declare variable V$LENGTH integer;
declare variable V$POS integer;
BEGIN
    V$I = 1;
    V$LENGTH = CHAR_LENGTH(:I$VALS);
    IF (:V$LENGTH = 0) THEN
    BEGIN
        VAL = '';
        SUSPEND;
        EXIT;
    END
    V$I2 = 0;
    WHILE (:V$I2 <= :I$PART) DO
    BEGIN
        V$I2 = :V$I2 + 1;
        V$STR = '';
        WHILE (:V$STR = '' AND :V$I <= :V$LENGTH) DO
        BEGIN
            V$STR = SUBSTRING(:I$VALS FROM :V$I FOR I$LENGTH);
            WHILE (SUBSTRING(:V$STR FROM 1 FOR 1) IN (ASCII_CHAR(13), ASCII_CHAR(10), ' ')) DO
            BEGIN
                V$I = :V$I + 1;
                V$STR = SUBSTRING(:I$VALS FROM :V$I FOR :I$LENGTH);
            END
            WHILE (SUBSTRING(:V$STR FROM CHAR_LENGTH(:V$STR) FOR 1) IN (ASCII_CHAR(13), ASCII_CHAR(10), ' ')) DO
            BEGIN
                V$STR = SUBSTRING(:V$STR FROM 1 FOR CHAR_LENGTH(:V$STR) - 1);
            END
            IF (:V$STR = '') THEN
            BEGIN
                V$I = :V$I + :I$LENGTH;
            END
        END
        V$POS = POSITION(ASCII_CHAR(13) || ASCII_CHAR(10), :V$STR);
        IF (CHAR_LENGTH(:V$STR) = :I$LENGTH) THEN
        BEGIN
            IF (:V$POS > 0) THEN
            BEGIN
                V$STR = SUBSTRING(:V$STR FROM 1 FOR :V$POS - 1);
            END
            ELSE
            BEGIN
                IF (SUBSTRING(:I$VALS FROM :V$I + :I$LENGTH FOR 1) NOT IN (' ', ASCII_CHAR(13), ASCII_CHAR(10)) AND POSITION(' ', :V$STR) > 0) THEN
                BEGIN
                    V$I3 = CHAR_LENGTH(:V$STR);
                    WHILE (SUBSTRING(:V$STR FROM :V$I3 FOR 1) <> ' ') DO
                    BEGIN
                        V$I3 = :V$I3 - 1;
                    END
                    V$STR = SUBSTRING(:V$STR FROM 1 FOR :V$I3);
                END
            END
        END
        ELSE
        BEGIN
            IF (:V$POS > 0) THEN
            BEGIN
                V$STR = SUBSTRING(:V$STR FROM 1 FOR :V$POS - 1);
            END
        END
        IF (:V$POS > 0) THEN
        BEGIN
            V$POS = 1;
        END
        V$I = :V$I + CHAR_LENGTH(:V$STR) + :V$POS;
    END
    VAL = TRIM(:V$STR);
    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE STRUCTURE_OO_EMPLOYEE_LIST (
    I$USER_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    PARENT_ID BIGINT,
    OBJ_CAPTION VARCHAR(4000))
AS
DECLARE VARIABLE V$SCHOOL_ID BIGINT;
BEGIN
    PARENT_ID = NULL;

    SELECT OBJ_ID
    FROM LINKS
    WHERE PARENT_ID IS NULL
    AND OBJ_TYPE_ID = 2
    AND DATE_DEL IS NULL
    INTO :V$SCHOOL_ID;

    FOR
        SELECT DISTINCT L14.OBJ_ID
        FROM LINKS L14

        WHERE L14.PARENT_ID IN (
                SELECT OBJ_ID
                FROM LINKS L
                WHERE L.PARENT_ID = :V$SCHOOL_ID
                AND L.DATE_DEL IS NULL
                AND L.OBJ_TYPE_ID = 211
    
                UNION ALL
    
                SELECT :V$SCHOOL_ID
                FROM RDB$DATABASE
            )
        AND L14.OBJ_TYPE_ID = 14
        AND L14.DATE_DEL IS NULL

        AND EXISTS(
            SELECT FIRST 1 1
            FROM LINKS L15

            JOIN VALR V69
            ON V69.OBJ_ID = L15.OBJ_ID
            AND V69.PARAM_ID = 69
            AND V69.IS_DEL = 0

            JOIN VALL V64
            ON V64.OBJ_ID = V69.VAL
            AND V64.PARAM_ID = 64
            AND V64.IS_DEL = 0
            AND V64.LISTVAL_ID IN (113, 70)

            LEFT JOIN VAL_GET(L15.OBJ_ID, 73) V73 ON 1=1
            LEFT JOIN VAL_GET(L15.OBJ_ID, 74) V74 ON 1=1

            WHERE L15.PARENT_ID = L14.OBJ_ID
            AND L15.OBJ_TYPE_ID = 15
            AND L15.DATE_DEL IS NULL
            AND V73.DT <= CURRENT_TIMESTAMP
            AND ((V74.DT IS NULL) OR (V74.DT > CURRENT_TIMESTAMP))
        )

        INTO :OBJ_ID
    DO
    BEGIN
        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:OBJ_ID, NULL, NULL, :I$USER_ID)
        INTO :OBJ_CAPTION;
        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE STRUCTURE_OO_POSITION_LIST (
    I$USER_ID BIGINT)
RETURNS (
    LISTVAL_ID BIGINT,
    PARENT_ID BIGINT,
    VAL VARCHAR(4000),
    VAL_LONG VARCHAR(4000),
    TAG VARCHAR(100))
AS
declare variable V$RES_ID bigint;
declare variable V$LANG_CODE char(2);
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :V$LANG_CODE;

    FOR
        SELECT LISTVAL_ID,
               PARENT_ID,
               TAG,
               RES_ID
        FROM LISTVALS LV

        WHERE LV.LIST_ID = 21
        AND LV.IS_DEL = 0
        AND (LV.LISTVAL_ID IN (55,113,70) OR LV.TAG IN ('R2','R3'))
        ORDER BY LV.SORT_ORDER

        INTO :LISTVAL_ID,
             :PARENT_ID,
             :TAG,
             :V$RES_ID
    DO
    BEGIN
        SELECT VAL,
               VAL_LONG
        FROM RES_GET(:V$RES_ID, :V$LANG_CODE)
        INTO :VAL,
             :VAL_LONG;
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE STRUCTURE_OO_REPORT (
    I$OBJ_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    "LEVEL" SMALLINT,
    NAME VARCHAR(1000),
    SHORTNAME VARCHAR(1000),
    EMPLOYEE VARCHAR(1000))
AS
declare variable V$LEVEL1_ID bigint;
declare variable V$LEVEL2_ID bigint;
declare variable V$LEVEL3_ID bigint;
declare variable V$TMP varchar(1000);
BEGIN
    FOR
        SELECT L211.OBJ_ID,
               1
        FROM LINKS L211

        WHERE L211.PARENT_ID = :I$OBJ_ID
        AND L211.OBJ_TYPE_ID = 211
        AND L211.DATE_DEL IS NULL

        INTO :V$LEVEL1_ID,
             :"LEVEL"
    DO
    BEGIN
        SELECT V
        FROM VAL_GET(:V$LEVEL1_ID, 1791, 0, :I$USER_ID)
        INTO :NAME;

        SELECT V
        FROM VAL_GET(:V$LEVEL1_ID, 1792, 0, :I$USER_ID)
        INTO :SHORTNAME;

        SELECT V
        FROM VAL_GET(:V$LEVEL1_ID, 1793, 0, :I$USER_ID)
        INTO :V$TMP;

        SELECT V
        FROM VAL_GET(:V$LEVEL1_ID, 1794, 0, :I$USER_ID)
        INTO :EMPLOYEE;

        IF (V$TMP <> '') THEN
        BEGIN
            EMPLOYEE = V$TMP || ': ' || EMPLOYEE;
        END
        SUSPEND;

        FOR
            SELECT L212.OBJ_ID,
                   2
            FROM LINKS L212

            WHERE L212.PARENT_ID = :V$LEVEL1_ID
            AND L212.OBJ_TYPE_ID = 212
            AND L212.DATE_DEL IS NULL

            INTO :V$LEVEL2_ID,
                 :"LEVEL"
        DO
        BEGIN
            SELECT V
            FROM VAL_GET(:V$LEVEL2_ID, 1795, 0, :I$USER_ID)
            INTO :NAME;
    
            SELECT V
            FROM VAL_GET(:V$LEVEL2_ID, 1796, 0, :I$USER_ID)
            INTO :SHORTNAME;
    
            SELECT V
            FROM VAL_GET(:V$LEVEL2_ID, 1797, 0, :I$USER_ID)
            INTO :V$TMP;
    
            SELECT V
            FROM VAL_GET(:V$LEVEL2_ID, 1798, 0, :I$USER_ID)
            INTO :EMPLOYEE;
    
            IF (V$TMP <> '') THEN
            BEGIN
                EMPLOYEE = V$TMP || ': ' || EMPLOYEE;
            END
            SUSPEND;

            FOR
                SELECT L213.OBJ_ID,
                       3
                FROM LINKS L213
    
                WHERE L213.PARENT_ID = :V$LEVEL2_ID
                AND L213.OBJ_TYPE_ID = 213
                AND L213.DATE_DEL IS NULL
    
                INTO :V$LEVEL3_ID,
                     :"LEVEL"
            DO
            BEGIN
                SELECT V
                FROM VAL_GET(:V$LEVEL3_ID, 1799, 0, :I$USER_ID)
                INTO :NAME;
        
                SELECT V
                FROM VAL_GET(:V$LEVEL3_ID, 1800, 0, :I$USER_ID)
                INTO :SHORTNAME;
        
                SELECT V
                FROM VAL_GET(:V$LEVEL3_ID, 1801, 0, :I$USER_ID)
                INTO :V$TMP;
        
                SELECT V
                FROM VAL_GET(:V$LEVEL3_ID, 1802, 0, :I$USER_ID)
                INTO :EMPLOYEE;
        
                IF (V$TMP <> '') THEN
                BEGIN
                    EMPLOYEE = V$TMP || ': ' || EMPLOYEE;
                END
                SUSPEND;
            END
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE STR_IN_LIST (
    VAL_S VARCHAR(100),
    S VARCHAR(2000),
    SEPARATOR CHAR(1) = ',')
RETURNS (
    IS_PRESENT SMALLINT)
AS
declare variable P integer;
begin
  IS_PRESENT = 0;

  WHILE(CHAR_LENGTH(S) > 0) DO
  BEGIN

    P = POSITION(SEPARATOR, S);
    IF(P = 0) THEN P = CHAR_LENGTH(S) + 1;

    IF(SUBSTRING(S FROM 1 FOR P - 1) = VAL_S) THEN
    BEGIN
      IS_PRESENT = 1;
      S = '';
    END
    ELSE
    BEGIN
      S = SUBSTRING(S FROM P + 1 FOR 2000);
    END

  END

  SUSPEND;
end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE STR_REMOVE_FROM_LIST (
    IN_S VARCHAR(2000),
    REMOVE_S VARCHAR(100),
    SEPARATOR CHAR(1) = ',')
RETURNS (
    OUT_S VARCHAR(2000))
AS
declare variable P integer;
begin
  OUT_S = '';

  WHILE(CHAR_LENGTH(IN_S) > 0) DO
  BEGIN

    P = POSITION(SEPARATOR, IN_S);
    IF(P <= 0) THEN P = CHAR_LENGTH(IN_S) + 1;

    IF(REMOVE_S <> SUBSTRING(IN_S FROM 1 FOR P - 1)) THEN
    BEGIN
      IF(OUT_S <> '') THEN OUT_S = OUT_S || SEPARATOR;
      OUT_S = OUT_S || SUBSTRING(IN_S FROM 1 FOR P - 1);
    END

    IN_S = SUBSTRING(IN_S FROM P + 1 FOR 2000);

  END

  SUSPEND;
end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE STR_TO_ID_LIST (
    I$LIST VARCHAR(4000))
RETURNS (
    ID BIGINT)
AS
declare variable P integer;
begin
  WHILE(I$LIST IS NOT NULL AND CHAR_LENGTH(I$LIST) > 0) DO
  BEGIN
    P = POSITION(',' IN I$LIST);
    IF(P <= 0) THEN P = CHAR_LENGTH(I$LIST) + 1;
    ID = CAST(SUBSTRING(I$LIST FROM 1 FOR P - 1) AS BIGINT);
    SUSPEND;

    I$LIST = SUBSTRING(I$LIST FROM P + 1);
  END
end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE STR_TO_YEAR (
    S VARCHAR(100))
RETURNS (
    Y INTEGER)
AS
begin

  IF(CHAR_LENGTH(S) = 2) THEN
  BEGIN
      IF(CAST(S AS INTEGER) < 50) THEN Y = '20' || S; ELSE Y = '19' || S;
  END
  ELSE IF(CHAR_LENGTH(S) = 4) THEN
  BEGIN
      Y = S;
  END
  ELSE IF(CHAR_LENGTH(S) = 10) THEN
  BEGIN
      Y = EXTRACT(YEAR FROM CAST(S AS DATE));
  END
  ELSE Y = NULL;

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE STUDENTS_LIST_12932 RETURNS (
    OBJ_ID BIGINT,
    CAPTION VARCHAR(400),
    GRADE_ID BIGINT,
    GRADE_CAPTION VARCHAR(400),
    STAGE_ID BIGINT)
AS
begin

  -- Исключаем приказы об аттестации, чтобы не мешали незакрытые приказы

  FOR
    SELECT L9.OBJ_ID, C1.CAPTION, L10.OBJ_ID, C2.CAPTION, V49.LISTVAL_ID
    FROM LINKS L2
    JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
    JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C1 ON 1 = 1
    LEFT JOIN OBJECT_CAPTION_GET(L10.OBJ_ID, 23) C2 ON 1 = 1
    LEFT JOIN CHECK_ORDERS(L10.OBJ_ID, NULL, 13326) CO on 1 = 1
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND CO.ORDER_ID IS NULL
    INTO :GRADE_ID, :GRADE_CAPTION, :OBJ_ID, :CAPTION, :STAGE_ID
  DO
  BEGIN
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE STUDENT_ATTENDANCE_REF (
    I$OBJ_ID BIGINT,
    I$REF_NUM VARCHAR(20) = NULL,
    I$REF_TO VARCHAR(1000) = NULL)
RETURNS (
    TAG_NAME VARCHAR(30),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$SCHOOL BIGINT;
DECLARE VARIABLE S VARCHAR(100);
DECLARE VARIABLE V$CLASS_ID BIGINT;
DECLARE VARIABLE V$ID BIGINT;
DECLARE VARIABLE V$DT DATE;
DECLARE VARIABLE V$STAGE_PAR BIGINT;
DECLARE VARIABLE V$STAGE_COST BIGINT;
DECLARE VARIABLE P INTEGER;
begin
  TAG_NAME = 'place';
  VAL = I$REF_TO;
  SUSPEND;

  TAG_NAME = 'district';
  BEGIN
    -- используется в справке для военкомата через I$REF_TO будет передан район Спб. Надо его переделать в формат "какого района"
    SELECT VAL FROM LISTVALS_LIST(7) WHERE LISTVAL_ID = :I$REF_TO INTO :VAL;
    SELECT REPLACE(:VAL, 'ный', 'ному') FROM RDB$DATABASE INTO :VAL;
    SELECT REPLACE(:VAL, 'кий', 'кому') FROM RDB$DATABASE INTO :VAL;
    WHEN ANY DO
    BEGIN
      -- Для Школы/ДОУ сюда передается сторока - куда справка предназначена
      VAL = I$REF_TO;
    END
  END
  SUSPEND;

  TAG_NAME = 'doc_num';
  VAL = I$REF_NUM;
  SUSPEND;

  TAG_NAME = 'licence_type';
  SELECT STATUS FROM OU_LICENCE_TYPE INTO :VAL;
  SUSPEND;

  TAG_NAME = 'today';
  VAL = NULL;
  V$DT = CURRENT_DATE;
  SELECT RESULT FROM DATE2STR(:V$DT) INTO :VAL;
  SUSPEND;

  SELECT L2.OBJ_ID
  FROM LINKS L2
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$SCHOOL;

  TAG_NAME = 'upper_name';
  SELECT V FROM VAL_GET(:V$SCHOOL, 7) WHERE IS_EXISTS = 1 INTO :VAL;
  SUSPEND;

  TAG_NAME = 'ou_name';
  VAL = NULL;
  SELECT V FROM VAL_GET(:V$SCHOOL, 5) WHERE IS_EXISTS = 1 INTO :VAL;
  SUSPEND;

  TAG_NAME = 'ou_name_genitive';
  VAL = NULL;
  SELECT OFG.RESULT
  FROM VAL_GET(:V$SCHOOL, 5)
  LEFT JOIN OU_FULLNAME_GENITIVE(V) OFG ON 1 = 1
  WHERE IS_EXISTS = 1 INTO :VAL;
  SUSPEND;

  TAG_NAME = 'inn';
  VAL = NULL;
  SELECT V FROM VAL_GET(:V$SCHOOL, 33) WHERE IS_EXISTS = 1 INTO :VAL;
  SUSPEND;

  TAG_NAME = 'ogrn';
  VAL = NULL;
  SELECT V FROM VAL_GET(:V$SCHOOL, 9) WHERE IS_EXISTS = 1 INTO :VAL;
  SUSPEND;

  TAG_NAME = 'kpp';
  VAL = NULL;
  SELECT V FROM VAL_GET(:V$SCHOOL, 34) WHERE IS_EXISTS = 1 INTO :VAL;
  SUSPEND;

  TAG_NAME = 'okogu';
  VAL = NULL;
  SELECT V FROM VAL_GET(:V$SCHOOL, 19) WHERE IS_EXISTS = 1 INTO :VAL;
  SUSPEND;

  TAG_NAME = 'okpo';
  VAL = NULL;
  SELECT V FROM VAL_GET(:V$SCHOOL, 16) WHERE IS_EXISTS = 1 INTO :VAL;
  SUSPEND;

  TAG_NAME = 'address';
  VAL = NULL;
  SELECT V FROM VAL_GET(:V$SCHOOL, 27) WHERE IS_EXISTS = 1 INTO :VAL;
  SUSPEND;

  TAG_NAME = 'phone';
  VAL = NULL;
  SELECT V FROM VAL_GET(:V$SCHOOL, 29) WHERE IS_EXISTS = 1 INTO :VAL;
  SUSPEND;

  TAG_NAME = 'fax';
  VAL = NULL;
  SELECT V FROM VAL_GET(:V$SCHOOL, 30) WHERE IS_EXISTS = 1 INTO :VAL;
  SUSPEND;

  TAG_NAME = 'email';
  VAL = NULL;
  SELECT V FROM VAL_GET(:V$SCHOOL, 35) WHERE IS_EXISTS = 1 INTO :VAL;
  SUSPEND;

  -- ФИО ученика в дательном падеже
  TAG_NAME = 'name';
  VAL = NULL;
  SELECT DC.F || ' ' || DC.I || ' ' || DC.O
  FROM RDB$DATABASE
  LEFT JOIN BUILD_REP_FIO(:I$OBJ_ID, 55, 56, 57) BF ON 1 = 1
  LEFT JOIN DATIVECASE(BF.F, BF.I, BF.O) DC ON 1 = 1
  WHERE 1 = 1
  INTO :VAL;
  SUSPEND;

  V$DT = NULL;
  TAG_NAME = 'dob';
  VAL = NULL;
  SELECT V FROM VAL_GET(:I$OBJ_ID, 89) WHERE IS_EXISTS = 1 INTO :V$DT;
  SELECT RESULT FROM DATE2STR(:V$DT) INTO :VAL;
  SUSPEND;

  TAG_NAME = 'prn';
  VAL = NULL;
  SELECT I FROM VAL_GET(:I$OBJ_ID, 88) WHERE IS_EXISTS = 1 INTO :V$ID;
  IF (V$ID = 182) THEN VAL = 'она'; ELSE VAL = 'он';
  SUSPEND;

  TAG_NAME = 'edu_finance';
  VAL = NULL;
  SELECT I FROM VAL_GET(:I$OBJ_ID, 1812) WHERE IS_EXISTS = 1 INTO :V$ID;
  IF (V$ID = 5260) THEN VAL = 'платное'; ELSE VAL = 'бюджетное';
  SUSPEND;

  TAG_NAME = 'class';
  VAL = NULL;
  V$ID = NULL;
  SELECT P.GROUP_ID, CAP.SCAPTION
  FROM PERSON_MOVEMENTS P
  JOIN OBJECT_CAPTION_GET(P.GROUP_ID) CAP ON 1 = 1
  WHERE P.PERSON_ID = :I$OBJ_ID AND P.DATE_DEL IS NULL AND P.DATE_OUT IS NULL AND P.GROUP_TYPE_ID IN (9, 187)
  INTO :V$CLASS_ID, :VAL;
  SUSPEND;

  -- Определим этап обучения
  TAG_NAME = 'stage';
  VAL = NULL;
  SELECT FIRST 1 LV.PARENT_ID, LV.COST
  FROM LINKS L9
  JOIN VALL V49 ON V49.OBJ_ID = L9.PARENT_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V49.LISTVAL_ID AND LV.IS_DEL = 0
  WHERE L9.OBJ_ID = :V$CLASS_ID AND L9.PARENT_TYPE_ID = 8 AND L9.DATE_DEL IS NULL
  INTO :V$STAGE_PAR, :V$STAGE_COST;
  VAL = V$STAGE_PAR;
  SUSPEND;

  -- специальность для студентов колледжа
  TAG_NAME = 'speciality';
  VAL = NULL;
  SELECT V FROM VAL_GET(:V$CLASS_ID, 2165, 0) INTO : VAL;
  IF (VAL IS NULL OR VAL = '')  THEN
    SELECT V FROM VAL_GET(:V$CLASS_ID, 2821, 0) INTO : VAL;
  SUSPEND;

  -- Определим форму обучения группы
  TAG_NAME = 'form';
  VAL = NULL;
  SELECT CAP.VAL
  FROM VAL_GET(:V$CLASS_ID, 1768)
  LEFT JOIN LISTVAL_TEXT(I) CAP ON 1 = 1
  WHERE IS_EXISTS = 1
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'form_genitive';
  P = POSITION('ная' IN VAL);
  IF (P > 0) THEN
    SELECT REPLACE(:VAL, 'ная', 'ной') FROM RDB$DATABASE INTO :VAL;
  ELSE
  BEGIN
    P = POSITION('НАЯ' IN VAL);
    IF (P > 0) THEN
      SELECT REPLACE(:VAL, 'НАЯ', 'НОЙ') FROM RDB$DATABASE INTO :VAL;
  END
  SUSPEND;

  -- Найдем УП
  V$ID = NULL;
  SELECT I FROM VAL_GET(:V$CLASS_ID, 3075) WHERE IS_EXISTS = 1 INTO :V$ID;
  IF (V$ID IS NULL) THEN
  BEGIN
    SELECT FIRST 1 L400.OBJ_ID
    FROM LINKS L10
    JOIN LINKS L256 ON L256.OBJ_ID = L10.PARENT_ID AND L256.OBJ_TYPE_ID = 256 AND L256.DATE_DEL IS NULL
    JOIN LINKS L54 ON L54.OBJ_ID = L256.PARENT_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
    JOIN LINKS L400 ON L400.OBJ_ID = L54.PARENT_ID AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL
    WHERE L10.OBJ_ID = :I$OBJ_ID AND L10.PARENT_TYPE_ID = 256 AND L10.DATE_DEL IS NULL
    INTO :V$ID;
  END

  -- найдем последний этап обучения
  SELECT MAX(LV.COST)
  FROM LINKS L54
  JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V381.LISTVAL_ID AND LV.IS_DEL = 0
  WHERE L54.OBJ_TYPE_ID = 54 AND L54.PARENT_ID = :V$ID AND L54.DATE_DEL IS NULL
  INTO :V$ID;

  -- сколько лет до окончания
  IF (V$STAGE_PAR = 2141 AND V$STAGE_COST <= 9) THEN
    V$ID = 9 - V$STAGE_COST;
  ELSE IF (V$STAGE_PAR = 2141 AND V$STAGE_COST > 9) THEN
    V$ID = 11 - V$STAGE_COST;
  ELSE
    V$ID = V$ID - V$STAGE_COST;
  IF (EXTRACT(MONTH FROM CURRENT_DATE) > 5) THEN
    V$ID = V$ID + 1;

  -- Определим датой окончания последний день мая
  TAG_NAME = 'dt_edu_end';
  V$DT = DATEADD(YEAR, V$ID, CURRENT_DATE);
  V$DT = CAST(EXTRACT(YEAR FROM V$DT) || '-05-31' AS DATE);
  SELECT RESULT FROM DATE2STR(:V$DT) INTO VAL;
  SUSPEND;

  TAG_NAME = 'year_edu_end';
  VAL = CAST(EXTRACT(YEAR FROM V$DT) AS INTEGER);
  SUSPEND;

  V$DT = NULL;
  TAG_NAME = 'date_from';
  VAL = NULL;
  -- В контингенте ОУ не учитываются ученики классов-экстернатов
  -- Найдем последнюю дату выбытия
  SELECT MAX(M.DATE_OUT)
  FROM PERSON_MOVEMENTS M
  WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :I$OBJ_ID AND M.GROUP_TYPE_ID = 9 AND M.REASON_OUT IN (5548, 5549, 811, 812)
  INTO :V$DT;
  -- Найдем последнюю дату зачисления в ОУ после последнего выбытия, если оно было
  SELECT MIN(M.DATE_IN)
  FROM PERSON_MOVEMENTS M
  WHERE M.PERSON_ID = :I$OBJ_ID AND M.DATE_DEL IS NULL AND M.GROUP_TYPE_ID = 9 AND (:V$DT IS NULL OR M.DATE_IN > :V$DT)
  INTO :V$DT;
  SELECT RESULT FROM DATE2STR(:V$DT) INTO :VAL;
  SUSPEND;

  TAG_NAME = 'year_from';
  VAL = CAST(EXTRACT(YEAR FROM V$DT) AS INTEGER);
  SUSPEND;

  VAL = NULL;
  SELECT P.ORDER_DATE_IN, P.ORDER_NUM_IN
  FROM PERSON_MOVEMENTS P
  WHERE P.PERSON_ID = :I$OBJ_ID AND P.DATE_DEL IS NULL AND P.GROUP_TYPE_ID = 9 AND P.DATE_IN = :V$DT
  INTO :V$DT, :S;
  TAG_NAME = 'ord_date';
  SELECT RESULT FROM DATE2STR(:V$DT) INTO :VAL;
  SUSPEND;
  TAG_NAME = 'ord_num';
  VAL = :S;
  SUSPEND;

  S = NULL;
  VAL = NULL;
  SELECT C.POST, SUBSTRING(TRIM(C.I) FROM 1 FOR 1) || '.' || SUBSTRING(TRIM(C.O) FROM 1 FOR 1) || '.'|| C.F --FIO
  FROM R_SPB_POST_DIRECTOR(:V$SCHOOL, 1) C
  INTO :VAL, :S;
  TAG_NAME = 'head_post';
  SUSPEND;
  TAG_NAME = 'head_name';
  VAL = S;
  SUSPEND;

  -- реквизиты из выписки из реестра по аккредитации
  V$ID = NULL;
  SELECT FIRST 1 L17.OBJ_ID
  FROM LINKS L17
  JOIN VALL V471 ON V471.OBJ_ID = L17.OBJ_ID AND V471.PARAM_ID = 471 AND V471.IS_DEL = 0 AND V471.LISTVAL_ID IN (1053, 18625)
  WHERE L17.OBJ_TYPE_ID = 17 AND L17.PARENT_ID = :V$SCHOOL AND L17.DATE_DEL IS NULL
  ORDER BY L17.DATE_INS DESC
  INTO :V$ID;

  TAG_NAME = 'akk_num';
  VAL = NULL;
  SELECT V FROM VAL_GET(:V$ID, 480) INTO :VAL;
  SUSPEND;

  TAG_NAME = 'akk_date_from';
  V$DT = NULL;
  SELECT D FROM VAL_GET(:V$ID, 482) INTO :V$DT;
  SELECT RESULT FROM DATE2STR(:V$DT) INTO :VAL;
  SUSPEND;

  TAG_NAME = 'akk_date_to';
  V$DT = NULL;
  SELECT D FROM VAL_GET(:V$ID, 483) INTO :V$DT;
  SELECT RESULT FROM DATE2STR(:V$DT) INTO :VAL;
  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE STUDENT_EXISTS_AT (
    I$STUDENT_ID BIGINT,
    I$GRADE_ID BIGINT,
    I$GRADE_TYPE_ID BIGINT,
    I$DATE_FROM DATE,
    I$DATE_TO DATE)
RETURNS (
    IS_EXISTS SMALLINT)
AS
begin
  IS_EXISTS = 0;

  SELECT FIRST 1 1
  FROM PERSON_MOVEMENTS M
  WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :I$STUDENT_ID AND M.GROUP_ID = :I$GRADE_ID
    AND (:I$DATE_TO IS NULL OR M.DATE_IN <= :I$DATE_TO) AND (:I$DATE_FROM IS NULL OR M.DATE_OUT IS NULL OR M.DATE_OUT >= :I$DATE_FROM)
  INTO :IS_EXISTS;

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE STUDENT_STUDY_INFO (
    I$OBJ_ID BIGINT,
    I$PARENT_ID BIGINT = null)
RETURNS (
    STUDY_FORM VARCHAR(200),
    LEAVE_DATE VARCHAR(20),
    BIRTH_DATE VARCHAR(20),
    ACCEPT_DATE VARCHAR(20),
    ORDER_DATE VARCHAR(20),
    ORDER_NUM VARCHAR(400))
AS
declare variable V$STAGE bigint;
declare variable V$YEAR integer;
begin
  STUDY_FORM = 'очная, дневная';

  -- В какой параллели учится ?
  SELECT LV.COST
  FROM LINKS LPG
  JOIN LINKS LP8 ON LP8.OBJ_ID = LPG.PARENT_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
  JOIN VALL V49 ON V49.OBJ_ID = LP8.PARENT_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V49.LISTVAL_ID
  WHERE LPG.OBJ_ID = :I$OBJ_ID AND LPG.PARENT_TYPE_ID IN (9, 187) AND LPG.DATE_DEL IS NULL
  INTO :V$STAGE;

  V$YEAR = EXTRACT(YEAR FROM CURRENT_DATE);
  IF(EXTRACT(MONTH FROM CURRENT_DATE) < 9) THEN V$YEAR = V$YEAR - 1;

  -- Для 12 класса, чтобы счетчик в минус не ушел
  IF(V$STAGE = 12) THEN V$STAGE = 11;
  V$YEAR = V$YEAR + (11 - V$STAGE + 1);

  LEAVE_DATE = '30.06.' || V$YEAR;

  SELECT FIRST 1 D.RESULT
  FROM VALD
  LEFT JOIN DATE2STR(VAL) D ON 1 = 1
  WHERE OBJ_ID = :I$OBJ_ID AND PARAM_ID = 89 AND IS_DEL = 0
  INTO :BIRTH_DATE;

  SELECT FIRST 1 D.RESULT
  FROM PERSON_MOVEMENTS M
  JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID IN (9, 243)
  JOIN LISTVALS LV ON LV.LISTVAL_ID = M.REASON_IN AND (LV."FILTER" LIKE '%ACCEPTED%')
  LEFT JOIN LINKS L242_1 ON L242_1.OBJ_ID = :I$PARENT_ID AND L242_1.PARENT_TYPE_ID = 242 AND L242_1.DATE_DEL IS NULL
  LEFT JOIN LINKS L242_2 ON L242_2.OBJ_ID = M.GROUP_ID AND L242_2.PARENT_TYPE_ID = 242 AND L242_2.DATE_DEL IS NULL
  LEFT JOIN DATE2STR(M.DATE_IN) D ON 1 = 1
  WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :I$OBJ_ID AND ((L242_1.PARENT_ID IS NULL) OR (L242_1.PARENT_ID IS NOT NULL AND L242_1.PARENT_ID = L242_2.PARENT_ID))
  ORDER BY DATE_IN DESC
  INTO :ACCEPT_DATE;

  SELECT FIRST 1 M.ORDER_NUM_IN
  FROM PERSON_MOVEMENTS M
  JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID IN (9, 243)
  LEFT JOIN LINKS L242_1 ON L242_1.OBJ_ID = :I$PARENT_ID AND L242_1.PARENT_TYPE_ID = 242 AND L242_1.DATE_DEL IS NULL
  LEFT JOIN LINKS L242_2 ON L242_2.OBJ_ID = M.GROUP_ID AND L242_2.PARENT_TYPE_ID = 242 AND L242_2.DATE_DEL IS NULL
  WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :I$OBJ_ID AND M.REASON_IN IN (805, 806, 3276, 5547, 11397)
    AND ((L242_1.PARENT_ID IS NULL) OR (L242_1.PARENT_ID IS NOT NULL AND L242_1.PARENT_ID = L242_2.PARENT_ID))
  ORDER BY DATE_IN DESC
  INTO :ORDER_NUM;

  SELECT FIRST 1 D.RESULT
  FROM PERSON_MOVEMENTS M
  JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID IN (9, 243)
  LEFT JOIN LINKS L242_1 ON L242_1.OBJ_ID = :I$PARENT_ID AND L242_1.PARENT_TYPE_ID = 242 AND L242_1.DATE_DEL IS NULL
  LEFT JOIN LINKS L242_2 ON L242_2.OBJ_ID = M.GROUP_ID AND L242_2.PARENT_TYPE_ID = 242 AND L242_2.DATE_DEL IS NULL
  LEFT JOIN DATE2STR(M.ORDER_DATE_IN) D ON 1 = 1
  WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :I$OBJ_ID AND M.REASON_IN IN (805, 806, 3276, 5547, 11397) AND ((L242_1.PARENT_ID IS NULL) OR (L242_1.PARENT_ID IS NOT NULL AND L242_1.PARENT_ID = L242_2.PARENT_ID))
  ORDER BY DATE_IN DESC
  INTO :ORDER_DATE;

  SUSPEND;
end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SUBGROUP_SCHOOLARS_LIST (
    I$SUBGROUP_ID BIGINT,
    I$USER_ID BIGINT,
    I$IN_SUBGROUP_FL SMALLINT = NULL)
RETURNS (
    PARENT_ID BIGINT,
    TREE_PARENT_ID VARCHAR(255),
    OBJ_ID BIGINT,
    TREE_OBJ_ID VARCHAR(255),
    TYPE_ID BIGINT,
    OBJ_CAPTION VARCHAR(4000),
    COLOR INTEGER,
    SORT_ORDER VARCHAR(4000))
AS
DECLARE VARIABLE V$CURRICULUM_GROUP BIGINT;
DECLARE VARIABLE V$DIVISION BIGINT;
BEGIN
    IF (COALESCE(:I$IN_SUBGROUP_FL, 0) = 0) THEN
    BEGIN
        SELECT FIRST 1 OBJ_ID
        FROM OBJECT_PARENTS_GET(:I$SUBGROUP_ID, 256)
        INTO :V$CURRICULUM_GROUP;

        SELECT FIRST 1 OBJ_ID
        FROM OBJECT_PARENTS_GET(:I$SUBGROUP_ID, 47)
        INTO :V$DIVISION;

        FOR SELECT L10.PARENT_ID, L10.PARENT_ID, L10.OBJ_ID, L10.OBJ_ID, L10.OBJ_TYPE_ID
            FROM LINKS L10
            WHERE L10.PARENT_ID = :V$CURRICULUM_GROUP
              AND L10.OBJ_TYPE_ID+0 = 10
              AND L10.DATE_DEL IS NULL
              AND (:I$IN_SUBGROUP_FL IS NULL
               OR L10.OBJ_ID NOT IN (
                SELECT L10.OBJ_ID
                FROM LINKS L48
                INNER JOIN LINKS L10 ON L10.PARENT_ID = L48.OBJ_ID
                  AND L10.OBJ_TYPE_ID+0 = 10
                  AND L10.DATE_DEL IS NULL
                WHERE L48.PARENT_ID = :V$DIVISION
                  AND L48.OBJ_TYPE_ID+0 = 48
                  AND L48.DATE_DEL IS NULL))
            INTO :PARENT_ID, :TREE_PARENT_ID, :OBJ_ID, :TREE_OBJ_ID, :TYPE_ID
        DO
        BEGIN
            SELECT CAPTION, COLOR, CAPTION
            FROM OBJECT_CAPTION_GET(:OBJ_ID, NULL, NULL, :I$USER_ID)
            INTO :OBJ_CAPTION, :COLOR, :SORT_ORDER;
            SUSPEND;
        END
    END
    ELSE
    BEGIN
        FOR SELECT :I$SUBGROUP_ID, :I$SUBGROUP_ID, L10.OBJ_ID, :I$SUBGROUP_ID || '_' || L10.OBJ_ID, L10.OBJ_TYPE_ID
            FROM LINKS L10
            WHERE L10.PARENT_ID = :I$SUBGROUP_ID
              AND L10.OBJ_TYPE_ID+0 = 10
              AND L10.DATE_DEL IS NULL
            INTO :PARENT_ID, :TREE_PARENT_ID, :OBJ_ID, :TREE_OBJ_ID, :TYPE_ID
        DO
        BEGIN
            SELECT CAPTION, COLOR, CAPTION
            FROM OBJECT_CAPTION_GET(:OBJ_ID, NULL, NULL, :I$USER_ID)
            INTO :OBJ_CAPTION, :COLOR, :SORT_ORDER;
            SUSPEND;
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SUBJECT_DECODE_DIFF (
    I$VAL VARCHAR(100),
    I$TYPE_ID BIGINT)
RETURNS (
    VAL VARCHAR(400),
    MDVAL INTEGER)
AS
DECLARE VARIABLE C VARCHAR(1);
DECLARE VARIABLE N INTEGER;
begin

  IF(I$VAL IS NULL OR (I$TYPE_ID = 51 AND CHAR_LENGTH(I$VAL) <> 11) OR (I$TYPE_ID = 197 AND CHAR_LENGTH(I$VAL) <> 6)) THEN VAL = 'Н/Д';
  ELSE
  BEGIN
    VAL = '';
    MDVAL = 0;

    WHILE(CHAR_LENGTH(I$VAL) > 0) DO
    BEGIN
      C = UPPER(SUBSTRING(I$VAL FROM 1 FOR 1));
      I$VAL = SUBSTRING(I$VAL FROM 2);

      N = POSITION(C IN '0123456789ABCDEF') - 1;
      IF(VAL <> '') THEN VAL = VAL || ' ';
      IF(N >= 0) THEN
      BEGIN
        VAL = VAL || N;
        MDVAL = MAXVALUE(MDVAL, N);
      END
      ELSE
      BEGIN
        VAL = VAL || '*';
      END
    END
  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SUBJECT_DELETE (
    I$OBJ_ID BIGINT NOT NULL,
    I$USER_ID VARCHAR(100))
RETURNS (
    DEL_COUNT INTEGER)
AS
declare variable V$PARENT_ID bigint;
declare variable V$CAN_DELETE smallint;
declare variable V$ERR varchar(4000);
declare variable V$DB_LEVEL bigint;
declare variable V$OBJ_ID bigint;
declare variable V$USER_ID bigint;
declare variable V$USER_TYPE bigint;
declare variable V$LC bigint;
declare variable V$MUL bigint;
begin
  DEL_COUNT = 0;
  IF(I$USER_ID = 'Веб-администратор') THEN V$USER_ID = 1; ELSE V$USER_ID = CAST(I$USER_ID AS BIGINT);

  SELECT FIRST 1 CAST(K.KEY_VAL AS INTEGER) - 1
  FROM KEYS K
  WHERE K.KEY_CODE = 'LEVEL'
  INTO :V$DB_LEVEL;
  IF(V$DB_LEVEL > 0) THEN EXCEPTION DATA_ERROR 'Удаление предмета возможно только на уровне школы';

  SELECT FIRST 1 U.USER_TYPE
  FROM USERS U
  JOIN LUSERS L ON L.USER_ID = U.USER_ID AND L.READ_ONLY = 0 AND L.LEVEL_ID IN (546) --инженер, завуч, директор
  WHERE U.USER_ID = :V$USER_ID AND U.DATE_DEL IS NULL AND U.IS_BLOCKED = 0 AND (U.EXP_DATE IS NULL OR U.EXP_DATE > CURRENT_DATE)
  INTO :V$USER_TYPE;

  IF(V$USER_TYPE IS NULL) THEN EXCEPTION DATA_ERROR 'У вас нет доступа';

  SELECT GEN, MULTIPLIER FROM GEN INTO :V$LC, :V$MUL;
  IF(I$OBJ_ID / V$MUL <> V$LC) THEN EXCEPTION DATA_ERROR 'Предмет создан в другой базе, его нельзя удалить';

  SELECT FIRST 1 L.OBJ_ID, L.PARENT_ID
  FROM LINKS L
  WHERE L.OBJ_ID = :I$OBJ_ID AND L.PARENT_TYPE_ID IN (301, 193) AND DATE_DEL IS NULL
  INTO :V$OBJ_ID, :V$PARENT_ID;

  IF(V$OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Предмет не найден';

  SELECT FIRST 1 DEL.CAN_DELETE, DEL.ERR_MSG
  FROM PARAGRAF_CAN_DELETE_OBJECT(:V$OBJ_ID) DEL
  INTO :V$CAN_DELETE, :V$ERR;

  IF (V$CAN_DELETE = 1) THEN
  BEGIN
    SELECT OD.DEL_COUNT FROM OBJECT_DEL(:V$PARENT_ID, :V$OBJ_ID) OD INTO :DEL_COUNT;
  END
  ELSE
  BEGIN
    EXCEPTION DATA_ERROR V$ERR;
  END
  SUSPEND;
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SUBJECT_ENUM_DIR (
    I$OBJ_ID BIGINT,
    I$DIR BIGINT)
AS
declare variable V$ORDER_VAL bigint;
declare variable V$ORDER_BASE bigint;
declare variable V$NUM bigint;
declare variable TMP bigint;
begin

  -- Получаем текущий порядковый номер
  SELECT V375.VAL
  FROM VALI V375
  WHERE V375.OBJ_ID = :I$OBJ_ID AND V375.PARAM_ID = 375 AND V375.IS_DEL = 0
  INTO :V$ORDER_VAL;

  -- Получаем базу нумерации из LISTVALS
  SELECT CAST(TAG AS BIGINT)
  FROM LISTVALS
  WHERE LISTVAL_ID = :I$DIR
  INTO :V$ORDER_BASE;

  -- Нужно ли делать перенумерацию ?
  IF(V$ORDER_VAL IS NULL OR TRUNC(V$ORDER_VAL / 1000, 0) <> V$ORDER_VAL) THEN
  BEGIN

    -- Текущий максимальный номер
    SELECT MAX(V375.VAL)
    FROM LINKS LP301
    JOIN LINKS L51 ON L51.PARENT_ID = LP301.PARENT_ID AND L51.OBJ_TYPE_ID = 51 AND L51.DATE_DEL IS NULL AND L51.OBJ_ID <> :I$OBJ_ID
    JOIN VALI V375 ON V375.OBJ_ID = L51.OBJ_ID AND V375.PARAM_ID = 375 AND V375.IS_DEL = 0 AND (V375.VAL >= (:V$ORDER_BASE * 1000)) AND (V375.VAL < ((:V$ORDER_BASE + 1) * 1000))
    WHERE LP301.OBJ_ID = :I$OBJ_ID AND LP301.PARENT_TYPE_ID = 301 AND LP301.DATE_DEL IS NULL
    INTO :V$NUM;

    IF(V$NUM IS NULL) THEN V$NUM = V$ORDER_BASE * 1000 + 1; ELSE V$NUM = V$NUM + 1;

    SELECT BLOB_ID FROM VAL_ADD(375, :I$OBJ_ID, :V$NUM) INTO :TMP;

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SUBJECT_ENUM_MASTER (
    I$OBJ_ID BIGINT,
    I$AREA BIGINT)
AS
declare variable V$ORDER_VAL bigint;
declare variable V$ORDER_BASE bigint;
declare variable V$NUM bigint;
declare variable TMP bigint;
declare variable V$SUBJECT_ID bigint;
begin

  -- Внимание: поле меняется у @301, а номер исправляем у самого предмета
  -- Получаем ID предмета
  SELECT LP51.PARENT_ID
  FROM LINKS LP51
  WHERE LP51.OBJ_ID = :I$OBJ_ID AND LP51.PARENT_TYPE_ID = 51 AND LP51.DATE_DEL IS NULL
  INTO :V$SUBJECT_ID;

  IF(V$SUBJECT_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Предмет не найден';

  -- Получаем текущий порядковый номер
  SELECT V375.VAL
  FROM VALI V375
  WHERE V375.OBJ_ID = :V$SUBJECT_ID AND V375.PARAM_ID = 375 AND V375.IS_DEL = 0
  INTO :V$ORDER_VAL;

  -- Получаем базу нумерации из LISTVALS
  SELECT CAST(TAG AS BIGINT)
  FROM LISTVALS
  WHERE LISTVAL_ID = :I$AREA
  INTO :V$ORDER_BASE;

  -- Нужно ли делать перенумерацию ?
  IF(V$ORDER_VAL IS NULL OR TRUNC(V$ORDER_VAL / 1000, 0) <> V$ORDER_VAL) THEN
  BEGIN

    -- Текущий максимальный номер - только в том же каталоге
    SELECT MAX(V375.VAL)
    FROM LINKS LP301
    JOIN LINKS L51 ON L51.PARENT_ID = LP301.PARENT_ID AND L51.OBJ_TYPE_ID = 51 AND L51.DATE_DEL IS NULL AND L51.OBJ_ID <> :V$SUBJECT_ID
    JOIN VALI V375 ON V375.OBJ_ID = L51.OBJ_ID AND V375.PARAM_ID = 375 AND V375.IS_DEL = 0 AND (V375.VAL >= (:V$ORDER_BASE * 1000)) AND (V375.VAL < ((:V$ORDER_BASE + 1) * 1000))
    WHERE LP301.OBJ_ID = :V$SUBJECT_ID AND LP301.PARENT_TYPE_ID = 301 AND LP301.DATE_DEL IS NULL
    INTO :V$NUM;

    IF(V$NUM IS NULL) THEN V$NUM = V$ORDER_BASE * 1000 + 1; ELSE V$NUM = V$NUM + 1;

    SELECT BLOB_ID FROM VAL_ADD(375, :V$SUBJECT_ID, :V$NUM) INTO :TMP;

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SUBJECT_GET (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(20),
    I$PARENT_ID BIGINT)
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$GEN BIGINT;
DECLARE VARIABLE V$MULT BIGINT;
DECLARE VARIABLE V$NAME VARCHAR(1000);
BEGIN
  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  SELECT FIRST 1 L.OBJ_ID
  FROM LINKS L
  WHERE L.OBJ_ID = :I$OBJ_ID AND L.OBJ_TYPE_ID IN (51, 197) AND L.PARENT_TYPE_ID IN (301, 193) AND L.DATE_DEL IS NULL
  INTO :V$OBJ_ID;

  IF (I$OBJ_ID IS NOT NULL AND V$OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Предмет не найден или был удален';

  TAG_NAME = 'id';
  VAL = V$OBJ_ID;
  SUSPEND;

  SELECT GEN, MULTIPLIER
  FROM GEN
  INTO :V$GEN, :V$MULT;
  -- Вывод is_rootdb для блокировки полей на фронте
  TAG_NAME = 'is_rootdb';
  VAL = IIF(V$GEN = 0, 1, 0);
  SUSPEND;

  -- Блокировка для предметов, созданных в другой базе
  IF(I$OBJ_ID IS NOT NULL AND I$OBJ_ID / V$MULT <> V$GEN) THEN
  BEGIN
    TAG_NAME = 'row_readonly';
    VAL = 1;
    SUSPEND;
  END

  -- дисциплина СПО
  IF (I$PARENT_ID = 12313) THEN
  BEGIN
    -- название
    VAL = NULL;
    SELECT V
    FROM VAL_GET(:I$OBJ_ID, 1751)
    WHERE IS_EXISTS = 1
    INTO :VAL;
    TAG_NAME = 'subj_name';
    SUSPEND;

    -- Вид учебной деятельности
    TAG_NAME = 'study_type:selection::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT V.LISTVAL_ID, V.VAL
      FROM OO_SUBJECT_TYPE_LIST(:I$OBJ_ID, 1750, :I$USER_ID) V
      INTO :V$OBJ_ID, :V$NAME
    DO
    BEGIN
      TAG_NAME = 'study_type:selection:option';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'study_type:selection:option:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'study_type:selection:option:value';
      VAL = V$NAME;
      SUSPEND;
    END

    VAL = NULL;
    SELECT I
    FROM VAL_GET(:I$OBJ_ID, 1750)
    WHERE IS_EXISTS = 1
    INTO :VAL;
    TAG_NAME = 'study_type:values:value';
    SUSPEND;

    -- Сокращенное наименование
    VAL = NULL;
    SELECT V
    FROM VAL_GET(:I$OBJ_ID, 1752)
    WHERE IS_EXISTS = 1
    INTO :VAL;
    TAG_NAME = 'short_name';
    SUSPEND;

    -- Цвет в расписании
    VAL = NULL;
    SELECT V
    FROM VAL_GET(:I$OBJ_ID, 3067)
    WHERE IS_EXISTS = 1
    INTO :VAL;
    TAG_NAME = 'sched_color';
    SUSPEND;

    -- трудность
    VAL = NULL;
    SELECT V
    FROM VAL_GET(:I$OBJ_ID, 3614)
    WHERE IS_EXISTS = 1
    INTO :VAL;
    TAG_NAME = 'diff_level';
    SUSPEND;
  END
  -- Школа или сад
  ELSE
  BEGIN
    -- Название
    VAL = NULL;
    SELECT V
    FROM VAL_GET(:I$OBJ_ID, 376)
    WHERE IS_EXISTS = 1
    INTO :VAL;
    TAG_NAME = 'subj_name';
    SUSPEND;

    -- Код
    VAL = NULL;
    SELECT V
    FROM VAL_GET(:I$OBJ_ID, 377)
    WHERE IS_EXISTS = 1
    INTO :VAL;
    TAG_NAME = 'subj_code';
    SUSPEND;

    -- Порядок
    VAL = NULL;
    SELECT V
    FROM VAL_GET(:I$OBJ_ID, 375)
    WHERE IS_EXISTS = 1
    INTO :VAL;
    TAG_NAME = 'subj_order';
    SUSPEND;

    -- Цвет в расписании
    VAL = NULL;
    SELECT V
    FROM VAL_GET(:I$OBJ_ID, 3066)
    WHERE IS_EXISTS = 1
    INTO :VAL;
    TAG_NAME = 'sched_color';
    SUSPEND;

    IF (I$PARENT_ID <> 38699) THEN  -- далее для школы - для общего образования и внеурочной деятельноcти
    BEGIN
      -- Направленность для доп образования
      IF (I$PARENT_ID = -1) THEN    --Специально = -1, потому что Доп образование нигде не используется.
      BEGIN
        TAG_NAME = 'subj_trend:selection::json&colon;array';
        VAL = 1;
        SUSPEND;
        FOR
          SELECT V.LISTVAL_ID, VAL
          FROM LISTVALS_LIST(300) V
          WHERE IS_DEL = 0
          INTO :V$OBJ_ID, :V$NAME
        DO
        BEGIN
          TAG_NAME = 'subj_trend:selection:option';
          VAL = NULL;
          SUSPEND;
          TAG_NAME = 'subj_trend:selection:option:id';
          VAL = V$OBJ_ID;
          SUSPEND;
          TAG_NAME = 'subj_trend:selection:option:value';
          VAL = V$NAME;
          SUSPEND;
        END

        VAL = NULL;
        SELECT I
        FROM VAL_GET(:I$OBJ_ID, 2463)
        WHERE IS_EXISTS = 1
        INTO :VAL;
        TAG_NAME = 'subj_trend:values:value';
        SUSPEND;
      END

      -- Внеурочная деятельность
      IF (I$PARENT_ID = 32772) THEN
      BEGIN
        -- Обязательный предмет
        VAL = 0;
        SELECT IIF(I = 2, 1, 0)
        FROM VAL_GET(:I$OBJ_ID, 3377)
        WHERE IS_EXISTS = 1
        INTO :VAL;
        TAG_NAME = 'must_have';
        SUSPEND;

        --Направление
        TAG_NAME = 'subj_field:selection::json&colon;array';
        VAL = 1;
        SUSPEND;
        FOR
          SELECT V.LISTVAL_ID, VAL
          FROM LISTVALS_LIST(301) V
          WHERE IS_DEL = 0
          INTO :V$OBJ_ID, :V$NAME
        DO
        BEGIN
          TAG_NAME = 'subj_field:selection:option';
          VAL = NULL;
          SUSPEND;
          TAG_NAME = 'subj_field:selection:option:id';
          VAL = V$OBJ_ID;
          SUSPEND;
          TAG_NAME = 'subj_field:selection:option:value';
          VAL = V$NAME;
          SUSPEND;
        END

        VAL = NULL;
        SELECT I
        FROM VAL_GET(:I$OBJ_ID, 2464)
        WHERE IS_EXISTS = 1
        INTO :VAL;
        TAG_NAME = 'subj_field:values:value';
        SUSPEND;
      END
      ELSE IF (I$PARENT_ID = 32771) THEN
      -- Общее образование
      BEGIN
        -- фгос
        VAL = 0;
        SELECT IIF(I = 2, 1, 0)
        FROM VAL_GET(:I$OBJ_ID, 2465)
        WHERE IS_EXISTS = 1
        INTO :VAL;
        TAG_NAME = 'is_fgos';
        SUSPEND;

        -- Тип
        TAG_NAME = 'subj_type:selection::json&colon;array';
        VAL = 1;
        SUSPEND;
        FOR
          SELECT V.LISTVAL_ID, V.VAL
          FROM OO_SUBJECT_TYPE_LIST(:I$OBJ_ID, 3158, :I$USER_ID) V
          INTO :V$OBJ_ID, :V$NAME
        DO
        BEGIN
          TAG_NAME = 'subj_type:selection:option';
          VAL = NULL;
          SUSPEND;
          TAG_NAME = 'subj_type:selection:option:id';
          VAL = V$OBJ_ID;
          SUSPEND;
          TAG_NAME = 'subj_type:selection:option:value';
          VAL = V$NAME;
          SUSPEND;
        END

        VAL = NULL;
        SELECT I
        FROM VAL_GET(:I$OBJ_ID, 3158)
        WHERE IS_EXISTS = 1
        INTO :VAL;
        TAG_NAME = 'subj_type:values:value';
        SUSPEND;

        -- эталонный предмет
        TAG_NAME = 'base_subj_name:selection::json&colon;array';
        VAL = 1;
        SUSPEND;
        FOR
          SELECT L.OBJ_ID, L.OBJ_CAPTION
          FROM PARAGRAF_TYPE_NOT_LINKED_LIST(301, 51, NULL, :I$USER_ID, NULL, 32771) L
          JOIN VALL V ON V.OBJ_ID = L.OBJ_ID AND V.PARAM_ID = 2465 AND V.LISTVAL_ID = 2
          INTO :V$OBJ_ID, :V$NAME
        DO
        BEGIN
          TAG_NAME = 'base_subj_name:selection:option';
          VAL = NULL;
          SUSPEND;
          TAG_NAME = 'base_subj_name:selection:option:id';
          VAL = V$OBJ_ID;
          SUSPEND;
          TAG_NAME = 'base_subj_name:selection:option:value';
          VAL = V$NAME;
          SUSPEND;
        END

        VAL = NULL;
        SELECT I
        FROM VAL_GET(:I$OBJ_ID, 3159)
        WHERE IS_EXISTS = 1
        INTO :VAL;
        TAG_NAME = 'base_subj_name:values:value';
        SUSPEND;

        -- уровень сложности, строковая маска в формате hex, 11 символов по параллелям
        VAL = NULL;
        SELECT V
        FROM VAL_GET(:I$OBJ_ID, 3058)
        WHERE IS_EXISTS = 1
        INTO :VAL;
        TAG_NAME = 'diff_level';
        SUSPEND;

        -- макс кол-во часов в день
        VAL = NULL;
        SELECT CAST(F AS NUMERIC(15, 1))
        FROM VAL_GET(:I$OBJ_ID, 3059)
        WHERE IS_EXISTS = 1
        INTO :VAL;
        VAL = REPLACE(VAL, '.0', '');
        TAG_NAME = 'max_hours';
        SUSPEND;

        -- Ограничение углубленного изучения для уровней
        VAL = NULL;
        SELECT V
        FROM VAL_GET(:I$OBJ_ID, 3156)
        WHERE IS_EXISTS = 1
        INTO :VAL;
        TAG_NAME = 'restr';
        SUSPEND;

        -- Код ГИА
        VAL = NULL;
        SELECT I
        FROM VAL_GET(:I$OBJ_ID, 600)
        WHERE IS_EXISTS = 1
        INTO :VAL;
        TAG_NAME = 'code_gia';
        SUSPEND;

        -- элективный предмет
        VAL = 0;
        SELECT IIF(I = 2, 1, 0)
        FROM VAL_GET(:I$OBJ_ID, 2816)
        WHERE IS_EXISTS = 1
        INTO :VAL;
        TAG_NAME = 'is_elective';
        SUSPEND;

        -- MultiSelect Предметная область
        -- Для передачи использовать форматирование данных как для dropdown multiselect (поле values передается как массив, а сами значения берем простым перечислением параметра 2462)

        TAG_NAME = 'subj_scope:selection::json&colon;array';
        VAL = 1;
        SUSPEND;
        FOR
          SELECT V.LISTVAL_ID, VAL
          FROM LISTVALS_LIST(299) V
          WHERE IS_DEL = 0
          INTO :V$OBJ_ID, :V$NAME
        DO
        BEGIN
          TAG_NAME = 'subj_scope:selection:option';
          VAL = NULL;
          SUSPEND;
          TAG_NAME = 'subj_scope:selection:option:id';
          VAL = V$OBJ_ID;
          SUSPEND;
          TAG_NAME = 'subj_scope:selection:option:value';
          VAL = V$NAME;
          SUSPEND;
        END

        -- найдем значения для мультиселекта
        TAG_NAME = 'subj_scope:values::json&colon;array';
        VAL = 1;
        SUSPEND;
        FOR
          SELECT DISTINCT V2462.LISTVAL_ID
          FROM LINKS L302
          JOIN VALL V2462 ON V2462.OBJ_ID = L302.OBJ_ID AND V2462.IS_DEL = 0 AND V2462.PARAM_ID = 2462
          WHERE L302.OBJ_TYPE_ID = 302 AND L302.PARENT_ID = :I$OBJ_ID AND L302.DATE_DEL IS NULL
          INTO :VAL
        DO
        BEGIN
          TAG_NAME = 'subj_scope:values:v';
          SUSPEND;
        END
      END
    END
  END
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SUBJECT_GET_SCOPE (
    I$SUBJECT_ID BIGINT)
RETURNS (
    SCOPE VARCHAR(400))
AS
declare variable V$S varchar(100);
declare variable V$ID bigint;
BEGIN
  SCOPE = '';
  FOR
    SELECT DISTINCT R2462.VAL
    FROM LINKS L302
    JOIN VALL V2462 ON V2462.OBJ_ID = L302.OBJ_ID AND V2462.IS_DEL = 0 AND V2462.PARAM_ID = 2462
    JOIN LISTVALS LV2462 ON LV2462.LISTVAL_ID = V2462.LISTVAL_ID AND LV2462.IS_DEL = 0
    JOIN RES R2462 ON R2462.RES_ID = LV2462.RES_ID AND R2462.LANG_CODE = 'RU' AND R2462.IS_DEL = 0
    WHERE L302.OBJ_TYPE_ID = 302 AND L302.PARENT_TYPE_ID = 51 AND L302.PARENT_ID = :I$SUBJECT_ID
    INTO :V$S
  DO
  BEGIN
    IF (CHAR_LENGTH(SCOPE) > 0) THEN
    BEGIN
      SCOPE = SCOPE || ', ' || V$S;
    END
    ELSE
    BEGIN
      SCOPE = V$S;
    END
  END
  SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SUBJECT_SET (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(100),
    I$PARENT_ID BIGINT,
    I$OBJ_NAME VARCHAR(1000),
    I$TYPE BIGINT,
    I$CODE VARCHAR(50),
    I$COLOR VARCHAR(100),
    I$BASE_SUBJECT BIGINT,
    I$ELECTIVE SMALLINT,
    I$DIFF_LEVEL VARCHAR(100),
    I$MAX_HOURS DOUBLE PRECISION,
    I$RESTRICTION VARCHAR(100),
    I$OBLIGATORY SMALLINT,
    I$SCOPE_LIST VARCHAR(100),
    I$CODE_GIA INTEGER,
    I$ORDER INTEGER,
    I$FGOS SMALLINT,
    I$SUBJ_FIELD BIGINT)
RETURNS (
    OBJ_ID BIGINT)
AS
DECLARE VARIABLE V$USER_TYPE SMALLINT;
DECLARE VARIABLE V$USER_ID BIGINT;
DECLARE VARIABLE V$DB_LEVEL SMALLINT;
DECLARE VARIABLE V$LC BIGINT;
DECLARE VARIABLE V$MUL BIGINT;
DECLARE VARIABLE V$TYPE_ID BIGINT;
begin
  IF(I$USER_ID = 'Веб-администратор') THEN V$USER_ID = 1; ELSE V$USER_ID = CAST(I$USER_ID AS BIGINT);

  SELECT FIRST 1 CAST(K.KEY_VAL AS INTEGER) - 1
  FROM KEYS K
  WHERE K.KEY_CODE = 'LEVEL'
  INTO :V$DB_LEVEL;
  IF(V$DB_LEVEL > 0) THEN EXCEPTION DATA_ERROR 'Редактирование предмета возможно только на уровне школы';

  SELECT GEN, MULTIPLIER FROM GEN INTO :V$LC, :V$MUL;
  IF(I$OBJ_ID / V$MUL <> V$LC) THEN EXCEPTION DATA_ERROR 'Предмет создан в другой базе, его нельзя редактировить';

  SELECT FIRST 1 U.USER_TYPE
  FROM USERS U
  JOIN LUSERS L ON L.USER_ID = U.USER_ID AND L.READ_ONLY = 0 AND L.LEVEL_ID IN (546, 202, 42) -- предметы
  WHERE U.USER_ID = :V$USER_ID AND U.DATE_DEL IS NULL AND U.IS_BLOCKED = 0 AND (U.EXP_DATE IS NULL OR U.EXP_DATE > CURRENT_DATE)
  INTO :V$USER_TYPE;

  IF(V$USER_TYPE IS NULL AND V$LC <> 0) THEN EXCEPTION DATA_ERROR 'У вас нет доступа';

  IF (I$OBJ_ID IS NULL) THEN
  BEGIN
    -- Определяем тип предмета по его родителю. Создаем предмет
    V$TYPE_ID = IIF(I$PARENT_ID = 12313, 197, 51);
    SELECT OBJ_ID FROM OBJECT_ADD(:I$PARENT_ID, :V$TYPE_ID, NULL, NULL, :V$USER_ID) INTO :OBJ_ID;
  END
  ELSE
  BEGIN
    -- Ищем предмет
    SELECT FIRST 1 L.OBJ_ID
    FROM LINKS L
    WHERE L.OBJ_ID = :I$OBJ_ID AND L.PARENT_ID = :I$PARENT_ID AND DATE_DEL IS NULL
    INTO :OBJ_ID;

    IF (OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Предмет не найден';
  END

  IF (I$PARENT_ID = 12313) THEN
  BEGIN
    -- дисциплина СПО
    SELECT 1 FROM VAL_ADD(1751, :OBJ_ID, :I$OBJ_NAME, :V$USER_ID) INTO :V$MUL;   -- название
    SELECT 1 FROM VAL_ADD(1750, :OBJ_ID, :I$TYPE, :V$USER_ID) INTO :V$MUL;       -- тип / вид учебной деятельности
    SELECT 1 FROM VAL_ADD(1752, :OBJ_ID, :I$CODE, :V$USER_ID) INTO :V$MUL;       -- код / сокращенное название
    SELECT 1 FROM VAL_ADD(3067, :OBJ_ID, :I$COLOR, :V$USER_ID) INTO :V$MUL;      -- цвет в расписании
    SELECT 1 FROM VAL_ADD(3614, :OBJ_ID, :I$DIFF_LEVEL, :V$USER_ID) INTO :V$MUL; -- трудность
  END
  ELSE
  BEGIN
    -- Для школ и ДОУ
    SELECT 1 FROM VAL_ADD(375, :OBJ_ID, :I$ORDER, :V$USER_ID) INTO :V$MUL;       -- порядок
    SELECT 1 FROM VAL_ADD(376, :OBJ_ID, :I$OBJ_NAME, :V$USER_ID) INTO :V$MUL;    -- название
    SELECT 1 FROM VAL_ADD(377, :OBJ_ID, :I$CODE, :V$USER_ID) INTO :V$MUL;        -- код / сокращенное название
    SELECT 1 FROM VAL_ADD(3066, :OBJ_ID, :I$COLOR, :V$USER_ID) INTO :V$MUL;      -- цвет в расписании

    --Только для школ
    IF (I$PARENT_ID <> 38699) THEN
    BEGIN
      --SELECT 1 FROM VAL_ADD(2463, :OBJ_ID, :I$COLOR, :V$USER_ID) INTO :V$MUL; -- Направленность не используется
      -- общее образование
      IF (I$PARENT_ID = 32771) THEN
      BEGIN
        SELECT 1 FROM VAL_ADD(3158, :OBJ_ID, :I$TYPE, :V$USER_ID) INTO :V$MUL;       -- тип / вид учебной деятельности
        SELECT 1 FROM VAL_ADD(3159, :OBJ_ID, :I$BASE_SUBJECT, :V$USER_ID) INTO :V$MUL;
        SELECT 1 FROM VAL_ADD(2816, :OBJ_ID, IIF(:I$ELECTIVE = 1, 2, 3), :V$USER_ID) INTO :V$MUL;
        SELECT 1 FROM VAL_ADD(3058, :OBJ_ID, :I$DIFF_LEVEL, :V$USER_ID) INTO :V$MUL;
        SELECT 1 FROM VAL_ADD(3059, :OBJ_ID, :I$MAX_HOURS, :V$USER_ID) INTO :V$MUL;

        -- Редактирование возможно только для эталонной базы
        IF (V$LC = 0) THEN
        BEGIN
          SELECT 1 FROM VAL_ADD(2465, :OBJ_ID, IIF(:I$FGOS = 1, 2, 3), :V$USER_ID) INTO :V$MUL;
          SELECT 1 FROM VAL_ADD(600, :OBJ_ID, :I$CODE_GIA, :V$USER_ID) INTO :V$MUL;
          SELECT 1 FROM VAL_ADD(3156, :OBJ_ID, :I$RESTRICTION, :V$USER_ID) INTO :V$MUL;
        END

        -- Сохраняем список предметных областей для общего образования
        -- Находим предметные области, которых нет в новом списке. Их надо удалить
        FOR
          SELECT L.OBJ_ID, V2462.LISTVAL_ID
          FROM LINKS L
          LEFT JOIN VALL V2462 ON V2462.OBJ_ID = L.OBJ_ID AND V2462.PARAM_ID = 2462 AND V2462.IS_DEL = 0
          WHERE L.OBJ_TYPE_ID = 302 AND L.PARENT_ID = :OBJ_ID AND DATE_DEL IS NULL
            AND COALESCE(V2462.LISTVAL_ID, 0) NOT IN (SELECT ID FROM STR_TO_ID_LIST(:I$SCOPE_LIST))
          INTO :V$LC, :V$MUL    --id, предметная область
        DO
        BEGIN
          UPDATE LINKS
          SET DATE_DEL = CURRENT_TIMESTAMP
          WHERE PARENT_ID = :OBJ_ID AND OBJ_ID = :V$LC AND DATE_DEL IS NULL;
        END

        -- проверим, есть ли предметная область из списка у предмета. Если нет, то добавим
        FOR
          SELECT ID
          FROM STR_TO_ID_LIST(:I$SCOPE_LIST)
          INTO :V$MUL
        DO
        BEGIN
          IF (NOT EXISTS(SELECT FIRST 1 1
            FROM LINKS L
            JOIN VALL V2462 ON V2462.OBJ_ID = L.OBJ_ID AND V2462.PARAM_ID = 2462 AND V2462.IS_DEL = 0 AND V2462.LISTVAL_ID = :V$MUL
            WHERE L.OBJ_TYPE_ID = 302 AND L.PARENT_ID = :OBJ_ID AND DATE_DEL IS NULL)) THEN
          BEGIN
            SELECT OBJ_ID FROM OBJECT_ADD(:OBJ_ID, 302, NULL, NULL, :V$USER_ID) INTO :V$LC;
            SELECT 1 FROM VAL_ADD(2462, :V$LC, :V$MUL, :V$USER_ID) INTO :V$LC;
          END
        END

      END
      ELSE
      BEGIN
        -- внеурочная деятельность
        SELECT 1 FROM VAL_ADD(3377, :OBJ_ID, IIF(:I$OBLIGATORY = 1, 2, 3), :V$USER_ID) INTO :V$MUL;
        SELECT 1 FROM VAL_ADD(2464, :OBJ_ID, :I$SUBJ_FIELD, :V$USER_ID) INTO :V$MUL;
      END
    END
  END

  SUSPEND;
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE SUBJECT_TYPES RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$DB_LEVEL SMALLINT;
DECLARE VARIABLE V$IS_DOU SMALLINT;
DECLARE VARIABLE V$IS_SCHOOL SMALLINT;
DECLARE VARIABLE V$IS_SPO SMALLINT;
BEGIN
  -- Идентифицируем уровень - для района и региона будем показывать все
  SELECT COALESCE(CAST(K.KEY_VAL AS INTEGER) - 1, 0)
  FROM KEYS K
  WHERE K.KEY_CODE = 'LEVEL'
  INTO :V$DB_LEVEL;

  -- Для эталонной базы показываем все имитируя более высокий уровень
  IF(EXISTS(SELECT FIRST 1 1 FROM GEN WHERE GEN = 0)) THEN V$DB_LEVEL = 1;

  TAG_NAME = 'items::json&colon;array';
  VAL = 1;
  SUSPEND;

  -- Определим, есть ли лицензия школы
  V$IS_SCHOOL = 0;
  IF (EXISTS(SELECT FIRST 1 1
     FROM LINKS L472
     JOIN VALL V3327 ON V3327.OBJ_ID = L472.OBJ_ID AND V3327.PARAM_ID = 3327 AND V3327.IS_DEL = 0
     WHERE L472.OBJ_TYPE_ID = 472 AND L472.PARENT_TYPE_ID = 2 AND L472.DATE_DEL IS NULL AND V3327.LISTVAL_ID IN (22, 26, 27))) THEN --начальная, средняя и старшая школа
  BEGIN
    V$IS_SCHOOL = 1;
  END
  -- Определим, есть ли лицензия детского сада
  V$IS_DOU = 0;
  IF (EXISTS(SELECT FIRST 1 1
    FROM LINKS L472
    JOIN VALL V3327 ON V3327.OBJ_ID = L472.OBJ_ID AND V3327.PARAM_ID = 3327 AND V3327.IS_DEL = 0
    WHERE L472.OBJ_TYPE_ID = 472 AND L472.PARENT_TYPE_ID = 2 AND L472.DATE_DEL IS NULL AND V3327.LISTVAL_ID IN (3263, 3264))) THEN  --ясли и детский сад
  BEGIN
    V$IS_DOU = 1;
  END
  -- Определим, есть ли лицензия СПО
  V$IS_SPO = 0;
  IF (EXISTS(SELECT FIRST 1 1
    FROM LINKS L472
    JOIN VALL V3327 ON V3327.OBJ_ID = L472.OBJ_ID AND V3327.PARAM_ID = 3327 AND V3327.IS_DEL = 0
    WHERE L472.OBJ_TYPE_ID = 472 AND L472.PARENT_TYPE_ID = 2 AND L472.DATE_DEL IS NULL AND V3327.LISTVAL_ID IN (29, 13131))) THEN
  BEGIN
    V$IS_SPO = 1;
  END

  -- Предметы ОУ. Выводим на уровне, выше ОУ, или в ОУ, если лицензия позволяет
  IF (V$DB_LEVEL > 0 OR V$IS_SCHOOL = 1) THEN
  BEGIN
    --Добавим общее образование
    TAG_NAME = 'items:types';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'items:types:id';
    VAL = 32771;
    SUSPEND;
    TAG_NAME = 'items:types:name';
    VAL = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:VAL));
    SUSPEND;
    TAG_NAME = 'items:types:type_id';
    VAL = 301;
    SUSPEND;

    --внеурочная деятельность
    TAG_NAME = 'items:types';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'items:types:id';
    VAL = 32772;
    SUSPEND;
    TAG_NAME = 'items:types:name';
    VAL = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:VAL));
    SUSPEND;
    TAG_NAME = 'items:types:type_id';
    VAL = 301;
    SUSPEND;
  END

  --дошкольное образование
  IF (V$DB_LEVEL > 0 OR V$IS_DOU = 1) THEN
  BEGIN
    TAG_NAME = 'items:types';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'items:types:id';
    VAL = 38699;
    SUSPEND;
    TAG_NAME = 'items:types:name';
    VAL = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:VAL));
    SUSPEND;
    TAG_NAME = 'items:types:type_id';
    VAL = 301;
    SUSPEND;
  END

  -- Выводим список: СПО один раздел - Дисциплины (193). Выводим на уровне, выше ОУ, или, есди лицензия позволяет
  IF (V$DB_LEVEL > 0 OR V$IS_SPO = 1) THEN
  BEGIN
    TAG_NAME = 'items:types';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'items:types:id';
    VAL = 12313;
    SUSPEND;
    TAG_NAME = 'items:types:name';
    VAL = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:VAL));
    SUSPEND;
    TAG_NAME = 'items:types:type_id';
    VAL = 193;
    SUSPEND;
  END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE TABS_LIST (
    I$TYPE_ID BIGINT,
    I$LANG_CODE VARCHAR(2) = 'RU')
RETURNS (
    TAB_ID BIGINT,
    TYPE_ID BIGINT,
    TAB_NUM SMALLINT,
    RES_ID BIGINT,
    IS_DEL SMALLINT,
    TAB_CAPTION VARCHAR(4000))
AS
BEGIN
    FOR
        SELECT TAB_ID,
               TYPE_ID,
               TAB_NUM,
               RES_ID,
               IS_DEL
        FROM TABS
        WHERE (TYPE_ID = :I$TYPE_ID OR :I$TYPE_ID IS NULL)
        ORDER BY TAB_NUM
        INTO   :TAB_ID,
               :TYPE_ID,
               :TAB_NUM,
               :RES_ID,
               :IS_DEL
    DO
    BEGIN
        SELECT VAL
        FROM RES_GET(:RES_ID, :I$LANG_CODE)
        INTO   :TAB_CAPTION;
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE TAB_ADD (
    I$TAB_ID BIGINT,
    I$TYPE_ID BIGINT,
    I$TAB_NUM SMALLINT,
    I$RES_ID BIGINT,
    I$IS_DEL SMALLINT,
    I$LANG_CODE CHAR(2),
    I$TAB_CAPTION VARCHAR(4000))
RETURNS (
    RC INTEGER)
AS
DECLARE VARIABLE T SMALLINT;
BEGIN
 RC = I$TAB_NUM;
    IF (I$TAB_ID IS NULL) THEN
    BEGIN
        SELECT MAX(TAB_NUM) + 1
        FROM TABS
        WHERE TYPE_ID = :I$TYPE_ID
        INTO :T;

        IF (T IS NULL) THEN T = 1;

        INSERT INTO TABS (TAB_NUM, TYPE_ID, IS_DEL)
        VALUES (:T, :I$TYPE_ID, :I$IS_DEL)
        RETURNING TYPE_ID, RES_ID
        INTO :I$TYPE_ID, :I$RES_ID;
    END
    ELSE
    BEGIN
        UPDATE TABS
        SET IS_DEL = :I$IS_DEL,
            TAB_NUM = :I$TAB_NUM
        WHERE TAB_ID = :I$TAB_ID;
    END
    IF (I$RES_ID IS NOT NULL) THEN
    BEGIN
        EXECUTE PROCEDURE RES_ADD (:I$RES_ID,:I$LANG_CODE,:I$TAB_CAPTION);
    END

    IF (I$IS_DEL = 1) THEN BEGIN
        UPDATE PARAMS SET
            TAB_ID = NULL
        WHERE TAB_ID = :I$TAB_ID;

        UPDATE PARENTS SET
            TAB_ID = NULL
        WHERE TAB_ID = :I$TAB_ID;
    END
    suspend;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE TAB_MOVE (
    I$TAB_ID BIGINT,
    I$MOVE SMALLINT)
RETURNS (
    TN SMALLINT)
AS
DECLARE VARIABLE TAB_ID BIGINT = NULL;
DECLARE VARIABLE TYPE_ID BIGINT = NULL;
BEGIN
   SELECT TYPE_ID,
          TAB_NUM
   FROM TABS
   WHERE TAB_ID = :I$TAB_ID
   INTO   :TYPE_ID,
          :TN;

   SELECT TAB_ID
   FROM TABS
   WHERE TYPE_ID = :TYPE_ID
   AND TAB_NUM = (:TN + :I$MOVE)
   INTO   :TAB_ID;

   IF (TAB_ID IS NOT NULL) THEN
   BEGIN
      UPDATE TABS
      SET TAB_NUM = :TN
      WHERE TAB_ID = :TAB_ID;
      UPDATE TABS
      SET TAB_NUM = (:TN + :I$MOVE)
      WHERE TAB_ID = :I$TAB_ID;
   END
   SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE TAB_PARAMS_LIST (
    I$TYPE_ID BIGINT,
    I$LANG_CODE VARCHAR(2) = 'RU')
RETURNS (
    OBJ_ID VARCHAR(40),
    PARENT_ID VARCHAR(40),
    CAPTION VARCHAR(4000),
    PARAM_TYPE SMALLINT,
    LIST_ID BIGINT,
    DO_FUNC VARCHAR(100),
    TAG VARCHAR(100))
AS
declare variable V$RES_ID bigint;
declare variable V$TAB_RES_ID bigint;
declare variable V$SUB_PARENT_ID varchar(40);
declare variable V$SUB_TAB_ID varchar(40);
BEGIN
    FOR
        SELECT DISTINCT
               'T' || T.TAB_ID,
               T.RES_ID
        FROM TABS T
        INNER JOIN PARAMS P
        ON P.TAB_ID = T.TAB_ID
        AND P.PARAM_TYPE NOT IN (17,14,15)
        WHERE T.TYPE_ID = :I$TYPE_ID
        AND T.IS_DEL = 0
        ORDER BY T.TAB_NUM
        INTO :OBJ_ID,
             :V$TAB_RES_ID
    DO
    BEGIN
        SELECT VAL FROM RES_GET(:V$TAB_RES_ID,  :I$LANG_CODE) INTO :CAPTION;
        SUSPEND;
    END
    V$SUB_PARENT_ID = NULL;
    FOR
        SELECT P.PARAM_ID,
               P.PARAM_TYPE,
               P.LIST_ID,
               'T' || P.TAB_ID,
               P.DO_FUNC,
               P.TAG,
               P.RES_ID
        FROM PARAMS P
        WHERE P.TYPE_ID = :I$TYPE_ID
        AND P.PARAM_TYPE NOT IN (17)
        AND P.IS_DEL = 0
        ORDER BY P.GRID_ORDER
        INTO   :OBJ_ID,
               :PARAM_TYPE,
               :LIST_ID,
               :PARENT_ID,
               :DO_FUNC,
               :TAG,
               :V$RES_ID
    DO
    BEGIN
        SELECT VAL FROM RES_GET(:V$RES_ID,  :I$LANG_CODE) INTO :CAPTION;

        IF ((PARAM_TYPE = 14) OR (PARAM_TYPE = 15) ) THEN -- SEPARATORS
        BEGIN
            V$SUB_TAB_ID = PARENT_ID;
            OBJ_ID = 'TT' || OBJ_ID;
            V$SUB_PARENT_ID = OBJ_ID;
        END
        ELSE
        BEGIN
            IF (V$SUB_TAB_ID <> PARENT_ID) THEN
            BEGIN
                V$SUB_PARENT_ID = NULL;
            END
            IF (V$SUB_PARENT_ID IS NOT NULL) THEN
            BEGIN
                PARENT_ID = V$SUB_PARENT_ID;
            END
        END
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE TAB_PARAMS_LIST2 (
    I$TYPE_ID BIGINT,
    I$LEVEL_ID BIGINT,
    I$LANG_CODE VARCHAR(2) = 'RU')
RETURNS (
    OBJ_ID VARCHAR(40),
    PARENT_ID VARCHAR(40),
    CAPTION VARCHAR(4000),
    PARAM_TYPE SMALLINT,
    LIST_ID BIGINT,
    DO_FUNC VARCHAR(100),
    TAG VARCHAR(100),
    RUN_SQL VARCHAR(1000))
AS
DECLARE VARIABLE V$RES_ID BIGINT;
DECLARE VARIABLE S$RES_ID BIGINT;
DECLARE VARIABLE V$TAB_RES_ID BIGINT;
DECLARE VARIABLE V$SUB_PARENT_ID VARCHAR(40);
DECLARE VARIABLE V$SUB_TAB_ID VARCHAR(40);
DECLARE VARIABLE V$TAB_NUM SMALLINT;
DECLARE VARIABLE V$GRID_ORDER SMALLINT;
DECLARE VARIABLE V VARCHAR(4000);
BEGIN
    FOR
        SELECT DISTINCT
               'T' || T.TAB_ID,
               T.RES_ID,
               T.TAB_NUM

        FROM TABS T

        JOIN PARAMS P
        ON P.TAB_ID = T.TAB_ID
        AND P.PARAM_TYPE NOT IN (14, 15)

        JOIN LPARAMS LP
        ON LP.PARAM_ID = P.PARAM_ID
        AND LP.LEVEL_ID = :I$LEVEL_ID
        AND LP.EDIT_TYPE > -1

        WHERE T.TYPE_ID = :I$TYPE_ID
        AND T.IS_DEL = 0

        UNION

        SELECT DISTINCT
               'T' || T.TAB_ID,
               T.RES_ID,
               T.TAB_NUM

        FROM TABS T

        JOIN PARENTS PR
        ON PR.TAB_ID = T.TAB_ID

        JOIN LTYPES LT
        ON LT.TYPE_ID = PR.CHILD_ID
        AND LT.LEVEL_ID = :I$LEVEL_ID
        AND LT.IS_DEL = 0

        JOIN PARAMS P
        ON P.TYPE_ID = PR.CHILD_ID
        AND P.PARAM_TYPE NOT IN (14, 15)

        JOIN LPARAMS LP
        ON LP.PARAM_ID = P.PARAM_ID
        AND LP.LEVEL_ID = :I$LEVEL_ID
        AND LP.EDIT_TYPE > -1

        WHERE T.TYPE_ID = :I$TYPE_ID
        AND T.IS_DEL = 0

        ORDER BY 3

        INTO :OBJ_ID,
             :V$TAB_RES_ID,
             :V$TAB_NUM
    DO
    BEGIN
        SELECT UPPER(VAL) || ':'
        FROM RES_GET(:V$TAB_RES_ID, :I$LANG_CODE)
        INTO :CAPTION;
        SUSPEND;
    END

    V$SUB_PARENT_ID = NULL;
    FOR
        SELECT P.PARAM_ID,
               P.PARAM_TYPE,
               P.LIST_ID,
               'T' || P.TAB_ID,
               P.DO_FUNC,
               P.TAG,
               P.RES_ID,
               P.RUN_SQL
        FROM PARAMS P

        JOIN LPARAMS LP
        ON LP.PARAM_ID = P.PARAM_ID
        AND LP.LEVEL_ID = :I$LEVEL_ID
        AND LP.EDIT_TYPE > -1

        WHERE P.TYPE_ID = :I$TYPE_ID
        AND P.IS_DEL = 0
          --  AND P.PARAM_TYPE NOT IN (17)
        AND P.TAB_ID IS NULL

        ORDER BY P.GRID_ORDER

        INTO :OBJ_ID,
             :PARAM_TYPE,
             :LIST_ID,
             :PARENT_ID,
             :DO_FUNC,
             :TAG,
             :V$RES_ID,
             :RUN_SQL
    DO
    BEGIN
        SELECT VAL
        FROM RES_GET(:V$RES_ID, :I$LANG_CODE)
        INTO :CAPTION;

        IF ((PARAM_TYPE = 14) OR (PARAM_TYPE = 15)) THEN -- SEPARATORS
        BEGIN
            V$SUB_TAB_ID = PARENT_ID;
            OBJ_ID = 'TT' || OBJ_ID;
            V$SUB_PARENT_ID = OBJ_ID;
        END
        ELSE
        BEGIN
            IF (V$SUB_TAB_ID <> PARENT_ID) THEN
            BEGIN
                V$SUB_PARENT_ID = NULL;
            END
            IF (V$SUB_PARENT_ID IS NOT NULL) THEN
            BEGIN
                PARENT_ID = V$SUB_PARENT_ID;
            END
        END
        SUSPEND;
    END

    V$SUB_PARENT_ID = NULL;
    FOR
        SELECT P.PARAM_ID,
               P.PARAM_TYPE,
               P.LIST_ID,
               'T' || P.TAB_ID,
               P.DO_FUNC,
               P.TAG,
               P.RES_ID,
               P.SIZE_RES_ID,
               P.RUN_SQL
        FROM TABS T

        JOIN PARAMS P
        ON P.TAB_ID = T.TAB_ID

        JOIN LPARAMS LP
        ON LP.PARAM_ID = P.PARAM_ID
        AND LP.LEVEL_ID = :I$LEVEL_ID
        AND LP.EDIT_TYPE > -1

        WHERE T.TYPE_ID = :I$TYPE_ID
        AND T.IS_DEL = 0
--        AND P.PARAM_TYPE NOT IN (17)
        AND P.IS_DEL = 0

        ORDER BY T.TAB_NUM, P.GRID_ORDER

        INTO :OBJ_ID,
             :PARAM_TYPE,
             :LIST_ID,
             :PARENT_ID,
             :DO_FUNC,
             :TAG,
             :V$RES_ID,
             :S$RES_ID,
             :RUN_SQL
    DO
    BEGIN
        SELECT VAL
        FROM RES_GET(:V$RES_ID, :I$LANG_CODE)
        INTO :CAPTION;

        V = '';

        SELECT VAL
        FROM RES_GET(:S$RES_ID, :I$LANG_CODE)
        INTO :V;

        IF (V > '') THEN
        BEGIN
            CAPTION = CAPTION || ' (' || V || ')';
        END

        IF ((PARAM_TYPE = 14) OR (PARAM_TYPE = 15)) THEN -- SEPARATORS
        BEGIN
            V$SUB_TAB_ID = PARENT_ID;
            OBJ_ID = 'TT' || OBJ_ID;
            V$SUB_PARENT_ID = OBJ_ID;
        END
        ELSE
        BEGIN
            IF (V$SUB_TAB_ID <> PARENT_ID) THEN
            BEGIN
                V$SUB_PARENT_ID = NULL;
            END
            IF (V$SUB_PARENT_ID IS NOT NULL) THEN
            BEGIN
                PARENT_ID = V$SUB_PARENT_ID;
            END
        END
        SUSPEND;
    END

    FOR
        SELECT DISTINCT
               'T' || T.TAB_ID,
               'TTT' || PR.CHILD_ID,
               TY.RES_ID

        FROM TABS T

        JOIN PARENTS PR
        ON PR.TAB_ID = T.TAB_ID

        JOIN LTYPES LT
        ON LT.TYPE_ID = PR.CHILD_ID
        AND LT.LEVEL_ID = :I$LEVEL_ID
        AND LT.IS_DEL = 0

        JOIN PARAMS P
        ON P.TYPE_ID = PR.CHILD_ID
        AND P.PARAM_TYPE NOT IN (14, 15)

        JOIN LPARAMS LP
        ON LP.PARAM_ID = P.PARAM_ID
        AND LP.LEVEL_ID = :I$LEVEL_ID
        AND LP.EDIT_TYPE > -1

        JOIN TYPES TY
        ON TY.TYPE_ID = PR.CHILD_ID

        WHERE T.TYPE_ID = :I$TYPE_ID
        AND T.IS_DEL = 0

        ORDER BY TY.SORT_ORDER, T.TAB_NUM, P.GRID_ORDER

        INTO :PARENT_ID,
             :OBJ_ID,
             :V$TAB_RES_ID
    DO
    BEGIN
        SELECT UPPER(VAL) || ':'
        FROM RES_GET(:V$TAB_RES_ID, :I$LANG_CODE)
        INTO :CAPTION;
        SUSPEND;

        IF (:I$TYPE_ID = 14 AND :OBJ_ID = 'TTT15') THEN
        BEGIN
            OBJ_ID = 'TTT85';
            SELECT UPPER(VAL) || ':'
            FROM RES_GET((SELECT RES_ID FROM TYPES WHERE TYPE_ID = 85), :I$LANG_CODE)
            INTO :CAPTION;
            SUSPEND;
        END
    END

    V$SUB_PARENT_ID = NULL;
    FOR
        SELECT P.PARAM_ID,
               P.PARAM_TYPE,
               P.LIST_ID,
               'TTT' || PR.CHILD_ID,
               P.DO_FUNC,
               P.TAG,
               P.RES_ID,
               T.TAB_NUM,
               P.GRID_ORDER,
               P.RUN_SQL

        FROM TABS T

        JOIN PARENTS PR
        ON PR.TAB_ID = T.TAB_ID

        JOIN LTYPES LT
        ON LT.TYPE_ID = PR.CHILD_ID
        AND LT.LEVEL_ID = :I$LEVEL_ID
        AND LT.IS_DEL = 0

        JOIN PARAMS P
        ON P.TYPE_ID = PR.CHILD_ID

        JOIN LPARAMS LP
        ON LP.PARAM_ID = P.PARAM_ID
        AND LP.LEVEL_ID = :I$LEVEL_ID
        AND LP.EDIT_TYPE > -1

        WHERE T.TYPE_ID = :I$TYPE_ID
        AND T.IS_DEL = 0
--        AND P.PARAM_TYPE NOT IN (17)
        AND P.IS_DEL = 0

        UNION ALL

        SELECT P.PARAM_ID,
               P.PARAM_TYPE,
               P.LIST_ID,
               'TTT85',
               P.DO_FUNC,
               P.TAG,
               P.RES_ID,
               9999,
               P.GRID_ORDER,
               P.RUN_SQL

        FROM PARAMS P

        WHERE P.TYPE_ID = 85
        AND P.IS_DEL = 0
        AND :I$TYPE_ID = 14

        ORDER BY 8, 9

        INTO :OBJ_ID,
             :PARAM_TYPE,
             :LIST_ID,
             :PARENT_ID,
             :DO_FUNC,
             :TAG,
             :V$RES_ID,
             :V$TAB_NUM,
             :V$GRID_ORDER,
             :RUN_SQL
    DO
    BEGIN
        SELECT VAL
        FROM RES_GET(:V$RES_ID, :I$LANG_CODE)
        INTO :CAPTION;

        IF ((PARAM_TYPE = 14) OR (PARAM_TYPE = 15)) THEN -- SEPARATORS
        BEGIN
            V$SUB_TAB_ID = PARENT_ID;
            OBJ_ID = 'TT' || OBJ_ID;
            V$SUB_PARENT_ID = OBJ_ID;
        END
        ELSE
        BEGIN
            IF (V$SUB_TAB_ID <> PARENT_ID) THEN
            BEGIN
                V$SUB_PARENT_ID = NULL;
            END
            IF (V$SUB_PARENT_ID IS NOT NULL) THEN
            BEGIN
                PARENT_ID = V$SUB_PARENT_ID;
            END
        END
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE TARIFF_ADD (
    I$OBJ_ID BIGINT,
    I$TYPE_ID BIGINT,
    I$RANGE_ID BIGINT,
    I$NAME VARCHAR(1000),
    I$DATE DATE,
    I$RATE_MGMT FLOAT,
    I$RATE_BASE FLOAT,
    I$RATE_CLASS FLOAT,
    I$RATE_ROOM FLOAT,
    I$RATE_CHECK FLOAT,
    I$USER_ID VARCHAR(40),
    I$CORR_LIST VARCHAR(4000))
RETURNS (
    OBJ_ID BIGINT)
AS
DECLARE VARIABLE V$OU_ID BIGINT;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$PERSON_ID BIGINT;
DECLARE VARIABLE V$STATUS BIGINT;
DECLARE VARIABLE V$Y INTEGER;
DECLARE VARIABLE V$YEAR_DATE DATE;
DECLARE VARIABLE V$LAST_DATE DATE;
DECLARE VARIABLE V1 FLOAT;
DECLARE VARIABLE V2 FLOAT;
DECLARE VARIABLE V3 FLOAT;
DECLARE VARIABLE V4 FLOAT;
DECLARE VARIABLE V5 FLOAT;
DECLARE VARIABLE VN FLOAT;
DECLARE VARIABLE T INTEGER;
DECLARE VARIABLE V$TERMS BIGINT;
DECLARE VARIABLE S VARCHAR(4000);
DECLARE VARIABLE S2 VARCHAR(4000);
DECLARE VARIABLE V$Q1 BIGINT;
DECLARE VARIABLE V$Q2 BIGINT;
DECLARE VARIABLE P INTEGER;
DECLARE VARIABLE IDX INTEGER;
DECLARE VARIABLE V VARCHAR(400);
DECLARE VARIABLE V$JOB_ID BIGINT;
DECLARE VARIABLE V$JT VARCHAR(100);
begin

  -- Если указан OBJ_ID - сохраняем настройки имеющегося, если не указан - создаем новый

  SELECT FIRST 1 L2.OBJ_ID, LV.COST, CAST(LV.TAG AS DATE)
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$OU_ID, :V$Y, :V$YEAR_DATE;

  IF(I$DATE IS NULL) THEN I$DATE = CURRENT_DATE;
  IF(I$DATE < DATEADD(-10 DAY TO V$YEAR_DATE)) THEN EXCEPTION DATA_ERROR 'Тарификационный список можно добавлять с датой не ранее начала текущего учебного года';

  -- Кастомный список
  IF(I$CORR_LIST IS NOT NULL AND I$CORR_LIST <> '') THEN I$RANGE_ID = 101;

  -- Ведомости добавляются строго по хронологии
  SELECT FIRST 1 V3571.VAL, V3575.VAL, V3576.VAL, V3577.VAL, V3578.VAL, V3579.VAL
  FROM LINKS L532
  JOIN VALD V3571 ON V3571.OBJ_ID = L532.OBJ_ID AND V3571.PARAM_ID = 3571 AND V3571.IS_DEL = 0
  LEFT JOIN VALF V3575 ON V3575.OBJ_ID = L532.OBJ_ID AND V3575.PARAM_ID = 3575 AND V3575.IS_DEL = 0
  LEFT JOIN VALF V3576 ON V3576.OBJ_ID = L532.OBJ_ID AND V3576.PARAM_ID = 3576 AND V3576.IS_DEL = 0
  LEFT JOIN VALF V3577 ON V3577.OBJ_ID = L532.OBJ_ID AND V3577.PARAM_ID = 3577 AND V3577.IS_DEL = 0
  LEFT JOIN VALF V3578 ON V3578.OBJ_ID = L532.OBJ_ID AND V3578.PARAM_ID = 3578 AND V3578.IS_DEL = 0
  LEFT JOIN VALF V3579 ON V3579.OBJ_ID = L532.OBJ_ID AND V3579.PARAM_ID = 3579 AND V3579.IS_DEL = 0
  WHERE L532.PARENT_ID = :V$OU_ID AND L532.OBJ_TYPE_ID = 532 AND L532.DATE_DEL IS NULL
  ORDER BY 1 DESC
  INTO :V$LAST_DATE, :V1, :V2, :V3, :V4, :V5;

  IF(I$DATE < V$LAST_DATE) THEN EXCEPTION DATA_ERROR 'Списки добавляются строго по хронологии, уже есть список с датой позднее указанной';

  -- Заполняем поля, которые не заполнены. Ругаемся если не получилось
  IF(I$RATE_MGMT IS NULL OR I$RATE_BASE IS NULL OR I$RATE_CLASS IS NULL OR I$RATE_ROOM IS NULL OR I$RATE_CHECK IS NULL) THEN EXCEPTION DATA_ERROR 'Не заполнена одна из настроек тарификации';

  -- Создаем новый объект (шапка тарификационного списка)
  IF(I$OBJ_ID IS NULL) THEN
  BEGIN
    IF(I$TYPE_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не указан тип тарифного списка';
    IF(I$RANGE_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не указан состав втарифного списка';
    SELECT OBJ_ID FROM OBJECT_ADD(:V$OU_ID, 532) INTO :OBJ_ID;
    SELECT 1 FROM VAL_ADD(3572, :OBJ_ID, :I$TYPE_ID) INTO :T;
  END
  ELSE
  BEGIN
    SELECT FIRST 1 L532.OBJ_ID, V3573.LISTVAL_ID, V3575.VAL, V3576.VAL, V3577.VAL, V3578.VAL, V3579.VAL
    FROM LINKS L532
    JOIN VALL V3573 ON V3573.OBJ_ID = L532.OBJ_ID AND V3573.PARAM_ID = 3573 AND V3573.IS_DEL = 0
    LEFT JOIN VALF V3575 ON V3575.OBJ_ID = L532.OBJ_ID AND V3575.PARAM_ID = 3575 AND V3575.IS_DEL = 0
    LEFT JOIN VALF V3576 ON V3576.OBJ_ID = L532.OBJ_ID AND V3576.PARAM_ID = 3576 AND V3576.IS_DEL = 0
    LEFT JOIN VALF V3577 ON V3577.OBJ_ID = L532.OBJ_ID AND V3577.PARAM_ID = 3577 AND V3577.IS_DEL = 0
    LEFT JOIN VALF V3578 ON V3578.OBJ_ID = L532.OBJ_ID AND V3578.PARAM_ID = 3578 AND V3578.IS_DEL = 0
    LEFT JOIN VALF V3579 ON V3579.OBJ_ID = L532.OBJ_ID AND V3579.PARAM_ID = 3579 AND V3579.IS_DEL = 0
    WHERE L532.OBJ_ID = :I$OBJ_ID AND L532.PARENT_TYPE_ID = 2 AND L532.DATE_DEL IS NULL
    INTO :OBJ_ID, :V$STATUS, :V1, :V2, :V3, :V4, :V5;

    IF(OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Тарификационный список не найден или был удален';
    IF(V$STATUS <> 11716) THEN EXCEPTION DATA_ERROR 'Тарификационный список можно изменять только в статусе Проект';
  END

  SELECT 1 FROM VAL_ADD(3571, :OBJ_ID, :I$DATE) INTO :T;
  SELECT 1 FROM VAL_ADD(3574, :OBJ_ID, :I$NAME) INTO :T;
  SELECT 1 FROM VAL_ADD(3575, :OBJ_ID, :I$RATE_MGMT) INTO :T;
  SELECT 1 FROM VAL_ADD(3576, :OBJ_ID, :I$RATE_BASE) INTO :T;
  SELECT 1 FROM VAL_ADD(3577, :OBJ_ID, :I$RATE_CLASS) INTO :T;
  SELECT 1 FROM VAL_ADD(3578, :OBJ_ID, :I$RATE_ROOM) INTO :T;
  SELECT 1 FROM VAL_ADD(3579, :OBJ_ID, :I$RATE_CHECK) INTO :T;

  -- Список сотрудников и должностей
  -- надо бы сохранять еще и название текстом, на случай последующего изменения (S2)
  T = 0;
  IF(I$OBJ_ID IS NULL) THEN
  FOR
    SELECT L15.OBJ_ID, L14.OBJ_ID, V71.VAL, V587.LISTVAL_ID, V66.VAL, 0, LV58.SORT_ORDER, C.CAPTION
    FROM LINKS L14
    JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
    JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0 AND V73.VAL <= :I$DATE
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
    JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
    JOIN VALL V58 ON V58.OBJ_ID = LP13.PARENT_ID AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0    -- должность по списку
    JOIN LISTVALS LV58 ON LV58.LISTVAL_ID = V58.LISTVAL_ID
    JOIN VALS V66 ON V66.OBJ_ID = LP13.PARENT_ID AND V66.PARAM_ID = 66 AND V66.IS_DEL = 0    -- должность текст
    JOIN VALF V71 ON V71.OBJ_ID = L15.OBJ_ID AND V71.PARAM_ID = 71 AND V71.IS_DEL = 0        -- кол-во ставок
    JOIN VALL V587 ON V587.OBJ_ID = L15.OBJ_ID AND V587.PARAM_ID = 587 AND V587.IS_DEL = 0   -- условия приема на должность
    LEFT JOIN OBJECT_CAPTION_GET(L14.OBJ_ID) C ON 1 = 1
    WHERE L14.PARENT_TYPE_ID IN (2, 211) AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL AND (V74.VAL IS NULL OR V74.VAL >= :I$DATE)
    AND (
      :I$RANGE_ID = 0 -- все
      OR (:I$RANGE_ID = 1 AND (LV58.TAG IN ('R1', 'R2', 'R3') OR LV58."FILTER" IN ('R1', 'R2', 'R3')))  -- руководители
      OR (:I$RANGE_ID = 2 AND (LV58.TAG IN ('U', 'V', 'P', 'S', 'C', 'W') OR LV58."FILTER" IN ('U', 'V', 'P', 'S', 'C', 'W')))  -- рабочие и служащие ???
      OR (:I$RANGE_ID = 3 AND (LV58.TAG IN ('Z') OR LV58."FILTER" IN ('Z')))  -- прочие ?!!
      OR (:I$RANGE_ID = 101 AND L15.OBJ_ID IN (SELECT ID FROM STR_TO_ID_LIST(:I$CORR_LIST)))  --корректирующий тарификационный список
    )
    -- Вакантные ставки по указанную дату (временно делаем по текущему состоянию)
    UNION
    SELECT DISTINCT L13.OBJ_ID, NULL, V62.VAL - CAST(V2850.V AS FLOAT), NULL, V66.VAL, 1, LV58.SORT_ORDER, NULL-- , V62.VAL, V2850.F
    FROM LINKS L13
    JOIN VALF V62 ON V62.OBJ_ID = L13.OBJ_ID AND V62.PARAM_ID = 62 AND V62.IS_DEL = 0    -- кол-во ставок
    JOIN VALS V66 ON V66.OBJ_ID = L13.OBJ_ID AND V66.PARAM_ID = 66 AND V66.IS_DEL = 0    -- должность текст
    JOIN VALL V58 ON V58.OBJ_ID = L13.OBJ_ID AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0    -- должность по списку
    JOIN LISTVALS LV58 ON LV58.LISTVAL_ID = V58.LISTVAL_ID
    LEFT JOIN VAL_GET(L13.OBJ_ID, 2850, 0) V2850 ON 1 =  1
    WHERE L13.OBJ_TYPE_ID = 13 AND L13.PARENT_TYPE_ID IN (2, 211) AND L13.DATE_DEL IS NULL AND V2850.V < V62.VAL
    AND (
      :I$RANGE_ID = 0 -- все
      OR (:I$RANGE_ID = 1 AND (LV58.TAG IN ('R1', 'R2', 'R3') OR LV58."FILTER" IN ('R1', 'R2', 'R3')))  -- руководители
      OR (:I$RANGE_ID = 2 AND (LV58.TAG IN ('U', 'V', 'P', 'S', 'C', 'W') OR LV58."FILTER" IN ('U', 'V', 'P', 'S', 'C', 'W')))  -- рабочие и служащие ???
      OR (:I$RANGE_ID = 3 AND (LV58.TAG IN ('Z') OR LV58."FILTER" IN ('Z')))  -- прочие ?!!
    )
    ORDER BY 6, 7, 8 -- временно
    INTO :V$OBJ_ID, :V$PERSON_ID, :VN, :V$TERMS, :S2, :V$Q1, :V$Q2, :S -- последние три поля только для сортировки
  DO
  BEGIN
    -- Значение поля пока берем из предыдущей версии тарификационного списка, неважно в проекте или в действующем
    S = NULL;
    SELECT FIRST 1 D.VAL
    FROM TARIFF_DATA D
    JOIN LINKS LP2 ON LP2.OBJ_ID = D.PARENT_ID AND LP2.PARENT_TYPE_ID = 2 AND LP2.DATE_DEL IS NULL
    JOIN VALD V3571 ON V3571.OBJ_ID = D.PARENT_ID AND V3571.PARAM_ID = 3571 AND V3571.IS_DEL = 0 AND V3571.VAL < :I$DATE
    WHERE D.DATE_DEL IS NULL AND D.JOB_ID = :V$OBJ_ID -- тут покроется оба варианта выбора
    ORDER BY V3571.VAL DESC
    INTO :S;
    -- Если конкретной персоны нет, значит это вакантная должность
    -- Если встречается в первый раз, заполняем по фактическому наполнению
    IF(S IS NULL) THEN
    BEGIN
      S = ';;;;;;;;;;;;;;;;;;;;;;;;;;;;;'; -- всего 29 значений
    END

    EXECUTE PROCEDURE TARIFF_FILL(:OBJ_ID, :V$OBJ_ID, :V$PERSON_ID, :S, :T);
    T = T + 1;
  END

  -- Если редактируем существующий список - надо пересчитать
  -- суммы не пересчитываем - они все равно обновятся на фронте
  IF(I$OBJ_ID IS NOT NULL) THEN
  BEGIN
    FOR
      SELECT D.OBJ_ID, D.VAL, D.JOB_ID
      FROM TARIFF_DATA D
      WHERE D.DATE_DEL IS NULL AND D.PARENT_ID = :OBJ_ID
      ORDER BY D.ROW_INDEX
      INTO :V$OBJ_ID, :S, :V$JOB_ID
    DO
    BEGIN
      S2 = '';
      IDX = 9;
      WHILE(CHAR_LENGTH(S) > 0) DO
      BEGIN
        P = POSITION(';' IN S);
        IF(P <= 0) THEN P = CHAR_LENGTH(S) + 1;
        V = SUBSTRING(S FROM 1 FOR P - 1);
        S = SUBSTRING(S FROM P + 1);
        IF(IDX = 9) THEN V = I$RATE_BASE;
        ELSE IF(IDX = 17) THEN
        BEGIN
          -- Только для руководителей, масштаб управления
          V$JT = NULL;
          SELECT FIRST 1 LV."FILTER"
          FROM VALL V58
          JOIN LISTVALS LV ON LV.LISTVAL_ID = V58.LISTVAL_ID
          WHERE V58.OBJ_ID = :V$JOB_ID AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0
          UNION
          SELECT FIRST 1 LV."FILTER"
          FROM LINKS LP13
          JOIN VALL V58 ON V58.OBJ_ID = LP13.PARENT_ID AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0
          JOIN LISTVALS LV ON LV.LISTVAL_ID = V58.LISTVAL_ID
          WHERE LP13.OBJ_ID = :V$JOB_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
          INTO :V$JT;
          IF(V$JT IN ('R1', 'R2')) THEN V = I$RATE_MGMT;
        END
        ELSE IF(IDX = 30) THEN
        BEGIN
          IF(V <> '') THEN V = V * I$RATE_CLASS / V3;
        END
        ELSE IF(IDX = 31) THEN
        BEGIN
          IF(V <> '') THEN V = V * I$RATE_ROOM / V4;
        END
        ELSE IF(IDX = 32) THEN
        BEGIN
          IF(V <> '') THEN V = V * I$RATE_CHECK / V5;
        END
        IF(IDX <> 37 AND V <> '' AND POSITION('.' IN V) > 0) THEN
        BEGIN
          WHILE(RIGHT(V, 1) = '0') DO V = SUBSTRING(V FROM 1 FOR CHAR_LENGTH(V) - 1);
          IF(RIGHT(V, 1) = '.') THEN V = SUBSTRING(V FROM 1 FOR CHAR_LENGTH(V) - 1);
        END
        IF(S2 <> '') THEN S2 = S2 || ';';
        S2 = S2 || V;
        IDX = IDX + 1;
      END

      UPDATE TARIFF_DATA
      SET VAL = :S2
      WHERE OBJ_ID = :V$OBJ_ID AND VAL <> :S2;
    END
  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE TARIFF_ADD_ROW (
    I$PARENT_ID BIGINT,
    I$JOB_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    OBJ_ID BIGINT,
    PERSON_ID BIGINT,
    PERSON_NAME VARCHAR(400),
    JOB_ID BIGINT,
    JOB_NAME VARCHAR(400),
    JOB_TYPE VARCHAR(40),
    JOB_GROUP VARCHAR(400),
    JOB_SUBGROUP VARCHAR(400),
    VAL VARCHAR(2000),
    EDU_COL BIGINT,
    QUAL_COL BIGINT,
    SDEG_COL BIGINT,
    RANK_COL BIGINT,
    EXPR_COL INTEGER,
    GRADES_K INTEGER,
    ROOMS_K INTEGER,
    COPYBOOK_K INTEGER)
AS
DECLARE VARIABLE V$STATUS BIGINT;
DECLARE VARIABLE V$DATE DATE;
DECLARE VARIABLE V$TYPE_ID BIGINT;
DECLARE VARIABLE V$INDEX INTEGER;
begin

  SELECT V3573.LISTVAL_ID, V3571.VAL
  FROM LINKS L532
  JOIN VALL V3573 ON V3573.OBJ_ID = L532.OBJ_ID AND V3573.PARAM_ID = 3573 AND V3573.IS_DEL = 0
  JOIN VALD V3571 ON V3571.OBJ_ID = L532.OBJ_ID AND V3571.PARAM_ID = 3571 AND V3571.IS_DEL = 0
  WHERE L532.PARENT_TYPE_ID = 2 AND L532.OBJ_ID = :I$PARENT_ID AND L532.DATE_DEL IS NULL
  INTO :V$STATUS, V$DATE;

  IF(V$STATUS IS NULL) THEN EXCEPTION DATA_ERROR 'Список не найден или был удален';
  IF(V$STATUS <> 11716) THEN EXCEPTION DATA_ERROR 'Список можно изменять только в статусе Проект';

  -- Проверяем на дубли
  SELECT FIRST 1 D.OBJ_ID
  FROM TARIFF_DATA D
  WHERE D.DATE_DEL IS NULL AND D.PARENT_ID = :I$PARENT_ID AND D.JOB_ID = :I$JOB_ID
  INTO :OBJ_ID;

  IF(OBJ_ID IS NOT NULL) THEN EXCEPTION DATA_ERROR 'Запись уже добавлена в список: ' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$JOB_ID));

  -- Проверяем тип записи
  SELECT TYPE_ID
  FROM OBJECTS
  WHERE OBJ_ID = :I$JOB_ID
  INTO :V$TYPE_ID;

  IF(V$TYPE_ID IS NULL OR V$TYPE_ID NOT IN (13, 15)) THEN EXCEPTION DATA_ERROR 'Недопустимый тип объекта для добавления';

  IF(V$TYPE_ID = 15) THEN
  BEGIN
    SELECT FIRST 1 LP14.PARENT_ID
    FROM LINKS LP14
    WHERE LP14.OBJ_ID = :I$JOB_ID AND LP14.PARENT_TYPE_ID = 14 AND LP14.DATE_DEL IS NULL
    INTO :PERSON_ID;

    IF(PERSON_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не найдена персона по назначению на должность';
  END

  IF(V$TYPE_ID = 13) THEN
  BEGIN
    -- В конец
    SELECT FIRST 1 D.ROW_INDEX + 1
    FROM TARIFF_DATA D
    WHERE D.DATE_DEL IS NULL AND D.PARENT_ID = :I$PARENT_ID
    ORDER BY 1 DESC
    INTO :V$INDEX;

    IF(V$INDEX IS NULL) THEN V$INDEX = 0;
  END
  ELSE
  BEGIN
    -- Раздвигаем строки для вакансий
    SELECT FIRST 1 D.ROW_INDEX + 1
    FROM TARIFF_DATA D
    WHERE D.DATE_DEL IS NULL AND D.PARENT_ID = :I$PARENT_ID AND D.PERSON_ID IS NULL
    ORDER BY 1 DESC
    INTO :V$INDEX;

    IF(V$INDEX IS NULL) THEN V$INDEX = 0;

    UPDATE TARIFF_DATA
    SET ROW_INDEX = ROW_INDEX + 1
    WHERE DATE_DEL IS NULL AND PARENT_ID = :I$PARENT_ID AND ROW_INDEX >= :V$INDEX;
  END

    -- Значение поля пока берем из предыдущей версии тарификационного списка, неважно в проекте или в действующем
  VAL = NULL;
  SELECT FIRST 1 D.VAL
  FROM TARIFF_DATA D
  JOIN LINKS LP2 ON LP2.OBJ_ID = D.PARENT_ID AND LP2.PARENT_TYPE_ID = 2 AND LP2.DATE_DEL IS NULL
  JOIN VALD V3571 ON V3571.OBJ_ID = D.PARENT_ID AND V3571.PARAM_ID = 3571 AND V3571.IS_DEL = 0 AND V3571.VAL < :V$DATE
  WHERE D.DATE_DEL IS NULL AND D.JOB_ID = :I$JOB_ID -- тут покроется оба варианта выбора
  ORDER BY V3571.VAL DESC
  INTO :VAL;
  -- Если конкретной персоны нет, значит это вакантная должность
  -- Если встречается в первый раз, заполняем по фактическому наполнению
  IF(VAL IS NULL) THEN
  BEGIN
    VAL = ';;;;;;;;;;;;;;;;;;;;;;;;;;;;;'; -- всего 29 значений
  END

  EXECUTE PROCEDURE TARIFF_FILL(:I$PARENT_ID, :I$JOB_ID, :PERSON_ID, :VAL, :V$INDEX);

  SELECT FIRST 1 D.OBJ_ID, D.VAL
  FROM TARIFF_DATA D
  WHERE D.DATE_DEL IS NULL AND D.PARENT_ID = :I$PARENT_ID AND D.JOB_ID = :I$JOB_ID
  INTO :OBJ_ID, :VAL;

  -- Заполняем остальные справочные поля
  JOB_ID = I$JOB_ID;
  IF(V$TYPE_ID = 13) THEN
  BEGIN
    -- Сама должность
    JOB_NAME = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$JOB_ID));
    SELECT FIRST 1 IIF(LV.LIST_ID = 21, LV.TAG, LV."FILTER"), C1.VAL, C2.VAL
    FROM OBJECTS L13
    JOIN VALL V58 ON V58.OBJ_ID = L13.OBJ_ID AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V58.LISTVAL_ID
    JOIN VALL V63 ON V63.OBJ_ID = L13.OBJ_ID AND V63.PARAM_ID = 63 AND V63.IS_DEL = 0
    LEFT JOIN LISTVAL_TEXT(V63.LISTVAL_ID) C1 ON 1 = 1
    JOIN VALL V64 ON V64.OBJ_ID = L13.OBJ_ID AND V64.PARAM_ID = 64 AND V64.IS_DEL = 0
    LEFT JOIN LISTVAL_TEXT(V64.LISTVAL_ID) C2 ON 1 = 1
    WHERE L13.OBJ_ID = :I$JOB_ID
    INTO :JOB_TYPE, :JOB_GROUP, :JOB_SUBGROUP;
  END
  ELSE
  BEGIN
    -- Назначение на должность
    PERSON_NAME = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:PERSON_ID));
    SELECT FIRST 1 IIF(LV.LIST_ID = 21, LV.TAG, LV."FILTER"), C1.VAL, C2.VAL
    FROM LINKS LP13
    JOIN VALL V58 ON V58.OBJ_ID = LP13.PARENT_ID AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V58.LISTVAL_ID
    JOIN VALL V63 ON V63.OBJ_ID = LP13.PARENT_ID AND V63.PARAM_ID = 63 AND V63.IS_DEL = 0
    LEFT JOIN LISTVAL_TEXT(V63.LISTVAL_ID) C1 ON 1 = 1
    JOIN VALL V64 ON V64.OBJ_ID = LP13.PARENT_ID AND V64.PARAM_ID = 64 AND V64.IS_DEL = 0
    LEFT JOIN LISTVAL_TEXT(V64.LISTVAL_ID) C2 ON 1 = 1
    WHERE LP13.OBJ_ID = :I$JOB_ID AND LP13.PARENT_TYPE_ID = 13 -- DATE_DEL не проверять !
    INTO :JOB_TYPE, :JOB_GROUP, :JOB_SUBGROUP;

    SELECT FIRST 1 V284.LISTVAL_ID
    FROM LINKS L33
    JOIN VALD V290 ON V290.OBJ_ID = L33.OBJ_ID AND V290.PARAM_ID = 290 AND V290.IS_DEL = 0 AND V290.VAL <= :V$DATE
    JOIN VALL V284 ON V284.OBJ_ID = L33.OBJ_ID AND V284.PARAM_ID = 284 AND V284.IS_DEL = 0 AND V284.LISTVAL_ID IN (620, 622, 623, 3031, 3032, 14146, 5256)
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V284.LISTVAL_ID
    WHERE L33.PARENT_ID = :PERSON_ID AND L33.OBJ_TYPE_ID = 33 AND L33.DATE_DEL IS NULL
    ORDER BY V290.VAL DESC
    INTO :EDU_COL;

    -- Смотри комментарии в TARIFF_GET
    SELECT FIRST 1 V545.LISTVAL_ID--, JOB.VAL
    FROM LINKS L34
    JOIN VALD V544 ON V544.OBJ_ID = L34.OBJ_ID AND V544.PARAM_ID = 544 AND V544.IS_DEL = 0      -- дата комиссии
    JOIN VALL V545 ON V545.OBJ_ID = L34.OBJ_ID AND V545.PARAM_ID = 545 AND V545.IS_DEL = 0 AND V545.LISTVAL_ID IN (1208, 1209, 1210) -- решение комиссии
    --LEFT JOIN VALL V2347 ON V2347.OBJ_ID = L34.OBJ_ID AND V2347.PARAM_ID = 2347 AND V2347.IS_DEL = 0 -- должность
    --LEFT JOIN LISTVAL_TEXT(V2347.LISTVAL_ID) JOB ON 1 = 1
    WHERE L34.PARENT_ID = :PERSON_ID AND L34.OBJ_TYPE_ID = 34 AND L34.DATE_DEL IS NULL
      AND (V544.VAL IS NOT NULL AND V544.VAL < :V$DATE)
    ORDER BY V544.VAL DESC
    INTO :QUAL_COL;

    SELECT FIRST 1 V280.LISTVAL_ID
    FROM VALL V280
    WHERE V280.OBJ_ID = :PERSON_ID AND V280.PARAM_ID = 280 AND V280.IS_DEL = 0 AND V280.LISTVAL_ID <> 629
    INTO :RANK_COL;

    SELECT FIRST 1 V279.LISTVAL_ID
    FROM VALL V279
    WHERE V279.OBJ_ID = :PERSON_ID AND V279.PARAM_ID = 279 AND V279.IS_DEL = 0 AND V279.LISTVAL_ID <> 626
    INTO :SDEG_COL;
    IF(SDEG_COL IS NULL) THEN
    SELECT FIRST 1 V345.LISTVAL_ID
    FROM LINKS L39
    JOIN VALD V347 ON V347.OBJ_ID = L39.OBJ_ID AND V347.PARAM_ID = 347 AND V347.IS_DEL = 0 -- дата награждения
    JOIN VALL V345 ON V345.OBJ_ID = L39.OBJ_ID AND V345.PARAM_ID = 345 AND V345.IS_DEL = 0 -- тип награды
    WHERE L39.PARENT_ID = :PERSON_ID AND L39.OBJ_TYPE_ID = 39 AND L39.DATE_DEL IS NULL
      AND (V347.VAL IS NOT NULL AND V347.VAL < :V$DATE)
    ORDER BY V347.VAL DESC
    INTO :SDEG_COL;

    -- Стаж работы, в днях
    -- Для педагогических должностяж берем педагогический, для остальных по должности
    SELECT SUM(V.DAYS360_COUNT)
    FROM LINKS L85
    JOIN VALL V465 ON V465.OBJ_ID = L85.OBJ_ID AND V465.PARAM_ID = 465 AND V465.IS_DEL = 0 AND V465.LISTVAL_ID = IIF(:JOB_TYPE = 'U', 942, 1978)
    JOIN VALD V466 ON V466.OBJ_ID = L85.OBJ_ID AND V466.PARAM_ID = 466 AND V466.IS_DEL = 0
    LEFT JOIN VALD V467 ON V467.OBJ_ID = L85.OBJ_ID AND V467.PARAM_ID = 467 AND V467.IS_DEL = 0
    LEFT JOIN GET_DAYS360_COUNT(V466.VAL, COALESCE(V467.VAL, :V$DATE)) V ON 1 = 1
    WHERE L85.PARENT_ID = :PERSON_ID AND L85.OBJ_TYPE_ID = 85 AND L85.DATE_DEL IS NULL
    INTO :EXPR_COL;

    SELECT COUNT(*)
    FROM EDULOAD_DATA D
    JOIN LINKS L531 ON L531.OBJ_ID = D.PARENT_ID AND L531.OBJ_TYPE_ID = 531 AND L531.DATE_DEL IS NULL
    JOIN VALL V3567 ON V3567.OBJ_ID = L531.OBJ_ID AND V3567.PARAM_ID = 3567 AND V3567.IS_DEL = 0
    JOIN LISTVALS LV3567 ON LV3567.LISTVAL_ID = V3567.LISTVAL_ID AND LV3567.LIST_ID = 29 AND LV3567.IS_DEL = 0 AND LV3567.COST = EXTRACT(YEAR FROM :V$DATE)
    WHERE D.PERSON_ID = :PERSON_ID AND D.REF_TYPE_ID = 9 AND D.DATE_DEL IS NULL
    INTO :GRADES_K;

    SELECT COUNT(*)
    FROM EDULOAD_DATA D
    JOIN LINKS L531 ON L531.OBJ_ID = D.PARENT_ID AND L531.OBJ_TYPE_ID = 531 AND L531.DATE_DEL IS NULL
    JOIN VALL V3567 ON V3567.OBJ_ID = L531.OBJ_ID AND V3567.PARAM_ID = 3567 AND V3567.IS_DEL = 0
    JOIN LISTVALS LV3567 ON LV3567.LISTVAL_ID = V3567.LISTVAL_ID AND LV3567.LIST_ID = 29 AND LV3567.IS_DEL = 0 AND LV3567.COST = EXTRACT(YEAR FROM :V$DATE)
    WHERE D.PERSON_ID = :PERSON_ID AND D.REF_TYPE_ID = 61 AND D.DATE_DEL IS NULL
    INTO :ROOMS_K;

    -- COPYBOOK_K
  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE TARIFF_CLONE (
    I$PARENT_ID BIGINT,
    I$NAME VARCHAR(1000),
    I$DATE DATE,
    I$RATE_MGMT FLOAT,
    I$RATE_BASE FLOAT,
    I$RATE_CLASS FLOAT,
    I$RATE_ROOM FLOAT,
    I$RATE_CHECK FLOAT,
    I$USER_ID VARCHAR(40))
AS
DECLARE VARIABLE V$OU_ID BIGINT;
DECLARE VARIABLE V$TYPE_ID BIGINT;
DECLARE VARIABLE V$Y INTEGER;
DECLARE VARIABLE V$YEAR_DATE DATE;
DECLARE VARIABLE V$LAST_DATE DATE;
DECLARE VARIABLE V1 FLOAT;
DECLARE VARIABLE V2 FLOAT;
DECLARE VARIABLE V3 FLOAT;
DECLARE VARIABLE V4 FLOAT;
DECLARE VARIABLE V5 FLOAT;
DECLARE VARIABLE OBJ_ID BIGINT;
DECLARE VARIABLE T INTEGER;
DECLARE VARIABLE S VARCHAR(4000);
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$JOB_ID BIGINT;
begin

  SELECT FIRST 1 L2.OBJ_ID, LV.COST, CAST(LV.TAG AS DATE)
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$OU_ID, :V$Y, :V$YEAR_DATE;

  SELECT V3572.LISTVAL_ID
  FROM LINKS L532
  JOIN VALL V3573 ON V3573.OBJ_ID = L532.OBJ_ID AND V3573.PARAM_ID = 3573 AND V3573.IS_DEL = 0  -- статус
  JOIN VALL V3572 ON V3572.OBJ_ID = L532.OBJ_ID AND V3572.PARAM_ID = 3572 AND V3572.IS_DEL = 0
  WHERE L532.PARENT_TYPE_ID = 2 AND L532.OBJ_TYPE_ID = 532 AND L532.OBJ_ID = :I$PARENT_ID AND L532.DATE_DEL IS NULL
  INTO :V$TYPE_ID;

  IF(V$TYPE_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Выбранный тарифный список не найден';

  IF(I$DATE IS NULL) THEN I$DATE = CURRENT_DATE;
  IF(I$DATE < DATEADD(-10 DAY TO V$YEAR_DATE)) THEN EXCEPTION DATA_ERROR 'Тарификационный список можно добавлять с датой не ранее начала текущего учебного года';

  -- Ведомости добавляются строго по хронологии
  SELECT FIRST 1 V3571.VAL, V3575.VAL, V3576.VAL, V3577.VAL, V3578.VAL, V3579.VAL
  FROM LINKS L532
  JOIN VALD V3571 ON V3571.OBJ_ID = L532.OBJ_ID AND V3571.PARAM_ID = 3571 AND V3571.IS_DEL = 0
  LEFT JOIN VALF V3575 ON V3575.OBJ_ID = L532.OBJ_ID AND V3575.PARAM_ID = 3575 AND V3575.IS_DEL = 0
  LEFT JOIN VALF V3576 ON V3576.OBJ_ID = L532.OBJ_ID AND V3576.PARAM_ID = 3576 AND V3576.IS_DEL = 0
  LEFT JOIN VALF V3577 ON V3577.OBJ_ID = L532.OBJ_ID AND V3577.PARAM_ID = 3577 AND V3577.IS_DEL = 0
  LEFT JOIN VALF V3578 ON V3578.OBJ_ID = L532.OBJ_ID AND V3578.PARAM_ID = 3578 AND V3578.IS_DEL = 0
  LEFT JOIN VALF V3579 ON V3579.OBJ_ID = L532.OBJ_ID AND V3579.PARAM_ID = 3579 AND V3579.IS_DEL = 0
  WHERE L532.PARENT_ID = :V$OU_ID AND L532.OBJ_TYPE_ID = 532 AND L532.DATE_DEL IS NULL
  ORDER BY 1 DESC
  INTO :V$LAST_DATE, :V1, :V2, :V3, :V4, :V5;

  IF(I$DATE < V$LAST_DATE) THEN EXCEPTION DATA_ERROR 'Списки добавляются строго по хронологии, уже есть список с датой позднее указанной';

  -- Заполняем поля, которые не заполнены. Ругаемся если не получилось
  IF(I$RATE_MGMT IS NULL) THEN I$RATE_MGMT = V1;
  IF(I$RATE_BASE IS NULL) THEN I$RATE_BASE = V2;
  IF(I$RATE_CLASS IS NULL) THEN I$RATE_CLASS = V3;
  IF(I$RATE_ROOM IS NULL) THEN I$RATE_ROOM = V4;
  IF(I$RATE_CHECK IS NULL) THEN I$RATE_CHECK = V5;
  IF(I$RATE_MGMT IS NULL OR I$RATE_BASE IS NULL OR I$RATE_CLASS IS NULL OR I$RATE_ROOM IS NULL OR I$RATE_CHECK IS NULL) THEN EXCEPTION DATA_ERROR 'Не заполнена одна из настроек тарификации';

  -- Создаем новый объект (шапка тарификационного списка)
  SELECT OBJ_ID FROM OBJECT_ADD(:V$OU_ID, 532) INTO :OBJ_ID;
  SELECT 1 FROM VAL_ADD(3571, :OBJ_ID, :I$DATE) INTO :T;
  SELECT 1 FROM VAL_ADD(3572, :OBJ_ID, :V$TYPE_ID) INTO :T;
  SELECT 1 FROM VAL_ADD(3574, :OBJ_ID, :I$NAME) INTO :T;
  SELECT 1 FROM VAL_ADD(3575, :OBJ_ID, :I$RATE_MGMT) INTO :T;
  SELECT 1 FROM VAL_ADD(3576, :OBJ_ID, :I$RATE_BASE) INTO :T;
  SELECT 1 FROM VAL_ADD(3577, :OBJ_ID, :I$RATE_CLASS) INTO :T;
  SELECT 1 FROM VAL_ADD(3578, :OBJ_ID, :I$RATE_ROOM) INTO :T;
  SELECT 1 FROM VAL_ADD(3579, :OBJ_ID, :I$RATE_CHECK) INTO :T;

  FOR
    SELECT D.PERSON_ID, D.JOB_ID, D.ROW_INDEX, D.VAL
    FROM TARIFF_DATA D
    WHERE D.DATE_DEL IS NULL AND D.PARENT_ID = :I$PARENT_ID
    ORDER BY D.ROW_INDEX
    INTO :V$OBJ_ID, :V$JOB_ID, :T, :S
  DO
  BEGIN
    -- По идее надо пересчитать цифры с учетом новых данных хотя бы основных настройках

    INSERT INTO TARIFF_DATA
    (PARENT_ID, PERSON_ID, JOB_ID, ROW_INDEX, VAL)
    VALUES (:OBJ_ID, :V$OBJ_ID, :V$JOB_ID, :T, :S);
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE TARIFF_CORR_SEL (
    I$RANGE_ID BIGINT,
    I$DATE DATE,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$OU_ID BIGINT;
DECLARE VARIABLE V$Y INTEGER;
DECLARE VARIABLE V$YEAR_DATE DATE;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$PERSON_ID BIGINT;
DECLARE VARIABLE VN FLOAT;
DECLARE VARIABLE V$TERMS BIGINT;
DECLARE VARIABLE S VARCHAR(1000);
DECLARE VARIABLE S2 VARCHAR(1000);
DECLARE VARIABLE V$Q1 BIGINT;
DECLARE VARIABLE V$Q2 BIGINT;
begin

  SELECT FIRST 1 L2.OBJ_ID, LV.COST, CAST(LV.TAG AS DATE)
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$OU_ID, :V$Y, :V$YEAR_DATE;

  IF(I$DATE IS NULL) THEN I$DATE = CURRENT_DATE;
  IF(I$RANGE_ID > 0 AND I$DATE < DATEADD(-10 DAY TO V$YEAR_DATE)) THEN EXCEPTION DATA_ERROR 'Тарификационный список можно добавлять с датой не ранее начала текущего учебного года';

  -- Выбираем список должностей по персонам
  TAG_NAME = 'items::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L15.OBJ_ID, L14.OBJ_ID, V71.VAL, V587.LISTVAL_ID, COALESCE(V3543.SVAL, V66.SVAL), 0, LV58.SORT_ORDER, C.CAPTION
    FROM LINKS L14
    JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
    JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0 AND V73.VAL <= :I$DATE
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
    JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
    JOIN VALL V58 ON V58.OBJ_ID = LP13.PARENT_ID AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0    -- должность по списку
    JOIN LISTVALS LV58 ON LV58.LISTVAL_ID = V58.LISTVAL_ID
    JOIN VALS V66 ON V66.OBJ_ID = LP13.PARENT_ID AND V66.PARAM_ID = 66 AND V66.IS_DEL = 0    -- должность текст
    LEFT JOIN VALS V3543 ON V3543.OBJ_ID = L15.OBJ_ID AND V3543.PARAM_ID = 3543 AND V3543.IS_DEL = 0 -- должность в трудовой
    JOIN VALF V71 ON V71.OBJ_ID = L15.OBJ_ID AND V71.PARAM_ID = 71 AND V71.IS_DEL = 0        -- кол-во ставок
    JOIN VALL V587 ON V587.OBJ_ID = L15.OBJ_ID AND V587.PARAM_ID = 587 AND V587.IS_DEL = 0   -- условия приема на должность
    LEFT JOIN OBJECT_CAPTION_GET(L14.OBJ_ID) C ON 1 = 1
    WHERE L14.PARENT_TYPE_ID IN (2, 211, 84) AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL AND (V74.VAL IS NULL OR V74.VAL >= :I$DATE)
    AND (
      :I$RANGE_ID = 0 -- все
      OR (:I$RANGE_ID = 1 AND (LV58.TAG IN ('R1', 'R2', 'R3') OR LV58."FILTER" IN ('R1', 'R2', 'R3')))  -- руководители
      OR (:I$RANGE_ID = 2 AND (LV58.TAG IN ('U', 'V', 'P', 'S', 'C', 'W') OR LV58."FILTER" IN ('U', 'V', 'P', 'S', 'C', 'W')))  -- рабочие и служащие ???
      OR (:I$RANGE_ID = 3 AND (LV58.TAG IN ('Z') OR LV58."FILTER" IN ('Z')))  -- прочие ?!!
    )
    ORDER BY 6, 7, 8 -- временно
    INTO :V$OBJ_ID, :V$PERSON_ID, :VN, :V$TERMS, :S2, :V$Q1, :V$Q2, :S -- последние три поля только для сортировки
  DO
  BEGIN
    TAG_NAME = 'items:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'items:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'items:r:person_id';
    VAL = V$PERSON_ID;
    SUSPEND;
    TAG_NAME = 'items:r:name';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'items:r:job_name';
    VAL = S2;
    SUSPEND;
    TAG_NAME = 'items:r:rate';
    VAL = CAST(VN AS NUMERIC (18, 2));
    SUSPEND;
  END

  -- Если указан range = -1, то выбираем не персон, а должности
  -- но только из числа действующих на текущую дату - а не указанную в запросе дату
  IF(I$RANGE_ID = -1) THEN
  FOR
    SELECT L13.OBJ_ID, V62.VAL, V66.SVAL, LV58.SORT_ORDER
    FROM LINKS L13
    JOIN VALL V58 ON V58.OBJ_ID = L13.OBJ_ID AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0    -- должность по списку
    JOIN LISTVALS LV58 ON LV58.LISTVAL_ID = V58.LISTVAL_ID
    JOIN VALS V66 ON V66.OBJ_ID = L13.OBJ_ID AND V66.PARAM_ID = 66 AND V66.IS_DEL = 0    -- должность текст
    JOIN VALF V62 ON V62.OBJ_ID = L13.OBJ_ID AND V62.PARAM_ID = 62 AND V62.IS_DEL = 0    -- кол-во ставок
    WHERE L13.PARENT_TYPE_ID IN (2, 211) AND L13.OBJ_TYPE_ID = 13 AND L13.DATE_DEL IS NULL
    ORDER BY 3
    INTO :V$OBJ_ID, :VN, :S2, :V$Q1
  DO
  BEGIN
    TAG_NAME = 'items:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'items:r:job_id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'items:r:job_name';
    VAL = S2;
    SUSPEND;
    TAG_NAME = 'items:r:rate';
    VAL = CAST(VN AS NUMERIC (18, 2));
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE TARIFF_DELETE (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
AS
DECLARE VARIABLE V$LINK_ID BIGINT;
DECLARE VARIABLE V$STATUS BIGINT;
begin

  SELECT FIRST 1 L532.LINK_ID, V3573.LISTVAL_ID
  FROM LINKS L532
  JOIN VALL V3573 ON V3573.OBJ_ID = L532.OBJ_ID AND V3573.PARAM_ID = 3573 AND V3573.IS_DEL = 0
  WHERE L532.PARENT_TYPE_ID = 2 AND L532.OBJ_TYPE_ID = 532 AND L532.OBJ_ID = :I$OBJ_ID AND L532.DATE_DEL IS NULL
  INTO :V$LINK_ID, :V$STATUS;

  IF(V$STATUS IS NULL) THEN EXCEPTION DATA_ERROR 'Тарификационный список не найден или был удален';
  IF(V$STATUS <> 11716) THEN EXCEPTION DATA_ERROR 'Удаление тарификационного списка допускается только в статусе проекта';

  UPDATE LINKS
  SET DATE_DEL = CURRENT_TIMESTAMP
  WHERE LINK_ID = :V$LINK_ID;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE TARIFF_FILL (
    I$PARENT_ID BIGINT NOT NULL,
    I$JOB_ID BIGINT NOT NULL,
    I$PERSON_ID BIGINT,
    I$INI_VAL VARCHAR(4000) NOT NULL,
    I$ROW_INDEX BIGINT NOT NULL)
AS
DECLARE VARIABLE V$DATE DATE;
DECLARE VARIABLE VN FLOAT;
DECLARE VARIABLE V VARCHAR(400);
DECLARE VARIABLE V$TERMS BIGINT;
DECLARE VARIABLE V$TAG VARCHAR(10);
DECLARE VARIABLE V$JG BIGINT;
DECLARE VARIABLE V$JT BIGINT;
DECLARE VARIABLE V$HOURS FLOAT;
DECLARE VARIABLE K_EDU FLOAT;
DECLARE VARIABLE K_MNG FLOAT;
DECLARE VARIABLE K_EXP FLOAT;
DECLARE VARIABLE K14 FLOAT;
DECLARE VARIABLE K15 FLOAT;
DECLARE VARIABLE K16 FLOAT;
DECLARE VARIABLE K30 FLOAT;
DECLARE VARIABLE K31 FLOAT;
DECLARE VARIABLE P INTEGER;
DECLARE VARIABLE IDX INTEGER;
DECLARE VARIABLE S2 VARCHAR(4000);
DECLARE VARIABLE V$RATE_BASE FLOAT;
DECLARE VARIABLE V$RATE_MNGT FLOAT;
DECLARE VARIABLE V$RATE_ROOM FLOAT;
DECLARE VARIABLE V$RATE_CLASS FLOAT;
DECLARE VARIABLE V$JOB_LISTVAL_ID BIGINT;
begin
  SELECT D FROM VAL_GET(:I$PARENT_ID, 3571) WHERE IS_EXISTS = 1 INTO :V$DATE;
  SELECT F FROM VAL_GET(:I$PARENT_ID, 3575) WHERE IS_EXISTS = 1 INTO :V$RATE_MNGT;
  SELECT F FROM VAL_GET(:I$PARENT_ID, 3576) WHERE IS_EXISTS = 1 INTO :V$RATE_BASE;
  SELECT F FROM VAL_GET(:I$PARENT_ID, 3577) WHERE IS_EXISTS = 1 INTO :V$RATE_CLASS;
  SELECT F FROM VAL_GET(:I$PARENT_ID, 3578) WHERE IS_EXISTS = 1 INTO :V$RATE_ROOM;
  SELECT I FROM VAL_GET(:I$JOB_ID, 587) WHERE IS_EXISTS = 1 INTO :V$TERMS;                        -- Условия приёма на должность
  SELECT VAL FROM VALF WHERE OBJ_ID = :I$JOB_ID AND PARAM_ID IN (62, 71) AND IS_DEL = 0 INTO :VN; -- число ставок

  -- Найдем группу и подгруппу должности - руководитель, специалист...
  SELECT FIRST 1 V58.LISTVAL_ID, COALESCE(LV.TAG, LV."FILTER"), V63.LISTVAL_ID, V64.LISTVAL_ID
  FROM LINKS L15
  JOIN VALL V63 ON V63.OBJ_ID = L15.PARENT_ID AND V63.PARAM_ID = 63 AND V63.IS_DEL = 0
  JOIN VALL V64 ON V64.OBJ_ID = L15.PARENT_ID AND V64.PARAM_ID = 64 AND V64.IS_DEL = 0
  JOIN VALL V58 ON V58.OBJ_ID = L15.PARENT_ID AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V58.LISTVAL_ID AND LV.LIST_ID IN (21, 369, 370) AND LV.IS_DEL = 0
  WHERE L15.OBJ_ID = :I$JOB_ID AND L15.PARENT_TYPE_ID = 13 AND L15.DATE_DEL IS NULL
  INTO :V$JOB_LISTVAL_ID, :V$TAG, :V$JG, :V$JT;

  -- для строк с работником на должности
  IF (I$PERSON_ID IS NOT NULL) THEN
  BEGIN
    -- найдем коэффициент базового образования
    SELECT FIRST 1 IIF(V279.LISTVAL_ID <> 626, 1.6, LV.COST) -- зададим K = 1.6 для ученой степени, иначе берем коэффициент из справочника
    FROM LINKS L33
    JOIN VALD V290 ON V290.OBJ_ID = L33.OBJ_ID AND V290.PARAM_ID = 290 AND V290.IS_DEL = 0 AND V290.VAL <= :V$DATE
    JOIN VALL V284 ON V284.OBJ_ID = L33.OBJ_ID AND V284.PARAM_ID = 284 AND V284.IS_DEL = 0 AND V284.LISTVAL_ID IN (620, 622, 623, 625, 3031, 3032, 14146, 5256)
    LEFT JOIN VALL V279 ON V279.OBJ_ID = L33.PARENT_ID AND V279.PARAM_ID = 279 AND V279.IS_DEL = 0
    JOIN LISTVALS LV ON LV.LIST_ID = 379 AND LV.TAG CONTAINING V284.LISTVAL_ID  -- список Тарификация. Коэффициент уровня образования
      AND (LV.PARENT_ID = 18645 AND :V$JG = 55) OR -- руководители
          (LV.PARENT_ID = 18644 AND :V$JG = 97) OR -- специалисты
          (LV.PARENT_ID = 18643 AND :V$JG = 1310)  -- служащие
    WHERE L33.PARENT_ID = :I$PERSON_ID AND L33.OBJ_TYPE_ID = 33 AND L33.DATE_DEL IS NULL
    ORDER BY V290.VAL DESC
    INTO :K_EDU;
    -- если нет повышающего коэффициента, то задаем К = 1
    K_EDU = COALESCE(K_EDU, 1);

    -- найдем коэффициент по стажу. Стаж работы, в днях, пересчитываем в годы (/ 360). Для педагогических должностей берем стаж педагогический, для остальных - по должности. Для руководителей коэффициент по стажу = 0.
    P = NULL;
    SELECT SUM(V.DAYS360_COUNT) / 360
    FROM LINKS L85
    JOIN VALL V465 ON V465.OBJ_ID = L85.OBJ_ID AND V465.PARAM_ID = 465 AND V465.IS_DEL = 0 AND V465.LISTVAL_ID = IIF(:V$TAG = 'U', 942, 1978)
    JOIN VALD V466 ON V466.OBJ_ID = L85.OBJ_ID AND V466.PARAM_ID = 466 AND V466.IS_DEL = 0
    LEFT JOIN VALD V467 ON V467.OBJ_ID = L85.OBJ_ID AND V467.PARAM_ID = 467 AND V467.IS_DEL = 0
    LEFT JOIN GET_DAYS360_COUNT(V466.VAL, COALESCE(V467.VAL, :V$DATE)) V ON 1 = 1
    WHERE L85.PARENT_ID = :I$PERSON_ID AND L85.OBJ_TYPE_ID = 85 AND L85.DATE_DEL IS NULL
    INTO :P;

    K_EXP = NULL;
    IF (COALESCE(P, 0) >= 2) THEN -- Для стажа < 2лет очень сложное определение коэффициента. Надо дать пользователю возможность задать самим. Может дать на выбор 0.05, 0.33 или 0.15
    BEGIN
      SELECT FIRST 1 LV.COST
      FROM LISTVALS_LIST(380, 'RU') LV
      WHERE ((LV.PARENT_ID = 18648 AND :V$JG = 55) OR (LV.PARENT_ID = 18647 AND :V$JG = 97) OR (LV.PARENT_ID = 18646 AND :V$JG = 1310))
        AND (:P >= CAST(LV.TAG AS INTEGER))
      ORDER BY CAST(LV.TAG AS INTEGER) DESC
      INTO :K_EXP;
    END

    -- найдем коэффициент уровня управления
    K_MNG = NULL;
    SELECT FIRST 1 LV.COST FROM LISTVALS_LIST(382, 'RU') LV WHERE LV.TAG = :V$JT INTO :K_MNG;

    -- найдем коэффициент квалификации
    K14 = NULL;
    SELECT FIRST 1 LV.COST
    FROM LINKS L34
    JOIN VALD V544 ON V544.OBJ_ID = L34.OBJ_ID AND V544.PARAM_ID = 544 AND V544.IS_DEL = 0                                          -- дата комиссии
    JOIN VALL V545 ON V545.OBJ_ID = L34.OBJ_ID AND V545.PARAM_ID = 545 AND V545.IS_DEL = 0 AND V545.LISTVAL_ID IN (1208, 1209, 1210)-- решение комиссии
    JOIN VALL V2347 ON V2347.OBJ_ID = L34.OBJ_ID AND V2347.PARAM_ID = 2347 AND V2347.IS_DEL = 0                                     -- должность
      -- соответствие должности из справочника должностей с должностью из справочника должности для аттестации.
      AND ((:V$JOB_LISTVAL_ID IN (18507,128) AND V2347.LISTVAL_ID = 11101) OR
        (:V$JOB_LISTVAL_ID IN (18517,152) AND V2347.LISTVAL_ID = 11104) OR
        (:V$JOB_LISTVAL_ID IN (18518, 16971,151) AND V2347.LISTVAL_ID = 11102) OR
        (:V$JOB_LISTVAL_ID IN (18515,16972,150,1293) AND V2347.LISTVAL_ID = 11103) OR
        (:V$JOB_LISTVAL_ID IN (18513,17083,132) AND V2347.LISTVAL_ID = 11105) OR
        (:V$JOB_LISTVAL_ID IN (18544,17117,1281) AND V2347.LISTVAL_ID = 11106) OR
        (:V$JOB_LISTVAL_ID IN (18521,17174,130) AND V2347.LISTVAL_ID = 11107) OR
        (:V$JOB_LISTVAL_ID IN (18516,17228,133) AND V2347.LISTVAL_ID = 11108) OR
        (:V$JOB_LISTVAL_ID IN (18512,17291,140) AND V2347.LISTVAL_ID = 11109) OR
        (:V$JOB_LISTVAL_ID IN (18511,17632,143) AND V2347.LISTVAL_ID = 11110) OR
        (:V$JOB_LISTVAL_ID IN (18509,12832) AND V2347.LISTVAL_ID = 11111) OR
        (:V$JOB_LISTVAL_ID IN (18503,17633,144) AND V2347.LISTVAL_ID = 11112) OR
        (:V$JOB_LISTVAL_ID IN (18506,17634,145) AND V2347.LISTVAL_ID = 11113) OR
        (:V$JOB_LISTVAL_ID IN (18519,369) AND V2347.LISTVAL_ID = 11115) OR
        (:V$JOB_LISTVAL_ID IN (18514,17897,149) AND V2347.LISTVAL_ID = 11116) OR
        (:V$JOB_LISTVAL_ID IN (18504,1251) AND V2347.LISTVAL_ID = 11117) OR
        (:V$JOB_LISTVAL_ID IN (18510,1252) AND V2347.LISTVAL_ID = 11118) OR
        (:V$JOB_LISTVAL_ID IN (18546,127) AND V2347.LISTVAL_ID = 11119) OR
        (:V$JOB_LISTVAL_ID IN (18547) AND V2347.LISTVAL_ID = 11120) OR
        (:V$JOB_LISTVAL_ID IN (18548,1255) AND V2347.LISTVAL_ID = 11121) OR
        (:V$JOB_LISTVAL_ID IN (18549) AND V2347.LISTVAL_ID = 11122) OR
        (:V$JOB_LISTVAL_ID IN (18550) AND V2347.LISTVAL_ID = 11123) OR
        (:V$JOB_LISTVAL_ID IN (18520,1256) AND V2347.LISTVAL_ID = 11124) OR
        (:V$JOB_LISTVAL_ID IN (18508,1291) AND V2347.LISTVAL_ID = 11125) OR
        (:V$JOB_LISTVAL_ID IN (18501) AND V2347.LISTVAL_ID = 11126) OR
        (:V$JOB_LISTVAL_ID IN (18505,18172,120) AND V2347.LISTVAL_ID = 11127) OR
        (:V$JOB_LISTVAL_ID IN (18551,18174,119) AND V2347.LISTVAL_ID = 11128) OR
        (:V$JOB_LISTVAL_ID IN (18497,64) AND V2347.LISTVAL_ID = 11130) OR
        (:V$JOB_LISTVAL_ID IN (18530,66) AND V2347.LISTVAL_ID = 11131) OR
        (:V$JOB_LISTVAL_ID IN (18498) AND V2347.LISTVAL_ID = 11133) OR
        (:V$JOB_LISTVAL_ID IN (18499) AND V2347.LISTVAL_ID = 11134) OR
        (:V$JOB_LISTVAL_ID IN (18534) AND V2347.LISTVAL_ID = 11135) OR
        (:V$JOB_LISTVAL_ID IN (18500,94) AND V2347.LISTVAL_ID = 11136))
    JOIN LISTVALS_LIST(381) LV ON LV.TAG = V545.LISTVAL_ID
    WHERE L34.PARENT_ID = :I$PERSON_ID AND L34.OBJ_TYPE_ID = 34 AND L34.DATE_DEL IS NULL
    ORDER BY V544.VAL DESC
    INTO :K14;

    -- Ученая степень: кандидат/доктор
    K15 = NULL;
    SELECT LV.COST
    FROM VALL V279
    JOIN LISTVALS_LIST(381) LV ON LV.TAG = V279.LISTVAL_ID
    WHERE V279.OBJ_ID = :I$PERSON_ID AND V279.PARAM_ID = 279 AND V279.IS_DEL = 0
    INTO K15;

    -- Звание: заслуженный учитель, ...
    K16 = NULL;
    SELECT LV.COST
    FROM VALL V280
    JOIN LISTVALS_LIST(381) LV ON LV.TAG = V280.LISTVAL_ID
    WHERE V280.OBJ_ID = :I$PERSON_ID AND V280.PARAM_ID = 280 AND V280.IS_DEL = 0
    INTO K16;

    -- Из учебной нагрузки. Количество классных руководств и сумма доплаты
    P = NULL;
    SELECT COUNT(*)
    FROM EDULOAD_DATA D
    JOIN LINKS L531 ON L531.OBJ_ID = D.PARENT_ID AND L531.PARENT_TYPE_ID = 527 AND L531.DATE_DEL IS NULL
    JOIN VALL V3567 ON V3567.OBJ_ID = L531.OBJ_ID AND V3567.PARAM_ID = 3567 AND V3567.IS_DEL = 0
    JOIN LISTVALS LV3567 ON LV3567.LISTVAL_ID = V3567.LISTVAL_ID AND LV3567.LIST_ID = 29 AND LV3567.IS_DEL = 0 AND LV3567.COST = EXTRACT(YEAR FROM :V$DATE)
    JOIN LISTVALS LV3568 ON LV3568.LISTVAL_ID = V3567.LISTVAL_ID AND LV3568.LIST_ID = 29 AND LV3568.IS_DEL = 0 AND LV3568.COST = 11715 -- действуюющий
    WHERE D.PERSON_ID = :I$PERSON_ID AND D.REF_TYPE_ID = 9 AND D.DATE_DEL IS NULL
    INTO :P;
    K30 = P * V$RATE_CLASS;

    -- Из учебной нагрузки. Количество кабинетов и сумма доплаты
    P = NULL;
    SELECT COUNT(*)
    FROM EDULOAD_DATA D
    JOIN LINKS L531 ON L531.OBJ_ID = D.PARENT_ID AND L531.PARENT_TYPE_ID = 527 AND L531.DATE_DEL IS NULL
    JOIN VALL V3567 ON V3567.OBJ_ID = L531.OBJ_ID AND V3567.PARAM_ID = 3567 AND V3567.IS_DEL = 0
    JOIN LISTVALS LV3567 ON LV3567.LISTVAL_ID = V3567.LISTVAL_ID AND LV3567.LIST_ID = 29 AND LV3567.IS_DEL = 0 AND LV3567.COST = EXTRACT(YEAR FROM :V$DATE)
    JOIN LISTVALS LV3568 ON LV3568.LISTVAL_ID = V3567.LISTVAL_ID AND LV3568.LIST_ID = 29 AND LV3568.IS_DEL = 0 AND LV3568.COST = 11715 -- действуюющий
    WHERE D.PERSON_ID = :I$PERSON_ID AND D.REF_TYPE_ID = 61 AND D.DATE_DEL IS NULL
    INTO :P;
    K31 = P * V$RATE_ROOM;

    -- Из учебной нагрузки. Количество часов нагрузки
    V$HOURS = NULL;
    SELECT SUM(D.LOAD_VAL)
    FROM EDULOAD_DATA D
    JOIN LINKS L531 ON L531.OBJ_ID = D.PARENT_ID AND L531.PARENT_TYPE_ID = 527 AND L531.DATE_DEL IS NULL
    JOIN VALL V3567 ON V3567.OBJ_ID = L531.OBJ_ID AND V3567.PARAM_ID = 3567 AND V3567.IS_DEL = 0
    JOIN LISTVALS LV3567 ON LV3567.LISTVAL_ID = V3567.LISTVAL_ID AND LV3567.LIST_ID = 29 AND LV3567.IS_DEL = 0 AND LV3567.COST = EXTRACT(YEAR FROM :V$DATE)
    JOIN LISTVALS LV3568 ON LV3568.LISTVAL_ID = V3567.LISTVAL_ID AND LV3568.LIST_ID = 29 AND LV3568.IS_DEL = 0 AND LV3568.COST = 11715 -- действуюющий
    WHERE D.PERSON_ID = :I$PERSON_ID AND D.REF_TYPE_ID = 51 AND D.DATE_DEL IS NULL
    INTO :V$HOURS;
  END

  -- Заполняем поля и коэффициенты в соответствии с формулами начиная со столбца 9
  -- Количество ставок 22, 23 столбцы заполняем по статусу сотрудника на дату, для вакантных дожностей - заполняем основную ставку
  S2 = '';
  IDX = 9;
  WHILE(CHAR_LENGTH(I$INI_VAL) > 0) DO
  BEGIN
    P = POSITION(';' IN I$INI_VAL);
    IF(P <= 0) THEN P = CHAR_LENGTH(I$INI_VAL) + 1;
    -- Будем брать за снову значения из предыдущего списка только для вакантных должностей
    V = IIF(I$PERSON_ID IS NULL, SUBSTRING(I$INI_VAL FROM 1 FOR P - 1), '');
    I$INI_VAL = SUBSTRING(I$INI_VAL FROM P + 1);
    IF (IDX = 9) THEN V = CAST(V$RATE_BASE AS NUMERIC(18, 2));                                                          -- Базовая единица (входный параметр)
    ELSE IF(IDX = 10 AND K_EDU IS NOT NULL) THEN V = CAST(K_EDU AS NUMERIC(18, 2));                                     -- Коэффициент уровня образования
    ELSE IF(IDX = 11 AND K_EDU IS NOT NULL) THEN V = CAST(V$RATE_BASE * K_EDU AS NUMERIC(18, 2));                       -- Базовый оклад
    ELSE IF(IDX = 12 AND K_EXP IS NOT NULL) THEN V = CAST(K_EXP AS NUMERIC(18, 2));                                     -- Коэффициент стажа работы
    ELSE IF(IDX = 14 AND K14 IS NOT NULL) THEN V = CAST(K14 AS NUMERIC(18, 2));                                         -- Коэффициент квалификации, уровня квалификации
    ELSE IF(IDX = 15 AND K15 IS NOT NULL) THEN V = CAST(K15 AS NUMERIC(18, 2));                                         -- Коэффициент квалификации, Ученая степень
    ELSE IF(IDX = 16 AND K16 IS NOT NULL) THEN V = CAST(K16 AS NUMERIC(18, 2));                                         -- Коэффициент квалификации, Звание, Награды
    ELSE IF(IDX = 17 AND V$JG = 55) THEN V = CAST(V$RATE_MNGT AS NUMERIC(18, 2));                                       -- Коэффициент масштаба управления (входный параметр) только для руководителей 1,2,3 уровня
    ELSE IF(IDX = 18 AND K_MNG IS NOT NULL) THEN V = CAST(K_MNG AS NUMERIC(18, 2));                                     -- Коэффициент уровня управления
    ELSE IF(IDX = 22) THEN V = IIF(V$TERMS IS NULL OR V$TERMS IN (207, 1720, 209), CAST(VN AS NUMERIC(18, 2)), '');     -- Кол-во ставок (штат)
    ELSE IF(IDX = 23 AND V$TERMS IS NOT NULL) THEN V = IIF(V$TERMS IN (207, 1720, 209), '', CAST(VN AS NUMERIC(18, 2)));-- Кол-во ставок (совместитель)
    ELSE IF(IDX = 24 AND V$TAG = 'P' AND V$HOURS IS NOT NULL) THEN V = CAST(V$HOURS AS NUMERIC(18, 2));                 -- Число часов в неделю, только для педагогических работников: V$TAG = 'P'
    ELSE IF(IDX = 30 AND K30 IS NOT NULL) THEN V = CAST(K30 AS NUMERIC(18, 2));                                         -- Размер доплаты за классное руководство
    ELSE IF(IDX = 31 AND K31 IS NOT NULL) THEN V = CAST(K31 AS NUMERIC(18, 2));                                         -- Размер доплаты за кабинеты
    ELSE IF(IDX <> 13 AND IDX <> 32 AND IDX <> 33) THEN V = '';                                                         -- копируем значения от предыдущей записи
    IF(S2 <> '') THEN S2 = S2 || ';';
    S2 = S2 || V;
    IDX = IDX + 1;
  END

  INSERT INTO TARIFF_DATA
  (PARENT_ID, PERSON_ID, JOB_ID, ROW_INDEX, VAL)
  VALUES (:I$PARENT_ID, :I$PERSON_ID, :I$JOB_ID, :I$ROW_INDEX, :S2);
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE TARIFF_GET (
    I$OBJ_ID BIGINT,
    I$HEADERS INTEGER,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$OU_ID BIGINT;
DECLARE VARIABLE V$DATE DATE;
DECLARE VARIABLE V$TYPE_ID BIGINT;
DECLARE VARIABLE V$STATE_ID BIGINT;
DECLARE VARIABLE V1 FLOAT;
DECLARE VARIABLE V2 FLOAT;
DECLARE VARIABLE V3 FLOAT;
DECLARE VARIABLE V4 FLOAT;
DECLARE VARIABLE V5 FLOAT;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$PERSON_ID BIGINT;
DECLARE VARIABLE V$JOB_ID BIGINT;
DECLARE VARIABLE S VARCHAR(1000);
DECLARE VARIABLE S2 VARCHAR(1000);
DECLARE VARIABLE S3 VARCHAR(4000);
DECLARE VARIABLE V$JT VARCHAR(10);
DECLARE VARIABLE V$LISTVAL_ID BIGINT;
DECLARE VARIABLE V$JOB_LISTVAL_ID BIGINT;
begin
  -- Отрицательное значение в I$OBJ_ID означает, что надо ХП дергается для печати. Необходимо вывести полные наменования текстовых значений
  SELECT FIRST 1 L532.PARENT_ID, V3571.VAL, V3572.LISTVAL_ID, V3573.LISTVAL_ID, V3574.VAL, V3575.VAL, V3576.VAL, V3577.VAL, V3578.VAL, V3579.VAL
  FROM LINKS L532
  JOIN VALD V3571 ON V3571.OBJ_ID = L532.OBJ_ID AND V3571.PARAM_ID = 3571 AND V3571.IS_DEL = 0
  JOIN VALL V3572 ON V3572.OBJ_ID = L532.OBJ_ID AND V3572.PARAM_ID = 3572 AND V3572.IS_DEL = 0
  JOIN VALL V3573 ON V3573.OBJ_ID = L532.OBJ_ID AND V3573.PARAM_ID = 3573 AND V3573.IS_DEL = 0
  JOIN VALS V3574 ON V3574.OBJ_ID = L532.OBJ_ID AND V3574.PARAM_ID = 3574 AND V3574.IS_DEL = 0
  LEFT JOIN VALF V3575 ON V3575.OBJ_ID = L532.OBJ_ID AND V3575.PARAM_ID = 3575 AND V3575.IS_DEL = 0
  LEFT JOIN VALF V3576 ON V3576.OBJ_ID = L532.OBJ_ID AND V3576.PARAM_ID = 3576 AND V3576.IS_DEL = 0
  LEFT JOIN VALF V3577 ON V3577.OBJ_ID = L532.OBJ_ID AND V3577.PARAM_ID = 3577 AND V3577.IS_DEL = 0
  LEFT JOIN VALF V3578 ON V3578.OBJ_ID = L532.OBJ_ID AND V3578.PARAM_ID = 3578 AND V3578.IS_DEL = 0
  LEFT JOIN VALF V3579 ON V3579.OBJ_ID = L532.OBJ_ID AND V3579.PARAM_ID = 3579 AND V3579.IS_DEL = 0
  WHERE L532.OBJ_ID = ABS(:I$OBJ_ID) AND L532.OBJ_TYPE_ID = 532 AND L532.PARENT_TYPE_ID = 2 AND L532.DATE_DEL IS NULL
  ORDER BY 1 DESC
  INTO :V$OU_ID, :V$DATE, :V$TYPE_ID, :V$STATE_ID, :S, :V1, :V2, :V3, :V4, :V5;

  IF(I$OBJ_ID IS NOT NULL AND V$DATE IS NULL) THEN EXCEPTION DATA_ERROR 'Список не найден или был удален';

  -- Если OBJ_ID не указан - подтягиваем настройки из последней ведомости
  IF(I$OBJ_ID IS NULL) THEN
  BEGIN
    I$HEADERS = 1;
    V$DATE = CURRENT_DATE;

    SELECT FIRST 1 V3575.VAL, V3576.VAL, V3577.VAL, V3578.VAL, V3579.VAL
    FROM LINKS L532
    JOIN VALD V3571 ON V3571.OBJ_ID = L532.OBJ_ID AND V3571.PARAM_ID = 3571 AND V3571.IS_DEL = 0
    LEFT JOIN VALF V3575 ON V3575.OBJ_ID = L532.OBJ_ID AND V3575.PARAM_ID = 3575 AND V3575.IS_DEL = 0
    LEFT JOIN VALF V3576 ON V3576.OBJ_ID = L532.OBJ_ID AND V3576.PARAM_ID = 3576 AND V3576.IS_DEL = 0
    LEFT JOIN VALF V3577 ON V3577.OBJ_ID = L532.OBJ_ID AND V3577.PARAM_ID = 3577 AND V3577.IS_DEL = 0
    LEFT JOIN VALF V3578 ON V3578.OBJ_ID = L532.OBJ_ID AND V3578.PARAM_ID = 3578 AND V3578.IS_DEL = 0
    LEFT JOIN VALF V3579 ON V3579.OBJ_ID = L532.OBJ_ID AND V3579.PARAM_ID = 3579 AND V3579.IS_DEL = 0
    WHERE L532.PARENT_TYPE_ID = 2 AND L532.OBJ_TYPE_ID = 532 AND L532.DATE_DEL IS NULL
    ORDER BY V3571.VAL DESC
    INTO :V1, :V2, :V3, :V4, :V5;
  END

  TAG_NAME = 'db_level';
  VAL = (SELECT KEY_VAL FROM KEYS WHERE KEY_CODE = 'LEVEL');
  SUSPEND;

  TAG_NAME = 'id';
  VAL = ABS(I$OBJ_ID);
  SUSPEND;

  TAG_NAME = 'date';
  VAL = (SELECT VAL FROM DATE2ISO(:V$DATE, 0));
  SUSPEND;

  TAG_NAME = 'type_id';
  VAL = V$TYPE_ID;
  SUSPEND;

  TAG_NAME = 'state_id';
  VAL = V$STATE_ID;
  SUSPEND;

  TAG_NAME = 'name';
  VAL = S;
  SUSPEND;

  TAG_NAME = 'rate_mgmt';
  VAL = CAST(V1 AS NUMERIC(18, 2));
  SUSPEND;

  TAG_NAME = 'rate_base';
  VAL = CAST(V2 AS NUMERIC(18, 2));
  SUSPEND;

  TAG_NAME = 'rate_class';
  VAL = CAST(V3 AS NUMERIC(18, 2));
  SUSPEND;

  TAG_NAME = 'rate_room';
  VAL = CAST(V4 AS NUMERIC(18, 2));
  SUSPEND;

  TAG_NAME = 'rate_check';
  VAL = CAST(V5 AS NUMERIC(18, 2));
  SUSPEND;

  IF(I$HEADERS IS NOT NULL) THEN EXIT;

  TAG_NAME = 'rows::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    -- JOB_ID будет или должность или назначение на должность персоны
    SELECT D.OBJ_ID, D.PERSON_ID, D.JOB_ID, IIF(D.PERSON_ID IS NULL, 'Вакантная ставка', C.CAPTION), COALESCE(VJ.VAL, V.VAL), D.VAL
    FROM TARIFF_DATA D
    LEFT JOIN OBJECT_CAPTION_GET(D.PERSON_ID) C ON 1 = 1
    LEFT JOIN VALS VJ ON VJ.OBJ_ID = D.JOB_ID AND VJ.PARAM_ID = 3543 AND VJ.IS_DEL = 0
    LEFT JOIN LINKS L15 ON L15.OBJ_ID = D.JOB_ID AND L15.PARENT_TYPE_ID = 13 AND L15.DATE_DEL IS NULL
    LEFT JOIN LINKS L13 ON L13.OBJ_ID = D.JOB_ID AND L13.PARENT_TYPE_ID IN (2, 211) AND L13.DATE_DEL IS NULL
    LEFT JOIN VALS V ON V.OBJ_ID = L13.OBJ_ID AND V.PARAM_ID = 66 AND V.IS_DEL = 0
    WHERE D.PARENT_ID = ABS(:I$OBJ_ID) AND D.DATE_DEL IS NULL
    ORDER BY D.ROW_INDEX
    INTO :V$OBJ_ID, :V$PERSON_ID, :V$JOB_ID, :S, :S2, :S3
  DO
  BEGIN
    TAG_NAME = 'rows:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'rows:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'rows:r:person_id';
    VAL = V$PERSON_ID;
    SUSPEND;
    TAG_NAME = 'rows:r:job_id';
    VAL = V$JOB_ID;
    SUSPEND;
    TAG_NAME = 'rows:r:person_name';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'rows:r:job_name';
    VAL = S2;
    SUSPEND;
    TAG_NAME = 'rows:r:job_type';
    VAL = NULL;
    IF(V$PERSON_ID IS NULL) THEN
    BEGIN
      SELECT FIRST 1 IIF(LV.LIST_ID = 21, LV.TAG, LV."FILTER"), V63.LISTVAL_ID, V64.LISTVAL_ID
      FROM OBJECTS L13
      JOIN VALL V58 ON V58.OBJ_ID = L13.OBJ_ID AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0
      JOIN LISTVALS LV ON LV.LISTVAL_ID = V58.LISTVAL_ID
      JOIN VALL V63 ON V63.OBJ_ID = L13.OBJ_ID AND V63.PARAM_ID = 63 AND V63.IS_DEL = 0
      JOIN VALL V64 ON V64.OBJ_ID = L13.OBJ_ID AND V64.PARAM_ID = 64 AND V64.IS_DEL = 0
      WHERE L13.OBJ_ID = :V$JOB_ID
      INTO :VAL, :V$TYPE_ID, :V$LISTVAL_ID;
    END
    ELSE
    BEGIN
      SELECT FIRST 1 IIF(LV.LIST_ID = 21, LV.TAG, LV."FILTER"), V63.LISTVAL_ID, V64.LISTVAL_ID, V58.LISTVAL_ID
      FROM LINKS LP13
      JOIN VALL V58 ON V58.OBJ_ID = LP13.PARENT_ID AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0
      JOIN LISTVALS LV ON LV.LISTVAL_ID = V58.LISTVAL_ID
      JOIN VALL V63 ON V63.OBJ_ID = LP13.PARENT_ID AND V63.PARAM_ID = 63 AND V63.IS_DEL = 0
      JOIN VALL V64 ON V64.OBJ_ID = LP13.PARENT_ID AND V64.PARAM_ID = 64 AND V64.IS_DEL = 0
      WHERE LP13.OBJ_ID = :V$JOB_ID AND LP13.PARENT_TYPE_ID = 13 -- DATE_DEL не проверять !
      INTO :VAL, :V$TYPE_ID, :V$LISTVAL_ID, :V$JOB_LISTVAL_ID;
    END
    -- Запоминаем код типа должности
    V$JT = VAL;
    SUSPEND;
    TAG_NAME = 'rows:r:job_group';
    SELECT VAL FROM LISTVAL_TEXT(:V$TYPE_ID) INTO :VAL;
    SUSPEND;
    TAG_NAME = 'rows:r:job_subgroup';
    SELECT VAL FROM LISTVAL_TEXT(:V$LISTVAL_ID) INTO :VAL;
    SUSPEND;
    TAG_NAME = 'rows:r:value';
    VAL = S3;
    SUSPEND;
    -- Для сотрудника выдаем столбцы 4-8 - только коды, без текстовок
    IF(V$PERSON_ID IS NOT NULL) THEN
    BEGIN
      -- Образование. Предполагаем, что не бывает понижения уровня образования по хронологии
      TAG_NAME = 'rows:r:edu_col';
      VAL = NULL;
      SELECT FIRST 1 L33.OBJ_ID, V284.LISTVAL_ID
      FROM LINKS L33
      JOIN VALD V290 ON V290.OBJ_ID = L33.OBJ_ID AND V290.PARAM_ID = 290 AND V290.IS_DEL = 0 AND V290.VAL <= :V$DATE
      JOIN VALL V284 ON V284.OBJ_ID = L33.OBJ_ID AND V284.PARAM_ID = 284 AND V284.IS_DEL = 0 AND V284.LISTVAL_ID IN (620, 622, 623, 3031, 3032, 14146, 5256)
      JOIN LISTVALS LV ON LV.LISTVAL_ID = V284.LISTVAL_ID
      WHERE L33.PARENT_ID = :V$PERSON_ID AND L33.OBJ_TYPE_ID = 33 AND L33.DATE_DEL IS NULL
      ORDER BY V290.VAL DESC
      INTO :V$OBJ_ID, :VAL;
      IF (I$OBJ_ID < 0) THEN
      BEGIN
        VAL = NULL;
        SELECT CAP.VAL
        FROM VALL V
        LEFT JOIN LISTVAL_TEXT(V.LISTVAL_ID) CAP ON 1 = 1
        WHERE V.OBJ_ID = :V$OBJ_ID AND V.PARAM_ID = 284 AND V.IS_DEL = 0
        INTO :VAL;
        IF (VAL IS NOT NULL) THEN
        BEGIN
          S = NULL;
          SELECT V.SVAL FROM VALS V WHERE V.OBJ_ID = :V$OBJ_ID AND V.PARAM_ID = 285 AND V.IS_DEL = 0 INTO :S;
          S2 = NULL;
          SELECT CAP.VAL
          FROM VALL V
          LEFT JOIN LISTVAL_TEXT(V.LISTVAL_ID) CAP ON 1 = 1
          WHERE V.OBJ_ID = :V$OBJ_ID AND V.PARAM_ID = 286 AND V.IS_DEL = 0
          INTO :S2;
          VAL = VAL || ', ' || COALESCE(S, '') || ' ' || COALESCE(S2, '');
          S = NULL;
          SELECT V.SVAL FROM VALS V WHERE V.OBJ_ID = :V$OBJ_ID AND V.PARAM_ID = 287 AND V.IS_DEL = 0 INTO :S;
          S2 = NULL;
          SELECT V.SVAL FROM VALS V WHERE V.OBJ_ID = :V$OBJ_ID AND V.PARAM_ID = 288 AND V.IS_DEL = 0 INTO :S2;
          VAL = VAL || ' ' || COALESCE(S, '') || ' №' || COALESCE(S2, '');
          S = NULL;
          SELECT V.VAL FROM VALD V WHERE V.OBJ_ID = :V$OBJ_ID AND V.PARAM_ID = 290 AND V.IS_DEL = 0 INTO :S;
          VAL = VAL || ' от ' || COALESCE(S, '');
        END
      END
      SUSPEND;
      -- Квалификационная категория
      TAG_NAME = 'rows:r:qual_col';
      V$LISTVAL_ID = NULL;
      SELECT FIRST 1 V545.LISTVAL_ID--, JOB.VAL
      FROM LINKS L34
      JOIN VALD V544 ON V544.OBJ_ID = L34.OBJ_ID AND V544.PARAM_ID = 544 AND V544.IS_DEL = 0      -- дата комиссии
      JOIN VALL V545 ON V545.OBJ_ID = L34.OBJ_ID AND V545.PARAM_ID = 545 AND V545.IS_DEL = 0 AND V545.LISTVAL_ID IN (1208, 1209, 1210) -- решение комиссии
      JOIN VALL V2347 ON V2347.OBJ_ID = L34.OBJ_ID AND V2347.PARAM_ID = 2347 AND V2347.IS_DEL = 0 -- должность
      WHERE L34.PARENT_ID = :V$PERSON_ID AND L34.OBJ_TYPE_ID = 34 AND L34.DATE_DEL IS NULL
        AND (V544.VAL IS NOT NULL AND V544.VAL < :V$DATE)
      -- соответствие должности из справочника должностей с должностью из справочника должности для аттестации.
        AND ((:V$JOB_LISTVAL_ID IN (18507,128) AND V2347.LISTVAL_ID = 11101) OR
        (:V$JOB_LISTVAL_ID IN (18517,152) AND V2347.LISTVAL_ID = 11104) OR
        (:V$JOB_LISTVAL_ID IN (18518, 16971,151) AND V2347.LISTVAL_ID = 11102) OR
        (:V$JOB_LISTVAL_ID IN (18515,16972,150,1293) AND V2347.LISTVAL_ID = 11103) OR
        (:V$JOB_LISTVAL_ID IN (18513,17083,132) AND V2347.LISTVAL_ID = 11105) OR
        (:V$JOB_LISTVAL_ID IN (18544,17117,1281) AND V2347.LISTVAL_ID = 11106) OR
        (:V$JOB_LISTVAL_ID IN (18521,17174,130) AND V2347.LISTVAL_ID = 11107) OR
        (:V$JOB_LISTVAL_ID IN (18516,17228,133) AND V2347.LISTVAL_ID = 11108) OR
        (:V$JOB_LISTVAL_ID IN (18512,17291,140) AND V2347.LISTVAL_ID = 11109) OR
        (:V$JOB_LISTVAL_ID IN (18511,17632,143) AND V2347.LISTVAL_ID = 11110) OR
        (:V$JOB_LISTVAL_ID IN (18509,12832) AND V2347.LISTVAL_ID = 11111) OR
        (:V$JOB_LISTVAL_ID IN (18503,17633,144) AND V2347.LISTVAL_ID = 11112) OR
        (:V$JOB_LISTVAL_ID IN (18506,17634,145) AND V2347.LISTVAL_ID = 11113) OR
        (:V$JOB_LISTVAL_ID IN (18519,369) AND V2347.LISTVAL_ID = 11115) OR
        (:V$JOB_LISTVAL_ID IN (18514,17897,149) AND V2347.LISTVAL_ID = 11116) OR
        (:V$JOB_LISTVAL_ID IN (18504,1251) AND V2347.LISTVAL_ID = 11117) OR
        (:V$JOB_LISTVAL_ID IN (18510,1252) AND V2347.LISTVAL_ID = 11118) OR
        (:V$JOB_LISTVAL_ID IN (18546,127) AND V2347.LISTVAL_ID = 11119) OR
        (:V$JOB_LISTVAL_ID IN (18547) AND V2347.LISTVAL_ID = 11120) OR
        (:V$JOB_LISTVAL_ID IN (18548,1255) AND V2347.LISTVAL_ID = 11121) OR
        (:V$JOB_LISTVAL_ID IN (18549) AND V2347.LISTVAL_ID = 11122) OR
        (:V$JOB_LISTVAL_ID IN (18550) AND V2347.LISTVAL_ID = 11123) OR
        (:V$JOB_LISTVAL_ID IN (18520,1256) AND V2347.LISTVAL_ID = 11124) OR
        (:V$JOB_LISTVAL_ID IN (18508,1291) AND V2347.LISTVAL_ID = 11125) OR
        (:V$JOB_LISTVAL_ID IN (18501) AND V2347.LISTVAL_ID = 11126) OR
        (:V$JOB_LISTVAL_ID IN (18505,18172,120) AND V2347.LISTVAL_ID = 11127) OR
        (:V$JOB_LISTVAL_ID IN (18551,18174,119) AND V2347.LISTVAL_ID = 11128) OR
        (:V$JOB_LISTVAL_ID IN (18497,64) AND V2347.LISTVAL_ID = 11130) OR
        (:V$JOB_LISTVAL_ID IN (18530,66) AND V2347.LISTVAL_ID = 11131) OR
        (:V$JOB_LISTVAL_ID IN (18498) AND V2347.LISTVAL_ID = 11133) OR
        (:V$JOB_LISTVAL_ID IN (18499) AND V2347.LISTVAL_ID = 11134) OR
        (:V$JOB_LISTVAL_ID IN (18534) AND V2347.LISTVAL_ID = 11135) OR
        (:V$JOB_LISTVAL_ID IN (18500,94) AND V2347.LISTVAL_ID = 11136))
      ORDER BY V544.VAL DESC
      INTO :V$LISTVAL_ID;
      VAL = V$LISTVAL_ID;
      IF (I$OBJ_ID < 0) THEN
      BEGIN
        VAL = NULL;
        IF (V$LISTVAL_ID = 1208) THEN VAL = 'Высшая квалификационная категория';
        ELSE IF (V$LISTVAL_ID = 1209) THEN VAL = 'Первая квалификационная категория';
        ELSE IF (V$LISTVAL_ID = 1210) THEN VAL = 'Вторая квалификационная категория';
      END
      SUSPEND;
      -- Ученая степень
      TAG_NAME = 'rows:r:sdeg_col';
      VAL = NULL;
      SELECT FIRST 1 V279.LISTVAL_ID
      FROM VALL V279
      WHERE V279.OBJ_ID = :V$PERSON_ID AND V279.PARAM_ID = 279 AND V279.IS_DEL = 0 AND V279.LISTVAL_ID <> 626
      INTO :VAL;
      IF (I$OBJ_ID < 0 AND VAL IS NOT NULL) THEN
      BEGIN
        SELECT VAL FROM LISTVAL_TEXT(:VAL) INTO :VAL;
      END
      SUSPEND;
      -- Звание
      TAG_NAME = 'rows:r:rank_col';
      VAL = NULL;
      SELECT FIRST 1 V280.LISTVAL_ID
      FROM VALL V280
      WHERE V280.OBJ_ID = :V$PERSON_ID AND V280.PARAM_ID = 280 AND V280.IS_DEL = 0 AND V280.LISTVAL_ID <> 629
      INTO :VAL;
      IF (I$OBJ_ID < 0 AND VAL IS NOT NULL) THEN
      BEGIN
        SELECT VAL FROM LISTVAL_TEXT(:VAL) INTO :VAL;
      END
      SUSPEND;
      -- Отраслевые награды, если нет звания
      IF (VAL IS NULL) THEN
      BEGIN
        V$LISTVAL_ID = NULL;
        SELECT FIRST 1 V345.LISTVAL_ID
        FROM LINKS L39
        JOIN VALD V347 ON V347.OBJ_ID = L39.OBJ_ID AND V347.PARAM_ID = 347 AND V347.IS_DEL = 0 -- дата награждения
        JOIN VALL V345 ON V345.OBJ_ID = L39.OBJ_ID AND V345.PARAM_ID = 345 AND V345.IS_DEL = 0 -- тип награды
        WHERE L39.PARENT_ID = :V$PERSON_ID AND L39.OBJ_TYPE_ID = 39 AND L39.DATE_DEL IS NULL
          AND (V347.VAL IS NOT NULL AND V347.VAL < :V$DATE)
        ORDER BY V347.VAL DESC
        INTO :V$LISTVAL_ID;
        -- Не будем детализировать, просто смотрим, если ли есть отраслевая награда и всегда выдаем 3151 (как признак наличия отраслевой награды)
        IF (V$LISTVAL_ID IS NOT NULL) THEN
        BEGIN
          IF (I$OBJ_ID > 0) THEN
          BEGIN
            VAL = 3151;
          END
          ELSE
          BEGIN
            SELECT VAL FROM LISTVAL_TEXT(:V$LISTVAL_ID) INTO :VAL;
          END
          SUSPEND;
        END
      END
      -- Стаж работы, в днях
      -- Для педагогических должностяж берем педагогический, для остальных по должности
      TAG_NAME = 'rows:r:expr_col';
      VAL = NULL;
      SELECT SUM(V.DAYS360_COUNT)
      FROM LINKS L85
      JOIN VALL V465 ON V465.OBJ_ID = L85.OBJ_ID AND V465.PARAM_ID = 465 AND V465.IS_DEL = 0 AND V465.LISTVAL_ID = IIF(:V$JT = 'U', 942, 1978)
      JOIN VALD V466 ON V466.OBJ_ID = L85.OBJ_ID AND V466.PARAM_ID = 466 AND V466.IS_DEL = 0
      LEFT JOIN VALD V467 ON V467.OBJ_ID = L85.OBJ_ID AND V467.PARAM_ID = 467 AND V467.IS_DEL = 0
      LEFT JOIN GET_DAYS360_COUNT(V466.VAL, COALESCE(V467.VAL, :V$DATE)) V ON 1 = 1
      WHERE L85.PARENT_ID = :V$PERSON_ID AND L85.OBJ_TYPE_ID = 85 AND L85.DATE_DEL IS NULL
      INTO :VAL;
      SUSPEND;
      -- Из учебной нагрузки. Сами значения суммы доплат выдаем в value
      -- Количество классных руководств
      TAG_NAME = 'rows:r:grades_K';
      VAL = NULL;
      SELECT COUNT(*)
      FROM EDULOAD_DATA D
      JOIN LINKS L531 ON L531.OBJ_ID = D.PARENT_ID AND L531.OBJ_TYPE_ID = 531 AND L531.DATE_DEL IS NULL
      JOIN VALL V3567 ON V3567.OBJ_ID = L531.OBJ_ID AND V3567.PARAM_ID = 3567 AND V3567.IS_DEL = 0
      JOIN LISTVALS LV3567 ON LV3567.LISTVAL_ID = V3567.LISTVAL_ID AND LV3567.LIST_ID = 29 AND LV3567.IS_DEL = 0 AND LV3567.COST = EXTRACT(YEAR FROM :V$DATE)
      WHERE D.PERSON_ID = :V$PERSON_ID AND D.REF_TYPE_ID = 9 AND D.DATE_DEL IS NULL
      INTO :VAL;
      SUSPEND;
      -- Количество кабинетов
      TAG_NAME = 'rows:r:rooms_K';
      VAL = NULL;
      SELECT COUNT(*)
      FROM EDULOAD_DATA D
      JOIN LINKS L531 ON L531.OBJ_ID = D.PARENT_ID AND L531.OBJ_TYPE_ID = 531 AND L531.DATE_DEL IS NULL
      JOIN VALL V3567 ON V3567.OBJ_ID = L531.OBJ_ID AND V3567.PARAM_ID = 3567 AND V3567.IS_DEL = 0
      JOIN LISTVALS LV3567 ON LV3567.LISTVAL_ID = V3567.LISTVAL_ID AND LV3567.LIST_ID = 29 AND LV3567.IS_DEL = 0 AND LV3567.COST = EXTRACT(YEAR FROM :V$DATE)
      WHERE D.PERSON_ID = :V$PERSON_ID AND D.REF_TYPE_ID = 61 AND D.DATE_DEL IS NULL
      INTO :VAL;
      SUSPEND;
      -- проверка тетрадей (V5)
      TAG_NAME = 'rows:r:copybook_K';
      VAL = NULL;
      SUSPEND;
    END
  END

  -- Значения справочников для выбора - только в статусе проекта
  IF(V$STATE_ID = 11716) THEN
  BEGIN
    FOR
      SELECT TAG_NAME, VAL
      FROM TARIFF_SETTINGS_GET(:V$OU_ID)
      INTO :TAG_NAME, :VAL
    DO
    BEGIN
      SUSPEND;
    END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE TARIFF_REORDER (
    I$OBJ_ID BIGINT)
AS
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE I INTEGER;
DECLARE VARIABLE N INTEGER;
begin

  I = 0;
  FOR
    SELECT D.OBJ_ID, D.ROW_INDEX
    FROM TARIFF_DATA D
    WHERE D.PARENT_ID = :I$OBJ_ID AND D.DATE_DEL IS NULL
    ORDER BY IIF(D.PERSON_ID IS NULL, 1, 0), D.ROW_INDEX
    INTO :V$OBJ_ID, :N
  DO
  BEGIN
    IF(I <> N) THEN
    UPDATE TARIFF_DATA
    SET ROW_INDEX = :I
    WHERE OBJ_ID = :V$OBJ_ID;

    I = I + 1;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE TARIFF_SET (
    I$PARENT_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$VALUE VARCHAR(4000),
    I$USER_ID VARCHAR(40),
    I$JOB_ID BIGINT,
    I$PERSON_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT)
AS
DECLARE VARIABLE S VARCHAR(4000);
DECLARE VARIABLE V$STATUS BIGINT;
DECLARE VARIABLE V$ROW_INDEX BIGINT;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE N INTEGER;
begin
  IF (I$OBJ_ID IS NULL AND I$JOB_ID IS NULL AND I$PERSON_ID IS NULL) THEN
    EXCEPTION DATA_ERROR 'Не задана ни строка тарификационного списка, ни сотрудник на должности';

  SELECT FIRST 1 V3573.LISTVAL_ID
  FROM LINKS L532
  JOIN VALL V3573 ON V3573.OBJ_ID = L532.OBJ_ID AND V3573.PARAM_ID = 3573 AND V3573.IS_DEL = 0
  WHERE L532.PARENT_TYPE_ID = 2 AND L532.OBJ_TYPE_ID = 532 AND L532.OBJ_ID = :I$PARENT_ID AND L532.DATE_DEL IS NULL
  INTO :V$STATUS;

  IF(V$STATUS IS NULL) THEN EXCEPTION DATA_ERROR 'Тарификационный список не найден или был удален';
  IF(V$STATUS <> 11716) THEN EXCEPTION DATA_ERROR 'Изменения можно вносить только в статусе проекта';
  -- IF(I$VALUE = '' OR I$VALUE IS NULL) THEN I$VALUE = 'delete';

  SELECT FIRST 1 D.VAL
  FROM TARIFF_DATA D
  WHERE D.DATE_DEL IS NULL AND D.OBJ_ID = :I$OBJ_ID AND D.PARENT_ID = :I$PARENT_ID
  INTO :S;

  IF(I$VALUE = 'delete') THEN
  BEGIN
    -- Удаление строки
    UPDATE TARIFF_DATA
    SET DATE_DEL = CURRENT_TIMESTAMP
    WHERE PARENT_ID = :I$PARENT_ID AND OBJ_ID = :I$OBJ_ID AND DATE_DEL IS NULL;
    -- Перенумерация
    N = 0;
    FOR
      SELECT D.OBJ_ID
      FROM TARIFF_DATA D
      WHERE D.DATE_DEL IS NULL AND D.PARENT_ID = :I$PARENT_ID
      ORDER BY D.ROW_INDEX
      INTO :V$OBJ_ID
    DO
    BEGIN
      UPDATE TARIFF_DATA
      SET ROW_INDEX = :N
      WHERE OBJ_ID = :V$OBJ_ID AND ROW_INDEX <> :N;
      N = N + 1;
    END
  END
  ELSE IF(S IS NULL) THEN
  BEGIN
    SELECT MAX(COALESCE(D.ROW_INDEX, 0))
    FROM TARIFF_DATA D
    WHERE D.DATE_DEL IS NULL AND D.PARENT_ID = :I$PARENT_ID
    INTO :V$ROW_INDEX;

    EXECUTE PROCEDURE TARIFF_FILL(:I$PARENT_ID, :I$JOB_ID, :I$PERSON_ID, :I$VALUE, :V$ROW_INDEX + 1);
  END
  ELSE
  BEGIN
    IF(I$VALUE IS NULL) THEN I$VALUE = '';
    IF(S <> I$VALUE) THEN
    UPDATE TARIFF_DATA
    SET VAL = :I$VALUE
    WHERE OBJ_ID = :I$OBJ_ID;
    OBJ_ID = I$OBJ_ID;
  END

  SUSPEND;
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE TARIFF_SETTINGS_GET (
    I$OBJ_ID BIGINT)
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$LIST_ID BIGINT;
DECLARE VARIABLE S VARCHAR(1000);
DECLARE VARIABLE V$COL_ID BIGINT;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE F FLOAT;
DECLARE VARIABLE V$TAG VARCHAR(400);
DECLARE VARIABLE V$FLT VARCHAR(400);
begin

  TAG_NAME = 'categories::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L.LIST_ID, L.LIST_CAPTION
    FROM LISTS_LIST('RU') L
    WHERE L.IS_DEL = 0 AND L.LIST_CAPTION LIKE 'Тарификация.%'
    INTO :V$LIST_ID, :S
  DO
  BEGIN
    TAG_NAME = 'categories:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'categories:r:id';
    VAL = V$LIST_ID;
    SUSPEND;
    TAG_NAME = 'categories:r:name';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'categories:r:cols::json&colon;array';
    VAL = 1;
    SUSPEND;
    -- Столбцы
    FOR
      SELECT LV.LISTVAL_ID, C.VAL
      FROM LISTVALS LV
      LEFT JOIN LISTVAL_TEXT(LV.LISTVAL_ID) C ON 1 = 1
      WHERE LV.LIST_ID = :V$LIST_ID AND LV.IS_DEL = 0 AND LV.PARENT_ID IS NULL
      ORDER BY LV.SORT_ORDER
      INTO :V$COL_ID, :S
    DO
    BEGIN
      TAG_NAME = 'categories:r:cols:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'categories:r:cols:r:id';
      VAL = V$COL_ID;
      SUSPEND;
      TAG_NAME = 'categories:r:cols:r:name';
      VAL = S;
      SUSPEND;
    END
    TAG_NAME = 'categories:r:rows::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT DISTINCT C.VAL
      FROM LISTVALS LV
      LEFT JOIN LISTVAL_TEXT(LV.LISTVAL_ID) C ON 1 = 1
      WHERE LV.LIST_ID = :V$LIST_ID AND LV.IS_DEL = 0 AND LV.PARENT_ID IS NOT NULL
      ORDER BY LV.SORT_ORDER
      INTO :S
    DO
    BEGIN
      TAG_NAME = 'categories:r:rows:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'categories:r:rows:r:name';
      VAL = S;
      SUSPEND;
      TAG_NAME = 'categories:r:rows:r:items::json&colon;array';
      VAL = 1;
      SUSPEND;
      FOR
        SELECT LV.LISTVAL_ID, LV.PARENT_ID, LV.COST, LV.TAG, LV."FILTER"
        FROM LISTVALS LV
        LEFT JOIN LISTVAL_TEXT(LV.LISTVAL_ID) C ON 1 = 1
        WHERE LV.LIST_ID = :V$LIST_ID AND LV.IS_DEL = 0 AND LV.PARENT_ID IS NOT NULL AND C.VAL = :S
        ORDER BY LV.SORT_ORDER
        INTO :V$OBJ_ID, :V$COL_ID, :F, :V$TAG, :V$FLT
      DO
      BEGIN
        TAG_NAME = 'categories:r:rows:r:items:r';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'categories:r:rows:r:items:r:id';
        VAL = V$OBJ_ID;
        SUSPEND;
        TAG_NAME = 'categories:r:rows:r:items:r:col';
        VAL = V$COL_ID;
        SUSPEND;
        TAG_NAME = 'categories:r:rows:r:items:r:for_value';
        VAL = V$TAG;
        SUSPEND;
        TAG_NAME = 'categories:r:rows:r:items:r:for_col';
        VAL = V$FLT;
        SUSPEND;
        TAG_NAME = 'categories:r:rows:r:items:r:value';
        VAL = CAST(F AS NUMERIC(18, 2));
        SUSPEND;
      END
    END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE TARIFF_STATUS (
    I$OBJ_ID BIGINT,
    I$STATE_ID BIGINT,
    I$USER_ID VARCHAR(40))
AS
DECLARE VARIABLE V$OU_ID BIGINT;
DECLARE VARIABLE V$STATUS BIGINT;
DECLARE VARIABLE V$DATE DATE;
DECLARE VARIABLE T INTEGER;
begin

  SELECT FIRST 1 L532.PARENT_ID, V3573.LISTVAL_ID, V3571.VAL
  FROM LINKS L532
  JOIN VALL V3573 ON V3573.OBJ_ID = L532.OBJ_ID AND V3573.PARAM_ID = 3573 AND V3573.IS_DEL = 0
  JOIN VALD V3571 ON V3571.OBJ_ID = L532.OBJ_ID AND V3571.PARAM_ID = 3571 AND V3571.IS_DEL = 0
  WHERE L532.PARENT_TYPE_ID = 2 AND L532.OBJ_ID = :I$OBJ_ID AND L532.DATE_DEL IS NULL
  INTO :V$OU_ID, :V$STATUS, :V$DATE;

  IF(V$STATUS IS NULL) THEN EXCEPTION DATA_ERROR 'Запись не найдена или была удалена';
  IF(V$STATUS = 14261) THEN EXCEPTION DATA_ERROR 'Тарификационный список не может быть возвращен в статус проекта после закрытия учетного периода';

  -- Нельзя менять статус с разрывом хронологии
  IF(I$STATE_ID = 11716) THEN     -- проект
  BEGIN
    IF(EXISTS(
      SELECT FIRST 1 1
      FROM LINKS L532
      JOIN VALL V3573 ON V3573.OBJ_ID = L532.OBJ_ID AND V3573.PARAM_ID = 3573 AND V3573.IS_DEL = 0 AND V3573.LISTVAL_ID = 11715
      JOIN VALD V3571 ON V3571.OBJ_ID = L532.OBJ_ID AND V3571.PARAM_ID = 3571 AND V3571.IS_DEL = 0
        AND (V3571.VAL > :V$DATE OR (V3571.VAL = :V$DATE AND L532.OBJ_ID > :I$OBJ_ID))
      WHERE L532.PARENT_ID = :V$OU_ID AND L532.OBJ_TYPE_ID = 532 AND L532.DATE_DEL IS NULL AND L532.OBJ_ID <> :I$OBJ_ID
    ))
    THEN
      EXCEPTION DATA_ERROR 'В статус проекта можно переводить только последний по хронологи тарификационный список';
  END
  ELSE IF(I$STATE_ID = 11715) THEN   -- действующий
  BEGIN
    IF(EXISTS(
      SELECT FIRST 1 1
      FROM LINKS L532
      JOIN VALL V3573 ON V3573.OBJ_ID = L532.OBJ_ID AND V3573.PARAM_ID = 3573 AND V3573.IS_DEL = 0 AND V3573.LISTVAL_ID = 11715
      JOIN VALD V3571 ON V3571.OBJ_ID = L532.OBJ_ID AND V3571.PARAM_ID = 3571 AND V3571.IS_DEL = 0
        AND (V3571.VAL > :V$DATE OR (V3571.VAL = :V$DATE AND L532.OBJ_ID > :I$OBJ_ID))
      WHERE L532.PARENT_ID = :V$OU_ID AND L532.OBJ_TYPE_ID = 532 AND L532.DATE_DEL IS NULL AND L532.OBJ_ID <> :I$OBJ_ID
    ))
    THEN
      EXCEPTION DATA_ERROR 'В статус действующего можно переводить только последний по хронологи тарификационный список';
  END
  ELSE
    EXCEPTION DATA_ERROR 'Недопустимый статус тарификационного списка';

  SELECT 1 FROM VAL_ADD(3573, :I$OBJ_ID, :I$STATE_ID) INTO :T;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE TASKS_ACTIVE_LIST (
    I$MODULE_ID BIGINT = NULL,
    I$LANG_CODE CHAR(2) = 'RU')
RETURNS (
    MODULE_ID BIGINT,
    MODULE_CAPTION VARCHAR(4000),
    TASK_ID BIGINT,
    TASK_CAPTION VARCHAR(4000))
AS
DECLARE VARIABLE MRES_ID BIGINT;
DECLARE VARIABLE TRES_ID BIGINT;
BEGIN
    FOR
        SELECT M.MODULE_ID,
               T.TASK_ID,
               M.RES_ID,
               T.RES_ID
        FROM MODULES M
        INNER JOIN TASKS T
        ON M.MODULE_ID = T.MODULE_ID
        WHERE (:I$MODULE_ID IS NULL OR M.MODULE_ID = :I$MODULE_ID)
        AND   T.IS_DEL = 0
        AND   M.IS_DEL = 0
        AND   M.IS_ACTIVE = 1
        ORDER BY M.SORT_ORDER,
                 T.SORT_ORDER
        INTO   :MODULE_ID,
               :TASK_ID,
               :MRES_ID,
               :TRES_ID
    DO
    BEGIN
        SELECT VAL FROM RES_GET(:MRES_ID, :I$LANG_CODE) INTO :MODULE_CAPTION;
        SELECT VAL FROM RES_GET(:TRES_ID, :I$LANG_CODE) INTO :TASK_CAPTION;
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE TASKS_LIST (
    I$MODULE_ID BIGINT,
    I$LANG_CODE VARCHAR(2) = 'RU')
RETURNS (
    TASK_ID BIGINT,
    RES_ID BIGINT,
    MODULE_ID BIGINT,
    IS_DEL SMALLINT,
    TASK_CAPTION VARCHAR(4000))
AS
BEGIN
    FOR
        SELECT TASK_ID,
               RES_ID,
               MODULE_ID,
               IS_DEL
        FROM TASKS
        WHERE MODULE_ID = :I$MODULE_ID
        ORDER BY SORT_ORDER
        INTO   :TASK_ID,
               :RES_ID,
               :MODULE_ID,
               :IS_DEL
    DO
    BEGIN
        SELECT VAL
        FROM RES_GET(:RES_ID, :I$LANG_CODE)
        INTO   :TASK_CAPTION;
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE TASK_ADD (
    I$TASK_ID BIGINT,
    I$RES_ID BIGINT,
    I$MODULE_ID BIGINT,
    I$LANG_CODE CHAR(2),
    I$TASK_CAPTION VARCHAR(4000),
    I$IS_DEL SMALLINT = 0)
RETURNS (
    TASK_ID BIGINT,
    RES_ID BIGINT)
AS
declare variable sort_order smallint;
BEGIN
    TASK_ID = I$TASK_ID;
    RES_ID = I$RES_ID;

    IF (I$TASK_ID IS NULL) THEN BEGIN
        SELECT MAX(SORT_ORDER) + 1 FROM TASKS WHERE MODULE_ID = :I$MODULE_ID
        INTO :SORT_ORDER;
        IF (SORT_ORDER IS NULL) THEN SORT_ORDER = 1;

        INSERT INTO TASKS (MODULE_ID, SORT_ORDER, IS_DEL)
        VALUES (:I$MODULE_ID, :SORT_ORDER, :I$IS_DEL)
        RETURNING TASK_ID, RES_ID INTO :TASK_ID, :RES_ID;
    END ELSE BEGIN
        UPDATE TASKS SET
            IS_DEL = :I$IS_DEL
        WHERE TASK_ID = :I$TASK_ID;
    END

    IF (RES_ID IS NOT NULL) THEN
    BEGIN
        EXECUTE PROCEDURE RES_ADD (:RES_ID,:I$LANG_CODE,:I$TASK_CAPTION);
    END

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE TASK_MOVE (
    I$TASK_ID BIGINT,
    I$MOVE SMALLINT)
RETURNS (
    SORT_ORDER SMALLINT)
AS
DECLARE VARIABLE MODULE_ID BIGINT = NULL;
DECLARE VARIABLE TASK_ID BIGINT = NULL;
BEGIN
   SELECT MODULE_ID, SORT_ORDER FROM TASKS
   WHERE TASK_ID = :I$TASK_ID
   INTO :MODULE_ID, :SORT_ORDER;

   SELECT TASK_ID FROM TASKS
   WHERE MODULE_ID = :MODULE_ID AND SORT_ORDER = (:SORT_ORDER + :I$MOVE)
   INTO :TASK_ID;

   IF (TASK_ID IS NOT NULL) THEN
   BEGIN
      UPDATE TASKS SET SORT_ORDER = :SORT_ORDER WHERE TASK_ID = :TASK_ID;
      UPDATE TASKS SET SORT_ORDER = (:SORT_ORDER + :I$MOVE) WHERE TASK_ID = :I$TASK_ID;
   END
   SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE TEACHER_CAPTION_GET (
    OBJ_ID BIGINT)
RETURNS (
    CAPTION VARCHAR(1000))
AS
declare variable V1 varchar(1000);
declare variable V2 varchar(1000);
begin

  CAPTION = '';
  SELECT V59.VAL
  FROM VALS V59
  WHERE V59.OBJ_ID = :OBJ_ID AND V59.PARAM_ID = 59 AND V59.IS_DEL = 0
  INTO :CAPTION;

  V1 = '';
  SELECT COALESCE(' ' || SUBSTRING(V60.VAL FROM 1 FOR 1) || '.', '')
  FROM VALS V60
  WHERE V60.OBJ_ID = :OBJ_ID AND V60.PARAM_ID = 60 AND V60.IS_DEL = 0
  INTO :V1;

  V2 = '';
  IF(V1 <> '') THEN
  BEGIN
    SELECT COALESCE(' ' || SUBSTRING(V61.VAL FROM 1 FOR 1) || '.', '')
    FROM VALS V61
    WHERE V61.OBJ_ID = :OBJ_ID AND V61.PARAM_ID = 61 AND V61.IS_DEL = 0
    INTO :V2;
  END

  CAPTION = CAPTION || V1 || V2;

  IF(CAPTION = '') THEN CAPTION = '< ... >';

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE TEST_D_12 RETURNS (
    ROW_NUM INTEGER,
    C1 INTEGER,
    C2 INTEGER,
    C3 INTEGER)
AS
declare variable V$OBJ_ID bigint;
declare variable T varchar(10);
begin

  SELECT FIRST 1 L2.OBJ_ID
  FROM LINKS L2
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$OBJ_ID;

  select N from D_12_ADD_CALC_OU(:V$OBJ_ID, '31.08.2020', '01.09.2021', 2) into :t;

  for
    select row_num, sum(C1), sum(C2), sum(C3)
    from REPORT_D12
    group by 1
    into :ROW_NUM, :C1, :c2, :c3
  do
  begin
    suspend;
  end

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE THE_CAPTION_CLASS (
    I$OBJ_ID BIGINT,
    I$CAPTION VARCHAR(4000))
RETURNS (
    CAPTION VARCHAR(4000),
    SORT_ORDER SMALLINT)
AS
declare variable V$TAG varchar(100);
declare variable V$PARENT_TYPE_ID bigint;
declare variable V$TYPE_ID bigint;
declare variable V$OBJ_ID bigint;
declare variable V$PARENT_ID bigint;
declare variable V$INT_OBJ_ID bigint;
declare variable V$COST integer;
declare variable V$LISTVAL bigint;
BEGIN
    CAPTION = I$CAPTION;
    V$TAG = NULL;
    SORT_ORDER = 0;

    SELECT FIRST 1 PARENT_TYPE_ID, PARENT_ID, OBJ_TYPE_ID
    FROM LINKS
    WHERE OBJ_ID = :I$OBJ_ID AND DATE_DEL IS NULL AND (PARENT_TYPE_ID = 8 OR PARENT_TYPE_ID = 77)
    INTO :V$PARENT_TYPE_ID, :V$OBJ_ID, :V$TYPE_ID;

    IF (V$PARENT_TYPE_ID = 8) THEN
    BEGIN
        SELECT FIRST 1 LV.TAG, LV.SORT_ORDER
        FROM VALL V
        JOIN LISTVALS LV ON V.LISTVAL_ID = LV.LISTVAL_ID
        WHERE V.PARAM_ID = 49 AND V.OBJ_ID = :V$OBJ_ID AND V.IS_DEL = 0
        INTO :V$TAG, :SORT_ORDER;

        IF (V$TAG IS NULL OR V$TAG = '')  THEN
        BEGIN
            CAPTION = I$CAPTION;
        END
        ELSE
        BEGIN
            IF (I$CAPTION = '<  ...  >') THEN
            BEGIN
                CAPTION = V$TAG;
            END
            ELSE
            BEGIN
                CAPTION = V$TAG || ' ' || I$CAPTION;
            END
        END
    END
    ELSE IF (V$PARENT_TYPE_ID = 77) THEN
    BEGIN
        IF (V$TYPE_ID = 290) THEN
        BEGIN
            SELECT FIRST 1 LV.COST, LV.TAG, LV.SORT_ORDER, LV.LISTVAL_ID
            FROM VALL V2346
            JOIN LISTVALS LV ON LV.LISTVAL_ID = V2346.LISTVAL_ID WHERE V2346.OBJ_ID = :I$OBJ_ID AND V2346.PARAM_ID = 2346 AND V2346.IS_DEL = 0
            INTO :V$COST, :V$TAG, :SORT_ORDER, :V$LISTVAL;

            CAPTION = 'поступающие в ' || V$COST;
            IF(V$LISTVAL > 12941) THEN CAPTION = CAPTION || ' (' || V$TAG || ' год)';
        END
        ELSE
        BEGIN
            -- Непонятная устаревшая ветка кода ?
            SELECT PARENT_ID
            FROM LINKS
            WHERE OBJ_ID = :V$OBJ_ID AND DATE_DEL IS NULL AND PARENT_TYPE_ID = 2
            INTO :V$PARENT_ID;
    
            SELECT FIRST 1 OBJ_ID
            FROM PARAGRAF_TYPE_LEVEL(:V$PARENT_ID, 8, 2)
            ORDER BY SORT_ORDER
            INTO :V$INT_OBJ_ID;

            SELECT LV.TAG, LV.SORT_ORDER
            FROM VALL V
            JOIN LISTVALS LV ON V.LISTVAL_ID = LV.LISTVAL_ID
            WHERE V.OBJ_ID = :V$INT_OBJ_ID AND V.IS_DEL = 0
            INTO :V$TAG, :SORT_ORDER;

            IF(V$TAG IS NULL) THEN
            BEGIN
            END
            ELSE IF (I$CAPTION = '<  ...  >') THEN
            BEGIN
                CAPTION = 'поступающие в ' || :V$TAG;
            END
            ELSE
            BEGIN
                CAPTION = 'поступающие в ' || V$TAG || ' ' || I$CAPTION;
            END
        END
    END

    IF(V$TYPE_ID = 403) THEN
    BEGIN
        CAPTION = 'будущий ' || CAPTION;
        SORT_ORDER = SORT_ORDER + 1000;
    END

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE THE_CAPTION_CLASS_GIA_VIRTUAL (
    I$OBJ_ID BIGINT,
    I$CAPTION VARCHAR(4000))
RETURNS (
    CAPTION VARCHAR(4000),
    SORT_ORDER SMALLINT)
AS
DECLARE VARIABLE V$TAG VARCHAR(100);
DECLARE VARIABLE V$OBJ_ID BIGINT;
BEGIN
    CAPTION = I$CAPTION;
    V$TAG = NULL;
    SORT_ORDER = 0;
    V$OBJ_ID = NULL;

    FOR SELECT FIRST 1 PARENT_ID
        FROM LINKS
        WHERE OBJ_ID = :I$OBJ_ID
          AND DATE_DEL IS NULL
          AND PARENT_TYPE_ID = 8
        INTO :V$OBJ_ID
    DO
    BEGIN
        FOR SELECT LV.TAG, LV.SORT_ORDER
            FROM VALL V
            INNER JOIN LISTVALS LV ON V.LISTVAL_ID = LV.LISTVAL_ID
            WHERE V.PARAM_ID = 49
              AND V.OBJ_ID = :V$OBJ_ID
            INTO :V$TAG, :SORT_ORDER
        DO
        BEGIN
            IF ((V$TAG IS NULL) OR (V$TAG = '')) THEN
            BEGIN
                CAPTION = I$CAPTION;
            END
            ELSE
            BEGIN
                IF (:I$CAPTION = '<  ...  >') THEN
                BEGIN
                    CAPTION = V$TAG;
                END
                ELSE
                BEGIN
                    CAPTION = V$TAG || ' ' || I$CAPTION;
                END
            END
        END
    END

    IF (V$OBJ_ID IS NULL) THEN
    BEGIN
        FOR SELECT FIRST 1 PARENT_ID
            FROM LINKS
            WHERE OBJ_ID = :I$OBJ_ID
              AND DATE_DEL IS NULL
              AND PARENT_TYPE_ID = 124
            INTO :V$OBJ_ID
        DO
        BEGIN
            IF (:I$CAPTION = '<  ...  >') THEN
            BEGIN
                CAPTION = '11';
            END
            ELSE
            BEGIN
                CAPTION = '11 ' || I$CAPTION;
            END
        END
    END

    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE THE_CAPTION_COLLEGE_GROUP (
    I$OBJ_ID BIGINT,
    I$CAPTION VARCHAR(4000))
RETURNS (
    CAPTION VARCHAR(4000),
    SORT_ORDER SMALLINT)
AS
declare variable V$TAG varchar(100);
declare variable V$PARENT_TYPE_ID bigint;
declare variable V$TYPE_ID bigint;
declare variable V$OBJ_ID bigint;
declare variable V$PARENT_ID bigint;
declare variable V$INT_OBJ_ID bigint;
BEGIN
    CAPTION = I$CAPTION;
    V$TAG = NULL;
    SORT_ORDER = 0;

    SELECT FIRST 1 PARENT_TYPE_ID, PARENT_ID, OBJ_TYPE_ID
    FROM LINKS
    WHERE OBJ_ID = :I$OBJ_ID AND DATE_DEL IS NULL AND (PARENT_TYPE_ID = 8 OR PARENT_TYPE_ID = 77)
    INTO :V$PARENT_TYPE_ID, :V$OBJ_ID, :V$TYPE_ID;

    IF (V$PARENT_TYPE_ID = 8) THEN
    BEGIN
        FOR
            SELECT LV.TAG, LV.SORT_ORDER
            FROM VALL V
            JOIN LISTVALS LV ON V.LISTVAL_ID = LV.LISTVAL_ID
            WHERE V.PARAM_ID = 49 AND V.OBJ_ID = :V$OBJ_ID AND V.IS_DEL = 0
            INTO :V$TAG, :SORT_ORDER
        DO
        BEGIN
            IF (V$TAG IS NULL OR V$TAG = '')  THEN
            BEGIN
                CAPTION = I$CAPTION;
            END
            ELSE
            BEGIN
                IF (I$CAPTION = '<  ...  >') THEN
                BEGIN
                    CAPTION = V$TAG;
                END
                ELSE
                BEGIN
                    CAPTION = V$TAG || ' ' || I$CAPTION;
                END
            END
        END
    END

    IF (V$PARENT_TYPE_ID = 77) THEN
    BEGIN
        IF (V$TYPE_ID = 290) THEN
        BEGIN
            CAPTION = 'Поступающие на ' || (
                SELECT LV.TAG
                FROM VALL V2346
                JOIN LISTVALS LV ON LV.LISTVAL_ID = V2346.LISTVAL_ID
                WHERE V2346.OBJ_ID = :I$OBJ_ID AND V2346.PARAM_ID = 2346 AND V2346.IS_DEL = 0
            );
        END
        ELSE
        BEGIN
            SELECT PARENT_ID
            FROM LINKS
            WHERE OBJ_ID = :V$OBJ_ID AND DATE_DEL IS NULL AND PARENT_TYPE_ID = 2
            INTO :V$PARENT_ID;
    
            FOR
                SELECT FIRST 1 OBJ_ID
                FROM PARAGRAF_TYPE_LEVEL(:V$PARENT_ID, 8, 2)
                ORDER BY SORT_ORDER
                INTO :V$INT_OBJ_ID
            DO
            BEGIN
                FOR
                    SELECT LV.TAG, LV.SORT_ORDER
                    FROM VALL V
                    JOIN LISTVALS LV ON V.LISTVAL_ID = LV.LISTVAL_ID
                    WHERE V.OBJ_ID = :V$INT_OBJ_ID AND V.IS_DEL = 0
                    INTO :V$TAG, :SORT_ORDER
                DO
                BEGIN
                    IF (:I$CAPTION = '<  ...  >') THEN
                    BEGIN
                        CAPTION = 'поступающие в ' || :V$TAG;
                    END
                    ELSE
                    BEGIN
                        CAPTION = 'поступающие в ' || :V$TAG || ' ' || :I$CAPTION;
                    END
                END
            END
        END
    END

    IF(V$TYPE_ID = 403) THEN
    BEGIN
        CAPTION = 'будущий ' || CAPTION;
        SORT_ORDER = SORT_ORDER + 1000;
    END

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE THE_CAPTION_DYNAMIC (
    I$OBJ_ID BIGINT,
    I$CAPTION VARCHAR(4000),
    I$USER_ID BIGINT)
RETURNS (
    CAPTION VARCHAR(4000),
    SORT_ORDER SMALLINT)
AS
DECLARE VARIABLE V$VAL VARCHAR(1000);
DECLARE VARIABLE V$TYPE_ID BIGINT;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$PARENT_TYPE_ID BIGINT;
DECLARE VARIABLE V$TAG VARCHAR(100);
DECLARE VARIABLE V$COST INTEGER;
DECLARE VARIABLE V$LISTVAL BIGINT;
DECLARE VARIABLE V$PARENT_ID BIGINT;
DECLARE VARIABLE V$INT_OBJ_ID BIGINT;
DECLARE VARIABLE V$LEVEL_ID BIGINT;
DECLARE VARIABLE V$PLISTVAL BIGINT;
DECLARE VARIABLE LANG_CODE VARCHAR(10);
BEGIN

    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :LANG_CODE;

    CAPTION = I$CAPTION;
    V$TAG = NULL;
    SORT_ORDER = 0;

    SELECT FIRST 1 PARENT_TYPE_ID, PARENT_ID, OBJ_TYPE_ID
    FROM LINKS
    WHERE OBJ_ID = :I$OBJ_ID AND DATE_DEL IS NULL AND (PARENT_TYPE_ID = 8 OR PARENT_TYPE_ID = 77)
    INTO :V$PARENT_TYPE_ID, :V$OBJ_ID, :V$TYPE_ID;

    IF (V$PARENT_TYPE_ID = 8) THEN
    BEGIN
        SELECT FIRST 1 CAST(LV.COST AS INTEGER), R.VAL, LV.SORT_ORDER
        FROM VALL V
        JOIN LISTVALS LV ON V.LISTVAL_ID = LV.LISTVAL_ID
        LEFT JOIN RES_GET(LV.RES_ID, :LANG_CODE) R ON 1 = 1
        WHERE V.PARAM_ID = 49 AND V.OBJ_ID = :V$OBJ_ID AND V.IS_DEL = 0
        INTO :V$TAG, :V$VAL, :SORT_ORDER;

        -- Уровень образования ?
        SELECT FIRST 1 V43.LISTVAL_ID
        FROM LINKS LP7
        JOIN VALL V43 ON V43.OBJ_ID = LP7.PARENT_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0
        WHERE LP7.OBJ_ID = :V$OBJ_ID AND LP7.PARENT_TYPE_ID = 7 AND LP7.DATE_DEL IS NULL
        INTO :V$LEVEL_ID;

        -- TAG = пустая строка не может быть, если нет ошибки в справочнике
        IF (V$TAG IS NULL OR V$TAG = '')  THEN
        BEGIN
            -- Не указан этап обучения вообще ?
            CAPTION = I$CAPTION;
        END
        ELSE
        BEGIN
            IF (I$CAPTION = '<  ...  >') THEN
            BEGIN
                -- Непонятно что за случай
                CAPTION = V$TAG;
            END
            ELSE
            BEGIN
                -- Класс + суффикс, либо Уровень + суффикс в кавычках
                IF (V$LEVEL_ID IN (3263, 3264)) THEN
                BEGIN
                    V$TAG = V$VAL;
                    IF(CHAR_LENGTH(I$CAPTION) > 1) THEN I$CAPTION = '«' || I$CAPTION || '»';
                END
                CAPTION = V$TAG || ' ' || I$CAPTION;
            END
        END
    END
    ELSE IF (V$PARENT_TYPE_ID = 77) THEN
    BEGIN
        IF (V$TYPE_ID = 290) THEN
        BEGIN
            SELECT FIRST 1 LV.COST, LV.TAG, LV.SORT_ORDER, LV.LISTVAL_ID, LV.PARENT_ID, R.VAL
            FROM VALL V2346
            JOIN LISTVALS LV ON LV.LISTVAL_ID = V2346.LISTVAL_ID
            JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
            WHERE V2346.OBJ_ID = :I$OBJ_ID AND V2346.PARAM_ID = 2346 AND V2346.IS_DEL = 0
            INTO :V$COST, :V$TAG, :SORT_ORDER, :V$LISTVAL, :V$PLISTVAL, :V$VAL;

            IF(V$PLISTVAL = 2142) THEN
              CAPTION = 'поступающие на ' || V$COST || ' курс'; -- СПО
            ELSE IF(V$PLISTVAL = 2140) THEN
              CAPTION = 'поступающие на этап ' || V$VAL; -- ДОУ
            ELSE
              CAPTION = 'поступающие в ' || V$COST;
            IF(V$LISTVAL > 12941) THEN CAPTION = CAPTION || ' (' || V$TAG || ' год)';
        END
        ELSE
        BEGIN
            SELECT PARENT_ID
            FROM LINKS
            WHERE OBJ_ID = :V$OBJ_ID AND DATE_DEL IS NULL AND PARENT_TYPE_ID = 2
            INTO :V$PARENT_ID;
    
            SELECT FIRST 1 OBJ_ID
            FROM PARAGRAF_TYPE_LEVEL(:V$PARENT_ID, 8, 2)
            ORDER BY SORT_ORDER
            INTO :V$INT_OBJ_ID;

            SELECT LV.TAG, LV.SORT_ORDER
            FROM VALL V
            JOIN LISTVALS LV ON V.LISTVAL_ID = LV.LISTVAL_ID
            WHERE V.OBJ_ID = :V$INT_OBJ_ID AND V.IS_DEL = 0
            INTO :V$TAG, :SORT_ORDER;

            IF(V$TAG IS NULL) THEN
            BEGIN
            END
            ELSE IF (I$CAPTION = '<  ...  >') THEN
            BEGIN
                CAPTION = 'поступающие в ' || V$TAG;
            END
            ELSE
            BEGIN
                CAPTION = 'поступающие в ' || V$TAG || ' ' || I$CAPTION;
            END
        END
    END

    IF(V$TYPE_ID = 403) THEN
    BEGIN
        CAPTION = 'будущий ' || CAPTION;
        SORT_ORDER = SORT_ORDER + 1000;
    END

    SUSPEND;

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE THE_CAPTION_FINISHED (
    I$OBJ_ID BIGINT,
    I$CAPTION VARCHAR(4000),
    I$USER_ID BIGINT)
RETURNS (
    CAPTION VARCHAR(4000))
AS
declare variable V$FROM varchar(100);
declare variable V$TO varchar(100);
BEGIN
    CAPTION = I$CAPTION;
    
    SELECT V
    FROM VAL_GET(:I$OBJ_ID, 444, 0, :I$USER_ID)
    INTO :V$FROM;

    SELECT V
    FROM VAL_GET(:I$OBJ_ID, 445, 0, :I$USER_ID)
    INTO :V$TO;

    IF (V$FROM <> '') THEN
    BEGIN
        CAPTION = CAPTION || ' ' || V$FROM;
        IF (V$TO <> '') THEN
        BEGIN
            CAPTION = CAPTION || ' - ' || V$TO;
        END
    END

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE THE_CAPTION_GROUP (
    I$OBJ_ID BIGINT,
    I$CAPTION VARCHAR(4000),
    I$USER_ID BIGINT)
RETURNS (
    CAPTION VARCHAR(4000),
    SORT_ORDER SMALLINT)
AS
DECLARE VARIABLE V$VAL VARCHAR(1000);
DECLARE VARIABLE V$TYPE_ID BIGINT;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE LANG_CODE VARCHAR(2);
DECLARE VARIABLE V$PARENT_TYPE_ID BIGINT;
BEGIN
    SELECT LANG_CODE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :LANG_CODE;

    CAPTION = I$CAPTION;
    V$VAL = NULL;
    SORT_ORDER = 0;

    SELECT FIRST 1 PARENT_TYPE_ID, PARENT_ID, OBJ_TYPE_ID
    FROM LINKS
    WHERE OBJ_ID = :I$OBJ_ID AND DATE_DEL IS NULL AND (PARENT_TYPE_ID = 8 OR PARENT_TYPE_ID = 77)
    INTO :V$PARENT_TYPE_ID, :V$OBJ_ID, :V$TYPE_ID;

    IF (V$PARENT_TYPE_ID = 8) THEN
    BEGIN
        FOR
            SELECT R.VAL, LV.SORT_ORDER
            FROM VALL V
            JOIN LISTVALS LV ON V.LISTVAL_ID = LV.LISTVAL_ID
            LEFT JOIN RES_GET(LV.RES_ID,  :LANG_CODE) R ON 1=1
            WHERE V.PARAM_ID = 49 AND V.OBJ_ID = :V$OBJ_ID AND V.IS_DEL = 0
            INTO :V$VAL, :SORT_ORDER
        DO
        BEGIN
            IF ((V$VAL IS NULL) OR (V$VAL = ''))  THEN
            BEGIN
                CAPTION = I$CAPTION;
            END
            ELSE
            BEGIN
                IF (I$CAPTION = '<  ...  >') THEN
                BEGIN
                    CAPTION = V$VAL;
                END
                ELSE
                BEGIN
                    IF (CHAR_LENGTH(I$CAPTION) > 1) THEN
                    BEGIN
                        I$CAPTION = '«' || I$CAPTION || '»';
                    END
                    CAPTION = V$VAL || ' ' || I$CAPTION;
                END
            END
        END
    END

    IF (V$PARENT_TYPE_ID = 77) THEN
    BEGIN
        IF (V$TYPE_ID = 290) THEN
        BEGIN
            CAPTION = 'Поступающие на этап ' || (
                SELECT R.VAL
                FROM VALL V2346
                JOIN LISTVALS LV ON LV.LISTVAL_ID = V2346.LISTVAL_ID
                LEFT JOIN RES_GET(LV.RES_ID, :LANG_CODE) R ON 1=1
                WHERE V2346.OBJ_ID = :I$OBJ_ID AND V2346.PARAM_ID = 2346 AND V2346.IS_DEL = 0
            );
        END
    END

    IF(V$TYPE_ID = 403) THEN
    BEGIN
        CAPTION = 'будущий ' || CAPTION;
        SORT_ORDER = SORT_ORDER + 1000;
    END

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE THE_CAPTION_GUP (
    I$OBJ_ID BIGINT,
    I$CAPTION VARCHAR(4000))
RETURNS (
    CAPTION VARCHAR(4000),
    SORT_ORDER SMALLINT)
AS
declare variable V$OBJ_ID bigint;
BEGIN
    CAPTION = I$CAPTION;
    SORT_ORDER = 0;

    SELECT FIRST 1 LP8.PARENT_ID
    FROM LINKS L10
    JOIN LINKS LP9 ON LP9.OBJ_ID = L10.OBJ_ID AND LP9.PARENT_TYPE_ID IN (9,187) AND LP9.DATE_DEL IS NULL
    JOIN LINKS LP8 ON LP8.OBJ_ID = LP9.PARENT_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
    WHERE L10.PARENT_ID = :I$OBJ_ID AND L10.OBJ_TYPE_ID = 10 -- AND L10.DATE_DEL IS NULL
    ORDER BY IIF(L10.DATE_DEL IS NULL, 1, 0)
    INTO :V$OBJ_ID;

    SELECT LV.SORT_ORDER
    FROM VALL V
    JOIN LISTVALS LV ON V.LISTVAL_ID = LV.LISTVAL_ID
    WHERE V.PARAM_ID = 49 AND V.OBJ_ID = :V$OBJ_ID AND V.IS_DEL = 0
    INTO :SORT_ORDER;

    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE THE_CAPTION_LEAVED (
    I$OBJ_ID BIGINT,
    I$CAPTION VARCHAR(4000),
    I$USER_ID BIGINT)
RETURNS (
    CAPTION VARCHAR(4000))
AS
declare variable V$FROM varchar(100);
declare variable V$TO varchar(100);
BEGIN
    CAPTION = I$CAPTION;
    
    SELECT V
    FROM VAL_GET(:I$OBJ_ID, 448, 0, :I$USER_ID)
    INTO :V$FROM;

    SELECT V
    FROM VAL_GET(:I$OBJ_ID, 449, 0, :I$USER_ID)
    INTO :V$TO;

    IF (V$FROM <> '') THEN
    BEGIN
        CAPTION = CAPTION || ' ' || V$FROM;
        IF (V$TO <> '') THEN
        BEGIN
            CAPTION = CAPTION || ' - ' || V$TO;
        END
    END

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE THE_CAPTION_STREAM (
    I$OBJ_ID BIGINT,
    I$CAPTION VARCHAR(4000))
RETURNS (
    CAPTION VARCHAR(4000),
    SORT_ORDER SMALLINT)
AS
declare variable TAG varchar(100);
declare variable V$TYPE_ID bigint;
BEGIN
    CAPTION = I$CAPTION;
    TAG = NULL;
    SORT_ORDER = 0;

    SELECT TYPE_ID
    FROM OBJECTS
    WHERE OBJ_ID = :I$OBJ_ID
    INTO :V$TYPE_ID;

    IF(V$TYPE_ID = 46) THEN
    BEGIN

        /* #46 Объединение, группа */

        SELECT LV.TAG, LV.SORT_ORDER
        FROM LINKS L
        JOIN OBJECTS O ON L.PARENT_ID = O.OBJ_ID AND O.TYPE_ID = 8
        JOIN VALL V ON V.OBJ_ID = O.OBJ_ID AND V.PARAM_ID = 49 AND V.IS_DEL = 0
        JOIN LISTVALS LV ON V.LISTVAL_ID = LV.LISTVAL_ID
        WHERE L.OBJ_ID = :I$OBJ_ID AND L.DATE_DEL IS NULL
        INTO :TAG, :SORT_ORDER;

        IF (TAG IS NOT NULL) THEN BEGIN
            IF (:I$CAPTION='<  ...  >') THEN CAPTION = TAG;
                                        ELSE CAPTION = TAG||'-'||I$CAPTION;
        END

    END
    ELSE
    BEGIN

        /* #347 Поток - нужна только сортировка */

        SELECT LV.SORT_ORDER
        FROM LINKS LP346
        JOIN LINKS LP54 ON LP54.OBJ_ID = LP346.PARENT_ID AND LP54.PARENT_TYPE_ID = 54 AND LP54.DATE_DEL IS NULL
        JOIN VALL V ON V.OBJ_ID = LP54.PARENT_ID AND V.PARAM_ID = 381 AND V.IS_DEL = 0
        JOIN LISTVALS LV ON V.LISTVAL_ID = LV.LISTVAL_ID
        WHERE LP346.OBJ_ID = :I$OBJ_ID AND LP346.PARENT_TYPE_ID = 346 AND LP346.DATE_DEL IS NULL
        INTO :SORT_ORDER;

    END

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE THE_CAPTION_TEACHER (
    I$TEACHER_ID BIGINT)
RETURNS (
    CAPTION VARCHAR(4000))
AS
declare variable V varchar(4000);
BEGIN
    CAPTION = '';

    SELECT TRIM(V.VAL)
    FROM VALS V
    WHERE V.PARAM_ID = 59
    AND V.OBJ_ID = :I$TEACHER_ID
    AND IS_DEL = 0
    INTO :CAPTION;

    V = '';

    SELECT TRIM(V.VAL)
    FROM VALS V
    WHERE V.PARAM_ID = 60
    AND V.OBJ_ID = :I$TEACHER_ID
    AND IS_DEL = 0
    INTO :V;

    IF (V > '') THEN CAPTION = CAPTION || ' ' || SUBSTRING(V FROM 1 FOR 1) || '.';

    V = '';

    SELECT TRIM(V.VAL)
    FROM VALS V
    WHERE V.PARAM_ID = 61
    AND V.OBJ_ID = :I$TEACHER_ID
    AND IS_DEL = 0
    INTO :V;

    IF (V > '') THEN CAPTION = CAPTION || ' ' || SUBSTRING(V FROM 1 FOR 1) || '.';

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE TRANSFER_GRADE_LIST (
    I$OBJ_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    CAPTION VARCHAR(1000),
    OBJ_TYPE_ID BIGINT)
AS
declare variable V$TYPE bigint;
declare variable V$OU_LICENCE_TYPE char(1);
declare variable V$CURRENT_ID bigint;
declare variable V$CURRENT_IN_ID bigint;
declare variable V$ORDER double precision;
begin

    SELECT TYPE_ID FROM OBJECTS WHERE OBJ_ID = :I$OBJ_ID INTO :V$TYPE;
    V$OU_LICENCE_TYPE = (SELECT STATUS FROM OU_LICENCE_TYPE);

    -- Ученик в предварительном приеме ?
    SELECT FIRST 1 LP.PARENT_ID
    FROM LINKS LP
    WHERE LP.OBJ_ID = :I$OBJ_ID AND LP.PARENT_TYPE_ID = 290 AND LP.DATE_DEL IS NULL
    INTO :V$CURRENT_IN_ID;

    SELECT FIRST 1 LP9.PARENT_ID
    FROM LINKS LP9
    WHERE LP9.OBJ_ID = :I$OBJ_ID AND LP9.PARENT_TYPE_ID IN (9, 187) AND LP9.DATE_DEL IS NULL
    INTO :V$CURRENT_ID;

    -- Если ученик в предварительном приеме, то учебные коллективы не даем выбирать
    -- можно только этапы предварительного приема
    IF(V$CURRENT_IN_ID IS NULL) THEN
    FOR
      -- Действующие классы и экстернаты, специально уменьшаем номер чтобы были в начала списка
      SELECT L9.OBJ_ID, L9.OBJ_TYPE_ID, C.CAPTION, -1000 + LV.COST
      FROM LINKS L2
      JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
      JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
      JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
      JOIN LISTVALS LV ON LV.LISTVAL_ID = V49.LISTVAL_ID
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 187) AND L9.DATE_DEL IS NULL AND (L9.OBJ_ID <> :V$CURRENT_ID OR :V$CURRENT_ID IS NULL)
      LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C ON 1 = 1
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      ORDER BY 4, 3
      INTO :OBJ_ID, :OBJ_TYPE_ID, :CAPTION, :V$ORDER
    DO
    BEGIN
      SUSPEND;
    END

    -- Если вызываем для выбывшего (не окончившего), и он не в экстернате - разрешено выбирать предварительный прием
    IF(V$CURRENT_ID IS NULL AND I$OBJ_ID IS NOT NULL) THEN
    BEGIN

      SELECT FIRST 1 LP.PARENT_ID
      FROM LINKS LP
      WHERE LP.OBJ_ID = :I$OBJ_ID AND LP.PARENT_TYPE_ID = 82 AND LP.DATE_DEL IS NULL
      INTO :V$CURRENT_ID;

      IF(V$CURRENT_ID IS NOT NULL OR V$CURRENT_IN_ID IS NOT NULL) THEN
      FOR
        SELECT L290.OBJ_ID, L290.OBJ_TYPE_ID, C.CAPTION, 1000 + LV.COST
        FROM LINKS L2
        JOIN LINKS L77 ON L77.PARENT_ID = L2.OBJ_ID AND L77.OBJ_TYPE_ID = 77 AND L77.DATE_DEL IS NULL
        JOIN LINKS L290 ON L290.PARENT_ID = L77.OBJ_ID AND L290.OBJ_TYPE_ID = 290 AND L290.DATE_DEL IS NULL
          AND (:V$CURRENT_IN_ID IS NULL OR L290.OBJ_ID <> :V$CURRENT_IN_ID)
        JOIN VALL V2346 ON V2346.OBJ_ID = L290.OBJ_ID AND V2346.PARAM_ID = 2346 AND V2346.IS_DEL = 0
        JOIN LISTVALS LV ON LV.LISTVAL_ID = V2346.LISTVAL_ID
        LEFT JOIN OBJECT_CAPTION_GET(L290.OBJ_ID) C ON 1 = 1
        WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
        ORDER BY 4, 3
        INTO :OBJ_ID, :OBJ_TYPE_ID, :CAPTION, :V$ORDER
      DO
      BEGIN
        SUSPEND;
      END

    END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE TRANSFER_GUP_LIST (
    I$OBJ_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    OBJ_TYPE_ID BIGINT,
    CAPTION VARCHAR(1000),
    SUBJECT_NAME VARCHAR(1000))
AS
DECLARE VARIABLE V$TYPE BIGINT;
DECLARE VARIABLE V$STAGE_ID BIGINT;
DECLARE VARIABLE V$STAGE_COST BIGINT;
DECLARE VARIABLE V$OU_LICENCE_TYPE VARCHAR(1);
DECLARE VARIABLE V$YEAR BIGINT;
DECLARE VARIABLE V$STAGE_LEVEL BIGINT;
DECLARE VARIABLE V$STAGE_LEVEL2 BIGINT;
begin

    SELECT TYPE_ID FROM OBJECTS WHERE OBJ_ID = :I$OBJ_ID INTO :V$TYPE;
    V$OU_LICENCE_TYPE = (SELECT STATUS FROM OU_LICENCE_TYPE);

    SELECT FIRST 1 V49.LISTVAL_ID, LV.COST, LV.PARENT_ID
    FROM LINKS LP8
    JOIN VALL V49 ON V49.OBJ_ID = LP8.PARENT_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V49.LISTVAL_ID
    WHERE LP8.OBJ_ID = :I$OBJ_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
    INTO :V$STAGE_ID, :V$STAGE_COST, :V$STAGE_LEVEL;

    -- А если это предварительный прием ? Вместо ОВЗ подставляем обычные этапы
    IF(V$STAGE_ID IS NULL) THEN
    SELECT FIRST 1 LV.LISTVAL_ID, LV.COST, LV.PARENT_ID
    FROM VALL V2346
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V2346.LISTVAL_ID
    JOIN LISTVALS LV2 ON LV2.PARENT_ID = IIF(LV.PARENT_ID = 12941, 2141, LV.PARENT_ID) AND LV2.COST = LV.COST
    WHERE V2346.OBJ_ID = :I$OBJ_ID AND V2346.PARAM_ID = 2346 AND V2346.IS_DEL = 0
    INTO :V$STAGE_ID, :V$STAGE_COST, :V$STAGE_LEVEL;

    -- Обработка этапов ОВЗ для школ
    IF(V$STAGE_LEVEL = 2141) THEN V$STAGE_LEVEL2 = 12941;
    IF(V$STAGE_LEVEL = 12941) THEN V$STAGE_LEVEL2 = 2141;

    -- При выборе экстернатов не даем выбирать ни ГУП, ни группы по предмету
    -- При выборе будущего класса разрешаем выбирать только будущие ГУП и журналы будущего года !!! TODO !!!
    -- ГУП
    FOR
      SELECT L256.OBJ_ID, L256.OBJ_TYPE_ID, C.CAPTION
      FROM LINKS L69
      JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
      JOIN LINKS L400 ON L400.PARENT_ID = L57.OBJ_ID AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL
      JOIN VALL V3022 ON V3022.OBJ_ID = L400.OBJ_ID AND V3022.PARAM_ID = 3022 AND V3022.IS_DEL = 0 AND V3022.LISTVAL_ID = 3
      -- только действующие
      JOIN VALL V3013 ON V3013.OBJ_ID = L400.OBJ_ID AND V3013.PARAM_ID = 3013 AND V3013.IS_DEL = 0 AND V3013.LISTVAL_ID = 11715
      JOIN LINKS L54 ON L54.PARENT_ID = L400.OBJ_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
      JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
      JOIN LISTVALS LV ON LV.LISTVAL_ID = V381.LISTVAL_ID AND LV.COST = :V$STAGE_COST AND (LV.PARENT_ID = :V$STAGE_LEVEL OR LV.PARENT_ID = :V$STAGE_LEVEL2)
      JOIN LINKS L256 ON L256.PARENT_ID = L54.OBJ_ID AND L256.OBJ_TYPE_ID = 256 AND L256.DATE_DEL IS NULL
      LEFT JOIN OBJECT_CAPTION_GET(L256.OBJ_ID) C ON 1 = 1
      WHERE L69.PARENT_TYPE_ID = 2 AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL AND :V$TYPE <> 187
      ORDER BY 3
      INTO :OBJ_ID, :OBJ_TYPE_ID, :CAPTION
    DO
    BEGIN
      SUSPEND;
    END

    -- Группы по предмету текущего года
    SELECT FIRST 1 V1236.LISTVAL_ID
    FROM LINKS L2
    JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :V$YEAR;

    FOR
      SELECT J.GRADE_ID, G.OBJ_TYPE_ID, J.JOURNAL_NAME, C.CAPTION
      FROM CJ2_JOURNAL J
      JOIN LINKS G ON G.OBJ_ID = J.GRADE_ID AND G.OBJ_TYPE_ID = 179 AND G.PARENT_TYPE_ID = 2 AND G.EXT_OBJ_ID IS NULL
      LEFT JOIN OBJECT_CAPTION_GET(J.SUBJECT_ID) C ON 1 = 1
      WHERE J.DATE_DEL IS NULL AND J.JOURNAL_TYPE = 0 AND J.YEAR_ID = :V$YEAR AND J.STAGE_INDEX = :V$STAGE_ID AND :V$TYPE <> 187
      ORDER BY 4, 3
      INTO :OBJ_ID, :OBJ_TYPE_ID, :CAPTION, :SUBJECT_NAME
    DO
    BEGIN
      SUSPEND;
    END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE TRANSLITERATION (
    I$VAL VARCHAR(250))
RETURNS (
    VAL VARCHAR(250))
AS
DECLARE VARIABLE I INTEGER;
DECLARE VARIABLE N INTEGER;
BEGIN
    SELECT CHAR_LENGTH(TRIM(:I$VAL))
    FROM RDB$DATABASE
    INTO :I;

    N = 1;
    VAL = '';

    WHILE(I > 0) DO
    BEGIN
        SELECT VAL || COALESCE(R.VAL_LONG, '')
        FROM LISTVALS LV
        JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
        WHERE LV.LIST_ID = 213 AND R.VAL = (SELECT SUBSTRING(:I$VAL FROM :N FOR 1) FROM RDB$DATABASE)

        INTO :VAL;

        I = I - 1;
        N = N + 1;
    END

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE TYPES_ACTIVE_LIST (
    I$LANG_CODE VARCHAR(2) = 'RU')
RETURNS (
    TYPE_ID BIGINT,
    COLOR INTEGER,
    RES_ID BIGINT,
    FOR_REPL_UP SMALLINT,
    FOR_REPL_DOWN SMALLINT,
    TAG VARCHAR(100),
    TYPE_CAPTION VARCHAR(4000))
AS
BEGIN
    FOR
        SELECT TYPE_ID,
               COLOR,
               RES_ID,
               FOR_REPL_UP,
               FOR_REPL_DOWN,
               TAG
        FROM TYPES
        WHERE IS_DEL = 0
        ORDER BY SORT_ORDER
        INTO   :TYPE_ID,
               :COLOR,
               :RES_ID,
               :FOR_REPL_UP,
               :FOR_REPL_DOWN,
               :TAG
    DO
    BEGIN
        SELECT VAL
        FROM RES_GET(:RES_ID, :I$LANG_CODE)
        INTO   :TYPE_CAPTION;
        SUSPEND;
   END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE TYPES_LIST (
    I$LANG_CODE VARCHAR(2) = 'RU')
RETURNS (
    TYPE_ID BIGINT,
    COLOR INTEGER,
    RES_ID BIGINT,
    FOR_REPL_UP SMALLINT,
    FOR_REPL_DOWN SMALLINT,
    TAG VARCHAR(100),
    IS_DEL SMALLINT,
    IS_HIDDEN SMALLINT,
    TYPE_CAPTION VARCHAR(4000),
    CAPTION_SEPARATOR VARCHAR(10))
AS
BEGIN
    FOR
        SELECT TYPE_ID,
               COLOR,
               RES_ID,
               FOR_REPL_UP,
               FOR_REPL_DOWN,
               TAG,
               IS_DEL,
               IS_HIDDEN,
               CAPTION_SEPARATOR
        FROM TYPES
        ORDER BY SORT_ORDER
        INTO   :TYPE_ID,
               :COLOR,
               :RES_ID,
               :FOR_REPL_UP,
               :FOR_REPL_DOWN,
               :TAG,
               :IS_DEL,
               :IS_HIDDEN,
               :CAPTION_SEPARATOR
    DO
    BEGIN
        SELECT VAL
        FROM RES_GET(:RES_ID, :I$LANG_CODE)
        INTO   :TYPE_CAPTION;
        SUSPEND;
   END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE TYPE_ADD (
    I$TYPE_ID BIGINT,
    I$RES_ID BIGINT,
    I$COLOR INTEGER,
    I$FOR_REPL_UP SMALLINT,
    I$FOR_REPL_DOWN SMALLINT,
    I$TAG VARCHAR(100),
    I$LANG_CODE CHAR(2),
    I$TYPE_CAPTION VARCHAR(4000),
    I$IS_DEL SMALLINT = 0,
    I$IS_HIDDEN SMALLINT = 0,
    I$CAPTION_SEPARATOR VARCHAR(10) = '')
RETURNS (
    TYPE_ID BIGINT,
    RES_ID BIGINT)
AS
declare variable SORT_ORDER smallint;
BEGIN
   TYPE_ID = I$TYPE_ID;
   RES_ID = I$RES_ID;

   IF (I$TYPE_ID IS NULL) THEN BEGIN
      SELECT MAX(SORT_ORDER) + 1 FROM TYPES INTO :SORT_ORDER;
      IF (SORT_ORDER IS NULL) THEN SORT_ORDER = 1;

      INSERT INTO TYPES (COLOR, FOR_REPL_UP, FOR_REPL_DOWN, SORT_ORDER,  TAG, IS_DEL, IS_HIDDEN, CAPTION_SEPARATOR)
      VALUES (:I$COLOR, :I$FOR_REPL_UP, :I$FOR_REPL_DOWN, :SORT_ORDER, :I$TAG, :I$IS_DEL, :I$IS_HIDDEN, :I$CAPTION_SEPARATOR)
      RETURNING TYPE_ID, RES_ID INTO :TYPE_ID, :RES_ID;
   END
   ELSE BEGIN
      UPDATE TYPES
      SET
         COLOR = :I$COLOR,
         FOR_REPL_UP = :I$FOR_REPL_UP,
         FOR_REPL_DOWN = :I$FOR_REPL_DOWN,
         TAG = :I$TAG,
         IS_DEL = :I$IS_DEL,
         IS_HIDDEN = :I$IS_HIDDEN,
         CAPTION_SEPARATOR = :I$CAPTION_SEPARATOR
      WHERE
          TYPE_ID = :I$TYPE_ID;

      -- Дополнение для schema
      SELECT RES_ID
      FROM TYPES
      WHERE TYPE_ID = :I$TYPE_ID
      INTO :RES_ID;
   END

   IF (RES_ID IS NOT NULL) THEN
   BEGIN
       EXECUTE PROCEDURE RES_ADD (:RES_ID, :I$LANG_CODE, :I$TYPE_CAPTION);
   END

   SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE TYPE_CAPTION_GET (
    I$TYPE_ID BIGINT,
    I$LANG_CODE VARCHAR(2) = 'RU')
RETURNS (
    TYPE_CAPTION VARCHAR(4000))
AS
DECLARE VARIABLE V$RES_ID BIGINT;
BEGIN
    FOR
        SELECT T.RES_ID
        FROM TYPES T
        WHERE T.TYPE_ID = :I$TYPE_ID
        INTO :V$RES_ID
   DO
   BEGIN
        SELECT VAL
        FROM RES_GET(:V$RES_ID, :I$LANG_CODE)
        INTO :TYPE_CAPTION;
        SUSPEND;
   END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE TYPE_MOVE (
    I$TYPE_ID BIGINT,
    I$MOVE SMALLINT)
RETURNS (
    SORT_ORDER SMALLINT)
AS
DECLARE VARIABLE TYPE_ID BIGINT = NULL;
BEGIN
   SELECT SORT_ORDER FROM TYPES WHERE TYPE_ID = :I$TYPE_ID INTO :SORT_ORDER;

   SELECT TYPE_ID FROM TYPES WHERE SORT_ORDER = (:SORT_ORDER + :I$MOVE) INTO :TYPE_ID;

   IF (TYPE_ID IS NOT NULL) THEN
   BEGIN
      UPDATE TYPES SET SORT_ORDER = :SORT_ORDER WHERE TYPE_ID = :TYPE_ID;
      UPDATE TYPES SET SORT_ORDER = (:SORT_ORDER + :I$MOVE) WHERE TYPE_ID = :I$TYPE_ID;
   END
   SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE TYPE_PARENTS_LIST (
    I$TYPE_ID BIGINT,
    I$LANG_CODE VARCHAR(2) = 'RU')
RETURNS (
    TYPE_ID BIGINT,
    TYPE_CAPTION VARCHAR(4000),
    CHILD_ID BIGINT,
    IS_ADD SMALLINT,
    IS_INTERNAL_ADD SMALLINT,
    IS_COPY SMALLINT,
    IS_CUT SMALLINT,
    IS_LINK SMALLINT,
    DO_FUNC SMALLINT,
    IS_FROM_LIST SMALLINT,
    RUN_SQL VARCHAR(1000),
    IS_AUTO_CREATE SMALLINT,
    TAB_ID BIGINT,
    IS_DEL SMALLINT)
AS
DECLARE VARIABLE RES_ID BIGINT;
BEGIN
   FOR SELECT P.TYPE_ID, P.CHILD_ID, P.IS_ADD, P.IS_INTERNAL_ADD, P.IS_COPY, P.IS_CUT, P.IS_LINK,
              P.DO_FUNC, P.IS_FROM_LIST, P.RUN_SQL, P.IS_AUTO_CREATE, P.TAB_ID, P.IS_DEL,
              T.RES_ID
       FROM PARENTS P
       INNER JOIN TYPES T ON T.TYPE_ID = P.TYPE_ID
       WHERE P.CHILD_ID = :I$TYPE_ID
       INTO :TYPE_ID, :CHILD_ID, :IS_ADD, :IS_INTERNAL_ADD, :IS_COPY, :IS_CUT, :IS_LINK,
            :DO_FUNC, :IS_FROM_LIST, :RUN_SQL, :IS_AUTO_CREATE, :TAB_ID, :IS_DEL, 
            :RES_ID
   DO BEGIN
      SELECT VAL FROM RES_GET(:RES_ID, :I$LANG_CODE) INTO :TYPE_CAPTION;
      SUSPEND;
   END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE TYPE_PARENT_ADD (
    I$TYPE_ID BIGINT,
    I$CHILD_ID BIGINT,
    I$IS_ADD SMALLINT,
    I$IS_INTERNAL_ADD SMALLINT,
    I$IS_COPY SMALLINT,
    I$IS_CUT SMALLINT,
    I$IS_LINK SMALLINT,
    I$DO_FUNC SMALLINT,
    I$IS_FROM_LIST SMALLINT,
    I$RUN_SQL VARCHAR(1000),
    I$IS_AUTO_CREATE SMALLINT,
    I$TAB_ID BIGINT,
    I$IS_DEL SMALLINT)
AS
BEGIN
    UPDATE OR INSERT INTO PARENTS (TYPE_ID, CHILD_ID, IS_ADD, IS_INTERNAL_ADD, IS_COPY, IS_CUT, IS_LINK,
                           DO_FUNC, IS_FROM_LIST, RUN_SQL, IS_AUTO_CREATE, TAB_ID, IS_DEL)
    VALUES (:I$TYPE_ID, :I$CHILD_ID, :I$IS_ADD, :I$IS_INTERNAL_ADD, :I$IS_COPY, :I$IS_CUT, :I$IS_LINK,
              :I$DO_FUNC, :I$IS_FROM_LIST, :I$RUN_SQL, :I$IS_AUTO_CREATE, :I$TAB_ID, :I$IS_DEL);
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UDOD_EMPLOYEE_LIST (
    I$SCHOOL_ID BIGINT = null)
RETURNS (
    EMPLOYEE_ID BIGINT)
AS
BEGIN
    FOR
        SELECT :I$SCHOOL_ID
        FROM RDB$DATABASE
        UNION ALL
        SELECT FIRST 1 OBJ_ID
        FROM LINKS
        WHERE PARENT_ID IS NULL AND OBJ_TYPE_ID = 2 AND DATE_DEL IS NULL
        INTO :I$SCHOOL_ID
    DO
    BEGIN
        FOR
            SELECT L14.OBJ_ID
            FROM LINKS L211
            JOIN LINKS L14 ON L14.PARENT_ID = L211.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
            WHERE L211.PARENT_ID = :I$SCHOOL_ID AND L211.OBJ_TYPE_ID = 211 AND L211.DATE_DEL IS NULL
            UNION
            SELECT L14.OBJ_ID
            FROM LINKS L14
            WHERE L14.PARENT_ID = :I$SCHOOL_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
            INTO :EMPLOYEE_ID
        DO
        BEGIN
            SUSPEND;
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UDOD_LOADING_UNION_LIST (
    I$STAGE_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    PARENT_ID BIGINT,
    OBJ_CAPTION VARCHAR(4000),
    SORT_ORDER DOUBLE PRECISION)
AS
declare variable V$OBJ_ID bigint;
BEGIN
    PARENT_ID = NULL;
    SELECT FIRST 1 OBJ_ID
    FROM OBJECT_PARENTS_GET(:I$STAGE_ID, 211)
    INTO :V$OBJ_ID;

    FOR
        SELECT DISTINCT
               O.OBJ_ID

        FROM OBJECT_CHILDREN_GET_DEEP(:V$OBJ_ID, 242, 2) O

        INTO :OBJ_ID
    DO
    BEGIN
        SELECT CAPTION, SORT_ORDER
        FROM OBJECT_CAPTION_GET(:OBJ_ID, NULL, NULL, :I$USER_ID)
        INTO :OBJ_CAPTION, :SORT_ORDER;

        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UDOD_PERSON_LIST (
    I$SCHOOL_ID BIGINT = null)
RETURNS (
    PERSON_ID BIGINT)
AS
BEGIN
    FOR
        SELECT :I$SCHOOL_ID
        FROM RDB$DATABASE

        UNION ALL

        SELECT FIRST 1
               OBJ_ID
        FROM LINKS

        WHERE PARENT_ID IS NULL
        AND OBJ_TYPE_ID = 2
        AND DATE_DEL IS NULL

        INTO :I$SCHOOL_ID
    DO
    BEGIN
        FOR
            SELECT L10.OBJ_ID
            FROM LINKS L242

            JOIN LINKS L243
            ON L243.PARENT_ID = L242.OBJ_ID
            AND L243.OBJ_TYPE_ID = 243
            AND L243.DATE_DEL IS NULL

            JOIN LINKS L10
            ON L10.PARENT_ID = L243.OBJ_ID
            AND L10.OBJ_TYPE_ID = 10
            AND L10.DATE_DEL IS NULL

            WHERE L242.PARENT_ID = :I$SCHOOL_ID
            AND L242.OBJ_TYPE_ID = 242
            AND L242.DATE_DEL IS NULL

            UNION

            SELECT L20.OBJ_ID
            FROM LINKS L242

            JOIN LINKS L243
            ON L243.PARENT_ID = L242.OBJ_ID
            AND L243.OBJ_TYPE_ID = 243
            AND L243.DATE_DEL IS NULL

            JOIN LINKS L10
            ON L10.PARENT_ID = L243.OBJ_ID
            AND L10.OBJ_TYPE_ID = 10
            AND L10.DATE_DEL IS NULL

            JOIN LINKS L20
            ON L20.PARENT_ID = L10.OBJ_ID
            AND L20.OBJ_TYPE_ID = 20
            AND L20.DATE_DEL IS NULL

            WHERE L242.PARENT_ID = :I$SCHOOL_ID
            AND L242.OBJ_TYPE_ID = 242
            AND L242.DATE_DEL IS NULL

            UNION

            SELECT L10.OBJ_ID
            FROM LINKS L211

            JOIN LINKS L242
            ON L242.PARENT_ID = L211.OBJ_ID
            AND L242.OBJ_TYPE_ID = 242
            AND L242.DATE_DEL IS NULL

            JOIN LINKS L243
            ON L243.PARENT_ID = L242.OBJ_ID
            AND L243.OBJ_TYPE_ID = 243
            AND L243.DATE_DEL IS NULL

            JOIN LINKS L10
            ON L10.PARENT_ID = L243.OBJ_ID
            AND L10.OBJ_TYPE_ID = 10
            AND L10.DATE_DEL IS NULL

            WHERE L211.PARENT_ID = :I$SCHOOL_ID
            AND L211.OBJ_TYPE_ID = 211
            AND L211.DATE_DEL IS NULL

            UNION

            SELECT L20.OBJ_ID
            FROM LINKS L211

            JOIN LINKS L242
            ON L242.PARENT_ID = L211.OBJ_ID
            AND L242.OBJ_TYPE_ID = 242
            AND L242.DATE_DEL IS NULL

            JOIN LINKS L243
            ON L243.PARENT_ID = L242.OBJ_ID
            AND L243.OBJ_TYPE_ID = 243
            AND L243.DATE_DEL IS NULL

            JOIN LINKS L10
            ON L10.PARENT_ID = L243.OBJ_ID
            AND L10.OBJ_TYPE_ID = 10
            AND L10.DATE_DEL IS NULL

            JOIN LINKS L20
            ON L20.PARENT_ID = L10.OBJ_ID
            AND L20.OBJ_TYPE_ID = 20
            AND L20.DATE_DEL IS NULL

            WHERE L211.PARENT_ID = :I$SCHOOL_ID
            AND L211.OBJ_TYPE_ID = 211
            AND L211.DATE_DEL IS NULL

            UNION

            SELECT L14.OBJ_ID
            FROM LINKS L211

            JOIN LINKS L14
            ON L14.PARENT_ID = L211.OBJ_ID
            AND L14.OBJ_TYPE_ID = 14
            AND L14.DATE_DEL IS NULL

            WHERE L211.PARENT_ID = :I$SCHOOL_ID
            AND L211.OBJ_TYPE_ID = 211
            AND L211.DATE_DEL IS NULL

            UNION

            SELECT L14.OBJ_ID
            FROM LINKS L14
            WHERE L14.PARENT_ID = :I$SCHOOL_ID
            AND L14.OBJ_TYPE_ID = 14
            AND L14.DATE_DEL IS NULL

            INTO :PERSON_ID

        DO
        BEGIN
            SUSPEND;
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UDOD_PUPIL_LIST (
    I$SCHOOL_ID BIGINT = null)
RETURNS (
    LINK_ID BIGINT,
    PUPIL_ID BIGINT,
    UNION_ID BIGINT,
    STAGE_ID BIGINT,
    LASTNAME VARCHAR(255),
    FIRSTNAME VARCHAR(255),
    MIDDLENAME VARCHAR(255),
    DOB DATE,
    ACCEPTEDDISTR VARCHAR(255),
    ACCEPTEDOOOD VARCHAR(255),
    ACCEPTEDTYPE VARCHAR(255))
AS
BEGIN
    FOR
        SELECT :I$SCHOOL_ID
        FROM RDB$DATABASE
        UNION ALL
        SELECT FIRST 1 OBJ_ID
        FROM LINKS
        WHERE PARENT_ID IS NULL AND OBJ_TYPE_ID = 2 AND DATE_DEL IS NULL
        INTO :I$SCHOOL_ID
    DO
    BEGIN
        FOR
            SELECT L10.LINK_ID, L10.OBJ_ID, L242.OBJ_ID, L243.OBJ_ID
            FROM LINKS L242
            JOIN LINKS L243 ON L243.PARENT_ID = L242.OBJ_ID AND L243.OBJ_TYPE_ID = 243 AND L243.DATE_DEL IS NULL
            JOIN LINKS L10 ON L10.PARENT_ID = L243.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
            WHERE L242.PARENT_ID = :I$SCHOOL_ID AND L242.OBJ_TYPE_ID = 242 AND L242.DATE_DEL IS NULL

            UNION

            SELECT L10.LINK_ID, L10.OBJ_ID, L242.OBJ_ID, L243.OBJ_ID
            FROM LINKS L211
            JOIN LINKS L242 ON L242.PARENT_ID = L211.OBJ_ID AND L242.OBJ_TYPE_ID = 242 AND L242.DATE_DEL IS NULL
            JOIN LINKS L243 ON L243.PARENT_ID = L242.OBJ_ID AND L243.OBJ_TYPE_ID = 243 AND L243.DATE_DEL IS NULL
            JOIN LINKS L10 ON L10.PARENT_ID = L243.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
            WHERE L211.PARENT_ID = :I$SCHOOL_ID AND L211.OBJ_TYPE_ID = 211 AND L211.DATE_DEL IS NULL

            INTO :LINK_ID, :PUPIL_ID, :UNION_ID, :STAGE_ID

        DO
        BEGIN
            FOR
                SELECT V55.VAL, V56.VAL, V57.VAL, IIF(V1345.LISTVAL_ID IS NULL, NULL, VL1345.V), V117.VAL, IIF(V2715.LISTVAL_ID IS NULL, NULL, VL2715.V), V89.VAL
                FROM VALS V55
                JOIN VALS V56 ON V56.OBJ_ID = V55.OBJ_ID AND V56.PARAM_ID = 56 AND V56.IS_DEL = 0
                LEFT JOIN VALS V57 ON V57.OBJ_ID = V55.OBJ_ID AND V57.PARAM_ID = 57 AND V57.IS_DEL = 0
                JOIN VALD V89 ON V89.OBJ_ID = V55.OBJ_ID AND V89.PARAM_ID = 89 AND V89.IS_DEL = 0
                LEFT JOIN VALS V117 ON V117.OBJ_ID = V55.OBJ_ID AND V117.PARAM_ID = 117 AND V117.IS_DEL = 0
                LEFT JOIN VALL V1345 ON V1345.OBJ_ID = V55.OBJ_ID AND V1345.PARAM_ID = 1345 AND V1345.IS_DEL = 0
                LEFT JOIN VAL_GET(V55.OBJ_ID, 1345) VL1345 ON 1=1
                LEFT JOIN VALL V2715 ON V2715.OBJ_ID = V55.OBJ_ID AND V2715.PARAM_ID = 2715 AND V2715.IS_DEL = 0
                LEFT JOIN VAL_GET(V55.OBJ_ID, 2715) VL2715 ON 1=1
                WHERE V55.OBJ_ID = :PUPIL_ID AND V55.PARAM_ID = 55 AND V55.IS_DEL = 0
                INTO :LASTNAME, :FIRSTNAME, :MIDDLENAME, :ACCEPTEDDISTR, :ACCEPTEDOOOD, :ACCEPTEDTYPE, :DOB
            DO
            BEGIN
                SUSPEND;
            END
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UDOD_PUPIL_TWINS_REPORT (
    I$SCHOOL_ID BIGINT = null)
RETURNS (
    LINK_ID BIGINT,
    OBJ_ID BIGINT,
    UNION_ID BIGINT,
    STAGE_ID BIGINT,
    UNION_NAME VARCHAR(255),
    STAGE_NAME VARCHAR(255),
    LASTNAME VARCHAR(255),
    FIRSTNAME VARCHAR(255),
    MIDDLENAME VARCHAR(255),
    DOB DATE,
    ACCEPTEDDISTR VARCHAR(255),
    ACCEPTEDOOOD VARCHAR(255),
    ACCEPTEDTYPE VARCHAR(255))
AS
BEGIN
    FOR
        SELECT DISTINCT
               P.LINK_ID,
               P.PUPIL_ID,
               P.UNION_ID,
               P.STAGE_ID,
               P.LASTNAME,
               P.FIRSTNAME,
               P.MIDDLENAME,
               P.ACCEPTEDDISTR,
               P.ACCEPTEDOOOD,
               P.ACCEPTEDTYPE,
               P.DOB
        FROM UDOD_PUPIL_LIST(:I$SCHOOL_ID) P
        JOIN UDOD_PUPIL_LIST(:I$SCHOOL_ID) P2 ON P2.PUPIL_ID <> P.PUPIL_ID
          AND P2.LASTNAME LIKE P.LASTNAME
          AND P2.FIRSTNAME LIKE P.FIRSTNAME
          AND ((P2.MIDDLENAME IS NULL) OR (P.MIDDLENAME IS NULL) OR (P2.MIDDLENAME LIKE P.MIDDLENAME))
          AND ((P.ACCEPTEDDISTR IS NULL) OR (P2.ACCEPTEDDISTR IS NULL) OR (P2.ACCEPTEDDISTR = P.ACCEPTEDDISTR))
          AND ((P.ACCEPTEDTYPE IS NULL) OR (P2.ACCEPTEDTYPE IS NULL) OR (P2.ACCEPTEDTYPE = P.ACCEPTEDTYPE))
          AND P2.DOB = P.DOB
        INTO :LINK_ID,
             :OBJ_ID,
             :UNION_ID,
             :STAGE_ID,
             :LASTNAME,
             :FIRSTNAME,
             :MIDDLENAME,
             :ACCEPTEDDISTR,
             :ACCEPTEDOOOD,
             :ACCEPTEDTYPE,
             :DOB
    DO
    BEGIN
        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:UNION_ID)
        INTO :UNION_NAME;

        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:STAGE_ID)
        INTO :STAGE_NAME;

        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UDOD_PUPIL_TWINS_UNITE (
    I$MAIN_PUPIL_ID BIGINT,
    I$ADD_PUPIL_ID BIGINT)
RETURNS (
    PUPIL_ID BIGINT)
AS
BEGIN
    PUPIL_ID = I$MAIN_PUPIL_ID;
    UPDATE VALS
    SET OBJ_ID = :I$MAIN_PUPIL_ID
    WHERE OBJ_ID = :I$ADD_PUPIL_ID
    AND IS_DEL = 0
    AND PARAM_ID NOT IN (SELECT PARAM_ID FROM VALS WHERE OBJ_ID = :I$MAIN_PUPIL_ID AND IS_DEL = 0);

    UPDATE VALL
    SET OBJ_ID = :I$MAIN_PUPIL_ID
    WHERE OBJ_ID = :I$ADD_PUPIL_ID
    AND IS_DEL = 0
    AND PARAM_ID NOT IN (SELECT PARAM_ID FROM VALL WHERE OBJ_ID = :I$MAIN_PUPIL_ID AND IS_DEL = 0);

    UPDATE VALD
    SET OBJ_ID = :I$MAIN_PUPIL_ID
    WHERE OBJ_ID = :I$ADD_PUPIL_ID
    AND IS_DEL = 0
    AND PARAM_ID NOT IN (SELECT PARAM_ID FROM VALD WHERE OBJ_ID = :I$MAIN_PUPIL_ID AND IS_DEL = 0);

    UPDATE VALT
    SET OBJ_ID = :I$MAIN_PUPIL_ID
    WHERE OBJ_ID = :I$ADD_PUPIL_ID
    AND IS_DEL = 0
    AND PARAM_ID NOT IN (SELECT PARAM_ID FROM VALT WHERE OBJ_ID = :I$MAIN_PUPIL_ID AND IS_DEL = 0);

    UPDATE VALDT
    SET OBJ_ID = :I$MAIN_PUPIL_ID
    WHERE OBJ_ID = :I$ADD_PUPIL_ID
    AND IS_DEL = 0
    AND PARAM_ID NOT IN (SELECT PARAM_ID FROM VALDT WHERE OBJ_ID = :I$MAIN_PUPIL_ID AND IS_DEL = 0);

    UPDATE VALR
    SET OBJ_ID = :I$MAIN_PUPIL_ID
    WHERE OBJ_ID = :I$ADD_PUPIL_ID
    AND IS_DEL = 0
    AND PARAM_ID NOT IN (SELECT PARAM_ID FROM VALR WHERE OBJ_ID = :I$MAIN_PUPIL_ID AND IS_DEL = 0);

    UPDATE VALI
    SET OBJ_ID = :I$MAIN_PUPIL_ID
    WHERE OBJ_ID = :I$ADD_PUPIL_ID
    AND IS_DEL = 0
    AND PARAM_ID NOT IN (SELECT PARAM_ID FROM VALI WHERE OBJ_ID = :I$MAIN_PUPIL_ID AND IS_DEL = 0);

    UPDATE VALA
    SET OBJ_ID = :I$MAIN_PUPIL_ID
    WHERE OBJ_ID = :I$ADD_PUPIL_ID
    AND IS_DEL = 0
    AND PARAM_ID NOT IN (SELECT PARAM_ID FROM VALA WHERE OBJ_ID = :I$MAIN_PUPIL_ID AND IS_DEL = 0);

    UPDATE VALB
    SET OBJ_ID = :I$MAIN_PUPIL_ID
    WHERE OBJ_ID = :I$ADD_PUPIL_ID
    AND IS_DEL = 0
    AND PARAM_ID NOT IN (SELECT PARAM_ID FROM VALB WHERE OBJ_ID = :I$MAIN_PUPIL_ID AND IS_DEL = 0);

    UPDATE VALDT
    SET OBJ_ID = :I$MAIN_PUPIL_ID
    WHERE OBJ_ID = :I$ADD_PUPIL_ID
    AND IS_DEL = 0
    AND PARAM_ID NOT IN (SELECT PARAM_ID FROM VALDT WHERE OBJ_ID = :I$MAIN_PUPIL_ID AND IS_DEL = 0);

    UPDATE VALF
    SET OBJ_ID = :I$MAIN_PUPIL_ID
    WHERE OBJ_ID = :I$ADD_PUPIL_ID
    AND IS_DEL = 0
    AND PARAM_ID NOT IN (SELECT PARAM_ID FROM VALF WHERE OBJ_ID = :I$MAIN_PUPIL_ID AND IS_DEL = 0);

    UPDATE LINKS
    SET PARENT_ID = :I$MAIN_PUPIL_ID
    WHERE PARENT_ID = :I$ADD_PUPIL_ID
    AND DATE_DEL IS NULL;

    UPDATE LINKS
    SET OBJ_ID = :I$MAIN_PUPIL_ID
    WHERE OBJ_ID = :I$ADD_PUPIL_ID
    AND DATE_DEL IS NULL;

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UDOD_TEACHER_LIST (
    I$OBJ_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    PARENT_ID BIGINT,
    OBJ_CAPTION VARCHAR(1000))
AS
declare variable V$SCHOOL_ID bigint;
BEGIN
    PARENT_ID = NULL;

    IF (I$OBJ_ID IS NULL) THEN
    BEGIN
        SELECT FIRST 1 OBJ_ID
        FROM LINKS L
        WHERE L.PARENT_ID IS NULL AND L.OBJ_TYPE_ID = 2 AND L.DATE_DEL IS NULL
        INTO :V$SCHOOL_ID;
    END
    ELSE
    BEGIN
        SELECT FIRST 1 OBJ_ID
        FROM OBJECT_PARENTS_GET(:I$OBJ_ID, 2)
        INTO :V$SCHOOL_ID;
    END

    FOR
        SELECT DISTINCT L14.OBJ_ID
        FROM LINKS L14
        JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
        JOIN LINKS L13 ON L13.OBJ_ID = L15.OBJ_ID AND L13.PARENT_TYPE_ID = 13 AND L13.DATE_DEL IS NULL
        JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0 AND V73.VAL <= CURRENT_DATE
        LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0 AND ((V74.VAL IS NULL) OR (V74.VAL >= CURRENT_DATE))

        WHERE L14.PARENT_ID IN (
            SELECT :V$SCHOOL_ID
            FROM RDB$DATABASE
            UNION
            -- Сотрудники подразделений УДОД
            SELECT L211.OBJ_ID
            FROM LINKS L211
            WHERE L211.PARENT_ID = :V$SCHOOL_ID AND L211.OBJ_TYPE_ID = 211 AND L211.DATE_DEL IS NULL)
        AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
        -- Фильтр только по педагогам - пока отключен
        --AND (SELECT SORT_ORDER FROM DO_FUNC(L13.PARENT_ID, 400)) = 2)

        INTO :OBJ_ID
    DO
    BEGIN
        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:OBJ_ID, NULL)
        INTO :OBJ_CAPTION;
        SUSPEND;
    END

END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UDOD_TRANSFER_STAGE_LIST (
    I$PUPIL_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    COLOR INTEGER,
    OBJ_CAPTION VARCHAR(4000),
    SORT_ORDER DOUBLE PRECISION)
AS
declare variable V$OBJ_ID bigint;
declare variable V$STRUCTURE_ID bigint;
declare variable V$UNION_ID bigint;
declare variable V$UNION_CAPTION varchar(1000);
declare variable V$SORT_ORDER double precision;
BEGIN
    V$SORT_ORDER = 0;
    FOR
        SELECT LP.OBJ_ID
        FROM OBJECT_PARENTS_GET(:I$PUPIL_ID, 2) LP

        UNION

        SELECT L211.OBJ_ID
        FROM OBJECT_PARENTS_GET(:I$PUPIL_ID, 2) LP
        JOIN LINKS L211
        ON L211.PARENT_ID = LP.OBJ_ID
        AND L211.OBJ_TYPE_ID = 211
        AND L211.DATE_DEL IS NULL

        UNION

        SELECT L211.OBJ_ID
        FROM LINKS LP

        JOIN LINKS LP78
        ON LP78.OBJ_ID = LP.PARENT_ID
        AND LP78.PARENT_TYPE_ID = 78
        AND LP78.DATE_DEL IS NULL

        JOIN LINKS LP2
        ON LP2.OBJ_ID = LP78.PARENT_ID
        AND LP2.PARENT_TYPE_ID = 2
        AND LP2.DATE_DEL IS NULL

        JOIN LINKS L211
        ON L211.PARENT_ID = LP2.PARENT_ID
        AND L211.OBJ_TYPE_ID = 211
        AND L211.DATE_DEL IS NULL

        WHERE LP.OBJ_ID = :I$PUPIL_ID
        AND LP.PARENT_TYPE_ID IN (81, 82, 83)
        AND LP.DATE_DEL IS NULL

        INTO   :V$STRUCTURE_ID
    DO
    BEGIN
        FOR
            SELECT L242.OBJ_ID
            FROM LINKS L242

            WHERE L242.PARENT_ID = :V$STRUCTURE_ID
            AND L242.OBJ_TYPE_ID = 242
            AND L242.DATE_DEL IS NULL

            INTO :V$UNION_ID
        DO
        BEGIN
            V$SORT_ORDER = V$SORT_ORDER + 1;
            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:V$UNION_ID, NULL,  NULL, :I$USER_ID)
            INTO :V$UNION_CAPTION;

            FOR
                SELECT L243.OBJ_ID,
                       T243.COLOR
                FROM LINKS L243

                JOIN TYPES T243
                ON T243.TYPE_ID = L243.OBJ_TYPE_ID

                WHERE L243.PARENT_ID = :V$UNION_ID
                AND L243.OBJ_TYPE_ID = 243
                AND L243.DATE_DEL IS NULL

                INTO :OBJ_ID,
                     :COLOR
            DO
            BEGIN
                SELECT :V$UNION_CAPTION || ' - ' || CAPTION, :V$SORT_ORDER * 100 + SORT_ORDER
                FROM OBJECT_CAPTION_GET(:OBJ_ID, NULL,  NULL, :I$USER_ID)
                INTO :OBJ_CAPTION, :SORT_ORDER;

                SUSPEND;
            END
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UDOD_YEAR_CHANGER_PUPIL_LIST (
    I$UNION_ID BIGINT)
RETURNS (
    PUPIL_ID BIGINT,
    FIO VARCHAR(1000),
    STAGE_ID BIGINT,
    STAGE_CAPTION VARCHAR(255),
    DISABLED SMALLINT,
    MOVE_DATE DATE)
AS
declare variable V$YEAR_START date;
BEGIN
    -- Не учебный, а календарный год
    V$YEAR_START = '01.01.' || EXTRACT(YEAR FROM CURRENT_DATE);

    FOR
        -- Список всех учеников объединения (внимание: теоретически при сбоях ученика может занести в несколько этапов обучения)
        SELECT L10.OBJ_ID, L243.OBJ_ID
        FROM LINKS L243
        JOIN LINKS L10 ON L10.PARENT_ID = L243.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        LEFT JOIN VALS V55 ON V55.OBJ_ID = L10.OBJ_ID AND V55.PARAM_ID = 55 AND V55.IS_DEL = 0
        LEFT JOIN VALS V56 ON V56.OBJ_ID = L10.OBJ_ID AND V56.PARAM_ID = 56 AND V56.IS_DEL = 0
        WHERE L243.PARENT_ID = :I$UNION_ID AND L243.OBJ_TYPE_ID = 243 AND L243.DATE_DEL IS NULL
        ORDER BY V55.VAL, V56.VAL
        INTO :PUPIL_ID, :STAGE_ID
    DO
    BEGIN
        SELECT CAPTION FROM OBJECT_CAPTION_GET(:PUPIL_ID) INTO :FIO;
        SELECT CAPTION FROM OBJECT_CAPTION_GET(:STAGE_ID) INTO :STAGE_CAPTION;

        DISABLED = 0;
        MOVE_DATE = NULL;

        -- #1826 Если в этом году уже переводили на следующий этап обучения, то больше нельзя
        -- Исправление #1922 - проверка идет только в этом объединении !

        SELECT FIRST 1 1, M.DATE_IN
        FROM PERSON_MOVEMENTS M
        JOIN OBJECTS O ON O.OBJ_ID = M.GROUP_ID AND O.TYPE_ID = 243
        WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :PUPIL_ID AND M.REASON_IN = 11397 AND M.DATE_IN >= :V$YEAR_START
        ORDER BY M.DATE_IN DESC
        INTO :DISABLED, :MOVE_DATE;

        DISABLED = COALESCE(DISABLED, 0);

        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UDOD_YEAR_CHANGER_PUPIL_MOVE (
    I$PUPIL_ID BIGINT,
    I$STAGE_ID BIGINT,
    I$UNION_ID BIGINT,
    I$MOVEMENT_DATE DATE,
    I$ORDER_NUMBER VARCHAR(255),
    I$ORDER_DATE DATE,
    I$OPERATION SMALLINT)
AS
declare variable V$STAGE_NUMBER smallint;
declare variable V$NEXT_STAGE_ID bigint;
declare variable V$NEXT_STAGE_INDEX bigint;
declare variable V$MOVEMENT_TYPE_ID bigint;
declare variable V$BLOB_ID bigint;
BEGIN
    SELECT LV2114.COST
    FROM VALL V2114
    JOIN LISTVALS LV2114 ON LV2114.LISTVAL_ID = V2114.LISTVAL_ID
    WHERE V2114.OBJ_ID = :I$STAGE_ID AND V2114.PARAM_ID = 2114 AND V2114.IS_DEL = 0
    INTO :V$STAGE_NUMBER;

    IF((V$STAGE_NUMBER IS NOT NULL) AND (V$STAGE_NUMBER = 11)) THEN I$OPERATION = 2;

    SELECT FIRST 1 LV.LISTVAL_ID
    FROM LISTVALS LV
    WHERE LV.LIST_ID = 25 AND PARENT_ID = 2143 AND COST = :V$STAGE_NUMBER + 1
    INTO :V$NEXT_STAGE_INDEX;

    SELECT FIRST 1 L243.OBJ_ID
    FROM LINKS L243
    JOIN VALL V2114 ON V2114.OBJ_ID = L243.OBJ_ID AND V2114.PARAM_ID = 2114 AND V2114.IS_DEL = 0 AND V2114.LISTVAL_ID = :V$NEXT_STAGE_INDEX
    WHERE L243.PARENT_ID = :I$UNION_ID AND L243.OBJ_TYPE_ID = 243 AND L243.DATE_DEL IS NULL AND L243.OBJ_ID <> :I$STAGE_ID
    INTO :V$NEXT_STAGE_ID;

    -- Выбываем со старого этапа в любом случае
    IF(I$OPERATION = 1) THEN V$MOVEMENT_TYPE_ID = 11397;
    ELSE IF(V$NEXT_STAGE_ID IS NULL) THEN V$MOVEMENT_TYPE_ID = 5549;
    ELSE V$MOVEMENT_TYPE_ID = 5548;
    SELECT OBJ_ID FROM VARGRP_MOVE_PUPIL(:I$PUPIL_ID, :I$STAGE_ID, :I$ORDER_NUMBER, :I$ORDER_DATE, :I$MOVEMENT_DATE, 1, NULL, NULL, :V$MOVEMENT_TYPE_ID) INTO :V$BLOB_ID;

    -- Удаляем ученика из всех подгрупп старого этапа обучения
    -- Актуально только для перевода летом 2021. Реестра движения для подгрупп нет
    FOR
        SELECT L10.LINK_ID
        FROM LINKS L243
        JOIN LINKS L47 ON L47.PARENT_ID = L243.OBJ_ID AND L47.OBJ_TYPE_ID = 47 AND L47.DATE_DEL IS NULL
        JOIN LINKS L48 ON L48.PARENT_ID = L47.OBJ_ID AND L48.OBJ_TYPE_ID = 48 AND L48.DATE_DEL IS NULL
        JOIN LINKS L10 ON L10.PARENT_ID = L48.OBJ_ID AND L10.OBJ_ID = :I$PUPIL_ID AND L10.DATE_DEL IS NULL
        WHERE L243.PARENT_ID = :I$UNION_ID AND L243.OBJ_TYPE_ID = 243 AND L243.DATE_DEL IS NULL
        INTO :V$BLOB_ID
    DO
    BEGIN
        UPDATE LINKS
        SET DATE_DEL = CURRENT_TIMESTAMP
        WHERE LINK_ID = :V$BLOB_ID AND DATE_DEL IS NULL;
    END

    IF (I$OPERATION = 1) THEN
    BEGIN
        -- Перевод на следующий этап
        IF (V$NEXT_STAGE_ID IS NULL) THEN
        BEGIN
            SELECT OBJ_ID FROM OBJECT_ADD(:I$UNION_ID, 243) INTO :V$NEXT_STAGE_ID;
            SELECT BLOB_ID FROM VAL_ADD(2114, :V$NEXT_STAGE_ID, :V$NEXT_STAGE_INDEX) INTO :V$BLOB_ID;
        END

        SELECT OBJ_ID FROM VARGRP_MOVE_PUPIL(:I$PUPIL_ID, :V$NEXT_STAGE_ID, :I$ORDER_NUMBER, :I$ORDER_DATE, :I$MOVEMENT_DATE, 0, NULL, NULL, 11397) INTO :V$BLOB_ID;
    END

END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UNDO_GPD_MOVEMENT (
    I$GUP_ID BIGINT,
    I$PUPIL_ID BIGINT)
RETURNS (
    X SMALLINT,
    OBJ_ID BIGINT,
    OBJ_CAPTION VARCHAR(4000))
AS
declare variable V$LAST_MOVE_DATE date;
declare variable V$LAST_MOVE_TYPE bigint;
declare variable V$HAS_MARKS smallint;
declare variable V$MOVE_ID bigint;
BEGIN

    -- Тут надо переделывать, функция используется на кнопке в ГПД-ДО
    -- X: 0 если нельзя отменить, 1 если можно отменить
    -- В перспективе функцию вообще прибить и оставить только вызов VARGRP*

    /*SELECT X, OBJ_ID, OBJ_CAPTION
    FROM UNDO_GUP_MOVEMENT(:I$GUP_ID, :I$PUPIL_ID)
    INTO :X, :OBJ_ID, :OBJ_CAPTION;*/

    SUSPEND;

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UNI_STRING_COMPARE (
    S1 VARCHAR(4000),
    S2 VARCHAR(4000))
RETURNS (
    RESULT SMALLINT)
AS
BEGIN
    RESULT = 0;

    -- меняем символы русского алфавита на латинские
    S1 = UPPER (S1);
    SELECT REPLACE(:S1, 'А', 'A')
    FROM RDB$DATABASE
    INTO :S1;
    SELECT REPLACE(:S1, 'В', 'B')
    FROM RDB$DATABASE
    INTO :S1;
    SELECT REPLACE(:S1, 'Е', 'E')
    FROM RDB$DATABASE
    INTO :S1;
    SELECT REPLACE(:S1, 'К', 'K')
    FROM RDB$DATABASE
    INTO :S1;
    SELECT REPLACE(:S1, 'М', 'M')
    FROM RDB$DATABASE
    INTO :S1;
    SELECT REPLACE(:S1, 'Н', 'H')
    FROM RDB$DATABASE
    INTO :S1;
    SELECT REPLACE(:S1, 'О', 'O')
    FROM RDB$DATABASE
    INTO :S1;
    SELECT REPLACE(:S1, 'Р', 'P')
    FROM RDB$DATABASE
    INTO :S1;
    SELECT REPLACE(:S1, 'С', 'C')
    FROM RDB$DATABASE
    INTO :S1;
    SELECT REPLACE(:S1, 'Т', 'T')
    FROM RDB$DATABASE
    INTO :S1;
    SELECT REPLACE(:S1, 'Х', 'X')
    FROM RDB$DATABASE
    INTO :S1;

    S2 = UPPER (S2);
    SELECT REPLACE(:S2, 'А', 'A')
    FROM RDB$DATABASE
    INTO :S2;
    SELECT REPLACE(:S2, 'В', 'B')
    FROM RDB$DATABASE
    INTO :S2;
    SELECT REPLACE(:S2, 'Е', 'E')
    FROM RDB$DATABASE
    INTO :S2;
    SELECT REPLACE(:S2, 'К', 'K')
    FROM RDB$DATABASE
    INTO :S2;
    SELECT REPLACE(:S2, 'М', 'M')
    FROM RDB$DATABASE
    INTO :S2;
    SELECT REPLACE(:S2, 'Н', 'H')
    FROM RDB$DATABASE
    INTO :S2;
    SELECT REPLACE(:S2, 'О', 'O')
    FROM RDB$DATABASE
    INTO :S2;
    SELECT REPLACE(:S2, 'Р', 'P')
    FROM RDB$DATABASE
    INTO :S2;
    SELECT REPLACE(:S2, 'С', 'C')
    FROM RDB$DATABASE
    INTO :S2;
    SELECT REPLACE(:S2, 'Т', 'T')
    FROM RDB$DATABASE
    INTO :S2;
    SELECT REPLACE(:S2, 'Х', 'X')
    FROM RDB$DATABASE
    INTO :S2;

    IF (S1 = S2) THEN RESULT = 1;

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UPDATE_4LINKS (
    I$OBJ_ID BIGINT)
RETURNS (
    LINK_ID BIGINT,
    PARENT_ID BIGINT,
    OBJ_ID BIGINT,
    REASON_ID BIGINT,
    LISTVAL_ID BIGINT,
    USER_ID BIGINT,
    DATE_INS TIMESTAMP,
    DATE_DEL TIMESTAMP,
    COST FLOAT,
    IS_REPL SMALLINT)
AS
BEGIN
    IS_REPL = 0;
    USER_ID = NULL;
    LISTVAL_ID = NULL;
    COST = 0;

    FOR
        SELECT L.LINK_ID, L.PARENT_ID, L.OBJ_ID, L.REASON_ID, L.DATE_INS, L.DATE_DEL
        FROM LINKS L
        WHERE L.PARENT_ID = :I$OBJ_ID
        INTO :LINK_ID, :PARENT_ID, :OBJ_ID, :REASON_ID, :DATE_INS, :DATE_DEL
    DO
    BEGIN
        SUSPEND;
        FOR
            SELECT LINK_ID, PARENT_ID, OBJ_ID, REASON_ID, DATE_INS, DATE_DEL
            FROM UPDATE_4LINKS(:OBJ_ID)
            INTO :LINK_ID, :PARENT_ID, :OBJ_ID, :REASON_ID, :DATE_INS, :DATE_DEL
        DO
        BEGIN
            SUSPEND;
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UPDATE_4LISTVALS (
    I$OBJ_ID BIGINT)
RETURNS (
    LISTVAL_ID BIGINT,
    LIST_ID BIGINT,
    PARENT_ID BIGINT,
    RES_ID BIGINT,
    TAG VARCHAR(100),
    SORT_ORDER SMALLINT,
    COST FLOAT,
    IS_REPL SMALLINT,
    IS_DEL SMALLINT)
AS
declare variable G bigint;
declare variable M bigint;
declare variable L char(1);
BEGIN
    IS_REPL = 0;

    SELECT GEN, MULTIPLIER FROM GEN INTO :G, :M;

    SELECT K.KEY_VAL FROM KEYS K WHERE K.KEY_CODE = 'LEVEL' INTO :L;

    FOR
        SELECT
            LV.LISTVAL_ID,
            LV.LIST_ID,
            LV.PARENT_ID,
            R.RES_ID,
            LV.TAG,
            LV.SORT_ORDER,
            LV.COST,
            LV.IS_DEL
        FROM LISTVALS LV

        JOIN RES R
        ON R.RES_ID = LV.RES_ID
        AND R.LANG_CODE = 'RU'

        JOIN LISTS L
        ON L.LIST_ID = LV.LIST_ID

        WHERE L.FOR_REPL_DOWN = 1
        INTO :LISTVAL_ID,
            :LIST_ID,
            :PARENT_ID,
            :RES_ID,
            :TAG,
            :SORT_ORDER,
            :COST,
            :IS_DEL
    DO BEGIN
        IF ((L = '2') OR (L = '3') OR ((LISTVAL_ID / M) = G))  THEN SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UPDATE_4OBJECTS (
    I$OBJ_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    TYPE_ID BIGINT,
    IS_REPL SMALLINT)
AS
BEGIN
    IS_REPL = 0;
    FOR
        SELECT O.OBJ_ID,
               O.TYPE_ID
        FROM OBJECT_TREE(:I$OBJ_ID) L
        INNER JOIN OBJECTS O
        ON O.OBJ_ID = L.OBJ_ID
        INTO
              :OBJ_ID,
              :TYPE_ID
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UPDATE_4RES (
    I$OBJ_ID BIGINT)
RETURNS (
    RES_ID BIGINT,
    LANG_CODE CHAR(2),
    VAL VARCHAR(4000),
    VAL_LONG VARCHAR(4000),
    IS_REPL SMALLINT,
    IS_DEL SMALLINT)
AS
declare variable LISTVAL_ID bigint;
declare variable G bigint;
declare variable M bigint;
declare variable L char(1);
BEGIN
    IS_REPL = 0;

    -- Перенесено из EXPORT_OBJECTS для исключения дублирующих операций
    EXECUTE PROCEDURE RSOKO_CALC_PUPIL_ABSENCES_COUNT;

    SELECT GEN, MULTIPLIER FROM GEN INTO :G, :M;
    SELECT K.KEY_VAL FROM KEYS K WHERE K.KEY_CODE = 'LEVEL' INTO :L;

    FOR
        SELECT LV.LISTVAL_ID, R.RES_ID, R.LANG_CODE, R.VAL, R.VAL_LONG, R.IS_DEL
        FROM LISTVALS LV
        JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
        JOIN LISTS L ON L.LIST_ID = LV.LIST_ID
        WHERE L.FOR_REPL_DOWN = 1
        INTO :LISTVAL_ID, :RES_ID, :LANG_CODE, :VAL, :VAL_LONG, :IS_DEL
    DO BEGIN
        IF ((L = '2') OR (L = '3') OR ((LISTVAL_ID / M) = G))  THEN SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UPDATE_4VALA (
    I$OBJ_ID BIGINT)
RETURNS (
    PARAM_ID BIGINT,
    OBJ_ID BIGINT,
    USER_ID BIGINT,
    IS_REPL SMALLINT,
    IS_DEL SMALLINT,
    REGION VARCHAR(255),
    DISTRICT VARCHAR(255),
    TOWN VARCHAR(255),
    SETTLEMENT VARCHAR(255),
    STREET VARCHAR(255),
    HOUSE VARCHAR(10),
    LITER VARCHAR(10),
    CORP VARCHAR(10),
    FLAT VARCHAR(10),
    POST_INDEX VARCHAR(20),
    OCATD VARCHAR(11),
    FIAS_UID VARCHAR(36),
    STREET_UID VARCHAR(36))
AS
declare variable I integer;
BEGIN
    IS_REPL = 0;
    I = 0;

    SELECT COUNT(*)
    FROM PARAMS P
    WHERE P.PARAM_TYPE = 18
      AND P.FOR_REPL_DOWN = 1
      AND P.IS_DEL = 0
    INTO :I;

    IF (I = 0) THEN
        EXIT;

    FOR
        SELECT V.PARAM_ID, V.OBJ_ID, NULL, V.IS_DEL, V.REGION, V.DISTRICT, V.TOWN, V.SETTLEMENT, V.STREET, V.HOUSE, V.LITER, V.CORP, V.FLAT, V.POST_INDEX, V.OCATD, V.FIAS_UID, V.STREET_UID
        FROM VALA V
        JOIN PARAMS P ON P.PARAM_ID = V.PARAM_ID
        JOIN OBJECT_TREE(:I$OBJ_ID) E ON E.OBJ_ID = V.OBJ_ID
        WHERE P.PARAM_TYPE = 18 AND P.FOR_REPL_DOWN = 1
        INTO :PARAM_ID, :OBJ_ID, :USER_ID, :IS_DEL, :REGION, :DISTRICT, :TOWN, :SETTLEMENT, :STREET, :HOUSE, :LITER, :CORP, :FLAT, :POST_INDEX, :OCATD, :FIAS_UID, :STREET_UID
    DO
    BEGIN
        SUSPEND;
    END

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UPDATE_4VALB (
    I$OBJ_ID BIGINT)
RETURNS (
    PARAM_ID BIGINT,
    OBJ_ID BIGINT,
    USER_ID BIGINT,
    IS_REPL SMALLINT,
    IS_DEL SMALLINT,
    VAL VARCHAR(4000),
    BLOB_ID BIGINT)
AS
DECLARE VARIABLE I INTEGER;
BEGIN
    IS_REPL = 0;
    I = 0;

    SELECT COUNT(*)
    FROM PARAMS P
    WHERE P.PARAM_TYPE IN (11,12)
      AND P.FOR_REPL_DOWN = 1
      AND P.IS_DEL = 0
    INTO :I;

    IF (I = 0) THEN
        EXIT;

    FOR SELECT V.PARAM_ID, V.OBJ_ID, NULL, V.IS_DEL, V.VAL, V.BLOB_ID
        FROM VALB V
        INNER JOIN PARAMS P ON P.PARAM_ID = V.PARAM_ID
        INNER JOIN OBJECT_TREE(:I$OBJ_ID) E ON E.OBJ_ID = V.OBJ_ID
        WHERE P.FOR_REPL_DOWN = 1
        INTO :PARAM_ID, :OBJ_ID, :USER_ID, :IS_DEL, :VAL, :BLOB_ID
    DO
    BEGIN
        SUSPEND;
    END

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UPDATE_4VALD (
    I$OBJ_ID BIGINT)
RETURNS (
    PARAM_ID BIGINT,
    OBJ_ID BIGINT,
    USER_ID BIGINT,
    IS_REPL SMALLINT,
    IS_DEL SMALLINT,
    VAL DATE)
AS
DECLARE VARIABLE I INTEGER;
BEGIN
    IS_REPL = 0;
    I = 0;

    SELECT COUNT(*)
    FROM PARAMS P
    WHERE P.PARAM_TYPE = 4
      AND P.FOR_REPL_DOWN = 1
      AND P.IS_DEL = 0
    INTO :I;

    IF (I = 0) THEN
        EXIT;

    FOR SELECT V.PARAM_ID, V.OBJ_ID, NULL, V.IS_DEL, V.VAL
        FROM VALD V
        INNER JOIN PARAMS P ON P.PARAM_ID = V.PARAM_ID
        INNER JOIN OBJECT_TREE(:I$OBJ_ID) E ON E.OBJ_ID = V.OBJ_ID
        WHERE P.PARAM_TYPE = 4
          AND P.FOR_REPL_DOWN = 1
        INTO :PARAM_ID, :OBJ_ID, :USER_ID, :IS_DEL, :VAL
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UPDATE_4VALDT (
    I$OBJ_ID BIGINT)
RETURNS (
    PARAM_ID BIGINT,
    OBJ_ID BIGINT,
    USER_ID BIGINT,
    IS_REPL SMALLINT,
    IS_DEL SMALLINT,
    VAL TIMESTAMP)
AS
DECLARE VARIABLE I INTEGER;
BEGIN
    IS_REPL = 0;
    I = 0;

    SELECT COUNT(*)
    FROM PARAMS P
    WHERE P.PARAM_TYPE = 3
      AND P.FOR_REPL_DOWN = 1
      AND P.IS_DEL = 0
    INTO :I;

    IF (I = 0) THEN
        EXIT;

    FOR SELECT V.PARAM_ID, V.OBJ_ID, NULL, V.IS_DEL, V.VAL
        FROM VALDT V
        INNER JOIN PARAMS P ON P.PARAM_ID = V.PARAM_ID
        INNER JOIN OBJECT_TREE(:I$OBJ_ID) E ON E.OBJ_ID = V.OBJ_ID
        WHERE P.PARAM_TYPE = 3
          AND P.FOR_REPL_DOWN = 1
        INTO :PARAM_ID, :OBJ_ID, :USER_ID, :IS_DEL, :VAL
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UPDATE_4VALF (
    I$OBJ_ID BIGINT)
RETURNS (
    PARAM_ID BIGINT,
    OBJ_ID BIGINT,
    USER_ID BIGINT,
    IS_REPL SMALLINT,
    IS_DEL SMALLINT,
    VAL DOUBLE PRECISION)
AS
DECLARE VARIABLE I INTEGER;
BEGIN
    IS_REPL = 0;
    I = 0;

    SELECT COUNT(*)
    FROM PARAMS P
    WHERE P.PARAM_TYPE = 2
      AND P.FOR_REPL_DOWN = 1
      AND P.IS_DEL = 0
    INTO :I;

    IF (I = 0) THEN
        EXIT;

    FOR SELECT V.PARAM_ID, V.OBJ_ID, NULL, V.IS_DEL, V.VAL
        FROM VALF V
        INNER JOIN PARAMS P ON P.PARAM_ID = V.PARAM_ID
        INNER JOIN OBJECT_TREE(:I$OBJ_ID) E ON E.OBJ_ID = V.OBJ_ID
        WHERE P.PARAM_TYPE = 2
          AND P.FOR_REPL_DOWN = 1
        INTO :PARAM_ID, :OBJ_ID, :USER_ID, :IS_DEL, :VAL
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UPDATE_4VALI (
    I$OBJ_ID BIGINT)
RETURNS (
    PARAM_ID BIGINT,
    OBJ_ID BIGINT,
    USER_ID BIGINT,
    IS_REPL SMALLINT,
    IS_DEL SMALLINT,
    VAL INTEGER)
AS
DECLARE VARIABLE I INTEGER;
BEGIN
    IS_REPL = 0;
    I = 0;

    SELECT COUNT(*)
    FROM PARAMS P
    WHERE P.PARAM_TYPE = 1
      AND P.FOR_REPL_DOWN = 1
      AND P.IS_DEL = 0
    INTO :I;

    IF (I = 0) THEN
        EXIT;

    FOR SELECT V.PARAM_ID, V.OBJ_ID, NULL, V.IS_DEL, V.VAL
        FROM VALI V
        INNER JOIN PARAMS P ON P.PARAM_ID = V.PARAM_ID
        INNER JOIN OBJECT_TREE(:I$OBJ_ID) E ON E.OBJ_ID = V.OBJ_ID
        WHERE P.PARAM_TYPE = 1
          AND P.FOR_REPL_DOWN = 1
        INTO :PARAM_ID, :OBJ_ID, :USER_ID, :IS_DEL, :VAL
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UPDATE_4VALL (
    I$OBJ_ID BIGINT)
RETURNS (
    PARAM_ID BIGINT,
    OBJ_ID BIGINT,
    USER_ID BIGINT,
    IS_REPL SMALLINT,
    IS_DEL SMALLINT,
    LISTVAL_ID BIGINT)
AS
DECLARE VARIABLE I INTEGER;
BEGIN
    IS_REPL = 0;
    I = 0;

    SELECT COUNT(*)
    FROM PARAMS P
    WHERE P.PARAM_TYPE = 6
      AND P.FOR_REPL_DOWN = 1
      AND P.IS_DEL = 0
    INTO :I;

    IF (I = 0) THEN
        EXIT;

    FOR SELECT V.PARAM_ID, V.OBJ_ID, NULL, V.IS_DEL, V.LISTVAL_ID
        FROM VALL V
        INNER JOIN PARAMS P ON P.PARAM_ID = V.PARAM_ID
        INNER JOIN OBJECT_TREE(:I$OBJ_ID) E ON E.OBJ_ID = V.OBJ_ID
        WHERE P.PARAM_TYPE = 6
          AND P.FOR_REPL_DOWN = 1
        INTO :PARAM_ID, :OBJ_ID, :USER_ID, :IS_DEL, :LISTVAL_ID
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UPDATE_4VALR (
    I$OBJ_ID BIGINT)
RETURNS (
    PARAM_ID BIGINT,
    OBJ_ID BIGINT,
    USER_ID BIGINT,
    IS_REPL SMALLINT,
    IS_DEL SMALLINT,
    VAL BIGINT)
AS
DECLARE VARIABLE I INTEGER;
BEGIN
    IS_REPL = 0;
    I = 0;

    SELECT COUNT(*)
    FROM PARAMS P
    WHERE P.PARAM_TYPE = 13
      AND P.FOR_REPL_DOWN = 1
      AND P.IS_DEL = 0
    INTO :I;

    IF (I = 0) THEN
        EXIT;

    FOR SELECT V.PARAM_ID, V.OBJ_ID, NULL, V.IS_DEL, V.VAL
        FROM VALR V
        INNER JOIN PARAMS P ON P.PARAM_ID = V.PARAM_ID
        INNER JOIN OBJECT_TREE(:I$OBJ_ID) E ON E.OBJ_ID = V.OBJ_ID
        WHERE P.PARAM_TYPE = 13 AND P.FOR_REPL_DOWN = 1
        INTO :PARAM_ID, :OBJ_ID, :USER_ID, :IS_DEL, :VAL
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UPDATE_4VALS (
    I$OBJ_ID BIGINT)
RETURNS (
    PARAM_ID BIGINT,
    OBJ_ID BIGINT,
    USER_ID BIGINT,
    IS_REPL SMALLINT,
    IS_DEL SMALLINT,
    VAL VARCHAR(4000))
AS
DECLARE VARIABLE I INTEGER;
BEGIN
    IS_REPL = 0;
    I = 0;

    SELECT COUNT(*)
    FROM PARAMS P
    WHERE P.PARAM_TYPE IN (8, 9, 10) AND P.FOR_REPL_DOWN = 1 AND P.IS_DEL = 0
    INTO :I;

    IF (I = 0) THEN
        EXIT;

    FOR
        SELECT V.PARAM_ID, V.OBJ_ID, NULL, V.IS_DEL, V.VAL
        FROM VALS V
        JOIN PARAMS P ON P.PARAM_ID = V.PARAM_ID
        JOIN OBJECT_TREE(:I$OBJ_ID) E ON E.OBJ_ID = V.OBJ_ID
        WHERE P.FOR_REPL_DOWN = 1
        INTO :PARAM_ID, :OBJ_ID, :USER_ID, :IS_DEL, :VAL
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UPDATE_4VALT (
    I$OBJ_ID BIGINT)
RETURNS (
    PARAM_ID BIGINT,
    OBJ_ID BIGINT,
    USER_ID BIGINT,
    IS_REPL SMALLINT,
    IS_DEL SMALLINT,
    VAL TIME)
AS
DECLARE VARIABLE I INTEGER;
BEGIN
    IS_REPL = 0;
    I = 0;

    SELECT COUNT(*)
    FROM PARAMS P
    WHERE P.PARAM_TYPE = 5 AND P.FOR_REPL_DOWN = 1 AND P.IS_DEL = 0
    INTO :I;

    IF (I = 0) THEN
        EXIT;

    FOR
        SELECT V.PARAM_ID, V.OBJ_ID, NULL, V.IS_DEL, V.VAL
        FROM VALT V
        JOIN PARAMS P ON P.PARAM_ID = V.PARAM_ID
        JOIN OBJECT_TREE(:I$OBJ_ID) E ON E.OBJ_ID = V.OBJ_ID
        WHERE P.PARAM_TYPE = 5 AND P.FOR_REPL_DOWN = 1
        INTO :PARAM_ID, :OBJ_ID, :USER_ID, :IS_DEL, :VAL
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UPDATE_CHECK_PLAN (
    I$OBJ_ID BIGINT,
    I$NEW SMALLINT,
    I$USER_ID VARCHAR(40) = NULL)
AS
DECLARE VARIABLE V$YEAR_ID BIGINT;
DECLARE VARIABLE V$GRADE_ID BIGINT;
DECLARE VARIABLE V$GRADE_NAME VARCHAR(200);
DECLARE VARIABLE V$STAGE_ID BIGINT;
DECLARE VARIABLE V$SUBJECT_ID BIGINT;
DECLARE VARIABLE V$CJ_ID BIGINT;
DECLARE VARIABLE V$PTP_ID BIGINT;
DECLARE VARIABLE N INTEGER;
DECLARE VARIABLE V$PTP_LESSON_ID BIGINT;
DECLARE VARIABLE V$CT BIGINT;
DECLARE VARIABLE V$LESSON_DATE DATE;
DECLARE VARIABLE V$LESSON_NUM INTEGER;
DECLARE VARIABLE V$LAST_DATE DATE;
DECLARE VARIABLE V$LAST_NUM INTEGER;
DECLARE VARIABLE V$PERIOD_ID BIGINT;
DECLARE VARIABLE V$LAST_INDEX INTEGER;
DECLARE VARIABLE V$PREV_PERIOD BIGINT;
DECLARE VARIABLE V$FIRST_DATE DATE;
DECLARE VARIABLE V$END_DATE DATE;
DECLARE VARIABLE V$DD DATE;
DECLARE VARIABLE V$DN SMALLINT;
DECLARE VARIABLE V$NW SMALLINT;
DECLARE VARIABLE V$NN SMALLINT;
DECLARE VARIABLE V$WEEK SMALLINT;
DECLARE VARIABLE V$CS1 DATE;
DECLARE VARIABLE V$CE1 DATE;
DECLARE VARIABLE V$CS2 DATE;
DECLARE VARIABLE V$CE2 DATE;
DECLARE VARIABLE V$CS3 DATE;
DECLARE VARIABLE V$CE3 DATE;
DECLARE VARIABLE V$CS4 DATE;
DECLARE VARIABLE V$CE4 DATE;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$DT TIMESTAMP;
DECLARE VARIABLE V$OLD_DATE DATE;
DECLARE VARIABLE V$OLD_NUM INTEGER;
DECLARE VARIABLE V$SKIP SMALLINT;
DECLARE VARIABLE V$HDAYS VARCHAR(1000);
DECLARE VARIABLE V$WDAYS VARCHAR(1000);
DECLARE VARIABLE V$OLD_TEACHER BIGINT;
DECLARE VARIABLE V$TEACHER_ID BIGINT;
begin

  -- Проверяем права доступа пользователя

  IF(EXISTS(
    SELECT FIRST 1 1
    FROM VALL V3591
    WHERE V3591.OBJ_ID = :I$OBJ_ID AND V3591.PARAM_ID = 3591 AND V3591.IS_DEL = 0 AND V3591.LISTVAL_ID <> 11716
  ))
  THEN
    EXCEPTION DATA_ERROR 'Обновление графика возможно только в статусе Проект';

  SELECT V3590.LISTVAL_ID
  FROM VALL V3590
  WHERE V3590.OBJ_ID = :I$OBJ_ID AND V3590.PARAM_ID = 3590 AND V3590.IS_DEL = 0
  INTO :V$YEAR_ID;

  -- Выходные и праздники
  SELECT LIST(D.VAL, ';')
  FROM LINKS L2
  JOIN LINKS L481 ON L481.PARENT_ID = L2.OBJ_ID AND L481.OBJ_TYPE_ID = 481 AND L481.DATE_DEL IS NULL
  JOIN VALL V3389 ON V3389.OBJ_ID = L481.OBJ_ID AND V3389.PARAM_ID = 3389 AND V3389.IS_DEL = 0 AND V3389.LISTVAL_ID = :V$YEAR_ID
  JOIN LINKS L486 ON L486.PARENT_ID = L481.OBJ_ID AND L486.OBJ_TYPE_ID = 486 AND L486.DATE_DEL IS NULL
  JOIN VALL V3394 ON V3394.OBJ_ID = L486.OBJ_ID AND V3394.PARAM_ID = 3394 AND V3394.IS_DEL = 0 AND V3394.LISTVAL_ID IN (14233, 14234)
  JOIN VALD V3393 ON V3393.OBJ_ID = L486.OBJ_ID AND V3393.PARAM_ID = 3393 AND V3393.IS_DEL = 0
  LEFT JOIN DATE2ISO(V3393.VAL, 0) D ON 1 = 1
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$HDAYS;

  -- TODO: переносы рабочих дней, нужно указывать с какой даты перенос

  -- Хранение данных в EDULOAD_DATA
  -- PARENT_ID - ссылка на план мероприятий
  -- PERSON_ID - класс
  -- GROUP_NAME - название класса
  -- REF_ID - предмет
  -- REF_TYPE_ID ссылка на урок в ПТП
  -- PLAN_ID - тип контроля из CJ2_CONTROL_TYPE
  -- STAGE_ID - этап обучения, параллель
  -- GROUP_TYPE_ID - ссылка на сотрудника
  -- VAL_DATE - дата
  -- VERIFIED - номер урока
  -- LOAD_VAL - количество часов или уроков

  -- Двигаемся по классам, только школьный уровень
  V$PREV_PERIOD = -1;
  FOR
    SELECT L9.OBJ_ID, V49.LISTVAL_ID, C.SCAPTION
    FROM LINKS L2
    JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    JOIN VALL V43 ON V43.OBJ_ID = L7.OBJ_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0 AND V43.LISTVAL_ID IN (22, 26, 27)
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
    LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C ON 1 = 1
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    ORDER BY C.SORT_ORDER, C.SCAPTION
    INTO :V$GRADE_ID, :V$STAGE_ID, :V$GRADE_NAME
  DO
  BEGIN

    FOR
      -- Берем все группы по предмету, где больше 3 учеников класса
      -- отсекаем только школьные предметы, без СПО
      SELECT J.SUBJECT_ID, J.OBJ_ID, P.PTP_ID, J.PERIOD_ID, J.TEACHER_ID, COUNT(L10.OBJ_ID)
      FROM LINKS L10
      JOIN LINKS LP179 ON LP179.OBJ_ID = L10.OBJ_ID AND LP179.PARENT_TYPE_ID = 179 AND LP179.DATE_DEL IS NULL
      JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.GRADE_ID = LP179.PARENT_ID AND J.YEAR_ID = :V$YEAR_ID AND J.JOURNAL_TYPE = 0 AND J.PERIOD_ID IS NOT NULL
      LEFT JOIN CJ2_JOURNAL_PTP P ON P.DATE_DEL IS NULL AND P.CJ_ID = J.OBJ_ID AND P.APPROVAL_STATE = 2
      JOIN OBJECTS OBJ ON OBJ.OBJ_ID = J.SUBJECT_ID AND OBJ.TYPE_ID = 51
      WHERE L10.PARENT_ID = :V$GRADE_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      GROUP BY 1, 2, 3, 4, 5
      HAVING COUNT(L10.OBJ_ID) > 3
      ORDER BY 1
      INTO :V$SUBJECT_ID, :V$CJ_ID, :V$PTP_ID, :V$PERIOD_ID, :V$TEACHER_ID, :N
    DO
    BEGIN

      IF(V$PREV_PERIOD <> V$PERIOD_ID) THEN
      BEGIN
        -- Дата начала и конца занятий
        V$FIRST_DATE = NULL;
        SELECT MIN(V1169.VAL), MAX(V1174.VAL)
        FROM LINKS L154
        JOIN VALD V1169 ON V1169.OBJ_ID = L154.OBJ_ID AND V1169.PARAM_ID = 1169 AND V1169.IS_DEL = 0
        JOIN VALD V1174 ON V1174.OBJ_ID = L154.OBJ_ID AND V1174.PARAM_ID = 1174 AND V1174.IS_DEL = 0
        WHERE L154.PARENT_ID = :V$PERIOD_ID AND L154.OBJ_TYPE_ID = 154 AND L154.DATE_DEL IS NULL
        INTO :V$FIRST_DATE, :V$END_DATE;
        IF(V$FIRST_DATE IS NULL) THEN EXCEPTION DATA_ERROR 'Не удалось найти дату начала занятий в расписании учебных периодов';

        -- Даты каникул перегружаем в память

        V$PREV_PERIOD = V$PERIOD_ID;
      END

      V$LAST_NUM = -1;
      V$LAST_DATE = NULL;
      V$LAST_INDEX = -1;
      FOR
        SELECT L.OBJ_ID, C.CONTROL_TYPE_ID, L.LESSON_NUM, JL.LESSON_DATE, JL.LESSON_NUM
        FROM PTP_LESSONS L
        JOIN PTP_LESSON_CONTROLS C ON C.DATE_DEL IS NULL AND C.LESSON_ID = L.OBJ_ID AND C.CONTROL_TYPE_ID IN (/*1077, 1083,*/ 1084, 1085, 1086, 1087, 1091, 1092)
        -- если урок уже посажен на дату в журнале - берем дату из него
        -- только поставленные по номеру урока, а не по времени
        LEFT JOIN CJ2_JOURNAL_LESSONS JL ON JL.DATE_DEL IS NULL AND JL.LESSON_PTP_ID = L.OBJ_ID AND JL.LESSON_NUM < 60
        WHERE L.DATE_DEL IS NULL AND L.PTP_ID = :V$PTP_ID
        ORDER BY 3
        INTO :V$PTP_LESSON_ID, :V$CT, :N, :V$LESSON_DATE, :V$LESSON_NUM
      DO
      BEGIN

        IF(V$LAST_INDEX = N) THEN EXCEPTION DATA_ERROR 'В ПТП включено более 1 контроля в одном уроке, ' || V$PTP_ID || ', урок ' || N;

        -- Если урок еще не посажен на дату - аппроксимируем через расписание и КУГ от предыдущей известной
        IF(V$LESSON_DATE IS NULL) THEN
        BEGIN
          -- Дата еще неизвестна - ищем дату начала занятий по расписанию периодов, перебирая урок за уроком
          -- смотрим только шаблоны, лента может не совпадать с картиной на весь учебный год
          IF(V$LAST_DATE IS NULL) THEN
          BEGIN
            V$LAST_DATE = V$FIRST_DATE;
            V$LESSON_NUM = 0;
            V$LAST_INDEX = -1;
          END
          WHILE(V$LAST_INDEX < N) DO
          BEGIN
            V$DN = EXTRACT(WEEKDAY FROM V$LAST_DATE);
            IF(V$DN = 0) THEN V$DN = 6; ELSE V$DN = V$DN - 1;

            -- Доделать переносы рабочихъ дней на выходные

            V$NW = NULL;
            V$WEEK = 0;
            -- Ищем следующий урок за уже известным
            -- !!! Возможно имеет смысл перегрузить в память все расписание, там точно не больше 10 записей в неделю
            SELECT FIRST 1 SI.WEEKDAY_NUM, SI.LESSON_NUM
            FROM SCHEDULE_ITEMS SI
            JOIN LINKS LP ON LP.OBJ_ID = SI.SCHEDULE_ID AND LP.PARENT_TYPE_ID = 3 AND LP.DATE_DEL IS NULL
            -- действующий шаблон
            JOIN VALL V1341 ON V1341.OBJ_ID = LP.OBJ_ID AND V1341.PARAM_ID = 1341 AND V1341.IS_DEL = 0 AND V1341.LISTVAL_ID = 2
            WHERE SI.DATE_DEL IS NULL AND SI.CJ_ID = :V$CJ_ID AND (SI.WEEKDAY_NUM > :V$DN OR (SI.WEEKDAY_NUM = :V$DN AND SI.LESSON_NUM > :V$LESSON_NUM)) AND SI.LESSON_NUM < 60
            ORDER BY 1, 2
            INTO :V$NW, :V$NN;

            -- Если на нашли, смотрим всю неделю, это будет уже следующая неделя
            IF(V$NW IS NULL) THEN
            BEGIN
              V$WEEK = 1;
              SELECT FIRST 1 SI.WEEKDAY_NUM, SI.LESSON_NUM
              FROM SCHEDULE_ITEMS SI
              JOIN LINKS LP ON LP.OBJ_ID = SI.SCHEDULE_ID AND LP.PARENT_TYPE_ID = 3 AND LP.DATE_DEL IS NULL
              -- действующий шаблон
              JOIN VALL V1341 ON V1341.OBJ_ID = LP.OBJ_ID AND V1341.PARAM_ID = 1341 AND V1341.IS_DEL = 0 AND V1341.LISTVAL_ID = 2
              WHERE SI.DATE_DEL IS NULL AND SI.CJ_ID = :V$CJ_ID AND SI.LESSON_NUM < 60
              ORDER BY 1, 2
              INTO :V$NW, :V$NN;
            END

            -- Не нашли - дальше искать нет смысла
            IF(V$NW IS NULL) THEN
            BEGIN
               V$LESSON_DATE = NULL;
               BREAK;
            END

            -- Дату приводим к понедельнику
            V$LESSON_DATE = DATEADD(V$NW - V$DN DAY TO V$LAST_DATE);
            IF(V$WEEK = 1) THEN V$LESSON_DATE = DATEADD(7 DAY TO V$LESSON_DATE);
            V$LAST_DATE = V$LESSON_DATE;
            V$LESSON_NUM = V$NN;

            -- Если нашли - проверяем что это не каникулы
            V$SKIP = 0;
            IF(V$LESSON_DATE >= V$CS1 AND V$LESSON_DATE <= V$CE1 OR V$LESSON_DATE >= V$CS2 AND V$LESSON_DATE <= V$CE2
              OR V$LESSON_DATE >= V$CS3 AND V$LESSON_DATE <= V$CE3 OR V$LESSON_DATE >= V$CS4 AND V$LESSON_DATE <= V$CE4
            )
            THEN
              V$SKIP = 1;
            -- И не выходной
            IF(V$SKIP = 0 AND POSITION((SELECT VAL FROM DATE2ISO(:V$LESSON_DATE, 0)) IN V$HDAYS) > 0) THEN V$SKIP = 1;

            IF(V$SKIP = 0) THEN V$LAST_INDEX = V$LAST_INDEX + 1;
          END
        END

        -- Не нашли - дальше искать нет смысла
        IF(V$LESSON_DATE IS NULL) THEN BREAK;

        -- По урокам ПТП надо подняться по истории коррекции до самой старой копии

        -- Обновляем запись
        V$OBJ_ID = NULL;
        SELECT FIRST 1 D.OBJ_ID, D.DATE_DEL, D.VAL_DATE, D.VERIFIED, COALESCE(D.GROUP_TYPE_ID, 0)
        FROM EDULOAD_DATA D
        WHERE D.PARENT_ID = :I$OBJ_ID AND D.PERSON_ID = :V$GRADE_ID AND D.REF_ID = :V$SUBJECT_ID AND D.PLAN_ID = :V$CT AND D.REF_TYPE_ID = :V$PTP_LESSON_ID
        INTO :V$OBJ_ID, :V$DT, :V$OLD_DATE, :V$OLD_NUM, :V$OLD_TEACHER;

        IF(V$OBJ_ID IS NULL) THEN
        BEGIN
          INSERT INTO EDULOAD_DATA
          (PARENT_ID, PERSON_ID, REF_ID, GROUP_NAME, PLAN_ID, REF_TYPE_ID, STAGE_ID, VAL_DATE, VERIFIED, GROUP_TYPE_ID, LOAD_VAL)
          VALUES(:I$OBJ_ID, :V$GRADE_ID, :V$SUBJECT_ID, :V$GRADE_NAME, :V$CT, :V$PTP_LESSON_ID, :V$STAGE_ID, :V$LESSON_DATE, :V$LESSON_NUM,
            :V$TEACHER_ID, 1);
        END
        ELSE IF(V$DT IS NOT NULL OR V$OLD_DATE <> V$LESSON_DATE OR V$OLD_NUM <> V$LESSON_NUM OR V$OLD_TEACHER <> V$TEACHER_ID) THEN
        BEGIN
          UPDATE EDULOAD_DATA
          SET DATE_DEL = NULL, VAL_DATE = :V$LESSON_DATE, VERIFIED = :V$LESSON_NUM, GROUP_TYPE_ID = :V$TEACHER_ID
          WHERE OBJ_ID = :V$OBJ_ID;
        END

      END

    END

  END

  -- Удалить строки, которые пропали в ПТП

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UPDATE_DOCUMENT_STATUS (
    I$OBJ_ID BIGINT,
    I$VAL BIGINT)
AS
DECLARE VARIABLE V$LINK_ID BIGINT;
DECLARE VARIABLE V$OLD_ID BIGINT;
DECLARE VARIABLE V$DT TIMESTAMP;
DECLARE VARIABLE V$FOLDER_ID BIGINT;
DECLARE VARIABLE V$ID BIGINT;
begin

  IF(I$VAL IN (1983, 14262)) THEN
  BEGIN
    -- В архив
    SELECT FIRST 1 LP.LINK_ID, LP.DATE_DEL
    FROM LINKS LP
    WHERE LP.OBJ_ID = :I$OBJ_ID AND LP.PARENT_TYPE_ID = 496
    ORDER BY LP.DATE_DEL NULLS FIRST
    INTO :V$LINK_ID, :V$DT;

    IF(V$LINK_ID IS NULL) THEN
    BEGIN
      SELECT FIRST 1 L496.OBJ_ID
      FROM LINKS LP2
      JOIN LINKS L496 ON L496.PARENT_ID = LP2.PARENT_ID AND L496.OBJ_TYPE_ID = 496 AND L496.DATE_DEL IS NULL
      WHERE LP2.OBJ_ID = :I$OBJ_ID AND LP2.PARENT_TYPE_ID = 2
      INTO :V$FOLDER_ID;

      IF(V$FOLDER_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не найдена папка архивных документов';

      SELECT LINK_ID FROM OBJECT_ADD_LINK(:V$FOLDER_ID, :I$OBJ_ID, 17) INTO :V$LINK_ID;
    END
    ELSE
    BEGIN
      IF(V$DT IS NOT NULL) THEN
      UPDATE LINKS
      SET DATE_DEL = NULL
      WHERE LINK_ID = :V$LINK_ID;
    END

    -- Удаляем непосредственно в ОУ
    UPDATE LINKS
    SET DATE_DEL = CURRENT_TIMESTAMP
    WHERE OBJ_ID = :I$OBJ_ID AND PARENT_TYPE_ID = 2 AND DATE_DEL IS NULL;
  END
  ELSE
  -- Переход в статус "Действующий"
  BEGIN
    -- В основные
    SELECT FIRST 1 LP.LINK_ID, LP.DATE_DEL
    FROM LINKS LP
    WHERE LP.OBJ_ID = :I$OBJ_ID AND LP.PARENT_TYPE_ID IN (2, 530)
    ORDER BY LP.DATE_DEL NULLS FIRST
    INTO :V$LINK_ID, :V$DT;

    IF(V$LINK_ID IS NULL) THEN
    BEGIN
      -- По идее этой ветки вообще не должно быть - документы непосредственно в архив добавлять нельзя
      SELECT FIRST 1 LP2.PARENT_ID
      FROM LINKS LP496
      JOIN LINKS LP2 ON LP2.OBJ_ID = LP496.PARENT_ID AND LP2.PARENT_TYPE_ID = 2
      WHERE LP496.OBJ_ID = :I$OBJ_ID AND LP496.PARENT_TYPE_ID = 496
      INTO :V$FOLDER_ID;

      IF(V$FOLDER_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не найден объект ОУ';

      SELECT LINK_ID FROM OBJECT_ADD_LINK(:V$FOLDER_ID, :I$OBJ_ID, 17) INTO :V$LINK_ID;
    END
    ELSE
    BEGIN
      IF(V$DT IS NOT NULL) THEN
      UPDATE LINKS
      SET DATE_DEL = NULL
      WHERE LINK_ID = :V$LINK_ID;
    END

    -- Удаляем в архиве
    UPDATE LINKS
    SET DATE_DEL = CURRENT_TIMESTAMP
    WHERE OBJ_ID = :I$OBJ_ID AND PARENT_TYPE_ID = 496 AND DATE_DEL IS NULL;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UPDATE_LESSON_TIME (
    I$OBJ_ID BIGINT,
    I$TIME TIME)
AS
DECLARE VARIABLE V$D1 DATE;
DECLARE VARIABLE V$D2 DATE;
DECLARE VARIABLE V$SCH_ID BIGINT;
DECLARE VARIABLE V$NUM INTEGER;
DECLARE VARIABLE V$FLOW_ID BIGINT;
DECLARE VARIABLE V$CJ_ID BIGINT;
DECLARE VARIABLE N1 INTEGER;
DECLARE VARIABLE N2 INTEGER;
begin

  -- Если I$TIME указан - это изменение в записи урока
  -- если NULL, то это изменение действующего статуса или дат в шаблоне

  -- Предполагается что номер урока в графике не меняется
  SELECT FIRST 1 V3120.VAL, V3121.VAL, LP59.PARENT_ID, V404.VAL, LP3.PARENT_ID
  FROM LINKS LP59
  JOIN VALL V1341 ON V1341.OBJ_ID = LP59.PARENT_ID AND V1341.PARAM_ID = 1341 AND V1341.IS_DEL = 0 AND V1341.LISTVAL_ID = 2
  JOIN VALD V3120 ON V3120.OBJ_ID = LP59.PARENT_ID AND V3120.PARAM_ID = 3120 AND V3120.IS_DEL = 0
  JOIN VALD V3121 ON V3121.OBJ_ID = LP59.PARENT_ID AND V3121.PARAM_ID = 3121 AND V3121.IS_DEL = 0
  JOIN VALI V404 ON V404.OBJ_ID = LP59.OBJ_ID AND V404.PARAM_ID = 404 AND V404.IS_DEL = 0
  JOIN LINKS LP3 ON LP3.OBJ_ID = LP59.PARENT_ID AND LP3.PARENT_TYPE_ID = 3 AND LP3.DATE_DEL IS NULL
  WHERE LP59.OBJ_ID = :I$OBJ_ID AND LP59.PARENT_TYPE_ID = 59 AND LP59.DATE_DEL IS NULL
  INTO :V$D1, :V$D2, :V$SCH_ID, :V$NUM, :V$FLOW_ID;

  -- В том числе если статус действующего снят
  IF(V$D1 IS NULL) THEN EXIT;

  -- Сначала записи расписания
  -- Непосредственно в этом шаблоне
  UPDATE SCHEDULE_ITEMS
  SET LESSON_TIME = :I$TIME
  WHERE DATE_DEL IS NULL AND SCHEDULE_ID = :V$SCH_ID AND LESSON_NUM = :V$NUM;

  -- В ленте, для указанного диапазона дат
  N1 = EXTRACT(MONTH FROM V$D1) * 100 + EXTRACT(DAY FROM V$D1);
  N2 = EXTRACT(MONTH FROM V$D2) * 100 + EXTRACT(DAY FROM V$D2);
  IF(N1 <= N2) THEN
  BEGIN
    -- Без перехода через НГ
    UPDATE SCHEDULE_ITEMS
    SET LESSON_TIME = :I$TIME
    WHERE DATE_DEL IS NULL AND SCHEDULE_ID = :V$FLOW_ID AND LESSON_NUM = :V$NUM AND WEEKDAY_NUM >= :N1 AND WEEKDAY_NUM <= :N2;
  END
  ELSE
  BEGIN
    -- С переходом через НГ
    UPDATE SCHEDULE_ITEMS
    SET LESSON_TIME = :I$TIME
    WHERE DATE_DEL IS NULL AND SCHEDULE_ID = :V$FLOW_ID AND LESSON_NUM = :V$NUM AND (WEEKDAY_NUM >= :N1 OR WEEKDAY_NUM <= :N2);
  END

  -- Уроки в КЖ
  -- Только через шаблон, считаем что лента является подчиненной
  FOR
    SELECT DISTINCT SI.CJ_ID
    FROM SCHEDULE_ITEMS SI
    WHERE SI.DATE_DEL IS NULL AND SI.SCHEDULE_ID = :V$SCH_ID AND SI.LESSON_NUM = :V$NUM
    INTO :V$CJ_ID
  DO
  BEGIN
    UPDATE CJ2_JOURNAL_LESSONS
    SET LESSON_TIME = :I$TIME
    WHERE DATE_DEL IS NULL AND CJ_ID = :V$CJ_ID AND LESSON_NUM = :V$NUM AND LESSON_DATE >= :V$D1 AND LESSON_DATE <= :V$D2;
  END

  -- Замещения - предполагается что тут не должно быть изменений

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UPDATE_MOVEMENTS_CNAME (
    I$OBJ_ID BIGINT)
AS
declare variable S varchar(1000);
begin

  S = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$OBJ_ID));

  UPDATE PERSON_MOVEMENTS
  SET NAME_IN = :S
  WHERE DATE_DEL IS NULL AND GROUP_ID = :I$OBJ_ID AND DATE_OUT IS NULL;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UPDATE_PROFESSION_CODE (
    I$OBJ_ID BIGINT,
    I$LISTVAL_ID BIGINT)
AS
declare variable V$TMP bigint;
declare variable V$TAG varchar(100);
begin

    SELECT TAG
    FROM LISTVALS
    WHERE LISTVAL_ID = :I$LISTVAL_ID
    INTO :V$TAG;

    SELECT BLOB_ID FROM VAL_ADD(2120, :I$OBJ_ID, :V$TAG) INTO :V$TMP;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UPDATE_PUPIL_MK_SUBJECTS (
    I$PLAN_ID BIGINT,
    I$USER_ID VARCHAR(40))
AS
declare variable V$OU_ID bigint;
declare variable V$YEAR_ID bigint;
declare variable V$GUP_ID bigint;
declare variable V$STAGE_ID bigint;
declare variable V$STAGE integer;
declare variable V$STUDENT_ID bigint;
declare variable V$SUBJECT_ID bigint;
declare variable V$GROUP_ID bigint;
declare variable V$GROUP_TYPE bigint;
declare variable V$DATE date;
declare variable V$VD bigint;
declare variable S varchar(1000);
declare variable G varchar(1000);
declare variable T integer;
begin

  SELECT FIRST 1 P.OBJ_ID, V1236.LISTVAL_ID
  FROM OBJECT_PARENTS_GET(:I$PLAN_ID, 2) P
  JOIN VALL V1236 ON V1236.OBJ_ID = P.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  INTO :V$OU_ID, :V$YEAR_ID;

  -- ВД или общеобр ?
  SELECT V3022.LISTVAL_ID
  FROM VALL V3022
  WHERE V3022.OBJ_ID = :I$PLAN_ID AND V3022.PARAM_ID = 3022 AND V3022.IS_DEL = 0
  INTO :V$VD;

  -- Общеобразовательные УП
  IF(V$VD IS NULL OR V$VD = 3) THEN
  FOR
    SELECT L256.OBJ_ID, LV.LISTVAL_ID, LV.COST, C.CAPTION
    FROM LINKS L54
    JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V381.LISTVAL_ID
    JOIN LINKS L256 ON L256.PARENT_ID = L54.OBJ_ID AND L256.OBJ_TYPE_ID = 256 AND L256.DATE_DEL IS NULL
    LEFT JOIN OBJECT_CAPTION_GET(L256.OBJ_ID) C ON 1 = 1
    WHERE L54.PARENT_ID = :I$PLAN_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL AND POSITION('будущий ' IN C.CAPTION) <= 0
    ORDER BY LV.COST, 3
    INTO :V$GUP_ID, :V$STAGE_ID, :V$STAGE, :S
  DO
  BEGIN
    FOR
      SELECT L10.OBJ_ID, COALESCE(V2838.VAL, '')
      FROM LINKS L10
      LEFT JOIN VALS V2838 ON V2838.OBJ_ID = L10.OBJ_ID AND V2838.PARAM_ID = 2838 AND V2838.IS_DEL = 0
      WHERE L10.PARENT_ID = :V$GROUP_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      INTO :V$STUDENT_ID, :G
    DO
    BEGIN
      FOR
        SELECT ID
        FROM STR_TO_ID_LIST(:G)
        INTO :V$SUBJECT_ID
      DO
      BEGIN
        -- Числится ли студент в группе по этому предмету ?
        V$GROUP_ID = NULL;
        SELECT FIRST 1 J.GRADE_ID
        FROM PERSON_MOVEMENTS M
        JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.YEAR_ID = :V$YEAR_ID AND J.JOURNAL_TYPE = 0 AND J.SUBJECT_ID = :V$SUBJECT_ID AND J.GRADE_ID = M.GROUP_ID
        WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :V$STUDENT_ID AND M.DATE_OUT IS NULL
        INTO :V$GROUP_ID;

        -- Если уже числится - пусть там и остается
        IF(V$GROUP_ID IS NULL) THEN
        BEGIN
          -- Если группы по этому предмету в этой параллели нет - создаем новую
          -- группы всегда создаем в разрезе ГУПов
          V$GROUP_ID = NULL;
          V$GROUP_TYPE = NULL;
          SELECT FIRST 1 J.GRADE_ID, J.GRADE_TYPE_ID
          FROM CJ2_JOURNAL J
          WHERE J.DATE_DEL IS NULL AND J.YEAR_ID = :V$YEAR_ID AND J.JOURNAL_TYPE = 0 AND J.SUBJECT_ID = :V$SUBJECT_ID AND J.REF_ID = :I$PLAN_ID AND J.STAGE_INDEX = :V$STAGE_ID
          INTO :V$GROUP_ID, :V$GROUP_TYPE;

          IF(V$GROUP_ID IS NULL) THEN
          BEGIN
            SELECT GRADE_ID, GRADE_TYPE_ID
            FROM CJ2_JOURNAL_ADD(NULL, 0, NULL, 179, :V$SUBJECT_ID, NULL, :S, :V$STAGE_ID, NULL, :I$PLAN_ID, :V$YEAR_ID)
            INTO :V$GROUP_ID, :V$GROUP_TYPE;

            UPDATE LINKS SET EXT_OBJ_ID = :V$GUP_ID WHERE PARENT_ID = :V$OU_ID AND OBJ_ID = :V$GROUP_ID;
            SELECT 1 FROM VAL_ADD(3370, :V$GROUP_ID, :V$GUP_ID) INTO :T;
          END

          -- Зачисляем в группу с даты зачисления в ГУП
          SELECT FIRST 1 M.DATE_IN
          FROM PERSON_MOVEMENTS M
          WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :V$STUDENT_ID AND M.GROUP_ID = :V$GUP_ID
          ORDER BY M.DATE_IN DESC
          INTO :V$DATE;

          SELECT 1 FROM VARGRP_MOVE_PUPIL(:V$STUDENT_ID, :V$GROUP_ID, NULL, NULL, :V$DATE, 0, :I$USER_ID) INTO :T;
        END
      END
    END
  END
  -- ВД
  -- Выбираем всех студентов из всех ГУП этой ОП
  ELSE IF(V$VD = 2) THEN
  FOR
    SELECT L256.OBJ_ID, LV.LISTVAL_ID, LV.COST, C.CAPTION
    FROM LINKS LP57
    JOIN LINKS L400 ON L400.PARENT_ID = LP57.PARENT_ID AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL
    -- статус действующего проверять не надо, в недействующих не будет ГУП
    JOIN LINKS L54 ON L54.PARENT_ID = L400.OBJ_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
    JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V381.LISTVAL_ID
    JOIN LINKS L256 ON L256.PARENT_ID = L54.OBJ_ID AND L256.OBJ_TYPE_ID = 256 AND L256.DATE_DEL IS NULL
    LEFT JOIN OBJECT_CAPTION_GET(L256.OBJ_ID) C ON 1 = 1
    WHERE LP57.OBJ_ID = :I$PLAN_ID AND LP57.OBJ_TYPE_ID = 57 AND LP57.DATE_DEL IS NULL AND POSITION('будущий ' IN C.CAPTION) <= 0
    ORDER BY LV.COST, 3
    INTO :V$GUP_ID, :V$STAGE_ID, :V$STAGE, :S
  DO
  BEGIN
    FOR
      SELECT L10.OBJ_ID, COALESCE(V3466.VAL, '')
      FROM LINKS L10
      LEFT JOIN VALS V3466 ON V3466.OBJ_ID = L10.OBJ_ID AND V3466.PARAM_ID = 3466 AND V3466.IS_DEL = 0
      WHERE L10.PARENT_ID = :V$GROUP_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      INTO :V$STUDENT_ID, :G
    DO
    BEGIN
      FOR
        SELECT ID
        FROM STR_TO_ID_LIST(:G)
        INTO :V$SUBJECT_ID
      DO
      BEGIN
        -- Числится ли студент в группе по этому предмету ?
        V$GROUP_ID = NULL;
        SELECT FIRST 1 J.GRADE_ID
        FROM PERSON_MOVEMENTS M
        JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.YEAR_ID = :V$YEAR_ID AND J.JOURNAL_TYPE = 1 AND J.SUBJECT_ID = :V$SUBJECT_ID AND J.GRADE_ID = M.GROUP_ID
        WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :V$STUDENT_ID AND M.DATE_OUT IS NULL
        INTO :V$GROUP_ID;

        -- Если уже числится - пусть там и остается
        IF(V$GROUP_ID IS NULL) THEN
        BEGIN
          -- Если группы по этому предмету в этой параллели нет - создаем новую
          -- группы всегда создаем в разрезе ГУПов
          V$GROUP_ID = NULL;
          V$GROUP_TYPE = NULL;
          SELECT FIRST 1 J.GRADE_ID, J.GRADE_TYPE_ID
          FROM CJ2_JOURNAL J
          WHERE J.DATE_DEL IS NULL AND J.YEAR_ID = :V$YEAR_ID AND J.JOURNAL_TYPE = 1 AND J.SUBJECT_ID = :V$SUBJECT_ID AND J.REF_ID = :I$PLAN_ID AND J.STAGE_INDEX = :V$STAGE_ID
          INTO :V$GROUP_ID, :V$GROUP_TYPE;

          IF(V$GROUP_ID IS NULL) THEN
          BEGIN
            SELECT GRADE_ID, GRADE_TYPE_ID
            FROM CJ2_JOURNAL_ADD(NULL, 0, NULL, 179, :V$SUBJECT_ID, NULL, :S, :V$STAGE_ID, NULL, :I$PLAN_ID, :V$YEAR_ID)
            INTO :V$GROUP_ID, :V$GROUP_TYPE;

            UPDATE LINKS SET EXT_OBJ_ID = :V$GUP_ID WHERE PARENT_ID = :V$OU_ID AND OBJ_ID = :V$GROUP_ID;
            SELECT 1 FROM VAL_ADD(3370, :V$GROUP_ID, :V$GUP_ID) INTO :T;
          END

          -- Зачисляем в группу с даты зачисления в ГУП
          SELECT FIRST 1 M.DATE_IN
          FROM PERSON_MOVEMENTS M
          WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :V$STUDENT_ID AND M.GROUP_ID = :V$GUP_ID
          ORDER BY M.DATE_IN DESC
          INTO :V$DATE;

          SELECT 1 FROM VARGRP_MOVE_PUPIL(:V$STUDENT_ID, :V$GROUP_ID, NULL, NULL, :V$DATE, 0, :I$USER_ID) INTO :T;
        END
      END
    END
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UPDATE_PUPIL_SEL_SUBJECTS (
    I$PLAN_ID BIGINT,
    I$PUPIL_ID BIGINT NOT NULL,
    I$SEL_SUBJECTS VARCHAR(1000) NOT NULL,
    I$SEL_GROUPS VARCHAR(1000) NOT NULL,
    I$ACTION_DATE DATE,
    I$USER_ID BIGINT)
AS
declare variable V$STAGE_INDEX bigint;
declare variable V$YEAR_ID bigint;
declare variable V$STREAM_ID bigint;
declare variable V$IS_PRESENT smallint;
declare variable V$IS_VD bigint;
declare variable P integer;
begin

  -- Это общеобразовательные модули или ВД ?
  SELECT I
  FROM VAL_GET(:I$PLAN_ID, 3022)
  INTO :V$IS_VD;

  IF(V$IS_VD IS NULL) THEN V$IS_VD = 3;

  IF(V$IS_VD = 2) THEN
  BEGIN
    -- Внеурочка, этап берем из реального класса ученика
    SELECT FIRST 1 LV.COST
    FROM LINKS LP9
    JOIN LINKS LP8 ON LP8.OBJ_ID = LP9.PARENT_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
    JOIN VALL V49 ON V49.OBJ_ID = LP8.PARENT_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V49.LISTVAL_ID
    WHERE LP9.OBJ_ID = :I$PUPIL_ID AND LP9.PARENT_TYPE_ID = 9 AND LP9.DATE_DEL IS NULL
    INTO :V$STAGE_INDEX;
  END
  ELSE
  BEGIN
    -- Общеобр
    SELECT FIRST 1 LV.COST
    FROM LINKS LP256
    JOIN LINKS LP54 ON LP54.OBJ_ID = LP256.PARENT_ID AND LP54.PARENT_TYPE_ID = 54 AND LP54.DATE_DEL IS NULL
    JOIN VALL V381 ON V381.OBJ_ID = LP54.PARENT_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V381.LISTVAL_ID
    WHERE LP256.OBJ_ID = :I$PUPIL_ID AND LP256.PARENT_TYPE_ID = 256 AND LP256.DATE_DEL IS NULL
    INTO :V$STAGE_INDEX;
  END

  SELECT FIRST 1 V1236.LISTVAL_ID
  FROM OBJECT_PARENTS_GET(:I$PLAN_ID, 2) P
  JOIN VALL V1236 ON V1236.OBJ_ID = P.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  INTO :V$YEAR_ID;

  -- Исключаем из модулей, которых больше нет в списке выбора, и где числится обучающийся
  -- Только предметы, которые были в нагрузке УП
  FOR
    SELECT J.GRADE_ID
    FROM CJ2_JOURNAL J
    JOIN LINKS L10 ON L10.PARENT_ID = J.GRADE_ID AND L10.OBJ_TYPE_ID = 10 AND L10.OBJ_ID = :I$PUPIL_ID AND L10.DATE_DEL IS NULL
    LEFT JOIN VALL V3158 ON V3158.OBJ_ID = J.SUBJECT_ID AND V3158.PARAM_ID = 3158 AND V3158.IS_DEL = 0 -- тип предмета
    LEFT JOIN VALL V2816 ON V2816.OBJ_ID = J.SUBJECT_ID AND V2816.PARAM_ID = 2818 AND V2816.IS_DEL = 0 -- электив
    LEFT JOIN VALR V3159 ON V3159.PARAM_ID = 3159 AND V3159.OBJ_ID = J.SUBJECT_ID AND V3159.IS_DEL = 0 -- ссылка на мастер-предмет
    JOIN PLAN_SUBJECTS PS ON PS.DATE_DEL IS NULL AND PS.PLAN_ID = :I$PLAN_ID AND (PS.SUBJECT_ID = J.SUBJECT_ID OR PS.SUBJECT_ID = V3159.VAL)
    WHERE J.DATE_DEL IS NULL AND J.YEAR_ID = :V$YEAR_ID AND J.GRADE_TYPE_ID = 179 AND J.JOURNAL_TYPE = 0
      AND (V2816.LISTVAL_ID = 2 OR V3158.LISTVAL_ID IN (13456, 13457)) AND :V$IS_VD = 3
    UNION
    SELECT J.GRADE_ID
    FROM CJ2_JOURNAL J
    JOIN LINKS L10 ON L10.PARENT_ID = J.GRADE_ID AND L10.OBJ_TYPE_ID = 10 AND L10.OBJ_ID = :I$PUPIL_ID AND L10.DATE_DEL IS NULL
    JOIN PLAN_SUBJECTS PS ON PS.DATE_DEL IS NULL AND PS.PLAN_ID = :I$PLAN_ID AND PS.SUBJECT_ID = J.SUBJECT_ID
    WHERE J.DATE_DEL IS NULL AND J.YEAR_ID = :V$YEAR_ID AND J.GRADE_TYPE_ID = 179 AND J.JOURNAL_TYPE = 1 AND :V$IS_VD = 2
    INTO :V$STREAM_ID
  DO
  BEGIN
    -- Есть ли этот поток в списке ?
    SELECT IS_PRESENT FROM STR_IN_LIST(:V$STREAM_ID, :I$SEL_GROUPS) INTO :V$IS_PRESENT;
    IF(V$IS_PRESENT = 0) THEN
    BEGIN
      -- Вносим запись движения и убираем ученика из потока
      SELECT 1 FROM VARGRP_MOVE_PUPIL(:I$PUPIL_ID, :V$STREAM_ID, NULL, NULL, :I$ACTION_DATE, 1, :I$USER_ID, NULL, 12029) INTO :V$IS_PRESENT;
      -- Убираем уже обработанные ID из списка
      SELECT OUT_S FROM STR_REMOVE_FROM_LIST(:I$SEL_GROUPS, :I$PUPIL_ID) INTO :I$SEL_GROUPS;
    END
  END

  -- Проходим по всем оставшимся ID потоков в списке и добавляем в них ученика (если поток существует в данном сечении)
  WHILE(CHAR_LENGTH(I$SEL_GROUPS) > 0) DO
  BEGIN
    P = POSITION(',', I$SEL_GROUPS);
    IF(P <= 0) THEN P = CHAR_LENGTH(I$SEL_GROUPS) + 1;
    V$STREAM_ID = SUBSTRING(I$SEL_GROUPS FROM 1 FOR P - 1);
    I$SEL_GROUPS = SUBSTRING(I$SEL_GROUPS FROM P + 1 FOR 2000);
    -- Проверяем наличие такого потока, а также что это поток по выбору. Либо предмет по выбору, либо модуль
    P = 0;
    IF(V$IS_VD = 2) THEN
    BEGIN
      SELECT FIRST 1 1
      FROM PLAN_SUBJECTS PS
      JOIN PLAN_LOADS L ON L.DATE_DEL IS NULL AND L.SUBJECT_ID = PS.OBJ_ID AND (L.LOAD_HOURS_S1 > 0 OR L.LOAD_HOURS_S2 > 0)
      JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.SUBJECT_ID = PS.SUBJECT_ID AND BIN_OR(J.STAGE_MASK, BIN_SHL(1, :V$STAGE_INDEX)) <> 0 AND J.JOURNAL_TYPE = 1 AND J.GRADE_TYPE_ID = 179 AND J.GRADE_ID = :V$STREAM_ID AND J.YEAR_ID = :V$YEAR_ID
      WHERE PS.PLAN_ID = :I$PLAN_ID AND PS.DATE_DEL IS NULL AND PS.ROW_TYPE = 10
      INTO :P;
    END
    ELSE
    BEGIN
      SELECT FIRST 1 1
      FROM PLAN_SUBJECTS PS
      JOIN PLAN_SUBJECTS PSP ON PSP.OBJ_ID = PS.PARENT_ID
      JOIN PLAN_LOADS L ON L.DATE_DEL IS NULL AND L.SUBJECT_ID = PS.OBJ_ID AND (L.LOAD_HOURS_S1 > 0 OR L.LOAD_HOURS_S2 > 0)
      JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.SUBJECT_ID = PS.SUBJECT_ID AND BIN_OR(J.STAGE_MASK, BIN_SHL(1, :V$STAGE_INDEX)) <> 0 AND J.JOURNAL_TYPE = 0 AND J.GRADE_TYPE_ID = 179 AND J.GRADE_ID = :V$STREAM_ID AND J.YEAR_ID = :V$YEAR_ID
      WHERE PS.PLAN_ID = :I$PLAN_ID AND PS.DATE_DEL IS NULL AND PS.ROW_TYPE = 10 AND PSP.FIELD_ID = 12928
      UNION
      SELECT FIRST 1 1
      FROM PLAN_SUBJECTS PS
      JOIN VALL V3158 ON V3158.OBJ_ID = PS.SUBJECT_ID AND V3158.PARAM_ID = 3158 AND V3158.IS_DEL = 0 AND V3158.LISTVAL_ID IN (13454, 13455, 13462)
      JOIN PLAN_LOADS L ON L.DATE_DEL IS NULL AND L.SUBJECT_ID = PS.OBJ_ID AND (L.LOAD_HOURS_S1 > 0 OR L.LOAD_HOURS_S2 > 0)
      JOIN VALR V3159 ON V3159.PARAM_ID = 3159 AND V3159.VAL = PS.SUBJECT_ID AND V3159.IS_DEL = 0
      JOIN VALL V3158X ON V3158X.OBJ_ID = V3159.OBJ_ID AND V3158X.PARAM_ID = 3158 AND V3158X.IS_DEL = 0 AND V3158X.LISTVAL_ID IN (13456, 13457)
      JOIN LINKS LP51 ON LP51.OBJ_ID = V3159.OBJ_ID AND LP51.PARENT_TYPE_ID = 301 AND LP51.DATE_DEL IS NULL
      JOIN CJ2_JOURNAL J ON J.DATE_DEL IS NULL AND J.SUBJECT_ID = V3159.OBJ_ID AND BIN_OR(J.STAGE_MASK, BIN_SHL(1, :V$STAGE_INDEX)) <> 0 AND J.JOURNAL_TYPE = 0 AND J.GRADE_TYPE_ID = 179 AND J.GRADE_ID = :V$STREAM_ID AND J.YEAR_ID = :V$YEAR_ID
      WHERE PS.PLAN_ID = :I$PLAN_ID AND PS.DATE_DEL IS NULL AND PS.ROW_TYPE = 10
      INTO :P;
    END
    IF(P = 0) THEN EXCEPTION DATA_ERROR 'Не найдена группа по предмету ' || V$STREAM_ID || ', либо изменились настройки группы';
    -- Проверяем, что ученик еще не входит в данный поток
    P = 0;
    SELECT COUNT(*)
    FROM LINKS L10
    WHERE L10.PARENT_ID = :V$STREAM_ID AND L10.OBJ_ID = :I$PUPIL_ID AND L10.DATE_DEL IS NULL
    INTO :P;
    IF(P = 0) THEN
    BEGIN
      -- Вносим запись движения и добавляем ученика в поток
      SELECT 1 FROM VARGRP_MOVE_PUPIL(:I$PUPIL_ID, :V$STREAM_ID, NULL, NULL, :I$ACTION_DATE, 0, :I$USER_ID, NULL, 12028) INTO :V$IS_PRESENT;
    END
  END

  -- Просеиваем и дополняем список предметов, поскольку SEL_SUBJECTS включает предметы только по одному УП - а таких УП может быть несколько
  SELECT 1 FROM VAL_ADD(IIF(:V$IS_VD = 3, 2838, 3466), :I$PUPIL_ID, :I$SEL_SUBJECTS) INTO :V$IS_PRESENT;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UPDATE_SPECIALITY_CODE (
    I$OBJ_ID BIGINT,
    I$PARAM_ID BIGINT,
    I$CODE_PARAM_ID BIGINT,
    I$VAL BIGINT,
    I$USER_ID BIGINT,
    I$IS_DEL SMALLINT)
AS
declare variable J bigint;
declare variable OTHER_PARAM bigint;
declare variable OTHER_PARAM2 bigint;
declare variable V$PLAN_ID bigint;
declare variable V$OBJ_ID bigint;
BEGIN
    -- Коды можно руками вводить только если не указана ссылка на УП
    SELECT V.VAL
    FROM VALR V
    WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID IN (3477, 3075) AND V.IS_DEL = 0
    INTO :V$PLAN_ID;

    IF(V$PLAN_ID IS NOT NULL) THEN EXCEPTION DATA_ERROR 'При указании учебного плана коды профессии/специальности должны указываться именно в нем';

    -- Требуем, чтобы было заполнено только одно из трех полей
    -- #9
    IF (I$CODE_PARAM_ID = 2822 AND I$IS_DEL = 0) THEN
    BEGIN
      IF(I$PARAM_ID = 2165) THEN BEGIN
        OTHER_PARAM = 2821;
        OTHER_PARAM2 = 3367;
      END
      ELSE IF(I$PARAM_ID = 3367) THEN BEGIN
        OTHER_PARAM = 2821;
        OTHER_PARAM2 = 2165;
      END
      ELSE BEGIN
        OTHER_PARAM = 2165;
        OTHER_PARAM2 = 3367;
      END

      J = 0;
      SELECT COUNT(*)
      FROM VALL
      WHERE OBJ_ID = :I$OBJ_ID AND (PARAM_ID = :OTHER_PARAM OR PARAM_ID = :OTHER_PARAM2) AND IS_DEL = 0
      INTO :J;

      IF(J > 0) THEN EXCEPTION DATA_ERROR 'Разрешается заполнить только один из кодов профессии/специальности';
    END
    -- #403
    IF (I$CODE_PARAM_ID = 3384 AND I$IS_DEL = 0) THEN
    BEGIN
      IF(I$PARAM_ID = 3381) THEN BEGIN
        OTHER_PARAM = 3382;
        OTHER_PARAM2 = 3383;
      END
      ELSE IF(I$PARAM_ID = 3383) THEN BEGIN
        OTHER_PARAM = 3382;
        OTHER_PARAM2 = 3381;
      END
      ELSE BEGIN
        OTHER_PARAM = 3381;
        OTHER_PARAM2 = 3383;
      END

      J = 0;
      SELECT COUNT(*)
      FROM VALL
      WHERE OBJ_ID = :I$OBJ_ID AND (PARAM_ID = :OTHER_PARAM OR PARAM_ID = :OTHER_PARAM2) AND IS_DEL = 0
      INTO :J;

      IF(J > 0) THEN EXCEPTION DATA_ERROR 'Разрешается заполнить только один из кодов профессии/специальности';
    END
    -- #400
    IF (I$CODE_PARAM_ID = 3476 AND I$IS_DEL = 0) THEN
    BEGIN
      IF(I$PARAM_ID = 3473) THEN BEGIN
        OTHER_PARAM = 3474;
        OTHER_PARAM2 = 3475;
      END
      ELSE IF(I$PARAM_ID = 3474) THEN BEGIN
        OTHER_PARAM = 3473;
        OTHER_PARAM2 = 3475;
      END
      ELSE BEGIN
        OTHER_PARAM = 3473;
        OTHER_PARAM2 = 3474;
      END

      J = 0;
      SELECT COUNT(*)
      FROM VALL
      WHERE OBJ_ID = :I$OBJ_ID AND (PARAM_ID = :OTHER_PARAM OR PARAM_ID = :OTHER_PARAM2) AND IS_DEL = 0
      INTO :J;

      IF(J > 0) THEN EXCEPTION DATA_ERROR 'Разрешается заполнить только один из кодов профессии/специальности';
    END

    -- Фиксируем код специальности
    IF (I$IS_DEL = 1) THEN
    BEGIN
      UPDATE VALS
      SET IS_DEL = 1
      WHERE OBJ_ID = :I$OBJ_ID AND PARAM_ID = :I$CODE_PARAM_ID AND IS_DEL = 0;
    END
    ELSE
    BEGIN
      SELECT BLOB_ID
      FROM VAL_ADD(:I$CODE_PARAM_ID, :I$OBJ_ID, (SELECT TAG FROM LISTVALS WHERE LISTVAL_ID = :I$VAL), :I$USER_ID, 0, 0)
      INTO :J;
    END

    -- При изменении кодов в УП обновляем коды по всем учебным коллективам и будущим учебным коллективам
    IF (I$CODE_PARAM_ID = 3476 AND I$IS_DEL = 0) THEN
    BEGIN
      FOR
        SELECT LP8.OBJ_ID
        FROM VALR VR
        JOIN LINKS LP8 ON LP8.OBJ_ID = VR.OBJ_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
        WHERE VR.PARAM_ID IN (3477, 3075) AND VR.VAL = :I$OBJ_ID AND VR.IS_DEL = 0
        INTO :V$OBJ_ID
      DO
      BEGIN
        EXECUTE PROCEDURE COPY_SPO_CODES(:V$OBJ_ID, :I$OBJ_ID);
      END
    END

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE USA_LIST_LEVELS (
    I$MASK BIGINT)
RETURNS (
    VAL VARCHAR(1000))
AS
begin

  VAL = '';

  IF(BIN_AND(I$MASK, 1) > 0) THEN
  BEGIN
    IF(VAL <> '') THEN VAL = VAL || ', ';
    VAL = VAL || 'НОО';
  END
  IF(BIN_AND(I$MASK, 2) > 0) THEN
  BEGIN
    IF(VAL <> '') THEN VAL = VAL || ', ';
    VAL = VAL || 'ООО';
  END
  IF(BIN_AND(I$MASK, 4) > 0) THEN
  BEGIN
    IF(VAL <> '') THEN VAL = VAL || ', ';
    VAL = VAL || 'СОО';
  END

  IF(I$MASK = 0) THEN VAL = '*';

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE USERADM_ACCOUNT_EXTEND
AS
DECLARE VARIABLE V$MONTH INTEGER;
DECLARE VARIABLE V$NEW_DATE DATE;
BEGIN
  SELECT EXTRACT(MONTH FROM CURRENT_DATE) FROM RDB$DATABASE INTO :V$MONTH;

  IF (V$MONTH >= 9) THEN
  BEGIN
    V$NEW_DATE = '01.09.'|| (EXTRACT(YEAR FROM CURRENT_DATE) + 1);
  END
  ELSE
  BEGIN
    V$NEW_DATE = '01.09.'|| EXTRACT(YEAR FROM CURRENT_DATE);
  END

  -- Также снимаем флаг IS_BLOCKED
  UPDATE USERS U
  SET U.EXP_DATE = :V$NEW_DATE, U.IS_BLOCKED = 0
  WHERE U.OBJ_ID IN (
    SELECT U.OBJ_ID
    FROM USERS U
    JOIN LINKS L ON L.OBJ_ID = U.OBJ_ID AND L.OBJ_TYPE_ID = 10 AND L.PARENT_TYPE_ID = 9 AND L.DATE_DEL IS NULL
    WHERE U.DATE_DEL IS NULL
  );

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE USERADM_ACTIVITES_LIST (
    I$LANG_CODE CHAR(2) = 'RU')
RETURNS (
    DATE_START TIMESTAMP,
    FIO VARCHAR(100),
    PC_NAME VARCHAR(100),
    LEVEL_CAPTION VARCHAR(1000),
    TASK_CAPTION VARCHAR(1000),
    MODULE_CAPTION VARCHAR(1000),
    USER_NAME VARCHAR(100))
AS
declare variable LEVEL_RES_ID bigint;
declare variable TASK_RES_ID bigint;
declare variable MODULE_RES_ID bigint;
BEGIN
    FOR SELECT COALESCE(US.FIRST_NAME, '') || ' ' || COALESCE(US.MIDDLE_NAME, '') || ' ' || COALESCE(US.LAST_NAME, ' ') AS FIO, L.PC_NAME,
               L.DATE_START, LV.RES_ID, T.RES_ID, M.RES_ID, US.USER_NAME
        FROM LOG L
        INNER JOIN USERS US ON US.USER_ID = L.USER_ID
        INNER JOIN LEVELS LV ON LV.LEVEL_ID = L.LEVEL_ID
        INNER JOIN TASKS T ON T.TASK_ID = LV.TASK_ID
        INNER JOIN MODULES M ON M.MODULE_ID = T.MODULE_ID
        WHERE L.DATE_START > CURRENT_DATE
          AND L.DATE_EXIT IS NULL
        ORDER BY L.LOG_ID
        INTO :FIO, :PC_NAME, :DATE_START, :LEVEL_RES_ID, :TASK_RES_ID, :MODULE_RES_ID, :USER_NAME
    DO
    BEGIN
        SELECT VAL
        FROM RES_GET(:LEVEL_RES_ID, :I$LANG_CODE)
        INTO :LEVEL_CAPTION;

        SELECT VAL
        FROM RES_GET(:TASK_RES_ID, :I$LANG_CODE)
        INTO :TASK_CAPTION;

        SELECT VAL
        FROM RES_GET(:MODULE_RES_ID, :I$LANG_CODE)
        INTO :MODULE_CAPTION;

        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE USERADM_ADD (
    I$USER_ID BIGINT,
    I$USER_TYPE SMALLINT,
    I$USER_NAME VARCHAR(100),
    I$PWD VARCHAR(100),
    I$OBJ_ID BIGINT,
    I$IS_BLOCKED SMALLINT,
    I$MUST_CHANGE SMALLINT,
    I$EXP_DATE DATE = null,
    I$LANG_CODE CHAR(2) = 'RU',
    I$IS_BLOCKED_PWD SMALLINT = null)
RETURNS (
    USER_ID BIGINT)
AS
declare variable FIRST_NAME varchar(100);
declare variable MIDDLE_NAME varchar(100);
declare variable LAST_NAME varchar(100);
BEGIN
    USER_ID = I$USER_ID;

    SELECT V FROM VAL_GET(:I$OBJ_ID, 59) INTO :LAST_NAME;
    SELECT V FROM VAL_GET(:I$OBJ_ID, 60) INTO :FIRST_NAME;
    SELECT V FROM VAL_GET(:I$OBJ_ID, 61) INTO :MIDDLE_NAME;

    IF (I$USER_ID IS NULL) THEN
    BEGIN
        INSERT INTO USERS (USER_TYPE, USER_NAME, PWD, FIRST_NAME, MIDDLE_NAME, LAST_NAME,
                           LANG_CODE, OBJ_ID, IS_BLOCKED, MUST_CHANGE, EXP_DATE, IS_BLOCKED_PWD)
        VALUES (:I$USER_TYPE, :I$USER_NAME, :I$PWD, :FIRST_NAME, :MIDDLE_NAME, :LAST_NAME,
                :I$LANG_CODE, :I$OBJ_ID, :I$IS_BLOCKED, :I$MUST_CHANGE, :I$EXP_DATE, COALESCE(:I$IS_BLOCKED_PWD, 0))
        RETURNING USER_ID INTO :USER_ID;
    END
    ELSE
    BEGIN
        UPDATE USERS
        SET USER_TYPE   = :I$USER_TYPE,
            USER_NAME   = :I$USER_NAME,
            FIRST_NAME  = :FIRST_NAME,
            MIDDLE_NAME = :MIDDLE_NAME,
            LAST_NAME   = :LAST_NAME,
            LANG_CODE   = :I$LANG_CODE,
            IS_BLOCKED  = :I$IS_BLOCKED,
            MUST_CHANGE = :I$MUST_CHANGE,
            EXP_DATE    = :I$EXP_DATE,
            IS_BLOCKED_PWD  = COALESCE(:I$IS_BLOCKED_PWD, IS_BLOCKED_PWD)
        WHERE USER_ID   = :I$USER_ID;

        IF ((I$PWD <> '') OR ((I$PWD = '') AND (I$IS_BLOCKED = 1))) THEN
        BEGIN
            UPDATE USERS
            SET PWD = :I$PWD
            WHERE USER_ID = :USER_ID;
        END
    END

    EXECUTE PROCEDURE CJ2_JOURNAL_ACCESS_UPD(NULL, :USER_ID);

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE USERADM_ADD_USER (
    I$USER_ID BIGINT,
    I$USER_TYPE SMALLINT,
    I$USER_NAME VARCHAR(100),
    I$PWD VARCHAR(100),
    I$IS_BLOCKED SMALLINT,
    I$MUST_CHANGE SMALLINT,
    I$DATE_DEL TIMESTAMP,
    I$FIRST_NAME VARCHAR(100),
    I$MIDDLE_NAME VARCHAR(100),
    I$LAST_NAME VARCHAR(100),
    I$EXP_DATE DATE = null,
    I$LANG_CODE CHAR(2) = 'RU',
    I$SNILS VARCHAR(40) = null)
RETURNS (
    USER_ID BIGINT)
AS
BEGIN
    USER_ID = I$USER_ID;

    IF(I$SNILS IS NOT NULL) THEN
    BEGIN
      IF(NOT EXISTS(SELECT 1 FROM CHECK_SNILS(:I$SNILS) WHERE IS_REAL = 1))
        THEN EXCEPTION DATA_ERROR 'Введенный СНИЛС не валиден';
    END

    IF (I$USER_ID IS NULL) THEN
    BEGIN
        INSERT INTO USERS (USER_TYPE, USER_NAME, PWD, FIRST_NAME, MIDDLE_NAME, LAST_NAME, LANG_CODE, OBJ_ID, IS_BLOCKED, MUST_CHANGE, EXP_DATE, SNILS, DATE_DEL)
        VALUES (:I$USER_TYPE, :I$USER_NAME, :I$PWD, :I$FIRST_NAME, :I$MIDDLE_NAME, :I$LAST_NAME, :I$LANG_CODE, NULL, :I$IS_BLOCKED, :I$MUST_CHANGE, :I$EXP_DATE, :I$SNILS, :I$DATE_DEL)
        RETURNING USER_ID
        INTO :USER_ID;
    END
    ELSE
    BEGIN
        UPDATE USERS
        SET USER_TYPE = :I$USER_TYPE,
            USER_NAME = :I$USER_NAME,
            FIRST_NAME = :I$FIRST_NAME,
            MIDDLE_NAME = :I$MIDDLE_NAME,
            LAST_NAME = :I$LAST_NAME,
            LANG_CODE = :I$LANG_CODE,
            IS_BLOCKED = :I$IS_BLOCKED,
            MUST_CHANGE = :I$MUST_CHANGE,
            EXP_DATE = :I$EXP_DATE,
            SNILS = :I$SNILS,
            DATE_DEL = :I$DATE_DEL
        WHERE USER_ID = :I$USER_ID;

        IF (I$PWD <> '') THEN
        BEGIN
            UPDATE USERS
            SET PWD = :I$PWD
            WHERE USER_ID = :USER_ID;
        END
    END

    EXECUTE PROCEDURE CJ2_JOURNAL_ACCESS_UPD(NULL, :USER_ID);

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE USERADM_APP_ADD (
    I$LEVEL_ID BIGINT,
    I$USER_ID BIGINT,
    I$ROOT_OBJ_ID BIGINT,
    I$READ_ONLY SMALLINT = 0)
AS
declare variable V$LEVEL smallint;
BEGIN

    -- Для регионального уровня 0 = Уровень региона, зануляем
    SELECT FIRST 1 KEY_VAL FROM KEYS WHERE KEY_CODE = 'LEVEL' INTO :V$LEVEL;
    IF(V$LEVEL = 3 AND I$ROOT_OBJ_ID = 0) THEN I$ROOT_OBJ_ID = NULL;

    UPDATE OR INSERT INTO LUSERS (LEVEL_ID, USER_ID, ROOT_OBJ_ID, READ_ONLY)
    VALUES (:I$LEVEL_ID, :I$USER_ID, :I$ROOT_OBJ_ID, :I$READ_ONLY)
    MATCHING (LEVEL_ID, USER_ID);

    IF(I$LEVEL_ID = 50) THEN EXECUTE PROCEDURE CJ2_JOURNAL_ACCESS_UPD(NULL, :I$USER_ID);
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE USERADM_APP_CLEAR (
    I$USER_ID BIGINT)
AS
BEGIN
    DELETE FROM LUSERS WHERE USER_ID = :I$USER_ID;

    EXECUTE PROCEDURE CJ2_JOURNAL_ACCESS_UPD(NULL, :I$USER_ID);
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE USERADM_APP_GET (
    I$USER_ID BIGINT)
RETURNS (
    LEVEL_ID BIGINT,
    IS_CHECKED SMALLINT,
    LEVEL_NAME VARCHAR(4000),
    READ_ONLY SMALLINT,
    MODULE_ID BIGINT)
AS
declare variable MC varchar(100);
BEGIN
    FOR
        SELECT L.LEVEL_ID, R.VAL, M.MODULE_ID, M.MODULE_CODE
        FROM MODULES M
        JOIN TASKS T ON T.MODULE_ID = M.MODULE_ID AND T.IS_DEL = 0 
        JOIN LEVELS L ON L.TASK_ID = T.TASK_ID AND L.IS_DEL = 0
        JOIN RES R ON R.RES_ID = T.RES_ID AND R.LANG_CODE = 'RU' AND R.IS_DEL = 0
        WHERE M.IS_ACTIVE = 1 AND M.IS_DEL = 0
        ORDER BY M.SORT_ORDER, T.SORT_ORDER, L.SORT_ORDER
        INTO :LEVEL_ID, :LEVEL_NAME, :MODULE_ID, :MC
    DO
    BEGIN
        IS_CHECKED = 0;
        READ_ONLY = 0;

        SELECT FIRST 1 CASE WHEN READ_ONLY = 1 THEN 0 ELSE 1 END, READ_ONLY
        FROM LUSERS
        WHERE LEVEL_ID = :LEVEL_ID AND USER_ID = :I$USER_ID
        INTO :IS_CHECKED, :READ_ONLY;

        -- Убираем лишние приложения CJ
        -- В СПО пока оставляем все варианты
        IF(MC = 'CJOURNAL' AND LEVEL_ID NOT IN (46, 180, 230, 249, 254, 255)) THEN LEVEL_ID = NULL;

        IF(LEVEL_ID IS NOT NULL) THEN SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE USERADM_CHECK (
    I$USER_ID BIGINT,
    I$USER_NAME VARCHAR(100))
RETURNS (
    IS_LOGIN_EXISTS INTEGER,
    OWNER_CAPTION VARCHAR(500))
AS
DECLARE VARIABLE V$OBJ_ID BIGINT;
BEGIN
    FOR
      SELECT FIRST 1 1, U.OBJ_ID, 'Внештатный сотрудник: ' || TRIM(U.LAST_NAME || ' ' || U.FIRST_NAME || ' ' || U.MIDDLE_NAME)
      FROM USERS U
      WHERE U.USER_NAME = :I$USER_NAME AND ((:I$USER_ID IS NULL) OR (:I$USER_ID <> U.USER_ID)) AND U.DATE_DEL IS NULL
      INTO :IS_LOGIN_EXISTS, :V$OBJ_ID, :OWNER_CAPTION
    DO
    BEGIN
      IF (V$OBJ_ID IS NOT NULL) THEN
      BEGIN
         SELECT 'Сотрудник: ' || CAPTION
         FROM OBJECT_CAPTION_GET(:V$OBJ_ID)
         INTO :OWNER_CAPTION;
      END
      SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE USERADM_CJ_ACCESS_CLEAR (
    I$USER_ID BIGINT,
    I$CLASS_ID BIGINT,
    I$LEVEL_ID BIGINT = 0)
AS
BEGIN
    DELETE FROM CJ_ACCESS A
    WHERE A.USER_ID = :I$USER_ID
      AND A.CLASS_ID = :I$CLASS_ID
      AND COALESCE(A.LEVEL_ID, 0) = COALESCE(:I$LEVEL_ID, 0);
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE USERADM_CJ_ACCESS_GET (
    I$USER_ID BIGINT)
RETURNS (
    CLASS_CAPTION VARCHAR(4000),
    SUBJECT_CAPTION VARCHAR(4000),
    SORT_ORDER1 DOUBLE PRECISION,
    SORT_ORDER2 DOUBLE PRECISION,
    CLASS_ID BIGINT,
    SUBJECT_ID BIGINT,
    LEVEL_ID BIGINT,
    SUBJECT_TYPE SMALLINT)
AS
declare variable BUP_TYPE bigint;
BEGIN
    FOR SELECT CLASS_ID, SUBJECT_ID, COALESCE(LEVEL_ID, 0)
        FROM CJ_ACCESS
        WHERE USER_ID = :I$USER_ID
        INTO :CLASS_ID, :SUBJECT_ID, :LEVEL_ID
    DO
    BEGIN
        SELECT CAPTION, SORT_ORDER
        FROM OBJECT_CAPTION_GET(:CLASS_ID, NULL)
        INTO :CLASS_CAPTION, :SORT_ORDER1;

        SELECT CAPTION, SORT_ORDER
        FROM OBJECT_CAPTION_GET(:SUBJECT_ID, NULL)
        INTO :SUBJECT_CAPTION, :SORT_ORDER2;

        SELECT LV.LISTVAL_ID
        FROM LINKS L256
        INNER JOIN LINKS L50 on L50.OBJ_ID = L256.PARENT_ID AND L50.PARENT_TYPE_ID = 50
        INNER JOIN VALL LV on LV.OBJ_ID = L50.PARENT_ID and LV.PARAM_ID = 2545 AND LV.IS_DEL = 0
        WHERE L256.OBJ_ID = :CLASS_ID and L256.PARENT_TYPE_ID = 54
        INTO :BUP_TYPE;

        IF((BUP_TYPE IS NULL) OR (BUP_TYPE = 3)) THEN SUBJECT_TYPE = 0; ELSE SUBJECT_TYPE = 1;

        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE USERADM_CJ_ACCESS_SET (
    I$USER_ID BIGINT,
    I$CLASS_ID BIGINT,
    I$SUBJECT_ID BIGINT,
    DODELETE SMALLINT = 0,
    I$LEVEL_ID BIGINT = null)
AS
BEGIN
    IF (DODELETE = 0) THEN
    BEGIN
        IF (:I$LEVEL_ID IS NULL) THEN
        BEGIN
            UPDATE OR INSERT INTO CJ_ACCESS (USER_ID, CLASS_ID, SUBJECT_ID, LEVEL_ID)
            VALUES (:I$USER_ID, :I$CLASS_ID, :I$SUBJECT_ID, NULL);
        END
        ELSE
        BEGIN
            UPDATE OR INSERT INTO CJ_ACCESS (USER_ID, CLASS_ID, SUBJECT_ID, LEVEL_ID)
            VALUES (:I$USER_ID, :I$CLASS_ID, :I$SUBJECT_ID, :I$LEVEL_ID)
            MATCHING (USER_ID, CLASS_ID, SUBJECT_ID, LEVEL_ID);
        END
    END
    ELSE
    BEGIN
        DELETE FROM CJ_ACCESS
        WHERE USER_ID = :I$USER_ID
          AND CLASS_ID = :I$CLASS_ID
          AND SUBJECT_ID = :I$SUBJECT_ID
          AND COALESCE(LEVEL_ID, 0) = COALESCE(:I$LEVEL_ID, 0);
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE USERADM_CJ_DEFAULT_ACCESS (
    I$USER_ID BIGINT)
RETURNS (
    CAPTION VARCHAR(4000),
    SORT_ORDER1 DOUBLE PRECISION,
    SORT_ORDER2 DOUBLE PRECISION,
    SUBJECT_TYPE SMALLINT,
    GROUP_ID BIGINT)
AS
declare variable V$USER_TYPE smallint;
declare variable V$TEACHER_ID bigint;
declare variable V$VD_TYPE bigint;
declare variable V$USTAGE_ID bigint;
declare variable V$UPLAN_ID bigint;
declare variable V$OLD_ROOT_ACCESS_CLASS_ID bigint;
declare variable V$SUBJECT_ID bigint;
declare variable V$CAPTION varchar(4000);
declare variable V$SUBJECT_CAPTION varchar(4000);
declare variable V$TYPE_ID bigint;
declare variable V$IS_OK smallint;
declare variable V$SG_ID bigint;
declare variable V$SG_CAPTION varchar(4000);
BEGIN
    SORT_ORDER1 = 0;
    SORT_ORDER2 = 0;

    SELECT U.USER_TYPE, U.OBJ_ID
    FROM USERS U
    WHERE U.USER_ID = :I$USER_ID AND U.DATE_DEL IS NULL AND U.IS_BLOCKED = 0
    INTO :V$USER_TYPE, V$TEACHER_ID;

    /* Для руководства специальная подсветка */
    IF (V$USER_TYPE IN (1, 5, 6)) THEN
    BEGIN
        CAPTION = 'ПОЛНЫЙ ДОСТУП';
        SUBJECT_TYPE = 2;
        GROUP_ID = NULL;
        SUSPEND;
        EXIT;
    END

    /* Получаем ID класса, к которому назначен полный доступ как для руководителя по "старой схеме" */
    SELECT FIRST 1 ROOT_OBJ_ID
    FROM LUSERS
    WHERE LEVEL_ID IN (50, 174, /* AP */ 305, 440) AND USER_ID = :I$USER_ID
    INTO :V$OLD_ROOT_ACCESS_CLASS_ID;

    /* Для всех обычных преподавателей делаем общую выборку групп, и ее затем разбираем */
    FOR
        /* ГУП */
        SELECT DISTINCT LV381.SORT_ORDER, L256.OBJ_ID as GROUP_ID, L256.OBJ_TYPE_ID as TYPE_ID,
          L54.OBJ_ID as USTAGE_ID, L50.OBJ_ID as UPLAN_ID, V2545.LISTVAL_ID
        /* ОУ */
        FROM LINKS L2
        /* Образовательные программы */
        JOIN LINKS L69 ON L69.PARENT_ID = L2.OBJ_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL
        /* Образовательная программа */
        JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
        /* Учебный план */
        JOIN LINKS L50 ON L50.PARENT_ID = L57.OBJ_ID AND L50.OBJ_TYPE_ID = 50 AND L50.DATE_DEL IS NULL
        /* Этап учебного плана */
        JOIN LINKS L54 ON L54.PARENT_ID = L50.OBJ_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
        /* Номер этапа (параллели) - для сортировки */
        JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
        JOIN LISTVALS LV381 ON LV381.LISTVAL_ID = V381.LISTVAL_ID
        /* Тип плана - обычный или ВД */
        LEFT JOIN VALL V2545 ON V2545.OBJ_ID = L50.OBJ_ID AND V2545.PARAM_ID = 2545 AND V2545.IS_DEL = 0
        /* ГУП */
        JOIN LINKS L256 ON L256.PARENT_ID = L54.OBJ_ID AND L256.OBJ_TYPE_ID = 256 AND L256.DATE_DEL IS NULL
        /* Основная выборка - ОУ */
        WHERE L2.OBJ_TYPE_ID = 2 AND L2.PARENT_TYPE_ID IS NULL AND L2.DATE_DEL IS NULL

        UNION

        /* Потоки */
        SELECT DISTINCT LV381.SORT_ORDER, L347.OBJ_ID as GROUP_ID, L347.OBJ_TYPE_ID as TYPE_ID,
          L54.OBJ_ID as USTAGE_ID, L50.OBJ_ID as UPLAN_ID, V2545.LISTVAL_ID
        /* ОУ */
        FROM LINKS L2
        /* Образовательные программы */
        JOIN LINKS L69 ON L69.PARENT_ID = L2.OBJ_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL
        /* Образовательная программа */
        JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
        /* Учебный план */
        JOIN LINKS L50 ON L50.PARENT_ID = L57.OBJ_ID AND L50.OBJ_TYPE_ID = 50 AND L50.DATE_DEL IS NULL
        /* Этап учебного плана */
        JOIN LINKS L54 ON L54.PARENT_ID = L50.OBJ_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
        /* Номер этапа (параллели) - для сортировки */
        JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
        JOIN LISTVALS LV381 ON LV381.LISTVAL_ID = V381.LISTVAL_ID
        /* Тип плана - обычный или ВД */
        LEFT JOIN VALL V2545 ON V2545.OBJ_ID = L50.OBJ_ID AND V2545.PARAM_ID = 2545 AND V2545.IS_DEL = 0
        /* Потоки */
        JOIN LINKS L346 ON L346.PARENT_ID = L54.OBJ_ID AND L346.OBJ_TYPE_ID = 346 AND L346.DATE_DEL IS NULL
        /* Поток */
        JOIN LINKS L347 ON L347.PARENT_ID = L346.OBJ_ID AND L347.OBJ_TYPE_ID = 347 AND L347.DATE_DEL IS NULL
        /* Основная выборка - ОУ */
        WHERE L2.OBJ_TYPE_ID = 2 AND L2.PARENT_TYPE_ID IS NULL AND L2.DATE_DEL IS NULL

        /* Сортируем по классам */
        ORDER BY 1

        INTO :SORT_ORDER1, :GROUP_ID, :V$TYPE_ID, :V$USTAGE_ID, :V$UPLAN_ID, :V$VD_TYPE
    DO
    BEGIN

        /* Получаем наименование коллектива */
        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:GROUP_ID)
        INTO :V$CAPTION;

        /* Проверяем тип плана - обычный или ВД */
        IF((V$VD_TYPE IS NULL) OR (V$VD_TYPE = 3)) THEN SUBJECT_TYPE = 0; ELSE SUBJECT_TYPE = 1;

        /* Проверяем наличие классного руководства */
        EXECUTE PROCEDURE CJ_IS_GROUP_CLASSMATE(:V$TEACHER_ID, :GROUP_ID, :V$TYPE_ID, :V$OLD_ROOT_ACCESS_CLASS_ID) RETURNING_VALUES (:V$IS_OK);
        IF(V$IS_OK = 1) THEN
        BEGIN
            CAPTION = V$CAPTION || ' - ПОЛНЫЙ ДОСТУП';
            SUSPEND;
        END

        /* Предметы, доступ к которым задан в CJ_ACCESS - тут не показываем, они идут в другом разделе */

        /* Список предметов из УП, закрепленных за данным учителем. Здесь же выдается список подгрупп */
        FOR
            SELECT GL.SUBJECT_ID, SP.CAPTION, SP.SORT_ORDER, GL.SUBGROUP_ID, GP.CAPTION
            FROM PARAGRAF_GRADE_LOADING_LIST(:GROUP_ID, :V$UPLAN_ID) GL
            JOIN OBJECT_CAPTION_GET(GL.SUBJECT_ID, NULL, NULL, :I$USER_ID) SP ON 1=1
            JOIN OBJECT_CAPTION_GET(GL.SUBGROUP_ID, NULL, NULL, :I$USER_ID) GP ON 1=1
            WHERE GL.TEACHER_ID = :V$TEACHER_ID
            INTO :V$SUBJECT_ID, :V$SUBJECT_CAPTION, :SORT_ORDER2, :V$SG_ID, :V$SG_CAPTION
        DO
        BEGIN
            CAPTION = V$CAPTION || ' - ' || V$SUBJECT_CAPTION;
            IF(V$SG_ID <> GROUP_ID) THEN CAPTION = CAPTION || ' (' || V$SG_CAPTION || ')';
            SUSPEND;
        END

    END

END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE USERADM_CLASSES_LIST (
    FOR_USERS SMALLINT = 1)
RETURNS (
    OBJ_ID BIGINT,
    OBJ_CAPTION VARCHAR(4000),
    SORT_ORDER DOUBLE PRECISION)
AS
declare variable V$SCHOOL_ID bigint;
declare variable V$LIC_TYPE varchar(1);
declare variable V$LEVEL smallint;
BEGIN
  SELECT FIRST 1 L.OBJ_ID
  FROM LINKS L
  WHERE L.PARENT_ID IS NULL AND L.OBJ_TYPE_ID = 2 AND L.DATE_DEL IS NULL
  INTO :V$SCHOOL_ID;

  SELECT STATUS FROM OU_LICENCE_TYPE INTO :V$LIC_TYPE;
  SELECT FIRST 1 KEY_VAL FROM KEYS WHERE KEY_CODE = 'LEVEL' INTO :V$LEVEL;

  IF(V$LEVEL = 3) THEN
  BEGIN
      -- Уровень Регион - показываем районы + сам регион
      OBJ_ID = 0;
      OBJ_CAPTION = 'Регион';
      SORT_ORDER = 0;
      SUSPEND;

      FOR
          SELECT L111.OBJ_ID, C111.CAPTION, 0
          FROM LINKS L112
          JOIN LINKS L111 ON L111.PARENT_ID = L112.OBJ_ID AND L111.OBJ_TYPE_ID = 111 AND L111.DATE_DEL IS NULL
          LEFT JOIN OBJECT_CAPTION_GET(L111.OBJ_ID) C111 ON 1 = 1
          WHERE L112.PARENT_ID IS NULL AND L112.OBJ_TYPE_ID = 112 AND L112.DATE_DEL IS NULL
          ORDER BY 2
          INTO :OBJ_ID, :OBJ_CAPTION, :SORT_ORDER
      DO
      BEGIN
          SUSPEND;
      END
  END
  ELSE IF (V$LIC_TYPE = 'U') THEN
  BEGIN
    -- Для УДОД в диалоге прав для сотрудников выбираются не коллективы, а отделы
    IF(FOR_USERS = 1) THEN
    BEGIN
        FOR
            SELECT L211.OBJ_ID, C211.CAPTION, C211.SORT_ORDER
            FROM LINKS L2
            JOIN LINKS L211 ON L211.PARENT_ID = L2.OBJ_ID AND L211.OBJ_TYPE_ID = 211 AND L211.DATE_DEL IS NULL
            LEFT JOIN OBJECT_CAPTION_GET(L211.OBJ_ID) C211 ON 1=1
            WHERE L2.OBJ_ID = :V$SCHOOL_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
            ORDER BY 2
            INTO :OBJ_ID, :OBJ_CAPTION, :SORT_ORDER
        DO
        BEGIN
            SUSPEND;
        END
    END
    ELSE
    BEGIN
        FOR
            SELECT L243.OBJ_ID, CAST(C242.CAPTION || ' (' || C243.CAPTION || ')' AS VARCHAR(400)) CAPTION, C243.SORT_ORDER SORT_ORDER
            FROM LINKS L2
            JOIN LINKS L211 ON L211.PARENT_ID = L2.OBJ_ID AND L211.OBJ_TYPE_ID = 211 AND L211.DATE_DEL IS NULL
            JOIN LINKS L242 ON L242.PARENT_ID IN (L2.OBJ_ID, L211.OBJ_ID) AND L242.OBJ_TYPE_ID = 242 AND L242.DATE_DEL IS NULL
            JOIN LINKS L243 ON L243.PARENT_ID = L242.OBJ_ID AND L243.OBJ_TYPE_ID = 243 AND L243.DATE_DEL IS NULL
            LEFT JOIN OBJECT_CAPTION_GET(L242.OBJ_ID) C242 ON 1=1
            LEFT JOIN OBJECT_CAPTION_GET(L243.OBJ_ID) C243 ON 1=1
            WHERE L2.OBJ_ID = :V$SCHOOL_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
            ORDER BY C242.SORT_ORDER, C243.SORT_ORDER
            INTO :OBJ_ID, :OBJ_CAPTION, :SORT_ORDER
        DO
        BEGIN
            SUSPEND;
        END
    END
  END
  ELSE
  BEGIN
    FOR
        SELECT L9.OBJ_ID
        FROM LINKS L7
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
        WHERE L7.PARENT_ID = :V$SCHOOL_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL

        UNION

        SELECT L187.OBJ_ID
        FROM LINKS L7
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
        JOIN LINKS L187 ON L187.PARENT_ID = L8.OBJ_ID AND L187.OBJ_TYPE_ID = 187 AND L187.DATE_DEL IS NULL
        WHERE L7.PARENT_ID = :V$SCHOOL_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL

        INTO :OBJ_ID
    DO
    BEGIN
        SELECT CAPTION, SORT_ORDER
        FROM OBJECT_CAPTION_GET(:OBJ_ID)
        INTO :OBJ_CAPTION, SORT_ORDER;

        SUSPEND;
    END
  END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE USERADM_CLASS_SUBJECTS_LIST (
    I$USER_ID BIGINT,
    I$CLASS_ID BIGINT,
    I$TYPE_VD SMALLINT = 0)
RETURNS (
    SUBJECT_ID BIGINT,
    SUBJECT_CAPTION VARCHAR(4000),
    IS_CHECKED SMALLINT,
    SORT_ORDER DOUBLE PRECISION)
AS
declare variable V$TYPE_ID bigint;
BEGIN

    /* Для подгрупп необходимо получить вышестоящего родителя или ГУП */
    SELECT TYPE_ID FROM OBJECTS WHERE OBJ_ID = :I$CLASS_ID
    INTO :V$TYPE_ID;

    IF(V$TYPE_ID = 347) THEN
    BEGIN
        /* Поток */
        SELECT VA.VAL, CP.CAPTION, CP.SORT_ORDER
        FROM LINKS LP347
        JOIN VALR VA ON VA.OBJ_ID = LP347.PARENT_ID AND VA.PARAM_ID = 2705 AND VA.IS_DEL = 0
        LEFT JOIN OBJECT_CAPTION_GET(VA.VAL, NULL) CP ON 1=1
        WHERE LP347.OBJ_ID = :I$CLASS_ID AND LP347.PARENT_TYPE_ID = 346 AND LP347.DATE_DEL IS NULL
        INTO :SUBJECT_ID, :SUBJECT_CAPTION, :SORT_ORDER;

        SELECT COUNT(*)
        FROM CJ_ACCESS A
        WHERE A.USER_ID = :I$USER_ID AND A.CLASS_ID = :I$CLASS_ID AND A.SUBJECT_ID = :SUBJECT_ID
        INTO :IS_CHECKED;

        SUSPEND;
    END
    ELSE IF(V$TYPE_ID = 48) THEN
    BEGIN
        /* Подгруппа */
        SELECT VA.VAL, CP.CAPTION, CP.SORT_ORDER
        FROM LINKS LP47
        JOIN VALR VA ON VA.OBJ_ID = LP47.PARENT_ID AND VA.PARAM_ID = 428 AND VA.IS_DEL = 0
        LEFT JOIN OBJECT_CAPTION_GET(VA.VAL, NULL) CP ON 1=1
        WHERE LP47.OBJ_ID = :I$CLASS_ID AND LP47.PARENT_TYPE_ID = 47 AND LP47.DATE_DEL IS NULL
        INTO :SUBJECT_ID, :SUBJECT_CAPTION, :SORT_ORDER;

        SELECT COUNT(*)
        FROM CJ_ACCESS A
        WHERE A.USER_ID = :I$USER_ID AND A.CLASS_ID = :I$CLASS_ID AND A.SUBJECT_ID = :SUBJECT_ID
        INTO :IS_CHECKED;

        SUSPEND;
    END
    ELSE BEGIN

        /* ГУП */

        IF (I$TYPE_VD = 0) THEN
        BEGIN

            FOR SELECT DISTINCT L51.OBJ_ID
                FROM LINKS L54
                JOIN LINKS L50 ON L50.OBJ_ID = L54.PARENT_ID AND L50.PARENT_TYPE_ID = 50 AND L50.DATE_DEL IS NULL
                JOIN LINKS L49 ON L49.PARENT_ID = L50.PARENT_ID AND L49.OBJ_TYPE_ID = 49 AND L49.DATE_DEL IS NULL
                JOIN LINKS L51 ON L51.PARENT_ID = L49.OBJ_ID AND L51.OBJ_TYPE_ID = 51 AND L51.DATE_DEL IS NULL
                JOIN LINKS L56 ON L56.PARENT_ID = L50.OBJ_ID AND L56.OBJ_TYPE_ID = 56 AND L56.DATE_DEL IS NULL
                JOIN LINKS L51_56 ON L51_56.OBJ_ID = L56.OBJ_ID AND L51_56.PARENT_ID = L51.OBJ_ID AND L51_56.DATE_DEL IS NULL
                JOIN LINKS L49_56 ON L49_56.OBJ_ID = L56.OBJ_ID AND L49_56.PARENT_ID = L49.OBJ_ID AND L49_56.DATE_DEL IS NULL
                /* С ненулевой учебной нагрузкой */
                JOIN VALI VI ON VI.OBJ_ID = L56.OBJ_ID and VI.PARAM_ID = 385 and VI.IS_DEL = 0 AND VI.VAL > 0
                LEFT JOIN VALL VD ON VD.OBJ_ID = L50.PARENT_ID and VD.PARAM_ID = 2545 and VD.IS_DEL = 0
                WHERE L54.OBJ_ID = :I$CLASS_ID AND L54.PARENT_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
                  /* Исключить учебные планы внеурочной деятельности */
                  AND ((VD.LISTVAL_ID IS NULL) or (VD.LISTVAL_ID <> 2))
            INTO :SUBJECT_ID
            DO
            BEGIN
                SELECT CAPTION, SORT_ORDER
                FROM OBJECT_CAPTION_GET(:SUBJECT_ID, NULL)
                INTO :SUBJECT_CAPTION, :SORT_ORDER;

                SELECT COUNT(*)
                FROM CJ_ACCESS A
                WHERE A.USER_ID = :I$USER_ID AND A.CLASS_ID = :I$CLASS_ID AND A.SUBJECT_ID = :SUBJECT_ID
                INTO :IS_CHECKED;

                SUSPEND;
            END

        END
        ELSE BEGIN

            FOR SELECT DISTINCT L51.OBJ_ID
                FROM LINKS L54
                JOIN LINKS L50 ON L50.OBJ_ID = L54.PARENT_ID AND L50.PARENT_TYPE_ID = 50 AND L50.DATE_DEL IS NULL
                JOIN LINKS L49 ON L49.PARENT_ID = L50.PARENT_ID AND L49.OBJ_TYPE_ID = 49 AND L49.DATE_DEL IS NULL
                JOIN LINKS L51 ON L51.PARENT_ID = L49.OBJ_ID AND L51.OBJ_TYPE_ID = 51 AND L51.DATE_DEL IS NULL
                JOIN LINKS L56 ON L56.PARENT_ID = L50.OBJ_ID AND L56.OBJ_TYPE_ID = 56 AND L56.DATE_DEL IS NULL
                JOIN LINKS L51_56 ON L51_56.OBJ_ID = L56.OBJ_ID AND L51_56.PARENT_ID = L51.OBJ_ID AND L51_56.DATE_DEL IS NULL
                JOIN LINKS L49_56 ON L49_56.OBJ_ID = L56.OBJ_ID AND L49_56.PARENT_ID = L49.OBJ_ID AND L49_56.DATE_DEL IS NULL
                JOIN VALI VI ON VI.OBJ_ID = L56.OBJ_ID and VI.PARAM_ID = 385 and VI.IS_DEL = 0
                JOIN VALL VD ON VD.OBJ_ID = L50.PARENT_ID and VD.PARAM_ID = 2545 and VD.IS_DEL = 0 AND VD.LISTVAL_ID = 2
                WHERE L54.OBJ_ID = :I$CLASS_ID AND L54.PARENT_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
                  /* С ненулевой учебной нагрузкой */
                  AND VI.VAL > 0
                INTO :SUBJECT_ID
            DO
            BEGIN
                SELECT CAPTION, SORT_ORDER
                FROM OBJECT_CAPTION_GET(:SUBJECT_ID, NULL)
                INTO :SUBJECT_CAPTION, :SORT_ORDER;
            
                SELECT COUNT(*)
                FROM CJ_ACCESS A
                WHERE A.USER_ID = :I$USER_ID AND A.CLASS_ID = :I$CLASS_ID AND A.SUBJECT_ID = :SUBJECT_ID
                INTO :IS_CHECKED;

                SUSPEND;
            END

        END

    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE USERADM_DEL (
    I$USER_ID BIGINT)
AS
BEGIN
    UPDATE USERS
    SET DATE_DEL = CURRENT_TIMESTAMP
    WHERE USER_ID = :I$USER_ID;

    UPDATE CJ2_JOURNAL_AUTOUSERS
    SET DATE_DEL = CURRENT_TIMESTAMP
    WHERE DATE_DEL IS NULL AND USER_ID = :I$USER_ID;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE USERADM_GET (
    I$OBJ_ID BIGINT)
RETURNS (
    USER_ID BIGINT,
    USER_TYPE SMALLINT,
    USER_NAME VARCHAR(100),
    PWD VARCHAR(100),
    IS_BLOCKED SMALLINT,
    MUST_CHANGE SMALLINT,
    EXP_DATE DATE,
    CLASS_ID BIGINT,
    USER_TYPE_NAME VARCHAR(4000),
    CLASS_NAME VARCHAR(4000),
    IS_BLOCKED_PWD SMALLINT)
AS
declare variable V$LANG_CODE char(2);
BEGIN
    SELECT USER_ID,
           USER_TYPE,
           USER_NAME,
           PWD,
           IS_BLOCKED,
           MUST_CHANGE,
           EXP_DATE,
           LANG_CODE,
           IS_BLOCKED_PWD
    FROM USERS
    WHERE OBJ_ID = :I$OBJ_ID
    AND DATE_DEL IS NULL
    INTO :USER_ID,
         :USER_TYPE,
         :USER_NAME,
         :PWD,
         :IS_BLOCKED,
         :MUST_CHANGE,
         :EXP_DATE,
         :V$LANG_CODE,
         :IS_BLOCKED_PWD;

    SELECT FIRST 1 ROOT_OBJ_ID
    FROM LUSERS
    WHERE LEVEL_ID IN (50, 174, 239, 240, 241, 243, 245, /* AP */ 305, 440 /*, 391, 392, 393, 395, 396 */)
    AND ROOT_OBJ_ID IS NOT NULL
    AND USER_ID = :USER_ID
    INTO :CLASS_ID;

    SELECT FIRST 1 R.VAL
    FROM USERTYPES U

    JOIN RES R
    ON R.RES_ID = U.RES_ID

    WHERE U.USER_TYPE = :USER_TYPE
    AND R.LANG_CODE IN ('RU', :V$LANG_CODE)
    AND R.IS_DEL = 0

    ORDER BY IIF(R.LANG_CODE = :V$LANG_CODE, 0, 1)
    INTO :USER_TYPE_NAME;

    SELECT CAPTION
    FROM OBJECT_CAPTION_GET(:CLASS_ID)
    INTO :CLASS_NAME;

    SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE USERADM_GRADE_DISCIPLINES_LIST (
    I$USER_ID BIGINT,
    I$LEVEL_ID BIGINT,
    I$GRADE_ID BIGINT)
RETURNS (
    DISCIPLINE_ID BIGINT,
    DISCIPLINE_CAPTION VARCHAR(4000),
    IS_CHECKED SMALLINT,
    SORT_ORDER DOUBLE PRECISION)
AS
BEGIN
    FOR SELECT
            OBJ_ID,
            OBJ_CAPTION,
            SORT_ORDER
        FROM CJ_COLLEGE_SUBJECTS_LIST(:I$GRADE_ID, NULL, :I$LEVEL_ID)
        INTO :DISCIPLINE_ID, :DISCIPLINE_CAPTION, :SORT_ORDER
    DO
    BEGIN
        SELECT COUNT(*)
        FROM CJ_ACCESS A
        WHERE A.USER_ID = :I$USER_ID
          AND A.LEVEL_ID = :I$LEVEL_ID
          AND A.CLASS_ID = :I$GRADE_ID
          AND A.SUBJECT_ID = :DISCIPLINE_ID
        INTO :IS_CHECKED;

        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE USERADM_GUPS_LIST (
    TYPE_VD SMALLINT)
RETURNS (
    OBJ_ID BIGINT,
    OBJ_CAPTION VARCHAR(4000),
    SORT_ORDER DOUBLE PRECISION)
AS
declare variable SCHOOL_ID bigint;
declare variable V$GUP_ID bigint;
declare variable V$DIV_ID bigint;
declare variable V$GUP_CAPTION varchar(1000);
declare variable V$DIV_CAPTION varchar(1000);
BEGIN
    SELECT FIRST 1 L.OBJ_ID
    FROM LINKS L
    WHERE L.PARENT_ID IS NULL AND L.OBJ_TYPE_ID = 2 AND L.DATE_DEL IS NULL
    INTO :SCHOOL_ID;

    IF(TYPE_VD = 0) THEN
    BEGIN

        /* ГУП */
        FOR
            SELECT L256.OBJ_ID, LV.SORT_ORDER
            FROM LINKS L69
            JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
            JOIN LINKS L50 ON L50.PARENT_ID = L57.OBJ_ID AND L50.OBJ_TYPE_ID = 50 AND L50.DATE_DEL IS NULL
            JOIN LINKS L54 ON L54.PARENT_ID = L50.OBJ_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
            JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
            JOIN LISTVALS LV ON LV.LISTVAL_ID = V381.LISTVAL_ID AND LV.IS_DEL = 0
            JOIN LINKS L256 ON L256.PARENT_ID = L54.OBJ_ID AND L256.OBJ_TYPE_ID = 256 AND L256.DATE_DEL IS NULL
            LEFT JOIN VALL VL ON VL.OBJ_ID = L50.OBJ_ID AND VL.PARAM_ID = 2545 AND VL.IS_DEL = 0
            WHERE L69.PARENT_ID = :SCHOOL_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL AND (VL.LISTVAL_ID IS NULL OR VL.LISTVAL_ID = 3)
            ORDER BY LV.SORT_ORDER
            INTO :OBJ_ID, :SORT_ORDER
        DO
        BEGIN
            SELECT CAPTION, SORT_ORDER
            FROM OBJECT_CAPTION_GET(:OBJ_ID)
            INTO :OBJ_CAPTION, SORT_ORDER;

            SUSPEND;
        END

        /* Потоки */
        FOR
            SELECT L346.OBJ_ID, L347.OBJ_ID, LV.SORT_ORDER
            FROM LINKS L69
            JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
            JOIN LINKS L50 ON L50.PARENT_ID = L57.OBJ_ID AND L50.OBJ_TYPE_ID = 50 AND L50.DATE_DEL IS NULL
            JOIN LINKS L54 ON L54.PARENT_ID = L50.OBJ_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
            JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
            JOIN LISTVALS LV ON LV.LISTVAL_ID = V381.LISTVAL_ID AND LV.IS_DEL = 0
            JOIN LINKS L346 ON L346.PARENT_ID = L54.OBJ_ID AND L346.OBJ_TYPE_ID = 346 AND L346.DATE_DEL IS NULL
            JOIN LINKS L347 ON L347.PARENT_ID = L346.OBJ_ID AND L347.OBJ_TYPE_ID = 347 AND L347.DATE_DEL IS NULL
            LEFT JOIN VALL VL ON VL.OBJ_ID = L50.OBJ_ID AND VL.PARAM_ID = 2545 AND VL.IS_DEL = 0
            WHERE L69.PARENT_ID = :SCHOOL_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL AND (VL.LISTVAL_ID IS NULL OR VL.LISTVAL_ID = 3)
            ORDER BY LV.SORT_ORDER
            INTO :V$DIV_ID, :OBJ_ID, :SORT_ORDER
        DO
        BEGIN
            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:V$DIV_ID)
            INTO :V$DIV_CAPTION;

            SELECT :V$DIV_CAPTION || ', ' || CAPTION
            FROM OBJECT_CAPTION_GET(:OBJ_ID)
            INTO :OBJ_CAPTION;

            SUSPEND;
        END

    END
    ELSE
    BEGIN

        /* ГУП */
        FOR
            SELECT L256.OBJ_ID, LV.SORT_ORDER
            FROM LINKS L69
            JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
            JOIN LINKS L50 ON L50.PARENT_ID = L57.OBJ_ID AND L50.OBJ_TYPE_ID = 50 AND L50.DATE_DEL IS NULL
            JOIN LINKS L54 ON L54.PARENT_ID = L50.OBJ_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
            JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
            JOIN LISTVALS LV ON LV.LISTVAL_ID = V381.LISTVAL_ID AND LV.IS_DEL = 0
            JOIN LINKS L256 ON L256.PARENT_ID = L54.OBJ_ID AND L256.OBJ_TYPE_ID = 256 AND L256.DATE_DEL IS NULL
            JOIN VALL VL ON VL.OBJ_ID = L50.OBJ_ID AND VL.PARAM_ID = 2545 AND VL.IS_DEL = 0 AND VL.LISTVAL_ID = 2
            WHERE L69.PARENT_ID = :SCHOOL_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL
            INTO :OBJ_ID, :SORT_ORDER
        DO
        BEGIN
            SELECT CAPTION, SORT_ORDER
            FROM OBJECT_CAPTION_GET(:OBJ_ID)
            INTO :OBJ_CAPTION, SORT_ORDER;

            SUSPEND;
        END

        FOR
            SELECT L346.OBJ_ID, L347.OBJ_ID, LV.SORT_ORDER
            FROM LINKS L69
            JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
            JOIN LINKS L50 ON L50.PARENT_ID = L57.OBJ_ID AND L50.OBJ_TYPE_ID = 50 AND L50.DATE_DEL IS NULL
            JOIN LINKS L54 ON L54.PARENT_ID = L50.OBJ_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
            JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
            JOIN LISTVALS LV ON LV.LISTVAL_ID = V381.LISTVAL_ID AND LV.IS_DEL = 0
            JOIN LINKS L346 ON L346.PARENT_ID = L54.OBJ_ID AND L346.OBJ_TYPE_ID = 346 AND L346.DATE_DEL IS NULL
            JOIN LINKS L347 ON L347.PARENT_ID = L346.OBJ_ID AND L347.OBJ_TYPE_ID = 347 AND L347.DATE_DEL IS NULL
            JOIN VALL VL ON VL.OBJ_ID = L50.OBJ_ID AND VL.PARAM_ID = 2545 AND VL.IS_DEL = 0
            WHERE L69.PARENT_ID = :SCHOOL_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL AND VL.LISTVAL_ID = 2
            ORDER BY LV.SORT_ORDER
            INTO :V$DIV_ID, :OBJ_ID, :SORT_ORDER
        DO
        BEGIN
            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:V$DIV_ID)
            INTO :V$DIV_CAPTION;

            SELECT :V$DIV_CAPTION || ', ' || CAPTION
            FROM OBJECT_CAPTION_GET(:OBJ_ID)
            INTO :OBJ_CAPTION;

            SUSPEND;
        END

    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE USERADM_JGPD_LIST (
    I$USER_ID BIGINT,
    I$LEVEL_ID INTEGER = 189)
RETURNS (
    GPD_ID BIGINT,
    GPD_CAPTION VARCHAR(500),
    IS_CHECKED SMALLINT)
AS
declare variable SCHOOL_ID bigint;
BEGIN
    SELECT FIRST 1 L.OBJ_ID
    FROM LINKS L
    WHERE L.PARENT_ID IS NULL
    AND L.OBJ_TYPE_ID = 2
    AND L.DATE_DEL IS NULL
    INTO :SCHOOL_ID;

    FOR
        SELECT L46.OBJ_ID
        FROM LINKS L86

        LEFT JOIN VALL VL1579
        ON VL1579.OBJ_ID = L86.OBJ_ID
        AND VL1579.IS_DEL = 0
        AND VL1579.PARAM_ID = 1579
        AND VL1579.LISTVAL_ID =
            CASE :I$LEVEL_ID
                WHEN 274 THEN 3316 -- OutAct
                WHEN 318 THEN 3316 -- OutAct AP
                WHEN 275 THEN 3315 -- AddEdu
                WHEN 319 THEN 3315 -- AddEdu AP
                ELSE 3317          -- GPD
            END

        JOIN LINKS L46
        ON L46.OBJ_TYPE_ID = 46
        AND L46.DATE_DEL IS NULL
        AND L46.PARENT_ID = L86.OBJ_ID

        LEFT JOIN VALL VL369
        ON VL369.OBJ_ID = L46.OBJ_ID
        AND VL369.IS_DEL = 0
        AND VL369.PARAM_ID = 369
        AND VL369.LISTVAL_ID = IIF(:I$LEVEL_ID = 189, 1246, 3318)

        LEFT JOIN VALR VR
        ON VR.OBJ_ID = L46.OBJ_ID
        AND VR.PARAM_ID = 550
        AND VR.IS_DEL = 0

        WHERE L86.OBJ_TYPE_ID = 86
        AND L86.DATE_DEL IS NULL
        AND L86.PARENT_ID = :SCHOOL_ID
        AND ((SELECT STATUS FROM OU_LICENCE_TYPE) = 'C'
         OR (VL369.OBJ_ID IS NOT NULL AND VL1579.OBJ_ID IS NOT NULL))

        INTO :GPD_ID
    DO
    BEGIN
        IF (EXISTS(
            SELECT FIRST 1 1
            FROM CJ_ACCESS
            WHERE USER_ID = :I$USER_ID
            AND CLASS_ID = :GPD_ID
        )) THEN
        BEGIN
            IS_CHECKED = 1;
        END
        ELSE
        BEGIN
            IS_CHECKED = 0;
        END

        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:GPD_ID, NULL)
        INTO :GPD_CAPTION;
    
        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE USERADM_LOG_LIST (
    I$DATA_START TIMESTAMP,
    I$DATE_END TIMESTAMP,
    I$LANG_CODE CHAR(2))
RETURNS (
    DATE_START TIMESTAMP,
    DATE_EXIT TIMESTAMP,
    PC_NAME VARCHAR(100),
    LEVEL_CAPTION VARCHAR(1000),
    TASK_CAPTION VARCHAR(1000),
    MODULE_CAPTION VARCHAR(1000),
    FIO VARCHAR(100),
    USER_NAME VARCHAR(100))
AS
declare variable LEVEL_RES_ID bigint;
declare variable TASK_RES_ID bigint;
declare variable MODULE_RES_ID bigint;
BEGIN
    FOR SELECT L.DATE_START, L.DATE_EXIT, L.PC_NAME, LV.RES_ID, T.RES_ID, M.RES_ID,
               COALESCE(US.LAST_NAME, '') || ' ' || COALESCE(US.FIRST_NAME, '') || ' ' || COALESCE(US.MIDDLE_NAME, ' '), US.USER_NAME
        FROM "LOG" L
        INNER JOIN USERS US ON US.USER_ID = L.USER_ID
        INNER JOIN LEVELS LV ON LV.LEVEL_ID = L.LEVEL_ID
        INNER JOIN TASKS T ON T.TASK_ID = LV.TASK_ID
        INNER JOIN MODULES M ON M.MODULE_ID = T.MODULE_ID
        WHERE L.DATE_START >= :I$DATA_START
          AND L.DATE_START <= :I$DATE_END
        ORDER BY L.DATE_START
        INTO :DATE_START, :DATE_EXIT, :PC_NAME, :LEVEL_RES_ID, :TASK_RES_ID, :MODULE_RES_ID, :FIO, :USER_NAME
    DO
    BEGIN
        SELECT VAL
        FROM RES_GET(:LEVEL_RES_ID, :I$LANG_CODE)
        INTO :LEVEL_CAPTION;

        SELECT VAL
        FROM RES_GET(:TASK_RES_ID, :I$LANG_CODE)
        INTO :TASK_CAPTION;

        SELECT VAL
        FROM RES_GET(:MODULE_RES_ID, :I$LANG_CODE)
        INTO :MODULE_CAPTION;

        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE USERADM_PUPILS_LIST (
    I$CLASS_ID BIGINT)
RETURNS (
    PUPIL_ID BIGINT,
    USER_ID BIGINT,
    USER_NAME VARCHAR(100),
    FIO VARCHAR(500),
    USER_TYPE SMALLINT,
    PWD VARCHAR(100),
    DATE_DEL TIMESTAMP,
    MUST_CHANGE SMALLINT,
    FIRST_NAME VARCHAR(100),
    MIDDLE_NAME VARCHAR(100),
    LAST_NAME VARCHAR(100),
    DESCRIPTION VARCHAR(100),
    LANG_CODE CHAR(2),
    IS_BLOCKED SMALLINT,
    EXP_DATE DATE,
    IS_DEL SMALLINT,
    USER_TYPE_NAME VARCHAR(100),
    DOB DATE,
    SDO_ID VARCHAR(100),
    CLASS_NAME VARCHAR(100))
AS
declare variable V$NUM integer;
declare variable V$USED smallint;
BEGIN
    -- Нумерация пойдет с 1
    V$NUM = 0;

    FOR
        SELECT L10.OBJ_ID, US.USER_ID, US.USER_NAME,
               COALESCE(US.FIRST_NAME, '') || ' ' || COALESCE(US.MIDDLE_NAME, '') || ' ' || COALESCE(US.LAST_NAME, ''),
               US.PWD, US.MUST_CHANGE, US.EXP_DATE, US.IS_BLOCKED, 12, US.DATE_DEL, US.DESCRIPTION, US.LANG_CODE,
               C.CAPTION
        FROM LINKS L10
        LEFT JOIN USERS US ON US.OBJ_ID = L10.OBJ_ID
        LEFT JOIN OBJECT_CAPTION_GET(L10.PARENT_ID) C ON 1 = 1
        WHERE L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL AND (
            (L10.PARENT_ID = :I$CLASS_ID) OR
            (:I$CLASS_ID IS NULL AND L10.PARENT_TYPE_ID IN (9, 187))
        )
        ORDER BY C.CAPTION, USER_ID
        INTO :PUPIL_ID, :USER_ID, :USER_NAME,
             :FIO,
             :PWD, :MUST_CHANGE, :EXP_DATE, :IS_BLOCKED, :USER_TYPE, :DATE_DEL, :DESCRIPTION, :LANG_CODE,
             :CLASS_NAME
    DO
    BEGIN

        IF (USER_NAME IS NULL) THEN
        BEGIN
            -- Пытаемся искать свободные идентификаторы учеников, начиная с текущего
            V$USED = 1;

            WHILE(V$USED = 1) DO
            BEGIN
              V$NUM = V$NUM + 1;
              USER_NAME = 'Ученик' || V$NUM;

              V$USED = 0;
              SELECT FIRST 1 1
              FROM USERS
              WHERE USER_NAME = :USER_NAME
              INTO :V$USED;

            END
        END

        SELECT D FROM VAL_GET(:PUPIL_ID, 89) INTO :DOB;
        SELECT V FROM VAL_GET(:PUPIL_ID, 2153) INTO :SDO_ID;
        SELECT V FROM VAL_GET(:PUPIL_ID, 55) INTO :LAST_NAME;
        SELECT V FROM VAL_GET(:PUPIL_ID, 57) INTO :MIDDLE_NAME;
        SELECT V FROM VAL_GET(:PUPIL_ID, 56) INTO :FIRST_NAME;

        SELECT R.VAL
        FROM USERTYPES U
        JOIN RES R ON R.RES_ID = U.RES_ID AND R.LANG_CODE = 'RU' AND R.IS_DEL = 0
        WHERE U.USER_TYPE = :USER_TYPE
        ORDER BY SORT_ORDER
        INTO :USER_TYPE_NAME;

        IF (DATE_DEL <= CURRENT_TIMESTAMP) THEN
        BEGIN
            IS_DEL = 1;
        END
        ELSE
        BEGIN
            IS_DEL = 0;
        END
        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE USERADM_ROLE_LIST (
    I$ROLEUSER_ID BIGINT,
    I$LANG_CODE CHAR(2))
RETURNS (
    FIO VARCHAR(100),
    USER_NAME VARCHAR(50),
    IS_BLOCKED VARCHAR(12))
AS
BEGIN
    FOR SELECT COALESCE(U.LAST_NAME, '') || ' ' || COALESCE(U.FIRST_NAME, '') || ' ' || COALESCE(U.MIDDLE_NAME, '') AS FIO, U.USER_NAME,
               CASE
                 WHEN U.IS_BLOCKED = 0 THEN 'Активна'
                 ELSE 'Блокирована'
               END AS IS_BLOCKED
        FROM USERS U
        WHERE U.DATE_DEL IS NULL
          AND U.USER_TYPE = :I$ROLEUSER_ID
          AND U.LANG_CODE = :I$LANG_CODE
        INTO :FIO, :USER_NAME, :IS_BLOCKED
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE USERADM_TEACHERS_LIST RETURNS (
    PUPIL_ID BIGINT,
    USER_ID BIGINT,
    USER_NAME VARCHAR(100),
    USER_TYPE SMALLINT,
    PWD VARCHAR(100),
    FIRST_NAME VARCHAR(100),
    MIDDLE_NAME VARCHAR(100),
    LAST_NAME VARCHAR(100),
    IS_BLOCKED SMALLINT,
    DOB DATE,
    TESTING_ONLY SMALLINT,
    SDO_ID VARCHAR(100))
AS
declare variable V$NUM integer;
BEGIN
    V$NUM = 1;
    FOR
        SELECT L14.OBJ_ID, US.USER_ID, US.USER_NAME, US.PWD, US.IS_BLOCKED, COALESCE(US.USER_TYPE, 9)
        FROM LINKS L14
        LEFT JOIN USERS US ON US.OBJ_ID = L14.OBJ_ID
        WHERE L14.PARENT_TYPE_ID = 2 AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
        ORDER BY USER_ID
        INTO :PUPIL_ID, :USER_ID, :USER_NAME, :PWD, :IS_BLOCKED, :USER_TYPE
    DO
    BEGIN

        IF (USER_NAME IS NULL) THEN
        BEGIN
            TESTING_ONLY = 1;
            WHILE (V$NUM < 1000) DO
            BEGIN
                USER_NAME = 'Сотрудник' || V$NUM;
                V$NUM = V$NUM + 1;
                IF (NOT EXISTS(
                    SELECT FIRST 1 1
                    FROM USERS
                    WHERE USER_NAME = :USER_NAME)) THEN
                BEGIN
                    BREAK;
                END
            END
        END
        ELSE
        BEGIN
            TESTING_ONLY = IIF(EXISTS(
                SELECT FIRST 1 1
                FROM LUSERS
                WHERE USER_ID = :USER_ID AND LEVEL_ID NOT IN (138, 154, 155, 208)), 0, 1);
        END

        SELECT D FROM VAL_GET(:PUPIL_ID, 241) INTO :DOB;
        SELECT V FROM VAL_GET(:PUPIL_ID, 59) INTO :LAST_NAME;
        SELECT V FROM VAL_GET(:PUPIL_ID, 61) INTO :MIDDLE_NAME;
        SELECT V FROM VAL_GET(:PUPIL_ID, 60) INTO :FIRST_NAME;
        SELECT V FROM VAL_GET(:PUPIL_ID, 2152) INTO :SDO_ID;

        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE USERADM_USERS_LIST RETURNS (
    USER_ID BIGINT,
    USER_NAME VARCHAR(100),
    FIO VARCHAR(500),
    USER_TYPE SMALLINT,
    PWD VARCHAR(100),
    DATE_DEL TIMESTAMP,
    MUST_CHANGE SMALLINT,
    FIRST_NAME VARCHAR(100),
    MIDDLE_NAME VARCHAR(100),
    LAST_NAME VARCHAR(100),
    DESCRIPTION VARCHAR(100),
    LANG_CODE CHAR(2),
    IS_BLOCKED SMALLINT,
    EXP_DATE DATE,
    IS_DEL SMALLINT,
    CLASS_ID BIGINT,
    USER_TYPE_NAME VARCHAR(100),
    CLASS_NAME VARCHAR(100),
    SNILS VARCHAR(40))
AS
declare variable V$LEVEL smallint;
BEGIN

    SELECT FIRST 1 KEY_VAL FROM KEYS WHERE KEY_CODE = 'LEVEL' INTO :V$LEVEL;

    FOR
        SELECT US.USER_ID, US.USER_NAME, COALESCE(US.FIRST_NAME, '') || ' ' || COALESCE(US.MIDDLE_NAME, '') || ' ' || COALESCE(US.LAST_NAME, ''), US.SNILS,
               US.PWD, US.MUST_CHANGE, US.EXP_DATE, US.IS_BLOCKED, US.USER_TYPE, US.FIRST_NAME, US.MIDDLE_NAME, US.LAST_NAME, US.DATE_DEL, US.DESCRIPTION, US.LANG_CODE
        FROM USERS US
        WHERE US.OBJ_ID IS NULL --and us.Date_del is null
        ORDER BY USER_ID
        INTO :USER_ID, :USER_NAME, :FIO, :SNILS,
             :PWD, :MUST_CHANGE, :EXP_DATE, :IS_BLOCKED, :USER_TYPE, :FIRST_NAME, :MIDDLE_NAME, :LAST_NAME, :DATE_DEL, :DESCRIPTION, :LANG_CODE
    DO
    BEGIN
        -- Учебный коллектив или район
        CLASS_ID = NULL;
        IF(V$LEVEL = 3) THEN
        BEGIN
            SELECT FIRST 1 ROOT_OBJ_ID
            FROM LUSERS
            WHERE USER_ID = :USER_ID AND ROOT_OBJ_ID IS NOT NULL
            INTO :CLASS_ID;

            -- Добавление от 20.10.2022 - если не указан район, считаем что это регион
            IF(CLASS_ID IS NULL) THEN CLASS_ID = 0;
        END
        ELSE
        BEGIN
            SELECT FIRST 1 ROOT_OBJ_ID
            FROM LUSERS
            WHERE LEVEL_ID IN (50, 174, /* AP */ 305, 440) AND USER_ID = :USER_ID
            INTO :CLASS_ID;
        END

        SELECT R.VAL
        FROM USERTYPES U
        JOIN RES R ON R.RES_ID = U.RES_ID
        WHERE U.USER_TYPE = :USER_TYPE AND R.LANG_CODE = 'RU' AND R.IS_DEL = 0
        ORDER BY SORT_ORDER
        INTO :USER_TYPE_NAME;

        IF(USER_TYPE = 8 AND V$LEVEL = 3) THEN USER_TYPE_NAME = 'Специалист района';

        IF(CLASS_ID = 0) THEN CLASS_NAME = 'Регион'; ELSE SELECT CAPTION FROM OBJECT_CAPTION_GET(:CLASS_ID) INTO :CLASS_NAME;

        IF (DATE_DEL <= CURRENT_TIMESTAMP) THEN
        BEGIN
            IS_DEL = 1;
        END
        ELSE
        BEGIN
            IS_DEL = 0;
        END
        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE USERADM_USERS_LIST2 (
    I$USER_ID VARCHAR(40))
RETURNS (
    USER_ID BIGINT,
    USER_NAME VARCHAR(100),
    FIO VARCHAR(500),
    USER_TYPE SMALLINT,
    MUST_CHANGE SMALLINT,
    DESCRIPTION VARCHAR(100),
    LANG_CODE CHAR(2),
    IS_BLOCKED SMALLINT,
    EXP_DATE DATE,
    IS_DEL SMALLINT,
    CLASS_ID BIGINT,
    USER_TYPE_NAME VARCHAR(100),
    CLASS_NAME VARCHAR(100))
AS
begin

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  IF(I$USER_ID <> 1) THEN
  BEGIN
    IF(NOT EXISTS(
      SELECT FIRST 1 1
      FROM USERS U
      JOIN LUSERS LU ON LU.USER_ID = U.USER_ID
      JOIN LEVELS L ON L.LEVEL_ID = LU.LEVEL_ID
      JOIN TASKS T ON T.TASK_ID = L.TASK_ID
      JOIN RES R ON R.RES_ID = T.RES_ID AND R.LANG_CODE = 'RU' AND R.VAL = 'Администрирование пользователей'
      WHERE U.USER_ID = :I$USER_ID AND U.IS_BLOCKED = 0 AND U.DATE_DEL IS NULL
    )) THEN EXCEPTION DATA_ERROR 'Нет доступа к приложению';
  END

  FOR
    SELECT USER_ID, USER_NAME, FIO, USER_TYPE, MUST_CHANGE, DESCRIPTION, LANG_CODE, IS_BLOCKED, EXP_DATE, IS_DEL, USER_TYPE_NAME, CLASS_NAME
    FROM USERADM_USERS_LIST
    WHERE DATE_DEL IS NULL
    INTO :USER_ID, :USER_NAME, :FIO, :USER_TYPE, :MUST_CHANGE, :DESCRIPTION, :LANG_CODE, :IS_BLOCKED, :EXP_DATE, :IS_DEL, :USER_TYPE_NAME, :CLASS_NAME
  DO
  BEGIN
    SUSPEND;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE USERADM_USERTYPES_LIST RETURNS (
    OBJ_ID BIGINT,
    OBJ_CAPTION VARCHAR(4000))
AS
declare variable V$LANG_CODE varchar(2);
declare variable V$LIC_TYPE char(1);
declare variable V$LEVEL smallint;
BEGIN

    -- Для УДОД идет подмена названия через код LANG у администратора
    SELECT LANG_CODE FROM USERS WHERE USER_ID = 1 INTO :V$LANG_CODE;

    SELECT STATUS FROM OU_LICENCE_TYPE INTO :V$LIC_TYPE;
    SELECT FIRST 1 KEY_VAL FROM KEYS WHERE KEY_CODE = 'LEVEL' INTO :V$LEVEL;

    FOR
        SELECT U.USER_TYPE, (
            SELECT FIRST 1 R.VAL
            FROM RES R
            WHERE R.RES_ID = U.RES_ID AND R.LANG_CODE IN ('RU', :V$LANG_CODE) AND R.IS_DEL = 0
            ORDER BY IIF(R.LANG_CODE = :V$LANG_CODE, 0, 1))
        FROM USERTYPES U
        JOIN RES R ON R.RES_ID = U.RES_ID AND R.LANG_CODE = 'RU' AND R.IS_DEL = 0
        ORDER BY SORT_ORDER
        INTO :OBJ_ID, :OBJ_CAPTION
    DO
    BEGIN
        -- На городском уровне вместо роли "классный руководитель" отдаем "специалист района", а учителя-предметника вообще не показываем
        IF(OBJ_ID = 8 AND V$LEVEL = 3) THEN OBJ_CAPTION = 'Специалист района';

        -- Прячем классного руководителя, библиотекаря, воспитателя на уровне выше ОУ
        IF(OBJ_ID NOT IN (9, 11, 19) OR V$LEVEL = 1) THEN SUSPEND;
    END

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE USERS_LIST (
    I$USER_TYPE SMALLINT)
RETURNS (
    USER_ID BIGINT,
    USER_TYPE SMALLINT,
    USER_NAME VARCHAR(100),
    DATE_DEL TIMESTAMP,
    PWD VARCHAR(100),
    FIRST_NAME VARCHAR(100),
    MIDDLE_NAME VARCHAR(100),
    LAST_NAME VARCHAR(100),
    DESCRIPTION VARCHAR(100),
    LANG_CODE CHAR(2),
    OBJ_ID BIGINT,
    OBJECT_CAPTION VARCHAR(4000),
    IS_BLOCKED SMALLINT,
    MUST_CHANGE SMALLINT,
    EXP_DATE DATE,
    IS_DEL SMALLINT)
AS
BEGIN
    FOR
        SELECT USER_ID,
               USER_TYPE,
               USER_NAME,
               DATE_DEL,
               PWD,
               FIRST_NAME,
               MIDDLE_NAME,
               LAST_NAME,
               DESCRIPTION,
               LANG_CODE,
               OBJ_ID,
               IS_BLOCKED,
               MUST_CHANGE,
               EXP_DATE
        FROM USERS
        WHERE USER_TYPE = :I$USER_TYPE
           OR :I$USER_TYPE = 0
        ORDER BY USER_ID
        INTO   :USER_ID,
               :USER_TYPE,
               :USER_NAME,
               :DATE_DEL,
               :PWD,
               :FIRST_NAME,
               :MIDDLE_NAME,
               :LAST_NAME,
               :DESCRIPTION,
               :LANG_CODE,
               :OBJ_ID,
               :IS_BLOCKED,
               :MUST_CHANGE,
               :EXP_DATE
    DO BEGIN
        IF (DATE_DEL <= CURRENT_TIMESTAMP) THEN
        BEGIN
            IS_DEL = 1;
        END
        ELSE
        BEGIN
            IS_DEL = 0;
        END
        IF (OBJ_ID IS NOT NULL) THEN
        BEGIN
            SELECT CAPTION FROM OBJECT_CAPTION_GET(:OBJ_ID) INTO :OBJECT_CAPTION;
        END
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE USERS_SEC_UPDATE RETURNS (
    USER_EMAIL VARCHAR(200),
    USER_NAME VARCHAR(200),
    USER_TITLE VARCHAR(1000),
    STATE_ID SMALLINT)
AS
DECLARE VARIABLE V$USER_ID BIGINT;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$TYPE_ID BIGINT;
begin

  -- Выполняем блокировку пользователей, не входивших в систему за 90 дней
  -- кроме пользователя admin
  -- а также кроме уже заблокированных пользователей
  -- свежие пользователи заблокируются через 30 дней, а не через 90
  FOR
    SELECT USER_ID, OBJ_ID, USER_NAME
    FROM USERS
    WHERE USER_ID <> 1 AND DATE_DEL IS NULL AND IS_BLOCKED = 0 AND (EXP_DATE IS NULL OR EXP_DATE > CURRENT_DATE)
    AND (
      (LAST_ACCESS IS NOT NULL AND LAST_ACCESS < DATEADD(-90 DAY TO CURRENT_DATE))
      OR (LAST_ACCESS IS NULL AND DATE_MODIFY < DATEADD(-30 DAY TO CURRENT_DATE))
    )
    ORDER BY 1
    INTO :V$USER_ID, :V$OBJ_ID, :USER_NAME
  DO
  BEGIN
    UPDATE USERS
    SET IS_BLOCKED = 1
    WHERE USER_ID = :V$USER_ID;

    INSERT INTO USER_EVENTS
    (USER_ID, OBJ_ID, AUTHOR_ID, EVENT_TYPE, VAL)
    VALUES (:V$USER_ID, :V$OBJ_ID, NULL, 'BLOCK', 'Блокировка из-за неактивности');

    STATE_ID = 0;
    USER_EMAIL = NULL;
    USER_TITLE = NULL;
    IF(V$OBJ_ID IS NOT NULL) THEN
    BEGIN
      SELECT FIRST 1 V.VAL
      FROM VALS V
      WHERE V.OBJ_ID = :V$OBJ_ID AND V.PARAM_ID IN (3076, 1180, 144) AND V.IS_DEL = 0
      INTO :USER_EMAIL;

      SELECT TYPE_ID
      FROM OBJECTS
      WHERE OBJ_ID = :V$OBJ_ID
      INTO :V$TYPE_ID;

      IF(V$TYPE_ID = 10) THEN SELECT F.C1 FROM BUILD_REP_FIO(:V$OBJ_ID, 55, 56, 57, 1) F INTO :USER_TITLE;
      IF(V$TYPE_ID = 14) THEN SELECT F.C1 FROM BUILD_REP_FIO(:V$OBJ_ID, 59, 60, 61, 1) F INTO :USER_TITLE;
      IF(V$TYPE_ID = 20) THEN SELECT F.C1 FROM BUILD_REP_FIO(:V$OBJ_ID, 128, 129, 130, 1) F INTO :USER_TITLE;
    END

    SUSPEND;
  END

  -- Выставляем флаг требования смены пароля после 75 дней - у тех кто еще не заблокировался
  -- К сдаче - только на тестовой базе
  -- IF(EXISTS(SELECT FIRST 1 1 FROM GEN WHERE GEN = 201)) THEN
  FOR
    SELECT USER_ID, OBJ_ID, USER_NAME
    FROM USERS
    WHERE USER_ID <> 1 AND DATE_DEL IS NULL AND IS_BLOCKED = 0 AND MUST_CHANGE = 0 AND IS_BLOCKED_PWD = 0 AND (EXP_DATE IS NULL OR EXP_DATE > CURRENT_DATE)
      AND PWD_TIMEMARK < DATEADD(-75 DAY TO CURRENT_DATE) AND PWD_TIMEMARK >= DATEADD(-90 DAY TO CURRENT_DATE)
    ORDER BY 1
    INTO :V$USER_ID, :V$OBJ_ID, :USER_NAME
  DO
  BEGIN
    UPDATE USERS
    SET MUST_CHANGE = 1
    WHERE USER_ID = :V$USER_ID;

    STATE_ID = 1;
    USER_EMAIL = NULL;
    USER_TITLE = NULL;
    IF(V$OBJ_ID IS NOT NULL) THEN
    BEGIN
      SELECT FIRST 1 V.VAL
      FROM VALS V
      WHERE V.OBJ_ID = :V$OBJ_ID AND V.PARAM_ID IN (3076, 1180, 144) AND V.IS_DEL = 0
      INTO :USER_EMAIL;

      SELECT TYPE_ID
      FROM OBJECTS
      WHERE OBJ_ID = :V$OBJ_ID
      INTO :V$TYPE_ID;

      IF(V$TYPE_ID = 10) THEN SELECT F.C1 FROM BUILD_REP_FIO(:V$OBJ_ID, 55, 56, 57, 1) F INTO :USER_TITLE;
      IF(V$TYPE_ID = 14) THEN SELECT F.C1 FROM BUILD_REP_FIO(:V$OBJ_ID, 59, 60, 61, 1) F INTO :USER_TITLE;
      IF(V$TYPE_ID = 20) THEN SELECT F.C1 FROM BUILD_REP_FIO(:V$OBJ_ID, 128, 129, 130, 1) F INTO :USER_TITLE;
    END

    SUSPEND;
  END

  -- Блокируем после 90 дней от предыдущей смены пароля
  FOR
    SELECT USER_ID, OBJ_ID, USER_NAME
    FROM USERS
    WHERE USER_ID <> 1 AND DATE_DEL IS NULL AND IS_BLOCKED = 0 AND IS_BLOCKED_PWD = 0 AND (EXP_DATE IS NULL OR EXP_DATE > CURRENT_DATE)
      AND PWD_TIMEMARK < DATEADD(-90 DAY TO CURRENT_DATE)
    ORDER BY 1
    INTO :V$USER_ID, :V$OBJ_ID, :USER_NAME
  DO
  BEGIN
    UPDATE USERS
    SET IS_BLOCKED = 1
    WHERE USER_ID = :V$USER_ID;

    STATE_ID = 2;
    USER_EMAIL = NULL;
    USER_TITLE = NULL;
    IF(V$OBJ_ID IS NOT NULL) THEN
    BEGIN
      SELECT FIRST 1 V.VAL
      FROM VALS V
      WHERE V.OBJ_ID = :V$OBJ_ID AND V.PARAM_ID IN (3076, 1180, 144) AND V.IS_DEL = 0
      INTO :USER_EMAIL;

      SELECT TYPE_ID
      FROM OBJECTS
      WHERE OBJ_ID = :V$OBJ_ID
      INTO :V$TYPE_ID;

      IF(V$TYPE_ID = 10) THEN SELECT F.C1 FROM BUILD_REP_FIO(:V$OBJ_ID, 55, 56, 57, 1) F INTO :USER_TITLE;
      IF(V$TYPE_ID = 14) THEN SELECT F.C1 FROM BUILD_REP_FIO(:V$OBJ_ID, 59, 60, 61, 1) F INTO :USER_TITLE;
      IF(V$TYPE_ID = 20) THEN SELECT F.C1 FROM BUILD_REP_FIO(:V$OBJ_ID, 128, 129, 130, 1) F INTO :USER_TITLE;
    END

    SUSPEND;
  END

  -- У кого смены пароля и не было - выставляем текущее время
  UPDATE USERS
  SET PWD_TIMEMARK = CURRENT_TIMESTAMP
  WHERE PWD_TIMEMARK IS NULL;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE USERTYPES_LIST (
    I$LANG_CODE CHAR(2) = 'RU')
RETURNS (
    USER_TYPE SMALLINT,
    TAG VARCHAR(100),
    TYPE_ID BIGINT,
    USERTYPE_NAME VARCHAR(4000))
AS
BEGIN
    FOR
      SELECT U.USER_TYPE, U.TAG, U.TYPE_ID, R.VAL
      FROM USERTYPES U
      JOIN RES R ON R.RES_ID = U.RES_ID AND R.LANG_CODE = :I$LANG_CODE AND R.IS_DEL = 0
      WHERE U.USER_TYPE <> -22 -- роль родителя тут не показываем
      ORDER BY SORT_ORDER
      INTO :USER_TYPE, :TAG, :TYPE_ID, :USERTYPE_NAME
    DO
    BEGIN
      SUSPEND;
    END

    USER_TYPE = 0;
    TAG = '';
    TYPE_ID = NULL;

    SELECT WORD
    FROM REPORT_WORDS
    WHERE ID = 21
    INTO :USERTYPE_NAME;

    SUSPEND;

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE USER_ADD (
    I$USER_ID BIGINT,
    I$USER_TYPE SMALLINT,
    I$USER_NAME VARCHAR(100),
    I$PWD VARCHAR(100),
    I$FIRST_NAME VARCHAR(100),
    I$MIDDLE_NAME VARCHAR(100),
    I$LAST_NAME VARCHAR(100),
    I$DESCRIPTION VARCHAR(100),
    I$LANG_CODE CHAR(2),
    I$OBJ_ID BIGINT,
    I$IS_BLOCKED SMALLINT,
    I$MUST_CHANGE SMALLINT,
    I$EXP_DATE DATE = NULL,
    I$IS_DEL SMALLINT = 0)
RETURNS (
    USER_ID BIGINT)
AS
DECLARE VARIABLE DATE_DEL TIMESTAMP = NULL;
BEGIN
    USER_ID = I$USER_ID;
    IF (I$IS_DEL = 1) THEN DATE_DEL = CURRENT_TIMESTAMP;

    IF (I$USER_ID IS NULL) THEN
        INSERT INTO USERS (USER_TYPE, USER_NAME, DATE_DEL, PWD,
                           FIRST_NAME, MIDDLE_NAME, LAST_NAME, DESCRIPTION,
                           LANG_CODE, OBJ_ID, IS_BLOCKED, MUST_CHANGE, EXP_DATE)
        VALUES (:I$USER_TYPE, :I$USER_NAME, :DATE_DEL, :I$PWD,
                :I$FIRST_NAME, :I$MIDDLE_NAME, :I$LAST_NAME, :I$DESCRIPTION,
                :I$LANG_CODE, :I$OBJ_ID, :I$IS_BLOCKED, :I$MUST_CHANGE, :I$EXP_DATE)
        RETURNING USER_ID INTO :USER_ID;
    ELSE
        UPDATE USERS
        SET USER_TYPE   = :I$USER_TYPE,
            USER_NAME   = :I$USER_NAME,
            DATE_DEL    = :DATE_DEL,
            PWD         = :I$PWD,
            FIRST_NAME  = :I$FIRST_NAME,
            MIDDLE_NAME = :I$MIDDLE_NAME,
            LAST_NAME   = :I$LAST_NAME,
            DESCRIPTION = :I$DESCRIPTION,
            LANG_CODE   = :I$LANG_CODE,
            OBJ_ID      = :I$OBJ_ID,
            IS_BLOCKED  = :I$IS_BLOCKED,
            MUST_CHANGE = :I$MUST_CHANGE,
            EXP_DATE    = :I$EXP_DATE
        WHERE USER_ID   = :I$USER_ID;

    EXECUTE PROCEDURE CJ2_JOURNAL_ACCESS_UPD(NULL, :USER_ID);
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE USER_CHANGE_PASS (
    I$USER_ID BIGINT,
    I$OLDPASSWORD VARCHAR(200),
    I$NEWPASSWORD VARCHAR(200),
    I$FROM VARCHAR(1000) = NULL,
    I$OLDPASSWORD2 VARCHAR(200) = NULL)
RETURNS (
    STATUS SMALLINT)
AS
DECLARE VARIABLE V$OBJ_ID BIGINT;
BEGIN
  STATUS = 0;

  SELECT FIRST 1 OBJ_ID
  FROM USERS
  WHERE USER_ID = :I$USER_ID AND (PWD = :I$OLDPASSWORD OR PWD = :I$OLDPASSWORD2) AND DATE_DEL IS NULL
  INTO :V$OBJ_ID;

  -- IF(V$OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Пользователь не найден';

  IF(V$OBJ_ID IS NOT NULL) THEN
  BEGIN
    UPDATE USERS
    SET PWD = :I$NEWPASSWORD, MUST_CHANGE = 0, PWD_TIMEMARK = CURRENT_TIMESTAMP
    WHERE USER_ID = :I$USER_ID;
    STATUS = 1;

    -- Сохраняем весь хэш при изменении пароля, хотя хорошо бы его обрезать
    -- I$FROM передается корректно только из DG, сохраняем адрес в OLD_VAL
    INSERT INTO HISTVALS
    (TABLE_NAME, USER_ID, OBJ_ID, PARAM_ID, OPT_ID, PARENT_ID, OLD_VAL, VAL)
    VALUES ('USERS', :I$USER_ID, :I$USER_ID, 0, NULL, NULL, :I$FROM, :I$NEWPASSWORD);

    INSERT INTO USER_EVENTS
    (USER_ID, OBJ_ID, AUTHOR_ID, EVENT_TYPE, VAL)
    VALUES (:I$USER_ID, :V$OBJ_ID, NULL, 'CHPWD2', 'Изменен пароль пользователем');
  END

  SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE USER_CHANGE_PWD (
    I$USER_ID BIGINT,
    I$PWD VARCHAR(200))
RETURNS (
    IS_CHANGED SMALLINT)
AS
BEGIN

  -- Непонятно зачем второй экземляр функции, когда есть USER_CHANGE_PASS

  UPDATE USERS
  SET PWD = :I$PWD, MUST_CHANGE = 0
  WHERE USER_ID = :I$USER_ID;

  IS_CHANGED = ROW_COUNT;

  SUSPEND;

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE USER_CLASS_GEN (
    I$OBJ_ID BIGINT,
    I$GRADE_ID BIGINT,
    I$METHOD SMALLINT,
    I$ROLE INTEGER,
    I$ACTION SMALLINT,
    I$PASSWORD VARCHAR(40),
    I$USER_ID VARCHAR(40))
RETURNS (
    USER_ID BIGINT,
    USER_EMAIL VARCHAR(100),
    USER_NAME VARCHAR(100),
    CLASS_NAME VARCHAR(100),
    USER_FIO VARCHAR(400),
    MODIFIED SMALLINT)
AS
declare variable V$USER_NAME varchar(100);
declare variable V$DT timestamp;
declare variable V$IS_BLOCKED smallint;
declare variable T bigint;
declare variable V$USED smallint;
declare variable V$YEAR integer;
declare variable S1 varchar(200);
declare variable S2 varchar(200);
declare variable S3 varchar(200);
begin

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  -- ACTION
  -- 0 - ничего не делать
  -- 1 - актуализировать пользователя
  -- 2 - сменить пароль
  -- 3 - заблокировать пользователя
  -- 4 - разблокировать пользователя
  IF(I$ACTION = 0) THEN EXIT;

  SELECT FIRST 1 U.USER_ID, U.USER_NAME, U.DATE_DEL, U.IS_BLOCKED
  FROM USERS U
  WHERE U.OBJ_ID = :I$OBJ_ID
  INTO :USER_ID, :V$USER_NAME, :V$DT, :V$IS_BLOCKED;

  USER_NAME = V$USER_NAME;
  MODIFIED = 0;

  CLASS_NAME = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$GRADE_ID));
  USER_FIO = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$OBJ_ID, 23));

  -- Получаем email
  SELECT VM.VAL
  FROM VALS VM
  WHERE VM.OBJ_ID = :I$OBJ_ID AND VM.PARAM_ID IN (3076, 144) AND VM.IS_DEL = 0
  INTO :USER_EMAIL;

  IF(I$ACTION = 1) THEN
  BEGIN
    IF(I$METHOD = 0 AND USER_EMAIL IS NOT NULL) THEN USER_NAME = USER_EMAIL;
    ELSE IF(I$METHOD = 1) THEN
    BEGIN
      T = I$OBJ_ID / 1000000000;
      USER_NAME = T || 'p';
      USER_NAME = USER_NAME || (I$OBJ_ID - T * 1000000000);
    END
    ELSE IF(I$METHOD = 2) THEN
    BEGIN
      IF((I$ROLE = 12 AND SUBSTRING(V$USER_NAME FROM 1 FOR 6) <> 'Ученик') OR (I$ROLE = 22 AND SUBSTRING(V$USER_NAME FROM 1 FOR 8) <> 'Родитель')
        OR V$USER_NAME IS NULL) THEN
      BEGIN
        V$USED = 1;
        T = 1;
        WHILE(V$USED = 1) DO
        BEGIN
          T = T + 1;
          IF(I$ROLE = 12) THEN USER_NAME = 'Ученик' || T; ELSE USER_NAME = 'Родитель' || T;

          V$USED = 0;
          SELECT FIRST 1 1
          FROM USERS
          WHERE USER_NAME = :USER_NAME AND OBJ_ID <> :I$OBJ_ID
          INTO :V$USED;
        END
      END
    END

    -- Не занято ли имя пользователя ?
    IF(EXISTS(
      SELECT FIRST 1 1
      FROM USERS U
      WHERE U.USER_ID <> :USER_ID AND U.USER_NAME = :USER_NAME
    ))
    THEN EXCEPTION DATA_ERROR 'Пользователь с именем ' || USER_NAME || ' уже закреплен за другой персоной';

    IF(USER_ID IS NULL) THEN
    BEGIN
      IF(USER_NAME IS NULL) THEN
      BEGIN
        USER_NAME = 'Не сформировано, нет email';
      END
      ELSE
      BEGIN

        SELECT VAL FROM VALS WHERE OBJ_ID = :I$OBJ_ID AND PARAM_ID IN (56, 60, 129) AND IS_DEL = 0 INTO :S1;
        SELECT VAL FROM VALS WHERE OBJ_ID = :I$OBJ_ID AND PARAM_ID IN (57, 61, 130) AND IS_DEL = 0 INTO :S2;
        SELECT VAL FROM VALS WHERE OBJ_ID = :I$OBJ_ID AND PARAM_ID IN (55, 59, 128) AND IS_DEL = 0 INTO :S3;

        INSERT INTO USERS
        (OBJ_ID, USER_NAME, PWD, ADDED_BY, USER_TYPE, EXP_DATE, FIRST_NAME, MIDDLE_NAME, LAST_NAME)
        VALUES (:I$OBJ_ID, :USER_NAME, :I$PASSWORD, :I$USER_ID, :I$ROLE, '31.08.' || :V$YEAR, COALESCE(:S1, ''), COALESCE(:S2, ''), COALESCE(:S3, ''))
        RETURNING USER_ID INTO :USER_ID;

        -- Только для ученика - доступ к тестированию
        IF(I$ROLE = 12) THEN
        UPDATE OR INSERT INTO LUSERS
        (USER_ID, LEVEL_ID)
        VALUES (:USER_ID, 138);

        MODIFIED = 1;
      END

    END
    ELSE
    BEGIN
      -- Пароль не меняем, но включаем пользователя
      IF(V$DT IS NOT NULL) THEN
      BEGIN
        UPDATE USERS SET DATE_DEL = NULL, PWD = :I$PASSWORD WHERE USER_ID = :USER_ID;
        MODIFIED = 1;
      END

      -- Корректируем имя пользователя
      IF(USER_NAME <> V$USER_NAME) THEN
      BEGIN
        UPDATE USERS SET USER_NAME = :USER_NAME WHERE USER_ID = :USER_ID;
        MODIFIED = 1;
      END
    END
  END
  ELSE IF(I$ACTION = 2) THEN
  BEGIN
    -- Если юзера нет или он удален, то он не будет создан или активирован
    UPDATE USERS
    SET PWD = :I$PASSWORD
    WHERE USER_ID = :USER_ID;

    MODIFIED = 1;
  END
  ELSE IF(I$ACTION = 3) THEN
  BEGIN
    UPDATE USERS SET IS_BLOCKED = 1 WHERE USER_ID = :I$USER_ID;
  END
  ELSE IF(I$ACTION = 4) THEN
  BEGIN
    UPDATE USERS SET IS_BLOCKED = 0 WHERE USER_ID = :I$USER_ID;
  END
  ELSE EXCEPTION DATA_ERROR 'Недопустимый код операции';

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE USER_COPY (
    I$USER_ID BIGINT)
AS
DECLARE VARIABLE USER_ID BIGINT;
DECLARE VARIABLE USER_TYPE SMALLINT;
DECLARE VARIABLE USER_NAME VARCHAR(100);
DECLARE VARIABLE DATE_DEL TIMESTAMP;
DECLARE VARIABLE PWD VARCHAR(100);
DECLARE VARIABLE FIRST_NAME VARCHAR(100);
DECLARE VARIABLE MIDDLE_NAME VARCHAR(100);
DECLARE VARIABLE LAST_NAME VARCHAR(100);
DECLARE VARIABLE DESCRIPTION VARCHAR(100);
DECLARE VARIABLE LANG_CODE CHAR(2);
DECLARE VARIABLE OBJ_ID BIGINT;
DECLARE VARIABLE IS_BLOCKED SMALLINT;
DECLARE VARIABLE MUST_CHANGE SMALLINT;
DECLARE VARIABLE EXP_DATE DATE;
BEGIN
    USER_ID = I$USER_ID;

    SELECT USER_TYPE,
           '< ? >',
           DATE_DEL,
           '< ? >',
           '< ? >',
           '< ? >',
           '< ? >',
           DESCRIPTION,
           LANG_CODE,
           OBJ_ID,
           1,
           MUST_CHANGE,
           EXP_DATE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO   :USER_TYPE,
           :USER_NAME,
           :DATE_DEL,
           :PWD,
           :FIRST_NAME,
           :MIDDLE_NAME,
           :LAST_NAME,
           :DESCRIPTION,
           :LANG_CODE,
           :OBJ_ID,
           :IS_BLOCKED,
           :MUST_CHANGE,
           :EXP_DATE;

    INSERT INTO USERS
                (
                 USER_TYPE,
                 USER_NAME,
                 DATE_DEL,
                 PWD,
                 FIRST_NAME,
                 MIDDLE_NAME,
                 LAST_NAME,
                 DESCRIPTION,
                 LANG_CODE,
                 OBJ_ID,
                 IS_BLOCKED,
                 MUST_CHANGE,
                 EXP_DATE
                )
                VALUES
                (
                 :USER_TYPE,
                 :USER_NAME,
                 :DATE_DEL,
                 :PWD,
                 :FIRST_NAME,
                 :MIDDLE_NAME,
                 :LAST_NAME,
                 :DESCRIPTION,
                 :LANG_CODE,
                 :OBJ_ID,
                 :IS_BLOCKED,
                 :MUST_CHANGE,
                 :EXP_DATE
                )
    RETURNING USER_ID
    INTO :USER_ID;

    UPDATE USERS
    SET USER_NAME = 'LOGIN_' || CAST(USER_ID AS VARCHAR(1000))
    WHERE USER_ID = :USER_ID;

    IF (ROW_COUNT = 0) THEN EXIT;

    INSERT INTO LUSERS
    (LEVEL_ID, USER_ID, ROOT_OBJ_ID, ROOT_PARENT_ID)
    SELECT LEVEL_ID, :USER_ID, ROOT_OBJ_ID, ROOT_PARENT_ID
    FROM LUSERS
    WHERE USER_ID = :I$USER_ID;

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE USER_GRANT_SET (
    I$USER_ID BIGINT,
    I$LEVEL_ID BIGINT,
    I$ACCESS SMALLINT,
    I$OBJ_ID BIGINT,
    I$AUTHOR_ID VARCHAR(40) = NULL)
RETURNS (
    OBJ_ID BIGINT)
AS
DECLARE VARIABLE G SMALLINT;
begin

  IF(I$AUTHOR_ID = 'Веб-администратор') THEN I$AUTHOR_ID = NULL;

  SELECT FIRST 1 LU.READ_ONLY
  FROM LUSERS LU
  WHERE USER_ID = :I$USER_ID AND LEVEL_ID = :I$LEVEL_ID
  INTO :G;

  -- Для админа только полный доступ
  IF(I$USER_ID = 1) THEN I$ACCESS = 0;

  IF(I$ACCESS IS NULL) THEN
  BEGIN
    IF(G IS NOT NULL) THEN
    BEGIN
      DELETE FROM LUSERS
      WHERE USER_ID = :I$USER_ID AND LEVEL_ID = :I$LEVEL_ID;

      INSERT INTO USER_EVENTS
      (USER_ID, OBJ_ID, AUTHOR_ID, EVENT_TYPE, VAL)
      VALUES (:I$USER_ID, :I$OBJ_ID, :I$AUTHOR_ID, 'DELACCESS', 'Удален доступ RO=' || :G || ' к приложению ' || :I$LEVEL_ID);
    END
  END
  ELSE
  BEGIN
    -- !!! что там с ROOT_PARENT_ID ?!
    -- Подмена Региона на NULL
    IF(I$OBJ_ID = 0) THEN I$OBJ_ID = NULL;

    UPDATE OR INSERT
    INTO LUSERS
    (USER_ID, LEVEL_ID, READ_ONLY, ROOT_OBJ_ID)
    VALUES (:I$USER_ID, :I$LEVEL_ID, :I$ACCESS, :I$OBJ_ID)
    MATCHING (USER_ID, LEVEL_ID);

    IF(G IS NULL) THEN
    INSERT INTO USER_EVENTS
    (USER_ID, OBJ_ID, AUTHOR_ID, EVENT_TYPE, VAL)
    VALUES (:I$USER_ID, :I$OBJ_ID, :I$AUTHOR_ID, 'ADDACCESS', 'Предоставлен доступ RO=' || :G || ' к приложению ' || :I$LEVEL_ID);
  END

  -- Доступ к личным делам обучающихся
  IF(I$LEVEL_ID IN (50, 164, 174, 533)) THEN EXECUTE PROCEDURE CJ2_JOURNAL_ACCESS_UPD(NULL, :I$USER_ID);

  OBJ_ID = I$LEVEL_ID;
  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE USER_ID_GET (
    I$USER_NAME VARCHAR(100),
    I$PWD VARCHAR(200),
    I$PWD2 VARCHAR(200) = NULL)
RETURNS (
    USER_ID BIGINT,
    USER_FIO VARCHAR(4000),
    LANG_CODE CHAR(2),
    IS_BLOCKED SMALLINT,
    IS_EXPIRE SMALLINT,
    MUST_CHANGE SMALLINT,
    USER_TYPE SMALLINT)
AS
DECLARE VARIABLE OBJ_ID BIGINT;
DECLARE VARIABLE EXP_DATE DATE;
BEGIN
    USER_ID = NULL;
    OBJ_ID  = NULL;
    USER_FIO = '';
    LANG_CODE = '';

    SELECT FIRST 1 USER_ID, COALESCE(FIRST_NAME,'') || ' ' || COALESCE(MIDDLE_NAME, ''), LANG_CODE, OBJ_ID, IS_BLOCKED, MUST_CHANGE, EXP_DATE, USER_TYPE
    FROM USERS
    WHERE USER_NAME = :I$USER_NAME AND (PWD = :I$PWD OR PWD = :I$PWD2) AND DATE_DEL IS NULL
    INTO :USER_ID, :USER_FIO, :LANG_CODE, :OBJ_ID, :IS_BLOCKED, :MUST_CHANGE, :EXP_DATE, :USER_TYPE;

    IF (OBJ_ID IS NOT NULL) THEN
    BEGIN
        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:OBJ_ID)
        INTO :USER_FIO;
    END

    IF ((EXP_DATE IS NULL) OR (EXP_DATE >= CURRENT_DATE)) THEN
    BEGIN
        IS_EXPIRE = 0;
    END
    ELSE
    BEGIN
        IS_EXPIRE = 1;
    END

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE USER_ITEM_DEL (
    I$USER_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$USER_ID1 VARCHAR(40))
AS
declare variable V$USER_ID bigint;
declare variable V$OBJ_ID bigint;
begin

  IF(I$USER_ID = 1) THEN EXCEPTION DATA_ERROR 'Этого пользователя нельзя удалить';

  IF(I$USER_ID1 = 'Веб-администратор') THEN I$USER_ID1 = 1;

  SELECT U.USER_ID, U.OBJ_ID
  FROM USERS U
  WHERE U.DATE_DEL IS NULL AND (U.USER_ID = :I$USER_ID OR U.OBJ_ID = :I$OBJ_ID)
  INTO :V$USER_ID, :V$OBJ_ID;

  IF(V$USER_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Пользователь не найден или был удален';

  -- Можно ли текущему пользователю удалять выбранного ?

  UPDATE USERS
  SET DATE_DEL = CURRENT_TIMESTAMP
  WHERE USER_ID = :V$USER_ID;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE USER_ITEM_GET (
    I$OBJ_ID BIGINT,
    I$IS_EXT SMALLINT,
    I$APPNAME VARCHAR(100),
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$USER_ID BIGINT;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$USER_TYPE SMALLINT;
DECLARE VARIABLE V$USER_NAME VARCHAR(100);
DECLARE VARIABLE V$TYPE_ID BIGINT;
DECLARE VARIABLE V$DATE_DEL TIMESTAMP;
DECLARE VARIABLE V$IS_BLOCKED SMALLINT;
DECLARE VARIABLE V$IS_BLOCKED_PWD SMALLINT;
DECLARE VARIABLE V$MUST_CHANGE SMALLINT;
DECLARE VARIABLE V$EXP_DATE DATE;
DECLARE VARIABLE V$DESCRIPTION VARCHAR(100);
DECLARE VARIABLE V$LANG_CODE VARCHAR(3);
DECLARE VARIABLE V$FIRST_NAME VARCHAR(100);
DECLARE VARIABLE V$MIDDLE_NAME VARCHAR(100);
DECLARE VARIABLE V$LAST_NAME VARCHAR(100);
DECLARE VARIABLE V$ID BIGINT;
DECLARE VARIABLE V$RO SMALLINT;
DECLARE VARIABLE V$ROOT BIGINT;
DECLARE VARIABLE S VARCHAR(1000);
DECLARE VARIABLE V$OU_LICENCE_TYPE CHAR(1);
DECLARE VARIABLE V$TYPE INTEGER;
DECLARE VARIABLE V$LEVEL SMALLINT;
DECLARE VARIABLE T INTEGER;
DECLARE VARIABLE V$SNILS VARCHAR(40);
DECLARE VARIABLE V$MODULE_ID BIGINT;
DECLARE VARIABLE V$SECTION_ID BIGINT;
begin

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  -- Адресацию пользователей выполняем по OBJ_ID если I$IS_EXT = 0
  -- и USER_ID если I$IS_EXT = 1

  SELECT FIRST 1 U.USER_TYPE
  FROM USERS U
  JOIN LUSERS LU ON LU.USER_ID = U.USER_ID
  JOIN LEVELS L ON L.LEVEL_ID = LU.LEVEL_ID
  JOIN TASKS T ON T.TASK_ID = L.TASK_ID
  JOIN RES R ON R.RES_ID = T.RES_ID AND R.LANG_CODE = 'RU' AND R.VAL = 'Администрирование пользователей'
  WHERE U.USER_ID = :I$USER_ID AND U.IS_BLOCKED = 0 AND U.DATE_DEL IS NULL AND (U.EXP_DATE IS NULL OR U.EXP_DATE >= CURRENT_DATE)
  INTO :T;

  IF(T IS NULL) THEN EXCEPTION DATA_ERROR 'Нет доступа к приложению';

  -- Внешних пользователей может добавлять только админ, директор и завуч
  IF(I$IS_EXT = 1 AND T NOT IN (1, 5, 6)) THEN EXCEPTION DATA_ERROR 'Только административный пользователь может управлять внешними пользователями';

  SELECT FIRST 1 U.USER_ID, U.OBJ_ID, U.USER_TYPE, U.USER_NAME, U.DATE_DEL, U.IS_BLOCKED, U.IS_BLOCKED_PWD,
    U.MUST_CHANGE, U.EXP_DATE, U.DESCRIPTION, U.LANG_CODE, U.FIRST_NAME, U.MIDDLE_NAME, U.LAST_NAME, U.SNILS, U.SECTION_ID
  FROM USERS U
  WHERE (U.USER_ID = :I$OBJ_ID AND :I$IS_EXT = 1) OR (U.OBJ_ID = :I$OBJ_ID AND :I$IS_EXT = 0) AND U.DATE_DEL IS NULL
  INTO :V$USER_ID, :V$OBJ_ID, :V$USER_TYPE, :V$USER_NAME, :V$DATE_DEL, :V$IS_BLOCKED, :V$IS_BLOCKED_PWD,
    :V$MUST_CHANGE, :V$EXP_DATE, :V$DESCRIPTION, :V$LANG_CODE, :V$FIRST_NAME, :V$MIDDLE_NAME, :V$LAST_NAME, :V$SNILS, :V$SECTION_ID;

  IF(I$OBJ_ID IS NOT NULL AND V$USER_ID IS NULL AND I$IS_EXT = 1) THEN EXCEPTION DATA_ERROR 'Пользователь не найден';

  IF(I$IS_EXT = 0) THEN
  BEGIN
    V$OBJ_ID = I$OBJ_ID;
    V$LAST_NAME = (SELECT VAL FROM VALS WHERE OBJ_ID = :V$OBJ_ID AND PARAM_ID IN (59, 55, 128) AND IS_DEL = 0);
    V$FIRST_NAME = (SELECT VAL FROM VALS WHERE OBJ_ID = :V$OBJ_ID AND PARAM_ID IN (60, 56, 129) AND IS_DEL = 0);
    V$MIDDLE_NAME = (SELECT VAL FROM VALS WHERE OBJ_ID = :V$OBJ_ID AND PARAM_ID IN (61, 57, 130) AND IS_DEL = 0);

    SELECT TYPE_ID
    FROM OBJECTS
    WHERE OBJ_ID = :I$OBJ_ID
    INTO :V$TYPE_ID;
  END

  TAG_NAME = 'ou_type';
  V$OU_LICENCE_TYPE = (SELECT STATUS FROM OU_LICENCE_TYPE);
  VAL = V$OU_LICENCE_TYPE;
  SUSPEND;

  TAG_NAME = 'level';
  V$LEVEL = (SELECT KEY_VAL FROM KEYS WHERE KEY_CODE = 'LEVEL');
  VAL = V$LEVEL;
  SUSPEND;

  TAG_NAME = 'user_id';
  VAL = V$USER_ID;
  SUSPEND;

  TAG_NAME = 'obj_id';
  VAL = V$OBJ_ID;
  SUSPEND;

  TAG_NAME = 'user_type';
  IF(V$TYPE_ID = 10) THEN V$USER_TYPE = 12;
  IF(V$TYPE_ID = 20) THEN V$USER_TYPE = 22;
  VAL = V$USER_TYPE;
  SUSPEND;

  TAG_NAME = 'user_name';
  VAL = V$USER_NAME;
  SUSPEND;

  TAG_NAME = 'external';
  VAL = I$IS_EXT;
  SUSPEND;

  TAG_NAME = 'is_del';
  VAL = IIF(V$DATE_DEL IS NULL, '0', '1');
  SUSPEND;

  TAG_NAME = 'is_blocked';
  VAL = COALESCE(V$IS_BLOCKED, 0);
  SUSPEND;

  TAG_NAME = 'is_blocked_pwd';
  VAL = COALESCE(V$IS_BLOCKED_PWD, 0);
  SUSPEND;

  TAG_NAME = 'must_change';
  VAL = COALESCE(V$MUST_CHANGE, 0);
  SUSPEND;

  TAG_NAME = 'exp_date';
  VAL = (SELECT VAL FROM DATE2ISO(:V$EXP_DATE, 0));
  SUSPEND;

  TAG_NAME = 'description';
  VAL = V$DESCRIPTION;
  SUSPEND;

  TAG_NAME = 'lang_code';
  VAL = COALESCE(V$LANG_CODE, 'RU');
  SUSPEND;

  TAG_NAME = 'first_name';
  VAL = V$FIRST_NAME;
  SUSPEND;

  TAG_NAME = 'middle_name';
  VAL = V$MIDDLE_NAME;
  SUSPEND;

  TAG_NAME = 'last_name';
  VAL = V$LAST_NAME;
  SUSPEND;

  TAG_NAME = 'snils';
  VAL = V$SNILS;
  SUSPEND;

  -- Список для выбора типа пользователя
  TAG_NAME = 'user_types::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT OBJ_ID, OBJ_CAPTION
    FROM USERADM_USERTYPES_LIST
    WHERE (:V$TYPE_ID = 10 AND OBJ_ID = 12) OR (:V$TYPE_ID = 20 AND OBJ_ID = 22) OR ((:V$TYPE_ID IS NULL OR :V$TYPE_ID = 14) AND OBJ_ID NOT IN (12, 22))
    INTO :V$ID, :S
  DO
  BEGIN
    -- Для ЦОПП скрываем ненужные виды пользователей
    -- Для родителя тип пользователя только родитель, для ученика - ученик
    IF(I$APPNAME <> 'copp' OR V$ID NOT IN (5, 7, 10, 11, 12, 16, 17, 18, 19, 20)) THEN
    BEGIN
      TAG_NAME = 'user_types:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'user_types:r:id';
      VAL = V$ID;
      SUSPEND;
      TAG_NAME = 'user_types:r:value';
      VAL = S;
      -- Для ЦОПП заменяем Завуча на сотрудник ЦОПП, специалист ИОГВ на Заказчик
      IF(V$ID = 6 AND I$APPNAME = 'copp') THEN VAL = 'Сотрудник ЦОПП';
      IF(V$ID = 9 AND I$APPNAME = 'copp') THEN VAL = 'Преподаватель';
      IF(V$ID = 21 AND I$APPNAME = 'copp') THEN VAL = 'Заказчик';
      SUSPEND;
    END
  END

  -- Список приложений и доступ к ним
  -- Ученику только к ЗНАКу, родителю вообще никуда не положено
  TAG_NAME = 'grants::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L.LEVEL_ID, R.VAL, LU.READ_ONLY, LU.ROOT_OBJ_ID, M.MODULE_CODE
    FROM TASKS T
    JOIN RES R ON R.RES_ID = T.RES_ID AND R.LANG_CODE = 'RU'
    JOIN LEVELS L ON L.TASK_ID = T.TASK_ID AND L.IS_DEL = 0
    JOIN MODULES M ON M.MODULE_ID = T.MODULE_ID AND M.IS_DEL = 0 AND M.IS_ACTIVE = 1
    LEFT JOIN LUSERS LU ON LU.USER_ID = :V$USER_ID AND LU.LEVEL_ID = L.LEVEL_ID
    WHERE T.IS_DEL = 0 AND (:V$USER_TYPE IS NULL OR (:V$USER_TYPE <> 22 AND (:V$USER_TYPE <> 12 OR L.LEVEL_ID IN (138))))
    ORDER BY M.SORT_ORDER, T.SORT_ORDER, L.SORT_ORDER
    INTO :V$ID, :S, :V$RO, :V$ROOT, :V$SNILS
  DO
  BEGIN
    -- Для ЦОПП убираем ненужные права доступа
    -- Библиограф #90 вернули
    IF(I$APPNAME = 'copp' OR V$ID IN (168, 171, 172, 176, 206, 207, 208, 209, 249, 250, 251, 254, 258, 255, 258, 290, 468, 478, 490)) THEN V$ID = NULL;

    -- Убираем устаревшие права доступа к журналам из толстого клиента CJ
    -- В СПО пока оставляем все варианты
    IF(V$SNILS = 'CJOURNAL' AND V$ID NOT IN (46, 180, 230, 249, 254, 255)) THEN V$ID = NULL;

    IF(V$ID IS NOT NULL) THEN
    BEGIN
      TAG_NAME = 'grants:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'grants:r:id';
      VAL = V$ID;
      SUSPEND;
      TAG_NAME = 'grants:r:value';
      IF(V$ID = 16 AND I$APPNAME = 'copp') THEN S = 'Здания и помещения';
      IF(V$ID = 167 AND I$APPNAME = 'copp') THEN S = 'Пользователи';
      IF(V$ID = 169 AND I$APPNAME = 'copp') THEN S = 'Сведения об организации';
      IF(V$ID = 170 AND I$APPNAME = 'copp') THEN S = 'Сотрудники';
      IF(V$ID = 215 AND I$APPNAME = 'copp') THEN S = 'Структура организации';
      IF(V$ID = 210) THEN S = 'Демонстрационный экзамен';
      IF(V$ID = 230) THEN S = 'Журнал занятий';
      IF(V$ID = 485) THEN S = 'Управление электронными журналами';
      VAL = S;
      SUSPEND;
      TAG_NAME = 'grants:r:access';
      VAL = V$RO;
      SUSPEND;
      TAG_NAME = 'grants:r:obj_id';
      VAL = V$ROOT;
      SUSPEND;
    END
  END

  -- Связывание больше не выполняем, классного руководителя и руководителя подразделения назначаем в самом классе/подразделении

  -- Доступ к журналам
  TAG_NAME = 'journals::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT J.OBJ_ID, J.JOURNAL_NAME || IIF(J.SUBJECT_ID IS NULL, '', ' - ' || C.CAPTION), NULL, J.JOURNAL_TYPE
    FROM CJ2_JOURNAL J
    LEFT JOIN OBJECT_CAPTION_GET(J.SUBJECT_ID) C ON 1 = 1
    WHERE J.TEACHER_ID = :V$OBJ_ID AND J.DATE_DEL IS NULL
    UNION
    SELECT J.OBJ_ID, J.JOURNAL_NAME || IIF(J.SUBJECT_ID IS NULL, '', ' - ' || C.CAPTION), JU.ACCESS, J.JOURNAL_TYPE
    FROM CJ2_JOURNAL_USERS JU
    JOIN CJ2_JOURNAL J ON J.OBJ_ID = JU.CJ_ID AND J.DATE_DEL IS NULL
    LEFT JOIN OBJECT_CAPTION_GET(J.SUBJECT_ID) C ON 1 = 1
    WHERE JU.DATE_DEL IS NULL AND JU.USER_ID = :V$USER_ID
    INTO :V$ID, :S, :V$LEVEL, :V$TYPE
  DO
  BEGIN
    TAG_NAME = 'journals:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'journals:r:id';
    VAL = V$ID;
    SUSPEND;
    TAG_NAME = 'journals:r:type';
    VAL = V$TYPE;
    SUSPEND;
    TAG_NAME = 'journals:r:name';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'journals:r:access';
    VAL = :V$LEVEL;
    SUSPEND;
  END

  -- Селектор выбора района или отдела
  TAG_NAME = 'levels::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L.OBJ_ID, L.OBJ_CAPTION
    FROM USERADM_CLASSES_LIST L
    ORDER BY L.SORT_ORDER
    INTO :V$ID, :S
  DO
  BEGIN
    TAG_NAME = 'levels:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'levels:r:id';
    VAL = V$ID;
    SUSPEND;
    TAG_NAME = 'levels:r:name';
    VAL = S;
    SUSPEND;
  END

  TAG_NAME = 'access_level';
  VAL = NULL;
  SELECT FIRST 1 LU.ROOT_OBJ_ID
  FROM LUSERS LU
  WHERE LU.USER_ID = :V$USER_ID AND LU.ROOT_OBJ_ID IS NOT NULL
  INTO :VAL;
  IF(VAL IS NULL AND V$LEVEL = 3) THEN VAL = 0;
  SUSPEND;

  -- Биты выдаем 1-based, чтобы не слетело ничего
  TAG_NAME = 'section_id:values::json&colon;array';
  VAL = 1;
  SUSPEND;
  T = 1;
  WHILE(T <= 8) DO
  BEGIN
    IF(BIN_AND(V$SECTION_ID, BIN_SHL(1, T - 1)) <> 0) THEN
    BEGIN
      TAG_NAME = 'section_id:values:v';
      VAL = T;
      SUSPEND;
    END
    T = T + 1;
  END
  TAG_NAME = 'section_id:selection::json&colon;array';
  VAL = 1;
  SUSPEND;
    TAG_NAME = 'section_id:selection:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'section_id:selection:r:id';
    VAL = 1;
    SUSPEND;
    TAG_NAME = 'section_id:selection:r:value';
    VAL = 'ДОО';
    SUSPEND;
    TAG_NAME = 'section_id:selection:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'section_id:selection:r:id';
    VAL = 2;
    SUSPEND;
    TAG_NAME = 'section_id:selection:r:value';
    VAL = 'НОО';
    SUSPEND;
    TAG_NAME = 'section_id:selection:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'section_id:selection:r:id';
    VAL = 3;
    SUSPEND;
    TAG_NAME = 'section_id:selection:r:value';
    VAL = 'ООО';
    SUSPEND;
    TAG_NAME = 'section_id:selection:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'section_id:selection:r:id';
    VAL = 4;
    SUSPEND;
    TAG_NAME = 'section_id:selection:r:value';
    VAL = 'СОО';
    SUSPEND;
    TAG_NAME = 'section_id:selection:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'section_id:selection:r:id';
    VAL = 5;
    SUSPEND;
    TAG_NAME = 'section_id:selection:r:value';
    VAL = 'СПО';
    SUSPEND;
    TAG_NAME = 'section_id:selection:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'section_id:selection:r:id';
    VAL = 6;
    SUSPEND;
    TAG_NAME = 'section_id:selection:r:value';
    VAL = 'ПО';
    SUSPEND;
    TAG_NAME = 'section_id:selection:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'section_id:selection:r:id';
    VAL = 7;
    SUSPEND;
    TAG_NAME = 'section_id:selection:r:value';
    VAL = 'ДО';
    SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE USER_ITEM_SET (
    I$USER_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$USER_NAME VARCHAR(100),
    I$USER_TYPE SMALLINT,
    I$PWD VARCHAR(200),
    I$FIRST_NAME VARCHAR(100),
    I$MIDDLE_NAME VARCHAR(100),
    I$LAST_NAME VARCHAR(100),
    I$IS_DEL SMALLINT,
    I$IS_BLOCKED SMALLINT,
    I$IS_BLOCKED_PWD SMALLINT,
    I$MUST_CHANGE SMALLINT,
    I$EXP_DATE DATE,
    I$DESCRIPTION VARCHAR(100),
    I$LANG_CODE VARCHAR(3),
    I$SNILS VARCHAR(40),
    M$USER_ID VARCHAR(40),
    I$SECTION_ID VARCHAR(100))
RETURNS (
    USER_ID BIGINT)
AS
DECLARE VARIABLE S VARCHAR(200);
DECLARE VARIABLE V$OLD_NAME VARCHAR(100);
DECLARE VARIABLE V$T INTEGER;
DECLARE VARIABLE V$TYPE BIGINT;
DECLARE VARIABLE V$OLD_TYPE INTEGER;
DECLARE VARIABLE V$AUTHOR_ID BIGINT;
DECLARE VARIABLE T BIGINT;
DECLARE VARIABLE V$SECTION_ID BIGINT;
begin

  -- IS_DEL никогда не используется, удаление идет другой процедурой

  I$USER_NAME = TRIM(I$USER_NAME);
  IF(M$USER_ID = 'Веб-администратор') THEN V$AUTHOR_ID = NULL; ELSE V$AUTHOR_ID = M$USER_ID;
  IF(M$USER_ID = 'Веб-администратор') THEN M$USER_ID = 1;
  IF(I$USER_ID = 1 AND (I$USER_NAME IS NULL OR I$USER_NAME <> 'admin')) THEN EXCEPTION DATA_ERROR 'Системный пользователь может называться только admin';
  IF(I$USER_ID = 1 AND (I$EXP_DATE IS NOT NULL OR I$IS_BLOCKED = 1)) THEN EXCEPTION DATA_ERROR 'Пользователь admin не может быть заблокирован или ограничен по времени действия';

  IF(I$SNILS IS NOT NULL) THEN
  BEGIN
    IF(NOT EXISTS(SELECT 1 FROM CHECK_SNILS(:I$SNILS) WHERE IS_REAL = 1))
      THEN EXCEPTION DATA_ERROR 'Введенный СНИЛС не валиден';
  END

  SELECT FIRST 1 U.USER_TYPE
  FROM USERS U
  JOIN LUSERS LU ON LU.USER_ID = U.USER_ID
  JOIN LEVELS L ON L.LEVEL_ID = LU.LEVEL_ID
  JOIN TASKS T ON T.TASK_ID = L.TASK_ID
  JOIN RES R ON R.RES_ID = T.RES_ID AND R.LANG_CODE = 'RU' AND R.VAL = 'Администрирование пользователей'
  WHERE U.USER_ID = :M$USER_ID AND U.IS_BLOCKED = 0 AND U.DATE_DEL IS NULL
  INTO :V$T;

  -- Внештатных юзеров может создавать только администрация
  IF(V$T IS NULL) THEN EXCEPTION DATA_ERROR 'Нет доступа к приложению';
  IF(I$OBJ_ID IS NULL AND V$T NOT IN (1, 5, 6)) THEN EXCEPTION DATA_ERROR 'Только администрация может создавать внештатных пользователей';

  IF(I$OBJ_ID IS NOT NULL) THEN
  BEGIN
    SELECT FIRST 1 TYPE_ID
    FROM OBJECTS
    WHERE OBJ_ID = :I$OBJ_ID AND TYPE_ID IN (10, 14, 20)
    INTO :V$TYPE;

    IF(V$TYPE IS NULL) THEN EXCEPTION DATA_ERROR 'Ссылка на несуществующего сотрудника, обучающегося или родителя';
    IF(V$TYPE = 10 AND I$USER_TYPE <> 12) THEN EXCEPTION DATA_ERROR 'Недопустимая роль для обучающегося';
    IF(V$TYPE = 20 AND I$USER_TYPE <> 22) THEN EXCEPTION DATA_ERROR 'Недопустимая роль для родителя';

    --I$FIRST_NAME = NULL;
    --I$MIDDLE_NAME = NULL;
    --I$LAST_NAME = NULL;
  END

  IF(I$USER_NAME IS NULL OR CHAR_LENGTH(I$USER_NAME) < 3) THEN EXCEPTION DATA_ERROR 'Должно быть указано имя пользователя, не менее 3 символов';

  -- Уникальность имени пользователя
  IF(EXISTS(
    SELECT FIRST 1 1
    FROM USERS U
    WHERE U.USER_NAME = :I$USER_NAME AND (:I$USER_ID IS NULL OR U.USER_ID <> :I$USER_ID) AND U.DATE_DEL IS NULL
  ))
  THEN
    EXCEPTION DATA_ERROR 'Пользователь с таким именем уже есть';

  -- Запрет использования того же имени для удаленных пользователей на 1 год
  IF(EXISTS(
    SELECT FIRST 1 1
    FROM USERS U
    WHERE U.USER_NAME = :I$USER_NAME AND (:I$USER_ID IS NULL OR U.USER_ID <> :I$USER_ID) AND U.DATE_DEL > DATEADD(-1 YEAR TO CURRENT_DATE)
  ))
  THEN
    EXCEPTION DATA_ERROR 'Нельзя использовать имя удаленного пользователя повторно в течение года';

  IF(I$USER_ID IS NULL) THEN
  BEGIN
    -- На случай если пользователь уже был, но удаленный - восстанавливаем
    -- Обязательно после проверки повтора использования имени, иначе нарушение безопасности
    SELECT FIRST 1 U.USER_ID
    FROM USERS U
    WHERE U.OBJ_ID = :I$OBJ_ID
    INTO :I$USER_ID;
  END

  -- 1-based
  V$SECTION_ID = 0;
  FOR
    SELECT ID
    FROM STR_TO_ID_LIST(:I$SECTION_ID)
    INTO :T
  DO
  BEGIN
    V$SECTION_ID = BIN_OR(V$SECTION_ID, BIN_SHL(1, T - 1));
  END
  IF(V$SECTION_ID = 0) THEN V$SECTION_ID = NULL;

  IF(I$USER_ID IS NULL) THEN
  BEGIN

    IF(I$PWD IS NULL) THEN EXCEPTION DATA_ERROR 'При создании пользователя должен быть указан пароль';

    INSERT INTO USERS
    (OBJ_ID, USER_NAME, USER_TYPE, PWD, DATE_DEL, IS_BLOCKED, IS_BLOCKED_PWD, MUST_CHANGE, EXP_DATE, DESCRIPTION,
      LANG_CODE, FIRST_NAME, MIDDLE_NAME, LAST_NAME, SNILS, PWD_TIMEMARK, SECTION_ID)
    VALUES (:I$OBJ_ID, :I$USER_NAME, :I$USER_TYPE, :I$PWD, NULL, :I$IS_BLOCKED, :I$IS_BLOCKED_PWD, :I$MUST_CHANGE, :I$EXP_DATE, :I$DESCRIPTION,
      :I$LANG_CODE, :I$FIRST_NAME, COALESCE(:I$MIDDLE_NAME, ''), :I$LAST_NAME, :I$SNILS, CURRENT_TIMESTAMP, :V$SECTION_ID)
    RETURNING USER_ID INTO :USER_ID;

    -- Регистрируем факт создания
    S = '';
    IF(I$IS_BLOCKED = 1) THEN S = S || ',Заблокирован';
    IF(I$IS_BLOCKED_PWD = 1) THEN S = S || ',БезСменыПароля';
    IF(I$MUST_CHANGE = 1) THEN S = S || ',СменитьПароль';
    IF(LEFT(S, 1) = ',') THEN S = SUBSTRING(S FROM 2);
    IF(S = '') THEN S = 'Активный';

    INSERT INTO USER_EVENTS
    (USER_ID, OBJ_ID, AUTHOR_ID, EVENT_TYPE, VAL)
    VALUES (:USER_ID, :I$OBJ_ID, :V$AUTHOR_ID, 'NEW', 'Создан пользователь ' || :I$USER_NAME || ', статус ' || :S);

    IF(I$USER_TYPE = 1) THEN
    INSERT INTO USER_EVENTS
    (USER_ID, OBJ_ID, AUTHOR_ID, EVENT_TYPE, VAL)
    VALUES (:USER_ID, :I$OBJ_ID, :V$AUTHOR_ID, 'ROLE_ADMIN', 'Назначена роль Администратор при создании');

  END
  ELSE
  BEGIN

    SELECT USER_ID, USER_NAME, USER_TYPE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :USER_ID, :V$OLD_NAME, :V$OLD_TYPE;

    IF(USER_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Пользователь не найден';

    -- Также скидываем метку времени доступа
    UPDATE USERS
    SET
      USER_NAME = :I$USER_NAME, USER_TYPE = :I$USER_TYPE, PWD = COALESCE(:I$PWD, PWD), IS_BLOCKED = :I$IS_BLOCKED, IS_BLOCKED_PWD = :I$IS_BLOCKED_PWD,
      MUST_CHANGE = :I$MUST_CHANGE, EXP_DATE = :I$EXP_DATE, DESCRIPTION = :I$DESCRIPTION, LANG_CODE = :I$LANG_CODE,
      FIRST_NAME = :I$FIRST_NAME, MIDDLE_NAME = COALESCE(:I$MIDDLE_NAME, ''), LAST_NAME = :I$LAST_NAME, SNILS = :I$SNILS,
      SECTION_ID = :V$SECTION_ID,
      DATE_DEL = NULL, LAST_ACCESS = NULL
    WHERE
      USER_ID = :I$USER_ID;

    IF(I$USER_NAME <> V$OLD_NAME) THEN
    INSERT INTO USER_EVENTS
    (USER_ID, OBJ_ID, AUTHOR_ID, EVENT_TYPE, VAL)
    VALUES (:USER_ID, :I$OBJ_ID, :V$AUTHOR_ID, 'CHNAME', 'Новое имя ' || :I$USER_NAME);

    IF(V$OLD_TYPE <> I$USER_TYPE AND I$USER_TYPE = 1) THEN
    INSERT INTO USER_EVENTS
    (USER_ID, OBJ_ID, AUTHOR_ID, EVENT_TYPE, VAL)
    VALUES (:USER_ID, :I$OBJ_ID, :V$AUTHOR_ID, 'ROLE_ADMIN', 'Назначена роль Администратор при изменении');

    IF(V$OLD_TYPE <> I$USER_TYPE AND I$USER_TYPE <> 1) THEN
    INSERT INTO USER_EVENTS
    (USER_ID, OBJ_ID, AUTHOR_ID, EVENT_TYPE, VAL)
    VALUES (:USER_ID, :I$OBJ_ID, :V$AUTHOR_ID, 'ROLE_CHANGE', 'Изменена роль, была роль ' || :V$OLD_TYPE || ', новая ' || :I$USER_TYPE);

    IF(I$PWD IS NOT NULL) THEN
    BEGIN
      UPDATE USERS
      SET PWD_TIMEMARK = CURRENT_TIMESTAMP
      WHERE USER_ID = :I$USER_ID;

      INSERT INTO USER_EVENTS
      (USER_ID, OBJ_ID, AUTHOR_ID, EVENT_TYPE, VAL)
      VALUES (:USER_ID, :I$OBJ_ID, :V$AUTHOR_ID, 'CHPWD', 'Изменен пароль административно');
    END

  END

  EXECUTE PROCEDURE CJ2_JOURNAL_ACCESS_UPD(NULL, :I$USER_ID);

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE USER_LEVEL_GET (
    I$USER_ID BIGINT)
RETURNS (
    LEVEL_ID BIGINT,
    LEVEL_NAME VARCHAR(400))
AS
begin

  SELECT FIRST 1 L.ROOT_OBJ_ID
  FROM LUSERS L
  WHERE L.USER_ID = :I$USER_ID AND L.ROOT_OBJ_ID IS NOT NULL
  INTO :LEVEL_ID;

  IF(LEVEL_ID IS NULL) THEN LEVEL_NAME = 'Регион';
  ELSE LEVEL_NAME = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:LEVEL_ID));

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE USER_SETTINGS_GET (
    USER_ID BIGINT,
    MODULE_ID BIGINT)
RETURNS (
    SETTINGS VARCHAR(4000))
AS
BEGIN
    SELECT SETTINGS
    FROM USER_SETTINGS
    WHERE USER_ID = :USER_ID
      AND MODULE_ID = :MODULE_ID
    INTO SETTINGS;
    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE USER_SETTINGS_SET (
    I$USER_ID BIGINT,
    I$MODULE_ID BIGINT,
    I$SETTINGS VARCHAR(4000))
AS
BEGIN
    UPDATE OR INSERT INTO USER_SETTINGS (USER_ID, MODULE_ID, SETTINGS)
    VALUES (:I$USER_ID, :I$MODULE_ID, :I$SETTINGS)
    MATCHING (USER_ID, MODULE_ID);
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE USER_STAT_GET (
    I$ROLE SMALLINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
declare variable V$OBJ_ID bigint;
declare variable S varchar(1000);
begin

  TAG_NAME = 'classes::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
    SELECT L9.OBJ_ID, C.CAPTION
    FROM LINKS L9
    JOIN VALL V49 ON V49.OBJ_ID = L9.PARENT_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V49.LISTVAL_ID
    LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C ON 1 = 1
    WHERE L9.PARENT_TYPE_ID = 8 AND L9.OBJ_TYPE_ID IN (9, 187) AND L9.DATE_DEL IS NULL
    ORDER BY LV.SORT_ORDER, 2
    INTO :V$OBJ_ID, :S
  DO
  BEGIN
    TAG_NAME = 'classes:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'classes:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'classes:r:name';
    VAL = S;
    SUSPEND;

    -- Всего учеников
    TAG_NAME = 'classes:r:n_students';
    IF(I$ROLE = 22) THEN
    SELECT COUNT(DISTINCT L20.OBJ_ID)
    FROM LINKS L10
    JOIN LINKS L20 ON L20.PARENT_ID = L10.OBJ_ID AND L20.OBJ_TYPE_ID = 20 AND L20.DATE_DEL IS NULL
    WHERE L10.PARENT_ID = :V$OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    INTO :VAL;
    ELSE
    SELECT COUNT(DISTINCT L10.OBJ_ID)
    FROM LINKS L10
    WHERE L10.PARENT_ID = :V$OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    INTO :VAL;
    SUSPEND;

    -- Всего аккаунтов
    TAG_NAME = 'classes:r:n_logins';
    IF(I$ROLE = 22) THEN
    SELECT COUNT(DISTINCT L20.OBJ_ID)
    FROM LINKS L10
    JOIN LINKS L20 ON L20.PARENT_ID = L10.OBJ_ID AND L20.OBJ_TYPE_ID = 20 AND L20.DATE_DEL IS NULL
    JOIN USERS U ON U.OBJ_ID = L20.OBJ_ID AND U.DATE_DEL IS NULL
    WHERE L10.PARENT_ID = :V$OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    INTO :VAL;
    ELSE
    SELECT COUNT(DISTINCT L10.OBJ_ID)
    FROM LINKS L10
    JOIN USERS U ON U.OBJ_ID = L10.OBJ_ID AND U.DATE_DEL IS NULL
    WHERE L10.PARENT_ID = :V$OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    INTO :VAL;
    SUSPEND;

    -- Действующих аккаунтов
    TAG_NAME = 'classes:r:n_logins_good';
    IF(I$ROLE = 22) THEN
    SELECT COUNT(DISTINCT L20.OBJ_ID)
    FROM LINKS L10
    JOIN LINKS L20 ON L20.PARENT_ID = L10.OBJ_ID AND L20.OBJ_TYPE_ID = 20 AND L20.DATE_DEL IS NULL
    JOIN USERS U ON U.OBJ_ID = L20.OBJ_ID AND U.DATE_DEL IS NULL AND U.IS_BLOCKED = 0 AND (U.EXP_DATE IS NULL OR U.EXP_DATE > CURRENT_DATE)
    WHERE L10.PARENT_ID = :V$OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    INTO :VAL;
    ELSE
    SELECT COUNT(DISTINCT L10.OBJ_ID)
    FROM LINKS L10
    JOIN USERS U ON U.OBJ_ID = L10.OBJ_ID AND U.DATE_DEL IS NULL AND U.IS_BLOCKED = 0 AND (U.EXP_DATE IS NULL OR U.EXP_DATE > CURRENT_DATE)
    WHERE L10.PARENT_ID = :V$OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    INTO :VAL;
    SUSPEND;

    -- Аккаунтов СДО
    TAG_NAME = 'classes:r:n_sdo';
    IF(I$ROLE = 22) THEN
    VAL = NULL;
    ELSE
    SELECT COUNT(DISTINCT L10.OBJ_ID)
    FROM LINKS L10
    JOIN VALS V2153 ON V2153.OBJ_ID = L10.OBJ_ID AND V2153.PARAM_ID = 2153 AND V2153.IS_DEL = 0
    WHERE L10.PARENT_ID = :V$OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    INTO :VAL;
    SUSPEND;

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE USER_TASKS_LIST (
    I$USER_ID BIGINT,
    I$MODULE_ID BIGINT = NULL)
RETURNS (
    MODULE_ID BIGINT,
    MODULE_CAPTION VARCHAR(4000),
    TASK_ID BIGINT,
    TASK_CAPTION VARCHAR(4000),
    LEVEL_ID BIGINT,
    LEVEL_CAPTION VARCHAR(4000),
    MODULE_CODE VARCHAR(100),
    ROOT_OBJ_ID BIGINT,
    ROOT_PARENT_ID BIGINT,
    ICON_ID BIGINT,
    READ_ONLY SMALLINT)
AS
DECLARE VARIABLE LANG_CODE CHAR(2);
DECLARE VARIABLE MRES_ID BIGINT;
DECLARE VARIABLE TRES_ID BIGINT;
DECLARE VARIABLE LRES_ID BIGINT;
DECLARE VARIABLE IS_METODIST SMALLINT;
BEGIN
    IF (EXISTS(
        SELECT FIRST 1 1
        FROM KEYS
        WHERE KEY_CODE = 'REG_NUMBER' AND KEY_VAL = 4233
    )) THEN
    BEGIN
        IS_METODIST = 1;
    END
    ELSE
    BEGIN
        IS_METODIST = 0;
    END

    FOR
        SELECT M.MODULE_ID, T.TASK_ID, L.LEVEL_ID, M.MODULE_CODE, LU.ROOT_OBJ_ID, LU.ROOT_PARENT_ID,
          U.LANG_CODE, M.RES_ID, T.RES_ID, L.RES_ID, L.ICON_ID, LU.READ_ONLY
        FROM TASKS T
        JOIN LEVELS L ON L.TASK_ID = T.TASK_ID /*AND L.LEVEL_ID NOT IN (474, 475)*/ AND L.IS_DEL = 0
          AND L.LEVEL_ID NOT IN (489, 490, 211) -- исключаем из толстой версии старую печать документов
        LEFT JOIN LUSERS LU ON LU.LEVEL_ID = L.LEVEL_ID
        LEFT JOIN USERS U ON U.USER_ID = LU.USER_ID
        JOIN MODULES M ON M.MODULE_ID = T.MODULE_ID AND M.IS_DEL = 0 AND M.IS_ACTIVE = 1 AND ((:I$MODULE_ID IS NULL) OR (M.MODULE_ID = :I$MODULE_ID))
        WHERE LU.USER_ID = :I$USER_ID AND T.IS_DEL = 0
        ORDER BY M.SORT_ORDER, T.SORT_ORDER, L.SORT_ORDER
        INTO :MODULE_ID, :TASK_ID, :LEVEL_ID, :MODULE_CODE, :ROOT_OBJ_ID, :ROOT_PARENT_ID,
          :LANG_CODE, :MRES_ID, :TRES_ID, :LRES_ID, :ICON_ID, :READ_ONLY
    DO
    BEGIN
        SELECT VAL
        FROM RES_GET(:MRES_ID, :LANG_CODE)
        INTO :MODULE_CAPTION;

        SELECT VAL
        FROM RES_GET(:TRES_ID, :LANG_CODE)
        INTO :TASK_CAPTION;

        SELECT VAL
        FROM RES_GET(:LRES_ID, :LANG_CODE)
        INTO :LEVEL_CAPTION;

        IF ((IS_METODIST = 0) OR (TASK_ID <> 130)) THEN
        BEGIN
            SUSPEND;
        END
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE USER_TRANSFER_EXPORT RETURNS (
    USER_ID BIGINT,
    USER_TYPE SMALLINT,
    USER_NAME VARCHAR(100),
    DATE_DEL TIMESTAMP,
    PWD VARCHAR(100),
    FIRST_NAME VARCHAR(100),
    MIDDLE_NAME VARCHAR(100),
    LAST_NAME VARCHAR(100),
    DESCRIPTION VARCHAR(100),
    LANG_CODE VARCHAR(2),
    OBJ_ID BIGINT,
    IS_BLOCKED SMALLINT,
    MUST_CHANGE SMALLINT,
    EXP_DATE DATE,
    IS_BLOCKED_PWD SMALLINT,
    ADDED_BY BIGINT,
    DATE_MODIFY TIMESTAMP,
    SNILS VARCHAR(40),
    REG_ID VARCHAR(60),
    ACCESS_LEVEL VARCHAR(4000))
AS
declare variable V$LEVEL bigint;
declare variable V$RO smallint;
declare variable V$ROOT_OBJ_ID bigint;
begin

  FOR
    SELECT U.USER_ID, U.USER_TYPE, U.USER_NAME, U.DATE_DEL, U.PWD, U.FIRST_NAME, U.MIDDLE_NAME, U.LAST_NAME, U.DESCRIPTION, U.LANG_CODE,
      U.IS_BLOCKED, U.MUST_CHANGE, U.EXP_DATE, U.IS_BLOCKED_PWD, U.ADDED_BY, U.DATE_MODIFY, U.SNILS, U.REG_ID
    FROM USERS U
    WHERE U.OBJ_ID IS NULL
    INTO :USER_ID, :USER_TYPE, :USER_NAME, :DATE_DEL, :PWD, :FIRST_NAME, :MIDDLE_NAME, :LAST_NAME, :DESCRIPTION, :LANG_CODE,
      :IS_BLOCKED, :MUST_CHANGE, :EXP_DATE, :IS_BLOCKED_PWD, :ADDED_BY, :DATE_MODIFY, :SNILS, :REG_ID
  DO
  BEGIN
    ACCESS_LEVEL = '';

    -- Для админа права не выгружаем
    FOR
      SELECT U.LEVEL_ID, U.READ_ONLY, U.ROOT_OBJ_ID
      FROM LUSERS U
      WHERE U.USER_ID = :USER_ID AND :USER_ID <> 1
      INTO :V$LEVEL, :V$RO, :V$ROOT_OBJ_ID
    DO
    BEGIN
      IF(ACCESS_LEVEL <> '') THEN ACCESS_LEVEL = ACCESS_LEVEL || ',';
      ACCESS_LEVEL = ACCESS_LEVEL || V$LEVEL;
      ACCESS_LEVEL = ACCESS_LEVEL || IIF(V$RO = 1, 'R', 'F');
      IF(V$ROOT_OBJ_ID IS NOT NULL) THEN ACCESS_LEVEL = ACCESS_LEVEL || V$ROOT_OBJ_ID;
    END

    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE USER_TRANSFER_IMPORT (
    I$USER_ID BIGINT,
    I$USER_TYPE SMALLINT,
    I$USER_NAME VARCHAR(100),
    I$DATE_DEL TIMESTAMP,
    I$PWD VARCHAR(100),
    I$FIRST_NAME VARCHAR(100),
    I$MIDDLE_NAME VARCHAR(100),
    I$LAST_NAME VARCHAR(100),
    I$DESCRIPTION VARCHAR(100),
    I$LANG_CODE VARCHAR(2),
    I$OBJ_ID BIGINT,
    I$IS_BLOCKED SMALLINT,
    I$MUST_CHANGE SMALLINT,
    I$EXP_DATE DATE,
    I$IS_BLOCKED_PWD SMALLINT,
    I$ADDED_BY BIGINT,
    I$DATE_MODIFY TIMESTAMP,
    I$SNILS VARCHAR(40),
    I$REG_ID VARCHAR(60),
    I$ACCESS_LEVEL VARCHAR(4000))
RETURNS (
    USER_ID BIGINT)
AS
declare variable ACCESS_LEVEL varchar(4000);
declare variable LEVEL_ID bigint;
declare variable V$ROOT_OBJ_ID bigint;
declare variable V$LEVEL bigint;
declare variable V$RO smallint;
declare variable P integer;
declare variable S varchar(40);
begin

  UPDATE OR INSERT INTO USERS
  (USER_ID, USER_TYPE, USER_NAME, DATE_DEL, PWD, FIRST_NAME, MIDDLE_NAME, LAST_NAME, DESCRIPTION, LANG_CODE, OBJ_ID,
    IS_BLOCKED, MUST_CHANGE, EXP_DATE, IS_BLOCKED_PWD, ADDED_BY, DATE_MODIFY, SNILS, REG_ID)
  VALUES (:I$USER_ID, :I$USER_TYPE, :I$USER_NAME, :I$DATE_DEL, :I$PWD, :I$FIRST_NAME, :I$MIDDLE_NAME, :I$LAST_NAME, :I$DESCRIPTION, :I$LANG_CODE, :I$OBJ_ID,
    :I$IS_BLOCKED, :I$MUST_CHANGE, :I$EXP_DATE, :I$IS_BLOCKED_PWD, :I$ADDED_BY, :I$DATE_MODIFY, :I$SNILS, :I$REG_ID);

  USER_ID = I$USER_ID;

  -- Корректируем список прав доступа
  -- Если хоть что-то поменялось, просто все сносим и вставляем заново
  ACCESS_LEVEL = '';
  LEVEL_ID = NULL;
  FOR
    SELECT U.LEVEL_ID, U.READ_ONLY, U.ROOT_OBJ_ID
    FROM LUSERS U
    WHERE U.USER_ID = :USER_ID AND :USER_ID <> 1
    INTO :V$LEVEL, :V$RO, :V$ROOT_OBJ_ID
  DO
  BEGIN
    IF(ACCESS_LEVEL <> '') THEN ACCESS_LEVEL = ACCESS_LEVEL || ',';
    ACCESS_LEVEL = ACCESS_LEVEL || V$LEVEL;
    ACCESS_LEVEL = ACCESS_LEVEL || IIF(V$RO = 1, 'R', 'F');
    IF(V$ROOT_OBJ_ID IS NOT NULL) THEN ACCESS_LEVEL = ACCESS_LEVEL || V$ROOT_OBJ_ID;
  END

  IF(I$ACCESS_LEVEL <> ACCESS_LEVEL AND I$USER_ID <> 1) THEN
  BEGIN
    DELETE FROM LUSERS WHERE USER_ID = :I$USER_ID;

    WHILE(I$ACCESS_LEVEL <> '') DO
    BEGIN
      P = POSITION(',' IN I$ACCESS_LEVEL);
      IF(P <= 0) THEN P = CHAR_LENGTH(I$ACCESS_LEVEL) + 1;
      S = SUBSTRING(I$ACCESS_LEVEL FROM 1 FOR P - 1);
      I$ACCESS_LEVEL = SUBSTRING(I$ACCESS_LEVEL FROM P + 1);

      P = MAXVALUE(POSITION('R' IN S), POSITION('F' IN S));
      IF(P <= 0) THEN EXCEPTION DATA_ERROR 'Неверный формат строки с правами доступа';
      V$LEVEL = SUBSTRING(S FROM 1 FOR P - 1);
      V$RO = IIF(SUBSTRING(S FROM P FOR 1) = 'R', 1, 0);
      S = SUBSTRING(S FROM P + 1);
      IF(S = '') THEN V$ROOT_OBJ_ID = NULL; ELSE V$ROOT_OBJ_ID = S;

      INSERT INTO LUSERS
      (USER_ID, LEVEL_ID, ROOT_OBJ_ID, READ_ONLY)
      VALUES (:I$USER_ID, :V$LEVEL, :V$ROOT_OBJ_ID, :V$RO);
    END
  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_ANSWER_SUBMIT (
    I$SQ_ID BIGINT,
    I$USER_ID BIGINT,
    I$ANSWER_DATA VARCHAR(4000),
    I$METADATA_ID VARCHAR(40),
    I$NETWORK_DATA VARCHAR(100),
    I$TIME INTEGER)
RETURNS (
    STATE_ID INTEGER,
    SESSION_STATE_ID INTEGER,
    QUESTION_NUM INTEGER,
    SESSION_ID BIGINT)
AS
DECLARE VARIABLE V$PERSON_ID BIGINT;
DECLARE VARIABLE V$SSN_PERSON_ID BIGINT;
DECLARE VARIABLE V$SESSION_STATE INTEGER;
DECLARE VARIABLE V$QUESTION_TYPE SMALLINT;
DECLARE VARIABLE V$QUESTION_STATE INTEGER;
DECLARE VARIABLE V$QUESTION_ID BIGINT;
DECLARE VARIABLE V$NEW_STATE_ID INTEGER;
DECLARE VARIABLE V$RATE INTEGER;
DECLARE VARIABLE V$TIME INTEGER;
begin

  -- Сдвигаем время на 1 секунду, если вдруг пользователь жамкнул слишком быстро
  IF(I$TIME = 0) THEN I$TIME = 1;

  -- UPPER не делаем, чтобы не портить ответы типа C
  I$ANSWER_DATA = TRIM(I$ANSWER_DATA);

  -- По USER_ID определяем персону
  SELECT U.OBJ_ID FROM USERS U WHERE U.USER_ID = :I$USER_ID INTO :V$PERSON_ID;

  -- Получаем тип и статус вопроса, статус тестирования, сверяем персону сдающего
  SELECT S.STATE_ID, S.PERSON_ID, Q.QUESTION_TYPE, SQ.STATE_ID, Q.OBJ_ID, S.DURATION, S.OBJ_ID, S.STATE_ID, TSP.Q_ORDER
  FROM UT_SESSION_QUESTIONS SQ
  JOIN UT_SESSIONS S ON S.OBJ_ID = SQ.SESSION_ID AND S.DATE_DEL IS NULL AND S.PERSON_ID = :V$PERSON_ID
  JOIN UT_TEST_VAR_QUESTIONS VQ ON VQ.OBJ_ID = SQ.QUESTION_ID AND VQ.DATE_DEL IS NULL
  JOIN UT_TEST_STRUCT_POINTS TSP ON TSP.OBJ_ID = VQ.STRUCT_POINT_ID
  JOIN UT_QUESTIONS Q ON Q.OBJ_ID = VQ.QUESTION_ID AND Q.DATE_DEL IS NULL
  WHERE SQ.OBJ_ID = :I$SQ_ID AND SQ.DATE_DEL IS NULL AND SQ.QUESTION_ID IS NOT NULL
  UNION
  SELECT S.STATE_ID, S.PERSON_ID, Q.QUESTION_TYPE, SQ.STATE_ID, Q.OBJ_ID, S.DURATION, S.OBJ_ID, S.STATE_ID, EQ.SORT_INDEX
  FROM UT_SESSION_QUESTIONS SQ
  JOIN UT_SESSIONS S ON S.OBJ_ID = SQ.SESSION_ID AND S.DATE_DEL IS NULL AND S.PERSON_ID = :V$PERSON_ID
  JOIN UT_EXAM_QUESTIONS EQ ON EQ.OBJ_ID = SQ.QUESTION_RAW
  JOIN UT_QUESTIONS Q ON Q.OBJ_ID = EQ.QUESTION_ID
  WHERE SQ.OBJ_ID = :I$SQ_ID AND SQ.DATE_DEL IS NULL AND SQ.QUESTION_RAW IS NOT NULL
  INTO :V$SESSION_STATE, :V$SSN_PERSON_ID, :V$QUESTION_TYPE, :V$QUESTION_STATE, :V$QUESTION_ID, :V$TIME, :SESSION_ID, :SESSION_STATE_ID, :QUESTION_NUM;

  IF(V$SESSION_STATE IS NULL) THEN EXCEPTION DATA_ERROR 'Тестирование или вопрос не найдены, или были удалены';
  IF(V$SESSION_STATE <> 2) THEN EXCEPTION DATA_ERROR 'Недопустимый статус тестирования (' || V$SESSION_STATE || '), ответ не может быть принят';

  -- Проверяем, находится ли переданное время в пределах допустимого для тестирования, и не меньше ли оно момента на начало теста
  IF(I$TIME < V$TIME) THEN EXCEPTION DATA_ERROR 'Полученная метка времени ошибочна, ответ не может быть принят';

  -- Проверяем, можно ли создавать ответ повторно, если он уже был отвечен ?

  -- Статус по умолчанию = ответ загружен
  V$NEW_STATE_ID = 21;
  V$RATE = NULL;

  -- Если ответ может быть сразу же проверен, формируем базовую запись результата
  -- При повторном ответе, старую запись затираем и создаем новую
  IF(V$QUESTION_TYPE IN (1, 2, 4, 5)) THEN
  BEGIN

    -- !!! UT_SESSION_RESULTS более не используется
    /*UPDATE UT_SESSION_RESULTS
    SET DATE_DEL = CURRENT_TIMESTAMP
    WHERE DATE_DEL IS NULL AND QUESTION_ID = :I$SQ_ID AND LEVEL_ID = 0;*/

    -- Далее парсер результатов конкретного типа вопросов
    IF(V$QUESTION_TYPE = 1) THEN
    BEGIN
      SELECT STATE_ID, RATE
      FROM UT_VALIDATE_ANSWER_01(:V$QUESTION_ID, :I$ANSWER_DATA)
      INTO :V$NEW_STATE_ID, :V$RATE;
    END
    ELSE IF(V$QUESTION_TYPE = 2) THEN
    BEGIN
      SELECT STATE_ID, RATE
      FROM UT_VALIDATE_ANSWER_02(:V$QUESTION_ID, :I$ANSWER_DATA)
      INTO :V$NEW_STATE_ID, :V$RATE;
    END
    ELSE IF(V$QUESTION_TYPE = 4) THEN
    BEGIN
      SELECT STATE_ID, RATE
      FROM UT_VALIDATE_ANSWER_04(:V$QUESTION_ID, :I$ANSWER_DATA)
      INTO :V$NEW_STATE_ID, :V$RATE;
    END
    ELSE IF(V$QUESTION_TYPE = 5) THEN
    BEGIN
      SELECT STATE_ID, RATE
      FROM UT_VALIDATE_ANSWER_05(:V$QUESTION_ID, :I$ANSWER_DATA)
      INTO :V$NEW_STATE_ID, :V$RATE;
    END

    -- Если смогли проверить, то выставляем статус обработки
    IF(V$NEW_STATE_ID IS NOT NULL AND V$NEW_STATE_ID > 21) THEN
    BEGIN
      -- !!! UT_SESSION_RESULTS более не используется
      /*INSERT INTO UT_SESSION_RESULTS
      (QUESTION_ID, CRITERIA_ID, EXPERT_ID, LEVEL_ID, STATE_ID, RAW_RESULT)
      VALUES (:I$SQ_ID, 0, NULL, 0, :V$NEW_STATE_ID, :V$RATE);*/
    END
  END

  -- Если результат не определен, сохраняем со статусом "результат загружен"
  IF(V$NEW_STATE_ID IS NULL) THEN V$NEW_STATE_ID = 21;

  -- Сохраняем результат в ответе, статус зависит от предыдущего шага
  UPDATE UT_SESSION_QUESTIONS
  SET ANSWER_DATA = :I$ANSWER_DATA, METADATA_ID = :I$METADATA_ID, STATE_ID = :V$NEW_STATE_ID, RAW_RESULT = :V$RATE
  WHERE OBJ_ID = :I$SQ_ID;

  -- Обновляем время и общий результат теста
  V$RATE = (SELECT RAW_RESULT FROM UT_TEST_SESSION_TOTAL_RECALC(:SESSION_ID, NULL, NULL, 0));

  UPDATE UT_SESSIONS
  SET RAW_RESULT = :V$RATE, DURATION = :I$TIME
  WHERE OBJ_ID = :SESSION_ID;

  STATE_ID = V$NEW_STATE_ID;
  -- SESSION_STATE_ID пока не трогаем на предмет истечения времени тестирования
  -- SESSION_STATE_ID =

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_BLANK_ACQUIRE (
    I$EXAM_ID BIGINT,
    I$STATION_ID VARCHAR(40),
    I$USER_ID VARCHAR(40))
RETURNS (
    EXAM_ID BIGINT,
    PACKET_ID BIGINT,
    PAGE_ID BIGINT,
    FILE_ID VARCHAR(40),
    TEMPLATE_ID INTEGER,
    SIDE SMALLINT,
    BARCODE1 VARCHAR(128),
    CHARSETS VARCHAR(4000))
AS
declare variable V$DB_LEVEL integer;
begin

  SELECT COALESCE(CAST(K.KEY_VAL AS INTEGER) - 1, 0)
  FROM KEYS K
  WHERE K.KEY_CODE = 'LEVEL'
  INTO :V$DB_LEVEL;

  -- Если есть залипший бланк для этой станции - возвращаем его
  SELECT FIRST 1 B.OBJ_ID, P.OBJ_ID, D.OBJ_ID, B.BLANK_TYPE, B.BLANK_SIDE, B.BARCODE_DATA, B.FILE_ID
  FROM UT_EXAM_DATES D
  JOIN UT_PACKAGES P ON P.DATE_DEL IS NULL AND P.ED_ID = D.OBJ_ID AND P.STATE_ID IN (9, 10)
  JOIN UT_BLANKS B ON B.DATE_DEL IS NULL AND B.PACKAGE_ID = P.OBJ_ID AND B.STATE_ID = 10 AND B.RCV_STATION_ID = :I$STATION_ID
  WHERE D.DATE_DEL IS NULL AND D.EXAM_STATE >= 600 AND D.EXAM_STATE <= 900 AND (:I$EXAM_ID IS NULL OR D.OBJ_ID = :I$EXAM_ID) AND D.H_LEVEL = :V$DB_LEVEL
  INTO :PAGE_ID, :PACKET_ID, :EXAM_ID, :TEMPLATE_ID, :SIDE, :BARCODE1, :FILE_ID;

  IF(PAGE_ID IS NOT NULL) THEN
  BEGIN
      -- Выбираем кодировки полей
      CHARSETS = (SELECT VAL FROM UT_TEST_ATTR_CHARSETS(:EXAM_ID));
      SUSPEND;
      EXIT;
  END

  -- Получаем новый бланк
  SELECT FIRST 1 B.OBJ_ID, P.OBJ_ID, D.OBJ_ID, B.BLANK_TYPE, B.BLANK_SIDE, B.BARCODE_DATA, B.FILE_ID
  FROM UT_EXAM_DATES D
  JOIN UT_PACKAGES P ON P.DATE_DEL IS NULL AND P.ED_ID = D.OBJ_ID AND P.STATE_ID >= 9
  JOIN UT_BLANKS B ON B.DATE_DEL IS NULL AND B.PACKAGE_ID = P.OBJ_ID AND B.STATE_ID = 9
  WHERE D.DATE_DEL IS NULL AND D.EXAM_STATE >= 600 AND D.EXAM_STATE <= 900 AND (:I$EXAM_ID IS NULL OR D.OBJ_ID = :I$EXAM_ID) AND D.H_LEVEL = :V$DB_LEVEL
  INTO :PAGE_ID, :PACKET_ID, :EXAM_ID, :TEMPLATE_ID, :SIDE, :BARCODE1, :FILE_ID;

  IF(PAGE_ID IS NOT NULL) THEN
  BEGIN

      UPDATE UT_BLANKS B
      SET B.STATE_ID = 10, B.RCV_STATION_ID = :I$STATION_ID, DATE_MODIFY = CURRENT_TIMESTAMP
      WHERE OBJ_ID = :PAGE_ID AND B.STATE_ID = 9;

      -- Проверяем, все ли ОК
      IF(NOT EXISTS(
          SELECT FIRST 1 1
          FROM UT_BLANKS B
          WHERE B.OBJ_ID = :PAGE_ID AND B.STATE_ID = 10 AND B.RCV_STATION_ID = :I$STATION_ID
      )) THEN EXCEPTION DATA_ERROR 'Сетевой конфликт при захвате бланка, повторим позже';

      -- Выбираем кодировки полей
      CHARSETS = (SELECT VAL FROM UT_TEST_ATTR_CHARSETS(:EXAM_ID));

  END

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_CHECKSUM_EAN128 (
    I$S VARCHAR(128) NOT NULL)
RETURNS (
    VAL VARCHAR(1))
AS
begin
    SUSPEND;
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_CHECKSUM_EAN13 (
    I$S VARCHAR(128) NOT NULL)
RETURNS (
    VAL VARCHAR(1))
AS
declare variable N integer;
declare variable C smallint;
declare variable V integer;
begin

  N = 1;
  V = 0;

  WHILE(CHAR_LENGTH(I$S) > 0) DO
  BEGIN

      C = SUBSTRING(I$S FROM CHAR_LENGTH(I$S) FOR 1);
      IF(N = 1) THEN V = V + C * 3; ELSE V = V + C;

      IF(N = 1) THEN N = 2; ELSE N = 1;
      I$S = SUBSTRING(I$S FROM 1 FOR CHAR_LENGTH(I$S) - 1);

  END

  V = MOD(V, 10);
  IF(V > 0) THEN V = 10 - V;

  VAL = V;

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_CHECKSUM_EAN39 (
    I$S VARCHAR(128) NOT NULL)
RETURNS (
    VAL VARCHAR(1))
AS
declare variable C char(1);
declare variable CN smallint;
declare variable V integer;
begin

  -- Код идет без стартового символа
  V = 0;

  WHILE(CHAR_LENGTH(I$S) > 0) DO
  BEGIN

      C = SUBSTRING(I$S FROM 1 FOR 1);
      I$S = SUBSTRING(I$S FROM 2);

      -- Переводим код символа
      CN = ASCII_VAL(C);
      IF(CN >= 48 AND CN <= 57) THEN CN = CN - 48; -- 0..9
      ELSE IF(CN >= 65 AND CN <= 90) THEN CN = CN - 65 + 10; -- A..Z
      ELSE IF(CN = 45) THEN CN = 36; -- -
      ELSE IF(CN = 46) THEN CN = 37; -- .
      ELSE IF(CN = 32) THEN CN = 38; -- пробел
      ELSE IF(CN = 36) THEN CN = 39; -- $
      ELSE IF(CN = 47) THEN CN = 40; -- /
      ELSE IF(CN = 43) THEN CN = 41; -- +
      ELSE IF(CN = 37) THEN CN = 42; -- %
      ELSE EXCEPTION DATA_ERROR 'Неверный символ в штрихкоде';

      V = V + CN;

  END

  V = MOD(V, 43);

  IF(V >= 0 AND V <= 9) THEN VAL = ASCII_CHAR(V + 48);
  ELSE IF(V >= 10 AND V <= 35) THEN VAL = ASCII_CHAR(65 + V - 10);
  ELSE VAL = SUBSTRING('-. $/+%' FROM V - 35 FOR 1);

  SUSPEND;
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_CLASS_GET RETURNS (
    FORMSTEP INTEGER,
    FORMNUM INTEGER,
    FORMINDEX VARCHAR(5),
    KEYFIELD VARCHAR(25))
AS
declare variable V$OBJ_ID bigint;
BEGIN
  SELECT FIRST 1 L2.OBJ_ID
  FROM LINKS L2
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2
  INTO V$OBJ_ID;

  FOR
      SELECT
          CASE WHEN VL.LISTVAL_ID = 22 THEN 1 WHEN VL.LISTVAL_ID = 26 THEN 2 WHEN VL.LISTVAL_ID = 27 THEN 4 END AS FORMSTEP,
          VL1.LISTVAL_ID - 36 AS FORMNUM, VS.VAL AS FORMINDEX
      FROM LINKS L7
      JOIN VALL VL ON L7.OBJ_ID = VL.OBJ_ID AND VL.PARAM_ID = 43
      JOIN LINKS L8 ON L7.OBJ_ID = L8.PARENT_ID and l8.DATE_DEL IS NULL
      JOIN VALL VL1 ON L8.OBJ_ID = VL1.OBJ_ID AND VL1.PARAM_ID = 49
      JOIN LINKS L9 ON L8.OBJ_ID = L9.PARENT_ID and l9.DATE_DEL IS NULL
      JOIN VALS VS ON L9.OBJ_ID = VS.OBJ_ID AND VS.PARAM_ID = 54
      WHERE L7.OBJ_TYPE_ID = 7 AND l7.DATE_DEL IS NULL AND L7.PARENT_ID = :V$OBJ_ID
      ORDER BY 2
      INTO FORMSTEP, FORMNUM, FORMINDEX
  DO
  BEGIN
      KEYFIELD = FORMSTEP || FORMNUM || FORMINDEX;
      SUSPEND;
  END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_CODING_TREE_GET (
    I$OBJ_ID BIGINT,
    I$SHOW_QUESTIONS SMALLINT = 1)
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(4000))
AS
declare variable V$OBJ_ID bigint;
declare variable V$NAME varchar(1000);
declare variable V$TYPE varchar(10);
declare variable V$SCORE integer;
declare variable V$ORDER integer;
declare variable V$LEVEL integer;
declare variable V$CHARSET smallint;
declare variable V$CHARSET_NAME varchar(100);
begin

  TAG_NAME = 'sections';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'sections::json&colon;array';
  VAL = '1';
  SUSPEND;

  FOR
      SELECT T.OBJ_ID, T.OBJ_NAME, T.SORT_ORDER, T.N_LEVEL
      FROM UT_KIM_CODING_LEVELS T
      WHERE T.DATE_DEL IS NULL AND ((T.CODING_ID = :I$OBJ_ID AND T.PARENT_ID IS NULL) OR T.PARENT_ID = :I$OBJ_ID)
      ORDER BY T.SORT_ORDER
      INTO :V$OBJ_ID, :V$NAME, :V$ORDER, :V$LEVEL
  DO
  BEGIN
      TAG_NAME = 'sections:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'sections:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'sections:r:name';
      VAL = V$NAME;
      SUSPEND;
      TAG_NAME = 'sections:r:order';
      VAL = V$ORDER;
      SUSPEND;
      TAG_NAME = 'sections:r:n_level';
      VAL = V$LEVEL;
      SUSPEND;

      TAG_NAME = 'sections:r:n_children';
      VAL = (SELECT COUNT(*) FROM UT_KIM_CODING_LEVELS WHERE DATE_DEL IS NULL AND PARENT_ID = :V$OBJ_ID);
      SUSPEND;

      TAG_NAME = 'sections:r:n_questions';
      VAL = (SELECT COUNT(*) FROM UT_QUESTIONS WHERE DATE_DEL IS NULL AND SECTION_ID = :V$OBJ_ID);
      SUSPEND;
  END

  IF(I$SHOW_QUESTIONS = 1) THEN
  BEGIN

      TAG_NAME = 'questions';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'questions::json&colon;array';
      VAL = '1';
      SUSPEND;

      FOR
          SELECT T.OBJ_ID, T.OBJ_NAME, QT.OBJ_VALUE, T.MAX_SCORE, T.Q_LEVEL, T.SORT_ORDER, C.OBJ_ID, C.OBJ_NAME
          FROM UT_QUESTIONS T
          JOIN UT_QUESTION_TYPE QT ON QT.OBJ_ID = T.QUESTION_TYPE
          LEFT JOIN UT_CHARSETS C ON C.OBJ_ID = T.CHARSET_ID
          WHERE T.DATE_DEL IS NULL AND T.SECTION_ID = :I$OBJ_ID
          ORDER BY T.SORT_ORDER
          INTO :V$OBJ_ID, :V$NAME, :V$TYPE, :V$SCORE, :V$LEVEL, :V$ORDER, :V$CHARSET, :V$CHARSET_NAME
      DO
      BEGIN
          TAG_NAME = 'questions:r';
          VAL = NULL;
          SUSPEND;
          TAG_NAME = 'questions:r:id';
          VAL = V$OBJ_ID;
          SUSPEND;
          TAG_NAME = 'questions:r:name';
          VAL = V$NAME;
          SUSPEND;
          TAG_NAME = 'questions:r:type';
          VAL = V$TYPE;
          SUSPEND;
          TAG_NAME = 'questions:r:level';
          VAL = V$LEVEL;
          SUSPEND;
          TAG_NAME = 'questions:r:score';
          VAL = V$SCORE;
          SUSPEND;
          TAG_NAME = 'questions:r:order';
          VAL = V$ORDER;
          SUSPEND;
          TAG_NAME = 'questions:r:charset_id';
          VAL = V$CHARSET;
          SUSPEND;
          TAG_NAME = 'questions:r:charset';
          VAL = V$CHARSET_NAME;
          SUSPEND;
      END
  END
  ELSE
  BEGIN
      TAG_NAME = 'n_questions';
      VAL = (SELECT COUNT(*) FROM UT_QUESTIONS WHERE DATE_DEL IS NULL AND SECTION_ID = :I$OBJ_ID);
      SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_DISTRICT_LIST RETURNS (
    DISTRICT_ID BIGINT,
    DISTRICT_CAPTION VARCHAR(4000),
    SORT_ORDER DOUBLE PRECISION)
AS
DECLARE VARIABLE V$SREGION_ID BIGINT;
BEGIN
    V$SREGION_ID = NULL;

    SELECT FIRST 1 L.OBJ_ID
    FROM LINKS L
    WHERE L.DATE_DEL IS NULL
      AND L.OBJ_TYPE_ID = 112
    INTO :V$SREGION_ID;

    IF (V$SREGION_ID IS NULL) THEN
    BEGIN
        SELECT FIRST 1 L.PARENT_ID
        FROM LINKS L
        WHERE L.DATE_DEL IS NULL
          AND L.PARENT_TYPE_ID = 112
        INTO :V$SREGION_ID;
    END

    IF (V$SREGION_ID IS NOT NULL) THEN
    BEGIN
        FOR SELECT L.OBJ_ID
            FROM LINKS L
            WHERE L.PARENT_ID = :V$SREGION_ID
              AND L.DATE_DEL IS NULL
              AND L.OBJ_TYPE_ID = 111
            INTO :DISTRICT_ID
        DO
        BEGIN
            SELECT CAPTION, SORT_ORDER
            FROM OBJECT_CAPTION_GET(:DISTRICT_ID)
            INTO :DISTRICT_CAPTION, :SORT_ORDER;

            SUSPEND;
        END
    END
    ELSE
    BEGIN
        FOR SELECT L.OBJ_ID
            FROM LINKS L
            WHERE L.PARENT_ID IS NULL
              AND L.DATE_DEL IS NULL
              AND L.OBJ_TYPE_ID = 111
            INTO :DISTRICT_ID
        DO
        BEGIN
            SELECT CAPTION, SORT_ORDER
            FROM OBJECT_CAPTION_GET(:DISTRICT_ID)
            INTO :DISTRICT_CAPTION, :SORT_ORDER;

            SUSPEND;
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_EMPLOYEE_DESC (
    I$OBJ_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    NAME_LAST VARCHAR(200),
    NAME_FIRST VARCHAR(200),
    NAME_MID VARCHAR(200),
    NAME_FULL VARCHAR(400),
    BIRTH_DATE DATE,
    JOB_TITLE VARCHAR(400),
    OU_ID BIGINT,
    OU_NAME VARCHAR(200),
    AREA_ID BIGINT,
    AREA_NAME VARCHAR(200),
    JOB_ID BIGINT)
AS
begin

  OBJ_ID = I$OBJ_ID;

  -- ФИО и дата рождения
  SELECT FIRST 1 V59.VAL, V60.VAL, V61.VAL, V241.VAL
  FROM OBJECTS O
  JOIN VALS V59 ON V59.OBJ_ID = O.OBJ_ID AND V59.PARAM_ID = 59 AND V59.IS_DEL = 0
  JOIN VALS V60 ON V60.OBJ_ID = O.OBJ_ID AND V60.PARAM_ID = 60 AND V60.IS_DEL = 0
  LEFT JOIN VALS V61 ON V61.OBJ_ID = O.OBJ_ID AND V61.PARAM_ID = 61 AND V61.IS_DEL = 0
  LEFT JOIN VALD V241 ON V241.OBJ_ID = O.OBJ_ID AND V241.PARAM_ID = 241 AND V241.IS_DEL = 0
  WHERE O.OBJ_ID = :I$OBJ_ID
  INTO :NAME_LAST, :NAME_FIRST, :NAME_MID, :BIRTH_DATE;

  -- Действующая основная должность
  SELECT FIRST 1 LP13.PARENT_ID, V589.VAL
  FROM LINKS L15
  JOIN VALL V72 ON V72.OBJ_ID = L15.OBJ_ID AND V72.PARAM_ID = 72 AND V72.IS_DEL = 0 AND V72.LISTVAL_ID = 934
  LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
  JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
  JOIN VALS V589 ON V589.OBJ_ID = LP13.PARENT_ID AND V589.PARAM_ID = 589 AND V589.IS_DEL = 0
  WHERE L15.PARENT_ID = :I$OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
      AND (V74.VAL IS NULL OR V74.VAL >= CURRENT_DATE)
  INTO :JOB_ID, :JOB_TITLE;

  -- Восстанавливаем реквизиты ОУ
  SELECT LP2.PARENT_ID
  FROM LINKS LP2
  WHERE LP2.OBJ_ID = :I$OBJ_ID AND LP2.PARENT_TYPE_ID = 2 AND LP2.DATE_DEL IS NULL
  INTO :OU_ID;

  -- Уволенный ?
  IF(OU_ID IS NULL) THEN
  BEGIN
      SELECT LP2.PARENT_ID
      FROM LINKS LP84
      JOIN LINKS LP2 ON LP2.OBJ_ID = LP84.PARENT_ID AND LP2.PARENT_TYPE_ID = 2 AND LP2.DATE_DEL IS NULL
      WHERE LP84.OBJ_ID = :I$OBJ_ID AND LP84.PARENT_TYPE_ID = 84 AND LP84.DATE_DEL IS NULL
      INTO :OU_ID;
  END

  -- Реквизиты ОУ
  SELECT SUBSTRING(V2.VAL FROM 1 FOR 200), V2163.LISTVAL_ID, R.VAL
  FROM VALS V2
  LEFT JOIN VALL V2163 ON V2163.OBJ_ID = V2.OBJ_ID AND V2163.PARAM_ID = 2163 AND V2163.IS_DEL = 0
  LEFT JOIN LISTVALS LV ON LV.LISTVAL_ID = V2163.LISTVAL_ID
  LEFT JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
  WHERE V2.OBJ_ID = :OU_ID AND V2.PARAM_ID = 2 AND V2.IS_DEL = 0
  INTO :OU_NAME, :AREA_ID, :AREA_NAME;

  NAME_FULL = NAME_LAST || ' ' || NAME_FIRST || COALESCE(' ' || NAME_MID, '');

  SUSPEND;
end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_EPLAN_GET (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE N INTEGER;
DECLARE VARIABLE V$ID BIGINT;
DECLARE VARIABLE V$T BIGINT;
DECLARE VARIABLE V$SC SMALLINT;
DECLARE VARIABLE V$S VARCHAR(1000);
DECLARE VARIABLE SUBJECT_ID BIGINT;
DECLARE VARIABLE STAGE_ID INTEGER;
DECLARE VARIABLE EXAM_DATE_START DATE;
DECLARE VARIABLE EXAM_DATE_END DATE;
DECLARE VARIABLE DURATION INTEGER;
DECLARE VARIABLE EXAM_DAY_TYPE INTEGER;
DECLARE VARIABLE EXAM_STATE INTEGER;
DECLARE VARIABLE C_CALC_MODE INTEGER;
DECLARE VARIABLE C_EXPERT_NUM INTEGER;
DECLARE VARIABLE C_DIFF_QUESTION INTEGER;
DECLARE VARIABLE C_DIFF_TOTAL INTEGER;
DECLARE VARIABLE METHOD_ID INTEGER;
DECLARE VARIABLE PLAN_METHOD_ID INTEGER;
DECLARE VARIABLE ATTEMPTS INTEGER;
DECLARE VARIABLE OWNER_ID BIGINT;
DECLARE VARIABLE H_LEVEL INTEGER;
DECLARE VARIABLE ORG_REF BIGINT;
DECLARE VARIABLE OBJ_NAME VARCHAR(400);
DECLARE VARIABLE PAUSE_ENABLED INTEGER;
DECLARE VARIABLE FLOW_MODE INTEGER;
DECLARE VARIABLE V$KIM_ID BIGINT;
DECLARE VARIABLE V$KIM_NAME VARCHAR(1000);
DECLARE VARIABLE V$TV_ID BIGINT;
DECLARE VARIABLE V$TV_NAME VARCHAR(100);
DECLARE VARIABLE V$TV_NUM INTEGER;
DECLARE VARIABLE V$BLANK_AB_ID BIGINT;
DECLARE VARIABLE V$BLANK_C_ID BIGINT;
DECLARE VARIABLE V$BLANK_EXT_ID BIGINT;
DECLARE VARIABLE V$BLANK_GEN_ID BIGINT;
DECLARE VARIABLE V$DB_LEVEL SMALLINT;
DECLARE VARIABLE V$ACTIVE SMALLINT;
DECLARE VARIABLE V$OUR_ORG BIGINT;
DECLARE VARIABLE V$ACCESS SMALLINT;
DECLARE VARIABLE V$EXPERT_ASSN_MODE SMALLINT;
DECLARE VARIABLE V$OU_ID BIGINT;
DECLARE VARIABLE V$D1 DATE;
DECLARE VARIABLE V$D2 DATE;
DECLARE VARIABLE V$N0 INTEGER;
DECLARE VARIABLE V$NMIN INTEGER;
DECLARE VARIABLE V$N4 INTEGER;
DECLARE VARIABLE V$N5 INTEGER;
DECLARE VARIABLE V$NMAX INTEGER;
DECLARE VARIABLE V$MATCH_ORG SMALLINT;
DECLARE VARIABLE V$FILE_ID BIGINT;
DECLARE VARIABLE V$OU_LICENCE_TYPE CHAR(1);
DECLARE VARIABLE PPE_ID BIGINT;
DECLARE VARIABLE V$HAS_OU SMALLINT;
DECLARE VARIABLE V$HAS_SPO SMALLINT;
DECLARE VARIABLE V$RESULTS_ALW SMALLINT;
DECLARE VARIABLE V$HINT_MODE SMALLINT;
begin

  SELECT STATUS FROM OU_LICENCE_TYPE INTO :V$OU_LICENCE_TYPE;

  V$HAS_OU = 0;
  V$HAS_SPO = 0;
  IF(V$OU_LICENCE_TYPE = 'O') THEN V$HAS_OU = 1;
  IF(V$OU_LICENCE_TYPE = 'C') THEN V$HAS_SPO = 1;


  IF(V$OU_LICENCE_TYPE = 'S') THEN
  BEGIN
    SELECT FIRST 1 L2.OBJ_ID
    FROM LINKS L2
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :V$OU_ID;

    SELECT FIRST 1 1
    FROM LINKS L472
    JOIN VALL V3327 ON V3327.OBJ_ID = L472.OBJ_ID AND V3327.PARAM_ID = 3327 AND V3327.IS_DEL = 0 AND V3327.LISTVAL_ID IN (22, 26, 27)
    WHERE L472.PARENT_ID = :V$OU_ID AND L472.OBJ_TYPE_ID = 472 AND L472.DATE_DEL IS NULL
    INTO :V$HAS_OU;

    SELECT FIRST 1 1
    FROM LINKS L472
    JOIN VALL V3327 ON V3327.OBJ_ID = L472.OBJ_ID AND V3327.PARAM_ID = 3327 AND V3327.IS_DEL = 0 AND V3327.LISTVAL_ID IN (28, 29, 13129)
    WHERE L472.PARENT_ID = :V$OU_ID AND L472.OBJ_TYPE_ID = 472 AND L472.DATE_DEL IS NULL
    INTO :V$HAS_SPO;

    -- На региональном уровне всегда оба варианта
    IF(V$OU_ID IS NULL) THEN
    BEGIN
      V$HAS_OU = 1;
      V$HAS_SPO = 1;
    END
  END

  TAG_NAME = 'id';
  VAL = I$OBJ_ID;
  SUSPEND;

  TAG_NAME = 'ou_type';
  VAL = V$OU_LICENCE_TYPE;
  SUSPEND;

  SELECT D.SUBJECT_ID, D.STAGE_ID, D.EXAM_DATE_START, D.EXAM_DATE_END, D.DURATION, D.EXAM_DAY_TYPE, D.EXAM_STATE, D.C_CALC_MODE, D.C_EXPERT_NUM,
    D.C_DIFF_QUESTION, D.C_DIFF_TOTAL, D.METHOD_ID, D.PLAN_METHOD_ID, D.ATTEMPTS, D.OWNER_ID, D.H_LEVEL, D.ORG_REF, D.OBJ_NAME,
    D.FLOW_MODE, D.PAUSE_ENABLED, D.BLANK_AB_ID, D.BLANK_C_ID, D.BLANK_EXT_ID, D.BLANK_GEN_ID, D.EXPERT_ASSN_MODE,
    D.SCALE_N0, D.SCALE_NMIN, D.SCALE_N4, D.SCALE_N5, D.SCALE_NMAX, D.PPE_ID, D.RESULTS_ALW, D.HINT_MODE
  FROM UT_EXAM_DATES D
  WHERE D.DATE_DEL IS NULL AND D.OBJ_ID = :I$OBJ_ID
  INTO :SUBJECT_ID, :STAGE_ID, :EXAM_DATE_START, :EXAM_DATE_END, :DURATION, :EXAM_DAY_TYPE, :EXAM_STATE, :C_CALC_MODE, :C_EXPERT_NUM,
    :C_DIFF_QUESTION, :C_DIFF_TOTAL, :METHOD_ID, :PLAN_METHOD_ID, :ATTEMPTS, :OWNER_ID, :H_LEVEL, :ORG_REF, :OBJ_NAME,
    :FLOW_MODE, :PAUSE_ENABLED, :V$BLANK_AB_ID, :V$BLANK_C_ID, :V$BLANK_EXT_ID, :V$BLANK_GEN_ID, :V$EXPERT_ASSN_MODE,
    :V$N0, :V$NMIN, :V$N4, :V$N5, :V$NMAX, :PPE_ID, :V$RESULTS_ALW, :V$HINT_MODE;

  -- Сначала дискретные поля
  TAG_NAME = 'obj_name';
  VAL = OBJ_NAME;
  SUSPEND;

  TAG_NAME = 'exam_date_start';
  VAL = (SELECT VAL FROM DATE2ISO(:EXAM_DATE_START, 0));
  SUSPEND;

  TAG_NAME = 'exam_date_end';
  VAL = (SELECT VAL FROM DATE2ISO(:EXAM_DATE_END, 0));
  SUSPEND;

  TAG_NAME = 'duration';
  VAL = DURATION;
  SUSPEND;

  TAG_NAME = 'c_diff_question';
  VAL = C_DIFF_QUESTION;
  SUSPEND;

  TAG_NAME = 'c_diff_total';
  VAL = C_DIFF_TOTAL;
  SUSPEND;

  TAG_NAME = 'attempts';
  VAL = ATTEMPTS;
  SUSPEND;

  TAG_NAME = 'owner_id';
  VAL = OWNER_ID;
  SUSPEND;

  TAG_NAME = 'h_level';
  VAL = H_LEVEL;
  SUSPEND;

  TAG_NAME = 'org_ref';
  VAL = ORG_REF;
  SUSPEND;

  TAG_NAME = 'org_ref_name';
  VAL = NULL;
  IF(H_LEVEL = 2) THEN VAL = 'Регион+';
  ELSE IF(H_LEVEL = 1) THEN
  BEGIN
    SELECT R.VAL
    FROM LISTVALS LV
    JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
    WHERE LV.LISTVAL_ID = :ORG_REF
    INTO :VAL;
  END
  ELSE
  BEGIN
    SELECT CAPTION
    FROM OBJECT_CAPTION_GET(:ORG_REF)
    INTO :VAL;
  END
  SUSPEND;

  -- на уровне ОУ выгружаем ее айдишник => в app.test_plan выбираем сразу сами себя
  TAG_NAME = 'school_ref_id';
  VAL = '';
  IF (H_LEVEL IS NULL) THEN
  BEGIN 
    SELECT L2.OBJ_ID
    FROM LINKS L2
    LEFT JOIN OBJECT_CAPTION_GET(L2.OBJ_ID) C ON 1 = 1
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :VAL;
  END
  SUSPEND;

  TAG_NAME = 'pause_enabled';
  VAL = PAUSE_ENABLED;
  SUSPEND;

  -- Уровень доступа текущего пользователя, равен уровню базы (0 = ОУ, ...)
  TAG_NAME = 'user_level';
  SELECT COALESCE(CAST(K.KEY_VAL AS INTEGER) - 1, 0)
  FROM KEYS K
  WHERE K.KEY_CODE = 'LEVEL'
  INTO :V$DB_LEVEL;
  VAL = V$DB_LEVEL;
  SUSPEND;

  -- Получаем наш домашний уровень (ОУ, район, регион), и его название
  TAG_NAME = 'level_name';
  VAL = NULL;
  IF(V$DB_LEVEL = 0) THEN
  BEGIN
    SELECT FIRST 1 L2.OBJ_ID, V2.VAL
    FROM LINKS L2
    LEFT JOIN VALS V2 ON V2.OBJ_ID = L2.OBJ_ID AND V2.PARAM_ID = 2 AND V2.IS_DEL = 0
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :V$OUR_ORG, :VAL;
  END
  ELSE IF(V$DB_LEVEL = 1) THEN
  BEGIN
    SELECT FIRST 1 V665.LISTVAL_ID, R.VAL
    FROM LINKS L111
    JOIN VALL V665 ON V665.OBJ_ID = L111.OBJ_ID AND V665.PARAM_ID = 665 AND V665.IS_DEL = 0
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V665.LISTVAL_ID
    JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
    WHERE L111.PARENT_ID IS NULL AND L111.OBJ_TYPE_ID = 111 AND L111.DATE_DEL IS NULL
    INTO :V$OUR_ORG, :VAL;
  END
  ELSE IF(V$DB_LEVEL = 2) THEN
  BEGIN
    VAL = 'Регион';
  END
  SUSPEND;

  -- Битовая маска прав доступа - только в режиме редактирования
  -- Бит 0 - можно ли редактировать поля самого тестирования и варианты
  -- Бит 1 - можно ли создавать новые КИМ или варианты (расширение бита 0, будет дополнительно проверяться что сам тест не R/O) - пока не используется
  -- Бит 2 - можно ли редактировать участников тестирования непосредственно в данном диалоге (только для уровня ОУ, когда тестирование свое собственное)
  -- Бит 3 - может ли редактировать состав экспертов (только в пределах своей области видимости)
  -- ??? Для классных руководителей - даем доступ только чтение
  -- Бит 4 - можно ли раскрывать поля экспертов, назначений ОУ, и формировать отчеты
  V$MATCH_ORG = 0;
  IF(V$DB_LEVEL = 2) THEN V$MATCH_ORG = 1;
  ELSE IF(V$DB_LEVEL = 1 AND H_LEVEL <= 1) THEN V$MATCH_ORG = 1;
  ELSE IF(V$DB_LEVEL = 0 AND H_LEVEL = 0 AND ORG_REF = V$OUR_ORG) THEN V$MATCH_ORG = 1;

  TAG_NAME = 'allowed';
  V$ACCESS = 0;
  IF(V$MATCH_ORG = 1) THEN V$ACCESS = BIN_OR(V$ACCESS, 1);
  -- V$ACCESS = BIN_OR(V$ACCESS, 2);
  IF(H_LEVEL = 0 AND V$MATCH_ORG = 1) THEN V$ACCESS = BIN_OR(V$ACCESS, 4);
  IF((V$DB_LEVEL = 0 AND V$EXPERT_ASSN_MODE = 1) OR (V$DB_LEVEL = H_LEVEL AND V$EXPERT_ASSN_MODE = 0)) THEN V$ACCESS = BIN_OR(V$ACCESS, 8);
  IF(V$MATCH_ORG = 1 OR
      EXISTS (
          -- наша ОУ в числе допустимых, или все ОУ
          SELECT FIRST 1 1
          FROM UT_EXAM_OU_ASSN EA
          WHERE EA.EXAM_ID = :I$OBJ_ID AND EA.DATE_DEL IS NULL AND (EA.OU_ID = 0 OR EA.OU_ID = :V$OUR_ORG)
      ) OR EXISTS (
          -- ОУ из нашего района
          SELECT FIRST 1 1
          FROM UT_EXAM_OU_ASSN EA
          JOIN LINKS LPR ON LPR.OBJ_ID = EA.OU_ID AND LPR.PARENT_TYPE_ID = 111 AND LPR.DATE_DEL IS NULL
          JOIN LINKS LM ON LM.OBJ_ID = LPR.PARENT_ID AND LM.PARENT_ID IS NULL AND LM.DATE_DEL IS NULL
          WHERE EA.EXAM_ID = :I$OBJ_ID AND EA.DATE_DEL IS NULL
      )
  ) THEN V$ACCESS = BIN_OR(V$ACCESS, 16);
  VAL = V$ACCESS;
  SUSPEND;

  -- Поля-списки
  -- SUBJECT_ID
  TAG_NAME = 'subject_id';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'subject_id:selection';
  VAL = NULL;
  SUSPEND;
  FOR
    SELECT OBJ_ID, OBJ_NAME, TYPE_ID
    FROM UT_SUBJECTS
    UNION
    SELECT NULL, 'Метапредмет', 51
    FROM RDB$DATABASE
    ORDER BY 2
    INTO :V$ID, :V$S, :V$T
  DO
  BEGIN
    TAG_NAME = 'subject_id:selection:option';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'subject_id:selection:option:id';
    IF(V$ID IS NULL) THEN VAL = '*'; ELSE VAL = V$ID;
    SUSPEND;
    TAG_NAME = 'subject_id:selection:option:subtype_id';
    VAL = V$T;
    SUSPEND;
    TAG_NAME = 'subject_id:selection:option:value';
    VAL = V$S;
    SUSPEND;
  END
  TAG_NAME = 'subject_id:values:value';
  IF(SUBJECT_ID IS NULL) THEN VAL = '*'; ELSE VAL = SUBJECT_ID;
  SUSPEND;

  -- EXAM_STATE
  TAG_NAME = 'stage_id';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'stage_id:selection';
  VAL = NULL;
  SUSPEND;
  FOR
    SELECT OBJ_ID, OBJ_NAME
    FROM UT_EXAM_STAGES
    WHERE (:V$HAS_OU = 1 AND (OBJ_ID <= 40 OR OBJ_ID >= 100)) OR (:V$HAS_SPO = 1 AND OBJ_ID >= 20)
    ORDER BY SORT_INDEX, 2
    INTO :V$ID, :V$S
  DO
  BEGIN
    TAG_NAME = 'stage_id:selection:option';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'stage_id:selection:option:id';
    VAL = V$ID;
    SUSPEND;
    TAG_NAME = 'stage_id:selection:option:value';
    VAL = V$S;
    SUSPEND;
  END
  TAG_NAME = 'stage_id:values:value';
  VAL = STAGE_ID;
  SUSPEND;

  -- EXAM_STATE
  TAG_NAME = 'exam_state';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'exam_state:selection';
  VAL = NULL;
  SUSPEND;
  FOR
    SELECT OBJ_ID, OBJ_NAME
    FROM UT_EXAM_STATES
    ORDER BY 1, 2
    INTO :V$ID, :V$S
  DO
  BEGIN
    TAG_NAME = 'exam_state:selection:option';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'exam_state:selection:option:id';
    VAL = V$ID;
    SUSPEND;
    TAG_NAME = 'exam_state:selection:option:value';
    VAL = V$S;
    SUSPEND;
  END
  TAG_NAME = 'exam_state:values:value';
  VAL = EXAM_STATE;
  SUSPEND;

  -- METHOD_ID
  TAG_NAME = 'method_id';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'method_id:selection';
  VAL = NULL;
  SUSPEND;
  FOR
    SELECT OBJ_ID, OBJ_NAME
    FROM UT_EXAM_METHODS
    ORDER BY 1, 2
    INTO :V$ID, :V$S
  DO
  BEGIN
    TAG_NAME = 'method_id:selection:option';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'method_id:selection:option:id';
    VAL = V$ID;
    SUSPEND;
    TAG_NAME = 'method_id:selection:option:value';
    VAL = V$S;
    SUSPEND;
  END
  TAG_NAME = 'method_id:values:value';
  VAL = METHOD_ID;
  SUSPEND;

  -- PLAN_METHOD_ID
  TAG_NAME = 'plan_method_id';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'plan_method_id:selection';
  VAL = NULL;
  SUSPEND;
  FOR
    SELECT OBJ_ID, OBJ_NAME
    FROM UT_EXAM_PLAN_METHODS
    ORDER BY 1, 2
    INTO :V$ID, :V$S
  DO
  BEGIN
    TAG_NAME = 'plan_method_id:selection:option';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'plan_method_id:selection:option:id';
    VAL = V$ID;
    SUSPEND;
    TAG_NAME = 'plan_method_id:selection:option:value';
    VAL = V$S;
    SUSPEND;
  END
  TAG_NAME = 'plan_method_id:values:value';
  VAL = PLAN_METHOD_ID;
  SUSPEND;

  -- C_CALC_MODE
  TAG_NAME = 'c_calc_mode';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'c_calc_mode:selection';
  VAL = NULL;
  SUSPEND;
  FOR
    SELECT OBJ_ID, OBJ_NAME
    FROM UT_EXPERT_CALC_MODES
    ORDER BY 1, 2
    INTO :V$ID, :V$S
  DO
  BEGIN
    TAG_NAME = 'c_calc_mode:selection:option';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'c_calc_mode:selection:option:id';
    VAL = V$ID;
    SUSPEND;
    TAG_NAME = 'c_calc_mode:selection:option:value';
    VAL = V$S;
    SUSPEND;
  END
  TAG_NAME = 'c_calc_mode:values:value';
  VAL = C_CALC_MODE;
  SUSPEND;

  -- EXAM_DAY_TYPE
  TAG_NAME = 'exam_day_type';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'exam_day_type:selection';
  VAL = NULL;
  SUSPEND;
  FOR
    SELECT OBJ_ID, OBJ_NAME
    FROM UT_EXAM_DAY_TYPES
    ORDER BY 1, 2
    INTO :V$ID, :V$S
  DO
  BEGIN
    TAG_NAME = 'exam_day_type:selection:option';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'exam_day_type:selection:option:id';
    VAL = V$ID;
    SUSPEND;
    TAG_NAME = 'exam_day_type:selection:option:value';
    VAL = V$S;
    SUSPEND;
  END
  TAG_NAME = 'exam_day_type:values:value';
  VAL = EXAM_DAY_TYPE;
  SUSPEND;

  -- Число экспертов от 1 до 3
  TAG_NAME = 'c_expert_num';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'c_expert_num:selection';
  VAL = NULL;
  SUSPEND;
      TAG_NAME = 'c_expert_num:selection:option';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'c_expert_num:selection:option:id';
      VAL = '1';
      SUSPEND;
      TAG_NAME = 'c_expert_num:selection:option:value';
      VAL = '1';
      SUSPEND;
      TAG_NAME = 'c_expert_num:selection:option';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'c_expert_num:selection:option:id';
      VAL = '2';
      SUSPEND;
      TAG_NAME = 'c_expert_num:selection:option:value';
      VAL = '2';
      SUSPEND;
      TAG_NAME = 'c_expert_num:selection:option';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'c_expert_num:selection:option:id';
      VAL = '3';
      SUSPEND;
      TAG_NAME = 'c_expert_num:selection:option:value';
      VAL = '3';
      SUSPEND;
  TAG_NAME = 'c_expert_num:values:value';
  VAL = C_EXPERT_NUM;
  SUSPEND;

  -- Режим отображения
  TAG_NAME = 'flow_mode';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'flow_mode:selection';
  VAL = NULL;
  SUSPEND;
      TAG_NAME = 'flow_mode:selection:option';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'flow_mode:selection:option:id';
      VAL = '0';
      SUSPEND;
      TAG_NAME = 'flow_mode:selection:option:value';
      VAL = 'По одному вопросу, без навигации и возможности возврата';
      SUSPEND;
      TAG_NAME = 'flow_mode:selection:option';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'flow_mode:selection:option:id';
      VAL = '1';
      SUSPEND;
      TAG_NAME = 'flow_mode:selection:option:value';
      VAL = 'По одному вопросу, с навигацией и возможностью возврата';
      SUSPEND;
      TAG_NAME = 'flow_mode:selection:option';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'flow_mode:selection:option:id';
      VAL = '2';
      SUSPEND;
      TAG_NAME = 'flow_mode:selection:option:value';
      VAL = 'Сразу весь список вопросов';
      SUSPEND;
  TAG_NAME = 'flow_mode:values:value';
  VAL = COALESCE(FLOW_MODE, 1);
  SUSPEND;

  -- Назначения бланков
  TAG_NAME = 'blank_ab_id';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'blank_ab_id:selection';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'blank_ab_id:selection::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT OBJ_ID, OBJ_NAME, IS_ACTIVE
    FROM UT_PAGE_TEMPLATES
    WHERE BLANK_TYPE IN (0, 1) AND DATE_DEL IS NULL
    ORDER BY IS_ACTIVE DESC, 2
    INTO :V$ID, :V$S, :V$ACTIVE
  DO
  BEGIN
    TAG_NAME = 'blank_ab_id:selection:option';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'blank_ab_id:selection:option:id';
    VAL = V$ID;
    SUSPEND;
    TAG_NAME = 'blank_ab_id:selection:option:value';
    VAL = V$S;
    SUSPEND;
    TAG_NAME = 'blank_ab_id:selection:option:active';
    VAL = V$ACTIVE;
    SUSPEND;
  END
  TAG_NAME = 'blank_ab_id:values:value';
  VAL = V$BLANK_AB_ID;
  SUSPEND;

  TAG_NAME = 'blank_c_id';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'blank_c_id:selection';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'blank_c_id:selection::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT OBJ_ID, OBJ_NAME, IS_ACTIVE
    FROM UT_PAGE_TEMPLATES
    WHERE BLANK_TYPE IN (0, 2) AND DATE_DEL IS NULL
    ORDER BY IS_ACTIVE DESC, 2
    INTO :V$ID, :V$S, :V$ACTIVE
  DO
  BEGIN
    TAG_NAME = 'blank_c_id:selection:option';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'blank_c_id:selection:option:id';
    VAL = V$ID;
    SUSPEND;
    TAG_NAME = 'blank_c_id:selection:option:value';
    VAL = V$S;
    SUSPEND;
    TAG_NAME = 'blank_c_id:selection:option:active';
    VAL = V$ACTIVE;
    SUSPEND;
  END
  TAG_NAME = 'blank_c_id:values:value';
  VAL = V$BLANK_C_ID;
  SUSPEND;

  TAG_NAME = 'blank_ext_id';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'blank_ext_id:selection';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'blank_ext_id:selection::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT OBJ_ID, OBJ_NAME, IS_ACTIVE
    FROM UT_PAGE_TEMPLATES
    WHERE BLANK_TYPE IN (0, 3) AND DATE_DEL IS NULL
    ORDER BY IS_ACTIVE DESC, 2
    INTO :V$ID, :V$S, :V$ACTIVE
  DO
  BEGIN
    TAG_NAME = 'blank_ext_id:selection:option';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'blank_ext_id:selection:option:id';
    VAL = V$ID;
    SUSPEND;
    TAG_NAME = 'blank_ext_id:selection:option:value';
    VAL = V$S;
    SUSPEND;
    TAG_NAME = 'blank_ext_id:selection:option:active';
    VAL = V$ACTIVE;
    SUSPEND;
  END
  TAG_NAME = 'blank_ext_id:values:value';
  VAL = V$BLANK_EXT_ID;
  SUSPEND;

  TAG_NAME = 'blank_gen_id';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'blank_gen_id:selection';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'blank_gen_id:selection::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT OBJ_ID, OBJ_NAME, IS_ACTIVE
    FROM UT_PAGE_TEMPLATES
    WHERE BLANK_TYPE IN (0, 4) AND DATE_DEL IS NULL
    ORDER BY IS_ACTIVE DESC, 2
    INTO :V$ID, :V$S, :V$ACTIVE
  DO
  BEGIN
    TAG_NAME = 'blank_gen_id:selection:option';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'blank_gen_id:selection:option:id';
    VAL = V$ID;
    SUSPEND;
    TAG_NAME = 'blank_gen_id:selection:option:value';
    VAL = V$S;
    SUSPEND;
    TAG_NAME = 'blank_gen_id:selection:option:active';
    VAL = V$ACTIVE;
    SUSPEND;
  END
  TAG_NAME = 'blank_gen_id:values:value';
  VAL = V$BLANK_GEN_ID;
  SUSPEND;

  -- Поля-списки
  -- EXPERT_ASSN_MODE - выбор уровня ОУ показываем только для тестирований выше уровня ОУ
  TAG_NAME = 'expert_assn_mode';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'expert_assn_mode:selection';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'expert_assn_mode:selection::json&colon;array';
  VAL = '1';
  SUSPEND;
  TAG_NAME = 'expert_assn_mode:selection:option';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'expert_assn_mode:selection:option:id';
  VAL = 0;
  SUSPEND;
  TAG_NAME = 'expert_assn_mode:selection:option:value';
  VAL = 'На уровне, где создано тестирование';
  SUSPEND;
  IF(H_LEVEL IS NULL OR H_LEVEL > 0) THEN
  BEGIN
      TAG_NAME = 'expert_assn_mode:selection:option';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'expert_assn_mode:selection:option:id';
      VAL = 1;
      SUSPEND;
      TAG_NAME = 'expert_assn_mode:selection:option:value';
      VAL = 'На уровне ОУ';
      SUSPEND;
  END
  TAG_NAME = 'expert_assn_mode:values:value';
  VAL = V$EXPERT_ASSN_MODE;
  SUSPEND;

  TAG_NAME = 'results_alw:selection::json&colon;array';
  VAL = '1';
  SUSPEND;
  TAG_NAME = 'results_alw:selection:option';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'results_alw:selection:option:id';
  VAL = 0;
  SUSPEND;
  TAG_NAME = 'results_alw:selection:option:value';
  VAL = 'После завершения тестирования';
  SUSPEND;
  TAG_NAME = 'results_alw:selection:option';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'results_alw:selection:option:id';
  VAL = 1;
  SUSPEND;
  TAG_NAME = 'results_alw:selection:option:value';
  VAL = 'Никогда не показывать';
  SUSPEND;
  TAG_NAME = 'results_alw:selection:option';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'results_alw:selection:option:id';
  VAL = 2;
  SUSPEND;
  TAG_NAME = 'results_alw:selection:option:value';
  VAL = 'Показывать всегда';
  SUSPEND;
  TAG_NAME = 'results_alw:values:value';
  VAL = V$RESULTS_ALW;
  SUSPEND;

  TAG_NAME = 'hint_mode:selection::json&colon;array';
  VAL = '1';
  SUSPEND;
  TAG_NAME = 'hint_mode:selection:option';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'hint_mode:selection:option:id';
  VAL = 0;
  SUSPEND;
  TAG_NAME = 'hint_mode:selection:option:value';
  VAL = 'Не показывать';
  SUSPEND;
  TAG_NAME = 'hint_mode:selection:option';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'hint_mode:selection:option:id';
  VAL = 1;
  SUSPEND;
  TAG_NAME = 'hint_mode:selection:option:value';
  VAL = 'Показывать по запросу';
  SUSPEND;
  TAG_NAME = 'hint_mode:selection:option';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'hint_mode:selection:option:id';
  VAL = 2;
  SUSPEND;
  TAG_NAME = 'hint_mode:selection:option:value';
  VAL = 'Показывать сразу';
  SUSPEND;
  TAG_NAME = 'hint_mode:values:value';
  VAL = V$HINT_MODE;
  SUSPEND;

  -- Шкалы показываем только если уровень базы = уровню тестирования
  IF(V$DB_LEVEL = H_LEVEL AND EXAM_DAY_TYPE <> 100) THEN
  BEGIN
      TAG_NAME = 'scale_n0';
      VAL = V$N0;
      SUSPEND;
      TAG_NAME = 'scale_nmin';
      VAL = V$NMIN;
      SUSPEND;
      TAG_NAME = 'scale_n4';
      VAL = V$N4;
      SUSPEND;
      TAG_NAME = 'scale_n5';
      VAL = V$N5;
      SUSPEND;
      TAG_NAME = 'scale_nmax';
      VAL = V$NMAX;
      SUSPEND;
  END

  -- Списки вариантов тестирования - отдаем только если положено по уровню доступа
  TAG_NAME = 'variants';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'variants::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
      SELECT T.OBJ_ID, T.OBJ_NAME, TV.OBJ_ID, TV.OBJ_NAME, TV.NUM
      FROM UT_EXAM_TEST_VARS ETV
      JOIN UT_TEST_VARS TV ON TV.OBJ_ID = ETV.TEST_VAR_ID AND TV.DATE_DEL IS NULL
      JOIN UT_TESTS T ON T.OBJ_ID = TV.TEST_ID AND T.DATE_DEL IS NULL
      WHERE ETV.EXAM_ID = :I$OBJ_ID AND ETV.DATE_DEL IS NULL
      INTO :V$KIM_ID, :V$KIM_NAME, :V$TV_ID, :V$TV_NAME, :V$TV_NUM
  DO
  BEGIN
      TAG_NAME = 'variants:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'variants:r:id';
      VAL = V$TV_ID;
      SUSPEND;
      TAG_NAME = 'variants:r:name';
      VAL = V$TV_NAME;
      SUSPEND;
      TAG_NAME = 'variants:r:num';
      VAL = V$TV_NUM;
      SUSPEND;
      TAG_NAME = 'variants:r:kim_id';
      VAL = V$KIM_ID;
      SUSPEND;
      TAG_NAME = 'variants:r:kim_name';
      VAL = V$KIM_NAME;
      SUSPEND;

      -- Файлы
      TAG_NAME = 'variants:r:files';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'variants:r:files::json&colon;array';
      VAL = NULL;
      SUSPEND;
      FOR
          SELECT F.OBJ_ID, F.OBJ_NAME, F.CONTENT_TYPE, CHAR_LENGTH(F.CONTENT_DATA), F.ATTR_MASK, F.FILE_HASH
          FROM UT_TEST_VAR_FILES F
          WHERE F.DATE_DEL IS NULL AND F.VAR_ID = :V$TV_ID
          INTO :V$FILE_ID, :V$KIM_NAME, :OBJ_NAME, :V$NMAX, :V$NMIN, :V$S
      DO
      BEGIN
          TAG_NAME = 'variants:r:files:r';
          VAL = NULL;
          SUSPEND;
          TAG_NAME = 'variants:r:files:r:id';
          VAL = V$FILE_ID;
          SUSPEND;
          TAG_NAME = 'variants:r:files:r:name';
          VAL = V$KIM_NAME;
          SUSPEND;
          TAG_NAME = 'variants:r:files:r:hash';
          VAL = V$S;
          SUSPEND;
          TAG_NAME = 'variants:r:files:r:type';
          VAL = OBJ_NAME;
          SUSPEND;
          TAG_NAME = 'variants:r:files:r:mask';
          VAL = V$NMIN;
          SUSPEND;
          TAG_NAME = 'variants:r:files:r:size';
          VAL = V$NMAX;
          SUSPEND;
      END
  END

  -- Списки экспертов - отдаем только если положено по уровню доступа (т.е. есть право изменения)
  -- Экспертов отдаем только список, относящийся к конкретной ОУ. Если уровень тестирования выше 1, персон показываем только на уровне ОУ
  N = 0;
  SELECT COUNT(*)
  FROM UT_EXAM_EXPERT_ASSN U
  JOIN UT_EXPERTS E ON E.EXPERT_ID = U.EXPERT_ID AND E.DATE_DEL IS NULL
  WHERE U.EXAM_ID = :I$OBJ_ID AND U.DATE_DEL IS NULL
  INTO :N;
  TAG_NAME = 'n_experts';
  VAL = N;
  SUSPEND;

  TAG_NAME = 'experts';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'experts::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
      SELECT U.EXPERT_ID, CT.NAME_FULL, U.ROLE_ID, U.SECOND_CHECK
      FROM UT_EXAM_EXPERT_ASSN U
      JOIN UT_EXPERTS E ON E.EXPERT_ID = U.EXPERT_ID AND E.DATE_DEL IS NULL
      LEFT JOIN UT_EXPERT_DESC(E.EXPERT_ID) CT ON 1 = 1
      WHERE U.EXAM_ID = :I$OBJ_ID AND U.DATE_DEL IS NULL AND BIN_AND(:V$ACCESS, 8) <> 0
          AND ((:V$EXPERT_ASSN_MODE = 0 AND :V$DB_LEVEL = :H_LEVEL) OR ((:V$EXPERT_ASSN_MODE = 1 OR :H_LEVEL = 0) AND :V$DB_LEVEL = 0 AND E.ORG_ID = :V$OUR_ORG))
          AND (:V$DB_LEVEL = 0 OR :H_LEVEL = 0)
      INTO :V$ID, :V$S, :V$T, :V$SC
  DO
  BEGIN
      TAG_NAME = 'experts:m';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'experts:m:id';
      VAL = V$ID;
      SUSPEND;
      TAG_NAME = 'experts:m:name';
      VAL = V$S;
      SUSPEND;
      TAG_NAME = 'experts:m:role';
      VAL = V$T;
      SUSPEND;
      TAG_NAME = 'experts:m:is_sc';
      VAL = V$SC;
      SUSPEND;
  END

  -- Списки участников, отдаем только для тестирования уровня ОУ, при наличии доступа. В остальных случаях отдаем только количество
  N = 0;
  SELECT COUNT(*)
  FROM UT_EXAM_PERSON_ASSN
  WHERE DATE_DEL IS NULL AND EXAM_ID = :I$OBJ_ID
  INTO :N;
  TAG_NAME = 'n_members';
  VAL = N;
  SUSPEND;

  TAG_NAME = 'members';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'members::json&colon;array';
  VAL = '1';
  SUSPEND;

  FOR
      SELECT A.PERSON_ID, O.TYPE_ID, C.NAME_FULL
      FROM UT_EXAM_PERSON_ASSN A
      JOIN OBJECTS O ON O.OBJ_ID = A.PERSON_ID
      LEFT JOIN UT_PERSON_DESC(O.OBJ_ID) C ON 1 = 1
      WHERE A.EXAM_ID = :I$OBJ_ID AND A.DATE_DEL IS NULL AND :H_LEVEL = 0
      ORDER BY 2, 3
      INTO :V$ID, :V$T, :V$S
  DO
  BEGIN
      TAG_NAME = 'members:m';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'members:m:type';
      VAL = V$T;
      SUSPEND;
      TAG_NAME = 'members:m:id';
      VAL = V$ID;
      SUSPEND;
      TAG_NAME = 'members:m:name';
      VAL = V$S;
      SUSPEND;
  END

  -- Список назначений ОУ. Если количество строк менее 50 - отдаем весь список. Если более, отдаем только общее количество, и подгружаем потом
  -- Для уровня ОУ отдаем только самого себя
  N = 0;
  SELECT COUNT(*)
  FROM UT_EXAM_OU_ASSN A
  WHERE A.DATE_DEL IS NULL AND A.EXAM_ID = :I$OBJ_ID
  INTO :N;
  TAG_NAME = 'n_ou_assn';
  VAL = N;
  SUSPEND;

  N = 0;
  SELECT FIRST 1 1
  FROM UT_EXAM_OU_ASSN A
  WHERE A.DATE_DEL IS NULL AND A.EXAM_ID = :I$OBJ_ID AND A.OU_ID = 0
  INTO :N;
  TAG_NAME = 'n_ou_assn_all';
  VAL = N;
  SUSPEND;

  TAG_NAME = 'ou_assn';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'ou_assn::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
      SELECT EA.OU_ID, EA.DATE_START, EA.DATE_END, D.NAME_SHORT
      FROM UT_EXAM_OU_ASSN EA
      JOIN OBJECTS ORG ON ORG.OBJ_ID = EA.OU_ID
      LEFT JOIN UT_OU_DESC(ORG.OBJ_ID, 1) D ON 1 = 1
      WHERE EA.DATE_DEL IS NULL AND EA.EXAM_ID = :I$OBJ_ID AND (:N <= 50 OR :ORG_REF = :V$OUR_ORG)
      INTO :V$OU_ID, :V$D1, :V$D2, :V$S
  DO
  BEGIN
      TAG_NAME = 'ou_assn:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'ou_assn:r:id';
      VAL = V$OU_ID;
      SUSPEND;
      TAG_NAME = 'ou_assn:r:name';
      VAL = V$S;
      SUSPEND;
  END

  -- Список ППЭ для выбора
  TAG_NAME = 'ppe_id';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'ppe_id:selection::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
      SELECT L2.OBJ_ID, V2.SVAL
      FROM LINKS L2
      JOIN VALS V2 ON V2.OBJ_ID = L2.OBJ_ID AND V2.PARAM_ID = 2 AND V2.IS_DEL = 0
      WHERE :V$OU_LICENCE_TYPE = 'C' AND (L2.PARENT_ID IS NULL OR L2.PARENT_TYPE_ID IN (111, 112)) AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      ORDER BY 2
      INTO :V$ID, :V$S
  DO
  BEGIN
      TAG_NAME = 'ppe_id:selection:option';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'ppe_id:selection:option:id';
      VAL = V$ID;
      SUSPEND;
      TAG_NAME = 'ppe_id:selection:option:value';
      VAL = V$S;
      SUSPEND;
  END
  TAG_NAME = 'ppe_id:values:value';
  VAL = PPE_ID;
  SUSPEND;

  TAG_NAME = 'resources';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'resources::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
    SELECT RA.OBJ_ID, R.VAL, VN.VAL, RA.QTY, RA.RES_ID
    FROM UT_EXAM_RES_ASSN RA
    JOIN OBJECTS OBJ ON OBJ.OBJ_ID = RA.RES_ID
    JOIN TYPES T ON T.TYPE_ID = OBJ.TYPE_ID
    JOIN RES R ON R.RES_ID = T.RES_ID AND R.LANG_CODE = 'RU'
    LEFT JOIN VALS VN ON VN.OBJ_ID = OBJ.OBJ_ID AND VN.PARAM_ID IN (408, 627, 606, 639, 647) AND VN.IS_DEL = 0
    WHERE RA.DATE_DEL IS NULL AND RA.EXAM_ID = :I$OBJ_ID
    INTO :V$ID, :OBJ_NAME, :V$S, :V$N0, :V$BLANK_AB_ID
  DO
  BEGIN
    TAG_NAME = 'resources:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'resources:r:id';
    VAL = V$ID;
    SUSPEND;
    TAG_NAME = 'resources:r:res_id';
    VAL = V$BLANK_AB_ID;
    SUSPEND;
    TAG_NAME = 'resources:r:type';
    VAL = OBJ_NAME;
    SUSPEND;
    TAG_NAME = 'resources:r:name';
    VAL = V$S;
    SUSPEND;
    TAG_NAME = 'resources:r:qty';
    VAL = V$N0;
    SUSPEND;
  END

  -- Данные по прямым вопросам
  TAG_NAME = 'n_variants';
  SELECT COUNT(DISTINCT Q.VARIANT_INDEX)
  FROM UT_EXAM_QUESTIONS Q
  WHERE Q.EXAM_ID = :I$OBJ_ID AND Q.DATE_DEL IS NULL
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'n_questions';
  SELECT COUNT(*)
  FROM UT_EXAM_QUESTIONS Q
  WHERE Q.EXAM_ID = :I$OBJ_ID AND Q.DATE_DEL IS NULL
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'n_per_var';
  SELECT COUNT(DISTINCT Q.SORT_INDEX)
  FROM UT_EXAM_QUESTIONS Q
  WHERE Q.EXAM_ID = :I$OBJ_ID AND Q.DATE_DEL IS NULL
  INTO :VAL;
  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_EPLAN_GETCODES (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
declare variable V$STATE integer;
declare variable V$LEVEL integer;
declare variable V$ORG_REF bigint;
declare variable V$OUR_ORG bigint;
declare variable V$DATE1 date;
declare variable V$DATE2 date;
declare variable V$DB_LEVEL integer;
declare variable V$AREA_ID bigint;
declare variable V$OBJ_ID bigint;
declare variable V$TITLE varchar(1000);
declare variable V$TYPE varchar(10);
declare variable V$IS_ALL smallint;
declare variable V$TMP bigint;
declare variable V$CODE varchar(40);
begin

  TAG_NAME = 'data';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'data::json&colon;array';
  VAL = 1;
  SUSPEND;

  SELECT D.EXAM_STATE, D.EXAM_DATE_START, D.EXAM_DATE_END, D.H_LEVEL, D.ORG_REF
  FROM UT_EXAM_DATES D
  WHERE D.OBJ_ID = :I$OBJ_ID AND D.DATE_DEL IS NULL
  INTO :V$STATE, :V$DATE1, :V$DATE2, :V$LEVEL, :V$ORG_REF;

  -- Коды можно получать только в статусе от готовности и до сбора материалов
  IF(V$STATE IS NULL) THEN EXCEPTION DATA_ERROR 'Тестирование не найдено или было удалено';
  IF(V$STATE NOT IN (550, 600, 700, 800)) THEN EXCEPTION DATA_ERROR 'Статус тестирования не позволяет сформировать коды активации';

  -- Какой у нас уровень у базы ?
  SELECT COALESCE(CAST(K.KEY_VAL AS INTEGER) - 1, 0)
  FROM KEYS K
  WHERE K.KEY_CODE = 'LEVEL'
  INTO :V$DB_LEVEL;

  V$IS_ALL = 0;
  SELECT FIRST 1 1
  FROM UT_EXAM_OU_ASSN A
  WHERE A.DATE_DEL IS NULL AND A.EXAM_ID = :I$OBJ_ID AND A.OU_ID = 0
  INTO :V$IS_ALL;

  IF(V$DB_LEVEL = 0) THEN EXCEPTION DATA_ERROR 'Формирование кодов активации для уровня ОУ не предусмотрено';
  IF(V$DB_LEVEL > V$LEVEL) THEN EXCEPTION DATA_ERROR 'Коды активации могут быть сформированы только на том же уровне, на котором проводится само тестирование';
  IF(V$LEVEL = 1) THEN V$AREA_ID = V$ORG_REF;

  FOR
      -- ОУ - эта ветка только для тестовых целей, на этом уровне не может генерироваться код
      SELECT L2.OBJ_ID, V2.VAL, 'ou', NULL
      FROM LINKS L2
      JOIN VALS V2 ON V2.OBJ_ID = L2.OBJ_ID AND V2.PARAM_ID = 2 AND V2.IS_DEL = 0
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND :V$DB_LEVEL = 0
      -- Район (сам район не актуален)
      UNION
      SELECT L2.OBJ_ID, V2.VAL, 'ou', NULL
      FROM LINKS L111
      JOIN LINKS L2 ON L2.PARENT_ID = L111.OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      JOIN VALS V2 ON V2.OBJ_ID = L2.OBJ_ID AND V2.PARAM_ID = 2 AND V2.IS_DEL = 0
      LEFT JOIN UT_EXAM_OU_ASSN A ON A.DATE_DEL IS NULL AND A.EXAM_ID = :I$OBJ_ID AND A.OU_ID = L2.OBJ_ID
      WHERE L111.PARENT_ID IS NULL AND L111.OBJ_TYPE_ID = 111 AND L111.DATE_DEL IS NULL AND :V$DB_LEVEL = 1 AND (:V$IS_ALL = 1 OR A.OBJ_ID IS NOT NULL)
      -- Регион - тут выбираем и районы, и ОУ
      UNION
      SELECT V665.LISTVAL_ID, C.CAPTION, 'district', L111.OBJ_ID
      FROM LINKS L112
      JOIN LINKS L111 ON L111.PARENT_ID = L112.OBJ_ID AND L111.OBJ_TYPE_ID = 111 AND L111.DATE_DEL IS NULL
      JOIN VALL V665 ON V665.OBJ_ID = L111.OBJ_ID AND V665.PARAM_ID = 665 AND V665.IS_DEL = 0
      LEFT JOIN OBJECT_CAPTION_GET(L111.OBJ_ID) C ON 1 = 1
      WHERE L112.PARENT_ID IS NULL AND L112.OBJ_TYPE_ID = 112 AND L112.DATE_DEL IS NULL AND :V$DB_LEVEL = 2 AND (
        :V$IS_ALL = 1 OR EXISTS(
            SELECT FIRST 1 1
            FROM LINKS L2
            JOIN UT_EXAM_OU_ASSN A ON A.DATE_DEL IS NULL AND A.EXAM_ID = :I$OBJ_ID AND A.OBJ_ID = L2.OBJ_ID
            WHERE L2.PARENT_ID = L111.OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
        )
      )
      UNION
      SELECT L2.OBJ_ID, V2.VAL, 'ou', L111.OBJ_ID
      FROM LINKS L112
      JOIN LINKS L111 ON L111.PARENT_ID = L112.OBJ_ID AND L111.OBJ_TYPE_ID = 111 AND L111.DATE_DEL IS NULL
      JOIN LINKS L2 ON L2.PARENT_ID = L111.OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      JOIN VALS V2 ON V2.OBJ_ID = L2.OBJ_ID AND V2.PARAM_ID = 2 AND V2.IS_DEL = 0
      LEFT JOIN UT_EXAM_OU_ASSN A ON A.DATE_DEL IS NULL AND A.EXAM_ID = :I$OBJ_ID AND A.OU_ID = L2.OBJ_ID
      WHERE L112.PARENT_ID IS NULL AND L112.OBJ_TYPE_ID = 112 AND L112.DATE_DEL IS NULL AND :V$DB_LEVEL = 2 AND (:V$IS_ALL = 1 OR A.OBJ_ID IS NOT NULL)
      ORDER BY 4, 3, 2
      INTO :V$OBJ_ID, :V$TITLE, :V$TYPE, :V$TMP
  DO
  BEGIN
      TAG_NAME = 'data:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'data:r:row_type';
      VAL = V$TYPE;
      SUSPEND;
      TAG_NAME = 'data:r:title';
      VAL = V$TITLE;
      SUSPEND;

      TAG_NAME = 'data:r:value';
      V$CODE = HASH('ED' || I$OBJ_ID || ':' || V$OBJ_ID);
      VAL = '';

      -- Разбиваем строку дефисами по 3 цифры, причем начиная с хвоста
      WHILE(CHAR_LENGTH(V$CODE) > 0) DO
      BEGIN
          IF(CHAR_LENGTH(V$CODE) >= 3) THEN
          BEGIN
              VAL = SUBSTRING(V$CODE FROM CHAR_LENGTH(V$CODE) - 2) || VAL;
              V$CODE = SUBSTRING(V$CODE FROM 1 FOR CHAR_LENGTH(V$CODE) - 3);
          END
          ELSE
          BEGIN
              VAL = V$CODE || VAL;
              V$CODE = '';
          END

          IF(CHAR_LENGTH(V$CODE) > 0) THEN VAL = '-' || VAL;
      END
      SUSPEND;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_EPLAN_OU_GET (
    I$EXAM_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
declare variable V$OU_ID bigint;
declare variable V$D1 date;
declare variable V$D2 date;
declare variable V$S varchar(1000);
begin

  TAG_NAME = 'data';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'data::json&colon;array';
  VAL = 1;
  SUSPEND;

  FOR
      SELECT EA.OU_ID, EA.DATE_START, EA.DATE_END, D.NAME_SHORT
      FROM UT_EXAM_OU_ASSN EA
      LEFT JOIN UT_OU_DESC(EA.OU_ID, 1) D ON 1 = 1
      WHERE EA.DATE_DEL IS NULL AND EA.EXAM_ID = :I$EXAM_ID
      INTO :V$OU_ID, :V$D1, :V$D2, :V$S
  DO
  BEGIN
      TAG_NAME = 'data:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'data:r:id';
      VAL = V$OU_ID;
      SUSPEND;
      TAG_NAME = 'data:r:name';
      VAL = V$S;
      SUSPEND;
  END


end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_EPLAN_OWNER_LIST (
    I$TYPE INTEGER,
    I$LEVEL INTEGER,
    I$PARENT_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(4000))
AS
declare variable V$BASE_LEVEL integer;
declare variable V$OBJ_ID bigint;
declare variable V$OBJ_NAME varchar(1000);
begin

  -- I$LEVEL - уровень тестирования, для которого выбираем элементы (0 = ОУ, 1 = районы, 2 = город - не используется)
  -- I$TYPE - тип выбираемых объектов, NULL когда выбор первого уровня

  SELECT COALESCE(CAST(K.KEY_VAL AS INTEGER) - 1, 0)
  FROM KEYS K
  WHERE K.KEY_CODE = 'LEVEL'
  INTO :V$BASE_LEVEL;

  -- Начальный выбор уровня
  IF(I$TYPE IS NULL) THEN
  BEGIN
      IF(V$BASE_LEVEL = 0) THEN
      BEGIN
          -- В ОУ - всегда уровень ОУ
          IF(I$LEVEL = 0) THEN I$TYPE = 0;
      END
      ELSE IF(V$BASE_LEVEL = 1) THEN
      BEGIN
          -- В районе выбор или самого района, или ОУ
          IF(I$LEVEL = 0) THEN I$TYPE = 0;
          ELSE IF(I$LEVEL = 1) THEN I$TYPE = 1;
      END
      ELSE IF(V$BASE_LEVEL = 2) THEN
      BEGIN
          I$TYPE = 1;
      END
  END
  IF(I$TYPE IS NULL) THEN EXCEPTION DATA_ERROR 'Нельзя добавить уровень тестирования выше, чем уровень базы';

  TAG_NAME = 'items';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'items::json&colon;array';
  VAL = 1;
  SUSPEND;

  IF(V$BASE_LEVEL = 0) THEN
  BEGIN
      -- ОУ, тут можно выбирать только себя
      IF(I$TYPE = 0) THEN
      BEGIN
          SELECT L2.OBJ_ID, C.CAPTION
          FROM LINKS L2
          LEFT JOIN OBJECT_CAPTION_GET(L2.OBJ_ID) C ON 1 = 1
          WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
          INTO :V$OBJ_ID, :V$OBJ_NAME;

          IF(V$OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не найден объект ОУ, база не настроена';

          TAG_NAME = 'items:r';
          VAL = NULL;
          SUSPEND;
          TAG_NAME = 'items:r:id';
          VAL = V$OBJ_ID;
          SUSPEND;
          TAG_NAME = 'items:r:name';
          VAL = V$OBJ_NAME;
          SUSPEND;
          TAG_NAME = 'items:r:level';
          VAL = 0;
          SUSPEND;
      END
  END
  ELSE IF(V$BASE_LEVEL = 1) THEN
  BEGIN
      -- Район
      IF(I$TYPE = 1) THEN
      BEGIN
          -- Выбор района
          SELECT V665.LISTVAL_ID, R.VAL
          FROM LINKS L111
          JOIN VALL V665 ON V665.OBJ_ID = L111.OBJ_ID AND V665.PARAM_ID = 665 AND V665.IS_DEL = 0
          JOIN LISTVALS LV ON LV.LISTVAL_ID = V665.LISTVAL_ID
          JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
          WHERE L111.PARENT_ID IS NULL AND L111.OBJ_TYPE_ID = 111 AND L111.DATE_DEL IS NULL
          INTO :V$OBJ_ID, :V$OBJ_NAME;

          IF(V$OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не найден объект района, база не настроена';

          TAG_NAME = 'items:r';
          VAL = NULL;
          SUSPEND;
          TAG_NAME = 'items:r:id';
          VAL = V$OBJ_ID;
          SUSPEND;
          TAG_NAME = 'items:r:name';
          VAL = V$OBJ_NAME;
          SUSPEND;
          TAG_NAME = 'items:r:level';
          VAL = 1;
          SUSPEND;
      END
      ELSE IF(I$TYPE = 0) THEN
      BEGIN
          -- Выбор ОУ в районе
          FOR
              SELECT L2.OBJ_ID, C.CAPTION
              FROM LINKS L111
              JOIN LINKS L2 ON L2.PARENT_ID = L111.OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
              LEFT JOIN VALI V17 ON V17.OBJ_ID = L2.OBJ_ID AND V17.PARAM_ID = 17 AND V17.IS_DEL = 0
              LEFT JOIN OBJECT_CAPTION_GET(L2.OBJ_ID) C ON 1 = 1
              WHERE L111.PARENT_ID IS NULL AND L111.OBJ_TYPE_ID = 111 AND L111.DATE_DEL IS NULL
              ORDER BY V17.VAL, C.CAPTION
              INTO :V$OBJ_ID, :V$OBJ_NAME
          DO
          BEGIN
              TAG_NAME = 'items:r';
              VAL = NULL;
              SUSPEND;
              TAG_NAME = 'items:r:id';
              VAL = V$OBJ_ID;
              SUSPEND;
              TAG_NAME = 'items:r:name';
              VAL = V$OBJ_NAME;
              SUSPEND;
              TAG_NAME = 'items:r:level';
              VAL = 0;
              SUSPEND;
          END
      END
  END
  ELSE IF(V$BASE_LEVEL = 2) THEN
  BEGIN
      -- Город, тут можно выбирать как ОУ, так и районы
      IF(I$TYPE = 1) THEN
      BEGIN
          FOR
              SELECT V665.LISTVAL_ID, R.VAL
              FROM LINKS L111
              JOIN VALL V665 ON V665.OBJ_ID = L111.OBJ_ID AND V665.PARAM_ID = 665 AND V665.IS_DEL = 0
              JOIN LISTVALS LV ON LV.LISTVAL_ID = V665.LISTVAL_ID
              JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
              WHERE L111.PARENT_TYPE_ID = 112 AND L111.OBJ_TYPE_ID = 111 AND L111.DATE_DEL IS NULL
              ORDER BY 2
              INTO :V$OBJ_ID, :V$OBJ_NAME
          DO
          BEGIN
              TAG_NAME = 'items:r';
              VAL = NULL;
              SUSPEND;
              TAG_NAME = 'items:r:id';
              VAL = V$OBJ_ID;
              SUSPEND;
              TAG_NAME = 'items:r:name';
              VAL = V$OBJ_NAME;
              SUSPEND;
              TAG_NAME = 'items:r:level';
              VAL = 1;
              SUSPEND;
          END
      END
      ELSE IF(I$TYPE = 0) THEN
      BEGIN
          FOR
              SELECT L2.OBJ_ID, C.CAPTION
              FROM LINKS L112
              JOIN LINKS L111 ON L111.PARENT_ID = L112.OBJ_ID AND L111.OBJ_TYPE_ID = 111 AND L111.DATE_DEL IS NULL
              JOIN VALL V665 ON V665.OBJ_ID = L111.OBJ_ID AND V665.PARAM_ID = 665 AND V665.IS_DEL = 0 AND V665.LISTVAL_ID = :I$PARENT_ID
              JOIN LINKS L2 ON L2.PARENT_ID = L111.OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
              LEFT JOIN VALI V17 ON V17.OBJ_ID = L2.OBJ_ID AND V17.PARAM_ID = 17 AND V17.IS_DEL = 0
              LEFT JOIN OBJECT_CAPTION_GET(L2.OBJ_ID) C ON 1 = 1
              WHERE L112.PARENT_ID IS NULL AND L112.OBJ_TYPE_ID = 112 AND L112.DATE_DEL IS NULL
              ORDER BY V17.VAL, C.CAPTION
              INTO :V$OBJ_ID, :V$OBJ_NAME
          DO
          BEGIN
              TAG_NAME = 'items:r';
              VAL = NULL;
              SUSPEND;
              TAG_NAME = 'items:r:id';
              VAL = V$OBJ_ID;
              SUSPEND;
              TAG_NAME = 'items:r:name';
              VAL = V$OBJ_NAME;
              SUSPEND;
              TAG_NAME = 'items:r:level';
              VAL = 0;
              SUSPEND;
          END
      END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_EPLAN_SETCODE (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40),
    I$CODE VARCHAR(40))
RETURNS (
    STUB INTEGER)
AS
declare variable V$USER_ID bigint;
declare variable V$STATE integer;
declare variable V$DATE1 date;
declare variable V$DATE2 date;
declare variable V$LEVEL integer;
declare variable V$ORG_REF bigint;
declare variable V$OUR_ID bigint;
begin

  IF(I$USER_ID = 'Веб-администратор') THEN V$USER_ID = 0; ELSE V$USER_ID = CAST(I$USER_ID AS BIGINT);

  -- Проверяем статус тестирования
  SELECT D.EXAM_STATE, D.EXAM_DATE_START, D.EXAM_DATE_END, D.H_LEVEL, D.ORG_REF
  FROM UT_EXAM_DATES D
  WHERE D.OBJ_ID = :I$OBJ_ID AND D.DATE_DEL IS NULL
  INTO :V$STATE, :V$DATE1, :V$DATE2, :V$LEVEL, :V$ORG_REF;

  IF(V$STATE IS NULL) THEN EXCEPTION DATA_ERROR 'Тестирование не найдено или было удалено';
  IF(V$STATE < 550) THEN EXCEPTION DATA_ERROR 'Тестирование находится в неподобающем статусе и не может быть активировано';
  --IF(V$STATE >= 600) THEN EXCEPTION DATA_ERROR 'Тестирование уже активировано';

  -- Позволяет ли дата ?
  IF(CURRENT_DATE < DATEADD(-1 DAY TO V$DATE1)) THEN EXCEPTION DATA_ERROR 'Тестирование может быть активировано не ранее, чем за сутки до указанной даты начала';
  IF(CURRENT_DATE > DATEADD(3 DAY TO V$DATE2)) THEN EXCEPTION DATA_ERROR 'Тестирование не может быть активировано после указанной даты окончания';

  -- Получаем id района или ОУ
  SELECT FIRST 1 L2.OBJ_ID
  FROM LINKS L2
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$OUR_ID;

  IF(V$OUR_ID IS NULL) THEN
  BEGIN
      SELECT FIRST 1 V665.LISTVAL_ID
      FROM LINKS L111
      JOIN VALL V665 ON V665.OBJ_ID = L111.OBJ_ID AND V665.PARAM_ID = 665 AND V665.IS_DEL = 0
      WHERE L111.PARENT_ID IS NULL AND L111.OBJ_TYPE_ID = 111 AND L111.DATE_DEL IS NULL
      INTO :V$OUR_ID;
  END

  -- Входит ли данная ОУ в назначения ?
  -- !!!

  -- Проверяем код
  IF(HASH('ED' || I$OBJ_ID || ':' || V$OUR_ID) <> CAST(I$CODE AS BIGINT)) THEN EXCEPTION DATA_ERROR 'Код активации не является валидным';

  -- Обновляем статус тестирования
  UPDATE UT_EXAM_DATES
  SET EXAM_STATE = 600
  WHERE OBJ_ID = :I$OBJ_ID;

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_EXAMS_LIST_REG (
    I$LIC_ID INTEGER,
    I$EXAM_ID BIGINT)
RETURNS (
    EXAM_ID BIGINT,
    DATE_ADD TIMESTAMP,
    DATE_MODIFY TIMESTAMP,
    DATE_DEL TIMESTAMP)
AS
declare variable V$MULT bigint;
begin

  SELECT MULTIPLIER
  FROM GEN
  INTO :V$MULT;

  -- Тестирования, созданные не ранее года назад, где были назначены все ОУ, или эта конкретная хоть когда нибудь
  FOR
      SELECT D.OBJ_ID, D.DATE_ADD, D.DATE_MODIFY, D.DATE_DEL
      FROM UT_EXAM_DATES D
      WHERE (:I$EXAM_ID IS NULL OR D.OBJ_ID = :I$EXAM_ID) AND (D.DATE_ADD >= DATEADD(-1 YEAR TO CURRENT_DATE))
      INTO :EXAM_ID, :DATE_ADD, :DATE_MODIFY, :DATE_DEL
  DO
  BEGIN
      IF(EXISTS(
          SELECT FIRST 1 1
          FROM UT_EXAM_OU_ASSN A
          WHERE A.EXAM_ID = :EXAM_ID AND (A.OU_ID = 0 OR (A.OU_ID >= :V$MULT * :I$LIC_ID AND A.OU_ID < :V$MULT * (:I$LIC_ID + 1)))
      ))
      THEN
          SUSPEND;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_EXAM_BLANK_SET (
    I$EXAM_ID BIGINT,
    I$PACKET_ID BIGINT,
    I$FILE_ID VARCHAR(40),
    I$HASH VARCHAR(40),
    I$BLANK_TYPE BIGINT,
    I$BLANK_SIDE SMALLINT,
    I$BARCODE1 VARCHAR(128),
    I$BARCODE2 VARCHAR(128),
    I$USER_ID VARCHAR(40))
RETURNS (
    OBJ_ID BIGINT,
    STATE_ID INTEGER)
AS
declare variable V$PACKET_STATE integer;
declare variable V$YEAR varchar(20);
declare variable V$PPE_ID bigint;
begin

  -- Проверяем доступность
  SELECT P.STATE_ID, P.PPE_ID
  FROM UT_PACKAGES P
  WHERE P.OBJ_ID = :I$PACKET_ID AND P.ED_ID = :I$EXAM_ID AND P.DATE_DEL IS NULL
  INTO :V$PACKET_STATE, :V$PPE_ID;

  IF(V$PACKET_STATE IS NULL) THEN EXCEPTION DATA_ERROR 'Пакет не найден или обработка пакета завершена, прием файлов невозможен';

  IF(EXISTS(
      SELECT FIRST 1 1
      FROM UT_PACKAGES P
      JOIN UT_BLANKS B ON B.DATE_DEL IS NULL AND B.PACKAGE_ID = P.OBJ_ID AND B.FILE_HASH = :I$HASH
      WHERE P.ED_ID = :I$EXAM_ID AND P.DATE_DEL IS NULL -- AND P.OBJ_ID = :I$PACKET_ID
  ))
  THEN EXCEPTION DATA_ERROR 'Данный файл уже был загружен (совпадает сигнатура файла), загрузка дубликата невозможна';

  IF(EXISTS(
      SELECT FIRST 1 1
      FROM UT_PACKAGES P
      JOIN UT_BLANKS B ON B.DATE_DEL IS NULL AND B.PACKAGE_ID = P.OBJ_ID AND B.BARCODE_DATA = :I$BARCODE1
          AND (:I$BLANK_SIDE IS NULL OR B.BLANK_SIDE IS NULL OR B.BLANK_SIDE = :I$BLANK_SIDE)
      WHERE P.ED_ID = :I$EXAM_ID AND P.DATE_DEL IS NULL
  ))
  THEN EXCEPTION DATA_ERROR 'Бланк с таким штрихкодом уже был загружен (для той же стороны бланка)';

  SELECT FIRST 1 EXTRACT(YEAR FROM D.EXAM_DATE_START)
  FROM UT_EXAM_DATES D
  WHERE D.OBJ_ID = :I$EXAM_ID
  INTO :V$YEAR;

  -- Проверяем корректность штрихкода
  -- EAN13 - всегда полностью
  -- 2yteePPPPPPP, y = год, t = тип бланка, ee = цифры кода экзамена, PPPPPPP = код участника
  IF(CHAR_LENGTH(I$BARCODE1) = 13) THEN
  BEGIN

      IF(SUBSTRING(I$BARCODE1 FROM 1 FOR 1) <> '2') THEN EXCEPTION DATA_ERROR 'Бланк не относится к выбранному тестированию (E0001)';

      -- Сверяем типа бланка в штрихкоде и распознанный по маркерам
      -- !!!

      -- Проверяем поле y
      IF(RIGHT(V$YEAR, 1) <> SUBSTRING(I$BARCODE1 FROM 2 FOR 1)) THEN EXCEPTION DATA_ERROR 'Бланк не относится к выбранному тестированию (E0003)';

      -- Цифра типа бланка t: 1 = AB (односторонние), 2 = C лицевая, 3 = C оборотная, код экзамена XX для лицевой стороны, 00 для оборотной
      -- 4 = С дополнительный, код экзамена аналогично бланку типа C

      IF(I$BLANK_TYPE = 3) THEN
      BEGIN
          -- Дополнительные бланки неименные, и не связаны с конкретным тестированием. Надо проверить регистрацию в системе
          -- !!!!
      END
      ELSE
      BEGIN
          -- Проверяем поле ee
          IF(SUBSTRING(I$BARCODE1 FROM 4 FOR 2) <> '00') THEN
          BEGIN
              V$YEAR = I$EXAM_ID;
              IF(RIGHT(V$YEAR, 2) <> SUBSTRING(I$BARCODE1 FROM 4 FOR 2)) THEN EXCEPTION DATA_ERROR 'Бланк не относится к выбранному тестированию (E0002)';
          END
          IF(NOT EXISTS(
              SELECT FIRST 1 1
              FROM UT_EXAM_PERSON_ASSN PA
              WHERE PA.DATE_DEL IS NULL AND PA.EXAM_ID = :I$EXAM_ID AND PA.LOCAL_ID = SUBSTRING(:I$BARCODE1 FROM 6 FOR 7)
          )) THEN EXCEPTION DATA_ERROR 'Бланк не удалось соотнести с участником тестирования (E0004)';
     END

  END
  -- CODE39 - контрольная цифра кода может быть пропущена, в последнем случае восстанавливаем ее
  -- yyteeeessssPPPPPPPz
  ELSE IF(CHAR_LENGTH(I$BARCODE1) IN (18, 19)) THEN
  BEGIN

      -- Корректируем контрольную сумму, если номер вводился вручную
      IF(CHAR_LENGTH(I$BARCODE1) = 18) THEN
      BEGIN
          I$BARCODE1 = I$BARCODE1 || (SELECT VAL FROM UT_CHECKSUM_EAN39(:I$BARCODE1));
      END

      -- Проверяем поле yy
      IF(RIGHT(V$YEAR, 2) <> SUBSTRING(I$BARCODE1 FROM 1 FOR 2)) THEN EXCEPTION DATA_ERROR 'Бланк не относится к выбранному тестированию (E0003)';

      -- Проверяем поле eeee
      IF(SUBSTRING(I$BARCODE1 FROM 4 FOR 4) <> '0000') THEN
      BEGIN
          V$YEAR = I$EXAM_ID;
          IF(RIGHT(V$YEAR, 4) <> SUBSTRING(I$BARCODE1 FROM 4 FOR 4)) THEN EXCEPTION DATA_ERROR 'Бланк не относится к выбранному тестированию (E0002)';
      END

      -- Проверяем, что этот бланк из пакета нужной ОУ/ППЭ поле ssss
      V$YEAR = V$PPE_ID;
      V$YEAR = SUBSTRING(V$YEAR FROM 1 FOR CHAR_LENGTH(V$YEAR) - 9);
      WHILE(CHAR_LENGTH(V$YEAR) < 4) DO V$YEAR = '0' || V$YEAR;
      IF(V$YEAR <> SUBSTRING(I$BARCODE1 FROM 8 FOR 4)) THEN EXCEPTION DATA_ERROR 'Бланк не относится к ОУ/ППЭ данного пакета (E0005)';

      IF(I$BLANK_TYPE = 3) THEN
      BEGIN
          -- Дополнительный бланк
          IF(NOT EXISTS(
              SELECT FIRST 1 1
              FROM UT_EXT_BLANKS B
              WHERE B.DATE_DEL IS NULL AND B.EXAM_ID = :I$EXAM_ID AND B.REF_ID = :V$PPE_ID AND B.LOCAL_ID = SUBSTRING(:I$BARCODE1 FROM 12 FOR 7)
          )) THEN EXCEPTION DATA_ERROR 'Бланк не найден в числе действующих дополнительных бланков (E0006)';
      END
      ELSE
      BEGIN
          IF(NOT EXISTS(
              SELECT FIRST 1 1
              FROM UT_EXAM_PERSON_ASSN PA
              WHERE PA.DATE_DEL IS NULL AND PA.EXAM_ID = :I$EXAM_ID AND PA.LOCAL_ID = SUBSTRING(:I$BARCODE1 FROM 12 FOR 7)
          )) THEN EXCEPTION DATA_ERROR 'Бланк не удалось соотнести с участником тестирования (E0004)';
      END

  END
  ELSE EXCEPTION DATA_ERROR 'Тип штрихкода не удалось определить. Требуется 13 или 18(19) символов';

  -- Добавляем в статусе 1 для сырых бланков и в статусе 3 для предварительно обработанных
  STATE_ID = 1;
  IF(I$BARCODE1 IS NOT NULL) THEN STATE_ID = 3;

  INSERT INTO UT_BLANKS
  (PACKAGE_ID, FILE_ID, FILE_HASH, BLANK_TYPE, BLANK_SIDE, BARCODE_DATA, BARCODE2_DATA, STATE_ID)
  VALUES (:I$PACKET_ID, :I$FILE_ID, :I$HASH, :I$BLANK_TYPE, :I$BLANK_SIDE, :I$BARCODE1, :I$BARCODE2, :STATE_ID)
  RETURNING OBJ_ID INTO :OBJ_ID;

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_EXAM_DATES_SET (
    I$OBJ_ID BIGINT,
    I$NAME VARCHAR(400),
    I$EXAM_STATE INTEGER,
    I$SUBJECT_ID BIGINT,
    I$STAGE_ID INTEGER,
    I$EXAM_DATE_START DATE,
    I$EXAM_DATE_END DATE,
    I$DURATION INTEGER,
    I$EXAM_DAY_TYPE INTEGER,
    I$C_CALC_MODE INTEGER,
    I$C_EXPERT_NUM INTEGER,
    I$C_DIFF_QUESTION INTEGER,
    I$C_DIFF_TOTAL INTEGER,
    I$METHOD_ID INTEGER,
    I$PLAN_METHOD_ID INTEGER,
    I$ATTEMPTS INTEGER,
    I$OWNER_ID BIGINT,
    I$H_LEVEL INTEGER,
    I$ORG_REF BIGINT,
    I$FLOW_MODE SMALLINT,
    I$PAUSE_ENABLED SMALLINT,
    I$EXPERT_ASSN_MODE SMALLINT,
    I$BLANK_AB_ID BIGINT,
    I$BLANK_C_ID BIGINT,
    I$BLANK_EXT_ID BIGINT,
    I$BLANK_GEN_ID BIGINT,
    I$SCALE_N0 SMALLINT,
    I$SCALE_NMIN SMALLINT,
    I$SCALE_N4 SMALLINT,
    I$SCALE_N5 SMALLINT,
    I$SCALE_NMAX SMALLINT,
    I$PPE_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT)
AS
DECLARE VARIABLE V$STATE INTEGER;
DECLARE VARIABLE V$EXPERTS_NUM SMALLINT;
DECLARE VARIABLE V$EXPERTS_NEEDED SMALLINT;
DECLARE VARIABLE V$VAR_ID BIGINT;
DECLARE VARIABLE V$POINT_ID BIGINT;
DECLARE VARIABLE V$VAR_NUM SMALLINT;
DECLARE VARIABLE V$Q_NUM SMALLINT;
DECLARE VARIABLE V$Q_TYPE SMALLINT;
DECLARE VARIABLE V$DB_LEVEL INTEGER;
DECLARE VARIABLE V$H_LEVEL INTEGER;
BEGIN
  OBJ_ID = I$OBJ_ID;

  SELECT COALESCE(CAST(KEY_VAL AS INTEGER) - 1, 0)
  FROM KEYS
  WHERE KEY_CODE = 'LEVEL'
  INTO :V$DB_LEVEL;

  IF(I$EXAM_DATE_START IS NOT NULL AND I$EXAM_DATE_END IS NOT NULL AND I$EXAM_DATE_START > I$EXAM_DATE_END) THEN
    EXCEPTION DATA_ERROR 'Неправильный порядок дат начала и окончания тестирования';

  -- Проверяем уникальность названия
  IF(EXISTS(
    SELECT FIRST 1 1
    FROM UT_EXAM_DATES
    WHERE DATE_DEL IS NULL AND OBJ_NAME = :I$NAME AND (:I$OBJ_ID IS NULL OR OBJ_ID <> :I$OBJ_ID)
  ))
  THEN
    EXCEPTION DATA_ERROR 'Тестирование с таким наименованием уже есть';

  IF(I$DURATION IS NOT NULL AND I$DURATION < 1) THEN
    EXCEPTION DATA_ERROR 'Недопустимая длительность тестирования';

  -- Обнуляем организацию на всякий случай, при выборе уровня регион+
  IF(I$H_LEVEL >= 2) THEN I$ORG_REF = NULL;

  -- Проверяем порядок шкалы
  IF(I$SCALE_N0 IS NOT NULL) THEN
  BEGIN
    IF(I$SCALE_N0 > I$SCALE_NMIN OR I$SCALE_N0 > I$SCALE_N4 OR I$SCALE_N0 > I$SCALE_N5 OR I$SCALE_N0 > I$SCALE_NMAX) THEN
      EXCEPTION DATA_ERROR 'Нарушен порядок следования показателей в шкале';
  END
  IF(I$SCALE_NMIN IS NOT NULL) THEN
  BEGIN
    IF(I$SCALE_NMIN > I$SCALE_N4 OR I$SCALE_NMIN > I$SCALE_N5 OR I$SCALE_NMIN > I$SCALE_NMAX) THEN
      EXCEPTION DATA_ERROR 'Нарушен порядок следования показателей в шкале';
  END
  IF(I$SCALE_N4 IS NOT NULL) THEN
  BEGIN
    IF(I$SCALE_N4 > I$SCALE_N5 OR I$SCALE_N4 > I$SCALE_NMAX) THEN
      EXCEPTION DATA_ERROR 'Нарушен порядок следования показателей в шкале';
  END
  IF(I$SCALE_N5 IS NOT NULL) THEN
  BEGIN
    IF(I$SCALE_N5 > I$SCALE_NMAX) THEN
      EXCEPTION DATA_ERROR 'Нарушен порядок следования показателей в шкале';
  END

  I$PAUSE_ENABLED = COALESCE(I$PAUSE_ENABLED, 0);

  IF(I$OBJ_ID IS NULL) THEN
  BEGIN

    -- Добавление только в статусе черновика
    -- Если поля шаблонов документов не заданы - берем последние добавленные нужного типа
    IF(I$BLANK_AB_ID IS NULL) THEN
    BEGIN
      SELECT FIRST 1 OBJ_ID
      FROM UT_PAGE_TEMPLATES
      WHERE DATE_DEL IS NULL AND BLANK_TYPE = 1
      ORDER BY DATE_ADD DESC
      INTO :I$BLANK_AB_ID;
    END
    IF(I$BLANK_C_ID IS NULL) THEN
    BEGIN
      SELECT FIRST 1 OBJ_ID
      FROM UT_PAGE_TEMPLATES
      WHERE DATE_DEL IS NULL AND BLANK_TYPE = 2
      ORDER BY DATE_ADD DESC
      INTO :I$BLANK_C_ID;
    END
    IF(I$BLANK_EXT_ID IS NULL) THEN
    BEGIN
      SELECT FIRST 1 OBJ_ID
      FROM UT_PAGE_TEMPLATES
      WHERE DATE_DEL IS NULL AND BLANK_TYPE = 3
      ORDER BY DATE_ADD DESC
      INTO :I$BLANK_EXT_ID;
    END
    IF(I$BLANK_GEN_ID IS NULL) THEN
    BEGIN
      SELECT FIRST 1 OBJ_ID
      FROM UT_PAGE_TEMPLATES
      WHERE DATE_DEL IS NULL AND BLANK_TYPE = 4
      ORDER BY DATE_ADD DESC
      INTO :I$BLANK_GEN_ID;
    END

    INSERT INTO UT_EXAM_DATES
    (OBJ_NAME, SUBJECT_ID, STAGE_ID, EXAM_DATE_START, EXAM_DATE_END, DURATION, EXAM_DAY_TYPE, EXAM_STATE,
      C_CALC_MODE, C_EXPERT_NUM, C_DIFF_QUESTION, C_DIFF_TOTAL, METHOD_ID, PLAN_METHOD_ID, ATTEMPTS, OWNER_ID, H_LEVEL, ORG_REF,
      FLOW_MODE, PAUSE_ENABLED, EXPERT_ASSN_MODE, BLANK_AB_ID, BLANK_C_ID, BLANK_EXT_ID, BLANK_GEN_ID,
      SCALE_N0, SCALE_NMIN, SCALE_N4, SCALE_N5, SCALE_NMAX, PPE_ID)
    VALUES (:I$NAME, :I$SUBJECT_ID, :I$STAGE_ID, :I$EXAM_DATE_START, :I$EXAM_DATE_END, :I$DURATION, :I$EXAM_DAY_TYPE, 0,
      COALESCE(:I$C_CALC_MODE, 0), COALESCE(:I$C_EXPERT_NUM, 1), COALESCE(:I$C_DIFF_QUESTION, 1), COALESCE(:I$C_DIFF_TOTAL, 1),
      COALESCE(:I$METHOD_ID, 0), COALESCE(:I$PLAN_METHOD_ID, 0), COALESCE(:I$ATTEMPTS, 1),
      :I$OWNER_ID, :I$H_LEVEL, :I$ORG_REF, :I$FLOW_MODE, :I$PAUSE_ENABLED, :I$EXPERT_ASSN_MODE,
      :I$BLANK_AB_ID, :I$BLANK_C_ID, :I$BLANK_EXT_ID, :I$BLANK_GEN_ID, :I$SCALE_N0, :I$SCALE_NMIN, :I$SCALE_N4, :I$SCALE_N5, :I$SCALE_NMAX, :I$PPE_ID
    )
    RETURNING OBJ_ID INTO :OBJ_ID;

  END
  ELSE
  BEGIN

    -- STATE_ID на этом этапе выставляем только если ранее был статус черновика. Если статус не-черновик, то статус на этом этапе оставляем старый
    SELECT FIRST 1 EXAM_STATE, H_LEVEL
    FROM UT_EXAM_DATES
    WHERE DATE_DEL IS NULL AND OBJ_ID = :I$OBJ_ID
    INTO :V$STATE, :V$H_LEVEL;

    IF(V$STATE IS NULL) THEN EXCEPTION DATA_ERROR 'Тестирование не найдено или было удалено';
    IF(V$STATE > 0) THEN I$EXAM_STATE = V$STATE;

    -- Сверяем уровень тестирования с уровнем текущей базы
    -- Если уровень тестирования выше уровня базы, ничего не меняем
    IF(V$DB_LEVEL >= V$H_LEVEL) THEN
    BEGIN
      UPDATE UT_EXAM_DATES
      SET DATE_MODIFY = CURRENT_TIMESTAMP, OBJ_NAME = :I$NAME, EXAM_STATE = :I$EXAM_STATE,
        STAGE_ID = :I$STAGE_ID, EXAM_DATE_START = :I$EXAM_DATE_START, EXAM_DATE_END = :I$EXAM_DATE_END,
        DURATION = :I$DURATION, C_CALC_MODE = COALESCE(:I$C_CALC_MODE, C_CALC_MODE),
        C_EXPERT_NUM = COALESCE(:I$C_EXPERT_NUM, C_EXPERT_NUM), C_DIFF_QUESTION = COALESCE(:I$C_DIFF_QUESTION, C_DIFF_QUESTION),
        C_DIFF_TOTAL = COALESCE(:I$C_DIFF_TOTAL, C_DIFF_TOTAL),
        PLAN_METHOD_ID = COALESCE(:I$PLAN_METHOD_ID, PLAN_METHOD_ID), ATTEMPTS = COALESCE(:I$ATTEMPTS, ATTEMPTS),
        OWNER_ID = COALESCE(:I$OWNER_ID, OWNER_ID), ORG_REF = :I$ORG_REF, FLOW_MODE = :I$FLOW_MODE, PAUSE_ENABLED = :I$PAUSE_ENABLED,
        EXPERT_ASSN_MODE = :I$EXPERT_ASSN_MODE,
        BLANK_AB_ID = COALESCE(:I$BLANK_AB_ID, BLANK_AB_ID), BLANK_C_ID = COALESCE(:I$BLANK_C_ID, BLANK_C_ID), BLANK_EXT_ID = COALESCE(:I$BLANK_EXT_ID, BLANK_EXT_ID),
        BLANK_GEN_ID = COALESCE(:I$BLANK_GEN_ID, BLANK_GEN_ID),
        SCALE_N0 = COALESCE(:I$SCALE_N0, SCALE_N0), SCALE_NMIN = COALESCE(:I$SCALE_NMIN, SCALE_NMIN), SCALE_N4 = COALESCE(:I$SCALE_N4, SCALE_N4),
        SCALE_N5 = COALESCE(:I$SCALE_N5, SCALE_N5), SCALE_NMAX = COALESCE(:I$SCALE_NMAX, SCALE_NMAX),
        PPE_ID = :I$PPE_ID
      WHERE OBJ_ID = :OBJ_ID;
    END
  END

  SUSPEND;

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_EXAM_DATES_STATE_SET (
    I$OBJ_ID BIGINT,
    I$EXAM_STATE INTEGER)
RETURNS (
    STUB INTEGER)
AS
DECLARE VARIABLE V$STATE INTEGER;
DECLARE VARIABLE V$EXPERTS_NUM INTEGER;
DECLARE VARIABLE V$EXPERTS_NEEDED INTEGER;
DECLARE VARIABLE V$EXAM_DATE_START DATE;
DECLARE VARIABLE V$EXAM_DATE_END DATE;
DECLARE VARIABLE V$VAR_ID BIGINT;
DECLARE VARIABLE V$POINT_ID BIGINT;
DECLARE VARIABLE V$VAR_NUM INTEGER;
DECLARE VARIABLE V$Q_NUM INTEGER;
DECLARE VARIABLE V$Q_TYPE SMALLINT;
DECLARE VARIABLE V$CHARSET INTEGER;
DECLARE VARIABLE N INTEGER;
DECLARE VARIABLE NS INTEGER;
DECLARE VARIABLE V$BLANK_AB_ID BIGINT;
DECLARE VARIABLE V$BLANK_C_ID BIGINT;
DECLARE VARIABLE V$BLANK_EXT_ID BIGINT;
DECLARE VARIABLE V$BLANK_GEN_ID BIGINT;
DECLARE VARIABLE V$METHOD INTEGER;
DECLARE VARIABLE V$DT INTEGER;
DECLARE VARIABLE V$H_LEVEL INTEGER;
DECLARE VARIABLE V$PLAN_METHOD INTEGER;
DECLARE VARIABLE V$CONTROL_ID BIGINT;
DECLARE VARIABLE V$MARK_SYSTEM_ID BIGINT;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$SESSION_ID BIGINT;
DECLARE VARIABLE V$RESULT_ID BIGINT;
DECLARE VARIABLE V$PERSON_ID BIGINT;
DECLARE VARIABLE V$MARK_ID BIGINT;
DECLARE VARIABLE V$MARKVAL BIGINT;
DECLARE VARIABLE V$MV BIGINT;
DECLARE VARIABLE V$MIN_ID BIGINT;
DECLARE VARIABLE V$MAX_ID BIGINT;
DECLARE VARIABLE V$USER_ID BIGINT;
begin

  -- В случае изменения статуса выполняем проверки
  SELECT EXAM_STATE, C_EXPERT_NUM, EXAM_DATE_START, EXAM_DATE_END, BLANK_AB_ID, BLANK_C_ID, BLANK_EXT_ID, BLANK_GEN_ID,
    METHOD_ID, PLAN_METHOD_ID, H_LEVEL, EXAM_DAY_TYPE
  FROM UT_EXAM_DATES
  WHERE OBJ_ID = :I$OBJ_ID AND DATE_DEL IS NULL
  INTO :V$STATE, :V$EXPERTS_NUM, :V$EXAM_DATE_START, :V$EXAM_DATE_END, :V$BLANK_AB_ID, :V$BLANK_C_ID, :V$BLANK_EXT_ID, :V$BLANK_GEN_ID,
    :V$METHOD, :V$PLAN_METHOD, :V$H_LEVEL, :V$DT;

  IF(V$STATE IS NULL) THEN EXCEPTION DATA_ERROR 'Тестирование не найдено или было удалено';

  V$EXPERTS_NEEDED = 0;

  IF(I$EXAM_STATE <> V$STATE AND I$EXAM_STATE <> 1001) THEN
  BEGIN

    -- Сбор данных и далее: как минимум дата начала должна быть задана
    IF(I$EXAM_STATE > 0 AND (V$EXAM_DATE_START IS NULL OR V$EXAM_DATE_END IS NULL)) THEN
      EXCEPTION DATA_ERROR 'Должна быть заданы даты начала и окончания тестирования';

    -- Должна быть задана хотя бы одна ОУ, если уровень выше уровня ОУ
    IF(I$EXAM_STATE > 0 AND V$H_LEVEL > 0 AND NOT EXISTS(
      SELECT FIRST 1 1
      FROM UT_EXAM_OU_ASSN A
      WHERE A.DATE_DEL IS NULL AND A.EXAM_ID = :I$OBJ_ID
    ))
    THEN
      EXCEPTION DATA_ERROR 'Необходимо указать хотя бы одну организацию, в которых будет проводиться тестирование';

    -- Задание всех видов бланков
    IF(I$EXAM_STATE > 0 AND V$METHOD = 2) THEN
    BEGIN
      IF(V$BLANK_AB_ID IS NULL OR V$BLANK_AB_ID = 0) THEN
        EXCEPTION DATA_ERROR 'Не задан рабочий шаблон бланка AB';
      IF(V$EXPERTS_NEEDED = 1 AND (V$BLANK_C_ID IS NULL OR V$BLANK_C_ID = 0 OR V$BLANK_EXT_ID IS NULL OR V$BLANK_EXT_ID = 0)) THEN
        EXCEPTION DATA_ERROR 'Не заданы рабочие шаблоны бланка C или дополнительного бланка типа C';
      IF(V$BLANK_EXT_ID IS NULL OR V$BLANK_EXT_ID = 0) THEN
        EXCEPTION DATA_ERROR 'Не задан рабочий шаблон бланка ведомостей';
    END

    -- Печать бланков и КИМ и далее: проверяем структуру теста
    IF(I$EXAM_STATE >= 500 AND V$DT < 90) THEN
    BEGIN

      IF(V$PLAN_METHOD = 4) THEN
      BEGIN
        N = 0;
        SELECT FIRST 1 1
        FROM UT_EXAM_QUESTIONS EQ
        WHERE EQ.DATE_DEL IS NULL AND EQ.EXAM_ID = :I$OBJ_ID
        INTO :N;

        IF(N = 0) THEN EXCEPTION DATA_ERROR 'Не заданы вопросы для тестирования';
      END
      ELSE
      BEGIN
        -- Задан хотя бы один вариант КИМ
        N = 0;
        SELECT FIRST 1 1
        FROM UT_EXAM_TEST_VARS TV
        JOIN UT_TEST_VARS V ON V.OBJ_ID = TV.TEST_VAR_ID AND V.DATE_DEL IS NULL
        JOIN UT_TESTS T ON T.OBJ_ID = V.TEST_ID AND T.DATE_DEL IS NULL
        JOIN UT_TEST_STRUCTS TS ON TS.OBJ_ID = T.STRUCT_ID AND TS.DATE_DEL IS NULL
        WHERE TV.EXAM_ID = :I$OBJ_ID AND TV.DATE_DEL IS NULL
        INTO :N;

        IF(N = 0) THEN EXCEPTION DATA_ERROR 'Не назначено ни одного варианта КИМ';
      END

      -- Количество экспертов не менее указанного количества, при этом если указано 2+, должен быть хотя бы один ведущий
      IF(V$EXPERTS_NUM > 0) THEN
      BEGIN
        SELECT COUNT(*)
        FROM UT_EXAM_EXPERT_ASSN EA
        WHERE EA.EXAM_ID = :I$OBJ_ID AND EA.DATE_DEL IS NULL
        INTO :N;

        IF(N < V$EXPERTS_NUM) THEN EXCEPTION DATA_ERROR 'Количество экспертов недостаточно';

        IF(V$EXPERTS_NUM >= 2) THEN
        BEGIN
          SELECT COUNT(*)
          FROM UT_EXAM_EXPERT_ASSN EA
          WHERE EA.EXAM_ID = :I$OBJ_ID AND EA.DATE_DEL IS NULL AND EA.ROLE_ID >= 3
          INTO :N;

          --IF(N = 0) THEN EXCEPTION DATA_ERROR 'Требуется хотя бы один ведущий эксперт для проведения повторной проверки';
        END
      END

      -- Проверяем, что у всех назначенных вариантов КИМ совпадают сигнатуры
      SELECT COUNT(DISTINCT TS.STR_HASH)
      FROM UT_EXAM_TEST_VARS TV
      JOIN UT_TEST_VARS V ON V.OBJ_ID = TV.TEST_VAR_ID AND V.DATE_DEL IS NULL
      JOIN UT_TESTS T ON T.OBJ_ID = V.TEST_ID AND T.DATE_DEL IS NULL
      JOIN UT_TEST_STRUCTS TS ON TS.OBJ_ID = T.STRUCT_ID AND TS.DATE_DEL IS NULL
      WHERE TV.EXAM_ID = :I$OBJ_ID AND TV.DATE_DEL IS NULL
      INTO :N;

      IF(N > 1) THEN EXCEPTION DATA_ERROR 'В тестировании назначены варианты, не совпадающие по структуре';

      -- Во всех вариантах должны быть назначены все вопросы, и у всех вопросов типа B заданы кодировки
      NS = 0;
      FOR
        SELECT V.OBJ_ID, TSP.OBJ_ID, V.NUM, TSP.Q_ORDER, TSP.Q_TYPE_ID, TSP.CHARSET_ID
        FROM UT_EXAM_TEST_VARS TV
        JOIN UT_TEST_VARS V ON V.OBJ_ID = TV.TEST_VAR_ID AND V.DATE_DEL IS NULL
        JOIN UT_TESTS T ON T.OBJ_ID = V.TEST_ID AND T.DATE_DEL IS NULL
        JOIN UT_TEST_STRUCTS TS ON TS.OBJ_ID = T.STRUCT_ID AND TS.DATE_DEL IS NULL
        JOIN UT_TEST_STRUCT_POINTS TSP ON TSP.STRUCT_ID = TS.OBJ_ID AND TSP.DATE_DEL IS NULL
        WHERE TV.EXAM_ID = :I$OBJ_ID AND TV.DATE_DEL IS NULL AND :V$PLAN_METHOD <> 4
        ORDER BY TSP.Q_ORDER
        INTO :V$VAR_ID, :V$POINT_ID, :V$VAR_NUM, :V$Q_NUM, :V$Q_TYPE, :V$CHARSET
      DO
      BEGIN
        IF(V$Q_TYPE = 2 AND V$CHARSET IS NULL) THEN EXCEPTION DATA_ERROR 'В позиции ' || V$Q_NUM || ' для вопроса типа B не задана кодировка';

        SELECT COUNT(*)
        FROM UT_TEST_VAR_QUESTIONS Q
        JOIN UT_QUESTIONS QQ ON QQ.OBJ_ID = Q.QUESTION_ID AND QQ.DATE_DEL IS NULL
        WHERE Q.VAR_ID = :V$VAR_ID AND Q.STRUCT_POINT_ID = :V$POINT_ID AND Q.DATE_DEL IS NULL
        INTO :N;

        IF(N = 0) THEN EXCEPTION DATA_ERROR 'В варианте ' || V$VAR_NUM || ' не назначен вопрос в позиции ' || V$Q_NUM;

        -- Требуем наличия экспертов для вопросов типа C и V
        IF(V$Q_TYPE IN (3, 8)) THEN V$EXPERTS_NEEDED = 1;

        NS = NS + 1;
      END

      -- Аналогично, дубль проверки для упрощенного варианта
      FOR
        SELECT EQ.VARIANT_INDEX, EQ.SORT_INDEX, Q.QUESTION_TYPE
        FROM UT_EXAM_QUESTIONS EQ
        JOIN UT_QUESTIONS Q ON Q.OBJ_ID = EQ.QUESTION_ID AND Q.DATE_DEL IS NULL
        WHERE EQ.DATE_DEL IS NULL AND EQ.EXAM_ID = :I$OBJ_ID AND :V$PLAN_METHOD = 4
        ORDER BY 1, 2
        INTO :V$VAR_ID, :V$Q_NUM, :V$Q_TYPE
      DO
      BEGIN
        -- Требуем наличия экспертов для вопросов типа C и V
        IF(V$Q_TYPE IN (3, 8)) THEN V$EXPERTS_NEEDED = 1;

        NS = NS + 1;
      END

      IF(V$EXPERTS_NEEDED = 1 AND V$EXPERTS_NUM = 0) THEN
        EXCEPTION DATA_ERROR 'Вопросы предполагают экспертную проверку, но в тестировании не заданы параметры экспертной проверки';
      IF(NS = 0) THEN
        EXCEPTION DATA_ERROR 'В тестировании нет ни одного вопроса - структура и варианты не назначены, или произошла системная ошибка';

    END

    -- Обновляем оценки в КЖ для упрощенной схемы тестирования
    IF(I$EXAM_STATE = 1000 AND V$PLAN_METHOD = 4) THEN
    BEGIN
      SELECT FIRST 1 C.CONTROL_ID, C.MARK_SYSTEM_ID
      FROM CJ2_CONTROL C
      WHERE C.DATE_DEL IS NULL AND C.TEST_ID = :I$OBJ_ID
      INTO :V$CONTROL_ID, :V$MARK_SYSTEM_ID;

      SELECT MIN(MT.MARK_TYPE_ID), MAX(MT.MARK_TYPE_ID)
      FROM CJ2_MARK_TYPE MT
      WHERE MT.PARENT_ID = :V$MARK_SYSTEM_ID
      INTO :V$MIN_ID, :V$MAX_ID;
      -- В 12-балльной шкале не выставляем 11 и 12 баллов автоматом
      IF(V$MAX_ID = 462) THEN V$MAX_ID = 460;

      -- Отменяем незаконченные тестирования, если есть оконечнные предыдущие сессии
      FOR
        SELECT S1.OBJ_ID
        FROM UT_SESSIONS S1
        WHERE S1.DATE_DEL IS NULL AND S1.ED_ID = :I$OBJ_ID AND S1.STATE_ID < 10 AND EXISTS(
          SELECT FIRST 1 1
          FROM UT_SESSIONS S2
          WHERE S2.DATE_DEL IS NULL AND S2.ED_ID = S1.ED_ID AND S2.PERSON_ID = S1.PERSON_ID AND S2.STATE_ID IN (10, 100)
        )
        ORDER BY 1
        INTO :V$OBJ_ID
      DO
      BEGIN
        UPDATE UT_SESSIONS
        SET STATE_ID = 101
        WHERE OBJ_ID = :V$OBJ_ID;
      END

      -- Если оценивание вообще не предполагается - ничего не делаем
      IF(V$MARK_SYSTEM_ID <> 999) THEN
      BEGIN
        FOR
          SELECT PA.PERSON_ID, MAX(S.OBJ_ID)
          FROM UT_EXAM_PERSON_ASSN PA
          JOIN UT_SESSIONS S ON S.DATE_DEL IS NULL AND S.ED_ID = PA.EXAM_ID AND S.PERSON_ID = PA.PERSON_ID AND S.STATE_ID = 100
          WHERE PA.DATE_DEL IS NULL AND PA.EXAM_ID = :I$OBJ_ID
          GROUP BY 1
          INTO :V$PERSON_ID, :V$SESSION_ID
        DO
        BEGIN
          V$RESULT_ID = NULL;
          SELECT S.FINAL_RESULT_ID
          FROM UT_SESSIONS S
          WHERE S.OBJ_ID = :V$SESSION_ID
          INTO :V$RESULT_ID;

          IF(V$RESULT_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Нельзя завершить тестирование, пока остались незавершенные сессии (не выставлены оценки)';

          V$MV = NULL;
          V$MARK_ID = NULL;
          V$MARKVAL = NULL;
          V$USER_ID = NULL;
          -- USER_ID = NULL означает что оценка поставлена автоматически
          SELECT FIRST 1 M.MARK_ID, M.MARK_TYPE_ID, M.USER_ID
          FROM CJ2_MARK M
          WHERE M.DATE_DEL IS NULL AND M.CONTROL_ID = :V$CONTROL_ID AND M.STUDENT_ID = :V$PERSON_ID
          INTO :V$MARK_ID, :V$MARKVAL, :V$USER_ID;

          -- Конвертируем шкалу по необходимости
          IF(V$RESULT_ID >= 401 AND V$RESULT_ID <= 405) THEN V$MV = V$RESULT_ID;
          ELSE
          BEGIN
            -- но если учитель поставил руками - оставляем то что поставил учитель
            -- Шкалы всегда предполагаем линейными по ID, ни в коем случае не должно быть разрывов
            -- реально оценка может быть 2, 3, 4 или 5
            V$MV = V$MIN_ID + (V$MAX_ID - V$MIN_ID) * (V$RESULT_ID - 401) / 4;
          END

          IF(V$MARK_ID IS NULL) THEN
          BEGIN
            INSERT INTO CJ2_MARK
            (CONTROL_ID, STUDENT_ID, MARK_TYPE_ID, MARK_DATE)
            VALUES (:V$CONTROL_ID, :V$PERSON_ID, :V$MV, CURRENT_DATE);
          END
          ELSE IF(V$MARKVAL <> V$MV AND V$USER_ID IS NULL) THEN
          BEGIN
            -- Удаляем старую оценку для истории и выставляем новую
            UPDATE CJ2_MARK
            SET DATE_DEL = CURRENT_TIMESTAMP
            WHERE MARK_ID = :V$MARK_ID;

            INSERT INTO CJ2_MARK
            (CONTROL_ID, STUDENT_ID, MARK_TYPE_ID, MARK_DATE)
            VALUES (:V$CONTROL_ID, :V$PERSON_ID, :V$MV, CURRENT_DATE);
          END
        END
      END
    END

  END

  IF(I$EXAM_STATE <> V$STATE) THEN
  BEGIN
    UPDATE UT_EXAM_DATES
    SET EXAM_STATE = :I$EXAM_STATE
    WHERE OBJ_ID = :I$OBJ_ID;
  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_EXAM_DATE_DELETE (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
AS
DECLARE VARIABLE V$STATE INTEGER;
DECLARE VARIABLE V$LEVEL INTEGER;
DECLARE VARIABLE V$REF BIGINT;
DECLARE VARIABLE S VARCHAR(1000);
begin

  SELECT D.EXAM_STATE, D.H_LEVEL, D.ORG_REF
  FROM UT_EXAM_DATES D
  WHERE D.OBJ_ID = :I$OBJ_ID AND D.DATE_DEL IS NULL
  INTO :V$STATE, :V$LEVEL, :V$REF;
  
  IF(V$STATE IS NULL) THEN EXCEPTION DATA_ERROR 'Запись тестирования не найдена или была удалена';
  IF(V$STATE > 0 AND V$STATE <> 1001) THEN EXCEPTION DATA_ERROR 'Удалить тестирование можно только в статусе черновика или после отмены тестирования';

  SELECT FIRST 1 P.OBJ_NAME
  FROM PTP_LESSON_TESTS T
  JOIN PTP_LESSONS L ON L.OBJ_ID = T.LESSON_ID AND L.DATE_DEL IS NULL
  JOIN PTP P ON P.OBJ_ID = L.PTP_ID AND P.DATE_DEL IS NULL
  WHERE T.DATE_DEL IS NULL AND T.TEST_ID = :I$OBJ_ID
  INTO :S;

  IF(S IS NOT NULL) THEN EXCEPTION DATA_ERROR 'На данный тест имеются ссылки из ПТП ' || S || ', нельзя удалить';

  SELECT FIRST 1 J.JOURNAL_NAME || ' за ' || D.RESULT
  FROM CJ2_CONTROL C
  JOIN CJ2_JOURNAL_LESSONS L ON L.OBJ_ID = C.LESSON_ID AND L.DATE_DEL IS NULL
  JOIN CJ2_JOURNAL J ON J.OBJ_ID = L.CJ_ID AND L.DATE_DEL IS NULL
  LEFT JOIN DATE2STR(L.LESSON_DATE) D ON 1 = 1
  WHERE C.DATE_DEL IS NULL AND C.TEST_ID = :I$OBJ_ID
  INTO :S;

  IF(S IS NOT NULL) THEN EXCEPTION DATA_ERROR 'На данный тест имеются ссылки в уроке ' || S || ', нельзя удалить';

  UPDATE UT_EXAM_DATES
  SET DATE_DEL = CURRENT_TIMESTAMP, EXAM_STATE = 1001
  WHERE OBJ_ID = :I$OBJ_ID;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_EXAM_DATE_READY (
    I$ED_ID BIGINT)
RETURNS (
    READY_STATE SMALLINT)
AS
declare variable V$STATE integer;
declare variable V$DATE_START date;
declare variable V$DATE_END date;
begin

  -- READY_STATE: 0 = экзамен не активен, 1 = время начала еще не достигнуто, 2 = можно начинать

  SELECT ED.EXAM_STATE, ED.EXAM_DATE_START, ED.EXAM_DATE_END
  FROM UT_EXAM_DATES ED
  WHERE ED.OBJ_ID = :I$ED_ID AND ED.DATE_DEL IS NULL
  INTO :V$STATE, :V$DATE_START, :V$DATE_END;

  IF(V$STATE IS NULL) THEN EXCEPTION DATA_ERROR 'Тестирование не найдено';

  READY_STATE = 0;

  -- Если в стадии проведения, то разрешаем выдачу результатов
  IF(V$STATE = 600) THEN
  BEGIN

      -- Даты попадают в разрешенный диапазон
      IF(CURRENT_DATE >= V$DATE_START AND CURRENT_DATE <= V$DATE_END) THEN
      BEGIN
          -- Тестирование разрешено
          READY_STATE = 2;
      END

  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_EXAM_DATE_RESULTS (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40) = null)
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(4000))
AS
declare variable V$SESSION_ID bigint;
declare variable V$PERSON_ID bigint;
declare variable V$PERSON_NAME varchar(1000);
declare variable V$STATE_ID integer;
declare variable V$STATE_NAME varchar(200);
declare variable V$VAR_NUM integer;
declare variable V$DATE_START timestamp;
declare variable V$DATE_END timestamp;
declare variable V$DURATION integer;
declare variable V$PERCENT smallint;
declare variable V$RAW_RESULT integer;
declare variable V$RESULT_ID bigint;
declare variable V$RESULT_NAME varchar(200);
declare variable V$DB_LEVEL smallint;
declare variable V$OUR_ORG bigint;
begin

  TAG_NAME = 'data';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'data::json&colon;array';
  VAL = '1';
  SUSPEND;

  -- Уровень доступа текущего пользователя, равен уровню базы
  TAG_NAME = 'user_level';
  SELECT COALESCE(CAST(K.KEY_VAL AS INTEGER) - 1, 0)
  FROM KEYS K
  WHERE K.KEY_CODE = 'LEVEL'
  INTO :V$DB_LEVEL;

  -- Получаем наш домашний уровень (только для ОУ)
  SELECT FIRST 1 L2.OBJ_ID
  FROM LINKS L2
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$OUR_ORG;

  -- Идем по участникам тестирования и сразу джойним их результаты
  -- Показываем только участников тестирования в пределах своего уровня доступа. Для уровней район и регион не показываем ничего
  FOR
      SELECT PA.PERSON_ID, C.CAPTION, S.OBJ_ID, S.STATE_ID, SS.STATE_NAME, TV.NUM, S.STARTED_AT, S.COMPLETED_AT, S.DURATION,
          S.RAW_RESULT, MT.MARK_TYPE_ID, MT.MARK_NAME
      FROM UT_EXAM_PERSON_ASSN PA
      JOIN OBJECTS OBJ ON OBJ.OBJ_ID = PA.PERSON_ID
      LEFT JOIN OBJECT_CAPTION_GET(PA.PERSON_ID) C ON 1 = 1
      LEFT JOIN UT_SESSIONS S ON S.ED_ID = PA.EXAM_ID AND S.PERSON_ID = PA.PERSON_ID AND S.DATE_DEL IS NULL
      LEFT JOIN UT_SESSION_STATES SS ON SS.STATE_ID = S.STATE_ID
      LEFT JOIN UT_EXAM_TEST_VARS ETV ON ETV.OBJ_ID = S.VARIANT_ID
      LEFT JOIN UT_TEST_VARS TV ON TV.OBJ_ID = ETV.TEST_VAR_ID
      LEFT JOIN CJ2_MARK_TYPE MT ON MT.MARK_TYPE_ID = S.FINAL_RESULT_ID
      WHERE PA.EXAM_ID = :I$OBJ_ID AND PA.DATE_DEL IS NULL AND (:V$DB_LEVEL = 0) AND (1 = 1)
      ORDER BY OBJ.TYPE_ID, C.CAPTION, PA.PERSON_ID
      INTO :V$PERSON_ID, :V$PERSON_NAME, :V$SESSION_ID, :V$STATE_ID, :V$STATE_NAME, :V$VAR_NUM, :V$DATE_START, :V$DATE_END, :V$DURATION,
          :V$RAW_RESULT, :V$RESULT_ID, :V$RESULT_NAME
  DO
  BEGIN

      TAG_NAME = 'data:m';
      VAL = NULL;
      SUSPEND;

      TAG_NAME = 'data:m:person_id';
      VAL = V$PERSON_ID;
      SUSPEND;

      TAG_NAME = 'data:m:person_name';
      VAL = V$PERSON_NAME;
      SUSPEND;

      TAG_NAME = 'data:m:session_id';
      VAL = V$SESSION_ID;
      SUSPEND;

      TAG_NAME = 'data:m:session_state_id';
      VAL = V$STATE_ID;
      SUSPEND;

      TAG_NAME = 'data:m:session_state_name';
      VAL = V$STATE_NAME;
      SUSPEND;

      TAG_NAME = 'data:m:variant_num';
      VAL = V$VAR_NUM;
      SUSPEND;

      TAG_NAME = 'data:m:date_start';
      VAL = V$DATE_START;
      SUSPEND;

      TAG_NAME = 'data:m:date_end';
      VAL = V$DATE_END;
      SUSPEND;

      TAG_NAME = 'data:m:time_pass';
      IF(V$DATE_START IS NULL OR V$DATE_END IS NULL OR V$DATE_END < V$DATE_START) THEN VAL = '';
      ELSE BEGIN
          V$DURATION = V$DURATION / 60;
          IF(V$DURATION < 300) THEN VAL = V$DURATION || ' мин';
          ELSE VAL = TRUNC(V$DURATION / 60) || ' час ' || (V$DURATION - TRUNC(V$DURATION / 60) * 60) || ' мин';
      END
      SUSPEND;

      TAG_NAME = 'data:m:progress';
      VAL = '';
      SUSPEND;

      TAG_NAME = 'data:m:raw_result';
      VAL = V$RAW_RESULT;
      SUSPEND;

      TAG_NAME = 'data:m:final_result_id';
      VAL = V$RESULT_ID;
      SUSPEND;

      TAG_NAME = 'data:m:final_result_name';
      VAL = V$RESULT_NAME;
      SUSPEND;

  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_EXAM_DROP (
    I$EXAM_ID BIGINT)
AS
begin

   DELETE FROM UT_SESSIONS
   WHERE ED_ID = :I$EXAM_ID;

   DELETE FROM UT_EXAM_TEST_VARS
   WHERE EXAM_ID = :I$EXAM_ID;

   DELETE FROM UT_EXAM_DATES
   WHERE OBJ_ID = :I$EXAM_ID;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_EXAM_EXPERT_ASSN_SET (
    I$EXAM_ID BIGINT,
    I$EXPERT_ID BIGINT,
    I$ROLE_ID INTEGER,
    I$SECOND_CHECK INTEGER,
    I$USER_ID VARCHAR(40),
    I$OP SMALLINT)
RETURNS (
    OBJ_ID BIGINT,
    EXAM_ID BIGINT,
    EXAM_NAME VARCHAR(200),
    EXAM_DATE DATE,
    STATE INTEGER,
    ROLE_ID INTEGER,
    ROLE_NAME VARCHAR(200),
    SECOND_CHECK SMALLINT)
AS
declare variable V$DATE_DEL timestamp;
declare variable V$ROLE_ID integer;
declare variable V$SECOND_CHECK integer;
BEGIN

  -- I$OP - тип операции: 0 = обновить, 1 = добавить, 2 = удалить

  SELECT D.OBJ_ID, D.EXAM_DATE_START, D.OBJ_NAME, D.EXAM_STATE
  FROM UT_EXAM_DATES D
  WHERE D.OBJ_ID = :I$EXAM_ID AND D.DATE_DEL IS NULL
  INTO :EXAM_ID, :EXAM_DATE, :EXAM_NAME, :STATE;

  IF(EXAM_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Тестирование не найдено или было было удалено';
  IF(STATE < 300 OR STATE > 900) THEN EXCEPTION DATA_ERROR 'Для назначения экспертов статус должен быть не ниже: Планирование персонала, и не выше: Экспертная проверка';

  IF(I$OP IN (0, 1)) THEN
  BEGIN

      SELECT FIRST 1 OBJ_ID, DATE_DEL, ROLE_ID, SECOND_CHECK
      FROM UT_EXAM_EXPERT_ASSN
      WHERE EXAM_ID = :I$EXAM_ID AND EXPERT_ID = :I$EXPERT_ID
      INTO :OBJ_ID, :V$DATE_DEL, :V$ROLE_ID, :V$SECOND_CHECK;

      IF(OBJ_ID IS NULL) THEN
      BEGIN

          INSERT INTO UT_EXAM_EXPERT_ASSN
          (EXAM_ID, EXPERT_ID, ROLE_ID, SECOND_CHECK)
          VALUES (:I$EXAM_ID, :I$EXPERT_ID, :I$ROLE_ID, :I$SECOND_CHECK)
          RETURNING OBJ_ID INTO :OBJ_ID;

      END
      ELSE IF(V$DATE_DEL IS NOT NULL) THEN
      BEGIN

          -- Восстанавливаем удаление
          UPDATE UT_EXAM_EXPERT_ASSN
          SET DATE_DEL = NULL, DATE_MODIFY = CURRENT_TIMESTAMP, ROLE_ID = :I$ROLE_ID, SECOND_CHECK = :I$SECOND_CHECK
          WHERE OBJ_ID = :OBJ_ID;

      END
      ELSE IF(V$ROLE_ID <> I$ROLE_ID OR V$SECOND_CHECK <> I$SECOND_CHECK) THEN
      BEGIN

          -- Коррекктируем по необходимости существующую запись
          UPDATE UT_EXAM_EXPERT_ASSN
          SET DATE_MODIFY = CURRENT_TIMESTAMP, ROLE_ID = :I$ROLE_ID, SECOND_CHECK = :I$SECOND_CHECK
          WHERE OBJ_ID = :OBJ_ID;

      END

      ROLE_ID = I$ROLE_ID;
      ROLE_NAME = (SELECT OBJ_NAME FROM UT_EXPERT_ROLES WHERE OBJ_ID = :I$ROLE_ID);
      SECOND_CHECK = I$SECOND_CHECK;

  END
  ELSE
  BEGIN

      UPDATE UT_EXAM_EXPERT_ASSN
      SET DATE_DEL = CURRENT_TIMESTAMP, DATE_MODIFY = CURRENT_TIMESTAMP
      WHERE EXAM_ID = :I$EXAM_ID AND EXPERT_ID = :I$EXPERT_ID AND DATE_DEL IS NULL;

  END

  SUSPEND;

END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_EXAM_EXPORT_DESC RETURNS (
    USER_LEVEL INTEGER,
    LEVEL_ID BIGINT,
    LEVEL_NAME VARCHAR(400))
AS
begin

  SELECT COALESCE(CAST(K.KEY_VAL AS INTEGER) - 1, 0)
  FROM KEYS K
  WHERE K.KEY_CODE = 'LEVEL'
  INTO :USER_LEVEL;

  -- Получаем наш домашний уровень (ОУ, район, регион), и его название
  IF(USER_LEVEL = 0) THEN
  BEGIN
      SELECT FIRST 1 L2.OBJ_ID, V2.VAL
      FROM LINKS L2
      LEFT JOIN VALS V2 ON V2.OBJ_ID = L2.OBJ_ID AND V2.PARAM_ID = 2 AND V2.IS_DEL = 0
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      INTO :LEVEL_ID, :LEVEL_NAME;
  END
  ELSE IF(USER_LEVEL = 1) THEN
  BEGIN
      SELECT FIRST 1 V665.LISTVAL_ID, R.VAL
      FROM LINKS L111
      JOIN VALL V665 ON V665.OBJ_ID = L111.OBJ_ID AND V665.PARAM_ID = 665 AND V665.IS_DEL = 0
      JOIN LISTVALS LV ON LV.LISTVAL_ID = V665.LISTVAL_ID
      JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
      WHERE L111.PARENT_ID IS NULL AND L111.OBJ_TYPE_ID = 111 AND L111.DATE_DEL IS NULL
      INTO :LEVEL_ID, :LEVEL_NAME;
  END
  ELSE IF(USER_LEVEL = 2) THEN
  BEGIN
      LEVEL_NAME = 'Регион';
  END
  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_EXAM_FILE_ACCESS (
    I$EXAM_ID BIGINT,
    I$PACKET_ID BIGINT,
    I$FILE_ID VARCHAR(40),
    I$USER_ID VARCHAR(40),
    I$MODE SMALLINT = 0)
RETURNS (
    OBJ_ID BIGINT,
    TEMPLATE_ID BIGINT,
    BLANK_TYPE SMALLINT,
    SIDE SMALLINT)
AS
declare variable V$EXAM_STATE integer;
declare variable V$PACKET_STATE integer;
declare variable V$FILE_STATE integer;
begin

  -- MODE: 0 = просмотр файла (FILE_ID = имя файла), 1 = загрузка распознанных результатов (FILE_ID -> OBJ_ID)

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  IF(I$MODE = 0) THEN
  BEGIN

      SELECT FIRST 1 D.EXAM_STATE, P.STATE_ID, B.STATE_ID, B.OBJ_ID, B.BLANK_SIDE, PT.BLANK_TYPE, PT.OBJ_ID
      FROM UT_PACKAGES P
      JOIN UT_EXAM_DATES D ON D.OBJ_ID = P.ED_ID AND D.DATE_DEL IS NULL
      JOIN UT_BLANKS B ON B.PACKAGE_ID = P.OBJ_ID AND B.DATE_DEL IS NULL AND B.FILE_ID = :I$FILE_ID
      JOIN UT_PAGE_TEMPLATES PT ON PT.OBJ_ID = B.BLANK_TYPE
      WHERE P.DATE_DEL IS NULL AND P.OBJ_ID = :I$PACKET_ID
      INTO :V$EXAM_STATE, :V$PACKET_STATE, :V$FILE_STATE, :OBJ_ID, :SIDE, :BLANK_TYPE, :TEMPLATE_ID;

  END
  ELSE IF(I$MODE = 1) THEN
  BEGIN

      SELECT FIRST 1 D.EXAM_STATE, P.STATE_ID, B.STATE_ID, B.OBJ_ID, B.BLANK_SIDE, PT.BLANK_TYPE, PT.OBJ_ID
      FROM UT_PACKAGES P
      JOIN UT_EXAM_DATES D ON D.OBJ_ID = P.ED_ID AND D.DATE_DEL IS NULL
      JOIN UT_BLANKS B ON B.PACKAGE_ID = P.OBJ_ID AND B.DATE_DEL IS NULL AND B.OBJ_ID = :I$FILE_ID
      JOIN UT_PAGE_TEMPLATES PT ON PT.OBJ_ID = B.BLANK_TYPE
      WHERE P.DATE_DEL IS NULL AND P.OBJ_ID = :I$PACKET_ID
      INTO :V$EXAM_STATE, :V$PACKET_STATE, :V$FILE_STATE, :OBJ_ID, :SIDE, :BLANK_TYPE, :TEMPLATE_ID;

  END

  IF(OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Файл работы не найден';
  -- !!! Статусы

  -- Кидаем исключение, если пытается получить доступ неправильный пользователь
  -- !!!

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_EXAM_FILE_FINISH (
    I$OBJ_ID BIGINT)
RETURNS (
    STUB INTEGER)
AS
declare variable V$PACKAGE_ID bigint;
declare variable V$STATE integer;
begin

  SELECT B.PACKAGE_ID, B.STATE_ID
  FROM UT_BLANKS B
  WHERE B.OBJ_ID = :I$OBJ_ID AND B.DATE_DEL IS NULL
  INTO :V$PACKAGE_ID, :V$STATE;

  IF(V$STATE IS NULL) THEN EXCEPTION DATA_ERROR 'Бланк не найден';
  IF(V$STATE <> 10) THEN EXCEPTION DATA_ERROR 'Бланк не в статусе обработки';

  -- Все ли обязательные атрибуты установлены
  -- Для бланков типа C+ проверяем сшивку бланков в пакет

  UPDATE UT_BLANKS B
  SET B.STATE_ID = 11, B.DATE_MODIFY = CURRENT_TIMESTAMP
  WHERE B.OBJ_ID = :I$OBJ_ID;

  -- Если еще остались неразобранные файлы, выходим
  IF(EXISTS(
      SELECT FIRST 1 1
      FROM UT_BLANKS BX
      WHERE BX.PACKAGE_ID = :V$PACKAGE_ID AND BX.DATE_DEL IS NULL AND BX.STATE_ID NOT IN (10, 11, 12)
  )) THEN EXIT;

  -- Хотя тут по идее надо бы проверять статус 9
  UPDATE UT_PACKAGES P
  SET P.STATE_ID = 10, P.DATE_MODIFY = CURRENT_TIMESTAMP
  WHERE P.OBJ_ID = :V$PACKAGE_ID;

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_EXAM_FILE_RESULT_SET (
    I$OBJ_ID BIGINT,
    I$PARAM_ID VARCHAR(40),
    I$VALUE VARCHAR(100))
RETURNS (
    STUB INTEGER)
AS
declare variable V$OBJ_ID bigint;
begin

  SELECT FIRST 1 A.OBJ_ID
  FROM UT_BLANK_ATTRS A
  WHERE A.BLANK_ID = :I$OBJ_ID AND A.ATTR_NAME = :I$PARAM_ID AND A.DATE_DEL IS NULL
  INTO :V$OBJ_ID;

  IF(V$OBJ_ID IS NULL) THEN
  BEGIN
      INSERT INTO UT_BLANK_ATTRS
      (BLANK_ID, ATTR_NAME, DATE_DEL, ATTR_VALUE, SRC_VALUE)
      VALUES (:I$OBJ_ID, :I$PARAM_ID, NULL, :I$VALUE, :I$VALUE);
  END
  ELSE
  BEGIN
      UPDATE UT_BLANK_ATTRS
      SET ATTR_VALUE = :I$VALUE, SRC_VALUE = :I$VALUE
      WHERE OBJ_ID = :V$OBJ_ID;
  END

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_EXAM_FILE_SETBC (
    I$EXAM_ID BIGINT,
    I$PACKET_ID BIGINT,
    I$FILE_ID VARCHAR(40),
    I$USER_ID VARCHAR(40),
    I$BC1 VARCHAR(128),
    I$BC2 VARCHAR(128),
    I$BC3 VARCHAR(128))
RETURNS (
    STUB INTEGER)
AS
begin


  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_EXAM_FORSCAN_LIST (
    I$USER_ID VARCHAR(40))
RETURNS (
    EXAM_ID BIGINT,
    EXAM_NAME VARCHAR(200),
    SUBJECT_ID BIGINT,
    SUBJECT_NAME VARCHAR(200),
    EXAM_STATE INTEGER,
    EXAM_STATE_NAME VARCHAR(200),
    EXAM_DATE DATE)
AS
declare variable V$DB_LEVEL bigint;
declare variable V$OUR_ORG bigint;
begin

  -- Выбираем тестирования, доступные в статусе 800, и предусматривающие загрузку бланков как таковую
  -- Для сотрудников, ведущих валидацию, проверяем права доступа

  SELECT COALESCE(CAST(K.KEY_VAL AS INTEGER) - 1, 0)
  FROM KEYS K
  WHERE K.KEY_CODE = 'LEVEL'
  INTO :V$DB_LEVEL;

  SELECT FIRST 1 L2.OBJ_ID
  FROM LINKS L2
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$OUR_ORG;

  FOR
      SELECT D.OBJ_ID, D.OBJ_NAME, D.SUBJECT_ID, COALESCE(VS.VAL, 'Метапредмет'), D.EXAM_STATE, ES.OBJ_NAME, D.EXAM_DATE_START
      FROM UT_EXAM_DATES D
      JOIN UT_EXAM_STATES ES ON ES.OBJ_ID = D.EXAM_STATE
      LEFT JOIN UT_EXAM_OU_ASSN EA ON EA.DATE_DEL IS NULL AND EA.EXAM_ID = D.OBJ_ID AND (EA.OU_ID = 0 OR EA.OU_ID = :V$OUR_ORG OR :V$DB_LEVEL > 0)
      LEFT JOIN VALS VS ON VS.OBJ_ID = D.SUBJECT_ID AND VS.PARAM_ID = 376 AND VS.IS_DEL = 0
      WHERE D.DATE_DEL IS NULL AND D.METHOD_ID = 2 AND D.EXAM_STATE IN (600, 700, 800, 900)
          AND D.H_LEVEL >= :V$DB_LEVEL AND (EA.OBJ_ID IS NOT NULL OR D.ORG_REF = :V$OUR_ORG)
      ORDER BY D.EXAM_DATE_START, D.OBJ_NAME
      INTO :EXAM_ID, :EXAM_NAME, :SUBJECT_ID, :SUBJECT_NAME, :EXAM_STATE, :EXAM_STATE_NAME, :EXAM_DATE
  DO
  BEGIN
      SUSPEND;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_EXAM_FORVERIFY_LIST (
    I$USER_ID VARCHAR(40))
RETURNS (
    EXAM_ID BIGINT,
    EXAM_NAME VARCHAR(200),
    SUBJECT_ID BIGINT,
    SUBJECT_NAME VARCHAR(200),
    EXAM_STATE INTEGER,
    EXAM_STATE_NAME VARCHAR(200),
    EXAM_DATE DATE,
    N_BLANKS INTEGER)
AS
declare variable V$DB_LEVEL integer;
begin

  -- Выбираем тестирования, доступные в статусе 800, и предусматривающие загрузку бланков как таковую
  -- Для сотрудников, ведущих валидацию, проверяем права доступа

  SELECT COALESCE(CAST(K.KEY_VAL AS INTEGER) - 1, 0)
  FROM KEYS K
  WHERE K.KEY_CODE = 'LEVEL'
  INTO :V$DB_LEVEL;

  FOR
      SELECT D.OBJ_ID, D.OBJ_NAME, D.SUBJECT_ID, COALESCE(VS.VAL, 'Метапредмет'), D.EXAM_STATE, ES.OBJ_NAME, D.EXAM_DATE_START
      FROM UT_EXAM_DATES D
      JOIN UT_EXAM_STATES ES ON ES.OBJ_ID = D.EXAM_STATE
      LEFT JOIN VALS VS ON VS.OBJ_ID = D.SUBJECT_ID AND VS.PARAM_ID = 376 AND VS.IS_DEL = 0
      WHERE D.DATE_DEL IS NULL AND D.METHOD_ID = 2 AND D.EXAM_STATE IN (600, 700, 800, 900) AND D.H_LEVEL = :V$DB_LEVEL
      ORDER BY D.EXAM_DATE_START, D.OBJ_NAME
      INTO :EXAM_ID, :EXAM_NAME, :SUBJECT_ID, :SUBJECT_NAME, :EXAM_STATE, :EXAM_STATE_NAME, :EXAM_DATE
  DO
  BEGIN

      SELECT COUNT(*)
      FROM UT_PACKAGES P
      JOIN UT_BLANKS B ON B.PACKAGE_ID = P.OBJ_ID AND B.DATE_DEL IS NULL AND B.STATE_ID IN (11, 12)
      WHERE P.ED_ID = :EXAM_ID AND P.DATE_DEL IS NULL
      INTO :N_BLANKS;

      SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_EXAM_KEYS_APPLY (
    I$EXAM_ID BIGINT,
    I$QUESTION_ID BIGINT,
    I$TEXT VARCHAR(100),
    I$STATE SMALLINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    STUB INTEGER)
AS
declare variable V$Q_ID bigint;
declare variable V$SQ_ID bigint;
declare variable V$DB_LEVEL integer;
declare variable V$STATE integer;
declare variable V$H_LEVEL integer;
declare variable V$MAX_SCORE integer;
declare variable V$TYPE smallint;
begin

  -- Пересчитать результаты можно только на уровне тестирования
  SELECT COALESCE(CAST(K.KEY_VAL AS INTEGER) - 1, 0)
  FROM KEYS K
  WHERE K.KEY_CODE = 'LEVEL'
  INTO :V$DB_LEVEL;

  SELECT FIRST 1 D.EXAM_STATE, D.H_LEVEL
  FROM UT_EXAM_DATES D
  WHERE D.OBJ_ID = :I$EXAM_ID AND D.DATE_DEL IS NULL
  INTO :V$STATE, :V$H_LEVEL;

  IF(V$STATE IS NULL) THEN EXCEPTION DATA_ERROR 'Тестирование не найдено или было удалено';
  --IF(V$STATE < 800 OR V$STATE >= 1000) THEN EXCEPTION DATA_ERROR 'Тестирование находится в недопустимом статусе';
  IF(V$DB_LEVEL <> V$H_LEVEL) THEN EXCEPTION DATA_ERROR 'Управление результатами возможно только на уровне владельца тестирования';

  SELECT Q.OBJ_ID, Q.QUESTION_TYPE, Q.MAX_SCORE
  FROM UT_TEST_VAR_QUESTIONS TVQ
  JOIN UT_QUESTIONS Q ON Q.OBJ_ID = TVQ.QUESTION_ID
  WHERE TVQ.OBJ_ID = :I$QUESTION_ID
  INTO :V$Q_ID, :V$TYPE, :V$MAX_SCORE;

  IF(V$TYPE = 1) THEN
  BEGIN

      IF(EXISTS(
          SELECT FIRST 1 1
          FROM UT_ANSWERS A
          WHERE A.DATE_DEL IS NULL AND A.QUESTION_ID = :V$Q_ID AND CAST(A.SORT_ORDER AS VARCHAR(10)) = :I$TEXT
      )) THEN EXIT;

      FOR
          SELECT SQ.OBJ_ID
          FROM UT_SESSIONS S
          JOIN UT_SESSION_QUESTIONS SQ ON SQ.DATE_DEL IS NULL AND SQ.SESSION_ID = S.OBJ_ID AND SQ.QUESTION_ID = :I$QUESTION_ID AND SQ.ANSWER_DATA = :I$TEXT
          WHERE S.DATE_DEL IS NULL AND S.ED_ID = :I$EXAM_ID
          INTO :V$SQ_ID
      DO
      BEGIN
          UPDATE UT_SESSION_QUESTIONS SQ
          SET SQ.RAW_RESULT = IIF(:I$STATE = 0, 0, :V$MAX_SCORE)
          WHERE SQ.OBJ_ID = :V$SQ_ID;
      END

  END
  ELSE IF(V$TYPE = 2) THEN
  BEGIN

      IF(EXISTS(
          SELECT FIRST 1 1
          FROM UT_ANSWERS A
          WHERE A.DATE_DEL IS NULL AND A.QUESTION_ID = :V$Q_ID AND CAST(A.VARIANT AS VARCHAR(1000)) = :I$TEXT
      )) THEN EXIT;

      FOR
          SELECT SQ.OBJ_ID
          FROM UT_SESSIONS S
          JOIN UT_SESSION_QUESTIONS SQ ON SQ.DATE_DEL IS NULL AND SQ.SESSION_ID = S.OBJ_ID AND SQ.QUESTION_ID = :I$QUESTION_ID AND SQ.ANSWER_DATA = :I$TEXT
          WHERE S.DATE_DEL IS NULL AND S.ED_ID = :I$EXAM_ID
          INTO :V$SQ_ID
      DO
      BEGIN
          UPDATE UT_SESSION_QUESTIONS SQ
          SET SQ.RAW_RESULT = IIF(:I$STATE = 0, 0, :V$MAX_SCORE)
          WHERE SQ.OBJ_ID = :V$SQ_ID;
      END

  END
  ELSE IF(V$TYPE = 4) THEN
  BEGIN
  END

  IF(0 = 1) THEN SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_EXAM_MON_LIST (
    I$USER_ID VARCHAR(40))
RETURNS (
    EXAM_ID BIGINT,
    EXAM_NAME VARCHAR(200),
    EXAM_DATE DATE,
    SUBJECT_ID BIGINT,
    SUBJECT_NAME VARCHAR(200),
    EXAM_STATE INTEGER,
    EXAM_STATE_NAME VARCHAR(200),
    METHOD_ID INTEGER)
AS
begin

  FOR
      SELECT D.OBJ_ID, D.OBJ_NAME, D.SUBJECT_ID, COALESCE(VS.VAL, 'Метапредмет'), D.EXAM_STATE, ES.OBJ_NAME, D.METHOD_ID, D.EXAM_DATE_START
      FROM UT_EXAM_DATES D
      JOIN UT_EXAM_STATES ES ON ES.OBJ_ID = D.EXAM_STATE
      LEFT JOIN VALS VS ON VS.OBJ_ID = D.SUBJECT_ID AND VS.PARAM_ID = 376 AND VS.IS_DEL = 0
      WHERE D.DATE_DEL IS NULL AND D.EXAM_STATE > 0 AND D.EXAM_STATE < 1000
        AND D.EXAM_DAY_TYPE <> 100 -- без олимпиад
      ORDER BY D.EXAM_DATE_START, D.OBJ_NAME
      INTO :EXAM_ID, :EXAM_NAME, :SUBJECT_ID, :SUBJECT_NAME, :EXAM_STATE, :EXAM_STATE_NAME, :METHOD_ID, :EXAM_DATE
  DO
  BEGIN
      SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_EXAM_OLYMPIC_DEL (
    I$OBJ_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$YEAR_ID bigint;
declare variable V$Y integer;
declare variable V$CY integer;
begin

  -- Экзамены мы вообще не удаляем, а переставляем статус в черновик

  SELECT FIRST 1 V.LISTVAL_ID, V.COST
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS V ON V.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$YEAR_ID, :V$Y;

  IF(V$YEAR_ID IS NULL) THEN EXIT;

  V$CY = EXTRACT(YEAR FROM CURRENT_DATE);
  IF(EXTRACT(MONTH FROM CURRENT_DATE) < 9) THEN V$CY = V$CY - 1;

  -- В августе запись на олимпиады вообще неактивна
  IF(EXTRACT(MONTH FROM CURRENT_DATE) = 8) THEN EXIT;
  IF(V$CY <> V$Y) THEN EXIT;

  UPDATE UT_EXAM_DATES
  SET EXAM_STATE = 0
  --DATE_DEL = CURRENT_TIMESTAMP
  WHERE OBJ_ID = :I$OBJ_ID AND DATE_DEL IS NULL AND EXAM_DAY_TYPE = 100 AND PERIOD_ID = :V$YEAR_ID AND EXAM_STATE = 100;

  OBJ_ID = I$OBJ_ID;
  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_EXAM_OLYMPIC_LIST (
    I$VERSION VARCHAR(100) = null)
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$YEAR_ID bigint;
declare variable V$Y integer;
declare variable V$CY integer;
begin

  SELECT FIRST 1 V.LISTVAL_ID, V.COST
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS V ON V.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$YEAR_ID, :V$Y;

  IF(V$YEAR_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не настроена образовательная организация или учебный год';

  V$CY = EXTRACT(YEAR FROM CURRENT_DATE);
  IF(EXTRACT(MONTH FROM CURRENT_DATE) < 9) THEN V$CY = V$CY - 1;

  -- В августе запись на олимпиады вообще неактивна
  IF(EXTRACT(MONTH FROM CURRENT_DATE) = 8 AND (I$VERSION IS NULL OR I$VERSION = 'paragraf')) THEN EXCEPTION DATA_ERROR 'В августе запись на олимпиады закрыта';
  IF(V$CY <> V$Y AND (I$VERSION IS NULL OR I$VERSION = 'paragraf')) THEN EXCEPTION DATA_ERROR 'Запись на олимпиады возможна только после открытия учебного года';

  -- Возвращаем олимпиады, у которых стоит статус действующей
  FOR
    SELECT D.OBJ_ID
    FROM UT_EXAM_DATES D
    WHERE D.DATE_DEL IS NULL AND D.EXAM_DAY_TYPE = 100 AND D.PERIOD_ID = :V$YEAR_ID AND D.EXAM_STATE = 100
    INTO :OBJ_ID
  DO
  BEGIN
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_EXAM_OLYMPIC_RES (
    I$REG_ID VARCHAR(100),
    I$OD_ID VARCHAR(100),
    I$OD_NAME VARCHAR(400),
    I$SUBJECT_ID BIGINT,
    I$PLAN_ID VARCHAR(100),
    I$DATE_FROM DATE,
    I$DATE_TO DATE,
    I$PERIOD_ID VARCHAR(100),
    I$LEVEL SMALLINT,
    I$STAGE_ID VARCHAR(100),
    I$RESULT_ID BIGINT,
    I$RESULT_VAL VARCHAR(100),
    I$RESULT_RATE VARCHAR(100))
RETURNS (
    OBJ_ID BIGINT)
AS
DECLARE VARIABLE V$STAGE_ID BIGINT;
DECLARE VARIABLE V$PERSON_ID BIGINT;
DECLARE VARIABLE V$LEVEL_ID BIGINT;
DECLARE VARIABLE V$ALEVEL_ID BIGINT;
DECLARE VARIABLE V$RESULT_ID BIGINT;
DECLARE VARIABLE S$RESULT_ID VARCHAR(100);
DECLARE VARIABLE V$NAME VARCHAR(1000);
DECLARE VARIABLE T INTEGER;
begin

  -- N класс - перекодируем в id этапа
  I$STAGE_ID = UPPER(I$STAGE_ID);
  IF(POSITION(' ' IN I$STAGE_ID) > 0) THEN I$STAGE_ID = SUBSTRING(I$STAGE_ID FROM 1 FOR POSITION(' ' IN I$STAGE_ID) - 1);

  SELECT FIRST 1 LV.LISTVAL_ID
  FROM LISTVALS LV
  WHERE LV.IS_DEL = 0 AND LV.LIST_ID = 25 AND LV.PARENT_ID = 2141 AND LV.TAG = :I$STAGE_ID
  INTO :V$STAGE_ID;

  -- Обновляем только действующих персон
  I$REG_ID = UPPER(I$REG_ID);
  SELECT FIRST 1 V2912.OBJ_ID
  FROM VALS V2912
  JOIN LINKS LP ON LP.OBJ_ID = V2912.OBJ_ID AND LP.PARENT_TYPE_ID IN (9, 187, 290) AND LP.DATE_DEL IS NULL
  WHERE V2912.PARAM_ID = 2912 AND UPPER(SUBSTRING(V2912.SVAL FROM 1 FOR 36)) = :I$REG_ID AND V2912.IS_DEL = 0
  INTO :V$PERSON_ID;

  IF(V$PERSON_ID IS NULL) THEN EXIT;

  S$RESULT_ID = I$RESULT_ID;
  SELECT FIRST 1 L22.OBJ_ID
  FROM LINKS L22
  JOIN VALS V2879 ON V2879.OBJ_ID = L22.OBJ_ID AND V2879.PARAM_ID = 2879 AND V2879.IS_DEL = 0 AND V2879.SVAL = :S$RESULT_ID
  WHERE L22.PARENT_ID = :V$PERSON_ID AND L22.OBJ_TYPE_ID = 22 AND L22.DATE_DEL IS NULL
  INTO :OBJ_ID;

  IF(I$SUBJECT_ID IS NULL) THEN V$NAME = 'Олимпиада (неизвестный предмет)';
  ELSE V$NAME = 'Олимпиада по ' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$SUBJECT_ID));

  -- Статус мероприятия
  -- Всегда всероссийский
  V$LEVEL_ID = 5292;

  -- Тур мероприятия, LEVEL нужно перевернуть
  I$LEVEL = 4 - I$LEVEL;
  IF(I$LEVEL = 0) THEN V$ALEVEL_ID = 18598; -- ОУ
  ELSE IF(I$LEVEL = 1) THEN V$ALEVEL_ID = 18599; -- Район
  ELSE IF(I$LEVEL = 2) THEN V$ALEVEL_ID = 18600; -- Регион
  ELSE IF(I$LEVEL = 3) THEN V$ALEVEL_ID = 18601; -- Всероссийский

  -- Результат
  -- Зачёт Незачёт Победитель Призёр Участник Опоздал Присутствовал Отсутствовал
  IF(I$RESULT_VAL = 'Участник' OR I$RESULT_VAL = 'Присутствовал') THEN V$RESULT_ID = 5281;
  ELSE IF(I$RESULT_VAL = 'Призёр') THEN V$RESULT_ID = 5282;
  ELSE IF(I$RESULT_VAL = 'Победитель') THEN V$RESULT_ID = 5283;

  IF(OBJ_ID IS NULL) THEN
  BEGIN
    SELECT OBJ_ID FROM OBJECT_ADD(:V$PERSON_ID, 22) INTO :OBJ_ID;
    SELECT 1 FROM VAL_ADD(2879, :OBJ_ID, :S$RESULT_ID) INTO :T;
  END
  ELSE
  BEGIN
    -- Ничего не надо
  END

  -- TODO сверять на факт изменений
    SELECT 1 FROM VAL_ADD(166, :OBJ_ID, :I$DATE_TO) INTO :T;
    SELECT 1 FROM VAL_ADD(1818, :OBJ_ID, :V$NAME) INTO :T;
    SELECT 1 FROM VAL_ADD(1819, :OBJ_ID, :V$LEVEL_ID) INTO :T;
    SELECT 1 FROM VAL_ADD(3533, :OBJ_ID, :V$ALEVEL_ID) INTO :T;
    SELECT 1 FROM VAL_ADD(3534, :OBJ_ID, :V$STAGE_ID) INTO :T;
    SELECT 1 FROM VAL_ADD(3539, :OBJ_ID, :I$SUBJECT_ID) INTO :T;
    SELECT 1 FROM VAL_ADD(237, :OBJ_ID, :V$RESULT_ID) INTO :T;
    SELECT 1 FROM VAL_ADD(3597, :OBJ_ID, :I$RESULT_RATE) INTO :T;
    SELECT 1 FROM VAL_ADD(167, :OBJ_ID, 'олимпиада') INTO :T;

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_EXAM_OLYMPIC_SET (
    I$YEAR_ID BIGINT,
    I$OD_ID VARCHAR(40),
    I$OD_NAME VARCHAR(1000),
    I$SUBJECT_ID BIGINT,
    I$PLAN_ID VARCHAR(40),
    I$DATE_FROM DATE,
    I$DATE_TO DATE,
    I$PERIOD_ID VARCHAR(40),
    I$LEVEL SMALLINT,
    I$GRADE_MASK INTEGER)
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$SIG varchar(200);
declare variable V$LEVEL_NAME varchar(100);
declare variable V$YEAR_ID bigint;
declare variable V$Y integer;
declare variable V$CY integer;
declare variable V$NULL date;
begin

  -- YEAR_ID заложен для потенциального расширения, пока никак не используем
  -- OD_ID, PLAN_ID, PERIOD_ID при изменениях обнуляют старые данные, поля берем не id, а uid
  -- PROGRAM - это мероприятие как таковое (+название +предмет)
  -- PLAN - это собственно период планирования (даты начала и окончания)
  -- PERIOD - это тур (школа-район-регион-страна)
  -- LEVEL - код этапа (ОУ...страна), к нему уже относится битовая маска параллелей

  SELECT FIRST 1 V.LISTVAL_ID, V.COST
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS V ON V.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$YEAR_ID, :V$Y;

  IF(V$YEAR_ID IS NULL) THEN EXIT;

  -- Олимпиады начинают публиковать уже в августе, поэтому новый год также считаем с августа
  V$CY = EXTRACT(YEAR FROM CURRENT_DATE);
  IF(EXTRACT(MONTH FROM CURRENT_DATE) < 8) THEN V$CY = V$CY - 1;

  -- В августе запись на олимпиады вообще неактивна
  IF(EXTRACT(MONTH FROM CURRENT_DATE) = 8 AND (I$YEAR_ID IS NULL OR I$YEAR_ID <> -1)) THEN EXIT;
  IF(V$CY <> V$Y) THEN EXIT;

  V$SIG = I$OD_ID || ';' || I$PLAN_ID || ';' || I$PERIOD_ID;

  SELECT FIRST 1 D.OBJ_ID
  FROM UT_EXAM_DATES D
  WHERE D.DATE_DEL IS NULL AND D.EXAM_DAY_TYPE = 100 AND D.PERIOD_ID = :V$YEAR_ID AND D.LINK_HASH = :V$SIG
  INTO :OBJ_ID;

  -- LEVEL нужно перевернуть
  I$LEVEL = 4 - I$LEVEL;

  IF(I$LEVEL = 0) THEN V$LEVEL_NAME = 'школьный тур';
  ELSE IF(I$LEVEL = 1) THEN V$LEVEL_NAME = 'районный тур';
  ELSE IF(I$LEVEL = 2) THEN V$LEVEL_NAME = 'региональный тур';
  ELSE IF(I$LEVEL = 3) THEN V$LEVEL_NAME = 'всероссийский тур';
  ELSE EXCEPTION DATA_ERROR 'Неизвестный код уровня олимпиады';

  I$OD_NAME = I$OD_NAME || ' - ' || V$LEVEL_NAME;

  IF(OBJ_ID IS NULL) THEN
  BEGIN

    -- Регистрируем новую олимпиаду
    INSERT INTO UT_EXAM_DATES
    (OBJ_NAME, SUBJECT_ID, STAGE_ID, EXAM_DATE_START, EXAM_DATE_END, EXAM_DAY_TYPE, EXAM_STATE, METHOD_ID, PLAN_METHOD_ID, H_LEVEL, ORG_REF, PERIOD_ID, LINK_HASH, LINK_MASK)
    VALUES (:I$OD_NAME, :I$SUBJECT_ID, 20, :I$DATE_FROM, :I$DATE_TO, 100, 100, 4, 2, :I$LEVEL, NULL, :V$YEAR_ID, :V$SIG, :I$GRADE_MASK)
    RETURNING OBJ_ID INTO :OBJ_ID;

  END
  ELSE
  BEGIN

    -- Обновляем данные по существующей
    V$NULL = CAST('01.01.2000' AS DATE);

    UPDATE UT_EXAM_DATES
    SET OBJ_NAME = :I$OD_NAME, SUBJECT_ID = :I$SUBJECT_ID, EXAM_DATE_START = :I$DATE_FROM, EXAM_DATE_END = :I$DATE_TO,
      H_LEVEL = :I$LEVEL, LINK_MASK = :I$GRADE_MASK, EXAM_STATE = 100
    WHERE OBJ_ID = :OBJ_ID AND (OBJ_NAME <> :I$OD_NAME OR SUBJECT_ID <> :I$SUBJECT_ID OR H_LEVEL <> :I$LEVEL OR LINK_MASK <> :I$GRADE_MASK
      OR EXAM_STATE <> 100 OR COALESCE(EXAM_DATE_START, :V$NULL) <> COALESCE(:I$DATE_FROM, :V$NULL)
      OR COALESCE(EXAM_DATE_END, :V$NULL) <> COALESCE(:I$DATE_TO, :V$NULL));

  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_EXAM_OU_ASSN_SET (
    I$EXAM_ID BIGINT,
    I$OU_ID BIGINT,
    I$USER_ID VARCHAR(40),
    I$OP SMALLINT)
RETURNS (
    OBJ_ID BIGINT)
AS
DECLARE VARIABLE V$STATE INTEGER;
DECLARE VARIABLE V$DATE_DEL TIMESTAMP;
begin

  -- I$OP - тип операции: 0 = обновить, 1 = добавить, 2 = удалить

  SELECT D.EXAM_STATE
  FROM UT_EXAM_DATES D
  WHERE D.OBJ_ID = :I$EXAM_ID AND D.DATE_DEL IS NULL
  INTO :V$STATE;

  IF(V$STATE IS NULL) THEN EXCEPTION DATA_ERROR 'Тестирование не найдено или было удалено';
  IF(V$STATE >= 700) THEN EXCEPTION DATA_ERROR 'Недопустимый статус тестирования для назначения ОУ';

  IF(I$OP IN (0, 1)) THEN
  BEGIN
    SELECT FIRST 1 OBJ_ID, DATE_DEL
    FROM UT_EXAM_OU_ASSN
    WHERE EXAM_ID = :I$EXAM_ID AND OU_ID = :I$OU_ID
    INTO :OBJ_ID, :V$DATE_DEL;

    IF(OBJ_ID IS NULL) THEN
    BEGIN
      INSERT INTO UT_EXAM_OU_ASSN
      (EXAM_ID, OU_ID)
      VALUES (:I$EXAM_ID, :I$OU_ID)
      RETURNING OBJ_ID INTO :OBJ_ID;
    END
    ELSE IF(V$DATE_DEL IS NOT NULL) THEN
    BEGIN
      -- Восстанавливаем удаление
      UPDATE UT_EXAM_OU_ASSN
      SET DATE_DEL = NULL, DATE_MODIFY = CURRENT_TIMESTAMP
      WHERE OBJ_ID = :OBJ_ID;
    END
  END
  ELSE
  BEGIN
    UPDATE UT_EXAM_OU_ASSN
    SET DATE_DEL = CURRENT_TIMESTAMP, DATE_MODIFY = CURRENT_TIMESTAMP
    WHERE EXAM_ID = :I$EXAM_ID AND OU_ID = :I$OU_ID AND DATE_DEL IS NULL;
  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_EXAM_PACKET_DEL (
    I$EXAM_ID BIGINT,
    I$PACKET_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    OBJ_ID BIGINT,
    FILE_ID VARCHAR(40))
AS
declare variable V$PACKET_STATE integer;
begin

  -- Проверяем доступность
  SELECT P.STATE_ID
  FROM UT_PACKAGES P
  WHERE P.OBJ_ID = :I$PACKET_ID AND P.ED_ID = :I$EXAM_ID AND P.DATE_DEL IS NULL
  INTO :V$PACKET_STATE;

  IF(V$PACKET_STATE IS NULL) THEN EXCEPTION DATA_ERROR 'Пакет не найден или обработка пакета завершена, удалить пакет нельзя';
  IF(V$PACKET_STATE > 3 AND V$PACKET_STATE <= 10) THEN EXCEPTION DATA_ERROR 'Обработка пакета уже началась, удалить пакет нельзя';

  -- На всякий случай
  IF(EXISTS(
      SELECT FIRST 1 1
      FROM UT_BLANKS B
      WHERE B.DATE_DEL IS NULL AND B.PACKAGE_ID = :I$PACKET_ID AND B.STATE_ID IN (10)
  ))
  THEN EXCEPTION DATA_ERROR 'Уже начата обработка файлов пакета, удалить пакет нельзя';

  -- Удаляем сам пакет
  UPDATE UT_PACKAGES
  SET DATE_DEL = CURRENT_TIMESTAMP, DATE_MODIFY = CURRENT_TIMESTAMP
  WHERE OBJ_ID = :I$PACKET_ID AND DATE_DEL IS NULL;

  -- Выдаем ID всех файлов
  FOR
      SELECT B.OBJ_ID, B.FILE_ID
      FROM UT_BLANKS B
      WHERE B.PACKAGE_ID = :I$PACKET_ID AND B.DATE_DEL IS NULL
      INTO :OBJ_ID, :FILE_ID
  DO
  BEGIN
      SUSPEND;
  END

  -- Удаляем файлы пакета
  UPDATE UT_BLANKS
  SET DATE_DEL = CURRENT_TIMESTAMP, DATE_MODIFY = CURRENT_TIMESTAMP
  WHERE PACKAGE_ID = :I$PACKET_ID AND DATE_DEL IS NULL;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_EXAM_PACKET_FILE_DEL (
    I$EXAM_ID BIGINT,
    I$PACKET_ID BIGINT,
    I$FILE_ID VARCHAR(40),
    I$USER_ID VARCHAR(40))
RETURNS (
    DELETED SMALLINT)
AS
declare variable V$STATUS integer;
declare variable V$EXAM_ID bigint;
declare variable V$OBJ_ID bigint;
declare variable V$NEXT_ID bigint;
begin

  -- Проверяем существование и статус тестирования
  SELECT D.EXAM_STATE
  FROM UT_EXAM_DATES D
  WHERE D.OBJ_ID = :I$EXAM_ID AND D.DATE_DEL IS NULL
  INTO :V$STATUS;

  IF(V$STATUS IS NULL) THEN EXCEPTION DATA_ERROR 'Тестирование не найдено или было удалено другим пользователем';
  --IF(V$STATUS <= 600 OR V$STATUS >= 1000) THEN EXCEPTION DATA_ERROR 'Текущий статус тестирования не допускает выполнения операций с файлами';

  -- Проверяем существование пакета
  SELECT FIRST 1 P.ED_ID, P.STATE_ID
  FROM UT_PACKAGES P
  WHERE P.OBJ_ID = :I$PACKET_ID AND P.DATE_DEL IS NULL
  INTO :V$EXAM_ID, :V$STATUS;

  IF(V$EXAM_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Пакет не найден или был удален другим пользователем';
  IF(V$EXAM_ID <> I$EXAM_ID) THEN EXCEPTION DATA_ERROR 'Пакет не относится к выбранному тестированию';
  IF(V$STATUS IN (10, 11)) THEN EXCEPTION DATA_ERROR 'Обработка пакета завершена, изменение файлов невозможно';

  DELETED = 0;
  SELECT FIRST 1 B.OBJ_ID, B.NEXT_BLANK_ID
  FROM UT_BLANKS B
  WHERE B.FILE_ID = :I$FILE_ID AND B.PACKAGE_ID = :I$PACKET_ID AND B.DATE_DEL IS NULL
  INTO :V$OBJ_ID, :V$NEXT_ID;

  IF(V$OBJ_ID IS NOT NULL) THEN
  BEGIN

      -- Нельзя удалять не последний файл в цепочке
      IF(EXISTS(
          SELECT FIRST 1 1
          FROM UT_BLANKS B
          WHERE B.OBJ_ID = :V$NEXT_ID AND B.DATE_DEL IS NULL
      )) THEN EXCEPTION DATA_ERROR 'Нельзя удалять промежуточный файл в цепочке, начните с конца цепочки';

      DELETED = 1;

      UPDATE UT_BLANKS
      SET DATE_DEL = CURRENT_TIMESTAMP, DATE_MODIFY = CURRENT_TIMESTAMP
      WHERE OBJ_ID = :V$OBJ_ID;
  END

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_EXAM_PACKET_SET (
    I$EXAM_ID BIGINT,
    I$PACKET_ID BIGINT,
    I$PPE_CODE VARCHAR(40),
    I$ROOM_CODE VARCHAR(40),
    I$N_PAGES INTEGER,
    I$USER_ID VARCHAR(40),
    I$IP_INFO VARCHAR(200))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE T$ROOM_CODE VARCHAR(40);
DECLARE VARIABLE V$PPE_ID BIGINT;
DECLARE VARIABLE V$ROOM_ID BIGINT;
DECLARE VARIABLE V$OLD_ROOM_ID BIGINT;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$FILE_ID VARCHAR(40);
DECLARE VARIABLE V$FILE_HASH VARCHAR(40);
DECLARE VARIABLE V$BC1 VARCHAR(128);
DECLARE VARIABLE V$BC2 VARCHAR(128);
DECLARE VARIABLE V$BC3 VARCHAR(128);
DECLARE VARIABLE V$STATE SMALLINT;
DECLARE VARIABLE V$BLANK_TYPE SMALLINT;
DECLARE VARIABLE V$BLANK_SIDE SMALLINT;
DECLARE VARIABLE V$PLAN_METHOD INTEGER;
DECLARE VARIABLE M INTEGER;
DECLARE VARIABLE CC1 BIGINT;
DECLARE VARIABLE CC2 BIGINT;
begin

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  IF(I$N_PAGES < 0) THEN EXCEPTION DATA_ERROR 'Не допускается отрицательное значение количества бланков';

  -- Идентифицируем само тестирование
  SELECT FIRST 1 D.EXAM_STATE, D.PLAN_METHOD_ID
  FROM UT_EXAM_DATES D
  WHERE D.OBJ_ID = :I$EXAM_ID AND D.DATE_DEL IS NULL
  INTO :V$STATE, :V$PLAN_METHOD;

  IF(V$STATE IS NULL) THEN EXCEPTION DATA_ERROR 'Тестирование не найдено или было удалено';
  IF(V$STATE < 500 OR V$STATE >= 1000) THEN EXCEPTION DATA_ERROR 'Тестирование находится в недопустимом статусе';

  -- !!! Проверять права доступа !!!
  -- Если метод планирования с рассадкой
  IF(V$PLAN_METHOD = 0) THEN
  BEGIN
      SELECT FIRST 1 R.OBJ_ID, R.PPE_ID
      FROM UT_PPE_ROOMS R
      JOIN UT_EXAM_ROOM_ASSN RA ON RA.ROOM_ID = R.OBJ_ID AND RA.EXAM_ID = :I$EXAM_ID AND RA.DATE_DEL IS NULL -- ROLE_ID !!!
      JOIN UT_PPE P ON P.OBJ_ID = R.PPE_ID AND R.DATE_DEL IS NULL AND R.PPE_CODE = :I$PPE_CODE
      WHERE R.PPE_CODE = :I$ROOM_CODE AND R.DATE_DEL IS NULL
      INTO :V$PPE_ID, :V$ROOM_ID;
  END
  -- Метод планирования с распределением по ППЭ, но без рассадки
  ELSE IF(V$PLAN_METHOD = 1) THEN
  BEGIN
      SELECT FIRST 1 R.OBJ_ID, R.PPE_ID
      FROM UT_PPE_ROOMS R
      JOIN UT_EXAM_ROOM_ASSN RA ON RA.ROOM_ID = R.OBJ_ID AND RA.EXAM_ID = :I$EXAM_ID AND RA.DATE_DEL IS NULL -- ROLE_ID !!!
      JOIN UT_PPE P ON P.OBJ_ID = R.PPE_ID AND R.DATE_DEL IS NULL AND R.PPE_CODE = :I$PPE_CODE
      WHERE R.PPE_CODE = :I$ROOM_CODE AND R.DATE_DEL IS NULL
      INTO :V$PPE_ID, :V$ROOM_ID;
  END
  -- Метод планирования без распределения по ППЭ
  ELSE IF(V$PLAN_METHOD = 2) THEN
  BEGIN
      -- Коды для определения ППЭ
      WHILE(SUBSTRING(I$PPE_CODE FROM 1 FOR 1) = '0') DO I$PPE_CODE = SUBSTRING(I$PPE_CODE FROM 2);
      SELECT MULTIPLIER FROM GEN INTO :M;
      CC1 = M * CAST(I$PPE_CODE AS BIGINT);
      CC2 = M * (CAST(I$PPE_CODE AS BIGINT) + 1);

      -- Для сотрудников указываем сотрудник, для
      T$ROOM_CODE = UPPER(REPLACE(I$ROOM_CODE, ' ', ''));

      IF(I$ROOM_CODE = 'СОТРУДНИК') THEN
      BEGIN
          SELECT FIRST 1 LPG.PARENT_ID, LPG.PARENT_ID
          FROM UT_EXAM_PERSON_ASSN PA
          JOIN LINKS LPG ON LPG.OBJ_ID = PA.PERSON_ID AND LPG.PARENT_TYPE_ID = 2 AND LPG.DATE_DEL IS NULL
          WHERE PA.DATE_DEL IS NULL AND PA.EXAM_ID = :I$EXAM_ID AND PA.OBJ_ID >= :CC1 AND PA.OBJ_ID < :CC2
          INTO :V$ROOM_ID, :V$PPE_ID;
      END
      ELSE
      BEGIN
          SELECT FIRST 1 LPG.PARENT_ID, LP2.PARENT_ID
          FROM UT_EXAM_PERSON_ASSN PA
          JOIN LINKS LPG ON LPG.OBJ_ID = PA.PERSON_ID AND LPG.PARENT_TYPE_ID IN (9, 125, 187) AND LPG.DATE_DEL IS NULL
          JOIN LINKS LP8 ON LP8.OBJ_ID = LPG.PARENT_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
          JOIN LINKS LP7 ON LP7.OBJ_ID = LP8.PARENT_ID AND LP7.PARENT_TYPE_ID IN (7, 502) AND LP7.DATE_DEL IS NULL
          JOIN LINKS LP2 ON LP2.OBJ_ID = LP7.PARENT_ID AND LP2.PARENT_TYPE_ID = 2 AND LP2.DATE_DEL IS NULL
          LEFT JOIN OBJECT_CAPTION_GET(LPG.PARENT_ID) C9 ON 1 = 1
          WHERE PA.DATE_DEL IS NULL AND PA.EXAM_ID = :I$EXAM_ID AND PA.OBJ_ID >= :CC1 AND PA.OBJ_ID < :CC2 AND UPPER(REPLACE(C9.CAPTION, ' ', '')) = :T$ROOM_CODE
          INTO :V$ROOM_ID, :V$PPE_ID;
      END
  END

  IF(V$ROOM_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не удалось идентифицировать помещение (класс) для указанных кодов';

  -- Регистрирует или обновляет данные по пакету отсканированных бланков
  -- Нет ли существующего пакета для того же помещения, обработка которого не завершена ?
  IF(I$PACKET_ID IS NULL) THEN
  BEGIN
      SELECT FIRST 1 P.OBJ_ID
      FROM UT_PACKAGES P
      WHERE P.DATE_DEL IS NULL AND (P.STATE_ID < 9 OR P.STATE_ID = 11) AND P.ROOM_ID = :V$ROOM_ID AND P.ED_ID = :I$EXAM_ID
      INTO :I$PACKET_ID;
  END

  IF(I$PACKET_ID IS NULL) THEN
  BEGIN

      -- Новый пакет
      INSERT INTO UT_PACKAGES
      (ED_ID, PPE_ID, ROOM_ID, USER_ID, N_PAGES, IP_INFO)
      VALUES (:I$EXAM_ID, :V$PPE_ID, :V$ROOM_ID, :I$USER_ID, :I$N_PAGES, :I$IP_INFO)
      RETURNING OBJ_ID INTO :I$PACKET_ID;

  END
  ELSE
  BEGIN

      -- Обновляем пакет, корректируем количество файлов
      SELECT FIRST 1 ROOM_ID
      FROM UT_PACKAGES
      WHERE OBJ_ID = :I$PACKET_ID AND ED_ID = :I$EXAM_ID
      INTO :V$OLD_ROOM_ID;

      IF(V$OLD_ROOM_ID IS NULL OR V$OLD_ROOM_ID <> V$ROOM_ID) THEN EXCEPTION DATA_ERROR 'Пакет не найден, либо не соответствует запрошенным параметрам';

      UPDATE UT_PACKAGES
      SET N_PAGES = :I$N_PAGES, IP_INFO = :I$IP_INFO, DATE_MODIFY = CURRENT_TIMESTAMP
      WHERE OBJ_ID = :I$PACKET_ID;

  END

  TAG_NAME = 'packet_id';
  VAL = I$PACKET_ID;
  SUSPEND;

  TAG_NAME = 'n_pages';
  VAL = I$N_PAGES;
  SUSPEND;

  TAG_NAME = 'room_code';
  VAL = I$ROOM_CODE;
  SUSPEND;

  TAG_NAME = 'ppe_code';
  VAL = I$PPE_CODE;
  SUSPEND;

  -- Возвращаем список уже загруженных файлов пакета
  TAG_NAME = 'pages';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'pages::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
      SELECT B.OBJ_ID, B.FILE_ID, B.FILE_HASH, B.BARCODE_DATA, B.BARCODE2_DATA, B.BARCODE3_DATA, B.STATE_ID, B.BLANK_TYPE, B.BLANK_SIDE
      FROM UT_BLANKS B
      WHERE B.PACKAGE_ID = :I$PACKET_ID AND B.DATE_DEL IS NULL AND B.STATE_ID NOT IN (10, 11)
      INTO :V$OBJ_ID, :V$FILE_ID, :V$FILE_HASH, :V$BC1, :V$BC2, :V$BC3, :V$STATE, :V$BLANK_TYPE, :V$BLANK_SIDE
  DO
  BEGIN
      TAG_NAME = 'pages:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'pages:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'pages:r:file_id';
      VAL = V$FILE_ID;
      SUSPEND;
      TAG_NAME = 'pages:r:hash';
      VAL = V$FILE_HASH;
      SUSPEND;
      TAG_NAME = 'pages:r:barcode1';
      VAL = V$BC1;
      SUSPEND;
      TAG_NAME = 'pages:r:barcode2';
      VAL = V$BC2;
      SUSPEND;
      TAG_NAME = 'pages:r:barcode3';
      VAL = V$BC3;
      SUSPEND;
      TAG_NAME = 'pages:r:blank_type';
      VAL = V$BLANK_TYPE;
      SUSPEND;
      TAG_NAME = 'pages:r:blank_side';
      VAL = V$BLANK_SIDE;
      SUSPEND;
      TAG_NAME = 'pages:r:state';
      VAL = V$STATE;
      SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_EXAM_PACKET_START (
    I$EXAM_ID BIGINT,
    I$PACKET_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    FILE_ID VARCHAR(40),
    BARCODE_ID VARCHAR(40),
    BARCODE3_ID VARCHAR(40),
    FILE_HASH VARCHAR(40))
AS
declare variable V$PACKET_STATE integer;
declare variable V$OBJ_ID bigint;
declare variable V$STATE integer;
declare variable N integer;
declare variable N2 integer;
begin

  -- Проверяем доступность
  SELECT P.STATE_ID, P.N_PAGES
  FROM UT_PACKAGES P
  WHERE P.OBJ_ID = :I$PACKET_ID AND P.ED_ID = :I$EXAM_ID AND P.DATE_DEL IS NULL
  INTO :V$PACKET_STATE, :N;

  IF(V$PACKET_STATE IS NULL) THEN EXCEPTION DATA_ERROR 'Пакет не найден или был удален другим пользователем';
  IF(V$PACKET_STATE IN (10, 12)) THEN EXCEPTION DATA_ERROR 'Пакет уже обработан, повторая обработка невозможна';
  IF(N <= 0) THEN EXCEPTION DATA_ERROR 'Задекларировано недопустимое количество бланков в пакете';

  -- Выдаем по очереди все файлы
  N2 = 0;
  FOR
      SELECT B.OBJ_ID, B.FILE_ID, B.FILE_HASH, B.STATE_ID, B.BARCODE_DATA, B.BARCODE3_DATA
      FROM UT_BLANKS B
      WHERE B.PACKAGE_ID = :I$PACKET_ID AND B.DATE_DEL IS NULL
      INTO :V$OBJ_ID, :FILE_ID, :FILE_HASH, :V$STATE, :BARCODE_ID, :BARCODE3_ID
  DO
  BEGIN
      IF(BARCODE_ID IS NULL) THEN EXCEPTION DATA_ERROR 'В одном из файлов не распознан штрихкод';
      IF(V$STATE <> 3) THEN EXCEPTION DATA_ERROR 'Статус файла со штрихкодом "' || BARCODE_ID || ' не позволяет начать его обработку';

      -- Проверяем наличие дубликатов в этом же пакете
      IF(EXISTS(
          SELECT FIRST 1 1
          FROM UT_BLANKS B
          WHERE B.PACKAGE_ID = :I$PACKET_ID AND B.DATE_DEL IS NULL AND B.OBJ_ID <> :V$OBJ_ID AND B.BARCODE_DATA = :BARCODE_ID
      )) THEN EXCEPTION DATA_ERROR 'Дублирующийся основной штрихкод "' || BARCODE_ID || '" у файла в этом же пакете';

      IF(EXISTS(
          SELECT FIRST 1 1
          FROM UT_PACKAGES P
          JOIN UT_BLANKS B ON B.PACKAGE_ID = P.OBJ_ID AND B.DATE_DEL IS NULL AND B.BARCODE_DATA = :BARCODE_ID
          WHERE P.ED_ID = :I$EXAM_ID AND P.DATE_DEL IS NULL AND P.STATE_ID IN (9, 10)
      )) THEN EXCEPTION DATA_ERROR 'Дублирующийся основной штрихкод "' || BARCODE_ID || '" с другим пакетом работ';

      -- Если указан третий штрихкод (ссылка на следующий лист), следующий лист должен быть в этом же пакете
      IF(BARCODE3_ID IS NOT NULL) THEN
      BEGIN
          IF(NOT EXISTS(
              SELECT FIRST 1 1
              FROM UT_BLANKS B
              WHERE B.PACKAGE_ID = :I$PACKET_ID AND B.DATE_DEL IS NULL AND B.OBJ_ID <> :V$OBJ_ID AND B.BARCODE_DATA = :BARCODE3_ID
          )) THEN EXCEPTION DATA_ERROR 'Бланк "' || BARCODE_ID || '" ссылается на следующий лист, штрихкод которого отсутствует в данном пакете';
      END

      N2 = N2 + 1;

      SUSPEND;
  END

  IF(N <> N2) THEN EXCEPTION DATA_ERROR 'Фактическое количество бланков (' || N2 || ') в пакете не соответствует указанному (' || N || ')' ;

  -- Выдаем запись stub
  FILE_ID = NULL;
  SUSPEND;

  -- Отмечаем смену статуса у пакета и всех файлов
  UPDATE UT_BLANKS B
  SET B.STATE_ID = 9, B.DATE_MODIFY = CURRENT_TIMESTAMP
  WHERE B.PACKAGE_ID = :I$PACKET_ID AND B.DATE_DEL IS NULL AND B.STATE_ID = 3;

  UPDATE UT_PACKAGES P
  SET P.STATE_ID = 9, P.DATE_MODIFY = CURRENT_TIMESTAMP
  WHERE P.OBJ_ID = :I$PACKET_ID;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_EXAM_PACKET_STATUS (
    I$PACKET_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
declare variable V$FILE_ID varchar(40);
declare variable V$PARENT_ID varchar(40);
declare variable V$STATE integer;
begin

  TAG_NAME = 'items';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'items::json&colon;array';
  VAL = 1;
  SUSPEND;

  FOR
      SELECT B.FILE_ID, B.STATE_ID, PB.FILE_ID
      FROM UT_BLANKS B
      LEFT JOIN UT_BLANKS PB ON PB.OBJ_ID = B.PARENT_ID
      WHERE B.PACKAGE_ID = :I$PACKET_ID AND B.DATE_DEL IS NULL
      INTO :V$FILE_ID, :V$STATE, :V$PARENT_ID
  DO
  BEGIN
      TAG_NAME = 'items:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'items:r:id';
      VAL = V$FILE_ID;
      SUSPEND;
      TAG_NAME = 'items:r:parent_id';
      VAL = V$PARENT_ID;
      SUSPEND;
      TAG_NAME = 'items:r:state';
      VAL = V$STATE;
      SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_EXAM_PERSON_ASSN_SET (
    I$EXAM_ID BIGINT,
    I$PERSON_ID BIGINT,
    I$USER_ID VARCHAR(40),
    I$OP SMALLINT)
RETURNS (
    OBJ_ID BIGINT,
    EXAM_ID BIGINT,
    EXAM_NAME VARCHAR(200),
    EXAM_DATE DATE)
AS
declare variable V$DATE_DEL timestamp;
declare variable STATE integer;
declare variable V$OU_ID bigint;
declare variable V$AREA_ID bigint;
BEGIN

  -- I$OP - тип операции: 0 = обновить, 1 = добавить, 2 = удалить

  SELECT D.OBJ_ID, D.EXAM_DATE_START, D.OBJ_NAME, D.EXAM_STATE
  FROM UT_EXAM_DATES D
  WHERE D.OBJ_ID = :I$EXAM_ID AND D.DATE_DEL IS NULL
  INTO :EXAM_ID, :EXAM_DATE, :EXAM_NAME, :STATE;

  IF(EXAM_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Тестирование не найдено или было удалено';
  IF(STATE < 100 OR STATE > 800) THEN EXCEPTION DATA_ERROR 'Для назначения участников статус должен быть не ниже: Планирование участников, и не выше: Обработка результатов';

  IF(I$OP IN (0, 1)) THEN
  BEGIN

      SELECT FIRST 1 OBJ_ID, DATE_DEL
      FROM UT_EXAM_PERSON_ASSN
      WHERE EXAM_ID = :I$EXAM_ID AND PERSON_ID = :I$PERSON_ID
      INTO :OBJ_ID, :V$DATE_DEL;

      IF(OBJ_ID IS NULL) THEN
      BEGIN

          SELECT OU_ID, AREA_ID
          FROM UT_PERSON_DESC(:I$PERSON_ID)
          INTO :V$OU_ID, :V$AREA_ID;

          IF(V$OU_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не удалось идентифицировать организацию для участника тестирования';
          IF(V$AREA_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не удалось идентифицировать район. Проверьте, указан ли район в настройках организации';

          INSERT INTO UT_EXAM_PERSON_ASSN
          (EXAM_ID, PERSON_ID, OU_ID, AREA_ID)
          VALUES (:I$EXAM_ID, :I$PERSON_ID, :V$OU_ID, :V$AREA_ID)
          RETURNING OBJ_ID INTO :OBJ_ID;

      END
      ELSE IF(V$DATE_DEL IS NOT NULL) THEN
      BEGIN

          -- Восстанавливаем удаление
          UPDATE UT_EXAM_PERSON_ASSN
          SET DATE_DEL = NULL, DATE_MODIFY = CURRENT_TIMESTAMP
          WHERE OBJ_ID = :OBJ_ID;

      END

  END
  ELSE
  BEGIN

      UPDATE UT_EXAM_PERSON_ASSN
      SET DATE_DEL = CURRENT_TIMESTAMP, DATE_MODIFY = CURRENT_TIMESTAMP
      WHERE EXAM_ID = :I$EXAM_ID AND PERSON_ID = :I$PERSON_ID AND DATE_DEL IS NULL;

  END

  SUSPEND;

END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_EXAM_PPE_ASSN_SET (
    I$EXAM_ID BIGINT,
    I$PPE_ID BIGINT,
    I$USER_ID VARCHAR(40),
    I$OP SMALLINT)
RETURNS (
    OBJ_ID BIGINT,
    EXAM_ID BIGINT,
    EXAM_NAME VARCHAR(200),
    EXAM_DATE DATE)
AS
declare variable V$DATE_DEL timestamp;
BEGIN

  -- I$OP - тип операции: 0 = обновить, 1 = добавить, 2 = удалить

  IF(I$OP IN (0, 1)) THEN
  BEGIN

      SELECT D.OBJ_ID, D.EXAM_DATE_START, D.OBJ_NAME
      FROM UT_EXAM_DATES D
      WHERE D.OBJ_ID = :I$EXAM_ID AND D.DATE_DEL IS NULL AND D.EXAM_STATE > 0 AND D.EXAM_STATE < 700
      INTO :EXAM_ID, :EXAM_DATE, :EXAM_NAME;

      IF(EXAM_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Тестирование не найдено, было удалено, или находится в недопустимом статусе';

      SELECT FIRST 1 OBJ_ID, DATE_DEL
      FROM UT_EXAM_PPE_ASSN
      WHERE EXAM_ID = :I$EXAM_ID AND PPE_ID = :I$PPE_ID
      INTO :OBJ_ID, :V$DATE_DEL;

      IF(OBJ_ID IS NULL) THEN
      BEGIN

          INSERT INTO UT_EXAM_PPE_ASSN
          (EXAM_ID, PPE_ID)
          VALUES (:I$EXAM_ID, :I$PPE_ID)
          RETURNING OBJ_ID INTO :OBJ_ID;

      END
      ELSE IF(V$DATE_DEL IS NOT NULL) THEN
      BEGIN

          UPDATE UT_EXAM_PPE_ASSN
          SET DATE_DEL = NULL
          WHERE OBJ_ID = :OBJ_ID;

      END

  END
  ELSE
  BEGIN

      -- Есть ли назначенные тестируемые в этом ППЭ
      -- !!!

      -- Если есть назначенные помещения - снимаем назначения
      -- !!!

      UPDATE UT_EXAM_PPE_ASSN
      SET DATE_DEL = CURRENT_TIMESTAMP
      WHERE EXAM_ID = :I$EXAM_ID AND PPE_ID = :I$PPE_ID AND DATE_DEL IS NULL;

  END

  SUSPEND;

END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_EXAM_PRINT_GET (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(1000))
AS
declare variable SUBJECT_ID bigint;
declare variable STAGE_ID bigint;
declare variable EXAM_DATE_START date;
declare variable EXAM_DATE_END date;
declare variable DURATION integer;
declare variable EXAM_DAY_TYPE integer;
declare variable EXAM_STATE integer;
declare variable C_CALC_MODE integer;
declare variable C_EXPERT_NUM integer;
declare variable C_DIFF_QUESTION integer;
declare variable C_DIFF_TOTAL integer;
declare variable METHOD_ID integer;
declare variable PLAN_METHOD_ID integer;
declare variable ATTEMPTS integer;
declare variable OWNER_ID bigint;
declare variable OBJ_NAME varchar(400);
declare variable H_LEVEL integer;
declare variable ORG_REF bigint;
declare variable FLOW_MODE integer;
declare variable PAUSE_ENABLED integer;
declare variable V$BLANK_AB_ID bigint;
declare variable V$BLANK_C_ID bigint;
declare variable V$BLANK_EXT_ID bigint;
declare variable V$BLANK_GEN_ID bigint;
declare variable V$EXPERT_ASSN_MODE integer;
declare variable V$N0 integer;
declare variable V$NMIN integer;
declare variable V$N4 integer;
declare variable V$N5 integer;
declare variable V$NMAX integer;
declare variable V$OUR_ORG bigint;
declare variable V$DB_LEVEL integer;
declare variable V$ACCESS integer;
declare variable V$ID bigint;
declare variable V$S varchar(1000);
declare variable V$ACTIVE smallint;
declare variable N integer;
begin

  -- Общие данные по тестированию

  TAG_NAME = 'id';
  VAL = I$OBJ_ID;
  SUSPEND;

  SELECT D.SUBJECT_ID, D.STAGE_ID, D.EXAM_DATE_START, D.EXAM_DATE_END, D.DURATION, D.EXAM_DAY_TYPE, D.EXAM_STATE, D.C_CALC_MODE, D.C_EXPERT_NUM,
      D.C_DIFF_QUESTION, D.C_DIFF_TOTAL, D.METHOD_ID, D.PLAN_METHOD_ID, D.ATTEMPTS, D.OWNER_ID, D.H_LEVEL, D.ORG_REF, D.OBJ_NAME,
      D.FLOW_MODE, D.PAUSE_ENABLED, D.BLANK_AB_ID, D.BLANK_C_ID, D.BLANK_EXT_ID, D.BLANK_GEN_ID, D.EXPERT_ASSN_MODE,
      D.SCALE_N0, D.SCALE_NMIN, D.SCALE_N4, D.SCALE_N5, D.SCALE_NMAX
  FROM UT_EXAM_DATES D
  WHERE D.DATE_DEL IS NULL AND D.OBJ_ID = :I$OBJ_ID
  INTO :SUBJECT_ID, :STAGE_ID, :EXAM_DATE_START, :EXAM_DATE_END, :DURATION, :EXAM_DAY_TYPE, :EXAM_STATE, :C_CALC_MODE, :C_EXPERT_NUM,
      :C_DIFF_QUESTION, :C_DIFF_TOTAL, :METHOD_ID, :PLAN_METHOD_ID, :ATTEMPTS, :OWNER_ID, :H_LEVEL, :ORG_REF, :OBJ_NAME,
      :FLOW_MODE, :PAUSE_ENABLED, :V$BLANK_AB_ID, :V$BLANK_C_ID, :V$BLANK_EXT_ID, :V$BLANK_GEN_ID, :V$EXPERT_ASSN_MODE,
      :V$N0, :V$NMIN, :V$N4, :V$N5, :V$NMAX;

  -- Сначала дискретные поля
  TAG_NAME = 'obj_name';
  VAL = OBJ_NAME;
  SUSPEND;

  TAG_NAME = 'exam_date_start';
  VAL = (SELECT VAL FROM DATE2ISO(:EXAM_DATE_START, 0));
  SUSPEND;

  TAG_NAME = 'exam_date_end';
  VAL = (SELECT VAL FROM DATE2ISO(:EXAM_DATE_END, 0));
  SUSPEND;

  TAG_NAME = 'duration';
  VAL = DURATION;
  SUSPEND;

  TAG_NAME = 'c_diff_question';
  VAL = C_DIFF_QUESTION;
  SUSPEND;

  TAG_NAME = 'c_diff_total';
  VAL = C_DIFF_TOTAL;
  SUSPEND;

  TAG_NAME = 'attempts';
  VAL = ATTEMPTS;
  SUSPEND;

  TAG_NAME = 'owner_id';
  VAL = OWNER_ID;
  SUSPEND;

  TAG_NAME = 'h_level';
  VAL = H_LEVEL;
  SUSPEND;

  TAG_NAME = 'org_ref';
  VAL = ORG_REF;
  SUSPEND;

  TAG_NAME = 'org_ref_name';
  VAL = NULL;
  IF(H_LEVEL = 2) THEN VAL = 'Регион+';
  ELSE IF(H_LEVEL = 1) THEN
  BEGIN
      SELECT R.VAL
      FROM LISTVALS LV
      JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
      WHERE LV.LISTVAL_ID = :ORG_REF
      INTO :VAL;
  END
  ELSE
  BEGIN
      SELECT CAPTION
      FROM OBJECT_CAPTION_GET(:ORG_REF)
      INTO :VAL;
  END
  SUSPEND;

  TAG_NAME = 'pause_enabled';
  VAL = PAUSE_ENABLED;
  SUSPEND;

  -- Уровень доступа текущего пользователя, равен уровню базы (0 = ОУ, ...)
  TAG_NAME = 'user_level';
  SELECT COALESCE(CAST(K.KEY_VAL AS INTEGER) - 1, 0)
  FROM KEYS K
  WHERE K.KEY_CODE = 'LEVEL'
  INTO :V$DB_LEVEL;
  VAL = V$DB_LEVEL;
  SUSPEND;

  -- Получаем наш домашний уровень (ОУ или район)
  IF(V$DB_LEVEL = 0) THEN
  BEGIN
      SELECT FIRST 1 L2.OBJ_ID
      FROM LINKS L2
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      INTO :V$OUR_ORG;
  END
  ELSE IF(V$DB_LEVEL = 1) THEN
  BEGIN
      SELECT FIRST 1 V665.LISTVAL_ID
      FROM LINKS L111
      JOIN VALL V665 ON V665.OBJ_ID = L111.OBJ_ID AND V665.LISTVAL_ID = 665 AND V665.IS_DEL = 0
      WHERE L111.PARENT_ID IS NULL AND L111.OBJ_TYPE_ID = 111 AND L111.DATE_DEL IS NULL
      INTO :V$OUR_ORG;
  END

  -- Битовая маска прав доступа
  -- Бит 0 - можно ли редактировать поля самого тестирования и варианты
  -- Бит 1 - можно ли создавать новые КИМ или варианты (расширение бита 0, будет дополнительно проверяться что сам тест не R/O)
  -- Бит 2 - можно ли редактировать участников тестирования непосредственно в данном диалоге (только для уровня ОУ, когда тестирование свое собственное)
  -- Бит 3 - может ли редактировать состав экспертов (только в пределах своей области видимости)
  -- Для классных руководителей - даем доступ только чтение
  TAG_NAME = 'allowed';
  V$ACCESS = 0;
  IF(V$DB_LEVEL = H_LEVEL AND (ORG_REF = V$OUR_ORG OR (ORG_REF IS NULL AND V$OUR_ORG IS NULL))) THEN V$ACCESS = BIN_OR(V$ACCESS, 1);
  IF(V$DB_LEVEL = 0 AND H_LEVEL = 0 AND ORG_REF = V$OUR_ORG) THEN V$ACCESS = BIN_OR(V$ACCESS, 4);
  IF((V$DB_LEVEL = 0 AND V$EXPERT_ASSN_MODE = 1) OR (V$DB_LEVEL = H_LEVEL AND V$EXPERT_ASSN_MODE = 0)) THEN V$ACCESS = BIN_OR(V$ACCESS, 8);
  VAL = V$ACCESS;
  SUSPEND;

  TAG_NAME = 'subject_id';
  VAL = SUBJECT_ID;
  SUSPEND;
  TAG_NAME = 'subject_name';
  VAL = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:SUBJECT_ID));
  SUSPEND;

  TAG_NAME = 'stage_id';
  VAL = STAGE_ID;
  SUSPEND;
  TAG_NAME = 'stage_name';
  VAL = (SELECT D.OBJ_NAME FROM UT_EXAM_STAGES D WHERE D.OBJ_ID = :STAGE_ID);
  SUSPEND;

  TAG_NAME = 'exam_state';
  VAL = EXAM_STATE;
  SUSPEND;
  TAG_NAME = 'exam_state_name';
  VAL = (SELECT D.OBJ_NAME FROM UT_EXAM_STATES D WHERE D.OBJ_ID = :EXAM_STATE);
  SUSPEND;

  TAG_NAME = 'method_id';
  VAL = METHOD_ID;
  SUSPEND;
  TAG_NAME = 'method_name';
  VAL = (SELECT D.OBJ_NAME FROM UT_EXAM_METHODS D WHERE D.OBJ_ID = :METHOD_ID);
  SUSPEND;

  TAG_NAME = 'plan_method_id';
  VAL = PLAN_METHOD_ID;
  SUSPEND;
  TAG_NAME = 'plan_method_name';
  VAL = (SELECT D.OBJ_NAME FROM UT_EXAM_PLAN_METHODS D WHERE D.OBJ_ID = :PLAN_METHOD_ID);
  SUSPEND;

  TAG_NAME = 'c_calc_mode';
  VAL = C_CALC_MODE;
  SUSPEND;
  TAG_NAME = 'c_calc_mode_name';
  VAL = (SELECT D.OBJ_NAME FROM UT_EXPERT_CALC_MODES D WHERE D.OBJ_ID = :C_CALC_MODE);
  SUSPEND;

  TAG_NAME = 'exam_day_type';
  VAL = EXAM_DAY_TYPE;
  SUSPEND;
  TAG_NAME = 'exam_day_type_name';
  VAL = (SELECT D.OBJ_NAME FROM UT_EXAM_DAY_TYPES D WHERE D.OBJ_ID = :EXAM_DAY_TYPE);
  SUSPEND;

  TAG_NAME = 'c_expert_num';
  VAL = C_EXPERT_NUM;
  SUSPEND;

  TAG_NAME = 'blank_ab_id';
  VAL = V$BLANK_AB_ID;
  SUSPEND;
  TAG_NAME = 'blank_c_id';
  VAL = V$BLANK_C_ID;
  SUSPEND;
  TAG_NAME = 'blank_ext_id';
  VAL = V$BLANK_EXT_ID;
  SUSPEND;
  TAG_NAME = 'blank_gen_id';
  VAL = V$BLANK_GEN_ID;
  SUSPEND;

  TAG_NAME = 'blank_types';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'blank_types::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
      SELECT OBJ_ID, OBJ_NAME, IS_ACTIVE
      FROM UT_PAGE_TEMPLATES
      WHERE BLANK_TYPE IN (0, 1) AND DATE_DEL IS NULL
      ORDER BY IS_ACTIVE DESC, 2
      INTO :V$ID, :V$S, :V$ACTIVE
  DO
  BEGIN
      TAG_NAME = 'blank_types:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'blank_types:r:id';
      VAL = V$ID;
      SUSPEND;
      TAG_NAME = 'blank_types:r:value';
      VAL = V$S;
      SUSPEND;
      TAG_NAME = 'blank_types:r:active';
      VAL = V$ACTIVE;
      SUSPEND;
  END

  -- Шкалы показываем только если уровень базы = уровню тестирования
  IF(V$DB_LEVEL = H_LEVEL AND EXAM_DAY_TYPE <> 100) THEN
  BEGIN
      TAG_NAME = 'scale_n0';
      VAL = V$N0;
      SUSPEND;
      TAG_NAME = 'scale_nmin';
      VAL = V$NMIN;
      SUSPEND;
      TAG_NAME = 'scale_n4';
      VAL = V$N4;
      SUSPEND;
      TAG_NAME = 'scale_n5';
      VAL = V$N5;
      SUSPEND;
      TAG_NAME = 'scale_nmax';
      VAL = V$NMAX;
      SUSPEND;
  END

  -- Списки вариантов тестирования - для печати КИМ
  FOR
      SELECT TAG_NAME, VAL
      FROM UT_TEST_KIM_LIST(:I$OBJ_ID, :I$USER_ID)
      INTO :TAG_NAME, :VAL
  DO
  BEGIN
      -- Меняем тег, в котором отдаются списки бланков
      TAG_NAME = 'var_blanks' || TAG_NAME;
      SUSPEND;
  END

  -- Списки групп и участников для печати основных бланков и протоколов
  -- Внимание: тут нужно делать фильтр по текущей ОУ ?
  N = 0;
  SELECT COUNT(*)
  FROM UT_EXAM_PERSON_ASSN
  WHERE DATE_DEL IS NULL AND EXAM_ID = :I$OBJ_ID
  INTO :N;
  TAG_NAME = 'n_members';
  VAL = N;
  SUSPEND;

  FOR
      SELECT TAG_NAME, VAL
      FROM UT_TEST_BLANKS_LIST(:I$OBJ_ID, :I$USER_ID)
      INTO :TAG_NAME, :VAL
  DO
  BEGIN
      -- Меняем тег, в котором отдаются списки бланков
      TAG_NAME = 'main_blanks' || TAG_NAME;
      SUSPEND;
  END

  FOR
      SELECT TAG_NAME, VAL
      FROM UT_TEST_EXT_LIST(:I$OBJ_ID, :I$USER_ID)
      INTO :TAG_NAME, :VAL
  DO
  BEGIN
      -- Меняем тег, в котором отдаются списки бланков
      TAG_NAME = 'ext_blanks' || TAG_NAME;
      SUSPEND;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_EXAM_PRINT_LIST (
    I$USER_ID VARCHAR(40))
RETURNS (
    EXAM_ID BIGINT,
    EXAM_NAME VARCHAR(200),
    EXAM_DATE DATE,
    SUBJECT_ID BIGINT,
    SUBJECT_NAME VARCHAR(200),
    EXAM_STATE INTEGER,
    EXAM_STATE_NAME VARCHAR(200),
    METHOD_ID INTEGER,
    BLANKS_PRINTED INTEGER)
AS
begin

  FOR
      SELECT D.OBJ_ID, D.OBJ_NAME, D.SUBJECT_ID, COALESCE(VS.VAL, 'Метапредмет'), D.EXAM_STATE, ES.OBJ_NAME, D.METHOD_ID, D.EXAM_DATE_START
      FROM UT_EXAM_DATES D
      JOIN UT_EXAM_STATES ES ON ES.OBJ_ID = D.EXAM_STATE
      LEFT JOIN VALS VS ON VS.OBJ_ID = D.SUBJECT_ID AND VS.PARAM_ID = 376 AND VS.IS_DEL = 0
      WHERE D.DATE_DEL IS NULL AND D.EXAM_STATE >= 550 AND D.EXAM_STATE <= 700 AND D.METHOD_ID = 2
      ORDER BY D.EXAM_DATE_START, D.OBJ_NAME
      INTO :EXAM_ID, :EXAM_NAME, :SUBJECT_ID, :SUBJECT_NAME, :EXAM_STATE, :EXAM_STATE_NAME, :METHOD_ID, :EXAM_DATE
  DO
  BEGIN

      BLANKS_PRINTED = 0;

      SELECT COUNT(*)
      FROM UT_EXAM_PRINT_LOG L
      WHERE L.DATE_DEL IS NULL AND L.EXAM_ID = :EXAM_ID
      INTO :BLANKS_PRINTED;

      SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_EXAM_QUESTION_SET (
    I$EXAM_ID BIGINT NOT NULL,
    I$OBJ_ID BIGINT,
    I$QUESTION_ID BIGINT,
    I$VARIANT_INDEX INTEGER NOT NULL,
    I$SORT_INDEX INTEGER NOT NULL,
    I$USER_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT)
AS
begin

  -- Передается либо OBJ_ID, либо QUESTION_ID
  IF(I$OBJ_ID IS NULL AND I$QUESTION_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не указан id вопроса';

  IF(I$OBJ_ID IS NOT NULL) THEN
    SELECT FIRST 1 Q.OBJ_ID
    FROM UT_EXAM_QUESTIONS Q
    WHERE Q.DATE_DEL IS NULL AND Q.EXAM_ID = :I$EXAM_ID AND Q.OBJ_ID = :I$OBJ_ID
    INTO :OBJ_ID;
  ELSE
    SELECT FIRST 1 Q.OBJ_ID
    FROM UT_EXAM_QUESTIONS Q
    WHERE Q.DATE_DEL IS NULL AND Q.EXAM_ID = :I$EXAM_ID AND Q.QUESTION_ID = :I$OBJ_ID AND Q.VARIANT_INDEX = :I$VARIANT_INDEX
    INTO :OBJ_ID;

  IF(OBJ_ID IS NULL AND I$OBJ_ID IS NOT NULL) THEN EXCEPTION DATA_ERROR 'Вопрос ' || I$SORT_INDEX || ' был удален';

  IF(OBJ_ID IS NULL) THEN
  BEGIN
    INSERT INTO UT_EXAM_QUESTIONS
    (EXAM_ID, QUESTION_ID, VARIANT_INDEX, SORT_INDEX)
    VALUES (:I$EXAM_ID, :I$QUESTION_ID, :I$VARIANT_INDEX, :I$SORT_INDEX)
    RETURNING OBJ_ID INTO :OBJ_ID;
  END
  ELSE
  BEGIN
    -- Обязательно будет изменение индексов, вопрос поменяться не может
    UPDATE UT_EXAM_QUESTIONS
    SET VARIANT_INDEX = :I$VARIANT_INDEX, SORT_INDEX = :I$SORT_INDEX
    WHERE OBJ_ID = :OBJ_ID;
  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_EXAM_RECALC (
    I$EXAM_ID BIGINT,
    I$SCALE_N0 INTEGER,
    I$SCALE_NMIN INTEGER,
    I$SCALE_N4 INTEGER,
    I$SCALE_N5 INTEGER,
    I$SCALE_NMAX INTEGER,
    I$USER_ID VARCHAR(40))
AS
DECLARE VARIABLE V$EXAM_STATE INTEGER;
DECLARE VARIABLE V$OWNER_ID BIGINT;
DECLARE VARIABLE V$ORG_REF BIGINT;
DECLARE VARIABLE V$H_LEVEL INTEGER;
DECLARE VARIABLE V$PERSON_ID BIGINT;
DECLARE VARIABLE V$SESSION_ID BIGINT;
DECLARE VARIABLE V$QUESTION_TYPE SMALLINT;
DECLARE VARIABLE V$ANSWER_DATA VARCHAR(4000);
DECLARE VARIABLE V$RAW INTEGER;
DECLARE VARIABLE V$RATE INTEGER;
DECLARE VARIABLE V$NEW_STATE_ID INTEGER;
DECLARE VARIABLE V$QUESTION_ID BIGINT;
DECLARE VARIABLE V$VAR_ID BIGINT;
begin

  SELECt FIRST 1 D.EXAM_STATE, D.OWNER_ID, D.H_LEVEL, D.ORG_REF
  FROM UT_EXAM_DATES D
  WHERE D.OBJ_ID = :I$EXAM_ID AND D.DATE_DEL IS NULL
  INTO :V$EXAM_STATE, :V$OWNER_ID, :V$H_LEVEL, :V$ORG_REF;

  IF(V$EXAM_STATE IS NULL) THEN EXCEPTION DATA_ERROR 'Тестирование не найдено';

  IF(V$EXAM_STATE < 600 OR V$EXAM_STATE > 900) THEN EXCEPTION DATA_ERROR 'Недопустимый статус тестирования для пересчета итогов';

  -- Проверяем порядок шкалы
  IF(I$SCALE_N0 IS NOT NULL) THEN
  BEGIN
    IF(I$SCALE_N0 > I$SCALE_NMIN OR I$SCALE_N0 > I$SCALE_N4 OR I$SCALE_N0 > I$SCALE_N5 OR I$SCALE_N0 > I$SCALE_NMAX) THEN
      EXCEPTION DATA_ERROR 'Нарушен порядок следования показателей в шкале';
  END
  IF(I$SCALE_NMIN IS NOT NULL) THEN
  BEGIN
    IF(I$SCALE_NMIN > I$SCALE_N4 OR I$SCALE_NMIN > I$SCALE_N5 OR I$SCALE_NMIN > I$SCALE_NMAX) THEN
      EXCEPTION DATA_ERROR 'Нарушен порядок следования показателей в шкале';
  END
  IF(I$SCALE_N4 IS NOT NULL) THEN
  BEGIN
    IF(I$SCALE_N4 > I$SCALE_N5 OR I$SCALE_N4 > I$SCALE_NMAX) THEN
      EXCEPTION DATA_ERROR 'Нарушен порядок следования показателей в шкале';
  END
  IF(I$SCALE_N5 IS NOT NULL) THEN
  BEGIN
    IF(I$SCALE_N5 > I$SCALE_NMAX) THEN
      EXCEPTION DATA_ERROR 'Нарушен порядок следования показателей в шкале';
  END

  UPDATE UT_EXAM_DATES
  SET SCALE_N0 = :I$SCALE_N0, SCALE_NMIN = :I$SCALE_NMIN, SCALE_N4 = :I$SCALE_N4,
    SCALE_N5 = :I$SCALE_N5, SCALE_NMAX = :I$SCALE_NMAX
  WHERE OBJ_ID = :I$EXAM_ID;

  -- Перепроверяем ответы в соответствии с возможно изменившимися ключами-антиключами
  -- только в последнем варианте проверки
  FOR
    SELECT PA.PERSON_ID, MAX(S.OBJ_ID)
    FROM UT_EXAM_PERSON_ASSN PA
    JOIN UT_SESSIONS S ON S.DATE_DEL IS NULL AND S.ED_ID = PA.EXAM_ID AND S.PERSON_ID = PA.PERSON_ID AND S.STATE_ID = 100
    WHERE PA.DATE_DEL IS NULL AND PA.EXAM_ID = :I$EXAM_ID
    GROUP BY 1
    INTO :V$PERSON_ID, :V$SESSION_ID
  DO
  BEGIN
    FOR
      SELECT SQ.OBJ_ID, Q.OBJ_ID, SQ.ANSWER_DATA, Q.QUESTION_TYPE, SQ.RAW_RESULT
      FROM UT_SESSION_QUESTIONS SQ
      JOIN UT_EXAM_QUESTIONS EQ ON EQ.OBJ_ID = SQ.QUESTION_ID
      JOIN UT_QUESTIONS Q ON Q.OBJ_ID = EQ.QUESTION_ID
      WHERE SQ.DATE_DEL IS NULL AND SQ.SESSION_ID = :V$SESSION_ID AND SQ.ANSWER_DATA IS NOT NULL
      ORDER BY EQ.SORT_INDEX
      INTO :V$VAR_ID, :V$QUESTION_ID, :V$ANSWER_DATA, :V$QUESTION_TYPE, :V$RAW
    DO
    BEGIN
      -- Далее парсер результатов конкретного типа вопросов
      IF(V$QUESTION_TYPE = 1) THEN
      BEGIN
        SELECT STATE_ID, RATE
        FROM UT_VALIDATE_ANSWER_01(:V$QUESTION_ID, :V$ANSWER_DATA)
        INTO :V$NEW_STATE_ID, :V$RATE;
      END
      ELSE IF(V$QUESTION_TYPE = 2) THEN
      BEGIN
        SELECT STATE_ID, RATE
        FROM UT_VALIDATE_ANSWER_02(:V$QUESTION_ID, :V$ANSWER_DATA)
        INTO :V$NEW_STATE_ID, :V$RATE;
      END
      ELSE IF(V$QUESTION_TYPE = 4) THEN
      BEGIN
        SELECT STATE_ID, RATE
        FROM UT_VALIDATE_ANSWER_04(:V$QUESTION_ID, :V$ANSWER_DATA)
        INTO :V$NEW_STATE_ID, :V$RATE;
      END
      ELSE IF(V$QUESTION_TYPE = 5) THEN
      BEGIN
        SELECT STATE_ID, RATE
        FROM UT_VALIDATE_ANSWER_05(:V$QUESTION_ID, :V$ANSWER_DATA)
        INTO :V$NEW_STATE_ID, :V$RATE;
      END

      -- Считаем что ответ всегда получился, сохраняем при изменении
      IF(COALESCE(V$RATE, -1) <> COALESCE(V$RAW, -1)) THEN
      UPDATE UT_SESSION_QUESTIONS
      SET RAW_RESULT = :V$RATE
      WHERE OBJ_ID = :V$VAR_ID;
    END
  END

  -- Пересчитываем общий итог по шкале
  SELECT COUNT(*) FROM UT_EXAM_SCALE_APPLY(:I$EXAM_ID, :I$USER_ID) INTO :V$EXAM_STATE;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_EXAM_REPORT_EXPERTS (
    I$EXAM_ID BIGINT,
    I$USER_ID VARCHAR(40),
    I$ORDER VARCHAR(40) = null)
RETURNS (
    VAL VARCHAR(8000))
AS
declare variable V$S varchar(1000);
declare variable V$ID bigint;
declare variable V$D date;
declare variable V$H_LEVEL smallint;
declare variable V$ORG_REF bigint;
declare variable V$ALL smallint;
declare variable V$AREA_NAME varchar(400);
declare variable V$AREA_ID bigint;
declare variable V$PREV_ID bigint;
declare variable N1 integer;
declare variable N2 integer;
declare variable N3 integer;
declare variable V varchar(30);
begin

  SELECT D.OBJ_ID, D.OBJ_NAME, D.EXAM_DATE_START, D.H_LEVEL, D.ORG_REF
  FROM UT_EXAM_DATES D
  WHERE D.OBJ_ID = :I$EXAM_ID AND D.DATE_DEL IS NULL
  INTO :V$ID, :V$S, :V$D, :V$H_LEVEL, :V$ORG_REF;

  IF(V$ID IS NULL) THEN EXCEPTION DATA_ERROR 'Тестирование не найдено';

  -- Порядок сортировки по ОУ, но группировка всегда по районам
  IF(I$ORDER IS NULL) THEN I$ORDER = 'ou';

  -- Есть ли назначение "все ОУ" ?
  V$ALL = 0;
  SELECT FIRST 1 1
  FROM UT_EXAM_OU_ASSN A
  WHERE A.DATE_DEL IS NULL AND A.EXAM_ID = :I$EXAM_ID AND A.OU_ID = 0
  INTO :V$ALL;

  -- Если это тестирование уровня ОУ, выдаем как будто назначены все ОУ
  IF(V$H_LEVEL = 0) THEN V$ALL = 1;

  -- Шапка HTML
  VAL = '<style>';
  VAL = VAL || '.report-table tr td { padding: 0.1rem 0.5rem; } ';
  VAL = VAL || '.report-table tr:nth-child(odd) td { background-color: rgba(0,0,0,0.05); } ';
  VAL = VAL || '.report-table tr th { padding: 0.1rem 0.5rem; border-bottom: 2px solid gray; } ';
  VAL = VAL || '.report-table tr th:nth-child(1), .report-table tr td:nth-child(1) { width: 25%; } ';
  VAL = VAL || '.report-table tr th:nth-child(2), .report-table tr td:nth-child(2) { width: 35%; } ';
  VAL = VAL || '.district { font-weight: bold; } ';
  VAL = VAL || '</style>';

  VAL = VAL || '<h1 style="font-size: 16px;">Отчет по назначению экспертов на тестировании</h1>';
  VAL = VAL || '<h2 style="font-size: 14px;">' || V$S || '</h2>';
  VAL = VAL || '<h3 style="font-size: 14px; margin-top: 0 ! important;">Дата начала тестирования: ' || (SELECT RESULT FROM DATE2STR(:V$D)) || '</h3>';

  SUSPEND;
  VAL = '';

  VAL = VAL || '<table class="content-table report-table" style="border-collapse: collapse; width: 100%;" data-order="' || I$ORDER || '">';
  VAL = VAL || '<tr>';
      VAL = VAL || '<th>Район</th>';
      VAL = VAL || '<th data-field="ou">ОУ</th>';
      VAL = VAL || '<th data-field="members">Заявлено участников</th>';
      VAL = VAL || '<th data-field="experts">Заявлено экспертов</th>';
      VAL = VAL || '<th>Работ на 1 эксперта</th>';
      VAL = VAL || '<th data-field="checked">Проверено работ</th>';
  VAL = VAL || '</tr>';
  SUSPEND;

  V$PREV_ID = -1;

  IF(V$ALL = 0) THEN
  BEGIN

      -- Назначены конкретные ОУ + сюда же добавляем конкретную ОУ при тестировании уровня ОУ
      FOR
          SELECT COALESCE(D.AREA_ID, 0), COALESCE(D.AREA_NAME, ''), A.OU_ID, D.NAME_SHORT
          FROM UT_EXAM_OU_ASSN A
          LEFT JOIN UT_OU_DESC(A.OU_ID) D ON 1 = 1
          WHERE A.DATE_DEL IS NULL AND A.EXAM_ID = :I$EXAM_ID AND A.OU_ID <> 0
          ORDER BY 2, 4
          INTO :V$AREA_ID, :V$AREA_NAME, :V$ID, :V$S
      DO
      BEGIN

          VAL = '';
          N1= NULL;
          N2 = NULL;
          N3 = NULL;

          IF(V$AREA_ID <> V$PREV_ID) THEN
          BEGIN
              VAL = VAL || '<tr class="district">';
                  VAL = VAL || '<td colspan="6">Район: ' || V$AREA_NAME || '</td>';
              VAL = VAL || '</tr>';
          END
          V$PREV_ID = V$AREA_ID;

          SELECT COUNT(*)
          FROM UT_EXAM_PERSON_ASSN A
          LEFT JOIN UT_PERSON_DESC(A.PERSON_ID) D ON 1 = 1
          WHERE A.DATE_DEL IS NULL AND A.EXAM_ID = :I$EXAM_ID AND A.OU_ID = :V$ID
          INTO :N1;

          SELECT COUNT(*)
          FROM UT_EXAM_EXPERT_ASSN A
          JOIN UT_EXPERTS E ON E.EXPERT_ID = A.EXPERT_ID AND E.DATE_DEL IS NULL AND E.ORG_ID = :V$ID
          WHERE A.DATE_DEL IS NULL AND A.EXAM_ID = :I$EXAM_ID
          INTO :N2;

          IF(N1 IS NULL OR N2 IS NULL OR N2 = 0) THEN V = '-'; ELSE V = CAST((N1 / N2) AS NUMERIC(18, 1));

          -- Счетчик проверок экспертами этой ОУ (считаем все проверки - как первую, так и повторную)
          SELECT COUNT(DISTINCT S.OBJ_ID)
          FROM UT_SESSIONS S
          JOIN UT_SESSION_QUESTIONS SQ ON SQ.DATE_DEL IS NULL AND SQ.SESSION_ID = S.OBJ_ID
          JOIN UT_SESSION_CHECKS SC ON SC.DATE_DEL IS NULL AND SC.QUESTION_ID = SQ.OBJ_ID
          JOIN UT_EXPERTS E ON E.EXPERT_ID = SC.EXPERT_ID AND E.ORG_ID = :V$ID
          WHERE S.DATE_DEL IS NULL AND S.ED_ID = :I$EXAM_ID
          INTO :N3;

          VAL = VAL || '<tr class="detailed" detail-id="' || V$ID || '">';
              VAL = VAL || '<td>' || V$AREA_NAME || '</td>';
              VAL = VAL || '<td>' || V$S || '</td>';
              VAL = VAL || '<td>' || N1 || '</td>';
              VAL = VAL || '<td>' || N2 || '</td>';
              VAL = VAL || '<td>' || V || '</td>';
              VAL = VAL || '<td>' || N3 || '</td>';
          VAL = VAL || '</tr>';
          SUSPEND;

      END

  END
  ELSE
  BEGIN

      -- Назначены все ОУ, идем по уникальному списку из числа участников и экспертов
      FOR
          SELECT DISTINCT COALESCE(D.AREA_ID, 0), COALESCE(D.AREA_NAME, ''), D.OU_ID, D.OU_NAME
          FROM UT_EXAM_PERSON_ASSN A
          LEFT JOIN UT_PERSON_DESC(A.PERSON_ID) D ON 1 = 1
          WHERE A.DATE_DEL IS NULL AND A.EXAM_ID = :I$EXAM_ID
          UNION
          SELECT DISTINCT COALESCE(D.AREA_ID, 0), COALESCE(D.AREA_NAME, ''), D.OBJ_ID, D.NAME_SHORT
          FROM UT_EXAM_EXPERT_ASSN A
          JOIN UT_EXPERTS E ON E.EXPERT_ID = A.EXPERT_ID AND E.DATE_DEL IS NULL
          JOIN UT_OU_DESC(E.ORG_ID) D ON 1 = 1
          WHERE A.DATE_DEL IS NULL AND A.EXAM_ID = :I$EXAM_ID
          ORDER BY 2, 4
          INTO :V$AREA_ID, :V$AREA_NAME, :V$ID, :V$S
      DO
      BEGIN

          VAL = '';
          N1 = NULL;
          N2 = NULL;
          N3 = NULL;

          IF(V$AREA_ID <> V$PREV_ID) THEN
          BEGIN
              VAL = VAL || '<tr class="district">';
                  VAL = VAL || '<td colspan="6">Район: ' || V$AREA_NAME || '</td>';
              VAL = VAL || '</tr>';
          END
          V$PREV_ID = V$AREA_ID;

          SELECT COUNT(*)
          FROM UT_EXAM_PERSON_ASSN A
          LEFT JOIN UT_PERSON_DESC(A.PERSON_ID) D ON 1 = 1
          WHERE A.DATE_DEL IS NULL AND A.EXAM_ID = :I$EXAM_ID AND A.OU_ID = :V$ID
          INTO :N1;

          SELECT COUNT(*)
          FROM UT_EXAM_EXPERT_ASSN A
          JOIN UT_EXPERTS E ON E.EXPERT_ID = A.EXPERT_ID AND E.DATE_DEL IS NULL AND E.ORG_ID = :V$ID
          WHERE A.DATE_DEL IS NULL AND A.EXAM_ID = :I$EXAM_ID
          INTO :N2;

          IF(N1 IS NULL OR N2 IS NULL OR N2 = 0) THEN V = '-'; ELSE V = CAST((N1 / N2) AS NUMERIC(18, 1));

          -- Счетчик проверок экспертами этой ОУ (считаем все проверки - как первую, так и повторную)
          SELECT COUNT(DISTINCT S.OBJ_ID)
          FROM UT_SESSIONS S
          JOIN UT_SESSION_QUESTIONS SQ ON SQ.DATE_DEL IS NULL AND SQ.SESSION_ID = S.OBJ_ID
          JOIN UT_SESSION_CHECKS SC ON SC.DATE_DEL IS NULL AND SC.QUESTION_ID = SQ.OBJ_ID
          JOIN UT_EXPERTS E ON E.EXPERT_ID = SC.EXPERT_ID AND E.ORG_ID = :V$ID
          WHERE S.DATE_DEL IS NULL AND S.ED_ID = :I$EXAM_ID
          INTO :N3;

          VAL = VAL || '<tr class="detailed" detail-id="' || V$ID || '">';
              VAL = VAL || '<td>' || V$AREA_NAME || '</td>';
              VAL = VAL || '<td>' || V$S || '</td>';
              VAL = VAL || '<td>' || N1 || '</td>';
              VAL = VAL || '<td>' || N2 || '</td>';
              VAL = VAL || '<td>' || V || '</td>';
              VAL = VAL || '<td>' || N3 || '</td>';
          VAL = VAL || '</tr>';
          SUSPEND;

      END

  END

  VAL = '</table>';
  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_EXAM_REPORT_MEMBERS (
    I$EXAM_ID BIGINT,
    I$USER_ID VARCHAR(40),
    I$ORDER VARCHAR(40) = null)
RETURNS (
    VAL VARCHAR(8000))
AS
declare variable V$S varchar(1000);
declare variable V$ID bigint;
declare variable V$D date;
declare variable V$H_LEVEL smallint;
declare variable V$ORG_REF bigint;
declare variable V$ALL smallint;
declare variable V$AREA_NAME varchar(400);
declare variable V$AREA_ID bigint;
declare variable V$PREV_ID bigint;
declare variable N1 integer;
declare variable N2 integer;
declare variable N3 integer;
declare variable N4 integer;
begin

  SELECT D.OBJ_ID, D.OBJ_NAME, D.EXAM_DATE_START, D.H_LEVEL, D.ORG_REF
  FROM UT_EXAM_DATES D
  WHERE D.OBJ_ID = :I$EXAM_ID AND D.DATE_DEL IS NULL
  INTO :V$ID, :V$S, :V$D, :V$H_LEVEL, :V$ORG_REF;

  IF(V$ID IS NULL) THEN EXCEPTION DATA_ERROR 'Тестирование не найдено';

  -- Порядок сортировки по ОУ, но группировка всегда по районам
  IF(I$ORDER IS NULL) THEN I$ORDER = 'ou';

  -- Есть ли назначение "все ОУ" ?
  V$ALL = 0;
  SELECT FIRST 1 1
  FROM UT_EXAM_OU_ASSN A
  WHERE A.DATE_DEL IS NULL AND A.EXAM_ID = :I$EXAM_ID AND A.OU_ID = 0
  INTO :V$ALL;

  -- Если это тестирование уровня ОУ, выдаем как будто назначены все ОУ
  IF(V$H_LEVEL = 0) THEN V$ALL = 1;

  -- Шапка HTML
  VAL = '<style>';
  VAL = VAL || '.report-table tr td { padding: 0.1rem 0.5rem; } ';
  VAL = VAL || '.report-table tr:nth-child(odd) td { background-color: rgba(0,0,0,0.05); } ';
  VAL = VAL || '.report-table tr th { padding: 0.1rem 0.5rem; border-bottom: 2px solid gray; } ';
  VAL = VAL || '.report-table tr th:nth-child(1), .report-table tr td:nth-child(1) { width: 25%; } ';
  VAL = VAL || '.report-table tr th:nth-child(2), .report-table tr td:nth-child(2) { width: 35%; } ';
  VAL = VAL || '.district { font-weight: bold } ';
  VAL = VAL || '</style>';

  VAL = VAL || '<h1 style="font-size: 16px;">Отчет по участникам тестирования</h1>';
  VAL = VAL || '<h2 style="font-size: 14px;">' || V$S || '</h2>';
  VAL = VAL || '<h3 style="font-size: 14px; margin-top: 0 ! important;">Дата начала тестирования: ' || (SELECT RESULT FROM DATE2STR(:V$D)) || '</h3>';

  SUSPEND;
  VAL = '';

  VAL = VAL || '<table class="content-table report-table" style="border-collapse: collapse; width: 100%;" data-order="' || I$ORDER || '">';
  VAL = VAL || '<tr>';
      VAL = VAL || '<th>Район</th>';
      VAL = VAL || '<th data-field="ou">ОУ</th>';
      VAL = VAL || '<th data-field="members">Заявлено участников</th>';
      VAL = VAL || '<th data-field="printed">Распечатано бланков</th>';
      VAL = VAL || '<th data-field="reported">Фактически участвовало</th>';
      VAL = VAL || '<th data-field="completed">Завершено</th>';
  VAL = VAL || '</tr>';
  SUSPEND;

  V$PREV_ID = -1;

  IF(V$ALL = 0) THEN
  BEGIN

      -- Назначены конкретные ОУ
      FOR
          SELECT COALESCE(D.AREA_ID, 0), COALESCE(D.AREA_NAME, ''), A.OU_ID, D.NAME_SHORT
          FROM UT_EXAM_OU_ASSN A
          LEFT JOIN UT_OU_DESC(A.OU_ID) D ON 1 = 1
          WHERE A.DATE_DEL IS NULL AND A.EXAM_ID = :I$EXAM_ID AND A.OU_ID <> 0
          ORDER BY 2, 4
          INTO :V$AREA_ID, :V$AREA_NAME, :V$ID, :V$S
      DO
      BEGIN

          VAL = '';
          N1 =  NULL;
          N2 = NULL;
          N3 = NULL;
          N4 = NULL;

          IF(V$AREA_ID <> V$PREV_ID) THEN
          BEGIN
              VAL = VAL || '<tr class="district">';
                  VAL = VAL || '<td colspan="6">Район: ' || V$AREA_NAME || '</td>';
              VAL = VAL || '</tr>';
          END
          V$PREV_ID = V$AREA_ID;

          -- Зарегистрировано
          SELECT COUNT(*)
          FROM UT_EXAM_PERSON_ASSN A
          LEFT JOIN UT_PERSON_DESC(A.PERSON_ID) D ON 1 = 1
          WHERE A.DATE_DEL IS NULL AND A.EXAM_ID = :I$EXAM_ID AND A.OU_ID = :V$ID
          INTO :N1;

          -- Распечатано бланков
          SELECT COUNT(*)
          FROM UT_EXAM_PERSON_ASSN A
          LEFT JOIN UT_PERSON_DESC(A.PERSON_ID) D ON 1 = 1
          WHERE A.DATE_DEL IS NULL AND A.EXAM_ID = :I$EXAM_ID AND A.OU_ID = :V$ID AND A.BLANKS_PRINTED <> 0
          INTO :N2;

          -- Загружено бланков (считаем по созданным сессиям)
          SELECT COUNT(*)
          FROM UT_SESSIONS S
          JOIN UT_EXAM_PERSON_ASSN A ON A.PERSON_ID = S.PERSON_ID AND A.DATE_DEL IS NULL
          LEFT JOIN UT_PERSON_DESC(S.PERSON_ID) D ON 1 = 1
          WHERE S.DATE_DEL IS NULL AND S.ED_ID = :I$EXAM_ID AND A.OU_ID = :V$ID
          INTO :N3;

          -- Обработка завершена в любом статусе
          SELECT COUNT(*)
          FROM UT_SESSIONS S
          JOIN UT_EXAM_PERSON_ASSN A ON A.PERSON_ID = S.PERSON_ID AND A.DATE_DEL IS NULL
          LEFT JOIN UT_PERSON_DESC(S.PERSON_ID) D ON 1 = 1
          WHERE S.DATE_DEL IS NULL AND S.ED_ID = :I$EXAM_ID AND A.OU_ID = :V$ID AND S.STATE_ID IN (100, 101, 102)
          INTO :N4;

          VAL = VAL || '<tr class="detailed" detail-id="' || V$ID || '">';
              VAL = VAL || '<td>' || V$AREA_NAME || '</td>';
              VAL = VAL || '<td>' || V$S || '</td>';
              VAL = VAL || '<td>' || N1 || '</td>';
              VAL = VAL || '<td>' || N2 || '</td>';
              VAL = VAL || '<td>' || N3 || '</td>';
              VAL = VAL || '<td>' || N4 || '</td>';
          VAL = VAL || '</tr>';
          SUSPEND;

      END

  END
  ELSE
  BEGIN

      -- Назначены все ОУ, идем по уникальному списку из числа участников
      FOR
          SELECT DISTINCT COALESCE(D.AREA_ID, 0), COALESCE(D.AREA_NAME, ''), D.OU_ID, D.OU_NAME, COUNT(*)
          FROM UT_EXAM_PERSON_ASSN A
          LEFT JOIN UT_PERSON_DESC(A.PERSON_ID) D ON 1 = 1
          WHERE A.DATE_DEL IS NULL AND A.EXAM_ID = :I$EXAM_ID
          GROUP BY 1, 2, 3, 4
          ORDER BY 2, 4
          INTO :V$AREA_ID, :V$AREA_NAME, :V$ID, :V$S, :N1
      DO
      BEGIN

          VAL = '';
          N2 = NULL;
          N3 = NULL;
          N4 = NULL;

          IF(V$AREA_ID <> V$PREV_ID) THEN
          BEGIN
              VAL = VAL || '<tr class="district">';
                  VAL = VAL || '<td colspan="6">Район: ' || V$AREA_NAME || '</td>';
              VAL = VAL || '</tr>';
          END
          V$PREV_ID = V$AREA_ID;

          -- Зарегистрировано
          SELECT COUNT(*)
          FROM UT_EXAM_PERSON_ASSN A
          LEFT JOIN UT_PERSON_DESC(A.PERSON_ID) D ON 1 = 1
          WHERE A.DATE_DEL IS NULL AND A.EXAM_ID = :I$EXAM_ID AND A.OU_ID = :V$ID
          INTO :N1;

          -- Распечатано бланков
          SELECT COUNT(*)
          FROM UT_EXAM_PERSON_ASSN A
          LEFT JOIN UT_PERSON_DESC(A.PERSON_ID) D ON 1 = 1
          WHERE A.DATE_DEL IS NULL AND A.EXAM_ID = :I$EXAM_ID AND A.OU_ID = :V$ID AND A.BLANKS_PRINTED <> 0
          INTO :N2;

          -- Загружено бланков (считаем по созданным сессиям)
          SELECT COUNT(*)
          FROM UT_SESSIONS S
          JOIN UT_EXAM_PERSON_ASSN A ON A.PERSON_ID = S.PERSON_ID AND A.DATE_DEL IS NULL
          LEFT JOIN UT_PERSON_DESC(S.PERSON_ID) D ON 1 = 1
          WHERE S.DATE_DEL IS NULL AND S.ED_ID = :I$EXAM_ID AND A.OU_ID = :V$ID
          INTO :N3;

          -- Обработка завершена в любом статусе
          SELECT COUNT(*)
          FROM UT_SESSIONS S
          JOIN UT_EXAM_PERSON_ASSN A ON A.PERSON_ID = S.PERSON_ID AND A.DATE_DEL IS NULL
          LEFT JOIN UT_PERSON_DESC(S.PERSON_ID) D ON 1 = 1
          WHERE S.DATE_DEL IS NULL AND S.ED_ID = :I$EXAM_ID AND A.OU_ID = :V$ID AND S.STATE_ID IN (100, 101, 102)
          INTO :N4;

          VAL = VAL || '<tr class="detailed" detail-id="' || V$ID || '">';
              VAL = VAL || '<td>' || V$AREA_NAME || '</td>';
              VAL = VAL || '<td>' || V$S || '</td>';
              VAL = VAL || '<td>' || N1 || '</td>';
              VAL = VAL || '<td>' || N2 || '</td>';
              VAL = VAL || '<td>' || N3 || '</td>';
              VAL = VAL || '<td>' || N4 || '</td>';
          VAL = VAL || '</tr>';
          SUSPEND;

      END

  END

  VAL = '</table>';
  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_EXAM_REPORT_MEMBERS_DTL (
    I$EXAM_ID BIGINT,
    I$DETAIL_ID BIGINT,
    I$USER_ID VARCHAR(40),
    I$ORDER VARCHAR(40) = null)
RETURNS (
    VAL VARCHAR(8000))
AS
declare variable V$S varchar(1000);
declare variable V$ID bigint;
declare variable V$D date;
declare variable V$H_LEVEL smallint;
declare variable V$ORG_REF bigint;
declare variable V$S2 varchar(1000);
declare variable V$BLANKS_PRINTED smallint;
declare variable N1 integer;
declare variable N2 integer;
begin

  SELECT D.OBJ_ID, D.OBJ_NAME, D.EXAM_DATE_START, D.H_LEVEL, D.ORG_REF
  FROM UT_EXAM_DATES D
  WHERE D.OBJ_ID = :I$EXAM_ID AND D.DATE_DEL IS NULL
  INTO :V$ID, :V$S, :V$D, :V$H_LEVEL, :V$ORG_REF;

  IF(V$ID IS NULL) THEN EXCEPTION DATA_ERROR 'Тестирование не найдено';

  V$S2 = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$DETAIL_ID));

  VAL = '<style>';
  VAL = VAL || '.report-table2 tr td { padding: 0.1rem 0.5rem; } ';
  VAL = VAL || '.report-table2 tr:nth-child(odd) td { background-color: rgba(0,0,0,0.05); } ';
  VAL = VAL || '.report-table2 tr th { padding: 0.1rem 0.5rem; border-bottom: 2px solid gray; } ';
  VAL = VAL || '.report-table2 tr th:nth-child(1), .report-table2 tr td:nth-child(1) { width: 35%; } ';
  VAL = VAL || '.report-table2 tr th:nth-child(3), .report-table2 tr td:nth-child(2) { width: 30%; } ';
  VAL = VAL || '</style>';

  VAL = VAL || '<h1 style="font-size: 16px;">Отчет по участникам тестирования (' || V$S2 || ')</h1>';
  VAL = VAL || '<h2 style="font-size: 14px;">' || V$S || '</h2>';
  VAL = VAL || '<h3 style="font-size: 14px; margin-top: 0 ! important;">Дата начала тестирования: ' || (SELECT RESULT FROM DATE2STR(:V$D)) || '</h3>';

  SUSPEND;
  VAL = '';

  VAL = VAL || '<table class="content-table report-table2" style="border-collapse: collapse; width: 100%;" data-order="' || V$S2 || '">';
  VAL = VAL || '<tr>';
      VAL = VAL || '<th data-field="members">Участник</th>';
      VAL = VAL || '<th data-field="printed">Бланки распечатаны</th>';
      VAL = VAL || '<th data-field="blanks">Номера бланков</th>';
      VAL = VAL || '<th data-field="reported">Сканы загружены</th>';
      VAL = VAL || '<th data-field="completed">Обработка завершена</th>';
  VAL = VAL || '</tr>';
  SUSPEND;

  FOR
      SELECT PA.OBJ_ID, D.NAME_FULL, PA.BLANKS_PRINTED
      FROM UT_EXAM_PERSON_ASSN PA
      LEFT JOIN UT_PERSON_DESC(PA.PERSON_ID) D ON 1 = 1
      WHERE PA.DATE_DEL IS NULL AND PA.EXAM_ID = :I$EXAM_ID AND PA.OU_ID = :I$DETAIL_ID
      ORDER BY 2
      INTO :V$ID, :V$S, :V$BLANKS_PRINTED
  DO
  BEGIN

      SELECT COUNT(*)
      FROM UT_SESSIONS S
      WHERE S.DATE_DEL IS NULL AND S.ED_ID = :I$EXAM_ID AND S.PERSON_ID = :V$ID
      INTO :N1;

      SELECT COUNT(*)
      FROM UT_SESSIONS S
      WHERE S.DATE_DEL IS NULL AND S.ED_ID = :I$EXAM_ID AND S.PERSON_ID = :V$ID AND S.STATE_ID IN (100, 101, 102)
      INTO :N2;

      SELECT COALESCE(LIST(B.BARCODE_DATA, ', '), '-')
      FROM UT_SESSIONS S
      JOIN UT_BLANKS B ON B.DATE_DEL IS NULL AND B.SESSION_ID = S.OBJ_ID
      WHERE S.DATE_DEL IS NULL AND S.ED_ID = :I$EXAM_ID AND S.PERSON_ID = :V$ID AND S.STATE_ID IN (100, 101, 102)
      INTO :V$S2;

      VAL = '<tr detail-id="' || V$ID || '">';
          VAL = VAL || '<td>' || V$S || '</td>';
          VAL = VAL || '<td>' || IIF(V$BLANKS_PRINTED = 0, 'Нет', 'Да') || '</td>';
          VAL = VAL || '<td>' || V$S2 || '</td>';
          VAL = VAL || '<td>' || IIF(N1 = 0, 'Нет', 'Да') || '</td>';
          VAL = VAL || '<td>' || IIF(N2 = 0, 'Нет', 'Да') || '</td>';
      VAL = VAL || '</tr>';

      SUSPEND;

  END

  VAL = '</table>';
  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_EXAM_RESULTS_EXPORT (
    I$EXAM_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    SESSION_ID BIGINT,
    PERSON_ID BIGINT,
    NAME_FULL VARCHAR(400),
    OU_ID BIGINT,
    OU_NAME VARCHAR(400),
    COL_INDEX INTEGER,
    VAL INTEGER)
AS
declare variable V$STRUCT_ID bigint;
declare variable V$VARIANT_ID bigint;
declare variable V$VAR_NUM integer;
declare variable N_AB integer;
declare variable N_C integer;
declare variable N_CRITERIAS integer;
declare variable CRITERIA integer;
declare variable SCORE integer;
declare variable V$QUESTION_ID bigint;
declare variable V$QUESTION_NUM integer;
declare variable N integer;
begin

  -- В столбце 1 идет ФИО, 2 = ОУ, 3 - номер варианта, 4 = сумма баллов, 5 = отметка
  -- Далее N ячеек вопросов типа AB, далее результаты проверок типа C по критериям - 1,2,3 проверки

  -- Уточняем количество вопросов типа AB, C, а также общее количество критериев в вопросах типа C
  SELECT FIRST 1 T.STRUCT_ID, TV.OBJ_ID
  FROM UT_EXAM_TEST_VARS ETV
  JOIN UT_TEST_VARS TV ON TV.OBJ_ID = ETV.TEST_VAR_ID
  JOIN UT_TESTS T ON T.OBJ_ID = TV.TEST_ID
  WHERE ETV.DATE_DEL IS NULL AND ETV.EXAM_ID = :I$EXAM_ID
  INTO :V$STRUCT_ID, :V$VARIANT_ID;

  SELECT COUNT(*)
  FROM UT_TEST_STRUCT_POINTS TSP
  WHERE TSP.DATE_DEL IS NULL AND TSP.STRUCT_ID = :V$STRUCT_ID AND TSP.Q_TYPE_ID IN (1, 2, 4)
  INTO :N_AB;

  SELECT COUNT(*)
  FROM UT_TEST_STRUCT_POINTS TSP
  WHERE TSP.DATE_DEL IS NULL AND TSP.STRUCT_ID = :V$STRUCT_ID AND TSP.Q_TYPE_ID IN (3, 8)
  INTO :N_C;

  SELECT COUNT(*)
  FROM UT_TEST_VAR_QUESTIONS TVQ
  JOIN UT_QUESTIONS Q ON Q.OBJ_ID = TVQ.QUESTION_ID AND Q.QUESTION_TYPE IN (3, 8)
  JOIN UT_ANSWERS A ON A.DATE_DEL IS NULL AND A.QUESTION_ID = Q.OBJ_ID
  WHERE TVQ.DATE_DEL IS NULL AND TVQ.VAR_ID = :V$VARIANT_ID AND TVQ.ORDER_INDEX = 1
  INTO :N_CRITERIAS;

  -- Отдаем описание вопросов - номера, баллы
  FOR
      SELECT TSP.Q_ORDER, TSP.Q_MAX_SCORE
      FROM UT_TEST_STRUCT_POINTS TSP
      WHERE TSP.DATE_DEL IS NULL AND TSP.STRUCT_ID = :V$STRUCT_ID AND TSP.Q_TYPE_ID IN (1, 2, 4)
      INTO :COL_INDEX, :SCORE
  DO
  BEGIN
      NAME_FULL = 'AB ' || COL_INDEX ||' (' || SCORE || ')';
      COL_INDEX = COL_INDEX + 5;
      SUSPEND;
  END

  N = N_AB;
  FOR
      SELECT TSP.Q_ORDER, A.SORT_ORDER, A.A_LEVEL
      FROM UT_TEST_VAR_QUESTIONS TVQ
      JOIN UT_TEST_STRUCT_POINTS TSP ON TSP.OBJ_ID = TVQ.STRUCT_POINT_ID
      JOIN UT_QUESTIONS Q ON Q.OBJ_ID = TVQ.QUESTION_ID AND Q.QUESTION_TYPE IN (3, 8)
      JOIN UT_ANSWERS A ON A.DATE_DEL IS NULL AND A.QUESTION_ID = Q.OBJ_ID
      WHERE TVQ.DATE_DEL IS NULL AND TVQ.VAR_ID = :V$VARIANT_ID AND TVQ.ORDER_INDEX = 1
      ORDER BY 1, 2
      INTO :COL_INDEX, :CRITERIA, :SCORE
  DO
  BEGIN
      -- Выдаем однократно, общий итог
      NAME_FULL = 'C ' || COL_INDEX || '.' || CRITERIA || ' (' || SCORE || ')';
      COL_INDEX = 6 + N;
      N = N + 1;
      SUSPEND;
  END

  -- Пошли по отметкам
  FOR
      SELECT S.OBJ_ID, D.OU_ID, D.OU_NAME, S.PERSON_ID, D.NAME_FULL, TV.NUM, S.RAW_RESULT
      FROM UT_SESSIONS S
      JOIN UT_EXAM_TEST_VARS ETV ON ETV.OBJ_ID = S.VARIANT_ID
      JOIN UT_TEST_VARS TV ON TV.OBJ_ID = ETV.TEST_VAR_ID
      JOIN UT_PERSON_DESC(S.PERSON_ID) D ON 1 = 1
      WHERE S.DATE_DEL IS NULL AND S.ED_ID = :I$EXAM_ID
      ORDER BY 3, 5
      INTO :SESSION_ID, :OU_ID, :OU_NAME, :PERSON_ID, :NAME_FULL, :V$VAR_NUM, :SCORE
  DO
  BEGIN

      -- Титул участника, и далее пойдут пустые ФИО и ОУ
      COL_INDEX = NULL;
      VAL = NULL;
      SUSPEND;

      NAME_FULL = NULL;
      OU_NAME = NULL;

      -- Номер варианта
      COL_INDEX = 3;
      VAL = V$VAR_NUM;
      SUSPEND;

      -- Сырой балл
      COL_INDEX = 4;
      VAL = SCORE;
      SUSPEND;

      -- Оценка
      COL_INDEX = 5;
      VAL = NULL;
      SUSPEND;

      -- Вопросы типа AB (начиная с 4 столбца), результаты в самом вопросе
      FOR
          SELECT TSP.Q_ORDER, SQ.RAW_RESULT
          FROM UT_SESSION_QUESTIONS SQ
          JOIN UT_TEST_VAR_QUESTIONS TVQ ON TVQ.OBJ_ID = SQ.QUESTION_ID
          JOIN UT_TEST_STRUCT_POINTS TSP ON TSP.OBJ_ID = TVQ.STRUCT_POINT_ID AND TSP.Q_TYPE_ID IN (1, 2, 4)
          WHERE SQ.DATE_DEL IS NULL AND SQ.SESSION_ID = :SESSION_ID
          ORDER BY TSP.Q_ORDER
          INTO :COL_INDEX, :VAL
      DO
      BEGIN
          COL_INDEX = COL_INDEX + 5;
          SUSPEND;
      END

      -- Вопросы типа C - идем последовательно по вопросам
      N = N_AB;
      FOR
          SELECT TSP.Q_ORDER, SQ.OBJ_ID
          FROM UT_SESSION_QUESTIONS SQ
          JOIN UT_TEST_VAR_QUESTIONS TVQ ON TVQ.OBJ_ID = SQ.QUESTION_ID
          JOIN UT_TEST_STRUCT_POINTS TSP ON TSP.OBJ_ID = TVQ.STRUCT_POINT_ID AND TSP.Q_TYPE_ID IN (3, 8)
          WHERE SQ.DATE_DEL IS NULL AND SQ.SESSION_ID = :SESSION_ID
          ORDER BY TSP.Q_ORDER
          INTO :V$QUESTION_NUM, :V$QUESTION_ID
      DO
      BEGIN
          -- Идем по номерам критериев в данном номере вопроса
          FOR
              SELECT A.SORT_ORDER, CR.RAW_RESULT
              FROM UT_TEST_VAR_QUESTIONS TVQ
              JOIN UT_TEST_STRUCT_POINTS TSP ON TSP.OBJ_ID = TVQ.STRUCT_POINT_ID AND TSP.Q_ORDER = :V$QUESTION_NUM
              JOIN UT_QUESTIONS Q ON Q.OBJ_ID = TVQ.QUESTION_ID AND Q.QUESTION_TYPE IN (3, 8)
              JOIN UT_ANSWERS A ON A.DATE_DEL IS NULL AND A.QUESTION_ID = Q.OBJ_ID
              JOIN UT_SESSION_CHECKS C ON C.DATE_DEL IS NULL AND C.QUESTION_ID = :V$QUESTION_ID AND C.EXPERT_ID IS NULL
              JOIN UT_SESSION_CHECK_RES CR ON CR.DATE_DEL IS NULL AND CR.CHECK_ID = C.OBJ_ID AND CR.CRITERIA_ID = A.SORT_ORDER
              WHERE TVQ.DATE_DEL IS NULL AND TVQ.VAR_ID = :V$VARIANT_ID AND TVQ.ORDER_INDEX = 1
              ORDER BY 1
              INTO :SCORE, :VAL
          DO
          BEGIN
              COL_INDEX = 6 + N;
              N = N + 1;
              SUSPEND;
          END
      END

  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_EXAM_RESULTS_RESET (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    N INTEGER)
AS
begin

  -- Физически прибиваем все сессии
  DELETE FROM UT_SESSIONS
  WHERE ED_ID = :I$OBJ_ID;

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_EXAM_RESULTS_RUN (
    I$EXAM_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    N INTEGER)
AS
declare variable V$PERSON_ID bigint;
declare variable V$SESSION_ID bigint;
declare variable V$VARIANT_ID bigint;
declare variable V$REAL_VAR bigint;
declare variable V$SOURCE_ID bigint;
declare variable V$QUESTION_TYPE integer;
declare variable V$QUESTION_SCORE integer;
declare variable V$QUESTION_ID bigint;
declare variable V double precision;
begin

  -- Сессии всех участников должны быть созданы. Новые формируем в статусе 10
  FOR
      SELECT PA.PERSON_ID
      FROM UT_EXAM_PERSON_ASSN PA
      LEFT JOIN UT_SESSIONS S ON S.ED_ID = :I$EXAM_ID AND S.PERSON_ID = PA.PERSON_ID AND S.DATE_DEL IS NULL
      WHERE PA.EXAM_ID = :I$EXAM_ID AND PA.DATE_DEL IS NULL AND S.OBJ_ID IS NULL
      INTO :V$PERSON_ID
  DO
  BEGIN

      -- Формируем сессию в статусе 10
      V$VARIANT_ID = NULL;
      SELECT FIRST 1 TV.OBJ_ID, V.OBJ_ID
      FROM UT_EXAM_TEST_VARS TV
      JOIN UT_TEST_VARS V ON V.OBJ_ID = TV.TEST_VAR_ID AND V.DATE_DEL IS NULL
      JOIN UT_TESTS T ON T.OBJ_ID = V.TEST_ID
      WHERE TV.EXAM_ID = :I$EXAM_ID AND TV.DATE_DEL IS NULL
      ORDER BY RAND()
      INTO :V$VARIANT_ID, :V$REAL_VAR;

      IF(V$VARIANT_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не удалось подобрать вариант';

      INSERT INTO UT_SESSIONS
      (ED_ID, PERSON_ID, VARIANT_ID, STATE_ID)
      VALUES (:I$EXAM_ID, :V$PERSON_ID, :V$VARIANT_ID, 10)
      RETURNING OBJ_ID INTO :V$SESSION_ID;

      -- Вопросы - формируем в статусе 21
      FOR
          SELECT VQ.OBJ_ID, Q.QUESTION_TYPE, Q.MAX_SCORE
          FROM UT_TEST_VAR_QUESTIONS VQ
          JOIN UT_QUESTIONS Q ON Q.OBJ_ID = VQ.QUESTION_ID
          WHERE VQ.VAR_ID = :V$REAL_VAR AND VQ.DATE_DEL IS NULL
          INTO :V$SOURCE_ID, :V$QUESTION_TYPE, :V$QUESTION_SCORE
      DO
      BEGIN

          INSERT INTO UT_SESSION_QUESTIONS
          (SESSION_ID, QUESTION_ID, RAW_RESULT, STATE_ID)
          VALUES (:V$SESSION_ID, :V$SOURCE_ID, NULL, 21)
          RETURNING OBJ_ID INTO :V$QUESTION_ID;

          /*INSERT INTO UT_SESSION_RESULTS
          (QUESTION_ID, LEVEL_ID, CRITERIA_ID, RAW_RESULT)
          VALUES (:V$QUESTION_ID, 0, 0, NULL);*/

      END

  END

  -- А теперь берем по одному ответу, формируем результат и меняем статус
  V$SESSION_ID = NULL;
  V$QUESTION_ID = NULL;

  FOR
      SELECT FIRST 10 S.OBJ_ID, SQ.OBJ_ID, Q.QUESTION_TYPE, Q.MAX_SCORE
      FROM UT_SESSIONS S
      JOIN UT_SESSION_QUESTIONS SQ ON SQ.SESSION_ID = S.OBJ_ID AND SQ.DATE_DEL IS NULL
      JOIN UT_TEST_VAR_QUESTIONS VQ ON VQ.OBJ_ID = SQ.QUESTION_ID
      JOIN UT_QUESTIONS Q ON Q.OBJ_ID = VQ.QUESTION_ID
      WHERE S.DATE_DEL IS NULL AND S.ED_ID = :I$EXAM_ID AND S.STATE_ID < 1000
      ORDER BY RAND()
      INTO :V$SESSION_ID, :V$QUESTION_ID, V$QUESTION_TYPE, :V$QUESTION_SCORE
  DO
  BEGIN

      -- Для вопросов на 1 балл поднимаем вероятность правильного ответа
      IF(V$QUESTION_SCORE = 1) THEN V = SQRT(SQRT(RAND() * V$QUESTION_SCORE)); ELSE V = SQRT(RAND()) * V$QUESTION_SCORE;
      IF(V - TRUNC(V) < 0.5) THEN V = TRUNC(V); ELSE V = TRUNC(V) + 1;

      -- Результат и статус завершенного
      /*UPDATE UT_SESSION_RESULTS
      SET RAW_RESULT = :V, STATE_ID = 1000
      WHERE QUESTION_ID = :V$QUESTION_ID AND LEVEL_ID = 0 AND EXPERT_ID IS NULL AND CRITERIA_ID = 0;*/

      UPDATE UT_SESSION_QUESTIONS
      SET RAW_RESULT = :V, STATE_ID = 1000
      WHERE OBJ_ID = :V$QUESTION_ID;

      -- Итоги - обновляем в сессии
      V = (SELECT SUM(RAW_RESULT) FROM UT_SESSION_QUESTIONS WHERE SESSION_ID = :V$SESSION_ID);

      UPDATE UT_SESSIONS
      SET RAW_RESULT = :V
      WHERE OBJ_ID = :V$SESSION_ID;

      -- Закрываем сессию, когда все вопросы кончились
      IF(NOT EXISTS(
          SELECT FIRST 1 1
          FROM UT_SESSION_QUESTIONS
          WHERE DATE_DEL IS NULL AND SESSION_ID = :V$SESSION_ID AND STATE_ID < 1000
      ))
      THEN
      BEGIN
          UPDATE UT_SESSIONS
          SET STATE_ID = 100
          WHERE OBJ_ID = :V$SESSION_ID;
      END

  END

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_EXAM_RES_ASSN_SET (
    I$EXAM_ID BIGINT NOT NULL,
    I$RES_ID BIGINT NOT NULL,
    I$QTY INTEGER NOT NULL,
    I$USER_ID VARCHAR(40) NOT NULL)
RETURNS (
    OBJ_ID BIGINT)
AS
begin

  IF(I$QTY <= 0) THEN
  BEGIN

    UPDATE UT_EXAM_RES_ASSN
    SET DATE_DEL = CURRENT_TIMESTAMP
    WHERE EXAM_ID = :I$EXAM_ID AND RES_ID = :I$RES_ID AND DATE_DEL IS NULL;

  END
  ELSE
  BEGIN

    INSERT INTO UT_EXAM_RES_ASSN
    (EXAM_ID, RES_ID, QTY)
    VALUES (:I$EXAM_ID, :I$RES_ID, :I$QTY)
    RETURNING OBJ_ID INTO :OBJ_ID;

  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_EXAM_ROOM_ASSN_SET (
    I$EXAM_ID BIGINT,
    I$ROOM_ID BIGINT,
    I$ROLE_ID INTEGER,
    I$USER_ID VARCHAR(40))
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$OBJ_ID bigint;
declare variable V$ROLE_ID integer;
begin

  IF(I$ROLE_ID = 0) THEN
  BEGIN

      -- Снимаем назначение помещения
      -- Есть ли назначения учащихся на места в этом помещении ?
      IF(EXISTS(
          SELECT FIRST 1 1
          FROM UT_PERSON_PLACE_ASSN PA
          JOIN UT_PPE_PLACES P ON P.DATE_DEL IS NULL AND P.OBJ_ID = PA.PERSON_ID AND P.ROOM_ID = :I$ROOM_ID
          WHERE PA.DATE_DEL IS NULL AND PA.EXAM_ID = :I$EXAM_ID
     ))
     THEN EXCEPTION DATA_ERROR 'В помещении уже рассажены участники, необходимо сначала отменить рассадку';

      -- Теперь можно снимать
      SELECT FIRST 1 A.OBJ_ID
      FROM UT_EXAM_ROOM_ASSN A
      WHERE A.DATE_DEL IS NULL AND A.EXAM_ID = :I$EXAM_ID AND A.ROOM_ID = :I$ROOM_ID
      INTO :V$OBJ_ID;

      IF(V$OBJ_ID IS NOT NULL) THEN
      BEGIN
          UPDATE UT_EXAM_ROOM_ASSN
          SET DATE_DEL = CURRENT_TIMESTAMP
          WHERE OBJ_ID = :V$OBJ_ID AND DATE_DEL IS NULL;

          OBJ_ID = NULL;
      END

  END
  ELSE
  BEGIN

      -- Устанавливаем назначение
      -- Есть ли этот ППЭ в тестировании ?
      IF(NOT EXISTS(
          SELECT FIRST 1 1
          FROM UT_PPE_ROOMS R
          JOIN UT_EXAM_PPE_ASSN PA ON PA.DATE_DEL IS NULL AND PA.EXAM_ID = :I$EXAM_ID AND PA.PPE_ID = R.PPE_ID
          WHERE R.OBJ_ID = :I$ROOM_ID AND R.DATE_DEL IS NULL
      ))
      THEN EXCEPTION DATA_ERROR 'ППЭ не задействован в данном тестировании, либо назначение было изменено с другого компьютера';

      -- Нет ли других назначений на тестирования на ту же дату ?
      -- !!!

      SELECT FIRST 1 OBJ_ID, ROLE_ID
      FROM UT_EXAM_ROOM_ASSN A
      WHERE A.DATE_DEL IS NULL AND A.EXAM_ID = :I$EXAM_ID AND A.ROOM_ID = :I$ROOM_ID
      INTO :V$OBJ_ID, :V$ROLE_ID;

      -- Если роль не та - удаляем старое назначение
      -- Нужны проверки, когда роль меняется с основной аудитории на вспомогательную !!!
      IF(V$ROLE_ID <> I$ROLE_ID) THEN
      BEGIN
      END

      -- Работаем только на добавление
      IF(V$OBJ_ID IS NULL) THEN
      BEGIN
          INSERT INTO UT_EXAM_ROOM_ASSN
          (EXAM_ID, ROOM_ID, ROLE_ID)
          VALUES (:I$EXAM_ID, :I$ROOM_ID, :I$ROLE_ID)
          RETURNING OBJ_ID INTO :OBJ_ID;
      END

  END

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_EXAM_SCALE_APPLY (
    I$EXAM_ID BIGINT NOT NULL,
    I$USER_ID VARCHAR(40),
    I$SESSION_ID BIGINT = NULL)
RETURNS (
    STUB INTEGER,
    RESULTS_DONE SMALLINT)
AS
DECLARE VARIABLE V$DB_LEVEL INTEGER;
DECLARE VARIABLE V$STATE INTEGER;
DECLARE VARIABLE V$H_LEVEL INTEGER;
DECLARE VARIABLE V$NMIN INTEGER;
DECLARE VARIABLE V$N0 INTEGER;
DECLARE VARIABLE V$N4 INTEGER;
DECLARE VARIABLE V$N5 INTEGER;
DECLARE VARIABLE V$NMAX INTEGER;
DECLARE VARIABLE V$SESSION_ID BIGINT;
DECLARE VARIABLE V$MARK INTEGER;
DECLARE VARIABLE V$FINAL_ID BIGINT;
DECLARE VARIABLE V$RAW_RESULT INTEGER;
begin

  -- Если указан SESSION_ID, то пересчитываем итоги тестирования для конкретной сессии
  -- после завершения всех ответов на вопросы, вне зависимости от уровня тестирования
  RESULTS_DONE = 0;

  -- Пересчитать результаты можно только на уровне тестирования
  SELECT COALESCE(CAST(K.KEY_VAL AS INTEGER) - 1, 0)
  FROM KEYS K
  WHERE K.KEY_CODE = 'LEVEL'
  INTO :V$DB_LEVEL;

  SELECT FIRST 1 D.EXAM_STATE, D.H_LEVEL, D.SCALE_NMIN, D.SCALE_N0, D.SCALE_N4, D.SCALE_N5, D.SCALE_NMAX
  FROM UT_EXAM_DATES D
  WHERE D.OBJ_ID = :I$EXAM_ID AND D.DATE_DEL IS NULL
  INTO :V$STATE, :V$H_LEVEL, :V$NMIN, :V$N0, :V$N4, :V$N5, :V$NMAX;

  IF(V$STATE IS NULL) THEN EXCEPTION DATA_ERROR 'Тестирование не найдено или было удалено';
  --IF(V$STATE < 800 OR V$STATE >= 1000) THEN EXCEPTION DATA_ERROR 'Тестирование находится в недопустимом статусе';
  IF(V$DB_LEVEL <> V$H_LEVEL) THEN
  BEGIN
    IF(I$SESSION_ID IS NOT NULL) THEN EXIT;
    EXCEPTION DATA_ERROR 'Управление результатами возможно только на уровне владельца тестирования';
  END

  IF(V$NMIN IS NULL OR V$N4 IS NULL OR V$N5 IS NULL) THEN
  BEGIN
    IF(I$SESSION_ID IS NOT NULL) THEN EXIT;
    EXCEPTION DATA_ERROR 'Шкалы не заданы, пересчет невозможен';
  END

  -- Выполняем пересчет итоговых отметок - только там где завершена обработка
  FOR
    SELECT S.OBJ_ID, S.RAW_RESULT
    FROM UT_SESSIONS S
    WHERE S.DATE_DEL IS NULL AND S.ED_ID = :I$EXAM_ID AND S.STATE_ID = 100 AND S.RAW_RESULT IS NOT NULL
      AND (:I$SESSION_ID IS NULL OR S.OBJ_ID = :I$SESSION_ID)
    INTO :V$SESSION_ID, :V$RAW_RESULT
  DO
  BEGIN
    IF(V$RAW_RESULT < V$NMIN) THEN V$MARK = 2;
    ELSE IF(V$RAW_RESULT < V$N4) THEN V$MARK = 3;
    ELSE IF(V$RAW_RESULT < V$N5) THEN V$MARK = 4;
    ELSE V$MARK = 5;

    SELECT FIRST 1 M.MARK_TYPE_ID
    FROM CJ2_MARK_TYPE M
    WHERE M.IS_DEL = 0 AND M.MARK_COST = :V$MARK AND M.PARENT_ID = 400 -- пока только 5-балльная шкала
    INTO :V$FINAL_ID;

    UPDATE UT_SESSIONS S
    SET S.FINAL_RESULT_ID = :V$FINAL_ID
    WHERE OBJ_ID = :V$SESSION_ID;

    -- Этот параметр важен только для конкретной указанной сессии
    RESULTS_DONE = 1;
  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_EXAM_SCALE_SET (
    I$EXAM_ID BIGINT,
    I$SCALE VARCHAR(20),
    I$VALUE INTEGER,
    I$USER_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$STATE integer;
declare variable V$DB_LEVEL integer;
declare variable V$H_LEVEL integer;
begin

  -- Пересчитать результаты можно только на уровне тестирования
  SELECT COALESCE(CAST(K.KEY_VAL AS INTEGER) - 1, 0)
  FROM KEYS K
  WHERE K.KEY_CODE = 'LEVEL'
  INTO :V$DB_LEVEL;

  SELECT FIRST 1 D.EXAM_STATE, D.H_LEVEL
  FROM UT_EXAM_DATES D
  WHERE D.OBJ_ID = :I$EXAM_ID AND D.DATE_DEL IS NULL
  INTO :V$STATE, :V$H_LEVEL;

  IF(V$STATE IS NULL) THEN EXCEPTION DATA_ERROR 'Тестирование не найдено или было удалено';
  -- IF(V$STATE >= 1000) THEN EXCEPTION DATA_ERROR 'Тестирование находится в недопустимом статусе';
  IF(V$DB_LEVEL <> V$H_LEVEL) THEN EXCEPTION DATA_ERROR 'Управление результатами возможно только на уровне владельца тестирования';

  IF(I$VALUE IS NOT NULL AND I$VALUE < 0) THEN EXCEPTION DATA_ERROR 'Отрицательные значения недопустимы';

  I$SCALE = UPPER(I$SCALE);

  IF(I$SCALE = 'N0') THEN
  BEGIN
      UPDATE UT_EXAM_DATES
      SET SCALE_N0 = :I$VALUE
      WHERE OBJ_ID = :I$EXAM_ID AND DATE_DEL IS NULL AND EXAM_STATE < 1000;
  END
  ELSE IF(I$SCALE = 'NMIN') THEN
  BEGIN
      UPDATE UT_EXAM_DATES
      SET SCALE_NMIN = :I$VALUE
      WHERE OBJ_ID = :I$EXAM_ID AND DATE_DEL IS NULL AND EXAM_STATE < 1000;
  END
  ELSE IF(I$SCALE = 'N4') THEN
  BEGIN
      UPDATE UT_EXAM_DATES
      SET SCALE_N4 = :I$VALUE
      WHERE OBJ_ID = :I$EXAM_ID AND DATE_DEL IS NULL AND EXAM_STATE < 1000;
  END
  ELSE IF(I$SCALE = 'N5') THEN
  BEGIN
      UPDATE UT_EXAM_DATES
      SET SCALE_N5 = :I$VALUE
      WHERE OBJ_ID = :I$EXAM_ID AND DATE_DEL IS NULL AND EXAM_STATE < 1000;
  END
  ELSE IF(I$SCALE = 'NMAX') THEN
  BEGIN
      UPDATE UT_EXAM_DATES
      SET SCALE_NMAX = :I$VALUE
      WHERE OBJ_ID = :I$EXAM_ID AND DATE_DEL IS NULL AND EXAM_STATE < 1000;
  END

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_EXAM_SCAN_STATS (
    I$EXAM_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$LEVEL INTEGER,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
declare variable V$OBJ_ID bigint;
declare variable V$H_LEVEL integer;
declare variable V$DB_LEVEL integer;
declare variable V$ORG_REF bigint;
declare variable V$CAPTION varchar(1000);
declare variable V$S varchar(1000);
declare variable V$D timestamp;
declare variable V$STATE integer;
declare variable V$MULT bigint;
declare variable V$TYPE integer;
declare variable N integer;
declare variable V$LOCATION_ID bigint;
begin

  -- LEVEL:
  -- вверх 0 = ОУ, 1 = район, 2 = регион
  -- вниз -1 = пакет, -2 = бланк

  SELECT MULTIPLIER FROM GEN INTO :V$MULT;

  SELECT CAST(KEY_VAL AS INTEGER) - 1
  FROM KEYS
  WHERE KEY_CODE = 'LEVEL'
  INTO :V$DB_LEVEL;

  SELECT D.OBJ_ID, D.H_LEVEL, D.ORG_REF
  FROM UT_EXAM_DATES D
  WHERE D.OBJ_ID = :I$EXAM_ID AND D.DATE_DEL IS NULL
  INTO :V$OBJ_ID, :V$H_LEVEL, :V$ORG_REF;

  IF(V$OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Тестирование не найдено или было удалено';

  -- Ограничиваемся уровнем региона
  IF(V$H_LEVEL > 2) THEN V$H_LEVEL = 2;

  -- Корневой уровень
  IF(I$LEVEL IS NULL) THEN
  BEGIN
      I$LEVEL = MINVALUE(V$H_LEVEL, V$DB_LEVEL);

      IF(I$LEVEL = 0) THEN
      BEGIN
          SELECT FIRST 1 L2.OBJ_ID
          FROM LINKS L2
          WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
          INTO :I$OBJ_ID;
      END
      ELSE IF(I$LEVEL = 1) THEN
      BEGIN
          SELECT FIRST 1 L111.OBJ_ID
          FROM LINKS L111
          WHERE L111.PARENT_ID IS NULL AND L111.OBJ_TYPE_ID = 111 AND L111.DATE_DEL IS NULL
          INTO :I$OBJ_ID;
      END
  END

  IF(I$LEVEL > V$H_LEVEL) THEN EXCEPTION DATA_ERROR 'Неверный код уровня';

  TAG_NAME = 'items';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'items::json&colon;array';
  VAL = 1;
  SUSPEND;

  IF(I$LEVEL = 2) THEN
  BEGIN

      -- Регион, выдаем список районов
      FOR
          SELECT L.LISTVAL_ID, L.VAL
          FROM LISTVALS_LIST(7) L
          WHERE L.IS_DEL = 0 AND EXISTS (
              SELECT FIRST 1 1
              FROM UT_EXAM_OU_ASSN A
              JOIN LINKS LP111 ON LP111.PARENT_TYPE_ID = 111 AND LP111.OBJ_TYPE_ID = 2 AND (LP111.OBJ_ID = A.OU_ID OR A.OU_ID = 0) AND LP111.DATE_DEL IS NULL
              JOIN VALL V665 ON V665.OBJ_ID = LP111.PARENT_ID AND V665.PARAM_ID = 665 AND V665.IS_DEL = 0 AND V665.LISTVAL_ID = L.LISTVAL_ID
              WHERE A.DATE_DEL IS NULL AND A.EXAM_ID = :I$EXAM_ID
          )
          ORDER BY L.SORT_ORDER
          INTO :V$OBJ_ID, :V$S
      DO
      BEGIN
          TAG_NAME = 'items:r';
          VAL = NULL;
          SUSPEND;
          TAG_NAME = 'items:r:level';
          VAL = 1;
          SUSPEND;
          TAG_NAME = 'items:r:id';
          VAL = V$OBJ_ID;
          SUSPEND;
          TAG_NAME = 'items:r:name';
          VAL = V$S;
          SUSPEND;

          TAG_NAME = 'items:r:has_children';
          VAL = 0;
          SELECT FIRST 1 1
          FROM UT_EXAM_OU_ASSN A
          JOIN LINKS LP111 ON (LP111.OBJ_ID = A.OU_ID OR A.OU_ID = 0) AND LP111.PARENT_TYPE_ID = 111 AND LP111.OBJ_TYPE_ID = 2 AND LP111.DATE_DEL IS NULL
          JOIN VALL V665 ON V665.OBJ_ID = LP111.PARENT_ID AND V665.PARAM_ID = 665 AND V665.IS_DEL = 0 AND V665.LISTVAL_ID = :V$OBJ_ID
          WHERE A.DATE_DEL IS NULL AND A.EXAM_ID = :I$EXAM_ID
          INTO :VAL;
          SUSPEND;

          -- Цифры
          V$D = NULL;
          TAG_NAME = 'items:r:n_packets';
          VAL = 0;
          SELECT COUNT(*), MIN(P.DATE_ADD)
          FROM UT_EXAM_OU_ASSN A
          JOIN LINKS LP111 ON (LP111.OBJ_ID = A.OU_ID OR A.OU_ID = 0) AND LP111.PARENT_TYPE_ID = 111 AND LP111.OBJ_TYPE_ID = 2 AND LP111.DATE_DEL IS NULL
          JOIN VALL V665 ON V665.OBJ_ID = LP111.PARENT_ID AND V665.PARAM_ID = 665 AND V665.IS_DEL = 0 AND V665.LISTVAL_ID = :V$OBJ_ID
          JOIN UT_PACKAGES P ON P.ED_ID = A.EXAM_ID AND P.DATE_DEL IS NULL AND P.PPE_ID = LP111.OBJ_ID AND P.STATE_ID >= 9
          WHERE A.DATE_DEL IS NULL AND A.EXAM_ID = :I$EXAM_ID
          INTO :VAL, :V$D;
          SUSPEND;

          TAG_NAME = 'items:r:date';
          VAL = (SELECT VAL FROM DATE2ISO(:V$D));
          SUSPEND;

          TAG_NAME = 'items:r:n_blanks';
          VAL = 0;
          SELECT COUNT(*)
          FROM UT_EXAM_OU_ASSN A
          JOIN LINKS LP111 ON (LP111.OBJ_ID = A.OU_ID OR A.OU_ID = 0) AND LP111.PARENT_TYPE_ID = 111 AND LP111.OBJ_TYPE_ID = 2 AND LP111.DATE_DEL IS NULL
          JOIN VALL V665 ON V665.OBJ_ID = LP111.PARENT_ID AND V665.PARAM_ID = 665 AND V665.IS_DEL = 0 AND V665.LISTVAL_ID = :V$OBJ_ID
          JOIN UT_PACKAGES P ON P.ED_ID = A.EXAM_ID AND P.DATE_DEL IS NULL AND P.PPE_ID = LP111.OBJ_ID AND P.STATE_ID >= 9
          JOIN UT_BLANKS B ON B.PACKAGE_ID = P.OBJ_ID AND B.DATE_DEL IS NULL AND B.STATE_ID >= 9
          WHERE A.DATE_DEL IS NULL AND A.EXAM_ID = :I$EXAM_ID
          INTO :VAL;
          SUSPEND;

          TAG_NAME = 'items:r:n_members';
          VAL = 0;
          SELECT COUNT(*)
          FROM UT_EXAM_OU_ASSN A
          JOIN LINKS LP111 ON (LP111.OBJ_ID = A.OU_ID OR A.OU_ID = 0) AND LP111.PARENT_TYPE_ID = 111 AND LP111.OBJ_TYPE_ID = 2 AND LP111.DATE_DEL IS NULL
          JOIN VALL V665 ON V665.OBJ_ID = LP111.PARENT_ID AND V665.PARAM_ID = 665 AND V665.IS_DEL = 0 AND V665.LISTVAL_ID = :V$OBJ_ID
          JOIN UT_EXAM_PERSON_ASSN PA ON PA.EXAM_ID = A.EXAM_ID AND PA.DATE_DEL IS NULL AND TRUNC(PA.PERSON_ID / :V$MULT) = TRUNC(PA.OBJ_ID / :V$MULT)
          WHERE A.DATE_DEL IS NULL AND A.EXAM_ID = :I$EXAM_ID
          INTO :VAL;
          SUSPEND;

          TAG_NAME = 'items:r:n_rcv';
          VAL = 0;
          SUSPEND;
          TAG_NAME = 'items:r:n_verify';
          VAL = 0;
          SUSPEND;
          TAG_NAME = 'items:r:n_done';
          VAL = 0;
          SUSPEND;
      END

  END
  ELSE IF(I$LEVEL = 1) THEN
  BEGIN

      -- Район, выдаем список ОУ
      FOR
          SELECT LP111.OBJ_ID, V2.VAL
          FROM UT_EXAM_OU_ASSN A
          JOIN LINKS LP111 ON (LP111.OBJ_ID = A.OU_ID OR A.OU_ID = 0) AND LP111.PARENT_TYPE_ID = 111 AND LP111.OBJ_TYPE_ID = 2 AND LP111.DATE_DEL IS NULL
          JOIN VALL V665 ON V665.OBJ_ID = LP111.PARENT_ID AND V665.PARAM_ID = 665 AND V665.IS_DEL = 0 AND V665.LISTVAL_ID = :I$OBJ_ID
          JOIN VALS V2 ON V2.OBJ_ID = LP111.OBJ_ID AND V2.PARAM_ID = 2 AND V2.IS_DEL = 0
          WHERE A.DATE_DEL IS NULL AND A.EXAM_ID = :I$EXAM_ID
          ORDER BY 2
          INTO :V$OBJ_ID, :V$S
      DO
      BEGIN
          TAG_NAME = 'items:r';
          VAL = NULL;
          SUSPEND;
          TAG_NAME = 'items:r:level';
          VAL = 0;
          SUSPEND;
          TAG_NAME = 'items:r:id';
          VAL = V$OBJ_ID;
          SUSPEND;
          TAG_NAME = 'items:r:name';
          VAL = V$S;
          SUSPEND;

          -- Есть ли пакеты ?
          TAG_NAME = 'items:r:has_children';
          VAL = 0;
          SELECT FIRST 1 1
          FROM UT_PACKAGES P
          WHERE P.DATE_DEL IS NULL AND P.ED_ID = :I$EXAM_ID AND P.PPE_ID = :V$OBJ_ID AND P.STATE_ID >= 9
          INTO :VAL;
          SUSPEND;

          -- Цифры
          V$D = NULL;
          TAG_NAME = 'items:r:n_packets';
          VAL = 0;
          SELECT COUNT(*), MIN(P.DATE_ADD)
          FROM UT_PACKAGES P
          WHERE P.DATE_DEL IS NULL AND P.ED_ID = :I$EXAM_ID AND P.PPE_ID = :V$OBJ_ID AND P.STATE_ID >= 9
          INTO :VAL, :V$D;
          SUSPEND;

          TAG_NAME = 'items:r:date';
          VAL = (SELECT VAL FROM DATE2ISO(:V$D));
          SUSPEND;

          TAG_NAME = 'items:r:n_blanks';
          VAL = 0;
          SELECT COUNT(*)
          FROM UT_PACKAGES P
          JOIN UT_BLANKS B ON B.PACKAGE_ID = P.OBJ_ID AND B.DATE_DEL IS NULL AND B.STATE_ID >= 9
          WHERE P.DATE_DEL IS NULL AND P.ED_ID = :I$EXAM_ID AND P.PPE_ID = :V$OBJ_ID AND P.STATE_ID >= 9
          INTO :VAL;
          SUSPEND;

          TAG_NAME = 'items:r:n_members';
          VAL = 0;
          SELECT COUNT(*)
          FROM UT_EXAM_PERSON_ASSN PA
          WHERE PA.EXAM_ID = :I$EXAM_ID AND PA.DATE_DEL IS NULL AND TRUNC(PA.PERSON_ID / :V$MULT) = TRUNC(:V$OBJ_ID / :V$MULT)
          INTO :VAL;
          SUSPEND;

          TAG_NAME = 'items:r:n_rcv';
          VAL = 0;
          SUSPEND;
          TAG_NAME = 'items:r:n_verify';
          VAL = 0;
          SUSPEND;
          TAG_NAME = 'items:r:n_done';
          VAL = 0;
          SUSPEND;
      END

  END
  ELSE IF(I$LEVEL = 0) THEN
  BEGIN

      -- ОУ, выдаем список пакетов (в названии пакета покаываем id и учебный коллектив)
      FOR
          SELECT P.OBJ_ID, P.OBJ_ID, P.STATE_ID, P.DATE_ADD, P.ROOM_ID
          FROM UT_PACKAGES P
          WHERE P.DATE_DEL IS NULL AND P.PPE_ID = :I$OBJ_ID AND P.ED_ID = :I$EXAM_ID
          ORDER BY P.DATE_ADD
          INTO :V$OBJ_ID, :V$S, :V$STATE, :V$D, :V$LOCATION_ID
      DO
      BEGIN
          TAG_NAME = 'items:r';
          VAL = NULL;
          SUSPEND;
          TAG_NAME = 'items:r:level';
          VAL = -1;
          SUSPEND;
          TAG_NAME = 'items:r:id';
          VAL = V$OBJ_ID;
          SUSPEND;

          V$CAPTION = NULL;
          SELECT C.CAPTION
          FROM OBJECTS L
          LEFT JOIN OBJECT_CAPTION_GET(L.OBJ_ID) C ON 1 = 1
          WHERE L.OBJ_ID = :V$LOCATION_ID
          INTO :V$CAPTION;

          IF(V$CAPTION IS NULL) THEN
          BEGIN
              -- ROOM_ID
          END

          TAG_NAME = 'items:r:name';
          VAL = V$S || ' (' || COALESCE(V$CAPTION, '?') || ')';
          SUSPEND;
          TAG_NAME = 'items:r:state';
          VAL = V$STATE;
          SUSPEND;

          TAG_NAME = 'items:r:has_children';
          N = 0;
          SELECT COUNT(*)
          FROM UT_BLANKS B
          WHERE B.DATE_DEL IS NULL AND B.PACKAGE_ID = :V$OBJ_ID
          INTO :N;
          VAL = IIF(N = 0, '0', '1');
          SUSPEND;

          -- Цифры
          TAG_NAME = 'items:r:n_packets';
          VAL = NULL;
          SUSPEND;

          TAG_NAME = 'items:r:date';
          VAL = (SELECT VAL FROM DATE2ISO(:V$D));
          SUSPEND;

          TAG_NAME = 'items:r:n_blanks';
          VAL = N;
          SUSPEND;

          TAG_NAME = 'items:r:n_members';
          VAL = NULL;
          SUSPEND;

          TAG_NAME = 'items:r:n_rcv';
          VAL = 0;
          SUSPEND;
          TAG_NAME = 'items:r:n_verify';
          VAL = 0;
          SUSPEND;
          TAG_NAME = 'items:r:n_done';
          VAL = 0;
          SUSPEND;
      END

  END
  ELSE IF(I$LEVEL = -1) THEN
  BEGIN

      -- Пакет, выдаем список бланков
      FOR
          SELECT B.OBJ_ID, B.BARCODE_DATA, B.STATE_ID, B.DATE_ADD, T.BLANK_TYPE
          FROM UT_PACKAGES P
          JOIN UT_BLANKS B ON B.DATE_DEL IS NULL AND B.PACKAGE_ID = P.OBJ_ID
          JOIN UT_PAGE_TEMPLATES T ON T.OBJ_ID = B.BLANK_TYPE
          WHERE P.DATE_DEL IS NULL AND P.OBJ_ID = :I$OBJ_ID AND P.ED_ID = :I$EXAM_ID
          ORDER BY B.DATE_ADD
          INTO :V$OBJ_ID, :V$S, :V$STATE, :V$D, :V$TYPE
      DO
      BEGIN
          TAG_NAME = 'items:r';
          VAL = NULL;
          SUSPEND;
          TAG_NAME = 'items:r:level';
          VAL = -1;
          SUSPEND;
          TAG_NAME = 'items:r:id';
          VAL = V$OBJ_ID;
          SUSPEND;
          TAG_NAME = 'items:r:name';
          VAL = V$S;
          SUSPEND;
          TAG_NAME = 'items:r:type';
          VAL = V$TYPE;
          SUSPEND;
          TAG_NAME = 'items:r:state';
          VAL = V$STATE;
          SUSPEND;

          TAG_NAME = 'items:r:has_children';
          VAL = 0;
          SUSPEND;

          -- Цифры
          TAG_NAME = 'items:r:n_packets';
          VAL = NULL;
          SUSPEND;

          TAG_NAME = 'items:r:date';
          VAL = (SELECT VAL FROM DATE2ISO(:V$D));
          SUSPEND;

          TAG_NAME = 'items:r:n_blanks';
          VAL = 1;
          SUSPEND;

          TAG_NAME = 'items:r:n_members';
          VAL = NULL;
          SUSPEND;

          TAG_NAME = 'items:r:n_rcv';
          VAL = 0;
          SUSPEND;
          TAG_NAME = 'items:r:n_verify';
          VAL = 0;
          SUSPEND;
          TAG_NAME = 'items:r:n_done';
          VAL = 0;
          SUSPEND;
      END

  END
  ELSE EXCEPTION DATA_ERROR 'Неверный код уровня (2)';

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_EXAM_SETTINGS (
    I$OBJ_ID BIGINT)
RETURNS (
    H_LEVEL INTEGER,
    DB_LEVEL INTEGER,
    EXPERT_ASSN_MODE INTEGER,
    ORG_ID BIGINT,
    THIS_ID BIGINT)
AS
begin

  SELECT D.H_LEVEL, D.EXPERT_ASSN_MODE, D.ORG_REF
  FROM UT_EXAM_DATES D
  WHERE D.DATE_DEL IS NULL AND D.OBJ_ID = :I$OBJ_ID
  INTO :H_LEVEL, :EXPERT_ASSN_MODE, :ORG_ID;

  SELECT COALESCE(CAST(K.KEY_VAL AS INTEGER) - 1, 0)
  FROM KEYS K
  WHERE K.KEY_CODE = 'LEVEL'
  INTO :DB_LEVEL;

  IF(DB_LEVEL = 0) THEN
  BEGIN
      SELECT FIRST 1 L2.OBJ_ID
      FROM LINKS L2
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      INTO :THIS_ID;
  END

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_EXAM_SMPL_RESULTS (
    I$EXAM_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$PERSON_ID BIGINT;
DECLARE VARIABLE S VARCHAR(4000);
DECLARE VARIABLE V$SSN_ID BIGINT;
DECLARE VARIABLE V$RAW INTEGER;
DECLARE VARIABLE V$DUR INTEGER;
DECLARE VARIABLE V$START TIMESTAMP;
DECLARE VARIABLE V$FINISH TIMESTAMP;
DECLARE VARIABLE V$STATE INTEGER;
DECLARE VARIABLE V$INDEX INTEGER;
DECLARE VARIABLE V$MAX INTEGER;
begin

  -- Список вопросов в контексте номеров ответов
  TAG_NAME = 'questions::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT DISTINCT EQ.SORT_INDEX
    FROM UT_EXAM_QUESTIONS EQ
    WHERE EQ.DATE_DEL IS NULL AND EQ.EXAM_ID = :I$EXAM_ID
    ORDER BY 1
    INTO :V$RAW
  DO
  BEGIN
    TAG_NAME = 'questions:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'questions:r:index';
    VAL = V$RAW;
    SUSPEND;
  END

  TAG_NAME = 'persons::json&colon;array';
  VAL = 1;
  SUSPEND;
  -- Выбираем последнюю сессию персоны
  FOR
    SELECT EPA.PERSON_ID, C.NAME_FULL
    FROM UT_EXAM_PERSON_ASSN EPA
    LEFT JOIN UT_PERSON_DESC(EPA.PERSON_ID) C ON 1 = 1
    WHERE EPA.EXAM_ID = :I$EXAM_ID AND EPA.DATE_DEL IS NULL
    ORDER BY 2
    INTO :V$PERSON_ID, :S
  DO
  BEGIN
    TAG_NAME = 'persons:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'persons:r:id';
    VAL = V$PERSON_ID;
    SUSPEND;
    TAG_NAME = 'persons:r:name';
    VAL = S;
    SUSPEND;

    -- Достаем ID последней сессии
    V$SSN_ID = NULL;
    V$RAW = NULL;
    V$DUR = NULL;
    V$START = NULL;
    V$FINISH = NULL;
    S = NULL;
    SELECT FIRST 1 S.OBJ_ID, S.RAW_RESULT, MT.MARK_NAME, S.DURATION, S.STARTED_AT, S.COMPLETED_AT, S.VARIANT_INDEX
    FROM UT_SESSIONS S
    LEFT JOIN CJ2_MARK_TYPE MT ON MT.MARK_TYPE_ID = S.FINAL_RESULT_ID
    WHERE S.DATE_DEL IS NULL AND S.ED_ID = :I$EXAM_ID AND S.PERSON_ID = :V$PERSON_ID AND S.STATE_ID = 100
    ORDER BY S.DATE_ADD DESC
    INTO :V$SSN_ID, :V$RAW, :S, :V$DUR, :V$START, :V$FINISH, :V$INDEX;

    TAG_NAME = 'persons:r:variant';
    VAL = V$INDEX;
    SUSPEND;
    TAG_NAME = 'persons:r:raw_result';
    VAL = V$RAW;
    SUSPEND;
    TAG_NAME = 'persons:r:text_result';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'persons:r:duration';
    VAL = V$DUR;
    SUSPEND;
    TAG_NAME = 'persons:r:started_at';
    VAL = V$START;
    SUSPEND;
    TAG_NAME = 'persons:r:completed_at';
    VAL = V$FINISH;
    SUSPEND;

    TAG_NAME = 'persons:r:answers::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT EQ.SORT_INDEX, SQ.ANSWER_DATA, SQ.RAW_RESULT, SQ.STATE_ID, Q.MAX_SCORE
      FROM UT_SESSION_QUESTIONS SQ
      JOIN UT_EXAM_QUESTIONS EQ ON EQ.OBJ_ID = SQ.QUESTION_RAW
      JOIN UT_QUESTIONS Q ON Q.OBJ_ID = EQ.QUESTION_ID
      WHERE SQ.DATE_DEL IS NULL AND SQ.SESSION_ID = :V$SSN_ID
      INTO :V$INDEX, :S, :V$RAW, :V$STATE, :V$MAX
    DO
    BEGIN
      TAG_NAME = 'persons:r:answers:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'persons:r:answers:r:index';
      VAL = V$INDEX;
      SUSPEND;
      TAG_NAME = 'persons:r:answers:r:raw_result';
      VAL = V$RAW;
      SUSPEND;
      TAG_NAME = 'persons:r:answers:r:max_score';
      VAL = V$MAX;
      SUSPEND;
      TAG_NAME = 'persons:r:answers:r:value';
      VAL = S;
      SUSPEND;
      TAG_NAME = 'persons:r:answers:r:state_id';
      VAL = V$STATE;
      SUSPEND;
    END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_EXAM_TEST_VARS_SET (
    I$EXAM_ID BIGINT NOT NULL,
    I$TEST_VAR_ID BIGINT NOT NULL,
    I$STATE INTEGER)
RETURNS (
    OBJ_ID BIGINT)
AS
BEGIN

  IF(I$STATE = 2) THEN
  BEGIN

      UPDATE UT_EXAM_TEST_VARS
      SET DATE_DEL = CURRENT_TIMESTAMP
      WHERE EXAM_ID = :I$EXAM_ID AND TEST_VAR_ID = :I$TEST_VAR_ID AND DATE_DEL IS NULL;

  END
  ELSE
  BEGIN

      IF (NOT EXISTS(SELECT FIRST 1 1 FROM UT_EXAM_TEST_VARS WHERE EXAM_ID = :I$EXAM_ID AND TEST_VAR_ID = :I$TEST_VAR_ID AND DATE_DEL IS NULL)) THEN
      BEGIN

          INSERT INTO UT_EXAM_TEST_VARS
          (EXAM_ID, TEST_VAR_ID)
          VALUES (:I$EXAM_ID, :I$TEST_VAR_ID)
          RETURNING OBJ_ID INTO :OBJ_ID;

      END

  END

  SUSPEND;

END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_EXAM_TITLE_GET (
    I$EXAM_ID BIGINT,
    I$SESSION_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    EXAM_ID BIGINT,
    SESSION_ID BIGINT,
    OBJ_NAME VARCHAR(200),
    USER_NAME VARCHAR(200),
    EXAM_CURRENT_DATE TIMESTAMP,
    EXAM_COMPLETED_DATE TIMESTAMP,
    DURATION INTEGER,
    EXAM_EXEC_PERCENT SMALLINT,
    AUDIO_CHECK SMALLINT,
    PAUSE_ENABLED SMALLINT,
    EXAM_STATE SMALLINT,
    TOTAL_COUNT SMALLINT,
    SESSION_STATE_ID INTEGER,
    SESSION_STATE_TEXT VARCHAR(200),
    PERSON_ID BIGINT,
    PERSON_TYPE_ID BIGINT,
    EXAM_TIME INTEGER,
    FLOW_MODE SMALLINT,
    RAW_RESULT INTEGER,
    FINAL_RESULT_ID BIGINT,
    FINAL_RESULT_TEXT VARCHAR(100),
    N_ATTEMPS SMALLINT,
    START_ALLOWED SMALLINT,
    PLAN_METHOD_ID INTEGER)
AS
DECLARE VARIABLE V$PERSON_ID BIGINT;
DECLARE VARIABLE V$STRUCT_ID BIGINT;
DECLARE VARIABLE V$MAX_ATTEMPTS INTEGER;
DECLARE VARIABLE V$METHOD_ID SMALLINT;
DECLARE VARIABLE V$PLAN_METHOD_ID INTEGER;
begin
  -- Передается или OBJ_ID:NULL, или OBJ_ID:SESSION_ID
  -- Надо что-то делать с анонимными опросами !

  -- По USER_ID определяем персону
  SELECT U.OBJ_ID FROM USERS U WHERE U.USER_ID = :I$USER_ID INTO :V$PERSON_ID;

  -- метод планирования участников
  SELECT ED.PLAN_METHOD_ID
  FROM UT_EXAM_DATES ED
  WHERE ED.OBJ_ID = :I$EXAM_ID AND ED.DATE_DEL IS NULL
  INTO :V$PLAN_METHOD_ID;
  PLAN_METHOD_ID = V$PLAN_METHOD_ID;


  -- * тестирование с назначением?
  IF (V$PLAN_METHOD_ID <> 3) THEN BEGIN
    SELECT EPA.EXAM_ID, EPA.PERSON_ID, ED.OBJ_NAME, ED.DURATION, ED.EXAM_STATE, ED.FLOW_MODE, ED.PAUSE_ENABLED, ED.ATTEMPTS, ED.METHOD_ID
    FROM UT_EXAM_DATES ED
    JOIN UT_EXAM_PERSON_ASSN EPA ON EPA.EXAM_ID = ED.OBJ_ID AND EPA.PERSON_ID = :V$PERSON_ID AND EPA.DATE_DEL IS NULL
    WHERE ED.OBJ_ID = :I$EXAM_ID AND ED.DATE_DEL IS NULL
    INTO :EXAM_ID, :PERSON_ID, :OBJ_NAME, :EXAM_TIME, :EXAM_STATE, :FLOW_MODE, :PAUSE_ENABLED, :V$MAX_ATTEMPTS, :V$METHOD_ID;

    IF(EXAM_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не найдено назначение на тестирование';
  END
  -- * проверяем, что тестирование для всех желающих, назначение создасться при нажатии кнопки начать тестирование
  ELSE BEGIN
    SELECT ED.OBJ_ID, ED.OBJ_NAME, ED.DURATION, ED.EXAM_STATE, ED.FLOW_MODE, ED.PAUSE_ENABLED, ED.ATTEMPTS, ED.METHOD_ID
    FROM UT_EXAM_DATES ED
    WHERE ED.OBJ_ID = :I$EXAM_ID AND ED.DATE_DEL IS NULL
    INTO :EXAM_ID, :OBJ_NAME, :EXAM_TIME, :EXAM_STATE, :FLOW_MODE, :PAUSE_ENABLED, :V$MAX_ATTEMPTS, :V$METHOD_ID;

    PERSON_ID = V$PERSON_ID;
  END


  -- (ученик / учитель / родитель)
  SELECT FIRST 1 C.TYPE_ID, C.NAME_FULL
  FROM UT_PERSON_DESC(:PERSON_ID, 0, 1) C
  INTO :PERSON_TYPE_ID, :USER_NAME;

  -- Данные по сессии тестирования (если есть)
  SELECT S.OBJ_ID, S.STARTED_AT, S.COMPLETED_AT, S.STATE_ID, SS.STATE_NAME,
    S.DURATION, S.RAW_RESULT, S.FINAL_RESULT_ID, MT.MARK_NAME
  FROM UT_SESSIONS S
  JOIN UT_SESSION_STATES SS ON SS.STATE_ID = S.STATE_ID
  LEFT JOIN CJ2_MARK_TYPE MT ON MT.MARK_TYPE_ID = S.FINAL_RESULT_ID
  WHERE S.OBJ_ID = :I$SESSION_ID AND S.DATE_DEL IS NULL
  INTO :SESSION_ID, :EXAM_CURRENT_DATE, :EXAM_COMPLETED_DATE, :SESSION_STATE_ID, :SESSION_STATE_TEXT,
    :DURATION, :RAW_RESULT, :FINAL_RESULT_ID, :FINAL_RESULT_TEXT;

  -- Нужно ли проверять аудиотракт при тестировании ?
  AUDIO_CHECK = 0;
  IF (V$METHOD_ID = 1) THEN AUDIO_CHECK = 1;

  -- Количество оставшихся попыток тестирования
  -- Сколько уже попыток задействовано ?
  SELECT COUNT(*)
  FROM UT_SESSIONS S
  WHERE S.ED_ID = :I$EXAM_ID AND S.DATE_DEL IS NULL AND S.STATE_ID < 10
  INTO :N_ATTEMPS;

  IF(V$MAX_ATTEMPTS = 0) THEN N_ATTEMPS = -1;
  ELSE IF(N_ATTEMPS >= V$MAX_ATTEMPTS) THEN N_ATTEMPS = 0;
  ELSE N_ATTEMPS = V$MAX_ATTEMPTS - N_ATTEMPS;

  -- Разрешение начала/продолжения тестирования исходя из статуса EXAM_DATE
  -- 0/1/2
  START_ALLOWED = (SELECT READY_STATE FROM UT_EXAM_DATE_READY(:I$EXAM_ID));

  -- Количество вопросов в тесте - берем либо из сессии, либо из структуры экзамена
  IF(SESSION_ID IS NULL) THEN
  BEGIN
    -- Берем первую структуру - если несколько, все должны быть одинаковые
    TOTAL_COUNT = 0;
    FOR
      SELECT FIRST 1 TS.OBJ_ID
      FROM UT_EXAM_TEST_VARS ETV
      JOIN UT_TEST_VARS TV ON TV.OBJ_ID = ETV.TEST_VAR_ID AND TV.DATE_DEL IS NULL
      JOIN UT_TESTS T ON T.OBJ_ID = TV.TEST_ID AND T.DATE_DEL IS NULL
      JOIN UT_TEST_STRUCTS TS ON TS.OBJ_ID = T.STRUCT_ID AND TS.DATE_DEL IS NULL
      WHERE ETV.DATE_DEL IS NULL AND ETV.EXAM_ID = :I$EXAM_ID
      INTO :V$STRUCT_ID
    DO
    BEGIN
      SELECT COUNT(*)
      FROM UT_TEST_STRUCT_POINTS TP
      WHERE TP.DATE_DEL IS NULL AND TP.STRUCT_ID = :V$STRUCT_ID
      INTO :TOTAL_COUNT;
    END

    -- Сколько вопросов уже отвечено ?
    EXAM_EXEC_PERCENT = 0;
    DURATION = 0;
  END
  ELSE
  BEGIN
    -- Костыль, надо считать вопросы в структуре !
    SELECT COUNT(*)
    FROM UT_SESSION_QUESTIONS SQ
    WHERE SQ.SESSION_ID = :SESSION_ID AND SQ.DATE_DEL IS NULL
    INTO :TOTAL_COUNT;

    EXAM_EXEC_PERCENT = 0;
  END

  SUSPEND;
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_EXPARENTS_VIEW (
    I$LEVEL_ID INTEGER,
    I$USER_ID VARCHAR(40))
RETURNS (
    OBJ_ID BIGINT,
    OBJ_NAME VARCHAR(1000),
    LEVEL_ID SMALLINT,
    LEVEL_TITLE VARCHAR(1000),
    LEVEL_PARENT VARCHAR(1000),
    DATE_DEL TIMESTAMP)
AS
begin
  -- I$LEVEL_ID: 1 = ОУ, 2 = район, 3+ = регион

  -- Для уровня региона вообще не предполагается выбор из списка
  IF(I$LEVEL_ID >= 3) THEN EXIT;

  IF(I$LEVEL_ID = 1) THEN
  BEGIN

    -- ОУ
    LEVEL_ID = 1;
    LEVEL_TITLE = 'ОО';
    LEVEL_PARENT = 'Текущая образовательная организация';

    SELECT FIRST 1 L2.OBJ_ID, V2.VAL
    FROM LINKS L2
    JOIN VALS V2 ON V2.OBJ_ID = L2.OBJ_ID AND V2.PARAM_ID = 2 AND V2.IS_DEL = 0
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :OBJ_ID, :OBJ_NAME;

    SUSPEND;

  END
  ELSE
  BEGIN

    -- Район

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_EXPERTS_LIST (
    I$EXPERT_ID BIGINT,
    I$AREA_ID BIGINT,
    I$ACC_AREA_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    PERSON_NAME VARCHAR(1000),
    LAST_NAME VARCHAR(400),
    FIRST_NAME VARCHAR(400),
    MIDDLE_NAME VARCHAR(400),
    BIRTH_DATE DATE,
    JOB_TITLE VARCHAR(400),
    AREA_ID BIGINT,
    AREA_NAME VARCHAR(400),
    OU_NAME VARCHAR(400),
    ACC_AREA_TEXT VARCHAR(1000),
    IS_ACTIVE INTEGER,
    IS_ACTIVE_TEXT VARCHAR(10),
    TEACHER_ID BIGINT)
AS
begin

  FOR
      SELECT D.EXPERT_ID, D.LAST_NAME, D.FIRST_NAME, D.MIDDLE_NAME, D.BIRTHDATE, D.AREA_ID, D.ORGANIZATION, D.JOB_TITLE, D.IS_ACTIVE, IIF(D.IS_ACTIVE = 0, 'Нет', 'Да'), D.TEACHER_ID
      FROM UT_EXPERTS D
      WHERE D.DATE_DEL IS NULL AND (:I$EXPERT_ID IS NULL OR D.EXPERT_ID = :I$EXPERT_ID) AND (:I$AREA_ID IS NULL OR D.AREA_ID = :I$AREA_ID)
      INTO :OBJ_ID, :LAST_NAME, :FIRST_NAME, :MIDDLE_NAME, :BIRTH_DATE, :AREA_ID, :OU_NAME, :JOB_TITLE, :IS_ACTIVE, :IS_ACTIVE_TEXT, :TEACHER_ID
  DO
  BEGIN

      -- Проверяем фильтр по области аккредитации, и параллельно формируем список
      -- !!!
      ACC_AREA_TEXT = '';

      -- Для штатных сотрудников восстанавливаем реквизиты
      IF(TEACHER_ID IS NOT NULL) THEN
      BEGIN
        SELECT VAL FROM VALS WHERE OBJ_ID = :TEACHER_ID AND PARAM_ID = 59 AND IS_DEL = 0 INTO :LAST_NAME;
        SELECT VAL FROM VALS WHERE OBJ_ID = :TEACHER_ID AND PARAM_ID = 60 AND IS_DEL = 0 INTO :FIRST_NAME;
        SELECT VAL FROM VALS WHERE OBJ_ID = :TEACHER_ID AND PARAM_ID = 61 AND IS_DEL = 0 INTO :MIDDLE_NAME;
        SELECT VAL FROM VALD WHERE OBJ_ID = :TEACHER_ID AND PARAM_ID = 241 AND IS_DEL = 0 INTO :BIRTH_DATE;

        -- Основная актуальная должность
        SELECT FIRST 1 V589.VAL
        FROM LINKS L15
        LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
        JOIN VALL V72 ON V72.OBJ_ID = L15.OBJ_ID AND V72.PARAM_ID = 72 AND V72.IS_DEL = 0 AND V72.LISTVAL_ID = 934
        JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
        JOIN VALS V589 ON V589.OBJ_ID = LP13.PARENT_ID AND V589.PARAM_ID = 589 AND V589.IS_DEL = 0
        WHERE L15.PARENT_ID = :TEACHER_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL AND (V74.VAL IS NULL OR V74.VAL > CURRENT_DATE)
        INTO :JOB_TITLE;

      END

      PERSON_NAME = LAST_NAME || ' ' || FIRST_NAME || COALESCE(' ' || MIDDLE_NAME, '');

      -- Название района
      AREA_NAME = NULL;

      SELECT FIRST 1 R.VAL
      FROM LISTVALS LV
      JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
      WHERE LV.LISTVAL_ID = :AREA_ID
      INTO :AREA_NAME;

      SUSPEND;

  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_EXPERT_DELETE (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    STUB INTEGER)
AS
declare variable V$GEN bigint;
declare variable V$MULT bigint;
declare variable V$EXPERT_ID bigint;
declare variable V$TEACHER_ID bigint;
declare variable V$ROLE smallint;
declare variable TMP bigint;
begin

  -- Снять назначение эксперта можно только в той же базе, где оно выставлялось
  SELECT GEN, MULTIPLIER
  FROM GEN
  INTO :V$GEN, :V$MULT;

  IF((I$OBJ_ID / V$MULT) <> V$GEN) THEN EXCEPTION DATA_ERROR 'Снять назначение эксперта можно только на том же уровне, где оно было создано';

  SELECT EXPERT_ID, TEACHER_ID
  FROM UT_EXPERTS
  WHERE EXPERT_ID = :I$OBJ_ID AND DATE_DEL IS NULL
  INTO :V$EXPERT_ID, :V$TEACHER_ID;

  IF(V$EXPERT_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Запись эксперта не найдена';

  SELECT EXPERT_ROLE FROM UT_USER_TO_EXPERT(:I$USER_ID) INTO :V$ROLE;
  IF(V$ROLE NOT IN (1, 5, 6)) THEN EXCEPTION DATA_ERROR 'Вы не можете удалять записи экспертов';

  -- Нет ли назначений на действующие тестирования ?
  IF(EXISTS(
      SELECT FIRST 1 1
      FROM UT_EXAM_EXPERT_ASSN EA
      JOIN UT_EXAM_DATES D ON D.OBJ_ID = EA.EXAM_ID AND D.DATE_DEL IS NULL AND D.EXAM_STATE < 1000
      WHERE EA.EXAM_ID = :V$EXPERT_ID AND EA.DATE_DEL IS NULL
  ))
  THEN EXCEPTION DATA_ERROR 'Эксперт назначен на действующие тестирования, сначала снимите назначения';

  IF(V$TEACHER_ID IS NULL) THEN
  BEGIN
      UPDATE UT_EXPERTS
      SET DATE_DEL = CURRENT_TIMESTAMP
      WHERE EXPERT_ID = :V$EXPERT_ID;
  END
  ELSE
  BEGIN
      -- Запись обновится из VAL_ADD
      SELECT BLOB_ID FROM VAL_ADD(2935, :V$TEACHER_ID, 3) INTO :TMP;
  END

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_EXPERT_DESC (
    I$OBJ_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    NAME_LAST VARCHAR(200),
    NAME_FIRST VARCHAR(200),
    NAME_MID VARCHAR(200),
    NAME_FULL VARCHAR(400),
    BIRTH_DATE DATE,
    JOB_TITLE VARCHAR(400),
    OU_ID BIGINT,
    OU_NAME VARCHAR(200),
    AREA_ID BIGINT,
    AREA_NAME VARCHAR(200),
    JOB_ID BIGINT,
    IS_ACTIVE SMALLINT,
    IS_ACTIVE_TEXT VARCHAR(10),
    ACC_AREA_TEXT VARCHAR(1000))
AS
begin

  OBJ_ID = I$OBJ_ID;

  SELECT COALESCE(D.NAME_LAST, U.LAST_NAME), COALESCE(D.NAME_FIRST, U.FIRST_NAME), COALESCE(D.NAME_MID, U.MIDDLE_NAME),
      COALESCE(D.BIRTH_DATE, U.BIRTHDATE), D.JOB_ID, COALESCE(D.JOB_TITLE, U.JOB_TITLE), D.OU_ID, COALESCE(D.OU_NAME, U.ORGANIZATION),
      COALESCE(D.AREA_ID, U.AREA_ID), R.VAL, U.IS_ACTIVE
  FROM UT_EXPERTS U
  LEFT JOIN UT_EMPLOYEE_DESC(U.TEACHER_ID) D ON 1 = 1
  LEFT JOIN LISTVALS LV ON LV.LISTVAL_ID = COALESCE(D.AREA_ID, U.AREA_ID)
  LEFt JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
  WHERE U.EXPERT_ID = :I$OBJ_ID AND U.DATE_DEL IS NULL
  INTO :NAME_LAST, :NAME_FIRST, :NAME_MID, :BIRTH_DATE, :JOB_ID, :JOB_TITLE, :OU_ID, :OU_NAME, :AREA_ID, :AREA_NAME, :IS_ACTIVE;

  NAME_FULL = NAME_LAST || ' ' || NAME_FIRST || COALESCE(' ' || NAME_MID, '');

  IF(IS_ACTIVE IS NOT NULL) THEN
  BEGIN
      IF(IS_ACTIVE = 0) THEN IS_ACTIVE_TEXT = 'Нет'; ELSE IS_ACTIVE_TEXT = 'Да';
  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_EXPERT_EXAM_ASSNS_LIST (
    I$PERSON_ID BIGINT,
    I$PERIOD_ID INTEGER,
    I$USER_ID VARCHAR(40) = null)
RETURNS (
    OBJ_ID BIGINT,
    EXAM_ID BIGINT,
    EXAM_NAME VARCHAR(200),
    EXAM_DATE DATE,
    STATE INTEGER,
    ROLE_ID INTEGER,
    ROLE_NAME VARCHAR(200),
    SECOND_CHECK SMALLINT)
AS
declare variable V$DATE_FROM date;
declare variable V$DATE_TO date;
begin
  -- В версии для FB в качестве PERIOD_ID передаем год, соответствующий началу учебного года
  IF(I$PERIOD_ID IS NOT NULL) THEN
  BEGIN
      V$DATE_FROM = '01.09.' || I$PERIOD_ID;
      V$DATE_TO = '31.08.' || (I$PERIOD_ID + 1);
  END

  FOR
      SELECT EA.OBJ_ID, D.OBJ_ID, D.OBJ_NAME, D.EXAM_DATE_START, D.STAGE_ID, EA.ROLE_ID, R.OBJ_NAME, EA.SECOND_CHECK
      FROM UT_EXAM_EXPERT_ASSN EA
      JOIN UT_EXAM_DATES D ON D.OBJ_ID = EA.EXAM_ID AND D.DATE_DEL IS NULL
         AND (:V$DATE_TO IS NULL OR D.EXAM_DATE_START <= :V$DATE_TO)
         AND (:V$DATE_FROM IS NULL OR D.EXAM_DATE_END >= :V$DATE_FROM)
      JOIN UT_EXPERT_ROLES R ON R.OBJ_ID = EA.ROLE_ID
      WHERE EA.EXPERT_ID = :I$PERSON_ID AND EA.DATE_DEL IS NULL
      ORDER BY D.EXAM_DATE_START
      INTO :OBJ_ID, :EXAM_ID, :EXAM_NAME, :EXAM_DATE, :STATE, :ROLE_ID, :ROLE_NAME, :SECOND_CHECK
  DO
  BEGIN
      SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_EXPERT_EXAM_CA_LIST (
    I$USER_ID VARCHAR(40))
RETURNS (
    EXAM_ID BIGINT,
    EXAM_NAME VARCHAR(200),
    SUBJECT_ID BIGINT,
    SUBJECT_NAME VARCHAR(200),
    EXAM_STATE INTEGER,
    EXAM_STATE_NAME VARCHAR(200),
    ROLE_ID INTEGER,
    ROLE_NAME VARCHAR(200),
    EXAM_DATE DATE,
    N_TASKS INTEGER,
    N_SECOND INTEGER,
    METHOD_ID INTEGER)
AS
declare variable V$EXPERT_ID bigint;
declare variable V$METHOD integer;
declare variable V$READY_STATE integer;
declare variable V$DB_LEVEL integer;
declare variable V$N_CHECKS integer;
begin

  SELECT EXPERT_ID
  FROM UT_USER_TO_EXPERT(:I$USER_ID)
  INTO :V$EXPERT_ID;

  SELECT COALESCE(CAST(K.KEY_VAL AS INTEGER) - 1, 0)
  FROM KEYS K
  WHERE K.KEY_CODE = 'LEVEL'
  INTO :V$DB_LEVEL;

  FOR
      SELECT D.OBJ_ID, D.OBJ_NAME, D.SUBJECT_ID, COALESCE(VS.VAL, 'Метапредмет'), D.EXAM_STATE, ES.OBJ_NAME, EA.ROLE_ID, R.OBJ_NAME, D.METHOD_ID, D.EXAM_DATE_START, D.C_EXPERT_NUM
      FROM UT_EXPERTS E
      JOIN UT_EXAM_EXPERT_ASSN EA ON EA.EXPERT_ID = E.EXPERT_ID AND EA.DATE_DEL IS NULL
      JOIN UT_EXAM_DATES D ON D.OBJ_ID = EA.EXAM_ID AND D.DATE_DEL IS NULL AND D.EXAM_STATE = 900 -- только этап экспертной проверки, и только на том же уровне
         AND D.H_LEVEL = :V$DB_LEVEL
      JOIN UT_EXAM_STATES ES ON ES.OBJ_ID = D.EXAM_STATE
      LEFT JOIN VALS VS ON VS.OBJ_ID = D.SUBJECT_ID AND VS.PARAM_ID = 376 AND VS.IS_DEL = 0
      JOIN UT_EXPERT_ROLES R ON R.OBJ_ID = EA.ROLE_ID AND R.DATE_DEL IS NULL
      WHERE E.EXPERT_ID = :V$EXPERT_ID AND E.DATE_DEL IS NULL
      ORDER BY D.EXAM_DATE_START, D.OBJ_NAME
      INTO :EXAM_ID, :EXAM_NAME, :SUBJECT_ID, :SUBJECT_NAME, :EXAM_STATE, :EXAM_STATE_NAME, :ROLE_ID, :ROLE_NAME, :V$METHOD, :EXAM_DATE, :V$N_CHECKS
  DO
  BEGIN
      -- Если идет проверка, показываем количество необработанных заданий для первой и повторной проверки
      IF(EXAM_STATE = 900) THEN
      BEGIN
            
          METHOD_ID = V$METHOD;

          -- статус сессии = сырой результат загружен
          -- в электронном тестировании или аудио-тестировании отдаем в статусе 21, в бумажном при электронной проверке в статусе 30 (валидирован)
          -- вариант с бумажными проверками при бумажном тестировании идет в другой SP
          IF(V$METHOD IN (0, 1)) THEN V$READY_STATE = 21; ELSE V$READY_STATE = 30;

          SELECT COUNT(*)
          FROM (
              -- Все работы, где количество первых проверок еще не дошло до заданного
              SELECT Q.OBJ_ID, COUNT(C.OBJ_ID) CN
              FROM UT_SESSIONS S
              JOIN UT_SESSION_QUESTIONS Q ON Q.SESSION_ID = S.OBJ_ID AND Q.DATE_DEL IS NULL AND Q.STATE_ID = :V$READY_STATE
              JOIN UT_TEST_VAR_QUESTIONS TVQ ON TVQ.OBJ_ID = Q.QUESTION_ID
              JOIN UT_TEST_STRUCT_POINTS TSP ON TSP.OBJ_ID = TVQ.STRUCT_POINT_ID
              JOIN UT_QUESTION_TYPE T ON T.OBJ_ID = TSP.Q_TYPE_ID AND T.IS_HANDCHECKED = 1
              LEFT JOIN UT_SESSION_CHECKS C ON C.QUESTION_ID = Q.OBJ_ID AND C.DATE_DEL IS NULL AND C.LEVEL_ID = 1 AND C.STATE_ID <> 1001 AND C.EXPERT_ID IS NOT NULL
              WHERE S.ED_ID = :EXAM_ID AND S.DATE_DEL IS NULL AND S.STATE_ID = 10 AND C.OBJ_ID IS NULL
              GROUP BY 1
              HAVING COUNT(C.OBJ_ID) < :V$N_CHECKS
              -- Добавляем работы, которые зарезервированы за данным экспертом
              UNION
              SELECT Q.OBJ_ID, COUNT(C.OBJ_ID) CN
              FROM UT_SESSIONS S
              JOIN UT_SESSION_QUESTIONS Q ON Q.SESSION_ID = S.OBJ_ID AND Q.DATE_DEL IS NULL AND Q.STATE_ID = 50
              JOIN UT_TEST_VAR_QUESTIONS TVQ ON TVQ.OBJ_ID = Q.QUESTION_ID
              JOIN UT_TEST_STRUCT_POINTS TSP ON TSP.OBJ_ID = TVQ.STRUCT_POINT_ID
              JOIN UT_QUESTION_TYPE T ON T.OBJ_ID = TSP.Q_TYPE_ID AND T.IS_HANDCHECKED = 1
              JOIN UT_SESSION_CHECKS C ON C.QUESTION_ID = Q.OBJ_ID AND C.DATE_DEL IS NULL AND C.LEVEL_ID = 1 AND C.STATE_ID <> 1001
                  AND C.EXPERT_ID = :V$EXPERT_ID AND C.STATE_ID < 1000
              WHERE S.ED_ID = :EXAM_ID AND S.DATE_DEL IS NULL AND S.STATE_ID = 10
              GROUP BY 1
          )
          INTO :N_TASKS;

          -- пока заглушка
          N_SECOND = NULL;

      END
      ELSE
      BEGIN
          N_TASKS = NULL;
          N_SECOND = NULL;
      END

      SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_EXPERT_GET (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(1000))
AS
declare variable V$EXPERT_ID bigint;
declare variable V$TEACHER_ID bigint;
declare variable V$NAME_LAST varchar(200);
declare variable V$NAME_FIRST varchar(200);
declare variable V$NAME_MID varchar(200);
declare variable V$BD date;
declare variable V$JOB_TITLE varchar(200);
declare variable V$AREA_ID bigint;
declare variable V$OU_NAME varchar(200);
declare variable V$AREA_NAME varchar(200);
declare variable V$IS_ACTIVE smallint;
declare variable V$CURRENT_YEAR integer;
declare variable V$DATE_FROM date;
declare variable V$DATE_TO date;
declare variable V$ASSN_ID bigint;
declare variable V$EXAM_ID bigint;
declare variable V$EXAM_NAME varchar(200);
declare variable V$EXAM_DATE date;
declare variable V$ROLE_ID integer;
declare variable V$ROLE_NAME varchar(100);
declare variable V$EXAM_STATE integer;
declare variable V$USER_NAME varchar(100);
declare variable V$SECOND_CHECK smallint;
declare variable V$ID bigint;
declare variable V$NAME varchar(1000);
declare variable V$SELF_ID bigint;
begin

  SELECT U.EXPERT_ID, U.TEACHER_ID, U.LAST_NAME, U.FIRST_NAME, U.MIDDLE_NAME, U.BIRTHDATE, U.JOB_TITLE, U.ORGANIZATION, U.AREA_ID, U.IS_ACTIVE, U.USER_NAME
  FROM UT_EXPERTS U
  WHERE U.EXPERT_ID = :I$OBJ_ID AND U.DATE_DEL IS NULL
  INTO :V$EXPERT_ID, :V$TEACHER_ID, :V$NAME_LAST, :V$NAME_FIRST, :V$NAME_MID, :V$BD, :V$JOB_TITLE, :V$OU_NAME, :V$AREA_ID, :V$IS_ACTIVE, :V$USER_NAME;

  IF(I$OBJ_ID IS NOT NULL AND V$EXPERT_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Данные по эксперту утрачены или запись была удалена';

  -- Для сотрудников ОУ добираем данные напрямую из объектной базы
  -- Если эксперт относится к числу явных сотрудников, возвращаем readonly - редактирование идет в Параграфе
  IF(V$TEACHER_ID IS NOT NULL) THEN
  BEGIN
      TAG_NAME = 'expert_readonly';
      VAL = '1';
      SUSPEND;

      SELECT NAME_LAST, NAME_FIRST, NAME_MID, BIRTH_DATE, JOB_TITLE, OU_NAME, AREA_ID, AREA_NAME
      FROM UT_EMPLOYEE_DESC(:V$TEACHER_ID)
      INTO :V$NAME_LAST, :V$NAME_FIRST, :V$NAME_MID, :V$BD, :V$JOB_TITLE, :V$OU_NAME, :V$AREA_ID, :V$AREA_NAME;
  END

  TAG_NAME = 'db_level';
  VAL = (SELECT KEY_VAL FROM KEYS WHERE KEY_CODE = 'LEVEL');
  SUSPEND;

  TAG_NAME = 'is_self';
  SELECT EXPERT_ID FROM UT_USER_TO_EXPERT(:I$USER_ID) INTO :V$SELF_ID;
  IF(V$SELF_ID = I$OBJ_ID) THEN VAL = '1'; ELSE VAL = '0';
  SUSPEND;

  TAG_NAME = 'id';
  VAL = I$OBJ_ID;
  SUSPEND;

  TAG_NAME = 'name_last';
  VAL = V$NAME_LAST;
  SUSPEND;

  TAG_NAME = 'name_first';
  VAL = V$NAME_FIRST;
  SUSPEND;

  TAG_NAME = 'name_mid';
  VAL = V$NAME_MID;
  SUSPEND;

  TAG_NAME = 'birth_date';
  VAL = V$BD;
  SUSPEND;

  TAG_NAME = 'job_title';
  VAL = V$JOB_TITLE;
  SUSPEND;

  TAG_NAME = 'ou_name';
  VAL = V$OU_NAME;
  SUSPEND;

  TAG_NAME = 'user_name';
  VAL = V$USER_NAME;
  SUSPEND;

  TAG_NAME = 'is_active';
  If(V$IS_ACTIVE IS NULL) THEN V$IS_ACTIVE = 1;
  VAL = V$IS_ACTIVE;
  SUSPEND;

  -- Название района
  TAG_NAME = 'area_id';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'area_id:selection';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'area_id:selection::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
      SELECT LISTVAL_ID, VAL
      FROM LISTVALS_LIST(7)
      ORDER BY 2
      INTO :V$ID, :V$NAME
  DO
  BEGIN
      TAG_NAME = 'area_id:selection:o';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'area_id:selection:o:id';
      VAL = V$ID;
      SUSPEND;
      TAG_NAME = 'area_id:selection:o:value';
      VAL = V$NAME;
      SUSPEND;
  END
  TAG_NAME = 'area_id:values:value';
  VAL = V$AREA_ID;
  SUSPEND;

  -- Список аккредитаций
  TAG_NAME = 'accreditations';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'accreditations::json&colon;array';
  VAL = '1';
  SUSPEND;

  -- Список текстирований, где назначен - отображаем только текущий учебный период
  -- Текущий учебный год
  IF(EXTRACT(MONTH FROM CURRENT_DATE) < 9) THEN V$CURRENT_YEAR = EXTRACT(YEAR FROM CURRENT_DATE) - 1; ELSE V$CURRENT_YEAR = EXTRACT(YEAR FROM CURRENT_DATE);
  V$DATE_FROM = '01.09.' || V$CURRENT_YEAR;
  V$DATE_TO = '31.08.' || (V$CURRENT_YEAR + 1);

  TAG_NAME = 'test_assns';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'test_assns::json&colon;array';
  VAL = '1';
  SUSPEND;

  FOR
      SELECT OBJ_ID, EXAM_ID, EXAM_NAME, EXAM_DATE, STATE, ROLE_ID, ROLE_NAME, SECOND_CHECK
      FROM UT_EXPERT_EXAM_ASSNS_LIST(:I$OBJ_ID, :V$CURRENT_YEAR)
      ORDER BY EXAM_DATE
      INTO :V$ASSN_ID, :V$EXAM_ID, :V$EXAM_NAME, :V$EXAM_DATE, :V$EXAM_STATE, :V$ROLE_ID, :V$ROLE_NAME, :V$SECOND_CHECK
  DO
  BEGIN

      TAG_NAME = 'test_assns:r';
      VAL = NULL;
      SUSPEND;

      TAG_NAME = 'test_assns:r:id';
      VAL = V$ASSN_ID;
      SUSPEND;

      TAG_NAME = 'test_assns:r:exam_id';
      VAL = V$EXAM_ID;
      SUSPEND;

      TAG_NAME = 'test_assns:r:name';
      VAL = V$EXAM_NAME;
      SUSPEND;

      TAG_NAME = 'test_assns:r:date';
      VAL = V$EXAM_DATE;
      SUSPEND;

      TAG_NAME = 'test_assns:r:role_id';
      VAL = V$ROLE_ID;
      SUSPEND;

      TAG_NAME = 'test_assns:r:role_name';
      VAL = V$ROLE_NAME;
      SUSPEND;

      TAG_NAME = 'test_assns:r:second_check';
      VAL = V$SECOND_CHECK;
      SUSPEND;

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_EXPERT_MARKUP_SUBMIT (
    I$OBJ_ID BIGINT,
    I$TASK_ID BIGINT,
    I$RESULT_ID BIGINT,
    I$USER_ID VARCHAR(40),
    I$TYPE SMALLINT,
    I$TEXT VARCHAR(1000),
    I$X1 INTEGER,
    I$Y1 INTEGER,
    I$X2 INTEGER,
    I$Y2 INTEGER,
    I$DELETE SMALLINT = 0)
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$EXPERT_ID bigint;
begin

  -- Проверяем права доступа
  SELECT EXPERT_ID
  FROM UT_USER_TO_EXPERT(:I$USER_ID)
  INTO :V$EXPERT_ID;

  IF(V$EXPERT_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Вы не идентифицированы как эксперт';

  IF(I$DELETE <> 0) THEN
  BEGIN

      UPDATE UT_SESSION_MARKUPS
      SET DATE_DEL = CURRENT_TIMESTAMP
      WHERE OBJ_ID = :I$OBJ_ID AND DATE_DEL IS NULL;

      OBJ_ID = NULL;

  END
  ELSE
  BEGIN

      IF(I$OBJ_ID IS NULL) THEN
      BEGIN

          IF(I$RESULT_ID IS NULL) THEN
          BEGIN

              SELECT FIRST 1 C.OBJ_ID
              FROM UT_SESSION_CHECKS C
              WHERE C.DATE_DEL IS NULL AND C.QUESTION_ID = :I$TASK_ID AND C.EXPERT_ID = :V$EXPERT_ID
              INTO :I$RESULT_ID;

              IF(I$RESULT_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не удалось найти запись проверки, подходящую по сочетанию параметров';

          END

          INSERT INTO UT_SESSION_MARKUPS
          (RESULT_ID, MARK_TYPE, TEXT_VALUE, INDEX_X1, INDEX_Y1, INDEX_X2, INDEX_Y2)
          VALUES (:I$RESULT_ID, :I$TYPE, :I$TEXT, :I$X1, :I$Y1, :I$X2, :I$Y2)
          RETURNING OBJ_ID INTO :OBJ_ID;

      END
      ELSE
      BEGIN

          UPDATE UT_SESSION_MARKUPS
          SET TEXT_VALUE = :I$TEXT
          WHERE OBJ_ID = :I$OBJ_ID;

          OBJ_ID = :I$OBJ_ID;

      END

  END

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_EXPERT_NEXT_TASK (
    I$EXAM_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(8000))
AS
declare variable V$EXPERT_ID bigint;
declare variable V$EXAM_ID bigint;
declare variable V$TASK_ID bigint;
declare variable V$CHECK_LEVEL smallint;
declare variable V$Q_ID bigint;
declare variable V$METHOD integer; /* 0 - электронное, 1 - электронное аудио, 2 - бумажные */
declare variable V$READY_STATE integer;
declare variable V$N_EXPERTS smallint;
declare variable V$N_PROCESSING smallint;
declare variable V$ORDER timestamp;
declare variable V$INDEX smallint;
declare variable V$QINDEX smallint;
declare variable V$MAX_SCORE smallint;
declare variable V$OBJ_NAME varchar(400);
declare variable V$DESC varchar(8000);
declare variable V$METADATA_ID varchar(40);
declare variable V$SCORE integer;
declare variable V$RES_ID bigint;
declare variable V$MARKUP_ID bigint;
declare variable V$MARKUP_TYPE integer;
declare variable V$X1 integer;
declare variable V$Y1 integer;
declare variable V$X2 integer;
declare variable V$Y2 integer;
declare variable V$BLANK_ID bigint;
declare variable V$NEXT_ID bigint;
declare variable V$PACKAGE_ID bigint;
declare variable V$FILE_ID varchar(40);
declare variable V$ID bigint;
declare variable V$THIS_ID bigint;
declare variable V$METHOD_ID smallint;
declare variable V$QUESTION_TEXT blob sub_type 1 segment size 80; /* текст вопроса */
declare variable V$QUESTION_HINT blob sub_type 1 segment size 80; /* подсказка к вопросу */
declare variable V$QUESTION_MEDIA_ID varchar(40); /* медиа-файл, прикрепленный к заданию, не путать с аудиозаписью ответа ученика */
declare variable V$KIM_QUESTION_ID bigint; /* вопрос в варианте тестирования в КИМ, куда создатель контента прикрепил файл */
declare variable V$LEVEL smallint;
begin

  SELECT EXPERT_ID
  FROM UT_USER_TO_EXPERT(:I$USER_ID)
  INTO :V$EXPERT_ID;

  IF(V$EXPERT_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Вы не идентифицированы как эксперт';

  -- Открыто ли вообще тестирование и находится ли оно в доступном статусе ?
  -- Есть ли у нас доступ к нему как у эксперта
  SELECT D.OBJ_ID, D.METHOD_ID, D.C_EXPERT_NUM, D.METHOD_ID
  FROM UT_EXPERTS E
  JOIN UT_EXAM_EXPERT_ASSN EA ON EA.EXPERT_ID = E.EXPERT_ID AND EA.DATE_DEL IS NULL
  JOIN UT_EXAM_DATES D ON D.OBJ_ID = EA.EXAM_ID AND D.DATE_DEL IS NULL AND D.EXAM_STATE = 900 AND D.OBJ_ID = :I$EXAM_ID
  WHERE E.EXPERT_ID = :V$EXPERT_ID AND E.DATE_DEL IS NULL
  INTO :V$EXAM_ID, :V$METHOD, :V$N_EXPERTS, :V$METHOD_ID;

  TAG_NAME = 'exam_id';
  VAL = V$EXAM_ID;
  SUSPEND;

  -- Если тестирование ушло со статуса проверки, возвращаем пустой ответ и выходим
  IF(V$EXAM_ID IS NULL) THEN
  BEGIN
      TAG_NAME = 'id';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'criterias';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'materials';
      VAL = NULL;
      SUSPEND;
      EXIT;
      TAG_NAME = 'markups';
      VAL = NULL;
      SUSPEND;
      EXIT;
  END

  -- Статус заданий, в котором можно проверять
  IF(V$METHOD IN (0, 1)) THEN V$READY_STATE = 21; ELSE V$READY_STATE = 30;

  -- Для мультизаданий типа C и V логика для электронных и бумажных тестирований разная
  -- Для бумаги всегда возвращается объект, соответствующий первому заданию по порядку
  -- обновление статусов по всем вопросам идет всегда синхронно, блокировка проверки создается сразу на все вопросы
  -- Для электронных проверок будет возвращаться только конкретный вопрос со своими критериями

  -- !!! пока только как для бумаги !!!

  -- Ищем очередное задание из числа вообще не проверявшихся, где не все проверки размещены, и данный эксперт еще ничего не проверял
  -- Работы берутся сначала из вообще не проверявшихся, затем из тех уже прошли проверку одним экспертом, и т.д.
  V$CHECK_LEVEL = 1;

  SELECT FIRST 1 Q.OBJ_ID, TVQ.QUESTION_ID, COUNT(SC.OBJ_ID)
  FROM UT_SESSIONS S
  JOIN UT_SESSION_QUESTIONS Q ON Q.SESSION_ID = S.OBJ_ID AND Q.DATE_DEL IS NULL AND Q.STATE_ID >= :V$READY_STATE AND Q.STATE_ID < 1000
  JOIN UT_TEST_VAR_QUESTIONS TVQ ON TVQ.OBJ_ID = Q.QUESTION_ID
  JOIN UT_TEST_STRUCT_POINTS TSP ON TSP.OBJ_ID = TVQ.STRUCT_POINT_ID
  JOIN UT_QUESTION_TYPE T ON T.OBJ_ID = TSP.Q_TYPE_ID AND T.IS_HANDCHECKED = 1
  -- Сколько экспертов уже взяли эту работу на проверку ?
  LEFT JOIN UT_SESSION_CHECKS SC ON SC.QUESTION_ID = Q.OBJ_ID AND SC.DATE_DEL IS NULL AND SC.LEVEL_ID = 1 AND SC.STATE_ID <> 1001
  WHERE S.ED_ID = :I$EXAM_ID AND S.DATE_DEL IS NULL AND S.STATE_ID = 10
      AND NOT EXISTS (
          -- Если эксперт отдал проверку другому, он все равно может снова получить эту работу
          SELECT FIRST 1 1
          FROM UT_SESSION_CHECKS C
          WHERE C.QUESTION_ID = Q.OBJ_ID AND C.DATE_DEL IS NULL AND C.LEVEL_ID = 1 AND C.EXPERT_ID = :V$EXPERT_ID AND C.STATE_ID <> 1001
      )
  GROUP BY 1, 2
  HAVING COUNT(SC.OBJ_ID) < :V$N_EXPERTS
  ORDER BY 3
  INTO :V$TASK_ID, :V$Q_ID, :V$N_PROCESSING;

  -- Повторная проверка работ экспертом, у которого есть права на такуж проверку
  -- !!!
  IF(V$TASK_ID IS NULL) THEN
  BEGIN
      V$CHECK_LEVEL = 2;
  END

  -- Если кончились не проверявшиеся работы, не осталось ли чего из ранее зарезервированных на этого эксперта, но еще не до конца проверенных
  -- Внимание: тут будут возвращены данные по любому уровню проверки (первая, вторая, апелляция)
  -- Если вопросов несколько, самая свежая метка будет у первого по порядку
  IF(V$TASK_ID IS NULL) THEN
  BEGIN
      SELECT FIRST 1 Q.OBJ_ID, TVQ.QUESTION_ID, -1, SC.LEVEL_ID
      FROM UT_SESSIONS S
      JOIN UT_SESSION_QUESTIONS Q ON Q.SESSION_ID = S.OBJ_ID AND Q.DATE_DEL IS NULL AND (Q.STATE_ID = :V$READY_STATE OR Q.STATE_ID = 50)
      JOIN UT_SESSION_CHECKS SC ON SC.QUESTION_ID = Q.OBJ_ID AND SC.DATE_DEL IS NULL AND SC.LEVEL_ID > 0 AND SC.STATE_ID NOT IN (1000, 1001) AND SC.EXPERT_ID = :V$EXPERT_ID
      JOIN UT_TEST_VAR_QUESTIONS TVQ ON TVQ.OBJ_ID = Q.QUESTION_ID
      JOIN UT_TEST_STRUCT_POINTS TSP ON TSP.OBJ_ID = TVQ.STRUCT_POINT_ID
      WHERE S.ED_ID = :I$EXAM_ID AND S.DATE_DEL IS NULL AND S.STATE_ID = 10
      ORDER BY SC.QUEUE_TIME, TSP.Q_ORDER
      INTO :V$TASK_ID, :V$Q_ID, :V$N_PROCESSING, :V$CHECK_LEVEL;
  END

  -- Выдаем код работы
  TAG_NAME = 'id';
  VAL = V$TASK_ID;
  SUSPEND;

  -- Если работ не осталось, выходим
  IF(V$TASK_ID IS NULL) THEN
  BEGIN
      TAG_NAME = 'criterias';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'materials';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'markups';
      VAL = NULL;
      SUSPEND;
      EXIT;
  END

  -- Формулировки вопросов - отдаем в виде массива, и сразу же регистрируем блокирующую запись
  -- !!! дофильтровать для электронного варианта сдачи, чтобы был только конкретный вопрос
  TAG_NAME = 'question';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'question::json&colon;array';
  VAL = NULL;
  SUSPEND;
  FOR
      SELECT TVQ.OBJ_ID, TSP.Q_ORDER, Q.QUESTION, SQ2.OBJ_ID, Q.QUESTION, Q.HINT, Q.METADATA_ID, Q.OBJ_ID, Q.Q_LEVEL
      FROM UT_SESSION_QUESTIONS SQ
      JOIN UT_SESSIONS S ON S.OBJ_ID = SQ.SESSION_ID
      JOIN UT_EXAM_TEST_VARS ETV ON ETV.OBJ_ID = S.VARIANT_ID
      JOIN UT_TEST_VARS TV ON TV.OBJ_ID = ETV.TEST_VAR_ID
      JOIN UT_TEST_VAR_QUESTIONS TVQ ON TVQ.DATE_DEL IS NULL AND TVQ.VAR_ID = TV.OBJ_ID
      JOIN UT_TEST_STRUCT_POINTS TSP ON TSP.OBJ_ID = TVQ.STRUCT_POINT_ID
      JOIN UT_QUESTIONS Q ON Q.OBJ_ID = TVQ.QUESTION_ID AND Q.QUESTION_TYPE IN (3, 8)
      -- и обратно связь с реальным вопросом
      JOIN UT_SESSION_QUESTIONS SQ2 ON SQ2.DATE_DEL IS NULL AND SQ2.SESSION_ID = SQ.SESSION_ID AND SQ2.QUESTION_ID = TVQ.OBJ_ID
      -- * в электронных тестированиях только один вопрос
      AND ( SQ2.OBJ_ID = :V$TASK_ID OR :V$METHOD_ID NOT IN (0,1) )
      WHERE SQ.OBJ_ID = :V$TASK_ID AND SQ.DATE_DEL IS NULL
      ORDER BY 2
      INTO :V$ID, :V$INDEX, :V$DESC, :V$THIS_ID, :V$QUESTION_TEXT, :V$QUESTION_HINT, :V$QUESTION_MEDIA_ID, :V$KIM_QUESTION_ID, :V$LEVEL

  DO
  BEGIN
      TAG_NAME = 'question:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'question:r:id'; -- это не особо нужно
      VAL = V$ID;
      SUSPEND;
      TAG_NAME = 'question:r:index';
      VAL = V$INDEX;
      SUSPEND;
      TAG_NAME = 'question:r:value';
      VAL = V$DESC;
      SUSPEND;
      TAG_NAME = 'question:r:level';
      VAL = V$LEVEL;
      SUSPEND;
      TAG_NAME = 'question:r:question_text';
      VAL = V$QUESTION_TEXT;
      SUSPEND;
      TAG_NAME = 'question:r:question_hint';
      VAL = V$QUESTION_HINT;
      SUSPEND;
      TAG_NAME = 'question:r:question_media_id';
      VAL = V$QUESTION_MEDIA_ID;
      SUSPEND;
      TAG_NAME = 'question:r:kim_question_id';
      VAL = V$KIM_QUESTION_ID;
      SUSPEND;

      -- Если это начало проверки, формируем запись блокировки в этом конкретном вопросе в статусе 10, а также корректируем статус вопроса
      -- вопрос переводится в статус передано на проверку или передано на перепроверку
      IF(V$N_PROCESSING >= 0) THEN
      BEGIN
          -- Запись итогового результата
          IF(V$N_PROCESSING = 0) THEN
          BEGIN
              INSERT INTO UT_SESSION_CHECKS
              (QUESTION_ID, EXPERT_ID, LEVEL_ID, STATE_ID)
              VALUES (:V$THIS_ID, NULL, 0, 10);
--              EXECUTE PROCEDURE ADD_TO_CONSOLE_LOG 'Итоговый результат INSERT UT_SESSION_CHECKS V$THIS_ID: ' || V$THIS_ID;
          END

          -- Запись блокировки конкретным экспертом
          INSERT INTO UT_SESSION_CHECKS
          (QUESTION_ID, EXPERT_ID, LEVEL_ID, STATE_ID)
          VALUES (:V$THIS_ID, :V$EXPERT_ID, :V$CHECK_LEVEL, 10);
--          EXECUTE PROCEDURE ADD_TO_CONSOLE_LOG 'Хапись блокировки экспертом INSERT UT_SESSION_CHECKS V$THIS_ID: ' || V$THIS_ID || ' V$EXPERT_ID: ' || V$EXPERT_ID || ' :V$CHECK_LEVEL ' || :V$CHECK_LEVEL;

          UPDATE UT_SESSION_QUESTIONS
          SET STATE_ID = IIF(:V$CHECK_LEVEL = 1, 50, 80)
          WHERE OBJ_ID = :V$THIS_ID AND STATE_ID < IIF(:V$CHECK_LEVEL = 1, 50, 80);
      END
  END

  -- Список критериев для данного вопроса. Внимание: один и тот же эксперт не должен проверять одну работу дважды
  -- !!! дофильтровать для электронного варианта сдачи, чтобы был только конкретный вопрос
  TAG_NAME = 'criterias';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'criterias::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
      SELECT TSP.Q_ORDER, A.SORT_ORDER, A.A_LEVEL, A.OBJ_NAME, A.VARIANT, CR.RAW_RESULT
      FROM UT_SESSION_QUESTIONS SQ
      JOIN UT_SESSIONS S ON S.OBJ_ID = SQ.SESSION_ID
      JOIN UT_EXAM_TEST_VARS ETV ON ETV.OBJ_ID = S.VARIANT_ID
      JOIN UT_TEST_VARS TV ON TV.OBJ_ID = ETV.TEST_VAR_ID
      JOIN UT_TEST_VAR_QUESTIONS TVQ ON TVQ.DATE_DEL IS NULL AND TVQ.VAR_ID = TV.OBJ_ID -- !!! AND TVQ.OBJ_ID = Q.QUESTION_ID
      -- * в электронных тестированиях выдается по 1 вопросу
        AND (SQ.QUESTION_ID = TVQ.OBJ_ID OR :V$METHOD_ID NOT IN (0,1))
      JOIN UT_TEST_STRUCT_POINTS TSP ON TSP.OBJ_ID = TVQ.STRUCT_POINT_ID
      JOIN UT_QUESTIONS Q ON Q.OBJ_ID = TVQ.QUESTION_ID AND Q.QUESTION_TYPE IN (3, 8)
      -- * для вопроов С и V критерии хранятся в таблице ответов
      JOIN UT_ANSWERS A ON A.QUESTION_ID = Q.OBJ_ID AND A.DATE_DEL IS NULL
      LEFT JOIN UT_SESSION_CHECKS SC ON SC.QUESTION_ID = SQ.OBJ_ID AND SC.EXPERT_ID = :V$EXPERT_ID AND SC.DATE_DEL IS NULL AND SC.STATE_ID <> 1001
      LEFT JOIN UT_SESSION_CHECK_RES CR ON CR.DATE_DEL IS NULL AND CR.CHECK_ID = SC.OBJ_ID AND CR.CRITERIA_ID = A.SORT_ORDER
      WHERE SQ.OBJ_ID = :V$TASK_ID AND SQ.DATE_DEL IS NULL
      ORDER BY TSP.Q_ORDER, A.SORT_ORDER
      INTO :V$QINDEX, :V$INDEX, :V$MAX_SCORE, :V$OBJ_NAME, :V$DESC, :V$SCORE
  DO
  BEGIN
      TAG_NAME = 'criterias:c';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'criterias:c:q_index';
      VAL = V$QINDEX;
      SUSPEND;
      TAG_NAME = 'criterias:c:index';
      VAL = V$INDEX;
      SUSPEND;
      TAG_NAME = 'criterias:c:obj_name';
      VAL = V$OBJ_NAME;
      SUSPEND;
      TAG_NAME = 'criterias:c:description';
      VAL = V$DESC;
      SUSPEND;
      TAG_NAME = 'criterias:c:max_score';
      VAL = V$MAX_SCORE;
      SUSPEND;
      -- Оценка в данном вопросе
      TAG_NAME = 'criterias:c:score';
      VAL = V$SCORE;
      SUSPEND;
  END

  -- Список материалов в ответе
  TAG_NAME = 'materials';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'materials::json&colon;array';
  VAL = '1';
  SUSPEND;

  V$DESC = NULL;
  V$METADATA_ID = NULL;
  SELECT ANSWER_DATA, METADATA_ID
  FROM UT_SESSION_QUESTIONS
  WHERE OBJ_ID = :V$TASK_ID
  INTO :V$DESC, :V$METADATA_ID;

  -- Возвращаем текстовый контент только когда он есть
  IF(V$METHOD = 0 AND V$DESC IS NOT NULL) THEN
  BEGIN
      TAG_NAME = 'materials:m';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'materials:m:id';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'materials:m:type';
      VAL = 'text';
      SUSPEND;
      TAG_NAME = 'materials:m:text';
      VAL = V$DESC;
      SUSPEND;
  END

  -- Метаданные из основного файла. Данные по самому файлу будут подгружены вместе с самим файлом
  IF(V$METADATA_ID IS NOT NULL AND CHAR_LENGTH(V$METADATA_ID) > 0) THEN
  BEGIN
      TAG_NAME = 'materials:m';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'materials:m:id';
      VAL = V$METADATA_ID;
      SUSPEND;
      TAG_NAME = 'materials:m:type';
      VAL = 'file';
      SUSPEND;
  END

  -- Файлы со сканами работ V$METHOD = 2
  -- Всегда отдаем все бланки работ типа C и дополнительные бланки из сессии
  IF(V$DESC IS NULL) THEN
  BEGIN
      SELECT FIRST 1 B.OBJ_ID, B.NEXT_BLANK_ID, B.PACKAGE_ID, B.FILE_ID
      FROM UT_PACKAGES P
      JOIN UT_BLANKS B ON B.DATE_DEL IS NULL AND B.PACKAGE_ID = P.OBJ_ID AND B.BLANK_SIDE = 0
      JOIN UT_PAGE_TEMPLATES PT ON PT.OBJ_ID = B.BLANK_TYPE AND PT.BLANK_TYPE = 2
      WHERE P.DATE_DEL IS NULL AND P.ED_ID = :I$EXAM_ID
      INTO :V$BLANK_ID, :V$NEXT_ID, :V$PACKAGE_ID, :V$FILE_ID;

      WHILE(V$BLANK_ID IS NOT NULL) DO
      BEGIN
          TAG_NAME = 'materials:m';
          VAL = NULL;
          SUSPEND;
          TAG_NAME = 'materials:m:id';
          VAL = V$PACKAGE_ID || ':' || V$FILE_ID;
          SUSPEND;
          TAG_NAME = 'materials:m:type';
          VAL = 'file';
          SUSPEND;

          V$BLANK_ID = NULL;
          SELECT FIRST 1 B.OBJ_ID, B.PACKAGE_ID, B.FILE_ID, B.NEXT_BLANK_ID
          FROM UT_PACKAGES P
          JOIN UT_BLANKS B ON B.DATE_DEL IS NULL AND B.PACKAGE_ID = P.OBJ_ID AND B.OBJ_ID = :V$NEXT_ID
          WHERE P.DATE_DEL IS NULL AND P.ED_ID = :I$EXAM_ID
          INTO :V$BLANK_ID, :V$PACKAGE_ID, :V$FILE_ID, :V$NEXT_ID;
      END
  END

  -- Маркеры проверки, всегда идут к конкретному вопросу (для бумажного варианта - к первому вопросу типа C)
  -- !!! переделать UT_SESSION_MARKUPS в остальных запросах !!!
  TAG_NAME = 'markups';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'markups::json&colon;array';
  VAL = '1';
  SUSPEND;

  FOR
      SELECT C.OBJ_ID, SM.OBJ_ID, SM.MARK_TYPE, SM.TEXT_VALUE, SM.INDEX_X1, SM.INDEX_Y1, SM.INDEX_X2, SM.INDEX_Y2
      FROM UT_SESSION_CHECKS C
      JOIN UT_SESSION_MARKUPS SM ON SM.RESULT_ID = C.OBJ_ID AND SM.DATE_DEL IS NULL
      WHERE C.DATE_DEL IS NULL AND C.QUESTION_ID = :V$TASK_ID AND C.EXPERT_ID = :V$EXPERT_ID
      INTO :V$RES_ID, :V$MARKUP_ID, :V$MARKUP_TYPE, :V$OBJ_NAME, :V$X1, :V$Y1, :V$X2, :V$Y2
  DO
  BEGIN
      TAG_NAME = 'markups:m';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'markups:m:id';
      VAL = V$MARKUP_ID;
      SUSPEND;
      TAG_NAME = 'markups:m:result_id';
      VAL = V$RES_ID;
      SUSPEND;
      TAG_NAME = 'markups:m:type';
      VAL = V$MARKUP_TYPE;
      SUSPEND;
      TAG_NAME = 'markups:m:text';
      VAL = V$OBJ_NAME;
      SUSPEND;

      -- В зависимости от типа коррекция названий параметров
      IF(V$MARKUP_TYPE IN (0, 1, 2)) THEN
      BEGIN
          TAG_NAME = 'markups:m:index';
          VAL = V$X1;
          SUSPEND;
          TAG_NAME = 'markups:m:index_to';
          VAL = V$X2;
          SUSPEND;
      END
      ELSE IF(V$MARKUP_TYPE IN (10, 11, 12)) THEN
      BEGIN
          TAG_NAME = 'markups:m:index';
          VAL = V$X1;
          SUSPEND;
      END
      ELSE
      BEGIN
      END
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_EXPERT_SAVE (
    I$OBJ_ID BIGINT,
    I$INT_ID BIGINT,
    I$NAME_LAST VARCHAR(200),
    I$NAME_FIRST VARCHAR(200),
    I$NAME_MID VARCHAR(200),
    I$BIRTH_DATE DATE,
    I$AREA_ID BIGINT,
    I$JOB_TITLE VARCHAR(400),
    I$ORG_NAME VARCHAR(400),
    I$IS_ACTIVE SMALLINT,
    I$USER_NAME VARCHAR(100),
    I$PASSWORD VARCHAR(40),
    I$USER_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$OLD_USER_NAME varchar(100);
declare variable V$OLD_PASSWORD varchar(100);
declare variable V$EMPLOYEE_ID bigint;
declare variable V$ORG_ID bigint;
declare variable V$SELF_ID bigint;
declare variable V$ROLE smallint;
begin

  -- Сотрудники-эксперты, если не имеют админских прав, не могут добавлять экспертов или менять что-то кроме пароля
  SELECT EXPERT_ID, EXPERT_ROLE
  FROM UT_USER_TO_EXPERT(:I$USER_ID)
  INTO :V$SELF_ID, :V$ROLE;

  -- Внимание: PERSON_ID передается только при создании нового эксперта, при редактировании восстанавливаем
  IF(I$OBJ_ID IS NOT NULL) THEN
  BEGIN
      SELECT FIRST 1 U.TEACHER_ID
      FROM UT_EXPERTS U
      WHERE U.EXPERT_ID = :I$OBJ_ID
      INTO :I$INT_ID;
  END

  -- Для эксперта из числа сотрудников логина может не быть, этот вариант обходим
  -- PASSWORD: NULL = нет пароля, пустая строка = оставляем старый пароль, иначе хэш
  IF(I$INT_ID IS NULL AND I$USER_NAME IS NULL AND I$PASSWORD IS NOT NULL) THEN EXCEPTION DATA_ERROR 'При удалении логина необходимо очистить также и пароль';

  -- I$INT_ID - ID внутренней персоны-сотрудника, если NULL то сторонний эксперт
  IF(I$INT_ID IS NULL) THEN
  BEGIN
      IF(I$NAME_LAST IS NULL) THEN EXCEPTION DATA_ERROR 'Фамилия не указана';
      IF(I$NAME_FIRST IS NULL) THEN EXCEPTION DATA_ERROR 'Имя не указано';
      IF(I$ORG_NAME IS NULL) THEN EXCEPTION DATA_ERROR 'Организация не указана';
      IF(I$JOB_TITLE IS NULL) THEN EXCEPTION DATA_ERROR 'Должность по месту работы не указана';
      IF(I$AREA_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Район не указан';
  END
  ELSE
  BEGIN
      -- Проверяем тип объекта, и сразу забираем все реквизиты
      SELECT OBJ_ID, OU_NAME, NAME_LAST, NAME_FIRST, NAME_MID, BIRTH_DATE, JOB_TITLE, AREA_ID, OU_ID
      FROM UT_EMPLOYEE_DESC(:I$INT_ID)
      INTO :V$EMPLOYEE_ID, :I$ORG_NAME, :I$NAME_LAST, :I$NAME_FIRST, :I$NAME_MID, :I$BIRTH_DATE, :I$JOB_TITLE, :I$AREA_ID, :V$ORG_ID;

      IF(V$EMPLOYEE_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Запись сотрудника не найдена';

      SELECT FIRST 1 V1180.VAL
      FROM VALS V1180
      WHERE V1180.OBJ_ID = :I$INT_ID AND V1180.PARAM_ID = 1180 AND V1180.IS_DEL = 0
      INTO :I$USER_NAME;

      IF(I$USER_NAME IS NULL) THEN EXCEPTION DATA_ERROR 'Нельзя сохранить данные, пока для пользователя не прописана электронная почта';
  END

  -- Проверяем что такого логина нет больше ни у кого
  IF(I$USER_NAME IS NOT NULL) THEN
  BEGIN

      IF(EXISTS(
          SELECT FIRST 1 1
          FROM USERS U
          LEFT JOIN UT_EXPERTS E ON E.TEACHER_ID = U.OBJ_ID AND E.DATE_DEL IS NULL
          WHERE U.DATE_DEL IS NULL AND U.USER_NAME = :I$USER_NAME AND (:I$OBJ_ID IS NULL OR E.EXPERT_ID IS NULL OR E.EXPERT_ID <> :I$OBJ_ID)
          UNION
          SELECT FIRST 1 1
          FROM UT_EXPERTS 
          WHERE DATE_DEL IS NULL AND USER_NAME = :I$USER_NAME AND (:I$OBJ_ID IS NULL OR EXPERT_ID <> :I$OBJ_ID)
      ))
      THEN EXCEPTION DATA_ERROR 'Такое имя пользователя уже используется';

  END

  IF(I$OBJ_ID IS NULL) THEN
  BEGIN

      IF(V$SELF_ID IS NOT NULL AND V$ROLE NOT IN (1, 5, 6)) THEN
          EXCEPTION DATA_ERROR 'Вы не можете добавлять записи экспертов';

      -- Для нового стороннего эксперта - если заводим логин, должен быть и пароль
      IF(I$INT_ID IS NULL AND I$USER_NAME IS NOT NULL AND (I$PASSWORD = '' OR I$PASSWORD IS NULL)) THEN
          EXCEPTION DATA_ERROR 'При задании имени пользователя, необходимо задать также и пароль';

      -- Для сотрудников проставляется реальная ОУ, откуда они взяты. Для сторонних проставляется ID ОУ, которая их добавила
      IF(I$INT_ID IS NULL) THEN
      BEGIN
          SELECT FIRST 1 L2.OBJ_ID
          FROM LINKS L2
          WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
          INTO :V$ORG_ID;
      END

      INSERT INTO UT_EXPERTS
      (TEACHER_ID, LAST_NAME, FIRST_NAME, MIDDLE_NAME, BIRTHDATE, JOB_TITLE, ORGANIZATION, IS_ACTIVE, AREA_ID, USER_NAME, PWD, ORG_ID)
      VALUES (:I$INT_ID, :I$NAME_LAST, :I$NAME_FIRST, :I$NAME_MID, :I$BIRTH_DATE, :I$JOB_TITLE, :I$ORG_NAME, :I$IS_ACTIVE, :I$AREA_ID, :I$USER_NAME, :I$PASSWORD, :V$ORG_ID)
      RETURNING EXPERT_ID INTO :OBJ_ID;

  END
  ELSE
  BEGIN

      -- Выбираем старый пароль и имя пользователя
      SELECT USER_NAME, PWD
      FROM UT_EXPERTS
      WHERE EXPERT_ID = :I$OBJ_ID AND DATE_DEL IS NULL
      INTO :V$OLD_USER_NAME, :V$OLD_PASSWORD;

      IF(((V$OLD_USER_NAME IS NULL AND I$USER_NAME IS NOT NULL) OR (I$USER_NAME <> V$OLD_USER_NAME)) AND (I$PASSWORD = '' OR I$PASSWORD IS NULL)) THEN
          EXCEPTION DATA_ERROR 'При изменении имени пользователя необходимо заново указать пароль';

      -- Пароль остается старый ?
      IF(I$PASSWORD = '') THEN I$PASSWORD = V$OLD_PASSWORD;

      -- Внимание: ORG_ID при редактировании не меняем, остается какой был изначально

      IF(V$SELF_ID IS NOT NULL AND V$ROLE NOT IN (1, 5, 6)) THEN
      BEGIN

          -- Рядовой пользователь может менять только пароль, а логин подставляется автоматически
          UPDATE UT_EXPERTS
          SET USER_NAME = :I$USER_NAME, PWD = :I$PASSWORD
          WHERE EXPERT_ID = :I$OBJ_ID AND DATE_DEL IS NULL;

      END
      ELSE
      BEGIN

          UPDATE UT_EXPERTS
          SET LAST_NAME = :I$NAME_LAST, FIRST_NAME = :I$NAME_FIRST, MIDDLE_NAME = :I$NAME_MID, BIRTHDATE = :I$BIRTH_DATE,
              JOB_TITLE = :I$JOB_TITLE, ORGANIZATION = :I$ORG_NAME, IS_ACTIVE = :I$IS_ACTIVE, AREA_ID = :I$AREA_ID, USER_NAME = :I$USER_NAME, PWD = :I$PASSWORD
          WHERE EXPERT_ID = :I$OBJ_ID AND DATE_DEL IS NULL;

      END

      -- Для уровня ОУ, обновляем пароль у пользователя, к которому привязан сотрудник
      -- !!!

      OBJ_ID = I$OBJ_ID;

  END

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_EXPERT_TASK_CR_SUBMIT (
    I$TASK_ID BIGINT,
    I$USER_ID VARCHAR(40),
    I$QUESTION SMALLINT,
    I$INDEX SMALLINT,
    I$SCORE SMALLINT)
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$EXPERT_ID bigint;
declare variable V$LEVEL_ID smallint;
declare variable V$CHECK_ID bigint;
declare variable V$MAX_SCORE smallint;
declare variable V$IS_HANDCHECKED smallint;
declare variable V$REAL_TASK_ID bigint;
begin

  SELECT EXPERT_ID
  FROM UT_USER_TO_EXPERT(:I$USER_ID)
  INTO :V$EXPERT_ID;

  IF(V$EXPERT_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Эксперт не найден';

  -- Добавление: теперь нужно передавать номер вопроса + номер критерия, при этом в качестве I$USER_ID отдается ID первого вопроса
  -- А есть ли у нас назначенная проверка данным экспертом по этой работе ?
  SELECT C.LEVEL_ID, S.OBJ_ID, C.OBJ_ID
  FROM UT_SESSION_QUESTIONS SS
  JOIN UT_SESSION_QUESTIONS S ON S.DATE_DEL IS NULL AND S.SESSION_ID = SS.SESSION_ID
  JOIN UT_TEST_VAR_QUESTIONS TVQ ON TVQ.OBJ_ID = S.QUESTION_ID
  JOIN UT_TEST_STRUCT_POINTS TSP ON TSP.OBJ_ID = TVQ.STRUCT_POINT_ID AND TSP.Q_ORDER = :I$QUESTION
  JOIN UT_SESSION_CHECKS C ON C.QUESTION_ID = S.OBJ_ID AND C.DATE_DEL IS NULL AND C.STATE_ID >= 10 AND C.STATE_ID < 1000 AND C.EXPERT_ID = :V$EXPERT_ID
  WHERE SS.OBJ_ID = :I$TASK_ID AND SS.DATE_DEL IS NULL AND SS.STATE_ID >= 50 AND SS.STATE_ID < 1000
  INTO :V$LEVEL_ID, :V$REAL_TASK_ID, :V$CHECK_ID;

  IF(V$LEVEL_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Нет записи проверки, либо статус работы не допускает изменения данных';

  -- STATE_ID для данного случае нас не интересует, он обновляется автоматически для электронной проверки
  SELECT FIRST 1 R.OBJ_ID
  FROM UT_SESSION_CHECK_RES R
  WHERE R.CHECK_ID = :V$CHECK_ID AND R.CRITERIA_ID = :I$INDEX AND R.DATE_DEL IS NULL
  INTO :OBJ_ID;

  -- Если балл уже был проставлен - удаляем старую запись
  IF(OBJ_ID IS NOT NULL) THEN
  BEGIN
      UPDATE UT_SESSION_CHECK_RES
      SET DATE_DEL = CURRENT_TIMESTAMP
      WHERE OBJ_ID = :OBJ_ID AND DATE_DEL IS NULL;
  END

  IF(I$SCORE IS NOT NULL) THEN
  BEGIN

      -- А есть ли у нас такой критерий в вопросе, и положено ли вообще этот вопрос проверять эксперту ?
      SELECT FIRST 1 A.A_LEVEL, T.IS_HANDCHECKED
      FROM UT_SESSION_QUESTIONS SQ
      JOIN UT_TEST_VAR_QUESTIONS TVQ ON TVQ.OBJ_ID = SQ.QUESTION_ID
      JOIN UT_QUESTIONS Q ON Q.OBJ_ID = TVQ.QUESTION_ID -- проверить наличие критерия !
      JOIN UT_QUESTION_TYPE T ON T.OBJ_ID = Q.QUESTION_TYPE
      JOIN UT_ANSWERS A ON A.QUESTION_ID = Q.OBJ_ID AND A.DATE_DEL IS NULL AND A.SORT_ORDER = :I$INDEX
      WHERE SQ.OBJ_ID = :V$REAL_TASK_ID AND SQ.DATE_DEL IS NULL
      INTO :V$MAX_SCORE, :V$IS_HANDCHECKED;

      IF(V$MAX_SCORE IS NULL) THEN EXCEPTION DATA_ERROR 'Нет критерия ' || I$INDEX || ', заданного для проверяемого вопроса';
      IF(I$SCORE > V$MAX_SCORE) THEN EXCEPTION DATA_ERROR 'Оценка по критерию ' || I$INDEX || ' превышает максимально допустимую';

      -- Внимание: SCORE тут может быть -1 (не проверялся)
      INSERT INTO UT_SESSION_CHECK_RES
      (CHECK_ID, CRITERIA_ID, RAW_RESULT)
      VALUES (:V$CHECK_ID, :I$INDEX, :I$SCORE)
      RETURNING OBJ_ID INTO :OBJ_ID;

  END

  -- Суммарную запись не обновляем, она посчитается в TASK_SUBMIT

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_EXPERT_TASK_DEFER (
    I$TASK_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$EXPERT_ID bigint;
begin

  SELECT EXPERT_ID
  FROM UT_USER_TO_EXPERT(:I$USER_ID)
  INTO :V$EXPERT_ID;

  IF(V$EXPERT_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Эксперт не найден';

  SELECT FIRST 1 C.OBJ_ID
  FROM UT_SESSION_QUESTIONS S
  JOIN UT_SESSION_CHECKS C ON C.QUESTION_ID = S.OBJ_ID AND C.DATE_DEL IS NULL AND C.STATE_ID >= 10 AND C.STATE_ID < 1000 AND C.EXPERT_ID = :V$EXPERT_ID
  WHERE S.OBJ_ID = :I$TASK_ID AND S.DATE_DEL IS NULL
  INTO :OBJ_ID;

  IF(OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Нет записи проверки, либо статус работы не допускает изменения данных';

  UPDATE UT_SESSION_CHECKS
  SET QUEUE_TIME = CURRENT_TIMESTAMP
  WHERE OBJ_ID = :OBJ_ID;

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_EXPERT_TASK_FORWARD (
    I$TASK_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$EXPERT_ID bigint;
declare variable V$C_EXPERT_NUM smallint;
declare variable V$CHECK_LEVEL smallint;
begin

  SELECT EXPERT_ID
  FROM UT_USER_TO_EXPERT(:I$USER_ID)
  INTO :V$EXPERT_ID;

  IF(V$EXPERT_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Эксперт не найден';

  SELECT FIRST 1 C.OBJ_ID, D.C_EXPERT_NUM, C.LEVEL_ID
  FROM UT_SESSION_QUESTIONS SQ
  JOIN UT_SESSION_CHECKS C ON C.QUESTION_ID = SQ.OBJ_ID AND C.DATE_DEL IS NULL AND C.STATE_ID >= 10 AND C.STATE_ID < 1000 AND C.EXPERT_ID = :V$EXPERT_ID
  JOIN UT_SESSIONS S ON S.OBJ_ID = SQ.SESSION_ID
  JOIN UT_EXAM_DATES D ON D.OBJ_ID = S.ED_ID
  WHERE SQ.OBJ_ID = :I$TASK_ID AND SQ.DATE_DEL IS NULL
  INTO :OBJ_ID, :V$C_EXPERT_NUM, :V$CHECK_LEVEL;

  IF(OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Нет записи проверки, либо статус работы не допускает изменения данных';
  IF(V$CHECK_LEVEL > 1) THEN EXCEPTION DATA_ERROR 'Нельзя передать работу другому эксперту для повторных проверок';

  -- Ищем первого случайного эксперта с уровнем ведущий+

  -- Создаем новую запись проверки на этого эксперта

  -- Переводим свою проверку в статус 1001
  UPDATE UT_SESSION_CHECKS
  SET STATE_ID = 1001
  WHERE OBJ_ID = :OBJ_ID AND STATE_ID < 1000;

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_EXPERT_TASK_SUBMIT (
    I$TASK_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$SESSION_ID bigint;
declare variable V$EXPERT_ID bigint;
declare variable V$LEVEL_ID bigint;
declare variable V$SUM_RATE integer;
declare variable V$C_CALC_MODE smallint;
declare variable V$C_EXPERT_NUM smallint;
declare variable V$C_DIFF_QUESTION integer;
declare variable V$C_DIFF_TOTAL integer;
declare variable V$FINAL_ID bigint;
declare variable V$FINAL_RES_ID bigint;
declare variable V$CRITERIA integer;
declare variable V$CHECKS integer;
declare variable V$RATE integer;
declare variable V$MIN integer;
declare variable V$MAX integer;
declare variable V$REAL_MIN integer;
declare variable V$REAL_MAX integer;
declare variable V$AVG double precision;
declare variable V$SC smallint;
declare variable V$NEW_STATE bigint;
declare variable TMP integer;
declare variable V$REAL_TASK_ID bigint;
declare variable V$CHECK_ID bigint;
declare variable V$METHOD_ID integer;
begin

  SELECT EXPERT_ID
  FROM UT_USER_TO_EXPERT(:I$USER_ID)
  INTO :V$EXPERT_ID;

  IF(V$EXPERT_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Эксперт не найден';

  -- А есть ли у нас назначенная проверка данным экспертом по этой работе ?
  SELECT FIRST 1 C.OBJ_ID, C.LEVEL_ID, SQ.SESSION_ID, D.C_CALC_MODE, D.C_EXPERT_NUM, D.C_DIFF_QUESTION, D.C_DIFF_TOTAL, D.METHOD_ID
  FROM UT_SESSION_QUESTIONS SQ
  JOIN UT_SESSION_CHECKS C ON C.QUESTION_ID = SQ.OBJ_ID AND C.DATE_DEL IS NULL AND C.STATE_ID >= 10 AND C.STATE_ID < 1000 AND C.EXPERT_ID = :V$EXPERT_ID
  -- вверх по дереву
  JOIN UT_SESSIONS SS ON SS.OBJ_ID = SQ.SESSION_ID
  JOIN UT_EXAM_DATES D ON D.OBJ_ID = SS.ED_ID
  WHERE SQ.OBJ_ID = :I$TASK_ID AND SQ.DATE_DEL IS NULL AND SQ.STATE_ID >= 50 AND SQ.STATE_ID < 1000
  INTO :OBJ_ID, :V$LEVEL_ID, :V$SESSION_ID, :V$C_CALC_MODE, :V$C_EXPERT_NUM, :V$C_DIFF_QUESTION, :V$C_DIFF_TOTAL, :V$METHOD_ID;

  IF(OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Нет записи проверки, либо статус работы не допускает изменения данных';
  IF(V$C_EXPERT_NUM = 0) THEN EXCEPTION DATA_ERROR 'Системная ошибка: в тестировании указано нулевое количество экспертов';

  -- В случае бумажного тестирования проверяем все вопросы, в электронном только этот конкретный
  FOR
      SELECT SQ.OBJ_ID, C.OBJ_ID
      FROM UT_SESSION_QUESTIONS SQ
      JOIN UT_TEST_VAR_QUESTIONS TVQ ON TVQ.OBJ_ID = SQ.QUESTION_ID
      JOIN UT_TEST_STRUCT_POINTS TSP ON TSP.OBJ_ID = TVQ.STRUCT_POINT_ID AND TSP.Q_TYPE_ID IN (3, 8)
      JOIN UT_SESSION_CHECKS C ON C.QUESTION_ID = SQ.OBJ_ID AND C.DATE_DEL IS NULL AND C.STATE_ID >= 10 AND C.STATE_ID < 1000
          AND C.EXPERT_ID = :V$EXPERT_ID AND C.LEVEL_ID = :V$LEVEL_ID -- сверка по LEVEL избыточна
      WHERE SQ.DATE_DEL IS NULL AND SQ.SESSION_ID = :V$SESSION_ID AND (:V$METHOD_ID = 2 OR SQ.OBJ_ID = :I$TASK_ID)
      INTO :V$REAL_TASK_ID, :V$CHECK_ID
  DO
  BEGIN

      -- Все ли критерии у нас проставлены ?
      -- Проверить, что баллы в допустимых пределах !
      IF(EXISTS(
          SELECT FIRST 1 1
          FROM UT_SESSION_QUESTIONS SQ
          JOIN UT_TEST_VAR_QUESTIONS TVQ ON TVQ.OBJ_ID = SQ.QUESTION_ID
          JOIN UT_QUESTIONS Q ON Q.OBJ_ID = TVQ.QUESTION_ID
          JOIN UT_ANSWERS A ON A.QUESTION_ID = Q.OBJ_ID AND A.DATE_DEL IS NULL
          LEFT JOIN UT_SESSION_CHECK_RES CR ON CR.CHECK_ID = :V$CHECK_ID AND CR.DATE_DEL IS NULL AND CR.CRITERIA_ID = A.SORT_ORDER AND CR.RAW_RESULT IS NOT NULL
          WHERE SQ.OBJ_ID = :V$REAL_TASK_ID AND SQ.DATE_DEL IS NULL AND CR.OBJ_ID IS NULL
      ))
      THEN EXCEPTION DATA_ERROR 'Не все критерии оценки были выставлены';

      -- Суммарный балл по всем критериям (отрицательные значения критериев = не приступал, считаем нулями)
      SELECT SUM(IIF(CR.RAW_RESULT < 0, 0, CR.RAW_RESULT))
      FROM UT_SESSION_CHECK_RES CR
      WHERE CR.CHECK_ID = :V$CHECK_ID AND CR.CRITERIA_ID > 0 AND CR.DATE_DEL IS NULL
      INTO :V$SUM_RATE;

      IF(V$SUM_RATE IS NULL) THEN V$SUM_RATE = 0;

      -- Суммарный итог и статус этой конкретной проверки = завершена
      UPDATE UT_SESSION_CHECKS
      SET RAW_RESULT = :V$SUM_RATE, STATE_ID = 1000
      WHERE OBJ_ID = :V$CHECK_ID;

  END

  -- Обновляем статус в работе, когда все проверки работы завершились
  -- либо на третью проверку, либо в окончательную готовность

  IF(V$LEVEL_ID = 1) THEN
  BEGIN
      -- Если это первый раунд проверок, сколько проверок выполнены ? Смотрим только непосредственно переданный вопрос
      -- для бумажного варианта все вопросы проверяются синхронно, поэтому смотрим только первый
      SELECT COUNT(*)
      FROM UT_SESSION_QUESTIONS SQ
      JOIN UT_SESSION_CHECKS C ON C.QUESTION_ID = SQ.OBJ_ID AND C.DATE_DEL IS NULL AND C.STATE_ID = 1000 AND C.LEVEL_ID = 1
      WHERE SQ.OBJ_ID = :I$TASK_ID
      INTO :V$CHECKS;

      -- Все эксперты работу проверили, вычисляем баллы по критериям, переносим их в общие итоги, и закрываем вопрос
      IF(V$CHECKS >= V$C_EXPERT_NUM) THEN
      BEGIN
          V$NEW_STATE = 1000; -- по-умолчанию считаем что проверка закончилась
          V$SC = 0; -- флаг требования второй проверки

          FOR
              SELECT S.OBJ_ID
              FROM UT_SESSION_QUESTIONS SQ
              JOIN UT_SESSION_QUESTIONS S ON S.DATE_DEL IS NULL AND S.SESSION_ID = SQ.SESSION_ID
              JOIN UT_TEST_VAR_QUESTIONS TVQ ON TVQ.OBJ_ID = S.QUESTION_ID
              JOIN UT_TEST_STRUCT_POINTS TSP ON TSP.OBJ_ID = TVQ.STRUCT_POINT_ID AND TSP.Q_TYPE_ID IN (3, 8)
              WHERE SQ.OBJ_ID = :I$TASK_ID
              INTO :V$REAL_TASK_ID
          DO
          BEGIN

              V$SUM_RATE = 0;

              FOR
                  -- Отрицательные значения (не приступал) переводим в нули
                  SELECT DISTINCT CR.CRITERIA_ID, MC.OBJ_ID, MCR.OBJ_ID, MIN(IIF(CR.RAW_RESULT < 0, 0, CR.RAW_RESULT)), MAX(IIF(CR.RAW_RESULT < 0, 0, CR.RAW_RESULT)),
                      AVG(CAST(IIF(CR.RAW_RESULT < 0, 0, CR.RAW_RESULT) AS DOUBLE PRECISION)), MIN(CR.RAW_RESULT), MAX(CR.RAW_RESULT)
                  FROM UT_SESSION_CHECKS C
                  JOIN UT_SESSION_CHECK_RES CR ON CR.DATE_DEL IS NULL AND CR.CHECK_ID = C.OBJ_ID
                  -- Запись итогового результата для этого балла
                  JOIN UT_SESSION_CHECKS MC ON MC.QUESTION_ID = C.QUESTION_ID AND MC.DATE_DEL IS NULL AND MC.EXPERT_ID IS NULL
                  LEFT JOIN UT_SESSION_CHECK_RES MCR ON MCR.CHECK_ID = MC.OBJ_ID AND MCR.CRITERIA_ID = CR.CRITERIA_ID AND MCR.DATE_DEL IS NULL
                  WHERE C.DATE_DEL IS NULL AND C.QUESTION_ID = :V$REAL_TASK_ID AND C.EXPERT_ID IS NOT NULL AND C.LEVEL_ID = 1
                  GROUP BY 1, 2, 3
                  ORDER BY 1
                  INTO :V$CRITERIA, :V$FINAL_ID, :V$FINAL_RES_ID, :V$MIN, :V$MAX, :V$AVG, :V$REAL_MIN, :V$REAL_MAX
              DO
              BEGIN
                  IF(V$C_CALC_MODE = 1) THEN V$RATE = V$MIN;
                  ELSE IF(V$C_CALC_MODE = 2) THEN V$RATE = V$MAX;
                  ELSE BEGIN
                      V$RATE = TRUNC(V$AVG);
                      IF((V$AVG - CAST(V$RATE AS DOUBLE PRECISION)) >= 0.5) THEN V$RATE = V$RATE + 1;
                  END
                  V$SUM_RATE = V$SUM_RATE + V$RATE;

                  -- Если кто-то из экспертов поставил не приступал, и есть оценка больше нуля - также на перепроверку
                  IF(V$C_EXPERT_NUM > 1 AND (((V$MAX - V$MIN) >= V$C_DIFF_QUESTION) OR (V$REAL_MIN < 0 AND V$REAL_MAX > 0))) THEN V$SC = 1;

                  IF(V$FINAL_ID IS NULL) THEN
                  BEGIN
                      INSERT INTO UT_SESSION_CHECK_RES
                      (CHECK_ID, CRITERIA_ID, RAW_RESULT)
                      VALUES(:V$FINAL_ID, NULL, :V$RATE);
                  END
                  ELSE
                  BEGIN
                      UPDATE UT_SESSION_CHECK_RES
                      SET RAW_RESULT = :V$RATE
                      WHERE OBJ_ID = :V$FINAL_ID;
                  END
              END

              -- Заполняем общий итог по всем проверкам задания, но без обновления в самом задании
              SELECT RAW_RESULT FROM UT_TEST_TASK_TOTAL_RECALC(:V$REAL_TASK_ID, NULL, :V$SUM_RATE, 0) INTO :TMP;

              -- Сверяем общий результат. Пока считаем, что общее расхождение при нескольких вопросах типа C будет браться по каждому заданию
              IF(V$C_DIFF_TOTAL > 0) THEN
              BEGIN
                  SELECT MIN(C.RAW_RESULT), MAX(C.RAW_RESULT)
                  FROM UT_SESSION_CHECKS C
                  WHERE C.QUESTION_ID = :V$REAL_TASK_ID AND C.DATE_DEL IS NULL AND C.EXPERT_ID IS NOT NULL
                  INTO :V$MIN, :V$MAX;

                  IF((V$MAX - V$MIN) > V$C_DIFF_TOTAL) THEN V$SC = 1;
              END

              -- Будет вторая проверка по данному вопросу ?
              IF(V$SC <> 0) THEN V$NEW_STATE = 80;

              -- Обновляем статус вопроса и пишем туда текущий суммарный результат
              UPDATE UT_SESSION_QUESTIONS
              SET RAW_RESULT = :V$SUM_RATE
              WHERE OBJ_ID = :V$REAL_TASK_ID;

          END

      END

      -- Теперь переставляем общий статус у всех вопросов, а также у итогов по критериям
      -- только в бумажных тестированиях где все ответы на одном листе, в прочих закрываем только одно конкретное
      FOR
          SELECT S.OBJ_ID
          FROM UT_SESSION_QUESTIONS SQ
          JOIN UT_SESSION_QUESTIONS S ON S.DATE_DEL IS NULL AND S.SESSION_ID = SQ.SESSION_ID AND S.STATE_ID < :V$NEW_STATE
              AND (:V$METHOD_ID = 2 OR S.OBJ_ID = SQ.OBJ_ID)
          JOIN UT_TEST_VAR_QUESTIONS TVQ ON TVQ.OBJ_ID = S.QUESTION_ID
          JOIN UT_TEST_STRUCT_POINTS TSP ON TSP.OBJ_ID = TVQ.STRUCT_POINT_ID AND TSP.Q_TYPE_ID IN (3, 8)
          WHERE SQ.OBJ_ID = :I$TASK_ID
          INTO :V$REAL_TASK_ID
      DO
      BEGIN
          UPDATE UT_SESSION_QUESTIONS
          SET STATE_ID = :V$NEW_STATE
          WHERE OBJ_ID = :V$REAL_TASK_ID;

          UPDATE UT_SESSION_CHECKS
          SET STATE_ID = :V$NEW_STATE
          WHERE QUESTION_ID = :V$REAL_TASK_ID AND DATE_DEL IS NULL;
      END

  END
  -- При сохранении проверок уровнями выше 1-го, проверка всего одна и это - наша
  ELSE V$NEW_STATE = 1000;

  -- Все ли проверки по работе в целом завершены ? Если да, смотрим сколько заданий осталось непроверенными
  IF(V$NEW_STATE = 1000) THEN
  BEGIN
      IF(NOT EXISTS(
          SELECT FIRST 1 1
          FROM UT_SESSION_QUESTIONS
          WHERE SESSION_ID = :V$SESSION_ID AND DATE_DEL IS NULL AND STATE_ID NOT IN (1000, 1001)
      )) THEN
      BEGIN
          -- Закрываем сессию, обновляем сырой балл
          -- Итоговый результат формируем сразу или оставляем на подгонку шкал
          SELECT 1 FROM UT_TEST_SESSION_TOTAL_RECALC(:V$SESSION_ID, 100, NULL, 1) INTO :TMP;
      END
  END

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_FIND_TEST_FREE_PLACE (
    I$EXAM_ID BIGINT,
    I$PPE_ID BIGINT,
    I$ROOM_ID BIGINT,
    I$PERSON_ID BIGINT,
    I$LEVEL1 INTEGER,
    I$FLAGS INTEGER)
RETURNS (
    ROOM_ID BIGINT,
    PLACE_ID BIGINT)
AS
DECLARE VARIABLE V$CLASS_ID BIGINT;
DECLARE VARIABLE V$CLASS_TYPE_ID BIGINT;
DECLARE VARIABLE V$OU_ID BIGINT;
begin

  SELECT FIRST 1 LPG.PARENT_ID, LPG.PARENT_TYPE_ID
  FROM LINKS LPG
  WHERE LPG.OBJ_ID = :I$PERSON_ID AND LPG.PARENT_TYPE_ID IN (2, 9, 125, 157) AND LPG.DATE_DEL IS NULL
  INTO :V$CLASS_ID, :V$CLASS_TYPE_ID;

  IF(V$CLASS_TYPE_ID = 2) THEN V$OU_ID = V$CLASS_ID;
  ELSE
  BEGIN
      SELECT FIRST 1 LP2.PARENT_ID
      FROM LINKS LP8
      JOIN LINKS LP7 ON LP7.OBJ_ID = LP8.PARENT_ID AND LP7.PARENT_TYPE_ID = 7 AND LP7.DATE_DEL IS NULL
      JOIN LINKS LP2 ON LP2.OBJ_ID = LP7.PARENT_ID AND LP2.PARENT_TYPE_ID = 2 AND LP2.DATE_DEL IS NULL
      WHERE LP8.OBJ_ID = :V$CLASS_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
      INTO :V$OU_ID;
  END

  -- Внимание: если распределяем уровень коллектива в конкретное помещение, игнорируем рассадку в других помещениях
  -- Сначала пытаемся найти помещение с местами, где есть другие участники коллектива
  SELECT FIRST 1 P.ROOM_ID
  FROM LINKS LP
  JOIN UT_PERSON_PPE_ASSN PPE ON PPE.DATE_DEL IS NULL AND PPE.EXAM_ID = :I$EXAM_ID AND PPE.PERSON_ID = LP.OBJ_ID AND PPE.PPE_ID = :I$PPE_ID
  JOIN UT_PERSON_PLACE_ASSN PA ON PA.DATE_DEL IS NULL AND PA.EXAM_ID = :I$EXAM_ID AND PA.PERSON_ID = LP.OBJ_ID
  JOIN UT_PPE_PLACES P ON P.OBJ_ID = PA.PLACE_ID AND P.DATE_DEL IS NULL AND P.IS_DELETED = 0
  WHERE LP.PARENT_ID = :V$CLASS_ID AND LP.OBJ_TYPE_ID IN (10, 14, 126) AND LP.DATE_DEL IS NULL AND EXISTS (
      SELECT FIRST 1 1
      FROM UT_PPE_PLACES P2
      LEFT JOIN UT_PERSON_PLACE_ASSN PA2 ON PA2.DATE_DEL IS NULL AND PA2.EXAM_ID = :I$EXAM_ID AND PA2.PLACE_ID = P2.OBJ_ID
      WHERE P2.DATE_DEL IS NULL AND P2.ROOM_ID = P.ROOM_ID AND P2.IS_DELETED = 0 AND PA2.OBJ_ID IS NULL
  ) AND (:I$ROOM_ID IS NULL OR P.ROOM_ID = :I$ROOM_ID)
  INTO :ROOM_ID;

  -- Если не нашлось, пытаемся найти помещение с местами, где есть другие участники той же ОУ
  IF(ROOM_ID IS NULL) THEN
  BEGIN
      SELECT FIRST 1 ROOM_ID
      FROM (
          -- Сотрудники
          SELECT P.ROOM_ID
          FROM UT_PERSON_PPE_ASSN PPE
          JOIN LINKS LP2 ON LP2.OBJ_ID = PPE.PERSON_ID AND LP2.PARENT_TYPE_ID = 2 AND LP2.DATE_DEL IS NULL AND LP2.PARENT_ID = :V$OU_ID
          JOIN UT_PERSON_PLACE_ASSN PA ON PA.DATE_DEL IS NULL AND PA.EXAM_ID = :I$EXAM_ID AND PA.PERSON_ID = PPE.PERSON_ID
          JOIN UT_PPE_PLACES P ON P.OBJ_ID = PA.PLACE_ID AND P.DATE_DEL IS NULL AND P.IS_DELETED = 0
          WHERE PPE.DATE_DEL IS NULL AND PPE.EXAM_ID = :I$EXAM_ID AND PPE.PPE_ID = :I$PPE_ID
          -- Учащиеся
          UNION
          SELECT P.ROOM_ID
          FROM UT_PERSON_PPE_ASSN PPE
          JOIN LINKS LP9 ON LP9.OBJ_ID = PPE.PERSON_ID AND LP9.PARENT_TYPE_ID IN (9, 125, 187) AND LP9.DATE_DEL IS NULL
          JOIN LINKS LP8 ON LP8.OBJ_ID = LP9.PARENT_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
          JOIN LINKS LP7 ON LP7.OBJ_ID = LP8.PARENT_ID AND LP7.PARENT_TYPE_ID IN (7, 502) AND LP7.DATE_DEL IS NULL
          JOIN LINKS LP2 ON LP2.OBJ_ID = LP7.PARENT_ID AND LP2.PARENT_TYPE_ID = 2 AND LP2.DATE_DEL IS NULL AND LP2.PARENT_ID = :V$OU_ID
          JOIN UT_PERSON_PLACE_ASSN PA ON PA.DATE_DEL IS NULL AND PA.EXAM_ID = :I$EXAM_ID AND PA.PERSON_ID = PPE.PERSON_ID
          JOIN UT_PPE_PLACES P ON P.OBJ_ID = PA.PLACE_ID AND P.DATE_DEL IS NULL AND P.IS_DELETED = 0
          WHERE PPE.DATE_DEL IS NULL AND PPE.EXAM_ID = :I$EXAM_ID AND PPE.PPE_ID = :I$PPE_ID
      ) ROOMS
      WHERE EXISTS (
          SELECT FIRST 1 1
          FROM UT_PPE_PLACES P2
          LEFT JOIN UT_PERSON_PLACE_ASSN PA2 ON PA2.DATE_DEL IS NULL AND PA2.EXAM_ID = :I$EXAM_ID AND PA2.PLACE_ID = P2.OBJ_ID
          WHERE P2.DATE_DEL IS NULL AND P2.ROOM_ID = ROOMS.ROOM_ID AND P2.IS_DELETED = 0 AND PA2.OBJ_ID IS NULL
              AND (:I$ROOM_ID IS NULL OR P2.ROOM_ID = :I$ROOM_ID)
      )
      INTO :ROOM_ID;
  END

  -- Если так и не нашлось, ищем из оставшихся помещений первое попавшееся
  -- !!! проверять критерии из FLAGS !!!
  IF(ROOM_ID IS NULL) THEN
  BEGIN
      SELECT FIRST 1 R.OBJ_ID
      FROM UT_EXAM_ROOM_ASSN RA
      JOIN UT_PPE_ROOMS R ON R.DATE_DEL IS NULL AND R.OBJ_ID = RA.ROOM_ID AND R.PPE_ID = :I$PPE_ID
      WHERE RA.DATE_DEL IS NULL AND RA.EXAM_ID = :I$EXAM_ID
          AND (:I$ROOM_ID IS NULL OR R.OBJ_ID = :I$ROOM_ID)
          AND EXISTS (
              SELECT FIRST 1 1
              FROM UT_PPE_PLACES P2
              LEFT JOIN UT_PERSON_PLACE_ASSN PA2 ON PA2.DATE_DEL IS NULL AND PA2.EXAM_ID = :I$EXAM_ID AND PA2.PLACE_ID = P2.OBJ_ID
              WHERE P2.DATE_DEL IS NULL AND P2.ROOM_ID = R.OBJ_ID AND P2.IS_DELETED = 0 AND PA2.OBJ_ID IS NULL
          )
      INTO :ROOM_ID;
  END

  -- Если нашлось помещение, берем из него первое попавшееся место
  IF(ROOM_ID IS NOT NULL) THEN
  BEGIN
      SELECT FIRST 1 P.OBJ_ID
      FROM UT_PPE_PLACES P
      LEFT JOIN UT_PERSON_PLACE_ASSN PA2 ON PA2.DATE_DEL IS NULL AND PA2.EXAM_ID = :I$EXAM_ID AND PA2.PLACE_ID = P.OBJ_ID
      WHERE P.DATE_DEL IS NULL AND P.ROOM_ID = :ROOM_ID AND P.IS_DELETED = 0 AND PA2.OBJ_ID IS NULL
      ORDER BY RAND()
      INTO :PLACE_ID;
  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_FIND_TEST_FREE_PPE (
    I$EXAM_ID BIGINT,
    I$LEVEL INTEGER,
    I$OBJ_ID BIGINT,
    I$FLAGS INTEGER,
    I$PPE_ID BIGINT = null)
RETURNS (
    PPE_ID BIGINT)
AS
declare variable V$ORG_ID bigint;
declare variable V$AREA_ID bigint;
declare variable V$GROUP_ID bigint;
declare variable V$TYPE_ID bigint;
declare variable V$N integer;
declare variable V$N_MEMBERS integer;
declare variable V$N_USED integer;
declare variable V$N_DONE integer;
declare variable V$PPE_ID bigint;
declare variable V$AREA_FLAGS integer;
declare variable V$GROUP_FLAGS integer;
begin

  -- Если задан конкретный ППЭ, смотрим именно его
  -- Тут может быть конфликт, если пользователь пытается распределить группу+ в конкретный ППЭ, когда группа уже размещена в другом

  V$GROUP_FLAGS = BIN_AND(I$FLAGS, 3);
  V$AREA_FLAGS = BIN_AND(BIN_SHR(I$FLAGS, 2), 3);

  IF(I$LEVEL = 3) THEN
  BEGIN

      -- Группа. Сколько осталось нераспределенных участников, и сколько уже распределили ?
      SELECT COUNT(*)
      FROM LINKS LS
      JOIN UT_EXAM_PERSON_ASSN PA ON PA.EXAM_ID = :I$EXAM_ID AND PA.PERSON_ID = LS.OBJ_ID AND PA.DATE_DEL IS NULL
      LEFT JOIN UT_PERSON_PPE_ASSN A ON A.EXAM_ID = :I$EXAM_ID AND A.PERSON_ID = LS.OBJ_ID AND A.DATE_DEL IS NULL
      WHERE LS.PARENT_ID = :I$OBJ_ID AND LS.OBJ_TYPE_ID IN (10, 14, 126) AND LS.DATE_DEL IS NULL AND A.OBJ_ID IS NULL
      INTO :V$N_MEMBERS;

      SELECT COUNT(*)
      FROM LINKS LS
      JOIN UT_EXAM_PERSON_ASSN PA ON PA.EXAM_ID = :I$EXAM_ID AND PA.PERSON_ID = LS.OBJ_ID AND PA.DATE_DEL IS NULL
      JOIN UT_PERSON_PPE_ASSN A ON A.EXAM_ID = :I$EXAM_ID AND A.PERSON_ID = LS.OBJ_ID AND A.DATE_DEL IS NULL
      WHERE LS.PARENT_ID = :I$OBJ_ID AND LS.OBJ_TYPE_ID IN (10, 14, 126) AND LS.DATE_DEL IS NULL
      INTO :V$N_DONE;

      FOR
          SELECT DISTINCT A.PPE_ID, P.N_PLACES
          FROM LINKS LS
          JOIN UT_PERSON_PPE_ASSN A ON A.EXAM_ID = :I$EXAM_ID AND A.PERSON_ID = LS.OBJ_ID AND A.DATE_DEL IS NULL
          JOIN UT_PPE P ON P.OBJ_ID = A.PPE_ID AND P.DATE_DEL IS NULL AND (:I$PPE_ID IS NULL OR P.OBJ_ID = :I$PPE_ID)
          JOIN UT_EXAM_PPE_ASSN PA ON PA.PPE_ID = P.OBJ_ID AND PA.EXAM_ID = :I$EXAM_ID AND PA.DATE_DEL IS NULL
          WHERE LS.PARENT_ID = :I$OBJ_ID AND LS.OBJ_TYPE_ID IN (10, 14, 126) AND LS.DATE_DEL IS NULL
          INTO :V$PPE_ID, :V$N
      DO
      BEGIN
          -- Сколько мест осталось. Если есть места в нужном количестве, размещаем именно в этот ППЭ
          SELECT COUNT(*)
          FROM UT_PERSON_PPE_ASSN A
          WHERE A.EXAM_ID = :I$EXAM_ID AND A.PPE_ID = :V$PPE_ID AND A.DATE_DEL IS NULL
          INTO :V$N_USED;

          IF((V$N_USED + V$N_MEMBERS) <= V$N) THEN
          BEGIN
              PPE_ID = V$PPE_ID;
              BREAK;
          END
      END

      -- Дальше ищем если: распределяем эту группу с нуля, либо мест где уже посажены другие учащиеся не нашлось, но флаги допускают распределение в разные ППЭ
      IF(V$N_DONE = 0 OR (PPE_ID IS NULL AND V$GROUP_FLAGS <> 0)) THEN
      BEGIN
          FOR
              SELECT P.OBJ_ID, P.N_PLACES
              FROM UT_PPE P
              JOIN UT_EXAM_PPE_ASSN PA ON PA.PPE_ID = P.OBJ_ID AND PA.EXAM_ID = :I$EXAM_ID AND PA.DATE_DEL IS NULL
              WHERE P.DATE_DEL IS NULL AND ((:V$AREA_FLAGS = 0 AND P.AREA_ID = :V$AREA_ID) OR (:V$AREA_FLAGS = 1 AND P.AREA_ID <> :V$AREA_ID) OR (:V$AREA_FLAGS >= 2))
                  AND (:I$PPE_ID IS NULL OR P.OBJ_ID = :I$PPE_ID)
              INTO :V$PPE_ID, :V$N
          DO
          BEGIN
              SELECT COUNT(*)
              FROM UT_PERSON_PPE_ASSN A
              WHERE A.EXAM_ID = :I$EXAM_ID AND A.PPE_ID = :V$PPE_ID AND A.DATE_DEL IS NULL
              INTO :V$N_USED;

              IF((V$N_USED + V$N_MEMBERS) <= V$N) THEN
              BEGIN
                  PPE_ID = V$PPE_ID;
                  BREAK;
              END
          END
      END

  END
  ELSE IF(I$LEVEL = 4) THEN
  BEGIN

      -- Индивидуальный участник. Сначала пытаемся распределить туда же, куда и остальной класс (если распределен в несколько ППЭ, то смотрим по очереди)
      SELECT FIRST 1 LPG.PARENT_ID, LPG.PARENT_TYPE_ID
      FROM LINKS LPG
      WHERE LPG.OBJ_ID = :I$OBJ_ID AND LPG.PARENT_TYPE_ID IN (2, 9, 125, 187) AND LPG.DATE_DEL IS NULL
      INTO :V$GROUP_ID, :V$TYPE_ID;

      IF(V$TYPE_ID = 2) THEN V$ORG_ID = V$GROUP_ID;
      ELSE
      BEGIN
          SELECT FIRST 1 LP2.PARENT_ID
          FROM LINKS LP8
          JOIN LINKS LP7 ON LP7.OBJ_ID = LP8.PARENT_ID AND LP7.PARENT_TYPE_ID = 7 AND LP7.DATE_DEL IS NULL
          JOIN LINKS LP2 ON LP2.OBJ_ID = LP7.PARENT_ID AND LP2.PARENT_TYPE_ID = 2 AND LP2.DATE_DEL IS NULL
          WHERE LP8.OBJ_ID = :V$GROUP_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
          INTO :V$ORG_ID;
      END

      SELECT V2163.LISTVAL_ID
      FROM VALL V2163
      WHERE V2163.OBJ_ID = :V$ORG_ID AND V2163.PARAM_ID = 2163 AND V2163.IS_DEL = 0
      INTO :V$AREA_ID;

      FOR
          SELECT DISTINCT A.PPE_ID, P.N_PLACES
          FROM LINKS LP
          JOIN UT_PERSON_PPE_ASSN A ON A.EXAM_ID = :I$EXAM_ID AND A.PERSON_ID = LP.OBJ_ID AND A.DATE_DEL IS NULL
          JOIN UT_PPE P ON P.OBJ_ID = A.PPE_ID AND P.DATE_DEL IS NULL AND (:I$PPE_ID IS NULL OR P.OBJ_ID = :I$PPE_ID)
          JOIN UT_EXAM_PPE_ASSN PA ON PA.PPE_ID = P.OBJ_ID AND PA.EXAM_ID = :I$EXAM_ID AND PA.DATE_DEL IS NULL
          WHERE LP.PARENT_ID = :V$GROUP_ID AND LP.OBJ_TYPE_ID IN (10, 14, 126) AND LP.DATE_DEL IS NULL
          INTO :V$PPE_ID, :V$N
      DO
      BEGIN
          -- Сколько мест осталось. Если есть места, размещаем именно в этот ППЭ
          SELECT COUNT(*)
          FROM UT_PERSON_PPE_ASSN A
          WHERE A.EXAM_ID = :I$EXAM_ID AND A.PPE_ID = :V$PPE_ID AND A.DATE_DEL IS NULL
          INTO :V$N_USED;

          IF(V$N_USED < V$N) THEN
          BEGIN
              PPE_ID = V$PPE_ID;
              BREAK;
          END
      END

      -- Если ППЭ так и не назначен, смотрим полный список в соответствии с заданными критериями по району
      IF(PPE_ID IS NULL) THEN
      BEGIN

          FOR
              SELECT P.OBJ_ID, P.N_PLACES
              FROM UT_PPE P
              JOIN UT_EXAM_PPE_ASSN PA ON PA.PPE_ID = P.OBJ_ID AND PA.EXAM_ID = :I$EXAM_ID AND PA.DATE_DEL IS NULL
              WHERE P.DATE_DEL IS NULL AND ((:V$AREA_FLAGS = 0 AND P.AREA_ID = :V$AREA_ID) OR (:V$AREA_FLAGS = 1 AND P.AREA_ID <> :V$AREA_ID) OR (:V$AREA_FLAGS >= 2))
                  AND (:I$PPE_ID IS NULL OR P.OBJ_ID = :I$PPE_ID)
              INTO :V$PPE_ID, :V$N
          DO
          BEGIN
              SELECT COUNT(*)
              FROM UT_PERSON_PPE_ASSN A
              WHERE A.EXAM_ID = :I$EXAM_ID AND A.PPE_ID = :V$PPE_ID AND A.DATE_DEL IS NULL
              INTO :V$N_USED;

              IF(V$N_USED < V$N) THEN
              BEGIN
                  PPE_ID = V$PPE_ID;
                  BREAK;
              END
          END

      END

  END
  ELSE EXCEPTION DATA_ERROR 'Поиск вариантов размещения допускается только для индивидуальных участников и коллективов';

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_GET_STRUCTURE_BY_ID (
    I$ID BIGINT)
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(4000))
AS
declare variable V$ID bigint;
declare variable V$INDEX integer;
declare variable V$TYPE_ID smallint;
declare variable V$NAME varchar(100);
declare variable V$NAME_SHORT char(1);
declare variable V$SCORE smallint;
declare variable V$LEVEL smallint;
declare variable V$CHARSET smallint;
declare variable V$CHARSET_NAME varchar(100);
begin

  -- Описание позиций структуры
  TAG_NAME = 'structs';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'structs::json&colon;array';
  VAL = 1;
  SUSPEND;

  FOR
    SELECT TSP.OBJ_ID, TSP.Q_ORDER, TSP.Q_TYPE_ID, QT.OBJ_NAME, QT.OBJ_VALUE, TSP.Q_MAX_SCORE, TSP.Q_LEVEL, TSP.CHARSET_ID, C.OBJ_NAME
    FROM UT_TEST_STRUCT_POINTS TSP
    JOIN UT_QUESTION_TYPE QT ON QT.OBJ_ID = TSP.Q_TYPE_ID
    LEFT JOIN UT_CHARSETS C ON C.OBJ_ID = TSP.CHARSET_ID
    WHERE TSP.STRUCT_ID = :I$ID AND TSP.DATE_DEL IS NULL
    ORDER BY 2
    INTO :V$ID, :V$INDEX, :V$TYPE_ID, :V$NAME, :V$NAME_SHORT, :V$SCORE, :V$LEVEL, :V$CHARSET, :V$CHARSET_NAME
  DO
  BEGIN
    
    TAG_NAME = 'structs:s';
    VAL = NULL;
    SUSPEND;

    TAG_NAME = 'structs:s:id';
    VAL = V$ID;
    SUSPEND;

    TAG_NAME = 'structs:s:index';
    VAL = V$INDEX;
    SUSPEND;

    TAG_NAME = 'structs:s:type_id';
    VAL = V$TYPE_ID;
    SUSPEND;

    TAG_NAME = 'structs:s:type_value';
    VAL = V$NAME_SHORT;
    SUSPEND;

    TAG_NAME = 'structs:s:type_name';
    VAL = V$NAME;
    SUSPEND;

    TAG_NAME = 'structs:s:level';
    VAL = V$LEVEL;
    SUSPEND;

    TAG_NAME = 'structs:s:max_score';
    VAL = V$SCORE;
    SUSPEND;

    TAG_NAME = 'structs:s:charset_id';
    VAL = V$CHARSET;
    SUSPEND;

    TAG_NAME = 'structs:s:charset';
    VAL = V$CHARSET_NAME;
    SUSPEND;

    TAG_NAME = 'structs:s:questions';
    VAL = NULL;
    SUSPEND;

    TAG_NAME = 'structs:s:questions::json&colon;array';
    VAL = 1;
    SUSPEND;

  END
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_GIA_PRINT_CONFIRM (
    I$GRADE_ID BIGINT,
    I$USER_ID VARCHAR(40))
AS
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$YEAR_ID BIGINT;
DECLARE VARIABLE V$EXAM_FOLDER BIGINT;
DECLARE VARIABLE V$F1 SMALLINT;
DECLARE VARIABLE V$F2 SMALLINT;
begin

  -- Какой сейчас учебный год ?
  SELECT FIRST 1 V1236.LISTVAL_ID
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$YEAR_ID;

  SELECT FIRST 1 L119.OBJ_ID
  FROM LINKS L119
  JOIN VALL V742 ON V742.OBJ_ID = L119.OBJ_ID AND V742.PARAM_ID = 742 AND V742.IS_DEL = 0 AND V742.LISTVAL_ID = :V$YEAR_ID
  WHERE L119.PARENT_ID = 3866 AND L119.OBJ_TYPE_ID = 119 AND L119.DATE_DEL IS NULL
  INTO :V$EXAM_FOLDER;

  IF(V$EXAM_FOLDER IS NULL) THEN EXCEPTION DATA_ERROR 'Не загружены экзамены текущего учебного года';

  FOR
    SELECT L10.OBJ_ID
    FROM LINKS L10
    WHERE L10.PARENT_ID = :I$GRADE_ID AND L10.OBJ_TYPE_ID IN (10, 126) AND L10.DATE_DEL IS NULL
    INTO :V$OBJ_ID
  DO
  BEGIN
    -- Выставляем флаг только там, где вообще все экзамены без флага
    -- в том числе удаленные
    -- Если есть хотя бы один, где флаг уже стоит - заявление навсегда становится повторным
    V$F1 = 0;
    V$F2 = 0;
    SELECT FIRST 1 1
    FROM LINKS L120
    JOIN LINKS LP119 ON LP119.OBJ_ID = L120.OBJ_ID AND LP119.PARENT_ID = :V$EXAM_FOLDER
    WHERE L120.PARENT_ID = :V$OBJ_ID AND L120.OBJ_TYPE_ID = 120 AND L120.LISTVAL_ID IS NULL
    INTO :V$F1;

    SELECT FIRST 1 1
    FROM LINKS L120
    JOIN LINKS LP119 ON LP119.OBJ_ID = L120.OBJ_ID AND LP119.PARENT_ID = :V$EXAM_FOLDER
    WHERE L120.PARENT_ID = :V$OBJ_ID AND L120.OBJ_TYPE_ID = 120 AND L120.LISTVAL_ID IS NOT NULL
    INTO :V$F2;

    IF(V$F1 = 1 AND V$F2 = 0) THEN
    BEGIN
      UPDATE LINKS L120
      SET L120.LISTVAL_ID = 0
      WHERE L120.PARENT_ID = :V$OBJ_ID AND L120.OBJ_TYPE_ID = 120 AND L120.LISTVAL_ID IS NULL
      AND EXISTS (
        SELECT FIRST 1 1
        FROM LINKS LP119
        WHERE LP119.OBJ_ID = L120.OBJ_ID AND LP119.PARENT_ID = :V$EXAM_FOLDER
      );
    END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_KIM_CDLEVEL_SYNC (
    I$CODING_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$PARENT_ID BIGINT,
    I$OBJ_NAME VARCHAR(400),
    I$N_LEVEL INTEGER,
    I$SORT_ORDER INTEGER)
RETURNS (
    OBJ_ID BIGINT)
AS
DECLARE VARIABLE V$PARENT_ID BIGINT;
DECLARE VARIABLE V$OBJ_NAME VARCHAR(400);
DECLARE VARIABLE V$SORT_ORDER INTEGER;
DECLARE VARIABLE V$OLD_PARENT BIGINT;
begin

  IF(I$PARENT_ID IS NOT NULL) THEN
  BEGIN
    SELECT FIRST 1 CL.OBJ_ID
    FROM UT_KIM_CODING_LEVELS CL
    WHERE CL.CODING_ID = :I$CODING_ID AND CL.REF_ID = :I$PARENT_ID
    INTO :V$PARENT_ID;

    IF(V$PARENT_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Запись родительского уровня не найдена для ' || I$PARENT_ID || ' и дочерней строки ' || I$OBJ_ID;
  END

  SELECT FIRST 1 CL.OBJ_ID, CL.OBJ_NAME, CL.SORT_ORDER, CL.PARENT_ID
  FROM UT_KIM_CODING_LEVELS CL
  WHERE CL.CODING_ID = :I$CODING_ID AND CL.REF_ID = :I$OBJ_ID
  INTO :OBJ_ID, :V$OBJ_NAME, :V$SORT_ORDER, :V$OLD_PARENT;

  IF(OBJ_ID IS NULL) THEN
  BEGIN
    INSERT INTO UT_KIM_CODING_LEVELS
    (OBJ_ID, REF_ID, CODING_ID, PARENT_ID, OBJ_NAME, N_LEVEL, SORT_ORDER)
    VALUES (:I$OBJ_ID, :I$OBJ_ID, :I$CODING_ID, :V$PARENT_ID, :I$OBJ_NAME, :I$N_LEVEL, :I$SORT_ORDER)
    RETURNING OBJ_ID INTO :OBJ_ID;
  END
  ELSE IF(I$OBJ_NAME <> V$OBJ_NAME OR I$SORT_ORDER <> V$SORT_ORDER OR COALESCE(V$PARENT_ID, 0) <> COALESCE(V$OLD_PARENT, 0)) THEN
  BEGIN
    UPDATE UT_KIM_CODING_LEVELS
    SET OBJ_NAME = :I$OBJ_NAME, PARENT_ID = :V$PARENT_ID, N_LEVEL = :I$N_LEVEL, SORT_ORDER = :I$SORT_ORDER
    WHERE OBJ_ID = :OBJ_ID;
  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_KIM_CODING_CNT (
    I$OBJ_ID BIGINT)
RETURNS (
    MAX_LEVEL INTEGER,
    MIN_QUESTIONS INTEGER)
AS
declare variable V$LEVEL_ID bigint;
declare variable V$T_LEVEL integer;
declare variable V$T_QUESTIONS integer;
begin

  -- Возвращаем максимальный уровень уровня и минимальный уровень, на котором есть вопросы
  MAX_LEVEL = -1;
  MIN_QUESTIONS = 9999;

  FOR
      SELECT CL.OBJ_ID
      FROM UT_KIM_CODING_LEVELS CL
      WHERE ((CL.CODING_ID = :I$OBJ_ID AND CL.PARENT_ID IS NULL) OR CL.PARENT_ID = :I$OBJ_ID) AND CL.DATE_DEL IS NULL
      INTO :V$LEVEL_ID
  DO
  BEGIN

      -- Уже +1 уровень, раз есть раздел
      MAX_LEVEL = 0;

      SELECT MAX_LEVEL, MIN_QUESTIONS
      FROM UT_KIM_CODING_CNT(:V$LEVEL_ID)
      INTO :V$T_LEVEL, :V$T_QUESTIONS;

      IF(V$T_LEVEL + 1 > MAX_LEVEL) THEN MAX_LEVEL = V$T_LEVEL + 1;
      IF(V$T_QUESTIONS + 1 < MIN_QUESTIONS) THEN MIN_QUESTIONS = V$T_QUESTIONS + 1;

  END

  -- В дочерних разделах вопросов нет. Если есть вопросы прямо тут, возвращаем уровень 0
  IF(MIN_QUESTIONS = 9999) THEN
  BEGIN
      SELECT FIRST 1 0
      FROM UT_QUESTIONS
      WHERE SECTION_ID = :I$OBJ_ID AND DATE_DEL IS NULL
      INTO :MIN_QUESTIONS;
  END

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_KIM_CODING_DELETE (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    ERROR_TEXT VARCHAR(200))
AS
declare variable V$T_DATE_DEL timestamp;
declare variable V$T_OBJ_ID bigint;
declare variable V$GEN bigint;
declare variable V$MULTIPLIER bigint;
declare variable V$USER_ID bigint;
declare variable N integer;
begin

  SELECT D.DATE_DEL, D.OBJ_ID
  FROM UT_KIM_CODING D
  WHERE D.OBJ_ID = :I$OBJ_ID
  INTO :V$T_DATE_DEL, :V$T_OBJ_ID;

  IF (V$T_OBJ_ID IS NULL) THEN
  BEGIN
      ERROR_TEXT = 'Кодификатор не найден';
      SUSPEND;
  END
  ELSE IF(V$T_DATE_DEL IS NOT NULL) THEN
  BEGIN
      ERROR_TEXT = 'Нельзя повторно удалить кодификатор';
      SUSPEND;
  END

  -- Проверяем уровень доступа пользователя
  IF(I$USER_ID = 'Веб-администратор') THEN V$USER_ID = 0; ELSE V$USER_ID = CAST(I$USER_ID AS BIGINT);

  SELECT GEN, MULTIPLIER
  FROM GEN
  INTO :V$GEN, :V$MULTIPLIER;

  N = I$OBJ_ID / V$MULTIPLIER;
  IF(N <> V$GEN) THEN EXCEPTION DATA_ERROR 'Нельзя удалить кодификатор, созданный в другой организации/уровне';
  
  -- Проверяем наличие вопросов в кодификаторе - если вопросы остались, удалять нельзя
  N = 0;
  SELECT FIRST 1 1
  FROM UT_KIM_CODING_LEVELS CL
  JOIN UT_QUESTIONS Q ON Q.SECTION_ID = CL.OBJ_ID AND Q.DATE_DEL IS NULL
  WHERE CL.DATE_DEL IS NULL AND CL.CODING_ID = :I$OBJ_ID
  INTO :N;

  IF(N > 0) THEN EXCEPTION DATA_ERROR 'В кодификаторе остались вопросы, удалить кодификатор нельзя';

  UPDATE UT_KIM_CODING
  SET DATE_DEL = CURRENT_TIMESTAMP
  WHERE OBJ_ID = :I$OBJ_ID;

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_KIM_CODING_EVENT_SET (
    I$CODING_ID BIGINT,
    I$PARENT_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$STATE SMALLINT,
    I$OBJ_NAME VARCHAR(1000),
    I$ORDER INTEGER)
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$LEVEL integer;
declare variable V$PARENT_CID bigint;
declare variable N1 integer;
declare variable N2 integer;
declare variable NQ integer;
declare variable V$CODING_ID bigint;
begin

  IF(I$OBJ_ID IS NULL) THEN
  BEGIN

      IF(I$STATE <> 1) THEN EXCEPTION DATA_ERROR 'Для нового раздела возможно только добавление';

      -- На каком уровне добавляем ?
      V$LEVEL = 0;
      IF(I$PARENT_ID IS NOT NULL) THEN
      BEGIN
          SELECT CODING_ID, N_LEVEL + 1
          FROM UT_KIM_CODING_LEVELS
          WHERE OBJ_ID = :I$PARENT_ID AND DATE_DEL IS NULL
          INTO :V$PARENT_CID, :V$LEVEL;

          IF(V$PARENT_CID <> I$CODING_ID) THEN EXCEPTION DATA_ERROR 'Родительский уровень кодификатора относится к чужому кодификатору';
      END

      INSERT INTO UT_KIM_CODING_LEVELS
      (CODING_ID, PARENT_ID, OBJ_NAME, SORT_ORDER, N_LEVEL)
      VALUES (:I$CODING_ID, :I$PARENT_ID, :I$OBJ_NAME, :I$ORDER, :V$LEVEL)
      RETURNING OBJ_ID
      INTO :OBJ_ID;

  END
  ELSE IF(I$STATE = 1) THEN
  BEGIN

      -- Проверяем, что при наличии вопросов уровень не поменялся
      SELECT L.N_LEVEL, L.CODING_ID
      FROM UT_KIM_CODING_LEVELS L
      WHERE L.OBJ_ID = :I$OBJ_ID AND L.DATE_DEL IS NULL
      INTO :N1, :V$CODING_ID;

      SELECT L.N_LEVEL
      FROM UT_KIM_CODING_LEVELS L
      WHERE L.OBJ_ID = :I$PARENT_ID AND L.DATE_DEL IS NULL
      INTO :N2;

      SELECT COUNT(*)
      FROM UT_QUESTIONS Q
      WHERE Q.DATE_DEL IS NULL AND Q.SECTION_ID = :I$OBJ_ID
      INTO :NQ;

      --  у строк 1го уровня в кодификаторе parent_id пустой
      IF(N1 IS NULL OR (N2 IS NULL AND I$PARENT_ID IS NOT NULL)) THEN EXCEPTION DATA_ERROR 'Не найден один из узлов в структуре дерева';
      IF(NQ > 0 AND N1 <> N2 + 1) THEN EXCEPTION DATA_ERROR 'Нельзя перемещать узел с уже созданными вопросами в другое место дерева';
      IF(V$CODING_ID <> I$CODING_ID) THEN EXCEPTION DATA_ERROR 'Нельзя перемещать разделы в другой кодификатор';

      -- Обновление, включая родителя
      UPDATE UT_KIM_CODING_LEVELS
      SET OBJ_NAME = :I$OBJ_NAME, SORT_ORDER = :I$ORDER, PARENT_ID = :I$PARENT_ID, DATE_MODIFY = CURRENT_TIMESTAMP
      WHERE OBJ_ID = :I$OBJ_ID;

      OBJ_ID = I$OBJ_ID;

  END
  ELSE IF(I$STATE = 2) THEN
  BEGIN

      -- Удаление. Не осталось ли висячих вопросов или разделов ?
      IF(EXISTS(
          SELECT FIRST 1 1
          FROM UT_KIM_CODING_LEVELS
          WHERE DATE_DEL IS NULL AND PARENT_ID = :I$OBJ_ID
      )) THEN EXCEPTION DATA_ERROR 'Нельзя удалить раздел кодификатора, в котором остались вложенные разделы';

      IF(EXISTS(
          SELECT FIRST 1 1
          FROM UT_QUESTIONS
          WHERE DATE_DEL IS NULL AND SECTION_ID = :I$OBJ_ID
      )) THEN EXCEPTION DATA_ERROR 'Нельзя удалить раздел кодификатора, в котором остались вопросы';

      UPDATE UT_KIM_CODING_LEVELS
      SET DATE_DEL = CURRENT_TIMESTAMP
      WHERE OBJ_ID = :I$OBJ_ID AND DATE_DEL IS NULL;

      OBJ_ID = NULL;

  END
  ELSE OBJ_ID = I$OBJ_ID;

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_KIM_CODING_GET (
    I$OBJ_ID BIGINT = NULL,
    I$DETAILS SMALLINT = 0)
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(4000))
AS
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$NAME VARCHAR(1000);
DECLARE VARIABLE V$N_LEVELS INTEGER;
DECLARE VARIABLE V$TEMP_ID BIGINT;
DECLARE VARIABLE V$OWNER_LEVEL SMALLINT;
DECLARE VARIABLE V$OWNER_ID BIGINT;
DECLARE VARIABLE V$GEN BIGINT;
DECLARE VARIABLE V$MULTIPLIER BIGINT;
DECLARE VARIABLE N INTEGER;
DECLARE VARIABLE V$TEST_ID BIGINT;
DECLARE VARIABLE V$PARENT_ID BIGINT;
DECLARE VARIABLE S VARCHAR(300);
DECLARE VARIABLE V$OBJ_ID_Q BIGINT;
DECLARE VARIABLE V$NAME_Q VARCHAR(1000);
DECLARE VARIABLE V$SCORE_Q INTEGER;
DECLARE VARIABLE V$LEVEL_Q INTEGER;
DECLARE VARIABLE V$ORDER_Q INTEGER;
DECLARE VARIABLE V$CHARSET_Q SMALLINT;
DECLARE VARIABLE V$CHARSET_NAME_Q VARCHAR(100);
DECLARE VARIABLE V$TYPE_Q VARCHAR(10);
begin

  SELECT FIRST 1 KC.OBJ_ID, KC.OBJ_NAME, KC.N_LEVELS, KC.OWNER_LEVEL, KC.OWNER_ID
  FROM UT_KIM_CODING KC
  WHERE KC.DATE_DEL IS NULL AND KC.OBJ_ID = :I$OBJ_ID
  INTO :V$OBJ_ID, :V$NAME, :V$N_LEVELS, :V$OWNER_LEVEL, :V$OWNER_ID;

  IF(I$OBJ_ID IS NOT NULL AND V$OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Кодификатор не найден или был удален';

  TAG_NAME = 'obj_id';
  VAL = V$OBJ_ID;
  SUSPEND;

  TAG_NAME = 'obj_name';
  VAL = V$NAME;
  SUSPEND;

  TAG_NAME = 'n_levels';
  VAL = V$N_LEVELS;
  SUSPEND;

  -- Данные о владельце кодификатора и права доступа

  TAG_NAME = 'owner_level';
  VAL = V$OWNER_LEVEL;
  SUSPEND;

  TAG_NAME = 'owner_id';
  VAL = V$OWNER_ID;
  SUSPEND;

  TAG_NAME = 'test_id';
  VAL = NULL;
  SUSPEND;

  TAG_NAME = 'test_name';
  VAL = NULL;
  SUSPEND;

  SELECT GEN, MULTIPLIER
  FROM GEN
  INTO :V$GEN, :V$MULTIPLIER;

  N = I$OBJ_ID / V$MULTIPLIER;
  TAG_NAME = 'allowed';
  VAL = 0;
  IF(I$OBJ_ID IS NULL OR N = V$GEN) THEN VAL = 1;
  SUSPEND;

  -- Сколько максимально уровней уже занято (рекурсивно) ?
  TAG_NAME = 'used_levels';
  VAL = (SELECT N FROM UT_KIM_CODING_SUB_CNT(:I$OBJ_ID));
  SUSPEND;

  -- Список предметов
  TAG_NAME = 'subject_id';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'subject_id:selection';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'subject_id:selection::json&colon;array';
  VAL = 1;
  SUSPEND;
  TAG_NAME = 'subject_id:selection:r';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'subject_id:selection:r:id';
  VAL = '*';
  SUSPEND;
  TAG_NAME = 'subject_id:selection:r:value';
  VAL = 'Метапредмет';
  SUSPEND;
  FOR
    SELECT OBJ_ID, OBJ_NAME
    FROM UT_SUBJECTS
    WHERE DATE_DEL IS NULL
    ORDER BY 2
    INTO :V$TEMP_ID, :V$NAME
  DO
  BEGIN
    TAG_NAME = 'subject_id:selection:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'subject_id:selection:r:id';
    VAL = V$TEMP_ID;
    SUSPEND;
    TAG_NAME = 'subject_id:selection:r:value';
    VAL = V$NAME;
    SUSPEND;
  END
  TAG_NAME = 'subject_id:values::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT SUBJECT_ID
    FROM UT_KIM_CODING_SUBJECTS
    WHERE DATE_DEL IS NULL AND CODING_ID = :V$OBJ_ID
    INTO :V$TEMP_ID
  DO
  BEGIN
    TAG_NAME = 'subject_id:values:v';
    VAL = IIF(V$TEMP_ID IS NULL, '*', V$TEMP_ID);
    SUSPEND;
  END

  -- Список этапов
  TAG_NAME = 'stage_id';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'stage_id:selection';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'stage_id:selection::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
    SELECT OBJ_ID, OBJ_NAME
    FROM UT_EXAM_STAGES
    ORDER BY SORT_INDEX
    INTO :V$TEMP_ID, :V$NAME
  DO
  BEGIN
    TAG_NAME = 'stage_id:selection:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'stage_id:selection:r:id';
    VAL = V$TEMP_ID;
    SUSPEND;
    TAG_NAME = 'stage_id:selection:r:value';
    VAL = V$NAME;
    SUSPEND;
  END
  TAG_NAME = 'stage_id:values::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT STAGE_ID
    FROM UT_KIM_CODING_STAGES
    WHERE DATE_DEL IS NULL AND CODING_ID = :V$OBJ_ID
    INTO :V$TEMP_ID
  DO
  BEGIN
    TAG_NAME = 'stage_id:values:r';
    VAL = V$TEMP_ID;
    SUSPEND;
  END

  -- Новый формат работы с кодификатором
  -- Сразу отдаем все данные по содержимому
  TAG_NAME = 'items::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L.OBJ_ID, L.PARENT_ID, L.OBJ_NAME, L.SORT_ORDER
    FROM UT_KIM_CODING_LEVELS L
    WHERE L.DATE_DEL IS NULL AND L.CODING_ID = :I$OBJ_ID
    ORDER BY L.N_LEVEL, L.SORT_ORDER
    INTO :V$OBJ_ID, :V$PARENT_ID, :S, :N
  DO
  BEGIN
    TAG_NAME = 'items:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'items:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'items:r:parent_id';
    VAL = V$PARENT_ID;
    SUSPEND;
    TAG_NAME = 'items:r:name';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'items:r:sort_order';
    VAL = N;
    SUSPEND;
    TAG_NAME = 'items:r:n_questions';
    SELECT COUNT(*)
    FROM UT_QUESTIONS Q
    WHERE Q.SECTION_ID = :V$OBJ_ID AND Q.DATE_DEL IS NULL
    INTO :VAL;
    SUSPEND;

    -- добавил в выдачу вопросы (для поиска по дереву)
    IF(I$DETAILS <> 0) THEN
    BEGIN
      TAG_NAME = 'items:r:questions::json&colon;array';
      VAL = 1;
      SUSPEND;
      FOR
        SELECT T.OBJ_ID, T.OBJ_NAME, QT.OBJ_VALUE, T.MAX_SCORE, T.Q_LEVEL, T.SORT_ORDER, C.OBJ_ID, C.OBJ_NAME
        FROM UT_QUESTIONS T
        JOIN UT_QUESTION_TYPE QT ON QT.OBJ_ID = T.QUESTION_TYPE
        LEFT JOIN UT_CHARSETS C ON C.OBJ_ID = T.CHARSET_ID
        WHERE T.DATE_DEL IS NULL AND T.SECTION_ID = :V$OBJ_ID
        ORDER BY T.SORT_ORDER
        INTO :V$OBJ_ID_Q, :V$NAME_Q, :V$TYPE_Q, :V$SCORE_Q, :V$LEVEL_Q, :V$ORDER_Q, :V$CHARSET_Q, :V$CHARSET_NAME_Q
      DO
      BEGIN
        TAG_NAME = 'items:r:questions:t';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'items:r:questions:t:id';
        VAL = V$OBJ_ID_Q;
        SUSPEND;
        TAG_NAME = 'items:r:questions:t:name';
        VAL = V$NAME_Q;
        SUSPEND;
        TAG_NAME = 'items:r:questions:t:type';
        VAL = V$TYPE_Q;
        SUSPEND;
        TAG_NAME = 'items:r:questions:t:level';
        VAL = V$LEVEL_Q;
        SUSPEND;
        TAG_NAME = 'items:r:questions:t:score';
        VAL = V$SCORE_Q;
        SUSPEND;
        TAG_NAME = 'items:r:questions:t:order';
        VAL = V$ORDER_Q;
        SUSPEND;
        TAG_NAME = 'items:r:questions:t:charset_id';
        VAL = V$CHARSET_Q;
        SUSPEND;
        TAG_NAME = 'items:r:questions:t:charset';
        VAL = V$CHARSET_NAME_Q;
        SUSPEND;
      END
    END

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_KIM_CODING_LEVELS_LIST (
    I$PARENT_ID BIGINT,
    I$OBJ_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    CODING_ID BIGINT,
    PARENT_ID BIGINT,
    CODING_LEVEL_NAME VARCHAR(200),
    N_LEVEL SMALLINT,
    SORT_ORDER SMALLINT,
    N_CHILDREN INTEGER,
    N_QUESTIONS INTEGER,
    ALLOWED SMALLINT)
AS
declare variable V$GEN bigint;
declare variable V$MULTIPLIER bigint;
declare variable N integer;
begin

  -- Глобальные права доступа
  SELECT GEN, MULTIPLIER
  FROM GEN
  INTO :V$GEN, :V$MULTIPLIER;

  FOR
      SELECT KCL.OBJ_ID, KCL.CODING_ID, KCL.PARENT_ID, KCL.OBJ_NAME, KCL.N_LEVEL, KCL.SORT_ORDER
      FROM UT_KIM_CODING_LEVELS KCL
      WHERE KCL.DATE_DEL IS NULL
          AND ((KCL.PARENT_ID is null and KCL.CODING_ID = :I$PARENT_ID) OR (KCL.PARENT_ID = :I$PARENT_ID))
          AND (:I$OBJ_ID IS NULL OR KCL.obj_id = :I$OBJ_ID)
      ORDER BY KCL.SORT_ORDER
      INTO :OBJ_ID, :CODING_ID, :PARENT_ID, :CODING_LEVEL_NAME, :N_LEVEL, :SORT_ORDER
  DO
  BEGIN

      SELECT COUNT(*)
      FROM UT_KIM_CODING_LEVELS KCL
      WHERE KCL.PARENT_ID = :OBJ_ID AND KCL.DATE_DEL IS NULL
      INTO :N_CHILDREN;

      SELECT COUNT(*)
      FROM UT_QUESTIONS Q
      WHERE Q.SECTION_ID = :OBJ_ID AND Q.DATE_DEL IS NULL
      INTO :N_QUESTIONS;

      N = OBJ_ID / V$MULTIPLIER;
      ALLOWED = 0;
      IF(N = V$GEN) THEN ALLOWED = 1;

      SUSPEND;
  END
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_KIM_CODING_LIST (
    I$OBJ_ID BIGINT = null,
    I$SUBJECT_ID BIGINT = null)
RETURNS (
    OBJ_ID BIGINT,
    DATE_ADD TIMESTAMP,
    DATE_MODIFY TIMESTAMP,
    DATE_DEL TIMESTAMP,
    CODING_NAME VARCHAR(200),
    N_LEVELS SMALLINT)
AS
begin

  FOR
      SELECT KC.OBJ_ID, KC.DATE_ADD, KC.DATE_MODIFY, KC.DATE_DEL, KC.OBJ_NAME, KC.N_LEVELS
      FROM UT_KIM_CODING KC
      WHERE KC.DATE_DEL IS NULL AND (:I$OBJ_ID IS NULL OR KC.OBJ_ID = :I$OBJ_ID) AND
        EXISTS (
            SELECT FIRST 1 1
            FROM UT_KIM_CODING_SUBJECTS CS
            WHERE CS.DATE_DEL IS NULL AND CS.CODING_ID = KC.OBJ_ID AND
                ((CS.SUBJECT_ID IS NULL AND :I$SUBJECT_ID IS NULL) OR (CS.SUBJECT_ID = :I$SUBJECT_ID))
        )
      INTO :OBJ_ID, :DATE_ADD, :DATE_MODIFY, :DATE_DEL, :CODING_NAME, :N_LEVELS
  DO
  BEGIN
      SUSPEND;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_KIM_CODING_SET (
    I$OBJ_ID BIGINT,
    I$OBJ_NAME VARCHAR(1000) NOT NULL,
    I$N_LEVELS INTEGER NOT NULL,
    I$SUBJECTS VARCHAR(4000) NOT NULL,
    I$STAGES VARCHAR(4000) NOT NULL,
    I$USER_ID VARCHAR(40))
RETURNS (
    OBJ_ID BIGINT)
AS
DECLARE VARIABLE S VARCHAR(100);
DECLARE VARIABLE P INTEGER;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$MAX_LEVEL INTEGER;
DECLARE VARIABLE V$MIN_QUESTIONS INTEGER;
DECLARE VARIABLE V$USER_ID BIGINT;
DECLARE VARIABLE V$GEN BIGINT;
DECLARE VARIABLE V$MULTIPLIER BIGINT;
DECLARE VARIABLE N INTEGER;
begin

  -- Проверяем уровень доступа пользователя
  IF(I$USER_ID = 'Веб-администратор') THEN V$USER_ID = 1; ELSE V$USER_ID = CAST(I$USER_ID AS BIGINT);

  SELECT GEN, MULTIPLIER
  FROM GEN
  INTO :V$GEN, :V$MULTIPLIER;

  IF(I$N_LEVELS < 1 OR I$N_LEVELS > 5) THEN EXCEPTION DATA_ERROR 'Количество уровней не в пределах 1..5';

  IF(I$OBJ_ID IS NULL) THEN
  BEGIN
    -- Эта ветка только для ручного добавления кодификатора, автоматический импорт идет по другой ветке
    INSERT INTO UT_KIM_CODING
    (OBJ_NAME, N_LEVELS, USER_ID)
    VALUES (:I$OBJ_NAME, :I$N_LEVELS, :V$USER_ID)
    RETURNING OBJ_ID
    INTO :OBJ_ID;
  END
  ELSE
  BEGIN
    N = I$OBJ_ID / V$MULTIPLIER;
    IF(N <> V$GEN) THEN EXCEPTION DATA_ERROR 'Нельзя изменять кодификатор, созданный в другой организации/уровне';

    -- Сколько уровней занято сейчас, и на каком уровне есть вопросы ?
    OBJ_ID = I$OBJ_ID;

    SELECT MAX_LEVEL, MIN_QUESTIONS
    FROM UT_KIM_CODING_CNT(:OBJ_ID)
    INTO :V$MAX_LEVEL, :V$MIN_QUESTIONS;

    IF(V$MIN_QUESTIONS < I$N_LEVELS) THEN
      EXCEPTION DATA_ERROR 'Уже внесены вопросы на уровнях кодификатора меньшем, чем вы задали. Необходимо удалить вопросы, либо создать новый кодификатор';
    IF(I$N_LEVELS < V$MAX_LEVEL) THEN
      EXCEPTION DATA_ERROR 'Нельзя сократить количество уровней, поскольку в базе уже сохранены данные по разделам кодификатора. ' ||
        'Сначала удалите разделы, сохранение изменения, и затем скорректируйте количество уровней';

    UPDATE UT_KIM_CODING
    SET OBJ_NAME = :I$OBJ_NAME, N_LEVELS = :I$N_LEVELS
    WHERE OBJ_ID = :OBJ_ID;
  END

  -- Этапы
  UPDATE UT_KIM_CODING_STAGES
  SET DATE_DEL = CURRENT_TIMESTAMP
  WHERE CODING_ID = :OBJ_ID AND DATE_DEL IS NULL;

  WHILE(CHAR_LENGTH(I$STAGES) > 0) DO
  BEGIN

      P = POSITION(',' IN I$STAGES);
      IF(P = 1) THEN I$STAGES = SUBSTRING(I$STAGES FROM 2);
      ELSE
      BEGIN
          IF(P <= 0) THEN P = CHAR_LENGTH(I$STAGES) + 1;
          S = SUBSTRING(I$STAGES FROM 1 FOR P - 1);
          I$STAGES = SUBSTRING(I$STAGES FROM P + 1);

          V$OBJ_ID = NULL;

          SELECT FIRST 1 OBJ_ID
          FROM UT_KIM_CODING_STAGES
          WHERE CODING_ID = :OBJ_ID AND STAGE_ID = :S
          INTO :V$OBJ_ID;

          IF(V$OBJ_ID IS NULL) THEN
          BEGIN
              INSERT INTO UT_KIM_CODING_STAGES
              (CODING_ID, STAGE_ID)
              VALUES (:OBJ_ID, :S);
          END
          ELSE
          BEGIN
              UPDATE UT_KIM_CODING_STAGES
              SET DATE_DEL = NULL
              WHERE OBJ_ID = :V$OBJ_ID;
          END

      END

  END

  -- Предметы
  UPDATE UT_KIM_CODING_SUBJECTS
  SET DATE_DEL = CURRENT_TIMESTAMP
  WHERE CODING_ID = :OBJ_ID AND DATE_DEL IS NULL;

  WHILE(CHAR_LENGTH(I$SUBJECTS) > 0) DO
  BEGIN

      P = POSITION(',' IN I$SUBJECTS);
      IF(P = 1) THEN I$SUBJECTS = SUBSTRING(I$SUBJECTS FROM 2);
      ELSE
      BEGIN
          IF(P <= 0) THEN P = CHAR_LENGTH(I$SUBJECTS) + 1;
          S = SUBSTRING(I$SUBJECTS FROM 1 FOR P - 1);
          I$SUBJECTS = SUBSTRING(I$SUBJECTS FROM P + 1);
          IF(S = '' OR S = '*') THEN S = NULL; -- Метапредмет

          V$OBJ_ID = NULL;

          SELECT FIRST 1 OBJ_ID
          FROM UT_KIM_CODING_SUBJECTS
          WHERE CODING_ID = :OBJ_ID AND ((:S IS NULL AND SUBJECT_ID IS NULL) OR SUBJECT_ID = :S)
          INTO :V$OBJ_ID;

          IF(V$OBJ_ID IS NULL) THEN
          BEGIN
              INSERT INTO UT_KIM_CODING_SUBJECTS
              (CODING_ID, SUBJECT_ID)
              VALUES (:OBJ_ID, :S);
          END
          ELSE
          BEGIN
              UPDATE UT_KIM_CODING_SUBJECTS
              SET DATE_DEL = NULL
              WHERE OBJ_ID = :V$OBJ_ID;
          END

      END

  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_KIM_CODING_SUB_CNT (
    I$SECTION_ID BIGINT)
RETURNS (
    N INTEGER)
AS
declare variable V$OBJ_ID bigint;
declare variable V$TMP integer;
begin

  N = 0;

  FOR
      SELECT OBJ_ID
      FROM UT_KIM_CODING_LEVELS
      WHERE DATE_DEL IS NULL AND (PARENT_ID = :I$SECTION_ID OR (CODING_ID = :I$SECTION_ID AND PARENT_ID IS NULL))
      INTO :V$OBJ_ID
  DO
  BEGIN

      IF(N = 0) THEN N = 1;

      V$TMP = (SELECT N FROM UT_KIM_CODING_SUB_CNT(:V$OBJ_ID)) + 1;
      IF(V$TMP > N) THEN N = V$TMP;

  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_KIM_CODING_SYNC (
    I$OBJ_ID BIGINT,
    I$OBJ_NAME VARCHAR(400),
    I$LEVELS INTEGER,
    I$SUBJECTS VARCHAR(1000),
    I$STAGES VARCHAR(1000))
RETURNS (
    OBJ_ID BIGINT)
AS
DECLARE VARIABLE V$OBJ_NAME VARCHAR(400);
DECLARE VARIABLE V$N_LEVELS INTEGER;
DECLARE VARIABLE V$VAL BIGINT;
DECLARE VARIABLE V$LVAL BIGINT;
begin

  SELECT FIRST 1 C.OBJ_ID, C.OBJ_NAME, C.N_LEVELS
  FROM UT_KIM_CODING C
  WHERE C.REF_ID = :I$OBJ_ID
  INTO :OBJ_ID, :V$OBJ_NAME, :V$N_LEVELS;

  IF(OBJ_ID IS NULL) THEN
  BEGIN
    -- ID обязательно будут в районе 0, региональные в районе 100+GEN
    INSERT INTO UT_KIM_CODING
    (OBJ_ID, REF_ID, OBJ_NAME, N_LEVELS, OWNER_LEVEL)
    VALUES (:I$OBJ_ID, :I$OBJ_ID, :I$OBJ_NAME, :I$LEVELS, 0)
    RETURNING OBJ_ID INTO :OBJ_ID;
  END
  ELSE IF(I$LEVELS <> V$N_LEVELS OR I$OBJ_NAME <> V$OBJ_NAME) THEN
  BEGIN
    UPDATE UT_KIM_CODING
    SET OBJ_NAME = :I$OBJ_NAME, N_LEVELS = :I$LEVELS
    WHERE OBJ_ID = :OBJ_ID;
  END

  -- Обновляем привязки к предметам и этапам - только на пополнение
  FOR
    SELECT C.ID
    FROM STR_TO_ID_LIST(:I$STAGES) C
    INTO :V$VAL
  DO
  BEGIN
    IF(V$VAL >= 1 AND V$VAL <= 11) THEN V$LVAL = V$VAL;
    ELSE V$LVAL = NULL;
    IF(V$LVAL IS NOT NULL AND NOT EXISTS(
      SELECT FIRST 1 1
      FROM UT_KIM_CODING_STAGES CS
      WHERE CS.DATE_DEL IS NULL AND CS.CODING_ID = :OBJ_ID AND CS.STAGE_ID = :V$LVAL
    ))
    THEN
    BEGIN
      INSERT INTO UT_KIM_CODING_STAGES
      (CODING_ID, STAGE_ID)
      VALUES (:OBJ_ID, :V$LVAL);
    END
  END

  FOR
    SELECT C.ID
    FROM STR_TO_ID_LIST(:I$SUBJECTS) C
    INTO :V$VAL
  DO
  BEGIN
    IF(NOT EXISTS(
      SELECT FIRST 1 1
      FROM UT_KIM_CODING_SUBJECTS CS
      WHERE CS.DATE_DEL IS NULL AND CS.CODING_ID = :OBJ_ID AND COALESCE(CS.SUBJECT_ID, 0) = COALESCE(:V$VAL, 0)
    ))
    THEN
    BEGIN
      INSERT INTO UT_KIM_CODING_SUBJECTS
      (CODING_ID, SUBJECT_ID)
      VALUES (:OBJ_ID, :V$VAL);
    END
  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_KIM_CODING_VIEW (
    I$SUBJECT_ID BIGINT = NULL,
    I$STAGE_ID BIGINT = NULL)
RETURNS (
    OBJ_ID BIGINT,
    SUBJECT_ID BIGINT,
    STAGE_ID BIGINT,
    OBJ_NAME VARCHAR(1000),
    SUBJECT_NAME VARCHAR(2000),
    STAGE_NAME VARCHAR(2000),
    N_LEVELS SMALLINT)
AS
DECLARE VARIABLE S VARCHAR(1000);
begin
  -- Используется в app.test_coding метод list
  -- Процедура заменена на прямую выборку

  FOR
    SELECT KC.OBJ_ID, KC.OBJ_NAME, KC.N_LEVELS
    FROM UT_KIM_CODING KC
    WHERE DATE_DEL IS NULL
    -- Дофильтровываем по предмету или этапу
    INTO :OBJ_ID, :OBJ_NAME, :N_LEVELS
  DO
  BEGIN
    SUBJECT_NAME = '';
    STAGE_NAME = '';

    FOR
      SELECT ES.OBJ_NAME
      FROM UT_KIM_CODING_STAGES CS
      JOIN UT_EXAM_STAGES ES ON ES.OBJ_ID = CS.STAGE_ID
      WHERE CS.DATE_DEL IS NULL AND CS.CODING_ID = :OBJ_ID
      ORDER BY ES.SORT_INDEX
      INTO :S
    DO
    BEGIN
      IF(CHAR_LENGTH(STAGE_NAME) > 0) THEN STAGE_NAME = STAGE_NAME || ', ';
      IF(CHAR_LENGTH(STAGE_NAME) + CHAR_LENGTH(S) + 1 > 2000) THEN STAGE_NAME = STAGE_NAME || '...'; ELSE STAGE_NAME = STAGE_NAME || S;
    END

    FOR
      SELECT IIF(CS.SUBJECT_ID IS NULL, 'Метапредмет', V376.VAL)
      FROM UT_KIM_CODING_SUBJECTS CS
      LEFT JOIN VALS V376 ON V376.OBJ_ID = CS.SUBJECT_ID AND V376.PARAM_ID = 376 AND V376.IS_DEL = 0
      WHERE CS.DATE_DEL IS NULL AND CS.CODING_ID = :OBJ_ID
      ORDER BY 1
      INTO :S
    DO
    BEGIN
      IF(CHAR_LENGTH(SUBJECT_NAME) > 0) THEN SUBJECT_NAME = SUBJECT_NAME || ', ';
      IF(CHAR_LENGTH(SUBJECT_NAME) + CHAR_LENGTH(S) + 1 > 2000) THEN SUBJECT_NAME = SUBJECT_NAME || '...'; ELSE SUBJECT_NAME = SUBJECT_NAME || S;
    END

    SUSPEND;
  END
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_KIM_QUESTION_DESC (
    I$OBJ_ID BIGINT,
    I$CODING_ID BIGINT = NULL)
RETURNS (
    SUBJECTS_TEXT VARCHAR(4000),
    STAGES_TEXT VARCHAR(1000),
    LEVELS_TEXT VARCHAR(400))
AS
DECLARE VARIABLE V$LEVELS INTEGER;
DECLARE VARIABLE S VARCHAR(100);
DECLARE VARIABLE V INTEGER;
begin

  V$LEVELS = 0;
  STAGES_TEXT = '';

  IF(I$CODING_ID IS NULL) THEN
  BEGIN
    SELECT LIST(COALESCE(SVAL, 'Метапредмет'), ', ')
    FROM (
      SELECT DISTINCT V376.SVAL
      FROM UT_QUESTION_RELS R
      JOIN UT_KIM_CODING_LEVELS CL ON CL.OBJ_ID = R.SECTION_ID AND CL.DATE_DEL IS NULL
      JOIN UT_KIM_CODING_SUBJECTS C ON C.CODING_ID = CL.CODING_ID AND C.DATE_DEL IS NULL
      LEFT JOIN VALS V376 ON V376.OBJ_ID = C.SUBJECT_ID AND V376.PARAM_ID IN (376, 1751)
      WHERE R.DATE_DEL IS NULL AND R.QUESTION_ID = :I$OBJ_ID
    )
    INTO :SUBJECTS_TEXT;

    FOR
      SELECT DISTINCT S.OBJ_NAME, S.OBJ_ID
      FROM UT_QUESTION_RELS R
      JOIN UT_KIM_CODING_LEVELS CL ON CL.OBJ_ID = R.SECTION_ID AND CL.DATE_DEL IS NULL
      JOIN UT_KIM_CODING_STAGES C ON C.CODING_ID = CL.CODING_ID AND C.DATE_DEL IS NULL
      JOIN UT_EXAM_STAGES S ON S.OBJ_ID = C.STAGE_ID
      WHERE R.DATE_DEL IS NULL AND R.QUESTION_ID = :I$OBJ_ID
      ORDER BY S.SORT_INDEX
      INTO :S, :V
    DO
    BEGIN
      IF(STAGES_TEXT <> '') THEN STAGES_TEXT = STAGES_TEXT || ', ';
      STAGES_TEXT = STAGES_TEXT || S;
      IF((V >= 1 AND V <= 4) OR V = 20 OR V = 100) THEN V$LEVELS = BIN_OR(V$LEVELS, 1);
      IF((V >= 5 AND V <= 9) OR V = 20 OR V = 100) THEN V$LEVELS = BIN_OR(V$LEVELS, 2);
      IF((V >= 10 AND V <= 11) OR V = 20 OR V = 100) THEN V$LEVELS = BIN_OR(V$LEVELS, 4);
      IF((V >= 41 AND V <= 46) OR V = 20 OR V = 100) THEN V$LEVELS = BIN_OR(V$LEVELS, 8);
    END
  END
  ELSE
  BEGIN
    SELECT LIST(COALESCE(SVAL, 'Метапредмет'), ', ')
    FROM (
      SELECT DISTINCT V376.SVAL
      FROM UT_KIM_CODING_SUBJECTS C
      LEFT JOIN VALS V376 ON V376.OBJ_ID = C.SUBJECT_ID AND V376.PARAM_ID IN (376, 1751)
      WHERE C.CODING_ID = :I$CODING_ID AND C.DATE_DEL IS NULL
    )
    INTO :SUBJECTS_TEXT;

    FOR
      SELECT DISTINCT S.OBJ_NAME, S.OBJ_ID
      FROM UT_KIM_CODING_STAGES C
      JOIN UT_EXAM_STAGES S ON S.OBJ_ID = C.STAGE_ID
      WHERE C.CODING_ID = :I$CODING_ID AND C.DATE_DEL IS NULL
      ORDER BY S.SORT_INDEX
      INTO :S, :V
    DO
    BEGIN
      IF(STAGES_TEXT <> '') THEN STAGES_TEXT = STAGES_TEXT || ', ';
      STAGES_TEXT = STAGES_TEXT || S;
      IF((V >= 1 AND V <= 4) OR V = 20 OR V = 100) THEN V$LEVELS = BIN_OR(V$LEVELS, 1);
      IF((V >= 5 AND V <= 9) OR V = 20 OR V = 100) THEN V$LEVELS = BIN_OR(V$LEVELS, 2);
      IF((V >= 10 AND V <= 11) OR V = 20 OR V = 100) THEN V$LEVELS = BIN_OR(V$LEVELS, 4);
      IF((V >= 41 AND V <= 46) OR V = 20 OR V = 100) THEN V$LEVELS = BIN_OR(V$LEVELS, 8);
    END
  END

  LEVELS_TEXT = '';
  IF(BIN_AND(V$LEVELS, 1) <> 0) THEN LEVELS_TEXT = LEVELS_TEXT || 'НОО, ';
  IF(BIN_AND(V$LEVELS, 2) <> 0) THEN LEVELS_TEXT = LEVELS_TEXT || 'ООО, ';
  IF(BIN_AND(V$LEVELS, 4) <> 0) THEN LEVELS_TEXT = LEVELS_TEXT || 'СОО, ';
  IF(BIN_AND(V$LEVELS, 8) <> 0) THEN LEVELS_TEXT = LEVELS_TEXT || 'СПО, ';

  IF(LEVELS_TEXT <> '') THEN LEVELS_TEXT = SUBSTRING(LEVELS_TEXT FROM 1 FOR CHAR_LENGTH(LEVELS_TEXT) - 2);

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_LEVEL_GROUP_UA_LIST (
    I$EXAM_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$LEVEL INTEGER)
RETURNS (
    OBJ_ID BIGINT,
    N_MEMBERS INTEGER)
AS
begin

  -- Коллективы берем из числа где остались нераспределенные участники

  IF(I$LEVEL = 0) THEN
  BEGIN
      -- Регион - берем вообще все коллективы без разбору
      FOR
          -- Действующие сотрудники
          SELECT DISTINCT L14.PARENT_ID
          FROM LINKS L111
          JOIN LINKS L2 ON L2.PARENT_ID = L111.OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
          JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
          JOIN UT_EXAM_PERSON_ASSN A ON A.EXAM_ID = :I$EXAM_ID AND A.PERSON_ID = L14.OBJ_ID AND A.DATE_DEL IS NULL
          LEFT JOIN UT_PERSON_PPE_ASSN PA ON PA.EXAM_ID = :I$EXAM_ID AND PA.DATE_DEL IS NULL AND PA.PERSON_ID = L14.OBJ_ID
          WHERE L111.PARENT_ID = :I$OBJ_ID AND L111.OBJ_TYPE_ID = 111 AND L111.DATE_DEL IS NULL AND PA.OBJ_ID IS NULL
          -- Действующие учащиеся
          UNION
          SELECT DISTINCT L10.PARENT_ID
          FROM LINKS L111
          JOIN LINKS L2 ON L2.PARENT_ID = L111.OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
          JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID IN (7, 502) AND L7.DATE_DEL IS NULL
          JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
          JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 125, 187) AND L9.DATE_DEL IS NULL
          JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID IN (10, 126) AND L10.DATE_DEL IS NULL
          JOIN UT_EXAM_PERSON_ASSN A ON A.EXAM_ID = :I$EXAM_ID AND A.PERSON_ID = L10.OBJ_ID AND A.DATE_DEL IS NULL
          LEFT JOIN UT_PERSON_PPE_ASSN PA ON PA.EXAM_ID = :I$EXAM_ID AND PA.DATE_DEL IS NULL AND PA.PERSON_ID = L10.OBJ_ID
          WHERE L111.PARENT_ID = :I$OBJ_ID AND L111.OBJ_TYPE_ID = 111 AND L111.DATE_DEL IS NULL AND PA.OBJ_ID IS NULL
          INTO :OBJ_ID
      DO
      BEGIN
          SELECT COUNT(*)
          FROM LINKS LP
          JOIN UT_EXAM_PERSON_ASSN A ON A.EXAM_ID = :I$EXAM_ID AND A.PERSON_ID = LP.OBJ_ID AND A.DATE_DEL IS NULL
          LEFT JOIN UT_PERSON_PPE_ASSN PA ON PA.EXAM_ID = :I$EXAM_ID AND PA.PERSON_ID = LP.OBJ_ID AND PA.DATE_DEL IS NULL
          WHERE LP.PARENT_ID = :OBJ_ID AND LP.OBJ_TYPE_ID IN (10, 14, 126) AND LP.DATE_DEL IS NULL AND PA.OBJ_ID IS NULL
          INTO :N_MEMBERS;

          SUSPEND;
      END
  END
  ELSE IF(I$LEVEL = 1) THEN
  BEGIN
      -- Район
      FOR
          -- Действующие сотрудники
          SELECT DISTINCT L14.PARENT_ID
          FROM LINKS L2
          JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
          JOIN UT_EXAM_PERSON_ASSN A ON A.EXAM_ID = :I$EXAM_ID AND A.PERSON_ID = L14.OBJ_ID AND A.DATE_DEL IS NULL
          LEFT JOIN UT_PERSON_PPE_ASSN PA ON PA.EXAM_ID = :I$EXAM_ID AND PA.DATE_DEL IS NULL AND PA.PERSON_ID = L14.OBJ_ID
          WHERE L2.PARENT_ID = :I$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND PA.OBJ_ID IS NULL
          -- Действующие учащиеся
          UNION
          SELECT DISTINCT L10.PARENT_ID
          FROM LINKS L2
          JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID IN (7, 502) AND L7.DATE_DEL IS NULL
          JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
          JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 125, 187) AND L9.DATE_DEL IS NULL
          JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID IN (10, 126) AND L10.DATE_DEL IS NULL
          JOIN UT_EXAM_PERSON_ASSN A ON A.EXAM_ID = :I$EXAM_ID AND A.PERSON_ID = L10.OBJ_ID AND A.DATE_DEL IS NULL
          LEFT JOIN UT_PERSON_PPE_ASSN PA ON PA.EXAM_ID = :I$EXAM_ID AND PA.DATE_DEL IS NULL AND PA.PERSON_ID = L10.OBJ_ID
          WHERE L2.PARENT_ID = :I$OBJ_ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND PA.OBJ_ID IS NULL
          INTO :OBJ_ID
      DO
      BEGIN
          SELECT COUNT(*)
          FROM LINKS LP
          JOIN UT_EXAM_PERSON_ASSN A ON A.EXAM_ID = :I$EXAM_ID AND A.PERSON_ID = LP.OBJ_ID AND A.DATE_DEL IS NULL
          LEFT JOIN UT_PERSON_PPE_ASSN PA ON PA.EXAM_ID = :I$EXAM_ID AND PA.PERSON_ID = LP.OBJ_ID AND PA.DATE_DEL IS NULL
          WHERE LP.PARENT_ID = :OBJ_ID AND LP.OBJ_TYPE_ID IN (10, 14, 126) AND LP.DATE_DEL IS NULL AND PA.OBJ_ID IS NULL
          INTO :N_MEMBERS;

          SUSPEND;
      END
  END
  ELSE IF(I$LEVEL = 2) THEN
  BEGIN
      -- ОУ
      FOR
          -- Действующие сотрудники
          SELECT DISTINCT L14.PARENT_ID
          FROM LINKS L14
          JOIN UT_EXAM_PERSON_ASSN A ON A.EXAM_ID = :I$EXAM_ID AND A.PERSON_ID = L14.OBJ_ID AND A.DATE_DEL IS NULL
          LEFT JOIN UT_PERSON_PPE_ASSN PA ON PA.EXAM_ID = :I$EXAM_ID AND PA.DATE_DEL IS NULL AND PA.PERSON_ID = L14.OBJ_ID
          WHERE L14.PARENT_ID = :I$OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL AND PA.OBJ_ID IS NULL
          -- Действующие учащиеся
          UNION
          SELECT DISTINCT L10.PARENT_ID
          FROM LINKS L7
          JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
          JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 125, 187) AND L9.DATE_DEL IS NULL
          JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID IN (10, 126) AND L10.DATE_DEL IS NULL
          JOIN UT_EXAM_PERSON_ASSN A ON A.EXAM_ID = :I$EXAM_ID AND A.PERSON_ID = L10.OBJ_ID AND A.DATE_DEL IS NULL
          LEFT JOIN UT_PERSON_PPE_ASSN PA ON PA.EXAM_ID = :I$EXAM_ID AND PA.DATE_DEL IS NULL AND PA.PERSON_ID = L10.OBJ_ID
          WHERE L7.PARENT_ID = :I$OBJ_ID AND L7.OBJ_TYPE_ID IN (7, 502) AND L7.DATE_DEL IS NULL AND PA.OBJ_ID IS NULL
          INTO :OBJ_ID
      DO
      BEGIN
          SELECT COUNT(*)
          FROM LINKS LP
          JOIN UT_EXAM_PERSON_ASSN A ON A.EXAM_ID = :I$EXAM_ID AND A.PERSON_ID = LP.OBJ_ID AND A.DATE_DEL IS NULL
          LEFT JOIN UT_PERSON_PPE_ASSN PA ON PA.EXAM_ID = :I$EXAM_ID AND PA.PERSON_ID = LP.OBJ_ID AND PA.DATE_DEL IS NULL
          WHERE LP.PARENT_ID = :OBJ_ID AND LP.OBJ_TYPE_ID IN (10, 14, 126) AND LP.DATE_DEL IS NULL AND PA.OBJ_ID IS NULL
          INTO :N_MEMBERS;

          SUSPEND;
      END
  END
  ELSE IF(I$LEVEL = 3) THEN
  BEGIN
      -- Коллектив
      FOR
          SELECT DISTINCT LP.PARENT_ID
          FROM LINKS LP
          JOIN UT_EXAM_PERSON_ASSN A ON A.EXAM_ID = :I$EXAM_ID AND A.PERSON_ID = LP.OBJ_ID AND A.DATE_DEL IS NULL
          LEFT JOIN UT_PERSON_PPE_ASSN PA ON PA.EXAM_ID = :I$EXAM_ID AND PA.DATE_DEL IS NULL AND PA.PERSON_ID = LP.OBJ_ID
          WHERE LP.PARENT_ID = :I$OBJ_ID AND LP.OBJ_TYPE_ID IN (10, 14, 126) AND LP.DATE_DEL IS NULL AND PA.OBJ_ID IS NULL
          INTO :OBJ_ID
      DO
      BEGIN
          SELECT COUNT(*)
          FROM LINKS LP
          JOIN UT_EXAM_PERSON_ASSN A ON A.EXAM_ID = :I$EXAM_ID AND A.PERSON_ID = LP.OBJ_ID AND A.DATE_DEL IS NULL
          LEFT JOIN UT_PERSON_PPE_ASSN PA ON PA.EXAM_ID = :I$EXAM_ID AND PA.PERSON_ID = LP.OBJ_ID AND PA.DATE_DEL IS NULL
          WHERE LP.PARENT_ID = :OBJ_ID AND LP.OBJ_TYPE_ID IN (10, 14, 126) AND LP.DATE_DEL IS NULL AND PA.OBJ_ID IS NULL
          INTO :N_MEMBERS;

          SUSPEND;
      END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_OU_DESC (
    I$OBJ_ID BIGINT,
    I$CUT_NAME SMALLINT = 0)
RETURNS (
    OBJ_ID BIGINT,
    NAME_FULL VARCHAR(400),
    NAME_SHORT VARCHAR(200),
    AREA_ID BIGINT,
    AREA_NAME VARCHAR(100),
    OPF_ID BIGINT,
    OPF_NAME VARCHAR(100),
    PROP_TYPE_ID BIGINT,
    PROP_TYPE_NAME VARCHAR(100),
    ORG_TYPE_ID BIGINT,
    ORG_TYPE_NAME VARCHAR(100),
    ORG_KIND_ID BIGINT,
    ORG_KIND_NAME VARCHAR(100),
    ORG_STATE_ID BIGINT,
    ORG_STATE_NAME VARCHAR(100),
    OGRN VARCHAR(100),
    INN VARCHAR(100),
    IS_ALL SMALLINT)
AS
begin

  -- Специальный случай OBJ_ID = 0 - все ОУ региона
  OBJ_ID = I$OBJ_ID;

  SELECT SUBSTRING(V5.VAL FROM 1 FOR 400)
  FROM VALS V5
  WHERE V5.OBJ_ID = :I$OBJ_ID AND V5.PARAM_ID = 5 AND V5.IS_DEL = 0
  INTO :NAME_FULL;

  SELECT SUBSTRING(V2.VAL FROM 1 FOR 200)
  FROM VALS V2
  WHERE V2.OBJ_ID = :I$OBJ_ID AND V2.PARAM_ID = 2 AND V2.IS_DEL = 0
  INTO :NAME_SHORT;

  IF(I$CUT_NAME = 1) THEN
  BEGIN
    NAME_SHORT = REPLACE(NAME_SHORT, 'Государственное', '');
    NAME_SHORT = REPLACE(NAME_SHORT, 'бюджетное', '');
    NAME_SHORT = REPLACE(NAME_SHORT, 'образовательное', '');
    NAME_SHORT = REPLACE(NAME_SHORT, 'учреждение', '');
    NAME_SHORT = TRIM(NAME_SHORT);
  END

  -- С кодом района идем двумя путями. Если задан прямо в ОУ - берем оттуда. Если нет, смотрим вышестоящий район
  SELECT V2163.LISTVAL_ID, R.VAL
  FROM VALL V2163
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V2163.LISTVAL_ID
  JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
  WHERE V2163.OBJ_ID = :I$OBJ_ID AND V2163.PARAM_ID = 2163 AND V2163.IS_DEL = 0
  INTO :AREA_ID, :AREA_NAME;

  IF(AREA_ID IS NULL) THEN
  BEGIN
      SELECT V665.LISTVAL_ID, R.VAL
      FROM LINKS LP111
      JOIN VALL V665 ON V665.OBJ_ID = :I$OBJ_ID AND V665.PARAM_ID = 665 AND V665.IS_DEL = 0
      JOIN LISTVALS LV ON LV.LISTVAL_ID = V665.LISTVAL_ID
      JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
      WHERE LP111.OBJ_ID = :I$OBJ_ID AND LP111.PARENT_TYPE_ID = 111 AND LP111.DATE_DEL IS NULL
      INTO :AREA_ID, :AREA_NAME;
  END

  SELECT V8.LISTVAL_ID, SUBSTRING(R.VAL FROM 1 FOR 100)
  FROM VALL V8
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V8.LISTVAL_ID
  JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
  WHERE V8.OBJ_ID = :I$OBJ_ID AND V8.PARAM_ID = 8 AND V8.IS_DEL = 0
  INTO :OPF_ID, :OPF_NAME;

  -- PROP_TYPE_ID, PROP_TYPE_NAME оставляем пустыми

  SELECT V11.LISTVAL_ID, SUBSTRING(R.VAL FROM 1 FOR 100)
  FROM VALL V11
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V11.LISTVAL_ID
  JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
  WHERE V11.OBJ_ID = :I$OBJ_ID AND V11.PARAM_ID = 11 AND V11.IS_DEL = 0
  INTO :ORG_TYPE_ID, :ORG_TYPE_NAME;

  SELECT V10.LISTVAL_ID, SUBSTRING(R.VAL FROM 1 FOR 100)
  FROM VALL V10
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V10.LISTVAL_ID
  JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
  WHERE V10.OBJ_ID = :I$OBJ_ID AND V10.PARAM_ID = 10 AND V10.IS_DEL = 0
  INTO :ORG_KIND_ID, :ORG_KIND_NAME;

  SELECT V2371.LISTVAL_ID, R.VAL
  FROM VALL V2371
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V2371.LISTVAL_ID
  JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
  WHERE V2371.OBJ_ID = :I$OBJ_ID AND V2371.PARAM_ID = 2371 AND V2371.IS_DEL = 0
  INTO :ORG_STATE_ID, :ORG_STATE_NAME;

  SELECT V9.VAL
  FROM VALS V9
  WHERE V9.OBJ_ID = :I$OBJ_ID AND V9.PARAM_ID = 9 AND V9.IS_DEL = 0
  INTO :OGRN;

  SELECT V33.VAL
  FROM VALS V33
  WHERE V33.OBJ_ID = :I$OBJ_ID AND V33.PARAM_ID = 33 AND V33.IS_DEL = 0
  INTO :INN;

  IS_ALL = 0;
  IF(OBJ_ID = 0) THEN
  BEGIN
      NAME_SHORT = 'Все организации региона';
      NAME_FULL = 'Все организации региона';
      IS_ALL = 1;
  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_PARTICIPANTS_GET (
    SCBOYCOD BIGINT)
RETURNS (
    SCBOYCODE BIGINT,
    FORMID BIGINT,
    FORMNUM INTEGER,
    FORMNAME VARCHAR(1000),
    FIRSTNAME VARCHAR(1000),
    NAME VARCHAR(1000),
    LASTNAME VARCHAR(1000),
    SCHOOLID BIGINT)
AS
BEGIN
    FOR
        SELECT PUPIL.OBJ_ID AS PUPIL_ID,
               CAST(FN.VAL AS VARCHAR(1000)) AS FIRST_NAME,
               CAST(N.VAL AS VARCHAR(1000)) AS NAME,
               CAST(LN.VAL AS VARCHAR(1000)) AS LAST_NAME,
               FORM.OBJ_ID AS CLASS_ID,
               FNUM.TAG AS FORM_NUM,
               F.CAPTION AS FORM_NAME,
               GRADE.PARENT_ID AS SCHOOL_ID
        FROM LINKS PUPIL
        LEFT JOIN VALS FN ON FN.OBJ_ID = PUPIL.OBJ_ID AND FN.PARAM_ID = 55 AND FN.IS_DEL = 0
        LEFT JOIN VALS N ON N.OBJ_ID = PUPIL.OBJ_ID AND N.PARAM_ID = 56 AND N.IS_DEL = 0
        LEFT JOIN VALS LN ON LN.OBJ_ID = PUPIL.OBJ_ID AND LN.PARAM_ID = 57 AND LN.IS_DEL = 0
        JOIN LINKS FORM ON FORM.OBJ_ID = PUPIL.PARENT_ID AND FORM.DATE_DEL IS NULL AND FORM.PARENT_TYPE_ID = 8 --STAGE
        JOIN LINKS STAGE ON STAGE.OBJ_ID = FORM.PARENT_ID AND STAGE.DATE_DEL IS NULL AND STAGE.PARENT_TYPE_ID = 7 --GRADE
        JOIN VALL FNUML ON FNUML.OBJ_ID = STAGE.OBJ_ID AND FNUML.PARAM_ID = 49 AND FNUML.IS_DEL = 0
        JOIN LISTVALS FNUM ON FNUM.LISTVAL_ID = FNUML.LISTVAL_ID
        JOIN LINKS GRADE ON GRADE.OBJ_ID = STAGE.PARENT_ID AND GRADE.DATE_DEL IS NULL AND GRADE.PARENT_TYPE_ID = 2 --SCHOOL
        LEFT JOIN OBJECT_CAPTION_GET(FORM.OBJ_ID) F ON 1=1
        WHERE PUPIL.OBJ_ID = :SCBOYCOD AND PUPIL.DATE_DEL IS NULL AND PUPIL.PARENT_TYPE_ID = 9 --CLASS

        UNION

        SELECT TEACHER.OBJ_ID,
               CAST(FN.VAL AS VARCHAR(1000)) AS FIRST_NAME,
               CAST(N.VAL AS VARCHAR(1000)) AS NAME,
               CAST(L.VAL AS VARCHAR(1000)) AS LAST_NAME,
               NULL, NULL, NULL,
               TEACHER.PARENT_ID AS SCHOOL_ID
        FROM LINKS TEACHER
        JOIN VALS FN ON FN.OBJ_ID = TEACHER.OBJ_ID AND FN.PARAM_ID = 59 AND FN.IS_DEL = 0
        JOIN VALS N ON N.OBJ_ID = TEACHER.OBJ_ID AND N.PARAM_ID = 60 AND N.IS_DEL = 0
        LEFT JOIN VALS L ON L.OBJ_ID = TEACHER.OBJ_ID AND L.PARAM_ID = 61 AND L.IS_DEL = 0
        WHERE TEACHER.OBJ_ID = :SCBOYCOD AND TEACHER.DATE_DEL IS NULL AND TEACHER.PARENT_TYPE_ID = 2
        
        UNION

        SELECT TEACHER.OBJ_ID,
               CAST(FN.VAL AS VARCHAR(1000)) AS FIRST_NAME,
               CAST(N.VAL AS VARCHAR(1000)) AS NAME,
               CAST(L.VAL AS VARCHAR(1000)) AS LAST_NAME,
               NULL, NULL, NULL,
               L211.PARENT_ID AS SCHOOL_ID
        FROM LINKS TEACHER
        JOIN VALS FN ON FN.OBJ_ID = TEACHER.OBJ_ID AND FN.PARAM_ID = 59 AND FN.IS_DEL = 0
        JOIN VALS N ON N.OBJ_ID = TEACHER.OBJ_ID AND N.PARAM_ID = 60 AND N.IS_DEL = 0
        LEFT JOIN VALS L ON L.OBJ_ID = TEACHER.OBJ_ID AND L.PARAM_ID = 61 AND L.IS_DEL = 0
        JOIN LINKS L211 ON L211.OBJ_ID = TEACHER.PARENT_ID AND L211.DATE_DEL IS NULL AND L211.PARENT_TYPE_ID = 211
        WHERE TEACHER.OBJ_ID = :SCBOYCOD AND TEACHER.DATE_DEL IS NULL AND TEACHER.PARENT_TYPE_ID = 211

        INTO :SCBOYCODE,
             :FIRSTNAME,
             :NAME,
             :LASTNAME,
             :FORMID,
             :FORMNUM,
             :FORMNAME,
             :SCHOOLID
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_PERSONS_DD_GRADES RETURNS (
    OBJ_ID BIGINT,
    OBJ_CAPTION VARCHAR(1000))
AS
declare variable TMP double precision;
begin

  FOR
      SELECT 0, 0, 'Сотрудники'
      FROM RDB$DATABASE
      UNION
      SELECT DISTINCT C.SORT_ORDER, L9.OBJ_ID, C.CAPTION
      FROM LINKS L2
      JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
      JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
      LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C ON 1 = 1
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      ORDER BY 1
      INTO :TMP, :OBJ_ID, :OBJ_CAPTION
  DO
  BEGIN
      SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_PERSONS_DD_STAGES RETURNS (
    OBJ_ID BIGINT,
    OBJ_CAPTION VARCHAR(1000))
AS
declare variable TMP double precision;
begin

  FOR
      SELECT 0, 0, 'Сотрудники'
      FROM RDB$DATABASE
      UNION
      SELECT DISTINCT LV.COST, V49.LISTVAL_ID, REPLACE(R.VAL, 'Параллель ', '')
      FROM LINKS L2
      JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
      JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
      JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
      JOIN LISTVALS LV ON LV.LISTVAL_ID = V49.LISTVAL_ID
      JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      ORDER BY 1
      INTO :TMP, :OBJ_ID, :OBJ_CAPTION
  DO
  BEGIN
      SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_PERSONS_LIST (
    I$FROM INTEGER,
    I$COUNT INTEGER,
    I$SORT_BY VARCHAR(20),
    I$STAGE_FILTER BIGINT,
    I$SUBJECT_FILTER BIGINT,
    I$FIO_FILTER VARCHAR(400),
    I$OBJ_ID BIGINT,
    I$GRADE_ID BIGINT,
    I$STAGE_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    OBJ_TYPE_ID BIGINT,
    PERSON_NAME VARCHAR(1000),
    GRADE_ID BIGINT,
    GRADE_NAME VARCHAR(1000),
    STAGE_ID BIGINT,
    STAGE_NAME VARCHAR(1000),
    EXAM_STATE SMALLINT,
    CNT INTEGER)
AS
declare variable V$STAGE_ID bigint;
declare variable V$SORT_INDEX integer;
begin

  -- I$STAGE_FILTER > UT_EXAM_STAGES
  -- I$SUBJECT_FILTER > конкретный предмет или NULL если любой предмет
  -- EXAM_STATE: 0 = можно менять, 1 = нельзя менять

  I$SORT_BY = UPPER(I$SORT_BY);
  IF(I$SORT_BY = 'STAGE_NAME') THEN V$SORT_INDEX = 7;
  ELSE IF(I$SORT_BY = 'GRADE_NAME') THEN V$SORT_INDEX = 5;
  ELSE V$SORT_INDEX = 3;

  -- Перекодируем I$STAGE_FILTER, при этом можно также использовать родные LISTVAL_ID Параграфа
  IF(I$STAGE_FILTER IN (20, 100)) THEN V$STAGE_ID = NULL;
  ELSE IF(I$STAGE_FILTER = 1) THEN V$STAGE_ID = 37;
  ELSE IF(I$STAGE_FILTER = 2) THEN V$STAGE_ID = 38;
  ELSE IF(I$STAGE_FILTER = 3) THEN V$STAGE_ID = 39;
  ELSE IF(I$STAGE_FILTER = 4) THEN V$STAGE_ID = 40;
  ELSE IF(I$STAGE_FILTER = 5) THEN V$STAGE_ID = 41;
  ELSE IF(I$STAGE_FILTER = 6) THEN V$STAGE_ID = 42;
  ELSE IF(I$STAGE_FILTER = 7) THEN V$STAGE_ID = 43;
  ELSE IF(I$STAGE_FILTER = 8) THEN V$STAGE_ID = 44;
  ELSE IF(I$STAGE_FILTER = 9) THEN V$STAGE_ID = 45;
  ELSE IF(I$STAGE_FILTER = 10) THEN V$STAGE_ID = 46;
  ELSE IF(I$STAGE_FILTER = 11) THEN V$STAGE_ID = 47;
  ELSE V$STAGE_ID = -1;

  -- Если I$FROM = NULL и I$COUNT = NULL, возвращаем количество строк в поле CNT
  IF(I$FROM IS NULL AND I$COUNT IS NULL AND I$SORT_BY = '*') THEN
  BEGIN

      SELECT COUNT(*)
      FROM (
          -- Сотрудники
          SELECT L14.OBJ_ID
          FROM LINKS L2
          JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
             AND (:I$STAGE_FILTER IN (21, 100))
             AND (:I$OBJ_ID IS NULL OR L14.OBJ_ID = :I$OBJ_ID) AND (:I$GRADE_ID IS NULL OR :I$GRADE_ID = 0) AND (:I$STAGE_ID IS NULL OR :I$STAGE_ID = 0)
          WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
          -- Учащиеся
          UNION
          SELECT L10.OBJ_ID
          FROM LINKS L2
          JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
          JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
          JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0 AND (:V$STAGE_ID IS NULL OR V49.LISTVAL_ID = :V$STAGE_ID)
          JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 125, 187) AND L9.DATE_DEL IS NULL
          JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
             AND (:I$OBJ_ID IS NULL OR L10.OBJ_ID = :I$OBJ_ID) AND (:I$GRADE_ID IS NULL OR L9.OBJ_ID = :I$GRADE_ID) AND (:I$STAGE_ID IS NULL OR V49.LISTVAL_ID = :I$STAGE_ID)
          WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      )
      INTO :CNT;

      SUSPEND;
      EXIT;

  END

  CNT = 1;

  FOR
      SELECT FIRST (:I$COUNT) SKIP (:I$FROM)
          OBJ_ID, OBJ_TYPE_ID, PERSON_NAME, GRADE_ID, GRADE_NAME, STAGE_ID, STAGE_NAME
      FROM (
          -- Сотрудники
          SELECT L14.OBJ_ID as OBJ_ID, L14.OBJ_TYPE_ID as OBJ_TYPE_ID,
              CAST(V59.VAL || ' ' || SUBSTRING(V60.VAL FROM 1 FOR 1) || '.' || COALESCE(SUBSTRING(V61.VAL FROM 1 FOR 1) || '.', '') AS VARCHAR(1000)) as PERSON_NAME,
              0 as GRADE_ID, 'Сотрудник' as GRADE_NAME, 0 as STAGE_ID, 'Сотрудник' as STAGE_NAME
          FROM LINKS L2
          JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
             AND (:I$STAGE_FILTER IN (21, 100))
             AND (:I$OBJ_ID IS NULL OR L14.OBJ_ID = :I$OBJ_ID) AND (:I$GRADE_ID IS NULL OR :I$GRADE_ID = 0) AND (:I$STAGE_ID IS NULL OR :I$STAGE_ID = 0)
          -- ФИО
          JOIN VALS V59 ON V59.OBJ_ID = L14.OBJ_ID AND V59.PARAM_ID = 59 AND V59.IS_DEL = 0
          JOIN VALS V60 ON V60.OBJ_ID = L14.OBJ_ID AND V60.PARAM_ID = 60 AND V60.IS_DEL = 0
          LEFT JOIN VALS V61 ON V61.OBJ_ID = L14.OBJ_ID AND V61.PARAM_ID = 61 AND V61.IS_DEL = 0
          WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
          -- Учащиеся
          UNION
          SELECT L10.OBJ_ID as OBJ_ID, L10.OBJ_TYPE_ID as OBJ_TYPE_ID,
              CAST(V55.VAL || ' ' || SUBSTRING(V56.VAL FROM 1 FOR 1) || '.' || COALESCE(SUBSTRING(V57.VAL FROM 1 FOR 1) || '.', '') AS VARCHAR(400)) as PERSON_NAME,
              L9.OBJ_ID as GRADE_ID, CAST(C9.CAPTION AS VARCHAR(200)) as GRADE_NAME,
              V49.LISTVAL_ID as STAGE_ID, REPLACE(R49.VAL, ' параллель', '') as STAGE_NAME
          FROM LINKS L2
          JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
          JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
          JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0 AND (:V$STAGE_ID IS NULL OR V49.LISTVAL_ID = :V$STAGE_ID)
          JOIN LISTVALS LV49 ON LV49.LISTVAL_ID = V49.LISTVAL_ID
          JOIN RES R49 ON R49.RES_ID = LV49.RES_ID AND R49.LANG_CODE = 'RU'
          JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 125, 187) AND L9.DATE_DEL IS NULL
          LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C9 ON 1 = 1
          JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
             AND (:I$OBJ_ID IS NULL OR L10.OBJ_ID = :I$OBJ_ID) AND (:I$GRADE_ID IS NULL OR L9.OBJ_ID = :I$GRADE_ID) AND (:I$STAGE_ID IS NULL OR V49.LISTVAL_ID = :I$STAGE_ID)
          -- ФИО
          JOIN VALS V55 ON V55.OBJ_ID = L10.OBJ_ID AND V55.PARAM_ID = 55 AND V55.IS_DEL = 0
          JOIN VALS V56 ON V56.OBJ_ID = L10.OBJ_ID AND V56.PARAM_ID = 56 AND V56.IS_DEL = 0
          LEFT JOIN VALS V57 ON V57.OBJ_ID = L10.OBJ_ID AND V57.PARAM_ID = 57 AND V57.IS_DEL = 0
          WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      )
      ORDER BY :V$SORT_INDEX, 3
      INTO :OBJ_ID, :OBJ_TYPE_ID, :PERSON_NAME, :GRADE_ID, :GRADE_NAME, :STAGE_ID, :STAGE_NAME
  DO
  BEGIN
      EXAM_STATE = 0;
      SUSPEND;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_PERSON_DESC (
    I$OBJ_ID BIGINT,
    I$ZONE SMALLINT = 0,
    I$FIO_ONLY SMALLINT = 0)
RETURNS (
    OBJ_ID BIGINT,
    TYPE_ID BIGINT,
    NAME_LAST VARCHAR(200),
    NAME_FIRST VARCHAR(200),
    NAME_MID VARCHAR(200),
    NAME_FULL VARCHAR(400),
    BIRTH_DATE DATE,
    OU_ID BIGINT,
    OU_NAME VARCHAR(200),
    AREA_ID BIGINT,
    AREA_NAME VARCHAR(200),
    STAGE_ID BIGINT,
    STAGE_NAME VARCHAR(100),
    CLASS_ID BIGINT,
    CLASS_NAME VARCHAR(100),
    NAME_ALIAS VARCHAR(400))
AS
DECLARE VARIABLE V$MULT BIGINT;
DECLARE VARIABLE V$GEN BIGINT;
begin

  OBJ_ID = I$OBJ_ID;

  -- ФИО и дата рождения
  SELECT FIRST 1 O.TYPE_ID, V55.VAL, V56.VAL, V57.VAL, V89.VAL
  FROM OBJECTS O
  JOIN VALS V55 ON V55.OBJ_ID = O.OBJ_ID AND V55.PARAM_ID IN (55, 59, 827) AND V55.IS_DEL = 0
  JOIN VALS V56 ON V56.OBJ_ID = O.OBJ_ID AND V56.PARAM_ID IN (56, 60, 828) AND V56.IS_DEL = 0
  LEFT JOIN VALS V57 ON V57.OBJ_ID = O.OBJ_ID AND V57.PARAM_ID IN (57, 61, 829) AND V57.IS_DEL = 0
  LEFT JOIN VALD V89 ON V89.OBJ_ID = O.OBJ_ID AND V89.PARAM_ID IN (89, 241, 830) AND V89.IS_DEL = 0 AND :I$FIO_ONLY = 0
  WHERE O.OBJ_ID = :I$OBJ_ID
  INTO :TYPE_ID, :NAME_LAST, :NAME_FIRST, :NAME_MID, :BIRTH_DATE;

  NAME_FULL = NAME_LAST || ' ' || NAME_FIRST || COALESCE(' ' || NAME_MID, '');

  -- 0 = белая зона, 1 = черная зона, 2 - серая (неизвестная)
  IF(I$ZONE <> 1) THEN -- OR TYPE_ID  = 14
    NAME_ALIAS = NAME_FULL;
  ELSE
  BEGIN
    SELECT FIRST 1 V2991.VAL
    FROM VALS V2991
    WHERE V2991.OBJ_ID = :I$OBJ_ID AND V2991.PARAM_ID = 2991 AND V2991.IS_DEL = 0
    INTO :NAME_ALIAS;

    IF(NAME_ALIAS IS NULL) THEN
    BEGIN
      SELECT FIRST 1 V2153.VAL
      FROM VALS V2153
      WHERE V2153.OBJ_ID = :I$OBJ_ID AND V2153.PARAM_ID IN (2153, 2152) AND V2153.IS_DEL = 0
      INTO :NAME_ALIAS;
      IF(NAME_ALIAS IS NULL) THEN
      BEGIN
        SELECT MULTIPLIER, GEN
        FROM GEN
        INTO :V$MULT, :V$GEN;
        NAME_ALIAS = V$GEN;
        IF(TYPE_ID = 14) THEN NAME_ALIAS = NAME_ALIAS || 't'; ELSE NAME_ALIAS = NAME_ALIAS || 'p';
        NAME_ALIAS = NAME_ALIAS || (I$OBJ_ID - TRUNC(I$OBJ_ID / V$MULT) * V$MULT);
      END
    END
    -- заменяем ФИО на алиасы в черной зоне, redmine #1060
    NAME_FULL = NAME_ALIAS;
  END

  -- заполняем поля (кроме ФИО) только при :I$FIO_ONLY=0, redmine #1060
  IF (I$FIO_ONLY = 0) then
  BEGIN
    IF(TYPE_ID = 14) THEN
    BEGIN
      STAGE_NAME = 'Сотрудник';
      CLASS_NAME = 'Сотрудник';

      -- Восстанавливаем реквизиты ОУ
      SELECT FIRST 1 LP2.PARENT_ID
      FROM LINKS LP2
      WHERE LP2.OBJ_ID = :I$OBJ_ID AND LP2.PARENT_TYPE_ID = 2 AND LP2.DATE_DEL IS NULL
      INTO :OU_ID;

      -- Уволенный ?
      IF(OU_ID IS NULL) THEN
      BEGIN
        SELECT FIRST 1 LP2.PARENT_ID
        FROM LINKS LP84
        JOIN LINKS LP2 ON LP2.OBJ_ID = LP84.PARENT_ID AND LP2.PARENT_TYPE_ID = 2 AND LP2.DATE_DEL IS NULL
        WHERE LP84.OBJ_ID = :I$OBJ_ID AND LP84.PARENT_TYPE_ID = 84 AND LP84.DATE_DEL IS NULL
        INTO :OU_ID;
      END

    END
    ELSE
    BEGIN

      -- Восстанавливаем реквизиты ОУ, класса и уровня
      SELECT FIRST 1 LP2.PARENT_ID, V49.LISTVAL_ID, R.VAL, LP9.PARENT_ID, LV.TAG || COALESCE(' ' || V54.VAL, '')
      FROM LINKS LP9
      LEFT JOIN VALS V54 ON V54.OBJ_ID = LP9.PARENT_ID AND V54.PARAM_ID IN (54, 1652) AND V54.IS_DEL = 0
      JOIN LINKS LP8 ON LP8.OBJ_ID = LP9.PARENT_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
      JOIN VALL V49 ON V49.OBJ_ID = LP8.PARENT_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
      JOIN LISTVALS LV ON LV.LISTVAL_ID = V49.LISTVAL_ID
      JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
      JOIN LINKS LP7 ON LP7.OBJ_ID = LP8.PARENT_ID AND LP7.PARENT_TYPE_ID IN (7, 502) AND LP7.DATE_DEL IS NULL
      JOIN LINKS LP2 ON LP2.OBJ_ID = LP7.PARENT_ID AND LP2.PARENT_TYPE_ID = 2 AND LP2.DATE_DEL IS NULL
      WHERE LP9.OBJ_ID = :I$OBJ_ID AND LP9.PARENT_TYPE_ID IN (9, 187, 125) AND LP9.DATE_DEL IS NULL
      ORDER BY LP9.PARENT_TYPE_ID
      INTO :OU_ID, :STAGE_ID, :STAGE_NAME, :CLASS_ID, :CLASS_NAME;

      -- Выбывший ?
      IF(OU_ID IS NULL) THEN
      BEGIN
        SELECT FIRST 1 LP2.PARENT_ID
        FROM LINKS LP84
        JOIN LINKS LP2 ON LP2.OBJ_ID = LP84.PARENT_ID AND LP2.PARENT_TYPE_ID = 2 AND LP2.DATE_DEL IS NULL
        WHERE LP84.OBJ_ID = :I$OBJ_ID AND LP84.PARENT_TYPE_ID = 84 AND LP84.DATE_DEL IS NULL
        INTO :OU_ID;
      END

    END

    -- Реквизиты ОУ
    SELECT FIRST 1 SUBSTRING(V2.VAL FROM 1 FOR 200), V2163.LISTVAL_ID, R.VAL
    FROM VALS V2
    LEFT JOIN VALL V2163 ON V2163.OBJ_ID = V2.OBJ_ID AND V2163.PARAM_ID = 2163 AND V2163.IS_DEL = 0
    LEFT JOIN LISTVALS LV ON LV.LISTVAL_ID = V2163.LISTVAL_ID
    LEFT JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
    WHERE V2.OBJ_ID = :OU_ID AND V2.PARAM_ID = 2 AND V2.IS_DEL = 0
    INTO :OU_NAME, :AREA_ID, :AREA_NAME;
  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_PERSON_EXAMS_GET (
    I$USER_ID BIGINT,
    I$ACTIVE SMALLINT = NULL)
RETURNS (
    OBJ_ID BIGINT,
    SESSION_ID BIGINT,
    EXAM_NAME VARCHAR(200),
    EXAM_LOCATION VARCHAR(200),
    EXAM_DATE_START TIMESTAMP,
    EXAM_DATE_END TIMESTAMP,
    DURATION INTEGER,
    EXAM_DATE_EXEC TIMESTAMP,
    EXAM_STATE VARCHAR(100),
    SESSION_STATE_ID INTEGER,
    SESSION_STATE VARCHAR(100),
    EXAM_RESULT VARCHAR(100),
    VARIANT_NAME VARCHAR(100),
    RAW_RESULT INTEGER,
    DATE_CLASS VARCHAR(40))
AS
DECLARE VARIABLE V$PERSON_ID BIGINT;
DECLARE VARIABLE V$EXAM_STATE INTEGER;
begin
  -- По USER_ID определяем персону
  SELECT U.OBJ_ID FROM USERS U WHERE U.USER_ID = :I$USER_ID INTO :V$PERSON_ID;

  -- Назначены всем ?
  -- * Тестирование без планирования участников, тестируем всех желающих?

  -- * сессия еще не назначена?
  -- * в UT_EXAM_TITLE_GET отдаем тестирование без проверки на назначение
  -- * создадим назначение в момент, когда тестируемый нажал кнопку Начать тест
  FOR
    SELECT ED.OBJ_ID, ED.OBJ_NAME, '-', ED.EXAM_DATE_START, ED.EXAM_DATE_END, ED.DURATION,
      NULL, ES.OBJ_NAME, SS.STATE_ID, SS.STATE_NAME, ''
    FROM UT_EXAM_DATES ED
    -- * в списке тестов должны показываться только электронные
    JOIN UT_EXAM_STATES ES ON ES.OBJ_ID = ED.EXAM_STATE
    JOIN UT_SESSION_STATES SS ON SS.STATE_ID = 0
      AND NOT EXISTS (SELECT FIRST 1 1 FROM UT_SESSIONS S WHERE S.ED_ID = ED.OBJ_ID AND S.DATE_DEL IS NULL AND S.PERSON_ID = :V$PERSON_ID)
    WHERE ED.DATE_DEL IS NULL AND ED.EXAM_STATE >= 550 AND ED.PLAN_METHOD_ID = 3 AND ED.METHOD_ID IN (0, 1)
      AND (:I$ACTIVE IS NULL OR (:I$ACTIVE = 1 AND ED.EXAM_STATE = 600))
    ORDER BY ED.EXAM_DATE_START, ED.EXAM_STATE
    INTO :OBJ_ID, :EXAM_NAME, :EXAM_LOCATION, :EXAM_DATE_START, :EXAM_DATE_END, :DURATION,
      :EXAM_DATE_EXEC, :EXAM_STATE, :SESSION_STATE_ID, :SESSION_STATE, :EXAM_RESULT
  DO
  BEGIN
    IF(EXAM_DATE_START < CURRENT_DATE) THEN
    BEGIN
      IF(EXAM_DATE_END <= CURRENT_DATE) THEN DATE_CLASS = 'urgent';
      ELSE DATE_CLASS = 'late';
    END
    ELSE IF(EXAM_DATE_START = CURRENT_DATE) THEN DATE_CLASS = 'today';
    ELSE DATE_CLASS = 'future';
    SUSPEND;
  END

  -- * тестирования с назначением

  -- Назначения на тесты в статусе 600+, где еще не было сдачи
  SESSION_ID = NULL;
  FOR
    SELECT EPA.EXAM_ID, ED.OBJ_NAME, '-', ED.EXAM_DATE_START, ED.EXAM_DATE_END, ED.DURATION,
      NULL, ES.OBJ_NAME, SS.STATE_ID, SS.STATE_NAME, '', NULL
    FROM UT_EXAM_PERSON_ASSN EPA
    -- * в списке тестов должны показываться только электронные
    JOIN UT_EXAM_DATES ED ON ED.OBJ_ID = EPA.EXAM_ID AND ED.DATE_DEL IS NULL AND ED.EXAM_STATE >= 600 AND ED.METHOD_ID IN (0, 1)
    JOIN UT_EXAM_STATES ES ON ES.OBJ_ID = ED.EXAM_STATE
    JOIN UT_SESSION_STATES SS ON SS.STATE_ID = 0
    WHERE EPA.DATE_DEL IS NULL AND EPA.PERSON_ID = :V$PERSON_ID
      AND NOT EXISTS (SELECT FIRST 1 1 FROM UT_SESSIONS S WHERE S.ED_ID = ED.OBJ_ID AND S.DATE_DEL IS NULL AND S.PERSON_ID = EPA.PERSON_ID)
       AND (:I$ACTIVE IS NULL OR (:I$ACTIVE = 1 AND ED.EXAM_STATE = 600))
    ORDER BY ED.EXAM_DATE_START, ED.EXAM_STATE
    INTO :OBJ_ID, :EXAM_NAME, :EXAM_LOCATION, :EXAM_DATE_START, :EXAM_DATE_END, :DURATION,
      :EXAM_DATE_EXEC, :EXAM_STATE, :SESSION_STATE_ID, :SESSION_STATE, :EXAM_RESULT, :RAW_RESULT
  DO
  BEGIN
    IF(EXAM_DATE_START < CURRENT_DATE) THEN
    BEGIN
      IF(EXAM_DATE_END <= CURRENT_DATE) THEN DATE_CLASS = 'urgent';
      ELSE DATE_CLASS = 'late';
    END
    ELSE IF(EXAM_DATE_START = CURRENT_DATE) THEN DATE_CLASS = 'today';
    ELSE DATE_CLASS = 'future';
    SUSPEND;
  END

  -- Сессии тестирования - в любой фазе теста
  -- Внимание: ID будут
  FOR
    SELECT S.OBJ_ID, EPA.EXAM_ID, ED.OBJ_NAME, '-', ED.EXAM_DATE_START, ED.EXAM_DATE_END, ED.DURATION,
      S.STARTED_AT, ES.OBJ_NAME, SS.STATE_ID, SS.STATE_NAME, MT.MARK_SHORTNAME, S.RAW_RESULT, ED.EXAM_STATE
    FROM UT_SESSIONS S
    -- * в списке тестов должны показываться только электронные
    JOIN UT_EXAM_DATES ED ON ED.OBJ_ID = S.ED_ID AND ED.DATE_DEL IS NULL AND ED.EXAM_STATE >= 600 AND ED.METHOD_ID IN (0, 1)
    JOIN UT_EXAM_PERSON_ASSN EPA ON EPA.EXAM_ID = ED.OBJ_ID AND EPA.PERSON_ID = S.PERSON_ID
    JOIN UT_EXAM_STATES ES ON ES.OBJ_ID = ED.EXAM_STATE
    JOIN UT_SESSION_STATES SS ON SS.STATE_ID = S.STATE_ID
    LEFT JOIN CJ2_MARK_TYPE MT ON MT.MARK_TYPE_ID = S.FINAL_RESULT_ID
    WHERE S.PERSON_ID = :V$PERSON_ID AND S.DATE_DEL IS NULL AND :I$ACTIVE IS NULL
    ORDER BY S.STARTED_AT
    INTO :SESSION_ID, :OBJ_ID, :EXAM_NAME, :EXAM_LOCATION, :EXAM_DATE_START, :EXAM_DATE_END, :DURATION,
      :EXAM_DATE_EXEC, :EXAM_STATE, :SESSION_STATE_ID, :SESSION_STATE, :EXAM_RESULT, :RAW_RESULT, :V$EXAM_STATE
  DO
  BEGIN
    -- Запарываем поля результата, пока тест не завершился, кроме случая когда разрешено показывать
    IF(V$EXAM_STATE < 1000) THEN
    BEGIN
      EXAM_RESULT = NULL;
      RAW_RESULT = NULL;
    END
    DATE_CLASS = 'done';
    SUSPEND;
  END

  -- Если запросили активные - то уже сданные сессии показываем только последний экземпляр
  IF(I$ACTIVE = 1) THEN
  FOR
    SELECT S.OBJ_ID, EPA.EXAM_ID, ED.OBJ_NAME, '-', ED.EXAM_DATE_START, ED.EXAM_DATE_END, ED.DURATION,
      S.STARTED_AT, ES.OBJ_NAME, SS.STATE_ID, SS.STATE_NAME, MT.MARK_SHORTNAME, S.RAW_RESULT, ED.EXAM_STATE
    FROM UT_SESSIONS S
    -- * в списке тестов должны показываться только электронные
    JOIN UT_EXAM_DATES ED ON ED.OBJ_ID = S.ED_ID AND ED.DATE_DEL IS NULL AND ED.EXAM_STATE >= 600 AND ED.METHOD_ID IN (0, 1)
    JOIN UT_EXAM_PERSON_ASSN EPA ON EPA.EXAM_ID = ED.OBJ_ID AND EPA.PERSON_ID = S.PERSON_ID
    JOIN UT_EXAM_STATES ES ON ES.OBJ_ID = ED.EXAM_STATE
    JOIN UT_SESSION_STATES SS ON SS.STATE_ID = S.STATE_ID
    LEFT JOIN CJ2_MARK_TYPE MT ON MT.MARK_TYPE_ID = S.FINAL_RESULT_ID
    WHERE S.PERSON_ID = :V$PERSON_ID AND S.DATE_DEL IS NULL AND NOT EXISTS(
      SELECT FIRST 1 1
      FROM UT_SESSIONS S2
      WHERE S2.DATE_DEL IS NULL AND S2.ED_ID = S.ED_ID AND S2.PERSON_ID = S.PERSON_ID AND S2.OBJ_ID > S.OBJ_ID
    )
    ORDER BY S.STARTED_AT
    INTO :SESSION_ID, :OBJ_ID, :EXAM_NAME, :EXAM_LOCATION, :EXAM_DATE_START, :EXAM_DATE_END, :DURATION,
      :EXAM_DATE_EXEC, :EXAM_STATE, :SESSION_STATE_ID, :SESSION_STATE, :EXAM_RESULT, :RAW_RESULT, :V$EXAM_STATE
  DO
  BEGIN
    -- Запарываем поля результата, пока тест не завершился, кроме случая когда разрешено показывать
    IF(V$EXAM_STATE < 1000) THEN
    BEGIN
      EXAM_RESULT = NULL;
      RAW_RESULT = NULL;
    END
    DATE_CLASS = 'done';
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_PERSON_EXAM_ADD_LIST (
    I$PERSON_ID BIGINT,
    I$USER_ID VARCHAR(40),
    I$PERSON_TYPE SMALLINT = 0)
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(1000))
AS
declare variable V$ID bigint;
declare variable V$DATE date;
declare variable V$DAY_TYPE_ID integer;
declare variable V$DAY_TYPE_NAME varchar(200);
declare variable V$NAME varchar(1000);
declare variable V$YEAR integer;
declare variable V$YEAR_ID bigint;
begin

  -- Список открытых тестирований, где человек не назначен
  TAG_NAME = 'items';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'items::json&colon;array';
  VAL = '1';
  SUSPEND;

  -- Для уровня школы берем заданный текущий период
  SELECT FIRST 1 V1236.LISTVAL_ID
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$YEAR_ID;

  -- Для района и региона берем текущий учебный год
  IF(V$YEAR_ID IS NULL) THEN
  BEGIN
      V$YEAR = EXTRACT(YEAR FROM CURRENT_DATE);
      IF(EXTRACT(MONTH FROM CURRENT_DATE) < 9) THEN V$YEAR = V$YEAR - 1;
      SELECT FIRST 1 L.LISTVAL_ID
      FROM LISTVALS L
      WHERE L.LIST_ID = 29 AND L.IS_DEL = 0 AND L.COST = :V$YEAR
      INTO :V$YEAR_ID;
  END

  IF(I$PERSON_TYPE = 0) THEN
  BEGIN

      -- Участники тестирования

      FOR
          SELECT D.OBJ_ID, D.EXAM_DATE_START, D.EXAM_DAY_TYPE, DT.OBJ_NAME, D.OBJ_NAME
          FROM UT_EXAM_DATES D
          JOIN UT_EXAM_DAY_TYPES DT ON DT.OBJ_ID = D.EXAM_DAY_TYPE
          LEFT JOIN UT_EXAM_PERSON_ASSN PA ON PA.EXAM_ID = D.OBJ_ID AND PA.PERSON_ID = :I$PERSON_ID AND PA.DATE_DEL IS NULL
          WHERE D.DATE_DEL IS NULL AND D.EXAM_STATE > 0 AND D.EXAM_STATE <= 600 AND PA.OBJ_ID IS NULL
              AND D.PLAN_METHOD_ID <> 3 -- кроме свободных тестирований
              AND D.EXAM_DAY_TYPE <> 100 -- кроме олимпиад
              AND (D.PERIOD_ID IS NULL OR D.PERIOD_ID = :V$YEAR_ID)
          ORDER BY D.EXAM_DATE_START, D.OBJ_NAME
          INTO :V$ID, :V$DATE, :V$DAY_TYPE_ID, :V$DAY_TYPE_NAME, :V$NAME
      DO
      BEGIN
          TAG_NAME = 'items:p';
          VAL = NULL;
          SUSPEND;
          TAG_NAME = 'items:p:id';
          VAL = V$ID;
          SUSPEND;
          TAG_NAME = 'items:p:name';
          VAL = V$NAME;
          SUSPEND;
          TAG_NAME = 'items:p:date';
          VAL = (SELECT RESULT FROM DATE2STR(:V$DATE));
          SUSPEND;
          TAG_NAME = 'items:p:day_type';
          VAL = V$DAY_TYPE_NAME;
          SUSPEND;
          TAG_NAME = 'items:p:day_type_id';
          VAL = V$DAY_TYPE_ID;
          SUSPEND;
      END

  END
  ELSE IF(I$PERSON_TYPE = 1) THEN
  BEGIN

      -- Сотрудники

      FOR
          SELECT D.OBJ_ID, D.EXAM_DATE_START, D.EXAM_DAY_TYPE, DT.OBJ_NAME, D.OBJ_NAME
          FROM UT_EXAM_DATES D
          JOIN UT_EXAM_DAY_TYPES DT ON DT.OBJ_ID = D.EXAM_DAY_TYPE
          --LEFT JOIN UT_EXAM_STUFF_ASSN SA ON SA.EXAM_ID = D.OBJ_ID AND SA.PERSON_ID = :I$PERSON_ID AND SA.DATE_DEL IS NULL
          WHERE D.DATE_DEL IS NULL AND D.EXAM_STATE > 0 AND D.EXAM_STATE <= 600 -- AND SA.OBJ_ID IS NULL
              AND D.EXAM_DAY_TYPE <> 100 -- кроме олимпиад
              AND (D.PERIOD_ID IS NULL OR D.PERIOD_ID = :V$YEAR_ID)
          ORDER BY D.EXAM_DATE_START, D.OBJ_NAME
          INTO :V$ID, :V$DATE, :V$DAY_TYPE_ID, :V$DAY_TYPE_NAME, :V$NAME
      DO
      BEGIN
          TAG_NAME = 'items:p';
          VAL = NULL;
          SUSPEND;
          TAG_NAME = 'items:p:id';
          VAL = V$ID;
          SUSPEND;
          TAG_NAME = 'items:p:name';
          VAL = V$NAME;
          SUSPEND;
          TAG_NAME = 'items:p:date';
          VAL = (SELECT RESULT FROM DATE2STR(:V$DATE));
          SUSPEND;
          TAG_NAME = 'items:p:day_type';
          VAL = V$DAY_TYPE_NAME;
          SUSPEND;
          TAG_NAME = 'items:p:day_type_id';
          VAL = V$DAY_TYPE_ID;
          SUSPEND;
      END

  END
  ELSE IF(I$PERSON_TYPE = 2) THEN
  BEGIN

      -- Эксперты

      FOR
          SELECT D.OBJ_ID, D.EXAM_DATE_START, D.EXAM_DAY_TYPE, DT.OBJ_NAME, D.OBJ_NAME
          FROM UT_EXAM_DATES D
          JOIN UT_EXAM_DAY_TYPES DT ON DT.OBJ_ID = D.EXAM_DAY_TYPE
          LEFT JOIN UT_EXAM_EXPERT_ASSN EA ON EA.EXAM_ID = D.OBJ_ID AND EA.EXPERT_ID = :I$PERSON_ID AND EA.DATE_DEL IS NULL
          WHERE D.DATE_DEL IS NULL AND D.EXAM_STATE > 0 AND D.EXAM_STATE <= 600 AND EA.OBJ_ID IS NULL
              AND D.EXAM_DAY_TYPE <> 100 -- кроме олимпиад
              AND (D.PERIOD_ID IS NULL OR D.PERIOD_ID = :V$YEAR_ID)
          ORDER BY D.EXAM_DATE_START, D.OBJ_NAME
          INTO :V$ID, :V$DATE, :V$DAY_TYPE_ID, :V$DAY_TYPE_NAME, :V$NAME
      DO
      BEGIN
          TAG_NAME = 'items:p';
          VAL = NULL;
          SUSPEND;
          TAG_NAME = 'items:p:id';
          VAL = V$ID;
          SUSPEND;
          TAG_NAME = 'items:p:name';
          VAL = V$NAME;
          SUSPEND;
          TAG_NAME = 'items:p:date';
          VAL = (SELECT RESULT FROM DATE2STR(:V$DATE));
          SUSPEND;
          TAG_NAME = 'items:p:day_type';
          VAL = V$DAY_TYPE_NAME;
          SUSPEND;
          TAG_NAME = 'items:p:day_type_id';
          VAL = V$DAY_TYPE_ID;
          SUSPEND;
      END

      TAG_NAME = 'roles';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'roles::json&colon;array';
      VAL = '1';
      SUSPEND;
      FOR
          SELECT R.OBJ_ID, R.OBJ_NAME
          FROM UT_EXPERT_ROLES R
          WHERE R.DATE_DEL IS NULL
          ORDER BY R.OBJ_ID
          INTO :V$ID, :V$NAME
      DO
      BEGIN
          TAG_NAME = 'roles:p';
          VAL = NULL;
          SUSPEND;
          TAG_NAME = 'roles:p:id';
          VAL = V$ID;
          SUSPEND;
          TAG_NAME = 'roles:p:name';
          VAL = V$NAME;
          SUSPEND;
      END

  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_PERSON_EXAM_ASSNS_LIST (
    I$PERSON_ID BIGINT,
    I$PERIOD_ID INTEGER,
    I$USER_ID VARCHAR(40) = null)
RETURNS (
    OBJ_ID BIGINT,
    EXAM_ID BIGINT,
    EXAM_NAME VARCHAR(200),
    EXAM_DATE DATE,
    STATE INTEGER)
AS
declare variable V$DATE_FROM date;
declare variable V$DATE_TO date;
begin
  -- В версии для FB в качестве PERIOD_ID передаем год, соответствующий началу учебного года
  IF(I$PERIOD_ID IS NOT NULL) THEN
  BEGIN
      V$DATE_FROM = '01.09.' || I$PERIOD_ID;
      V$DATE_TO = '31.08.' || (I$PERIOD_ID + 1);
  END

  FOR
      SELECT PA.OBJ_ID, D.OBJ_ID, D.OBJ_NAME, D.EXAM_DATE_START, D.STAGE_ID
      FROM UT_EXAM_PERSON_ASSN PA
      JOIN UT_EXAM_DATES D ON D.OBJ_ID = PA.EXAM_ID AND D.DATE_DEL IS NULL
         AND (:V$DATE_TO IS NULL OR D.EXAM_DATE_START <= :V$DATE_TO)
         AND (:V$DATE_FROM IS NULL OR D.EXAM_DATE_END >= :V$DATE_FROM)
      WHERE PA.PERSON_ID = :I$PERSON_ID AND PA.DATE_DEL IS NULL
      ORDER BY D.EXAM_DATE_START
      INTO :OBJ_ID, :EXAM_ID, :EXAM_NAME, :EXAM_DATE, :STATE
  DO
  BEGIN
      SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_PLACES_LEVEL_UA_LIST (
    I$EXAM_ID BIGINT,
    I$PPE_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$LEVEL INTEGER)
RETURNS (
    OBJ_ID BIGINT)
AS
begin

  IF(I$LEVEL = 0) THEN
  BEGIN
      -- Все участники
      FOR
          SELECT PA.PERSON_ID
          FROM UT_PERSON_PPE_ASSN PA
          LEFT JOIN UT_PERSON_PLACE_ASSN A ON A.DATE_DEL IS NULL AND A.EXAM_ID = PA.EXAM_ID AND A.PERSON_ID = PA.PERSON_ID
          WHERE PA.DATE_DEL IS NULL AND PA.EXAM_ID = :I$EXAM_ID AND PA.PPE_ID = :I$PPE_ID AND A.OBJ_ID IS NULL
          INTO :OBJ_ID
      DO
      BEGIN
          SUSPEND;
      END
  END
  ELSE IF(I$LEVEL = 1) THEN
  BEGIN
      -- Конретная ОУ
      FOR
          SELECT PA.PERSON_ID
          FROM UT_PERSON_PPE_ASSN PA
          JOIN LINKS LP2 ON LP2.OBJ_ID = PA.PERSON_ID AND LP2.PARENT_TYPE_ID = 2 AND LP2.PARENT_ID = :I$OBJ_ID AND LP2.DATE_DEL IS NULL
          LEFT JOIN UT_PERSON_PLACE_ASSN A ON A.DATE_DEL IS NULL AND A.EXAM_ID = PA.EXAM_ID AND A.PERSON_ID = PA.PERSON_ID
          WHERE PA.DATE_DEL IS NULL AND PA.EXAM_ID = :I$EXAM_ID AND PA.PPE_ID = :I$PPE_ID AND A.OBJ_ID IS NULL
          UNION
          SELECT PA.PERSON_ID
          FROM UT_PERSON_PPE_ASSN PA
          JOIN LINKS LP9 ON LP9.OBJ_ID = PA.PERSON_ID AND LP9.PARENT_TYPE_ID IN (9, 125, 187) AND LP9.DATE_DEL IS NULL
          JOIN LINKS LP8 ON LP8.OBJ_ID = LP9.PARENT_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
          JOIN LINKS LP7 ON LP7.OBJ_ID = LP8.PARENT_ID AND LP7.PARENT_TYPE_ID IN (7, 502) AND LP7.DATE_DEL IS NULL
          JOIN LINKS LP2 ON LP2.OBJ_ID = LP7.PARENT_ID AND LP2.PARENT_TYPE_ID = 2 AND LP2.PARENT_ID = :I$OBJ_ID AND LP2.DATE_DEL IS NULL
          LEFT JOIN UT_PERSON_PLACE_ASSN A ON A.DATE_DEL IS NULL AND A.EXAM_ID = PA.EXAM_ID AND A.PERSON_ID = PA.PERSON_ID
          WHERE PA.DATE_DEL IS NULL AND PA.EXAM_ID = :I$EXAM_ID AND PA.PPE_ID = :I$PPE_ID AND A.OBJ_ID IS NULL
          INTO :OBJ_ID
      DO
      BEGIN
          SUSPEND;
      END
  END
  ELSE IF(I$LEVEL = 2) THEN
  BEGIN
      -- Конкретный коллектив
      FOR
          SELECT PA.PERSON_ID
          FROM UT_PERSON_PPE_ASSN PA
          JOIN LINKS LPG ON LPG.OBJ_ID = PA.PERSON_ID AND LPG.PARENT_TYPE_ID IN (2, 84, 9, 125, 187) AND LPG.PARENT_ID = :I$OBJ_ID AND LPG.DATE_DEL IS NULL
          LEFT JOIN UT_PERSON_PLACE_ASSN A ON A.DATE_DEL IS NULL AND A.EXAM_ID = PA.EXAM_ID AND A.PERSON_ID = PA.PERSON_ID
          WHERE PA.DATE_DEL IS NULL AND PA.EXAM_ID = :I$EXAM_ID AND PA.PPE_ID = :I$PPE_ID AND A.OBJ_ID IS NULL
          INTO :OBJ_ID
      DO
      BEGIN
          SUSPEND;
      END
  END
  ELSE IF(I$LEVEL = 3) THEN
  BEGIN
      -- Конкретный участник
      FOR
          SELECT PA.PERSON_ID
          FROM UT_PERSON_PPE_ASSN PA
          LEFT JOIN UT_PERSON_PLACE_ASSN A ON A.DATE_DEL IS NULL AND A.EXAM_ID = PA.EXAM_ID AND A.PERSON_ID = PA.PERSON_ID
          WHERE PA.DATE_DEL IS NULL AND PA.EXAM_ID = :I$EXAM_ID AND PA.PPE_ID = :I$PPE_ID AND PA.PERSON_ID = :I$OBJ_ID AND A.OBJ_ID IS NULL
          INTO :OBJ_ID
      DO
      BEGIN
          SUSPEND;
      END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_PPE_DELETE (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    ERROR_TEXT VARCHAR(100))
AS
declare variable V$OBJ_ID bigint;
declare variable V$ORG_ID bigint;
begin

  SELECT D.OBJ_ID, D.ORG_ID
  FROM UT_PPE D
  WHERE D.OBJ_ID = :I$OBJ_ID AND D.DATE_DEL IS NULL
  INTO :V$OBJ_ID, :V$ORG_ID;
  
  IF(V$OBJ_ID IS NOT NULL) THEN EXCEPTION DATA_ERROR 'Запись ППЭ не найдена или уже удалена';
  IF(V$ORG_ID IS NOT NULL) THEN EXCEPTION DATA_ERROR 'Нельзя удалить ППЭ, созданную на базе образовательной организации';

  -- Проверяем, есть ли уже рабочее планирование на данный ППЭ

  UPDATE UT_PPE
  SET DATE_DEL = CURRENT_TIMESTAMP
  WHERE OBJ_ID = :I$OBJ_ID;

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_PPE_DESC (
    I$OBJ_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    ORG_ID BIGINT,
    NAME_SHORT VARCHAR(1000),
    NAME_FULL VARCHAR(1000),
    PPE_CODE VARCHAR(40),
    FLAGS INTEGER,
    N_PLACES INTEGER,
    AREA_ID BIGINT,
    AREA_NAME VARCHAR(200),
    IS_OU VARCHAR(10),
    ADDRESS VARCHAR(1000),
    IS_SPEC VARCHAR(10))
AS
declare variable V$SPEC_COUNT smallint;
begin

  SELECT U.OBJ_ID, U.ORG_ID, U.NAME_SHORT, U.NAME_FULL, U.PPE_CODE, U.FLAGS, U.N_PLACES, U.AREA_ID, R.VAL, U.SPEC_COUNT
  FROM UT_PPE U
  LEFT JOIN LISTVALS LV ON LV.LISTVAL_ID = U.AREA_ID
  LEFT JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
  WHERE OBJ_ID = :I$OBJ_ID AND DATE_DEL IS NULL
  INTO :OBJ_ID, :ORG_ID, :NAME_SHORT, :NAME_FULL, :PPE_CODE, :FLAGS, :N_PLACES, :AREA_ID, :AREA_NAME, :V$SPEC_COUNT;

  IF(ORG_ID IS NOT NULL) THEN
  BEGIN

      -- Пока используем полную копию данных, чтобы сохранялось при передаче из региона-района на уровень ниже

  END

  IF(ORG_ID IS NULL) THEN IS_OU = 'Нет'; ELSE IS_OU = 'Да';
  IF(V$SPEC_COUNT = 0) THEN IS_SPEC = 'Нет'; ELSE IS_SPEC = 'Да';

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_PPE_EXAM_ADD_LIST (
    I$PPE_ID BIGINT,
    I$USER_ID VARCHAR(40),
    I$PERSON_TYPE SMALLINT = 0)
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(1000))
AS
declare variable V$ID bigint;
declare variable V$DATE date;
declare variable V$DAY_TYPE_ID integer;
declare variable V$DAY_TYPE_NAME varchar(200);
declare variable V$NAME varchar(1000);
begin

  -- Список открытых тестирований, где человек не назначен
  TAG_NAME = 'items';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'items::json&colon;array';
  VAL = '1';
  SUSPEND;

  FOR
      SELECT D.OBJ_ID, D.EXAM_DATE_START, D.EXAM_DAY_TYPE, DT.OBJ_NAME, D.OBJ_NAME
      FROM UT_EXAM_DATES D
      JOIN UT_EXAM_DAY_TYPES DT ON DT.OBJ_ID = D.EXAM_DAY_TYPE
      LEFT JOIN UT_EXAM_PPE_ASSN PA ON PA.EXAM_ID = D.OBJ_ID AND PA.PPE_ID = :I$PPE_ID AND PA.DATE_DEL IS NULL
      WHERE D.DATE_DEL IS NULL AND D.EXAM_STATE > 0 AND D.EXAM_STATE <= 600 AND PA.OBJ_ID IS NULL
          AND D.PLAN_METHOD_ID <> 3 -- кроме свободных тестирований
      ORDER BY D.EXAM_DATE_START, D.OBJ_NAME
      INTO :V$ID, :V$DATE, :V$DAY_TYPE_ID, :V$DAY_TYPE_NAME, :V$NAME
  DO
  BEGIN
      TAG_NAME = 'items:p';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'items:p:id';
      VAL = V$ID;
      SUSPEND;
      TAG_NAME = 'items:p:name';
      VAL = V$NAME;
      SUSPEND;
      TAG_NAME = 'items:p:date';
      VAL = (SELECT RESULT FROM DATE2STR(:V$DATE));
      SUSPEND;
      TAG_NAME = 'items:p:day_type';
      VAL = V$DAY_TYPE_NAME;
      SUSPEND;
      TAG_NAME = 'items:p:day_type_id';
      VAL = V$DAY_TYPE_ID;
      SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_PPE_EXAM_ASSNS_LIST (
    I$PPE_ID BIGINT,
    I$PERIOD_ID INTEGER,
    I$USER_ID VARCHAR(40) = null)
RETURNS (
    OBJ_ID BIGINT,
    EXAM_ID BIGINT,
    EXAM_NAME VARCHAR(200),
    EXAM_DATE DATE,
    STATE INTEGER)
AS
declare variable V$DATE_FROM date;
declare variable V$DATE_TO date;
begin

  -- В версии для FB в качестве PERIOD_ID передаем год, соответствующий началу учебного года
  IF(I$PERIOD_ID IS NOT NULL) THEN
  BEGIN
      V$DATE_FROM = '01.09.' || I$PERIOD_ID;
      V$DATE_TO = '31.08.' || (I$PERIOD_ID + 1);
  END

  FOR
      SELECT PA.OBJ_ID, D.OBJ_ID, D.OBJ_NAME, D.EXAM_DATE_START, D.STAGE_ID
      FROM UT_EXAM_PPE_ASSN PA
      JOIN UT_EXAM_DATES D ON D.OBJ_ID = PA.EXAM_ID AND D.DATE_DEL IS NULL
         AND (:V$DATE_TO IS NULL OR D.EXAM_DATE_START <= :V$DATE_TO)
         AND (:V$DATE_FROM IS NULL OR D.EXAM_DATE_END >= :V$DATE_FROM)
      WHERE PA.PPE_ID = :I$PPE_ID AND PA.DATE_DEL IS NULL
      ORDER BY D.EXAM_DATE_START
      INTO :OBJ_ID, :EXAM_ID, :EXAM_NAME, :EXAM_DATE, :STATE
  DO
  BEGIN
      SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_PPE_EXAM_ASSN_SET (
    I$PPE_ID BIGINT,
    I$EXAM_ID BIGINT,
    I$STATE SMALLINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$OBJ_ID bigint;
declare variable V$EXAM_STATE smallint;
declare variable V$NAME varchar(1000);
begin

  -- STATE: 0 или 2 = снять регистрацию, 1 = установить регистрацию
  IF(I$STATE IN (0, 2)) THEN
  BEGIN

      SELECT OBJ_ID
      FROM UT_EXAM_PPE_ASSN
      WHERE EXAM_ID = :I$EXAM_ID AND PPE_ID = :I$PPE_ID AND DATE_DEL IS NULL
      INTO :V$OBJ_ID;

      IF(V$OBJ_ID IS NOT NULL) THEN
      BEGIN

          -- Есть действующее назначение. Проверяем, не запланированы ли учащиеся в этот ППЭ
          IF(EXISTS(
              SELECT FIRST 1 1
              FROM UT_PERSON_PPE_ASSN
              WHERE PPE_ID = :I$PPE_ID AND DATE_DEL IS NULL
          ))
          THEN EXCEPTION DATA_ERROR 'Для ППЭ ' || (SELECT NAME_SHORT FROM UT_PPE_DESC(:I$PPE_ID)) || ' есть назначенные участники. Необходимо сначала снять участников';

          UPDATE UT_EXAM_PPE_ASSN
          SET DATE_DEL = CURRENT_TIMESTAMP
          WHERE OBJ_ID = :V$OBJ_ID;

      END

  END
  ELSE IF(I$STATE = 1) THEN
  BEGIN

      -- Устанавливаем назначение
      -- Проверяем валидность ППЭ и статус тестирования
      SELECT EXAM_STATE, OBJ_NAME
      FROM UT_EXAM_DATES
      WHERE OBJ_ID = :I$EXAM_ID AND DATE_DEL IS NULL
      INTO :V$EXAM_STATE, :V$NAME;

      IF(V$EXAM_STATE IS NULL) THEN EXCEPTION DATA_ERROR 'Тестирование не найдено';
      IF(V$EXAM_STATE < 100 OR V$EXAM_STATE > 700) THEN EXCEPTION DATA_ERROR 'Тестирование ' || V$NAME || ' находится в недопустимом статусе, изменение назначений ППЭ недопустимо';

      IF(NOT EXISTS(
          SELECT FIRST 1 1
          FROM UT_PPE
          WHERE OBJ_ID = :I$PPE_ID AND DATE_DEL IS NULL
      ))
      THEN EXCEPTION DATA_ERROR 'ППЭ не найдено или было удалено';

      SELECT OBJ_ID
      FROM UT_EXAM_PPE_ASSN
      WHERE EXAM_ID = :I$EXAM_ID AND PPE_ID = :I$PPE_ID AND DATE_DEL IS NULL
      INTO :V$OBJ_ID;

      IF(V$OBJ_ID IS NULL) THEN
      BEGIN

          INSERT INTO UT_EXAM_PPE_ASSN
          (PPE_ID, EXAM_ID)
          VALUES (:I$PPE_ID, :I$EXAM_ID)
          RETURNING OBJ_ID INTO :OBJ_ID;

      END
      ELSE OBJ_ID = V$OBJ_ID;

  END
  ELSE EXCEPTION DATA_ERROR 'Недопустимый код выбора статуса регистрации ППЭ';

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_PPE_GET (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40) = null)
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(4000))
AS
declare variable V$OBJ_ID bigint;
declare variable V$ORG_ID bigint;
declare variable V$NAME_SHORT varchar(1000);
declare variable V$NAME_FULL varchar(1000);
declare variable V$PPE_CODE varchar(40);
declare variable V$AREA_ID bigint;
declare variable V$TMP bigint;
declare variable V$N_PLACES integer;
declare variable V$FLAGS integer;
declare variable V$N_FLOOR integer;
declare variable V$N_ROWS integer;
declare variable V$N_COLS integer;
declare variable V$IS_ACTIVE integer;
declare variable V$NUM varchar(20);
begin

  -- Выбираем все базовые поля самого ППЭ
  SELECT OBJ_ID, ORG_ID, NAME_SHORT, NAME_FULL, PPE_CODE, FLAGS, N_PLACES, AREA_ID
  FROM UT_PPE_DESC(:I$OBJ_ID)
  INTO :V$OBJ_ID, :V$ORG_ID, :V$NAME_SHORT, :V$NAME_FULL, :V$PPE_CODE, :V$FLAGS, :V$N_PLACES, :V$AREA_ID;

  IF(I$OBJ_ID IS NOT NULL AND V$OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Запись ППЭ не найдена';

  TAG_NAME = 'id';
  VAL = I$OBJ_ID;
  SUSPEND;

  TAG_NAME = 'org_id';
  VAL = V$ORG_ID;
  SUSPEND;

  TAG_NAME = 'name_short';
  VAL = V$NAME_SHORT;
  SUSPEND;

  TAG_NAME = 'name_full';
  VAL = V$NAME_FULL;
  SUSPEND;

  TAG_NAME = 'ppe_code';
  VAL = V$PPE_CODE;
  SUSPEND;

  TAG_NAME = 'area_id';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'area_id:selection';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'area_id:selection::json&colon;array';
  VAL = NULL;
  SUSPEND;
  FOR
      SELECT LISTVAL_ID, VAL
      FROM LISTVALS_LIST(7, 'RU')
      INTO :V$TMP, :V$NAME_FULL
  DO
  BEGIN
      TAG_NAME = 'area_id:selection:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'area_id:selection:r:id';
      VAL = V$TMP;
      SUSPEND;
      TAG_NAME = 'area_id:selection:r:value';
      VAL = V$NAME_FULL;
      SUSPEND;
  END
  TAG_NAME = 'area_id:values:value';
  VAL = V$AREA_ID;
  SUSPEND;

  TAG_NAME = 'flags';
  VAL = V$FLAGS;
  SUSPEND;

  TAG_NAME = 'n_places';
  VAL = V$N_PLACES;
  SUSPEND;

  -- Выбираем список помещений
  TAG_NAME = 'rooms';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'rooms::json&colon;array';
  VAL = '1';
  SUSPEND;

  FOR
      SELECT PR.OBJ_ID, PR.OBJ_NAME, PR.LOCATION, PR.N_FLOOR, PR.ROOM_NUM, PR.PPE_CODE, PR.FLAGS, PR.N_PLACES, PR.IS_ACTIVE, PR.N_ROWS, PR.N_COLS
      FROM UT_PPE_ROOMS PR
      WHERE PR.PPE_ID = :I$OBJ_ID AND PR.DATE_DEL IS NULL
      ORDER BY PR.OBJ_NAME
      INTO :V$OBJ_ID, :V$NAME_SHORT, :V$NAME_FULL, :V$N_FLOOR, :V$NUM, :V$PPE_CODE, :V$FLAGS, :V$N_PLACES, :V$IS_ACTIVE, :V$N_ROWS, :V$N_COLS
  DO
  BEGIN
      TAG_NAME = 'rooms:r';
      VAL = NULL;
      SUSPEND;

      TAG_NAME = 'rooms:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;

      TAG_NAME = 'rooms:r:obj_name';
      VAL = V$NAME_SHORT;
      SUSPEND;

      TAG_NAME = 'rooms:r:location';
      VAL = V$NAME_FULL;
      SUSPEND;

      TAG_NAME = 'rooms:r:n_floor';
      VAL = V$N_FLOOR;
      SUSPEND;

      TAG_NAME = 'rooms:r:room_num';
      VAL = V$NUM;
      SUSPEND;

      TAG_NAME = 'rooms:r:ppe_code';
      VAL = V$PPE_CODE;
      SUSPEND;

      TAG_NAME = 'rooms:r:flags';
      VAL = V$FLAGS;
      SUSPEND;

      TAG_NAME = 'rooms:r:is_active';
      VAL = V$IS_ACTIVE;
      SUSPEND;

      TAG_NAME = 'rooms:r:n_rows';
      VAL = V$N_ROWS;
      SUSPEND;

      TAG_NAME = 'rooms:r:n_cols';
      VAL = V$N_COLS;
      SUSPEND;

      TAG_NAME = 'rooms:r:n_places';
      VAL = V$N_PLACES;
      SUSPEND;

      TAG_NAME = 'rooms:r:map';
      VAL = '';
      SUSPEND;

      TAG_NAME = 'rooms:r:is_used';
      VAL = 0;
      SUSPEND;

      -- Места здесь не отдаем, их запрашиваем отдельным запросом

  END

  -- Назначения на тестирования


end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_PPE_PLACES_GET (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40) = null)
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(4000))
AS
declare variable V$OBJ_ID bigint;
declare variable V$NAME varchar(100);
declare variable V$NR integer;
declare variable V$NC integer;
declare variable V$CX float;
declare variable V$CY float;
declare variable V$CR float;
declare variable V$IS_DELETED smallint;
declare variable V$FLAGS integer;
declare variable V$NUM integer;
begin

  -- Выбираем все базовые поля самого ППЭ
  SELECT OBJ_ID
  FROM UT_PPE_ROOMS R
  WHERE R.OBJ_ID = :I$OBJ_ID AND R.DATE_DEL IS NULL
  INTO :V$OBJ_ID;

  IF(I$OBJ_ID IS NOT NULL AND V$OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Помещение ППЭ не найдено';

  TAG_NAME = 'places';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'places::json&colon;array';
  VAL = NULL;
  SUSPEND;
  FOR
      SELECT P.OBJ_ID, P.PLACE_NUM, P.OBJ_NAME, P.N_ROW, P.N_COL, P.COORD_X, P.COORD_Y, P.COORD_R, P.IS_DELETED, P.FLAGS
      FROM UT_PPE_PLACES P
      WHERE P.ROOM_ID = :I$OBJ_ID AND P.DATE_DEL IS NULL
      ORDER BY P.PLACE_NUM
      INTO :V$OBJ_ID, :V$NUM, :V$NAME, :V$NR, :V$NC, :V$CX, :V$CY, :V$CR, :V$IS_DELETED, :V$FLAGS
  DO
  BEGIN
      TAG_NAME = 'places:r';
      VAL = NULL;
      SUSPEND;

      TAG_NAME = 'places:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;

      TAG_NAME = 'places:r:place_num';
      VAL = V$NUM;
      SUSPEND;

      TAG_NAME = 'places:r:obj_name';
      VAL = V$NAME;
      SUSPEND;

      TAG_NAME = 'places:r:n_row';
      VAL = V$NR;
      SUSPEND;

      TAG_NAME = 'places:r:n_col';
      VAL = V$NC;
      SUSPEND;

      TAG_NAME = 'places:r:coord_x';
      VAL = V$CX;
      SUSPEND;

      TAG_NAME = 'places:r:coord_y';
      VAL = V$CY;
      SUSPEND;

      TAG_NAME = 'places:r:coord_r';
      VAL = V$CR;
      SUSPEND;

      TAG_NAME = 'places:r:is_deleted';
      VAL = V$IS_DELETED;
      SUSPEND;

      TAG_NAME = 'places:r:flags';
      VAL = V$FLAGS;
      SUSPEND;

      TAG_NAME = 'places:r:is_used';
      VAL = 0;
      SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_PPE_PLACES_LIST (
    I$ROOM_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT)
AS
begin

  FOR
      SELECT OBJ_ID
      FROM UT_PPE_PLACES
      WHERE ROOM_ID = :I$ROOM_ID AND DATE_DEL IS NULL
      INTO :OBJ_ID
  DO
  BEGIN
      SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_PPE_PLACE_DELETE (
    I$OBJ_ID BIGINT)
RETURNS (
    ERROR_TEXT VARCHAR(100))
AS
declare variable V$OBJ_ID bigint;
begin

  SELECT D.OBJ_ID
  FROM UT_PPE_PLACES D
  WHERE D.OBJ_ID = :I$OBJ_ID AND D.DATE_DEL IS NULL
  INTO :V$OBJ_ID;
  
  IF(V$OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Место ППЭ не найдено или было удалено';

  -- Проверяем, есть ли уже рабочее планирование на данное место
  -- ...

  UPDATE UT_PPE_PLACES
  SET DATE_DEL = CURRENT_TIMESTAMP
  WHERE OBJ_ID = :I$OBJ_ID;

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_PPE_PLACE_SET (
    I$OBJ_ID BIGINT,
    I$ROOM_ID BIGINT,
    I$PLACE_NUM SMALLINT,
    I$N_ROW SMALLINT,
    I$N_COL SMALLINT,
    I$OBJ_NAME VARCHAR(100),
    I$FLAGS INTEGER,
    I$IS_DELETED SMALLINT,
    I$COORD_X FLOAT,
    I$COORD_Y FLOAT,
    I$COORD_R FLOAT)
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$OBJ_ID bigint;
begin

  IF(I$OBJ_ID IS NULL) THEN
  BEGIN

      INSERT INTO UT_PPE_PLACES
      (ROOM_ID, PLACE_NUM, N_ROW, N_COL, OBJ_NAME, FLAGS, IS_DELETED, COORD_X, COORD_Y, COORD_R)
      VALUES (:I$ROOM_ID, :I$PLACE_NUM, :I$N_ROW, :I$N_COL, :I$OBJ_NAME, :I$FLAGS, :I$IS_DELETED, :I$COORD_X, :I$COORD_Y, :I$COORD_R)
      RETURNING OBJ_ID INTO :OBJ_ID;

  END
  ELSE
  BEGIN

      SELECT OBJ_ID
      FROM UT_PPE_PLACES
      WHERE OBJ_ID = :I$OBJ_ID AND DATE_DEL IS NULL
      INTO :V$OBJ_ID;

      IF(V$OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Место не найдено или было удалено';

      -- Нельзя снимать активность с мест, которые уже запланированы в незавершенные тестирования
      -- ...

      UPDATE UT_PPE_PLACES
      SET PLACE_NUM = :I$PLACE_NUM, N_ROW = :I$N_ROW, N_COL = :I$N_COL, OBJ_NAME = :I$OBJ_NAME,
          FLAGS = :I$FLAGS, IS_DELETED = :I$IS_DELETED, COORD_X = :I$COORD_X, COORD_Y = :I$COORD_Y, COORD_R = :I$COORD_R
      WHERE OBJ_ID = :I$OBJ_ID;

      OBJ_ID = I$OBJ_ID;

  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_PPE_RECALC (
    I$OBJ_ID BIGINT)
RETURNS (
    ERROR_TEXT VARCHAR(10))
AS
declare variable V$ROOM_ID bigint;
declare variable V$ROOM_NAME varchar(100);
declare variable PN integer;
declare variable CN integer;
declare variable N integer;
declare variable N_SPEC integer;
declare variable FLAGS bigint;
begin

  -- Проверяем ошибки с двойным назначением мест
  FOR
      SELECT R.OBJ_ID, R.OBJ_NAME, P.PLACE_NUM, COUNT(*)
      FROM UT_PPE_ROOMS R
      JOIN UT_PPE_PLACES P ON P.ROOM_ID = R.OBJ_ID AND P.DATE_DEL IS NULL
      WHERE R.DATE_DEL IS NULL AND R.PPE_ID = :I$OBJ_ID
      GROUP BY 1, 2, 3
      HAVING COUNT(*) > 1
      INTO :V$ROOM_ID, :V$ROOM_NAME, :PN, :N
  DO
  BEGIN
      EXCEPTION DATA_ERROR 'Двойное назначение номера места в помещении ' || V$ROOM_NAME;
  END

  FOR
      SELECT R.OBJ_ID, R.OBJ_NAME, P.N_ROW, P.N_COL, COUNT(*)
      FROM UT_PPE_ROOMS R
      JOIN UT_PPE_PLACES P ON P.ROOM_ID = R.OBJ_ID AND P.DATE_DEL IS NULL
      WHERE R.DATE_DEL IS NULL AND R.PPE_ID = :I$OBJ_ID
      GROUP BY 1, 2, 3, 4
      HAVING COUNT(*) > 1
      INTO :V$ROOM_ID, :V$ROOM_NAME, :PN, :CN, :N
  DO
  BEGIN
      EXCEPTION DATA_ERROR 'Двойное назначение адреса места в помещении ' || V$ROOM_NAME;
  END

  -- Подсчитываем места
  N_SPEC = 0;

  FOR
      SELECT OBJ_ID, N_ROWS, N_COLS, FLAGS
      FROM UT_PPE_ROOMS
      WHERE DATE_DEL IS NULL AND PPE_ID = :I$OBJ_ID
      INTO :V$ROOM_ID, :PN, :CN, :FLAGS
  DO
  BEGIN

      PN = COALESCE(PN, 0) * COALESCE(CN, 0);

      SELECT COUNT(*)
      FROM UT_PPE_PLACES
      WHERE ROOM_ID = :V$ROOM_ID AND DATE_DEL IS NULL
      INTO :N;

      IF(N <> PN) THEN EXCEPTION DATA_ERROR 'Сохраненное количество мест не соответствует указанной размерности помещения';

      SELECT COUNT(*)
      FROM UT_PPE_PLACES
      WHERE ROOM_ID = :V$ROOM_ID AND DATE_DEL IS NULL AND IS_DELETED = 0
      INTO :N;

      UPDATE UT_PPE_ROOMS
      SET N_PLACES = :N
      WHERE OBJ_ID = :V$ROOM_ID;

      IF(BIN_AND(FLAGS, 1) <> 0) THEN N_SPEC = N_SPEC + 1;

  END

  UPDATE UT_PPE
  SET SPEC_COUNT = :N_SPEC
  WHERE OBJ_ID = :I$OBJ_ID;

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_PPE_ROOMS_LIST (
    I$PPE_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT)
AS
begin

  FOR
      SELECT OBJ_ID
      FROM UT_PPE_ROOMS
      WHERE PPE_ID = :I$PPE_ID AND DATE_DEL IS NULL
      INTO :OBJ_ID
  DO
  BEGIN
      SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_PPE_ROOM_ASSN_GET (
    I$PPE_ID BIGINT,
    I$EXAMS VARCHAR(1000),
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
declare variable V$DATE_FROM date;
declare variable V$DATE_TO date;
declare variable V$NAME_SHORT varchar(1000);
declare variable V$PPE_CODE varchar(40);
declare variable V$AREA_NAME varchar(400);
declare variable V$ADDRESS varchar(1000);
declare variable V$N_PLACES integer;
declare variable V$OBJ_ID bigint;
declare variable V$EXAM_ID bigint;
declare variable V$N_FLOOR integer;
declare variable V$ROOM_NUM varchar(40);
declare variable V$FLAGS integer;
declare variable V$IS_SPEC varchar(10);
declare variable V$DATE date;
declare variable V$DAY_TYPE integer;
declare variable V$SUBJECT_ID bigint;
declare variable S varchar(1000);
declare variable P integer;
begin

   V$FLAGS = EXTRACT(YEAR FROM CURRENT_DATE);
   IF(EXTRACT(MONTH FROM CURRENT_DATE) < 9) THEN V$FLAGS = V$FLAGS - 1;
   V$DATE_FROM = V$FLAGS || '-09-01';
   V$DATE_TO = (V$FLAGS + 1) || '-08-31';

   -- Общие данные по ППЭ
   SELECT NAME_SHORT, N_PLACES, PPE_CODE, AREA_NAME, ADDRESS, FLAGS, IS_SPEC
   FROM UT_PPE_DESC(:I$PPE_ID)
   INTO :V$NAME_SHORT, :V$N_PLACES, :V$PPE_CODE, :V$AREA_NAME, :V$ADDRESS, :V$FLAGS, :V$IS_SPEC;

   TAG_NAME = 'id';
   VAL = I$PPE_ID;
   SUSPEND;

   TAG_NAME = 'name_short';
   VAL = V$NAME_SHORT;
   SUSPEND;

   TAG_NAME = 'ppe_code';
   VAL = V$PPE_CODE;
   SUSPEND;

   TAG_NAME = 'area_name';
   VAL = V$AREA_NAME;
   SUSPEND;

   TAG_NAME = 'address';
   VAL = V$ADDRESS;
   SUSPEND;

   TAG_NAME = 'n_places';
   VAL = V$N_PLACES;
   SUSPEND;

   TAG_NAME = 'flags';
   VAL = V$FLAGS;
   SUSPEND;

   TAG_NAME = 'is_spec';
   VAL = V$IS_SPEC;
   SUSPEND;

   -- Список тестирований - разбираем полученный список с разделителями запятыми
   TAG_NAME = 'exams';
   VAL = NULL;
   SUSPEND;
   TAG_NAME = 'exams::json&colon;array';
   VAL = '1';
   SUSPEND;

   S = I$EXAMS;
   WHILE(CHAR_LENGTH(S) > 0) DO
   BEGIN
       P = POSITION(',' IN S);
       IF(P <= 0) THEN P = CHAR_LENGTH(S) + 1;
       V$OBJ_ID = CAST(SUBSTRING(S FROM 1 FOR P - 1) AS BIGINT);
       S = SUBSTRING(S FROM P + 1);

       -- Если чего-то нет, то и на выходе не будет
       FOR
           SELECT D.EXAM_STATE, D.STATE_NAME, D.EXAM_DATE_START, D.EXAM_DAY_TYPE, D.DAY_TYPE_NAME, D.SUBJECT_ID, D.SUBJECT_NAME
           FROM UT_EXAM_DATES_VIEW D
           WHERE D.OBJ_ID = :V$OBJ_ID AND D.DATE_DEL IS NULL
           ORDER BY D.EXAM_DATE_START, D.SUBJECT_ID, D.EXAM_DAY_TYPE
           INTO :V$FLAGS, :V$AREA_NAME, :V$DATE, :V$DAY_TYPE, :V$NAME_SHORT, :V$SUBJECT_ID, :V$ADDRESS
       DO
       BEGIN
           TAG_NAME = 'exams:r';
           VAL = NULL;
           SUSPEND;

           TAG_NAME = 'exams:r:id';
           VAL = V$OBJ_ID;
           SUSPEND;

           TAG_NAME = 'exams:r:date';
           VAL = V$DATE;
           SUSPEND;

           TAG_NAME = 'exams:r:exam_state';
           VAL = V$FLAGS;
           SUSPEND;

           TAG_NAME = 'exams:r:state_name';
           VAL = V$AREA_NAME;
           SUSPEND;

           TAG_NAME = 'exams:r:day_type';
           VAL = V$IS_SPEC;
           SUSPEND;

           TAG_NAME = 'exams:r:day_type_name';
           VAL = V$NAME_SHORT;
           SUSPEND;

           TAG_NAME = 'exams:r:subject_id';
           VAL = V$SUBJECT_ID;
           SUSPEND;

           TAG_NAME = 'exams:r:subject_name';
           VAL = V$ADDRESS;
           SUSPEND;

           -- Сколько мест надо в этом ППЭ ?
           TAG_NAME = 'exams:r:need_places';
           VAL = (SELECT COUNT(*) FROM UT_PERSON_PPE_ASSN A WHERE A.EXAM_ID = :V$OBJ_ID AND A.PPE_ID = :I$PPE_ID AND A.DATE_DEL IS NULL);
           SUSPEND;
       END

   END

   -- Список помещений
   TAG_NAME = 'rooms';
   VAL = NULL;
   SUSPEND;
   TAG_NAME = 'rooms::json&colon;array';
   VAL = '1';
   SUSPEND;

   FOR
       SELECT R.OBJ_ID, R.PPE_CODE, R.OBJ_NAME, R.LOCATION, R.N_FLOOR, R.ROOM_NUM, R.FLAGS, R.N_PLACES
       FROM UT_PPE_ROOMS R
       WHERE R.PPE_ID = :I$PPE_ID AND R.DATE_DEL IS NULL
       ORDER BY R.N_FLOOR, R.ROOM_NUM
       INTO :V$OBJ_ID, :V$PPE_CODE, :V$AREA_NAME, :V$ADDRESS, :V$N_FLOOR, :V$ROOM_NUM, :V$FLAGS, :V$N_PLACES
   DO
   BEGIN
       TAG_NAME = 'rooms:r';
       VAL = NULL;
       SUSPEND;

       TAG_NAME = 'rooms:r:id';
       VAL = V$OBJ_ID;
       SUSPEND;

       TAG_NAME = 'rooms:r:ppe_code';
       VAL = V$PPE_CODE;
       SUSPEND;

       TAG_NAME = 'rooms:r:obj_name';
       VAL = V$AREA_NAME;
       SUSPEND;

       TAG_NAME = 'rooms:r:location';
       VAL = V$ADDRESS;
       SUSPEND;

       TAG_NAME = 'rooms:r:n_floor';
       VAL = V$N_FLOOR;
       SUSPEND;

       TAG_NAME = 'rooms:r:room_num';
       VAL = V$ROOM_NUM;
       SUSPEND;

       TAG_NAME = 'rooms:r:flags';
       VAL = V$FLAGS;
       SUSPEND;

       TAG_NAME = 'rooms:r:n_places';
       VAL = V$N_PLACES;
       SUSPEND;

       -- Специализация помещений - пока пусто
       TAG_NAME = 'rooms:r:subjects';
       VAL = NULL;
       SUSPEND;
       TAG_NAME = 'rooms:r:subjects::json&colon;array';
       VAL = '1';
       SUSPEND;

       -- Назначения - вадаем все в текущем сезоне
       TAG_NAME = 'rooms:r:assns';
       VAL = NULL;
       SUSPEND;
       TAG_NAME = 'rooms:r:assns::json&colon;array';
       VAL = '1';
       SUSPEND;

       FOR
           SELECT D.OBJ_ID, D.EXAM_DATE_START, 0
           FROM UT_EXAM_ROOM_ASSN A
           JOIN UT_EXAM_DATES D ON D.OBJ_ID = A.EXAM_ID AND D.DATE_DEL IS NULL AND D.EXAM_DATE_START >= :V$DATE_FROM AND D.EXAM_DATE_START <= :V$DATE_TO
           WHERE A.DATE_DEL IS NULL AND A.ROOM_ID = :V$OBJ_ID
           ORDER BY 2, 1
           INTO :V$EXAM_ID, :V$DATE, :V$FLAGS
       DO
       BEGIN
           TAG_NAME = 'rooms:r:assns:r';
           VAL = NULL;
           SUSPEND;

           TAG_NAME = 'rooms:r:assns:r:exam_id';
           VAL = V$EXAM_ID;
           SUSPEND;

           TAG_NAME = 'rooms:r:assns:r:date';
           VAL = V$DATE;
           SUSPEND;

           TAG_NAME = 'rooms:r:assns:r:role_id';
           VAL = V$FLAGS;
           SUSPEND;
       END
   END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_PPE_ROOM_DELETE (
    I$OBJ_ID BIGINT)
RETURNS (
    ERROR_TEXT VARCHAR(100))
AS
declare variable V$OBJ_ID bigint;
begin

  SELECT D.OBJ_ID
  FROM UT_PPE_ROOMS D
  WHERE D.OBJ_ID = :I$OBJ_ID AND D.DATE_DEL IS NULL
  INTO :V$OBJ_ID;
  
  IF(V$OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Помещение ППЭ не найдено или было удалено';

  -- Проверяем, есть ли уже рабочее планирование на данное помещение
  -- ...

  UPDATE UT_PPE_ROOMS
  SET DATE_DEL = CURRENT_TIMESTAMP
  WHERE OBJ_ID = :I$OBJ_ID;

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_PPE_ROOM_SET (
    I$OBJ_ID BIGINT,
    I$PPE_ID BIGINT,
    I$OBJ_NAME VARCHAR(100),
    I$LOCATION VARCHAR(400),
    I$PPE_CODE VARCHAR(40),
    I$N_FLOOR SMALLINT,
    I$ROOM_NUM VARCHAR(20),
    I$N_ROWS SMALLINT,
    I$N_COLS SMALLINT,
    I$FLAGS INTEGER,
    I$IS_ACTIVE SMALLINT,
    I$MAP VARCHAR(8000))
RETURNS (
    OBJ_ID BIGINT,
    GEOMETRY_CHANGED SMALLINT)
AS
declare variable V$OBJ_ID bigint;
declare variable V$N_ROWS smallint;
declare variable V$N_COLS smallint;
begin

  IF(I$N_ROWS = 0) THEN I$N_ROWS = NULL;
  IF(I$N_COLS = 0) THEN I$N_COLS = NULL;

  IF((I$N_ROWS IS NULL AND I$N_COLS IS NOT NULL) OR (I$N_ROWS IS NOT NULL AND I$N_COLS IS NULL)) THEN
      EXCEPTION DATA_ERROR 'Поля размерности помещения должны быть заданы или пусты одновременно';

  IF(I$N_ROWS < 0 OR I$N_COLS < 0) THEN EXCEPTION DATA_ERROR 'Отрицательные значения размерности помещения недопустимы';

  -- Проверяем уникальность кода ППЭ
  IF(I$PPE_CODE IS NOT NULL) THEN
  BEGIN

      IF(EXISTS(
          SELECT FIRST 1 1 FROM UT_PPE_ROOMS WHERE DATE_DEL IS NULL AND PPE_CODE = :I$PPE_CODE AND (:I$OBJ_ID IS NULL OR OBJ_ID <> :I$OBJ_ID)
      ))
      THEN EXCEPTION DATA_ERROR 'Этот код ППЭ уже использован';

  END

  IF(I$OBJ_ID IS NULL) THEN
  BEGIN

      INSERT INTO UT_PPE_ROOMS
      (PPE_ID, OBJ_NAME, LOCATION, PPE_CODE, N_FLOOR, ROOM_NUM, N_ROWS, N_COLS, FLAGS, IS_ACTIVE, PLACES_MAP)
      VALUES (:I$PPE_ID, :I$OBJ_NAME, :I$LOCATION, :I$PPE_CODE, :I$N_FLOOR, :I$ROOM_NUM, :I$N_ROWS, :I$N_COLS, :I$FLAGS, :I$IS_ACTIVE, :I$MAP)
      RETURNING OBJ_ID INTO :OBJ_ID;

      GEOMETRY_CHANGED = 1;

  END
  ELSE
  BEGIN

      SELECT OBJ_ID, N_ROWS, N_COLS
      FROM UT_PPE_ROOMS
      WHERE OBJ_ID = :I$OBJ_ID AND DATE_DEL IS NULL
      INTO :V$OBJ_ID, :V$N_ROWS, :V$N_COLS;

      IF(V$OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Помещение не найдено или было удалено';

      IF((V$N_ROWS IS NOT NULL OR V$N_COLS IS NOT NULL) AND (I$N_ROWS IS NULL OR I$N_COLS IS NULL)) THEN
          EXCEPTION DATA_ERROR 'После того, как размеры помещения были заданы, и созданы записи мест, обнулять размеры нельзя';

      GEOMETRY_CHANGED = 0;
      IF((V$N_ROWS IS NULL OR V$N_COLS IS NULL) AND (I$N_ROWS IS NOT NULL OR I$N_COLS IS NOT NULL)) THEN GEOMETRY_CHANGED = 1;
      IF(I$N_ROWS <> V$N_ROWS OR I$N_COLS <> V$N_COLS) THEN GEOMETRY_CHANGED = 1;

      -- Нельзя снимать активность с помещений, которые уже запланированы в незавершенные тестирования
      -- ...

      UPDATE UT_PPE_ROOMS
      SET OBJ_NAME = :I$OBJ_NAME, LOCATION = :I$LOCATION, PPE_CODE = :I$PPE_CODE, N_FLOOR = :I$N_FLOOR, ROOM_NUM = :I$ROOM_NUM,
          N_ROWS = :I$N_ROWS, N_COLS = :I$N_COLS, FLAGS = :I$FLAGS, IS_ACTIVE = :I$IS_ACTIVE, PLACES_MAP = :I$MAP
      WHERE OBJ_ID = :I$OBJ_ID;

      -- N_PLACES пересчитаем после сохранения мест

      OBJ_ID = I$OBJ_ID;

  END

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_PPE_SET (
    I$OBJ_ID BIGINT,
    I$ORG_ID BIGINT,
    I$USER_ID VARCHAR(40),
    I$NAME_SHORT VARCHAR(1000),
    I$NAME_FULL VARCHAR(1000),
    I$AREA_ID BIGINT,
    I$PPE_CODE VARCHAR(40),
    I$FLAGS INTEGER,
    I$N_PLACES INTEGER)
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$ORG_ID bigint;
declare variable V$OBJ_ID bigint;
begin

  -- Проверяем уникальность кода ППЭ
  IF(I$PPE_CODE IS NOT NULL) THEN
  BEGIN

      IF(EXISTS(
          SELECT FIRST 1 1 FROM UT_PPE WHERE DATE_DEL IS NULL AND PPE_CODE = :I$PPE_CODE AND (:I$OBJ_ID IS NULL OR OBJ_ID <> :I$OBJ_ID)
      ))
      THEN EXCEPTION DATA_ERROR 'Этот код ППЭ уже использован';

  END

  IF(I$N_PLACES <= 0) THEN EXCEPTION DATA_ERROR 'Не может быть задано отрицательное или нулевое количество мест';

  IF(I$OBJ_ID IS NULL) THEN
  BEGIN

      -- Добавлять руками можно только реальные ППЭ, виртуальные добавятся сами проставлением галочки в организации
      -- данное сечение оставлено для автоматического вызова из VAL_ADD
      IF(I$ORG_ID IS NOT NULL) THEN
      BEGIN

          SELECT L2.OBJ_ID, V2.VAL, V5.VAL, V2163.LISTVAL_ID
          FROM LINKS L2
          JOIN VALS V2 ON V2.OBJ_ID = L2.OBJ_ID AND V2.PARAM_ID = 2 AND V2.IS_DEL = 0
          JOIN VALS V5 ON V5.OBJ_ID = L2.OBJ_ID AND V5.PARAM_ID = 5 AND V5.IS_DEL = 0
          LEFT JOIN VALL V2163 ON V2163.OBJ_ID = L2.OBJ_ID AND V2163.PARAM_ID = 2163 AND V2163.IS_DEL = 0
          WHERE L2.OBJ_TYPE_ID = 2 AND L2.OBJ_ID = :I$ORG_ID AND L2.DATE_DEL IS NULL AND (L2.PARENT_ID IS NULL OR L2.PARENT_TYPE_ID IN (111, 112))
          INTO :V$ORG_ID, :I$NAME_SHORT, :I$NAME_FULL, :I$AREA_ID;

          IF(V$ORG_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Родительская организация не найдена';

      END

      INSERT INTO UT_PPE
      (ORG_ID, NAME_FULL, NAME_SHORT, PPE_CODE, FLAGS, AREA_ID, N_PLACES)
      VALUES (:I$OBJ_ID, :I$NAME_FULL, :I$NAME_SHORT, :I$PPE_CODE, :I$FLAGS, :I$AREA_ID, :I$N_PLACES)
      RETURNING OBJ_ID INTO :OBJ_ID;

  END
  ELSE
  BEGIN

      SELECT OBJ_ID
      FROM UT_PPE
      WHERE DATE_DEL IS NULL AND OBJ_ID = :I$OBJ_ID
      INTO :V$OBJ_ID;

      IF(V$OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Запись ППЭ не найдена или была удалена';

      -- Реквизиты ОУ не корректируем, только основные поля
      IF(I$ORG_ID IS NULL) THEN
      BEGIN

          UPDATE UT_PPE
          SET NAME_SHORT = :I$NAME_SHORT, NAME_FULL = :I$NAME_FULL, AREA_ID = :I$AREA_ID, PPE_CODE = :I$PPE_CODE, FLAGS = :I$FLAGS, N_PLACES = :I$N_PLACES
          WHERE OBJ_ID = :I$OBJ_ID;

      END
      ELSE
      BEGIN

          UPDATE UT_PPE
          SET PPE_CODE = :I$PPE_CODE, FLAGS = :I$FLAGS, N_PLACES = :I$N_PLACES
          WHERE OBJ_ID = :I$OBJ_ID;

      END

      OBJ_ID = I$OBJ_ID;

  END

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_PUPIL_GET (
    SCBOYCOD BIGINT)
RETURNS (
    SCBOYCODE BIGINT,
    FORMID BIGINT,
    FORMNUM INTEGER,
    FORMNAME VARCHAR(1000),
    FIRSTNAME VARCHAR(1000),
    NAME VARCHAR(1000),
    LASTNAME VARCHAR(1000),
    SCHOOLID BIGINT)
AS
BEGIN
    FOR
        SELECT PUPIL.OBJ_ID AS PUPIL_ID,
               FN.VAL AS FIRST_NAME,
               N.VAL AS NAME,
               LN.VAL AS LAST_NAME,
               FORM.OBJ_ID AS CLASS_ID,
               FNUM.TAG AS FORM_NUM,
               F.CAPTION AS FORM_NAME,
               GRADE.PARENT_ID AS SCHOOL_ID
        FROM LINKS PUPIL
    
        LEFT JOIN VALS FN
        ON FN.OBJ_ID = PUPIL.OBJ_ID
        AND FN.PARAM_ID = 55
        AND FN.IS_DEL = 0
        
        LEFT JOIN VALS N
        ON N.OBJ_ID = PUPIL.OBJ_ID
        AND N.PARAM_ID = 56
        AND N.IS_DEL = 0

        LEFT JOIN VALS LN
        ON LN.OBJ_ID = PUPIL.OBJ_ID
        AND LN.PARAM_ID = 57
        AND LN.IS_DEL = 0

        JOIN LINKS FORM
        ON FORM.OBJ_ID = PUPIL.PARENT_ID
        AND FORM.DATE_DEL IS NULL
        AND FORM.PARENT_TYPE_ID = 8 --STAGE

        JOIN LINKS STAGE
        ON STAGE.OBJ_ID = FORM.PARENT_ID
        AND STAGE.DATE_DEL IS NULL
        AND STAGE.PARENT_TYPE_ID = 7 --GRADE

        JOIN VALL FNUML
        ON FNUML.OBJ_ID = STAGE.OBJ_ID
        AND FNUML.PARAM_ID = 49
        AND FNUML.IS_DEL = 0

        JOIN LISTVALS FNUM
        ON FNUM.LISTVAL_ID = FNUML.LISTVAL_ID
 
        JOIN LINKS GRADE
        ON GRADE.OBJ_ID = STAGE.PARENT_ID
        AND GRADE.DATE_DEL IS NULL
        AND GRADE.PARENT_TYPE_ID = 2 --SCHOOL

        LEFT JOIN OBJECT_CAPTION_GET(FORM.OBJ_ID) F
        ON 1=1

        WHERE PUPIL.OBJ_ID = :SCBOYCOD
        AND PUPIL.DATE_DEL IS NULL
        AND PUPIL.PARENT_TYPE_ID = 9 --CLASS
        INTO :SCBOYCODE,
             :FIRSTNAME,
             :NAME,
             :LASTNAME,
             :FORMID,
             :FORMNUM,
             :FORMNAME,
             :SCHOOLID
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_PUPIL_GET_NEW (
    SCBOYCOD BIGINT)
RETURNS (
    SCBOYCODE BIGINT,
    FORMID BIGINT,
    FORMNUM INTEGER,
    FORMNAME VARCHAR(1000),
    FIRSTNAME VARCHAR(1000),
    NAME VARCHAR(1000),
    LASTNAME VARCHAR(1000),
    SCHOOLID BIGINT,
    SCHOOLSHORTNAME VARCHAR(100),
    DISTRICTID BIGINT,
    DISTRICTNAME VARCHAR(1000))
AS
BEGIN
    FOR
        SELECT PUPIL.OBJ_ID AS PUPIL_ID,
               FN.VAL AS FIRST_NAME,
               N.VAL AS NAME,
               LN.VAL AS LAST_NAME,
               FORM.OBJ_ID AS CLASS_ID,
               FNUM.TAG AS FORM_NUM,
               case when PUPIL.PARENT_TYPE_ID = 82 then 'выбыл' else F.CAPTION end AS FORM_NAME,
               GRADE.PARENT_ID AS SCHOOL_ID,
               V2.V SCHOOL_SHORT_NAME,
               SCHOOL.PARENT_ID DISTRICT_ID,
               D.CAPTION DISTRICT_NAME
        FROM LINKS PUPIL
    
        LEFT JOIN VALS FN
        ON FN.OBJ_ID = PUPIL.OBJ_ID
        AND FN.PARAM_ID = 55
        AND FN.IS_DEL = 0
        
        LEFT JOIN VALS N
        ON N.OBJ_ID = PUPIL.OBJ_ID
        AND N.PARAM_ID = 56
        AND N.IS_DEL = 0

        LEFT JOIN VALS LN
        ON LN.OBJ_ID = PUPIL.OBJ_ID
        AND LN.PARAM_ID = 57
        AND LN.IS_DEL = 0

--        JOIN LINKS FORM
        LEFT JOIN LINKS FORM
        ON FORM.OBJ_ID = PUPIL.PARENT_ID
        AND FORM.DATE_DEL IS NULL
        AND FORM.PARENT_TYPE_ID = 8 --STAGE

        LEFT JOIN OBJECT_CAPTION_GET(FORM.OBJ_ID) F
        ON 1=1

--        JOIN LINKS STAGE
        LEFT JOIN LINKS STAGE
        ON STAGE.OBJ_ID = FORM.PARENT_ID
        AND STAGE.DATE_DEL IS NULL
        AND STAGE.PARENT_TYPE_ID = 7 --GRADE

--        JOIN VALL FNUML
        LEFT JOIN VALL FNUML
        ON FNUML.OBJ_ID = STAGE.OBJ_ID
        AND FNUML.PARAM_ID = 49
        AND FNUML.IS_DEL = 0

--        JOIN LISTVALS FNUM
        LEFT JOIN LISTVALS FNUM
        ON FNUM.LISTVAL_ID = FNUML.LISTVAL_ID
 
--        JOIN LINKS GRADE
        LEFT JOIN LINKS GRADE
        ON GRADE.OBJ_ID = STAGE.PARENT_ID
        AND GRADE.DATE_DEL IS NULL
        AND GRADE.PARENT_TYPE_ID = 2 --SCHOOL

        LEFT JOIN VAL_GET(GRADE.PARENT_ID, 2) V2
        ON 1=1

        LEFT JOIN LINKS SCHOOL
        ON SCHOOL.OBJ_ID = GRADE.PARENT_ID
        AND SCHOOL.DATE_DEL IS NULL
        AND SCHOOL.PARENT_TYPE_ID = 111 --DISTRICT

        LEFT JOIN OBJECT_CAPTION_GET(SCHOOL.PARENT_ID) D
        ON 1=1

        WHERE PUPIL.OBJ_ID = :SCBOYCOD
        AND PUPIL.DATE_DEL IS NULL
--        AND PUPIL.PARENT_TYPE_ID = 9 --CLASS
        AND PUPIL.PARENT_TYPE_ID in (9,82) --CLASS
        INTO :SCBOYCODE,
             :FIRSTNAME,
             :NAME,
             :LASTNAME,
             :FORMID,
             :FORMNUM,
             :FORMNAME,
             :SCHOOLID,
             :SCHOOLSHORTNAME,
             :DISTRICTID, 
             :DISTRICTNAME
    DO
    BEGIN
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_QUESTIONS_GET (
    I$SECTION_ID BIGINT NOT NULL,
    I$TEST_ID BIGINT = null,
    I$OBJ_ID BIGINT = null)
RETURNS (
    OBJ_ID BIGINT,
    SECTION_ID BIGINT,
    CODING_ID BIGINT,
    OBJ_NAME VARCHAR(100),
    QUESTION_TYPE SMALLINT,
    QUESTION_TYPE_VALUE CHAR(1),
    SORT_ORDER SMALLINT,
    MAX_SCORE SMALLINT,
    STAGE SMALLINT,
    QUESTION BLOB SUB_TYPE 1 SEGMENT SIZE 80,
    ONLY_FOR_CONTROL SMALLINT,
    ANSWER VARCHAR(250),
    CASE_SENSITIVE SMALLINT,
    ANSWER_HINT VARCHAR(100),
    IGNORE_SPACES SMALLINT,
    HINT BLOB SUB_TYPE 1 SEGMENT SIZE 80,
    SOLUTION BLOB SUB_TYPE 1 SEGMENT SIZE 80)
AS
begin
  FOR
      SELECT Q.OBJ_ID, Q.SECTION_ID, CL.CODING_ID, Q.OBJ_NAME, Q.QUESTION_TYPE, QT.OBJ_VALUE, Q.SORT_ORDER, Q.MAX_SCORE, Q.QUESTION
      FROM UT_QUESTIONS Q
      JOIN UT_KIM_CODING_LEVELS CL ON CL.obj_id = Q.SECTION_ID
      JOIN UT_QUESTION_TYPE QT ON QT.OBJ_ID = Q.QUESTION_TYPE
      WHERE Q.DATE_DEL IS NULL AND (:I$SECTION_ID = -1 OR Q.SECTION_ID = :I$SECTION_ID) AND (Q.OBJ_ID = :I$OBJ_ID OR :I$OBJ_ID IS NULL)
      INTO :OBJ_ID, :SECTION_ID, :CODING_ID, :OBJ_NAME, :QUESTION_TYPE, :QUESTION_TYPE_VALUE, :SORT_ORDER, :MAX_SCORE, :QUESTION
  DO
  BEGIN
      SUSPEND;
  END
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_QUESTIONS_LIST (
    I$SECTION_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    SECTION_ID BIGINT,
    CODING_ID BIGINT,
    OBJ_NAME VARCHAR(400),
    QUESTION_TYPE SMALLINT,
    QUESTION_TYPE_VALUE VARCHAR(50),
    SORT_ORDER SMALLINT,
    MAX_SCORE SMALLINT,
    "LEVEL" SMALLINT)
AS
begin

  FOR
    -- старая схема привязки к кодификаторам
    SELECT Q.OBJ_ID, Q.SECTION_ID, CL.CODING_ID, Q.OBJ_NAME, Q.QUESTION_TYPE, QT.OBJ_VALUE || ' (' || QT.OBJ_NAME || ')' , Q.SORT_ORDER, Q.MAX_SCORE, Q.Q_LEVEL + 1
    FROM UT_QUESTIONS Q
    JOIN UT_KIM_CODING_LEVELS CL ON CL.OBJ_ID = Q.SECTION_ID
    JOIN UT_QUESTION_TYPE QT ON QT.OBJ_ID = Q.QUESTION_TYPE
    WHERE Q.DATE_DEL IS NULL AND Q.SECTION_ID = :I$SECTION_ID
    -- новая схема привязки к кодификаторам
    UNION
    SELECT Q.OBJ_ID, Q.SECTION_ID, CL.CODING_ID, Q.OBJ_NAME, Q.QUESTION_TYPE, QT.OBJ_VALUE || ' (' || QT.OBJ_NAME || ')' , Q.SORT_ORDER, Q.MAX_SCORE, Q.Q_LEVEL + 1
    FROM UT_QUESTION_RELS QR
    JOIN UT_QUESTIONS Q ON Q.DATE_DEL IS NULL AND Q.OBJ_ID = QR.QUESTION_ID
    JOIN UT_KIM_CODING_LEVELS CL ON CL.OBJ_ID = QR.SECTION_ID
    JOIN UT_QUESTION_TYPE QT ON QT.OBJ_ID = Q.QUESTION_TYPE
    WHERE QR.DATE_DEL IS NULL AND QR.SECTION_ID = :I$SECTION_ID
    ORDER BY 7
    INTO :OBJ_ID, :SECTION_ID, :CODING_ID, :OBJ_NAME, :QUESTION_TYPE, :QUESTION_TYPE_VALUE, :SORT_ORDER, :MAX_SCORE, :LEVEL
  DO
  BEGIN
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_QUESTION_ANSWERS_GET (
    I$QUESTION_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    SORT_ORDER SMALLINT,
    VARIANT BLOB SUB_TYPE 1 SEGMENT SIZE 80,
    A_LEVEL SMALLINT,
    OBJ_NAME VARCHAR(100))
AS
BEGIN

  -- Для вопросов на соответствие, вопросы левой части идут в обратном порядке
  FOR
      SELECT OBJ_ID, SORT_ORDER, VARIANT, A_LEVEL, OBJ_NAME
      FROM UT_ANSWERS
      WHERE DATE_DEL IS NULL AND QUESTION_ID = :I$QUESTION_ID AND SORT_ORDER < 0
      ORDER BY SORT_ORDER DESC
      INTO :OBJ_ID, :SORT_ORDER, :VARIANT, :A_LEVEL, :OBJ_NAME
  DO
  BEGIN
      SUSPEND;
  END

  FOR
      SELECT OBJ_ID, SORT_ORDER, VARIANT, A_LEVEL, OBJ_NAME
      FROM UT_ANSWERS
      WHERE DATE_DEL IS NULL AND QUESTION_ID = :I$QUESTION_ID AND SORT_ORDER > 0
      ORDER BY SORT_ORDER
      INTO :OBJ_ID, :SORT_ORDER, :VARIANT, :A_LEVEL, :OBJ_NAME
  DO
  BEGIN
      SUSPEND;
  END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_QUESTION_ANSWERS_IDS (
    I$QUESTION_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT)
AS
BEGIN
  FOR
    SELECT OBJ_ID
    FROM UT_ANSWERS
    WHERE DATE_DEL IS NULL AND QUESTION_ID = :I$QUESTION_ID
    INTO :OBJ_ID
  DO
  BEGIN
    SUSPEND;
  END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_QUESTION_ANSWER_DEL (
    I$OBJ_ID BIGINT)
RETURNS (
    STUB INTEGER)
AS
DECLARE VARIABLE V$CODING_ID BIGINT;
DECLARE VARIABLE V$TYPE SMALLINT;
DECLARE VARIABLE V$Q_NAME VARCHAR(400);
DECLARE VARIABLE V$Q_ID BIGINT;
DECLARE VARIABLE V$ATTR_ID BIGINT;
DECLARE VARIABLE V$OLD_ORDER INTEGER;
begin

  SELECT Q.OBJ_ID, Q.QUESTION_TYPE, Q.OBJ_NAME, QA.SORT_ORDER
  FROM UT_ANSWERS QA
  JOIN UT_QUESTIONS Q ON Q.OBJ_ID = QA.QUESTION_ID
  WHERE QA.OBJ_ID = :I$OBJ_ID AND QA.DATE_DEL IS NULL
  INTO :V$Q_ID, :V$TYPE, :V$Q_NAME, :V$OLD_ORDER;

  IF(V$Q_ID IS NULL) THEN EXIT;

  UPDATE UT_ANSWERS
  SET DATE_DEL = CURRENT_TIMESTAMP
  WHERE OBJ_ID = :I$OBJ_ID AND DATE_DEL IS NULL;

  -- Для автокодификаторов удаляем данный критерий во всех вопросах
  SELECT FIRST 1 KC.OBJ_ID
  FROM UT_QUESTIONS Q
  JOIN UT_KIM_CODING_LEVELS CL ON CL.OBJ_ID = Q.SECTION_ID
  JOIN UT_KIM_CODING KC ON KC.OBJ_ID = CL.CODING_ID
  JOIN UT_TESTS T ON T.CODING_ID = KC.OBJ_ID
  WHERE Q.OBJ_ID = :V$Q_ID
  INTO :V$CODING_ID;

  IF(V$CODING_ID IS NOT NULL AND V$TYPE IN (3, 8)) THEN
  BEGIN
    FOR
      SELECT QA.OBJ_ID
      FROM UT_KIM_CODING_LEVELS CL
      JOIN UT_QUESTIONS Q ON Q.SECTION_ID = CL.OBJ_ID AND Q.DATE_DEL IS NULL AND Q.QUESTION_TYPE = :V$TYPE AND Q.OBJ_NAME = :V$Q_NAME
      JOIN UT_ANSWERS QA ON QA.QUESTION_ID = Q.OBJ_ID AND QA.DATE_DEL IS NULL AND QA.SORT_ORDER = :V$OLD_ORDER
      WHERE CL.CODING_ID = :V$CODING_ID AND CL.DATE_DEL IS NULL
      INTO :V$ATTR_ID
    DO
    BEGIN
      -- Остальные критерии не трогаем - они перенумеруются через *_ANSWER_SET
      UPDATE UT_ANSWERS QA
      SET DATE_DEL = CURRENT_TIMESTAMP
      WHERE QA.OBJ_ID = :V$ATTR_ID;
    END
  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_QUESTION_ANSWER_SET (
    I$OBJ_ID BIGINT,
    I$QUESTION_ID BIGINT,
    I$SORT_ORDER SMALLINT,
    I$OBJ_NAME VARCHAR(400),
    I$VARIANT BLOB SUB_TYPE 1 SEGMENT SIZE 8,
    I$A_LEVEL SMALLINT,
    I$APPLY_ALL SMALLINT = 1)
RETURNS (
    OBJ_ID BIGINT)
AS
DECLARE VARIABLE V$Q_NAME VARCHAR(400);
DECLARE VARIABLE V$OLD_LEVEL INTEGER;
DECLARE VARIABLE V$IS_AUTOCODING SMALLINT;
DECLARE VARIABLE V$CODING_ID BIGINT;
DECLARE VARIABLE V$TYPE SMALLINT;
DECLARE VARIABLE V$FAKE_ORDER SMALLINT;
DECLARE VARIABLE V$SIGNATURE INTEGER;
DECLARE VARIABLE V$OK SMALLINT;
DECLARE VARIABLE N INTEGER;
DECLARE VARIABLE V$Q_ID BIGINT;
DECLARE VARIABLE V$ATTR_ID BIGINT;
DECLARE VARIABLE V$OLD_NAME VARCHAR(400);
DECLARE VARIABLE V$OLD_ORDER SMALLINT;
DECLARE VARIABLE V$OLD_HASH BIGINT;
DECLARE VARIABLE V$NEW_HASH BIGINT;
BEGIN

  -- Права доступа не проверяем - сюда можно попасть только после сохранения вопроса

  SELECT Q.QUESTION_TYPE, Q.OBJ_NAME
  FROM UT_QUESTIONS Q
  WHERE Q.OBJ_ID = :I$QUESTION_ID
  INTO :V$TYPE, :V$Q_NAME;

  V$IS_AUTOCODING = 0;
  SELECT FIRST 1 1, KC.OBJ_ID
  FROM UT_QUESTIONS Q
  JOIN UT_KIM_CODING_LEVELS CL ON CL.OBJ_ID = Q.SECTION_ID
  JOIN UT_KIM_CODING KC ON KC.OBJ_ID = CL.CODING_ID
  JOIN UT_TESTS T ON T.CODING_ID = KC.OBJ_ID
  WHERE Q.OBJ_ID = :I$QUESTION_ID
  INTO :V$IS_AUTOCODING, :V$CODING_ID;

  IF(V$TYPE = 4) THEN V$FAKE_ORDER = TRUNC(RAND() * 32760); ELSE V$FAKE_ORDER = I$SORT_ORDER;

  V$NEW_HASH = HASH(I$VARIANT);

  IF(I$OBJ_ID IS NULL) THEN
  BEGIN

      -- Создаем новую сигнатуру, гарантированно отсутствующую даже в удаленных вариантах
      V$OK = 0;
      N = 0;
      WHILE(V$OK = 0)
      DO
      BEGIN
        V$SIGNATURE = TRUNC(RAND() * 32760);

        V$OK = 1;
        SELECT FIRST 1 0
        FROM UT_ANSWERS
        WHERE QUESTION_ID = :I$QUESTION_ID AND SIGNATURE = :V$SIGNATURE
        INTO :V$OK;

        N = N + 1;
        IF(N > 32000) THEN EXCEPTION DATA_ERROR 'Слишком много вариантов в базе данных, невозможно сохранить новый вариант';
      END

      INSERT INTO UT_ANSWERS
      (QUESTION_ID, SORT_ORDER, VARIANT, A_LEVEL, OBJ_NAME, FAKE_ORDER, SIGNATURE, HSIGNATURE)
      VALUES (:I$QUESTION_ID, :I$SORT_ORDER, :I$VARIANT, :I$A_LEVEL, :I$OBJ_NAME, :V$FAKE_ORDER, :V$SIGNATURE, :V$NEW_HASH)
      RETURNING OBJ_ID
      INTO :OBJ_ID;

      -- Если это был автокодификатор - добавляем такой же параметр в остальные варианты, его наверняка раньше не было
      IF(V$IS_AUTOCODING = 1 AND V$TYPE IN (3, 8)) THEN
      BEGIN
        FOR
          SELECT Q.OBJ_ID, QA.OBJ_ID
          FROM UT_KIM_CODING_LEVELS CL
          JOIN UT_QUESTIONS Q ON Q.SECTION_ID = CL.OBJ_ID AND Q.DATE_DEL IS NULL AND Q.OBJ_ID <> :I$QUESTION_ID AND Q.QUESTION_TYPE = :V$TYPE AND Q.OBJ_NAME = :V$Q_NAME
          LEFT JOIN UT_ANSWERS QA ON QA.QUESTION_ID = Q.OBJ_ID AND QA.DATE_DEL IS NULL AND QA.SORT_ORDER = :I$SORT_ORDER
          WHERE CL.CODING_ID = :V$CODING_ID AND CL.DATE_DEL IS NULL
          INTO :V$Q_ID, :V$ATTR_ID
        DO
        BEGIN
          IF(V$ATTR_ID IS NULL) THEN
          BEGIN
            INSERT INTO UT_ANSWERS
            (QUESTION_ID, SORT_ORDER, OBJ_NAME, A_LEVEL, VARIANT)
            VALUES (:V$Q_ID, :I$SORT_ORDER, :I$OBJ_NAME, :I$A_LEVEL, :I$VARIANT);
          END
        END
      END

  END
  ELSE
  BEGIN

      -- Какое было старое название ?
      SELECT QA.OBJ_ID, QA.OBJ_NAME, QA.A_LEVEL, QA.SORT_ORDER, HASH(QA.VARIANT)
      FROM UT_ANSWERS QA
      WHERE QA.OBJ_ID = :I$OBJ_ID AND QA.QUESTION_ID = :I$QUESTION_ID AND QA.DATE_DEL IS NULL
      INTO :OBJ_ID, :V$OLD_NAME, :V$OLD_LEVEL, :V$OLD_ORDER, :V$OLD_HASH;

      IF(OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Вариант (критерий) ответа не найден или был удален';

      UPDATE UT_ANSWERS
      SET SORT_ORDER = :I$SORT_ORDER, VARIANT = :I$VARIANT, A_LEVEL = :I$A_LEVEL, OBJ_NAME = :I$OBJ_NAME, FAKE_ORDER = :V$FAKE_ORDER, HSIGNATURE = :V$NEW_HASH
      WHERE OBJ_ID = :I$OBJ_ID;

      -- Если поменялся вес или название, не снят флаг автообновления всех записей - обновляем во всех автокодификаторах, где старое название было такое же. VARIANT тут не обновляем
      -- Новые записи тут не создаем, правим только существующие
      IF(V$IS_AUTOCODING = 1 AND V$TYPE IN (3, 8) AND (I$SORT_ORDER <> V$OLD_ORDER OR I$A_LEVEL <> V$OLD_LEVEL OR I$OBJ_NAME <> V$OLD_NAME OR V$NEW_HASH <> V$OLD_HASH)) THEN
      BEGIN
        FOR
          SELECT QA.OBJ_ID
          FROM UT_KIM_CODING_LEVELS CL
          JOIN UT_QUESTIONS Q ON Q.SECTION_ID = CL.OBJ_ID AND Q.DATE_DEL IS NULL AND Q.OBJ_ID <> :I$QUESTION_ID AND Q.QUESTION_TYPE = :V$TYPE AND Q.OBJ_NAME = :V$Q_NAME
          JOIN UT_ANSWERS QA ON QA.QUESTION_ID = Q.OBJ_ID AND QA.DATE_DEL IS NULL AND QA.SORT_ORDER = :V$OLD_ORDER AND QA.OBJ_NAME = :V$OLD_NAME
          WHERE CL.CODING_ID = :V$CODING_ID AND CL.DATE_DEL IS NULL AND :I$APPLY_ALL = 1
          INTO :V$ATTR_ID
        DO
        BEGIN
          UPDATE UT_ANSWERS QA
          SET SORT_ORDER = :I$SORT_ORDER, VARIANT = :I$VARIANT, A_LEVEL = :I$A_LEVEL, OBJ_NAME = :I$OBJ_NAME
          WHERE QA.OBJ_ID = :V$ATTR_ID;
        END
      END

  END

  SUSPEND;

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_QUESTION_CLONE (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    OBJ_ID BIGINT)
AS
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$USER_ID BIGINT;
begin

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  SELECT Q.OBJ_ID, Q.USER_ID
  FROM UT_QUESTIONS Q
  WHERE Q.DATE_DEL IS NULL AND Q.OBJ_ID = :I$OBJ_ID
  INTO :V$OBJ_ID, :V$USER_ID;

  IF(V$OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Вопрос не найден или был удален';

  -- Даже если вопрос и так наш - все равно даем копировать
  -- По идее надо бы перешифровать файл и сделать его копию

  INSERT INTO UT_QUESTIONS
  (OBJ_NAME, SORT_ORDER, QUESTION_TYPE, QUESTION, MAX_SCORE, HINT, TIME_LIMIT, METADATA_ID, FLAGS, CHARSET_ID, Q_LEVEL, FILE_SIZE, K, REF_ID, USER_ID)
  SELECT Q.OBJ_NAME, 1, Q.QUESTION_TYPE, Q.QUESTION, Q.MAX_SCORE, Q.HINT, Q.TIME_LIMIT, Q.METADATA_ID, Q.FLAGS, Q.CHARSET_ID, Q.Q_LEVEL, Q.FILE_SIZE, Q.K, Q.REF_ID, :I$USER_ID
  FROM UT_QUESTIONS Q
  WHERE Q.OBJ_ID = :I$OBJ_ID
  RETURNING OBJ_ID INTO :OBJ_ID;

  INSERT INTO UT_QUESTION_RELS
  (QUESTION_ID, SECTION_ID)
  SELECT :OBJ_ID, QR.SECTION_ID
  FROM UT_QUESTION_RELS QR
  JOIN UT_KIM_CODING_LEVELS CL ON CL.OBJ_ID = QR.SECTION_ID AND CL.DATE_DEL IS NULL
  JOIN UT_KIM_CODING C ON C.OBJ_ID = CL.CODING_ID AND C.DATE_DEL IS NULL AND (C.USER_ID IS NULL OR C.USER_ID = :I$USER_ID)
  WHERE QR.DATE_DEL IS NULL AND QR.QUESTION_ID = :I$OBJ_ID;

  INSERT INTO UT_ANSWERS
  (QUESTION_ID, SORT_ORDER, VARIANT, A_LEVEL, OBJ_NAME, FAKE_ORDER, SIGNATURE)
  SELECT :OBJ_ID, A.SORT_ORDER, A.VARIANT, A.A_LEVEL, A.OBJ_NAME, A.FAKE_ORDER, A.SIGNATURE
  FROM UT_ANSWERS A
  WHERE A.DATE_DEL IS NULL AND A.QUESTION_ID = :I$OBJ_ID;

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_QUESTION_DELETE (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    ERROR_TEXT VARCHAR(1000))
AS
declare variable V$DEL_INDEX integer;
declare variable V$RUNNING_ID bigint;
declare variable V$RUNNING_INDEX integer;
declare variable V$SECTION_ID bigint;
declare variable V$GEN bigint;
declare variable V$MULTIPLIER bigint;
declare variable N integer;
begin

  -- Проверяем права доступа к кодификатору

  -- Проверяем факт использования вопроса на этапах от проведения до завершения
  IF(EXISTS(
      SELECT FIRST 1 1
      FROM UT_TEST_VAR_QUESTIONS TVQ
      JOIN UT_SESSION_QUESTIONS SQ ON SQ.QUESTION_ID = TVQ.OBJ_ID AND SQ.DATE_DEL IS NULL
      JOIN UT_SESSIONS S ON S.OBJ_ID = SQ.SESSION_ID AND S.DATE_DEL IS NULL
      JOIN UT_EXAM_DATES ED ON ED.OBJ_ID = S.ED_ID AND ED.DATE_DEL IS NULL AND ED.EXAM_STATE >= 600 AND ED.EXAM_STATE < 1000
      WHERE TVQ.QUESTION_ID = :I$OBJ_ID AND TVQ.DATE_DEL IS NULL
  ))
  THEN EXCEPTION DATA_ERROR 'Вопрос уже назначен в как минимум одном незавершенном тестировании';

  -- Забираем номер по порядку
  SELECT SORT_ORDER, SECTION_ID
  FROM UT_QUESTIONS
  WHERE OBJ_ID = :I$OBJ_ID AND DATE_DEL IS NULL
  INTO :V$DEL_INDEX, :V$SECTION_ID;

  IF(V$DEL_INDEX IS NULL) THEN EXCEPTION DATA_ERROR 'Вопрос не найден или был удален другим пользователем';
  V$RUNNING_INDEX = V$DEL_INDEX;

  SELECT GEN, MULTIPLIER
  FROM GEN
  INTO :V$GEN, :V$MULTIPLIER;
  N = V$SECTION_ID / V$MULTIPLIER;
  IF(N <> V$GEN) THEN EXCEPTION DATA_ERROR 'Нельзя удалить вопрос, созданный на другом уровне или в другой организации';

  -- Отмечаем пункт как удаленный
  UPDATE UT_QUESTIONS
  SET DATE_DEL = CURRENT_TIMESTAMP 
  WHERE OBJ_ID = :I$OBJ_ID AND DATE_DEL IS NULL;

  -- Перенумеровываем вопросы в уровне кодификатора
  FOR
      SELECT Q.OBJ_ID
      FROM UT_QUESTIONS Q
      WHERE Q.DATE_DEL IS NULL AND Q.SORT_ORDER > :V$DEL_INDEX
      ORDER BY Q.SORT_ORDER
      INTO :V$RUNNING_ID
  DO
  BEGIN

      UPDATE UT_QUESTIONS
      SET SORT_ORDER = :V$RUNNING_INDEX
      WHERE OBJ_ID = :V$RUNNING_ID;

      V$RUNNING_INDEX = V$RUNNING_INDEX + 1;

  END

  SUSPEND;
end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_QUESTION_GET (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    OBJ_ID BIGINT,
    SECTION_ID BIGINT,
    SECTION_PRE VARCHAR(1000),
    CODING_ID BIGINT,
    OBJ_NAME VARCHAR(400),
    SORT_ORDER SMALLINT,
    QUESTION_TYPE SMALLINT,
    QUESTION_TYPE_VALUE VARCHAR(10),
    QUESTION BLOB SUB_TYPE 1 SEGMENT SIZE 80,
    HINT BLOB SUB_TYPE 1 SEGMENT SIZE 80,
    TIME_LIMIT INTEGER,
    METADATA_ID VARCHAR(40),
    FLAGS INTEGER,
    MAX_SCORE SMALLINT,
    "LEVEL" SMALLINT,
    ALLOWED SMALLINT,
    CHARSET_ID SMALLINT,
    FILE_SIZE INTEGER,
    K VARCHAR(64),
    SUBJECT_ID BIGINT,
    USER_ID BIGINT)
AS
DECLARE VARIABLE V$GEN BIGINT;
DECLARE VARIABLE V$MULTIPLIER BIGINT;
DECLARE VARIABLE V$REL_ID BIGINT;
DECLARE VARIABLE V$USER_ID BIGINT;
DECLARE VARIABLE N INTEGER;
begin

  -- Глобальные права доступа
  SELECT GEN, MULTIPLIER
  FROM GEN
  INTO :V$GEN, :V$MULTIPLIER;

  SELECT Q.OBJ_ID, Q.SECTION_ID, CL.CODING_ID, Q.OBJ_NAME, Q.SORT_ORDER, Q.QUESTION_TYPE, QT.OBJ_VALUE, Q.QUESTION, Q.HINT, Q.TIME_LIMIT,
    Q.METADATA_ID, Q.FLAGS, Q.MAX_SCORE, Q.Q_LEVEL, Q.CHARSET_ID, Q.FILE_SIZE, Q.K, Q.USER_ID
  FROM UT_QUESTIONS Q
  LEFT JOIN UT_KIM_CODING_LEVELS CL ON CL.OBJ_ID = Q.SECTION_ID
  JOIN UT_QUESTION_TYPE QT ON QT.OBJ_ID = Q.QUESTION_TYPE
  WHERE Q.OBJ_ID = :I$OBJ_ID AND Q.DATE_DEL IS NULL
  INTO :OBJ_ID, :SECTION_ID, :CODING_ID, :OBJ_NAME, :SORT_ORDER, :QUESTION_TYPE, :QUESTION_TYPE_VALUE, :QUESTION, :HINT, :TIME_LIMIT,
    :METADATA_ID, :FLAGS, :MAX_SCORE, :LEVEL, :CHARSET_ID, :FILE_SIZE, :K, :USER_ID;

  IF(I$OBJ_ID IS NOT NULL AND OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Вопрос не найден или был удален';

  -- Добавляем сюда корневой id, если он уже указан, но это чисто для формальной совместимости
  -- Названия кодификаторов добавим дополнительно
  SECTION_PRE = SECTION_ID;
  IF(SECTION_PRE IS NULL) THEN SECTION_PRE = '';
  FOR
    SELECT QR.SECTION_ID
    FROM UT_QUESTION_RELS QR
    JOIN UT_KIM_CODING_LEVELS CL ON CL.OBJ_ID = QR.SECTION_ID AND CL.DATE_DEL IS NULL
    JOIN UT_KIM_CODING C ON C.OBJ_ID = CL.CODING_ID AND C.DATE_DEL IS NULL
    WHERE QR.DATE_DEL IS NULL AND QR.QUESTION_ID = :OBJ_ID
    INTO :V$REL_ID
  DO
  BEGIN
    IF(SECTION_PRE <> '') THEN SECTION_PRE = SECTION_PRE || ',';
    SECTION_PRE = SECTION_PRE || V$REL_ID;
  END

  -- Берем первый попавшийся предмет по кодификаторам
  SELECT FIRST 1 CS.SUBJECT_ID
  FROM UT_QUESTION_RELS QR
  JOIN UT_KIM_CODING_LEVELS CL ON CL.OBJ_ID = QR.SECTION_ID AND CL.DATE_DEL IS NULL
  JOIN UT_KIM_CODING_SUBJECTS CS ON CS.CODING_ID = CL.CODING_ID AND CS.DATE_DEL IS NULL
  WHERE QR.DATE_DEL IS NULL AND QR.QUESTION_ID = :OBJ_ID
  ORDER BY CS.DATE_ADD
  INTO :SUBJECT_ID;

  -- Права доступа определяются кодификатором, а не самим вопросом - устарело
  -- Теперь SECTION_ID в вопросе не сохраняется, поэтому проверяем именно по самому вопросу
  -- N = SECTION_ID / V$MULTIPLIER;
  N = OBJ_ID / V$MULTIPLIER;
  ALLOWED = 0;
  IF(I$OBJ_ID IS NULL OR N = V$GEN) THEN ALLOWED = 1;

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_QUESTION_KIM_CAT (
    I$SUBJECT_ID BIGINT,
    I$CAT_ID BIGINT = NULL,
    I$USER_ID VARCHAR(40) = NULL)
RETURNS (
    TAG_NAME VARCHAR(400),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$CODING_ID BIGINT;
DECLARE VARIABLE V$PARENT_ID BIGINT;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE S VARCHAR(1000);
DECLARE VARIABLE N INTEGER;
DECLARE VARIABLE V$USER_ID BIGINT;
begin

  IF(I$USER_ID = 'Веб-администратор') THEN V$USER_ID = 1; ELSE V$USER_ID = CAST(I$USER_ID AS BIGINT);

  TAG_NAME = 'items::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    -- Поиск по предмету - конкретному
    -- SUBJECT_ID = 0 передается как мультипредмет
    SELECT C.OBJ_ID, C.OBJ_NAME, C.N_LEVELS
    FROM UT_KIM_CODING C
    WHERE :I$SUBJECT_ID IS NOT NULL AND C.DATE_DEL IS NULL
    AND (C.USER_ID IS NULL OR C.USER_ID = :V$USER_ID)
    AND EXISTS(
      SELECT FIRST 1 1
      FROM UT_KIM_CODING_SUBJECTS S
      WHERE S.DATE_DEL IS NULL AND S.CODING_ID = C.OBJ_ID AND (
        (:I$CAT_ID = 0 AND S.SUBJECT_ID IS NULL) OR -- строго мультипредмет
        ((:I$CAT_ID IS NULL OR :I$CAT_ID <> 0) AND (S.SUBJECT_ID = :I$SUBJECT_ID OR S.SUBJECT_ID IS NULL)) -- конкретный предмет и всегда мультипредмет
      )
    )
    -- Выборка по конкретному id кодификатора, либо все когда получился косяк
    UNION
    SELECT C.OBJ_ID, C.OBJ_NAME, C.N_LEVELS
    FROM UT_KIM_CODING C
    WHERE C.DATE_DEL IS NULL AND ((:I$CAT_ID IS NOT NULL AND C.OBJ_ID = :I$CAT_ID) OR (:I$SUBJECT_ID IS NULL AND :I$CAT_ID IS NULL))
    AND (C.USER_ID IS NULL OR C.USER_ID = :V$USER_ID)
    ORDER BY 2
    INTO :V$CODING_ID, :S, :N
  DO
  BEGIN
    TAG_NAME = 'items:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'items:r:id';
    VAL = V$CODING_ID;
    SUSPEND;
    TAG_NAME = 'items:r:name';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'items:r:levels';
    VAL = N;
    SUSPEND;
    -- Первый уровень
    TAG_NAME = 'items:r:items::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT CL.PARENT_ID, CL.OBJ_ID, CL.OBJ_NAME
      FROM UT_KIM_CODING_LEVELS CL
      WHERE CL.DATE_DEL IS NULL AND CL.CODING_ID = :V$CODING_ID
      ORDER BY CL.SORT_ORDER
      INTO :V$PARENT_ID, :V$OBJ_ID, :S
    DO
    BEGIN
      TAG_NAME = 'items:r:items:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'items:r:items:r:parent_id';
      VAL = V$PARENT_ID;
      SUSPEND;
      TAG_NAME = 'items:r:items:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'items:r:items:r:name';
      VAL = S;
      SUSPEND;
    END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_QUESTION_MOVE (
    I$OBJ_ID BIGINT,
    I$SECTION_ID BIGINT,
    I$USER_ID VARCHAR(40))
AS
DECLARE VARIABLE V$USER_ID BIGINT;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$OWNER_ID BIGINT;
DECLARE VARIABLE V$CODING_ID BIGINT;
DECLARE VARIABLE V$CODING_OWNER BIGINT;
DECLARE VARIABLE V$SECTION_ID BIGINT;
begin

  IF(I$USER_ID = 'Веб-администратор') THEN V$USER_ID = 1; ELSE V$USER_ID = CAST(I$USER_ID AS BIGINT);

  SELECT FIRST 1 Q.OBJ_ID, Q.USER_ID
  FROM UT_QUESTIONS Q
  WHERE Q.OBJ_ID = :I$OBJ_ID AND Q.DATE_DEL IS NULL
  INTO :V$OBJ_ID, :V$OWNER_ID;

  IF(V$OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Вопрос не найден или был удален';
  IF(V$OWNER_ID <> V$USER_ID) THEN EXCEPTION DATA_ERROR 'Нельзя изменять вопросы другого пользователя. Скопируйте вопрос';

  -- Чей кодификатор
  SELECT C.OBJ_ID, C.USER_ID
  FROM UT_KIM_CODING_LEVELS CL
  JOIN UT_KIM_CODING C ON C.OBJ_ID = CL.CODING_ID AND C.DATE_DEL IS NULL
  WHERE CL.DATE_DEL IS NULL AND CL.OBJ_ID = :I$SECTION_ID
  INTO :V$CODING_ID, :V$CODING_OWNER;

  IF(V$CODING_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Кодификатор не найден или был удален';
  IF(V$CODING_OWNER <> V$USER_ID) THEN EXCEPTION DATA_ERROR 'Нельзя использовать для привязки чужой кодификатор. Создате свой собственный';

  -- Если связь уже есть - ничего не делаем
  IF(EXISTS(SELECT FIRST 1 1 FROM UT_QUESTION_RELS R WHERE R.DATE_DEL IS NULL AND R.QUESTION_ID = :I$OBJ_ID AND R.SECTION_ID = :I$SECTION_ID)) THEN EXIT;

  -- Удаляем старые привязки в том же кодификаторе
  FOR
    SELECT R.SECTION_ID
    FROM UT_QUESTION_RELS R
    JOIN UT_KIM_CODING_LEVELS C ON C.OBJ_ID = R.SECTION_ID AND C.CODING_ID = :V$CODING_ID AND C.DATE_DEL IS NULL
    WHERE R.DATE_DEL IS NULL AND R.QUESTION_ID = :I$OBJ_ID
    ORDER BY 1
    INTO :V$SECTION_ID
  DO
  BEGIN
    UPDATE UT_QUESTION_RELS
    SET DATE_DEL = CURRENT_TIMESTAMP
    WHERE QUESTION_ID = :I$OBJ_ID AND SECTION_ID = :V$SECTION_ID;
  END

  -- Отменяем удаление или добавляем новую запись
  UPDATE OR INSERT INTO UT_QUESTION_RELS
  (QUESTION_ID, SECTION_ID, DATE_DEL)
  VALUES (:I$OBJ_ID, :I$SECTION_ID, NULL)
  MATCHING (QUESTION_ID, SECTION_ID);

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_QUESTION_REORDER (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40),
    I$AFTER_ID BIGINT)
RETURNS (
    ERROR_TEXT VARCHAR(10))
AS
declare variable V$SORT_ORDER integer;
declare variable V$OLD_ORDER integer;
declare variable N integer;
declare variable V$SECTION_ID bigint;
declare variable V$SECTION_ID2 bigint;
declare variable V$OBJ_ID bigint;
declare variable V$NEW_ORDER integer;
begin

  IF(I$OBJ_ID = I$AFTER_ID) THEN EXIT;

  -- Вопрос, который переставляем
  SELECT SORT_ORDER, SECTION_ID
  FROM UT_QUESTIONS
  WHERE OBJ_ID = :I$OBJ_ID AND DATE_DEL IS NULL
  INTO :V$OLD_ORDER, :V$SECTION_ID;

  -- Вопрос, за которым вставляем
  SELECT SORT_ORDER, SECTION_ID
  FROM UT_QUESTIONS
  WHERE OBJ_ID = :I$AFTER_ID AND DATE_DEL IS NULL
  INTO :V$SORT_ORDER, :V$SECTION_ID2;

  IF(V$OLD_ORDER IS NULL OR V$SORT_ORDER IS NULL) THEN EXCEPTION DATA_ERROR 'Перемещаемый вопрос или вопрос, после которого хотим переместить, утрачены';
  IF(V$SECTION_ID <> V$SECTION_ID2) THEN EXCEPTION DATA_ERROR 'Нельзя переместить вопрос в другой раздел';

  -- Если перетаскиваем вопрос на старое место, или вдруг наслоение кодов
  IF(V$SORT_ORDER + 1 = V$OLD_ORDER OR V$SORT_ORDER = V$OLD_ORDER) THEN EXIT;

  IF(V$OLD_ORDER < V$SORT_ORDER) THEN
  BEGIN

      -- Перемещаем вопрос вперед, на всякий случай учитываем и точное равенство SORT_ORDER
      N = V$OLD_ORDER;

      FOR
          SELECT OBJ_ID
          FROM UT_QUESTIONS
          WHERE DATE_DEL IS NULL AND SECTION_ID = :V$SECTION_ID AND OBJ_ID <> :I$OBJ_ID AND SORT_ORDER >= :V$OLD_ORDER
          ORDER BY SORT_ORDER
          INTO :V$OBJ_ID
      DO
      BEGIN

          UPDATE UT_QUESTIONS
          SET SORT_ORDER = :N
          WHERE OBJ_ID = :V$OBJ_ID;

          -- Резерв места под вставку вопроса - на случай если что-то потерялось в середине
          IF(V$OBJ_ID = :I$AFTER_ID) THEN
          BEGIN
              N = N + 1;
              V$NEW_ORDER = N;
          END

          N = N + 1;

      END

  END
  ELSE IF(V$OLD_ORDER > V$SORT_ORDER + 1) THEN
  BEGIN

      -- Перемещаем вопрос назад, сразу резервируем место
      V$NEW_ORDER = V$SORT_ORDER + 1;
      N = V$SORT_ORDER + 2;

      FOR
          SELECT OBJ_ID
          FROM UT_QUESTIONS
          WHERE DATE_DEL IS NULL AND SECTION_ID = :V$SECTION_ID AND OBJ_ID <> :I$OBJ_ID AND SORT_ORDER > :V$SORT_ORDER
          ORDER BY SORT_ORDER
          INTO :V$OBJ_ID
      DO
      BEGIN

          UPDATE UT_QUESTIONS
          SET SORT_ORDER = :N
          WHERE OBJ_ID = :V$OBJ_ID;

          N = N + 1;

      END

  END

  UPDATE UT_QUESTIONS
  SET SORT_ORDER = :V$NEW_ORDER
  WHERE OBJ_ID = :I$OBJ_ID;

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_QUESTION_SET (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40),
    SECTION_ID BIGINT,
    SECTION_IDS VARCHAR(1000),
    PARENT_ID BIGINT,
    OBJ_NAME VARCHAR(400),
    SORT_ORDER SMALLINT,
    QUESTION_TYPE SMALLINT,
    QUESTION BLOB SUB_TYPE 1 SEGMENT SIZE 80,
    "LEVEL" SMALLINT,
    MAX_SCORE SMALLINT,
    HINT BLOB SUB_TYPE 1 SEGMENT SIZE 80,
    FLAGS INTEGER,
    TIME_LIMIT INTEGER,
    METADATA_ID VARCHAR(40),
    CHARSET_ID SMALLINT,
    FILE_SIZE INTEGER,
    I$K VARCHAR(64),
    I$REF_ID VARCHAR(64) = NULL)
RETURNS (
    OBJ_ID BIGINT,
    IS_AUTOCODING SMALLINT,
    METADATA_OLD VARCHAR(40),
    OUTPUT_KEY VARCHAR(64))
AS
DECLARE VARIABLE V$USER_ID BIGINT;
DECLARE VARIABLE V$GEN BIGINT;
DECLARE VARIABLE V$MULTIPLIER BIGINT;
DECLARE VARIABLE V$REF_ID BIGINT;
DECLARE VARIABLE N BIGINT;
BEGIN

  -- Проверяем права доступа
  IF(I$USER_ID = 'Веб-администратор') THEN V$USER_ID = 1; ELSE V$USER_ID = CAST(I$USER_ID AS BIGINT);

  SELECT GEN, MULTIPLIER
  FROM GEN
  INTO :V$GEN, :V$MULTIPLIER;

  -- Проверяем теперь не по привязке к кодификатору, а по самому id вопроса
  N = I$OBJ_ID / V$MULTIPLIER;
  IF(N <> V$GEN) THEN EXCEPTION DATA_ERROR 'Нельзя изменить вопрос, созданный на другом уровне или в другой организации';

  IF(QUESTION_TYPE = 2 AND CHARSET_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Для вопросов типа B требуется обязательно указать кодировку ответа';
  IF(SECTION_IDS IS NULL OR CHAR_LENGTH(REPLACE(SECTION_IDS, ',', '')) = 0) THEN EXCEPTION DATA_ERROR 'Должен быть указан хотя бы один кодификатор';

  IF(I$OBJ_ID IS NULL) THEN
  BEGIN

      -- SORT_ORDER формируем последним по списку
      -- По новой схеме SORT_ORDER уже не получится
      SELECT FIRST 1 SORT_ORDER + 1
      FROM UT_QUESTIONS
      WHERE SECTION_ID = :SECTION_ID AND DATE_DEL IS NULL
      ORDER BY SORT_ORDER DESC
      INTO :SORT_ORDER;

      IF(SORT_ORDER IS NULL) THEN SORT_ORDER = 1;

      INSERT INTO UT_QUESTIONS
      (SECTION_ID, PARENT_ID, OBJ_NAME, SORT_ORDER, QUESTION_TYPE, QUESTION, Q_LEVEL, MAX_SCORE, HINT, FLAGS, TIME_LIMIT, METADATA_ID, CHARSET_ID, FILE_SIZE, K, REF_ID, USER_ID)
      VALUES (:SECTION_ID, :PARENT_ID, :OBJ_NAME, :SORT_ORDER, :QUESTION_TYPE, :QUESTION, :LEVEL, :MAX_SCORE, :HINT, :FLAGS, :TIME_LIMIT, :METADATA_ID, :CHARSET_ID, :FILE_SIZE, :I$K, :I$REF_ID, :V$USER_ID)
      RETURNING OBJ_ID INTO :OBJ_ID;

      OUTPUT_KEY = I$K;
      METADATA_OLD = METADATA_ID;

  END
  ELSE
  BEGIN

      -- Достаем актуальный идентификатор файла, чтобы на фронте обработать удаление файла
      SELECT OBJ_ID, METADATA_ID
      FROM UT_QUESTIONS
      WHERE OBJ_ID = :I$OBJ_ID
      INTO :OBJ_ID, :METADATA_OLD;

      IF(OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Вопрос не найден или был удален';

      -- Двигать вопрос в другой раздел, переподчинять или менять тип пока не планируем
      -- sort_order по идее меняться тут не должен ! SORT_ORDER = :SORT_ORDER
      UPDATE UT_QUESTIONS
      SET OBJ_NAME = :OBJ_NAME, QUESTION = :QUESTION, Q_LEVEL = :LEVEL, MAX_SCORE = :MAX_SCORE, HINT = :HINT,
        FLAGS = :FLAGS, TIME_LIMIT = :TIME_LIMIT, METADATA_ID = :METADATA_ID, CHARSET_ID = :CHARSET_ID, FILE_SIZE = :FILE_SIZE, K = :I$K
      WHERE OBJ_ID = :I$OBJ_ID;

      OUTPUT_KEY = I$K;

  END

  -- Сохраняем привязки к кодификаторам
  -- Добавление
  FOR
    SELECT L.ID
    FROM STR_TO_ID_LIST(:SECTION_IDS) L
    JOIN UT_KIM_CODING_LEVELS CL ON CL.OBJ_ID = L.ID AND CL.DATE_DEL IS NULL
    JOIN UT_KIM_CODING C ON C.OBJ_ID = CL.CODING_ID AND C.DATE_DEL IS NULL
    LEFT JOIN UT_QUESTION_RELS RL ON RL.QUESTION_ID = :OBJ_ID AND RL.SECTION_ID = L.ID
    WHERE RL.QUESTION_ID IS NULL OR RL.DATE_DEL IS NOT NULL
    INTO :V$REF_ID
  DO
  BEGIN
    UPDATE OR INSERT INTO UT_QUESTION_RELS
    (QUESTION_ID, SECTION_ID, DATE_DEL)
    VALUES (:OBJ_ID, :V$REF_ID, NULL)
    MATCHING (QUESTION_ID, SECTION_ID);
  END
  -- Удаление утраченных
  FOR
    SELECT R.SECTION_ID
    FROM UT_QUESTION_RELS R
    WHERE R.DATE_DEL IS NULL AND R.QUESTION_ID = :OBJ_ID AND NOT EXISTS(SELECT FIRST 1 1 FROM STR_TO_ID_LIST(:SECTION_IDS) L WHERE L.ID = R.SECTION_ID)
    INTO :V$REF_ID
  DO
  BEGIN
    UPDATE UT_QUESTION_RELS
    SET DATE_DEL = CURRENT_TIMESTAMP
    WHERE QUESTION_ID = :OBJ_ID AND SECTION_ID = :V$REF_ID;
  END

  -- Возвращаем флаг автогенерации кодификатора IS_AUTOCODING - непонятно зачем
  -- !!!
  IS_AUTOCODING = 0;
  /* SELECT FIRST 1 1
  FROM UT_QUESTIONS Q
  JOIN UT_KIM_CODING_LEVELS CL ON CL.OBJ_ID = Q.SECTION_ID
  JOIN UT_KIM_CODING KC ON KC.OBJ_ID = CL.CODING_ID
  JOIN UT_TESTS T ON T.CODING_ID = KC.OBJ_ID
  WHERE Q.OBJ_ID = :I$OBJ_ID
  INTO :IS_AUTOCODING;*/

  -- В случае автокодификатора по идее надо обновить везде
  -- !!!

  SUSPEND;

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_SCHOLAR_GET RETURNS (
    FIRSTNAME VARCHAR(50),
    NAME VARCHAR(50),
    LASTNAME VARCHAR(50),
    S_SEX INTEGER,
    S_BIRTHDAY DATE,
    KEYFIELD VARCHAR(25),
    KEYFIELDFULL VARCHAR(500))
AS
declare variable V$OBJ_ID bigint;
declare variable V$FORMNUM integer;
declare variable V$FORMINDEX varchar(5);
declare variable V$FORMSTEP integer;
BEGIN
    SELECT FIRST 1 L2.OBJ_ID
    FROM LINKS L2
    WHERE L2.PARENT_ID IS NULL
      AND L2.OBJ_TYPE_ID = 2
      AND L2.DATE_DEL IS NULL
    INTO V$OBJ_ID;

    FOR SELECT
               CASE
                 WHEN VL2.LISTVAL_ID = 22 THEN 1
                 WHEN VL2.LISTVAL_ID = 26 THEN 2
                 WHEN VL2.LISTVAL_ID = 27 THEN 4
               END AS FORMSTEP,
               VL1.LISTVAL_ID - 36 AS FORMNUM, VS.VAL AS FORMINDEX, COALESCE(VS1.VAL, '') AS FIRSTNAME, COALESCE(VS2.VAL, '') AS NAME, COALESCE(VS3.VAL, '') AS LASTNAME,
               CASE
                 WHEN VL.LISTVAL_ID = 183 THEN 1
                 WHEN VL.LISTVAL_ID = 182 THEN 2
               END AS S_SEX,
               VD.VAL AS S_BIRTHDAY
        FROM LINKS L7
        JOIN VALL VL2 ON L7.OBJ_ID = VL2.OBJ_ID AND VL2.PARAM_ID = 43 AND VL2.IS_DEL = 0
        JOIN LINKS L8 ON L7.OBJ_ID = L8.PARENT_ID AND L8.DATE_DEL IS NULL
        JOIN VALL VL1 ON L8.OBJ_ID = VL1.OBJ_ID AND VL1.PARAM_ID = 49 AND VL1.IS_DEL = 0
        JOIN LINKS L9 ON L8.OBJ_ID = L9.PARENT_ID AND L9.DATE_DEL IS NULL
        JOIN VALS VS ON L9.OBJ_ID = VS.OBJ_ID AND VS.PARAM_ID = 54 AND VS.IS_DEL = 0
        JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.DATE_DEL IS NULL
        JOIN VALS VS1 ON L10.OBJ_ID = VS1.OBJ_ID AND VS1.PARAM_ID = 55 AND VS1.IS_DEL = 0
        LEFT JOIN VALS VS2 ON L10.OBJ_ID = VS2.OBJ_ID AND VS2.PARAM_ID = 56 AND VS2.IS_DEL = 0
        LEFT JOIN VALS VS3 ON L10.OBJ_ID = VS3.OBJ_ID AND VS3.PARAM_ID = 57 AND VS3.IS_DEL = 0
        JOIN VALL VL ON L10.OBJ_ID = VL.OBJ_ID AND VL.PARAM_ID = 88 AND VL.IS_DEL = 0
        JOIN VALD VD ON L10.OBJ_ID = VD.OBJ_ID AND VD.PARAM_ID = 89 AND VD.IS_DEL = 0
        WHERE L7.OBJ_TYPE_ID = 7
          AND L7.DATE_DEL IS NULL
          AND L7.PARENT_ID = :V$OBJ_ID
        ORDER BY 1
        INTO V$FORMSTEP, V$FORMNUM, V$FORMINDEX, FIRSTNAME, NAME, LASTNAME, S_SEX, S_BIRTHDAY
    DO
    BEGIN
        KEYFIELDFULL = :V$FORMSTEP || :V$FORMNUM || :V$FORMINDEX || FIRSTNAME || NAME || LASTNAME || S_SEX || S_BIRTHDAY;
        KEYFIELD = :V$FORMSTEP || :V$FORMNUM || :V$FORMINDEX;
        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_SCHOOL_LIST (
    DISTRICT_ID BIGINT)
RETURNS (
    SCHOOL_ID BIGINT,
    SCHOOL_CAPTION VARCHAR(4000),
    SORT_ORDER DOUBLE PRECISION)
AS
BEGIN
    FOR SELECT L.OBJ_ID, SN.VAL, COALESCE(O.VAL, 1E15)
        FROM LINKS L
        LEFT JOIN VALS SN ON SN.OBJ_ID = L.obj_id AND SN.PARAM_ID = 2 AND SN.IS_DEL = 0
        LEFT JOIN VALI O ON O.OBJ_ID = l.obj_id AND O.PARAM_ID = 17 AND O.IS_DEL = 0
        WHERE (L.PARENT_ID = :DISTRICT_ID OR :DISTRICT_ID IS NULL)
          AND L.DATE_DEL IS NULL
          AND L.OBJ_TYPE_ID = 2
        INTO :SCHOOL_ID, :SCHOOL_CAPTION, :SORT_ORDER
    DO
        SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_SESSION_COMPLETE (
    I$SESSION_ID BIGINT,
    I$USER_ID BIGINT,
    I$FORCE SMALLINT = 0)
RETURNS (
    SESSION_STATE_ID INTEGER)
AS
DECLARE VARIABLE V$PERSON_ID BIGINT;
DECLARE VARIABLE N INTEGER;
DECLARE VARIABLE V$QUESTION_ID BIGINT;
DECLARE VARIABLE V$VARIANT_ID BIGINT;
DECLARE VARIABLE V$EXAM_ID BIGINT;
DECLARE VARIABLE RR INTEGER;
begin

  -- Завершаем тестирование
  -- Если остались неотвеченные вопросы и не установлен флаг FORCE - сессия не закроется

  -- По USER_ID определяем персону
  SELECT U.OBJ_ID FROM USERS U WHERE U.USER_ID = :I$USER_ID INTO :V$PERSON_ID;

  SELECT S.STATE_ID, S.VARIANT_ID, S.ED_ID
  FROM UT_SESSIONS S
  WHERE S.OBJ_ID = :I$SESSION_ID AND S.PERSON_ID = :V$PERSON_ID AND S.DATE_DEL IS NULL
  INTO :SESSION_STATE_ID, :V$VARIANT_ID, :V$EXAM_ID;

  IF(SESSION_STATE_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Сессия тестирования утрачена или относится к другому человеку';
  IF(SESSION_STATE_ID >= 100) THEN EXCEPTION DATA_ERROR 'Сессия тестирования уже завершена';

  -- Есть ли неотвеченные вопросы в масштабах теста ?
  -- Собираем из двух частей - те что уже были сформированы, и те что не были сфомированы, но должны быть по структуре
  N = 0;
  SELECT FIRST 1 1
  FROM UT_SESSION_QUESTIONS SQ
  WHERE SQ.SESSION_ID = :I$SESSION_ID AND SQ.DATE_DEL IS NULL AND SQ.STATE_ID < 21
  INTO :N;

  /*SELECT FIRST 1 1
  FROM UT_SESSIONS S
  JOIN UT_EXAM_TEST_VARS ETV ON ETV.OBJ_ID = S.VARIANT_ID
  JOIN UT_TEST_VARS TV ON TV.OBJ_ID = ETV.TEST_VAR_ID
  JOIN UT_TESTS T ON T.OBJ_ID = TV.TEST_ID
  JOIN UT_TEST_STRUCTS TS ON T.OBJ_ID = T.STRUCT_ID
  -- Идем по номерам вопросов из описания структуры
  JOIN UT_TEST_STRUCT_POINTS TSP ON TSP.STRUCT_ID = T.OBJ_ID AND TSP.DATE_DEL IS NULL
  WHERE S.OBJ_ID = :I$SESSION_ID AND SQ.STATE_ID < 21
  INTO :N;*/

  -- Загружаем нулевые результаты по всем неотвеченным вопросам, указывая причину NETWORK_DATA
  IF(N <> 0 AND I$FORCE = 1) THEN
  BEGIN
    -- Закрываем сформированные неотмеченные вопросы
    FOR
      SELECT SQ.OBJ_ID
      FROM UT_SESSION_QUESTIONS SQ
      WHERE SQ.SESSION_ID = :I$SESSION_ID AND SQ.DATE_DEL IS NULL AND SQ.STATE_ID < 21
      INTO :V$QUESTION_ID
    DO
    BEGIN
      -- !!! Переделка
      /*INSERT INTO UT_SESSION_RESULTS
      (QUESTION_ID, CRITERIA_ID, EXPERT_ID, LEVEL_ID, STATE_ID, RAW_RESULT)
      VALUES (:V$QUESTION_ID, 0, NULL, 0, 1000, 0);*/

      UPDATE UT_SESSION_QUESTIONS
      SET STATE_ID = 1000, NETWORK_DATA = NULL, RAW_RESULT = 0
      WHERE OBJ_ID = :V$QUESTION_ID;
    END

    -- Вопросы, которые не были сформированы, так и оставляем отсутствующими

    -- И зануляем счетчик ошибок
    N = 0;

  END

  -- Фиксируем сессию в статусе готовности сырого результата
  -- TODO: если вопросы позволяют сформировать финальный результат, формируем его прямо тут
  IF(N = 0) THEN
  BEGIN
    -- Если в тесте есть вопросы для экспертной проверки - статус пока подвешиваем
    -- Если все вопросы уже проверились - ставим завершенный статус
    SESSION_STATE_ID = 100;
    IF(V$VARIANT_ID IS NOT NULL) THEN
    BEGIN
      -- Полный вариант
      SELECT FIRST 1 10
      FROM UT_SESSION_QUESTIONS SQ
      JOIN UT_TEST_VAR_QUESTIONS TVQ ON TVQ.OBJ_ID = SQ.QUESTION_ID
      JOIN UT_QUESTIONS Q ON Q.OBJ_ID = TVQ.QUESTION_ID AND Q.QUESTION_TYPE IN (3, 8)
      WHERE SQ.SESSION_ID = :I$SESSION_ID AND SQ.DATE_DEL IS NULL
      INTO :SESSION_STATE_ID;
    END
    ELSE
    BEGIN
      -- Упрощенный вариант
      SELECT FIRST 1 10
      FROM UT_SESSION_QUESTIONS SQ
      JOIN UT_EXAM_QUESTIONS EQ ON EQ.OBJ_ID = SQ.QUESTION_RAW
      JOIN UT_QUESTIONS Q ON Q.OBJ_ID = EQ.QUESTION_ID AND Q.QUESTION_TYPE IN (3, 8)
      WHERE SQ.SESSION_ID = :I$SESSION_ID AND SQ.DATE_DEL IS NULL
      INTO :SESSION_STATE_ID;
    END

    SELECT SUM(RAW_RESULT)
    FROM UT_SESSION_QUESTIONS
    WHERE SESSION_ID = :I$SESSION_ID AND DATE_DEL IS NULL
    INTO :RR;

    UPDATE UT_SESSIONS
    SET STATE_ID = :SESSION_STATE_ID, RAW_RESULT = :RR, COMPLETED_AT = CURRENT_TIMESTAMP
    WHERE OBJ_ID = :I$SESSION_ID;

    -- Можно пересчитать итоговую оценку ?
    IF(SESSION_STATE_ID = 100) THEN
      SELECT COUNT(*) FROM UT_EXAM_SCALE_APPLY(:V$EXAM_ID, NULL, :I$SESSION_ID) INTO :N;
  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_SESSION_GET (
    I$SESSION_ID BIGINT,
    I$QUESTION_NUM INTEGER,
    I$USER_ID BIGINT)
RETURNS (
    FLOW_MODE SMALLINT,
    QUESTIONS_MASK VARCHAR(1000),
    QUESTION_NUM INTEGER,
    MAX_ORDER INTEGER,
    IS_LAST SMALLINT)
AS
DECLARE VARIABLE V$Q_ID BIGINT;
DECLARE VARIABLE V$TMP_NUM INTEGER;
DECLARE VARIABLE N INTEGER;
DECLARE VARIABLE V$EXAM_ID BIGINT;
DECLARE VARIABLE V$VARIANT_ID BIGINT;
DECLARE VARIABLE V$VARIANT_INDEX SMALLINT;
DECLARE VARIABLE D1 DATE;
DECLARE VARIABLE D2 DATE;
DECLARE VARIABLE V$RESULTS_ALW INTEGER;
DECLARE VARIABLE V$STATE INTEGER;
begin

  -- Дополнительно проверяем что пользователь сессии правильный
  SELECT ED.FLOW_MODE, S.ED_ID, S.VARIANT_ID, S.VARIANT_INDEX, ED.EXAM_DATE_START, ED.EXAM_DATE_END, ED.EXAM_STATE, ED.RESULTS_ALW
  FROM UT_SESSIONS S
  JOIN UT_EXAM_DATES ED ON ED.OBJ_ID = S.ED_ID AND ED.DATE_DEL IS NULL
  JOIN USERS U ON U.OBJ_ID = S.PERSON_ID AND U.DATE_DEL IS NULL AND U.USER_ID = :I$USER_ID
  WHERE S.OBJ_ID = :I$SESSION_ID AND S.DATE_DEL IS NULL
  INTO :FLOW_MODE, :V$EXAM_ID, :V$VARIANT_ID, :V$VARIANT_INDEX, :D1, :D2, :V$STATE, :V$RESULTS_ALW;

  IF(FLOW_MODE IS NULL) THEN EXCEPTION DATA_ERROR 'Сессия тестирования или само тестирование не найдены';

  -- После окончания теста можно смотреть детализацию
  IF(V$STATE <> 1000) THEN
  BEGIN
    IF(CURRENT_DATE < D1) THEN EXCEPTION DATA_ERROR 'Нельзя проходить тестирование раньше назначенной даты';
    IF(CURRENT_DATE > D2) THEN EXCEPTION DATA_ERROR 'Нельзя проходить тестирование позже назначенной даты';
  END
  ELSE
  BEGIN
    IF(V$RESULTS_ALW = 1) THEN EXCEPTION DATA_ERROR 'Вы не можете просмотреть детализованные результаты по данному тесту';
  END

  -- Когда режим сдачи не-лента, и сессия не завершена - всегда выдаем номер вопроса
  -- IF(FLOW_MODE <> 2 AND I$QUESTION_NUM IS NULL) THEN I$QUESTION_NUM = -1;

  -- Маска статусов вопросов - отвечен/не-отвечен - только если вопросы отображаются поодиночке, а не простыней
  QUESTIONS_MASK = '';

  -- Идем по структуре
  -- Полный вариант
  FOR
    SELECT TSP.OBJ_ID
    FROM UT_EXAM_TEST_VARS ETV
    JOIN UT_TEST_VARS TV ON TV.OBJ_ID = ETV.TEST_VAR_ID
    JOIN UT_TESTS T ON T.OBJ_ID = TV.TEST_ID
    JOIN UT_TEST_STRUCTS TS ON TS.OBJ_ID = T.STRUCT_ID
    JOIN UT_TEST_STRUCT_POINTS TSP ON TSP.STRUCT_ID = TS.OBJ_ID AND TSP.DATE_DEL IS NULL
    WHERE ETV.OBJ_ID = :V$VARIANT_ID AND :V$VARIANT_ID IS NOT NULL
    ORDER BY TSP.Q_ORDER
    INTO :V$Q_ID
  DO
  BEGIN
    -- Ответ ? Предполагается что в назначении таки ровно один вопрос на позицию структуры
    N = 0;
    SELECT FIRST 1 1
    FROM UT_SESSION_QUESTIONS SQ
    JOIN UT_TEST_VAR_QUESTIONS TVQ ON TVQ.OBJ_ID = SQ.QUESTION_ID AND TVQ.STRUCT_POINT_ID = :V$Q_ID AND TVQ.DATE_DEL IS NULL
    WHERE SQ.SESSION_ID = :I$SESSION_ID AND SQ.DATE_DEL IS NULL AND SQ.STATE_ID >= 20
    INTO :N;

    QUESTIONS_MASK = QUESTIONS_MASK || N;
  END
  -- Упрощенный вариант - вопросы все равно уже распределены
  FOR
    SELECT Q.SORT_INDEX, IIF(SQ.STATE_ID >= 20, 1, 0)
    FROM UT_SESSION_QUESTIONS SQ
    JOIN UT_EXAM_QUESTIONS Q ON Q.OBJ_ID = SQ.QUESTION_RAW
    WHERE SQ.DATE_DEL IS NULL AND SQ.SESSION_ID = :I$SESSION_ID AND :V$VARIANT_INDEX IS NOT NULL
    ORDER BY Q.SORT_INDEX
    INTO :V$Q_ID, :N
  DO
  BEGIN
    QUESTIONS_MASK = QUESTIONS_MASK || N;
  END

  -- Если передан I$QUESTION_NUM < 0, возвращаем первый неотвеченный вопрос с номером >= запрошенного по модулю
  IF(I$QUESTION_NUM < 0) THEN
  BEGIN
    -- Инвертируем знак и ищем первый неотвеченный
    V$TMP_NUM = - I$QUESTION_NUM;
    I$QUESTION_NUM = NULL;

    SELECT FIRST 1 TSP.Q_ORDER
    FROM UT_SESSION_QUESTIONS SQ
    JOIN UT_TEST_VAR_QUESTIONS TVQ ON TVQ.OBJ_ID = SQ.QUESTION_ID AND TVQ.DATE_DEL IS NULL
    -- Структура нужна чтобы получить порядковый номер вопроса
    JOIN UT_TEST_STRUCT_POINTS TSP ON TSP.OBJ_ID = TVQ.STRUCT_POINT_ID AND TSP.DATE_DEL IS NULL
    WHERE SQ.SESSION_ID = :I$SESSION_ID AND SQ.DATE_DEL IS NULL AND TSP.Q_ORDER >= :V$TMP_NUM AND SQ.STATE_ID < 21 AND :V$VARIANT_ID IS NOT NULL
    UNION
    SELECT FIRST 1 Q.SORT_INDEX
    FROM UT_SESSION_QUESTIONS SQ
    JOIN UT_EXAM_QUESTIONS Q ON Q.OBJ_ID = SQ.QUESTION_RAW AND Q.VARIANT_INDEX = :V$VARIANT_INDEX
    WHERE SQ.SESSION_ID = :I$SESSION_ID AND SQ.DATE_DEL IS NULL AND Q.SORT_INDEX >= :V$TMP_NUM AND SQ.STATE_ID < 21 AND :V$VARIANT_INDEX IS NOT NULL
    ORDER BY 1
    INTO :I$QUESTION_NUM;

    -- Если больше вопросов нет, возвращаем снова первый ? или возвращаем -1 ?
    IF(I$QUESTION_NUM IS NULL) THEN I$QUESTION_NUM = 9999;
  END

  QUESTION_NUM = I$QUESTION_NUM;

  -- Какой у нас последний номер вопроса в структуре ?
  -- Если запросили вопрос с номером N+1, возвращаем фейковый вопрос с типом final, и заполненным order
  MAX_ORDER = 0;
  SELECT MAX(V.Q_ORDER) FROM (
    SELECT TSP.Q_ORDER Q_ORDER
    FROM UT_EXAM_TEST_VARS ETV
    JOIN UT_TEST_VARS TV ON TV.OBJ_ID = ETV.TEST_VAR_ID
    JOIN UT_TESTS T ON T.OBJ_ID = TV.TEST_ID
    JOIN UT_TEST_STRUCT_POINTS TSP ON TSP.STRUCT_ID = T.STRUCT_ID AND TSP.DATE_DEL IS NULL
    WHERE ETV.OBJ_ID = :V$VARIANT_ID AND :V$VARIANT_ID IS NOT NULL
    UNION
    SELECT Q.SORT_INDEX
    FROM UT_EXAM_QUESTIONS Q
    WHERE Q.DATE_DEL IS NULL AND Q.EXAM_ID = :V$EXAM_ID AND Q.VARIANT_INDEX = :V$VARIANT_INDEX AND :V$VARIANT_INDEX IS NOT NULL
  ) V
  INTO :MAX_ORDER;

  IF(I$QUESTION_NUM IS NOT NULL AND I$QUESTION_NUM > MAX_ORDER) THEN IS_LAST = 1; ELSE IS_LAST = 0;

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_SESSION_QUESTIONS_GET (
    I$SESSION_ID BIGINT,
    I$QUESTION_NUM INTEGER)
RETURNS (
    RECORD_TYPE SMALLINT,
    INSTANCE_ID BIGINT,
    QUESTION_ID BIGINT,
    TYPE_ID SMALLINT,
    TYPE_NAME VARCHAR(100),
    Q_ORDER SMALLINT,
    MAX_SCORE SMALLINT,
    ANSWER_STATE INTEGER,
    ANSWER_STATE_NAME VARCHAR(100),
    METADATA_SID VARCHAR(40),
    METADATA_ID VARCHAR(40),
    ANSWER_DATA VARCHAR(4000),
    RAW_RESULT INTEGER,
    QUESTION_NAME VARCHAR(400),
    QUESTION_DATA BLOB SUB_TYPE 1 SEGMENT SIZE 80,
    QUESTION_SIGNATURE SMALLINT,
    FLAGS INTEGER,
    SESSION_Q_FILE_ID VARCHAR(40),
    K VARCHAR(64),
    FILE_SIZE INTEGER,
    TIME_LIMIT INTEGER,
    HINT BLOB SUB_TYPE 1 SEGMENT SIZE 80,
    HSIGNATURE BIGINT)
AS
DECLARE VARIABLE V$TYPE_ID SMALLINT;
DECLARE VARIABLE V$STATE INTEGER;
begin

  -- I$QUESTION_NUM - номер вопроса, который мы хотим получить, или NULL если хотим получить первый

  -- RECORD_TYPE определяет тип записи
  -- 0 = заголовок вопроса
  -- 1 = вариант ответа
  -- 2 = закрытие вопроса

  SELECT FIRST 1 D.EXAM_STATE
  FROM UT_SESSIONS S
  JOIN UT_EXAM_DATES D ON D.OBJ_ID = S.ED_ID
  WHERE S.OBJ_ID = :I$SESSION_ID
  INTO :V$STATE;

  -- Идем во порядку вопросов в структуре
  FOR
    -- Полный вариант
    SELECT TSP.Q_TYPE_ID, QT.OBJ_NAME, TSP.Q_ORDER, TSP.Q_MAX_SCORE, SQ.STATE_ID, QAS.OBJ_NAME, SQ.OBJ_ID,
      Q.OBJ_ID, Q.OBJ_NAME, Q.METADATA_ID, SQ.METADATA_ID, SQ.ANSWER_DATA, SQ.RAW_RESULT, Q.QUESTION, Q.FLAGS, SQ.METADATA_ID, Q.K, Q.FILE_SIZE, Q.TIME_LIMIT, Q.HINT
    FROM UT_SESSIONS S
    JOIN UT_SESSION_QUESTIONS SQ ON SQ.SESSION_ID = S.OBJ_ID AND SQ.DATE_DEL IS NULL AND SQ.QUESTION_ID IS NOT NULL
    JOIN UT_ANSWER_STATES QAS ON QAS.OBJ_ID = SQ.STATE_ID
    JOIN UT_TEST_VAR_QUESTIONS TVQ ON TVQ.OBJ_ID = SQ.QUESTION_ID AND TVQ.DATE_DEL IS NULL
    -- Структура нужна чтобы получить порядковый номер вопроса
    JOIN UT_TEST_STRUCT_POINTS TSP ON TSP.OBJ_ID = TVQ.STRUCT_POINT_ID AND TSP.DATE_DEL IS NULL
    -- Сразу достаем данные вопроса, он точно уникальный
    JOIN UT_QUESTIONS Q ON Q.OBJ_ID = TVQ.QUESTION_ID AND (Q.DATE_DEL IS NULL OR :V$STATE = 1000)
    JOIN UT_QUESTION_TYPE QT ON QT.OBJ_ID = Q.QUESTION_TYPE
    WHERE S.OBJ_ID = :I$SESSION_ID AND (:I$QUESTION_NUM IS NULL OR TSP.Q_ORDER = :I$QUESTION_NUM)
    UNION
    -- Упрощенный вариант
    SELECT Q.QUESTION_TYPE, QT.OBJ_NAME, EQ.SORT_INDEX, Q.MAX_SCORE, SQ.STATE_ID, QAS.OBJ_NAME, SQ.OBJ_ID,
      Q.OBJ_ID, Q.OBJ_NAME, Q.METADATA_ID, SQ.METADATA_ID, SQ.ANSWER_DATA, SQ.RAW_RESULT, Q.QUESTION, Q.FLAGS, SQ.METADATA_ID, Q.K, Q.FILE_SIZE, Q.TIME_LIMIT, Q.HINT
    FROM UT_SESSIONS S
    JOIN UT_SESSION_QUESTIONS SQ ON SQ.SESSION_ID = S.OBJ_ID AND SQ.DATE_DEL IS NULL AND SQ.QUESTION_RAW IS NOT NULL
    JOIN UT_ANSWER_STATES QAS ON QAS.OBJ_ID = SQ.STATE_ID
    JOIN UT_EXAM_QUESTIONS EQ ON EQ.OBJ_ID = SQ.QUESTION_RAW
    -- Сразу достаем данные вопроса, он точно уникальный
    -- проверку по Q.DATE_DEL выключаем, иначе
    JOIN UT_QUESTIONS Q ON Q.OBJ_ID = EQ.QUESTION_ID AND (Q.DATE_DEL IS NULL OR :V$STATE = 1000)
    JOIN UT_QUESTION_TYPE QT ON QT.OBJ_ID = Q.QUESTION_TYPE
    WHERE S.OBJ_ID = :I$SESSION_ID AND (:I$QUESTION_NUM IS NULL OR EQ.SORT_INDEX = :I$QUESTION_NUM)
    ORDER BY 3
    INTO :TYPE_ID, :TYPE_NAME, :Q_ORDER, :MAX_SCORE, :ANSWER_STATE, :ANSWER_STATE_NAME, :INSTANCE_ID,
      :QUESTION_ID, :QUESTION_NAME, :METADATA_ID, :METADATA_SID, :ANSWER_DATA, :RAW_RESULT, :QUESTION_DATA, :FLAGS, :SESSION_Q_FILE_ID, :K, :FILE_SIZE, :TIME_LIMIT, :HINT
  DO
  BEGIN
    -- Сначала отдаем заголовок самого вопроса с реальным INSTANCE_ID
    V$TYPE_ID = TYPE_ID;
    RECORD_TYPE = 0;
    HSIGNATURE = NULL;
    SUSPEND;

    -- Обнуляем все лишние поля, остаются только Q_ORDER, INSTANCE_ID, QUESTION_NAME, QUESTION_DATA
    TYPE_ID = NULL;
    TYPE_NAME = NULL;
    ANSWER_STATE = NULL;
    ANSWER_STATE_NAME = NULL;
    METADATA_ID = NULL;
    METADATA_SID = NULL;
    ANSWER_DATA = NULL;
    RAW_RESULT = NULL;
    QUESTION_SIGNATURE = NULL;
    MAX_SCORE = NULL;
    FLAGS = NULL;
    HINT = NULL;
    RECORD_TYPE = 1;
  
    -- Внимание: для вопросов на соответствие порядок вопросов однозначно определяет само соответствие и фейковые варианты,
    -- поэтому вопросы при выдаче сортируем не по SORT_ORDER, а по случайному FAKE_ORDER (генерируется при сохранении вопроса)
    -- для всех остальных типов вопросов он равен SORT_ORDER
    FOR
      SELECT A.OBJ_ID, A.SORT_ORDER, A.OBJ_NAME, A.SIGNATURE, A.VARIANT, A.HSIGNATURE
      FROM UT_ANSWERS A
      WHERE A.DATE_DEL IS NULL AND A.QUESTION_ID = :QUESTION_ID AND A.DATE_DEL IS NULL AND :V$TYPE_ID IN (1, 2, 4, 5)
      ORDER BY A.FAKE_ORDER
      INTO :INSTANCE_ID, :Q_ORDER, :QUESTION_NAME, :QUESTION_SIGNATURE, :QUESTION_DATA, :HSIGNATURE
    DO
    BEGIN
      -- Для вопроса на соответствие в ORDER хранится ссылка на левую или правую половину списка (оставляем только знак)
      IF(V$TYPE_ID = 4) THEN BEGIN
        IF(Q_ORDER < 0) THEN Q_ORDER = -1;
        ELSE IF(Q_ORDER > 0) THEN Q_ORDER = 1;
      END
      SUSPEND;
    END

    -- Закрываем вопрос
    RECORD_TYPE = 2;
    INSTANCE_ID = NULL;
    QUESTION_NAME = NULL;
    QUESTION_DATA = NULL;
    Q_ORDER = NULL;
    QUESTION_SIGNATURE = NULL;
    HSIGNATURE = NULL;
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_SESSION_START (
    I$SESSION_ID BIGINT,
    I$EXAM_ID BIGINT,
    I$MODE SMALLINT,
    I$PERSON_ID BIGINT,
    I$NETWORK_DATA VARCHAR(100),
    I$USER_ID VARCHAR(40))
RETURNS (
    SESSION_ID BIGINT,
    DURATION INTEGER)
AS
DECLARE VARIABLE V$STATE_ID INTEGER;
DECLARE VARIABLE V$VARIANT_ID BIGINT;
DECLARE VARIABLE V$VARIANT_INDEX SMALLINT;
DECLARE VARIABLE V$TSP_ID BIGINT;
DECLARE VARIABLE V$Q_ID BIGINT;
DECLARE VARIABLE V$STATE INTEGER;
DECLARE VARIABLE V$PLAN_METHOD_ID INTEGER;
DECLARE VARIABLE V$PA_OBJ_ID BIGINT; /* нужно только для того, чтобы не срабатывал ворнинг */
DECLARE VARIABLE V$PA_EXAM_ID BIGINT; /* нужно только для того, чтобы не срабатывал ворнинг */
DECLARE VARIABLE V$PA_EXAM_NAME VARCHAR(200); /* нужно только для того, чтобы не срабатывал ворнинг */
DECLARE VARIABLE V$PA_EXAM_DATE DATE; /* нужно только для того, чтобы не срабатывал ворнинг */
DECLARE VARIABLE D1 DATE;
DECLARE VARIABLE D2 DATE;
DECLARE VARIABLE V$ATTEMPTS INTEGER;
DECLARE VARIABLE N INTEGER;
BEGIN
  -- I$MODE:
  -- 0 = начать тестирование (все прошлые сессии отменяем)
  -- 1 = отменить тестирование
  -- 2 = продолжить тестирование
  -- 3 = начать тестирование заново (работает аналогично 1+0)
  -- 103 = техническая ошибка

  -- Случай заранее назначенного варианта
  IF(I$MODE = 0 AND I$SESSION_ID IS NOT NULL) THEN I$MODE = 2;

  SELECT D.EXAM_STATE, D.PLAN_METHOD_ID, D.EXAM_DATE_START, D.EXAM_DATE_END, D.ATTEMPTS
  FROM UT_EXAM_DATES D
  WHERE D.DATE_DEL IS NULL AND D.OBJ_ID = :I$EXAM_ID
  INTO :V$STATE, :V$PLAN_METHOD_ID, :D1, :D2, :V$ATTEMPTS;

  IF(V$STATE <> 600) THEN EXCEPTION DATA_ERROR 'Тестирование не находится в статусе проведения';
  IF(CURRENT_DATE < D1) THEN EXCEPTION DATA_ERROR 'Нельзя проходить тестирование раньше назначенной даты';
  IF(CURRENT_DATE > D2) THEN EXCEPTION DATA_ERROR 'Нельзя проходить тестирование позже назначенной даты';

  -- Уже завершенные тестирования трогать нельзя
  IF(I$SESSION_ID IS NOT NULL) THEN
  BEGIN
    SELECT STATE_ID, DURATION
    FROM UT_SESSIONS
    WHERE DATE_DEL IS NULL AND OBJ_ID = :I$SESSION_ID
    INTO :V$STATE_ID, :DURATION;

    IF(V$STATE_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Сессия тестирования утрачена или не найдена';
    IF(V$STATE_ID >= 100 AND I$MODE <> 3) THEN EXCEPTION DATA_ERROR 'Сессия тестирования уже завершена и не может быть сброшена';
  END

  IF(I$MODE IN (0, 3) AND V$ATTEMPTS > 0) THEN
  BEGIN
    SELECT COUNT(*)
    FROM UT_SESSIONS S
    WHERE S.DATE_DEL IS NULL AND S.ED_ID = :I$EXAM_ID AND S.PERSON_ID = :I$PERSON_ID AND S.STATE_ID > 0
    INTO :N;

    IF(N >= V$ATTEMPTS) THEN EXCEPTION DATA_ERROR 'Количество попыток прохождения исчерпано, нельзя пройти повторно';
  END

  -- Отменяем текущее тестирование в статус 101
  -- Тут надо проверить, разрешено ли сбрасывать сессии в данном тесте !
  IF(I$MODE IN (1, 3)) THEN
  BEGIN
    UPDATE UT_SESSIONS
    SET RAW_RESULT = NULL, STATE_ID = 101
    WHERE DATE_DEL IS NULL AND OBJ_ID = :I$SESSION_ID AND STATE_ID < 100;
  END

  -- техническая ошибка (сбрасываем старое, далее создадим новое)
  IF(I$MODE = 103) THEN
  BEGIN
    UPDATE UT_SESSIONS
    SET RAW_RESULT = NULL, STATE_ID = 103
    WHERE DATE_DEL IS NULL AND OBJ_ID = :I$SESSION_ID AND STATE_ID < 100;
  END

  -- Создаем новую сессиию тестирования
  IF(I$MODE IN (0, 3, 103)) THEN
  BEGIN
    IF(V$PLAN_METHOD_ID = 4) THEN
    BEGIN
      SELECT FIRST 1 Q.VARIANT_INDEX
      FROM UT_EXAM_QUESTIONS Q
      WHERE Q.DATE_DEL IS NULL AND Q.EXAM_ID = :I$EXAM_ID
      ORDER BY RAND()
      INTO :V$VARIANT_INDEX;

      IF(V$VARIANT_INDEX IS NULL) THEN EXCEPTION DATA_ERROR 'Не внесены вопросы для тестирования';
    END
    ELSE
    BEGIN
      SELECT FIRST 1 V.OBJ_ID
      FROM UT_EXAM_TEST_VARS V
      WHERE V.DATE_DEL IS NULL AND V.EXAM_ID = :I$EXAM_ID
      ORDER BY RAND()
      INTO :V$VARIANT_ID;

      IF(V$VARIANT_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не заданы варианты тестирования';
    END

    DURATION = 1;

    -- создаем назначение на тестирование для тестирования всех желающих
    IF (V$PLAN_METHOD_ID = 3) THEN BEGIN
      SELECT * FROM UT_EXAM_PERSON_ASSN_SET(:I$EXAM_ID, :I$PERSON_ID, :I$USER_ID, 1)
      INTO :V$PA_OBJ_ID, :V$PA_EXAM_ID, :V$PA_EXAM_NAME, :V$PA_EXAM_DATE;
    END

    INSERT INTO UT_SESSIONS (ED_ID, PERSON_ID, VARIANT_ID, VARIANT_INDEX, STARTED_AT, STATE_ID, DURATION, TEST_PROGRESS, NETWORK_DATA)
    VALUES (:I$EXAM_ID, :I$PERSON_ID, :V$VARIANT_ID, :V$VARIANT_INDEX, CURRENT_TIMESTAMP, 2, :DURATION, 0, :I$NETWORK_DATA)
    RETURNING OBJ_ID INTO SESSION_ID;

    -- Формируем список вопросов в статусе 10, по 1 вопросу в каждой позиции
    -- Вариант для больших тестирований
    FOR
      SELECT DISTINCT TVQ.STRUCT_POINT_ID
      FROM UT_EXAM_TEST_VARS ETV
      JOIN UT_TEST_VAR_QUESTIONS TVQ ON TVQ.VAR_ID = ETV.TEST_VAR_ID AND TVQ.DATE_DEL IS NULL
      WHERE ETV.OBJ_ID = :V$VARIANT_ID AND ETV.DATE_DEL IS NULL AND :V$VARIANT_ID IS NOT NULL
      ORDER BY TVQ.ORDER_INDEX
      INTO :V$TSP_ID
    DO
    BEGIN
      SELECT FIRST 1 TVQ.OBJ_ID
      FROM UT_EXAM_TEST_VARS ETV
      JOIN UT_TEST_VAR_QUESTIONS TVQ ON TVQ.VAR_ID = ETV.TEST_VAR_ID
      WHERE TVQ.DATE_DEL IS NULL AND ETV.OBJ_ID = :V$VARIANT_ID AND TVQ.STRUCT_POINT_ID = :V$TSP_ID
      ORDER BY RAND()
      INTO :V$Q_ID;

      INSERT INTO UT_SESSION_QUESTIONS
      (SESSION_ID, QUESTION_ID, STATE_ID)
      VALUES(:SESSION_ID, :V$Q_ID, 10);
    END
    -- Упрощенный вариант
    FOR
      SELECT Q.OBJ_ID
      FROM UT_EXAM_QUESTIONS Q
      WHERE Q.DATE_DEL IS NULL AND Q.EXAM_ID = :I$EXAM_ID AND Q.VARIANT_INDEX = :V$VARIANT_INDEX AND :V$VARIANT_INDEX IS NOT NULL
      ORDER BY Q.SORT_INDEX
      INTO :V$Q_ID
    DO
    BEGIN
      INSERT INTO UT_SESSION_QUESTIONS
      (SESSION_ID, QUESTION_RAW, STATE_ID)
      VALUES(:SESSION_ID, :V$Q_ID, 10);
    END
  END
  -- Продолжаем текущее тестирование (либо стартуем)
  ELSE IF(I$MODE = 2) THEN
  BEGIN
    -- Проверяем статус сессии ?
    IF(V$STATE_ID < 2) THEN V$STATE_ID = 2;
    IF(DURATION = 0) THEN DURATION = 1;

    -- DURATION остается тот, который уже был в сессии
    UPDATE UT_SESSIONS
    SET STATE_ID = :V$STATE_ID, NETWORK_DATA = :I$NETWORK_DATA, DURATION = :DURATION
    WHERE OBJ_ID = :I$SESSION_ID;

    SESSION_ID = I$SESSION_ID;
  END
  -- Начать тестирование заново
  ELSE IF(I$MODE = 1) THEN
  BEGIN
    SESSION_ID = NULL;
    DURATION = 0;
  END

  SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_SESSION_TIME_SET (
    I$SESSION_ID BIGINT,
    I$USER_ID BIGINT,
    I$TIME INTEGER)
RETURNS (
    SESSION_STATE_ID INTEGER)
AS
DECLARE VARIABLE V$PERSON_ID BIGINT;
DECLARE VARIABLE V$DURATION INTEGER;
DECLARE VARIABLE V$TIME_LIMIT INTEGER;
begin

  -- По USER_ID определяем персону
  SELECT U.OBJ_ID FROM USERS U WHERE U.USER_ID = :I$USER_ID INTO :V$PERSON_ID;

  SELECT S.STATE_ID, S.DURATION, ED.DURATION
  FROM UT_SESSIONS S
  JOIN UT_EXAM_DATES ED ON ED.OBJ_ID = S.ED_ID
  WHERE S.OBJ_ID = :I$SESSION_ID AND S.PERSON_ID = :V$PERSON_ID AND S.DATE_DEL IS NULL
  INTO :SESSION_STATE_ID, :V$DURATION, :V$TIME_LIMIT;

  IF(SESSION_STATE_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Сессия тестирования утрачена или относится к другому человеку';

  IF(SESSION_STATE_ID < 10) THEN
  BEGIN
    IF(I$TIME >= V$DURATION) THEN
    BEGIN
      IF(V$TIME_LIMIT IS NOT NULL AND I$TIME >= V$TIME_LIMIT * 60) THEN
      BEGIN
        -- Время истекло, обновляем время и статус
        SESSION_STATE_ID = 10;
        UPDATE UT_SESSIONS
        SET DURATION = :I$TIME, STATE_ID = :SESSION_STATE_ID
        WHERE OBJ_ID = :I$SESSION_ID;
      END
      ELSE
      BEGIN
        -- Обновляем только время
        UPDATE UT_SESSIONS
        SET DURATION = :I$TIME
        WHERE OBJ_ID = :I$SESSION_ID;
      END
    END
  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_SET_STRUCTS_LIST (
    I$SUBJECT_ID BIGINT,
    I$STAGE_ID INTEGER,
    I$METHOD_ID INTEGER)
RETURNS (
    OBJ_ID BIGINT,
    OBJ_NAME VARCHAR(1000))
AS
begin

  FOR
      SELECT OBJ_ID, OBJ_NAME
      FROM UT_TEST_STRUCTS
      WHERE DATE_DEL IS NULL AND STAGE_ID = :I$STAGE_ID AND METHOD_ID = :I$METHOD_ID AND IS_AUTO = 0 AND
          ((:I$SUBJECT_ID IS NULL AND SUBJECT_ID IS NULL) OR SUBJECT_ID = :I$SUBJECT_ID)
      ORDER BY 2
      INTO :OBJ_ID, :OBJ_NAME
  DO
  BEGIN
      SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_STUDENT_DESC (
    I$OBJ_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    NAME_LAST VARCHAR(200),
    NAME_FIRST VARCHAR(200),
    NAME_MID VARCHAR(200),
    NAME_FULL VARCHAR(400),
    BIRTH_DATE DATE,
    OU_ID BIGINT,
    OU_NAME VARCHAR(200),
    AREA_ID BIGINT,
    AREA_NAME VARCHAR(200),
    STAGE_ID BIGINT,
    STAGE_NAME VARCHAR(40),
    CLASS_ID BIGINT,
    CLASS_NAME VARCHAR(40))
AS
begin

  OBJ_ID = I$OBJ_ID;

  -- ФИО и дата рождения
  SELECT FIRST 1 V55.VAL, V56.VAL, V57.VAL, V89.VAL
  FROM OBJECTS O
  JOIN VALS V55 ON V55.OBJ_ID = O.OBJ_ID AND V55.PARAM_ID = 55 AND V55.IS_DEL = 0
  JOIN VALS V56 ON V56.OBJ_ID = O.OBJ_ID AND V56.PARAM_ID = 56 AND V56.IS_DEL = 0
  LEFT JOIN VALS V57 ON V57.OBJ_ID = O.OBJ_ID AND V57.PARAM_ID = 57 AND V57.IS_DEL = 0
  LEFT JOIN VALD V89 ON V89.OBJ_ID = O.OBJ_ID AND V89.PARAM_ID = 89 AND V89.IS_DEL = 0
  WHERE O.OBJ_ID = :I$OBJ_ID
  INTO :NAME_LAST, :NAME_FIRST, :NAME_MID, :BIRTH_DATE;

  -- Восстанавливаем реквизиты ОУ, класса и уровня
  SELECT LP2.PARENT_ID, V49.LISTVAL_ID, R.VAL, LP9.PARENT_ID, LV.TAG || COALESCE(' ' || V54.VAL, '')
  FROM LINKS LP9
  LEFT JOIN VALS V54 ON V54.OBJ_ID = LP9.PARENT_ID AND V54.PARAM_ID IN (54, 1652) AND V54.IS_DEL = 0
  JOIN LINKS LP8 ON LP8.OBJ_ID = LP9.PARENT_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
  JOIN VALL V49 ON V49.OBJ_ID = LP8.PARENT_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V49.LISTVAL_ID
  JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
  JOIN LINKS LP7 ON LP7.OBJ_ID = LP8.PARENT_ID AND LP7.PARENT_TYPE_ID = 7 AND LP7.DATE_DEL IS NULL
  JOIN LINKS LP2 ON LP2.OBJ_ID = LP7.PARENT_ID AND LP2.PARENT_TYPE_ID = 2 AND LP2.DATE_DEL IS NULL
  WHERE LP9.OBJ_ID = :I$OBJ_ID AND LP9.PARENT_TYPE_ID IN (9, 187) AND LP9.DATE_DEL IS NULL
  INTO :OU_ID, :STAGE_ID, :STAGE_NAME, :CLASS_ID, :CLASS_NAME;

  -- Выбывший ?
  IF(OU_ID IS NULL) THEN
  BEGIN
      SELECT LP2.PARENT_ID
      FROM LINKS LP84
      JOIN LINKS LP2 ON LP2.OBJ_ID = LP84.PARENT_ID AND LP2.PARENT_TYPE_ID = 2 AND LP2.DATE_DEL IS NULL
      WHERE LP84.OBJ_ID = :I$OBJ_ID AND LP84.PARENT_TYPE_ID = 84 AND LP84.DATE_DEL IS NULL
      INTO :OU_ID;
  END

  -- Реквизиты ОУ
  SELECT SUBSTRING(V2.VAL FROM 1 FOR 200), V2163.LISTVAL_ID, R.VAL
  FROM VALS V2
  LEFT JOIN VALL V2163 ON V2163.OBJ_ID = V2.OBJ_ID AND V2163.PARAM_ID = 2163 AND V2163.IS_DEL = 0
  LEFT JOIN LISTVALS LV ON LV.LISTVAL_ID = V2163.LISTVAL_ID
  LEFT JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
  WHERE V2.OBJ_ID = :OU_ID AND V2.PARAM_ID = 2 AND V2.IS_DEL = 0
  INTO :OU_NAME, :AREA_ID, :AREA_NAME;

  NAME_FULL = NAME_LAST || ' ' || NAME_FIRST || COALESCE(' ' || NAME_MID, '');

  SUSPEND;
end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_STUDENT_GET (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(1000))
AS
declare variable V$PERSON_ID bigint;
declare variable V$TYPE_ID integer;
declare variable V$NAME_LAST varchar(200);
declare variable V$NAME_FIRST varchar(200);
declare variable V$NAME_MID varchar(200);
declare variable V$BD date;
declare variable V$JOB_TITLE varchar(200);
declare variable V$STAGE_ID bigint;
declare variable V$CLASS_ID bigint;
declare variable V$STAGE_NAME varchar(100);
declare variable V$CLASS_NAME varchar(100);
declare variable V$AREA_ID bigint;
declare variable V$OU_NAME varchar(200);
declare variable V$AREA_NAME varchar(200);
declare variable V$CURRENT_YEAR integer;
declare variable V$DATE_FROM date;
declare variable V$DATE_TO date;
declare variable V$ASSN_ID bigint;
declare variable V$EXAM_ID bigint;
declare variable V$EXAM_NAME varchar(200);
declare variable V$EXAM_DATE date;
declare variable V$EXAM_STATE integer;
begin

  -- Проверяем
  SELECT FIRST 1 OBJ_ID, OBJ_TYPE_ID
  FROM LINKS LX
  WHERE LX.OBJ_ID = :I$OBJ_ID AND LX.PARENT_TYPE_ID IN (2, 84, 9, 187) AND LX.OBJ_TYPE_ID IN (10, 14) AND LX.DATE_DEL IS NULL
  INTO :V$PERSON_ID, :V$TYPE_ID;

  IF(I$OBJ_ID IS NOT NULL AND V$PERSON_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Данные по учащемуся или сотрудники утрачены, или запись была удалена';

  -- Сотрудники всегда readonly
  TAG_NAME = 'person_readonly';
  VAL = '1';
  SUSPEND;

  IF(V$TYPE_ID = 10) THEN
  BEGIN
      SELECT NAME_LAST, NAME_FIRST, NAME_MID, BIRTH_DATE, OU_NAME, AREA_ID, AREA_NAME, STAGE_ID, STAGE_NAME, CLASS_ID, CLASS_NAME
      FROM UT_STUDENT_DESC(:V$PERSON_ID)
      INTO :V$NAME_LAST, :V$NAME_FIRST, :V$NAME_MID, :V$BD, :V$OU_NAME, :V$AREA_ID, :V$AREA_NAME, :V$STAGE_ID, :V$STAGE_NAME, :V$CLASS_ID, :V$CLASS_NAME;
  END
  ELSE
  BEGIN
      SELECT NAME_LAST, NAME_FIRST, NAME_MID, BIRTH_DATE, JOB_TITLE, OU_NAME, AREA_ID, AREA_NAME
      FROM UT_EMPLOYEE_DESC(:V$PERSON_ID)
      INTO :V$NAME_LAST, :V$NAME_FIRST, :V$NAME_MID, :V$BD, :V$JOB_TITLE, :V$OU_NAME, :V$AREA_ID, :V$AREA_NAME;

      V$STAGE_NAME = 'Сотрудник';
      V$CLASS_NAME = 'Сотрудник';
  END

  TAG_NAME = 'id';
  VAL = I$OBJ_ID;
  SUSPEND;

  TAG_NAME = 'name_last';
  VAL = V$NAME_LAST;
  SUSPEND;

  TAG_NAME = 'name_first';
  VAL = V$NAME_FIRST;
  SUSPEND;

  TAG_NAME = 'name_mid';
  VAL = V$NAME_MID;
  SUSPEND;

  TAG_NAME = 'birth_date';
  VAL = V$BD;
  SUSPEND;

  TAG_NAME = 'stage_id';
  VAL = V$STAGE_ID;
  SUSPEND;

  TAG_NAME = 'stage_name';
  VAL = V$STAGE_NAME;
  SUSPEND;

  TAG_NAME = 'class_id';
  VAL = V$CLASS_ID;
  SUSPEND;

  TAG_NAME = 'class_name';
  VAL = V$CLASS_NAME;
  SUSPEND;

  TAG_NAME = 'ou_name';
  VAL = V$OU_NAME;
  SUSPEND;

  -- Название района
  TAG_NAME = 'area_id';
  VAL = V$AREA_ID;
  SUSPEND;

  TAG_NAME = 'area_name';
  VAL = NULL;
  SELECT R.VAL
  FROM LISTVALS LV
  JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
  WHERE LV.LISTVAL_ID = :V$AREA_ID
  INTO :VAL;
  SUSPEND;

  -- Список тестирований, где назначен - отображаем только текущий учебный период
  -- Текущий учебный год
  IF(EXTRACT(MONTH FROM CURRENT_DATE) < 9) THEN V$CURRENT_YEAR = EXTRACT(YEAR FROM CURRENT_DATE) - 1; ELSE V$CURRENT_YEAR = EXTRACT(YEAR FROM CURRENT_DATE);

  TAG_NAME = 'test_assns';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'test_assns::json&colon;array';
  VAL = '1';
  SUSPEND;

  FOR
      SELECT OBJ_ID, EXAM_ID, EXAM_NAME, EXAM_DATE, STATE
      FROM UT_PERSON_EXAM_ASSNS_LIST(:I$OBJ_ID, :V$CURRENT_YEAR)
      ORDER BY EXAM_DATE
      INTO :V$ASSN_ID, :V$EXAM_ID, :V$EXAM_NAME, :V$EXAM_DATE, :V$EXAM_STATE
  DO
  BEGIN

      TAG_NAME = 'test_assns:r';
      VAL = NULL;
      SUSPEND;

      TAG_NAME = 'test_assns:r:id';
      VAL = V$ASSN_ID;
      SUSPEND;

      TAG_NAME = 'test_assns:r:exam_id';
      VAL = V$EXAM_ID;
      SUSPEND;

      TAG_NAME = 'test_assns:r:name';
      VAL = V$EXAM_NAME;
      SUSPEND;

      TAG_NAME = 'test_assns:r:date';
      VAL = V$EXAM_DATE;
      SUSPEND;

      TAG_NAME = 'test_assns:r:state';
      VAL = V$EXAM_STATE;
      SUSPEND;

  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_STUFF_GET (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(1000))
AS
declare variable V$PERSON_ID bigint;
declare variable V$NAME_LAST varchar(200);
declare variable V$NAME_FIRST varchar(200);
declare variable V$NAME_MID varchar(200);
declare variable V$BD date;
declare variable V$JOB_TITLE varchar(200);
declare variable V$AREA_ID bigint;
declare variable V$OU_NAME varchar(200);
declare variable V$AREA_NAME varchar(200);
declare variable V$IS_ACTIVE smallint;
declare variable V$CURRENT_YEAR integer;
declare variable V$ASSN_ID bigint;
declare variable V$EXAM_ID bigint;
declare variable V$EXAM_NAME varchar(200);
declare variable V$EXAM_DATE date;
declare variable V$EXAM_STATE integer;
begin

  -- Проверяем
  SELECT FIRST 1 OBJ_ID
  FROM LINKS L14
  WHERE L14.OBJ_ID = :I$OBJ_ID AND L14.PARENT_TYPE_ID IN (2, 84) AND L14.DATE_DEL IS NULL
  INTO :V$PERSON_ID;

  IF(I$OBJ_ID IS NOT NULL AND V$PERSON_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Данные по сотруднику утрачены или запись была удалена';

  -- Сотрудники всегда readonly
  TAG_NAME = 'person_readonly';
  VAL = '1';
  SUSPEND;

  SELECT NAME_LAST, NAME_FIRST, NAME_MID, BIRTH_DATE, JOB_TITLE, OU_NAME, AREA_ID, AREA_NAME
  FROM UT_EMPLOYEE_DESC(:V$PERSON_ID)
  INTO :V$NAME_LAST, :V$NAME_FIRST, :V$NAME_MID, :V$BD, :V$JOB_TITLE, :V$OU_NAME, :V$AREA_ID, :V$AREA_NAME;

  TAG_NAME = 'id';
  VAL = I$OBJ_ID;
  SUSPEND;

  TAG_NAME = 'name_last';
  VAL = V$NAME_LAST;
  SUSPEND;

  TAG_NAME = 'name_first';
  VAL = V$NAME_FIRST;
  SUSPEND;

  TAG_NAME = 'name_mid';
  VAL = V$NAME_MID;
  SUSPEND;

  TAG_NAME = 'birth_date';
  VAL = V$BD;
  SUSPEND;

  TAG_NAME = 'job_title';
  VAL = V$JOB_TITLE;
  SUSPEND;

  TAG_NAME = 'ou_name';
  VAL = V$OU_NAME;
  SUSPEND;

  TAG_NAME = 'is_active';
  VAL = V$IS_ACTIVE;
  SUSPEND;

  -- Название района
  TAG_NAME = 'area_id';
  VAL = V$AREA_ID;
  SUSPEND;

  TAG_NAME = 'area_name';
  VAL = NULL;
  SELECT R.VAL
  FROM LISTVALS LV
  JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
  WHERE LV.LISTVAL_ID = :V$AREA_ID
  INTO :VAL;
  SUSPEND;

  -- Список тестирований, где назначен участником - отображаем только текущий учебный период
  -- Текущий учебный год
  IF(EXTRACT(MONTH FROM CURRENT_DATE) < 9) THEN V$CURRENT_YEAR = EXTRACT(YEAR FROM CURRENT_DATE) - 1; ELSE V$CURRENT_YEAR = EXTRACT(YEAR FROM CURRENT_DATE);

  TAG_NAME = 'test_assns';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'test_assns::json&colon;array';
  VAL = '1';
  SUSPEND;

  FOR
      SELECT OBJ_ID, EXAM_ID, EXAM_NAME, EXAM_DATE, STATE
      FROM UT_PERSON_EXAM_ASSNS_LIST(:I$OBJ_ID, :V$CURRENT_YEAR)
      ORDER BY EXAM_DATE
      INTO :V$ASSN_ID, :V$EXAM_ID, :V$EXAM_NAME, :V$EXAM_DATE, :V$EXAM_STATE
  DO
  BEGIN

      TAG_NAME = 'test_assns:r';
      VAL = NULL;
      SUSPEND;

      TAG_NAME = 'test_assns:r:id';
      VAL = V$ASSN_ID;
      SUSPEND;

      TAG_NAME = 'test_assns:r:exam_id';
      VAL = V$EXAM_ID;
      SUSPEND;

      TAG_NAME = 'test_assns:r:name';
      VAL = V$EXAM_NAME;
      SUSPEND;

      TAG_NAME = 'test_assns:r:date';
      VAL = V$EXAM_DATE;
      SUSPEND;

      TAG_NAME = 'test_assns:r:state';
      VAL = V$EXAM_STATE;
      SUSPEND;

  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_SUBJECTS RETURNS (
    OBJ_ID BIGINT,
    OBJ_NAME VARCHAR(1000),
    DATE_DEL TIMESTAMP,
    TYPE_ID BIGINT)
AS
DECLARE VARIABLE V$OU_LICENCE_TYPE CHAR(1);
DECLARE VARIABLE V$HAS_OU SMALLINT;
DECLARE VARIABLE V$HAS_SPO SMALLINT;
DECLARE VARIABLE V$OU_ID BIGINT;
DECLARE VARIABLE T INTEGER;
begin
  SELECT STATUS FROM OU_LICENCE_TYPE INTO :V$OU_LICENCE_TYPE;

  V$HAS_OU = 0;
  V$HAS_SPO = 0;
  IF(V$OU_LICENCE_TYPE = 'O') THEN V$HAS_OU = 1;
  IF(V$OU_LICENCE_TYPE = 'C') THEN V$HAS_SPO = 1;

  IF(V$OU_LICENCE_TYPE = 'S') THEN
  BEGIN
    SELECT FIRST 1 L2.OBJ_ID
    FROM LINKS L2
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :V$OU_ID;

    SELECT FIRST 1 1
    FROM LINKS L472
    JOIN VALL V3327 ON V3327.OBJ_ID = L472.OBJ_ID AND V3327.PARAM_ID = 3327 AND V3327.IS_DEL = 0 AND V3327.LISTVAL_ID IN (22, 26, 27)
    WHERE L472.PARENT_ID = :V$OU_ID AND L472.OBJ_TYPE_ID = 472 AND L472.DATE_DEL IS NULL
    INTO :V$HAS_OU;

    SELECT FIRST 1 1
    FROM LINKS L472
    JOIN VALL V3327 ON V3327.OBJ_ID = L472.OBJ_ID AND V3327.PARAM_ID = 3327 AND V3327.IS_DEL = 0 AND V3327.LISTVAL_ID IN (28, 29, 13129)
    WHERE L472.PARENT_ID = :V$OU_ID AND L472.OBJ_TYPE_ID = 472 AND L472.DATE_DEL IS NULL
    INTO :V$HAS_SPO;

    -- На региональном уровне всегда оба варианта
    IF(V$OU_ID IS NULL) THEN
    BEGIN
      V$HAS_OU = 1;
      V$HAS_SPO = 1;
    END
  END

  FOR
    -- Школы
    SELECT L51.OBJ_ID, 0, V376.VAL, L51.OBJ_TYPE_ID
    FROM LINKS L51
    JOIN VALS V376 ON V376.OBJ_ID = L51.OBJ_ID AND V376.PARAM_ID = 376 AND V376.IS_DEL = 0
    LEFT JOIN VALL V2816 ON V2816.OBJ_ID = L51.OBJ_ID AND V2816.PARAM_ID = 2816 AND V2816.IS_DEL = 0
    WHERE L51.PARENT_ID = 32771 AND L51.OBJ_TYPE_ID = 51 AND L51.DATE_DEL IS NULL AND L51.OBJ_ID < 1000000000
      -- исключаем индивидуальный проект
      AND L51.OBJ_ID <> 34651
      -- исключаем элективные курсы
      AND (V2816.LISTVAL_ID IS NULL OR V2816.LISTVAL_ID = 3)
      AND :V$HAS_OU = 1
    -- ЦОПП и колледжи - выдаем список предметов, отмеченных как аттестационные
    UNION
    SELECT L197.OBJ_ID, 1, V1751.VAL, L197.OBJ_TYPE_ID
    FROM LINKS L197
    JOIN VALL V1750 ON V1750.OBJ_ID = L197.OBJ_ID AND V1750.PARAM_ID = 1750 AND V1750.IS_DEL = 0 AND V1750.LISTVAL_ID = 3402 -- 3411
    JOIN VALS V1751 ON V1751.OBJ_ID = L197.OBJ_ID AND V1751.PARAM_ID = 1751 AND V1751.IS_DEL = 0
    WHERE L197.PARENT_ID = 12313 AND L197.OBJ_TYPE_ID = 197 AND L197.DATE_DEL IS NULL AND L197.OBJ_ID < 1000000000
      AND :V$HAS_SPO = 1
    ORDER BY 2, 3
    INTO :OBJ_ID, :T, :OBJ_NAME, :TYPE_ID
  DO
  BEGIN
    SUSPEND;
  END
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_SYNC_EXPERT (
    I$PERSON_ID BIGINT,
    I$IS_EXPERT VARCHAR(100))
AS
declare variable V$EX smallint;
declare variable V$USER_ID bigint;
declare variable V$USER_NAME varchar(100);
declare variable V$PWD varchar(40);
declare variable V$EXPERT_ID bigint;
declare variable V$EXPERT_DEL timestamp;
declare variable V$NAME_LAST varchar(200);
declare variable V$NAME_FIRST varchar(200);
declare variable V$NAME_MID varchar(200);
declare variable V$BIRTHDATE date;
declare variable V$OU_NAME varchar(200);
declare variable V$JOB_TITLE varchar(200);
declare variable V$AREA_ID bigint;
declare variable V$OU_ID bigint;
declare variable V$LEVEL smallint;
begin

  -- I$IS_EXPERT либо NULL, либо LISTVAL 2/3
  IF(I$IS_EXPERT IS NULL) THEN
  BEGIN
      SELECT I
      FROM VAL_GET(:I$PERSON_ID, 2935)
      INTO :I$IS_EXPERT;
  END
  ELSE I$IS_EXPERT = CAST(I$IS_EXPERT AS INTEGER);

  V$EX = 3;
  IF(I$IS_EXPERT = 2) THEN V$EX = 2;

  SELECT FIRST 1 E.EXPERT_ID, E.DATE_DEL
  FROM UT_EXPERTS E
  WHERE E.TEACHER_ID = :I$PERSON_ID
  ORDER BY E.DATE_DEL
  INTO :V$EXPERT_ID, :V$EXPERT_DEL;

  IF(V$EX = 3) THEN
  BEGIN

      -- Более не является экспертом, но был
      IF(V$EXPERT_ID IS NOT NULL AND V$EXPERT_DEL IS NULL) THEN
      BEGIN
          UPDATE UT_EXPERTS
          SET DATE_DEL = CURRENT_TIMESTAMP
          WHERE EXPERT_ID = :V$EXPERT_ID;
      END

  END
  ELSE
  BEGIN

      SELECT KEY_VAL FROM KEYS WHERE KEY_CODE = 'LEVEL' INTO :V$LEVEL;

      -- Является экспертом - обязательно должен быть создан пользователь (на уровне ОУ)
      SELECT U.USER_ID, U.PWD
      FROM USERS U
      WHERE U.OBJ_ID = :I$PERSON_ID AND U.DATE_DEL IS NULL AND U.IS_BLOCKED = 0 AND (U.EXP_DATE IS NULL OR U.EXP_DATE > CURRENT_DATE)
      INTO :V$USER_ID, :V$PWD;

      IF(V$LEVEL = 1 AND V$USER_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Перед установкой статуса эксперта, для сотрудника должен быть назначен пользователь, с актуальной датой действия пароля';

      -- Должен быть прописан адрес электронной почты
      SELECT FIRST 1 V1180.VAL
      FROM VALS V1180
      WHERE V1180.OBJ_ID = :I$PERSON_ID AND V1180.PARAM_ID = 1180 AND V1180.IS_DEL = 0
      INTO :V$USER_NAME;

      IF(V$LEVEL = 1 AND V$USER_NAME IS NULL) THEN EXCEPTION DATA_ERROR 'Для сотрудника, отмеченного как эксперт, должен быть указан адрес электронной почты';

      SELECT D.NAME_LAST, D.NAME_FIRST, D.NAME_MID, D.BIRTH_DATE, D.JOB_TITLE, D.OU_NAME, D.AREA_ID, D.OU_ID
      FROM UT_EMPLOYEE_DESC(:I$PERSON_ID) D
      INTO :V$NAME_LAST, :V$NAME_FIRST, :V$NAME_MID, :V$BIRTHDATE, :V$JOB_TITLE, :V$OU_NAME, :V$AREA_ID, :V$OU_ID;

      IF(V$EXPERT_ID IS NULL) THEN
      BEGIN

          -- Начальное добавление выполняем без пароля, но пароль можно задать через интерфейс
          INSERT INTO UT_EXPERTS
          (TEACHER_ID, LAST_NAME, FIRST_NAME, MIDDLE_NAME, BIRTHDATE, JOB_TITLE, ORGANIZATION, AREA_ID, IS_ACTIVE, USER_NAME, PWD, ORG_ID)
          VALUES (:I$PERSON_ID, :V$NAME_LAST, :V$NAME_FIRST, :V$NAME_MID, :V$BIRTHDATE, :V$JOB_TITLE, :V$OU_NAME, :V$AREA_ID, 1, :V$USER_NAME, :V$PWD, :V$OU_ID);

      END
      ELSE
      BEGIN

          -- Отменяем удаление
          IF(V$EXPERT_DEL IS NOT NULL) THEN
          BEGIN
              UPDATE UT_EXPERTS
              SET DATE_DEL = NULL
              WHERE EXPERT_ID = :V$EXPERT_ID;
          END

          UPDATE UT_EXPERTS E
          SET E.LAST_NAME = :V$NAME_LAST, E.FIRST_NAME = :V$NAME_FIRST, E.MIDDLE_NAME = :V$NAME_MID, E.BIRTHDATE = :V$BIRTHDATE, E.JOB_TITLE = :V$JOB_TITLE,
              E.ORGANIZATION = :V$OU_NAME, E.AREA_ID = :V$AREA_ID, E.USER_NAME = :V$USER_NAME, E.ORG_ID = :V$OU_ID
          WHERE E.EXPERT_ID = :V$EXPERT_ID;

      END

  END


end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEMPLATES_LIST (
    I$USER_ID VARCHAR(40))
RETURNS (
    OBJ_ID BIGINT,
    OBJ_NAME VARCHAR(400),
    BLANK_TYPE SMALLINT,
    BLANK_TYPE_NAME VARCHAR(100),
    IS_DS SMALLINT,
    IS_ACTIVE SMALLINT)
AS
begin

  FOR
      SELECT PT.OBJ_ID, PT.OBJ_NAME, PT.IS_DS, PT.IS_ACTIVE, PT.BLANK_TYPE
      FROM UT_PAGE_TEMPLATES PT
      WHERE PT.DATE_DEL IS NULL
      ORDER BY PT.IS_ACTIVE DESC, PT.OBJ_NAME
      INTO :OBJ_ID, :OBJ_NAME, :IS_DS, :IS_ACTIVE, :BLANK_TYPE
  DO
  BEGIN

      IF(BLANK_TYPE = 0) THEN BLANK_TYPE_NAME = 'Пустой бланк';
      ELSE IF(BLANK_TYPE = 1) THEN BLANK_TYPE_NAME = 'Бланк AB';
      ELSE IF(BLANK_TYPE = 2) THEN BLANK_TYPE_NAME = 'Бланк C';
      ELSE IF(BLANK_TYPE = 3) THEN BLANK_TYPE_NAME = 'Дополнительный C';
      ELSE IF(BLANK_TYPE = 4) THEN BLANK_TYPE_NAME = 'Административный';
      ELSE BLANK_TYPE_NAME = 'Неизвестный тип';

      SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEMPLATE_ACCESS (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    STUB INTEGER)
AS
declare variable V$GEN integer;
declare variable V$MULTIPLIER bigint;
declare variable N bigint;
begin

  SELECT GEN, MULTIPLIER
  FROM GEN
  INTO :V$GEN, :V$MULTIPLIER;

  N = I$OBJ_ID / V$MULTIPLIER;
  IF(N <> V$GEN) THEN EXCEPTION DATA_ERROR 'Нельзя изменить шаблон бланка, созданный в другой организации/уровне';

  SUSPEND;
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEMPLATE_COPY (
    I$OBJ_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    OBJ_NAME VARCHAR(400))
AS
declare variable PREFIX varchar(400);
declare variable N integer;
begin

  SELECT FIRST 1 PT.OBJ_NAME
  FROM UT_PAGE_TEMPLATES PT
  WHERE PT.OBJ_ID = :I$OBJ_ID AND PT.DATE_DEL IS NULL
  INTO :PREFIX;

  IF(PREFIX IS NULL) THEN EXCEPTION DATA_ERROR 'Объект не найден или был удален другим пользователем';

  -- Если в конце в последних 4 символах есть решетка - подчищаем ее
  N = 2;
  IF(POSITION('#' IN PREFIX) >= CHAR_LENGTH(PREFIX) - 4) THEN PREFIX = SUBSTRING(PREFIX FROM 1 FOR POSITION('#' IN PREFIX) - 1);
  IF(SUBSTRING(PREFIX FROM CHAR_LENGTH(PREFIX)) <> ' ') THEN PREFIX = PREFIX || ' ';

  WHILE(1 = 1) DO
  BEGIN
      IF(NOT EXISTS(
          SELECT FIRST 1 1
          FROM UT_PAGE_TEMPLATES PT
          WHERE PT.DATE_DEL IS NULL AND PT.OBJ_NAME = :PREFIX || '#' || :N
      )) THEN LEAVE;

      N = N + 1;
  END

  INSERT INTO UT_PAGE_TEMPLATES
  (OBJ_NAME, IS_DS, IS_ACTIVE, BLANK_TYPE, DATA_FRONT, DATA_BACK)
      SELECT :PREFIX || '#' || :N, IS_DS, IS_ACTIVE, BLANK_TYPE, DATA_FRONT, DATA_BACK
      FROM UT_PAGE_TEMPLATES
      WHERE OBJ_ID = :I$OBJ_ID
  RETURNING OBJ_ID INTO :OBJ_ID;
  OBJ_NAME = :PREFIX || '#' || :N;
  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEMPLATE_DELETE (
    I$OBJ_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$GEN integer;
declare variable V$MULTIPLIER bigint;
declare variable N bigint;
begin

  IF(NOT EXISTS(
      SELECT FIRST 1 1
      FROM UT_PAGE_TEMPLATES PT
      WHERE PT.OBJ_ID = :I$OBJ_ID AND PT.DATE_DEL IS NULL
  )) THEN EXCEPTION DATA_ERROR 'Объект не найден или был удален другим пользователем';

  IF(EXISTS(
      SELECT FIRST 1 1
      FROM UT_EXAM_DATES D
      WHERE D.DATE_DEL IS NULL AND (D.EXAM_STATE >= 0 AND D.EXAM_STATE < 1000) AND (D.BLANK_AB_ID = :I$OBJ_ID OR D.BLANK_C_ID = :I$OBJ_ID OR D.BLANK_EXT_ID = :I$OBJ_ID)
  )) THEN EXCEPTION DATA_ERROR 'Данный шаблон задействован в открытых тестированиях, удалить нельзя';

  SELECT GEN, MULTIPLIER
  FROM GEN
  INTO :V$GEN, :V$MULTIPLIER;

  N = I$OBJ_ID / V$MULTIPLIER;
  IF(N <> V$GEN) THEN EXCEPTION DATA_ERROR 'Нельзя удалить шаблон бланка, созданный в другой организации/уровне';

  UPDATE UT_PAGE_TEMPLATES
  SET DATE_DEL = CURRENT_TIMESTAMP
  WHERE OBJ_ID = :I$OBJ_ID;

  OBJ_ID = I$OBJ_ID;
  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEMPLATE_GET (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40),
    I$FIELD SMALLINT)
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$DEL TIMESTAMP;
DECLARE VARIABLE V$OBJ_NAME VARCHAR(400);
DECLARE VARIABLE V$BLANK_TYPE SMALLINT;
DECLARE VARIABLE V$IS_DS SMALLINT;
DECLARE VARIABLE V$IS_ACTIVE SMALLINT;
begin

  -- FIELD: 2 = все текстовые поля, 0 = шаблон лицевой стороны, 1 = шаблон оборотной стороны
  IF(I$FIELD = 2) THEN
  BEGIN
      SELECT FIRST 1 PT.DATE_DEL, PT.OBJ_NAME, PT.BLANK_TYPE, PT.IS_DS, PT.IS_ACTIVE
      FROM UT_PAGE_TEMPLATES PT
      WHERE PT.OBJ_ID = :I$OBJ_ID
      INTO :V$DEL, :V$OBJ_NAME, :V$BLANK_TYPE, :V$IS_DS, :V$IS_ACTIVE;

      IF(V$DEL IS NOT NULL) THEN EXCEPTION DATA_ERROR 'Шаблон бланка удален';

      TAG_NAME = 'id';
      VAL = I$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'obj_name';
      VAL = V$OBJ_NAME;
      SUSPEND;
      TAG_NAME = 'is_ds';
      VAL = V$IS_DS;
      SUSPEND;
      TAG_NAME = 'is_active';
      VAL = V$IS_ACTIVE;
      SUSPEND;

      TAG_NAME = 'blank_type';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'blank_type:selection';
      VAL = NULL;
      SUSPEND;

      TAG_NAME = 'blank_type:selection:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'blank_type:selection:r:id';
      VAL = '0';
      SUSPEND;
      TAG_NAME = 'blank_type:selection:r:value';
      VAL = 'Пустой бланк';
      SUSPEND;
      TAG_NAME = 'blank_type:selection:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'blank_type:selection:r:id';
      VAL = '1';
      SUSPEND;
      TAG_NAME = 'blank_type:selection:r:value';
      VAL = 'Бланк типа AB';
      SUSPEND;
      TAG_NAME = 'blank_type:selection:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'blank_type:selection:r:id';
      VAL = '2';
      SUSPEND;
      TAG_NAME = 'blank_type:selection:r:value';
      VAL = 'Бланк типа C';
      SUSPEND;
      TAG_NAME = 'blank_type:selection:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'blank_type:selection:r:id';
      VAL = '3';
      SUSPEND;
      TAG_NAME = 'blank_type:selection:r:value';
      VAL = 'Дополнительный бланк C';
      SUSPEND;
      TAG_NAME = 'blank_type:selection:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'blank_type:selection:r:id';
      VAL = '4';
      SUSPEND;
      TAG_NAME = 'blank_type:selection:r:value';
      VAL = 'Административный бланк';
      SUSPEND;

      TAG_NAME = 'blank_type:values:value';
      VAL = V$BLANK_TYPE;
      SUSPEND;
  END
  ELSE IF(I$FIELD = 0) THEN
  BEGIN
      -- DATA_FRONT
  END
  ELSE IF(I$FIELD = 1) THEN
  BEGIN
      -- DATA_BACK
  END
  ELSE EXCEPTION DATA_ERROR 'Неверный параметр';

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEMPLATE_SAVE (
    I$OBJ_ID BIGINT,
    I$OBJ_NAME VARCHAR(400),
    I$BLANK_TYPE SMALLINT,
    I$IS_DS SMALLINT,
    I$IS_ACTIVE SMALLINT)
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$BLANK_TYPE smallint;
declare variable V$GEN integer;
declare variable V$MULTIPLIER bigint;
declare variable N bigint;
begin

  I$OBJ_NAME = TRIM(I$OBJ_NAME);
  IF(CHAR_LENGTH(I$OBJ_NAME) < 3) THEN EXCEPTION DATA_ERROR 'Слишком короткое наименование шаблона';

  IF(EXISTS(
      SELECT FIRST 1 1
      FROM UT_PAGE_TEMPLATES PT
      WHERE PT.DATE_DEL IS NULL AND UPPER(PT.OBJ_NAME) = UPPER(:I$OBJ_NAME) AND (:I$OBJ_ID IS NULL OR PT.OBJ_ID <> :I$OBJ_ID)
  )) THEN EXCEPTION DATA_ERROR 'Шаблон с таким наименованием уже есть';

  IF(I$OBJ_ID IS NULL) THEN
  BEGIN

      INSERT INTO UT_PAGE_TEMPLATES
      (OBJ_NAME, BLANK_TYPE, IS_DS, IS_ACTIVE)
      VALUES (:I$OBJ_NAME, :I$BLANK_TYPE, :I$IS_DS, :I$IS_ACTIVE)
      RETURNING OBJ_ID INTO :OBJ_ID;

  END
  ELSE
  BEGIN

      SELECT GEN, MULTIPLIER
      FROM GEN
      INTO :V$GEN, :V$MULTIPLIER;

      N = I$OBJ_ID / V$MULTIPLIER;
      IF(N <> V$GEN) THEN EXCEPTION DATA_ERROR 'Нельзя изменить шаблон бланка, созданный в другой организации/уровне';

      SELECT PT.BLANK_TYPE
      FROM UT_PAGE_TEMPLATES PT
      WHERE PT.DATE_DEL IS NULL AND PT.OBJ_ID = :I$OBJ_ID
      INTO :V$BLANK_TYPE;

      IF(V$BLANK_TYPE IS NULL) THEN EXCEPTION DATA_ERROR 'Шаблон не найден или был удален';

      IF(V$BLANK_TYPE <> I$BLANK_TYPE) THEN
      BEGIN
          IF(EXISTS(
              SELECT FIRST 1 1
              FROM UT_EXAM_DATES D
              WHERE D.DATE_DEL IS NULL AND (D.EXAM_STATE >= 0 AND D.EXAM_STATE < 1000) AND (D.BLANK_AB_ID = :I$OBJ_ID OR D.BLANK_C_ID = :I$OBJ_ID OR D.BLANK_EXT_ID = :I$OBJ_ID)
          )) THEN EXCEPTION DATA_ERROR 'Шаблон бланка привязан в открытых тестированиях, изменить тип нельзя. Сначала снимите привязку к данному шаблону';
      END

      UPDATE UT_PAGE_TEMPLATES PT
      SET PT.OBJ_NAME = :I$OBJ_NAME, PT.BLANK_TYPE = :I$BLANK_TYPE, PT.IS_DS = :I$IS_DS, PT.IS_ACTIVE = :I$IS_ACTIVE
      WHERE PT.OBJ_ID = :I$OBJ_ID;

  END

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TESTS_GET (
    I$EXAM_ID BIGINT,
    I$VARIANT_ID BIGINT = null)
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
declare variable V$RUN_ID bigint;
declare variable V$RUN_ID2 bigint;
declare variable V$ID bigint;
declare variable V$NAME varchar(1000);
declare variable V$S varchar(1000);
declare variable V$TYPE_ID bigint;
declare variable V$INDEX integer;
declare variable V$SCORE integer;
declare variable V$POINT_ID bigint;
declare variable V$MASTER_ID bigint;
declare variable V$AUTO smallint;
declare variable V$Q_NAME varchar(200);
declare variable V$NAME_SHORT varchar(10);
declare variable V$LEVEL smallint;
declare variable V$Q_ID bigint;
declare variable V$GEN bigint;
declare variable V$MULTIPLIER bigint;
declare variable V$CHARSET smallint;
declare variable V$CHARSET_NAME varchar(100);
declare variable V$OBJ_NAME varchar(8000);
declare variable N integer;
declare variable V$OBJ_ID bigint;
declare variable V$LOOP_VARIANT_ID bigint;
begin

  -- Корелляция с UT_TEST_VAR_GET !

  SELECT GEN, MULTIPLIER
  FROM GEN
  INTO :V$GEN, :V$MULTIPLIER;

     -- Файлы вложений (КИМы и проч)
  TAG_NAME = 'files';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'files::json&colon;array';
  VAL = 1;
  SUSPEND;

  FOR
      SELECT F.OBJ_ID, F.OBJ_NAME, F.FILE_HASH, F.CONTENT_TYPE, F.ATTR_MASK, CHAR_LENGTH(F.CONTENT_DATA)
      FROM UT_TEST_VAR_FILES F
      WHERE F.DATE_DEL IS NULL AND F.VAR_ID = :I$VARIANT_ID
      ORDER BY 2
      INTO :V$OBJ_ID, :V$NAME, :V$S, :V$Q_NAME, :V$TYPE_ID, :N
  DO
  BEGIN
      TAG_NAME = 'files:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'files:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'files:r:name';
      VAL = V$NAME;
      SUSPEND;
      TAG_NAME = 'files:r:hash';
      VAL = V$S;
      SUSPEND;
      TAG_NAME = 'files:r:type';
      VAL = V$Q_NAME;
      SUSPEND;
      TAG_NAME = 'files:r:mask';
      VAL = V$TYPE_ID;
      SUSPEND;
      TAG_NAME = 'files:r:size';
      VAL = N;
      SUSPEND;
  END

  TAG_NAME = 'data';
  VAL = NULL;
  SUSPEND;

  -- Справочник: типы вопросов
  TAG_NAME = 'data:types';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'data:types::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
      SELECT QT.OBJ_ID, QT.OBJ_NAME, QT.OBJ_VALUE
      FROM UT_QUESTION_TYPE QT
      INTO :V$ID, :V$NAME, :V$S
  DO
  BEGIN
      TAG_NAME = 'data:types:q';
      VAL = NULL;
      SUSPEND;
  
      TAG_NAME = 'data:types:q:id';
      VAL = V$ID;
      SUSPEND;
  
      TAG_NAME = 'data:types:q:name';
      VAL = V$NAME;
      SUSPEND;
  
      TAG_NAME = 'data:types:q:value';
      VAL = V$S;
      SUSPEND;
  END

  -- Справочник: кодировки
  TAG_NAME = 'data:charsets';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'data:charsets::json&colon;array';
  VAL = 1;
  SUSPEND;

  FOR
      SELECT C.OBJ_ID, C.OBJ_NAME, C.LANG_CODE
      FROM UT_CHARSETS C
      INTO :V$ID, :V$NAME, :V$S
  DO
  BEGIN
      TAG_NAME = 'data:charsets:q';
      VAL = NULL;
      SUSPEND;
  
      TAG_NAME = 'data:charsets:q:id';
      VAL = V$ID;
      SUSPEND;
  
      TAG_NAME = 'data:charsets:q:name';
      VAL = V$NAME;
      SUSPEND;
  
      TAG_NAME = 'data:charsets:q:lang_code';
      VAL = V$S;
      SUSPEND;
  END

  -- Кодификаторы, соответствующие предмету в данном тестировании
  -- метапредмет считаем соответствующим любому предмету
  TAG_NAME = 'data:codings';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'data:codings::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
      SELECT KC.OBJ_ID, KC.OBJ_NAME
      FROM UT_EXAM_DATES ED
      -- Связка сначала через этап
      JOIN UT_KIM_CODING_STAGES CS ON CS.STAGE_ID = ED.STAGE_ID AND CS.DATE_DEL IS NULL
      JOIN UT_KIM_CODING KC ON KC.OBJ_ID = CS.CODING_ID AND KC.DATE_DEL IS NULL
      -- Убираем автокодификатор (в том числе где пакет тестов удален)
      LEFT JOIN UT_TESTS T ON T.CODING_ID = KC.OBJ_ID
      -- Досвязка по предмету
      WHERE ED.OBJ_ID = :I$EXAM_ID
      -- AND KC.OBJ_ID IS NULL -- убрал
      AND EXISTS(
         SELECT FIRST 1 1
         FROM UT_KIM_CODING_SUBJECTS CSS
         WHERE CSS.CODING_ID = KC.OBJ_ID AND CSS.DATE_DEL IS NULL AND ((CSS.SUBJECT_ID IS NULL AND ED.SUBJECT_ID IS NULL) OR CSS.SUBJECT_ID = ED.SUBJECT_ID)
      )
      INTO :V$ID, :V$NAME
  DO
  BEGIN
      TAG_NAME = 'data:codings:c';
      VAL = NULL;
      SUSPEND;
  
      TAG_NAME = 'data:codings:c:id';
      VAL = V$ID;
      SUSPEND;
  
      TAG_NAME = 'data:codings:c:name';
      VAL = V$NAME;
      SUSPEND;
  END


  -- Структуры, соответствующие предмету, методу тестирования и этапу тестирования
  -- соответствие по предмету в структурах проверяется на точное соответствие
  -- Берем только явно занесенные оператором, автосозданные не показываем
  TAG_NAME = 'data:structs';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'data:structs::json&colon;array';
  VAL = 1;
  SUSPEND;

  FOR
      SELECT TS.OBJ_ID, TS.OBJ_NAME, TS.IS_AUTO
      FROM UT_EXAM_DATES ED
      JOIN UT_TEST_STRUCTS TS ON TS.STAGE_ID = ED.STAGE_ID AND TS.METHOD_ID = ED.METHOD_ID
          AND ((TS.SUBJECT_ID IS NULL AND ED.SUBJECT_ID IS NULL) OR TS.SUBJECT_ID = ED.SUBJECT_ID)
      WHERE ED.OBJ_ID = :I$EXAM_ID AND TS.IS_AUTO = 0
      INTO :V$ID, :V$NAME, :V$AUTO
  DO
  BEGIN
      TAG_NAME = 'data:structs:s';
      VAL = NULL;
      SUSPEND;
  
      TAG_NAME = 'data:structs:s:id';
      VAL = V$ID;
      SUSPEND;
  
      TAG_NAME = 'data:structs:s:name';
      VAL = V$NAME;
      SUSPEND;

      TAG_NAME = 'data:structs:s:is_auto';
      VAL = V$AUTO;
      SUSPEND;

      -- Использована ли эта структура уже где-то ?
      -- 0 = не использована, 1 = использована
      TAG_NAME = 'data:structs:s:is_used';
      VAL = 0;
      SELECT FIRST 1 1
      FROM UT_TESTS T
      JOIN UT_TEST_VARS V ON V.DATE_DEL IS NULL AND V.TEST_ID = T.OBJ_ID
      JOIN UT_EXAM_TEST_VARS TV ON TV.DATE_DEL IS NULL AND TV.TEST_VAR_ID = V.OBJ_ID
      JOIN UT_EXAM_DATES D ON D.DATE_DEL IS NULL AND D.OBJ_ID = TV.EXAM_ID AND (D.EXAM_STATE > 500 AND D.EXAM_STATE < 1000)
      WHERE T.DATE_DEL IS NULL AND T.STRUCT_ID = :V$ID
      INTO :VAL;
      SUSPEND;

  END

  -- Возвращаем список уже выбранных в тест данных в сечении структура -> пакет -> вариант
  -- Но для свежедобавленных вариантов добавляем также конкретный id структуры, поскольку связи еще нет в базе
  TAG_NAME = 'data:tstr';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'data:tstr::json&colon;array';
  VAL = 1;
  SUSPEND;

  FOR
      SELECT DISTINCT TS.OBJ_ID, TS.OBJ_NAME, TS.STR_HASH
      FROM UT_EXAM_TEST_VARS V
      JOIN UT_TEST_VARS TV ON TV.OBJ_ID = V.TEST_VAR_ID AND TV.DATE_DEL IS NULL
      JOIN UT_TESTS T ON T.OBJ_ID = TV.TEST_ID AND T.DATE_DEL IS NULL
      JOIN UT_TEST_STRUCTS TS ON TS.OBJ_ID = T.STRUCT_ID AND TS.DATE_DEL IS NULL
      WHERE V.EXAM_ID = :I$EXAM_ID AND V.DATE_DEL IS NULL AND (:I$VARIANT_ID IS NULL OR TV.OBJ_ID = :I$VARIANT_ID)
      UNION
      SELECT TS.OBJ_ID, TS.OBJ_NAME, TS.STR_HASH
      FROM UT_TEST_VARS TV
      JOIN UT_TESTS T ON T.OBJ_ID = TV.TEST_ID AND T.DATE_DEL IS NULL
      JOIN UT_TEST_STRUCTS TS ON TS.OBJ_ID = T.STRUCT_ID AND TS.DATE_DEL IS NULL
      WHERE TV.OBJ_ID = :I$VARIANT_ID AND TV.DATE_DEL IS NULL
      ORDER BY 2
      INTO :V$ID, :V$NAME, :V$S
  DO
  BEGIN

      TAG_NAME = 'data:tstr:s';
      VAL = NULL;
      SUSPEND;

      TAG_NAME = 'data:tstr:s:id';
      VAL = V$ID;
      SUSPEND;

      TAG_NAME = 'data:tstr:s:name';
      VAL = V$NAME;
      SUSPEND;

      TAG_NAME = 'data:tstr:s:hash';
      VAL = V$S;
      SUSPEND;

      N = V$ID / V$MULTIPLIER;
      TAG_NAME = 'data:tstr:s:allowed';
      VAL = 0;
      IF(N = V$GEN) THEN VAL = 1;
      SUSPEND;

      V$RUN_ID = V$ID;

      -- Описание структуры
      TAG_NAME = 'data:tstr:s:structs';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'data:tstr:s:structs::json&colon;array';
      VAL = 1;
      SUSPEND;

      FOR
          SELECT TSP.OBJ_ID, TSP.Q_ORDER, TSP.Q_TYPE_ID, QT.OBJ_NAME, QT.OBJ_VALUE, TSP.Q_MAX_SCORE, TSP.Q_LEVEL, TSP.CHARSET_ID, C.OBJ_NAME, TSP.TEXT_NOTES
          FROM UT_TEST_STRUCT_POINTS TSP
          JOIN UT_QUESTION_TYPE QT ON QT.OBJ_ID = TSP.Q_TYPE_ID
          LEFT JOIN UT_CHARSETS C ON C.OBJ_ID = TSP.CHARSET_ID
          WHERE TSP.STRUCT_ID = :V$RUN_ID AND TSP.DATE_DEL IS NULL
          ORDER BY 2
          INTO :V$ID, :V$INDEX, :V$TYPE_ID, :V$NAME, :V$NAME_SHORT, :V$SCORE, :V$LEVEL, :V$CHARSET, :V$CHARSET_NAME, :V$OBJ_NAME
      DO
      BEGIN

          TAG_NAME = 'data:tstr:s:structs:struct';
          VAL = NULL;
          SUSPEND;
          TAG_NAME = 'data:tstr:s:structs:struct:id';
          VAL = V$ID;
          SUSPEND;
          TAG_NAME = 'data:tstr:s:structs:struct:index';
          VAL = V$INDEX;
          SUSPEND;
          TAG_NAME = 'data:tstr:s:structs:struct:type_id';
          VAL = V$TYPE_ID;
          SUSPEND;
          TAG_NAME = 'data:tstr:s:structs:struct:type_value';
          VAL = V$NAME_SHORT;
          SUSPEND;
          TAG_NAME = 'data:tstr:s:structs:struct:type_name';
          VAL = V$NAME;
          SUSPEND;
          TAG_NAME = 'data:tstr:s:structs:struct:level';
          VAL = V$LEVEL;
          SUSPEND;
          TAG_NAME = 'data:tstr:s:structs:struct:max_score';
          VAL = V$SCORE;
          SUSPEND;
          TAG_NAME = 'data:tstr:s:structs:struct:charset_id';
          VAL = V$CHARSET;
          SUSPEND;
          TAG_NAME = 'data:tstr:s:structs:struct:charset';
          VAL = V$CHARSET_NAME;
          SUSPEND;
          TAG_NAME = 'data:tstr:s:structs:struct:text_notes';
          VAL = V$OBJ_NAME;
          SUSPEND;

          -- Для каждой позиции - флаг, что к данной структуре уже прикреплены вопросы
          TAG_NAME = 'data:tstr:s:structs:struct:has_refs';
          VAL = 1;
          SELECT FIRST 1 1
          FROM UT_TEST_VAR_QUESTIONS TVQ
          JOIN UT_TEST_VARS TV ON TV.OBJ_ID = TVQ.VAR_ID AND TV.DATE_DEL IS NULL
          JOIN UT_TESTS T ON T.OBJ_ID = TV.TEST_ID AND T.DATE_DEL IS NULL
          WHERE TVQ.DATE_DEL IS NULL AND TVQ.STRUCT_POINT_ID = :V$ID
          INTO :VAL;
          SUSPEND;

      END

      -- Пакеты по данной структуре, также параллелим туда наш вариант
      TAG_NAME = 'data:tstr:s:tests';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'data:tstr:s:tests::json&colon;array';
      VAL = 1;
      SUSPEND;

      FOR
          SELECT DISTINCT T.OBJ_ID, T.OBJ_NAME, T.MASTER_ED_ID
          FROM UT_EXAM_TEST_VARS V
          JOIN UT_TEST_VARS TV ON TV.OBJ_ID = V.TEST_VAR_ID AND TV.DATE_DEL IS NULL
          JOIN UT_TESTS T ON T.OBJ_ID = TV.TEST_ID AND T.DATE_DEL IS NULL AND T.STRUCT_ID = :V$RUN_ID
          WHERE V.EXAM_ID = :I$EXAM_ID AND V.DATE_DEL IS NULL AND (:I$VARIANT_ID IS NULL OR TV.OBJ_ID = :I$VARIANT_ID)
          UNION
          SELECT DISTINCT T.OBJ_ID, T.OBJ_NAME, T.MASTER_ED_ID
          FROM UT_TEST_VARS TV
          JOIN UT_TESTS T ON T.OBJ_ID = TV.TEST_ID AND T.DATE_DEL IS NULL AND T.STRUCT_ID = :V$RUN_ID
          WHERE TV.OBJ_ID = :I$VARIANT_ID AND TV.DATE_DEL IS NULL
          ORDER BY 2
          INTO :V$ID, :V$NAME, :V$MASTER_ID
      DO
      BEGIN

          TAG_NAME = 'data:tstr:s:tests:t';
          VAL = NULL;
          SUSPEND;

          TAG_NAME = 'data:tstr:s:tests:t:id';
          VAL = V$ID;
          SUSPEND;

          TAG_NAME = 'data:tstr:s:tests:t:name';
          VAL = V$NAME;
          SUSPEND;

          TAG_NAME = 'data:tstr:s:tests:t:master';
          VAL = V$MASTER_ID;
          SUSPEND;

          -- Третий уровень - варианты в данном пакете
          V$RUN_ID2 = V$ID;

          TAG_NAME = 'data:tstr:s:tests:t:variants';
          VAL = NULL;
          SUSPEND;
          TAG_NAME = 'data:tstr:s:tests:t:variants::json&colon;array';
          VAL = 1;
          SUSPEND;

          FOR
              SELECT TV.OBJ_ID, TV.NUM, TV.OBJ_NAME, TV.MASTER_ED_ID
              FROM UT_EXAM_TEST_VARS V
              JOIN UT_TEST_VARS TV ON TV.OBJ_ID = V.TEST_VAR_ID AND TV.DATE_DEL IS NULL
              JOIN UT_TESTS T ON T.OBJ_ID = TV.TEST_ID AND T.DATE_DEL IS NULL AND T.OBJ_ID = :V$RUN_ID2
              WHERE V.EXAM_ID = :I$EXAM_ID AND V.DATE_DEL IS NULL AND (:I$VARIANT_ID IS NULL OR TV.OBJ_ID = :I$VARIANT_ID)
              ORDER BY 2
              INTO :V$ID, :V$INDEX, :V$NAME, :V$MASTER_ID
          DO
          BEGIN

              TAG_NAME = 'data:tstr:s:tests:t:variants:v';
              VAL = NULL;
              SUSPEND;

              TAG_NAME = 'data:tstr:s:tests:t:variants:v:id';
              VAL = V$ID;
              -- для выдачи файлов в моальном окне редактирования всех вариантов
              V$LOOP_VARIANT_ID = V$ID;
              SUSPEND;

              TAG_NAME = 'data:tstr:s:tests:t:variants:v:number';
              VAL = V$INDEX;
              SUSPEND;

              TAG_NAME = 'data:tstr:s:tests:t:variants:v:name';
              VAL = V$NAME;
              SUSPEND;

              TAG_NAME = 'data:tstr:s:tests:t:variants:v:master';
              VAL = V$MASTER_ID;
              SUSPEND;

              N = V$ID / V$MULTIPLIER;
              TAG_NAME = 'data:tstr:s:tests:t:variants:v:allowed';
              VAL = 0;
              IF(N = V$GEN) THEN VAL = 1;
              SUSPEND;

              -- Флаг использования варианта
              TAG_NAME = 'data:tstr:s:tests:t:variants:v:is_used';
              VAL = 0;
              SELECT FIRST 1 1
              FROM UT_EXAM_TEST_VARS TV
              JOIN UT_EXAM_DATES D ON D.DATE_DEL IS NULL AND D.OBJ_ID = TV.EXAM_ID AND (D.EXAM_STATE > 500 AND D.EXAM_STATE < 1000)
              WHERE TV.DATE_DEL IS NULL AND TV.TEST_VAR_ID = :V$ID
              INTO :VAL;
              SUSPEND;

              -- Было: Вопросы отображаем только для того варианта теста, который явно запросили
              -- Стало: Отображаем вопросы для всех вариантов, если не передали вариант (нам это нужно для диалога массового редактирования)
              TAG_NAME = 'data:tstr:s:tests:t:variants:v:qts';
              VAL = NULL;
              SUSPEND;
              TAG_NAME = 'data:tstr:s:tests:t:variants:v:qts::json&colon;array';
              VAL = 1;
              SUSPEND;

              FOR
                  SELECT Q.OBJ_ID, P.Q_ORDER, Q.STRUCT_POINT_ID, Q.ORDER_INDEX, QT.OBJ_ID, QT.OBJ_NAME
                  FROM UT_TEST_VAR_QUESTIONS Q
                  JOIN UT_TEST_STRUCT_POINTS P ON P.OBJ_ID = Q.STRUCT_POINT_ID
                  JOIN UT_QUESTIONS QT ON QT.OBJ_ID = Q.QUESTION_ID
                  -- WHERE Q.DATE_DEL IS NULL AND Q.VAR_ID = :I$VARIANT_ID
                  -- если вариант не передали, то отдаем все вопросы по всем вариантам
                  WHERE Q.DATE_DEL IS NULL AND Q.VAR_ID = COALESCE(:I$VARIANT_ID, :V$ID)
                  ORDER BY 2, 4
                  INTO :V$ID, :V$INDEX, :V$POINT_ID, :V$SCORE, :V$Q_ID, :V$Q_NAME
              DO
              BEGIN

                  TAG_NAME = 'data:tstr:s:tests:t:variants:v:qts:qt';
                  VAL = NULL;
                  SUSPEND;
    
                  TAG_NAME = 'data:tstr:s:tests:t:variants:v:qts:qt:id';
                  VAL = V$ID;
                  SUSPEND;
    
                  TAG_NAME = 'data:tstr:s:tests:t:variants:v:qts:qt:number';
                  VAL = V$INDEX;
                  SUSPEND;
    
                  TAG_NAME = 'data:tstr:s:tests:t:variants:v:qts:qt:point_id';
                  VAL = V$POINT_ID;
                  SUSPEND;
    
                  TAG_NAME = 'data:tstr:s:tests:t:variants:v:qts:qt:order_index';
                  VAL = V$SCORE;
                  SUSPEND;
    
                  TAG_NAME = 'data:tstr:s:tests:t:variants:v:qts:qt:q_id';
                  VAL = V$Q_ID;
                  SUSPEND;
    
                  TAG_NAME = 'data:tstr:s:tests:t:variants:v:qts:qt:q_name';
                  VAL = V$Q_NAME;
                  SUSPEND;

              END

              -- Файлы отображаем только того варианта, который запросили
              TAG_NAME = 'data:tstr:s:tests:t:variants:v:files';
              VAL = NULL;
              SUSPEND;
              TAG_NAME = 'data:tstr:s:tests:t:variants:v:files::json&colon;array';
              VAL = 1;
              SUSPEND;

              FOR
                  SELECT F.OBJ_ID, F.OBJ_NAME, F.FILE_HASH, F.CONTENT_TYPE, F.ATTR_MASK
                  FROM UT_TEST_VAR_FILES F
                  -- :I$VARIANT_ID = 0 > модальное окно редактирования всех вариантов
                  WHERE F.DATE_DEL IS NULL AND F.VAR_ID = COALESCE(:I$VARIANT_ID, :V$LOOP_VARIANT_ID)
                  ORDER BY 2
                  INTO :V$ID, :V$NAME, :V$S, :V$Q_NAME, :V$TYPE_ID
              DO
              BEGIN
                  TAG_NAME = 'data:tstr:s:tests:t:variants:v:files:r';
                  VAL = NULL;
                  SUSPEND;
                  TAG_NAME = 'data:tstr:s:tests:t:variants:v:files:r:id';
                  VAL = V$ID;
                  SUSPEND;
                  TAG_NAME = 'data:tstr:s:tests:t:variants:v:files:r:name';
                  VAL = V$NAME;
                  SUSPEND;
                  TAG_NAME = 'data:tstr:s:tests:t:variants:v:files:r:hash';
                  VAL = V$S;
                  SUSPEND;
                  TAG_NAME = 'data:tstr:s:tests:t:variants:v:files:r:type';
                  VAL = V$Q_NAME;
                  SUSPEND;
                  TAG_NAME = 'data:tstr:s:tests:t:variants:v:files:r:mask';
                  VAL = V$TYPE_ID;
                  SUSPEND;
              END

          END

      END

  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TESTS_SET (
    I$OBJ_ID BIGINT,
    I$STRUCT_ID BIGINT,
    I$OBJ_NAME VARCHAR(1000),
    I$EXAM_ID BIGINT = null)
RETURNS (
    OBJ_ID BIGINT,
    OBJ_NAME VARCHAR(1000))
AS
declare variable V$USER_ID bigint;
declare variable V$SUBJECT_ID bigint;
declare variable V$STAGE_ID integer;
declare variable V$GEN bigint;
declare variable V$MULTIPLIER bigint;
declare variable N integer;
BEGIN

  SELECT GEN, MULTIPLIER
  FROM GEN
  INTO :V$GEN, :V$MULTIPLIER;

  -- Проверка I$OBJ_NAME на NULL непонятно откуда вылезла
  IF(I$OBJ_NAME IS NOT NULL AND EXISTS(
      SELECT FIRST 1 1
      FROM UT_TESTS
      WHERE DATE_DEL IS NULL AND OBJ_NAME = :I$OBJ_NAME AND (OBJ_ID <> :I$OBJ_ID OR :I$OBJ_ID IS NULL)
  ))
  THEN EXCEPTION DATA_ERROR 'Пакет КИМ с таким названием уже есть';

  IF(I$OBJ_ID IS NULL) THEN
  BEGIN

      IF(I$OBJ_NAME IS NULL OR CHAR_LENGTH(I$OBJ_NAME) < 3) THEN EXCEPTION DATA_ERROR 'Название пакета КИМ должно быть не менее 3 символов';

      INSERT INTO UT_TESTS (STRUCT_ID, OBJ_NAME, MASTER_ED_ID)
      VALUES (:I$STRUCT_ID, :I$OBJ_NAME, :I$EXAM_ID)
      RETURNING OBJ_ID
      INTO :OBJ_ID;

      OBJ_NAME = I$OBJ_NAME;

  END
  ELSE
  BEGIN

      N = I$OBJ_ID / V$MULTIPLIER;
      IF(N <> V$GEN) THEN EXCEPTION DATA_ERROR 'Нельзя изменять пакет тестов, созданный в другой организации/уровне';

      OBJ_ID = I$OBJ_ID;

      SELECT T.OBJ_NAME, TS.SUBJECT_ID, TS.STAGE_ID
      FROM UT_TESTS T
      JOIN UT_TEST_STRUCTS TS ON TS.OBJ_ID = T.STRUCT_ID
      WHERE T.OBJ_ID = :I$OBJ_ID AND T.DATE_DEL IS NULL
      INTO :OBJ_NAME, :V$SUBJECT_ID, :V$STAGE_ID;

      IF(OBJ_NAME IS NULL) THEN EXCEPTION DATA_ERROR 'Пакет КИМ не найден или был удален другим пользователем';

      IF(OBJ_NAME <> I$OBJ_NAME) THEN
      BEGIN
          UPDATE UT_TESTS
          SET OBJ_NAME = :I$OBJ_NAME
          WHERE OBJ_ID = :I$OBJ_ID;
      END

  END

  SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_ASSN_PLACE_APPLY (
    I$EXAM_ID BIGINT,
    I$PPE_ID BIGINT,
    I$LEVEL1 INTEGER,
    I$OBJ_ID1 BIGINT,
    I$LEVEL2 INTEGER,
    I$OBJ_ID2 BIGINT,
    I$USER_ID VARCHAR(40),
    I$FLAGS INTEGER = 0)
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(200))
AS
declare variable V$TIME timestamp;
declare variable V$USER_TYPE smallint;
declare variable V$DB_LEVEL smallint;
declare variable V$STATE integer;
declare variable N_OK integer;
declare variable N_FAIL integer;
declare variable V$OBJ_ID bigint;
declare variable V$L integer;
declare variable V$N1 integer;
declare variable V$N2 integer;
declare variable TMP integer;
declare variable V$PLACE_ID bigint;
declare variable V$ROOM_ID bigint;
declare variable V$ASSN_ID bigint;
declare variable V$PLACE_NUM smallint;
declare variable V$PERSON_ID bigint;
declare variable V$PERSON_NAME varchar(1000);
begin

  V$TIME = CURRENT_TIMESTAMP;
  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  SELECT USER_TYPE
  FROM USERS
  WHERE USER_ID = :I$USER_ID AND DATE_DEL IS NULL
  INTO :V$USER_TYPE;

  -- Если пользователь не является админом, директором или завучем - ошибка
  -- IF(V$USER_TYPE NOT IN (1, 4, 5, 6)) THEN EXCEPTION DATA_ERROR 'У данного пользователя нет доступа к назначению на тестирование';

  -- Текущий уровень базы ?
  SELECT K.KEY_VAL
  FROM KEYS K
  WHERE K.KEY_CODE = 'LEVEL'
  INTO :V$DB_LEVEL;
  V$DB_LEVEL = 3 - V$DB_LEVEL;

  -- Проверяем статус тестирования ?
  SELECT EXAM_STATE
  FROM UT_EXAM_DATES
  WHERE DATE_DEL IS NULL AND OBJ_ID = :I$EXAM_ID
  INTO :V$STATE;

  IF(V$STATE IS NULL) THEN EXCEPTION DATA_ERROR 'Тестирование не найдено или было удалено другим пользователем';
  IF(V$STATE > 600) THEN EXCEPTION DATA_ERROR 'Нельзя выполнить резервирование участников тестирования на данной стадии';

  N_OK = 0;
  N_FAIL = 0;

  -- Далее выполняем распределение от конечного участника
  FOR
      SELECT OBJ_ID
      FROM UT_PLACES_LEVEL_UA_LIST(:I$EXAM_ID, :I$PPE_ID, :I$OBJ_ID1, :I$LEVEL1)
      INTO :V$OBJ_ID
  DO
  BEGIN

      -- Рассадка на конкретное место, либо ищем первое подходящее место
      IF(I$LEVEL2 = 2) THEN V$PLACE_ID = I$OBJ_ID2;
      ELSE IF(I$LEVEL2 = 1) THEN V$PLACE_ID = (SELECT PLACE_ID FROM UT_FIND_TEST_FREE_PLACE(:I$EXAM_ID, :I$PPE_ID, :I$OBJ_ID2, :V$OBJ_ID, :I$LEVEL1, :I$FLAGS));
      ELSE V$PLACE_ID = (SELECT PLACE_ID FROM UT_FIND_TEST_FREE_PLACE(:I$EXAM_ID, :I$PPE_ID, NULL, :V$OBJ_ID, :I$LEVEL1, :I$FLAGS));

      SELECT ASSN_ID
      FROM UT_TEST_ASSN_PLACE_APPLY_PERSON(:I$EXAM_ID, :V$OBJ_ID, :V$PLACE_ID)
      INTO :V$ASSN_ID;

      IF(V$ASSN_ID IS NULL) THEN N_FAIL = N_FAIL + 1; ELSE N_OK = N_OK + 1;

  END

  -- Статистика по дереву участников
  TAG_NAME = 'items';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'items::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
      SELECT C.OBJ_ID, C.OBJ_LEVEL, C.N_ASSN, C.N_FREE, C.PLACE_ID, C.ROOM_ID, C.PLACE_NUM
      FROM UT_TEST_ASSN_PLACE_CHANGES(:I$EXAM_ID, :I$PPE_ID, :I$LEVEL1, :V$TIME, :V$DB_LEVEL) C
      INTO :V$OBJ_ID, :V$L, :V$N1, :V$N2, :V$PLACE_ID, :V$ROOM_ID, :V$PLACE_NUM
  DO
  BEGIN
      TAG_NAME = 'items:p';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'items:p:level';
      VAL = V$L;
      SUSPEND;
      TAG_NAME = 'items:p:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'items:p:n_assn';
      VAL = V$N1;
      SUSPEND;
      TAG_NAME = 'items:p:n_free';
      VAL = V$N2;
      SUSPEND;
      IF(V$L = 3) THEN
      BEGIN
          TAG_NAME = 'items:p:place_id';
          VAL = V$PLACE_ID;
          SUSPEND;
          TAG_NAME = 'items:p:room_id';
          VAL = V$ROOM_ID;
          SUSPEND;
          TAG_NAME = 'items:p:place_num';
          VAL = V$PLACE_NUM;
          SUSPEND;
      END
  END

  -- Статистика по местам
  TAG_NAME = 'places';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'places::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
      SELECT C.OBJ_ID, C.OBJ_LEVEL, C.N_ASSN, C.N_FREE, C.N_TOTAL, C.PERSON_ID, C.PERSON_NAME
      FROM UT_TEST_ASSN_PLACE_RCHANGES(:I$EXAM_ID, :I$PPE_ID, :I$LEVEL2, :V$TIME, :V$DB_LEVEL) C
      INTO :V$OBJ_ID, :V$L, :V$N1, :V$N2, :TMP, :V$PERSON_ID, :V$PERSON_NAME
  DO
  BEGIN
      TAG_NAME = 'places:p';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'places:p:level';
      VAL = V$L;
      SUSPEND;
      TAG_NAME = 'places:p:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'places:p:n_total';
      VAL = TMP;
      SUSPEND;
      TAG_NAME = 'places:p:n_assn';
      VAL = V$N1;
      SUSPEND;
      TAG_NAME = 'places:p:n_free';
      VAL = V$N2;
      SUSPEND;
      IF(V$PERSON_ID IS NOT NULL) THEN
      BEGIN
          TAG_NAME = 'places:p:person_id';
          VAL = V$PERSON_ID;
          SUSPEND;
          TAG_NAME = 'places:p:person_name';
          VAL = V$PERSON_NAME;
          SUSPEND;
      END
  END

  -- Итоги
  TAG_NAME = 'n_assigned';
  VAL = N_OK;
  SUSPEND;
  TAG_NAME = 'n_failed';
  VAL = N_FAIL;
  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_ASSN_PLACE_APPLY_PERSON (
    I$EXAM_ID BIGINT,
    I$PERSON_ID BIGINT,
    I$PLACE_ID BIGINT)
RETURNS (
    ASSN_ID BIGINT)
AS
declare variable V$PLACE_ASSN bigint;
begin

  SELECT FIRST 1 A.OBJ_ID
  FROM UT_PERSON_PLACE_ASSN A
  WHERE A.EXAM_ID = :I$EXAM_ID AND A.PERSON_ID = :I$PERSON_ID AND A.DATE_DEL IS NULL
  INTO :ASSN_ID;

  SELECT FIRST 1 A.OBJ_ID
  FROM UT_PERSON_PLACE_ASSN A
  WHERE A.EXAM_ID = :I$EXAM_ID AND A.PLACE_ID = :I$PLACE_ID AND A.DATE_DEL IS NULL
  INTO :V$PLACE_ASSN;

  -- А доступно ли это место
  IF(EXISTS(
      SELECT FIRST 1 1
      FROM UT_PPE_PLACES P
      WHERE P.OBJ_ID = :I$PLACE_ID AND P.IS_DELETED <> 0
  ))
  THEN EXCEPTION DATA_ERROR 'Выбранное место для рассадки недоступно';

  -- Смену закрепления делаем только если участник ранее не был рассажен, и место не было занято
  IF(I$PLACE_ID IS NOT NULL AND ASSN_ID IS NULL AND V$PLACE_ASSN IS NULL) THEN
  BEGIN

      INSERT INTO UT_PERSON_PLACE_ASSN
      (EXAM_ID, PERSON_ID, PLACE_ID)
      VALUES (:I$EXAM_ID, :I$PERSON_ID, :I$PLACE_ID)
      RETURNING OBJ_ID INTO :ASSN_ID;

  END

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_ASSN_PLACE_CHANGES (
    I$EXAM_ID BIGINT,
    I$PPE_ID BIGINT,
    I$LEVEL INTEGER,
    I$TIME TIMESTAMP,
    I$USER_LEVEL SMALLINT)
RETURNS (
    OBJ_ID BIGINT,
    OBJ_LEVEL INTEGER,
    N_ASSN INTEGER,
    N_FREE INTEGER,
    PLACE_ID BIGINT,
    PLACE_NUM SMALLINT,
    ROOM_ID BIGINT)
AS
begin

  -- Уровень участников
  OBJ_LEVEL = 3;
  FOR
      SELECT DISTINCT A.PERSON_ID
      FROM UT_PERSON_PLACE_ASSN A
      JOIN UT_PERSON_PPE_ASSN PPE ON PPE.DATE_DEL IS NULL AND PPE.EXAM_ID = :I$EXAM_ID AND PPE.PERSON_ID = A.PERSON_ID AND PPE.PPE_ID = :I$PPE_ID
      WHERE A.DATE_MODIFY >= :I$TIME AND A.EXAM_ID = :I$EXAM_ID
      INTO :OBJ_ID
  DO
  BEGIN
      PLACE_ID = NULL;
      ROOM_ID = NULL;
      PLACE_NUM = NULL;
      SELECT FIRST 1 A.PLACE_ID, P.ROOM_ID, P.PLACE_NUM
      FROM UT_PERSON_PLACE_ASSN A
      JOIN UT_PPE_PLACES P ON P.OBJ_ID = A.PLACE_ID
      WHERE A.EXAM_ID = :I$EXAM_ID AND A.PERSON_ID = :OBJ_ID AND A.DATE_DEL IS NULL
      INTO :PLACE_ID, :ROOM_ID, :PLACE_NUM;

      N_ASSN = IIF(PLACE_ID IS NULL, 0, 1);
      N_FREE = IIF(PLACE_ID IS NULL, 1, 0);
      SUSPEND;
  END
  ROOM_ID = NULL;
  PLACE_ID = NULL;
  PLACE_NUM = NULL;

  -- Группы
  OBJ_LEVEL = 2;
  FOR
      SELECT DISTINCT LPG.PARENT_ID
      FROM UT_PERSON_PLACE_ASSN A
      JOIN UT_PERSON_PPE_ASSN PPE ON PPE.DATE_DEL IS NULL AND PPE.EXAM_ID = :I$EXAM_ID AND PPE.PERSON_ID = A.PERSON_ID AND PPE.PPE_ID = :I$PPE_ID
      JOIN LINKS LPG ON LPG.OBJ_ID = A.PERSON_ID AND LPG.PARENT_TYPE_ID IN (2, 9, 125, 187) AND LPG.DATE_DEL IS NULL
      WHERE A.DATE_MODIFY >= :I$TIME AND A.EXAM_ID = :I$EXAM_ID
      INTO :OBJ_ID
  DO
  BEGIN
      SELECT COUNT(*)
      FROM LINKS LS
      JOIN UT_PERSON_PPE_ASSN PPE ON PPE.DATE_DEL IS NULL AND PPE.EXAM_ID = :I$EXAM_ID AND PPE.PERSON_ID = LS.OBJ_ID AND PPE.PPE_ID = :I$PPE_ID
      JOIN UT_PERSON_PLACE_ASSN A ON A.EXAM_ID = :I$EXAM_ID AND A.PERSON_ID = LS.OBJ_ID AND A.DATE_DEL IS NULL
      WHERE LS.PARENT_ID = :OBJ_ID AND LS.OBJ_TYPE_ID IN (10, 14, 126) AND LS.DATE_DEL IS NULL
      INTO :N_ASSN;
      SELECT COUNT(*)
      FROM LINKS LS
      JOIN UT_PERSON_PPE_ASSN PPE ON PPE.DATE_DEL IS NULL AND PPE.EXAM_ID = :I$EXAM_ID AND PPE.PERSON_ID = LS.OBJ_ID AND PPE.PPE_ID = :I$PPE_ID
      LEFT JOIN UT_PERSON_PLACE_ASSN A ON A.EXAM_ID = :I$EXAM_ID AND A.PERSON_ID = LS.OBJ_ID AND A.DATE_DEL IS NULL
      WHERE LS.PARENT_ID = :OBJ_ID AND LS.OBJ_TYPE_ID IN (10, 14, 126) AND LS.DATE_DEL IS NULL AND A.OBJ_ID IS NULL
      INTO :N_FREE;

      SUSPEND;
  END

  -- ОУ
  OBJ_LEVEL = 1;
  FOR
      SELECT DISTINCT LPG.PARENT_ID
      FROM UT_PERSON_PLACE_ASSN A
      JOIN UT_PERSON_PPE_ASSN PPE ON PPE.DATE_DEL IS NULL AND PPE.EXAM_ID = :I$EXAM_ID AND PPE.PERSON_ID = A.PERSON_ID AND PPE.PPE_ID = :I$PPE_ID
      JOIN LINKS LPG ON LPG.OBJ_ID = A.PERSON_ID AND LPG.PARENT_TYPE_ID = 2 AND LPG.DATE_DEL IS NULL
      WHERE A.DATE_MODIFY >= :I$TIME AND A.EXAM_ID = :I$EXAM_ID
      UNION
      SELECT DISTINCT LP2.PARENT_ID
      FROM UT_PERSON_PLACE_ASSN A
      JOIN UT_PERSON_PPE_ASSN PPE ON PPE.DATE_DEL IS NULL AND PPE.EXAM_ID = :I$EXAM_ID AND PPE.PERSON_ID = A.PERSON_ID AND PPE.PPE_ID = :I$PPE_ID
      JOIN LINKS LPG ON LPG.OBJ_ID = A.PERSON_ID AND LPG.PARENT_TYPE_ID IN (9, 125, 187) AND LPG.DATE_DEL IS NULL
      JOIN LINKS LP8 ON LP8.OBJ_ID = LPG.PARENT_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
      JOIN LINKS LP7 ON LP7.OBJ_ID = LP8.PARENT_ID AND LP7.PARENT_TYPE_ID IN (7, 502) AND LP7.DATE_DEL IS NULL
      JOIN LINKS LP2 ON LP2.OBJ_ID = LP7.PARENT_ID AND LP2.PARENT_TYPE_ID = 2 AND LP2.DATE_DEL IS NULL
      WHERE A.DATE_MODIFY >= :I$TIME AND A.EXAM_ID = :I$EXAM_ID
      INTO :OBJ_ID
  DO
  BEGIN
      SELECT COUNT(*)
      FROM (
          SELECT L14.OBJ_ID
          FROM LINKS L14
          JOIN UT_PERSON_PPE_ASSN PPE ON PPE.DATE_DEL IS NULL AND PPE.EXAM_ID = :I$EXAM_ID AND PPE.PERSON_ID = L14.OBJ_ID AND PPE.PPE_ID = :I$PPE_ID
          JOIN UT_PERSON_PLACE_ASSN A ON A.EXAM_ID = :I$EXAM_ID AND A.PERSON_ID = L14.OBJ_ID AND A.DATE_DEL IS NULL
          WHERE L14.PARENT_ID = :OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
          UNION
          SELECT L10.OBJ_ID
          FROM LINKS L7
          JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
          JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 125, 187) AND L9.DATE_DEL IS NULL
          JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID IN (10, 126) AND L10.DATE_DEL IS NULL
          JOIN UT_PERSON_PPE_ASSN PPE ON PPE.DATE_DEL IS NULL AND PPE.EXAM_ID = :I$EXAM_ID AND PPE.PERSON_ID = L10.OBJ_ID AND PPE.PPE_ID = :I$PPE_ID
          JOIN UT_PERSON_PLACE_ASSN A ON A.EXAM_ID = :I$EXAM_ID AND A.PERSON_ID = L10.OBJ_ID AND A.DATE_DEL IS NULL
          WHERE L7.PARENT_ID = :OBJ_ID AND L7.OBJ_TYPE_ID IN (7, 502) AND L7.DATE_DEL IS NULL
      )
      INTO :N_ASSN;
      SELECT COUNT(*)
      FROM (
          SELECT L14.OBJ_ID
          FROM LINKS L14
          JOIN UT_EXAM_PERSON_ASSN PA ON PA.DATE_DEL IS NULL AND PA.EXAM_ID = :I$EXAM_ID AND PA.PERSON_ID = L14.OBJ_ID
          JOIN UT_PERSON_PPE_ASSN PPE ON PPE.DATE_DEL IS NULL AND PPE.EXAM_ID = :I$EXAM_ID AND PPE.PERSON_ID = L14.OBJ_ID AND PPE.PPE_ID = :I$PPE_ID
          LEFT JOIN UT_PERSON_PLACE_ASSN A ON A.EXAM_ID = :I$EXAM_ID AND A.PERSON_ID = L14.OBJ_ID AND A.DATE_DEL IS NULL
          WHERE L14.PARENT_ID = :OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL AND A.OBJ_ID IS NULL
          UNION
          SELECT L10.OBJ_ID
          FROM LINKS L7
          JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
          JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 125, 187) AND L9.DATE_DEL IS NULL
          JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID IN (10, 126) AND L10.DATE_DEL IS NULL
          JOIN UT_EXAM_PERSON_ASSN PA ON PA.DATE_DEL IS NULL AND PA.EXAM_ID = :I$EXAM_ID AND PA.PERSON_ID = L10.OBJ_ID
          JOIN UT_PERSON_PPE_ASSN PPE ON PPE.DATE_DEL IS NULL AND PPE.EXAM_ID = :I$EXAM_ID AND PPE.PERSON_ID = L10.OBJ_ID AND PPE.PPE_ID = :I$PPE_ID
          LEFT JOIN UT_PERSON_PLACE_ASSN A ON A.EXAM_ID = :I$EXAM_ID AND A.PERSON_ID = L10.OBJ_ID AND A.DATE_DEL IS NULL
          WHERE L7.PARENT_ID = :OBJ_ID AND L7.OBJ_TYPE_ID IN (7, 502) AND L7.DATE_DEL IS NULL AND A.OBJ_ID IS NULL
      )
      INTO :N_FREE;

      SUSPEND;
  END

  -- Все распределенные в ППЭ
  OBJ_LEVEL = 0;
  OBJ_ID = NULL;
  SELECT COUNT(*)
  FROM UT_PERSON_PPE_ASSN PPE
  JOIN UT_PERSON_PLACE_ASSN A ON A.EXAM_ID = :I$EXAM_ID AND A.PERSON_ID = PPE.PERSON_ID AND A.DATE_DEL IS NULL
  WHERE PPE.DATE_DEL IS NULL AND PPE.EXAM_ID = :I$EXAM_ID AND PPE.PPE_ID = :I$PPE_ID
  INTO :N_ASSN;
  SELECT COUNT(*)
  FROM UT_PERSON_PPE_ASSN PPE
  LEFT JOIN UT_PERSON_PLACE_ASSN A ON A.EXAM_ID = :I$EXAM_ID AND A.PERSON_ID = PPE.PERSON_ID AND A.DATE_DEL IS NULL
  WHERE PPE.DATE_DEL IS NULL AND PPE.EXAM_ID = :I$EXAM_ID AND PPE.PPE_ID = :I$PPE_ID AND A.OBJ_ID IS NULL
  INTO :N_FREE;

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_ASSN_PLACE_LTREE (
    I$EXAM_ID BIGINT,
    I$PPE_ID BIGINT,
    I$LEVEL INTEGER,
    I$PARENT_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$ID BIGINT;
DECLARE VARIABLE V$NAME VARCHAR(1000);
DECLARE VARIABLE V$ORDER DOUBLE PRECISION;
DECLARE VARIABLE V$PLACE_ID BIGINT;
DECLARE VARIABLE V$PLACE_NAME VARCHAR(100);
DECLARE VARIABLE V$NUM INTEGER;
DECLARE VARIABLE V$N_COL INTEGER;
DECLARE VARIABLE V$N_ROW INTEGER;
DECLARE VARIABLE V$ROOM_ID BIGINT;
DECLARE VARIABLE N1 INTEGER;
DECLARE VARIABLE N2 INTEGER;
begin

  TAG_NAME = 'items';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'items::json&colon;array';
  VAL = '1';
  SUSPEND;

  -- Корень дерева - виртуальный узел
  IF(I$LEVEL IS NULL) THEN
  BEGIN

      SELECT COUNT(*)
      FROM UT_PERSON_PPE_ASSN PA
      WHERE PA.EXAM_ID = :I$EXAM_ID AND PA.PPE_ID = :I$PPE_ID AND PA.DATE_DEL IS NULL
      INTO :N1;

      SELECT COUNT(*)
      FROM UT_PERSON_PPE_ASSN PA
      JOIN UT_PERSON_PLACE_ASSN A ON A.DATE_DEL IS NULL AND A.EXAM_ID = :I$EXAM_ID AND A.PERSON_ID = PA.PERSON_ID
      WHERE PA.EXAM_ID = :I$EXAM_ID AND PA.PPE_ID = :I$PPE_ID AND PA.DATE_DEL IS NULL
      INTO :N2;

      TAG_NAME = 'items:p';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'items:p:level';
      VAL = 0;
      SUSPEND;
      TAG_NAME = 'items:p:id';
      VAL = '';
      SUSPEND;
      TAG_NAME = 'items:p:name';
      VAL = 'Все распределенные участники';
      SUSPEND;
      TAG_NAME = 'items:p:has_children';
      VAL = 1;
      IF(N1 > 0) THEN VAL = 1; ELSE VAL = 0;
      SUSPEND;

      TAG_NAME = 'items:p:n_assn';
      VAL = N2;
      SUSPEND;

      TAG_NAME = 'items:p:n_free';
      VAL = N1 - N2;
      SUSPEND;

  END
  -- Нулевой уровень выбора = Виртуальный узел "Все участники", возвращаем список ОУ
  ELSE IF(I$LEVEL = 0) THEN
  BEGIN
      FOR
          -- Сотрудники
          SELECT DISTINCT LP2.PARENT_ID, C.CAPTION
          FROM UT_PERSON_PPE_ASSN PA
          JOIN LINKS LP2 ON LP2.OBJ_ID = PA.PERSON_ID AND LP2.PARENT_TYPE_ID = 2 AND LP2.DATE_DEL IS NULL
          LEFT JOIN OBJECT_CAPTION_GET(LP2.PARENT_ID) C ON 1 = 1
          WHERE PA.DATE_DEL IS NULL AND PA.EXAM_ID = :I$EXAM_ID AND PA.PPE_ID = :I$PPE_ID
          -- Учащиеся
          UNION
          SELECT DISTINCT LP2.PARENT_ID, C.CAPTION
          FROM UT_PERSON_PPE_ASSN PA
          JOIN LINKS LP9 ON LP9.OBJ_ID = PA.PERSON_ID AND LP9.PARENT_TYPE_ID IN (9, 125, 187) AND LP9.DATE_DEL IS NULL
          JOIN LINKS LP8 ON LP8.OBJ_ID = LP9.PARENT_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
          JOIN LINKS LP7 ON LP7.OBJ_ID = LP8.PARENT_ID AND LP7.PARENT_TYPE_ID IN (7, 502) AND LP7.DATE_DEL IS NULL
          JOIN LINKS LP2 ON LP2.OBJ_ID = LP7.PARENT_ID AND LP2.PARENT_TYPE_ID = 2 AND LP2.DATE_DEL IS NULL
          LEFT JOIN OBJECT_CAPTION_GET(LP2.PARENT_ID) C ON 1 = 1
          WHERE PA.DATE_DEL IS NULL AND PA.EXAM_ID = :I$EXAM_ID AND PA.PPE_ID = :I$PPE_ID
          ORDER BY 2
          INTO :V$ID, :V$NAME
      DO
      BEGIN
          SELECT COUNT(*)
          FROM (
              SELECT L10.OBJ_ID
              FROM LINKS L7
              JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
              JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 125, 187) AND L9.DATE_DEL IS NULL
              JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID IN (10, 14) AND L10.DATE_DEL IS NULL
              JOIN UT_PERSON_PPE_ASSN PA ON PA.PERSON_ID = L10.OBJ_ID AND PA.EXAM_ID = :I$EXAM_ID AND PA.PPE_ID = :I$PPE_ID AND PA.DATE_DEL IS NULL
              WHERE L7.PARENT_ID = :V$ID AND L7.OBJ_TYPE_ID IN (7, 502) AND L7.DATE_DEL IS NULL
              UNION
              SELECT L14.OBJ_ID
              FROM LINKS L14
              JOIN UT_PERSON_PPE_ASSN PA ON PA.PERSON_ID = L14.OBJ_ID AND PA.EXAM_ID = :I$EXAM_ID AND PA.PPE_ID = :I$PPE_ID AND PA.DATE_DEL IS NULL
              WHERE L14.PARENT_ID = :V$ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
          )
          INTO :N1;

          SELECT COUNT(*)
          FROM (
              SELECT L10.OBJ_ID
              FROM LINKS L7
              JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
              JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 125, 187) AND L9.DATE_DEL IS NULL
              JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID IN (10, 14) AND L10.DATE_DEL IS NULL
              JOIN UT_PERSON_PPE_ASSN PA ON PA.PERSON_ID = L10.OBJ_ID AND PA.EXAM_ID = :I$EXAM_ID AND PA.PPE_ID = :I$PPE_ID AND PA.DATE_DEL IS NULL
              JOIN UT_PERSON_PLACE_ASSN A ON A.DATE_DEL IS NULL AND A.EXAM_ID = :I$EXAM_ID AND A.PERSON_ID = PA.PERSON_ID
              WHERE L7.PARENT_ID = :V$ID AND L7.OBJ_TYPE_ID IN (7, 502) AND L7.DATE_DEL IS NULL
              UNION
              SELECT L14.OBJ_ID
              FROM LINKS L14
              JOIN UT_PERSON_PPE_ASSN PA ON PA.PERSON_ID = L14.OBJ_ID AND PA.EXAM_ID = :I$EXAM_ID AND PA.PPE_ID = :I$PPE_ID AND PA.DATE_DEL IS NULL
              JOIN UT_PERSON_PLACE_ASSN A ON A.DATE_DEL IS NULL AND A.EXAM_ID = :I$EXAM_ID AND A.PERSON_ID = PA.PERSON_ID
              WHERE L14.PARENT_ID = :V$ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
          )
          INTO :N2;

          TAG_NAME = 'items:p';
          VAL = NULL;
          SUSPEND;
          TAG_NAME = 'items:p:level';
          VAL = 1;
          SUSPEND;
          TAG_NAME = 'items:p:id';
          VAL = V$ID;
          SUSPEND;
          TAG_NAME = 'items:p:name';
          VAL = V$NAME;
          SUSPEND;
          TAG_NAME = 'items:p:has_children';
          VAL = 1;
          IF(N1 > 0) THEN VAL = 1; ELSE VAL = 0;
          SUSPEND;

          TAG_NAME = 'items:p:n_assn';
          VAL = N2;
          SUSPEND;

          TAG_NAME = 'items:p:n_free';
          VAL = N1 - N2;
          SUSPEND;
      END

  END
  -- Первый уровень выбора = возвращаем список коллективов выбранной ОУ
  ELSE IF(I$LEVEL = 1) THEN
  BEGIN
      FOR
          -- Сотрудники
          SELECT DISTINCT LP2.PARENT_ID, 'Сотрудники', -1
          FROM UT_PERSON_PPE_ASSN PA
          JOIN LINKS LP2 ON LP2.OBJ_ID = PA.PERSON_ID AND LP2.DATE_DEL IS NULL AND LP2.PARENT_ID = :I$PARENT_ID
          WHERE PA.DATE_DEL IS NULL AND PA.EXAM_ID = :I$EXAM_ID AND PA.PPE_ID = :I$PPE_ID
          -- Ученики
          UNION
          SELECT DISTINCT LP9.PARENT_ID, C.CAPTION, LV49.SORT_ORDER
          FROM UT_PERSON_PPE_ASSN PA
          JOIN LINKS LP9 ON LP9.OBJ_ID = PA.PERSON_ID AND LP9.PARENT_TYPE_ID IN (9, 125, 187) AND LP9.DATE_DEL IS NULL
          JOIN LINKS LP8 ON LP8.OBJ_ID = LP9.PARENT_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
          JOIN VALL V49 ON V49.OBJ_ID = LP8.PARENT_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
          JOIN LISTVALS LV49 ON LV49.LISTVAL_ID = V49.LISTVAL_ID
          JOIN LINKS LP7 ON LP7.OBJ_ID = LP8.PARENT_ID AND LP7.PARENT_TYPE_ID IN (7, 502) AND LP7.DATE_DEL IS NULL
          JOIN LINKS LP2 ON LP2.OBJ_ID = LP7.PARENT_ID AND LP2.DATE_DEL IS NULL AND LP2.PARENT_ID = :I$PARENT_ID
          LEFT JOIN OBJECT_CAPTION_GET(LP9.PARENT_ID) C ON 1 = 1
          WHERE PA.DATE_DEL IS NULL AND PA.EXAM_ID = :I$EXAM_ID AND PA.PPE_ID = :I$PPE_ID
          ORDER BY 3, 2
          INTO :V$ID, :V$NAME, :V$ORDER
      DO
      BEGIN
          SELECT COUNT(*)
          FROM LINKS L10
          JOIN UT_PERSON_PPE_ASSN PA ON PA.PERSON_ID = L10.OBJ_ID AND PA.EXAM_ID = :I$EXAM_ID AND PA.PPE_ID = :I$PPE_ID AND PA.DATE_DEL IS NULL
          WHERE L10.PARENT_ID = :V$ID AND L10.OBJ_TYPE_ID IN (10, 14) AND L10.DATE_DEL IS NULL
          INTO :N1;

          SELECT COUNT(*)
          FROM LINKS L10
          JOIN UT_PERSON_PPE_ASSN PA ON PA.PERSON_ID = L10.OBJ_ID AND PA.EXAM_ID = :I$EXAM_ID AND PA.PPE_ID = :I$PPE_ID AND PA.DATE_DEL IS NULL
          JOIN UT_PERSON_PLACE_ASSN A ON A.DATE_DEL IS NULL AND A.EXAM_ID = :I$EXAM_ID AND A.PERSON_ID = PA.PERSON_ID
          WHERE L10.PARENT_ID = :V$ID AND L10.OBJ_TYPE_ID IN (10, 14) AND L10.DATE_DEL IS NULL
          INTO :N2;

          TAG_NAME = 'items:p';
          VAL = NULL;
          SUSPEND;
          TAG_NAME = 'items:p:level';
          VAL = 2;
          SUSPEND;
          TAG_NAME = 'items:p:id';
          VAL = V$ID;
          SUSPEND;
          TAG_NAME = 'items:p:name';
          VAL = V$NAME;
          SUSPEND;
          TAG_NAME = 'items:p:has_children';
          VAL = 1;
          IF(N1 > 0) THEN VAL = 1; ELSE VAL = 0;
          SUSPEND;

          TAG_NAME = 'items:p:n_assn';
          VAL = N2;
          SUSPEND;

          TAG_NAME = 'items:p:n_free';
          VAL = N1 - N2;
          SUSPEND;
      END
  END
  -- Третий уровень выбора = участники
  ELSE IF(I$LEVEL = 2) THEN
  BEGIN
      FOR
          SELECT PA.PERSON_ID, D.NAME_FULL
          FROM UT_PERSON_PPE_ASSN PA
          JOIN LINKS LP ON LP.OBJ_ID = PA.PERSON_ID AND LP.PARENT_TYPE_ID IN (2, 9, 125, 187) AND LP.DATE_DEL IS NULL AND LP.PARENT_ID = :I$PARENT_ID
          LEFT JOIN UT_PERSON_DESC(PA.PERSON_ID) D ON 1 = 1
          WHERE PA.DATE_DEL IS NULL AND PA.EXAM_ID = :I$EXAM_ID AND PA.PPE_ID = :I$PPE_ID
          ORDER BY 2
          INTO :V$ID, :V$NAME
      DO
      BEGIN
          N1 = 1;
          N2 = 0;
          V$ROOM_ID = NULL;
          V$PLACE_ID = NULL;
          V$PLACE_NAME = NULL;
          V$NUM = NULL;
          V$N_ROW = NULL;
          V$N_COL = NULL;
          SELECT FIRST 1 1, PP.ROOM_ID, A.PLACE_ID, PP.PLACE_NUM, PP.OBJ_NAME, PP.N_ROW, PP.N_COL
          FROM UT_PERSON_PPE_ASSN PA
          JOIN UT_PERSON_PLACE_ASSN A ON A.DATE_DEL IS NULL AND A.EXAM_ID = :I$EXAM_ID AND A.PERSON_ID = PA.PERSON_ID
          JOIN UT_PPE_PLACES PP ON PP.OBJ_ID = A.PLACE_ID AND PP.DATE_DEL IS NULL
          WHERE PA.PERSON_ID = :V$ID AND PA.EXAM_ID = :I$EXAM_ID AND PA.PPE_ID = :I$PPE_ID AND PA.DATE_DEL IS NULL
          INTO :N2, :V$ROOM_ID, :V$PLACE_ID, :V$NUM, :V$PLACE_NAME, :V$N_ROW, :V$N_COL;

          TAG_NAME = 'items:p';
          VAL = NULL;
          SUSPEND;
          TAG_NAME = 'items:p:level';
          VAL = 3;
          SUSPEND;
          TAG_NAME = 'items:p:id';
          VAL = V$ID;
          SUSPEND;
          TAG_NAME = 'items:p:name';
          VAL = V$NAME;
          SUSPEND;
          TAG_NAME = 'items:p:has_children';
          VAL = 0;
          SUSPEND;

          TAG_NAME = 'items:p:n_assn';
          VAL = N2;
          SUSPEND;

          TAG_NAME = 'items:p:n_free';
          VAL = N1 - N2;
          SUSPEND;

          TAG_NAME = 'items:p:room_id';
          VAL = V$ROOM_ID;
          SUSPEND;
          TAG_NAME = 'items:p:place_id';
          VAL = V$PLACE_ID;
          SUSPEND;
          TAG_NAME = 'items:p:place_name';
          VAL = V$PLACE_NAME;
          SUSPEND;
          TAG_NAME = 'items:p:place_num';
          VAL = V$NUM;
          SUSPEND;
          TAG_NAME = 'items:p:n_row';
          VAL = V$N_ROW;
          SUSPEND;
          TAG_NAME = 'items:p:n_col';
          VAL = V$N_COL;
          SUSPEND;
      END
  END
  ELSE EXCEPTION DATA_ERROR 'Недопустимый код уровня';

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_ASSN_PLACE_RCHANGES (
    I$EXAM_ID BIGINT,
    I$PPE_ID BIGINT,
    I$LEVEL INTEGER,
    I$TIME TIMESTAMP,
    I$USER_LEVEL SMALLINT)
RETURNS (
    OBJ_ID BIGINT,
    OBJ_LEVEL INTEGER,
    PERSON_ID BIGINT,
    PERSON_NAME VARCHAR(1000),
    N_TOTAL INTEGER,
    N_ASSN INTEGER,
    N_FREE INTEGER)
AS
begin

  -- Места
  OBJ_LEVEL = 2;
  FOR
      SELECT DISTINCT A.PLACE_ID
      FROM UT_PERSON_PLACE_ASSN A
      JOIN UT_PERSON_PPE_ASSN PPE ON PPE.EXAM_ID = :I$EXAM_ID AND PPE.PERSON_ID = A.PERSON_ID AND PPE.PPE_ID = :I$PPE_ID
      WHERE A.DATE_MODIFY >= :I$TIME AND A.EXAM_ID = :I$EXAM_ID
      INTO :OBJ_ID
  DO
  BEGIN
      PERSON_ID = NULL;
      PERSON_NAME = NULL;
      N_ASSN = 0;

      SELECT FIRST 1 1, A.PERSON_ID, D.NAME_FULL || ', ' || D.CLASS_NAME || ', ' || D.OU_NAME
      FROM UT_PERSON_PLACE_ASSN A
      JOIN UT_PERSON_PPE_ASSN PPE ON PPE.DATE_DEL IS NULL AND PPE.EXAM_ID = :I$EXAM_ID AND PPE.PERSON_ID = A.PERSON_ID AND PPE.PPE_ID = :I$PPE_ID
      LEFT JOIN UT_STUDENT_DESC(A.PERSON_ID) D ON 1 = 1
      WHERE A.EXAM_ID = :I$EXAM_ID AND A.PLACE_ID = :OBJ_ID AND A.DATE_DEL IS NULL
      INTO :N_ASSN, :PERSON_ID, :PERSON_NAME;

      N_TOTAL = 1;
      N_FREE = MAXVALUE(N_TOTAL - N_ASSN, 0);

      SUSPEND;
  END

  PERSON_ID = NULL;
  PERSON_NAME = NULL;

  -- Помещения
  OBJ_LEVEL = 1;
  FOR
      SELECT DISTINCT PP.ROOM_ID, R.N_PLACES
      FROM UT_PERSON_PLACE_ASSN A
      JOIN UT_PERSON_PPE_ASSN PPE ON PPE.DATE_DEL IS NULL AND PPE.EXAM_ID = :I$EXAM_ID AND PPE.PERSON_ID = A.PERSON_ID AND PPE.PPE_ID = :I$PPE_ID
      JOIN UT_PPE_PLACES PP ON PP.DATE_DEL IS NULL AND PP.OBJ_ID = A.PLACE_ID
      JOIN UT_PPE_ROOMS R ON R.OBJ_ID = PP.ROOM_ID
      WHERE A.DATE_MODIFY >= :I$TIME AND A.EXAM_ID = :I$EXAM_ID
      INTO :OBJ_ID, :N_TOTAL
  DO
  BEGIN
      SELECT COUNT(*)
      FROM UT_PERSON_PLACE_ASSN A
      JOIN UT_PERSON_PPE_ASSN PPE ON PPE.DATE_DEL IS NULL AND PPE.EXAM_ID = :I$EXAM_ID AND PPE.PERSON_ID = A.PERSON_ID AND PPE.PPE_ID = :I$PPE_ID
      JOIN UT_PPE_PLACES PP ON PP.DATE_DEL IS NULL AND PP.OBJ_ID = A.PLACE_ID AND PP.ROOM_ID = :OBJ_ID
      WHERE A.EXAM_ID = :I$EXAM_ID AND A.DATE_DEL IS NULL
      INTO :N_ASSN;

      N_FREE = MAXVALUE(N_TOTAL - N_ASSN, 0);

      SUSPEND;
  END

  -- ППЭ в целом
  OBJ_LEVEL = 0;
  OBJ_ID = NULL;

  SELECT COALESCE(SUM(R.N_PLACES), 0)
  FROM UT_EXAM_ROOM_ASSN A
  JOIN UT_PPE_ROOMS R ON R.OBJ_ID = A.ROOM_ID AND R.PPE_ID = :I$PPE_ID AND R.DATE_DEL IS NULL
  WHERE A.EXAM_ID = :I$EXAM_ID AND A.DATE_DEL IS NULL
  INTO :N_TOTAL;

  SELECT COUNT(*)
  FROM UT_PERSON_PLACE_ASSN A
  JOIN UT_PERSON_PPE_ASSN PPE ON PPE.DATE_DEL IS NULL AND PPE.EXAM_ID = :I$EXAM_ID AND PPE.PERSON_ID = A.PERSON_ID AND PPE.PPE_ID = :I$PPE_ID
  WHERE A.EXAM_ID = :I$EXAM_ID AND A.DATE_DEL IS NULL
  INTO :N_ASSN;

  N_FREE = MAXVALUE(N_TOTAL - N_ASSN, 0);

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_ASSN_PLACE_REVERT (
    I$EXAM_ID BIGINT,
    I$PPE_ID BIGINT,
    I$SIDE INTEGER,
    I$LEVEL INTEGER,
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(200))
AS
DECLARE VARIABLE V$TIME TIMESTAMP;
DECLARE VARIABLE V$USER_TYPE SMALLINT;
DECLARE VARIABLE V$DB_LEVEL BIGINT;
DECLARE VARIABLE V$STATE INTEGER;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE N INTEGER;
DECLARE VARIABLE N_ALL INTEGER;
DECLARE VARIABLE V$N1 INTEGER;
DECLARE VARIABLE V$N2 INTEGER;
DECLARE VARIABLE V$L INTEGER;
DECLARE VARIABLE V$PLACE_ID BIGINT;
DECLARE VARIABLE V$PERSON_ID BIGINT;
DECLARE VARIABLE V$PERSON_NAME VARCHAR(1000);
begin

  -- I$SIDE - какую сторону отменяем (0 = участники, 1 = ППЭ)

  V$TIME = CURRENT_TIMESTAMP;
  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  SELECT USER_TYPE
  FROM USERS
  WHERE USER_ID = :I$USER_ID AND DATE_DEL IS NULL
  INTO :V$USER_TYPE;

  -- Текущий уровень базы ?
  SELECT K.KEY_VAL
  FROM KEYS K
  WHERE K.KEY_CODE = 'LEVEL'
  INTO :V$DB_LEVEL;
  V$DB_LEVEL = 3 - V$DB_LEVEL;

  -- Проверяем статус тестирования ?
  SELECT EXAM_STATE
  FROM UT_EXAM_DATES
  WHERE DATE_DEL IS NULL AND OBJ_ID = :I$EXAM_ID
  INTO :V$STATE;

  IF(V$STATE IS NULL) THEN EXCEPTION DATA_ERROR 'Тестирование не найдено или было удалено другим пользователем';
  IF(V$STATE >= 700) THEN EXCEPTION DATA_ERROR 'Нельзя выполнить резервирование участников тестирования на данной стадии';

  N = 0;
  N_ALL = 0;

  -- Отменяем распределение
  IF(I$SIDE = 0) THEN
  BEGIN
      -- Отменяем для участников
      IF(I$LEVEL = 0) THEN
      BEGIN
          -- Все участники данного ППЭ - снимаем вообще все распределения, в OBJ_ID должен быть передан ID ППЭ
          -- Предполагается что при назначении в конкретный ППЭ, место не может перескочить на чужой
          FOR
              SELECT PA.PERSON_ID
              FROM UT_PERSON_PPE_ASSN A
              JOIN UT_PERSON_PLACE_ASSN PA ON PA.EXAM_ID = A.EXAM_ID AND PA.DATE_DEL IS NULL AND PA.PERSON_ID = A.PERSON_ID
              WHERE A.EXAM_ID = :I$EXAM_ID AND A.DATE_DEL IS NULL AND A.PPE_ID = :I$PPE_ID
              INTO :V$OBJ_ID
          DO
          BEGIN
              N_ALL = N_ALL + 1;
              N = N + (SELECT DONE FROM UT_TEST_ASSN_PLC_REVERT_PERSON(:I$EXAM_ID, :V$OBJ_ID));
          END
      END
      ELSE IF(I$LEVEL = 1) THEN
      BEGIN
          -- Участники из конкретной ОУ
          FOR
              SELECT A.PERSON_ID
              FROM UT_PERSON_PLACE_ASSN A
              JOIN UT_PERSON_PPE_ASSN PPE ON PPE.DATE_DEL IS NULL AND PPE.EXAM_ID = A.EXAM_ID AND PPE.PERSON_ID = A.PERSON_ID AND PPE.PPE_ID = :I$PPE_ID
              JOIN LINKS LPG ON LPG.OBJ_ID = A.PERSON_ID AND LPG.PARENT_TYPE_ID IN (2, 84) AND LPG.PARENT_ID = :I$OBJ_ID AND LPG.DATE_DEL IS NULL
              WHERE A.EXAM_ID = :I$EXAM_ID AND A.DATE_DEL IS NULL
              UNION
              SELECT A.PERSON_ID
              FROM UT_PERSON_PLACE_ASSN A
              JOIN UT_PERSON_PPE_ASSN PPE ON PPE.DATE_DEL IS NULL AND PPE.EXAM_ID = A.EXAM_ID AND PPE.PERSON_ID = A.PERSON_ID AND PPE.PPE_ID = :I$PPE_ID
              JOIN LINKS LP9 ON LP9.OBJ_ID = A.PERSON_ID AND LP9.PARENT_TYPE_ID IN (9, 125, 187) AND LP9.DATE_DEL IS NULL
              JOIN LINKS LP8 ON LP8.OBJ_ID = LP9.PARENT_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
              JOIN LINKS LP7 ON LP7.OBJ_ID = LP8.PARENT_ID AND LP7.PARENT_TYPE_ID IN (7, 502) AND LP7.DATE_DEL IS NULL
              JOIN LINKS LP2 ON LP2.OBJ_ID = LP7.PARENT_ID AND LP2.PARENT_ID = :I$OBJ_ID AND LP2.DATE_DEL IS NULL
              WHERE A.EXAM_ID = :I$EXAM_ID AND A.DATE_DEL IS NULL
              INTO :V$OBJ_ID
          DO
          BEGIN
              N_ALL = N_ALL + 1;
              N = N + (SELECT DONE FROM UT_TEST_ASSN_PLC_REVERT_PERSON(:I$EXAM_ID, :V$OBJ_ID));
          END
      END
      ELSE IF(I$LEVEL = 2) THEN
      BEGIN
          -- Участники из конкретного коллектива
          FOR
              SELECT A.PERSON_ID
              FROM UT_PERSON_PLACE_ASSN A
              JOIN UT_PERSON_PPE_ASSN PPE ON PPE.DATE_DEL IS NULL AND PPE.EXAM_ID = A.EXAM_ID AND PPE.PERSON_ID = A.PERSON_ID AND PPE.PPE_ID = :I$PPE_ID
              JOIN LINKS LPG ON LPG.OBJ_ID = A.PERSON_ID AND LPG.PARENT_TYPE_ID IN (2, 81, 82, 83, 84, 9, 125, 187) AND LPG.PARENT_ID = :I$OBJ_ID AND LPG.DATE_DEL IS NULL
              WHERE A.EXAM_ID = :I$EXAM_ID AND A.DATE_DEL IS NULL
              INTO :V$OBJ_ID
          DO
          BEGIN
              N_ALL = N_ALL + 1;
              N = N + (SELECT DONE FROM UT_TEST_ASSN_PLC_REVERT_PERSON(:I$EXAM_ID, :V$OBJ_ID));
          END
      END
      ELSE IF(I$LEVEL = 3) THEN
      BEGIN
          -- Конкретный участник
          FOR
              SELECT A.PERSON_ID
              FROM UT_PERSON_PLACE_ASSN A
              JOIN UT_PERSON_PPE_ASSN PPE ON PPE.DATE_DEL IS NULL AND PPE.EXAM_ID = A.EXAM_ID AND PPE.PERSON_ID = A.PERSON_ID AND PPE.PPE_ID = :I$PPE_ID
              WHERE A.EXAM_ID = :I$EXAM_ID AND A.PERSON_ID = :I$OBJ_ID AND A.DATE_DEL IS NULL
              INTO :V$OBJ_ID
          DO
          BEGIN
              N_ALL = N_ALL + 1;
              N = N + (SELECT DONE FROM UT_TEST_ASSN_PLC_REVERT_PERSON(:I$EXAM_ID, :V$OBJ_ID));
          END
      END
      ELSE EXCEPTION DATA_ERROR 'Недопустимый уровень';
  END
  ELSE
  BEGIN
      IF(I$LEVEL = 0) THEN
      BEGIN
          -- Все участники данного ППЭ - снимаем вообще все распределения, в OBJ_ID должен быть передан ID ППЭ
          -- Предполагается что при назначении в конкретный ППЭ, место не может перескочить на чужой
          FOR
              SELECT PA.PERSON_ID
              FROM UT_PERSON_PPE_ASSN A
              JOIN UT_PERSON_PLACE_ASSN PA ON PA.EXAM_ID = A.EXAM_ID AND PA.DATE_DEL IS NULL AND PA.PERSON_ID = A.PERSON_ID
              WHERE A.EXAM_ID = :I$EXAM_ID AND A.DATE_DEL IS NULL AND A.PPE_ID = :I$PPE_ID
              INTO :V$OBJ_ID
          DO
          BEGIN
              N_ALL = N_ALL + 1;
              N = N + (SELECT DONE FROM UT_TEST_ASSN_PLC_REVERT_PERSON(:I$EXAM_ID, :V$OBJ_ID));
          END
      END
      ELSE IF(I$LEVEL = 1) THEN
      BEGIN
          -- Помещение
          FOR
              SELECT A.PERSON_ID
              FROM UT_PERSON_PLACE_ASSN A
              JOIN UT_PERSON_PPE_ASSN PPE ON PPE.DATE_DEL IS NULL AND PPE.EXAM_ID = A.EXAM_ID AND PPE.PERSON_ID = A.PERSON_ID AND PPE.PPE_ID = :I$PPE_ID
              JOIN UT_PPE_PLACES PP ON PP.OBJ_ID = A.PLACE_ID AND PP.ROOM_ID = :I$OBJ_ID AND PP.DATE_DEL IS NULL
              WHERE A.EXAM_ID = :I$EXAM_ID AND A.DATE_DEL IS NULL
              INTO :V$OBJ_ID
          DO
          BEGIN
              N_ALL = N_ALL + 1;
              N = N + (SELECT DONE FROM UT_TEST_ASSN_PLC_REVERT_PERSON(:I$EXAM_ID, :V$OBJ_ID));
          END
      END
      ELSE IF(I$LEVEL = 2) THEN
      BEGIN
          -- Конкретное место
          FOR
              SELECT A.PERSON_ID
              FROM UT_PERSON_PLACE_ASSN A
              JOIN UT_PERSON_PPE_ASSN PPE ON PPE.DATE_DEL IS NULL AND PPE.EXAM_ID = A.EXAM_ID AND PPE.PERSON_ID = A.PERSON_ID AND PPE.PPE_ID = :I$PPE_ID
              WHERE A.EXAM_ID = :I$EXAM_ID AND A.PLACE_ID = :I$OBJ_ID AND A.DATE_DEL IS NULL
              INTO :V$OBJ_ID
          DO
          BEGIN
              N_ALL = N_ALL + 1;
              N = N + (SELECT DONE FROM UT_TEST_ASSN_PLC_REVERT_PERSON(:I$EXAM_ID, :V$OBJ_ID));
          END
      END
      ELSE EXCEPTION DATA_ERROR 'Недопустимый уровень';
  END

  -- Итоги
  TAG_NAME = 'n_unassigned';
  VAL = N;
  SUSPEND;
  TAG_NAME = 'n_failed';
  VAL = N_ALL - N;
  SUSPEND;

  -- Статистика по дереву участников
  TAG_NAME = 'items';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'items::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
      SELECT C.OBJ_ID, C.OBJ_LEVEL, C.N_ASSN, C.N_FREE, C.PLACE_ID
      FROM UT_TEST_ASSN_PLACE_CHANGES(:I$EXAM_ID, :I$PPE_ID, :V$DB_LEVEL, :V$TIME, :V$DB_LEVEL) C
      INTO :V$OBJ_ID, :V$L, :V$N1, :V$N2, :V$PLACE_ID
  DO
  BEGIN
      TAG_NAME = 'items:p';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'items:p:level';
      VAL = V$L;
      SUSPEND;
      TAG_NAME = 'items:p:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'items:p:n_assn';
      VAL = V$N1;
      SUSPEND;
      TAG_NAME = 'items:p:n_free';
      VAL = V$N2;
      SUSPEND;
      IF(V$L = 3) THEN
      BEGIN
          TAG_NAME = 'items:p:place_id';
          VAL = V$PLACE_ID;
          SUSPEND;
          TAG_NAME = 'items:p:place_name';
          --VAL = V$PPE_NAME;
          SUSPEND;
      END
  END

  TAG_NAME = 'places';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'places::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
      SELECT C.OBJ_ID, C.OBJ_LEVEL, C.N_ASSN, C.N_FREE, C.N_TOTAL, C.PERSON_ID, C.PERSON_NAME
      FROM UT_TEST_ASSN_PLACE_RCHANGES(:I$EXAM_ID, :I$PPE_ID, 0, :V$TIME, :V$DB_LEVEL) C
      INTO :V$OBJ_ID, :V$L, :V$N1, :V$N2, :N, :V$PERSON_ID, :V$PERSON_NAME
  DO
  BEGIN
      TAG_NAME = 'places:p';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'places:p:level';
      VAL = V$L;
      SUSPEND;
      TAG_NAME = 'places:p:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'places:p:n_total';
      VAL = N;
      SUSPEND;
      TAG_NAME = 'places:p:n_assn';
      VAL = V$N1;
      SUSPEND;
      TAG_NAME = 'places:p:n_free';
      VAL = V$N2;
      SUSPEND;
      IF(V$PERSON_ID IS NOT NULL) THEN
      BEGIN
          TAG_NAME = 'places:p:person_id';
          VAL = V$PERSON_ID;
          SUSPEND;
          TAG_NAME = 'places:p:person_name';
          VAL = V$PERSON_NAME;
          SUSPEND;
      END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_ASSN_PLACE_RTREE (
    I$EXAM_ID BIGINT,
    I$PPE_ID BIGINT,
    I$LEVEL INTEGER,
    I$PARENT_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(8000))
AS
declare variable V$ID bigint;
declare variable V$NAME varchar(1000);
declare variable V$CODE varchar(100);
declare variable V$FLAGS integer;
declare variable V$ADDRESS varchar(1000);
declare variable V$AREA_NAME varchar(400);
declare variable V$ROLE_ID integer;
declare variable V$NUM varchar(20);
declare variable V$FLOOR integer;
declare variable V$R integer;
declare variable V$C integer;
declare variable V$CX float;
declare variable V$CY float;
declare variable V$CR float;
declare variable V$PERSON_ID bigint;
declare variable N1 integer;
declare variable N2 integer;
begin

  TAG_NAME = 'items';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'items::json&colon;array';
  VAL = '1';
  SUSPEND;

  IF(I$LEVEL IS NULL) THEN
  BEGIN
      -- Корень дерева - отдаем сам ППЭ и помещения в нем

      FOR
          SELECT D.NAME_SHORT, D.PPE_CODE, D.FLAGS, D.ADDRESS, D.AREA_NAME
          FROM UT_PPE P
          JOIN UT_EXAM_PPE_ASSN PA ON PA.DATE_DEL IS NULL AND PA.PPE_ID = :I$PPE_ID AND PA.EXAM_ID = :I$EXAM_ID
          LEFT JOIN UT_PPE_DESC(P.OBJ_ID) D ON 1 = 1
          WHERE P.OBJ_ID = :I$PPE_ID AND P.DATE_DEL IS NULL
          INTO :V$NAME, :V$CODE, :V$FLAGS, :V$ADDRESS, :V$AREA_NAME
      DO
      BEGIN

          -- Всего мест по помещениям
          SELECT COALESCE(SUM(R.N_PLACES), 0)
          FROM UT_EXAM_ROOM_ASSN RA
          JOIN UT_PPE_ROOMS R ON R.OBJ_ID = RA.ROOM_ID AND R.DATE_DEL IS NULL AND R.PPE_ID = :I$PPE_ID
          WHERE RA.EXAM_ID = :I$EXAM_ID AND RA.DATE_DEL IS NULL
          INTO :N1;

          -- Сколько участников рассажено
          SELECT COUNT(*)
          FROM UT_PERSON_PPE_ASSN PA
          JOIN UT_PERSON_PLACE_ASSN A ON A.DATE_DEL IS NULL AND A.EXAM_ID = :I$EXAM_ID AND A.PERSON_ID = PA.PERSON_ID
          WHERE PA.EXAM_ID = :I$EXAM_ID AND PA.PPE_ID = :I$PPE_ID AND PA.DATE_DEL IS NULL
          INTO :N2;

          TAG_NAME = 'items:p';
          VAL = NULL;
          SUSPEND;
          TAG_NAME = 'items:p:level';
          VAL = 0;
          SUSPEND;
          TAG_NAME = 'items:p:id';
          VAL = I$PPE_ID;
          SUSPEND;
          TAG_NAME = 'items:p:name';
          VAL = V$NAME;
          SUSPEND;
          TAG_NAME = 'items:p:ppe_code';
          VAL = V$CODE;
          SUSPEND;
          TAG_NAME = 'items:p:address';
          VAL = V$ADDRESS;
          SUSPEND;
          TAG_NAME = 'items:p:area_name';
          VAL = V$AREA_NAME;
          SUSPEND;
          TAG_NAME = 'items:p:flags';
          VAL = V$FLAGS;
          SUSPEND;

          TAG_NAME = 'items:p:n_places';
          VAL = N1;
          SUSPEND;

          TAG_NAME = 'items:p:n_assn';
          VAL = N2;
          SUSPEND;

          TAG_NAME = 'items:p:n_free';
          VAL = MAXVALUE(N1 - N2, 0);
          SUSPEND;

          -- Список помещений
          FOR
              SELECT R.OBJ_ID, RA.ROLE_ID, R.PPE_CODE, R.OBJ_NAME, R.ROOM_NUM, R.LOCATION, R.N_FLOOR, R.FLAGS, R.N_PLACES
              FROM UT_EXAM_ROOM_ASSN RA
              JOIN UT_PPE_ROOMS R ON R.OBJ_ID = RA.ROOM_ID AND R.DATE_DEL IS NULL AND R.PPE_ID = :I$PPE_ID
              WHERE RA.EXAM_ID = :I$EXAM_ID AND RA.DATE_DEL IS NULL
              ORDER BY 5, 4
              INTO :V$ID, :V$ROLE_ID, :V$CODE, :V$NAME, :V$NUM, :V$ADDRESS, :V$FLOOR, :V$FLAGS, :N1
          DO
          BEGIN

              -- Сколько участников рассажено в этом помещении
              SELECT COUNT(*)
              FROM UT_PPE_PLACES PP
              JOIN UT_PERSON_PLACE_ASSN A ON A.DATE_DEL IS NULL AND A.EXAM_ID = :I$EXAM_ID AND A.PLACE_ID = PP.OBJ_ID
              WHERE PP.DATE_DEL IS NULL AND PP.ROOM_ID = :V$ID
              INTO :N2;

              TAG_NAME = 'items:p';
              VAL = NULL;
              SUSPEND;
              TAG_NAME = 'items:p:level';
              VAL = 1;
              SUSPEND;
              TAG_NAME = 'items:p:id';
              VAL = V$ID;
              SUSPEND;
              TAG_NAME = 'items:p:name';
              VAL = V$NAME;
              SUSPEND;
              TAG_NAME = 'items:p:ppe_code';
              VAL = V$CODE;
              SUSPEND;
              TAG_NAME = 'items:p:location';
              VAL = V$ADDRESS;
              SUSPEND;
              TAG_NAME = 'items:p:num';
              VAL = V$NUM;
              SUSPEND;
              TAG_NAME = 'items:p:n_floor';
              VAL = V$FLOOR;
              SUSPEND;
              TAG_NAME = 'items:p:flags';
              VAL = V$FLAGS;
              SUSPEND;

              TAG_NAME = 'items:p:n_places';
              VAL = N1;
              SUSPEND;

              TAG_NAME = 'items:p:n_assn';
              VAL = N2;
              SUSPEND;

              TAG_NAME = 'items:p:n_free';
              VAL = MAXVALUE(N1 - N2, 0);
              SUSPEND;

          END

      END

  END
  ELSE IF(I$LEVEL = 1) THEN
  BEGIN

      -- Карта помещений в ППЭ (для ППЭ в целом выборка не предусмотрена)
      -- Сначала выдаем места списком, и вдогонку карту в xml
      FOR
          SELECT PS.OBJ_ID, PS.OBJ_NAME, PS.PLACE_NUM, PS.N_ROW, PS.N_COL, PS.FLAGS, PS.IS_DELETED, PS.COORD_X, PS.COORD_Y, PS.COORD_R,
              PA.PERSON_ID, C.NAME_FULL || ', ' || C.CLASS_NAME || ', ' || C.OU_NAME
          FROM UT_PPE_PLACES PS
          LEFT JOIN UT_PERSON_PLACE_ASSN PA ON PA.DATE_DEL IS NULL AND PA.EXAM_ID = :I$EXAM_ID AND PA.PLACE_ID = PS.OBJ_ID
          LEFT JOIN UT_PERSON_DESC(PA.PERSON_ID) C ON 1 = 1
          WHERE PS.ROOM_ID = :I$PARENT_ID AND PS.DATE_DEL IS NULL
          ORDER BY PS.PLACE_NUM
          INTO :V$ID, :V$NAME, :V$NUM, :V$R, :V$C, :V$FLAGS, :V$FLOOR, :V$CX, :V$CY, :V$CR, :V$PERSON_ID, :V$ADDRESS
      DO
      BEGIN

          TAG_NAME = 'items:p';
          VAL = NULL;
          SUSPEND;
          TAG_NAME = 'items:p:level';
          VAL = 2;
          SUSPEND;
          TAG_NAME = 'items:p:id';
          VAL = V$ID;
          SUSPEND;
          TAG_NAME = 'items:p:name';
          VAL = V$NAME;
          SUSPEND;
          TAG_NAME = 'items:p:num';
          VAL = V$NUM;
          SUSPEND;
          TAG_NAME = 'items:p:row';
          VAL = V$R;
          SUSPEND;
          TAG_NAME = 'items:p:col';
          VAL = V$C;
          SUSPEND;
          TAG_NAME = 'items:p:flags';
          VAL = V$FLAGS;
          SUSPEND;
          TAG_NAME = 'items:p:is_deleted';
          VAL = V$FLOOR;
          SUSPEND;
          TAG_NAME = 'items:p:cx';
          VAL = V$CX;
          SUSPEND;
          TAG_NAME = 'items:p:cy';
          VAL = V$CY;
          SUSPEND;
          TAG_NAME = 'items:p:cr';
          VAL = V$CR;
          SUSPEND;

          TAG_NAME = 'items:p:n_places';
          VAL = 1;
          SUSPEND;

          N2 = IIF(V$PERSON_ID IS NULL, 0, 1);
          TAG_NAME = 'items:p:n_assn';
          VAL = N2;
          SUSPEND;

          TAG_NAME = 'items:p:n_free';
          VAL = MAXVALUE(1 - N2, 0);
          SUSPEND;

          TAG_NAME = 'items:p:person_name';
          VAL = V$ADDRESS;
          SUSPEND;

      END

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_ASSN_PLC_REVERT_PERSON (
    I$EXAM_ID BIGINT,
    I$PERSON_ID BIGINT)
RETURNS (
    OLD_PLACE_ID BIGINT,
    DONE SMALLINT)
AS
declare variable V$ASSN_ID bigint;
declare variable V$PLACE_ASSN_ID bigint;
begin

  DONE = 0;

  -- Было ли назначение участника ? Если было, то снимаем - даже если в том же ППЭ
  SELECT FIRST 1 A.OBJ_ID, A.PLACE_ID
  FROM UT_PERSON_PLACE_ASSN A
  WHERE A.EXAM_ID = :I$EXAM_ID AND A.PERSON_ID = :I$PERSON_ID AND A.DATE_DEL IS NULL
  INTO :V$ASSN_ID, :OLD_PLACE_ID;

  IF(V$ASSN_ID IS NOT NULL) THEN
  BEGIN
      UPDATE UT_PERSON_PLACE_ASSN
      SET DATE_DEL = CURRENT_TIMESTAMP
      WHERE OBJ_ID = :V$ASSN_ID AND DATE_DEL IS NULL;

      DONE = 1;
  END

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_ASSN_PPE_APPLY (
    I$EXAM_ID BIGINT,
    I$LEVEL1 INTEGER,
    I$OBJ_ID1 BIGINT,
    I$LEVEL2 INTEGER,
    I$OBJ_ID2 BIGINT,
    I$USER_ID VARCHAR(40),
    I$FLAGS INTEGER = 0)
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(200))
AS
declare variable V$USER_TYPE smallint;
declare variable V$DB_LEVEL smallint;
declare variable V$TIME timestamp;
declare variable V$STATE integer;
declare variable N_OK integer;
declare variable N_FAIL integer;
declare variable V$N_MEMBERS integer;
declare variable V$PPE_ID bigint;
declare variable V$OBJ_ID bigint;
declare variable V$GROUP_ID bigint;
declare variable V$GROUP_FLAGS integer;
declare variable V$PPE_NAME varchar(1000);
declare variable V$L integer;
declare variable V$N1 integer;
declare variable V$N2 integer;
declare variable TMP integer;
begin

  -- FLAGS:
  -- биты 0+1: 0 = ОВ в ППЭ, 1 = класс в ППЭ, 2 или 3 куда бог пошлет
  -- биты 2+3: 0 = в свой район, 1 = в чужой район, 2 или 3 = куда бог пошлет
  V$GROUP_FLAGS = BIN_AND(I$FLAGS, 3);

  V$TIME = CURRENT_TIMESTAMP;
  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  SELECT USER_TYPE
  FROM USERS
  WHERE USER_ID = :I$USER_ID AND DATE_DEL IS NULL
  INTO :V$USER_TYPE;

  -- Если пользователь не является админом, директором или завучем - ошибка
  IF(V$USER_TYPE NOT IN (1, 4, 5, 6)) THEN EXCEPTION DATA_ERROR 'У данного пользователя нет доступа к назначению на тестирование';

  -- Текущий уровень базы ?
  SELECT K.KEY_VAL
  FROM KEYS K
  WHERE K.KEY_CODE = 'LEVEL'
  INTO :V$DB_LEVEL;
  V$DB_LEVEL = 3 - V$DB_LEVEL;

  -- Проверяем статус тестирования ?
  SELECT EXAM_STATE
  FROM UT_EXAM_DATES
  WHERE DATE_DEL IS NULL AND OBJ_ID = :I$EXAM_ID
  INTO :V$STATE;

  IF(V$STATE IS NULL) THEN EXCEPTION DATA_ERROR 'Тестирование не найдено или было удалено другим пользователем';
  IF(V$STATE > 600) THEN EXCEPTION DATA_ERROR 'Нельзя выполнить резервирование участников тестирования на данной стадии';

  N_OK = 0;
  N_FAIL = 0;

  -- Далее выполняем распределение
  IF(I$LEVEL1 = 4) THEN
  BEGIN

      -- Конечный участник тестирования. Если перетаскиваем на конкретный ППЭ, все равно распределяем даже если мест не осталось
      IF(I$LEVEL2 < 2) THEN
      BEGIN
          SELECT PPE_ID
          FROM UT_FIND_TEST_FREE_PPE(:I$EXAM_ID, :I$LEVEL1, :I$OBJ_ID1, :I$FLAGS)
          INTO :V$PPE_ID;
      END
      ELSE V$PPE_ID = I$OBJ_ID2;

      IF(V$PPE_ID IS NULL) THEN N_FAIL = N_FAIL + 1;
      ELSE
      BEGIN
          N_OK = N_OK + 1;

          SELECT FIRST 1 1
          FROM UT_TEST_ASSN_PPE_APPLY_PERSON(:I$EXAM_ID, :I$OBJ_ID1, :V$PPE_ID)
          INTO :TMP;
      END

  END
  ELSE
  BEGIN

      -- В остальных случаях идем по учебным коллективам, где осталось кого распределять
      FOR
          SELECT OBJ_ID, N_MEMBERS
          FROM UT_LEVEL_GROUP_UA_LIST(:I$EXAM_ID, :I$OBJ_ID1, :I$LEVEL1)
          INTO :V$GROUP_ID, :V$N_MEMBERS
      DO
      BEGIN

          IF(V$GROUP_FLAGS >= 2) THEN
          BEGIN
              -- Если алгоритм не ограничивает разбиение групп, то распределяем индивидуально
              FOR
                  SELECT LP.OBJ_ID
                  FROM LINKS LP
                  JOIN UT_EXAM_PERSON_ASSN A ON A.EXAM_ID = :I$EXAM_ID AND A.PERSON_ID = LP.OBJ_ID AND A.DATE_DEL IS NULL
                  LEFT JOIN UT_PERSON_PPE_ASSN PA ON PA.EXAM_ID = :I$EXAM_ID AND PA.PERSON_ID = LP.OBJ_ID AND PA.DATE_DEL IS NULL
                  WHERE LP.PARENT_ID = :V$GROUP_ID AND LP.OBJ_TYPE_ID IN (10, 14, 126) AND LP.DATE_DEL IS NULL AND PA.OBJ_ID IS NULL
                  INTO :V$OBJ_ID
              DO
              BEGIN
                  SELECT PPE_ID
                  FROM UT_FIND_TEST_FREE_PPE(:I$EXAM_ID, 4, :V$OBJ_ID, :I$FLAGS, IIF(:I$LEVEL2 = 2, :I$OBJ_ID2, NULL))
                  INTO :V$PPE_ID;

                  IF(V$PPE_ID IS NULL) THEN N_FAIL = N_FAIL + 1;
                  ELSE
                  BEGIN
                      N_OK = N_OK + 1;

                      SELECT FIRST 1 1
                      FROM UT_TEST_ASSN_PPE_APPLY_PERSON(:I$EXAM_ID, :V$OBJ_ID, :V$PPE_ID)
                      INTO :TMP;
                  END
              END
          END
          ELSE
          BEGIN
              -- Если алгоритм ограничивает группы, то распределяем группами
              SELECT PPE_ID
              FROM UT_FIND_TEST_FREE_PPE(:I$EXAM_ID, 3, :V$GROUP_ID, :I$FLAGS, IIF(:I$LEVEL2 = 2, :I$OBJ_ID2, NULL))
              INTO :V$PPE_ID;

              IF(V$PPE_ID IS NULL) THEN N_FAIL = N_FAIL + V$N_MEMBERS;
              ELSE
              BEGIN
                  FOR
                      SELECT LP.OBJ_ID
                      FROM LINKS LP
                      JOIN UT_EXAM_PERSON_ASSN A ON A.EXAM_ID = :I$EXAM_ID AND A.PERSON_ID = LP.OBJ_ID AND A.DATE_DEL IS NULL
                      LEFT JOIN UT_PERSON_PPE_ASSN PA ON PA.EXAM_ID = :I$EXAM_ID AND PA.PERSON_ID = LP.OBJ_ID AND PA.DATE_DEL IS NULL
                      WHERE LP.PARENT_ID = :V$GROUP_ID AND LP.OBJ_TYPE_ID IN (10, 14, 126) AND LP.DATE_DEL IS NULL AND PA.OBJ_ID IS NULL
                      INTO :V$OBJ_ID
                  DO
                  BEGIN
                      N_OK = N_OK + 1;

                      SELECT FIRST 1 1
                      FROM UT_TEST_ASSN_PPE_APPLY_PERSON(:I$EXAM_ID, :V$OBJ_ID, :V$PPE_ID)
                      INTO :TMP;
                  END
              END
          END

      END

  END

  -- Статистика по дереву участников
  TAG_NAME = 'items';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'items::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
      SELECT C.OBJ_ID, C.OBJ_LEVEL, C.N_ASSN, C.N_FREE, C.PPE_ID, D.NAME_SHORT
      FROM UT_TEST_ASSN_PPE_CHANGES(:I$EXAM_ID, :I$LEVEL1, :V$TIME, :V$DB_LEVEL) C
      LEFT JOIN UT_PPE_DESC(C.PPE_ID) D ON 1 = 1
      INTO :V$OBJ_ID, :V$L, :V$N1, :V$N2, :V$PPE_ID, :V$PPE_NAME
  DO
  BEGIN
      TAG_NAME = 'items:p';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'items:p:level';
      VAL = V$L;
      SUSPEND;
      TAG_NAME = 'items:p:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'items:p:n_assn';
      VAL = V$N1;
      SUSPEND;
      TAG_NAME = 'items:p:n_free';
      VAL = V$N2;
      SUSPEND;
      IF(V$L = 4) THEN
      BEGIN
          TAG_NAME = 'items:p:ppe_id';
          VAL = V$PPE_ID;
          SUSPEND;
          TAG_NAME = 'items:p:ppe_name';
          VAL = V$PPE_NAME;
          SUSPEND;
      END
  END

  -- Статистика по ППЭ
  TAG_NAME = 'ppe';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'ppe::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
      SELECT C.OBJ_ID, C.OBJ_LEVEL, C.N_ASSN, C.N_FREE, C.N_TOTAL
      FROM UT_TEST_ASSN_PPE_RCHANGES(:I$EXAM_ID, :I$LEVEL2, :V$TIME, :V$DB_LEVEL) C
      INTO :V$OBJ_ID, :V$L, :V$N1, :V$N2, :TMP
  DO
  BEGIN
      TAG_NAME = 'ppe:p';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'ppe:p:level';
      VAL = V$L;
      SUSPEND;
      TAG_NAME = 'ppe:p:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'ppe:p:n_total';
      VAL = TMP;
      SUSPEND;
      TAG_NAME = 'ppe:p:n_assn';
      VAL = V$N1;
      SUSPEND;
      TAG_NAME = 'ppe:p:n_free';
      VAL = V$N2;
      SUSPEND;
  END

  -- Итоги
  TAG_NAME = 'n_assigned';
  VAL = N_OK;
  SUSPEND;
  TAG_NAME = 'n_failed';
  VAL = N_FAIL;
  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_ASSN_PPE_APPLY_PERSON (
    I$EXAM_ID BIGINT,
    I$PERSON_ID BIGINT,
    I$PPE_ID BIGINT)
RETURNS (
    ASSN_ID BIGINT,
    PPE_ID BIGINT,
    OLD_PPE_ID BIGINT)
AS
DECLARE VARIABLE V$ASSN_ID BIGINT;
begin

  -- Было ли назначение участника ? Если было, то снимаем - даже если в том же ППЭ
  SELECT FIRST 1 A.OBJ_ID, A.PPE_ID
  FROM UT_PERSON_PPE_ASSN A
  WHERE A.EXAM_ID = :I$EXAM_ID AND A.PERSON_ID = :I$PERSON_ID AND A.DATE_DEL IS NULL
  INTO :V$ASSN_ID, :OLD_PPE_ID;

  IF(V$ASSN_ID IS NOT NULL) THEN
  BEGIN
    -- Если ППЭ изменяется, проверяем закрепление рассадки участника в старом ППЭ !!!

    UPDATE UT_PERSON_PPE_ASSN
    SET DATE_DEL = CURRENT_TIMESTAMP
    WHERE OBJ_ID = :V$ASSN_ID AND DATE_DEL IS NULL;
  END

  INSERT INTO UT_PERSON_PPE_ASSN
  (EXAM_ID, PERSON_ID, PPE_ID)
  VALUES (:I$EXAM_ID, :I$PERSON_ID, :I$PPE_ID)
  RETURNING OBJ_ID INTO :ASSN_ID;

  PPE_ID = I$PPE_ID;

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_ASSN_PPE_CHANGES (
    I$EXAM_ID BIGINT,
    I$LEVEL INTEGER,
    I$TIME TIMESTAMP,
    I$USER_LEVEL SMALLINT)
RETURNS (
    OBJ_ID BIGINT,
    OBJ_LEVEL INTEGER,
    N_ASSN INTEGER,
    N_FREE INTEGER,
    PPE_ID BIGINT)
AS
begin

  -- Уровень участников - выдаем только если распределяли уровень 3 или 4 (группы или индивидуально)
  OBJ_LEVEL = 4;
  FOR
      SELECT DISTINCT A.PERSON_ID
      FROM UT_PERSON_PPE_ASSN A
      WHERE A.DATE_MODIFY >= :I$TIME AND A.EXAM_ID = :I$EXAM_ID AND :I$LEVEL >= 3
      INTO :OBJ_ID
  DO
  BEGIN
      PPE_ID = NULL;
      SELECT FIRST 1 A.PPE_ID
      FROM UT_PERSON_PPE_ASSN A
      WHERE A.EXAM_ID = :I$EXAM_ID AND A.PERSON_ID = :OBJ_ID AND A.DATE_DEL IS NULL
      INTO :PPE_ID;

      N_ASSN = IIF(PPE_ID IS NULL, 0, 1);
      N_FREE = IIF(PPE_ID IS NULL, 1, 0);
      SUSPEND;
  END
  PPE_ID = NULL;

  -- Группы - только если распределяли уровень 2+ (ОУ и ниже)
  OBJ_LEVEL = 3;
  FOR
      SELECT DISTINCT LPG.PARENT_ID
      FROM UT_PERSON_PPE_ASSN A
      JOIN LINKS LPG ON LPG.OBJ_ID = A.PERSON_ID AND LPG.PARENT_TYPE_ID IN (2, 9, 125, 187) AND LPG.DATE_DEL IS NULL
      WHERE A.DATE_MODIFY >= :I$TIME AND A.EXAM_ID = :I$EXAM_ID AND :I$LEVEL >= 2
      INTO :OBJ_ID
  DO
  BEGIN
      SELECT COUNT(*)
      FROM LINKS LS
      JOIN UT_PERSON_PPE_ASSN A ON A.EXAM_ID = :I$EXAM_ID AND A.PERSON_ID = LS.OBJ_ID AND A.DATE_DEL IS NULL
      WHERE LS.PARENT_ID = :OBJ_ID AND LS.OBJ_TYPE_ID IN (10, 14, 126) AND LS.DATE_DEL IS NULL
      INTO :N_ASSN;
      SELECT COUNT(*)
      FROM LINKS LS
      JOIN UT_EXAM_PERSON_ASSN PA ON PA.DATE_DEL IS NULL AND PA.EXAM_ID = :I$EXAM_ID AND PA.PERSON_ID = LS.OBJ_ID
      LEFT JOIN UT_PERSON_PPE_ASSN A ON A.EXAM_ID = :I$EXAM_ID AND A.PERSON_ID = LS.OBJ_ID AND A.DATE_DEL IS NULL
      WHERE LS.PARENT_ID = :OBJ_ID AND LS.OBJ_TYPE_ID IN (10, 14, 126) AND LS.DATE_DEL IS NULL AND A.OBJ_ID IS NULL
      INTO :N_FREE;

      SUSPEND;
  END

  -- ОУ, выдаем изменения всегда
  OBJ_LEVEL = 2;
  FOR
      SELECT DISTINCT LPG.PARENT_ID
      FROM UT_PERSON_PPE_ASSN A
      JOIN LINKS LPG ON LPG.OBJ_ID = A.PERSON_ID AND LPG.PARENT_TYPE_ID = 2 AND LPG.DATE_DEL IS NULL
      WHERE A.DATE_MODIFY >= :I$TIME AND A.EXAM_ID = :I$EXAM_ID
      UNION
      SELECT DISTINCT LP2.PARENT_ID
      FROM UT_PERSON_PPE_ASSN A
      JOIN LINKS LPG ON LPG.OBJ_ID = A.PERSON_ID AND LPG.PARENT_TYPE_ID IN (9, 125, 187) AND LPG.DATE_DEL IS NULL
      JOIN LINKS LP8 ON LP8.OBJ_ID = LPG.PARENT_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
      JOIN LINKS LP7 ON LP7.OBJ_ID = LP8.PARENT_ID AND LP7.PARENT_TYPE_ID IN (7, 502) AND LP7.DATE_DEL IS NULL
      JOIN LINKS LP2 ON LP2.OBJ_ID = LP7.PARENT_ID AND LP2.PARENT_TYPE_ID = 2 AND LP2.DATE_DEL IS NULL
      WHERE A.DATE_MODIFY >= :I$TIME AND A.EXAM_ID = :I$EXAM_ID
      INTO :OBJ_ID
  DO
  BEGIN
      SELECT COUNT(*)
      FROM (
          SELECT L14.OBJ_ID
          FROM LINKS L14
          JOIN UT_PERSON_PPE_ASSN A ON A.EXAM_ID = :I$EXAM_ID AND A.PERSON_ID = L14.OBJ_ID AND A.DATE_DEL IS NULL
          WHERE L14.PARENT_ID = :OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
          UNION
          SELECT L10.OBJ_ID
          FROM LINKS L7
          JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
          JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 125, 187) AND L9.DATE_DEL IS NULL
          JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID IN (10, 126) AND L10.DATE_DEL IS NULL
          JOIN UT_PERSON_PPE_ASSN A ON A.EXAM_ID = :I$EXAM_ID AND A.PERSON_ID = L10.OBJ_ID AND A.DATE_DEL IS NULL
          WHERE L7.PARENT_ID = :OBJ_ID AND L7.OBJ_TYPE_ID IN (7, 502) AND L7.DATE_DEL IS NULL
      )
      INTO :N_ASSN;
      SELECT COUNT(*)
      FROM (
          SELECT L14.OBJ_ID
          FROM LINKS L14
          JOIN UT_EXAM_PERSON_ASSN PA ON PA.DATE_DEL IS NULL AND PA.EXAM_ID = :I$EXAM_ID AND PA.PERSON_ID = L14.OBJ_ID
          LEFT JOIN UT_PERSON_PPE_ASSN A ON A.EXAM_ID = :I$EXAM_ID AND A.PERSON_ID = L14.OBJ_ID AND A.DATE_DEL IS NULL
          WHERE L14.PARENT_ID = :OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL AND A.OBJ_ID IS NULL
          UNION
          SELECT L10.OBJ_ID
          FROM LINKS L7
          JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
          JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 125, 187) AND L9.DATE_DEL IS NULL
          JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID IN (10, 126) AND L10.DATE_DEL IS NULL
          JOIN UT_EXAM_PERSON_ASSN PA ON PA.DATE_DEL IS NULL AND PA.EXAM_ID = :I$EXAM_ID AND PA.PERSON_ID = L10.OBJ_ID
          LEFT JOIN UT_PERSON_PPE_ASSN A ON A.EXAM_ID = :I$EXAM_ID AND A.PERSON_ID = L10.OBJ_ID AND A.DATE_DEL IS NULL
          WHERE L7.PARENT_ID = :OBJ_ID AND L7.OBJ_TYPE_ID IN (7, 502) AND L7.DATE_DEL IS NULL AND A.OBJ_ID IS NULL
      )
      INTO :N_FREE;

      SUSPEND;
  END

  -- Районы

  -- Регион

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_ASSN_PPE_LTREE (
    I$EXAM_ID BIGINT,
    I$LEVEL INTEGER,
    I$PARENT_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$USER_TYPE SMALLINT;
DECLARE VARIABLE V$DB_LEVEL SMALLINT;
DECLARE VARIABLE V$ID BIGINT;
DECLARE VARIABLE V$TYPE BIGINT;
DECLARE VARIABLE V$NAME VARCHAR(1000);
DECLARE VARIABLE V$ORDER DOUBLE PRECISION;
DECLARE VARIABLE N1 INTEGER;
DECLARE VARIABLE N2 INTEGER;
DECLARE VARIABLE V$PPE_ID BIGINT;
DECLARE VARIABLE V$PPE_NAME VARCHAR(1000);
begin

  -- Идентифицируем роль пользователя
  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  SELECT USER_TYPE
  FROM USERS
  WHERE USER_ID = :I$USER_ID AND DATE_DEL IS NULL
  INTO :V$USER_TYPE;

  -- Если пользователь не является админом, директором или завучем - ошибка
  IF(V$USER_TYPE NOT IN (1, 4, 5, 6)) THEN EXCEPTION DATA_ERROR 'У данного пользователя нет доступа к назначению на тестирование';

  -- Текущий уровень базы ?
  SELECT K.KEY_VAL
  FROM KEYS K
  WHERE K.KEY_CODE = 'LEVEL'
  INTO :V$DB_LEVEL;

  -- Запрошен корень дерева
  IF(I$LEVEL IS NULL OR I$PARENT_ID IS NULL) THEN
  BEGIN

      -- Уровень пользователя (0 = регион ... 2 = ОУ), в корне дерева выбираем на 1 уровень меньше уровня пользователя
      TAG_NAME = 'level';
      IF(V$USER_TYPE = 8) THEN I$LEVEL = 3; ELSE I$LEVEL = 3 - V$DB_LEVEL;
      VAL = I$LEVEL;
      I$LEVEL = I$LEVEL - 1;
      SUSPEND;

      -- Идентифицируем корневой объект пользователя
      IF(I$LEVEL = -1) THEN
          I$PARENT_ID = NULL;
      ELSE IF(I$LEVEL = 0) THEN
          I$PARENT_ID = (SELECT FIRST 1 OBJ_ID FROM LINKS WHERE (PARENT_ID IS NULL OR PARENT_TYPE_ID = 112) AND OBJ_TYPE_ID = 111 AND DATE_DEL IS NULL);
      ELSE IF(I$LEVEL >= 1) THEN
          I$PARENT_ID = (SELECT FIRST 1 OBJ_ID FROM LINKS WHERE (PARENT_ID IS NULL OR PARENT_TYPE_ID IN (111, 112)) AND OBJ_TYPE_ID = 2 AND DATE_DEL IS NULL);

      TAG_NAME = 'readonly';
      VAL = '0'; -- !!!
      SUSPEND;

  END
  ELSE IF(I$LEVEL < (3 - V$DB_LEVEL)) THEN EXCEPTION DATA_ERROR 'Нельзя запросить уровень выше текущего';

  TAG_NAME = 'items';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'items::json&colon;array';
  VAL = '1';
  SUSPEND;

  IF(I$LEVEL = -1) THEN
  BEGIN
      -- Уровень региона
      FOR
          SELECT L.OBJ_ID, C.CAPTION, L.OBJ_TYPE_ID
          FROM LINKS L
          LEFT JOIN OBJECT_CAPTION_GET(L.OBJ_ID) C ON 1 = 1
          WHERE L.PARENT_ID IS NULL AND L.OBJ_TYPE_ID = 112 AND L.DATE_DEL IS NULL
          ORDER BY 2
          INTO :V$ID, :V$NAME, :V$TYPE
      DO
      BEGIN
          TAG_NAME = 'items:p';
          VAL = NULL;
          SUSPEND;
          TAG_NAME = 'items:p:id';
          VAL = V$ID;
          SUSPEND;
          TAG_NAME = 'items:p:name';
          VAL = V$NAME;
          SUSPEND;
          TAG_NAME = 'items:p:type';
          VAL = V$TYPE;
          SUSPEND;
          TAG_NAME = 'items:p:level';
          VAL = 0;
          SUSPEND;
          TAG_NAME = 'items:p:has_children';
          IF(EXISTS(SELECT FIRST 1 1 FROM LINKS WHERE PARENT_ID = :V$ID AND OBJ_TYPE_ID IN (2, 111) AND DATE_DEL IS NULL)) THEN VAL = 1; ELSE VAL = 0;
          SUSPEND;

          SELECT COUNT(*)
          FROM LINKS L10
          JOIN UT_EXAM_PERSON_ASSN PA ON PA.PERSON_ID = L10.OBJ_ID AND PA.EXAM_ID = :I$EXAM_ID AND PA.DATE_DEL IS NULL
          WHERE L10.PARENT_ID = :V$ID AND L10.OBJ_TYPE_ID IN (10, 14) AND L10.DATE_DEL IS NULL
          INTO :N1;

          SELECT COUNT(*)
          FROM LINKS L10
          LEFT JOIN UT_EXAM_PERSON_ASSN PA ON PA.PERSON_ID = L10.OBJ_ID AND PA.EXAM_ID = :I$EXAM_ID AND PA.DATE_DEL IS NULL
          WHERE L10.PARENT_ID = :V$ID AND L10.OBJ_TYPE_ID IN (10, 14) AND L10.DATE_DEL IS NULL AND PA.OBJ_ID IS NULL
          INTO :N2;

          TAG_NAME = 'items:p:n_assn';
          VAL = N1 - N2;
          SUSPEND;

          TAG_NAME = 'items:p:n_free';
          VAL = N2;
          SUSPEND;

      END
  END
  ELSE IF(I$LEVEL = 0) THEN
  BEGIN
      -- Список районов или ОУ ?
      FOR
          SELECT L.OBJ_ID, C.CAPTION, L.OBJ_TYPE_ID
          FROM LINKS L
          LEFT JOIN OBJECT_CAPTION_GET(L.OBJ_ID) C ON 1 = 1
          WHERE (L.PARENT_ID = :I$PARENT_ID OR L.PARENT_ID IS NULL) AND L.OBJ_TYPE_ID IN (111, 2) AND L.DATE_DEL IS NULL
          ORDER BY 2
          INTO :V$ID, :V$NAME, :V$TYPE
      DO
      BEGIN
          TAG_NAME = 'items:p';
          VAL = NULL;
          SUSPEND;
          TAG_NAME = 'items:p:id';
          VAL = V$ID;
          SUSPEND;
          TAG_NAME = 'items:p:name';
          VAL = V$NAME;
          SUSPEND;
          TAG_NAME = 'items:p:type';
          VAL = V$TYPE;
          SUSPEND;
          TAG_NAME = 'items:p:level';
          IF(V$TYPE = 111) THEN VAL = 1; ELSE VAL = 2;
          SUSPEND;

          IF(V$TYPE = 2) THEN
          BEGIN
              SELECT COUNT(*)
              FROM (
                  SELECT L10.OBJ_ID
                  FROM LINKS L7
                  JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
                  JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 125, 187) AND L9.DATE_DEL IS NULL
                  JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID IN (10, 14) AND L10.DATE_DEL IS NULL
                  JOIN UT_EXAM_PERSON_ASSN PA ON PA.PERSON_ID = L10.OBJ_ID AND PA.EXAM_ID = :I$EXAM_ID AND PA.DATE_DEL IS NULL
                  WHERE L7.PARENT_ID = :V$ID AND L7.OBJ_TYPE_ID IN (7, 502) AND L7.DATE_DEL IS NULL
                  UNION
                  SELECT L14.OBJ_ID
                  FROM LINKS L14
                  WHERE L14.PARENT_ID = :V$ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
              )
              INTO :N1;

              SELECT COUNT(*)
              FROM (
                  SELECT L10.OBJ_ID
                  FROM LINKS L7
                  JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
                  JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 125, 187) AND L9.DATE_DEL IS NULL
                  JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID IN (10, 14) AND L10.DATE_DEL IS NULL
                  JOIN UT_EXAM_PERSON_ASSN PA ON PA.PERSON_ID = L10.OBJ_ID AND PA.EXAM_ID = :I$EXAM_ID AND PA.DATE_DEL IS NULL
                  LEFT JOIN UT_PERSON_PPE_ASSN A ON A.PERSON_ID = L10.OBJ_ID AND A.EXAM_ID = :I$EXAM_ID AND A.DATE_DEL IS NULL
                  WHERE L7.PARENT_ID = :V$ID AND L7.OBJ_TYPE_ID IN (7, 502) AND L7.DATE_DEL IS NULL AND A.OBJ_ID IS NULL
                  UNION
                  SELECT L14.OBJ_ID
                  FROM LINKS L14
                  JOIN UT_EXAM_PERSON_ASSN PA ON PA.PERSON_ID = L14.OBJ_ID AND PA.EXAM_ID = :I$EXAM_ID AND PA.DATE_DEL IS NULL
                  LEFT JOIN UT_PERSON_PPE_ASSN A ON A.PERSON_ID = L14.OBJ_ID AND A.EXAM_ID = :I$EXAM_ID AND A.DATE_DEL IS NULL
                  WHERE L14.PARENT_ID = :V$ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL AND A.OBJ_ID IS NULL
              )
              INTO :N2;

              TAG_NAME = 'items:p:has_children';
              IF(N1 > 0) THEN VAL = 1; ELSE VAL = 0;
              SUSPEND;

          END
          ELSE
          BEGIN
              SELECT COUNT(*)
              FROM (
                  SELECT L10.OBJ_ID
                  FROM LINKS L2
                  JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID IN (7, 502) AND L7.DATE_DEL IS NULL
                  JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
                  JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 125, 187) AND L9.DATE_DEL IS NULL
                  JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID IN (10, 14) AND L10.DATE_DEL IS NULL
                  JOIN UT_EXAM_PERSON_ASSN PA ON PA.PERSON_ID = L10.OBJ_ID AND PA.EXAM_ID = :I$EXAM_ID AND PA.DATE_DEL IS NULL
                  WHERE L2.PARENT_ID = :V$ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
                  UNION
                  SELECT L14.OBJ_ID
                  FROM LINKS L2
                  JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
                  WHERE L2.PARENT_ID = :V$ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
              )
              INTO :N1;

              SELECT COUNT(*)
              FROM (
                  SELECT L10.OBJ_ID
                  FROM LINKS L2
                  JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID IN (7, 502) AND L7.DATE_DEL IS NULL
                  JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
                  JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 125, 187) AND L9.DATE_DEL IS NULL
                  JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID IN (10, 14) AND L10.DATE_DEL IS NULL
                  JOIN UT_EXAM_PERSON_ASSN PA ON PA.PERSON_ID = L10.OBJ_ID AND PA.EXAM_ID = :I$EXAM_ID AND PA.DATE_DEL IS NULL
                  LEFT JOIN UT_PERSON_PPE_ASSN A ON A.PERSON_ID = L10.OBJ_ID AND A.EXAM_ID = :I$EXAM_ID AND A.DATE_DEL IS NULL
                  WHERE L2.PARENT_ID = :V$ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND A.OBJ_ID IS NULL
                  UNION
                  SELECT L14.OBJ_ID
                  FROM LINKS L2
                  JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
                  JOIN UT_EXAM_PERSON_ASSN PA ON PA.PERSON_ID = L14.OBJ_ID AND PA.EXAM_ID = :I$EXAM_ID AND PA.DATE_DEL IS NULL
                  LEFT JOIN UT_PERSON_PPE_ASSN A ON A.PERSON_ID = L14.OBJ_ID AND A.EXAM_ID = :I$EXAM_ID AND A.DATE_DEL IS NULL
                  WHERE L2.PARENT_ID = :V$ID AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND A.OBJ_ID IS NULL
              )
              INTO :N2;

              TAG_NAME = 'items:p:has_children';
              IF(EXISTS(SELECT FIRST 1 1 FROM LINKS WHERE PARENT_ID = :V$ID AND OBJ_TYPE_ID IN (111, 2) AND DATE_DEL IS NULL)) THEN VAL = 1; ELSE VAL = 0;
              SUSPEND;
          END

          TAG_NAME = 'items:p:n_assn';
          VAL = N1 - N2;
          SUSPEND;

          TAG_NAME = 'items:p:n_free';
          VAL = N2;
          SUSPEND;

      END
  END
  ELSE IF(I$LEVEL = 1) THEN
  BEGIN
      -- Список ОУ
      FOR
          SELECT L.OBJ_ID, C.CAPTION, L.OBJ_TYPE_ID
          FROM LINKS L
          LEFT JOIN OBJECT_CAPTION_GET(L.OBJ_ID) C ON 1 = 1
          WHERE (L.PARENT_ID = :I$PARENT_ID OR L.PARENT_ID IS NULL) AND L.OBJ_TYPE_ID = 2 AND L.DATE_DEL IS NULL
          ORDER BY 2
          INTO :V$ID, :V$NAME, :V$TYPE
      DO
      BEGIN
          TAG_NAME = 'items:p';
          VAL = NULL;
          SUSPEND;
          TAG_NAME = 'items:p:id';
          VAL = V$ID;
          SUSPEND;
          TAG_NAME = 'items:p:name';
          VAL = V$NAME;
          SUSPEND;
          TAG_NAME = 'items:p:type';
          VAL = V$TYPE;
          SUSPEND;
          TAG_NAME = 'items:p:level';
          IF(V$TYPE = 111) THEN VAL = 1; ELSE VAL = 2;
          SUSPEND;

          SELECT COUNT(*)
          FROM (
              SELECT L10.OBJ_ID
              FROM LINKS L7
              JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
              JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 125, 187) AND L9.DATE_DEL IS NULL
              JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID IN (10, 14) AND L10.DATE_DEL IS NULL
              JOIN UT_EXAM_PERSON_ASSN PA ON PA.PERSON_ID = L10.OBJ_ID AND PA.EXAM_ID = :I$EXAM_ID AND PA.DATE_DEL IS NULL
              WHERE L7.PARENT_ID = :V$ID AND L7.OBJ_TYPE_ID IN (7, 502) AND L7.DATE_DEL IS NULL
              UNION
              SELECT L14.OBJ_ID
              FROM LINKS L14
              JOIN UT_EXAM_PERSON_ASSN PA ON PA.PERSON_ID = L14.OBJ_ID AND PA.EXAM_ID = :I$EXAM_ID AND PA.DATE_DEL IS NULL
              WHERE L14.PARENT_ID = :V$ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
          )
          INTO :N1;

          SELECT COUNT(*)
          FROM (
              SELECT L10.OBJ_ID
              FROM LINKS L7
              JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
              JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 125, 187) AND L9.DATE_DEL IS NULL
              JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID IN (10, 14) AND L10.DATE_DEL IS NULL
              JOIN UT_EXAM_PERSON_ASSN PA ON PA.PERSON_ID = L10.OBJ_ID AND PA.EXAM_ID = :I$EXAM_ID AND PA.DATE_DEL IS NULL
              LEFT JOIN UT_PERSON_PPE_ASSN A ON A.PERSON_ID = L10.OBJ_ID AND A.EXAM_ID = :I$EXAM_ID AND A.DATE_DEL IS NULL
              WHERE L7.PARENT_ID = :V$ID AND L7.OBJ_TYPE_ID IN (7, 502) AND L7.DATE_DEL IS NULL AND A.OBJ_ID IS NULL
              UNION
              SELECT L14.OBJ_ID
              FROM LINKS L14
              JOIN UT_EXAM_PERSON_ASSN PA ON PA.PERSON_ID = L14.OBJ_ID AND PA.EXAM_ID = :I$EXAM_ID AND PA.DATE_DEL IS NULL
              LEFT JOIN UT_PERSON_PPE_ASSN A ON A.PERSON_ID = L14.OBJ_ID AND A.EXAM_ID = :I$EXAM_ID AND A.DATE_DEL IS NULL
              WHERE L14.PARENT_ID = :V$ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL AND A.OBJ_ID IS NULL
          )
          INTO :N2;

          TAG_NAME = 'items:p:has_children';
          IF(N1 > 0) THEN VAL = 1; ELSE VAL = 0;
          SUSPEND;

          TAG_NAME = 'items:p:n_assn';
          VAL = N1 - N2;
          SUSPEND;

          TAG_NAME = 'items:p:n_free';
          VAL = N2;
          SUSPEND;
      END
  END
  ELSE IF(I$LEVEL = 2) THEN
  BEGIN
      -- Список классов - только там где есть назначенные на тестирования текущего года
      FOR
          SELECT L9.OBJ_ID, C.CAPTION, L9.OBJ_TYPE_ID, LV49.SORT_ORDER
          FROM LINKS L7
          JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
          JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
          JOIN LISTVALS LV49 ON LV49.LISTVAL_ID = V49.LISTVAL_ID
          JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 125, 187) AND L9.DATE_DEL IS NULL
          LEFT JOIN VALR V53 ON V53.OBJ_ID = L9.OBJ_ID AND V53.PARAM_ID = 53 AND V53.IS_DEL = 0
          LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C ON 1 = 1
          WHERE L7.PARENT_ID = :I$PARENT_ID AND L7.OBJ_TYPE_ID IN (7, 502) AND L7.DATE_DEL IS NULL
          UNION
          SELECT :I$PARENT_ID, 'Сотрудники', 14, -1
          FROM RDB$DATABASE
          WHERE :V$USER_TYPE <> 8
          ORDER BY 4
          INTO :V$ID, :V$NAME, :V$TYPE, :V$ORDER
      DO
      BEGIN
          -- Всего зачислено на тестирование
          SELECT COUNT(*)
          FROM LINKS L10
          JOIN UT_EXAM_PERSON_ASSN PA ON PA.PERSON_ID = L10.OBJ_ID AND PA.EXAM_ID = :I$EXAM_ID AND PA.DATE_DEL IS NULL
          WHERE L10.PARENT_ID = :V$ID AND L10.OBJ_TYPE_ID IN (10, 14) AND L10.DATE_DEL IS NULL
          INTO :N1;

          IF(N1 > 0) THEN
          BEGIN

              TAG_NAME = 'items:p';
              VAL = NULL;
              SUSPEND;
              TAG_NAME = 'items:p:id';
              VAL = V$ID;
              SUSPEND;
              TAG_NAME = 'items:p:name';
              VAL = V$NAME;
              SUSPEND;
              TAG_NAME = 'items:p:type';
              VAL = V$TYPE;
              SUSPEND;
              TAG_NAME = 'items:p:level';
              VAL = 3;
              SUSPEND;
              TAG_NAME = 'items:p:has_children';
              VAL = 1; -- Тут всегда только зачисленные, классы где нет зачисленных не показываются
              SUSPEND;

              SELECT COUNT(*)
              FROM LINKS L10
              JOIN UT_EXAM_PERSON_ASSN PA ON PA.PERSON_ID = L10.OBJ_ID AND PA.EXAM_ID = :I$EXAM_ID AND PA.DATE_DEL IS NULL
              LEFT JOIN UT_PERSON_PPE_ASSN A ON A.PERSON_ID = L10.OBJ_ID AND A.EXAM_ID = :I$EXAM_ID AND A.DATE_DEL IS NULL
              WHERE L10.PARENT_ID = :V$ID AND L10.OBJ_TYPE_ID IN (10, 14) AND L10.DATE_DEL IS NULL AND A.OBJ_ID IS NULL
              INTO :N2;

              TAG_NAME = 'items:p:n_assn';
              VAL = N1 - N2;
              SUSPEND;

              TAG_NAME = 'items:p:n_free';
              VAL = N2;
              SUSPEND;

          END

      END
  END
  ELSE IF(I$LEVEL = 3) THEN
  BEGIN
      -- Пофамильный список
      FOR
          SELECT L10.OBJ_ID, C.CAPTION, L10.OBJ_TYPE_ID, A.PPE_ID, PN.NAME_SHORT
          FROM LINKS L10
          JOIN UT_EXAM_PERSON_ASSN PA ON PA.PERSON_ID = L10.OBJ_ID AND PA.EXAM_ID = :I$EXAM_ID AND PA.DATE_DEL IS NULL
          LEFT JOIN OBJECT_CAPTION_GET(L10.OBJ_ID, 23) C ON 1 = 1
          LEFT JOIN UT_PERSON_PPE_ASSN A ON A.PERSON_ID = L10.OBJ_ID AND A.EXAM_ID = :I$EXAM_ID AND A.DATE_DEL IS NULL
          LEFT JOIN UT_PPE_DESC(A.PPE_ID) PN ON 1 = 1
          WHERE L10.PARENT_ID = :I$PARENT_ID AND L10.OBJ_TYPE_ID IN (10, 126) AND L10.DATE_DEL IS NULL
          UNION
          -- Добавляем сотрудников - там где они есть
          SELECT L14.OBJ_ID, C.CAPTION, L14.OBJ_TYPE_ID, A.PPE_ID, PN.NAME_SHORT
          FROM LINKS L14
          JOIN UT_EXAM_PERSON_ASSN PA ON PA.PERSON_ID = L14.OBJ_ID AND PA.EXAM_ID = :I$EXAM_ID AND PA.DATE_DEL IS NULL
          LEFT JOIN OBJECT_CAPTION_GET(L14.OBJ_ID) C ON 1 = 1
          LEFT JOIN UT_PERSON_PPE_ASSN A ON A.PERSON_ID = L14.OBJ_ID AND A.EXAM_ID = :I$EXAM_ID AND A.DATE_DEL IS NULL
          LEFT JOIN UT_PPE_DESC(A.PPE_ID) PN ON 1 = 1
          WHERE L14.PARENT_ID = :I$PARENT_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
          ORDER BY 2
          INTO :V$ID, :V$NAME, :V$TYPE, :V$PPE_ID, :V$PPE_NAME
      DO
      BEGIN

          TAG_NAME = 'items:p';
          VAL = NULL;
          SUSPEND;
          TAG_NAME = 'items:p:id';
          VAL = V$ID;
          SUSPEND;
          TAG_NAME = 'items:p:name';
          VAL = V$NAME;
          SUSPEND;
          TAG_NAME = 'items:p:type';
          VAL = V$TYPE;
          SUSPEND;
          TAG_NAME = 'items:p:level';
          VAL = 4;
          SUSPEND;
          TAG_NAME = 'items:p:has_children';
          VAL = 0; -- Тут точно конец дерева
          SUSPEND;
          TAG_NAME = 'items:p:flags';
          VAL = 0;
          SUSPEND;

          N1 = 1;
          IF(V$PPE_ID IS NULL) THEN N2 = 1; ELSE N2 = 0;

          TAG_NAME = 'items:p:n_assn';
          VAL = N1 - N2;
          SUSPEND;

          TAG_NAME = 'items:p:n_free';
          VAL = N2;
          SUSPEND;

          TAG_NAME = 'items:p:ppe_id';
          VAL = V$PPE_ID;
          SUSPEND;

          TAG_NAME = 'items:p:ppe_name';
          VAL = V$PPE_NAME;
          SUSPEND;

      END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_ASSN_PPE_RCHANGES (
    I$EXAM_ID BIGINT,
    I$LEVEL INTEGER,
    I$TIME TIMESTAMP,
    I$USER_LEVEL SMALLINT)
RETURNS (
    OBJ_ID BIGINT,
    OBJ_LEVEL INTEGER,
    N_TOTAL INTEGER,
    N_ASSN INTEGER,
    N_FREE INTEGER)
AS
begin

  -- ППЭ
  OBJ_LEVEL = 2;
  FOR
      SELECT DISTINCT A.PPE_ID, P.N_PLACES
      FROM UT_PERSON_PPE_ASSN A
      JOIN UT_PPE P ON P.OBJ_ID = A.PPE_ID AND P.DATE_DEL IS NULL
      WHERE A.DATE_MODIFY >= :I$TIME AND A.EXAM_ID = :I$EXAM_ID
      INTO :OBJ_ID, :N_TOTAL
  DO
  BEGIN
      SELECT COUNT(*)
      FROM UT_PERSON_PPE_ASSN A
      WHERE A.EXAM_ID = :I$EXAM_ID AND A.PPE_ID = :OBJ_ID AND A.DATE_DEL IS NULL
      INTO :N_ASSN;

      N_FREE = MAXVALUE(N_TOTAL - N_ASSN, 0);

      SUSPEND;
  END

  -- Районы - только если уровень пользователя соответствует
  OBJ_LEVEL = 1;
  FOR
      SELECT DISTINCT P.AREA_ID, SUM(P.N_PLACES * IIF(A.DATE_DEL IS NULL, 1, 0))
      FROM UT_PERSON_PPE_ASSN A
      JOIN UT_PPE P ON P.OBJ_ID = A.PPE_ID AND P.DATE_DEL IS NULL
      WHERE A.DATE_MODIFY >= :I$TIME AND A.EXAM_ID = :I$EXAM_ID AND :I$USER_LEVEL <= 1
      GROUP BY 1
      INTO :OBJ_ID, :N_TOTAL
  DO
  BEGIN
      SELECT COUNT(*)
      FROM UT_PERSON_PPE_ASSN A
      JOIN UT_PPE P ON P.OBJ_ID = A.PPE_ID AND P.DATE_DEL IS NULL AND P.AREA_ID = :OBJ_ID
      WHERE A.EXAM_ID = :I$EXAM_ID AND A.DATE_DEL IS NULL
      INTO :N_ASSN;

      N_FREE = MAXVALUE(N_TOTAL - N_ASSN, 0);

      SUSPEND;
  END

  -- Город - только если уровень пользователя соответствует
  OBJ_LEVEL = 0;
  IF(I$USER_LEVEL = 0) THEN
  BEGIN

      --SELECT SUM()

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_ASSN_PPE_REVERT (
    I$EXAM_ID BIGINT,
    I$SIDE INTEGER,
    I$LEVEL INTEGER,
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(200))
AS
DECLARE VARIABLE V$TIME TIMESTAMP;
DECLARE VARIABLE V$USER_TYPE SMALLINT;
DECLARE VARIABLE V$DB_LEVEL INTEGER;
DECLARE VARIABLE V$STATE INTEGER;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$L INTEGER;
DECLARE VARIABLE V$N1 INTEGER;
DECLARE VARIABLE V$N2 INTEGER;
DECLARE VARIABLE N INTEGER;
DECLARE VARIABLE N_ALL INTEGER;
DECLARE VARIABLE V$PPE_ID BIGINT;
DECLARE VARIABLE V$PPE_NAME VARCHAR(1000);
begin

  -- I$SIDE - какую сторону отменяем (0 = участники, 1 = ППЭ)

  V$TIME = CURRENT_TIMESTAMP;
  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  SELECT USER_TYPE
  FROM USERS
  WHERE USER_ID = :I$USER_ID AND DATE_DEL IS NULL
  INTO :V$USER_TYPE;

  -- Текущий уровень базы ?
  SELECT K.KEY_VAL
  FROM KEYS K
  WHERE K.KEY_CODE = 'LEVEL'
  INTO :V$DB_LEVEL;
  V$DB_LEVEL = 3 - V$DB_LEVEL;

  -- Проверяем статус тестирования ?
  SELECT EXAM_STATE
  FROM UT_EXAM_DATES
  WHERE DATE_DEL IS NULL AND OBJ_ID = :I$EXAM_ID
  INTO :V$STATE;

  IF(V$STATE IS NULL) THEN EXCEPTION DATA_ERROR 'Тестирование не найдено или было удалено другим пользователем';
  IF(V$STATE >= 700) THEN EXCEPTION DATA_ERROR 'Нельзя выполнить резервирование участников тестирования на данной стадии';

  N = 0;
  N_ALL = 0;

  -- Отменяем распределение
  IF(I$SIDE = 0) THEN
  BEGIN
      -- Отменяем для участников
      IF(I$LEVEL = 0) THEN
      BEGIN
          -- Уровень региона - снимаем вообще все распределения
          FOR
              SELECT A.PERSON_ID
              FROM UT_PERSON_PPE_ASSN A
              WHERE A.EXAM_ID = :I$EXAM_ID AND A.DATE_DEL IS NULL
              INTO :V$OBJ_ID
          DO
          BEGIN
              N_ALL = N_ALL + 1;
              N = N + (SELECT DONE FROM UT_TEST_ASSN_PPE_REVERT_PERSON(:I$EXAM_ID, :V$OBJ_ID));
          END
      END
      ELSE IF(I$LEVEL = 1) THEN
      BEGIN
          -- Уровень района
          FOR
              -- Действующие сотрудники
              SELECT A.PERSON_ID
              FROM UT_PERSON_PPE_ASSN A
              JOIN LINKS LP2 ON LP2.OBJ_ID = A.PERSON_ID AND LP2.PARENT_TYPE_ID = 111 AND LP2.DATE_DEL IS NULL
              JOIN LINKS LP111 ON LP111.OBJ_ID = LP2.PARENT_ID AND LP111.PARENT_ID = :I$OBJ_ID AND LP111.DATE_DEL IS NULL
              WHERE A.EXAM_ID = :I$EXAM_ID AND A.DATE_DEL IS NULL
              -- Уволенные сотрудники
              UNION
              SELECT A.PERSON_ID
              FROM UT_PERSON_PPE_ASSN A
              JOIN LINKS LP84 ON LP84.OBJ_ID = A.PERSON_ID AND LP84.PARENT_TYPE_ID = 84 AND LP84.DATE_DEL IS NULL
              JOIN LINKS LP2 ON LP2.OBJ_ID = LP84.PARENT_ID AND LP2.PARENT_TYPE_ID = 111 AND LP2.DATE_DEL IS NULL
              JOIN LINKS LP111 ON LP111.OBJ_ID = LP2.PARENT_ID AND LP111.PARENT_ID = :I$OBJ_ID AND LP111.DATE_DEL IS NULL
              WHERE A.EXAM_ID = :I$EXAM_ID AND A.DATE_DEL IS NULL
              -- Действующие учащиеся
              UNION
              SELECT A.PERSON_ID
              FROM UT_PERSON_PPE_ASSN A
              JOIN LINKS LP9 ON LP9.OBJ_ID = A.PERSON_ID AND LP9.PARENT_TYPE_ID IN (9, 125, 187) AND LP9.DATE_DEL IS NULL
              JOIN LINKS LP8 ON LP8.OBJ_ID = LP9.PARENT_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
              JOIN LINKS LP7 ON LP7.OBJ_ID = LP8.PARENT_ID AND LP7.PARENT_TYPE_ID IN (7, 502) AND LP7.DATE_DEL IS NULL
              JOIN LINKS LP2 ON LP2.OBJ_ID = LP7.PARENT_ID AND LP2.PARENT_TYPE_ID = 111 AND LP2.DATE_DEL IS NULL
              JOIN LINKS LP111 ON LP111.OBJ_ID = LP2.PARENT_ID AND LP111.PARENT_ID = :I$OBJ_ID AND LP111.DATE_DEL IS NULL
              WHERE A.EXAM_ID = :I$EXAM_ID AND A.DATE_DEL IS NULL
              INTO :V$OBJ_ID
          DO
          BEGIN
              N_ALL = N_ALL + 1;
              N = N + (SELECT DONE FROM UT_TEST_ASSN_PPE_REVERT_PERSON(:I$EXAM_ID, :V$OBJ_ID));
          END
      END
      ELSE IF(I$LEVEL = 2) THEN
      BEGIN
          -- Уровень ОУ
          FOR
              -- Действующие сотрудники
              SELECT A.PERSON_ID
              FROM UT_PERSON_PPE_ASSN A
              JOIN LINKS LP2 ON LP2.OBJ_ID = A.PERSON_ID AND LP2.PARENT_ID = :I$OBJ_ID AND LP2.DATE_DEL IS NULL
              WHERE A.EXAM_ID = :I$EXAM_ID AND A.DATE_DEL IS NULL
              -- Уволенные сотрудники
              UNION
              SELECT A.PERSON_ID
              FROM UT_PERSON_PPE_ASSN A
              JOIN LINKS LP84 ON LP84.OBJ_ID = A.PERSON_ID AND LP84.PARENT_TYPE_ID = 84 AND LP84.DATE_DEL IS NULL
              JOIN LINKS LP2 ON LP2.OBJ_ID = LP84.PARENT_ID AND LP2.PARENT_ID = :I$OBJ_ID AND LP2.DATE_DEL IS NULL
              WHERE A.EXAM_ID = :I$EXAM_ID AND A.DATE_DEL IS NULL
              -- Действующие учащиеся
              UNION
              SELECT A.PERSON_ID
              FROM UT_PERSON_PPE_ASSN A
              JOIN LINKS LP9 ON LP9.OBJ_ID = A.PERSON_ID AND LP9.PARENT_TYPE_ID IN (9, 125, 187) AND LP9.DATE_DEL IS NULL
              JOIN LINKS LP8 ON LP8.OBJ_ID = LP9.PARENT_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
              JOIN LINKS LP7 ON LP7.OBJ_ID = LP8.PARENT_ID AND LP7.PARENT_TYPE_ID IN (7, 502) AND LP7.DATE_DEL IS NULL
              JOIN LINKS LP2 ON LP2.OBJ_ID = LP7.PARENT_ID AND LP2.PARENT_ID = :I$OBJ_ID AND LP2.DATE_DEL IS NULL
              WHERE A.EXAM_ID = :I$EXAM_ID AND A.DATE_DEL IS NULL
              INTO :V$OBJ_ID
          DO
          BEGIN
              N_ALL = N_ALL + 1;
              N = N + (SELECT DONE FROM UT_TEST_ASSN_PPE_REVERT_PERSON(:I$EXAM_ID, :V$OBJ_ID));
          END
      END
      ELSE IF(I$LEVEL = 3) THEN
      BEGIN
          -- Коллектив
          FOR
              -- Действующие сотрудники
              SELECT A.PERSON_ID
              FROM UT_PERSON_PPE_ASSN A
              JOIN LINKS LP2 ON LP2.OBJ_ID = A.PERSON_ID AND LP2.PARENT_ID = :I$OBJ_ID AND LP2.DATE_DEL IS NULL
              WHERE A.EXAM_ID = :I$EXAM_ID AND A.DATE_DEL IS NULL
              -- Уволенные сотрудники
              UNION
              SELECT A.PERSON_ID
              FROM UT_PERSON_PPE_ASSN A
              JOIN LINKS LP84 ON LP84.OBJ_ID = A.PERSON_ID AND LP84.PARENT_TYPE_ID = 84 AND LP84.DATE_DEL IS NULL
              JOIN LINKS LP2 ON LP2.OBJ_ID = LP84.PARENT_ID AND LP2.PARENT_ID = :I$OBJ_ID AND LP2.DATE_DEL IS NULL
              WHERE A.EXAM_ID = :I$EXAM_ID AND A.DATE_DEL IS NULL
              -- Действующие учащиеся коллектива
              UNION
              SELECT A.PERSON_ID
              FROM UT_PERSON_PPE_ASSN A
              JOIN LINKS LP9 ON LP9.OBJ_ID = A.PERSON_ID AND LP9.PARENT_ID = :I$OBJ_ID AND LP9.DATE_DEL IS NULL
              WHERE A.EXAM_ID = :I$EXAM_ID AND A.DATE_DEL IS NULL
              INTO :V$OBJ_ID
          DO
          BEGIN
              N_ALL = N_ALL + 1;
              N = N + (SELECT DONE FROM UT_TEST_ASSN_PPE_REVERT_PERSON(:I$EXAM_ID, :V$OBJ_ID));
          END
      END
      ELSE IF(I$LEVEL = 4) THEN
      BEGIN
          -- Конкретный участник
          FOR
              SELECT A.PERSON_ID
              FROM UT_PERSON_PPE_ASSN A
              WHERE A.EXAM_ID = :I$EXAM_ID AND A.PERSON_ID = :I$OBJ_ID AND A.DATE_DEL IS NULL
              INTO :V$OBJ_ID
          DO
          BEGIN
              N_ALL = N_ALL + 1;
              N = N + (SELECT DONE FROM UT_TEST_ASSN_PPE_REVERT_PERSON(:I$EXAM_ID, :V$OBJ_ID));
          END
      END
  END
  ELSE
  BEGIN
      -- Отменяем для ППЭ
      IF(I$LEVEL = 0) THEN
      BEGIN
          -- Уровень региона - снимаем вообще все распределения
          FOR
              SELECT A.PERSON_ID
              FROM UT_PERSON_PPE_ASSN A
              WHERE A.EXAM_ID = :I$EXAM_ID AND A.DATE_DEL IS NULL
              INTO :V$OBJ_ID
          DO
          BEGIN
              N_ALL = N_ALL + 1;
              N = N + (SELECT DONE FROM UT_TEST_ASSN_PPE_REVERT_PERSON(:I$EXAM_ID, :V$OBJ_ID));
          END
      END
      ELSE IF(I$LEVEL = 1) THEN
      BEGIN
          -- Уровень района
          FOR
              SELECT A.PERSON_ID
              FROM UT_PERSON_PPE_ASSN A
              JOIN UT_PPE P ON P.OBJ_ID = A.PPE_ID AND P.AREA_ID = :I$OBJ_ID
              WHERE A.EXAM_ID = :I$EXAM_ID AND A.PPE_ID = :I$OBJ_ID AND A.DATE_DEL IS NULL
              INTO :V$OBJ_ID
          DO
          BEGIN
              N_ALL = N_ALL + 1;
              N = N + (SELECT DONE FROM UT_TEST_ASSN_PPE_REVERT_PERSON(:I$EXAM_ID, :V$OBJ_ID));
          END
      END
      ELSE IF(I$LEVEL = 2) THEN
      BEGIN
          -- Уровень ППЭ
          FOR
              SELECT A.PERSON_ID
              FROM UT_PERSON_PPE_ASSN A
              WHERE A.EXAM_ID = :I$EXAM_ID AND A.PPE_ID = :I$OBJ_ID AND A.DATE_DEL IS NULL
              INTO :V$OBJ_ID
          DO
          BEGIN
              N_ALL = N_ALL + 1;
              N = N + (SELECT DONE FROM UT_TEST_ASSN_PPE_REVERT_PERSON(:I$EXAM_ID, :V$OBJ_ID));
          END
      END
      ELSE EXCEPTION DATA_ERROR 'Недопустимый уровень';
  END

  -- Итоги
  TAG_NAME = 'n_unassigned';
  VAL = N;
  SUSPEND;
  TAG_NAME = 'n_failed';
  VAL = N_ALL;
  SUSPEND;

  -- Статистика по дереву участников
  TAG_NAME = 'items';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'items::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
      SELECT C.OBJ_ID, C.OBJ_LEVEL, C.N_ASSN, C.N_FREE, C.PPE_ID, D.NAME_SHORT
      FROM UT_TEST_ASSN_PPE_CHANGES(:I$EXAM_ID, :V$DB_LEVEL, :V$TIME, :V$DB_LEVEL) C
      LEFT JOIN UT_PPE_DESC(C.PPE_ID) D ON 1 = 1
      INTO :V$OBJ_ID, :V$L, :V$N1, :V$N2, :V$PPE_ID, :V$PPE_NAME
  DO
  BEGIN
      TAG_NAME = 'items:p';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'items:p:level';
      VAL = V$L;
      SUSPEND;
      TAG_NAME = 'items:p:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'items:p:n_assn';
      VAL = V$N1;
      SUSPEND;
      TAG_NAME = 'items:p:n_free';
      VAL = V$N2;
      SUSPEND;
      IF(V$L = 4) THEN
      BEGIN
          TAG_NAME = 'items:p:ppe_id';
          VAL = V$PPE_ID;
          SUSPEND;
          TAG_NAME = 'items:p:ppe_name';
          VAL = V$PPE_NAME;
          SUSPEND;
      END
  END

  -- Статистика по ППЭ - всегда с уровня 0
  TAG_NAME = 'ppe';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'ppe::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
      SELECT C.OBJ_ID, C.OBJ_LEVEL, C.N_ASSN, C.N_FREE, C.N_TOTAL
      FROM UT_TEST_ASSN_PPE_RCHANGES(:I$EXAM_ID, 0, :V$TIME, :V$DB_LEVEL) C
      INTO :V$OBJ_ID, :V$L, :V$N1, :V$N2, :N
  DO
  BEGIN
      TAG_NAME = 'ppe:p';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'ppe:p:level';
      VAL = V$L;
      SUSPEND;
      TAG_NAME = 'ppe:p:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'ppe:p:n_total';
      VAL = N;
      SUSPEND;
      TAG_NAME = 'ppe:p:n_assn';
      VAL = V$N1;
      SUSPEND;
      TAG_NAME = 'ppe:p:n_free';
      VAL = V$N2;
      SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_ASSN_PPE_REVERT_PERSON (
    I$EXAM_ID BIGINT,
    I$PERSON_ID BIGINT)
RETURNS (
    OLD_PPE_ID BIGINT,
    DONE SMALLINT)
AS
declare variable V$ASSN_ID bigint;
declare variable V$PLACE_ASSN_ID bigint;
begin

  DONE = 0;

  -- Было ли назначение участника ? Если было, то снимаем - даже если в том же ППЭ
  SELECT FIRST 1 A.OBJ_ID, A.PPE_ID
  FROM UT_PERSON_PPE_ASSN A
  WHERE A.EXAM_ID = :I$EXAM_ID AND A.PERSON_ID = :I$PERSON_ID AND A.DATE_DEL IS NULL
  INTO :V$ASSN_ID, :OLD_PPE_ID;

  IF(V$ASSN_ID IS NOT NULL) THEN
  BEGIN
      -- Проверяем, не было ли закреплено место ?!!
      SELECT FIRST 1 OBJ_ID
      FROM UT_PERSON_PLACE_ASSN A
      WHERE A.EXAM_ID = :I$EXAM_ID AND A.PERSON_ID = :I$PERSON_ID AND A.DATE_DEL IS NULL
      INTO :V$PLACE_ASSN_ID;

      IF(V$PLACE_ASSN_ID IS NULL) THEN
      BEGIN
          UPDATE UT_PERSON_PPE_ASSN
          SET DATE_DEL = CURRENT_TIMESTAMP
          WHERE OBJ_ID = :V$ASSN_ID AND DATE_DEL IS NULL;

          DONE = 1;
      END
  END

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_ASSN_PPE_RTREE (
    I$EXAM_ID BIGINT,
    I$LEVEL INTEGER,
    I$PARENT_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(1000))
AS
declare variable V$USER_TYPE smallint;
declare variable V$DB_LEVEL smallint;
declare variable V$ID bigint;
declare variable V$NAME varchar(1000);
declare variable N1 integer;
declare variable N2 integer;
begin

  -- Идентифицируем роль пользователя
  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  SELECT USER_TYPE
  FROM USERS
  WHERE USER_ID = :I$USER_ID AND DATE_DEL IS NULL
  INTO :V$USER_TYPE;

  -- Если пользователь не является админом, классным руководителем, директором или завучем - ошибка
  IF(V$USER_TYPE NOT IN (1, 4, 5, 6)) THEN EXCEPTION DATA_ERROR 'У данного пользователя нет доступа к назначению на тестирование';

  -- Текущий уровень базы ?
  SELECT K.KEY_VAL
  FROM KEYS K
  WHERE K.KEY_CODE = 'LEVEL'
  INTO :V$DB_LEVEL;

  -- Запрошен корень дерева
  IF(I$LEVEL IS NULL OR I$PARENT_ID IS NULL) THEN
  BEGIN

      -- Уровень пользователя (0 = регион ... 2 = ОУ), в корне дерева выбираем на 1 уровень меньше уровня пользователя
      TAG_NAME = 'level';
      IF(V$USER_TYPE = 8) THEN I$LEVEL = 3; ELSE I$LEVEL = 3 - V$DB_LEVEL;
      VAL = I$LEVEL;
      I$LEVEL = I$LEVEL - 1;
      SUSPEND;

      -- Идентифицируем корневой объект пользователя (регион, район или ППЭ, соответствующий конкретной ОУ)
      IF(I$LEVEL = -1) THEN
      BEGIN
          I$PARENT_ID = NULL;
      END
      ELSE IF(I$LEVEL = 0) THEN
      BEGIN
          -- INTO :I$PARENT_ID;
      END
      ELSE IF(I$LEVEL >= 1) THEN
      BEGIN
          SELECT FIRST 1 P.OBJ_ID
          FROM LINKS L
          JOIN UT_PPE P ON P.ORG_ID = L.OBJ_ID AND P.DATE_DEL IS NULL
          WHERE (L.PARENT_ID IS NULL OR L.PARENT_TYPE_ID IN (111, 112)) AND L.OBJ_TYPE_ID = 2 AND L.DATE_DEL IS NULL
          INTO :I$PARENT_ID;
      END

      IF(I$PARENT_ID IS NULL AND I$LEVEL >= 0) THEN EXCEPTION DATA_ERROR 'Для вашего уровня прав доступа нет доступных ППЭ';

      TAG_NAME = 'readonly';
      VAL = '0'; -- !!!
      SUSPEND;

  END
  ELSE IF(I$LEVEL < (3 - V$DB_LEVEL)) THEN EXCEPTION DATA_ERROR 'Нельзя запросить уровень выше текущего';

  TAG_NAME = 'items';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'items::json&colon;array';
  VAL = '1';
  SUSPEND;

  IF(I$LEVEL = -1) THEN
  BEGIN
      -- Уровень региона > сам регион
      FOR
          SELECT L.OBJ_ID, C.CAPTION
          FROM LINKS L
          LEFT JOIN OBJECT_CAPTION_GET(L.OBJ_ID) C ON 1 = 1
          WHERE L.PARENT_ID IS NULL AND L.OBJ_TYPE_ID = 112 AND L.DATE_DEL IS NULL
          ORDER BY 2
          INTO :V$ID, :V$NAME
      DO
      BEGIN
          TAG_NAME = 'items:p';
          VAL = NULL;
          SUSPEND;
          TAG_NAME = 'items:p:id';
          VAL = V$ID;
          SUSPEND;
          TAG_NAME = 'items:p:name';
          VAL = V$NAME;
          SUSPEND;
          TAG_NAME = 'items:p:level';
          VAL = 0;
          SUSPEND;
          TAG_NAME = 'items:p:has_children';
          IF(EXISTS(SELECT FIRST 1 1 FROM LINKS WHERE PARENT_ID = :V$ID AND OBJ_TYPE_ID IN (2, 111) AND DATE_DEL IS NULL)) THEN VAL = 1; ELSE VAL = 0;
          SUSPEND;

          -- Без ограничения по ППЭ
          SELECT SUM(P.N_PLACES)
          FROM UT_EXAM_PPE_ASSN A
          JOIN UT_PPE P ON P.OBJ_ID = A.PPE_ID AND P.DATE_DEL IS NULL
          WHERE A.EXAM_ID = :I$EXAM_ID AND A.DATE_DEL IS NULL
          INTO :N1;

          SELECT COUNT(*)
          FROM UT_PERSON_PPE_ASSN A
          WHERE A.EXAM_ID = :I$EXAM_ID AND A.DATE_DEL IS NULL
          INTO :N2;

          TAG_NAME = 'items:p:n_total';
          VAL = N1;
          SUSPEND;

          TAG_NAME = 'items:p:n_assn';
          VAL = N2;
          SUSPEND;

          TAG_NAME = 'items:p:n_free';
          VAL = MAXVALUE(N1 - N2, 0);
          SUSPEND;

      END
  END
  ELSE IF(I$LEVEL = 0) THEN
  BEGIN
      -- Уровень района - список ППЭ по районам
      FOR
          SELECT LISTVAL_ID, VAL
          FROM LISTVALS_LIST(7)
          WHERE LISTVAL_ID <> 3387
          ORDER BY 2
          INTO :V$ID, :V$NAME
      DO
      BEGIN
          TAG_NAME = 'items:p';
          VAL = NULL;
          SUSPEND;
          TAG_NAME = 'items:p:id';
          VAL = V$ID;
          SUSPEND;
          TAG_NAME = 'items:p:name';
          VAL = V$NAME;
          SUSPEND;
          TAG_NAME = 'items:p:level';
          VAL = 2;
          SUSPEND;

          SELECT SUM(P.N_PLACES)
          FROM UT_EXAM_PPE_ASSN A
          JOIN UT_PPE P ON P.OBJ_ID = A.PPE_ID AND P.DATE_DEL IS NULL AND P.AREA_ID = :I$PARENT_ID
          WHERE A.EXAM_ID = :I$EXAM_ID AND A.DATE_DEL IS NULL
          INTO :N1;

          SELECT COUNT(*)
          FROM UT_PERSON_PPE_ASSN A
          JOIN UT_PPE P ON P.OBJ_ID = A.PPE_ID AND P.DATE_DEL IS NULL AND P.AREA_ID = :I$PARENT_ID
          WHERE A.EXAM_ID = :I$EXAM_ID AND A.DATE_DEL IS NULL
          INTO :N2;

          TAG_NAME = 'items:p:has_children';
          VAL = 0;
          SUSPEND;

          TAG_NAME = 'items:p:n_total';
          VAL = N1;
          SUSPEND;

          TAG_NAME = 'items:p:n_assn';
          VAL = N2;
          SUSPEND;

          TAG_NAME = 'items:p:n_free';
          VAL = MAXVALUE(N1 - N2, 0);
          SUSPEND;
      END
  END
  ELSE IF(I$LEVEL = 1) THEN
  BEGIN
      -- Конкретный ППЭ или список ППЭ в районе
      FOR
          SELECT P.OBJ_ID, D.NAME_SHORT, D.N_PLACES
          FROM UT_PPE P
          JOIN UT_EXAM_PPE_ASSN PA ON PA.PPE_ID = P.OBJ_ID AND PA.EXAM_ID = :I$EXAM_ID AND PA.DATE_DEL IS NULL
          LEFT JOIN UT_PPE_DESC(P.OBJ_ID) D ON 1 = 1
          WHERE P.DATE_DEL IS NULL AND (P.OBJ_ID = :I$PARENT_ID OR P.AREA_ID = :I$PARENT_ID)
          ORDER BY 2
          INTO :V$ID, :V$NAME, :N1
      DO
      BEGIN
          TAG_NAME = 'items:p';
          VAL = NULL;
          SUSPEND;
          TAG_NAME = 'items:p:id';
          VAL = V$ID;
          SUSPEND;
          TAG_NAME = 'items:p:name';
          VAL = V$NAME;
          SUSPEND;
          TAG_NAME = 'items:p:level';
          VAL = 2;
          SUSPEND;

          SELECT COUNT(*)
          FROM UT_PERSON_PPE_ASSN A
          WHERE A.PPE_ID = :V$ID AND A.EXAM_ID = :I$EXAM_ID AND A.DATE_DEL IS NULL
          INTO :N2;

          TAG_NAME = 'items:p:has_children';
          VAL = 0;
          SUSPEND;

          TAG_NAME = 'items:p:n_total';
          VAL = N1;
          SUSPEND;

          TAG_NAME = 'items:p:n_assn';
          VAL = N2;
          SUSPEND;

          TAG_NAME = 'items:p:n_free';
          VAL = MAXVALUE(N1 - N2, 0);
          SUSPEND;
      END
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_ATTR_CHARSETS (
    I$EXAM_ID BIGINT)
RETURNS (
    VAL VARCHAR(4000))
AS
declare variable V$STRUCT_ID bigint;
declare variable S varchar(100);
begin

  VAL = '';

  SELECT FIRST 1 T.STRUCT_ID
  FROM UT_EXAM_TEST_VARS ETV
  JOIN UT_TEST_VARS TV ON TV.OBJ_ID = ETV.TEST_VAR_ID
  JOIN UT_TESTS T ON T.OBJ_ID = TV.TEST_ID
  WHERE ETV.EXAM_ID = :I$EXAM_ID AND ETV.DATE_DEL IS NULL
  INTO :V$STRUCT_ID;

  FOR
      SELECT COALESCE(C.LANG_CODE, 'digits')
      FROM UT_TEST_STRUCT_POINTS TSP
      LEFT JOIN UT_CHARSETS C ON C.OBJ_ID = TSP.CHARSET_ID
      WHERE TSP.STRUCT_ID = :V$STRUCT_ID AND TSP.DATE_DEL IS NULL
      ORDER BY TSP.Q_ORDER
      INTO :S
  DO
  BEGIN
      IF(CHAR_LENGTH(VAL) > 0) THEN VAL = VAL || ';';
      VAL = VAL || S;
  END

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_AUTOCODING (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
declare variable V$ID bigint;
declare variable V$CODING_ID bigint;
declare variable V$STRUCT_ID bigint;
declare variable V$STAGE_ID bigint;
declare variable V$SUBJECT_ID bigint;
declare variable V$VAR_ID bigint;
declare variable V$VAR_NUM integer;
declare variable V$CL_ID bigint;
declare variable V$TYPE smallint;
declare variable V$LEVEL smallint;
declare variable V$SCORE integer;
declare variable V$CHARSET integer;
declare variable V$ORDER integer;
declare variable V$Q_ID bigint;
declare variable V$TYPE2 smallint;
declare variable V$N_VARIANTS integer;
declare variable V$N_ADDED integer;
declare variable V$N_WARNING integer;
declare variable V$N_MISSC integer;
declare variable V$TSP_ID bigint;
declare variable V$REF_ID bigint;
declare variable V$NAME varchar(1000);
declare variable V$DESC blob sub_type 1 segment size 80;
declare variable V$REF_LEVEL integer;
declare variable N1 integer;
declare variable N2 integer;
declare variable V$Q_CHARSET integer;
begin

  V$N_ADDED = 0;
  V$N_VARIANTS = 0;
  V$N_WARNING = 0;
  V$N_MISSC = 0;

  -- Проверяем, привязан ли к тесту автокодификатора ?
  SELECT FIRST 1 T.STRUCT_ID
  FROM UT_TESTS T
  WHERE T.OBJ_ID = :I$OBJ_ID AND T.DATE_DEL IS NULL
  INTO :V$STRUCT_ID;

  IF(V$STRUCT_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Пакет КИМ не найден или был удален, либо не назначена структура';

  -- Если нет ни одного варианта, или в структуре нет позиций - все идут к черту
  IF(NOT EXISTS(
      SELECT FIRST 1 1
      FROM UT_TEST_VARS TV
      WHERE TV.DATE_DEL IS NULL AND TV.TEST_ID = :I$OBJ_ID
  )) THEN EXCEPTION DATA_ERROR 'В тесте нет ни одного варианта';

  IF(NOT EXISTS(
      SELECT FIRST 1 1
      FROM UT_TEST_STRUCT_POINTS P
      WHERE P.DATE_DEL IS NULL AND P.STRUCT_ID = :V$STRUCT_ID
  )) THEN EXCEPTION DATA_ERROR 'Назначенная в пакете КИМ структура теста не заполнена';

  -- Смотрим, сколько у нас разных кодификаторов участвуют в назначенных вопросах
  FOR
      SELECT DISTINCT CL.CODING_ID
      FROM UT_TEST_VARS TV
      JOIN UT_TEST_VAR_QUESTIONS TVQ ON TVQ.VAR_ID = TV.OBJ_ID AND TVQ.DATE_DEL IS NULL
      JOIN UT_QUESTIONS Q ON Q.DATE_DEL IS NULL AND Q.OBJ_ID = TVQ.QUESTION_ID
      JOIN UT_KIM_CODING_LEVELS CL ON CL.OBJ_ID = Q.SECTION_ID
      WHERE TV.DATE_DEL IS NULL AND TV.TEST_ID = :I$OBJ_ID
      INTO :V$ID
  DO
  BEGIN
      IF(V$CODING_ID IS NULL) THEN V$CODING_ID = V$ID;
      ELSE EXCEPTION DATA_ERROR 'В тесте использованы вопросы из нескольких кодификаторов, невозможно выполнить автоматическую генерацию прототипов вопросов';
  END

  -- Если кодификатора нет - создаем новый автокодификатор, всегда 1 уровень вложений (номер варианта)
  IF(V$CODING_ID IS NULL) THEN
  BEGIN
      SELECT TS.STAGE_ID, TS.SUBJECT_ID
      FROM UT_TEST_STRUCTS TS
      WHERE TS.OBJ_ID = :V$STRUCT_ID AND TS.DATE_DEL IS NULL
      INTO :V$STAGE_ID, :V$SUBJECT_ID;

      IF(V$STAGE_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не удалось определить уровень контингента в описании структуры';

      SELECT T.OBJ_NAME
      FROM UT_TESTS T
      WHERE T.OBJ_ID = :I$OBJ_ID
      INTO :V$NAME;

      INSERT INTO UT_KIM_CODING
      (OBJ_NAME, N_LEVELS)
      VALUES ('Автокодификатор - ' || :V$NAME, 1)
      RETURNING OBJ_ID INTO :V$CODING_ID;

      -- Предмет
      INSERT INTO UT_KIM_CODING_SUBJECTS
      (CODING_ID, SUBJECT_ID)
      VALUES (:V$CODING_ID, :V$SUBJECT_ID);

      -- Этап
      INSERT INTO UT_KIM_CODING_STAGES
      (CODING_ID, STAGE_ID)
      VALUES (:V$CODING_ID, :V$STAGE_ID);

  END

  -- Идем по всем номерам вариантов, которые еще не полностью заполнены вопросами, и формируем разделы
  FOR
      SELECT TV.OBJ_ID, TV.NUM
      FROM UT_TEST_VARS TV
      WHERE TV.TEST_ID = :I$OBJ_ID AND TV.DATE_DEL IS NULL
      INTO :V$VAR_ID, :V$VAR_NUM
  DO
  BEGIN

      -- Все ли вопросы назначены в этом варианте ? Если все назначено, этот вариант пропускаем
      IF(EXISTS(
          SELECT FIRST 1 1
          FROM UT_TEST_STRUCT_POINTS TSP
          LEFT JOIN UT_TEST_VAR_QUESTIONS TVQ ON TVQ.DATE_DEL IS NULL AND TVQ.VAR_ID = :V$VAR_ID AND TVQ.STRUCT_POINT_ID = TSP.OBJ_ID
          WHERE TSP.DATE_DEL IS NULL AND TSP.STRUCT_ID = :V$STRUCT_ID AND TVQ.OBJ_ID IS NULL
      )) THEN
      BEGIN

          -- Создаем уровень в кодификаторе
          V$CL_ID = NULL;
          SELECT FIRST 1 CL.OBJ_ID
          FROM UT_KIM_CODING_LEVELS CL
          WHERE CL.CODING_ID = :V$CODING_ID AND CL.DATE_DEL IS NULL AND CL.PARENT_ID IS NULL AND CL.OBJ_NAME = 'Вариант ' || :V$VAR_NUM
          INTO :V$CL_ID;

          IF(V$CL_ID IS NULL) THEN
          BEGIN
              INSERT INTO UT_KIM_CODING_LEVELS
              (CODING_ID, PARENT_ID, N_LEVEL, OBJ_NAME, SORT_ORDER)
              VALUES (:V$CODING_ID, NULL, 0, 'Вариант ' || :V$VAR_NUM, :V$VAR_NUM)
              RETURNING OBJ_ID INTO :V$CL_ID;
          END

          V$N_VARIANTS = V$N_VARIANTS + 1;

          -- Добавляем вопросы - только те, которые еще не назначены
          FOR
              SELECT TSP.OBJ_ID, TSP.Q_ORDER, TSP.Q_TYPE_ID, TSP.Q_LEVEL, TSP.Q_MAX_SCORE, TSP.CHARSET_ID
              FROM UT_TEST_STRUCT_POINTS TSP
              LEFT JOIN UT_TEST_VAR_QUESTIONS TVQ ON TVQ.DATE_DEL IS NULL AND TVQ.VAR_ID = :V$VAR_ID AND TVQ.STRUCT_POINT_ID = TSP.OBJ_ID
              WHERE TSP.STRUCT_ID = :V$STRUCT_ID AND TSP.DATE_DEL IS NULL AND TVQ.OBJ_ID IS NULL
              ORDER BY TSP.Q_ORDER
              INTO :V$TSP_ID, :V$ORDER, :V$TYPE, :V$LEVEL, :V$SCORE, :V$CHARSET
          DO
          BEGIN

              -- Если вдруг уже есть вопрос с таким номером - возвращаем его
              V$Q_ID = NULL;
              SELECT FIRST 1 Q.OBJ_ID, Q.QUESTION_TYPE, Q.CHARSET_ID
              FROM UT_QUESTIONS Q
              WHERE Q.SECTION_ID = :V$CL_ID AND Q.DATE_DEL IS NULL AND Q.OBJ_NAME = 'Вопрос ' || :V$ORDER
              INTO :V$Q_ID, :V$TYPE2, :V$Q_CHARSET;

              IF(V$Q_ID IS NULL) THEN
              BEGIN
                  INSERT INTO UT_QUESTIONS
                  (SECTION_ID, SORT_ORDER, QUESTION_TYPE, OBJ_NAME, QUESTION, MAX_SCORE, Q_LEVEL, CHARSET_ID)
                  VALUES (:V$CL_ID, :V$ORDER, :V$TYPE, 'Вопрос ' || :V$ORDER, 'Текст вопроса...', :V$SCORE, :V$LEVEL, :V$CHARSET)
                  RETURNING OBJ_ID INTO :V$Q_ID;

                  V$N_ADDED = V$N_ADDED + 1;
              END
              ELSE IF(V$TYPE2 <> V$TYPE) THEN EXCEPTION DATA_ERROR 'Системная ошибка. Тип вопроса в кодификаторе не соответствует типу в описании структуры';
              ELSE IF(V$Q_CHARSET <> V$CHARSET) THEN
              BEGIN
                  -- Корректируем кодировку вопроса
                  UPDATE UT_QUESTIONS
                  SET CHARSET_ID = :V$CHARSET
                  WHERE OBJ_ID = :V$Q_ID;
              END

              -- Для вопросов типа C и F (письменный и аудирование) корректируем список критериев по первому прототипу, где что-то есть
              IF(V$TYPE IN (3, 8)) THEN
              BEGIN

                  V$REF_ID = NULL;
                  SELECT FIRST 1 Q.OBJ_ID
                  FROM UT_TEST_VARS TV
                  JOIN UT_TEST_VAR_QUESTIONS TVQ ON TVQ.VAR_ID = TV.OBJ_ID AND TVQ.DATE_DEL IS NULL AND TVQ.STRUCT_POINT_ID = :V$TSP_ID
                  JOIN UT_QUESTIONS Q ON Q.OBJ_ID = TVQ.QUESTION_ID AND Q.DATE_DEL IS NULL
                  JOIN UT_ANSWERS QA ON QA.QUESTION_ID = Q.OBJ_ID AND QA.DATE_DEL IS NULL
                  WHERE TV.TEST_ID = :I$OBJ_ID AND TV.DATE_DEL IS NULL -- смотрим все номера вариантов
                  INTO :V$REF_ID;

                  IF(V$REF_ID IS NOT NULL) THEN
                  BEGIN

                      FOR
                          SELECT QA.SORT_ORDER, QA.OBJ_NAME, QA.A_LEVEL, QA.VARIANT, QA2.A_LEVEL
                          FROM UT_ANSWERS QA
                          LEFT JOIN UT_ANSWERS QA2 ON QA2.QUESTION_ID = :V$Q_ID AND QA2.DATE_DEL IS NULL AND QA2.SORT_ORDER = QA.SORT_ORDER
                          WHERE QA.QUESTION_ID = :V$REF_ID AND QA.DATE_DEL IS NULL
                          ORDER BY QA.SORT_ORDER
                          INTO :V$ORDER, :V$NAME, :V$LEVEL, :V$DESC, :V$REF_LEVEL
                      DO
                      BEGIN
                          IF(V$REF_LEVEL IS NULL) THEN
                          BEGIN
                              INSERT INTO UT_ANSWERS
                              (QUESTION_ID, SORT_ORDER, OBJ_NAME, A_LEVEL, VARIANT)
                              VALUES (:V$Q_ID, :V$ORDER, :V$NAME, :V$LEVEL, :V$DESC);
                          END
                          ELSE IF (V$REF_LEVEL <> V$LEVEL) THEN EXCEPTION DATA_ERROR 'В вопросе ' || V$ORDER || ' различаются веса критериев';
                      END

                  END
                  ELSE
                  BEGIN

                      -- Если нет ни одного заполненного варианта, создаем все критерии по 1 баллу
                      N1 = 1;
                      WHILE(N1 <= V$SCORE) DO
                      BEGIN
                          INSERT INTO UT_ANSWERS
                          (QUESTION_ID, SORT_ORDER, OBJ_NAME, A_LEVEL, VARIANT)
                          VALUES (:V$Q_ID, :N1, 'Критерий ' || :N1, 1, 'Критерий ' || :N1);

                          N1 = N1 + 1;
                      END

                  END

              END

              -- Прописываем связь с вопросом в данном варианте
              V$REF_ID = NULL;
              SELECT FIRST 1 TVQ.QUESTION_ID
              FROM UT_TEST_VAR_QUESTIONS TVQ
              WHERE TVQ.VAR_ID = :V$VAR_ID AND TVQ.STRUCT_POINT_ID = :V$TSP_ID AND TVQ.DATE_DEL IS NULL
              INTO :V$REF_ID;

              IF(V$REF_ID <> V$Q_ID) THEN EXCEPTION DATA_ERROR 'Системная ошибка. В вопросах в вариантах теста найдена ссылка на чужой вопрос';

              IF(V$REF_ID IS NULL) THEN
              BEGIN
                  INSERT INTO UT_TEST_VAR_QUESTIONS
                  (VAR_ID, STRUCT_POINT_ID, QUESTION_ID, ORDER_INDEX)
                  VALUES (:V$VAR_ID, :V$TSP_ID, :V$Q_ID, 1)
                  RETURNING OBJ_ID INTO :V$REF_ID;
              END

          END -- цикл по позициям структуры

      END -- проверка наличия дырок в вопросах

  END

  -- Во всех ли вопросах типа C и F прописаны одинаковое количество критериев ?
  IF(V$N_MISSC = 0) THEN
  BEGIN
      FOR
          SELECT DISTINCT TSP.OBJ_ID, TSP.Q_ORDER
          FROM UT_TEST_VARS TV
          JOIN UT_TEST_VAR_QUESTIONS TVQ ON TVQ.VAR_ID = TV.OBJ_ID AND TVQ.DATE_DEL IS NULL
          JOIN UT_TEST_STRUCT_POINTS TSP ON TSP.OBJ_ID = TVQ.STRUCT_POINT_ID AND TSP.DATE_DEL IS NULL AND TSP.Q_TYPE_ID IN (3, 8)
          WHERE TV.TEST_ID = :I$OBJ_ID AND TV.DATE_DEL IS NULL
          INTO :V$TSP_ID, :V$LEVEL
      DO
      BEGIN
          N1 = NULL;
          N2 = NULL;
          SELECT MIN(QC), MAX(QC)
          FROM (
              SELECT TV.OBJ_ID, COUNT(*) QC
              FROM UT_TEST_VARS TV
              JOIN UT_TEST_VAR_QUESTIONS TVQ ON TVQ.VAR_ID = TV.OBJ_ID AND TVQ.DATE_DEL IS NULL AND TVQ.STRUCT_POINT_ID = :V$TSP_ID
              JOIN UT_QUESTIONS Q ON Q.OBJ_ID = TVQ.QUESTION_ID
              JOIN UT_ANSWERS QA ON QA.QUESTION_ID = Q.OBJ_ID AND QA.DATE_DEL IS NULL
              WHERE TV.TEST_ID = :I$OBJ_ID AND TV.DATE_DEL IS NULL
              GROUP BY 1
          )
          INTO :N1, :N2;

          IF(N1 IS NULL) THEN N1 = 0;

          IF(N1 <> N2) THEN V$N_WARNING = V$N_WARNING + 1;
          IF(N1 = 0) THEN V$N_MISSC = 1;
      END
  END

  TAG_NAME = 'variants';
  VAL = V$N_VARIANTS;
  SUSPEND;

  TAG_NAME = 'questions';
  VAL = V$N_ADDED;
  SUSPEND;

  TAG_NAME = 'warning';
  VAL = V$N_WARNING;
  SUSPEND;

  TAG_NAME = 'missing_c';
  VAL = V$N_MISSC;
  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_BLANKS_GET (
    I$EXAM_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    BLANK_NAME VARCHAR(100),
    BLOB_ID BLOB SUB_TYPE 1 SEGMENT SIZE 80)
AS
declare variable V$STATE integer;
declare variable V$BLANK_GEN_ID bigint;
declare variable V$BLANK_AB_ID bigint;
declare variable V$BLANK_C_ID bigint;
declare variable V$BLANK_EXT_ID bigint;
declare variable V$BLANK_TYPE smallint;
declare variable V$IS_DS smallint;
declare variable V$DATA_FRONT blob sub_type 0 segment size 80;
declare variable V$DATA_BACK blob sub_type 0 segment size 80;
declare variable V$MASK smallint;
declare variable V$LOCAL_ID varchar(40);
declare variable V$DATE date;
declare variable V$NAME varchar(200);
declare variable V$STAGE_ID integer;
declare variable V$SUBJECT_ID bigint;
declare variable V$CLASS_NAME varchar(100);
declare variable V$OU_NAME varchar(200);
begin

  -- Первыми строками возвращаются шаблоны всех бланков в BLOB_ID, в TAG_NAME передается текст BLOB, в VAL описание бланка
  -- После чего выдаются уже сериализованные данные по участнику

  SELECT D.EXAM_STATE, D.BLANK_AB_ID, D.BLANK_C_ID, D.BLANK_EXT_ID, D.BLANK_GEN_ID, D.EXAM_DATE_START, D.OBJ_NAME, D.SUBJECT_ID, D.STAGE_ID
  FROM UT_EXAM_DATES D
  WHERE D.OBJ_ID = :I$EXAM_ID AND D.DATE_DEL IS NULL
  INTO :V$STATE, :V$BLANK_AB_ID, :V$BLANK_C_ID, :V$BLANK_EXT_ID, :V$BLANK_GEN_ID, :V$DATE, :V$NAME, :V$SUBJECT_ID, :V$STAGE_ID;

  IF(V$STATE IS NULL) THEN EXCEPTION DATA_ERROR 'Тестирование не найдено или было удалено';
  IF(V$STATE < 600 OR V$STATE >= 1000) THEN EXCEPTION DATA_ERROR 'Недопустимый статус тестирования';

  V$MASK = 0;

  -- Ведомость участников
  V$BLANK_TYPE = NULL;
  V$IS_DS = NULL;
  V$DATA_FRONT = NULL;
  V$DATA_BACK = NULL;
  SELECT PT.BLANK_TYPE, PT.IS_DS, PT.DATA_FRONT, PT.DATA_BACK
  FROM UT_PAGE_TEMPLATES PT
  WHERE PT.OBJ_ID = :V$BLANK_GEN_ID
  INTO :V$BLANK_TYPE, :V$IS_DS, :V$DATA_FRONT, :V$DATA_BACK;

  IF(V$BLANK_TYPE <> 0) THEN
  BEGIN
      BLANK_NAME = 'G:0';
      BLOB_ID = V$DATA_FRONT;
      SUSPEND;

      IF(V$IS_DS = 1) THEN
      BEGIN
          BLANK_NAME = 'G:1';
          BLOB_ID = V$DATA_BACK;
          SUSPEND;
      END
  END

  -- Бланк AB
  V$BLANK_TYPE = NULL;
  V$IS_DS = NULL;
  V$DATA_FRONT = NULL;
  V$DATA_BACK = NULL;
  SELECT PT.BLANK_TYPE, PT.IS_DS, PT.DATA_FRONT, PT.DATA_BACK
  FROM UT_PAGE_TEMPLATES PT
  WHERE PT.OBJ_ID = :V$BLANK_AB_ID
  INTO :V$BLANK_TYPE, :V$IS_DS, :V$DATA_FRONT, :V$DATA_BACK;

  IF(V$BLANK_TYPE <> 0) THEN
  BEGIN
      BLANK_NAME = 'AB:0';
      BLOB_ID = V$DATA_FRONT;
      SUSPEND;

      IF(V$IS_DS = 1) THEN
      BEGIN
          BLANK_NAME = 'AB:1';
          BLOB_ID = V$DATA_BACK;
          SUSPEND;
      END

      V$MASK = BIN_OR(V$MASK, 1);
  END

  -- Бланк C
  V$BLANK_TYPE = NULL;
  V$IS_DS = NULL;
  V$DATA_FRONT = NULL;
  V$DATA_BACK = NULL;
  SELECT PT.BLANK_TYPE, PT.IS_DS, PT.DATA_FRONT, PT.DATA_BACK
  FROM UT_PAGE_TEMPLATES PT
  WHERE PT.OBJ_ID = :V$BLANK_C_ID
  INTO :V$BLANK_TYPE, :V$IS_DS, :V$DATA_FRONT, :V$DATA_BACK;

  IF(V$BLANK_TYPE <> 0) THEN
  BEGIN
      BLANK_NAME = 'C:0';
      BLOB_ID = V$DATA_FRONT;
      SUSPEND;

      IF(V$IS_DS = 1) THEN
      BEGIN
          BLANK_NAME = 'C:1';
          BLOB_ID = V$DATA_BACK;
          SUSPEND;
      END

      V$MASK = BIN_OR(V$MASK, 1);
  END

  IF(V$MASK = 0) THEN EXCEPTION DATA_ERROR 'Не заданы шаблоны бланков AB или C';

  -- Дополнительный бланк C
  V$BLANK_TYPE = NULL;
  V$IS_DS = NULL;
  V$DATA_FRONT = NULL;
  V$DATA_BACK = NULL;
  SELECT PT.BLANK_TYPE, PT.IS_DS, PT.DATA_FRONT, PT.DATA_BACK
  FROM UT_PAGE_TEMPLATES PT
  WHERE PT.OBJ_ID = :V$BLANK_EXT_ID
  INTO :V$BLANK_TYPE, :V$IS_DS, :V$DATA_FRONT, :V$DATA_BACK;

  IF(V$BLANK_TYPE <> 0) THEN
  BEGIN
      BLANK_NAME = 'CX:0';
      BLOB_ID = V$DATA_FRONT;
      SUSPEND;

      IF(V$IS_DS = 1) THEN
      BEGIN
          BLANK_NAME = 'CX:1';
          BLOB_ID = V$DATA_BACK;
          SUSPEND;
      END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_BLANKS_LIST (
    I$EXAM_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
declare variable V$DB_LEVEL smallint;
declare variable V$STATE integer;
declare variable V$ORG_REF bigint;
declare variable V$LEVEL integer;
declare variable V$OUR_ORG bigint;
declare variable V$METHOD smallint;
declare variable V$PLAN_METHOD smallint;
declare variable V$GROUP_ID bigint;
declare variable V$GROUP_TYPE bigint;
declare variable V$NAME varchar(1000);
declare variable V$OBJ_ID bigint;
declare variable V$OBJ_TYPE_ID bigint;
declare variable V$PRINTED smallint;
begin

  -- Идентифицируем себя
  SELECT COALESCE(CAST(K.KEY_VAL AS INTEGER) - 1, 0)
  FROM KEYS K
  WHERE K.KEY_CODE = 'LEVEL'
  INTO :V$DB_LEVEL;

  IF(V$DB_LEVEL <> 0) THEN EXCEPTION DATA_ERROR 'Печать бланков может выполняться только на уровне ОУ';

  SELECT D.EXAM_STATE, D.ORG_REF, D.H_LEVEL, D.METHOD_ID, D.PLAN_METHOD_ID
  FROM UT_EXAM_DATES D
  WHERE D.OBJ_ID = :I$EXAM_ID AND D.DATE_DEL IS NULL
  INTO :V$STATE, :V$ORG_REF, :V$LEVEL, :V$METHOD, :V$PLAN_METHOD;

  IF(V$STATE IS NULL) THEN EXCEPTION DATA_ERROR 'Тестирование не найдено или было удалено';
  --IF(V$STATE < 600 OR V$STATE >= 1000) THEN EXCEPTION DATA_ERROR 'Печать бланков в данном статусе невозможна';
  --IF(V$METHOD = 0) THEN EXCEPTION DATA_ERROR 'Для электронного тестирования печать не предусмотрена';
  IF(V$PLAN_METHOD = 3) THEN EXCEPTION DATA_ERROR 'Для тестирования с произвольными участниками печать не предусмотрена';

  SELECT FIRST 1 L2.OBJ_ID
  FROM LINKS L2
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$OUR_ORG;

  TAG_NAME = 'items';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'items::json&colon;array';
  VAL = NULL;
  SUSPEND;

  -- Печать только в ОУ, где есть назначение
  IF(V$PLAN_METHOD = 0) THEN
  BEGIN

      -- ППЭ, по помещениям

  END
  ELSE IF(V$PLAN_METHOD = 1) THEN
  BEGIN

      -- ППЭ, по коллективам

  END
  ELSE
  BEGIN

      -- По коллективам как есть
      FOR
          SELECT DISTINCT LPG.PARENT_ID, LPG.PARENT_TYPE_ID, C.CAPTION
          FROM UT_EXAM_PERSON_ASSN PA
          JOIN LINKS LPG ON LPG.OBJ_ID = PA.PERSON_ID AND LPG.PARENT_TYPE_ID IN (2, 9, 125, 187) AND LPG.DATE_DEL IS NULL
          LEFT JOIN OBJECT_CAPTION_GET(LPG.PARENT_ID) C ON 1 = 1
          WHERE PA.DATE_DEL IS NULL AND PA.EXAM_ID = :I$EXAM_ID
          ORDER BY 2, 3
          INTO :V$GROUP_ID, :V$GROUP_TYPE, :V$NAME
      DO
      BEGIN

          TAG_NAME = 'items:r';
          VAL = NULL;
          SUSPEND;
          TAG_NAME = 'items:r:id';
          VAL = 'pg:' || V$GROUP_ID;
          SUSPEND;

          TAG_NAME = 'items:r:printed';
          VAL = 0;
          SELECT FIRST 1 1
          FROM UT_EXAM_PRINT_LOG PL
          WHERE PL.DATE_DEL IS NULL AND PL.EXAM_ID = :I$EXAM_ID AND PL.REF_ID = :V$GROUP_ID AND PL.EVENT_TYPE = 1
          INTO :VAL;
          SUSPEND;

          TAG_NAME = 'items:r:title';
          VAL = 'Ведомость участников: ';
          IF(V$GROUP_TYPE = 2) THEN VAL = VAL || 'Сотрудники ' || V$NAME; ELSE VAL = VAL || V$NAME;
          SUSPEND;

          FOR
              SELECT PA.PERSON_ID, LPG.OBJ_TYPE_ID, C.NAME_FULL, PA.BLANKS_PRINTED
              FROM UT_EXAM_PERSON_ASSN PA
              JOIN LINKS LPG ON LPG.OBJ_ID = PA.PERSON_ID AND LPG.PARENT_ID = :V$GROUP_ID AND LPG.DATE_DEL IS NULL
              LEFT JOIN UT_PERSON_DESC(LPG.OBJ_ID) C ON 1 = 1
              WHERE PA.DATE_DEL IS NULL AND PA.EXAM_ID = :I$EXAM_ID
              ORDER BY 3
              INTO :V$OBJ_ID, :V$OBJ_TYPE_ID, :V$NAME, :V$PRINTED
          DO
          BEGIN

              TAG_NAME = 'items:r';
              VAL = NULL;
              SUSPEND;
              TAG_NAME = 'items:r:id';
              VAL = 'person:' || V$OBJ_ID;
              SUSPEND;
              TAG_NAME = 'items:r:printed';
              VAL = V$PRINTED;
              SUSPEND;
              TAG_NAME = 'items:r:title';
              VAL = 'Бланки участника: ' || V$NAME;
              SUSPEND;

          END

      END

  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_BLANK_CONFIRM (
    I$EXAM_ID BIGINT,
    I$BLANK_ID BIGINT,
    I$BLANK_TYPE VARCHAR(100),
    I$USER_ID VARCHAR(40))
RETURNS (
    STUB INTEGER)
AS
declare variable V$STATE integer;
declare variable V$USER_ID bigint;
begin

  IF(I$USER_ID = 'Веб-администратор') THEN V$USER_ID = 1; ELSE V$USER_ID = CAST(I$USER_ID AS BIGINT);

  -- Проверяем статус
  SELECT D.EXAM_STATE
  FROM UT_EXAM_DATES D
  WHERE D.DATE_DEL IS NULL AND D.OBJ_ID = :I$EXAM_ID
  INTO :V$STATE;

  IF(V$STATE IS NULL) THEN EXCEPTION DATA_ERROR 'Тестирование не найдено или было удалено';
  IF(V$STATE <= 500 OR V$STATE >= 1000) THEN EXCEPTION DATA_ERROR 'Тестирование не найдено или было удалено';

  -- Бланки ответов
  IF(I$BLANK_TYPE = 'person:') THEN
  BEGIN

      UPDATE UT_EXAM_PERSON_ASSN PA
      SET BLANKS_PRINTED = 1
      WHERE PA.EXAM_ID = :I$EXAM_ID AND PA.PERSON_ID = :I$BLANK_ID AND PA.DATE_DEL IS NULL;

  END
  -- Ведомость на коллектив - тут только через журнал событий
  ELSE IF(I$BLANK_TYPE = 'pg:') THEN
  BEGIN
      --
  END
  ELSE EXCEPTION DATA_ERROR 'Неизвестный тип бланка';

  INSERT INTO UT_EXAM_PRINT_LOG
  (EXAM_ID, REF_ID, USER_ID, EVENT_TYPE)
  VALUES (:I$EXAM_ID, :I$BLANK_ID, :V$USER_ID, 1);

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_CHOOSE_ASSN (
    I$PERIOD_ID BIGINT,
    I$PARENT_ID BIGINT,
    I$PAGE SMALLINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$USER_TYPE SMALLINT;
DECLARE VARIABLE V$TEACHER_ID BIGINT;
DECLARE VARIABLE V$DB_LEVEL SMALLINT;
DECLARE VARIABLE V$PERIOD_YEAR INTEGER;
DECLARE VARIABLE V$CURRENT_YEAR INTEGER;
DECLARE VARIABLE V$ID BIGINT;
DECLARE VARIABLE V$NAME VARCHAR(1000);
DECLARE VARIABLE V$TYPE BIGINT;
DECLARE VARIABLE V$SUBJECT_ID BIGINT;
DECLARE VARIABLE V$SUBJECT_NAME VARCHAR(1000);
DECLARE VARIABLE V$SUBJECT_CODE VARCHAR(100);
DECLARE VARIABLE V$DATE VARCHAR(20);
DECLARE VARIABLE V$METHOD INTEGER;
DECLARE VARIABLE V$EXAM_ID BIGINT;
DECLARE VARIABLE V$GRADE_TYPE BIGINT;
DECLARE VARIABLE V$STAGE_TYPE BIGINT;
DECLARE VARIABLE V$DT1 INTEGER;
DECLARE VARIABLE V$DT2 INTEGER;
DECLARE VARIABLE V$LEVEL SMALLINT;
DECLARE VARIABLE V$MASK INTEGER;
DECLARE VARIABLE V$STATE SMALLINT;
DECLARE VARIABLE V$PARENT_ID BIGINT;
DECLARE VARIABLE V$GIA_LEVEL BIGINT;
DECLARE VARIABLE V$GIA_TYPE BIGINT;
DECLARE VARIABLE V$CUST VARCHAR(2000);
DECLARE VARIABLE D DATE;
begin

  -- Идентифицируем роль пользователя
  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  SELECT USER_TYPE, OBJ_ID
  FROM USERS
  WHERE USER_ID = :I$USER_ID AND DATE_DEL IS NULL
  INTO :V$USER_TYPE, :V$TEACHER_ID;

  -- Если пользователь не является админом, классным руководителем, директором или завучем - ошибка
  IF(V$USER_TYPE NOT IN (1, 4, 5, 6, 8, 18, 20)) THEN EXCEPTION DATA_ERROR 'У данного пользователя нет доступа к назначению на тестирование';

  -- Текущий уровень базы ?
  SELECT K.KEY_VAL
  FROM KEYS K
  WHERE K.KEY_CODE = 'LEVEL'
  INTO :V$DB_LEVEL;

  -- PAGE: 0 = ГИА+ЕГЭ+демонстрационный, 1 = обычные тестирования, 2 = олимпиады
  IF(I$PAGE = 0) THEN
  BEGIN
    V$DT1 = 10;
    V$DT2 = 99;
  END
  ELSE IF(I$PAGE = 1) THEN
  BEGIN
    V$DT1 = 0;
    V$DT2 = 0;
  END
  ELSE IF(I$PAGE = 2 OR I$PAGE = 21 OR I$PAGE = 22) THEN
  BEGIN
    V$DT1 = 100;
    V$DT2 = 100;
  END

  -- Есть ли права доступа у класного руководителя к этому коллективу ?
  IF(V$USER_TYPE = 8) THEN
  BEGIN
  END

  -- I$PARENT_ID - учебный коллектив, 2 = Сотрудники, 9-187-125 классы разных сортовв
  -- Какой контингент у выбраннного коллектива ?
  SELECT TYPE_ID
  FROM OBJECTS
  WHERE OBJ_ID = :I$PARENT_ID
  INTO :V$GRADE_TYPE;

  IF(V$GRADE_TYPE = 2) THEN
  BEGIN
    -- Сотрудники
    V$STAGE_TYPE = 21;
  END
  ELSE
  BEGIN
    -- Параллель 1...12 (12-ая параллель трактуется как 11-ая)
    SELECT V49.LISTVAL_ID
    FROM LINKS LP8
    JOIN VALL V49 ON V49.OBJ_ID = LP8.PARENT_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
    WHERE LP8.OBJ_ID = :I$PARENT_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
    INTO :V$STAGE_TYPE;

    IF(V$STAGE_TYPE >= 37 AND V$STAGE_TYPE <= 47) THEN V$STAGE_TYPE = V$STAGE_TYPE - 37 + 1;
    ELSE IF(V$STAGE_TYPE = 48) THEN V$STAGE_TYPE = 11;
    -- Курсы СПО - непонятно почему так странно ?
    ELSE IF(V$STAGE_TYPE >= 49 AND V$STAGE_TYPE <= 54) THEN V$STAGE_TYPE = 40 + V$STAGE_TYPE - 49 + 1;
  END

  -- Какой сейчас учебный период ? Старые учебные периоды делаем readonly
  SELECT CAST(LV.COST AS INTEGER)
  FROM LISTVALS LV
  WHERE LV.LISTVAL_ID = :I$PERIOD_ID
  INTO :V$PERIOD_YEAR;

  V$CURRENT_YEAR = EXTRACT(YEAR FROM CURRENT_DATE);
  IF(EXTRACT(MONTH FROM CURRENT_DATE) < 9) THEN V$CURRENT_YEAR = V$CURRENT_YEAR - 1;

  TAG_NAME = 'readonly';
  VAL = IIF(V$PERIOD_YEAR = V$CURRENT_YEAR, 0, 1);
  SUSPEND;

  -- Список учащихся - только текущие учащиеся. При выбытии все назначения должны быть обнулены
  TAG_NAME = 'persons';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'persons::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
    SELECT L10.OBJ_ID, C.NAME_FULL, L10.OBJ_TYPE_ID, V3596.VAL
    FROM LINKS L10
    LEFT JOIN CJ2_PERSON_NAME(L10.OBJ_ID) C ON 1 = 1
    -- хотелки ученика только для ГИА
    LEFT JOIN VALS V3596 ON V3596.OBJ_ID = L10.OBJ_ID AND V3596.PARAM_ID = 3596 AND V3596.IS_DEL = 0 AND :I$PAGE = 0
    WHERE L10.PARENT_ID = :I$PARENT_ID AND L10.OBJ_TYPE_ID IN (10, 126) AND L10.DATE_DEL IS NULL
    UNION
    -- Добавляем сотрудников - там где они есть
    SELECT L14.OBJ_ID, C.NAME_FULL, L14.OBJ_TYPE_ID, NULL
    FROM LINKS L14
    LEFT JOIN CJ2_PERSON_NAME(L14.OBJ_ID) C ON 1 = 1
    WHERE L14.PARENT_ID = :I$PARENT_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
    ORDER BY 2
    INTO :V$ID, :V$NAME, :V$TYPE, :V$CUST
  DO
  BEGIN
    TAG_NAME = 'persons:p';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'persons:p:id';
    VAL = V$ID;
    SUSPEND;
    TAG_NAME = 'persons:p:name';
    VAL = V$NAME;
    SUSPEND;
    TAG_NAME = 'persons:p:custom_choose';
    VAL = V$CUST;
    SUSPEND;
    -- Допуск
    TAG_NAME = 'persons:p:is_allowed';
    IF(V$TYPE = 126 OR V$TYPE = 14) THEN VAL = 1;
    ELSE
    BEGIN
      VAL = 0;
      IF(EXISTS(
        SELECT FIRST 1 1
        FROM VALL V2155
        WHERE V2155.OBJ_ID = :V$ID AND V2155.PARAM_ID = 2155 AND V2155.IS_DEL = 0 AND V2155.LISTVAL_ID = 2
      ))
      THEN VAL = 1;
    END
    SUSPEND;
  END

  -- Список тестирований - нужен фильтр по этапу
  -- олимпиады выдаем вообще всегда
  TAG_NAME = 'exams';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'exams::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
    SELECT D.OBJ_ID, D.EXAM_DAY_TYPE, D.OBJ_NAME, D.SUBJECT_ID, COALESCE(V376.VAL, 'Метапредмет'), V377.VAL, DD.VAL, D.METHOD_ID, D.H_LEVEL, D.LINK_MASK, D.EXAM_STATE
    FROM UT_EXAM_DATES D
    LEFT JOIN VALS V376 ON V376.OBJ_ID = D.SUBJECT_ID AND V376.PARAM_ID IN (376, 1751) AND V376.IS_DEL = 0
    LEFT JOIN VALS V377 ON V377.OBJ_ID = D.SUBJECT_ID AND V377.PARAM_ID IN (377, 1752) AND V377.IS_DEL = 0
    LEFT JOIN DATE2ISO(D.EXAM_DATE_START, 0) DD ON 1 = 1
    WHERE D.DATE_DEL IS NULL AND D.PLAN_METHOD_ID NOT IN (3, 4) -- кроме свободных тестирований и тестирований для журналов
      AND (D.STAGE_ID = 100 OR D.STAGE_ID = :V$STAGE_TYPE OR (D.STAGE_ID = 20 AND (:V$STAGE_TYPE <= 11 OR :V$STAGE_TYPE IN (41, 42, 43, 44, 45, 46))))
      AND (D.EXAM_DAY_TYPE >= :V$DT1 AND D.EXAM_DAY_TYPE <= :V$DT2)
      AND (D.PERIOD_ID IS NULL OR D.PERIOD_ID = :I$PERIOD_ID) -- NULL для совместимости со старыми тестированиями
      AND (D.EXAM_STATE > 0 OR :I$PAGE IN (2, 21, 22))
      AND ((D.H_LEVEL = 0 AND :I$PAGE = 2) OR (D.H_LEVEL = 1 AND :I$PAGE = 21) OR (D.H_LEVEL = 2 AND :I$PAGE = 22) OR :I$PAGE NOT IN (2, 21, 22))
    ORDER BY D.EXAM_DATE_START, D.EXAM_DAY_TYPE, D.SUBJECT_ID, D.H_LEVEL
    INTO :V$ID, :V$TYPE, :V$NAME, :V$SUBJECT_ID, :V$SUBJECT_NAME, :V$SUBJECT_CODE, :V$DATE, :V$METHOD, :V$LEVEL, :V$MASK, :V$STATE
  DO
  BEGIN
    TAG_NAME = 'exams:p';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'exams:p:id';
    VAL = V$ID;
    SUSPEND;
    TAG_NAME = 'exams:p:name';
    VAL = V$NAME;
    SUSPEND;
    TAG_NAME = 'exams:p:date';
    VAL = V$DATE;
    SUSPEND;
    TAG_NAME = 'exams:p:type';
    VAL = V$TYPE;
    SUSPEND;
    TAG_NAME = 'exams:p:method';
    VAL = V$METHOD;
    SUSPEND;
    TAG_NAME = 'exams:p:subject_id';
    VAL = V$SUBJECT_ID;
    SUSPEND;
    TAG_NAME = 'exams:p:subject_name';
    VAL = V$SUBJECT_NAME;
    SUSPEND;
    TAG_NAME = 'exams:p:subject_code';
    IF(V$SUBJECT_CODE IS NULL) THEN V$SUBJECT_CODE = SUBSTRING(V$SUBJECT_NAME FROM 1 FOR 5);
    VAL = V$SUBJECT_CODE;
    SUSPEND;
    TAG_NAME = 'exams:p:h_level';
    VAL = V$LEVEL;
    SUSPEND;
    TAG_NAME = 'exams:p:link_mask';
    VAL = V$MASK;
    SUSPEND;
    TAG_NAME = 'exams:p:state';
    VAL = V$STATE;
    SUSPEND;
  END

  -- ГИА по старой схеме хранения, id выдаем минусовые
  IF(I$PAGE = 0) THEN
  BEGIN
    SELECT FIRST 1 L.OBJ_ID
    FROM LINKS L
    JOIN VALL V742 ON V742.OBJ_ID = L.OBJ_ID AND V742.PARAM_ID = 742 AND V742.IS_DEL = 0 AND V742.LISTVAL_ID = :I$PERIOD_ID
    WHERE L.PARENT_ID = 3866 AND L.OBJ_TYPE_ID = 119 AND L.DATE_DEL IS NULL
    INTO :V$PARENT_ID;

    -- В зависимости от выбранного типа ГИА выбираем ГИА либо 9, либо 11 классов
    SELECT FIRST 1 V.LISTVAL_ID
    FROM VALL V
    WHERE V.OBJ_ID = :I$PARENT_ID AND V.PARAM_ID IN (2388, 2418, 2419) AND V.IS_DEL = 0
    INTO :V$GIA_TYPE;

    IF(V$GIA_TYPE = 11202) THEN V$GIA_TYPE = 3000; -- ГИА-9
    IF(V$GIA_TYPE = 11203) THEN V$GIA_TYPE = 3162; -- ГИА-11

    FOR
      SELECT L120.OBJ_ID, V804.VAL, V802.LISTVAL_ID, V801.LISTVAL_ID, V803.LISTVAL_ID, R.VAL
      FROM LINKS L120
      JOIN VALI V800 ON V800.OBJ_ID = L120.OBJ_ID AND V800.PARAM_ID = 800 AND V800.IS_DEL = 0
      JOIN VALL V801 ON V801.OBJ_ID = L120.OBJ_ID AND V801.PARAM_ID = 801 AND V801.IS_DEL = 0 AND V801.LISTVAL_ID = :V$GIA_TYPE
      JOIN VALL V802 ON V802.OBJ_ID = L120.OBJ_ID AND V802.PARAM_ID = 802 AND V802.IS_DEL = 0
      JOIN VALL V803 ON V803.OBJ_ID = L120.OBJ_ID AND V803.PARAM_ID = 803 AND V803.IS_DEL = 0
      JOIN VALD V804 ON V804.OBJ_ID = L120.OBJ_ID AND V804.PARAM_ID = 804 AND V804.IS_DEL = 0
      JOIN LISTVALS LV ON LV.LISTVAL_ID = V803.LISTVAL_ID
      JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
      WHERE L120.PARENT_ID = :V$PARENT_ID AND L120.OBJ_TYPE_ID = 120 AND L120.DATE_DEL IS NULL
      ORDER BY LV.SORT_ORDER, V804.VAL, V802.LISTVAL_ID
      INTO :V$ID, :D, :V$TYPE, :V$GIA_LEVEL, :V$SUBJECT_ID, :V$SUBJECT_NAME
    DO
    BEGIN
      TAG_NAME = 'exams:p';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'exams:p:id';
      VAL = - V$ID;
      SUSPEND;
      TAG_NAME = 'exams:p:name';
      VAL = V$SUBJECT_NAME;
      SUSPEND;
      TAG_NAME = 'exams:p:date';
      VAL = (SELECT VAL FROM DATE2ISO(:D, 0));
      SUSPEND;
      -- Тип дня перекодируем
      TAG_NAME = 'exams:p:type';
      IF(V$TYPE = 2996) THEN V$TYPE = 10; -- пробный
      ELSE IF(V$TYPE IN (2997, 12774)) THEN V$TYPE = 20; -- досрочный основной
      ELSE IF(V$TYPE IN (3167, 12775)) THEN V$TYPE = 30; -- досрочный резервный
      ELSE IF(V$TYPE IN (3163, 12776)) THEN V$TYPE = 40; -- основной основной
      ELSE IF(V$TYPE IN (3164, 12777)) THEN V$TYPE = 50; -- основной резервный
      ELSE IF(V$TYPE IN (3165, 12778)) THEN V$TYPE = 60; -- доп основной
      ELSE IF(V$TYPE IN (3166, 12779)) THEN V$TYPE = 70; -- доп резервный
      ELSE IF(V$TYPE IN (12781, 3168)) THEN V$TYPE = 0;  -- не ГИА, порядок тут перепутан
      ELSE V$TYPE = 0;                                   -- 12780 прочее
      VAL = V$TYPE;
      SUSPEND;
      TAG_NAME = 'exams:p:method';
      VAL = 3; -- как будто очное тестирование
      SUSPEND;
      TAG_NAME = 'exams:p:subject_id';
      VAL = V$SUBJECT_ID; -- этот id в другой плоскости
      SUSPEND;
      TAG_NAME = 'exams:p:subject_name';
      VAL = V$SUBJECT_NAME;
      SUSPEND;
      -- Конвертируем название в код
      TAG_NAME = 'exams:p:subject_code';
      V$SUBJECT_NAME = UPPER(V$SUBJECT_NAME);
      VAL = SUBSTRING(V$SUBJECT_NAME FROM 1 FOR 3);
      IF(V$SUBJECT_ID = 10878) THEN VAL = VAL || '/Б';
      ELSE IF(V$SUBJECT_ID = 2923) THEN VAL = VAL || '/П';
      ELSE IF(POSITION('УСТН' IN V$SUBJECT_NAME) > 0) THEN VAL = VAL || '/УСТ';
      ELSE IF(POSITION('ГВЭ' IN V$SUBJECT_NAME) > 0) THEN VAL = VAL || '/ГВЭ';
      SUSPEND;
      TAG_NAME = 'exams:p:h_level';
      VAL = 2;
      SUSPEND;
      TAG_NAME = 'exams:p:link_mask';
      VAL = 0;
      SUSPEND;
      TAG_NAME = 'exams:p:state';
      VAL = 100; -- Планирование участников
      SUSPEND;
    END
  END

  -- Назначения
  TAG_NAME = 'assns';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'assns::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
    SELECT PA.PERSON_ID, PA.EXAM_ID, PA.LEVEL_ID
    FROM LINKS P
    JOIN UT_EXAM_PERSON_ASSN PA ON PA.PERSON_ID = P.OBJ_ID AND PA.DATE_DEL IS NULL
    JOIN UT_EXAM_DATES D ON D.OBJ_ID = PA.EXAM_ID AND D.DATE_DEL IS NULL
    WHERE P.PARENT_ID = :I$PARENT_ID AND P.OBJ_TYPE_ID IN (10, 126, 14) AND P.DATE_DEL IS NULL
      AND (D.STAGE_ID = 100 OR D.STAGE_ID = :V$STAGE_TYPE OR (D.STAGE_ID = 20 AND (:V$STAGE_TYPE <= 11 OR :V$STAGE_TYPE IN (41, 42, 43, 44, 45, 46))))
      AND (D.EXAM_DAY_TYPE >= :V$DT1 AND D.EXAM_DAY_TYPE <= :V$DT2)
      AND (D.PERIOD_ID IS NULL OR D.PERIOD_ID = :I$PERIOD_ID) -- NULL для совместимости со старыми тестированиями
    INTO :V$ID, :V$EXAM_ID, :V$MASK
  DO
  BEGIN
    TAG_NAME = 'assns:p';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'assns:p:person_id';
    VAL = V$ID;
    SUSPEND;
    TAG_NAME = 'assns:p:exam_id';
    VAL = V$EXAM_ID;
    SUSPEND;
    -- level - только для олимпиад
    TAG_NAME = 'assns:p:level';
    VAL = V$MASK;
    SUSPEND;
  END

  IF(I$PAGE = 0) THEN
  BEGIN
    -- Пока оставляем схему выборки, но надо поменять на PERSON_MOVEMENTS
    FOR
      SELECT P.OBJ_ID, L120.OBJ_ID
      FROM LINKS P
      JOIN LINKS L120 ON L120.PARENT_ID = P.OBJ_ID AND L120.OBJ_TYPE_ID = 120 AND L120.DATE_DEL IS NULL
      JOIN LINKS LP119 ON LP119.OBJ_ID = L120.OBJ_ID AND LP119.PARENT_ID = :V$PARENT_ID AND LP119.DATE_DEL IS NULL
      WHERE P.PARENT_ID = :I$PARENT_ID AND P.OBJ_TYPE_ID IN (10, 126) AND P.DATE_DEL IS NULL
      INTO :V$ID, :V$EXAM_ID
    DO
    BEGIN
      TAG_NAME = 'assns:p';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'assns:p:person_id';
      VAL = V$ID;
      SUSPEND;
      TAG_NAME = 'assns:p:exam_id';
      VAL = - V$EXAM_ID;
      SUSPEND;
      -- level - только для олимпиад
      TAG_NAME = 'assns:p:level';
      VAL = NULL;
      SUSPEND;
    END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_CHOOSE_REPORT (
    I$PERIOD_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$PAGE INTEGER,
    I$USER_ID VARCHAR(40))
RETURNS (
    VAL VARCHAR(4000))
AS
DECLARE VARIABLE V$CALLER_TYPE BIGINT;
DECLARE VARIABLE V$PARENT_ID BIGINT;
DECLARE VARIABLE V$PUPIL VARCHAR(400);
DECLARE VARIABLE N INTEGER;
begin

  SELECT TYPE_ID
  FROM OBJECTS
  WHERE OBJ_ID = :I$OBJ_ID
  INTO :V$CALLER_TYPE;

  -- Таблица стилей
  VAL = '<!DOCTYPE html>';
  VAL = VAL || '<html lang="ru">';
  VAL = VAL || '<head>';
  VAL = VAL || '<meta charset="utf-8" />';
  VAL = VAL || '</head>';
  VAL = VAL || '<body>';
  SUSPEND;

  VAL = '<h2 class="ui header left aligned">Обучающиеся выпускных классов, не записанные ни на один экзамен ГИА</h2>';
  SUSPEND;

  -- Заголовок таблицы
  VAL = '<table class="ui striped table" cellspacing="0" cellpadding="25">';
  SUSPEND;

  VAL = '<tr class="ui left aligned">';
  VAL = VAL || '<th class="ui left aligned">№№</th>';
  VAL = VAL || '<th>ФИО, класс обучающегося</th>';
  VAL = VAL || '</tr>';
  SUSPEND;

  SELECT FIRST 1 L.OBJ_ID
  FROM LINKS L
  JOIN VALL V742 ON V742.OBJ_ID = L.OBJ_ID AND V742.PARAM_ID = 742 AND V742.IS_DEL = 0 AND V742.LISTVAL_ID = :I$PERIOD_ID
  WHERE L.PARENT_ID = 3866 AND L.OBJ_TYPE_ID = 119 AND L.DATE_DEL IS NULL
  INTO :V$PARENT_ID;

  N = 0;
  FOR
    SELECT P.SCAPTION
    FROM LINKS L10
    LEFT JOIN OBJECT_CAPTION_GET(L10.OBJ_ID) P ON 1 = 1
    LEFT JOIN VAL_GET(L10.PARENT_ID, 555, 0) ST ON 1 = 1
    WHERE L10.OBJ_TYPE_ID IN (10, 126) AND L10.PARENT_TYPE_ID IN (9, 125) AND L10.DATE_DEL IS NULL
      AND (ST.V LIKE '9%' OR ST.V LIKE '11%')
      AND L10.OBJ_ID NOT IN
      (SELECT DISTINCT(L.OBJ_ID)
       FROM LINKS L
       JOIN LINKS L120 ON L120.PARENT_ID = L.OBJ_ID AND L120.OBJ_TYPE_ID = 120 AND L120.DATE_DEL IS NULL
       JOIN VALL V803 ON V803.OBJ_ID = L120.OBJ_ID AND V803.PARAM_ID = 803 AND V803.IS_DEL = 0 AND V803.LISTVAL_ID NOT IN (10876, 10877)   --итоговое сочинение/изложение
       JOIN LINKS LP119 ON LP119.OBJ_ID = L120.OBJ_ID AND LP119.PARENT_ID = :V$PARENT_ID AND LP119.DATE_DEL IS NULL
       WHERE L.OBJ_TYPE_ID IN (10, 126) AND L.PARENT_TYPE_ID IN (9, 125) AND L.DATE_DEL IS NULL
      )
    ORDER BY ST.V, P.SCAPTION
    INTO :V$PUPIL
  DO
  BEGIN
    N = N + 1;
    VAL = '<tr class="ui left aligned">';
    VAL = VAL || '<td class="ui left aligned">' || N || '</td>';
    VAL = VAL || '<td>' || V$PUPIL || '</td>';
    VAL = VAL || '</tr>';
  SUSPEND;
  END

  -- Закрываем таблицу
  VAL = '</table></body></html>';
  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_CHOOSE_SET (
    I$PERSON_ID BIGINT,
    I$EXAM_ID BIGINT,
    I$SUBJECT_ID BIGINT,
    I$LEVEL SMALLINT,
    I$STATE INTEGER,
    I$USER_ID VARCHAR(40))
RETURNS (
    OBJ_ID BIGINT,
    STATE_ID INTEGER)
AS
DECLARE VARIABLE V$EXAM_STATE INTEGER;
DECLARE VARIABLE V$EXAM_DAY_TYPE INTEGER;
DECLARE VARIABLE V$TYPE_ID BIGINT;
DECLARE VARIABLE V$PARAM_ID BIGINT;
DECLARE VARIABLE V$SUBJECT_ID BIGINT;
DECLARE VARIABLE V$YEAR INTEGER;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$EXAM_ID BIGINT;
DECLARE VARIABLE V$PERIOD_ID BIGINT;
DECLARE VARIABLE V$EXAM_YEAR INTEGER;
DECLARE VARIABLE V$LEVEL INTEGER;
DECLARE VARIABLE V$DB_LEVEL SMALLINT;
DECLARE VARIABLE V$OU_ID BIGINT;
DECLARE VARIABLE V$AREA_ID BIGINT;
DECLARE VARIABLE V$PARENT_ID BIGINT;
DECLARE VARIABLE V$YEAR_ID BIGINT;
DECLARE VARIABLE V$LINK_ID BIGINT;
DECLARE VARIABLE D DATE;
DECLARE VARIABLE D2 DATE;
DECLARE VARIABLE V$ALLOW BIGINT;
DECLARE VARIABLE V$DE DATE;
DECLARE VARIABLE V$GRAD_TYPE BIGINT;
DECLARE VARIABLE V$USERTYPE SMALLINT;
begin

  -- I$EXAM_ID: NULL = допуск к экзаменам, либо удаление назначения ГИА (только в паре с SUBJECT_ID)
  -- SUBJECT_ID: ID предмета по которому снимаем назначение ГИА, если I$EXAM_ID пустой
  -- I$STATE: 0 = снять назначение, 1 = установить назначение

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = -1;

  -- Только на школьном уровне !
  SELECT KEY_VAL
  FROM KEYS
  WHERE KEY_CODE = 'LEVEL'
  INTO :V$DB_LEVEL;

  IF(V$DB_LEVEL > 1) THEN EXCEPTION DATA_ERROR 'Изменять назначение на тестирование можно только на уровне образовательной организации';

  SELECT FIRST 1 U.USER_TYPE
  FROM USERS U
  WHERE U.USER_ID = ABS(:I$USER_ID)
  INTO :V$USERTYPE;

  V$YEAR = EXTRACT(YEAR FROM CURRENT_DATE);
  IF(EXTRACT(MONTH FROM CURRENT_DATE) < 9) THEN V$YEAR = V$YEAR - 1;

  SELECT TYPE_ID
  FROM OBJECTS
  WHERE OBJ_ID = :I$PERSON_ID
  INTO :V$TYPE_ID;

  IF(V$TYPE_ID NOT IN (10, 126, 14)) THEN EXCEPTION DATA_ERROR 'Недопустимая персона';

  IF(I$EXAM_ID IS NULL AND I$SUBJECT_ID IS NULL) THEN
  BEGIN

    -- Установка допуска через I$STATE, только учащиеся
    IF(V$TYPE_ID = 10) THEN V$PARAM_ID = 2155;
    ELSE IF(V$TYPE_ID = 126) THEN V$PARAM_ID = 2160;

    IF(V$PARAM_ID IS NOT NULL) THEN
    BEGIN
      SELECT BLOB_ID
      FROM VAL_ADD(:V$PARAM_ID, :I$PERSON_ID, IIF(:I$STATE = 0, 3, 2))
      INTO :OBJ_ID;

      STATE_ID = I$STATE;
    END
    ELSE STATE_ID = 1;

  END
  ELSE IF(I$STATE = 0 AND ((I$EXAM_ID IS NULL AND I$SUBJECT_ID IS NOT NULL) OR I$EXAM_ID < 0)) THEN
  BEGIN
    -- Снятие назначения ГИА по этому предмету
    -- Только в последнем загруженном пакете - сверить даты
    -- Здесь пока реализация только для старой схемы, но синхронно надо и для новой прописать
    SELECT FIRST 1 L.OBJ_ID, LV.LISTVAL_ID, LV.COST
    FROM LINKS L
    JOIN VALL V742 ON V742.OBJ_ID = L.OBJ_ID AND V742.PARAM_ID = 742 AND V742.IS_DEL = 0
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V742.LISTVAL_ID
    WHERE L.PARENT_ID = 3866 AND L.OBJ_TYPE_ID = 119 AND L.DATE_DEL IS NULL
    ORDER BY LV.COST DESC
    INTO :V$PARENT_ID, :V$YEAR_ID, :V$EXAM_YEAR;

    IF(V$EXAM_YEAR <> V$YEAR) THEN EXCEPTION DATA_ERROR 'Нельзя менять назначения вне текущего учебного года';

    SELECT FIRST 1 LP10.LINK_ID, L120.OBJ_ID, V804.VAL
    FROM LINKS L120
    JOIN VALL V803 ON V803.OBJ_ID = L120.OBJ_ID AND V803.PARAM_ID = 803 AND V803.IS_DEL = 0 AND V803.LISTVAL_ID = :I$SUBJECT_ID
    JOIN VALD V804 ON V804.OBJ_ID = L120.OBJ_ID AND V804.PARAM_ID = 804 AND V804.IS_DEL = 0
    JOIN LINKS LP10 ON LP10.OBJ_ID = L120.OBJ_ID AND LP10.PARENT_ID = :I$PERSON_ID AND LP10.DATE_DEL IS NULL
    WHERE L120.PARENT_ID = :V$PARENT_ID AND L120.OBJ_TYPE_ID = 120 AND L120.DATE_DEL IS NULL
    INTO :V$LINK_ID, :V$EXAM_ID, :D;

    IF(V$LINK_ID IS NOT NULL) THEN
    BEGIN
      UPDATE LINKS
      SET DATE_DEL = CURRENT_TIMESTAMP
      WHERE LINK_ID = :V$LINK_ID;

      -- Внести запись в лог
      INSERT INTO HISTVALS
      (TABLE_NAME, OBJ_ID, PARAM_ID, OLD_VAL, USER_ID)
      VALUES ('GIA', :I$PERSON_ID, :V$EXAM_ID, (SELECT RESULT FROM DATE2STR(:D)) || ' ' || (SELECT VAL FROM LISTVAL_TEXT(:I$SUBJECT_ID)), :I$USER_ID);
    END
  END
  ELSE
  BEGIN

    -- Только текущий учебный год !
    IF(I$EXAM_ID < 0) THEN
    BEGIN
      -- Старая схема, I$STATE = 0 тут быть не может - она уже учтена выше
      -- Смотрим было ли другое назначение на тот же предмет ?
      I$EXAM_ID = ABS(I$EXAM_ID);

      SELECT FIRST 1 L.OBJ_ID, LV.LISTVAL_ID, LV.COST
      FROM LINKS L
      JOIN VALL V742 ON V742.OBJ_ID = L.OBJ_ID AND V742.PARAM_ID = 742 AND V742.IS_DEL = 0
      JOIN LISTVALS LV ON LV.LISTVAL_ID = V742.LISTVAL_ID
      WHERE L.PARENT_ID = 3866 AND L.OBJ_TYPE_ID = 119 AND L.DATE_DEL IS NULL
      ORDER BY LV.COST DESC
      INTO :V$PARENT_ID, :V$YEAR_ID, :V$EXAM_YEAR;

      IF(V$EXAM_YEAR <> V$YEAR) THEN EXCEPTION DATA_ERROR 'Нельзя менять назначения вне текущего учебного года';

      SELECT FIRST 1 V3598.LISTVAL_ID
      FROM LINKS L2
      JOIN VALL V3598 ON V3598.OBJ_ID = L2.OBJ_ID AND V3598.PARAM_ID = 3598 AND V3598.IS_DEL = 0
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      INTO :V$ALLOW;

      SELECT FIRST 1 LP10.LINK_ID, L120.OBJ_ID, V804.VAL
      FROM LINKS L120
      JOIN VALL V803 ON V803.OBJ_ID = L120.OBJ_ID AND V803.PARAM_ID = 803 AND V803.IS_DEL = 0 AND V803.LISTVAL_ID = :I$SUBJECT_ID
      JOIN VALD V804 ON V804.OBJ_ID = L120.OBJ_ID AND V804.PARAM_ID = 804 AND V804.IS_DEL = 0
      JOIN LINKS LP10 ON LP10.OBJ_ID = L120.OBJ_ID AND LP10.PARENT_ID = :I$PERSON_ID AND LP10.DATE_DEL IS NULL
      WHERE L120.PARENT_ID = :V$PARENT_ID AND L120.OBJ_TYPE_ID = 120 AND L120.DATE_DEL IS NULL AND L120.OBJ_ID <> :I$EXAM_ID
      INTO :V$LINK_ID, :V$EXAM_ID, :D;

      SELECT FIRST 1 V.LISTVAL_ID
      FROM LINKS LP9
      JOIN VALL V ON V.OBJ_ID = LP9.PARENT_ID AND V.PARAM_ID IN (2388, 2418, 2419) AND V.IS_DEL = 0
      WHERE LP9.OBJ_ID = :I$PERSON_ID AND LP9.PARENT_TYPE_ID IN (9, 125, 157) AND LP9.DATE_DEL IS NULL
      INTO :V$GRAD_TYPE;

      IF(V$ALLOW IS NULL OR V$ALLOW = 18743) THEN EXCEPTION DATA_ERROR 'Запись на ГИА еще не открыта или не настроена';
      IF(V$ALLOW = 18745 AND V$USERTYPE NOT IN (1, 5, 6)) THEN EXCEPTION DATA_ERROR 'Запись на ГИА разрешена только руководству';
      IF(V$ALLOW = 18746) THEN EXCEPTION DATA_ERROR 'Запись на ГИА прекращена';

      IF(V$GRAD_TYPE = 11202) THEN V$DE = '01.03.' || (V$EXAM_YEAR + 1); ELSE V$DE = '01.02.' || (V$EXAM_YEAR + 1);
      IF(CURRENT_DATE >= V$DE) THEN EXCEPTION DATA_ERROR 'Изменения в записи на ГИА не допускается после 1 февраля (1 марта)';

      -- Если было - снимаем его
      IF(V$LINK_ID IS NOT NULL) THEN
      BEGIN
        UPDATE LINKS
        SET DATE_DEL = CURRENT_TIMESTAMP
        WHERE LINK_ID = :V$LINK_ID;
      END

      -- Нет ли уже назначения на этот экзамен. Если есть, и мы удалили еще одно - все равно обойдемся без лога
      IF(EXISTS(
        SELECT FIRST 1 1
        FROM LINKS L120
        WHERE L120.PARENT_ID = :I$PERSON_ID AND L120.OBJ_ID = :I$EXAM_ID AND L120.DATE_DEL IS NULL
      ))
      THEN
        EXIT;

      SELECT FIRST 1 V804.VAL
      FROM LINKS L120
      JOIN VALL V803 ON V803.OBJ_ID = L120.OBJ_ID AND V803.PARAM_ID = 803 AND V803.IS_DEL = 0 AND V803.LISTVAL_ID = :I$SUBJECT_ID
      JOIN VALD V804 ON V804.OBJ_ID = L120.OBJ_ID AND V804.PARAM_ID = 804 AND V804.IS_DEL = 0
      WHERE L120.PARENT_ID = :V$PARENT_ID AND L120.OBJ_TYPE_ID = 120 AND L120.DATE_DEL IS NULL AND L120.OBJ_ID = :I$EXAM_ID
      INTO :D2;

      IF(D2 IS NULL) THEN EXCEPTION DATA_ERROR 'Назначаемый экзамен не найден, относится к другому учебному году или предмету';

      -- Регистрируем
      INSERT INTO LINKS (PARENT_ID, OBJ_ID, DATE_INS) VALUES (:I$PERSON_ID, :I$EXAM_ID, CURRENT_TIMESTAMP);

      INSERT INTO HISTVALS
      (TABLE_NAME, OBJ_ID, PARAM_ID, OPT_ID, VAL, OLD_VAL, USER_ID)
      VALUES ('GIA', :I$PERSON_ID, :I$EXAM_ID, :V$EXAM_ID, (SELECT RESULT FROM DATE2STR(:D2)) || ' ' || (SELECT VAL FROM LISTVAL_TEXT(:I$SUBJECT_ID)),
        (SELECT RESULT FROM DATE2STR(:D)) || ' ' || (SELECT VAL FROM LISTVAL_TEXT(:I$SUBJECT_ID)), :I$USER_ID);
    END
    ELSE
    BEGIN
      -- Новая схема, пока не действует
      SELECT D.EXAM_STATE, D.EXAM_DAY_TYPE, D.SUBJECT_ID, D.PERIOD_ID, LV.COST
      FROM UT_EXAM_DATES D
      LEFT JOIN LISTVALS LV ON LV.LISTVAL_ID = D.PERIOD_ID
      WHERE D.OBJ_ID = :I$EXAM_ID AND D.DATE_DEL IS NULL
      INTO :V$EXAM_STATE, :V$EXAM_DAY_TYPE, :V$SUBJECT_ID, :V$PERIOD_ID, :V$EXAM_YEAR;

      IF(V$EXAM_STATE IS NULL) THEN EXCEPTION DATA_ERROR 'Экзамен (текстирование) не найден или был удален другим пользователем';
      IF(V$EXAM_STATE >= 700) THEN EXCEPTION DATA_ERROR 'Нельзя менять назначения на этапе сбора результатов и далее';
      IF(V$EXAM_YEAR <> V$YEAR) THEN EXCEPTION DATA_ERROR 'Нельзя менять назначения вне текущего учебного года';

      IF(I$STATE = 0) THEN
      BEGIN
        -- Нет ли назначения в ППЭ ?!!!
        -- Нет ли напечатанных бланков ?!!!
        IF(EXISTS(
          SELECT FIRST 1 1
          FROM UT_EXAM_PERSON_ASSN PA
          WHERE PA.EXAM_ID = :I$EXAM_ID AND PA.PERSON_ID = :I$PERSON_ID AND PA.DATE_DEL IS NULL AND PA.BLANKS_PRINTED <> 0
        ))
        THEN
          EXCEPTION DATA_ERROR 'Бланки по данному участнику уже распечатаны, отменить назначение нельзя';

        UPDATE UT_EXAM_PERSON_ASSN PA
        SET PA.DATE_DEL = CURRENT_TIMESTAMP
        WHERE PA.EXAM_ID = :I$EXAM_ID AND PA.PERSON_ID = :I$PERSON_ID AND PA.DATE_DEL IS NULL;
      END
      ELSE
      BEGIN
        IF(V$EXAM_DAY_TYPE <> 0) THEN
        BEGIN
          -- Проверяем другие назначения на ГИА в том же учебном году
          -- Ошибочная ветка, DAY_TYPE 0 может быть также и для ГИА, с этим надо что-то сделать
          FOR
            SELECT PA.OBJ_ID, PA.EXAM_ID
            FROM UT_EXAM_PERSON_ASSN PA
            JOIN UT_EXAM_DATES D ON D.OBJ_ID = PA.EXAM_ID AND D.DATE_DEL IS NULL AND D.SUBJECT_ID = :V$SUBJECT_ID AND D.PERIOD_ID = :V$PERIOD_ID
            WHERE PA.DATE_DEL IS NULL AND PA.PERSON_ID = :I$PERSON_ID AND PA.EXAM_ID <> :I$EXAM_ID
            INTO :V$OBJ_ID, :V$EXAM_ID
          DO
          BEGIN
            -- Нет ли назначения в ППЭ ?!!!
            UPDATE UT_EXAM_PERSON_ASSN PA
            SET PA.DATE_DEL = CURRENT_TIMESTAMP
            WHERE PA.OBJ_ID = :V$OBJ_ID AND PA.DATE_DEL IS NULL;
          END
        END

        -- Если назначение уже есть - ничего не делаем, но при необходимости корректируем уровень
        SELECT FIRST 1 PA.OBJ_ID, PA.LEVEL_ID
        FROM UT_EXAM_PERSON_ASSN PA
        WHERE PA.EXAM_ID = :I$EXAM_ID AND PA.PERSON_ID = :I$PERSON_ID AND DATE_DEL IS NULL
        INTO :OBJ_ID, :V$LEVEL;

        IF(OBJ_ID IS NULL) THEN
        BEGIN
          SELECT OU_ID, AREA_ID
          FROM UT_PERSON_DESC(:I$PERSON_ID)
          INTO :V$OU_ID, :V$AREA_ID;

          IF(V$OU_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не удалось идентифицировать организацию для участника тестирования';
          IF(V$AREA_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не удалось идентифицировать район. Проверьте, указан ли район в настройках организации';

          INSERT INTO UT_EXAM_PERSON_ASSN
          (EXAM_ID, PERSON_ID, LEVEL_ID, OU_ID, AREA_ID)
          VALUES (:I$EXAM_ID, :I$PERSON_ID, :I$LEVEL, :V$OU_ID, :V$AREA_ID)
          RETURNING OBJ_ID INTO :OBJ_ID;
        END
        ELSE IF((I$LEVEL IS NULL AND V$LEVEL IS NOT NULL) OR (I$LEVEL IS NOT NULL AND V$LEVEL IS NULL) OR V$LEVEL <> I$LEVEL) THEN
        BEGIN
          UPDATE UT_EXAM_PERSON_ASSN
          SET LEVEL_ID = :I$LEVEL
          WHERE OBJ_ID = :OBJ_ID;
        END
      END
    END

    -- Тут чисто для красоты
    STATE_ID = 0;

  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_CHOOSE_TREE (
    I$PERIOD_ID BIGINT,
    I$LEVEL INTEGER,
    I$PARENT_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$USER_TYPE SMALLINT;
DECLARE VARIABLE V$TEACHER_ID BIGINT;
DECLARE VARIABLE V$DB_LEVEL SMALLINT;
DECLARE VARIABLE V$YEAR INTEGER;
DECLARE VARIABLE V$ID BIGINT;
DECLARE VARIABLE V$TYPE BIGINT;
DECLARE VARIABLE V$NAME VARCHAR(1000);
DECLARE VARIABLE V$FLAG SMALLINT;
DECLARE VARIABLE V$ORDER DOUBLE PRECISION;
begin

  -- Идентифицируем роль пользователя
  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  SELECT USER_TYPE, OBJ_ID
  FROM USERS
  WHERE USER_ID = :I$USER_ID AND DATE_DEL IS NULL
  INTO :V$USER_TYPE, :V$TEACHER_ID;

  -- Если пользователь не является админом, классным руководителем, директором или завучем - ошибка
  -- Добавлено: тестолог-организатор и специалист по работе с обучающимися
  IF(V$USER_TYPE NOT IN (1, 4, 5, 6, 8, 18, 20)) THEN EXCEPTION DATA_ERROR 'У данного пользователя нет доступа к назначению на тестирование';

  -- Текущий уровень базы ?
  SELECT K.KEY_VAL
  FROM KEYS K
  WHERE K.KEY_CODE = 'LEVEL'
  INTO :V$DB_LEVEL;

  -- Запрошен корень дерева
  IF(I$LEVEL IS NULL OR I$PARENT_ID IS NULL) THEN
  BEGIN

      TAG_NAME = 'db_level';
      VAL = V$DB_LEVEL;
      SUSPEND;

      -- Уровень пользователя (0 = регион ... 3 = классный руководитель), в корне дерева выбираем на 1 уровень меньше уровня пользователя
      TAG_NAME = 'level';
      IF(V$USER_TYPE = 8) THEN I$LEVEL = 3; ELSE I$LEVEL = 3 - V$DB_LEVEL;
      VAL = I$LEVEL;
      I$LEVEL = I$LEVEL - 1;
      SUSPEND;

      -- Идентифицируем корневой объект пользователя
      IF(I$LEVEL = -1) THEN
        I$PARENT_ID = NULL;
      ELSE IF(I$LEVEL = 0) THEN
        I$PARENT_ID = (SELECT FIRST 1 OBJ_ID FROM LINKS WHERE (PARENT_ID IS NULL OR PARENT_TYPE_ID = 112) AND OBJ_TYPE_ID = 111 AND DATE_DEL IS NULL);
      ELSE IF(I$LEVEL >= 1) THEN
        I$PARENT_ID = (SELECT FIRST 1 OBJ_ID FROM LINKS WHERE (PARENT_ID IS NULL OR PARENT_TYPE_ID IN (111, 112)) AND OBJ_TYPE_ID = 2 AND DATE_DEL IS NULL);

      TAG_NAME = 'readonly';
      VAL = '0'; -- !!!
      SUSPEND;

      -- Справочник учебных периодов
      V$YEAR = EXTRACT(YEAR FROM CURRENT_DATE);
      IF(EXTRACT(MONTH FROM CURRENT_DATE) < 8) THEN V$YEAR = V$YEAR - 1;

      TAG_NAME = 'periods::json&colon;array';
      VAL = '1';
      SUSPEND;
      FOR
          SELECT LV.LISTVAL_ID, R.VAL, IIF(LV.COST = :V$YEAR, 1, 0)
          FROM LISTVALS LV
          JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
          WHERE LV.LIST_ID = 29 AND LV.IS_DEL = 0 AND LV.COST < (:V$YEAR + 1)
          ORDER BY LV.COST
          INTO :V$ID, :V$NAME, :V$FLAG
      DO
      BEGIN
          TAG_NAME = 'periods:p';
          VAL = NULL;
          SUSPEND;
          TAG_NAME = 'periods:p:id';
          VAL = V$ID;
          SUSPEND;
          TAG_NAME = 'periods:p:name';
          VAL = V$NAME;
          SUSPEND;
          TAG_NAME = 'periods:p:is_active';
          VAL = V$FLAG;
          SUSPEND;
      END

      -- Справочников типов дней ГИА/ЕГЭ
      TAG_NAME = 'day_types::json&colon;array';
      VAL = '1';
      SUSPEND;
      FOR
          SELECT OBJ_ID, OBJ_NAME
          FROM UT_EXAM_DAY_TYPES
          WHERE IS_DEL = 0
          ORDER BY 1
          INTO :V$ID, :V$NAME
      DO
      BEGIN
          TAG_NAME = 'day_types:p';
          VAL = NULL;
          SUSPEND;
          TAG_NAME = 'day_types:p:id';
          VAL = V$ID;
          SUSPEND;
          TAG_NAME = 'day_types:p:name';
          VAL = V$NAME;
          SUSPEND;
      END

  END
  ELSE IF(I$LEVEL < (3 - V$DB_LEVEL)) THEN EXCEPTION DATA_ERROR 'Нельзя запросить уровень выше текущего';

  -- Запрошен один из подкаталогов
  TAG_NAME = 'items::json&colon;array';
  VAL = '1';
  SUSPEND;

  IF(I$LEVEL = -1) THEN
  BEGIN
      -- Уровень региона
      FOR
          SELECT L.OBJ_ID, C.CAPTION, L.OBJ_TYPE_ID
          FROM LINKS L
          LEFT JOIN OBJECT_CAPTION_GET(L.OBJ_ID) C ON 1 = 1
          WHERE L.PARENT_ID IS NULL AND L.OBJ_TYPE_ID = 112 AND L.DATE_DEL IS NULL
          ORDER BY 2
          INTO :V$ID, :V$NAME, :V$TYPE
      DO
      BEGIN
          TAG_NAME = 'items:p';
          VAL = NULL;
          SUSPEND;
          TAG_NAME = 'items:p:id';
          VAL = V$ID;
          SUSPEND;
          TAG_NAME = 'items:p:name';
          VAL = V$NAME;
          SUSPEND;
          TAG_NAME = 'items:p:type';
          VAL = V$TYPE;
          SUSPEND;
          TAG_NAME = 'items:p:level';
          VAL = 0;
          SUSPEND;
          TAG_NAME = 'items:p:has_children';
          IF(EXISTS(SELECT FIRST 1 1 FROM LINKS WHERE PARENT_ID = :V$ID AND OBJ_TYPE_ID IN (2, 111) AND DATE_DEL IS NULL)) THEN VAL = 1; ELSE VAL = 0;
          SUSPEND;
      END
  END
  ELSE IF(I$LEVEL = 0) THEN
  BEGIN
      -- Список районов или ОУ ?
      FOR
          SELECT L.OBJ_ID, C.CAPTION, L.OBJ_TYPE_ID
          FROM LINKS L
          LEFT JOIN OBJECT_CAPTION_GET(L.OBJ_ID) C ON 1 = 1
          WHERE (L.PARENT_ID = :I$PARENT_ID OR L.PARENT_ID IS NULL) AND L.OBJ_TYPE_ID IN (111, 2) AND L.DATE_DEL IS NULL
          ORDER BY 2
          INTO :V$ID, :V$NAME, :V$TYPE
      DO
      BEGIN
          TAG_NAME = 'items:p';
          VAL = NULL;
          SUSPEND;
          TAG_NAME = 'items:p:id';
          VAL = V$ID;
          SUSPEND;
          TAG_NAME = 'items:p:name';
          VAL = V$NAME;
          SUSPEND;
          TAG_NAME = 'items:p:type';
          VAL = V$TYPE;
          SUSPEND;
          TAG_NAME = 'items:p:level';
          IF(V$TYPE = 111) THEN VAL = 1; ELSE VAL = 2;
          SUSPEND;
          TAG_NAME = 'items:p:has_children';
          IF(V$TYPE = 2) THEN
          BEGIN
              IF(EXISTS(
                  SELECT FIRST 1 1
                  FROM LINKS L7
                  JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
                  JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 125, 187) AND L9.DATE_DEL IS NULL
                  LEFT JOIN VALR V53 ON V53.OBJ_ID = L9.OBJ_ID AND V53.PARAM_ID = 53 AND V53.IS_DEL = 0
                  WHERE L7.PARENT_ID = :V$ID AND L7.OBJ_TYPE_ID IN (7, 502) AND L7.DATE_DEL IS NULL AND (:V$USER_TYPE <> 8 OR V53.VAL = :V$TEACHER_ID)
                  UNION
                  SELECT FIRST 1 1
                  FROM RDB$DATABASE
                  WHERE :V$USER_TYPE <> 8
              ))
              THEN VAL = 1;
              ELSE VAL = 0;
          END
          ELSE
          BEGIN
              IF(EXISTS(SELECT FIRST 1 1 FROM LINKS WHERE PARENT_ID = :V$ID AND OBJ_TYPE_ID IN (111, 2) AND DATE_DEL IS NULL)) THEN VAL = 1; ELSE VAL = 0;
          END
          SUSPEND;
      END
  END
  ELSE IF(I$LEVEL = 1) THEN
  BEGIN
      -- Список ОУ
      FOR
          SELECT L.OBJ_ID, C.CAPTION, L.OBJ_TYPE_ID
          FROM LINKS L
          LEFT JOIN OBJECT_CAPTION_GET(L.OBJ_ID) C ON 1 = 1
          WHERE (L.PARENT_ID = :I$PARENT_ID OR L.PARENT_ID IS NULL) AND L.OBJ_TYPE_ID = 2 AND L.DATE_DEL IS NULL
          ORDER BY 2
          INTO :V$ID, :V$NAME, :V$TYPE
      DO
      BEGIN
          TAG_NAME = 'items:p';
          VAL = NULL;
          SUSPEND;
          TAG_NAME = 'items:p:id';
          VAL = V$ID;
          SUSPEND;
          TAG_NAME = 'items:p:name';
          VAL = V$NAME;
          SUSPEND;
          TAG_NAME = 'items:p:type';
          VAL = V$TYPE;
          SUSPEND;
          TAG_NAME = 'items:p:level';
          IF(V$TYPE = 111) THEN VAL = 1; ELSE VAL = 2;
          SUSPEND;
          TAG_NAME = 'items:p:has_children';
          IF(EXISTS(
              SELECT FIRST 1 1
              FROM LINKS L7
              JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
              JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 125, 187) AND L9.DATE_DEL IS NULL
              LEFT JOIN VALR V53 ON V53.OBJ_ID = L9.OBJ_ID AND V53.PARAM_ID = 53 AND V53.IS_DEL = 0
              WHERE L7.PARENT_ID = :V$ID AND L7.OBJ_TYPE_ID IN (7, 502) AND L7.DATE_DEL IS NULL AND (:V$USER_TYPE <> 8 OR V53.VAL = :V$TEACHER_ID)
              UNION
              SELECT FIRST 1 1
              FROM RDB$DATABASE
              WHERE :V$USER_TYPE <> 8
          ))
          THEN VAL = 1;
          ELSE VAL = 0;
          SUSPEND;
      END
  END
  ELSE IF(I$LEVEL = 2) THEN
  BEGIN
      -- Список классов - фильтр по классному руководителю
      FOR
          SELECT L9.OBJ_ID, C.CAPTION, L9.OBJ_TYPE_ID, LV49.COST
          FROM LINKS L7
          JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
          JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
          JOIN LISTVALS LV49 ON LV49.LISTVAL_ID = V49.LISTVAL_ID
          JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 125, 187) AND L9.DATE_DEL IS NULL
          LEFT JOIN VALR V53 ON V53.OBJ_ID = L9.OBJ_ID AND V53.PARAM_ID = 53 AND V53.IS_DEL = 0
          LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C ON 1 = 1
          WHERE L7.PARENT_ID = :I$PARENT_ID AND L7.OBJ_TYPE_ID IN (7, 502) AND L7.DATE_DEL IS NULL AND (:V$USER_TYPE <> 8 OR V53.VAL = :V$TEACHER_ID)
          UNION
          SELECT :I$PARENT_ID, 'Сотрудники', 14, -1
          FROM RDB$DATABASE
          WHERE :V$USER_TYPE <> 8
          ORDER BY 4
          INTO :V$ID, :V$NAME, :V$TYPE, :V$ORDER
      DO
      BEGIN
          TAG_NAME = 'items:p';
          VAL = NULL;
          SUSPEND;
          TAG_NAME = 'items:p:id';
          VAL = V$ID;
          SUSPEND;
          TAG_NAME = 'items:p:name';
          VAL = V$NAME;
          SUSPEND;
          TAG_NAME = 'items:p:type';
          VAL = V$TYPE;
          SUSPEND;
          TAG_NAME = 'items:p:level';
          VAL = 3;
          SUSPEND;
          TAG_NAME = 'items:p:stage';
          VAL = CAST(V$ORDER AS INTEGER);
          SUSPEND;
          TAG_NAME = 'items:p:has_children';
          VAL = 0;
          SUSPEND;
      END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_CLONE (
    I$TEST_ID BIGINT,
    I$NEW_STATE INTEGER,
    I$DATE_FROM DATE,
    I$DATE_TO DATE,
    I$TIME_FROM TIME,
    I$GRADE_NAME VARCHAR(100))
RETURNS (
    OBJ_ID BIGINT)
AS
DECLARE VARIABLE V$PERIOD_ID BIGINT;
DECLARE VARIABLE V$NAME VARCHAR(200);
DECLARE VARIABLE S VARCHAR(100);
DECLARE VARIABLE N INTEGER;
begin

  -- Период всегда ставим текущий
  SELECT FIRST 1 V1236.LISTVAL_ID
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$PERIOD_ID;

  -- Названию нужно обеспечить уникальность
  SELECT D.OBJ_ID
  FROM UT_EXAM_DATES D
  WHERE D.OBJ_ID = :I$TEST_ID
  INTO :V$NAME;

  -- Оставляем 40 символов под переменную часть
  V$NAME = SUBSTRING(V$NAME FROM 1 FOR 160);

  -- Название группы
  V$NAME = V$NAME || COALESCE(' ' || SUBSTRING(I$GRADE_NAME FROM 1 FOR 20), '');

  -- Если в названии нет даты - добавляем
  S = SUBSTRING((SELECT RESULT FROM DATE2STR(:I$DATE_FROM)) FROM 1 FOR 8);
  IF(POSITION(S IN V$NAME) <= 0) THEN V$NAME = V$NAME || ' ' || S;

  N = 0;
  WHILE(EXISTS(
    SELECT FIRST 1 1
    FROM UT_EXAM_DATES D
    WHERE D.DATE_DEL IS NULL AND D.OBJ_NAME = IIF(:N = 0, :V$NAME, :V$NAME || ' #' || :N)
  ))
  DO
    N = N + 1;

  INSERT INTO UT_EXAM_DATES
  (OBJ_NAME, SUBJECT_ID, STAGE_ID, EXAM_DATE_START, EXAM_DATE_END, EXAM_DAY_TYPE, EXAM_STATE, C_CALC_MODE, C_EXPERT_NUM, C_DIFF_QUESTION, C_DIFF_TOTAL,
    METHOD_ID, PLAN_METHOD_ID, ATTEMPTS, OWNER_ID, H_LEVEL, ORG_REF, FLOW_MODE, PAUSE_ENABLED, SCALE_N0, SCALE_NMIN, SCALE_N4, SCALE_N5, SCALE_NMAX,
    BLANK_AB_ID, BLANK_C_ID, BLANK_EXT_ID, BLANK_GEN_ID, EXPERT_ASSN_MODE, PERIOD_ID, LINK_HASH, LINK_MASK, DURATION, PPE_ID)
  SELECT IIF(:N = 0, :V$NAME, :V$NAME || ' #' || :N), C.SUBJECT_ID, C.STAGE_ID, :I$DATE_FROM, :I$DATE_TO, C.EXAM_DAY_TYPE, :I$NEW_STATE, C.C_CALC_MODE, C.C_EXPERT_NUM, C.C_DIFF_QUESTION, C.C_DIFF_TOTAL,
    C.METHOD_ID, C.PLAN_METHOD_ID, C.ATTEMPTS, C.OWNER_ID, C.H_LEVEL, C.ORG_REF, C.FLOW_MODE, C.PAUSE_ENABLED, C.SCALE_N0, C.SCALE_NMIN, C.SCALE_N4, C.SCALE_N5, C.SCALE_NMAX,
    C.BLANK_AB_ID, C.BLANK_C_ID, C.BLANK_EXT_ID, C.BLANK_GEN_ID, C.EXPERT_ASSN_MODE, :V$PERIOD_ID, C.LINK_HASH, C.LINK_MASK, C.DURATION, C.PPE_ID
  FROM UT_EXAM_DATES C
  WHERE C.OBJ_ID = :I$TEST_ID
  RETURNING OBJ_ID INTO :OBJ_ID;

  -- Копируем задания
  INSERT INTO UT_EXAM_QUESTIONS
  (EXAM_ID, QUESTION_ID, VARIANT_INDEX, SORT_INDEX)
  SELECT :OBJ_ID, C.QUESTION_ID, C.VARIANT_INDEX, C.SORT_INDEX
  FROM UT_EXAM_QUESTIONS C
  WHERE C.DATE_DEL IS NULL AND C.EXAM_ID = :I$TEST_ID;

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_DELETE (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40) = null)
RETURNS (
    OBJ_ID BIGINT)
AS
begin

  IF(EXISTS(
      SELECT FIRST 1 1
      FROM UT_TEST_VARS TV
      JOIN UT_EXAM_TEST_VARS ETV ON ETV.DATE_DEL IS NULL AND ETV.TEST_VAR_ID = TV.OBJ_ID
      JOIN UT_EXAM_DATES D ON D.OBJ_ID = ETV.EXAM_ID AND D.DATE_DEL IS NULL AND D.EXAM_STATE < 1000
      WHERE TV.TEST_ID = :I$OBJ_ID AND TV.DATE_DEL IS NULL
  ))
  THEN EXCEPTION DATA_ERROR 'Нельзя удалить пакет, задействованный в открытых тестированиях';

  UPDATE UT_TESTS
  SET DATE_DEL = CURRENT_TIMESTAMP
  WHERE OBJ_ID = :I$OBJ_ID AND DATE_DEL IS NULL;

  SUSPEND;
end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_DETAILS (
    I$STUDENT_ID BIGINT,
    I$SUBJECT_ID BIGINT)
RETURNS (
    PLAN_ID BIGINT,
    LOAD_HOURS INTEGER,
    UMK VARCHAR(1000),
    TEACHER_NAME VARCHAR(400))
AS
declare variable STAGE_ID bigint;
begin

  -- Проверяем приписку ученика к ГУП
  SELECT FIRST 1 LP400.PARENT_ID, LP54.PARENT_ID
  FROM LINKS LP256
  JOIN LINKS LP54 ON LP54.OBJ_ID = LP256.PARENT_ID AND LP54.PARENT_TYPE_ID = 54 AND LP54.DATE_DEL IS NULL
  JOIN LINKS LP400 ON LP400.OBJ_ID = LP54.PARENT_ID AND LP400.PARENT_TYPE_ID = 400 AND LP400.DATE_DEL IS NULL
  JOIN VALL V3022 ON V3022.OBJ_ID = LP400.PARENT_ID AND V3022.PARAM_ID = 3022 AND V3022.IS_DEL = 0 AND V3022.LISTVAL_ID = 3
  WHERE LP256.OBJ_ID = :I$STUDENT_ID AND LP256.PARENT_TYPE_ID = 256 AND LP256.DATE_DEL IS NULL
  INTO :PLAN_ID, :STAGE_ID;

  -- Если вдруг ГУП нет = пытаемся найти журнал, связанный с ГУП
  IF(PLAN_ID IS NULL) THEN
  BEGIN
    SELECT FIRST 1 LP400.PARENT_ID, LP54.PARENT_ID
    FROM LINKS LP179
    JOIN LINKS LP2 ON LP2.OBJ_ID = LP179.PARENT_ID AND LP2.PARENT_TYPE_ID = 2 AND LP2.DATE_DEL IS NULL
    -- ГУП находится в EXT_OBJ_ID
    JOIN LINKS LP54 ON LP54.OBJ_ID = LP2.EXT_OBJ_ID AND LP54.PARENT_TYPE_ID = 54 AND LP54.DATE_DEL IS NULL
    JOIN LINKS LP400 ON LP400.OBJ_ID = LP54.PARENT_ID AND LP400.PARENT_TYPE_ID = 400 AND LP400.DATE_DEL IS NULL
    JOIN VALL V3022 ON V3022.OBJ_ID = LP400.PARENT_ID AND V3022.PARAM_ID = 3022 AND V3022.IS_DEL = 0 AND V3022.LISTVAL_ID = 3
    WHERE LP179.OBJ_ID = :I$STUDENT_ID AND LP179.PARENT_TYPE_ID = 179 AND LP179.DATE_DEL IS NULL
    INTO :PLAN_ID, :STAGE_ID;
  END

  -- Выбираем нагрузку по предмету
  SELECT SUM(COALESCE(L.LOAD_HOURS_S1, 0) + COALESCE(L.LOAD_HOURS_S2, 0))
  FROM PLAN_SUBJECTS S
  JOIN PLAN_LOADS L ON L.DATE_DEL IS NULL AND L.SUBJECT_ID = S.OBJ_ID AND L.STAGE_ID = :STAGE_ID
  WHERE S.DATE_DEL IS NULL AND S.PLAN_ID = :PLAN_ID AND (S.SUBJECT_ID = :I$SUBJECT_ID OR S.SRC_SUBJECT_ID = :I$SUBJECT_ID)
  INTO :LOAD_HOURS;

  SELECT FIRST 1 C.CAPTION
  FROM CJ2_JOURNAL J
  JOIN LINKS L10 ON L10.PARENT_ID = J.GRADE_ID AND L10.OBJ_ID = :I$STUDENT_ID AND L10.DATE_DEL IS NULL
  LEFT JOIN OBJECT_CAPTION_GET(J.TEACHER_ID) C ON J.TEACHER_ID IS NOT NULL
  WHERE J.DATE_DEL IS NULL AND J.SUBJECT_ID = :I$SUBJECT_ID
  INTO :TEACHER_NAME;

  SELECT FIRST 1 SUBSTRING(C.CAPTION FROM 1 FOR 1000)
  FROM PLAN_SUBJECTS S
  JOIN PLAN_LOADS L ON L.DATE_DEL IS NULL AND L.SUBJECT_ID = S.OBJ_ID AND L.STAGE_ID = :STAGE_ID
  JOIN PLAN_RESOURCES R ON R.DATE_DEL IS NULL AND R.LOAD_ID = L.OBJ_ID
  LEFT JOIN OBJECT_CAPTION_GET(R.RES_ID) C ON 1 = 1
  WHERE S.DATE_DEL IS NULL AND S.PLAN_ID = :PLAN_ID AND (S.SUBJECT_ID = :I$SUBJECT_ID OR S.SRC_SUBJECT_ID = :I$SUBJECT_ID)
  INTO :UMK;

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_EXPORT_B0 (
    I$EXAM_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
declare variable V$GEN bigint;
declare variable V$MULT bigint;
declare variable V$DB_LEVEL integer;
declare variable V$H_LEVEL integer;
declare variable V$T1 timestamp;
declare variable V$T2 timestamp;
declare variable V$T3 timestamp;
declare variable V$S varchar(200);
declare variable V$PACKAGE_ID bigint;
declare variable V$PPE_ID bigint;
declare variable V$ROOM_ID bigint;
declare variable V$USER_ID bigint;
declare variable V$N integer;
declare variable V$STATE integer;
declare variable V$OBJ_ID bigint;
declare variable V$BLANK_TYPE bigint;
declare variable V$SIDE integer;
declare variable V$PARENT_ID bigint;
declare variable V$NEXT_ID bigint;
declare variable V$FILE_ID varchar(40);
declare variable V$HASH varchar(40);
declare variable V$BC1 varchar(128);
declare variable V$BC2 varchar(128);
declare variable V$BC3 varchar(128);
declare variable V$SESSION_ID bigint;
begin

  IF(I$USER_ID = 'Веб-администратор') THEN V$USER_ID = 0; ELSE V$USER_ID = CAST(I$USER_ID AS BIGINT);

  SELECT COALESCE(CAST(K.KEY_VAL AS INTEGER) - 1, 0)
  FROM KEYS K
  WHERE K.KEY_CODE = 'LEVEL'
  INTO :V$DB_LEVEL;

  -- Заголовок, содержащий данные об экспортере
  TAG_NAME = 'content';
  VAL = NULL;
  SUSPEND;

  TAG_NAME = 'content:owner_id';
  SELECT GEN, MULTIPLIER
  FROM GEN
  INTO :V$GEN, :V$MULT;
  VAL = V$GEN;
  SUSPEND;

  TAG_NAME = 'content:level';
  VAL = V$DB_LEVEL;
  SUSPEND;

  TAG_NAME = 'content:user_id';
  VAL = V$USER_ID;
  SUSPEND;

  TAG_NAME = 'content:date';
  VAL = (SELECT VAL FROM DATE2ISO(CURRENT_TIMESTAMP));
  SUSPEND;

  -- Тестирование
  TAG_NAME = 'exam';
  VAL = NULL;
  SUSPEND;

  TAG_NAME = 'exam:id';
  VAL = I$EXAM_ID;
  SUSPEND;

  SELECT D.H_LEVEL, D.ORG_REF
  FROM UT_EXAM_DATES D
  WHERE D.OBJ_ID = :I$EXAM_ID AND D.DATE_DEL IS NULL
  INTO :V$H_LEVEL, :V$OBJ_ID;

  IF(V$H_LEVEL IS NULL) THEN EXCEPTION DATA_ERROR 'Тестирование не найдено или было удалено';

  TAG_NAME = 'exam:h_level';
  VAL = V$H_LEVEL;
  SUSPEND;

  TAG_NAME = 'exam:org_ref';
  VAL = V$OBJ_ID;
  SUSPEND;

  -- Данные пакетов и бланков. Выгружаем только заверешнные пакеты
  TAG_NAME = 'packages';
  VAL = NULL;
  SUSPEND;

  FOR
      SELECT P.OBJ_ID, P.DATE_ADD, P.DATE_MODIFY, P.DATE_DEL, P.PPE_ID, P.ROOM_ID, P.USER_ID, P.N_PAGES, P.STATE_ID, P.IP_INFO
      FROM UT_PACKAGES P
      WHERE P.ED_ID = :I$EXAM_ID AND P.STATE_ID >= 9
      INTO :V$PACKAGE_ID, :V$T1, :V$T2, :V$T3, :V$PPE_ID, :V$ROOM_ID, :V$USER_ID, :V$N, :V$STATE, :V$S
  DO
  BEGIN
      TAG_NAME = 'packages:item';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'packages:item:id';
      VAL = V$PACKAGE_ID;
      SUSPEND;
      TAG_NAME = 'packages:item:date_add';
      VAL = (SELECT VAL FROM DATE2ISO(:V$T1));
      SUSPEND;
      TAG_NAME = 'packages:item:date_modify';
      VAL = (SELECT VAL FROM DATE2ISO(:V$T2));
      SUSPEND;
      TAG_NAME = 'packages:item:date_del';
      VAL = (SELECT VAL FROM DATE2ISO(:V$T3));
      SUSPEND;
      TAG_NAME = 'packages:item:ppe_id';
      VAL = V$PPE_ID;
      SUSPEND;
      TAG_NAME = 'packages:item:room_id';
      VAL = V$ROOM_ID;
      SUSPEND;
      TAG_NAME = 'packages:item:user_id';
      VAL = V$USER_ID;
      SUSPEND;
      TAG_NAME = 'packages:item:n_files';
      VAL = V$N;
      SUSPEND;
      TAG_NAME = 'packages:item:state';
      VAL = V$STATE;
      SUSPEND;
      TAG_NAME = 'packages:item:ip_info';
      VAL = V$S;
      SUSPEND;

      -- Файлы только для не-удаленных пакетов
      -- Внимание: грузим файлы в случайном порядке, и при импорте next_blank_id устанавливаем после загрузки всех бланков
      TAG_NAME = 'packages:item:files';
      VAL = NULL;
      SUSPEND;
      IF(V$T3 IS NULL) THEN
      FOR
          SELECT B.OBJ_ID, B.DATE_ADD, B.DATE_MODIFY, B.DATE_DEL, B.BLANK_TYPE, B.BLANK_SIDE, B.PARENT_ID, B.NEXT_BLANK_ID, B.SESSION_ID,
              B.FILE_ID, B.FILE_HASH, B.BARCODE_DATA, B.BARCODE2_DATA, B.BARCODE3_DATA, B.STATE_ID, B.RCV_STATION_ID, B.VER_USER_ID
          FROM UT_BLANKS B
          WHERE B.PACKAGE_ID = :V$PACKAGE_ID
          INTO :V$OBJ_ID, :V$T1, :V$T2, :V$T3, :V$BLANK_TYPE, :V$SIDE, :V$PARENT_ID, :V$NEXT_ID, :V$SESSION_ID, :V$FILE_ID, :V$HASH,
            :V$BC1, :V$BC2, :V$BC3, :V$STATE, :V$S, :V$USER_ID
      DO
      BEGIN
          TAG_NAME = 'packages:item:files:file';
          VAL = NULL;
          SUSPEND;
          TAG_NAME = 'packages:item:files:file:id';
          VAL = V$OBJ_ID;
          SUSPEND;
          TAG_NAME = 'packages:item:files:file:date_add';
          VAL = (SELECT VAL FROM DATE2ISO(:V$T1));
          SUSPEND;
          TAG_NAME = 'packages:item:files:file:date_modify';
          VAL = (SELECT VAL FROM DATE2ISO(:V$T2));
          SUSPEND;
          TAG_NAME = 'packages:item:files:file:date_del';
          VAL = (SELECT VAL FROM DATE2ISO(:V$T3));
          SUSPEND;
          TAG_NAME = 'packages:item:files:file:blank_type';
          VAL = V$BLANK_TYPE;
          SUSPEND;
          TAG_NAME = 'packages:item:files:file:side';
          VAL = V$SIDE;
          SUSPEND;
          TAG_NAME = 'packages:item:files:file:parent_id';
          VAL = V$PARENT_ID;
          SUSPEND;
          TAG_NAME = 'packages:item:files:file:next_id';
          VAL = V$NEXT_ID;
          SUSPEND;
          TAG_NAME = 'packages:item:files:file:session_id';
          VAL = V$SESSION_ID;
          SUSPEND;
          TAG_NAME = 'packages:item:files:file:file_id';
          VAL = V$FILE_ID;
          SUSPEND;
          TAG_NAME = 'packages:item:files:file:hash';
          VAL = V$HASH;
          SUSPEND;
          TAG_NAME = 'packages:item:files:file:barcode1';
          VAL = V$BC1;
          SUSPEND;
          TAG_NAME = 'packages:item:files:file:barcode2';
          VAL = V$BC2;
          SUSPEND;
          TAG_NAME = 'packages:item:files:file:barcode3';
          VAL = V$BC3;
          SUSPEND;
          TAG_NAME = 'packages:item:files:file:state';
          VAL = V$STATE;
          SUSPEND;
          TAG_NAME = 'packages:item:files:file:station';
          VAL = V$S;
          SUSPEND;
          TAG_NAME = 'packages:item:files:file:user_id';
          VAL = V$USER_ID;
          SUSPEND;
      END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_EXPORT_CS (
    I$CODING_ID BIGINT,
    I$PARENT_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$OBJ_ID bigint;
begin

  FOR
      SELECT KCL.OBJ_ID
      FROM UT_KIM_CODING_LEVELS KCL
      WHERE KCL.CODING_ID = :I$CODING_ID AND ((KCL.PARENT_ID IS NULL AND :I$PARENT_ID IS NULL) OR KCL.PARENT_ID = :I$PARENT_ID)
      INTO :V$OBJ_ID
  DO
  BEGIN
      OBJ_ID = V$OBJ_ID;
      SUSPEND;

      FOR
          SELECT OBJ_ID
          FROM UT_TEST_EXPORT_CS(:I$CODING_ID, :V$OBJ_ID)
          INTO :OBJ_ID
      DO
      BEGIN
          SUSPEND;
      END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_EXPORT_LOCAL (
    I$OBJ_ID BIGINT = null)
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
declare variable V$EXAM_ID bigint;
declare variable V$ASSN_ID bigint;
declare variable V$PERSON_ID bigint;
declare variable D1 timestamp;
declare variable D2 timestamp;
declare variable D3 timestamp;
declare variable V$LOCAL_ID varchar(40);
declare variable V$ROLE_ID integer;
declare variable V$BLANKS_PRINTED smallint;
declare variable V$SC smallint;
declare variable V$LEVEL_ID smallint;
declare variable V$TEACHER_ID bigint;
declare variable D4 timestamp;
declare variable D5 timestamp;
declare variable D6 timestamp;
declare variable V$IS_ACTIVE smallint;
declare variable V$USERNAME varchar(100);
declare variable V$PWD varchar(100);
declare variable V$ORG_ID bigint;
declare variable V$NAME_LAST varchar(400);
declare variable V$NAME_FIRST varchar(400);
declare variable V$NAME_MID varchar(400);
declare variable V$DB_LEVEL smallint;
begin

  SELECT COALESCE(CAST(K.KEY_VAL AS INTEGER) - 1, 0)
  FROM KEYS K
  WHERE K.KEY_CODE = 'LEVEL'
  INTO :V$DB_LEVEL;

  -- Идем по тестированиям не старше 1 года
  -- Внимание: не передаем тестирования нижестоящих уровней вверх, т.е. созданные в ОУ тестирования не поднимаем в район, а районные - в город
  -- 1. Участники
  FOR
      SELECT D.OBJ_ID, PA.OBJ_ID, PA.PERSON_ID, PA.DATE_ADD, PA.DATE_MODIFY, PA.DATE_DEL, PA.LOCAL_ID, PA.BLANKS_PRINTED, PA.LEVEL_ID
      FROM UT_EXAM_DATES D
      JOIN UT_EXAM_PERSON_ASSN PA ON PA.EXAM_ID = D.OBJ_ID
      WHERE D.DATE_DEL IS NULL AND D.DATE_ADD >= DATEADD(-1 YEAR TO CURRENT_DATE) AND D.EXAM_STATE > 0 AND (:I$OBJ_ID IS NULL OR D.OBJ_ID = :I$OBJ_ID)
        -- !!! доделать фильтр по уровню, чтобы не грузить школьный уровень в город
          -- AND (D.H_LEVEL > :V$DB_LEVEL OR )
      ORDER BY 1, 2
      INTO :V$EXAM_ID, :V$ASSN_ID, :V$PERSON_ID, :D1, :D2, :D3, :V$LOCAL_ID, :V$BLANKS_PRINTED, :V$LEVEL_ID
  DO
  BEGIN
      TAG_NAME = 'member';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'member:exam_id';
      VAL = V$EXAM_ID;
      SUSPEND;
      TAG_NAME = 'member:id';
      VAL = V$ASSN_ID;
      SUSPEND;
      TAG_NAME = 'member:person_id';
      VAL = V$PERSON_ID;
      SUSPEND;
      TAG_NAME = 'member:local_id';
      VAL = V$LOCAL_ID;
      SUSPEND;
      TAG_NAME = 'member:blanks_printed';
      VAL = V$BLANKS_PRINTED;
      SUSPEND;
      TAG_NAME = 'member:level_id';
      VAL = V$LEVEL_ID;
      SUSPEND;
      TAG_NAME = 'member:date_add';
      VAL = (SELECT VAL FROM DATE2ISO(:D1));
      SUSPEND;
      TAG_NAME = 'member:date_modify';
      VAL = (SELECT VAL FROM DATE2ISO(:D2));
      SUSPEND;
      TAG_NAME = 'member:date_del';
      VAL = (SELECT VAL FROM DATE2ISO(:D3));
      SUSPEND;
  END

  -- 2. Эксперты
  FOR
      SELECT D.OBJ_ID, PA.OBJ_ID, PA.EXPERT_ID, PA.DATE_ADD, PA.DATE_MODIFY, PA.DATE_DEL, PA.ROLE_ID, PA.SECOND_CHECK,
          E.TEACHER_ID, E.DATE_ADD, E.DATE_MODIFY, E.DATE_DEL, E.IS_ACTIVE, E.USER_NAME, E.PWD, E.ORG_ID,
          E.LAST_NAME, E.FIRST_NAME, E.MIDDLE_NAME
      FROM UT_EXAM_DATES D
      JOIN UT_EXAM_EXPERT_ASSN PA ON PA.EXAM_ID = D.OBJ_ID
      JOIN UT_EXPERTS E ON E.EXPERT_ID = PA.EXPERT_ID
      WHERE D.DATE_DEL IS NULL AND D.DATE_ADD >= DATEADD(-1 YEAR TO CURRENT_DATE) AND D.EXAM_STATE > 0 AND (:I$OBJ_ID IS NULL OR D.OBJ_ID = :I$OBJ_ID)
        -- !!! доделать фильтр по уровню, чтобы не грузить школьный уровень в город
      ORDER BY 1, 2
      INTO :V$EXAM_ID, :V$ASSN_ID, :V$PERSON_ID, :D1, :D2, :D3, :V$ROLE_ID, :V$SC, :V$TEACHER_ID, :D4, :D5, :D6, :V$IS_ACTIVE, :V$USERNAME, :V$PWD, :V$ORG_ID,
          :V$NAME_LAST, :V$NAME_FIRST, :V$NAME_MID
  DO
  BEGIN
      TAG_NAME = 'expert';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'expert:exam_id';
      VAL = V$EXAM_ID;
      SUSPEND;
      TAG_NAME = 'expert:id';
      VAL = V$ASSN_ID;
      SUSPEND;
      TAG_NAME = 'expert:person_id';
      VAL = V$PERSON_ID;
      SUSPEND;
      TAG_NAME = 'expert:role_id';
      VAL = V$ROLE_ID;
      SUSPEND;
      TAG_NAME = 'expert:second_check';
      VAL = V$SC;
      SUSPEND;
      TAG_NAME = 'expert:date_add';
      VAL = (SELECT VAL FROM DATE2ISO(:D1));
      SUSPEND;
      TAG_NAME = 'expert:date_modify';
      VAL = (SELECT VAL FROM DATE2ISO(:D2));
      SUSPEND;
      TAG_NAME = 'expert:date_del';
      VAL = (SELECT VAL FROM DATE2ISO(:D3));
      SUSPEND;

      TAG_NAME = 'expert:teacher_id';
      VAL = V$TEACHER_ID;
      SUSPEND;
      TAG_NAME = 'expert:date_add2';
      VAL = (SELECT VAL FROM DATE2ISO(:D4));
      SUSPEND;
      TAG_NAME = 'expert:date_modify2';
      VAL = (SELECT VAL FROM DATE2ISO(:D5));
      SUSPEND;
      TAG_NAME = 'expert:date_del2';
      VAL = (SELECT VAL FROM DATE2ISO(:D6));
      SUSPEND;
      TAG_NAME = 'expert:is_active';
      VAL = V$IS_ACTIVE;
      SUSPEND;
      TAG_NAME = 'expert:username';
      VAL = V$USERNAME;
      SUSPEND;
      TAG_NAME = 'expert:password';
      VAL = V$PWD;
      SUSPEND;
      TAG_NAME = 'expert:organization_id';
      VAL = V$ORG_ID;
      SUSPEND;
      TAG_NAME = 'expert:name_last';
      VAL = V$NAME_LAST;
      SUSPEND;
      TAG_NAME = 'expert:name_first';
      VAL = V$NAME_FIRST;
      SUSPEND;
      TAG_NAME = 'expert:name_mid';
      VAL = V$NAME_MID;
      SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_EXPORT_P0 (
    I$EXAM_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$GEN BIGINT;
DECLARE VARIABLE V$MULT BIGINT;
DECLARE VARIABLE V$USER_ID BIGINT;
DECLARE VARIABLE V$DB_LEVEL INTEGER;
DECLARE VARIABLE V$T1 TIMESTAMP;
DECLARE VARIABLE V$T2 TIMESTAMP;
DECLARE VARIABLE V$T3 TIMESTAMP;
DECLARE VARIABLE V$S VARCHAR(8000);
DECLARE VARIABLE V$S1 VARCHAR(400);
DECLARE VARIABLE V$S2 VARCHAR(400);
DECLARE VARIABLE V$S3 VARCHAR(400);
DECLARE VARIABLE V$SUBJECT_ID BIGINT;
DECLARE VARIABLE V$STAGE_ID INTEGER;
DECLARE VARIABLE V$EXAM_DATE_START DATE;
DECLARE VARIABLE V$EXAM_DATE_END DATE;
DECLARE VARIABLE V$TIME INTEGER;
DECLARE VARIABLE V$EXAM_DAY_TYPE INTEGER;
DECLARE VARIABLE V$EXAM_STATE INTEGER;
DECLARE VARIABLE V$C_CALC_MODE INTEGER;
DECLARE VARIABLE V$C_EXPERT_NUM INTEGER;
DECLARE VARIABLE V$C_DIFF_QUESTION INTEGER;
DECLARE VARIABLE V$C_DIFF_TOTAL INTEGER;
DECLARE VARIABLE V$METHOD_ID INTEGER;
DECLARE VARIABLE V$PLAN_METHOD_ID INTEGER;
DECLARE VARIABLE V$ATTEMPTS INTEGER;
DECLARE VARIABLE V$H_LEVEL INTEGER;
DECLARE VARIABLE V$ORG_REF BIGINT;
DECLARE VARIABLE V$FLOW_MODE INTEGER;
DECLARE VARIABLE V$PAUSE_ENABLED INTEGER;
DECLARE VARIABLE V$SCALE_N0 INTEGER;
DECLARE VARIABLE V$SCALE_NMIN INTEGER;
DECLARE VARIABLE V$SCALE_N4 INTEGER;
DECLARE VARIABLE V$SCALE_N5 INTEGER;
DECLARE VARIABLE V$SCALE_NMAX INTEGER;
DECLARE VARIABLE V$BLANK_AB_ID BIGINT;
DECLARE VARIABLE V$BLANK_C_ID BIGINT;
DECLARE VARIABLE V$BLANK_EXT_ID BIGINT;
DECLARE VARIABLE V$BLANK_GEN_ID BIGINT;
DECLARE VARIABLE V$EXPERT_ASSN_MODE INTEGER;
DECLARE VARIABLE V$PERIOD_ID BIGINT;
DECLARE VARIABLE V$LINK_HASH VARCHAR(200) COLLATE UTF8;
DECLARE VARIABLE V$LINK_MASK INTEGER;
DECLARE VARIABLE V$DURATION INTEGER;
DECLARE VARIABLE V$PPE_ID BIGINT;
DECLARE VARIABLE V$OU_ID BIGINT;
DECLARE VARIABLE V$D1 DATE;
DECLARE VARIABLE V$D2 DATE;
DECLARE VARIABLE V$STRUCT_ID BIGINT;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$IS_AUTO SMALLINT;
DECLARE VARIABLE V$Q_ORDER INTEGER;
DECLARE VARIABLE V$Q_TYPE_ID INTEGER;
DECLARE VARIABLE V$Q_LEVEL INTEGER;
DECLARE VARIABLE V$FILE_SIZE INTEGER;
DECLARE VARIABLE V$K VARCHAR(64) COLLATE UTF8;
DECLARE VARIABLE V$Q_MAX_SCORE INTEGER;
DECLARE VARIABLE V$CHARSET_ID INTEGER;
DECLARE VARIABLE V$N INTEGER;
DECLARE VARIABLE V$N_LEVEL INTEGER;
DECLARE VARIABLE V$OWNER_ID BIGINT;
DECLARE VARIABLE V$METADATA_ID VARCHAR(40);
DECLARE VARIABLE V$VAR_ID BIGINT;
DECLARE VARIABLE V$AREA_ID BIGINT;
DECLARE VARIABLE V$WND_MIN FLOAT;
DECLARE VARIABLE V$WND_MAX FLOAT;
begin

  IF(I$USER_ID = 'Веб-администратор') THEN V$USER_ID = 0; ELSE V$USER_ID = CAST(I$USER_ID AS BIGINT);

  SELECT COALESCE(CAST(K.KEY_VAL AS INTEGER) - 1, 0)
  FROM KEYS K
  WHERE K.KEY_CODE = 'LEVEL'
  INTO :V$DB_LEVEL;

  -- Заголовок, содержащий данные об экспортере
  TAG_NAME = 'content';
  VAL = NULL;
  SUSPEND;

  TAG_NAME = 'content:owner_id';
  SELECT GEN, MULTIPLIER
  FROM GEN
  INTO :V$GEN, :V$MULT;
  VAL = V$GEN;
  SUSPEND;

  TAG_NAME = 'content:level';
  VAL = V$DB_LEVEL;
  SUSPEND;

  TAG_NAME = 'content:user_id';
  VAL = V$USER_ID;
  SUSPEND;

  TAG_NAME = 'content:date';
  VAL = (SELECT VAL FROM DATE2ISO(CURRENT_TIMESTAMP));
  SUSPEND;

  -- Тестирование
  TAG_NAME = 'exam';
  VAL = NULL;
  SUSPEND;

  TAG_NAME = 'exam:id';
  VAL = I$EXAM_ID;
  SUSPEND;

  SELECT D.DATE_ADD, D.DATE_MODIFY, D.OBJ_NAME, D.SUBJECT_ID, D.STAGE_ID, D.EXAM_DATE_START, D.EXAM_DATE_END, D.DURATION, D.EXAM_DAY_TYPE, D.EXAM_STATE,
     D.C_CALC_MODE, D.C_EXPERT_NUM, D.C_DIFF_QUESTION, D.C_DIFF_TOTAL, D.METHOD_ID, D.PLAN_METHOD_ID, D.ATTEMPTS, D.OWNER_ID, D.H_LEVEL, D.ORG_REF,
     D.FLOW_MODE, D.PAUSE_ENABLED, D.SCALE_N0, D.SCALE_NMIN, D.SCALE_N4, D.SCALE_N5, D.SCALE_NMAX,
     D.BLANK_AB_ID, D.BLANK_C_ID, D.BLANK_EXT_ID, D.BLANK_GEN_ID, D.EXPERT_ASSN_MODE,
     D.PERIOD_ID, D.LINK_HASH, D.LINK_MASK, D.DURATION, D.PPE_ID
  FROM UT_EXAM_DATES D
  WHERE D.OBJ_ID = :I$EXAM_ID AND D.DATE_DEL IS NULL
  INTO :V$T1, :V$T2, :V$S, :V$SUBJECT_ID, :V$STAGE_ID, :V$EXAM_DATE_START, :V$EXAM_DATE_END, :V$TIME, :V$EXAM_DAY_TYPE, :V$EXAM_STATE,
     :V$C_CALC_MODE, :V$C_EXPERT_NUM, :V$C_DIFF_QUESTION, :V$C_DIFF_TOTAL, :V$METHOD_ID, :V$PLAN_METHOD_ID, :V$ATTEMPTS, :V$OWNER_ID, :V$H_LEVEL, :V$ORG_REF,
     :V$FLOW_MODE, :V$PAUSE_ENABLED, :V$SCALE_N0, :V$SCALE_NMIN, :V$SCALE_N4, :V$SCALE_N5, :V$SCALE_NMAX,
     :V$BLANK_AB_ID, :V$BLANK_C_ID, :V$BLANK_EXT_ID, :V$BLANK_GEN_ID, :V$EXPERT_ASSN_MODE,
     :V$PERIOD_ID, :V$LINK_HASH, :V$LINK_MASK, :V$DURATION, :V$PPE_ID;

  IF(V$S IS NULL) THEN EXCEPTION DATA_ERROR 'Тестирование не найдено или было удалено';

  TAG_NAME = 'exam:date_add';
  VAL = (SELECT VAL FROM DATE2ISO(:V$T1));
  SUSPEND;
  TAG_NAME = 'exam:date_modify';
  VAL = (SELECT VAL FROM DATE2ISO(:V$T2));
  SUSPEND;
  TAG_NAME = 'exam:date_del';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'exam:obj_name';
  VAL = V$S;
  SUSPEND;
  TAG_NAME = 'exam:subject_id';
  VAL = V$SUBJECT_ID;
  SUSPEND;
  TAG_NAME = 'exam:stage_id';
  VAL = V$STAGE_ID;
  SUSPEND;
  TAG_NAME = 'exam:exam_date_start';
  VAL = (SELECT VAL FROM DATE2ISO(:V$EXAM_DATE_START, 0));
  SUSPEND;
  TAG_NAME = 'exam:exam_date_end';
  VAL = (SELECT VAL FROM DATE2ISO(:V$EXAM_DATE_END, 0));
  SUSPEND;
  TAG_NAME = 'exam:duration';
  VAL = V$TIME;
  SUSPEND;
  TAG_NAME = 'exam:exam_day_type';
  VAL = V$EXAM_DAY_TYPE;
  SUSPEND;
  TAG_NAME = 'exam:state';
  VAL = V$EXAM_STATE;
  SUSPEND;
  TAG_NAME = 'exam:c_calc_mode';
  VAL = V$C_CALC_MODE;
  SUSPEND;
  TAG_NAME = 'exam:c_expert_num';
  VAL = V$C_EXPERT_NUM;
  SUSPEND;
  TAG_NAME = 'exam:c_diff_question';
  VAL = V$C_DIFF_QUESTION;
  SUSPEND;
  TAG_NAME = 'exam:c_diff_total';
  VAL = V$C_DIFF_TOTAL;
  SUSPEND;
  TAG_NAME = 'exam:method_id';
  VAL = V$METHOD_ID;
  SUSPEND;
  TAG_NAME = 'exam:plan_method_id';
  VAL = V$PLAN_METHOD_ID;
  SUSPEND;
  TAG_NAME = 'exam:attempts';
  VAL = V$ATTEMPTS;
  SUSPEND;
  TAG_NAME = 'exam:owner_id';
  VAL = V$OWNER_ID;
  SUSPEND;
  TAG_NAME = 'exam:h_level';
  VAL = V$H_LEVEL;
  SUSPEND;
  TAG_NAME = 'exam:org_ref';
  VAL = V$ORG_REF;
  SUSPEND;
  TAG_NAME = 'exam:flow_mode';
  VAL = V$FLOW_MODE;
  SUSPEND;
  TAG_NAME = 'exam:pause_enabled';
  VAL = V$PAUSE_ENABLED;
  SUSPEND;
  TAG_NAME = 'exam:scale_n0';
  VAL = V$SCALE_N0;
  SUSPEND;
  TAG_NAME = 'exam:scale_nmin';
  VAL = V$SCALE_NMIN;
  SUSPEND;
  TAG_NAME = 'exam:scale_n4';
  VAL = V$SCALE_N4;
  SUSPEND;
  TAG_NAME = 'exam:scale_n5';
  VAL = V$SCALE_N5;
  SUSPEND;
  TAG_NAME = 'exam:scale_nmax';
  VAL = V$SCALE_NMAX;
  SUSPEND;
  TAG_NAME = 'exam:blank_ab_id';
  VAL = V$BLANK_AB_ID;
  SUSPEND;
  TAG_NAME = 'exam:blank_c_id';
  VAL = V$BLANK_C_ID;
  SUSPEND;
  TAG_NAME = 'exam:blank_ext_id';
  VAL = V$BLANK_EXT_ID;
  SUSPEND;
  TAG_NAME = 'exam:blank_gen_id';
  VAL = V$BLANK_GEN_ID;
  SUSPEND;
  TAG_NAME = 'exam:expert_assn_mode';
  VAL = V$EXPERT_ASSN_MODE;
  SUSPEND;
  TAG_NAME = 'exam:period_id';
  VAL = V$PERIOD_ID;
  SUSPEND;
  TAG_NAME = 'exam:link_hash';
  VAL = V$LINK_HASH;
  SUSPEND;
  TAG_NAME = 'exam:link_mask';
  VAL = V$LINK_MASK;
  SUSPEND;
  TAG_NAME = 'exam:duration';
  VAL = V$DURATION;
  SUSPEND;
  TAG_NAME = 'exam:ppe_id';
  VAL = V$PPE_ID;
  SUSPEND;

  -- Список ОУ, назначенных на данное тестирование
  TAG_NAME = 'exam:ou';
  VAL = NULL;
  SUSPEND;
  FOR
      SELECT EA.OBJ_ID, EA.DATE_ADD, EA.DATE_MODIFY, EA.DATE_DEL, EA.OU_ID, EA.DATE_START, EA.DATE_END
      FROM UT_EXAM_OU_ASSN EA
      WHERE EA.EXAM_ID = :I$EXAM_ID
      INTO :V$OBJ_ID, :V$T1, :V$T2, :V$T3, :V$OU_ID, :V$D1, :V$D2
  DO
  BEGIN
      TAG_NAME = 'exam:ou:item';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'exam:ou:item:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'exam:ou:item:date_add';
      VAL = (SELECT VAL FROM DATE2ISO(:V$T1));
      SUSPEND;
      TAG_NAME = 'exam:ou:item:date_modify';
      VAL = (SELECT VAL FROM DATE2ISO(:V$T2));
      SUSPEND;
      TAG_NAME = 'exam:ou:item:date_del';
      VAL = (SELECT VAL FROM DATE2ISO(:V$T3));
      SUSPEND;
      TAG_NAME = 'exam:ou:item:ou_id';
      VAL = V$OU_ID;
      SUSPEND;
      TAG_NAME = 'exam:ou:item:date_start';
      VAL = (SELECT VAL FROM DATE2ISO(:V$D1, 0));
      SUSPEND;
      TAG_NAME = 'exam:ou:item:date_end';
      VAL = (SELECT VAL FROM DATE2ISO(:V$D2, 0));
      SUSPEND;
  END

  -- Шаблоны бланков, данные из полей DATA_FRONT и DATA_BACK выгружаются позднее
  TAG_NAME = 'templates';
  VAL = NULL;
  SUSPEND;
  FOR
      SELECT PT.OBJ_ID, PT.DATE_ADD, PT.DATE_MODIFY, PT.DATE_DEL, PT.OBJ_NAME, PT.BLANK_TYPE, PT.IS_DS, PT.IS_ACTIVE
      FROM UT_EXAM_DATES D
      JOIN UT_PAGE_TEMPLATES PT ON (PT.OBJ_ID = D.BLANK_AB_ID OR PT.OBJ_ID = D.BLANK_C_ID OR PT.OBJ_ID = D.BLANK_EXT_ID OR PT.OBJ_ID = D.BLANK_GEN_ID)
      WHERE D.OBJ_ID = :I$EXAM_ID
      INTO :V$OBJ_ID, :V$T1, :V$T2, :V$T3, :V$S, :V$N, :V$N_LEVEL, :V$CHARSET_ID
  DO
  BEGIN
      TAG_NAME = 'templates:template';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'templates:template:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'templates:template:date_add';
      VAL = (SELECT VAL FROM DATE2ISO(:V$T1));
      SUSPEND;
      TAG_NAME = 'templates:template:date_modify';
      VAL = (SELECT VAL FROM DATE2ISO(:V$T2));
      SUSPEND;
      TAG_NAME = 'templates:template:date_del';
      VAL = (SELECT VAL FROM DATE2ISO(:V$T3));
      SUSPEND;
      TAG_NAME = 'templates:template:obj_name';
      VAL = V$S;
      SUSPEND;
      TAG_NAME = 'templates:template:blank_type';
      VAL = V$N;
      SUSPEND;
      TAG_NAME = 'templates:template:is_ds';
      VAL = V$N_LEVEL;
      SUSPEND;
      TAG_NAME = 'templates:template:is_active';
      VAL = V$CHARSET_ID;
      SUSPEND;
  END

  -- Структуры задействованных тестов (TEXT_NOTES подгружается позднее)
  TAG_NAME = 'structures';
  VAL = NULL;
  SUSPEND;
  FOR
      SELECT DISTINCT TS.OBJ_ID, TS.DATE_ADD, TS.DATE_MODIFY, TS.OBJ_NAME, TS.SUBJECT_ID, TS.STAGE_ID, TS.METHOD_ID, TS.IS_AUTO, TS.STR_HASH
      FROM UT_EXAM_TEST_VARS ETV
      JOIN UT_TEST_VARS TV ON TV.OBJ_ID = ETV.TEST_VAR_ID
      JOIN UT_TESTS T ON T.OBJ_ID = TV.TEST_ID AND T.DATE_DEL IS NULL
      JOIN UT_TEST_STRUCTS TS ON TS.OBJ_ID = T.STRUCT_ID AND TS.DATE_DEL IS NULL
      WHERE ETV.EXAM_ID = :I$EXAM_ID AND ETV.DATE_DEL IS NULL
      INTO :V$STRUCT_ID, :V$T1, :V$T2, :V$S, :V$SUBJECT_ID, :V$STAGE_ID, :V$METHOD_ID, :V$IS_AUTO, :V$METADATA_ID
  DO
  BEGIN
      TAG_NAME = 'structures:item';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'structures:item:id';
      VAL = V$STRUCT_ID;
      SUSPEND;
      TAG_NAME = 'structures:item:date_add';
      VAL = (SELECT VAL FROM DATE2ISO(:V$T1));
      SUSPEND;
      TAG_NAME = 'structures:item:date_modify';
      VAL = (SELECT VAL FROM DATE2ISO(:V$T2));
      SUSPEND;
      TAG_NAME = 'structures:item:date_del';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'structures:item:obj_name';
      VAL = V$S;
      SUSPEND;
      TAG_NAME = 'structures:item:subject_id';
      VAL = V$SUBJECT_ID;
      SUSPEND;
      TAG_NAME = 'structures:item:stage_id';
      VAL = V$STAGE_ID;
      SUSPEND;
      TAG_NAME = 'structures:item:method_id';
      VAL = V$METHOD_ID;
      SUSPEND;
      TAG_NAME = 'structures:item:is_auto';
      VAL = V$IS_AUTO;
      SUSPEND;
      TAG_NAME = 'structures:item:hash';
      VAL = V$METADATA_ID;
      SUSPEND;

      TAG_NAME = 'structures:item:points';
      VAL = NULL;
      SUSPEND;
      FOR
          SELECT TSP.OBJ_ID, TSP.DATE_ADD, TSP.DATE_MODIFY, TSP.DATE_DEL, TSP.Q_TYPE_ID, TSP.Q_ORDER, TSP.Q_LEVEL, TSP.Q_MAX_SCORE, TSP.CHARSET_ID, TSP.TEXT_NOTES,
            TSP.WND_MIN, WND_MAX
          FROM UT_TEST_STRUCT_POINTS TSP
          WHERE TSP.STRUCT_ID = :V$STRUCT_ID
          ORDER BY TSP.Q_ORDER
          INTO :V$OBJ_ID, :V$T1, :V$T2, :V$T3, :V$Q_TYPE_ID, :V$Q_ORDER, :V$Q_LEVEL, :V$Q_MAX_SCORE, :V$CHARSET_ID, :V$S,
            V$WND_MIN, V$WND_MAX
      DO
      BEGIN
          TAG_NAME = 'structures:item:points:point';
          VAL = NULL;
          SUSPEND;
          TAG_NAME = 'structures:item:points:point:id';
          VAL = V$OBJ_ID;
          SUSPEND;
          TAG_NAME = 'structures:item:points:point:date_add';
          VAL = (SELECT VAL FROM DATE2ISO(:V$T1));
          SUSPEND;
          TAG_NAME = 'structures:item:points:point:date_modify';
          VAL = (SELECT VAL FROM DATE2ISO(:V$T2));
          SUSPEND;
          TAG_NAME = 'structures:item:points:point:date_del';
          VAL = (SELECT VAL FROM DATE2ISO(:V$T3));
          SUSPEND;

          TAG_NAME = 'structures:item:points:point:type_id';
          VAL = V$Q_TYPE_ID;
          SUSPEND;
          TAG_NAME = 'structures:item:points:point:order';
          VAL = V$Q_ORDER;
          SUSPEND;
          TAG_NAME = 'structures:item:points:point:level';
          VAL = V$Q_LEVEL;
          SUSPEND;
          TAG_NAME = 'structures:item:points:point:max_score';
          VAL = V$Q_MAX_SCORE;
          SUSPEND;
          TAG_NAME = 'structures:item:points:point:charset_id';
          VAL = V$CHARSET_ID;
          SUSPEND;
          TAG_NAME = 'structures:item:points:point:text_notes';
          VAL = V$S;
          SUSPEND;
          TAG_NAME = 'structures:item:points:point:wnd_min';
          VAL = V$WND_MIN;
          SUSPEND;
          TAG_NAME = 'structures:item:points:point:wnd_max';
          VAL = V$WND_MAX;
          SUSPEND;
      END
  END

  -- Кодификаторы для использованных вопросов
  TAG_NAME = 'coding';
  VAL = NULL;
  SUSPEND;
  FOR
      SELECT DISTINCT KC.OBJ_ID, KC.DATE_ADD, KC.DATE_MODIFY, KC.DATE_DEL, KC.OBJ_NAME, KC.N_LEVELS, KC.OWNER_LEVEL, KC.OWNER_ID
      FROM UT_EXAM_TEST_VARS ETV
      JOIN UT_TEST_VARS TV ON TV.OBJ_ID = ETV.TEST_VAR_ID
      JOIN UT_TEST_VAR_QUESTIONS TVQ ON TVQ.VAR_ID = TV.OBJ_ID AND TVQ.DATE_DEL IS NULL
      JOIN UT_QUESTIONS Q ON Q.OBJ_ID = TVQ.QUESTION_ID
      JOIN UT_KIM_CODING_LEVELS KCL ON KCL.OBJ_ID = Q.SECTION_ID
      JOIN UT_KIM_CODING KC ON KC.OBJ_ID = KCL.CODING_ID
      WHERE ETV.EXAM_ID = :I$EXAM_ID AND ETV.DATE_DEL IS NULL
      INTO :V$STRUCT_ID, :V$T1, :V$T2, :V$T3, :V$S, :V$N, :V$N_LEVEL, :V$OWNER_ID
  DO
  BEGIN
      TAG_NAME = 'coding:item';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'coding:item:id';
      VAL = V$STRUCT_ID;
      SUSPEND;
      TAG_NAME = 'coding:item:date_add';
      VAL = (SELECT VAL FROM DATE2ISO(:V$T1));
      SUSPEND;
      TAG_NAME = 'coding:item:date_modify';
      VAL = (SELECT VAL FROM DATE2ISO(:V$T2));
      SUSPEND;
      TAG_NAME = 'coding:item:date_del';
      VAL = (SELECT VAL FROM DATE2ISO(:V$T3));
      SUSPEND;
      IF(V$T3 IS NULL) THEN
      BEGIN
          TAG_NAME = 'coding:item:obj_name';
          VAL = V$S;
          SUSPEND;
          TAG_NAME = 'coding:item:n_levels';
          VAL = V$N;
          SUSPEND;
          TAG_NAME = 'coding:item:owner_level';
          VAL = V$N_LEVEL;
          SUSPEND;
          TAG_NAME = 'coding:item:owner_id';
          VAL = V$OWNER_ID;
          SUSPEND;
      END

      TAG_NAME = 'coding:item:stages';
      VAL = NULL;
      SUSPEND;
      FOR
          SELECT D.OBJ_ID, D.STAGE_ID, D.DATE_ADD, D.DATE_MODIFY, D.DATE_DEL
          FROM UT_KIM_CODING_STAGES D
          WHERE D.CODING_ID = :V$STRUCT_ID
          INTO :V$OBJ_ID, :V$N, :V$T1, :V$T2, :V$T3
      DO
      BEGIN
          TAG_NAME = 'coding:item:stages:stage';
          VAL = NULL;
          SUSPEND;
          TAG_NAME = 'coding:item:stages:stage:id';
          VAL = V$OBJ_ID;
          SUSPEND;
          TAG_NAME = 'coding:item:stages:stage:stage_id';
          VAL = V$N;
          SUSPEND;
          TAG_NAME = 'coding:item:stages:stage:date_add';
          VAL = (SELECT VAL FROM DATE2ISO(:V$T1));
          SUSPEND;
          TAG_NAME = 'coding:item:stages:stage:date_modify';
          VAL = (SELECT VAL FROM DATE2ISO(:V$T2));
          SUSPEND;
          TAG_NAME = 'coding:item:stages:stage:date_del';
          VAL = (SELECT VAL FROM DATE2ISO(:V$T3));
          SUSPEND;
      END

      TAG_NAME = 'coding:item:subjects';
      VAL = NULL;
      SUSPEND;
      FOR
          SELECT D.OBJ_ID, D.SUBJECT_ID, D.DATE_ADD, D.DATE_MODIFY, D.DATE_DEL
          FROM UT_KIM_CODING_SUBJECTS D
          WHERE D.CODING_ID = :V$STRUCT_ID
          INTO :V$OBJ_ID, :V$VAR_ID, :V$T1, :V$T2, :V$T3
      DO
      BEGIN
          TAG_NAME = 'coding:item:subjects:subject';
          VAL = NULL;
          SUSPEND;
          TAG_NAME = 'coding:item:subjects:subject:id';
          VAL = V$OBJ_ID;
          SUSPEND;
          TAG_NAME = 'coding:item:subjects:subject:subject_id';
          VAL = V$VAR_ID;
          SUSPEND;
          TAG_NAME = 'coding:item:subjects:subject:date_add';
          VAL = (SELECT VAL FROM DATE2ISO(:V$T1));
          SUSPEND;
          TAG_NAME = 'coding:item:subjects:subject:date_modify';
          VAL = (SELECT VAL FROM DATE2ISO(:V$T2));
          SUSPEND;
          TAG_NAME = 'coding:item:subjects:subject:date_del';
          VAL = (SELECT VAL FROM DATE2ISO(:V$T3));
          SUSPEND;
      END

      -- Дочерние разделы собираем в порядке следования по уровням дерева
      TAG_NAME = 'coding:item:sections';
      VAL = NULL;
      SUSPEND;
      IF(V$T3 IS NULL) THEN
      FOR
          SELECT KCL.OBJ_ID, KCL.DATE_ADD, KCL.DATE_MODIFY, KCL.DATE_DEL, KCL.PARENT_ID, KCL.OBJ_NAME, KCL.N_LEVEL, KCL.SORT_ORDER
          FROM UT_TEST_EXPORT_CS(:V$STRUCT_ID, NULL) TS
          JOIN UT_KIM_CODING_LEVELS KCL ON KCL.OBJ_ID = TS.OBJ_ID
          WHERE :V$T3 IS NULL
          INTO :V$OBJ_ID, :V$T1, :V$T2, :V$T3, :V$OWNER_ID, :V$S, :V$N_LEVEL, :V$Q_ORDER
      DO
      BEGIN
          TAG_NAME = 'coding:item:sections:section';
          VAL = NULL;
          SUSPEND;
          TAG_NAME = 'coding:item:sections:section:id';
          VAL = V$OBJ_ID;
          SUSPEND;
          TAG_NAME = 'coding:item:sections:section:date_add';
          VAL = (SELECT VAL FROM DATE2ISO(:V$T1));
          SUSPEND;
          TAG_NAME = 'coding:item:sections:section:date_modify';
          VAL = (SELECT VAL FROM DATE2ISO(:V$T2));
          SUSPEND;
          TAG_NAME = 'coding:item:sections:section:date_del';
          VAL = (SELECT VAL FROM DATE2ISO(:V$T3));
          SUSPEND;

          IF(V$T3 IS NULL) THEN
          BEGIN
              TAG_NAME = 'coding:item:sections:section:obj_name';
              VAL = V$S;
              SUSPEND;
              TAG_NAME = 'coding:item:sections:section:order';
              VAL = V$Q_ORDER;
              SUSPEND;
              TAG_NAME = 'coding:item:sections:section:n_level';
              VAL = V$N_LEVEL;
              SUSPEND;
              TAG_NAME = 'coding:item:sections:section:parent_id';
              VAL = V$OWNER_ID;
              SUSPEND;
          END
      END
  END

  -- Вопросы, участвующие в данном тесте (бинарные данные подгружаются позднее)
  TAG_NAME = 'questions';
  VAL = NULL;
  SUSPEND;
  FOR
      SELECT Q.OBJ_ID, Q.DATE_ADD, Q.DATE_MODIFY, Q.DATE_DEL, Q.PARENT_ID, Q.SECTION_ID, Q.OBJ_NAME, Q.SORT_ORDER, Q.QUESTION_TYPE, Q.MAX_SCORE, Q.TIME_LIMIT,
          Q.METADATA_ID, Q.FLAGS, Q.CHARSET_ID, Q.Q_LEVEL, Q.FILE_SIZE, Q.K
      FROM UT_EXAM_TEST_VARS ETV
      JOIN UT_TEST_VARS TV ON TV.OBJ_ID = ETV.TEST_VAR_ID
      JOIN UT_TEST_VAR_QUESTIONS TVQ ON TVQ.VAR_ID = TV.OBJ_ID AND TVQ.DATE_DEL IS NULL
      JOIN UT_QUESTIONS Q ON Q.OBJ_ID = TVQ.QUESTION_ID
      WHERE ETV.EXAM_ID = :I$EXAM_ID AND ETV.DATE_DEL IS NULL
      INTO :V$STRUCT_ID, :V$T1, :V$T2, :V$T3, :V$OWNER_ID, :V$SUBJECT_ID, :V$S, :V$Q_ORDER, :V$Q_TYPE_ID, :V$Q_MAX_SCORE, :V$TIME,
           :V$METADATA_ID, :V$N, :V$CHARSET_ID, :V$Q_LEVEL, :V$FILE_SIZE, :V$K
  DO
  BEGIN
      TAG_NAME = 'questions:item';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'questions:item:id';
      VAL = V$STRUCT_ID;
      SUSPEND;
      TAG_NAME = 'questions:item:date_add';
      VAL = (SELECT VAL FROM DATE2ISO(:V$T1));
      SUSPEND;
      TAG_NAME = 'questions:item:date_modify';
      VAL = (SELECT VAL FROM DATE2ISO(:V$T2));
      SUSPEND;
      TAG_NAME = 'questions:item:date_del';
      VAL = (SELECT VAL FROM DATE2ISO(:V$T3));
      SUSPEND;
      IF(V$T3 IS NULL) THEN
      BEGIN
          TAG_NAME = 'questions:item:obj_name';
          VAL = V$S;
          SUSPEND;
          TAG_NAME = 'questions:item:section_id';
          VAL = V$SUBJECT_ID;
          SUSPEND;
          TAG_NAME = 'questions:item:parent_id';
          VAL = V$OWNER_ID;
          SUSPEND;
          TAG_NAME = 'questions:item:order';
          VAL = V$Q_ORDER;
          SUSPEND;
          TAG_NAME = 'questions:item:type';
          VAL = V$Q_TYPE_ID;
          SUSPEND;
          TAG_NAME = 'questions:item:max_score';
          VAL = V$Q_MAX_SCORE;
          SUSPEND;
          TAG_NAME = 'questions:item:time_limit';
          VAL = V$TIME;
          SUSPEND;
          TAG_NAME = 'questions:item:metadata_id';
          VAL = V$METADATA_ID;
          SUSPEND;
          TAG_NAME = 'questions:item:flags';
          VAL = V$N;
          SUSPEND;
          TAG_NAME = 'questions:item:charset_id';
          VAL = V$CHARSET_ID;
          SUSPEND;
          TAG_NAME = 'questions:item:level';
          VAL = V$Q_LEVEL;
          SUSPEND;
          TAG_NAME = 'questions:item:file_size';
          VAL = V$FILE_SIZE;
          SUSPEND;
          TAG_NAME = 'questions:item:k';
          VAL = V$K;
          SUSPEND;
      END

      -- Критерии и ключи ответов - бинарные данные подгружаются позднее
      TAG_NAME = 'questions:item:answers';
      VAL = NULL;
      SUSPEND;
      FOR
          SELECT A.OBJ_ID, A.DATE_ADD, A.DATE_MODIFY, A.DATE_DEL, A.SORT_ORDER, A.A_LEVEL, A.OBJ_NAME, A.FAKE_ORDER, A.SIGNATURE
          FROM UT_ANSWERS A
          WHERE A.QUESTION_ID = :V$STRUCT_ID
          INTO :V$OBJ_ID, :V$T1, :V$T2, :V$T3, :V$Q_ORDER, :V$Q_LEVEL, :V$S, :V$N, :V$N_LEVEL
      DO
      BEGIN
          TAG_NAME = 'questions:item:answers:answer';
          VAL = NULL;
          SUSPEND;
          TAG_NAME = 'questions:item:answers:answer:id';
          VAL = V$OBJ_ID;
          SUSPEND;
          TAG_NAME = 'questions:item:answers:answer:date_add';
          VAL = (SELECT VAL FROM DATE2ISO(:V$T1));
          SUSPEND;
          TAG_NAME = 'questions:item:answers:answer:date_modify';
          VAL = (SELECT VAL FROM DATE2ISO(:V$T2));
          SUSPEND;
          TAG_NAME = 'questions:item:answers:answer:date_del';
          VAL = (SELECT VAL FROM DATE2ISO(:V$T3));
          SUSPEND;

          IF(V$T3 IS NULL) THEN
          BEGIN
              TAG_NAME = 'questions:item:answers:answer:obj_name';
              VAL = V$S;
              SUSPEND;
              TAG_NAME = 'questions:item:answers:answer:order';
              VAL = V$Q_ORDER;
              SUSPEND;
              TAG_NAME = 'questions:item:answers:answer:a_level';
              VAL = V$Q_LEVEL;
              SUSPEND;
              TAG_NAME = 'questions:item:answers:answer:f_order';
              VAL = V$N;
              SUSPEND;
              TAG_NAME = 'questions:item:answers:answer:signature';
              VAL = V$N_LEVEL;
              SUSPEND;
          END
      END
  END

  -- Все пакеты тестов, варианты из которых задействованы в тестировании - только задействованные варианты
  -- + сами варианты
  -- ++ вопросы вариантов
  TAG_NAME = 'tests';
  VAL = NULL;
  SUSPEND;
  FOR
      SELECT DISTINCT T.OBJ_ID, T.DATE_ADD, T.DATE_MODIFY, T.DATE_DEL, T.OBJ_NAME, T.MASTER_ED_ID, T.STRUCT_ID, T.CODING_ID
      FROM UT_EXAM_TEST_VARS ETV
      JOIN UT_TEST_VARS TV ON TV.OBJ_ID = ETV.TEST_VAR_ID
      JOIN UT_TESTS T ON T.OBJ_ID = TV.TEST_ID
      WHERE ETV.EXAM_ID = :I$EXAM_ID AND ETV.DATE_DEL IS NULL
      INTO :V$STRUCT_ID, :V$T1, :V$T2, :V$T3, :V$S, :V$OBJ_ID, :V$SUBJECT_ID, :V$VAR_ID
  DO
  BEGIN
      TAG_NAME = 'tests:item';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'tests:item:id';
      VAL = V$STRUCT_ID;
      SUSPEND;
      TAG_NAME = 'tests:item:date_add';
      VAL = (SELECT VAL FROM DATE2ISO(:V$T1));
      SUSPEND;
      TAG_NAME = 'tests:item:date_modify';
      VAL = (SELECT VAL FROM DATE2ISO(:V$T2));
      SUSPEND;
      TAG_NAME = 'tests:item:date_del';
      VAL = (SELECT VAL FROM DATE2ISO(:V$T3));
      SUSPEND;
      IF(V$T3 IS NULL) THEN
      BEGIN
          TAG_NAME = 'tests:item:obj_name';
          VAL = V$S;
          SUSPEND;
          TAG_NAME = 'tests:item:struct_id';
          VAL = V$SUBJECT_ID;
          SUSPEND;
          TAG_NAME = 'tests:item:master_ed_id';
          VAL = V$OBJ_ID;
          SUSPEND;
          TAG_NAME = 'tests:item:coding_id';
          VAL = V$VAR_ID;
          SUSPEND;
      END

      TAG_NAME = 'tests:item:variants';
      VAL = NULL;
      SUSPEND;
      IF(V$T3 IS NULL) THEN
      FOR
          SELECT TV.OBJ_ID, TV.DATE_ADD, TV.DATE_MODIFY, TV.DATE_DEL, TV.NUM, TV.OBJ_NAME, TV.MASTER_ED_ID
          FROM UT_EXAM_TEST_VARS ETV
          JOIN UT_TEST_VARS TV ON TV.OBJ_ID = ETV.TEST_VAR_ID AND TV.TEST_ID = :V$STRUCT_ID
          WHERE ETV.EXAM_ID = :I$EXAM_ID AND ETV.DATE_DEL IS NULL
          INTO :V$VAR_ID, :V$T1, :V$T2, :V$T3, :V$N, :V$S, :V$OWNER_ID
      DO
      BEGIN
          TAG_NAME = 'tests:item:variants:variant';
          VAL = NULL;
          SUSPEND;
          TAG_NAME = 'tests:item:variants:variant:id';
          VAL = V$VAR_ID;
          SUSPEND;
          TAG_NAME = 'tests:item:variants:variant:date_add';
          VAL = (SELECT VAL FROM DATE2ISO(:V$T1));
          SUSPEND;
          TAG_NAME = 'tests:item:variants:variant:date_modify';
          VAL = (SELECT VAL FROM DATE2ISO(:V$T2));
          SUSPEND;
          TAG_NAME = 'tests:item:variants:variant:date_del';
          VAL = (SELECT VAL FROM DATE2ISO(:V$T3));
          SUSPEND;

          IF(V$T3 IS NULL) THEN
          BEGIN
              TAG_NAME = 'tests:item:variants:variant:obj_name';
              VAL = V$S;
              SUSPEND;
              TAG_NAME = 'tests:item:variants:variant:num';
              VAL = V$N;
              SUSPEND;
              TAG_NAME = 'tests:item:variants:variant:master_ed_id';
              VAL = V$OWNER_ID;
              SUSPEND;
          END

          -- Вопросы в не-удаленных вариантах
          TAG_NAME = 'tests:item:variants:variant:questions';
          VAL = NULL;
          SUSPEND;
          IF(V$T3 IS NULL) THEN
          FOR
              SELECT TVQ.OBJ_ID, TVQ.DATE_ADD, TVQ.DATE_MODIFY, TVQ.DATE_DEL, TVQ.ORDER_INDEX, TVQ.STRUCT_POINT_ID, TVQ.QUESTION_ID
              FROM UT_TEST_VARS TV
              JOIN UT_TEST_VAR_QUESTIONS TVQ ON TVQ.VAR_ID = TV.OBJ_ID
              WHERE TV.OBJ_ID = :V$VAR_ID
              INTO :V$OBJ_ID, :V$T1, :V$T2, :V$T3, :V$Q_ORDER, :V$OWNER_ID, :V$SUBJECT_ID
          DO
          BEGIN
              TAG_NAME = 'tests:item:variants:variant:questions:question';
              VAL = NULL;
              SUSPEND;
              TAG_NAME = 'tests:item:variants:variant:questions:question:id';
              VAL = V$OBJ_ID;
              SUSPEND;
              TAG_NAME = 'tests:item:variants:variant:questions:question:date_add';
              VAL = (SELECT VAL FROM DATE2ISO(:V$T1));
              SUSPEND;
              TAG_NAME = 'tests:item:variants:variant:questions:question:date_modify';
              VAL = (SELECT VAL FROM DATE2ISO(:V$T2));
              SUSPEND;
              TAG_NAME = 'tests:item:variants:variant:questions:question:date_del';
              VAL = (SELECT VAL FROM DATE2ISO(:V$T3));
              SUSPEND;

              IF(V$T3 IS NULL) THEN
              BEGIN
                  TAG_NAME = 'tests:item:variants:variant:questions:question:order';
                  VAL = V$Q_ORDER;
                  SUSPEND;
                  TAG_NAME = 'tests:item:variants:variant:questions:question:point_id';
                  VAL = V$OWNER_ID;
                  SUSPEND;
                  TAG_NAME = 'tests:item:variants:variant:questions:question:question_id';
                  VAL = V$SUBJECT_ID;
                  SUSPEND;
              END
          END
      END
  END

  -- Ссылки на варианты
  TAG_NAME = 'variants';
  VAL = NULL;
  SUSPEND;
  FOR
      SELECT ETV.OBJ_ID, ETV.DATE_ADD, ETV.DATE_MODIFY, ETV.DATE_DEL, ETV.TEST_VAR_ID
      FROM UT_EXAM_TEST_VARS ETV
      WHERE ETV.EXAM_ID = :I$EXAM_ID
      INTO :V$STRUCT_ID, :V$T1, :V$T2, :V$T3, :V$OBJ_ID
  DO
  BEGIN
      TAG_NAME = 'variants:item';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'variants:item:id';
      VAL = V$STRUCT_ID;
      SUSPEND;
      TAG_NAME = 'variants:item:date_add';
      VAL = (SELECT VAL FROM DATE2ISO(:V$T1));
      SUSPEND;
      TAG_NAME = 'variants:item:date_modify';
      VAL = (SELECT VAL FROM DATE2ISO(:V$T2));
      SUSPEND;
      TAG_NAME = 'variants:item:date_del';
      VAL = (SELECT VAL FROM DATE2ISO(:V$T3));
      SUSPEND;
      IF(V$T3 IS NULL) THEN
      BEGIN
          TAG_NAME = 'variants:item:variant_id';
          VAL = V$OBJ_ID;
          SUSPEND;
      END
  END

  -- Списки назначений
  -- Выбор участников
  TAG_NAME = 'person_assn';
  VAL = NULL;
  SUSPEND;
  FOR
      SELECT PA.OBJ_ID, PA.DATE_ADD, PA.DATE_MODIFY, PA.DATE_DEL, PA.PERSON_ID, PA.LOCAL_ID, PA.BLANKS_PRINTED, PA.OU_ID, PA.AREA_ID
      FROM UT_EXAM_PERSON_ASSN PA
      WHERE PA.EXAM_ID = :I$EXAM_ID
      INTO :V$OBJ_ID, :V$T1, :V$T2, :V$T3, :V$OWNER_ID, :V$METADATA_ID, :V$N, :V$OU_ID, :V$AREA_ID
  DO
  BEGIN
      TAG_NAME = 'person_assn:item';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'person_assn:item:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'person_assn:item:date_add';
      VAL = (SELECT VAL FROM DATE2ISO(:V$T1));
      SUSPEND;
      TAG_NAME = 'person_assn:item:date_modify';
      VAL = (SELECT VAL FROM DATE2ISO(:V$T2));
      SUSPEND;
      TAG_NAME = 'person_assn:item:date_del';
      VAL = (SELECT VAL FROM DATE2ISO(:V$T3));
      SUSPEND;
      IF(V$T3 IS NULL) THEN
      BEGIN
          TAG_NAME = 'person_assn:item:person_id';
          VAL = V$OWNER_ID;
          SUSPEND;
          TAG_NAME = 'person_assn:item:local_id';
          VAL = V$METADATA_ID;
          SUSPEND;
          TAG_NAME = 'person_assn:item:blanks_printed';
          VAL = V$N;
          SUSPEND;
          TAG_NAME = 'person_assn:item:ou_id';
          VAL = V$OU_ID;
          SUSPEND;
          TAG_NAME = 'person_assn:item:area_id';
          VAL = V$AREA_ID;
          SUSPEND;
      END
  END

  -- Список экспертов. Временное решение
  TAG_NAME = 'experts';
  VAL = NULL;
  SUSPEND;
  FOR
      SELECT DISTINCT E.EXPERT_ID, E.DATE_ADD, E.DATE_MODIFY, E.DATE_DEL, E.TEACHER_ID, E.ORG_ID, E.USER_NAME, E.PWD, E.IS_ACTIVE, E.LAST_NAME, E.FIRST_NAME, E.MIDDLE_NAME
      FROM UT_EXAM_EXPERT_ASSN PA
      JOIN UT_EXPERTS E ON E.EXPERT_ID = PA.EXPERT_ID
      WHERE PA.EXAM_ID = :I$EXAM_ID
      INTO :V$OBJ_ID, :V$T1, :V$T2, :V$T3, :V$STRUCT_ID, :V$OWNER_ID, :V$S, :V$METADATA_ID, :V$N, :V$S1, :V$S2, :V$S3
  DO
  BEGIN
      TAG_NAME = 'experts:item';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'experts:item:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'experts:item:date_add';
      VAL = (SELECT VAL FROM DATE2ISO(:V$T1));
      SUSPEND;
      TAG_NAME = 'experts:item:date_modify';
      VAL = (SELECT VAL FROM DATE2ISO(:V$T2));
      SUSPEND;
      TAG_NAME = 'experts:item:date_del';
      VAL = (SELECT VAL FROM DATE2ISO(:V$T3));
      SUSPEND;
      IF(V$T3 IS NULL) THEN
      BEGIN
          TAG_NAME = 'experts:item:teacher_id';
          VAL = V$STRUCT_ID;
          SUSPEND;
          TAG_NAME = 'experts:item:org_id';
          VAL = V$OWNER_ID;
          SUSPEND;
          TAG_NAME = 'experts:item:username';
          VAL = V$S;
          SUSPEND;
          TAG_NAME = 'experts:item:password';
          VAL = V$METADATA_ID;
          SUSPEND;
          TAG_NAME = 'experts:item:is_active';
          VAL = V$N;
          SUSPEND;
          TAG_NAME = 'experts:item:name_last';
          VAL = V$S1;
          SUSPEND;
          TAG_NAME = 'experts:item:name_first';
          VAL = V$S2;
          SUSPEND;
          TAG_NAME = 'experts:item:name_mid';
          VAL = V$S3;
          SUSPEND;
      END
  END

  -- Назначение экспертов
  TAG_NAME = 'expert_assn';
  VAL = NULL;
  SUSPEND;
  FOR
      SELECT PA.OBJ_ID, PA.DATE_ADD, PA.DATE_MODIFY, PA.DATE_DEL, PA.EXPERT_ID, PA.ROLE_ID, PA.SECOND_CHECK
      FROM UT_EXAM_EXPERT_ASSN PA
      WHERE PA.EXAM_ID = :I$EXAM_ID
      INTO :V$OBJ_ID, :V$T1, :V$T2, :V$T3, :V$OWNER_ID, :V$Q_LEVEL, :V$N
  DO
  BEGIN
      TAG_NAME = 'expert_assn:item';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'expert_assn:item:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'expert_assn:item:date_add';
      VAL = (SELECT VAL FROM DATE2ISO(:V$T1));
      SUSPEND;
      TAG_NAME = 'expert_assn:item:date_modify';
      VAL = (SELECT VAL FROM DATE2ISO(:V$T2));
      SUSPEND;
      TAG_NAME = 'expert_assn:item:date_del';
      VAL = (SELECT VAL FROM DATE2ISO(:V$T3));
      SUSPEND;
      IF(V$T3 IS NULL) THEN
      BEGIN
          TAG_NAME = 'expert_assn:item:expert_id';
          VAL = V$OWNER_ID;
          SUSPEND;
          TAG_NAME = 'expert_assn:item:role';
          VAL = V$Q_LEVEL;
          SUSPEND;
          TAG_NAME = 'expert_assn:item:second_check';
          VAL = V$N;
          SUSPEND;
      END
  END

  -- Сотрудники пока пустые
  TAG_NAME = 'stuff_assn';
  VAL = NULL;
  SUSPEND;

  -- Список ППЭ - передается только с уровня города
  -- Назначение ППЭ - передается только с уровня города
  IF(V$DB_LEVEL = 2) THEN
  BEGIN
      TAG_NAME = 'ppe';
      VAL = NULL;
      SUSPEND;

      TAG_NAME = 'ppe_assn';
      VAL = NULL;
      SUSPEND;
  END

-- Распредение участников по ППЭ - передается только с уровня города, но может дополняться случайными абитуриентами с уровня ОУ
  TAG_NAME = 'person_ppe_assn';
  VAL = NULL;
  SUSPEND;

  -- Назначение помещений ППЭ
  TAG_NAME = 'room_assn';
  VAL = NULL;
  SUSPEND;

  -- Рассадка участников
  TAG_NAME = 'place_assn';
  VAL = NULL;
  SUSPEND;

    -- Список файлов, прикрепеленных к данному тестированию
  TAG_NAME = 'files';
  VAL = NULL;
  SUSPEND;
  FOR
    SELECT FL.OBJ_ID, FL.DATE_ADD, FL.DATE_MODIFY, FL.DATE_DEL, FL.VAR_ID, FL.OBJ_NAME, FL.FILE_HASH, FL.CONTENT_TYPE, FL.ATTR_MASK
    FROM UT_EXAM_TEST_VARS ETV
    JOIN UT_TEST_VARS TV ON TV.OBJ_ID = ETV.TEST_VAR_ID
    JOIN UT_TEST_VAR_FILES FL ON FL.VAR_ID = TV.OBJ_ID AND FL.DATE_DEL IS NULL
    WHERE ETV.EXAM_ID = :I$EXAM_ID
    INTO :V$OBJ_ID, :V$T1, :V$T2, :V$T3, :V$OU_ID, :V$S1, :V$S2, :V$S3, :V$STAGE_ID
  DO
  BEGIN
    TAG_NAME = 'files:item';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'files:item:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'files:item:date_add';
    VAL = (SELECT VAL FROM DATE2ISO(:V$T1));
    SUSPEND;
    TAG_NAME = 'files:item:date_modify';
    VAL = (SELECT VAL FROM DATE2ISO(:V$T2));
    SUSPEND;
    TAG_NAME = 'files:item:date_del';
    VAL = (SELECT VAL FROM DATE2ISO(:V$T3));
    SUSPEND;
    TAG_NAME = 'files:item:var_id';
    VAL = V$OU_ID;
    SUSPEND;
    TAG_NAME = 'files:item:file_name';
    VAL = V$S1;
    SUSPEND;
    TAG_NAME = 'files:item:file_hash';
    VAL = V$S2;
    SUSPEND;
    TAG_NAME = 'files:item:content_type';
    VAL = V$S3;
    SUSPEND;
    TAG_NAME = 'files:item:attr_mask';
    VAL = V$STAGE_ID;
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_EXPORT_P1 (
    I$EXAM_ID BIGINT)
RETURNS (
    REF_ID BIGINT,
    REF_TYPE VARCHAR(20),
    BLOB_DATA BLOB SUB_TYPE 1 SEGMENT SIZE 80)
AS
begin

  -- Начальный текст пояснений к структуре (элементы структуры идут в основной выгрузке)
  REF_TYPE = 'structure';
  FOR
      SELECT DISTINCT TS.OBJ_ID, TS.TEXT_NOTES
      FROM UT_EXAM_TEST_VARS ETV
      JOIN UT_TEST_VARS TV ON TV.OBJ_ID = ETV.TEST_VAR_ID
      JOIN UT_TESTS T ON T.OBJ_ID = TV.TEST_ID AND T.DATE_DEL IS NULL
      JOIN UT_TEST_STRUCTS TS ON TS.OBJ_ID = T.STRUCT_ID AND TS.DATE_DEL IS NULL
      WHERE ETV.EXAM_ID = :I$EXAM_ID AND ETV.DATE_DEL IS NULL
      INTO :REF_ID, :BLOB_DATA
  DO
  BEGIN
      SUSPEND;
  END

  REF_TYPE = 'qtext';
  FOR
      SELECT Q.OBJ_ID, Q.QUESTION
      FROM UT_EXAM_TEST_VARS ETV
      JOIN UT_TEST_VARS TV ON TV.OBJ_ID = ETV.TEST_VAR_ID
      JOIN UT_TEST_VAR_QUESTIONS TVQ ON TVQ.VAR_ID = TV.OBJ_ID AND TVQ.DATE_DEL IS NULL
      JOIN UT_QUESTIONS Q ON Q.OBJ_ID = TVQ.QUESTION_ID AND Q.DATE_DEL IS NULL
      WHERE ETV.EXAM_ID = :I$EXAM_ID AND ETV.DATE_DEL IS NULL
      INTO :REF_ID, :BLOB_DATA
  DO
  BEGIN
      SUSPEND;
  END

  REF_TYPE = 'qhint';
  FOR
      SELECT Q.OBJ_ID, Q.HINT
      FROM UT_EXAM_TEST_VARS ETV
      JOIN UT_TEST_VARS TV ON TV.OBJ_ID = ETV.TEST_VAR_ID
      JOIN UT_TEST_VAR_QUESTIONS TVQ ON TVQ.VAR_ID = TV.OBJ_ID AND TVQ.DATE_DEL IS NULL
      JOIN UT_QUESTIONS Q ON Q.OBJ_ID = TVQ.QUESTION_ID AND Q.DATE_DEL IS NULL
      WHERE ETV.EXAM_ID = :I$EXAM_ID AND ETV.DATE_DEL IS NULL
      INTO :REF_ID, :BLOB_DATA
  DO
  BEGIN
      SUSPEND;
  END

  REF_TYPE = 'qa';
  FOR
      SELECT A.OBJ_ID, A.VARIANT
      FROM UT_EXAM_TEST_VARS ETV
      JOIN UT_TEST_VARS TV ON TV.OBJ_ID = ETV.TEST_VAR_ID
      JOIN UT_TEST_VAR_QUESTIONS TVQ ON TVQ.VAR_ID = TV.OBJ_ID AND TVQ.DATE_DEL IS NULL
      JOIN UT_QUESTIONS Q ON Q.OBJ_ID = TVQ.QUESTION_ID AND Q.DATE_DEL IS NULL
      JOIN UT_ANSWERS A ON A.QUESTION_ID = Q.OBJ_ID AND A.DATE_DEL IS NULL
      WHERE ETV.EXAM_ID = :I$EXAM_ID AND ETV.DATE_DEL IS NULL
      INTO :REF_ID, :BLOB_DATA
  DO
  BEGIN
      SUSPEND;
  END

  REF_TYPE = 'template:front';
  FOR
      SELECT PT.OBJ_ID, PT.DATA_FRONT
      FROM UT_EXAM_DATES D
      JOIN UT_PAGE_TEMPLATES PT ON (PT.OBJ_ID = D.BLANK_AB_ID OR PT.OBJ_ID = D.BLANK_C_ID OR PT.OBJ_ID = D.BLANK_EXT_ID OR PT.OBJ_ID = D.BLANK_GEN_ID)
          AND PT.DATA_FRONT IS NULL
      WHERE D.OBJ_ID = :I$EXAM_ID
      INTO :REF_ID, :BLOB_DATA
  DO
  BEGIN
      SUSPEND;
  END
  REF_TYPE = 'template:back';
  FOR
      SELECT PT.OBJ_ID, PT.DATA_BACK
      FROM UT_EXAM_DATES D
      JOIN UT_PAGE_TEMPLATES PT ON (PT.OBJ_ID = D.BLANK_AB_ID OR PT.OBJ_ID = D.BLANK_C_ID OR PT.OBJ_ID = D.BLANK_EXT_ID OR PT.OBJ_ID = D.BLANK_GEN_ID)
          AND PT.DATA_BACK IS NULL
      WHERE D.OBJ_ID = :I$EXAM_ID
      INTO :REF_ID, :BLOB_DATA
  DO
  BEGIN
      SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_EXT_BLANKS (
    I$EXAM_ID BIGINT,
    I$N_BLANKS INTEGER,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
declare variable V$DB_LEVEL integer;
declare variable V$USER_ID bigint;
declare variable V$STATE integer;
declare variable V$LOCAL_ID varchar(40);
declare variable V$DATE date;
declare variable V$NAME varchar(200);
declare variable V$STAGE_ID integer;
declare variable V$SUBJECT_ID bigint;
declare variable V$OU_NAME varchar(200);
declare variable V$OBJ_ID bigint;
declare variable BASE integer;
declare variable N integer;
begin

  IF(I$N_BLANKS IS NULL OR I$N_BLANKS < 0 OR I$N_BLANKS > 100) THEN EXCEPTION DATA_ERROR 'Некорректное количество бланков';

  IF(I$USER_ID = 'Веб-администратор') THEN V$USER_ID = 1; ELSE V$USER_ID = CAST(I$USER_ID AS BIGINT);

  -- Первыми строками возвращаются шаблоны всех бланков в BLOB_ID, в TAG_NAME передается текст BLOB, в VAL описание бланка
  -- После чего выдаются уже сериализованные данные по участнику

  SELECT D.EXAM_STATE, D.EXAM_DATE_START, D.OBJ_NAME, D.SUBJECT_ID, D.STAGE_ID
  FROM UT_EXAM_DATES D
  WHERE D.OBJ_ID = :I$EXAM_ID AND D.DATE_DEL IS NULL
  INTO :V$STATE, :V$DATE, :V$NAME, :V$SUBJECT_ID, :V$STAGE_ID;

  IF(V$STATE IS NULL) THEN EXCEPTION DATA_ERROR 'Тестирование не найдено или было удалено';
  IF(V$STATE < 600 OR V$STATE >= 1000) THEN EXCEPTION DATA_ERROR 'Недопустимый статус тестирования';

  SELECT COALESCE(CAST(K.KEY_VAL AS INTEGER) - 1, 0)
  FROM KEYS K
  WHERE K.KEY_CODE = 'LEVEL'
  INTO :V$DB_LEVEL;

  IF(V$DB_LEVEL <> 0) THEN EXCEPTION DATA_ERROR 'Печать дополнительных бланков возможна только непосредственно в ОУ/ППЭ';

  TAG_NAME = 'data:exam_id';
  VAL = I$EXAM_ID;
  SUSPEND;

  TAG_NAME = 'data:exam_name';
  VAL = V$NAME;
  SUSPEND;

  TAG_NAME = 'data:subject_name';
  IF(V$SUBJECT_ID IS NULL) THEN VAL = 'Метапредмет'; ELSE VAL = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$SUBJECT_ID));
  SUSPEND;

  TAG_NAME = 'data:stage_name';
  VAL = (SELECT OBJ_NAME FROM UT_EXAM_STAGES WHERE OBJ_ID = :V$STAGE_ID);
  SUSPEND;

  TAG_NAME = 'data:exam_date_start';
  VAL = (SELECT VAL FROM DATE2ISO(:V$DATE, 0));
  SUSPEND;

  TAG_NAME = 'data:exam_date_str';
  VAL = (SELECT RESULT FROM DATE2STR(:V$DATE));
  SUSPEND;

  TAG_NAME = 'data:ou_name';
  VAL = NULL;
  SELECT FIRST 1 L2.OBJ_ID, C.CAPTION
  FROM LINKS L2
  LEFT JOIN OBJECT_CAPTION_GET(L2.OBJ_ID) C ON 1 = 1
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$OBJ_ID, :VAL;
  SUSPEND;

  TAG_NAME = 'data:ppe_id';
  VAL = V$OBJ_ID;
  SUSPEND;

  TAG_NAME = 'data:ppe_name';
  VAL = '-';
  SUSPEND;

  -- Место куда будет вставляться штрихкод конкретного бланка
  TAG_NAME = 'data:local_id';
  VAL = NULL;
  SUSPEND;

  -- Начинаем формировать бланки
  TAG_NAME = 'data:barcodes';
  VAL = NULL;
  SUSPEND;
  WHILE(I$N_BLANKS > 0) DO
  BEGIN
      -- Генерируем случайный 7-значный номер, от которого идем в сторону увеличения
      -- Ограничиваем количество попыток
      N = 0;
      BASE = RAND() * 9999999;
      WHILE(N >= 0) DO
      BEGIN
          V$LOCAL_ID = BASE;
          WHILE(CHAR_LENGTH(V$LOCAL_ID) < 7) DO V$LOCAL_ID = '0' || V$LOCAL_ID;

          IF(NOT EXISTS(
              SELECT FIRST 1 1
              FROM UT_EXT_BLANKS
              WHERE DATE_DEL IS NULL AND EXAM_ID = :I$EXAM_ID AND REF_ID = :V$OBJ_ID AND LOCAL_ID = :V$LOCAL_ID
          ))
          THEN N = -1;

          IF(N >= 0) THEN N = N + 1;
          IF(N > 100000) THEN EXCEPTION DATA_ERROR 'Превышено количество попыток при генерации номеров бланков';
      END

      INSERT INTO UT_EXT_BLANKS
      (EXAM_ID, REF_ID, USER_ID, LOCAL_ID, BLANK_STATE)
      VALUES (:I$EXAM_ID, :V$OBJ_ID, :V$USER_ID, :V$LOCAL_ID, 1);

      TAG_NAME = 'data:barcodes:item';
      VAL = V$LOCAL_ID;
      SUSPEND;

      I$N_BLANKS = I$N_BLANKS - 1;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_EXT_LIST (
    I$EXAM_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
declare variable V$DB_LEVEL smallint;
declare variable V$STATE integer;
declare variable V$ORG_REF bigint;
declare variable V$LEVEL integer;
declare variable V$OUR_ORG bigint;
declare variable V$METHOD smallint;
declare variable V$PLAN_METHOD smallint;
declare variable V$NAME varchar(128);
declare variable V$OBJ_ID bigint;
begin

  -- Идентифицируем себя
  SELECT COALESCE(CAST(K.KEY_VAL AS INTEGER) - 1, 0)
  FROM KEYS K
  WHERE K.KEY_CODE = 'LEVEL'
  INTO :V$DB_LEVEL;

  IF(V$DB_LEVEL <> 0) THEN EXCEPTION DATA_ERROR 'Печать бланков может выполняться только на уровне ОУ';

  SELECT D.EXAM_STATE, D.ORG_REF, D.H_LEVEL, D.METHOD_ID, D.PLAN_METHOD_ID
  FROM UT_EXAM_DATES D
  WHERE D.OBJ_ID = :I$EXAM_ID AND D.DATE_DEL IS NULL
  INTO :V$STATE, :V$ORG_REF, :V$LEVEL, :V$METHOD, :V$PLAN_METHOD;

  IF(V$STATE IS NULL) THEN EXCEPTION DATA_ERROR 'Тестирование не найдено или было удалено';
  IF(V$STATE < 600 OR V$STATE >= 1000) THEN EXCEPTION DATA_ERROR 'Печать КИМ в данном статусе невозможна';
  --IF(V$METHOD = 0) THEN EXCEPTION DATA_ERROR 'Для электронного тестирования печать не предусмотрена';

  -- А есть ли вообще дополнительные бланки в данном тестировании ?
  -- !!!

  -- Локальный ID для формирования штрихкода
  TAG_NAME = 'ppe_prefix';
  VAL = NULL;
  SELECT COALESCE(GEN, 0)
  FROM GEN
  INTO :VAL;
  WHILE(CHAR_LENGTH(VAL) < 4) DO VAL = '0' || VAL;
  SUSPEND;

  SELECT FIRST 1 L2.OBJ_ID
  FROM LINKS L2
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$OUR_ORG;

  -- Возвращаем список бланков

  TAG_NAME = 'items';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'items::json&colon;array';
  VAL = NULL;
  SUSPEND;
  FOR
      SELECT B.OBJ_ID, B.LOCAL_ID, B.BLANK_STATE
      FROM UT_EXT_BLANKS B
      WHERE B.DATE_DEL IS NULL AND B.EXAM_ID = :I$EXAM_ID AND B.REF_ID = :V$OUR_ORG
      ORDER BY 2
      INTO :V$OBJ_ID, :V$NAME, :V$STATE
  DO
  BEGIN
      TAG_NAME = 'items:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'items:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'items:r:local_id';
      VAL = V$NAME;
      SUSPEND;
      TAG_NAME = 'items:r:state';
      VAL = V$STATE;
      SUSPEND;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_GENERIC_BLANKS (
    I$EXAM_ID BIGINT,
    I$LOC_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
declare variable V$STATE integer;
declare variable V$LOCAL_ID varchar(40);
declare variable V$DATE date;
declare variable V$NAME varchar(200);
declare variable V$STAGE_ID integer;
declare variable V$SUBJECT_ID bigint;
declare variable V$PLAN_METHOD_ID integer;
declare variable V$N_MEMBERS integer;
declare variable V$OBJ_ID bigint;
declare variable V$OU_NAME varchar(400);
declare variable V$PERSON_NAME varchar(1000);
declare variable V$MULT bigint;
declare variable V$GEN varchar(10);
begin

  -- Первыми строками возвращаются шаблоны всех бланков в BLOB_ID, в TAG_NAME передается текст BLOB, в VAL описание бланка
  -- После чего выдаются уже сериализованные данные по участнику

  SELECT D.EXAM_STATE, D.EXAM_DATE_START, D.OBJ_NAME, D.SUBJECT_ID, D.STAGE_ID, D.PLAN_METHOD_ID
  FROM UT_EXAM_DATES D
  WHERE D.OBJ_ID = :I$EXAM_ID AND D.DATE_DEL IS NULL
  INTO :V$STATE, :V$DATE, :V$NAME, :V$SUBJECT_ID, :V$STAGE_ID, :V$PLAN_METHOD_ID;

  IF(V$STATE IS NULL) THEN EXCEPTION DATA_ERROR 'Тестирование не найдено или было удалено';
  IF(V$STATE < 600 OR V$STATE >= 1000) THEN EXCEPTION DATA_ERROR 'Недопустимый статус тестирования';

  SELECT MULTIPLIER
  FROM GEN
  INTO :V$MULT;

  TAG_NAME = 'data:exam_id';
  VAL = I$EXAM_ID;
  SUSPEND;

  TAG_NAME = 'data:exam_name';
  VAL = V$NAME;
  SUSPEND;

  TAG_NAME = 'data:subject_name';
  IF(V$SUBJECT_ID IS NULL) THEN VAL = 'Метапредмет'; ELSE VAL = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$SUBJECT_ID));
  SUSPEND;

  TAG_NAME = 'data:stage_name';
  VAL = (SELECT OBJ_NAME FROM UT_EXAM_STAGES WHERE OBJ_ID = :V$STAGE_ID);
  SUSPEND;

  TAG_NAME = 'data:exam_date_start';
  VAL = (SELECT VAL FROM DATE2ISO(:V$DATE, 0));
  SUSPEND;

  TAG_NAME = 'data:exam_date_str';
  VAL = (SELECT RESULT FROM DATE2STR(:V$DATE));
  SUSPEND;

  V$N_MEMBERS = 0;

  TAG_NAME = 'data:items';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'data:items::json&colon;array';
  VAL = NULL;
  SUSPEND;

  IF(V$PLAN_METHOD_ID IN (0, 1)) THEN
  BEGIN
      -- По помещениям, LOC_ID содержит код помещения

      TAG_NAME = 'data:ppe_name';
      VAL = '-';
      SUSPEND;
  END
  ELSE IF(V$PLAN_METHOD_ID = 2) THEN
  BEGIN
      -- По классам, LOC_ID содержит код класса
      FOR
          SELECT PA.PERSON_ID, PA.LOCAL_ID, C.NAME_FULL, C.CLASS_NAME, C.OU_NAME
          FROM UT_EXAM_PERSON_ASSN PA
          JOIN LINKS LPG ON LPG.OBJ_ID = PA.PERSON_ID AND LPG.DATE_DEL IS NULL AND LPG.PARENT_ID = :I$LOC_ID
          LEFT JOIN UT_PERSON_DESC(PA.PERSON_ID) C ON 1 = 1
          WHERE PA.EXAM_ID = :I$EXAM_ID AND PA.DATE_DEL IS NULL
          ORDER BY 4, 3
          INTO :V$OBJ_ID, :V$LOCAL_ID, :V$PERSON_NAME, :V$NAME, :V$OU_NAME
      DO
      BEGIN
          V$N_MEMBERS = V$N_MEMBERS + 1;

          TAG_NAME = 'data:items:r';
          VAL = NULL;
          SUSPEND;

          TAG_NAME = 'data:items:r:position';
          VAL = V$N_MEMBERS;
          SUSPEND;

          TAG_NAME = 'data:items:r:id';
          VAL = V$OBJ_ID;
          SUSPEND;

          V$OBJ_ID = V$OBJ_ID / V$MULT;
          V$GEN = V$OBJ_ID;
          WHILE(CHAR_LENGTH(V$GEN) < 4) DO V$GEN = '0' || V$GEN;

          TAG_NAME = 'data:items:r:name_full';
          VAL = V$PERSON_NAME;
          SUSPEND;

          TAG_NAME = 'data:items:r:ou_name';
          VAL = V$OU_NAME;
          SUSPEND;

          TAG_NAME = 'data:items:r:grade_name';
          VAL = V$NAME;
          SUSPEND;

          TAG_NAME = 'data:items:r:local_id';
          VAL = V$LOCAL_ID;
          SUSPEND;

          -- Типовой штрихкод бланка AB в формате EAN13 2yteePPPPPPPz
          TAG_NAME = 'data:items:r:barcode13';
          VAL = '2' || SUBSTRING(EXTRACT(YEAR FROM V$DATE) FROM 4) || '1' || RIGHT(I$EXAM_ID, 2) || V$LOCAL_ID;
          VAL = VAL || (SELECT VAL FROM UT_CHECKSUM_EAN13(:VAL));
          SUSPEND;

          -- Типовой штрихкод бланка AB в формате CODE39 yyteeeessssPPPPPPPz
          TAG_NAME = 'data:items:r:barcode39';
          VAL = SUBSTRING(EXTRACT(YEAR FROM V$DATE) FROM 3) || '1' || RIGHT(I$EXAM_ID, 4) || RIGHT(V$GEN, 4) || V$LOCAL_ID;
          -- Контрольный символ в штрихкод не добавляем
          -- VAL = VAL || (SELECT VAL FROM UT_CHECKSUM_EAN39(:VAL));
          SUSPEND;

      END

      -- Наименование сущности, для которой печатается ведомость
      TAG_NAME = 'data:location_name';
      VAL = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$LOC_ID));
      SUSPEND;

      -- Код сущности, для которой печатается ведомость = названию класса
      TAG_NAME = 'data:location_id';
      VAL = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$LOC_ID));
      SUSPEND;

      -- В качестве название ППЭ отдаем название ОУ
      TAG_NAME = 'data:ppe_name';
      VAL = '-';
      SUSPEND;

      -- В качестве кода ППЭ отдаем шифр лицензии - предполагаем, что ранее в него что-то попало
      TAG_NAME = 'data:ppe_code';
      VAL = V$GEN;
      SUSPEND;
  END

  -- Количество участников
  TAG_NAME = 'data:n_members';
  VAL = V$N_MEMBERS;
  SUSPEND;

  -- Буфер для номера текущего листа - подсчитывается и заполняется на стороне апп-сервера
  TAG_NAME = 'data:current_page';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'data:total_pages';
  VAL = NULL;
  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_GET (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(4000))
AS
declare variable V$OBJ_ID bigint;
declare variable V$STRUCT_ID bigint;
declare variable V$OBJ_NAME varchar(1000);
declare variable V$STRUCT_NAME varchar(1000);
declare variable V$SUBJECT_ID bigint;
declare variable V$STAGE_ID integer;
declare variable V$METHOD_ID integer;
declare variable V$NUM integer;
declare variable V$GLOBAL_USED smallint;
declare variable V$CODING_ID bigint;
declare variable V$IS_AUTO smallint;
declare variable V$CT varchar(100);
declare variable V$GEN bigint;
declare variable V$MULTIPLIER bigint;
declare variable N integer;
begin

  SELECT T.OBJ_ID, T.STRUCT_ID, T.OBJ_NAME, S.OBJ_NAME, S.SUBJECT_ID, S.STAGE_ID, S.METHOD_ID, T.CODING_ID, S.IS_AUTO
  FROM UT_TESTS T
  JOIN UT_TEST_STRUCTS S on S.OBJ_ID = T.STRUCT_ID
  WHERE T.DATE_DEL IS NULL AND T.OBJ_ID = :I$OBJ_ID
  INTO :V$OBJ_ID, :V$STRUCT_ID, :V$OBJ_NAME, :V$STRUCT_NAME, :V$SUBJECT_ID, :V$STAGE_ID, :V$METHOD_ID, :V$CODING_ID, :V$IS_AUTO;

  IF(I$OBJ_ID IS NOT NULL AND V$OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Объект не найден или был удален другим пользователем';

  TAG_NAME = 'id';
  VAL = I$OBJ_ID;
  SUSPEND;

  TAG_NAME = 'struct_id';
  VAL = V$STRUCT_ID;
  SUSPEND;

  TAG_NAME = 'struct_name';
  VAL = V$STRUCT_NAME;
  SUSPEND;

  TAG_NAME = 'is_auto';
  VAL = V$IS_AUTO;
  SUSPEND;

  TAG_NAME = 'obj_name';
  VAL = V$OBJ_NAME;
  SUSPEND;

  TAG_NAME = 'coding_id';
  VAL = V$CODING_ID;
  SUSPEND;

  TAG_NAME = 'subject_id:selection';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'subject_id:selection::json&colon;array';
  VAL = '1';
  SUSPEND;
  TAG_NAME = 'subject_id:selection:option';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'subject_id:selection:option:id';
  VAL = '*';
  SUSPEND;
  TAG_NAME = 'subject_id:selection:option:value';
  VAL = 'Метапредмет';
  SUSPEND;
  FOR
    SELECT OBJ_ID, OBJ_NAME
    FROM UT_SUBJECTS
    ORDER BY 2
    INTO :V$OBJ_ID, :V$OBJ_NAME
  DO
  BEGIN
    TAG_NAME = 'subject_id:selection:option';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'subject_id:selection:option:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'subject_id:selection:option:value';
    VAL = V$OBJ_NAME;
    SUSPEND;
  END
  TAG_NAME = 'subject_id:values:value';
  VAL = V$SUBJECT_ID;
  SUSPEND;

  TAG_NAME = 'stage_id:selection';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'stage_id:selection::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
    SELECT OBJ_ID, OBJ_NAME
    FROM UT_EXAM_STAGES
    INTO :V$OBJ_ID, :V$OBJ_NAME
  DO
  BEGIN
    TAG_NAME = 'stage_id:selection:option';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'stage_id:selection:option:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'stage_id:selection:option:value';
    VAL = V$OBJ_NAME;
    SUSPEND;
  END
  TAG_NAME = 'stage_id:values:value';
  VAL = V$STAGE_ID;
  SUSPEND;

  TAG_NAME = 'method_id:selection';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'method_id:selection::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
    SELECT OBJ_ID, OBJ_NAME
    FROM UT_EXAM_METHODS
    WHERE OBJ_ID <> 4 -- кроме олимпиад
    INTO :V$OBJ_ID, :V$OBJ_NAME
  DO
  BEGIN
    TAG_NAME = 'method_id:selection:option';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'method_id:selection:option:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'method_id:selection:option:value';
    VAL = V$OBJ_NAME;
    SUSPEND;
  END
  TAG_NAME = 'method_id:values:value';
  VAL = V$METHOD_ID;
  SUSPEND;

  V$GLOBAL_USED = 0;
  TAG_NAME = 'variants';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'variants::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
    SELECT TV.OBJ_ID, TV.OBJ_NAME, TV.NUM
    FROM UT_TEST_VARS TV
    WHERE TV.DATE_DEL IS NULL AND TV.TEST_ID = :I$OBJ_ID
    ORDER BY 2
    INTO :V$OBJ_ID, :V$OBJ_NAME, :V$NUM
  DO
  BEGIN
    TAG_NAME = 'variants:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'variants:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'variants:r:name';
    VAL = V$OBJ_NAME;
    SUSPEND;
    TAG_NAME = 'variants:r:num';
    VAL = V$NUM;
    SUSPEND;

    -- Есть ли активные назначения данного варианта на тестирования ?
    TAG_NAME = 'variants:r:is_used';
    VAL = 0;
    SELECT FIRST 1 1
    FROM UT_EXAM_TEST_VARS ETV
    JOIN UT_EXAM_DATES D ON D.OBJ_ID = ETV.EXAM_ID AND D.DATE_DEL IS NULL AND (D.EXAM_STATE > 500 AND D.EXAM_STATE < 1000)
    WHERE ETV.DATE_DEL IS NULL AND ETV.TEST_VAR_ID = :V$OBJ_ID
    INTO :VAL;
    IF(VAL <> '0') THEN V$GLOBAL_USED = 1;
    SUSPEND;

    -- Файлы вложений (КИМы и проч)
    TAG_NAME = 'variants:r:files';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'variants:r:files::json&colon;array';
    VAL = 1;
    SUSPEND;

    FOR
      SELECT F.OBJ_ID, F.OBJ_NAME, F.FILE_HASH, F.CONTENT_TYPE, F.ATTR_MASK, CHAR_LENGTH(F.CONTENT_DATA)
      FROM UT_TEST_VAR_FILES F
      WHERE F.DATE_DEL IS NULL AND F.VAR_ID = :V$OBJ_ID
      ORDER BY 2
      INTO :V$SUBJECT_ID, :V$OBJ_NAME, :V$STRUCT_NAME, :V$CT, :V$STAGE_ID, :N
    DO
    BEGIN
      TAG_NAME = 'variants:r:files:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'variants:r:files:r:id';
      VAL = V$SUBJECT_ID;
      SUSPEND;
      TAG_NAME = 'variants:r:files:r:name';
      VAL = V$OBJ_NAME;
      SUSPEND;
      TAG_NAME = 'variants:r:files:r:hash';
      VAL = V$STRUCT_NAME;
      SUSPEND;
      TAG_NAME = 'variants:r:files:r:type';
      VAL = V$CT;
      SUSPEND;
      TAG_NAME = 'variants:r:files:r:mask';
      VAL = V$STAGE_ID;
      SUSPEND;
      TAG_NAME = 'variants:r:files:r:size';
      VAL = N;
      SUSPEND;
    END
  END

  TAG_NAME = 'is_used';
  VAL = V$GLOBAL_USED;
  SUSPEND;

  SELECT GEN, MULTIPLIER
  FROM GEN
  INTO :V$GEN, :V$MULTIPLIER;

  N = I$OBJ_ID / V$MULTIPLIER;
  TAG_NAME = 'allowed';
  VAL = 0;
  IF(I$OBJ_ID IS NULL OR N = V$GEN) THEN VAL = 1;
  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_GIA_SIGNATURE (
    I$YEAR_ID BIGINT)
RETURNS (
    FILE_ID VARCHAR(100),
    YEAR_VAL VARCHAR(40))
AS
begin

  SELECT FIRST 1 V2930.VAL, R.VAL
  FROM LINKS L
  JOIN VALL V742 ON V742.OBJ_ID = L.OBJ_ID AND V742.PARAM_ID = 742 AND V742.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V742.LISTVAL_ID
  JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
  LEFT JOIN VALS V1192 ON V1192.OBJ_ID = L.OBJ_ID AND V1192.PARAM_ID = 1192 AND V1192.IS_DEL = 0
  LEFT JOIN VALS V2930 ON V2930.OBJ_ID = L.OBJ_ID AND V2930.PARAM_ID = 2930 AND V2930.IS_DEL = 0
  WHERE L.PARENT_ID = 3866 AND L.OBJ_TYPE_ID = 119 AND L.DATE_DEL IS NULL AND (:I$YEAR_ID IS NULL OR V742.LISTVAL_ID = :I$YEAR_ID)
  ORDER BY LV.COST DESC
  INTO :FILE_ID, :YEAR_VAL;

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_IMPORT_B0 (
    I$USER_ID VARCHAR(40),
    I$SOURCE_LEVEL SMALLINT,
    I$OBJ_ID BIGINT)
RETURNS (
    STUB INTEGER)
AS
declare variable V$DB_LEVEL integer;
declare variable V$STATE integer;
declare variable V$METHOD integer;
begin

  SELECT COALESCE(CAST(K.KEY_VAL AS INTEGER) - 1, 0)
  FROM KEYS K
  WHERE K.KEY_CODE = 'LEVEL'
  INTO :V$DB_LEVEL;

  SELECT FIRST 1 D.EXAM_STATE, D.METHOD_ID
  FROM UT_EXAM_DATES D
  WHERE D.OBJ_ID = :I$OBJ_ID AND D.DATE_DEL IS NULL
  INTO :V$STATE, :V$METHOD;

  IF(V$STATE IS NULL) THEN EXCEPTION DATA_ERROR 'Тестирование не найдено. Импортируйте файл тестирования или выполните синхронизацию с сервером';
  IF(V$STATE = 0 OR V$STATE >= 1000) THEN EXCEPTION DATA_ERROR 'Нельзя выполнять импорт файлов бланков в статусе черновика, или когда тестирование уже завершено';

  SUSPEND;
end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_IMPORT_B1 (
    I$SOURCE_LEVEL SMALLINT,
    I$OBJ_ID BIGINT,
    I$DATE_ADD TIMESTAMP,
    I$DATE_MODIFY TIMESTAMP,
    I$DATE_DEL TIMESTAMP,
    I$ED_ID BIGINT,
    I$PPE_ID BIGINT,
    I$ROOM_ID BIGINT,
    I$USER_ID BIGINT,
    I$N_PAGES INTEGER,
    I$STATE_ID BIGINT,
    I$IP_INFO VARCHAR(200))
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$H_LEVEL integer;
declare variable V$DB_LEVEL integer;
declare variable V$OBJ_ID bigint;
declare variable V$GEN bigint;
declare variable V$MULTIPLIER bigint;
begin

  SELECT COALESCE(CAST(K.KEY_VAL AS INTEGER) - 1, 0)
  FROM KEYS K
  WHERE K.KEY_CODE = 'LEVEL'
  INTO :V$DB_LEVEL;

  SELECT D.H_LEVEL
  FROM UT_EXAM_DATES D
  WHERE D.OBJ_ID = :I$ED_ID
  INTO :V$H_LEVEL;

  SELECT GEN, MULTIPLIER
  FROM GEN
  INTO :V$GEN, :V$MULTIPLIER;

  -- Загружаем либо бланки снизу вверх, либо только свои
  V$OBJ_ID = I$OBJ_ID / V$MULTIPLIER;
  IF(V$DB_LEVEL <= I$SOURCE_LEVEL) THEN
  BEGIN
      IF(V$OBJ_ID <> V$GEN) THEN EXIT;
  END

  -- Статус тестирования корректируем в зависимости от соотношения уровней
  V$OBJ_ID = NULL;
  SELECT P.OBJ_ID
  FROM UT_PACKAGES P
  WHERE P.OBJ_ID = :I$OBJ_ID
  INTO :V$OBJ_ID;

  IF(V$OBJ_ID IS NULL) THEN
  BEGIN

      INSERT INTO UT_PACKAGES
      (OBJ_ID, DATE_ADD, DATE_MODIFY, DATE_DEL, ED_ID, PPE_ID, ROOM_ID, USER_ID, N_PAGES, STATE_ID, IP_INFO)
      VALUES (:I$OBJ_ID, :I$DATE_ADD, :I$DATE_MODIFY, :I$DATE_DEL, :I$ED_ID, :I$PPE_ID, :I$ROOM_ID, :I$USER_ID, :I$N_PAGES, :I$STATE_ID, :I$IP_INFO)
      RETURNING OBJ_ID INTO :OBJ_ID;

  END
  ELSE
  BEGIN

      -- Данные полностью обновляются только при импорте того же уровня
      IF(V$DB_LEVEL = I$SOURCE_LEVEL) THEN
      BEGIN
          UPDATE UT_PACKAGES
          SET DATE_MODIFY = :I$DATE_MODIFY, DATE_DEL = :I$DATE_DEL, N_PAGES = :I$N_PAGES, STATE_ID = :I$STATE_ID
          WHERE OBJ_ID = :I$OBJ_ID;

          OBJ_ID = I$OBJ_ID;
      END

  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_IMPORT_B2 (
    I$SOURCE_LEVEL SMALLINT,
    I$OBJ_ID BIGINT,
    I$DATE_ADD TIMESTAMP,
    I$DATE_MODIFY TIMESTAMP,
    I$DATE_DEL TIMESTAMP,
    I$PACKAGE_ID BIGINT,
    I$BLANK_TYPE BIGINT,
    I$BLANK_SIDE SMALLINT,
    I$PARENT_ID BIGINT,
    I$FILE_ID VARCHAR(40),
    I$FILE_HASH VARCHAR(40),
    I$BARCODE1 VARCHAR(128),
    I$BARCODE2 VARCHAR(128),
    I$BARCODE3 VARCHAR(128),
    I$STATE_ID INTEGER,
    I$RCV_STATION_ID VARCHAR(40),
    I$VER_USER_ID BIGINT)
RETURNS (
    STUB INTEGER)
AS
declare variable V$DB_LEVEL integer;
declare variable V$OBJ_ID bigint;
begin

  SELECT COALESCE(CAST(K.KEY_VAL AS INTEGER) - 1, 0)
  FROM KEYS K
  WHERE K.KEY_CODE = 'LEVEL'
  INTO :V$DB_LEVEL;

  SELECT B.OBJ_ID
  FROM UT_BLANKS B
  WHERE B.OBJ_ID = :I$OBJ_ID
  INTO :V$OBJ_ID;

  -- Если файл удален, и его нет в базе - и черт с ним
  IF(V$OBJ_ID IS NULL AND I$DATE_DEL IS NOT NULL) THEN EXIT;

  -- PARENT_ID и SESSION_ID вообще игнорируем

  IF(V$OBJ_ID IS NULL) THEN
  BEGIN

      INSERT INTO UT_BLANKS
      (OBJ_ID, DATE_ADD, DATE_MODIFY, DATE_DEL, PACKAGE_ID, BLANK_TYPE, BLANK_SIDE, FILE_ID, FILE_HASH,
          BARCODE_DATA, BARCODE2_DATA, BARCODE3_DATA, STATE_ID, RCV_STATION_ID, VER_USER_ID)
      VALUES (:I$OBJ_ID, :I$DATE_ADD, :I$DATE_MODIFY, :I$DATE_DEL, :I$PACKAGE_ID, :I$BLANK_TYPE, :I$BLANK_SIDE, :I$FILE_ID, :I$FILE_HASH,
          :I$BARCODE1, :I$BARCODE2, :I$BARCODE3, :I$STATE_ID, :I$RCV_STATION_ID, :I$VER_USER_ID);

  END
  ELSE
  BEGIN

      -- Данные полностью обновляются только при импорте того же уровня
      IF(V$DB_LEVEL = I$SOURCE_LEVEL) THEN
      BEGIN
          UPDATE UT_BLANKS
          SET DATE_MODIFY = :I$DATE_MODIFY, DATE_DEL = :I$DATE_DEL, STATE_ID = :I$STATE_ID, VER_USER_ID = :I$VER_USER_ID
          WHERE OBJ_ID = :I$OBJ_ID;
      END

  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_IMPORT_B3 (
    I$OBJ_ID BIGINT,
    I$NEXT_ID BIGINT)
RETURNS (
    STUB INTEGER)
AS
begin

  UPDATE UT_BLANKS
  SET NEXT_BLANK_ID = :I$NEXT_ID
  WHERE OBJ_ID = :I$OBJ_ID;

  IF(0 = 1) THEN SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_IMPORT_MD0 (
    I$SOURCE_LEVEL INTEGER,
    I$REF_ID BIGINT,
    I$REF_TYPE VARCHAR(40))
RETURNS (
    BLOB_DATA BLOB SUB_TYPE 1 SEGMENT SIZE 80)
AS
declare variable V$DB_LEVEL integer;
begin

  -- Бинарные данные передаются только сверху вниз по иерархии
  SELECT COALESCE(CAST(K.KEY_VAL AS INTEGER) - 1, 0)
  FROM KEYS K
  WHERE K.KEY_CODE = 'LEVEL'
  INTO :V$DB_LEVEL;

  IF(V$DB_LEVEL > I$SOURCE_LEVEL) THEN EXIT;

  IF(I$REF_TYPE = 'structure') THEN
  BEGIN
      SELECT S.TEXT_NOTES
      FROM UT_TEST_STRUCTS S
      WHERE S.OBJ_ID = :I$REF_ID AND S.DATE_DEL IS NULL
      INTO :BLOB_DATA;
  END
  ELSE IF(I$REF_TYPE = 'qtext') THEN
  BEGIN
      SELECT S.QUESTION
      FROM UT_QUESTIONS S
      WHERE S.OBJ_ID = :I$REF_ID AND S.DATE_DEL IS NULL
      INTO :BLOB_DATA;
  END
  ELSE IF(I$REF_TYPE = 'qhint') THEN
  BEGIN
      SELECT S.HINT
      FROM UT_QUESTIONS S
      WHERE S.OBJ_ID = :I$REF_ID AND S.DATE_DEL IS NULL
      INTO :BLOB_DATA;
  END
  ELSE IF(I$REF_TYPE = 'qa') THEN
  BEGIN
      SELECT S.VARIANT
      FROM UT_ANSWERS S
      WHERE S.OBJ_ID = :I$REF_ID AND S.DATE_DEL IS NULL
      INTO :BLOB_DATA;
  END
  ELSE IF(I$REF_TYPE = 'template:front') THEN
  BEGIN
      SELECT S.DATA_FRONT
      FROM UT_PAGE_TEMPLATES S
      WHERE S.OBJ_ID = :I$REF_ID AND S.DATE_DEL IS NULL
      INTO :BLOB_DATA;
  END
  ELSE IF(I$REF_TYPE = 'template:back') THEN
  BEGIN
      SELECT S.DATA_BACK
      FROM UT_PAGE_TEMPLATES S
      WHERE S.OBJ_ID = :I$REF_ID AND S.DATE_DEL IS NULL
      INTO :BLOB_DATA;
  END
  ELSE EXCEPTION DATA_ERROR 'Неизвестный тип метаданных';

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_IMPORT_MD1 (
    I$SOURCE_LEVEL INTEGER,
    I$REF_ID BIGINT,
    I$REF_TYPE VARCHAR(40),
    I$BLOB_DATA BLOB SUB_TYPE 1 SEGMENT SIZE 80)
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$DB_LEVEL integer;
begin

  SELECT COALESCE(CAST(K.KEY_VAL AS INTEGER) - 1, 0)
  FROM KEYS K
  WHERE K.KEY_CODE = 'LEVEL'
  INTO :V$DB_LEVEL;

  IF(V$DB_LEVEL > I$SOURCE_LEVEL) THEN EXIT;

  IF(I$REF_TYPE = 'structure') THEN
  BEGIN
      UPDATE UT_TEST_STRUCTS
      SET TEXT_NOTES = :I$BLOB_DATA
      WHERE OBJ_ID = :I$REF_ID AND DATE_DEL IS NULL;
  END
  ELSE IF(I$REF_TYPE = 'qtext') THEN
  BEGIN
      UPDATE UT_QUESTIONS
      SET QUESTION = :I$BLOB_DATA
      WHERE OBJ_ID = :I$REF_ID AND DATE_DEL IS NULL;
  END
  ELSE IF(I$REF_TYPE = 'qhint') THEN
  BEGIN
      UPDATE UT_QUESTIONS
      SET HINT = :I$BLOB_DATA
      WHERE OBJ_ID = :I$REF_ID AND DATE_DEL IS NULL;
  END
  ELSE IF(I$REF_TYPE = 'qa') THEN
  BEGIN
      UPDATE UT_ANSWERS
      SET VARIANT = :I$BLOB_DATA
      WHERE OBJ_ID = :I$REF_ID;
  END
  ELSE IF(I$REF_TYPE = 'template:front') THEN
  BEGIN
      UPDATE UT_PAGE_TEMPLATES
      SET DATA_FRONT = :I$BLOB_DATA
      WHERE OBJ_ID = :I$REF_ID AND DATE_DEL IS NULL;
  END
  ELSE IF(I$REF_TYPE = 'template:back') THEN
  BEGIN
      UPDATE UT_PAGE_TEMPLATES
      SET DATA_BACK = :I$BLOB_DATA
      WHERE OBJ_ID = :I$REF_ID AND DATE_DEL IS NULL;
  END
  ELSE EXCEPTION DATA_ERROR 'Неизвестный тип метаданных';

  OBJ_ID = I$REF_ID;
  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_IMPORT_P0 (
    I$USER_ID VARCHAR(40),
    I$SOURCE_LEVEL SMALLINT,
    I$OBJ_ID BIGINT,
    I$DATE_ADD TIMESTAMP,
    I$DATE_MODIFY TIMESTAMP,
    I$DATE_DEL TIMESTAMP,
    I$BLANK_TYPE SMALLINT,
    I$OBJ_NAME VARCHAR(400),
    I$IS_DS SMALLINT,
    I$IS_ACTIVE SMALLINT)
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$TYPE integer;
declare variable V$DB_LEVEL integer;
begin

  -- При импорте нижестоящих тестирований обратно в вышестоящую базу - данные обновляем только если это свой собственный файл !
  SELECT COALESCE(CAST(K.KEY_VAL AS INTEGER) - 1, 0)
  FROM KEYS K
  WHERE K.KEY_CODE = 'LEVEL'
  INTO :V$DB_LEVEL;

  IF(V$DB_LEVEL > I$SOURCE_LEVEL) THEN EXIT;

  --
  SELECT FIRST 1 OBJ_ID, BLANK_TYPE
  FROM UT_PAGE_TEMPLATES
  WHERE OBJ_ID = :I$OBJ_ID
  INTO :OBJ_ID, :V$TYPE;

  IF(OBJ_ID IS NULL) THEN
  BEGIN

      -- Удаленные не загружаем
      IF(I$DATE_DEL IS NOT NULL) THEN EXIT;

      INSERT INTO UT_PAGE_TEMPLATES
      (OBJ_ID, DATE_ADD, DATE_MODIFY, OBJ_NAME, BLANK_TYPE, IS_DS, IS_ACTIVE)
      VALUES (:I$OBJ_ID, :I$DATE_ADD, :I$DATE_MODIFY, :I$OBJ_NAME, :I$BLANK_TYPE, :I$IS_DS, :I$IS_ACTIVE);

  END
  ELSE
  BEGIN
      IF(V$TYPE <> I$BLANK_TYPE) THEN EXCEPTION DATA_ERROR 'Тип бланка не может быть изменен';

      -- Нельзя понизить статус (удалить) используемого бланка
      -- !!!

      UPDATE UT_PAGE_TEMPLATES
      SET DATE_DEL = :I$DATE_DEL, OBJ_NAME = :I$OBJ_NAME, IS_DS = :I$IS_DS, IS_ACTIVE = :I$IS_ACTIVE
      WHERE OBJ_ID = :I$OBJ_ID;
  END

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_IMPORT_P1 (
    I$USER_ID VARCHAR(40),
    I$SOURCE_LEVEL SMALLINT,
    I$EXAM_ID BIGINT,
    I$DATE_ADD TIMESTAMP,
    I$DATE_MODIFY TIMESTAMP,
    I$DATE_DEL TIMESTAMP,
    I$OBJ_NAME VARCHAR(400),
    I$EXAM_STATE INTEGER,
    I$SUBJECT_ID BIGINT,
    I$STAGE_ID INTEGER,
    I$EXAM_DATE_START DATE,
    I$EXAM_DATE_END DATE,
    I$DURATION INTEGER,
    I$EXAM_DAY_TYPE INTEGER,
    I$C_CALC_MODE INTEGER,
    I$C_EXPERT_NUM INTEGER,
    I$C_DIFF_QUESTION INTEGER,
    I$C_DIFF_TOTAL INTEGER,
    I$METHOD_ID INTEGER,
    I$PLAN_METHOD_ID INTEGER,
    I$ATTEMPTS INTEGER,
    I$OWNER_ID BIGINT,
    I$H_LEVEL INTEGER,
    I$ORG_REF BIGINT,
    I$FLOW_MODE SMALLINT,
    I$PAUSE_ENABLED SMALLINT,
    I$EXPERT_ASSN_MODE SMALLINT,
    I$BLANK_AB_ID BIGINT,
    I$BLANK_C_ID BIGINT,
    I$BLANK_EXT_ID BIGINT,
    I$BLANK_GEN_ID BIGINT,
    I$SCALE_N0 SMALLINT,
    I$SCALE_NMIN SMALLINT,
    I$SCALE_N4 SMALLINT,
    I$SCALE_N5 SMALLINT,
    I$SCALE_NMAX SMALLINT)
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$USER_ID bigint;
declare variable V$DB_LEVEL smallint;
declare variable V$GEN bigint;
declare variable V$MULT bigint;
declare variable V$TMP bigint;
declare variable V$DATE_DEL timestamp;
declare variable V$N integer;
declare variable V$STATE integer;
begin

  IF(I$USER_ID = 'Веб-администратор') THEN V$USER_ID = 0; ELSE V$USER_ID = CAST(I$USER_ID AS BIGINT);

  -- При импорте нижестоящих тестирований обратно в вышестоящую базу - данные обновляем только если это свой собственный файл !
  SELECT COALESCE(CAST(K.KEY_VAL AS INTEGER) - 1, 0)
  FROM KEYS K
  WHERE K.KEY_CODE = 'LEVEL'
  INTO :V$DB_LEVEL;

  IF(V$DB_LEVEL > I$SOURCE_LEVEL) THEN EXIT;

  SELECT GEN, MULTIPLIER
  FROM GEN
  INTO :V$GEN, :V$MULT;

  -- Нельзя импортировать тестирования в вышестоящую базу, если они не были изначально в ней созданы
  -- !!! загрузка файла из города в район !!!
  IF(V$DB_LEVEL > I$H_LEVEL) THEN
  BEGIN
      V$TMP = I$EXAM_ID / V$MULT;
      IF(V$TMP <> V$GEN) THEN EXCEPTION DATA_ERROR 'Нельзя загружать тестирования нижестоящих уровней, если они не были изначально созданы в данной базе';
  END

  SELECT FIRST 1 D.OBJ_ID, D.DATE_DEL, D.H_LEVEL, D.ORG_REF, D.EXAM_STATE
  FROM UT_EXAM_DATES D
  WHERE D.OBJ_ID = :I$EXAM_ID
  INTO :OBJ_ID, :V$DATE_DEL, :V$N, :V$TMP, :V$STATE;

  IF(OBJ_ID IS NOT NULL AND (V$N <> I$H_LEVEL OR V$TMP <> I$ORG_REF)) THEN EXCEPTION DATA_ERROR 'Нельзя изменить уровень и владельца тестирования';

  -- Восстанавливаем удаление
  IF(OBJ_ID IS NOT NULL AND V$DATE_DEL IS NOT NULL) THEN
  BEGIN
      UPDATE UT_EXAM_DATES
      SET DATE_DEL = NULL
      WHERE OBJ_ID = :I$EXAM_ID;
  END

  IF(OBJ_ID IS NULL) THEN
  BEGIN

      INSERT INTO UT_EXAM_DATES
      (OBJ_ID, DATE_ADD, OBJ_NAME, SUBJECT_ID, STAGE_ID, EXAM_DATE_START, EXAM_DATE_END, DURATION, EXAM_DAY_TYPE, EXAM_STATE,
          C_CALC_MODE, C_EXPERT_NUM, C_DIFF_QUESTION, C_DIFF_TOTAL, METHOD_ID, PLAN_METHOD_ID, ATTEMPTS, OWNER_ID, H_LEVEL, ORG_REF,
          FLOW_MODE, PAUSE_ENABLED, EXPERT_ASSN_MODE, BLANK_AB_ID, BLANK_C_ID, BLANK_EXT_ID, BLANK_GEN_ID,
          SCALE_N0, SCALE_NMIN, SCALE_N4, SCALE_N5, SCALE_NMAX)
      VALUES (:I$EXAM_ID, :I$DATE_ADD, :I$OBJ_NAME, :I$SUBJECT_ID, :I$STAGE_ID, :I$EXAM_DATE_START, :I$EXAM_DATE_END, :I$DURATION, :I$EXAM_DAY_TYPE, :I$EXAM_STATE,
          :I$C_CALC_MODE, :I$C_EXPERT_NUM, :I$C_DIFF_QUESTION, :I$C_DIFF_TOTAL,
          :I$METHOD_ID, :I$PLAN_METHOD_ID, :I$ATTEMPTS,
          :I$OWNER_ID, :I$H_LEVEL, :I$ORG_REF, :I$FLOW_MODE, :I$PAUSE_ENABLED, :I$EXPERT_ASSN_MODE,
          :I$BLANK_AB_ID, :I$BLANK_C_ID, :I$BLANK_EXT_ID, :I$BLANK_GEN_ID, :I$SCALE_N0, :I$SCALE_NMIN, :I$SCALE_N4, :I$SCALE_N5, :I$SCALE_NMAX
          );

      OBJ_ID = I$EXAM_ID;

  END
  ELSE
  BEGIN

      -- Статус может только увеличиваться
      IF(I$EXAM_STATE < V$STATE) THEN I$EXAM_STATE = V$STATE;

      UPDATE UT_EXAM_DATES
      SET OBJ_NAME = :I$OBJ_NAME, EXAM_STATE = :I$EXAM_STATE,
          SUBJECT_ID = :I$SUBJECT_ID, STAGE_ID = :I$STAGE_ID, EXAM_DATE_START = :I$EXAM_DATE_START, EXAM_DATE_END = :I$EXAM_DATE_END,
          DURATION = :I$DURATION, EXAM_DAY_TYPE = :I$EXAM_DAY_TYPE, C_CALC_MODE = COALESCE(:I$C_CALC_MODE, C_CALC_MODE),
          C_EXPERT_NUM = :I$C_EXPERT_NUM, C_DIFF_QUESTION = :I$C_DIFF_QUESTION,
          C_DIFF_TOTAL = :I$C_DIFF_TOTAL, METHOD_ID = :I$METHOD_ID,
          PLAN_METHOD_ID = :I$PLAN_METHOD_ID, ATTEMPTS = :I$ATTEMPTS,
          OWNER_ID = :I$OWNER_ID, H_LEVEL = :I$H_LEVEL, ORG_REF = :I$ORG_REF, FLOW_MODE = :I$FLOW_MODE, PAUSE_ENABLED = :I$PAUSE_ENABLED,
          EXPERT_ASSN_MODE = :I$EXPERT_ASSN_MODE,
          BLANK_AB_ID = :I$BLANK_AB_ID, BLANK_C_ID = :I$BLANK_C_ID, BLANK_EXT_ID = :I$BLANK_EXT_ID, BLANK_GEN_ID = :I$BLANK_GEN_ID,
          SCALE_N0 = :I$SCALE_N0, SCALE_NMIN = :I$SCALE_NMIN, SCALE_N4 = :I$SCALE_N4,
          SCALE_N5 = :I$SCALE_N5, SCALE_NMAX = :I$SCALE_NMAX
      WHERE OBJ_ID = :OBJ_ID;

  END

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_IMPORT_P10 (
    I$SOURCE_LEVEL SMALLINT,
    I$EXAM_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$DATE_ADD TIMESTAMP,
    I$DATE_MODIFY TIMESTAMP,
    I$DATE_DEL TIMESTAMP,
    I$PERSON_ID BIGINT,
    I$LOCAL_ID VARCHAR(40),
    I$BLANKS_PRINTED SMALLINT,
    I$OU_ID BIGINT,
    I$AREA_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$DB_LEVEL integer;
declare variable V$GEN bigint;
declare variable V$MULT bigint;
declare variable V$BASE bigint;
begin

  -- Назначение участников загружается только из нижестоящей базы в вышестоящую
  SELECT COALESCE(CAST(K.KEY_VAL AS INTEGER) - 1, 0)
  FROM KEYS K
  WHERE K.KEY_CODE = 'LEVEL'
  INTO :V$DB_LEVEL;

  IF(V$DB_LEVEL < I$SOURCE_LEVEL) THEN EXIT;

  -- Для уровня ОУ забираем только участников, относящихся к нашей зоне ответственности
  SELECT GEN, MULTIPLIER
  FROM GEN
  INTO :V$GEN, :V$MULT;

  IF(I$PERSON_ID IS NOT NULL AND V$DB_LEVEL = 0) THEN
  BEGIN
      V$BASE = I$PERSON_ID / V$MULT;
      IF(V$GEN <> V$BASE) THEN EXIT;
  END

  -- !!! проверка связи с тестированием !!!!
  SELECT OBJ_ID
  FROM UT_EXAM_PERSON_ASSN
  WHERE OBJ_ID = :I$OBJ_ID
  INTO :OBJ_ID;

  IF(OBJ_ID IS NULL AND I$DATE_DEL IS NULL) THEN
  BEGIN

      OBJ_ID = I$OBJ_ID;

      INSERT INTO UT_EXAM_PERSON_ASSN
      (OBJ_ID, DATE_ADD, DATE_MODIFY, DATE_DEL, EXAM_ID, PERSON_ID, LOCAL_ID, BLANKS_PRINTED, OU_ID, AREA_ID)
      VALUES (:I$OBJ_ID, :I$DATE_ADD, :I$DATE_MODIFY, :I$DATE_DEL, :I$EXAM_ID, :I$PERSON_ID, :I$LOCAL_ID, :I$BLANKS_PRINTED, :I$OU_ID, :I$AREA_ID);

  END
  ELSE IF(OBJ_ID IS NOT NULL) THEN
  BEGIN

      IF(I$DATE_DEL IS NOT NULL) THEN
      BEGIN
          UPDATE UT_EXAM_PERSON_ASSN
          SET DATE_DEL = :I$DATE_DEL
          WHERE OBJ_ID = :I$OBJ_ID AND DATE_DEL IS NULL;
      END
      ELSE
      BEGIN
          UPDATE UT_EXAM_PERSON_ASSN
          SET DATE_DEL = :I$DATE_DEL, PERSON_ID = :I$PERSON_ID, LOCAL_ID = :I$LOCAL_ID, BLANKS_PRINTED = :I$BLANKS_PRINTED, OU_ID = :I$OU_ID, AREA_ID = :I$AREA_ID
          WHERE OBJ_ID = :I$OBJ_ID;
      END

  END

  IF(I$DATE_DEL IS NULL) THEN SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_IMPORT_P11 (
    I$SOURCE_LEVEL SMALLINT,
    I$EXAM_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$DATE_ADD TIMESTAMP,
    I$DATE_MODIFY TIMESTAMP,
    I$DATE_DEL TIMESTAMP,
    I$EXPERT_ID BIGINT,
    I$ROLE_ID VARCHAR(40),
    I$SECOND_CHECK SMALLINT)
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$DB_LEVEL integer;
declare variable V$GEN bigint;
declare variable V$MULT bigint;
declare variable V$BASE bigint;
declare variable V$MODE smallint;
begin

  SELECT COALESCE(CAST(K.KEY_VAL AS INTEGER) - 1, 0)
  FROM KEYS K
  WHERE K.KEY_CODE = 'LEVEL'
  INTO :V$DB_LEVEL;

  -- Внимание: эксперты могут передаваться либо снизу вверх, либо сверху вниз, в зависимости от настроек тестирования
  -- 0 = сверху вниз, 1 = снизу вверх
  SELECT EXPERT_ASSN_MODE
  FROM UT_EXAM_DATES
  WHERE OBJ_ID = :I$EXAM_ID
  INTO :V$MODE;

  IF(V$MODE = 0) THEN
  BEGIN
      -- Режим сверху вниз
      IF(V$DB_LEVEL > I$SOURCE_LEVEL) THEN EXIT;
  END
  ELSE
  BEGIN
      -- Режим снизу вверх
      IF(V$DB_LEVEL < I$SOURCE_LEVEL) THEN EXIT;
  END

  -- Для уровня ОУ забираем только экспертов, относящихся к нашей зоне ответственности
  SELECT GEN, MULTIPLIER
  FROM GEN
  INTO :V$GEN, :V$MULT;

  IF(I$EXPERT_ID IS NOT NULL AND V$DB_LEVEL = 0) THEN
  BEGIN
      V$BASE = I$EXPERT_ID / V$MULT;
      IF(V$GEN <> V$BASE) THEN EXIT;
  END

  -- !!! проверка связи с тестированием !!!!
  SELECT OBJ_ID
  FROM UT_EXAM_EXPERT_ASSN
  WHERE OBJ_ID = :I$OBJ_ID
  INTO :OBJ_ID;

  IF(OBJ_ID IS NULL AND I$DATE_DEL IS NULL) THEN
  BEGIN

      OBJ_ID = I$OBJ_ID;

      INSERT INTO UT_EXAM_EXPERT_ASSN
      (OBJ_ID, DATE_ADD, DATE_MODIFY, DATE_DEL, EXAM_ID, EXPERT_ID, ROLE_ID, SECOND_CHECK)
      VALUES (:I$OBJ_ID, :I$DATE_ADD, :I$DATE_MODIFY, :I$DATE_DEL, :I$EXAM_ID, :I$EXPERT_ID, :I$ROLE_ID, :I$SECOND_CHECK);

  END
  ELSE IF(OBJ_ID IS NOT NULL) THEN
  BEGIN

      IF(I$DATE_DEL IS NOT NULL) THEN
      BEGIN
          UPDATE UT_EXAM_EXPERT_ASSN
          SET DATE_DEL = :I$DATE_DEL
          WHERE OBJ_ID = :I$OBJ_ID AND DATE_DEL IS NULL;
      END
      ELSE
      BEGIN
          UPDATE UT_EXAM_EXPERT_ASSN
          SET DATE_DEL = :I$DATE_DEL, EXPERT_ID = :I$EXPERT_ID, ROLE_ID = :I$ROLE_ID, SECOND_CHECK = :I$SECOND_CHECK
          WHERE OBJ_ID = :I$OBJ_ID;
      END

  END

  IF(I$DATE_DEL IS NULL) THEN SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_IMPORT_P11X (
    I$SOURCE_LEVEL SMALLINT,
    I$EXAM_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$DATE_ADD TIMESTAMP,
    I$DATE_MODIFY TIMESTAMP,
    I$DATE_DEL TIMESTAMP,
    I$TEACHER_ID BIGINT,
    I$ORG_ID BIGINT,
    I$USER_NAME VARCHAR(100),
    I$PWD VARCHAR(100),
    I$IS_ACTIVE SMALLINT,
    I$LAST_NAME VARCHAR(400),
    I$FIRST_NAME VARCHAR(400),
    I$MID_NAME VARCHAR(400))
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$DB_LEVEL integer;
declare variable V$GEN bigint;
declare variable V$MULT bigint;
declare variable V$BASE bigint;
begin

  SELECT COALESCE(CAST(K.KEY_VAL AS INTEGER) - 1, 0)
  FROM KEYS K
  WHERE K.KEY_CODE = 'LEVEL'
  INTO :V$DB_LEVEL;

  -- Экспертов пока передаем снизу вверх
  IF(V$DB_LEVEL < I$SOURCE_LEVEL) THEN EXIT;

  -- Для уровня ОУ забираем только экспертов, относящихся к нашей зоне ответственности
  -- пароль при импорте не переносим, на городской базе задается свой пароль для входа в систему
  SELECT GEN, MULTIPLIER
  FROM GEN
  INTO :V$GEN, :V$MULT;

  IF(V$DB_LEVEL = 0) THEN
  BEGIN
      V$BASE = I$OBJ_ID / V$MULT;
      IF(V$GEN <> V$BASE) THEN EXIT;
  END

  -- !!! проверка связи с тестированием при удалении !!!!
  SELECT EXPERT_ID
  FROM UT_EXPERTS
  WHERE EXPERT_ID = :I$OBJ_ID
  INTO :OBJ_ID;

  IF(OBJ_ID IS NULL AND I$DATE_DEL IS NULL) THEN
  BEGIN

      OBJ_ID = I$OBJ_ID;

      INSERT INTO UT_EXPERTS
      (EXPERT_ID, DATE_ADD, DATE_MODIFY, DATE_DEL, TEACHER_ID, ORG_ID, USER_NAME, IS_ACTIVE, LAST_NAME, FIRST_NAME, MIDDLE_NAME)
      VALUES (:I$OBJ_ID, :I$DATE_ADD, :I$DATE_MODIFY, :I$DATE_DEL, :I$TEACHER_ID, :I$ORG_ID, :I$USER_NAME, :I$IS_ACTIVE, :I$LAST_NAME, :I$FIRST_NAME, :I$MID_NAME);

  END
  ELSE IF(OBJ_ID IS NOT NULL) THEN
  BEGIN

      IF(I$DATE_DEL IS NOT NULL) THEN
      BEGIN
          UPDATE UT_EXPERTS
          SET DATE_DEL = :I$DATE_DEL
          WHERE EXPERT_ID = :I$OBJ_ID AND DATE_DEL IS NULL;
      END
      ELSE
      BEGIN
          -- !!! Тут может быть сбой при импорте на чистую базу, надо проверять наличие записей сотрудников
          UPDATE UT_EXPERTS
          SET DATE_DEL = :I$DATE_DEL, TEACHER_ID = :I$TEACHER_ID, ORG_ID = :I$ORG_ID, USER_NAME = :I$USER_NAME, IS_ACTIVE = :I$IS_ACTIVE,
              LAST_NAME = :I$LAST_NAME, FIRST_NAME = :I$FIRST_NAME, MIDDLE_NAME = :I$MID_NAME
          WHERE EXPERT_ID = :I$OBJ_ID;

          -- Обновляем пароль, только снизу вверх по уровню базы
          IF(V$DB_LEVEL > I$SOURCE_LEVEL AND I$PWD IS NOT NULL) THEN
          BEGIN
              UPDATE UT_EXPERTS
              SET PWD = :I$PWD
              WHERE EXPERT_ID = :I$OBJ_ID;
          END
      END

  END

  IF(I$DATE_DEL IS NULL) THEN SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_IMPORT_P1_2 (
    I$EXAM_ID BIGINT,
    I$SOURCE_LEVEL INTEGER,
    I$OBJ_ID BIGINT,
    I$DATE_ADD TIMESTAMP,
    I$DATE_MODIFY TIMESTAMP,
    I$DATE_DEL TIMESTAMP,
    I$OU_ID BIGINT,
    I$DATE_START DATE,
    I$DATE_END DATE)
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$DB_LEVEL bigint;
declare variable V$EXAM_ID bigint;
declare variable V$OU_ID bigint;
begin

  -- При импорте нижестоящих тестирований обратно в вышестоящую базу - данные обновляем только если это свой собственный файл !
  SELECT COALESCE(CAST(K.KEY_VAL AS INTEGER) - 1, 0)
  FROM KEYS K
  WHERE K.KEY_CODE = 'LEVEL'
  INTO :V$DB_LEVEL;

  IF(V$DB_LEVEL > I$SOURCE_LEVEL) THEN EXIT;

  SELECT OBJ_ID, EXAM_ID, OU_ID
  FROM UT_EXAM_OU_ASSN
  WHERE OBJ_ID = :I$OBJ_ID
  INTO :OBJ_ID, :V$EXAM_ID, :V$OU_ID;

  IF(OBJ_ID IS NULL) THEN
  BEGIN

      OBJ_ID = :I$OBJ_ID;

      INSERT INTO UT_EXAM_OU_ASSN
      (OBJ_ID, EXAM_ID, DATE_ADD, DATE_MODIFY, DATE_DEL, OU_ID, DATE_START, DATE_END)
      VALUES (:I$OBJ_ID, :I$EXAM_ID, :I$DATE_ADD, :I$DATE_MODIFY, :I$DATE_DEL, :I$OU_ID, :I$DATE_START, :I$DATE_END);

  END
  ELSE
  BEGIN

      -- Сверка !!!!

      UPDATE UT_EXAM_OU_ASSN
      SET DATE_DEL = :I$DATE_DEL, DATE_START = :I$DATE_START, DATE_END = :I$DATE_END
      WHERE OBJ_ID = :I$OBJ_ID;

  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_IMPORT_P1_3 (
    I$EXAM_ID BIGINT,
    I$IMPORT_METHOD SMALLINT)
RETURNS (
    N_OU INTEGER)
AS
declare variable V$DB_LEVEL bigint;
declare variable V$OU_ID bigint;
declare variable V$H_LEVEL integer;
declare variable V$DATE_DEL timestamp;
declare variable V$IS_ALL smallint;
begin

  SELECT COALESCE(CAST(K.KEY_VAL AS INTEGER) - 1, 0)
  FROM KEYS K
  WHERE K.KEY_CODE = 'LEVEL'
  INTO :V$DB_LEVEL;

  SELECT FIRST 1 L2.OBJ_ID
  FROM LINKS L2
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$OU_ID;

  SELECT H_LEVEL, DATE_DEL
  FROM UT_EXAM_DATES
  WHERE OBJ_ID = :I$EXAM_ID
  INTO :V$H_LEVEL, :V$DATE_DEL;

  SELECT COUNT(*)
  FROM UT_EXAM_OU_ASSN
  WHERE EXAM_ID = :I$EXAM_ID AND DATE_DEL IS NULL
  INTO :N_OU;

  V$IS_ALL = 0;
  SELECT FIRST 1 1
  FROM UT_EXAM_OU_ASSN
  WHERE EXAM_ID = :I$EXAM_ID AND DATE_DEL IS NULL AND OU_ID = 0
  INTO :V$IS_ALL;

  -- Если тестирование удалено, то проверять нечего
  -- Но: если тестирование живое, но эта ОУ в нем более не участвует - удаляем тестирование

  IF(N_OU > 0 AND V$DATE_DEL IS NULL) THEN
  BEGIN
      IF(V$DB_LEVEL = 0) THEN
      BEGIN
          -- База уровня ОУ
          IF(V$IS_ALL = 0 AND NOT EXISTS(
              SELECT FIRST 1 1
              FROM UT_EXAM_OU_ASSN
              WHERE EXAM_ID = :I$EXAM_ID AND DATE_DEL IS NULL AND OU_ID = :V$OU_ID
          ))
          THEN
          BEGIN
              IF(I$IMPORT_METHOD = 0) THEN EXCEPTION DATA_ERROR 'Данная ОУ не назначена в выбранное тестирование, импорт невозможен';
          END
      END
      ELSE IF(V$DB_LEVEL = 1) THEN
      BEGIN
          IF(V$IS_ALL = 0 AND NOT EXISTS(
              SELECT FIRST 1 1
              FROM LINKS L2
              JOIN UT_EXAM_OU_ASSN A ON A.EXAM_ID = :I$EXAM_ID AND A.DATE_DEL IS NULL AND A.OU_ID = L2.OBJ_ID
              WHERE L2.PARENT_TYPE_ID = 111 AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
          ))
          THEN EXCEPTION DATA_ERROR 'В данном районе нет назначенных на тестирование ОУ, импорт невозможен';
      END
  END

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_IMPORT_P2 (
    I$SOURCE_LEVEL SMALLINT,
    I$OBJ_ID BIGINT,
    I$DATE_ADD TIMESTAMP,
    I$DATE_MODIFY TIMESTAMP,
    I$DATE_DEL TIMESTAMP,
    I$SUBJECT_ID BIGINT,
    I$STAGE_ID INTEGER,
    I$METHOD_ID INTEGER,
    I$OBJ_NAME VARCHAR(1000),
    I$IS_AUTO SMALLINT,
    I$STR_HASH VARCHAR(100))
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$DB_LEVEL integer;
begin

  -- При импорте нижестоящих тестирований обратно в вышестоящую базу - данные обновляем только если это свой собственный файл !
  SELECT COALESCE(CAST(K.KEY_VAL AS INTEGER) - 1, 0)
  FROM KEYS K
  WHERE K.KEY_CODE = 'LEVEL'
  INTO :V$DB_LEVEL;

  IF(V$DB_LEVEL > I$SOURCE_LEVEL) THEN EXIT;

  SELECT OBJ_ID
  FROM UT_TEST_STRUCTS
  WHERE OBJ_ID = :I$OBJ_ID
  INTO :OBJ_ID;

  IF(OBJ_ID IS NULL) THEN
  BEGIN

      OBJ_ID = I$OBJ_ID;

      INSERT INTO UT_TEST_STRUCTS
      (OBJ_ID, DATE_ADD, DATE_MODIFY, DATE_DEL, SUBJECT_ID, STAGE_ID, METHOD_ID, OBJ_NAME, IS_AUTO, STR_HASH)
      VALUES (:I$OBJ_ID, :I$DATE_ADD, :I$DATE_MODIFY, :I$DATE_DEL, :I$SUBJECT_ID, :I$STAGE_ID, :I$METHOD_ID, :I$OBJ_NAME, :I$IS_AUTO, :I$STR_HASH);

  END
  ELSE
  BEGIN

      -- Бинарные данные тут не трогаем

      UPDATE UT_TEST_STRUCTS
      SET DATE_DEL = :I$DATE_DEL, SUBJECT_ID = :I$SUBJECT_ID, STAGE_ID = :I$STAGE_ID, METHOD_ID = :I$METHOD_ID,
          OBJ_NAME = :I$OBJ_NAME, IS_AUTO = :I$IS_AUTO, STR_HASH = :I$STR_HASH
      WHERE OBJ_ID = :I$OBJ_ID;

  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_IMPORT_P2_1 (
    I$SOURCE_LEVEL SMALLINT,
    I$STRUCT_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$DATE_ADD TIMESTAMP,
    I$DATE_MODIFY TIMESTAMP,
    I$DATE_DEL TIMESTAMP,
    I$TYPE_ID SMALLINT,
    I$ORDER SMALLINT,
    I$LEVEL SMALLINT,
    I$SCORE SMALLINT,
    I$CHARSET_ID SMALLINT,
    I$NOTES VARCHAR(8000))
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$DB_LEVEL integer;
begin

  -- При импорте нижестоящих тестирований обратно в вышестоящую базу - данные обновляем только если это свой собственный файл !
  SELECT COALESCE(CAST(K.KEY_VAL AS INTEGER) - 1, 0)
  FROM KEYS K
  WHERE K.KEY_CODE = 'LEVEL'
  INTO :V$DB_LEVEL;

  IF(V$DB_LEVEL > I$SOURCE_LEVEL) THEN EXIT;

  SELECT OBJ_ID
  FROM UT_TEST_STRUCT_POINTS
  WHERE OBJ_ID = :I$OBJ_ID
  INTO :OBJ_ID;

  IF(OBJ_ID IS NULL) THEN
  BEGIN

      OBJ_ID = I$OBJ_ID;

      INSERT INTO UT_TEST_STRUCT_POINTS
      (OBJ_ID, DATE_ADD, DATE_MODIFY, DATE_DEL, STRUCT_ID, Q_TYPE_ID, Q_ORDER, Q_LEVEL, Q_MAX_SCORE, CHARSET_ID, TEXT_NOTES)
      VALUES (:I$OBJ_ID, :I$DATE_ADD, :I$DATE_MODIFY, :I$DATE_DEL, :I$STRUCT_ID, :I$TYPE_ID, :I$ORDER, :I$LEVEL, :I$SCORE, :I$CHARSET_ID, :I$NOTES);

  END
  ELSE
  BEGIN

      UPDATE UT_TEST_STRUCT_POINTS
      SET DATE_DEL = :I$DATE_DEL, Q_TYPE_ID = :I$TYPE_ID, Q_ORDER = :I$ORDER, Q_LEVEL = :I$LEVEL, Q_MAX_SCORE = :I$SCORE, CHARSET_ID = :I$CHARSET_ID, TEXT_NOTES = :I$NOTES
      WHERE OBJ_ID = :I$OBJ_ID;

  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_IMPORT_P3 (
    I$SOURCE_LEVEL SMALLINT,
    I$OBJ_ID BIGINT,
    I$DATE_ADD TIMESTAMP,
    I$DATE_MODIFY TIMESTAMP,
    I$DATE_DEL TIMESTAMP,
    I$OBJ_NAME VARCHAR(1000),
    I$N_LEVELS SMALLINT,
    I$OWNER_LEVEL INTEGER,
    I$OWNER_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$DB_LEVEL integer;
begin

  -- При импорте нижестоящих тестирований обратно в вышестоящую базу - данные обновляем только если это свой собственный файл !
  SELECT COALESCE(CAST(K.KEY_VAL AS INTEGER) - 1, 0)
  FROM KEYS K
  WHERE K.KEY_CODE = 'LEVEL'
  INTO :V$DB_LEVEL;

  IF(V$DB_LEVEL > I$SOURCE_LEVEL) THEN EXIT;

  SELECT OBJ_ID
  FROM UT_KIM_CODING
  WHERE OBJ_ID = :I$OBJ_ID
  INTO :OBJ_ID;

  IF(OBJ_ID IS NULL AND I$DATE_DEL IS NULL) THEN
  BEGIN

      OBJ_ID = I$OBJ_ID;

      INSERT INTO UT_KIM_CODING
      (OBJ_ID, DATE_ADD, DATE_MODIFY, DATE_DEL, OBJ_NAME, N_LEVELS, OWNER_LEVEL, OWNER_ID)
      VALUES (:I$OBJ_ID, :I$DATE_ADD, :I$DATE_MODIFY, :I$DATE_DEL, :I$OBJ_NAME, :I$N_LEVELS, :I$OWNER_LEVEL, :I$OWNER_ID);

  END
  ELSE IF(OBJ_ID IS NOT NULL) THEN
  BEGIN

      IF(I$DATE_DEL IS NOT NULL) THEN
      BEGIN
          UPDATE UT_KIM_CODING
          SET DATE_DEL = :I$DATE_DEL
          WHERE OBJ_ID = :I$OBJ_ID AND DATE_DEL IS NULL;
      END
      ELSE
      BEGIN
          UPDATE UT_KIM_CODING
          SET DATE_DEL = :I$DATE_DEL, OBJ_NAME = :I$OBJ_NAME, N_LEVELS = :I$N_LEVELS, OWNER_LEVEL = :I$OWNER_LEVEL, OWNER_ID = :I$OWNER_ID
          WHERE OBJ_ID = :I$OBJ_ID;
      END

  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_IMPORT_P3_1 (
    I$SOURCE_LEVEL SMALLINT,
    I$CODING_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$DATE_ADD TIMESTAMP,
    I$DATE_MODIFY TIMESTAMP,
    I$DATE_DEL TIMESTAMP,
    I$PARENT_ID BIGINT,
    I$OBJ_NAME VARCHAR(1000),
    I$ORDER INTEGER,
    I$N_LEVEL INTEGER)
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$DB_LEVEL integer;
begin

  -- При импорте нижестоящих тестирований обратно в вышестоящую базу - данные обновляем только если это свой собственный файл !
  SELECT COALESCE(CAST(K.KEY_VAL AS INTEGER) - 1, 0)
  FROM KEYS K
  WHERE K.KEY_CODE = 'LEVEL'
  INTO :V$DB_LEVEL;

  IF(V$DB_LEVEL > I$SOURCE_LEVEL) THEN EXIT;

  SELECT OBJ_ID
  FROM UT_KIM_CODING_LEVELS
  WHERE OBJ_ID = :I$OBJ_ID
  INTO :OBJ_ID;

  IF(OBJ_ID IS NULL AND I$DATE_DEL IS NULL) THEN
  BEGIN

      OBJ_ID = I$OBJ_ID;

      INSERT INTO UT_KIM_CODING_LEVELS
      (OBJ_ID, DATE_ADD, DATE_MODIFY, DATE_DEL, CODING_ID, PARENT_ID, OBJ_NAME, SORT_ORDER, N_LEVEL)
      VALUES (:I$OBJ_ID, :I$DATE_ADD, :I$DATE_MODIFY, :I$DATE_DEL, :I$CODING_ID, :I$PARENT_ID, :I$OBJ_NAME, :I$ORDER, :I$N_LEVEL);

  END
  ELSE IF(OBJ_ID IS NOT NULL) THEN
  BEGIN

      IF(I$DATE_DEL IS NOT NULL) THEN
      BEGIN
          UPDATE UT_KIM_CODING_LEVELS
          SET DATE_DEL = :I$DATE_DEL
          WHERE OBJ_ID = :I$OBJ_ID AND DATE_DEL IS NULL;
      END
      ELSE
      BEGIN
          UPDATE UT_KIM_CODING_LEVELS
          SET DATE_DEL = :I$DATE_DEL, PARENT_ID = :I$PARENT_ID, OBJ_NAME = :I$OBJ_NAME, SORT_ORDER = :I$ORDER, N_LEVEL = :I$N_LEVEL
          WHERE OBJ_ID = :I$OBJ_ID;
      END

  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_IMPORT_P3_2 (
    I$SOURCE_LEVEL SMALLINT,
    I$CODING_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$DATE_ADD TIMESTAMP,
    I$DATE_MODIFY TIMESTAMP,
    I$DATE_DEL TIMESTAMP,
    I$STAGE_ID INTEGER)
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$DB_LEVEL integer;
begin

  -- При импорте нижестоящих тестирований обратно в вышестоящую базу - данные обновляем только если это свой собственный файл !
  SELECT COALESCE(CAST(K.KEY_VAL AS INTEGER) - 1, 0)
  FROM KEYS K
  WHERE K.KEY_CODE = 'LEVEL'
  INTO :V$DB_LEVEL;

  IF(V$DB_LEVEL > I$SOURCE_LEVEL) THEN EXIT;

  SELECT OBJ_ID
  FROM UT_KIM_CODING_STAGES
  WHERE OBJ_ID = :I$OBJ_ID
  INTO :OBJ_ID;

  IF(OBJ_ID IS NULL AND I$DATE_DEL IS NULL) THEN
  BEGIN

      OBJ_ID = I$OBJ_ID;

      INSERT INTO UT_KIM_CODING_STAGES
      (OBJ_ID, DATE_ADD, DATE_MODIFY, DATE_DEL, CODING_ID, STAGE_ID)
      VALUES (:I$OBJ_ID, :I$DATE_ADD, :I$DATE_MODIFY, :I$DATE_DEL, :I$CODING_ID, :I$STAGE_ID);

  END
  ELSE IF(OBJ_ID IS NOT NULL) THEN
  BEGIN

      IF(I$DATE_DEL IS NOT NULL) THEN
      BEGIN
          UPDATE UT_KIM_CODING_STAGES
          SET DATE_DEL = :I$DATE_DEL
          WHERE OBJ_ID = :I$OBJ_ID AND DATE_DEL IS NULL;
      END
      ELSE
      BEGIN
          UPDATE UT_KIM_CODING_STAGES
          SET DATE_DEL = :I$DATE_DEL, STAGE_ID = :I$STAGE_ID
          WHERE OBJ_ID = :I$OBJ_ID;
      END

  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_IMPORT_P3_3 (
    I$SOURCE_LEVEL SMALLINT,
    I$CODING_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$DATE_ADD TIMESTAMP,
    I$DATE_MODIFY TIMESTAMP,
    I$DATE_DEL TIMESTAMP,
    I$SUBJECT_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$DB_LEVEL integer;
begin

  -- При импорте нижестоящих тестирований обратно в вышестоящую базу - данные обновляем только если это свой собственный файл !
  SELECT COALESCE(CAST(K.KEY_VAL AS INTEGER) - 1, 0)
  FROM KEYS K
  WHERE K.KEY_CODE = 'LEVEL'
  INTO :V$DB_LEVEL;

  IF(V$DB_LEVEL > I$SOURCE_LEVEL) THEN EXIT;

  SELECT OBJ_ID
  FROM UT_KIM_CODING_SUBJECTS
  WHERE OBJ_ID = :I$OBJ_ID
  INTO :OBJ_ID;

  IF(OBJ_ID IS NULL AND I$DATE_DEL IS NULL) THEN
  BEGIN

      OBJ_ID = I$OBJ_ID;

      INSERT INTO UT_KIM_CODING_SUBJECTS
      (OBJ_ID, DATE_ADD, DATE_MODIFY, DATE_DEL, CODING_ID, SUBJECT_ID)
      VALUES (:I$OBJ_ID, :I$DATE_ADD, :I$DATE_MODIFY, :I$DATE_DEL, :I$CODING_ID, :I$SUBJECT_ID);

  END
  ELSE IF(OBJ_ID IS NOT NULL) THEN
  BEGIN

      IF(I$DATE_DEL IS NOT NULL) THEN
      BEGIN
          UPDATE UT_KIM_CODING_SUBJECTS
          SET DATE_DEL = :I$DATE_DEL
          WHERE OBJ_ID = :I$OBJ_ID AND DATE_DEL IS NULL;
      END
      ELSE
      BEGIN
          UPDATE UT_KIM_CODING_SUBJECTS
          SET DATE_DEL = :I$DATE_DEL, SUBJECT_ID = :I$SUBJECT_ID
          WHERE OBJ_ID = :I$OBJ_ID;
      END

  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_IMPORT_P4 (
    I$SOURCE_LEVEL SMALLINT,
    I$OBJ_ID BIGINT,
    I$DATE_ADD TIMESTAMP,
    I$DATE_MODIFY TIMESTAMP,
    I$DATE_DEL TIMESTAMP,
    I$SECTION_ID BIGINT,
    I$OBJ_NAME VARCHAR(1000),
    I$PARENT_ID BIGINT,
    I$Q_ORDER INTEGER,
    I$Q_TYPE INTEGER,
    I$MAX_SCORE INTEGER,
    I$TIME_LIMIT INTEGER,
    I$METADATA_ID VARCHAR(40),
    I$FLAGS INTEGER,
    I$CHARSET_ID INTEGER,
    I$Q_LEVEL INTEGER)
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$DB_LEVEL integer;
begin

  -- При импорте нижестоящих тестирований обратно в вышестоящую базу - данные обновляем только если это свой собственный файл !
  SELECT COALESCE(CAST(K.KEY_VAL AS INTEGER) - 1, 0)
  FROM KEYS K
  WHERE K.KEY_CODE = 'LEVEL'
  INTO :V$DB_LEVEL;

  IF(V$DB_LEVEL > I$SOURCE_LEVEL) THEN EXIT;

  SELECT OBJ_ID
  FROM UT_QUESTIONS
  WHERE OBJ_ID = :I$OBJ_ID
  INTO :OBJ_ID;

  IF(OBJ_ID IS NULL AND I$DATE_DEL IS NULL) THEN
  BEGIN

      OBJ_ID = I$OBJ_ID;

      INSERT INTO UT_QUESTIONS
      (OBJ_ID, DATE_ADD, DATE_MODIFY, DATE_DEL, OBJ_NAME, PARENT_ID, SECTION_ID, SORT_ORDER, QUESTION_TYPE, MAX_SCORE, TIME_LIMIT, METADATA_ID, FLAGS, CHARSET_ID, Q_LEVEL)
      VALUES (:I$OBJ_ID, :I$DATE_ADD, :I$DATE_MODIFY, :I$DATE_DEL, :I$OBJ_NAME, :I$PARENT_ID, :I$SECTION_ID, :I$Q_ORDER, :I$Q_TYPE, :I$MAX_SCORE, :I$TIME_LIMIT,
          :I$METADATA_ID, :I$FLAGS, :I$CHARSET_ID, :I$Q_LEVEL);

  END
  ELSE IF(OBJ_ID IS NOT NULL) THEN
  BEGIN

      IF(I$DATE_DEL IS NOT NULL) THEN
      BEGIN
          UPDATE UT_QUESTIONS
          SET DATE_DEL = :I$DATE_DEL
          WHERE OBJ_ID = :I$OBJ_ID AND DATE_DEL IS NULL;
      END
      ELSE
      BEGIN
          UPDATE UT_QUESTIONS
          SET DATE_DEL = :I$DATE_DEL, OBJ_NAME = :I$OBJ_NAME, PARENT_ID = :I$PARENT_ID, SECTION_ID = :I$SECTION_ID, SORT_ORDER = :I$Q_ORDER, QUESTION_TYPE = :I$Q_TYPE,
              MAX_SCORE = :I$MAX_SCORE, TIME_LIMIT = :I$TIME_LIMIT, METADATA_ID = :I$METADATA_ID, FLAGS = :I$FLAGS, CHARSET_ID = :I$CHARSET_ID, Q_LEVEL = :I$Q_LEVEL
          WHERE OBJ_ID = :I$OBJ_ID;
      END

  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_IMPORT_P4_1 (
    I$SOURCE_LEVEL SMALLINT,
    I$QUESTION_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$DATE_ADD TIMESTAMP,
    I$DATE_MODIFY TIMESTAMP,
    I$DATE_DEL TIMESTAMP,
    I$OBJ_NAME VARCHAR(400),
    I$ORDER INTEGER,
    I$A_LEVEL INTEGER,
    I$FAKE_ORDER INTEGER,
    I$SIGNATURE SMALLINT)
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$DB_LEVEL integer;
begin

  -- При импорте нижестоящих тестирований обратно в вышестоящую базу - данные обновляем только если это свой собственный файл !
  SELECT COALESCE(CAST(K.KEY_VAL AS INTEGER) - 1, 0)
  FROM KEYS K
  WHERE K.KEY_CODE = 'LEVEL'
  INTO :V$DB_LEVEL;

  IF(V$DB_LEVEL > I$SOURCE_LEVEL) THEN EXIT;

  SELECT OBJ_ID
  FROM UT_ANSWERS
  WHERE OBJ_ID = :I$OBJ_ID
  INTO :OBJ_ID;

  IF(OBJ_ID IS NULL AND I$DATE_DEL IS NULL) THEN
  BEGIN

      OBJ_ID = I$OBJ_ID;

      INSERT INTO UT_ANSWERS
      (OBJ_ID, DATE_ADD, DATE_MODIFY, DATE_DEL, QUESTION_ID, OBJ_NAME, SORT_ORDER, A_LEVEL, FAKE_ORDER, SIGNATURE)
      VALUES (:I$OBJ_ID, :I$DATE_ADD, :I$DATE_MODIFY, :I$DATE_DEL, :I$QUESTION_ID, :I$OBJ_NAME, :I$ORDER, :I$A_LEVEL, :I$FAKE_ORDER, :I$SIGNATURE);

  END
  ELSE IF(OBJ_ID IS NOT NULL) THEN
  BEGIN

      IF(I$DATE_DEL IS NOT NULL) THEN
      BEGIN
          UPDATE UT_ANSWERS
          SET DATE_DEL = :I$DATE_DEL
          WHERE OBJ_ID = :I$OBJ_ID AND DATE_DEL IS NULL;
      END
      ELSE
      BEGIN
          UPDATE UT_ANSWERS
          SET DATE_DEL = :I$DATE_DEL, OBJ_NAME = :I$OBJ_NAME, SORT_ORDER = :I$ORDER, A_LEVEL = :I$A_LEVEL, FAKE_ORDER = :I$FAKE_ORDER, SIGNATURE = :I$SIGNATURE
          WHERE OBJ_ID = :I$OBJ_ID;
      END

  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_IMPORT_P5 (
    I$SOURCE_LEVEL SMALLINT,
    I$OBJ_ID BIGINT,
    I$DATE_ADD TIMESTAMP,
    I$DATE_MODIFY TIMESTAMP,
    I$DATE_DEL TIMESTAMP,
    I$OBJ_NAME VARCHAR(1000),
    I$STRUCT_ID BIGINT,
    I$MASTER_ED_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$DB_LEVEL integer;
begin

  -- При импорте нижестоящих тестирований обратно в вышестоящую базу - данные обновляем только если это свой собственный файл !
  SELECT COALESCE(CAST(K.KEY_VAL AS INTEGER) - 1, 0)
  FROM KEYS K
  WHERE K.KEY_CODE = 'LEVEL'
  INTO :V$DB_LEVEL;

  IF(V$DB_LEVEL > I$SOURCE_LEVEL) THEN EXIT;

  SELECT OBJ_ID
  FROM UT_TESTS
  WHERE OBJ_ID = :I$OBJ_ID
  INTO :OBJ_ID;

  IF(OBJ_ID IS NULL AND I$DATE_DEL IS NULL) THEN
  BEGIN

      OBJ_ID = I$OBJ_ID;

      INSERT INTO UT_TESTS
      (OBJ_ID, DATE_ADD, DATE_MODIFY, DATE_DEL, OBJ_NAME, STRUCT_ID, MASTER_ED_ID)
      VALUES (:I$OBJ_ID, :I$DATE_ADD, :I$DATE_MODIFY, :I$DATE_DEL, :I$OBJ_NAME, :I$STRUCT_ID, :I$MASTER_ED_ID);

  END
  ELSE IF(OBJ_ID IS NOT NULL) THEN
  BEGIN

      IF(I$DATE_DEL IS NOT NULL) THEN
      BEGIN
          UPDATE UT_TESTS
          SET DATE_DEL = :I$DATE_DEL
          WHERE OBJ_ID = :I$OBJ_ID AND DATE_DEL IS NULL;
      END
      ELSE
      BEGIN
          UPDATE UT_TESTS
          SET DATE_DEL = :I$DATE_DEL, OBJ_NAME = :I$OBJ_NAME, STRUCT_ID = :I$STRUCT_ID, MASTER_ED_ID = :I$MASTER_ED_ID
          WHERE OBJ_ID = :I$OBJ_ID;
      END

  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_IMPORT_P5_1 (
    I$SOURCE_LEVEL SMALLINT,
    I$TEST_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$DATE_ADD TIMESTAMP,
    I$DATE_MODIFY TIMESTAMP,
    I$DATE_DEL TIMESTAMP,
    I$OBJ_NAME VARCHAR(400),
    I$NUM INTEGER,
    I$MASTER_ED_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$DB_LEVEL integer;
begin

  -- При импорте нижестоящих тестирований обратно в вышестоящую базу - данные обновляем только если это свой собственный файл !
  SELECT COALESCE(CAST(K.KEY_VAL AS INTEGER) - 1, 0)
  FROM KEYS K
  WHERE K.KEY_CODE = 'LEVEL'
  INTO :V$DB_LEVEL;

  IF(V$DB_LEVEL > I$SOURCE_LEVEL) THEN EXIT;

  SELECT OBJ_ID
  FROM UT_TEST_VARS
  WHERE OBJ_ID = :I$OBJ_ID
  INTO :OBJ_ID;

  IF(OBJ_ID IS NULL AND I$DATE_DEL IS NULL) THEN
  BEGIN

      OBJ_ID = I$OBJ_ID;

      INSERT INTO UT_TEST_VARS
      (OBJ_ID, DATE_ADD, DATE_MODIFY, DATE_DEL, TEST_ID, OBJ_NAME, NUM, MASTER_ED_ID)
      VALUES (:I$OBJ_ID, :I$DATE_ADD, :I$DATE_MODIFY, :I$DATE_DEL, :I$TEST_ID, :I$OBJ_NAME, :I$NUM, :I$MASTER_ED_ID);

  END
  ELSE IF(OBJ_ID IS NOT NULL) THEN
  BEGIN

      IF(I$DATE_DEL IS NOT NULL) THEN
      BEGIN
          UPDATE UT_TEST_VARS
          SET DATE_DEL = :I$DATE_DEL
          WHERE OBJ_ID = :I$OBJ_ID AND DATE_DEL IS NULL;
      END
      ELSE
      BEGIN
          UPDATE UT_TEST_VARS
          SET DATE_DEL = :I$DATE_DEL, OBJ_NAME = :I$OBJ_NAME, NUM = :I$NUM, MASTER_ED_ID = :I$MASTER_ED_ID
          WHERE OBJ_ID = :I$OBJ_ID;
      END

  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_IMPORT_P5_2 (
    I$SOURCE_LEVEL SMALLINT,
    I$VAR_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$DATE_ADD TIMESTAMP,
    I$DATE_MODIFY TIMESTAMP,
    I$DATE_DEL TIMESTAMP,
    I$STRUCT_POINT_ID BIGINT,
    I$QUESTION_ID BIGINT,
    I$ORDER_INDEX INTEGER)
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$DB_LEVEL integer;
begin

  -- При импорте нижестоящих тестирований обратно в вышестоящую базу - данные обновляем только если это свой собственный файл !
  SELECT COALESCE(CAST(K.KEY_VAL AS INTEGER) - 1, 0)
  FROM KEYS K
  WHERE K.KEY_CODE = 'LEVEL'
  INTO :V$DB_LEVEL;

  IF(V$DB_LEVEL > I$SOURCE_LEVEL) THEN EXIT;

  SELECT OBJ_ID
  FROM UT_TEST_VAR_QUESTIONS
  WHERE OBJ_ID = :I$OBJ_ID
  INTO :OBJ_ID;

  IF(OBJ_ID IS NULL AND I$DATE_DEL IS NULL) THEN
  BEGIN

      OBJ_ID = I$OBJ_ID;

      INSERT INTO UT_TEST_VAR_QUESTIONS
      (OBJ_ID, DATE_ADD, DATE_MODIFY, DATE_DEL, VAR_ID, STRUCT_POINT_ID, QUESTION_ID, ORDER_INDEX)
      VALUES (:I$OBJ_ID, :I$DATE_ADD, :I$DATE_MODIFY, :I$DATE_DEL, :I$VAR_ID, :I$STRUCT_POINT_ID, :I$QUESTION_ID, :I$ORDER_INDEX);

  END
  ELSE IF(OBJ_ID IS NOT NULL) THEN
  BEGIN

      IF(I$DATE_DEL IS NOT NULL) THEN
      BEGIN
          UPDATE UT_TEST_VAR_QUESTIONS
          SET DATE_DEL = :I$DATE_DEL
          WHERE OBJ_ID = :I$OBJ_ID AND DATE_DEL IS NULL;
      END
      ELSE
      BEGIN
          UPDATE UT_TEST_VAR_QUESTIONS
          SET DATE_DEL = :I$DATE_DEL, STRUCT_POINT_ID = :I$STRUCT_POINT_ID, QUESTION_ID = :I$QUESTION_ID, ORDER_INDEX = :I$ORDER_INDEX
          WHERE OBJ_ID = :I$OBJ_ID;
      END

  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_IMPORT_P6 (
    I$SOURCE_LEVEL SMALLINT,
    I$EXAM_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$DATE_ADD TIMESTAMP,
    I$DATE_MODIFY TIMESTAMP,
    I$DATE_DEL TIMESTAMP,
    I$VARIANT_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$DB_LEVEL integer;
begin

  -- При импорте нижестоящих тестирований обратно в вышестоящую базу - данные обновляем только если это свой собственный файл !
  SELECT COALESCE(CAST(K.KEY_VAL AS INTEGER) - 1, 0)
  FROM KEYS K
  WHERE K.KEY_CODE = 'LEVEL'
  INTO :V$DB_LEVEL;

  IF(V$DB_LEVEL > I$SOURCE_LEVEL) THEN EXIT;

  -- !!! проверка связи с тестированием !!!!
  SELECT OBJ_ID
  FROM UT_EXAM_TEST_VARS
  WHERE OBJ_ID = :I$OBJ_ID
  INTO :OBJ_ID;

  IF(OBJ_ID IS NULL AND I$DATE_DEL IS NULL) THEN
  BEGIN

      OBJ_ID = I$OBJ_ID;

      INSERT INTO UT_EXAM_TEST_VARS
      (OBJ_ID, DATE_ADD, DATE_MODIFY, DATE_DEL, EXAM_ID, TEST_VAR_ID)
      VALUES (:I$OBJ_ID, :I$DATE_ADD, :I$DATE_MODIFY, :I$DATE_DEL, :I$EXAM_ID, :I$VARIANT_ID);

  END
  ELSE IF(OBJ_ID IS NOT NULL) THEN
  BEGIN

      IF(I$DATE_DEL IS NOT NULL) THEN
      BEGIN
          UPDATE UT_EXAM_TEST_VARS
          SET DATE_DEL = :I$DATE_DEL
          WHERE OBJ_ID = :I$OBJ_ID AND DATE_DEL IS NULL;
      END
      ELSE
      BEGIN
          UPDATE UT_EXAM_TEST_VARS
          SET DATE_DEL = :I$DATE_DEL, TEST_VAR_ID = :I$VARIANT_ID
          WHERE OBJ_ID = :I$OBJ_ID;
      END

  END

  IF(I$DATE_DEL IS NULL) THEN SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_IMPORT_P7 (
    I$SOURCE_LEVEL SMALLINT,
    I$OBJ_ID BIGINT NOT NULL,
    I$DATE_ADD TIMESTAMP NOT NULL,
    I$DATE_MODIFY TIMESTAMP NOT NULL,
    I$DATE_DEL TIMESTAMP,
    I$VAR_ID BIGINT NOT NULL,
    I$OBJ_NAME VARCHAR(1000) NOT NULL,
    I$FILE_HASH VARCHAR(40),
    I$CONTENT_TYPE VARCHAR(40) NOT NULL,
    I$ATTR_MASK INTEGER)
RETURNS (
    OBJ_ID BIGINT)
AS
DECLARE VARIABLE V$DB_LEVEL INTEGER;
begin
  --импорт файлов тестирования

  -- При импорте нижестоящих тестирований обратно в вышестоящую базу - данные обновляем только если это свой собственный файл !
  SELECT COALESCE(CAST(K.KEY_VAL AS INTEGER) - 1, 0)
  FROM KEYS K
  WHERE K.KEY_CODE = 'LEVEL'
  INTO :V$DB_LEVEL;

  IF (V$DB_LEVEL > I$SOURCE_LEVEL) THEN EXIT;
  IF (I$DATE_DEL IS NOT NULL) THEN EXIT;

  SELECT OBJ_ID
  FROM UT_TEST_VAR_FILES
  WHERE OBJ_ID = :I$OBJ_ID
  INTO :OBJ_ID;
--  EXCEPTION DATA_ERROR 'OBJ_ID = ' || IIF(OBJ_ID IS NULL, 'NULL', CAST(OBJ_ID AS VARCHAR(20)));

  IF(OBJ_ID IS NULL) THEN
  BEGIN
    OBJ_ID = I$OBJ_ID;

    INSERT INTO UT_TEST_VAR_FILES
      (OBJ_ID, DATE_ADD, DATE_MODIFY, DATE_DEL, VAR_ID, OBJ_NAME, FILE_HASH, CONTENT_TYPE, ATTR_MASK)
    VALUES (:I$OBJ_ID, :I$DATE_ADD, :I$DATE_MODIFY, NULL, :I$VAR_ID, :I$OBJ_NAME, :I$FILE_HASH, :I$CONTENT_TYPE, :I$ATTR_MASK);
  END
  ELSE
  BEGIN
    UPDATE UT_TEST_VAR_FILES
    SET
      DATE_ADD = :I$DATE_ADD,
      DATE_MODIFY = :I$DATE_MODIFY,
      DATE_DEL = NULL,
      VAR_ID = :I$VAR_ID,
      OBJ_NAME = :I$OBJ_NAME,
      FILE_HASH = :I$FILE_HASH,
      CONTENT_TYPE = :I$CONTENT_TYPE,
      ATTR_MASK = :I$ATTR_MASK
    WHERE OBJ_ID = :I$OBJ_ID;
  END

  SUSPEND;
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_KIM_LIST (
    I$EXAM_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$DB_LEVEL SMALLINT;
DECLARE VARIABLE V$STATE INTEGER;
DECLARE VARIABLE V$ORG_REF BIGINT;
DECLARE VARIABLE V$LEVEL INTEGER;
DECLARE VARIABLE V$OUR_ORG BIGINT;
DECLARE VARIABLE V$METHOD SMALLINT;
DECLARE VARIABLE V$PLAN_METHOD SMALLINT;
DECLARE VARIABLE V$NAME VARCHAR(1000);
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$NUM INTEGER;
DECLARE VARIABLE V$FILE_ID BIGINT;
DECLARE VARIABLE V$CONTENT_TYPE VARCHAR(100);
DECLARE VARIABLE V$HASH VARCHAR(100);
begin

  -- Идентифицируем себя
  SELECT COALESCE(CAST(K.KEY_VAL AS INTEGER) - 1, 0)
  FROM KEYS K
  WHERE K.KEY_CODE = 'LEVEL'
  INTO :V$DB_LEVEL;

  IF(V$DB_LEVEL <> 0) THEN EXCEPTION DATA_ERROR 'Печать бланков может выполняться только на уровне ОУ';

  SELECT D.EXAM_STATE, D.ORG_REF, D.H_LEVEL, D.METHOD_ID, D.PLAN_METHOD_ID
  FROM UT_EXAM_DATES D
  WHERE D.OBJ_ID = :I$EXAM_ID AND D.DATE_DEL IS NULL
  INTO :V$STATE, :V$ORG_REF, :V$LEVEL, :V$METHOD, :V$PLAN_METHOD;

  IF(V$STATE IS NULL) THEN EXCEPTION DATA_ERROR 'Тестирование не найдено или было удалено';
  IF(V$STATE < 600 OR V$STATE >= 1000) THEN EXCEPTION DATA_ERROR 'Печать КИМ в данном статусе невозможна';
  --IF(V$METHOD = 0) THEN EXCEPTION DATA_ERROR 'Для электронного тестирования печать не предусмотрена';

  SELECT FIRST 1 L2.OBJ_ID
  FROM LINKS L2
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$OUR_ORG;

  -- Возвращаем список КИМ в данном тестировании

  TAG_NAME = 'items';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'items::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
      SELECT TV.OBJ_ID, TV.NUM, TV.OBJ_NAME
      FROM UT_EXAM_TEST_VARS ETV
      JOIN UT_TEST_VARS TV ON TV.OBJ_ID = ETV.TEST_VAR_ID AND TV.DATE_DEL IS NULL
      WHERE ETV.DATE_DEL IS NULL AND ETV.EXAM_ID = :I$EXAM_ID
      ORDER BY 2
      INTO :V$OBJ_ID, :V$NUM, :V$NAME
  DO
  BEGIN
      TAG_NAME = 'items:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'items:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'items:r:num';
      VAL = V$NUM;
      SUSPEND;
      TAG_NAME = 'items:r:obj_name';
      VAL = V$NAME;
      SUSPEND;

      -- Файлы
      TAG_NAME = 'items:r:files';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'items:r:files::json&colon;array';
      VAL = NULL;
      SUSPEND;
      FOR
          SELECT F.OBJ_ID, F.OBJ_NAME, F.CONTENT_TYPE, CHAR_LENGTH(F.CONTENT_DATA), F.ATTR_MASK, F.FILE_HASH
          FROM UT_TEST_VAR_FILES F
          WHERE F.DATE_DEL IS NULL AND F.VAR_ID = :V$OBJ_ID
          INTO :V$FILE_ID, :V$NAME, :V$CONTENT_TYPE, :V$NUM, :V$LEVEL, :V$HASH
      DO
      BEGIN
          TAG_NAME = 'items:r:files:r';
          VAL = NULL;
          SUSPEND;
          TAG_NAME = 'items:r:files:r:id';
          VAL = V$FILE_ID;
          SUSPEND;
          TAG_NAME = 'items:r:files:r:name';
          VAL = V$NAME;
          SUSPEND;
          TAG_NAME = 'items:r:files:r:hash';
          VAL = V$HASH;
          SUSPEND;
          TAG_NAME = 'items:r:files:r:type';
          VAL = V$CONTENT_TYPE;
          SUSPEND;
          TAG_NAME = 'items:r:files:r:mask';
          VAL = V$LEVEL;
          SUSPEND;
          TAG_NAME = 'items:r:files:r:size';
          VAL = V$NUM;
          SUSPEND;
      END
  END

  -- Сколько всего бланков уже распечатано ?

  -- Печать только в ОУ, где есть назначение
  IF(V$PLAN_METHOD = 0) THEN
  BEGIN

      -- ППЭ, по помещениям

  END
  ELSE IF(V$PLAN_METHOD = 1) THEN
  BEGIN

      -- ППЭ, по коллективам

  END
  ELSE
  BEGIN

      -- По коллективам как есть

  END

  TAG_NAME = 'n_total';
  VAL = '9999';
  SUSPEND;
  TAG_NAME = 'n_printed';
  VAL = '0';
  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_MON_DATA (
    I$EXAM_ID BIGINT,
    I$USER_ID VARCHAR(40),
    I$EXT SMALLINT = 0)
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(1000))
AS
declare variable V$OBJ_ID bigint;
declare variable V$CNT integer;
declare variable V$PREV_CNT integer;
declare variable V$STRUCT_ID bigint;
declare variable V$TYPE integer;
declare variable V$MAX_SCORE integer;
declare variable V$VALUE varchar(10);
declare variable V$NAME varchar(200);
declare variable V$L float;
declare variable V$H float;
declare variable V$N0 integer;
declare variable V$NMIN integer;
declare variable V$N4 integer;
declare variable V$N5 integer;
declare variable V$NMAX integer;
declare variable V$WMIN float;
declare variable V$WMAX float;
begin

  -- Получаем первый попавшийся идентификатор структуры
  SELECT FIRST 1 T.STRUCT_ID, D.SCALE_N0, D.SCALE_NMIN, D.SCALE_N4, D.SCALE_N5, D.SCALE_NMAX
  FROM UT_EXAM_DATES D
  JOIN UT_EXAM_TEST_VARS ETV ON ETV.EXAM_ID = D.OBJ_ID AND ETV.DATE_DEL IS NULL
  JOIN UT_TEST_VARS TV ON TV.OBJ_ID = ETV.TEST_VAR_ID
  JOIN UT_TESTS T ON T.OBJ_ID = TV.TEST_ID
  WHERE D.OBJ_ID = :I$EXAM_ID AND D.DATE_DEL IS NULL
  INTO :V$STRUCT_ID, :V$N0, :V$NMIN, :V$N4, :V$N5, :V$NMAX;

  TAG_NAME = 'scale_n0';
  VAL = V$N0;
  SUSPEND;
  TAG_NAME = 'scale_nmin';
  VAL = V$NMIN;
  SUSPEND;
  TAG_NAME = 'scale_n4';
  VAL = V$N4;
  SUSPEND;
  TAG_NAME = 'scale_n5';
  VAL = V$N5;
  SUSPEND;
  TAG_NAME = 'scale_nmax';
  VAL = V$NMAX;
  SUSPEND;

  TAG_NAME = 'n_assigned';
  SELECT COUNT(*)
  FROM UT_EXAM_DATES D
  JOIN UT_EXAM_PERSON_ASSN PA ON PA.EXAM_ID = D.OBJ_ID AND PA.DATE_DEL IS NULL
  WHERE D.DATE_DEL IS NULL AND D.OBJ_ID = :I$EXAM_ID
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'n_ppe_assigned';
  SELECT COUNT(*)
  FROM UT_EXAM_DATES D
  JOIN UT_PERSON_PPE_ASSN PA ON PA.EXAM_ID = D.OBJ_ID AND PA.DATE_DEL IS NULL
  WHERE D.DATE_DEL IS NULL AND D.OBJ_ID = :I$EXAM_ID
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'n_places_assigned';
  SELECT COUNT(*)
  FROM UT_EXAM_DATES D
  JOIN UT_PERSON_PLACE_ASSN PA ON PA.EXAM_ID = D.OBJ_ID AND PA.DATE_DEL IS NULL
  WHERE D.DATE_DEL IS NULL AND D.OBJ_ID = :I$EXAM_ID
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'n_accepted';
  SELECT COUNT(DISTINCT S.PERSON_ID)
  FROM UT_EXAM_DATES D
  JOIN UT_SESSIONS S ON S.ED_ID = D.OBJ_ID AND S.DATE_DEL IS NULL
  WHERE D.DATE_DEL IS NULL AND D.OBJ_ID = :I$EXAM_ID
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'n_completed';
  SELECT COUNT(DISTINCT S.PERSON_ID)
  FROM UT_EXAM_DATES D
  JOIN UT_SESSIONS S ON S.ED_ID = D.OBJ_ID AND S.DATE_DEL IS NULL AND S.STATE_ID IN (100, 102)
  WHERE D.DATE_DEL IS NULL AND D.OBJ_ID = :I$EXAM_ID
  INTO :VAL;
  SUSPEND;

  -- Данные для деталей по вопросам
  TAG_NAME = 'n_questions';
  VAL = NULL;
  SELECT COUNT(*)
  FROM UT_TEST_STRUCT_POINTS
  WHERE DATE_DEL IS NULL AND STRUCT_ID = :V$STRUCT_ID
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'max_result';
  VAL = NULL;
  SELECT MAX(S.RAW_RESULT)
  FROM UT_EXAM_DATES D
  JOIN UT_SESSIONS S ON S.ED_ID = D.OBJ_ID AND S.DATE_DEL IS NULL AND S.STATE_ID >= 10 AND S.STATE_ID <> 101
  WHERE D.DATE_DEL IS NULL AND D.OBJ_ID = :I$EXAM_ID
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'min_result';
  VAL = NULL;
  SELECT MIN(S.RAW_RESULT)
  FROM UT_EXAM_DATES D
  JOIN UT_SESSIONS S ON S.ED_ID = D.OBJ_ID AND S.DATE_DEL IS NULL AND S.STATE_ID >= 10 AND S.STATE_ID <> 101
  WHERE D.DATE_DEL IS NULL AND D.OBJ_ID = :I$EXAM_ID
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'avg_result';
  VAL = NULL;
  SELECT CAST(AVG(CAST(S.RAW_RESULT AS FLOAT)) AS NUMERIC(18, 2))
  FROM UT_EXAM_DATES D
  JOIN UT_SESSIONS S ON S.ED_ID = D.OBJ_ID AND S.DATE_DEL IS NULL AND S.STATE_ID >= 10 AND S.STATE_ID <> 101
  WHERE D.DATE_DEL IS NULL AND D.OBJ_ID = :I$EXAM_ID
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'dispersion';
  VAL = NULL;
  SUSPEND;

  -- Распределение по статусам бланков - для бланков до и на верификации

  -- Распределение по очередям обработки - для бланков уже прошедших верификацию
  TAG_NAME = 'queues';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'queues::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
      SELECT A.OBJ_ID, (
          SELECT COUNT(*)
          FROM UT_SESSION_QUESTIONS Q
          JOIN UT_SESSIONS S ON S.OBJ_ID = Q.SESSION_ID AND S.DATE_DEL IS NULL AND S.ED_ID = :I$EXAM_ID
          WHERE Q.STATE_ID = A.OBJ_ID AND Q.DATE_DEL IS NULL
      ) CNT
      FROM UT_ANSWER_STATES A
      WHERE A.IS_DEL = 0 AND A.OBJ_ID > 0
      ORDER BY 1
      INTO :V$OBJ_ID, :V$CNT
  DO
  BEGIN
      TAG_NAME = 'queues:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'queues:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'queues:r:name';
      VAL = (SELECT OBJ_NAME FROM UT_ANSWER_STATES WHERE OBJ_ID = :V$OBJ_ID);
      SUSPEND;
      TAG_NAME = 'queues:r:value';
      VAL = V$CNT;
      SUSPEND;

      -- Детализируем статусы для проверок экспертами в статусе - Передан на проверку
      IF(V$OBJ_ID = 50) THEN
      BEGIN
      END
  END

  -- Гистограмма результатов
  TAG_NAME = 'hysto';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'hysto::json&colon;array';
  VAL = '1';
  SUSPEND;

  V$PREV_CNT = -1;

  FOR
      SELECT S.RAW_RESULT, COUNT(*)
      FROM UT_SESSIONS S
      WHERE S.DATE_DEL IS NULL AND S.ED_ID = :I$EXAM_ID AND S.RAW_RESULT IS NOT NULL -- AND S.STATE_ID > 50 AND S.STATE_ID <> 1001
      GROUP BY 1
      ORDER BY 1
      INTO :V$OBJ_ID, :V$CNT
  DO
  BEGIN
      -- Заполняем выпавшие промежуточные значения
      IF(V$OBJ_ID > V$PREV_CNT + 1) THEN
      BEGIN
          V$PREV_CNT = V$PREV_CNT + 1;
          WHILE(V$PREV_CNT <= V$OBJ_ID - 1) DO
          BEGIN
              TAG_NAME = 'hysto:r';
              VAL = NULL;
              SUSPEND;
              TAG_NAME = 'hysto:r:score';
              VAL = V$PREV_CNT;
              SUSPEND;
              TAG_NAME = 'hysto:r:value';
              VAL = '';
              SUSPEND;
              V$PREV_CNT = V$PREV_CNT + 1;
          END
      END

      TAG_NAME = 'hysto:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'hysto:r:score';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'hysto:r:value';
      VAL = V$CNT;
      SUSPEND;

      V$PREV_CNT = V$OBJ_ID;
  END

  -- Расширенная статистика, вызывается в app.test_review
  IF(I$EXT = 0) THEN EXIT;

  TAG_NAME = 'questions';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'questions::json&colon;array';
  VAL = '1';
  SUSPEND;

  IF(V$STRUCT_ID IS NULL) THEN EXIT;

  FOR
      SELECT TSP.Q_ORDER, TSP.Q_TYPE_ID, TSP.Q_MAX_SCORE, QT.OBJ_NAME, QT.OBJ_VALUE, TSP.WND_MIN, TSP.WND_MAX
      FROM UT_TEST_STRUCT_POINTS TSP
      JOIN UT_QUESTION_TYPE QT ON QT.OBJ_ID = TSP.Q_TYPE_ID
      WHERE TSP.STRUCT_ID = :V$STRUCT_ID AND TSP.DATE_DEL IS NULL
      ORDER BY 1
      INTO :V$CNT, :V$TYPE, :V$MAX_SCORE, :V$NAME, :V$VALUE, :V$WMIN, :V$WMAX
  DO
  BEGIN

      TAG_NAME = 'questions:r';
      VAL = NULL;
      SUSPEND;

      TAG_NAME = 'questions:r:index';
      VAL = V$CNT;
      SUSPEND;

      TAG_NAME = 'questions:r:type';
      VAL = V$TYPE;
      SUSPEND;

      TAG_NAME = 'questions:r:type_name';
      VAL = V$VALUE;
      SUSPEND;

      TAG_NAME = 'questions:r:type_desc';
      VAL = V$NAME;
      SUSPEND;

      -- V$MAX_SCORE = RAND() * 10;

      -- Коридор берем исходя из максимальных баллов, если не заданы стандартные
      IF(V$WMIN IS NULL AND V$WMAX IS NULL) THEN
        BEGIN
          IF(V$MAX_SCORE <= 2) THEN
          BEGIN
            V$L = 60;
            V$H = 90;
          END
          ELSE IF(V$MAX_SCORE <= 5) THEN
          BEGIN
            V$L = 40;
            V$H = 60;
          END
          ELSE
          BEGIN
            V$L = 0;
            V$H = 40;
          END
        END
      ELSE BEGIN
       V$L = V$WMIN;
       V$H = V$WMAX;
      END

      TAG_NAME = 'questions:r:b_min';
      VAL = CAST(V$L AS NUMERIC(18, 1));
      SUSPEND;

      TAG_NAME = 'questions:r:b_max';
      VAL = CAST(V$H AS NUMERIC(18, 1));
      SUSPEND;

      TAG_NAME = 'questions:r:score';
      VAL = V$MAX_SCORE;
      SUSPEND;

      -- Решаемость - % набравших максимальный балл, пока для всех типов заданий
      -- Количество участников, прошедших данный вопрос
      TAG_NAME = 'questions:r:n_total';
      SELECT COUNT(*)
      FROM UT_SESSIONS S
      JOIN UT_SESSION_QUESTIONS Q ON Q.SESSION_ID = S.OBJ_ID AND Q.DATE_DEL IS NULL AND Q.STATE_ID >= 21
      JOIN UT_TEST_VAR_QUESTIONS TVQ ON TVQ.OBJ_ID = Q.QUESTION_ID
      JOIN UT_TEST_STRUCT_POINTS TSP ON TSP.OBJ_ID = TVQ.STRUCT_POINT_ID AND TSP.Q_ORDER = :V$CNT
      WHERE S.ED_ID = :I$EXAM_ID AND S.STATE_ID >= 10 AND S.STATE_ID <> 101
      INTO :VAL;
      SUSPEND;

      -- Количество успешно решивших
      TAG_NAME = 'questions:r:n_success';
      SELECT COUNT(*)
      FROM UT_SESSIONS S
      JOIN UT_SESSION_QUESTIONS Q ON Q.SESSION_ID = S.OBJ_ID AND Q.DATE_DEL IS NULL AND Q.STATE_ID >= 21 AND Q.RAW_RESULT >= :V$MAX_SCORE
      JOIN UT_TEST_VAR_QUESTIONS TVQ ON TVQ.OBJ_ID = Q.QUESTION_ID
      JOIN UT_TEST_STRUCT_POINTS TSP ON TSP.OBJ_ID = TVQ.STRUCT_POINT_ID AND TSP.Q_ORDER = :V$CNT
      WHERE S.ED_ID = :I$EXAM_ID AND S.STATE_ID >= 10 AND S.STATE_ID <> 101
      INTO :VAL;
      SUSPEND;

      -- Критерии для экспертных проверок
      IF(V$TYPE IN (3, 8)) THEN
      BEGIN
          -- Параметр недостоверных итогов всегда пустой
          TAG_NAME = 'questions:r:n_unsure';
          VAL = '';
          SUSPEND;
      END
      -- Для дискретных вопросов проверяем веер ответов
      ELSE
      BEGIN
          -- Количекство недостоверных результатов
          TAG_NAME = 'questions:r:n_unsure';
          SELECT COUNT(*)
          FROM UT_SESSIONS S
          JOIN UT_SESSION_QUESTIONS SQ ON SQ.DATE_DEL IS NULL AND SQ.SESSION_ID = S.OBJ_ID AND SQ.STATE_ID = 30 -- статус 30 = залипание
          JOIN UT_TEST_VAR_QUESTIONS TVQ ON TVQ.OBJ_ID = SQ.QUESTION_ID
          JOIN UT_TEST_STRUCT_POINTS TSP ON TSP.OBJ_ID = TVQ.STRUCT_POINT_ID AND TSP.Q_ORDER = :V$CNT
          WHERE S.DATE_DEL IS NULL AND S.ED_ID = :I$EXAM_ID
          INTO :VAL;
          SUSPEND;
      END

  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_PERSON_BLANKS (
    I$EXAM_ID BIGINT,
    I$PERSON_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
declare variable V$STATE integer;
declare variable V$LOCAL_ID varchar(40);
declare variable V$DATE date;
declare variable V$NAME varchar(200);
declare variable V$STAGE_ID integer;
declare variable V$SUBJECT_ID bigint;
declare variable V$CLASS_NAME varchar(100);
declare variable V$OU_NAME varchar(200);
begin

  -- Первыми строками возвращаются шаблоны всех бланков в BLOB_ID, в TAG_NAME передается текст BLOB, в VAL описание бланка
  -- После чего выдаются уже сериализованные данные по участнику

  SELECT D.EXAM_STATE, D.EXAM_DATE_START, D.OBJ_NAME, D.SUBJECT_ID, D.STAGE_ID
  FROM UT_EXAM_DATES D
  WHERE D.OBJ_ID = :I$EXAM_ID AND D.DATE_DEL IS NULL
  INTO :V$STATE, :V$DATE, :V$NAME, :V$SUBJECT_ID, :V$STAGE_ID;

  IF(V$STATE IS NULL) THEN EXCEPTION DATA_ERROR 'Тестирование не найдено или было удалено';
  IF(V$STATE < 600 OR V$STATE >= 1000) THEN EXCEPTION DATA_ERROR 'Недопустимый статус тестирования';

  TAG_NAME = 'data:exam_id';
  VAL = I$EXAM_ID;
  SUSPEND;

  TAG_NAME = 'data:exam_name';
  VAL = V$NAME;
  SUSPEND;

  TAG_NAME = 'data:subject_name';
  IF(V$SUBJECT_ID IS NULL) THEN VAL = 'Метапредмет'; ELSE VAL = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$SUBJECT_ID));
  SUSPEND;

  TAG_NAME = 'data:stage_name';
  VAL = (SELECT OBJ_NAME FROM UT_EXAM_STAGES WHERE OBJ_ID = :V$STAGE_ID);
  SUSPEND;

  TAG_NAME = 'data:exam_date_start';
  VAL = (SELECT VAL FROM DATE2ISO(:V$DATE, 0));
  SUSPEND;

  TAG_NAME = 'data:exam_date_str';
  VAL = (SELECT RESULT FROM DATE2STR(:V$DATE));
  SUSPEND;

  SELECT FIRST 1 PA.LOCAL_ID
  FROM UT_EXAM_PERSON_ASSN PA
  WHERE PA.DATE_DEL IS NULL AND PA.EXAM_ID = :I$EXAM_ID AND PA.PERSON_ID = :I$PERSON_ID
  INTO :V$LOCAL_ID;

  TAG_NAME = 'data:local_id';
  VAL = V$LOCAL_ID;
  SUSPEND;

  TAG_NAME = 'data:person_id';
  VAL = I$PERSON_ID;
  SUSPEND;

  SELECT NAME_FULL, CLASS_NAME, OU_NAME
  FROM UT_PERSON_DESC(:I$PERSON_ID)
  INTO :VAL, :V$CLASS_NAME, :V$OU_NAME;

  TAG_NAME = 'data:name_full';
  SUSPEND;

  TAG_NAME = 'data:class_name';
  VAL = V$CLASS_NAME;
  SUSPEND;

  TAG_NAME = 'data:ou_name';
  VAL = V$OU_NAME;
  SUSPEND;

  TAG_NAME = 'data:ppe_name';
  VAL = '-';
  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_QVECTOR (
    I$EXAM_ID BIGINT,
    I$INDEX INTEGER,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
declare variable V$VAR_ID bigint;
declare variable V$VAR_NUM integer;
declare variable V$TYPE smallint;
declare variable V$VQ_ID bigint;
declare variable V$Q_ID bigint;
declare variable V$N integer;
declare variable V$N_VALID integer;
declare variable V$S varchar(1000);
begin

  TAG_NAME = 'index';
  VAL = I$INDEX;
  SUSPEND;

  TAG_NAME = 'type';
  VAL = '2';
  SUSPEND;

  TAG_NAME = 'type_name';
  VAL = 'B';
  SUSPEND;

  TAG_NAME = 'variants';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'variants::json&colon;array';
  VAL = 1;
  SUSPEND;

  -- Разбиновка по вариантам
  FOR
      SELECT TV.NUM, TV.OBJ_ID, TVQ.OBJ_ID, TVQ.QUESTION_ID, TSP.Q_TYPE_ID
      FROM UT_EXAM_TEST_VARS ETV
      JOIN UT_TEST_VARS TV ON TV.OBJ_ID = ETV.TEST_VAR_ID
      JOIN UT_TESTS T ON T.OBJ_ID = TV.TEST_ID
      JOIN UT_TEST_VAR_QUESTIONS TVQ ON TVQ.VAR_ID = TV.OBJ_ID AND TVQ.DATE_DEL IS NULL AND TVQ.ORDER_INDEX = 1
      JOIN UT_TEST_STRUCT_POINTS TSP ON TSP.OBJ_ID = TVQ.STRUCT_POINT_ID AND TSP.Q_ORDER = :I$INDEX
      WHERE ETV.EXAM_ID = :I$EXAM_ID AND ETV.DATE_DEL IS NULL
      ORDER BY 1
      INTO :V$VAR_NUM, :V$VAR_ID, :V$VQ_ID, :V$Q_ID, :V$TYPE
  DO
  BEGIN

      TAG_NAME = 'variants:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'variants:r:id';
      VAL = V$VAR_ID;
      SUSPEND;
      TAG_NAME = 'variants:r:num';
      VAL = V$VAR_NUM;
      SUSPEND;
      TAG_NAME = 'variants:r:question_id';
      VAL = V$VQ_ID;
      SUSPEND;

      TAG_NAME = 'variants:r:keys';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'variants:r:keys::json&colon;array';
      VAL = NULL;
      SUSPEND;

      IF(V$TYPE = 1) THEN
      BEGIN
          -- Сначала выдаем введенные ключи и антиключи
          FOR
              SELECT A.A_LEVEL, A.SORT_ORDER
              FROM UT_ANSWERS A
              WHERE A.DATE_DEL IS NULL AND A.QUESTION_ID = :V$Q_ID
              ORDER BY 2
              INTO :V$N, :V$S
          DO
          BEGIN
              TAG_NAME = 'variants:r:keys:r';
              VAL = NULL;
              SUSPEND;
              TAG_NAME = 'variants:r:keys:r:value';
              VAL = V$S;
              SUSPEND;
              TAG_NAME = 'variants:r:keys:r:type';
              VAL = V$N; -- 1 = правильный, 0 = неправильный
              SUSPEND;

              -- Количество ответов с таким значением ключа, и сколько из них учтены
              TAG_NAME = 'variants:r:keys:r:answers';
              SELECT COUNT(*)
              FROM UT_SESSIONS S
              JOIN UT_SESSION_QUESTIONS SQ ON SQ.DATE_DEL IS NULL AND SQ.SESSION_ID = S.OBJ_ID AND SQ.QUESTION_ID = :V$VQ_ID AND SQ.ANSWER_DATA = :V$S
              WHERE S.DATE_DEL IS NULL AND S.ED_ID = :I$EXAM_ID
              INTO :VAL;
              SUSPEND;
          END

          -- Теперь значения, не попавшие в ключи
          FOR
              SELECT DISTINCT SQ.ANSWER_DATA, COUNT(*), SUM(IIF(SQ.RAW_RESULT > 0, 1, 0))
              FROM UT_SESSIONS S
              JOIN UT_SESSION_QUESTIONS SQ ON SQ.DATE_DEL IS NULL AND SQ.SESSION_ID = S.OBJ_ID AND SQ.QUESTION_ID = :V$VQ_ID AND CHAR_LENGTH(SQ.ANSWER_DATA) > 0
              LEFT JOIN UT_ANSWERS A ON A.DATE_DEL IS NULL AND A.QUESTION_ID = :V$Q_ID AND CAST(A.SORT_ORDER AS VARCHAR(10)) = SQ.ANSWER_DATA
              WHERE S.DATE_DEL IS NULL AND S.ED_ID = :I$EXAM_ID AND A.OBJ_ID IS NULL
              GROUP BY 1
              ORDER BY 1
              INTO :V$S, :V$N, :V$N_VALID
          DO
          BEGIN
              TAG_NAME = 'variants:r:keys:r';
              VAL = NULL;
              SUSPEND;
              TAG_NAME = 'variants:r:keys:r:value';
              VAL = V$S;
              SUSPEND;
              TAG_NAME = 'variants:r:keys:r:type';
              VAL = '';
              SUSPEND;

              -- Количество ответов с таким значением ключа
              TAG_NAME = 'variants:r:keys:r:answers';
              VAL = V$N;
              SUSPEND;
              TAG_NAME = 'variants:r:keys:r:as_good';
              VAL = V$N_VALID;
              SUSPEND;
          END
      END
      ELSE IF(V$TYPE = 2) THEN
      BEGIN
          FOR
              SELECT A.A_LEVEL, CAST(A.VARIANT AS VARCHAR(1000))
              FROM UT_ANSWERS A
              WHERE A.DATE_DEL IS NULL AND A.QUESTION_ID = :V$Q_ID
              ORDER BY A.SORT_ORDER
              INTO :V$N, :V$S
          DO
          BEGIN
              TAG_NAME = 'variants:r:keys:r';
              VAL = NULL;
              SUSPEND;
              TAG_NAME = 'variants:r:keys:r:value';
              VAL = V$S;
              SUSPEND;
              TAG_NAME = 'variants:r:keys:r:type';
              VAL = V$N; -- 1 = правильный, 0 = неправильный
              SUSPEND;

              -- Количество ответов с таким значением ключа
              TAG_NAME = 'variants:r:keys:r:answers';
              SELECT COUNT(*)
              FROM UT_SESSIONS S
              JOIN UT_SESSION_QUESTIONS SQ ON SQ.DATE_DEL IS NULL AND SQ.SESSION_ID = S.OBJ_ID AND SQ.QUESTION_ID = :V$VQ_ID AND SQ.ANSWER_DATA = :V$S
              WHERE S.DATE_DEL IS NULL AND S.ED_ID = :I$EXAM_ID
              INTO :VAL;
              SUSPEND;
          END

          -- Теперь значения, не попавшие в ключи
          FOR
              SELECT DISTINCT SQ.ANSWER_DATA, COUNT(*), SUM(IIF(SQ.RAW_RESULT > 0, 1, 0))
              FROM UT_SESSIONS S
              JOIN UT_SESSION_QUESTIONS SQ ON SQ.DATE_DEL IS NULL AND SQ.SESSION_ID = S.OBJ_ID AND SQ.QUESTION_ID = :V$VQ_ID AND CHAR_LENGTH(SQ.ANSWER_DATA) > 0
              LEFT JOIN UT_ANSWERS A ON A.DATE_DEL IS NULL AND A.QUESTION_ID = :V$Q_ID AND CAST(A.VARIANT AS VARCHAR(1000)) = SQ.ANSWER_DATA
              WHERE S.DATE_DEL IS NULL AND S.ED_ID = :I$EXAM_ID AND A.OBJ_ID IS NULL
              GROUP BY 1
              ORDER BY 1
              INTO :V$S, :V$N, :V$N_VALID
          DO
          BEGIN
              TAG_NAME = 'variants:r:keys:r';
              VAL = NULL;
              SUSPEND;
              TAG_NAME = 'variants:r:keys:r:value';
              VAL = V$S;
              SUSPEND;
              TAG_NAME = 'variants:r:keys:r:type';
              VAL = '';
              SUSPEND;

              -- Количество ответов с таким значением ключа
              TAG_NAME = 'variants:r:keys:r:answers';
              VAL = V$N;
              SUSPEND;
              TAG_NAME = 'variants:r:keys:r:as_good';
              VAL = V$N_VALID;
              SUSPEND;
          END
      END

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_RANDOM_RESULTS (
    I$EXAM_ID BIGINT)
AS
declare variable V$PERSON_ID bigint;
declare variable V$SESSION_ID bigint;
declare variable V$VARIANT_ID bigint;
declare variable V$REAL_VAR bigint;
declare variable V$SOURCE_ID bigint;
declare variable V$QUESTION_TYPE integer;
declare variable V$QUESTION_SCORE integer;
declare variable V$QUESTION_ID bigint;
declare variable V double precision;
begin

  FOR
      SELECT PA.PERSON_ID
      FROM UT_EXAM_PERSON_ASSN PA
      WHERE PA.EXAM_ID = :I$EXAM_ID AND PA.DATE_DEL IS NULL
      INTO :V$PERSON_ID
  DO
  BEGIN

      V$SESSION_ID = NULL;
      SELECT FIRST 1 S.OBJ_ID
      FROM UT_SESSIONS S
      WHERE S.ED_ID = :I$EXAM_ID AND S.PERSON_ID = :V$PERSON_ID
      INTO :V$SESSION_ID;

      IF(V$SESSION_ID IS NULL) THEN
      BEGIN

          V$VARIANT_ID = NULL;
          SELECT FIRST 1 TV.OBJ_ID, V.OBJ_ID
          FROM UT_EXAM_TEST_VARS TV
          JOIN UT_TEST_VARS V ON V.OBJ_ID = TV.TEST_VAR_ID AND V.DATE_DEL IS NULL
          JOIN UT_TESTS T ON T.OBJ_ID = V.TEST_ID
          WHERE TV.EXAM_ID = :I$EXAM_ID AND TV.DATE_DEL IS NULL
          ORDER BY RAND()
          INTO :V$VARIANT_ID, :V$REAL_VAR;

          IF(V$VARIANT_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не удалось подобрать вариант';

          -- Запись тестирования сразу в завершенном статусе
          INSERT INTO UT_SESSIONS
          (ED_ID, PERSON_ID, VARIANT_ID, STATE_ID)
          VALUES (:I$EXAM_ID, :V$PERSON_ID, :V$VARIANT_ID, 100)
          RETURNING OBJ_ID INTO :V$SESSION_ID;

          -- Вопросы
          FOR
              SELECT VQ.OBJ_ID, Q.QUESTION_TYPE, Q.MAX_SCORE
              FROM UT_TEST_VAR_QUESTIONS VQ
              JOIN UT_QUESTIONS Q ON Q.OBJ_ID = VQ.QUESTION_ID
              WHERE VQ.VAR_ID = :V$REAL_VAR AND VQ.DATE_DEL IS NULL
              INTO :V$SOURCE_ID, :V$QUESTION_TYPE, :V$QUESTION_SCORE
          DO
          BEGIN

              IF(V$QUESTION_SCORE = 1) THEN V = SQRT(SQRT(RAND() * V$QUESTION_SCORE)); ELSE V = RAND() * V$QUESTION_SCORE;
              IF(V - TRUNC(V) < 0.5) THEN V = TRUNC(V); ELSE V = TRUNC(V) + 1;

              INSERT INTO UT_SESSION_QUESTIONS
              (SESSION_ID, QUESTION_ID, RAW_RESULT, STATE_ID)
              VALUES (:V$SESSION_ID, :V$SOURCE_ID, :V, 1000)
              RETURNING OBJ_ID INTO :V$QUESTION_ID;

              /*INSERT INTO UT_SESSION_RESULTS
              (QUESTION_ID, LEVEL_ID, CRITERIA_ID, RAW_RESULT)
              VALUES (:V$QUESTION_ID, 0, 0, :V);*/

          END

          -- Итоги
          V = (SELECT SUM(RAW_RESULT) FROM UT_SESSION_QUESTIONS WHERE SESSION_ID = :V$SESSION_ID);

          UPDATE UT_SESSIONS
          SET RAW_RESULT = :V
          WHERE OBJ_ID = :V$SESSION_ID;

      END

  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_SCAN_GET (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
declare variable V$EXAM_ID bigint;
declare variable V$PACKET_ID bigint;
declare variable V$OBJ_ID bigint;
declare variable V$BLANK_TYPE bigint;
declare variable V$BLANK_SIDE smallint;
declare variable V$BC1 varchar(128);
declare variable V$BC2 varchar(128);
declare variable V$BC3 varchar(128);
declare variable V$NEXT_ID bigint;
declare variable V$FILE_ID varchar(40);
declare variable V$HASH varchar(40);
declare variable V$STATE integer;
declare variable V$PPE_NAME varchar(200);
begin
  TAG_NAME = 'barcode1';
  VAL = V$BC1;
  SUSPEND;
  SELECT P.ED_ID, P.OBJ_ID, B.OBJ_ID, B.BLANK_TYPE, B.BLANK_SIDE, B.BARCODE_DATA, B.BARCODE2_DATA, B.BARCODE3_DATA, B.NEXT_BLANK_ID, B.FILE_ID, B.FILE_HASH, B.STATE_ID, D.NAME_SHORT
  FROM UT_BLANKS B
  JOIN UT_PACKAGES P ON P.OBJ_ID = B.PACKAGE_ID
  LEFT JOIN UT_OU_DESC(P.PPE_ID) D ON 1 = 1
  WHERE B.OBJ_ID = :I$OBJ_ID AND B.DATE_DEL IS NULL
  INTO :V$EXAM_ID, :V$PACKET_ID, :V$OBJ_ID, :V$BLANK_TYPE, :V$BLANK_SIDE, :V$BC1, :V$BC2, :V$BC3, :V$NEXT_ID, :V$FILE_ID, :V$HASH, :V$STATE, :V$PPE_NAME;

  IF(V$OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Бланк не найден или был удален';

  TAG_NAME = 'exam_id';
  VAL = V$EXAM_ID;
  SUSPEND;

  TAG_NAME = 'packet_id';
  VAL = V$PACKET_ID;
  SUSPEND;

  TAG_NAME = 'id';
  VAL = V$OBJ_ID;
  SUSPEND;

  TAG_NAME = 'blank_type';
  VAL = V$BLANK_TYPE;
  SUSPEND;

  TAG_NAME = 'blank_type_name';
  VAL = (SELECT OBJ_NAME FROM UT_PAGE_TEMPLATES WHERE OBJ_ID = :V$BLANK_TYPE);
  SUSPEND;

  TAG_NAME = 'blank_side';
  VAL = V$BLANK_SIDE;
  SUSPEND;

  TAG_NAME = 'ppe_name';
  VAL = V$PPE_NAME;
  SUSPEND;

  TAG_NAME = 'barcode1';
  VAL = V$BC1;
  SUSPEND;

  TAG_NAME = 'barcode2';
  VAL = V$BC2;
  SUSPEND;

  TAG_NAME = 'barcode3';
  VAL = V$BC3;
  SUSPEND;

  TAG_NAME = 'next_id';
  VAL = V$NEXT_ID;
  SUSPEND;

  TAG_NAME = 'prev_id';
  VAL = (SELECT OBJ_ID FROM UT_BLANKS WHERE DATE_DEL IS NULL AND NEXT_BLANK_ID = :I$OBJ_ID);
  SUSPEND;

  TAG_NAME = 'file_id';
  VAL = V$FILE_ID;
  SUSPEND;

  TAG_NAME = 'file_hash';
  VAL = V$HASH;
  SUSPEND;

  TAG_NAME = 'state_id';
  VAL = V$STATE;
  SUSPEND;

  TAG_NAME = 'state_name';
  IF(V$STATE = 0) THEN VAL = 'Черновик';
  ELSE IF(V$STATE = 1) then VAL = 'Загружен';
  ELSE IF(V$STATE = 2) then VAL = 'Отмасштабирован';
  ELSE IF(V$STATE = 3) then VAL = 'Штрихкоды прочитаны';
  ELSE IF(V$STATE = 9) then VAL = 'Готов к распознаванию';
  ELSE IF(V$STATE = 10) then VAL = 'Распознается';
  ELSE IF(V$STATE = 11) then VAL = 'Распознавание завершено';
  ELSE IF(V$STATE = 12) then VAL = 'На верификации';
  ELSE IF(V$STATE = 13) then VAL = 'Верифицирован';
  ELSE IF(V$STATE = 14) then VAL = 'Обработка завершена';
  ELSE IF(V$STATE = 15) then VAL = 'Отменен';
  ELSE IF(V$STATE = 16) then VAL = 'Чистый';
  ELSE IF(V$STATE = 17) then VAL = 'Аннулирован';
  ELSE VAL = 'Иной статус (' || V$STATE || ')';
  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_SESSION_RV_GET (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(4000))
AS
declare variable V$PERSON_ID bigint;
declare variable V$TIME1 timestamp;
declare variable V$TIME2 timestamp;
declare variable V$STATE_ID integer;
declare variable V$STATE_NAME varchar(100);
declare variable V$VARIANT_ID bigint;
declare variable V$VARIANT_NAME varchar(100);
declare variable V$VARIANT_NUM smallint;
declare variable V$DURATION integer;
declare variable V$NAME_LAST varchar(200);
declare variable V$NAME_FIRST varchar(200);
declare variable V$NAME_MID varchar(200);
declare variable V$BIRTH_DATE date;
declare variable V$OU_ID bigint;
declare variable V$OU_NAME varchar(400);
declare variable V$AREA_ID bigint;
declare variable V$AREA_NAME varchar(200);
declare variable V$STAGE_ID bigint;
declare variable V$STAGE_NAME varchar(100);
declare variable V$CLASS_ID bigint;
declare variable V$CLASS_NAME varchar(100);
declare variable V$QUESTION_ID bigint;
declare variable V$INNER_ID bigint;
declare variable V$QUESTION_ORDER integer;
declare variable V$RAW_RESULT varchar(200);
declare variable V$RESULT1 varchar(200);
declare variable V$RESULT2 varchar(200);
declare variable V$QUESTION_TYPE smallint;
declare variable V$QUESTION_TYPE_NAME varchar(10);
declare variable V$MAX_SCORE smallint;
declare variable V$EXPERT_ID bigint;
declare variable N integer;
declare variable GN integer;
begin

  SELECT S.PERSON_ID, S.STARTED_AT, S.COMPLETED_AT, S.STATE_ID, SS.STATE_NAME, TV.OBJ_ID, TV.OBJ_NAME, TV.NUM, S.DURATION, S.RAW_RESULT, MT.MARK_TYPE_ID, MT.MARK_NAME
  FROM UT_SESSIONS S
  JOIN UT_SESSION_STATES SS ON SS.STATE_ID = S.STATE_ID
  JOIN UT_EXAM_TEST_VARS ETV ON ETV.OBJ_ID = S.VARIANT_ID
  JOIN UT_TEST_VARS TV ON TV.OBJ_ID = ETV.TEST_VAR_ID
  LEFT JOIN CJ2_MARK_TYPE MT ON MT.MARK_TYPE_ID = S.FINAL_RESULT_ID
  WHERE S.OBJ_ID = :I$OBJ_ID AND S.DATE_DEL IS NULL
  INTO :V$PERSON_ID, :V$TIME1, :V$TIME2, :V$STATE_ID, :V$STATE_NAME, :V$VARIANT_ID, :V$VARIANT_NAME, :V$VARIANT_NUM, :V$DURATION, :V$RAW_RESULT, :V$AREA_ID, :V$AREA_NAME;

  IF(V$PERSON_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Данные не найдены или были удалены';

  TAG_NAME = 'id';
  VAL = I$OBJ_ID;
  SUSPEND;

  TAG_NAME = 'started_at';
  VAL = (SELECT VAL FROM DATE2ISO(:V$TIME1));
  SUSPEND;

  TAG_NAME = 'completed_at';
  VAL = (SELECT VAL FROM DATE2ISO(:V$TIME2));
  SUSPEND;

  TAG_NAME = 'duration';
  VAL = V$DURATION;
  SUSPEND;

  TAG_NAME = 'state_id';
  VAL = V$STATE_ID;
  SUSPEND;

  TAG_NAME = 'state_name';
  VAL = V$STATE_NAME;
  SUSPEND;

  TAG_NAME = 'variant_id';
  VAL = V$VARIANT_ID;
  SUSPEND;

  TAG_NAME = 'variant_name';
  VAL = V$VARIANT_NAME;
  SUSPEND;

  TAG_NAME = 'variant_num';
  VAL = V$VARIANT_NUM;
  SUSPEND;

  TAG_NAME = 'raw_result';
  VAL = V$RAW_RESULT;
  SUSPEND;

  TAG_NAME = 'mark_id';
  VAL = V$AREA_ID;
  SUSPEND;

  TAG_NAME = 'mark_name';
  VAL = V$AREA_NAME;
  SUSPEND;

  SELECT NAME_LAST, NAME_FIRST, NAME_MID, BIRTH_DATE, OU_ID, OU_NAME, AREA_ID, AREA_NAME, STAGE_ID, STAGE_NAME, CLASS_ID, CLASS_NAME
  FROM UT_PERSON_DESC(:V$PERSON_ID)
  INTO :V$NAME_LAST, :V$NAME_FIRST, :V$NAME_MID, :V$BIRTH_DATE, :V$OU_ID, :V$OU_NAME, :V$AREA_ID, :V$AREA_NAME, :V$STAGE_ID, :V$STAGE_NAME, :V$CLASS_ID, :V$CLASS_NAME;

  TAG_NAME = 'person_id';
  VAL = V$PERSON_ID;
  SUSPEND;

  TAG_NAME = 'name_last';
  VAL = V$NAME_LAST;
  SUSPEND;

  TAG_NAME = 'name_first';
  VAL = V$NAME_FIRST;
  SUSPEND;

  TAG_NAME = 'name_mid';
  VAL = V$NAME_MID;
  SUSPEND;

  TAG_NAME = 'birth_date';
  VAL = V$BIRTH_DATE;
  SUSPEND;

  TAG_NAME = 'ou_id';
  VAL = V$OU_ID;
  SUSPEND;

  TAG_NAME = 'ou_name';
  VAL = V$OU_NAME;
  SUSPEND;

  TAG_NAME = 'area_id';
  VAL = V$AREA_ID;
  SUSPEND;

  TAG_NAME = 'area_name';
  VAL = V$AREA_NAME;
  SUSPEND;

  TAG_NAME = 'stage_id';
  VAL = V$STAGE_ID;
  SUSPEND;

  TAG_NAME = 'stage_name';
  VAL = V$STAGE_NAME;
  SUSPEND;

  TAG_NAME = 'class_id';
  VAL = V$CLASS_ID;
  SUSPEND;

  TAG_NAME = 'class_name';
  VAL = V$CLASS_NAME;
  SUSPEND;

  -- Вопросы
  TAG_NAME = 'questions';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'questions::json&colon;array';
  VAL = '1';
  SUSPEND;

  FOR
      SELECT SQ.OBJ_ID, Q.OBJ_ID, TSP.Q_ORDER, SQ.RAW_RESULT, QT.OBJ_ID, QT.OBJ_VALUE, TSP.Q_MAX_SCORE, SA.OBJ_ID, SA.OBJ_NAME
      FROM UT_SESSION_QUESTIONS SQ
      JOIN UT_TEST_VAR_QUESTIONS TVQ ON TVQ.OBJ_ID = SQ.QUESTION_ID
      JOIN UT_QUESTIONS Q ON Q.OBJ_ID = TVQ.QUESTION_ID
      JOIN UT_TEST_STRUCT_POINTS TSP ON TSP.OBJ_ID = TVQ.STRUCT_POINT_ID
      JOIN UT_QUESTION_TYPE QT ON QT.OBJ_ID = TSP.Q_TYPE_ID
      JOIN UT_ANSWER_STATES SA ON SA.OBJ_ID = SQ.STATE_ID
      WHERE SQ.DATE_DEL IS NULL AND SQ.SESSION_ID = :I$OBJ_ID
      ORDER BY TSP.Q_ORDER
      INTO :V$QUESTION_ID, :V$INNER_ID, :V$QUESTION_ORDER, :V$RAW_RESULT, :V$QUESTION_TYPE, :V$QUESTION_TYPE_NAME, :V$MAX_SCORE, :V$CLASS_ID, :V$CLASS_NAME
  DO
  BEGIN

      TAG_NAME = 'questions:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'questions:r:id';
      VAL = V$QUESTION_ID;
      SUSPEND;
      TAG_NAME = 'questions:r:state_id';
      VAL = V$CLASS_ID;
      SUSPEND;
      TAG_NAME = 'questions:r:state_name';
      VAL = V$CLASS_NAME;
      SUSPEND;
      TAG_NAME = 'questions:r:num';
      VAL = V$QUESTION_ORDER;
      SUSPEND;
      TAG_NAME = 'questions:r:type';
      VAL = V$QUESTION_TYPE;
      SUSPEND;
      TAG_NAME = 'questions:r:type_name';
      VAL = V$QUESTION_TYPE_NAME;
      SUSPEND;
      TAG_NAME = 'questions:r:max_score';
      VAL = V$MAX_SCORE;
      SUSPEND;
      TAG_NAME = 'questions:r:raw_result';
      VAL = V$RAW_RESULT;
      SUSPEND;

      -- По тексту ответов типа C и аудиотестированию, отдаем данные по критериям
      IF(V$QUESTION_TYPE IN (3, 8)) THEN
      BEGIN
          TAG_NAME = 'questions:r:criteria';
          VAL = NULL;
          SUSPEND;
          TAG_NAME = 'questions:r:criteria::json&colon;array';
          VAL = NULL;
          SUSPEND;

          FOR
              SELECT A.SORT_ORDER, A.A_LEVEL, A.OBJ_NAME
              FROM UT_ANSWERS A
              WHERE A.QUESTION_ID = :V$INNER_ID AND A.DATE_DEL IS NULL
              ORDER BY 1
              INTO :V$QUESTION_ORDER, :V$MAX_SCORE, :V$OU_NAME
          DO
          BEGIN
              TAG_NAME = 'questions:r:criteria:r';
              VAL = NULL;
              SUSPEND;
              TAG_NAME = 'questions:r:criteria:r:index';
              VAL = V$QUESTION_ORDER;
              SUSPEND;
              TAG_NAME = 'questions:r:criteria:r:max_score';
              VAL = V$MAX_SCORE;
              SUSPEND;
              TAG_NAME = 'questions:r:criteria:r:name';
              VAL = V$OU_NAME;
              SUSPEND;

              TAG_NAME = 'questions:r:criteria:r:marks';
              VAL = NULL;
              SUSPEND;
              TAG_NAME = 'questions:r:criteria:r:marks::json&colon;array';
              VAL = NULL;
              SUSPEND;

              -- Первичная проверка экспертами, итоговая отметка по первой проверке
              GN = 1;
              FOR
                  -- Проверки
                  SELECT C.EXPERT_ID, C.LEVEL_ID, CR.RAW_RESULT
                  FROM UT_SESSION_CHECKS C
                  JOIN UT_SESSION_CHECK_RES CR ON CR.CHECK_ID = C.OBJ_ID AND CR.DATE_DEL IS NULL AND CR.CRITERIA_ID = :V$QUESTION_ORDER
                  WHERE C.DATE_DEL IS NULL AND C.QUESTION_ID = :V$QUESTION_ID AND C.EXPERT_ID IS NOT NULL
                  -- Общий итог
                  UNION
                  SELECT C.EXPERT_ID, 10, CR.RAW_RESULT
                  FROM UT_SESSION_CHECKS C
                  JOIN UT_SESSION_CHECK_RES CR ON CR.CHECK_ID = C.OBJ_ID AND CR.DATE_DEL IS NULL AND CR.CRITERIA_ID = :V$QUESTION_ORDER
                  WHERE C.DATE_DEL IS NULL AND C.QUESTION_ID = :V$QUESTION_ID AND C.EXPERT_ID IS NULL
                  ORDER BY 2, 1
                  INTO :V$EXPERT_ID, :N, :V$RAW_RESULT
              DO
              BEGIN
                  TAG_NAME = 'questions:r:criteria:r:marks:r';
                  VAL = NULL;
                  SUSPEND;
                  TAG_NAME = 'questions:r:criteria:r:marks:r:level';
                  VAL = N;
                  SUSPEND;
                  TAG_NAME = 'questions:r:criteria:r:marks:r:index';
                  VAL = IIF(N = 1, GN, 0); -- номер проверки в пределах первой проверки
                  SUSPEND;
                  TAG_NAME = 'questions:r:criteria:r:marks:r:value';
                  VAL = V$RAW_RESULT;
                  SUSPEND;
                  GN = GN + 1;
              END
          END

      END

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_SESSION_TOTAL_RECALC (
    I$SESSION_ID BIGINT,
    I$STATE_ID INTEGER,
    I$RAW_SUM INTEGER,
    I$UPDATE SMALLINT = 1)
RETURNS (
    RAW_RESULT INTEGER)
AS
DECLARE VARIABLE V$BLANK_ID BIGINT;
DECLARE VARIABLE V$NMIN INTEGER;
DECLARE VARIABLE V$N0 INTEGER;
DECLARE VARIABLE V$N4 INTEGER;
DECLARE VARIABLE V$N5 INTEGER;
DECLARE VARIABLE V$NMAX INTEGER;
DECLARE VARIABLE V$MARK INTEGER;
DECLARE VARIABLE V$FINAL_ID BIGINT;
DECLARE VARIABLE B BIGINT;
begin

  -- Пересчет общих итогов по работе. Данные берутся из ранее обсчитанных итогов по каждому вопросу
  IF(I$RAW_SUM IS NULL) THEN
  BEGIN
    SELECT SUM(RAW_RESULT)
    FROM UT_SESSION_QUESTIONS SQ
    WHERE SQ.SESSION_ID = :I$SESSION_ID AND SQ.DATE_DEL IS NULL
    INTO :RAW_RESULT;

    IF(RAW_RESULT IS NULL) THEN RAW_RESULT = 0;
  END
  ELSE RAW_RESULT = I$RAW_SUM;

  -- Меняем или не меняем статус
  IF(I$UPDATE <> 0) THEN
  BEGIN
    IF(I$STATE_ID IS NULL) THEN
    BEGIN
      UPDATE UT_SESSIONS
      SET RAW_RESULT = :RAW_RESULT
      WHERE OBJ_ID = :I$SESSION_ID;
    END
    ELSE
    BEGIN
      -- Если в тестировании уже задана шкала, выставляем отметку
      SELECT D.SCALE_NMIN, D.SCALE_N0, D.SCALE_N4, D.SCALE_N5, D.SCALE_NMAX
      FROM UT_SESSIONS S
      JOIN UT_EXAM_DATES D ON D.OBJ_ID = S.ED_ID
      WHERE S.OBJ_ID = :I$SESSION_ID
      INTO :V$NMIN, :V$N0, :V$N4, :V$N5, :V$NMAX;

      IF(V$N0 IS NOT NULL AND V$N4 IS NOT NULL AND V$N5 IS NOT NULL) THEN
      BEGIN
        IF(RAW_RESULT < V$N0) THEN V$MARK = 2;
        ELSE IF(RAW_RESULT < V$N4) THEN V$MARK = 3;
        ELSE IF(RAW_RESULT < V$N5) THEN V$MARK = 4;
        ELSE V$MARK = 5;

        SELECT FIRST 1 M.MARK_TYPE_ID
        FROM CJ2_MARK_TYPE M
        WHERE M.IS_DEL = 0 AND M.MARK_COST = :V$MARK AND M.PARENT_ID IS NULL AND M.PARENT_ID = 400 -- пока только 5-балльная шкала
        INTO :V$FINAL_ID;
      END

      UPDATE UT_SESSIONS
      SET RAW_RESULT = :RAW_RESULT, STATE_ID = :I$STATE_ID, FINAL_RESULT_ID = COALESCE(:V$FINAL_ID, FINAL_RESULT_ID)
      WHERE OBJ_ID = :I$SESSION_ID AND STATE_ID <= :I$STATE_ID;

      -- Закрываем обработку всех бланков типа C и дополнительных. Сессия сохранена только в первом бланке типа C
      SELECT FIRST 1 B.OBJ_ID
      FROM UT_BLANKS B
      JOIN UT_PAGE_TEMPLATES PT ON PT.OBJ_ID = B.BLANK_TYPE AND PT.BLANK_TYPE = 2
      WHERE B.DATE_DEL IS NULL AND B.SESSION_ID = :I$SESSION_ID
      INTO :V$BLANK_ID;

      WHILE(V$BLANK_ID IS NOT NULL) DO
      BEGIN
        UPDATE UT_BLANKS
        SET STATE_ID = 14
        WHERE OBJ_ID = :V$BLANK_ID AND STATE_ID = 13;

        B = V$BLANK_ID;
        V$BLANK_ID = NULL;
        SELECT B1.NEXT_BLANK_ID
        FROM UT_BLANKS B1
        WHERE B1.OBJ_ID = :B
        INTO :V$BLANK_ID;
      END
    END
  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_STRUCTS_GET (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(8000))
AS
declare variable V$OBJ_ID bigint;
declare variable V$SUBJECT_ID bigint;
declare variable V$STAGE_ID bigint;
declare variable V$METHOD_ID bigint;
declare variable V$OBJ_NAME varchar(8000);
declare variable V$ORDER integer;
declare variable V$TYPE integer;
declare variable V$SCORE integer;
declare variable V$OBJ_VALUE varchar(10);
declare variable V$LEVEL smallint;
declare variable V$CHARSET smallint;
declare variable V$L float;
declare variable V$H float;
BEGIN

  SELECT OBJ_ID, SUBJECT_ID, STAGE_ID, METHOD_ID, OBJ_NAME
  FROM UT_TEST_STRUCTS
  WHERE OBJ_ID = :I$OBJ_ID AND DATE_DEL IS NULL
  INTO :V$OBJ_ID, :V$SUBJECT_ID, :V$STAGE_ID, :V$METHOD_ID, :V$OBJ_NAME;

  IF(I$OBJ_ID IS NOT NULL AND V$OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Объект не найден или был удален';

  TAG_NAME = 'id';
  VAL = I$OBJ_ID;
  SUSPEND;

  TAG_NAME = 'obj_name';
  VAL = V$OBJ_NAME;
  SUSPEND;

  TAG_NAME = 'subject_id:selection';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'subject_id:selection::json&colon;array';
  VAL = '1';
  SUSPEND;
  TAG_NAME = 'subject_id:selection:option';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'subject_id:selection:option:id';
  VAL = '*';
  SUSPEND;
  TAG_NAME = 'subject_id:selection:option:value';
  VAL = 'Метапредмет';
  SUSPEND;
  FOR
    SELECT OBJ_ID, OBJ_NAME
    FROM UT_SUBJECTS
    ORDER BY 2
    INTO :V$OBJ_ID, :V$OBJ_NAME
  DO
  BEGIN
    TAG_NAME = 'subject_id:selection:option';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'subject_id:selection:option:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'subject_id:selection:option:value';
    VAL = V$OBJ_NAME;
    SUSPEND;
  END
  TAG_NAME = 'subject_id:values:value';
  VAL = V$SUBJECT_ID;
  SUSPEND;

  TAG_NAME = 'stage_id:selection';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'stage_id:selection::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
    SELECT OBJ_ID, OBJ_NAME
    FROM UT_EXAM_STAGES
    INTO :V$OBJ_ID, :V$OBJ_NAME
  DO
  BEGIN
    TAG_NAME = 'stage_id:selection:option';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'stage_id:selection:option:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'stage_id:selection:option:value';
    VAL = V$OBJ_NAME;
    SUSPEND;
  END
  TAG_NAME = 'stage_id:values:value';
  VAL = V$STAGE_ID;
  SUSPEND;

  TAG_NAME = 'method_id:selection';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'method_id:selection::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
    SELECT OBJ_ID, OBJ_NAME
    FROM UT_EXAM_METHODS
    WHERE OBJ_ID <> 4 -- кроме олимпиад
    INTO :V$OBJ_ID, :V$OBJ_NAME
  DO
  BEGIN
    TAG_NAME = 'method_id:selection:option';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'method_id:selection:option:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'method_id:selection:option:value';
    VAL = V$OBJ_NAME;
    SUSPEND;
  END
  TAG_NAME = 'method_id:values:value';
  VAL = V$METHOD_ID;
  SUSPEND;

  -- Флаг IS_USED указывает наличие действующих тестирований, где используется эта структура
  TAG_NAME = 'is_used';
  VAL = 0;
  SELECT FIRST 1 1
  FROM UT_TESTS T
  JOIN UT_TEST_VARS TV ON TV.TEST_ID = T.OBJ_ID AND TV.DATE_DEL IS NULL
  JOIN UT_EXAM_TEST_VARS ETV ON ETV.TEST_VAR_ID = TV.OBJ_ID AND ETV.DATE_DEL IS NULL
  JOIN UT_EXAM_DATES D ON D.OBJ_ID = ETV.EXAM_ID AND D.DATE_DEL IS NULL AND (D.EXAM_STATE >= 0 AND D.EXAM_STATE < 1000)
  WHERE T.STRUCT_ID = :I$OBJ_ID AND T.DATE_DEL IS NULL
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'points';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'points::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
    SELECT P.OBJ_ID, P.Q_ORDER, P.Q_TYPE_ID, P.Q_MAX_SCORE, P.CHARSET_ID, P.Q_LEVEL, P.TEXT_NOTES, P.WND_MIN, P.WND_MAX
    FROM UT_TEST_STRUCT_POINTS P
    WHERE P.STRUCT_ID = :I$OBJ_ID AND P.DATE_DEL IS NULL
    ORDER BY P.Q_ORDER
    INTO :V$OBJ_ID, :V$ORDER, :V$TYPE, :V$SCORE, :V$CHARSET, :V$LEVEL, :V$OBJ_NAME, :V$L, :V$H
  DO
  BEGIN
    TAG_NAME = 'points:p';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'points:p:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'points:p:index';
    VAL = V$ORDER;
    SUSPEND;
    TAG_NAME = 'points:p:question_type';
    VAL = V$TYPE;
    SUSPEND;
    TAG_NAME = 'points:p:max_score';
    VAL = V$SCORE;
    SUSPEND;
    TAG_NAME = 'points:p:level';
    VAL = V$LEVEL;
    SUSPEND;
    TAG_NAME = 'points:p:charset';
    VAL = V$CHARSET;
    SUSPEND;
    TAG_NAME = 'points:p:text_notes';
    VAL = V$OBJ_NAME;
    SUSPEND;
    TAG_NAME = 'points:p:wnd_min';
    VAL = CAST(V$L AS NUMERIC(18, 1));
    SUSPEND;
    TAG_NAME = 'points:p:wnd_max';
    VAL = CAST(V$H AS NUMERIC(18, 1));
    SUSPEND;
  END

  -- Типы вопросов
  TAG_NAME = 'question_types';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'question_types::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
    SELECT OBJ_ID, OBJ_NAME, OBJ_VALUE, IS_HANDCHECKED
    FROM UT_QUESTION_TYPE
    WHERE IS_DEL = 0
    ORDER BY OBJ_ID
    INTO :V$OBJ_ID, :V$OBJ_NAME, :V$OBJ_VALUE, :V$SCORE
  DO
  BEGIN
    TAG_NAME = 'question_types:t';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'question_types:t:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'question_types:t:name';
    VAL = V$OBJ_NAME;
    SUSPEND;
    TAG_NAME = 'question_types:t:value';
    VAL = V$OBJ_VALUE;
    SUSPEND;
    TAG_NAME = 'question_types:t:is_handchecked';
    VAL = V$SCORE;
    SUSPEND;
  END

  -- Кодировки
  TAG_NAME = 'charsets';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'charsets::json&colon;array';
  VAL = '1';
  SUSPEND;
  FOR
    SELECT OBJ_ID, OBJ_NAME
    FROM UT_CHARSETS
    WHERE IS_DEL = 0
    ORDER BY OBJ_ID
    INTO :V$OBJ_ID, :V$OBJ_NAME
  DO
  BEGIN
    TAG_NAME = 'charsets:t';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'charsets:t:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'charsets:t:name';
    VAL = V$OBJ_NAME;
    SUSPEND;
  END

END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_STRUCTS_LIST (
    I$SUBJECT_ID BIGINT,
    I$STAGE_ID INTEGER,
    I$METHOD_ID INTEGER)
RETURNS (
    OBJ_ID BIGINT,
    OBJ_NAME VARCHAR(1000))
AS
begin

  FOR
      SELECT S.OBJ_ID, S.OBJ_NAME
      FROM UT_TEST_STRUCTS S
      WHERE S.DATE_DEL IS NULL AND (S.SUBJECT_ID = :I$SUBJECT_ID OR (:I$SUBJECT_ID IS NULL AND S.SUBJECT_ID IS NULL)) AND
          S.STAGE_ID = :I$STAGE_ID AND S.METHOD_ID = :I$METHOD_ID AND S.IS_AUTO = 0
      ORDER BY 2
      INTO :OBJ_ID, :OBJ_NAME
  DO
  BEGIN
      SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_STRUCTS_SET (
    I$OBJ_ID BIGINT,
    I$SUBJECT_ID BIGINT,
    I$STAGE_ID INTEGER,
    I$METHOD_ID INTEGER,
    I$OBJ_NAME VARCHAR(100),
    I$IS_AUTO SMALLINT,
    I$TEXT_NOTES BLOB SUB_TYPE 1 SEGMENT SIZE 80 = null,
    I$NOTES_DELETE SMALLINT = 0)
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$SUBJECT_ID bigint;
declare variable V$METHOD_ID integer;
declare variable V$STAGE_ID integer;
BEGIN

  -- Проверяем, что это реальный предмет
  IF(I$SUBJECT_ID IS NOT NULL AND NOT EXISTS(
      SELECT FIRST 1 1
      FROM UT_SUBJECTS
      WHERE OBJ_ID = :I$SUBJECT_ID
  ))
  THEN EXCEPTION DATA_ERROR 'Ссылка на несуществующий предмет';

  IF(I$IS_AUTO = 0) THEN
  BEGIN

      IF(EXISTS(
          SELECT FIRST 1 1
          FROM UT_TEST_STRUCTS
          WHERE DATE_DEL IS NULL AND IS_AUTO = 0 AND OBJ_NAME = :I$OBJ_NAME AND (OBJ_ID <> :I$OBJ_ID OR :I$OBJ_ID IS NULL)
      ))
      THEN EXCEPTION DATA_ERROR 'Структура с таким названием уже есть';

  END

  IF (I$OBJ_ID IS NULL) THEN
  BEGIN

      INSERT INTO UT_TEST_STRUCTS
      (SUBJECT_ID, STAGE_ID, METHOD_ID, OBJ_NAME, IS_AUTO)
      VALUES (:I$SUBJECT_ID, :I$STAGE_ID, :I$METHOD_ID, :I$OBJ_NAME, :I$IS_AUTO)
      RETURNING OBJ_ID INTO OBJ_ID;

  END
  ELSE
  BEGIN

      -- Нельзя менять метод, предмет и этап, когда есть открытые тестирования с этой структурой
      SELECT S.SUBJECT_ID, S.METHOD_ID, S.STAGE_ID
      FROM UT_TEST_STRUCTS S
      WHERE S.OBJ_ID = :I$OBJ_ID AND S.DATE_DEL IS NULL
      INTO :V$SUBJECT_ID, :V$METHOD_ID, :V$STAGE_ID;

      IF(V$STAGE_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Структура не найдена или была удалена другим пользователем';

      IF(EXISTS(
          SELECT FIRST 1 1
          FROM UT_TESTS T
          JOIN UT_TEST_VARS TV ON TV.TEST_ID = T.OBJ_ID AND TV.DATE_DEL IS NULL
          JOIN UT_EXAM_TEST_VARS ETV ON ETV.TEST_VAR_ID = TV.OBJ_ID AND ETV.DATE_DEL IS NULL
          JOIN UT_EXAM_DATES D ON D.OBJ_ID = ETV.EXAM_ID AND D.DATE_DEL IS NULL AND (D.EXAM_STATE >= 0 AND D.EXAM_STATE < 1000)
          WHERE T.STRUCT_ID = :I$OBJ_ID AND T.DATE_DEL IS NULL
      )) THEN
      BEGIN
          -- При проверке исключаем случай обновления NOTES
          IF(I$STAGE_ID IS NOT NULL AND (V$STAGE_ID <> I$STAGE_ID OR V$METHOD_ID <> I$METHOD_ID OR
              (V$SUBJECT_ID <> I$SUBJECT_ID OR (V$SUBJECT_ID IS NULL AND I$SUBJECT_ID IS NOT NULL) OR (V$SUBJECT_ID IS NOT NULL AND I$SUBJECT_ID IS NULL))
          ))
          THEN EXCEPTION DATA_ERROR 'Структура использована в действующем тестировании. Предмет, метод проведения и контингент менять нельзя';
      END

      -- IS_AUTO тут не меняется никогда

      IF(I$SUBJECT_ID IS NULL AND I$STAGE_ID IS NULL AND I$METHOD_ID IS NULL) THEN
      BEGIN
          -- Сохранение только TEXT_NOTES (проверка на IS_AUTO)
          UPDATE UT_TEST_STRUCTS
          SET TEXT_NOTES = :I$TEXT_NOTES
          WHERE OBJ_ID = :I$OBJ_ID AND IS_AUTO = 1;
      END
      ELSE
      BEGIN
          -- Нормальное обновление
          UPDATE UT_TEST_STRUCTS
          SET SUBJECT_ID = :I$SUBJECT_ID, STAGE_ID = :I$STAGE_ID, METHOD_ID = :I$METHOD_ID, OBJ_NAME = :I$OBJ_NAME
          WHERE OBJ_ID = :I$OBJ_ID;
      END

      OBJ_ID = :I$OBJ_ID;

  END

  -- Добавляем бинарные данные, если они не NULL
  IF(I$TEXT_NOTES IS NOT NULL) THEN
  BEGIN
      UPDATE UT_TEST_STRUCTS
      SET TEXT_NOTES = :I$TEXT_NOTES
      WHERE OBJ_ID = :OBJ_ID;
  END
  ELSE IF(I$NOTES_DELETE <> 0) THEN
  BEGIN
      UPDATE UT_TEST_STRUCTS
      SET TEXT_NOTES = NULL
      WHERE OBJ_ID = :OBJ_ID AND TEXT_NOTES IS NOT NULL;
  END

  SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_STRUCT_DELETE (
    I$OBJ_ID BIGINT)
RETURNS (
    ERROR_TEXT VARCHAR(10))
AS
declare variable S varchar(1000);
begin

  -- Проверяем, что структура не задействована в вариантах
  SELECT FIRST 1 T.OBJ_NAME
  FROM UT_TESTS T
  WHERE T.STRUCT_ID = :I$OBJ_ID AND T.DATE_DEL IS NULL
  INTO :S;
  IF(S IS NOT NULL) THEN EXCEPTION DATA_ERROR 'Структура задействована в вариантах тестов, см. ' || S;

  UPDATE UT_TEST_STRUCTS
  SET DATE_DEL = CURRENT_TIMESTAMP
  WHERE OBJ_ID = :I$OBJ_ID AND DATE_DEL IS NULL;

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_STRUCT_POINTS_DELETE (
    I$OBJ_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable S varchar(1000);
BEGIN

  -- Задействована ли данная позиция структуры ?

  SELECT FIRST 1 T.OBJ_NAME
  FROM UT_TEST_VAR_QUESTIONS VQ
  JOIN UT_TEST_VARS V ON V.OBJ_ID = VQ.VAR_ID AND V.DATE_DEL IS NULL
  JOIN UT_TESTS T ON T.OBJ_ID = V.TEST_ID AND T.DATE_DEL IS NULL
  WHERE VQ.DATE_DEL IS NULL AND VQ.STRUCT_POINT_ID = :I$OBJ_ID
  INTO :S;

  IF(S IS NOT NULL) THEN EXCEPTION DATA_ERROR 'Позиция структуры уже задействована в одном из вариантов, см. ' || S;

  UPDATE UT_TEST_STRUCT_POINTS
  SET DATE_DEL = CURRENT_TIMESTAMP
  WHERE OBJ_ID = :I$OBJ_ID AND DATE_DEL IS NULL;

  SUSPEND;

END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_STRUCT_POINTS_GET (
    I$STRUCT_ID BIGINT = null)
RETURNS (
    OBJ_ID BIGINT,
    STRUCT_ID BIGINT,
    Q_TYPE_ID SMALLINT,
    Q_ORDER INTEGER,
    Q_MAX_SCORE SMALLINT)
AS
BEGIN
  FOR
      SELECT OBJ_ID, STRUCT_ID, Q_TYPE_ID, Q_ORDER, Q_MAX_SCORE
      FROM UT_TEST_STRUCT_POINTS
      WHERE STRUCT_ID = :I$STRUCT_ID AND DATE_DEL IS NULL
      ORDER BY Q_ORDER
      INTO :OBJ_ID, :STRUCT_ID, :Q_TYPE_ID, :Q_ORDER, :Q_MAX_SCORE
  DO
  BEGIN
      SUSPEND;
  END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_STRUCT_POINTS_SET (
    I$OBJ_ID BIGINT,
    I$STRUCT_ID BIGINT,
    I$Q_TYPE_ID SMALLINT,
    I$Q_ORDER SMALLINT,
    I$Q_LEVEL SMALLINT,
    I$Q_MAX_SCORE SMALLINT,
    I$CHARSET_ID SMALLINT = null,
    I$TEXT_NOTES VARCHAR(8000) = null,
    I$WND_MIN FLOAT = null,
    I$WND_MAX FLOAT = null)
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$IS_USED smallint;
declare variable V$Q_TYPE_ID smallint;
declare variable V$Q_ORDER integer;
declare variable V$LEVEL smallint;
declare variable V$Q_MAX_SCORE smallint;
declare variable V$CHARSET_ID smallint;
declare variable V$TEXT_NOTES varchar(8000);
declare variable V$NOTES_CHANGED smallint;
declare variable V$CHARSET_CHANGED smallint;
declare variable V$QUESTION_ID bigint;
BEGIN

  -- Проверяем прикрепление структуры к тестированиям
  V$IS_USED = 0;
  SELECT FIRST 1 1
  FROM UT_TEST_STRUCTS TS
  JOIN UT_TESTS T ON T.STRUCT_ID = TS.OBJ_ID AND T.DATE_DEL IS NULL
  JOIN UT_TEST_VARS V ON V.DATE_DEL IS NULL AND V.TEST_ID = T.OBJ_ID
  JOIN UT_EXAM_TEST_VARS TV ON TV.DATE_DEL IS NULL AND TV.TEST_VAR_ID = V.OBJ_ID
  JOIN UT_EXAM_DATES D ON D.DATE_DEL IS NULL AND D.OBJ_ID = TV.EXAM_ID AND (D.EXAM_STATE > 500 AND D.EXAM_STATE < 1000)
  WHERE TS.OBJ_ID = :I$STRUCT_ID
  INTO :V$IS_USED;

  IF(I$WND_MIN < 0 OR I$WND_MIN > 100 OR I$WND_MAX < 0 OR I$WND_MAX > 100 OR I$WND_MAX < I$WND_MIN) THEN EXCEPTION DATA_ERROR 'Неверно задан коридор решаемости';

  IF(I$OBJ_ID IS NULL) THEN
  BEGIN

      -- Если структура зафиксирована, добавлять нельзя
      IF(V$IS_USED = 1) THEN EXCEPTION DATA_ERROR 'Структура уже использована в действующих назначениях на тестирования, добавлять позиции нельзя';
      IF(I$Q_TYPE_ID = 2 AND I$CHARSET_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Для одного из вопросов типа B не указана кодировка';

      INSERT INTO UT_TEST_STRUCT_POINTS
      (STRUCT_ID, Q_TYPE_ID, Q_ORDER, Q_LEVEL, Q_MAX_SCORE, CHARSET_ID, TEXT_NOTES, WND_MIN, WND_MAX)
      VALUES (:I$STRUCT_ID, :I$Q_TYPE_ID, :I$Q_ORDER, :I$Q_LEVEL, :I$Q_MAX_SCORE, :I$CHARSET_ID, :I$TEXT_NOTES, :I$WND_MAX, :I$WND_MAX)
      RETURNING OBJ_ID INTO :OBJ_ID;

  END
  ELSE
  BEGIN

      -- Если структура зафиксирована, нельзя менять наполнение
      -- Внимание: при сохранении нового варианта эта SP все равно будет вызвана, поэтому проверяем только реальные изменения

      SELECT TSP.Q_TYPE_ID, TSP.Q_ORDER, TSP.Q_LEVEL, TSP.Q_MAX_SCORE, TSP.CHARSET_ID, TSP.TEXT_NOTES
      FROM UT_TEST_STRUCT_POINTS TSP
      JOIN UT_TEST_STRUCTS TS ON TS.OBJ_ID = TSP.STRUCT_ID
      WHERE TSP.STRUCT_ID = :I$STRUCT_ID AND TSP.OBJ_ID = :I$OBJ_ID
      INTO :V$Q_TYPE_ID, :V$Q_ORDER, :V$LEVEL, :V$Q_MAX_SCORE, :V$CHARSET_ID, :V$TEXT_NOTES;

      IF(V$Q_TYPE_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Позиция структуры не найдена или была удалена';
      IF(V$IS_USED = 1 AND (V$Q_TYPE_ID <> I$Q_TYPE_ID OR V$Q_ORDER <> I$Q_ORDER OR V$LEVEL <> I$Q_LEVEL OR V$Q_MAX_SCORE <> I$Q_MAX_SCORE)) THEN
          EXCEPTION DATA_ERROR 'Структура уже использована в действующих назначениях на тестирования, вносить изменения нельзя';

      V$CHARSET_CHANGED = 0;
      IF((I$CHARSET_ID IS NULL AND V$CHARSET_ID IS NOT NULL) OR (I$CHARSET_ID IS NOT NULL AND V$CHARSET_ID IS NULL)
          OR (I$CHARSET_ID <> V$CHARSET_ID))
      THEN
          V$CHARSET_CHANGED = 1;

      -- Если есть хотя бы один вопрос не из автокодификатора - нельзя менять кодировку
      -- Если все из автокодификаторов - обновляем во всех прототипах вопросов
      IF(V$CHARSET_CHANGED <> 0 AND EXISTS(
          SELECT FIRST 1 1
          FROM UT_TEST_VAR_QUESTIONS TVQ
          JOIN UT_TEST_VARS TV ON TV.OBJ_ID = TVQ.VAR_ID AND TV.DATE_DEL IS NULL
          JOIN UT_TESTS T ON T.OBJ_ID = TV.TEST_ID AND T.DATE_DEL IS NULL AND T.CODING_ID IS NULL
          WHERE TVQ.DATE_DEL IS NULL AND TVQ.STRUCT_POINT_ID = :I$OBJ_ID
      )) THEN
          EXCEPTION DATA_ERROR 'Нельзя менять кодировку вопроса в структуре, к которой есть варианты с вопросами не из авто-кодификаторов';

      -- I$TEXT_NOTES если приходит NULL - оставляем старое значение. А вот если приходит пустая строка, тогда меняем на NULL
      V$NOTES_CHANGED = 0;
      IF(I$TEXT_NOTES IS NOT NULL) THEN
      BEGIN
          IF(I$TEXT_NOTES <> COALESCE(V$NOTES_CHANGED, '')) THEN V$NOTES_CHANGED = 1;
          IF(I$TEXT_NOTES = '') THEN I$TEXT_NOTES = NULL;
      END
      ELSE IF(I$TEXT_NOTES IS NULL) THEN I$TEXT_NOTES = V$TEXT_NOTES;

      IF(V$Q_TYPE_ID <> I$Q_TYPE_ID OR V$Q_ORDER <> I$Q_ORDER OR V$LEVEL <> I$Q_LEVEL OR V$Q_MAX_SCORE <> I$Q_MAX_SCORE OR V$NOTES_CHANGED = 1 OR
          (V$CHARSET_ID <> I$CHARSET_ID OR (I$CHARSET_ID IS NULL AND V$CHARSET_ID IS NOT NULL) OR (V$CHARSET_ID IS NULL AND I$CHARSET_ID IS NOT NULL))) THEN
      BEGIN
          UPDATE UT_TEST_STRUCT_POINTS
          SET Q_TYPE_ID = :I$Q_TYPE_ID, Q_ORDER = :I$Q_ORDER, Q_MAX_SCORE = :I$Q_MAX_SCORE, CHARSET_ID = COALESCE(:I$CHARSET_ID, :V$CHARSET_ID),
              Q_LEVEL = COALESCE(:I$Q_LEVEL, :V$LEVEL), TEXT_NOTES = :I$TEXT_NOTES, WND_MIN = :I$WND_MIN, WND_MAX = :I$WND_MAX
          WHERE OBJ_ID = :I$OBJ_ID;
      END

      -- Обновляем кодировку во всех вопросах, где используется этот вариант
      -- !!! надо проверять ит другие структуры, куда могли быть назначены эти вопросы !!!
      IF(V$CHARSET_CHANGED <> 0) THEN
      BEGIN
          FOR
              SELECT TVQ.QUESTION_ID
              FROM UT_TEST_VAR_QUESTIONS TVQ
              JOIN UT_TEST_VARS TV ON TV.OBJ_ID = TVQ.VAR_ID AND TV.DATE_DEL IS NULL
              JOIN UT_TESTS T ON T.OBJ_ID = TV.TEST_ID AND T.DATE_DEL IS NULL AND T.CODING_ID IS NULL
              WHERE TVQ.DATE_DEL IS NULL AND TVQ.STRUCT_POINT_ID = :I$OBJ_ID
              INTO :V$QUESTION_ID
          DO
          BEGIN
              UPDATE UT_QUESTIONS
              SET CHARSET_ID = :I$CHARSET_ID
              WHERE OBJ_ID = :V$QUESTION_ID;
          END
      END

      OBJ_ID = :I$OBJ_ID;

  END

  SUSPEND;

END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_STRUCT_POINT_DELETE (
    I$OBJ_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$IS_USED smallint;
begin

  -- Проверяем прикрепление структуры к тестированиям
  V$IS_USED = 0;
  SELECT FIRST 1 1
  FROM UT_TEST_STRUCT_POINTS SP
  JOIN UT_TESTS T ON T.STRUCT_ID = SP.STRUCT_ID AND T.DATE_DEL IS NULL
  JOIN UT_TEST_VARS V ON V.DATE_DEL IS NULL AND V.TEST_ID = T.OBJ_ID
  JOIN UT_EXAM_TEST_VARS TV ON TV.DATE_DEL IS NULL AND TV.TEST_VAR_ID = V.OBJ_ID
  JOIN UT_EXAM_DATES D ON D.DATE_DEL IS NULL AND D.OBJ_ID = TV.EXAM_ID AND (D.EXAM_STATE > 500 AND D.EXAM_STATE < 1000)
  WHERE SP.OBJ_ID = :I$OBJ_ID
  INTO :V$IS_USED;

  -- Если структура зафиксирована, добавлять нельзя
  IF(V$IS_USED = 1) THEN EXCEPTION DATA_ERROR 'Структура уже использована в действующих назначениях на тестирования, изменять нельзя';

  -- Проверяем, что к позиции не прикреплены вопросы
  V$IS_USED = 0;
  SELECT FIRST 1 1
  FROM UT_TEST_VAR_QUESTIONS TVQ
  JOIN UT_TEST_VARS TV ON TV.OBJ_ID = TVQ.VAR_ID AND TV.DATE_DEL IS NULL
  JOIN UT_TESTS T ON T.OBJ_ID = TV.TEST_ID AND T.DATE_DEL IS NULL
  WHERE TVQ.DATE_DEL IS NULL AND TVQ.STRUCT_POINT_ID = :I$OBJ_ID
  INTO :V$IS_USED;
  IF(V$IS_USED = 1) THEN EXCEPTION DATA_ERROR 'К позиции структуры есть назначения вопросов, удалить позицию нельзя';

  UPDATE UT_TEST_STRUCT_POINTS
  SET DATE_DEL = CURRENT_TIMESTAMP
  WHERE OBJ_ID = :I$OBJ_ID AND DATE_DEL IS NULL;

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_STRUCT_VALIDATE (
    I$OBJ_ID BIGINT)
RETURNS (
    ERROR_TEXT VARCHAR(10))
AS
declare variable V$METHOD smallint;
declare variable N integer;
declare variable V$N integer;
declare variable V$TYPE smallint;
declare variable V$A smallint;
declare variable V$B smallint;
declare variable V$C smallint;
declare variable V$PREV_TYPE smallint;
declare variable N$C integer;
declare variable V$HSTR varchar(4000);
declare variable V$LEVEL smallint;
declare variable V$SCORE smallint;
declare variable V$CHARSET_ID smallint;
declare variable V$NEW_HASH bigint;
begin

  SELECT METHOD_ID
  FROM UT_TEST_STRUCTS
  WHERE OBJ_ID = :I$OBJ_ID AND DATE_DEL IS NULL
  INTO :V$METHOD;

  -- Нумерация пунктов должна идти подряд без перерывов
  N = 1;
  V$A = 0;
  V$B = 0;
  V$C = 0;
  N$C = 0;
  V$PREV_TYPE = NULL;
  V$HSTR = '';

  -- В процессе обработки формируем новую строку хэша
  FOR
      SELECT Q_ORDER, Q_TYPE_ID, Q_LEVEL, Q_MAX_SCORE, CHARSET_ID
      FROM UT_TEST_STRUCT_POINTS
      WHERE STRUCT_ID = :I$OBJ_ID AND DATE_DEL IS NULL
      ORDER BY Q_ORDER
      INTO :V$N, :V$TYPE, :V$LEVEL, :V$SCORE, :V$CHARSET_ID
  DO
  BEGIN

      V$HSTR = V$HSTR || V$N || ':' || V$TYPE || ',' || V$LEVEL || ',' || V$SCORE || ',' || V$CHARSET_ID || ';';

      -- Нумерация без дырок, начиная с 1
      IF(V$N <> N) THEN EXCEPTION DATA_ERROR 'Нарушение порядка нумерации';
      N = N + 1;

      -- Для бумажного тестирования возможны только вопросы типов A, B, C, при этом блоки должны быть сплошными
      -- Вопрос типа C может быть только один
      IF(V$METHOD = 2 AND V$TYPE NOT IN (1, 2, 3)) THEN EXCEPTION DATA_ERROR 'Для бумажного тестирования могут быть использованы только вопросы типов A, B, C';

      IF(V$METHOD = 2) THEN
      BEGIN
          IF(V$TYPE = 1) THEN
          BEGIN
              IF(V$PREV_TYPE IN (2, 3)) THEN EXCEPTION DATA_ERROR 'Типы вопросов не должны перемежаться';
              IF(V$B = 1 OR V$C = 1) THEN EXCEPTION DATA_ERROR 'Вопросы типа A должны следовать первыми по порядку';
              V$A = 1;
          END
          IF(V$TYPE = 2) THEN
          BEGIN
              IF(V$PREV_TYPE = 3) THEN EXCEPTION DATA_ERROR 'Типы вопросов не должны перемежаться';
              IF(V$C = 1) THEN EXCEPTION DATA_ERROR 'Вопросы типа B должны находиться перед вопросами типа C';
              V$B = 1;
          END
          IF(V$TYPE = 3) THEN
          BEGIN
              V$C = 1;
              N$C = N$C + 1;
          END
      END

      V$PREV_TYPE = V$TYPE;

  END

  IF(V$TYPE = 2 AND N$C > 1) THEN EXCEPTION DATA_ERROR 'При бумажном тестировании может быть задан только один вопрос с ответом в развернутой форме';

  V$NEW_HASH = HASH(V$HSTR);

  IF(EXISTS(
      SELECT FIRST 1 1
      FROM UT_TEST_STRUCTS
      WHERE OBJ_ID = :I$OBJ_ID AND (STR_HASH IS NULL OR STR_HASH <> :V$NEW_HASH)
  )) THEN
  BEGIN
      UPDATE UT_TEST_STRUCTS
      SET STR_HASH = :V$NEW_HASH
      WHERE OBJ_ID = :I$OBJ_ID;
  END

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_SYNC_EXPERT (
    I$EXAM_ID BIGINT,
    I$OU_ID INTEGER,
    I$OBJ_ID BIGINT,
    I$DATE_ADD TIMESTAMP,
    I$DATE_MODIFY TIMESTAMP,
    I$DATE_DEL TIMESTAMP,
    I$PERSON_ID BIGINT,
    I$ROLE_ID INTEGER,
    I$SECOND_CHECK SMALLINT,
    I$TEACHER_ID BIGINT,
    I$ORG_ID BIGINT,
    I$USERNAME VARCHAR(100),
    I$PWD VARCHAR(100),
    I$IS_ACTIVE SMALLINT,
    I$NAME_LAST VARCHAR(400),
    I$NAME_FIRST VARCHAR(400),
    I$NAME_MID VARCHAR(400),
    I$DATE_ADD2 TIMESTAMP,
    I$DATE_MODIFY2 TIMESTAMP,
    I$DATE_DEL2 TIMESTAMP)
AS
declare variable V$OBJ_ID bigint;
declare variable V$EXPERT_ID bigint;
declare variable V$MULT bigint;
begin

  SELECT MULTIPLIER FROM GEN INTO :V$MULT;

  IF(I$OBJ_ID < I$OU_ID * V$MULT OR I$OBJ_ID >= (I$OU_ID + 1) * V$MULT) THEN EXIT;
  -- EXCEPTION DATA_ERROR 'Данный код назначения эксперта не может быть использован для указанной организации';

  -- Если тестирования нет в базе, то не выгружаем (например, локальное тестирование из школы не выгружаем в регион)
  IF(NOT EXISTS(
      SELECT FIRST 1 1
      FROM UT_EXAM_DATES
      WHERE OBJ_ID = :I$EXAM_ID
  )) THEN EXIT;

  SELECT PA.OBJ_ID
  FROM UT_EXAM_EXPERT_ASSN PA
  WHERE PA.OBJ_ID = :I$OBJ_ID
  INTO :V$OBJ_ID;

  -- Сначала проверяем запись самого эксперта, и добавляем ее если что-то поменялось
  -- а также корректируем ФИО и адрес электронной почты, но только если запись не менялась на уровне региона
  SELECT E.EXPERT_ID
  FROM UT_EXPERTS E
  WHERE E.EXPERT_ID = :I$PERSON_ID
  INTO :V$EXPERT_ID;

  IF(V$EXPERT_ID IS NULL) THEN
  BEGIN

      INSERT INTO UT_EXPERTS
      (EXPERT_ID, DATE_ADD, DATE_MODIFY, DATE_DEL, TEACHER_ID, LAST_NAME, FIRST_NAME, MIDDLE_NAME, IS_ACTIVE, USER_NAME, PWD, ORG_ID)
      VALUES (:I$PERSON_ID, :I$DATE_ADD2, :I$DATE_MODIFY2, :I$DATE_DEL2, :I$TEACHER_ID, :I$NAME_LAST, :I$NAME_FIRST, :I$NAME_MID, :I$IS_ACTIVE, :I$USERNAME, :I$PWD, :I$ORG_ID);

  END
  ELSE
  BEGIN

      UPDATE UT_EXPERTS E
      SET E.DATE_ADD = :I$DATE_ADD2, E.DATE_MODIFY = :I$DATE_MODIFY2, E.DATE_DEL = :I$DATE_DEL2, E.TEACHER_ID = :I$TEACHER_ID, E.LAST_NAME = :I$NAME_LAST,
          E.FIRST_NAME = :I$NAME_FIRST, E.MIDDLE_NAME = :I$NAME_MID, E.IS_ACTIVE = :I$IS_ACTIVE, E.USER_NAME = :I$USERNAME, E.PWD = :I$PWD, E.ORG_ID = :I$ORG_ID
      WHERE E.EXPERT_ID = :I$PERSON_ID;

  END

  IF(V$OBJ_ID IS NULL) THEN
  BEGIN

      INSERT INTO UT_EXAM_EXPERT_ASSN
      (OBJ_ID, DATE_ADD, DATE_MODIFY, DATE_DEL, EXAM_ID, EXPERT_ID, ROLE_ID, SECOND_CHECK)
      VALUES (:I$OBJ_ID, :I$DATE_ADD, :I$DATE_MODIFY, :I$DATE_DEL, :I$EXAM_ID, :I$PERSON_ID, :I$ROLE_ID, :I$SECOND_CHECK);

  END
  ELSE
  BEGIN

      -- EXAM_ID тут меняться не должен
      UPDATE UT_EXAM_EXPERT_ASSN
      SET DATE_ADD = :I$DATE_ADD, DATE_MODIFY = :I$DATE_MODIFY, DATE_DEL = :I$DATE_DEL, EXPERT_ID = :I$PERSON_ID,
          ROLE_ID = :I$ROLE_ID, SECOND_CHECK = :I$SECOND_CHECK
      WHERE OBJ_ID = :I$OBJ_ID;

  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_SYNC_MEMBER (
    I$EXAM_ID BIGINT,
    I$OU_ID INTEGER,
    I$OBJ_ID BIGINT,
    I$DATE_ADD TIMESTAMP,
    I$DATE_MODIFY TIMESTAMP,
    I$DATE_DEL TIMESTAMP,
    I$PERSON_ID BIGINT,
    I$LOCAL_ID VARCHAR(40),
    I$BLANKS_PRINTED SMALLINT,
    I$LEVEL_ID SMALLINT)
AS
declare variable V$OBJ_ID bigint;
declare variable V$MULT bigint;
begin

  SELECT MULTIPLIER FROM GEN INTO :V$MULT;

  IF(I$OBJ_ID < I$OU_ID * V$MULT OR I$OBJ_ID >= (I$OU_ID + 1) * V$MULT) THEN EXIT;
  -- EXCEPTION DATA_ERROR 'Данный код назначения участника не может быть использован для указанной организации';

  -- Если тестирования нет в базе, то не выгружаем (например, локальное тестирование из школы не выгружаем в регион)
  IF(NOT EXISTS(
      SELECT FIRST 1 1
      FROM UT_EXAM_DATES
      WHERE OBJ_ID = :I$EXAM_ID
  )) THEN EXIT;

  -- Если участника нет в базе, то не выгружаем
  IF(NOT EXISTS(
      SELECT FIRST 1 1
      FROM OBJECTS
      WHERE OBJ_ID = :I$PERSON_ID
  )) THEN EXIT;

  SELECT PA.OBJ_ID
  FROM UT_EXAM_PERSON_ASSN PA
  WHERE PA.OBJ_ID = :I$OBJ_ID
  INTO :V$OBJ_ID;

  IF(V$OBJ_ID IS NULL) THEN
  BEGIN

      INSERT INTO UT_EXAM_PERSON_ASSN
      (OBJ_ID, DATE_ADD, DATE_MODIFY, DATE_DEL, EXAM_ID, PERSON_ID, LOCAL_ID, BLANKS_PRINTED, LEVEL_ID)
      VALUES (:I$OBJ_ID, :I$DATE_ADD, :I$DATE_MODIFY, :I$DATE_DEL, :I$EXAM_ID, :I$PERSON_ID, :I$LOCAL_ID, :I$BLANKS_PRINTED, :I$LEVEL_ID);

  END
  ELSE
  BEGIN

      -- EXAM_ID тут меняться не должен
      UPDATE UT_EXAM_PERSON_ASSN
      SET DATE_ADD = :I$DATE_ADD, DATE_MODIFY = :I$DATE_MODIFY, DATE_DEL = :I$DATE_DEL, PERSON_ID = :I$PERSON_ID, LOCAL_ID = :I$LOCAL_ID,
          BLANKS_PRINTED = :I$BLANKS_PRINTED, LEVEL_ID = :I$LEVEL_ID
      WHERE OBJ_ID = :I$OBJ_ID;

  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_TASK_TOTAL_RECALC (
    I$TASK_ID BIGINT,
    I$STATE_ID INTEGER,
    I$RAW_SUM INTEGER,
    I$UPDATE INTEGER = 1)
RETURNS (
    RAW_RESULT INTEGER)
AS
declare variable V$FINAL_ID bigint;
begin

  SELECT FIRST 1 C.OBJ_ID
  FROM UT_SESSION_CHECKS C
  WHERE C.QUESTION_ID = :I$TASK_ID AND C.DATE_DEL IS NULL AND C.EXPERT_ID IS NULL
  INTO :V$FINAL_ID;

  -- Пересчет общих итогов по работе. Данные берутся из ранее обсчитанных итогов по каждому вопросу
  IF(I$RAW_SUM IS NULL) THEN
  BEGIN
      SELECT SUM(IIF(CR.RAW_RESULT < 0, 0, CR.RAW_RESULT))
      FROM UT_SESSION_CHECK_RES CR
      WHERE CR.CHECK_ID = :V$FINAL_ID AND CR.DATE_DEL IS NULL
      INTO :RAW_RESULT;

      IF(RAW_RESULT IS NULL) THEN RAW_RESULT = 0;
  END
  ELSE RAW_RESULT = I$RAW_SUM;

  UPDATE UT_SESSION_CHECKS
  SET RAW_RESULT = :RAW_RESULT
  WHERE OBJ_ID = :V$FINAL_ID;

  -- Меняем или не меняем статус у конкретного задания
  IF(I$UPDATE <> 0) THEN
  BEGIN
      IF(I$STATE_ID IS NULL) THEN
      BEGIN
          UPDATE UT_SESSION_QUESTIONS
          SET RAW_RESULT = :RAW_RESULT
          WHERE OBJ_ID = :I$TASK_ID;
      END
      ELSE
      BEGIN
          UPDATE UT_SESSION_QUESTIONS
          SET RAW_RESULT = :RAW_RESULT, STATE_ID = :I$STATE_ID
          WHERE OBJ_ID = :I$TASK_ID AND STATE_ID <= :I$STATE_ID;

          -- Закрываем запись итогов по первому этапу проверки
          UPDATE UT_SESSION_CHECKS
          SET STATE_ID = :I$STATE_ID
          WHERE OBJ_ID = :V$FINAL_ID AND STATE_ID <= :I$STATE_ID;
      END
  END

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_VARS_LIST (
    I$OBJ_ID BIGINT = null)
RETURNS (
    OBJ_ID BIGINT)
AS
BEGIN
  FOR
      SELECT OBJ_ID
      FROM UT_TEST_VARS
      WHERE TEST_ID = :I$OBJ_ID AND DATE_DEL IS NULL
      INTO :OBJ_ID
  DO
  BEGIN
      SUSPEND;
  END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_VARS_SET (
    I$OBJ_ID BIGINT,
    I$TEST_ID BIGINT,
    I$NUM SMALLINT,
    I$OBJ_NAME VARCHAR(1000),
    I$EXAM_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    OBJ_NAME VARCHAR(1000),
    NUM INTEGER,
    IS_USED SMALLINT)
AS
BEGIN

  -- Формируем номер варианта автоматически
  IF(I$NUM IS NULL) THEN
  BEGIN

      SELECT MAX(NUM)
      FROM UT_TEST_VARS
      WHERE TEST_ID = :I$TEST_ID AND DATE_DEL IS NULL
      INTO :I$NUM;

      IF(I$NUM IS NULL) THEN I$NUM = 1; ELSE I$NUM = I$NUM + 1;

  END
  ELSE
  BEGIN

      -- Не должно быть двух одинаковых номера варианта
      IF(EXISTS(
          SELECT FIRST 1 1
          FROM UT_TEST_VARS
          WHERE TEST_ID = :I$TEST_ID AND DATE_DEL IS NULL AND NUM = :I$NUM AND (:I$OBJ_ID IS NULL OR OBJ_ID <> :I$OBJ_ID)
      ))
      THEN EXCEPTION DATA_ERROR 'Не может быть два одинаковых номера варианта в одном пакете';

  END

  IF(I$OBJ_NAME = 'Новый') THEN I$OBJ_NAME = NULL;
  IF(I$OBJ_NAME IS NULL) THEN I$OBJ_NAME = 'Вариант ' || I$NUM;

  IF(EXISTS(
      SELECT FIRST 1 1
      FROM UT_TEST_VARS
      WHERE TEST_ID = :I$TEST_ID AND DATE_DEL IS NULL AND OBJ_NAME = :I$OBJ_NAME AND (:I$OBJ_ID IS NULL OR OBJ_ID <> :I$OBJ_ID)
  ))
  THEN EXCEPTION DATA_ERROR 'Не может быть два варианта с одинаковым названием в одном пакете';

  IF(I$OBJ_ID IS NULL) THEN
  BEGIN

      INSERT INTO UT_TEST_VARS
      (TEST_ID, NUM, OBJ_NAME, MASTER_ED_ID)
      VALUES (:I$TEST_ID, :I$NUM, :I$OBJ_NAME, :I$EXAM_ID)
      RETURNING OBJ_ID INTO :OBJ_ID;

      IS_USED = 0;

  END
  ELSE
  BEGIN

      -- Тут пока заглушено
      -- MASTER_ED_ID прописываем только при добавлении и впоследствии не меняем

      UPDATE UT_TEST_VARS
      SET NUM = :I$NUM, OBJ_NAME = :I$OBJ_NAME
      WHERE OBJ_ID = :I$OBJ_ID;

      OBJ_ID = :I$OBJ_ID;

      IS_USED = 0;
      SELECT FIRST 1 1
      FROM UT_EXAM_TEST_VARS TV
      JOIN UT_EXAM_DATES D ON D.DATE_DEL IS NULL AND D.OBJ_ID = TV.EXAM_ID AND (D.EXAM_STATE > 500 AND D.EXAM_STATE < 1000)
      WHERE TV.DATE_DEL IS NULL AND TV.TEST_VAR_ID = :I$OBJ_ID
      INTO :IS_USED;

  END

  OBJ_NAME = I$OBJ_NAME;
  NUM = I$NUM;

  SUSPEND;
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_VAR_DELETE (
    I$OBJ_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable S varchar(1000);
BEGIN

  -- Задействована ли данная позиция структуры ?

  SELECT FIRST 1 ED.OBJ_NAME
  FROM UT_TEST_VARS V
  JOIN UT_EXAM_TEST_VARS ETV ON ETV.DATE_DEL IS NULL AND ETV.TEST_VAR_ID = V.OBJ_ID
  JOIN UT_EXAM_DATES ED ON ED.OBJ_ID = ETV.EXAM_ID AND ED.DATE_DEL IS NULL AND ED.EXAM_STATE < 1000
  WHERE V.OBJ_ID = :I$OBJ_ID AND V.DATE_DEL IS NULL
  INTO :S;

  IF(S IS NOT NULL) THEN EXCEPTION DATA_ERROR 'Вариант уже задействован в тестированиях, см. ' || S;

  UPDATE UT_TEST_VARS
  SET DATE_DEL = CURRENT_TIMESTAMP
  WHERE OBJ_ID = :I$OBJ_ID AND DATE_DEL IS NULL;

  SUSPEND;

END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_VAR_FILE_DEL (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(100))
RETURNS (
    OBJ_ID BIGINT,
    CONTENT_TYPE VARCHAR(10))
AS
begin

  SELECT F.OBJ_ID
  FROM UT_TEST_VAR_FILES F
  WHERE F.DATE_DEL IS NULL AND F.OBJ_ID = :I$OBJ_ID
  INTO :OBJ_ID;

  IF(OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Файл не найден или был удален';

  -- Проверяем права доступа

  UPDATE UT_TEST_VAR_FILES
  SET DATE_DEL = CURRENT_TIMESTAMP
  WHERE OBJ_ID = :I$OBJ_ID;

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_VAR_FILE_GET (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(100))
RETURNS (
    CONTENT_DATA BLOB SUB_TYPE 0 SEGMENT SIZE 80,
    OBJ_NAME VARCHAR(1000),
    CONTENT_TYPE VARCHAR(40))
AS
declare variable V$MASK integer;
declare variable V$VAR_ID bigint;
begin

  SELECT F.CONTENT_DATA, F.CONTENT_TYPE, F.OBJ_NAME, F.ATTR_MASK, F.VAR_ID
  FROM UT_TEST_VAR_FILES F
  WHERE F.DATE_DEL IS NULL AND F.OBJ_ID = :I$OBJ_ID
  INTO :CONTENT_DATA, :CONTENT_TYPE, :OBJ_NAME, :V$MASK, :V$VAR_ID;

  IF(V$VAR_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Файл не найден или был удален';

  -- Проверяем права доступа

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_VAR_GET (
    I$TEST_ID BIGINT,
    I$OBJ_ID BIGINT)
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(4000))
AS
declare variable V$IS_AUTO smallint;
declare variable V$STRUCT_ID bigint;
declare variable V$SUBJECT_ID bigint;
declare variable V$STAGE_ID integer;
declare variable V$METHOD_ID integer;
declare variable V$ID bigint;
declare variable V$POINT_ID bigint;
declare variable V$Q_ID bigint;
declare variable V$NAME varchar(1000);
declare variable V$S varchar(1000);
declare variable V$INDEX integer;
declare variable V$TYPE_ID integer;
declare variable V$NAME_SHORT varchar(10);
declare variable V$SCORE integer;
declare variable V$Q_NAME varchar(200);
declare variable V$LEVEL smallint;
declare variable V$CHARSET smallint;
declare variable V$CHARSET_NAME varchar(100);
declare variable V$GEN bigint;
declare variable V$MULTIPLIER bigint;
declare variable V$OBJ_ID bigint;
declare variable N integer;
begin

  -- Корелляция с UT_TESTS_GET !

  SELECT FIRST 1 S.OBJ_ID, S.SUBJECT_ID, S.STAGE_ID, S.METHOD_ID, S.IS_AUTO
  FROM UT_TESTS T
  JOIN UT_TEST_STRUCTS S ON S.OBJ_ID = T.STRUCT_ID
  WHERE T.OBJ_ID = :I$TEST_ID AND T.DATE_DEL IS NULL
  INTO :V$STRUCT_ID, :V$SUBJECT_ID, :V$STAGE_ID, :V$METHOD_ID, :V$IS_AUTO;

  SELECT OBJ_ID, OBJ_NAME, NUM
  FROM UT_TEST_VARS
  WHERE OBJ_ID = :I$OBJ_ID AND DATE_DEL IS NULL
  INTO :V$ID, :V$NAME, :V$INDEX;

  IF(I$OBJ_ID IS NOT NULL AND V$ID IS NULL) THEN EXCEPTION DATA_ERROR 'Вариант не найден или был удален другим пользователем';

  TAG_NAME = 'id';
  VAL = I$OBJ_ID;
  SUSPEND;

  TAG_NAME = 'name';
  VAL = V$NAME;
  SUSPEND;

  TAG_NAME = 'num';
  VAL = V$INDEX;
  SUSPEND;

  TAG_NAME = 'struct_id';
  VAL = V$STRUCT_ID;
  SUSPEND;

  -- Флаг является ли структура публичной, или создана только под конкретное тестирование
  TAG_NAME = 'is_auto';
  VAL = V$IS_AUTO;
  SUSPEND;

  -- Использована ли эта структура уже где-то ?
  -- 0 = не использована, 1 = использована
  TAG_NAME = 'is_used';
  VAL = 0;
  SELECT FIRST 1 1
  FROM UT_TESTS T
  JOIN UT_TEST_VARS V ON V.DATE_DEL IS NULL AND V.TEST_ID = T.OBJ_ID
  JOIN UT_EXAM_TEST_VARS TV ON TV.DATE_DEL IS NULL AND TV.TEST_VAR_ID = V.OBJ_ID
  JOIN UT_EXAM_DATES D ON D.DATE_DEL IS NULL AND D.OBJ_ID = TV.EXAM_ID AND (D.EXAM_STATE > 500 AND D.EXAM_STATE < 1000)
  WHERE T.DATE_DEL IS NULL AND T.STRUCT_ID = :V$STRUCT_ID
  INTO :VAL;
  SUSPEND;

  -- Флаг использования варианта
  TAG_NAME = 'var_is_used';
  VAL = 0;
  SELECT FIRST 1 1
  FROM UT_EXAM_TEST_VARS TV
  JOIN UT_EXAM_DATES D ON D.DATE_DEL IS NULL AND D.OBJ_ID = TV.EXAM_ID AND (D.EXAM_STATE > 500 AND D.EXAM_STATE < 1000)
  WHERE TV.DATE_DEL IS NULL AND TV.TEST_VAR_ID = :I$OBJ_ID
  INTO :VAL;
  SUSPEND;

  -- Справочник: типы вопросов
  TAG_NAME = 'types';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'types::json&colon;array';
  VAL = 1;
  SUSPEND;

  FOR
      SELECT QT.OBJ_ID, QT.OBJ_NAME, QT.OBJ_VALUE
      FROM UT_QUESTION_TYPE QT
      INTO :V$ID, :V$NAME, :V$S
  DO
  BEGIN
      TAG_NAME = 'types:q';
      VAL = NULL;
      SUSPEND;
  
      TAG_NAME = 'types:q:id';
      VAL = V$ID;
      SUSPEND;
  
      TAG_NAME = 'types:q:name';
      VAL = V$NAME;
      SUSPEND;
  
      TAG_NAME = 'types:q:value';
      VAL = V$S;
      SUSPEND;
  END

  -- Справочник: кодировки
  TAG_NAME = 'charsets';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'charsets::json&colon;array';
  VAL = 1;
  SUSPEND;

  FOR
      SELECT C.OBJ_ID, C.OBJ_NAME, C.LANG_CODE
      FROM UT_CHARSETS C
      INTO :V$ID, :V$NAME, :V$S
  DO
  BEGIN
      TAG_NAME = 'charsets:q';
      VAL = NULL;
      SUSPEND;
  
      TAG_NAME = 'charsets:q:id';
      VAL = V$ID;
      SUSPEND;
  
      TAG_NAME = 'charsets:q:name';
      VAL = V$NAME;
      SUSPEND;
  
      TAG_NAME = 'charsets:q:lang_code';
      VAL = V$S;
      SUSPEND;
  END

  -- Кодификаторы, соответствующие предмету в структуре, за исключением автосформированных кодификаторов
  -- метапредмет считаем соответствующим любому предмету
  TAG_NAME = 'codings';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'codings::json&colon;array';
  VAL = 1;
  SUSPEND;

  FOR
      SELECT KC.OBJ_ID, KC.OBJ_NAME
      FROM UT_KIM_CODING KC
      -- Связка сначала через этап
      JOIN UT_KIM_CODING_STAGES CS ON CS.CODING_ID = KC.OBJ_ID AND CS.STAGE_ID = :V$STAGE_ID AND CS.DATE_DEL IS NULL
      -- Досвязка по предмету
      WHERE KC.DATE_DEL IS NULL AND EXISTS(
         SELECT FIRST 1 1
         FROM UT_KIM_CODING_SUBJECTS CSS
         WHERE CSS.CODING_ID = KC.OBJ_ID AND CSS.DATE_DEL IS NULL AND ((CSS.SUBJECT_ID IS NULL AND :V$SUBJECT_ID IS NULL) OR CSS.SUBJECT_ID = :V$SUBJECT_ID)
      )
      INTO :V$ID, :V$NAME
  DO
  BEGIN
      TAG_NAME = 'codings:c';
      VAL = NULL;
      SUSPEND;
  
      TAG_NAME = 'codings:c:id';
      VAL = V$ID;
      SUSPEND;
  
      TAG_NAME = 'codings:c:name';
      VAL = V$NAME;
      SUSPEND;
  END

  -- Описание позиций структуры
  TAG_NAME = 'structs';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'structs::json&colon;array';
  VAL = 1;
  SUSPEND;

  FOR
      SELECT TSP.OBJ_ID, TSP.Q_ORDER, TSP.Q_TYPE_ID, QT.OBJ_NAME, QT.OBJ_VALUE, TSP.Q_MAX_SCORE, TSP.Q_LEVEL, TSP.CHARSET_ID, C.OBJ_NAME
      FROM UT_TEST_STRUCT_POINTS TSP
      JOIN UT_QUESTION_TYPE QT ON QT.OBJ_ID = TSP.Q_TYPE_ID
      LEFT JOIN UT_CHARSETS C ON C.OBJ_ID = TSP.CHARSET_ID
      WHERE TSP.STRUCT_ID = :V$STRUCT_ID AND TSP.DATE_DEL IS NULL
      ORDER BY 2
      INTO :V$ID, :V$INDEX, :V$TYPE_ID, :V$NAME, :V$NAME_SHORT, :V$SCORE, :V$LEVEL, :V$CHARSET, :V$CHARSET_NAME
  DO
  BEGIN

      TAG_NAME = 'structs:s';
      VAL = NULL;
      SUSPEND;

      TAG_NAME = 'structs:s:id';
      VAL = V$ID;
      SUSPEND;

      TAG_NAME = 'structs:s:index';
      VAL = V$INDEX;
      SUSPEND;

      TAG_NAME = 'structs:s:type_id';
      VAL = V$TYPE_ID;
      SUSPEND;

      TAG_NAME = 'structs:s:type_value';
      VAL = V$NAME_SHORT;
      SUSPEND;

      TAG_NAME = 'structs:s:type_name';
      VAL = V$NAME;
      SUSPEND;

      TAG_NAME = 'structs:s:level';
      VAL = V$LEVEL;
      SUSPEND;

      TAG_NAME = 'structs:s:max_score';
      VAL = V$SCORE;
      SUSPEND;

      TAG_NAME = 'structs:s:charset_id';
      VAL = V$CHARSET;
      SUSPEND;

      TAG_NAME = 'structs:s:charset';
      VAL = V$CHARSET_NAME;
      SUSPEND;

      -- Для каждой позиции - флаг, что к данной структуре уже прикреплены вопросы
      TAG_NAME = 'structs:s:has_refs';
      VAL = 1;
      SELECT FIRST 1 1
      FROM UT_TEST_VAR_QUESTIONS TVQ
      JOIN UT_TEST_VARS TV ON TV.OBJ_ID = TVQ.VAR_ID AND TV.DATE_DEL IS NULL
      JOIN UT_TESTS T ON T.OBJ_ID = TV.TEST_ID AND T.DATE_DEL IS NULL
      WHERE TVQ.DATE_DEL IS NULL AND TVQ.STRUCT_POINT_ID = :V$ID
      INTO :VAL;
      SUSPEND;

  END

  -- Вопросы в варианте
  TAG_NAME = 'qts';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'qts::json&colon;array';
  VAL = 1;
  SUSPEND;

  FOR
      SELECT Q.OBJ_ID, P.Q_ORDER, Q.STRUCT_POINT_ID, Q.ORDER_INDEX, QT.OBJ_ID, QT.OBJ_NAME
      FROM UT_TEST_VAR_QUESTIONS Q
      JOIN UT_TEST_STRUCT_POINTS P ON P.OBJ_ID = Q.STRUCT_POINT_ID
      JOIN UT_QUESTIONS QT ON QT.OBJ_ID = Q.QUESTION_ID
      WHERE Q.DATE_DEL IS NULL AND Q.VAR_ID = :I$OBJ_ID
      ORDER BY 2, 4
      INTO :V$ID, :V$INDEX, :V$POINT_ID, :V$SCORE, :V$Q_ID, :V$Q_NAME
  DO
  BEGIN

      TAG_NAME = 'qts:qt';
      VAL = NULL;
      SUSPEND;
    
      TAG_NAME = 'qts:qt:id';
      VAL = V$ID;
      SUSPEND;
    
      TAG_NAME = 'qts:qt:number';
      VAL = V$INDEX;
      SUSPEND;

      TAG_NAME = 'qts:qt:point_id';
      VAL = V$POINT_ID;
      SUSPEND;
    
      TAG_NAME = 'qts:qt:order_index';
      VAL = V$SCORE;
      SUSPEND;
    
      TAG_NAME = 'qts:qt:q_id';
      VAL = V$Q_ID;
      SUSPEND;
    
      TAG_NAME = 'qts:qt:q_name';
      VAL = V$Q_NAME;
      SUSPEND;

  END

  -- Файлы вложений (КИМы и проч)
  TAG_NAME = 'files';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'files::json&colon;array';
  VAL = 1;
  SUSPEND;

  FOR
      SELECT F.OBJ_ID, F.OBJ_NAME, F.FILE_HASH, F.CONTENT_TYPE, F.ATTR_MASK, CHAR_LENGTH(F.CONTENT_DATA)
      FROM UT_TEST_VAR_FILES F
      WHERE F.DATE_DEL IS NULL AND F.VAR_ID = :I$OBJ_ID
      ORDER BY 2
      INTO :V$OBJ_ID, :V$NAME, :V$S, :V$Q_NAME, :V$TYPE_ID, :N
  DO
  BEGIN
      TAG_NAME = 'files:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'files:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'files:r:name';
      VAL = V$NAME;
      SUSPEND;
      TAG_NAME = 'files:r:hash';
      VAL = V$S;
      SUSPEND;
      TAG_NAME = 'files:r:type';
      VAL = V$Q_NAME;
      SUSPEND;
      TAG_NAME = 'files:r:mask';
      VAL = V$TYPE_ID;
      SUSPEND;
      TAG_NAME = 'files:r:size';
      VAL = N;
      SUSPEND;
  END

  -- Глобальные права доступа к варианту и к структур
  SELECT GEN, MULTIPLIER
  FROM GEN
  INTO :V$GEN, :V$MULTIPLIER;

  N = I$OBJ_ID / V$MULTIPLIER;
  TAG_NAME = 'allowed';
  VAL = 0;
  IF(I$OBJ_ID IS NULL OR N = V$GEN) THEN VAL = 1;
  SUSPEND;

  N = V$STRUCT_ID / V$MULTIPLIER;
  TAG_NAME = 'str_allowed';
  VAL = 0;
  IF(N = V$GEN) THEN VAL = 1;
  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_VAR_PRINT (
    I$EXAM_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$VAR_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    VARIANT_ID BIGINT,
    VARIANT_NUM INTEGER,
    POINT_INDEX INTEGER,
    POINT_LEVEL SMALLINT,
    POINT_SCORE SMALLINT,
    TEXT_NOTES VARCHAR(8000),
    QUESTION_TYPE SMALLINT,
    QUESTION_DATA BLOB SUB_TYPE 1 SEGMENT SIZE 80,
    ANSWER_INDEX INTEGER,
    ANSWER_DATA BLOB SUB_TYPE 1 SEGMENT SIZE 80)
AS
declare variable V$STATE integer;
declare variable V$STRUCT_ID bigint;
declare variable V$POINT_ID bigint;
declare variable V$QUESTION_ID bigint;
declare variable V$INDEX integer;
declare variable V$L integer;
declare variable V$R integer;
begin

  -- Если EXAM_ID указан - проверяем статус тестирования, чтобы не напечатать КИМ раньше чем положено
  -- Если EXAM_ID не указан, проверяем наличие прав доступа к кодификатору
  IF(I$EXAM_ID IS NOT NULL) THEN
  BEGIN
      SELECT D.EXAM_STATE
      FROM UT_EXAM_DATES D
      WHERE D.OBJ_ID = :I$EXAM_ID AND D.DATE_DEL IS NULL
      INTO :V$STATE;

      IF(V$STATE IS NULL) THEN EXCEPTION DATA_ERROR 'Тестирование не найдено или было удалено';
      IF(V$STATE < 600 OR V$STATE >= 1000) THEN EXCEPTION DATA_ERROR 'Недопустимый статус тестирования';
  END

  FOR
      SELECT TV.OBJ_ID, TV.NUM, T.STRUCT_ID, T.OBJ_NAME || ASCII_CHAR(9) ||  IIF(TS.SUBJECT_ID IS NULL, 'Метапредмет', C.CAPTION), TS.TEXT_NOTES
      FROM UT_TEST_VARS TV
      JOIN UT_TESTS T ON T.OBJ_ID = TV.TEST_ID
      JOIN UT_TEST_STRUCTS TS ON TS.OBJ_ID = T.STRUCT_ID
      LEFT JOIN OBJECT_CAPTION_GET(TS.SUBJECT_ID) C ON 1 = 1
      WHERE TV.OBJ_ID = :I$OBJ_ID AND TV.DATE_DEL IS NULL
      UNION
      SELECT TV.OBJ_ID, TV.NUM, T.STRUCT_ID, T.OBJ_NAME || ASCII_CHAR(9) ||  IIF(TS.SUBJECT_ID IS NULL, 'Метапредмет', C.CAPTION), TS.TEXT_NOTES
      FROM UT_EXAM_TEST_VARS ETV
      JOIN UT_TEST_VARS TV ON TV.OBJ_ID = ETV.TEST_VAR_ID AND TV.DATE_DEL IS NULL
      JOIN UT_TESTS T ON T.OBJ_ID = TV.TEST_ID
      JOIN UT_TEST_STRUCTS TS ON TS.OBJ_ID = T.STRUCT_ID
      LEFT JOIN OBJECT_CAPTION_GET(TS.SUBJECT_ID) C ON 1 = 1
      WHERE ETV.DATE_DEL IS NULL AND ETV.EXAM_ID = :I$EXAM_ID
      INTO :VARIANT_ID, :VARIANT_NUM, :V$STRUCT_ID, :TEXT_NOTES, :ANSWER_DATA
  DO
  BEGIN
      -- Первая строка = сам вариант, в TEXT_NOTES возвращаем название предмета и название пакета тестов
      POINT_INDEX = NULL;
      POINT_LEVEL = NULL;
      POINT_SCORE = NULL;
      QUESTION_TYPE = NULL;
      QUESTION_DATA = NULL;
      ANSWER_INDEX = NULL;
      ANSWER_DATA = NULL;
      SUSPEND;

      -- Идем по позициям вопросов
      FOR
          SELECT TSP.OBJ_ID, TSP.Q_TYPE_ID, TSP.Q_ORDER, TSP.TEXT_NOTES, TSP.Q_LEVEL, TSP.Q_MAX_SCORE
          FROM UT_TEST_STRUCT_POINTS TSP
          WHERE TSP.STRUCT_ID = :V$STRUCT_ID AND TSP.DATE_DEL IS NULL
          ORDER BY 3
          INTO :V$POINT_ID, :QUESTION_TYPE, :POINT_INDEX, :TEXT_NOTES, :POINT_LEVEL, :POINT_SCORE
      DO
      BEGIN

          -- Если вопросов несколько, выдаем только первый
          V$QUESTION_ID = NULL;
          QUESTION_DATA = NULL;

          SELECT FIRST 1 Q.OBJ_ID, Q.QUESTION
          FROM UT_TEST_VAR_QUESTIONS TVQ
          JOIN UT_QUESTIONS Q ON Q.OBJ_ID = TVQ.QUESTION_ID
          WHERE TVQ.VAR_ID = :VARIANT_ID AND TVQ.DATE_DEL IS NULL AND TVQ.STRUCT_POINT_ID = :V$POINT_ID
          INTO :V$QUESTION_ID, :QUESTION_DATA;

          IF(V$QUESTION_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Системная ошибка. Некорректно настроен кодификатор';

          ANSWER_INDEX = NULL;
          ANSWER_DATA = NULL;
          SUSPEND;

          -- Варианты ответов для вопросов типа A
          IF(QUESTION_TYPE = 1) THEN
          BEGIN
              FOR
                  SELECT A.SORT_ORDER, A.VARIANT
                  FROM UT_ANSWERS A
                  WHERE A.QUESTION_ID = :V$QUESTION_ID AND A.DATE_DEL IS NULL
                  ORDER BY 1
                  INTO :ANSWER_INDEX, :ANSWER_DATA
              DO
              BEGIN
                  SUSPEND;
              END
          END
          -- Задание на соответствие
          ELSE IF(QUESTION_TYPE = 4) THEN
          BEGIN
              -- Сортировка идет по фейковому порядку, индексы переформируем в этом же порядке
              V$L = 1;
              V$R = 1;
              FOR
                  SELECT A.SORT_ORDER, A.VARIANT
                  FROM UT_ANSWERS A
                  WHERE A.QUESTION_ID = :V$QUESTION_ID AND A.DATE_DEL IS NULL
                  ORDER BY A.FAKE_ORDER
                  INTO :V$INDEX, :ANSWER_DATA
              DO
              BEGIN
                  IF(V$INDEX < 0) THEN BEGIN
                      V$L = V$L + 1;
                      ANSWER_INDEX = - V$L;
                  END
                  ELSE IF(V$INDEX > 0) THEN BEGIN
                      V$R = V$R + 1;
                      ANSWER_INDEX = V$R;
                  END
                  SUSPEND;
              END
          END

      END
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_VAR_QUESTIONS_GET (
    I$VAR_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    VAR_ID BIGINT,
    STRUCT_POINT_ID BIGINT,
    QUESTION_ID BIGINT)
AS
BEGIN

  FOR
      SELECT OBJ_ID, VAR_ID, STRUCT_POINT_ID, QUESTION_ID
      FROM UT_TEST_VAR_QUESTIONS
      WHERE VAR_ID = :I$VAR_ID AND DATE_DEL IS NULL
      INTO :OBJ_ID, :VAR_ID, :STRUCT_POINT_ID, :QUESTION_ID
  DO
  BEGIN
      SUSPEND;
  END

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_VAR_QUESTIONS_SET (
    I$OBJ_ID BIGINT,
    I$VAR_ID BIGINT,
    I$STRUCT_POINT_ID BIGINT,
    I$QUESTION_ID BIGINT,
    I$ORDER_INDEX INTEGER,
    I$STATUS SMALLINT = 1)
RETURNS (
    OBJ_ID BIGINT)
AS
BEGIN
  -- I$STATUS: 0/1 = обновить, 2 = удалить

  IF (I$OBJ_ID IS NULL) THEN
  BEGIN

      IF(NOT EXISTS(
          SELECT FIRST 1 1
          FROM UT_TEST_VARS TV
          JOIN UT_TESTS T ON T.OBJ_ID = TV.TEST_ID
          JOIN UT_TEST_STRUCTS TS ON TS.OBJ_ID = T.STRUCT_ID AND TS.DATE_DEL IS NULL
          JOIN UT_TEST_STRUCT_POINTS TSP ON TSP.STRUCT_ID = TS.OBJ_ID AND TSP.DATE_DEL IS NULL AND TSP.OBJ_ID = :I$STRUCT_POINT_ID
          WHERE TV.OBJ_ID = :I$VAR_ID AND TV.DATE_DEL IS NULL
      ))
      THEN EXCEPTION DATA_ERROR 'Системная ошибка: выбран элемент структуры из чужой структуры, либо один из объектов в тесте утрачен';

      INSERT INTO UT_TEST_VAR_QUESTIONS
      (VAR_ID, STRUCT_POINT_ID, QUESTION_ID, ORDER_INDEX)
      VALUES (:I$VAR_ID, :I$STRUCT_POINT_ID, :I$QUESTION_ID, :I$ORDER_INDEX)
      RETURNING OBJ_ID INTO :OBJ_ID;

  END
  ELSE
  BEGIN

      UPDATE UT_TEST_VAR_QUESTIONS
      SET ORDER_INDEX = :I$ORDER_INDEX, DATE_DEL = CASE WHEN :I$STATUS = 2 THEN CURRENT_TIMESTAMP ELSE NULL END
      WHERE OBJ_ID = :I$OBJ_ID;

      OBJ_ID = I$OBJ_ID;

  END

  SUSPEND;

END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TEST_VAR_QUESTION_DELETE (
    I$OBJ_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$IS_USED smallint;
begin

  -- Если вариант уже назначен кому-то - не разрешаем
  V$IS_USED = 0;
  SELECT FIRST 1 1
  FROM UT_TEST_VAR_QUESTIONS VQ
  JOIN UT_TEST_VARS V ON V.OBJ_ID = VQ.VAR_ID AND V.DATE_DEL IS NULL
  JOIN UT_EXAM_TEST_VARS ETV ON ETV.TEST_VAR_ID = V.OBJ_ID AND ETV.DATE_DEL IS NULL
  JOIN UT_EXAM_DATES D ON D.DATE_DEL IS NULL AND D.OBJ_ID = ETV.EXAM_ID AND (D.EXAM_STATE > 500 AND D.EXAM_STATE < 1000)
  WHERE VQ.OBJ_ID = :I$OBJ_ID AND VQ.DATE_DEL IS NULL
  INTO :V$IS_USED;

  IF(V$IS_USED = 1) THEN EXCEPTION DATA_ERROR 'Вариант уже использован в действующих назначениях на тестирования, изменять нельзя';

  UPDATE UT_TEST_VAR_QUESTIONS
  SET DATE_DEL = CURRENT_TIMESTAMP
  WHERE OBJ_ID = :I$OBJ_ID AND DATE_DEL IS NULL;

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_TIME_SUBMIT (
    I$QUESTION_ID BIGINT,
    I$TIME INTEGER)
RETURNS (
    STATUS_CODE INTEGER)
AS
declare variable V$SESSION_STATE integer;
declare variable V$EXAM_STATE integer;
declare variable V$EXAM_TIME time;
begin

  -- I$TIME передается кумулятивно, начиная с момента который был в момент открытия

  -- STATUS_CODE: 0 = есть время, 1 = время теста истекло и надо закончить
  -- либо EXCEPTION

  SELECT S.STATE_ID, ED.EXAM_STATE, ED.DURATION
  FROM UT_SESSION_QUESTIONS SQ
  JOIN UT_SESSIONS S ON S.OBJ_ID = SQ.SESSION_ID AND S.DATE_DEL IS NULL
  JOIN UT_EXAM_DATES ED ON ED.OBJ_ID = S.ED_ID AND ED.DATE_DEL IS NULL
  WHERE SQ.OBJ_ID = :I$QUESTION_ID AND SQ.DATE_DEL IS NULL
  INTO :V$SESSION_STATE, :V$EXAM_STATE, :V$EXAM_TIME;

  STATUS_CODE = 0;

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_USER_TO_EXPERT (
    I$USER_ID VARCHAR(40))
RETURNS (
    EXPERT_ID BIGINT,
    EXPERT_ROLE SMALLINT)
AS
declare variable V$USER_ID bigint;
begin

  IF(I$USER_ID = 'Веб-администратор') THEN V$USER_ID = 0; ELSE V$USER_ID = CAST(I$USER_ID AS BIGINT);

  -- В случае Параграф сотрудник логинится как эксперт - нужно поменять ID
  SELECT E.EXPERT_ID, U.USER_TYPE
  FROM USERS U
  JOIN UT_EXPERTS E ON E.TEACHER_ID = U.OBJ_ID AND E.DATE_DEL IS NULL
  WHERE U.USER_ID = :V$USER_ID AND U.DATE_DEL IS NULL
  INTO :EXPERT_ID, :EXPERT_ROLE;

  -- В случае, если залогинен не-сотрудник, проверяем отдельно внешних экспертов
  IF(EXPERT_ID IS NULL) THEN
  BEGIN

      SELECT E.EXPERT_ID
      FROM UT_EXPERTS E
      WHERE E.EXPERT_ID = :V$USER_ID AND E.DATE_DEL IS NULL -- AND E.TEACHER_ID IS NULL
      INTO :EXPERT_ID;

      -- Стороннему эксперту даем права как учителю-предметнику
      IF(EXPERT_ID IS NOT NULL) THEN EXPERT_ROLE = 9;

  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_VALIDATE_ANSWER_01 (
    I$QUESTION_ID BIGINT,
    I$ANSWER_DATA VARCHAR(4000) NOT NULL)
RETURNS (
    STATE_ID INTEGER,
    RATE INTEGER)
AS
DECLARE VARIABLE V$FLAGS INTEGER;
DECLARE VARIABLE V$RIGHT_ANSWERS INTEGER;
DECLARE VARIABLE V$WRONG_ANSWERS INTEGER;
DECLARE VARIABLE V$TOTAL_RIGHT INTEGER;
DECLARE VARIABLE V$TOTAL INTEGER;
DECLARE VARIABLE V$Q_RATE INTEGER;
DECLARE VARIABLE V$RATE INTEGER;
DECLARE VARIABLE S VARCHAR(1000);
DECLARE VARIABLE P INTEGER;
DECLARE VARIABLE V INTEGER;
begin

  -- Формат ответа: упорядоченный список из номеров отмеченных позиций
  -- Результат: 0 баллов если

  -- Ответ дополняем запятыми в начале и конце чтобы проверять по цифрам
  I$ANSWER_DATA = ',' || I$ANSWER_DATA || ',';

  -- Счетчики правильных и неправильных ответов
  RATE = 0;
  V$RIGHT_ANSWERS = 0;
  V$WRONG_ANSWERS = 0;

  -- Маска атрибутов вопроса и максимальный балл
  SELECT FLAGS, MAX_SCORE
  FROM UT_QUESTIONS
  WHERE OBJ_ID = :I$QUESTION_ID
  INTO :V$FLAGS, :V$Q_RATE;

  -- Сколько у нас вопросов в эталоне - всего и правильных ?
  SELECT SUM(1), SUM(A.A_LEVEL)
  FROM UT_ANSWERS A
  WHERE A.QUESTION_ID = :I$QUESTION_ID AND A.DATE_DEL IS NULL
  INTO :V$TOTAL, :V$TOTAL_RIGHT;

  -- Часть 1 - идем по отвеченным позициям из ANSWER_DATA
  S = I$ANSWER_DATA;
  WHILE(S <> '') DO
  BEGIN
    P = POSITION(',' IN S);
    IF(P = 1) THEN S = SUBSTRING(S FROM 2);
    ELSE
    BEGIN
      V = CAST(SUBSTRING(S FROM 1 FOR P - 1) AS INTEGER);
      V$RATE = NULL;

      SELECT A.A_LEVEL
      FROM UT_ANSWERS A
      WHERE A.QUESTION_ID = :I$QUESTION_ID AND A.DATE_DEL IS NULL AND A.SORT_ORDER = :V
      INTO :V$RATE;

      IF(V$RATE IS NULL OR V$RATE = 0) THEN V$WRONG_ANSWERS = V$WRONG_ANSWERS + 1; ELSE V$RIGHT_ANSWERS = V$RIGHT_ANSWERS + 1;

      S = SUBSTRING(S FROM P + 1);
    END
  END

  -- Если есть неправильные ответы, на выходе всегда 0 баллов
  IF(V$WRONG_ANSWERS > 0) THEN
  BEGIN
    -- Результат = неправильный ответ, баллы обнуляем только если явно указано (бит 1 флагов)
    RATE = 0;
  END
  ELSE IF(V$TOTAL_RIGHT <> V$RIGHT_ANSWERS) THEN
  BEGIN
    -- Если не все правильные ответы выбраны, смотрим бит 1 флагов - если установлен, делаем линейную аппроксимацию
    IF(BIN_AND(V$FLAGS, 2) = 1) THEN RATE = ROUND(V$Q_RATE * (V$RIGHT_ANSWERS / V$TOTAL_RIGHT));
    ELSE RATE = 0;
  END
  ELSE RATE = V$Q_RATE;

  STATE_ID = 1000;
  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_VALIDATE_ANSWER_02 (
    I$QUESTION_ID BIGINT,
    I$ANSWER_DATA VARCHAR(4000) NOT NULL)
RETURNS (
    STATE_ID INTEGER,
    RATE INTEGER)
AS
declare variable V$FLAGS integer;
declare variable V$Q_RATE integer;
declare variable V$IS_RIGHT integer;
declare variable V$IS_WRONG integer;
begin

  I$ANSWER_DATA = SUBSTRING(I$ANSWER_DATA FROM 1 FOR 400);

  -- Маска атрибутов вопроса и максимальный балл
  SELECT FLAGS, MAX_SCORE
  FROM UT_QUESTIONS
  WHERE OBJ_ID = :I$QUESTION_ID
  INTO :V$FLAGS, :V$Q_RATE;

  V$IS_RIGHT = 0;
  V$IS_WRONG = 0;

  -- Регистрозависимость бит 0, игнорировать пробелы бит 1
  V$FLAGS = BIN_AND(V$FLAGS, 3);
  IF(V$FLAGS = 0) THEN
  BEGIN
      -- Регистронезависимо, пробелы как есть
      SELECT FIRST 1 1
      FROM UT_ANSWERS A
      WHERE A.QUESTION_ID = :I$QUESTION_ID AND A.DATE_DEL IS NULL AND UPPER(A.OBJ_NAME) = UPPER(:I$ANSWER_DATA) AND A.A_LEVEL > 0
      INTO :V$IS_RIGHT;
      SELECT FIRST 1 1
      FROM UT_ANSWERS A
      WHERE A.QUESTION_ID = :I$QUESTION_ID AND A.DATE_DEL IS NULL AND UPPER(A.OBJ_NAME) = UPPER(:I$ANSWER_DATA) AND A.A_LEVEL = 0
      INTO :V$IS_WRONG;
  END
  ELSE IF(V$FLAGS = 1) THEN
  BEGIN
      -- Регистрозависимо, пробелы как есть
      SELECT FIRST 1 1
      FROM UT_ANSWERS A
      WHERE A.QUESTION_ID = :I$QUESTION_ID AND A.DATE_DEL IS NULL AND A.OBJ_NAME = :I$ANSWER_DATA AND A.A_LEVEL > 0
      INTO :V$IS_RIGHT;
      SELECT FIRST 1 1
      FROM UT_ANSWERS A
      WHERE A.QUESTION_ID = :I$QUESTION_ID AND A.DATE_DEL IS NULL AND A.OBJ_NAME = :I$ANSWER_DATA AND A.A_LEVEL = 0
      INTO :V$IS_WRONG;
  END
  ELSE IF(V$FLAGS = 2) THEN
  BEGIN
      -- Регистронезависимо, пробелы вырезаем
      SELECT FIRST 1 1
      FROM UT_ANSWERS A
      WHERE A.QUESTION_ID = :I$QUESTION_ID AND A.DATE_DEL IS NULL AND UPPER(REPLACE(A.OBJ_NAME, ' ', '')) = UPPER(REPLACE(:I$ANSWER_DATA, ' ', '')) AND A.A_LEVEL > 0
      INTO :V$IS_RIGHT;
      SELECT FIRST 1 1
      FROM UT_ANSWERS A
      WHERE A.QUESTION_ID = :I$QUESTION_ID AND A.DATE_DEL IS NULL AND UPPER(REPLACE(A.OBJ_NAME, ' ', '')) = UPPER(REPLACE(:I$ANSWER_DATA, ' ', '')) AND A.A_LEVEL = 0
      INTO :V$IS_WRONG;
  END
  ELSE IF(V$FLAGS = 3) THEN
  BEGIN
      -- Регистрозависимо, пробелы вырезаем
      SELECT FIRST 1 1
      FROM UT_ANSWERS A
      WHERE A.QUESTION_ID = :I$QUESTION_ID AND A.DATE_DEL IS NULL AND REPLACE(A.OBJ_NAME, ' ', '') = REPLACE(:I$ANSWER_DATA, ' ', '') AND A.A_LEVEL > 0
      INTO :V$IS_RIGHT;
      SELECT FIRST 1 1
      FROM UT_ANSWERS A
      WHERE A.QUESTION_ID = :I$QUESTION_ID AND A.DATE_DEL IS NULL AND REPLACE(A.OBJ_NAME, ' ', '') = REPLACE(:I$ANSWER_DATA, ' ', '') AND A.A_LEVEL = 0
      INTO :V$IS_WRONG;
  END

  -- Полный балл, если все ОК
  IF(V$IS_RIGHT > 0) THEN RATE = V$Q_RATE; ELSE RATE = 0;

  -- Если определен как валидный или невалидный ответ, переводим в статус завершено
  IF(V$IS_RIGHT > 0 OR V$IS_WRONG > 0) THEN
  BEGIN
      STATE_ID = 1000;
  END

  SUSPEND;
end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_VALIDATE_ANSWER_04 (
    I$QUESTION_ID BIGINT,
    I$ANSWER_DATA VARCHAR(4000) NOT NULL)
RETURNS (
    STATE_ID INTEGER,
    RATE INTEGER)
AS
declare variable V$FLAGS integer;
declare variable V$Q_RATE float;
declare variable SS varchar(4000);
declare variable P integer;
declare variable S varchar(100);
declare variable S2 varchar(100);
declare variable V$LEFT bigint;
declare variable V$RIGHT bigint;
declare variable V$N_RIGHT float;
declare variable V$N_WRONG integer;
declare variable V$TOTAL_RIGHT float;
declare variable V$PAIR integer;
declare variable M1 smallint;
declare variable R1 integer;
declare variable M2 integer;
declare variable R2 integer;
begin

  -- Маска атрибутов вопроса и максимальный балл
  SELECT FLAGS, MAX_SCORE
  FROM UT_QUESTIONS
  WHERE OBJ_ID = :I$QUESTION_ID
  INTO :V$FLAGS, :V$Q_RATE;

  V$N_RIGHT = 0;
  V$N_WRONG = 0;
  V$PAIR = 1;

  -- Переформатируем I$ANSWER_DATA, добавляя префиксы +
  SS = I$ANSWER_DATA;
  I$ANSWER_DATA = '';
  WHILE(CHAR_LENGTH(SS) > 0) DO
  BEGIN

      P = POSITION(',' IN SS);
      IF(P <= 0) THEN P = CHAR_LENGTH(SS) + 1;
      S = SUBSTRING(SS FROM 1 FOR P - 1);
      SS = SUBSTRING(SS FROM P + 1);
      P = POSITION(':' IN S);
      IF(P <= 0) THEN EXCEPTION DATA_ERROR 'Неверный формат ANSWER_DATA';
      V$LEFT = SUBSTRING(S FROM 1 FOR P - 1);
      V$RIGHT = SUBSTRING(S FROM P + 1);
      I$ANSWER_DATA = I$ANSWER_DATA || '+' || V$LEFT || '+,';
      I$ANSWER_DATA = I$ANSWER_DATA || '+' || V$RIGHT || '+,';

      M1 = NULL;
      M2 = NULL;
      R1 = NULL;
      R2 = NULL;

      SELECT FIRST 1 A.A_LEVEL, A.SORT_ORDER
      FROM UT_ANSWERS A
      WHERE A.QUESTION_ID = :I$QUESTION_ID AND A.DATE_DEL IS NULL AND A.SIGNATURE = :V$LEFT
      INTO :M1, :R1;

      -- Запасной вариант: вместо сигнатуры при повторах вариантов может быть хэш
      SELECT FIRST 1 A.A_LEVEL, A.SORT_ORDER
      FROM UT_ANSWERS A
      WHERE A.QUESTION_ID = :I$QUESTION_ID AND A.DATE_DEL IS NULL AND A.SIGNATURE = :V$RIGHT
      INTO :M2, :R2;

      IF(M1 IS NOT NULL AND M2 IS NULL) THEN
      SELECT FIRST 1 A.A_LEVEL, A.SORT_ORDER
      FROM UT_ANSWERS A
      WHERE A.QUESTION_ID = :I$QUESTION_ID AND A.DATE_DEL IS NULL AND A.HSIGNATURE = :V$RIGHT AND A.SORT_ORDER = ABS(:R1)
      INTO :M2, :R2;

      -- Если нет варианта с такими сигнатурами, считаем ошибкой
      IF(M1 IS NULL OR M2 IS NULL) THEN V$N_WRONG = V$N_WRONG + 1;
      ELSE IF(BIN_AND(V$FLAGS, 1) = 0) THEN
      BEGIN
        -- Нестрогий режим проверки, проверяем наличие пары как таковой
        IF(M1 = 0 OR M2 = 0 OR ABS(R1) <> ABS(R2)) THEN V$N_WRONG = V$N_WRONG + 1;
        ELSE V$N_RIGHT = V$N_RIGHT + 1;
      END
      ELSE
      BEGIN
        -- Строгий режим проверки. Если ошибка в середине, все после нее считаем ошибкой
        IF(V$N_WRONG <> 0 OR M1 = 0 OR M2 = 0 OR ABS(R1) <> ABS(R2) OR ABS(R1) <> V$PAIR) THEN V$N_WRONG = V$N_WRONG + 1;
        ELSE V$N_RIGHT = V$N_RIGHT + 1;
      END

      V$PAIR = V$PAIR + 1;

  END

  -- Все что осталось непарным, относим к ошибкам; также подсчитываем общее количество требуемых правильных пар
  V$TOTAL_RIGHT = 0;
  FOR
    SELECT A.SIGNATURE, A.HSIGNATURE, A.SORT_ORDER, A.A_LEVEL
    FROM UT_ANSWERS A
    WHERE A.QUESTION_ID = :I$QUESTION_ID AND A.DATE_DEL IS NULL
    INTO :S, :S2, :M1, :R1
  DO
  BEGIN
    -- Считаем пары по левой стороне
    IF(M1 < 0 AND R1 = 1) THEN V$TOTAL_RIGHT = V$TOTAL_RIGHT + 1;

    -- Ошибочные позиции, которые вошли в ответ, и так уже посчитаны. Смотрим правильные, которые не вошли
    P = POSITION(('+' || S || '+') IN I$ANSWER_DATA);
    IF(P <= 0) THEN P = POSITION(('+' || S2 || '+') IN I$ANSWER_DATA);
    IF(P <= 0 AND M1 = 1) THEN V$N_WRONG = V$N_WRONG + 1;
  END

  IF(V$TOTAL_RIGHT = 0) THEN RATE = 0;
  ELSE IF(V$N_WRONG > 0) THEN
  BEGIN
    -- Если не все правильные ответы выбраны, смотрим бит 1 флагов - если установлен, делаем линейную аппроксимацию
    IF(BIN_AND(V$FLAGS, 2) <> 0) THEN RATE = ROUND(V$Q_RATE * (V$N_RIGHT / V$TOTAL_RIGHT));
    ELSE RATE = 0;
  END
  ELSE RATE = V$Q_RATE;

  STATE_ID = 1000;
  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_VALIDATE_ANSWER_05 (
    I$QUESTION_ID BIGINT,
    I$ANSWER_DATA VARCHAR(4000) NOT NULL)
RETURNS (
    STATE_ID INTEGER,
    RATE INTEGER)
AS
DECLARE VARIABLE P INTEGER; /* позиция разделителя в строке вопросов */
DECLARE VARIABLE V$BF VARCHAR(1000); /* строка для проверки введенного фрагмента */
DECLARE VARIABLE V$BF2 VARCHAR(1000); /* запасной вариант ответа */
DECLARE VARIABLE V$FF VARCHAR(1000); /* ответ на вопрос, отправленный тестируемым */
DECLARE VARIABLE V$MAX_SCORE FLOAT; /* максимальный балл за вопрос, нужен для рассчета линейной апроксимации при частичном ответе */
DECLARE VARIABLE V$FRAGMENTS_COUNT FLOAT; /* число фрагментов в вопросе для заполнения */
DECLARE VARIABLE V$CHECKDATA VARCHAR(1000); /* строка с разделителями | для проверки фрагментов */
DECLARE VARIABLE V$FLAGS INTEGER; /* флаги вопроса (например, регистрозависимость) */
DECLARE VARIABLE V$RIGHT_COUNT FLOAT; /* число правильных ответов на фрагменты */
DECLARE VARIABLE P2 INTEGER; /* позиция следующего разделителя в строке с фрагментами, которые задал создатель тестирования */
DECLARE VARIABLE V$STOP SMALLINT;
DECLARE VARIABLE V$BINS INTEGER; /* 1 и 2 биты перемножаем */
begin

  -- Маска атрибутов вопроса и максимальный балл
  SELECT FLAGS, MAX_SCORE
  FROM UT_QUESTIONS
  WHERE OBJ_ID = :I$QUESTION_ID
  INTO :V$FLAGS, :V$MAX_SCORE;

  -- количество фрагментов для заполнения
  SELECT A.VARIANT
  FROM UT_ANSWERS A
  WHERE A.QUESTION_ID = :I$QUESTION_ID AND A.DATE_DEL IS NULL
  INTO :V$CHECKDATA;

  V$FRAGMENTS_COUNT = 0;
  I$ANSWER_DATA = I$ANSWER_DATA;
  V$RIGHT_COUNT = 0;
  V$STOP = 0;

  -- количество разделителей должно совпадать
  WHILE(V$STOP = 0) DO
  BEGIN
    -- ответы по порядку в строке через разделитель
    P = POSITION('|' IN I$ANSWER_DATA);
    P2 = POSITION('|' IN V$CHECKDATA);
    V$FRAGMENTS_COUNT = V$FRAGMENTS_COUNT + 1;
  
    -- остался один ответ?
    IF (P = 0) THEN
    BEGIN
      V$FF = I$ANSWER_DATA;
      V$BF = V$CHECKDATA;
      I$ANSWER_DATA = '';
      V$STOP = 1;
      IF (P2 <> 0) THEN EXCEPTION DATA_ERROR 'Системная ошибка, неправильно задано количество фрагментов на входе и выходе';
    END
    ELSE
    BEGIN
      V$FF = SUBSTRING(I$ANSWER_DATA FROM 1 FOR P - 1);
      V$BF = SUBSTRING(V$CHECKDATA FROM 1 FOR P2 - 1);
    END
    -- отрезаем от строк с фрагментами тот фрагмент, который проверили
    I$ANSWER_DATA = SUBSTRING(I$ANSWER_DATA FROM P + 1);
    V$CHECKDATA = SUBSTRING(V$CHECKDATA FROM P2 + 1);

    -- Есть ли альтернативный ответ в сегменте ?
    P = POSITION('~' IN V$BF);
    V$BF2 = NULL;
    IF(P > 0) THEN
    BEGIN
      V$BF2 = SUBSTRING(V$BF FROM P + 1);
      V$BF = SUBSTRING(V$BF FROM 1 FOR P - 1);
    END
  
    -- Флаги битовой маски Регистрозависимость бит 0, игнорировать пробелы бит 1, запретить повтор медиа 2, разрешать неполный ответ 3
    -- перемножаем 2 младших бита 1+2 = 3, по сути двумерная таблица с порядковым индексом
    V$BINS = BIN_AND(V$FLAGS, 3);
    IF(V$BINS = 0) THEN
    BEGIN
      -- Регистронезависимо, пробелы как есть
      IF(UPPER(V$FF) = UPPER(V$BF) OR UPPER(V$FF) = UPPER(V$BF2)) THEN V$RIGHT_COUNT = V$RIGHT_COUNT + 1;
    END
    ELSE IF(V$BINS = 1) THEN
    BEGIN
      -- Регистрозависимо, пробелы как есть
      IF(V$FF = V$BF OR V$FF = V$BF2) THEN V$RIGHT_COUNT = V$RIGHT_COUNT + 1;
    END
    ELSE IF(V$BINS = 2) THEN
    BEGIN
      -- Регистронезависимо, пробелы вырезаем
      V$FF = REPLACE(V$FF, ' ', '');
      V$BF = REPLACE(V$BF, ' ', '');
      V$BF2 = REPLACE(V$BF2, ' ', '');
      IF(UPPER(V$FF) = UPPER(V$BF) OR UPPER(V$FF) = UPPER(V$BF2)) THEN V$RIGHT_COUNT = V$RIGHT_COUNT + 1;
    END
    ELSE IF(V$BINS = 3) THEN
    BEGIN
      -- Регистрозависимо, пробелы вырезаем
      V$FF = REPLACE(V$FF, ' ', '');
      V$BF = REPLACE(V$BF, ' ', '');
      IF(V$FF = V$BF OR V$FF = V$BF2) THEN V$RIGHT_COUNT = V$RIGHT_COUNT + 1;
    END
  END

  -- установлен флаг разрешать неполный ответ? делаем линейную апроксимацию
  IF (BIN_AND(V$FLAGS, BIN_SHL(1, 3) ) <> 0) THEN
  BEGIN
    RATE = ROUND(V$MAX_SCORE * (V$RIGHT_COUNT / V$FRAGMENTS_COUNT));
    EXCEPTION DATA_ERROR RATE;
  END
  -- часть ответов была неверная
  ELSE IF (V$RIGHT_COUNT < V$FRAGMENTS_COUNT) THEN RATE = 0;
  -- все ответы были верные?
  ELSE RATE = V$MAX_SCORE;

  STATE_ID = 1000;
  SUSPEND;
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_VARIANTS_GET (
    I$EXAM_ID BIGINT,
    I$TEST_ID BIGINT)
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(1000))
AS
declare variable V$KIM_ID bigint;
declare variable V$KIM_NAME varchar(1000);
declare variable V$OBJ_ID bigint;
declare variable V$OBJ_NAME varchar(1000);
declare variable V$STRUCT_ID bigint;
declare variable V$VAR_NUM integer;
declare variable V$STR_HASH varchar(100);
declare variable V$FILE_ID bigint;
declare variable V$FILE_NAME varchar(1000);
declare variable V$S varchar(1000);
declare variable V$FILE_TYPE varchar(40);
declare variable V$NMIN integer;
declare variable V$NMAX integer;
begin

  TAG_NAME = 'data';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'data::json&colon;array';
  VAL = 1;
  SUSPEND;

  -- Функция возвращает данные для двух уровней вложения
  -- Первый уровень запрашивается с TEST_ID = NULL, и возвращает список пакетов КИМ
  -- Второй идет уже с конкретным TEST_ID и возвращает варианты в нем

  IF(I$TEST_ID IS NULL) THEN
  BEGIN

      -- Когда ID пакета не указан, выбираем список пакетов
      FOR
          SELECT T.OBJ_ID, T.OBJ_NAME, TS.OBJ_ID, TS.STR_HASH
          FROM UT_EXAM_DATES D
          JOIN UT_TEST_STRUCTS TS ON TS.SUBJECT_ID = D.SUBJECT_ID AND TS.STAGE_ID = D.STAGE_ID AND TS.METHOD_ID = D.METHOD_ID AND TS.DATE_DEL IS NULL
          JOIN UT_TESTS T ON T.STRUCT_ID = TS.OBJ_ID AND T.DATE_DEL IS NULL
          WHERE D.OBJ_ID = :I$EXAM_ID AND D.DATE_DEL IS NULL
          ORDER BY 2
          INTO :V$OBJ_ID, :V$OBJ_NAME, :V$STRUCT_ID, :V$STR_HASH
      DO
      BEGIN
            TAG_NAME = 'data:k';
            VAL = NULL;
            SUSPEND;
            TAG_NAME = 'data:k:obj_id';
            VAL = V$OBJ_ID;
            SUSPEND;
            TAG_NAME = 'data:k:obj_name';
            VAL = V$OBJ_NAME;
            SUSPEND;
            TAG_NAME = 'data:k:struct_id';
            VAL = V$STRUCT_ID;
            SUSPEND;
            TAG_NAME = 'data:k:str_hash';
            VAL = V$STR_HASH;
            SUSPEND;
            
      END

  END
  ELSE
  BEGIN

      -- Выбираем список вариантов в указанном пакете
      FOR
          SELECT V.OBJ_ID, V.NUM, COALESCE(V.OBJ_NAME, 'Вариант ' || cast(V.NUM as varchar(10))), TS.STR_HASH, T.OBJ_ID, T.OBJ_NAME
          FROM UT_TEST_VARS V
          JOIN UT_TESTS T ON T.OBJ_ID = V.TEST_ID
          JOIN UT_TEST_STRUCTS TS ON TS.OBJ_ID = T.STRUCT_ID
          WHERE V.TEST_ID = :I$TEST_ID AND V.DATE_DEL IS NULL
          ORDER BY 2
          INTO :V$OBJ_ID, :V$VAR_NUM, :V$OBJ_NAME, :V$STR_HASH, :V$KIM_ID, :V$KIM_NAME
      DO
      BEGIN

          TAG_NAME = 'data:v';
          VAL = NULL;
          SUSPEND;
          TAG_NAME = 'data:v:obj_id';
          VAL = V$OBJ_ID;
          SUSPEND;
          TAG_NAME = 'data:v:obj_name';
          VAL = V$OBJ_NAME;
          SUSPEND;
          TAG_NAME = 'data:v:var_num';
          VAL = V$VAR_NUM;
          SUSPEND;
          TAG_NAME = 'data:v:kim_id';
          VAL = V$KIM_ID;
          SUSPEND;
          TAG_NAME = 'data:v:kim_name';
          VAL = V$KIM_NAME;
          SUSPEND;
          TAG_NAME = 'data:v:str_hash';
          VAL = V$STR_HASH;
          SUSPEND;

          -- Файлы
          TAG_NAME = 'data:v:files';
          VAL = NULL;
          SUSPEND;
          TAG_NAME = 'data:v:files::json&colon;array';
          VAL = NULL;
          SUSPEND;
          FOR
              SELECT F.OBJ_ID, F.OBJ_NAME, F.CONTENT_TYPE, CHAR_LENGTH(F.CONTENT_DATA), F.ATTR_MASK, F.FILE_HASH
              FROM UT_TEST_VAR_FILES F
              WHERE F.DATE_DEL IS NULL AND F.VAR_ID = :V$OBJ_ID
              INTO :V$FILE_ID, :V$FILE_NAME, :V$FILE_TYPE, :V$NMAX, :V$NMIN, :V$S
          DO
          BEGIN
              TAG_NAME = 'data:v:files:f';
              VAL = NULL;
              SUSPEND;
              TAG_NAME = 'data:v:files:f:id';
              VAL = V$FILE_ID;
              SUSPEND;
              TAG_NAME = 'data:v:files:f:name';
              VAL = V$FILE_NAME;
              SUSPEND;
              TAG_NAME = 'data:v:files:f:hash';
              VAL = V$S;
              SUSPEND;
              TAG_NAME = 'data:v:files:f:type';
              VAL = V$FILE_TYPE;
              SUSPEND;
              TAG_NAME = 'data:v:files:f:mask';
              VAL = V$NMIN;
              SUSPEND;
              TAG_NAME = 'data:v:files:f:size';
              VAL = V$NMAX;
              SUSPEND;
          END

      END

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_VERIFY_ANSWERS_APPLY (
    I$BLANK_ID BIGINT,
    I$SESSION_ID BIGINT,
    I$VARIANT_ID BIGINT)
RETURNS (
    STATE_ID SMALLINT,
    RAW_RESULT INTEGER)
AS
declare variable V$SQ bigint;
declare variable V$QUESTION_ID bigint;
declare variable V$TYPE smallint;
declare variable V$ORDER smallint;
declare variable V$MAX_SCORE integer;
declare variable V$FLAGS integer;
declare variable V$ATTR_STATE smallint;
declare variable V$T smallint;
declare variable V$GOOD smallint;
declare variable V$BAD smallint;
declare variable V$ALL smallint;
declare variable V$ATTR_VALUE varchar(100);
declare variable V$STR varchar(100);
declare variable V$R smallint;
declare variable V$OBJ_ID bigint;
begin

  STATE_ID = 14;
  RAW_RESULT = 0;

  FOR
      SELECT TVQ.OBJ_ID, Q.OBJ_ID, TSP.Q_TYPE_ID, TSP.Q_ORDER, TSP.Q_MAX_SCORE, Q.FLAGS, COALESCE(BA.ATTR_VALUE, ''), COALESCE(BA.STATE_ID, 0)
      FROM UT_EXAM_TEST_VARS ETV
      JOIN UT_TEST_VAR_QUESTIONS TVQ ON TVQ.VAR_ID = ETV.TEST_VAR_ID AND TVQ.DATE_DEL IS NULL AND TVQ.ORDER_INDEX = 1
      JOIN UT_TEST_STRUCT_POINTS TSP ON TSP.OBJ_ID = TVQ.STRUCT_POINT_ID
      JOIN UT_QUESTIONS Q ON Q.OBJ_ID = TVQ.QUESTION_ID
      LEFT JOIN UT_BLANK_ATTRS BA ON BA.DATE_DEL IS NULL AND BA.BLANK_ID = :I$BLANK_ID AND BA.ATTR_NAME = '@answer[' || TSP.Q_ORDER || ']'
      WHERE ETV.OBJ_ID = :I$VARIANT_ID AND ETV.DATE_DEL IS NULL
      ORDER BY TSP.Q_ORDER
      INTO :V$SQ, :V$QUESTION_ID, :V$TYPE, :V$ORDER, :V$MAX_SCORE, :V$FLAGS, :V$ATTR_VALUE, :V$ATTR_STATE
  DO
  BEGIN

      -- Если есть замена - берем текст ответа и статус из нее
      V$STR = V$ORDER;
      SELECT FIRST 1 BV.ATTR_VALUE, BV.STATE_ID
      FROM UT_BLANK_ATTRS BR
      JOIN UT_BLANK_ATTRS BV ON BV.BLANK_ID = BR.BLANK_ID AND BV.ATTR_NAME = '@spval[' || SUBSTRING(BR.ATTR_NAME FROM 8 FOR CHAR_LENGTH(BR.ATTR_NAME) - 8) || ']' AND BV.STATE_ID > 0
      WHERE BR.DATE_DEL IS NULL AND BR.BLANK_ID = :I$BLANK_ID AND BR.ATTR_NAME STARTING WITH '@spnum[' AND BR.STATE_ID > 0
          AND (BR.ATTR_VALUE = :V$STR OR BR.ATTR_VALUE = '0' || :V$STR)
      ORDER BY BR.ATTR_NAME DESC
      INTO :V$ATTR_VALUE, :V$ATTR_STATE;

      V$GOOD = 0;
      V$BAD = 0;
      V$R = NULL;
      V$ATTR_VALUE = TRIM(V$ATTR_VALUE);

      IF(V$TYPE = 1) THEN
      BEGIN

          -- Тут может быть несколько символов, сверку делаем по каждому. Сколько всего правильных ?
          SELECT COUNT(*)
          FROM UT_ANSWERS A
          WHERE A.DATE_DEL IS NULL AND A.QUESTION_ID = :V$QUESTION_ID AND A.A_LEVEL = 1
          INTO :V$ALL;

          V$STR = V$ATTR_VALUE;

          WHILE(CHAR_LENGTH(V$STR) > 0) DO
          BEGIN

              V$T = 0;
              SELECT FIRST 1 1
              FROM UT_ANSWERS A
              WHERE A.DATE_DEL IS NULL AND A.QUESTION_ID = :V$QUESTION_ID AND A.A_LEVEL = 1 AND A.SORT_ORDER = SUBSTRING(:V$STR FROM 1 FOR 1)
              INTO :V$T;
              V$GOOD = V$GOOD + V$T;

              V$T = 0;
              SELECT FIRST 1 1
              FROM UT_ANSWERS A
              WHERE A.DATE_DEL IS NULL AND A.QUESTION_ID = :V$QUESTION_ID AND A.A_LEVEL = 0 AND A.SORT_ORDER = SUBSTRING(:V$STR FROM 1 FOR 1)
              INTO :V$T;
              V$BAD = V$BAD + V$T;

              V$STR = SUBSTRING(V$STR FROM 2 FOR 1);

          END

          -- Нельзя верифицировать с нейтральным статусом поле, если нет положительных вариантов ответа
          IF(V$ATTR_STATE = 1 AND V$ALL = 0 AND CHAR_LENGTH(V$ATTR_VALUE) > 0) THEN EXCEPTION DATA_ERROR 'Для вопроса ' || V$ORDER || ' не сформированы положительные ключи ответов';

          -- Бит 1 отвечает за возможность неполных ответов
          IF(BIN_AND(V$FLAGS, 2) <> 0) THEN
          BEGIN
              IF(V$GOOD > 0 AND V$BAD = 0) THEN V$R = ROUND(V$MAX_SCORE * V$GOOD / V$ALL);
              ELSE V$R = 0;
          END
          ELSE
          BEGIN
              IF(V$GOOD > 0 AND V$BAD = 0) THEN V$R = V$MAX_SCORE;
              ELSE V$R = 0;
          END

      END
      ELSE IF(V$TYPE = 2) THEN
      BEGIN

          SELECT COUNT(*)
          FROM UT_ANSWERS A
          WHERE A.DATE_DEL IS NULL AND A.QUESTION_ID = :V$QUESTION_ID AND A.A_LEVEL = 1
          INTO :V$ALL;

          -- Нельзя верифицировать с нейтральным статусом
          IF(V$ATTR_STATE = 1 AND V$ALL = 0 AND CHAR_LENGTH(V$ATTR_VALUE) > 0) THEN EXCEPTION DATA_ERROR 'Для вопроса ' || V$ORDER || ' не сформированы положительные ключи ответов';

          SELECT FIRST 1 1
          FROM UT_ANSWERS A
          WHERE A.DATE_DEL IS NULL AND A.QUESTION_ID = :V$QUESTION_ID AND A.A_LEVEL = 1 AND UPPER(TRIM(CAST(A.VARIANT AS VARCHAR(1000)))) = UPPER(TRIM(:V$ATTR_VALUE))
          INTO :V$GOOD;

          SELECT FIRST 1 1
          FROM UT_ANSWERS A
          WHERE A.DATE_DEL IS NULL AND A.QUESTION_ID = :V$QUESTION_ID AND A.A_LEVEL = 0 AND UPPER(TRIM(CAST(A.VARIANT AS VARCHAR(1000)))) = UPPER(TRIM(:V$ATTR_VALUE))
          INTO :V$BAD;

          IF(V$GOOD > 0 AND V$BAD = 0) THEN V$R = V$MAX_SCORE;
          ELSE IF(V$GOOD = 0 AND V$BAD > 0) THEN V$R = 0;
          ELSE IF(CHAR_LENGTH(V$ATTR_VALUE) = 0) THEN V$R = 0;

      END
      ELSE IF(V$TYPE = 3) THEN
      BEGIN
          -- Вопрос типа C, результат не выставляется
          V$ATTR_VALUE = NULL;
      END
      ELSE IF(V$TYPE = 4) THEN
      BEGIN
          -- На соответствие, пока ничего не делаем
      END
      ELSE IF(V$TYPE = 8) THEN
      BEGIN
          -- Аудирование, результат не выставляется
          V$ATTR_VALUE = NULL;
      END
      ELSE EXCEPTION DATA_ERROR 'Системная ошибка. Недопустимый тип вопроса ' || V$TYPE || ' при бумажном тестировании';

      IF(V$BAD > 0 AND V$ATTR_STATE = 2) THEN EXCEPTION DATA_ERROR 'Значение, внесенное как антиключ в вопросе ' || V$ORDER || ', было отмечено как валидное';
      IF(V$GOOD > 0 AND V$ATTR_STATE = 3) THEN EXCEPTION DATA_ERROR 'Значение, внесенное как ключ в вопросе ' || V$ORDER || ', было отмечено как невалидное';

      -- Если хотя бы один вопрос нельзя оценить, отменяем смену статуса бланка и оставляем в статусе 13
      IF(V$R IS NULL) THEN STATE_ID = 13;

      V$OBJ_ID = NULL;
      SELECT FIRST 1 SQ.OBJ_ID
      FROM UT_SESSION_QUESTIONS SQ
      WHERE SQ.SESSION_ID = :I$SESSION_ID AND SQ.DATE_DEL IS NULL AND SQ.QUESTION_ID = :V$SQ
      INTO :V$OBJ_ID;

      IF(V$OBJ_ID IS NULL) THEN
      BEGIN
          INSERT INTO UT_SESSION_QUESTIONS
          (SESSION_ID, QUESTION_ID, ANSWER_DATA, RAW_RESULT, STATE_ID)
          VALUES (:I$SESSION_ID, :V$SQ, :V$ATTR_VALUE, :V$R, IIF(:V$R IS NULL, 30, 1000));
      END
      ELSE
      BEGIN
          UPDATE UT_SESSION_QUESTIONS SQ
          SET SQ.RAW_RESULT = :V$R, SQ.STATE_ID = IIF(:V$R IS NULL, 30, 1000), SQ.ANSWER_DATA = :V$ATTR_VALUE
          WHERE SQ.OBJ_ID = :V$OBJ_ID;
      END

      -- Неотвеченные вопросы идут с нулевым баллом
      RAW_RESULT = RAW_RESULT + COALESCE(V$R, 0);

  END

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_VERIFY_ANSWERS_DICT (
    I$VARIANT_ID BIGINT,
    I$ATTR_NAME VARCHAR(100),
    I$ATTR_VALUE VARCHAR(100),
    I$STATE SMALLINT)
AS
declare variable V$INDEX integer;
declare variable V$Q_ID bigint;
declare variable V$TYPE smallint;
declare variable V$A_ID bigint;
declare variable V$A_LEVEL integer;
declare variable N integer;
begin

  -- ATTR_NAME тут всегда @answer
  I$ATTR_NAME = REPLACE(SUBSTRING(I$ATTR_NAME FROM 9), ']', '');
  WHILE(SUBSTRING(I$ATTR_NAME FROM 1 FOR 1) = '0') DO I$ATTR_NAME = SUBSTRING(I$ATTR_NAME FROM 2);

  BEGIN
      V$INDEX = CAST(I$ATTR_NAME AS INTEGER);
      WHEN ANY DO EXCEPTION DATA_ERROR 'Неверный номер ответа в настройках шаблона, либо в поле замены ответа';
  END

  -- Получаем вопрос
  SELECT FIRST 1 TVQ.QUESTION_ID, TSP.Q_TYPE_ID
  FROM UT_EXAM_TEST_VARS ETV
  JOIN UT_TEST_VARS TV ON TV.OBJ_ID = ETV.TEST_VAR_ID AND TV.DATE_DEL IS NULL
  JOIN UT_TEST_VAR_QUESTIONS TVQ ON TVQ.VAR_ID = TV.OBJ_ID AND TVQ.DATE_DEL IS NULL AND TVQ.ORDER_INDEX = 1
  JOIN UT_TEST_STRUCT_POINTS TSP ON TSP.OBJ_ID = TVQ.STRUCT_POINT_ID AND TSP.Q_ORDER = :V$INDEX
  WHERE ETV.DATE_DEL IS NULL AND ETV.OBJ_ID = :I$VARIANT_ID
  INTO :V$Q_ID, :V$TYPE;
  IF(V$Q_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не удалось найти прототип вопроса ' || V$INDEX;

  IF(V$TYPE = 1) THEN
  BEGIN
      BEGIN
          N = CAST(:I$ATTR_VALUE AS INTEGER);
          WHEN ANY DO EXCEPTION DATA_ERROR 'В ответе может быть только целое число';
      END
      IF(N <= 0 OR N > 20) THEN EXCEPTION DATA_ERROR 'Ответ должен быть числом в диапазоне 1..20';

      -- Ответ = номер варианта ответа
      SELECT A.OBJ_ID, A.A_LEVEL
      FROM UT_ANSWERS A
      WHERE A.DATE_DEL IS NULL AND A.QUESTION_ID = :V$Q_ID AND A.SORT_ORDER = :N
      INTO :V$A_ID, :V$A_LEVEL;

      IF(V$A_ID IS NULL) THEN
      BEGIN
          -- Надо досоздать все промежуточные варианты ответов, чтобы нужная нам позиция была на положенном месте
          INSERT INTO UT_ANSWERS
          (QUESTION_ID, SORT_ORDER, VARIANT, A_LEVEL)
          VALUES (:V$Q_ID, :N, 'Ответ ' || :N, IIF(:I$STATE = 2, 1, 0));

          N = N - 1;
          WHILE(N > 0) DO
          BEGIN
              IF(NOT EXISTS(
                  SELECT FIRST 1 1
                  FROM UT_ANSWERS A
                  WHERE A.DATE_DEL IS NULL AND A.QUESTION_ID = :V$Q_ID AND A.SORT_ORDER = :N
              ))
              THEN
              BEGIN
                  -- Все промежуточные вносим со статусом 2 => должны быть исправлены
                  INSERT INTO UT_ANSWERS
                  (QUESTION_ID, SORT_ORDER, VARIANT, A_LEVEL)
                  VALUES (:V$Q_ID, :N, 'Ответ ' || :N, 2);
              END
              N = N - 1;
          END
      END
      ELSE
      BEGIN
          IF((I$STATE = 2 AND V$A_LEVEL = 0) OR (I$STATE = 3 AND V$A_LEVEL = 1)) THEN EXCEPTION DATA_ERROR 'Нельзя изменить изменить валидность на противоположную';
      END
  END
  ELSE IF(V$TYPE = 2) THEN
  BEGIN
      -- Строка
      SELECT FIRST 1 A.OBJ_ID, A.A_LEVEL
      FROM UT_ANSWERS A
      WHERE A.DATE_DEL IS NULL AND A.QUESTION_ID = :V$Q_ID AND CAST(A.VARIANT AS VARCHAR(1000)) = :I$ATTR_VALUE
      INTO :V$A_ID, :V$A_LEVEL;

      IF(V$A_ID IS NULL) THEN
      BEGIN
          SELECT COALESCE(MAX(A.SORT_ORDER) + 1, 1)
          FROM UT_ANSWERS A
          WHERE A.DATE_DEL IS NULL AND A.QUESTION_ID = :V$Q_ID
          INTO :N;

          INSERT INTO UT_ANSWERS
          (QUESTION_ID, SORT_ORDER, VARIANT, A_LEVEL)
          VALUES (:V$Q_ID, :N, :I$ATTR_VALUE, IIF(:I$STATE = 2, 1, 0));
      END
      ELSE
      BEGIN
          IF((I$STATE = 2 AND V$A_LEVEL = 0) OR (I$STATE = 3 AND V$A_LEVEL = 1)) THEN EXCEPTION DATA_ERROR 'Нельзя изменить изменить валидность на противоположную';
      END
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_VERIFY_ATTR_SUBMIT (
    I$BLANK_ID BIGINT,
    I$USER_ID VARCHAR(40),
    I$ATTR_NAME VARCHAR(40),
    I$ATTR_VALUE VARCHAR(100),
    I$STATE SMALLINT)
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
declare variable V$STATE integer;
declare variable V$USER_ID bigint;
declare variable V$VER_USER_ID bigint;
declare variable V$OBJ_ID bigint;
declare variable V$BLANK_TYPE smallint;
declare variable V$EXAM_ID bigint;
declare variable V$VARIANT_ID bigint;
declare variable N integer;
declare variable QN integer;
declare variable V$Q_ID bigint;
declare variable V$TYPE smallint;
declare variable V$A_ID bigint;
declare variable V$A_LEVEL integer;
begin

  IF(I$USER_ID = 'Веб-администратор') THEN V$USER_ID = 1; ELSE V$USER_ID = CAST(I$USER_ID AS BIGINT);

  -- Доступен ли бланк для обработки ?
  SELECT FIRST 1 B.STATE_ID, B.VER_USER_ID, PT.BLANK_TYPE, P.ED_ID
  FROM UT_BLANKS B
  JOIN UT_PAGE_TEMPLATES PT ON PT.OBJ_ID = B.BLANK_TYPE
  JOIN UT_PACKAGES P ON P.OBJ_ID = B.PACKAGE_ID
  WHERE B.OBJ_ID = :I$BLANK_ID AND B.DATE_DEL IS NULL
  INTO :V$STATE, :V$VER_USER_ID, :V$BLANK_TYPE, :V$EXAM_ID;

  IF(V$STATE IS NULL) THEN EXCEPTION DATA_ERROR 'Бланк не найден';
  IF(V$STATE <> 12) THEN EXCEPTION DATA_ERROR 'Бланк находится в недопустимом статусе. Возможно он уже был проверифицирован с другой станции';
  IF(V$VER_USER_ID <> V$USER_ID) THEN EXCEPTION DATA_ERROR 'Бланк верифицируется другим оператором';

  -- Верифицировать с указанием ключа/антиключа может только ведущий специалист !
  -- Внимание: после указания положительной/отрицательной верификации, сами значения заводим в справочник после квитирования ответа целиком

  SELECT FIRST 1 BA.OBJ_ID
  FROM UT_BLANK_ATTRS BA
  WHERE BA.DATE_DEL IS NULL AND BA.BLANK_ID = :I$BLANK_ID AND BA.ATTR_NAME = :I$ATTR_NAME
  INTO :V$OBJ_ID;

  IF(V$OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Атрибут не найден';

  I$ATTR_VALUE = TRIM(I$ATTR_VALUE);
  IF(I$STATE = 1 AND (I$ATTR_VALUE IS NULL OR I$ATTR_VALUE = '')) THEN
      EXCEPTION DATA_ERROR 'Пустое значение не может быть подтверждено как значение поля, используйте отметку пустого поля';
  ELSE IF(I$STATE = -1 AND I$ATTR_VALUE IS NOT NULL AND I$ATTR_VALUE <> '') THEN
      EXCEPTION DATA_ERROR 'Нельзя подтверждать пустое поле, при наличии текста в поле';

  -- Верификация ключевых полей
  IF(I$ATTR_NAME = '@variant' AND I$STATE = 1) THEN
  BEGIN
      -- Для работ, к которым не приступали, можно задавать пустой номер варианта
      BEGIN
          N = CAST(I$ATTR_VALUE AS INTEGER);
          WHEN ANY DO EXCEPTION DATA_ERROR 'Номер варианта должен быть целым числом';
      END
      IF(N <= 0 OR N > 9999) THEN EXCEPTION DATA_ERROR 'Номер варианта должен быть в диапазоне 1..9999';
      IF(I$STATE NOT IN (0, 1)) THEN EXCEPTION DATA_ERROR 'Недопустимый статус для поля номера варианта';

      SELECT FIRST 1 TV.OBJ_ID
      FROM UT_EXAM_TEST_VARS ETV
      JOIN UT_TEST_VARS TV ON TV.OBJ_ID = ETV.TEST_VAR_ID AND TV.DATE_DEL IS NULL AND TV.NUM = :N
      JOIN UT_TESTS T ON T.OBJ_ID = TV.TEST_ID
      WHERE ETV.DATE_DEL IS NULL AND ETV.EXAM_ID = :V$EXAM_ID
      INTO :V$VARIANT_ID;

      IF(V$VARIANT_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Указанный номер варианта не используется в данном тестировании. Свяжитесь с администратором';
  END
  -- Ключи или антиключи ответов - в справочники пока не вносим, но сверяем
  ELSE IF(SUBSTRING(I$ATTR_NAME FROM 1 FOR 8) = '@answer[' AND I$STATE IN (2, 3)) THEN
  BEGIN
      BEGIN
          N = NULL;
          SELECT ATTR_VALUE
          FROM UT_BLANK_ATTRS BA
          WHERE BA.DATE_DEL IS NULL AND BA.BLANK_ID = :I$BLANK_ID AND BA.ATTR_NAME = '@variant'
          INTO :N;
          WHEN ANY DO EXCEPTION DATA_ERROR 'Ошибка с идентификацией варианта';
      END
      IF(N IS NULL) THEN EXCEPTION DATA_ERROR 'Ошибка с идентификацией варианта';

      -- Номер вопроса
      QN = CAST(REPLACE(SUBSTRING(I$ATTR_NAME FROM 9), ']', '') AS INTEGER);
      -- Получаем ID нужного вопроса в этом варианте
      SELECT FIRST 1 TVQ.QUESTION_ID, TSP.Q_TYPE_ID
      FROM UT_EXAM_TEST_VARS ETV
      JOIN UT_TEST_VARS TV ON TV.OBJ_ID = ETV.TEST_VAR_ID AND TV.DATE_DEL IS NULL AND TV.NUM = :N
      JOIN UT_TEST_VAR_QUESTIONS TVQ ON TVQ.VAR_ID = TV.OBJ_ID AND TVQ.DATE_DEL IS NULL AND TVQ.ORDER_INDEX = 1
      JOIN UT_TEST_STRUCT_POINTS TSP ON TSP.OBJ_ID = TVQ.STRUCT_POINT_ID AND TSP.Q_ORDER = :QN
      WHERE ETV.DATE_DEL IS NULL AND ETV.EXAM_ID = :V$EXAM_ID
      INTO :V$Q_ID, :V$TYPE;
      IF(V$Q_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не удалось найти прототип вопроса ' || QN;

      IF(V$TYPE = 1) THEN
      BEGIN
          BEGIN
              N = CAST(:I$ATTR_VALUE AS INTEGER);
              WHEN ANY DO EXCEPTION DATA_ERROR 'В ответе может быть только целое число';
          END
          IF(N <= 0 OR N > 20) THEN EXCEPTION DATA_ERROR 'Ответ должен быть числом в диапазоне 1..20';

          -- Должен быть номер
          SELECT A.OBJ_ID, A.A_LEVEL
          FROM UT_ANSWERS A
          WHERE A.DATE_DEL IS NULL AND A.QUESTION_ID = :V$Q_ID AND A.SORT_ORDER = :N
          INTO :V$A_ID, :V$A_LEVEL;

          -- Сверяем только если такое значение уже заполнено. Если нет, внесем при заверешении верификации
          IF(V$A_ID IS NOT NULL) THEN
          BEGIN
              IF((I$STATE = 2 AND V$A_LEVEL = 0) OR (I$STATE = 3 AND V$A_LEVEL = 1)) THEN EXCEPTION DATA_ERROR 'Нельзя изменить изменить валидность на противоположную';
          END
      END
      ELSE IF(V$TYPE = 2) THEN
      BEGIN
          -- Строка
          SELECT FIRST 1 A.OBJ_ID, A.A_LEVEL
          FROM UT_ANSWERS A
          WHERE A.DATE_DEL IS NULL AND A.QUESTION_ID = :V$Q_ID AND CAST(A.VARIANT AS VARCHAR(1000)) = :I$ATTR_VALUE
          INTO :V$A_ID, :V$A_LEVEL;

          -- Только если значение уже есть в ключах-антиключах
          IF(V$A_ID IS NOT NULL) THEN
          BEGIN
              IF((I$STATE = 2 AND V$A_LEVEL = 0) OR (I$STATE = 3 AND V$A_LEVEL = 1)) THEN EXCEPTION DATA_ERROR 'Нельзя изменить изменить валидность на противоположную';
          END
      END
  END

  UPDATE UT_BLANK_ATTRS BA
  SET BA.DATE_DEL = CURRENT_TIMESTAMP
  WHERE BA.OBJ_ID = :V$OBJ_ID;

  INSERT INTO UT_BLANK_ATTRS
  (BLANK_ID, ATTR_NAME, ATTR_VALUE, STATE_ID, USER_ID)
  VALUES (:I$BLANK_ID, :I$ATTR_NAME, :I$ATTR_VALUE, :I$STATE, :V$USER_ID);

  -- При получении поля номера варианта выполняем проверку, что такой вариант вообще есть
  -- и возвращаем ключи ответов для данного задания, чтобы автоматически расставить верификацию по ключам и антиключам (только бланки AB)
  IF(I$ATTR_NAME = '@variant' AND V$BLANK_TYPE = 1 AND I$STATE = 1) THEN
  BEGIN
      TAG_NAME = 'questions';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'questions::json&colon;array';
      VAL = 1;
      SUSPEND;

      FOR
          SELECT TAG_NAME, VAL
          FROM UT_VERIFY_QUESTIONS_LIST(:V$VARIANT_ID)
          INTO :TAG_NAME, :VAL
      DO
      BEGIN
          TAG_NAME = 'questions:' || TAG_NAME;
          SUSPEND;
      END
  END

  -- При получении ссылки на следующий бланк проверяем наличие следующего бланка в пакете
  -- !!! вероятно пока не сделано !!!
  IF(I$ATTR_NAME = '@next') THEN
  BEGIN
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_VERIFY_NEXT_TASK (
    I$EXAM_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
declare variable V$USER_ID bigint;
declare variable V$EXAM_ID bigint;
declare variable V$METHOD integer;
declare variable V$PACKAGE_ID bigint;
declare variable V$OBJ_ID bigint;
declare variable V$FILE_ID varchar(40);
declare variable V$BLANK_TYPE bigint;
declare variable V$BLANK_SIDE smallint;
declare variable V$ATTR_NAME varchar(40);
declare variable V$ATTR_VALUE varchar(100);
declare variable V$STATE smallint;
declare variable V$VARIANT_NUM integer;
declare variable V$VARIANT_ID bigint;
declare variable V$BLANK_TT_ID smallint;
begin

  -- Есть ли у пользователя доступ к верификации на данном тестировании ?
  IF(I$USER_ID = 'Веб-администратор') THEN V$USER_ID = 1; ELSE V$USER_ID = CAST(I$USER_ID AS BIGINT);
  -- !!!

  TAG_NAME = 'data';
  VAL = NULL;
  SUSPEND;

  -- Оставить только статус 800 ???
  SELECT D.OBJ_ID, D.METHOD_ID
  FROM UT_EXAM_DATES D
  WHERE D.OBJ_ID = :I$EXAM_ID AND D.DATE_DEL IS NULL AND D.EXAM_STATE IN (600, 700, 800, 900)
  INTO :V$EXAM_ID, :V$METHOD;

  IF(V$METHOD <> 2) THEN EXCEPTION DATA_ERROR 'Тестирование не предполагает работу с бумажными бланками';

  TAG_NAME = 'data:exam_id';
  VAL = V$EXAM_ID;
  SUSPEND;

  -- Разрешено ли в данном тесте и данному пользователю пополнять ключи ?
  TAG_NAME = 'data:kim_keys';
  VAL = '0';
  SUSPEND;

  -- Если тестирование ушло - выдаем пустоту и заканчиваем
  IF(V$EXAM_ID IS NULL) THEN
  BEGIN
      VAL = NULL;
      TAG_NAME = 'data:id';
      SUSPEND;
      TAG_NAME = 'data:packet_id';
      SUSPEND;
      TAG_NAME = 'data:file_id';
      SUSPEND;
      TAG_NAME = 'data:questions';
      SUSPEND;
      TAG_NAME = 'data:attributes';
      SUSPEND;
      EXIT;
  END

  -- Выбираем из отсканированных пакетов, и еще не обработанных бланков
  SELECT FIRST 1 P.OBJ_ID, B.OBJ_ID, B.FILE_ID, B.BLANK_TYPE, B.BLANK_SIDE, PT.BLANK_TYPE
  FROM UT_PACKAGES P
  JOIN UT_BLANKS B ON B.PACKAGE_ID = P.OBJ_ID AND B.STATE_ID IN (11, 12) AND (B.VER_USER_ID IS NULL OR B.VER_USER_ID = :V$USER_ID)
  JOIN UT_PAGE_TEMPLATES PT ON PT.OBJ_ID = B.BLANK_TYPE
  WHERE P.ED_ID = :I$EXAM_ID AND P.DATE_DEL IS NULL AND P.STATE_ID = 10
  ORDER BY B.DATE_MODIFY
  INTO :V$PACKAGE_ID, :V$OBJ_ID, :V$FILE_ID, :V$BLANK_TYPE, :V$BLANK_SIDE, :V$BLANK_TT_ID;

  IF(V$OBJ_ID IS NOT NULL) THEN
  BEGIN
      UPDATE UT_BLANKS B
      SET B.STATE_ID = 12, B.VER_USER_ID = :V$USER_ID, B.DATE_MODIFY = CURRENT_TIMESTAMP
      WHERE B.OBJ_ID = :V$OBJ_ID AND B.STATE_ID IN (11, 12) AND (B.VER_USER_ID IS NULL OR B.VER_USER_ID = :V$USER_ID);
  END

  TAG_NAME = 'data:id';
  VAL = V$OBJ_ID;
  SUSPEND;

  TAG_NAME = 'data:packet_id';
  VAL = V$PACKAGE_ID;
  SUSPEND;

  TAG_NAME = 'data:file_id';
  VAL = V$FILE_ID;
  SUSPEND;

  TAG_NAME = 'data:template_id';
  VAL = V$BLANK_TYPE;
  SUSPEND;

  TAG_NAME = 'data:side';
  VAL = V$BLANK_SIDE;
  SUSPEND;

  -- Для бланка C смотрим номер варианта, указанный в бланке AB, если вдруг забыли вписать
  TAG_NAME = 'data:parent_variant_num';
  VAL = NULL;
  IF(V$BLANK_TT_ID = 2) THEN
  BEGIN
      SELECT FIRST 1 BA.ATTR_VALUE
      FROM UT_PACKAGES P
      JOIN UT_BLANKS B ON B.DATE_DEL IS NULL AND B.PACKAGE_ID = P.OBJ_ID AND B.NEXT_BLANK_ID = :V$OBJ_ID
      JOIN UT_BLANK_ATTRS BA ON BA.DATE_DEL IS NULL AND BA.BLANK_ID = B.OBJ_ID AND BA.ATTR_NAME = '@variant'
      WHERE P.DATE_DEL IS NULL AND P.ED_ID = :I$EXAM_ID
      INTO :VAL;
  END
  SUSPEND;

  -- Возвращаем распознанные поля - шаблон будет разбираться в основном коде, и подкладываться к полям
  V$VARIANT_NUM = 0;

  TAG_NAME = 'data:attributes';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'data:attributes::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
      SELECT A.ATTR_NAME, A.ATTR_VALUE, A.STATE_ID
      FROM UT_BLANK_ATTRS A
      WHERE A.BLANK_ID = :V$OBJ_ID AND A.DATE_DEL IS NULL
      ORDER BY 1
      INTO :V$ATTR_NAME, :V$ATTR_VALUE, :V$STATE
  DO
  BEGIN
      TAG_NAME = 'data:attributes:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'data:attributes:r:name';
      VAL = V$ATTR_NAME;
      SUSPEND;
      TAG_NAME = 'data:attributes:r:value';
      VAL = V$ATTR_VALUE;
      SUSPEND;
      TAG_NAME = 'data:attributes:r:state';
      VAL = V$STATE;
      SUSPEND;
      IF(V$ATTR_NAME = '@variant' AND V$STATE = 1) THEN V$VARIANT_NUM = CAST(V$ATTR_VALUE AS INTEGER);
  END

  -- Если уже начата верификация и есть номер варианта, возвращаем данные вопросов
  TAG_NAME = 'data:questions';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'data:questions::json&colon;array';
  VAL = 1;
  SUSPEND;

  IF(V$VARIANT_NUM IS NOT NULL) THEN
  BEGIN
      SELECT FIRST 1 TV.OBJ_ID
      FROM UT_EXAM_TEST_VARS ETV
      JOIN UT_TEST_VARS TV ON TV.OBJ_ID = ETV.TEST_VAR_ID AND TV.DATE_DEL IS NULL AND TV.NUM = :V$VARIANT_NUM
      JOIN UT_TESTS T ON T.OBJ_ID = TV.TEST_ID
      WHERE ETV.DATE_DEL IS NULL AND ETV.EXAM_ID = :V$EXAM_ID
      INTO :V$VARIANT_ID;

      FOR
          SELECT TAG_NAME, VAL
          FROM UT_VERIFY_QUESTIONS_LIST(:V$VARIANT_ID)
          INTO :TAG_NAME, :VAL
      DO
      BEGIN
          TAG_NAME = 'data:questions:' || TAG_NAME;
          SUSPEND;
      END
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_VERIFY_QUESTIONS_LIST (
    I$VARIANT_ID BIGINT)
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
declare variable V$STRUCT_ID bigint;
declare variable V$POINT_ID bigint;
declare variable V$NUM integer;
declare variable V$TYPE smallint;
declare variable V$CS_NAME varchar(100);
declare variable V$CHARSET varchar(100);
declare variable V$QUESTION_ID bigint;
declare variable V$FLAGS integer;
declare variable V$FLAG smallint;
declare variable V$ORDER smallint;
declare variable V$ANSWER_ID bigint;
begin

    SELECT FIRST 1 T.STRUCT_ID
    FROM UT_TEST_VARS TV
    JOIN UT_TESTS T ON T.OBJ_ID = TV.TEST_ID
    WHERE TV.OBJ_ID = :I$VARIANT_ID
    INTO :V$STRUCT_ID;

    FOR
        SELECT P.OBJ_ID, P.Q_ORDER, COALESCE(C.LANG_CODE, 'digits'), P.Q_TYPE_ID, COALESCE(C.OBJ_NAME, 'Цифры')
        FROM UT_TEST_STRUCT_POINTS P
        LEFT JOIN UT_CHARSETS C ON C.OBJ_ID = P.CHARSET_ID
        -- Вопросы на соответствие тоже тут разрешаем
        WHERE P.STRUCT_ID = :V$STRUCT_ID AND P.DATE_DEL IS NULL AND P.Q_TYPE_ID IN (1, 2, 4)
        ORDER BY P.Q_ORDER
        INTO :V$POINT_ID, :V$NUM, :V$CHARSET, :V$TYPE, :V$CS_NAME
    DO
    BEGIN
        TAG_NAME = 'r';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'r:num';
        VAL = V$NUM;
        SUSPEND;
        TAG_NAME = 'r:charset';
        VAL = V$CHARSET;
        SUSPEND;
        TAG_NAME = 'r:csname';
        VAL = V$CS_NAME;
        SUSPEND;
        TAG_NAME = 'r:type';
        VAL = V$TYPE;
        SUSPEND;

        TAG_NAME = 'r:question';
        V$QUESTION_ID = NULL;
        VAL = NULL;
        SELECT FIRST 1 Q.OBJ_ID, Q.OBJ_NAME, COALESCE(Q.FLAGS, 0)
        FROM UT_TEST_VAR_QUESTIONS VQ
        JOIN UT_QUESTIONS Q ON Q.OBJ_ID = VQ.QUESTION_ID
        WHERE VQ.VAR_ID = :I$VARIANT_ID AND VQ.STRUCT_POINT_ID = :V$POINT_ID AND VQ.DATE_DEL IS NULL
        INTO :V$QUESTION_ID, :VAL, :V$FLAGS;
        SUSPEND;

        TAG_NAME = 'r:flags';
        VAL = V$FLAGS;
        SUSPEND;

        TAG_NAME = 'r:keyvals';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'r:keyvals::json&colon;array';
        VAL = 1;
        SUSPEND;

        -- Списки ключей и антиключей
        IF(V$TYPE IN (1, 2)) THEN
        BEGIN
            FOR
                SELECT A.OBJ_ID, A.A_LEVEL, A.SORT_ORDER
                FROM UT_ANSWERS A
                WHERE A.QUESTION_ID = :V$QUESTION_ID AND A.DATE_DEL IS NULL
                ORDER BY A.SORT_ORDER
                INTO :V$ANSWER_ID, :V$FLAG, :V$ORDER
            DO
            BEGIN
                TAG_NAME = 'r:keyvals:r';
                VAL = NULL;
                SUSPEND;
                TAG_NAME = 'r:keyvals:r:type';
                VAL = V$FLAG;
                SUSPEND;
                TAG_NAME = 'r:keyvals:r:value';
                -- Для вопросов типа А передаем порядковый номер, для вопросов типа B - текст
                IF(V$TYPE = 1) THEN VAL = V$ORDER;
                ELSE VAL = (SELECT CAST(A.VARIANT AS VARCHAR(4000)) FROM UT_ANSWERS A WHERE A.OBJ_ID = :V$ANSWER_ID);
                SUSPEND;
            END
        END
        -- Вопросы на соответствие обрабатываем отдельно, здесь нужно передать упорядоченный список пар значений
        ELSE IF(V$TYPE = 4) THEN
        BEGIN
        END
    END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_VERIFY_RUN_C (
    I$EXAM_ID BIGINT,
    I$BLANK_ID BIGINT)
AS
declare variable N integer;
declare variable V$SIDE smallint;
declare variable V$TYPE smallint;
declare variable V$NEXT_ID bigint;
declare variable V$SESSION_ID bigint;
declare variable V$T_SESSION bigint;
declare variable V$STATE smallint;
declare variable V$QUESTION_ID bigint;
declare variable V$QS_ID bigint;
begin

  N = 0;

  SELECT FIRST 1 B.STATE_ID,B.BLANK_SIDE, PT.BLANK_TYPE, B.NEXT_BLANK_ID, B.SESSION_ID
  FROM UT_BLANKS B
  JOIN UT_PAGE_TEMPLATES PT ON PT.OBJ_ID = B.BLANK_TYPE
  WHERE B.OBJ_ID = :I$BLANK_ID AND B.DATE_DEL IS NULL
  INTO :V$STATE, :V$SIDE, :V$TYPE, :V$NEXT_ID, :V$SESSION_ID;

  -- Что-то не срослось
  IF(V$STATE IS NULL OR V$STATE <> 13) THEN EXIT;

  -- Если это бланк AB - спускаемся до лицевой стороны бланка типа C, при этом номер сессии оставляем как был
  IF(V$TYPE = 1) THEN
  BEGIN
      V$STATE = NULL;

      SELECT FIRST 1 B.OBJ_ID, B.STATE_ID, B.BLANK_SIDE, PT.BLANK_TYPE, B.NEXT_BLANK_ID
      FROM UT_PACKAGES P
      JOIN UT_BLANKS B ON B.DATE_DEL IS NULL AND B.OBJ_ID = :V$NEXT_ID AND B.BLANK_SIDE = 0
      JOIN UT_PAGE_TEMPLATES PT ON PT.OBJ_ID = B.BLANK_TYPE AND PT.BLANK_TYPE = 2
      WHERE P.DATE_DEL IS NULL AND P.ED_ID = :I$EXAM_ID
      INTO :I$BLANK_ID, :V$STATE, :V$SIDE, :V$TYPE, :V$NEXT_ID;

      -- Что-то не срослось
      IF(V$STATE IS NULL OR V$STATE <> 13) THEN EXIT;
  END
  -- Для оборотной стороны бланка типа C и дополнительных бланков идем по цепочке вверх до лицевой стороны бланка типа C
  ELSE IF(V$TYPE <> 2 OR V$SIDE <> 0) THEN
  BEGIN
      WHILE(V$TYPE <> 2 AND V$SIDE <> 0) DO
      BEGIN
          V$STATE = NULL;

          SELECT FIRST 1 B.OBJ_ID, B.STATE_ID, B.BLANK_SIDE, PT.BLANK_TYPE, B.NEXT_BLANK_ID, B.SESSION_ID
          FROM UT_PACKAGES P
          JOIN UT_BLANKS B ON B.DATE_DEL IS NULL AND B.NEXT_BLANK_ID = :I$BLANK_ID
          JOIN UT_PAGE_TEMPLATES PT ON PT.OBJ_ID = B.BLANK_TYPE AND PT.BLANK_TYPE IN (2, 3)
          WHERE P.DATE_DEL IS NULL AND P.ED_ID = :I$EXAM_ID
          INTO :I$BLANK_ID, :V$STATE, :V$SIDE, :V$TYPE, :V$NEXT_ID, :V$T_SESSION;

          -- Что-то не срослось
          IF(V$STATE IS NULL OR V$STATE <> 13) THEN EXIT;
          -- Если достигли лицевой стороны бланка C, в ней может быть сессия
          IF(V$T_SESSION IS NOT NULL AND V$TYPE = 2 AND V$SIDE = 0) THEN V$SESSION_ID = V$T_SESSION;

          N = N + 1;
          IF(N > 100) THEN EXCEPTION DATA_ERROR 'Где-то произошло зацикливание ссылок бланков';
      END
  END

  -- Если у нас еще нет id сессии, т.е. не перешли с бланка AB - досматриваем id сессии из бланка AB
  IF(V$SESSION_ID IS NULL AND V$TYPE = 2) THEN
  BEGIN
      V$STATE = NULL;

      SELECT FIRST 1 B.STATE_ID, B.SESSION_ID
      FROM UT_PACKAGES P
      JOIN UT_BLANKS B ON B.DATE_DEL IS NULL AND B.NEXT_BLANK_ID = :I$BLANK_ID
      JOIN UT_PAGE_TEMPLATES PT ON PT.OBJ_ID = B.BLANK_TYPE AND PT.BLANK_TYPE = 1
      WHERE P.DATE_DEL IS NULL AND P.ED_ID = :I$EXAM_ID
      INTO :V$STATE, :V$SESSION_ID;

      -- Что-то не срослось
      IF(V$STATE IS NULL OR V$STATE <> 13 OR V$SESSION_ID IS NULL) THEN EXIT;
  END

  -- Спускаемся вниз по цепочке и проверяем, все ли бланки прошли верификацию
  N = 0;

  WHILE(V$NEXT_ID IS NOT NULL) DO
  BEGIN

      V$STATE = NULL;

      SELECT FIRST 1 B.STATE_ID, B.NEXT_BLANK_ID
      FROM UT_PACKAGES P
      JOIN UT_BLANKS B ON B.DATE_DEL IS NULL AND B.OBJ_ID = :V$NEXT_ID
      JOIN UT_PAGE_TEMPLATES PT ON PT.OBJ_ID = B.BLANK_TYPE AND PT.BLANK_TYPE IN (2, 3)
      WHERE P.DATE_DEL IS NULL AND P.ED_ID = :I$EXAM_ID
      INTO :V$STATE, :V$NEXT_ID;

      N = N + 1;
      IF(N > 100) THEN EXCEPTION DATA_ERROR 'Где-то произошло зацикливание ссылок бланков';
  END

  -- Если таки дошли сюда - все ок, можно запускать проверку
  -- Внимание: возможен вариант с нескольмими вопросами типа C (вопросы типа V тут попасть не могут)
  FOR
      SELECT TVQ.OBJ_ID, SQ.OBJ_ID
      FROM UT_SESSIONS S
      JOIN UT_EXAM_TEST_VARS ETV ON ETV.OBJ_ID = S.VARIANT_ID
      JOIN UT_TEST_VARS TV ON TV.OBJ_ID = ETV.TEST_VAR_ID
      JOIN UT_TEST_VAR_QUESTIONS TVQ ON TVQ.VAR_ID = TV.OBJ_ID AND TVQ.DATE_DEL IS NULL -- мультивопроса тут быть не должно !
      JOIN UT_TEST_STRUCT_POINTS TSP ON TSP.OBJ_ID = TVQ.STRUCT_POINT_ID AND TSP.Q_TYPE_ID = 3
      LEFT JOIN UT_SESSION_QUESTIONS SQ ON SQ.SESSION_ID = S.OBJ_ID AND SQ.DATE_DEL IS NULL AND SQ.QUESTION_ID = TVQ.OBJ_ID
      WHERE S.OBJ_ID = :V$SESSION_ID
      ORDER BY TSP.Q_ORDER
      INTO :V$QUESTION_ID, :V$QS_ID
  DO
  BEGIN
      IF(V$QS_ID IS NULL) THEN
      BEGIN
          INSERT INTO UT_SESSION_QUESTIONS
          (SESSION_ID, QUESTION_ID, STATE_ID)
          VALUES (:V$SESSION_ID, :V$QUESTION_ID, 21);
      END
  END

  -- И далее разом меняем статус всех вопросов на 30
  UPDATE UT_SESSION_QUESTIONS SQ
  SET SQ.STATE_ID = 30
  WHERE SQ.SESSION_ID = :V$SESSION_ID AND SQ.DATE_DEL IS NULL AND SQ.STATE_ID = 21;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_VERIFY_TASK_ASCLEAN (
    I$BLANK_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$USER_ID bigint;
declare variable V$VER_USER_ID bigint;
declare variable V$STATE integer;
begin

  IF(I$USER_ID = 'Веб-администратор') THEN V$USER_ID = 1; ELSE V$USER_ID = CAST(I$USER_ID AS BIGINT);

  -- Доступен ли бланк для обработки ?
  SELECT FIRST 1 B.STATE_ID, B.VER_USER_ID
  FROM UT_BLANKS B
  WHERE B.OBJ_ID = :I$BLANK_ID AND B.DATE_DEL IS NULL
  INTO :V$STATE, :V$VER_USER_ID;

  IF(V$STATE IS NULL) THEN EXCEPTION DATA_ERROR 'Бланк не найден';
  IF(V$STATE <> 12) THEN EXCEPTION DATA_ERROR 'Бланк находится в недопустимом статусе. Возможно он уже был проверифицирован с другой станции';
  IF(V$VER_USER_ID <> V$USER_ID) THEN EXCEPTION DATA_ERROR 'Бланк верифицируется другим оператором';

  -- Не допускаем обнуление бланка при наличии подтвержденных полей @answer
  IF(EXISTS(
      SELECT FIRST 1 1
      FROM UT_BLANK_ATTRS BA
      WHERE BA.BLANK_ID = :I$BLANK_ID AND BA.DATE_DEL IS NULL AND BA.STATE_ID > 1
  )) THEN EXCEPTION DATA_ERROR 'Нельзя отметить бланк как чистый при наличии верифицированных полей';

  -- Фиксируем статус
  UPDATE UT_BLANKS B
  SET B.STATE_ID = 16
  WHERE B.OBJ_ID = :I$BLANK_ID AND B.STATE_ID = 12;

  OBJ_ID = I$BLANK_ID;

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_VERIFY_TASK_ASINC (
    I$BLANK_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$USER_ID bigint;
declare variable V$VER_USER_ID bigint;
declare variable V$STATE integer;
begin

  IF(I$USER_ID = 'Веб-администратор') THEN V$USER_ID = 1; ELSE V$USER_ID = CAST(I$USER_ID AS BIGINT);

  -- Доступен ли бланк для обработки ?
  SELECT FIRST 1 B.STATE_ID, B.VER_USER_ID
  FROM UT_BLANKS B
  WHERE B.OBJ_ID = :I$BLANK_ID AND B.DATE_DEL IS NULL
  INTO :V$STATE, :V$VER_USER_ID;

  IF(V$STATE IS NULL) THEN EXCEPTION DATA_ERROR 'Бланк не найден';
  IF(V$STATE <> 12) THEN EXCEPTION DATA_ERROR 'Бланк находится в недопустимом статусе. Возможно он уже был проверифицирован с другой станции';
  IF(V$VER_USER_ID <> V$USER_ID) THEN EXCEPTION DATA_ERROR 'Бланк верифицируется другим оператором';

  -- При аннулировании все поля должны быть верифицированы
  IF(EXISTS(
      SELECT FIRST 1 1
      FROM UT_BLANK_ATTRS BA
      WHERE BA.BLANK_ID = :I$BLANK_ID AND BA.DATE_DEL IS NULL AND BA.STATE_ID = 0 AND
          (BA.ATTR_NAME = '@variant')
  )) THEN EXCEPTION DATA_ERROR 'При аннулировании бланка должны быть верифицированы обязательные поля (...)';

  -- Фиксируем статус
  UPDATE UT_BLANKS B
  SET B.STATE_ID = 17
  WHERE B.OBJ_ID = :I$BLANK_ID AND B.STATE_ID = 12;

  OBJ_ID = I$BLANK_ID;

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_VERIFY_TASK_DEFER (
    I$BLANK_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$USER_ID bigint;
declare variable V$VER_USER_ID bigint;
declare variable V$STATE integer;
begin

  IF(I$USER_ID = 'Веб-администратор') THEN V$USER_ID = 1; ELSE V$USER_ID = CAST(I$USER_ID AS BIGINT);

  -- Доступен ли бланк для обработки ?
  SELECT FIRST 1 B.STATE_ID, B.VER_USER_ID
  FROM UT_BLANKS B
  WHERE B.OBJ_ID = :I$BLANK_ID AND B.DATE_DEL IS NULL
  INTO :V$STATE, :V$VER_USER_ID;

  IF(V$STATE IS NULL) THEN EXCEPTION DATA_ERROR 'Бланк не найден';
  IF(V$STATE <> 12) THEN EXCEPTION DATA_ERROR 'Бланк находится в недопустимом статусе. Возможно он уже был проверифицирован с другой станции';
  IF(V$VER_USER_ID <> V$USER_ID) THEN EXCEPTION DATA_ERROR 'Бланк верифицируется другим оператором';

  -- Корректируем метку времени, статус не трогаем
  UPDATE UT_BLANKS B
  SET B.DATE_MODIFY = CURRENT_TIMESTAMP
  WHERE B.OBJ_ID = :I$BLANK_ID AND B.STATE_ID = 12;

  OBJ_ID = I$BLANK_ID;

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_VERIFY_TASK_FORWARD (
    I$BLANK_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$USER_ID bigint;
declare variable V$VER_USER_ID bigint;
declare variable V$STATE integer;
begin

  IF(I$USER_ID = 'Веб-администратор') THEN V$USER_ID = 1; ELSE V$USER_ID = CAST(I$USER_ID AS BIGINT);

  -- Доступен ли бланк для обработки ?
  SELECT FIRST 1 B.STATE_ID, B.VER_USER_ID
  FROM UT_BLANKS B
  WHERE B.OBJ_ID = :I$BLANK_ID AND B.DATE_DEL IS NULL
  INTO :V$STATE, :V$VER_USER_ID;

  IF(V$STATE IS NULL) THEN EXCEPTION DATA_ERROR 'Бланк не найден';
  IF(V$STATE <> 12) THEN EXCEPTION DATA_ERROR 'Бланк находится в недопустимом статусе. Возможно он уже был проверифицирован с другой станции';
  IF(V$VER_USER_ID <> V$USER_ID) THEN EXCEPTION DATA_ERROR 'Бланк верифицируется другим оператором';

  -- Корректируем привязку пользователя
  /*UPDATE UT_BLANKS B
  SET B.VER_USER_ID =
  WHERE B.OBJ_ID = :I$BLANK_ID AND B.STATE_ID = 12;*/

  OBJ_ID = I$BLANK_ID;

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE UT_VERIFY_TASK_SUBMIT (
    I$BLANK_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$USER_ID bigint;
declare variable V$VER_USER_ID bigint;
declare variable V$EXAM_ID bigint;
declare variable V$STATE integer;
declare variable V$STRUCT_ID bigint;
declare variable V$BLANK_TYPE smallint;
declare variable V$SIDE smallint;
declare variable V$IS_DS smallint;
declare variable V$MAX_N integer;
declare variable V$ATTR_ID bigint;
declare variable V$N integer;
declare variable V$ATTR_NAME varchar(100);
declare variable V$SESSION_ID bigint;
declare variable V$VARIANT_ID bigint;
declare variable V$PERSON_ID bigint;
declare variable V$BARCODE varchar(128);
declare variable V$NEXT_ID bigint;
declare variable V$CONTEXT varchar(100);
declare variable V$NEXT_STATE smallint;
declare variable V$NEXT_SESSION bigint;
declare variable V$HAS_AB smallint;
declare variable V$RUN_C smallint;
declare variable V$PPE_ID bigint;
declare variable V$LOCAL_ID varchar(128);
declare variable V$RAW_RESULT integer;
declare variable V$SESSION_RESULT integer;
begin

  IF(I$USER_ID = 'Веб-администратор') THEN V$USER_ID = 1; ELSE V$USER_ID = CAST(I$USER_ID AS BIGINT);

  -- Доступен ли бланк для обработки ?
  SELECT FIRST 1 B.STATE_ID, B.VER_USER_ID, T.STRUCT_ID, B.BLANK_SIDE, PT.BLANK_TYPE, PT.IS_DS, D.OBJ_ID, B.SESSION_ID, B.BARCODE_DATA, P.PPE_ID, S.RAW_RESULT
  FROM UT_BLANKS B
  JOIN UT_PAGE_TEMPLATES PT ON PT.OBJ_ID = B.BLANK_TYPE
  JOIN UT_PACKAGES P ON P.OBJ_ID = B.PACKAGE_ID
  JOIN UT_EXAM_DATES D ON D.OBJ_ID = P.ED_ID
  JOIN UT_EXAM_TEST_VARS ETV ON ETV.EXAM_ID = D.OBJ_ID AND ETV.DATE_DEL IS NULL
  JOIN UT_TEST_VARS TV ON TV.OBJ_ID = ETV.TEST_VAR_ID
  JOIN UT_TESTS T ON T.OBJ_ID = TV.TEST_ID
  LEFT JOIN UT_SESSIONS S ON S.OBJ_ID = B.SESSION_ID
  WHERE B.OBJ_ID = :I$BLANK_ID AND B.DATE_DEL IS NULL
  INTO :V$STATE, :V$VER_USER_ID, :V$STRUCT_ID, :V$SIDE, :V$BLANK_TYPE, :V$IS_DS, :V$EXAM_ID, :V$SESSION_ID, :V$BARCODE, :V$PPE_ID, :V$SESSION_RESULT;

  IF(V$STATE IS NULL) THEN EXCEPTION DATA_ERROR 'Бланк не найден';
  IF(V$STATE <> 12) THEN EXCEPTION DATA_ERROR 'Бланк находится в недопустимом статусе. Возможно он уже был проверифицирован с другой станции';
  IF(V$VER_USER_ID <> V$USER_ID) THEN EXCEPTION DATA_ERROR 'Бланк верифицируется другим оператором';

  V$RUN_C = 0;

  -- Если есть поле @variant, проверяем что оно верифицировано, а также сверяем с номерами вариантов
  V$STATE = NULL;
  SELECT FIRST 1 BA.STATE_ID, BA.ATTR_VALUE
  FROM UT_BLANK_ATTRS BA
  WHERE BA.BLANK_ID = :I$BLANK_ID AND BA.DATE_DEL IS NULL AND BA.ATTR_NAME = '@variant'
  INTO :V$STATE, :V$ATTR_NAME;

  IF(V$STATE IS NOT NULL) THEN
  BEGIN
      IF(V$STATE = -1) THEN
      BEGIN
      END
      ELSE IF(V$STATE = 1) THEN
      BEGIN
          V$N = CAST(V$ATTR_NAME AS INTEGER);

          SELECT FIRST 1 ETV.OBJ_ID
          FROM UT_EXAM_TEST_VARS ETV
          JOIN UT_TEST_VARS TV ON TV.OBJ_ID = ETV.TEST_VAR_ID AND TV.NUM = :V$N
          WHERE ETV.EXAM_ID = :V$EXAM_ID AND ETV.DATE_DEL IS NULL
          INTO :V$VARIANT_ID;

          IF(V$VARIANT_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Указанный номер варианта не назначен в данном тестировании';
      END
      ELSE EXCEPTION DATA_ERROR 'Поле номера варианта должно быть верифицировано';
  END

  -- Если есть код следующего бланка - указанный код бланка должен находиться в системе, т.е. быть уже обработан
  -- Сразу же прописываем цепочку связей
  V$STATE = NULL;
  SELECT FIRST 1 BA.STATE_ID, BA.ATTR_VALUE
  FROM UT_BLANK_ATTRS BA
  WHERE BA.BLANK_ID = :I$BLANK_ID AND BA.DATE_DEL IS NULL AND BA.ATTR_NAME = '@next'
  INTO :V$STATE, :V$ATTR_NAME;

  IF(V$STATE IS NOT NULL) THEN
  BEGIN
      IF(V$STATE NOT IN (-1, 1)) THEN EXCEPTION DATA_ERROR 'Поле номера следующего бланка должно быть верифицировано или отмечено как пустое';

      IF(V$ATTR_NAME <> '') THEN
      BEGIN
          IF(V$VARIANT_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Нельзя указывать следующий бланк, если бланк отмечен как чистый';

          SELECT FIRST 1 B.OBJ_ID
          FROM UT_PACKAGES P
          JOIN UT_BLANKS B ON B.DATE_DEL IS NULL AND B.PACKAGE_ID = P.OBJ_ID AND B.BARCODE_DATA = :V$ATTR_NAME AND B.BLANK_SIDE = 0
          -- Ограничиваем варианты ввода только дополнительными бланками, и только лицевой стороной
          JOIN UT_PAGE_TEMPLATES PT ON PT.OBJ_ID = B.BLANK_TYPE AND PT.BLANK_TYPE = 3
          WHERE P.DATE_DEL IS NULL AND P.ED_ID = :V$EXAM_ID
          INTO :V$NEXT_ID;

          -- Если не нашли по полному формату, проверяем укороченный CODE39
          IF(V$NEXT_ID IS NULL) THEN
          BEGIN
              V$LOCAL_ID = SUBSTRING(V$BARCODE FROM 1 FOR 2) || '3' || SUBSTRING(V$BARCODE FROM 4 FOR 8) || V$ATTR_NAME;
              V$LOCAL_ID = V$LOCAL_ID || (SELECT VAL FROM UT_CHECKSUM_EAN39(:V$LOCAL_ID));

              SELECT FIRST 1 B.OBJ_ID
              FROM UT_PACKAGES P
              JOIN UT_BLANKS B ON B.DATE_DEL IS NULL AND B.PACKAGE_ID = P.OBJ_ID AND B.BARCODE_DATA = :V$LOCAL_ID AND B.BLANK_SIDE = 0
              -- Ограничиваем варианты ввода только дополнительными бланками, и только лицевой стороной
              JOIN UT_PAGE_TEMPLATES PT ON PT.OBJ_ID = B.BLANK_TYPE AND PT.BLANK_TYPE = 3
              WHERE P.DATE_DEL IS NULL AND P.ED_ID = :V$EXAM_ID
              INTO :V$NEXT_ID;
          END

          IF(V$NEXT_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Дополнительный бланк с кодом "' || V$ATTR_NAME || '" не найден в системе. Проверьте правильность верификации. Если все верно, отложите верификацию и сообщите администратору';
      END
  END
  ELSE
  BEGIN

      -- Для бланка типа AB связь AB -> C, а также для двусторонних бланков указываем связь автоматически
      -- Форматы бланков:
      -- EAN13:  2yteePPPPPPP
      -- CODE39: yyteeeessssPPPPPPPz
      V$ATTR_NAME = NULL;
      IF(V$BLANK_TYPE = 1) THEN
      BEGIN
          IF(EXISTS(
              SELECT FIRST 1 1
              FROM UT_TEST_STRUCT_POINTS SP
              WHERE SP.STRUCT_ID = :V$STRUCT_ID AND SP.DATE_DEL IS NULL AND SP.Q_TYPE_ID = 3
          ))
          THEN
          BEGIN
              IF(CHAR_LENGTH(V$BARCODE) = 13) THEN
                  V$ATTR_NAME = SUBSTRING(V$BARCODE FROM 1 FOR 2) || '2' || SUBSTRING(V$BARCODE FROM 4 FOR 9);
              ELSE IF(CHAR_LENGTH(V$BARCODE) IN (18, 19)) THEN
                  V$ATTR_NAME = SUBSTRING(V$BARCODE FROM 1 FOR 2) || '2' || SUBSTRING(V$BARCODE FROM 4 FOR 15);
              V$CONTEXT = 'Следующий бланк типа C';
          END
      END
      ELSE IF(V$BLANK_TYPE = 2 AND V$SIDE = 0 AND V$IS_DS = 1) THEN
      BEGIN
          -- Ссылка на обратную сторону бланка типа C
          V$ATTR_NAME = SUBSTRING(V$BARCODE FROM 1 FOR 3) || '00' || SUBSTRING(V$BARCODE FROM 6 FOR 7);
          V$CONTEXT = 'Оборотная сторона бланка типа C';
      END
      ELSE IF(V$BLANK_TYPE = 3 AND V$SIDE = 0 AND V$IS_DS = 1) THEN
      BEGIN
          -- Ссылка на обратную сторону бланка типа C дополнительный
          V$ATTR_NAME = SUBSTRING(V$BARCODE FROM 1 FOR 3) || '00' || SUBSTRING(V$BARCODE FROM 6 FOR 7);
          V$CONTEXT = 'Оборотная сторона дополнительного бланка типа C';
      END

      IF(V$ATTR_NAME IS NOT NULL) THEN
      BEGIN
          IF(CHAR_LENGTH(V$ATTR_NAME) <= 13) THEN V$ATTR_NAME = V$ATTR_NAME || (SELECT VAL FROM UT_CHECKSUM_EAN13(:V$ATTR_NAME));
          ELSE IF(CHAR_LENGTH(V$ATTR_NAME) <= 18) THEN V$ATTR_NAME = V$ATTR_NAME || (SELECT VAL FROM UT_CHECKSUM_EAN39(:V$ATTR_NAME));

          SELECT FIRST 1 B.OBJ_ID
          FROM UT_PACKAGES P
          JOIN UT_BLANKS B ON B.DATE_DEL IS NULL AND B.PACKAGE_ID = P.OBJ_ID AND B.BARCODE_DATA = :V$ATTR_NAME
          WHERE P.DATE_DEL IS NULL AND P.ED_ID = :V$EXAM_ID
          INTO :V$NEXT_ID;

          IF(V$NEXT_ID IS NULL) THEN EXCEPTION DATA_ERROR V$CONTEXT || ' с кодом "' || V$ATTR_NAME || '" не найден в системе, проверьте состав пакетов';
      END

  END

  -- В бланках AB отмечаем как чистые все оставшиеся поля answer, которые выходят за пределы сетки структуры
  IF(V$BLANK_TYPE = 1) THEN
  BEGIN
      SELECT MAX(SP.Q_ORDER)
      FROM UT_TEST_STRUCT_POINTS SP
      WHERE SP.DATE_DEL IS NULL AND SP.STRUCT_ID = :V$STRUCT_ID AND SP.Q_TYPE_ID IN (1, 2, 4)
      INTO :V$MAX_N;

      FOR
          SELECT BA.OBJ_ID, BA.ATTR_NAME
          FROM UT_BLANK_ATTRS BA
          WHERE BA.BLANK_ID = :I$BLANK_ID AND BA.DATE_DEL IS NULL AND BA.STATE_ID = 0 AND BA.ATTR_NAME STARTING WITH '@answer['
          INTO :V$ATTR_ID, :V$ATTR_NAME
      DO
      BEGIN
          V$ATTR_NAME = REPLACE(SUBSTRING(V$ATTR_NAME FROM 9), ']', '');
          V$N = CAST(V$ATTR_NAME AS INTEGER);

          IF(V$N > V$MAX_N) THEN
          BEGIN
              UPDATE UT_BLANK_ATTRS BA
              SET BA.STATE_ID = -1
              WHERE BA.OBJ_ID = :V$ATTR_ID AND BA.STATE_ID = 0;
          END
      END
  END

  -- Должны быть верифицированы или отмечены чистыми абсолютно все поля
  IF(V$VARIANT_ID IS NOT NULL AND EXISTS(
      SELECT FIRST 1 1
      FROM UT_BLANK_ATTRS BA
      WHERE BA.BLANK_ID = :I$BLANK_ID AND BA.DATE_DEL IS NULL AND BA.STATE_ID = 0
  )) THEN EXCEPTION DATA_ERROR 'В бланке остались не верифицированные поля';

  -- Вытаскиваем идентифицирующую часть штрихкода
  IF(CHAR_LENGTH(V$BARCODE) <= 13) THEN V$LOCAL_ID = SUBSTRING(V$BARCODE FROM 6 FOR 7);
  ELSE IF(CHAR_LENGTH(V$BARCODE) <= 19) THEN V$LOCAL_ID = SUBSTRING(V$BARCODE FROM 12 FOR 7);

  -- Новый статус - пока ожидаем "верифицирован"
  V$STATE = 13;
  -- Создаем новую сессию и переносим результаты - только для бланка типа AB (сессия вносится в статусе промежуточной готовности)
  -- только если первый бланк не отмечен как чистый !
  IF(V$BLANK_TYPE = 1 AND V$VARIANT_ID IS NOT NULL) THEN
  BEGIN

      IF(V$SESSION_ID IS NULL) THEN
      BEGIN
          -- Тут делаем проверку только участника, остальное предполагается что все и так ОК
          SELECT FIRST 1 PA.PERSON_ID
          FROM UT_EXAM_PERSON_ASSN PA
          WHERE PA.DATE_DEL IS NULL AND PA.EXAM_ID = :V$EXAM_ID AND PA.LOCAL_ID = :V$LOCAL_ID
          INTO :V$PERSON_ID;

          IF(V$PERSON_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не удалось идентифицировать участника по штрихкоду "' || V$BARCODE || '"';

          INSERT INTO UT_SESSIONS
          (ED_ID, PERSON_ID, VARIANT_ID, STATE_ID)
          VALUES (:V$EXAM_ID, :V$PERSON_ID, :V$VARIANT_ID, 10)
          RETURNING OBJ_ID INTO :V$SESSION_ID;

          V$SESSION_RESULT = NULL;
      END

      -- Синхронизируем со справочниками положительные и отрицательные значения статуса
      -- пока выставление таких статусов закрыто !!!
      FOR
          -- основные ответы
          SELECT BA.ATTR_NAME, BA.ATTR_VALUE, BA.STATE_ID
          FROM UT_BLANK_ATTRS BA
          WHERE BA.DATE_DEL IS NULL AND BA.BLANK_ID = :I$BLANK_ID AND BA.ATTR_NAME STARTING WITH '@answer[' AND BA.STATE_ID IN (2, 3)
          -- замены ответов, берем последний
          -- !!! мультизамены !!!
          UNION
          SELECT '@answer[' || BR.ATTR_VALUE || ']', BV.ATTR_VALUE, BV.STATE_ID
          FROM UT_BLANK_ATTRS BR
          JOIN UT_BLANK_ATTRS BV ON BV.BLANK_ID = BR.BLANK_ID AND BV.ATTR_NAME = '@spval[' || SUBSTRING(BR.ATTR_NAME FROM 8 FOR CHAR_LENGTH(BR.ATTR_NAME) - 8) || ']' AND BV.STATE_ID IN (2, 3)
          WHERE BR.DATE_DEL IS NULL AND BR.BLANK_ID = :I$BLANK_ID AND BR.ATTR_NAME STARTING WITH '@spnum[' AND BR.STATE_ID > 0
          INTO :V$ATTR_NAME, :V$CONTEXT, :V$STATE
      DO
      BEGIN
          EXECUTE PROCEDURE UT_VERIFY_ANSWERS_DICT(:V$VARIANT_ID, :V$ATTR_NAME, :V$CONTEXT, :V$STATE);
      END

      SELECT STATE_ID, RAW_RESULT
      FROM UT_VERIFY_ANSWERS_APPLY(:I$BLANK_ID, :V$SESSION_ID, :V$VARIANT_ID)
      INTO :V$STATE, :V$RAW_RESULT;

      -- Закрываем сессию, если все вопросы оценились, и вопросы типа C в тесте не предусмотрены
      -- Если не все оценилось, то сессия будет висеть пока все оценки не будут определены
      IF(V$STATE = 14 AND V$NEXT_ID IS NULL) THEN
      BEGIN
          -- !!! пересчитать отметку, если есть шкалы !!!
          UPDATE UT_SESSIONS S
          SET S.STATE_ID = 100, S.RAW_RESULT = :V$RAW_RESULT
          WHERE S.OBJ_ID = :V$SESSION_ID AND S.STATE_ID = 10;
      END
      ELSE IF(V$SESSION_RESULT IS NULL AND V$RAW_RESULT IS NOT NULL) THEN
      BEGIN
          -- Если проверка части C еще не делалась, вносим результат по части AB
          UPDATE UT_SESSIONS S
          SET S.RAW_RESULT = :V$RAW_RESULT
          WHERE S.OBJ_ID = :V$SESSION_ID;
      END

      -- Если есть бланк C, при закрытии бланка AB:
      --   если бланк C уже верифицирован и без сессии - копируем в него сессию
      --   если бланк C не верифицирован - сессия перенесется при закрытии его самого
      --   запуск обработки бланков типа C производим когда вся цепочка соберется
      IF(V$NEXT_ID IS NOT NULL) THEN
      BEGIN
          SELECT FIRST 1 B.STATE_ID, B.SESSION_ID
          FROM UT_BLANKS B
          WHERE B.OBJ_ID = :V$NEXT_ID
          INTO :V$NEXT_STATE, :V$NEXT_SESSION;

          IF(V$NEXT_STATE = 13 AND V$NEXT_SESSION IS NULL) THEN
          BEGIN
              UPDATE UT_BLANKS B
              SET B.SESSION_ID = :V$SESSION_ID, B.DATE_MODIFY = CURRENT_TIMESTAMP
              WHERE B.OBJ_ID = :V$NEXT_ID;

              V$RUN_C = 1;
          END
      END

  END
  -- Бланки типа C. Если в бланке есть @variant - смотрим его и сверяем с бланком AB, если он есть
  -- если @variant нет, то забираем его же в бланке AB
  ELSE IF(V$BLANK_TYPE = 2) THEN
  BEGIN

      -- Есть ли в тестировании вопросы типа AB ?
      V$HAS_AB = 0;
      IF(EXISTS(
          SELECT FIRST 1 1
          FROM UT_TEST_STRUCT_POINTS SP
          WHERE SP.STRUCT_ID = :V$STRUCT_ID AND SP.DATE_DEL IS NULL AND SP.Q_TYPE_ID IN (1, 2, 4)
      )) THEN V$HAS_AB = 1;

      -- Свое поле варианта - оно должно быть в V$VARIANT_ID. Сверяем с возможным бланком AB - только когда он уже верифицирован
      IF(V$HAS_AB = 1) THEN
      BEGIN
          -- !!! вторая сторона бланка C !!!
          IF(V$SESSION_ID IS NULL) THEN
          BEGIN
              SELECT FIRST 1 B.SESSION_ID
              FROM UT_PACKAGES P
              JOIN UT_BLANKS B ON B.DATE_DEL IS NULL AND B.PACKAGE_ID = P.OBJ_ID AND B.NEXT_BLANK_ID = :I$BLANK_ID AND B.STATE_ID IN (13, 14)
              JOIN UT_PAGE_TEMPLATES PT ON PT.OBJ_ID = B.BLANK_TYPE AND PT.BLANK_TYPE = 1
              WHERE P.DATE_DEL IS NULL AND P.ED_ID = :V$EXAM_ID
              INTO :V$SESSION_ID;
          END

          -- Если сессия есть, пытаемся запустить в работу цепочку
          IF(V$SESSION_ID IS NOT NULL) THEN V$RUN_C = 1;
      END
      ELSE
      BEGIN
          -- Вариант тестирования только с вопросами типа C, без AB
          -- IF(V$SIDE = 0 AND V$VARIANT_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Системная ошибка. В шаблоне отсутствует поле варианта, и нет вопросов типа AB';

          -- Если VARIANT_ID пустой, тут тоже может быть вариант с отсутствующим участником
          IF(V$SESSION_ID IS NULL AND V$VARIANT_ID IS NOT NULL AND V$SIDE = 0) THEN
          BEGIN
              -- Копия кода аналогично бланкам AB
              SELECT FIRST 1 PA.PERSON_ID
              FROM UT_EXAM_PERSON_ASSN PA
              WHERE PA.DATE_DEL IS NULL AND PA.EXAM_ID = :V$EXAM_ID AND PA.LOCAL_ID = :V$LOCAL_ID
              INTO :V$PERSON_ID;

              IF(V$PERSON_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не удалось идентифицировать участника по штрихкоду "' || V$BARCODE || '"';

              INSERT INTO UT_SESSIONS
              (ED_ID, PERSON_ID, VARIANT_ID, STATE_ID)
              VALUES (:V$EXAM_ID, :V$PERSON_ID, :V$VARIANT_ID, 10)
              RETURNING OBJ_ID INTO :V$SESSION_ID;

              V$RUN_C = 1;
          END
      END

  END
  -- Дополнительные бланки типа C, поле варианта тут точно не предусмотрено
  ELSE IF(V$BLANK_TYPE = 3) THEN
  BEGIN
      V$RUN_C = 1;
  END

  -- Корректируем статус > Верифицирован или завершен (бланки AB переходят в завершенный статус, если все ответы однозначно идентифицируются)
  UPDATE UT_BLANKS B
  SET B.STATE_ID = :V$STATE, B.SESSION_ID = :V$SESSION_ID, B.NEXT_BLANK_ID = :V$NEXT_ID, B.DATE_MODIFY = CURRENT_TIMESTAMP
  WHERE B.OBJ_ID = :I$BLANK_ID AND B.STATE_ID = 12;

  IF(V$RUN_C = 1) THEN EXECUTE PROCEDURE UT_VERIFY_RUN_C(:V$EXAM_ID, :I$BLANK_ID);

  OBJ_ID = I$BLANK_ID;

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE VACANCY_GET_CAT (
    I$OBJ_ID BIGINT)
RETURNS (
    VAL VARCHAR(1000),
    LISTVAL_ID BIGINT)
AS
declare variable V$ASSN_ID bigint;
declare variable V$ASSN_TYPE bigint;
declare variable V$CAT_TEMP bigint;
begin

  LISTVAL_ID = NULL;
  FOR
    SELECT L15.OBJ_ID, V72.LISTVAL_ID, V1790.LISTVAL_ID
    FROM LINKS L15
    JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0
    LEFT JOIN VALL V72 ON V72.OBJ_ID = L15.OBJ_ID AND V72.PARAM_ID = 72 AND V72.IS_DEL = 0
    LEFT JOIN VALL V1790 ON V1790.OBJ_ID = L15.OBJ_ID AND V1790.PARAM_ID = 1790 AND V1790.IS_DEL = 0
    -- Если есть дата увольнения, пропускаем запись
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
    WHERE L15.PARENT_ID = :I$OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL AND V74.VAL IS NULL
    -- Сортируем в порядке приема на должность - будет возвращено последнее непустое назначение
    ORDER BY V73.VAL
    INTO :V$ASSN_ID, :V$ASSN_TYPE, :V$CAT_TEMP
  DO
  BEGIN
    IF(V$ASSN_TYPE = 934) THEN
    BEGIN
      IF(V$CAT_TEMP IS NOT NULL) THEN
      BEGIN
        LISTVAL_ID = V$CAT_TEMP;
      END
    END
  END

  IF(LISTVAL_ID IS NULL) THEN LISTVAL_ID = 632;

  SELECT R.VAL
  FROM LISTVALS V
  JOIN RES R ON R.RES_ID = V.RES_ID AND R.LANG_CODE = 'RU'
  WHERE V.LISTVAL_ID = :LISTVAL_ID
  INTO :VAL;

  SUSPEND;
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE VACANCY_NUM_OCCUPIED (
    OBJ_ID BIGINT)
RETURNS (
    VAL NUMERIC(15,5))
AS
declare variable VAC_TYPE_ID bigint;
begin

  SELECT TYPE_ID FROM OBJECTS WHERE OBJ_ID = :OBJ_ID INTO :VAC_TYPE_ID;
  IF(VAC_TYPE_ID IS NULL) THEN EXIT;

  IF(VAC_TYPE_ID = 13) THEN
  BEGIN

    SELECT SUM(V71.VAL)
    FROM LINKS L15
    -- Связь с сотрудником - проверяем статус
    JOIN LINKS LP14 ON LP14.OBJ_ID = L15.OBJ_ID AND LP14.PARENT_TYPE_ID = 14 AND LP14.DATE_DEL IS NULL
    JOIN VALL V274 ON V274.OBJ_ID = LP14.PARENT_ID AND V274.PARAM_ID = 274 AND V274.IS_DEL = 0 AND V274.LISTVAL_ID = 602
    -- Сверку по дате приема на должность не проводим, чтобы не плодить операционные ошибки
    -- Не уволенные или с датой увольнения позднее текущей даты
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
    -- Условия приема на должность
    JOIN VALL V587 ON V587.OBJ_ID = L15.OBJ_ID AND V587.PARAM_ID = 587 AND V587.IS_DEL = 0
    -- Количество ставок
    JOIN VALF V71 ON V71.OBJ_ID = L15.OBJ_ID AND V71.PARAM_ID = 71 AND V71.IS_DEL = 0
    -- Подсчитываем только работающих в данное время сотрудников
    WHERE L15.PARENT_ID = :OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
      AND (V74.VAL IS NULL OR V74.VAL > CURRENT_DATE)
    INTO :VAL;

  END
  ELSE IF(VAC_TYPE_ID = 2) THEN
  BEGIN

    SELECT SUM(V71.VAL)
    -- Цикл по всем учительским должностям
    FROM LINKS L13
    JOIN VALL V58 ON V58.OBJ_ID = L13.OBJ_ID AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V58.LISTVAL_ID AND LV.TAG = 'U' AND LV.PARENT_ID = 98
    -- Все назначения на данные должности
    JOIN LINKS L15 ON L15.PARENT_ID = L13.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
    -- Связь с сотрудником - проверяем статус
    JOIN LINKS LP14 ON LP14.OBJ_ID = L15.OBJ_ID AND LP14.PARENT_TYPE_ID = 14 AND LP14.DATE_DEL IS NULL
    JOIN VALL V274 ON V274.OBJ_ID = LP14.PARENT_ID AND V274.PARAM_ID = 274 AND V274.IS_DEL = 0 AND V274.LISTVAL_ID = 602
    -- Сверку по дате приема на должность не проводим, чтобы не плодить операционные ошибки
    -- Не уволенные или с датой увольнения позднее текущей даты
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
    -- Условия приема на должность
    JOIN VALL V587 ON V587.OBJ_ID = L15.OBJ_ID AND V587.PARAM_ID = 587 AND V587.IS_DEL = 0
    -- Количество ставок
    JOIN VALF V71 ON V71.OBJ_ID = L15.OBJ_ID AND V71.PARAM_ID = 71 AND V71.IS_DEL = 0
    -- Подсчитываем только работающих в данный момент сотрудников
    WHERE L13.OBJ_TYPE_ID = 13 AND L13.DATE_DEL IS NULL AND L13.PARENT_ID = :OBJ_ID
      AND (V74.VAL IS NULL OR V74.VAL > CURRENT_DATE)
    INTO :VAL;

  END

  IF(VAL IS NULL) THEN VAL = 0;

  SUSPEND;
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE VACANCY_NUM_TEMPFREE (
    OBJ_ID BIGINT)
RETURNS (
    VAL NUMERIC(15,5))
AS
declare variable VAC_TYPE_ID bigint;
declare variable TEMP_AVAIL double precision;
begin

  SELECT TYPE_ID FROM OBJECTS WHERE OBJ_ID = :OBJ_ID INTO :VAC_TYPE_ID;
  IF(VAC_TYPE_ID IS NULL) THEN EXIT;

  IF(VAC_TYPE_ID = 13) THEN
  BEGIN

    -- Количество временно доступных ставок
    SELECT SUM(V71.VAL)
    FROM LINKS L15
    -- Связь с сотрудником - проверяем статус
    JOIN LINKS LP14 ON LP14.OBJ_ID = L15.OBJ_ID AND LP14.PARENT_TYPE_ID = 14 AND LP14.DATE_DEL IS NULL
    JOIN VALL V274 ON V274.OBJ_ID = LP14.PARENT_ID AND V274.PARAM_ID = 274 AND V274.IS_DEL = 0 AND V274.LISTVAL_ID <> 602
    -- Сверку по дате приема на должность не проводим, чтобы не плодить операционные ошибки
    -- Не уволенные или с датой увольнения позднее текущей даты
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
    -- Условия приема на должность
    JOIN VALL V587 ON V587.OBJ_ID = L15.OBJ_ID AND V587.PARAM_ID = 587 AND V587.IS_DEL = 0 AND V587.LISTVAL_ID NOT IN (1720, 12824)
    -- Количество ставок
    JOIN VALF V71 ON V71.OBJ_ID = L15.OBJ_ID AND V71.PARAM_ID = 71 AND V71.IS_DEL = 0
    -- Подсчитываем только постоянную занятость, где сотрудник в отпуске
    WHERE L15.PARENT_ID = :OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL AND (V74.VAL IS NULL OR V74.VAL > CURRENT_DATE)
    INTO :TEMP_AVAIL;

    IF(TEMP_AVAIL IS NULL) THEN TEMP_AVAIL = 0;

    -- Количество занятых ставок на время отсутствия основного сотрудника
    SELECT SUM(V71.VAL)
    FROM LINKS L15
    -- Связь с сотрудником - проверяем статус
    JOIN LINKS LP14 ON LP14.OBJ_ID = L15.OBJ_ID AND LP14.PARENT_TYPE_ID = 14 AND LP14.DATE_DEL IS NULL
    JOIN VALL V274 ON V274.OBJ_ID = LP14.PARENT_ID AND V274.PARAM_ID = 274 AND V274.IS_DEL = 0 AND V274.LISTVAL_ID = 602
    -- Сверку по дате приема на должность не проводим, чтобы не плодить операционные ошибки
    -- Не уволенные или с датой увольнения позднее текущей даты
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
    -- Условия приема на должность
    JOIN VALL V587 ON V587.OBJ_ID = L15.OBJ_ID AND V587.PARAM_ID = 587 AND V587.IS_DEL = 0 AND V587.LISTVAL_ID IN (1720, 12824)
    -- Количество ставок
    JOIN VALF V71 ON V71.OBJ_ID = L15.OBJ_ID AND V71.PARAM_ID = 71 AND V71.IS_DEL = 0
    -- Подсчитываем только фактически присутствующих сотрудников
    WHERE L15.PARENT_ID = :OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL AND (V74.VAL IS NULL OR V74.VAL > CURRENT_DATE)
    INTO :VAL;

    IF(VAL IS NULL) THEN VAL = 0;

    VAL = TEMP_AVAIL - VAL;

  END
  ELSE IF(VAC_TYPE_ID = 2) THEN
  BEGIN

    -- Количество временно доступных ставок
    SELECT SUM(V71.VAL)
    -- Цикл по всем педагогическим должностям
    FROM LINKS L13
    JOIN VALL V58 ON V58.OBJ_ID = L13.OBJ_ID AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V58.LISTVAL_ID AND LV.IS_DEL = 0 AND LV.TAG = 'U' AND LV.PARENT_ID = 98
    -- Все назначения на данные должности
    JOIN LINKS L15 ON L15.PARENT_ID = L13.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
    -- Связь с сотрудником - проверяем статус
    JOIN LINKS LP14 ON LP14.OBJ_ID = L15.OBJ_ID AND LP14.PARENT_TYPE_ID = 14 AND LP14.DATE_DEL IS NULL
    JOIN VALL V274 ON V274.OBJ_ID = LP14.PARENT_ID AND V274.PARAM_ID = 274 AND V274.IS_DEL = 0 AND V274.LISTVAL_ID <> 602
    -- Сверку по дате приема на должность не проводим, чтобы не плодить операционные ошибки
    -- Не уволенные или с датой увольнения позднее текущей даты
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
    -- Условия приема на должность
    JOIN VALL V587 ON V587.OBJ_ID = L15.OBJ_ID AND V587.PARAM_ID = 587 AND V587.IS_DEL = 0 AND V587.LISTVAL_ID NOT IN (1720, 12824)
    -- Количество ставок
    JOIN VALF V71 ON V71.OBJ_ID = L15.OBJ_ID AND V71.PARAM_ID = 71 AND V71.IS_DEL = 0
    -- Подсчитываем только постоянную занятость, где сотрудник в отпуске
    WHERE L13.OBJ_TYPE_ID = 13 AND L13.DATE_DEL IS NULL AND L13.PARENT_ID = :OBJ_ID
      AND (V74.VAL IS NULL OR V74.VAL > CURRENT_DATE)
    INTO :TEMP_AVAIL;

    IF(TEMP_AVAIL IS NULL) THEN TEMP_AVAIL = 0;

    -- Количество занятых ставок на время отсутствия основного сотрудника
    SELECT SUM(V71.VAL)
    -- Цикл по всем педагогическим должностям
    FROM LINKS L13
    JOIN VALL V58 ON V58.OBJ_ID = L13.OBJ_ID AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V58.LISTVAL_ID AND LV.IS_DEL = 0 AND LV.TAG = 'U' AND LV.PARENT_ID = 98
    -- Все назначения на данные должности
    JOIN LINKS L15 ON L15.PARENT_ID = L13.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
    -- Связь с сотрудником - проверяем статус
    JOIN LINKS LP14 ON LP14.OBJ_ID = L15.OBJ_ID AND LP14.PARENT_TYPE_ID = 14 AND LP14.DATE_DEL IS NULL
    JOIN VALL V274 ON V274.OBJ_ID = LP14.PARENT_ID AND V274.PARAM_ID = 274 AND V274.IS_DEL = 0 AND V274.LISTVAL_ID = 602
    -- Сверку по дате приема на должность не проводим, чтобы не плодить операционные ошибки
    -- Не уволенные или с датой увольнения позднее текущей даты
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
    -- Условия приема на должность
    JOIN VALL V587 ON V587.OBJ_ID = L15.OBJ_ID AND V587.PARAM_ID = 587 AND V587.IS_DEL = 0 AND V587.LISTVAL_ID IN (1720, 12824)
    -- Количество ставок
    JOIN VALF V71 ON V71.OBJ_ID = L15.OBJ_ID AND V71.PARAM_ID = 71 AND V71.IS_DEL = 0
    -- Подсчитываем только фактически присутствующих сотрудников
    WHERE L13.OBJ_TYPE_ID = 13 AND L13.DATE_DEL IS NULL AND L13.PARENT_ID = :OBJ_ID
      AND (V74.VAL IS NULL OR V74.VAL > CURRENT_DATE)
    INTO :VAL;

    IF(VAL IS NULL) THEN VAL = 0;

    VAL = TEMP_AVAIL - VAL;

  END

  IF(VAL IS NULL) THEN VAL = 0;

  SUSPEND;
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE VACANCY_UPDATE_CAT (
    I$OBJ_ID BIGINT)
AS
declare variable PERSON_ID bigint;
declare variable TMP bigint;
declare variable QUAL_LV bigint;
declare variable TYPE_ID integer;
begin

  SELECT TYPE_ID
  FROM OBJECTS
  WHERE OBJ_ID = :I$OBJ_ID
  INTO :TYPE_ID;

  IF(TYPE_ID = 14) THEN PERSON_ID = I$OBJ_ID;
  ELSE
  BEGIN
    SELECT FIRST 1 PARENT_ID
    FROM LINKS LP14
    WHERE OBJ_ID = :I$OBJ_ID AND PARENT_TYPE_ID = 14 AND DATE_DEL IS NULL
    INTO :PERSON_ID;
  END

  IF(PERSON_ID IS NULL) THEN EXIT;

  SELECT LISTVAL_ID
  FROM VACANCY_GET_CAT(:PERSON_ID)
  INTO :QUAL_LV;

  SELECT BLOB_ID FROM VAL_ADD(281, :PERSON_ID, :QUAL_LV) INTO :TMP;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE VACATION_ADD (
    I$PERSON_ID BIGINT,
    I$JOB_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$PLAN_TYPE BIGINT,
    I$TYPE_ID BIGINT,
    I$DATE_FROM DATE,
    I$DATE_TO DATE,
    I$PERIOD INTEGER,
    I$DAYS INTEGER,
    I$COMMENTS VARCHAR(1000),
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$DATE_FROM DATE;
DECLARE VARIABLE V$DATE_TO DATE;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE T INTEGER;
DECLARE VARIABLE V$PERSON_ID BIGINT;
DECLARE VARIABLE V$USER_TYPE SMALLINT;
begin

  IF(I$PLAN_TYPE <> 736 AND I$TYPE_ID <> 730) THEN EXCEPTION DATA_ERROR 'Планирование предусмотрено только для ежегодных отпусков';
  IF(I$DATE_TO < I$DATE_FROM) THEN EXCEPTION DATA_ERROR 'Дата окончания не может быть раньше даты начала';
  IF(EXTRACT(YEAR FROM I$DATE_FROM) < 2000 OR I$DATE_FROM < DATEADD(-10 YEAR TO CURRENT_DATE))
    THEN EXCEPTION DATA_ERROR 'Нельзя вносить сведения ранее чем за 10 лет от текущей даты';
  IF(I$DATE_FROM > DATEADD(3 YEAR TO CURRENT_DATE))
    THEN EXCEPTION DATA_ERROR 'Нельзя вносить сведения с датой начала более 3 лет от текущей даты';
  IF(I$PLAN_TYPE = 735 AND I$DATE_FROM > DATEADD(15 DAY TO CURRENT_DATE))
    THEN EXCEPTION DATA_ERROR 'Данные о фактическом отпуске можно внести не ранее чем за 2 недели до его начала';
  IF(I$PERIOD IS NULL) THEN I$PERIOD = EXTRACT(YEAR FROM I$DATE_FROM);

  IF(I$PERIOD < EXTRACT(YEAR FROM I$DATE_FROM) - 5) THEN EXCEPTION DATA_ERROR 'Нельзя указывать период меньше чем 5 лет от даты начала отпуска';

  -- Добавить проверки чтобы рядовой пользователь мог добавлять даты только в открытом периоде планирования
  -- Есть ли у пользователя права RW в личных делах ?
  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  SELECT U.OBJ_ID, U.USER_TYPE
  FROM USERS U
  WHERE U.USER_ID = :I$USER_ID
  INTO :V$PERSON_ID, :V$USER_TYPE;

  IF(V$USER_TYPE IN (12, 22) OR (V$USER_TYPE <> 1 AND V$PERSON_ID IS NULL)) THEN EXCEPTION DATA_ERROR 'Только сотрудники ОУ могут работать с отпусками';

  -- ...

  -- Если PERSON_ID отрицательный, надо проверить что персона еще числится
  IF(I$PERSON_ID < 0) THEN
  BEGIN
    I$PERSON_ID = - I$PERSON_ID;
    IF(NOT EXISTS(
      SELECT FIRST 1 1
      FROM LINKS L14
      WHERE L14.OBJ_ID = :I$PERSON_ID AND L14.PARENT_TYPE_ID IN (2, 211) AND L14.DATE_DEL IS NULL
    ))
    THEN
      EXIT;
  END

  -- Если должность не указали, берем основную должность
  IF(I$JOB_ID IS NULL) THEN
  SELECT FIRST 1 L15.OBJ_ID
  FROM LINKS L15
  JOIN VALL V72 ON V72.OBJ_ID = L15.OBJ_ID AND V72.PARAM_ID = 72 AND V72.IS_DEL = 0 AND V72.LISTVAL_ID = 934
  JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0
  WHERE L15.PARENT_ID = :I$PERSON_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
  ORDER BY 1 DESC
  INTO :I$JOB_ID;

  -- Нет ли пересечения с другими отпусками того же типа на той же должности?
  SELECT VAC_EXISTS FROM VACATION_CHECK_EXISTS(:I$PERSON_ID, :I$JOB_ID, :I$OBJ_ID, :I$PLAN_TYPE, :I$DATE_FROM, :I$DATE_TO) INTO :T;
  IF (T = 1) THEN
    EXCEPTION DATA_ERROR 'Периоды отпусков не должны пересекаться';

  -- Дата приема на работу по выбранной должности
  SELECT FIRST 1 V73.VAL, V74.VAL
  FROM LINKS L15
  JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0
  LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
  WHERE L15.PARENT_ID = :I$PERSON_ID AND L15.OBJ_TYPE_ID = 15 AND L15.OBJ_ID = :I$JOB_ID AND L15.DATE_DEL IS NULL
  ORDER BY 1 DESC
  INTO :V$DATE_FROM, :V$DATE_TO;

  IF(I$DATE_FROM < V$DATE_FROM) THEN EXCEPTION DATA_ERROR 'Дата начала отпуска не может быть раньше даты приема на работу';
  IF(V$DATE_TO IS NOT NULL AND (I$DATE_TO IS NULL OR I$DATE_TO > V$DATE_TO)) THEN EXCEPTION DATA_ERROR 'Дата конца отпуска не может быть позднее даты увольнения';

  -- Посчитаем календарные дни с учетом праздников по КУГ
  IF(I$DATE_TO IS NULL) THEN I$DAYS = NULL;
  IF(I$DATE_TO IS NOT NULL AND I$DAYS IS NULL) THEN
  BEGIN
    I$DAYS = DATEDIFF(DAY, I$DATE_FROM, I$DATE_TO) + 1 - (
      SELECT COUNT(*)
      FROM LINKS L481
      JOIN LINKS L486 ON L486.PARENT_ID = L481.OBJ_ID AND L486.OBJ_TYPE_ID = 486 AND L486.DATE_DEL IS NULL
      JOIN VALD V3393 ON V3393.OBJ_ID = L486.OBJ_ID AND V3393.PARAM_ID = 3393 AND V3393.IS_DEL = 0 AND V3393.VAL >= :I$DATE_FROM AND V3393.VAL <= :I$DATE_TO
      JOIN VALL V3394 ON V3394.OBJ_ID = L486.OBJ_ID AND V3394.PARAM_ID = 3394 AND V3394.IS_DEL = 0 AND V3394.LISTVAL_ID = 14234
      WHERE L481.PARENT_TYPE_ID = 2 AND L481.OBJ_TYPE_ID = 481 AND L481.DATE_DEL IS NULL
    );
  END
  IF(I$DAYS < 1) THEN EXCEPTION DATA_ERROR 'Количество дней отпуска с учетом праздничных дней не может быть нулевым';

  IF(I$OBJ_ID IS NULL) THEN
    SELECT OBJ_ID FROM OBJECT_ADD(:I$PERSON_ID, 37) INTO :V$OBJ_ID;
  ELSE
    V$OBJ_ID = I$OBJ_ID;

  SELECT 1 FROM VAL_ADD(330, :V$OBJ_ID, :I$PLAN_TYPE) INTO :T;
  SELECT 1 FROM VAL_ADD(326, :V$OBJ_ID, :I$TYPE_ID) INTO :T;
  SELECT 1 FROM VAL_ADD(327, :V$OBJ_ID, :I$DATE_FROM) INTO :T;
  SELECT 1 FROM VAL_ADD(328, :V$OBJ_ID, :I$DATE_TO) INTO :T;
  SELECT 1 FROM VAL_ADD(325, :V$OBJ_ID, :I$PERIOD) INTO :T;
  SELECT 1 FROM VAL_ADD(3582, :V$OBJ_ID, :I$JOB_ID) INTO :T;
  SELECT 1 FROM VAL_ADD(329, :V$OBJ_ID, :I$DAYS) INTO :T;
  SELECT 1 FROM VAL_ADD(1401, :V$OBJ_ID, :I$COMMENTS) INTO :T;

  TAG_NAME = 'id';
  VAL = V$OBJ_ID;
  SUSPEND;
  TAG_NAME = 'period';
  VAL = I$PERIOD;
  SUSPEND;
  TAG_NAME = 'type_id';
  VAL = I$TYPE_ID;
  SUSPEND;
  TAG_NAME = 'type_name';
  VAL = (SELECT VAL FROM LISTVAL_TEXT(:I$TYPE_ID));
  SUSPEND;
  TAG_NAME = 'plan_type';
  VAL = I$PLAN_TYPE;
  SUSPEND;
  TAG_NAME = 'date_from';
  VAL = (SELECT VAL FROM DATE2ISO(:I$DATE_FROM));
  SUSPEND;
  TAG_NAME = 'date_to';
  VAL = (SELECT VAL FROM DATE2ISO(:I$DATE_TO));
  SUSPEND;
  TAG_NAME = 'days';
  VAL = I$DAYS;
  SUSPEND;
  TAG_NAME = 'comments';
  VAL = I$COMMENTS;
  SUSPEND;
  TAG_NAME = 'job_id';
  VAL = I$JOB_ID;
  SUSPEND;
  TAG_NAME = 'job_name';
  VAL = (SELECT SVAL FROM VALS WHERE OBJ_ID = :I$JOB_ID AND PARAM_ID = 3543 AND IS_DEL = 0);
  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE VACATION_ADD_OU (
    I$YEAR INTEGER NOT NULL,
    I$USER_ID VARCHAR(40))
RETURNS (
    OBJ_ID BIGINT)
AS
DECLARE VARIABLE V$OU_ID BIGINT;
begin

  IF(I$YEAR < EXTRACT(YEAR FROM CURRENT_DATE) - 3 OR I$YEAR > EXTRACT(YEAR FROM CURRENT_DATE) + 1) THEN EXCEPTION DATA_ERROR 'Год может быть в пределах -3...+1 от текущего';

  -- Нет ли уже такой ведомости ?
  SELECT FIRST 1 L2.OBJ_ID
  FROM LINKS L2
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$OU_ID;

  SELECT FIRST 1 L534.OBJ_ID
  FROM LINKS L534
  JOIN VALI V3584 ON V3584.OBJ_ID = L534.OBJ_ID AND V3584.PARAM_ID = 3584 AND V3584.IS_DEL = 0 AND V3584.VAL = :I$YEAR
  WHERE L534.PARENT_ID = :V$OU_ID AND L534.OBJ_TYPE_ID = 534 AND L534.DATE_DEL IS NULL
  INTO :OBJ_ID;

  IF(OBJ_ID IS NOT NULL) THEN EXCEPTION DATA_ERROR 'Расписание на указанный год уже есть';

  SELECT OBJ_ID FROM OBJECT_ADD_WITH_PARAM(:V$OU_ID, null, 534, 3584, :I$YEAR) INTO :OBJ_ID;

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE VACATION_APPROVE (
    I$OBJ_ID BIGINT,
    I$STATE_ID BIGINT,
    I$USER_ID BIGINT)
AS
DECLARE VARIABLE V$Y INTEGER;
begin

  -- Статус могут менять: админ, директор, завуч, кадровик
  IF(I$USER_ID IS NOT NULL AND NOT EXISTS(
    SELECT FIRST 1 1
    FROM USERS U
    WHERE U.USER_ID = :I$USER_ID AND U.DATE_DEL IS NULL AND U.USER_TYPE IN (1, 5, 6, 10)
  ))
  THEN
    EXCEPTION DATA_ERROR 'У вас нет прав доступа для изменения статуса';

  IF(I$STATE_ID = 11717) THEN EXCEPTION DATA_ERROR 'Статус Не действующий не может быть установлен';

  -- При переводе в архив вообще ничего не надо
  -- Перевод в архив выполняется при переводе года, обратно вернуться нельзя
  IF(I$STATE_ID = 14261) THEN EXIT;

  SELECT V3584.VAL
  FROM VALI V3584
  WHERE V3584.OBJ_ID = :I$OBJ_ID AND V3584.PARAM_ID = 3584 AND V3584.IS_DEL = 0
  INTO :V$Y;

  IF(I$STATE_ID = 11716) THEN
  BEGIN
    -- В статус проекта
    IF(EXISTS(
      SELECT FIRST 1 1
      FROM LINKS L2
      JOIN LINKS L534 ON L534.PARENT_ID = L2.OBJ_ID AND L534.OBJ_TYPE_ID = 534 AND L534.DATE_DEL IS NULL
      JOIN VALI V3584 ON V3584.OBJ_ID = L534.OBJ_ID AND V3584.PARAM_ID = 3584 AND V3584.IS_DEL = 0 AND V3584.VAL > :V$Y
      JOIN VALL V3585 ON V3585.OBJ_ID = L534.OBJ_ID AND V3585.PARAM_ID = 3585 AND V3585.IS_DEL = 0 AND V3585.LISTVAL_ID <> 11716
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    ))
    THEN
      EXCEPTION DATA_ERROR 'Нельзя переводить в статус действующего при наличии действующих планов за более поздние годы';
  END
  ELSE IF(I$STATE_ID = 11715) THEN
  BEGIN
    -- В статус действующего
    IF(EXISTS(
      SELECT FIRST 1 1
      FROM LINKS L2
      JOIN LINKS L534 ON L534.PARENT_ID = L2.OBJ_ID AND L534.OBJ_TYPE_ID = 534 AND L534.DATE_DEL IS NULL
      JOIN VALI V3584 ON V3584.OBJ_ID = L534.OBJ_ID AND V3584.PARAM_ID = 3584 AND V3584.IS_DEL = 0 AND V3584.VAL < :V$Y
      JOIN VALL V3585 ON V3585.OBJ_ID = L534.OBJ_ID AND V3585.PARAM_ID = 3585 AND V3585.IS_DEL = 0 AND V3585.LISTVAL_ID = 11716
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    ))
    THEN
      EXCEPTION DATA_ERROR 'Нельзя переводить в статус действующего при наличии проектов за более ранние годы';
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE VACATION_CHECK_EXISTS (
    I$PERSON_ID BIGINT,
    I$JOB_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$PLAN_TYPE BIGINT,
    I$DATE_FROM DATE,
    I$DATE_TO DATE)
RETURNS (
    VAC_EXISTS SMALLINT)
AS
begin
 VAC_EXISTS = 0;
 IF(EXISTS(
    SELECT FIRST 1 1
    FROM LINKS L37
    JOIN VALL V330 ON V330.OBJ_ID = L37.OBJ_ID AND V330.PARAM_ID = 330 AND V330.IS_DEL = 0 AND V330.LISTVAL_ID = :I$PLAN_TYPE
    JOIN VALD V327 ON V327.OBJ_ID = L37.OBJ_ID AND V327.PARAM_ID = 327 AND V327.IS_DEL = 0
    JOIN VALR V3582 ON V3582.OBJ_ID = L37.OBJ_ID AND V3582.PARAM_ID = 3582 AND V3582.IS_DEL = 0 AND V3582.VAL = :I$JOB_ID
    LEFT JOIN VALD V328 ON V328.OBJ_ID = L37.OBJ_ID AND V328.PARAM_ID = 328 AND V328.IS_DEL = 0
    WHERE L37.PARENT_ID = :I$PERSON_ID AND L37.OBJ_TYPE_ID = 37 AND (L37.OBJ_ID <> :I$OBJ_ID OR :I$OBJ_ID IS NULL) AND L37.DATE_DEL IS NULL
      AND (V327.VAL <= :I$DATE_TO OR :I$DATE_TO IS NULL)
      AND (V328.VAL >= :I$DATE_FROM OR V328.VAL IS NULL)
  ))
  THEN
    VAC_EXISTS = 1;
  SUSPEND;
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE VACATION_CLONE (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    OBJ_ID BIGINT,
    JOB_ID BIGINT,
    TYPE_ID BIGINT,
    TYPE_NAME VARCHAR(100),
    PLAN_TYPE BIGINT,
    DATE_FROM VARCHAR(40),
    DATE_TO VARCHAR(40),
    DAYS INTEGER)
AS
DECLARE VARIABLE V$PERSON_ID BIGINT;
DECLARE VARIABLE V$PERIOD INTEGER;
DECLARE VARIABLE V$D1 DATE;
DECLARE VARIABLE V$D2 DATE;
DECLARE VARIABLE V$STATE_ID BIGINT;
DECLARE VARIABLE T INTEGER;
begin

  SELECT FIRST 1 LP14.PARENT_ID, V3582.VAL, V325.VAL, V326.LISTVAL_ID, V330.LISTVAL_ID, V327.VAL, V328.VAL, V329.VAL
  FROM LINKS LP14
  JOIN VALR V3582 ON V3582.OBJ_ID = LP14.OBJ_ID AND V3582.PARAM_ID = 3582 AND V3582.IS_DEL = 0
  JOIN VALI V325 ON V325.OBJ_ID = LP14.OBJ_ID AND V325.PARAM_ID = 325 AND V325.IS_DEL = 0
  JOIN VALL V326 ON V326.OBJ_ID = LP14.OBJ_ID AND V326.PARAM_ID = 326 AND V326.IS_DEL = 0
  JOIN VALL V330 ON V330.OBJ_ID = LP14.OBJ_ID AND V330.PARAM_ID = 330 AND V330.IS_DEL = 0
  JOIN VALD V327 ON V327.OBJ_ID = LP14.OBJ_ID AND V327.PARAM_ID = 327 AND V327.IS_DEL = 0
  JOIN VALD V328 ON V328.OBJ_ID = LP14.OBJ_ID AND V328.PARAM_ID = 328 AND V328.IS_DEL = 0
  JOIN VALI V329 ON V329.OBJ_ID = LP14.OBJ_ID AND V329.PARAM_ID = 329 AND V329.IS_DEL = 0
  WHERE LP14.OBJ_ID = :I$OBJ_ID AND LP14.PARENT_TYPE_ID = 14 AND LP14.DATE_DEL IS NULL
  INTO :V$PERSON_ID, :JOB_ID, :V$PERIOD, :TYPE_ID, :PLAN_TYPE, :V$D1, :V$D2, :DAYS;

  IF(V$PERSON_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Запись отпуска не найдена';
  IF(TYPE_ID <> 730) THEN EXCEPTION DATA_ERROR 'Операция переноса в план доступна только для текущих отпусков';
  IF(PLAN_TYPE <> 18710) THEN EXCEPTION DATA_ERROR 'Операция переноса в план доступна только для пожеланий сотрудника';
  PLAN_TYPE = 736;

  -- Открыт ли период планирования ?

  SELECT FIRST 1 V3585.LISTVAL_ID
  FROM LINKS L2
  JOIN LINKS L534 ON L534.PARENT_ID = L2.OBJ_ID AND L534.OBJ_TYPE_ID = 534 AND L534.DATE_DEL IS NULL
  JOIN VALI V3584 ON V3584.OBJ_ID = L534.OBJ_ID AND V3584.PARAM_ID = 3584 AND V3584.IS_DEL = 0 AND V3584.VAL = EXTRACT(YEAR FROM :V$D1)
  JOIN VALL V3585 ON V3585.OBJ_ID = L534.OBJ_ID AND V3585.PARAM_ID = 3585 AND V3585.IS_DEL = 0
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$STATE_ID;

  IF(V$STATE_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Период планирования не найден';
  IF(V$STATE_ID <> 11716) THEN EXCEPTION DATA_ERROR 'Период планирования закрыт, внесение изменений недоступно';

  -- У нас точно уже другой записи на эти даты ?
  IF(EXISTS(
    SELECT FIRST 1 1
    FROM LINKS L37
    JOIN VALR V3582 ON V3582.OBJ_ID = L37.OBJ_ID AND V3582.PARAM_ID = 3582 AND V3582.IS_DEL = 0 AND V3582.VAL = :JOB_ID
    JOIN VALL V330 ON V330.OBJ_ID = L37.OBJ_ID AND V330.PARAM_ID = 330 AND V330.IS_DEL = 0 AND V330.LISTVAL_ID = :PLAN_TYPE
    JOIN VALD V327 ON V327.OBJ_ID = L37.OBJ_ID AND V327.PARAM_ID = 327 AND V327.IS_DEL = 0
    JOIN VALD V328 ON V328.OBJ_ID = L37.OBJ_ID AND V328.PARAM_ID = 328 AND V328.IS_DEL = 0
    WHERE L37.PARENT_ID = :V$PERSON_ID AND L37.OBJ_TYPE_ID = 37 AND L37.DATE_DEL IS NULL
      AND V327.VAL <= :V$D2 AND V328.VAL >= :V$D1
  ))
  THEN
    EXCEPTION DATA_ERROR 'Уже есть запись на указанный диапазон дат';

  SELECT OBJ_ID FROM OBJECT_ADD(:V$PERSON_ID, 37) INTO :OBJ_ID;
  SELECT 1 FROM VAL_ADD(3582, :OBJ_ID, :JOB_ID) INTO :T;
  SELECT 1 FROM VAL_ADD(325, :OBJ_ID, :V$PERIOD) INTO :T;
  SELECT 1 FROM VAL_ADD(326, :OBJ_ID, :TYPE_ID) INTO :T;
  SELECT 1 FROM VAL_ADD(330, :OBJ_ID, :PLAN_TYPE) INTO :T;
  SELECT 1 FROM VAL_ADD(327, :OBJ_ID, :V$D1) INTO :T;
  SELECT 1 FROM VAL_ADD(328, :OBJ_ID, :V$D2) INTO :T;
  SELECT 1 FROM VAL_ADD(329, :OBJ_ID, :DAYS) INTO :T;

  DATE_FROM = (SELECT VAL FROM DATE2ISO(:V$D1, 0));
  DATE_TO = (SELECT VAL FROM DATE2ISO(:V$D2, 0));

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE VACATION_DAYS_REST (
    I$OBJ_ID BIGINT)
RETURNS (
    N INTEGER)
AS
DECLARE VARIABLE V$DATE1 DATE;
DECLARE VARIABLE V$DATE2 DATE;
DECLARE VARIABLE V$JOB_ID BIGINT;
DECLARE VARIABLE U INTEGER;
begin

  V$DATE1 = '01.01.' || EXTRACT(YEAR FROM CURRENT_DATE);
  V$DATE2 = '31.12.' || EXTRACT(YEAR FROM CURRENT_DATE);

  -- По основной должности

  SELECT L15.OBJ_ID, COALESCE(V3580.VAL, 28)
  FROM LINKS L15
  JOIN VALL V72 ON V72.OBJ_ID = L15.OBJ_ID AND V72.PARAM_ID = 72 AND V72.IS_DEL = 0 AND V72.LISTVAL_ID = 934
  LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
  LEFT JOIN VALI V3580 ON V3580.OBJ_ID = L15.OBJ_ID AND V3580.PARAM_ID = 3580 AND V3580.IS_DEL = 0
  WHERE L15.PARENT_ID = :I$OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL AND V74.VAL IS NULL
  INTO :V$JOB_ID, :N;

  SELECT SUM(V329.VAL)
  FROM LINKS L37
  JOIN VALR V3582 ON V3582.OBJ_ID = L37.OBJ_ID AND V3582.PARAM_ID = 3582 AND V3582.IS_DEL = 0 AND V3582.VAL = :V$JOB_ID
  JOIN VALL V326 ON V326.OBJ_ID = L37.OBJ_ID AND V326.PARAM_ID = 326 AND V326.IS_DEL = 0 AND V326.LISTVAL_ID = 730 -- ежегодный
  JOIN VALL V330 ON V330.OBJ_ID = L37.OBJ_ID AND V330.PARAM_ID = 330 AND V330.IS_DEL = 0 AND V330.LISTVAL_ID = 736 -- план
  JOIN VALD V327 ON V327.OBJ_ID = L37.OBJ_ID AND V327.PARAM_ID = 327 AND V327.IS_DEL = 0 AND V327.VAL BETWEEN :V$DATE1 AND :V$DATE2
  JOIN VALI V329 ON V329.OBJ_ID = L37.OBJ_ID AND V329.PARAM_ID = 329 AND V329.IS_DEL = 0
  WHERE L37.PARENT_ID = :I$OBJ_ID AND L37.OBJ_TYPE_ID = 37 AND L37.DATE_DEL IS NULL
  INTO :U;

  N = N - COALESCE(U, 0);

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE VACATION_DELETE (
    I$PARENT_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    OBJ_ID BIGINT)
AS
DECLARE VARIABLE V$PERSON_ID BIGINT;
begin

  SELECT FIRST 1 U.OBJ_ID
  FROM USERS U
  WHERE U.USER_ID = :I$USER_ID AND U.DATE_DEL IS NULL
  INTO :V$PERSON_ID;

  IF(V$PERSON_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не найдена запись сотрудника для данного пользователя';

  IF(V$PERSON_ID <> I$PARENT_ID) THEN EXCEPTION DATA_error 'Нельзя удалить чужой отпуск';

  -- TODO проверить все условия

  UPDATE LINKS
  SET DATE_DEL = CURRENT_TIMESTAMP
  WHERE PARENT_ID = :V$PERSON_ID AND OBJ_ID = :I$OBJ_ID AND DATE_DEL IS NULL AND OBJ_TYPE_ID = 37;

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE VACATION_DELETE_PLAN (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
AS
DECLARE VARIABLE V$STATUS BIGINT;
DECLARE VARIABLE V$OU_ID BIGINT;
DECLARE VARIABLE T INTEGER;
begin

  -- Архивные и действующие удалять нельзя
  SELECT L534.PARENT_ID, V3585.LISTVAL_ID
  FROM LINKS L534
  JOIN VALL V3585 ON V3585.OBJ_ID = L534.OBJ_ID AND V3585.PARAM_ID = 3585 AND V3585.IS_DEL = 0
  WHERE L534.OBJ_ID = :I$OBJ_ID AND L534.PARENT_TYPE_ID = 2 AND L534.DATE_DEL IS NULL
  INTO :V$OU_ID, :V$STATUS;

  IF(V$STATUS IS NULL) THEN EXCEPTION DATA_ERROR 'График не найден или был удален';
  IF(V$STATUS <> 11716) THEN EXCEPTION DATA_ERROR 'График можно удалять только в статусе проекта';

  SELECT 1 FROM DC_OBJECT_DELETE(:V$OU_ID, :I$OBJ_ID, NULL, :I$USER_ID) INTO :T;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE VACATION_GET (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
declare variable V$OU_ID bigint;
declare variable V$TYPE_ID bigint;
declare variable V$DATE date;
declare variable V$DATE2 date;
declare variable V$OBJ_ID bigint;
declare variable V$PERIOD integer;
declare variable V$TYPE bigint;
declare variable V$PLAN_TYPE bigint;
declare variable V$JOB_ID bigint;
declare variable V$D1 date;
declare variable V$D2 date;
declare variable N integer;
declare variable S varchar(1000);
declare variable S2 varchar(400);
declare variable S3 varchar(100);
declare variable V$TYPE_NAME varchar(200);
declare variable V$YEAR integer;
declare variable V$PARENT_ID bigint;
declare variable V$STATE_ID bigint;
declare variable V$PERSON_ID bigint;
declare variable V$MERGE smallint;
declare variable V$DIV_ID bigint;
declare variable V$DIV_NAME varchar(400);
begin

  -- Тут может быть ID сотрудника, ID конкретного отпуска, подразделение, всей ОУ
  -- также может быть ID #534
  -- NULL мы не пускаем, для добавления графика сначала спрашиваем год, создаем запись, и далее ее открываем
  SELECT TYPE_ID
  FROM OBJECTS
  WHERE OBJ_ID = :I$OBJ_ID
  INTO :V$TYPE_ID;

  -- Копируем id
  TAG_NAME = 'id';
  VAL = I$OBJ_ID;
  SUSPEND;

  TAG_NAME = 'vc_types::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L.LISTVAL_ID, L.VAL
    FROM LISTVALS_LIST(104) L
    WHERE L.IS_DEL = 0
    INTO :V$OBJ_ID, :S
  DO
  BEGIN
    TAG_NAME = 'vc_types:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'vc_types:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'vc_types:r:value';
    VAL = S;
    SUSPEND;
  END

  IF(V$TYPE_ID IN (2, 534)) THEN
  BEGIN
    -- Расписание отпусков по ОУ
    -- Возвращаем прошлый, текущий и будущий календарные годы
    -- Если ничего нет - тут же создаем
    IF(V$TYPE_ID = 2) THEN
    BEGIN
      -- Старый вариант с фреймом - загружаем кусками по 3 года
      SELECT FIRST 1 LV.COST
      FROM VALL V1236
      JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
      WHERE V1236.OBJ_ID = :I$OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
      INTO :V$YEAR;

      IF(V$YEAR < EXTRACT(YEAR FROM CURRENT_DATE) - 1 OR V$YEAR > EXTRACT(YEAR FROM CURRENT_DATE) + 1) THEN
        EXCEPTION DATA_ERROR 'Неверные настройки или сбой часов в сервере, календарный год сильно расходится с учебным';

      -- Создаем автоматически только текущий и будущий, прошлый берем только исторично
      IF(NOT EXISTS(
        SELECT FIRST 1 1
        FROM LINKS L534
        JOIN VALI V3584 ON V3584.OBJ_ID = L534.OBJ_ID AND V3584.PARAM_ID = 3584 AND V3584.IS_DEL = 0 AND V3584.VAL = :V$YEAR
        WHERE L534.PARENT_ID = :I$OBJ_ID AND L534.OBJ_TYPE_ID = 534 AND L534.DATE_DEL IS NULL
      ))
      THEN
      SELECT 1 FROM OBJECT_ADD_WITH_PARAM(:I$OBJ_ID, NULL, 534, 3584, :V$YEAR) INTO :N;
      -- Будущий год создаем в сентябре
      IF(EXTRACT(MONTH FROM CURRENT_DATE) >= 9 AND NOT EXISTS(
        SELECT FIRST 1 1
        FROM LINKS L534
        JOIN VALI V3584 ON V3584.OBJ_ID = L534.OBJ_ID AND V3584.PARAM_ID = 3584 AND V3584.IS_DEL = 0 AND V3584.VAL = :V$YEAR + 1
        WHERE L534.PARENT_ID = :I$OBJ_ID AND L534.OBJ_TYPE_ID = 534 AND L534.DATE_DEL IS NULL
      ))
      THEN
      SELECT 1 FROM OBJECT_ADD_WITH_PARAM(:I$OBJ_ID, NULL, 534, 3584, :V$YEAR + 1) INTO :N;
      V$OU_ID = I$OBJ_ID;
    END
    ELSE
    BEGIN
      -- Новый вариант, загружаем конкретный год
      SELECT FIRST 1 LP2.PARENT_ID, V3584.VAL
      FROM LINKS LP2
      JOIN VALI V3584 ON V3584.OBJ_ID = LP2.OBJ_ID AND V3584.PARAM_ID = 3584 AND V3584.IS_DEL = 0
      WHERE LP2.OBJ_ID = :I$OBJ_ID AND LP2.PARENT_TYPE_ID = 2 AND LP2.DATE_DEL IS NULL
      INTO :V$OU_ID, :V$YEAR;
    END

    TAG_NAME = 'years::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT L534.OBJ_ID, V3584.VAL, V3585.LISTVAL_ID
      FROM LINKS L534
      JOIN VALI V3584 ON V3584.OBJ_ID = L534.OBJ_ID AND V3584.PARAM_ID = 3584 AND V3584.IS_DEL = 0
        AND ((:V$TYPE_ID = 2 AND V3584.VAL >= :V$YEAR - 1) OR ((:V$TYPE_ID = 534 AND V3584.VAL = :V$YEAR)) )
      JOIN VALL V3585 ON V3585.OBJ_ID = L534.OBJ_ID AND V3585.PARAM_ID = 3585 AND V3585.IS_DEL = 0
      WHERE L534.PARENT_ID = :V$OU_ID AND L534.OBJ_TYPE_ID = 534 AND L534.DATE_DEL IS NULL
      ORDER BY 2
      INTO :V$PARENT_ID, :V$PERIOD, :V$STATE_ID
    DO
    BEGIN
      TAG_NAME = 'years:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'years:r:id';
      VAL = V$PARENT_ID;
      SUSPEND;
      TAG_NAME = 'years:r:year';
      VAL = V$PERIOD;
      SUSPEND;
      TAG_NAME = 'years:r:state';
      VAL = V$STATE_ID;
      SUSPEND;
      TAG_NAME = 'years:r:state_name';
      VAL = (SELECT VAL FROM LISTVAL_TEXT(:V$STATE_ID));
      SUSPEND;
      V$DATE = '01.01.' || V$PERIOD;
      V$DATE2 = '31.12.' || V$PERIOD;
      -- Персоны - только основные должности
      -- В перспективе сортируем по приоритету должностей
      TAG_NAME = 'years:r:items::json&colon;array';
      VAL = 1;
      SUSPEND;
      FOR
        -- Сама ОУ
        SELECT L14.OBJ_ID, L15.OBJ_ID, V73.VAL, V74.VAL, C.CAPTION, V3543.SVAL, COALESCE(V3580.VAL, 0), V273.SVAL, IIF(V3581.LISTVAL_ID = 3, 0, 1),
          NULL, NULL
        FROM LINKS L14
        JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
        JOIN VALL V72 ON V72.OBJ_ID = L15.OBJ_ID AND V72.PARAM_ID = 72 AND V72.IS_DEL = 0 AND V72.LISTVAL_ID = 934
        JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0 AND V73.VAL <= :V$DATE2
        JOIN VALS V3543 ON V3543.OBJ_ID = L15.OBJ_ID AND V3543.PARAM_ID = 3543 AND V3543.IS_DEL = 0
        LEFT JOIN VALI V3580 ON V3580.OBJ_ID = L15.OBJ_ID AND V3580.PARAM_ID = 3580 AND V3580.IS_DEL = 0
        LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
        LEFT JOIN OBJECT_CAPTION_GET(L14.OBJ_ID) C ON 1 = 1
        LEFT JOIN VALS V273 ON V273.OBJ_ID = L14.OBJ_ID AND V273.PARAM_ID = 273 AND V273.IS_DEL = 0 -- табельный номер
        LEFT JOIN VALL V3581 ON V3581.OBJ_ID = L14.OBJ_ID AND V3581.PARAM_ID = 3581 AND V3581.IS_DEL = 0 -- склеивать периоды
        WHERE L14.PARENT_ID = :V$OU_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
          AND (V74.VAL IS NULL OR V74.VAL >= :V$DATE)
        -- Подразделения
        UNION
        SELECT L14.OBJ_ID, L15.OBJ_ID, V73.VAL, V74.VAL, C.CAPTION, V3543.SVAL, COALESCE(V3580.VAL, 0), V273.SVAL, IIF(V3581.LISTVAL_ID = 3, 0, 1),
          L211.OBJ_ID, (SELECT CAPTION FROM OBJECT_CAPTION_GET(L211.OBJ_ID))
        FROM LINKS L211
        JOIN LINKS L14 ON L14.PARENT_ID = L211.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
        JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
        JOIN VALL V72 ON V72.OBJ_ID = L15.OBJ_ID AND V72.PARAM_ID = 72 AND V72.IS_DEL = 0 AND V72.LISTVAL_ID = 934
        JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0 AND V73.VAL <= :V$DATE2
        JOIN VALS V3543 ON V3543.OBJ_ID = L15.OBJ_ID AND V3543.PARAM_ID = 3543 AND V3543.IS_DEL = 0
        LEFT JOIN VALI V3580 ON V3580.OBJ_ID = L15.OBJ_ID AND V3580.PARAM_ID = 3580 AND V3580.IS_DEL = 0
        LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
        LEFT JOIN OBJECT_CAPTION_GET(L14.OBJ_ID) C ON 1 = 1
        LEFT JOIN VALS V273 ON V273.OBJ_ID = L14.OBJ_ID AND V273.PARAM_ID = 273 AND V273.IS_DEL = 0 -- табельный номер
        LEFT JOIN VALL V3581 ON V3581.OBJ_ID = L14.OBJ_ID AND V3581.PARAM_ID = 3581 AND V3581.IS_DEL = 0 -- склеивать периоды
        WHERE L211.PARENT_ID = :V$OU_ID AND L211.OBJ_TYPE_ID = 211 AND L211.DATE_DEL IS NULL
          AND (V74.VAL IS NULL OR V74.VAL >= :V$DATE)
        -- Уволенные
        UNION
        SELECT L14.OBJ_ID, L15.OBJ_ID, V73.VAL, V74.VAL, C.CAPTION, V3543.SVAL, COALESCE(V3580.VAL, 0), V273.SVAL, IIF(V3581.LISTVAL_ID = 3, 0, 1),
          NULL, NULL
        FROM LINKS L84
        JOIN LINKS L14 ON L14.PARENT_ID = L84.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
        JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
        JOIN VALL V72 ON V72.OBJ_ID = L15.OBJ_ID AND V72.PARAM_ID = 72 AND V72.IS_DEL = 0 AND V72.LISTVAL_ID = 934
        JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0 AND V73.VAL <= :V$DATE2
        JOIN VALS V3543 ON V3543.OBJ_ID = L15.OBJ_ID AND V3543.PARAM_ID = 3543 AND V3543.IS_DEL = 0
        LEFT JOIN VALI V3580 ON V3580.OBJ_ID = L15.OBJ_ID AND V3580.PARAM_ID = 3580 AND V3580.IS_DEL = 0
        LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
        LEFT JOIN OBJECT_CAPTION_GET(L14.OBJ_ID) C ON 1 = 1
        LEFT JOIN VALS V273 ON V273.OBJ_ID = L14.OBJ_ID AND V273.PARAM_ID = 273 AND V273.IS_DEL = 0 -- табельный номер
        LEFT JOIN VALL V3581 ON V3581.OBJ_ID = L14.OBJ_ID AND V3581.PARAM_ID = 3581 AND V3581.IS_DEL = 0 -- склеивать периоды
        WHERE L84.PARENT_ID = :V$OU_ID AND L84.OBJ_TYPE_ID = 84 AND L84.DATE_DEL IS NULL
          AND (V74.VAL IS NULL OR V74.VAL >= :V$DATE)
        ORDER BY 11 NULLS FIRST, 5
        INTO :V$PERSON_ID, :V$JOB_ID, :V$D1, :V$D2, :S, :S2, :N, :S3, :V$MERGE,
          :V$DIV_ID, :V$DIV_NAME
      DO
      BEGIN
        TAG_NAME = 'years:r:items:r';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'years:r:items:r:div_id';
        VAL = V$DIV_ID;
        SUSPEND;
        TAG_NAME = 'years:r:items:r:div_name';
        VAL = V$DIV_NAME;
        SUSPEND;
        TAG_NAME = 'years:r:items:r:person_id';
        VAL = V$PERSON_ID;
        SUSPEND;
        TAG_NAME = 'years:r:items:r:job_id';
        VAL = V$JOB_ID;
        SUSPEND;
        TAG_NAME = 'years:r:items:r:days';
        VAL = N;
        SUSPEND;
        TAG_NAME = 'years:r:items:r:date_from';
        VAL = (SELECT VAL FROM DATE2ISO(:V$D1));
        SUSPEND;
        TAG_NAME = 'years:r:items:r:date_to';
        VAL = (SELECT VAL FROM DATE2ISO(:V$D2));
        SUSPEND;
        TAG_NAME = 'years:r:items:r:name';
        VAL = S;
        SUSPEND;
        TAG_NAME = 'years:r:items:r:job_name';
        VAL = S2;
        SUSPEND;
        TAG_NAME = 'years:r:items:r:tabnum';
        VAL = S3;
        SUSPEND;
        TAG_NAME = 'years:r:items:r:merge_jobs';
        VAL = V$MERGE;
        SUSPEND;
        -- Тут выдаем и хотелки, и план, и факт
        TAG_NAME = 'years:r:items:r:periods::json&colon;array';
        VAL = 1;
        SUSPEND;
        FOR
          SELECT L37.OBJ_ID, V325.VAL, V326.LISTVAL_ID, C326.VAL, V330.LISTVAL_ID, V327.VAL, V328.VAL, V3582.VAL, V329.VAL
          FROM LINKS L37
          LEFT JOIN VALI V325 ON V325.OBJ_ID = L37.OBJ_ID AND V325.PARAM_ID = 325 AND V325.IS_DEL = 0
          JOIN VALL V326 ON V326.OBJ_ID = L37.OBJ_ID AND V326.PARAM_ID = 326 AND V326.IS_DEL = 0
          LEFT JOIN LISTVAL_TEXT(V326.LISTVAL_ID) C326 ON 1 = 1
          JOIN VALL V330 ON V330.OBJ_ID = L37.OBJ_ID AND V330.PARAM_ID = 330 AND V330.IS_DEL = 0
          JOIN VALD V327 ON V327.OBJ_ID = L37.OBJ_ID AND V327.PARAM_ID = 327 AND V327.IS_DEL = 0 AND V327.VAL > :V$DATE AND (V327.VAL <= :V$DATE2 OR :V$DATE2 IS NULL)
          JOIN VALD V328 ON V328.OBJ_ID = L37.OBJ_ID AND V328.PARAM_ID = 328 AND V328.IS_DEL = 0
          JOIN VALI V329 ON V329.OBJ_ID = L37.OBJ_ID AND V329.PARAM_ID = 329 AND V329.IS_DEL = 0
          LEFT JOIN VALR V3582 ON V3582.OBJ_ID = L37.OBJ_ID AND V3582.PARAM_ID = 3582 AND V3582.IS_DEL = 0
          WHERE L37.PARENT_ID = :V$PERSON_ID AND L37.OBJ_TYPE_ID = 37 AND L37.DATE_DEL IS NULL
          ORDER BY V327.VAL
          INTO :V$OBJ_ID, :V$PERIOD, :V$TYPE, :V$TYPE_NAME, :V$PLAN_TYPE, :V$D1, :V$D2, :V$JOB_ID, :N
        DO
        BEGIN
          TAG_NAME = 'years:r:items:r:periods:r';
          VAL = NULL;
          SUSPEND;
          TAG_NAME = 'years:r:items:r:periods:r:id';
          VAL = V$OBJ_ID;
          SUSPEND;
          TAG_NAME = 'years:r:items:r:periods:r:job_id';
          VAL = V$JOB_ID;
          SUSPEND;
          TAG_NAME = 'years:r:items:r:periods:r:type_id';
          VAL = V$TYPE;
          SUSPEND;
          TAG_NAME = 'years:r:items:r:periods:r:type_name';
          VAL = V$TYPE_NAME;
          SUSPEND;
          TAG_NAME = 'years:r:items:r:periods:r:plan_type';
          VAL = V$PLAN_TYPE;
          SUSPEND;
          TAG_NAME = 'years:r:items:r:periods:r:date_from';
          VAL = (SELECT VAL FROM DATE2ISO(:V$D1));
          SUSPEND;
          TAG_NAME = 'years:r:items:r:periods:r:date_to';
          VAL = (SELECT VAL FROM DATE2ISO(:V$D2));
          SUSPEND;
          TAG_NAME = 'years:r:items:r:periods:r:days';
          VAL = N;
          SUSPEND;
        END
      END
    END

    -- Для текущего года выдаем список кандидатов на перенос в факт отпусков
    -- Записи в плане за 2 недели до начала срока по действующим сотрудникам
    -- Старше 3 месяцев в прошлое не лазим, предполагается что там все должно быть внесено
    V$DATE = DATEADD(-3 MONTH TO CURRENT_DATE);
    V$DATE2 = DATEADD(15 DAY TO CURRENT_DATE);
    TAG_NAME = 'fact::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT L14.OBJ_ID, V3582.VAL, L37.OBJ_ID, V327.VAL, V328.VAL, V329.VAL
      FROM LINKS L14
      JOIN LINKS L37 ON L37.PARENT_ID = L14.OBJ_ID AND L37.OBJ_TYPE_ID = 37 AND L37.DATE_DEL IS NULL
      JOIN VALR V3582 ON V3582.OBJ_ID = L37.OBJ_ID AND V3582.PARAM_ID = 3582 AND V3582.IS_DEL = 0
      JOIN VALL V330 ON V330.OBJ_ID = L37.OBJ_ID AND V330.PARAM_ID = 330 AND V330.IS_DEL = 0 AND V330.LISTVAL_ID = 736 -- план
      JOIN VALL V326 ON V326.OBJ_ID = L37.OBJ_ID AND V326.PARAM_ID = 326 AND V326.IS_DEL = 0 AND V326.LISTVAL_ID = 730 -- текущий
      JOIN VALD V327 ON V327.OBJ_ID = L37.OBJ_ID AND V327.PARAM_ID = 327 AND V327.IS_DEL = 0 -- дата начала
        AND V327.VAL >= :V$DATE AND V327.VAL < :V$DATE2
      JOIN VALD V328 ON V328.OBJ_ID = L37.OBJ_ID AND V328.PARAM_ID = 328 AND V328.IS_DEL = 0 -- дата окончания
      JOIN VALI V329 ON V329.OBJ_ID = L37.OBJ_ID AND V329.PARAM_ID = 329 AND V329.IS_DEL = 0 -- дата начала
      WHERE L14.PARENT_ID = :V$OU_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
      AND NOT EXISTS(
        SELECT FIRST 1 1
        FROM LINKS L37X
        JOIN VALR V3582X ON V3582X.OBJ_ID = L37X.OBJ_ID AND V3582X.PARAM_ID = 3582 AND V3582X.IS_DEL = 0 AND V3582X.VAL = V3582.VAL
        JOIN VALL V330X ON V330X.OBJ_ID = L37X.OBJ_ID AND V330X.PARAM_ID = 330 AND V330X.IS_DEL = 0 AND V330X.LISTVAL_ID = 735 -- факт
        JOIN VALL V326X ON V326X.OBJ_ID = L37X.OBJ_ID AND V326X.PARAM_ID = 326 AND V326X.IS_DEL = 0 AND V326X.LISTVAL_ID = 730 -- текущий
        JOIN VALD V327X ON V327X.OBJ_ID = L37X.OBJ_ID AND V327X.PARAM_ID = 327 AND V327X.IS_DEL = 0 -- дата начала плюс-минус 2 недели от заданной
          AND V327X.VAL >= DATEADD(-2 WEEK TO V327.VAL) AND V327X.VAL <= DATEADD(2 WEEK TO V327.VAL)
        WHERE L37X.PARENT_ID = L14.OBJ_ID AND L37X.OBJ_TYPE_ID = 37 AND L37X.DATE_DEL IS NULL
      )
      ORDER BY 1, 2, 4
      INTO :V$PERSON_ID, :V$JOB_ID, :V$OBJ_ID, :V$D1, :V$D2, :N
    DO
    BEGIN
      TAG_NAME = 'fact:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'fact:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'fact:r:person_id';
      VAL = V$PERSON_ID;
      SUSPEND;
      TAG_NAME = 'fact:r:job_id';
      VAL = V$JOB_ID;
      SUSPEND;
      TAG_NAME = 'fact:r:date_from';
      VAL = (SELECT VAL FROM DATE2ISO(:V$D1));
      SUSPEND;
      TAG_NAME = 'fact:r:date_to';
      VAL = (SELECT VAL FROM DATE2ISO(:V$D2));
      SUSPEND;
      TAG_NAME = 'fact:r:days';
      VAL = N;
      SUSPEND;
    END

    EXIT;
  END

  -- Конкретный отпуск
  IF(V$TYPE_ID = 37) THEN
  BEGIN
    SELECT FIRST 1 L37.OBJ_ID, L37.PARENT_ID, V325.VAL, V326.LISTVAL_ID, C326.VAL, V330.LISTVAL_ID, V327.VAL, V328.VAL, V329.VAL, V1401.VAL, V3582.VAL, V3543.SVAL
    FROM LINKS L37
    LEFT JOIN VALI V325 ON V325.OBJ_ID = L37.OBJ_ID AND V325.PARAM_ID = 325 AND V325.IS_DEL = 0
    JOIN VALL V326 ON V326.OBJ_ID = L37.OBJ_ID AND V326.PARAM_ID = 326 AND V326.IS_DEL = 0
    LEFT JOIN LISTVAL_TEXT(V326.LISTVAL_ID) C326 ON 1 = 1
    LEFT JOIN VALL V330 ON V330.OBJ_ID = L37.OBJ_ID AND V330.PARAM_ID = 330 AND V330.IS_DEL = 0
    JOIN VALD V327 ON V327.OBJ_ID = L37.OBJ_ID AND V327.PARAM_ID = 327 AND V327.IS_DEL = 0
    LEFT JOIN VALD V328 ON V328.OBJ_ID = L37.OBJ_ID AND V328.PARAM_ID = 328 AND V328.IS_DEL = 0
    LEFT JOIN VALI V329 ON V329.OBJ_ID = L37.OBJ_ID AND V329.PARAM_ID = 329 AND V329.IS_DEL = 0
    LEFT JOIN VALS V1401 ON V1401.OBJ_ID = L37.OBJ_ID AND V1401.PARAM_ID = 1401 AND V1401.IS_DEL = 0
    LEFT JOIN VALR V3582 ON V3582.OBJ_ID = L37.OBJ_ID AND V3582.PARAM_ID = 3582 AND V3582.IS_DEL = 0
    LEFT JOIN VALS V3543 ON V3543.OBJ_ID = V3582.VAL AND V3543.PARAM_ID = 3543 AND V3543.IS_DEL = 0
    WHERE L37.OBJ_ID = :I$OBJ_ID AND L37.PARENT_TYPE_ID = 14 AND L37.DATE_DEL IS NULL
    ORDER BY V327.VAL
    INTO :V$OBJ_ID, :V$PERSON_ID, :V$PERIOD, :V$TYPE, :V$TYPE_NAME, :V$PLAN_TYPE, :V$D1, :V$D2, :N, :S, :V$JOB_ID, :S2;

    IF(V$OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Запись отпуска не найдена';

    TAG_NAME = 'id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'person_id';
    VAL = V$PERSON_ID;
    SUSPEND;
    TAG_NAME = 'period';
    VAL = V$PERIOD;
    SUSPEND;
    TAG_NAME = 'type_id';
    VAL = V$TYPE;
    SUSPEND;
    TAG_NAME = 'type_name';
    VAL = V$TYPE_NAME;
    SUSPEND;
    TAG_NAME = 'plan_type';
    VAL = V$PLAN_TYPE;
    SUSPEND;
    TAG_NAME = 'date_from';
    VAL = (SELECT VAL FROM DATE2ISO(:V$D1));
    SUSPEND;
    TAG_NAME = 'date_to';
    VAL = (SELECT VAL FROM DATE2ISO(:V$D2));
    SUSPEND;
    TAG_NAME = 'days';
    VAL = N;
    SUSPEND;
    TAG_NAME = 'comments';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'job_id';
    VAL = V$JOB_ID;
    SUSPEND;
    TAG_NAME = 'job_name';
    VAL = S2;
    SUSPEND;
    TAG_NAME = 'name';
    VAL = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$PERSON_ID));
    SUSPEND;

    EXIT;
  END

  -- Дальше только кейс: Сотрудник
  -- Какого числа принят на работу в последнем цикле ?
  -- Смотрим основную должность
  SELECT FIRST 1 V73.VAL, V74.VAL
  FROM LINKS L15
  JOIN VALL V72 ON V72.OBJ_ID = L15.OBJ_ID AND V72.PARAM_ID = 72 AND V72.IS_DEL = 0 AND V72.LISTVAL_ID = 934
  JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0
  LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
  WHERE L15.PARENT_ID = :I$OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
  ORDER BY 1 DESC
  INTO :V$DATE, :V$DATE2;

  TAG_NAME = 'date_in';
  VAL = (SELECT VAL FROM DATE2ISO(:V$DATE));
  SUSPEND;
  TAG_NAME = 'date_out';
  VAL = (SELECT VAL FROM DATE2ISO(:V$DATE2));
  SUSPEND;
  TAG_NAME = 'name';
  VAL = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$OBJ_ID));
  SUSPEND;

  TAG_NAME = 'jobs::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L15.OBJ_ID, V3543.SVAL, V73.VAL, V74.VAL, V3580.VAL
    FROM LINKS L15
    JOIN VALL V72 ON V72.OBJ_ID = L15.OBJ_ID AND V72.PARAM_ID = 72 AND V72.IS_DEL = 0
    JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
    LEFT JOIN VALS V3543 ON V3543.OBJ_ID = L15.OBJ_ID AND V3543.PARAM_ID = 3543 AND V3543.IS_DEL = 0
    LEFT JOIN VALI V3580 ON V3580.OBJ_ID = L15.OBJ_ID AND V3580.PARAM_ID = 3580 AND V3580.IS_DEL = 0
    WHERE L15.PARENT_ID = :I$OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL AND V74.VAL IS NULL
    ORDER BY V72.LISTVAL_ID, V73.VAL DESC, 2
    INTO :V$OBJ_ID, :S, :V$D1, :V$D2, :N
  DO
  BEGIN
    TAG_NAME = 'jobs:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'jobs:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'jobs:r:value';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'jobs:r:vdays';
    -- Пытаемся угадать из должности - 28 или 56
    IF(N IS NULL) THEN
    BEGIN
      N = 28;
      SELECT FIRST 1 56
      FROM LINKS LP13
      JOIN VALL V589 ON V589.OBJ_ID = LP13.PARENT_ID AND V589.PARAM_ID = 589 AND V589.IS_DEL = 0
      JOIN LISTVALS LV ON LV.LISTVAL_ID = V589.LISTVAL_ID AND (LV.TAG = 'U' OR LV."FILTER" = 'U')
      WHERE LP13.OBJ_ID = :V$OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
      INTO :N;
    END
    VAL = N;
    SUSPEND;
    TAG_NAME = 'jobs:r:date_from';
    VAL = (SELECT VAL FROM DATE2ISO(:V$D1, 0));
    SUSPEND;
    TAG_NAME = 'jobs:r:date_to';
    VAL = (SELECT VAL FROM DATE2ISO(:V$D2, 0));
    SUSPEND;
  END

  TAG_NAME = 'items::json&colon;array';
  VAL = 1;
  SUSPEND;
  -- Необходимо итерироваться по последовательным периодам работы в ОУ независимо
  -- сами периоды обсчитываем уже на фронте
  -- Идти только по основным должностям нельзя - они могут менять статус, и будут потери данных
  -- Идем обязательно по непересекающимся периодам работы в ОУ
  V$DATE = NULL;
  SELECT FIRST 1 V73.VAL
  FROM LINKS L15
  JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0
  WHERE L15.PARENT_ID = :I$OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
  ORDER BY 1
  INTO :V$DATE;
  WHILE(V$DATE IS NOT NULL) DO
  BEGIN
    -- Конец текущего периода выборки
    -- Будет либо незакрытый период, либо после данного периода есть окно в занятости
    V$DATE2 = NULL;
    SELECT FIRST 1 V74.VAL
    FROM LINKS L15
    JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0 AND V73.VAL >= :V$DATE
    LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
    WHERE L15.PARENT_ID = :I$OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL AND (V74.VAL IS NULL OR EXISTS(
      SELECT FIRST 1 1
      FROM LINKS L15N
      JOIN VALD V73N ON V73.OBJ_ID = L15N.OBJ_ID AND V73N.PARAM_ID = 73 AND V73N.IS_DEL = 0 AND V73N.VAL > V74.VAL
      WHERE L15N.PARENT_ID = L15.PARENT_ID AND L15N.OBJ_TYPE_ID = 15 AND L15N.DATE_DEL IS NULL
    ))
    ORDER BY 1 DESC NULLS FIRST
    INTO :V$DATE2;

    TAG_NAME = 'items:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'items:r:range_from';
    VAL = (SELECT VAL FROM DATE2ISO(:V$DATE));
    SUSPEND;
    TAG_NAME = 'items:r:range_to';
    VAL = (SELECT VAL FROM DATE2ISO(:V$DATE2));
    SUSPEND;
    TAG_NAME = 'items:r:periods::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT L37.OBJ_ID, V325.VAL, V326.LISTVAL_ID, C326.VAL, V330.LISTVAL_ID, V327.VAL, V328.VAL, V329.VAL, V1401.VAL, V3582.VAL, V3543.SVAL
      FROM LINKS L37
      LEFT JOIN VALI V325 ON V325.OBJ_ID = L37.OBJ_ID AND V325.PARAM_ID = 325 AND V325.IS_DEL = 0
      JOIN VALL V326 ON V326.OBJ_ID = L37.OBJ_ID AND V326.PARAM_ID = 326 AND V326.IS_DEL = 0
      LEFT JOIN LISTVAL_TEXT(V326.LISTVAL_ID) C326 ON 1 = 1
      LEFT JOIN VALL V330 ON V330.OBJ_ID = L37.OBJ_ID AND V330.PARAM_ID = 330 AND V330.IS_DEL = 0
      JOIN VALD V327 ON V327.OBJ_ID = L37.OBJ_ID AND V327.PARAM_ID = 327 AND V327.IS_DEL = 0 AND V327.VAL > :V$DATE AND (V327.VAL <= :V$DATE2 OR :V$DATE2 IS NULL)
      LEFT JOIN VALD V328 ON V328.OBJ_ID = L37.OBJ_ID AND V328.PARAM_ID = 328 AND V328.IS_DEL = 0
      LEFT JOIN VALI V329 ON V329.OBJ_ID = L37.OBJ_ID AND V329.PARAM_ID = 329 AND V329.IS_DEL = 0
      LEFT JOIN VALS V1401 ON V1401.OBJ_ID = L37.OBJ_ID AND V1401.PARAM_ID = 1401 AND V1401.IS_DEL = 0
      LEFT JOIN VALR V3582 ON V3582.OBJ_ID = L37.OBJ_ID AND V3582.PARAM_ID = 3582 AND V3582.IS_DEL = 0
      LEFT JOIN VALS V3543 ON V3543.OBJ_ID = V3582.VAL AND V3543.PARAM_ID = 3543 AND V3543.IS_DEL = 0
      WHERE L37.PARENT_ID = :I$OBJ_ID AND L37.OBJ_TYPE_ID = 37 AND L37.DATE_DEL IS NULL
      ORDER BY V327.VAL
      INTO :V$OBJ_ID, :V$PERIOD, :V$TYPE, :V$TYPE_NAME, :V$PLAN_TYPE, :V$D1, :V$D2, :N, :S, :V$JOB_ID, :S2
    DO
    BEGIN
      TAG_NAME = 'items:r:periods:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'items:r:periods:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'items:r:periods:r:period';
      IF(V$PERIOD IS NULL) THEN V$PERIOD = EXTRACT(YEAR FROM V$D1);
      VAL = V$PERIOD;
      SUSPEND;
      TAG_NAME = 'items:r:periods:r:type_id';
      VAL = V$TYPE;
      SUSPEND;
      TAG_NAME = 'items:r:periods:r:type_name';
      VAL = V$TYPE_NAME;
      SUSPEND;
      TAG_NAME = 'items:r:periods:r:plan_type';
      VAL = V$PLAN_TYPE;
      SUSPEND;
      TAG_NAME = 'items:r:periods:r:date_from';
      VAL = (SELECT VAL FROM DATE2ISO(:V$D1));
      SUSPEND;
      TAG_NAME = 'items:r:periods:r:date_to';
      VAL = (SELECT VAL FROM DATE2ISO(:V$D2));
      SUSPEND;
      TAG_NAME = 'items:r:periods:r:days';
      VAL = N;
      SUSPEND;
      TAG_NAME = 'items:r:periods:r:comments';
      VAL = S;
      SUSPEND;
      TAG_NAME = 'items:r:periods:r:job_id';
      VAL = V$JOB_ID;
      SUSPEND;
      TAG_NAME = 'items:r:periods:r:job_name';
      VAL = S2;
      SUSPEND;
    END

    -- Ищем дату начала следующего периода
    V$DATE = NULL;
    IF(V$DATE2 IS NOT NULL) THEN
    SELECT FIRST 1 V73.VAL
    FROM LINKS L15
    JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0 AND V73.VAL > :V$DATE2
    WHERE L15.PARENT_ID = :I$OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
    ORDER BY 1
    INTO :V$DATE;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE VALIDATE_CURRENT_YEAR (
    I$YEAR_LV BIGINT)
AS
declare variable CURRENT_YEAR integer;
begin

    SELECT SUBSTRING(R.VAL FROM 1 FOR 4)
    FROM LISTVALS LV
    JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
    WHERE LV.LISTVAL_ID = :I$YEAR_LV AND LV.IS_DEL = 0
    INTO :CURRENT_YEAR;

    -- В период с июня по август можно выставлять как текущий, так и предыдущий учебный год
    IF(EXTRACT(MONTH FROM CURRENT_DATE) <= 5) THEN
    BEGIN
      -- Только предыдущий учебный год
      IF(CURRENT_YEAR <> EXTRACT(YEAR FROM CURRENT_DATE) - 1) THEN EXCEPTION DATA_ERROR 'Допускается выбор только текущего учебного года';
    END
    ELSE IF(EXTRACT(MONTH FROM CURRENT_DATE) >= 9) THEN
    BEGIN
      -- Только текущий учебный год
     IF(CURRENT_YEAR <> EXTRACT(YEAR FROM CURRENT_DATE)) THEN EXCEPTION DATA_ERROR 'Допускается выбор только текущего учебного года';
    END
    ELSE
    BEGIN
      -- Текущий или будущий учебный год
      IF((CURRENT_YEAR <> EXTRACT(YEAR FROM CURRENT_DATE)) AND (CURRENT_YEAR <> EXTRACT(YEAR FROM CURRENT_DATE) - 1)) THEN
        EXCEPTION DATA_ERROR 'Допускается выбор только текущего или нового учебного года. Будьте осторожны: при ошибке ввода возможно нарушение работы перевода года';
    END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE VALIDATE_DEFAULT_JOB (
    I$OBJ_ID BIGINT)
AS
begin

  IF(EXISTS(
      SELECT FIRST 1 1
      FROM LINKS LP14
      JOIN LINKS L15 ON L15.PARENT_ID = LP14.PARENT_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL AND L15.OBJ_ID <> :I$OBJ_ID
      JOIN VALL V2934 ON V2934.OBJ_ID = L15.OBJ_ID AND V2934.PARAM_ID = 2934 AND V2934.IS_DEL = 0 AND V2934.LISTVAL_ID = 2
      WHERE LP14.OBJ_ID = :I$OBJ_ID AND LP14.PARENT_TYPE_ID = 14 AND LP14.DATE_DEL IS NULL
  )) THEN
  BEGIN
      EXCEPTION DATA_ERROR 'Должность по-умолчанию у данного сотрудника уже задана';
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE VALIDATE_KUG (
    I$OBJ_ID BIGINT,
    I$YEAR_ID BIGINT)
AS
declare variable V$PREV_KUG bigint;
declare variable V$PERIOD_ID bigint;
declare variable T integer;
begin

  -- Проверка уникальности учебного года
  IF(EXISTS(
    SELECT FIRST 1 1
    FROM LINKS LP2
    JOIN LINKS L481 ON L481.PARENT_ID = LP2.PARENT_ID AND L481.OBJ_TYPE_ID = 481 AND L481.DATE_DEL IS NULL AND L481.OBJ_ID <> LP2.OBJ_ID
    JOIN VALL V3389 ON V3389.OBJ_ID = L481.OBJ_ID AND V3389.PARAM_ID = 3389 AND V3389.IS_DEL = 0 AND V3389.LISTVAL_ID = :I$YEAR_ID
    JOIN VALL V3390 ON V3390.OBJ_ID = L481.OBJ_ID AND V3390.PARAM_ID = 3390 AND V3390.IS_DEL = 0 AND V3390.LISTVAL_ID IN (11715, 11716)
    WHERE LP2.OBJ_ID = :I$OBJ_ID AND LP2.PARENT_TYPE_ID = 2 AND LP2.DATE_DEL IS NULL
  ))
  THEN
    EXCEPTION DATA_ERROR 'В статусе проект или действующий в пределах одного учебного года может находиться только один График';

  -- Нельзя менять год, когда стоит действующий статус
  IF(EXISTS(
    SELECT FIRST 1 1
    FROM VALL V3390
    WHERE V3390.OBJ_ID = :I$OBJ_ID AND V3390.PARAM_ID = 3390 AND V3390.IS_DEL = 0 AND V3390.LISTVAL_ID <> 11716
  ))
  THEN
    EXCEPTION DATA_ERROR 'Нельзя менять учебный год не в статусе проект';

  -- Если у нас не был указан учебный год, а затем стал - копируем ссылки на учебные периоды из предыдущего КУГ этого же года
  IF(NOT EXISTS(
    SELECT FIRST 1 1
    FROM LINKS L151
    WHERE L151.PARENT_ID = :I$OBJ_ID AND L151.OBJ_TYPE_ID = 151 AND L151.DATE_DEL IS NULL
  ))
  THEN
  BEGIN
    SELECT FIRST 1 L481.OBJ_ID
    FROM LINKS LP2
    JOIN LINKS L481 ON L481.PARENT_ID = LP2.PARENT_ID AND L481.OBJ_TYPE_ID = 481 AND L481.DATE_DEL IS NULL AND L481.OBJ_ID <> LP2.OBJ_ID
    JOIN VALL V3389 ON V3389.OBJ_ID = L481.OBJ_ID AND V3389.PARAM_ID = 3389 AND V3389.IS_DEL = 0 AND V3389.LISTVAL_ID = :I$YEAR_ID
    JOIN VALL V3390 ON V3390.OBJ_ID = L481.OBJ_ID AND V3390.PARAM_ID = 3390 AND V3390.IS_DEL = 0 AND V3390.LISTVAL_ID = 11716
    WHERE LP2.OBJ_ID = :I$OBJ_ID AND LP2.PARENT_TYPE_ID = 2 AND LP2.DATE_DEL IS NULL
    INTO :V$PREV_KUG;

    FOR
      SELECT L151.OBJ_ID
      FROM LINKS L151
      WHERE L151.PARENT_ID = :V$PREV_KUG AND L151.OBJ_TYPE_ID = 151 AND L151.DATE_DEL IS NULL
      INTO :V$PERIOD_ID
    DO
    BEGIN
      SELECT 1 FROM OBJECT_ADD_LINK(:I$OBJ_ID, :V$PERIOD_ID, 151) INTO :T;
    END
  END


end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE VALIDATE_LAST_JOB (
    I$OBJ_ID BIGINT)
AS
declare variable V$PERSON_ID bigint;
declare variable V$GRADE_NAME varchar(2000);
declare variable V$GRADE_ID bigint;
declare variable V$GRADE_TYPE_ID bigint;
declare variable TMP bigint;
begin

  SELECT FIRST 1 LP14.PARENT_ID
  FROM LINKS LP14
  WHERE LP14.OBJ_ID = :I$OBJ_ID AND LP14.PARENT_TYPE_ID = 14 AND LP14.DATE_DEL IS NULL
  INTO :V$PERSON_ID;

  -- Если есть хоть одна педагогическая должность, больше ничего не нужно
  IF(EXISTS(
      SELECT FIRST 1 1
      FROM LINKS L15
      JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
      LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
      LEFT JOIN DO_FUNC(LP13.PARENT_ID, 400) DF ON 1 = 1
      WHERE L15.PARENT_ID = :V$PERSON_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL AND V74.VAL IS NULL AND DF.I = 1
  ))
  THEN EXIT;

  -- Должны быть обнулены учебные нагрузки (в случае с потоками поверх ГУП, пропускаем такие)
  /* SELECT FIRST 1 C.CAPTION, LPG.PARENT_ID, LPG.PARENT_TYPE_ID
  FROM LINKS L58
  JOIN LINKS LPG ON LPG.OBJ_ID = L58.OBJ_ID AND LPG.PARENT_TYPE_ID IN (256, 347) AND LPG.DATE_DEL IS NULL
  JOIN LINKS LP ON LP.OBJ_ID = LPG.PARENT_ID AND LP.PARENT_TYPE_ID IN (54, 346) AND LP.DATE_DEL IS NULL
  JOIN LINKS LP51 ON LP51.OBJ_ID = L58.OBJ_ID AND LP51.PARENT_TYPE_ID = 51 AND LP51.DATE_DEL IS NULL
  LEFT JOIN OBJECT_CAPTION_GET(LPG.PARENT_ID) C ON 1 = 1
  WHERE L58.PARENT_ID = :V$PERSON_ID AND L58.OBJ_TYPE_ID = 58 AND L58.DATE_DEL IS NULL
      AND (LPG.PARENT_TYPE_ID <> 256 OR (NOT EXISTS(
          -- Проверяем, нет ли потоков по тому же предмету
          SELECT FIRST 1 1
          FROM LINKS L346
          JOIN VALR V2705 ON V2705.OBJ_ID = L346.OBJ_ID AND V2705.PARAM_ID = 2705 AND V2705.IS_DEL = 0 AND V2705.VAL = LP51.PARENT_ID
          WHERE L346.PARENT_ID = LP.PARENT_ID AND L346.OBJ_TYPE_ID = 346 AND L346.DATE_DEL IS NULL
      )))
  INTO :V$GRADE_NAME, :V$GRADE_ID, :V$GRADE_TYPE_ID;

  IF(V$GRADE_NAME IS NOT NULL) THEN
  BEGIN
      IF(V$GRADE_TYPE_ID = 256) THEN
      BEGIN
          SELECT FIRST 1 :V$GRADE_NAME || ', ' || C54.CAPTION || ', ' || COALESCE(V374.VAL, '')
          FROM LINKS LP54
          LEFT JOIN OBJECT_CAPTION_GET(LP54.PARENT_ID) C54 ON 1 = 1
          JOIN LINKS LP50 ON LP50.OBJ_ID = LP54.PARENT_ID AND LP50.PARENT_TYPE_ID = 50 AND LP50.DATE_DEL IS NULL
          JOIN VALS V374 ON V374.OBJ_ID = LP50.PARENT_ID AND V374.PARAM_ID = 374 AND V374.IS_DEL = 0
          WHERE LP54.OBJ_ID = :V$GRADE_ID AND LP54.PARENT_TYPE_ID = 54 AND LP54.DATE_DEL IS NULL
          INTO :V$GRADE_NAME;
      END
      ELSE
      BEGIN
          SELECT FIRST 1 :V$GRADE_NAME || ', ' || C54.CAPTION || ', ' || COALESCE(V374.VAL, '')
          FROM LINKS LP346
          JOIN LINKS LP54 ON LP54.OBJ_ID = LP346.PARENT_ID AND LP54.PARENT_TYPE_ID = 54 AND LP54.DATE_DEL IS NULL
          LEFT JOIN OBJECT_CAPTION_GET(LP54.PARENT_ID) C54 ON 1 = 1
          JOIN LINKS LP50 ON LP50.OBJ_ID = LP54.PARENT_ID AND LP50.PARENT_TYPE_ID = 50 AND LP50.DATE_DEL IS NULL
          JOIN VALS V374 ON V374.OBJ_ID = LP50.PARENT_ID AND V374.PARAM_ID = 374 AND V374.IS_DEL = 0
          WHERE LP346.OBJ_ID = :V$GRADE_ID AND LP346.PARENT_TYPE_ID = 346 AND LP346.DATE_DEL IS NULL
          INTO :V$GRADE_NAME;
      END

      EXCEPTION DATA_ERROR 'При снятии с последней педагогической должности должны быть сняты учебные нагрузки (см. ' || V$GRADE_NAME || ')';
  END */

  -- Принудительно снимаем все учебные нагрузки
  UPDATE LINKS
  SET DATE_DEL = CURRENT_TIMESTAMP
  WHERE PARENT_ID = :I$OBJ_ID AND OBJ_TYPE_ID = 58 AND DATE_DEL IS NULL;

  -- Должно быть снято классное руководство, когда полностью уволен
  IF(EXISTS(
      SELECT FIRST 1 1
      FROM LINKS L15
      JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
      LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
      WHERE L15.PARENT_ID = :V$PERSON_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL AND V74.VAL IS NULL
  ))
  THEN EXIT;

  /*SELECT FIRST 1 C.CAPTION
  FROM VALR V53
  JOIN LINKS LPG ON LPG.OBJ_ID = V53.OBJ_ID AND LPG.PARENT_TYPE_ID = 8 AND LPG.DATE_DEL IS NULL
  LEFT JOIN OBJECT_CAPTION_GET(LPG.OBJ_ID) C ON 1 = 1
  WHERE V53.VAL = :V$PERSON_ID AND V53.PARAM_ID = 53 AND V53.IS_DEL = 0
  INTO :V$GRADE_NAME;

  IF(V$GRADE_NAME IS NOT NULL) THEN EXCEPTION DATA_ERROR 'Не снято классное руководство (см. ' || V$GRADE_NAME || ')';*/

  -- Снимаем классное руководство при полном увольнении
  FOR
      SELECT LPG.OBJ_ID
      FROM VALR V53
      JOIN LINKS LPG ON LPG.OBJ_ID = V53.OBJ_ID AND LPG.PARENT_TYPE_ID = 8 AND LPG.DATE_DEL IS NULL
      WHERE V53.VAL = :V$PERSON_ID AND V53.PARAM_ID = 53 AND V53.IS_DEL = 0
      INTO :V$GRADE_ID
  DO
  BEGIN
      SELECT BLOB_ID FROM VAL_ADD(53, :V$GRADE_ID, '') INTO :TMP;
  END

  -- Снимаем руководство ГПД и прочих групп
  FOR
      SELECT LPG.OBJ_ID
      FROM VALR V1609
      JOIN LINKS LPG ON LPG.OBJ_ID = V1609.OBJ_ID AND LPG.PARENT_TYPE_ID = 46 AND LPG.DATE_DEL IS NULL
      WHERE V1609.VAL = :V$PERSON_ID AND V1609.PARAM_ID = 1609 AND V1609.IS_DEL = 0
      INTO :V$GRADE_ID
  DO
  BEGIN
      UPDATE LINKS L186
      SET DATE_DEL = CURRENT_TIMESTAMP
      WHERE DATE_DEL IS NULL AND OBJ_ID = :V$GRADE_ID AND PARENT_TYPE_ID = 46;
  END

  -- Проставить дату окончания действия для записи пользователя
  -- !!!

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE VAL_ADD (
    I$PARAM_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$VAL VARCHAR(4000),
    I$USER_ID BIGINT = null,
    I$IS_DEL SMALLINT = 0,
    I$PROCESS_TAG SMALLINT = 1,
    I$LINK_ID BIGINT = null)
RETURNS (
    BLOB_ID BIGINT,
    REFRESH_FLAG VARCHAR(100),
    ID BIGINT)
AS
declare variable VAL_TYPE varchar(100);
declare variable I bigint;
declare variable TAG varchar(100);
declare variable IS_LINK_REFERENSE smallint;
declare variable OLD_REFERENSE_ID bigint;
declare variable OBJ_ID bigint;
declare variable TYPE_ID bigint;
declare variable V varchar(4000);
declare variable V_LONG varchar(4000);
declare variable LANG_CODE varchar(2);
declare variable V$OBJ_ID bigint;
declare variable V$OLD_USER bigint;
declare variable USER_TYPE smallint;
declare variable V$VAL_ID bigint;
declare variable V$PT smallint;
declare variable V$WAS_DEL smallint;
BEGIN
    SELECT LANG_CODE, USER_TYPE
    FROM USERS
    WHERE USER_ID = :I$USER_ID
    INTO :LANG_CODE, :USER_TYPE;

    BLOB_ID = NULL;
    REFRESH_FLAG = NULL;
    ID = NULL;

    IF (I$VAL IS NULL) THEN I$VAL = '';
    IF (I$VAL = '') THEN I$IS_DEL = 1;

    IF ((I$IS_DEL = 1) AND (I$VAL = '')) THEN
    BEGIN
        SELECT V, I
        FROM VAL_GET(:I$OBJ_ID, :I$PARAM_ID)
        INTO :V, :V_LONG;

        IF (V_LONG <> '0') THEN I$VAL = V_LONG;
        ELSE IF (V <> '') THEN I$VAL = V;
        ELSE I$VAL = NULL;
    END

    IF (I$VAL IS NULL) THEN EXIT;

    SELECT PT.VAL_TYPE, P.TAG, P.IS_LINK_REFERENSE, P.TYPE_ID, P.PARAM_TYPE
    FROM PARAMS P
    JOIN PARAMTYPES PT ON P.PARAM_TYPE = PT.PARAM_TYPE
    WHERE PARAM_ID = :I$PARAM_ID
    INTO :VAL_TYPE, :TAG, :IS_LINK_REFERENSE, :TYPE_ID, :V$PT;

    IF (I$LINK_ID IS NOT NULL) THEN
    BEGIN
        SELECT FIRST 1 IIF(OBJ_TYPE_ID = :TYPE_ID, OBJ_ID, EXT_OBJ_ID)
        FROM LINKS
        WHERE LINK_ID = :I$LINK_ID AND OBJ_ID = :I$OBJ_ID AND (OBJ_TYPE_ID = :TYPE_ID OR EXT_OBJ_TYPE_ID = :TYPE_ID)
        INTO :I$OBJ_ID;
    END

    IF (TAG = 'DEFAULT_DOC') THEN
    BEGIN
        REFRESH_FLAG = 'REFRESH_TAB';
        IF (I$VAL = 2) THEN
        BEGIN
            FOR
                SELECT L79.OBJ_ID
                FROM LINKS LP10
                JOIN LINKS L79 ON L79.PARENT_ID = LP10.PARENT_ID AND L79.OBJ_TYPE_ID = 79 AND L79.DATE_DEL IS NULL AND L79.OBJ_ID <> :I$OBJ_ID
                JOIN VALL V2457 ON V2457.OBJ_ID = L79.OBJ_ID AND V2457.PARAM_ID = 2457 AND V2457.IS_DEL = 0 AND V2457.LISTVAL_ID = 2
                WHERE LP10.OBJ_ID = :I$OBJ_ID AND LP10.PARENT_TYPE_ID = 10 AND LP10.DATE_DEL IS NULL
                INTO :V$OBJ_ID
            DO
            BEGIN
                UPDATE OR INSERT INTO VALL (PARAM_ID, OBJ_ID, USER_ID, LISTVAL_ID, DATE_MODIFY)
                VALUES (2457, :V$OBJ_ID, :I$USER_ID, 3, CURRENT_TIMESTAMP);
            END
        END
        ELSE IF ((I$VAL = 3) AND NOT EXISTS(
            SELECT L79.OBJ_ID
            FROM LINKS LP10
            JOIN LINKS L79 ON L79.PARENT_ID = LP10.PARENT_ID AND L79.OBJ_TYPE_ID = 79 AND L79.DATE_DEL IS NULL AND L79.OBJ_ID <> :I$OBJ_ID
            WHERE LP10.OBJ_ID = :I$OBJ_ID AND LP10.PARENT_TYPE_ID = 10 AND LP10.DATE_DEL IS NULL
        )) THEN
        BEGIN
            I$VAL = '2';
        END
    END
    ELSE IF (TAG = 'DIVISION_SUBJECT') THEN
    BEGIN
        -- Это не может работать с 2015 года !
        V = NULL;
        /* old subject */
        SELECT V.VAL
        FROM VALR V
        WHERE V.PARAM_ID = :I$PARAM_ID AND V.OBJ_ID = :I$OBJ_ID AND V.IS_DEL = 0
        INTO :V;
        /* parent class */
        I = NULL;
        SELECT FIRST 1 L9.PARENT_ID
        FROM LINKS L9
        WHERE L9.PARENT_TYPE_ID = 9 AND L9.OBJ_ID = :I$OBJ_ID AND L9.DATE_DEL IS NULL
        INTO :I;

        FOR
            SELECT L9.OBJ_ID
            FROM LINKS L9
            JOIN LINKS L51 ON L51.OBJ_ID = L9.OBJ_ID AND ((L51.PARENT_ID = :I$VAL) OR (L51.PARENT_ID = :V)) AND L51.OBJ_TYPE_ID = 58 AND L51.DATE_DEL IS NULL
            WHERE L9.PARENT_ID = :I AND L9.OBJ_TYPE_ID = 58 AND L9.DATE_DEL IS NULL
            INTO :OBJ_ID
        DO
        BEGIN
            UPDATE LINKS L
            SET L.DATE_DEL = CURRENT_TIMESTAMP
            WHERE L.OBJ_ID = :OBJ_ID AND L.DATE_DEL IS NULL;
        END
    END
    -- Длительный отпуск
    ELSE IF(TYPE_ID = 376) THEN
    BEGIN
      EXECUTE PROCEDURE LONGVACATION_CHANGE(:I$OBJ_ID, :I$PARAM_ID, :I$VAL, :I$IS_DEL);
      REFRESH_FLAG = 'REFRESH_TAB';
    END
    ELSE IF(I$PARAM_ID IN (2985, 2987, 2988, 2989)) THEN
    BEGIN
        EXECUTE PROCEDURE CHECK_EMPL_MENTOR(:I$OBJ_ID, :I$PARAM_ID, :I$VAL, :I$IS_DEL);
        REFRESH_FLAG = 'REFRESH_TAB';
    END
    -- ОПФ откуда прибыл - замена списка 258 на 4
    ELSE IF(I$PARAM_ID = 160) THEN
    BEGIN
        SELECT FIRST 1 LV4.LISTVAL_ID
        FROM LISTVALS LV258
        JOIN LISTVALS LV4 ON LV4.LIST_ID = 4 AND LV4.TAG = LV258.TAG
        WHERE LV258.LIST_ID = 258 AND LV258.LISTVAL_ID = :I$VAL
        INTO :I$VAL;
    END
    -- Проверяем корректность ввода срока освоения ОП
    ELSE IF(I$PARAM_ID = 399 AND I$IS_DEL = 0) THEN
    BEGIN
        EXECUTE PROCEDURE VERIFY_OP_DURATION(:I$OBJ_ID, :I$VAL);
    END
    -- Проверяем корректность ввода стандарта
    ELSE IF(I$PARAM_ID IN (2478, 3014) AND I$IS_DEL = 0) THEN
    BEGIN
        EXECUTE PROCEDURE VERIFY_UP_STD(:I$OBJ_ID, :I$VAL);
    END
    -- запрет выбора значения вне списка
    ELSE IF(I$PARAM_ID = 167 AND I$IS_DEL = 0) THEN
    BEGIN
        IF(NOT EXISTS(SELECT 1 FROM LISTVALS_LIST(53) WHERE VAL = :I$VAL)) THEN EXCEPTION DATA_ERROR 'Недопустимое значение, выберите из списка';
    END
    -- запрет удаления поля года обучения
    ELSE IF(I$PARAM_ID IN (3024, 3114) AND I$IS_DEL = 1) THEN
    BEGIN
        EXCEPTION DATA_ERROR 'Нельзя удалять год обучения';
    END
    -- запрет изменения типа бланка аттестата
    ELSE IF(I$PARAM_ID = 1847 AND I$IS_DEL = 0) THEN
    BEGIN
        EXECUTE PROCEDURE VERIFY_ATT_TYPE(:I$OBJ_ID, :I$VAL);
    END
    ELSE IF(I$PARAM_ID IN (54, 1652)) THEN
    BEGIN
        EXECUTE PROCEDURE VERIFY_CURRENT_CLASS(:I$OBJ_ID, IIF(:I$IS_DEL = 0, :I$VAL, NULL));
    END
    ELSE IF(I$PARAM_ID IN (3118, 3026)) THEN
    BEGIN
        EXECUTE PROCEDURE VERIFY_FUTURE_CLASS(:I$OBJ_ID, IIF(:I$IS_DEL = 0, :I$VAL, NULL));
    END
    ELSE IF(I$PARAM_ID IN (53, 1609)) THEN
    BEGIN
        SELECT FIRST 1 U.USER_ID
        FROM VALR V
        JOIN USERS U ON U.OBJ_ID = V.VAL
        WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = :I$PARAM_ID AND V.IS_DEL = 0
        INTO :V$OLD_USER;
    END
    ELSE IF(I$PARAM_ID IN (3321, 3322, 3323, 3324) AND USER_TYPE NOT IN (1, 5)) THEN BEGIN
        EXCEPTION DATA_ERROR 'Только администратор или руководитель может менять данные параметры';
    END
    ELSE IF(I$PARAM_ID IN (54, 3118, 3026)) THEN
    BEGIN
        EXECUTE PROCEDURE FUTURE_GUP_CHECK(:I$OBJ_ID);
    END

    IF(TYPE_ID = 17) THEN
    BEGIN
        EXECUTE PROCEDURE VAL_DOCUMENT_CHECK(:I$OBJ_ID, :I$PARAM_ID, :I$VAL, :I$IS_DEL);
    END

    V = NULL;
    IF (VAL_TYPE = 'INTEGER') THEN
    BEGIN /* 2147483647 */
        SELECT FIRST 1 V.VAL, V.IS_DEL
        FROM VALI V
        WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = :I$PARAM_ID
        INTO :V, :V$WAS_DEL;

        UPDATE OR INSERT INTO VALI (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
        VALUES (:I$PARAM_ID, :I$OBJ_ID, :I$USER_ID, :I$IS_DEL, :I$VAL);
    END
    ELSE
    IF (VAL_TYPE = 'FLOAT') THEN
    BEGIN /* 1234567890.123456 */
        SELECT FIRST 1 V.VAL, V.IS_DEL
        FROM VALF V
        WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = :I$PARAM_ID
        INTO :V, :V$WAS_DEL;

        UPDATE OR INSERT INTO VALF (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
        VALUES (:I$PARAM_ID, :I$OBJ_ID, :I$USER_ID, :I$IS_DEL, :I$VAL);
    END
    ELSE
    IF (VAL_TYPE = 'TIMESTAMP') THEN
    BEGIN /* 2008-12-29 23:23:59 */
        UPDATE OR INSERT INTO VALDT (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
        VALUES (:I$PARAM_ID, :I$OBJ_ID, :I$USER_ID, :I$IS_DEL, :I$VAL);
    END
    ELSE
    IF (VAL_TYPE = 'DATE') THEN
    BEGIN /* 2008-12-29 */
        SELECT FIRST 1 V.VAL, V.IS_DEL
        FROM VALD V
        WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = :I$PARAM_ID
        INTO :V, :V$WAS_DEL;

        UPDATE OR INSERT INTO VALD (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
        VALUES (:I$PARAM_ID, :I$OBJ_ID, :I$USER_ID, :I$IS_DEL, :I$VAL);
    END
    ELSE
    IF (VAL_TYPE = 'TIME') THEN
    BEGIN /* 23:23:59 */
        SELECT FIRST 1 V.VAL, V.IS_DEL
        FROM VALT V
        WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = :I$PARAM_ID
        INTO :V, :V$WAS_DEL;

        UPDATE OR INSERT INTO VALT (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
        VALUES (:I$PARAM_ID, :I$OBJ_ID, :I$USER_ID, :I$IS_DEL, :I$VAL);
    END
    ELSE
    IF (VAL_TYPE = 'LIST_VALUE') THEN
    BEGIN
        SELECT FIRST 1 V.LISTVAL_ID, V.IS_DEL
        FROM VALL V
        WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = :I$PARAM_ID
        INTO :V, :V$WAS_DEL;

        UPDATE OR INSERT INTO VALL (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, LISTVAL_ID)
        VALUES (:I$PARAM_ID, :I$OBJ_ID, :I$USER_ID, :I$IS_DEL, :I$VAL);
    END
    ELSE
    IF (VAL_TYPE IN ('SDO_IDENTIFY', 'STRING_OR_LIST_VALUE_RO', 'STRING_OR_LIST_VALUE', 'STRING', 'SQL_QUERY', 'FUNCTION', 'FUNCTION_CS', 'CALC_FUNCTION')) THEN
    BEGIN
        SELECT FIRST 1 V.VAL, V.IS_DEL
        FROM VALS V
        WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = :I$PARAM_ID
        INTO :V, :V$WAS_DEL;

        UPDATE OR INSERT INTO VALS (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
        VALUES (:I$PARAM_ID, :I$OBJ_ID, :I$USER_ID, :I$IS_DEL, :I$VAL);
    END
    ELSE
    IF (VAL_TYPE IN ('FILE', 'IMAGE')) THEN
    BEGIN
        SELECT FIRST 1 V.VAL, V.IS_DEL
        FROM VALB V
        WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = :I$PARAM_ID
        INTO :V, :V$WAS_DEL;

        BLOB_ID = NULL;
        UPDATE OR INSERT INTO VALB (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
        VALUES (:I$PARAM_ID, :I$OBJ_ID, :I$USER_ID, :I$IS_DEL, :I$VAL)
        RETURNING BLOB_ID
        INTO :BLOB_ID;
    END
    ELSE
    IF (VAL_TYPE = 'REFERENCE') THEN
    BEGIN
        SELECT FIRST 1 V.VAL, V.IS_DEL
        FROM VALR V
        WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = :I$PARAM_ID
        INTO :V, :V$WAS_DEL;

        IF (IS_LINK_REFERENSE = 1 AND I$IS_DEL = 0) THEN
        BEGIN
            OLD_REFERENSE_ID = NULL;

            SELECT I
            FROM VAL_GET(:I$OBJ_ID, :I$PARAM_ID, :I$IS_DEL)
            INTO :OLD_REFERENSE_ID;

            IF (OLD_REFERENSE_ID <> 0) THEN
            BEGIN
                UPDATE LINKS
                SET PARENT_ID = :I$VAL
                WHERE PARENT_ID = :OLD_REFERENSE_ID AND OBJ_ID = :I$OBJ_ID;
            END
            ELSE
            BEGIN
                UPDATE OR INSERT INTO LINKS (PARENT_ID, OBJ_ID, DATE_INS, DATE_DEL)
                VALUES (:I$VAL, :I$OBJ_ID, CURRENT_TIMESTAMP, NULL)
                MATCHING (PARENT_ID, OBJ_ID);
            END
        END

        UPDATE OR INSERT INTO VALR (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
        VALUES (:I$PARAM_ID, :I$OBJ_ID, :I$USER_ID, :I$IS_DEL, :I$VAL);
    END

    -- Регистрируем в логе
    IF(V$PT IN (6, 13)) THEN V$VAL_ID = I$VAL;

    IF(I$IS_DEL = 0) THEN
    BEGIN
      -- Фиксируем только реальные изменения, пропускаем первую запись значения
      IF(V$WAS_DEL = 1) THEN V = NULL;

      IF(V$WAS_DEL IS NOT NULL AND I$VAL <> COALESCE(V, '')) THEN
      INSERT INTO HISTVALS
      (TABLE_NAME, USER_ID, OBJ_ID, PARAM_ID, OPT_ID, PARENT_ID, OLD_VAL, VAL)
      VALUES ('VAL', :I$USER_ID, :I$OBJ_ID, :I$PARAM_ID, :V$PT, :V$VAL_ID, SUBSTRING(:V FROM 1 FOR 1000), SUBSTRING(:I$VAL FROM 1 FOR 1000));
    END
    ELSE
    BEGIN
      INSERT INTO HISTVALS
      (TABLE_NAME, USER_ID, OBJ_ID, PARAM_ID, OPT_ID, PARENT_ID, OLD_VAL)
      VALUES ('VAL_DEL', :I$USER_ID, :I$OBJ_ID, :I$PARAM_ID, :V$PT, :V$VAL_ID, SUBSTRING(:V FROM 1 FOR 1000));
    END

    SELECT COALESCE(VA.REFRESH_FLAG, :REFRESH_FLAG), COALESCE(VA.BLOB_ID, :BLOB_ID)
    FROM VAL_ADD_AFTER(:I$PARAM_ID, :I$OBJ_ID, :I$VAL, :I$USER_ID, :I$IS_DEL, :I$PROCESS_TAG, :TAG, :LANG_CODE, :TYPE_ID) VA
    INTO :REFRESH_FLAG, :BLOB_ID;

    IF(TAG = 'F.' OR TAG = 'I.' OR TAG = 'O.') THEN
    BEGIN
        REFRESH_FLAG = 'REFRESH_TAB_AND_CAPTION';
    END

    -- Если что-то менялось в назначении классных руководителей - делаем пересчет
    IF(V$OLD_USER IS NOT NULL) THEN EXECUTE PROCEDURE CJ2_JOURNAL_ACCESS_UPD(NULL, :V$OLD_USER);

    SUSPEND;

    WHEN SQLCODE -413 DO
    BEGIN
        EXCEPTION DATA_ERROR 'Введенное значение параметра не соответствует формату';
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE VAL_ADD_AFTER (
    I$PARAM_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$VAL VARCHAR(4000),
    I$USER_ID BIGINT,
    I$IS_DEL SMALLINT,
    I$PROCESS_TAG SMALLINT,
    TAG VARCHAR(100),
    LANG_CODE VARCHAR(2),
    TYPE_ID BIGINT)
RETURNS (
    BLOB_ID BIGINT,
    REFRESH_FLAG VARCHAR(100))
AS
DECLARE VARIABLE I BIGINT;
DECLARE VARIABLE I1 BIGINT;
DECLARE VARIABLE I2 BIGINT;
DECLARE VARIABLE I3 BIGINT;
DECLARE VARIABLE I4 BIGINT;
DECLARE VARIABLE J BIGINT;
DECLARE VARIABLE V$OU_LICENCE_TYPE CHAR(1);
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$PARENT_ID BIGINT;
DECLARE VARIABLE V$VAL_LONG VARCHAR(1000);
DECLARE VARIABLE V$PARAM_ID BIGINT;
DECLARE VARIABLE V$BLOB_ID BIGINT;
DECLARE VARIABLE D1 DATE;
DECLARE VARIABLE D2 DATE;
DECLARE VARIABLE F NUMERIC(14,3);
DECLARE VARIABLE V VARCHAR(4000);
DECLARE VARIABLE V_LONG VARCHAR(4000);
DECLARE VARIABLE V$GEN BIGINT;
begin

    SELECT STATUS FROM OU_LICENCE_TYPE INTO :V$OU_LICENCE_TYPE;
    SELECT GEN FROM GEN INTO :V$GEN;

    /*PUPIL*/
    IF (TAG = 'PUPIL_DISTRICT') THEN
    BEGIN
        I1 = NULL;
        SELECT FIRST 1 LV.COST
        FROM OBJECT_PARENTS_GET(:I$OBJ_ID, 2) O
        JOIN VALS V7 ON V7.OBJ_ID = O.OBJ_ID AND V7.PARAM_ID = 7 AND V7.IS_DEL = 0
        JOIN LISTVALS LV ON LV.LIST_ID = 168 AND LV.IS_DEL = 0
        LEFT JOIN RES_GET(LV.RES_ID, :LANG_CODE) R ON 1 = 1
        WHERE R.VAL LIKE V7.VAL

        INTO :I1;

        IF ((I$IS_DEL = 1)/* OR (I1 IS NULL)*/) THEN
        BEGIN
            UPDATE VALL
            SET IS_DEL = 1
            WHERE OBJ_ID = :I$OBJ_ID AND PARAM_ID = 100 AND IS_DEL = 0;
        END
        ELSE
        BEGIN
            UPDATE OR INSERT INTO VALL (OBJ_ID,PARAM_ID,IS_DEL,LISTVAL_ID)
            VALUES (:I$OBJ_ID,100,0,IIF((:I1 IS NULL) OR (:I1 = 0) OR (:I1 = :I$VAL),200,201));
        END
        REFRESH_FLAG = 'REFRESH_TAB';
    END
    ELSE IF (TAG = 'GROUP_SPECIALITY') THEN
    BEGIN
        IF (V$OU_LICENCE_TYPE = 'C') THEN
        BEGIN
            -- Обновляем поле кода профессии / специальности
            IF(I$PARAM_ID IN (2165, 2821, 3367)) THEN J = 2822; -- #9
            ELSE IF(I$PARAM_ID IN (3381, 3382, 3383)) THEN J = 3384; -- #403
            ELSE IF(I$PARAM_ID IN (3473, 3474, 3475)) THEN J = 3476; -- #400
            EXECUTE PROCEDURE UPDATE_SPECIALITY_CODE(:I$OBJ_ID, :I$PARAM_ID, :J, :I$VAL, :I$USER_ID, :I$IS_DEL);

            -- Несмотря на то, что параметр 2164 должен быть из списка 244
            -- все равно пишем туда значение по любому из 3 справочников
            -- когда вызывается для УП, тут ничего не произойдет
            FOR
                SELECT L10.OBJ_ID
                FROM LINKS L10
                WHERE L10.PARENT_ID = :I$OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
                INTO :V$OBJ_ID
            DO
            BEGIN
                SELECT BLOB_ID
                FROM VAL_ADD(2164, :V$OBJ_ID, :I$VAL, :I$USER_ID, :I$IS_DEL)
                INTO :V$PARENT_ID;
            END
            REFRESH_FLAG = 'REFRESH_TAB';
        END
    END
    ELSE IF (TAG = 'OOOD_SHORT') THEN
    BEGIN
        V$VAL_LONG = NULL;
        SELECT R.VAL_LONG
        FROM LISTVALS LV
        LEFT JOIN RES_GET(LV.RES_ID,:LANG_CODE) R ON 1=1
        WHERE LV.LIST_ID = 281 AND LV.IS_DEL = 0 AND R.VAL LIKE :I$VAL
        INTO :V$VAL_LONG;

        IF (V$VAL_LONG IS NOT NULL) THEN
        BEGIN
            SELECT PARAM_ID
            FROM PARAMS P
            WHERE P.TYPE_ID = :TYPE_ID AND P.IS_DEL = 0 AND P.TAG LIKE 'OOOD_FULL'
            INTO :V$PARAM_ID;

            SELECT BLOB_ID
            FROM VAL_ADD(:V$PARAM_ID, :I$OBJ_ID, :V$VAL_LONG, :I$USER_ID)
            INTO :V$BLOB_ID;

            REFRESH_FLAG = 'REFRESH_TAB_AND_CAPTION';
        END
    END
    /*EDUCATION PROGRAM*/
    ELSE IF (TAG = 'EDU_PROG_TYPE') THEN
    BEGIN
        SELECT TYPE_ID
        FROM PARAMS
        WHERE PARAM_ID = :I$PARAM_ID
        INTO :J;

        SELECT PARAM_ID
        FROM PARAMS
        WHERE TYPE_ID = :J AND TAG LIKE 'EDU_PROG_VID' AND IS_DEL = 0
        INTO :I3;

        SELECT PARAM_ID
        FROM PARAMS
        WHERE TYPE_ID = :J AND TAG LIKE 'EDU_PROG_LEVEL' AND IS_DEL = 0
        INTO :I4;

        I = NULL;
        SELECT LV1.PARENT_ID, LV2.PARENT_ID
        FROM LISTVALS LV1
        LEFT JOIN LISTVALS LV2 ON LV2.LISTVAL_ID =  LV1.PARENT_ID
        WHERE LV1.LISTVAL_ID = :I$VAL
        INTO :I, :I1;
        IF ((I IS NOT NULL) AND (I1 IS NOT NULL)) THEN
        BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD(:I4, :I$OBJ_ID, :I, :I$USER_ID, :I$IS_DEL, :I$PROCESS_TAG)
            INTO :I;

            SELECT BLOB_ID
            FROM VAL_ADD(:I3, :I$OBJ_ID, :I1, :I$USER_ID, :I$IS_DEL, :I$PROCESS_TAG)
            INTO :I;

            REFRESH_FLAG = 'REFRESH_TAB_AND_CAPTION';
        END
        ELSE IF (I IS NOT NULL) THEN
        BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD(:I3, :I$OBJ_ID, :I, :I$USER_ID, :I$IS_DEL, :I$PROCESS_TAG)
            INTO :I;    

            REFRESH_FLAG = 'REFRESH_TAB_AND_CAPTION';
        END
    END
    /* OU */
    ELSE IF (TAG = 'OUTLESSON') THEN
    BEGIN
        IF (I$VAL = 2) THEN
        BEGIN
            FOR
                SELECT L49.OBJ_ID
                FROM LINKS L49
                JOIN VALL V372 ON V372.OBJ_ID = L49.OBJ_ID AND V372.PARAM_ID = 372 AND V372.IS_DEL = 0 AND V372.LISTVAL_ID = 780
                WHERE L49.PARENT_ID = :I$OBJ_ID AND L49.OBJ_TYPE_ID = 49 AND L49.DATE_DEL IS NULL
                INTO :V$OBJ_ID
            DO
            BEGIN
                UPDATE VALL
                SET IS_DEL = 1
                WHERE OBJ_ID = :V$OBJ_ID
                AND PARAM_ID = 372
                AND IS_DEL = 0;
    
                REFRESH_FLAG = 'REFRESH_BRANCH';
            END
        END
    END
    ELSE IF (TAG = 'OU_OWNER_ORGANIZATION') THEN
    BEGIN
        EXECUTE PROCEDURE FIXER_SCHOOL_DISTRICT(:I$OBJ_ID, :I$USER_ID);
    END
    ELSE IF (TAG = 'OU_VID') THEN
    BEGIN
        I = NULL;
        SELECT PARENT_ID
        FROM LISTVALS
        WHERE LISTVAL_ID = :I$VAL
        INTO :I;
        IF (I IS NOT NULL) THEN
        BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD(11, :I$OBJ_ID, :I, :I$USER_ID, :I$IS_DEL, :I$PROCESS_TAG)
            INTO :I;
            UPDATE VALS
            SET IS_DEL = 1
            WHERE PARAM_ID = 937 AND OBJ_ID = :I$OBJ_ID;
            REFRESH_FLAG = 'REFRESH_TAB';
        END
    END
    ELSE IF (TAG = 'REFRESH_TAB') THEN
    BEGIN
        REFRESH_FLAG = 'REFRESH_TAB';
    END
    ELSE IF (TAG = 'OU_OPF') THEN
    BEGIN
        I = NULL;
        SELECT COST
        FROM LISTVALS
        WHERE LISTVAL_ID = :I$VAL
        INTO :I;
        IF (I IS NOT NULL) THEN
        BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD(22, :I$OBJ_ID, :I, :I$USER_ID, :I$IS_DEL, :I$PROCESS_TAG)
            INTO :I;
        END
    END
    ELSE IF (TAG = 'ROOM_PURPOSE') THEN
    BEGIN
        I = NULL;
        SELECT PARENT_ID
        FROM LISTVALS
        WHERE LISTVAL_ID = :I$VAL
        INTO :I;
        IF (I IS NOT NULL) THEN J = NULL;
        SELECT PARENT_ID
        FROM LISTVALS
        WHERE LISTVAL_ID = :I
        INTO :J;
        IF (J IS NOT NULL) THEN
        BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD(525, :I$OBJ_ID, :J, :I$USER_ID, :I$IS_DEL, :I$PROCESS_TAG)
            INTO :J;
            REFRESH_FLAG = 'REFRESH_TAB';
        END
        ELSE
        BEGIN
            IF (I IS NOT NULL) THEN
            BEGIN
                SELECT BLOB_ID
                FROM VAL_ADD(525, :I$OBJ_ID, :I, :I$USER_ID, :I$IS_DEL, :I$PROCESS_TAG)
                INTO :I;
                REFRESH_FLAG = 'REFRESH_TAB';
            END
        END
    END
    ELSE IF (TAG = 'EMPLOYEE_POST') THEN
    BEGIN
        FOR
            SELECT PARENT_ID
            FROM LINKS
            WHERE OBJ_ID = :I$OBJ_ID AND PARENT_TYPE_ID = 14 AND DATE_DEL IS NULL
            INTO :V$OBJ_ID
        DO
        BEGIN
            FOR
                SELECT LP.PARENT_ID
                FROM LINKS L15
                LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
                JOIN VALR V69 ON V69.OBJ_ID = L15.OBJ_ID AND V69.PARAM_ID = 69 AND V69.IS_DEL = 0
                JOIN LINKS LP ON LP.OBJ_ID = V69.VAL AND LP.PARENT_TYPE_ID IN (211,2) AND LP.DATE_DEL IS NULL
                WHERE L15.PARENT_ID = :V$OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL AND ((V74.VAL IS NULL) OR (V74.VAL > CURRENT_DATE))
                AND NOT EXISTS (
                    SELECT FIRST 1 1
                    FROM LINKS L
                    WHERE L.PARENT_ID = LP.PARENT_ID AND L.OBJ_ID = :V$OBJ_ID AND L.DATE_DEL IS NULL
                )
                INTO :V$PARENT_ID
            DO
            BEGIN
                SELECT LINK_ID
                FROM OBJECT_ADD_LINK(:V$PARENT_ID, :V$OBJ_ID, 14, NULL, NULL, :I$USER_ID)
                INTO :I;
                REFRESH_FLAG = 'REFRESH_TREE';
            END
            FOR
                SELECT LP.PARENT_ID
                FROM LINKS LP
                WHERE LP.OBJ_ID = :V$OBJ_ID AND LP.PARENT_TYPE_ID IN (2, 211) AND LP.DATE_DEL IS NULL
                AND NOT EXISTS (
                    SELECT FIRST 1 1
                    FROM LINKS L15
                    LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
                    JOIN VALR V69 ON V69.OBJ_ID = L15.OBJ_ID AND V69.PARAM_ID = 69 AND V69.IS_DEL = 0
                    JOIN LINKS LP2 ON LP2.OBJ_ID = V69.VAL AND LP2.PARENT_TYPE_ID IN (211, 2) AND LP2.DATE_DEL IS NULL AND LP2.PARENT_ID = LP.PARENT_ID
                    WHERE L15.PARENT_ID = :V$OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL AND ((V74.VAL IS NULL) OR (V74.VAL > CURRENT_DATE))
                )

                INTO :V$PARENT_ID
            DO
            BEGIN
                UPDATE LINKS
                SET DATE_DEL = CURRENT_TIMESTAMP
                WHERE OBJ_ID = :V$OBJ_ID AND PARENT_ID = :V$PARENT_ID AND DATE_DEL IS NULL;
                REFRESH_FLAG = 'REFRESH_TREE';
            END
        END
    END
    ELSE IF (TAG = 'OU_POST') THEN
    BEGIN
        -- Код должности по кодификатору
        V = NULL;
        V_LONG = NULL;
        SELECT V, V_LONG
        FROM VAL_GET(:I$OBJ_ID, 58)
        INTO :V, :V_LONG;

        SELECT FIRST 1 L2.PARENT_ID
        FROM LINKS L2
        WHERE L2.PARENT_TYPE_ID IN (2, 211) AND L2.OBJ_ID = :I$OBJ_ID AND L2.DATE_DEL IS NULL
        INTO :I;

        -- Должность Учитель может быть единственной
        IF(I$VAL = 18501) THEN
        BEGIN
          IF(EXISTS(
            SELECT FIRST 1 1
            FROM LINKS L
            JOIN VALL V58 ON V58.OBJ_ID = L.OBJ_ID AND V58.PARAM_ID = 58 AND V58.LISTVAL_ID = 18501
            WHERE L.PARENT_ID = :I AND L.OBJ_TYPE_ID = 13 AND L.DATE_DEL IS NULL AND L.OBJ_ID <> :I$OBJ_ID
          ))
          THEN
            EXCEPTION DATA_ERROR 'Должность "Учитель" может быть только одна в пределах уровня';
        END

        -- Если вдруг получилось наслоение названий должности, приписываем к названию цифру
        -- но в Мультипараграфе это не делаем, чтобы не получить конфликт со штатным расписанием
        IF(V$OU_LICENCE_TYPE <> 'S' AND I$IS_DEL = 0) THEN
        BEGIN
          IF(EXISTS(
            SELECT FIRST 1 1
            FROM LINKS L13
            JOIN VALS V ON V.OBJ_ID = L13.OBJ_ID AND V.PARAM_ID = 66 AND V.IS_DEL = 0 AND V.VAL = :V
            WHERE L13.PARENT_ID = :I AND L13.OBJ_TYPE_ID = 13 AND L13.DATE_DEL IS NULL AND L13.OBJ_ID <> :I$OBJ_ID
          ))
          THEN
          BEGIN
            I1 = 1;
            WHILE(EXISTS(
              SELECT FIRST 1 1
              FROM LINKS L13
              JOIN VALS V ON V.OBJ_ID = L13.OBJ_ID AND V.PARAM_ID = 66 AND V.IS_DEL = 0 AND V.VAL = :V || :I1
              WHERE L13.PARENT_ID = :I AND L13.OBJ_TYPE_ID = 13 AND L13.DATE_DEL IS NULL AND L13.OBJ_ID <> :I$OBJ_ID
            ))
            DO
            BEGIN
              I1 = I1 + 1;
            END
            V = V || I1;
          END
          SELECT BLOB_ID
          FROM VAL_ADD(66, :I$OBJ_ID, :V, :I$USER_ID, :I$IS_DEL, :I$PROCESS_TAG)
          INTO :BLOB_ID;
          SELECT BLOB_ID
          FROM VAL_ADD(589, :I$OBJ_ID, :V_LONG, :I$USER_ID, :I$IS_DEL, :I$PROCESS_TAG)
          INTO :BLOB_ID;
        END

        -- подгруппа должностей
        I = NULL;
        IF (EXISTS(SELECT FIRST 1 1 FROM LISTVALS WHERE LIST_ID = 21 AND LISTVAL_ID = :I$VAL)) THEN
        BEGIN
          -- Старый вариант - прямой родитель элемента
          SELECT PARENT_ID
          FROM LISTVALS
          WHERE LISTVAL_ID = :I$VAL
          INTO :I;
        END
        ELSE
        BEGIN
          -- Смотрим по коду в поле FILTER, хардкодим конкретные значения
          V = NULL;
          V_LONG = NULL;
          SELECT FIRST 1 "FILTER", TAG FROM LISTVALS WHERE LISTVAL_ID = :I$VAL INTO :V, :V_LONG;
          IF(V = 'R1' OR V_LONG = 'R1') THEN I = 56; -- рук 1 ур
          ELSE IF(V = 'R2' OR V_LONG = 'R2') THEN I = 113; -- рук 2 ур
          ELSE IF(V = 'R3' OR V_LONG = 'R3') THEN I = 70; -- рук 3 ур
          ELSE IF(V = 'U' OR V_LONG = 'U') THEN I = 98; -- предподаватели
          ELSE I = 1257; -- все остальное - персонал
        END
        -- группа должностей
        J = NULL;
        SELECT PARENT_ID
        FROM LISTVALS
        WHERE LISTVAL_ID = :I
        INTO :J;

        IF (I IS NOT NULL) THEN
        BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD(64, :I$OBJ_ID, :I, :I$USER_ID, :I$IS_DEL, :I$PROCESS_TAG)
            INTO :BLOB_ID;
            IF (J IS NULL) THEN J = I;
            SELECT BLOB_ID
            FROM VAL_ADD(63, :I$OBJ_ID, :J, :I$USER_ID, :I$IS_DEL, :I$PROCESS_TAG)
            INTO :BLOB_ID;
        END

        -- Педагогическая должность
        V = NULL;
        SELECT VAL FROM DO_FUNC(:I$OBJ_ID, 400) INTO :V;
        UPDATE OR INSERT INTO VALL (OBJ_ID,PARAM_ID,IS_DEL,LISTVAL_ID)
        VALUES (:I$OBJ_ID, 400, 0, IIF(:V = 'Да', 2, 3));

        REFRESH_FLAG = 'REFRESH_TAB_AND_CAPTION';
    END
    ELSE IF ((TAG = 'VACATION_BEGIN') OR (TAG = 'VACATION_END')) THEN
    BEGIN
        SELECT D
        FROM VAL_GET(:I$OBJ_ID, 327)
        INTO :D1;
        SELECT D
        FROM VAL_GET(:I$OBJ_ID, 328)
        INTO :D2;
        IF ((D1 != '2000-01-01') AND (D2 != '2000-01-01')) THEN
        BEGIN
            IF (D2 < D1) THEN
                EXCEPTION DATA_ERROR('Дата окончания не может быть раньше даты начала');
            I = D2 - D1 + 1;
            SELECT BLOB_ID
            FROM VAL_ADD(329, :I$OBJ_ID, :I)
            INTO :BLOB_ID;
            REFRESH_FLAG = 'REFRESH_TAB';
        END
    END
    ELSE IF (TAG = 'MTR_TCO_GR') THEN
    BEGIN
        I = NULL;
        SELECT R.VAL, L.PARENT_ID
        FROM LISTVALS L

        LEFT JOIN RES_GET(L.RES_ID,  :LANG_CODE) R ON 1=1

        WHERE L.LISTVAL_ID = :I$VAL
        INTO :V, :I;
        IF (I IS NOT NULL) THEN
        BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD(626, :I$OBJ_ID, :I, :I$USER_ID, :I$IS_DEL, :I$PROCESS_TAG)
            INTO :BLOB_ID;
            SELECT BLOB_ID
            FROM VAL_ADD(627, :I$OBJ_ID, :V, :I$USER_ID, :I$IS_DEL, :I$PROCESS_TAG)
            INTO :BLOB_ID;
            REFRESH_FLAG = 'REFRESH_TAB_AND_CAPTION';
        END

    END
    ELSE IF (TAG = 'MTR_TCO_KK') THEN
    BEGIN
        V = NULL;
        SELECT VAL
        FROM VALS
        WHERE PARAM_ID = 877
          AND OBJ_ID = :I$OBJ_ID
          AND IS_DEL = 0
        INTO :V;
        IF (V IS NULL) THEN
        BEGIN
            SELECT R.VAL
            FROM LISTVALS L
            LEFT JOIN RES_GET(L.RES_ID,  :LANG_CODE) R ON 1=1
            WHERE L.LISTVAL_ID = :I$VAL
            INTO :V;
            SELECT BLOB_ID
            FROM VAL_ADD(877, :I$OBJ_ID, :V, :I$USER_ID, :I$IS_DEL, :I$PROCESS_TAG)
            INTO :BLOB_ID;
            REFRESH_FLAG = 'REFRESH_TAB_AND_CAPTION';
        END

    END
    ELSE IF (TAG = 'IR_ELECTRO_GR') THEN
    BEGIN
        I = NULL;
        SELECT PARENT_ID
        FROM LISTVALS
        WHERE LISTVAL_ID = :I$VAL
        INTO :I;
        IF (I IS NOT NULL) THEN
        BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD(637, :I$OBJ_ID, :I, :I$USER_ID, :I$IS_DEL, :I$PROCESS_TAG)
            INTO :BLOB_ID;
            REFRESH_FLAG = 'REFRESH_TAB_AND_CAPTION';
        END

    END
    ELSE IF (TAG = 'LIC_SCHOOLAR_COUNT') THEN
    BEGIN
        I1 = 0;
        I2 = 0;
        I3 = 0;
        I4 = 0;
        SELECT I.VAL
        FROM VALI I
        WHERE I.PARAM_ID = 1186 AND I.OBJ_ID = :I$OBJ_ID AND I.IS_DEL = 0
        INTO :I1;
        SELECT I.VAL
        FROM VALI I
        WHERE I.PARAM_ID = 1187 AND I.OBJ_ID = :I$OBJ_ID AND I.IS_DEL = 0
        INTO :I2;
        SELECT I.VAL
        FROM VALI I
        WHERE I.PARAM_ID = 1188 AND I.OBJ_ID = :I$OBJ_ID AND I.IS_DEL = 0
        INTO :I3;
        SELECT I.VAL
        FROM VALI I
        WHERE I.PARAM_ID = 1189 AND I.OBJ_ID = :I$OBJ_ID AND I.IS_DEL = 0
        INTO :I4;
        I = I1 + I2 + I3 + I4;
        UPDATE OR INSERT INTO VALI (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
        VALUES (1190, :I$OBJ_ID, :I$USER_ID, 0, :I);
        F = I1 + 0.25 * I2 + 0.1 * I3 + 0.025 * I4;
        UPDATE OR INSERT INTO VALF (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
        VALUES (1191, :I$OBJ_ID, :I$USER_ID, 0, :F);

        REFRESH_FLAG = 'REFRESH_TAB';
    END
    ELSE IF (TAG = 'DIVISION_SUBJECT') THEN
    BEGIN
        FOR
            SELECT L58.OBJ_ID
            FROM LINKS L48
            JOIN LINKS L58 ON L58.PARENT_ID = L48.OBJ_ID AND L58.OBJ_TYPE_ID = 58 AND L58.DATE_DEL IS NULL
            WHERE L48.PARENT_ID = :I$OBJ_ID AND L48.OBJ_TYPE_ID = 48 AND L48.DATE_DEL IS NULL
            INTO :V$OBJ_ID
        DO
        BEGIN
            UPDATE LINKS L
            SET L.DATE_DEL = CURRENT_TIMESTAMP
            WHERE L.OBJ_ID = :V$OBJ_ID AND L.DATE_DEL IS NULL;
        END
    END
    ELSE IF (TAG = 'PUPIL_MOVEMENT_TYPE') THEN
    BEGIN
        I = NULL;
        IF (I$IS_DEL = 0) THEN I = I$VAL;
        UPDATE LINKS L
        SET L.REASON_ID = :I
        WHERE L.PARENT_TYPE_ID = 10 AND L.OBJ_ID = :I$OBJ_ID AND L.DATE_DEL IS NULL;
    END
    ELSE IF (TAG = 'GIA_TYPE_CLASS') THEN
    BEGIN
        SELECT TYPE_ID
        FROM OBJECTS
        WHERE OBJ_ID = :I$OBJ_ID
        INTO :TYPE_ID;

        EXECUTE PROCEDURE GIA_CHECK_CLASS_CHANGE(:I$OBJ_ID);

        IF (I$IS_DEL = 0) THEN
        BEGIN
            IF (I$VAL <> 11217) THEN
            BEGIN
                SELECT SINONIM
                FROM GIA_CLASS_SINONIM_GET(:I$OBJ_ID)
                INTO :V;

                UPDATE OR INSERT INTO VALS (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
                VALUES (CASE WHEN :TYPE_ID = 9 THEN 1363 WHEN :TYPE_ID = 187 THEN 1653 WHEN :TYPE_ID = 125 THEN 821 END, :I$OBJ_ID, :I$USER_ID, 0, :V);
                REFRESH_FLAG = 'REFRESH_TAB';

                -- В колледжах категорию участника не меняем !
                IF(V$OU_LICENCE_TYPE <> 'C') THEN
                FOR
                    SELECT L.OBJ_ID
                    FROM LINKS L
                    LEFT JOIN VALL V ON V.PARAM_ID = 1340 AND V.OBJ_ID = L.OBJ_ID AND V.IS_DEL = 0
                    WHERE L.PARENT_ID = :I$OBJ_ID AND L.OBJ_TYPE_ID = 10 AND L.DATE_DEL IS NULL AND (V.OBJ_ID IS NULL OR V.LISTVAL_ID = 2992 OR V.LISTVAL_ID = 10874)
                    INTO :I
                DO
                BEGIN
                    UPDATE OR INSERT INTO VALL (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, LISTVAL_ID)
                    VALUES (1340, :I, :I$USER_ID, 0, 2993);
                END
            END
        END
    END
    ELSE IF (TAG = 'CLASS_NAME') THEN
    BEGIN
        SELECT TYPE_ID
        FROM OBJECTS
        WHERE OBJ_ID = :I$OBJ_ID
        INTO :TYPE_ID;

        IF (I$IS_DEL = 0) THEN
        BEGIN
            IF (TYPE_ID = 9) THEN
            BEGIN
                SELECT COUNT(*)
                FROM VALS V
                WHERE V.PARAM_ID = 1363 AND V.OBJ_ID = :I$OBJ_ID AND V.IS_DEL = 0
                INTO :J;
    
                IF (J = 0) THEN
                BEGIN
                    SELECT SINONIM
                    FROM GIA_CLASS_SINONIM_GET(:I$OBJ_ID)
                    INTO :V;
    
                    IF (V IS NOT NULL) THEN
                    BEGIN
                        UPDATE OR INSERT INTO VALS (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
                        VALUES (1363, :I$OBJ_ID, :I$USER_ID, 0, :V);
                    END
                END
            END
            ELSE IF (TYPE_ID = 187) THEN
            BEGIN
                SELECT COUNT(*)
                FROM VALS V
                WHERE V.PARAM_ID = 1653 AND V.OBJ_ID = :I$OBJ_ID AND V.IS_DEL = 0
                INTO :J;
    
                IF (J = 0) THEN
                BEGIN
                    SELECT SINONIM
                    FROM GIA_CLASS_SINONIM_GET(:I$OBJ_ID)
                    INTO :V;
    
                    IF (V IS NOT NULL) THEN
                    BEGIN
                        UPDATE OR INSERT INTO VALS (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
                        VALUES (1653, :I$OBJ_ID, :I$USER_ID, 0, :V);
                    END
                END
            END
        END
        EXECUTE PROCEDURE UPDATE_MOVEMENTS_CNAME(:I$OBJ_ID);
        REFRESH_FLAG = 'REFRESH_TAB';
    END
    ELSE IF (TAG = 'GIA_VIRTUAL_CLASS_NAME') THEN
    BEGIN
        IF (I$IS_DEL = 0) THEN
        BEGIN
            SELECT COUNT(*)
            FROM VALS V
            WHERE V.PARAM_ID = 821 AND V.OBJ_ID = :I$OBJ_ID AND V.IS_DEL = 0
            INTO :J;

            IF (J = 0) THEN
            BEGIN
                SELECT SINONIM
                FROM GIA_CLASS_SINONIM_GET(:I$OBJ_ID)
                INTO :V;

                UPDATE OR INSERT INTO VALS (PARAM_ID, OBJ_ID, USER_ID, IS_DEL, VAL)
                VALUES (821, :I$OBJ_ID, :I$USER_ID, 0, :V);
            END
        END
        REFRESH_FLAG = 'REFRESH_TAB';
    END
    ELSE IF (TAG = 'GIA_VIRTUAL_OU_DISTR') THEN
    BEGIN
        REFRESH_FLAG = 'REFRESH_TAB';
    END
    ELSE IF (TAG = 'PUPIL_MOVEMENT_DATE') THEN
    BEGIN
        IF (I$IS_DEL = 0) THEN
        BEGIN
            SELECT X
            FROM PARAGRAF_EDUCATION_LEAVE_CHECK(:I$OBJ_ID, CAST(:I$VAL AS DATE), :I$USER_ID)
            INTO :I;

            IF (I > 1) THEN REFRESH_FLAG = 'REFRESH_TREE_GO_OBJECT';
        END
    END
    ELSE IF (TAG = 'BUILDING_OWNERSHIP') THEN
    BEGIN
        FOR
            SELECT L.OBJ_ID
            FROM LINKS L
            WHERE L.PARENT_ID = :I$OBJ_ID AND L.OBJ_TYPE_ID = 61 AND L.DATE_DEL IS NULL
            INTO :V$OBJ_ID
        DO BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD(527, :V$OBJ_ID, :I$VAL)
            INTO :BLOB_ID;
        END
    END
    ELSE IF (TAG = 'BUILDING_OWNERSHIP_DOC') THEN
    BEGIN
        FOR
            SELECT L.OBJ_ID
            FROM LINKS L
            WHERE L.PARENT_ID = :I$OBJ_ID AND L.OBJ_TYPE_ID = 61 AND L.DATE_DEL IS NULL
            INTO :V$OBJ_ID
        DO BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD(528, :V$OBJ_ID, :I$VAL)
            INTO :BLOB_ID;
        END
    END
    ELSE IF (TAG = 'GIA_PROGRAM_LANG2') THEN
    BEGIN
        I = NULL;
        SELECT PARENT_ID
        FROM LISTVALS
        WHERE LISTVAL_ID = :I$VAL
        INTO :I;
        IF (I IS NOT NULL) THEN
        BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD(1626, :I$OBJ_ID, :I, :I$USER_ID, :I$IS_DEL, :I$PROCESS_TAG)
            INTO :J;
            REFRESH_FLAG = 'REFRESH_TAB';
        END
    END
    ELSE IF (TAG = 'GIA_PRO_LANG_CLASS2') THEN
    BEGIN
        I = NULL;
        SELECT PARENT_ID
        FROM LISTVALS
        WHERE LISTVAL_ID = :I$VAL
        INTO :I;
        IF (I IS NOT NULL) THEN
        BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD(1633, :I$OBJ_ID, :I, :I$USER_ID, :I$IS_DEL, :I$PROCESS_TAG)
            INTO :J;
            REFRESH_FLAG = 'REFRESH_TAB';
        END

        FOR
            SELECT L126.OBJ_ID
            FROM LINKS L126
            WHERE L126.PARENT_ID = :I$OBJ_ID AND L126.OBJ_TYPE_ID = 126 AND L126.DATE_DEL IS NULL
            INTO :V$OBJ_ID
        DO
        BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD(1628, :V$OBJ_ID, :I$VAL, :I$USER_ID, :I$IS_DEL, :I$PROCESS_TAG)
            INTO :J;
        END
    END
    ELSE IF (TAG = 'GIA_WORD_CLASS2') THEN
    BEGIN
        FOR
            SELECT L126.OBJ_ID
            FROM LINKS L126
            WHERE L126.PARENT_ID = :I$OBJ_ID AND L126.OBJ_TYPE_ID = 126 AND L126.DATE_DEL IS NULL
            INTO :V$OBJ_ID
        DO
        BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD(1629, :V$OBJ_ID, :I$VAL, :I$USER_ID, :I$IS_DEL, :I$PROCESS_TAG)
            INTO :J;
        END
    END
    ELSE IF (TAG = 'GIA_EXCEL_CLASS2') THEN
    BEGIN
        FOR
            SELECT L126.OBJ_ID
            FROM LINKS L126
            WHERE L126.PARENT_ID = :I$OBJ_ID AND L126.OBJ_TYPE_ID = 126 AND L126.DATE_DEL IS NULL
            INTO :V$OBJ_ID
        DO
        BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD(1630, :V$OBJ_ID, :I$VAL, :I$USER_ID, :I$IS_DEL, :I$PROCESS_TAG)
            INTO :J;
        END
    END
    ELSE IF (TAG = 'GIA_PROGRAM_LANG') THEN
    BEGIN
        I = NULL;
        SELECT PARENT_ID
        FROM LISTVALS
        WHERE LISTVAL_ID = :I$VAL
        INTO :I;
        IF (I IS NOT NULL) THEN
        BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD(1620, :I$OBJ_ID, :I, :I$USER_ID, :I$IS_DEL, :I$PROCESS_TAG)
            INTO :J;
            REFRESH_FLAG = 'REFRESH_TAB';
        END
    END
    ELSE IF (TAG IN ('GIA_PRO_LANG_CLASS', 'GIA_PRO_LANG_CLASS3')) THEN
    BEGIN
        I = NULL;
        SELECT PARENT_ID
        FROM LISTVALS
        WHERE LISTVAL_ID = :I$VAL
        INTO :I;
        IF (I IS NOT NULL) THEN
        BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD(IIF(:TAG = 'GIA_PRO_LANG_CLASS', 1613, 1743), :I$OBJ_ID, :I, :I$USER_ID, :I$IS_DEL, :I$PROCESS_TAG)
            INTO :J;
            REFRESH_FLAG = 'REFRESH_TAB';
        END

        FOR
            SELECT L10.OBJ_ID
            FROM LINKS L10
            WHERE L10.PARENT_ID = :I$OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
            INTO :V$OBJ_ID
        DO
        BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD(1622, :V$OBJ_ID, :I$VAL, :I$USER_ID, :I$IS_DEL, :I$PROCESS_TAG)
            INTO :J;
        END
    END
    ELSE IF (TAG IN ('GIA_WORD_CLASS', 'GIA_WORD_CLASS3')) THEN
    BEGIN
        FOR
            SELECT L10.OBJ_ID
            FROM LINKS L10
            WHERE L10.PARENT_ID = :I$OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
            INTO :V$OBJ_ID
        DO
        BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD(1624, :V$OBJ_ID, :I$VAL, :I$USER_ID, :I$IS_DEL, :I$PROCESS_TAG)
            INTO :J;
        END
    END
    ELSE IF (TAG IN ('GIA_EXCEL_CLASS', 'GIA_EXCEL_CLASS3')) THEN
    BEGIN
        FOR
            SELECT L10.OBJ_ID
            FROM LINKS L10
            WHERE L10.PARENT_ID = :I$OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
            INTO :V$OBJ_ID
        DO
        BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD(1625, :V$OBJ_ID, :I$VAL, :I$USER_ID, :I$IS_DEL, :I$PROCESS_TAG)
            INTO :J;
        END
    END
    ELSE IF (TAG = 'DOU_GROUP_TYPE') THEN
    BEGIN
        UPDATE VALL
        SET IS_DEL = 1
        WHERE OBJ_ID = :I$OBJ_ID AND PARAM_ID = 1655 AND IS_DEL = 0;
        REFRESH_FLAG = 'REFRESH_TAB';
    END
    ELSE IF ((TAG = 'FGOS_SPECIALITY') AND (I$PROCESS_TAG = 1)) THEN
    BEGIN
        EXECUTE PROCEDURE FGOS_SPECIALITY_SET(:I$OBJ_ID, :I$PARAM_ID, :I$VAL, :I$USER_ID, :I$IS_DEL);
        REFRESH_FLAG = 'REFRESH_TAB';
    END
    ELSE IF ((TAG = 'FGOS_SPECIALITY_CODE') AND (I$PROCESS_TAG = 1)) THEN
    BEGIN
        -- С 02.09 .18 поле readonly
        IF (I$IS_DEL = 1) THEN
        BEGIN
            -- При удалении кода специальности также удаляем саму профессию/специальность
            UPDATE VALL
            SET IS_DEL = 1
            WHERE OBJ_ID = :I$OBJ_ID AND PARAM_ID IN (1753, 2460, 3378) AND IS_DEL = 0;
        END
        ELSE
        BEGIN
            SELECT LIST_ID, LISTVAL_ID
            FROM LISTVALS
            WHERE LIST_ID IN (244, 298, 352) AND TAG = :I$VAL
            INTO :I, :J;

            SELECT BLOB_ID
            FROM VAL_ADD(IIF(:I = 244, 1753, IIF(:I = 298, 2460, 3378)), :I$OBJ_ID, :J, :I$USER_ID, 0, 0)
            INTO :J;
        END
        REFRESH_FLAG = 'REFRESH_TAB';
    END
    ELSE IF ((TAG = 'STUDY_FORM') AND (I$PROCESS_TAG = 1)) THEN
    BEGIN
        IF (I$IS_DEL = 1) THEN
        BEGIN
            UPDATE VALL
            SET IS_DEL = 1
            WHERE OBJ_ID = :I$OBJ_ID AND PARAM_ID = 1888 AND IS_DEL = 0;
        END
        ELSE
        BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD(1888, :I$OBJ_ID, (SELECT PARENT_ID FROM LISTVALS WHERE LISTVAL_ID=:I$VAL), :I$USER_ID, 0, 0)
            INTO :J;
        END
        REFRESH_FLAG = 'REFRESH_TAB';
    END
    ELSE IF ((TAG = 'OOOD_TYPE') AND (I$PROCESS_TAG = 1)) THEN
    BEGIN
        IF (I$IS_DEL = 1) THEN
        BEGIN
            UPDATE VALL
            SET IS_DEL = 1
            WHERE OBJ_ID = :I$OBJ_ID AND PARAM_ID = 1889 AND IS_DEL = 0;
        END
        ELSE
        BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD(1889, :I$OBJ_ID, (SELECT PARENT_ID FROM LISTVALS WHERE LISTVAL_ID=:I$VAL), :I$USER_ID, 0, 0)
            INTO :J;
        END
        REFRESH_FLAG = 'REFRESH_TAB';
    END
    ELSE IF ((TAG = 'OP_STATE_ORG') AND (I$PROCESS_TAG = 1)) THEN
    BEGIN
        IF (I$IS_DEL = 1) THEN
        BEGIN
            UPDATE VALL
            SET IS_DEL = 1
            WHERE OBJ_ID = :I$OBJ_ID AND PARAM_ID = 2390 AND IS_DEL = 0;
        END
        ELSE
        BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD(2390, :I$OBJ_ID, (SELECT PARENT_ID FROM LISTVALS WHERE LISTVAL_ID=:I$VAL), :I$USER_ID, 0, 0)
            INTO :J;
        END
        REFRESH_FLAG = 'REFRESH_TAB';
    END
    ELSE IF (TAG IN ('FGOS_SPECIALITY', 'FGOS_SPECIALITY_CODE') AND (I$PROCESS_TAG = 1)) THEN
    BEGIN
        EXECUTE PROCEDURE OO_SPECIALITY_LINK_CREATE(:I$OBJ_ID);
    END
    ELSE IF (TAG = 'COLLEGE_STUDY_PLAN_STAGE_COUNT') THEN
    BEGIN
        EXECUTE PROCEDURE COLLEGE_SP_STAGE_CHANGED(:I$OBJ_ID);
        REFRESH_FLAG = 'REFRESH_TAB_BRANCH';
    END
    ELSE IF (TAG = 'COLLEGE_SEMESTR_COUNT') THEN
    BEGIN
        EXECUTE PROCEDURE COLLEGE_SEMESTR_COUNT_CHANGED(:I$OBJ_ID);
        REFRESH_FLAG = 'REFRESH_TAB';
    END
    ELSE IF (TAG = 'YEARASDATEASYEAR') THEN
    BEGIN
        --211
        IF (I$PARAM_ID = 2181) THEN
        BEGIN
            SELECT VD.VAL
            FROM VALI VD
            WHERE VD.PARAM_ID = 2182 AND VD.IS_DEL = 0 AND VD.OBJ_ID = :I$OBJ_ID
            INTO :I;
    
            IF ((I IS NULL) OR (I <> EXTRACT(YEAR FROM CAST(:I$VAL AS DATE))))  THEN
            BEGIN
                UPDATE OR INSERT INTO VALI
                (OBJ_ID, PARAM_ID, IS_DEL, VAL)
                VALUES (:I$OBJ_ID, 2182, 0, EXTRACT(YEAR FROM CAST(:I$VAL AS DATE)));
            END
        END
        ELSE IF (I$PARAM_ID = 2182) THEN
        BEGIN
            SELECT VD.VAL
            FROM VALD VD
            WHERE VD.PARAM_ID = 2181 AND VD.IS_DEL = 0 AND VD.OBJ_ID = :I$OBJ_ID
            INTO :D1;
    
            IF (D1 IS NULL) THEN
            BEGIN
                UPDATE OR INSERT INTO VALD
                (OBJ_ID, PARAM_ID, IS_DEL, VAL)
                VALUES (:I$OBJ_ID, 2181, 0, '01.01.' || :I$VAL);
            END
            ELSE IF (D1 <> :I$VAL) THEN
            BEGIN
                UPDATE OR INSERT INTO VALD
                (OBJ_ID, PARAM_ID, IS_DEL, VAL)
                VALUES (:I$OBJ_ID, 2181, 0, CAST(EXTRACT(DAY FROM :D1) || '.' || EXTRACT(MONTH FROM :D1) || '.' || :I$VAL AS DATE));
            END
        END
        --212
        ELSE IF (I$PARAM_ID = 2183) THEN
        BEGIN
            SELECT VD.VAL
            FROM VALI VD
            WHERE VD.PARAM_ID = 2184 AND VD.IS_DEL = 0 AND VD.OBJ_ID = :I$OBJ_ID
            INTO :I;
    
            IF ((I IS NULL) OR (I <> EXTRACT(YEAR FROM CAST(:I$VAL AS DATE))))  THEN
            BEGIN
                SELECT BLOB_ID FROM VAL_ADD(2184, :I$OBJ_ID, EXTRACT(YEAR FROM CAST(:I$VAL AS DATE)), :I$USER_ID) INTO :BLOB_ID;
            END
        END
        ELSE IF (I$PARAM_ID = 2184) THEN
        BEGIN
            SELECT VD.VAL
            FROM VALD VD
            WHERE VD.PARAM_ID = 2183 AND VD.IS_DEL = 0 AND VD.OBJ_ID = :I$OBJ_ID
            INTO :D1;
    
            IF (D1 IS NULL) THEN
            BEGIN
                SELECT BLOB_ID FROM VAL_ADD(2183, :I$OBJ_ID, '01.01.' || :I$VAL, :I$USER_ID)
                INTO BLOB_ID;            
            END
            ELSE IF (EXTRACT(YEAR FROM D1) <> :I$VAL) THEN
            BEGIN
                SELECT BLOB_ID FROM VAL_ADD(2183, :I$OBJ_ID, CAST(EXTRACT(DAY FROM :D1) || '.' || EXTRACT(MONTH FROM :D1) || '.' || :I$VAL AS DATE), :I$USER_ID) INTO :BLOB_ID;
            END
        END
        --213
        ELSE IF (I$PARAM_ID = 2185) THEN
        BEGIN
            SELECT VD.VAL
            FROM VALI VD
            WHERE VD.PARAM_ID = 2186 AND VD.IS_DEL = 0 AND VD.OBJ_ID = :I$OBJ_ID
            INTO :I;
    
            IF ((I IS NULL) OR (I <> EXTRACT(YEAR FROM CAST(:I$VAL AS DATE))))  THEN
            BEGIN
                SELECT BLOB_ID FROM VAL_ADD(2186, :I$OBJ_ID, EXTRACT(YEAR FROM CAST(:I$VAL AS DATE)), :I$USER_ID) INTO :BLOB_ID;
            END
        END
        ELSE IF (I$PARAM_ID = 2186) THEN
        BEGIN
            SELECT VAL
            FROM VALD VD
            WHERE VD.PARAM_ID = 2185 AND VD.IS_DEL = 0 AND VD.OBJ_ID = :I$OBJ_ID
            INTO :D1;
    
            IF (D1 IS NULL) THEN
            BEGIN
                SELECT BLOB_ID FROM VAL_ADD(2185, :I$OBJ_ID, '01.01.'||:I$VAL, :I$USER_ID)
                INTO BLOB_ID;            
            END
            ELSE IF (EXTRACT(YEAR FROM D1) <> :I$VAL) THEN
            BEGIN
                SELECT BLOB_ID FROM VAL_ADD(2185, :I$OBJ_ID, CAST(EXTRACT(DAY FROM :D1) || '.' || EXTRACT(MONTH FROM :D1) || '.' || :I$VAL AS DATE), :I$USER_ID) INTO :BLOB_ID;
            END
        END
        --2
        ELSE IF (I$PARAM_ID = 2187) THEN
        BEGIN
            SELECT VD.VAL
            FROM VALI VD
            WHERE VD.PARAM_ID = 2188 AND VD.IS_DEL = 0 AND VD.OBJ_ID = :I$OBJ_ID
            INTO :I;
    
            IF ((I IS NULL) OR (I <> EXTRACT(YEAR FROM CAST(:I$VAL AS DATE))))  THEN
            BEGIN
                SELECT BLOB_ID FROM VAL_ADD(2188, :I$OBJ_ID, EXTRACT(YEAR FROM CAST(:I$VAL AS DATE)), :I$USER_ID) INTO :BLOB_ID;
            END
        END
        ELSE IF (I$PARAM_ID = 2188) THEN
        BEGIN
            SELECT VAL
            FROM VALD VD
            WHERE VD.PARAM_ID = 2187 AND VD.IS_DEL = 0 AND VD.OBJ_ID = :I$OBJ_ID
            INTO :D1;
    
            IF (D1 IS NULL) THEN
            BEGIN
                SELECT BLOB_ID FROM VAL_ADD(2187, :I$OBJ_ID, '01.01.' || :I$VAL, :I$USER_ID) INTO :BLOB_ID;
            END
            ELSE IF (EXTRACT(YEAR FROM D1) <> :I$VAL) THEN
            BEGIN
                SELECT BLOB_ID FROM VAL_ADD(2187, :I$OBJ_ID, CAST(EXTRACT(DAY FROM :D1)||'.'||EXTRACT(MONTH FROM :D1)||'.'||:I$VAL AS DATE), :I$USER_ID) INTO :BLOB_ID;
            END
        END
        --2
        ELSE IF (I$PARAM_ID = 2336) THEN
        BEGIN
            SELECT VD.VAL
            FROM VALI VD
            WHERE VD.PARAM_ID = 2337 AND VD.IS_DEL = 0 AND VD.OBJ_ID = :I$OBJ_ID
            INTO :I;
    
            IF ((I IS NULL) OR (I <> EXTRACT(YEAR FROM CAST(:I$VAL AS DATE))))  THEN
            BEGIN
                SELECT BLOB_ID FROM VAL_ADD(2337, :I$OBJ_ID, EXTRACT(YEAR FROM CAST(:I$VAL AS DATE)), :I$USER_ID) INTO :BLOB_ID;
            END
        END
        ELSE IF (I$PARAM_ID = 2337) THEN
        BEGIN
            SELECT VAL
            FROM VALD VD
            WHERE VD.PARAM_ID = 2336 AND VD.IS_DEL = 0 AND VD.OBJ_ID = :I$OBJ_ID
            INTO :D1;
    
            IF (D1 IS NULL) THEN
            BEGIN
                SELECT BLOB_ID FROM VAL_ADD(2336, :I$OBJ_ID, '01.01.' || :I$VAL, :I$USER_ID) INTO :BLOB_ID;
            END
            ELSE IF (EXTRACT(YEAR FROM D1) <> :I$VAL) THEN
            BEGIN
                SELECT BLOB_ID FROM VAL_ADD(2336, :I$OBJ_ID, CAST(EXTRACT(DAY FROM :D1) || '.' || EXTRACT(MONTH FROM :D1) || '.' || :I$VAL AS DATE), :I$USER_ID) INTO :BLOB_ID;
            END
        END

        REFRESH_FLAG = 'REFRESH_TAB';
    END
    ELSE IF (TAG = 'FPU_BOOK_CODE') THEN
    BEGIN
        /* Обновляем данные об учебнике */
        EXECUTE PROCEDURE LIB_BOOK_UPDATE_PRG(:I$OBJ_ID, I$VAL, I$USER_ID) RETURNING_VALUES(:V$VAL_LONG);
        REFRESH_FLAG = 'REFRESH_TAB_AND_CAPTION';
    END
    ELSE IF (TAG = 'FPU_BOOK_PAR') THEN
    BEGIN
        /* Пользователь ввел номер параллели (параллелей) вручную */
        I = POSITION('-' IN I$VAL);
        IF(I = 0) THEN
        BEGIN
            -- Оба номера параллели одинаковы
            I = CAST(I$VAL as INTEGER);
            IF(I < 0 OR I > 12) THEN EXCEPTION DATA_ERROR 'Номер параллели должен быть в пределах 0..12';
            SELECT BLOB_ID FROM VAL_ADD(2819, :I$OBJ_ID, :I) INTO :V$VAL_LONG;
            SELECT BLOB_ID FROM VAL_ADD(2820, :I$OBJ_ID, :I) INTO :V$VAL_LONG;
        END
        ELSE
        BEGIN
            I = CAST(SUBSTRING(I$VAL FROM 1 FOR (POSITION('-' IN I$VAL) - 1)) as INTEGER);
            IF(I < 0 OR I > 12) THEN EXCEPTION DATA_ERROR 'Номер параллели должен быть в пределах 0..12';
            J = CAST(SUBSTRING(I$VAL FROM (POSITION('-' IN I$VAL) + 1)) as INTEGER);
            IF(J < 0 OR J > 12) THEN EXCEPTION DATA_ERROR 'Номер параллели должен быть в пределах 0..12';
            IF(I >= J) THEN EXCEPTION DATA_ERROR 'Начальный номер параллели должен быть меньше конечного';
            SELECT BLOB_ID FROM VAL_ADD(2819, :I$OBJ_ID, :I) INTO :V$VAL_LONG;
            SELECT BLOB_ID FROM VAL_ADD(2820, :I$OBJ_ID, :J) INTO :V$VAL_LONG;
        END
        REFRESH_FLAG = 'REFRESH_TAB';
    END

    IF (I$PARAM_ID = 2330) THEN
    BEGIN
        SELECT OBJ_TYPE_ID
        FROM LINKS
        WHERE OBJ_ID = :I$OBJ_ID
        INTO :J;

        IF (J = 112) THEN
        BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD(2330, :I$OBJ_ID, 'КО', 1)
            INTO BLOB_ID;
        END
        ELSE IF (J = 111) THEN
        BEGIN
            SELECT BLOB_ID
            FROM VAL_ADD(2330, :I$OBJ_ID, 'ОУО', 1)
            INTO BLOB_ID;
        END
    END
    ELSE IF (I$PARAM_ID = 2085) THEN
    BEGIN
        SELECT BLOB_ID FROM VAL_ADD(2086, :I$OBJ_ID, CURRENT_DATE, :I$USER_ID, 1)
        INTO BLOB_ID;
    END
    ELSE IF (I$PARAM_ID IN (2725, 2722)) THEN
    BEGIN
        REFRESH_FLAG = 'REFRESH_TAB';
        IF (I$VAL = 3) THEN
        BEGIN
            UPDATE VALS
            SET IS_DEL = 1
            WHERE OBJ_ID = :I$OBJ_ID AND PARAM_ID IN (2723, 2724, 2726, 2727);
        END
    END
    -- Запрет на изменение предметных областей у предметов
    ELSE IF (I$PARAM_ID = 2462) THEN
    BEGIN
        IF(I$OBJ_ID < 1000000000 AND V$GEN > 0) THEN EXCEPTION DATA_ERROR 'Вы не можете изменять предметные области предустановленных предметов';
        ELSE
        BEGIN
            -- А вот пользовательские предметы перенумеруем при заполнении предметной области
            IF(I$IS_DEL = 0) THEN
            BEGIN
                EXECUTE PROCEDURE SUBJECT_ENUM_MASTER(:I$OBJ_ID, :I$VAL);
                REFRESH_FLAG = 'REFRESH_TAB';
            END
        END
    END
    -- Запрет дубликатов учебников по году издания
    ELSE IF (I$PARAM_ID = 650) THEN
    BEGIN
        EXECUTE PROCEDURE LIB_BOOK_VALIDATE_REFS(:I$OBJ_ID, :I$VAL);
    END
    -- Переформируем список при изменении параллели в учебнике
    ELSE IF(I$PARAM_ID = 2658) THEN
    BEGIN
        REFRESH_FLAG = 'REFRESH_TAB_AND_CAPTION';
    END
    -- учебная неделя или этап УП
    ELSE IF(I$PARAM_ID = 2837 OR I$PARAM_ID = 381) THEN
    BEGIN
      IF(I$PARAM_ID = 381) THEN EXECUTE PROCEDURE CHECK_PLAN_STAGE(:I$OBJ_ID);
      -- при смене этапа УП передаем значение NULL
      EXECUTE PROCEDURE SCHOOL_WEEK_ADD(:I$OBJ_ID, IIF(:I$PARAM_ID = 381, NULL, CAST(:I$VAL AS BIGINT)));
      REFRESH_FLAG = 'REFRESH_TAB';
    END
    -- площадь и количество учебно-лабораторных помещений
    ELSE IF((I$PARAM_ID = 526) or (I$PARAM_ID = 533)) THEN
    BEGIN
      EXECUTE PROCEDURE AREA_SL_ROOMS_CALC(:I$OBJ_ID);
      IF(I$PARAM_ID = 526) THEN EXECUTE PROCEDURE COUNT_SL_ROOMS_CALC(:I$OBJ_ID);
      REFRESH_FLAG = 'REFRESH_TAB';
    END
    -- при изменении регистрации обновляем закладку (опциональное поле даты окончания регистрации)
    ELSE IF((I$PARAM_ID = 108) or (I$PARAM_ID = 2836)) THEN
    BEGIN
      REFRESH_FLAG = 'REFRESH_TAB';
      -- если устанавливается новое значение, отличное от временной регистрации - очищаем дату окончания регистрации
      IF(I$IS_DEL = 1 OR I$VAL <> 1218) THEN
      BEGIN
        EXECUTE PROCEDURE RESET_REGISTRATION_DATE(:I$OBJ_ID);
      END
    END
    -- запрещаем удалять параметр "Вид ОП", если в ОП добавлены учебные планы
    ELSE IF(I$PARAM_ID = 1832 AND I$IS_DEL = 1) THEN
    BEGIN
      EXECUTE PROCEDURE CHECK_OP_PLAN_EXISTS(:I$OBJ_ID);
    END
    -- корректируем адаптированность
    ELSE IF(I$PARAM_ID IN (1832, 2379) AND I$IS_DEL = 0) THEN
    BEGIN
        EXECUTE PROCEDURE APPLY_AOOP_TYPE(:I$OBJ_ID, :I$PARAM_ID, :I$VAL);
        REFRESH_FLAG = 'REFRESH_TAB';
    END
    -- Запрет изменения статуса УП и режим ВД/обычный при наличии прикрепленных учеников
    ELSE IF(I$PARAM_ID IN (2470, 2545, 3013, 3022, 2478, 3014, 2101, 3373)) THEN
    BEGIN
      I1 = NULL;
      IF(I$PARAM_ID IN (2470, 3013, 3376)) THEN
      BEGIN
        IF(I$IS_DEL = 0) THEN I1 = I$VAL;
      END
      ELSE
      BEGIN
        SELECT FIRST 1 LISTVAL_ID
        FROM VALL
        WHERE OBJ_ID = :I$OBJ_ID AND PARAM_ID IN (2470, 3013, 3373) AND IS_DEL = 0
        INTO :I1;
      END

      EXECUTE PROCEDURE CHECK_PLAN_STATUS_CANCHANGE(:I$OBJ_ID, :I1, :I$PARAM_ID);
    END
    ELSE IF(I$PARAM_ID = 3029 AND I$IS_DEL = 0) THEN
    BEGIN
      -- Запрещаем добавлять более одного однотипного правила нумерации приказов
      IF (EXISTS(SELECT FIRST 1 1
        FROM LINKS L2
        JOIN LINKS L406 ON L406.PARENT_ID = L2.OBJ_ID AND L406.OBJ_TYPE_ID = 406 AND L406.DATE_DEL IS NULL AND L406.OBJ_ID <> :I$OBJ_ID
        JOIN VALL V3029 ON V3029.OBJ_ID = L406.OBJ_ID AND V3029.PARAM_ID = 3029 AND V3029.IS_DEL = 0 AND V3029.LISTVAL_ID = :I$VAL
        WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      )) THEN
        EXCEPTION DATA_ERROR('Нельзя добавить еще одно правило нумерации приказов одного и того же типа');
    END

    -- Изменение квалификационной категории, даты приема или вида должности - обновление квалификационной категории у сотрудника
    IF(I$PARAM_ID = 72 OR I$PARAM_ID = 73 OR I$PARAM_ID = 1790) THEN
    BEGIN
      EXECUTE PROCEDURE VACANCY_UPDATE_CAT(:I$OBJ_ID);
      -- REFRESH_FLAG = 'REFRESH_TAB';
    END

    -- Не разрешаем добавлять дублирующие деления для потоков и подгрупп
    IF((I$PARAM_ID = 428 OR I$PARAM_ID = 2705) AND I$IS_DEL = 0) THEN
    BEGIN
      EXECUTE PROCEDURE CHECK_UNIQUE_DIVS(:I$OBJ_ID, :I$VAL);
    END

    -- При заполнении с нуля или изменении направления предмета ВД, корректируем номер
    IF(I$PARAM_ID = 2464 AND I$IS_DEL = 0) THEN EXECUTE PROCEDURE SUBJECT_ENUM_DIR(:I$OBJ_ID, :I$VAL); -- refresh

    -- Проверяем, что при смене образовательного стандарта поле выбора профиля остается корректным
    -- Тут же при смене стандарта пересчитываем предметные области СОО
    IF(I$PARAM_ID IN (2478, 3014) AND I$IS_DEL = 0) THEN EXECUTE PROCEDURE PLAN_PROFILE_VALIDATE(:I$OBJ_ID, :I$VAL);

    -- Валидация указанного текущего учебного года
    IF(I$PARAM_ID = 1236 AND I$IS_DEL = 0) THEN EXECUTE PROCEDURE VALIDATE_CURRENT_YEAR(:I$VAL);

    -- Блокировка ввода СНИЛС в документе, а также проверка корреляции с данными персоны
    IF(I$PARAM_ID IN (51, 571, 1409, 2455)) THEN
    BEGIN
      EXECUTE PROCEDURE COPY_EMPLOYEE_SNILS(:I$OBJ_ID, :I$PARAM_ID, I$USER_ID);
      REFRESH_FLAG = 'REFRESH_TAB';
    END
    -- Запрет выбора двух должностей в отчет
    IF(I$PARAM_ID = 2934 AND I$IS_DEL = 0 AND I$VAL = 2) THEN EXECUTE PROCEDURE VALIDATE_DEFAULT_JOB(:I$OBJ_ID);

    -- Обнуление нагрузок при увольнении
    IF(I$PARAM_ID = 74 AND I$IS_DEL = 0) THEN EXECUTE PROCEDURE VALIDATE_LAST_JOB(:I$OBJ_ID);

    -- Выбор профессии ПО
    IF(I$PARAM_ID = 2126 AND I$IS_DEL = 0) THEN EXECUTE PROCEDURE UPDATE_PROFESSION_CODE(:I$OBJ_ID, :I$VAL); -- refresh

    -- Пересчет статуса инклюзивности класса при смене статуса обучающегося
    IF(I$PARAM_ID = 207) THEN EXECUTE PROCEDURE CLASS_OVZ_RECALC(:I$OBJ_ID);

    -- Уникальность разделов ОП
    IF(I$PARAM_ID = 2450) THEN EXECUTE PROCEDURE OP_ENSURE_UNQ(:I$OBJ_ID, IIF(:I$IS_DEL = 0, :I$VAL, 0));

    -- Выбор сотрудника экспертом
    IF(I$PARAM_ID = 2935) THEN
    BEGIN
        EXECUTE PROCEDURE UT_SYNC_EXPERT(:I$OBJ_ID, IIF(:I$VAL IS NULL, 3, :I$VAL));
    END
    ELSE IF(I$PARAM_ID IN (59, 60, 61, 241, 1180)) THEN
    BEGIN
        EXECUTE PROCEDURE UT_SYNC_EXPERT(:I$OBJ_ID, NULL);
    END
    ELSE IF(I$PARAM_ID IN (441, 614) AND I$IS_DEL = 0) THEN
    BEGIN
        EXECUTE PROCEDURE CHECK_ACTIVE_DOCUMENTS(:I$OBJ_ID);
    END
    -- Установка ОВЗ всем ученикам
    ELSE IF(I$PARAM_ID = 554 AND I$IS_DEL = 0) THEN
    BEGIN
        EXECUTE PROCEDURE APPLY_OVZ_TYPE(:I$OBJ_ID, :I$VAL);
    END
    ELSE IF(I$PARAM_ID = 592 AND I$IS_DEL = 0) THEN
    BEGIN
        -- Изменение типа учебного коллектива в записи движения при его изменении в самом коллективе
        IF((I$VAL = 13274 OR I$VAL = 13275)) THEN
        BEGIN
            SELECT BLOB_ID FROM VAL_ADD(554, :I$OBJ_ID, 1355) INTO :BLOB_ID;
        END

        UPDATE PERSON_MOVEMENTS SET TYPE_IN = :I$VAL WHERE DATE_DEL IS NULL AND DATE_OUT IS NULL AND GROUP_ID = :I$OBJ_ID;
    END
    ELSE IF(I$PARAM_ID IN (53, 1609)) THEN
    BEGIN
        IF(I$VAL IS NOT NULL AND I$VAL <> '') THEN
        BEGIN
            SELECT FIRST 1 U.USER_ID
            FROM USERS U
            WHERE U.OBJ_ID = :I$VAL
            INTO :V$OBJ_ID;

            IF(V$OBJ_ID IS NOT NULL) THEN EXECUTE PROCEDURE CJ2_JOURNAL_ACCESS_UPD(NULL, :V$OBJ_ID);
        END
    END
    ELSE IF(TYPE_ID IN (441, 442, 443, 444, 447, 453)) THEN
    BEGIN
        EXECUTE PROCEDURE GZ_VAL_AFTER(:I$OBJ_ID, :I$PARAM_ID, :I$VAL, :I$IS_DEL);
    END
    ELSE IF(TYPE_ID IN (458, 459)) THEN
    BEGIN
        EXECUTE PROCEDURE ATT_VAL_AFTER(:I$OBJ_ID, :I$PARAM_ID, :I$VAL, :I$IS_DEL, :I$USER_ID);
        REFRESH_FLAG = 'REFRESH_TAB';
    END
    ELSE IF(I$PARAM_ID = 3278) THEN
    BEGIN
      IF(I$IS_DEL = 0 AND CAST(I$VAL AS DATE) < '01.09.2022') THEN EXCEPTION DATA_ERROR 'Недопустимое значение даты';
      FOR
        SELECT LP10.PARENT_ID
        FROM LINKS LP10
        JOIN LINKS LP9 ON LP9.OBJ_ID = LP10.PARENT_ID AND LP9.PARENT_TYPE_ID IN (9, 187) AND LP9.DATE_DEL IS NULL
        WHERE LP10.OBJ_ID = :I$OBJ_ID AND LP10.PARENT_TYPE_ID = 10 AND LP10.DATE_DEL IS NULL
        INTO :V$OBJ_ID
      DO
      BEGIN
        IF(I$VAL IS NOT NULL AND I$IS_DEL = 0) THEN
        BEGIN
          IF(V$OU_LICENCE_TYPE = 'O') THEN SELECT 1 FROM VAL_ADD(3280, :V$OBJ_ID, 2) INTO :V$BLOB_ID;
          IF(V$OU_LICENCE_TYPE = 'O') THEN SELECT 1 FROM VAL_ADD(3281, :V$OBJ_ID, 2) INTO :V$BLOB_ID;
          IF(V$OU_LICENCE_TYPE = 'D') THEN SELECT 1 FROM VAL_ADD(3282, :V$OBJ_ID, 2) INTO :V$BLOB_ID;
        END
        ELSE
        BEGIN
          SELECT 1 FROM VAL_ADD(3280, :V$OBJ_ID, 3) INTO :V$BLOB_ID;
          SELECT 1 FROM VAL_ADD(3281, :V$OBJ_ID, 3) INTO :V$BLOB_ID;
          SELECT 1 FROM VAL_ADD(3282, :V$OBJ_ID, 3) INTO :V$BLOB_ID;
          SELECT 1 FROM VAL_ADD(3283, :V$OBJ_ID, 3) INTO :V$BLOB_ID;
          SELECT 1 FROM VAL_ADD(3284, :V$OBJ_ID, 3) INTO :V$BLOB_ID;
          SELECT 1 FROM VAL_ADD(3285, :V$OBJ_ID, 3) INTO :V$BLOB_ID;
        END
      END
    END
    ELSE IF(I$PARAM_ID = 1170 AND I$IS_DEL = 0) THEN
    BEGIN
      -- Проверяем периоды в расписании
      EXECUTE PROCEDURE PERIOD_VERIFY(:I$OBJ_ID, :I$VAL);
    END
    ELSE IF(I$PARAM_ID = 3372 AND I$IS_DEL = 0) THEN
    BEGIN
      -- Журнал воспитательной работы
      EXECUTE PROCEDURE CREATE_CJ_VOSP(:I$OBJ_ID);
    END
    ELSE IF(I$PARAM_ID = 613 AND I$IS_DEL = 0) THEN
    BEGIN
      -- Статус документа ОООД
      EXECUTE PROCEDURE UPDATE_DOCUMENT_STATUS(:I$OBJ_ID, :I$VAL);
    END
    ELSE IF(I$PARAM_ID IN (3244, 3247)) THEN
    BEGIN
      -- Пересчет данных УП при изменении количества в плановом периоде
      EXECUTE PROCEDURE PLAN_RECALC(:I$OBJ_ID, NULL);
    END
    ELSE IF(I$PARAM_ID = 3389 AND I$IS_DEL = 0) THEN
    BEGIN
      -- Проверка учебного года КУГ
      EXECUTE PROCEDURE VALIDATE_KUG(:I$OBJ_ID, :I$VAL);
    END
    ELSE IF(I$PARAM_ID IN (3477, 3075) AND I$IS_DEL = 0) THEN
    BEGIN
      -- Копирование кодов из УП при связи коллектива с УП
      EXECUTE PROCEDURE COPY_SPO_CODES(:I$OBJ_ID, :I$VAL);
      REFRESH_FLAG = 'REFRESH_TAB';
    END
    ELSE IF(I$PARAM_ID = 3479 AND I$IS_DEL = 0) THEN
    BEGIN
      -- Медаль - только выпускные 11-е классы
      EXECUTE PROCEDURE CHECK_MEDAL_ALLOW(:I$OBJ_ID);
    END
    ELSE IF(I$PARAM_ID IN (43, 49)) THEN
    BEGIN
      -- Нельзя менять уровень образования и этап при наличии подчиненных сущностей
      IF(EXISTS(
        SELECT FIRST 1 1
        FROM LINKS L
        WHERE L.PARENT_ID = :I$OBJ_ID AND L.OBJ_TYPE_ID IN (8, 9, 125, 187, 86) AND L.DATE_DEL IS NULL
      ))
      THEN
        EXCEPTION DATA_ERROR 'Нельзя изменять уровень образования или этап обучения при наличии дочерних объектов';
    END
    ELSE IF(I$PARAM_ID = 3585) THEN
    BEGIN
      -- График отпусков, тут только изменение статуса
      EXECUTE PROCEDURE VACATION_APPROVE(:I$OBJ_ID, :I$VAL, :I$USER_ID);
    END
    ELSE IF(I$PARAM_ID IN (3396, 3397) AND I$IS_DEL = 0) THEN
    BEGIN
      -- Проверка дат периодов аттестации
      EXECUTE PROCEDURE ATT_DATE_VERIFY(:I$OBJ_ID);
    END
    --ELSE IF (I$PARAM_ID = 1768 AND I$IS_DEL = 0) THEN
    --BEGIN
      -- форма обучения для класса. Продублируем ее для всех учеников класса у которых она отличается от "классной" https://jira.netrika.ru/browse/PARAGRAPH-1229
    --  UPDATE VALL
    --  SET LISTVAL_ID = :I$VAL
    --  WHERE PARAM_ID = 80 AND IS_DEL = 0 AND (LISTVAL_ID <> :I$VAL)
    --    AND OBJ_ID IN (SELECT DISTINCT L10.OBJ_ID FROM LINKS L10 WHERE L10.PARENT_ID = :I$OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL);
    --END

    IF(TYPE_ID = 505 AND I$IS_DEL = 0) THEN
    BEGIN
      EXECUTE PROCEDURE JOB_LIST_VERIFY(:I$OBJ_ID, :I$USER_ID, :TYPE_ID, :I$PARAM_ID, :I$VAL);
      REFRESH_FLAG = 'REFRESH_TAB';
      IF (I$PARAM_ID = 3490) THEN REFRESH_FLAG = 'REFRESH_BRANCH';
    END
    IF(TYPE_ID = 512) THEN
    BEGIN
      -- Отчеты мониторинга
      REFRESH_FLAG = 'REFRESH_TAB_AND_CAPTION';
    END
    IF(TYPE_ID = 531) THEN
    BEGIN
      -- Распределение учебной нагрузки
      IF(I$PARAM_ID = 3568) THEN EXECUTE PROCEDURE EDULOAD_APPROVE(:I$OBJ_ID, :I$VAL, :I$USER_ID);
      -- При сохранении даты приказа создаем сущность приказа (сначала сохраняется номер, затем дата)
      IF(I$PARAM_ID = 3570) THEN EXECUTE PROCEDURE EDULOAD_UPDATE_ORDER(:I$OBJ_ID);
      REFRESH_FLAG = 'REFRESH_TAB_AND_CAPTION';
    END

    -- 3016 изменение типа УП - исключен из блокировки
    IF(I$PARAM_ID = 3016) THEN SELECT COUNT(*) FROM MONITORING_PLAN_UPD(:I$OBJ_ID) INTO :I;

    -- Время начала урока
    IF(I$PARAM_ID = 405) THEN EXECUTE PROCEDURE UPDATE_LESSON_TIME(:I$OBJ_ID, :I$VAL);

    IF(I$PARAM_ID IN (72, 73, 51, 592, 1790, 2126, 2373, 2374, 2375, 2464, 3114)) THEN REFRESH_FLAG = 'REFRESH_TAB';

    SUSPEND;
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE VAL_DOCUMENT_CHECK (
    I$OBJ_ID BIGINT,
    I$PARAM_ID BIGINT,
    I$VAL VARCHAR(4000),
    I$IS_DEL SMALLINT)
AS
declare variable V$PARENT_TYPE bigint;
begin

  SELECT L.PARENT_TYPE_ID
  FROM LINKS L
  WHERE L.OBJ_ID = :I$OBJ_ID AND L.PARENT_TYPE_ID IN (2, 496) AND L.DATE_DEL IS NULL
  INTO :V$PARENT_TYPE;

  IF(V$PARENT_TYPE = 496 AND (I$IS_DEL <> 0 OR I$PARAM_ID <> 613)) THEN
    EXCEPTION DATA_ERROR 'Нельзя изменять атрибуты архивного документа';

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE VAL_GET (
    I$OBJ_ID BIGINT,
    I$PARAM_ID BIGINT,
    I$IS_DEL SMALLINT = 0,
    I$USER_ID BIGINT = 1,
    I$PARENT_ID BIGINT = null)
RETURNS (
    I BIGINT,
    F DOUBLE PRECISION,
    DT TIMESTAMP,
    D DATE,
    T TIME,
    V VARCHAR(4000),
    SORT_ORDER DOUBLE PRECISION,
    USER_ID BIGINT,
    IS_EXISTS INTEGER,
    V_LONG VARCHAR(4000),
    COST FLOAT)
AS
declare variable PT smallint;
declare variable C timestamp;
declare variable Y smallint;
declare variable M smallint;
declare variable K smallint;
declare variable H smallint;
declare variable N smallint;
declare variable Y1 char(4);
declare variable M1 char(3);
declare variable D1 char(3);
declare variable H1 char(2);
declare variable N1 char(3);
declare variable DO_FUNC bigint;
declare variable LANG_CODE varchar(2);
declare variable TAG varchar(100);
declare variable V$TAG varchar(100);
declare variable V$OU_LICENCE_TYPE varchar(1);
declare variable V$LV bigint;
BEGIN
    COST = 0;
    I = 0;
    F = 0;
    DT = '2000-01-01 00:00:00';
    D = '2000-01-01';
    T = '00:00';
    V = '';
    V_LONG = '';
    SORT_ORDER = 0;
    USER_ID = NULL;
    IS_EXISTS = 0;
    C = '2000-01-01 00:00:00';
    PT = 0;
    SELECT P.PARAM_TYPE, P.DO_FUNC, P.TAG
    FROM PARAMS P
    WHERE P.PARAM_ID = :I$PARAM_ID AND P.IS_DEL = 0
    INTO :PT, :DO_FUNC, :TAG;

    IF (PT = 1) THEN
    BEGIN /* INTEGER */
        SELECT USER_ID, VAL, CAST(VAL AS VARCHAR(4000)), CAST(VAL AS DOUBLE PRECISION)
        FROM VALI
        WHERE PARAM_ID = :I$PARAM_ID AND OBJ_ID = :I$OBJ_ID AND IS_DEL <= :I$IS_DEL
        INTO :USER_ID, :I, :V, :SORT_ORDER;
        IS_EXISTS = ROW_COUNT;
    END
    ELSE
    IF (PT = 2) THEN
    BEGIN /* FLOAT */
        SELECT USER_ID, VAL, CAST(VAL AS VARCHAR(4000)), VAL
        FROM VALF
        WHERE PARAM_ID = :I$PARAM_ID AND OBJ_ID = :I$OBJ_ID AND IS_DEL <= :I$IS_DEL
        INTO :USER_ID, :F, :V, :SORT_ORDER;
        IS_EXISTS = ROW_COUNT;
    END
    ELSE
    IF (PT = 3) THEN
    BEGIN /* TIMESTAMP */
        SELECT USER_ID, VAL, CAST(VAL AS DATE), CAST(VAL AS TIME)
        FROM VALDT
        WHERE PARAM_ID = :I$PARAM_ID AND OBJ_ID = :I$OBJ_ID AND IS_DEL <= :I$IS_DEL
        INTO :USER_ID, :DT, :D, :T;
        IS_EXISTS = ROW_COUNT;
    END
    ELSE
    IF (PT = 4) THEN
    BEGIN /* DATE */
        SELECT USER_ID, VAL, VAL
        FROM VALD
        WHERE PARAM_ID = :I$PARAM_ID AND OBJ_ID = :I$OBJ_ID AND IS_DEL <= :I$IS_DEL
        INTO :USER_ID, :DT, :D;
        IS_EXISTS = ROW_COUNT;
    END
    ELSE
    IF (PT = 5) THEN
    BEGIN /* TIME */
        SELECT USER_ID, VAL, VAL
        FROM VALT
        WHERE PARAM_ID = :I$PARAM_ID AND OBJ_ID = :I$OBJ_ID AND IS_DEL <= :I$IS_DEL
        INTO :USER_ID, :DT, :T;
        IS_EXISTS = ROW_COUNT;
    END
    ELSE
    IF (PT = 6) THEN
    BEGIN /* LIST_VALUE */
        SELECT V.USER_ID, V.LISTVAL_ID, L.TAG
        FROM VALL V
        JOIN LISTVALS L ON L.LISTVAL_ID = V.LISTVAL_ID
        WHERE V.PARAM_ID = :I$PARAM_ID AND V.OBJ_ID = :I$OBJ_ID AND V.IS_DEL <= :I$IS_DEL
        INTO :USER_ID, :I, :V$TAG;
        IS_EXISTS = ROW_COUNT;

        IF ((IS_EXISTS = 0) AND (I$PARAM_ID IN (2154, 2159, 2175))) THEN
        BEGIN
            USER_ID = I$USER_ID;
            IS_EXISTS = 1;
            I = 3;
        END
        ELSE IF ((IS_EXISTS = 0) AND (I$PARAM_ID IN (2155, 2160))) THEN
        BEGIN
            USER_ID = I$USER_ID;
            IS_EXISTS = 1;
            I = 2;
        END
        ELSE IF ((IS_EXISTS = 0) AND (I$PARAM_ID IN (1340,835))) THEN
        BEGIN
            SELECT STATUS FROM OU_LICENCE_TYPE INTO :V$OU_LICENCE_TYPE;     
            IF (V$OU_LICENCE_TYPE = 'O') THEN
            BEGIN
                -- Для ВПЛ выставляется выпускник прошлых лет
                IF (EXISTS(SELECT 1 FROM KEYS WHERE KEY_CODE = 'TYPE' AND KEY_VAL = '-1') AND EXISTS(SELECT 1 FROM KEYS WHERE KEY_CODE = 'LEVEL' AND KEY_VAL = '1')) THEN
                BEGIN
                    I = 2995;
                END
                ELSE IF (I$PARAM_ID = 1340) THEN
                BEGIN
                    -- Обновляем на базе признака текущего класса
                    V$LV = NULL;
                    SELECT V2388.LISTVAL_ID
                    FROM LINKS LP9
                    JOIN VALL V2388 ON V2388.OBJ_ID = LP9.PARENT_ID AND V2388.PARAM_ID = 2388 AND V2388.IS_DEL = 0
                    WHERE LP9.OBJ_ID = :I$OBJ_ID AND LP9.PARENT_TYPE_ID = 9 AND LP9.DATE_DEL IS NULL
                    INTO :V$LV;

                    IF(V$LV IS NOT NULL) THEN
                    BEGIN
                        IS_EXISTS = 1;
                        IF(V$LV = 11217) THEN I = 2992; ELSE I = 2993;
                        V = I;
                        SELECT BLOB_ID FROM VAL_ADD(1340, :I$OBJ_ID, :I) INTO :V$LV;
                    END
                END
                ELSE
                BEGIN
                    I = 2994;
                END
            END
            ELSE IF (V$OU_LICENCE_TYPE = 'C') THEN
            BEGIN
                SELECT BLOB_ID
                FROM VAL_ADD(1340, :I$OBJ_ID, 10874)
                INTO :I;
                I = 10874;
            END
            IF (I > 0) THEN
            BEGIN
                USER_ID = I$USER_ID;
                IS_EXISTS = 1;
            END
        END

        IF (IS_EXISTS > 0) THEN
        BEGIN
            SELECT LANG_CODE
            FROM USERS
            WHERE USER_ID = :I$USER_ID
            INTO :LANG_CODE;

            SELECT R.VAL, R.VAL_LONG, L.SORT_ORDER, L.COST
            FROM LISTVALS L
            LEFT JOIN RES_GET(L.RES_ID,  :LANG_CODE) R ON 1 = 1
            WHERE LISTVAL_ID = :I
            INTO :V, :V_LONG, :SORT_ORDER, :COST;

            IF (TAG = 'ENUMERATION') THEN
            BEGIN
                V = IIF(V$TAG <> '',V$TAG || '. ','') || V;
            END
        END
    END
    ELSE
    IF (PT IN (7, 8, 9, 10, 20, 21)) THEN
    BEGIN /* STRING_OR_LIST_VALUE_RO, STRING_OR_LIST_VALUE, STRING, SQL_QUERY, FUNCTION */
        SELECT USER_ID, VAL
        FROM VALS
        WHERE PARAM_ID = :I$PARAM_ID AND OBJ_ID = :I$OBJ_ID AND IS_DEL <= :I$IS_DEL
        INTO :USER_ID, :V;
        IS_EXISTS = ROW_COUNT;
    END
    ELSE
    IF ((PT = 11) OR (PT = 12)) THEN
    BEGIN /* FILE, IMAGE */
        SELECT USER_ID, VAL, BLOB_ID
        FROM VALB
        WHERE PARAM_ID = :I$PARAM_ID AND OBJ_ID = :I$OBJ_ID AND IS_DEL <= :I$IS_DEL
        INTO :USER_ID, :V, :I;
        IS_EXISTS = ROW_COUNT;
    END
    ELSE
    IF (PT = 13) THEN
    BEGIN /* REFERENCE */
        SELECT USER_ID, VAL
        FROM VALR
        WHERE PARAM_ID = :I$PARAM_ID AND OBJ_ID = :I$OBJ_ID AND IS_DEL <= :I$IS_DEL
        INTO :USER_ID, :I;
        IS_EXISTS = ROW_COUNT;

        IF (IS_EXISTS > 0) THEN
        BEGIN
            SELECT CAPTION, SORT_ORDER
            FROM OBJECT_CAPTION_GET(:I, NULL, NULL, :I$USER_ID)
            INTO :V, :SORT_ORDER;
        END
    END
    ELSE
    IF (PT = 18) THEN
    BEGIN /*ADDRESS*/
        SELECT VAL
        FROM ADR_GET(:I$PARAM_ID, :I$OBJ_ID, :I$IS_DEL)
        INTO :V;
        IS_EXISTS = ROW_COUNT;
    END

    IF ((PT > 2) AND
        (PT < 6) AND
        (IS_EXISTS > 0)) THEN
    BEGIN
        SORT_ORDER = :DT - :C;
        Y = EXTRACT(YEAR FROM :DT);
        M = EXTRACT(MONTH FROM :DT);
        K = EXTRACT(DAY FROM :DT);
        H = EXTRACT(HOUR FROM :DT);
        N = EXTRACT(MINUTE FROM :DT);

        Y1 = Y;
        IF (M > 9) THEN
            M1 = M || '.';
        ELSE
            M1 = '0' || M || '.';
        IF (K > 9) THEN
            D1 = K || '.';
        ELSE
            D1 = '0' || K || '.';
        IF (H > 9) THEN
            H1 = H;
        ELSE
            H1 = '0' || H;
        IF (N > 9) THEN
            N1 = ':' || N;
        ELSE
            N1 = ':0' || N;

        IF (PT = 3) THEN
            V = D1 || M1 || Y1 || ' ' || H1 || N1;
        IF (PT = 4) THEN
            V = D1 || M1 || Y1;
        IF (PT = 5) THEN
            V = H1 || N1;
    END
    ELSE IF (PT IN (10,17,19)) THEN
    BEGIN
        IS_EXISTS = 1;
        SELECT I,VAL FROM DO_FUNC(:I$OBJ_ID, :I$PARAM_ID, :DO_FUNC, NULL, :I$USER_ID, :I$PARENT_ID) INTO I,V;
    END

    IF (IS_EXISTS = 0) THEN
    BEGIN
        I = 0;
        F = 0;
        DT = NULL;
        D = NULL;
        T = NULL;
        V = '';
        V_LONG = '';
        SORT_ORDER = 999999999999999999;
    END
    ELSE
    BEGIN
        -- Учебники - сортировка по первым буквам названия
        IF(I$PARAM_ID = 647) THEN
        BEGIN
          -- Технически невозможно
        END
        -- Учебники - сортировка по первому числу в параллели
        ELSE IF(I$PARAM_ID = 2658) THEN
        BEGIN
           N = POSITION('-' IN V);
           IF(N = 0) THEN TAG = V; ELSE TAG = SUBSTRING(V FROM 1 FOR (N - 1));
           N = CAST(V AS INTEGER);
           SORT_ORDER = N;
           WHEN ANY DO N = 99;
        END
    END

    SUSPEND;

    WHEN ANY DO EXCEPTION DATA_ERROR 'Ошибка VAL_GET на объекте ' || COALESCE(I$OBJ_ID, 0) || ', параметр ' || COALESCE(I$PARAM_ID, 0);

END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE VAL_SERIALIZE (
    I$OBJ_ID BIGINT,
    I$PARAM_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(2000))
AS
DECLARE VARIABLE V$TYPE_ID BIGINT;
DECLARE VARIABLE V$LIST_ID BIGINT;
DECLARE VARIABLE V$I BIGINT;
DECLARE VARIABLE V$REGION VARCHAR(255);
DECLARE VARIABLE V$DISTRICT VARCHAR(255);
DECLARE VARIABLE V$TOWN VARCHAR(255);
DECLARE VARIABLE V$SETTLEMENT VARCHAR(255);
DECLARE VARIABLE V$STREET VARCHAR(255);
DECLARE VARIABLE V$HOUSE VARCHAR(10);
DECLARE VARIABLE V$CORP VARCHAR(10);
DECLARE VARIABLE V$LITER VARCHAR(10);
DECLARE VARIABLE V$FLAT VARCHAR(10);
DECLARE VARIABLE V$POST_INDEX VARCHAR(20);
DECLARE VARIABLE V$OCATD VARCHAR(11);
DECLARE VARIABLE V$FIAS_UID VARCHAR(40);
DECLARE VARIABLE V$STREET_UID VARCHAR(40);
begin

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  SELECT P.PARAM_TYPE, P.LIST_ID
  FROM PARAMS P
  WHERE P.PARAM_ID = :I$PARAM_ID
  INTO :V$TYPE_ID, :V$LIST_ID;

  TAG_NAME = 'obj_id';
  VAL = I$OBJ_ID;
  SUSPEND;

  TAG_NAME = 'param_id';
  VAL = I$PARAM_ID;
  SUSPEND;

  TAG_NAME = 'type_id';
  VAL = V$TYPE_ID;
  SUSPEND;

  TAG_NAME = 'list_id';
  VAL = V$LIST_ID;
  SUSPEND;

  IF(V$TYPE_ID = 18) THEN
  BEGIN

    -- Адрес
    TAG_NAME = 'text';
    VAL = NULL;
    SELECT REGION, DISTRICT, TOWN, SETTLEMENT, STREET, HOUSE, CORP, LITER, FLAT, POST_INDEX, OCATD, HOUSEGUID, STREETGUID, VAL
    FROM ADR_GET(:I$PARAM_ID, :I$OBJ_ID)
    INTO :V$REGION, :V$DISTRICT, :V$TOWN, :V$SETTLEMENT, :V$STREET, :V$HOUSE, :V$CORP, :V$LITER, :V$FLAT, :V$POST_INDEX, :V$OCATD, :V$FIAS_UID, :V$STREET_UID, :VAL;
    SUSPEND;

    TAG_NAME = 'region_text';
    VAL = V$REGION;
    SUSPEND;

    TAG_NAME = 'area_text';
    VAL = V$DISTRICT;
    SUSPEND;

    TAG_NAME = 'city_text';
    VAL = V$TOWN;
    SUSPEND;

    TAG_NAME = 'settlement_text';
    VAL = V$SETTLEMENT;
    SUSPEND;

    TAG_NAME = 'street_text';
    VAL = V$STREET;
    SUSPEND;

    TAG_NAME = 'house';
    VAL = V$HOUSE;
    SUSPEND;

    TAG_NAME = 'corp';
    VAL = V$CORP;
    SUSPEND;

    TAG_NAME = 'liter';
    VAL = V$LITER;
    SUSPEND;

    TAG_NAME = 'flat';
    VAL = V$FLAT;
    SUSPEND;

    TAG_NAME = 'street_id';
    VAL = V$STREET_UID;
    SUSPEND;

    TAG_NAME = 'reg_id';
    VAL = V$FIAS_UID;
    SUSPEND;

    TAG_NAME = 'postcode';
    VAL = V$POST_INDEX;
    SUSPEND;

    TAG_NAME = 'ocatd';
    VAL = V$OCATD;
    SUSPEND;

  END
  ELSE
  BEGIN

    -- Все остальное
    TAG_NAME = 'value';
    VAL = NULL;
    SELECT V, I
    FROM VAL_GET(:I$OBJ_ID, :I$PARAM_ID)
    WHERE IS_EXISTS = 1
    INTO :VAL, :V$I;
    SUSPEND;

    TAG_NAME = 'listval_id';
    VAL = V$I;
    SUSPEND;

  END

  -- Для названия в трудовой - добавляем список выбора для учительских должностей
  IF(I$PARAM_ID = 3543) THEN
  BEGIN
    V$I = NULL;
    SELECT FIRST 1 V58.LISTVAL_ID
    FROM LINKS LP13
    JOIN VALL V58 ON V58.OBJ_ID = LP13.PARENT_ID AND V58.PARAM_ID = 58 AND V58.IS_DEL = 0
    WHERE LP13.OBJ_ID = :I$OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
    INTO :V$I;

    IF(V$I = 18501) THEN
    BEGIN
      TAG_NAME = 'selection::json&colon;array';
      VAL = '1';
      SUSPEND;
      FOR
        SELECT L.VAL
        FROM LISTVALS_LIST(370) L
        WHERE L.IS_DEL = 0
        INTO :V$REGION
      DO
      BEGIN
        TAG_NAME = 'selection:r';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'selection:r:value';
        VAL = V$REGION;
        SUSPEND;
      END
    END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE VAL_SQL_QUERY_GET_INT (
    I$1 INTEGER,
    I$2 INTEGER)
RETURNS (
    V VARCHAR(4000))
AS
DECLARE VARIABLE I INTEGER;
BEGIN
    I = I$1;
    WHILE (I <= I$2)
    DO
    BEGIN
        V = I;
        SUSPEND;
        I = I + 1;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE VAL_TAG_GET (
    I$OBJ_ID BIGINT,
    I$TAG VARCHAR(100))
RETURNS (
    I BIGINT,
    F DOUBLE PRECISION,
    DT TIMESTAMP,
    D DATE,
    T TIME,
    V VARCHAR(4000),
    SORT_ORDER DOUBLE PRECISION,
    USER_ID BIGINT,
    IS_EXISTS INTEGER,
    V_LONG VARCHAR(4000))
AS
declare variable V$PARAM_ID bigint;
BEGIN
    FOR SELECT P.PARAM_ID
        FROM OBJECTS O
        JOIN PARAMS P ON P.TYPE_ID = O.TYPE_ID
        WHERE O.OBJ_ID = :I$OBJ_ID AND P.TAG LIKE :I$TAG
        INTO :V$PARAM_ID
    DO
    BEGIN
        SELECT I, F, DT, D, T, V, SORT_ORDER, USER_ID, IS_EXISTS, V_LONG
        FROM VAL_GET(:I$OBJ_ID, :V$PARAM_ID, 0)
        INTO :I, :F, :DT, :D, :T, :V, :SORT_ORDER, :USER_ID, :IS_EXISTS, :V_LONG;
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE VARGRP_APPLY (
    I$STAGE_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$NAME VARCHAR(1000),
    I$MASK BIGINT,
    I$DELETE SMALLINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    OBJ_ID BIGINT,
    TYPE_ID BIGINT)
AS
DECLARE VARIABLE V$STATE_ID BIGINT;
DECLARE VARIABLE V$STAGE_ID BIGINT;
DECLARE VARIABLE V$MASK BIGINT;
DECLARE VARIABLE V INTEGER;
DECLARE VARIABLE T BIGINT;
DECLARE VARIABLE S VARCHAR(1000);
begin

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  -- !!! права доступа

  SELECT V2470.LISTVAL_ID, V381.LISTVAL_ID, LV.COST
  FROM LINKS LP50
  JOIN VALL V381 ON V381.OBJ_ID = LP50.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
  JOIN VALL V2470 ON V2470.OBJ_ID = LP50.PARENT_ID AND V2470.PARAM_ID = IIF(LP50.PARENT_TYPE_ID = 50, 2470, 3013) AND V2470.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V381.LISTVAL_ID
  WHERE LP50.OBJ_ID = :I$STAGE_ID AND LP50.PARENT_TYPE_ID IN (50, 400) AND LP50.DATE_DEL IS NULL
  INTO :V$STATE_ID, :V$STAGE_ID, :V;

  IF(V$STATE_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Данные не найдены или были удалены';
  IF(V$STATE_ID <> 11715) THEN EXCEPTION DATA_ERROR 'Нельзя формировать группы, пока учебный план не утвержден';

  I$NAME = COALESCE(TRIM(I$NAME), '');
  IF(I$DELETE = 0 AND CHAR_LENGTH(I$NAME) = 0) THEN EXCEPTION DATA_ERROR 'Требуется указать название группы';

  IF(I$OBJ_ID IS NOT NULL) THEN
  BEGIN
    SELECT LG.OBJ_ID, LG.OBJ_TYPE_ID, COALESCE(V2162.VAL, ''), COALESCE(V3062.VAL, 0)
    FROM LINKS LG
    LEFT JOIN VALS V2162 ON V2162.OBJ_ID = LG.OBJ_ID AND V2162.PARAM_ID = 2162 AND V2162.IS_DEL = 0
    LEFT JOIN VALI V3062 ON V3062.OBJ_ID = LG.OBJ_ID AND V3062.PARAM_ID = 3062 AND V3062.IS_DEL = 0
    WHERE LG.PARENT_ID = :I$STAGE_ID AND LG.OBJ_ID = :I$OBJ_ID AND LG.DATE_DEL IS NULL
    INTO :OBJ_ID, :TYPE_ID, :S, :V$MASK;

    IF(OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Группа не найдена или была удалена';
  END

  IF(I$DELETE = 0) THEN
  BEGIN
    -- Маска должна как минимум содержать уровень, в котором находится сама группа
    IF(BIN_AND(I$MASK, BIN_SHL(1, V)) = 0) THEN EXCEPTION DATA_ERROR 'В выборе этапов обучения должен быть как минимум указан тот, к которому относится сама группа';
  END

  IF(I$OBJ_ID IS NULL) THEN
  BEGIN
    -- Создаем группу
    S = '';
    V$MASK = 0;

    IF(I$DELETE <> 0) THEN EXCEPTION DATA_ERROR 'Нельзя удалить несуществующее';

    SELECT OBJ_ID, TYPE_ID
    FROM OBJECT_ADD(:I$STAGE_ID, 256, NULL, NULL, :I$USER_ID)
    INTO :OBJ_ID, :TYPE_ID;
  END
  ELSE IF(I$DELETE = 0) THEN
  BEGIN
    -- Обновляем группу
  END
  ELSE IF(I$DELETE = 2) THEN
  BEGIN
    -- Фактическое удаление идет в два шага - сначала проверка с DELETE = 1, затем фактическое удаление с DELETE = 2
    -- Проверяем, что все участники группы удалены
    IF(EXISTS(
      SELECT FIRST 1 1
      FROM LINKS L10
      WHERE L10.PARENT_ID = :OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    )) THEN EXCEPTION DATA_ERROR 'В группе остались участники, нельзя удалить группу';

    SELECT DEL_COUNT FROM OBJECT_DEL(:I$STAGE_ID, :OBJ_ID) INTO :T;
  END

  IF(I$DELETE = 0) THEN
  BEGIN
    -- Сохраняем название
    IF(I$NAME <> S) THEN SELECT BLOB_ID FROM VAL_ADD(2162, :OBJ_ID, :I$NAME) INTO :T;
    -- Сохраняем новую маску
    IF(I$MASK <> V$MASK) THEN SELECT BLOB_ID FROM VAL_ADD(3062, :OBJ_ID, :I$MASK) INTO :T;
  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE VARGRP_GUP_ASSIGN (
    I$OBJ_ID BIGINT)
AS
declare variable V$REF_ID bigint;
declare variable V$GUP_ID bigint;
begin

  FOR
    SELECT DISTINCT LP256.PARENT_ID
    FROM LINKS L10
    JOIN LINKS LP256 ON LP256.OBJ_ID = L10.OBJ_ID AND LP256.PARENT_TYPE_ID = 256 AND LP256.DATE_DEL IS NULL
    WHERE L10.PARENT_ID = :I$OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    INTO :V$GUP_ID
  DO
  BEGIN
    IF(V$REF_ID IS NULL) THEN V$REF_ID = V$GUP_ID;
    ELSE IF(V$REF_ID <> V$GUP_ID) THEN V$REF_ID = -1;
  END

  IF(V$REF_ID = -1) THEN
    -- Удаляем ссылку, группа из учеников разных ГУП
    UPDATE VALR SET IS_DEL = 1 WHERE OBJ_ID = :I$OBJ_ID AND PARAM_ID = 3370 AND IS_DEL = 0;
  ELSE IF(V$REF_ID IS NOT NULL) THEN
    -- Добавляем или обновляем ссылку на моноГУП
    SELECT 1 FROM VAL_ADD(3370, :I$OBJ_ID, :V$REF_ID) INTO :V$GUP_ID;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE VARGRP_MOVE_PUPIL (
    I$PUPIL_ID BIGINT,
    I$GROUP_ID BIGINT,
    I$ORDER_NUM VARCHAR(100),
    I$ORDER_DATE DATE,
    I$ACTION_DATE DATE,
    I$ACTION_TYPE SMALLINT,
    I$USER_ID VARCHAR(40),
    I$ORDER_ID BIGINT = NULL,
    I$MOVE_TYPE BIGINT = NULL,
    I$MOVE_SOURCE BIGINT = 903)
RETURNS (
    OBJ_ID BIGINT)
AS
DECLARE VARIABLE V$OU_TYPE CHAR(1);
DECLARE VARIABLE V$YC SMALLINT;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$DATE DATE;
DECLARE VARIABLE V$GROUP_TYPE_ID BIGINT;
DECLARE VARIABLE V$TYPE_ID BIGINT;
DECLARE VARIABLE V$CAPTION VARCHAR(1000);
DECLARE VARIABLE TMP BIGINT;
DECLARE VARIABLE V$LINK_ID BIGINT;
DECLARE VARIABLE V$STAGE_ID BIGINT;
DECLARE VARIABLE V$GROUP_ID BIGINT;
DECLARE VARIABLE V$LAST_ID BIGINT;
DECLARE VARIABLE V$LEVEL_ID BIGINT;
DECLARE VARIABLE V$YEAR INTEGER;
DECLARE VARIABLE V$DX DATE;
DECLARE VARIABLE V$VD BIGINT;
DECLARE VARIABLE V$GT BIGINT;
DECLARE VARIABLE V$OUT_FOLDER BIGINT;
DECLARE VARIABLE V$OUT_TYPE BIGINT;
DECLARE VARIABLE V$OUT_LEVEL BIGINT;
DECLARE VARIABLE V$OUT BIGINT;
DECLARE VARIABLE V$SK BIGINT;
DECLARE VARIABLE V$ST BIGINT;
DECLARE VARIABLE DT1 DATE;
DECLARE VARIABLE DT2 DATE;
DECLARE VARIABLE V$LAST_STAGE_ID BIGINT;
DECLARE VARIABLE V$START_YEAR INTEGER;
DECLARE VARIABLE V$END_YEAR INTEGER;
DECLARE VARIABLE V$OLD_LINK BIGINT;
DECLARE VARIABLE V$HAS_ANY SMALLINT;
DECLARE VARIABLE V$DST_GROUP BIGINT;
DECLARE VARIABLE V$SY BIGINT;
DECLARE VARIABLE V$ORDER_ID BIGINT;
DECLARE VARIABLE V$OU_ID BIGINT;
DECLARE VARIABLE V$REASON_ID BIGINT;
DECLARE VARIABLE V$ORDER_DATE_IN DATE;
DECLARE VARIABLE V$ORDER_NUM_IN VARCHAR(100);
begin

  -- ACTION_TYPE смотри по коду 0, 1, 3, 4

  -- I$USER_ID с собакой в начале выставляется при переводе года

  V$YC = 0;
  IF(SUBSTRING(I$USER_ID FROM 1 FOR 1) = '@') THEN
  BEGIN
    I$USER_ID = SUBSTRING(I$USER_ID FROM 2);
    V$YC = 1;
  END

  V$OU_TYPE = (SELECT STATUS FROM OU_LICENCE_TYPE);
  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  I$ORDER_NUM = TRIM(I$ORDER_NUM);
  IF(I$ORDER_NUM = '') THEN I$ORDER_NUM = NULL;

  SELECT TYPE_ID FROM OBJECTS WHERE OBJ_ID = :I$GROUP_ID INTO :V$GROUP_TYPE_ID;
  IF(V$GROUP_TYPE_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Учебный коллектив не найден';

  IF(V$GROUP_TYPE_ID NOT IN (9, 187, 179, 256, 243, 347, 46, 289)) THEN
    EXCEPTION DATA_ERROR 'Системная ошибка. Недопустимый тип учебного коллектива (' || V$GROUP_TYPE_ID || '). Сообщите пожалуйста разработчикам.';

  V$TYPE_ID = NULL;
  SELECT TYPE_ID FROM OBJECTS WHERE OBJ_ID = :I$PUPIL_ID INTO :V$TYPE_ID;
  IF(V$TYPE_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Участник группы не найден';
  ELSE IF(V$TYPE_ID NOT IN (10, 14, 20)) THEN EXCEPTION DATA_ERROR 'Недопустимый тип участника группы';

  V$CAPTION = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$PUPIL_ID));

  -- Дата движения должна попадать в текущий учебный год
  -- Изменено: было разрешено с 20 августа до 10 сентября
  SELECT FIRST 1 LV.COST, L2.OBJ_ID
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$YEAR, :V$OU_ID;

  IF(V$YEAR IS NULL) THEN EXCEPTION DATA_ERROR 'Не задан текущий учебный год';
  IF(V$YC = 0 AND (I$ACTION_DATE < '01.09.' || V$YEAR OR I$ACTION_DATE > '31.08.' || (V$YEAR + 1))) THEN
    EXCEPTION DATA_ERROR 'Дата движения ' || I$ACTION_DATE || ' должна находиться в пределах текущего учебного года ' || V$YEAR;

  -- Нельзя выполнять любые движения при включении ученика в приказ по аттестатам
  IF(V$GROUP_TYPE_ID IN (9, 125, 187)) THEN
  BEGIN
    SELECT FIRST 1 D.OBJ_ID
    FROM ORDER_DATA OD
    JOIN ORDERS D ON D.DATE_DEL IS NULL AND D.OBJ_ID = OD.ORDER_ID AND D.TYPE_ID = 13326 AND D.STATE_ID = 11716
    WHERE OD.DATE_DEL IS NULL AND OD.REF_ID = :I$PUPIL_ID
    INTO :V$ORDER_ID;
    IF(V$ORDER_ID IS NOT NULL) THEN EXCEPTION DATA_ERROR 'Нельзя выполнять движение обучающихся, включенных в проекты приказов о печати аттестатов (' || V$CAPTION || ')';
  END

  -- Приход в группу
  IF(I$ACTION_TYPE = 0) THEN
  BEGIN

    IF(I$ACTION_DATE IS NULL) THEN EXCEPTION DATA_ERROR 'Не указана дата движения';

    SELECT FIRST 1 PM.OBJ_ID, PM.DATE_IN
    FROM PERSON_MOVEMENTS PM
    WHERE PM.DATE_DEL IS NULL AND PM.PERSON_ID = :I$PUPIL_ID AND PM.GROUP_ID = :I$GROUP_ID AND PM.DATE_OUT IS NULL
    INTO :V$OBJ_ID, :V$DATE;

    -- Если ученик уже тут (реквизиты приказа не сверяем) - ошибка только если дата зачисления отличается
    -- Исправление старых ошибок. При повторном отчислении, если осталось висеть незакрытое старое - закрываем его
    IF(V$OBJ_ID IS NOT NULL AND V$GROUP_TYPE_ID = 289) THEN
    BEGIN
      -- Пытаемся найти запись зачисления обратно, и достать из нее реквизиты
      SELECT FIRST 1 PM.DATE_IN, PM.REASON_IN, PM.ORDER_DATE_IN, PM.ORDER_NUM_IN
      FROM PERSON_MOVEMENTS PM
      WHERE PM.DATE_DEL IS NULL AND PM.PERSON_ID = :I$PUPIL_ID AND PM.GROUP_TYPE_ID = 9 AND PM.DATE_IN >= :V$DATE
      ORDER BY 1
      INTO :V$DX, :V$REASON_ID, :V$ORDER_DATE_IN, :V$ORDER_NUM_IN;

      IF(V$DX IS NOT NULL) THEN
      BEGIN
        UPDATE PERSON_MOVEMENTS
        SET DATE_OUT = :V$DX, REASON_OUT = :V$REASON_ID, ORDER_DATE_OUT = :V$ORDER_DATE_IN, ORDER_NUM_OUT = :V$ORDER_NUM_IN
        WHERE OBJ_ID = :V$OBJ_ID;
        V$OBJ_ID = NULL;
      END
    END

    IF(V$OBJ_ID IS NOT NULL) THEN
    BEGIN
      IF(V$DATE = I$ACTION_DATE) THEN EXIT;
      EXCEPTION DATA_ERROR 'Обучающийся ' || V$CAPTION || ' уже числится в группе, нельзя зачислить повторно';
    END

    -- Дата раньше даты выбытия ?
    -- для классов проверяем вообще все классы
    V$DX = NULL;
    SELECT FIRST 1 PM.DATE_OUT
    FROM PERSON_MOVEMENTS PM
    WHERE PM.DATE_DEL IS NULL AND PM.PERSON_ID = :I$PUPIL_ID AND (PM.GROUP_ID = :I$GROUP_ID OR :V$GROUP_TYPE_ID IN (9, 187, 289)) AND PM.DATE_OUT > :I$ACTION_DATE
    INTO :V$DX;
    IF(V$DX IS NOT NULL) THEN EXCEPTION DATA_ERROR 'Нельзя зачислить ' || V$CAPTION || ' в группу раньше, чем дата последнего выбытия из нее ' || (SELECT RESULT FROM DATE2STR(:V$DX));

    -- Только для учеников
    IF(V$GROUP_TYPE_ID NOT IN (9, 125, 187, 243, 46, 289) AND V$TYPE_ID = 10) THEN
    BEGIN
      -- Был ли ученик вообще в ОУ на указанную дату ?
      IF(NOT EXISTS(
        SELECT FIRST 1 1
        FROM PERSON_MOVEMENTS M
        JOIN OBJECTS O ON O.OBJ_ID = M.GROUP_ID AND O.TYPE_ID IN (9, 125, 187, 243)
        WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :I$PUPIL_ID AND M.DATE_IN <= :I$ACTION_DATE AND (M.DATE_OUT IS NULL OR M.DATE_OUT >= :I$ACTION_DATE)
      ))
      THEN
        EXCEPTION DATA_ERROR 'Ученика ' || V$CAPTION || ' нельзя принять в группу на дату, когда он не числился в ОУ';
    END

    -- Вычисляем текущий этап и тип по ОВЗ
    V$STAGE_ID = NULL;
    V$GT = NULL;
    IF(V$GROUP_TYPE_ID = 256) THEN
    BEGIN
      SELECT FIRST 1 V381.LISTVAL_ID, COALESCE(V3022.LISTVAL_ID, 3), LP400.PARENT_TYPE_ID --, V1594.LISTVAL_ID
      FROM LINKS LP54
      JOIN VALL V381 ON V381.OBJ_ID = LP54.PARENT_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
      JOIN LINKS LP400 ON LP400.OBJ_ID = LP54.PARENT_ID AND LP400.PARENT_TYPE_ID IN (50, 400) AND LP400.DATE_DEL IS NULL
      JOIN LINKS LP57 ON LP57.OBJ_ID = LP400.PARENT_ID AND LP57.PARENT_TYPE_ID = 57 AND LP57.DATE_DEL IS NULL
      LEFT JOIN VALL V3022 ON V3022.OBJ_ID = LP400.PARENT_ID AND V3022.PARAM_ID = IIF(LP400.PARENT_TYPE_ID = 50, 2545, 3022) AND V3022.IS_DEL = 0
      LEFT JOIN VALL V1594 ON V1594.OBJ_ID = LP57.PARENT_ID AND V1594.PARAM_ID = 1594 AND V1594.IS_DEL = 0
      WHERE LP54.OBJ_ID = :I$GROUP_ID AND LP54.PARENT_TYPE_ID = 54 AND LP54.DATE_DEL IS NULL
      INTO :V$STAGE_ID, :V$VD, :TMP; -- :V$LEVEL_ID

      IF(TMP = 50) THEN EXCEPTION DATA_ERROR 'Работа с УП старого образца более не выполняется. Прием обучающегося возможен только в ГУП УП нового типа';
      IF(V$VD = 3 OR V$VD IS NULL) THEN V$VD = 0; ELSE V$VD = 1;

      IF(V$STAGE_ID IN (37, 38, 39, 40, 12942, 12950)) THEN V$LEVEL_ID = 22;
      ELSE IF(V$STAGE_ID IN (41, 42, 43, 44, 45, 12951, 12960)) THEN V$LEVEL_ID = 26;
      ELSE IF(V$STAGE_ID IN (46, 47, 48, 12961)) THEN V$LEVEL_ID = 27;
      ELSE IF(V$STAGE_ID IN (30, 31, 32, 33, 3261)) THEN V$LEVEL_ID = 3263;
      ELSE IF(V$STAGE_ID IN (34, 35, 36, 3262)) THEN V$LEVEL_ID = 3264;
      ELSE IF(V$STAGE_ID IN (49, 50, 51, 52, 53, 54)) THEN V$LEVEL_ID = 29;
      ELSE V$LEVEL_ID = NULL;

      IF(V$VD = 0) THEN
      BEGIN
        -- Для общеобра требуем, чтобы дата последнего движения в другой ГУП была не раньше указанного
        IF(EXISTS(
          SELECT FIRST 1 1
          FROM PERSON_MOVEMENTS M
          JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 256
          WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :I$PUPIL_ID AND M.DATE_OUT IS NULL AND M.IS_VD = 0
        ))
        THEN
          EXCEPTION DATA_ERROR 'Ученик ' || V$CAPTION || ' числится в другой ГУП, нельзя зачислить';

        V$DATE = NULL;
        SELECT FIRST 1 M.DATE_OUT
        FROM PERSON_MOVEMENTS M
        JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID = 256
        WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :I$PUPIL_ID AND M.IS_VD = 0
        INTO :V$DATE;

        IF(I$ACTION_DATE < V$DATE) THEN EXCEPTION DATA_ERROR 'Ученик ' || V$CAPTION || ' был отчислен из другой ГУП ' || V$DATE || ', нельзя принять более ранней датой';
      END
    END
    ELSE IF(V$GROUP_TYPE_ID IN (9, 187)) THEN
    BEGIN
      SELECT V49.LISTVAL_ID, V592.LISTVAL_ID, V43.LISTVAL_ID
      FROM LINKS LP8
      JOIN VALL V49 ON V49.OBJ_ID = LP8.PARENT_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
      JOIN LINKS LP7 ON LP7.OBJ_ID = LP8.PARENT_ID AND LP7.PARENT_TYPE_ID = 7 AND LP7.DATE_DEL IS NULL
      JOIN VALL V43 ON V43.OBJ_ID = LP7.PARENT_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0
      LEFT JOIN VALL V592 ON V592.OBJ_ID = LP8.OBJ_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0
      WHERE LP8.OBJ_ID = :I$GROUP_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
      INTO :V$STAGE_ID, :V$GT, :V$LEVEL_ID;

      IF(V$STAGE_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не удалось определить этап обучения';
    END
    ELSE IF(V$GROUP_TYPE_ID = 243) THEN
    BEGIN
      SELECT V2114.LISTVAL_ID
      FROM VALL V2114
      WHERE V2114.OBJ_ID = :I$GROUP_ID AND V2114.PARAM_ID = 2114 AND V2114.IS_DEL = 0
      INTO :V$STAGE_ID;
    END
    ELSE IF(V$GROUP_TYPE_ID = 179) THEN
    BEGIN
      -- Смотрим по тому, в каком уровне ученик - выборка по CJ2_JOURNAL не работает
      /* SELECT FIRST 1 J.STAGE_INDEX
      FROM CJ2_JOURNAL J
      WHERE J.GRADE_ID = :I$GROUP_ID
      INTO :V$STAGE_ID;

      IF(V$STAGE_ID IN (37, 38, 39, 40, 12942, 12950)) THEN V$LEVEL_ID = 22;
      ELSE IF(V$STAGE_ID IN (41, 42, 43, 44, 45, 12951, 12960)) THEN V$LEVEL_ID = 26;
      ELSE IF(V$STAGE_ID IN (46, 47, 48, 12961)) THEN V$LEVEL_ID = 27;
      ELSE IF(V$STAGE_ID IN (30, 31, 32, 33, 3261)) THEN V$LEVEL_ID = 3263;
      ELSE IF(V$STAGE_ID IN (34, 35, 36, 3262)) THEN V$LEVEL_ID = 3264;
      ELSE IF(V$STAGE_ID IN (49, 50, 51, 52, 53, 54)) THEN V$LEVEL_ID = 29;
      ELSE V$LEVEL_ID = NULL; */

      SELECT V49.LISTVAL_ID, V43.LISTVAL_ID
      FROM LINKS LP9
      JOIN LINKS LP8 ON LP8.OBJ_ID = LP9.PARENT_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
      JOIN VALL V49 ON V49.OBJ_ID = LP8.PARENT_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
      JOIN LINKS LP7 ON LP7.OBJ_ID = LP8.PARENT_ID AND LP7.PARENT_TYPE_ID = 7 AND LP7.DATE_DEL IS NULL
      JOIN VALL V43 ON V43.OBJ_ID = LP7.PARENT_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0
      LEFT JOIN VALL V592 ON V592.OBJ_ID = LP8.OBJ_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0
      WHERE LP9.OBJ_ID = :I$PUPIL_ID AND LP9.PARENT_TYPE_ID = 9 AND LP9.DATE_DEL IS NULL
      INTO :V$STAGE_ID, :V$LEVEL_ID;
    END
    ELSE IF(V$GROUP_TYPE_ID = 289) THEN
    BEGIN
      -- Академический отпуск - нужно добыть текущий этап обучения обучающегося из предыдущей записи движения
      -- которая уже закрыта, поэтому ищем из удаленных самую свежую запись
      SELECT FIRST 1 V49.LISTVAL_ID, V43.LISTVAL_ID
      FROM LINKS LP9
      JOIN LINKS LP8 ON LP8.OBJ_ID = LP9.PARENT_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
      JOIN VALL V49 ON V49.OBJ_ID = LP8.PARENT_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
      JOIN LINKS LP7 ON LP7.OBJ_ID = LP8.PARENT_ID AND LP7.PARENT_TYPE_ID = 7 AND LP7.DATE_DEL IS NULL
      JOIN VALL V43 ON V43.OBJ_ID = LP7.PARENT_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0
      WHERE LP9.OBJ_ID = :I$PUPIL_ID AND LP9.PARENT_TYPE_ID = 9 -- запись уже удалена
      ORDER BY LP9.DATE_DEL DESC
      INTO :V$STAGE_ID, :V$LEVEL_ID;

      IF(V$STAGE_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не удалось определить этап обучения';
    END

    V$CAPTION = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$GROUP_ID));
    -- Заменяем слова про будущий всегда, хотя по идее надо это делать только при переводе года
    V$CAPTION = REPLACE(V$CAPTION, 'будущий ', '');

    -- Год обучения подставляем только при зачислении в класс, в прочих случаях будет NULL
    IF(V$GROUP_TYPE_ID = 9) THEN
    BEGIN
      SELECT FIRST 1 V3024.LISTVAL_ID
      FROM VALL V3024
      JOIN VALL V592 ON V592.OBJ_ID = V3024.OBJ_ID AND V592.PARAM_ID = 592 AND V592.IS_DEL = 0 AND V592.LISTVAL_ID = 13275
      WHERE V3024.OBJ_ID = :I$GROUP_ID AND V3024.PARAM_ID = 3024 AND V3024.IS_DEL = 0
      INTO :V$SY;

      IF(V$SY = 12938) THEN V$SY = 1;
      ELSE IF(V$SY = 12939) THEN V$SY = 2;
      ELSE V$SY = NULL;

      -- Запрещаем принимать в класс, если уже есть в экстернате (если кнопками пропихнули мимо блокировок)
      IF(EXISTS(
        SELECT FIRST 1 1
        FROM LINKS LP187
        WHERE LP187.OBJ_ID = :I$PUPIL_ID AND LP187.PARENT_TYPE_ID = 187 AND LP187.DATE_DEL IS NULL
      ))
      THEN EXCEPTION DATA_ERROR 'Обучающийся уже числится в классе-экстернате';

      -- Для СПО требуем чтобы был указан код специальности
      IF(V$OU_TYPE = 'C') THEN
      BEGIN
        IF(NOT EXISTS(
          SELECT FIRST 1 1
          FROM VALS V
          WHERE V.OBJ_ID = :I$GROUP_ID AND V.PARAM_ID = 2822 AND V.IS_DEL = 0
        ))
        THEN
          EXCEPTION DATA_ERROR 'При зачислении в группу СПО должен быть указан код специальности в группе';
      END
    END

    INSERT INTO PERSON_MOVEMENTS
    (PERSON_ID, GROUP_ID, GROUP_TYPE_ID, REASON_IN, DATE_IN, ORDER_DATE_IN, ORDER_NUM_IN, ORDER_ID_IN, NAME_IN, STAGE_ID, TYPE_IN, USER_IN,
      IS_VD, SOURCE_IN, STAGE_YEAR, LEVEL_ID, OU_ID)
    VALUES (:I$PUPIL_ID, :I$GROUP_ID, :V$GROUP_TYPE_ID, :I$MOVE_TYPE, :I$ACTION_DATE, :I$ORDER_DATE, :I$ORDER_NUM, :I$ORDER_ID, :V$CAPTION, :V$STAGE_ID, :V$GT, :I$USER_ID,
      COALESCE(:V$VD, 0), :I$MOVE_SOURCE, :V$SY, :V$LEVEL_ID, :V$OU_ID)
    RETURNING OBJ_ID INTO :OBJ_ID;

    SELECT LINK_ID FROM OBJECT_ADD_LINK(:I$GROUP_ID, :I$PUPIL_ID, :V$TYPE_ID) INTO :TMP;

    -- Зачисление в класс или академический отпуск
    IF(V$GROUP_TYPE_ID IN (9, 289)) THEN
    BEGIN

      -- Корректируем тип и форму обучения, если вернулся из экстерната (не проверяем только что созданную связь)
      SELECT FIRST 1 LPG.PARENT_TYPE_ID
      FROM LINKS LPG
      WHERE LPG.OBJ_ID = :I$PUPIL_ID AND LPG.PARENT_TYPE_ID IN (9, 125, 187) AND LPG.LINK_ID <> :TMP
      ORDER BY LPG.DATE_MODIFY DESC
      INTO :V$LAST_ID;

      IF(V$LAST_ID = 187) THEN
      BEGIN
        SELECT BLOB_ID FROM VAL_ADD(78, :I$PUPIL_ID, 11201) INTO :TMP;
        IF(V$OU_TYPE IN ('O', 'S')) THEN SELECT BLOB_ID FROM VAL_ADD(80, :I$PUPIL_ID, 5418) INTO :TMP;
      END

      -- Копируем выбор ГИА из старого класса при переносе через приказ, а не кнопкой
      -- !!!

      -- Убираем из выбывших/окончивших, если ученик там был
      SELECT FIRST 1 LP8X.LINK_ID
      FROM LINKS LP8X
      WHERE LP8X.OBJ_ID = :I$PUPIL_ID AND LP8X.PARENT_TYPE_ID IN (81, 82, 83) AND LP8X.DATE_DEL IS NULL
      INTO :V$OLD_LINK;

      IF(V$OLD_LINK IS NOT NULL) THEN
      UPDATE LINKS
      SET DATE_DEL = CURRENT_TIMESTAMP
      WHERE LINK_ID = :V$OLD_LINK;

      -- При зачислении в учебную группу - убираем из академического отпуска, и фиксируем реквизиты выбытия
      IF(V$GROUP_TYPE_ID = 9) THEN
      BEGIN
        V$OLD_LINK = NULL;
        SELECT FIRST 1 LP289.LINK_ID
        FROM LINKS LP289
        WHERE LP289.OBJ_ID = :I$PUPIL_ID AND LP289.PARENT_TYPE_ID = 289 AND LP289.DATE_DEL IS NULL
        INTO :V$OLD_LINK;

        IF(V$OLD_LINK IS NOT NULL) THEN
        UPDATE LINKS
        SET DATE_DEL = CURRENT_TIMESTAMP
        WHERE LINK_ID = :V$OLD_LINK;

        V$OBJ_ID = NULL;
        SELECT FIRST 1 PM.OBJ_ID
        FROM PERSON_MOVEMENTS PM
        WHERE PM.DATE_DEL IS NULL AND PM.PERSON_ID = :I$PUPIL_ID AND PM.GROUP_TYPE_ID = 289 AND PM.DATE_OUT IS NULL
        ORDER BY 1
        INTO :V$OBJ_ID;

        IF(V$OBJ_ID IS NOT NULL) THEN
        UPDATE PERSON_MOVEMENTS
        SET DATE_OUT = :I$ACTION_DATE, REASON_OUT = :I$MOVE_TYPE, ORDER_DATE_OUT = :I$ORDER_DATE, ORDER_NUM_OUT = :I$ORDER_NUM
        WHERE OBJ_ID = :V$OBJ_ID;

        EXECUTE PROCEDURE CLASS_OVZ_RECALC(NULL, :I$GROUP_ID);
      END

    END
    -- Зачисление в экстернат
    ELSE IF(V$GROUP_TYPE_ID = 187) THEN
    BEGIN
      -- Корректируем тип обучения
      IF(V$STAGE_ID IN (12765, 37, 38, 39, 40, 41, 42, 43, 44, 45)) THEN
      BEGIN
        -- 1-9 классы, семейное обучение
        SELECT BLOB_ID FROM VAL_ADD(80, :I$PUPIL_ID, 5422) INTO :TMP;
      END
      ELSE
      BEGIN
        -- 10-12, самообразование
        SELECT BLOB_ID FROM VAL_ADD(80, :I$PUPIL_ID, 5423) INTO :TMP;
      END
    END

    -- Если ученик числится в предварительном приеме - убираем его оттуда
    -- То же делаем, если ученик числится в выбывших, но только если он не принимается в класс-экстернат
    -- !!! возможно в случае с ЦОПП и ДПО для групп 46 тоже надо удалять
    V$LINK_ID = NULL;
    SELECT FIRST 1 LPG.LINK_ID
    FROM LINKS LPG
    WHERE LPG.OBJ_ID = :I$PUPIL_ID AND (LPG.PARENT_TYPE_ID = 290 OR (:V$GROUP_TYPE_ID <> 187 AND :V$GROUP_TYPE_ID <> 46 AND LPG.PARENT_TYPE_ID IN (81, 82, 83))) AND LPG.DATE_DEL IS NULL
    INTO :V$LINK_ID;

    IF(V$LINK_ID IS NOT NULL) THEN
    BEGIN
      UPDATE LINKS SET DATE_DEL = CURRENT_TIMESTAMP WHERE LINK_ID = :V$LINK_ID;
    END

    -- Если ученик из класса/группы ЦОПП - отмечаем новую группу как ЦОПП
    IF(EXISTS(
      SELECT FIRST 1 1
      FROM LINKS LP9
      JOIN VALL V3063 ON V3063.OBJ_ID = LP9.PARENT_ID AND V3063.PARAM_ID = 3063 AND V3063.IS_DEL = 0 AND V3063.LISTVAL_ID = 2
      WHERE LP9.OBJ_ID = :I$PUPIL_ID AND LP9.PARENT_TYPE_ID = 9 AND LP9.DATE_DEL IS NULL
    )) THEN
    BEGIN
      TMP = (SELECT I FROM VAL_GET(:I$GROUP_ID, 3064));
      IF(TMP IS NULL OR TMP = 3) THEN
      BEGIN
        SELECT BLOB_ID FROM VAL_ADD(3064, :I$GROUP_ID, 2) INTO :TMP;
      END
    END

    -- Если зачислен в ГУП, связанную с ГПП, то зачисляем по все связанные ГПП
    -- дополнение: куда он еще не зачислен
    IF(V$GROUP_TYPE_ID = 256) THEN
    BEGIN
      FOR
        SELECT L179.OBJ_ID
        FROM LINKS L179
        LEFT JOIN LINKS L10 ON L10.PARENT_ID = L179.OBJ_ID AND L10.OBJ_ID = :I$PUPIL_ID AND L10.DATE_DEL IS NULL
        WHERE L179.PARENT_TYPE_ID = 2 AND L179.OBJ_TYPE_ID = 179 AND L179.DATE_DEL IS NULL AND L179.EXT_OBJ_ID = :I$GROUP_ID AND L10.LINK_ID IS NULL
        INTO :V$GROUP_ID
      DO
      BEGIN
        SELECT OBJ_ID FROM VARGRP_MOVE_PUPIL(:I$PUPIL_ID, :V$GROUP_ID, :I$ORDER_NUM, :I$ORDER_DATE, :I$ACTION_DATE, 0, IIF(:V$YC = 0, '', '@') || :I$USER_ID, :I$ORDER_ID, :I$MOVE_TYPE, 902) INTO :TMP;
      END

      -- Обновляем счетчик этапов УП в записи движения
      FOR
        SELECT M.OBJ_ID
        FROM PERSON_MOVEMENTS M
        JOIN OBJECTS G ON G.OBJ_ID = M.GROUP_ID AND G.TYPE_ID IN (9, 187)
        WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :I$PUPIL_ID AND M.DATE_OUT IS NULL
        ORDER BY 1
        INTO :V$OBJ_ID
      DO
      BEGIN
        UPDATE PERSON_MOVEMENTS
        SET PLAN_STAGES = (
          SELECT COUNT(*)
          FROM LINKS LP54
          JOIN LINKS LP400 ON LP400.OBJ_ID = LP54.PARENT_ID AND LP400.PARENT_TYPE_ID = 400 AND LP400.DATE_DEL IS NULL
          JOIN LINKS L54 ON L54.PARENT_ID = LP400.PARENT_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
          WHERE LP54.OBJ_ID = :I$GROUP_ID AND LP54.PARENT_TYPE_ID = 54 AND LP54.DATE_DEL IS NULL
        )
        WHERE OBJ_ID = :V$OBJ_ID;
      END
    END

  END
  -- Выбытие
  ELSE IF(I$ACTION_TYPE = 1) THEN
  BEGIN

    IF(I$ACTION_DATE IS NULL) THEN EXCEPTION DATA_ERROR 'Не указана дата движения';

    -- А был ли ученик ?
    SELECT FIRST 1 PM.OBJ_ID, PM.DATE_IN
    FROM PERSON_MOVEMENTS PM
    WHERE PM.DATE_DEL IS NULL AND PM.PERSON_ID = :I$PUPIL_ID AND PM.GROUP_ID = :I$GROUP_ID AND PM.DATE_OUT IS NULL
    INTO :V$OBJ_ID, :V$DATE;

    -- Если ученик в академке вовсе без записей движения, генерируем липу
    IF(V$OBJ_ID IS NULL AND V$GROUP_TYPE_ID = 289) THEN
    BEGIN
      V$DATE = DATEADD(-1 DAY TO :I$ACTION_DATE);

      INSERT INTO PERSON_MOVEMENTS
      (PERSON_ID, GROUP_ID, GROUP_TYPE_ID, REASON_IN, DATE_IN, NAME_IN, LEVEL_ID, OU_ID)
      VALUES (:I$PUPIL_ID, :I$GROUP_ID, :V$GROUP_TYPE_ID, 5319, :V$DATE, 'Академический отпуск', 29, :V$OU_ID)
      RETURNING OBJ_ID INTO :V$OBJ_ID;
    END

    IF(V$OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не найдена запись движения учащегося ' || V$CAPTION || ' в группе ' ||
      (SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$GROUP_ID)) || ', тип ' || V$GROUP_TYPE_ID || ', id ' || I$GROUP_ID;

    -- Временно заткнули ошибку
    IF(V$YC = 0 AND V$DATE > I$ACTION_DATE) THEN EXCEPTION DATA_ERROR 'Нельзя выполнить выбытие учащегося ' || V$CAPTION || ' раньше даты зачисления в группу (' ||
      (SELECT RESULT FROM DATE2STR(:I$ACTION_DATE)) || ' vs ' ||
      (SELECT RESULT FROM DATE2STR(:V$DATE)) || ')';

    -- В ГУП должна быть дата + 1 день
    IF(V$GROUP_TYPE_ID = 256) THEN
    BEGIN
      IF(V$DATE = I$ACTION_DATE) THEN EXCEPTION DATA_ERROR 'Нельзя выполнить выбытие учащегося ' || V$CAPTION || ' из ГУП той же датой, что и зачисление';
    END

    -- Для СПО требуем чтобы был указан код специальности
    -- Изменение: не именно СПО, а уровень образования СПО !!!
    IF(V$GROUP_TYPE_ID = 9 AND V$OU_TYPE = 'C') THEN
    BEGIN
      IF(NOT EXISTS(
        SELECT FIRST 1 1
        FROM VALS V
        WHERE V.OBJ_ID = :I$GROUP_ID AND V.PARAM_ID = 2822 AND V.IS_DEL = 0
      ))
      THEN
        EXCEPTION DATA_ERROR 'В группе СПО должен быть указан код специальности';
    END

    -- Фиксируем выбытие ученика из ГУП, потоков, ГПД и ДО
    -- для потоков 347 это последний оставшийся старый хвост, после лета 2021 будет неактуально
    -- !!! прибить подгруппы !!!
    IF(V$GROUP_TYPE_ID IN (9, 125, 187, 243, 289) OR (V$OU_TYPE = 'P' AND V$GROUP_TYPE_ID = 46)) THEN
    BEGIN
      FOR
        SELECT LPG.PARENT_ID
        FROM LINKS LPG
        WHERE LPG.OBJ_ID = :I$PUPIL_ID AND LPG.PARENT_TYPE_ID IN (46, 256, 347) AND LPG.DATE_DEL IS NULL AND :V$OU_TYPE <> 'P'
        INTO :V$GROUP_ID
      DO
      BEGIN
        SELECT OBJ_ID FROM VARGRP_MOVE_PUPIL(:I$PUPIL_ID, :V$GROUP_ID, :I$ORDER_NUM, :I$ORDER_DATE, :I$ACTION_DATE, 1, IIF(:V$YC = 0, '', '@') || :I$USER_ID, :I$ORDER_ID, :I$MOVE_TYPE, 902) INTO :TMP;
      END
      -- Удаляем ученика из групп переменного состава, где он еще остался
      FOR
        SELECT LPG.PARENT_ID
        FROM LINKS LPG
        WHERE LPG.OBJ_ID = :I$PUPIL_ID AND LPG.PARENT_TYPE_ID = 179 AND LPG.DATE_DEL IS NULL
        INTO :V$GROUP_ID
      DO
      BEGIN
        SELECT OBJ_ID FROM VARGRP_MOVE_PUPIL(:I$PUPIL_ID, :V$GROUP_ID, :I$ORDER_NUM, :I$ORDER_DATE, :I$ACTION_DATE, 1, IIF(:V$YC = 0, '', '@') || :I$USER_ID, :I$ORDER_ID, :I$MOVE_TYPE, 902) INTO :TMP;
      END

      -- Переносим ученика в папку выбывших нужного типа (в случае экстерната ученик по идее и так может быть там)
      -- кроме случая УДОД, когда ученик еще остался в других группах
      IF(V$TYPE_ID = 10 AND (V$GROUP_TYPE_ID <> 243 OR NOT EXISTS(
        SELECT FIRST 1 1 FROM LINKS LPG WHERE LPG.OBJ_ID = :I$PUPIL_ID AND LPG.PARENT_TYPE_ID = 243 AND LPG.DATE_DEL IS NULL
      ))) THEN
      BEGIN

        SELECT FIRST 1 L78.OBJ_ID, V10.LISTVAL_ID, V11.LISTVAL_ID
        FROM LINKS L2
        LEFT JOIN VALL V10 ON V10.OBJ_ID = L2.OBJ_ID AND V10.PARAM_ID = 10 AND V10.IS_DEL = 0
        LEFT JOIN VALL V11 ON V11.OBJ_ID = L2.OBJ_ID AND V11.PARAM_ID = 11 AND V11.IS_DEL = 0
        JOIN LINKS L78 ON L78.PARENT_ID = L2.OBJ_ID AND L78.OBJ_TYPE_ID = 78 AND L78.DATE_DEL IS NULL
        WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
        INTO :V$OUT_FOLDER, :V$SK, :V$ST;

        IF(V$OUT_FOLDER IS NULL) THEN EXCEPTION DATA_ERROR 'Папка выбывших не найдена';

        -- Смотрим, это у нас окончание или выпуск
        SELECT FIRST 1 V49.LISTVAL_ID
        FROM LINKS LP8
        JOIN VALL V49 ON V49.OBJ_ID = LP8.PARENT_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
        WHERE LP8.OBJ_ID = :I$GROUP_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
        UNION
        SELECT FIRST 1 V2114.LISTVAL_ID
        FROM VALL V2114
        WHERE V2114.OBJ_ID = :I$GROUP_ID AND V2114.PARAM_ID = 2114 AND V2114.IS_DEL = 0
        INTO :V$STAGE_ID;

        DT1 = EXTRACT(YEAR FROM :I$ACTION_DATE) || '-05-31';
        DT2 = EXTRACT(YEAR FROM :I$ACTION_DATE) || '-09-01';

        IF(EXTRACT(MONTH FROM I$ACTION_DATE) > 8) THEN
        BEGIN
          V$START_YEAR = EXTRACT(YEAR FROM I$ACTION_DATE);
          V$END_YEAR = V$START_YEAR + 1;
        END
        ELSE
        BEGIN
          V$END_YEAR = EXTRACT(YEAR FROM I$ACTION_DATE);
          V$START_YEAR = V$END_YEAR - 1;
        END

        -- Самый старший этап обучения
        SELECT FIRST 1 LV.LISTVAL_ID
        FROM LINKS L2
        JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
        JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
        JOIN LISTVALS LV ON LV.IS_REPL = V49.LISTVAL_ID
        WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
        ORDER BY LV.COST DESC
        INTO :V$LAST_STAGE_ID;

        -- Фильтр по датам убран 07.03.2023
        IF(/*I$ACTION_DATE > DT1 AND I$ACTION_DATE < DT2 AND*/ I$MOVE_TYPE = 812 AND V$STAGE_ID = 40 AND ((V$ST = 954) OR (V$SK IN (961, 2213)) OR (V$LAST_STAGE_ID = 40))) THEN
        BEGIN
          -- Каталог = окончившие, начальная школа
          V$OUT_TYPE = 81;
          V$OUT_LEVEL = 22;
        END
        ELSE IF(/*I$ACTION_DATE > DT1 AND I$ACTION_DATE < DT2 AND*/ I$MOVE_TYPE = 812 AND V$STAGE_ID = 45 AND V$SK IN (962, 2214)) THEN
        BEGIN
          -- Каталог = окончившие, основная школа
          V$OUT_TYPE = 81;
          V$OUT_LEVEL = 26;
        END
        ELSE IF(/*I$ACTION_DATE > DT1 AND I$ACTION_DATE < DT2 AND*/ I$MOVE_TYPE = 812 AND
          ((V$STAGE_ID IN (46, 47, 48))) OR (V$ST = 978 AND (V$STAGE_ID IN (40, 45, 46, 47, 48)) AND I$MOVE_SOURCE = 901)) THEN
        BEGIN
          -- Просто выпуск, уровень тут не указывается
          V$OUT_TYPE = 83;
          V$START_YEAR = NULL;
        END
        ELSE IF (/*I$ACTION_DATE > DT1 AND I$ACTION_DATE < DT2 AND*/ I$MOVE_TYPE = 812 AND
          -- первая младшая также считается как выпуск, если в ДОУ только ясельный уровень
          (V$STAGE_ID IN (33, 35, 36, 3262) OR (V$STAGE_ID = 32 AND V$LAST_STAGE_ID IN (32, 33)))) THEN
        BEGIN
          -- Выпуск ДОУ
          V$OUT_TYPE = 83;
          V$OUT_LEVEL = 3320;
          V$START_YEAR = NULL;
        END
        ELSE IF (V$STAGE_ID IN (30, 31, 32, 33, 3261, 34, 35, 36, 3262)) THEN
        BEGIN
          -- Каталог = выбывшие ДОУ
          V$OUT_TYPE = 82;
          V$OUT_LEVEL = 3321;
        END
        ELSE IF (I$MOVE_TYPE = 5319) THEN
        BEGIN
          -- Академический отпуск, эта ветка заглушена. Обработка выбытия в академический отпуск только вызовом PARAGRAF_EDUCATION_LEAVE в два шага
          /*SELECT FIRST 1 L289.OBJ_ID, LP7.PARENT_ID
          FROM LINKS LP8
          JOIN LINKS LP7 ON LP7.OBJ_ID = LP8.PARENT_ID AND LP7.PARENT_TYPE_ID = 7 AND LP7.DATE_DEL IS NULL
          LEFT JOIN LINKS L289 ON L289.PARENT_ID = LP7.PARENT_ID AND L289.OBJ_TYPE_ID = 289 AND L289.DATE_DEL IS NULL
          WHERE LP8.OBJ_ID = :I$GROUP_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
          INTO :V$OUT, :V$OUT_FOLDER;

          IF (V$OUT IS NULL) THEN
          BEGIN
            IF(V$OUT_FOLDER IS NULL) THEN EXCEPTION DATA_ERROR 'Для Профобучения академический отпуск не предусмотрен';
            SELECT OBJ_ID FROM OBJECT_ADD(:V$OUT_FOLDER, 289) INTO :V$OUT;
            SELECT BLOB_ID FROM VAL_ADD(2342, :V$OUT, (SELECT VAL FROM RES_GET((SELECT RES_ID FROM TYPES WHERE TYPE_ID = 289), 'BY')), IIF(:V$YC = 0, '', '@') || :I$USER_ID) INTO :TMP;
          END*/
        END
        ELSE IF(I$MOVE_TYPE = 812 AND V$OU_TYPE = 'C') THEN
        BEGIN
          -- Колледжи - выпуск
          V$OUT_TYPE = 83;
          V$START_YEAR = NULL;
        END
        ELSE
        BEGIN
          -- Выбывшие
          V$OUT_TYPE = 82;
        END

        IF(I$MOVE_TYPE <> 5319) THEN
        BEGIN
          -- Академотпуск тут уже обработан
          SELECT FIRST 1 L.OBJ_ID
          FROM LINKS L
          LEFT JOIN VALL V443 ON V443.OBJ_ID = L.OBJ_ID AND V443.PARAM_ID IN (443, 447, 450) AND V443.IS_DEL = 0 -- тип, уровень
          LEFT JOIN VALI V444 ON V444.OBJ_ID = L.OBJ_ID AND V444.PARAM_ID IN (444, 448) AND V444.IS_DEL = 0 -- год начала
          LEFT JOIN VALI V445 ON V445.OBJ_ID = L.OBJ_ID AND V445.PARAM_ID IN (445, 449, 451) AND V445.IS_DEL = 0 -- год окончания или выпуска
          WHERE L.PARENT_ID = :V$OUT_FOLDER AND L.OBJ_TYPE_ID = :V$OUT_TYPE AND L.DATE_DEL IS NULL
            AND (:V$OUT_LEVEL IS NULL OR V443.LISTVAL_ID = :V$OUT_LEVEL)
            AND (:V$START_YEAR IS NULL OR V444.VAL = :V$START_YEAR)
            AND (:V$END_YEAR IS NULL OR V445.VAL = :V$END_YEAR)
          INTO :V$OUT;

          IF(V$OUT IS NULL) THEN
          BEGIN
            SELECT OBJ_ID FROM OBJECT_ADD(:V$OUT_FOLDER, :V$OUT_TYPE) INTO :V$OUT;
            IF(V$OUT_LEVEL IS NOT NULL) THEN SELECT BLOB_ID FROM VAL_ADD(CASE :V$OUT_TYPE WHEN 81 THEN 443 WHEN 82 THEN 447 ELSE 450 END, :V$OUT, :V$OUT_LEVEL) INTO :TMP;
            IF(V$START_YEAR IS NOT NULL AND V$OUT_TYPE <> 83) THEN SELECT BLOB_ID FROM VAL_ADD(CASE :V$OUT_TYPE WHEN 81 THEN 444 ELSE 448 END, :V$OUT, :V$START_YEAR) INTO :TMP;
            IF(V$END_YEAR IS NOT NULL) THEN SELECT BLOB_ID FROM VAL_ADD(CASE :V$OUT_TYPE WHEN 81 THEN 445 WHEN 82 THEN 449 ELSE 451 END, :V$OUT, :V$END_YEAR) INTO :TMP;
          END
        END

        V$LINK_ID = NULL;
        SELECT FIRST 1 LPG.LINK_ID
        FROM LINKS LPG
        WHERE LPG.OBJ_ID = :I$PUPIL_ID AND LPG.PARENT_ID = :V$OUT AND LPG.DATE_DEL IS NULL
        INTO :V$LINK_ID;

        IF(V$OUT IS NOT NULL AND V$LINK_ID IS NULL) THEN
        BEGIN
          SELECT LINK_ID FROM OBJECT_ADD_LINK(:V$OUT, :I$PUPIL_ID, 10) INTO :TMP;
        END

        -- Закрываем дистант
        SELECT FIRST 1 OBJ_ID
        FROM OBJECTS
        WHERE TYPE_ID = 338
        INTO :V$DST_GROUP;

        -- Найдем адаптированность ОП, к которой относится УП, по которому училась группа
        SELECT V2379.LISTVAL_ID
        FROM VALR V3075
        JOIN LINKS LP57 ON LP57.OBJ_ID = V3075.VAL AND LP57.PARENT_TYPE_ID = 57 AND LP57.DATE_DEL IS NULL
        JOIN VALL V2379 ON V2379.OBJ_ID = LP57.PARENT_ID AND V2379.PARAM_ID = 2379 AND V2379.IS_DEL = 0
        WHERE V3075.OBJ_ID = :I$GROUP_ID AND V3075.PARAM_ID = 3075 AND V3075.IS_DEL = 0
        INTO :V$TYPE_ID;

        UPDATE PERSON_MOVEMENTS
        SET DATE_OUT = :I$ACTION_DATE,
            ADAPT_ID = :V$TYPE_ID
        WHERE DATE_DEL IS NULL AND PERSON_ID = :I$PUPIL_ID AND GROUP_ID = :V$DST_GROUP AND DATE_OUT IS NULL;
      END
    END
    -- Отчисляем из всех ГПП, связанных с ГУП, где ученик все еще есть
    ELSE IF(V$GROUP_TYPE_ID = 256) THEN
    BEGIN
      FOR
        SELECT L179.OBJ_ID
        FROM LINKS L179
        JOIN LINKS L10 ON L10.PARENT_ID = L179.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL AND L10.OBJ_ID = :I$PUPIL_ID
        WHERE L179.PARENT_TYPE_ID = 2 AND L179.OBJ_TYPE_ID = 179 AND L179.DATE_DEL IS NULL AND L179.EXT_OBJ_ID = :I$GROUP_ID
        INTO :V$GROUP_ID
      DO
      BEGIN
        SELECT OBJ_ID FROM VARGRP_MOVE_PUPIL(:I$PUPIL_ID, :V$GROUP_ID, :I$ORDER_NUM, :I$ORDER_DATE, :I$ACTION_DATE, 1, IIF(:V$YC = 0, '', '@') || :I$USER_ID, :I$ORDER_ID, :I$MOVE_TYPE, 902) INTO :TMP;
      END
    END

    -- Вносим данные
    UPDATE PERSON_MOVEMENTS PM
    SET PM.DATE_MODIFY = CURRENT_TIMESTAMP, PM.DATE_OUT = :I$ACTION_DATE, PM.ORDER_DATE_OUT = :I$ORDER_DATE, PM.ORDER_NUM_OUT = :I$ORDER_NUM, PM.ORDER_ID_OUT = :I$ORDER_ID,
      PM.USER_OUT = :I$USER_ID, PM.REASON_OUT = :I$MOVE_TYPE, PM.SOURCE_OUT = :I$MOVE_SOURCE
    WHERE PM.OBJ_ID = :V$OBJ_ID;

    -- Удаляем связь ученика с группой
    UPDATE LINKS L
    SET L.DATE_DEL = CURRENT_TIMESTAMP
    WHERE L.PARENT_ID = :I$GROUP_ID AND L.OBJ_ID = :I$PUPIL_ID AND L.DATE_DEL IS NULL;

    IF(V$GROUP_TYPE_ID = 9) THEN
    BEGIN
      EXECUTE PROCEDURE CLASS_OVZ_RECALC(NULL, :I$GROUP_ID);
    END

    OBJ_ID = V$OBJ_ID;

  END
  -- Отмена зачисления
  -- это атомарная операция - при отмене движения делается отдельно отмена зачисления в текущем классе и отмена отчисления из прошлого
  ELSE IF(I$ACTION_TYPE = 3) THEN
  BEGIN

    -- А был ли ученик ?
    SELECT FIRST 1 PM.OBJ_ID, PM.DATE_IN
    FROM PERSON_MOVEMENTS PM
    WHERE PM.DATE_DEL IS NULL AND PM.PERSON_ID = :I$PUPIL_ID AND PM.GROUP_ID = :I$GROUP_ID AND PM.DATE_OUT IS NULL
    INTO :V$OBJ_ID, :DT1;
    
    IF(V$OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не найдена запись движения учащегося ' || V$CAPTION || ' в группе ' ||
      (SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$GROUP_ID)) || ', тип ' || V$GROUP_TYPE_ID || ', id ' || I$GROUP_ID;

    -- Отменяем зачисление во все группы, куда был включен
    IF(V$GROUP_TYPE_ID IN (9, 187)) THEN
    BEGIN
      FOR
        SELECT LPG.PARENT_ID
        FROM LINKS LPG
        WHERE LPG.OBJ_ID = :I$PUPIL_ID AND LPG.PARENT_TYPE_ID IN (46, 256) AND LPG.DATE_DEL IS NULL
        INTO :V$GROUP_ID
      DO
      BEGIN
        SELECT OBJ_ID FROM VARGRP_MOVE_PUPIL(:I$PUPIL_ID, :V$GROUP_ID, :I$ORDER_NUM, :I$ORDER_DATE, :I$ACTION_DATE, 3, IIF(:V$YC = 0, '', '@') || :I$USER_ID, :I$ORDER_ID, :I$MOVE_TYPE, 902) INTO :TMP;
      END

      -- Доотчисляем из ГПП, где остался
      FOR
        SELECT L179.OBJ_ID
        FROM LINKS L179
        JOIN LINKS L10 ON L10.PARENT_ID = L179.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL AND L10.OBJ_ID = :I$PUPIL_ID
        WHERE L179.PARENT_TYPE_ID = 2 AND L179.OBJ_TYPE_ID = 179 AND L179.DATE_DEL IS NULL AND L179.EXT_OBJ_ID = :I$GROUP_ID
        INTO :V$GROUP_ID
      DO
      BEGIN
        SELECT OBJ_ID FROM VARGRP_MOVE_PUPIL(:I$PUPIL_ID, :V$GROUP_ID, :I$ORDER_NUM, :I$ORDER_DATE, :I$ACTION_DATE, 3, IIF(:V$YC = 0, '', '@') || :I$USER_ID, :I$ORDER_ID, :I$MOVE_TYPE, 902) INTO :TMP;
      END
    END
    -- Отменяем зачисление во всех связанных ГПП
    ELSE IF(V$GROUP_TYPE_ID = 256) THEN
    BEGIN
      FOR
        SELECT L179.OBJ_ID
        FROM LINKS L179
        JOIN LINKS L10 ON L10.PARENT_ID = L179.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL AND L10.OBJ_ID = :I$PUPIL_ID
        WHERE L179.PARENT_TYPE_ID = 2 AND L179.OBJ_TYPE_ID = 179 AND L179.DATE_DEL IS NULL AND L179.EXT_OBJ_ID = :I$GROUP_ID
        INTO :V$GROUP_ID
      DO
      BEGIN
        SELECT OBJ_ID FROM VARGRP_MOVE_PUPIL(:I$PUPIL_ID, :V$GROUP_ID, :I$ORDER_NUM, :I$ORDER_DATE, :I$ACTION_DATE, 3, IIF(:V$YC = 0, '', '@') || :I$USER_ID, :I$ORDER_ID, :I$MOVE_TYPE, 902) INTO :TMP;
      END
    END

    -- Нет ли отметок с датой позднее даты зачисления ?
    IF(EXISTS(
      SELECT FIRST 1 1
      FROM CJ2_JOURNAL J
      JOIN CJ2_JOURNAL_LESSONS L ON L.CJ_ID = J.OBJ_ID AND L.DATE_DEL IS NULL
      JOIN CJ2_CONTROL C ON C.LESSON_ID = L.OBJ_ID AND C.DATE_DEL IS NULL
      JOIN CJ2_MARK M ON M.CONTROL_ID = C.CONTROL_ID AND M.DATE_DEL IS NULL AND M.STUDENT_ID = :I$PUPIL_ID
      WHERE J.DATE_DEL IS NULL AND J.GRADE_ID = :I$GROUP_ID AND (M.MARK_DATE >= :DT1 OR L.LESSON_DATE >= :DT1)
      UNION
      SELECT FIRST 1 1
      FROM CJ2_JOURNAL J
      JOIN CJ2_JOURNAL_FINALS L ON L.CJ_ID = J.OBJ_ID AND L.DATE_DEL IS NULL
      JOIN CJ2_MARK M ON M.FINAL_ID = L.OBJ_ID AND M.DATE_DEL IS NULL AND M.STUDENT_ID = :I$PUPIL_ID
      WHERE J.DATE_DEL IS NULL AND J.GRADE_ID = :I$GROUP_ID AND (M.MARK_DATE >= :DT1 OR L.FINAL_DATE >= :DT1)
    ))
    THEN
      EXCEPTION DATA_ERROR 'У обучающегося ' || V$CAPTION || ' есть выставленные отметки в журналах';

    UPDATE PERSON_MOVEMENTS PM
    SET PM.DATE_DEL = CURRENT_TIMESTAMP, PM.DATE_MODIFY = CURRENT_TIMESTAMP
    WHERE PM.OBJ_ID = :V$OBJ_ID;

    UPDATE LINKS L
    SET L.DATE_DEL = CURRENT_TIMESTAMP
    WHERE L.PARENT_ID = :I$GROUP_ID AND L.OBJ_ID = :I$PUPIL_ID AND L.DATE_DEL IS NULL;

    -- В классе - возвращаем в отчисленных или в предварительный прием, где он был до того
    -- Ученик из экстерната, если он не учился в школе, пропадет навсегда
    IF(V$GROUP_TYPE_ID IN (9, 289)) THEN
    BEGIN
      -- Есть ли еще записи движения до текущего ?
      V$HAS_ANY = 0;
      SELECT FIRST 1 1
      FROM PERSON_MOVEMENTS M
      WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :I$PUPIL_ID
      INTO :V$HAS_ANY;

      IF(V$HAS_ANY = 0) THEN
      BEGIN

        SELECT FIRST 1 L.LINK_ID, L.PARENT_TYPE_ID
        FROM LINKS L
        WHERE L.OBJ_ID = :I$PUPIL_ID AND L.PARENT_TYPE_ID IN (290, 289, 81, 82, 83)
        ORDER BY L.DATE_MODIFY DESC
        INTO :V$OUT, :V$OUT_TYPE;

        UPDATE LINKS
        SET DATE_DEL = CURRENT_TIMESTAMP
        WHERE LINK_ID = :V$OUT;

        IF(V$GROUP_TYPE_ID = 9) THEN
        BEGIN
          EXECUTE PROCEDURE CLASS_OVZ_RECALC(NULL, :I$GROUP_ID);
        END

        -- Восстановить папку предварительного приема
        IF(V$OUT_TYPE = 290) THEN
        BEGIN
          SELECT FIRST 1 L.LINK_ID
          FROM LINKS L
          WHERE L.OBJ_ID = :V$OUT AND L.PARENT_TYPE_ID = 77
          ORDER BY L.DATE_DEL DESC NULLS FIRST
          INTO :V$LINK_ID;

          UPDATE LINKS
          SET DATE_DEL = NULL
          WHERE LINK_ID = :V$LINK_ID AND DATE_DEL IS NOT NULL;
        END
      END
    END

    OBJ_ID = NULL;

  END
  -- Отмена отчисления
  ELSE IF(I$ACTION_TYPE = 4) THEN
  BEGIN
    -- А был ли ученик ?
    SELECT FIRST 1 PM.OBJ_ID, PM.DATE_OUT
    FROM PERSON_MOVEMENTS PM
    WHERE PM.DATE_DEL IS NULL AND PM.PERSON_ID = :I$PUPIL_ID AND PM.GROUP_ID = :I$GROUP_ID AND PM.DATE_OUT IS NOT NULL
    ORDER BY PM.OBJ_ID DESC
    INTO :V$OBJ_ID, :V$DATE;

    IF(V$OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не найдена запись движения учащегося ' || V$CAPTION || ' в группе ' ||
      (SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$GROUP_ID)) || ', тип ' || V$GROUP_TYPE_ID || ', id ' || I$GROUP_ID;

    UPDATE PERSON_MOVEMENTS PM
    SET PM.DATE_OUT = NULL, PM.REASON_OUT = NULL, PM.ORDER_NUM_OUT = NULL, PM.ORDER_DATE_OUT = NULL, PM.ORDER_ID_OUT = NULL, PM.DATE_MODIFY = CURRENT_TIMESTAMP
    WHERE PM.OBJ_ID = :V$OBJ_ID;

    -- Отменяем отчисление во всех связанных ГПП
    -- Внимание: если ученик не числился в ГПП, пока он не будет вновь туда добавлен
    IF(V$GROUP_TYPE_ID = 256) THEN
    BEGIN
      FOR
        SELECT L179.OBJ_ID
        FROM LINKS L179
        WHERE L179.PARENT_TYPE_ID = 2 AND L179.OBJ_TYPE_ID = 179 AND L179.DATE_DEL IS NULL AND L179.EXT_OBJ_ID = :I$GROUP_ID
        INTO :V$GROUP_ID
      DO
      BEGIN
        -- Выбираем ГПП, где ученик был отчислен, причем именно этим приказом
        -- либо если без приказа - то той же датой
        IF(EXISTS(
          SELECT 1
          FROM LINKS L10
          JOIN PERSON_MOVEMENTS M ON M.DATE_DEL IS NULL AND M.PERSON_ID = L10.OBJ_ID AND M.GROUP_ID = L10.PARENT_ID
            AND (M.ORDER_ID_OUT = :I$ORDER_ID OR (M.ORDER_ID_OUT IS NULL AND M.DATE_OUT = :V$DATE))
          WHERE L10.PARENT_ID = :V$GROUP_ID AND L10.OBJ_ID = :I$PUPIL_ID AND L10.DATE_DEL IS NOT NULL
        )) THEN
        BEGIN
          SELECT OBJ_ID FROM VARGRP_MOVE_PUPIL(:I$PUPIL_ID, :V$GROUP_ID, :I$ORDER_NUM, :I$ORDER_DATE, :I$ACTION_DATE, 4, IIF(:V$YC = 0, '', '@') || :I$USER_ID, :I$ORDER_ID, :I$MOVE_TYPE, 902) INTO :TMP;
        END
      END
    END

    IF(EXISTS(
      SELECT FIRST 1 1
      FROM LINKS L
      WHERE L.PARENT_ID = :I$GROUP_ID AND L.OBJ_ID = :I$PUPIL_ID AND L.DATE_DEL IS NULL
    ))
    THEN
      EXCEPTION DATA_ERROR 'Обучающийся уже числится в учебном коллективе, в котором должен быть восстановлен';

    SELECT FIRST 1 L.LINK_ID
    FROM LINKS L
    WHERE L.PARENT_ID = :I$GROUP_ID AND L.OBJ_ID = :I$PUPIL_ID AND L.DATE_DEL IS NOT NULL
    ORDER BY L.LINK_ID DESC
    INTO :V$LINK_ID;

    UPDATE LINKS
    SET DATE_DEL = NULL
    WHERE LINK_ID = :V$LINK_ID AND DATE_DEL IS NOT NULL;

    -- Удаляем линк в отчисленных, если ученик возвращен из окончивших/отчисленных
    V$LINK_ID = NULL;
    SELECT FIRST 1 L.LINK_ID
    FROM LINKS L
    WHERE L.OBJ_ID = :I$PUPIL_ID AND L.PARENT_TYPE_ID IN (81, 82, 83, 289) AND L.DATE_DEL IS NULL
    INTO :V$LINK_ID;

    UPDATE LINKS
    SET DATE_DEL = CURRENT_TIMESTAMP
    WHERE LINK_ID = :V$LINK_ID AND DATE_DEL IS NULL;

    -- Корректируем форму обучения в соответствии с текущим типом учебного коллектива
    IF(V$GROUP_TYPE_ID = 9) THEN
    BEGIN
      IF(V$OU_TYPE IN ('O', 'S')) THEN SELECT BLOB_ID FROM VAL_ADD(80, :I$PUPIL_ID, 5418) INTO :TMP;
      EXECUTE PROCEDURE CLASS_OVZ_RECALC(NULL, :I$GROUP_ID);
    END
    ELSE IF(V$GROUP_TYPE_ID = 187) THEN
    BEGIN
      -- Корректируем тип обучения
      IF(V$STAGE_ID IN (12765, 37, 38, 39, 40, 41, 42, 43, 44, 45)) THEN
      BEGIN
        -- 1-9 классы, семейное обучение
        SELECT BLOB_ID FROM VAL_ADD(80, :I$PUPIL_ID, 5422) INTO :TMP;
      END
      ELSE
      BEGIN
        -- 10-12, самообразование
        SELECT BLOB_ID FROM VAL_ADD(80, :I$PUPIL_ID, 5423) INTO :TMP;
      END
    END

    IF(V$GROUP_TYPE_ID IN (9, 187) OR (V$OU_TYPE = 'P' AND V$GROUP_TYPE_ID = 46)) THEN
    BEGIN
      -- Восстановить ГУП - вместе с ним восстановятся связанные ГПП
      FOR
        SELECT DISTINCT PM.GROUP_ID
        FROM PERSON_MOVEMENTS PM
        JOIN OBJECTS G ON G.OBJ_ID = PM.GROUP_ID AND G.TYPE_ID = 256
        WHERE PM.DATE_DEL IS NULL AND PM.PERSON_ID = :I$PUPIL_ID AND PM.DATE_OUT = :V$DATE
        INTO :V$GROUP_ID
      DO
      BEGIN
        SELECT OBJ_ID FROM VARGRP_MOVE_PUPIL(:I$PUPIL_ID, :V$GROUP_ID, :I$ORDER_NUM, :I$ORDER_DATE, :I$ACTION_DATE, 4, IIF(:V$YC = 0, '', '@') || :I$USER_ID, :I$ORDER_ID, :I$MOVE_TYPE, 902) INTO :TMP;
      END

      -- Восстановить оставшиеся ГПП и кружки
      FOR
        SELECT DISTINCT PM.GROUP_ID
        FROM PERSON_MOVEMENTS PM
        JOIN OBJECTS G ON G.OBJ_ID = PM.GROUP_ID AND G.TYPE_ID IN (46, 179) AND :V$OU_TYPE <> 'P'
        WHERE PM.DATE_DEL IS NULL AND PM.PERSON_ID = :I$PUPIL_ID AND PM.DATE_OUT = :V$DATE
        INTO :V$GROUP_ID
      DO
      BEGIN
        SELECT OBJ_ID FROM VARGRP_MOVE_PUPIL(:I$PUPIL_ID, :V$GROUP_ID, :I$ORDER_NUM, :I$ORDER_DATE, :I$ACTION_DATE, 4, IIF(:V$YC = 0, '', '@') || :I$USER_ID, :I$ORDER_ID, :I$MOVE_TYPE, 902) INTO :TMP;
      END
    END

  END

  -- Перерасчет статистики по УП
  IF(V$GROUP_TYPE_ID = 256) THEN EXECUTE PROCEDURE PLAN_GUP_RECALC(:I$GROUP_ID);

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE VERIFY_ADMIN2 (
    I$FROM VARCHAR(1000),
    I$RT VARCHAR(100),
    I$OLD_RT VARCHAR(100) = NULL)
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$OU_LEVEL SMALLINT;
DECLARE VARIABLE V$OU_LICENCE_TYPE CHAR(1);
DECLARE VARIABLE V$LEVEL BIGINT;
DECLARE VARIABLE V$KEY INTEGER;
DECLARE VARIABLE V$OLD_RT VARCHAR(100);
DECLARE VARIABLE V$DT TIME;
DECLARE VARIABLE V$OU_ID BIGINT;
DECLARE VARIABLE V$HAS_DO SMALLINT;
DECLARE VARIABLE V$HAS_OO SMALLINT;
DECLARE VARIABLE V$HAS_SPO SMALLINT;
DECLARE VARIABLE V$HAS_PO SMALLINT;
begin

  SELECT KEY_VAL FROM KEYS WHERE KEY_CODE = 'LEVEL' INTO :V$OU_LEVEL;
  SELECT STATUS FROM OU_LICENCE_TYPE INTO :V$OU_LICENCE_TYPE;
  IF(V$OU_LEVEL IS NULL) THEN EXCEPTION DATA_ERROR 'Не установлен лицензионный ключ';

  IF(NOT EXISTS(SELECT 1 FROM RDB$USER_PRIVILEGES WHERE RDB$RELATION_NAME = 'VER' AND RDB$USER = 'INISSOFT_ROLE' AND RDB$PRIVILEGE = 'S'))
    THEN EXCEPTION DATA_ERROR 'Обновление базы данных не было завершено, работа с базой невозможна';

  V$HAS_DO = 0;
  V$HAS_OO = 0;
  V$HAS_SPO = 0;
  V$HAS_PO = 0;
  SELECT FIRST 1 L2.OBJ_ID
  FROM LINKS L2
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$OU_ID;

  SELECT FIRST 1 1
  FROM LINKS L472
  JOIN VALL V3327 ON V3327.OBJ_ID = L472.OBJ_ID AND V3327.PARAM_ID = 3327 AND V3327.IS_DEL = 0 AND V3327.LISTVAL_ID IN (21, 3263, 3264)
  WHERE L472.PARENT_ID = :V$OU_ID AND L472.OBJ_TYPE_ID = 472 AND L472.DATE_DEL IS NULL
  INTO :V$HAS_DO;

  SELECT FIRST 1 1
  FROM LINKS L472
  JOIN VALL V3327 ON V3327.OBJ_ID = L472.OBJ_ID AND V3327.PARAM_ID = 3327 AND V3327.IS_DEL = 0 AND V3327.LISTVAL_ID IN (22, 26, 27)
  WHERE L472.PARENT_ID = :V$OU_ID AND L472.OBJ_TYPE_ID = 472 AND L472.DATE_DEL IS NULL
  INTO :V$HAS_OO;

  SELECT FIRST 1 1
  FROM LINKS L472
  JOIN VALL V3327 ON V3327.OBJ_ID = L472.OBJ_ID AND V3327.PARAM_ID = 3327 AND V3327.IS_DEL = 0 AND V3327.LISTVAL_ID IN (28, 29, 13129)
  WHERE L472.PARENT_ID = :V$OU_ID AND L472.OBJ_TYPE_ID = 472 AND L472.DATE_DEL IS NULL
  INTO :V$HAS_SPO;

  SELECT FIRST 1 1
  FROM LINKS L472
  JOIN VALL V3327 ON V3327.OBJ_ID = L472.OBJ_ID AND V3327.PARAM_ID = 3327 AND V3327.IS_DEL = 0 AND V3327.LISTVAL_ID IN (13129, 13131)
  WHERE L472.PARENT_ID = :V$OU_ID AND L472.OBJ_TYPE_ID = 472 AND L472.DATE_DEL IS NULL
  INTO :V$HAS_PO;

  TAG_NAME = 'key_id';
  V$KEY = (SELECT GEN FROM GEN);
  VAL = V$KEY;
  SUSPEND;

  TAG_NAME = 'level';
  -- Временно считаем по уровню базы, без разделения региональных пользователей на районные
  -- 0 - регион, 1 = район, 2 - организация, -1 - суперадмин (только уровень региона)
  VAL = (3 - V$OU_LEVEL);
  IF(VAL = 0) THEN VAL = -1;
  SUSPEND;

  TAG_NAME = 'id';
  VAL = 'Веб-администратор';
  SUSPEND;

  TAG_NAME = 'name';
  VAL = 'Веб-администратор';
  SUSPEND;

  TAG_NAME = 'ref_id';
  VAL = V$KEY;
  SUSPEND;

  TAG_NAME = 'ref_name';
  VAL = (SELECT KEY_VAL FROM KEYS WHERE KEY_CODE = 'ORGANIZATION_SHORT_NAME');
  SUSPEND;

  TAG_NAME = 'autoload';
  VAL = NULL;
  SUSPEND;

  TAG_NAME = 'modules';
  VAL = NULL;
  SUSPEND;

  -- Список доступных приложений
  TAG_NAME = 'modules:module';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'modules:module:name';
  VAL = 'app.admin';
  SUSPEND;
  TAG_NAME = 'modules:module:level';
  VAL = '1';
  SUSPEND;

  -- Статистика по организации - только для уровня ОУ
  IF(V$OU_LEVEL = 1) THEN
  BEGIN
    TAG_NAME = 'modules:module';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'modules:module:name';
    VAL = 'app.bb';
    SUSPEND;
    TAG_NAME = 'modules:module:level';
    VAL = '1';
    SUSPEND;
  END

  -- ПТП - кроме ДОУ
  IF(V$OU_LEVEL = 1 AND V$OU_LICENCE_TYPE <> 'D') THEN
  BEGIN
    TAG_NAME = 'modules:module';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'modules:module:name';
    VAL = 'app.ptp';
    SUSPEND;
    TAG_NAME = 'modules:module:level';
    VAL = '1';
    SUSPEND;
  END

  IF(V$OU_LEVEL = 1) THEN
  BEGIN
    TAG_NAME = 'modules:module';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'modules:module:name';
    VAL = 'app.cj';
    SUSPEND;
    TAG_NAME = 'modules:module:level';
    VAL = '1';
    SUSPEND;

    /*TAG_NAME = 'modules:module';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'modules:module:name';
    VAL = 'app.worktables';
    SUSPEND;
    TAG_NAME = 'modules:module:level';
    VAL = '1';
    SUSPEND;*/
  END

  -- Итоговые отметки и аттестация СПО
  -- МультиПараграф - смотрим не по лицензии, а по фактическим уровням образования
  -- аттестации СПО на районном и региональном уровнях нет
  IF(V$OU_LICENCE_TYPE IN ('O', 'P') OR V$HAS_OO = 1) THEN
  BEGIN
    TAG_NAME = 'modules:module';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'modules:module:name';
    VAL = 'app.finalmarks';
    SUSPEND;
    TAG_NAME = 'modules:module:level';
    VAL = '1';
    SUSPEND;
  END

  IF(V$OU_LICENCE_TYPE IN ('C', 'P') OR V$HAS_SPO = 1) THEN
  BEGIN
    TAG_NAME = 'modules:module';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'modules:module:name';
    VAL = 'app.attmarks';
    SUSPEND;
    TAG_NAME = 'modules:module:level';
    VAL = '1';
    SUSPEND;
  END

  IF(V$OU_LICENCE_TYPE IN ('O', 'S')) THEN
  BEGIN
    TAG_NAME = 'modules:module';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'modules:module:name';
    VAL = 'app.cec';
    SUSPEND;
    TAG_NAME = 'modules:module:level';
    VAL = '1';
    SUSPEND;
  END

  IF(V$OU_LEVEL = 1) THEN
  BEGIN
    TAG_NAME = 'modules:module';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'modules:module:name';
    VAL = 'app.messages';
    SUSPEND;
    TAG_NAME = 'modules:module:level';
    VAL = '1';
    SUSPEND;
  END

  IF(V$OU_LEVEL = 1 AND V$OU_LICENCE_TYPE <> 'D') THEN
  BEGIN
    TAG_NAME = 'modules:module';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'modules:module:name';
    VAL = 'app.subst';
    SUSPEND;
    TAG_NAME = 'modules:module:level';
    VAL = '1';
    SUSPEND;
  END

  IF(V$OU_LEVEL = 1 AND V$OU_LICENCE_TYPE <> 'U') THEN
  BEGIN
    TAG_NAME = 'modules:module';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'modules:module:name';
    VAL = 'app.ychange';
    SUSPEND;
    TAG_NAME = 'modules:module:level';
    VAL = '1';
    SUSPEND;
  END

  IF(V$OU_LICENCE_TYPE IN ('O', 'S')) THEN
  BEGIN
    TAG_NAME = 'modules:module';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'modules:module:name';
    VAL = 'app.test_experts';
    SUSPEND;
    TAG_NAME = 'modules:module:level';
    VAL = '1';
    SUSPEND;

    TAG_NAME = 'modules:module';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'modules:module:name';
    VAL = 'app.test_students';
    SUSPEND;
    TAG_NAME = 'modules:module:level';
    VAL = '1';
    SUSPEND;

    TAG_NAME = 'modules:module';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'modules:module:name';
    VAL = 'app.test_choose';
    SUSPEND;
    TAG_NAME = 'modules:module:level';
    VAL = '1';
    SUSPEND;

    TAG_NAME = 'modules:module';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'modules:module:name';
    VAL = 'app.test_ppe_assn';
    SUSPEND;
    TAG_NAME = 'modules:module:level';
    VAL = '1';
    SUSPEND;

    TAG_NAME = 'modules:module';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'modules:module:name';
    VAL = 'app.test_room_assn';
    SUSPEND;
    TAG_NAME = 'modules:module:level';
    VAL = '1';
    SUSPEND;

    TAG_NAME = 'modules:module';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'modules:module:name';
    VAL = 'app.test_byseat';
    SUSPEND;
    TAG_NAME = 'modules:module:level';
    VAL = '1';
    SUSPEND;

    TAG_NAME = 'modules:module';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'modules:module:name';
    VAL = 'app.test_stuff_assn';
    SUSPEND;
    TAG_NAME = 'modules:module:level';
    VAL = '1';
    SUSPEND;

    TAG_NAME = 'modules:module';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'modules:module:name';
    VAL = 'app.test_coding';
    SUSPEND;
    TAG_NAME = 'modules:module:level';
    VAL = '1';
    SUSPEND;

    TAG_NAME = 'modules:module';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'modules:module:name';
    VAL = 'app.test_questions';
    SUSPEND;
    TAG_NAME = 'modules:module:level';
    VAL = '1';
    SUSPEND;

    TAG_NAME = 'modules:module';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'modules:module:name';
    VAL = 'app.test_plan';
    SUSPEND;
    TAG_NAME = 'modules:module:level';
    VAL = '1';
    SUSPEND;

    TAG_NAME = 'modules:module';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'modules:module:name';
    VAL = 'app.test_variants';
    SUSPEND;
    TAG_NAME = 'modules:module:level';
    VAL = '1';
    SUSPEND;

    TAG_NAME = 'modules:module';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'modules:module:name';
    VAL = 'app.test_structures';
    SUSPEND;
    TAG_NAME = 'modules:module:level';
    VAL = '1';
    SUSPEND;

    TAG_NAME = 'modules:module';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'modules:module:name';
    VAL = 'app.test_ppe';
    SUSPEND;
    TAG_NAME = 'modules:module:level';
    VAL = '1';
    SUSPEND;

    TAG_NAME = 'modules:module';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'modules:module:name';
    VAL = 'app.test_psn_ppe';
    SUSPEND;
    TAG_NAME = 'modules:module:level';
    VAL = '1';
    SUSPEND;

    TAG_NAME = 'modules:module';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'modules:module:name';
    VAL = 'app.test_stuff';
    SUSPEND;
    TAG_NAME = 'modules:module:level';
    VAL = '1';
    SUSPEND;

    TAG_NAME = 'modules:module';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'modules:module:name';
    VAL = 'app.test_process';
    SUSPEND;
    TAG_NAME = 'modules:module:level';
    VAL = '1';
    SUSPEND;

    TAG_NAME = 'modules:module';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'modules:module:name';
    VAL = 'app.test_scan';
    SUSPEND;
    TAG_NAME = 'modules:module:level';
    VAL = '1';
    SUSPEND;

    TAG_NAME = 'modules:module';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'modules:module:name';
    VAL = 'app.test_verify';
    SUSPEND;
    TAG_NAME = 'modules:module:level';
    VAL = '1';
    SUSPEND;

    TAG_NAME = 'modules:module';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'modules:module:name';
    VAL = 'app.test_check';
    SUSPEND;
    TAG_NAME = 'modules:module:level';
    VAL = '1';
    SUSPEND;

    TAG_NAME = 'modules:module';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'modules:module:name';
    VAL = 'app.test_mon';
    SUSPEND;
    TAG_NAME = 'modules:module:level';
    VAL = '1';
    SUSPEND;

    TAG_NAME = 'modules:module';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'modules:module:name';
    VAL = 'app.test_review';
    SUSPEND;
    TAG_NAME = 'modules:module:level';
    VAL = '1';
    SUSPEND;

    TAG_NAME = 'modules:module';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'modules:module:name';
    VAL = 'app.test_templates';
    SUSPEND;
    TAG_NAME = 'modules:module:level';
    VAL = '1';
    SUSPEND;

    IF(V$OU_LEVEL = 1) THEN
    BEGIN
      TAG_NAME = 'modules:module';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'modules:module:name';
      VAL = 'app.test_print';
      SUSPEND;
      TAG_NAME = 'modules:module:level';
      VAL = '1';
      SUSPEND;
    END

  END

  TAG_NAME = 'modules:module';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'modules:module:name';
  VAL = 'app.rgnstat';
  SUSPEND;
  TAG_NAME = 'modules:module:level';
  VAL = '1';
  SUSPEND;

  IF(V$OU_LICENCE_TYPE <> 'D') THEN
  BEGIN
    TAG_NAME = 'modules:module';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'modules:module:name';
    VAL = 'app.study_docs';
    SUSPEND;
    TAG_NAME = 'modules:module:level';
    VAL = '1';
    SUSPEND;

    TAG_NAME = 'modules:module';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'modules:module:name';
    VAL = 'app.subjects';
    SUSPEND;
    TAG_NAME = 'modules:module:level';
    VAL = '1';
    SUSPEND;
  END

  -- app.att добавляем только чтобы были доступны методы, само приложение в меню будет скрыто
  IF(V$OU_LEVEL = 1) THEN
  BEGIN
    TAG_NAME = 'modules:module';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'modules:module:name';
    VAL = 'app.att';
    SUSPEND;
    TAG_NAME = 'modules:module:level';
    VAL = '1';
    SUSPEND;
  END

  -- Новый библиограф
  IF(V$OU_LEVEL = 1 AND V$OU_LICENCE_TYPE IN ('O', 'S')) THEN
  BEGIN
    TAG_NAME = 'modules:module';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'modules:module:name';
    VAL = 'app.library';
    SUSPEND;
    TAG_NAME = 'modules:module:level';
    VAL = '1';
    SUSPEND;
  END

  -- Должности - Кадровый учет
  TAG_NAME = 'modules:module';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'modules:module:name';
  VAL = 'app.joblist';
  SUSPEND;
  TAG_NAME = 'modules:module:level';
  VAL = '1';
  SUSPEND;

  -- Параграф Веб - отдаем полный список приложений для данного уровня (только где модуль = PARAGRAF)
  -- кроме печати аттестатов, экспорт в район Школы-ДОУ-СПО, Система оплаты питания, СКУД, Должности
  -- в S-версии убираем приложение Предметы - оно заменяется на app.subjects
  FOR
    SELECT L.LEVEL_ID
    FROM LUSERS LU
    JOIN LEVELS L ON L.LEVEL_ID = LU.LEVEL_ID AND L.IS_DEL = 0 AND L.LEVEL_ID NOT IN (489, 490, 478, 42, 114, 115, 202, /**/ 55, 158, 168, /**/ 474, 482, 211, /**/ 541, 546, 548, 24, 551)
    JOIN TASKS T ON T.TASK_ID = L.TASK_ID AND T.IS_DEL = 0
    JOIN MODULES M ON M.MODULE_ID = T.MODULE_ID AND M.IS_DEL = 0 AND M.MODULE_CODE = 'PARAGRAF' and M.IS_ACTIVE = 1
    WHERE LU.USER_ID = 1
    INTO :V$LEVEL
  DO
  BEGIN
    -- Вместо электронных журналов отдаем app.cj_manage
    IF(V$LEVEL IN (483, 517, 484, 485, 486, 547)) THEN
    BEGIN
      TAG_NAME = 'modules:module';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'modules:module:name';
      VAL = 'app.cj_manage';
      SUSPEND;
      TAG_NAME = 'modules:module:level';
      VAL = '1';
      SUSPEND;
    END
    ELSE
    BEGIN
      TAG_NAME = 'modules:module';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'modules:module:name';
      VAL = 'app.odb(' || V$LEVEL || ')';
      SUSPEND;
      TAG_NAME = 'modules:module:level';
      VAL = '1';
      SUSPEND;
    END
  END

  -- app.orders app.odb_persons неактуальны

  -- Логгирование - только если непосредственно вход, а не обновление кэша; добавляем рефреш-токен
  IF(I$FROM IS NOT NULL) THEN
  BEGIN
    -- Если это запрос продления, проверяем, был ли выдан этот RT
    IF(I$OLD_RT IS NOT NULL) THEN
    BEGIN
      SELECT FIRST 1 T.RT, T.DATE_ADD
      FROM AUTH_TOKENS T
      WHERE T.USER_ID = 1 AND T.ADDR = SUBSTRING(:I$FROM FROM 1 FOR 100)
      ORDER BY T.OBJ_ID DESC
      INTO :V$OLD_RT, :V$DT;

      IF(V$OLD_RT <> I$OLD_RT) THEN
      BEGIN
        V$OLD_RT = NULL;
        SELECT FIRST 1 T.RT
        FROM AUTH_TOKENS T
        WHERE T.USER_ID = 1 AND T.ADDR = SUBSTRING(:I$FROM FROM 1 FOR 100) AND T.RT = :I$OLD_RT AND T.DATE_ADD >= DATEADD(-1 HOUR TO :V$DT)
        ORDER BY T.OBJ_ID DESC
        INTO :V$OLD_RT;
      END

      IF(V$OLD_RT IS NULL OR V$OLD_RT <> I$OLD_RT) THEN EXCEPTION DATA_ERROR 'Недействительный refresh-token';
    END

    INSERT INTO AUTH_TOKENS
    (USER_ID, ADDR, RT, IS_LOGIN)
    VALUES (1, SUBSTRING(:I$FROM FROM 1 FOR 100), :I$RT, IIF(:I$OLD_RT IS NULL, 2, 0));
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE VERIFY_ALL (
    I$OBJ_ID BIGINT,
    I$USER_ID BIGINT = 1)
RETURNS (
    LINK_ID BIGINT,
    OBJECT_ID BIGINT,
    PARENT_ID BIGINT,
    NAME_TASK VARCHAR(1000),
    ERROR_NAME VARCHAR(1000),
    PARAMS_NAME VARCHAR(1000),
    ERROR_TEXT VARCHAR(1000),
    ERROR_TYPE SMALLINT)
AS
DECLARE VARIABLE V$STATUS VARCHAR(10);
DECLARE VARIABLE V$VPL SMALLINT;
DECLARE VARIABLE V$KO SMALLINT;
BEGIN

    V$STATUS = (SELECT STATUS FROM OU_LICENCE_TYPE);

    -- Для пунктов регистрации ГИА временно вырубаем вообще все ошибки
    V$VPL = 0;
    SELECT FIRST 1 1
    FROM LINKS L124
    WHERE L124.PARENT_ID IS NULL AND L124.OBJ_TYPE_ID = 124 AND L124.DATE_DEL IS NULL
    INTO :V$VPL;

    -- Понижаем уровень проверки для ОУ, не являющихся подведами КО
    V$KO = 0;
    SELECT FIRST 1 1
    FROM LINKS L2
    JOIN VALS V6 ON V6.OBJ_ID = L2.OBJ_ID AND V6.PARAM_ID = 6 AND V6.IS_DEL = 0 AND UPPER(V6.VAL) LIKE '%ОБРАЗОВАН%'
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :V$KO;

    -- Также понижаем уровнь проверки для ЧОУ
    IF(V$KO = 1) THEN
    SELECT FIRST 1 0
    FROM LINKS L2
    JOIN VALL V8 ON V8.OBJ_ID = L2.OBJ_ID AND V8.PARAM_ID = 8 AND V8.IS_DEL = 0 AND V8.LISTVAL_ID = 5404
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :V$KO;

    FOR
        SELECT LINK_ID, OBJECT_ID, PARENT_ID, NAME_TASK, ERROR_NAME, PARAMS_NAME, ERROR_TEXT, ERROR_TYPE
        FROM VERIFY_BUILDING(:I$OBJ_ID, :I$USER_ID)
        INTO :LINK_ID, :OBJECT_ID, :PARENT_ID, :NAME_TASK, :ERROR_NAME, :PARAMS_NAME, :ERROR_TEXT, :ERROR_TYPE
    DO
    BEGIN
        IF(V$KO = 0 AND ERROR_TYPE = 3) THEN ERROR_TYPE = 2;
        SUSPEND;
    END

    FOR
        SELECT LINK_ID, OBJECT_ID, PARENT_ID, NAME_TASK, ERROR_NAME, PARAMS_NAME, ERROR_TEXT, ERROR_TYPE
        FROM VERIFY_CLASS(:I$OBJ_ID)
        INTO :LINK_ID, :OBJECT_ID, :PARENT_ID, :NAME_TASK, :ERROR_NAME, :PARAMS_NAME, :ERROR_TEXT, :ERROR_TYPE
    DO
    BEGIN
        IF(V$KO = 0 AND ERROR_TYPE = 3) THEN ERROR_TYPE = 2;
        SUSPEND;
    END

    FOR
        SELECT LINK_ID, OBJECT_ID, PARENT_ID, NAME_TASK, ERROR_NAME, PARAMS_NAME, ERROR_TEXT, ERROR_TYPE
        FROM VERIFY_DOCS(:I$OBJ_ID)
        INTO :LINK_ID, :OBJECT_ID, :PARENT_ID, :NAME_TASK, :ERROR_NAME, :PARAMS_NAME, :ERROR_TEXT, :ERROR_TYPE
    DO
    BEGIN
        IF(V$KO = 0 AND ERROR_TYPE = 3) THEN ERROR_TYPE = 2;
        SUSPEND;
    END

    FOR
        SELECT LINK_ID, OBJECT_ID, PARENT_ID, NAME_TASK, ERROR_NAME, PARAMS_NAME, ERROR_TEXT, ERROR_TYPE
        FROM VERIFY_POST(:I$OBJ_ID)
        INTO :LINK_ID, :OBJECT_ID, :PARENT_ID, :NAME_TASK, :ERROR_NAME, :PARAMS_NAME, :ERROR_TEXT, :ERROR_TYPE
    DO
    BEGIN
        IF(V$KO = 0 AND ERROR_TYPE = 3) THEN ERROR_TYPE = 2;
        SUSPEND;
    END

    FOR
        SELECT LINK_ID, OBJECT_ID, PARENT_ID, NAME_TASK, ERROR_NAME, PARAMS_NAME, ERROR_TEXT, ERROR_TYPE
        FROM VERIFY_PUPIL(:I$OBJ_ID)
        INTO :LINK_ID, :OBJECT_ID, :PARENT_ID, :NAME_TASK, :ERROR_NAME, :PARAMS_NAME, :ERROR_TEXT, :ERROR_TYPE
    DO
    BEGIN
        IF(V$KO = 0 AND ERROR_TYPE = 3) THEN ERROR_TYPE = 2;
        SUSPEND;
    END

    FOR
        SELECT LINK_ID, OBJECT_ID, PARENT_ID, NAME_TASK, ERROR_NAME, PARAMS_NAME, ERROR_TEXT, ERROR_TYPE
        FROM VERIFY_SUBJECT(:I$OBJ_ID)
        INTO :LINK_ID, :OBJECT_ID, :PARENT_ID, :NAME_TASK, :ERROR_NAME, :PARAMS_NAME, :ERROR_TEXT, :ERROR_TYPE
    DO
    BEGIN
        IF(V$KO = 0 AND ERROR_TYPE = 3) THEN ERROR_TYPE = 2;
        SUSPEND;
    END

    FOR
        SELECT LINK_ID, OBJECT_ID, PARENT_ID, NAME_TASK, ERROR_NAME, PARAMS_NAME, ERROR_TEXT, ERROR_TYPE
        FROM VERIFY_WORKERS(:I$OBJ_ID)
        INTO :LINK_ID, :OBJECT_ID, :PARENT_ID, :NAME_TASK, :ERROR_NAME, :PARAMS_NAME, :ERROR_TEXT, :ERROR_TYPE
    DO
    BEGIN
        IF(V$KO = 0 AND ERROR_TYPE = 3) THEN ERROR_TYPE = 2;
        SUSPEND;
    END

    FOR
        SELECT LINK_ID, OBJECT_ID, PARENT_ID, NAME_TASK, ERROR_NAME, PARAMS_NAME, ERROR_TEXT, ERROR_TYPE
        FROM VERIFY_TIMETABLE(:I$OBJ_ID)
        INTO :LINK_ID, :OBJECT_ID, :PARENT_ID, :NAME_TASK, :ERROR_NAME, :PARAMS_NAME, :ERROR_TEXT, :ERROR_TYPE
    DO
    BEGIN
        IF(V$KO = 0 AND ERROR_TYPE = 3) THEN ERROR_TYPE = 2;
        SUSPEND;
    END

   FOR
        SELECT LINK_ID, SCHOOLAR_ID, PARENT_ID, NAME_TASK, ERROR_NAME, PARAMS_NAME, COALESCE(LOCATION || ', ', '') || COALESCE(PUPIL || ', ', '') || ERROR_TEXT, ERROR_TYPE
        FROM VERIFY_MOVEMENT(:I$OBJ_ID, :I$USER_ID)
        INTO :LINK_ID, :OBJECT_ID, :PARENT_ID, :NAME_TASK, :ERROR_NAME, :PARAMS_NAME, :ERROR_TEXT, :ERROR_TYPE
    DO
    BEGIN
        IF(V$KO = 0 AND ERROR_TYPE = 3) THEN ERROR_TYPE = 2;
        SUSPEND;
    END

    FOR
        SELECT LINK_ID, OBJECT_ID, PARENT_ID, NAME_TASK, ERROR_NAME, PARAMS_NAME, ERROR_TEXT, ERROR_TYPE
        FROM VERIFY_MTR(:I$OBJ_ID)
        INTO :LINK_ID, :OBJECT_ID, :PARENT_ID, :NAME_TASK, :ERROR_NAME, :PARAMS_NAME, :ERROR_TEXT, :ERROR_TYPE
    DO
    BEGIN
        IF(V$KO = 0 AND ERROR_TYPE = 3) THEN ERROR_TYPE = 2;
        SUSPEND;
    END

    FOR
        SELECT LINK_ID, OBJECT_ID, PARENT_ID, NAME_TASK, ERROR_NAME, PARAMS_NAME, ERROR_TEXT, ERROR_TYPE
        FROM VERIFY_MONITORING(:I$OBJ_ID)
        INTO :LINK_ID, :OBJECT_ID, :PARENT_ID, :NAME_TASK, :ERROR_NAME, :PARAMS_NAME, :ERROR_TEXT, :ERROR_TYPE
    DO
    BEGIN
        IF(V$KO = 0 AND ERROR_TYPE = 3) THEN ERROR_TYPE = 2;
        SUSPEND;
    END

    -- Только школы и СПО
    IF(V$STATUS IN ('O', 'C', 'S')) THEN
    FOR
        SELECT LINK_ID, OBJECT_ID, PARENT_ID, NAME_TASK, ERROR_NAME, PARAMS_NAME, ERROR_TEXT, ERROR_TYPE
        FROM VERIFY_GIA(:I$OBJ_ID)
        INTO :LINK_ID, :OBJECT_ID, :PARENT_ID, :NAME_TASK, :ERROR_NAME, :PARAMS_NAME, :ERROR_TEXT, :ERROR_TYPE
    DO
    BEGIN
        IF(V$KO = 0 AND ERROR_TYPE = 3) THEN ERROR_TYPE = 2;
        SUSPEND;
    END

    FOR
        SELECT LINK_ID, OBJECT_ID, PARENT_ID, NAME_TASK, ERROR_NAME, PARAMS_NAME, ERROR_TEXT, ERROR_TYPE
        FROM VERIFY_OP(:I$OBJ_ID)
        INTO :LINK_ID, :OBJECT_ID, :PARENT_ID, :NAME_TASK, :ERROR_NAME, :PARAMS_NAME, :ERROR_TEXT, :ERROR_TYPE
    DO
    BEGIN
        -- Для СПО не считаем ошибки в УП критическими
        IF((V$KO = 0 OR V$STATUS = 'C') AND ERROR_TYPE = 3) THEN ERROR_TYPE = 2;
        SUSPEND;
    END
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE VERIFY_ALL_DICT (
    I$LEVEL_ID BIGINT)
RETURNS (
    TYPE_ID BIGINT,
    TYPE_NAME VARCHAR(400),
    PARAM_ID BIGINT,
    PARAM_NAME VARCHAR(400),
    PARAM_TYPE_ID BIGINT,
    PARAM_TYPE_NAME VARCHAR(100),
    VAL_REQUIRED SMALLINT,
    VAL_CHECK SMALLINT,
    VAL_MASK VARCHAR(400),
    VAL_EXTRA VARCHAR(400),
    BLOCK_NAME VARCHAR(100))
AS
declare variable V$LEVEL_ID bigint;
begin

  V$LEVEL_ID = NULL;
  BLOCK_NAME = 'Здания, помещения, объекты';
  SELECT FIRST 1 L.LEVEL_ID
  FROM LEVELS L
  JOIN TASKS T ON T.TASK_ID = L.TASK_ID AND T.IS_DEL = 0
  JOIN MODULES M ON M.MODULE_ID = T.MODULE_ID AND M.IS_DEL = 0 AND M.IS_ACTIVE = 1
  JOIN RES R ON R.RES_ID = T.RES_ID AND R.LANG_CODE = 'RU' AND R.VAL LIKE '%дания%'
  WHERE L.IS_DEL = 0
  INTO :V$LEVEL_ID;
  IF(V$LEVEL_ID IS NOT NULL) THEN
  FOR
    SELECT TYPE_ID, TYPE_NAME, PARAM_ID, PARAM_NAME, PARAM_TYPE_ID, PARAM_TYPE_NAME, VAL_REQUIRED, VAL_CHECK, VAL_MASK, VAL_EXTRA
    FROM VERIFY_BUILDING_DICT(:V$LEVEL_ID)
    INTO :TYPE_ID, :TYPE_NAME, :PARAM_ID, :PARAM_NAME, :PARAM_TYPE_ID, :PARAM_TYPE_NAME, :VAL_REQUIRED, :VAL_CHECK, :VAL_MASK, :VAL_EXTRA
  DO
  BEGIN
    SUSPEND;
  END

  V$LEVEL_ID = NULL;
  BLOCK_NAME = 'Учебные коллективы';
  SELECT FIRST 1 L.LEVEL_ID
  FROM LEVELS L
  JOIN TASKS T ON T.TASK_ID = L.TASK_ID AND T.IS_DEL = 0
  JOIN MODULES M ON M.MODULE_ID = T.MODULE_ID AND M.IS_DEL = 0 AND M.IS_ACTIVE = 1
  JOIN RES R ON R.RES_ID = T.RES_ID AND R.LANG_CODE = 'RU' AND R.VAL LIKE '%коллективы%'
  WHERE L.IS_DEL = 0
  INTO :V$LEVEL_ID;
  IF(V$LEVEL_ID IS NOT NULL) THEN
  FOR
    SELECT TYPE_ID, TYPE_NAME, PARAM_ID, PARAM_NAME, PARAM_TYPE_ID, PARAM_TYPE_NAME, VAL_REQUIRED, VAL_CHECK, VAL_MASK, VAL_EXTRA
    FROM VERIFY_CLASS_DICT(:V$LEVEL_ID)
    INTO :TYPE_ID, :TYPE_NAME, :PARAM_ID, :PARAM_NAME, :PARAM_TYPE_ID, :PARAM_TYPE_NAME, :VAL_REQUIRED, :VAL_CHECK, :VAL_MASK, :VAL_EXTRA
  DO
  BEGIN
    SUSPEND;
  END

  V$LEVEL_ID = NULL;
  BLOCK_NAME = 'Документы ОООД';
  SELECT FIRST 1 L.LEVEL_ID
  FROM LEVELS L
  JOIN TASKS T ON T.TASK_ID = L.TASK_ID AND T.IS_DEL = 0
  JOIN MODULES M ON M.MODULE_ID = T.MODULE_ID AND M.IS_DEL = 0 AND M.IS_ACTIVE = 1
  JOIN RES R ON R.RES_ID = T.RES_ID AND R.LANG_CODE = 'RU' AND R.VAL LIKE '%окументы%'
  WHERE L.IS_DEL = 0
  INTO :V$LEVEL_ID;
  IF(V$LEVEL_ID IS NOT NULL) THEN
  FOR
    SELECT TYPE_ID, TYPE_NAME, PARAM_ID, PARAM_NAME, PARAM_TYPE_ID, PARAM_TYPE_NAME, VAL_REQUIRED, VAL_CHECK, VAL_MASK, VAL_EXTRA
    FROM VERIFY_DOCS_DICT(:V$LEVEL_ID)
    INTO :TYPE_ID, :TYPE_NAME, :PARAM_ID, :PARAM_NAME, :PARAM_TYPE_ID, :PARAM_TYPE_NAME, :VAL_REQUIRED, :VAL_CHECK, :VAL_MASK, :VAL_EXTRA
  DO
  BEGIN
    SUSPEND;
  END

  V$LEVEL_ID = NULL;
  BLOCK_NAME = 'Должности';
  SELECT FIRST 1 L.LEVEL_ID
  FROM LEVELS L
  JOIN TASKS T ON T.TASK_ID = L.TASK_ID AND T.IS_DEL = 0
  JOIN MODULES M ON M.MODULE_ID = T.MODULE_ID AND M.IS_DEL = 0 AND M.IS_ACTIVE = 1
  JOIN RES R ON R.RES_ID = T.RES_ID AND R.LANG_CODE = 'RU' AND R.VAL LIKE '%олжности%'
  WHERE L.IS_DEL = 0
  INTO :V$LEVEL_ID;
  IF(V$LEVEL_ID IS NOT NULL) THEN
  FOR
    SELECT TYPE_ID, TYPE_NAME, PARAM_ID, PARAM_NAME, PARAM_TYPE_ID, PARAM_TYPE_NAME, VAL_REQUIRED, VAL_CHECK, VAL_MASK, VAL_EXTRA
    FROM VERIFY_POST_DICT(:V$LEVEL_ID)
    INTO :TYPE_ID, :TYPE_NAME, :PARAM_ID, :PARAM_NAME, :PARAM_TYPE_ID, :PARAM_TYPE_NAME, :VAL_REQUIRED, :VAL_CHECK, :VAL_MASK, :VAL_EXTRA
  DO
  BEGIN
    SUSPEND;
  END

  V$LEVEL_ID = NULL;
  BLOCK_NAME = 'Обучающиеся';
  SELECT FIRST 1 L.LEVEL_ID
  FROM LEVELS L
  JOIN TASKS T ON T.TASK_ID = L.TASK_ID AND T.IS_DEL = 0
  JOIN MODULES M ON M.MODULE_ID = T.MODULE_ID AND M.IS_DEL = 0 AND M.IS_ACTIVE = 1
  JOIN RES R ON R.RES_ID = T.RES_ID AND R.LANG_CODE = 'RU' AND (R.VAL LIKE '%дела%восп%' OR R.VAL LIKE '%дела%студ%' OR R.VAL LIKE '%оллективы%ОО%')
  WHERE L.IS_DEL = 0
  INTO :V$LEVEL_ID;
  IF(V$LEVEL_ID IS NOT NULL) THEN
  FOR
    SELECT TYPE_ID, TYPE_NAME, PARAM_ID, PARAM_NAME, PARAM_TYPE_ID, PARAM_TYPE_NAME, VAL_REQUIRED, VAL_CHECK, VAL_MASK, VAL_EXTRA
    FROM VERIFY_PUPIL_DICT(:V$LEVEL_ID)
    INTO :TYPE_ID, :TYPE_NAME, :PARAM_ID, :PARAM_NAME, :PARAM_TYPE_ID, :PARAM_TYPE_NAME, :VAL_REQUIRED, :VAL_CHECK, :VAL_MASK, :VAL_EXTRA
  DO
  BEGIN
    SUSPEND;
  END

  V$LEVEL_ID = NULL;
  BLOCK_NAME = 'Предметы, дисциплины';
  SELECT FIRST 1 L.LEVEL_ID
  FROM LEVELS L
  JOIN TASKS T ON T.TASK_ID = L.TASK_ID AND T.IS_DEL = 0
  JOIN MODULES M ON M.MODULE_ID = T.MODULE_ID AND M.IS_DEL = 0 AND M.IS_ACTIVE = 1
  JOIN RES R ON R.RES_ID = T.RES_ID AND R.LANG_CODE = 'RU' AND R.VAL LIKE '%редметы%'
  WHERE L.IS_DEL = 0
  INTO :V$LEVEL_ID;
  IF(V$LEVEL_ID IS NOT NULL) THEN
  FOR
    SELECT TYPE_ID, TYPE_NAME, PARAM_ID, PARAM_NAME, PARAM_TYPE_ID, PARAM_TYPE_NAME, VAL_REQUIRED, VAL_CHECK, VAL_MASK, VAL_EXTRA
    FROM VERIFY_SUBJECT_DICT(:V$LEVEL_ID)
    INTO :TYPE_ID, :TYPE_NAME, :PARAM_ID, :PARAM_NAME, :PARAM_TYPE_ID, :PARAM_TYPE_NAME, :VAL_REQUIRED, :VAL_CHECK, :VAL_MASK, :VAL_EXTRA
  DO
  BEGIN
    SUSPEND;
  END

  V$LEVEL_ID = NULL;
  BLOCK_NAME = 'Сотрудники';
  SELECT FIRST 1 L.LEVEL_ID
  FROM LEVELS L
  JOIN TASKS T ON T.TASK_ID = L.TASK_ID AND T.IS_DEL = 0
  JOIN MODULES M ON M.MODULE_ID = T.MODULE_ID AND M.IS_DEL = 0 AND M.IS_ACTIVE = 1
  JOIN RES R ON R.RES_ID = T.RES_ID AND R.LANG_CODE = 'RU' AND (R.VAL LIKE '%отрудники%' OR R.VAL LIKE '%дела сотрудников%')
  WHERE L.IS_DEL = 0
  INTO :V$LEVEL_ID;
  IF(V$LEVEL_ID IS NOT NULL) THEN
  FOR
    SELECT TYPE_ID, TYPE_NAME, PARAM_ID, PARAM_NAME, PARAM_TYPE_ID, PARAM_TYPE_NAME, VAL_REQUIRED, VAL_CHECK, VAL_MASK, VAL_EXTRA
    FROM VERIFY_WORKERS_DICT(:V$LEVEL_ID)
    INTO :TYPE_ID, :TYPE_NAME, :PARAM_ID, :PARAM_NAME, :PARAM_TYPE_ID, :PARAM_TYPE_NAME, :VAL_REQUIRED, :VAL_CHECK, :VAL_MASK, :VAL_EXTRA
  DO
  BEGIN
    SUSPEND;
  END

  V$LEVEL_ID = NULL;
  BLOCK_NAME = 'Календарный график';
  SELECT FIRST 1 L.LEVEL_ID
  FROM LEVELS L
  JOIN TASKS T ON T.TASK_ID = L.TASK_ID AND T.IS_DEL = 0
  JOIN MODULES M ON M.MODULE_ID = T.MODULE_ID AND M.IS_DEL = 0 AND M.IS_ACTIVE = 1
  JOIN RES R ON R.RES_ID = T.RES_ID AND R.LANG_CODE = 'RU' AND R.VAL LIKE '%асписание%'
  WHERE L.IS_DEL = 0
  INTO :V$LEVEL_ID;
  IF(V$LEVEL_ID IS NOT NULL) THEN
  FOR
    SELECT TYPE_ID, TYPE_NAME, PARAM_ID, PARAM_NAME, PARAM_TYPE_ID, PARAM_TYPE_NAME, VAL_REQUIRED, VAL_CHECK, VAL_MASK, VAL_EXTRA
    FROM VERIFY_TIMETABLE_DICT(:V$LEVEL_ID)
    INTO :TYPE_ID, :TYPE_NAME, :PARAM_ID, :PARAM_NAME, :PARAM_TYPE_ID, :PARAM_TYPE_NAME, :VAL_REQUIRED, :VAL_CHECK, :VAL_MASK, :VAL_EXTRA
  DO
  BEGIN
    SUSPEND;
  END

  V$LEVEL_ID = NULL;
  BLOCK_NAME = 'Движение обучающихся';
  SELECT FIRST 1 L.LEVEL_ID
  FROM LEVELS L
  JOIN TASKS T ON T.TASK_ID = L.TASK_ID AND T.IS_DEL = 0
  JOIN MODULES M ON M.MODULE_ID = T.MODULE_ID AND M.IS_DEL = 0 AND M.IS_ACTIVE = 1
  JOIN RES R ON R.RES_ID = T.RES_ID AND R.LANG_CODE = 'RU' AND R.VAL LIKE '%вижение об%'
  WHERE L.IS_DEL = 0
  INTO :V$LEVEL_ID;
  IF(V$LEVEL_ID IS NOT NULL) THEN
  FOR
    SELECT TYPE_ID, TYPE_NAME, PARAM_ID, PARAM_NAME, PARAM_TYPE_ID, PARAM_TYPE_NAME, VAL_REQUIRED, VAL_CHECK, VAL_MASK, VAL_EXTRA
    FROM VERIFY_MOVEMENT_DICT(:V$LEVEL_ID)
    INTO :TYPE_ID, :TYPE_NAME, :PARAM_ID, :PARAM_NAME, :PARAM_TYPE_ID, :PARAM_TYPE_NAME, :VAL_REQUIRED, :VAL_CHECK, :VAL_MASK, :VAL_EXTRA
  DO
  BEGIN
    SUSPEND;
  END

  V$LEVEL_ID = NULL;
  BLOCK_NAME = 'МТР';
  SELECT FIRST 1 L.LEVEL_ID
  FROM LEVELS L
  JOIN TASKS T ON T.TASK_ID = L.TASK_ID AND T.IS_DEL = 0
  JOIN MODULES M ON M.MODULE_ID = T.MODULE_ID AND M.IS_DEL = 0 AND M.IS_ACTIVE = 1
  JOIN RES R ON R.RES_ID = T.RES_ID AND R.LANG_CODE = 'RU' AND R.VAL LIKE '%ресурсы%'
  WHERE L.IS_DEL = 0
  INTO :V$LEVEL_ID;
  IF(V$LEVEL_ID IS NOT NULL) THEN
  FOR
    SELECT TYPE_ID, TYPE_NAME, PARAM_ID, PARAM_NAME, PARAM_TYPE_ID, PARAM_TYPE_NAME, VAL_REQUIRED, VAL_CHECK, VAL_MASK, VAL_EXTRA
    FROM VERIFY_MTR_DICT(:V$LEVEL_ID)
    INTO :TYPE_ID, :TYPE_NAME, :PARAM_ID, :PARAM_NAME, :PARAM_TYPE_ID, :PARAM_TYPE_NAME, :VAL_REQUIRED, :VAL_CHECK, :VAL_MASK, :VAL_EXTRA
  DO
  BEGIN
    SUSPEND;
  END

  V$LEVEL_ID = NULL;
  BLOCK_NAME = 'Мониторинг';
  SELECT FIRST 1 L.LEVEL_ID
  FROM LEVELS L
  JOIN TASKS T ON T.TASK_ID = L.TASK_ID AND T.IS_DEL = 0
  JOIN MODULES M ON M.MODULE_ID = T.MODULE_ID AND M.IS_DEL = 0 AND M.IS_ACTIVE = 1
  JOIN RES R ON R.RES_ID = T.RES_ID AND R.LANG_CODE = 'RU' AND R.VAL LIKE '%ониторинг%'
  WHERE L.IS_DEL = 0
  INTO :V$LEVEL_ID;
  IF(V$LEVEL_ID IS NOT NULL) THEN
  FOR
    SELECT TYPE_ID, TYPE_NAME, PARAM_ID, PARAM_NAME, PARAM_TYPE_ID, PARAM_TYPE_NAME, VAL_REQUIRED, VAL_CHECK, VAL_MASK, VAL_EXTRA
    FROM VERIFY_MONITORING_DICT(:V$LEVEL_ID)
    INTO :TYPE_ID, :TYPE_NAME, :PARAM_ID, :PARAM_NAME, :PARAM_TYPE_ID, :PARAM_TYPE_NAME, :VAL_REQUIRED, :VAL_CHECK, :VAL_MASK, :VAL_EXTRA
  DO
  BEGIN
    SUSPEND;
  END

  V$LEVEL_ID = NULL;
  BLOCK_NAME = 'ГИА';
  SELECT FIRST 1 L.LEVEL_ID
  FROM LEVELS L
  JOIN TASKS T ON T.TASK_ID = L.TASK_ID AND T.IS_DEL = 0
  JOIN MODULES M ON M.MODULE_ID = T.MODULE_ID AND M.IS_DEL = 0 AND M.IS_ACTIVE = 1
  JOIN RES R ON R.RES_ID = T.RES_ID AND R.LANG_CODE = 'RU' AND R.VAL LIKE '%ониторинг%' -- ???
  WHERE L.IS_DEL = 0
  INTO :V$LEVEL_ID;
  IF(V$LEVEL_ID IS NOT NULL) THEN
  FOR
    SELECT TYPE_ID, TYPE_NAME, PARAM_ID, PARAM_NAME, PARAM_TYPE_ID, PARAM_TYPE_NAME, VAL_REQUIRED, VAL_CHECK, VAL_MASK, VAL_EXTRA
    FROM VERIFY_GIA_DICT(:V$LEVEL_ID)
    INTO :TYPE_ID, :TYPE_NAME, :PARAM_ID, :PARAM_NAME, :PARAM_TYPE_ID, :PARAM_TYPE_NAME, :VAL_REQUIRED, :VAL_CHECK, :VAL_MASK, :VAL_EXTRA
  DO
  BEGIN
    SUSPEND;
  END

  V$LEVEL_ID = NULL;
  BLOCK_NAME = 'Образовательные программы';
  SELECT FIRST 1 L.LEVEL_ID
  FROM LEVELS L
  JOIN TASKS T ON T.TASK_ID = L.TASK_ID AND T.IS_DEL = 0
  JOIN MODULES M ON M.MODULE_ID = T.MODULE_ID AND M.IS_DEL = 0 AND M.IS_ACTIVE = 1
  JOIN RES R ON R.RES_ID = T.RES_ID AND R.LANG_CODE = 'RU' AND R.VAL LIKE '%программ%'
  WHERE L.IS_DEL = 0
  INTO :V$LEVEL_ID;
  IF(V$LEVEL_ID IS NOT NULL) THEN
  FOR
    SELECT TYPE_ID, TYPE_NAME, PARAM_ID, PARAM_NAME, PARAM_TYPE_ID, PARAM_TYPE_NAME, VAL_REQUIRED, VAL_CHECK, VAL_MASK, VAL_EXTRA
    FROM VERIFY_OP_DICT(:V$LEVEL_ID)
    INTO :TYPE_ID, :TYPE_NAME, :PARAM_ID, :PARAM_NAME, :PARAM_TYPE_ID, :PARAM_TYPE_NAME, :VAL_REQUIRED, :VAL_CHECK, :VAL_MASK, :VAL_EXTRA
  DO
  BEGIN
    SUSPEND;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE VERIFY_AOOP_TYPES (
    I$OBJ_ID BIGINT,
    I$OP_TYPE BIGINT)
AS
declare variable V$FOLDER_TYPE bigint;
begin
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE VERIFY_ATT_TYPE (
    I$OBJ_ID BIGINT,
    I$VAL BIGINT)
AS
declare variable V$OLD_VAL bigint;
begin

  SELECT LISTVAL_ID
  FROM VALL
  WHERE OBJ_ID = :I$OBJ_ID AND PARAM_ID = 1847 AND IS_DEL = 0
  INTO :V$OLD_VAL;

  IF(I$VAL = V$OLD_VAL) THEN EXIT;

  IF(EXISTS(
    SELECT FIRST 1 1
    FROM LINKS L236
    WHERE L236.PARENT_ID = :I$OBJ_ID AND L236.OBJ_TYPE_ID = 236 AND L236.DATE_DEL IS NULL
  )) THEN EXCEPTION DATA_ERROR 'Нельзя изменить тип бланка, когда хотя бы один бланк уже использован';

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE VERIFY_BUILDING (
    I$OBJ_ID BIGINT,
    I$USER_ID BIGINT = 1)
RETURNS (
    LINK_ID BIGINT,
    OBJECT_ID BIGINT,
    PARENT_ID BIGINT,
    NAME_TASK VARCHAR(1000),
    ERROR_NAME VARCHAR(1000),
    PARAMS_NAME VARCHAR(1000),
    ERROR_TEXT VARCHAR(1000),
    ERROR_TYPE SMALLINT)
AS
DECLARE VARIABLE V$TEMP INTEGER;
DECLARE VARIABLE V$OU_LICENCE_TYPE VARCHAR(1);
DECLARE VARIABLE V$PARAM_ID BIGINT;
DECLARE VARIABLE S VARCHAR(1000);
DECLARE VARIABLE V VARCHAR(1000);
DECLARE VARIABLE N INTEGER;
DECLARE VARIABLE V$TYPE_ID BIGINT;
BEGIN
    SELECT STATUS FROM OU_LICENCE_TYPE INTO :V$OU_LICENCE_TYPE;

    NAME_TASK = 'Образовательное учреждение, здания, помещения';
    ERROR_TYPE = 0;

    -- Проверка пересекается с DOC - часть параметров проверяется там, остальные здесь
    SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$OBJ_ID) INTO :S;

    FOR
      SELECT ERROR_TYPE, ERROR_TEXT, ERROR_NAME, PARAMS_NAME, PARAM_ID
      FROM VERIFY_OBJECT_FIELDS(:I$OBJ_ID, 2, 'ОУ', :S)
      WHERE PARAM_ID NOT IN (9, 13, 16, 18, 19, 20, 21, 22, 33, 470)
      INTO :ERROR_TYPE, :ERROR_TEXT, :ERROR_NAME, :PARAMS_NAME, :V$PARAM_ID
    DO
    BEGIN
      SUSPEND;
    END

    IF(NOT EXISTS(
      SELECT FIRST 1 1
      FROM R_SPB_POST_DIRECTOR(:I$OBJ_ID, :I$USER_ID)
      WHERE POST_ID IN (64, 74, 65, 3399, 18497, 18531, 18532)
    )) THEN
    BEGIN
      ERROR_TEXT = 'Ошибочная должность руководителя';
      ERROR_NAME = ERROR_TEXT;
      PARAMS_NAME = 'Руководитель образовательного учреждения';
      ERROR_TYPE = 3;
      SUSPEND;
    END

    -- Краткое, полное, краткое по уставу, подчинение, вышестоящий орган - TRIM и удаление двойных пробелов

    -- Подчинение проверяем только для государственных ОУ, и пропускаем частные и филиалы
    IF (NOT EXISTS(
      SELECT FIRST 1 1
      FROM VALL VLL
      WHERE VLL.PARAM_ID = 8 AND VLL.IS_DEL = 0 AND VLL.LISTVAL_ID IN (1734, 1735) AND VLL.OBJ_ID = :I$OBJ_ID
    )) THEN
    BEGIN
      V = NULL;
      SELECT V6.VAL
      FROM VALS V6
      WHERE V6.OBJ_ID = :I$OBJ_ID AND V6.PARAM_ID = 6 AND V6.IS_DEL = 0
      INTO :V;

      IF(V IS NULL) THEN
      BEGIN
        ERROR_TEXT = 'Поле «Подчинение» должно быть заполнено';
        ERROR_NAME = ERROR_TEXT;
        PARAMS_NAME = 'Подчинение';
        ERROR_TYPE = 3;
        SUSPEND;
      END
      ELSE IF(V <> 'Комитет по образованию Санкт-Петербурга') THEN
      BEGIN
        ERROR_TEXT = 'Значение в поле «Подчинение» не соответствует стандартному "Комитет по образованию Санкт-Петербурга"';
        ERROR_NAME = ERROR_TEXT;
        PARAMS_NAME = 'Подчинение';
        ERROR_TYPE = 2;
        SUSPEND;
      END

      V = NULL;
      SELECT V7.VAL
      FROM VALS V7
      WHERE V7.OBJ_ID = :I$OBJ_ID AND V7.PARAM_ID = 7 AND V7.IS_DEL = 0
      INTO :V;

      IF(V IS NULL) THEN
      BEGIN
        ERROR_TEXT = 'Поле «Вышестоящий орган» должно быть заполнено';
        ERROR_NAME = ERROR_TEXT;
        PARAMS_NAME = 'Вышестоящий орган';
        ERROR_TYPE = 3;
        SUSPEND;
      END
      ELSE IF(NOT EXISTS(
        SELECT FIRST 1 1
        FROM LISTVALS LV
        JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU' AND R.VAL = :V
        WHERE LV.LIST_ID = 168 AND LV.IS_DEL = 0
      )) THEN
      BEGIN
        ERROR_TEXT = 'Значение не соответствует рекомендуемому (не выбрано из списка значений)';
        ERROR_NAME = ERROR_TEXT;
        PARAMS_NAME = 'Вышестоящий орган';
        ERROR_TYPE = 2;
        SUSPEND;
      END
    END

    V$TEMP = NULL;
    SELECT VI.VAL
    FROM VALI VI
    WHERE VI.PARAM_ID = 17 AND VI.IS_DEL = 0 AND VI.OBJ_ID = :I$OBJ_ID
    INTO :V$TEMP;

    IF (V$TEMP = 0) THEN
    BEGIN
      ERROR_TEXT = 'Номер ОУ не может содержать значение "0". Удалите номер, если ОУ не входит в число номерных';
      ERROR_NAME = ERROR_TEXT;
      PARAMS_NAME = 'Номер ОУ';
      ERROR_TYPE = 3;
      SUSPEND;
    END

    IF (V$TEMP > 0) THEN
    BEGIN
      IF(NOT EXISTS(
        SELECT 1
        FROM VALS VS
        WHERE VS.PARAM_ID = 5 AND VS.IS_DEL = 0 AND VS.OBJ_ID = :I$OBJ_ID AND VS.VAL LIKE '%' || :V$TEMP || '%'
      )) THEN
      BEGIN
        ERROR_TEXT = 'Номер ОУ не содержится в полном наименовании ОУ';
        ERROR_NAME = ERROR_TEXT;
        PARAMS_NAME = 'Полное наименование ОУ';
        ERROR_TYPE = 2;
        SUSPEND;
      END
    END

    /* это вычисляемое поле
    V$TEMP = NULL;
    SELECT V
    FROM VAL_GET(:OBJECT_ID, 2167, 0, :I$USER_ID)
    INTO :V$TEMP;

    IF ((V$TEMP IS NULL) OR (V$TEMP < 0)) THEN
    BEGIN
        ERROR_TEXT = 'Поле «Проектная мощность (чел.)» должно быть заполнено';
        ERROR_NAME = ERROR_TEXT;
        PARAMS_NAME = 'Проектная мощность (чел.)';
        ERROR_TYPE = 3;
        SUSPEND;
    END */

    -- Юридический адрес
    -- Если адрес не заполнен, сработает другая блокировка. Тут проверяем только если что-то заполнено
    V = NULL;
    SELECT FIRST 1 TRIM(VA.REGION)
    FROM VALA VA
    WHERE VA.PARAM_ID = 27 AND VA.OBJ_ID = :I$OBJ_ID AND VA.IS_DEL = 0
    INTO :V;

    IF (V <> 'Санкт-Петербург г') THEN
    BEGIN
      ERROR_TEXT = 'Поле «Регион» в юридическом адресе ОУ ="' || V || '", Вы уверены?';
      ERROR_NAME = 'Поле «Регион» в юридическом адресе ОУ <> "Санкт-Петербург г", Вы уверены?';
      PARAMS_NAME = 'Юридический адрес';
      ERROR_TYPE = 2;
      SUSPEND;
    END
    ELSE IF(EXISTS(
      SELECT 1
      FROM VALA VA
      WHERE VA.PARAM_ID = 27 AND VA.OBJ_ID = :I$OBJ_ID AND VA.IS_DEL = 0 AND COALESCE(VA.DISTRICT, '') <> ''
    )) THEN
    BEGIN
      ERROR_TEXT = 'Поле «Район» в юридическом адресе должно быть пустым';
      ERROR_NAME = ERROR_TEXT;
      PARAMS_NAME = 'Юридический адрес';
      ERROR_TYPE = 3;
      SUSPEND;
    END
    ELSE IF(NOT EXISTS(
      SELECT 1
      FROM VALA VA
      WHERE VA.PARAM_ID = 27 AND VA.OBJ_ID = :I$OBJ_ID AND VA.IS_DEL = 0 AND COALESCE(VA.STREET, '') <> ''
    )) THEN
    BEGIN
      ERROR_TEXT = 'Поле «Улица» в юридическом адресе не может быть пустым';
      ERROR_NAME = ERROR_TEXT;
      PARAMS_NAME = 'Юридический адрес';
      ERROR_TYPE = 3;
      SUSPEND;
    END
    ELSE IF(NOT EXISTS(
      SELECT 1
      FROM VALA VA
      WHERE VA.PARAM_ID = 27 AND VA.OBJ_ID = :I$OBJ_ID AND VA.IS_DEL = 0 AND COALESCE(VA.POST_INDEX, '') <> ''
    )) THEN
    BEGIN
      ERROR_TEXT = 'Поле «Индекс» в юридическом адресе не может быть пустым';
      ERROR_NAME = ERROR_TEXT;
      PARAMS_NAME = 'Юридический адрес';
      ERROR_TYPE = 3;
      SUSPEND;
    END
    ELSE IF(EXISTS(
      SELECT 1
      FROM VALA VA
      JOIN VALL VLL ON VLL.PARAM_ID = 8 AND VLL.IS_DEL = 0 AND VLL.OBJ_ID = VA.OBJ_ID AND VLL.LISTVAL_ID <> 1734 -- частое
      WHERE VA.PARAM_ID = 27 AND VA.OBJ_ID = :I$OBJ_ID AND VA.IS_DEL = 0 AND COALESCE(VA.FLAT, '') <> ''
    )) THEN
    BEGIN
      ERROR_TEXT = 'Поле «Квартира» в юридическом адресе государственного ОУ должно быть пустым';
      ERROR_NAME = ERROR_TEXT;
      PARAMS_NAME = 'Юридический адрес';
      ERROR_TYPE = 3;
      SUSPEND;
    END

    -- Отдельно проверяем статус ОУ, директор должен быть только для действующей ОУ
    IF(NOT EXISTS(
        SELECT FIRST 1 1
        FROM VALL V2371
        WHERE V2371.OBJ_ID = :I$OBJ_ID AND V2371.PARAM_ID = 2371 AND V2371.IS_DEL = 0 AND V2371.LISTVAL_ID IN (11184, 11185, 11186)
      )
      AND NOT EXISTS(
        SELECT FIRST 1 1
        FROM R_SPB_POST_DIRECTOR(:I$OBJ_ID, :I$USER_ID)
      )
    ) THEN
    BEGIN
      ERROR_TEXT = 'Не указан действующий (исполняющий обязанности) руководитель ОУ';
      ERROR_NAME = ERROR_TEXT;
      PARAMS_NAME = 'Руководитель образовательного учереждения';
      ERROR_TYPE = 3;
      SUSPEND;
    END

    -- 17 --
    IF (V$OU_LICENCE_TYPE <> 'U') THEN
    BEGIN
        V$TEMP = NULL;
        SELECT COUNT(L51.OBJ_ID)
        FROM LINKS L51
        WHERE L51.PARENT_ID = :I$OBJ_ID AND L51.OBJ_TYPE_ID = 51 AND L51.DATE_DEL IS NULL
        INTO :V$TEMP;

        IF (EXISTS(
            SELECT FIRST 1 1
            FROM VALL VLL
            WHERE VLL.PARAM_ID = 10 AND VLL.IS_DEL = 0 AND VLL.LISTVAL_ID IN (964, 2212, 970, 959, 960) AND VLL.OBJ_ID = :I$OBJ_ID
        )) THEN
        BEGIN
            IF (V$TEMP = 0) THEN
            BEGIN
                ERROR_TEXT = 'Не указаны предметы, изучаемые углубленно';
                ERROR_NAME = ERROR_TEXT;
                PARAMS_NAME = 'Предмет';
                ERROR_TYPE = 2;
                SUSPEND;
            END
        END
        ELSE IF (V$TEMP > 0) THEN
        BEGIN
            SELECT V
            FROM VAL_GET(:I$OBJ_ID, 10, 0, :I$USER_ID)
            INTO :ERROR_NAME;

            ERROR_TEXT = 'Для ОУ вида «' || ERROR_NAME || '» список «Углубленное изучение предметов» должен быть пуст';
            ERROR_NAME = ERROR_TEXT;
            PARAMS_NAME = 'Углубленное изучение предметов';
            ERROR_TYPE = 2;
            SUSPEND;
        END

        IF (V$TEMP > 10) THEN
        BEGIN
            ERROR_TEXT = 'Список предметов, изучаемых углубленно, не может содержать более 10 предметов';
            ERROR_NAME = ERROR_TEXT;
            PARAMS_NAME = 'Предмет';
            ERROR_TYPE = 2;
            SUSPEND;
        END
    END

    N = 0;
    FOR
      SELECT L16.OBJ_ID, L16.LINK_ID, L16.PARENT_ID, L16.OBJ_TYPE_ID
      FROM LINKS L73
      JOIN LINKS L16 ON L16.PARENT_ID = L73.OBJ_ID AND L16.OBJ_TYPE_ID IN (16, 492) AND L16.DATE_DEL IS NULL
      WHERE L73.DATE_DEL IS NULL AND L73.PARENT_ID = :I$OBJ_ID AND L73.OBJ_TYPE_ID = 73
      INTO :OBJECT_ID, :LINK_ID, :PARENT_ID, :V$TYPE_ID
    DO
    BEGIN
      SELECT CAPTION FROM OBJECT_CAPTION_GET(:OBJECT_ID, NULL, NULL, :I$USER_ID) INTO :S;
      IF(V$TYPE_ID = 16) THEN N = N + 1;

      -- !!! проверить по списку полей обязательность
      -- 504, 505, 542, 508, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 509, 510, 511, 512, 520, 522, 521
      FOR
        SELECT ERROR_TYPE, ERROR_TEXT, ERROR_NAME, PARAMS_NAME, PARAM_ID
        FROM VERIFY_OBJECT_FIELDS(:OBJECT_ID, :V$TYPE_ID, IIF(:V$TYPE_ID = 16, 'здания', 'объекта инфраструктуры'), :S)
        INTO :ERROR_TYPE, :ERROR_TEXT, :ERROR_NAME, :PARAMS_NAME, :V$PARAM_ID
      DO
      BEGIN
        SUSPEND;
      END
    END
    IF(N = 0) THEN
    BEGIN
      ERROR_TEXT = 'Должно быть введено хотя бы одно здание образовательного учреждения';
      ERROR_NAME = ERROR_TEXT;
      PARAMS_NAME = 'Здание';
      ERROR_TYPE = 3;
      SUSPEND;
    END

    -- Помещения зданий
    FOR
      SELECT L61.OBJ_ID, L61.LINK_ID, L61.PARENT_ID, L61.OBJ_TYPE_ID
      FROM LINKS L73
      JOIN LINKS L16 ON L16.PARENT_ID = L73.OBJ_ID AND L16.OBJ_TYPE_ID = 16 AND L16.DATE_DEL IS NULL
      JOIN LINKS L61 ON L61.PARENT_ID = L73.OBJ_ID AND L61.OBJ_TYPE_ID = 61 AND L61.DATE_DEL IS NULL
      WHERE L73.DATE_DEL IS NULL AND L73.PARENT_ID = :I$OBJ_ID AND L73.OBJ_TYPE_ID = 73
      INTO :OBJECT_ID, :LINK_ID, :PARENT_ID, :V$TYPE_ID
    DO
    BEGIN
      SELECT CAPTION FROM OBJECT_CAPTION_GET(:OBJECT_ID, NULL, NULL, :I$USER_ID) INTO :S;
      FOR
        SELECT ERROR_TYPE, ERROR_TEXT, ERROR_NAME, PARAMS_NAME
        FROM VERIFY_OBJECT_FIELDS(:OBJECT_ID, :V$TYPE_ID, 'помещения', :S)
        INTO :ERROR_TYPE, :ERROR_TEXT, :ERROR_NAME, :PARAMS_NAME
      DO
      BEGIN
        SUSPEND;
      END
    END

    -- Служебное сообщение об успешности проверок
    IF(ERROR_TYPE = 0) THEN
    BEGIN
      ERROR_TEXT = 'Данные успешно верифицированы, замечаний и ошибок нет';
      ERROR_NAME = 'Без замечаний';
      PARAMS_NAME = NAME_TASK;
      SUSPEND;
    END

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE VERIFY_BUILDING_DICT (
    I$LEVEL_ID BIGINT)
RETURNS (
    TYPE_ID BIGINT,
    TYPE_NAME VARCHAR(400),
    PARAM_ID BIGINT,
    PARAM_NAME VARCHAR(400),
    PARAM_TYPE_ID BIGINT,
    PARAM_TYPE_NAME VARCHAR(100),
    VAL_REQUIRED SMALLINT,
    VAL_CHECK SMALLINT,
    VAL_MASK VARCHAR(400),
    VAL_EXTRA VARCHAR(400))
AS
begin

  -- Проверяем что LEVEL_ID допустимый
  IF(NOT EXISTS(
    SELECT FIRST 1 1
    FROM LEVELS L
    JOIN TASKS T ON T.TASK_ID = L.TASK_ID AND T.IS_DEL = 0
    JOIN MODULES M ON M.MODULE_ID = T.MODULE_ID AND M.IS_DEL = 0 AND M.IS_ACTIVE = 1
    WHERE L.LEVEL_ID = :I$LEVEL_ID AND L.IS_DEL = 0
  ))
  THEN
    EXCEPTION DATA_ERROR 'Недопустимое приложение для контроля';

  -- Поля для объектов: здание, помещение, объект недвижимости
  -- заполняемые в данном приложении (RW)
  FOR
    SELECT P.TYPE_ID, P.PARAM_ID, P.PARAM_TYPE, RT.VAL, RP.VAL, P.IS_REQUIRED, IIF(P.DO_CHECK = 0, 0, 1), P.EDIT_MASK
    FROM PARAMS P
    JOIN LPARAMS LP ON LP.PARAM_ID = P.PARAM_ID AND LP.LEVEL_ID = :I$LEVEL_ID AND LP.IS_DEL = 0 AND LP.EDIT_TYPE = 1
    JOIN TYPES T ON T.TYPE_ID = P.TYPE_ID AND T.IS_DEL = 0
    JOIN RES RT ON RT.RES_ID = T.RES_ID AND RT.LANG_CODE = 'RU'
    JOIN RES RP ON RP.RES_ID = P.RES_ID AND RP.LANG_CODE = 'RU'
    WHERE P.TYPE_ID IN (16, 490, 492) AND P.IS_DEL = 0
      AND (P.IS_REQUIRED = 1 OR (P.EDIT_MASK IS NOT NULL AND P.EDIT_MASK <> ''))
    ORDER BY T.SORT_ORDER, P.GRID_ORDER
    INTO :TYPE_ID, :PARAM_ID, :PARAM_TYPE_ID, :TYPE_NAME, :PARAM_NAME, :VAL_REQUIRED, :VAL_CHECK, :VAL_MASK
  DO
  BEGIN
    IF(VAL_MASK = '') THEN VAL_MASK = NULL;

    IF(PARAM_TYPE_ID = 1) THEN PARAM_TYPE_NAME = 'Целое число';
    ELSE IF(PARAM_TYPE_ID = 2) THEN PARAM_TYPE_NAME = 'Вещественное число';
    ELSE IF(PARAM_TYPE_ID = 3) THEN PARAM_TYPE_NAME = 'Дата и время';
    ELSE IF(PARAM_TYPE_ID = 4) THEN PARAM_TYPE_NAME = 'Дата';
    ELSE IF(PARAM_TYPE_ID = 5) THEN PARAM_TYPE_NAME = 'Время';
    ELSE IF(PARAM_TYPE_ID = 6) THEN PARAM_TYPE_NAME = 'Значение из справочника';
    ELSE IF(PARAM_TYPE_ID = 7) THEN PARAM_TYPE_NAME = 'Строка или значение из справочника';
    ELSE IF(PARAM_TYPE_ID = 8) THEN PARAM_TYPE_NAME = 'Строка';
    ELSE IF(PARAM_TYPE_ID = 11) THEN PARAM_TYPE_NAME = 'Файл';
    ELSE IF(PARAM_TYPE_ID = 12) THEN PARAM_TYPE_NAME = 'Изображение';
    ELSE IF(PARAM_TYPE_ID = 13) THEN PARAM_TYPE_NAME = 'Ссылка на объект';
    ELSE IF(PARAM_TYPE_ID = 18) THEN PARAM_TYPE_NAME = 'Адрес';
    ELSE PARAM_TYPE_NAME = 'Недопустимый тип';

    VAL_EXTRA = NULL;
    -- IF(PARAM_ID IN (589)) THEN VAL_EXTRA = 'Уникальность';

    SUSPEND;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE VERIFY_CLASS (
    I$OBJ_ID BIGINT)
RETURNS (
    LINK_ID BIGINT,
    OBJECT_ID BIGINT,
    PARENT_ID BIGINT,
    NAME_TASK VARCHAR(1000),
    ERROR_NAME VARCHAR(1000),
    PARAMS_NAME VARCHAR(1000),
    ERROR_TEXT VARCHAR(1000),
    ERROR_TYPE SMALLINT)
AS
DECLARE VARIABLE I INTEGER;
DECLARE VARIABLE S VARCHAR(1000);
DECLARE VARIABLE SS VARCHAR(100);
DECLARE VARIABLE CLASS_OBJECT_ID BIGINT;
DECLARE VARIABLE CLASS_LINK_ID BIGINT;
DECLARE VARIABLE OBJ_ID BIGINT;
DECLARE VARIABLE V$TYPE_ID BIGINT;
DECLARE VARIABLE V$LEVEL_ID BIGINT;
BEGIN
    NAME_TASK = 'Учебные коллективы';
    ERROR_TYPE = 0;

    FOR
      SELECT L7.OBJ_ID, L7.OBJ_TYPE_ID, L7.LINK_ID, L7.PARENT_ID, NULL
      FROM LINKS L7
      WHERE L7.PARENT_ID = :I$OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
      UNION
      -- тут же берем предварительный прием
      SELECT L8.OBJ_ID, L8.OBJ_TYPE_ID, L8.LINK_ID, L8.PARENT_ID, NULL
      FROM LINKS L7
      JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID IN (8, 290) AND L8.DATE_DEL IS NULL
      WHERE L7.PARENT_ID = :I$OBJ_ID AND L7.OBJ_TYPE_ID IN (7, 77) AND L7.DATE_DEL IS NULL
      UNION
      SELECT L9.OBJ_ID, L9.OBJ_TYPE_ID, L9.LINK_ID, L9.PARENT_ID, V43.LISTVAL_ID
      FROM LINKS L7
      LEFT JOIN VALL V43 ON V43.OBJ_ID = L7.OBJ_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0
      JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 187, 125, 403) AND L9.DATE_DEL IS NULL
      WHERE L7.PARENT_ID = :I$OBJ_ID AND L7.OBJ_TYPE_ID IN (7, 502) AND L7.DATE_DEL IS NULL
      INTO :OBJECT_ID, :V$TYPE_ID, :LINK_ID, :PARENT_ID, :V$LEVEL_ID
    DO
    BEGIN
      IF(V$TYPE_ID = 7) THEN SS = 'уровня образования';
      ELSE IF(V$TYPE_ID = 8) THEN SS = 'этапа обучения';
      ELSE IF(V$TYPE_ID = 9) THEN SS = 'учебного коллектива';
      ELSE IF(V$TYPE_ID = 290) THEN SS = 'этапа преварительного приема';
      ELSE IF(V$TYPE_ID = 403) THEN SS = 'будущего учебного коллектива';
      ELSE IF(V$TYPE_ID = 187) THEN SS = 'класса-экстерната';
      ELSE IF(V$TYPE_ID = 125) THEN SS = 'класса сдачи ГИА';
      ELSE SS = '#' || V$TYPE_ID;

      SELECT CAPTION FROM OBJECT_CAPTION_GET(:OBJECT_ID) INTO :S;

      FOR
        SELECT ERROR_TYPE, ERROR_TEXT, ERROR_NAME, PARAMS_NAME
        FROM VERIFY_OBJECT_FIELDS(:OBJECT_ID, :V$TYPE_ID, :SS, :S)
        INTO :ERROR_TYPE, :ERROR_TEXT, :ERROR_NAME, :PARAMS_NAME
      DO
      BEGIN
        SUSPEND;
      END

      -- Требуем чтобы классный руководитель был заполнен всегда кроме июля и августа
      -- для групп ДОУ проверяем наличие воспитателей
      IF(V$TYPE_ID = 9 AND EXTRACT(MONTH FROM CURRENT_DATE) NOT IN (7, 8)) THEN
      BEGIN
        IF(V$LEVEL_ID IN (22, 26, 27, 28, 29) AND NOT EXISTS(SELECT 1 FROM VALR V WHERE V.OBJ_ID = :OBJECT_ID AND V.PARAM_ID = 53 AND V.IS_DEL = 0)) THEN
        BEGIN
          ERROR_TEXT = 'Для "' || S || '" не указан классный руководитель (куратор группы, воспитатель)';
          ERROR_NAME = 'Не указан классный руководитель (куратор группы, воспитатель)';
          PARAMS_NAME = 'Учебный коллектив';
          ERROR_TYPE = 3; -- 2, повышено 10.01.2025 из-за вероятного слетания
          SUSPEND;
        END
        IF(V$LEVEL_ID IN (21, 3263, 3264) AND NOT EXISTS(
          SELECT 1
          FROM LINKS L165
          JOIN VALR V1556 ON V1556.OBJ_ID = L165.OBJ_ID AND V1556.PARAM_ID = 1556 AND V1556.IS_DEL = 0
          WHERE L165.PARENT_ID = :OBJ_ID AND L165.OBJ_TYPE_ID = 165 AND L165.DATE_DEL IS NULL
        )) THEN
        BEGIN
          ERROR_TEXT = 'Для "' || S || '" не указан классный руководитель (куратор группы, воспитатель)';
          ERROR_NAME = 'Не указан классный руководитель (куратор группы, воспитатель)';
          PARAMS_NAME = 'Учебный коллектив';
          ERROR_TYPE = 3; -- 2, повышено 10.01.2025 из-за вероятного слетания
          SUSPEND;
        END
      END

      -- Дубли учебных коллективов по названию в текущем году
      -- будущие названия пусть проверяет перевод года, это долго
      IF(V$TYPE_ID = 9) THEN
      BEGIN
        IF(EXISTS(
          SELECT FIRST 1 1
          FROM LINKS L7
          JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
          JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 187, 125) AND L9.DATE_DEL IS NULL AND L9.OBJ_ID > :OBJECT_ID
          LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C ON 1 = 1
          WHERE L7.PARENT_ID = :I$OBJ_ID AND L7.OBJ_TYPE_ID IN (7, 502) AND L7.DATE_DEL IS NULL AND C.CAPTION = :S
        )) THEN
        BEGIN
          ERROR_TEXT = 'Существуют два учебных коллектива с кодом ' || S;
          ERROR_NAME = 'Существуют два учебных коллектива с одинаковым кодом';
          PARAMS_NAME = 'Учебный коллектив';
          ERROR_TYPE = 3;
          SUSPEND;
        END
      END
    END

    -- Служебное сообщение об успешности проверок
    IF(ERROR_TYPE = 0) THEN
    BEGIN
      ERROR_TEXT = 'Данные успешно верифицированы, замечаний и ошибок нет';
      ERROR_NAME = 'Без замечаний';
      PARAMS_NAME = NAME_TASK;
      PARENT_ID = I$OBJ_ID;
      OBJECT_ID = NULL;
      LINK_ID = NULL;
      SUSPEND;
    END

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE VERIFY_CLASS_DICT (
    I$LEVEL_ID BIGINT)
RETURNS (
    TYPE_ID BIGINT,
    TYPE_NAME VARCHAR(400),
    PARAM_ID BIGINT,
    PARAM_NAME VARCHAR(400),
    PARAM_TYPE_ID BIGINT,
    PARAM_TYPE_NAME VARCHAR(100),
    VAL_REQUIRED SMALLINT,
    VAL_CHECK SMALLINT,
    VAL_MASK VARCHAR(400),
    VAL_EXTRA VARCHAR(400))
AS
begin

  -- Проверяем что LEVEL_ID допустимый
  IF(NOT EXISTS(
    SELECT FIRST 1 1
    FROM LEVELS L
    JOIN TASKS T ON T.TASK_ID = L.TASK_ID AND T.IS_DEL = 0
    JOIN MODULES M ON M.MODULE_ID = T.MODULE_ID AND M.IS_DEL = 0 AND M.IS_ACTIVE = 1
    WHERE L.LEVEL_ID = :I$LEVEL_ID AND L.IS_DEL = 0
  ))
  THEN
    EXCEPTION DATA_ERROR 'Недопустимое приложение для контроля';

  -- Поля для объектов: уровень-этап-класс, экстернат, класс ГИА, предварительный прием, будущие классы
  -- заполняемые в данном приложении (RW)
  FOR
    SELECT P.TYPE_ID, P.PARAM_ID, P.PARAM_TYPE, RT.VAL, RP.VAL, P.IS_REQUIRED, IIF(P.DO_CHECK = 0, 0, 1), P.EDIT_MASK
    FROM PARAMS P
    JOIN LPARAMS LP ON LP.PARAM_ID = P.PARAM_ID AND LP.LEVEL_ID = :I$LEVEL_ID AND LP.IS_DEL = 0 AND LP.EDIT_TYPE = 1
    JOIN TYPES T ON T.TYPE_ID = P.TYPE_ID AND T.IS_DEL = 0
    JOIN RES RT ON RT.RES_ID = T.RES_ID AND RT.LANG_CODE = 'RU'
    JOIN RES RP ON RP.RES_ID = P.RES_ID AND RP.LANG_CODE = 'RU'
    WHERE P.TYPE_ID IN (7, 8, 9, 187, 125, 403, 290) AND P.IS_DEL = 0
      AND (P.IS_REQUIRED = 1 OR (P.EDIT_MASK IS NOT NULL AND P.EDIT_MASK <> '') OR P.PARAM_ID IN (53, 54))
    ORDER BY T.SORT_ORDER, P.GRID_ORDER
    INTO :TYPE_ID, :PARAM_ID, :PARAM_TYPE_ID, :TYPE_NAME, :PARAM_NAME, :VAL_REQUIRED, :VAL_CHECK, :VAL_MASK
  DO
  BEGIN
    IF(VAL_MASK = '') THEN VAL_MASK = NULL;

    IF(PARAM_TYPE_ID = 1) THEN PARAM_TYPE_NAME = 'Целое число';
    ELSE IF(PARAM_TYPE_ID = 2) THEN PARAM_TYPE_NAME = 'Вещественное число';
    ELSE IF(PARAM_TYPE_ID = 3) THEN PARAM_TYPE_NAME = 'Дата и время';
    ELSE IF(PARAM_TYPE_ID = 4) THEN PARAM_TYPE_NAME = 'Дата';
    ELSE IF(PARAM_TYPE_ID = 5) THEN PARAM_TYPE_NAME = 'Время';
    ELSE IF(PARAM_TYPE_ID = 6) THEN PARAM_TYPE_NAME = 'Значение из справочника';
    ELSE IF(PARAM_TYPE_ID = 7) THEN PARAM_TYPE_NAME = 'Строка или значение из справочника';
    ELSE IF(PARAM_TYPE_ID = 8) THEN PARAM_TYPE_NAME = 'Строка';
    ELSE IF(PARAM_TYPE_ID = 11) THEN PARAM_TYPE_NAME = 'Файл';
    ELSE IF(PARAM_TYPE_ID = 12) THEN PARAM_TYPE_NAME = 'Изображение';
    ELSE IF(PARAM_TYPE_ID = 13) THEN PARAM_TYPE_NAME = 'Ссылка на объект';
    ELSE IF(PARAM_TYPE_ID = 18) THEN PARAM_TYPE_NAME = 'Адрес';
    ELSE PARAM_TYPE_NAME = 'Недопустимый тип';

    VAL_EXTRA = NULL;
    IF(PARAM_ID = 54) THEN VAL_EXTRA = 'Уникальный';
    IF(PARAM_ID = 53) THEN VAL_EXTRA = 'Обязательно кроме июля и августа';

    SUSPEND;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE VERIFY_CURRENT_CLASS (
    I$CLASS_ID BIGINT,
    I$CURRSUFFIX VARCHAR(400))
AS
declare variable V$PARENT_ID bigint;
declare variable V$TYPE_ID bigint;
declare variable V$COST integer;
declare variable V$SUFFIX varchar(400);
declare variable V$ACT varchar(400);
declare variable P integer;
declare variable V$OLD varchar(400);
declare variable V$NEW varchar(400);
declare variable V$NEWACT varchar(400);
declare variable V$CLASS_TYPE bigint;
declare variable V$STAGE integer;
declare variable V$MATCH_STAGE smallint;
begin

  SELECT LP2.PARENT_ID, LP8.OBJ_TYPE_ID, LV.COST, COALESCE(V3118.VAL, '')
  FROM LINKS LP8
  JOIN VALL V49 ON V49.OBJ_ID = LP8.PARENT_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V49.LISTVAL_ID
  JOIN LINKS LP7 ON LP7.OBJ_ID = LP8.PARENT_ID AND LP7.PARENT_TYPE_ID = 7 AND LP7.DATE_DEL IS NULL
  JOIN LINKS LP2 ON LP2.OBJ_ID = LP7.PARENT_ID AND LP2.PARENT_TYPE_ID = 2 AND LP2.DATE_DEL IS NULL
  LEFT JOIN VALS V3118 ON V3118.OBJ_ID = LP8.OBJ_ID AND V3118.PARAM_ID = 3118 AND V3118.IS_DEL = 0
  WHERE LP8.OBJ_ID = :I$CLASS_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
  INTO :V$PARENT_ID, :V$TYPE_ID, :V$COST, :V$SUFFIX;

  -- Сначала проверяем дублирование текущего названия
  IF(EXISTS(
      SELECT FIRST 1 1
      FROM LINKS L7
      JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
      JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
      JOIN LISTVALS LV ON LV.LISTVAL_ID = V49.LISTVAL_ID AND LV.COST = :V$COST
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 187) AND L9.DATE_DEL IS NULL AND L9.OBJ_ID <> :I$CLASS_ID
      LEFT JOIN VALS VC ON VC.OBJ_ID = L9.OBJ_ID AND VC.PARAM_ID IN (54, 1652) AND VC.IS_DEL = 0
      WHERE L7.PARENT_ID = :V$PARENT_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL AND COALESCE(VC.VAL, '') = COALESCE(:I$CURRSUFFIX, '')
  ))
  THEN EXCEPTION DATA_ERROR 'Класс/группа с таким наименованием уже есть. Выберите другое наименование';

  V$ACT = '';
  P = POSITION(';' IN V$SUFFIX);
  IF(P > 0) THEN
  BEGIN
      V$ACT = SUBSTRING(V$SUFFIX FROM P + 1);
      V$SUFFIX = SUBSTRING(V$SUFFIX FROM 1 FOR P - 1);
  END
  IF(V$SUFFIX = '') THEN V$SUFFIX = I$CURRSUFFIX;

  -- Если класс удаляется - и хрен с ним
  IF(V$SUFFIX = '*') THEN EXIT;

  -- Если это класс, меняющий параллель - корректируем номер года
  IF(V$TYPE_ID = 9 AND V$ACT <> '@' AND V$ACT <> 'X') THEN V$COST = V$COST + 1;

  FOR
      SELECT COALESCE(VC.VAL, ''), COALESCE(VF.VAL, ''), L9.OBJ_TYPE_ID, LV.COST
      FROM LINKS L7
      JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
      JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
      JOIN LISTVALS LV ON LV.LISTVAL_ID = V49.LISTVAL_ID
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 187, 403) AND L9.DATE_DEL IS NULL AND L9.OBJ_ID <> :I$CLASS_ID
      LEFT JOIN VALS VC ON VC.OBJ_ID = L9.OBJ_ID AND VC.PARAM_ID IN (54, 1652) AND VC.IS_DEL = 0 -- текущее название
      LEFT JOIN VALS VF ON VF.OBJ_ID = L9.OBJ_ID AND VF.PARAM_ID IN (3118, 3026) AND VF.IS_DEL = 0 -- будущее название
      WHERE L7.PARENT_ID = :V$PARENT_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
      ORDER BY LV.COST, 1
      INTO :V$OLD, :V$NEW, :V$CLASS_TYPE, :V$STAGE
  DO
  BEGIN
      V$NEWACT = '';
      P = POSITION(';' IN V$NEW);
      IF(P > 0) THEN
      BEGIN
          V$NEWACT = SUBSTRING(V$NEW FROM P + 1);
          V$NEW = SUBSTRING(V$NEW FROM 1 FOR P - 1);
      END
      IF(V$CLASS_TYPE = 9 AND V$NEW = '') THEN V$NEW = V$OLD;

      -- Проверяем параллель
      V$MATCH_STAGE = 0;
      IF(V$CLASS_TYPE = 403 AND V$STAGE = V$COST) THEN V$MATCH_STAGE = 1;      -- новые классы и так в нужной параллели
      ELSE IF(V$CLASS_TYPE = 187 AND V$STAGE = V$COST) THEN V$MATCH_STAGE = 1; -- классы-экстернаты остаются на своем месте
      ELSE IF(V$CLASS_TYPE = 9 AND V$NEWACT IN ('', '^', '1', '2') AND V$STAGE = V$COST - 1) THEN V$MATCH_STAGE = 1; -- обычные классы и классы ОВЗ, меняющие год
      ELSE IF(V$CLASS_TYPE = 9 AND V$NEWACT IN ('@', 'X') AND V$STAGE = V$COST) THEN V$MATCH_STAGE = 1; -- классы ОВЗ, не меняющие год

      -- Если класс удаляется - и черт с ним
      IF(V$MATCH_STAGE = 1 AND V$NEW <> '*') THEN
      BEGIN
          IF(V$SUFFIX = V$NEW) THEN EXCEPTION DATA_ERROR 'Нельзя использовать это наименование, оно указано в другом классе/группе в качестве наименования в будущем году. Проверьте схему перевода года для классов ОВЗ';
      END
  END

  -- Корректируем название в реестрах движения для последней строки
  SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$CLASS_ID) INTO :V$NEW;
  IF(POSITION(' ' IN V$NEW) > 0) THEN V$NEW = SUBSTRING(V$NEW FROM 1 FOR POSITION(' ' IN V$NEW) - 1);
  IF(I$CURRSUFFIX IS NOT NULL) THEN V$NEW = V$NEW || ' ' || I$CURRSUFFIX;

  UPDATE PERSON_MOVEMENTS M
  SET NAME_IN = :V$NEW
  WHERE M.DATE_DEL IS NULL AND M.DATE_OUT IS NULL AND M.GROUP_ID = :I$CLASS_ID;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE VERIFY_DOCS (
    I$OBJ_ID BIGINT)
RETURNS (
    LINK_ID BIGINT,
    OBJECT_ID BIGINT,
    PARENT_ID BIGINT,
    NAME_TASK VARCHAR(1000),
    ERROR_NAME VARCHAR(1000),
    PARAMS_NAME VARCHAR(1000),
    ERROR_TEXT VARCHAR(1000),
    ERROR_TYPE SMALLINT)
AS
DECLARE VARIABLE V$PARAM_ID BIGINT;
DECLARE VARIABLE S VARCHAR(1000);
DECLARE VARIABLE N INTEGER;
BEGIN
    NAME_TASK = 'Документы образовательного учреждения';
    ERROR_TYPE = 0;

    -- Проверяем только ограниченный набор полей самой ОУ, остальные проверяем в BUILDING
    -- незаполнение счетов (13, 470) является warning
    SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$OBJ_ID) INTO :S;

    FOR
      SELECT ERROR_TYPE, ERROR_TEXT, ERROR_NAME, PARAMS_NAME, PARAM_ID
      FROM VERIFY_OBJECT_FIELDS(:I$OBJ_ID, 2, 'ОУ', :S)
      WHERE PARAM_ID IN (9, 13, 16, 18, 19, 20, 21, 22, 33, 470)
      INTO :ERROR_TYPE, :ERROR_TEXT, :ERROR_NAME, :PARAMS_NAME, :V$PARAM_ID
    DO
    BEGIN
      IF(V$PARAM_ID IN (13, 470)) THEN ERROR_TYPE = 2;
      SUSPEND;
    END

    -- Учредители
    N = 0;
    FOR
        SELECT L5.OBJ_ID, L5.LINK_ID, L5.PARENT_ID
        FROM LINKS L5
        WHERE L5.DATE_DEL IS NULL AND L5.OBJ_TYPE_ID = 5 AND L5.PARENT_ID = :I$OBJ_ID
        INTO :OBJECT_ID, :LINK_ID, :PARENT_ID
    DO
    BEGIN
      N = N + 1;
      -- Добавить исправление двойных пробелов и TRIM
      FOR
        SELECT ERROR_TYPE, ERROR_TEXT, ERROR_NAME, PARAMS_NAME
        FROM VERIFY_OBJECT_FIELDS(:OBJECT_ID, 5, 'учредителя', :S)
        INTO :ERROR_TYPE, :ERROR_TEXT, :ERROR_NAME, :PARAMS_NAME
      DO
      BEGIN
        SUSPEND;
      END
    END
    IF (N = 0) THEN
    BEGIN
        ERROR_TEXT = 'Не указаны учредители образовательного учреждения';
        ERROR_NAME = ERROR_TEXT;
        PARAMS_NAME = 'Список учредителей';
        ERROR_TYPE = 2;
        SUSPEND;
    END

    -- Документы, сразу подсчитываем по типам
    FOR
        SELECT L17.OBJ_ID, L17.LINK_ID, L17.PARENT_ID
        FROM LINKS L17
        WHERE L17.DATE_DEL IS NULL AND L17.OBJ_TYPE_ID = 17 AND L17.PARENT_ID = :I$OBJ_ID
        INTO :OBJECT_ID, :LINK_ID, :PARENT_ID
    DO
    BEGIN
      SELECT CAPTION FROM OBJECT_CAPTION_GET(:OBJECT_ID) INTO :S;
      FOR
        SELECT ERROR_TYPE, ERROR_TEXT, ERROR_NAME, PARAMS_NAME
        FROM VERIFY_OBJECT_FIELDS(:OBJECT_ID, 17, 'документа ОООД', :S)
        INTO :ERROR_TYPE, :ERROR_TEXT, :ERROR_NAME, :PARAMS_NAME
      DO
      BEGIN
        SUSPEND;
      END
      IF (EXISTS(
        SELECT FIRST 1 1
        FROM VALD V
        JOIN VALL VS ON VS.OBJ_ID = V.PARAM_ID AND VS.PARAM_ID = 613 AND VS.IS_DEL = 0 AND VS.LISTVAL_ID IN (1982, 1984)
        WHERE V.PARAM_ID = 483 AND V.OBJ_ID = :OBJECT_ID AND V.VAL < CURRENT_TIMESTAMP)) THEN
      BEGIN
        ERROR_TEXT = 'Дата окончания действия документа «' || S || '» прошла. Необходимо изменить статус документа.';
        ERROR_NAME = 'Дата окончания действия документа прошла. Необходимо изменить статус документа.';
        PARAMS_NAME = 'Документы';
        ERROR_TYPE = 2;
        SUSPEND;
      END
    END

    -- Проверка документов по типам
    -- устав
    IF (NOT EXISTS(
      SELECT FIRST 1 1 FROM LINKS L17
      JOIN VALL VL ON VL.OBJ_ID = L17.OBJ_ID AND VL.IS_DEL = 0 AND VL.PARAM_ID = 471 AND VL.LISTVAL_ID = 1047
      WHERE DATE_DEL IS NULL AND OBJ_TYPE_ID = 17 AND PARENT_ID = :I$OBJ_ID
    )) THEN
    BEGIN
      ERROR_TEXT = 'Нет документа с типом Устав';
      ERROR_NAME = ERROR_TEXT;
      PARAMS_NAME = 'Устав';
      ERROR_TYPE = 3;
      SUSPEND;
    END
    -- лицензия
    IF (NOT EXISTS(
      SELECT FIRST 1 1
      FROM LINKS L17
      JOIN VALL VL ON VL.OBJ_ID = L17.OBJ_ID AND VL.IS_DEL = 0 AND VL.PARAM_ID = 471 AND VL.LISTVAL_ID IN (1052, 18624)
      JOIN VALL V ON V.OBJ_ID = L17.OBJ_ID AND V.IS_DEL = 0 AND V.PARAM_ID = 613 AND V.LISTVAL_ID IN (1982, 1984)
      WHERE DATE_DEL IS NULL AND OBJ_TYPE_ID = 17 AND PARENT_ID = :I$OBJ_ID
    )) THEN
    BEGIN
      ERROR_TEXT = 'Нет документа с типом Лицензия';
      ERROR_NAME = ERROR_TEXT;
      PARAMS_NAME = 'Лицензия';
      ERROR_TYPE = 3;
      SUSPEND;
    END
    -- приложение к лицензии
    IF (NOT EXISTS(
      SELECT FIRST 1 1
      FROM LINKS L17
      JOIN VALL VL ON VL.OBJ_ID = L17.OBJ_ID AND VL.IS_DEL = 0 AND VL.PARAM_ID = 471 AND VL.LISTVAL_ID = 1079
      WHERE DATE_DEL IS NULL AND OBJ_TYPE_ID = 17 AND PARENT_ID = :I$OBJ_ID
    )) THEN
    BEGIN
      ERROR_TEXT = 'Нет документа с типом Приложение к лицензии';
      ERROR_NAME = ERROR_TEXT;
      PARAMS_NAME = 'Приложение к лицензии';
      ERROR_TYPE = 3;
      SUSPEND;
    END
    ERROR_NAME = 'Отсутствуют документы ОУ';
    /*IF (NOT EXISTS(
      SELECT FIRST 1 1
      FROM LINKS L17
      JOIN VALL VL ON VL.OBJ_ID = L17.OBJ_ID AND VL.IS_DEL = 0 AND VL.PARAM_ID = 471 AND VL.LISTVAL_ID = 1053
      WHERE DATE_DEL IS NULL AND OBJ_TYPE_ID = 17 AND PARENT_ID = :I$OBJ_ID
    )) THEN
    BEGIN
        ERROR_TEXT = 'Нет документа с типом Свидетельство о государственной аккредитации';
        PARAMS_NAME = 'Свидетельство о государственной аккредитации';
        ERROR_TYPE = 3;
        SUSPEND;
    END*/
    IF (NOT EXISTS(
      SELECT FIRST 1 1
      FROM LINKS L17
      JOIN VALL VL ON VL.OBJ_ID = L17.OBJ_ID AND VL.IS_DEL = 0 AND VL.PARAM_ID = 471 AND VL.LISTVAL_ID = 1051
      WHERE DATE_DEL IS NULL AND OBJ_TYPE_ID = 17 AND PARENT_ID = :I$OBJ_ID
    )) THEN
    BEGIN
        ERROR_TEXT = 'Нет документа с типом Свидетельство о внесении в Реестр собственности Санкт-Петербурга';
        PARAMS_NAME = 'Свидетельство о внесении в Реестр собственности Санкт-Петербурга';
        ERROR_TYPE = 2;
        SUSPEND;
    END
    IF (NOT EXISTS(
      SELECT FIRST 1 1
      FROM LINKS L17
      JOIN VALL VL ON VL.OBJ_ID = L17.OBJ_ID AND VL.IS_DEL = 0 AND VL.PARAM_ID = 471 AND VL.LISTVAL_ID = 1050
      WHERE DATE_DEL IS NULL AND OBJ_TYPE_ID = 17 AND PARENT_ID = :I$OBJ_ID
    )) THEN
    BEGIN
        ERROR_TEXT = 'Нет документа с типом Свидетельство о праве землепользования';
        PARAMS_NAME = 'Свидетельство о праве землепользования';
        ERROR_TYPE = 2;
        SUSPEND;
    END
    IF (NOT EXISTS(
      SELECT FIRST 1 1
      FROM LINKS L17
      JOIN VALL VL ON VL.OBJ_ID = L17.OBJ_ID AND VL.IS_DEL = 0 AND VL.PARAM_ID = 471 AND VL.LISTVAL_ID = 1049
       WHERE DATE_DEL IS NULL AND OBJ_TYPE_ID = 17 AND PARENT_ID = :I$OBJ_ID
    )) THEN
    BEGIN
      ERROR_TEXT = 'Нет документа с типом Свидетельство о постановке на учет в налоговом органе';
      PARAMS_NAME = 'Свидетельство о постановке на учет в налоговом органе';
      ERROR_TYPE = 3;
      SUSPEND;
    END

    -- Служебное сообщение об успешности проверок
    IF(ERROR_TYPE = 0) THEN
    BEGIN
      ERROR_TEXT = 'Данные успешно верифицированы, замечаний и ошибок нет';
      ERROR_NAME = 'Без замечаний';
      PARAMS_NAME = NAME_TASK;
      PARENT_ID = I$OBJ_ID;
      OBJECT_ID = NULL;
      LINK_ID = NULL;
      SUSPEND;
    END

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE VERIFY_DOCS_DICT (
    I$LEVEL_ID BIGINT)
RETURNS (
    TYPE_ID BIGINT,
    TYPE_NAME VARCHAR(400),
    PARAM_ID BIGINT,
    PARAM_NAME VARCHAR(400),
    PARAM_TYPE_ID BIGINT,
    PARAM_TYPE_NAME VARCHAR(100),
    VAL_REQUIRED SMALLINT,
    VAL_CHECK SMALLINT,
    VAL_MASK VARCHAR(400),
    VAL_EXTRA VARCHAR(400))
AS
begin

  -- Проверяем что LEVEL_ID допустимый
  IF(NOT EXISTS(
    SELECT FIRST 1 1
    FROM LEVELS L
    JOIN TASKS T ON T.TASK_ID = L.TASK_ID AND T.IS_DEL = 0
    JOIN MODULES M ON M.MODULE_ID = T.MODULE_ID AND M.IS_DEL = 0 AND M.IS_ACTIVE = 1
    WHERE L.LEVEL_ID = :I$LEVEL_ID AND L.IS_DEL = 0
  ))
  THEN
    EXCEPTION DATA_ERROR 'Недопустимое приложение для контроля';

  -- Поля для объектов: ОУ #2, учредители #5, документ ОУ #17, статус ЖЗЦ
  -- заполняемые в данном приложении (RW)
  -- !!! пропиcать параметры REQUIRED 13, 470, 16, 18, 19, 20, 21, 22
  FOR
    SELECT P.TYPE_ID, P.PARAM_ID, P.PARAM_TYPE, RT.VAL, RP.VAL, P.IS_REQUIRED, IIF(P.DO_CHECK = 0, 0, 1), P.EDIT_MASK
    FROM PARAMS P
    JOIN LPARAMS LP ON LP.PARAM_ID = P.PARAM_ID AND LP.LEVEL_ID = :I$LEVEL_ID AND LP.IS_DEL = 0 AND LP.EDIT_TYPE = 1
    JOIN TYPES T ON T.TYPE_ID = P.TYPE_ID AND T.IS_DEL = 0
    JOIN RES RT ON RT.RES_ID = T.RES_ID AND RT.LANG_CODE = 'RU'
    JOIN RES RP ON RP.RES_ID = P.RES_ID AND RP.LANG_CODE = 'RU'
    WHERE P.TYPE_ID IN (2, 5, 17, 497, 211, 212, 441, 442, 443, 444, 447, 453) AND P.IS_DEL = 0
      AND (P.IS_REQUIRED = 1 OR (P.EDIT_MASK IS NOT NULL AND P.EDIT_MASK <> '') OR P.PARAM_ID IN (483)) -- дата окончания действия
    ORDER BY T.SORT_ORDER, P.GRID_ORDER
    INTO :TYPE_ID, :PARAM_ID, :PARAM_TYPE_ID, :TYPE_NAME, :PARAM_NAME, :VAL_REQUIRED, :VAL_CHECK, :VAL_MASK
  DO
  BEGIN
    IF(VAL_MASK = '') THEN VAL_MASK = NULL;

    IF(PARAM_TYPE_ID = 1) THEN PARAM_TYPE_NAME = 'Целое число';
    ELSE IF(PARAM_TYPE_ID = 2) THEN PARAM_TYPE_NAME = 'Вещественное число';
    ELSE IF(PARAM_TYPE_ID = 3) THEN PARAM_TYPE_NAME = 'Дата и время';
    ELSE IF(PARAM_TYPE_ID = 4) THEN PARAM_TYPE_NAME = 'Дата';
    ELSE IF(PARAM_TYPE_ID = 5) THEN PARAM_TYPE_NAME = 'Время';
    ELSE IF(PARAM_TYPE_ID = 6) THEN PARAM_TYPE_NAME = 'Значение из справочника';
    ELSE IF(PARAM_TYPE_ID = 7) THEN PARAM_TYPE_NAME = 'Строка или значение из справочника';
    ELSE IF(PARAM_TYPE_ID = 8) THEN PARAM_TYPE_NAME = 'Строка';
    ELSE IF(PARAM_TYPE_ID = 11) THEN PARAM_TYPE_NAME = 'Файл';
    ELSE IF(PARAM_TYPE_ID = 12) THEN PARAM_TYPE_NAME = 'Изображение';
    ELSE IF(PARAM_TYPE_ID = 13) THEN PARAM_TYPE_NAME = 'Ссылка на объект';
    ELSE IF(PARAM_TYPE_ID = 18) THEN PARAM_TYPE_NAME = 'Адрес';
    ELSE PARAM_TYPE_NAME = 'Недопустимый тип';

    VAL_EXTRA = NULL;
    IF(PARAM_ID IN (9, 33)) THEN VAL_EXTRA = 'CHECKSUM';
    IF(PARAM_ID = 483) THEN VAL_EXTRA = 'Статус документа = не действующий';
    IF(PARAM_TYPE_ID = 8 AND TYPE_ID = 2 AND VAL_MASK IS NULL) THEN VAL_EXTRA = 'CLEANUP';

    SUSPEND;
  END

  -- Дополнительные формальные проверки связности и заполненности
  -- Учредители
  TYPE_ID = 5;
  TYPE_NAME = (SELECT TYPE_CAPTION FROM TYPE_CAPTION_GET(:TYPE_ID));
  PARAM_ID = NULL;
  PARAM_NAME = NULL;
  PARAM_TYPE_NAME = NULL;
  VAL_REQUIRED = 1;
  VAL_CHECK = NULL;
  VAL_MASK = NULL;
  VAL_EXTRA = 'ANY';
  SUSPEND;

  -- Документы ОУ
  TYPE_ID = 17;
  TYPE_NAME = (SELECT TYPE_CAPTION FROM TYPE_CAPTION_GET(:TYPE_ID));
  PARAM_ID = NULL;
  PARAM_NAME = NULL;
  VAL_REQUIRED = 1;
  VAL_CHECK = NULL;
  VAL_MASK = NULL;

  VAL_EXTRA = 'ANY @Устав';
  SUSPEND;

  VAL_EXTRA = 'ANY @Лицензия';
  SUSPEND;

  VAL_EXTRA = 'ANY @Приложение к лицензии';
  SUSPEND;

  --VAL_EXTRA = 'ANY @Свидетельство о государственной аккредитации';
  --SUSPEND;

  VAL_EXTRA = 'ANY @Устав';
  SUSPEND;

  VAL_EXTRA = 'ANY @Свидетельство о внесении в Реестр собственности Санкт-Петербурга';
  SUSPEND;

  VAL_EXTRA = 'ANY @Свидетельство о праве землепользования';
  SUSPEND;

  VAL_EXTRA = 'ANY @Свидетельство о постановке на учет в налоговом органе';
  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE VERIFY_FOOD_BENEFIT_APP_EXPORT (
    I$OBJ_ID BIGINT,
    I$USER_ID BIGINT)
RETURNS (
    LINK_ID BIGINT,
    OBJECT_ID BIGINT,
    NAME_TASK VARCHAR(1000),
    ERROR_NAME VARCHAR(1000),
    PARAMS_NAME VARCHAR(1000),
    ERROR_TEXT VARCHAR(1000),
    ERROR_TYPE SMALLINT)
AS
declare variable V$CLASS_NAME char(10);
declare variable V$FIO varchar(300);
declare variable V$REGION varchar(255);
declare variable V$TOWN varchar(255);
declare variable V$SETTLEMENT varchar(255);
declare variable V$STREET varchar(255);
declare variable V$HOUSE varchar(255);
declare variable V$FLAT varchar(255);
BEGIN
    NAME_TASK = 'Льготное питание';
    FOR
        SELECT L10.OBJ_ID,
               L10.LINK_ID,
               CC.CAPTION
        FROM LINKS L7

        JOIN LINKS L8
        ON L8.PARENT_ID = L7.OBJ_ID
        AND L8.OBJ_TYPE_ID = 8
        AND L8.DATE_DEL IS NULL

        JOIN LINKS L9
        ON L9.PARENT_ID = L8.OBJ_ID
        AND L9.OBJ_TYPE_ID IN (9,187)
        AND L9.DATE_DEL IS NULL

        LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID, 231, NULL, :I$USER_ID) CC ON 1=1

        JOIN LINKS L10
        ON L10.PARENT_ID = L9.OBJ_ID
        AND L10.OBJ_TYPE_ID = 10
        AND L10.DATE_DEL IS NULL

        WHERE L7.PARENT_ID = :I$OBJ_ID
        AND L7.OBJ_TYPE_ID = 7
        AND L7.DATE_DEL IS NULL

        INTO :OBJECT_ID,
             :LINK_ID,
             :V$CLASS_NAME
    DO
    BEGIN
        IF (NOT EXISTS(
            SELECT FIRST 1 1
            FROM VALL V
            WHERE V.PARAM_ID = 2085
            AND V.OBJ_ID = :OBJECT_ID
            AND V.IS_DEL = 0
            AND V.LISTVAL_ID > 0
        )) THEN
        BEGIN
            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:OBJECT_ID, 231, NULL, :I$USER_ID)
            INTO :V$FIO;
    
            ERROR_TEXT = 'Не указана льгота "' || TRIM(V$CLASS_NAME) || '" обучающийся ' || TRIM(V$FIO);
            ERROR_NAME = 'Не указана льгота для ученика';
            PARAMS_NAME = 'Льготное питание';
            ERROR_TYPE = 2;
    
            SUSPEND;
        END
    
        SELECT ADR.REGION, ADR.TOWN, ADR.SETTLEMENT, ADR.STREET, ADR.HOUSE,   ADR.FLAT
        FROM ADR_GET(111, :OBJECT_ID) ADR
        INTO :V$REGION, :V$TOWN, :V$SETTLEMENT, :V$STREET, :V$HOUSE,  :V$FLAT;
    
        IF
            ((((V$REGION LIKE '%обл%') AND (V$TOWN IS NOT NULL)) OR ((V$REGION LIKE '%обл%') AND (V$SETTLEMENT IS NOT NULL)) OR (V$REGION LIKE 'Санкт-Петербург%')) AND
            (V$STREET IS NOT NULL) AND
            (V$HOUSE IS NOT NULL) AND
            (V$FLAT IS NOT NULL))
        THEN
        BEGIN
    
        END
        ELSE
        BEGIN
            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:OBJECT_ID, 231, NULL, :I$USER_ID)
            INTO :V$FIO;
    
            ERROR_TEXT = 'Не указан адрес регистрации "' || TRIM(V$CLASS_NAME) || '" обучающийся ' || TRIM(V$FIO);
            ERROR_NAME = 'Не указан адрес регистрации ученика';
            PARAMS_NAME = 'Льготное питание';
            ERROR_TYPE = 2;
    
            SUSPEND;
        END
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE VERIFY_FUTURE_CLASS (
    I$CLASS_ID BIGINT,
    I$SUFFIX VARCHAR(1000))
AS
declare variable V$PARENT_ID bigint;
declare variable V$TYPE_ID bigint;
declare variable V$COST integer;
declare variable P integer;
declare variable V$ACT varchar(100);
declare variable V$NEWACT varchar(100);
declare variable V$OLD varchar(400);
declare variable V$NEW varchar(400);
declare variable V$CLASS_TYPE bigint;
declare variable V$STAGE integer;
declare variable V$MATCH_STAGE smallint;
begin

  SELECT LP2.PARENT_ID, LP8.OBJ_TYPE_ID, LV.COST
  FROM LINKS LP8
  JOIN VALL V49 ON V49.OBJ_ID = LP8.PARENT_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V49.LISTVAL_ID
  JOIN LINKS LP7 ON LP7.OBJ_ID = LP8.PARENT_ID AND LP7.PARENT_TYPE_ID = 7 AND LP7.DATE_DEL IS NULL
  JOIN LINKS LP2 ON LP2.OBJ_ID = LP7.PARENT_ID AND LP2.PARENT_TYPE_ID = 2 AND LP2.DATE_DEL IS NULL
  WHERE LP8.OBJ_ID = :I$CLASS_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
  INTO :V$PARENT_ID, :V$TYPE_ID, :V$COST;

  V$ACT = '';
  IF(I$SUFFIX IS NOT NULL) THEN
  BEGIN
      P = POSITION(';' IN I$SUFFIX);
      IF(P > 0) THEN
      BEGIN
          V$ACT = SUBSTRING(I$SUFFIX FROM P + 1);
          I$SUFFIX = SUBSTRING(I$SUFFIX FROM 1 FOR P - 1);
      END
  END
  ELSE
  BEGIN
      I$SUFFIX = '';
  END

  -- Если это класс, меняющий параллель - корректируем номер года
  IF(V$TYPE_ID = 9 AND V$ACT <> '@' AND V$ACT <> 'X') THEN V$COST = V$COST + 1;

  -- Если класс удаляется - и хрен с ним
  IF(I$SUFFIX = '*') THEN EXIT;

  FOR
      SELECT COALESCE(VC.VAL, ''), COALESCE(VF.VAL, ''), L9.OBJ_TYPE_ID, LV.COST
      FROM LINKS L7
      JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
      JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
      JOIN LISTVALS LV ON LV.LISTVAL_ID = V49.LISTVAL_ID
      JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 187, 403) AND L9.DATE_DEL IS NULL AND L9.OBJ_ID <> :I$CLASS_ID
      LEFT JOIN VALS VC ON VC.OBJ_ID = L9.OBJ_ID AND VC.PARAM_ID IN (54, 1652) AND VC.IS_DEL = 0 -- текущее название
      LEFT JOIN VALS VF ON VF.OBJ_ID = L9.OBJ_ID AND VF.PARAM_ID IN (3118, 3026) AND VF.IS_DEL = 0 -- будущее название
      WHERE L7.PARENT_ID = :V$PARENT_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
      ORDER BY LV.COST, 1
      INTO :V$OLD, :V$NEW, :V$CLASS_TYPE, :V$STAGE
  DO
  BEGIN
      V$NEWACT = '';
      P = POSITION(';' IN V$NEW);
      IF(P > 0) THEN
      BEGIN
          V$NEWACT = SUBSTRING(V$NEW FROM P + 1);
          V$NEW = SUBSTRING(V$NEW FROM 1 FOR P - 1);
      END
      IF(V$CLASS_TYPE = 9 AND V$NEW = '') THEN V$NEW = V$OLD;

      -- Проверяем параллель
      V$MATCH_STAGE = 0;
      IF(V$CLASS_TYPE = 403 AND V$STAGE = V$COST) THEN V$MATCH_STAGE = 1;      -- новые классы и так в нужной параллели
      ELSE IF(V$CLASS_TYPE = 187 AND V$STAGE = V$COST) THEN V$MATCH_STAGE = 1; -- классы-экстернаты остаются на своем месте
      ELSE IF(V$CLASS_TYPE = 9 AND V$NEWACT IN ('', '^', '1', '2') AND V$STAGE = V$COST - 1) THEN V$MATCH_STAGE = 1; -- обычные классы и классы ОВЗ, меняющие год
      ELSE IF(V$CLASS_TYPE = 9 AND V$NEWACT IN ('@', 'X') AND V$STAGE = V$COST) THEN V$MATCH_STAGE = 1; -- классы ОВЗ, не меняющие год

      -- Если класс удаляется - и черт с ним
      IF(V$MATCH_STAGE = 1 AND V$NEW <> '*') THEN
      BEGIN
          IF(I$SUFFIX = V$NEW) THEN EXCEPTION DATA_ERROR 'Нельзя использовать это наименование, оно уже используется другим классом. Проверьте схему перевода года для классов ОВЗ';
      END
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE VERIFY_GIA (
    I$OBJ_ID BIGINT,
    I$VPL_CHECKS SMALLINT = 0)
RETURNS (
    LINK_ID BIGINT,
    OBJECT_ID BIGINT,
    PARENT_ID BIGINT,
    NAME_TASK VARCHAR(1000),
    ERROR_NAME VARCHAR(1000),
    PARAMS_NAME VARCHAR(1000),
    ERROR_TEXT VARCHAR(1000),
    ERROR_TYPE SMALLINT)
AS
DECLARE VARIABLE V$TYPE_ID BIGINT;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$TAG VARCHAR(4000);
DECLARE VARIABLE V$CAPTION VARCHAR(4000);
DECLARE VARIABLE V$BLOB_ID BIGINT;
DECLARE VARIABLE V$STATUS VARCHAR(10);
DECLARE VARIABLE V$HAS_OUT_CLASS SMALLINT;
DECLARE VARIABLE Y INTEGER;
DECLARE VARIABLE M INTEGER;
DECLARE VARIABLE V$LEVEL_ID INTEGER;
DECLARE VARIABLE V$Y SMALLINT;
DECLARE VARIABLE V$DT DATE;
DECLARE VARIABLE V$YEAR_VAL VARCHAR(100);
DECLARE VARIABLE V$YEAR_ID BIGINT;
DECLARE VARIABLE LANG_CODE VARCHAR(2);
DECLARE VARIABLE V$SCHOOL_ID BIGINT;
DECLARE VARIABLE V$LNG_1 BIGINT;
DECLARE VARIABLE V$LNG_2 BIGINT;
BEGIN

    NAME_TASK = 'ГИА';
    ERROR_TYPE = 0;

    LANG_CODE = 'RU';

    SELECT LANG_CODE FROM USERS WHERE USER_ID = 1 INTO :LANG_CODE;

    V$Y = EXTRACT(YEAR FROM CURRENT_TIMESTAMP);
    V$DT = '1.09.' || V$Y;
    
    IF (CURRENT_TIMESTAMP < V$DT) THEN V$YEAR_VAL = (V$Y - 1) || '-' || V$Y; ELSE V$YEAR_VAL = V$Y || '-' ||(V$Y + 1);

    SELECT FIRST 1 LV.LISTVAL_ID
    FROM LISTVALS LV
    JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = :LANG_CODE
    WHERE LV.LIST_ID = 29 AND R.VAL LIKE :V$YEAR_VAL
    INTO :V$YEAR_ID;

    SELECT KEY_VAL FROM KEYS WHERE KEY_CODE = 'LEVEL' INTO :V$LEVEL_ID;
    V$STATUS = (SELECT STATUS FROM OU_LICENCE_TYPE);

    SELECT TYPE_ID
    FROM OBJECTS
    WHERE OBJ_ID = :I$OBJ_ID
    INTO :V$TYPE_ID;

    -- Проверка всех ОУ района
    IF (I$VPL_CHECKS = 1 AND V$TYPE_ID = 111 AND V$LEVEL_ID = 2) THEN
    BEGIN
        FOR
            SELECT OBJ_ID
            FROM OBJECT_CHILDREN_GET_DEEP(:I$OBJ_ID, 2, 1)
            INTO :V$OBJ_ID
        DO
        BEGIN
            FOR
                SELECT LINK_ID, OBJECT_ID, PARENT_ID, NAME_TASK, ERROR_NAME, PARAMS_NAME, ERROR_TEXT, ERROR_TYPE
                FROM VERIFY_GIA(:V$OBJ_ID)
                INTO :LINK_ID, :OBJECT_ID, :PARENT_ID, :NAME_TASK, :ERROR_NAME, :PARAMS_NAME, :ERROR_TEXT, :ERROR_TYPE
            DO
            BEGIN
                SUSPEND;
            END
        END

        EXIT;
    END

    NAME_TASK = 'Государственная (итоговая) аттестация';
    ERROR_TYPE = 2;

    IF (I$VPL_CHECKS = 1 AND V$TYPE_ID IN (9, 10, 124, 125, 126)) THEN
    BEGIN
        FOR
            SELECT L10_126.OBJ_ID, L10_126.LINK_ID, L9_125.OBJ_ID, V804.VAL
            FROM LINKS L9_125
            JOIN LINKS L10_126 ON L10_126.PARENT_ID = L9_125.OBJ_ID AND L10_126.OBJ_TYPE_ID IN (10, 126) AND L10_126.DATE_DEL IS NULL
            JOIN LINKS L120 ON L120.PARENT_ID = L10_126.OBJ_ID AND L120.OBJ_TYPE_ID =120 AND L120.DATE_DEL IS NULL
            JOIN LINKS L119 ON L119.OBJ_TYPE_ID = 119 AND L119.DATE_DEL IS NULL
            JOIN VALL V742 ON V742.OBJ_ID = L119.OBJ_ID AND V742.PARAM_ID = 742 AND V742.IS_DEL = 0 AND V742.LISTVAL_ID = :V$YEAR_ID
            JOIN LINKS Y120 ON Y120.PARENT_ID = L119.OBJ_ID AND Y120.OBJ_TYPE_ID = 120 AND Y120.DATE_DEL IS NULL AND L120.OBJ_ID = Y120.OBJ_ID
            JOIN VALD V804 ON V804.OBJ_ID = L120.OBJ_ID AND V804.PARAM_ID = 804 AND V804.IS_DEL = 0
            WHERE (
                (:V$TYPE_ID = 124 AND L9_125.PARENT_ID = :I$OBJ_ID) OR
                (:V$TYPE_ID IN (9, 125) AND L9_125.OBJ_ID = :I$OBJ_ID) OR
                (:V$TYPE_ID IN (10, 126) AND L10_126.OBJ_ID = :I$OBJ_ID)
              )
              AND (:V$TYPE_ID > 10 OR L9_125.PARENT_TYPE_ID = 8)
              AND L9_125.DATE_DEL IS NULL AND L9_125.OBJ_TYPE_ID IN (9, 125)
            GROUP BY L10_126.OBJ_ID, L10_126.LINK_ID, L9_125.OBJ_ID, V804.VAL
            HAVING COUNT(*) > 1
            INTO :OBJECT_ID, :LINK_ID, :V$OBJ_ID, :V$DT
        DO
        BEGIN
            PARENT_ID = V$OBJ_ID;

            SELECT FIRST 1 OBJ_ID
            FROM OBJECT_PARENTS_GET(:I$OBJ_ID, 2)
            INTO :V$SCHOOL_ID;

            SELECT 'Школа ' || CAPTION
            FROM OBJECT_CAPTION_GET(:V$SCHOOL_ID)
            INTO :V$CAPTION;

            SELECT :V$CAPTION || ', класс ' || CAPTION
            FROM OBJECT_CAPTION_GET(:V$OBJ_ID)
            INTO :V$CAPTION;

            SELECT :V$CAPTION || ', учащийся ' || CAPTION
            FROM OBJECT_CAPTION_GET(:OBJECT_ID, 126)
            INTO :V$CAPTION;

            SELECT :V$CAPTION || ' ' || V
            FROM VAL_GET(:OBJECT_ID, 57)
            INTO :V$CAPTION;

            SELECT :V$CAPTION || ' ' || V
            FROM VAL_GET(:OBJECT_ID, 829)
            INTO :V$CAPTION;

            FOR
                SELECT TRIM(:V$CAPTION) || ' назначен(а) на несколько экзаменов ' || :V$DT || ': ' || LIST((SELECT V FROM VAL_GET(L120.OBJ_ID, 803)), ', ')
                FROM LINKS L120
                JOIN VALD V804 ON V804.OBJ_ID = L120.OBJ_ID AND V804.PARAM_ID = 804 AND V804.IS_DEL = 0 AND V804.VAL = :V$DT
                WHERE L120.PARENT_ID = :OBJECT_ID AND L120.OBJ_TYPE_ID = 120 AND L120.DATE_DEL IS NULL
                INTO :V$CAPTION
            DO
            BEGIN
                --13
                PARAMS_NAME = 'Дата проведения экзамена';
                ERROR_TEXT = :V$CAPTION;
                ERROR_NAME = 'Ошибка: обучающийся не может сдавать разные экзамены в один день';
                ERROR_TYPE = 3;
                SUSPEND;
            END
        END

        FOR
            SELECT L10_126.OBJ_ID, L10_126.LINK_ID, L9_125.OBJ_ID, LV.PARENT_ID, LV.LISTVAL_ID
            FROM LINKS L9_125
            JOIN LINKS L10_126 ON L10_126.PARENT_ID = L9_125.OBJ_ID AND L10_126.OBJ_TYPE_ID IN (10, 126) AND L10_126.DATE_DEL IS NULL
            JOIN LINKS L120_10 ON L120_10.PARENT_ID = L10_126.OBJ_ID AND L120_10.OBJ_TYPE_ID = 120 AND L120_10.DATE_DEL IS NULL
            JOIN LINKS L120_119 ON L120_119.OBJ_ID = L120_10.OBJ_ID AND L120_119.OBJ_TYPE_ID = 120 AND L120_119.DATE_DEL IS NULL
            JOIN LINKS L119 ON L119.OBJ_ID = L120_119.PARENT_ID AND L119.OBJ_TYPE_ID = 119 AND L119.DATE_DEL IS NULL
            JOIN VALL V742 ON V742.OBJ_ID = L119.OBJ_ID AND V742.PARAM_ID = 742 AND V742.LISTVAL_ID = :V$YEAR_ID --10976
            JOIN VALL V803 ON V803.OBJ_ID = L120_10.OBJ_ID AND V803.PARAM_ID = 803 AND V803.IS_DEL = 0
            JOIN LISTVALS LV ON LV.LISTVAL_ID = V803.LISTVAL_ID AND LV.TAG IN (70, 71, 72, 73) -- ин. яз. устно

            WHERE ((:V$TYPE_ID = 124 AND L9_125.PARENT_ID = :I$OBJ_ID)
                OR (:V$TYPE_ID IN (9, 125) AND L9_125.OBJ_ID = :I$OBJ_ID)
                OR (:V$TYPE_ID IN (10, 126) AND L10_126.OBJ_ID = :I$OBJ_ID))
              AND (:V$TYPE_ID > 10 OR L9_125.PARENT_TYPE_ID = 8)
              AND L9_125.DATE_DEL IS NULL AND L9_125.OBJ_TYPE_ID IN (9, 125)

            AND NOT EXISTS (
              SELECT FIRST 1 1
              FROM LINKS L120_10
              JOIN LINKS L120_119 ON L120_119.OBJ_ID = L120_10.OBJ_ID AND L120_119.OBJ_TYPE_ID = 120 AND L120_119.DATE_DEL IS NULL
              JOIN LINKS L119 ON L119.OBJ_ID = L120_119.PARENT_ID AND L119.OBJ_TYPE_ID = 119 AND L119.DATE_DEL IS NULL
              JOIN VALL V742 ON V742.OBJ_ID = L119.OBJ_ID AND V742.PARAM_ID = 742 AND V742.LISTVAL_ID = :V$YEAR_ID --10976
              JOIN VALL V803 ON V803.OBJ_ID = L120_10.OBJ_ID AND V803.PARAM_ID = 803 AND V803.IS_DEL = 0 AND V803.LISTVAL_ID = LV.PARENT_ID
              WHERE L120_10.PARENT_ID = L10_126.OBJ_ID AND L120_10.OBJ_TYPE_ID = 120 AND L120_10.DATE_DEL IS NULL
            )
            INTO :OBJECT_ID, :LINK_ID, :V$OBJ_ID, :V$LNG_1, :V$LNG_2
        DO
        BEGIN
            PARENT_ID = V$OBJ_ID;

            SELECT FIRST 1 OBJ_ID
            FROM OBJECT_PARENTS_GET(:I$OBJ_ID, 2)
            INTO :V$SCHOOL_ID;

            SELECT 'Школа ' || CAPTION
            FROM OBJECT_CAPTION_GET(:V$SCHOOL_ID)
            INTO :V$CAPTION;

            SELECT :V$CAPTION || ', класс ' || CAPTION
            FROM OBJECT_CAPTION_GET(:V$OBJ_ID)
            INTO :V$CAPTION;

            SELECT :V$CAPTION || ', учащийся ' || CAPTION
            FROM OBJECT_CAPTION_GET(:OBJECT_ID, 126)
            INTO :V$CAPTION;

            SELECT :V$CAPTION || ' ' || V
            FROM VAL_GET(:OBJECT_ID, 57)
            INTO :V$CAPTION;

            SELECT :V$CAPTION || ' ' || V
            FROM VAL_GET(:OBJECT_ID, 829)
            INTO :V$CAPTION;

            SELECT TRIM(:V$CAPTION) || ' не может быть назначен(а) на экзамен по ' || R.VAL
            FROM LISTVALS LV
            JOIN RES R ON R.RES_ID = LV.RES_ID
            WHERE LISTVAL_ID = :V$LNG_2 AND R.LANG_CODE = :LANG_CODE
            INTO :V$CAPTION;
            
            SELECT TRIM(:V$CAPTION) || ' если не назначен(а) на экзамен по ' || R.VAL
            FROM LISTVALS LV
            JOIN RES R ON R.RES_ID = LV.RES_ID
            WHERE LISTVAL_ID = :V$LNG_1 AND R.LANG_CODE = :LANG_CODE
            INTO :V$CAPTION;

            PARAMS_NAME = 'Устная часть экзамена по иностранному языку';
            ERROR_TEXT = V$CAPTION;
            ERROR_NAME = 'Ошибка: обучающийся не может сдавать устную часть экзамена по иностранному языку, если не назначен на письменную часть экзамена по этому языку';
            ERROR_TYPE = 3;
            SUSPEND;
        END

    END

    IF (I$VPL_CHECKS = 0) THEN
    BEGIN

        FOR
            SELECT L10.OBJ_ID, L10.LINK_ID, L9.OBJ_ID, V804.VAL
            FROM LINKS L7
            JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
            JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
            JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID =10 AND L10.DATE_DEL IS NULL
            JOIN LINKS L120 ON L120.PARENT_ID = L10.OBJ_ID AND L120.OBJ_TYPE_ID =120 AND L120.DATE_DEL IS NULL
            JOIN LINKS L119 ON L119.OBJ_TYPE_ID = 119 AND L119.DATE_DEL IS NULL
            JOIN VALL V742 ON V742.OBJ_ID = L119.OBJ_ID AND V742.PARAM_ID = 742 AND V742.IS_DEL = 0 AND V742.LISTVAL_ID = :V$YEAR_ID
            JOIN LINKS Y120 ON Y120.PARENT_ID = L119.OBJ_ID AND Y120.OBJ_TYPE_ID = 120 AND Y120.DATE_DEL IS NULL AND L120.OBJ_ID = Y120.OBJ_ID
            JOIN VALD V804 ON V804.OBJ_ID = L120.OBJ_ID AND V804.PARAM_ID = 804 AND V804.IS_DEL = 0
            WHERE :V$TYPE_ID = 2 AND L7.PARENT_ID = :I$OBJ_ID AND L7.OBJ_TYPE_ID IN (7, 502) AND L7.DATE_DEL IS NULL
            GROUP BY L10.OBJ_ID, L10.LINK_ID, L9.OBJ_ID, V804.VAL
            HAVING COUNT(*) > 1
            INTO :OBJECT_ID, :LINK_ID, :V$OBJ_ID, :V$DT
        DO
        BEGIN
            PARENT_ID = V$OBJ_ID;

            SELECT 'Школа ' || CAPTION
            FROM OBJECT_CAPTION_GET(:I$OBJ_ID)
            INTO :V$CAPTION;

            SELECT :V$CAPTION || ', класс ' || CAPTION
            FROM OBJECT_CAPTION_GET(:V$OBJ_ID)
            INTO :V$CAPTION;

            SELECT :V$CAPTION || ', учащийся ' || CAPTION
            FROM OBJECT_CAPTION_GET(:OBJECT_ID, 126)
            INTO :V$CAPTION;

            SELECT :V$CAPTION || ' ' || V
            FROM VAL_GET(:OBJECT_ID, 57)
            INTO :V$CAPTION;

            SELECT :V$CAPTION || ' ' || V
            FROM VAL_GET(:OBJECT_ID, 829)
            INTO :V$CAPTION;

            FOR
              SELECT TRIM(:V$CAPTION) || ' назначен(а) на несколько экзаменов ' || :V$DT || ': ' || LIST((SELECT V FROM VAL_GET(L120.OBJ_ID, 803)), ', ')
              FROM LINKS L120
              JOIN VALD V804 ON V804.OBJ_ID = L120.OBJ_ID AND V804.PARAM_ID = 804 AND V804.IS_DEL = 0 AND V804.VAL = :V$DT
              WHERE L120.PARENT_ID = :OBJECT_ID AND L120.OBJ_TYPE_ID = 120 AND L120.DATE_DEL IS NULL
              INTO :V$CAPTION
            DO
            BEGIN
              --13
              PARAMS_NAME = 'Дата проведения экзамена';
              ERROR_TEXT = V$CAPTION;
              ERROR_NAME = 'Ошибка: обучающийся не может сдавать разные экзамены в один день';
              ERROR_TYPE = 3;
              SUSPEND;
            END
        END

        FOR
            SELECT L10.OBJ_ID, L10.LINK_ID, L9.OBJ_ID, LV.PARENT_ID, LV.LISTVAL_ID
            FROM LINKS L7
            JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
            JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
            JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID =10 AND L10.DATE_DEL IS NULL
            JOIN LINKS L120_10 ON L120_10.PARENT_ID = L10.OBJ_ID AND L120_10.OBJ_TYPE_ID = 120 AND L120_10.DATE_DEL IS NULL
            JOIN LINKS L120_119 ON L120_119.OBJ_ID = L120_10.OBJ_ID AND L120_119.OBJ_TYPE_ID = 120 AND L120_119.DATE_DEL IS NULL
            JOIN LINKS L119 ON L119.OBJ_ID = L120_119.PARENT_ID AND L119.OBJ_TYPE_ID = 119 AND L119.DATE_DEL IS NULL
            JOIN VALL V742 ON V742.OBJ_ID = L119.OBJ_ID AND V742.PARAM_ID = 742 AND V742.LISTVAL_ID = :V$YEAR_ID --10976
            JOIN VALL V803 ON V803.OBJ_ID = L120_10.OBJ_ID AND V803.PARAM_ID = 803 AND V803.IS_DEL = 0
            JOIN LISTVALS LV ON LV.LISTVAL_ID = V803.LISTVAL_ID AND LV.TAG IN (70, 71, 72, 73) -- ин. яз. устно
            WHERE :V$TYPE_ID = 2 AND L7.PARENT_ID = :I$OBJ_ID AND L7.OBJ_TYPE_ID IN (7, 502) AND L7.DATE_DEL IS NULL

            AND NOT EXISTS (
              SELECT FIRST 1 1
              FROM LINKS L120_10
              JOIN LINKS L120_119 ON L120_119.OBJ_ID = L120_10.OBJ_ID AND L120_119.OBJ_TYPE_ID = 120 AND L120_119.DATE_DEL IS NULL
              JOIN LINKS L119 ON L119.OBJ_ID = L120_119.PARENT_ID AND L119.OBJ_TYPE_ID = 119 AND L119.DATE_DEL IS NULL
              JOIN VALL V742 ON V742.OBJ_ID = L119.OBJ_ID AND V742.PARAM_ID = 742 AND V742.LISTVAL_ID = :V$YEAR_ID --10976
              JOIN VALL V803 ON V803.OBJ_ID = L120_10.OBJ_ID AND V803.PARAM_ID = 803 AND V803.IS_DEL = 0 AND V803.LISTVAL_ID = LV.PARENT_ID
              WHERE L120_10.PARENT_ID = L10.OBJ_ID AND L120_10.OBJ_TYPE_ID = 120 AND L120_10.DATE_DEL IS NULL
            )
            INTO :OBJECT_ID, :LINK_ID, :V$OBJ_ID, :V$LNG_1, :V$LNG_2
        DO
        BEGIN
            PARENT_ID = V$OBJ_ID;

            SELECT 'Школа ' || CAPTION
            FROM OBJECT_CAPTION_GET(:I$OBJ_ID)
            INTO :V$CAPTION;

            SELECT :V$CAPTION || ', класс ' || CAPTION
            FROM OBJECT_CAPTION_GET(:V$OBJ_ID)
            INTO :V$CAPTION;

            SELECT :V$CAPTION || ', учащийся ' || CAPTION
            FROM OBJECT_CAPTION_GET(:OBJECT_ID, 126)
            INTO :V$CAPTION;

            SELECT :V$CAPTION || ' ' || V
            FROM VAL_GET(:OBJECT_ID, 57)
            INTO :V$CAPTION;

            SELECT :V$CAPTION || ' ' || V
            FROM VAL_GET(:OBJECT_ID, 829)
            INTO :V$CAPTION;

            SELECT TRIM(:V$CAPTION) || ' не может быть назначен(а) на экзамен по ' || R.VAL
            FROM LISTVALS LV
            JOIN RES R ON R.RES_ID = LV.RES_ID
            WHERE LISTVAL_ID = :V$LNG_2 AND R.LANG_CODE = :LANG_CODE
            INTO :V$CAPTION;
            
            SELECT TRIM(:V$CAPTION) || ' если не назначен(а) на экзамен по ' || R.VAL
            FROM LISTVALS LV
            JOIN RES R ON R.RES_ID = LV.RES_ID
            WHERE LISTVAL_ID = :V$LNG_1 AND R.LANG_CODE = :LANG_CODE
            INTO :V$CAPTION;

            PARAMS_NAME = 'Устная часть экзамена по иностранному языку';
            ERROR_TEXT = V$CAPTION;
            ERROR_NAME = 'Ошибка: обучающийся не может сдавать устную часть экзамена по иностранному языку, если не назначен на письменную часть экзамена по этому языку';
            ERROR_TYPE = 3;
            SUSPEND;
        END

        IF (
          EXISTS(
            SELECT FIRST 1 1
            FROM VALI V
            WHERE V.PARAM_ID = 1364 AND V.OBJ_ID = :I$OBJ_ID AND V.IS_DEL = 0 AND V.VAL > 0
          )
          -- Не проверяем ответственных в сентябре-октябре
          AND EXTRACT(MONTH FROM CURRENT_DATE) NOT IN (7, 8, 9, 10)
        ) THEN
        BEGIN
            SELECT LINK_ID
            FROM LINKS
            WHERE PARENT_ID IS NULL AND OBJ_ID = :I$OBJ_ID AND DATE_DEL IS NULL
            INTO :LINK_ID;

            OBJECT_ID = I$OBJ_ID;
            --1
            IF (NOT EXISTS(
                SELECT FIRST 1 1
                FROM VALR V
                WHERE V.PARAM_ID = 1369 AND V.OBJ_ID = :I$OBJ_ID AND V.IS_DEL = 0 AND V.VAL > 0
            )) THEN
            BEGIN
                PARAMS_NAME = IIF(V$LEVEL_ID = 2, (SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$OBJ_ID)) || ' - ', '') ||
                    'Ответственный за сбор данных для итоговой аттестации';
                ERROR_TEXT = 'Ошибка: поле «Ответственный за сбор данных для итоговой аттестации» должно быть заполнено';
                ERROR_NAME = ERROR_TEXT;
                ERROR_TYPE = 3;
                SUSPEND;
            END

            IF (V$LEVEL_ID = 2) THEN
            BEGIN
                EXIT;
            END
            --2
            IF (EXISTS(
                SELECT FIRST 1 1
                FROM VALI V
                WHERE V.PARAM_ID = 1365 AND V.OBJ_ID = :I$OBJ_ID AND V.IS_DEL = 0 AND V.VAL > 0
            ) AND NOT EXISTS(
                SELECT FIRST 1 1
                FROM VALA V
                WHERE V.PARAM_ID = 1371 AND V.OBJ_ID = :I$OBJ_ID AND V.IS_DEL = 0 AND V.REGION <> '' AND V.STREET <> '' AND V.HOUSE <> ''
            )) THEN
            BEGIN
                PARAMS_NAME = 'Фактический адрес ППЭ';
                ERROR_TEXT = 'Ошибка: поле «Фактический адрес ППЭ» должно быть заполнено';
                ERROR_NAME = ERROR_TEXT;
                ERROR_TYPE = 3;
                SUSPEND;            
            END
            --3
            V$HAS_OUT_CLASS = 0;
            FOR
                SELECT L.OBJ_ID, L.LINK_ID, L.OBJ_TYPE_ID, LV.TAG
                FROM LINKS L7
                JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.DATE_DEL IS NULL AND L8.OBJ_TYPE_ID = 8
                LEFT JOIN VALL V ON V.PARAM_ID = 49 AND V.OBJ_ID = L8.OBJ_ID
                LEFT JOIN LISTVALS LV ON V.LISTVAL_ID = LV.LISTVAL_ID
                JOIN LINKS L ON L.PARENT_ID = L8.OBJ_ID AND L.DATE_DEL IS NULL AND L.OBJ_TYPE_ID IN (9, 125, 187)
                WHERE L7.PARENT_ID = :I$OBJ_ID AND L7.DATE_DEL IS NULL AND L7.OBJ_TYPE_ID IN (7, 502)
                INTO :OBJECT_ID, :LINK_ID, :V$TYPE_ID, :V$TAG
            DO
            BEGIN
                IF ((V$TYPE_ID IN (9, 187)) AND (V$HAS_OUT_CLASS = 0) AND EXISTS(
                    SELECT FIRST 1 1
                    FROM VALL
                    WHERE OBJ_ID = :OBJECT_ID AND PARAM_ID IN (2388,2418) AND IS_DEL = 0 AND LISTVAL_ID <> 11217
                )) THEN
                BEGIN
                    V$HAS_OUT_CLASS = 1;
                END
                IF ((V$TYPE_ID = 9) AND (NOT EXISTS(
                    SELECT FIRST 1 1
                    FROM VALS V
                    WHERE V.OBJ_ID = :OBJECT_ID AND V.IS_DEL = 0 AND V.PARAM_ID = 1363 AND TRIM(V.VAL) <> ''
                ))) THEN
                BEGIN
                    SELECT V
                    FROM VAL_GET(:OBJECT_ID, 54)
                    INTO :V$CAPTION;
                    IF (:V$CAPTION = '<  ...  >') THEN
                    BEGIN
                        V$CAPTION = V$TAG;
                    END
                    ELSE
                    BEGIN
                        V$CAPTION = V$TAG || V$CAPTION;
                    END
                    SELECT BLOB_ID
                    FROM VAL_ADD(1363, :OBJECT_ID, :V$CAPTION)
                    INTO :V$BLOB_ID;
                END
                ELSE IF ((V$TYPE_ID = 125) AND (NOT EXISTS(
                    SELECT FIRST 1 1
                    FROM VALS V
                    WHERE V.OBJ_ID = :OBJECT_ID AND V.IS_DEL = 0 AND V.PARAM_ID = 821 AND TRIM(V.VAL) <> ''
                ))) THEN
                BEGIN
                    SELECT V
                    FROM VAL_GET(:OBJECT_ID, 820)
                    INTO :V$CAPTION;
                    IF (:V$CAPTION = '<  ...  >') THEN
                    BEGIN
                        V$CAPTION = V$TAG;
                    END
                    ELSE
                    BEGIN
                        V$CAPTION = V$TAG || V$CAPTION;
                    END
                    SELECT BLOB_ID
                    FROM VAL_ADD(821, :OBJECT_ID, :V$CAPTION)
                    INTO :V$BLOB_ID;
                END
                ELSE IF ((V$TYPE_ID = 187) AND (NOT EXISTS(
                    SELECT FIRST 1 1
                    FROM VALS V
                    WHERE V.OBJ_ID = :OBJECT_ID AND V.IS_DEL = 0 AND V.PARAM_ID = 1653 AND TRIM(V.VAL) <> ''
                ))) THEN
                BEGIN
                    SELECT V
                    FROM VAL_GET(:OBJECT_ID, 1652)
                    INTO :V$CAPTION;
                    IF (V$CAPTION = '<  ...  >') THEN
                    BEGIN
                        V$CAPTION = V$TAG;
                    END
                    ELSE
                    BEGIN
                        V$CAPTION = V$TAG || V$CAPTION;
                    END
                    SELECT BLOB_ID
                    FROM VAL_ADD(1653, :OBJECT_ID, :V$CAPTION)
                    INTO :V$BLOB_ID;
                END
            END
            --4
            SELECT LINK_ID
            FROM LINKS
            WHERE PARENT_ID IS NULL AND OBJ_ID = :I$OBJ_ID AND DATE_DEL IS NULL
            INTO :LINK_ID;
            OBJECT_ID = I$OBJ_ID;
    
            -- В СПО не проверяем ГИА
            IF (V$HAS_OUT_CLASS = 0 AND V$STATUS = 'O') THEN
            BEGIN
                PARAMS_NAME = 'Выпускной класс';
                ERROR_TEXT = 'Предупреждение: в образовательном учреждении нет выпускных классов';
                ERROR_NAME = ERROR_TEXT;
                ERROR_TYPE = 2;
                SUSPEND;
            END
            --5
            FOR
                SELECT TRIM(V59.SVAL) || ' ' || TRIM(V60.SVAL) || ' ' || TRIM(V61.SVAL) || ', ' || V241.VAL, COUNT(*)
                FROM LINKS L14
                JOIN VALS V59 ON V59.OBJ_ID = L14.OBJ_ID AND V59.PARAM_ID = 59 AND V59.IS_DEL = 0
                JOIN VALS V60 ON V60.OBJ_ID = L14.OBJ_ID AND V60.PARAM_ID = 60 AND V60.IS_DEL = 0
                JOIN VALS V61 ON V61.OBJ_ID = L14.OBJ_ID AND V61.PARAM_ID = 61 AND V61.IS_DEL = 0
                JOIN VALD V241 ON V241.OBJ_ID = L14.OBJ_ID AND V241.PARAM_ID = 241 AND V241.IS_DEL = 0
                JOIN VALL V1376 ON V1376.OBJ_ID = L14.OBJ_ID AND V1376.PARAM_ID = 1376 AND V1376.IS_DEL = 0 AND V1376.LISTVAL_ID <> 2989
                WHERE L14.PARENT_ID = :I$OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
                GROUP BY 1, V241.VAL
                HAVING COUNT(*) > 1
                INTO :V$CAPTION, :V$HAS_OUT_CLASS
            DO
            BEGIN
                PARAMS_NAME = '«Фамилия», «Имя», «Отчество», «Дата рождения»';
                ERROR_TEXT = 'Ошибка: В списке сотрудников не должно быть повторяющихся записей. Найдено ' || V$HAS_OUT_CLASS || ' повторений: ' || V$CAPTION;
                ERROR_NAME = 'Ошибка: В списке сотрудников не должно быть повторяющихся записей.';
                ERROR_TYPE = 3;
                SUSPEND;
            END
            --6
            FOR
                SELECT TRIM(V59.VAL) || ' ' || TRIM(V60.VAL) || ' ' || TRIM(V61.VAL) || ', ' || V241.VAL, L14.OBJ_ID, L14.LINK_ID
                FROM LINKS L14
                JOIN VALS V59 ON V59.OBJ_ID = L14.OBJ_ID AND V59.PARAM_ID = 59 AND V59.IS_DEL = 0
                JOIN VALS V60 ON V60.OBJ_ID = L14.OBJ_ID AND V60.PARAM_ID = 60 AND V60.IS_DEL = 0
                JOIN VALS V61 ON V61.OBJ_ID = L14.OBJ_ID AND V61.PARAM_ID = 61 AND V61.IS_DEL = 0
                JOIN VALD V241 ON V241.OBJ_ID = L14.OBJ_ID AND V241.PARAM_ID = 241 AND V241.IS_DEL = 0
                JOIN VALL V1376 ON V1376.OBJ_ID = L14.OBJ_ID AND V1376.PARAM_ID = 1376 AND V1376.IS_DEL = 0 AND V1376.LISTVAL_ID <> 2989
                LEFT JOIN VALL V274 ON V274.OBJ_ID = L14.OBJ_ID AND V274.PARAM_ID = 274 AND V274.IS_DEL = 0
                WHERE L14.PARENT_ID = :I$OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL AND V274.LISTVAL_ID IS NULL
                INTO :V$CAPTION, :OBJECT_ID, :LINK_ID
            DO
            BEGIN
                PARAMS_NAME = 'Статус сотрудника';
                ERROR_TEXT = 'Ошибка: не указан «Статус сотрудника» ' || V$CAPTION;
                ERROR_NAME = 'Ошибка: не указан «Статус сотрудника»';
                ERROR_TYPE = 3;
                SUSPEND;
            END
            --7
            FOR
                SELECT TRIM(V59.VAL) || ' ' || TRIM(V60.VAL) || ' ' || TRIM(V61.VAL) || ', ' || V241.VAL, L14.OBJ_ID, L14.LINK_ID
                FROM LINKS L14
                JOIN VALS V59 ON V59.OBJ_ID = L14.OBJ_ID AND V59.PARAM_ID = 59 AND V59.IS_DEL = 0
                JOIN VALS V60 ON V60.OBJ_ID = L14.OBJ_ID AND V60.PARAM_ID = 60 AND V60.IS_DEL = 0
                JOIN VALS V61 ON V61.OBJ_ID = L14.OBJ_ID AND V61.PARAM_ID = 61 AND V61.IS_DEL = 0
                JOIN VALD V241 ON V241.OBJ_ID = L14.OBJ_ID AND V241.PARAM_ID = 241 AND V241.IS_DEL = 0
                JOIN VALL V1376 ON V1376.OBJ_ID = L14.OBJ_ID AND V1376.PARAM_ID = 1376 AND V1376.IS_DEL = 0 AND V1376.LISTVAL_ID <> 2989
                JOIN VALL V279 ON V279.OBJ_ID = L14.OBJ_ID AND V279.PARAM_ID = 279 AND V279.IS_DEL = 0 AND V279.LISTVAL_ID <> 626
                JOIN VALL V278 ON V278.OBJ_ID = L14.OBJ_ID AND V278.PARAM_ID = 278 AND V278.IS_DEL = 0 AND V278.LISTVAL_ID <> 620
                WHERE L14.PARENT_ID = :I$OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
                INTO :V$CAPTION, :OBJECT_ID, :LINK_ID
            DO
            BEGIN
                PARAMS_NAME = 'Ученая степень';
                ERROR_TEXT = 'Ошибка: Указана ученая степень у сотрудника без высшего профессионального образования - ' || V$CAPTION;
                ERROR_NAME = 'Ошибка: Указана ученая степень у сотрудника без высшего профессионального образования';
                ERROR_TYPE = 3;
                SUSPEND;
            END
            --8
            FOR
                SELECT TRIM(V59.VAL) || ' ' || TRIM(V60.VAL) || ' ' || TRIM(V61.VAL) || ', ' || V241.VAL, L14.OBJ_ID, L14.LINK_ID
                FROM LINKS L14
                JOIN VALS V59 ON V59.OBJ_ID = L14.OBJ_ID AND V59.PARAM_ID = 59 AND V59.IS_DEL = 0
                JOIN VALS V60 ON V60.OBJ_ID = L14.OBJ_ID AND V60.PARAM_ID = 60 AND V60.IS_DEL = 0
                JOIN VALS V61 ON V61.OBJ_ID = L14.OBJ_ID AND V61.PARAM_ID = 61 AND V61.IS_DEL = 0
                JOIN VALD V241 ON V241.OBJ_ID = L14.OBJ_ID AND V241.PARAM_ID = 241 AND V241.IS_DEL = 0
                JOIN VALL V1376 ON V1376.OBJ_ID = L14.OBJ_ID AND V1376.PARAM_ID = 1376 AND V1376.IS_DEL = 0 AND V1376.LISTVAL_ID <> 2989
                LEFT JOIN VALL V281 ON V281.OBJ_ID = L14.OBJ_ID AND V281.PARAM_ID = 281 AND V281.IS_DEL = 0
                WHERE L14.PARENT_ID = :I$OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL AND V281.LISTVAL_ID IS NULL
                INTO :V$CAPTION, :OBJECT_ID, :LINK_ID
            DO
            BEGIN
                PARAMS_NAME = 'Квалификационная категория';
                ERROR_TEXT = 'Ошибка: не указана квалификационная категория для сотрудника - ' || V$CAPTION;
                ERROR_NAME = 'Ошибка: не указана квалификационная категория для сотрудника';
                ERROR_TYPE = 3;
                SUSPEND;
            END
        END

        IF (V$LEVEL_ID = 2) THEN EXIT;

        FOR
            SELECT L10_126.OBJ_ID, L10_126.LINK_ID, L.OBJ_ID
            FROM LINKS L7
            JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.DATE_DEL IS NULL AND L8.OBJ_TYPE_ID = 8
            JOIN LINKS L ON L.PARENT_ID = L8.OBJ_ID AND L.DATE_DEL IS NULL AND L.OBJ_TYPE_ID IN (9, 125, 187)
            LEFT JOIN VALL V2388 ON V2388.OBJ_ID = L.OBJ_ID AND V2388.PARAM_ID IN (2388, 2418) AND V2388.IS_DEL = 0
            LEFT JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
            LEFT JOIN LISTVALS LV ON LV.LISTVAL_ID = V49.LISTVAL_ID
            JOIN LINKS L10_126 ON L10_126.PARENT_ID = L.OBJ_ID AND L10_126.OBJ_TYPE_ID IN (10, 126) AND L10_126.DATE_DEL IS NULL
            WHERE L7.PARENT_ID = :I$OBJ_ID AND L7.DATE_DEL IS NULL AND L7.OBJ_TYPE_ID IN (7, 502) AND ((L.OBJ_TYPE_ID = 125) OR (V2388.LISTVAL_ID <> 11217) OR (LV.TAG IN (9,10)))
            INTO :OBJECT_ID, :LINK_ID, :V$OBJ_ID
        DO
        BEGIN
            PARENT_ID = V$OBJ_ID;

            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:V$OBJ_ID)
            INTO :V$CAPTION;

            SELECT :V$CAPTION || ' ' || CAPTION
            FROM OBJECT_CAPTION_GET(:OBJECT_ID, 126)
            INTO :V$CAPTION;

            SELECT :V$CAPTION || ' ' || V
            FROM VAL_GET(:OBJECT_ID, 57)
            INTO :V$CAPTION;

            SELECT :V$CAPTION || ' ' || V
            FROM VAL_GET(:OBJECT_ID, 829)
            INTO :V$CAPTION;

            IF (NOT EXISTS(
                SELECT FIRST 1 1
                FROM LINKS L79
                WHERE L79.PARENT_ID = :OBJECT_ID AND L79.OBJ_TYPE_ID = 79 AND L79.DATE_DEL IS NULL
            )) THEN
            BEGIN
                --10
                PARAMS_NAME = 'Документ удостоверяющий личность';
                ERROR_TEXT = 'Ошибка: нет документа удостоверяющего личность для обучающегося - ' || V$CAPTION;
                ERROR_NAME = 'Ошибка: нет документа удостоверяющего личность для обучающегося';
                ERROR_TYPE = 3;
                SUSPEND;    
            END
            ELSE IF (EXISTS(
                SELECT FIRST 1 1
                FROM LINKS L79
                LEFT JOIN VALL V441 ON V441.OBJ_ID = L79.OBJ_ID AND V441.PARAM_ID = 441 AND V441.IS_DEL = 0
                WHERE L79.PARENT_ID = :OBJECT_ID AND L79.OBJ_TYPE_ID = 79 AND L79.DATE_DEL IS NULL AND V441.LISTVAL_ID IS NULL
            )) THEN
            BEGIN
                --11
                PARAMS_NAME = 'Тип документа';
                ERROR_TEXT = 'Ошибка: не указан тип документа обучающегося - ' || V$CAPTION;
                ERROR_NAME = 'Ошибка: не указан тип документа обучающегося';
                ERROR_TYPE = 3;
                SUSPEND;    
            END
            IF (EXISTS(
                SELECT FIRST 1 1
                FROM LINKS L79
                LEFT JOIN VALS V559 ON V559.OBJ_ID = L79.OBJ_ID AND V559.PARAM_ID = 559 AND V559.IS_DEL = 0
                WHERE L79.PARENT_ID = :OBJECT_ID AND L79.OBJ_TYPE_ID = 79 AND L79.DATE_DEL IS NULL AND ((V559.VAL IS NULL) OR (V559.VAL NOT SIMILAR TO '[0-9]+'))
            )) THEN
            BEGIN
                --12
                PARAMS_NAME = 'Номер документа';
                ERROR_TEXT = 'Ошибка: номер документа удостоверяющего личность обучающегося не заполнен или заполнен неверно - ' || V$CAPTION;
                ERROR_NAME = 'Ошибка: номер документа удостоверяющего личность обучающегося не заполнен или заполнен неверно';
                ERROR_TYPE = 3;
                SUSPEND;    
            END
            IF (EXISTS(
                SELECT FIRST 1 1
                FROM LINKS L120
                JOIN LINKS Y120 ON Y120.OBJ_ID = L120.OBJ_ID AND Y120.PARENT_TYPE_ID = 119 AND Y120.DATE_DEL IS NULL AND Y120.PARENT_ID = :V$YEAR_ID
                JOIN VALL V802 ON V802.OBJ_ID = L120.OBJ_ID AND V802.PARAM_ID = 802 AND V802.IS_DEL = 0 AND V802.LISTVAL_ID = 3165
                WHERE L120.PARENT_ID = :OBJECT_ID AND L120.OBJ_TYPE_ID = 120 AND L120.DATE_DEL IS NULL
            )) THEN
            BEGIN
                --14
                PARAMS_NAME = 'Тип экзамена';
                ERROR_TEXT = 'Предупреждение: обучающийся зарегистрирован на экзамен второй волны - ' || V$CAPTION;
                ERROR_NAME = 'Предупреждение: обучающийся зарегистрирован на экзамен второй волны';
                ERROR_TYPE = 2;
                SUSPEND;    
            END

            Y = EXTRACT(YEAR FROM CURRENT_TIMESTAMP);
            M = EXTRACT(MONTH FROM CURRENT_TIMESTAMP);
    
            IF (M < 9) THEN
            BEGIN
                Y = Y - 1;
            END
    
            IF(EXISTS(
                SELECT FIRST 1 1
                FROM LINKS L120
                JOIN LINKS Y120 ON Y120.OBJ_ID = L120.OBJ_ID AND Y120.PARENT_TYPE_ID = 119 AND Y120.DATE_DEL IS NULL AND Y120.PARENT_ID = :V$YEAR_ID
                JOIN VALL V803 ON V803.OBJ_ID = L120.OBJ_ID AND V803.PARAM_ID = 803 AND V803.IS_DEL = 0 AND V803.LISTVAL_ID = 2926
                JOIN LINKS LP119 ON LP119.OBJ_ID = L120.OBJ_ID AND LP119.PARENT_TYPE_ID = 119 AND LP119.DATE_DEL IS NULL
                JOIN VALL V742 ON V742.OBJ_ID = LP119.PARENT_ID AND V742.PARAM_ID = 742 AND V742.IS_DEL = 0
                JOIN LISTVALS LV ON LV.LISTVAL_ID = V742.LISTVAL_ID AND LV.COST = :Y
                WHERE L120.PARENT_ID = :OBJECT_ID AND L120.PARENT_TYPE_ID = 126 AND L120.OBJ_TYPE_ID = 120 AND L120.DATE_DEL IS NULL
            )) THEN
            BEGIN
                IF (NOT EXISTS(
                    SELECT FIRST 1 1
                    FROM VALL
                    WHERE OBJ_ID = :OBJECT_ID AND PARAM_ID = 1626 AND IS_DEL = 0
                )) THEN
                BEGIN
                    ERROR_TEXT = 'Для ученика «' || :V$CAPTION || '», сдающего ГИА/ЕГЭ по информатике, не указано значение в поле «Язык программирования»';
                    ERROR_NAME = 'Для ученика, сдающего ГИА/ЕГЭ по информатике, не указано значение в поле «Язык программирования»';
                    PARAMS_NAME = 'Язык программирования';
                    ERROR_TYPE = 3;
                    SUSPEND;
                END
                IF (NOT EXISTS(
                    SELECT FIRST 1 1
                    FROM VALL
                    WHERE OBJ_ID = :OBJECT_ID AND PARAM_ID = 1628 AND IS_DEL = 0
                )) THEN
                BEGIN
                    ERROR_TEXT = 'Для ученика «' || :V$CAPTION || '», сдающего ГИА/ЕГЭ по информатике, не указано значение в поле «Среда программирования»';
                    ERROR_NAME = 'Для ученика, сдающего ГИА/ЕГЭ по информатике, не указано значение в поле «Среда программирования»';
                    PARAMS_NAME = 'Среда программирования';
                    ERROR_TYPE = 3;
                    SUSPEND;
                END
                IF (NOT EXISTS(
                    SELECT FIRST 1 1
                    FROM VALL
                    WHERE OBJ_ID = :OBJECT_ID AND PARAM_ID = 1629 AND IS_DEL = 0
                )) THEN
                BEGIN
                    ERROR_TEXT = 'Для ученика «' || :V$CAPTION || '», сдающего ГИА/ЕГЭ по информатике, не указано значение в поле «Текстовый редактор»';
                    ERROR_NAME = 'Для ученика, сдающего ГИА/ЕГЭ по информатике, не указано значение в поле «Текстовый редактор»';
                    PARAMS_NAME = 'Текстовый редактор';
                    ERROR_TYPE = 3;
                    SUSPEND;
                END
                IF (NOT EXISTS(
                    SELECT FIRST 1 1
                    FROM VALL
                    WHERE OBJ_ID = :OBJECT_ID AND PARAM_ID = 1630 AND IS_DEL = 0
                )) THEN
                BEGIN
                    ERROR_TEXT = 'Для ученика «' || :V$CAPTION || '», сдающего ГИА/ЕГЭ по информатике, не указано значение в поле «Редактор электронных таблиц»';
                    ERROR_NAME = 'Для ученика, сдающего ГИА/ЕГЭ по информатике, не указано значение в поле «Редактор электронных таблиц»';
                    PARAMS_NAME = 'Редактор электронных таблиц';
                    ERROR_TYPE = 3;
                    SUSPEND;
                END
            END
        END
        IF (I$VPL_CHECKS = 0) THEN
        BEGIN
            FOR
                SELECT TRIM(V1403.VAL)
                FROM LINKS L73
                JOIN LINKS L16 ON L16.PARENT_ID = L73.OBJ_ID AND L16.OBJ_TYPE_ID = 16 AND L16.DATE_DEL IS NULL
                JOIN LINKS L61 ON L61.PARENT_ID = L16.OBJ_ID AND L61.OBJ_TYPE_ID = 61 AND L61.DATE_DEL IS NULL
                JOIN VALS V1403 ON V1403.OBJ_ID = L61.OBJ_ID AND V1403.PARAM_ID = 1403 AND V1403.IS_DEL = 0
                WHERE L73.PARENT_ID = :I$OBJ_ID AND L73.OBJ_TYPE_ID = 73 AND L73.DATE_DEL IS NULL
                GROUP BY TRIM(V1403.VAL)
                HAVING COUNT(*) > 1
                INTO :V$TAG
            DO
            BEGIN
                V$CAPTION = '';
                FOR
                    SELECT L61.OBJ_ID
                    FROM LINKS L73
                    JOIN LINKS L16 ON L16.PARENT_ID = L73.OBJ_ID AND L16.OBJ_TYPE_ID = 16 AND L16.DATE_DEL IS NULL
                    JOIN LINKS L61 ON L61.PARENT_ID = L16.OBJ_ID AND L61.OBJ_TYPE_ID = 61 AND L61.DATE_DEL IS NULL
                    JOIN VALS V1403 ON V1403.OBJ_ID = L61.OBJ_ID AND V1403.PARAM_ID = 1403 AND V1403.IS_DEL = 0
                    WHERE L73.PARENT_ID = :I$OBJ_ID AND L73.OBJ_TYPE_ID = 73 AND L73.DATE_DEL IS NULL AND TRIM(V1403.VAL) LIKE :V$TAG
                    INTO :V$OBJ_ID
                DO
                BEGIN
                    IF (V$CAPTION <> '') THEN V$CAPTION = V$CAPTION || ', ';
                    SELECT :V$CAPTION || CAPTION
                    FROM OBJECT_CAPTION_GET(:V$OBJ_ID)
                    INTO :V$CAPTION;
                    --15
                    PARAMS_NAME = 'Обозначение аудитории';
                    ERROR_TEXT = 'Ошибка: Обозначения аудиторий для ЕГЭ повторяются - ' || V$TAG || ' Кабинеты: ' || V$CAPTION;
                    ERROR_NAME = 'Ошибка: Обозначения аудиторий для ЕГЭ повторяются';
                    ERROR_TYPE = 3;
                    SUSPEND;    
                END
    
            END

            IF (EXISTS(
                SELECT FIRST 1 1
                FROM VALI V1365
                WHERE V1365.OBJ_ID = :I$OBJ_ID AND V1365.PARAM_ID = 1365 AND V1365.IS_DEL = 0 AND V1365.VAL > 0
            )) THEN
            BEGIN
                FOR
                    SELECT L61.OBJ_ID, L61.LINK_ID, V1403.VAL
                    FROM LINKS L73
                    JOIN LINKS L16 ON L16.PARENT_ID = L73.OBJ_ID AND L16.OBJ_TYPE_ID = 16 AND L16.DATE_DEL IS NULL
                    JOIN LINKS L61 ON L61.PARENT_ID = L16.OBJ_ID AND L61.OBJ_TYPE_ID = 61 AND L61.DATE_DEL IS NULL
                    JOIN VALS V1403 ON V1403.OBJ_ID = L61.OBJ_ID AND V1403.PARAM_ID = 1403 AND V1403.IS_DEL = 0 AND V1403.VAL <> ''
                    WHERE L73.PARENT_ID = :I$OBJ_ID AND L73.OBJ_TYPE_ID = 73 AND L73.DATE_DEL IS NULL
                    INTO :OBJECT_ID, :LINK_ID, :V$TAG
                DO
                BEGIN
                    IF (NOT EXISTS(
                        SELECT FIRST 1 1
                        FROM LINKS L122
                        JOIN VALI V750 ON V750.OBJ_ID = L122.OBJ_ID AND V750.PARAM_ID = 750 AND V750.IS_DEL = 0 AND V750.VAL > 0
                        JOIN VALI V1372 ON V1372.OBJ_ID = L122.OBJ_ID AND V1372.PARAM_ID = 1372 AND V1372.IS_DEL = 0 AND V1372.VAL > 0
                        WHERE L122.PARENT_ID = :OBJECT_ID AND L122.OBJ_TYPE_ID = 122 AND L122.DATE_DEL IS NULL
                    )) THEN
                    BEGIN
                        SELECT CAPTION
                        FROM OBJECT_CAPTION_GET(:OBJECT_ID)
                        INTO :V$CAPTION;
                        PARAMS_NAME = 'Посадочных мест';
                        ERROR_TEXT = 'Ошибка: Не указана конфигурация посадочных мест в аудитории ЕГЭ - ' || V$TAG || ' Кабинет: ' || V$CAPTION;
                        ERROR_NAME = 'Ошибка: Не указана конфигурация посадочных мест в аудитории ЕГЭ';
                        ERROR_TYPE = 3;
                        SUSPEND;
                    END
                END
            END
        END
    END

    -- Служебное сообщение об успешности проверок
    IF(ERROR_TYPE = 0) THEN
    BEGIN
      ERROR_TEXT = 'Данные успешно верифицированы, замечаний и ошибок нет';
      ERROR_NAME = 'Без замечаний';
      PARAMS_NAME = NAME_TASK;
      PARENT_ID = I$OBJ_ID;
      OBJECT_ID = NULL;
      LINK_ID = NULL;
      SUSPEND;
    END

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE VERIFY_GIA_DICT (
    I$LEVEL_ID BIGINT)
RETURNS (
    TYPE_ID BIGINT,
    TYPE_NAME VARCHAR(400),
    PARAM_ID BIGINT,
    PARAM_NAME VARCHAR(400),
    PARAM_TYPE_ID BIGINT,
    PARAM_TYPE_NAME VARCHAR(100),
    VAL_REQUIRED SMALLINT,
    VAL_CHECK SMALLINT,
    VAL_MASK VARCHAR(400),
    VAL_EXTRA VARCHAR(400))
AS
begin

  -- Данный раздел есть только в сводной ведомости - в LEVELS этого приложения нет

  IF(0 = 1) THEN SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE VERIFY_MONITORING (
    I$OBJ_ID BIGINT)
RETURNS (
    LINK_ID BIGINT,
    OBJECT_ID BIGINT,
    PARENT_ID BIGINT,
    NAME_TASK VARCHAR(1000),
    ERROR_NAME VARCHAR(1000),
    PARAMS_NAME VARCHAR(1000),
    ERROR_TEXT VARCHAR(1000),
    ERROR_TYPE SMALLINT)
AS
declare variable V$PARAM_ID bigint;
BEGIN
    NAME_TASK = 'Мониторинг';
    ERROR_TYPE = 0;

    IF (EXISTS(SELECT FIRST 1 1 FROM OBJECTS WHERE OBJ_ID = :I$OBJ_ID AND TYPE_ID = 2)) THEN
    BEGIN
      IF (NOT EXISTS(SELECT FIRST 1 1 FROM LINKS WHERE PARENT_ID = :I$OBJ_ID AND OBJ_TYPE_ID = 162)) THEN
      BEGIN
        EXECUTE STATEMENT('SELECT OBJ_ID, LINK_ID FROM OBJECT_ADD(' || :I$OBJ_ID || ', 162)') WITH AUTONOMOUS TRANSACTION
        INTO :OBJECT_ID, :LINK_ID;
      END
      ELSE
      BEGIN
        SELECT FIRST 1 OBJ_ID, LINK_ID
        FROM LINKS
        WHERE PARENT_ID = :I$OBJ_ID AND OBJ_TYPE_ID = 162
        INTO :OBJECT_ID, :LINK_ID;
      END
      -- Вообще все поля мониторинга относим к warning
      -- только если этот уровень вообще виден
      FOR
        SELECT R.VAL, P.PARAM_ID
        FROM PARAMS P
        JOIN LPARAMS LP ON LP.PARAM_ID = P.PARAM_ID AND LP.IS_DEL = 0 AND LP.LEVEL_ID = 139
        JOIN LEVELS L ON L.LEVEL_ID = LP.LEVEL_ID AND L.IS_DEL = 0
        JOIN TASKS T ON T.TASK_ID = L.TASK_ID AND T.IS_DEL = 0
        JOIN MODULES M ON M.MODULE_ID = T.MODULE_ID AND M.IS_DEL = 0 AND M.IS_ACTIVE = 1
        JOIN RES R ON R.RES_ID = P.RES_ID AND R.LANG_CODE = 'RU'
        WHERE P.TYPE_ID = 162 AND P.IS_DEL = 0 AND P.PARAM_TYPE NOT IN (10, 17, 15, 19) -- AND P.PARAM_ID NOT IN (1503, 1504, 1505, 1506, 1507)
        ORDER BY P.GRID_ORDER
        INTO :PARAMS_NAME, :V$PARAM_ID
      DO
      BEGIN
        SELECT V FROM VAL_GET(:OBJECT_ID, :V$PARAM_ID) INTO :ERROR_TEXT;
        IF (ERROR_TEXT = '') THEN
        BEGIN
          ERROR_TEXT = 'Поле мониторинга "' || PARAMS_NAME || '" не заполнено';
          ERROR_NAME = 'Поле мониторинга не заполнено';
          ERROR_TYPE = 2;
          SUSPEND;
        END
      END
    END

    -- Служебное сообщение об успешности проверок
    IF(ERROR_TYPE = 0) THEN
    BEGIN
      ERROR_TEXT = 'Данные успешно верифицированы, замечаний и ошибок нет';
      ERROR_NAME = 'Без замечаний';
      PARAMS_NAME = NAME_TASK;
      PARENT_ID = I$OBJ_ID;
      OBJECT_ID = NULL;
      LINK_ID = NULL;
      SUSPEND;
    END

END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE VERIFY_MONITORING_DICT (
    I$LEVEL_ID BIGINT)
RETURNS (
    TYPE_ID BIGINT,
    TYPE_NAME VARCHAR(400),
    PARAM_ID BIGINT,
    PARAM_NAME VARCHAR(400),
    PARAM_TYPE_ID BIGINT,
    PARAM_TYPE_NAME VARCHAR(100),
    VAL_REQUIRED SMALLINT,
    VAL_CHECK SMALLINT,
    VAL_MASK VARCHAR(400),
    VAL_EXTRA VARCHAR(400))
AS
begin

  -- Проверяем что LEVEL_ID допустимый
  IF(NOT EXISTS(
    SELECT FIRST 1 1
    FROM LEVELS L
    JOIN TASKS T ON T.TASK_ID = L.TASK_ID AND T.IS_DEL = 0
    JOIN MODULES M ON M.MODULE_ID = T.MODULE_ID AND M.IS_DEL = 0 AND M.IS_ACTIVE = 1
    WHERE L.LEVEL_ID = :I$LEVEL_ID AND L.IS_DEL = 0
  ))
  THEN
    EXCEPTION DATA_ERROR 'Недопустимое приложение для контроля';

  -- Поля для объектов: только сам мониторинг
  -- заполняемые в данном приложении (RW)
  FOR
    SELECT P.TYPE_ID, P.PARAM_ID, P.PARAM_TYPE, RT.VAL, RP.VAL, P.IS_REQUIRED, IIF(P.DO_CHECK = 0, 0, 1), P.EDIT_MASK
    FROM PARAMS P
    JOIN LPARAMS LP ON LP.PARAM_ID = P.PARAM_ID AND LP.LEVEL_ID = :I$LEVEL_ID AND LP.IS_DEL = 0 AND LP.EDIT_TYPE = 1
    JOIN TYPES T ON T.TYPE_ID = P.TYPE_ID AND T.IS_DEL = 0
    JOIN RES RT ON RT.RES_ID = T.RES_ID AND RT.LANG_CODE = 'RU'
    JOIN RES RP ON RP.RES_ID = P.RES_ID AND RP.LANG_CODE = 'RU'
    WHERE P.TYPE_ID IN (162) AND P.IS_DEL = 0
      AND (P.IS_REQUIRED = 1 OR (P.EDIT_MASK IS NOT NULL AND P.EDIT_MASK <> ''))
    ORDER BY T.SORT_ORDER, P.GRID_ORDER
    INTO :TYPE_ID, :PARAM_ID, :PARAM_TYPE_ID, :TYPE_NAME, :PARAM_NAME, :VAL_REQUIRED, :VAL_CHECK, :VAL_MASK
  DO
  BEGIN
    IF(VAL_MASK = '') THEN VAL_MASK = NULL;

    IF(PARAM_TYPE_ID = 1) THEN PARAM_TYPE_NAME = 'Целое число';
    ELSE IF(PARAM_TYPE_ID = 2) THEN PARAM_TYPE_NAME = 'Вещественное число';
    ELSE IF(PARAM_TYPE_ID = 3) THEN PARAM_TYPE_NAME = 'Дата и время';
    ELSE IF(PARAM_TYPE_ID = 4) THEN PARAM_TYPE_NAME = 'Дата';
    ELSE IF(PARAM_TYPE_ID = 5) THEN PARAM_TYPE_NAME = 'Время';
    ELSE IF(PARAM_TYPE_ID = 6) THEN PARAM_TYPE_NAME = 'Значение из справочника';
    ELSE IF(PARAM_TYPE_ID = 7) THEN PARAM_TYPE_NAME = 'Строка или значение из справочника';
    ELSE IF(PARAM_TYPE_ID = 8) THEN PARAM_TYPE_NAME = 'Строка';
    ELSE IF(PARAM_TYPE_ID = 11) THEN PARAM_TYPE_NAME = 'Файл';
    ELSE IF(PARAM_TYPE_ID = 12) THEN PARAM_TYPE_NAME = 'Изображение';
    ELSE IF(PARAM_TYPE_ID = 13) THEN PARAM_TYPE_NAME = 'Ссылка на объект';
    ELSE IF(PARAM_TYPE_ID = 18) THEN PARAM_TYPE_NAME = 'Адрес';
    ELSE PARAM_TYPE_NAME = 'Недопустимый тип';

    VAL_EXTRA = NULL;
    -- IF(PARAM_ID IN (589)) THEN VAL_EXTRA = 'Уникальность';

    SUSPEND;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE VERIFY_MOVEMENT (
    I$OBJ_ID BIGINT,
    I$USER_ID BIGINT = 1,
    FLGERR1 SMALLINT = 0,
    FLGERR2 SMALLINT = 0,
    FLGERR3 SMALLINT = 0,
    FLGERR4 SMALLINT = 0,
    FLGERR5 SMALLINT = 0,
    FLGERR6 SMALLINT = 0,
    FLGERR7 SMALLINT = 0,
    FLGERR8 SMALLINT = 0,
    FLGERR9 SMALLINT = 0,
    FLGERR10 SMALLINT = 0,
    FLGERR11 SMALLINT = 0,
    FLGERR12 SMALLINT = 0,
    FLGERR13 SMALLINT = 0,
    FLGERR14 SMALLINT = 0)
RETURNS (
    LINK_ID BIGINT,
    SCHOOLAR_ID BIGINT,
    PARENT_ID BIGINT,
    NAME_TASK VARCHAR(1000),
    ERROR_NAME VARCHAR(1000),
    PARAMS_NAME VARCHAR(1000),
    LOCATION VARCHAR(1000),
    PUPIL VARCHAR(1000),
    ERROR_TEXT VARCHAR(1000),
    ERROR_TYPE SMALLINT)
AS
declare variable V$PRL_ID bigint;
declare variable V$TYPE_MOV smallint;
declare variable V$TEMP integer;
declare variable V$TMP integer;
declare variable V$CNT_OBJ_MOV integer;
declare variable V$DATECUR date;
declare variable V$Y smallint;
declare variable V$Y_LAST smallint;
declare variable V$PRL1 smallint;
declare variable V$PRL4 smallint;
declare variable V$PRL5 smallint;
declare variable V$PRL9 smallint;
declare variable V$PRL10 smallint;
declare variable V$ST1 varchar(50);
declare variable V$ST2 varchar(50);
declare variable FOLDER_VIBIL bigint;
declare variable FOLDER_VIPUSK bigint;
declare variable FOLDER_VIBIL_NAME varchar(1000);
declare variable FOLDER_VIPUSK_NAME varchar(1000);
declare variable MOVEMENT_ID bigint;
declare variable V$OBJ_ID bigint;
declare variable DT date;
BEGIN
    NAME_TASK = 'Движение обучающихся, воспитанников';
    ERROR_TYPE = 0;

    SELECT FIRST 1 CASE WHEN MAX(VLL1.LISTVAL_ID) = 40 THEN 1 ELSE 0 END
    FROM LINKS L7
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN VALL VLL ON VLL.OBJ_ID = L7.OBJ_ID AND VLL.PARAM_ID = 43 AND VLL.IS_DEL = 0 AND VLL.LISTVAL_ID = 22
    LEFT JOIN VALL VLL1 ON VLL1.OBJ_ID = L8.OBJ_ID AND VLL1.PARAM_ID = 49 AND VLL1.IS_DEL = 0
    WHERE L7.PARENT_ID = :I$OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    INTO :V$PRL4;

    SELECT FIRST 1 CASE WHEN MAX(VLL1.LISTVAL_ID) = 45 THEN 1 ELSE 0 END
    FROM LINKS L7
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN VALL VLL ON VLL.OBJ_ID = L7.OBJ_ID AND VLL.PARAM_ID = 43 AND VLL.IS_DEL = 0 AND VLL.LISTVAL_ID = 26
    LEFT JOIN VALL VLL1 ON VLL1.OBJ_ID = L8.OBJ_ID AND VLL1.PARAM_ID = 49 AND VLL1.IS_DEL = 0
    WHERE L7.PARENT_ID = :I$OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    INTO :V$PRL9;

    SELECT FIRST 1 CASE WHEN MIN(VLL1.LISTVAL_ID) = 37 THEN 1 ELSE 0 END
    FROM LINKS L7
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN VALL VLL ON VLL.OBJ_ID = L7.OBJ_ID AND VLL.PARAM_ID = 43 AND VLL.IS_DEL = 0 AND VLL.LISTVAL_ID = 22
    LEFT JOIN VALL VLL1 ON VLL1.OBJ_ID = L8.OBJ_ID AND VLL1.PARAM_ID = 49 AND VLL1.IS_DEL = 0
    WHERE L7.PARENT_ID = :I$OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    INTO :V$PRL1;

    SELECT FIRST 1 CASE WHEN MIN(VLL1.LISTVAL_ID) = 41 THEN 1 ELSE 0 END
    FROM LINKS L7
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN VALL VLL ON VLL.OBJ_ID = L7.OBJ_ID AND VLL.PARAM_ID = 43 AND VLL.IS_DEL = 0 AND VLL.LISTVAL_ID = 26
    LEFT JOIN VALL VLL1 ON VLL1.OBJ_ID = L8.OBJ_ID AND VLL1.PARAM_ID = 49 AND VLL1.IS_DEL = 0
    WHERE L7.PARENT_ID = :I$OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    INTO :V$PRL5;

    SELECT FIRST 1 CASE WHEN MIN(VLL1.LISTVAL_ID) = 46 THEN 1 ELSE 0 END
    FROM LINKS L7
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN VALL VLL ON VLL.OBJ_ID = L7.OBJ_ID AND VLL.PARAM_ID = 43 AND VLL.IS_DEL = 0 AND VLL.LISTVAL_ID = 27
    LEFT JOIN VALL VLL1 ON VLL1.OBJ_ID = L8.OBJ_ID AND VLL1.PARAM_ID = 49 AND VLL1.IS_DEL = 0
    WHERE L7.PARENT_ID = :I$OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    INTO :V$PRL10;

    V$Y = EXTRACT(YEAR FROM CURRENT_DATE);
    V$Y_LAST = V$Y - 1;

    FOR
        SELECT 0, L9.OBJ_ID, L10.OBJ_ID, L10.LINK_ID, L10.PARENT_ID
        FROM LINKS L7
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
        JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        WHERE L7.PARENT_ID = :I$OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
        UNION ALL
        SELECT 1, L.OBJ_ID, L10.OBJ_ID, L10.LINK_ID, L10.PARENT_ID
        FROM LINKS L78
        JOIN LINKS L ON L.PARENT_ID = L78.OBJ_ID AND L.OBJ_TYPE_ID IN (81, 82, 83) AND L.DATE_DEL IS NULL
        JOIN VALI VI ON VI.OBJ_ID = L.OBJ_ID AND VI.PARAM_ID = 449 AND VI.IS_DEL = 0 AND VI.VAL >= EXTRACT(YEAR FROM CURRENT_DATE)
        JOIN LINKS L10 ON L10.PARENT_ID = L.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        WHERE L78.PARENT_ID = :I$OBJ_ID AND L78.OBJ_TYPE_ID = 78 AND L78.DATE_DEL IS NULL
        INTO :V$TYPE_MOV, :V$PRL_ID, :SCHOOLAR_ID, :LINK_ID, :PARENT_ID
    DO
    BEGIN
        SELECT CAPTION FROM OBJECT_CAPTION_GET(:SCHOOLAR_ID, NULL, NULL, :I$USER_ID) INTO :PUPIL;
        SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$PRL_ID, NULL, NULL, :I$USER_ID) INTO :LOCATION;

        -- Пустых записей о движении быть не может, проверка удалена

        -- 1 --
        IF ((:FLGERR1 = 1) AND (V$TYPE_MOV IN (0, 1, 2))) THEN
        BEGIN
            SELECT COUNT(VLL.LISTVAL_ID)
            FROM VALL VLL
            WHERE VLL.PARAM_ID = 78 AND VLL.OBJ_ID = :SCHOOLAR_ID AND VLL.IS_DEL = 0
            INTO :V$TEMP;
            IF (V$TEMP = 0) THEN
            BEGIN
                ERROR_TEXT = 'Пустое поле «Принят(а) из»';
                ERROR_NAME = ERROR_TEXT;
                ERROR_TYPE = 3;
                PARAMS_NAME = 'Принят(а) из';
                SUSPEND;
            END
        END
        -- 2 --
        IF (FLGERR2 = 1 AND V$TYPE_MOV = 1) THEN
        BEGIN
            SELECT COUNT(VLL.LISTVAL_ID)
            FROM VALL VLL
            WHERE VLL.PARAM_ID = 105
            AND VLL.OBJ_ID = :SCHOOLAR_ID
            AND VLL.IS_DEL = 0
            INTO :V$TEMP;
            IF (V$TEMP = 0) THEN
            BEGIN
                ERROR_TEXT = 'Пустое поле «Выбыл(а) в»';
                ERROR_NAME = ERROR_TEXT;
                ERROR_TYPE = 3;
                PARAMS_NAME = 'Выбыл(а) из';
                SUSPEND;
            END
        END

        -- 3 -- неактуально
        -- 4 -- неактуально
        -- 5 -- неактуально
        -- 7 -- неактуально
        -- 6 -- неактуально
        -- 8 --
        IF (FLGERR8 = 1 AND V$TYPE_MOV IN (0, 1, 2)) THEN
        BEGIN
            SELECT COUNT(*)
            FROM PERSON_MOVEMENTS M
            JOIN OBJECTS O ON O.OBJ_ID = M.GROUP_ID AND O.TYPE_ID = 9
            WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :SCHOOLAR_ID AND M.REASON_IN IN (805, 806)
            INTO :V$TEMP;

            IF (V$TEMP = 0) THEN
            BEGIN
                ERROR_TEXT = 'Нет записи о прибытии';
                ERROR_NAME = ERROR_TEXT;
                ERROR_TYPE = 3;
                PARAMS_NAME = 'Запись о прибытии';
                SUSPEND;
            END
        END
        -- 9 -- неактуально (Запись о прибытии не первая по дате)
        -- 10 --
        IF (FLGERR10 = 1 AND V$TYPE_MOV IN (1, 2)) THEN
        BEGIN
            SELECT COUNT(*)
            FROM PERSON_MOVEMENTS M
            JOIN OBJECTS O ON O.OBJ_ID = M.GROUP_ID AND O.TYPE_ID = 9
            WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :SCHOOLAR_ID AND M.REASON_OUT IN (811, 812)
            INTO :V$TEMP;
            IF (V$TEMP = 0) THEN
            BEGIN
                ERROR_TEXT = 'Нет записи о выбытии';
                ERROR_NAME = ERROR_TEXT;
                ERROR_TYPE = 3;
                PARAMS_NAME = 'Запись о выбытии';
                SUSPEND;
            END
        END
        -- 11 -- переписать
        -- Запись о выбытии не последняя по дате
        IF (FLGERR11 = 1 AND V$TYPE_MOV IN (1, 2)) THEN
        BEGIN
            V$TEMP = 1;
            IF (V$TEMP = 0) THEN
            BEGIN
                ERROR_TEXT = 'Запись о выбытии не последняя по дате';
                ERROR_NAME = ERROR_TEXT;
                ERROR_TYPE = 3;
                PARAMS_NAME = 'Запись о выбытии';
                SUSPEND;
            END
        END
        -- 12 --
        IF (FLGERR12 = 1 AND V$TYPE_MOV IN (0, 1, 2)) THEN
        BEGIN
            V$TEMP = NULL;
            SELECT FIRST 1 M.DATE_IN, COUNT(*)
            FROM PERSON_MOVEMENTS M
            JOIN OBJECTS O ON O.OBJ_ID = M.GROUP_ID AND O.TYPE_ID = 9
            WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :SCHOOLAR_ID
            GROUP BY 1
            HAVING COUNT(*) > 1
            INTO :DT, :V$TEMP;

            IF (V$TEMP > 1) THEN
            BEGIN
                ERROR_TEXT = 'Две записи движения оформлены одним числом';
                ERROR_NAME = ERROR_TEXT;
                ERROR_TYPE = 3;
                PARAMS_NAME = 'Запись движения';
                SUSPEND;
            END
        END
        -- 13 --
        IF (FLGERR13 = 1 AND V$TYPE_MOV = 0) THEN
        BEGIN
            -- !!! переписать
            V$TEMP = 1; -- сверка с LOCATION
            IF (V$TEMP = 0) THEN
            BEGIN
                ERROR_TEXT = 'Учебный коллектив не соответствует текущему';
                ERROR_NAME = ERROR_TEXT;
                ERROR_TYPE = 3;
                PARAMS_NAME = 'Учебный коллектив';
                SUSPEND;
            END
        END
        -- 14 --  смотри в конце
        -- 15 -- переписать !!!
        IF (FLGERR14 = 1 AND V$TYPE_MOV = 0) THEN
        BEGIN
            IF (0 = 1 AND V$ST1 <> V$ST2) THEN
            BEGIN
                ERROR_TEXT = 'Неправильный этап или класс';
                ERROR_NAME = ERROR_TEXT;
                ERROR_TYPE = 3;
                PARAMS_NAME = 'Этап или класс';
                SUSPEND;
            END
        END
    END
    /*FOR
        SELECT DISTINCT L.OBJ_ID, L10.OBJ_ID, L10.LINK_ID, L10.PARENT_ID
        FROM LINKS L78
        JOIN LINKS L ON L.PARENT_ID = L78.OBJ_ID AND L.OBJ_TYPE_ID IN (81, 82, 83) AND L.DATE_DEL IS NULL
        JOIN LINKS L10 ON L10.PARENT_ID = L.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        WHERE L78.PARENT_ID = :I$OBJ_ID AND L78.OBJ_TYPE_ID = 78 AND L78.DATE_DEL IS NULL
        INTO :V$PRL_ID, :SCHOOLAR_ID, :LINK_ID, :PARENT_ID
    DO
    BEGIN
        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:SCHOOLAR_ID, NULL, NULL, :I$USER_ID)
        INTO :PUPIL;
        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:V$PRL_ID, NULL, NULL, :I$USER_ID)
        INTO :LOCATION;
    END*/

    -- Служебное сообщение об успешности проверок
    IF(ERROR_TYPE = 0) THEN
    BEGIN
      ERROR_TEXT = 'Данные успешно верифицированы, замечаний и ошибок нет';
      ERROR_NAME = 'Без замечаний';
      PARAMS_NAME = NAME_TASK;
      PARENT_ID = I$OBJ_ID;
      SCHOOLAR_ID = NULL;
      LINK_ID = NULL;
      LOCATION = NULL;
      PUPIL = NULL;
      SUSPEND;
    END

END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE VERIFY_MOVEMENT_DICT (
    I$LEVEL_ID BIGINT)
RETURNS (
    TYPE_ID BIGINT,
    TYPE_NAME VARCHAR(400),
    PARAM_ID BIGINT,
    PARAM_NAME VARCHAR(400),
    PARAM_TYPE_ID BIGINT,
    PARAM_TYPE_NAME VARCHAR(100),
    VAL_REQUIRED SMALLINT,
    VAL_CHECK SMALLINT,
    VAL_MASK VARCHAR(400),
    VAL_EXTRA VARCHAR(400))
AS
begin

  -- Проверяем что LEVEL_ID допустимый
  IF(NOT EXISTS(
    SELECT FIRST 1 1
    FROM LEVELS L
    JOIN TASKS T ON T.TASK_ID = L.TASK_ID AND T.IS_DEL = 0
    JOIN MODULES M ON M.MODULE_ID = T.MODULE_ID AND M.IS_DEL = 0 AND M.IS_ACTIVE = 1
    WHERE L.LEVEL_ID = :I$LEVEL_ID AND L.IS_DEL = 0
  ))
  THEN
    EXCEPTION DATA_ERROR 'Недопустимое приложение для контроля';

  -- Тут только программный контроль
  IF(0 = 1) THEn SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE VERIFY_MTR (
    I$OBJ_ID BIGINT)
RETURNS (
    LINK_ID BIGINT,
    OBJECT_ID BIGINT,
    PARENT_ID BIGINT,
    NAME_TASK VARCHAR(1000),
    ERROR_NAME VARCHAR(1000),
    PARAMS_NAME VARCHAR(1000),
    ERROR_TEXT VARCHAR(1000),
    ERROR_TYPE SMALLINT)
AS
declare variable OBJ_ID1 bigint;
declare variable OBJ_ID2 bigint;
declare variable OBJ_ID3 bigint;
declare variable NUMBER varchar(2000);
declare variable TNUMBER varchar(2000);
declare variable CNT integer;
declare variable TTXT varchar(2000);
BEGIN
    NAME_TASK = 'Материально-технические и информационные ресурсы';
    ERROR_TYPE = 0;
    TNUMBER = '';
    CNT = 0;

    -- Сначала заполнение обязательных полей и форматы ввода
    -- !!!

    PARAMS_NAME = 'Инвентарный номер';
    FOR
        SELECT L114.OBJ_ID, LX.OBJ_ID, LXX.OBJ_ID, S.VAL, LXX.PARENT_ID
        FROM LINKS LXX
        JOIN LINKS LX ON LX.PARENT_ID = LXX.OBJ_ID AND LX.OBJ_TYPE_ID IN (94,95,97,107,109,106) AND LX.DATE_DEL IS NULL
        JOIN LINKS L114 ON L114.PARENT_ID = LX.OBJ_ID AND L114.OBJ_TYPE_ID = 114 AND L114.DATE_DEL IS NULL
        JOIN VALS S ON S.OBJ_ID = L114.OBJ_ID AND S.PARAM_ID = 673 AND S.IS_DEL = 0
        WHERE LXX.PARENT_ID = :I$OBJ_ID AND LXX.OBJ_TYPE_ID IN (105, 104, 108, 92, 23, 74) AND LXX.DATE_DEL IS NULL
        ORDER BY S.VAL, 3, 2, 1
        INTO :OBJ_ID1, :OBJ_ID2, :OBJ_ID3, :NUMBER, :PARENT_ID
    DO
    BEGIN
        IF (NUMBER <> TNUMBER) THEN
        BEGIN
            TNUMBER = NUMBER;
            IF (CNT > 1) THEN
            BEGIN
                ERROR_TYPE = 2;
                SUSPEND;
            END
            CNT = 0;

            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:OBJ_ID3)
            INTO :TTXT;
            ERROR_TEXT = 'Инвентарный номер "' || NUMBER || '" использован несколько раз: ' || TTXT;
            ERROR_NAME = 'Инвентарный номер использован несколько раз';
            SELECT V
            FROM VAL_GET(:OBJ_ID1,674)
            INTO :TTXT;
            ERROR_TEXT = ERROR_TEXT || ' - ' || TTXT;
        END
        ELSE
        BEGIN
            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:OBJ_ID3)
            INTO :TTXT;
            IF (CHAR_LENGTH(ERROR_TEXT) + CHAR_LENGTH(TTXT) + CHAR_LENGTH(', ') < 1000) THEN
            BEGIN
                ERROR_TEXT = ERROR_TEXT || ', ' || TTXT;
            END
            SELECT V
            FROM VAL_GET(:OBJ_ID1,674)
            INTO :TTXT;
            IF (CHAR_LENGTH(ERROR_TEXT) + CHAR_LENGTH(TTXT) + CHAR_LENGTH(' - ') < 1000) THEN
            BEGIN
                ERROR_TEXT = ERROR_TEXT || ' - ' || TTXT;
            END
        END
        CNT = CNT + 1;
    END
    IF ((ERROR_TEXT <> '') AND (CNT > 1)) THEN
    BEGIN
        ERROR_TYPE = 2;
        SUSPEND;
    END

    -- Служебное сообщение об успешности проверок
    IF(ERROR_TYPE = 0) THEN
    BEGIN
      ERROR_TEXT = 'Данные успешно верифицированы, замечаний и ошибок нет';
      ERROR_NAME = 'Без замечаний';
      PARAMS_NAME = NAME_TASK;
      PARENT_ID = I$OBJ_ID;
      OBJECT_ID = NULL;
      LINK_ID = NULL;
      SUSPEND;
    END

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE VERIFY_MTR_DICT (
    I$LEVEL_ID BIGINT)
RETURNS (
    TYPE_ID BIGINT,
    TYPE_NAME VARCHAR(400),
    PARAM_ID BIGINT,
    PARAM_NAME VARCHAR(400),
    PARAM_TYPE_ID BIGINT,
    PARAM_TYPE_NAME VARCHAR(100),
    VAL_REQUIRED SMALLINT,
    VAL_CHECK SMALLINT,
    VAL_MASK VARCHAR(400),
    VAL_EXTRA VARCHAR(400))
AS
begin

  -- Проверяем что LEVEL_ID допустимый
  IF(NOT EXISTS(
    SELECT FIRST 1 1
    FROM LEVELS L
    JOIN TASKS T ON T.TASK_ID = L.TASK_ID AND T.IS_DEL = 0
    JOIN MODULES M ON M.MODULE_ID = T.MODULE_ID AND M.IS_DEL = 0 AND M.IS_ACTIVE = 1
    WHERE L.LEVEL_ID = :I$LEVEL_ID AND L.IS_DEL = 0
  ))
  THEN
    EXCEPTION DATA_ERROR 'Недопустимое приложение для контроля';

  -- Поля для объектов: МТР всех видов
  -- заполняемые в данном приложении (RW)
  FOR
    SELECT P.TYPE_ID, P.PARAM_ID, P.PARAM_TYPE, RT.VAL, RP.VAL, P.IS_REQUIRED, IIF(P.DO_CHECK = 0, 0, 1), P.EDIT_MASK
    FROM PARAMS P
    JOIN LPARAMS LP ON LP.PARAM_ID = P.PARAM_ID AND LP.LEVEL_ID = :I$LEVEL_ID AND LP.IS_DEL = 0 AND LP.EDIT_TYPE = 1
    JOIN TYPES T ON T.TYPE_ID = P.TYPE_ID AND T.IS_DEL = 0
    JOIN RES RT ON RT.RES_ID = T.RES_ID AND RT.LANG_CODE = 'RU'
    JOIN RES RP ON RP.RES_ID = P.RES_ID AND RP.LANG_CODE = 'RU'
    WHERE P.TYPE_ID IN (94, 95, 97, 114, 106, 107, 109, 117, 128) AND P.IS_DEL = 0
      AND (P.IS_REQUIRED = 1 OR (P.EDIT_MASK IS NOT NULL AND P.EDIT_MASK <> ''))
    ORDER BY T.SORT_ORDER, P.GRID_ORDER
    INTO :TYPE_ID, :PARAM_ID, :PARAM_TYPE_ID, :TYPE_NAME, :PARAM_NAME, :VAL_REQUIRED, :VAL_CHECK, :VAL_MASK
  DO
  BEGIN
    IF(VAL_MASK = '') THEN VAL_MASK = NULL;

    IF(PARAM_TYPE_ID = 1) THEN PARAM_TYPE_NAME = 'Целое число';
    ELSE IF(PARAM_TYPE_ID = 2) THEN PARAM_TYPE_NAME = 'Вещественное число';
    ELSE IF(PARAM_TYPE_ID = 3) THEN PARAM_TYPE_NAME = 'Дата и время';
    ELSE IF(PARAM_TYPE_ID = 4) THEN PARAM_TYPE_NAME = 'Дата';
    ELSE IF(PARAM_TYPE_ID = 5) THEN PARAM_TYPE_NAME = 'Время';
    ELSE IF(PARAM_TYPE_ID = 6) THEN PARAM_TYPE_NAME = 'Значение из справочника';
    ELSE IF(PARAM_TYPE_ID = 7) THEN PARAM_TYPE_NAME = 'Строка или значение из справочника';
    ELSE IF(PARAM_TYPE_ID = 8) THEN PARAM_TYPE_NAME = 'Строка';
    ELSE IF(PARAM_TYPE_ID = 11) THEN PARAM_TYPE_NAME = 'Файл';
    ELSE IF(PARAM_TYPE_ID = 12) THEN PARAM_TYPE_NAME = 'Изображение';
    ELSE IF(PARAM_TYPE_ID = 13) THEN PARAM_TYPE_NAME = 'Ссылка на объект';
    ELSE IF(PARAM_TYPE_ID = 18) THEN PARAM_TYPE_NAME = 'Адрес';
    ELSE PARAM_TYPE_NAME = 'Недопустимый тип';

    VAL_EXTRA = NULL;
    -- IF(PARAM_ID IN (589)) THEN VAL_EXTRA = 'Уникальность';

    SUSPEND;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE VERIFY_OBJECT_FIELDS (
    I$OBJ_ID BIGINT,
    I$TYPE_ID BIGINT,
    I$SUBTITLE VARCHAR(100),
    I$TITLE VARCHAR(400))
RETURNS (
    ERROR_TYPE SMALLINT,
    PARAM_ID BIGINT,
    PARAMS_NAME VARCHAR(400),
    ERROR_NAME VARCHAR(1000),
    ERROR_TEXT VARCHAR(1000))
AS
DECLARE VARIABLE V$IS_REQUIRED SMALLINT;
DECLARE VARIABLE V$DO_CHECK BIGINT;
DECLARE VARIABLE V$EXISTS SMALLINT;
DECLARE VARIABLE V$MASK VARCHAR(400);
DECLARE VARIABLE V$PARAM_TYPE BIGINT;
DECLARE VARIABLE V$LV BIGINT;
DECLARE VARIABLE V VARCHAR(4000);
DECLARE VARIABLE X SMALLINT;
DECLARE VARIABLE V$STATUS VARCHAR(2);
begin

  -- ERROR_TYPE 1..5: Автокоррекция, Предупреждение, Ошибка, Правка, Отчет заполненности данных
  -- 0 = hint

  V$STATUS = (SELECT STATUS FROM OU_LICENCE_TYPE);

  FOR
    SELECT DISTINCT P.PARAM_ID, R.VAL, P.IS_REQUIRED, P.DO_CHECK, P.EDIT_MASK, P.PARAM_TYPE, V.V, V.I, V.IS_EXISTS
    FROM PARAMS P
    JOIN LPARAMS LP ON LP.PARAM_ID = P.PARAM_ID AND LP.EDIT_TYPE = 1 AND LP.IS_DEL = 0
    JOIN LEVELS L ON L.LEVEL_ID = LP.LEVEL_ID AND L.IS_DEL = 0
    JOIN TASKS T ON T.TASK_ID = L.TASK_ID AND T.IS_DEL = 0
    JOIN MODULES M ON M.MODULE_ID = T.MODULE_ID AND T.IS_DEL = 0 AND M.IS_ACTIVE = 1
    JOIN RES R ON R.RES_ID = P.RES_ID AND R.LANG_CODE = 'RU'
    LEFT JOIN VAL_GET(:I$OBJ_ID, P.PARAM_ID) V ON 1 = 1
    WHERE P.TYPE_ID = :I$TYPE_ID AND P.IS_DEL = 0 AND (P.IS_REQUIRED = 1 OR P.DO_CHECK > 0 OR (P.EDIT_MASK IS NOT NULL AND P.EDIT_MASK <> ''))
    ORDER BY P.GRID_ORDER
    INTO :PARAM_ID, :PARAMS_NAME, :V$IS_REQUIRED, :V$DO_CHECK, :V$MASK, :V$PARAM_TYPE, :V, :V$LV, :V$EXISTS
  DO
  BEGIN
    -- Понижаем уровень проверки для всего кроме ОУ
    -- Для: сотрудники, здания, помещения, учебный коллектив
    IF(V$STATUS <> 'O' AND I$TYPE_ID IN (14, 16, 61, 9) AND V$IS_REQUIRED = 1) THEN V$IS_REQUIRED = 2;

    -- Убираем избранные параметры в СПО: ЦОПП, Заканчивает обучение
    -- Убираем поля про семью, статус личного дела, контекстные поля УП, год публикации ОП
    IF(PARAM_ID IN (3063, 3071, 3072, 3344, 118, 119, 3447, 3022, 3435, 3014, 3016, 3115) AND V$IS_REQUIRED > 0) THEN V$IS_REQUIRED = 0;

    -- Поля с типами файл, изображение - временно понижаем статус проверки
    IF(V$PARAM_TYPE IN (11, 12) AND V$IS_REQUIRED = 1) THEN V$IS_REQUIRED = 2;

    -- Понижаем уровень проверки для отдельных полей
    -- Ссылка на земельный участок, адаптированность ОП
    IF(PARAM_ID IN (3407, 3408, 2379) AND V$IS_REQUIRED = 1) THEN V$IS_REQUIRED = 2;

    IF(V$IS_REQUIRED > 0 AND V$EXISTS = 0) THEN
    BEGIN
      ERROR_TEXT = 'Поле «' || PARAMS_NAME || '» для ' || I$SUBTITLE || ' «' || I$TITLE || '» должно быть заполнено';
      ERROR_NAME = 'Поле «' || PARAMS_NAME || '» для ' || I$SUBTITLE || ' должно быть заполнено';
      IF(V$IS_REQUIRED = 1) THEN ERROR_TYPE = 3; ELSE ERROR_TYPE = 2;
      SUSPEND;
    END
    ELSE IF(V$EXISTS = 1) THEN
    BEGIN
      -- Поле заполнено
      -- Сверка по шаблону
      ERROR_TYPE = 1;
      IF(V$MASK IS NOT NULL AND V$MASK <> '') THEN
      BEGIN
        -- FB не поддерживает расширенный синтаксис regexp
        -- также пропускаем отдельные параметры со странностями
        -- )* это веб-ссылки
        IF(POSITION('*)' IN V$MASK) > 0) THEN
        BEGIN
        END
        ELSE IF(PARAM_ID IN (35, 144, 1180, 3076, 3167, 3400, 1753, 2460) OR POSITION(')*' IN V$MASK) > 0) THEN
        BEGIN
        END
        ELSE
        BEGIN
          V$MASK = TRIM(REPLACE(V$MASK, 'REXPEX:', ''));
          V$MASK = REPLACE(V$MASK, '\x20', ' ');
          X = 1;
          BEGIN
            IF(V NOT SIMILAR TO V$MASK ESCAPE '\') THEN X = 0;
            WHEN ANY DO EXCEPTION DATA_ERROR 'Ошибка маски параметра ' || PARAM_ID;
          END
          IF(X = 0) THEN
          BEGIN
            ERROR_TEXT = 'Поле «' || PARAMS_NAME || '» для ' || I$SUBTITLE || ' «' || I$TITLE || '» не соответствует шаблону';
            ERROR_NAME = 'Поле «' || PARAMS_NAME || '» для ' || I$SUBTITLE || ' не соответствует шаблону';
            ERROR_TYPE = 3;
            -- Номера телефонов
            IF(PARAM_ID IN (253, 254)) THEN ERROR_TYPE = 2;
            SUSPEND;
          END
        END
      END
      -- Если нет ошибки с шаблоном, проверяем алгоритмически
      IF(ERROR_TYPE = 1 AND V$DO_CHECK > 0) THEN
      BEGIN
        IF(V$PARAM_TYPE IN (6, 13)) THEN
          SELECT IS_OK, MSG
          FROM DO_CHECK(:I$OBJ_ID, :PARAM_ID, :V$LV, :V$DO_CHECK, 2)
          INTO :X, :V;
        ELSE
          SELECT IS_OK, MSG
          FROM DO_CHECK(:I$OBJ_ID, :PARAM_ID, :V, :V$DO_CHECK, 2)
          INTO :X, :V;

        IF(X = 0) THEN
        BEGIN
          ERROR_TEXT = 'Поле «' || PARAMS_NAME || '» для ' || I$SUBTITLE || ' «' || I$TITLE || '» невалидно, ' || V;
          ERROR_NAME = 'Поле «' || PARAMS_NAME || '» для ' || I$SUBTITLE || ' невалидно';
          ERROR_TYPE = 3;
          SUSPEND;
        END
      END
    END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE VERIFY_OP (
    I$OBJ_ID BIGINT)
RETURNS (
    LINK_ID BIGINT,
    OBJECT_ID BIGINT,
    PARENT_ID BIGINT,
    NAME_TASK VARCHAR(1000),
    ERROR_NAME VARCHAR(1000),
    PARAMS_NAME VARCHAR(1000),
    ERROR_TEXT VARCHAR(1000),
    ERROR_TYPE SMALLINT)
AS
declare variable V$OU_LICENCE_TYPE varchar(1);
declare variable V$LEVEL_ID integer;
declare variable V$TYPE_ID bigint;
declare variable S varchar(1000);
declare variable SS varchar(1000);
declare variable V$STATUS bigint;
declare variable V$Y integer;
declare variable V$GY integer;
declare variable V$OPTYPE bigint;
BEGIN

    NAME_TASK = 'Образовательные программы и Учебные планы';
    ERROR_TYPE = 0;

    SELECT STATUS FROM OU_LICENCE_TYPE INTO :V$OU_LICENCE_TYPE;
    SELECT KEY_VAL FROM KEYS WHERE KEY_CODE = 'LEVEL' INTO :V$LEVEL_ID;

    SELECT FIRST 1 LV.COST
    FROM VALL V1236
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
    WHERE V1236.OBJ_ID = :I$OBJ_ID AND V1236.PARAM_ID = 1216 AND V1236.IS_DEL = 0
    INTO :V$GY;

    FOR
      SELECT L69.OBJ_ID, L69.LINK_ID, L69.PARENT_ID, L69.OBJ_TYPE_ID, NULL, NULL, V2450.LISTVAL_ID
      FROM LINKS L69
      LEFT JOIN VALL V2450 ON V2450.OBJ_ID = L69.OBJ_ID AND V2450.PARAM_ID = 2450 AND V2450.IS_DEL = 0
      WHERE L69.DATE_DEL IS NULL AND L69.PARENT_ID = :I$OBJ_ID AND L69.OBJ_TYPE_ID = 69
      UNION
      SELECT L57.OBJ_ID, L57.LINK_ID, L57.PARENT_ID, L57.OBJ_TYPE_ID, NULL, NULL, V2450.LISTVAL_ID
      FROM LINKS L69
      LEFT JOIN VALL V2450 ON V2450.OBJ_ID = L69.OBJ_ID AND V2450.PARAM_ID = 2450 AND V2450.IS_DEL = 0
      JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
      WHERE L69.DATE_DEL IS NULL AND L69.PARENT_ID = :I$OBJ_ID AND L69.OBJ_TYPE_ID = 69
      UNION
      SELECT L400.OBJ_ID, L400.LINK_ID, L400.PARENT_ID, L400.OBJ_TYPE_ID, V3013.LISTVAL_ID, V3115.VAL, V2450.LISTVAL_ID
      FROM LINKS L69
      LEFT JOIN VALL V2450 ON V2450.OBJ_ID = L69.OBJ_ID AND V2450.PARAM_ID = 2450 AND V2450.IS_DEL = 0
      JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
      LEFT JOIN VALI V3115 ON V3115.OBJ_ID = L57.OBJ_ID AND V3115.PARAM_ID = 3115 AND V3115.IS_DEL = 0
      JOIN LINKS L400 ON L400.PARENT_ID = L57.OBJ_ID AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL
      LEFT JOIN VALL V3013 ON V3013.OBJ_ID = L400.OBJ_ID AND V3013.PARAM_ID = 3013 AND V3013.IS_DEL = 0
      WHERE L69.DATE_DEL IS NULL AND L69.PARENT_ID = :I$OBJ_ID AND L69.OBJ_TYPE_ID = 69
      ORDER BY 4
      INTO :OBJECT_ID, :LINK_ID, :PARENT_ID, :V$TYPE_ID, :V$STATUS, :V$Y, :V$OPTYPE
    DO
    BEGIN
      SELECT CAPTION FROM OBJECT_CAPTION_GET(:OBJECT_ID) INTO :S;

      IF(V$TYPE_ID = 69) THEN SS = 'образовательных программ';
      ELSE IF(V$TYPE_ID = 57) THEN SS = 'образовательной программы';
      ELSE IF(V$TYPE_ID = 400) THEN SS = 'учебного плана';
      ELSE SS = '#' || V$TYPE_ID;

      FOR
        SELECT ERROR_TYPE, ERROR_TEXT, ERROR_NAME, PARAMS_NAME
        FROM VERIFY_OBJECT_FIELDS(:OBJECT_ID, :V$TYPE_ID, :SS, :S)
        INTO :ERROR_TYPE, :ERROR_TEXT, :ERROR_NAME, :PARAMS_NAME
      DO
      BEGIN
        SUSPEND;
      END

      -- Отсутствие утвержденных УП со старыми годами утверждения
      -- В СПО проверка не сработает поскольку не будет указан год в ОП
      -- Для школ проверяем только для ОП общего образования
      IF(V$TYPE_ID = 400 AND V$OPTYPE = 11385 AND V$STATUS = 11715 AND V$Y <> V$GY AND V$Y <> V$GY + 1) THEN
      BEGIN
        ERROR_TEXT = 'Год публикации ОП для действующего УП "' || S || '" не соответствует текущему или следующему учебному году';
        ERROR_NAME = 'Действующий учебный план с недопустимым годом публикации ОП';
        ERROR_TYPE = 3;
        SUSPEND;
      END

    END

    -- Служебное сообщение об успешности проверок
    IF(ERROR_TYPE = 0) THEN
    BEGIN
      ERROR_TEXT = 'Данные успешно верифицированы, замечаний и ошибок нет';
      ERROR_NAME = 'Без замечаний';
      PARAMS_NAME = NAME_TASK;
      PARENT_ID = I$OBJ_ID;
      OBJECT_ID = NULL;
      LINK_ID = NULL;
      SUSPEND;
    END

END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE VERIFY_OP_DICT (
    I$LEVEL_ID BIGINT)
RETURNS (
    TYPE_ID BIGINT,
    TYPE_NAME VARCHAR(400),
    PARAM_ID BIGINT,
    PARAM_NAME VARCHAR(400),
    PARAM_TYPE_ID BIGINT,
    PARAM_TYPE_NAME VARCHAR(100),
    VAL_REQUIRED SMALLINT,
    VAL_CHECK SMALLINT,
    VAL_MASK VARCHAR(400),
    VAL_EXTRA VARCHAR(400))
AS
begin

  -- Проверяем что LEVEL_ID допустимый
  IF(NOT EXISTS(
    SELECT FIRST 1 1
    FROM LEVELS L
    JOIN TASKS T ON T.TASK_ID = L.TASK_ID AND T.IS_DEL = 0
    JOIN MODULES M ON M.MODULE_ID = T.MODULE_ID AND M.IS_DEL = 0 AND M.IS_ACTIVE = 1
    WHERE L.LEVEL_ID = :I$LEVEL_ID AND L.IS_DEL = 0
  ))
  THEN
    EXCEPTION DATA_ERROR 'Недопустимое приложение для контроля';

  -- Поля для объектов: МТР всех видов
  -- заполняемые в данном приложении (RW)
  FOR
    SELECT P.TYPE_ID, P.PARAM_ID, P.PARAM_TYPE, RT.VAL, RP.VAL, P.IS_REQUIRED, IIF(P.DO_CHECK = 0, 0, 1), P.EDIT_MASK
    FROM PARAMS P
    JOIN LPARAMS LP ON LP.PARAM_ID = P.PARAM_ID AND LP.LEVEL_ID = :I$LEVEL_ID AND LP.IS_DEL = 0 AND LP.EDIT_TYPE = 1
    JOIN TYPES T ON T.TYPE_ID = P.TYPE_ID AND T.IS_DEL = 0
    JOIN RES RT ON RT.RES_ID = T.RES_ID AND RT.LANG_CODE = 'RU'
    JOIN RES RP ON RP.RES_ID = P.RES_ID AND RP.LANG_CODE = 'RU'
    WHERE P.TYPE_ID IN (57, 69, 400, 478) AND P.IS_DEL = 0
      AND (P.IS_REQUIRED = 1 OR (P.EDIT_MASK IS NOT NULL AND P.EDIT_MASK <> ''))
    ORDER BY T.SORT_ORDER, P.GRID_ORDER
    INTO :TYPE_ID, :PARAM_ID, :PARAM_TYPE_ID, :TYPE_NAME, :PARAM_NAME, :VAL_REQUIRED, :VAL_CHECK, :VAL_MASK
  DO
  BEGIN
    IF(VAL_MASK = '') THEN VAL_MASK = NULL;

    IF(PARAM_TYPE_ID = 1) THEN PARAM_TYPE_NAME = 'Целое число';
    ELSE IF(PARAM_TYPE_ID = 2) THEN PARAM_TYPE_NAME = 'Вещественное число';
    ELSE IF(PARAM_TYPE_ID = 3) THEN PARAM_TYPE_NAME = 'Дата и время';
    ELSE IF(PARAM_TYPE_ID = 4) THEN PARAM_TYPE_NAME = 'Дата';
    ELSE IF(PARAM_TYPE_ID = 5) THEN PARAM_TYPE_NAME = 'Время';
    ELSE IF(PARAM_TYPE_ID = 6) THEN PARAM_TYPE_NAME = 'Значение из справочника';
    ELSE IF(PARAM_TYPE_ID = 7) THEN PARAM_TYPE_NAME = 'Строка или значение из справочника';
    ELSE IF(PARAM_TYPE_ID = 8) THEN PARAM_TYPE_NAME = 'Строка';
    ELSE IF(PARAM_TYPE_ID = 11) THEN PARAM_TYPE_NAME = 'Файл';
    ELSE IF(PARAM_TYPE_ID = 12) THEN PARAM_TYPE_NAME = 'Изображение';
    ELSE IF(PARAM_TYPE_ID = 13) THEN PARAM_TYPE_NAME = 'Ссылка на объект';
    ELSE IF(PARAM_TYPE_ID = 18) THEN PARAM_TYPE_NAME = 'Адрес';
    ELSE PARAM_TYPE_NAME = 'Недопустимый тип';

    VAL_EXTRA = NULL;
    -- IF(PARAM_ID IN (589)) THEN VAL_EXTRA = 'Уникальность';

    SUSPEND;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE VERIFY_OP_DURATION (
    I$OBJ_ID BIGINT,
    I$VAL VARCHAR(1000))
AS
declare variable V$OU_LICENCE_TYPE char(1);
declare variable V$OP_TYPE bigint;
declare variable V$ADAPT bigint;
declare variable V integer;
begin

  -- Только для школ !
  V$OU_LICENCE_TYPE = (SELECT STATUS FROM OU_LICENCE_TYPE);

  -- Вводить можно только указав адаптированность и тип
  SELECT FIRST 1 V.LISTVAL_ID
  FROM VALL V
  WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 1832 AND V.IS_DEL = 0
  INTO :V$OP_TYPE;

  SELECT FIRST 1 V.LISTVAL_ID
  FROM VALL V
  WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 2379 AND V.IS_DEL = 0
  INTO :V$ADAPT;

  IF(V$OU_LICENCE_TYPE = 'D') THEN V$ADAPT = 11187; -- чтобы не ругалось

  IF(V$OU_LICENCE_TYPE IN ('O', 'D')) THEN
  BEGIN

    IF(V$OP_TYPE IS NULL OR V$ADAPT IS NULL) THEN EXCEPTION DATA_ERROR 'Сначала необходимо заполнить вид и адаптированность ОП';

    -- Только число
    V = I$VAL;

    -- ДО
    IF(V$OP_TYPE = 5338) THEN
    BEGIN
      IF(V NOT IN (1, 2, 3, 4, 5, 6, 7, 8)) THEN EXCEPTION DATA_ERROR 'Допустимое значение 1...8';
    END
    -- НО
    ELSE IF(V$OP_TYPE = 5340) THEN
    BEGIN
      IF(V$ADAPT = 11187) THEN
      BEGIN
        IF(V <> 4) THEN EXCEPTION DATA_ERROR 'Допустимые значения: только 4';
      END
      ELSE
      BEGIN
        IF(V NOT IN (4, 5, 6)) THEN EXCEPTION DATA_ERROR 'Допустимые значения: 4, 5, 6';
      END
    END
    -- ОО
    ELSE IF(V$OP_TYPE = 5342) THEN
    BEGIN
      IF(V$ADAPT = 11187) THEN
      BEGIN
        IF(V <> 5) THEN EXCEPTION DATA_ERROR 'Допустимые значения: только 5';
      END
      ELSE
      BEGIN
        IF(V NOT IN (5, 6)) THEN EXCEPTION DATA_ERROR 'Допустимые значения: 5, 6';
      END
    END
    -- СО
    ELSE IF(V$OP_TYPE = 5344) THEN
    BEGIN
      IF(V$ADAPT = 11187) THEN
      BEGIN
        IF(V <> 2) THEN EXCEPTION DATA_ERROR 'Допустимые значения: только 2';
      END
      ELSE
      BEGIN
        IF(V NOT IN (2, 3)) THEN EXCEPTION DATA_ERROR 'Допустимые значения: 2, 3';
      END
    END
    -- АООП
    ELSE IF(V$OP_TYPE = 13287) THEN
    BEGIN
      IF(V NOT IN (9, 10, 12, 13)) THEN EXCEPTION DATA_ERROR 'Допустимые значения: 9, 10, 12, 13';
    END

  END

  WHEN SQLCODE -413 DO
  BEGIN
    EXCEPTION DATA_ERROR 'Требуется ввести число, соответствующее количеству лет нормативного срока освоения ОП';
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE VERIFY_PARAM_ADD (
    I$OBJ_ID BIGINT,
    I$TYPE_ID BIGINT,
    I$PARAM_ID BIGINT,
    I$MATCH_VAL_ID BIGINT,
    I$MATCH_VAL VARCHAR(4000),
    I$LIVE_ID BIGINT,
    I$ACTIVE BIGINT,
    I$MINVAL DOUBLE PRECISION,
    I$MAXVAL DOUBLE PRECISION,
    I$USER_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$STATUS varchar(10);
declare variable V$DT timestamp;
declare variable T integer;
declare variable V$LINK_ID bigint;
declare variable V$IS_CHILD smallint;
declare variable V$IS_PARENT smallint;
declare variable V$IS_STUFF smallint;
declare variable V$IS_ANY smallint;
begin

  V$STATUS = (SELECT STATUS FROM OU_LICENCE_TYPE);

  -- Условие всегда хранится в одном поле, что текстовое, что ID
  IF(I$MATCH_VAL IS NULL) THEN I$MATCH_VAL = I$MATCH_VAL_ID;
  -- По умолчанию = Все
  IF(I$LIVE_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не указано расположение или статус данных';
  -- Если не указано, то делаем предупредительным
  IF(I$ACTIVE IS NULL) THEN I$ACTIVE = 15822;

  -- Проверяем дубли
  SELECT FIRST 1 L498.OBJ_ID, L498.DATE_DEL
  FROM LINKS L498
  JOIN VALI V3453 ON V3453.OBJ_ID = L498.OBJ_ID AND V3453.PARAM_ID = 3453 AND V3453.IS_DEL = 0 AND V3453.VAL = :I$TYPE_ID
  JOIN VALI V3449 ON V3449.OBJ_ID = L498.OBJ_ID AND V3449.PARAM_ID = 3449 AND V3449.IS_DEL = 0 AND V3449.VAL = :I$PARAM_ID
  JOIN VALL V3468 ON V3468.OBJ_ID = L498.OBJ_ID AND V3468.PARAM_ID = 3468 AND V3468.IS_DEL = 0 AND V3468.LISTVAL_ID = :I$LIVE_ID
  LEFT JOIN VALS V3455 ON V3455.OBJ_ID = L498.OBJ_ID AND V3455.PARAM_ID = 3455 AND V3455.IS_DEL = 0
  WHERE L498.PARENT_ID = :I$OBJ_ID AND L498.OBJ_TYPE_ID = 498
    AND ((:I$MATCH_VAL IS NULL AND V3455.VAL IS NULL) OR (V3455.VAL = :I$MATCH_VAL))
    AND ((:I$MATCH_VAL IS NULL AND V3455.VAL IS NULL) OR (V3455.VAL = :I$MATCH_VAL))
  INTO :OBJ_ID, :V$DT;

  IF(OBJ_ID IS NOT NULL AND V$DT IS NULL) THEN EXCEPTION DATA_ERROR 'Параметр с такими условиями проверки уже есть';

  -- Группы по пути поиска, проверяем соответствие параметра и маршрута поиска
  -- Параметры, которые есть только в подчиненных данных конкретной сущности
  V$IS_CHILD = 0;
  V$IS_STUFF = 0;
  V$IS_PARENT = 0;
  V$IS_ANY = 0;

  SELECT COUNT(DISTINCT P2.TYPE_ID)
  FROM PARENTS P1
  JOIN PARENTS P2 ON P2.CHILD_ID = P1.CHILD_ID AND P2.TYPE_ID IN (10, 126, 14, 20) AND P2.IS_DEL = 0
  -- есть приложение, где вводится данный тип и хотя бы виден родительский
  JOIN LTYPES LT1 ON LT1.TYPE_ID = P1.CHILD_ID AND LT1.EDIT_TYPE = 1 AND LT1.IS_DEL = 0
  JOIN LTYPES LT1P ON LT1P.TYPE_ID = P1.TYPE_ID AND LT1P.EDIT_TYPE >= 0 AND LT1P.IS_DEL = 0 AND LT1P.LEVEL_ID = LT1.LEVEL_ID
  JOIN LEVELS L1 ON L1.LEVEL_ID = LT1.LEVEL_ID AND L1.IS_DEL = 0
  JOIN TASKS TS1 ON TS1.TASK_ID = L1.TASK_ID AND TS1.IS_DEL = 0
  -- модули: ДОУ, школа, СПО, ОДОД исходя из того, что выбрано
  JOIN MODULES M ON M.MODULE_ID = TS1.MODULE_ID AND M.IS_DEL = 0 AND (
    (:V$STATUS = 'D' AND M.MODULE_ID = 3) OR
    (:V$STATUS = 'O' AND M.MODULE_ID = 4) OR
    (:V$STATUS = 'C' AND M.MODULE_ID = 5) OR
    (:V$STATUS = 'U' AND M.MODULE_ID = 45) OR
    (:V$STATUS = 'P' AND M.MODULE_ID = 76)
  )
  -- и досматриваем, чтобы вторая ветка тоже существовала в этом модуле
  JOIN LTYPES LT2 ON LT2.TYPE_ID = P2.CHILD_ID AND LT2.EDIT_TYPE = 1 AND LT2.IS_DEL = 0
  JOIN LTYPES LT2P ON LT2P.TYPE_ID = P2.TYPE_ID AND LT2P.EDIT_TYPE >= 0 AND LT2P.IS_DEL = 0 AND LT2P.LEVEL_ID = LT2.LEVEL_ID
  JOIN LEVELS L2 ON L2.LEVEL_ID = LT2.LEVEL_ID AND L2.IS_DEL = 0
  JOIN TASKS TS2 ON TS2.TASK_ID = L2.TASK_ID AND TS2.IS_DEL = 0 AND TS2.MODULE_ID = M.MODULE_ID
  WHERE P1.CHILD_ID = :I$TYPE_ID AND P1.TYPE_ID IN (10, 126) AND P1.IS_DEL = 0
  INTO :V$IS_CHILD;

  SELECT COUNT(DISTINCT P2.TYPE_ID)
  FROM PARENTS P1
  JOIN PARENTS P2 ON P2.CHILD_ID = P1.CHILD_ID AND P2.TYPE_ID IN (10, 126, 14, 20) AND P2.IS_DEL = 0
  -- есть приложение, где вводится данный тип и хотя бы виден родительский
  JOIN LTYPES LT1 ON LT1.TYPE_ID = P1.CHILD_ID AND LT1.EDIT_TYPE = 1 AND LT1.IS_DEL = 0
  JOIN LTYPES LT1P ON LT1P.TYPE_ID = P1.TYPE_ID AND LT1P.EDIT_TYPE >= 0 AND LT1P.IS_DEL = 0 AND LT1P.LEVEL_ID = LT1.LEVEL_ID
  JOIN LEVELS L1 ON L1.LEVEL_ID = LT1.LEVEL_ID AND L1.IS_DEL = 0
  JOIN TASKS TS1 ON TS1.TASK_ID = L1.TASK_ID AND TS1.IS_DEL = 0
  -- модули: ДОУ, школа, СПО, ОДОД исходя из того, что выбрано
  JOIN MODULES M ON M.MODULE_ID = TS1.MODULE_ID AND M.IS_DEL = 0 AND (
    (:V$STATUS = 'D' AND M.MODULE_ID = 3) OR
    (:V$STATUS = 'O' AND M.MODULE_ID = 4) OR
    (:V$STATUS = 'C' AND M.MODULE_ID = 5) OR
    (:V$STATUS = 'U' AND M.MODULE_ID = 45) OR
    (:V$STATUS = 'P' AND M.MODULE_ID = 76)
  )
  -- и досматриваем, чтобы вторая ветка тоже существовала в этом модуле
  JOIN LTYPES LT2 ON LT2.TYPE_ID = P2.CHILD_ID AND LT2.EDIT_TYPE = 1 AND LT2.IS_DEL = 0
  JOIN LTYPES LT2P ON LT2P.TYPE_ID = P2.TYPE_ID AND LT2P.EDIT_TYPE >= 0 AND LT2P.IS_DEL = 0 AND LT2P.LEVEL_ID = LT2.LEVEL_ID
  JOIN LEVELS L2 ON L2.LEVEL_ID = LT2.LEVEL_ID AND L2.IS_DEL = 0
  JOIN TASKS TS2 ON TS2.TASK_ID = L2.TASK_ID AND TS2.IS_DEL = 0 AND TS2.MODULE_ID = M.MODULE_ID
  WHERE P1.CHILD_ID = :I$TYPE_ID AND P1.TYPE_ID = 20 AND P1.IS_DEL = 0
  INTO :V$IS_PARENT;

  SELECT COUNT(DISTINCT P2.TYPE_ID)
  FROM PARENTS P1
  JOIN PARENTS P2 ON P2.CHILD_ID = P1.CHILD_ID AND P2.TYPE_ID IN (10, 126, 14, 20) AND P2.IS_DEL = 0
  -- есть приложение, где вводится данный тип и хотя бы виден родительский
  JOIN LTYPES LT1 ON LT1.TYPE_ID = P1.CHILD_ID AND LT1.EDIT_TYPE = 1 AND LT1.IS_DEL = 0
  JOIN LTYPES LT1P ON LT1P.TYPE_ID = P1.TYPE_ID AND LT1P.EDIT_TYPE >= 0 AND LT1P.IS_DEL = 0 AND LT1P.LEVEL_ID = LT1.LEVEL_ID
  JOIN LEVELS L1 ON L1.LEVEL_ID = LT1.LEVEL_ID AND L1.IS_DEL = 0
  JOIN TASKS TS1 ON TS1.TASK_ID = L1.TASK_ID AND TS1.IS_DEL = 0
  -- модули: ДОУ, школа, СПО, ОДОД исходя из того, что выбрано
  JOIN MODULES M ON M.MODULE_ID = TS1.MODULE_ID AND M.IS_DEL = 0 AND (
    (:V$STATUS = 'D' AND M.MODULE_ID = 3) OR
    (:V$STATUS = 'O' AND M.MODULE_ID = 4) OR
    (:V$STATUS = 'C' AND M.MODULE_ID = 5) OR
    (:V$STATUS = 'U' AND M.MODULE_ID = 45) OR
    (:V$STATUS = 'P' AND M.MODULE_ID = 76)
  )
  -- и досматриваем, чтобы вторая ветка тоже существовала в этом модуле
  JOIN LTYPES LT2 ON LT2.TYPE_ID = P2.CHILD_ID AND LT2.EDIT_TYPE = 1 AND LT2.IS_DEL = 0
  JOIN LTYPES LT2P ON LT2P.TYPE_ID = P2.TYPE_ID AND LT2P.EDIT_TYPE >= 0 AND LT2P.IS_DEL = 0 AND LT2P.LEVEL_ID = LT2.LEVEL_ID
  JOIN LEVELS L2 ON L2.LEVEL_ID = LT2.LEVEL_ID AND L2.IS_DEL = 0
  JOIN TASKS TS2 ON TS2.TASK_ID = L2.TASK_ID AND TS2.IS_DEL = 0 AND TS2.MODULE_ID = M.MODULE_ID
  WHERE P1.CHILD_ID = :I$TYPE_ID AND P1.TYPE_ID = 14 AND P1.IS_DEL = 0
  INTO :V$IS_STUFF;

  SELECT COUNT(DISTINCT P1.TYPE_ID)
  FROM PARENTS P1
  -- есть приложение, где вводится данный тип и хотя бы виден родительский
  JOIN LTYPES LT1 ON LT1.TYPE_ID = P1.CHILD_ID AND LT1.EDIT_TYPE = 1 AND LT1.IS_DEL = 0
  JOIN LTYPES LT1P ON LT1P.TYPE_ID = P1.TYPE_ID AND LT1P.EDIT_TYPE >= 0 AND LT1P.IS_DEL = 0 AND LT1P.LEVEL_ID = LT1.LEVEL_ID
  JOIN LEVELS L1 ON L1.LEVEL_ID = LT1.LEVEL_ID AND L1.IS_DEL = 0
  JOIN TASKS TS1 ON TS1.TASK_ID = L1.TASK_ID AND TS1.IS_DEL = 0
  -- модули: ДОУ, школа, СПО, ОДОД исходя из того, что выбрано
  JOIN MODULES M ON M.MODULE_ID = TS1.MODULE_ID AND M.IS_DEL = 0 AND (
    (:V$STATUS = 'D' AND M.MODULE_ID = 3) OR
    (:V$STATUS = 'O' AND M.MODULE_ID = 4) OR
    (:V$STATUS = 'C' AND M.MODULE_ID = 5) OR
    (:V$STATUS = 'U' AND M.MODULE_ID = 45) OR
    (:V$STATUS = 'P' AND M.MODULE_ID = 76)
  )
  WHERE P1.CHILD_ID = :I$TYPE_ID AND P1.TYPE_ID IN (10, 126, 14, 20) AND P1.IS_DEL = 0
  INTO :V$IS_ANY;

  -- Конкретную сущность надо выбрать только если подчиненный объект может быть только в ней
  IF((I$TYPE_ID IN (10, 126) OR V$IS_CHILD = 1) AND I$LIVE_ID NOT IN (14550, 14551, 15815)) THEN
    EXCEPTION DATA_ERROR 'Для обучающихся должен быть указан один из режимов актуальности, относящихся именно к обучающимся';
  IF((I$TYPE_ID IN (14) OR V$IS_STUFF = 1) AND I$LIVE_ID NOT IN (15816, 15817, 15818)) THEN
    EXCEPTION DATA_ERROR 'Для сотрудников должен быть указан один из режимов актуальности, относящихся именно к сотрудникам';
  IF((I$TYPE_ID IN (20) OR V$IS_PARENT = 1) AND I$LIVE_ID NOT IN (15824, 15825, 15826)) THEN
    EXCEPTION DATA_ERROR 'Для родителей должен быть указан один из режимов актуальности, относящихся именно к родителям';
  IF(V$IS_ANY > 0 AND I$LIVE_ID IN (14549, 15819, 15820)) THEN
    EXCEPTION DATA_ERROR 'Для данных персон должен быть указан один из режимов актуальности, относящихся к одному из видов персон';
  IF(V$IS_ANY = 0 AND I$TYPE_ID NOT IN (10, 126, 14, 20) AND I$LIVE_ID NOT IN (14549, 15819, 15820)) THEN
    EXCEPTION DATA_ERROR 'Для параметров, не связанных с персонами, не может быть использован режим актуальности, относящийся к персонам';

  IF(OBJ_ID IS NULL) THEN
  BEGIN
    SELECT OBJ_ID
    FROM OBJECT_ADD(:I$OBJ_ID, 498, NULL, NULL, :I$USER_ID)
    INTO :OBJ_ID;
  END
  ELSE
  BEGIN
    UPDATE LINKS
    SET DATE_DEL = NULL
    WHERE PARENT_ID = :I$OBJ_ID AND OBJ_ID = :OBJ_ID AND DATE_DEL IS NOT NULL;
  END

  SELECT 1 FROM VAL_ADD(3449, :OBJ_ID, :I$PARAM_ID) INTO :T;
  SELECT 1 FROM VAL_ADD(3453, :OBJ_ID, :I$TYPE_ID) INTO :T;
  SELECT 1 FROM VAL_ADD(3468, :OBJ_ID, :I$LIVE_ID) INTO :T;
  SELECT 1 FROM VAL_ADD(3454, :OBJ_ID, :I$ACTIVE) INTO :T;
  SELECT 1 FROM VAL_ADD(3455, :OBJ_ID, :I$MATCH_VAL) INTO :T;
  SELECT 1 FROM VAL_ADD(3451, :OBJ_ID, :I$MINVAL) INTO :T;
  SELECT 1 FROM VAL_ADD(3452, :OBJ_ID, :I$MAXVAL) INTO :T;

  -- Пересортировываем чтобы показатели были выставлены по порядку и сгруппированы
  T = 0;
  FOR
    SELECT L498.LINK_ID
    FROM LINKS L498
    JOIN VALI V3449 ON V3449.OBJ_ID = L498.OBJ_ID AND V3449.PARAM_ID = 3449 AND V3449.IS_DEL = 0 AND V3449.VAL = :I$PARAM_ID
    JOIN PARAMS P ON P.PARAM_ID = V3449.VAL
    JOIN TYPES T ON T.TYPE_ID = P.TYPE_ID
    LEFT JOIN VALS V3455 ON V3455.OBJ_ID = L498.OBJ_ID AND V3455.PARAM_ID = 3455 AND V3455.IS_DEL = 0
    WHERE L498.PARENT_ID = :I$OBJ_ID AND L498.OBJ_TYPE_ID = 498 AND L498.DATE_DEL IS NULL
    ORDER BY T.SORT_ORDER, P.GRID_ORDER, V3455.SVAL
    INTO :V$LINK_ID
  DO
  BEGIN
    UPDATE LINKS
    SET COST = :T
    WHERE LINK_ID = :V$LINK_ID AND COST <> :T;
    T = T + 1;
  END

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE VERIFY_PARAM_GET (
    I$OBJ_ID BIGINT)
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
declare variable V$OBJ_ID bigint;
declare variable V$STATUS varchar(10);
declare variable V$TYPE_ID bigint;
declare variable V$PARAM_TYPE integer;
declare variable M integer;
declare variable S varchar(1000);
begin

  V$STATUS = (SELECT STATUS FROM OU_LICENCE_TYPE);

  -- Только типы, которые могут вводиться пользователем
  TAG_NAME = 'obj_type_id:selection::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT DISTINCT T.TYPE_ID, R.VAL
    FROM PARENTS P
    JOIN TYPES T ON T.TYPE_ID = P.CHILD_ID AND T.IS_DEL = 0
    JOIN RES R ON R.RES_ID = T.RES_ID AND R.LANG_CODE = 'RU'
    JOIN LTYPES LT ON LT.TYPE_ID = T.TYPE_ID AND LT.IS_DEL = 0 AND LT.EDIT_TYPE = 1
    JOIN LEVELS L ON L.LEVEL_ID = LT.LEVEL_ID AND L.IS_DEL = 0
    JOIN TASKS TS ON TS.TASK_ID = L.TASK_ID AND TS.IS_DEL = 0
    -- модули: ДОУ, школа, СПО, ОДОД исходя из того, что выбрано
    JOIN MODULES M ON M.MODULE_ID = TS.MODULE_ID AND M.IS_DEL = 0 AND (
      (:V$STATUS = 'D' AND M.MODULE_ID = 3) OR
      (:V$STATUS = 'O' AND M.MODULE_ID = 4) OR
      (:V$STATUS = 'C' AND M.MODULE_ID = 5) OR
      (:V$STATUS = 'U' AND M.MODULE_ID = 45) OR
      (:V$STATUS = 'P' AND M.MODULE_ID = 76)
    )
    WHERE P.IS_DEL = 0 AND (P.IS_ADD = 1 OR P.IS_INTERNAL_ADD = 1) -- те, которые юзер может добавить
    UNION
    SELECT T.TYPE_ID, R.VAL
    FROM TYPES T
    JOIN RES R ON R.RES_ID = T.RES_ID AND R.LANG_CODE = 'RU'
    WHERE T.TYPE_ID = 2
    ORDER BY 2
    INTO :V$OBJ_ID, :S
  DO
  BEGIN
    TAG_NAME = 'obj_type_id:selection:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'obj_type_id:selection:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'obj_type_id:selection:r:value';
    VAL = S;
    SUSPEND;
    -- Какие объекты могут быть родительскими - формируем маску по битам (0=обучающиеся, 1=сотрудники, 2=родители)
    TAG_NAME = 'obj_type_id:selection:r:parents';
    M = 0;
    FOR
      SELECT DISTINCT P.TYPE_ID
      FROM PARENTS P
      JOIN TYPES T ON T.TYPE_ID = P.CHILD_ID AND T.TYPE_ID IN (10, 126, 14, 20)
      JOIN LTYPES LT ON LT.TYPE_ID = T.TYPE_ID AND LT.IS_DEL = 0 AND LT.EDIT_TYPE = 1
      JOIN LEVELS L ON L.LEVEL_ID = LT.LEVEL_ID AND L.IS_DEL = 0
      JOIN TASKS TS ON TS.TASK_ID = L.TASK_ID AND TS.IS_DEL = 0
      -- модули: ДОУ, школа, СПО, ОДОД исходя из того, что выбрано
      JOIN MODULES M ON M.MODULE_ID = TS.MODULE_ID AND M.IS_DEL = 0 AND (
        (:V$STATUS = 'D' AND M.MODULE_ID = 3) OR
        (:V$STATUS = 'O' AND M.MODULE_ID = 4) OR
        (:V$STATUS = 'C' AND M.MODULE_ID = 5) OR
        (:V$STATUS = 'U' AND M.MODULE_ID = 45) OR
        (:V$STATUS = 'P' AND M.MODULE_ID = 76)
      )
      WHERE P.IS_DEL = 0 AND P.CHILD_ID = :V$OBJ_ID
      ORDER BY 1
      INTO :V$TYPE_ID
    DO
    BEGIN
      IF(V$TYPE_ID = 20) THEN M = BIN_OR(M, 4);
      ELSE IF(V$TYPE_ID = 14) THEN M = BIN_OR(M, 2);
      ELSE M = BIN_OR(M, 1);
    END
    VAL = M;
    SUSPEND;
  END
  TAG_NAME = 'obj_type_id:values:value';
  VAL = NULL;
  SUSPEND;

  TAG_NAME = 'param_id:selection::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT DISTINCT TT.TYPE_ID, PP.PARAM_ID, PP.PARAM_TYPE, R.VAL
    FROM (
      SELECT DISTINCT T.TYPE_ID, TS.MODULE_ID
      FROM PARENTS P
      JOIN TYPES T ON T.TYPE_ID = P.CHILD_ID
      JOIN LTYPES LT ON LT.TYPE_ID = T.TYPE_ID AND LT.IS_DEL = 0 AND LT.EDIT_TYPE = 1
      JOIN LEVELS L ON L.LEVEL_ID = LT.LEVEL_ID AND L.IS_DEL = 0
      JOIN TASKS TS ON TS.TASK_ID = L.TASK_ID AND TS.IS_DEL = 0
      -- модули: ДОУ, школа, СПО, ОДОД исходя из того, что выбрано
      JOIN MODULES M ON M.MODULE_ID = TS.MODULE_ID AND M.IS_DEL = 0 AND (
        (:V$STATUS = 'D' AND M.MODULE_ID = 3) OR
        (:V$STATUS = 'O' AND M.MODULE_ID = 4) OR
        (:V$STATUS = 'C' AND M.MODULE_ID = 5) OR
        (:V$STATUS = 'U' AND M.MODULE_ID = 45) OR
        (:V$STATUS = 'P' AND M.MODULE_ID = 76)
      )
      WHERE P.IS_DEL = 0 AND (P.IS_ADD = 1 OR P.IS_INTERNAL_ADD = 1) -- те, которые юзер может добавить
      -- отдельно добавляем параметры для самой ОУ
      UNION
      SELECT 2, M.MODULE_ID
      FROM RDB$DATABASE
      JOIN MODULES M ON M.IS_DEL = 0 AND (
        (:V$STATUS = 'D' AND M.MODULE_ID = 3) OR
        (:V$STATUS = 'O' AND M.MODULE_ID = 4) OR
        (:V$STATUS = 'C' AND M.MODULE_ID = 5) OR
        (:V$STATUS = 'U' AND M.MODULE_ID = 45) OR
        (:V$STATUS = 'P' AND M.MODULE_ID = 76)
      )
    ) TT
    JOIN PARAMS PP ON PP.TYPE_ID = TT.TYPE_ID AND PP.IS_DEL = 0
    JOIN LPARAMS LP ON LP.PARAM_ID = PP.PARAM_ID AND LP.IS_DEL = 0
    JOIN LEVELS L2 ON L2.LEVEL_ID = LP.LEVEL_ID
    JOIN TASKS TS2 ON TS2.TASK_ID = L2.TASK_ID AND TS2.IS_DEL = 0 AND TS2.MODULE_ID = TT.MODULE_ID -- и где-то в том же живом модуле
    JOIN RES R ON R.RES_ID = PP.RES_ID AND R.LANG_CODE = 'RU'
    WHERE (LP.EDIT_TYPE = 1 OR (PP.PARAM_TYPE IN (10, 17, 19) AND (PP.TAG = 'FLOAT' OR PP.TAG = 'INTEGER'))) -- либо можно вводить, либо результат = функция с типом int или float
    ORDER BY 1, PP.GRID_ORDER
    INTO :V$TYPE_ID, :V$OBJ_ID, :V$PARAM_TYPE, :S
  DO
  BEGIN
    TAG_NAME = 'param_id:selection:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'param_id:selection:r:subset_id';
    VAL = V$TYPE_ID;
    SUSPEND;
    TAG_NAME = 'param_id:selection:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'param_id:selection:r:ft_id';
    VAL = V$PARAM_TYPE;
    SUSPEND;
    TAG_NAME = 'param_id:selection:r:value';
    VAL = S;
    SUSPEND;
  END
  TAG_NAME = 'param_id:values:value';
  VAL = NULL;
  SUSPEND;

  TAG_NAME = 'live_id:selection::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L.LISTVAL_ID, L.VAL
    FROM LISTVALS_LIST(365) L
    WHERE L.IS_DEL = 0
    INTO :V$OBJ_ID, :S
  DO
  BEGIN
    TAG_NAME = 'live_id:selection:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'live_id:selection:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'live_id:selection:r:value';
    VAL = S;
    SUSPEND;
  END
  TAG_NAME = 'live_id:values:value';
  VAL = NULL;
  SUSPEND;

  TAG_NAME = 'active:selection::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L.LISTVAL_ID, L.VAL
    FROM LISTVALS_LIST(367) L
    WHERE L.IS_DEL = 0
    INTO :V$OBJ_ID, :S
  DO
  BEGIN
    TAG_NAME = 'active:selection:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'active:selection:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'active:selection:r:value';
    VAL = S;
    SUSPEND;
  END
  TAG_NAME = 'active:values:value';
  VAL = NULL;
  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE VERIFY_POST (
    I$OBJ_ID BIGINT)
RETURNS (
    LINK_ID BIGINT,
    OBJECT_ID BIGINT,
    PARENT_ID BIGINT,
    NAME_TASK VARCHAR(1000),
    ERROR_NAME VARCHAR(1000),
    PARAMS_NAME VARCHAR(1000),
    ERROR_TEXT VARCHAR(1000),
    ERROR_TYPE SMALLINT)
AS
declare variable V$TYPE_ID bigint;
declare variable V$VALS varchar(1000);
declare variable V varchar(1000);
declare variable V$OBJ_ID bigint;
declare variable V$LINK_ID bigint;
declare variable V$PARENT_ID bigint;
declare variable V$POST_ID bigint;
declare variable V$ROOT_POST_ID bigint;
declare variable I bigint;
BEGIN
    NAME_TASK = 'Должности';
    ERROR_TYPE = 0;

    FOR
      SELECT L13.LINK_ID, L13.OBJ_ID, L13.PARENT_ID, L13.OBJ_ID
      FROM LINKS L13
      WHERE L13.PARENT_ID = :I$OBJ_ID AND L13.OBJ_TYPE_ID = 13 AND L13.DATE_DEL IS NULL
      INTO :LINK_ID, :OBJECT_ID, :PARENT_ID, :V$TYPE_ID
    DO
    BEGIN
      SELECT CAPTION FROM OBJECT_CAPTION_GET(:OBJECT_ID) INTO :V$VALS;

      FOR
        SELECT ERROR_TYPE, ERROR_TEXT, ERROR_NAME, PARAMS_NAME
        FROM VERIFY_OBJECT_FIELDS(:OBJECT_ID, :V$TYPE_ID, 'должности', :V$VALS)
        INTO :ERROR_TYPE, :ERROR_TEXT, :ERROR_NAME, :PARAMS_NAME
      DO
      BEGIN
        SUSPEND;
      END
    END

    FOR
      SELECT UPPER(TRIM(V.VAL)), VL.LISTVAL_ID
      FROM LINKS L13
      JOIN VALS V ON V.OBJ_ID = L13.OBJ_ID AND V.PARAM_ID = 66 AND V.IS_DEL = 0
      JOIN VALL VL ON VL.OBJ_ID = L13.OBJ_ID AND VL.PARAM_ID = 58 AND VL.IS_DEL = 0
      WHERE L13.PARENT_ID = :I$OBJ_ID AND L13.DATE_DEL IS NULL AND L13.OBJ_TYPE_ID = 13
      GROUP BY 1, 2
      HAVING COUNT(UPPER(TRIM(V.VAL))) > 1
      INTO :V$VALS, :I
    DO
    BEGIN
      V$ROOT_POST_ID = NULL;
      SELECT FIRST 1 L13.OBJ_ID
      FROM LINKS L13
      JOIN VALL VL ON VL.OBJ_ID = L13.OBJ_ID AND VL.PARAM_ID = 58 AND VL.LISTVAL_ID = :I AND VL.IS_DEL = 0
      JOIN VALS V ON V.OBJ_ID = L13.OBJ_ID AND V.PARAM_ID = 66 AND V.IS_DEL = 0 AND UPPER(TRIM(V.VAL)) = :V$VALS
      WHERE L13.PARENT_ID = :I$OBJ_ID AND L13.DATE_DEL IS NULL AND L13.OBJ_TYPE_ID = 13
      INTO :V$ROOT_POST_ID;

      IF (V$ROOT_POST_ID IS NOT NULL) THEN
      BEGIN
        -- Изменить ссылки на дубликаты должности, теперь они ссылаются на первый дубликат
        DELETE FROM FILTER_SESSION_VALS WHERE 1 = 1;

        INSERT INTO FILTER_SESSION_VALS(OBJ_ID, TYPE_ID)
        SELECT DISTINCT L13.OBJ_ID, L13.OBJ_TYPE_ID
        FROM LINKS L13
        JOIN VALL VL ON VL.OBJ_ID = L13.OBJ_ID AND VL.PARAM_ID = 58 AND VL.LISTVAL_ID = :I AND VL.IS_DEL = 0
        JOIN VALS V ON V.OBJ_ID = L13.OBJ_ID AND V.PARAM_ID = 66 AND V.IS_DEL = 0 AND UPPER(TRIM(V.VAL)) = :V
        WHERE L13.PARENT_ID = :I$OBJ_ID AND L13.DATE_DEL IS NULL AND L13.OBJ_TYPE_ID = 13 AND L13.OBJ_ID <> :V$ROOT_POST_ID;

        FOR
          SELECT OBJ_ID, TYPE_ID
          FROM FILTER_SESSION_VALS
          INTO :V$POST_ID, :V$LINK_ID
        DO
        BEGIN
          UPDATE VALR VR SET VR.VAL = :V$ROOT_POST_ID WHERE VR.VAL = :V$POST_ID;
        END

        -- Перенаправляем все ссыки с дубликатов на ссылку с первого первый дубликата
        DELETE FROM FILTER_SESSION_VALS WHERE 1 = 1;
        INSERT INTO FILTER_SESSION_VALS(OBJ_ID, TYPE_ID)
        SELECT DISTINCT L.LINK_ID, L.OBJ_ID
        FROM LINKS L13
        JOIN VALL VL ON VL.OBJ_ID = L13.OBJ_ID AND VL.PARAM_ID = 58 AND VL.LISTVAL_ID = :I AND VL.IS_DEL = 0
        JOIN VALS V ON V.OBJ_ID = L13.OBJ_ID AND V.PARAM_ID = 66 AND V.IS_DEL = 0 AND UPPER(TRIM(V.VAL)) = :V
        JOIN LINKS L ON L.PARENT_ID = L13.OBJ_ID
        WHERE L13.PARENT_ID = :I$OBJ_ID AND L13.DATE_DEL IS NULL AND L13.OBJ_TYPE_ID = 13 AND L13.OBJ_ID <> :V$ROOT_POST_ID;

        FOR
          SELECT OBJ_ID, TYPE_ID
          FROM FILTER_SESSION_VALS
          INTO :V$LINK_ID, :V$OBJ_ID
        DO
        BEGIN
          IF (NOT EXISTS(SELECT 1 FROM LINKS WHERE OBJ_ID = :V$OBJ_ID AND PARENT_ID = :V$ROOT_POST_ID)) THEN
          BEGIN
            UPDATE LINKS
            SET PARENT_ID = :V$ROOT_POST_ID
            WHERE LINK_ID = :V$LINK_ID;
          END
          ELSE
          BEGIN
            UPDATE LINKS
            SET DATE_DEL = CURRENT_TIMESTAMP
            WHERE LINK_ID = :V$LINK_ID;
          END
        END

        -- Перенаправляем все ссылки на дубликаты на ссылку на первый дубликат
        DELETE FROM FILTER_SESSION_VALS WHERE 1 = 1;
        INSERT INTO FILTER_SESSION_VALS(OBJ_ID,TYPE_ID)
        SELECT DISTINCT L.LINK_ID, L.PARENT_ID
        FROM LINKS L13
        JOIN VALL VL ON VL.OBJ_ID = L13.OBJ_ID AND VL.PARAM_ID = 58 AND VL.LISTVAL_ID = :I AND VL.IS_DEL = 0
        JOIN VALS V ON V.OBJ_ID = L13.OBJ_ID AND V.PARAM_ID = 66 AND V.IS_DEL = 0 AND UPPER(TRIM(V.VAL)) = :V
        JOIN LINKS L ON L.OBJ_ID = L13.OBJ_ID
        WHERE L13.PARENT_ID = :I$OBJ_ID AND L13.DATE_DEL IS NULL AND L13.OBJ_TYPE_ID = 13 AND L13.OBJ_ID <> :V$ROOT_POST_ID;

        FOR
          SELECT OBJ_ID, TYPE_ID
          FROM FILTER_SESSION_VALS
          INTO :V$LINK_ID, :V$PARENT_ID
        DO
        BEGIN
          IF (NOT EXISTS(SELECT 1 FROM LINKS WHERE OBJ_ID = :V$ROOT_POST_ID AND PARENT_ID = :V$PARENT_ID)) THEN
          BEGIN
            UPDATE LINKS
            SET OBJ_ID = :V$ROOT_POST_ID
            WHERE LINK_ID = :V$LINK_ID;
          END
          ELSE
          BEGIN
            UPDATE LINKS
            SET DATE_DEL = CURRENT_TIMESTAMP
            WHERE LINK_ID = :V$LINK_ID;
          END
        END

        /*
        LINK_ID = NULL;
        OBJECT_ID = I$OBJ_ID;
        ERROR_TEXT = 'В список должностей содержал несколько должностей с одинаковым названием "' || V || '". Все ссылки были перенаправлены на первую в списке должность. Остальные были удалены.';
        ERROR_NAME = 'В список должностей содержал несколько должностей с одинаковым названием. Все ссылки были перенаправлены на первую в списке должность. Остальные были удалены.';
        PARAMS_NAME = 'Должности';
        ERROR_TYPE = 1;
        SUSPEND;
        */
      END
    END

    -- Служебное сообщение об успешности проверок
    IF(ERROR_TYPE = 0) THEN
    BEGIN
      ERROR_TEXT = 'Данные успешно верифицированы, замечаний и ошибок нет';
      ERROR_NAME = 'Без замечаний';
      PARAMS_NAME = NAME_TASK;
      PARENT_ID = I$OBJ_ID;
      OBJECT_ID = NULL;
      LINK_ID = NULL;
      SUSPEND;
    END

END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE VERIFY_POST_DICT (
    I$LEVEL_ID BIGINT)
RETURNS (
    TYPE_ID BIGINT,
    TYPE_NAME VARCHAR(400),
    PARAM_ID BIGINT,
    PARAM_NAME VARCHAR(400),
    PARAM_TYPE_ID BIGINT,
    PARAM_TYPE_NAME VARCHAR(100),
    VAL_REQUIRED SMALLINT,
    VAL_CHECK SMALLINT,
    VAL_MASK VARCHAR(400),
    VAL_EXTRA VARCHAR(400))
AS
begin

  -- Проверяем что LEVEL_ID допустимый
  IF(NOT EXISTS(
    SELECT FIRST 1 1
    FROM LEVELS L
    JOIN TASKS T ON T.TASK_ID = L.TASK_ID AND T.IS_DEL = 0
    JOIN MODULES M ON M.MODULE_ID = T.MODULE_ID AND M.IS_DEL = 0 AND M.IS_ACTIVE = 1
    WHERE L.LEVEL_ID = :I$LEVEL_ID AND L.IS_DEL = 0
  ))
  THEN
    EXCEPTION DATA_ERROR 'Недопустимое приложение для контроля';

  -- Поля для объектов: должность #13
  -- заполняемые в данном приложении (RW)
  FOR
    SELECT P.TYPE_ID, P.PARAM_ID, P.PARAM_TYPE, RT.VAL, RP.VAL, P.IS_REQUIRED, IIF(P.DO_CHECK = 0, 0, 1), P.EDIT_MASK
    FROM PARAMS P
    JOIN LPARAMS LP ON LP.PARAM_ID = P.PARAM_ID AND LP.LEVEL_ID = :I$LEVEL_ID AND LP.IS_DEL = 0 AND LP.EDIT_TYPE = 1
    JOIN TYPES T ON T.TYPE_ID = P.TYPE_ID AND T.IS_DEL = 0
    JOIN RES RT ON RT.RES_ID = T.RES_ID AND RT.LANG_CODE = 'RU'
    JOIN RES RP ON RP.RES_ID = P.RES_ID AND RP.LANG_CODE = 'RU'
    WHERE P.TYPE_ID IN (13) AND P.IS_DEL = 0
      AND (P.IS_REQUIRED = 1 OR (P.EDIT_MASK IS NOT NULL AND P.EDIT_MASK <> ''))
    ORDER BY T.SORT_ORDER, P.GRID_ORDER
    INTO :TYPE_ID, :PARAM_ID, :PARAM_TYPE_ID, :TYPE_NAME, :PARAM_NAME, :VAL_REQUIRED, :VAL_CHECK, :VAL_MASK
  DO
  BEGIN
    IF(VAL_MASK = '') THEN VAL_MASK = NULL;

    IF(PARAM_TYPE_ID = 1) THEN PARAM_TYPE_NAME = 'Целое число';
    ELSE IF(PARAM_TYPE_ID = 2) THEN PARAM_TYPE_NAME = 'Вещественное число';
    ELSE IF(PARAM_TYPE_ID = 3) THEN PARAM_TYPE_NAME = 'Дата и время';
    ELSE IF(PARAM_TYPE_ID = 4) THEN PARAM_TYPE_NAME = 'Дата';
    ELSE IF(PARAM_TYPE_ID = 5) THEN PARAM_TYPE_NAME = 'Время';
    ELSE IF(PARAM_TYPE_ID = 6) THEN PARAM_TYPE_NAME = 'Значение из справочника';
    ELSE IF(PARAM_TYPE_ID = 7) THEN PARAM_TYPE_NAME = 'Строка или значение из справочника';
    ELSE IF(PARAM_TYPE_ID = 8) THEN PARAM_TYPE_NAME = 'Строка';
    ELSE IF(PARAM_TYPE_ID = 11) THEN PARAM_TYPE_NAME = 'Файл';
    ELSE IF(PARAM_TYPE_ID = 12) THEN PARAM_TYPE_NAME = 'Изображение';
    ELSE IF(PARAM_TYPE_ID = 13) THEN PARAM_TYPE_NAME = 'Ссылка на объект';
    ELSE IF(PARAM_TYPE_ID = 18) THEN PARAM_TYPE_NAME = 'Адрес';
    ELSE PARAM_TYPE_NAME = 'Недопустимый тип';

    VAL_EXTRA = NULL;
    IF(PARAM_ID IN (589)) THEN VAL_EXTRA = 'Уникальность';

    SUSPEND;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE VERIFY_PUPIL (
    I$OBJ_ID BIGINT)
RETURNS (
    LINK_ID BIGINT,
    OBJECT_ID BIGINT,
    PARENT_ID BIGINT,
    NAME_TASK VARCHAR(1000),
    ERROR_NAME VARCHAR(1000),
    PARAMS_NAME VARCHAR(1000),
    ERROR_TEXT VARCHAR(1000),
    ERROR_TYPE SMALLINT)
AS
DECLARE VARIABLE OBJ_ID BIGINT;
DECLARE VARIABLE PARAM_ID BIGINT;
DECLARE VARIABLE I INTEGER;
DECLARE VARIABLE CLASS VARCHAR(1000);
DECLARE VARIABLE V VARCHAR(4000);
DECLARE VARIABLE V$TYPE CHAR(1);
DECLARE VARIABLE V$GY INTEGER;
DECLARE VARIABLE V$Y4 DATE;
DECLARE VARIABLE V$LAST_DATE DATE;
DECLARE VARIABLE V$BIRTH_DATE DATE;
DECLARE VARIABLE V$PARENT_TYPE_ID BIGINT;
DECLARE VARIABLE V$TYPE_ID BIGINT;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$DT BIGINT;
DECLARE VARIABLE V$AGE14 DATE;
DECLARE VARIABLE S VARCHAR(1000);
BEGIN
    NAME_TASK = 'Личные дела обучающихся, воспитанников ';
    ERROR_TYPE = 0;

    SELECT STATUS FROM OU_LICENCE_TYPE INTO :V$TYPE;

    SELECT FIRST 1 LV.COST
    FROM VALL V1236
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
    WHERE V1236.OBJ_ID = :I$OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
    INTO :V$GY;

    V$Y4 = '25.08.' || (V$GY - 4);

    -- Контрольная дата для получения паспорта - даем 2 месяца форы
    V$AGE14 = DATEADD(-14 YEAR TO CURRENT_DATE);
    V$AGE14 = DATEADD(-2 MONTH TO V$AGE14);

    -- Должны быть актуальные данные для действующих учеников и выбывших в последние 4 учебных года
    FOR
      SELECT V.PERSON_ID, V.BIRTH_DATE, MAX(V.DATE_IN)
      FROM (
        SELECT M.PERSON_ID, V89.VAL BIRTH_DATE, M.DATE_IN
        FROM PERSON_MOVEMENTS M
        JOIN LINKS LPG ON LPG.OBJ_ID = M.PERSON_ID AND LPG.PARENT_TYPE_ID IN (9, 125, 187, 81, 82, 83) AND LPG.DATE_DEL IS NULL
        LEFT JOIN VALD V89 ON V89.OBJ_ID = M.PERSON_ID AND V89.PARAM_ID = 89 AND V89.IS_DEL = 0
        WHERE M.DATE_DEL IS NULL AND M.GROUP_TYPE_ID IN (9, 125, 187) AND M.DATE_IN >= :V$Y4 AND M.OU_ID = :I$OBJ_ID
        UNION
        -- Добавляем предварительный прием
        SELECT L10.OBJ_ID, V89.VAL, CURRENT_DATE
        FROM LINKS L77
        JOIN LINKS L290 ON L290.PARENT_ID = L77.OBJ_ID AND L290.OBJ_TYPE_ID = 290 AND L290.DATE_DEL IS NULL
        JOIN LINKS L10 ON L10.PARENT_ID = L290.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        LEFT JOIN VALD V89 ON V89.OBJ_ID = L10.OBJ_ID AND V89.PARAM_ID = 89 AND V89.IS_DEL = 0
        WHERE L77.PARENT_ID = :I$OBJ_ID AND L77.OBJ_TYPE_ID = 77 AND L77.DATE_DEL IS NULL
      ) V
      GROUP BY 1, 2
      ORDER BY 1
      INTO :OBJECT_ID, :V$BIRTH_DATE, :V$LAST_DATE
    DO
    BEGIN

      SELECT FIRST 1 LPG.PARENT_ID, LPG.LINK_ID, LPG.PARENT_TYPE_ID, C.CAPTION
      FROM LINKS LPG
      LEFT JOIN OBJECT_CAPTION_GET(LPG.PARENT_ID) C ON 1 = 1
      WHERE LPG.OBJ_ID = :OBJECT_ID AND LPG.PARENT_TYPE_ID IN (9, 125, 187, 81, 82, 83, 290) AND LPG.DATE_DEL IS NULL
      ORDER BY LPG.DATE_INS DESC
      INTO :PARENT_ID, :LINK_ID, :V$PARENT_TYPE_ID, :CLASS;

      SELECT C1 FROM BUILD_REP_FIO(:OBJECT_ID, 55, 56, 57, 0) INTO :S;

      S = S || ' (' || CLASS || ')';

      -- Не указан пол
      IF(NOT EXISTS(
        SELECT FIRST 1 1
        FROM VALL V88
        WHERE V88.OBJ_ID = :OBJECT_ID AND V88.PARAM_ID IN (88, 1022) AND V88.IS_DEL = 0
      )) THEN
      BEGIN
        ERROR_TEXT = 'Для обучающегося «' || S || '» не указан пол';
        ERROR_NAME = 'Для обучающегося не указан пол';
        PARAMS_NAME = 'Контролируемые поля';
        IF(V$PARENT_TYPE_ID IN (9, 125, 187, 290)) THEN ERROR_TYPE = 3; ELSE ERROR_TYPE = 2;
        SUSPEND;
      END

      -- Поля самого обучающегося
      FOR
        SELECT ERROR_TYPE, ERROR_TEXT, ERROR_NAME, PARAMS_NAME
        FROM VERIFY_OBJECT_FIELDS(:OBJECT_ID, 10, 'обучающегося', :S)
        INTO :ERROR_TYPE, :ERROR_TEXT, :ERROR_NAME, :PARAMS_NAME
      DO
      BEGIN
        SUSPEND;
      END

      -- Поля вложенных объектов
      FOR
        SELECT L.OBJ_ID, L.OBJ_TYPE_ID, R.VAL
        FROM LINKS L
        JOIN TYPES T ON T.TYPE_ID = L.OBJ_ID
        JOIN RES R ON R.RES_ID = T.RES_ID AND R.LANG_CODE = 'RU'
        WHERE L.PARENT_ID = :OBJECT_ID AND L.DATE_DEL IS NULL
          AND L.OBJ_TYPE_ID IN (11, 12, 79, 293) -- 162 тип идет по другой связи
        ORDER BY T.SORT_ORDER
        INTO :V$OBJ_ID, :V$TYPE_ID, :S
      DO
      BEGIN
        FOR
          SELECT ERROR_TYPE, ERROR_TEXT, ERROR_NAME, PARAMS_NAME
          FROM VERIFY_OBJECT_FIELDS(:V$OBJ_ID, :V$TYPE_ID, 'обучающегося', :S)
          INTO :ERROR_TYPE, :ERROR_TEXT, :ERROR_NAME, :PARAMS_NAME
        DO
        BEGIN
          -- Название параметра заменяем на тип объекта
          PARAMS_NAME = S;
          SUSPEND;
        END

        -- Отдельно надо проверить серию документа для случая, когда она обязательна
        -- !!! дописать валидатор для номера документа

        -- Пустые объекты больше не удаляем - если их нет, это будет ошибка. Иначе будет дурить инкрементальная выгрузка
        -- Обязательно наличие действующего документа
        -- Ищем идентифицирующимй документ паспорт, потом все остальные варианты
        V$DT = NULL;
        SELECT FIRST 1 V441.LISTVAL_ID
        FROM LINKS L79
        JOIN VALL V441 ON V441.OBJ_ID = L79.OBJ_ID AND V441.PARAM_ID = 441 AND V441.IS_DEL = 0 -- тип
        JOIN VALS V559 ON V559.OBJ_ID = L79.OBJ_ID AND V559.PARAM_ID = 559 AND V559.IS_DEL = 0 -- номер
        JOIN VALD V560 ON V560.OBJ_ID = L79.OBJ_ID AND V560.PARAM_ID = 560 AND V560.IS_DEL = 0 -- дата
        JOIN VALL V614 ON V614.OBJ_ID = L79.OBJ_ID AND V614.PARAM_ID = 614 AND V614.IS_DEL = 0 AND V614.LISTVAL_ID IN (1982, 1984)
        WHERE L79.PARENT_ID = :OBJECT_ID AND L79.OBJ_TYPE_ID = 79 AND L79.DATE_DEL IS NULL
        ORDER BY IIF(V441.LISTVAL_ID = 1368, 0, V441.LISTVAL_ID)
        INTO :V$DT;

        IF(V$DT IS NULL) THEN
        BEGIN
          ERROR_TEXT = 'Для обучающегося «' || S || '» не введены данные документа, удостоверяющего личность';
          ERROR_NAME = 'Для обучающегося не введены данные документа, удостоверяющего личность';
          PARAMS_NAME = 'Документ удостоверяющий личность';
          ERROR_TYPE = 2;
          SUSPEND;
        END
        ELSE IF(V$DT <> 1368 AND V$BIRTH_DATE < V$AGE14) THEN BEGIN
          -- Надо проверить гражданство РФ
          IF(EXISTS(
            SELECT 1 FROM VALL V91 WHERE V91.OBJ_ID = :OBJECT_ID AND V91.PARAM_ID = 91 AND V91.IS_DEL = 0 AND V91.LISTVAL_ID = 1515
          )) THEN
          BEGIN
            ERROR_TEXT = 'Для обучающегося «' || S || '» старше 14 лет не введены данные паспорта';
            ERROR_NAME = 'Для обучающегося старше 14 лет не введены данные паспорта';
            PARAMS_NAME = 'Документ удостоверяющий личность';
            ERROR_TYPE = 2;
            SUSPEND;
          END
        END

        -- Идентифицирующие документы с датой выдачи ранее даты рождения или в будущем
        IF(EXISTS(
          SELECT FIRST 1 1
          FROM LINKS L79
          JOIN VALD V560 ON V560.OBJ_ID = L79.OBJ_ID AND V560.PARAM_ID = 560 AND V560.IS_DEL = 0 -- дата
            AND (V560.VAL < :V$BIRTH_DATE OR V560.VAL > CURRENT_DATE)
          WHERE L79.PARENT_ID = :OBJECT_ID AND L79.OBJ_TYPE_ID = 79 AND L79.DATE_DEL IS NULL
        )) THEN
        BEGIN
          ERROR_TEXT = 'Для обучающегося «' || S || '» дата выдачи документа, удостоверяющего личность, за пределами допустимого диапазона';
          ERROR_NAME = 'Для обучающегося дата выдачи документа, удостоверяющего личность, за пределами допустимого диапазона';
          PARAMS_NAME = 'Документ удостоверяющий личность';
          ERROR_TYPE = 3;
          SUSPEND;
        END

        -- Прочие документы с датой выдачи ранее даты рождения или в будущем
        IF(EXISTS(
          SELECT FIRST 1 1
          FROM LINKS L12
          JOIN VALD V572 ON V572.OBJ_ID = L12.OBJ_ID AND V572.PARAM_ID = 572 AND V572.IS_DEL = 0 -- дата
            AND (V572.VAL < :V$BIRTH_DATE OR V572.VAL > CURRENT_DATE)
          WHERE L12.PARENT_ID = :OBJECT_ID AND L12.OBJ_TYPE_ID = 12 AND L12.DATE_DEL IS NULL
        )) THEN
        BEGIN
          ERROR_TEXT = 'Для обучающегося «' || S || '» дата выдачи документа (свидетельства, удостоверения), за пределами допустимого диапазона';
          ERROR_NAME = 'Для обучающегося дата выдачи документа (свидетельства, удостоверения), за пределами допустимого диапазона';
          PARAMS_NAME = 'Документ (свидетельство, удостоверение)';
          ERROR_TYPE = 3;
          SUSPEND;
        END

        -- Документы об образовании с датой выдачи ранее даты рождения или в будущем
        IF(EXISTS(
          SELECT FIRST 1 1
          FROM LINKS L11
          JOIN VALD V566 ON V566.OBJ_ID = L11.OBJ_ID AND V566.PARAM_ID = 566 AND V566.IS_DEL = 0 -- дата
            AND (V566.VAL < :V$BIRTH_DATE OR V566.VAL > CURRENT_DATE)
          WHERE L11.PARENT_ID = :OBJECT_ID AND L11.OBJ_TYPE_ID = 11 AND L11.DATE_DEL IS NULL
        )) THEN
        BEGIN
          ERROR_TEXT = 'Для обучающегося «' || S || '» дата выдачи документа об образовании, за пределами допустимого диапазона';
          ERROR_NAME = 'Для обучающегося дата выдачи документа об образовании, за пределами допустимого диапазона';
          PARAMS_NAME = 'Документ об образовании';
          ERROR_TYPE = 3;
          SUSPEND;
        END

        -- Дополнительные сведения для выбывших
        IF(V$TYPE_ID = 82 AND V$TYPE <> 'U') THEN
        BEGIN
          IF (EXISTS(
            SELECT FIRST 1 1
            FROM VAL_GET(:OBJECT_ID, 105)
            WHERE V = ''
          )) THEN
          BEGIN
            ERROR_NAME = 'Не заполнено поле «Выбыл(а) в»';
            ERROR_TEXT = 'Не заполнено поле «Выбыл(а) в» для обучающегося «' || :S || '»';
            PARAMS_NAME = 'Выбыл(а) в';
            ERROR_TYPE = 5;
            SUSPEND;
          END
        END

        -- Дополнительные сведения для окончивших
        IF(V$TYPE_ID = 83) THEN
        BEGIN
          IF (NOT EXISTS(
            SELECT FIRST 1 1
            FROM LINKS L11
            WHERE L11.PARENT_ID = :OBJECT_ID AND L11.OBJ_TYPE_ID = 11 AND L11.DATE_DEL IS NULL
          )) THEN
          BEGIN
            ERROR_NAME = 'Не введены данные документа об образовании';
            ERROR_TEXT = 'Не введены данные документа об образовании для обучающегося «' || S || '»';
            PARAMS_NAME = 'Документ об образовании';
            ERROR_TYPE = 5;
            SUSPEND;
          END
        END

        -- Действующие обучающиеся
        IF(V$TYPE_ID IN (9, 187)) THEN
        BEGIN
          FOR
            SELECT R.VAL, P.PARAM_ID
            FROM PARAMS P
            JOIN LPARAMS LP ON LP.PARAM_ID = P.PARAM_ID AND LP.IS_DEL = 0 AND LP.LEVEL_ID = 50
            JOIN RES R ON R.RES_ID = P.RES_ID AND R.LANG_CODE = 'RU'
            LEFT JOIN VAL_GET(:OBJECT_ID, P.PARAM_ID) VL ON 1=1
            WHERE P.TYPE_ID = 10 AND P.IS_DEL = 0 AND P.PARAM_ID IN (108, 1343, 1409, 80, 176, 208, 78, 101, 103, 111) AND VL.V = ''
            INTO :V, :PARAM_ID
          DO
          BEGIN
            IF ((PARAM_ID <> 101) OR EXISTS(
              SELECT FIRST 1 1
              FROM ADR_GET(103, :OBJECT_ID)
              WHERE REGION LIKE 'Санкт-Петербург%'
            )) THEN
            BEGIN
              ERROR_NAME = 'Не заполнено поле «' || V || '»';
              ERROR_TEXT = 'Не заполнено поле «' || V || '» для обучающегося «' || :S || '»';
              PARAMS_NAME = V;
              ERROR_TYPE = 5;
              SUSPEND;
            END
          END

          -- Поля для ГИА
          IF(EXISTS(
            SELECT FIRST 1 1
            FROM LINKS L120
            JOIN VALL V803 ON V803.OBJ_ID = L120.OBJ_ID AND V803.PARAM_ID = 803 AND V803.IS_DEL = 0 AND V803.LISTVAL_ID = 2926
            JOIN LINKS LP119 ON LP119.OBJ_ID = L120.OBJ_ID AND LP119.PARENT_TYPE_ID = 119 AND LP119.DATE_DEL IS NULL
            JOIN VALL V742 ON V742.OBJ_ID = LP119.PARENT_ID AND V742.PARAM_ID = 742 AND V742.IS_DEL = 0
            JOIN LISTVALS LV ON LV.LISTVAL_ID = V742.LISTVAL_ID AND LV.COST = :V$GY
            WHERE L120.PARENT_ID = :OBJECT_ID AND L120.OBJ_TYPE_ID = 120 AND L120.DATE_DEL IS NULL
          )) THEN
          BEGIN
            IF (NOT EXISTS(
              SELECT FIRST 1 1
              FROM VALL
              WHERE OBJ_ID = :OBJECT_ID AND PARAM_ID = 1620 AND IS_DEL = 0
            )) THEN
            BEGIN
              ERROR_TEXT = 'Для обучающегося «' || S || '», сдающего ГИА/ЕГЭ по информатике, не указано значение в поле «Язык программирования»';
              ERROR_NAME = 'Для обучающегося, сдающего ГИА/ЕГЭ по информатике, не указано значение в поле «Язык программирования»';
              PARAMS_NAME = 'Язык программирования';
              ERROR_TYPE = 3;
              SUSPEND;
            END
            IF (NOT EXISTS(
              SELECT FIRST 1 1
              FROM VALL
              WHERE OBJ_ID = :OBJECT_ID AND PARAM_ID = 1622 AND IS_DEL = 0
            )) THEN
            BEGIN
              ERROR_TEXT = 'Для обучающегося «' || S || '», сдающего ГИА/ЕГЭ по информатике, не указано значение в поле «Среда программирования»';
              ERROR_NAME = 'Для обучающегося, сдающего ГИА/ЕГЭ по информатике, не указано значение в поле «Среда программирования»';
              PARAMS_NAME = 'Среда программирования';
              ERROR_TYPE = 3;
              SUSPEND;
            END
            IF (NOT EXISTS(
              SELECT FIRST 1 1
              FROM VALL
              WHERE OBJ_ID = :OBJECT_ID AND PARAM_ID = 1624 AND IS_DEL = 0
            )) THEN
            BEGIN
              ERROR_TEXT = 'Для обучающегося «' || S || '», сдающего ГИА/ЕГЭ по информатике, не указано значение в поле «Текстовый редактор»';
              ERROR_NAME = 'Для обучающегося, сдающего ГИА/ЕГЭ по информатике, не указано значение в поле «Текстовый редактор»';
              PARAMS_NAME = 'Текстовый редактор';
              ERROR_TYPE = 3;
              SUSPEND;
            END
            IF (NOT EXISTS(
              SELECT FIRST 1 1
              FROM VALL
              WHERE OBJ_ID = :OBJECT_ID AND PARAM_ID = 1625 AND IS_DEL = 0
            )) THEN
            BEGIN
              ERROR_TEXT = 'Для обучающегося «' || S || '», сдающего ГИА/ЕГЭ по информатике, не указано значение в поле «Редактор электронных таблиц»';
              ERROR_NAME = 'Для обучающегося, сдающего ГИА/ЕГЭ по информатике, не указано значение в поле «Редактор электронных таблиц»';
              PARAMS_NAME = 'Редактор электронных таблиц';
              ERROR_TYPE = 3;
              SUSPEND;
            END
          END
        END
      END
    END

    PARENT_ID = NULL;
    FOR
      SELECT V1570.VAL
      FROM LINKS L20
      JOIN LINKS L10 ON L10.OBJ_ID = L20.PARENT_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL AND L10.PARENT_TYPE_ID = 9
      JOIN LINKS L9 ON L9.OBJ_ID = L10.PARENT_ID AND L9.OBJ_TYPE_ID IN (9, 187) AND L9.DATE_DEL IS NULL AND L9.PARENT_TYPE_ID = 8
      JOIN VALS V1570 ON V1570.OBJ_ID = L20.EXT_OBJ_ID AND V1570.PARAM_ID = 1570 AND V1570.IS_DEL = 0
      WHERE L20.PARENT_TYPE_ID = 10 AND L20.DATE_DEL IS NULL AND L20.OBJ_TYPE_ID = 20
      GROUP BY 1
      HAVING COUNT(*) > 1
      INTO :V
    DO
    BEGIN
      ERROR_TYPE = 3;
      PARAMS_NAME = 'Идентификатор для экспорта на портал «Петербургское образование» (ученика)';
      ERROR_TEXT = 'Идентификатор ' || V || ' введен для нескольких учеников: ';
      ERROR_NAME = 'Идентификатор введен для нескольких учеников';
      I = 0;
      FOR
        SELECT L20.PARENT_ID, L20.OBJ_ID, L20.LINK_ID
        FROM LINKS L20
        JOIN VALS V1570 ON V1570.OBJ_ID = L20.EXT_OBJ_ID AND V1570.PARAM_ID = 1570 AND V1570.IS_DEL = 0
        WHERE L20.DATE_DEL IS NULL AND L20.PARENT_TYPE_ID = 10 AND L20.OBJ_TYPE_ID = 20 AND V1570.SVAL = :V
        INTO :OBJ_ID, :OBJECT_ID, :LINK_ID
      DO
      BEGIN
        IF (I = 1) THEN ERROR_TEXT = ERROR_TEXT || ', ';
        SELECT V FROM VAL_GET(:OBJ_ID, 55) INTO :S;
        ERROR_TEXT = ERROR_TEXT || S || ' ';
        SELECT VAL FROM DO_FUNC(:OBJ_ID, 1348, 21) INTO :S;
        IF (S IS NULL) THEN S = '';
        ERROR_TEXT = ERROR_TEXT || S || ' (родитель: ';
        SELECT V FROM VAL_GET(:OBJECT_ID, 128) INTO :S;
        ERROR_TEXT = ERROR_TEXT || S || ' ';
        SELECT VAL FROM DO_FUNC(:OBJECT_ID, 136, 21) INTO :S;
        IF (S IS NULL) THEN S = '';
        ERROR_TEXT = ERROR_TEXT || S || ')';
        I = 1;
      END
      SUSPEND;
    END

    -- Служебное сообщение об успешности проверок
    IF(ERROR_TYPE = 0) THEN
    BEGIN
      ERROR_TEXT = 'Данные успешно верифицированы, замечаний и ошибок нет';
      ERROR_NAME = 'Без замечаний';
      PARAMS_NAME = NAME_TASK;
      PARENT_ID = I$OBJ_ID;
      OBJECT_ID = NULL;
      LINK_ID = NULL;
      SUSPEND;
    END

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE VERIFY_PUPIL_DICT (
    I$LEVEL_ID BIGINT)
RETURNS (
    TYPE_ID BIGINT,
    TYPE_NAME VARCHAR(400),
    PARAM_ID BIGINT,
    PARAM_NAME VARCHAR(400),
    PARAM_TYPE_ID BIGINT,
    PARAM_TYPE_NAME VARCHAR(100),
    VAL_REQUIRED SMALLINT,
    VAL_CHECK SMALLINT,
    VAL_MASK VARCHAR(400),
    VAL_EXTRA VARCHAR(400))
AS
begin

  -- Проверяем что LEVEL_ID допустимый
  IF(NOT EXISTS(
    SELECT FIRST 1 1
    FROM LEVELS L
    JOIN TASKS T ON T.TASK_ID = L.TASK_ID AND T.IS_DEL = 0
    JOIN MODULES M ON M.MODULE_ID = T.MODULE_ID AND M.IS_DEL = 0 AND M.IS_ACTIVE = 1
    WHERE L.LEVEL_ID = :I$LEVEL_ID AND L.IS_DEL = 0
  ))
  THEN
    EXCEPTION DATA_ERROR 'Недопустимое приложение для контроля';

  -- Поля для объектов: ученик, связь ученик-родитель, идентифицирующий документ, документ об образовании
  -- заполняемые в данном приложении (RW)
  FOR
    SELECT P.TYPE_ID, P.PARAM_ID, P.PARAM_TYPE, RT.VAL, RP.VAL, P.IS_REQUIRED, IIF(P.DO_CHECK = 0, 0, 1), P.EDIT_MASK
    FROM PARAMS P
    JOIN LPARAMS LP ON LP.PARAM_ID = P.PARAM_ID AND LP.LEVEL_ID = :I$LEVEL_ID AND LP.IS_DEL = 0 AND LP.EDIT_TYPE = 1
    JOIN TYPES T ON T.TYPE_ID = P.TYPE_ID AND T.IS_DEL = 0
    JOIN RES RT ON RT.RES_ID = T.RES_ID AND RT.LANG_CODE = 'RU'
    JOIN RES RP ON RP.RES_ID = P.RES_ID AND RP.LANG_CODE = 'RU'
    WHERE P.TYPE_ID IN (10, 11, 12, 79, 162, 293) AND P.IS_DEL = 0
      AND (P.IS_REQUIRED = 1 OR (P.EDIT_MASK IS NOT NULL AND P.EDIT_MASK <> ''))
    ORDER BY T.SORT_ORDER, P.GRID_ORDER
    INTO :TYPE_ID, :PARAM_ID, :PARAM_TYPE_ID, :TYPE_NAME, :PARAM_NAME, :VAL_REQUIRED, :VAL_CHECK, :VAL_MASK
  DO
  BEGIN
    IF(VAL_MASK = '') THEN VAL_MASK = NULL;

    IF(PARAM_TYPE_ID = 1) THEN PARAM_TYPE_NAME = 'Целое число';
    ELSE IF(PARAM_TYPE_ID = 2) THEN PARAM_TYPE_NAME = 'Вещественное число';
    ELSE IF(PARAM_TYPE_ID = 3) THEN PARAM_TYPE_NAME = 'Дата и время';
    ELSE IF(PARAM_TYPE_ID = 4) THEN PARAM_TYPE_NAME = 'Дата';
    ELSE IF(PARAM_TYPE_ID = 5) THEN PARAM_TYPE_NAME = 'Время';
    ELSE IF(PARAM_TYPE_ID = 6) THEN PARAM_TYPE_NAME = 'Значение из справочника';
    ELSE IF(PARAM_TYPE_ID = 7) THEN PARAM_TYPE_NAME = 'Строка или значение из справочника';
    ELSE IF(PARAM_TYPE_ID = 8) THEN PARAM_TYPE_NAME = 'Строка';
    ELSE IF(PARAM_TYPE_ID = 11) THEN PARAM_TYPE_NAME = 'Файл';
    ELSE IF(PARAM_TYPE_ID = 12) THEN PARAM_TYPE_NAME = 'Изображение';
    ELSE IF(PARAM_TYPE_ID = 13) THEN PARAM_TYPE_NAME = 'Ссылка на объект';
    ELSE IF(PARAM_TYPE_ID = 18) THEN PARAM_TYPE_NAME = 'Адрес';
    ELSE PARAM_TYPE_NAME = 'Недопустимый тип';

    VAL_EXTRA = NULL;
    -- IF(PARAM_TYPE_ID = 8 AND TYPE_ID = 2 AND VAL_MASK IS NULL) THEN VAL_EXTRA = 'CLEANUP';

    SUSPEND;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE VERIFY_SUBJECT (
    I$OBJ_ID BIGINT)
RETURNS (
    LINK_ID BIGINT,
    OBJECT_ID BIGINT,
    PARENT_ID BIGINT,
    NAME_TASK VARCHAR(1000),
    ERROR_NAME VARCHAR(1000),
    PARAMS_NAME VARCHAR(1000),
    ERROR_TEXT VARCHAR(1000),
    ERROR_TYPE SMALLINT)
AS
declare variable V$TYPE_ID bigint;
declare variable V$VALS varchar(1000);
declare variable SUBJECT_ID bigint;
declare variable NEW_SUBJECT_ID bigint;
declare variable I$LOOP integer;
declare variable V$FIXED smallint;
BEGIN
    NAME_TASK = 'Предметы';
    ERROR_TYPE = 0;

    FOR
      SELECT L51.LINK_ID, L51.OBJ_ID, L51.PARENT_ID, L51.OBJ_ID
      FROM LINKS L301
      JOIN LINKS L51 ON L51.PARENT_ID = L301.OBJ_ID AND L51.DATE_DEL IS NULL AND L51.OBJ_TYPE_ID IN (51, 197)
      WHERE L301.PARENT_ID = :I$OBJ_ID AND L301.OBJ_TYPE_ID = 301 AND L301.DATE_DEL IS NULL
      INTO :LINK_ID, :OBJECT_ID, :PARENT_ID, :V$TYPE_ID
    DO
    BEGIN
      SELECT CAPTION FROM OBJECT_CAPTION_GET(:OBJECT_ID) INTO :V$VALS;

      FOR
        SELECT ERROR_TYPE, ERROR_TEXT, ERROR_NAME, PARAMS_NAME
        FROM VERIFY_OBJECT_FIELDS(:OBJECT_ID, :V$TYPE_ID, 'предмета', :V$VALS)
        INTO :ERROR_TYPE, :ERROR_TEXT, :ERROR_NAME, :PARAMS_NAME
      DO
      BEGIN
        SUSPEND;
      END
    END

    -- Служебное сообщение об успешности проверок
    IF(ERROR_TYPE = 0) THEN
    BEGIN
      ERROR_TEXT = 'Данные успешно верифицированы, замечаний и ошибок нет';
      ERROR_NAME = 'Без замечаний';
      PARAMS_NAME = NAME_TASK;
      PARENT_ID = I$OBJ_ID;
      OBJECT_ID = NULL;
      LINK_ID = NULL;
      SUSPEND;
    END

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE VERIFY_SUBJECT_DICT (
    I$LEVEL_ID BIGINT)
RETURNS (
    TYPE_ID BIGINT,
    TYPE_NAME VARCHAR(400),
    PARAM_ID BIGINT,
    PARAM_NAME VARCHAR(400),
    PARAM_TYPE_ID BIGINT,
    PARAM_TYPE_NAME VARCHAR(100),
    VAL_REQUIRED SMALLINT,
    VAL_CHECK SMALLINT,
    VAL_MASK VARCHAR(400),
    VAL_EXTRA VARCHAR(400))
AS
begin

  -- Проверяем что LEVEL_ID допустимый
  IF(NOT EXISTS(
    SELECT FIRST 1 1
    FROM LEVELS L
    JOIN TASKS T ON T.TASK_ID = L.TASK_ID AND T.IS_DEL = 0
    JOIN MODULES M ON M.MODULE_ID = T.MODULE_ID AND M.IS_DEL = 0 AND M.IS_ACTIVE = 1
    WHERE L.LEVEL_ID = :I$LEVEL_ID AND L.IS_DEL = 0
  ))
  THEN
    EXCEPTION DATA_ERROR 'Недопустимое приложение для контроля';

  -- Поля для объектов: предмет #51, дисциплина #197
  -- заполняемые в данном приложении (RW)
  FOR
    SELECT P.TYPE_ID, P.PARAM_ID, P.PARAM_TYPE, RT.VAL, RP.VAL, P.IS_REQUIRED, IIF(P.DO_CHECK = 0, 0, 1), P.EDIT_MASK
    FROM PARAMS P
    JOIN LPARAMS LP ON LP.PARAM_ID = P.PARAM_ID AND LP.LEVEL_ID = :I$LEVEL_ID AND LP.IS_DEL = 0 AND LP.EDIT_TYPE = 1
    JOIN TYPES T ON T.TYPE_ID = P.TYPE_ID AND T.IS_DEL = 0
    JOIN RES RT ON RT.RES_ID = T.RES_ID AND RT.LANG_CODE = 'RU'
    JOIN RES RP ON RP.RES_ID = P.RES_ID AND RP.LANG_CODE = 'RU'
    WHERE P.TYPE_ID IN (51, 197) AND P.IS_DEL = 0
      AND (P.IS_REQUIRED = 1 OR (P.EDIT_MASK IS NOT NULL AND P.EDIT_MASK <> ''))
    ORDER BY T.SORT_ORDER, P.GRID_ORDER
    INTO :TYPE_ID, :PARAM_ID, :PARAM_TYPE_ID, :TYPE_NAME, :PARAM_NAME, :VAL_REQUIRED, :VAL_CHECK, :VAL_MASK
  DO
  BEGIN
    IF(VAL_MASK = '') THEN VAL_MASK = NULL;

    IF(PARAM_TYPE_ID = 1) THEN PARAM_TYPE_NAME = 'Целое число';
    ELSE IF(PARAM_TYPE_ID = 2) THEN PARAM_TYPE_NAME = 'Вещественное число';
    ELSE IF(PARAM_TYPE_ID = 3) THEN PARAM_TYPE_NAME = 'Дата и время';
    ELSE IF(PARAM_TYPE_ID = 4) THEN PARAM_TYPE_NAME = 'Дата';
    ELSE IF(PARAM_TYPE_ID = 5) THEN PARAM_TYPE_NAME = 'Время';
    ELSE IF(PARAM_TYPE_ID = 6) THEN PARAM_TYPE_NAME = 'Значение из справочника';
    ELSE IF(PARAM_TYPE_ID = 7) THEN PARAM_TYPE_NAME = 'Строка или значение из справочника';
    ELSE IF(PARAM_TYPE_ID = 8) THEN PARAM_TYPE_NAME = 'Строка';
    ELSE IF(PARAM_TYPE_ID = 11) THEN PARAM_TYPE_NAME = 'Файл';
    ELSE IF(PARAM_TYPE_ID = 12) THEN PARAM_TYPE_NAME = 'Изображение';
    ELSE IF(PARAM_TYPE_ID = 13) THEN PARAM_TYPE_NAME = 'Ссылка на объект';
    ELSE IF(PARAM_TYPE_ID = 18) THEN PARAM_TYPE_NAME = 'Адрес';
    ELSE PARAM_TYPE_NAME = 'Недопустимый тип';

    VAL_EXTRA = NULL;
    -- IF(PARAM_TYPE_ID = 8 AND TYPE_ID = 2 AND VAL_MASK IS NULL) THEN VAL_EXTRA = 'CLEANUP';

    SUSPEND;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE VERIFY_TIMETABLE (
    I$OBJ_ID BIGINT)
RETURNS (
    LINK_ID BIGINT,
    OBJECT_ID BIGINT,
    PARENT_ID BIGINT,
    NAME_TASK VARCHAR(1000),
    ERROR_NAME VARCHAR(1000),
    PARAMS_NAME VARCHAR(1000),
    ERROR_TEXT VARCHAR(1000),
    ERROR_TYPE SMALLINT)
AS
declare variable V$OBJ_ID bigint;
declare variable V$LINK_ID bigint;
declare variable V$TEMP bigint;
declare variable V$VALS varchar(1000);
declare variable V$EMPTY_RECORD_COUNT integer;
declare variable V$EMPTY_RECORD_COUNT2 integer;
declare variable V$TVALS varchar(1000);
declare variable V$TVALS2 varchar(1000);
declare variable V$DATE_START timestamp;
declare variable V$DATE_STOP timestamp;
declare variable V$MIN_DATE_START timestamp;
declare variable V$MAX_DATE_STOP timestamp;
declare variable M smallint;
BEGIN
    NAME_TASK = 'Расписание занятий';
    ERROR_TYPE = 0;

    V$EMPTY_RECORD_COUNT = 0;
    FOR
        SELECT L151.OBJ_ID, L151.LINK_ID
        FROM LINKS L150
        JOIN LINKS L151 ON L151.PARENT_ID = L150.OBJ_ID AND L151.DATE_DEL IS NULL AND L151.OBJ_TYPE_ID = 151
        WHERE L150.PARENT_ID = :I$OBJ_ID AND L150.DATE_DEL IS NULL AND L150.OBJ_TYPE_ID IN (150, 481)
        INTO :OBJECT_ID, :LINK_ID
    DO
    BEGIN
        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:OBJECT_ID)
        INTO :V$TVALS2;

        SELECT TRIM(V)
        FROM VAL_GET(:OBJECT_ID, 1147)
        INTO :V$VALS;

        IF (V$VALS = '') THEN
        BEGIN
            IF (EXISTS(SELECT FIRST 1 1 FROM LINKS WHERE PARENT_ID = :OBJECT_ID AND DATE_DEL IS NULL AND OBJ_TYPE_ID = 154) OR
                EXISTS(SELECT FIRST 1 1 FROM LINKS WHERE PARENT_ID = :OBJECT_ID AND DATE_DEL IS NULL AND OBJ_TYPE_ID = 9)) THEN
            BEGIN
                ERROR_TEXT = 'В списке расписаний учебных периодов существует неназванное расписание учебных периодов обозначенное как "< ... >"';
                ERROR_NAME = :ERROR_TEXT;
                PARAMS_NAME = 'Расписание учебных периодов';
                ERROR_TYPE = 3;
                SUSPEND;
            END
            ELSE
            BEGIN
                UPDATE LINKS L
                SET L.DATE_DEL = CURRENT_TIMESTAMP
                WHERE L.LINK_ID = :LINK_ID AND L.OBJ_TYPE_ID = 151 AND L.DATE_DEL IS NULL;

                V$EMPTY_RECORD_COUNT = V$EMPTY_RECORD_COUNT + 1;
            END
        END
        V$EMPTY_RECORD_COUNT2 = 0;
        V$MIN_DATE_START = NULL;
        V$MAX_DATE_STOP = NULL;
        IF (EXISTS(
            SELECT FIRST 1 1
            FROM LINKS L9
            WHERE L9.PARENT_ID = :OBJECT_ID
            AND L9.DATE_DEL IS NULL
            AND L9.OBJ_TYPE_ID = 9
        ) AND NOT EXISTS(
            SELECT FIRST 1 1
            FROM LINKS L154
            WHERE L154.PARENT_ID = :OBJECT_ID
            AND L154.DATE_DEL IS NULL
            AND L154.OBJ_TYPE_ID = 154
        )) THEN
        BEGIN
            ERROR_TEXT = 'В расписании учебных периодов «' || V$TVALS2 || '» не введены даты учебных периодов.';
            ERROR_NAME = 'В расписании учебных периодов не введены даты учебных периодов.';
            PARAMS_NAME = 'Расписание учебных периодов';
            ERROR_TYPE = 3;
            SUSPEND;
        END
        FOR
            SELECT L154.OBJ_ID,
                   L154.LINK_ID
            FROM LINKS L154
            WHERE L154.PARENT_ID = :OBJECT_ID
            AND L154.DATE_DEL IS NULL
            AND L154.OBJ_TYPE_ID = 154
            INTO :V$OBJ_ID,
                 :V$LINK_ID
        DO
        BEGIN
            SELECT I FROM VAL_GET(:V$OBJ_ID, 1170) INTO :V$TEMP;
            V$DATE_START = NULL;
            V$DATE_STOP = NULL;
            SELECT FIRST 1 VAL
            FROM VALD
            WHERE OBJ_ID = :V$OBJ_ID
            AND PARAM_ID = 1169
            AND IS_DEL = 0
            INTO :V$DATE_START;
            SELECT FIRST 1 VAL
            FROM VALD
            WHERE OBJ_ID = :V$OBJ_ID
            AND PARAM_ID = 1174
            AND IS_DEL = 0
            INTO :V$DATE_STOP;

            IF ((V$TEMP = 0) AND (V$DATE_START IS NULL) AND (V$DATE_STOP IS NULL)) THEN
            BEGIN
                UPDATE LINKS L
                SET L.DATE_DEL = CURRENT_TIMESTAMP
                WHERE L.LINK_ID = :V$LINK_ID
                AND L.OBJ_TYPE_ID = 154
                AND L.DATE_DEL IS NULL;

                V$EMPTY_RECORD_COUNT2 = V$EMPTY_RECORD_COUNT2 + 1;
            END
            ELSE
            BEGIN
                IF ((V$DATE_START IS NOT NULL) AND
                    ((V$MIN_DATE_START IS NULL) OR (V$MIN_DATE_START > V$DATE_START))) THEN
                BEGIN
                    V$MIN_DATE_START = V$DATE_START;
                END
                IF ((V$DATE_STOP IS NOT NULL) AND
                    ((V$MAX_DATE_STOP IS NULL) OR (V$MAX_DATE_STOP < V$DATE_STOP))) THEN
                BEGIN
                    V$MAX_DATE_STOP = V$DATE_STOP;
                END
                IF ((V$DATE_START IS NOT NULL) AND (V$DATE_STOP IS NOT NULL) AND (V$DATE_STOP < V$DATE_START)) THEN
                BEGIN
                    SELECT CAPTION
                    FROM OBJECT_CAPTION_GET(:V$OBJ_ID)
                    INTO :V$TVALS;
                    ERROR_TEXT = 'В расписании учебных периодов «' || V$TVALS2 || '» у периода «' || V$TVALS || '» дата окончания меньше чем дата начала.';
                    ERROR_NAME = 'В расписании учебных периодов у периода дата окончания меньше чем дата начала.';
                    PARAMS_NAME = 'Расписание учебных периодов';
                    ERROR_TYPE = 3;
                    SUSPEND;
                END
                IF ((V$TEMP = 0) OR (V$DATE_START IS NULL) OR (V$DATE_STOP IS NULL)) THEN
                BEGIN
                    ERROR_TEXT = 'В расписании учебных периодов «' || V$TVALS2 || '» в списке учебных периодов есть незаполненные поля.';
                    ERROR_NAME = 'В расписании учебных периодов в списке учебных периодов есть незаполненные поля.';
                    PARAMS_NAME = 'Расписание учебных периодов';
                    ERROR_TYPE = 3;
                    SUSPEND;
                END
            END
        END
        M = EXTRACT(MONTH FROM CURRENT_TIMESTAMP);
        IF (M NOT IN (7,8) AND
            ((CURRENT_TIMESTAMP < V$MIN_DATE_START) OR (CURRENT_TIMESTAMP > V$MAX_DATE_STOP)) AND
            EXISTS(SELECT FIRST 1 1 FROM LINKS
                   WHERE PARENT_ID = :OBJECT_ID
                   AND DATE_DEL IS NULL
                   AND OBJ_TYPE_ID = 9
            )) THEN
        BEGIN
            ERROR_TEXT = 'Расписание учебных периодов «' || V$TVALS2 || '» не включает текущую дату. Возможно оно задано неверно.';
            ERROR_NAME = 'Расписание учебных периодов не включает текущую дату. Возможно оно задано неверно.';
            PARAMS_NAME = 'Расписание учебных периодов';
            ERROR_TYPE = 2;
            SUSPEND;
        END
        IF (V$EMPTY_RECORD_COUNT2 > 0) THEN
        BEGIN
            ERROR_TEXT = 'Список учебных периодов в расписании «' || V$TVALS2 || '» был очищен от пустых записей';
            ERROR_NAME = 'Список учебных периодов в расписании был очищен от пустых записей';
            PARAMS_NAME = 'Расписание учебных периодов';
            ERROR_TYPE = 1;
            SUSPEND;
        END
    END
    IF (V$EMPTY_RECORD_COUNT > 0) THEN
    BEGIN
        OBJECT_ID = NULL;
        LINK_ID = NULL;
        ERROR_TEXT = 'Список расписаний учебных периодов был очищен от пустых записей';
        ERROR_NAME = :ERROR_TEXT;
        PARAMS_NAME = 'Расписание учебных периодов';
        ERROR_TYPE = 1;
        SUSPEND;
    END
    FOR
        SELECT L256.OBJ_ID,
               L256.LINK_ID
        FROM LINKS L69

        JOIN LINKS L57
        ON L57.PARENT_ID = L69.OBJ_ID
        AND L57.OBJ_TYPE_ID = 57
        AND L57.DATE_DEL IS NULL

        JOIN LINKS L50
        ON L50.PARENT_ID = L57.OBJ_ID
        AND L50.OBJ_TYPE_ID = 50
        AND L50.DATE_DEL IS NULL

        JOIN LINKS L54
        ON L54.PARENT_ID = L50.OBJ_ID
        AND L54.OBJ_TYPE_ID = 54
        AND L54.DATE_DEL IS NULL

        JOIN LINKS L256
        ON L256.PARENT_ID = L54.OBJ_ID
        AND L256.OBJ_TYPE_ID = 256
        AND L256.DATE_DEL IS NULL

        WHERE L69.PARENT_ID = :I$OBJ_ID
        AND L69.OBJ_TYPE_ID = 69
        AND L69.DATE_DEL IS NULL

        INTO :OBJECT_ID,
             :LINK_ID
    DO
    BEGIN
        IF (NOT EXISTS(SELECT FIRST 1 1 FROM LINKS WHERE OBJ_ID = :OBJECT_ID AND DATE_DEL IS NULL AND PARENT_TYPE_ID = 151)) THEN
        BEGIN
            SELECT CAPTION
            FROM OBJECT_CAPTION_GET(:OBJECT_ID)
            INTO :V$TVALS2;

            ERROR_TEXT = 'Для учебного коллектива «' || V$TVALS2 || '» не задано расписание учебных периодов';
            ERROR_NAME = 'Для учебного коллектива не задано расписание учебных периодов';
            PARAMS_NAME = 'Учебный коллектив';
            ERROR_TYPE = 2;
            SUSPEND;
        END
    END

    -- Служебное сообщение об успешности проверок
    IF(ERROR_TYPE = 0) THEN
    BEGIN
      ERROR_TEXT = 'Данные успешно верифицированы, замечаний и ошибок нет';
      ERROR_NAME = 'Без замечаний';
      PARAMS_NAME = NAME_TASK;
      PARENT_ID = I$OBJ_ID;
      OBJECT_ID = NULL;
      LINK_ID = NULL;
      SUSPEND;
    END

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE VERIFY_TIMETABLE_DICT (
    I$LEVEL_ID BIGINT)
RETURNS (
    TYPE_ID BIGINT,
    TYPE_NAME VARCHAR(400),
    PARAM_ID BIGINT,
    PARAM_NAME VARCHAR(400),
    PARAM_TYPE_ID BIGINT,
    PARAM_TYPE_NAME VARCHAR(100),
    VAL_REQUIRED SMALLINT,
    VAL_CHECK SMALLINT,
    VAL_MASK VARCHAR(400),
    VAL_EXTRA VARCHAR(400))
AS
begin

  -- Проверяем что LEVEL_ID допустимый
  IF(NOT EXISTS(
    SELECT FIRST 1 1
    FROM LEVELS L
    JOIN TASKS T ON T.TASK_ID = L.TASK_ID AND T.IS_DEL = 0
    JOIN MODULES M ON M.MODULE_ID = T.MODULE_ID AND M.IS_DEL = 0 AND M.IS_ACTIVE = 1
    WHERE L.LEVEL_ID = :I$LEVEL_ID AND L.IS_DEL = 0
  ))
  THEN
    EXCEPTION DATA_ERROR 'Недопустимое приложение для контроля';

  -- Поля для объектов: МТР всех видов
  -- заполняемые в данном приложении (RW)
  FOR
    SELECT P.TYPE_ID, P.PARAM_ID, P.PARAM_TYPE, RT.VAL, RP.VAL, P.IS_REQUIRED, IIF(P.DO_CHECK = 0, 0, 1), P.EDIT_MASK
    FROM PARAMS P
    JOIN LPARAMS LP ON LP.PARAM_ID = P.PARAM_ID AND LP.LEVEL_ID = :I$LEVEL_ID AND LP.IS_DEL = 0 AND LP.EDIT_TYPE = 1
    JOIN TYPES T ON T.TYPE_ID = P.TYPE_ID AND T.IS_DEL = 0
    JOIN RES RT ON RT.RES_ID = T.RES_ID AND RT.LANG_CODE = 'RU'
    JOIN RES RP ON RP.RES_ID = P.RES_ID AND RP.LANG_CODE = 'RU'
    WHERE P.TYPE_ID IN (151, 154, 450, 491, 487, 486) AND P.IS_DEL = 0
      AND (P.IS_REQUIRED = 1 OR (P.EDIT_MASK IS NOT NULL AND P.EDIT_MASK <> ''))
    ORDER BY T.SORT_ORDER, P.GRID_ORDER
    INTO :TYPE_ID, :PARAM_ID, :PARAM_TYPE_ID, :TYPE_NAME, :PARAM_NAME, :VAL_REQUIRED, :VAL_CHECK, :VAL_MASK
  DO
  BEGIN
    IF(VAL_MASK = '') THEN VAL_MASK = NULL;

    IF(PARAM_TYPE_ID = 1) THEN PARAM_TYPE_NAME = 'Целое число';
    ELSE IF(PARAM_TYPE_ID = 2) THEN PARAM_TYPE_NAME = 'Вещественное число';
    ELSE IF(PARAM_TYPE_ID = 3) THEN PARAM_TYPE_NAME = 'Дата и время';
    ELSE IF(PARAM_TYPE_ID = 4) THEN PARAM_TYPE_NAME = 'Дата';
    ELSE IF(PARAM_TYPE_ID = 5) THEN PARAM_TYPE_NAME = 'Время';
    ELSE IF(PARAM_TYPE_ID = 6) THEN PARAM_TYPE_NAME = 'Значение из справочника';
    ELSE IF(PARAM_TYPE_ID = 7) THEN PARAM_TYPE_NAME = 'Строка или значение из справочника';
    ELSE IF(PARAM_TYPE_ID = 8) THEN PARAM_TYPE_NAME = 'Строка';
    ELSE IF(PARAM_TYPE_ID = 11) THEN PARAM_TYPE_NAME = 'Файл';
    ELSE IF(PARAM_TYPE_ID = 12) THEN PARAM_TYPE_NAME = 'Изображение';
    ELSE IF(PARAM_TYPE_ID = 13) THEN PARAM_TYPE_NAME = 'Ссылка на объект';
    ELSE IF(PARAM_TYPE_ID = 18) THEN PARAM_TYPE_NAME = 'Адрес';
    ELSE PARAM_TYPE_NAME = 'Недопустимый тип';

    VAL_EXTRA = NULL;
    -- IF(PARAM_ID IN (589)) THEN VAL_EXTRA = 'Уникальность';

    SUSPEND;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE VERIFY_UP_STD (
    I$OBJ_ID BIGINT,
    I$VAL BIGINT)
AS
declare variable V$PARENT_TYPE bigint;
declare variable V$OP_TYPE bigint;
declare variable V$OP_LEVEL bigint;
declare variable V$ADAPT bigint;
declare variable V$DT timestamp;
begin

  -- Какой стоит тип ОП ?
  -- Если это шаблон - то разрешаем любой

  SELECT FIRST 1 LP.PARENT_TYPE_ID
  FROM LINKS LP
  WHERE LP.OBJ_ID = :I$OBJ_ID AND LP.PARENT_TYPE_ID IN (55, 57) AND LP.DATE_DEL IS NULL
  INTO :V$PARENT_TYPE;

  SELECT V1832.LISTVAL_ID, V1593.LISTVAL_ID, V2379.LISTVAL_ID, LP57.DATE_INS
  FROM LINKS LP57
  JOIN VALL V1832 ON V1832.OBJ_ID = LP57.PARENT_ID AND V1832.PARAM_ID = 1832 AND V1832.IS_DEL = 0
  JOIN VALL V1593 ON V1593.OBJ_ID = LP57.PARENT_ID AND V1593.PARAM_ID = 1593 AND V1593.IS_DEL = 0
  JOIN VALL V2379 ON V2379.OBJ_ID = LP57.PARENT_ID AND V2379.PARAM_ID = 2379 AND V2379.IS_DEL = 0
  WHERE LP57.OBJ_ID = :I$OBJ_ID AND LP57.PARENT_TYPE_ID = 57 AND LP57.DATE_DEL IS NULL
  INTO :V$OP_TYPE, :V$OP_LEVEL, :V$ADAPT, :V$DT;

  -- Временно оставляем ФБУП
  -- IF(I$VAL = 11720 AND V$OP_TYPE <> 13287) THEN EXCEPTION DATA_ERROR 'Нельзя выбрать этот стандарт';

  IF(ABS(DATEDIFF(MILLISECOND FROM V$DT TO CURRENT_TIMESTAMP)) < 1000) THEN
  BEGIN
    -- Внимание: когда создается новый объект с чистого листа, возможен конфликт. Поэтому проверяем метку времени объекта, и не формируем ошибку если создание плана было менее 1 секунды назад
  END
  ELSE IF(V$PARENT_TYPE = 55) THEN
  BEGIN
    -- Для шаблонов все равно
  END
  ELSE IF(V$OP_TYPE = 13287) THEN
  BEGIN
    -- Только адаптированная для интеллектуальных нарушений
    IF(I$VAL NOT IN (11720, 13273, 14184, 14186)) THEN EXCEPTION DATA_ERROR 'Нельзя выбрать этот стандарт';
  END
  ELSE IF(V$ADAPT <> 11187) THEN
  BEGIN
    -- Адаптированная любых видов кроме интеллектуальных нарушений - только для НОО
    /*IF(V$OP_LEVEL = 5339 AND I$VAL NOT IN (11721, 13288)) THEN EXCEPTION DATA_ERROR 'Нельзя выбрать этот стандарт';
    ELSE IF(V$OP_LEVEL <> 5339 AND I$VAL NOT IN (11721)) THEN EXCEPTION DATA_ERROR 'Нельзя выбрать этот стандарт';*/

    IF(I$VAL NOT IN (11720, 11721, 13452, 13288, 14184, 14186)) THEN EXCEPTION DATA_ERROR 'Нельзя выбрать этот стандарт';
  END
  ELSE
  BEGIN
    IF(I$VAL NOT IN (11720, 11721, 13452, 14184)) THEN EXCEPTION DATA_ERROR 'Нельзя выбрать этот стандарт';
    -- Для НОО запрещаем выбор ФГОС и ФГОС-2021
    IF(V$OP_TYPE = 5340 AND I$VAL <> 14184) THEN EXCEPTION DATA_ERROR 'Для НОО может быть выбран только стандарт ФОП';
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE VERIFY_USER2 (
    I$NAME VARCHAR(100),
    I$PASSWORD VARCHAR(200),
    I$FROM VARCHAR(1000),
    I$ID VARCHAR(40),
    I$RT VARCHAR(100),
    I$OLD_RT VARCHAR(100) = NULL,
    I$PASSWORD2 VARCHAR(200) = NULL)
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$OU_LEVEL SMALLINT;
DECLARE VARIABLE V$OU_LICENCE_TYPE CHAR(1);
DECLARE VARIABLE V$LEVEL BIGINT;
DECLARE VARIABLE V$KEY INTEGER;
DECLARE VARIABLE V$USER_ID BIGINT;
DECLARE VARIABLE V$PERSON_TYPE BIGINT;
DECLARE VARIABLE V$USER_NAME VARCHAR(100);
DECLARE VARIABLE V$ROLE SMALLINT;
DECLARE VARIABLE V$PERSON_ID BIGINT;
DECLARE VARIABLE V$PWD VARCHAR(200);
DECLARE VARIABLE V$EXP_DATE DATE;
DECLARE VARIABLE V$BLOCKED SMALLINT;
DECLARE VARIABLE V$ACCESS SMALLINT;
DECLARE VARIABLE V$OVERRIDE SMALLINT;
DECLARE VARIABLE N INTEGER;
DECLARE VARIABLE V$HAS_TEST_CHOOSE SMALLINT;
DECLARE VARIABLE V$HAS_EXPERTS SMALLINT;
DECLARE VARIABLE V$EXPERT_ID BIGINT;
DECLARE VARIABLE V$REF_ID BIGINT;
DECLARE VARIABLE V$BASEID BIGINT;
DECLARE VARIABLE V$OLD_RT VARCHAR(100);
DECLARE VARIABLE V$DT TIMESTAMP;
DECLARE VARIABLE V$SNILS VARCHAR(40);
DECLARE VARIABLE S1 VARCHAR(200);
DECLARE VARIABLE S2 VARCHAR(200);
DECLARE VARIABLE S3 VARCHAR(200);
DECLARE VARIABLE P INTEGER;
DECLARE VARIABLE V$IS_BLOCKED_PWD SMALLINT;
DECLARE VARIABLE V$MUST_CHANGE SMALLINT;
DECLARE VARIABLE V$OVERRIDE2 SMALLINT;
DECLARE VARIABLE V$OU_ID BIGINT;
DECLARE VARIABLE V$HAS_DO SMALLINT;
DECLARE VARIABLE V$HAS_OO SMALLINT;
DECLARE VARIABLE V$HAS_SPO SMALLINT;
DECLARE VARIABLE V$HAS_PO SMALLINT;
DECLARE VARIABLE D BIGINT;
begin

  -- I$PASSWORD2 - пароль повышенной стойкости

  SELECT KEY_VAL FROM KEYS WHERE KEY_CODE = 'LEVEL' INTO :V$OU_LEVEL;
  SELECT STATUS FROM OU_LICENCE_TYPE INTO :V$OU_LICENCE_TYPE;
  IF(V$OU_LEVEL IS NULL) THEN EXIT;

  IF(NOT EXISTS(SELECT 1 FROM RDB$USER_PRIVILEGES WHERE RDB$RELATION_NAME = 'VER' AND RDB$USER = 'INISSOFT_ROLE' AND RDB$PRIVILEGE = 'S'))
    THEN EXCEPTION DATA_ERROR 'Обновление базы данных не было завершено, работа с базой невозможна';

  -- Указывается либо пара name:password, либо id (продление токена), либо @REGID@SNILS
  -- По СНИЛС авторизовываем только на региональном уровне
  IF((I$ID IS NULL AND SUBSTRING(I$NAME FROM 1 FOR 1) <> '@') OR SUBSTRING(I$ID FROM 1 FOR 1) <> 'e') THEN
  BEGIN
    SELECT FIRST 1 U.USER_ID, U.USER_TYPE, U.OBJ_ID, U.PWD, U.EXP_DATE, U.IS_BLOCKED, U.USER_NAME, O.TYPE_ID, U.IS_BLOCKED_PWD, U.MUST_CHANGE
    FROM USERS U
    LEFT JOIN OBJECTS O ON O.OBJ_ID = U.OBJ_ID
    WHERE (U.USER_NAME = :I$NAME OR U.USER_ID = :I$ID) AND U.DATE_DEL IS NULL
    INTO :V$USER_ID, :V$ROLE, :V$PERSON_ID, :V$PWD, :V$EXP_DATE, :V$BLOCKED, :V$USER_NAME, :V$PERSON_TYPE, :V$IS_BLOCKED_PWD, :V$MUST_CHANGE;
  END
  ELSE IF(SUBSTRING(I$NAME FROM 1 FOR 1) = '@') THEN
  BEGIN
    -- тут может быть вариант с фигурными скобками, но это старый формат и его игнорируем
    -- разделяем на СНИЛС и РегИД
    I$NAME = UPPER(SUBSTRING(I$NAME FROM 2));
    P = POSITION('@' IN I$NAME);
    V$SNILS = SUBSTRING(I$NAME FROM P + 1);
    I$NAME = SUBSTRING(I$NAME FROM 1 FOR P - 1);

    SELECT FIRST 1 U.USER_ID, U.USER_TYPE, U.OBJ_ID, U.PWD, U.EXP_DATE, U.IS_BLOCKED, U.USER_NAME, L.OBJ_TYPE_ID, U.IS_BLOCKED_PWD, U.MUST_CHANGE
    FROM VALS VID
    JOIN LINKS L ON L.OBJ_ID = VID.OBJ_ID AND L.PARENT_TYPE_ID IN (2, 211, 9, 187, 10) AND L.DATE_DEL IS NULL
    JOIN USERS U ON U.OBJ_ID = L.OBJ_ID AND U.DATE_DEL IS NULL
    WHERE UPPER(SUBSTRING(VID.SVAL FROM 1 FOR 36)) = :I$NAME AND VID.PARAM_ID IN (2912, 2915, 2917) AND VID.IS_DEL = 0
    ORDER BY L.OBJ_TYPE_ID -- роль родителя в последнюю очередь
    INTO :V$USER_ID, :V$ROLE, :V$PERSON_ID, :V$PWD, :V$EXP_DATE, :V$BLOCKED, :V$USER_NAME, :V$PERSON_TYPE, :V$IS_BLOCKED_PWD, :V$MUST_CHANGE;

    -- Юзера в персонах не нашли, ищем во внешних пользователях
    IF(V$USER_ID IS NULL) THEN
    BEGIN
      SELECT FIRST 1 U.USER_ID, U.USER_TYPE, U.OBJ_ID, U.PWD, U.EXP_DATE, U.IS_BLOCKED, U.USER_NAME, NULL, U.IS_BLOCKED_PWD, U.MUST_CHANGE
      FROM USERS U
      WHERE U.DATE_DEL IS NULL AND U.OBJ_ID IS NULL AND (REPLACE(REPLACE(U.SNILS, '-', ''), ' ', '') = :V$SNILS OR UPPER(SUBSTRING(U.REG_ID FROM 1 FOR 36)) = :I$NAME)
      INTO :V$USER_ID, :V$ROLE, :V$PERSON_ID, :V$PWD, :V$EXP_DATE, :V$BLOCKED, :V$USER_NAME, :V$PERSON_TYPE, :V$IS_BLOCKED_PWD, :V$MUST_CHANGE;
    END

    -- если юзера нет, но персона таки есть - вносим юзера в заблокированном виде
    IF(V$USER_ID IS NULL) THEN
    BEGIN
      SELECT FIRST 1 L.OBJ_ID, L.OBJ_TYPE_ID
      FROM VALS VID
      JOIN LINKS L ON L.OBJ_ID = VID.OBJ_ID AND L.PARENT_TYPE_ID IN (2, 211, 9, 187, 10) AND L.DATE_DEL IS NULL
      WHERE UPPER(SUBSTRING(VID.SVAL FROM 1 FOR 36)) = :I$NAME AND VID.PARAM_ID IN (2912, 2915, 2917) AND VID.IS_DEL = 0
      ORDER BY L.OBJ_TYPE_ID -- роль родителя в последнюю очередь
      INTO :V$PERSON_ID, :V$PERSON_TYPE;

      -- Добавляем юзера, причем пароль будет невалидный
      IF(V$PERSON_TYPE = 10) THEN BEGIN V$ROLE = 12; V$USER_NAME = 'student' || V$BASEID; END
      ELSE IF(V$PERSON_TYPE = 20) THEN BEGIN V$ROLE = 22; V$USER_NAME = 'parent' || V$BASEID; END
      -- для сотрудника в статусе только просмотр
      ELSE IF(V$PERSON_TYPE = 14) THEN BEGIN V$ROLE = 0; V$USER_NAME = 'teacher' || V$BASEID; END
      ELSE EXCEPTION DATA_ERROR 'Неизвестный тип персоны ' || COALESCE(V$PERSON_ID, 0);
      V$BLOCKED = 1;

      IF(V$PERSON_ID IS NOT NULL) THEN
      BEGIN
        SELECT FIRST 1 U.USER_ID, U.DATE_DEL
        FROM USERS U
        WHERE U.OBJ_ID = :V$PERSON_ID
        INTO :V$USER_ID, :V$DT;

        V$BASEID = (SELECT MAX(USER_ID) FROM USERS) + 1;
        IF(V$BASEID IS NULL) THEN V$BASEID = 1; ELSE V$BASEID = MOD(V$BASEID, 1000000000);

        SELECT V.VAL
        FROM VALS V
        WHERE V.OBJ_ID = :V$PERSON_ID AND V.PARAM_ID IN (55, 59, 128) AND V.IS_DEL = 0
        INTO :S1;
        SELECT V.VAL
        FROM VALS V
        WHERE V.OBJ_ID = :V$PERSON_ID AND V.PARAM_ID IN (56, 60, 129) AND V.IS_DEL = 0
        INTO :S2;
        SELECT COALESCE(V.VAL, '')
        FROM VALS V
        WHERE V.OBJ_ID = :V$PERSON_ID AND V.PARAM_ID IN (57, 61, 130) AND V.IS_DEL = 0
        INTO :S3;

        IF(V$USER_ID IS NULL) THEN
        BEGIN
          INSERT INTO USERS
          (OBJ_ID, USER_NAME, USER_TYPE, IS_BLOCKED, PWD, LAST_NAME, FIRST_NAME, MIDDLE_NAME)
          VALUES (:V$PERSON_ID, :V$USER_NAME, :V$ROLE, :V$BLOCKED, 'invalid', :S1, :S2, :S3)
          RETURNING USER_ID INTO :V$USER_ID;
        END
        ELSE
        BEGIN
          -- Восстанавливаем юзера, но блокируем
          UPDATE USERS
          SET DATE_DEL = NULL, IS_BLOCKED = 1, USER_TYPE = :V$ROLE, PWD = 'invalid', LAST_NAME = :S1, FIRST_NAME = :S2, MIDDLE_NAME = :S3
          WHERE USER_ID = :V$USER_ID;

          -- Порубить доступ к приложениям
          DELETE FROM LUSERS
          WHERE USER_ID = :V$USER_ID;
        END
      END
    END

    -- Пароль у нас не передается, ставим оригинальный
    I$PASSWORD = V$PWD;
  END
  ELSE IF(SUBSTRING(I$ID FROM 1 FOR 1) = 'e') THEN
  BEGIN
    V$EXPERT_ID = SUBSTRING(I$ID FROM 2);
  END

  -- Пароль истек ?
  IF(V$EXP_DATE IS NOT NULL AND V$EXP_DATE < CURRENT_DATE) THEN V$USER_ID = NULL;
  IF(V$BLOCKED <> 0) THEN
  BEGIN
    -- Фиксируем попытку доступа
    IF(V$USER_ID IS NOT NULL) THEN
    INSERT INTO AUTH_TOKENS
    (USER_ID, ADDR, RT, IS_VALID, IS_LOGIN)
    VALUES (:V$USER_ID, SUBSTRING(:I$FROM FROM 1 FOR 100), NULL, 2, 1);

    V$USER_ID = NULL;
  END

  -- Если логин нашелся, и это не актуализация кэша, фиксируем попытку доступа
  -- Если пароль неправильный - сбрасываем USER_ID
  IF(V$USER_ID IS NOT NULL AND I$FROM IS NOT NULL) THEN
  BEGIN
      -- Если это запрос продления, проверяем, был ли выдан этот RT
      IF(I$OLD_RT IS NOT NULL) THEN
      BEGIN
        V$DT = NULL;
        SELECT FIRST 1 T.RT, T.DATE_ADD
        FROM AUTH_TOKENS T
        WHERE T.USER_ID = :V$USER_ID AND T.ADDR = SUBSTRING(:I$FROM FROM 1 FOR 100)
        ORDER BY T.OBJ_ID DESC
        INTO :V$OLD_RT, :V$DT;

        IF(V$OLD_RT <> I$OLD_RT) THEN
        BEGIN
          V$OLD_RT = NULL;
          SELECT FIRST 1 T.RT
          FROM AUTH_TOKENS T
          WHERE T.USER_ID = :V$USER_ID AND T.ADDR = SUBSTRING(:I$FROM FROM 1 FOR 100) AND T.RT = :I$OLD_RT AND T.DATE_ADD >= DATEADD(-1 HOUR TO :V$DT)
          ORDER BY T.OBJ_ID DESC
          INTO :V$OLD_RT;
        END

        IF(V$OLD_RT IS NULL OR V$OLD_RT <> I$OLD_RT) THEN EXCEPTION DATA_ERROR 'Недействительный refresh-token';

        -- Чтобы правильно отметилось в реестре
        I$PASSWORD = V$PWD;
      END

      INSERT INTO AUTH_TOKENS
      (USER_ID, ADDR, RT, IS_VALID, IS_LOGIN)
      VALUES (:V$USER_ID, SUBSTRING(:I$FROM FROM 1 FOR 100), :I$RT, IIF(:V$PWD = :I$PASSWORD OR :V$PWD = :I$PASSWORD2, 1, 0), IIF(:I$OLD_RT IS NULL, 1, 0));

      -- Блокируем на 15 минут, если было более 5 ошибочных попыток
      SELECT COUNT(*)
      FROM AUTH_TOKENS
      WHERE USER_ID = :V$USER_ID AND DATE_ADD > DATEADD(-15 MINUTE TO CURRENT_TIMESTAMP) AND IS_VALID = 0
      INTO :N;

      -- Не кидаем исключение, а выдаем атрибут
      IF(N > 5) THEN
      BEGIN
        TAG_NAME = 'locked';
        VAL = NULL;
        SUSPEND;
        EXIT;
        -- EXCEPTION DATA_ERROR 'Превышено количество ошибочных авторизаций, блокировка на 15 минут';
      END

      IF(V$PWD <> I$PASSWORD AND V$PWD <> :I$PASSWORD2) THEN V$USER_ID = NULL;
  END

  -- Если это пользователь из числа внешних экпертов, проводим дополнительную проверку
  IF(V$USER_ID IS NULL) THEN
  BEGIN
    SELECT FIRST 1 E.EXPERT_ID, 4, E.ORG_ID
    FROM UT_EXPERTS E
    WHERE E.DATE_DEL IS NULL AND (E.TEACHER_ID IS NULL OR :V$OU_LEVEL > 1) AND E.IS_ACTIVE = 1 AND
      ((E.USER_NAME = :I$NAME AND (E.PWD = :I$PASSWORD OR E.PWD = :I$PASSWORD2)) OR E.EXPERT_ID = :V$EXPERT_ID)
    INTO :V$USER_ID, :V$ROLE, :V$REF_ID;

    IF(V$USER_ID IS NOT NULL) THEN
    BEGIN
      V$IS_BLOCKED_PWD = 0; -- временно !
      V$MUST_CHANGE = 0;

      TAG_NAME = 'key_id';
      V$KEY = (SELECT GEN FROM GEN);
      VAL = V$KEY;
      SUSPEND;

      -- Всегда уровень организации
      TAG_NAME = 'level';
      VAL = 2;
      SUSPEND;

      TAG_NAME = 'id';
      VAL = 'e' || V$USER_ID;
      SUSPEND;

      TAG_NAME = 'ref_id';
      VAL = V$REF_ID;
      SUSPEND;

      TAG_NAME = 'must_change_pwd';
      IF(V$IS_BLOCKED_PWD > 0 AND V$MUST_CHANGE > 0) THEN V$MUST_CHANGE = 0;
      VAL = V$MUST_CHANGE;
      SUSPEND;

      TAG_NAME = 'pwd_blocked';
      VAL = V$IS_BLOCKED_PWD;
      SUSPEND;

      -- !!! доделать, чтобы возвращалось название организации откуда приглашен
      TAG_NAME = 'ref_name';
      VAL = (SELECT KEY_VAL FROM KEYS WHERE KEY_CODE = 'ORGANIZATION_SHORT_NAME');
      SUSPEND;

      TAG_NAME = 'modules';
      VAL = NULL;
      SUSPEND;

      TAG_NAME = 'modules:module';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'modules:module:name';
      VAL = 'app.test_check';
      SUSPEND;
      TAG_NAME = 'modules:module:level';
      VAL = 4;
      SUSPEND;

      TAG_NAME = 'modules:module';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'modules:module:name';
      VAL = 'app.test_experts';
      SUSPEND;
      TAG_NAME = 'modules:module:level';
      VAL = 4;
      SUSPEND;

      EXIT;
    END
  END

  -- Не авторизован
  IF(V$USER_ID IS NULL) THEN EXIT;

  -- Конвертируем права доступа после перехода на S версию
  IF(V$OU_LICENCE_TYPE = 'S') THEN
  BEGIN
    FOR
      SELECT LU.LEVEL_ID, RT.VAL
      FROM LUSERS LU
      JOIN LEVELS L ON L.LEVEL_ID = LU.LEVEL_ID
      JOIN TASKS T ON T.TASK_ID = L.TASK_ID
      JOIN RES RT ON RT.RES_ID = T.RES_ID AND RT.LANG_CODE = 'RU'
      JOIN MODULES M ON M.MODULE_ID = T.MODULE_ID AND M.IS_ACTIVE = 0
      WHERE LU.USER_ID = :V$USER_ID
      ORDER BY 1
      INTO :V$LEVEL, :S1
    DO
    BEGIN
      S2 = NULL;
      IF(S1 = 'Личные дела сотрудников') THEN S2 = 'Сотрудники';
      IF(S1 = 'Личные дела обучающихся, воспитанников') THEN S2 = 'Учебные коллективы и обучающиеся';
      IF(S1 = 'Личные дела воспитанников') THEN S2 = 'Учебные коллективы и обучающиеся';
      IF(S1 = 'Электронные журналы') THEN S2 = 'Управление электронными журналами';
      IF(S1 = 'Структура ОООД') THEN S2 = 'Структура и документы образовательной организации';

      D = NULL;
      SELECT FIRST 1 L.LEVEL_ID
      FROM MODULES M
      JOIN TASKS T ON T.MODULE_ID = M.MODULE_ID AND T.IS_DEL = 0
      JOIN RES RT ON RT.RES_ID = T.RES_ID AND RT.LANG_CODE = 'RU' AND (UPPER(RT.VAL) = UPPER(:S1) OR UPPER(RT.VAL) = UPPER(:S2))
      JOIN LEVELS L ON L.TASK_ID = T.TASK_ID AND L.IS_DEL = 0
      WHERE M.IS_DEL = 0 AND M.IS_ACTIVE = 1
      INTO :D;

      IF(D IS NULL OR EXISTS(SELECT FIRST 1 1 FROM LUSERS WHERE USER_ID = :V$USER_ID AND LEVEL_ID = :D)) THEN
      BEGIN
        DELETE FROM LUSERS
        WHERE USER_ID = :V$USER_ID AND LEVEL_ID = :V$LEVEL;
      END
      ELSE
      BEGIN
        UPDATE LUSERS
        SET LEVEL_ID = :D
        WHERE USER_ID = :V$USER_ID AND LEVEL_ID = :V$LEVEL;
      END
    END
  END

  -- Пользователь уровня текущей ОУ, тип доступа в зависимости от реальных прав
  -- Уровень может быть понижен до 100, если в приложении стоит readonly
  IF(V$ROLE IN (1, 23)) THEN V$ACCESS = 1;
  ELSE IF(V$ROLE IN (5, 6)) THEN V$ACCESS = 2;
  ELSE V$ACCESS = 4;

  V$HAS_TEST_CHOOSE = 0;
  V$HAS_EXPERTS = 0;

  V$HAS_DO = 0;
  V$HAS_OO = 0;
  V$HAS_SPO = 0;
  V$HAS_PO = 0;
  SELECT FIRST 1 L2.OBJ_ID
  FROM LINKS L2
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$OU_ID;

  SELECT FIRST 1 1
  FROM LINKS L472
  JOIN VALL V3327 ON V3327.OBJ_ID = L472.OBJ_ID AND V3327.PARAM_ID = 3327 AND V3327.IS_DEL = 0 AND V3327.LISTVAL_ID IN (21, 3263, 3264)
  WHERE L472.PARENT_ID = :V$OU_ID AND L472.OBJ_TYPE_ID = 472 AND L472.DATE_DEL IS NULL
  INTO :V$HAS_DO;

  SELECT FIRST 1 1
  FROM LINKS L472
  JOIN VALL V3327 ON V3327.OBJ_ID = L472.OBJ_ID AND V3327.PARAM_ID = 3327 AND V3327.IS_DEL = 0 AND V3327.LISTVAL_ID IN (22, 26, 27)
  WHERE L472.PARENT_ID = :V$OU_ID AND L472.OBJ_TYPE_ID = 472 AND L472.DATE_DEL IS NULL
  INTO :V$HAS_OO;

  SELECT FIRST 1 1
  FROM LINKS L472
  JOIN VALL V3327 ON V3327.OBJ_ID = L472.OBJ_ID AND V3327.PARAM_ID = 3327 AND V3327.IS_DEL = 0 AND V3327.LISTVAL_ID IN (28, 29, 13129)
  WHERE L472.PARENT_ID = :V$OU_ID AND L472.OBJ_TYPE_ID = 472 AND L472.DATE_DEL IS NULL
  INTO :V$HAS_SPO;

  SELECT FIRST 1 1
  FROM LINKS L472
  JOIN VALL V3327 ON V3327.OBJ_ID = L472.OBJ_ID AND V3327.PARAM_ID = 3327 AND V3327.IS_DEL = 0 AND V3327.LISTVAL_ID IN (13129, 13131)
  WHERE L472.PARENT_ID = :V$OU_ID AND L472.OBJ_TYPE_ID = 472 AND L472.DATE_DEL IS NULL
  INTO :V$HAS_PO;

  -- Фиксируем активность пользователя, отсрочка блокировки
  UPDATE USERS
  SET LAST_ACCESS = CURRENT_TIMESTAMP
  WHERE USER_ID = :V$USER_ID;

  TAG_NAME = 'key_id';
  V$KEY = (SELECT GEN FROM GEN);
  VAL = V$KEY;
  SUSPEND;

  TAG_NAME = 'level';
  -- Временно считаем по уровню базы, без разделения региональных пользователей на районные
  -- 0 - регион, 1 = район, 2 - организация, -1 - суперадмин (только уровень региона)
  VAL = (3 - V$OU_LEVEL);
  IF(VAL = 0) THEN VAL = -1;
  SUSPEND;

  TAG_NAME = 'id';
  VAL = V$USER_ID;
  SUSPEND;

  TAG_NAME = 'name';
  VAL = V$USER_NAME;
  SUSPEND;

  TAG_NAME = 'ref_id';
  VAL = V$KEY;
  SUSPEND;

  TAG_NAME = 'ref_name';
  VAL = (SELECT KEY_VAL FROM KEYS WHERE KEY_CODE = 'ORGANIZATION_SHORT_NAME');
  SUSPEND;

  TAG_NAME = 'must_change_pwd';
  IF(V$IS_BLOCKED_PWD > 0 AND V$MUST_CHANGE > 0) THEN V$MUST_CHANGE = 0;
  VAL = V$MUST_CHANGE;
  SUSPEND;

  TAG_NAME = 'pwd_blocked';
  VAL = V$IS_BLOCKED_PWD;
  SUSPEND;

  TAG_NAME = 'person_id';
  VAL = V$PERSON_ID;
  SUSPEND;

  TAG_NAME = 'person_type';
  VAL = V$PERSON_TYPE;
  SUSPEND;

  -- Для сотрудников выбираем признак автозагрузки
  -- Для учеников и родителей идем не спрашивая
  TAG_NAME = 'autoload';
  VAL = NULL;
  IF(V$PERSON_TYPE = 14) THEN
  BEGIN
    SELECT FIRST 1 'app.calendar'
    FROM VALL V
    WHERE V.OBJ_ID = :V$PERSON_ID AND V.PARAM_ID = 3169 AND V.IS_DEL = 0 AND V.LISTVAL_ID = 2
    INTO :VAL;
  END
  ELSE
    VAL = 'app.calendar';
  SUSPEND;

  TAG_NAME = 'modules';
  VAL = NULL;
  SUSPEND;

  -- Список доступных приложений
  IF(V$OU_LEVEL > 1 AND V$ROLE IN (1, 4, 10, 20, 21)) THEN
  BEGIN
    TAG_NAME = 'modules:module';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'modules:module:name';
    VAL = 'app.rgnstat';
    SUSPEND;
    TAG_NAME = 'modules:module:level';
    VAL = V$ACCESS;
    SUSPEND;
  END

  IF(V$ROLE = 23) THEN
  BEGIN
    TAG_NAME = 'modules:module';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'modules:module:name';
    VAL = 'app.admin';
    SUSPEND;
    TAG_NAME = 'modules:module:level';
    VAL = '1';
    SUSPEND;
  END

  -- Статистика - тем у кого есть права к СМИР, с ролью админ, директор, специалист по кадрам
  IF(V$OU_LEVEL = 1 AND V$ROLE IN (1, 5, 6, 10, 16, 20) AND
    EXISTS(
      SELECT FIRST 1 1
      FROM LUSERS G
      WHERE G.USER_ID = :V$USER_ID AND G.LEVEL_ID IN (/* O */ 139, 536, /* C */ 468, /* D */ 199, /* U */ 469) AND G.READ_ONLY = 0
    ))
  THEN
  BEGIN
    TAG_NAME = 'modules:module';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'modules:module:name';
    VAL = 'app.bb';
    SUSPEND;
    TAG_NAME = 'modules:module:level';
    VAL = V$ACCESS;
    SUSPEND;
  END

  -- Проверяем наличие прав доступа к любому из приложений в блоке КЖ
  IF(EXISTS(
    SELECT FIRST 1 1
    FROM LUSERS G
    WHERE G.USER_ID = :V$USER_ID AND G.LEVEL_ID IN (/* O */ 46, 189, 274, 275, /* C */ 230, 249, 254, 255, /* D */ 180, /* U */ 256, /* P */ 524)
  )) THEN
  BEGIN
    V$OVERRIDE = 0;
    SELECT FIRST 1 100
    FROM LUSERS G
    WHERE G.USER_ID = :V$USER_ID AND G.LEVEL_ID IN (/* O */ 46, 189, 274, 275, /* C */ 230, 249, 254, 255, /* D */ 180, /* U */ 256, /* P */ 524) AND G.READ_ONLY = 1
    INTO :V$OVERRIDE;
    -- ПТП - кроме ДОУ
    IF(V$OU_LICENCE_TYPE <> 'D') THEN
    BEGIN
      TAG_NAME = 'modules:module';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'modules:module:name';
      VAL = 'app.ptp';
      SUSPEND;
      TAG_NAME = 'modules:module:level';
      VAL = MAXVALUE(V$ACCESS, V$OVERRIDE);
      SUSPEND;
    END
    -- Классный журнал
    TAG_NAME = 'modules:module';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'modules:module:name';
    VAL = 'app.cj';
    SUSPEND;
    TAG_NAME = 'modules:module:level';
    VAL = MAXVALUE(V$ACCESS, V$OVERRIDE);
    SUSPEND;
  END

  V$OVERRIDE = NULL;
  SELECT FIRST 1 G.READ_ONLY
  FROM LUSERS G
  WHERE G.USER_ID = :V$USER_ID AND G.LEVEL_ID IN (112, 530)
  INTO :V$OVERRIDE;
  IF(V$OVERRIDE IS NOT NULL AND (V$HAS_OO = 1 OR V$OU_LICENCE_TYPE = 'O')) THEN
  BEGIN
    TAG_NAME = 'modules:module';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'modules:module:name';
    VAL = 'app.finalmarks';
    SUSPEND;
    TAG_NAME = 'modules:module:level';
    IF(V$OVERRIDE = 1) THEN VAL = 100; ELSE VAL = V$ACCESS;
    SUSPEND;
  END
  IF(V$OVERRIDE IS NOT NULL AND (V$HAS_SPO = 1 OR V$OU_LICENCE_TYPE = 'C')) THEN
  BEGIN
    TAG_NAME = 'modules:module';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'modules:module:name';
    VAL = 'app.attmarks';
    SUSPEND;
    TAG_NAME = 'modules:module:level';
    IF(V$OVERRIDE = 1) THEN VAL = 100; ELSE VAL = V$ACCESS;
    SUSPEND;
  END

  -- Документы об образовании
  V$OVERRIDE = NULL;
  SELECT FIRST 1 G.READ_ONLY
  FROM LUSERS G
  WHERE G.USER_ID = :V$USER_ID AND G.LEVEL_ID IN (489, 490, 541)
  INTO :V$OVERRIDE;
  IF(V$OVERRIDE IS NOT NULL) THEN
  BEGIN
    TAG_NAME = 'modules:module';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'modules:module:name';
    VAL = 'app.study_docs';
    SUSPEND;
    TAG_NAME = 'modules:module:level';
    IF(V$OVERRIDE = 1) THEN VAL = 100; ELSE VAL = V$ACCESS;
    SUSPEND;
  END

  -- Предметы
  V$OVERRIDE = NULL;
  SELECT FIRST 1 G.READ_ONLY
  FROM LUSERS G
  WHERE G.USER_ID = :V$USER_ID AND G.LEVEL_ID IN (42, 114, 115, 202, 546, 229)
  INTO :V$OVERRIDE;
  IF(V$OVERRIDE IS NOT NULL) THEN
  BEGIN
    TAG_NAME = 'modules:module';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'modules:module:name';
    VAL = 'app.subjects';
    SUSPEND;
    TAG_NAME = 'modules:module:level';
    IF(V$OVERRIDE = 1) THEN VAL = 100; ELSE VAL = V$ACCESS;
    SUSPEND;
  END

  -- Кадровый учет
  V$OVERRIDE = NULL;
  SELECT FIRST 1 G.READ_ONLY
  FROM LUSERS G
  WHERE G.USER_ID = :V$USER_ID AND G.LEVEL_ID IN (548, 22, 24, 26, 239)
  INTO :V$OVERRIDE;
  IF(V$OVERRIDE IS NOT NULL) THEN
  BEGIN
    TAG_NAME = 'modules:module';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'modules:module:name';
    VAL = 'app.joblist';
    SUSPEND;
    TAG_NAME = 'modules:module:level';
    IF(V$OVERRIDE = 1) THEN VAL = 100; ELSE VAL = V$ACCESS;
    SUSPEND;
  END

  -- Табели учета рабочего времени - есть доступ у руководства и кадровика, у тех у кого есть доступ к личным делам сотрудников, и назначенных ответственных к табелям
  -- у завучей если не стоит доступ к личным делам сотрудников понижаем уровень до RO
  -- Доступ к приложению Личные дела ?
  V$OVERRIDE = NULL;
  SELECT FIRST 1 G.READ_ONLY
  FROM LUSERS G
  WHERE G.USER_ID = :V$USER_ID AND G.LEVEL_ID IN (534)
  INTO :V$OVERRIDE;

  -- Доступ для назначенных ответственных за табели ?
  V$OVERRIDE2 = NULL;
  SELECT FIRST 1 1
  FROM LINKS L518
  LEFT JOIN VALR V3548 ON V3548.OBJ_ID = L518.OBJ_ID AND V3548.PARAM_ID = 3548 AND V3548.IS_DEL = 0
  LEFT JOIN VALR V3549 ON V3549.OBJ_ID = L518.OBJ_ID AND V3549.PARAM_ID = 3549 AND V3549.IS_DEL = 0
  WHERE L518.PARENT_TYPE_ID IN (2, 211) AND L518.OBJ_TYPE_ID = 518 AND L518.DATE_DEL IS NULL AND (V3548.VAL = :V$PERSON_ID OR V3549.VAL = :V$PERSON_ID)
  INTO :V$OVERRIDE2;

  /*IF(V$OU_LEVEL = 1 AND (V$ROLE IN (1, 5, 6, 10) OR V$OVERRIDE IS NOT NULL OR V$OVERRIDE2 IS NOT NULL)) THEN
  BEGIN
    TAG_NAME = 'modules:module';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'modules:module:name';
    VAL = 'app.worktables';
    SUSPEND;
    TAG_NAME = 'modules:module:level';
    IF(V$OVERRIDE2 = 1 OR V$ROLE IN (1, 5, 10) OR (V$ROLE = 6 AND V$OVERRIDE = 0)) THEN VAL = 1; -- полный доступ
    ELSE VAL = 100; -- доступ RO у кого есть доступ к личным делам, и у завучей если стоит RO
    SUSPEND;
  END*/

  -- Действующие ученики и сотрудники имеют доступ для прохождения тестирования
  -- При наличии проставленного доступа в приложении тестирование/анкетирование
  IF((EXISTS(
    SELECT FIRST 1 1 FROM LINKS L14 WHERE L14.PARENT_TYPE_ID IN (2, 211) AND L14.OBJ_ID = :V$PERSON_ID AND L14.DATE_DEL IS NULL
  ) OR
  EXISTS(
    SELECT FIRST 1 1 FROM LINKS L10 WHERE L10.PARENT_TYPE_ID IN (9, 125, 187) AND L10.OBJ_ID = :V$PERSON_ID AND L10.DATE_DEL IS NULL
  )) AND EXISTS(
    SELECT FIRST 1 1 FROM LUSERS G WHERE G.USER_ID = :V$USER_ID AND G.LEVEL_ID IN (138, 154, 155, 208)
  )) THEN
  BEGIN
    TAG_NAME = 'modules:module';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'modules:module:name';
    VAL = 'app.test_process';
    SUSPEND;
    TAG_NAME = 'modules:module:level';
    VAL = V$ACCESS;
    SUSPEND;
  END

  -- Знак:Кодификатор, открываем доступ к приложению Кодификатор и Структуры КИМ (последний код - Колледжи)
  IF(EXISTS(
    SELECT FIRST 1 1 FROM LUSERS G WHERE G.USER_ID = :V$USER_ID AND G.LEVEL_ID IN (132, 140, 146, 206)
  ) AND V$OU_LICENCE_TYPE IN ('O', 'S')) THEN
  BEGIN
    TAG_NAME = 'modules:module';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'modules:module:name';
    VAL = 'app.test_coding';
    SUSPEND;
    TAG_NAME = 'modules:module:level';
    VAL = V$ACCESS;
    SUSPEND;
    --
    TAG_NAME = 'modules:module';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'modules:module:name';
    VAL = 'app.test_structures';
    SUSPEND;
    TAG_NAME = 'modules:module:level';
    VAL = V$ACCESS;
    SUSPEND;
    --
    TAG_NAME = 'modules:module';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'modules:module:name';
    VAL = 'app.test_verify';
    SUSPEND;
    TAG_NAME = 'modules:module:level';
    VAL = V$ACCESS;
    SUSPEND;
  END

  -- Знак:Тестовые задания
  IF(EXISTS(
    SELECT FIRST 1 1 FROM LUSERS G WHERE G.USER_ID = :V$USER_ID AND G.LEVEL_ID IN (133, 141, 147, 209)
  ) AND V$OU_LICENCE_TYPE IN ('O', 'S')) THEN
  BEGIN
    TAG_NAME = 'modules:module';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'modules:module:name';
    VAL = 'app.test_questions';
    SUSPEND;
    TAG_NAME = 'modules:module:level';
    VAL = V$ACCESS;
    SUSPEND;
    --
    TAG_NAME = 'modules:module';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'modules:module:name';
    VAL = 'app.test_variants';
    SUSPEND;
    TAG_NAME = 'modules:module:level';
    VAL = V$ACCESS;
    SUSPEND;
    --
    TAG_NAME = 'modules:module';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'modules:module:name';
    VAL = 'app.test_scan';
    SUSPEND;
    TAG_NAME = 'modules:module:level';
    VAL = V$ACCESS;
    SUSPEND;
  END

  -- Знак:Тесты
  IF(EXISTS(
      SELECT FIRST 1 1 FROM LUSERS G WHERE G.USER_ID = :V$USER_ID AND G.LEVEL_ID IN (134, 142, 148, 210)
  ) AND V$OU_LICENCE_TYPE IN ('O', 'S')) THEN
  BEGIN
    V$HAS_TEST_CHOOSE = 1;
    --
    TAG_NAME = 'modules:module';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'modules:module:name';
    VAL = 'app.test_plan';
    SUSPEND;
    TAG_NAME = 'modules:module:level';
    VAL = V$ACCESS;
    SUSPEND;
    --
    TAG_NAME = 'modules:module';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'modules:module:name';
    VAL = 'app.test_choose';
    SUSPEND;
    TAG_NAME = 'modules:module:level';
    VAL = V$ACCESS;
    SUSPEND;    
    --
    TAG_NAME = 'modules:module';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'modules:module:name';
    VAL = 'app.test_mon';
    SUSPEND;
    TAG_NAME = 'modules:module:level';
    VAL = V$ACCESS;
    SUSPEND;
    --
    TAG_NAME = 'modules:module';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'modules:module:name';
    VAL = 'app.test_print';
    SUSPEND;
    TAG_NAME = 'modules:module:level';
    VAL = V$ACCESS;
    SUSPEND;
  END
  -- Добавляем выдачу назначения на тестирования для классного руководителя (олимпиады)
  -- а также для завуча
  -- Кроме ДОУ
  IF(V$OU_LICENCE_TYPE <> 'D' AND V$HAS_TEST_CHOOSE = 0 AND V$ROLE IN (1, 5, 6, 8) AND V$OU_LEVEL = 1) THEN
  BEGIN
    TAG_NAME = 'modules:module';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'modules:module:name';
    VAL = 'app.test_choose';
    SUSPEND;
    TAG_NAME = 'modules:module:level';
    VAL = V$ACCESS;
    SUSPEND;
  END
  -- Печать бланков для всех учителей-предметников, классных руководителей и руководства
  IF(V$OU_LICENCE_TYPE IN ('O', 'S') AND V$HAS_TEST_CHOOSE = 0 AND V$ROLE IN (5, 6, 8, 9) AND V$OU_LEVEL = 1) THEN
  BEGIN
    TAG_NAME = 'modules:module';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'modules:module:name';
    VAL = 'app.test_review';
    SUSPEND;
    TAG_NAME = 'modules:module:level';
    VAL = V$ACCESS;
    SUSPEND;
  END

  -- Знак:Результаты
  IF(EXISTS(
    SELECT FIRST 1 1 FROM LUSERS G WHERE G.USER_ID = :V$USER_ID AND G.LEVEL_ID IN (136, 144, 150, 207)
  ) AND V$OU_LICENCE_TYPE IN ('O', 'S')) THEN
  BEGIN
    -- Анализ
    TAG_NAME = 'modules:module';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'modules:module:name';
    VAL = 'app.test_review';
    SUSPEND;
    TAG_NAME = 'modules:module:level';
    VAL = V$ACCESS;
    SUSPEND;
  END

  -- Доступ к экспертам даем пользователю, имеющему доступ к кодификаторам, и одновременно к личным делам сотрудников
  IF(EXISTS(
    SELECT FIRST 1 1 FROM LUSERS G WHERE G.USER_ID = :V$USER_ID AND G.LEVEL_ID IN (134, 142, 148, 210)
  ) AND
  EXISTS(
    SELECT FIRST 1 1 FROM LUSERS G WHERE G.USER_ID = :V$USER_ID AND G.LEVEL_ID IN (48, 27, 29, 171, 222)
  ) AND V$OU_LICENCE_TYPE IN ('O', 'S')) THEN
  BEGIN
    V$HAS_EXPERTS = 1;
    TAG_NAME = 'modules:module';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'modules:module:name';
    VAL = 'app.test_experts';
    SUSPEND;
    TAG_NAME = 'modules:module:level';
    VAL = V$ACCESS;
    SUSPEND;
  END

  -- Проверка результатов только пользователям, внесенным в число экспертов
  IF(EXISTS(
    SELECT FIRST 1 1 FROM UT_EXPERTS E WHERE E.TEACHER_ID = :V$PERSON_ID AND E.DATE_DEL IS NULL AND E.IS_ACTIVE = 1
  )) THEN
  BEGIN
    -- Проверка экспертом
    TAG_NAME = 'modules:module';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'modules:module:name';
    VAL = 'app.test_check';
    SUSPEND;
    TAG_NAME = 'modules:module:level';
    VAL = V$ACCESS;
    SUSPEND;
  END

  -- Если пользователь является экспертом, но не имеет явного доступа к списку экспертов - все равно показываем с доступом рядового сотрудника
  IF(V$HAS_EXPERTS = 0 AND EXISTS(
    SELECT FIRST 1 1
    FROM UT_EXPERTS E
    WHERE E.DATE_DEL IS NULL AND E.TEACHER_ID IS NULL AND E.IS_ACTIVE = 1 AND
      ((E.USER_NAME = :I$NAME AND (E.PWD = :I$PASSWORD OR E.PWD = :I$PASSWORD2)) OR E.EXPERT_ID = :V$EXPERT_ID)
  )) THEN
  BEGIN
    TAG_NAME = 'modules:module';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'modules:module:name';
    VAL = 'app.test_experts';
    SUSPEND;
    TAG_NAME = 'modules:module:level';
    VAL = 4;
    SUSPEND;
  END

  FOR
    SELECT L.LEVEL_ID, IIF(LU.READ_ONLY = 0, 0, 100)
    FROM LUSERS LU
    JOIN LEVELS L ON L.LEVEL_ID = LU.LEVEL_ID AND L.IS_DEL = 0 AND L.LEVEL_ID NOT IN (42, 114, 115, 202, 489, 490, 478, /**/ 55, 158, 168, /**/ 474, 482, 211, /**/ 541, 546, 548, 24, 551)
    JOIN TASKS T ON T.TASK_ID = L.TASK_ID AND T.IS_DEL = 0
    JOIN MODULES M ON M.MODULE_ID = T.MODULE_ID AND M.IS_DEL = 0 AND M.MODULE_CODE = 'PARAGRAF' and M.IS_ACTIVE = 1
    WHERE LU.USER_ID = :V$USER_ID
    INTO :V$LEVEL, :V$OVERRIDE
  DO
  BEGIN
    -- Вместо электронных журналов отдаем app.cj_manage
    IF(V$LEVEL IN (483, 517, 484, 485, 486, 547)) THEN
    BEGIN
      TAG_NAME = 'modules:module';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'modules:module:name';
      VAL = 'app.cj_manage';
      SUSPEND;
      TAG_NAME = 'modules:module:level';
      VAL = MAXVALUE(V$ACCESS, V$OVERRIDE);
      SUSPEND;
    END
    ELSE
    BEGIN
      TAG_NAME = 'modules:module';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'modules:module:name';
      VAL = 'app.odb(' || V$LEVEL || ')';
      SUSPEND;
      TAG_NAME = 'modules:module:level';
      VAL = MAXVALUE(V$ACCESS, V$OVERRIDE);
      SUSPEND;
    END
  END

  -- Отдаем Мои данные как ссылку на личные дела, но с режимом только чтение - для учителей
  -- !!! выдача приложения Мои данные временно отключена до решения проблем с повторной авторизацией
  -- Также добавляем app.att с обычным уровнем доступа
  -- Также добавляем app.portfolio с обычным уровнем доступа
  -- не показываем их если роль = администратор безопасности
  IF(V$OU_LEVEL = 1 AND V$PERSON_TYPE = 14 AND V$ROLE <> 23) THEN
  BEGIN
    /*TAG_NAME = 'modules:module';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'modules:module:name';
    IF(V$OU_LICENCE_TYPE = 'O') THEN VAL = 'app.odb(100048)';
    SUSPEND;
    TAG_NAME = 'modules:module:level';
    VAL = 100;
    SUSPEND;*/

    TAG_NAME = 'modules:module';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'modules:module:name';
    VAL = 'app.att';
    SUSPEND;
    TAG_NAME = 'modules:module:level';
    VAL = 4;
    SUSPEND;

    TAG_NAME = 'modules:module';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'modules:module:name';
    VAL = 'app.portfolio';
    SUSPEND;
    TAG_NAME = 'modules:module:level';
    VAL = 4;
    SUSPEND;
  END

  -- Отдаем Моя учеба для учеников
  -- Для студентов СПО также отдаем страницу с персональными данными
  IF(V$OU_LEVEL = 1 AND V$PERSON_TYPE = 10) THEN
  BEGIN
    TAG_NAME = 'modules:module';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'modules:module:name';
    VAL = 'app.portfolio';
    SUSPEND;
    TAG_NAME = 'modules:module:level';
    VAL = 4;
    SUSPEND;

    IF(EXISTS(
      SELECT FIRST 1 1
      FROM PERSON_MOVEMENTS M
      WHERE M.DATE_DEL IS NULL AND M.PERSON_ID = :V$PERSON_ID AND M.GROUP_TYPE_ID IN (9, 187, 289) AND M.LEVEL_ID = 29
    )) THEN
    BEGIN
      TAG_NAME = 'modules:module';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'modules:module:name';
      VAL = 'app.pd';
      SUSPEND;
      TAG_NAME = 'modules:module:level';
      VAL = 4;
      SUSPEND;
    END
  END

  -- Доступ к замещениям - роль завуч либо доступ к личным делам сотрудников на запись
  -- Добавлено: Специалист по кадрам, специалист по работе с обучающимися
  IF(V$ROLE IN (1, 5, 6, 10, 20) OR
  EXISTS(
    SELECT FIRST 1 1 FROM LUSERS G WHERE G.USER_ID = :V$USER_ID AND G.LEVEL_ID IN (48, 27, 29, 171, 222) AND G.READ_ONLY = 0
  )) THEN
  BEGIN
    V$HAS_EXPERTS = 1;
    TAG_NAME = 'modules:module';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'modules:module:name';
    VAL = 'app.subst';
    SUSPEND;
    TAG_NAME = 'modules:module:level';
    IF(V$ROLE = 1) THEN VAL = 1; -- админ
    ELSE IF(V$ROLE IN (5, 6)) THEN VAL = 2; -- руководитель
    ELSE VAL = 3; -- ведущий специалист
    SUSPEND;
  END

  -- Центр сообщений - всегда доступен
  TAG_NAME = 'modules:module';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'modules:module:name';
  VAL = 'app.messages';
  SUSPEND;
  TAG_NAME = 'modules:module:level';
  VAL = V$ACCESS;
  SUSPEND;

  -- Мой календарь - всегда полный доступ
  TAG_NAME = 'modules:module';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'modules:module:name';
  VAL = 'app.calendar';
  SUSPEND;
  TAG_NAME = 'modules:module:level';
  VAL = 4;
  SUSPEND;

  -- Мое расписание - всегда полный доступ
  TAG_NAME = 'modules:module';
  VAL = NULL;
  SUSPEND;
  TAG_NAME = 'modules:module:name';
  VAL = 'app.schedule';
  SUSPEND;
  TAG_NAME = 'modules:module:level';
  VAL = 4;
  SUSPEND;

  -- Справочник КЭС/ПЭС/ДЕ доступен админам и руководителям
  IF(V$ROLE IN (1, 5, 6)) THEN
  BEGIN
    TAG_NAME = 'modules:module';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'modules:module:name';
    VAL = 'app.cec';
    SUSPEND;
    TAG_NAME = 'modules:module:level';
    VAL = V$ACCESS;
    SUSPEND;
  END

  -- Новый библиографом - по наличию доступа в старый библиограф
  -- 549 код не нужен, прописываем старое приложение
  V$OVERRIDE = NULL;
  SELECT FIRST 1 G.READ_ONLY
  FROM LUSERS G
  WHERE G.USER_ID = :V$USER_ID AND G.LEVEL_ID IN (90)
  INTO :V$OVERRIDE;
  IF(V$OVERRIDE IS NOT NULL) THEN
  BEGIN
    TAG_NAME = 'modules:module';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'modules:module:name';
    VAL = 'app.library';
    SUSPEND;
    TAG_NAME = 'modules:module:level';
    IF(V$OVERRIDE = 1) THEN VAL = 100; ELSE VAL = V$ACCESS;
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE VERIFY_WORKERS (
    I$OBJ_ID BIGINT)
RETURNS (
    LINK_ID BIGINT,
    OBJECT_ID BIGINT,
    PARENT_ID BIGINT,
    NAME_TASK VARCHAR(1000),
    ERROR_NAME VARCHAR(1000),
    PARAMS_NAME VARCHAR(1000),
    ERROR_TEXT VARCHAR(1000),
    ERROR_TYPE SMALLINT)
AS
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$PARAM_ID BIGINT;
DECLARE VARIABLE V$TEMP BIGINT;
DECLARE VARIABLE V$VALI INTEGER;
DECLARE VARIABLE V$FIO VARCHAR(1000);
DECLARE VARIABLE V$STAVKA NUMERIC(10,2);
DECLARE VARIABLE V$TEACHER SMALLINT;
DECLARE VARIABLE V$MANAGER SMALLINT;
DECLARE VARIABLE V$ACTIVE SMALLINT;
DECLARE VARIABLE V$VALS VARCHAR(1000);
DECLARE VARIABLE S VARCHAR(1000);
DECLARE VARIABLE V$OU_LICENCE_TYPE CHAR(1);
DECLARE VARIABLE V$TYPE_ID BIGINT;
DECLARE VARIABLE V$PT BIGINT;
DECLARE VARIABLE V$PREV_OBJ BIGINT;
DECLARE VARIABLE V$PREV_TYPE BIGINT;
DECLARE VARIABLE V$BIRTH_DATE DATE;
DECLARE VARIABLE V$DATE DATE;
DECLARE VARIABLE V$G BIGINT;
BEGIN
    SELECT STATUS FROM OU_LICENCE_TYPE INTO :V$OU_LICENCE_TYPE;

    NAME_TASK = 'Личные дела сотрудников';
    ERROR_TYPE = 1;

    -- 1 = автокоррекция/hint, 2 = warning, 3 = error

    -- Дубли по ФИО+ДР и СНИЛС, предполагается что полных тезок в одной ОУ нет
    -- проверяем в обязательном порядке как действующих, так и уволенных
    ERROR_TYPE = 0;
    V$PREV_OBJ = 0;
    S = '';
    FOR
      SELECT DISTINCT P.OBJ_ID, P.PARENT_TYPE_ID, P.HH
      FROM (
        -- действующие
        SELECT L14.OBJ_ID, L14.PARENT_TYPE_ID, F.SVAL || ' ' || I.SVAL || COALESCE(' ' || O.SVAL, '') || ' ' || CAST(D.VAL AS VARCHAR(20)) HH
        FROM LINKS L14
        JOIN VALS F ON F.OBJ_ID = L14.OBJ_ID AND F.PARAM_ID = 59 AND F.IS_DEL = 0
        JOIN VALS I ON I.OBJ_ID = L14.OBJ_ID AND I.PARAM_ID = 60 AND I.IS_DEL = 0
        LEFT JOIN VALS O ON O.OBJ_ID = L14.OBJ_ID AND O.PARAM_ID = 61 AND O.IS_DEL = 0
        JOIN VALD D ON D.OBJ_ID = L14.OBJ_ID AND D.PARAM_ID = 241 AND D.IS_DEL = 0
        WHERE L14.PARENT_ID = :I$OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
        -- уволенные
        UNION
        SELECT L14.OBJ_ID, L14.PARENT_TYPE_ID, F.SVAL || ' ' || I.SVAL || COALESCE(' ' || O.SVAL, '') || ' ' || CAST(D.VAL AS VARCHAR(20)) HH
        FROM LINKS L84
        JOIN LINKS L14 ON L14.PARENT_ID = L84.OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
        JOIN VALS F ON F.OBJ_ID = L14.OBJ_ID AND F.PARAM_ID = 59 AND F.IS_DEL = 0
        JOIN VALS I ON I.OBJ_ID = L14.OBJ_ID AND I.PARAM_ID = 60 AND I.IS_DEL = 0
        LEFT JOIN VALS O ON O.OBJ_ID = L14.OBJ_ID AND O.PARAM_ID = 61 AND O.IS_DEL = 0
        JOIN VALD D ON D.OBJ_ID = L14.OBJ_ID AND D.PARAM_ID = 241 AND D.IS_DEL = 0
        WHERE L84.PARENT_ID = :I$OBJ_ID AND L84.OBJ_TYPE_ID = 84 AND L84.DATE_DEL IS NULL
      ) P
      ORDER BY 3, IIF(P.PARENT_TYPE_ID = 84, 9999, P.PARENT_TYPE_ID)
      INTO :V$OBJ_ID, :V$PT, :V$FIO
    DO
    BEGIN
      -- Повтор ФИО с другим ID ? Сначала идут записи в ОУ, потом уволенные
      IF(S = V$FIO AND V$OBJ_ID <> V$PREV_OBJ AND V$PREV_OBJ > 0) THEN
      BEGIN
        IF(OBJECT_ID IS NULL) THEN
        BEGIN
          OBJECT_ID = V$OBJ_ID;
          SELECT FIRST 1 LPG.LINK_ID, LPG.PARENT_ID
          FROM LINKS LPG
          WHERE LPG.OBJ_ID = :OBJECT_ID AND LPG.PARENT_TYPE_ID IN (2, 211, 84) AND LPG.DATE_DEL IS NULL
          ORDER BY IIF(LPG.PARENT_TYPE_ID = 84, 9999, LPG.PARENT_TYPE_ID)
          INTO :LINK_ID, :PARENT_ID;

          ERROR_TEXT = 'В списке сотрудников не должно быть повторяющихся записей. Найдено 2 или более записи: ' || :V$FIO;
          ERROR_NAME = 'В списке сотрудников не должно быть повторяющихся записей';
          PARAMS_NAME = 'Дубли';
          -- error или warning понимаем по первым двум записям в выдаче
          -- если они обе действующие - будет error, если нет - warning
          ERROR_TYPE = IIF(V$PREV_TYPE <> 84 AND V$PT <> 84, 3, 2);
        END
      END
      -- Новая персона. Флэшим старую, если был конфликт
      ELSE IF(S <> V$FIO) THEN
      BEGIN
        IF(ERROR_TYPE > 0) THEN SUSPEND;
        ERROR_TYPE = 0;
        OBJECT_ID = NULL;
      END

      S = V$FIO;
      V$PREV_OBJ = V$OBJ_ID;
      V$PREV_TYPE = V$PT;
    END

    -- Атрибуты - действующие сотрудники
    FOR
      SELECT L14.OBJ_ID, L14.LINK_ID, L14.PARENT_ID, C.C1, V241.VAL, V239.LISTVAL_ID, 1
      FROM LINKS L14
      LEFT JOIN BUILD_REP_FIO(L14.OBJ_ID, 59, 60, 61, 0) C ON 1 = 1
      LEFT JOIN VALD V241 ON V241.OBJ_ID = L14.OBJ_ID AND V241.PARAM_ID = 241 AND V241.IS_DEL = 0
      LEFT JOIN VALL V239 ON V239.OBJ_ID = L14.OBJ_ID AND V239.PARAM_ID = 239 AND V239.IS_DEL = 0
      WHERE L14.PARENT_ID = :I$OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
      INTO :OBJECT_ID, :LINK_ID, :PARENT_ID, :V$FIO, :V$BIRTH_DATE, :V$G, :V$ACTIVE
    DO
    BEGIN
      -- Непосредственно сам сотрудник
      FOR
        SELECT ERROR_TYPE, ERROR_TEXT, ERROR_NAME, PARAMS_NAME
        FROM VERIFY_OBJECT_FIELDS(:OBJECT_ID, 14, 'сотрудника', :V$FIO)
        INTO :ERROR_TYPE, :ERROR_TEXT, :ERROR_NAME, :PARAMS_NAME
      DO
      BEGIN
        SUSPEND;
      END

      -- Пустые объекты больше не удаляем - если их нет, это будет ошибка. Иначе будет дурить инкрементальная выгрузка
      -- Обязательно наличие действующего документа
      IF(NOT EXISTS(
        SELECT FIRST 1 1
        FROM LINKS L79
        JOIN VALL V441 ON V441.OBJ_ID = L79.OBJ_ID AND V441.PARAM_ID = 441 AND V441.IS_DEL = 0 -- тип
        JOIN VALS V559 ON V559.OBJ_ID = L79.OBJ_ID AND V559.PARAM_ID = 559 AND V559.IS_DEL = 0 -- номер
        JOIN VALD V560 ON V560.OBJ_ID = L79.OBJ_ID AND V560.PARAM_ID = 560 AND V560.IS_DEL = 0 -- дата
        JOIN VALL V614 ON V614.OBJ_ID = L79.OBJ_ID AND V614.PARAM_ID = 614 AND V614.IS_DEL = 0 AND V614.LISTVAL_ID IN (1982, 1984)
        WHERE L79.PARENT_ID = :OBJECT_ID AND L79.OBJ_TYPE_ID = 79 AND L79.DATE_DEL IS NULL
      )) THEN
      BEGIN
        ERROR_TEXT = 'Для сотрудника «' || V$FIO || '» не введены данные документа, удостоверяющего личность';
        ERROR_NAME = 'Для сотрудника не введены данные документа, удостоверяющего личность';
        PARAMS_NAME = 'Документ удостоверяющий личность';
        ERROR_TYPE = 2;
        SUSPEND;
      END

      -- Идентифицирующие документы с датой выдачи ранее даты рождения или в будущем
      IF(EXISTS(
        SELECT FIRST 1 1
        FROM LINKS L79
        JOIN VALD V560 ON V560.OBJ_ID = L79.OBJ_ID AND V560.PARAM_ID = 560 AND V560.IS_DEL = 0 -- дата
          AND (V560.VAL < :V$BIRTH_DATE OR V560.VAL > CURRENT_DATE)
        WHERE L79.PARENT_ID = :OBJECT_ID AND L79.OBJ_TYPE_ID = 79 AND L79.DATE_DEL IS NULL
      )) THEN
      BEGIN
        ERROR_TEXT = 'Для сотрудника «' || V$FIO || '» дата выдачи документа, удостоверяющего личность, за пределами допустимого диапазона';
        ERROR_NAME = 'Для сотрудника дата выдачи документа, удостоверяющего личность, за пределами допустимого диапазона';
        PARAMS_NAME = 'Документ удостоверяющий личность';
        ERROR_TYPE = 3;
        SUSPEND;
      END

      -- Прочие документы с датой выдачи ранее даты рождения или в будущем
      IF(EXISTS(
        SELECT FIRST 1 1
        FROM LINKS L12
        JOIN VALD V572 ON V572.OBJ_ID = L12.OBJ_ID AND V572.PARAM_ID = 572 AND V572.IS_DEL = 0 -- дата
          AND (V572.VAL < :V$BIRTH_DATE OR V572.VAL > CURRENT_DATE)
        WHERE L12.PARENT_ID = :OBJECT_ID AND L12.OBJ_TYPE_ID = 12 AND L12.DATE_DEL IS NULL
      )) THEN
      BEGIN
        ERROR_TEXT = 'Для сотрудника «' || V$FIO || '» дата выдачи документа (свидетельства, удостоверения), за пределами допустимого диапазона';
        ERROR_NAME = 'Для сотрудника дата выдачи документа (свидетельства, удостоверения), за пределами допустимого диапазона';
        PARAMS_NAME = 'Документ (свидетельство, удостоверение)';
        ERROR_TYPE = 3;
        SUSPEND;
      END

      -- Документы об образовании с датой выдачи ранее даты рождения или в будущем
      IF(EXISTS(
        SELECT FIRST 1 1
        FROM LINKS L11
        JOIN VALD V566 ON V566.OBJ_ID = L11.OBJ_ID AND V566.PARAM_ID = 566 AND V566.IS_DEL = 0 -- дата
          AND (V566.VAL < :V$BIRTH_DATE OR V566.VAL > CURRENT_DATE)
        WHERE L11.PARENT_ID = :OBJECT_ID AND L11.OBJ_TYPE_ID = 11 AND L11.DATE_DEL IS NULL
      )) THEN
      BEGIN
        ERROR_TEXT = 'Для сотрудника «' || V$FIO || '» дата выдачи документа об образовании, за пределами допустимого диапазона';
        ERROR_NAME = 'Для сотрудника дата выдачи документа об образовании, за пределами допустимого диапазона';
        PARAMS_NAME = 'Документ об образовании';
        ERROR_TYPE = 3;
        SUSPEND;
      END

      -- Записи стажа вне положенных дат
      -- Обязательно проверяем тип записи - были древние записи в которых типа еще не было, они не видно, но содержат местами косяки
      V$DATE = NULL;
      SELECT FIRST 1 IIF(V466.VAL < :V$BIRTH_DATE OR V466.VAL > CURRENT_DATE, V466.VAL, V467.VAL)
      FROM LINKS L85
      JOIN VALD V465 ON V465.OBJ_ID = L85.OBJ_ID AND V465.PARAM_ID = 465 AND V465.IS_DEL = 0 -- тип записи стажа
      JOIN VALD V466 ON V466.OBJ_ID = L85.OBJ_ID AND V466.PARAM_ID = 466 AND V466.IS_DEL = 0 -- дата начала
      LEFT JOIN VALD V467 ON V467.OBJ_ID = L85.OBJ_ID AND V467.PARAM_ID = 467 AND V467.IS_DEL = 0 -- дата окончания
      WHERE L85.PARENT_ID = :OBJECT_ID AND L85.OBJ_TYPE_ID = 85 AND L85.DATE_DEL IS NULL
        AND (
          (V466.VAL < :V$BIRTH_DATE OR V466.VAL > CURRENT_DATE) OR
          (V466.VAL > V467.VAL OR V467.VAL < :V$BIRTH_DATE OR V467.VAL > CURRENT_DATE)
        )
      INTO :V$DATE;

      IF(V$DATE IS NOT NULL) THEN
      BEGIN
        ERROR_TEXT = 'Для сотрудника «' || V$FIO || '» дата записи стажа ' || V$DATE || ' за пределами допустимого диапазона';
        ERROR_NAME = 'Для сотрудника дата записи стажа за пределами допустимого диапазона';
        PARAMS_NAME = 'Запись стажа';
        ERROR_TYPE = 3;
        SUSPEND;
      END

      -- Не указан пол
      IF(V$G IS NULL) THEN BEGIN
        ERROR_TEXT = 'Для сотрудника «' || V$FIO || '» не указан пол';
        ERROR_NAME = 'Для сотрудника не указан пол';
        PARAMS_NAME = 'Контролируемые поля';
        ERROR_TYPE = 3;
        SUSPEND;
      END

      SELECT X FROM IS_TEACHER(:OBJECT_ID) INTO :V$TEACHER;
      SELECT X FROM IS_MANAGER(:OBJECT_ID) INTO :V$MANAGER;

      -- Заполнение полей в подчиненных объектах, группируем по типам
      FOR
        SELECT L.OBJ_ID, L.OBJ_TYPE_ID, R.VAL
        FROM LINKS L
        JOIN TYPES T ON T.TYPE_ID = L.OBJ_ID
        JOIN RES R ON R.RES_ID = T.RES_ID AND R.LANG_CODE = 'RU'
        WHERE L.PARENT_ID = :OBJECT_ID AND L.DATE_DEL IS NULL
          AND L.OBJ_TYPE_ID IN (79, 11, 12, 15, 79, 31, 32, 33, 34, 35, 36, 37, 39, 40, 41, 42, 43, 44, 100, 101, 156, 376, 395, 397, 458)
        ORDER BY T.SORT_ORDER
        INTO :V$OBJ_ID, :V$TYPE_ID, :S
      DO
      BEGIN
        FOR
          SELECT ERROR_TYPE, ERROR_TEXT, ERROR_NAME, PARAMS_NAME
          FROM VERIFY_OBJECT_FIELDS(:V$OBJ_ID, :V$TYPE_ID, 'сотрудника', :V$FIO)
          INTO :ERROR_TYPE, :ERROR_TEXT, :ERROR_NAME, :PARAMS_NAME
        DO
        BEGIN
          -- Название параметра заменяем на тип объекта
          PARAMS_NAME = S;
          SUSPEND;
        END

        -- Отдельно надо проверить серию документа для случая, когда она обязательна
        -- !!! дописать валидатор для номера документа

      END

      SELECT COUNT(VLL.LISTVAL_ID)
      FROM LINKS L15
      JOIN VALL VLL ON VLL.OBJ_ID = L15.OBJ_ID AND VLL.PARAM_ID = 72 AND VLL.IS_DEL = 0 AND VLL.LISTVAL_ID = 934
      LEFT JOIN VALD V74 ON V74.PARAM_ID = 74 AND V74.OBJ_ID = L15.OBJ_ID AND V74.IS_DEL = 0
      WHERE L15.OBJ_TYPE_ID = 15 AND L15.PARENT_ID = :OBJECT_ID AND L15.DATE_DEL IS NULL AND V74.VAL IS NULL
      INTO :V$TEMP;

      IF (V$TEMP = 0 OR V$TEMP > 1) THEN
      BEGIN
        ERROR_TEXT = 'Сотрудник «' || V$FIO || '» занимает несколько основных должностей или основная отсутствует';
        ERROR_NAME = 'Сотрудник занимает несколько основных должностей или основная отсутствует';
        PARAMS_NAME = 'Должность основная или дополнительная';
        ERROR_TYPE = 3;
        SUSPEND;
      END

      IF(NOT EXISTS(
        SELECT FIRST 1 1
        FROM VALL V274
        WHERE V274.OBJ_ID = :OBJECT_ID AND V274.PARAM_ID = 274 AND V274.IS_DEL = 0
      )) THEN
      BEGIN
        ERROR_TEXT = 'Сотрудник «' || V$FIO || '» - не заполнен статус';
        ERROR_NAME = 'Сотрудник - не заполнен статус';
        PARAMS_NAME = 'Статус сотрудника';
        ERROR_TYPE = 3;
        SUSPEND;
      END

      FOR
        SELECT SUM(VF.VAL), VR.VAL
        FROM LINKS L15
        JOIN VALF VF ON VF.OBJ_ID = L15.OBJ_ID AND VF.PARAM_ID = 71 AND VF.IS_DEL = 0
        JOIN VALR VR ON VR.OBJ_ID = L15.OBJ_ID AND VR.PARAM_ID = 69 AND VR.IS_DEL = 0
        LEFT JOIN VALD VD74 ON VD74.OBJ_ID = L15.OBJ_ID AND VD74.PARAM_ID = 74 AND VD74.IS_DEL = 0
        LEFT JOIN VALD VD456 ON VD456.OBJ_ID = L15.OBJ_ID AND VD456.PARAM_ID = 456 AND VD456.IS_DEL = 0
        WHERE L15.OBJ_TYPE_ID = 15 AND L15.PARENT_ID = :OBJECT_ID AND L15.DATE_DEL IS NULL AND VD74.OBJ_ID IS NULL
          AND VD456.OBJ_ID IS NULL
        GROUP BY 2
        HAVING SUM(VF.VAL) > 2
        INTO :V$STAVKA, :V$OBJ_ID
      DO
      BEGIN
        SELECT CAPTION
        FROM OBJECT_CAPTION_GET(:V$OBJ_ID)
        INTO :V$VALS;

        ERROR_TEXT = 'Сотрудник «' || V$FIO || '» имеет ' || V$STAVKA || ' ставки по должности ' || V$VALS;
        ERROR_NAME = 'Сотрудник имеет более двух ставок по должности';
        PARAMS_NAME = 'Количество занимаемых ставок';
        -- #2020 - только для колледжей
        IF (V$OU_LICENCE_TYPE = 'C') THEN
          ERROR_TYPE = 2;
        ELSE
          ERROR_TYPE = 3;
        SUSPEND;
      END

      -- Дата вступления в должность - переделано через DO_CHECK
      -- не может быть в будущем, не может быть раньше чем в 13 лет
      -- !!!

      -- Сама по себе квалификационная категория необязательное поле, но проверяем для учителей
      IF(V$TEACHER = 1) THEN
      BEGIN
        SELECT COUNT(*)
        FROM VACANCY_GET_CAT(:OBJECT_ID)
        WHERE LISTVAL_ID IS NULL
        INTO :V$TEMP;
        IF (V$TEMP <> 0) THEN
        BEGIN
          ERROR_TEXT = 'Для педагогического сотрудника «' || V$FIO || '» не заполнено поле «Квалификационная категория»';
          ERROR_NAME = 'Для педагогического сотрудника не заполнено поле «Квалификационная категория»';
          PARAMS_NAME = 'Квалификационная категория';
          ERROR_TYPE = 3;
          SUSPEND;
        END
      END

      IF(V$ACTIVE = 1 AND NOT EXISTS(
        SELECT FIRST 1 1
        FROM LINKS L15
        JOIN VALL VLL ON VLL.OBJ_ID = L15.OBJ_ID AND VLL.PARAM_ID = 72 AND VLL.IS_DEL = 0 AND VLL.LISTVAL_ID = 934
        LEFT JOIN VALD V74 ON V74.PARAM_ID = 74 AND V74.OBJ_ID = L15.OBJ_ID AND V74.IS_DEL = 0
        WHERE L15.OBJ_TYPE_ID = 15 AND L15.PARENT_ID = :OBJECT_ID AND L15.DATE_DEL IS NULL AND V74.VAL IS NULL
      )) THEN
      BEGIN
        ERROR_TEXT = 'У сотрудника «' || V$FIO || '» отсутствует основная должность';
        ERROR_NAME = 'Отсутствует основная должность';
        PARAMS_NAME = 'Должность основная или дополнительная';
        ERROR_TYPE = 2;
        SUSPEND;
      END

      IF (V$MANAGER = 1 OR (V$TEACHER = 1 AND V$ACTIVE = 1)) THEN
      BEGIN
        IF (NOT EXISTS(
          SELECT FIRST 1 1
          FROM LINKS L36
            WHERE L36.OBJ_TYPE_ID = 36 AND L36.PARENT_ID = :OBJECT_ID AND L36.DATE_DEL IS NULL
          )) THEN
        BEGIN
          ERROR_TEXT = 'Не введены данные о повышении квалификации для руководителя или штатного педагогического сотрудника «' || V$FIO || '»';
          ERROR_NAME = 'Не введены данные о повышении квалификации для руководителя или штатного педагогического сотрудника';
          PARAMS_NAME = 'Прохождение аттестации';
          ERROR_TYPE = 2;
          SUSPEND;
        END
      END

      IF(V$TEACHER = 1 AND V$ACTIVE = 1) THEN
      BEGIN
        IF(NOT EXISTS(
          SELECT FIRST 1 1
          FROM LINKS L34
          WHERE L34.OBJ_TYPE_ID = 34 AND L34.PARENT_ID = :OBJECT_ID AND L34.DATE_DEL IS NULL
        )) THEN
        BEGIN
          ERROR_TEXT = 'Не введены данные о прохождении аттестации для штатного педагогического сотрудника «' || V$FIO || '»';
          ERROR_NAME = 'Не введены данные о прохождении аттестации для штатного педагогического сотрудника';
          PARAMS_NAME = 'Прохождение аттестации';
          ERROR_TYPE = 2;
          SUSPEND;
        END
      END

      IF(V$ACTIVE = 1) THEN
      BEGIN
        SELECT COUNT(L85.OBJ_ID)
        FROM LINKS L85
        JOIN VALL V465 ON V465.OBJ_ID = L85.OBJ_ID AND V465.PARAM_ID = 465 AND V465.IS_DEL = 0 AND V465.LISTVAL_ID = 941
        WHERE L85.PARENT_ID = :OBJECT_ID AND L85.OBJ_TYPE_ID = 85 AND L85.DATE_DEL IS NULL
        INTO :V$TEMP;
        IF (V$TEMP = 0) THEN
        BEGIN
          ERROR_TEXT = 'Для сотрудника «' || V$FIO || '» не введён общий стаж';
          ERROR_NAME = 'Не заполнено поле «Общий стаж»';
          PARAMS_NAME = 'Общий стаж';
          ERROR_TYPE = 2;
          SUSPEND;
        END
      END

      IF(V$TEACHER = 1 AND V$ACTIVE = 1) THEN
      BEGIN
        SELECT COUNT(L85.OBJ_ID), SUM(IIF(V466.VAL > V467.VAL, 1, 0))
        FROM LINKS L85
        JOIN VALL V465 ON V465.OBJ_ID = L85.OBJ_ID AND V465.PARAM_ID = 465 AND V465.IS_DEL = 0 AND V465.LISTVAL_ID = 942
        LEFT JOIN VALD V466 ON V466.OBJ_ID = L85.OBJ_ID AND V466.PARAM_ID = 466 AND V466.IS_DEL = 0
        LEFT JOIN VALD V467 ON V467.OBJ_ID = L85.OBJ_ID AND V467.PARAM_ID = 467 AND V467.IS_DEL = 0
        WHERE L85.PARENT_ID = :OBJECT_ID AND L85.OBJ_TYPE_ID = 85 AND L85.DATE_DEL IS NULL
        INTO :V$TEMP, :V$VALI;
        IF(V$TEMP = 0) THEN
        BEGIN
          ERROR_TEXT = 'Для педагогического сотрудника «' || V$FIO || '» не введён педагогический стаж';
          ERROR_NAME = 'Не заполнено поле «Педагогический стаж»';
          PARAMS_NAME = 'Педагогический стаж';
          ERROR_TYPE = 2;
          SUSPEND;
        END
        IF(V$VALI > 0) THEN
        BEGIN
          ERROR_TEXT = 'Для педагогического сотрудника «' || V$FIO || '» некорректно введены периоды педагогического стажа';
          ERROR_NAME = 'Не корректно введены периоды для поля «Педагогический стаж»';
          PARAMS_NAME = 'Педагогический стаж';
          ERROR_TYPE = 3;
          SUSPEND;
        END
      END

      EXECUTE PROCEDURE VERIFY_WORKERS2(:OBJECT_ID);

    END

    -- Служебное сообщение об успешности проверок
    IF(ERROR_TYPE = 0) THEN
    BEGIN
      ERROR_TEXT = 'Данные успешно верифицированы, замечаний и ошибок нет';
      ERROR_NAME = 'Без замечаний';
      PARAMS_NAME = NAME_TASK;
      PARENT_ID = I$OBJ_ID;
      OBJECT_ID = NULL;
      LINK_ID = NULL;
      SUSPEND;
    END

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE VERIFY_WORKERS2 (
    I$OBJ_ID BIGINT)
AS
declare variable V$OBJ_ID bigint;
declare variable V$TEMP integer;
begin
    IF (I$OBJ_ID IS NOT NULL) THEN
    BEGIN
        FOR
            SELECT L38.OBJ_ID,
                   (SELECT COUNT(VS.VAL)
                    FROM VALS VS
                    WHERE VS.PARAM_ID IN (338, 340)
                    AND VS.IS_DEL = 0
                    AND VS.OBJ_ID = L38.OBJ_ID
                   ) +
                   (SELECT COUNT(VLL.LISTVAL_ID)
                    FROM VALL VLL
                    WHERE VLL.PARAM_ID = 337
                    AND VLL.IS_DEL = 0
                    AND VLL.OBJ_ID = L38.OBJ_ID
                   ) +
                   (SELECT COUNT(VD.VAL)
                    FROM VALD VD
                    WHERE VD.PARAM_ID = 339
                    AND VD.IS_DEL = 0
                    AND VD.OBJ_ID = L38.OBJ_ID
                   )
            FROM LINKS L38
            WHERE L38.OBJ_TYPE_ID = 38 AND L38.PARENT_ID = :I$OBJ_ID AND L38.DATE_DEL IS NULL
            INTO :V$OBJ_ID, :V$TEMP
        DO
        BEGIN
            IF (V$TEMP = 0) THEN
            BEGIN
                UPDATE LINKS L
                SET L.DATE_DEL = CURRENT_TIMESTAMP
                WHERE L.OBJ_ID = :V$OBJ_ID AND L.OBJ_TYPE_ID = 38 AND DATE_DEL IS NULL;
            END
        END
        --
        FOR
            SELECT L39.OBJ_ID,
                   (SELECT COUNT(VS.VAL)
                    FROM VALS VS
                    WHERE VS.PARAM_ID IN (346, 348) AND VS.IS_DEL = 0 AND VS.OBJ_ID = L39.OBJ_ID
                   ) +
                   (SELECT COUNT(VLL.LISTVAL_ID)
                    FROM VALL VLL
                    WHERE VLL.PARAM_ID = 345 AND VLL.IS_DEL = 0 AND VLL.OBJ_ID = L39.OBJ_ID
                   ) +
                   (SELECT COUNT(VD.VAL)
                    FROM VALD VD
                    WHERE VD.PARAM_ID = 347 AND VD.IS_DEL = 0 AND VD.OBJ_ID = L39.OBJ_ID
                   )
            FROM LINKS L39
            WHERE L39.OBJ_TYPE_ID = 39 AND L39.PARENT_ID = :I$OBJ_ID AND L39.DATE_DEL IS NULL
            INTO :V$OBJ_ID, :V$TEMP
        DO
        BEGIN
            IF (V$TEMP = 0) THEN
            BEGIN
                UPDATE LINKS L
                SET L.DATE_DEL = CURRENT_TIMESTAMP
                WHERE L.OBJ_ID = :V$OBJ_ID AND L.OBJ_TYPE_ID = 39 AND DATE_DEL IS NULL;
            END
        END

        FOR
            SELECT L40.OBJ_ID,
                   (SELECT COUNT(VS.VAL)
                    FROM VALS VS
                    WHERE VS.PARAM_ID IN (342, 344) AND VS.IS_DEL = 0 AND VS.OBJ_ID = L40.OBJ_ID
                   ) +
                   (SELECT COUNT(VLL.LISTVAL_ID)
                    FROM VALL VLL
                    WHERE VLL.PARAM_ID = 341 AND VLL.IS_DEL = 0 AND VLL.OBJ_ID = L40.OBJ_ID
                   ) +
                   (SELECT COUNT(VD.VAL)
                    FROM VALD VD
                    WHERE VD.PARAM_ID = 343 AND VD.IS_DEL = 0 AND VD.OBJ_ID = L40.OBJ_ID
                   )
            FROM LINKS L40
            WHERE L40.OBJ_TYPE_ID = 40 AND L40.PARENT_ID = :I$OBJ_ID AND L40.DATE_DEL IS NULL
            INTO :V$OBJ_ID, :V$TEMP
        DO
        BEGIN
            IF (V$TEMP = 0) THEN
            BEGIN
                UPDATE LINKS L
                SET L.DATE_DEL = CURRENT_TIMESTAMP
                WHERE L.OBJ_ID = :V$OBJ_ID AND L.OBJ_TYPE_ID = 40 AND DATE_DEL IS NULL;
            END
        END

        FOR
            SELECT L41.OBJ_ID,
                   (SELECT COUNT(VLL.LISTVAL_ID)
                    FROM VALL VLL
                    WHERE VLL.PARAM_ID IN (350, 351) AND VLL.IS_DEL = 0 AND VLL.OBJ_ID = L41.OBJ_ID
                   ) +
                   (SELECT COUNT(VI.VAL)
                    FROM VALI VI
                    WHERE VI.PARAM_ID = 349 AND VI.IS_DEL = 0 AND VI.OBJ_ID = L41.OBJ_ID
                   )
            FROM LINKS L41
            WHERE L41.OBJ_TYPE_ID = 41 AND L41.PARENT_ID = :I$OBJ_ID AND L41.DATE_DEL IS NULL
            INTO :V$OBJ_ID, :V$TEMP
        DO
        BEGIN
            IF (:V$TEMP = 0) THEN
            BEGIN
                UPDATE LINKS L
                SET L.DATE_DEL = CURRENT_TIMESTAMP
                WHERE L.OBJ_ID = :V$OBJ_ID
                AND L.OBJ_TYPE_ID = 41
                AND DATE_DEL IS NULL;
            END
        END

        FOR
            SELECT L42.OBJ_ID,
                   (SELECT COUNT(VLL.LISTVAL_ID)
                    FROM VALL VLL
                    WHERE VLL.PARAM_ID = 353
                    AND VLL.IS_DEL = 0
                    AND VLL.OBJ_ID = L42.OBJ_ID
                   ) +
                   (SELECT COUNT(VI.VAL)
                    FROM VALI VI
                    WHERE VI.PARAM_ID = 352
                    AND VI.IS_DEL = 0
                    AND VI.OBJ_ID = L42.OBJ_ID
                   )
            FROM LINKS L42
            WHERE L42.OBJ_TYPE_ID = 42
            AND L42.PARENT_ID = :I$OBJ_ID
            AND L42.DATE_DEL IS NULL
            INTO :V$OBJ_ID, :V$TEMP
        DO
        BEGIN
            IF (V$TEMP = 0) THEN
            BEGIN
                UPDATE LINKS L
                SET L.DATE_DEL = CURRENT_TIMESTAMP
                WHERE L.OBJ_ID = :V$OBJ_ID AND L.OBJ_TYPE_ID = 42 AND DATE_DEL IS NULL;
            END
        END

        FOR
            SELECT L43.OBJ_ID,
                   (SELECT COUNT(VS.VAL)
                    FROM VALS VS
                    WHERE VS.PARAM_ID IN (355, 356) AND VS.IS_DEL = 0 AND VS.OBJ_ID = L43.OBJ_ID
                   ) +
                   (SELECT COUNT(VD.VAL)
                    FROM VALD VD
                    WHERE VD.PARAM_ID = 354 AND VD.IS_DEL = 0 AND VD.OBJ_ID = L43.OBJ_ID
                   )
            FROM LINKS L43
            WHERE L43.OBJ_TYPE_ID = 43 AND L43.PARENT_ID = :I$OBJ_ID AND L43.DATE_DEL IS NULL
            INTO :V$OBJ_ID, :V$TEMP
        DO
        BEGIN
            IF (V$TEMP = 0) THEN
            BEGIN
                UPDATE LINKS L
                SET L.DATE_DEL = CURRENT_TIMESTAMP
                WHERE L.OBJ_ID = :V$OBJ_ID AND L.OBJ_TYPE_ID = 43 AND DATE_DEL IS NULL;
            END
        END

        FOR
            SELECT L44.OBJ_ID,
                   (SELECT COUNT(VS.VAL)
                    FROM VALS VS
                    WHERE VS.PARAM_ID = 358 AND VS.IS_DEL = 0 AND VS.OBJ_ID = L44.OBJ_ID
                   ) +
                   (SELECT COUNT(VD.VAL)
                    FROM VALD VD
                    WHERE VD.PARAM_ID = 357 AND VD.IS_DEL = 0 AND VD.OBJ_ID = L44.OBJ_ID
                   )
            FROM LINKS L44
            WHERE L44.OBJ_TYPE_ID = 44 AND L44.PARENT_ID = :I$OBJ_ID AND L44.DATE_DEL IS NULL
            INTO :V$OBJ_ID, :V$TEMP
        DO
        BEGIN
            IF (:V$TEMP = 0) THEN
            BEGIN
                UPDATE LINKS L
                SET L.DATE_DEL = CURRENT_TIMESTAMP
                WHERE L.OBJ_ID = :V$OBJ_ID AND L.OBJ_TYPE_ID = 44 AND DATE_DEL IS NULL;
            END
        END

        FOR
            SELECT L31.OBJ_ID,
                   (SELECT COUNT(VS.VAL)
                    FROM VALS VS
                    WHERE VS.PARAM_ID IN (215, 324) AND VS.IS_DEL = 0 AND VS.OBJ_ID = L31.OBJ_ID
                   ) +
                   (SELECT COUNT(VLL.LISTVAL_ID)
                    FROM VALL VLL
                    WHERE VLL.PARAM_ID = 214 AND VLL.IS_DEL = 0 AND VLL.OBJ_ID = L31.OBJ_ID
                   ) +
                   (SELECT COUNT(VD.VAL)
                    FROM VALD VD
                    WHERE VD.PARAM_ID = 213 AND VD.IS_DEL = 0 AND VD.OBJ_ID = L31.OBJ_ID
                   )
            FROM LINKS L31
            WHERE L31.OBJ_TYPE_ID = 31 AND L31.PARENT_ID = :I$OBJ_ID AND L31.DATE_DEL IS NULL
            INTO :V$OBJ_ID, :V$TEMP
        DO
        BEGIN
            IF (:V$TEMP = 0) THEN
            BEGIN
                UPDATE LINKS L
                SET L.DATE_DEL = CURRENT_TIMESTAMP
                WHERE L.OBJ_ID = :V$OBJ_ID AND L.OBJ_TYPE_ID = 31 AND DATE_DEL IS NULL;
            END
        END

        FOR
            SELECT L37.OBJ_ID,
                   (SELECT COUNT(VS.VAL)
                    FROM VALS VS
                    WHERE VS.PARAM_ID = 1401 AND VS.IS_DEL = 0 AND VS.OBJ_ID = L37.OBJ_ID
                   ) +
                   (SELECT COUNT(VLL.LISTVAL_ID)
                    FROM VALL VLL
                    WHERE VLL.PARAM_ID IN (325, 326, 330) AND VLL.IS_DEL = 0 AND VLL.OBJ_ID = L37.OBJ_ID
                   ) +
                   (SELECT COUNT(VD.VAL)
                    FROM VALD VD
                    WHERE VD.PARAM_ID IN (327, 328) AND VD.IS_DEL = 0 AND VD.OBJ_ID = L37.OBJ_ID
                   )
            FROM LINKS L37
            WHERE L37.OBJ_TYPE_ID = 37 AND L37.PARENT_ID = :I$OBJ_ID AND L37.DATE_DEL IS NULL
            INTO :V$OBJ_ID, :V$TEMP
        DO
        BEGIN
            IF (V$TEMP = 0) THEN
            BEGIN
                UPDATE LINKS L
                SET L.DATE_DEL = CURRENT_TIMESTAMP
                WHERE L.OBJ_ID = :V$OBJ_ID AND L.OBJ_TYPE_ID = 37 AND DATE_DEL IS NULL;
            END
        END

        FOR
            SELECT L100.OBJ_ID,
                   (SELECT COUNT(VS.VAL)
                    FROM VALS VS
                    WHERE VS.PARAM_ID = 619 AND VS.IS_DEL = 0 AND VS.OBJ_ID = L100.OBJ_ID AND TRIM(VS.VAL) <> ''
                   ) +
                   (SELECT COUNT(VLL.LISTVAL_ID)
                    FROM VALL VLL
                    WHERE VLL.PARAM_ID IN (615, 616, 617) AND VLL.IS_DEL = 0 AND VLL.OBJ_ID = L100.OBJ_ID
                   ) +
                   (SELECT 1
                    FROM VAL_GET(L100.OBJ_ID, 618)
                    WHERE TRIM(V) <> ''
                   )
            FROM LINKS L100
            WHERE L100.OBJ_TYPE_ID = 100 AND L100.PARENT_ID = :I$OBJ_ID AND L100.DATE_DEL IS NULL
            INTO :V$OBJ_ID, :V$TEMP
        DO
        BEGIN
            IF (V$TEMP = 0) THEN
            BEGIN
                UPDATE LINKS L
                SET L.DATE_DEL = CURRENT_TIMESTAMP
                WHERE L.OBJ_ID = :V$OBJ_ID AND L.OBJ_TYPE_ID = 100 AND DATE_DEL IS NULL;
            END
        END

        FOR
            SELECT L101.OBJ_ID,
                   (SELECT COUNT(VS.VAL)
                    FROM VALS VS
                    WHERE VS.PARAM_ID = 622
                    AND VS.IS_DEL = 0
                    AND VS.OBJ_ID = L101.OBJ_ID
                    AND TRIM(VS.VAL) <> ''
                   ) +
                   (SELECT COUNT(VLI.VAL)
                    FROM VALI VLI
                    WHERE VLI.PARAM_ID IN (904)
                    AND VLI.IS_DEL = 0
                    AND VLI.OBJ_ID = L101.OBJ_ID
                    AND VLI.VAL > 0
                   ) +
                   (SELECT COUNT(VLL.LISTVAL_ID)
                    FROM VALL VLL
                    WHERE VLL.PARAM_ID IN (620)
                    AND VLL.IS_DEL = 0
                    AND VLL.OBJ_ID = L101.OBJ_ID
                   ) +
                   (SELECT 1
                    FROM VAL_GET(L101.OBJ_ID, 621)
                    WHERE TRIM(V) <> ''
                   )
            FROM LINKS L101
            WHERE L101.OBJ_TYPE_ID = 101
            AND L101.PARENT_ID = :I$OBJ_ID
            AND L101.DATE_DEL IS NULL
            INTO :V$OBJ_ID, :V$TEMP
        DO
        BEGIN
            IF (V$TEMP = 0) THEN
            BEGIN
                UPDATE LINKS L
                SET L.DATE_DEL = CURRENT_TIMESTAMP
                WHERE L.OBJ_ID = :V$OBJ_ID
                AND L.OBJ_TYPE_ID = 101
                AND DATE_DEL IS NULL;
            END
        END

        FOR
            SELECT L100.OBJ_ID,
                   (SELECT COUNT(VS.VAL)
                    FROM VALS VS
                    WHERE VS.PARAM_ID IN (615, 617, 619)
                    AND VS.IS_DEL = 0
                    AND VS.OBJ_ID = L100.OBJ_ID
                   ) +
                   (SELECT COUNT(VLL.LISTVAL_ID)
                    FROM VALL VLL
                    WHERE VLL.PARAM_ID IN (616)
                    AND VLL.IS_DEL = 0
                    AND VLL.OBJ_ID = L100.OBJ_ID
                   ) +
                   (SELECT COUNT(VD.VAL)
                    FROM VALD VD
                    WHERE VD.PARAM_ID = 618
                    AND VD.IS_DEL = 0
                    AND VD.OBJ_ID = L100.OBJ_ID
                   )
            FROM LINKS L100
            WHERE L100.OBJ_TYPE_ID = 100
            AND L100.PARENT_ID = :I$OBJ_ID
            AND L100.DATE_DEL IS NULL
            INTO :V$OBJ_ID, :V$TEMP
        DO
        BEGIN
            IF (V$TEMP = 0) THEN
            BEGIN
                UPDATE LINKS L
                SET L.DATE_DEL = CURRENT_TIMESTAMP
                WHERE L.OBJ_ID = :V$OBJ_ID AND L.OBJ_TYPE_ID = 100 AND DATE_DEL IS NULL;
            END
        END

        FOR
            SELECT L101.OBJ_ID,
                   (SELECT COUNT(VS.VAL)
                    FROM VALS VS
                    WHERE VS.PARAM_ID IN (620, 619, 622) AND VS.IS_DEL = 0 AND VS.OBJ_ID = L101.OBJ_ID
                   ) +
                   (SELECT COUNT(VLI.VAL)
                    FROM VALI VLI
                    WHERE VLI.PARAM_ID IN (904) AND VLI.IS_DEL = 0 AND VLI.OBJ_ID = L101.OBJ_ID
                   ) +
                   (SELECT COUNT(VD.VAL)
                    FROM VALD VD
                    WHERE VD.PARAM_ID = 621 AND VD.IS_DEL = 0 AND VD.OBJ_ID = L101.OBJ_ID
                   )
            FROM LINKS L101
            WHERE L101.OBJ_TYPE_ID = 101 AND L101.PARENT_ID = :I$OBJ_ID AND L101.DATE_DEL IS NULL
            INTO :V$OBJ_ID, :V$TEMP
        DO
        BEGIN
            IF (V$TEMP = 0) THEN
            BEGIN
                UPDATE LINKS L
                SET L.DATE_DEL = CURRENT_TIMESTAMP
                WHERE L.OBJ_ID = :V$OBJ_ID AND L.OBJ_TYPE_ID = 101 AND DATE_DEL IS NULL;
            END
        END
    END
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE VERIFY_WORKERS_DICT (
    I$LEVEL_ID BIGINT)
RETURNS (
    TYPE_ID BIGINT,
    TYPE_NAME VARCHAR(400),
    PARAM_ID BIGINT,
    PARAM_NAME VARCHAR(400),
    PARAM_TYPE_ID BIGINT,
    PARAM_TYPE_NAME VARCHAR(100),
    VAL_REQUIRED SMALLINT,
    VAL_CHECK SMALLINT,
    VAL_MASK VARCHAR(400),
    VAL_EXTRA VARCHAR(400))
AS
begin

  -- Проверяем что LEVEL_ID допустимый
  IF(NOT EXISTS(
    SELECT FIRST 1 1
    FROM LEVELS L
    JOIN TASKS T ON T.TASK_ID = L.TASK_ID AND T.IS_DEL = 0
    JOIN MODULES M ON M.MODULE_ID = T.MODULE_ID AND M.IS_DEL = 0 AND M.IS_ACTIVE = 1
    WHERE L.LEVEL_ID = :I$LEVEL_ID AND L.IS_DEL = 0
  ))
  THEN
    EXCEPTION DATA_ERROR 'Недопустимое приложение для контроля';

  -- Поля для объектов: сотрудники и все вложенные документы
  -- заполняемые в данном приложении (RW)
  FOR
    SELECT P.TYPE_ID, P.PARAM_ID, P.PARAM_TYPE, RT.VAL, RP.VAL, P.IS_REQUIRED, IIF(P.DO_CHECK = 0, 0, 1), P.EDIT_MASK
    FROM PARAMS P
    JOIN LPARAMS LP ON LP.PARAM_ID = P.PARAM_ID AND LP.LEVEL_ID = :I$LEVEL_ID AND LP.IS_DEL = 0 AND LP.EDIT_TYPE = 1
    JOIN TYPES T ON T.TYPE_ID = P.TYPE_ID AND T.IS_DEL = 0
    JOIN RES RT ON RT.RES_ID = T.RES_ID AND RT.LANG_CODE = 'RU'
    JOIN RES RP ON RP.RES_ID = P.RES_ID AND RP.LANG_CODE = 'RU'
    WHERE P.TYPE_ID IN (14, 15, 11, 12, 79, 31, 32, 33, 34, 35, 36, 37, 39, 40, 41, 42, 43, 44, 100, 101, 156, 376, 395, 397, 458) AND P.IS_DEL = 0
      AND (P.IS_REQUIRED = 1 OR (P.EDIT_MASK IS NOT NULL AND P.EDIT_MASK <> ''))
    ORDER BY T.SORT_ORDER, P.GRID_ORDER
    INTO :TYPE_ID, :PARAM_ID, :PARAM_TYPE_ID, :TYPE_NAME, :PARAM_NAME, :VAL_REQUIRED, :VAL_CHECK, :VAL_MASK
  DO
  BEGIN
    IF(VAL_MASK = '') THEN VAL_MASK = NULL;

    IF(PARAM_TYPE_ID = 1) THEN PARAM_TYPE_NAME = 'Целое число';
    ELSE IF(PARAM_TYPE_ID = 2) THEN PARAM_TYPE_NAME = 'Вещественное число';
    ELSE IF(PARAM_TYPE_ID = 3) THEN PARAM_TYPE_NAME = 'Дата и время';
    ELSE IF(PARAM_TYPE_ID = 4) THEN PARAM_TYPE_NAME = 'Дата';
    ELSE IF(PARAM_TYPE_ID = 5) THEN PARAM_TYPE_NAME = 'Время';
    ELSE IF(PARAM_TYPE_ID = 6) THEN PARAM_TYPE_NAME = 'Значение из справочника';
    ELSE IF(PARAM_TYPE_ID = 7) THEN PARAM_TYPE_NAME = 'Строка или значение из справочника';
    ELSE IF(PARAM_TYPE_ID = 8) THEN PARAM_TYPE_NAME = 'Строка';
    ELSE IF(PARAM_TYPE_ID = 11) THEN PARAM_TYPE_NAME = 'Файл';
    ELSE IF(PARAM_TYPE_ID = 12) THEN PARAM_TYPE_NAME = 'Изображение';
    ELSE IF(PARAM_TYPE_ID = 13) THEN PARAM_TYPE_NAME = 'Ссылка на объект';
    ELSE IF(PARAM_TYPE_ID = 18) THEN PARAM_TYPE_NAME = 'Адрес';
    ELSE PARAM_TYPE_NAME = 'Недопустимый тип';

    VAL_EXTRA = NULL;
    -- IF(PARAM_TYPE_ID = 8 AND TYPE_ID = 2 AND VAL_MASK IS NULL) THEN VAL_EXTRA = 'CLEANUP';

    SUSPEND;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE VERIFY_YEAR_CHANGER (
    I$USER_ID BIGINT)
RETURNS (
    LINK_ID BIGINT,
    SCHOOLAR_ID BIGINT,
    NAME_TASK VARCHAR(1000),
    ERROR_NAME VARCHAR(1000),
    PARAMS_NAME VARCHAR(1000),
    LOCATION VARCHAR(1000),
    PUPIL VARCHAR(1000),
    ERROR_TEXT VARCHAR(1000),
    ERROR_TYPE SMALLINT)
AS
declare variable V$PRL_ID bigint;
declare variable V$CHECK_DATE date;
declare variable V$SCHOOL_ID bigint;
declare variable V$MOVEMENT_ID bigint;
declare variable V$MOVE_DATE date;
BEGIN
    NAME_TASK = 'Движение обучающихся, воспитанников';

    SELECT FIRST 1 L.OBJ_ID
    FROM LINKS L
    WHERE L.PARENT_ID IS NULL AND L.OBJ_TYPE_ID = 2 AND L.DATE_DEL IS NULL
    INTO :V$SCHOOL_ID;

    V$CHECK_DATE = '31.08.' || EXTRACT(YEAR FROM CURRENT_DATE);

    FOR
        SELECT L10.PRL_ID, L10.SCHOOLAR_ID, L10.LINK_ID, COALESCE(M.REASON_OUT, M.REASON_IN), MAXVALUE(M.DATE_OUT, M.DATE_IN)
        FROM (
            SELECT L9.OBJ_ID PRL_ID, L10.OBJ_ID SCHOOLAR_ID, L10.LINK_ID
            FROM LINKS L7
            JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
            JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
            JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
            WHERE L7.PARENT_ID = :V$SCHOOL_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
            UNION ALL
            SELECT L.OBJ_ID PRL_ID, L10.OBJ_ID SCHOOLAR_ID, L10.LINK_ID
            FROM LINKS L78
            JOIN LINKS L ON L.PARENT_ID = L78.OBJ_ID AND L.OBJ_TYPE_ID IN (81,82,83) AND L.DATE_DEL IS NULL
            JOIN LINKS L10 ON L10.PARENT_ID = L.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
            WHERE L78.PARENT_ID = :V$SCHOOL_ID AND L78.OBJ_TYPE_ID = 78 AND L78.DATE_DEL IS NULL
        ) L10
        JOIN PERSON_MOVEMENTS M ON M.DATE_DEL IS NULL AND M.PERSON_ID = L10.SCHOOLAR_ID
            AND M.REASON_IN IN (805, 806, 811, 812) AND (M.DATE_IN >= :V$CHECK_DATE OR M.DATE_OUT >= :V$CHECK_DATE)
        INTO :V$PRL_ID, :SCHOOLAR_ID, :LINK_ID, :V$MOVEMENT_ID, :V$MOVE_DATE
    DO
    BEGIN
        SELECT CAPTION FROM OBJECT_CAPTION_GET(:SCHOOLAR_ID, 50, NULL, :I$USER_ID) INTO :PUPIL;
        SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$PRL_ID, NULL, NULL, :I$USER_ID) INTO :LOCATION;

        ERROR_TEXT = PUPIL || ' (' || LOCATION || ') ' || (SELECT VAL FROM LISTVAL_TEXT(:V$MOVEMENT_ID)) || ' ' || V$MOVE_DATE;
        ERROR_NAME = 'В контингенте есть учащиеся выбывшие/прибывшие после ' || V$CHECK_DATE;
        ERROR_TYPE = 3;
        PARAMS_NAME = 'Дата приёма/выбытия';
        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE VOSP_MEMBERS_LIST (
    I$LESSON_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT,
    MG_ID BIGINT,
    DATE_MODIFY TIMESTAMP)
AS
declare variable V$MEMBER_ID bigint;
declare variable V$MEMBER_TYPE bigint;
begin

  FOR
    SELECT A.REF_ID, O.TYPE_ID, A.DATE_MODIFY
    FROM CJ2_LESSON_ATTRS A
    JOIN OBJECTS O ON O.OBJ_ID = A.REF_ID
    WHERE A.DATE_DEL IS NULL AND A.ATTR_NAME = 'mlist' AND A.LESSON_ID = :I$LESSON_ID
    INTO :V$MEMBER_ID, :V$MEMBER_TYPE, :DATE_MODIFY
  DO
  BEGIN
    IF(V$MEMBER_TYPE = 9) THEN
    BEGIN
      OBJ_ID = V$MEMBER_ID;
      MG_ID = NULL;
      SELECT FIRST 1 LP256.PARENT_ID
      FROM LINKS L10
      JOIN LINKS LP256 ON LP256.OBJ_ID = L10.OBJ_ID AND LP256.PARENT_TYPE_ID = 256 AND LP256.DATE_DEL IS NULL
      WHERE L10.PARENT_ID = :OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      ORDER BY LP256.DATE_INS
      INTO :MG_ID;
      SUSPEND;
    END
    ELSE IF(V$MEMBER_TYPE = 8) THEN
    BEGIN
      FOR
        SELECT L9.OBJ_ID
        FROM LINKS L9
        WHERE L9.PARENT_ID = :V$MEMBER_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
        INTO :OBJ_ID
      DO
      BEGIN
        MG_ID = NULL;
        SELECT FIRST 1 LP256.PARENT_ID
        FROM LINKS L10
        JOIN LINKS LP256 ON LP256.OBJ_ID = L10.OBJ_ID AND LP256.PARENT_TYPE_ID = 256 AND LP256.DATE_DEL IS NULL
        WHERE L10.PARENT_ID = :OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        ORDER BY LP256.DATE_INS
        INTO :MG_ID;
        SUSPEND;
      END
    END
    ELSE IF(V$MEMBER_TYPE = 7) THEN
    BEGIN
      FOR
        SELECT L9.OBJ_ID
        FROM LINKS L8
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
        WHERE L8.PARENT_ID = :V$MEMBER_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
        INTO :OBJ_ID
      DO
      BEGIN
        MG_ID = NULL;
        SELECT FIRST 1 LP256.PARENT_ID
        FROM LINKS L10
        JOIN LINKS LP256 ON LP256.OBJ_ID = L10.OBJ_ID AND LP256.PARENT_TYPE_ID = 256 AND LP256.DATE_DEL IS NULL
        WHERE L10.PARENT_ID = :OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        ORDER BY LP256.DATE_INS
        INTO :MG_ID;
        SUSPEND;
      END
    END
    ELSE IF(V$MEMBER_TYPE = 2) THEN
    BEGIN
      FOR
        SELECT L9.OBJ_ID
        FROM LINKS L7
        JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
        JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
        WHERE L7.PARENT_ID = :V$MEMBER_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
        INTO :OBJ_ID
      DO
      BEGIN
        MG_ID = NULL;
        SELECT FIRST 1 LP256.PARENT_ID
        FROM LINKS L10
        JOIN LINKS LP256 ON LP256.OBJ_ID = L10.OBJ_ID AND LP256.PARENT_TYPE_ID = 256 AND LP256.DATE_DEL IS NULL
        WHERE L10.PARENT_ID = :OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
        ORDER BY LP256.DATE_INS
        INTO :MG_ID;
        SUSPEND;
      END
    END
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE VOSP_PLAN_DELETE (
    I$OBJ_ID BIGINT)
AS
declare variable V$CJ_ID bigint;
declare variable V$DAY_ID bigint;
declare variable M integer;
declare variable D integer;
declare variable V$Y integer;
declare variable V$DT date;
begin

  -- Нельзя удалять действующий план
  IF(EXISTS(
    SELECT FIRST 1 1
    FROM VALL V3373
    WHERE V3373.OBJ_ID = :I$OBJ_ID AND V3373.PARAM_ID = 3373 AND V3373.IS_DEL = 0 AND V3373.LISTVAL_ID = 11715
  ))
  THEN
    EXCEPTION DATA_ERROR 'Нельзя удалять действующий план';

  SELECT FIRST 1 J.OBJ_ID, V.COST
  FROM CJ2_JOURNAL J
  JOIN LISTVALS V ON V.LISTVAL_ID = J.YEAR_ID
  WHERE J.DATE_DEL IS NULL AND J.REF_ID = :I$OBJ_ID
  INTO :V$CJ_ID, :V$Y;

  -- Нельзя удалять план, в котором в расписание поставлены мероприятия
  SELECT FIRST 1 SI.WEEKDAY_NUM
  FROM SCHEDULE_ITEMS SI
  JOIN LINKS LP ON LP.OBJ_ID = SI.SCHEDULE_ID AND LP.PARENT_TYPE_ID IN (3, 68) AND LP.DATE_DEL IS NULL
  WHERE SI.CJ_ID = :V$CJ_ID AND SI.DATE_DEL IS NULL
  INTO :V$DAY_ID;

  IF(V$DAY_ID IS NOT NULL) THEN
  BEGIN
    IF(V$DAY_ID < 100) THEN EXCEPTION DATA_ERROR 'Журнал уже добавлен в шаблон расписания занятий';
    ELSE
    BEGIN
      M = V$DAY_ID / 100;
      D = V$DAY_ID - M * 100;
      IF(M >= 9) THEN V$DT = D || '.' || M || '.' || V$Y; ELSE V$DT = D || '.' || M || '.' || (V$Y + 1);
      EXCEPTION DATA_ERROR 'Журнал уже добавлен в ленту расписания, первое мероприятие на ' || (SELECT RESULT FROM DATE2STR(:V$DT));
    END
  END

  -- Удаляем связанный с планом журнал
  UPDATE CJ2_JOURNAL
  SET DATE_DEL = CURRENT_TIMESTAMP
  WHERE OBJ_ID = :V$CJ_ID;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE WORKDAYS_TO_TEXT (
    V VARCHAR(10))
RETURNS (
    VAL VARCHAR(100))
AS
declare variable VI integer;
declare variable YEARS integer;
declare variable MONTHS integer;
declare variable DAYS integer;
begin
  IF(V IS NULL OR V = '') THEN
  BEGIN     
      SUSPEND;
      EXIT;
  END

  VI = CAST(V AS INTEGER);
  YEARS = VI / 360;
  DAYS = VI - (YEARS * 360);
  MONTHS = DAYS / 30;
  DAYS = DAYS - (MONTHS * 30);

  VAL = '';

  IF(YEARS > 0) THEN
  BEGIN
    IF(YEARS < 5) THEN VAL = VAL || YEARS || ' г.'; ELSE VAL = VAL || YEARS || ' л.';
  END

  IF(MONTHS > 0) THEN
  BEGIN
    VAL = VAL || MONTHS || ' м.';
  END

  IF(DAYS > 0) THEN
  BEGIN
    VAL = VAL || DAYS || ' д.';
  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE WORKTAB_ADD (
    I$PARENT_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$DIV_ID BIGINT;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$D DATE;
DECLARE VARIABLE V$D2 DATE;
DECLARE VARIABLE T INTEGER;
DECLARE VARIABLE V$EX_PERSON BIGINT;
DECLARE VARIABLE V$RESP_PERSON BIGINT;
DECLARE VARIABLE V$PERSON_ID BIGINT;
DECLARE VARIABLE V$JOB_ID BIGINT;
DECLARE VARIABLE V$COLS VARCHAR(1000);
DECLARE VARIABLE V$ID1 BIGINT;
DECLARE VARIABLE V$M2 SMALLINT;
DECLARE VARIABLE V$M1_ID BIGINT;
begin

  SELECT FIRST 1 L.PARENT_ID, V3548.VAL, V3549.VAL, V3554.VAL
  FROM LINKS L
  LEFT JOIN VALR V3548 ON V3548.OBJ_ID = L.OBJ_ID AND V3548.PARAM_ID = 3548 AND V3548.IS_DEL = 0
  LEFT JOIN VALR V3549 ON V3549.OBJ_ID = L.OBJ_ID AND V3549.PARAM_ID = 3549 AND V3549.IS_DEL = 0
  LEFT JOIN VALS V3554 ON V3554.OBJ_ID = L.OBJ_ID AND V3554.PARAM_ID = 3554 AND V3554.IS_DEL = 0
  WHERE L.OBJ_ID = :I$PARENT_ID AND L.OBJ_TYPE_ID = 518 AND L.PARENT_TYPE_ID IN (2, 211) AND L.DATE_DEL IS NULL
  INTO :V$DIV_ID, :V$EX_PERSON, :V$RESP_PERSON, :V$COLS;

  IF(V$DIV_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Вид ведомости или подразделение не найдены, или были удалены';

  -- Что у нас с ответственными ?
  IF(V$EX_PERSON IS NOT NULL AND NOT EXISTS(
    SELECT FIRST 1 1
    FROM LINKS L14
    WHERE L14.OBJ_ID = :V$EX_PERSON AND L14.PARENT_TYPE_ID IN (2, 211) AND L14.DATE_DEL IS NULL
  ))
  THEN
    EXCEPTION DATA_ERROR 'Выбранный исполнитель не числится в организации, требуется внести изменения в настройки ведомости';

  IF(V$RESP_PERSON IS NOT NULL AND NOT EXISTS(
    SELECT FIRST 1 1
    FROM LINKS L14
    WHERE L14.OBJ_ID = :V$RESP_PERSON AND L14.PARENT_TYPE_ID IN (2, 211) AND L14.DATE_DEL IS NULL
  ))
  THEN
    EXCEPTION DATA_ERROR 'Выбранный ответственный не числится в организации, требуется внести изменения в настройки ведомости';

  -- Какой был последний период заполненный и последний по версии ?
  SELECT FIRST 1 L519.OBJ_ID, V3551.VAL
  FROM LINKS L519
  JOIN VALR V3545 ON V3545.OBJ_ID = L519.OBJ_ID AND V3545.PARAM_ID = 3545 AND V3545.IS_DEL = 0 AND V3545.VAL = :I$PARENT_ID
  JOIN VALD V3551 ON V3551.OBJ_ID = L519.OBJ_ID AND V3551.PARAM_ID = 3551 AND V3551.IS_DEL = 0
  WHERE L519.PARENT_ID = :V$DIV_ID AND L519.OBJ_TYPE_ID = 519 AND L519.DATE_DEL IS NULL
  ORDER BY 2 DESC, L519.COST DESC
  INTO :V$M1_ID, :V$D;

  -- Никогда не заполняем ведомость позднее текущей даты
  IF(V$D > CURRENT_DATE) THEN EXCEPTION DATA_ERROR 'Ведомости данного вида уже внесены на текущую дату, новые вносить нельзя до начала учетного периода';
  IF(V$D IS NULL) THEN
  BEGIN
    -- Первая в истории ведомость - начинаем с текущего месяца
    -- заполнять за первую половину тут все равно нечего
    V$D = '1.' || EXTRACT(MONTH FROM CURRENT_DATE) || '.' || EXTRACT(YEAR FROM CURRENT_DATE);
    IF(EXTRACT(DAY FROM V$D) < 20) THEN V$D2 = '15.' || EXTRACT(MONTH FROM V$D) || '.' || EXTRACT(YEAR FROM V$D);
      ELSE V$D2 = DATEADD(-1 DAY TO DATEADD(1 MONTH TO V$D));
  END
  ELSE
  BEGIN
    -- Продолжение
    -- Что делать если пропустили периоды ???
    IF(EXTRACT(DAY FROM V$D) < 20) THEN
    BEGIN
      -- Вторая половина того же месяца
      V$D = '01.' || EXTRACT(MONTH FROM V$D) || '.' || EXTRACT(YEAR FROM V$D);
      V$D2 = DATEADD(-1 DAY TO DATEADD(1 MONTH TO V$D));
      V$M2 = 1;
    END
    ELSE
    BEGIN
      -- Первая половина нового месяца
      V$D = DATEADD(1 MONTH TO V$D);
      V$D = '01.' || EXTRACT(MONTH FROM V$D) || '.' || EXTRACT(YEAR FROM V$D);
      V$D2 = '15.' || EXTRACT(MONTH FROM V$D) || '.' || EXTRACT(YEAR FROM V$D);
    END
  END

  -- Проверяем что столбцы все валидны
  FOR
    SELECT L.ID
    FROM STR_TO_ID_LIST(:V$COLS) L
    LEFT JOIN WORKTAB_COLS C ON C.OBJ_ID = L.ID
    WHERE C.OBJ_ID IS NULL
    INTO :V$ID1
  DO
  BEGIN
    EXCEPTION DATA_ERROR 'В списке дополнительных столбцов указан удаленный или несуществующий #' || V$ID1;
  END

  -- Вносим сразу со ссылкой на вид - данная ведомость будет корневой
  SELECT OBJ_ID
  FROM OBJECT_ADD(:V$DIV_ID, 519, NULL, 0)
  INTO :V$OBJ_ID;

  SELECT 1 FROM VAL_ADD(3545, :V$OBJ_ID, :I$PARENT_ID) INTO :T;
  SELECT 1 FROM VAL_ADD(3546, :V$OBJ_ID, :V$D) INTO :T;
  SELECT 1 FROM VAL_ADD(3551, :V$OBJ_ID, :V$D2) INTO :T;
  SELECT 1 FROM VAL_ADD(3547, :V$OBJ_ID, :V$EX_PERSON) INTO :T;
  SELECT 1 FROM VAL_ADD(3552, :V$OBJ_ID, :V$RESP_PERSON) INTO :T;
  SELECT 1 FROM VAL_ADD(3555, :V$OBJ_ID, :V$COLS) INTO :T;

  -- Заполняем состав сотрудников в ведомости из должностей
  -- увольнений в будущем не разрешаем, наличие сотрудника смотрим по текущей актуальности
  IF(EXISTS(
    SELECT FIRST 1 1
    FROM LINKS L
    WHERE L.PARENT_ID = :I$PARENT_ID AND L.OBJ_TYPE_ID IN (2, 211) AND L.DATE_DEL IS NULL
  )) THEN
  BEGIN
    -- Все сотрудники (этого подразделения) ?
    FOR
      SELECT DISTINCT LP14.PARENT_ID, L15.OBJ_ID
      FROM LINKS L13
      JOIN LINKS L15 ON L15.PARENT_ID = L13.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
      LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
      JOIN LINKS LP14 ON LP14.OBJ_ID = L15.OBJ_ID AND LP14.PARENT_TYPE_ID = 14 AND LP14.DATE_DEL IS NULL
      WHERE L13.PARENT_ID = :V$DIV_ID AND L13.OBJ_TYPE_ID = 13 AND L13.DATE_DEL IS NULL AND V74.VAL IS NULL
      ORDER BY 1, 2
      INTO :V$PERSON_ID, :V$JOB_ID
    DO
    BEGIN
      INSERT INTO WORKTAB_DATA
      (WORKTAB_ID, PERSON_ID, JOB_ID)
      VALUES (:V$OBJ_ID, :V$PERSON_ID, :V$JOB_ID);
    END
  END
  ELSE
  BEGIN
    -- Избирательный список сотрудников и должностей, причем сотрудник может быть из чужого подразделения
    FOR
      SELECT DISTINCT LP14.PARENT_ID, L15.OBJ_ID
      FROM LINKS L13
      JOIN LINKS L15 ON L15.PARENT_ID = L13.OBJ_ID AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
      LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
      JOIN LINKS LP14 ON LP14.OBJ_ID = L15.OBJ_ID AND LP14.PARENT_TYPE_ID = 14 AND LP14.DATE_DEL IS NULL
      WHERE L13.PARENT_ID = :I$PARENT_ID AND L13.OBJ_TYPE_ID = 13 AND L13.DATE_DEL IS NULL AND V74.VAL IS NULL
      UNION
      SELECT DISTINCT L14.OBJ_ID, L15.OBJ_ID
      FROM LINKS L14
      JOIN LINKS L15 ON L15.PARENT_ID = L14.OBJ_ID AND L15.OBJ_TYPE_ID = 14 AND L15.DATE_DEL IS NULL
      LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
      JOIN LINKS LP13 ON LP13.OBJ_ID = L15.OBJ_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
      -- связку LP13-подразделение не проверяем, может быть из чужого подразделения
      WHERE L14.PARENT_ID = :I$PARENT_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL AND V74.VAL IS NULL
      ORDER BY 1, 2
      INTO :V$PERSON_ID, :V$JOB_ID
    DO
    BEGIN
      INSERT INTO WORKTAB_DATA
      (WORKTAB_ID, PERSON_ID, JOB_ID)
      VALUES (:V$OBJ_ID, :V$PERSON_ID, :V$JOB_ID);
    END
  END

  -- После добавления ведомости за 2 часть месяца - копируем сведения из последней ведомости за 1 часть месяца
  -- только рядовые дни
  IF(V$M2 = 1) THEN
  BEGIN
    INSERT INTO WORKTAB_DATA
    (WORKTAB_ID, PERSON_ID, JOB_ID, COL_INDEX, TYPE_ID, VAL)
    SELECT :V$OBJ_ID, D.PERSON_ID, D.JOB_ID, D.COL_INDEX, D.TYPE_ID, D.VAL
    FROM WORKTAB_DATA D
    -- обязательно кореллируем со списком сотрудников во второй части месяца
    JOIN WORKTAB_DATA D2 ON D2.DATE_DEL IS NULL AND D2.WORKTAB_ID = :V$OBJ_ID AND D2.PERSON_ID = D.PERSON_ID AND D2.JOB_ID = D.JOB_ID AND D2.COL_INDEX IS NULL
    WHERE D.DATE_DEL IS NULL AND D.WORKTAB_ID = :V$M1_ID AND D.COL_INDEX IS NOT NULL AND D.COL_INDEX BETWEEN 1 AND 15;
  END

  -- Заполняем пропуски и замещения при их наличии
  EXECUTE PROCEDURE WORKTAB_UPDATE_EXTRA(:V$OBJ_ID);

  -- Сразу же возвращаем контент ведомости - чтобы открыть форму редактирования
  FOR
    SELECT TAG_NAME, VAL
    FROM WORKTAB_GET(:V$OBJ_ID, :I$USER_ID, NULL)
    INTO :TAG_NAME, VAL
  DO
  BEGIN
    SUSPEND;
  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE WORKTAB_CHANGE (
    I$OBJ_ID BIGINT,
    I$OP VARCHAR(100),
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$DIV_ID BIGINT;
DECLARE VARIABLE V$SEQ BIGINT;
DECLARE VARIABLE V$TMPL_ID BIGINT;
DECLARE VARIABLE V$STATUS_ID BIGINT;
DECLARE VARIABLE V$DATE1 DATE;
DECLARE VARIABLE V$DATE2 DATE;
DECLARE VARIABLE V$EX_PERSON BIGINT;
DECLARE VARIABLE V$RESP_PERSON BIGINT;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$USER_ID BIGINT;
DECLARE VARIABLE V$JT SMALLINT;
DECLARE VARIABLE V$PERSON_ID BIGINT;
DECLARE VARIABLE V$JOB_ID BIGINT;
DECLARE VARIABLE V$FORM_ID BIGINT;
DECLARE VARIABLE V$LEVEL_ID BIGINT;
DECLARE VARIABLE S VARCHAR(4000);
DECLARE VARIABLE T INTEGER;
DECLARE VARIABLE D DATE;
begin

  -- Возможные операции: project, approve, correction
  IF(I$USER_ID = 'Веб-администратор') THEN V$USER_ID = 1; ELSE V$USER_ID = I$USER_ID;

  SELECT FIRST 1 L.PARENT_ID, L.LISTVAL_ID, V3545.VAL, V3550.LISTVAL_ID, V3546.VAL, V3551.VAL, V3547.VAL, V3552.VAL, V3555.VAL
  FROM LINKS L
  JOIN VALR V3545 ON V3545.OBJ_ID = L.OBJ_ID AND V3545.PARAM_ID = 3545 AND V3545.IS_DEL = 0
  JOIN VALL V3550 ON V3550.OBJ_ID = L.OBJ_ID AND V3550.PARAM_ID = 3550 AND V3550.IS_DEL = 0
  JOIN VALD V3546 ON V3546.OBJ_ID = L.OBJ_ID AND V3546.PARAM_ID = 3546 AND V3546.IS_DEL = 0
  JOIN VALD V3551 ON V3551.OBJ_ID = L.OBJ_ID AND V3551.PARAM_ID = 3551 AND V3551.IS_DEL = 0
  LEFT JOIN VALR V3547 ON V3547.OBJ_ID = L.OBJ_ID AND V3547.PARAM_ID = 3547 AND V3547.IS_DEL = 0
  LEFT JOIN VALR V3552 ON V3552.OBJ_ID = L.OBJ_ID AND V3552.PARAM_ID = 3552 AND V3552.IS_DEL = 0
  LEFT JOIN VALS V3555 ON V3555.OBJ_ID = L.OBJ_ID AND V3555.PARAM_ID = 3555 AND V3555.IS_DEL = 0
  WHERE L.OBJ_ID = :I$OBJ_ID AND L.OBJ_TYPE_ID = 519 AND L.PARENT_TYPE_ID IN (2, 211) AND L.DATE_DEL IS NULL
  INTO :V$DIV_ID, :V$SEQ, :V$TMPL_ID, :V$STATUS_ID, :V$DATE1, :V$DATE2, :V$EX_PERSON, :V$RESP_PERSON, :S;

  IF(V$DIV_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Табель не найден или был удален';

  V$OBJ_ID = I$OBJ_ID;

  IF(I$OP = 'project') THEN
  BEGIN
    IF(V$STATUS_ID = 11716) THEN EXCEPTION DATA_ERROR 'Табель уже находится в статусе проекта';

    -- Это обязательно должна быть последняя версия
    IF(EXISTS(
      SELECT FIRST 1 1
      FROM LINKS L
      JOIN VALR V3545 ON V3545.OBJ_ID = L.OBJ_ID AND V3545.PARAM_ID = 3545 AND V3545.IS_DEL = 0 AND V3545.VAL = :V$TMPL_ID
      JOIN VALL V3550 ON V3550.OBJ_ID = L.OBJ_ID AND V3550.PARAM_ID = 3550 AND V3550.IS_DEL = 0 AND V3550.LISTVAL_ID = 11715
      JOIN VALD V3546 ON V3546.OBJ_ID = L.OBJ_ID AND V3546.PARAM_ID = 3546 AND V3546.IS_DEL = 0 AND V3546.VAL = :V$DATE1
      JOIN VALD V3551 ON V3551.OBJ_ID = L.OBJ_ID AND V3551.PARAM_ID = 3551 AND V3551.IS_DEL = 0 AND V3551.VAL = :V$DATE2
      WHERE L.PARENT_ID = :V$DIV_ID AND L.OBJ_TYPE_ID = 519 AND L.DATE_DEL IS NULL AND L.LISTVAL_ID > :V$SEQ
    ))
    THEN
      EXCEPTION DATA_ERROR 'У данного табеля имеется действующая коррекция. В проект можно переводить только последнюю версию';

    SELECT 1 FROM VAL_ADD(3550, :I$OBJ_ID, 11716, :V$USER_ID) INTO :T;
  END
  ELSE IF(I$OP = 'approve') THEN
  BEGIN
    IF(V$STATUS_ID <> 11716) THEN EXCEPTION DATA_ERROR 'Табель уже находится в действующем статусе';

    -- Это обязательно должна быть самая младшая версия
    IF(EXISTS(
      SELECT FIRST 1 1
      FROM LINKS L
      JOIN VALR V3545 ON V3545.OBJ_ID = L.OBJ_ID AND V3545.PARAM_ID = 3545 AND V3545.IS_DEL = 0 AND V3545.VAL = :V$TMPL_ID
      JOIN VALL V3550 ON V3550.OBJ_ID = L.OBJ_ID AND V3550.PARAM_ID = 3550 AND V3550.IS_DEL = 0 AND V3550.LISTVAL_ID = 11716
      JOIN VALD V3546 ON V3546.OBJ_ID = L.OBJ_ID AND V3546.PARAM_ID = 3546 AND V3546.IS_DEL = 0 AND V3546.VAL = :V$DATE1
      JOIN VALD V3551 ON V3551.OBJ_ID = L.OBJ_ID AND V3551.PARAM_ID = 3551 AND V3551.IS_DEL = 0 AND V3551.VAL = :V$DATE2
      WHERE L.PARENT_ID = :V$DIV_ID AND L.OBJ_TYPE_ID = 519 AND L.DATE_DEL IS NULL AND L.LISTVAL_ID < :V$SEQ
    ))
    THEN
      EXCEPTION DATA_ERROR 'В статус действующего может переводиться только самая младшая версия табеля из числа проектов';

    SELECT 1 FROM VAL_ADD(3550, :I$OBJ_ID, 11715, :V$USER_ID) INTO :T;

    -- Переводим табели старше 3 месяцев в статус архив
    D = DATEADD(-3 MONTH TO CURRENT_DATE);
    FOR
      SELECT L.OBJ_ID
      FROM LINKS L
      JOIN VALL V3550 ON V3550.OBJ_ID = L.OBJ_ID AND V3550.PARAM_ID = 3550 AND V3550.IS_DEL = 0 AND V3550.LISTVAL_ID = 11715
      JOIN VALD V3546 ON V3546.OBJ_ID = L.OBJ_ID AND V3546.PARAM_ID = 3546 AND V3546.IS_DEL = 0 AND V3546.VAL < :D
      WHERE L.PARENT_ID = :V$DIV_ID AND L.OBJ_TYPE_ID = 519 AND L.DATE_DEL IS NULL
      ORDER BY 1
      INTO :V$OBJ_ID
    DO
    BEGIN
      SELECT 1 FROM VAL_ADD(3550, :V$OBJ_ID, 14261, :V$USER_ID) INTO :T;
    END
  END
  ELSE IF(I$OP = 'correction') THEN
  BEGIN
    IF(V$STATUS_ID = 11716) THEN EXCEPTION DATA_ERROR 'Коррекцию можно делать только для действующего табеля';

    -- Коррекция делается только для последней версии
    IF(EXISTS(
      SELECT FIRST 1 1
      FROM LINKS L
      JOIN VALR V3545 ON V3545.OBJ_ID = L.OBJ_ID AND V3545.PARAM_ID = 3545 AND V3545.IS_DEL = 0 AND V3545.VAL = :V$TMPL_ID
      JOIN VALL V3550 ON V3550.OBJ_ID = L.OBJ_ID AND V3550.PARAM_ID = 3550 AND V3550.IS_DEL = 0 -- любой статус
      JOIN VALD V3546 ON V3546.OBJ_ID = L.OBJ_ID AND V3546.PARAM_ID = 3546 AND V3546.IS_DEL = 0 AND V3546.VAL = :V$DATE1
      JOIN VALD V3551 ON V3551.OBJ_ID = L.OBJ_ID AND V3551.PARAM_ID = 3551 AND V3551.IS_DEL = 0 AND V3551.VAL = :V$DATE2
      WHERE L.PARENT_ID = :V$DIV_ID AND L.OBJ_TYPE_ID = 519 AND L.DATE_DEL IS NULL AND L.LISTVAL_ID > :V$SEQ
    ))
    THEN
      EXCEPTION DATA_ERROR 'Коррекция может делаться только для последней версии табеля';

    SELECT OBJ_ID FROM OBJECT_ADD(:V$DIV_ID, 519, NULL, :V$SEQ + 1, :V$USER_ID) INTO :V$OBJ_ID;
    SELECT 1 FROM VAL_ADD(3545, :V$OBJ_ID, :V$TMPL_ID) INTO :T;
    SELECT 1 FROM VAL_ADD(3546, :V$OBJ_ID, :V$DATE1) INTO :T;
    SELECT 1 FROM VAL_ADD(3551, :V$OBJ_ID, :V$DATE2) INTO :T;
    SELECT 1 FROM VAL_ADD(3547, :V$OBJ_ID, :V$EX_PERSON) INTO :T;
    SELECT 1 FROM VAL_ADD(3552, :V$OBJ_ID, :V$RESP_PERSON) INTO :T;
    SELECT 1 FROM VAL_ADD(3555, :V$OBJ_ID, :S) INTO :T;

    -- Копируем все строки
    INSERT INTO WORKTAB_DATA
    (WORKTAB_ID, PERSON_ID, JOB_ID, COL_INDEX, TYPE_ID, VAL, COMMENTS)
    SELECT :V$OBJ_ID, D.PERSON_ID, D.JOB_ID, D.COL_INDEX, D.TYPE_ID, D.VAL, D.COMMENTS
    FROM WORKTAB_DATA D
    WHERE D.DATE_DEL IS NULL AND D.WORKTAB_ID = :I$OBJ_ID;
  END
  ELSE IF(I$OP = 'refresh') THEN
  BEGIN
    -- Обновляем данные по дополнительным столбцам
    EXECUTE PROCEDURE WORKTAB_UPDATE_EXTRA(:I$OBJ_ID);
  END
  ELSE
    EXCEPTION DATA_ERROR 'Неизвестное действие ' || COALESCE(I$OP, '???');

  FOR
    SELECT TAG_NAME, VAL
    FROM WORKTAB_GET(:V$OBJ_ID, :I$USER_ID, NULL)
    INTO :TAG_NAME, :VAL
  DO
  BEGIN
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE WORKTAB_DELETE (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
AS
DECLARE VARIABLE V$TMPL_ID BIGINT;
DECLARE VARIABLE V$DIV_ID BIGINT;
DECLARE VARIABLE V$SEQ BIGINT;
DECLARE VARIABLE V$STATUS_ID BIGINT;
DECLARE VARIABLE V$DATE1 DATE;
DECLARE VARIABLE V$DATE2 DATE;
DECLARE VARIABLE V$EX_PERSON BIGINT;
DECLARE VARIABLE V$RESP_PERSON BIGINT;
begin

  SELECT FIRST 1 L.PARENT_ID, L.LISTVAL_ID, V3550.LISTVAL_ID, V3546.VAL, V3551.VAL, V3547.VAL, V3552.VAL, V3545.VAL
  FROM LINKS L
  JOIN VALL V3550 ON V3550.OBJ_ID = L.OBJ_ID AND V3550.PARAM_ID = 3550 AND V3550.IS_DEL = 0
  JOIN VALD V3546 ON V3546.OBJ_ID = L.OBJ_ID AND V3546.PARAM_ID = 3546 AND V3546.IS_DEL = 0
  JOIN VALD V3551 ON V3551.OBJ_ID = L.OBJ_ID AND V3551.PARAM_ID = 3551 AND V3551.IS_DEL = 0
  LEFT JOIN VALR V3547 ON V3547.OBJ_ID = L.OBJ_ID AND V3547.PARAM_ID = 3547 AND V3547.IS_DEL = 0
  LEFT JOIN VALR V3552 ON V3552.OBJ_ID = L.OBJ_ID AND V3552.PARAM_ID = 3552 AND V3552.IS_DEL = 0
  JOIN VALR V3545 ON V3545.OBJ_ID = L.OBJ_ID AND V3545.PARAM_ID = 3545 AND V3545.IS_DEL = 0
  WHERE L.OBJ_ID = :I$OBJ_ID AND L.OBJ_TYPE_ID = 519 AND L.PARENT_TYPE_ID IN (2, 211) AND L.DATE_DEL IS NULL
  INTO :V$DIV_ID, :V$SEQ, :V$STATUS_ID, :V$DATE1, :V$DATE2, :V$EX_PERSON, :V$RESP_PERSON, :V$TMPL_ID;

  IF(V$DIV_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Табель не найден, или был удален';

  IF(V$STATUS_ID <> 11716) THEN EXCEPTION DATA_ERROR 'Можно удалить только табель в статусе проекта';

  -- Нельзя удалять, если есть более поздняя версия
  IF(EXISTS(
    SELECT FIRST 1 1
    FROM LINKS L
    JOIN VALR V3545 ON V3545.OBJ_ID = L.OBJ_ID AND V3545.PARAM_ID = 3545 AND V3545.IS_DEL = 0 AND V3545.VAL = :V$TMPL_ID
    JOIN VALL V3550 ON V3550.OBJ_ID = L.OBJ_ID AND V3550.PARAM_ID = 3550 AND V3550.IS_DEL = 0 AND V3550.LISTVAL_ID = 11715
    JOIN VALD V3546 ON V3546.OBJ_ID = L.OBJ_ID AND V3546.PARAM_ID = 3546 AND V3546.IS_DEL = 0 AND V3546.VAL = :V$DATE1
    JOIN VALD V3551 ON V3551.OBJ_ID = L.OBJ_ID AND V3551.PARAM_ID = 3551 AND V3551.IS_DEL = 0 AND V3551.VAL = :V$DATE2
    WHERE L.PARENT_ID = :V$DIV_ID AND L.OBJ_TYPE_ID = 519 AND L.DATE_DEL IS NULL AND L.LISTVAL_ID > :V$SEQ
  ))
  THEN
    EXCEPTION DATA_ERROR 'У данного табеля имеется коррекция. Можно удалять только последнюю коррекцию в цепочке';

  UPDATE LINKS
  SET DATE_DEL = CURRENT_TIMESTAMP
  WHERE OBJ_ID = :I$OBJ_ID AND DATE_DEL IS NULL;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE WORKTAB_DT_SET (
    I$OBJ_ID BIGINT NOT NULL,
    I$DATE_FROM DATE NOT NULL,
    I$DATE_TO DATE NOT NULL,
    I$USER_ID VARCHAR(40) NOT NULL)
AS
DECLARE VARIABLE D1 DATE;
DECLARE VARIABLE D2 DATE;
DECLARE VARIABLE T INTEGER;
DECLARE VARIABLE V$STATUS BIGINT;
begin

  SELECT V3550.LISTVAL_ID, V3546.VAL, V3551.VAL
  FROM LINKS L519
  JOIN VALL V3550 ON V3550.OBJ_ID = L519.OBJ_ID AND V3550.PARAM_ID = 3550 AND V3550.IS_DEL = 0
  JOIN VALD V3546 ON V3546.OBJ_ID = L519.OBJ_ID AND V3546.PARAM_ID = 3546 AND V3546.IS_DEL = 0
  JOIN VALD V3551 ON V3551.OBJ_ID = L519.OBJ_ID AND V3551.PARAM_ID = 3551 AND V3551.IS_DEL = 0
  WHERE L519.OBJ_ID = :I$OBJ_ID AND L519.PARENT_TYPE_ID IN (2, 211) AND L519.DATE_DEL IS NULL
  INTO :V$STATUS, :D1, :D2;

  IF(V$STATUS IS NULL) THEN EXCEPTION DATA_ERROR 'Табель не найден';
  IF(V$STATUS <> 11716) THEN EXCEPTION DATA_ERROR 'Табель можно менять только в статусе черновика';

  IF(EXTRACT(YEAR FROM D1) <> EXTRACT(YEAR FROM I$DATE_FROM) OR EXTRACT(MONTH FROM D1) <> EXTRACT(MONTH FROM I$DATE_FROM)
    OR EXTRACT(YEAR FROM D1) <> EXTRACT(YEAR FROM I$DATE_TO) OR EXTRACT(MONTH FROM D1) <> EXTRACT(MONTH FROM I$DATE_TO)
  )
  THEN
    EXCEPTION DATA_ERROR 'Даты можно менять только в пределах календарного месяца';

  IF(I$DATE_FROM >= I$DATE_TO) THEN EXCEPTION DATA_ERROR 'Дата начала должна быть строго раньше даты окончания';

  SELECT 1 FROM VAL_ADD(3546, :I$OBJ_ID, :I$DATE_FROM) INTO :T;
  SELECT 1 FROM VAL_ADD(3551, :I$OBJ_ID, :I$DATE_TO) INTO :T;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE WORKTAB_GET (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40),
    I$TM TIMESTAMP = NULL)
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$DIV_ID BIGINT;
DECLARE VARIABLE V$DIV_TYPE BIGINT;
DECLARE VARIABLE V$OU_ID BIGINT;
DECLARE VARIABLE V$EX_PERSON BIGINT;
DECLARE VARIABLE V$RESP_PERSON BIGINT;
DECLARE VARIABLE V$TMPL_ID BIGINT;
DECLARE VARIABLE V$STATUS_ID BIGINT;
DECLARE VARIABLE V$DATE1 DATE;
DECLARE VARIABLE V$DATE2 DATE;
DECLARE VARIABLE V$D DATE;
DECLARE VARIABLE V$SEQ BIGINT;
DECLARE VARIABLE V$ROW_ID BIGINT;
DECLARE VARIABLE V$PERSON_ID BIGINT;
DECLARE VARIABLE V$JOB_ID BIGINT;
DECLARE VARIABLE V$VAL FLOAT;
DECLARE VARIABLE V$RATE FLOAT;
DECLARE VARIABLE V$TYPE_ID BIGINT;
DECLARE VARIABLE V$WEEK BIGINT;
DECLARE VARIABLE T BIGINT;
DECLARE VARIABLE S VARCHAR(400);
DECLARE VARIABLE S2 VARCHAR(400);
DECLARE VARIABLE S3 VARCHAR(400);
begin

  SELECT FIRST 1 L.PARENT_ID, L.PARENT_TYPE_ID, L.LISTVAL_ID, V3545.VAL, V3550.LISTVAL_ID, V3546.VAL, V3551.VAL, V3547.VAL, V3552.VAL
  FROM LINKS L
  JOIN VALR V3545 ON V3545.OBJ_ID = L.OBJ_ID AND V3545.PARAM_ID = 3545 AND V3545.IS_DEL = 0
  JOIN VALL V3550 ON V3550.OBJ_ID = L.OBJ_ID AND V3550.PARAM_ID = 3550 AND V3550.IS_DEL = 0
  JOIN VALD V3546 ON V3546.OBJ_ID = L.OBJ_ID AND V3546.PARAM_ID = 3546 AND V3546.IS_DEL = 0
  JOIN VALD V3551 ON V3551.OBJ_ID = L.OBJ_ID AND V3551.PARAM_ID = 3551 AND V3551.IS_DEL = 0
  LEFT JOIN VALR V3547 ON V3547.OBJ_ID = L.OBJ_ID AND V3547.PARAM_ID = 3547 AND V3547.IS_DEL = 0
  LEFT JOIN VALR V3552 ON V3552.OBJ_ID = L.OBJ_ID AND V3552.PARAM_ID = 3552 AND V3552.IS_DEL = 0
  WHERE L.OBJ_ID = :I$OBJ_ID AND L.OBJ_TYPE_ID = 519 AND L.PARENT_TYPE_ID IN (2, 211) AND L.DATE_DEL IS NULL
  INTO :V$DIV_ID, :V$DIV_TYPE, :V$SEQ, :V$TMPL_ID, :V$STATUS_ID, :V$DATE1, :V$DATE2, :V$EX_PERSON, :V$RESP_PERSON;

  IF(V$DIV_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Табель не найден или был удален';

  IF(V$DIV_TYPE = 2) THEN V$OU_ID = V$DIV_ID;
  ELSE V$OU_ID = (SELECT FIRST 1 L.PARENT_ID FROM LINKS L WHERE L.OBJ_ID = :V$DIV_ID AND L.PARENT_TYPE_ID = 2);

  TAG_NAME = 'dt';
  VAL = (SELECT VAL FROM DATE2ISO(CURRENT_TIMESTAMP));
  SUSPEND;

  TAG_NAME = 'id';
  VAL = I$OBJ_ID;
  SUSPEND;

  TAG_NAME = 'state_id';
  VAL = V$STATUS_ID;
  SUSPEND;

  TAG_NAME = 'div_id';
  VAL = V$DIV_ID;
  SUSPEND;

  TAG_NAME = 'template_id';
  VAL = V$TMPL_ID;
  SUSPEND;

  TAG_NAME = 'template_name';
  VAL = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$TMPL_ID));
  SUSPEND;

  TAG_NAME = 'index';
  VAL = V$SEQ;
  SUSPEND;

  TAG_NAME = 'date_from';
  VAL = (SELECT VAL FROM DATE2ISO(:V$DATE1, 0));
  SUSPEND;

  TAG_NAME = 'date_to';
  VAL = (SELECT VAL FROM DATE2ISO(:V$DATE2, 0));
  SUSPEND;
  TAG_NAME = 'date_to_day';
  VAL = EXTRACT(DAY FROM V$DATE2);
  SUSPEND;
  TAG_NAME = 'date_to_month';
  VAL = EXTRACT(MONTH FROM V$DATE2);
  IF(VAL = '1') THEN VAL = 'января';
  ELSE IF(VAL = '2') THEN VAL = 'февраля';
  ELSE IF(VAL = '3') THEN VAL = 'марта';
  ELSE IF(VAL = '4') THEN VAL = 'апреля';
  ELSE IF(VAL = '5') THEN VAL = 'мая';
  ELSE IF(VAL = '6') THEN VAL = 'июня';
  ELSE IF(VAL = '7') THEN VAL = 'июля';
  ELSE IF(VAL = '8') THEN VAL = 'августа';
  ELSE IF(VAL = '9') THEN VAL = 'сентября';
  ELSE IF(VAL = '10') THEN VAL = 'октября';
  ELSE IF(VAL = '11') THEN VAL = 'ноября';
  ELSE IF(VAL = '12') THEN VAL = 'декабря';
  SUSPEND;
  TAG_NAME = 'date_to_year';
  VAL = EXTRACT(YEAR FROM V$DATE2);
  SUSPEND;

  -- Поля для печатной формы

  TAG_NAME = 'ou_name';
  VAL = (SELECT V.VAL FROM VALS V WHERE V.OBJ_ID = :V$OU_ID AND V.PARAM_ID = 999 AND V.IS_DEL = 0);
  SUSPEND;

  TAG_NAME = 'div_name';
  VAL = (SELECT V.VAL FROM VALS V WHERE V.OBJ_ID = :V$DIV_ID AND V.PARAM_ID IN (1791, 999) AND V.IS_DEL = 0);
  SUSPEND;

  TAG_NAME = 'ex_job';
  VAL = NULL;
  SELECT FIRST 1 V3543.VAL
  FROM LINKS L15
  JOIN VALL V72 ON V72.OBJ_ID = L15.OBJ_ID AND V72.PARAM_ID = 72 AND V72.IS_DEL = 0 AND V72.LISTVAL_ID = 934
  JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0 AND V73.VAL <= :V$DATE2
  LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
  JOIN VALS V3543 ON V3543.OBJ_ID = L15.OBJ_ID AND V3543.PARAM_ID = 3543 AND V3543.IS_DEL = 0
  WHERE L15.PARENT_ID = :V$EX_PERSON AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
    AND (V74.VAL IS NULL OR V74.VAL >= :V$DATE2)
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'ex_name';
  VAL = NULL;
  IF(V$EX_PERSON IS NOT NULL) THEN VAL = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$EX_PERSON));
  SUSPEND;

  TAG_NAME = 'resp_job';
  VAL = NULL;
  SELECT FIRST 1 V3543.VAL
  FROM LINKS L15
  JOIN VALL V72 ON V72.OBJ_ID = L15.OBJ_ID AND V72.PARAM_ID = 72 AND V72.IS_DEL = 0 AND V72.LISTVAL_ID = 934
  JOIN VALD V73 ON V73.OBJ_ID = L15.OBJ_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0 AND V73.VAL <= :V$DATE2
  LEFT JOIN VALD V74 ON V74.OBJ_ID = L15.OBJ_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0
  JOIN VALS V3543 ON V3543.OBJ_ID = L15.OBJ_ID AND V3543.PARAM_ID = 3543 AND V3543.IS_DEL = 0
  WHERE L15.PARENT_ID = :V$RESP_PERSON AND L15.OBJ_TYPE_ID = 15 AND L15.DATE_DEL IS NULL
    AND (V74.VAL IS NULL OR V74.VAL >= :V$DATE2)
  INTO :VAL;
  SUSPEND;

  TAG_NAME = 'resp_name';
  VAL = NULL;
  IF(V$RESP_PERSON IS NOT NULL) THEN VAL = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$RESP_PERSON));
  SUSPEND;

  IF(I$TM IS NULL OR (EXTRACT(YEAR FROM I$TM) <= 2000)) THEN
  BEGIN
    TAG_NAME = 'types::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT C.OBJ_ID, C.TYPE_ID, C.VAL, C.SVAL, C.WANT_HOURS
      FROM WORKTAB_TYPES C
      WHERE C.DATE_DEL IS NULL
      ORDER BY 3
      INTO :V$ROW_ID, :V$TYPE_ID, :S, :S2, :T
    DO
    BEGIN
      TAG_NAME = 'types:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'types:r:id';
      VAL = V$ROW_ID;
      SUSPEND;
      TAG_NAME = 'types:r:type_id';
      VAL = V$TYPE_ID;
      SUSPEND;
      TAG_NAME = 'types:r:value';
      VAL = S;
      SUSPEND;
      TAG_NAME = 'types:r:code';
      VAL = S2;
      SUSPEND;
      TAG_NAME = 'types:r:wh';
      VAL = T;
      SUSPEND;
    END

    -- Расписание праздников и специальных дней
    -- Берем из КУГ, причем год нас не интересует - там все равно конкретные даты
    -- добавляем сюда стандартные выходные, не перекрытые выходными
    TAG_NAME = 'spdays::json&colon;array';
    VAL = 1;
    SUSPEND;
    V$D = V$DATE1;
    WHILE(V$D <= V$DATE2) DO
    BEGIN
      IF(EXTRACT(WEEKDAY FROM V$D) IN (0, 6) AND NOT EXISTS(
        -- не сделан рабочим днем
        SELECT FIRST 1 1
        FROM LINKS L2
        JOIN LINKS L481 ON L481.PARENT_ID = L2.OBJ_ID AND L481.OBJ_TYPE_ID = 481 AND L481.DATE_DEL IS NULL
        JOIN LINKS L486 ON L486.PARENT_ID = L481.OBJ_ID AND L486.OBJ_TYPE_ID = 486 AND L486.DATE_DEL IS NULL
        JOIN VALD V3393 ON V3393.OBJ_ID = L486.OBJ_ID AND V3393.PARAM_ID = 3393 AND V3393.IS_DEL = 0 AND V3393.VAL = :V$D
        JOIN VALL V3394 ON V3394.OBJ_ID = L486.OBJ_ID AND V3394.PARAM_ID = 3394 AND V3394.IS_DEL = 0 AND V3394.LISTVAL_ID = 14235
        WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      )) THEN
      BEGIN
        TAG_NAME = 'spdays:r';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'spdays:r:date';
        VAL = EXTRACT(DAY FROM V$D); -- не дата, а только число месяца
        SUSPEND;
        TAG_NAME = 'spdays:r:type';
        VAL = EXTRACT(WEEKDAY FROM V$D - 1) + 1; -- 1..7 = MON...SUN
        SUSPEND;
      END
      V$D = DATEADD(1 DAY TO V$D);
    END
    FOR
      SELECT V3393.VAL, V3394.LISTVAL_ID
      FROM LINKS L2
      JOIN LINKS L481 ON L481.PARENT_ID = L2.OBJ_ID AND L481.OBJ_TYPE_ID = 481 AND L481.DATE_DEL IS NULL
      JOIN LINKS L486 ON L486.PARENT_ID = L481.OBJ_ID AND L486.OBJ_TYPE_ID = 486 AND L486.DATE_DEL IS NULL
      JOIN VALD V3393 ON V3393.OBJ_ID = L486.OBJ_ID AND V3393.PARAM_ID = 3393 AND V3393.IS_DEL = 0 AND V3393.VAL >= :V$DATE1 AND V3393.VAL <= :V$DATE2
      JOIN VALL V3394 ON V3394.OBJ_ID = L486.OBJ_ID AND V3394.PARAM_ID = 3394 AND V3394.IS_DEL = 0
      WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
      ORDER BY 1
      INTO :V$D, :V$WEEK
    DO
    BEGIN
      TAG_NAME = 'spdays:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'spdays:r:date';
      VAL = EXTRACT(DAY FROM V$D); -- не дата, а только число месяца
      SUSPEND;
      TAG_NAME = 'spdays:r:type';
      VAL = V$WEEK;
      SUSPEND;
    END

    -- Какие дополнительные столбцы настроены в данном табеле
    TAG_NAME = 'columns::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT C.OBJ_ID, C.VAL
      FROM VALS V
      LEFT JOIN STR_TO_ID_LIST(V.VAL) L ON 1 = 1
      LEFT JOIN WORKTAB_COLS C ON C.OBJ_ID = L.ID
      WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 3555 AND V.IS_DEL = 0 AND C.OBJ_ID IS NOT NULL
      ORDER BY C.SORT_INDEX
      INTO :V$ROW_ID, :S
    DO
    BEGIN
      TAG_NAME = 'columns:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'columns:r:id';
      VAL = V$ROW_ID;
      SUSPEND;
      TAG_NAME = 'columns:r:name';
      VAL = S;
      SUSPEND;
    END

    TAG_NAME = 'persons::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT D.OBJ_ID, D.PERSON_ID, D.JOB_ID, C1.CAPTION, COALESCE(V3543.SVAL, V66.SVAL), V273.VAL, V73.VAL, V74.VAL, V71.VAL, V3553.LISTVAL_ID
      FROM WORKTAB_DATA D
      JOIN LINKS LP13 ON LP13.OBJ_ID = D.JOB_ID AND LP13.PARENT_TYPE_ID = 13 AND LP13.DATE_DEL IS NULL
      LEFT JOIN OBJECT_CAPTION_GET(D.PERSON_ID) C1 ON 1 = 1
      LEFT JOIN VALS V3543 ON V3543.OBJ_ID = D.JOB_ID AND V3543.PARAM_ID = 3543 AND V3543.IS_DEL = 0 -- название по трудовой
      LEFT JOIN VALS V66 ON V66.OBJ_ID = LP13.PARENT_ID AND V66.PARAM_ID = 66 AND V66.IS_DEL = 0 -- название должности
      JOIN VALD V73 ON V73.OBJ_ID = D.JOB_ID AND V73.PARAM_ID = 73 AND V73.IS_DEL = 0 -- дата приема
      LEFT JOIN VALD V74 ON V74.OBJ_ID = D.JOB_ID AND V74.PARAM_ID = 74 AND V74.IS_DEL = 0 -- дата увольнения
      LEFT JOIN VALS V273 ON V273.OBJ_ID = D.PERSON_ID AND V273.PARAM_ID = 273 AND V273.IS_DEL = 0 -- табельный номер
      JOIN VALF V71 ON V71.OBJ_ID = D.JOB_ID AND V71.PARAM_ID = 71 AND V71.IS_DEL = 0 -- кол-во ставок
      LEFT JOIN VALL V3553 ON V3553.OBJ_ID = D.JOB_ID AND V3553.PARAM_ID = 3553 AND V3553.IS_DEL = 0 -- режим работы
      WHERE D.DATE_DEL IS NULL AND D.WORKTAB_ID = :I$OBJ_ID AND D.COL_INDEX IS NULL
      ORDER BY 4, 5
      INTO :V$ROW_ID, :V$PERSON_ID, :V$JOB_ID, :S, :S2, :S3, :V$DATE1, :V$DATE2, :V$RATE, :V$WEEK
    DO
    BEGIN
      TAG_NAME = 'persons:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'persons:r:id';
      VAL = V$ROW_ID;
      SUSPEND;
      TAG_NAME = 'persons:r:person_id';
      VAL = V$PERSON_ID;
      SUSPEND;
      TAG_NAME = 'persons:r:job_id';
      VAL = V$JOB_ID;
      SUSPEND;
      TAG_NAME = 'persons:r:name';
      VAL = S;
      SUSPEND;
      TAG_NAME = 'persons:r:job_name';
      VAL = S2;
      SUSPEND;
      TAG_NAME = 'persons:r:job_rate';
      VAL = CAST(V$RATE AS NUMERIC(18, 2));
      VAL = REPLACE(REPLACE(VAL, '.00', ''), '.0', '');
      SUSPEND;
      TAG_NAME = 'persons:r:tabnum';
      VAL = S3;
      SUSPEND;
      TAG_NAME = 'persons:r:date_in';
      VAL = (SELECT VAL FROM DATE2ISO(:V$DATE1, 0));
      SUSPEND;
      TAG_NAME = 'persons:r:date_out';
      VAL = (SELECT VAL FROM DATE2ISO(:V$DATE2, 0));
      SUSPEND;
      TAG_NAME = 'persons:r:week';
      VAL = V$WEEK;
      SUSPEND;
      TAG_NAME = 'persons:r:comments';
      VAL = NULL;
      SELECT FIRST 1 D.COMMENTS
      FROM WORKTAB_DATA D
      WHERE D.DATE_DEL IS NULL AND D.PERSON_ID = :V$PERSON_ID AND D.JOB_ID = :V$JOB_ID AND D.COL_INDEX = 0
      INTO :VAL;
      SUSPEND;

      -- Специальная история для вывода в экспорт
      IF(EXTRACT(YEAR FROM I$TM) <= 2000) THEN
      BEGIN
        TAG_NAME = 'persons:r:values::json&colon;array';
        VAL = 1;
        SUSPEND;
        FOR
          SELECT D.COL_INDEX, D.TYPE_ID, D.VAL, T.SVAL, T.TYPE_ID, T.WANT_HOURS
          FROM WORKTAB_DATA D
          JOIN WORKTAB_TYPES T ON T.OBJ_ID = D.TYPE_ID
          WHERE D.DATE_DEL IS NULL AND D.WORKTAB_ID = :I$OBJ_ID AND D.COL_INDEX IS NOT NULL AND D.PERSON_ID = :V$PERSON_ID AND D.JOB_ID = :V$JOB_ID
          ORDER BY 1, 2, 3
          INTO :V$SEQ, :V$TMPL_ID, :V$VAL, :S, :V$TYPE_ID, :V$WEEK
        DO
        BEGIN
          TAG_NAME = 'persons:r:values:r';
          VAL = NULL;
          SUSPEND;
          TAG_NAME = 'persons:r:values:r:index';
          VAL = V$SEQ;
          SUSPEND;
          TAG_NAME = 'persons:r:values:r:code';
          VAL = S;
          SUSPEND;
          TAG_NAME = 'persons:r:values:r:value';
          VAL = CAST(V$VAL AS NUMERIC(18, 2));
          -- Подчищаем дробную часть
          IF(RIGHT(VAL, 3) = '.00') THEN VAL = REPLACE(VAL, '.00', '');
          ELSE IF(RIGHT(VAL, 1) = '0') THEN VAL = SUBSTRING(VAL FROM 1 FOR CHAR_LENGTH(S) - 1);
          SUSPEND;
          -- Признак для подсчета рабочих дней
          TAG_NAME = 'persons:r:values:r:vt';
          VAL = V$TYPE_ID;
          SUSPEND;
        END
      END
    END
  END

  -- Все остальные данные таблицы в сериализованном виде
  -- сортирвка значений всегда делается в порядке первоначального ввода - по возрастанию id
  TAG_NAME = 'values::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT D.OBJ_ID, D.PERSON_ID, D.JOB_ID, D.COL_INDEX, D.TYPE_ID, D.VAL
    FROM WORKTAB_DATA D
    WHERE D.DATE_DEL IS NULL AND D.WORKTAB_ID = :I$OBJ_ID AND D.COL_INDEX IS NOT NULL AND (:I$TM IS NULL OR D.DATE_MODIFY >= :I$TM)
    ORDER BY 4, 2, 3, 1
    INTO :V$ROW_ID, :V$PERSON_ID, :V$JOB_ID, :V$SEQ, :V$TMPL_ID, :V$VAL
  DO
  BEGIN
    TAG_NAME = 'values:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'values:r:id';
    VAL = V$ROW_ID;
    SUSPEND;
    TAG_NAME = 'values:r:person_id';
    VAL = V$PERSON_ID;
    SUSPEND;
    TAG_NAME = 'values:r:job_id';
    VAL = V$JOB_ID;
    SUSPEND;
    TAG_NAME = 'values:r:col_id';
    VAL = V$SEQ;
    SUSPEND;
    TAG_NAME = 'values:r:type_id';
    VAL = V$TMPL_ID;
    SUSPEND;
    TAG_NAME = 'values:r:value';
    VAL = CAST(V$VAL AS NUMERIC(18, 2));
    SUSPEND;
  END

  IF(I$TM IS NOT NULL AND EXTRACT(YEAR FROM I$TM) > 2000) THEN
  BEGIN
    TAG_NAME = 'values_del::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT D.OBJ_ID, D.PERSON_ID, D.JOB_ID, D.COL_INDEX
      FROM WORKTAB_DATA D
      WHERE D.DATE_DEL >= :I$TM AND D.WORKTAB_ID = :I$OBJ_ID AND D.COL_INDEX IS NOT NULL
      INTO :V$ROW_ID, :V$PERSON_ID, :V$JOB_ID, :V$SEQ
    DO
    BEGIN
      TAG_NAME = 'values_del:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'values_del:r:id';
      VAL = V$ROW_ID;
      SUSPEND;
      TAG_NAME = 'values_del:r:person_id';
      VAL = V$PERSON_ID;
      SUSPEND;
      TAG_NAME = 'values_del:r:job_id';
      VAL = V$JOB_ID;
      SUSPEND;
      TAG_NAME = 'values_del:r:col_id';
      VAL = V$SEQ;
      SUSPEND;
    END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE WORKTAB_PERSON_FIND (
    I$OBJ_ID BIGINT,
    I$NAME VARCHAR(400),
    I$JOB VARCHAR(400))
RETURNS (
    OBJ_ID BIGINT)
AS
begin

  IF(OBJ_ID IS NOT NULL) THEN SUSPEND;

  I$NAME = UPPER(REPLACE(:I$NAME, ' ', ''));
  I$JOB = UPPER(REPLACE(:I$JOB, ' ', ''));

  SELECT FIRST 1 D.OBJ_ID
  FROM WORKTAB_DATA D
  LEFT JOIN OBJECT_CAPTION_GET(D.PERSON_ID) C ON 1 = 1
  LEFT JOIN VALS V3543 ON V3543.OBJ_ID = D.JOB_ID AND V3543.PARAM_ID = 3543 AND V3543.IS_DEL = 0
  WHERE D.WORKTAB_ID = :I$OBJ_ID AND D.DATE_DEL IS NULL AND UPPER(REPLACE(C.CAPTION, ' ', '')) = :I$NAME
    -- тут может висеть хвост с количеством ставок, поэтому проверяем по чистому названию должности
    AND UPPER(REPLACE(V3543.SVAL, ' ', '')) = SUBSTRING(:I$JOB FROM 1 FOR CHAR_LENGTH(REPLACE(V3543.SVAL, ' ', '')))
  INTO :OBJ_ID;

  -- Пробуем только по ФИО, если это уникально
  IF(OBJ_ID IS NULL) THEN
  BEGIN
    SELECT FIRST 1 D.OBJ_ID
    FROM WORKTAB_DATA D
    LEFT JOIN OBJECT_CAPTION_GET(D.PERSON_ID) C ON 1 = 1
    WHERE D.WORKTAB_ID = :I$OBJ_ID AND D.DATE_DEL IS NULL AND UPPER(REPLACE(C.CAPTION, ' ', '')) = :I$NAME
    INTO :OBJ_ID;

    -- Дубликат ?
    IF(OBJ_ID IS NOT NULL AND EXISTS(
      SELECT FIRST 1 1
      FROM WORKTAB_DATA D
      LEFT JOIN OBJECT_CAPTION_GET(D.PERSON_ID) C ON 1 = 1
      WHERE D.WORKTAB_ID = :I$OBJ_ID AND D.DATE_DEL IS NULL AND D.OBJ_ID <> :OBJ_ID AND UPPER(REPLACE(C.CAPTION, ' ', '')) = :I$NAME
    ))
    THEN
      OBJ_ID = NULL;

  END

  IF(OBJ_ID IS NOT NULL) THEN SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE WORKTAB_SETTINGS (
    I$USER_ID VARCHAR(40),
    I$VERIFY SMALLINT = 0)
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$TYPE_ID BIGINT;
DECLARE VARIABLE V$OBJ_ID2 BIGINT;
DECLARE VARIABLE S VARCHAR(1000);
DECLARE VARIABLE S1 VARCHAR(400);
DECLARE VARIABLE S2 VARCHAR(400);
DECLARE VARIABLE V$USERTYPE SMALLINT;
DECLARE VARIABLE V$PERSON_ID BIGINT;
DECLARE VARIABLE V$WH SMALLINT;
begin

  -- I$VERIFY передается при открытии диалога добавления табеля, и проверяются права юзера
  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;
  SELECT FIRST 1 U.USER_TYPE, U.OBJ_ID
  FROM USERS U
  WHERE U.USER_ID = :I$USER_ID
  INTO :V$USERTYPE, :V$PERSON_ID;

  TAG_NAME = 'divs::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L2.OBJ_ID, L2.OBJ_TYPE_ID, C.CAPTION
    FROM LINKS L2
    LEFT JOIN OBJECT_CAPTION_GET(L2.OBJ_ID) C ON 1 = 1
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    UNION
    SELECT L211.OBJ_ID, L211.OBJ_TYPE_ID, C.CAPTION
    FROM LINKS L2
    JOIN LINKS L211 ON L211.PARENT_ID = L2.OBJ_ID AND L211.OBJ_TYPE_ID = 211 AND L211.DATE_DEL IS NULL
    LEFT JOIN OBJECT_CAPTION_GET(L211.OBJ_ID) C ON 1 = 1
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    ORDER BY 2, 3
    INTO :V$OBJ_ID, :V$TYPE_ID, :S
  DO
  BEGIN
    TAG_NAME = 'divs:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'divs:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'divs:r:type_id';
    VAL = V$TYPE_ID;
    SUSPEND;
    TAG_NAME = 'divs:r:name';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'divs:r:items::json&colon;array';
    VAL = NULL;
    SUSPEND;
    FOR
      SELECT L518.OBJ_ID, V3544.VAL, C1.SCAPTION, C2.SCAPTION
      FROM LINKS L518
      JOIN VALS V3544 ON V3544.OBJ_ID = L518.OBJ_ID AND V3544.PARAM_ID = 3544 AND V3544.IS_DEL = 0
      LEFT JOIN VALR V3548 ON V3548.OBJ_ID = L518.OBJ_ID AND V3548.PARAM_ID = 3548 AND V3548.IS_DEL = 0
      LEFT JOIN OBJECT_CAPTION_GET(V3548.VAL) C1 ON V3548.VAL IS NOT NULL
      LEFT JOIN VALR V3549 ON V3549.OBJ_ID = L518.OBJ_ID AND V3549.PARAM_ID = 3549 AND V3549.IS_DEL = 0
      LEFT JOIN OBJECT_CAPTION_GET(V3549.VAL) C2 ON V3549.VAL IS NOT NULL
      WHERE L518.PARENT_ID = :V$OBJ_ID AND L518.OBJ_TYPE_ID = 518 AND L518.DATE_DEL IS NULL
        AND (
          :V$USERTYPE IN (1, 5, 6) -- руководители - всегда
          OR V3548.VAL = :V$PERSON_ID OR V3549.VAL = :V$PERSON_ID -- явно назначенные исполнители
          -- кадровики в своем подразделении
          OR (:V$USERTYPE = 10 AND EXISTS(SELECT FIRST 1 1 FROM LINKS LP WHERE LP.OBJ_ID = :V$PERSON_ID AND LP.PARENT_ID = :V$OBJ_ID AND LP.DATE_DEL IS NULL))
        )
      ORDER BY 2
      INTO :V$OBJ_ID2, :S, :S1, :S2
    DO
    BEGIN
      TAG_NAME = 'divs:r:items:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'divs:r:items:r:id';
      VAL = V$OBJ_ID2;
      SUSPEND;
      TAG_NAME = 'divs:r:items:r:name';
      VAL = S;
      SUSPEND;
      TAG_NAME = 'divs:r:items:r:ex_name';
      VAL = S1;
      SUSPEND;
      TAG_NAME = 'divs:r:items:r:resp_name';
      VAL = S2;
      SUSPEND;
    END
  END

  -- Группы должностей
  TAG_NAME = 'groups::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L509.OBJ_ID, V3497.VAL
    FROM LINKS L2
    JOIN LINKS L509 ON L509.PARENT_ID = L2.OBJ_ID AND L509.OBJ_TYPE_ID = 509 AND L509.DATE_DEL IS NULL
    LEFT JOIN VALS V3497 ON V3497.OBJ_ID = L509.OBJ_ID AND V3497.PARAM_ID = 3497 AND V3497.IS_DEL = 0
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :V$OBJ_ID, :S
  DO
  BEGIN
    TAG_NAME = 'groups:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'groups:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'groups:r:value';
    VAL = S;
    SUSPEND;
  END

  -- Дополнительные столбцы
  TAG_NAME = 'columns::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT C.OBJ_ID, C.SORT_INDEX, C.VAL
    FROM WORKTAB_COLS C
    WHERE C.DATE_DEL IS NULL
    ORDER BY 2
    INTO :V$OBJ_ID, :V$TYPE_ID, :S
  DO
  BEGIN
    TAG_NAME = 'columns:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'columns:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'columns:r:sort_index';
    VAL = V$TYPE_ID;
    SUSPEND;
    TAG_NAME = 'columns:r:value';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'columns:r:readonly';
    VAL = IIF(V$OBJ_ID < 1000000000, 1, 0);
    SUSPEND;
  END

  TAG_NAME = 'types::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT C.OBJ_ID, C.TYPE_ID, C.VAL, C.SVAL, C.WANT_HOURS
    FROM WORKTAB_TYPES C
    WHERE C.DATE_DEL IS NULL
    ORDER BY 3
    INTO :V$OBJ_ID, :V$TYPE_ID, :S, :S1, :V$WH
  DO
  BEGIN
    TAG_NAME = 'types:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'types:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'types:r:type_id';
    VAL = V$TYPE_ID;
    SUSPEND;
    TAG_NAME = 'types:r:value';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'types:r:code';
    VAL = S1;
    SUSPEND;
    TAG_NAME = 'types:r:want_hours';
    VAL = V$WH;
    SUSPEND;
    TAG_NAME = 'types:r:readonly';
    VAL = IIF(V$OBJ_ID < 1000000000, 1, 0);
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE WORKTAB_SETTINGS_DEL (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
AS
DECLARE VARIABLE V$LINK_ID BIGINT;
DECLARE VARIABLE V$PARENT_ID BIGINT;
begin

  -- Нет ли завязок на данный вид ведомости в статусе проекта ?
  SELECT FIRST 1 L.LINK_ID, L.PARENT_ID
  FROM LINKS L
  WHERE L.OBJ_ID = :I$OBJ_ID AND L.PARENT_TYPE_ID IN (2, 211) AND L.DATE_DEL IS NULL
  INTO :V$LINK_ID, V$PARENT_ID;

  IF(V$LINK_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Запись не найдена или была удалена';

  IF(EXISTS(
    SELECT FIRST 1 1
    FROM LINKS L519
    JOIN VALR V3545 ON V3545.OBJ_ID = L519.OBJ_ID AND V3545.PARAM_ID = 3545 AND V3545.IS_DEL = 0 AND V3545.VAL = :I$OBJ_ID
    JOIN VALL V3550 ON V3550.OBJ_ID = L519.OBJ_ID AND V3550.PARAM_ID = 3550 AND V3550.IS_DEL = 0 AND V3550.LISTVAL_ID = 11716
    WHERE L519.PARENT_ID = :V$PARENT_ID AND L519.OBJ_TYPE_ID = 519 AND L519.DATE_DEL IS NULL
  ))
  THEN
    EXCEPTION DATA_ERROR 'В систему внесен проект ведомости данного типа, его следует удалить вручную';

  UPDATE LINKS
  SET DATE_DEL = CURRENT_TIMESTAMP
  WHERE LINK_ID = :V$LINK_ID;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE WORKTAB_SETTINGS_GET (
    I$PARENT_ID BIGINT NOT NULL,
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$OU_ID BIGINT;
DECLARE VARIABLE S VARCHAR(1000);
DECLARE VARIABLE S1 VARCHAR(1000);
DECLARE VARIABLE S2 VARCHAR(1000);
DECLARE VARIABLE V$ID1 BIGINT;
DECLARE VARIABLE V$ID2 BIGINT;
begin

  SELECT FIRST 1 L518.OBJ_ID, V3544.VAL, C1.SCAPTION, C2.SCAPTION, V3548.VAL, V3549.VAL
  FROM LINKS L518
  JOIN VALS V3544 ON V3544.OBJ_ID = L518.OBJ_ID AND V3544.PARAM_ID = 3544 AND V3544.IS_DEL = 0
  LEFT JOIN VALR V3548 ON V3548.OBJ_ID = L518.OBJ_ID AND V3548.PARAM_ID = 3548 AND V3548.IS_DEL = 0
  LEFT JOIN OBJECT_CAPTION_GET(V3548.VAL) C1 ON V3548.VAL IS NOT NULL
  LEFT JOIN VALR V3549 ON V3549.OBJ_ID = L518.OBJ_ID AND V3549.PARAM_ID = 3549 AND V3549.IS_DEL = 0
  LEFT JOIN OBJECT_CAPTION_GET(V3549.VAL) C2 ON V3549.VAL IS NOT NULL
  WHERE L518.PARENT_ID = :I$PARENT_ID AND L518.OBJ_TYPE_ID = 518 AND L518.OBJ_ID = :I$OBJ_ID AND L518.DATE_DEL IS NULL
  INTO :V$OBJ_ID, :S, :S1, :S2, :V$ID1, :V$ID2;

  IF(I$OBJ_ID IS NOT NULL AND V$OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Запись не найдена или была удалена';

  SELECT FIRST 1 L2.OBJ_ID
  FROM LINKS L2
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$OU_ID;

  TAG_NAME = 'id';
  VAL = I$OBJ_ID;
  SUSPEND;

  TAG_NAME = 'name';
  VAL = S;
  SUSPEND;

  TAG_NAME = 'div_id';
  VAL = I$PARENT_ID;
  SUSPEND;

  TAG_NAME = 'div_name';
  VAL = (SELECT CAPTION FROM OBJECT_CAPTION_GET(:I$PARENT_ID));
  SUSPEND;

  TAG_NAME = 'ex_person:selection::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L.OBJ_ID, L.CAPTION
    FROM EMPLOYEES_LIST(:V$OU_ID) L
    UNION
    SELECT :V$ID1, C.CAPTION
    FROM RDB$DATABASE
    LEFT JOIN OBJECT_CAPTION_GET(:V$ID1) C ON 1 = 1
    WHERE :V$ID1 IS NOT NULL
    ORDER BY 2
    INTO :V$OBJ_ID, :S
  DO
  BEGIN
    TAG_NAME = 'ex_person:selection:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'ex_person:selection:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'ex_person:selection:r:value';
    VAL = S;
    SUSPEND;
  END
  TAG_NAME = 'ex_person:values:value';
  VAL = V$ID1;
  SUSPEND;

  TAG_NAME = 'resp_person:selection::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L.OBJ_ID, L.CAPTION
    FROM EMPLOYEES_LIST(:V$OU_ID) L
    UNION
    SELECT :V$ID2, C.CAPTION
    FROM RDB$DATABASE
    LEFT JOIN OBJECT_CAPTION_GET(:V$ID2) C ON 1 = 1
    WHERE :V$ID2 IS NOT NULL
    ORDER BY 2
    INTO :V$OBJ_ID, :S
  DO
  BEGIN
    TAG_NAME = 'resp_person:selection:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'resp_person:selection:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'resp_person:selection:r:value';
    VAL = S;
    SUSPEND;
  END
  TAG_NAME = 'resp_person:values:value';
  VAL = V$ID2;
  SUSPEND;

  -- Уже выбранные должности и сотрудники
  -- В составе должностей опция "все"
  TAG_NAME = 'job_selected::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L13.OBJ_ID
    FROM LINKS L13
    LEFT JOIN OBJECT_CAPTION_GET(L13.OBJ_ID) C ON 1 = 1
    WHERE L13.PARENT_ID = :I$OBJ_ID AND L13.OBJ_TYPE_ID IN (13, 2, 211) AND L13.DATE_DEL IS NULL
    INTO :V$ID1
  DO
  BEGIN
    TAG_NAME = 'job_selected:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'job_selected:r:id';
    VAL = V$ID1;
    SUSPEND;
  END
  TAG_NAME = 'persons_selected::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L14.OBJ_ID
    FROM LINKS L14
    LEFT JOIN OBJECT_CAPTION_GET(L14.OBJ_ID) C ON 1 = 1
    WHERE L14.PARENT_ID = :I$OBJ_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
    INTO :V$ID1
  DO
  BEGIN
    TAG_NAME = 'persons_selected:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'persons_selected:r:id';
    VAL = V$ID1;
    SUSPEND;
  END

  -- Доступные для выбора должности и сотрудники - только в данном подразделении
  TAG_NAME = 'job_avail::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT :I$PARENT_ID, 0, 'Все должности'
    FROM RDB$DATABASE
    WHERE 1 = 1
    UNION
    SELECT L13.OBJ_ID, 1, C.CAPTION
    FROM LINKS L13
    LEFT JOIN OBJECT_CAPTION_GET(L13.OBJ_ID) C ON 1 = 1
    WHERE L13.PARENT_ID = :I$PARENT_ID AND L13.OBJ_TYPE_ID = 13 AND L13.DATE_DEL IS NULL
    ORDER BY 2, 3
    INTO :V$OBJ_ID, :V$ID1, :S
  DO
  BEGIN
    TAG_NAME = 'job_avail:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'job_avail:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'job_avail:r:default';
    VAL = IIF(V$ID1 = 0, 1, 0);
    SUSPEND;
    TAG_NAME = 'job_avail:r:value';
    VAL = S;
    SUSPEND;
  END
  TAG_NAME = 'persons_avail::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L14.OBJ_ID, C.CAPTION
    FROM LINKS L14
    LEFT JOIN OBJECT_CAPTION_GET(L14.OBJ_ID) C ON 1 = 1
    WHERE L14.PARENT_ID = :I$PARENT_ID AND L14.OBJ_TYPE_ID = 14 AND L14.DATE_DEL IS NULL
    ORDER BY 2
    INTO :V$OBJ_ID, :S
  DO
  BEGIN
    TAG_NAME = 'persons_avail:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'persons_avail:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'persons_avail:r:value';
    VAL = S;
    SUSPEND;
  END

  TAG_NAME = 'columns_selected::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L.ID
    FROM VALS V
    LEFT JOIN STR_TO_ID_LIST(V.VAL) L ON 1 = 1
    WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 3554 AND V.IS_DEL = 0
    INTO :V$OBJ_ID
  DO
  BEGIN
    TAG_NAME = 'columns_selected:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'columns_selected:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
  END
  TAG_NAME = 'columns_avail::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT C.OBJ_ID, C.VAL
    FROM WORKTAB_COLS C
    WHERE C.DATE_DEL IS NULL
    ORDER BY C.SORT_INDEX
    INTO :V$OBJ_ID, :S
  DO
  BEGIN
    TAG_NAME = 'columns_avail:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'columns_avail:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'columns_avail:r:value';
    VAL = S;
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE WORKTAB_SETTINGS_SET (
    I$PARENT_ID BIGINT,
    I$OBJ_ID BIGINT,
    I$NAME VARCHAR(400),
    I$EX_PERSON BIGINT,
    I$RESP_PERSON BIGINT,
    I$JOBS VARCHAR(4000),
    I$PERSONS VARCHAR(4000),
    I$COLUMNS VARCHAR(1000),
    I$USER_ID VARCHAR(40))
RETURNS (
    OBJ_ID BIGINT)
AS
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$ID1 BIGINT;
DECLARE VARIABLE V$ID2 BIGINT;
DECLARE VARIABLE S VARCHAR(4000);
DECLARE VARIABLE V$DT TIMESTAMP;
begin

  SELECT FIRST 1 L518.OBJ_ID, V3548.VAL, V3548.VAL, V3549.VAL
  FROM LINKS L518
  JOIN VALS V3544 ON V3544.OBJ_ID = L518.OBJ_ID AND V3544.PARAM_ID = 3544 AND V3544.IS_DEL = 0
  LEFT JOIN VALR V3548 ON V3548.OBJ_ID = L518.OBJ_ID AND V3548.PARAM_ID = 3548 AND V3548.IS_DEL = 0
  LEFT JOIN VALR V3549 ON V3549.OBJ_ID = L518.OBJ_ID AND V3549.PARAM_ID = 3549 AND V3549.IS_DEL = 0
  WHERE L518.PARENT_ID = :I$PARENT_ID AND L518.OBJ_TYPE_ID = 518 AND L518.OBJ_ID = :I$OBJ_ID AND L518.DATE_DEL IS NULL
  INTO :V$OBJ_ID, :S, :V$ID1, :V$ID2;

  IF(I$OBJ_ID IS NOT NULL AND V$OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Запись не найдена или была удалена';
  IF(CHAR_LENGTH(:I$NAME) < 3) THEN EXCEPTION DATA_ERROR 'Наименование должно быть не менее 3 символов';

  OBJ_ID = I$OBJ_ID;
  IF(OBJ_ID IS NULL) THEN
  BEGIN
    SELECT OBJ_ID FROM OBJECT_ADD(:I$PARENT_ID, 518) INTO :OBJ_ID;
  END

  IF(I$NAME <> COALESCE(S, '')) THEN SELECT 1 FROM VAL_ADD(3544, :OBJ_ID, :I$NAME) INTO :V$OBJ_ID;
  IF(COALESCE(I$EX_PERSON, 0) <> COALESCE(:V$ID1, 0)) THEN SELECT 1 FROM VAL_ADD(3548, :OBJ_ID, :I$EX_PERSON) INTO :V$OBJ_ID;
  IF(COALESCE(I$RESP_PERSON, 0) <> COALESCE(:V$ID2, 0)) THEN SELECT 1 FROM VAL_ADD(3549, :OBJ_ID, :I$RESP_PERSON) INTO :V$OBJ_ID;

  -- Новые должности
  -- Тут же опция "все"
  FOR
    SELECT ID
    FROM STR_TO_ID_LIST(:I$JOBS)
    INTO :V$ID1
  DO
  BEGIN
    V$OBJ_ID = NULL;
    SELECT FIRST 1 L.LINK_ID, L.DATE_DEL
    FROM LINKS L
    WHERE L.PARENT_ID = :OBJ_ID AND L.OBJ_ID = :V$ID1 AND L.OBJ_TYPE_ID IN (13, 2, 211)
    ORDER BY 2 NULLS FIRST
    INTO :V$OBJ_ID, :V$DT;

    IF(V$DT IS NOT NULL) THEN
      UPDATE LINKS SET DATE_DEL = NULL WHERE LINK_ID = :V$OBJ_ID;
    ELSE IF(V$OBJ_ID IS NULL) THEN
      SELECT 1 FROM OBJECT_ADD_LINK(:OBJ_ID, :V$ID1, 13) INTO :V$OBJ_ID;
  END

  -- Удаленные должности
  FOR
    SELECT L.LINK_ID
    FROM LINKS L
    LEFT JOIN STR_TO_ID_LIST(:I$JOBS) LL ON LL.ID = L.OBJ_ID
    WHERE L.PARENT_ID = :OBJ_ID AND L.OBJ_TYPE_ID IN (13, 2, 211) AND L.DATE_DEL IS NULL AND LL.ID IS NULL
    ORDER BY 1
    INTO :V$OBJ_ID
  DO
  BEGIN
    UPDATE LINKS SET DATE_DEL = CURRENT_TIMESTAMP WHERE LINK_ID = :V$OBJ_ID;
  END

  -- Новые сотрудники
  FOR
    SELECT ID
    FROM STR_TO_ID_LIST(:I$PERSONS)
    INTO :V$ID1
  DO
  BEGIN
    V$OBJ_ID = NULL;
    SELECT FIRST 1 L.LINK_ID, L.DATE_DEL
    FROM LINKS L
    WHERE L.PARENT_ID = :OBJ_ID AND L.OBJ_ID = :V$ID1 AND L.OBJ_TYPE_ID = 14
    ORDER BY 2 NULLS FIRST
    INTO :V$OBJ_ID, :V$DT;

    IF(V$DT IS NOT NULL) THEN
      UPDATE LINKS SET DATE_DEL = NULL WHERE LINK_ID = :V$OBJ_ID;
    ELSE IF(V$OBJ_ID IS NULL) THEN
      SELECT 1 FROM OBJECT_ADD_LINK(:OBJ_ID, :V$ID1, 14) INTO :V$OBJ_ID;
  END

  -- Удаленные сотрудники
  FOR
    SELECT L.LINK_ID
    FROM LINKS L
    LEFT JOIN STR_TO_ID_LIST(:I$PERSONS) LL ON LL.ID = L.OBJ_ID
    WHERE L.PARENT_ID = :OBJ_ID AND L.OBJ_TYPE_ID = 14 AND L.DATE_DEL IS NULL AND LL.ID IS NULL
    ORDER BY 1
    INTO :V$OBJ_ID
  DO
  BEGIN
    UPDATE LINKS SET DATE_DEL = CURRENT_TIMESTAMP WHERE LINK_ID = :V$OBJ_ID;
  END

  -- Столбцы - сохраняем в виде строки с разделителем запятая, но проверяем что указаны живые столбцы
  FOR
    SELECT L.ID
    FROM STR_TO_ID_LIST(:I$COLUMNS) L
    LEFT JOIN WORKTAB_COLS C ON C.OBJ_ID = L.ID
    WHERE C.OBJ_ID IS NULL
    INTO :V$ID1
  DO
  BEGIN
    EXCEPTION DATA_ERROR 'В списке дополнительных столбцов указан удаленный или несуществующий #' || V$ID1;
  END

  SELECT 1 FROM VAL_ADD(3554, :OBJ_ID, :I$COLUMNS) INTO :V$ID1;

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE WORKTAB_SET_COL_DEL (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
AS
begin

  IF(I$USER_ID <> 'Веб-администратор') THEN EXCEPTION DATA_ERROR 'Только веб-администратор может изменять справочники';

  IF(I$OBJ_ID < 1000000000 AND NOT EXISTS(SELECT 1 FROM GEN WHERE GEN = 0)) THEN EXCEPTION DATA_ERROR 'Нельзя изменять системные записи';

  -- Нельзя удалять колонки, если они где-то упомянуты ?

  UPDATE WORKTAB_COLS
  SET DATE_DEL = CURRENT_TIMESTAMP
  WHERE OBJ_ID = :I$OBJ_ID AND DATE_DEL IS NULL;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE WORKTAB_SET_COL_GET (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$SI INTEGER;
DECLARE VARIABLE S VARCHAR(1000);
DECLARE VARIABLE V$GEN BIGINT;
begin

  SELECT C.OBJ_ID, C.SORT_INDEX, C.VAL
  FROM WORKTAB_COLS C
  WHERE C.DATE_DEL IS NULL AND C.OBJ_ID = :I$OBJ_ID
  INTO :V$OBJ_ID, :V$SI, :S;

  IF(I$OBJ_ID IS NOT NULL AND V$OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Запись не найдена или была удалена';

  V$GEN = (SELECT GEN FROM GEN);

  TAG_NAME = 'id';
  VAL = V$OBJ_ID;
  SUSPEND;
  TAG_NAME = 'sort_index';
  VAL = V$SI;
  SUSPEND;
  TAG_NAME = 'value';
  VAL = S;
  SUSPEND;
  TAG_NAME = 'readonly';
  VAL = IIF(V$OBJ_ID < 1000000000 AND V$GEN <> 0, 1, 0);
  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE WORKTAB_SET_COL_SET (
    I$OBJ_ID BIGINT,
    I$VALUE VARCHAR(100),
    I$SORT_INDEX SMALLINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    OBJ_ID BIGINT)
AS
begin

  IF(I$USER_ID <> 'Веб-администратор') THEN EXCEPTION DATA_ERROR 'Только веб-администратор может изменять справочники';

  IF(I$SORT_INDEX IS NULL) THEN
  BEGIN
    SELECT MAX(W.SORT_INDEX) + 1
    FROM WORKTAB_COLS W
    WHERE W.DATE_DEL IS NULL AND W.OBJ_ID <> COALESCE(:I$OBJ_ID, 0)
    INTO :I$SORT_INDEX;

    IF(I$SORT_INDEX IS NULL) THEN I$SORT_INDEX = 0;
  END

  IF(I$OBJ_ID IS NULL) THEN
  BEGIN
    INSERT INTO WORKTAB_COLS
    (VAL, SORT_INDEX)
    VALUES (:I$VALUE, :I$SORT_INDEX)
    RETURNING OBJ_ID INTO :OBJ_ID;
  END
  ELSE
  BEGIN
    SELECT FIRST 1 W.OBJ_ID
    FROM WORKTAB_COLS W
    WHERE W.OBJ_ID = :I$OBJ_ID AND W.DATE_DEL IS NULL
    INTO :OBJ_ID;

    IF(OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Запись не найдена или была удалена';
    IF(I$OBJ_ID < 1000000000 AND NOT EXISTS(SELECT 1 FROM GEN WHERE GEN = 0)) THEN EXCEPTION DATA_ERROR 'Нельзя изменять системные записи';

    UPDATE WORKTAB_COLS
    SET VAL = :I$VALUE, SORT_INDEX = :I$SORT_INDEX
    WHERE OBJ_ID = :I$OBJ_ID;
  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE WORKTAB_SET_GROUP_DEL (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
AS
begin

  IF(I$USER_ID <> 'Веб-администратор') THEN EXCEPTION DATA_ERROR 'Только веб-администратор может изменять справочники';

  IF(I$OBJ_ID < 1000000000 AND NOT EXISTS(SELECT 1 FROM GEN WHERE GEN = 0)) THEN EXCEPTION DATA_ERROR 'Нельзя изменять системные записи';

  -- Нельзя удалять группы, если они где-то упомянуты ?

  UPDATE LINKS
  SET DATE_DEL = CURRENT_TIMESTAMP
  WHERE OBJ_ID = :I$OBJ_ID AND OBJ_TYPE_ID = 509 AND PARENT_TYPE_ID = 2 AND DATE_DEL IS NULL;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE WORKTAB_SET_GROUP_GET (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE S VARCHAR(1000);
DECLARE VARIABLE V$GEN BIGINT;
begin

  SELECT L509.OBJ_ID, V3497.VAL
  FROM LINKS L509
  LEFT JOIN VALS V3497 ON V3497.OBJ_ID = L509.OBJ_ID AND V3497.PARAM_ID = 3497 AND V3497.IS_DEL = 0
  WHERE L509.DATE_DEL IS NULL AND L509.OBJ_ID = :I$OBJ_ID AND L509.PARENT_TYPE_ID = 2
  INTO :V$OBJ_ID, :S;

  IF(I$OBJ_ID IS NOT NULL AND V$OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Запись не найдена или была удалена';

  V$GEN = (SELECT GEN FROM GEN);

  TAG_NAME = 'id';
  VAL = V$OBJ_ID;
  SUSPEND;
  TAG_NAME = 'value';
  VAL = S;
  SUSPEND;
  TAG_NAME = 'readonly';
  VAL = IIF(V$OBJ_ID < 1000000000 AND V$GEN <> 0, 1, 0);
  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE WORKTAB_SET_GROUP_SET (
    I$OBJ_ID BIGINT,
    I$VALUE VARCHAR(1000),
    I$USER_ID VARCHAR(40))
RETURNS (
    OBJ_ID BIGINT)
AS
DECLARE VARIABLE V$OU_ID BIGINT;
begin

  IF(I$USER_ID <> 'Веб-администратор') THEN EXCEPTION DATA_ERROR 'Только веб-администратор может изменять справочники';

  I$VALUE = TRIM(I$VALUE);
  IF(I$VALUE IS NULL OR I$VALUE = '') THEN EXCEPTION DATA_ERROR 'Нельзя вносить группу с пустым названием';

  SELECT FIRST 1 L2.OBJ_ID
  FROM LINKS L2
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$OU_ID;

  IF(V$OU_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Сначала должна быть внесена организация';

  IF(I$OBJ_ID IS NULL) THEN
  BEGIN
    SELECT OBJ_ID FROM OBJECT_ADD_WITH_PARAM(:V$OU_ID, NULL, 509, 3497, :I$VALUE) INTO :OBJ_ID;
  END
  ELSE
  BEGIN
    SELECT FIRST 1 L509.OBJ_ID
    FROM LINKS L509
    WHERE L509.OBJ_ID = :I$OBJ_ID AND L509.PARENT_ID = :V$OU_ID AND L509.OBJ_TYPE_ID = 509 AND L509.DATE_DEL IS NULL
    INTO :OBJ_ID;

    IF(OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Запись не найдена или была удалена';
    IF(I$OBJ_ID < 1000000000 AND NOT EXISTS(SELECT 1 FROM GEN WHERE GEN = 0)) THEN EXCEPTION DATA_ERROR 'Нельзя изменять системные записи';

    SELECT 1 FROM VAL_ADD(3497, :OBJ_ID, :I$VALUE) INTO :V$OU_ID;
  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE WORKTAB_SET_TYPE_DEL (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
AS
begin

  IF(I$USER_ID <> 'Веб-администратор') THEN EXCEPTION DATA_ERROR 'Только веб-администратор может изменять справочники';

  IF(I$OBJ_ID < 1000000000 AND NOT EXISTS(SELECT 1 FROM GEN WHERE GEN = 0)) THEN EXCEPTION DATA_ERROR 'Нельзя изменять системные записи';

  -- Нельзя удалять типы записей, которые были использованы ?

  UPDATE WORKTAB_TYPES
  SET DATE_DEL = CURRENT_TIMESTAMP
  WHERE OBJ_ID = :I$OBJ_ID AND DATE_DEL IS NULL;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE WORKTAB_SET_TYPE_GET (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$TYPE_ID INTEGER;
DECLARE VARIABLE S VARCHAR(1000);
DECLARE VARIABLE SC VARCHAR(400);
DECLARE VARIABLE V$WH INTEGER;
DECLARE VARIABLE V$GEN BIGINT;
begin

  SELECT C.OBJ_ID, C.TYPE_ID, C.VAL, C.SVAL, C.WANT_HOURS
  FROM WORKTAB_TYPES C
  WHERE C.DATE_DEL IS NULL AND C.OBJ_ID = :I$OBJ_ID
  INTO :V$OBJ_ID, :V$TYPE_ID, :S, :SC, :V$WH;

  IF(I$OBJ_ID IS NOT NULL AND V$OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Запись не найдена или была удалена';

  V$GEN = (SELECT GEN FROM GEN);

  TAG_NAME = 'id';
  VAL = V$OBJ_ID;
  SUSPEND;
  TAG_NAME = 'value';
  VAL = S;
  SUSPEND;
  TAG_NAME = 'code';
  VAL = SC;
  SUSPEND;
  TAG_NAME = 'type_id:values:value';
  VAL = V$TYPE_ID;
  SUSPEND;
  TAG_NAME = 'type_id:selection::json&colon;array';
  VAL = 1;
  SUSPEND;
    TAG_NAME = 'type_id:selection:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'type_id:selection:r:id';
    VAL = 0;
    SUSPEND;
    TAG_NAME = 'type_id:selection:r:value';
    VAL = 'Переработка';
    SUSPEND;
    TAG_NAME = 'type_id:selection:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'type_id:selection:r:id';
    VAL = 1;
    SUSPEND;
    TAG_NAME = 'type_id:selection:r:value';
    VAL = 'Недоработка';
    SUSPEND;
  TAG_NAME = 'want_hours:values:value';
  VAL = V$WH;
  SUSPEND;
  TAG_NAME = 'want_hours:selection::json&colon;array';
  VAL = 1;
  SUSPEND;
    TAG_NAME = 'want_hours:selection:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'want_hours:selection:r:id';
    VAL = 0;
    SUSPEND;
    TAG_NAME = 'want_hours:selection:r:value';
    VAL = 'Часы или целый день';
    SUSPEND;
    TAG_NAME = 'want_hours:selection:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'want_hours:selection:r:id';
    VAL = 1;
    SUSPEND;
    TAG_NAME = 'want_hours:selection:r:value';
    VAL = 'Обязательно часы';
    SUSPEND;
    TAG_NAME = 'want_hours:selection:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'want_hours:selection:r:id';
    VAL = 2;
    SUSPEND;
    TAG_NAME = 'want_hours:selection:r:value';
    VAL = 'Обязательно целый день';
    SUSPEND;
  TAG_NAME = 'readonly';
  VAL = IIF(V$OBJ_ID < 1000000000 AND V$GEN <> 0, 1, 0);
  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE WORKTAB_SET_TYPE_SET (
    I$OBJ_ID BIGINT,
    I$VALUE VARCHAR(1000),
    I$CODE VARCHAR(10),
    I$TYPE_ID SMALLINT,
    I$WANT_HOURS SMALLINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    OBJ_ID BIGINT)
AS
begin

  IF(I$USER_ID <> 'Веб-администратор') THEN EXCEPTION DATA_ERROR 'Только веб-администратор может изменять справочники';

  IF(I$OBJ_ID IS NULL) THEN
  BEGIN
    INSERT INTO WORKTAB_TYPES
    (VAL, SVAL, TYPE_ID, WANT_HOURS)
    VALUES (:I$VALUE, :I$CODE, :I$TYPE_ID, :I$WANT_HOURS)
    RETURNING OBJ_ID INTO :OBJ_ID;
  END
  ELSE
  BEGIN
    SELECT FIRST 1 W.OBJ_ID
    FROM WORKTAB_TYPES W
    WHERE W.OBJ_ID = :I$OBJ_ID AND W.DATE_DEL IS NULL
    INTO :OBJ_ID;

    IF(OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Запись не найдена или была удалена';
    IF(I$OBJ_ID < 1000000000 AND NOT EXISTS(SELECT 1 FROM GEN WHERE GEN = 0)) THEN EXCEPTION DATA_ERROR 'Нельзя изменять системные записи';

    -- Поле типа после создания записи изменению не подлежит

    UPDATE WORKTAB_TYPES
    SET VAL = :I$VALUE, SVAL = :I$CODE, WANT_HOURS = :I$WANT_HOURS
    WHERE OBJ_ID = :I$OBJ_ID;
  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE WORKTAB_UPDATE_EXTRA (
    I$OBJ_ID BIGINT)
AS
DECLARE VARIABLE V$COLS VARCHAR(2000);
DECLARE VARIABLE V$COL_ID BIGINT;
DECLARE VARIABLE V$PERSON_ID BIGINT;
DECLARE VARIABLE V$JOB_ID BIGINT;
DECLARE VARIABLE V$DATE1 DATE;
DECLARE VARIABLE V$DATE2 DATE;
DECLARE VARIABLE V$CJT SMALLINT;
DECLARE VARIABLE V$STAGE1 BIGINT;
DECLARE VARIABLE V$STAGE2 BIGINT;
DECLARE VARIABLE V$STAGE3 BIGINT;
DECLARE VARIABLE V$STAGE4 BIGINT;
DECLARE VARIABLE V$STAGE5 BIGINT;
DECLARE VARIABLE V FLOAT;
DECLARE VARIABLE V$PREV_V FLOAT;
DECLARE VARIABLE V$PREV_PERSON BIGINT;
DECLARE VARIABLE V$FORM_ID BIGINT;
DECLARE VARIABLE V$OBJ_ID BIGINT;
begin

  SELECT V.VAL
  FROM VALS V
  WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 3555 AND V.IS_DEL = 0
  INTO :V$COLS;

  SELECT V.VAL
  FROM VALD V
  WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 3546 AND V.IS_DEL = 0
  INTO :V$DATE1;

  SELECT V.VAL
  FROM VALD V
  WHERE V.OBJ_ID = :I$OBJ_ID AND V.PARAM_ID = 3551 AND V.IS_DEL = 0
  INTO :V$DATE2;

  V$PREV_PERSON = 0;
  FOR
    SELECT C.ID, D.PERSON_ID, D.JOB_ID
    FROM STR_TO_ID_LIST(:V$COLS) C
    JOIN WORKTAB_COLS CC ON CC.OBJ_ID = C.ID AND CC.DATE_DEL IS NULL
    JOIN WORKTAB_DATA D ON D.DATE_DEL IS NULL AND D.COL_INDEX IS NULL AND D.WORKTAB_ID = :I$OBJ_ID
    WHERE C.ID >= 8 AND C.ID <= 21 -- по кодам пропусков и замещений
    -- по идее сортировать надо по основности должности
    ORDER BY 1, 2
    INTO :V$COL_ID, :V$PERSON_ID, :V$JOB_ID
  DO
  BEGIN
    V$STAGE1 = NULL;
    V$STAGE2 = NULL;
    V$STAGE3 = NULL;
    V$STAGE4 = NULL;
    V$STAGE5 = NULL;
    V$FORM_ID = NULL;
    IF(V$COL_ID IN (8, 9, 10, 15, 16, 17)) THEN
    BEGIN
      -- Общеобразовательный
      V$CJT = 0;
      IF(V$COL_ID IN (8, 15)) THEN
      BEGIN
        V$STAGE1 = 37;
        V$STAGE2 = 38;
        V$STAGE3 = 39;
        V$STAGE4 = 40;
        V$STAGE5 = 12942;
      END
      IF(V$COL_ID IN (9, 16)) THEN
      BEGIN
        V$STAGE1 = 41;
        V$STAGE2 = 42;
        V$STAGE3 = 43;
        V$STAGE4 = 44;
        V$STAGE5 = 45;
      END
      IF(V$COL_ID IN (10, 17)) THEN
      BEGIN
        V$STAGE1 = 46;
        V$STAGE2 = 47;
        V$STAGE2 = 48;
      END
    END
    ELSE IF(V$COL_ID IN (11, 18)) THEN
    BEGIN
      -- ВД
      V$CJT = 1;
    END
    ELSE IF(V$COL_ID IN (12, 19)) THEN
    BEGIN
      -- Надомное - пока этого не умеем ?
      V$CJT = 0;
      V$FORM_ID = 2;
    END
    ELSE IF(V$COL_ID IN (13, 20)) THEN
    BEGIN
      -- ДО
      V$CJT = 3;
    END
    ELSE IF(V$COL_ID IN (14, 21)) THEN
    BEGIN
      -- ГПД
      V$CJT = 2;
    END

    IF(V$COL_ID >= 8 AND V$COL_ID <= 14) THEN
    BEGIN
      -- Пропуск
      -- На доделку в замещениях - сейчас факт пропуска у нас есть только в плане, а в факте будет пусто
      -- Поэтому если урок не заменен, а отменен - мы это не увидим
      SELECT COUNT(*)
      FROM CJ2_REPL_PROCESS RP
      JOIN CJ2_JOURNAL J ON J.OBJ_ID = RP.CJ_ID AND J.JOURNAL_TYPE = :V$CJT
        AND (:V$STAGE1 IS NULL OR J.STAGE_INDEX = :V$STAGE1 OR J.STAGE_INDEX = :V$STAGE2 OR J.STAGE_INDEX = :V$STAGE3 OR J.STAGE_INDEX = :V$STAGE4 OR J.STAGE_INDEX = :V$STAGE5)
      LEFT JOIN VALL V3435 ON V3435.OBJ_ID = J.REF_ID AND V3435.PARAM_ID = 3435 AND V3435.IS_DEL = 0
      WHERE RP.DATE_DEL IS NULL AND RP.PERSON_ID = :V$PERSON_ID AND RP.REPL_DATE >= :V$DATE1 AND RP.REPL_DATE <= :V$DATE2 -- AND RP.IS_APPROVED = 1
        AND (:V$FORM_ID IS NULL OR V3435.LISTVAL_ID = :V$FORM_ID)
      INTO :V;
    END
    ELSE IF(V$COL_ID >= 15 AND V$COL_ID <= 21) THEN
    BEGIN
      -- Замещение
      -- REPL_CJ_ID = NULL - замещается в том же журнале
      SELECT COUNT(*)
      FROM CJ2_REPL_PROCESS RP
      JOIN CJ2_JOURNAL J ON J.OBJ_ID = COALESCE(RP.REPL_CJ_ID, RP.CJ_ID) AND J.JOURNAL_TYPE = :V$CJT
        AND (:V$STAGE1 IS NULL OR J.STAGE_INDEX = :V$STAGE1 OR J.STAGE_INDEX = :V$STAGE2 OR J.STAGE_INDEX = :V$STAGE3 OR J.STAGE_INDEX = :V$STAGE4 OR J.STAGE_INDEX = :V$STAGE5)
      LEFT JOIN VALL V3435 ON V3435.OBJ_ID = J.REF_ID AND V3435.PARAM_ID = 3435 AND V3435.IS_DEL = 0
      WHERE RP.DATE_DEL IS NULL AND RP.REPL_PERSON_ID = :V$PERSON_ID AND RP.REPL_DATE >= :V$DATE1 AND RP.REPL_DATE <= :V$DATE2 -- AND RP.IS_APPROVED = 1
        AND (:V$FORM_ID IS NULL OR V3435.LISTVAL_ID = :V$FORM_ID)
      INTO :V;
    END

    -- Заполняем только для первого появления должности
    IF(V$PREV_PERSON <> V$PERSON_ID) THEN
    BEGIN
      V$OBJ_ID = NULL;
      SELECT FIRST 1 D.OBJ_ID, D.VAL
      FROM WORKTAB_DATA D
      WHERE D.DATE_DEL IS NULL AND D.WORKTAB_ID = :I$OBJ_ID AND D.PERSON_ID = :V$PERSON_ID AND D.JOB_ID = :V$JOB_ID AND D.COL_INDEX = - :V$COL_ID
      INTO :V$OBJ_ID, :V$PREV_V;

      IF(V$OBJ_ID IS NULL AND V = 0) THEN
      BEGIN
        -- Ничего нет и не надо
      END
      ELSE IF(V$OBJ_ID IS NOT NULL AND V = 0) THEN
      BEGIN
        -- Удаляем
        UPDATE WORKTAB_DATA
        SET DATE_DEL = CURRENT_TIMESTAMP
        WHERE OBJ_ID = :V$OBJ_ID;
      END
      ELSE IF(V <> COALESCE(V$PREV_V, -1)) THEN
      BEGIN
        -- Добавляем или обновляем
        UPDATE OR INSERT INTO WORKTAB_DATA
        (WORKTAB_ID, PERSON_ID, JOB_ID, COL_INDEX, TYPE_ID, VAL, DATE_DEL)
        VALUES (:I$OBJ_ID, :V$PERSON_ID, :V$JOB_ID, - :V$COL_ID, 9999, :V, NULL)
        MATCHING (WORKTAB_ID, PERSON_ID, JOB_ID, COL_INDEX);
      END
    END

    V$PREV_PERSON = V$PERSON_ID;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE WORKTAB_VAL_IMPORT (
    I$ROW_ID BIGINT,
    I$COL_ID BIGINT,
    I$COL_NAME VARCHAR(400),
    I$CODES VARCHAR(1000),
    I$VALUES VARCHAR(1000))
AS
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$STATUS_ID BIGINT;
DECLARE VARIABLE V$PERSON_ID BIGINT;
DECLARE VARIABLE V$JOB_ID BIGINT;
DECLARE VARIABLE P INTEGER;
DECLARE VARIABLE P2 INTEGER;
DECLARE VARIABLE V$TYPE_ID BIGINT;
DECLARE VARIABLE V$CODE VARCHAR(40);
DECLARE VARIABLE S VARCHAR(100);
DECLARE VARIABLE V$VAL FLOAT;
DECLARE VARIABLE N INTEGER;
DECLARE VARIABLE V$WH SMALLINT;
DECLARE VARIABLE V$VAL_ID BIGINT;
DECLARE VARIABLE V$OLD FLOAT;
begin

  SELECT FIRST 1 D.WORKTAB_ID, V3550.LISTVAL_ID, D.PERSON_ID, D.JOB_ID
  FROM WORKTAB_DATA D
  JOIN VALL V3550 ON V3550.OBJ_ID = D.WORKTAB_ID AND V3550.PARAM_ID = 3550 AND V3550.IS_DEL = 0
  WHERE D.DATE_DEL IS NULL AND D.OBJ_ID = :I$ROW_ID AND D.COL_INDEX IS NULL
  INTO :V$OBJ_ID, :V$STATUS_ID, :V$PERSON_ID, :V$JOB_ID;

  IF(V$STATUS_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Табель не найден или был удален';
  IF(V$STATUS_ID <> 11716) THEN EXCEPTION DATA_ERROR 'Данные можно импортировать только в статусе проекта';

  IF(I$COL_ID IS NULL) THEN
  BEGIN
    -- Дополнительный столбец еще надо идентифицировать
    -- Зачищаем от сепаратора и знаков препинания
    I$COL_NAME = REPLACE(REPLACE(REPLACE(REPLACE(UPPER(I$COL_NAME), '|', ''), ' ', ''), '.', ''), ',', '');

    SELECT FIRST 1 -C.OBJ_ID
    FROM VALS V3555
    LEFT JOIN STR_TO_ID_LIST(V3555.VAL) D ON 1 = 1
    LEFT JOIN WORKTAB_COLS C ON REPLACE(REPLACE(REPLACE(REPLACE(UPPER(C.VAL), '|', ''), ' ', ''), '.', ''), ',', '') = :I$COL_NAME
    WHERE V3555.OBJ_ID = :V$OBJ_ID AND V3555.PARAM_ID = 3555 AND V3555.IS_DEL = 0
    INTO :I$COL_ID;

    IF(I$COL_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не удалось идентифицировать дополнительный столбец ' || I$COL_NAME;

    I$CODES = 'ЗНАЧ';
  END

  -- Столбец дня - можно сразу вносить
  N = 0;
  WHILE(CHAR_LENGTH(:I$CODES) > 0) DO
  BEGIN
    P = POSITION(';' IN I$CODES);
    IF(P <= 0) THEN P = CHAR_LENGTH(I$CODES) + 1;
    P2 = POSITION(';' IN I$VALUES);
    IF(P2 <= 0) THEN P2 = CHAR_LENGTH(I$VALUES) + 1;

    V$CODE = UPPER(TRIM(SUBSTRING(I$CODES FROM 1 FOR P - 1)));
    I$CODES = SUBSTRING(I$CODES FROM P + 1);
    S = TRIM(SUBSTRING(I$VALUES FROM 1 FOR P2 - 1));
    I$VALUES = SUBSTRING(I$VALUES FROM P2 + 1);

    -- Пустое значение можно сделать только один раз
    IF(S = '' AND N > 0) THEN EXCEPTION DATA_ERROR 'Пустое значение часов можно указывать только один раз, и только для обозначения, допускающего такое использование';
    IF(S = '' OR S = '*') THEN S = NULL;
    IF(S IS NULL) THEN V$VAL = NULL; ELSE V$VAL = REPLACE(S, ',', '.');
    IF(V$VAL <= 0) THEN EXCEPTION DATA_ERROR 'Значения часов должны быть строго положительными';

    -- Определяем тип записи
    V$TYPE_ID = NULL;
    SELECT FIRST 1 T.OBJ_ID, T.WANT_HOURS
    FROM WORKTAB_TYPES T
    WHERE T.DATE_DEL IS NULL AND UPPER(T.SVAL) = :V$CODE
    INTO :V$TYPE_ID, :V$WH;

    IF(V$TYPE_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Обозначение типа записи не найдено: ' || V$CODE;
    IF(V$VAL IS NULL AND V$WH = 1) THEN EXCEPTION DATA_ERROR 'Должны быть указаны часы для обозначения ' || V$CODE;

    -- Проверяем что такого обозначения в ячейке еще нет
    V$VAL_ID = NULL;
    SELECT FIRST 1 D.OBJ_ID, D.VAL
    FROM WORKTAB_DATA D
    WHERE D.DATE_DEL IS NULL AND D.WORKTAB_ID = :V$OBJ_ID AND D.PERSON_ID = :V$PERSON_ID AND D.JOB_ID = :V$JOB_ID AND D.COL_INDEX = :I$COL_ID AND D.TYPE_ID = :V$TYPE_ID
    INTO :V$VAL_ID, :V$OLD;

    IF(V$VAL_ID IS NULL) THEN
    BEGIN
      INSERT INTO WORKTAB_DATA
      (WORKTAB_ID, PERSON_ID, JOB_ID, COL_INDEX, TYPE_ID, VAL, COMMENTS)
      VALUES (:V$OBJ_ID, :V$PERSON_ID, :V$JOB_ID, :I$COL_ID, :V$TYPE_ID, :V$VAL, NULL);
    END
    ELSE
    BEGIN
      UPDATE WORKTAB_DATA D
      SET VAL = :V$VAL
      WHERE OBJ_ID = :V$VAL_ID AND COALESCE(D.VAL, -1) <> COALESCE(:V$VAL, -1);
    END
    N = N + 1;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE WORKTAB_VAL_SET (
    I$PARENT_ID BIGINT NOT NULL,
    I$OBJ_ID BIGINT,
    I$PERSON_ID BIGINT,
    I$JOB_ID BIGINT,
    I$COL_ID BIGINT,
    I$TYPE_ID BIGINT,
    I$VALUE VARCHAR(1000),
    I$USER_ID VARCHAR(40))
RETURNS (
    OBJ_ID BIGINT)
AS
DECLARE VARIABLE V$VAL FLOAT;
DECLARE VARIABLE V$VAL2 FLOAT;
DECLARE VARIABLE V$COMMENTS VARCHAR(1000);
DECLARE VARIABLE V$COMMENTS2 VARCHAR(1000);
DECLARE VARIABLE V$TYPE_ID BIGINT;
begin

  -- Проверить статус !!!
  IF(I$OBJ_ID IS NULL AND (I$VALUE = '' OR I$VALUE IS NULL)) THEN EXIT;

  IF((I$PERSON_ID IS NULL AND I$JOB_ID IS NULL) OR (I$OBJ_ID IS NOT NULL AND (I$VALUE = '' OR I$VALUE IS NULL))) THEN
  BEGIN
    -- Удаление
    OBJ_ID = I$OBJ_ID;
    UPDATE WORKTAB_DATA
    SET DATE_DEL = CURRENT_TIMESTAMP
    WHERE OBJ_ID = :OBJ_ID AND WORKTAB_ID = :I$PARENT_ID AND DATE_DEL IS NULL;
  END
  ELSE
  BEGIN
    -- Сохранение
    IF(I$PERSON_ID IS NULL OR I$JOB_ID IS NULL OR I$COL_ID IS NULL OR I$TYPE_ID IS NULL) THEN
      EXCEPTION DATA_ERROR 'Не заполнено одно из обязательных полей, тип записи является обязательным';

    IF(I$TYPE_ID = 0) THEN V$COMMENTS = I$VALUE;
    ELSE
    BEGIN
      V$VAL = I$VALUE;
      IF(V$VAL <= 0) THEN EXCEPTION DATA_ERROR 'Отрицательные или нулевые значения не допускаются';
    END

    IF(I$OBJ_ID IS NULL) THEN
    BEGIN
      INSERT INTO WORKTAB_DATA
      (WORKTAB_ID, PERSON_ID, JOB_ID, COL_INDEX, TYPE_ID, VAL, COMMENTS)
      VALUES (:I$PARENT_ID, :I$PERSON_ID, :I$JOB_ID, :I$COL_ID, :I$TYPE_ID, :V$VAL, :V$COMMENTS)
      RETURNING OBJ_ID INTO :OBJ_ID;
    END
    ELSE
    BEGIN
      SELECT FIRST 1 D.OBJ_ID, D.TYPE_ID, D.VAL, D.COMMENTS
      FROM WORKTAB_DATA D
      WHERE D.OBJ_ID = :I$OBJ_ID AND D.WORKTAB_ID = :I$PARENT_ID AND D.DATE_DEL IS NULL
      INTO :OBJ_ID, :V$TYPE_ID, :V$VAL2, :V$COMMENTS2;

      IF(OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Запись не найдена или была удалена';

      IF(COALESCE(I$TYPE_ID, -1) <> COALESCE(V$TYPE_ID, -1) OR COALESCE(V$VAL, -1) <> COALESCE(V$VAL2, -1) OR COALESCE(V$COMMENTS, '') <> COALESCE(V$COMMENTS2, '')) THEN
      BEGIN
        UPDATE WORKTAB_DATA
        SET TYPE_ID = :I$TYPE_ID, VAL = :V$VAL, COMMENTS = :V$COMMENTS
        WHERE OBJ_ID = :OBJ_ID;
      END
    END
  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE WORKTIME_GET (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$DAY INTEGER;
DECLARE VARIABLE V$T1 TIME;
DECLARE VARIABLE V$T2 TIME;
begin

  -- Признак разрешения редактирования
  TAG_NAME = 'readonly';
  VAL = 0;
  SUSPEND;

  TAG_NAME = 'items::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT LV.COST, V3531.VAL, V3532.VAL
    FROM LINKS L516
    JOIN VALL V3530 ON V3530.OBJ_ID = L516.OBJ_ID AND V3530.PARAM_ID = 3530 AND V3530.IS_DEL = 0
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V3530.LISTVAL_ID
    JOIN VALT V3531 ON V3531.OBJ_ID = L516.OBJ_ID AND V3531.PARAM_ID = 3531 AND V3531.IS_DEL = 0
    JOIN VALT V3532 ON V3532.OBJ_ID = L516.OBJ_ID AND V3532.PARAM_ID = 3532 AND V3532.IS_DEL = 0
    WHERE L516.PARENT_ID = :I$OBJ_ID AND L516.OBJ_TYPE_ID = 516 AND L516.DATE_DEL IS NULL
    ORDER BY 1
    INTO :V$DAY, :V$T1, :V$T2
  DO
  BEGIN
    TAG_NAME = 'items:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'items:r:day';
    VAL = V$DAY - 1; -- 0 = пн
    SUSPEND;
    TAG_NAME = 'items:r:time_from';
    VAL = V$T1;
    SUSPEND;
    TAG_NAME = 'items:r:time_to';
    VAL = V$T2;
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE WORKTIME_SET (
    I$PARENT_ID BIGINT NOT NULL,
    I$DAY BIGINT NOT NULL,
    I$TIMEFROM INTEGER NOT NULL,
    I$TIMETO INTEGER NOT NULL)
RETURNS (
    OBJ_ID BIGINT)
AS
declare variable V$DT bigint;
declare variable V$T1 time;
declare variable V$T2 time;
declare variable I$T1 time;
declare variable I$T2 time;
begin

  -- Время на входе - минуты с начала суток

  SELECT FIRST 1 L516.OBJ_ID, L516.DATE_DEL, V3531.VAL, V3532.VAL
  FROM LINKS L516
  JOIN VALL V3530 ON V3530.OBJ_ID = L516.OBJ_ID AND V3530.PARAM_ID = 3530 AND V3530.IS_DEL = 0 AND V3530.LISTVAL_ID = :I$DAY
  JOIN VALT V3531 ON V3531.OBJ_ID = L516.OBJ_ID AND V3531.PARAM_ID = 3531 AND V3531.IS_DEL = 0
  JOIN VALT V3532 ON V3532.OBJ_ID = L516.OBJ_ID AND V3532.PARAM_ID = 3532 AND V3532.IS_DEL = 0
  WHERE L516.PARENT_ID = :I$PARENT_ID AND L516.OBJ_TYPE_ID = 516
  INTO :OBJ_ID, :V$DT, :V$T1, :V$T2;

  IF(I$TIMEFROM < 0 OR I$TIMETO < 0) THEN
  BEGIN
    IF(OBJ_ID IS NOT NULL AND V$DT IS NULL) THEN
    BEGIN
      UPDATE LINKS
      SET DATE_DEL = CURRENT_TIMESTAMP
      WHERE PARENT_ID = :I$PARENT_ID AND OBJ_ID = :OBJ_ID AND DATE_DEL IS NULL;
    END
    EXIT;
  END

  IF(OBJ_ID IS NULL) THEN
  BEGIN
    SELECT OBJ_ID
    FROM OBJECT_ADD_WITH_PARAM(:I$PARENT_ID, NULL, 516, 3530, :I$DAY)
    INTO :OBJ_ID;
  END
  ELSE IF(V$DT IS NOT NULL) THEN
  BEGIN
    UPDATE LINKS
    SET DATE_DEL = NULL
    WHERE PARENT_ID = :I$PARENT_ID AND OBJ_ID = :OBJ_ID AND DATE_DEL IS NOT NULL;
  END

  I$T1 = DATEADD(I$TIMEFROM MINUTE TO TIME '00:00');
  I$T2 = DATEADD(I$TIMETO MINUTE TO TIME '00:00');

  IF(I$T1 <> V$T1 OR V$T1 IS NULL) THEN SELECT 1 FROM VAL_ADD(3531, :OBJ_ID, :I$T1) INTO :V$DT;
  IF(I$T2 <> V$T2 OR V$T2 IS NULL) THEN SELECT 1 FROM VAL_ADD(3532, :OBJ_ID, :I$T2) INTO :V$DT;

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE WORK_DIFF (
    I$DATE DATE,
    I$DAYS INTEGER)
RETURNS (
    RESULT DATE)
AS
begin

  IF(I$DATE IS NOT NULL AND I$DAYS IS NOT NULL) THEN
  BEGIN

    RESULT = I$DATE;

    IF(I$DAYS > 0) THEN
    BEGIN
      WHILE(I$DAYS > 0) DO
      BEGIN
        IF(EXTRACT(WEEKDAY FROM RESULT) = 0) THEN RESULT = DATEADD(1 DAY TO RESULT);
        IF(EXTRACT(WEEKDAY FROM RESULT) = 6) THEN RESULT = DATEADD(2 DAY TO RESULT);
        RESULT = DATEADD(1 DAY TO RESULT);
        I$DAYS = I$DAYS - 1;
      END
      IF(EXTRACT(WEEKDAY FROM RESULT) = 0) THEN RESULT = DATEADD(1 DAY TO RESULT);
      IF(EXTRACT(WEEKDAY FROM RESULT) = 6) THEN RESULT = DATEADD(2 DAY TO RESULT);
    END
    ELSE IF(I$DAYS < 0) THEN
    BEGIN
      WHILE(I$DAYS < 0) DO
      BEGIN
        IF(EXTRACT(WEEKDAY FROM RESULT) = 0) THEN RESULT = DATEADD(-2 DAY TO RESULT);
        IF(EXTRACT(WEEKDAY FROM RESULT) = 6) THEN RESULT = DATEADD(-1 DAY TO RESULT);
        RESULT = DATEADD(-1 DAY TO RESULT);
        I$DAYS = I$DAYS + 1;
      END
      IF(EXTRACT(WEEKDAY FROM RESULT) = 0) THEN RESULT = DATEADD(-2 DAY TO RESULT);
      IF(EXTRACT(WEEKDAY FROM RESULT) = 6) THEN RESULT = DATEADD(-1 DAY TO RESULT);
    END
  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE WSTAGE_LIST (
    I$OBJ_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(100),
    VAL VARCHAR(1000))
AS
declare variable V$OBJ_ID bigint;
declare variable V$TYPE_ID bigint;
declare variable V$D1 date;
declare variable V$D2 date;
begin

  TAG_NAME = 'items::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L85.OBJ_ID, V465.LISTVAL_ID, V466.VAL, V467.VAL
    FROM LINKS L85
    JOIN VALL V465 ON V465.OBJ_ID = L85.OBJ_ID AND V465.PARAM_ID = 465 AND V465.IS_DEL = 0
    JOIN VALD V466 ON V466.OBJ_ID = L85.OBJ_ID AND V466.PARAM_ID = 466 AND V466.IS_DEL = 0
    LEFT JOIN VALD V467 ON V467.OBJ_ID = L85.OBJ_ID AND V467.PARAM_ID = 467 AND V467.IS_DEL = 0
    WHERE L85.PARENT_ID = :I$OBJ_ID AND L85.OBJ_TYPE_ID = 85 AND L85.DATE_DEL IS NULL
    INTO :V$OBJ_ID, :V$TYPE_ID, :V$D1, :V$D2
  DO
  BEGIN
    TAG_NAME = 'items:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'items:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'items:r:type';
    VAL = V$TYPE_ID;
    SUSPEND;
    TAG_NAME = 'items:r:date_from';
    VAL = (SELECT VAL FROM DATE2ISO(:V$D1, 0));
    SUSPEND;
    TAG_NAME = 'items:r:date_to';
    VAL = (SELECT VAL FROM DATE2ISO(:V$D2, 0));
    SUSPEND;
    TAG_NAME = 'items:r:d360';
    IF(V$D2 IS NULL) THEN V$D2 = CURRENT_DATE;
    VAL = (SELECT DAYS360_COUNT FROM GET_DAYS360_COUNT(:V$D1, :V$D2));
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE WSTAGE_SET (
    I$OBJ_ID BIGINT NOT NULL,
    I$WS_ID BIGINT,
    I$TYPE_ID BIGINT,
    I$DATE1 DATE,
    I$DATE2 DATE,
    I$USER_ID VARCHAR(40))
RETURNS (
    OBJ_ID BIGINT,
    D360 INTEGER)
AS
declare variable T integer;
begin

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  IF(NOT EXISTS(SELECT 1 FROM OBJECTS WHERE OBJ_ID = :I$OBJ_ID AND TYPE_ID = 14)) THEN EXCEPTION DATA_ERROR 'Сотрудник не найден';
  IF(I$WS_ID IS NULL AND I$TYPE_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не указан тип стажа';

  IF(I$TYPE_ID IS NOT NULL) THEN
  BEGIN

    IF(I$DATE1 IS NULL) THEN EXCEPTION DATA_ERROR 'Не указана дата начала стажа';
    IF(I$DATE1 > CURRENT_DATE OR I$DATE1 < '01.01.1900') THEN EXCEPTION DATA_ERROR 'Дата начала стажа не должна быть в будущем или далеко в прошлом';
    IF(I$DATE2 IS NOT NULL AND I$DATE2 < I$DATE1) THEN EXCEPTION DATA_ERROR 'Дата окончания стажа не должна быть раньше даты начала';
    IF(I$DATE2 IS NOT NULL AND I$DATE2 > CURRENT_DATE) THEN EXCEPTION DATA_ERROR 'Дата окончания стажа не должна быть в будущем';

    -- Проверяем что строки стажа не пересекаются между собой
    IF(EXISTS(
      SELECT FIRST 1 1
      FROM LINKS L85
      JOIN VALL V465 ON V465.OBJ_ID = L85.OBJ_ID AND V465.PARAM_ID = 465 AND V465.IS_DEL = 0 AND V465.LISTVAL_ID = :I$TYPE_ID
      JOIN VALD V466 ON V466.OBJ_ID = L85.OBJ_ID AND V466.PARAM_ID = 466 AND V466.IS_DEL = 0
      LEFT JOIN VALD V467 ON V467.OBJ_ID = L85.OBJ_ID AND V467.PARAM_ID = 467 AND V467.IS_DEL = 0
      WHERE L85.PARENT_ID = :I$OBJ_ID AND L85.OBJ_TYPE_ID = 85 AND L85.DATE_DEL IS NULL AND (L85.OBJ_ID <> :I$WS_ID OR :I$WS_ID IS NULL)
        AND (V466.VAL <= :I$DATE2 OR :I$DATE2 IS NULL) AND (V467.VAL IS NULL OR V467.VAL >= :I$DATE1)
    ))
    THEN
      EXCEPTION DATA_ERROR 'Записи стажа одного вида не должны пересекаться между собой';

  END

  IF(I$WS_ID IS NULL) THEN
  BEGIN
    SELECT OBJ_ID FROM OBJECT_ADD(:I$OBJ_ID, 85, NULL, NULL, :I$USER_ID) INTO :OBJ_ID;
    SELECT 1 FROM VAL_ADD(465, :OBJ_ID, :I$TYPE_ID) INTO :T;
    SELECT 1 FROM VAL_ADD(466, :OBJ_ID, :I$DATE1) INTO :T;
    SELECT 1 FROM VAL_ADD(467, :OBJ_ID, :I$DATE2) INTO :T;
  END
  ELSE IF(I$WS_ID IS NOT NULL AND I$TYPE_ID IS NULL) THEN
  BEGIN
    UPDATE LINKS
    SET DATE_DEL = CURRENT_TIMESTAMP
    WHERE PARENT_ID = :I$OBJ_ID AND OBJ_ID = :I$WS_ID AND DATE_DEL IS NULL AND OBJ_TYPE_ID = 85;
  END
  ELSE
  BEGIN
    SELECT FIRST 1 L85.OBJ_ID
    FROM LINKS L85
    WHERE L85.PARENT_ID = :I$OBJ_ID AND L85.OBJ_ID = :I$WS_ID AND L85.OBJ_TYPE_ID = 85 AND L85.DATE_DEL IS NULL
    INTO :OBJ_ID;
    IF(OBJ_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Запись стажа не найдена';

    SELECT 1 FROM VAL_ADD(465, :OBJ_ID, :I$TYPE_ID) INTO :T;
    SELECT 1 FROM VAL_ADD(466, :OBJ_ID, :I$DATE1) INTO :T;
    SELECT 1 FROM VAL_ADD(467, :OBJ_ID, :I$DATE2) INTO :T;
  END

  IF(I$DATE2 IS NULL) THEN I$DATE2 = CURRENT_DATE;
  D360 = (SELECT DAYS360_COUNT FROM GET_DAYS360_COUNT(:I$DATE1, :I$DATE2));

  SUSPEND;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE YANDEX_HOMETASK_GET (
    I$GROUP VARCHAR(400),
    I$STUDENT VARCHAR(400),
    I$DATE DATE)
RETURNS (
    OBJ_ID BIGINT,
    SUBJECT_NAME VARCHAR(400),
    FROMDATE VARCHAR(20),
    HOMETASK VARCHAR(2000),
    NFILES SMALLINT)
AS
declare variable V$CLASS_ID bigint;
declare variable V$STUDENT_ID bigint;
declare variable V$GUP_ID bigint;
declare variable V$CJ_ID bigint;
declare variable V$HAS smallint;
declare variable V$DAYDATE integer;
declare variable V$DAY integer;
declare variable SUBNAME varchar(1000);
begin

  IF(I$DATE IS NULL) THEN I$DATE = CURRENT_DATE;

  -- Идентифицируем класс
  SELECT FIRST 1 L9.OBJ_ID
  FROM LINKS L9
  LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C ON 1 = 1
  WHERE L9.PARENT_TYPE_ID = 8 AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
    AND UPPER(C.CAPTION) = UPPER(:I$GROUP)
  INTO :V$CLASS_ID;

  IF(V$CLASS_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Класс не найден';

  -- Идентифицируем ученика
  SELECT FIRST 1 L10.OBJ_ID
  FROM LINKS L10
  JOIN VALS V55 ON V55.OBJ_ID = L10.OBJ_ID AND V55.PARAM_ID = 55 AND V55.IS_DEL = 0
  JOIN VALS V56 ON V56.OBJ_ID = L10.OBJ_ID AND V56.PARAM_ID = 56 AND V56.IS_DEL = 0
  WHERE L10.PARENT_ID = :V$CLASS_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    AND (UPPER(V55.VAL || ' ' || V56.VAL) = UPPER(:I$STUDENT) OR UPPER(V56.VAL || ' ' || V55.VAL) = UPPER(:I$STUDENT))
  INTO :V$STUDENT_ID;

  IF(I$STUDENT IS NOT NULL AND V$STUDENT_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Обучающийся не найден';

  -- Пытаемся определить ГУП класса
  SELECT FIRST 1 LP256.PARENT_ID
  FROM LINKS L10
  JOIN LINKS LP256 ON LP256.OBJ_ID = L10.OBJ_ID AND LP256.PARENT_TYPE_ID = 256 AND LP256.DATE_DEL IS NULL
  WHERE L10.PARENT_ID = :V$CLASS_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL AND (L10.OBJ_ID = :V$STUDENT_ID OR :V$STUDENT_ID IS NULL)
  INTO :V$GUP_ID;

  V$DAYDATE = EXTRACT(MONTH FROM I$DATE) * 100 + EXTRACT(DAY FROM I$DATE);
  V$DAY = EXTRACT(WEEKDAY FROM I$DATE);
  IF(V$DAY = 0) THEN V$DAY = 6; ELSE V$DAY = V$DAY - 1;

  FOR
    SELECT J.OBJ_ID, C.CAPTION, IIF(L179.EXT_OBJ_ID IS NULL, J.JOURNAL_NAME, NULL)
    FROM CJ2_JOURNAL J
    JOIN LINKS L179 ON L179.OBJ_ID = J.GRADE_ID AND L179.PARENT_TYPE_ID = 2
    LEFT JOIN OBJECT_CAPTION_GET(J.SUBJECT_ID) C ON 1 = 1
    WHERE J.DATE_DEL IS NULL AND J.JOURNAL_TYPE IN (0, 1)
      -- Кто-то из учеников есть в этом ГУП
      AND EXISTS (
        SELECT FIRST 1 1
        FROM LINKS L10
        JOIN LINKS LPG ON LPG.OBJ_ID = L10.OBJ_ID AND LPG.PARENT_ID = :V$GUP_ID AND LPG.DATE_DEL IS NULL
        WHERE L10.PARENT_ID = J.GRADE_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL AND (L10.OBJ_ID = :V$STUDENT_ID OR :V$STUDENT_ID IS NULL)
      )
    ORDER BY 2
    INTO :V$CJ_ID, :SUBJECT_NAME, :SUBNAME
  DO
  BEGIN
    IF(V$STUDENT_ID IS NULL AND SUBNAME IS NOT NULL) THEN SUBJECT_NAME = SUBJECT_NAME || ' (' || SUBNAME || ')';

    -- Есть ли урок по данному предмету в этот день ?
    V$HAS = 0;

    -- Сначала смотрим добавленные в уроки
    SELECT FIRST 1 1
    FROM CJ2_JOURNAL_LESSONS L
    WHERE L.DATE_DEL IS NULL AND L.CJ_ID = :V$CJ_ID AND L.LESSON_DATE = :I$DATE
    INTO :V$HAS;

    -- Далее смотрим расписание, но без замещений
    IF(V$HAS = 0) THEN
    BEGIN
      SELECT FIRST 1 1
      FROM LINKS L68
      JOIN LINKS L3 ON L3.PARENT_ID = L68.OBJ_ID AND L3.OBJ_TYPE_ID = 3 AND L3.DATE_DEL IS NULL
      JOIN LINKS L59 ON L59.PARENT_ID = L3.OBJ_ID AND L59.OBJ_TYPE_ID = 59 AND L3.DATE_DEL IS NULL
      JOIN VALL V1341 ON V1341.OBJ_ID = L59.OBJ_ID AND V1341.PARAM_ID = 1341 AND V1341.IS_DEL = 0 AND V1341.LISTVAL_ID = 2
      LEFT JOIN VALD V3120 ON V3120.OBJ_ID = L59.OBJ_ID AND V3120.PARAM_ID = 3120 AND V3120.IS_DEL = 0
      LEFT JOIN VALD V3121 ON V3121.OBJ_ID = L59.OBJ_ID AND V3121.PARAM_ID = 3121 AND V3121.IS_DEL = 0
      JOIN SCHEDULE_ITEMS SI ON SI.DATE_DEL IS NULL AND SI.SCHEDULE_ID = L59.OBJ_ID AND SI.WEEKDAY_NUM = :V$DAY AND SI.CJ_ID = :V$CJ_ID
      WHERE L68.PARENT_TYPE_ID = 2 AND L68.OBJ_TYPE_ID = 68 AND L68.DATE_DEL IS NULL
        AND (V3120.VAL IS NULL OR V3120.VAL <= :I$DATE) AND (V3121.VAL IS NULL OR V3121.VAL >= :I$DATE)
      INTO :V$HAS;

      IF(V$HAS = 0) THEN
      BEGIN
        SELECT FIRST 1 1
        FROM LINKS L68
        JOIN LINKS L3 ON L3.PARENT_ID = L68.OBJ_ID AND L3.OBJ_TYPE_ID = 3 AND L3.DATE_DEL IS NULL
        JOIN SCHEDULE_ITEMS SI ON SI.DATE_DEL IS NULL AND SI.SCHEDULE_ID = L3.OBJ_ID AND SI.WEEKDAY_NUM = :V$DAYDATE AND SI.CJ_ID = :V$CJ_ID
        WHERE L68.PARENT_TYPE_ID = 2 AND L68.OBJ_TYPE_ID = 68 AND L68.DATE_DEL IS NULL
        INTO :V$HAS;
      END
    END

    IF(V$HAS = 1) THEN
    BEGIN

      OBJ_ID = NULL;
      SELECT FIRST 1 L.OBJ_ID, L.LESSON_HOMEWORK, D.VAL
      FROM CJ2_JOURNAL_LESSONS L
      LEFT JOIN DATE2ISO(L.LESSON_DATE, 0) D ON 1 = 1
      WHERE L.DATE_DEL IS NULL AND L.CJ_ID = :V$CJ_ID AND L.LESSON_DATE < :I$DATE AND (L.IS_COMPLETED > 0 OR L.IS_PUBLISHED > 0)
      ORDER BY L.LESSON_DATE DESC
      INTO :OBJ_ID, :HOMETASK, :FROMDATE;

      IF(OBJ_ID IS NOT NULL) THEN
      BEGIN
        SELECT COUNT(*)
        FROM CJ2_BLOB B
        WHERE B.LESSON_ID = :OBJ_ID AND B.DATE_DEL IS NULL AND B.FILE_TYPE = 0
        INTO :NFILES;

        SUSPEND;
      END
    END

  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE YANDEX_SCHEDULE_GET (
    I$GROUP VARCHAR(400),
    I$STUDENT VARCHAR(400),
    I$DATE DATE)
RETURNS (
    LESSON_NUM INTEGER,
    SUBJECT_NAME VARCHAR(400),
    IS_REPL SMALLINT)
AS
declare variable V$CLASS_ID bigint;
declare variable V$STUDENT_ID bigint;
declare variable V$GUP_ID bigint;
declare variable V$DAYDATE integer;
declare variable V$DAY integer;
begin

  IF(I$DATE IS NULL) THEN I$DATE = CURRENT_DATE;

  -- Идентифицируем класс
  SELECT FIRST 1 L9.OBJ_ID
  FROM LINKS L9
  LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C ON 1 = 1
  WHERE L9.PARENT_TYPE_ID = 8 AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
    AND UPPER(C.CAPTION) = UPPER(:I$GROUP)
  INTO :V$CLASS_ID;

  IF(V$CLASS_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Класс не найден';

  -- Идентифицируем ученика
  SELECT FIRST 1 L10.OBJ_ID
  FROM LINKS L10
  JOIN VALS V55 ON V55.OBJ_ID = L10.OBJ_ID AND V55.PARAM_ID = 55 AND V55.IS_DEL = 0
  JOIN VALS V56 ON V56.OBJ_ID = L10.OBJ_ID AND V56.PARAM_ID = 56 AND V56.IS_DEL = 0
  WHERE L10.PARENT_ID = :V$CLASS_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    AND (UPPER(V55.VAL || ' ' || V56.VAL) = UPPER(:I$STUDENT) OR UPPER(V56.VAL || ' ' || V55.VAL) = UPPER(:I$STUDENT))
  INTO :V$STUDENT_ID;

  IF(I$STUDENT IS NOT NULL AND V$STUDENT_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Обучающийся не найден';

  -- Пытаемся определить ГУП класса
  SELECT FIRST 1 LP256.PARENT_ID
  FROM LINKS L10
  JOIN LINKS LP256 ON LP256.OBJ_ID = L10.OBJ_ID AND LP256.PARENT_TYPE_ID = 256 AND LP256.DATE_DEL IS NULL
  WHERE L10.PARENT_ID = :V$CLASS_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL AND (L10.OBJ_ID = :V$STUDENT_ID OR :V$STUDENT_ID IS NULL)
  INTO :V$GUP_ID;

  V$DAYDATE = EXTRACT(MONTH FROM I$DATE) * 100 + EXTRACT(DAY FROM I$DATE);
  V$DAY = EXTRACT(WEEKDAY FROM I$DATE);
  IF(V$DAY = 0) THEN V$DAY = 6; ELSE V$DAY = V$DAY - 1;

  -- Шаблонное расписание на эту дату
  FOR
    -- Групповые журналы
    SELECT DISTINCT SI.LESSON_NUM, CS.CAPTION, 0
    FROM LINKS L68
    JOIN LINKS L3 ON L3.PARENT_ID = L68.OBJ_ID AND L3.OBJ_TYPE_ID = 3 AND L3.DATE_DEL IS NULL
    JOIN LINKS L59 ON L59.PARENT_ID = L3.OBJ_ID AND L59.OBJ_TYPE_ID = 59 AND L3.DATE_DEL IS NULL
    JOIN VALL V1341 ON V1341.OBJ_ID = L59.OBJ_ID AND V1341.PARAM_ID = 1341 AND V1341.IS_DEL = 0 AND V1341.LISTVAL_ID = 2
    LEFT JOIN VALD V3120 ON V3120.OBJ_ID = L59.OBJ_ID AND V3120.PARAM_ID = 3120 AND V3120.IS_DEL = 0
    LEFT JOIN VALD V3121 ON V3121.OBJ_ID = L59.OBJ_ID AND V3121.PARAM_ID = 3121 AND V3121.IS_DEL = 0
    JOIN SCHEDULE_ITEMS SI ON SI.DATE_DEL IS NULL AND SI.SCHEDULE_ID = L59.OBJ_ID AND SI.WEEKDAY_NUM = :V$DAY
    JOIN CJ2_JOURNAL J ON J.OBJ_ID = SI.CJ_ID AND J.DATE_DEL IS NULL AND J.JOURNAL_TYPE = 0
    LEFT JOIN OBJECT_CAPTION_GET(J.SUBJECT_ID) CS ON 1 = 1
    LEFT JOIN SCHEDULE_ITEMS SIP ON SIP.DATE_DEL IS NULL AND SIP.PARENT_ID = SI.OBJ_ID
    LEFT JOIN CJ2_REPL_PROCESS RP ON RP.DATE_DEL IS NULL AND RP.CJ_ID = J.OBJ_ID AND RP.REPL_DATE = :I$DATE AND RP.LESSON_NUM = SI.LESSON_NUM AND RP.IS_APPROVED = 1
    WHERE L68.PARENT_TYPE_ID = 2 AND L68.OBJ_TYPE_ID = 68 AND L68.DATE_DEL IS NULL
      AND (V3120.VAL IS NULL OR V3120.VAL <= :I$DATE) AND (V3121.VAL IS NULL OR V3121.VAL >= :I$DATE)
      -- Кто-то из учеников есть в этом ГУП
      AND EXISTS (
        SELECT FIRST 1 1
        FROM LINKS L10
        JOIN LINKS LPG ON LPG.OBJ_ID = L10.OBJ_ID AND LPG.PARENT_ID = :V$GUP_ID AND LPG.DATE_DEL IS NULL
        WHERE L10.PARENT_ID = J.GRADE_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL AND (L10.OBJ_ID = :V$STUDENT_ID OR :V$STUDENT_ID IS NULL)
      )
      -- Нет переноса урока
      AND SIP.OBJ_ID IS NULL
      -- Нет замены
      AND RP.OBJ_ID IS NULL
    INTO :LESSON_NUM, :SUBJECT_NAME, :IS_REPL
  DO
  BEGIN
    SUSPEND;
  END

  -- Добавляем явно назначенные элементы расписания
  FOR
    SELECT DISTINCT SI.LESSON_NUM, CS.CAPTION, 1
    FROM LINKS L68
    JOIN LINKS L3 ON L3.PARENT_ID = L68.OBJ_ID AND L3.OBJ_TYPE_ID = 3 AND L3.DATE_DEL IS NULL
    JOIN SCHEDULE_ITEMS SI ON SI.DATE_DEL IS NULL AND SI.SCHEDULE_ID = L3.OBJ_ID AND SI.WEEKDAY_NUM = :V$DAYDATE
    JOIN CJ2_JOURNAL J ON J.OBJ_ID = SI.CJ_ID AND J.DATE_DEL IS NULL AND J.JOURNAL_TYPE = 0
    LEFT JOIN OBJECT_CAPTION_GET(J.SUBJECT_ID) CS ON 1 = 1
    WHERE L68.PARENT_TYPE_ID = 2 AND L68.OBJ_TYPE_ID = 68 AND L68.DATE_DEL IS NULL
      -- Кто-то из учеников есть в этом ГУП
      AND EXISTS (
        SELECT FIRST 1 1
        FROM LINKS L10
        JOIN LINKS LPG ON LPG.OBJ_ID = L10.OBJ_ID AND LPG.PARENT_ID = :V$GUP_ID AND LPG.DATE_DEL IS NULL
        WHERE L10.PARENT_ID = J.GRADE_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL AND (L10.OBJ_ID = :V$STUDENT_ID OR :V$STUDENT_ID IS NULL)
      )
    INTO :LESSON_NUM, :SUBJECT_NAME, :IS_REPL
  DO
  BEGIN
    SUSPEND;
  END

  -- Добавляем замещения
  FOR
    SELECT DISTINCT RP.LESSON_NUM, CS.CAPTION, 2
    FROM CJ2_REPL_PROCESS RP
    JOIN CJ2_JOURNAL J ON J.OBJ_ID = RP.CJ_ID AND J.DATE_DEL IS NULL AND J.JOURNAL_TYPE = 0
    LEFT JOIN CJ2_JOURNAL JP ON JP.OBJ_ID = RP.REPL_CJ_ID
    LEFT JOIN OBJECT_CAPTION_GET(COALESCE(JP.SUBJECT_ID, J.SUBJECT_ID)) CS ON 1 = 1
    WHERE RP.DATE_DEL IS NULL AND RP.REPL_DATE = :I$DATE
      -- Кто-то из учеников есть в этом ГУП
      AND EXISTS (
        SELECT FIRST 1 1
        FROM LINKS L10
        JOIN LINKS LPG ON LPG.OBJ_ID = L10.OBJ_ID AND LPG.PARENT_ID = :V$GUP_ID AND LPG.DATE_DEL IS NULL
        WHERE L10.PARENT_ID = J.GRADE_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL AND (L10.OBJ_ID = :V$STUDENT_ID OR :V$STUDENT_ID IS NULL)
      )
    INTO :LESSON_NUM, :SUBJECT_NAME, :IS_REPL
  DO
  BEGIN
    SUSPEND;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE YCHANGE_GRADE_DETAILS (
    I$GRADE_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(40),
    VAL VARCHAR(1000))
AS
declare variable V$OBJ_ID bigint;
declare variable S varchar(1000);
declare variable V$TYPE_ID bigint;
declare variable V$NAME varchar(1000);
begin

  TAG_NAME = 'students::json&colon;array';
  VAL = '1';
  SUSPEND;
  -- Действующие обучающиеся
  FOR
    SELECT L10.OBJ_ID, V55.SVAL || ' ' || V56.SVAL || COALESCE(' ' || V57.SVAL, '')
    FROM LINKS L10
    JOIN VALS V55 ON V55.OBJ_ID = L10.OBJ_ID AND V55.PARAM_ID = 55 AND V55.IS_DEL = 0
    JOIN VALS V56 ON V56.OBJ_ID = L10.OBJ_ID AND V56.PARAM_ID = 56 AND V56.IS_DEL = 0
    LEFT JOIN VALS V57 ON V57.OBJ_ID = L10.OBJ_ID AND V57.PARAM_ID = 57 AND V57.IS_DEL = 0
    WHERE L10.PARENT_ID = :I$GRADE_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    ORDER BY 2
    INTO :V$OBJ_ID, :S
  DO
  BEGIN
    TAG_NAME = 'students:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'students:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'students:r:present';
    VAL = '1';
    SUSPEND;
    TAG_NAME = 'students:r:name';
    VAL = S;
    SUSPEND;

    -- Синхронно смотрим приказ и назначение, только перевод в другой класс или оставление на второй год
    TAG_NAME = 'students:r:dest_type';
    VAL = NULL;
    SELECT FIRST 1 O.TYPE_ID
    FROM ORDER_DATA D
    JOIN ORDERS O ON O.OBJ_ID = D.ORDER_ID AND O.STATE_ID = 11716 AND O.TYPE_ID IN (12931, 12932, 12933, 12937) AND O.DATE_DEL IS NULL
    WHERE D.DATE_DEL IS NULL AND D.REF_ID = :V$OBJ_ID
    INTO :V$TYPE_ID;
    VAL = V$TYPE_ID;
    SUSPEND;

    TAG_NAME = 'students:r:dest';
    VAL = NULL;
    IF(V$TYPE_ID IS NOT NULL AND V$TYPE_ID <> 12932) THEN
    BEGIN
      SELECT V3025.SVAL
      FROM VALS V3025
      WHERE V3025.OBJ_ID = :V$OBJ_ID AND V3025.PARAM_ID = 3025 AND V3025.IS_DEL = 0
      INTO :VAL;
    END
    SUSPEND;

  END

  -- Учащиеся, которые приходят в данный класс из других классов или извне
  -- смотрим проекты приказов
  SELECT G.GRADE_NAME_NEW
  FROM OU_LICENCE_TYPE LT
  LEFT JOIN YCHANGE_REVIEW_GRADES(LT.STATUS, :I$GRADE_ID) G ON 1 = 1
  INTO :V$NAME;

  FOR
    SELECT OD.REF_ID, V55.SVAL || ' ' || V56.SVAL || COALESCE(' ' || V57.SVAL, ''), O.TYPE_ID
    FROM ORDERS O
    JOIN ORDER_DATA OD ON OD.DATE_DEL IS NULL AND OD.ORDER_ID = O.OBJ_ID
    JOIN VALS V3025 ON V3025.OBJ_ID = OD.REF_ID AND V3025.PARAM_ID = 3025 AND V3025.IS_DEL = 0 AND V3025.SVAL = 'будущий ' || :V$NAME
    JOIN VALS V55 ON V55.OBJ_ID = OD.REF_ID AND V55.PARAM_ID = 55 AND V55.IS_DEL = 0
    JOIN VALS V56 ON V56.OBJ_ID = OD.REF_ID AND V56.PARAM_ID = 56 AND V56.IS_DEL = 0
    LEFT JOIN VALS V57 ON V57.OBJ_ID = OD.REF_ID AND V57.PARAM_ID = 57 AND V57.IS_DEL = 0
    WHERE O.DATE_DEL IS NULL AND O.STATE_ID = 11716 AND O.TYPE_ID IN (12929, 12931, 12937)
    ORDER BY 2
    INTO :V$OBJ_ID, :S, :V$TYPE_ID
  DO
  BEGIN
    TAG_NAME = 'students:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'students:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'students:r:present';
    VAL = '0';
    SUSPEND;
    TAG_NAME = 'students:r:name';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'students:r:dest_type';
    VAL = V$TYPE_ID;
    SUSPEND;
    -- Откуда пришел
    TAG_NAME = 'students:r:dest';
    SELECT FIRST 1 C.CAPTION
    FROM LINKS LPG
    LEFT JOIN OBJECT_CAPTION_GET(LPG.PARENT_ID) C ON 1 = 1
    WHERE LPG.OBJ_ID = :V$OBJ_ID AND LPG.PARENT_TYPE_ID IN (290, 9, 187) AND LPG.DATE_DEL IS NULL
    INTO :VAL;
    SUSPEND;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE YCHANGE_GRADE_MEMBERS (
    I$GRADE_ID BIGINT)
RETURNS (
    PERSON_ID BIGINT)
AS
declare variable V$NAME varchar(1000);
begin

  SELECT G.GRADE_NAME_NEW
  FROM OU_LICENCE_TYPE LT
  LEFT JOIN YCHANGE_REVIEW_GRADES(LT.STATUS, :I$GRADE_ID) G ON 1 = 1
  INTO :V$NAME;

  FOR
    -- Действующие/переводимые
    SELECT D.REF_ID
    FROM LINKS L10
    JOIN ORDER_DATA D ON D.DATE_DEL IS NULL AND D.REF_ID = L10.OBJ_ID
    JOIN ORDERS O ON O.DATE_DEL IS NULL AND O.STATE_ID = 11716 AND O.TYPE_ID = 12932 AND O.OBJ_ID = D.ORDER_ID
    WHERE L10.PARENT_ID = :I$GRADE_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    -- Новые
    UNION
    SELECT OD.REF_ID
    FROM ORDERS O
    JOIN ORDER_DATA OD ON OD.DATE_DEL IS NULL AND OD.ORDER_ID = O.OBJ_ID
    JOIN VALS V3025 ON V3025.OBJ_ID = OD.REF_ID AND V3025.PARAM_ID = 3025 AND V3025.IS_DEL = 0 AND V3025.SVAL = 'будущий ' || :V$NAME
    WHERE O.DATE_DEL IS NULL AND O.STATE_ID = 11716 AND O.TYPE_ID IN (12929, 12931, 12937)
    INTO :PERSON_ID
  DO
  BEGIN
    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE YCHANGE_PLAN_ASSIGN (
    I$PERSON_ID BIGINT,
    I$PLAN_ID BIGINT,
    I$USER_ID VARCHAR(40))
AS
declare variable T bigint;
begin

  IF(NOT EXISTS(
    SELECT FIRST 1 1
    FROM LINKS LPG
    WHERE LPG.OBJ_ID = :I$PERSON_ID AND LPG.PARENT_TYPE_ID IN (9, 187, 290) AND LPG.DATE_DEL IS NULL
  ))
  THEN EXCEPTION DATA_ERROR 'Персона не найдена';

  IF(I$PLAN_ID = 0) THEN I$PLAN_ID = NULL;
  ELSE IF(NOT EXISTS(
    SELECT FIRST 1 1
    FROM LINKS LP57
    JOIN VALL V3013 ON V3013.OBJ_ID = LP57.OBJ_ID AND V3013.PARAM_ID = 3013 AND V3013.IS_DEL = 0 AND V3013.LISTVAL_ID = 11715
    WHERE LP57.OBJ_ID = :I$PLAN_ID AND LP57.PARENT_TYPE_ID = 57 AND LP57.OBJ_TYPE_ID = 400 AND LP57.DATE_DEL IS NULL
  ))
  THEN EXCEPTION DATA_ERROR 'Учебный план не найден, или не утвержден';

  SELECT BLOB_ID FROM VAL_ADD(3119, :I$PERSON_ID, :I$PLAN_ID) INTO :T;

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE YCHANGE_PLAN_DETAILS (
    I$GRADE_ID BIGINT,
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(40),
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$PLAN_ID BIGINT;
DECLARE VARIABLE S VARCHAR(1000);
DECLARE VARIABLE N INTEGER;
begin

  IF(I$GRADE_ID IS NULL) THEN
  BEGIN
    TAG_NAME = 'assn::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT G.GRADE_ID
      FROM OU_LICENCE_TYPE LT
      LEFT JOIN YCHANGE_REVIEW_GRADES(LT.STATUS) G ON 1 = 1
      WHERE G.STAGE_ID_NEW IS NOT NULL
      ORDER BY G.STAGE_COST_NEW
      INTO :V$OBJ_ID
    DO
    BEGIN
      FOR
        SELECT V3119.VAL, COUNT(*)
        FROM YCHANGE_GRADE_MEMBERS(:V$OBJ_ID) M
        LEFT JOIN VALR V3119 ON V3119.OBJ_ID = M.PERSON_ID AND V3119.PARAM_ID = 3119 AND V3119.IS_DEL = 0
        GROUP BY 1
        INTO :V$PLAN_ID, :N
      DO
      BEGIN
        TAG_NAME = 'assn:r';
        VAL = NULL;
        SUSPEND;
        TAG_NAME = 'assn:r:grade_id';
        VAL = V$OBJ_ID;
        SUSPEND;
        TAG_NAME = 'assn:r:plan_id';
        VAL = COALESCE(V$PLAN_ID, 0);
        SUSPEND;
        TAG_NAME = 'assn:r:n';
        VAL = N;
        SUSPEND;
      END
    END
  END
  ELSE
  BEGIN
    TAG_NAME = 'students::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT M.PERSON_ID, V55.SVAL || ' ' || V56.SVAL || COALESCE(' ' || V57.SVAL, ''), COALESCE(V3119.VAL, 0)
      FROM YCHANGE_GRADE_MEMBERS(:I$GRADE_ID) M
      JOIN VALS V55 ON V55.OBJ_ID = M.PERSON_ID AND V55.PARAM_ID = 55 AND V55.IS_DEL = 0
      JOIN VALS V56 ON V56.OBJ_ID = M.PERSON_ID AND V56.PARAM_ID = 56 AND V56.IS_DEL = 0
      LEFT JOIN VALS V57 ON V57.OBJ_ID = M.PERSON_ID AND V57.PARAM_ID = 57 AND V57.IS_DEL = 0
      LEFT JOIN VALR V3119 ON V3119.OBJ_ID = M.PERSON_ID AND V3119.PARAM_ID = 3119 AND V3119.IS_DEL = 0
      ORDER BY 2
      INTO :V$OBJ_ID, :S, :V$PLAN_ID
    DO
    BEGIN
      TAG_NAME = 'students:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'students:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'students:r:name';
      VAL = S;
      SUSPEND;
      TAG_NAME = 'students:r:plan_id';
      VAL = V$PLAN_ID;
      SUSPEND;
    END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE YCHANGE_PROCESS (
    I$USER_ID VARCHAR(40))
RETURNS (
    VAL VARCHAR(1000))
AS
DECLARE VARIABLE V$STATUS CHAR(1);
DECLARE VARIABLE V$PREV_YEAR INTEGER;
DECLARE VARIABLE V$NEW_YEAR INTEGER;
DECLARE VARIABLE V$NEW_YEAR_ID BIGINT;
DECLARE VARIABLE V$OU_ID BIGINT;
DECLARE VARIABLE T BIGINT;
DECLARE VARIABLE T2 BIGINT;
DECLARE VARIABLE S1 VARCHAR(400);
DECLARE VARIABLE S1X VARCHAR(400);
DECLARE VARIABLE S2 VARCHAR(400);
DECLARE VARIABLE V$OLD_SUFFIX VARCHAR(400);
DECLARE VARIABLE V$PARENT_ID BIGINT;
DECLARE VARIABLE V$NEW_PARENT_ID BIGINT;
DECLARE VARIABLE V$LEVEL_ID BIGINT;
DECLARE VARIABLE V$STAGE_ID BIGINT;
DECLARE VARIABLE V$OLD_STAGE BIGINT;
DECLARE VARIABLE V$TYPE_ID BIGINT;
DECLARE VARIABLE V$GRADE_ID BIGINT;
DECLARE VARIABLE V$OLD_GRADE BIGINT;
DECLARE VARIABLE V$OVZ BIGINT;
DECLARE VARIABLE V$OVZ_YEAR BIGINT;
DECLARE VARIABLE V$PLAN_ID BIGINT;
DECLARE VARIABLE V$GUP_ID BIGINT;
DECLARE VARIABLE V$DATE DATE;
DECLARE VARIABLE V$ACTION_DATE DATE;
DECLARE VARIABLE V$CURRENT_STAGE BIGINT;
DECLARE VARIABLE V$LEVEL INTEGER;
DECLARE VARIABLE V$DST_GROUP BIGINT;
DECLARE VARIABLE V$PARAM_ID BIGINT;
DECLARE VARIABLE V$LV BIGINT;
DECLARE VARIABLE V$SKIP SMALLINT;
DECLARE VARIABLE V$STAGE_P BIGINT;
DECLARE VARIABLE V$HAS_DOU SMALLINT;
DECLARE VARIABLE V$HAS_OU SMALLINT;
DECLARE VARIABLE V$FOLDER_ID BIGINT;
DECLARE VARIABLE V$SUB_ID BIGINT;
begin

  V$STATUS = (SELECT STATUS FROM OU_LICENCE_TYPE);

  IF(I$USER_ID = 'Веб-администратор') THEN I$USER_ID = 1;

  -- Проверяем соответствие дат текущего и нового учебного года
  SELECT FIRST 1 L2.OBJ_ID, LV.COST
  FROM LINKS L2
  LEFT JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  LEFT JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$OU_ID, :V$PREV_YEAR;

  V$NEW_YEAR = EXTRACT(YEAR FROM CURRENT_DATE);
  V$NEW_YEAR_ID = (SELECT FIRST 1 LISTVAL_ID FROM LISTVALS_LIST(29) WHERE IS_DEL = 0 AND COST = :V$NEW_YEAR);

  IF(V$OU_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Образовательная организация не найдена. Создайте объект образовательной организации и укажите текущий учебный год';

  IF(V$PREV_YEAR IS NULL) THEN V$PREV_YEAR = V$NEW_YEAR - 1; -- если вообще не было перевода года
  IF(V$PREV_YEAR <> V$NEW_YEAR - 1) THEN
  BEGIN
    IF(V$PREV_YEAR < V$NEW_YEAR) THEN EXCEPTION DATA_ERROR 'Текущий учебный год слишком старый. Если это не ошибка, установите корректный учебный год в настройках организации';
    ELSE EXCEPTION DATA_ERROR 'Некорректный учебный год. Проверьте настройки календаря на сервере, возможно произошел сбой часов, а также проверьте настройку текущего учебного года в ОООД';
  END

  -- Все выпускные классы должны быть к этому времени уже быть выпущены, кроме второгодников

  -- Нет ли дубликатов с названиями классов ?
  FOR
    SELECT G.GRADE_ID, G.GRADE_NAME_NEW
    FROM YCHANGE_REVIEW_GRADES(:V$STATUS, NULL) G
    WHERE G.GRADE_NAME_NEW IS NOT NULL AND G.GRADE_SUFFIX_NEW <> '*'
    INTO :T, :S1
  DO
  BEGIN
    IF(EXISTS(
      SELECT 1
      FROM YCHANGE_REVIEW_GRADES(:V$STATUS, NULL) G
      WHERE G.GRADE_ID <> :T AND G.GRADE_NAME_NEW = :S1
    ))
    THEN EXCEPTION DATA_ERROR 'В системе есть более одного учебного коллектива с названием ' || S1 ;
  END

  -- Проверяем даты приказов
  -- Приказ о переводе должен быть в пределах 20.08..31.08
  -- Приказ о приеме на обучение должен быть точно 01.09
  FOR
    SELECT D.TYPE_ID, D.PROJECT_NUM, D.ACTION_DATE
    FROM ORDERS D
    WHERE D.DATE_DEL IS NULL AND D.STATE_ID = 11716
    ORDER BY 1
    INTO :V$TYPE_ID, :S1, :V$DATE
  DO
  BEGIN
    IF(EXTRACT(YEAR FROM V$DATE) <> V$NEW_YEAR) THEN
      EXCEPTION DATA_ERROR 'Проекты приказов должны исполняться текущим годом, проверьте проект приказа ' || COALESCE(S1, '???');
    IF(V$TYPE_ID = 12929) THEN
    BEGIN
      IF(EXTRACT(MONTH FROM V$DATE) <> 9 OR EXTRACT(DAY FROM V$DATE) <> 1) THEN
        EXCEPTION DATA_ERROR 'Приказ о приеме на обучение может быть исполнен только с датой 01.09, проверьте проект приказа ' || COALESCE(S1, '???');
    END
    ELSE IF(V$TYPE_ID IN (12931, 12932, 12937)) THEN
    BEGIN
      IF(EXTRACT(MONTH FROM V$DATE) <> 8 OR EXTRACT(DAY FROM V$DATE) < 20) THEN
        EXCEPTION DATA_ERROR 'Все приказы о переводе допускаются с датой исполнения в пределах 20.08-31.08, проверьте проект приказа ' || COALESCE(S1, '???');
    END
  END

  -- Нет ли чудес, что один ученик в двух приказах ?
  FOR
    SELECT OD.REF_ID, COUNT(*)
    FROM ORDERS D
    JOIN ORDER_DATA OD ON OD.DATE_DEL IS NULL AND OD.ORDER_ID = D.OBJ_ID
    WHERE D.DATE_DEL IS NULL AND D.STATE_ID = 11716 AND D.TYPE_ID IN (12929, 12931, 12932, 12933, 12934, 12935, 12936, 12937)
    GROUP BY 1
    HAVING COUNT(*) > 1
    INTO :T, :T2
  DO
  BEGIN
    EXCEPTION DATA_ERROR 'Обучающийся ' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:T)) || ' указан в ' || T2 || ' приказах одновременно';
  END

  -- Все обучающиеся и кандидаты распределены по классам ?
  FOR
    -- Текущие обучающиеся, школа
    SELECT L10.OBJ_ID
    FROM LINKS L2
    JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
    JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    -- Предварительный прием
    UNION
    SELECT L10.OBJ_ID
    FROM LINKS L2
    JOIN LINKS L77 ON L77.PARENT_ID = L2.OBJ_ID AND L77.OBJ_TYPE_ID = 77 AND L77.DATE_DEL IS NULL
    JOIN LINKS L290 ON L290.PARENT_ID = L77.OBJ_ID AND L290.OBJ_TYPE_ID = 290 AND L290.DATE_DEL IS NULL
    JOIN LINKS L10 ON L10.PARENT_ID = L290.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :T
  DO
  BEGIN
    IF(NOT EXISTS(
      SELECT 1
      FROM ORDER_DATA OD
      JOIN ORDERS D ON D.DATE_DEL IS NULL AND D.OBJ_ID = OD.ORDER_ID AND D.STATE_ID = 11716 AND D.TYPE_ID IN (12929, 12931, 12932, 12933, 12937)
      WHERE OD.DATE_DEL IS NULL AND OD.REF_ID = :T
    ))
    THEN EXCEPTION DATA_ERROR 'Не создан проект приказа по движению обучающихся для ' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:T));
  END

  -- Все ли ссылки на учебный план для ГУП валидны ?
  T = NULL;
  SELECT FIRST 1 OD.REF_ID, V3119.VAL
  FROM ORDERS D
  JOIN ORDER_DATA OD ON OD.DATE_DEL IS NULL AND OD.ORDER_ID = D.OBJ_ID
  JOIN VALR V3119 ON V3119.OBJ_ID = OD.REF_ID AND V3119.PARAM_ID = 3119 AND V3119.IS_DEL = 0
  LEFT JOIN LINKS LP57 ON LP57.OBJ_ID = V3119.VAL AND LP57.PARENT_TYPE_ID = 57 AND LP57.DATE_DEL IS NULL
  LEFT JOIN VALL V3013 ON V3013.OBJ_ID = LP57.OBJ_ID AND V3013.PARAM_ID = 3013 AND V3013.IS_DEL = 0 AND V3013.LISTVAL_ID = 11715
  WHERE D.DATE_DEL IS NULL AND D.STATE_ID = 11716 AND D.TYPE_ID IN (12929, 12931, 12932, 12937) AND V3013.LISTVAL_ID IS NULL
  INTO :T, :T2;

  IF(T2 IS NOT NULL) THEN EXCEPTION DATA_ERROR 'Назначенный УП для ' || (SELECT CAPTION FROM OBJECT_CAPTION_GET(:T)) || ' некорректен, УП удален или не является действующим';

  -- Графики отпусков за текущий год должны быть действующими
  -- Временно отключено
  IF(0 = 1 AND NOT EXISTS(
    SELECT L534.OBJ_ID
    FROM LINKS L534
    JOIN VALI V3584 ON V3584.OBJ_ID = L534.OBJ_ID AND V3584.PARAM_ID = 3584 AND V3584.IS_DEL = 0 AND V3584.VAL = :V$NEW_YEAR
    JOIN VALL V3585 ON V3585.OBJ_ID = L534.OBJ_ID AND V3585.PARAM_ID = 3585 AND V3585.IS_DEL = 0 AND V3585.LISTVAL_ID = 11715
    WHERE L534.PARENT_ID = :V$OU_ID AND L534.OBJ_TYPE_ID = 534 AND L534.DATE_DEL IS NULL
  ))
  THEN
    EXCEPTION DATA_ERROR 'График отпусков в текущем году должен быть действующим';

  -- Переносим существующие классы, создаем новые
  -- Выполняем через буфер, чтобы не зациклиться

  -- Очистка статусов для распускаемых классов
  UPDATE LINKS SET LISTVAL_ID = NULL WHERE PARENT_TYPE_ID IN (8, 242) AND OBJ_TYPE_ID IN (9, 125, 187, 243);

  FOR
    SELECT G.GRADE_ID
    FROM YCHANGE_REVIEW_GRADES(:V$STATUS, NULL) G
    WHERE G.GRADE_SUFFIX_NEW = '*' OR G.GRADE_NAME_NEW IS NULL
    INTO :V$GRADE_ID
  DO
  BEGIN
    UPDATE LINKS SET LISTVAL_ID = 2 WHERE PARENT_TYPE_ID IN (8, 242) AND OBJ_ID = :V$GRADE_ID;
  END

  V$HAS_DOU = 0;
  V$HAS_OU = 0;
  FOR
    SELECT G.TYPE_ID, G.STAGE_ID_OLD, G.STAGE_ID_NEW, G.GRADE_ID, G.OVZ, G.OVZ_YEAR, V54.SVAL, G.GRADE_SUFFIX_NEW, G.GRADE_NAME_OLD, G.GRADE_NAME_NEW, LV.PARENT_ID
    FROM YCHANGE_REVIEW_GRADES(:V$STATUS, NULL) G
    LEFT JOIN VALS V54 ON V54.OBJ_ID = G.GRADE_ID AND V54.PARAM_ID = 54 AND V54.IS_DEL = 0
    LEFT JOIN LISTVALS LV ON LV.LISTVAL_ID = COALESCE(G.STAGE_ID_OLD, G.STAGE_ID_NEW)
    WHERE G.GRADE_NAME_NEW IS NOT NULL AND (G.GRADE_SUFFIX_NEW IS NULL OR G.GRADE_SUFFIX_NEW <> '*')
    INTO :V$TYPE_ID, :V$OLD_STAGE, :V$STAGE_ID, :V$GRADE_ID, :V$OVZ, :V$OVZ_YEAR, :V$OLD_SUFFIX, :S1, :S1X, :S2, :V$STAGE_P
  DO
  BEGIN
    -- Если класс с ОВЗ и год не переводится
    IF(V$STAGE_ID = V$OLD_STAGE) THEN V$STAGE_ID = NULL;
    IF(V$STAGE_P = 2140) THEN V$HAS_DOU = 1;
    IF(V$STAGE_P IN (2141, 12941)) THEN V$HAS_OU = 1;

    INSERT INTO YCHANGE_GRADES_TMP
    (TYPE_ID, STAGE_ID, GRADE_ID, OVZ, OVZ_YEAR, GRADE_SUFFIX_OLD, GRADE_SUFFIX_NEW, GRADE_NAME_OLD, GRADE_NAME_NEW)
    VALUES (:V$TYPE_ID, :V$STAGE_ID, :V$GRADE_ID, :V$OVZ, :V$OVZ_YEAR, :V$OLD_SUFFIX, :S1, :S1X, :S2);
  END

  -- В мультипараграфе при наличии учебных коллективов сразу и ДОУ, и ОУ - создаем папку для ДОУ
  -- в нее будет переназначаться связь окончания при выгрузке в район-регион
  -- сама папка будет пустой, если вообще все дошколята перешли в школьный уровень
  IF(V$STATUS = 'S' AND V$HAS_DOU = 1 AND V$HAS_OU = 1) THEN
  BEGIN
    SELECT FIRST 1 L78.OBJ_ID
    FROM LINKS L78
    WHERE L78.PARENT_ID = :V$OU_ID AND L78.OBJ_TYPE_ID = 78 AND L78.DATE_DEL IS NULL
    INTO :V$FOLDER_ID;

    IF(V$FOLDER_ID IS NULL) THEN
    SELECT OBJ_ID FROM OBJECT_ADD(:V$OU_ID, 78) INTO :V$FOLDER_ID;

    SELECT FIRST 1 L83.OBJ_ID
    FROM LINKS L83
    JOIN VALL V450 ON V450.OBJ_ID = L83.OBJ_ID AND V450.PARAM_ID = 450 AND V450.IS_DEL = 0 AND V450.LISTVAL_ID = 3320
    JOIN VALI V451 ON V451.OBJ_ID = L83.OBJ_ID AND V451.PARAM_ID = 451 AND V451.IS_DEL = 0 AND V451.VAL = :V$NEW_YEAR
    WHERE L83.PARENT_ID = :V$FOLDER_ID AND L83.OBJ_TYPE_ID = 83 AND L83.DATE_DEL IS NULL
    INTO :V$SUB_ID;

    IF(V$SUB_ID IS NULL) THEN
    BEGIN
      SELECT OBJ_ID FROM OBJECT_ADD_WITH_PARAM(:V$OU_ID, NULL, 78, 450, 3320) INTO :V$SUB_ID;
      SELECT 1 FROM VAL_ADD(451, :V$SUB_ID, :V$NEW_YEAR) INTO :T;
    END
  END

  FOR
    SELECT T.TYPE_ID, T.STAGE_ID, T.GRADE_ID, T.OVZ, T.OVZ_YEAR, T.GRADE_SUFFIX_OLD, T.GRADE_SUFFIX_NEW, T.GRADE_NAME_NEW
    FROM YCHANGE_GRADES_TMP T
    ORDER BY 2
    INTO :V$TYPE_ID, :V$STAGE_ID, :V$GRADE_ID, :V$OVZ, :V$OVZ_YEAR, :V$OLD_SUFFIX, :S1, :S2
  DO
  BEGIN

    VAL = 'id коллектива ' || V$GRADE_ID;
    SUSPEND;

    -- Текущее местонахождение класса или его проекта
    SELECT FIRST 1 LP8.PARENT_ID, LP7.PARENT_ID
    FROM LINKS LP8
    JOIN LINKS LP7 ON LP7.OBJ_ID = LP8.PARENT_ID AND LP7.PARENT_TYPE_ID = 7 AND LP7.DATE_DEL IS NULL
    WHERE LP8.OBJ_ID = :V$GRADE_ID AND LP8.PARENT_TYPE_ID = 8 AND LP8.DATE_DEL IS NULL
    INTO :V$PARENT_ID, :V$CURRENT_STAGE;

    IF(V$TYPE_ID = 403) THEN
    BEGIN
      -- Создаем реальный класс по проекту класса, проект прибиваем
      UPDATE LINKS SET DATE_DEL = CURRENT_TIMESTAMP WHERE PARENT_ID = :V$PARENT_ID AND OBJ_ID = :V$GRADE_ID AND DATE_DEL IS NULL;
      V$OLD_GRADE = V$GRADE_ID;

      SELECT OBJ_ID FROM OBJECT_ADD(:V$PARENT_ID, 9) INTO :V$GRADE_ID;
      VAL = 'Создан новый учебный коллектив ' || S2;

      -- Переносим коды специальностей и связь с ОП для СПО, заменяем коды параметров с 403 на 9
      -- сам код запишется автоматически
      -- если задан УП, то копируем только его - коды появятся сами
      V$SKIP = 0;
      FOR
        SELECT V.PARAM_ID, V.LISTVAL_ID
        FROM VALL V
        WHERE V.OBJ_ID = :V$OLD_GRADE AND V.PARAM_ID IN (3381, 3382, 3383) AND V.IS_DEL = 0
        UNION
        SELECT V.PARAM_ID, V.VAL
        FROM VALR V
        WHERE V.OBJ_ID = :V$OLD_GRADE AND V.PARAM_ID IN (3477) AND V.IS_DEL = 0
        -- сортировка чтобы сначала шел параметр с УП
        ORDER BY 1 DESC
        INTO :V$PARAM_ID, :V$LV
      DO
      BEGIN
        IF(V$PARAM_ID = 3381) THEN V$PARAM_ID = 2165;
        ELSE IF(V$PARAM_ID = 3382) THEN V$PARAM_ID = 2821;
        ELSE IF(V$PARAM_ID = 3383) THEN V$PARAM_ID = 3367;
        ELSE IF(V$PARAM_ID = 3477) THEN V$PARAM_ID = 3075; -- УП
        IF(V$SKIP = 0) THEN SELECT 1 FROM VAL_ADD(:V$PARAM_ID, :V$GRADE_ID, :V$LV) INTO :T;
        IF(V$PARAM_ID = 3075) THEN V$SKIP = 1; -- если задан УП, дальше коды не копируем
      END
    END
    ELSE
    BEGIN
      -- Переносим коллектив в новый этап
      -- V$STAGE_ID = NULL значит, что этап не меняется для классов ОВЗ
      IF(V$STAGE_ID IS NOT NULL) THEN
      BEGIN

        V$LEVEL_ID = NULL;
        IF(V$STAGE_ID BETWEEN 37 AND 48) THEN
        BEGIN
          -- Школа
          IF(V$STAGE_ID IN (37, 38, 39, 40)) THEN T = 22;
          ELSE IF(V$STAGE_ID IN (41, 42, 43, 44, 45)) THEN T = 26;
          ELSE IF(V$STAGE_ID IN (46, 47, 48)) THEN T = 27;
          ELSE EXCEPTION DATA_ERROR 'Недопустимый этап обучения ' || V$STAGE_ID;

          -- Если в классе ОВЗ особо указаны буквы - меняем этап
          -- также принудительно ставим этап для конкретных этапов
          IF(V$OVZ = 13275) THEN
          BEGIN
            IF(POSITION('Н' IN S1) > 0 OR V$STAGE_ID IN (12942, 12950)) THEN T = 22;
            ELSE IF(POSITION('О' IN S1) > 0 OR V$STAGE_ID IN (12951, 12960)) THEN T = 26;
            ELSE IF(POSITION('С' IN S1) > 0 OR V$STAGE_ID = 12961) THEN T = 27;
          END

          SELECT FIRST 1 L7.OBJ_ID
          FROM LINKS L2
          JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
          JOIN VALL V43 ON V43.OBJ_ID = L7.OBJ_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0 AND V43.LISTVAL_ID = :T
          WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
          INTO :V$LEVEL_ID;

          -- Если не нашли в подходящем уровне - ищем везде !
          -- с приоритетом текущего уровня
          IF(V$LEVEL_ID IS NULL) THEN
          BEGIN
            SELECT FIRST 1 L7.OBJ_ID
            FROM LINKS L2
            JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
            JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
            JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0 AND V49.LISTVAL_ID = :V$STAGE_ID
            WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
            ORDER BY IIF(L7.OBJ_ID = :V$CURRENT_STAGE, 0, 1)
            INTO :V$LEVEL_ID;
          END
        END
        ELSE IF(V$STAGE_ID IN (30, 31, 32, 3261, 34, 35, 36)) THEN
        BEGIN
          -- ДОУ - раскладываем между яслями и садом
          IF(V$STAGE_ID IN (30, 31, 32)) THEN T = 3263;
          ELSE IF(V$STAGE_ID IN (3261, 34, 35, 36)) THEN T = 3264;
          ELSE EXCEPTION DATA_ERROR 'Недопустимый этап обучения ' || V$STAGE_ID;

          SELECT FIRST 1 L7.OBJ_ID
          FROM LINKS L2
          JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
          JOIN VALL V43 ON V43.OBJ_ID = L7.OBJ_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0 AND V43.LISTVAL_ID = :T
          WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
          INTO :V$LEVEL_ID;
        END
        ELSE IF(V$STAGE_ID IN (33, 3262)) THEN
        BEGIN
          -- ДОУ мультивозрастные группы остаются на месте
          V$LEVEL_ID = V$CURRENT_STAGE;
        END
        ELSE
        BEGIN
          -- Колледжи - всегда берем тот же уровень
          V$LEVEL_ID = V$CURRENT_STAGE;
        END

        IF(V$LEVEL_ID IS NULL) THEN
        BEGIN
          S1 = (SELECT VAL FROM LISTVAL_TEXT(:V$STAGE_ID));
          EXCEPTION DATA_ERROR 'Не найден уровень образования для нового этапа обучения (' ||
            COALESCE(S1, '???') || '). Создайте уровень образования вручную';
        END

        -- Если в этом уровне не найден этап - создаем его
        V$NEW_PARENT_ID = NULL;
        SELECT FIRST 1 L8.OBJ_ID
        FROM LINKS L8
        JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0 AND V49.LISTVAL_ID = :V$STAGE_ID
        WHERE L8.PARENT_ID = :V$LEVEL_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
        INTO :V$NEW_PARENT_ID;

        IF(V$NEW_PARENT_ID IS NULL) THEN
        BEGIN
          SELECT OBJ_ID FROM OBJECT_ADD(:V$LEVEL_ID, 8) INTO :V$NEW_PARENT_ID;
          SELECT BLOB_ID FROM VAL_ADD(49, :V$NEW_PARENT_ID, :V$STAGE_ID) INTO :T;
        END

        SELECT LINK_ID FROM OBJECT_ADD_LINK(:V$NEW_PARENT_ID, :V$GRADE_ID, 9) INTO :T;
        UPDATE LINKS SET DATE_DEL = CURRENT_TIMESTAMP WHERE PARENT_ID = :V$PARENT_ID AND OBJ_ID = :V$GRADE_ID AND DATE_DEL IS NULL;
      END

      IF(COALESCE(V$OLD_SUFFIX, '') = COALESCE(S1, '')) THEN
        VAL = 'Переведен существующий учебный коллектив ' || S2;
      ELSE
        VAL = 'Переименован учебный коллектив ' || S2;
    END

    -- Меняем суффикс коллектива - делаем прямым исправлением в базе, чтобы последовательные изменения не ругались
    UPDATE OR INSERT INTO VALS
    (OBJ_ID, PARAM_ID, VAL, IS_DEL)
    VALUES (:V$GRADE_ID, 54, :S1, IIF(:S1 IS NULL OR :S1 = '', 1, 0))
    MATCHING (OBJ_ID, PARAM_ID);

    SELECT BLOB_ID FROM VAL_ADD(592, :V$GRADE_ID, :V$OVZ) INTO :T;
    SELECT BLOB_ID FROM VAL_ADD(3024, :V$GRADE_ID, :V$OVZ_YEAR) INTO :T;

    -- Выдача лога
    SUSPEND;

  END

  -- Записываем новый учебный год
  UPDATE OR INSERT INTO VALL
  (OBJ_ID, PARAM_ID, LISTVAL_ID, IS_DEL)
  VALUES (:V$OU_ID, 1236, :V$NEW_YEAR_ID, 0)
  MATCHING (OBJ_ID, PARAM_ID);

  -- Проводка приказов, фактическое перемещение учеников и зачисляемых
  FOR
    SELECT D.OBJ_ID, D.TYPE_ID, D.ORDER_NUM, D.ORDER_DATE, D.ACTION_DATE, D.PROJECT_NUM
    FROM ORDERS D
    WHERE D.DATE_DEL IS NULL AND D.STATE_ID = 11716 AND D.TYPE_ID IN (12929, 12931, 12932, 12933, 12937)
    ORDER BY D.OBJ_ID
    INTO :T, :V$TYPE_ID, :S1, :V$DATE, :V$ACTION_DATE, :S2
  DO
  BEGIN
    -- Формируем номер и дату движения, NULL в качестве user_id дает понять что это перевод года
    -- Дата всех движений будет 31.08, кроме зачисления - они 01.09
    IF(S1 IS NULL OR S1 = '') THEN S1 = 'АВТО';
    IF(V$TYPE_ID = 12929) THEN V$ACTION_DATE = '01.09.' || V$NEW_YEAR; ELSE V$ACTION_DATE = '31.08.' || V$NEW_YEAR;
    IF(V$DATE IS NULL) THEN V$DATE = V$ACTION_DATE;
    IF(V$DATE > '01.09.' || V$NEW_YEAR) THEN EXCEPTION DATA_ERROR 'Даты всех приказов должны быть не позднее 01.09, а указана ' || (SELECT RESULT FROM DATE2STR(:V$DATE));

    SELECT OBJ_ID
    FROM ORDER_SET(:T, '@' || :I$USER_ID, NULL, NULL, 11715, :V$DATE, :S1, :V$ACTION_DATE, NULL, NULL, NULL)
    INTO :T;

    VAL = 'Выполняем проводки приказа ' || S2;
    SUSPEND;

    -- @ в качестве префикса user_id дает понять что это перевод года
    FOR
      SELECT VAL
      FROM ORDER_SET_STATE(:T, 11715, '@' || :I$USER_ID)
      INTO :VAL
    DO
    BEGIN
      SUSPEND;
    END
  END

  -- Удаляем все папки зачисляемых, там ничего не осталось
  FOR
    SELECT OBJ_ID, PARENT_ID
    FROM LINKS
    WHERE OBJ_TYPE_ID = 290 AND DATE_DEL IS NULL
    INTO :T, :V$PARENT_ID
  DO
  BEGIN
    SELECT DEL_COUNT
    FROM OBJECT_DEL(:V$PARENT_ID, :T)
    INTO :T2;
  END

  -- Удаляем расформируемые и выпустившиеся учебные коллективы
  -- YCHANGE_REVIEW_GRADES использовать нельзя !
  FOR
    -- Расформируемые
    SELECT L9.OBJ_ID, C.CAPTION
    FROM LINKS L9
    LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C ON 1 = 1
    WHERE L9.PARENT_TYPE_ID IN (8, 242) AND L9.OBJ_TYPE_ID IN (9, 125, 187, 243) AND L9.DATE_DEL IS NULL AND L9.LISTVAL_ID = 2
    INTO :V$GRADE_ID, :S2
  DO
  BEGIN
    -- А не остался ли тут кто ?
    S1 = NULL;
    SELECT FIRST 1 IIF(L10.OBJ_ID IS NULL, NULL, C.CAPTION)
    FROM LINKS L10
    LEFT JOIN OBJECT_CAPTION_GET(L10.OBJ_ID) C ON 1 = 1
    WHERE L10.PARENT_ID = :V$GRADE_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    INTO :S1;

    IF(S1 IS NOT NULL) THEN EXCEPTION DATA_ERROR 'Остались обучающиеся в выпускном/распускаемом учебном коллективе ' || S2 || ' (' || S1 || ')';

    UPDATE LINKS L
    SET L.DATE_DEL = CURRENT_TIMESTAMP
    WHERE L.PARENT_TYPE_ID = 8 AND L.OBJ_ID = :V$GRADE_ID AND L.DATE_DEL IS NULL;

    VAL = 'Удален выпускной/распускаемый учебный коллектив ' || S2;
    SUSPEND;
  END

  -- Создаем ГУП и раскладываем туда учащихся
  -- Зачисление в ГУП идет не 31.08, а 01.09
  VAL = 'Создаем и распределяем ГУП';
  SUSPEND;

  FOR
    SELECT DISTINCT L9.OBJ_ID, V49.LISTVAL_ID, V3119.VAL, C.CAPTION
    FROM LINKS L2
    JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID = 9 AND L9.DATE_DEL IS NULL
    JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    JOIN VALR V3119 ON V3119.OBJ_ID = L10.OBJ_ID AND V3119.PARAM_ID = 3119 AND V3119.IS_DEL = 0
    LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C ON 1 = 1
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :V$GRADE_ID, :V$STAGE_ID, :V$PLAN_ID, :S1
  DO
  BEGIN
    -- ГУП с соответствующим наименованием в соответствующем этапе обучения
    V$PARENT_ID = NULL;
    SELECT FIRST 1 L54.OBJ_ID, LV.COST
    FROM LINKS L54
    JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0 AND V381.LISTVAL_ID = :V$STAGE_ID
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V381.LISTVAL_ID
    WHERE L54.PARENT_ID = :V$PLAN_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
    INTO :V$PARENT_ID, :V$LEVEL;

    IF(V$PARENT_ID IS NULL) THEN
    BEGIN
      S2 = '';
      FOR
        SELECT C.VAL
        FROM LINKS L54
        JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
        LEFT JOIN LISTVAL_TEXT(V381.LISTVAL_ID) C ON 1 = 1
        WHERE L54.PARENT_ID = :V$PLAN_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
        INTO :S1X
      DO
      BEGIN
        IF(S2 <> '') THEN S2 = S2 || ',';
        S2 = S2 || S1X;
      END

      EXCEPTION DATA_ERROR 'Ошибка: в учебном плане отсутствует требуемый этап обучения, ' || V$PLAN_ID || ' ' ||
        (SELECT CAPTION FROM OBJECT_CAPTION_GET(:V$PLAN_ID)) || ', этап ' || V$STAGE_ID || ', ГУП ' || S1 || ' (' || S2 || ')';
    END

    V$GUP_ID = NULL;
    SELECT FIRST 1 L256.OBJ_ID
    FROM LINKS L256
    JOIN VALS V2162 ON V2162.OBJ_ID = L256.OBJ_ID AND V2162.PARAM_ID = 2162 AND V2162.IS_DEL = 0 AND UPPER(V2162.SVAL) = UPPER('будущий ' || :S1)
    WHERE L256.PARENT_ID = :V$PARENT_ID AND L256.OBJ_TYPE_ID = 256 AND L256.DATE_DEL IS NULL
    INTO :V$GUP_ID;

    IF(V$GUP_ID IS NULL) THEN
    BEGIN
      SELECT OBJ_ID FROM OBJECT_ADD(:V$PARENT_ID, 256) INTO :V$GUP_ID;
      VAL = 'Создан ГУП ' || S1 || ' ' || V$GUP_ID || ' в УП ' || V$PARENT_ID;
      SUSPEND;
    END
    ELSE
    BEGIN
      VAL = 'Будущий ГУП ' || S1 || '' || V$GUP_ID || ' в УП ' || V$PARENT_ID;
      SUSPEND;
    END

    -- Задаем название или переименовываем из будущего
    SELECT BLOB_ID FROM VAL_ADD(2162, :V$GUP_ID, :S1) INTO :T;
    -- Маска этапов обучения
    V$LEVEL = BIN_SHL(1, :V$LEVEL);
    SELECT BLOB_ID FROM VAL_ADD(3062, :V$GUP_ID, :V$LEVEL) INTO :T;

    -- Принимаем учеников в ГУП
    FOR
      SELECT L10.OBJ_ID
      FROM LINKS L10
      JOIN VALR V3119 ON V3119.OBJ_ID = L10.OBJ_ID AND V3119.PARAM_ID = 3119 AND V3119.IS_DEL = 0 AND V3119.VAL = :V$PLAN_ID
      WHERE L10.PARENT_ID = :V$GRADE_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
      INTO :T
    DO
    BEGIN
      -- пока без ORDER_ID
      -- приказ берем тот же, которым ученик был зачислен или переведен
      SELECT FIRST 1 M.ORDER_DATE_IN, D.ORDER_NUM
      FROM PERSON_MOVEMENTS M
      JOIN ORDERS D ON D.OBJ_ID = M.ORDER_ID_IN
      WHERE M.PERSON_ID = :T AND M.DATE_DEL IS NULL AND M.DATE_OUT IS NULL
      ORDER BY 1 DESC
      INTO :V$DATE, :S2;

      VAL = 'Зачисляем ' || T || ' в ' || V$GUP_ID;
      SUSPEND;

      SELECT OBJ_ID FROM VARGRP_MOVE_PUPIL(:T, :V$GUP_ID, :S2, :V$DATE, '01.09.' || EXTRACT(YEAR FROM :V$DATE), 0, :I$USER_ID) INTO :T;
    END

  END

  -- Очищаем настройку ГУП
  UPDATE VALR SET IS_DEL = 1 WHERE PARAM_ID = 3119 AND IS_DEL = 0;

  -- Удаляем все старые параметры для перевода в классах
  UPDATE VALS SET IS_DEL = 1 WHERE PARAM_ID = 3118 AND IS_DEL = 0;

  -- Удаляем нулевую параллель
  DELETE FROM OBJECTS O
  WHERE O.TYPE_ID = 8 AND EXISTS(SELECT 1 FROM VALL V49 WHERE V49.OBJ_ID = O.OBJ_ID AND V49.LISTVAL_ID = 12765 AND V49.IS_DEL = 0);

  -- Снимаем флаги "на дистанте", удаляем все записи зачисления на дистант
  UPDATE VALL SET LISTVAL_ID = 3 WHERE PARAM_ID = 2992 AND IS_DEL = 0 AND LISTVAL_ID <> 3; -- ученик
  UPDATE VALL SET LISTVAL_ID = 3 WHERE PARAM_ID = 3053 AND IS_DEL = 0 AND LISTVAL_ID <> 3; -- класс

  -- Очищаем выбор сетки учебных периодов у классов
  -- !!! Переделать на автоподбор периодов по параллелям и названиям
  UPDATE VALR SET IS_DEL = 1 WHERE PARAM_ID IN (3517, 3518) AND IS_DEL = 0;

  SELECT FIRST 1 OBJ_ID
  FROM OBJECTS
  WHERE TYPE_ID = 338
  INTO :V$DST_GROUP;

  DELETE FROM PERSON_MOVEMENTS
  WHERE GROUP_ID = :V$DST_GROUP;

  -- Переименовываем группы по предмету и журналы, убираем слово будущий
  UPDATE CJ2_JOURNAL
  SET JOURNAL_NAME = REPLACE(JOURNAL_NAME, 'будущий ', '')
  WHERE JOURNAL_TYPE IN (0, 1);

  -- Группы переменного состава и оставшиеся ГУП, куда при переводе не выбрали учеников
  UPDATE VALS
  SET VAL = REPLACE(VAL, 'будущий ', '')
  WHERE PARAM_ID IN (2927, 2162) AND IS_DEL = 0;

  -- Переводим в статус архива графики отпусков за прошлые годы
  FOR
    SELECT L534.OBJ_ID
    FROM LINKS L534
    JOIN VALI V3584 ON V3584.OBJ_ID = L534.OBJ_ID AND V3584.PARAM_ID = 3584 AND V3584.IS_DEL = 0 AND V3584.VAL < :V$NEW_YEAR
    JOIN VALL V3585 ON V3585.OBJ_ID = L534.OBJ_ID AND V3585.PARAM_ID = 3585 AND V3585.IS_DEL = 0 AND V3585.LISTVAL_ID = 11715
    WHERE L534.PARENT_ID = :V$OU_ID AND L534.OBJ_TYPE_ID = 534 AND L534.DATE_DEL IS NULL
    ORDER BY 1
    INTO :V$GRADE_ID
  DO
  BEGIN
    UPDATE VALL
    SET LISTVAL_ID = 14261
    WHERE OBJ_ID = :V$GRADE_ID AND PARAM_ID = 3585;
  END

  -- Зачищаем неактуальные учебные планы
  EXECUTE PROCEDURE PLAN_CLEANUP;

  -- Отрабатываем нагрузки сотрудников
  EXECUTE PROCEDURE EDULOAD_PROCESS_DEFER(:V$NEW_YEAR_ID);

  -- Пересчитываем мониторинг действующих УП
  SELECT COUNT(*) FROM MONITORING_PLAN_UPD(NULL) INTO :T;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE YCHANGE_REVIEW (
    I$USER_ID VARCHAR(40))
RETURNS (
    TAG_NAME VARCHAR(200),
    VAL VARCHAR(4000))
AS
DECLARE VARIABLE V$OU_LICENCE_TYPE CHAR(1);
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$TYPE BIGINT;
DECLARE VARIABLE V$STAGE BIGINT;
DECLARE VARIABLE V$DATE DATE;
DECLARE VARIABLE V$I INTEGER;
DECLARE VARIABLE V$C INTEGER;
DECLARE VARIABLE V$C2 INTEGER;
DECLARE VARIABLE S VARCHAR(4000);
DECLARE VARIABLE S2 VARCHAR(1000);
DECLARE VARIABLE S3 VARCHAR(1000);
DECLARE VARIABLE S4 VARCHAR(1000);
DECLARE VARIABLE V$OVZ BIGINT;
DECLARE VARIABLE V$OVZ_YEAR BIGINT;
DECLARE VARIABLE V$OVZ_CHANGE SMALLINT;
DECLARE VARIABLE V$OUT BIGINT;
DECLARE VARIABLE V$Y INTEGER;
DECLARE VARIABLE V VARCHAR(400);
begin

  V$OU_LICENCE_TYPE = (SELECT STATUS FROM OU_LICENCE_TYPE);
  V$Y = EXTRACT(YEAR FROM CURRENT_DATE);

  TAG_NAME = 'ou_type';
  VAL = V$OU_LICENCE_TYPE;
  SUSPEND;

  TAG_NAME = 'orders::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT O.OBJ_ID, O.TYPE_ID, C.VAL, O.ORDER_DATE, COALESCE(O.ORDER_NUM, O.PROJECT_NUM), O.COMMENTS
    FROM ORDERS O
    LEFT JOIN LISTVAL_TEXT(O.TYPE_ID) C ON 1 = 1
    WHERE O.DATE_DEL IS NULL AND O.STATE_ID = 11716 AND O.TYPE_ID IN (12929, 12931, 12932, 12933, 12937) -- приказ об окончании проверяем как ошибку
    INTO :V$OBJ_ID, :V$TYPE, :S3, :V$DATE, :S2, :S
  DO
  BEGIN
    TAG_NAME = 'orders:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'orders:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'orders:r:type_id';
    VAL = V$TYPE;
    SUSPEND;
    TAG_NAME = 'orders:r:type_name';
    VAL = S3;
    SUSPEND;
    TAG_NAME = 'orders:r:project_num';
    VAL = S2;
    SUSPEND;
    TAG_NAME = 'orders:r:comments';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'orders:r:date';
    VAL = (SELECT VAL FROM DATE2ISO(:V$DATE, 0));
    SUSPEND;
    TAG_NAME = 'orders:r:count';
    SELECT COUNT(*)
    FROM ORDER_DATA D
    WHERE D.DATE_DEL IS NULL AND D.ORDER_ID = :V$OBJ_ID
    INTO :VAL;
    SUSPEND;
  END

  -- Все ли обучающиеся распределены ?
  TAG_NAME = 'errors::json&colon;array';
  VAL = 1;
  SUSPEND;
  -- Зачисляемые
  FOR
    SELECT L10.OBJ_ID, R.VAL, V55.SVAL || ' ' || V56.SVAL || COALESCE(' ' || V57.SVAL, '')
    FROM LINKS L2
    JOIN LINKS L77 ON L77.PARENT_ID = L2.OBJ_ID AND L77.OBJ_TYPE_ID = 77 AND L77.DATE_DEL IS NULL
    JOIN LINKS L290 ON L290.PARENT_ID = L77.OBJ_ID AND L290.OBJ_TYPE_ID = 290 AND L290.DATE_DEL IS NULL
    JOIN VALL V2346 ON V2346.OBJ_ID = L290.OBJ_ID AND V2346.PARAM_ID = 2346 AND V2346.IS_DEL = 0
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V2346.LISTVAL_ID
    JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
    JOIN LINKS L10 ON L10.PARENT_ID = L290.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    JOIN VALS V55 ON V55.OBJ_ID = L10.OBJ_ID AND V55.PARAM_ID = 55 AND V55.IS_DEL = 0
    JOIN VALS V56 ON V56.OBJ_ID = L10.OBJ_ID AND V56.PARAM_ID = 56 AND V56.IS_DEL = 0
    LEFT JOIN VALS V57 ON V57.OBJ_ID = L10.OBJ_ID AND V57.PARAM_ID = 57 AND V57.IS_DEL = 0
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    ORDER BY LV.COST, 3
    INTO :V$OBJ_ID, :S, :S2
  DO
  BEGIN
    IF(NOT EXISTS(
      SELECT 1
      FROM ORDER_DATA OD
      JOIN ORDERS O ON O.DATE_DEL IS NULL AND O.OBJ_ID = OD.ORDER_ID AND O.TYPE_ID = 12929 AND O.STATE_ID = 11716 -- зачисление, проект
      WHERE OD.DATE_DEL IS NULL AND OD.REF_ID = :V$OBJ_ID AND OD.ACTION_TYPE = 0
    )) THEN
    BEGIN
      TAG_NAME = 'errors:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'errors:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'errors:r:stage';
      VAL = S;
      SUSPEND;
      TAG_NAME = 'errors:r:name';
      VAL = S2;
      SUSPEND;
      TAG_NAME = 'errors:r:type';
      VAL = 0; -- не распределен предварительный прием
      SUSPEND;
    END
  END

  -- Действующие - перевод, второй год
  -- Оканчивающие должны быть уже отчислены другим приказом, либо включены в проект приказа об окончании
  FOR
    SELECT L10.OBJ_ID, C.CAPTION, V55.SVAL || ' ' || V56.SVAL || COALESCE(' ' || V57.SVAL, ''), COALESCE(V1747.LISTVAL_ID, 3)
    FROM LINKS L2
    JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V49.LISTVAL_ID
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 187) AND L9.DATE_DEL IS NULL -- экстернаты - смотрим только выпускные
    LEFT JOIN VALL V1747 ON V1747.OBJ_ID = L9.OBJ_ID AND V1747.PARAM_ID IN (1747, 1362) AND V1747.IS_DEL = 0
    JOIN LINKS L10 ON L10.PARENT_ID = L9.OBJ_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    JOIN VALS V55 ON V55.OBJ_ID = L10.OBJ_ID AND V55.PARAM_ID = 55 AND V55.IS_DEL = 0
    JOIN VALS V56 ON V56.OBJ_ID = L10.OBJ_ID AND V56.PARAM_ID = 56 AND V56.IS_DEL = 0
    LEFT JOIN VALS V57 ON V57.OBJ_ID = L10.OBJ_ID AND V57.PARAM_ID = 57 AND V57.IS_DEL = 0
    LEFT JOIN OBJECT_CAPTION_GET(L9.OBJ_ID) C ON 1 = 1
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND (L9.OBJ_TYPE_ID = 9 OR V1747.LISTVAL_ID = 2)
    ORDER BY LV.COST, 2, 3
    INTO :V$OBJ_ID, :S, :S2, :V$OUT
  DO     
  BEGIN
    IF(NOT EXISTS(
      SELECT 1
      FROM ORDER_DATA OD
      JOIN ORDERS O ON O.DATE_DEL IS NULL AND O.OBJ_ID = OD.ORDER_ID AND O.TYPE_ID IN (12931, 12932, 12933, 12937) AND O.STATE_ID = 11716 -- перевод, второй год, новый класс, окончание
      WHERE OD.DATE_DEL IS NULL AND OD.REF_ID = :V$OBJ_ID AND OD.ACTION_TYPE = 0 AND (:V$OUT = 3 OR O.TYPE_ID <> 12932) -- для выпускных классов перевод быть не может
    )) THEN
    BEGIN
      TAG_NAME = 'errors:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'errors:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'errors:r:stage'; -- класс
      VAL = S;
      SUSPEND;
      TAG_NAME = 'errors:r:name';
      VAL = S2;
      SUSPEND;
      TAG_NAME = 'errors:r:type';
      VAL = 1; -- не распределен основной состав
      SUSPEND;
    END
  END

  -- Обучающиеся распределены в распускаемые классы, либо указаны как продолжающие там обучение
  FOR
    SELECT L10.OBJ_ID, G.GRADE_NAME_OLD, V55.SVAL || ' ' || V56.SVAL || COALESCE(' ' || V57.SVAL, '')
    FROM YCHANGE_REVIEW_GRADES(:V$OU_LICENCE_TYPE) G
    JOIN LINKS L10 ON L10.PARENT_ID = G.GRADE_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    JOIN ORDER_DATA OD ON OD.DATE_DEL IS NULL AND OD.REF_ID = L10.OBJ_ID
    JOIN ORDERS D ON D.DATE_DEL IS NULL AND D.OBJ_ID = OD.ORDER_ID AND D.STATE_ID = 11716 AND D.TYPE_ID = 12932
    JOIN VALS V55 ON V55.OBJ_ID = L10.OBJ_ID AND V55.PARAM_ID = 55 AND V55.IS_DEL = 0
    JOIN VALS V56 ON V56.OBJ_ID = L10.OBJ_ID AND V56.PARAM_ID = 56 AND V56.IS_DEL = 0
    LEFT JOIN VALS V57 ON V57.OBJ_ID = L10.OBJ_ID AND V57.PARAM_ID = 57 AND V57.IS_DEL = 0
    WHERE G.GRADE_SUFFIX_NEW = '*' OR G.GRADE_NAME_NEW IS NULL
    INTO :V$OBJ_ID, :S, :S2
  DO
  BEGIN
    TAG_NAME = 'errors:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'errors:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'errors:r:stage'; -- класс
    VAL = S;
    SUSPEND;
    TAG_NAME = 'errors:r:name';
    VAL = S2;
    SUSPEND;
    TAG_NAME = 'errors:r:type';
    VAL = 2; -- перевод в расформируемом классе
    SUSPEND;
  END

  -- Перевод/зачисление в несуществующий класс - смотрим все приказы
  -- либо вообще поле назначения не заполнено
  FOR
    SELECT OD.REF_ID, CG.CAPTION, C.CAPTION, COALESCE(V3025.SVAL, 'неуказанный')
    FROM ORDERS O
    JOIN ORDER_DATA OD ON OD.ORDER_ID = O.OBJ_ID AND OD.DATE_DEL IS NULL
    LEFT JOIN VALS V3025 ON V3025.OBJ_ID = OD.REF_ID AND V3025.PARAM_ID = 3025 AND V3025.IS_DEL = 0
    JOIN LINKS LP9 ON LP9.OBJ_ID = OD.REF_ID AND LP9.PARENT_TYPE_ID IN (9, 187, 290) AND LP9.DATE_DEL IS NULL
    LEFT JOIN OBJECT_CAPTION_GET(OD.REF_ID, 23) C ON 1 = 1
    LEFT JOIN OBJECT_CAPTION_GET(LP9.PARENT_ID) CG ON 1 = 1
    WHERE O.DATE_DEL IS NULL AND O.STATE_ID = 11716 AND O.TYPE_ID IN (12929, 12931, 12937)
      AND (POSITION('будущий ' IN V3025.SVAL) > 0 OR V3025.SVAL IS NULL)
    INTO :V$OBJ_ID, :S, :S2, :S3
  DO
  BEGIN
    IF(NOT EXISTS(
      SELECT FIRST 1 1
      FROM YCHANGE_REVIEW_GRADES(:V$OU_LICENCE_TYPE) G
      WHERE 'будущий ' || G.GRADE_NAME_NEW = :S3
    )) THEN
    BEGIN
      TAG_NAME = 'errors:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'errors:r:id';
      VAL = V$OBJ_ID;
      SUSPEND;
      TAG_NAME = 'errors:r:stage'; -- класс
      VAL = S || ' > ' || S3;
      SUSPEND;
      TAG_NAME = 'errors:r:name';
      VAL = S2;
      SUSPEND;
      TAG_NAME = 'errors:r:type';
      VAL = 4; -- несуществующий коллектив
      SUSPEND;
    END
  END

  -- Перевод в класс текущего года вместо будущего класса (перевод по параллели, оставление на повторное обучение)
  FOR
    SELECT OD.REF_ID, CG.CAPTION, C.CAPTION
    FROM ORDERS O
    JOIN ORDER_DATA OD ON OD.ORDER_ID = O.OBJ_ID AND OD.DATE_DEL IS NULL
    JOIN VALS V3025 ON V3025.OBJ_ID = OD.REF_ID AND V3025.PARAM_ID = 3025 AND V3025.IS_DEL = 0 AND POSITION('будущий ' IN V3025.SVAL) <= 0
    JOIN LINKS LP9 ON LP9.OBJ_ID = OD.REF_ID AND LP9.PARENT_TYPE_ID IN (9, 187) AND LP9.DATE_DEL IS NULL
    LEFT JOIN OBJECT_CAPTION_GET(OD.REF_ID, 23) C ON 1 = 1
    LEFT JOIN OBJECT_CAPTION_GET(LP9.PARENT_ID) CG ON 1 = 1
    WHERE O.DATE_DEL IS NULL AND O.TYPE_ID IN (12929, 12931, 12937) AND O.STATE_ID = 11716
    INTO :V$OBJ_ID, :S, :S2
  DO
  BEGIN
    TAG_NAME = 'errors:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'errors:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'errors:r:stage'; -- класс
    VAL = S;
    SUSPEND;
    TAG_NAME = 'errors:r:name';
    VAL = S2;
    SUSPEND;
    TAG_NAME = 'errors:r:type';
    VAL = 5; -- класс текущего года вместо будущего
    SUSPEND;
  END

  -- Ошибки с дублированием названий учебных коллективов
  S = '';
  FOR
    SELECT G.STAGE_ID_NEW, COALESCE(G.GRADE_NAME_NEW, '')
    FROM YCHANGE_REVIEW_GRADES(:V$OU_LICENCE_TYPE) G
    WHERE G.GRADE_NAME_NEW IS NOT NULL AND G.GRADE_SUFFIX_NEW <> '*'
    ORDER BY G.GRADE_NAME_NEW
    INTO :V$STAGE, :S2
  DO
  BEGIN
    IF(S2 <> '' AND S2 = S) THEN
    BEGIN
      TAG_NAME = 'errors:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'errors:r:id';
      VAL = V$STAGE;
      SUSPEND;
      TAG_NAME = 'errors:r:stage';
      VAL = '';
      SUSPEND;
      TAG_NAME = 'errors:r:name';
      VAL = S2;
      SUSPEND;
      TAG_NAME = 'errors:r:type';
      VAL = 3; -- дубликат названия класса
      SUSPEND;
    END
    S = S2;
  END

  -- Запрет оставлять нулевые классы
  FOR
    SELECT G.GRADE_ID, G.GRADE_NAME_OLD, G.STAGE_NAME_OLD
    FROM YCHANGE_REVIEW_GRADES(:V$OU_LICENCE_TYPE) G
    WHERE G.STAGE_COST_OLD = 0 AND G.STAGE_ID_NEW IS NULL
    ORDER BY 2
    INTO :V$STAGE, :S, :S2
  DO
  BEGIN
    TAG_NAME = 'errors:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'errors:r:id';
    VAL = V$STAGE;
    SUSPEND;
    TAG_NAME = 'errors:r:stage';
    VAL = S2;
    SUSPEND;
    TAG_NAME = 'errors:r:name';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'errors:r:type';
    VAL = 6; -- неверная схема для нулевого класса
    SUSPEND;
  END

  -- Выбывшие ученики, забытые в приказах, а также потеряшки предварительного приема
  -- а также ученики, упомянутые более чем в одном приказе
  FOR
    SELECT OD.REF_ID, C.CAPTION, 'Выбывшие/окончившие'
    FROM ORDERS O
    JOIN ORDER_DATA OD ON OD.ORDER_ID = O.OBJ_ID AND OD.DATE_DEL IS NULL
    JOIN LINKS LP9 ON LP9.OBJ_ID = OD.REF_ID AND LP9.PARENT_TYPE_ID IN (81, 82, 83) AND LP9.DATE_DEL IS NULL
    -- выбывшим можно повторно числиться в классе-экстернате и предварительном приеме
    LEFT JOIN LINKS LP187 ON LP187.OBJ_ID = OD.REF_ID AND LP187.PARENT_TYPE_ID IN (187, 290) AND LP187.DATE_DEL IS NULL
    LEFT JOIN OBJECT_CAPTION_GET(OD.REF_ID, 23) C ON 1 = 1
    WHERE O.DATE_DEL IS NULL AND O.STATE_ID = 11716 AND LP187.PARENT_ID IS NULL
    UNION
    SELECT OD.REF_ID, C.CAPTION, 'Потеряшки'
    FROM ORDERS O
    JOIN ORDER_DATA OD ON OD.ORDER_ID = O.OBJ_ID AND OD.DATE_DEL IS NULL
    JOIN OBJECTS OBJ ON OBJ.OBJ_ID = OD.REF_ID AND OBJ.TYPE_ID = 10 -- отсекаем именно учеников, тут могут быть сотрудники
    LEFT JOIN LINKS LP290 ON LP290.OBJ_ID = OD.REF_ID AND LP290.PARENT_TYPE_ID IN (9, 125, 187, 81, 82, 83, 243, 290) AND LP290.DATE_DEL IS NULL
    LEFT JOIN OBJECT_CAPTION_GET(OD.REF_ID, 23) C ON 1 = 1
    WHERE O.DATE_DEL IS NULL AND O.STATE_ID = 11716 AND LP290.PARENT_ID IS NULL
    UNION
    SELECT DISTINCT OD.REF_ID, C.CAPTION, 'Дубликаты в приказе'
    FROM ORDERS O
    JOIN ORDER_DATA OD ON OD.ORDER_ID = O.OBJ_ID AND OD.DATE_DEL IS NULL
    JOIN OBJECTS OBJ ON OBJ.OBJ_ID = OD.REF_ID AND OBJ.TYPE_ID = 10 -- отсекаем именно учеников, тут могут быть сотрудники
    LEFT JOIN OBJECT_CAPTION_GET(OD.REF_ID, 23) C ON 1 = 1
    WHERE O.DATE_DEL IS NULL AND O.STATE_ID = 11716 AND EXISTS (SELECT FIRST 1 1 FROM ORDER_DATA OD2 WHERE OD2.ORDER_ID = O.OBJ_ID AND OD2.DATE_DEL IS NULL AND OD2.OBJ_ID <> OD.OBJ_ID AND OD2.REF_ID = OD.REF_ID)
    UNION
    SELECT OD.REF_ID, C.CAPTION, 'Включен в несколько приказов'
    FROM ORDERS D
    JOIN ORDER_DATA OD ON OD.DATE_DEL IS NULL AND OD.ORDER_ID = D.OBJ_ID
    LEFT JOIN OBJECT_CAPTION_GET(OD.REF_ID, 23) C ON 1 = 1
    WHERE D.DATE_DEL IS NULL AND D.STATE_ID = 11716 AND D.TYPE_ID IN (12929, 12931, 12932, 12933, 12934, 12935, 12936, 12937)
    GROUP BY 1, 2, 3
    HAVING COUNT(*) > 1
    INTO :V$OBJ_ID, :S2, :S3
  DO
  BEGIN
    TAG_NAME = 'errors:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'errors:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'errors:r:stage'; -- класс
    VAL = S3;
    SUSPEND;
    TAG_NAME = 'errors:r:name';
    VAL = S2;
    SUSPEND;
    TAG_NAME = 'errors:r:type';
    VAL = 7; -- забытые ученики
    SUSPEND;
  END

  -- Незакрытые приказы по печати аттестатов
  FOR
    SELECT OD.REF_ID, CG.CAPTION, C.CAPTION
    FROM ORDERS O
    JOIN ORDER_DATA OD ON OD.ORDER_ID = O.OBJ_ID AND OD.DATE_DEL IS NULL
    JOIN LINKS LP9 ON LP9.OBJ_ID = OD.REF_ID AND LP9.PARENT_TYPE_ID IN (9, 125, 187) AND LP9.DATE_DEL IS NULL
    LEFT JOIN OBJECT_CAPTION_GET(OD.REF_ID, 23) C ON 1 = 1
    LEFT JOIN OBJECT_CAPTION_GET(LP9.PARENT_ID) CG ON 1 = 1
    WHERE O.DATE_DEL IS NULL AND O.TYPE_ID = 13326 AND O.STATE_ID = 11716
    INTO :V$OBJ_ID, :S, :S2
  DO
  BEGIN
    TAG_NAME = 'errors:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'errors:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'errors:r:stage'; -- класс
    VAL = S;
    SUSPEND;
    TAG_NAME = 'errors:r:name';
    VAL = S2;
    SUSPEND;
    TAG_NAME = 'errors:r:type';
    VAL = 8; -- незакрытый приказ по аттестатам
    SUSPEND;
  END

  -- Сюда же добавляем документы, не переведенные в завершенный или отмененный статус
  SELECT MON$DATABASE_NAME
  FROM MON$DATABASE
  INTO :V;

  V = REPLACE(V, 'BASE.FDB', 'DOC.FDB');

  -- Испорченные бланки игнорируем и разрешаем удалить таких учеников
  -- только школы и колледжи
  S = NULL;
  IF(V$OU_LICENCE_TYPE IN ('O', 'C', 'S')) THEN
  EXECUTE STATEMENT
    'SELECT FIRST 1 D.OBJ_ID, D.NAME_LAST || '' '' || D.NAME_FIRST
    FROM DOCUMENTS D
    WHERE D.DATE_DEL IS NULL AND D.STATE_ID = 0'
  ON EXTERNAL :V
  -- ROLE 'INISSOFT_ROLE'
  WITH COMMON TRANSACTION
  INTO :V$OBJ_ID, :S;

  IF(S IS NOT NULL) THEN
  BEGIN
    TAG_NAME = 'errors:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'errors:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'errors:r:stage'; -- класс
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'errors:r:name';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'errors:r:type';
    VAL = 8; -- незакрытый приказ по аттестатам
    SUSPEND;
  END

  -- Пустые проекты приказов
  FOR
    SELECT O.OBJ_ID, 'Проект ' || O.PROJECT_NUM
    FROM ORDERS O
    LEFT JOIN ORDER_DATA OD ON OD.ORDER_ID = O.OBJ_ID AND OD.DATE_DEL IS NULL
    WHERE O.DATE_DEL IS NULL AND O.STATE_ID = 11716 AND OD.OBJ_ID IS NULL
    INTO :V$OBJ_ID, :S
  DO
  BEGIN
    TAG_NAME = 'errors:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'errors:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'errors:r:stage';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'errors:r:name';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'errors:r:type';
    VAL = 9; -- пустой проект приказа
    SUSPEND;
  END

  -- Не возвращенные учебники, а для выбывающих учеников вообще все
  -- смотрим только групповую выдачу
  FOR
    SELECT DISTINCT U.REF_ID, C.CAPTION
    FROM LIB2_USAGE U
    JOIN LIB2_BOOKS B ON B.OBJ_ID = U.BOOK_ID AND B.OBJ_TYPE = 18712
    LEFT JOIN OBJECT_CAPTION_GET(U.REF_ID) C ON 1 = 1
    WHERE U.DATE_DEL IS NULL AND U.REF_TYPE_ID = 9 AND U.RETURN_DATE IS NULL AND U.LOSS_DATE IS NULL
    ORDER BY 2
    INTO :V$OBJ_ID, :S
  DO
  BEGIN
    TAG_NAME = 'errors:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'errors:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'errors:r:stage';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'errors:r:name';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'errors:r:type';
    VAL = 10; -- библиограф
    SUSPEND;
  END

  -- Выдаем список учебных планов для создания ГУП, параллельно проверяем этапы для всех классов что продолжают обучение
  -- Только для школ !
  TAG_NAME = 'grades::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    -- Действующие классы
    SELECT G.GRADE_ID, G.TYPE_ID, G.GRADE_NAME_OLD, G.GRADE_NAME_NEW, G.STAGE_ID_NEW, G.STAGE_COST_NEW, G.OVZ, G.OVZ_YEAR, G.CNT_OLD, G.CNT_NEW, G.OVZ_CHANGE,
      G.STAGE_NAME_NEW, G.GRADE_SUFFIX_NEW
    FROM YCHANGE_REVIEW_GRADES(:V$OU_LICENCE_TYPE) G
    ORDER BY ABS(G.STAGE_COST_NEW)
    INTO :V$OBJ_ID, :V$TYPE, :S, :S2, :V$STAGE, :V$I, :V$OVZ, :V$OVZ_YEAR, :V$C, :V$C2, :V$OVZ_CHANGE,
      :S3, :S4
  DO
  BEGIN
    TAG_NAME = 'grades:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'grades:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'grades:r:name_before';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'grades:r:name_after';
    VAL = S2;
    SUSPEND;

    TAG_NAME = 'grades:r:prefix_after';
    VAL = S3;
    SUSPEND;
    TAG_NAME = 'grades:r:suffix_after';
    VAL = S4;
    SUSPEND;

    TAG_NAME = 'grades:r:stage';
    VAL = V$STAGE;
    SUSPEND;
    TAG_NAME = 'grades:r:stage_index';
    VAL = V$I;
    SUSPEND;
    TAG_NAME = 'grades:r:type';
    VAL = V$TYPE;
    SUSPEND;
    TAG_NAME = 'grades:r:ovz';
    VAL = V$OVZ;
    SUSPEND;
    TAG_NAME = 'grades:r:ovz_year';
    VAL = V$OVZ_YEAR;
    SUSPEND;
    TAG_NAME = 'grades:r:ovz_change';
    VAL = V$OVZ_CHANGE;
    SUSPEND;
    TAG_NAME = 'grades:r:n_before';
    VAL = V$C;
    SUSPEND;
    TAG_NAME = 'grades:r:n_after';
    VAL = V$C2;
    SUSPEND;

    -- Список УП, в которых запланированы будущие ГУП - нужны для раскраски приоритетов
    -- убираем фильтрацию по году ОП, разрешаем вообще все
    S3 = 'будущий ' || S2;
    TAG_NAME = 'grades:r:plans';
    VAL = NULL;
    SELECT LIST(CAST(L400.OBJ_ID AS VARCHAR(40)), ',')
    FROM LINKS L2
    JOIN LINKS L69 ON L69.PARENT_ID = L2.OBJ_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL
    JOIN VALL V2450 ON V2450.OBJ_ID = L69.OBJ_ID AND V2450.PARAM_ID = 2450 AND V2450.IS_DEL = 0 AND V2450.LISTVAL_ID IN (11385)
    JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
    JOIN VALL V1594 ON V1594.OBJ_ID = L57.OBJ_ID AND V1594.PARAM_ID = 1594 AND V1594.IS_DEL = 0 AND V1594.LISTVAL_ID IN (5339, 5341, 5343)
    JOIN VALI V3115 ON V3115.OBJ_ID = L57.OBJ_ID AND V3115.PARAM_ID = 3115 AND V3115.IS_DEL = 0 -- AND V3115.VAL = :V$Y
    JOIN LINKS L400 ON L400.PARENT_ID = L57.OBJ_ID AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL
    JOIN VALL V3022 ON V3022.OBJ_ID = L400.OBJ_ID AND V3022.PARAM_ID = 3022 AND V3022.IS_DEL = 0 AND V3022.LISTVAL_ID = 3
    JOIN VALL V3013 ON V3013.OBJ_ID = L400.OBJ_ID AND V3013.PARAM_ID = 3013 AND V3013.IS_DEL = 0 AND V3013.LISTVAL_ID = 11715
    -- Только групповые
    JOIN VALL V3016 ON V3016.OBJ_ID = L400.OBJ_ID AND V3016.PARAM_ID = 3016 AND V3016.IS_DEL = 0 AND V3016.LISTVAL_ID = 5465
    -- Этапы и ГУП
    JOIN LINKS L54 ON L54.PARENT_ID = L400.OBJ_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
    JOIN LINKS L256 ON L256.PARENT_ID = L54.OBJ_ID AND L256.OBJ_TYPE_ID = 256 AND L256.DATE_DEL IS NULL
    JOIN VALS V2162 ON V2162.OBJ_ID = L256.OBJ_ID AND V2162.PARAM_ID = 2162 AND V2162.IS_DEL = 0 AND V2162.SVAL = :S3
    WHERE :V$OU_LICENCE_TYPE IN ('O', 'S') AND L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :VAL;
    SUSPEND;
  END

  -- Выдаем из всех папок ОП с годом Y - 1, где название содержит новый учебный год, либо год ОП точно равен
  S4 = '%' || V$Y || '-' || (V$Y + 1) || '%';
  TAG_NAME = 'plans::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L400.OBJ_ID, C.CAPTION
    FROM LINKS L2
    JOIN LINKS L69 ON L69.PARENT_ID = L2.OBJ_ID AND L69.OBJ_TYPE_ID = 69 AND L69.DATE_DEL IS NULL
    JOIN VALL V2450 ON V2450.OBJ_ID = L69.OBJ_ID AND V2450.PARAM_ID = 2450 AND V2450.IS_DEL = 0 AND V2450.LISTVAL_ID IN (11385)
    JOIN LINKS L57 ON L57.PARENT_ID = L69.OBJ_ID AND L57.OBJ_TYPE_ID = 57 AND L57.DATE_DEL IS NULL
    JOIN VALL V1594 ON V1594.OBJ_ID = L57.OBJ_ID AND V1594.PARAM_ID = 1594 AND V1594.IS_DEL = 0 AND V1594.LISTVAL_ID IN (5339, 5341, 5343)
    JOIN LISTVALS LV1594 ON LV1594.LISTVAL_ID = V1594.LISTVAL_ID
    JOIN VALI V3115 ON V3115.OBJ_ID = L57.OBJ_ID AND V3115.PARAM_ID = 3115 AND V3115.IS_DEL = 0 AND V3115.VAL >= :V$Y - 1
    JOIN LINKS L400 ON L400.PARENT_ID = L57.OBJ_ID AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL
    JOIN VALL V3022 ON V3022.OBJ_ID = L400.OBJ_ID AND V3022.PARAM_ID = 3022 AND V3022.IS_DEL = 0 AND V3022.LISTVAL_ID = 3
    JOIN VALL V3013 ON V3013.OBJ_ID = L400.OBJ_ID AND V3013.PARAM_ID = 3013 AND V3013.IS_DEL = 0 AND V3013.LISTVAL_ID = 11715
    -- Только групповые
    JOIN VALL V3016 ON V3016.OBJ_ID = L400.OBJ_ID AND V3016.PARAM_ID = 3016 AND V3016.IS_DEL = 0 AND V3016.LISTVAL_ID = 5465
    LEFT JOIN OBJECT_CAPTION_GET(L400.OBJ_ID) C ON 1 = 1
    WHERE :V$OU_LICENCE_TYPE IN ('O', 'S') AND L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND (V3115.VAL = :V$Y OR C.CAPTION LIKE :S4)
    ORDER BY LV1594.SORT_ORDER, 2
    INTO :V$OBJ_ID, :S
  DO
  BEGIN
    TAG_NAME = 'plans:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'plans:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'plans:r:name';
    VAL = S;
    SUSPEND;

    S = '';
    FOR
      SELECT V381.LISTVAL_ID, R.VAL
      FROM LINKS L54
      JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
      JOIN LISTVALS LV ON LV.LISTVAL_ID = V381.LISTVAL_ID
      JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
      WHERE L54.PARENT_ID = :V$OBJ_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
      ORDER BY LV.COST
      INTO :V$TYPE, :S2
    DO
    BEGIN
      S = S || '|' || V$TYPE || ';' || S2;
    END

    TAG_NAME = 'plans:r:stages';
    VAL = S;
    SUSPEND;
  END

  TAG_NAME = 'calendar::json&colon;array';
  VAL = 1;
  SUSPEND;
  FOR
    SELECT L151.OBJ_ID, V1147.VAL
    FROM LINKS L2
    JOIN LINKS L481 ON L481.PARENT_ID = L2.OBJ_ID AND L481.OBJ_TYPE_ID = 481 AND L481.DATE_DEL IS NULL
    -- разрешаем работать и с проектом
    -- JOIN VALL V3390 ON V3390.OBJ_ID = L481.OBJ_ID AND V3390.PARAM_ID = 3390 AND V3390.IS_DEL = 0 AND V3390.LISTVAL_ID = 11715 -- действующий
    JOIN VALL V3389 ON V3389.OBJ_ID = L481.OBJ_ID AND V3389.PARAM_ID = 3389 AND V3389.IS_DEL = 0
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V3389.LISTVAL_ID AND LV.COST = :V$Y -- новый учебный год
    JOIN LINKS L151 ON L151.PARENT_ID = L481.OBJ_ID AND L151.OBJ_TYPE_ID = 151 AND L151.DATE_DEL IS NULL
    JOIN VALS V1147 ON V1147.OBJ_ID = L151.OBJ_ID AND V1147.PARAM_ID = 1147 AND V1147.IS_DEL = 0
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL AND
      EXISTS(
        SELECT FIRST 1 1
        FROM LINKS L154
        JOIN VALD V1169 ON V1169.OBJ_ID = L154.OBJ_ID AND V1169.PARAM_ID = 1169 AND V1169.IS_DEL = 0 AND V1169.VAL >= '01.09.' || :V$Y AND V1169.VAL <= '31.05.' || (:V$Y + 1)
        WHERE L154.PARENT_ID = L151.OBJ_ID AND L154.OBJ_TYPE_ID = 154 AND L154.DATE_DEL IS NULL
      )
    INTO :V$OUT, :S
  DO
  BEGIN
    TAG_NAME = 'calendar:r';
    VAL = NULL;
    SUSPEND;
    TAG_NAME = 'calendar:r:id';
    VAL = V$OBJ_ID;
    SUSPEND;
    TAG_NAME = 'calendar:r:name';
    VAL = S;
    SUSPEND;
    TAG_NAME = 'calendar:r:periods::json&colon;array';
    VAL = 1;
    SUSPEND;
    FOR
      SELECT C.VAL, D1.VAL, D2.VAL
      FROM LINKS L154
      JOIN VALL V1170 ON V1170.OBJ_ID = L154.OBJ_ID AND V1170.PARAM_ID = 1170 AND V1170.IS_DEL = 0
      JOIN VALD V1169 ON V1169.OBJ_ID = L154.OBJ_ID AND V1169.PARAM_ID = 1169 AND V1169.IS_DEL = 0
        AND V1169.VAL >= '01.09.' || :V$Y AND V1169.VAL <= '31.05.' || (:V$Y + 1)
      JOIN VALD V1174 ON V1174.OBJ_ID = L154.OBJ_ID AND V1174.PARAM_ID = 1174 AND V1174.IS_DEL = 0
      LEFT JOIN LISTVAL_TEXT(V1170.LISTVAL_ID) C ON 1 = 1
      LEFT JOIN DATE2ISO(V1169.VAL, 0) D1 ON 1 = 1
      LEFT JOIN DATE2ISO(V1174.VAL, 0) D2 ON 1 = 1
      WHERE L154.PARENT_ID = :V$OUT AND L154.OBJ_TYPE_ID = 154 AND L154.DATE_DEL IS NULL
      ORDER BY V1170.LISTVAL_ID
      INTO :S, :S2, :S3
    DO
    BEGIN
      TAG_NAME = 'calendar:r:periods:r';
      VAL = NULL;
      SUSPEND;
      TAG_NAME = 'calendar:r:periods:r:name';
      VAL = S;
      SUSPEND;
      TAG_NAME = 'calendar:r:periods:r:from';
      VAL = S2;
      SUSPEND;
      TAG_NAME = 'calendar:r:periods:r:to';
      VAL = S3;
      SUSPEND;
    END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE YCHANGE_REVIEW_GRADES (
    I$OU_TYPE CHAR(1) = 'O',
    I$GRADE_ID BIGINT = NULL)
RETURNS (
    GRADE_ID BIGINT,
    TYPE_ID BIGINT,
    STAGE_ID_OLD BIGINT,
    STAGE_NAME_OLD VARCHAR(100),
    STAGE_COST_OLD INTEGER,
    STAGE_ID_NEW BIGINT,
    STAGE_NAME_NEW VARCHAR(100),
    STAGE_COST_NEW INTEGER,
    GRADE_NAME_OLD VARCHAR(400),
    GRADE_NAME_NEW VARCHAR(400),
    GRADE_SUFFIX_NEW VARCHAR(400),
    OVZ BIGINT,
    OVZ_YEAR BIGINT,
    CNT_OLD INTEGER,
    CNT_NEW INTEGER,
    IS_OUT BIGINT,
    OVZ_CHANGE SMALLINT)
AS
DECLARE VARIABLE V$NAME VARCHAR(400);
DECLARE VARIABLE V$ATTRS VARCHAR(1000);
DECLARE VARIABLE V$MAX_STAGE INTEGER;
DECLARE VARIABLE V$STAGE_LEVEL BIGINT;
DECLARE VARIABLE V$STAGE_TEMP BIGINT;
begin

  -- STAGE выдается по состоянию ПОСЛЕ перевода года
  -- OVZ_YEAR указывает статус ПОСЛЕ перевода года

  SELECT MAX(LV.COST)
  FROM LINKS L2
  JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
  JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
  JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V49.LISTVAL_ID
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$MAX_STAGE;

  FOR
    SELECT L9.OBJ_ID, L9.OBJ_TYPE_ID, COALESCE(VN.VAL, ''), V49.LISTVAL_ID, LV.COST, R.VAL, COALESCE(NN.VAL, ''), COALESCE(V592.LISTVAL_ID, 197), COALESCE(V3024.LISTVAL_ID, 12965),
      COALESCE(V3344.LISTVAL_ID, V1362.LISTVAL_ID, 3), V43.LISTVAL_ID
    FROM LINKS L2
    JOIN LINKS L7 ON L7.PARENT_ID = L2.OBJ_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
    JOIN VALL V43 ON V43.OBJ_ID = L7.OBJ_ID AND V43.PARAM_ID = 43 AND V43.IS_DEL = 0
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0
    JOIN LISTVALS LV ON LV.LISTVAL_ID = V49.LISTVAL_ID
    JOIN LISTVALS LVP ON LVP.LISTVAL_ID = LV.PARENT_ID
    JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
    JOIN LINKS L9 ON L9.PARENT_ID = L8.OBJ_ID AND L9.OBJ_TYPE_ID IN (9, 403) AND L9.DATE_DEL IS NULL AND (:I$GRADE_ID IS NULL OR L9.OBJ_ID = :I$GRADE_ID)
    -- Название
    LEFT JOIN VALS VN ON VN.OBJ_ID = L9.OBJ_ID AND VN.PARAM_ID IN (54, 3026) AND VN.IS_DEL = 0
    -- Атрибуты и новое название
    LEFT JOIN VALS NN ON NN.OBJ_ID = L9.OBJ_ID AND NN.PARAM_ID = 3118 AND NN.IS_DEL = 0
    -- Тип класса по ОВЗ и год обучения
    LEFT JOIN VALL V592 ON V592.OBJ_ID = L9.OBJ_ID AND V592.PARAM_ID IN (592, 3117) AND V592.IS_DEL = 0
    LEFT JOIN VALL V3024 ON V3024.OBJ_ID = L9.OBJ_ID AND V3024.PARAM_ID IN (3024, 3114) AND V3024.IS_DEL = 0
    -- Выпускной для школ ?
    LEFT JOIN VALL V1362 ON V1362.OBJ_ID = L9.OBJ_ID AND V1362.PARAM_ID = 1362 AND V1362.IS_DEL = 0
    -- Выпускной для СПО ?
    LEFT JOIN VALL V3344 ON V3344.OBJ_ID = L9.OBJ_ID AND V3344.PARAM_ID = 3344 AND V3344.IS_DEL = 0
    WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    ORDER BY LVP.SORT_ORDER, LV.COST
    INTO :GRADE_ID, :TYPE_ID, :V$NAME, :STAGE_ID_OLD, :STAGE_COST_OLD, :STAGE_NAME_OLD, :V$ATTRS, :OVZ, :OVZ_YEAR, :IS_OUT, :V$STAGE_LEVEL
  DO
  BEGIN

    GRADE_SUFFIX_NEW = NULL;
    GRADE_NAME_OLD = V$NAME;
    IF(I$OU_TYPE IN ('O', 'C') OR V$STAGE_LEVEL IN (22, 26, 27, 28, 29)) THEN GRADE_NAME_OLD = STAGE_COST_OLD || ' ' || GRADE_NAME_OLD; -- номер параллели
    IF(I$OU_TYPE = 'D' OR V$STAGE_LEVEL IN (3263, 3264)) THEN GRADE_NAME_OLD = STAGE_NAME_OLD || ' ' || GRADE_NAME_OLD; -- в ДОУ - название этапа
    IF(OVZ <> 13275) THEN OVZ_YEAR = 12965;

    -- Исправляем V$NAME на новое название
    IF(POSITION(';' IN V$ATTRS) > 0) THEN
    BEGIN
      -- Если новый суффикс не заполнен - оставляем старый
      IF(POSITION(';' IN V$ATTRS) > 1) THEN V$NAME = SUBSTRING(V$ATTRS FROM 1 FOR POSITION(';' IN V$ATTRS) - 1);
      V$ATTRS = SUBSTRING(V$ATTRS FROM POSITION(';' IN V$ATTRS) + 1);
    END
    ELSE
    BEGIN
      -- V$NAME остается как было
      IF(V$ATTRS <>  '') THEN V$NAME = V$ATTRS;
      V$ATTRS = '';
    END

    -- Новый номер параллели
    OVZ_CHANGE = NULL;
    IF(OVZ = 13275) THEN
    BEGIN
      -- Класс с ОВЗ
      IF(TYPE_ID = 403) THEN
      BEGIN
        -- Год обучения берем как есть
        OVZ_CHANGE = 0;
      END
      ELSE IF(POSITION('@' IN V$ATTRS) > 0) THEN
      BEGIN
        -- Та же параллель без указания года - предполагается, что не будет случаев повторного оставления параллели
        STAGE_COST_NEW = STAGE_COST_OLD;
        OVZ_YEAR = 12965;
        OVZ_CHANGE = 1;
      END
      ELSE IF(POSITION('^' IN V$ATTRS) > 0) THEN
      BEGIN
        -- Следующая параллель без указания года - предполагается, что не будет случаев повторного оставления параллели
        STAGE_COST_NEW = STAGE_COST_OLD + 1;
        OVZ_YEAR = 12965;
        OVZ_CHANGE = 4;
      END
      ELSE IF(POSITION('1' IN V$ATTRS) > 0) THEN
      BEGIN
        -- Первый год следующей параллели
        STAGE_COST_NEW = STAGE_COST_OLD + 1;
        OVZ_YEAR = 12938;
        OVZ_CHANGE = 5;
      END
      ELSE IF(POSITION('2' IN V$ATTRS) > 0) THEN
      BEGIN
        -- Второй год следующей параллели
        STAGE_COST_NEW = STAGE_COST_OLD + 1;
        OVZ_YEAR = 12939;
        OVZ_CHANGE = 6;
      END
      ELSE IF(POSITION('X' IN V$ATTRS) > 0) THEN
      BEGIN
        -- Второй год той же параллели
        STAGE_COST_NEW = STAGE_COST_OLD;
        OVZ_YEAR = 12939;
        OVZ_CHANGE = 3;
      END
      ELSE
      BEGIN
        -- default
        STAGE_COST_NEW = STAGE_COST_OLD;
        IF(OVZ_YEAR = 12938) THEN
        BEGIN
          OVZ_YEAR = 12939; -- из первого года во второй год
          OVZ_CHANGE = 3;
        END
        ELSE IF(OVZ_YEAR = 12939) THEN
        BEGIN
          OVZ_YEAR = 12938; -- из второго года в первый год следующего этапа
          STAGE_COST_NEW = STAGE_COST_NEW + 1;
          OVZ_CHANGE = 5;
        END
        ELSE
        BEGIN
          STAGE_COST_NEW = STAGE_COST_NEW + 1; -- без указания года идем на следующий этап
          OVZ_CHANGE = 4;
        END
      END
      IF(STAGE_COST_NEW = 13) THEN IS_OUT = 2; -- если вдруг получился 13-й класс - считаем что 12-й выпускной
    END
    ELSE IF(IS_OUT = 3) THEN
    BEGIN
      -- Переходной класс
      -- Для ДОУ разновозрастные группы остаются на своих местах
      IF(TYPE_ID = 403) THEN BEGIN
        STAGE_COST_NEW = STAGE_COST_OLD;
      END
      ELSE IF(STAGE_ID_OLD IN (33, 3262)) THEN
      BEGIN
        STAGE_COST_NEW = STAGE_COST_OLD;
      END
      ELSE
      BEGIN
        STAGE_COST_NEW = STAGE_COST_OLD + 1;
        IF(STAGE_COST_NEW = 13) THEN IS_OUT = 2; -- если вдруг получился 13-й класс - считаем что 12-й выпускной
      END
    END

    -- Школы, где это последний этап обучения из имеющихся, даже если не указано иное - распускаем класс
    IF((I$OU_TYPE = 'O' OR V$STAGE_LEVEL IN (22, 26, 27)) AND TYPE_ID IN (9, 187) AND IS_OUT = 3) THEN
    BEGIN
      IF(STAGE_COST_NEW > V$MAX_STAGE) THEN IS_OUT = 2;
    END
    -- В садах нет признака окончания обучения, распускаем последний по списку этап обучения
    IF((I$OU_TYPE = 'D' OR V$STAGE_LEVEL IN (3263, 3264)) AND TYPE_ID IN (9) AND IS_OUT = 3) THEN
    BEGIN
      -- Максимальный номер этапа для мультипараграфа будет неправильный
      IF(STAGE_COST_NEW > V$MAX_STAGE AND I$OU_TYPE = 'D') THEN IS_OUT = 2;
      -- в ДОУ подготовительная группа всегда выпускная, но только в садах. В Мультипараграфе разрешаем переводиться
      IF(STAGE_ID_OLD = 36 AND I$OU_TYPE = 'D') THEN IS_OUT = 2;
      -- а также если есть только ясли, то первая младшая также выпускная
      IF(V$MAX_STAGE IN (3, 4) AND STAGE_ID_OLD = 32) THEN IS_OUT = 2;
    END
    -- СПО смотрим отдельный атрибут для выпускных
    IF((I$OU_TYPE = 'C' OR V$STAGE_LEVEL IN (28, 29)) AND TYPE_ID IN (9) AND IS_OUT = 3) THEN
    BEGIN
      IF(STAGE_COST_NEW > V$MAX_STAGE) THEN IS_OUT = 2;
    END

    -- Расформируемый класс
    IF(V$NAME = '*') THEN STAGE_COST_NEW = - STAGE_COST_NEW;

    V$STAGE_TEMP = STAGE_ID_OLD;
    IF(TYPE_ID = 403) THEN
    BEGIN
      GRADE_NAME_OLD = NULL;
      STAGE_NAME_OLD = NULL;
      STAGE_ID_NEW = STAGE_ID_OLD;
      STAGE_ID_OLD = NULL;
      STAGE_COST_NEW = STAGE_COST_OLD;
      STAGE_COST_OLD = NULL;
      V$STAGE_TEMP = NULL;

      SELECT FIRST 1 V.VAL
      FROM LISTVAL_TEXT(:STAGE_ID_NEW) V
      INTO :STAGE_NAME_NEW;
    END
    -- Выпускной класс
    ELSE IF(IS_OUT = 2) THEN
    BEGIN
      STAGE_ID_NEW = NULL;
      STAGE_COST_NEW = 9999;
      STAGE_NAME_NEW = 'Выпуск';
    END
    ELSE
    BEGIN
      -- Выбираем всегда в том же уровне образования, кроме случая когда подготовительная группа продолжает обучение
      -- Возможно имеет смысл отдельно указать уровень группы ДОУ, переходящей в обучение в школу ?
      IF(STAGE_ID_OLD = 36) THEN
      BEGIN
        STAGE_COST_NEW = 1;
        V$STAGE_TEMP = 37;
      END

      SELECT FIRST 1 LV2.LISTVAL_ID, R.VAL
      FROM LISTVALS LV
      -- Из порядка сортировки прячем разновозрастные группы, кроме случая когда они и есть сейчас
      JOIN LISTVALS LV2 ON LV2.LIST_ID = LV.LIST_ID AND LV2.IS_DEL = 0 AND LV2.PARENT_ID = LV.PARENT_ID AND LV2.PARENT_ID <> 12941
        AND LV2.COST >= ABS(:STAGE_COST_NEW) AND (LV2.LISTVAL_ID NOT IN (33, 3262) OR :V$STAGE_TEMP IN (33, 3262))
      JOIN RES R ON R.RES_ID = LV2.RES_ID AND R.LANG_CODE = 'RU'
      WHERE LV.LISTVAL_ID = :V$STAGE_TEMP
      ORDER BY LV2.COST, LV2.LISTVAL_ID
      INTO :STAGE_ID_NEW, :STAGE_NAME_NEW;
    END

    -- Специально чтобы переводная группа ДОУ правильно назвалась (V$STAGE_TEMP)
    GRADE_SUFFIX_NEW = V$NAME;
    GRADE_NAME_NEW = V$NAME;
    IF(I$OU_TYPE IN ('O', 'C') OR V$STAGE_LEVEL IN (22, 26, 27, 28, 29) OR V$STAGE_TEMP = 37) THEN GRADE_NAME_NEW = CAST(ABS(STAGE_COST_NEW) AS INTEGER) || ' ' || V$NAME;
    ELSE IF(I$OU_TYPE = 'D' OR V$STAGE_LEVEL IN (3263, 3264)) THEN GRADE_NAME_NEW = STAGE_NAME_NEW || ' ' || V$NAME;
    IF(STAGE_ID_NEW IS NULL) THEN GRADE_NAME_NEW = NULL;

    -- Количества обучающихся
    SELECT COUNT(*)
    FROM LINKS L10
    WHERE L10.DATE_DEL IS NULL AND L10.PARENT_ID = :GRADE_ID AND L10.OBJ_TYPE_ID = 10
    INTO :CNT_OLD;

    -- Все кто запланирован в новый класс при переводе, оставлении на второй год или новом зачислении
    SELECT COUNT(DISTINCT REF_ID)
    FROM (
      SELECT D.REF_ID
      FROM ORDERS O
      JOIN ORDER_DATA D ON D.DATE_DEL IS NULL AND D.ORDER_ID = O.OBJ_ID
      JOIN VALS V3025 ON V3025.OBJ_ID = D.REF_ID AND V3025.PARAM_ID = 3025 AND V3025.IS_DEL = 0 AND V3025.SVAL = 'будущий ' || :GRADE_NAME_NEW
      WHERE O.DATE_DEL IS NULL AND O.STATE_ID = 11716 AND O.TYPE_ID IN (12929, 12931, 12937)
      UNION
      SELECT D.REF_ID
      FROM LINKS L10
      JOIN ORDER_DATA D ON D.DATE_DEL IS NULL AND D.REF_ID = L10.OBJ_ID
      JOIN ORDERS O ON O.DATE_DEL IS NULL AND O.STATE_ID = 11716 AND O.TYPE_ID = 12932 AND O.OBJ_ID = D.ORDER_ID
      WHERE L10.PARENT_ID = :GRADE_ID AND L10.OBJ_TYPE_ID = 10 AND L10.DATE_DEL IS NULL
    )
    INTO :CNT_NEW;

    SUSPEND;

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE YCHANGE_SETATTR (
    I$GRADE_ID BIGINT,
    I$NAME VARCHAR(1000),
    I$ATTR INTEGER,
    I$USER_ID VARCHAR(40))
AS
declare variable V$TYPE_ID bigint;
declare variable P integer;
declare variable S varchar(1000);
declare variable SX varchar(40);
begin

  -- Может передаваться или название, или настройка года (ATTR)
  SELECT OBJ.TYPE_ID, COALESCE(V3118.VAL, ';')
  FROM OBJECTS OBJ
  LEFT JOIN VALS V3118 ON V3118.OBJ_ID = OBJ.OBJ_ID AND V3118.PARAM_ID = 3118 AND V3118.IS_DEL = 0
  WHERE OBJ.OBJ_ID = :I$GRADE_ID
  INTO :V$TYPE_ID, :S;

  IF(V$TYPE_ID = 403) THEN EXCEPTION DATA_ERROR 'Данная настройка выполняется непосредственно в учебном коллективе';

  P = POSITION(';' IN S);

  IF(I$NAME IS NOT NULL) THEN
  BEGIN
    IF(POSITION(';' IN I$NAME) > 0) THEN EXCEPTION DATA_ERROR 'Нельзя использовать точку с запятой в названии коллектива';
    S = I$NAME || ';' || SUBSTRING(S FROM P + 1);
  END
  ELSE IF(I$ATTR IS NOT NULL) THEN
  BEGIN
    IF(I$ATTR = 1) THEN SX = '@';
    ELSE IF(I$ATTR = 2) THEN SX = '*'; -- этого варианта нет
    ELSE IF(I$ATTR = 3) THEN SX = 'X';
    ELSE IF(I$ATTR = 4) THEN SX = '^';
    ELSE IF(I$ATTR = 5) THEN SX = '1';
    ELSE IF(I$ATTR = 6) THEN SX = '2';
    ELSE SX = '';
    S = SUBSTRING(S FROM 1 FOR P - 1) || ';' || SX;
  END

  UPDATE OR INSERT INTO VALS
  (OBJ_ID, PARAM_ID, VAL, IS_DEL)
  VALUES (:I$GRADE_ID, 3118, :S, 0)
  MATCHING (OBJ_ID, PARAM_ID);

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE YCHANGE_SETCAL (
    I$FROM1 DATE NOT NULL,
    I$TO1 DATE NOT NULL,
    I$FROM2 DATE NOT NULL,
    I$TO2 DATE NOT NULL,
    I$FROM3 DATE NOT NULL,
    I$TO3 DATE NOT NULL,
    I$USER_ID VARCHAR(40))
AS
DECLARE VARIABLE V$YEAR_ID BIGINT;
DECLARE VARIABLE V$YEAR INTEGER;
DECLARE VARIABLE V$FOLDER_ID BIGINT;
DECLARE VARIABLE T BIGINT;
DECLARE VARIABLE V$CAL_ID BIGINT;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$OU_ID BIGINT;
DECLARE VARIABLE V$PERIOD BIGINT;
DECLARE VARIABLE V$PREV BIGINT;
begin

  SELECT V1236.LISTVAL_ID, LV.COST, L2.OBJ_ID
  FROM LINKS L2
  JOIN VALL V1236 ON V1236.OBJ_ID = L2.OBJ_ID AND V1236.PARAM_ID = 1236 AND V1236.IS_DEL = 0
  JOIN LISTVALS LV ON LV.LISTVAL_ID = V1236.LISTVAL_ID
  WHERE L2.PARENT_ID IS NULL AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
  INTO :V$YEAR_ID, :V$YEAR, :V$OU_ID;

  IF(V$OU_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Системная ошибка. Не внесена образовательная организация, или не задан текущий учебный год';

  -- Обновлять учебные периоды можно только на новый учебный год
  IF(EXTRACT(YEAR FROM CURRENT_DATE) <> V$YEAR + 1) THEN EXCEPTION DATA_ERROR 'Учебные периоды можно обновлять только на будущий учебный год';
  V$YEAR = V$YEAR + 1;

  -- ID года надо пересчитать
  V$YEAR_ID = NULL;
  SELECT FIRST 1 LV.LISTVAL_ID
  FROM LISTVALS LV
  WHERE LV.LIST_ID = 29 AND LV.IS_DEL = 0 AND LV.COST = :V$YEAR
  INTO :V$YEAR_ID;

  IF(V$YEAR_ID IS NULL) THEN EXCEPTION DATA_ERROR 'В справочнике нет записи для следующего учебного года, свяжитесь с поддержкой. Либо у вас внесен неадекватный текущий учебный год';

  SELECT FIRST 1 L481.OBJ_ID
  FROM LINKS L481
  JOIN VALL V3389 ON V3389.OBJ_ID = L481.OBJ_ID AND V3389.PARAM_ID = 3389 AND V3389.IS_DEL = 0 AND V3389.LISTVAL_ID = :V$YEAR_ID
  WHERE L481.PARENT_ID = :V$OU_ID AND L481.OBJ_TYPE_ID = 481 AND L481.DATE_DEL IS NULL
  INTO :V$FOLDER_ID;

  -- Создаем КУГ - нельзя через OBJECT_ADD
  IF(V$FOLDER_ID IS NULL) THEN
  BEGIN
    SELECT OBJ_ID FROM OBJECT_ADD(:V$OU_ID, 481) INTO :V$FOLDER_ID;
    SELECT 1 FROM VAL_ADD(3389, :V$FOLDER_ID, :V$YEAR_ID) INTO :T;
  END

  -- Периоды для 1-9 классов, четверти
  V$CAL_ID = NULL;
  SELECT FIRST 1 L151.OBJ_ID
  FROM LINKS L151
  JOIN LINKS L154 ON L154.PARENT_ID = L151.OBJ_ID AND L154.OBJ_TYPE_ID = 154 AND L154.DATE_DEL IS NULL
  JOIN VALL V1170 ON V1170.OBJ_ID = L154.OBJ_ID AND V1170.PARAM_ID = 1170 AND V1170.IS_DEL = 0 AND V1170.LISTVAL_ID IN (12, 13, 14, 15)
  JOIN VALD V1169 ON V1169.OBJ_ID = L154.OBJ_ID AND V1169.PARAM_ID = 1169 AND V1169.IS_DEL = 0 AND V1169.VAL >= '01.09.' || :V$YEAR AND V1169.VAL <= '31.05.' || (:V$YEAR + 1)
  WHERE L151.PARENT_ID = :V$FOLDER_ID AND L151.OBJ_TYPE_ID = 151 AND L151.DATE_DEL IS NULL
  INTO :V$CAL_ID;

  IF(V$CAL_ID IS NULL) THEN
  BEGIN

    SELECT OBJ_ID FROM OBJECT_ADD(:V$FOLDER_ID, 151) INTO :V$CAL_ID;
    SELECT 1 FROM VAL_ADD(1147, :V$CAL_ID, 'НОО, ООО 1-9 классы ' || :V$YEAR || '-' || (:V$YEAR + 1)) INTO :T;

    SELECT OBJ_ID FROM OBJECT_ADD(:V$CAL_ID, 154) INTO :V$OBJ_ID;
    SELECT 1 FROM VAL_ADD(1170, :V$OBJ_ID, 12) INTO :T;
    SELECT 1 FROM VAL_ADD(1169, :V$OBJ_ID, '01.09.' || :V$YEAR) INTO :T;
    SELECT 1 FROM VAL_ADD(1174, :V$OBJ_ID, DATEADD(-1 DAY TO :I$FROM1)) INTO :T;

    SELECT OBJ_ID FROM OBJECT_ADD(:V$CAL_ID, 154) INTO :V$OBJ_ID;
    SELECT 1 FROM VAL_ADD(1170, :V$OBJ_ID, 13) INTO :T;
    SELECT 1 FROM VAL_ADD(1169, :V$OBJ_ID, DATEADD(1 DAY TO :I$TO1)) INTO :T;
    SELECT 1 FROM VAL_ADD(1174, :V$OBJ_ID, DATEADD(-1 DAY TO :I$FROM2)) INTO :T;

    SELECT OBJ_ID FROM OBJECT_ADD(:V$CAL_ID, 154) INTO :V$OBJ_ID;
    SELECT 1 FROM VAL_ADD(1170, :V$OBJ_ID, 14) INTO :T;
    SELECT 1 FROM VAL_ADD(1169, :V$OBJ_ID, DATEADD(1 DAY TO :I$TO2)) INTO :T;
    SELECT 1 FROM VAL_ADD(1174, :V$OBJ_ID, DATEADD(-1 DAY TO :I$FROM3)) INTO :T;

    SELECT OBJ_ID FROM OBJECT_ADD(:V$CAL_ID, 154) INTO :V$OBJ_ID;
    SELECT 1 FROM VAL_ADD(1170, :V$OBJ_ID, 15) INTO :T;
    SELECT 1 FROM VAL_ADD(1169, :V$OBJ_ID, DATEADD(1 DAY TO :I$TO3)) INTO :T;
    SELECT 1 FROM VAL_ADD(1174, :V$OBJ_ID, '31.05.' || (:V$YEAR + 1)) INTO :T;

  END
  ELSE
  BEGIN

    -- Тут должно быть именно 4 периода, по одному каждого типа
    V$PREV = -1;
    FOR
      SELECT L154.OBJ_ID, V1170.LISTVAL_ID
      FROM LINKS L154
      JOIN VALL V1170 ON V1170.OBJ_ID = L154.OBJ_ID AND V1170.PARAM_ID = 1170 AND V1170.IS_DEL = 0
      JOIN VALD V1169 ON V1169.OBJ_ID = L154.OBJ_ID AND V1169.PARAM_ID = 1169 AND V1169.IS_DEL = 0
      WHERE L154.PARENT_ID  = :V$CAL_ID AND L154.OBJ_TYPE_ID = 154 AND L154.DATE_DEL IS NULL
      ORDER BY V1170.LISTVAL_ID, V1169.VAL
      INTO :V$OBJ_ID, :V$PERIOD
    DO
    BEGIN
      IF(V$PREV = V$PERIOD) THEN EXCEPTION DATA_ERROR 'Повторение периода в сетке периодов, обновить невозможно';
      V$PREV = V$PERIOD;

      IF(V$PERIOD = 12) THEN
      BEGIN
        SELECT 1 FROM VAL_ADD(1169, :V$OBJ_ID, '01.09.' || :V$YEAR) INTO :T;
        SELECT 1 FROM VAL_ADD(1174, :V$OBJ_ID, DATEADD(-1 DAY TO :I$FROM1)) INTO :T;
      END
      ELSE IF(V$PERIOD = 13) THEN
      BEGIN
        SELECT 1 FROM VAL_ADD(1169, :V$OBJ_ID, DATEADD(1 DAY TO :I$TO1)) INTO :T;
        SELECT 1 FROM VAL_ADD(1174, :V$OBJ_ID, DATEADD(-1 DAY TO :I$FROM2)) INTO :T;
      END
      ELSE IF(V$PERIOD = 14) THEN
      BEGIN
        SELECT 1 FROM VAL_ADD(1169, :V$OBJ_ID, DATEADD(1 DAY TO :I$TO2)) INTO :T;
        SELECT 1 FROM VAL_ADD(1174, :V$OBJ_ID, DATEADD(-1 DAY TO :I$FROM3)) INTO :T;
      END
      ELSE IF(V$PERIOD = 15) THEN
      BEGIN
        SELECT 1 FROM VAL_ADD(1169, :V$OBJ_ID, DATEADD(1 DAY TO :I$TO3)) INTO :T;
       SELECT 1 FROM VAL_ADD(1174, :V$OBJ_ID, '31.05.' || (:V$YEAR + 1)) INTO :T;
      END
    END

  END

  -- Периоды для 10-11 классов, полугодия - если такие параллели вообще есть
  IF(EXISTS(SELECT FIRST 1 1
    FROM LINKS L7
    JOIN LINKS L8 ON L8.PARENT_ID = L7.OBJ_ID AND L8.OBJ_TYPE_ID = 8 AND L8.DATE_DEL IS NULL
    JOIN VALL V49 ON V49.OBJ_ID = L8.OBJ_ID AND V49.PARAM_ID = 49 AND V49.IS_DEL = 0 AND V49.LISTVAL_ID IN (46, 47, 48, 12960, 12961, 12962, 12963)
    WHERE L7.PARENT_ID = :V$OU_ID AND L7.OBJ_TYPE_ID = 7 AND L7.DATE_DEL IS NULL
  )) THEN
  BEGIN

    V$CAL_ID = NULL;
    SELECT FIRST 1 L151.OBJ_ID
    FROM LINKS L151
    JOIN LINKS L154 ON L154.PARENT_ID = L151.OBJ_ID AND L154.OBJ_TYPE_ID = 154 AND L154.DATE_DEL IS NULL
    JOIN VALL V1170 ON V1170.OBJ_ID = L154.OBJ_ID AND V1170.PARAM_ID = 1170 AND V1170.IS_DEL = 0 AND V1170.LISTVAL_ID IN (10, 11)
    JOIN VALD V1169 ON V1169.OBJ_ID = L154.OBJ_ID AND V1169.PARAM_ID = 1169 AND V1169.IS_DEL = 0 AND V1169.VAL >= '01.09.' || :V$YEAR AND V1169.VAL <= '31.05.' || (:V$YEAR + 1)
    WHERE L151.PARENT_ID = :V$FOLDER_ID AND L151.OBJ_TYPE_ID = 151 AND L151.DATE_DEL IS NULL
    INTO :V$CAL_ID;

    IF(V$CAL_ID IS NULL) THEN
    BEGIN

      SELECT OBJ_ID FROM OBJECT_ADD(:V$FOLDER_ID, 151) INTO :V$CAL_ID;
      SELECT 1 FROM VAL_ADD(1147, :V$CAL_ID, 'СОО 10-11 классы ' || :V$YEAR || '-' || (:V$YEAR + 1)) INTO :T;

      SELECT OBJ_ID FROM OBJECT_ADD(:V$CAL_ID, 154) INTO :V$OBJ_ID;
      SELECT 1 FROM VAL_ADD(1170, :V$OBJ_ID, 10) INTO :T;
      SELECT 1 FROM VAL_ADD(1169, :V$OBJ_ID, '01.09.' || :V$YEAR) INTO :T;
      SELECT 1 FROM VAL_ADD(1174, :V$OBJ_ID, DATEADD(-1 DAY TO :I$FROM2)) INTO :T;

      SELECT OBJ_ID FROM OBJECT_ADD(:V$CAL_ID, 154) INTO :V$OBJ_ID;
      SELECT 1 FROM VAL_ADD(1170, :V$OBJ_ID, 11) INTO :T;
      SELECT 1 FROM VAL_ADD(1169, :V$OBJ_ID, DATEADD(1 DAY TO :I$TO2)) INTO :T;
      SELECT 1 FROM VAL_ADD(1174, :V$OBJ_ID, '31.05.' || (:V$YEAR + 1)) INTO :T;

    END
    ELSE
    BEGIN

      -- Тут должно быть именно 2 периода, по одному каждого типа
      V$PREV = -1;
      FOR
        SELECT L154.OBJ_ID, V1170.LISTVAL_ID
        FROM LINKS L154
        JOIN VALL V1170 ON V1170.OBJ_ID = L154.OBJ_ID AND V1170.PARAM_ID = 1170 AND V1170.IS_DEL = 0
        JOIN VALD V1169 ON V1169.OBJ_ID = L154.OBJ_ID AND V1169.PARAM_ID = 1169 AND V1169.IS_DEL = 0
        WHERE L154.PARENT_ID  = :V$CAL_ID AND L154.OBJ_TYPE_ID = 154 AND L154.DATE_DEL IS NULL
        ORDER BY V1170.LISTVAL_ID, V1169.VAL
        INTO :V$OBJ_ID, :V$PERIOD
      DO
      BEGIN
        IF(V$PREV = V$PERIOD) THEN EXCEPTION DATA_ERROR 'Повторение периода в сетке периодов, обновить невозможно';
        V$PREV = V$PERIOD;

        IF(V$PERIOD = 10) THEN
        BEGIN
          SELECT 1 FROM VAL_ADD(1169, :V$OBJ_ID, '01.09.' || :V$YEAR) INTO :T;
          SELECT 1 FROM VAL_ADD(1174, :V$OBJ_ID, DATEADD(-1 DAY TO :I$FROM2)) INTO :T;
        END
        ELSE IF(V$PERIOD = 11) THEN
        BEGIN
          SELECT 1 FROM VAL_ADD(1169, :V$OBJ_ID, DATEADD(1 DAY TO :I$TO2)) INTO :T;
          SELECT 1 FROM VAL_ADD(1174, :V$OBJ_ID, '31.05.' || (:V$YEAR + 1)) INTO :T;
        END
      END

    END

  END

  -- Каникулы - вносим вообще во все папки, где есть нужный нам учебный год
  FOR
    SELECT L151.OBJ_ID
    FROM LINKS L151
    WHERE L151.PARENT_ID = :V$FOLDER_ID AND L151.OBJ_TYPE_ID = 151 AND L151.DATE_DEL IS NULL
    AND EXISTS (
      SELECT FIRST 1 1
      FROM LINKS L154
      JOIN VALD V1169 ON V1169.OBJ_ID = L154.OBJ_ID AND V1169.PARAM_ID = 1169 AND V1169.IS_DEL = 0 AND V1169.VAL >= '01.09.' || :V$YEAR AND V1169.VAL <= '31.05.' || (:V$YEAR + 1)
      WHERE L154.PARENT_ID = L151.OBJ_ID AND L154.OBJ_TYPE_ID = 154 AND L154.DATE_DEL IS NULL
    )
    INTO :V$CAL_ID
  DO
  BEGIN
    -- Осенние каникулы
    V$OBJ_ID = NULL;
    SELECT FIRST 1 L450.OBJ_ID
    FROM LINKS L450
    JOIN VALD V3263 ON V3263.OBJ_ID = L450.OBJ_ID AND V3263.PARAM_ID = 3263 AND V3263.IS_DEL = 0 AND V3263.VAL > '01.09.' || :V$YEAR AND V3263.VAL <= '01.12.' || :V$YEAR
    WHERE L450.PARENT_ID = :V$CAL_ID AND L450.OBJ_TYPE_ID = 450 AND L450.DATE_DEL IS NULL
    INTO :V$OBJ_ID;

    IF(V$OBJ_ID IS NULL) THEN
    BEGIN
      SELECT OBJ_ID FROM OBJECT_ADD(:V$CAL_ID, 450) INTO :V$OBJ_ID;
      SELECT 1 FROM VAL_ADD(3265, :V$OBJ_ID, 'Осенние каникулы') INTO :T;
    END

    SELECT 1 FROM VAL_ADD(3263, :V$OBJ_ID, :I$FROM1) INTO :T;
    SELECT 1 FROM VAL_ADD(3264, :V$OBJ_ID, :I$TO1) INTO :T;

    -- Зимние каникулы
    V$OBJ_ID = NULL;
    SELECT FIRST 1 L450.OBJ_ID
    FROM LINKS L450
    JOIN VALD V3263 ON V3263.OBJ_ID = L450.OBJ_ID AND V3263.PARAM_ID = 3263 AND V3263.IS_DEL = 0 AND V3263.VAL > '01.12.' || :V$YEAR AND V3263.VAL <= '01.02.' || (:V$YEAR + 1)
    WHERE L450.PARENT_ID = :V$CAL_ID AND L450.OBJ_TYPE_ID = 450 AND L450.DATE_DEL IS NULL
    INTO :V$OBJ_ID;

    IF(V$OBJ_ID IS NULL) THEN
    BEGIN
      SELECT OBJ_ID FROM OBJECT_ADD(:V$CAL_ID, 450) INTO :V$OBJ_ID;
      SELECT 1 FROM VAL_ADD(3265, :V$OBJ_ID, 'Зимние каникулы') INTO :T;
    END

    SELECT 1 FROM VAL_ADD(3263, :V$OBJ_ID, :I$FROM2) INTO :T;
    SELECT 1 FROM VAL_ADD(3264, :V$OBJ_ID, :I$TO2) INTO :T;

    -- Весенние каникулы
    V$OBJ_ID = NULL;
    SELECT FIRST 1 L450.OBJ_ID
    FROM LINKS L450
    JOIN VALD V3263 ON V3263.OBJ_ID = L450.OBJ_ID AND V3263.PARAM_ID = 3263 AND V3263.IS_DEL = 0 AND V3263.VAL > '01.02.' || (:V$YEAR + 1) AND V3263.VAL <= '01.05.' || (:V$YEAR + 1)
    WHERE L450.PARENT_ID = :V$CAL_ID AND L450.OBJ_TYPE_ID = 450 AND L450.DATE_DEL IS NULL
    INTO :V$OBJ_ID;

    IF(V$OBJ_ID IS NULL) THEN
    BEGIN
      SELECT OBJ_ID FROM OBJECT_ADD(:V$CAL_ID, 450) INTO :V$OBJ_ID;
      SELECT 1 FROM VAL_ADD(3265, :V$OBJ_ID, 'Весенние каникулы') INTO :T;
    END

    SELECT 1 FROM VAL_ADD(3263, :V$OBJ_ID, :I$FROM3) INTO :T;
    SELECT 1 FROM VAL_ADD(3264, :V$OBJ_ID, :I$TO3) INTO :T;

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE Z RETURNS (
    TYPE_ID BIGINT,
    CNT INTEGER,
    TYPE_NAME VARCHAR(4000))
AS
BEGIN
    FOR SELECT O.OBJ_TYPE_ID, COUNT(O.OBJ_TYPE_ID)
        FROM LINKS O
        GROUP BY O.OBJ_TYPE_ID
        INTO :TYPE_ID, :CNT
    DO
    BEGIN
        SELECT FIRST 1 R.VAL
        FROM TYPES T
        INNER JOIN RES R ON R.RES_ID = T.RES_ID
        WHERE T.TYPE_ID = :TYPE_ID
        INTO :TYPE_NAME;
        SUSPEND;
    END
END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE Z_COPY_LEVEL (
    I$FROM BIGINT,
    I$TO BIGINT)
AS
DECLARE VARIABLE V$PARAM_ID BIGINT;
DECLARE VARIABLE V$EDIT_TYPE SMALLINT;
DECLARE VARIABLE V$IS_REPL SMALLINT;
DECLARE VARIABLE V$IS_DEL SMALLINT;
DECLARE VARIABLE V$TYPE_ID BIGINT;
DECLARE VARIABLE V$BAR_ID BIGINT;
DECLARE VARIABLE V$SHOW_DEL SMALLINT;
DECLARE VARIABLE V$GROUP_NAME VARCHAR(200);
DECLARE VARIABLE V$REPORT_ID INTEGER;
begin

  -- Типы объектов
  FOR
      SELECT LT.TYPE_ID, LT.EDIT_TYPE, LT.SHOW_DEL, LT.BAR_ID, LT.IS_REPL, LT.IS_DEL
      FROM LTYPES LT
      LEFT JOIN LTYPES LT2 ON LT2.LEVEL_ID = :I$TO AND LT2.TYPE_ID = LT.TYPE_ID
      WHERE LT.LEVEL_ID = :I$FROM AND LT2.TYPE_ID IS NULL
      INTO :V$TYPE_ID, :V$EDIT_TYPE, :V$SHOW_DEL, :V$BAR_ID, :V$IS_REPL, :V$IS_DEL
  DO
  BEGIN
      INSERT INTO LTYPES
      (LEVEL_ID, TYPE_ID, EDIT_TYPE, SHOW_DEL, BAR_ID, IS_REPL, IS_DEL)
      VALUES (:I$TO, :V$TYPE_ID, :V$EDIT_TYPE, :V$SHOW_DEL, :V$BAR_ID, :V$IS_REPL, :V$IS_DEL);
  END

  -- Параметры
  FOR
      SELECT LP.PARAM_ID, LP.EDIT_TYPE, LP.IS_REPL, LP.IS_DEL
      FROM LPARAMS LP
      LEFT JOIN LPARAMS LP2 ON LP2.PARAM_ID = LP.PARAM_ID AND LP2.LEVEL_ID = :I$TO
      WHERE LP.LEVEL_ID = :I$FROM AND LP2.PARAM_ID IS NULL
      INTO :V$PARAM_ID, :V$EDIT_TYPE, :V$IS_REPL, :V$IS_DEL
  DO
  BEGIN
      INSERT INTO LPARAMS
      (LEVEL_ID, PARAM_ID, EDIT_TYPE, IS_REPL, IS_DEL)
      VALUES (:I$TO, :V$PARAM_ID, :V$EDIT_TYPE, :V$IS_REPL, :V$IS_DEL);
  END

  -- Отчеты
  FOR
      SELECT LR.REPORT_ID, LR.GROUP_NAME, LR.IS_REPL, LR.IS_DEL
      FROM LREPORTS LR
      LEFT JOIN LREPORTS LR2 ON LR2.LEVEL_ID = :I$TO AND LR2.REPORT_ID = LR.REPORT_ID
      WHERE LR.LEVEL_ID = :I$FROM AND LR2.REPORT_ID IS NULL
      INTO :V$REPORT_ID, :V$GROUP_NAME, :V$IS_REPL, :V$IS_DEL
  DO
  BEGIN
      INSERT INTO LREPORTS
      (LEVEL_ID, REPORT_ID, GROUP_NAME, IS_REPL, IS_DEL)
      VALUES (:I$TO, :V$REPORT_ID, :V$GROUP_NAME, :V$IS_REPL, :V$IS_DEL);
  END

  -- По идее надо бы LLISTS...

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE Z_DEL RETURNS (
    CNT BIGINT)
AS
BEGIN
    DELETE FROM LINKS T WHERE T.DATE_DEL IS NOT NULL;
    CNT = ROW_COUNT;
    DELETE FROM VALA  T WHERE T.IS_DEL > 0;
    DELETE FROM VALB  T WHERE T.IS_DEL > 0;
    DELETE FROM VALD  T WHERE T.IS_DEL > 0;
    DELETE FROM VALDT T WHERE T.IS_DEL > 0;
    DELETE FROM VALF  T WHERE T.IS_DEL > 0;
    DELETE FROM VALI  T WHERE T.IS_DEL > 0;
    DELETE FROM VALL  T WHERE T.IS_DEL > 0;
    DELETE FROM VALR  T WHERE T.IS_DEL > 0;
    DELETE FROM VALS  T WHERE T.IS_DEL > 0;
    DELETE FROM VALL  T WHERE T.IS_DEL > 0;
    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE Z_DEL_MOVEMENT RETURNS (
    OBJ_ID BIGINT)
AS
BEGIN
  -- Потеряла актуальность
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE Z_DEL_OBJ_TYPE RETURNS (
    OBJ_ID BIGINT)
AS
BEGIN
    DELETE FROM LINKS T
    WHERE T.OBJ_TYPE_ID IN (23, 49, 50, 54, 56, 58, 74, 92, 94, 95, 97, 104, 105, 106, 107, 108, 109, 114, 155)
       OR T.PARENT_TYPE_ID IN (23, 49, 50, 54, 56, 58, 74, 92, 94, 95, 97, 104, 105, 106, 107, 108, 109, 114, 155);

    FOR SELECT T.OBJ_ID
        FROM OBJECTS T
        WHERE T.TYPE_ID IN (23, 49, 50, 54, 56, 58, 74, 92, 94, 95, 97, 104, 105, 106, 107, 108, 109, 114, 155)
        INTO :OBJ_ID
    DO
    BEGIN
        DELETE FROM VALA T
        WHERE T.OBJ_ID = :OBJ_ID;
        DELETE FROM VALB T
        WHERE T.OBJ_ID = :OBJ_ID;
        DELETE FROM VALD T
        WHERE T.OBJ_ID = :OBJ_ID;
        DELETE FROM VALDT T
        WHERE T.OBJ_ID = :OBJ_ID;
        DELETE FROM VALF T
        WHERE T.OBJ_ID = :OBJ_ID;
        DELETE FROM VALI T
        WHERE T.OBJ_ID = :OBJ_ID;
        DELETE FROM VALL T
        WHERE T.OBJ_ID = :OBJ_ID;
        DELETE FROM VALR T
        WHERE T.OBJ_ID = :OBJ_ID;
        DELETE FROM VALS T
        WHERE T.OBJ_ID = :OBJ_ID;
        DELETE FROM VALL T
        WHERE T.OBJ_ID = :OBJ_ID;
    END

    DELETE FROM OBJECTS T
    WHERE T.TYPE_ID IN (23, 49, 50, 54, 56, 58, 74, 92, 94, 95, 97, 104, 105, 106, 107, 108, 109, 114, 155);
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE Z_EXPERT_BASE (
    F VARCHAR(255),
    I VARCHAR(255),
    O VARCHAR(255),
    S VARCHAR(255),
    N VARCHAR(255))
RETURNS (
    W VARCHAR(255),
    X INTEGER,
    Y VARCHAR(255),
    Z DATE,
    LISTVAL_ID BIGINT)
AS
DECLARE VARIABLE OBJ_ID BIGINT;
DECLARE VARIABLE DISTR_ID BIGINT;
DECLARE VARIABLE OU_ID BIGINT;
DECLARE VARIABLE WORKER_ID BIGINT;
DECLARE VARIABLE C INTEGER;
BEGIN
    SELECT FIRST 1 L.OBJ_ID
    FROM LINKS L
    WHERE L.PARENT_ID IS NULL
      AND L.OBJ_TYPE_ID = 112
      AND L.DATE_DEL IS NULL
    INTO :OBJ_ID;

    FOR SELECT L111.OBJ_ID, L2.OBJ_ID, L14.OBJ_ID
        FROM LINKS L111
        INNER JOIN LINKS L2 ON L2.PARENT_ID = L111.OBJ_ID
        INNER JOIN LINKS L14 ON L14.PARENT_ID = L2.OBJ_ID
        INNER JOIN VALS V59 ON V59.OBJ_ID = L14.OBJ_ID
        INNER JOIN VALS V60 ON V60.OBJ_ID = L14.OBJ_ID
        INNER JOIN VALS V61 ON V61.OBJ_ID = L14.OBJ_ID
        WHERE L111.PARENT_ID = :OBJ_ID
          AND L111.OBJ_TYPE_ID = 111
          AND L111.DATE_DEL IS NULL
          AND L2.OBJ_TYPE_ID = 2
          AND L2.DATE_DEL IS NULL
          AND L14.OBJ_TYPE_ID = 14
          AND L14.DATE_DEL IS NULL
          AND V59.PARAM_ID = 59
          AND V59.IS_DEL = 0
          AND V59.VAL = :F
          AND V60.PARAM_ID = 60
          AND V60.IS_DEL = 0
          AND V60.VAL = :I
          AND V61.PARAM_ID = 61
          AND V61.IS_DEL = 0
          AND V61.VAL = :O
        INTO :DISTR_ID, :OU_ID, :WORKER_ID
    DO
    BEGIN
        C = 0;
        SELECT COUNT(*)
        FROM LINKS L79
        LEFT JOIN VALS V442 ON V442.OBJ_ID = L79.OBJ_ID AND V442.PARAM_ID = 442 AND V442.IS_DEL = 0
        LEFT JOIN VALS V559 ON V559.OBJ_ID = L79.OBJ_ID AND V559.PARAM_ID = 559 AND V559.IS_DEL = 0
        WHERE L79.PARENT_ID = :WORKER_ID
          AND L79.OBJ_TYPE_ID = 79
          AND L79.DATE_DEL IS NULL
          AND (:S = '' OR V442.VAL = :S)
          AND (:N = '' OR V559.VAL = :N)
        INTO :C;

        IF (C > 0) THEN
        BEGIN
            FOR SELECT V587.LISTVAL_ID
                FROM LINKS L15
                INNER JOIN VALL V587 ON V587.OBJ_ID = L15.OBJ_ID
                WHERE L15.PARENT_ID = :WORKER_ID
                  AND L15.OBJ_TYPE_ID = 15
                  AND L15.DATE_DEL IS NULL
                  AND V587.PARAM_ID = 587
                  AND V587.IS_DEL = 0
                INTO :LISTVAL_ID
            DO
            BEGIN
                W = NULL;
                X = NULL;
                Y = NULL;
                Z = NULL;

                SELECT V
                FROM VAL_GET(:DISTR_ID, 665)
                INTO :W;

                SELECT V
                FROM VAL_GET(:OU_ID, 17)
                INTO :X;

                SELECT V
                FROM VAL_GET(:OU_ID, 2)
                INTO :Y;

                SELECT V
                FROM VAL_GET(:WORKER_ID, 241)
                INTO :Z;

                SUSPEND;
            END
        END
    END

END
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE Z_GUID RETURNS (
    A BIGINT,
    B BIGINT,
    C VARCHAR(36),
    G VARCHAR(36),
    GUID VARCHAR(36),
    D BIGINT)
AS
BEGIN
    SELECT UUID_TO_CHAR(GEN_UUID()) FROM RDB$DATABASE INTO :G;

    A = (1956123456789 - 1956000000000) + 100000000000;

    GUID = 'A0000000-0000-0000-0000-' || A;

    --SELECT CHAR_TO_UUID(:GUID36) FROM RDB$DATABASE INTO HEX_GUID;

    C = SUBSTRING(GUID FROM 25 FOR 10); -- 25 to 36

    B = C;

    D = B - 100000000000;

    SUSPEND;
END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE Z_IMPORT_JOBS (
    I$CODE BIGINT,
    I$VALUE VARCHAR(1000),
    I$L SMALLINT = 0)
AS
DECLARE VARIABLE V$LIST_ID BIGINT;
DECLARE VARIABLE V$PARENT_ID BIGINT;
DECLARE VARIABLE V$C BIGINT;
DECLARE VARIABLE S VARCHAR(100);
DECLARE VARIABLE V$ID BIGINT;
begin

  V$LIST_ID = 369;

  V$C = I$CODE / 1000;
  -- IF(V$C < 20) THEN EXCEPTION DATA_ERROR 'ERROR AT ' || I$CODE;
  V$C = V$C * 1000;
  S = V$C || '-' || (V$C + 999);

  SELECT FIRST 1 LV.LISTVAL_ID
  FROM LISTVALS LV
  JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU' AND R.VAL = :S
  WHERE LV.LIST_ID = :V$LIST_ID AND LV.IS_DEL = 0
  INTO :V$PARENT_ID;

  IF(V$PARENT_ID IS NULL) THEN
  SELECT LISTVAL_ID
  FROM LISTVAL_ADD(NULL, :V$LIST_ID, NULL, 'RU', NULL, :S, NULL, NULL, 0, 0, 0)
  INTO :V$PARENT_ID;

  S = I$CODE;
  SELECT FIRST 1 LV.LISTVAL_ID
  FROM LISTVALS LV
  WHERE LV.LIST_ID = :V$LIST_ID AND LV.IS_DEL = 0 AND LV.TAG = :S
  INTO :V$ID;

  IF(V$ID IS NULL) THEN
  SELECT LISTVAL_ID
  FROM LISTVAL_ADD(NULL, :V$LIST_ID, NULL, 'RU', :V$PARENT_ID, :I$VALUE, NULL, :S, :I$L, 0, 0)
  INTO :V$ID;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE Z_IS_FOREIGN_KEY (
    TABLE_NAME VARCHAR(100),
    FIELD_NAME VARCHAR(100))
RETURNS (
    IS_FK SMALLINT)
AS
begin

    if((TABLE_NAME is null) or (FIELD_NAME is null)) then begin
        IS_FK = 0;
    end
    else begin

        select count(*)
        from RDB$RELATION_CONSTRAINTS RC, RDB$INDEX_SEGMENTS SI
        where RC.RDB$RELATION_NAME = :TABLE_NAME and RDB$CONSTRAINT_TYPE = 'FOREIGN KEY'
          and SI.RDB$INDEX_NAME = RC.RDB$INDEX_NAME and SI.RDB$FIELD_NAME = :FIELD_NAME
        into :IS_FK;

    end

    SUSPEND;
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE Z_IS_PRIMARY_KEY (
    TABLE_NAME VARCHAR(100),
    FIELD_NAME VARCHAR(100))
RETURNS (
    IS_PK SMALLINT)
AS
begin

    if((TABLE_NAME is null) or (FIELD_NAME is null)) then begin
        IS_PK = 0;
    end
    else begin

        select count(*)
        from RDB$RELATION_CONSTRAINTS RC, RDB$INDEX_SEGMENTS SI
        where RC.RDB$RELATION_NAME = :TABLE_NAME and RDB$CONSTRAINT_TYPE = 'PRIMARY KEY'
          and SI.RDB$INDEX_NAME = RC.RDB$INDEX_NAME and SI.RDB$FIELD_NAME = :FIELD_NAME
        into :IS_PK;

    end

    SUSPEND;
end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE Z_OD_RESULTS (
    I$START_DATE DATE)
RETURNS (
    STUDENT_ID BIGINT,
    STUDENT_NAME VARCHAR(400),
    SNILS VARCHAR(40),
    CLASS_NAME VARCHAR(200),
    SUBJECT_NAME VARCHAR(400),
    RESULT_TYPE VARCHAR(40),
    SUBJECT_ID BIGINT,
    TEACHER_NAME VARCHAR(1000))
AS
DECLARE VARIABLE S VARCHAR(400);
begin

  FOR
    SELECT M.PERSON_ID, F.C1, M.NAME_IN, V1409.SVAL, IIF(V237.LISTVAL_ID = 5282, 'ПРИЗЕР', 'ПОБЕДИТЕЛЬ'), V1820.SVAL
    FROM (
      SELECT DISTINCT M.PERSON_ID, M.NAME_IN
      FROM PERSON_MOVEMENTS M
      JOIN LINKS LPG ON LPG.OBJ_ID = M.PERSON_ID AND LPG.PARENT_TYPE_ID IN (9, 187, 81, 82, 83) AND LPG.DATE_DEL IS NULL
      LEFT JOIN PERSON_MOVEMENTS M2 ON M2.DATE_DEL IS NULL AND M2.PERSON_ID = M.PERSON_ID AND M2.GROUP_TYPE_ID = 9 AND M2.OBJ_ID > M.OBJ_ID
      WHERE M.DATE_DEL IS NULL AND M.GROUP_TYPE_ID = 9 AND M.DATE_IN >= :I$START_DATE AND M2.OBJ_ID IS NULL
    ) M
    LEFT JOIN BUILD_REP_FIO(M.PERSON_ID, 55, 56, 57, 1) F ON 1 = 1
    LEFT JOIN VALS V1409 ON V1409.OBJ_ID = M.PERSON_ID AND V1409.PARAM_ID = 1409 AND V1409.IS_DEL = 0
    JOIN LINKS L22 ON L22.PARENT_ID = M.PERSON_ID AND L22.OBJ_TYPE_ID = 22 AND L22.DATE_DEL IS NULL
    JOIN VALS V167 ON V167.OBJ_ID = L22.OBJ_ID AND V167.PARAM_ID = 167 AND UPPER(V167.SVAL) LIKE '%ОЛИМПИАДА%'
    JOIN VALD V166 ON V166.OBJ_ID = L22.OBJ_ID AND V166.PARAM_ID = 166 AND V166.VAL >= :I$START_DATE
    JOIN VALL V237 ON V237.OBJ_ID = L22.OBJ_ID AND V237.PARAM_ID = 237 AND V237.LISTVAL_ID IN (5282, 5283)
    JOIN VALS V1820 ON V1820.OBJ_ID = L22.OBJ_ID AND V1820.PARAM_ID = 1820
    INTO :STUDENT_ID, :STUDENT_NAME, :CLASS_NAME, :SNILS, :RESULT_TYPE, :SUBJECT_NAME
  DO
  BEGIN
    -- Пытаемся угадать предмет
    SUBJECT_ID = NULL;
    TEACHER_NAME = NULL;

    S = UPPER(SUBJECT_NAME);
    S = REPLACE(S, 'РУССКОМУ', 'РУССКИЙ');
    S = REPLACE(S, 'АНГЛИЙСКОМУ', 'АНГЛИЙСКИЙ');
    S = REPLACE(S, 'КИТАЙСКОМУ', 'КИТАЙСКИЙ');
    S = REPLACE(S, 'НЕМЕЦКОМУ', 'НЕМЕЦКИЙ');
    S = REPLACE(S, 'ФРАНЦУЗСКОМУ', 'ФРАНЦУЗСКИЙ');
    S = REPLACE(S, 'ИСПАНСКОМУ', 'ИСПАНСКИЙ');
    S = REPLACE(S, 'ИТАЛЬЯНСКОМУ', 'ИТАЛЬЯНСКИЙ');
    S = REPLACE(S, 'КОРЕЙСКОМУ', 'КОРЕЙСКИЙ');
    S = REPLACE(S, 'АРАБСКОМУ', 'АРАБСКИЙ');

    IF(S LIKE '%АНГЛИЙСКИЙ%' OR S LIKE '%КИТАЙСКИЙ%' OR S LIKE '%НЕМЕЦКИЙ%' OR S LIKE '%ФРАНЦУЗСКИЙ%' OR S LIKE '%ИСПАНСКИЙ%' OR S LIKE '%ИТАЛЬЯНСКИЙ%' OR
      S LIKE '%КОРЕЙСКИЙ%' OR S LIKE '%АРАБСКИЙ%') THEN S = S || 'ИНОСТРАННЫЙ ЯЗЫК';

    SELECT FIRST 1 M.SUBJECT_ID
    FROM VALM M
    JOIN LISTVALS LV ON LV.LISTVAL_ID = M.YEAR_ID AND CAST(LV.TAG AS DATE) >= :I$START_DATE
    LEFT JOIN OBJECT_CAPTION_GET(M.SUBJECT_ID) C ON 1 = 1
    WHERE M.IS_DEL = 0 AND M.IS_NATIVE = 1 AND M.PUPIL_ID = :STUDENT_ID AND
      -- отрезаем последний символ, чтобы избежать проблем с падежом
      (
        POSITION(SUBSTRING(UPPER(C.SCAPTION) FROM 1 FOR CHAR_LENGTH(C.SCAPTION) - 1) IN :S) > 0 OR
        (:S LIKE '%ИНОСТРАННЫЙ%' AND (
          UPPER(C.SCAPTION) LIKE '%ИНОСТРАННЫЙ%' OR
          UPPER(C.SCAPTION) LIKE '%АНГЛИЙСКИЙ%' OR
          UPPER(C.SCAPTION) LIKE '%КИТАЙСКИЙ%' OR
          UPPER(C.SCAPTION) LIKE '%НЕМЕЦКИЙ%' OR
          UPPER(C.SCAPTION) LIKE '%ФРАНЦУЗСКИЙ%' OR
          UPPER(C.SCAPTION) LIKE '%ИСПАНСКИЙ%' OR
          UPPER(C.SCAPTION) LIKE '%ИТАЛЬЯНСКИЙ%' OR
          UPPER(C.SCAPTION) LIKE '%КОРЕЙСКИЙ%' OR
          UPPER(C.SCAPTION) LIKE '%АРАБСКИЙ%'
        ))
      )
    INTO :SUBJECT_ID;

    IF(SUBJECT_ID IS NOT NULL) THEN
    SELECT LIST(DISTINCT TC.SCAPTION, ', ')
    FROM VALM M
    JOIN LISTVALS LV ON LV.LISTVAL_ID = M.YEAR_ID AND CAST(LV.TAG AS DATE) >= :I$START_DATE
    LEFT JOIN OBJECT_CAPTION_GET(M.TEACHER_ID) TC ON 1 = 1
    WHERE M.IS_DEL = 0 AND M.IS_NATIVE = 1 AND M.PUPIL_ID = :STUDENT_ID AND M.SUBJECT_ID = :SUBJECT_ID
    INTO :TEACHER_NAME;

    SUSPEND;
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE Z_OKPDTR (
    I$CODE BIGINT,
    I$NAME VARCHAR(1000))
AS
DECLARE VARIABLE I$BASE BIGINT;
DECLARE VARIABLE I$PARENT VARCHAR(40);
DECLARE VARIABLE V$PARENT_ID BIGINT;
DECLARE VARIABLE V$CODE VARCHAR(40);
DECLARE VARIABLE V$LV BIGINT;
DECLARE VARIABLE Q INTEGER;
DECLARE VARIABLE N INTEGER;
begin

  -- Пересортировка
  IF(I$CODE IS NULL) THEN
  BEGIN
    N = 3;
    FOR
      SELECT LV.LISTVAL_ID, LV.SORT_ORDER
      FROM LISTVALS LV
      JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU'
      WHERE LV.LIST_ID = 352 AND LV.IS_DEL = 0 AND LV.PARENT_ID IS NOT NULL
      ORDER BY IIF(LV.PARENT_ID = 14189, CAST(SUBSTRING(R.VAL FROM 1 FOR 5) AS BIGINT), CAST(LV.TAG AS BIGINT))
      INTO :V$LV, :Q
    DO
    BEGIN
      IF(Q <> N) THEN
      UPDATE LISTVALS
      SET SORT_ORDER = :N
      WHERE LISTVAL_ID = :V$LV;

      N = N + 1;
    END

    EXIT;
  END

  V$CODE = I$CODE;
  I$BASE = I$CODE / 1000;
  I$BASE = I$BASE * 1000;
  I$PARENT = I$BASE || '-' || (I$BASE + 999);

  IF(POSITION('ИСКЛЮЧЕН' IN UPPER(I$NAME)) > 0) THEN EXIT;

  -- Наличие корневого раздела
  SELECT FIRST 1 LV.LISTVAL_ID
  FROM LISTVALS LV
  JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU' AND R.VAL = :I$PARENT
  WHERE LV.LIST_ID = 352 AND LV.IS_DEL = 0
  INTO :V$PARENT_ID;

  IF(V$PARENT_ID IS NULL) THEN
  BEGIN
    SELECT LISTVAL_ID
    FROM LISTVAL_ADD(NULL, 352, NULL, 'RU', 14189, :I$PARENT, NULL, NULL, NULL, NULL, 0)
    INTO :V$PARENT_ID;
  END

  V$LV = NULL;
  SELECT FIRST 1 LV.LISTVAL_ID
  FROM LISTVALS LV
  WHERE LV.LIST_ID = 352 AND LV.IS_DEL = 0 AND LV.TAG = :V$CODE
  INTO :V$LV;

  IF(V$LV IS NULL) THEN
  SELECT LISTVAL_ID
  FROM LISTVAL_ADD(NULL, 352, NULL, 'RU', :V$PARENT_ID, :I$NAME, NULL, :V$CODE, NULL, NULL, 0)
  INTO :V$LV;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE Z_OU_TO_POSTGRES RETURNS (
    VAL VARCHAR(1000))
AS
declare variable V$LIC_TYPE varchar(10);
declare variable V$OBJ_ID bigint;
declare variable V$AREA_ID bigint;
declare variable V$TYPE bigint;
declare variable INN varchar(100);
declare variable S varchar(1000);
declare variable S2 varchar(1000);
declare variable V$NAME_ID bigint;
declare variable V$OPF bigint;
declare variable V$STATUS bigint;
declare variable V$OWNER_S varchar(1000);
declare variable V$OWNER bigint;
begin

  V$LIC_TYPE = (SELECT STATUS FROM OU_LICENCE_TYPE);

  V$NAME_ID = 2;
  IF(V$LIC_TYPE = 'C') THEN V$NAME_ID = 999;

  FOR
    SELECT L2.OBJ_ID, V2.VAL, V5.VAL, V33.VAL, COALESCE(V665.LISTVAL_ID, 3387), V1890.LISTVAL_ID, V8.LISTVAL_ID, V2371.LISTVAL_ID, V6.VAL
    FROM LINKS L2
    JOIN VALS V2 ON V2.OBJ_ID = L2.OBJ_ID AND V2.PARAM_ID = :V$NAME_ID AND V2.IS_DEL = 0
    JOIN VALS V5 ON V5.OBJ_ID = L2.OBJ_ID AND V5.PARAM_ID = 5 AND V5.IS_DEL = 0
    JOIN VALS V33 ON V33.OBJ_ID = L2.OBJ_ID AND V33.PARAM_ID = 33 AND V33.IS_DEL = 0
    JOIN VALL V1890 ON V1890.OBJ_ID = L2.OBJ_ID AND V1890.PARAM_ID = 1890 AND V1890.IS_DEL = 0
    LEFT JOIN VALL V665 ON V665.OBJ_ID = L2.PARENT_ID AND V665.PARAM_ID = 665 AND V665.IS_DEL = 0
    LEFT JOIN VALL V8 ON V8.OBJ_ID = L2.OBJ_ID AND V8.PARAM_ID = 8 AND V8.IS_DEL = 0
    LEFT JOIN VALL V2371 ON V2371.OBJ_ID = L2.OBJ_ID AND V2371.PARAM_ID = 2371 AND V2371.IS_DEL = 0
    LEFT JOIN VALS V6 ON V6.OBJ_ID = L2.OBJ_ID AND V6.PARAM_ID = 6 AND V6.IS_DEL = 0
    WHERE L2.PARENT_TYPE_ID IN (111, 112) AND L2.OBJ_TYPE_ID = 2 AND L2.DATE_DEL IS NULL
    INTO :V$OBJ_ID, :S, :S2, :INN, :V$AREA_ID, :V$TYPE, :V$OPF, :V$STATUS, :V$OWNER_S
  DO
  BEGIN
    V$OWNER = NULL;
    SELECT FIRST 1 LV.LISTVAL_ID
    FROM LISTVALS LV
    JOIN RES R ON R.RES_ID = LV.RES_ID AND R.VAL = :V$OWNER_S
    WHERE LV.LIST_ID = 166 AND LV.IS_DEL = 0
    INTO :V$OWNER;

    VAL = 'select orgdata.sync_organization(''' || V$LIC_TYPE || ''', ' || V$OBJ_ID || '::bigint,''' || INN || ''',''' || S || ''',''' || S2 || ''',' ||
      COALESCE(V$AREA_ID, 'NULL') || '::bigint,' || COALESCE(V$TYPE, 'NULL') || '::bigint,' || COALESCE(V$OPF, 'NULL') || '::bigint,' ||
      COALESCE(V$STATUS, 'NULL') || '::bigint,' || COALESCE(V$OWNER, 'NULL') || '::bigint' || ');';
    SUSPEND;
  END

end
 ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE Z_PLAN_CLONE_TMPL (
    I$OBJ_ID BIGINT)
RETURNS (
    OBJ_ID BIGINT)
AS
DECLARE VARIABLE V VARCHAR(4000);
DECLARE VARIABLE T INTEGER;
DECLARE VARIABLE S VARCHAR(400);
DECLARE VARIABLE V$STD_ID BIGINT;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE V$PREV_ID BIGINT;
DECLARE VARIABLE V$STAGE_ID BIGINT;
DECLARE VARIABLE V$DUR INTEGER;
DECLARE VARIABLE V$DEST_ID BIGINT;
DECLARE VARIABLE V$SEQ INTEGER;
DECLARE VARIABLE V$SUBJECT_ID BIGINT;
DECLARE VARIABLE V$FIELD_ID BIGINT;
DECLARE VARIABLE V$SORT_INDEX INTEGER;
DECLARE VARIABLE V$PARENT_ID BIGINT;
DECLARE VARIABLE V$LEVEL_INDEX INTEGER;
DECLARE VARIABLE V$IS_ADV INTEGER;
DECLARE VARIABLE V$ROW_TYPE INTEGER;
DECLARE VARIABLE V$SRC_SUBJECT_ID BIGINT;
DECLARE VARIABLE V$IS_STM INTEGER;
DECLARE VARIABLE V$ROW_CODE VARCHAR(40);
DECLARE VARIABLE V$NEW_PARENT BIGINT;
DECLARE VARIABLE V$WEEKS INTEGER;
DECLARE VARIABLE V$LOAD_HOURS FLOAT;
DECLARE VARIABLE V$LOAD_HOURS_S1 FLOAT;
DECLARE VARIABLE V$LOAD_HOURS_S2 FLOAT;
DECLARE VARIABLE V$CONTROL_Q1 BIGINT;
DECLARE VARIABLE V$CONTROL_Q2 BIGINT;
begin

  -- Копирование идет из подложенной базы с именем BASE2

  SELECT MON$DATABASE_NAME
  FROM MON$DATABASE
  INTO :V;

  V = REPLACE(V, 'BASE.FDB', 'BASE2.FDB');

  SELECT FIRST 1 L400.OBJ_ID
  FROM LINKS L400
  WHERE L400.PARENT_ID = 258 AND L400.OBJ_TYPE_ID = 400 AND L400.DATE_DEL IS NULL AND L400.REASON_ID = :I$OBJ_ID
  INTO :OBJ_ID;

  IF(OBJ_ID IS NULL) THEN SELECT OBJ_ID FROM OBJECT_ADD(258, 400, :I$OBJ_ID) INTO :OBJ_ID;

  -- Копируем название, стандарт
  EXECUTE STATEMENT
  'SELECT FIRST 1 V3012.VAL, V3014.LISTVAL_ID
    FROM VALS V3012
    LEFT JOIN VALL V3014 ON V3014.OBJ_ID = V3012.OBJ_ID AND V3014.PARAM_ID = 3014 AND V3014.IS_DEL = 0
    WHERE V3012.OBJ_ID = ' || I$OBJ_ID || ' AND V3012.PARAM_ID = 3012 AND V3012.IS_DEL = 0'
  ON EXTERNAL :V
  WITH COMMON TRANSACTION
  INTO :S, :V$STD_ID;

  SELECT 1 FROM VAL_ADD(3012, :OBJ_ID, :S) INTO :T;
  SELECT 1 FROM VAL_ADD(3014, :OBJ_ID, :V$STD_ID) INTO :T;
  SELECT 1 FROM VAL_ADD(3016, :OBJ_ID, 5465) INTO :T;

  -- Копируем этапы, из атрибутов только номер этапа и длительность
  V$OBJ_ID = 0;
  WHILE(V$OBJ_ID IS NOT NULL) DO
  BEGIN
    V$PREV_ID = V$OBJ_ID;
    V$OBJ_ID = NULL;
    EXECUTE STATEMENT
    'SELECT FIRST 1 L54.OBJ_ID, V381.LISTVAL_ID, V382.VAL
      FROM LINKS L54
      JOIN VALL V381 ON V381.OBJ_ID = L54.OBJ_ID AND V381.PARAM_ID = 381 AND V381.IS_DEL = 0
      LEFT JOIN VALI V382 ON V382.OBJ_ID = L54.OBJ_ID AND V382.PARAM_ID = 382 AND V382.IS_DEL = 0
      WHERE L54.PARENT_ID = ' || I$OBJ_ID || ' AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL AND L54.OBJ_ID > ' || V$PREV_ID || ' ORDER BY 1'
    ON EXTERNAL :V
    WITH COMMON TRANSACTION
    INTO :V$OBJ_ID, :V$STAGE_ID, :V$DUR;

    IF(V$OBJ_ID IS NOT NULL) THEN
    BEGIN
      V$DEST_ID = NULL;
      SELECT FIRST 1 L54.OBJ_ID
      FROM LINKS L54
      WHERE L54.PARENT_ID = :OBJ_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL AND L54.REASON_ID = :V$OBJ_ID
      INTO :V$DEST_ID;

      IF(V$DEST_ID IS NULL) THEN SELECT OBJ_ID FROM OBJECT_ADD(:OBJ_ID, 54, :V$OBJ_ID) INTO :V$DEST_ID;

      SELECT 1 FROM VAL_ADD(381, :V$DEST_ID, :V$STAGE_ID) INTO :T;
      SELECT 1 FROM VAL_ADD(382, :V$DEST_ID, :V$DUR) INTO :T;
    END
  END

  -- Копируем предметы в порядке перечисления
  V$SEQ = -1;
  WHILE(V$SEQ IS NOT NULL) DO
  BEGIN
    V$PREV_ID = V$SEQ;
    V$SEQ = NULL;
    EXECUTE STATEMENT
    'SELECT FIRST 1 PS.OBJ_ID, PS.GLOBAL_INDEX, PS.SUBJECT_ID, PS.FIELD_ID, PS.SORT_INDEX, PS.PARENT_ID, PS.LEVEL_INDEX, PS.IS_ADV, PS.ROW_TYPE, PS.SRC_SUBJECT_ID, PS.IS_STM, PS.ROW_CODE
      FROM PLAN_SUBJECTS PS
      WHERE PS.PLAN_ID = ' || I$OBJ_ID || ' AND PS.DATE_DEL IS NULL AND PS.GLOBAL_INDEX > ' || V$PREV_ID || ' ORDER BY PS.GLOBAL_INDEX'
    ON EXTERNAL :V
    WITH COMMON TRANSACTION
    INTO :V$OBJ_ID, :V$SEQ, :V$SUBJECT_ID, :V$FIELD_ID, :V$SORT_INDEX, :V$PARENT_ID, :V$LEVEL_INDEX, :V$IS_ADV, :V$ROW_TYPE, :V$SRC_SUBJECT_ID, :V$IS_STM, :V$ROW_CODE;

    IF(V$SUBJECT_ID = 201000002765) THEN V$SUBJECT_ID = 39085; -- рисование
    IF(V$SUBJECT_ID = 201000002838) THEN V$SUBJECT_ID = 39086; -- домоводство

    -- Кода у нас пока нет, поэтому кладем данные в него
    IF(V$SEQ IS NOT NULL) THEN
    BEGIN
      V$NEW_PARENT = NULL;
      IF(V$PARENT_ID IS NOT NULL) THEN
      BEGIN
        SELECT FIRST 1 PS.OBJ_ID
        FROM PLAN_SUBJECTS PS
        WHERE PS.PLAN_ID = :OBJ_ID AND PS.DATE_DEL IS NULL AND PS.ROW_CODE = :V$PARENT_ID
        INTO :V$NEW_PARENT;

        IF(V$NEW_PARENT IS NULL) THEN EXCEPTION DATA_ERROR 'Не удалось назначить родительскую запись для ' || V$PARENT_ID;
      END

      V$DEST_ID = NULL;
      SELECT FIRST 1 PS.OBJ_ID
      FROM PLAN_SUBJECTS PS
      WHERE PS.PLAN_ID = :OBJ_ID AND PS.DATE_DEL IS NULL AND PS.ROW_CODE = :V$OBJ_ID
      INTO :V$DEST_ID;

      IF(V$DEST_ID IS NULL) THEN
      INSERT INTO PLAN_SUBJECTS
      (PLAN_ID, GLOBAL_INDEX, SUBJECT_ID, FIELD_ID, SORT_INDEX, PARENT_ID, LEVEL_INDEX, IS_ADV, ROW_TYPE, SRC_SUBJECT_ID, IS_STM, ROW_CODE)
      VALUES (:OBJ_ID, :V$SEQ, :V$SUBJECT_ID, :V$FIELD_ID, :V$SORT_INDEX, :V$NEW_PARENT, :V$LEVEL_INDEX, :V$IS_ADV, :V$ROW_TYPE, :V$SRC_SUBJECT_ID, :V$IS_STM, :V$OBJ_ID);
    END
  END

  -- Копируем нагрузки в порядке возрастания id
  V$OBJ_ID = 0;
  WHILE(V$OBJ_ID IS NOT NULL) DO
  BEGIN
    V$PREV_ID = V$OBJ_ID;
    V$OBJ_ID = NULL;

    EXECUTE STATEMENT
    'SELECT FIRST 1 PL.OBJ_ID, PL.SUBJECT_ID, PL.STAGE_ID, PL.WEEKS, PL.LOAD_HOURS, PL.LOAD_HOURS_S1, PL.LOAD_HOURS_S2, PL.CONTROL_Q1, PL.CONTROL_Q2
      FROM PLAN_SUBJECTS PS
      JOIN PLAN_LOADS PL ON PL.DATE_DEL IS NULL AND PL.SUBJECT_ID = PS.OBJ_ID
      LEFT JOIN LINKS L54 ON L54.OBJ_ID = PL.STAGE_ID AND L54.PARENT_TYPE_ID = 400 AND L54.DATE_DEL IS NULL
      WHERE PS.PLAN_ID = ' || I$OBJ_ID || ' AND PS.DATE_DEL IS NULL AND PL.OBJ_ID > ' || V$PREV_ID || '  AND (L54.LINK_ID IS NOT NULL OR PL.STAGE_ID IS NULL) ORDER BY 1'
    ON EXTERNAL :V
    WITH COMMON TRANSACTION
    INTO :V$OBJ_ID, :V$SUBJECT_ID, :V$STAGE_ID, :V$WEEKS, :V$LOAD_HOURS, :V$LOAD_HOURS_S1, :V$LOAD_HOURS_S2, :V$CONTROL_Q1, :V$CONTROL_Q2;

    IF(V$OBJ_ID IS NOT NULL) THEN
    BEGIN
      -- Записи SUBJECT_ID и STAGE_ID обязательно найдутся
      V$PREV_ID = V$SUBJECT_ID;
      V$SUBJECT_ID = NULL;
      SELECT FIRST 1 PS.OBJ_ID
      FROM PLAN_SUBJECTS PS
      WHERE PS.PLAN_ID = :OBJ_ID AND PS.DATE_DEL IS NULL AND PS.ROW_CODE = :V$PREV_ID
      INTO :V$SUBJECT_ID;

      IF(V$SUBJECT_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не удалось восстановить ссылку на предмет ' || V$PREV_ID;

      V$PREV_ID = V$STAGE_ID;
      V$STAGE_ID = NULL;
      IF(V$PREV_ID IS NOT NULL) THEN
      SELECT FIRST 1 L54.OBJ_ID
      FROM LINKS L54
      WHERE L54.PARENT_ID = :OBJ_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL AND L54.REASON_ID = :V$PREV_ID
      INTO :V$STAGE_ID;

      IF(V$STAGE_ID IS NULL AND V$PREV_ID IS NOT NULL) THEN EXCEPTION DATA_ERROR 'Не удалось восстановить ссылку на этап ' || V$PREV_ID;

      V$DEST_ID = NULL;
      SELECT FIRST 1 PL.OBJ_ID
      FROM PLAN_LOADS PL
      WHERE PL.DATE_DEL IS NULL AND PL.SUBJECT_ID = :V$SUBJECT_ID AND (PL.STAGE_ID = :V$STAGE_ID OR (PL.STAGE_ID IS NULL AND :V$STAGE_ID IS NULL))
      INTO :V$DEST_ID;

      IF(V$DEST_ID IS NULL) THEN
      INSERT INTO PLAN_LOADS
      (SUBJECT_ID, STAGE_ID, WEEKS, LOAD_HOURS, LOAD_HOURS_S1, LOAD_HOURS_S2, CONTROL_Q1, CONTROL_Q2)
      VALUES (:V$SUBJECT_ID, :V$STAGE_ID, :V$WEEKS, :V$LOAD_HOURS, :V$LOAD_HOURS_S1, :V$LOAD_HOURS_S2, :V$CONTROL_Q1, :V$CONTROL_Q2);
    END
  END

  SUSPEND;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE Z_PLAN_CONVERT (
    I$PLAN_ID BIGINT NOT NULL)
AS
declare variable V$SECTION_ID bigint;
declare variable V$SECTION_TYPE bigint;
declare variable V$SECTION_DEST bigint;
declare variable V$SUBJECT_ID bigint;
declare variable V$SUBJECT_DEST bigint;
declare variable V$LEVEL_ID bigint;
declare variable V$IS_ADV smallint;
declare variable V$FIELD_ID bigint;
declare variable V$STAGE_ID bigint;
declare variable V$LOAD bigint;
declare variable V$WEEKS integer;
declare variable V$HOURS integer;
declare variable N integer;
declare variable V$INDEX integer;
begin

  -- Конвертация шаблона учебного плана из старого формата #50 в новый #400
  -- Разделы плана #49 при конвертации удаляем, поэтому выборку делаем в том числе по удаленным
  -- Этапы #54 остаются на старом месте

  SELECT L.LISTVAL_ID
  FROM VALL L
  WHERE L.OBJ_ID = :I$PLAN_ID AND L.PARAM_ID IN (2503, 3345)
  INTO :V$LEVEL_ID;

  IF(V$LEVEL_ID IS NULL) THEN EXCEPTION DATA_ERROR 'Не указан уровень образования в шаблоне';

  FOR
    SELECT L49.OBJ_ID, V372.LISTVAL_ID
    FROM LINKS L49
    JOIN VALL V372 ON V372.OBJ_ID = L49.OBJ_ID AND V372.PARAM_ID = 372
    WHERE L49.PARENT_ID = :I$PLAN_ID AND L49.OBJ_TYPE_ID = 49
    ORDER BY 2
    INTO :V$SECTION_ID, :V$SECTION_TYPE
  DO
  BEGIN
    -- Раздел
    IF(V$SECTION_TYPE IN (780, 12752)) THEN V$SECTION_TYPE = 13303;
    ELSE IF(V$SECTION_TYPE IN (782, 12753)) THEN V$SECTION_TYPE = 13304;
    ELSE EXCEPTION DATA_ERROR 'Неизвестный компонет ' || V$SECTION_TYPE;

    V$SECTION_DEST = NULL;
    SELECT FIRST 1 PS.OBJ_ID
    FROM PLAN_SUBJECTS PS
    WHERE PS.DATE_DEL IS NULL AND PS.PLAN_ID = :I$PLAN_ID AND PS.FIELD_ID = :V$SECTION_TYPE
    INTO :V$SECTION_DEST;

    IF(V$SECTION_DEST IS NULL) THEN
    BEGIN
      INSERT INTO PLAN_SUBJECTS
      (PLAN_ID, FIELD_ID, ROW_TYPE, SORT_INDEX)
      VALUES (:I$PLAN_ID, :V$SECTION_TYPE, 0, IIF(:V$SECTION_TYPE = 13303, 0, 1))
      RETURNING OBJ_ID INTO :V$SECTION_DEST;
    END

    -- Список предметов
    N = 0;
    FOR
      SELECT L51.OBJ_ID
      FROM LINKS L51
      WHERE L51.PARENT_ID = :V$SECTION_ID AND L51.OBJ_TYPE_ID = 51 AND L51.DATE_DEL IS NULL
      ORDER BY L51.COST
      INTO :V$SUBJECT_ID
    DO
    BEGIN
      -- Корректируем предметную область

      V$SUBJECT_DEST = NULL;
      SELECT FIRST 1 PS.OBJ_ID, PS.SORT_INDEX
      FROM PLAN_SUBJECTS PS
      WHERE PS.DATE_DEL IS NULL AND PS.PLAN_ID = :I$PLAN_ID AND PS.PARENT_ID = :V$SECTION_DEST AND PS.SUBJECT_ID = :V$SUBJECT_ID
      INTO :V$SUBJECT_DEST, :V$INDEX;

      IF(V$SUBJECT_DEST IS NULL) THEN
      BEGIN
        V$IS_ADV = 0;
        SELECT FIRST 1 1
        FROM LINKS L51
        WHERE L51.PARENT_ID = :I$PLAN_ID AND L51.OBJ_TYPE_ID = 51 AND L51.OBJ_ID = :V$SUBJECT_ID
        INTO :V$IS_ADV;

        V$FIELD_ID = NULL;
        SELECT FIRST 1 V2462.LISTVAL_ID
        FROM LINKS L302
        JOIN VALL V2462 ON V2462.OBJ_ID = L302.OBJ_ID AND V2462.PARAM_ID = 2462 AND V2462.IS_DEL = 0 AND (
          ((:V$LEVEL_ID = 5339) AND (V2462.LISTVAL_ID IN (12740, 11680, 11682, 11685, 11686, 11689, 11693, 11694, 11695))) OR
          ((:V$LEVEL_ID = 5341) AND (V2462.LISTVAL_ID IN (11684, 11681, 11683, 11685, 11687, 11690, 11691, 11693, 11694, 11696))) OR
          -- Тут косяк для СОП, но исправлять уже не будем
          ((:V$LEVEL_ID = 5343) AND (V2462.LISTVAL_ID IN (11684, 11681, 11683, 11685, 11688, 11690, 11692, 11693, 11694, 11696, 11697)))
        )
        WHERE L302.PARENT_ID = :V$SUBJECT_ID AND L302.OBJ_TYPE_ID = 302 AND L302.DATE_DEL IS NULL
        INTO :V$FIELD_ID;

        INSERT INTO PLAN_SUBJECTS
        (PLAN_ID, PARENT_ID, ROW_TYPE, SUBJECT_ID, SORT_INDEX, IS_ADV, FIELD_ID)
        VALUES (:I$PLAN_ID, :V$SECTION_DEST, 10, :V$SUBJECT_ID, :N, :V$IS_ADV, :V$FIELD_ID)
        RETURNING OBJ_ID INTO :V$SUBJECT_DEST;
      END
      ELSE
      BEGIN
        IF(V$INDEX <> N) THEN
        UPDATE PLAN_SUBJECTS SET SORT_INDEX = :N
        WHERE OBJ_ID = :V$SUBJECT_DEST;
      END

      -- Нагрузки
      FOR
        SELECT L54.OBJ_ID, V2547.VAL, V385.VAL
        FROM LINKS L54
        JOIN LINKS L56 ON L56.PARENT_ID = L54.OBJ_ID AND L56.OBJ_TYPE_ID = 56 AND L56.DATE_DEL IS NULL
        JOIN LINKS LP51 ON LP51.OBJ_ID = L56.OBJ_ID AND LP51.PARENT_TYPE_ID = 51 AND LP51.PARENT_ID = :V$SUBJECT_ID
        JOIN LINKS LP5149 ON LP5149.OBJ_ID = L56.OBJ_ID AND LP5149.PARENT_TYPE_ID = 49 AND LP5149.PARENT_ID = :V$SECTION_ID
        JOIN VALI V2547 ON V2547.OBJ_ID = L56.OBJ_ID AND V2547.PARAM_ID = 2547 AND V2547.IS_DEL = 0
        JOIN VALI V385 ON V385.OBJ_ID = L56.OBJ_ID AND V385.PARAM_ID = 385 AND V385.IS_DEL = 0
        WHERE L54.PARENT_ID = :I$PLAN_ID AND L54.OBJ_TYPE_ID = 54 AND L54.DATE_DEL IS NULL
        INTO :V$STAGE_ID, :V$WEEKS, :V$HOURS
      DO
      BEGIN
        V$LOAD = NULL;
        SELECT FIRST 1 PL.OBJ_ID
        FROM PLAN_LOADS PL
        WHERE PL.DATE_DEL IS NULL AND PL.SUBJECT_ID = :V$SUBJECT_DEST AND PL.STAGE_ID = :V$STAGE_ID
        INTO :V$LOAD;

        IF(V$LOAD IS NULL) THEN
        BEGIN
          INSERT INTO PLAN_LOADS
          (SUBJECT_ID, STAGE_ID, WEEKS, LOAD_HOURS, LOAD_HOURS_S1)
          VALUES (:V$SUBJECT_DEST, :V$STAGE_ID, :V$WEEKS, :V$HOURS, :V$HOURS);
        END
      END

      N = N + 1;
    END

  END

  -- Перенумеровываем строки
  N = 0;
  FOR
    SELECT PS.OBJ_ID, IIF(PS.PARENT_ID IS NULL, PS.SORT_INDEX * 1000, PSP.SORT_INDEX * 1000 + PS.SORT_INDEX + 1)
    FROM PLAN_SUBJECTS PS
    LEFT JOIN PLAN_SUBJECTS PSP ON PSP.OBJ_ID = PS.PARENT_ID
    WHERE PS.DATE_DEL IS NULL AND PS.PLAN_ID = :I$PLAN_ID
    ORDER BY 2
    INTO :V$SUBJECT_ID, :V$SUBJECT_DEST
  DO
  BEGIN
    UPDATE PLAN_SUBJECTS
    SET GLOBAL_INDEX = :N
    WHERE OBJ_ID = :V$SUBJECT_ID AND (GLOBAL_INDEX <> :N OR GLOBAL_INDEX IS NULL);
    N = N + 1;
  END

  -- Обновляем тип данных
  UPDATE OBJECTS
  SET TYPE_ID = 400
  WHERE OBJ_ID = :I$PLAN_ID;

  UPDATE LINKS
  SET OBJ_TYPE_ID = 400
  WHERE OBJ_ID = :I$PLAN_ID;

  UPDATE LINKS
  SET PARENT_TYPE_ID = 400
  WHERE PARENT_ID = :I$PLAN_ID;

  -- Фиксируем удаление разделов и предметов углубленного изучения
  -- Предметы в разделах и нагрузки оставляем
  UPDATE LINKS
  SET DATE_DEL = CURRENT_TIMESTAMP
  WHERE PARENT_ID = :I$PLAN_ID AND OBJ_TYPE_ID IN (51, 49) AND DATE_DEL IS NULL;

  -- Переименовываем параметры
  UPDATE VALL
  SET PARAM_ID = 3345
  WHERE OBJ_ID = :I$PLAN_ID AND PARAM_ID = 2503;

  UPDATE VALL
  SET PARAM_ID = 3014
  WHERE OBJ_ID = :I$PLAN_ID AND PARAM_ID = 2478;

  UPDATE VALL
  SET PARAM_ID = 3346
  WHERE OBJ_ID = :I$PLAN_ID AND PARAM_ID = 3155;

  UPDATE VALL
  SET PARAM_ID = 3112
  WHERE OBJ_ID = :I$PLAN_ID AND PARAM_ID = 2166;

  UPDATE VALL
  SET PARAM_ID = 3016
  WHERE OBJ_ID = :I$PLAN_ID AND PARAM_ID = 2101;

  UPDATE VALL
  SET PARAM_ID = 3347
  WHERE OBJ_ID = :I$PLAN_ID AND PARAM_ID = 2466;

  UPDATE VALL
  SET PARAM_ID = 3022
  WHERE OBJ_ID = :I$PLAN_ID AND PARAM_ID = 2545;

  UPDATE VALS
  SET PARAM_ID = 3012
  WHERE OBJ_ID = :I$PLAN_ID AND PARAM_ID = 374;

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE Z_PP_IMPORT
AS
DECLARE VARIABLE V VARCHAR(400);
DECLARE VARIABLE V$PTP_ID BIGINT;
DECLARE VARIABLE V$OBJ_ID BIGINT;
DECLARE VARIABLE S VARCHAR(4000);
DECLARE VARIABLE V$LEVEL_ID BIGINT;
DECLARE VARIABLE V$SUBJECT_ID BIGINT;
DECLARE VARIABLE V$PTP_HOURS INTEGER;
DECLARE VARIABLE V$STAGE_MASK BIGINT;
DECLARE VARIABLE V$EDU_LEVEL_ID BIGINT;
DECLARE VARIABLE V$LESSON_ID BIGINT;
DECLARE VARIABLE V$DEST_ID BIGINT;
DECLARE VARIABLE V$DURATION FLOAT;
DECLARE VARIABLE V$TYPE_ID BIGINT;
DECLARE VARIABLE S2 VARCHAR(400);
begin

  SELECT MON$DATABASE_NAME
  FROM MON$DATABASE
  INTO :V;

  V = REPLACE(V, 'BASE.FDB', 'PP.FDB');

  V$PTP_ID = 0;
  WHILE(V$PTP_ID IS NOT NULL) DO
  BEGIN
    V$OBJ_ID = NULL;
    EXECUTE STATEMENT
      'SELECT FIRST 1 OBJ_ID, OBJ_NAME, SUBJECT_ID, LEVEL_ID, PTP_HOURS, STAGE_MASK, EDU_LEVEL_ID
      FROM PTP
      WHERE DATE_DEL IS NULL AND LEVEL_ID <> 2167 AND OBJ_NAME LIKE ''%ФОП%'' AND OBJ_ID > ' || V$PTP_ID || ' ORDER BY 1'
    ON EXTERNAL :V
    WITH COMMON TRANSACTION
    INTO :V$OBJ_ID, :S, :V$SUBJECT_ID, :V$LEVEL_ID, :V$PTP_HOURS, :V$STAGE_MASK, :V$EDU_LEVEL_ID;

    V$PTP_ID = V$OBJ_ID;

    IF(V$PTP_ID IS NOT NULL) THEN
    BEGIN
      V$OBJ_ID = NULL;
      SELECT FIRST 1 P.OBJ_ID
      FROM PTP P
      WHERE P.DATE_DEL IS NULL AND P.OBJ_NAME = :S AND P.LEVEL_ID = :V$LEVEL_ID
      INTO :V$OBJ_ID;

      IF(V$OBJ_ID IS NULL) THEN
      INSERT INTO PTP
      (OBJ_NAME, SUBJECT_ID, LEVEL_ID, PTP_HOURS, STAGE_MASK, EDU_LEVEL_ID)
      VALUES (:S, :V$SUBJECT_ID, :V$LEVEL_ID, :V$PTP_HOURS, :V$STAGE_MASK, :V$EDU_LEVEL_ID)
      RETURNING OBJ_ID INTO :V$OBJ_ID;

      V$LESSON_ID = -1;
      WHILE(V$LESSON_ID IS NOT NULL) DO
      BEGIN
        V$DEST_ID = NULL;
        EXECUTE STATEMENT
          'SELECT FIRST 1 P.LESSON_NUM, P.THEME_TEXT, P.DURATION, P.TYPE_ID, LIST(CAST(C.CONTROL_TYPE_ID AS VARCHAR(30)), '','')
          FROM PTP_LESSONS P
          LEFT JOIN PTP_LESSON_CONTROLS C ON C.LESSON_ID = P.OBJ_ID AND C.DATE_DEL IS NULL
          WHERE P.DATE_DEL IS NULL AND P.PTP_ID = ' || V$PTP_ID || ' AND P.LESSON_NUM > ' || V$LESSON_ID || ' GROUP BY 1, 2, 3, 4 ORDER BY 1'
        ON EXTERNAL :V
        WITH COMMON TRANSACTION
        INTO :V$DEST_ID, :S, :V$DURATION, :V$TYPE_ID, :S2;

        V$LESSON_ID = V$DEST_ID;

        IF(V$LESSON_ID IS NOT NULL) THEN
        BEGIN
          V$DEST_ID = NULL;
          SELECT FIRST 1 L.OBJ_ID
          FROM PTP_LESSONS L
          WHERE L.DATE_DEL IS NULL AND L.PTP_ID = :V$OBJ_ID AND L.LESSON_NUM = :V$LESSON_ID
          INTO :V$DEST_ID;

          IF(V$DEST_ID IS NULL) THEN
          INSERT INTO PTP_LESSONS
          (PTP_ID, LESSON_NUM, THEME_TEXT, DURATION, TYPE_ID)
          VALUES (:V$OBJ_ID, :V$LESSON_ID, :S, :V$DURATION, :V$TYPE_ID)
          RETURNING OBJ_ID INTO :V$DEST_ID;

          -- Контроли - только на пополнение
          FOR
            SELECT ID
            FROM STR_TO_ID_LIST(:S2)
            INTO :V$TYPE_ID
          DO
          BEGIN
            UPDATE OR INSERT INTO PTP_LESSON_CONTROLS
            (LESSON_ID, CONTROL_TYPE_ID)
            VALUES (:V$DEST_ID, :V$TYPE_ID)
            MATCHING (LESSON_ID, CONTROL_TYPE_ID);
          END
        END
      END
    END
  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE Z_RANDOM_SCUD
AS
declare variable V$OBJ_ID bigint;
begin

  FOR
    SELECT L10.OBJ_ID
    FROM LINKS L10
    WHERE L10.OBJ_TYPE_ID = 10 AND L10.PARENT_TYPE_ID = 9 AND L10.DATE_DEL IS NULL
    UNION
    SELECT L14.OBJ_ID
    FROM LINKS L14
    WHERE L14.OBJ_TYPE_ID = 14 AND L14.PARENT_TYPE_ID = 2 AND L14.DATE_DEL IS NULL
    INTO :V$OBJ_ID
  DO
  BEGIN
    IF(RAND() > 0.5) THEN
    BEGIN
      IF(NOT EXISTS(SELECT 1 FROM SCUD_PUPILS WHERE PUPIL_ID = :V$OBJ_ID)) THEN
      BEGIN
        INSERT INTO SCUD_PUPILS
        (PUPIL_ID, UPDATED)
        VALUES (:V$OBJ_ID, CURRENT_TIMESTAMP);
      END
    END
    ELSE
    BEGIN
      DELETE FROM SCUD_PUPILS
      WHERE PUPIL_ID = :V$OBJ_ID;
    END

    INSERT INTO SCUD_RAW
    (PERSON_ID, EVENT_DATE, EVENT_VAL)
    VALUES (:V$OBJ_ID, CURRENT_TIMESTAMP, IIF(RAND() > 0.5, 1, 0));

  END

end ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE Z_SCHOLAR (
    I$USER_ID BIGINT)
RETURNS (
    SCHOOL VARCHAR(500),
    CLASS VARCHAR(25),
    F VARCHAR(100),
    I VARCHAR(100),
    O VARCHAR(100),
    SEX VARCHAR(10),
    BIRTHDAY DATE,
    PLACE_OF_BIRTH VARCHAR(1000),
    DT_IN DATE,
    DT_OUT DATE)
AS
declare variable SCHOLAR_ID bigint;
declare variable CLASS_ID bigint;
declare variable LANG_CODE varchar(2);
BEGIN

  -- Неактуально

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE Z_SCHOLAR_IN (
    I$USER_ID BIGINT)
RETURNS (
    SCHOOL VARCHAR(100),
    CLASS VARCHAR(20),
    F VARCHAR(50),
    I VARCHAR(50),
    O VARCHAR(50),
    SEX VARCHAR(10),
    BIRTHDAY DATE,
    PLACE_OF_BIRTH VARCHAR(100),
    DT_IN DATE)
AS
declare variable SCHOLAR_ID bigint;
declare variable CLASS_ID bigint;
declare variable C_ID bigint;
declare variable LANG_CODE varchar(2);
BEGIN

  -- Неактуально

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE Z_SCHOLAR_OUT (
    I$USER_ID BIGINT)
RETURNS (
    SCHOOL VARCHAR(100),
    F VARCHAR(50),
    I VARCHAR(50),
    O VARCHAR(50),
    SEX VARCHAR(10),
    BIRTHDAY DATE,
    PLACE_OF_BIRTH VARCHAR(100),
    DT_IN DATE,
    DT_OUT DATE)
AS
declare variable SCHOLAR_ID bigint;
declare variable CLASS_ID bigint;
declare variable LANG_CODE varchar(2);
BEGIN

  -- Неактуально

END ^

COMMIT WORK ^

CREATE OR ALTER PROCEDURE Z_UPDATE_SPEC (
    TAG VARCHAR(100),
    NAME VARCHAR(1000),
    CAT_NAME VARCHAR(200))
AS
declare variable LISTVAL_ID bigint;
begin

    SELECT LV.LISTVAL_ID
    FROM LISTVALS LV
    JOIN RES R ON R.RES_ID = LV.RES_ID AND R.LANG_CODE = 'RU' AND R.VAL = :NAME
    JOIN LISTVALS LP ON LP.LISTVAL_ID = LV.PARENT_ID
    JOIN RES RP ON RP.RES_ID = LP.RES_ID AND R.LANG_CODE = 'RU' AND RP.VAL = :CAT_NAME
    WHERE LV.LIST_ID = 269 AND LV.IS_DEL = 0
    INTO :LISTVAL_ID;

    UPDATE LISTVALS LV
    SET LV.TAG = :TAG
    WHERE LV.LISTVAL_ID = :LISTVAL_ID;

end ^

COMMIT WORK ^


SET TERM ; ^

GRANT EXECUTE ON PROCEDURE ACCEPT_GIA_DTL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE ACCEPT_GIA_PROCESS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE ACCEPT_GRADE_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE ACCESS_SELECTOR_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE ACCESS_SELECTOR_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE ACTIVEDIR_USERS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE ACTIVEDIR_USER_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE ADDITIONAL_EDU_GPD_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE ADD_EXTERNAT_GRADUATE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE ADR_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE ADR_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE ANALISYS_REPORT_DISTRICT_1 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE ANALISYS_REPORT_DISTRICT_2 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE ANALISYS_REPORT_DISTRICT_3 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE ANALISYS_REPORT_DISTRICT_4 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE ANALISYS_REPORT_SCHOOL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE ANALISYS_SUBJECT_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE APPLY_AOOP_TYPE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE APPLY_OVZ_TYPE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE AREA_SL_ROOMS_CALC TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE ATT_CHOOSE_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE ATT_CLASSES_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE ATT_CLASS_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE ATT_CONTENT_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE ATT_DATE_VERIFY TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE ATT_DOCS_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE ATT_DOCS_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE ATT_FILE_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE ATT_FILE_DELETE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE ATT_FILE_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE ATT_FILE_STATE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE ATT_FOLDER_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE ATT_FOLDER_DELETE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE ATT_FOLDER_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE ATT_FOLDER_STATE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE ATT_INFO_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE ATT_MARK_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE ATT_OU_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE ATT_PKG_DATA TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE ATT_REGISTER_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE ATT_REGISTER_APPROVE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE ATT_REGISTER_DELETE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE ATT_REGISTER_EXPLODE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE ATT_REGISTER_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE ATT_REGISTER_LATE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE ATT_REGISTER_MARK TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE ATT_REGISTER_MERGE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE ATT_REGISTER_REJECT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE ATT_REGISTER_SCHEDULE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE ATT_REGISTER_SILENT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE ATT_REGISTER_STATE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE ATT_REGISTER_STUDENTS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE ATT_REGISTER_TEACHERS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE ATT_REG_MARK_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE ATT_REG_STUDENTS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE ATT_REG_TEACHERS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE ATT_REG_WIZDATA TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE ATT_SCHOOLAR_FIND TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE ATT_SUBJECT_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE ATT_VAL_AFTER TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE BARBUTTONS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE BARBUTTON_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE BARBUTTON_MOVE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE BARS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE BAR_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE BLOBS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE BOOK_SRC_SUBJECT_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE BOTAPI_IDENTIFY TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE BOT_MESSAGES_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE BOT_MESSAGE_CONFIRM TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE BUILDER_ACCESS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE BUILD_CURPLAN_HOURS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE BUILD_FIO TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE BUILD_REP_FIO TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE BUILD_REP_PARENT_VAL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE BVL_GIA_QUERY_REGION TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CALC_AGE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CALC_JOB_OCCUPIED TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CALENDAR_PLAN_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CAPTION_VIRTUAL_EXTERNAL_CLASS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CARDS_LIST_PERSONS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CARDS_LIST_SUBS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CARDS_MAIN_REPORT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CARDS_RETURN TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CARDS_TAGS_REPORT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CARDS_TAG_TEMPLATE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CARD_TO_STR TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CARTOGRAPHY_DATA_EXPORT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CEC_BROWSE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CEC_BROWSE_ITEMS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CEC_DELETE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CEC_DESCRIBE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CEC_DE_DELETE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CEC_DE_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CEC_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CEC_ITEM_DE_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CEC_ITEM_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CEC_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CEC_USA_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CERTIFICATE2_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CERTIFICATE2_DEL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CERTIFICATE2_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CERTIFICATE2_YEARS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CERTIFICATE_BASE_TMP_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CERTIFICATE_CLASSES_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CERTIFICATE_CLASS_ENABLED_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CERTIFICATE_CLASS_INFO_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CERTIFICATE_CLASS_INFO_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CERTIFICATE_CLASS_LOAD_SUBJECTS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CERTIFICATE_CLASS_LOAD_SUBJ_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CERTIFICATE_CLASS_SUBJECT_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CERTIFICATE_CLASS_SUBJECT_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CERTIFICATE_DIR_FORM_MASTER_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CERTIFICATE_DUPL_PUPIL_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CERTIFICATE_DUPL_PUPIL_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CERTIFICATE_FORM_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CERTIFICATE_OBJECT_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CERTIFICATE_OO_DEF_PARAM_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CERTIFICATE_OO_SETTINGS_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CERTIFICATE_OO_SETTINGS_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CERTIFICATE_PUPIL_ENABLED_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CERTIFICATE_PUPIL_INFO_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CERTIFICATE_PUPIL_INFO_READ TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CERTIFICATE_PUPIL_INFO_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CERTIFICATE_PUPIL_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CERTIFICATE_PUPIL_LOAD_SUBJECTS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CERTIFICATE_PUPIL_LOAD_SUBJ_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CERTIFICATE_PUPIL_SUBJECT_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CERTIFICATE_PUPIL_SUBJECT_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CERTIFICATE_PUPIL_TEMPLATES_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CERTIFICATE_REG_CLASSES_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CERTIFICATE_REG_CLASS_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CERTIFICATE_REG_CLASS_PRIL_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CERTIFICATE_REG_DUPL_INFO_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CERTIFICATE_REG_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CERTIFICATE_REG_PUPIL_CLASS_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CERTIFICATE_REG_TITUL_INFO_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CERTIFICATE_REG_YEARS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CERTIFICATE_SN_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CERTIFICATE_STAGES_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CERTIFICATE_STAGE_SUBJECT_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CERTIFICATE_STAGE_SUBJECT_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CERTIFICATE_SUBJECT_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CERTIFICATE_SUBJECT_MAP_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CERTIFICATE_SUBJECT_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CERTIFICATE_TEMPLATES_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CERTIFICATE_TEMPLATES_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CERTIFICATE_TYPES_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CERT_PUPIL_FINAL_MARKS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CERT_PUPIL_LOAD_SUBJECTS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CERT_STUDY_PUPIL_LOAD_SUBJECTS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CERT_STUDY_REG_CLASS_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CERT_STUDY_REG_CLASS_PRIL_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CERT_STUDY_REG_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CHANGER_CLASSES_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CHANGER_CLASS_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CHANGER_CLASS_NEXT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CHANGER_CLEAR_ALL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CHANGER_CLEAR_ENTRANCE_GRADES TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CHANGER_CREATE_GUP TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CHANGER_DELETING_PLANS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CHANGER_GRADES_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CHANGER_GRADE_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CHANGER_MONITORING_CLEANUP TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CHANGER_MONITORING_PROCCESS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CHANGER_PARALLEL_FIXER TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CHANGER_PCLASSES_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CHANGER_PUPIL_GIA_OUT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CHANGER_PUPIL_OUT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CHANGER_STAGES_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CHANGE_PROCESS_ORDERS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CHECK_ACTIVE_DOCUMENTS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CHECK_CURRICULUM_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CHECK_DIRECTOR_EXISTS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CHECK_EMPLOYEE_TEACHING_IS_LEFT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CHECK_EMPL_MENTOR TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CHECK_INN TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CHECK_MEDAL_ALLOW TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CHECK_OGRN TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CHECK_OP_PLAN_EXISTS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CHECK_ORDERS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CHECK_PLAN_STAGE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CHECK_PLAN_STATUS_CANCHANGE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CHECK_SNILS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CHECK_UNIQUE_DIVS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CHECK_USER_PWD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2022_DO2_LINKS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_ALIASES_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_ALIAS_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_ASST_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_ASST_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_ASST_VERIFY TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_AUDIT_ACCESS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_AUDIT_DELETE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_AUDIT_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_AUDIT_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_AUDIT_STATUS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_AUDIT_TEST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_AVMEMBERS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_CC_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_CC_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_CC_VERIFY TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_CJ_LIST_PTP TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_CLASS_JOURNALS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_DESCRIBE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_EXT_CONTROLS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_EXT_UPDATE_MARK TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_FILE_VERIFY TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_FULL_NAME TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_GPP_COPY_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_GRADE_ACCESS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_GROUPS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_HOMEWORK_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_JOURNAL_ACCESS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_JOURNAL_ACCESS_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_JOURNAL_ACCESS_UPD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_JOURNAL_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_JOURNAL_DELETE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_JOURNAL_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_JOURNAL_ITEM_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_JOURNAL_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_LESSONS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_LESSON_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_LESSON_ATTR_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_LESSON_ATTR_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_LESSON_AUTO TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_LESSON_CONTROL_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_LESSON_CONTROL_DELETE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_LESSON_DELETE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_LESSON_FILE_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_LESSON_FILE_DELETE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_LESSON_FINAL_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_LESSON_FINAL_DELETE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_LESSON_FINAL_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_LESSON_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_LESSON_MS_ASSIGN TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_LESSON_RES_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_LESSON_RES_DELETE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_LESSON_SETINST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_LESSON_TEACHERS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_LOAD_REPORT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_LOAD_TEACHERS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_MARKS_AGG TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_MARK_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_MARK_DETAILS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_MARK_FINAL_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_MARK_HISTORY TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_MASTER_ASSIGN TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_MEMBERS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_MEMBER_MOVEMENTS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_MENU_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_MISS_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_MOODLE_SUBSCRIBE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_MOODLE_SUBSCRIPTIONS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_PELIKAN_JOIN TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_PELIKAN_RSV TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_PELIKAN_UNDO TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_PERSON_MISS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_PERSON_NAME TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_PRESENCE_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_PRINT_DATA TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_PTP_APPROVE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_PTP_APPROVE_HAS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_PTP_APPROVE_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_PTP_ASSIGN TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_PTP_ASSIGN_CJ TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_PTP_CLONE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_PTP_DELETE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_PTP_FIX_HOURS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_PTP_LESSON_CLONE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_PTP_LESSON_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_PTP_LIST_BY_OWNER TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_PTP_LIST_CJ TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_PTP_LIST_GEN TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_PTP_LIST_GEN_INT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_PTP_LIST_OLD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_PTP_MENU_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_PTP_MIGRATE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_PTP_OLD_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_PTP_REASSIGN TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_PTP_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_PTP_TRANSFER TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_RANDOMDATA TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_REPLACEMENT_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_REPLACEMENT_DELETE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_REPLACEMENT_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_REPLACEMENT_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_REPL_APPROVE_DATES TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_REPL_BYDATE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_REPL_CAL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_REPL_DAPPROVE_DATES TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_REPL_DAYDATA TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_REPL_PROCESS_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_REPL_PROCESS_APPR TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_REPL_PROCESS_DELETE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_REPL_PROCESS_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_REPL_PROCESS_SRL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_REPL_PROCESS_UA TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_REPL_REPORT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_REPL_REPORT_1 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_REPL_REPORT_2 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_REPL_REPORT_3 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_REPL_TEACHERS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_REPORTS_DTL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_REPORTS_MENU TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_REPORT_NX100 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_REPORT_NX100_LESSONS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_REPORT_NX107 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_REPORT_NX11 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_REPORT_NX19 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_REPORT_NX2 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_REPORT_NX200 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_REPORT_NX210 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_REPORT_NX22 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_REPORT_NX2_OU TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_REPORT_NX300 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_REPORT_NX310 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_REPORT_NX310_CC TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_REPORT_NX310_FN TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_REPORT_NX310_PA TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_REPORT_NX310_SUBJ TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_REPORT_NX320 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_REPORT_NX320_CC TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_REPORT_NX320_PA TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_REPORT_NX321 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_REPORT_NX330 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_REPORT_NX330_CC TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_REPORT_NX400 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_REPORT_NX7 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_RESOURCES_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_SCHEDULE_GEN TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_SCHEDULE_STREAM TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_SCUD_PUPIL_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_SERIALIZE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_STATE_PROCESS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_TEACHER_NAME TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_UPDATE_RATING TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_USA_UPDATE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_WEEKDAYS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ2_WIZARD_DATA TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ_COLLEGE_SUBJECTS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ_GRADE_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ_GRADE_LIST3 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ_GRADE_SUBJECTS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ_IS_GROUP_CLASSMATE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ_PTP_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ_PTP_GET_FOR_CJ TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ_PTP_LIST_TEMPLATES TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ_PTP_PLAN_HOURS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ_PTP_PREVIEW TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ_PTP_STAGE_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ_PTP_ULESSONS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ_PTP_USEREFS_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ_STAGE_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ_STAGE_SUBJECTS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CJ_TEACHER_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CLASSES_COUNT_DISTRICT_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CLASSES_COUNT_ON_DATE_DTL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CLASSES_COUNT_ON_DATE_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CLASSEXTERNAT_LIST_NEXT_STAGE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CLASSEXTERNAT_PUPILS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CLASSEXTERNAT_PUPIL_TRANSFER TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CLASSEXTERNAT_TRANSFER_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CLASSIFY_COURSE_EXPORT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CLASS_EDU_DO_ATTR TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CLASS_EDU_DO_DATA TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CLASS_EDU_DO_MOVEMENTS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CLASS_EDU_DO_SETMOVE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CLASS_FILLDET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CLASS_OVZ_RECALC TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CLASS_PERIOD_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CLASS_PUPIL_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CLASS_VIRT_ID TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CLEAR_LEEVED_EMPLOYEE_STATUS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CLEAR_PPE_ROOMS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE COLLEGE_DISCIPLINES_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE COLLEGE_GRADE_CURRICULUM_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE COLLEGE_GRADE_DISCIPLINES_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE COLLEGE_GRADE_GROUPS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE COLLEGE_GRADE_LOADING_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE COLLEGE_GRADE_LOADING_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE COLLEGE_GRADE_TEACHERS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE COLLEGE_GRADE_TEACHER_L_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE COLLEGE_LOADING_COMPONENTS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE COLLEGE_LOADING_SUBJECTS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE COLLEGE_LOADING_UNION_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE COLLEGE_LOADING_VALS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE COLLEGE_OUT_PUPIL_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE COLLEGE_PUPIL_OUT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE COLLEGE_PUPIL_OUT_ALL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE COLLEGE_PUPIL_SPECIALITY_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE COLLEGE_SEMESTR_COUNT_CHANGED TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE COLLEGE_SP_STAGE_CHANGED TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE COLLEGE_VERIFY_ALL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE COLLEGE_VERIFY_BUILDING TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE COLLEGE_VERIFY_PUPIL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CONTINGENT_CALC_FOR_DISTRICT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE COPP_GROUP_SYNC TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE COPP_OP_SYNC TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE COPP_ORGANIZATION_FORCE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE COPP_ORGANIZATION_SYNC TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE COPP_PERSON_SYNC TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE COPY_EMPLOYEE_SNILS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE COPY_PARAM_VALUE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE COPY_SPO_CODES TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE COUNT_SL_ROOMS_CALC TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CPLAN_COPY TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CPLAN_PRINT_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CPLAN_ROW_DELETE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CPLAN_ROW_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CPLAN_ROW_IMPORT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CPLAN_ROW_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CREATE_CALENDAR_PLAN TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CREATE_CHECK_PLAN TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CREATE_CJ_VOSP TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CREATE_EDU_LOAD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CREATE_GZ_FOLDERS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CREATE_LOCAL_ACT_FOLDER TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CREATE_MTL_REPORT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CREATE_REPORT_FOLDERS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CREATE_SCHEDULE_DEF TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CREATE_SNILS_INDEX TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CUP_EXPORT_COMPONENTS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CUP_EXPORT_LOADS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CURGROUP_MOVE_PUPIL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CURRENT_DATE_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CURRENT_SCHOOL_YEAR_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CURRENT_TIME_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CURRENT_YEAR_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CURRICULUM_CONTROL_REPORT1 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CURRICULUM_CONTROL_REPORT2 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CURRICULUM_CONTROL_REPORT3 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CURRICULUM_CONTROL_REPORT4 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CURRICULUM_DELTA_INV_SUBJ_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CURRICULUM_DELTA_SUBJECT_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CURRICULUM_DELTA_SUBJECT_GET2 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CURRICULUM_FILL_REPORT1 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CURRICULUM_GUP_HAS_PTP TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CURRICULUM_GUP_SUBJ_HAS_PTP TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CURRICULUM_GUP_SUBJ_PTP_HOURS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CURRICULUM_HOURS_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CURRICULUM_HOURS_GET_CONST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CURRICULUM_INV_SUBJ_EXISTS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CURRICULUM_REPLACE_SUBJECT_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CURRICULUM_STAGE_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CURRICULUM_SUBJECT_HOURS_NEQ TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CURRICULUM_SUBJECT_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CURRICULUM_SUBJECT_LIST_HS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CURRICULUM_SUBJECT_TO_FGOS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE CURRICULUM_VIRTUAL_SUBJECT_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DATABUILDER_SETUP TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DATAPACKET_VALIDATE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DATE2ISO TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DATE2SCRIPT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DATE2STR TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DATIVECASE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DAYS_COUNT_TO_WORK_TIME TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_DELETE_LEAVE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_LINK_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_LIST_CONTENT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_LPJ_SERIALIZE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_LPJ_SERIALIZE_FILES TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_LPJ_SERIALIZE_LESSONS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_LPJ_SERIALIZE_MARKS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_LPJ_SERIALIZE_MOVES TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_LPJ_SERIALIZE_MSG TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_LPJ_SERIALIZE_MSGRCPT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_LPJ_SERIALIZE_RATING TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_LPJ_SERIALIZE_SCHEDULE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_MAX_CHATS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_MOVEMENT_DELETE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_MOVEMENT_REACCEPT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_MOVEMENT_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_MS_ADAPTATION TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_MS_ADDRESS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_MS_CHANGES TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_MS_CHANGE_DETAILS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_MS_CLASSES_PERIODS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_MS_COMMONPLANMARKS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_MS_CSTUDENTS_EDU_GROUP TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_MS_DOCUMENTS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_MS_ECONOMY_ACTIVITY TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_MS_EDU_GROUPS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_MS_EDU_LOCATIONS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_MS_EDU_LOCATIONS_CLASSES TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_MS_EVENTS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_MS_GROUPSS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_MS_HOMEWORKS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_MS_HOMEWORKS_MATERIALS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_MS_HOMEWORKS_STUDENTS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_MS_LESSONS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_MS_LESSONSCOUNT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_MS_LESSONS_MARKS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_MS_LESSONS_MATERIALS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_MS_LESSONS_STUDENTS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_MS_LESSON_PLAN TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_MS_LOCATION_PROPERTIES TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_MS_MARKS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_MS_MATERIALS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_MS_ORGANISATION_UNIT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_MS_ORG_ALIAS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_MS_ORG_MEMBER TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_MS_PL_ORG_UNIT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_MS_PMARKS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_MS_POSITIONS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_MS_POSITION_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_MS_PRECALC TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_MS_P_ORG_UNIT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_MS_QUALIFICATION TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_MS_REGION_EXPORT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_MS_REP_CITIZENSHIP TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_MS_REP_SCHOOL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_MS_REP_STD_SCHOOL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_MS_SCHOOL_CLASSES TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_MS_SKIPPINGS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_MS_SPECIALITY TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_MS_STATCOMMON TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_MS_STATSUBJECT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_MS_STUDENTS_COLLEGE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_MS_STUDENTS_SCHOOL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_MS_STUDENTS_TRAINING TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_MS_STUDENT_CITIZENSHIP TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_MS_SUBJECTS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_MS_SUBJECT_PLAN TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_MS_TEACHERS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_MS_TEACHERS_DOCUMENTS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_MS_TEACHERS_GROUPS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_MS_TEACHER_CITIZENSHIP TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_MS_TEACHER_ROLE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_MS_TEACHER_ROLE_EDU_GROUPS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_MS_TEACHER_ROLE_SERVICE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_MS_TELECOM TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_MS_TELECOM_LOCATIONS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_MS_TELECOM_ORGANISATIONS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_MS_TELECOM_STUDENT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_MS_TELECOM_TEACHER TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_MS_TELECOM_TEACHERS_ROLES TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_MS_UNIT_PLAN TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_MS_UPDATE_TM TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_MS_YMARKS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_OBJECTS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_OBJECT_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_OBJECT_CONTENT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_OBJECT_CONTEXT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_OBJECT_DELETE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_OBJECT_HISTORY TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_OBJECT_PARAM_DELETE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_OD_EDUCATION TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_OD_MEETINGS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_OD_MEETING_MEMBERS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_OD_PERSONS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_PORTAL_CONTENT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_PORTAL_CONTENT_DELETE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_PORTAL_CONTENT_TASKS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_PORTAL_CONTENT_TASKS_DELETE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_PORTAL_EDUCATION TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_PORTAL_EDUCATION_DELETE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_PORTAL_EDUCATION_GROUPS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_PORTAL_EDUCATION_GR_DELETE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_PORTAL_ESTIMATES TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_PORTAL_ESTIMATES_DELETE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_PORTAL_GROUPS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_PORTAL_GROUPS_DELETE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_PORTAL_INSTITUTION TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_PORTAL_JOB TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_PORTAL_JOB_DELETE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_PORTAL_LESSONS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_PORTAL_LESSONS_DELETE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_PORTAL_LESSON_FILES TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_PORTAL_LESSON_FILES_DELETE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_PORTAL_MEETINGS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_PORTAL_MEETINGS_DELETE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_PORTAL_MEETING_MEMBERS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_PORTAL_MEETING_MM_DELETE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_PORTAL_PERIODS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_PORTAL_PERIODS_DELETE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_PORTAL_PERSONS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_PORTAL_PERSONS_DELETE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_PORTAL_PORTFOLIO TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_PORTAL_PORTFOLIO_DELETE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_PORTAL_REPRESENTATIVES TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_PORTAL_REPS__DELETE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_PORTAL_SAVE_INST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_PORTAL_SCHEDULES TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_PORTAL_SCHEDULES_DELETE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_PORTAL_SCHEDULES_GROUPS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_PORTAL_SCHEDULES_GROUPS_DEL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_PORTAL_SCHEDULES_SUBJECTS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_PORTAL_SCHEDULES_SUBJ_DEL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_PORTAL_SCHEDULES_TEACHERS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_PORTAL_SCHEDULES_TEACH_DEL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_PORTAL_STUDENT_MV TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_PORTAL_SUBJECTS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_PORTAL_SUBJECTS_DELETE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_PORTAL_TASKS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_PORTAL_TASKS_DELETE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_PORTAL_TEACHERS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_PORTAL_TEACHERS_DELETE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_PORTAL_TEACHER_TO_SUBJECTS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_PORTAL_TTS__DELETE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_PUPIL_GRADUATE_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_PUPIL_LEAVE_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_PUPIL_MOVEMENTS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_RBOOK_ESTIMATIONS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_RBOOK_EXAMS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_RBOOK_STUDENTS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_REPORT_VERSION TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_SCUD_UPDATE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_SFERUM_CALLS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_SFERUM_CLASSCHATS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_SFERUM_CLEANUP TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_SFERUM_DELETE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_SFERUM_LINKS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_SFERUM_RESET_DONE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_SFERUM_RESET_USERS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_SFERUM_SUBJCHATS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_SFERUM_TEACHERS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_SFERUM_TIMEDOUT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_SFERUM_WM TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_SOCIAL_DELETE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_SOCIAL_SAVE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_SOP_UPDATE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_TRANSFER_CLASS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_UNDO_LEAVE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DC_VAL_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DELETE_STAY_DOCUMENTS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DG_FOODEVENTS_LAST_ID TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DG_FOOD_BENEFITS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DG_GIA_CODES TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DG_RC_EDUCATION TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DG_RC_EMPLOYEE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DG_RC_GET_ADDRESS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DG_RC_GET_DICT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DG_RC_INSTITUTION TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DG_RC_PERSON TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DISCIPLINE_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DISCIPLINE_CHECK TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DISCIPLINE_INDEX_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DISCIPLINE_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DISCIPLINE_LOADING_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DISCIPLINE_LOADING_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DISCIPLINE_LOADING_LIST_REPORT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DISCIPLINE_LOADING_PARAMS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DISCIPLINE_SUBTREE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DISCIPLINE_SUBTREE_IN TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DISCIPLINE_TIME_BUDGET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DISCIPLINE_TIME_BUDGET_REPORT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DISCIPLINE_TREE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DISTRICT_VERIFICATION_REP2_DTL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DISTRICT_VERIFICATION_REP3_DTL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DISTRICT_VERIFICATION_REP4_DTL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DISTRICT_VERIFICATION_REPORT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DISTRICT_VERIFICATION_REPORT2 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DISTRICT_VERIFICATION_REPORT2X TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DISTRICT_VERIFICATION_REPORT3 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DISTRICT_VERIFICATION_REPORT3X TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DISTRICT_VERIFICATION_REPORT4 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DISTRICT_VERIFICATION_REPORT4X TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DISTRICT_VERIFICATION_REPORT5X TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DISTRICT_VERIFICATION_REPORTX TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DISTRICT_VERIFICATION_REPX_DTL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DISTRICT_VERIFICATION_REP_DTL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DOU_CHECK_PARENT_STATUS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DOU_DISTR_VERIFICATION_REP2_DTL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DOU_DISTR_VERIFICATION_REP3_DTL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DOU_DISTR_VERIFICATION_REP4_DTL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DOU_DISTR_VERIFICATION_REPORT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DOU_DISTR_VERIFICATION_REPORT2 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DOU_DISTR_VERIFICATION_REPORT3 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DOU_DISTR_VERIFICATION_REPORT4 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DOU_DISTR_VERIFICATION_REP_DTL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DOU_GROUP_DIRECTION_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DOU_SCHOOLAR_IN TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DOU_VERIFY_ALL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DOU_VERIFY_BUILDING TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DOU_VERIFY_CLASS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DOU_VERIFY_DOCS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DOU_VERIFY_PUPIL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DOU_VERIFY_WORKERS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DO_CHECK TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DO_FAM_FIELD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DO_FUNC TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DO_FUNC2 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DO_FUNC_COUNT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DO_FUNC_MOVEMENT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DO_OBJECT_FILLED_CHECK TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DPO_DOCUMENTS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DPO_GROUP_FINISH TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DPO_GROUP_MEMBERS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DPO_GROUP_RESULTS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DPO_GROUP_SYNC TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DPO_PERSON_GROUP_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DPO_PLAN_EXPORT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DPO_PROGRAMS_EXPORT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DPO_PROGRAM_EXPORT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DPO_STUDENT_LEAVE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DPS_PERSON_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DROP_CLASS_LEADERSHIP TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DROP_STUDENT_MOVEMENTS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE DROP_TEACHING_LOADS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE D_12 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE D_12_ADD_CALC_DISTR TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE D_12_ADD_CALC_OU TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE D_12_ADD_GET_LBL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE D_12_ADD_GET_MOVEMENT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE D_12_ADD_GET_STAGES TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE D_12_ADD_INSERT_MOVEMENT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE D_12_ADD_INSERT_ROW TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE D_12_ADD_INSERT_ROWS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE D_12_ADD_INSERT_ROWS_DISTR TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE D_12_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE D_12_LIST_GET_SCHOOLAR TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE D_12_LIST_SUMM TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE D_12_MAIN_CALC_DISTR TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE D_12_MAIN_CALC_OU TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE D_12_MAIN_CALC_REGION TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE D_12_MAIN_GET_LBL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE D_12_MAIN_INSERT_ROW TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE D_12_MAIN_INSERT_ROWS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE D_12_MAIN_INSERT_ROWS_DISTR TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE EDITTYPES_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE EDUCATION_PROGRAM_DIR_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE EDULOAD_APPROVE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE EDULOAD_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE EDULOAD_PROCESS_DEFER TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE EDULOAD_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE EDULOAD_UPDATE_ORDER TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE EDU_REPORT_LEVELS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE EDU_REPORT_STAGES TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE EINSPECTOR_COINCIDE_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE EINSPECTOR_EQDEMAND_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE EINSPECTOR_EQDEMAND_COINCIDE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE EINSPECTOR_EQDEMAND_INIT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE EINSPECTOR_EQ_COINCIDE_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE EINSPECTOR_ROOMDEMAND_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE EINSPECTOR_ROOMDEMAND_CLEAR TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE EINSPECTOR_ROOMDEMAND_COINCIDE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE EINSPECTOR_ROOMDEMAND_INIT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE EMPLOYEES_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE EMPLOYEE_COURSE_IMPORT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE EMPLOYEE_JOBS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE EMPLOYEE_JOB_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE EMPLOYEE_JOB_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE EMPLOYEE_LEAVE_JOB_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE EMPLOYEE_LOAD_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE ENROLLEE_FIND_PUPIL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE ENROLLEE_SCHOOL_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE ENROLLEE_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE ENTRANCE_STAGE_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE EPT_FILTRED_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE ESCAPE_STR TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE EVENT_STAGE_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE EXPLODE_STR TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE EXPORT_CJ2_JOURNAL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE EXPORT_CONTINGENT_CALC TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE EXPORT_HASHES TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE EXPORT_INSPECTOR TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE EXPORT_LINKS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE EXPORT_LISTVALS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE EXPORT_LOCAL_DO_FUNC TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE EXPORT_METADATA TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE EXPORT_MI TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE EXPORT_MOVEMENTS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE EXPORT_OBJECTS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE EXPORT_ORDERS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE EXPORT_ORDER_DATA TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE EXPORT_PLAN_LOADS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE EXPORT_PLAN_RESOURCES TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE EXPORT_PLAN_SUBJECTS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE EXPORT_POST_AS_WORK_FUNC TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE EXPORT_RES TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE EXPORT_RETRAININGS_BY_SCHOOL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE EXPORT_RSOKO_INDICATORS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE EXPORT_RSOKO_SCHOOL_INDICATORS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE EXPORT_VALA TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE EXPORT_VALB TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE EXPORT_VALD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE EXPORT_VALDT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE EXPORT_VALF TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE EXPORT_VALI TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE EXPORT_VALL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE EXPORT_VALM TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE EXPORT_VALR TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE EXPORT_VALS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE EXPORT_VALT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE EXTERNAT_PUPIL_MOVEMENT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FGOS_SPECIALITY_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FGOS_SPECIALITY_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FILTERFIELDSSETS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FILTERFIELDSSET_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FILTERFIELDSSET_DEL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FILTERFIELDSSET_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FILTERFIELDS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FILTERFIELDS_LIST2 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FILTERFIELD_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FILTERFIELD_DEL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FILTERS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FILTERVALS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FILTERVAL_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FILTERVAL_DEL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FILTER_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FILTER_APARAM_CHECK TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FILTER_APPLY TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FILTER_APPLY2 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FILTER_APPLY3 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FILTER_CPARAM_CHECK TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FILTER_DEL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FILTER_DPARAM_CHECK TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FILTER_DTPARAM_CHECK TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FILTER_FPARAM_CHECK TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FILTER_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FILTER_IPARAM_CHECK TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FILTER_LPARAM_CHECK TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FILTER_OBJECT_CHILDREN_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FILTER_OBJECT_PARENTS_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FILTER_RPARAM_CHECK TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FILTER_SPARAM_CHECK TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FILTER_TPARAM_CHECK TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FILTRED_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FINALMARKS_CLASSES TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FINALMARKS_DATA TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FINALMARKS_DELETE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FINALMARKS_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FINALMARKS_MENU TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FINALMARKS_PM TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FINALMARKS_REPORT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FINALMARKS_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FINALMARKS_SUBJECTS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FINALMARK_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FINALMARK_CLASS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FINALMARK_DISTRICT_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FINALMARK_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FINALMARK_LIST2 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FINALMARK_LIST3 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FINALMARK_PUPIL_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FINALMARK_SCHOOL_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FINALMARK_SGC_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FINALMARK_SUBJECT_CLASS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FINALMARK_SUBJECT_FULL_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FINALMARK_SUBJECT_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FINALMARK_SUBJECT_LIST2 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FINALMARK_SYNCHRONIZE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FINALMARK_TEACHER_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FINALMARK_YEAR_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIND_EMPLOYEE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIN_CONFIG_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIN_LISTS_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIN_LIST_DELETE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIN_LIST_UPDATE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIN_ORG_APPLY_SETTINGS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIN_ORG_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIN_PARAMS_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIN_PARAM_DELETE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIN_PARAM_GROUPS_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIN_PARAM_GROUP_DELETE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIN_PARAM_GROUP_UPDATE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIN_PARAM_UPDATE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIN_VALUES_CLEAR TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIN_VALUE_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIN_VALUE_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIXER TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIXER3 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIXER4 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIXER5 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIXER_ALL_SNILS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIXER_ATHOME_STUDENTS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIXER_BAD_RELEASE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIXER_CERTIFICATE_FINAL_MARKS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIXER_CERTIFICATE_MARK TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIXER_CHANGER_LOST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIXER_CHANGER_LOST2 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIXER_CJ_DUPLICATES TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIXER_CLEAR_TEACHER_LABOR_RATE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIXER_CLONE_MARKS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIXER_CONVERT_VD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIXER_DELETED_CLASSES TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIXER_DELETED_CLASSES2 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIXER_DOU_INPUT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIXER_DOU_OUT_FOLDERS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIXER_EDUCATION_PROGRAM TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIXER_ENTRANCE_AS_GIA TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIXER_ENT_DATES TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIXER_EXTERNAT_ACCEPT_TYPE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIXER_EXTERNAT_LEAVED TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIXER_FINALS_EF TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIXER_FIX_COLLEGE_CIR_DIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIXER_FIX_PUPIL_STUDY_FORM TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIXER_FIX_REGION_GIA TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIXER_FIX_UDOD_CIR_DIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIXER_FPU_TMP TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIXER_GHOST_STUDENTS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIXER_GIA_ALIASES TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIXER_GIA_CLASS_TYPE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIXER_GIA_CLASS_TYPE2 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIXER_GIA_CLASS_TYPE3 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIXER_GIA_INFORMATIKA_PARAMS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIXER_GPDJ_PTP TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIXER_GRADUATE_CLASS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIXER_GUP_MASKS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIXER_HOMEBASED_EDU_ATTR TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIXER_JOURNAL_GRANTS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIXER_JOURNAL_JOURS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIXER_JOURNAL_PTP_LINKS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIXER_KEY TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIXER_LESSON_THEME TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIXER_MAJOR_TUTOR TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIXER_MICRODISTRICT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIXER_MISSING_MOVEMENTS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIXER_MONITORING_CHANGER TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIXER_ODNKNR TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIXER_OOOD_TYPE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIXER_ORGANIZATION_FORM TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIXER_OUTPUT_DOU TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIXER_OVZ TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIXER_OVZ_MOVE_TYPE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIXER_OVZ_STAGES2022 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIXER_P64 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIXER_PARAM_ID_1340 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIXER_PARAM_TYPE_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIXER_PARENTS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIXER_PARENTS_DOU TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIXER_PARENTS_DUPLICATES TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIXER_PARENT_EXT_DOU TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIXER_PARENT_REASONFORHELP TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIXER_PLANING TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIXER_POST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIXER_PUPIL_FINISH_TO_LEAVED TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIXER_RAISER_SKILL_JOB TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIXER_RAISER_SKILL_OOOD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIXER_REMOVE_DELETED_CERTIFICAT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIXER_REMOVE_FM_DUPLICATES TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIXER_REORGANIZE_DISTR_SUBJ TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIXER_REPAIR_OBJ_GEN TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIXER_SCHOOL_DISTRICT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIXER_SNILS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIXER_SNILS_DUPLICATE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIXER_STD2021_RECALC TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIXER_STUDY_FORM TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIXER_UDOD_P2448 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIXER_USERS_LANGUAGE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIXER_VD_DEST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIXER_YC2021 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIXER_YEAR_IN_FINALMARK TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIX_CALC_JOB_PARAMS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIX_CJ2_DUPLICATES TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIX_CJ2_LESSON_TIME TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIX_DC_TASKS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIX_DC_TASKS_DOU TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIX_DEMO_EXAM_FORMAT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIX_DOU_GUP TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIX_DOU_LEAVES TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIX_DUPLICATES TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIX_EMPLOYEES_SNILS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIX_ENTERING_PUPILS_TO_STAGE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIX_EXTERNAT_LEAVED TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIX_FILL_REQ_FIELDS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIX_FISOKO_INIT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIX_FPU2019 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIX_GIA_NEW_FOLDER TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIX_GRADUATES TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIX_JOB_LINK TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIX_JOB_R3 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIX_LESSON_THEME_PLAN_DEL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIX_LIBRARY_ROOTTYPE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIX_LONG_VACATIONS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIX_LOST_LINKS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIX_LOST_STUFF TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIX_MERGE_DB TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIX_MERGE_DB_MOVEMENTS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIX_MERGE_DB_VALS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIX_MERGE_PLAN TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIX_MOVEMENTS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIX_MOVEMENTS_OU TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIX_MOVE_GROUP_TYPE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIX_MOVE_LEVEL_ID TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIX_NEW_ACCEPTED_DATE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIX_OD_PERIODS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIX_OUTPUT_LAST_MOVEMENT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIX_OU_STUDY_LEVELS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIX_PERIOD_FIELDS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIX_PLANS400 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIX_PLAN_FIELD_ID TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIX_RECALC_TCO TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIX_RESTORE_JOB_GROUP TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIX_SCHEDULE_FOLDER TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIX_SCHEDULE_ITEMS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIX_SOP_TIMELINE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIX_SPO_ACAD_MOVEMENTS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIX_SPO_LICDATA TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIX_SPO_LICDATA_DTL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIX_SPO_MOVEMENTS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIX_SPO_SPEC_CODES TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIX_SPO_TRANSFER TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIX_STEAD_FOLDER TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIX_STUDENT_EDU_FROM TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIX_STUDY_PLANS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIX_TEMPLATE_UP_DAMAGED TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIX_UPGRADE_REQUEST_YEAR TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIX_USER_LEVELS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIX_VACANCY_CATEGORIES TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FIX_VARGRP_MOVES TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FN_EXAM_DATE_DELETE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FOOD_BENEFIT_APP_EXPORT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FOOD_BENEFIT_APP_EXPORT_PUPIL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FOOD_BENEFIT_APP_EXPORT_SCHOOL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FOOD_BENEFIT_APP_EXPORT_VERIFY1 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FOOD_BENEFIT_APP_EXPORT_VERIFY2 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FOOD_BENEFIT_APP_PUPIL_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FOOD_PUPIL_PARENTS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FOOD_SERVICER_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FOOD_UPDATE_SERVICER TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FPFIX TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FPU_CODE_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FULLLOAD_RQ_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FULLLOAD_RQ_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FULLOAD_REQUEST_CHECK TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FUTURE_GUP_CHECK TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FUTURE_GUP_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE FUTURE_GUP_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GENERATE_PTP_NAME TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GET_DAYS360_COUNT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GET_LAST_SCHOLAR_MOVE_ID TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GET_PIPIL_BY_SNILS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GIA_ACCEPT_CHECK_INT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GIA_APPOINT_ASSIGN TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GIA_APPOINT_CLASS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GIA_APPOINT_CURRENT_YEAR TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GIA_APPOINT_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GIA_APPOINT_REPORT_CONTENT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GIA_APPOINT_REPORT_HEADER TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GIA_BUILDING_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GIA_CHECK_CLASS_CHANGE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GIA_CHECK_PUPIL_EXAMS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GIA_CLASS_GRADUATING_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GIA_CLASS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GIA_CLASS_SCHOLAR_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GIA_CLASS_SINONIM_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GIA_CODES_CHECK TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GIA_CODES_EXPORT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GIA_CODES_EXPORT_CHECK TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GIA_CODES_IMPORT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GIA_CODES_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GIA_CODES_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GIA_CODES_SET_DISTRICT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GIA_CODE_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GIA_COPY_INFO_EXAM_PARAMS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GIA_EXAM_ATTACH_PPE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GIA_EXAM_ATTACH_PPE_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GIA_EXAM_DATE_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GIA_EXAM_DATE_CHECK TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GIA_EXAM_DATE_DEL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GIA_EXAM_DATE_EXPORT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GIA_EXAM_DATE_EXPORT_CHECK TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GIA_EXAM_DATE_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GIA_EXAM_DATE_IMPORT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GIA_EXAM_DATE_IMPORT_XML TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GIA_EXAM_DATE_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GIA_EXAM_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GIA_EXAM_PERMIT_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GIA_EXAM_PPE_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GIA_EXAM_STAGE_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GIA_EXAM_STATEMENT_IMPORT_XML TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GIA_EXAM_STEP_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GIA_EXAM_SUBJECT_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GIA_EXAM_YEAR_EXPORT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GIA_EXAM_YEAR_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GIA_EXAM_YEAR_IMPORT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GIA_EXAM_YEAR_IMPORT_XML TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GIA_EXPORT_DATA TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GIA_EXPORT_DATA_STUDENTS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GIA_FIND_STUDENT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GIA_FOREIGN_LANG_VERBALLY_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GIA_FORMDATA TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GIA_GET_DIRECTOR_FIO TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GIA_IS_VPL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GIA_NOT_PERMIT_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GIA_NOT_PERMIT_LIST_DISTR TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GIA_OU_EXPORT_CHECK TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GIA_OU_EXPORT_CHECK_FIO TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GIA_OU_EXPORT_CLASSROOM TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GIA_OU_EXPORT_PERSON TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GIA_OU_EXPORT_STUDENT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GIA_OU_EXPORT_STUDENT_EXAM TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GIA_OU_EXPORT_XML TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GIA_OU_EXPORT_XML_CHECK TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GIA_OU_ISVALID TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GIA_OU_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GIA_PPE_FLAGS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GIA_PPE_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GIA_REPORT_IF4_P1 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GIA_REPORT_IF4_P2 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GIA_RESET_GENERATORS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GIA_ROOM_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GIA_ROOM_CHECK TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GIA_ROOM_DEL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GIA_ROOM_EDIT_COL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GIA_ROOM_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GIA_ROOM_LIST2 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GIA_ROOM_LIST_COL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GIA_SUBJECT_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GIA_TRANSFER_EXPORT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GIA_TRANSFER_IMPORT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GIA_TRANSFER_IMPORT_FOLDER TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GIA_WORKER_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GPD_ACCEPT_PUPIL_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GPD_MEMBERS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GPD_PARENT_SCHOLAR_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GPD_PLAN_AUTHORS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GPD_REPORT_PARENT_SCHOLAR TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GPD_REPORT_SCHOLAR_HEALTH TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GPD_REPORT_SCHOLAR_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GPD_SUBJECTS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GPD_TRANSFER_PUPIL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GRADES_SCHOOLARS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GRADE_SCHOOLARS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GRID_CAPTION_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GRID_SELECT_ITEMS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GROUP_ITEM_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GROUP_PLAN_ID TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GUP_SUBJ_PTP_CJ_STATUS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GUP_SUBJ_PTP_EXECUTION_STATUS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GZ_ADD_CHECK TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GZ_ADD_QUALITY TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GZ_ADD_SECTION TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GZ_ADD_VOLUME TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GZ_CALC_RESULT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GZ_COPY TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GZ_DELETE_CHECK TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GZ_FUNC TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GZ_MEMBERS_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GZ_MEMBER_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GZ_NEXT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GZ_RENUMBER_SECTIONS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GZ_REPORT_AGG_VOL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GZ_REPORT_DATA TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GZ_REPORT_LIST_VOL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GZ_REPORT_MEMBERS_VOL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GZ_REPORT_OO_QTY TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GZ_REPORT_OO_VOL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GZ_RESULTS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GZ_SAVE_RESULT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE GZ_VAL_AFTER TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE HAS_FALSE_PUPIL_WITH_EDU_DOC TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE HOUSE_GUID_WRITE_IN TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE IAC3_FINDLEARNERSBYEDUDOC TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE IAC3_FINDLEARNERSBYIDENTDOC TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE IAC3_FINDLEARNERSBYPARAMS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE IAC3_FINDLEARNERSBYSNILS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE IAC3_FINDSCHOOLBYPARAMS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE IAC3_GETEDUCATIONDOCUMENT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE IAC3_GETIDENTITYDOCUMENTBYID TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE IAC3_GETLEARNERBYPID TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE IAC3_GETLEARNERSEDUDOCS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE IAC3_GETLEARNERSIDENTDOCS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE IAC3_GETLEARNERSREGISTRATIONS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE IAC3_GETSCHOOLBYID TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE IMPORT_CLEAR_LINKS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE IMPORT_CLEAR_REG_LINKS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE IMPORT_CREATE_INDEXES TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE IMPORT_DROP_INDEXES TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE IMPORT_OLD_CARDS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE INFOEQUIPMENT_ESTIMATION_DTL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE INFOEQUIPMENT_ESTIMATION_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE INFOEQUIPMENT_ESTIMATION_OU_REP TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE INFOEQUIPMENT_ESTIMATION_REPORT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE INFO_KEY_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE INTOKC_SCHOLAR_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE IS_CURRICULUM_HAS_NET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE IS_DOU TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE IS_MANAGER TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE IS_NATIVE_ID TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE IS_ON_THE_STAFF TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE IS_ROOT_OBJ_PARENT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE IS_SECOND_YEAR TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE IS_TEACHER TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE IS_VPL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE IS_YOUNG_EMPLOYEE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE JOBLIST_DELETE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE JOBLIST_DESCRIBE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE JOBLIST_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE JOBLIST_MERGE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE JOBLIST_MERGE_CND TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE JOBLIST_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE JOBLIST_TRANSFER TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE JOB_FUNCTION_TO_CODE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE JOB_LIST_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE JOB_LIST_COPY TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE JOB_LIST_CURRENT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE JOB_LIST_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE JOB_LIST_HEADERS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE JOB_LIST_SYNC TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE JOB_LIST_VERIFY TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE JOB_POS_DELETE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE JOB_POS_DELETE_ALL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE JOB_POS_MOVE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE JOB_POS_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE JOB_POS_SINGLE_VAL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE KONTINGENT_DOC_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE KONTINGENT_EMPLOYEES_EXPORT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE KONTINGENT_EMPLOYEE_EXPORT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE KONTINGENT_EXPORT_PROP_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE KONTINGENT_FILEUPDATE_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE KONTINGENT_FILEUPDATE_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE KONTINGENT_LAST_EXPORT_DATE_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE KONTINGENT_OOOD_EXPORT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE KONTINGENT_PERSONS_EXPORT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE KONTINGENT_PERSON_EXPORT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE KONTINGENT_PUPILS_EXPORT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE KONTINGENT_PUPIL_EXPORT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE KONTINGENT_UDOD_EMPLOYEES_EXP TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE KONTINGENT_UDOD_PERSONS_EXPORT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE KONTINGENT_UDOD_PUPILS_EXPORT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LAST_BACKUP_DATE_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LD_STUDENT_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LD_STUDENT_UPDATE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LD_STUFF_UPDATE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LEAVED_PUPIL_W_ATT_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LEAVE_TO_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LEVELS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LEVEL_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LEVEL_BARS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LEVEL_MOVE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LEVEL_TYPES_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIB2_ABN_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIB2_ABN_INFO TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIB2_ABN_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIB2_ABN_MASS_ASSN TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIB2_ABN_MASS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIB2_BOOK_ADD_FPU TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIB2_BOOK_DELETE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIB2_BOOK_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIB2_BOOK_GIVE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIB2_BOOK_HISTORY TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIB2_BOOK_RETURN TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIB2_BOOK_RETURN_ALL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIB2_BOOK_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIB2_BOOK_SET_ATTR TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIB2_BOOK_UNDO TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIB2_DESCRIBE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIB2_LISTS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIB2_LISTVAL_DELETE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIB2_LISTVAL_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIB2_LISTVAL_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIB2_LIST_DELETE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIB2_LIST_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIB2_LIST_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIB2_LIST_TREE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIB2_LOCATIONS_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIB2_LOCATION_BASE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIB2_LOCATION_DEL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIB2_LOCATION_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIB2_LOC_COUNT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIB2_MASS_ASSN TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIB2_MASS_GIVE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIB2_MG_PFPE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIB2_MOVE_CLEANUP TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIB2_MOVE_DELETE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIB2_MOVE_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIB2_MOVE_ITEM_IDS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIB2_MOVE_ITEM_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIB2_MOVE_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIB2_MOVE_TRANSFER TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIB2_REPORT_NX10 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIB2_REPORT_NX30 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIB2_REPORT_NX50 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIB2_REPORT_NX60 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIB2_REPORT_NX90 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIB2_REPORT_NX98 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIB2_REPORT_NX99 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIB2_SEARCH_DATA TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIB2_TRANSFER TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIB2_USAGE_SUBJ_GUP TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIB2_WB_SUFFICIENCY_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIB_BOOK_ADD_FPU TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIB_BOOK_UPDATE_PRG TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIB_BOOK_VALIDATE_REFS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIB_FORMS_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIB_FORMS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIB_FPU_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIB_FPU_DELETE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIB_FPU_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIB_FPU_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIB_FPU_UPDATE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIB_FPU_UPDATE_MASS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIB_FP_ADD_PUBLISHER TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIB_FP_BOOK_INFO_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIB_PUPIL_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIB_PUPIL_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIB_SCHOOL_INFO TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIB_SUBJECT_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIB_TEACHER_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIB_TEACHER_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIB_TEACHER_POSITION_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LICENCE_INFO_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIC_DATA_04_1 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIC_DATA_04_2 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIC_DATA_04_4 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIC_DATA_05 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIC_DATA_05_1 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIC_DATA_05_2 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIC_DATA_05_3 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIC_DATA_05_4 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIC_DATA_05_5 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIC_DATA_05_6 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIC_DATA_05_7 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIC_DATA_06_1 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIC_DATA_07 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIC_DATA_07_1 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIC_DATA_07_2 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIC_DATA_07_3 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIC_DATA_07_4 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIC_DATA_07_5 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIC_DATA_08 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIC_DATA_08_1 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIC_DATA_10 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIC_DATA_10_1 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIC_DATA_APP12 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIC_DATA_APP33 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIC_DATA_APP6 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIC_DATA_APP7 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIC_DATA_APP7_2 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIC_DATA_DOCOU TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIC_DATA_GET_PROGS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIC_DATA_LISTOU TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIC_DATA_PPLCOUNTS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIFECYCLE_DOC_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIFECYCLE_DOC_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LINK_COLUMNS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LISTS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LISTVALS_EDIT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LISTVALS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LISTVAL_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LISTVAL_DEL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LISTVAL_LEVEL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LISTVAL_MOVE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LISTVAL_MOVE_ABS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LISTVAL_TEXT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIST_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LIST_CLEAR TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LLISTS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LLIST_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LOG_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LOG_EXIT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LOG_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LOG_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LONGVACATION_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LONGVACATION_CHANGE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LONGVACATION_DELETE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LPARAMS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LPARAM_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LREPORTS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LREPORT_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LTYPES_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LTYPE_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LUSERS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LUSERS_ROOT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE LUSER_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE MASK_MATCH TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE MCAL_HANDLE_EDULOAD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE MCAL_HANDLE_GIA TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE MCAL_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE MCAL_SCHEDULE_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE MCAL_VIEW_CPLAN TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE MCAL_VIEW_EDULOAD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE MCAL_VIEW_GIA TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE MCAL_VIEW_LIBRARY TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE MCAL_VIEW_VACATION TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE MIGRATE_INT128 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE MODULES_ACTIVE_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE MODULES_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE MODULE_ACTIVATE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE MODULE_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE MODULE_MOVE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE MONITORING_BOOKS_GET_STAT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE MONITORING_BOOKS_SUBSTAT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE MONITORING_BOOKS_SUMMARY TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE MONITORING_BOOK_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE MONITORING_BUFFETS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE MONITORING_BUILDINGS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE MONITORING_CONTINGENT_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE MONITORING_CONTINGENT_DO_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE MONITORING_CURRICULUMTABL10_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE MONITORING_CURRICULUMTABL11_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE MONITORING_CURRICULUMTABL12_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE MONITORING_CURRICULUMTABL13_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE MONITORING_CURRICULUMTABL14_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE MONITORING_CURRICULUMTABL15_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE MONITORING_CURRICULUMTABLE1_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE MONITORING_CURRICULUMTABLE2_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE MONITORING_CURRICULUMTABLE3_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE MONITORING_CURRICULUMTABLE4_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE MONITORING_CURRICULUMTABLE5_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE MONITORING_CURRICULUMTABLE6_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE MONITORING_CURRICULUMTABLE7_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE MONITORING_CURRICULUMTABLE8_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE MONITORING_CURRICULUMTABLE9_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE MONITORING_DATA_REPORT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE MONITORING_DATA_REPORT2 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE MONITORING_DO_FUNC TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE MONITORING_DO_FUNC2 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE MONITORING_DO_FUNC3 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE MONITORING_DO_FUNC4 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE MONITORING_DO_FUNC5 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE MONITORING_DO_FUNC6 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE MONITORING_DO_FUNC7 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE MONITORING_DO_FUNC8 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE MONITORING_DO_FUNC_BOOKS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE MONITORING_EXPORT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE MONITORING_EXPORT_INFOEQUIPMENT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE MONITORING_EXPORT_MONITORING TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE MONITORING_GYMS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE MONITORING_PLAN_SUBJECTS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE MONITORING_PLAN_UPD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE MONITORING_PUPILS_REPORT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE MONITORING_SCHOOL_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE MONITORING_STAFF_REPORT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE MONITORING_TEACHER_HIDE_DOPS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE MONITORING_WORKLOAD_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE MONITORING_YEAR_REPORT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE MOVEMENT_VERIFY TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE MREPORT_512_AUTO TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE MREPORT_512_DTL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE MREPORT_512_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE MREPORT_SET_VAL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE MTR_DISTRICT_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE MTR_FILLING_DATA_REGION TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE MTR_FILLING_DATA_REPORT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE MTR_REPORT_ROOMS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE MTR_REPORT_ROOM_EQ TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE MTR_SCHOOL_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE NEW_SPO_CURRICULUM_ADD_LOADS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE NEW_SPO_PLAN_SUBJECT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OAIS_COLLECT_PARENTS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OAIS_COLLECT_PERSONS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OBFUSCATE_ALL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OBJECTS_EXPORT_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OBJECTS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OBJECTS_LIST_RET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OBJECTS_LIST_RET_GIA TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OBJECT_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OBJECT_ADD_400 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OBJECT_ADD_BY_CAPTION TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OBJECT_ADD_LINK TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OBJECT_ADD_WITH_PARAM TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OBJECT_CAN_LINK TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OBJECT_CAPTION_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OBJECT_CHILDREN_GET_DEEP TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OBJECT_CHILDREN_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OBJECT_COPY TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OBJECT_CREATE_AUTO_PARAMS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OBJECT_DEL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OBJECT_FRAMES_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OBJECT_GET_BY_PARAMS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OBJECT_GRIDS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OBJECT_GRID_PARAMS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OBJECT_GRID_VALS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OBJECT_GROUP_DEL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OBJECT_IS_PARENT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OBJECT_LISTVALS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OBJECT_LISTVALS_LIST_ROOT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OBJECT_LISTVALS_LIST_ROOTS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OBJECT_LISTVALS_UPPROFILE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OBJECT_MOVE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OBJECT_PARAMS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OBJECT_PARAMS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OBJECT_PARAM_USER_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OBJECT_PARENTS_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OBJECT_RESTORE_LAST_LINK TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OBJECT_ROOT_OBJECT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OBJECT_STATE_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OBJECT_TABS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OBJECT_TABS_LIST_RET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OBJECT_TAB_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OBJECT_TREE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OBJECT_TREE_COPY TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OBJECT_TYPES_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OBJECT_VR_LINKS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OD_SUBJECTS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OD_SUBJECT_EXT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OK009_FILTRED_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OLYMP_EVENT_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OLYMP_EVENT_PUPIL_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OLYMP_PUPIL_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OLYMP_RESULT_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OLYMP_SCHEDULE_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OO_ACCEPT_FROM_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OO_ACCEPT_REASON_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OO_DOCUMENT_INFO TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OO_DOC_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OO_DOC_TYPE_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OO_FILTRED_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OO_GRADES_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OO_LEVEL_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OO_ROOM_TYPE_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OO_SPECIALITY_LINK_CREATE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OO_SPECIALITY_LINK_DELETE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OO_STAGE_BASE_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OO_STAGE_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OO_STUDY_ACPT_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OO_STUDY_FORM_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OO_SUBJECT_TYPE_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OPLIST_BUILD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OPLIST_PLAN_DETAILS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OPTEXT_DELETE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OPTEXT_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OPTEXT_INNER_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OPTEXT_MOVE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OPTEXT_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OP_ENSURE_UNQ TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE ORDER_CHECK_PRINTED TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE ORDER_DELETE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE ORDER_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE ORDER_GROUP_SORTS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE ORDER_MK_NUM TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE ORDER_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE ORDER_SET_ROW TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE ORDER_SET_STATE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE ORDER_STATE_GO_EM_CMATE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE ORDER_STATE_GO_EM_IN TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE ORDER_STATE_GO_EM_OUT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE ORDER_STATE_RW_EM_CMATE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE ORDER_STATE_RW_EM_IN TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE ORDER_STATE_RW_EM_OUT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE ORD_NM_RULE_AUTO_CREATE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE ORGANIZATION_SHORT_NAME_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OSH1_1001 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OSH1_101 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OSH1_101DTL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OSH1_1101 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OSH1_1201 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OSH1_1201DTL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OSH1_1301 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OSH1_1301DTL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OSH1_1308 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OSH1_1318 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OSH1_1320 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OSH1_1321 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OSH1_1322 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OSH1_1326 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OSH1_1327 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OSH1_1328 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OSH1_1329 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OSH1_1334 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OSH1_1336 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OSH1_1340 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OSH1_1346 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OSH1_1401 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OSH1_1401DTL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OSH1_1407 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OSH1_1408 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OSH1_1501DTL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OSH1_1601DTL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OSH1_1611 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OSH1_1614 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OSH1_1641 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OSH1_1644 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OSH1_1701 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OSH1_1701DTL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OSH1_1801 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OSH1_1801DTL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OSH1_1802 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OSH1_1803 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OSH1_201 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OSH1_201DTL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OSH1_213 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OSH1_301 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OSH1_301DTL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OSH1_40 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OSH1_401 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OSH1_401DTL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OSH1_418 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OSH1_419 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OSH1_501 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OSH1_501DTL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OSH1_514 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OSH1_515 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OSH1_516 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OSH1_601 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OSH1_601DTL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OSH1_603 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OSH1_604 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OSH1_605 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OSH1_606 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OSH1_701DTL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OSH1_702 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OSH1_801 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OSH1_801DTL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OSH1_PUPIL_COUNT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OSH1_PUPIL_COUNT_ TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OSH1_T2_1 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OSH1_YEAR_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OSH5_101DTL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OSH5_301 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OSH5_301DTL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OSH5_401 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OSH5_401DTL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OSH5_501 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OSH5_501DTL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OSH5_601 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OSH5_601DTL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OSH5_701DTL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OSH5_801 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OSH5_901 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OSH5_901DTL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OU_ACTION_TYPES TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OU_CLASS_REPORT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OU_CLASS_REPORT2 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OU_CLASS_REPORT_DTL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OU_CLASS_REPORT_GPD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OU_EDU_DO_COMMIT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OU_EDU_DO_DATA TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OU_EDU_DO_OUTDATA TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OU_EDU_STAT_OUTDATA TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OU_FULLNAME_GENITIVE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OU_LICENCE_TYPE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OU_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OU_LIST_BY_ROOT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE OU_NET_REPORT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_CAN_CHANGE_VAL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_CAN_DELETE_OBJECT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_CLASS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_COLLEGE_SUBJECTS_LIST2 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_CURRICULUM_COPY TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_CURRICULUM_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_EDUCATION_FLEVELS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_EDUCATION_LEAVE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_EDUCATION_LEAVE_CHECK TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_EDUCATION_LEAVE_TYPES TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_EDUCATION_LEVELS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_EDUCATION_LINES_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_EDUCATION_TRANSFER TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_EMPLOYEE_ACCEPT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_EMPLOYEE_CANBE_FIRED TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_EMPLOYEE_CANCEL_LEAVE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_EMPLOYEE_HASBASEVAC TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_EMPLOYEE_JOB_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_EMPLOYEE_LEAVE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_EMPLOYEE_LEAVE_CHANGES TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_EMPLOYEE_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_EMPLOYEE_SENIORITY_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_EMPLOYEE_SENIORITY_DEL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_EMPLOYEE_SENIORITY_LST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_EMPLOYEE_VACANCY_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_EMPLOYEE_VACANCY_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_EMPLOYEE_VACANCY_LEAVE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_EMPLOYEE_VACANCY_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_ENTERING_CLASS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_ENTERING_TRANSFER TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_EXTMOVEMENT_MAXDATE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_GRADE_CURRICULUM_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_GRADE_GROUPS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_GRADE_LOADING_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_GRADE_OO_PARTNERS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_GRADE_SUBJECTS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_GRADE_TEACHERS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_GRADE_TEACHER_L_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_GROUP_SUBJECTS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_GROUP_SUBJECTS_LISTOLD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_INPUT_STAGE_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_INVENTORY_CARD_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_KINSFOLK_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_LIST_STAGE_PUPILS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_LIST_STAGE_SUBJECTS_SE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_LIST_STREAMS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_LOADING_CLASS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_LOADING_COLUMNS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_LOADING_COMPONENTS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_LOADING_EXTERNAL_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_LOADING_PUPIL_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_LOADING_ST_CLASS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_LOADING_ST_STREAM_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_LOADING_ST_UNION_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_LOADING_SUBJECTS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_LOADING_VALS_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_LOADING_VALS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_MAKER_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_MOVEMENT_IS_OUT_IN TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_MOVEMENT_MAXDATE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_NOT_LINKED_LIST_KK TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_PERIODS_ST_CLASS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_PERIODS_ST_GUP_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_PERIODS_ST_STM_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_PERIODS_ST_VGRP_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_PTP_LINK_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_PUPIL_NOT_LINKED_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_PUPIL_REVERT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_RECALC_EMPLOYEES TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_REF_SUBJECTS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_REPORT_335 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_REPORT_336 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_REPORT_VCN TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_ROOMS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_ROOMS_TREE_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_SUBGROUP_COPY TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_SUBGROUP_SUBJECT_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_SUBJECTS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_SUBJECT_LINK_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_TEACHERS_COUNT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_TEACHERS_COUNT_DISTR TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_TRANSFER_STAGE_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_TYPE_LEVEL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_TYPE_NOT_LINKED_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_TYPE_REFERENSE_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_UDOD_PUPIL_REVERT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_UMK1_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_UMK2_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_UMK3_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_VACANCY_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_VACANCY_LIST2 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_VACANCY_LIST3 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAGRAF_VACANCY_VERIFY TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAMS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAMTYPES_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAM_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAM_CAPTION_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAM_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAM_GET_BY_CAPTION TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAM_GET_DO_OP_DIRECTION TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAM_GET_DO_OP_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARAM_MOVE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARENTS_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARENTS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARENT_ACCOUNT_INFO TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARENT_CHILDREN_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARENT_REF_DOU TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PARSING_STRING_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PAUTH_APPLY TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PAUTH_CONTENT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PAUTH_REPORT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PAUTH_RESET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PBDOO_SERIALIZE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PD_CONTENT_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PERIOD_VERIFY TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PERSON_FMARKS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PERSON_JOB_DETAILS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PERSON_MOVEMENTS_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PERSON_PATH_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PF_BUILDINGS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PF_BUILDINGS_DIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PF_BUILDINGS_OU TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PF_BUILDINGS_RGN TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PF_CONTENT_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PF_EDU TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PF_EDU_DIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PF_EDU_OU TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PF_EDU_RGN TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PF_EQUIPMENT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PF_EQUIPMENT_DIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PF_EQUIPMENT_OU TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PF_EQUIPMENT_RGN TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PF_ITEM_DELETE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PF_ITEM_DO_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PF_ITEM_DO_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PF_ITEM_PF_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PF_ITEM_PF_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PF_KPI TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PF_KPI_OU TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PF_PERSONS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PF_PORTFOLIO TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PF_PORTFOLIO_DIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PF_PORTFOLIO_OU TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PF_PORTFOLIO_RGN TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PF_STUDENTS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PF_STUDENTS_DIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PF_STUDENTS_OU TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PF_STUDENTS_RGN TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PF_STUFF TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PF_STUFF_DIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PF_STUFF_OU TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PF_STUFF_RGN TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PLANTMPL_OP_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PLAN_CHECK_SAVE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PLAN_CLEANUP TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PLAN_CONTENT_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PLAN_COUNT_CLASS_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PLAN_COUNT_CLASS_DATA_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PLAN_COUNT_CLASS_DATA_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PLAN_COUNT_CLASS_TRANSFER TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PLAN_COUNT_ODOD_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PLAN_COUNT_ODOD_DISTRICT_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PLAN_COUNT_PUPIL_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PLAN_COUNT_PUPIL_DATA_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PLAN_COUNT_PUPIL_DATA_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PLAN_COUNT_PUPIL_DISTRICT_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PLAN_COUNT_PUPIL_REGION_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PLAN_COUNT_PUPIL_TO_DISTR_COPY TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PLAN_COUNT_PUPIL_TO_REGION_COPY TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PLAN_COUNT_PUPIL_TRANSFER TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PLAN_DELETE_ROW TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PLAN_DELTA_SUBJECT_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PLAN_DO_FUNC TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PLAN_EVENTS_TO_REGION_COPY TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PLAN_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PLAN_GUP_RECALC TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PLAN_HISTORY_REPORT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PLAN_IMPORT_CLEAR TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PLAN_IMPORT_LOAD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PLAN_IMPORT_STAGE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PLAN_IMPORT_SUBJECT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PLAN_IMPORT_TITLE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PLAN_KIND_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PLAN_MM_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PLAN_ODOD_DATA_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PLAN_ODOD_DATA_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PLAN_OO_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PLAN_PERIOD_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PLAN_PROFILE_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PLAN_PROFILE_DATA_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PLAN_PROFILE_DATA_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PLAN_PROFILE_VALIDATE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PLAN_RECALC TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PLAN_REPORT_COUNT_ODOD_BY_OU TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PLAN_REPORT_COUNT_PUPIL_BY_DSTR TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PLAN_REPORT_COUNT_PUPIL_BY_OU TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PLAN_REPORT_DISTRICT_ALL_EVENTS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PLAN_REPORT_LOAD_BY_OU TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PLAN_REPORT_YEARS_DOWN_3_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PLAN_REPORT_YEARS_UP_4_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PLAN_RESOURCES_SELECT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PLAN_RESOURCE_SAVE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PLAN_RES_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PLAN_SAVE_LOAD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PLAN_SET_ROW TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PLAN_SOO_SUBJECTS_MISS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PLAN_STAGE_VERIFY TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PLAN_SUBJECTS_SELECT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PLAN_SUBJECT_HOURS_NEQ TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PLAN_SUBJECT_LINK_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PLAN_SUBJECT_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PLAN_SUBJECT_LIST2 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PLAN_VOSP_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PLAN_WP_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PMPK_PKG_DATA TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PMPK_SEND_DATA TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PORTAL_BROKEN_UID_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PORTAL_CLASSES_DELETED_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PORTAL_CLASSES_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PORTAL_DIRECTORS_DELETED_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PORTAL_DIRECTORS_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PORTAL_EVENTS_DELETED_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PORTAL_EVENTS_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PORTAL_EXPORT_PROPERTIES_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PORTAL_EXPORT_PROPERTIES_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PORTAL_GIA_ASSN TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PORTAL_GIA_MARKS_DELETED_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PORTAL_GIA_MARKS_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PORTAL_GIS_DATA_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PORTAL_GROUP_TEACHER TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PORTAL_LAST_EXPORT_DATE_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PORTAL_LAST_EXPORT_DATE_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PORTAL_LAST_MARKS_DELETED_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PORTAL_LAST_MARKS_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PORTAL_LIST_GROUPS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PORTAL_OGRN_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PORTAL_OU_DATA_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PORTAL_PERIODS_DELETED_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PORTAL_PERIODS_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PORTAL_STUDENTS_DELETED_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PORTAL_STUDENTS_PARENT_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PORTAL_STUDENTS_WITH_UID_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PORTAL_SUBJECTS_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PORTAL_TEACHERS_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE POSTEVENT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PR3_FIND_EMPLOYEES TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PR3_FIND_PARENTS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PR3_FIND_STUDENTS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PRE_ACCEPT_PERSON TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PRG3_ABSENCE_IMPORT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PRG_PLAN_CMP_TYPES TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PROCEDURES_EXPORT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PROCESS_VERIFY TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PROCESS_VERIFY_OBJ TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PROCESS_VERIFY_SUBFLT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PROJECT_NAME_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PROJECT_TYPE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PTP_ALT_SUBJECTS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PTP_ASSIGNMENTS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PTP_CEC_SPLIT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PTP_EDS_REPORT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PTP_EDS_REPORT2 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PTP_STAGE_NAME TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PTP_TEST_BROWSE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PTP_TEST_JOIN TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PUPIL_ACCEPTED_INFO_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PUPIL_ACCEPT_MOVEMENTS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PUPIL_ADDITIONAL_EDUCATION_DEL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PUPIL_ADDITIONAL_EDUCATION_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PUPIL_ADDITIONAL_EDUCATION_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PUPIL_CHILDREN_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PUPIL_DUPLICATE_CHECK TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PUPIL_DUPLICATE_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PUPIL_GPD_LIST_BY_DATE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PUPIL_GROUP_ACCEPT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PUPIL_LEAVED_INFO_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PUPIL_LIST_BY_DATE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PUPIL_MOVEMENT_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PUPIL_PARENTS_DUPLICATE_CHECK TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PUPIL_PARENTS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE PUPIL_REGION_COUNT_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE QUERYS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE QUERYTYPES_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE QUERY_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE READ_REGISTRATION_PARAMS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE RECALC_STUDENT_AGG TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE REFERENCE_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE REGION_APPLY_TIMEMARK TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE REGION_SERIALIZE_PRE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE REGION_SERIALIZE_TM TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE REMOVE_FALSE_PUPIL_WITH_EDU_DOC TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE REPORTS_LEVEL_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE REPORTS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE REPORT_357_358 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE REPORT_85K_NEW TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE REPORT_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE REPORT_CJ_CORRS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE REPORT_CLASSNET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE REPORT_DO TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE REPORT_EMPLOYEES_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE REPORT_EMP_FORM TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE REPORT_FIS_FRDO TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE REPORT_FSPEO_DATA TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE REPORT_FSPEO_HTML TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE REPORT_FSPEO_JSON TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE REPORT_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE REPORT_MOVE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE REPORT_MTR TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE REPORT_MTR13 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE REPORT_OO1 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE REPORT_OO1_IN_VCS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE REPORT_OO1_OUT_VCS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE REPORT_OO1_R13 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE REPORT_OO1_R13_ROW TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE REPORT_OO1_R210 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE REPORT_OO1_R210_COL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE REPORT_OO1_R211 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE REPORT_OO1_R211_COL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE REPORT_OO1_R212 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE REPORT_OO1_R212_COL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE REPORT_OO1_R213 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE REPORT_OO1_R213_COL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE REPORT_OO1_R22 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE REPORT_OO1_R22_COL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE REPORT_OO1_R23 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE REPORT_OO1_R23_ROW TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE REPORT_OO1_R24 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE REPORT_OO1_R251 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE REPORT_OO1_R251_COL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE REPORT_OO1_R252 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE REPORT_OO1_R252_COL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE REPORT_OO1_R253 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE REPORT_OO1_R253_COL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE REPORT_OO1_R27 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE REPORT_OO1_R27_ROW TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE REPORT_OO1_R28 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE REPORT_OO1_R28_COL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE REPORT_OO1_R29 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE REPORT_OO1_R31 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE REPORT_OO1_R31_COL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE REPORT_OO1_R32 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE REPORT_OO1_R32_COL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE REPORT_OO1_R331 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE REPORT_OO1_R331_COL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE REPORT_OO1_R34 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE REPORT_OO1_R34_COL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE REPORT_OO1_R34_EA_COL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE REPORT_OO1_R34_IN_COL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE REPORT_OO1_R34_OUT_COL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE REPORT_OO1_R35 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE REPORT_OO1_R35_COL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE REPORT_OO1_VCS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE REPORT_PROGNOSE_STUDENTS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE REPORT_RKSYNC TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE REPORT_RKS_CARDS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE REPORT_SCHOLAR TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE REPORT_SCHOLAR_DTL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE REPORT_STUDENTS_NG TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE REPORT_UP_CONTROL_P1 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE REPORT_UP_CONTROL_P2 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE REPORT_VAL_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE RESET_REGISTRATION_DATE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE RES_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE RES_DEL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE RES_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE RES_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE RGN_ALLOWED_PARENTS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE RGN_FILTER_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE RGN_ITEM_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE RGN_MENU TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE RGN_PARAM_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE RGN_POSTFIX TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE RGN_REPORT_DELETE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE RGN_REPORT_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE RGN_REPORT_LINKS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE RGN_REPORT_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE RIK83 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE RIK83_ALL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE RIK83_DISTR1_1 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE RIK83_DISTR1_10 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE RIK83_DISTR1_11 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE RIK83_DISTR1_2 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE RIK83_DISTR1_3 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE RIK83_DISTR1_4 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE RIK83_DISTR1_5 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE RIK83_DISTR1_6 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE RIK83_DISTR1_7 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE RIK83_DISTR1_8 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE RIK83_DISTR1_9 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE RIK83_DTL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE RIK83_GRID TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE RIK83_INFO TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE RIK83_INSERT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE RIK83_STAVOK TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE RKS_ACCEPT_CHECK TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE RKS_ACCEPT_QUEUE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE RKS_ACCEPT_WARNING TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE RKS_ACTIVE_PERSON_IDS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE RKS_APPLY_PERSON TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE RKS_APPLY_TIMEMARK TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE RKS_APPLY_WARNING TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE RKS_DN_QUEUE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE RKS_DO_EVENT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE RKS_LIST_PERSONS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE RKS_OD_EVENT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE RKS_OU_INFO TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE RKS_SAVE_PERSON_ID TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE RKS_SAVE_ULS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE RKS_SERIALIZE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE RKS_SERIALIZE_ALL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE RKS_SERIALIZE_DPO TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE RKS_SERIALIZE_GRADES TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE RKS_SERIALIZE_HEADERS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE RKS_SERIALIZE_NOULS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE RKS_SERIALIZE_OODATA TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE RKS_SERIALIZE_OVZCNT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE RKS_SERIALIZE_PERIODS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE RKS_UPDATE_ALLOW2 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE ROD_EXPORT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE ROD_EXPORT_PROPERTIES_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE ROD_LAST_EXPORT_DATE_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE RPARAMS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE RPARAM_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE RSOKO_CALC_PUPIL_ABSENCES_COUNT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_1DO_5 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_1DO_6 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_1DO_ODOD_1 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_1DO_ODOD_2 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_1DO_ODOD_2_DTL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_1DO_ODOD_5 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_1DO_ODOD_6_1 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_1DO_ODOD_6_2 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_1DO_ODOD_6_3 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_1DO_ODOD_6_4 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_1DO_ODOD_6_DTL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_1DO_ODOD_6_DTL2 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_1DO_ODOD_6_DTL3 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_85K_1 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_85K_11 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_85K_12 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_85K_2 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_85K_21 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_85K_21DTL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_85K_22 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_85K_22DTL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_85K_3 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_85K_31 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_85K_31DTL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_85K_32 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_85K_32DTL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_85K_33 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_85K_33DTL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_85K_41 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_85K_DISTR_11 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_85K_DISTR_12 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_85K_DISTR_21 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_85K_DISTR_21DTL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_85K_DISTR_22 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_85K_DISTR_22DTL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_85K_DISTR_31 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_85K_DISTR_31DTL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_85K_DISTR_32 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_85K_DISTR_32DTL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_85K_DISTR_33 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_85K_DISTR_33DTL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_85K_DISTR_41 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_85K_DISTR_42 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_85K_NEW_HAS_DOO TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_CERTIFICATE_REG_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_CLASS_SHORT_DOU TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_COMPENSATION_DOU TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_EMPLOYEE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_EMPLOYEE_DOU TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_EMPLOYEE_IN TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_EMPLOYEE_OUT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_GET_WEBLINKS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_GET_WEBLINKS_STR TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_HOT_FOOD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_HOT_FOOD2 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_INFOCARD_202 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_INFOCARD_209 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_INFOCARD_210 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_INFOCARD_225 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_INFOCARD_300 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_INFOCARD_400 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_INFOCARD_600 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_INFOCARD_610 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_MOVEMENT_DOU TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_MOVEMENT_JOURNAL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_MOVEMENT_JOURNAL_SVOD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_MTR_BY_NUMER_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_PRG3_CLASSNET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_PRG3_CLASSNET_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_PRG3_CLASSNET_GET_OLD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_PRG3_CLASSNET_OU TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_PRG3_CLASSNET_OULIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_PRG3_CLASS_FILL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_PRG3_CLASS_FILL_DISTR TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_PRG3_FILL_DISTR_DOU TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_PRG3_FILL_REGION_DOU TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_PRG3_FILL_REGION_DOU_ALL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_PRG3_PERSONS_DEGREES TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_PRG3_PERSONS_FLUOROGRAPHY TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_PRG3_PERSON_ACHIEVE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_PRG3_PERSON_AWARDS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_PRG3_STAGE_FILL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_PRG3_TARIFICATION TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_PRG3_TOTAL_TEACHER_LOADING TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_PRG3_TOTAL_WORKERS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_PRG3_WORKERS_BIRTHDAY TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_PROF_DOC TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_QUAL_PROGRAMS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_QUAL_WORKERS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_QUAL_WORKERS_CNT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_SCHOLAR TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_SCHOLAR2 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_SCHOLAR_AGE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_SCHOLAR_BY_NAME_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_SCHOLAR_BY_PARENT_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_SCHOLAR_BY_YEAR TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_SCHOLAR_CNT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_SCHOLAR_CNT_DOU TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_SCHOLAR_DTL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_SCHOOLAR_FINISH TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_SCHOOLAR_IN TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_SCHOOLAR_IN_DISTR TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_SCHOOLAR_OUT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_SCHOOLAR_OUT_DISTR TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_SPB_INFOCARD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_SPB_INFOCARD_270 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_SPB_INF_OU_0 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_SPB_INF_OU_1 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_SPB_INF_OU_10 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_SPB_INF_OU_11 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_SPB_INF_OU_1_DTL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_SPB_INF_OU_2 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_SPB_INF_OU_2_ALL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_SPB_INF_OU_2_DTL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_SPB_INF_OU_3 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_SPB_INF_OU_3_DTL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_SPB_INF_OU_4 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_SPB_INF_OU_41 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_SPB_INF_OU_41_DTL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_SPB_INF_OU_4_DTL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_SPB_INF_OU_5 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_SPB_INF_OU_6 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_SPB_INF_OU_7 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_SPB_INF_OU_8 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_SPB_INF_OU_9 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_SPB_POST_BUHGALTER TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_SPB_POST_DIRECTOR TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_SPB_POST_EGE_RESPONSIBLE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_SPB_QUAL_DISTR_1 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_SPB_QUAL_DISTR_2 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_SPB_QUAL_DISTR_3 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_SPB_QUAL_DISTR_4 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_SPB_QUAL_DISTR_5 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_SPB_QUAL_DISTR_6 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_SPB_QUAL_NEEDS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_SPB_QUAL_OU_1 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_SPB_QUAL_OU_1P TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_SPB_QUAL_OU_1SV TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_SPB_QUAL_OU_2 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_SPB_QUAL_REQUEST_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_SPB_SKILL_0 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_SPB_SKILL_1_VID TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_SPB_SKILL_2_QUAL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_SPB_SKILL_3_SENIORITY TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_SPB_SKILL_4_POST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_SPB_TEACHER_POST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_SPB_TOTAL_QUALIFIED TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_SPB_TOTAL_SENIORITY TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_SPB_TOTAL_TEACHERS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_TWINS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_TWINSY_FIO TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_TWINSY_ID TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_TWINS_FIO TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_TWINS_HEAD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_TWINS_ID TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE R_WORKER_BY_NAME_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SAVE_REGISTRATION_PARAMS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SCARDS_CARD_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SCARDS_GET_PERSDATA TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SCHEDULE_CJ_IDATA TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SCHEDULE_CLASSES_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SCHEDULE_COPY TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SCHEDULE_COPY_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SCHEDULE_DATA_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SCHEDULE_DAYS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SCHEDULE_DELETE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SCHEDULE_FLOW TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SCHEDULE_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SCHEDULE_GRADE_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SCHEDULE_HOURS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SCHEDULE_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SCHEDULE_REPORT_ALL_CLASSES TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SCHEDULE_REPORT_ALL_ROOMS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SCHEDULE_REPORT_ALL_TEACHERS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SCHEDULE_REPORT_ALONE_CLASS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SCHEDULE_REPORT_ALONE_ROOM TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SCHEDULE_REPORT_ALONE_TEACHER TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SCHEDULE_ROOMS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SCHEDULE_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SCHEDULE_SET_SUBST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SCHEDULE_SUBJECTS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SCHEDULE_TEACHERS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SCHEDULE_TO_DATE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SCHOLAR_BY_DATE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SCHOLAR_CNT_CS_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SCHOLAR_CNT_DISTR_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SCHOLAR_CNT_DISTR_GET2 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SCHOLAR_CNT_DISTR_INS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SCHOLAR_CNT_REGION_CD_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SCHOLAR_CNT_REGION_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SCHOLAR_CNT_REGION_GET2 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SCHOLAR_CNT_UDOD_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SCHOOL_WEEK_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SCUD_STREAM_EXPORT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SDOCS_ADD_PERSON TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SDOCS_APPLY_DOC TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SDOCS_APPLY_DUB TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SDOCS_BLANK_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SDOCS_CHANGE_TYPE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SDOCS_DELETE_ORDER TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SDOCS_DOCUMENT_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SDOCS_LEVELS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SDOCS_MARKS_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SDOCS_MIGRATE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SDOCS_MIGRATE_LINKS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SDOCS_MIGRATE_ORDER TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SDOCS_ORDER_CHECK_PERSON TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SDOCS_ORDER_DUB TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SDOCS_ORDER_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SDOCS_ORDER_REPORT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SDOCS_ORDER_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SDOCS_PERSONS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SDOCS_SETTINGS_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SDOCS_STATE_REPORT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SDO_CLASS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SDO_EXPORT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SDO_EXPORT_CLASS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SDO_OU_NUM TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SEARCHFIELDS_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SEARCHFIELDS_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SEARCHPARAMS_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SEARCHPARAMS_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SEARCHTYPES_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SEARCHTYPES_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SEARCH_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SEARCH_APPLY TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SEARCH_CHECK_BIGINT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SEARCH_CHECK_DATE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SEARCH_CHECK_DOUBLE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SEARCH_CHECK_STRING TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SEARCH_COLUMNS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SEARCH_DEL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SEARCH_FIND TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SEARCH_INSERT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SEARCH_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SEARCH_OBJECT_CHILDREN_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SEARCH_PARAMS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SEARCH_TYPES_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SEARCH_TYPES_GET2 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SERIALIZE_OBJECT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SERVICE_MEO_DEFS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SITELOAD_CONTENT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SITELOAD_DATA_18581 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SITELOAD_DATA_18582 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SITELOAD_DATA_18583 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SITELOAD_DATA_18584 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SITELOAD_DATA_18585 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SITELOAD_DATA_18586 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SITELOAD_DATA_18587 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SITELOAD_DATA_18588 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SITELOAD_DATA_18589 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SITELOAD_DATA_18590 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SITELOAD_DATA_18591 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SITELOAD_DATA_18592 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SITELOAD_DATA_18593 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SITELOAD_DATA_18594 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SITELOAD_DATA_18595 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SITELOAD_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SITELOAD_STATUS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SMIR_MOVE_ENTER TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SMIR_MOVE_ERR_REPORT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SMIR_MOVE_ERR_REPORT_2 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SMIR_MOVE_ERR_REPORT_3 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SMIR_MOVE_LEAVE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SOCPASS_DATA TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SOCPASS_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SOCPASS_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE STAGE_AVAILABLE_GUP_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE STAGE_GROUPS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE STAGE_GROUPS_MAP TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE STAGE_PUPIL_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE STAGE_SUBJECTS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE STAT_UPDATE_FIELD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE STDFORM_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE STDWEEK_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE STEAD_DELETE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE STREAM_CREATE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE STREAM_MOVE_PUPIL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE STREAM_MOVE_PUPIL_FRC TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE STREAM_SCHOOLARS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE STRING_PART TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE STRUCTURE_OO_EMPLOYEE_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE STRUCTURE_OO_POSITION_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE STRUCTURE_OO_REPORT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE STR_IN_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE STR_REMOVE_FROM_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE STR_TO_ID_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE STR_TO_YEAR TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE STUDENTS_LIST_12932 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE STUDENT_ATTENDANCE_REF TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE STUDENT_EXISTS_AT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE STUDENT_STUDY_INFO TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SUBGROUP_SCHOOLARS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SUBJECT_DECODE_DIFF TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SUBJECT_DELETE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SUBJECT_ENUM_DIR TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SUBJECT_ENUM_MASTER TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SUBJECT_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SUBJECT_GET_SCOPE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SUBJECT_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE SUBJECT_TYPES TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE TABS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE TAB_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE TAB_MOVE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE TAB_PARAMS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE TAB_PARAMS_LIST2 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE TARIFF_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE TARIFF_ADD_ROW TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE TARIFF_CLONE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE TARIFF_CORR_SEL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE TARIFF_DELETE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE TARIFF_FILL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE TARIFF_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE TARIFF_REORDER TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE TARIFF_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE TARIFF_SETTINGS_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE TARIFF_STATUS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE TASKS_ACTIVE_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE TASKS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE TASK_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE TASK_MOVE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE TEACHER_CAPTION_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE TEST_D_12 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE THE_CAPTION_CLASS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE THE_CAPTION_CLASS_GIA_VIRTUAL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE THE_CAPTION_COLLEGE_GROUP TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE THE_CAPTION_DYNAMIC TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE THE_CAPTION_FINISHED TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE THE_CAPTION_GROUP TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE THE_CAPTION_GUP TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE THE_CAPTION_LEAVED TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE THE_CAPTION_STREAM TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE THE_CAPTION_TEACHER TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE TRANSFER_GRADE_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE TRANSFER_GUP_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE TRANSLITERATION TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE TYPES_ACTIVE_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE TYPES_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE TYPE_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE TYPE_CAPTION_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE TYPE_MOVE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE TYPE_PARENTS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE TYPE_PARENT_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UDOD_EMPLOYEE_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UDOD_LOADING_UNION_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UDOD_PERSON_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UDOD_PUPIL_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UDOD_PUPIL_TWINS_REPORT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UDOD_PUPIL_TWINS_UNITE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UDOD_TEACHER_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UDOD_TRANSFER_STAGE_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UDOD_YEAR_CHANGER_PUPIL_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UDOD_YEAR_CHANGER_PUPIL_MOVE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UNDO_GPD_MOVEMENT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UNI_STRING_COMPARE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UPDATE_4LINKS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UPDATE_4LISTVALS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UPDATE_4OBJECTS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UPDATE_4RES TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UPDATE_4VALA TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UPDATE_4VALB TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UPDATE_4VALD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UPDATE_4VALDT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UPDATE_4VALF TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UPDATE_4VALI TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UPDATE_4VALL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UPDATE_4VALR TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UPDATE_4VALS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UPDATE_4VALT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UPDATE_CHECK_PLAN TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UPDATE_DOCUMENT_STATUS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UPDATE_LESSON_TIME TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UPDATE_MOVEMENTS_CNAME TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UPDATE_PROFESSION_CODE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UPDATE_PUPIL_MK_SUBJECTS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UPDATE_PUPIL_SEL_SUBJECTS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UPDATE_SPECIALITY_CODE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE USA_LIST_LEVELS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE USERADM_ACCOUNT_EXTEND TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE USERADM_ACTIVITES_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE USERADM_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE USERADM_ADD_USER TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE USERADM_APP_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE USERADM_APP_CLEAR TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE USERADM_APP_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE USERADM_CHECK TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE USERADM_CJ_ACCESS_CLEAR TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE USERADM_CJ_ACCESS_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE USERADM_CJ_ACCESS_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE USERADM_CJ_DEFAULT_ACCESS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE USERADM_CLASSES_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE USERADM_CLASS_SUBJECTS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE USERADM_DEL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE USERADM_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE USERADM_GRADE_DISCIPLINES_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE USERADM_GUPS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE USERADM_JGPD_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE USERADM_LOG_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE USERADM_PUPILS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE USERADM_ROLE_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE USERADM_TEACHERS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE USERADM_USERS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE USERADM_USERS_LIST2 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE USERADM_USERTYPES_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE USERS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE USERS_SEC_UPDATE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE USERTYPES_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE USER_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE USER_CHANGE_PASS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE USER_CHANGE_PWD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE USER_CLASS_GEN TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE USER_COPY TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE USER_GRANT_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE USER_ID_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE USER_ITEM_DEL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE USER_ITEM_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE USER_ITEM_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE USER_LEVEL_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE USER_SETTINGS_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE USER_SETTINGS_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE USER_STAT_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE USER_TASKS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE USER_TRANSFER_EXPORT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE USER_TRANSFER_IMPORT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_ANSWER_SUBMIT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_BLANK_ACQUIRE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_CHECKSUM_EAN128 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_CHECKSUM_EAN13 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_CHECKSUM_EAN39 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_CLASS_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_CODING_TREE_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_DISTRICT_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_EMPLOYEE_DESC TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_EPLAN_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_EPLAN_GETCODES TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_EPLAN_OU_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_EPLAN_OWNER_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_EPLAN_SETCODE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_EXAMS_LIST_REG TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_EXAM_BLANK_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_EXAM_DATES_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_EXAM_DATES_STATE_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_EXAM_DATE_DELETE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_EXAM_DATE_READY TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_EXAM_DATE_RESULTS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_EXAM_DROP TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_EXAM_EXPERT_ASSN_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_EXAM_EXPORT_DESC TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_EXAM_FILE_ACCESS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_EXAM_FILE_FINISH TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_EXAM_FILE_RESULT_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_EXAM_FILE_SETBC TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_EXAM_FORSCAN_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_EXAM_FORVERIFY_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_EXAM_KEYS_APPLY TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_EXAM_MON_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_EXAM_OLYMPIC_DEL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_EXAM_OLYMPIC_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_EXAM_OLYMPIC_RES TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_EXAM_OLYMPIC_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_EXAM_OU_ASSN_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_EXAM_PACKET_DEL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_EXAM_PACKET_FILE_DEL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_EXAM_PACKET_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_EXAM_PACKET_START TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_EXAM_PACKET_STATUS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_EXAM_PERSON_ASSN_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_EXAM_PPE_ASSN_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_EXAM_PRINT_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_EXAM_PRINT_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_EXAM_QUESTION_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_EXAM_RECALC TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_EXAM_REPORT_EXPERTS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_EXAM_REPORT_MEMBERS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_EXAM_REPORT_MEMBERS_DTL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_EXAM_RESULTS_EXPORT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_EXAM_RESULTS_RESET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_EXAM_RESULTS_RUN TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_EXAM_RES_ASSN_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_EXAM_ROOM_ASSN_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_EXAM_SCALE_APPLY TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_EXAM_SCALE_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_EXAM_SCAN_STATS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_EXAM_SETTINGS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_EXAM_SMPL_RESULTS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_EXAM_TEST_VARS_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_EXAM_TITLE_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_EXPARENTS_VIEW TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_EXPERTS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_EXPERT_DELETE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_EXPERT_DESC TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_EXPERT_EXAM_ASSNS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_EXPERT_EXAM_CA_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_EXPERT_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_EXPERT_MARKUP_SUBMIT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_EXPERT_NEXT_TASK TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_EXPERT_SAVE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_EXPERT_TASK_CR_SUBMIT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_EXPERT_TASK_DEFER TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_EXPERT_TASK_FORWARD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_EXPERT_TASK_SUBMIT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_FIND_TEST_FREE_PLACE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_FIND_TEST_FREE_PPE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_GET_STRUCTURE_BY_ID TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_GIA_PRINT_CONFIRM TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_KIM_CDLEVEL_SYNC TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_KIM_CODING_CNT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_KIM_CODING_DELETE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_KIM_CODING_EVENT_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_KIM_CODING_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_KIM_CODING_LEVELS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_KIM_CODING_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_KIM_CODING_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_KIM_CODING_SUB_CNT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_KIM_CODING_SYNC TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_KIM_CODING_VIEW TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_KIM_QUESTION_DESC TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_LEVEL_GROUP_UA_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_OU_DESC TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_PARTICIPANTS_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_PERSONS_DD_GRADES TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_PERSONS_DD_STAGES TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_PERSONS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_PERSON_DESC TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_PERSON_EXAMS_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_PERSON_EXAM_ADD_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_PERSON_EXAM_ASSNS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_PLACES_LEVEL_UA_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_PPE_DELETE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_PPE_DESC TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_PPE_EXAM_ADD_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_PPE_EXAM_ASSNS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_PPE_EXAM_ASSN_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_PPE_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_PPE_PLACES_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_PPE_PLACES_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_PPE_PLACE_DELETE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_PPE_PLACE_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_PPE_RECALC TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_PPE_ROOMS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_PPE_ROOM_ASSN_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_PPE_ROOM_DELETE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_PPE_ROOM_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_PPE_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_PUPIL_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_PUPIL_GET_NEW TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_QUESTIONS_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_QUESTIONS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_QUESTION_ANSWERS_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_QUESTION_ANSWERS_IDS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_QUESTION_ANSWER_DEL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_QUESTION_ANSWER_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_QUESTION_CLONE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_QUESTION_DELETE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_QUESTION_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_QUESTION_KIM_CAT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_QUESTION_MOVE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_QUESTION_REORDER TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_QUESTION_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_SCHOLAR_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_SCHOOL_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_SESSION_COMPLETE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_SESSION_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_SESSION_QUESTIONS_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_SESSION_START TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_SESSION_TIME_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_SET_STRUCTS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_STUDENT_DESC TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_STUDENT_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_STUFF_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_SUBJECTS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_SYNC_EXPERT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEMPLATES_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEMPLATE_ACCESS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEMPLATE_COPY TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEMPLATE_DELETE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEMPLATE_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEMPLATE_SAVE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TESTS_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TESTS_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_ASSN_PLACE_APPLY TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_ASSN_PLACE_APPLY_PERSON TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_ASSN_PLACE_CHANGES TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_ASSN_PLACE_LTREE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_ASSN_PLACE_RCHANGES TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_ASSN_PLACE_REVERT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_ASSN_PLACE_RTREE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_ASSN_PLC_REVERT_PERSON TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_ASSN_PPE_APPLY TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_ASSN_PPE_APPLY_PERSON TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_ASSN_PPE_CHANGES TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_ASSN_PPE_LTREE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_ASSN_PPE_RCHANGES TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_ASSN_PPE_REVERT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_ASSN_PPE_REVERT_PERSON TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_ASSN_PPE_RTREE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_ATTR_CHARSETS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_AUTOCODING TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_BLANKS_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_BLANKS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_BLANK_CONFIRM TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_CHOOSE_ASSN TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_CHOOSE_REPORT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_CHOOSE_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_CHOOSE_TREE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_CLONE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_DELETE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_DETAILS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_EXPORT_B0 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_EXPORT_CS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_EXPORT_LOCAL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_EXPORT_P0 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_EXPORT_P1 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_EXT_BLANKS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_EXT_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_GENERIC_BLANKS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_GIA_SIGNATURE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_IMPORT_B0 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_IMPORT_B1 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_IMPORT_B2 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_IMPORT_B3 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_IMPORT_MD0 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_IMPORT_MD1 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_IMPORT_P0 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_IMPORT_P1 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_IMPORT_P10 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_IMPORT_P11 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_IMPORT_P11X TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_IMPORT_P1_2 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_IMPORT_P1_3 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_IMPORT_P2 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_IMPORT_P2_1 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_IMPORT_P3 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_IMPORT_P3_1 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_IMPORT_P3_2 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_IMPORT_P3_3 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_IMPORT_P4 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_IMPORT_P4_1 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_IMPORT_P5 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_IMPORT_P5_1 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_IMPORT_P5_2 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_IMPORT_P6 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_IMPORT_P7 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_KIM_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_MON_DATA TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_PERSON_BLANKS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_QVECTOR TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_RANDOM_RESULTS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_SCAN_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_SESSION_RV_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_SESSION_TOTAL_RECALC TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_STRUCTS_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_STRUCTS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_STRUCTS_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_STRUCT_DELETE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_STRUCT_POINTS_DELETE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_STRUCT_POINTS_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_STRUCT_POINTS_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_STRUCT_POINT_DELETE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_STRUCT_VALIDATE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_SYNC_EXPERT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_SYNC_MEMBER TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_TASK_TOTAL_RECALC TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_VARS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_VARS_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_VAR_DELETE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_VAR_FILE_DEL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_VAR_FILE_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_VAR_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_VAR_PRINT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_VAR_QUESTIONS_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_VAR_QUESTIONS_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TEST_VAR_QUESTION_DELETE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_TIME_SUBMIT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_USER_TO_EXPERT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_VALIDATE_ANSWER_01 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_VALIDATE_ANSWER_02 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_VALIDATE_ANSWER_04 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_VALIDATE_ANSWER_05 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_VARIANTS_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_VERIFY_ANSWERS_APPLY TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_VERIFY_ANSWERS_DICT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_VERIFY_ATTR_SUBMIT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_VERIFY_NEXT_TASK TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_VERIFY_QUESTIONS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_VERIFY_RUN_C TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_VERIFY_TASK_ASCLEAN TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_VERIFY_TASK_ASINC TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_VERIFY_TASK_DEFER TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_VERIFY_TASK_FORWARD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE UT_VERIFY_TASK_SUBMIT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE VACANCY_GET_CAT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE VACANCY_NUM_OCCUPIED TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE VACANCY_NUM_TEMPFREE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE VACANCY_UPDATE_CAT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE VACATION_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE VACATION_ADD_OU TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE VACATION_APPROVE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE VACATION_CHECK_EXISTS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE VACATION_CLONE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE VACATION_DAYS_REST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE VACATION_DELETE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE VACATION_DELETE_PLAN TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE VACATION_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE VALIDATE_CURRENT_YEAR TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE VALIDATE_DEFAULT_JOB TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE VALIDATE_KUG TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE VALIDATE_LAST_JOB TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE VAL_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE VAL_ADD_AFTER TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE VAL_DOCUMENT_CHECK TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE VAL_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE VAL_SERIALIZE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE VAL_SQL_QUERY_GET_INT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE VAL_TAG_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE VARGRP_APPLY TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE VARGRP_GUP_ASSIGN TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE VARGRP_MOVE_PUPIL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE VERIFY_ADMIN2 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE VERIFY_ALL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE VERIFY_ALL_DICT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE VERIFY_AOOP_TYPES TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE VERIFY_ATT_TYPE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE VERIFY_BUILDING TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE VERIFY_BUILDING_DICT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE VERIFY_CLASS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE VERIFY_CLASS_DICT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE VERIFY_CURRENT_CLASS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE VERIFY_DOCS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE VERIFY_DOCS_DICT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE VERIFY_FOOD_BENEFIT_APP_EXPORT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE VERIFY_FUTURE_CLASS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE VERIFY_GIA TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE VERIFY_GIA_DICT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE VERIFY_MONITORING TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE VERIFY_MONITORING_DICT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE VERIFY_MOVEMENT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE VERIFY_MOVEMENT_DICT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE VERIFY_MTR TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE VERIFY_MTR_DICT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE VERIFY_OBJECT_FIELDS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE VERIFY_OP TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE VERIFY_OP_DICT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE VERIFY_OP_DURATION TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE VERIFY_PARAM_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE VERIFY_PARAM_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE VERIFY_POST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE VERIFY_POST_DICT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE VERIFY_PUPIL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE VERIFY_PUPIL_DICT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE VERIFY_SUBJECT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE VERIFY_SUBJECT_DICT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE VERIFY_TIMETABLE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE VERIFY_TIMETABLE_DICT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE VERIFY_UP_STD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE VERIFY_USER2 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE VERIFY_WORKERS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE VERIFY_WORKERS2 TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE VERIFY_WORKERS_DICT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE VERIFY_YEAR_CHANGER TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE VOSP_MEMBERS_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE VOSP_PLAN_DELETE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE WORKDAYS_TO_TEXT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE WORKTAB_ADD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE WORKTAB_CHANGE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE WORKTAB_DELETE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE WORKTAB_DT_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE WORKTAB_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE WORKTAB_PERSON_FIND TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE WORKTAB_SETTINGS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE WORKTAB_SETTINGS_DEL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE WORKTAB_SETTINGS_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE WORKTAB_SETTINGS_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE WORKTAB_SET_COL_DEL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE WORKTAB_SET_COL_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE WORKTAB_SET_COL_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE WORKTAB_SET_GROUP_DEL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE WORKTAB_SET_GROUP_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE WORKTAB_SET_GROUP_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE WORKTAB_SET_TYPE_DEL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE WORKTAB_SET_TYPE_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE WORKTAB_SET_TYPE_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE WORKTAB_UPDATE_EXTRA TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE WORKTAB_VAL_IMPORT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE WORKTAB_VAL_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE WORKTIME_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE WORKTIME_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE WORK_DIFF TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE WSTAGE_LIST TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE WSTAGE_SET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE YANDEX_HOMETASK_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE YANDEX_SCHEDULE_GET TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE YCHANGE_GRADE_DETAILS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE YCHANGE_GRADE_MEMBERS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE YCHANGE_PLAN_ASSIGN TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE YCHANGE_PLAN_DETAILS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE YCHANGE_PROCESS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE YCHANGE_REVIEW TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE YCHANGE_REVIEW_GRADES TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE YCHANGE_SETATTR TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE YCHANGE_SETCAL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE Z TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE Z_COPY_LEVEL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE Z_DEL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE Z_DEL_MOVEMENT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE Z_DEL_OBJ_TYPE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE Z_EXPERT_BASE TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE Z_GUID TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE Z_IMPORT_JOBS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE Z_IS_FOREIGN_KEY TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE Z_IS_PRIMARY_KEY TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE Z_OD_RESULTS TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE Z_OKPDTR TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE Z_OU_TO_POSTGRES TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE Z_PLAN_CLONE_TMPL TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE Z_PLAN_CONVERT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE Z_PP_IMPORT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE Z_RANDOM_SCUD TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE Z_SCHOLAR TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE Z_SCHOLAR_IN TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE Z_SCHOLAR_OUT TO INISSOFT_ROLE;
GRANT EXECUTE ON PROCEDURE Z_UPDATE_SPEC TO INISSOFT_ROLE;

COMMIT WORK;


GRANT ALL ON VER TO INISSOFT_ROLE;

